summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-10-06 11:49:09 +0000
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-10-06 16:58:43 +0200
commit07840524085bd1785b8f9142b03d942f678c5c51 (patch)
tree499c1674fdd1b3e0c07688d8e4e56748dfea2ca3
Initial import
-rw-r--r--.gitattributes4
-rw-r--r--.gitignore18
-rw-r--r--.gitmodules12
-rw-r--r--.qmake.conf5
-rw-r--r--Studio/Build Configurations/Viewer.build67
-rw-r--r--Studio/Build Configurations/Viewer/deploy_PC.include5
-rw-r--r--Studio/Build Configurations/Viewer/preview_PC.include24
-rw-r--r--Studio/Build Configurations/Viewer/setup.include21
-rw-r--r--Studio/Content/Effect Library/AdditiveColorGradient.effect32
-rw-r--r--Studio/Content/Effect Library/BaseEffect.effect30
-rw-r--r--Studio/Content/Effect Library/Bloom.effect200
-rw-r--r--Studio/Content/Effect Library/Blur.effect47
-rw-r--r--Studio/Content/Effect Library/Brush Strokes.effect38
-rw-r--r--Studio/Content/Effect Library/ChromaticAberration.effect56
-rw-r--r--Studio/Content/Effect Library/ColorMaster.effect38
-rw-r--r--Studio/Content/Effect Library/Corona.effect97
-rw-r--r--Studio/Content/Effect Library/Depth Of Field Bokeh.effect302
-rw-r--r--Studio/Content/Effect Library/Depth Of Field HQ Blur.effect67
-rw-r--r--Studio/Content/Effect Library/Desaturate.effect35
-rw-r--r--Studio/Content/Effect Library/Distortion Ripple.effect50
-rw-r--r--Studio/Content/Effect Library/Distortion Sphere.effect46
-rw-r--r--Studio/Content/Effect Library/Distortion Spiral.effect51
-rw-r--r--Studio/Content/Effect Library/Edge Detect.effect81
-rw-r--r--Studio/Content/Effect Library/Emboss.effect41
-rw-r--r--Studio/Content/Effect Library/FXAA.effect51
-rw-r--r--Studio/Content/Effect Library/FrameFlipper.effect41
-rw-r--r--Studio/Content/Effect Library/FullScreenTextureOverlay.effect27
-rw-r--r--Studio/Content/Effect Library/Gaussian Blur.effect48
-rw-r--r--Studio/Content/Effect Library/HDRBloomTonemap.effect282
-rw-r--r--Studio/Content/Effect Library/LightTable.effect233
-rw-r--r--Studio/Content/Effect Library/Motion Blur.effect76
-rw-r--r--Studio/Content/Effect Library/SCurveTonemap.effect117
-rw-r--r--Studio/Content/Effect Library/SMAA1X.effect149
-rw-r--r--Studio/Content/Effect Library/Screen Space AO.effect90
-rw-r--r--Studio/Content/Effect Library/Sepia.effect64
-rw-r--r--Studio/Content/Effect Library/Stylize - Scatter.effect47
-rw-r--r--Studio/Content/Effect Library/Tilt Shift.effect111
-rw-r--r--Studio/Content/Effect Library/VignetteEffect.effect41
-rw-r--r--Studio/Content/Effect Library/maps/effects/AreaTex-yflipped.ddsbin0 -> 179328 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/CircleBokeh.pngbin0 -> 1718 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/HexagonalBokeh.pngbin0 -> 910 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/SearchTex-yflipped.pngbin0 -> 180 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/brushnoise.ddsbin0 -> 65664 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/noise.ddsbin0 -> 4224 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/noise3.ddsbin0 -> 349652 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/noiseUniform.ddsbin0 -> 262272 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_cloudlet.pngbin0 -> 2807 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_glowDisc.pngbin0 -> 2329 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_glowSphere.pngbin0 -> 2382 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_rectangle.pngbin0 -> 1285 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_sphere.ddsbin0 -> 16512 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_sphere.pngbin0 -> 789 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/ps_star.pngbin0 -> 6760 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/snownoise.ddsbin0 -> 1048704 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/starBokeh.pngbin0 -> 1326 bytes
-rw-r--r--Studio/Content/Effect Library/maps/effects/white.pngbin0 -> 189 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/DESCRIPTION.en_us.html22
-rw-r--r--Studio/Content/Font Library/titilliumweb/METADATA.pb107
-rw-r--r--Studio/Content/Font Library/titilliumweb/OFL.txt93
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-Black.ttfbin0 -> 49356 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-Bold.ttfbin0 -> 59908 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-BoldItalic.ttfbin0 -> 69796 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLight.ttfbin0 -> 63124 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLightItalic.ttfbin0 -> 67788 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-Italic.ttfbin0 -> 72416 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-Light.ttfbin0 -> 64032 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-LightItalic.ttfbin0 -> 71720 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-Regular.ttfbin0 -> 63752 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBold.ttfbin0 -> 63044 bytes
-rw-r--r--Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBoldItalic.ttfbin0 -> 71812 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1-mirror.pngbin0 -> 20716 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1.pngbin0 -> 20682 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2-mirror.pngbin0 -> 16960 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2.pngbin0 -> 16927 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3-mirror.pngbin0 -> 13242 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3.pngbin0 -> 13219 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4-mirror.pngbin0 -> 9122 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4.pngbin0 -> 9086 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-1.pngbin0 -> 20589 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-2.pngbin0 -> 13742 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-3.pngbin0 -> 9641 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1-inverse.pngbin0 -> 21355 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1.pngbin0 -> 21323 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2-inverse.pngbin0 -> 20946 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2.pngbin0 -> 20906 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3-inverse.pngbin0 -> 19449 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3.pngbin0 -> 19425 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4-inverse.pngbin0 -> 15421 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4.pngbin0 -> 15424 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5-inverse.pngbin0 -> 11673 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5.pngbin0 -> 11678 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1-mirror.pngbin0 -> 19304 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1.pngbin0 -> 19077 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2-mirror.pngbin0 -> 15431 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2.pngbin0 -> 15563 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3-mirror.pngbin0 -> 10641 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3.pngbin0 -> 10684 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4-mirror.pngbin0 -> 6791 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4.pngbin0 -> 6766 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-1.pngbin0 -> 16991 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-2.pngbin0 -> 9912 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-3.pngbin0 -> 7099 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-1.pngbin0 -> 5657 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-2.pngbin0 -> 5924 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-3.pngbin0 -> 7578 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-4.pngbin0 -> 6215 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-1.pngbin0 -> 848 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-2.pngbin0 -> 1049 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-3.pngbin0 -> 1061 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-1.pngbin0 -> 116581 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-2.pngbin0 -> 74198 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-3.pngbin0 -> 42908 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-ripple.pngbin0 -> 146951 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-twist.pngbin0 -> 116094 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-1.pngbin0 -> 2637 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-2.pngbin0 -> 3456 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-3.pngbin0 -> 3671 bytes
-rw-r--r--Studio/Content/Maps Library/Alpha Maps/misc alpha maps/splatter-1.pngbin0 -> 36062 bytes
-rw-r--r--Studio/Content/Maps Library/Automotive/indicators_icons.pngbin0 -> 49248 bytes
-rw-r--r--Studio/Content/Maps Library/Automotive/indicators_icons_extended.pngbin0 -> 34746 bytes
-rw-r--r--Studio/Content/Maps Library/Automotive/large_tic_marks.pngbin0 -> 82020 bytes
-rw-r--r--Studio/Content/Maps Library/Automotive/medium_tic_marks.pngbin0 -> 227788 bytes
-rw-r--r--Studio/Content/Maps Library/Automotive/small_tic_marks.pngbin0 -> 355557 bytes
-rw-r--r--Studio/Content/Maps Library/Bump Maps/bump.ddsbin0 -> 699192 bytes
-rw-r--r--Studio/Content/Maps Library/Bump Maps/rubber_hatch.ddsbin0 -> 1493 bytes
-rw-r--r--Studio/Content/Maps Library/Concepting Maps/Finger-idle.pngbin0 -> 34325 bytes
-rw-r--r--Studio/Content/Maps Library/Concepting Maps/Finger-pressureDown.pngbin0 -> 34649 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/LICENSE-OpenfootageNET.txt7
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-1024.hdrbin0 -> 1601679 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-512.hdrbin0 -> 401151 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-1024.hdrbin0 -> 1759202 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-512.hdrbin0 -> 443546 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-1024.hdrbin0 -> 1719709 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-512.hdrbin0 -> 434178 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-1024.hdrbin0 -> 1659936 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-512.hdrbin0 -> 416212 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-1024.hdrbin0 -> 1954066 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-512.hdrbin0 -> 489367 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-1024.hdrbin0 -> 1625204 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-512.hdrbin0 -> 421718 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-1024.hdrbin0 -> 1553532 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-512.hdrbin0 -> 385303 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_garage-1024.hdrbin0 -> 1675239 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_garage-512.hdrbin0 -> 422659 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-1024.hdrbin0 -> 1659619 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-512.hdrbin0 -> 407359 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-1024.hdrbin0 -> 1459275 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-512.hdrbin0 -> 362018 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-1024.hdrbin0 -> 1704663 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-512.hdrbin0 -> 426013 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/TestEnvironment-1024.hdrbin0 -> 182979 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/TestEnvironment-2048.hdrbin0 -> 379796 bytes
-rw-r--r--Studio/Content/Maps Library/Environments/TestEnvironment-512.hdrbin0 -> 87897 bytes
-rw-r--r--Studio/Content/Maps Library/Logos/Qt/QT-badge.pngbin0 -> 26806 bytes
-rw-r--r--Studio/Content/Maps Library/Logos/Qt/QT-symbol-flatWhite.pngbin0 -> 4407 bytes
-rw-r--r--Studio/Content/Maps Library/Logos/Qt/QT-symbol.pngbin0 -> 4541 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-128X128.pngbin0 -> 4653 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-256X256.pngbin0 -> 6847 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-32X32.pngbin0 -> 3091 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-64X64.pngbin0 -> 3503 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-01p.pngbin0 -> 12282 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-02p.pngbin0 -> 13612 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-03p.pngbin0 -> 14342 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-05p.pngbin0 -> 15330 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-10p.pngbin0 -> 16056 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-15p.pngbin0 -> 16015 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-20p.pngbin0 -> 15761 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-25p.pngbin0 -> 15580 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-30p.pngbin0 -> 15358 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/circles/circle-stroke-50p.pngbin0 -> 14444 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-01p.pngbin0 -> 308 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-02p.pngbin0 -> 311 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-03p.pngbin0 -> 315 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-05p.pngbin0 -> 315 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-10p.pngbin0 -> 315 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-25p.pngbin0 -> 316 bytes
-rw-r--r--Studio/Content/Maps Library/Shapes/squares/square-stroke-50p.pngbin0 -> 317 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/flares/Flare1.pngbin0 -> 67124 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/flares/Flare2.pngbin0 -> 34096 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/flares/Flare3.pngbin0 -> 55247 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/flares/Flare4.pngbin0 -> 10293 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/flares/Flare5.pngbin0 -> 6013 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/flares/Thumbs.dbbin0 -> 7168 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/glows/Glow-CircleBorder-1.pngbin0 -> 7713 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/glows/Glow-circle-1.pngbin0 -> 6956 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/glows/Glow-circle-2.pngbin0 -> 7378 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/glows/Glow-circle-3.pngbin0 -> 6261 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/glows/Thumbs.dbbin0 -> 6144 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/grids/grid-01.pngbin0 -> 852 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/grids/grid-02.pngbin0 -> 860 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/grids/grid-03.pngbin0 -> 804 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/grids/grid-04.pngbin0 -> 4294 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Color.pngbin0 -> 56784 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing.pngbin0 -> 41008 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing2.pngbin0 -> 18027 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Ring.pngbin0 -> 40346 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/cloudy_smoke.pngbin0 -> 44892 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-1.pngbin0 -> 18747 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-2.pngbin0 -> 20493 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-3.pngbin0 -> 59584 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-4.pngbin0 -> 40489 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-5.pngbin0 -> 39949 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-1.pngbin0 -> 7036 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-2.pngbin0 -> 6210 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/streaks/streak_narrow.pngbin0 -> 5423 bytes
-rw-r--r--Studio/Content/Maps Library/Special Effects/streaks/streak_wide.pngbin0 -> 6723 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_01.jpgbin0 -> 10337 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_02.jpgbin0 -> 3546 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_03.jpgbin0 -> 13591 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Gold/Gold_01.jpgbin0 -> 19212 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Gold/Gold_02.jpgbin0 -> 4708 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Gold/Gold_03.jpgbin0 -> 6617 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-1.jpgbin0 -> 32092 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-2.jpgbin0 -> 14997 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-3.jpgbin0 -> 14187 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Smear.jpgbin0 -> 4726 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Underwater.jpgbin0 -> 7250 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Window.jpgbin0 -> 9044 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-ceiling_lights-1.pngbin0 -> 112135 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-dull-1.pngbin0 -> 20645 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-dull-2.pngbin0 -> 23688 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-dull-3.pngbin0 -> 29961 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1-alpha-25_orange.pngbin0 -> 14680 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1.pngbin0 -> 77525 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-shiny-2.pngbin0 -> 32372 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/Specular-shiny-3.pngbin0 -> 24469 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha01.pngbin0 -> 88912 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha02.pngbin0 -> 47456 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha03.pngbin0 -> 53691 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha04.pngbin0 -> 21654 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha05.pngbin0 -> 21903 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-100.pngbin0 -> 63791 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-25.pngbin0 -> 76845 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-50.pngbin0 -> 82405 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-75.pngbin0 -> 83333 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-90.pngbin0 -> 85058 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-100.pngbin0 -> 31276 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25.pngbin0 -> 21781 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25_refIVI.pngbin0 -> 21781 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50.pngbin0 -> 26114 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50_green.pngbin0 -> 24660 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-75.pngbin0 -> 28962 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-90.pngbin0 -> 30974 bytes
-rw-r--r--Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-blue.pngbin0 -> 12397 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Cork1.pngbin0 -> 620566 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Fabric1.pngbin0 -> 252560 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Fabric2.pngbin0 -> 334081 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Grass2.pngbin0 -> 639867 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Metal_Bronze.pngbin0 -> 50334 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Metal_Oxydized.pngbin0 -> 109861 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Metal_Streaks.pngbin0 -> 13744 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Paper05.pngbin0 -> 321820 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Scratched_Aluminum.pngbin0 -> 84991 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Stone1.pngbin0 -> 279846 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Water1.pngbin0 -> 484212 bytes
-rw-r--r--Studio/Content/Maps Library/Texture Maps/Wood7.pngbin0 -> 445815 bytes
-rw-r--r--Studio/Content/Maps Library/UV-Checker.pngbin0 -> 10586 bytes
-rw-r--r--Studio/Content/Material Library/aluminium_anodized.material178
-rw-r--r--Studio/Content/Material Library/aluminium_anodized_emissive.material214
-rw-r--r--Studio/Content/Material Library/aluminum.material223
-rw-r--r--Studio/Content/Material Library/aluminum_anisotropic.material260
-rw-r--r--Studio/Content/Material Library/aluminum_brushed.material224
-rw-r--r--Studio/Content/Material Library/aluminum_emissive.material231
-rw-r--r--Studio/Content/Material Library/aluminum_textured_aniso.material263
-rw-r--r--Studio/Content/Material Library/asphalt.material236
-rw-r--r--Studio/Content/Material Library/bamboo_natural_matte.material236
-rw-r--r--Studio/Content/Material Library/bamboo_natural_matte_emissive.material242
-rw-r--r--Studio/Content/Material Library/carbon_fiber.material271
-rw-r--r--Studio/Content/Material Library/carbon_fiber_emissive.material277
-rw-r--r--Studio/Content/Material Library/carpaint_blue_standard.material231
-rw-r--r--Studio/Content/Material Library/carpaint_color_peel_2_layer.material255
-rw-r--r--Studio/Content/Material Library/carpaint_yellow_standard.material231
-rw-r--r--Studio/Content/Material Library/concrete.material235
-rw-r--r--Studio/Content/Material Library/copper.material178
-rw-r--r--Studio/Content/Material Library/leather_smoothed_black.material236
-rw-r--r--Studio/Content/Material Library/maps/materials/art_paper_normal.pngbin0 -> 8361968 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/art_paper_trans.pngbin0 -> 7271168 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/asphalt.pngbin0 -> 1884467 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/asphalt_bump.pngbin0 -> 243515 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/bamboo_natural.pngbin0 -> 1520156 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/bamboo_natural_bump.pngbin0 -> 111006 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/bamboo_natural_spec.pngbin0 -> 279332 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_a.pngbin0 -> 3805351 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_a_full_contrast_scratched.pngbin0 -> 2972427 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_a_scratched_50_percent.pngbin0 -> 4574567 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_chrome.pngbin0 -> 4114475 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_chrome_spec.pngbin0 -> 2700298 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_full_contrast.pngbin0 -> 2272310 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/brushed_full_contrast_inverted.pngbin0 -> 2272900 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/bubinga.pngbin0 -> 1617388 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/bubinga_bump.pngbin0 -> 245002 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/bubinga_spec.pngbin0 -> 229002 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/carbon_fiber.pngbin0 -> 4709566 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/carbon_fiber_aniso.pngbin0 -> 308757 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/carbon_fiber_bump.pngbin0 -> 2657804 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/carbon_fiber_spec.pngbin0 -> 4172072 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/concentric_milled_steel.pngbin0 -> 4216 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/concentric_milled_steel_aniso.pngbin0 -> 368334 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/concrete_plain.pngbin0 -> 2107394 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/concrete_plain_bump.pngbin0 -> 184163 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing.pngbin0 -> 342369 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing_normal.pngbin0 -> 92373 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/emissive.pngbin0 -> 334 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/emissive_mask.pngbin0 -> 334 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/gentle_noise.pngbin0 -> 4577174 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/granite_black.pngbin0 -> 1900736 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/granite_yellow.pngbin0 -> 2405231 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/grunge_b.pngbin0 -> 6977465 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/grunge_b1.pngbin0 -> 5502762 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/grunge_d.pngbin0 -> 3945985 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/grunge_texture_01.pngbin0 -> 8759326 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/mahogany.pngbin0 -> 1832923 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/mahogany_bump.pngbin0 -> 357957 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/mahogany_floorboards.pngbin0 -> 2254134 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/mahogany_floorboards_bump.pngbin0 -> 178207 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/mahogany_floorboards_spec.pngbin0 -> 219675 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/mahogany_spec.pngbin0 -> 355461 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/metal_mesh.pngbin0 -> 359882 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/metal_mesh_bump.pngbin0 -> 21046 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/metal_mesh_spec.pngbin0 -> 291286 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/paper_diffuse.pngbin0 -> 6055975 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/paper_trans.pngbin0 -> 4718043 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/powdercoat_bump_01.pngbin0 -> 3822468 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/randomGradient1D.pngbin0 -> 618 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/randomGradient2D.pngbin0 -> 738 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/randomGradient3D.pngbin0 -> 748 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/randomGradient4D.pngbin0 -> 535 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/shadow.pngbin0 -> 334 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/smooth_black_leather.pngbin0 -> 429570 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/smooth_black_leather_bump.pngbin0 -> 223014 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/smooth_black_leather_spec.pngbin0 -> 219279 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/spherical_checker.pngbin0 -> 11066 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/studded_rubber_bump.pngbin0 -> 26901 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/teak.pngbin0 -> 1198746 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/teak_bump.pngbin0 -> 170908 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/teak_spec.pngbin0 -> 213868 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/walnut.pngbin0 -> 1633772 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/walnut_bump.pngbin0 -> 283457 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/walnut_spec.pngbin0 -> 181017 bytes
-rw-r--r--Studio/Content/Material Library/maps/materials/white_marble.pngbin0 -> 1342939 bytes
-rw-r--r--Studio/Content/Material Library/mesh_fence.material236
-rw-r--r--Studio/Content/Material Library/metal_mesh_fine.material234
-rw-r--r--Studio/Content/Material Library/paper_artistic.material257
-rw-r--r--Studio/Content/Material Library/paper_office.material255
-rw-r--r--Studio/Content/Material Library/plastic_structured_red.material204
-rw-r--r--Studio/Content/Material Library/plastic_structured_red_emissive.material228
-rw-r--r--Studio/Content/Material Library/porcelain.material181
-rw-r--r--Studio/Content/Material Library/powder_coat.material221
-rw-r--r--Studio/Content/Material Library/powder_coat_emissive.material256
-rw-r--r--Studio/Content/Material Library/rubber_studded_black.material219
-rw-r--r--Studio/Content/Material Library/rubber_studded_emissive.material238
-rw-r--r--Studio/Content/Material Library/simple_glass.material197
-rw-r--r--Studio/Content/Material Library/steel_milled_concentric.material237
-rw-r--r--Studio/Content/Material Library/thin_glass_frosted.material485
-rw-r--r--Studio/Content/Material Library/thin_glass_frosted_sp.material246
-rw-r--r--Studio/Content/Material Library/thin_glass_refractive.material202
-rw-r--r--Studio/Content/Material Library/walnut_matte.material236
-rw-r--r--Studio/Content/Models Library/Electronics/Headphones.dae319
-rw-r--r--Studio/Content/Models Library/Logos/NVIDIA/NVIDIA_symbol.dae139
-rw-r--r--Studio/Content/Models Library/Media/DVD_cover-reflection.dae139
-rw-r--r--Studio/Content/Models Library/Media/DVD_cover.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Cubes/RoundedCube-1.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Cubes/RoundedCube-2.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Cubes/RoundedCube-3.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Cubes/RoundedCube-4.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Cubes/RoundedCube-5.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided-mirroredUVs.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-16X16.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-2X2.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-32X32.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-4X4.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-8X8.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-mirroredUVs.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/RoundedPlane-1.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/RoundedPlane-2.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3a.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3b.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-high-doublesided.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-high-inverted.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-high.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-low-doublesided.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-low-inverted.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-low.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-doublesided.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-inverted.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-medium.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Spheres/Sphere-planerUVprojection.dae139
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-1.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-2.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-3.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-4.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-5.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-6.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-7.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-8.DAE147
-rw-r--r--Studio/Content/Models Library/Primitives/Torus/Torus.dae139
-rw-r--r--build_instructions81
-rw-r--r--config.tests/fbx/fbx.pro13
-rw-r--r--config.tests/fbx/main.cpp39
-rw-r--r--configure.json5
-rw-r--r--doc/doc.pro6
-rw-r--r--doc/online/qt3dstudio.qdocconf2
-rw-r--r--doc/qt3dstudio-project.qdocconf54
-rw-r--r--doc/qt3dstudio.qdocconf2
-rw-r--r--doc/src/00-concepts.qdoc131
-rw-r--r--doc/src/03-studio/0-menu.qdoc223
-rw-r--r--doc/src/03-studio/1-toolbar.qdoc280
-rw-r--r--doc/src/03-studio/2-scene-view-and-matte.qdoc127
-rw-r--r--doc/src/03-studio/3-project-palette.qdoc122
-rw-r--r--doc/src/03-studio/4-basic-objects-palette.qdoc188
-rw-r--r--doc/src/03-studio/5-timeline-palette.qdoc379
-rw-r--r--doc/src/03-studio/6-slide-palette.qdoc96
-rw-r--r--doc/src/03-studio/7-inspector-palette.qdoc1092
-rw-r--r--doc/src/03-studio/8-action-palette.qdoc150
-rw-r--r--doc/src/03-studio/9-keyboard-shortcuts.qdoc315
-rw-r--r--doc/src/03-studio/studio-index.qdoc65
-rw-r--r--doc/src/04-viewer/0-menu.qdoc90
-rw-r--r--doc/src/04-viewer/1-keyboard.qdoc75
-rw-r--r--doc/src/04-viewer/viewer-index.qdoc44
-rw-r--r--doc/src/05-runtime/0-frame-update-cycle.qdoc174
-rw-r--r--doc/src/05-runtime/0b-inputplugins.qdoc47
-rw-r--r--doc/src/05-runtime/1-event-processing.qdoc227
-rw-r--r--doc/src/05-runtime/2-renderplugins.qdoc47
-rw-r--r--doc/src/05-runtime/runtime-index.qdoc49
-rw-r--r--doc/src/06-qml-reference/03-attribute-names.html1243
-rw-r--r--doc/src/06-qml-reference/03-attribute-names.qdoc39
-rw-r--r--doc/src/06-qml-reference/4-preserving-attributes.qdoc178
-rw-r--r--doc/src/06-qml-reference/Element.qdoc78
-rw-r--r--doc/src/06-qml-reference/Presentation.qdoc196
-rw-r--r--doc/src/06-qml-reference/Qt3DS_QML_Texture_Streaming.qdoc104
-rw-r--r--doc/src/06-qml-reference/SceneElement.qdoc151
-rw-r--r--doc/src/06-qml-reference/Studio3D.qdoc107
-rw-r--r--doc/src/06-qml-reference/ViewerSettings.qdoc131
-rw-r--r--doc/src/06-qml-reference/qml-index.qdoc58
-rw-r--r--doc/src/07-file-formats/0-uia.qdoc368
-rw-r--r--doc/src/07-file-formats/1-uip.qdoc36
-rw-r--r--doc/src/07-file-formats/3-material.qdoc265
-rw-r--r--doc/src/07-file-formats/4-effects.qdoc38
-rw-r--r--doc/src/07-file-formats/formats-index.qdoc45
-rw-r--r--doc/src/08-integrating/0-lua-modules.qdoc84
-rw-r--r--doc/src/08-integrating/1-render-plugins.qdoc179
-rw-r--r--doc/src/08-integrating/2-event-providers.qdoc36
-rw-r--r--doc/src/08-integrating/integrating-index.qdoc44
-rw-r--r--doc/src/10-best-practices/0-dynamic-keyframes.qdoc53
-rw-r--r--doc/src/10-best-practices/05-optimizingimages.qdoc281
-rw-r--r--doc/src/10-best-practices/10-antialiasing.qdoc371
-rw-r--r--doc/src/10-best-practices/20-creating-optimized-presentations.qdoc198
-rw-r--r--doc/src/10-best-practices/30-using-sub-presentations.qdoc97
-rw-r--r--doc/src/10-best-practices/35-scalemodes.qdoc234
-rw-r--r--doc/src/10-best-practices/40-disable-depth-test.qdoc131
-rw-r--r--doc/src/10-best-practices/45-blend-mode.qdoc126
-rw-r--r--doc/src/10-best-practices/50-creating-binary-and-optimized-presentations.qdoc193
-rw-r--r--doc/src/10-best-practices/60-importing-3d-content.qdoc779
-rw-r--r--doc/src/10-best-practices/70-using-skinned-animation.qdoc36
-rw-r--r--doc/src/10-best-practices/80-effects.qdoc257
-rw-r--r--doc/src/10-best-practices/practices-index.qdoc53
-rw-r--r--doc/src/11-quick-start-guides/10-getting-started.qdoc302
-rw-r--r--doc/src/12-copyright-notices.qdoc56
-rw-r--r--doc/src/12-cpp-reference/Q3DSElement.qdoc93
-rw-r--r--doc/src/12-cpp-reference/Q3DSPresentation.qdoc265
-rw-r--r--doc/src/12-cpp-reference/Q3DSSceneElement.qdoc123
-rw-r--r--doc/src/12-cpp-reference/Q3DSSurfaceViewer.qdoc191
-rw-r--r--doc/src/12-cpp-reference/Q3DSViewerSettings.qdoc117
-rw-r--r--doc/src/12-cpp-reference/Q3DSWidget.qdoc161
-rw-r--r--doc/src/12-cpp-reference/cpp-index.qdoc47
-rw-r--r--doc/src/13-contact-us.qdoc39
-rw-r--r--doc/src/contents.qdoc60
-rw-r--r--doc/src/images/3D_Content/00_transparentmap.pngbin0 -> 91229 bytes
-rw-r--r--doc/src/images/3D_Content/01_texture_map.pngbin0 -> 77774 bytes
-rw-r--r--doc/src/images/3D_Content/01b_modelingStart.pngbin0 -> 164004 bytes
-rw-r--r--doc/src/images/3D_Content/02_texture_elements.pngbin0 -> 47722 bytes
-rw-r--r--doc/src/images/3D_Content/03_backdropItem.pngbin0 -> 229213 bytes
-rw-r--r--doc/src/images/3D_Content/04_UVSpace.pngbin0 -> 375370 bytes
-rw-r--r--doc/src/images/3D_Content/05_TexturedModel.pngbin0 -> 514638 bytes
-rw-r--r--doc/src/images/3D_Content/07_freezeTransforms.pngbin0 -> 243537 bytes
-rw-r--r--doc/src/images/3D_Content/08_adjustPivots.pngbin0 -> 47903 bytes
-rw-r--r--doc/src/images/3D_Content/FBX-Maya.pngbin0 -> 20146 bytes
-rw-r--r--doc/src/images/3D_Content/Item_panel_parenting.pngbin0 -> 16328 bytes
-rw-r--r--doc/src/images/3D_Content/Lists.pngbin0 -> 9396 bytes
-rw-r--r--doc/src/images/3D_Content/Materials_InspectorPalette.pngbin0 -> 16873 bytes
-rw-r--r--doc/src/images/3D_Content/UVTab.pngbin0 -> 20127 bytes
-rw-r--r--doc/src/images/3D_Content/center.pngbin0 -> 34675 bytes
-rw-r--r--doc/src/images/3D_Content/colladaMax01.pngbin0 -> 53011 bytes
-rw-r--r--doc/src/images/3D_Content/colladaMax02.pngbin0 -> 21597 bytes
-rw-r--r--doc/src/images/3D_Content/colladaMaya01.pngbin0 -> 39780 bytes
-rw-r--r--doc/src/images/3D_Content/colladaMaya02.pngbin0 -> 33869 bytes
-rw-r--r--doc/src/images/3D_Content/colladaMaya03.pngbin0 -> 55939 bytes
-rw-r--r--doc/src/images/3D_Content/colladaMaya04.pngbin0 -> 69111 bytes
-rw-r--r--doc/src/images/3D_Content/colladaModo01.pngbin0 -> 114756 bytes
-rw-r--r--doc/src/images/3D_Content/colladaModo02.pngbin0 -> 130556 bytes
-rw-r--r--doc/src/images/3D_Content/colladaModo03.pngbin0 -> 119081 bytes
-rw-r--r--doc/src/images/3D_Content/colladaModo04.pngbin0 -> 64716 bytes
-rw-r--r--doc/src/images/3D_Content/export_DragDAE.pngbin0 -> 143579 bytes
-rw-r--r--doc/src/images/3D_Content/export_diffuseColor.pngbin0 -> 148613 bytes
-rw-r--r--doc/src/images/3D_Content/export_dragToScene.pngbin0 -> 104161 bytes
-rw-r--r--doc/src/images/3D_Content/export_exportSettings.pngbin0 -> 348902 bytes
-rw-r--r--doc/src/images/3D_Content/export_project.pngbin0 -> 12383 bytes
-rw-r--r--doc/src/images/3D_Content/export_triangulateMesh.pngbin0 -> 250623 bytes
-rw-r--r--doc/src/images/3D_Content/image_toMaterial.pngbin0 -> 159553 bytes
-rw-r--r--doc/src/images/3D_Content/modeling_glow.pngbin0 -> 40112 bytes
-rw-r--r--doc/src/images/3D_Content/modeling_needle.pngbin0 -> 81264 bytes
-rw-r--r--doc/src/images/3D_Content/selectPolys_MakeMaterial.pngbin0 -> 141496 bytes
-rw-r--r--doc/src/images/3D_Content/text01.pngbin0 -> 9588 bytes
-rw-r--r--doc/src/images/3D_Content/text02.pngbin0 -> 88155 bytes
-rw-r--r--doc/src/images/3D_Content/text03.pngbin0 -> 38738 bytes
-rw-r--r--doc/src/images/3D_Content/texture_inspectorPalette.pngbin0 -> 15148 bytes
-rw-r--r--doc/src/images/3D_Content/texture_selection.pngbin0 -> 46252 bytes
-rw-r--r--doc/src/images/3D_Content/timeline_material.pngbin0 -> 25852 bytes
-rw-r--r--doc/src/images/AA-GeometryAliasing.pngbin0 -> 33936 bytes
-rw-r--r--doc/src/images/AA-ReflectionAliasing.pngbin0 -> 136157 bytes
-rw-r--r--doc/src/images/AA-TextureAliasing.pngbin0 -> 268285 bytes
-rw-r--r--doc/src/images/AA-TextureAliasing2.pngbin0 -> 128348 bytes
-rw-r--r--doc/src/images/ApplicationPreferences.pngbin0 -> 24752 bytes
-rw-r--r--doc/src/images/Component.pngbin0 -> 14669 bytes
-rw-r--r--doc/src/images/DDS-Dialog.pngbin0 -> 16103 bytes
-rw-r--r--doc/src/images/DDS-Formats.pngbin0 -> 19836 bytes
-rw-r--r--doc/src/images/DisableDepthTest.pngbin0 -> 12357 bytes
-rw-r--r--doc/src/images/Effects-DOF-Debug.pngbin0 -> 1864 bytes
-rw-r--r--doc/src/images/Effects-DOF.pngbin0 -> 91209 bytes
-rw-r--r--doc/src/images/Effects-FXAA.pngbin0 -> 126136 bytes
-rw-r--r--doc/src/images/Effects-GaussianBlur.pngbin0 -> 103469 bytes
-rw-r--r--doc/src/images/Effects-HDRBloomTonemap.pngbin0 -> 154730 bytes
-rw-r--r--doc/src/images/Effects-MotionBlur.pngbin0 -> 27186 bytes
-rw-r--r--doc/src/images/Effects-TiltShift-Debug.pngbin0 -> 881 bytes
-rw-r--r--doc/src/images/Effects-TiltShift.pngbin0 -> 92429 bytes
-rw-r--r--doc/src/images/LayerBlendModeAdd.pngbin0 -> 9413 bytes
-rw-r--r--doc/src/images/LayerBlendModeColorburn.pngbin0 -> 8335 bytes
-rw-r--r--doc/src/images/LayerBlendModeColordodge.pngbin0 -> 9169 bytes
-rw-r--r--doc/src/images/LayerBlendModeMultiply.pngbin0 -> 8995 bytes
-rw-r--r--doc/src/images/LayerBlendModeNormal.pngbin0 -> 8248 bytes
-rw-r--r--doc/src/images/LayerBlendModeOverlay.pngbin0 -> 8992 bytes
-rw-r--r--doc/src/images/LayerBlendModeScreen.pngbin0 -> 9413 bytes
-rw-r--r--doc/src/images/LayerBlendModeSubtract.pngbin0 -> 8972 bytes
-rw-r--r--doc/src/images/LayerBlendModes.pngbin0 -> 7305 bytes
-rw-r--r--doc/src/images/Overview.pngbin0 -> 101718 bytes
-rw-r--r--doc/src/images/Runtime-AODistances.jpgbin0 -> 136494 bytes
-rw-r--r--doc/src/images/Runtime-AOSoftnesses.jpgbin0 -> 142684 bytes
-rw-r--r--doc/src/images/Runtime-ApplicationScaleMode.pngbin0 -> 11066 bytes
-rw-r--r--doc/src/images/Runtime-CameraModes.pngbin0 -> 97352 bytes
-rw-r--r--doc/src/images/Runtime-LayerSizing.pngbin0 -> 14338 bytes
-rw-r--r--doc/src/images/Studio-Action.pngbin0 -> 9589 bytes
-rw-r--r--doc/src/images/Studio-Basic-Alias.pngbin0 -> 3965 bytes
-rw-r--r--doc/src/images/Studio-Basic-Camera.pngbin0 -> 1776 bytes
-rw-r--r--doc/src/images/Studio-Basic-Component.pngbin0 -> 1357 bytes
-rw-r--r--doc/src/images/Studio-Basic-Cone.pngbin0 -> 1289 bytes
-rw-r--r--doc/src/images/Studio-Basic-Cube.pngbin0 -> 1391 bytes
-rw-r--r--doc/src/images/Studio-Basic-Cylinder.pngbin0 -> 1580 bytes
-rw-r--r--doc/src/images/Studio-Basic-Group.pngbin0 -> 1281 bytes
-rw-r--r--doc/src/images/Studio-Basic-Layer.pngbin0 -> 1026 bytes
-rw-r--r--doc/src/images/Studio-Basic-Light.pngbin0 -> 1228 bytes
-rw-r--r--doc/src/images/Studio-Basic-Rectangle.pngbin0 -> 1586 bytes
-rw-r--r--doc/src/images/Studio-Basic-Sphere.pngbin0 -> 1761 bytes
-rw-r--r--doc/src/images/Studio-Basic-Text.pngbin0 -> 863 bytes
-rw-r--r--doc/src/images/Studio-Project-Libraries.pngbin0 -> 1590 bytes
-rw-r--r--doc/src/images/Studio-Project-MissingAsset.pngbin0 -> 4843 bytes
-rw-r--r--doc/src/images/Studio-SceneView.pngbin0 -> 103811 bytes
-rw-r--r--doc/src/images/Studio-Slide-Main.pngbin0 -> 7378 bytes
-rw-r--r--doc/src/images/Studio-Slide-Master.pngbin0 -> 5123 bytes
-rw-r--r--doc/src/images/Studio-Timeline-ActionBadge.pngbin0 -> 238 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Animation-Keyframes.pngbin0 -> 13491 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Animation.pngbin0 -> 11068 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Breadcrumb.pngbin0 -> 7866 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Eyeball.pngbin0 -> 359 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Interpolation.pngbin0 -> 14344 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Lock.pngbin0 -> 265 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Overview.pngbin0 -> 35743 bytes
-rw-r--r--doc/src/images/Studio-Timeline-SceneGraph.pngbin0 -> 22598 bytes
-rw-r--r--doc/src/images/Studio-Timeline-Shy.pngbin0 -> 310 bytes
-rw-r--r--doc/src/images/Studio-Toolbar-Animation.pngbin0 -> 459 bytes
-rw-r--r--doc/src/images/Studio-Toolbar-EditCameras.pngbin0 -> 2974 bytes
-rw-r--r--doc/src/images/Studio-Toolbar-Playback.pngbin0 -> 393 bytes
-rw-r--r--doc/src/images/Studio-Toolbar-Preview.pngbin0 -> 397 bytes
-rw-r--r--doc/src/images/Studio-Toolbar-Selection.pngbin0 -> 707 bytes
-rw-r--r--doc/src/images/Studio-Toolbar-Transform.pngbin0 -> 882 bytes
-rw-r--r--doc/src/images/Studio-fx.pngbin0 -> 433 bytes
-rw-r--r--doc/src/images/Workflow-Solid.pngbin0 -> 184395 bytes
-rw-r--r--doc/src/images/add-diffuse-map-subpresentation.pngbin0 -> 25711 bytes
-rw-r--r--doc/src/images/add-diffuse-map.pngbin0 -> 26453 bytes
-rw-r--r--doc/src/images/addAssets.pngbin0 -> 29643 bytes
-rw-r--r--doc/src/images/animationIconActive.pngbin0 -> 15370 bytes
-rw-r--r--doc/src/images/animationIconInactive.pngbin0 -> 16268 bytes
-rw-r--r--doc/src/images/animationIcons.pngbin0 -> 953 bytes
-rw-r--r--doc/src/images/camera-scale-mode.pngbin0 -> 3350 bytes
-rw-r--r--doc/src/images/component_icon.pngbin0 -> 835 bytes
-rw-r--r--doc/src/images/component_timeline.pngbin0 -> 7381 bytes
-rw-r--r--doc/src/images/createNewProject.pngbin0 -> 918 bytes
-rw-r--r--doc/src/images/createNewProject2.pngbin0 -> 2009 bytes
-rw-r--r--doc/src/images/layer-position-properties.pngbin0 -> 13739 bytes
-rw-r--r--doc/src/images/layer-sub-presentation.pngbin0 -> 25319 bytes
-rw-r--r--doc/src/images/moreinfoicon.pngbin0 -> 19078 bytes
-rw-r--r--doc/src/images/newProjectDialog.pngbin0 -> 18524 bytes
-rw-r--r--doc/src/images/objectTimeline.pngbin0 -> 2728 bytes
-rw-r--r--doc/src/images/presentation-settings.pngbin0 -> 10877 bytes
-rw-r--r--doc/src/images/presentation-size.pngbin0 -> 4713 bytes
-rw-r--r--doc/src/images/sampleAssets.pngbin0 -> 2032 bytes
-rw-r--r--doc/src/images/slidePalette.pngbin0 -> 10319 bytes
-rw-r--r--doc/src/images/slidePlayMode.pngbin0 -> 3912 bytes
-rw-r--r--doc/src/images/studio_128.pngbin0 -> 5813 bytes
-rw-r--r--doc/src/images/subpresentation-dialog.pngbin0 -> 20443 bytes
-rw-r--r--doc/src/images/timeline.pngbin0 -> 26432 bytes
-rw-r--r--doc/src/images/uia-file.pngbin0 -> 18336 bytes
-rw-r--r--doc/src/images/view-scale-mode.pngbin0 -> 23229 bytes
-rw-r--r--doc/src/images/viewer_128.pngbin0 -> 4315 bytes
-rw-r--r--doc/src/images/welcomeScreen.pngbin0 -> 41478 bytes
-rw-r--r--examples/examples.pro4
-rw-r--r--examples/studio3d/qmlbehaviors/qmlbehaviors.uia16
-rw-r--r--examples/studio3d/qmlbehaviors/qmlbehaviors.uip93
-rw-r--r--examples/studio3d/qmlbehaviors/scripts/Billboard.qml182
-rw-r--r--examples/studio3d/qmlbehaviors/scripts/CatchEvents.qml66
-rw-r--r--examples/studio3d/qmlbehaviors/scripts/DateTime.qml60
-rw-r--r--examples/studio3d/qmlbehaviors/scripts/Keyboard.qml199
-rw-r--r--examples/studio3d/qmlbehaviors/scripts/SineWave.qml124
-rw-r--r--examples/studio3d/qmlbehaviors/scripts/Toggle.qml117
-rw-r--r--examples/studio3d/qmldynamickeyframes/main.cpp91
-rw-r--r--examples/studio3d/qmldynamickeyframes/presentation/dyn_key.uip95
-rw-r--r--examples/studio3d/qmldynamickeyframes/qml/qmldynamickeyframes/main.qml217
-rw-r--r--examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.pro19
-rw-r--r--examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.qrc6
-rw-r--r--examples/studio3d/qmlstreamer/main.cpp89
-rw-r--r--examples/studio3d/qmlstreamer/presentation/images/dummy.pngbin0 -> 1858 bytes
-rw-r--r--examples/studio3d/qmlstreamer/presentation/rotating_cube.uia7
-rw-r--r--examples/studio3d/qmlstreamer/presentation/rotating_cube.uip41
-rw-r--r--examples/studio3d/qmlstreamer/presentation/scripts/RedFill.qml80
-rw-r--r--examples/studio3d/qmlstreamer/qml/qmlstreamer/main.qml84
-rw-r--r--examples/studio3d/qmlstreamer/qmlstreamer.pro19
-rw-r--r--examples/studio3d/qmlstreamer/qmlstreamer.qrc9
-rw-r--r--examples/studio3d/studio3d.pro10
-rw-r--r--examples/studio3d/surfaceviewer/main.cpp101
-rw-r--r--examples/studio3d/surfaceviewer/presentation/circling_cube.uip72
-rw-r--r--examples/studio3d/surfaceviewer/presentation/fonts/TitilliumWeb-Regular.ttfbin0 -> 63752 bytes
-rw-r--r--examples/studio3d/surfaceviewer/surfaceviewer.pro13
-rw-r--r--examples/studio3d/surfaceviewer/surfaceviewer.qrc5
-rw-r--r--examples/studio3d/surfaceviewer_offscreen/main.cpp127
-rw-r--r--examples/studio3d/surfaceviewer_offscreen/presentation/circling_cube.uip70
-rw-r--r--examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.pro13
-rw-r--r--examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.qrc5
-rw-r--r--examples/studio3d/widgetviewer/main.cpp81
-rw-r--r--examples/studio3d/widgetviewer/mainwindow.cpp338
-rw-r--r--examples/studio3d/widgetviewer/mainwindow.h106
-rw-r--r--examples/studio3d/widgetviewer/mainwindow.ui201
-rw-r--r--examples/studio3d/widgetviewer/resources/style/checkbox.pngbin0 -> 343 bytes
-rw-r--r--examples/studio3d/widgetviewer/resources/style/dark.qss450
-rw-r--r--examples/studio3d/widgetviewer/resources/style/down_arrow.pngbin0 -> 1008 bytes
-rw-r--r--examples/studio3d/widgetviewer/resources/style/handle.pngbin0 -> 2837 bytes
-rw-r--r--examples/studio3d/widgetviewer/widgetviewer.pro14
-rw-r--r--examples/studio3d/widgetviewer/widgetviewer.qrc8
-rw-r--r--features/nostrictstrings.prf2
-rw-r--r--qt3dstudio.pro7
-rw-r--r--src/3rdparty/3rdparty.pro12
m---------src/3rdparty/ColladaDOM0
m---------src/3rdparty/EASTL0
m---------src/3rdparty/Lua0
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2.h677
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2ext.h2946
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2platform.h30
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3.h1213
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl31.h1528
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl32.h1829
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3ext.h24
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3platform.h30
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/MinKD.c317
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_extwindowprops.h65
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_multitouch.h84
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kd.h991
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kdplatform.h99
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_extwindowprops.h65
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_multitouch.h84
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kd.h991
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kdplatform.h99
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/MinKD.c327
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_extwindowprops.h65
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_multitouch.h84
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kd.h991
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kdplatform.h99
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_extwindowprops.h65
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_multitouch.h84
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kd.h991
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kdplatform.h101
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/MinKD.c326
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_extwindowprops.h65
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_multitouch.h84
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kd.h991
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kdplatform.h100
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/gl.h1543
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glcorearb.h4533
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glew.h16126
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glext.h11163
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glfuncdef.h343
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glu.h607
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glut.h771
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glx.h357
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxew.h1587
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxext.h941
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/nvogldebug.h794
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglew.h1363
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglext.h421
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_extwindowprops.h65
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_multitouch.h84
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kd.h991
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kdplatform.h99
-rw-r--r--src/3rdparty/RuntimePlatformSpecific/Windows/Qt3DSLibs/KD/MinKD.c330
-rw-r--r--src/3rdparty/color/CColor.cpp722
-rw-r--r--src/3rdparty/color/CColor.h298
m---------src/3rdparty/pcre0
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/doc/ReleaseNotes11
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/doc/utf8cpp.html1795
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/qt_attribution.json12
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/source/utf8.h34
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/source/utf8/checked.h327
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/source/utf8/core.h329
-rw-r--r--src/3rdparty/utf8cpp/2.3.2/source/utf8/unchecked.h228
-rw-r--r--src/Authoring/Authoring.pro19
-rw-r--r--src/Authoring/Build/versionnumber.h39
-rw-r--r--src/Authoring/Client/Code/Core/ClientErrorIDs.h171
-rw-r--r--src/Authoring/Client/Code/Core/Commands/Cmd.cpp187
-rw-r--r--src/Authoring/Client/Code/Core/Commands/Cmd.h140
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.cpp78
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.h64
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdBatch.cpp320
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdBatch.h85
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdCloseWindow.h73
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp193
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModel.h117
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelActionSetValue.h305
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelBase.h116
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelChangeKeyframe.h167
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelDeanimate.h159
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelDeleteInstance.h143
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h139
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModelRemoveKeyframe.h103
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdGeneric.h201
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdLocateReference.cpp331
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdLocateReference.h132
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdStack.cpp374
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdStack.h110
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdStackModifier.h42
-rw-r--r--src/Authoring/Client/Code/Core/Core/Core.cpp515
-rw-r--r--src/Authoring/Client/Code/Core/Core/Core.h106
-rw-r--r--src/Authoring/Client/Code/Core/Core/Dispatch.cpp693
-rw-r--r--src/Authoring/Client/Code/Core/Core/Dispatch.h272
-rw-r--r--src/Authoring/Client/Code/Core/Core/DispatchListeners.h339
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp2064
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h435
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ComposerEditorInterface.cpp598
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.cpp2869
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.h466
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp263
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp4874
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentEditorEnumerations.h66
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DynamicLua.cpp425
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DynamicLua.h98
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Exceptions.h169
-rw-r--r--src/Authoring/Client/Code/Core/Doc/GraphUtils.cpp431
-rw-r--r--src/Authoring/Client/Code/Core/Doc/GraphUtils.h118
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IComposerEditorInterface.h90
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp2864
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h115
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDataDrivenChangeListener.h64
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDoc.h155
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h66
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h106
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h476
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentReader.h295
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDragable.h69
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDropTargetHelper.h54
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IKeyframe.h57
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h58
-rw-r--r--src/Authoring/Client/Code/Core/Doc/INamable.h49
-rw-r--r--src/Authoring/Client/Code/Core/Doc/PathImportTranslator.cpp306
-rw-r--r--src/Authoring/Client/Code/Core/Doc/PathImportTranslator.h89
-rw-r--r--src/Authoring/Client/Code/Core/Doc/RelativePathTools.cpp338
-rw-r--r--src/Authoring/Client/Code/Core/Doc/RelativePathTools.h91
-rw-r--r--src/Authoring/Client/Code/Core/Doc/SelectedValue.h52
-rw-r--r--src/Authoring/Client/Code/Core/Doc/SelectedValueImpl.h227
-rw-r--r--src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp219
-rw-r--r--src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h95
-rw-r--r--src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.cpp241
-rw-r--r--src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.h84
-rw-r--r--src/Authoring/Client/Code/Core/Include/UICKeyDefs.h165
-rw-r--r--src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.cpp50
-rw-r--r--src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.h59
-rw-r--r--src/Authoring/Client/Code/Core/StdAfx.cpp33
-rw-r--r--src/Authoring/Client/Code/Core/StdAfx.h165
-rw-r--r--src/Authoring/Client/Code/Core/Timer/Timer.cpp135
-rw-r--r--src/Authoring/Client/Code/Core/Timer/Timer.h95
-rw-r--r--src/Authoring/Client/Code/Core/Types/BoolProbe.h51
-rw-r--r--src/Authoring/Client/Code/Core/Types/BoolScanner.h56
-rw-r--r--src/Authoring/Client/Code/Core/Types/BoundingBox.cpp228
-rw-r--r--src/Authoring/Client/Code/Core/Types/BoundingBox.h69
-rw-r--r--src/Authoring/Client/Code/Core/Types/CachedMatrix.cpp220
-rw-r--r--src/Authoring/Client/Code/Core/Types/CachedMatrix.h111
-rw-r--r--src/Authoring/Client/Code/Core/Types/Frustum.cpp138
-rw-r--r--src/Authoring/Client/Code/Core/Types/Frustum.h80
-rw-r--r--src/Authoring/Client/Code/Core/Types/Matrix.cpp1244
-rw-r--r--src/Authoring/Client/Code/Core/Types/Matrix.h195
-rw-r--r--src/Authoring/Client/Code/Core/Types/MatrixStack.h59
-rw-r--r--src/Authoring/Client/Code/Core/Types/OpaqueData.h43
-rw-r--r--src/Authoring/Client/Code/Core/Types/Pixel.cpp136
-rw-r--r--src/Authoring/Client/Code/Core/Types/Pixel.h83
-rw-r--r--src/Authoring/Client/Code/Core/Types/Plane.cpp115
-rw-r--r--src/Authoring/Client/Code/Core/Types/Plane.h74
-rw-r--r--src/Authoring/Client/Code/Core/Types/ProductStack.h40
-rw-r--r--src/Authoring/Client/Code/Core/Types/PropertyPublishLevels.h44
-rw-r--r--src/Authoring/Client/Code/Core/Types/Rotation3.cpp281
-rw-r--r--src/Authoring/Client/Code/Core/Types/Rotation3.h91
-rw-r--r--src/Authoring/Client/Code/Core/Types/TypesErrorIDs.h58
-rw-r--r--src/Authoring/Client/Code/Core/Types/UICColor.cpp612
-rw-r--r--src/Authoring/Client/Code/Core/Types/UICColor.h148
-rw-r--r--src/Authoring/Client/Code/Core/Types/Vector2.cpp407
-rw-r--r--src/Authoring/Client/Code/Core/Types/Vector2.h93
-rw-r--r--src/Authoring/Client/Code/Core/Types/Vector3.cpp579
-rw-r--r--src/Authoring/Client/Code/Core/Types/Vector3.h105
-rw-r--r--src/Authoring/Client/Code/Core/Types/Vertex.h99
-rw-r--r--src/Authoring/Client/Code/Core/UICOptions.h40
-rw-r--r--src/Authoring/Client/Code/Core/Utility/BuildConfigParser.cpp242
-rw-r--r--src/Authoring/Client/Code/Core/Utility/BuildConfigParser.h241
-rw-r--r--src/Authoring/Client/Code/Core/Utility/ColorConversion.cpp108
-rw-r--r--src/Authoring/Client/Code/Core/Utility/ColorConversion.h48
-rw-r--r--src/Authoring/Client/Code/Core/Utility/CoreConst.h134
-rw-r--r--src/Authoring/Client/Code/Core/Utility/CoreUtils.cpp54
-rw-r--r--src/Authoring/Client/Code/Core/Utility/CoreUtils.h44
-rw-r--r--src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.cpp326
-rw-r--r--src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.h94
-rw-r--r--src/Authoring/Client/Code/Core/Utility/DataTypesConverter.h150
-rw-r--r--src/Authoring/Client/Code/Core/Utility/GenericFunctor.h114
-rw-r--r--src/Authoring/Client/Code/Core/Utility/HotKeys.cpp651
-rw-r--r--src/Authoring/Client/Code/Core/Utility/HotKeys.h262
-rw-r--r--src/Authoring/Client/Code/Core/Utility/IDirectoryWatchingSystem.h76
-rw-r--r--src/Authoring/Client/Code/Core/Utility/IObjectReferenceHelper.h101
-rw-r--r--src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.cpp755
-rw-r--r--src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.h73
-rw-r--r--src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.cpp204
-rw-r--r--src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.h72
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioClipboard.cpp325
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioClipboard.h86
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioErrorIDs.h117
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp355
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h143
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp1854
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioPreferences.h299
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.cpp289
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.h102
-rw-r--r--src/Authoring/Client/Code/Core/Utility/TestCmdUtils.cpp122
-rw-r--r--src/Authoring/Client/Code/Core/Utility/TestCmdUtils.h65
-rw-r--r--src/Authoring/Client/Code/Core/Utility/cpuid.cpp352
-rw-r--r--src/Authoring/Client/Code/Core/Utility/cpuid.h70
-rw-r--r--src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.cpp86
-rw-r--r--src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.h49
-rw-r--r--src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.cpp231
-rw-r--r--src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.h81
-rw-r--r--src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.cpp261
-rw-r--r--src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.h98
-rw-r--r--src/Authoring/Client/Code/Core/VirtualAssets/VClock.h162
-rw-r--r--src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.cpp169
-rw-r--r--src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.h72
-rw-r--r--src/Authoring/Client/Code/Shared/CommonConstants.h156
-rw-r--r--src/Authoring/Client/Code/Shared/Log/LogHelper.cpp202
-rw-r--r--src/Authoring/Client/Code/Shared/Log/LogHelper.h60
-rw-r--r--src/Authoring/Client/Code/Shared/Log/LogProject.h400
-rw-r--r--src/Authoring/Client/Code/Shared/Log/LogTypes.h88
-rw-r--r--src/Authoring/Client/Code/Shared/Log/UICLog.h119
-rw-r--r--src/Authoring/Common/Code/AutoPtr.h287
-rw-r--r--src/Authoring/Common/Code/EulerAngles/EulerAngles.cpp880
-rw-r--r--src/Authoring/Common/Code/EulerAngles/EulerAngles.h186
-rw-r--r--src/Authoring/Common/Code/EulerAngles/QuatTypes.h53
-rw-r--r--src/Authoring/Common/Code/Exceptions/StudioException.h45
-rw-r--r--src/Authoring/Common/Code/Exceptions/UICExceptionClass.cpp425
-rw-r--r--src/Authoring/Common/Code/Exceptions/UICExceptionClass.h140
-rw-r--r--src/Authoring/Common/Code/Exceptions/UICExceptionConstants.h53
-rw-r--r--src/Authoring/Common/Code/Exceptions/UICExceptions.h144
-rw-r--r--src/Authoring/Common/Code/Exceptions/XMLException.cpp43
-rw-r--r--src/Authoring/Common/Code/Exceptions/XMLException.h54
-rw-r--r--src/Authoring/Common/Code/FileIterator.h62
-rw-r--r--src/Authoring/Common/Code/GUIDUtilities.h210
-rw-r--r--src/Authoring/Common/Code/Graph/Graph.cpp777
-rw-r--r--src/Authoring/Common/Code/Graph/Graph.h286
-rw-r--r--src/Authoring/Common/Code/Graph/GraphImpl.h446
-rw-r--r--src/Authoring/Common/Code/Graph/GraphPosition.h112
-rw-r--r--src/Authoring/Common/Code/Graph/IGraphable.h46
-rw-r--r--src/Authoring/Common/Code/HiResTimer.cpp104
-rw-r--r--src/Authoring/Common/Code/HiResTimer.h58
-rw-r--r--src/Authoring/Common/Code/IO/BufferedInputStream.cpp168
-rw-r--r--src/Authoring/Common/Code/IO/BufferedInputStream.h75
-rw-r--r--src/Authoring/Common/Code/IO/BufferedOutputStream.cpp241
-rw-r--r--src/Authoring/Common/Code/IO/BufferedOutputStream.h99
-rw-r--r--src/Authoring/Common/Code/IO/ByteSwap.h43
-rw-r--r--src/Authoring/Common/Code/IO/FileInputStream.cpp196
-rw-r--r--src/Authoring/Common/Code/IO/FileInputStream.h80
-rw-r--r--src/Authoring/Common/Code/IO/FileOutputStream.cpp243
-rw-r--r--src/Authoring/Common/Code/IO/FileOutputStream.h108
-rw-r--r--src/Authoring/Common/Code/IO/IOLibraryException.h48
-rw-r--r--src/Authoring/Common/Code/IO/IOStreams.cpp600
-rw-r--r--src/Authoring/Common/Code/IO/IOStreams.h127
-rw-r--r--src/Authoring/Common/Code/IO/InputStream.h62
-rw-r--r--src/Authoring/Common/Code/IO/LEndianStreams.cpp178
-rw-r--r--src/Authoring/Common/Code/IO/LEndianStreams.h70
-rw-r--r--src/Authoring/Common/Code/IO/MemBuf.cpp217
-rw-r--r--src/Authoring/Common/Code/IO/MemBuf.h90
-rw-r--r--src/Authoring/Common/Code/IO/MemInputStream.cpp145
-rw-r--r--src/Authoring/Common/Code/IO/MemInputStream.h110
-rw-r--r--src/Authoring/Common/Code/IO/MemOutputStream.cpp142
-rw-r--r--src/Authoring/Common/Code/IO/MemOutputStream.h100
-rw-r--r--src/Authoring/Common/Code/IO/MessageTypes.h98
-rw-r--r--src/Authoring/Common/Code/IO/OutputStream.h52
-rw-r--r--src/Authoring/Common/Code/IO/Seekable.cpp50
-rw-r--r--src/Authoring/Common/Code/IO/Seekable.h64
-rw-r--r--src/Authoring/Common/Code/IO/UICEndian.h97
-rw-r--r--src/Authoring/Common/Code/InfoDump/CoutSink.cpp60
-rw-r--r--src/Authoring/Common/Code/InfoDump/CoutSink.h64
-rw-r--r--src/Authoring/Common/Code/InfoDump/DumpFileSink.cpp101
-rw-r--r--src/Authoring/Common/Code/InfoDump/DumpFileSink.h73
-rw-r--r--src/Authoring/Common/Code/InfoDump/InfoDump.cpp219
-rw-r--r--src/Authoring/Common/Code/InfoDump/InfoDump.h115
-rw-r--r--src/Authoring/Common/Code/InfoDump/InfoSink.cpp59
-rw-r--r--src/Authoring/Common/Code/InfoDump/InfoSink.h75
-rw-r--r--src/Authoring/Common/Code/InfoDump/StrVecSink.cpp324
-rw-r--r--src/Authoring/Common/Code/InfoDump/StrVecSink.h90
-rw-r--r--src/Authoring/Common/Code/LICENSE_FOREACH.TXT7
-rw-r--r--src/Authoring/Common/Code/ListIterator.h174
-rw-r--r--src/Authoring/Common/Code/Literals.h51
-rw-r--r--src/Authoring/Common/Code/MapIterator.h173
-rw-r--r--src/Authoring/Common/Code/MasterP.cpp105
-rw-r--r--src/Authoring/Common/Code/MasterP.h145
-rw-r--r--src/Authoring/Common/Code/Matrix.inl687
-rw-r--r--src/Authoring/Common/Code/Memory/IMemoryObject.h120
-rw-r--r--src/Authoring/Common/Code/Memory/MemoryObject.cpp353
-rw-r--r--src/Authoring/Common/Code/Memory/MemoryObject.h167
-rw-r--r--src/Authoring/Common/Code/Memory/MemoryObjectMacros.h131
-rw-r--r--src/Authoring/Common/Code/Memory/MemoryObjectSize.h118
-rw-r--r--src/Authoring/Common/Code/Memory/UICMemoryLeak.cpp260
-rw-r--r--src/Authoring/Common/Code/Memory/UICMemoryLeak.h84
-rw-r--r--src/Authoring/Common/Code/MethProf.cpp167
-rw-r--r--src/Authoring/Common/Code/MethProf.h72
-rw-r--r--src/Authoring/Common/Code/Multicaster.h199
-rw-r--r--src/Authoring/Common/Code/Preferences.h94
-rw-r--r--src/Authoring/Common/Code/Pt.cpp39
-rw-r--r--src/Authoring/Common/Code/Pt.h258
-rw-r--r--src/Authoring/Common/Code/PtrVector.h141
-rw-r--r--src/Authoring/Common/Code/Quaternion.inl612
-rw-r--r--src/Authoring/Common/Code/Rct.h278
-rw-r--r--src/Authoring/Common/Code/Report/CompConfig.cpp71
-rw-r--r--src/Authoring/Common/Code/Report/CompConfig.h93
-rw-r--r--src/Authoring/Common/Code/Report/CrashInfo.cpp185
-rw-r--r--src/Authoring/Common/Code/Report/CrashInfo.h69
-rw-r--r--src/Authoring/Common/Code/Report/ProductInfo.cpp123
-rw-r--r--src/Authoring/Common/Code/Report/ProductInfo.h112
-rw-r--r--src/Authoring/Common/Code/Report/ProductInstance.cpp118
-rw-r--r--src/Authoring/Common/Code/Report/ProductInstance.h100
-rw-r--r--src/Authoring/Common/Code/Report/StackOps.cpp316
-rw-r--r--src/Authoring/Common/Code/Report/StackOps.h100
-rw-r--r--src/Authoring/Common/Code/SIterator.h49
-rw-r--r--src/Authoring/Common/Code/STLHelpers.h98
-rw-r--r--src/Authoring/Common/Code/SafeArray.h695
-rw-r--r--src/Authoring/Common/Code/SafeQueue.h223
-rw-r--r--src/Authoring/Common/Code/Serialize/FormattedInputStream.cpp176
-rw-r--r--src/Authoring/Common/Code/Serialize/FormattedInputStream.h70
-rw-r--r--src/Authoring/Common/Code/Serialize/FormattedOutputStream.cpp112
-rw-r--r--src/Authoring/Common/Code/Serialize/FormattedOutputStream.h65
-rw-r--r--src/Authoring/Common/Code/Serialize/PreferencesSerializer.cpp254
-rw-r--r--src/Authoring/Common/Code/Serialize/PreferencesSerializer.h85
-rw-r--r--src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h182
-rw-r--r--src/Authoring/Common/Code/StackTokenizer.cpp151
-rw-r--r--src/Authoring/Common/Code/StackTokenizer.h72
-rw-r--r--src/Authoring/Common/Code/StaticMaxSize.h50
-rw-r--r--src/Authoring/Common/Code/StopWatch.h65
-rw-r--r--src/Authoring/Common/Code/StrUtilities.cpp216
-rw-r--r--src/Authoring/Common/Code/StrUtilities.h191
-rw-r--r--src/Authoring/Common/Code/StringTokenizer.cpp125
-rw-r--r--src/Authoring/Common/Code/StringTokenizer.h65
-rw-r--r--src/Authoring/Common/Code/Thread/Conditional.h121
-rw-r--r--src/Authoring/Common/Code/Thread/Guard.h99
-rw-r--r--src/Authoring/Common/Code/Thread/Mutex.cpp51
-rw-r--r--src/Authoring/Common/Code/Thread/Mutex.h119
-rw-r--r--src/Authoring/Common/Code/Thread/Runnable.h43
-rw-r--r--src/Authoring/Common/Code/Thread/Thread.cpp251
-rw-r--r--src/Authoring/Common/Code/Thread/Thread.h103
-rw-r--r--src/Authoring/Common/Code/Thread/ThreadException.h49
-rw-r--r--src/Authoring/Common/Code/UICAtomic.cpp260
-rw-r--r--src/Authoring/Common/Code/UICDESKey.h31
-rw-r--r--src/Authoring/Common/Code/UICFile.h116
-rw-r--r--src/Authoring/Common/Code/UICFileToolTypes.h115
-rw-r--r--src/Authoring/Common/Code/UICFileTools.cpp1167
-rw-r--r--src/Authoring/Common/Code/UICFileTools.h488
-rw-r--r--src/Authoring/Common/Code/UICFunctor.h431
-rw-r--r--src/Authoring/Common/Code/UICId.cpp305
-rw-r--r--src/Authoring/Common/Code/UICId.h111
-rw-r--r--src/Authoring/Common/Code/UICLargeInteger.h40
-rw-r--r--src/Authoring/Common/Code/UICMacros.h137
-rw-r--r--src/Authoring/Common/Code/UICMath.cpp226
-rw-r--r--src/Authoring/Common/Code/UICMath.h434
-rw-r--r--src/Authoring/Common/Code/UICMemory.cpp225
-rw-r--r--src/Authoring/Common/Code/UICMemory.h114
-rw-r--r--src/Authoring/Common/Code/UICMessageBox.cpp99
-rw-r--r--src/Authoring/Common/Code/UICMessageBox.h89
-rw-r--r--src/Authoring/Common/Code/UICObjectCounter.cpp40
-rw-r--r--src/Authoring/Common/Code/UICObjectCounter.h178
-rw-r--r--src/Authoring/Common/Code/UICPoint.h149
-rw-r--r--src/Authoring/Common/Code/UICPointBase.h56
-rw-r--r--src/Authoring/Common/Code/UICRect.h417
-rw-r--r--src/Authoring/Common/Code/UICRectBase.h58
-rw-r--r--src/Authoring/Common/Code/UICSharedPtr.h346
-rw-r--r--src/Authoring/Common/Code/UICString.cpp987
-rw-r--r--src/Authoring/Common/Code/UICString.h525
-rw-r--r--src/Authoring/Common/Code/UICSynch.h430
-rw-r--r--src/Authoring/Common/Code/UICTime.cpp368
-rw-r--r--src/Authoring/Common/Code/UICTime.h156
-rw-r--r--src/Authoring/Common/Code/Vector3.inl545
-rw-r--r--src/Authoring/Common/Code/_Qt/QtUICFile.cpp455
-rw-r--r--src/Authoring/Common/Code/_Win32/DLLVersion.cpp417
-rw-r--r--src/Authoring/Common/Code/_Win32/DLLVersion.h123
-rw-r--r--src/Authoring/Common/Code/_Win32/FileIterator.cpp121
-rw-r--r--src/Authoring/Common/Code/_Win32/Include/PlatformConversion.h119
-rw-r--r--src/Authoring/Common/Code/_Win32/Include/PlatformMacros.h43
-rw-r--r--src/Authoring/Common/Code/_Win32/Include/PlatformStrings.h57
-rw-r--r--src/Authoring/Common/Code/_Win32/Include/PlatformTypes.h140
-rw-r--r--src/Authoring/Common/Code/_Win32/Preferences.cpp305
-rw-r--r--src/Authoring/Common/Code/_Win32/ProductInfo2.h83
-rw-r--r--src/Authoring/Common/Code/_Win32/SystemInfo.cpp862
-rw-r--r--src/Authoring/Common/Code/_Win32/SystemInfo.h175
-rw-r--r--src/Authoring/Common/Code/_Win32/UICFile.cpp623
-rw-r--r--src/Authoring/Common/Code/_Win32/UICRegistry.cpp203
-rw-r--r--src/Authoring/Common/Code/_Win32/UICRegistry.h72
-rw-r--r--src/Authoring/Common/Code/_Win32/Win32Config.cpp720
-rw-r--r--src/Authoring/Common/Code/_Win32/Win32Config.h160
-rw-r--r--src/Authoring/Common/Code/_Win32/stdafx.cpp36
-rw-r--r--src/Authoring/Common/Code/_Win32/stdafx.h85
-rw-r--r--src/Authoring/Common/Code/qt_attribution.json24
-rw-r--r--src/Authoring/CommonLib.pri63
-rw-r--r--src/Authoring/CommonLib.pro28
-rw-r--r--src/Authoring/CoreLib.pri67
-rw-r--r--src/Authoring/CoreLib.pro63
-rw-r--r--src/Authoring/FBXLineExporter.pri1
-rw-r--r--src/Authoring/FBXLineExporter.pro35
-rw-r--r--src/Authoring/FBXLineExporter/FBXLineExporter.cpp201
-rw-r--r--src/Authoring/MeshOptimizer/Source/MeshOptimizer.cpp253
-rw-r--r--src/Authoring/MorphLines.pri1
-rw-r--r--src/Authoring/MorphLines.pro38
-rw-r--r--src/Authoring/MorphLinesExporter/MorphLines.cpp133
-rw-r--r--src/Authoring/PresentationCompiler.pro50
-rw-r--r--src/Authoring/Q3DStudio.pri310
-rw-r--r--src/Authoring/Q3DStudio.pro225
-rw-r--r--src/Authoring/Qt3DSState.pri5
-rw-r--r--src/Authoring/Qt3DSState.pro21
-rw-r--r--src/Authoring/Studio/Application/MsgRouter.h125
-rw-r--r--src/Authoring/Studio/Application/StudioConst.h158
-rw-r--r--src/Authoring/Studio/Application/StudioDefs.h44
-rw-r--r--src/Authoring/Studio/Application/StudioInstance.cpp86
-rw-r--r--src/Authoring/Studio/Application/StudioInstance.h49
-rw-r--r--src/Authoring/Studio/Application/StudioTutorialWidget.cpp236
-rw-r--r--src/Authoring/Studio/Application/StudioTutorialWidget.h94
-rw-r--r--src/Authoring/Studio/Application/StudioTutorialWidget.ui184
-rw-r--r--src/Authoring/Studio/Controls/BaseMeasure.cpp206
-rw-r--r--src/Authoring/Studio/Controls/BaseMeasure.h81
-rw-r--r--src/Authoring/Studio/Controls/BlankControl.cpp118
-rw-r--r--src/Authoring/Studio/Controls/BlankControl.h57
-rw-r--r--src/Authoring/Studio/Controls/BreadCrumbControl.cpp326
-rw-r--r--src/Authoring/Studio/Controls/BreadCrumbControl.h94
-rw-r--r--src/Authoring/Studio/Controls/ButtonControl.cpp425
-rw-r--r--src/Authoring/Studio/Controls/ButtonControl.h124
-rw-r--r--src/Authoring/Studio/Controls/ClickableLabel.cpp51
-rw-r--r--src/Authoring/Studio/Controls/ClickableLabel.h48
-rw-r--r--src/Authoring/Studio/Controls/ComboTextBox.h65
-rw-r--r--src/Authoring/Studio/Controls/Control.cpp1806
-rw-r--r--src/Authoring/Studio/Controls/Control.h263
-rw-r--r--src/Authoring/Studio/Controls/ControlData.cpp763
-rw-r--r--src/Authoring/Studio/Controls/ControlData.h276
-rw-r--r--src/Authoring/Studio/Controls/ControlGraph.cpp188
-rw-r--r--src/Authoring/Studio/Controls/ControlGraph.h68
-rw-r--r--src/Authoring/Studio/Controls/ControlGraphIterators.h156
-rw-r--r--src/Authoring/Studio/Controls/EditInPlace.h280
-rw-r--r--src/Authoring/Studio/Controls/FloatEdit.cpp524
-rw-r--r--src/Authoring/Studio/Controls/FloatEdit.h115
-rw-r--r--src/Authoring/Studio/Controls/FlowLayout.cpp1009
-rw-r--r--src/Authoring/Studio/Controls/FlowLayout.h140
-rw-r--r--src/Authoring/Studio/Controls/GenericComboDropDown.h99
-rw-r--r--src/Authoring/Studio/Controls/GenericEdit.h94
-rw-r--r--src/Authoring/Studio/Controls/InsertionLine.cpp142
-rw-r--r--src/Authoring/Studio/Controls/InsertionLine.h76
-rw-r--r--src/Authoring/Studio/Controls/InsertionOverlay.cpp112
-rw-r--r--src/Authoring/Studio/Controls/InsertionOverlay.h74
-rw-r--r--src/Authoring/Studio/Controls/LazyFlow.cpp318
-rw-r--r--src/Authoring/Studio/Controls/LazyFlow.h267
-rw-r--r--src/Authoring/Studio/Controls/ListBoxItem.cpp277
-rw-r--r--src/Authoring/Studio/Controls/ListBoxItem.h101
-rw-r--r--src/Authoring/Studio/Controls/ListBoxStringItem.cpp108
-rw-r--r--src/Authoring/Studio/Controls/ListBoxStringItem.h72
-rw-r--r--src/Authoring/Studio/Controls/ListLayout.cpp185
-rw-r--r--src/Authoring/Studio/Controls/ListLayout.h60
-rw-r--r--src/Authoring/Studio/Controls/NameEdit.cpp138
-rw-r--r--src/Authoring/Studio/Controls/NameEdit.h70
-rw-r--r--src/Authoring/Studio/Controls/OverlayControl.cpp240
-rw-r--r--src/Authoring/Studio/Controls/OverlayControl.h83
-rw-r--r--src/Authoring/Studio/Controls/ProceduralButton.h569
-rw-r--r--src/Authoring/Studio/Controls/Renderer.cpp74
-rw-r--r--src/Authoring/Studio/Controls/Renderer.h105
-rw-r--r--src/Authoring/Studio/Controls/SIcon.cpp165
-rw-r--r--src/Authoring/Studio/Controls/SIcon.h74
-rw-r--r--src/Authoring/Studio/Controls/ScrollController.cpp211
-rw-r--r--src/Authoring/Studio/Controls/ScrollController.h82
-rw-r--r--src/Authoring/Studio/Controls/Scroller.cpp829
-rw-r--r--src/Authoring/Studio/Controls/Scroller.h171
-rw-r--r--src/Authoring/Studio/Controls/ScrollerBackground.cpp202
-rw-r--r--src/Authoring/Studio/Controls/ScrollerBackground.h69
-rw-r--r--src/Authoring/Studio/Controls/ScrollerBar.cpp333
-rw-r--r--src/Authoring/Studio/Controls/ScrollerBar.h120
-rw-r--r--src/Authoring/Studio/Controls/ScrollerButtonControl.cpp97
-rw-r--r--src/Authoring/Studio/Controls/ScrollerButtonControl.h76
-rw-r--r--src/Authoring/Studio/Controls/ScrollerThumb.cpp197
-rw-r--r--src/Authoring/Studio/Controls/ScrollerThumb.h76
-rw-r--r--src/Authoring/Studio/Controls/SplashControl.cpp107
-rw-r--r--src/Authoring/Studio/Controls/SplashControl.h70
-rw-r--r--src/Authoring/Studio/Controls/SplitBar.cpp205
-rw-r--r--src/Authoring/Studio/Controls/SplitBar.h97
-rw-r--r--src/Authoring/Studio/Controls/Splitter.cpp419
-rw-r--r--src/Authoring/Studio/Controls/Splitter.h74
-rw-r--r--src/Authoring/Studio/Controls/StringEdit.cpp246
-rw-r--r--src/Authoring/Studio/Controls/StringEdit.h73
-rw-r--r--src/Authoring/Studio/Controls/TextButton.h350
-rw-r--r--src/Authoring/Studio/Controls/TextEdit.cpp1478
-rw-r--r--src/Authoring/Studio/Controls/TextEdit.h215
-rw-r--r--src/Authoring/Studio/Controls/TextEditContextMenu.cpp135
-rw-r--r--src/Authoring/Studio/Controls/TextEditContextMenu.h77
-rw-r--r--src/Authoring/Studio/Controls/TextEditInPlace.cpp324
-rw-r--r--src/Authoring/Studio/Controls/TextEditInPlace.h92
-rw-r--r--src/Authoring/Studio/Controls/TimeEdit.cpp195
-rw-r--r--src/Authoring/Studio/Controls/TimeEdit.h81
-rw-r--r--src/Authoring/Studio/Controls/ToggleButton.cpp140
-rw-r--r--src/Authoring/Studio/Controls/ToggleButton.h89
-rw-r--r--src/Authoring/Studio/Controls/TreeControl.cpp749
-rw-r--r--src/Authoring/Studio/Controls/TreeControl.h140
-rw-r--r--src/Authoring/Studio/Controls/TreeItem.cpp939
-rw-r--r--src/Authoring/Studio/Controls/TreeItem.h158
-rw-r--r--src/Authoring/Studio/Controls/WidgetControl.cpp439
-rw-r--r--src/Authoring/Studio/Controls/WidgetControl.h110
-rw-r--r--src/Authoring/Studio/Docs/CmdLineOptions.txt27
-rw-r--r--src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.cpp266
-rw-r--r--src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.h64
-rw-r--r--src/Authoring/Studio/DragAndDrop/DropContainer.cpp96
-rw-r--r--src/Authoring/Studio/DragAndDrop/DropContainer.h81
-rw-r--r--src/Authoring/Studio/DragAndDrop/DropSource.cpp131
-rw-r--r--src/Authoring/Studio/DragAndDrop/DropSource.h100
-rw-r--r--src/Authoring/Studio/DragAndDrop/DropTarget.cpp57
-rw-r--r--src/Authoring/Studio/DragAndDrop/DropTarget.h67
-rw-r--r--src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.cpp123
-rw-r--r--src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.h70
-rw-r--r--src/Authoring/Studio/DragAndDrop/FileDropSource.cpp199
-rw-r--r--src/Authoring/Studio/DragAndDrop/FileDropSource.h74
-rw-r--r--src/Authoring/Studio/DragAndDrop/ListBoxDropSource.cpp83
-rw-r--r--src/Authoring/Studio/DragAndDrop/ListBoxDropSource.h60
-rw-r--r--src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.cpp116
-rw-r--r--src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.h65
-rw-r--r--src/Authoring/Studio/DragAndDrop/ProjectDropTarget.cpp229
-rw-r--r--src/Authoring/Studio/DragAndDrop/ProjectDropTarget.h62
-rw-r--r--src/Authoring/Studio/DragAndDrop/SceneDropTarget.cpp242
-rw-r--r--src/Authoring/Studio/DragAndDrop/SceneDropTarget.h67
-rw-r--r--src/Authoring/Studio/DragAndDrop/TimelineDropSource.cpp167
-rw-r--r--src/Authoring/Studio/DragAndDrop/TimelineDropSource.h66
-rw-r--r--src/Authoring/Studio/DragAndDrop/TimelineDropTarget.cpp230
-rw-r--r--src/Authoring/Studio/DragAndDrop/TimelineDropTarget.h88
-rw-r--r--src/Authoring/Studio/English.lproj/Strings/Static.stribin0 -> 50010 bytes
-rw-r--r--src/Authoring/Studio/English.lproj/Strings/Static.strobin0 -> 48720 bytes
-rw-r--r--src/Authoring/Studio/English.lproj/Strings/Strings.h301
-rw-r--r--src/Authoring/Studio/English.lproj/Strings/StringsReadme.htm124
-rw-r--r--src/Authoring/Studio/English.lproj/Strings/compile.py245
-rw-r--r--src/Authoring/Studio/English.lproj/Strings/compile32.py272
-rw-r--r--src/Authoring/Studio/MainFrm.cpp2049
-rw-r--r--src/Authoring/Studio/MainFrm.h249
-rw-r--r--src/Authoring/Studio/MainFrm.qrc83
-rw-r--r--src/Authoring/Studio/MainFrm.ui799
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionContextMenu.cpp76
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionContextMenu.h58
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionModel.cpp225
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionModel.h77
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionView.cpp848
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionView.h201
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionView.qml426
-rw-r--r--src/Authoring/Studio/Palettes/Action/EventsBrowser.qml163
-rw-r--r--src/Authoring/Studio/Palettes/Action/EventsBrowserView.cpp99
-rw-r--r--src/Authoring/Studio/Palettes/Action/EventsBrowserView.h70
-rw-r--r--src/Authoring/Studio/Palettes/Action/EventsModel.cpp262
-rw-r--r--src/Authoring/Studio/Palettes/Action/EventsModel.h96
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerEmitSignal.qml51
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerFireEvent.qml55
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerGenericBaseColor.qml80
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerGenericCheckbox.qml59
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerGenericColor.qml53
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerGenericText.qml53
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerGoToSlide.qml62
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerMultilineText.qml84
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerProperty.qml255
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseSlider.qml164
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseXYZ.qml91
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerPropertyCombo.qml55
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerPropertySlider.qml64
-rw-r--r--src/Authoring/Studio/Palettes/Action/HandlerPropertyXYZ.qml63
-rw-r--r--src/Authoring/Studio/Palettes/Action/PropertyModel.cpp219
-rw-r--r--src/Authoring/Studio/Palettes/Action/PropertyModel.h80
-rw-r--r--src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.cpp119
-rw-r--r--src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.h99
-rw-r--r--src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.cpp74
-rw-r--r--src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.h52
-rw-r--r--src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.qml88
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ChooserDelegate.qml81
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.cpp592
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.h119
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.cpp56
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.h58
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/FileChooser.qml65
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/FileChooserModel.cpp50
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/FileChooserModel.h46
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/FileChooserView.cpp108
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/FileChooserView.h67
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/GuideInspectable.cpp322
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/GuideInspectable.h86
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/HandlerFilesChooser.qml48
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/HandlerGenericChooser.qml47
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/IEasyInspectorRowListener.h48
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/IInspectableItem.h211
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ImageChooser.qml65
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.cpp49
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.h47
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ImageChooserView.cpp117
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ImageChooserView.h67
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectableBase.cpp38
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectableBase.h67
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp862
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h180
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp429
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h125
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml771
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorGroup.cpp61
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorGroup.h67
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/MeshChooser.qml63
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.cpp64
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.h47
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/MeshChooserView.cpp131
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/MeshChooserView.h68
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectBrowser.qml175
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.cpp117
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.h94
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectListModel.cpp336
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectListModel.h120
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectReference.qml41
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.cpp53
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.h45
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.cpp101
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.h65
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.cpp120
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.h65
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/TextureChooser.qml70
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/TextureChooserView.cpp107
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/TextureChooserView.h67
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.cpp325
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.h77
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.cpp83
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.h78
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.cpp75
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.h92
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.cpp226
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.h60
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.cpp77
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.h66
-rw-r--r--src/Authoring/Studio/Palettes/Master/MasterControl.cpp295
-rw-r--r--src/Authoring/Studio/Palettes/Master/MasterControl.h114
-rw-r--r--src/Authoring/Studio/Palettes/Master/MasterView.cpp154
-rw-r--r--src/Authoring/Studio/Palettes/Master/MasterView.h78
-rw-r--r--src/Authoring/Studio/Palettes/Progress/ProgressCallback.h57
-rw-r--r--src/Authoring/Studio/Palettes/Progress/ProgressControl.cpp133
-rw-r--r--src/Authoring/Studio/Palettes/Progress/ProgressControl.h72
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectContextMenu.cpp81
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectContextMenu.h53
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp587
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h107
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectView.cpp250
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectView.h102
-rw-r--r--src/Authoring/Studio/Palettes/Project/ProjectView.qml231
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideContextMenu.cpp71
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideContextMenu.h53
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideModel.cpp273
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideModel.h81
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideView.cpp315
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideView.h113
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideView.qml249
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.cpp64
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.h53
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.cpp440
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.h110
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BaseStateRow.cpp1139
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BaseStateRow.h205
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.cpp186
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.h80
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.cpp685
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.h125
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.cpp65
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.h61
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.cpp115
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.h66
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.cpp115
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.h63
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/IKeyframeSelector.h52
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItem.h73
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h190
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemProperty.h81
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineKeyframesManager.h55
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineTimebar.h74
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.cpp97
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.h78
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.cpp506
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.h108
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.cpp317
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.h77
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp336
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h83
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.cpp73
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.h65
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h118
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.cpp44
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.h69
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.cpp58
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.h65
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.cpp104
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.h121
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.cpp239
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.h74
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp599
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.h160
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.cpp80
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.h69
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimeline.h42
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.cpp1260
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.h225
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.cpp579
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.h119
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.cpp213
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.h84
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.cpp263
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.h90
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.cpp169
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.h65
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.cpp86
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.h60
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ColorControl.cpp307
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ColorControl.h98
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/CommentEdit.cpp231
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/CommentEdit.h77
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.cpp309
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.h107
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/FilterToolbar.cpp271
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/FilterToolbar.h80
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/IBreadCrumbProvider.h72
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ITimelineControl.h53
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.cpp405
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.h154
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.cpp30
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.h149
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Playhead.cpp266
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Playhead.h82
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.cpp89
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.h55
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.cpp152
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.h73
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyRow.cpp377
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyRow.h102
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.cpp234
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.h70
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.cpp508
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.h103
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.cpp374
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.h95
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.cpp110
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.h58
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.cpp190
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.h68
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ScalableScroller.cpp78
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ScalableScroller.h57
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.cpp359
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.h112
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/SlideRow.cpp124
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/SlideRow.h63
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.cpp78
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.h60
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Snapper.cpp455
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/Snapper.h118
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateRow.cpp311
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateRow.h90
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateRowFactory.cpp60
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateRowFactory.h50
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.cpp156
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.h67
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.cpp364
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.h87
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.cpp49
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.h51
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimeMeasure.cpp340
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimeMeasure.h74
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimeToolbar.cpp135
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimeToolbar.h75
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimebarControl.cpp690
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimebarControl.h144
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimebarTip.cpp235
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimebarTip.h84
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineControl.cpp587
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineControl.h158
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineFilter.cpp246
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineFilter.h84
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.cpp75
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.h57
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineRow.cpp170
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineRow.h87
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.cpp67
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.h56
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.cpp713
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.h153
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.cpp360
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.h122
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.cpp86
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.h60
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ToggleControl.cpp171
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ToggleControl.h63
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.cpp205
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.h82
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.cpp83
-rw-r--r--src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.h63
-rw-r--r--src/Authoring/Studio/Palettes/controls/BrowserCombo.qml79
-rw-r--r--src/Authoring/Studio/Palettes/controls/FloatTextField.qml98
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledComboBox.qml155
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledLabel.qml41
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledMenuItem.qml48
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledMenuSeparator.qml45
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledTextField.qml59
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledToolButton.qml54
-rw-r--r--src/Authoring/Studio/Palettes/controls/StyledTooltip.qml44
-rw-r--r--src/Authoring/Studio/PreviewHelper.cpp291
-rw-r--r--src/Authoring/Studio/PreviewHelper.h85
-rw-r--r--src/Authoring/Studio/Render/IStudioRenderer.h88
-rw-r--r--src/Authoring/Studio/Render/PathWidget.cpp512
-rw-r--r--src/Authoring/Studio/Render/PathWidget.h49
-rw-r--r--src/Authoring/Studio/Render/StudioPickValues.h217
-rw-r--r--src/Authoring/Studio/Render/StudioRenderer.cpp883
-rw-r--r--src/Authoring/Studio/Render/StudioRendererImpl.h134
-rw-r--r--src/Authoring/Studio/Render/StudioRendererTranslation.cpp3827
-rw-r--r--src/Authoring/Studio/Render/StudioRendererTranslation.h691
-rw-r--r--src/Authoring/Studio/Render/StudioRotationWidget.cpp437
-rw-r--r--src/Authoring/Studio/Render/StudioScaleWidget.cpp261
-rw-r--r--src/Authoring/Studio/Render/StudioTranslationWidget.cpp172
-rw-r--r--src/Authoring/Studio/Render/StudioWidget.cpp315
-rw-r--r--src/Authoring/Studio/Render/StudioWidget.h140
-rw-r--r--src/Authoring/Studio/Render/StudioWidgetImpl.h346
-rw-r--r--src/Authoring/Studio/Render/WGLRenderContext.cpp213
-rw-r--r--src/Authoring/Studio/Render/WGLRenderContext.h107
-rw-r--r--src/Authoring/Studio/UI/ContextMenu.h150
-rw-r--r--src/Authoring/Studio/UI/CustomReBar.cpp54
-rw-r--r--src/Authoring/Studio/UI/CustomReBar.h56
-rw-r--r--src/Authoring/Studio/UI/PaletteState.cpp160
-rw-r--r--src/Authoring/Studio/UI/PaletteState.h69
-rw-r--r--src/Authoring/Studio/Utils/CmdLineParser.cpp193
-rw-r--r--src/Authoring/Studio/Utils/CmdLineParser.h64
-rw-r--r--src/Authoring/Studio/Utils/ITickTock.h86
-rw-r--r--src/Authoring/Studio/Utils/ImportUtils.cpp90
-rw-r--r--src/Authoring/Studio/Utils/ImportUtils.h72
-rw-r--r--src/Authoring/Studio/Utils/MouseCursor.h91
-rw-r--r--src/Authoring/Studio/Utils/ResourceCache.cpp144
-rw-r--r--src/Authoring/Studio/Utils/ResourceCache.h64
-rw-r--r--src/Authoring/Studio/Utils/StringLoader.cpp151
-rw-r--r--src/Authoring/Studio/Utils/StringLoader.h59
-rw-r--r--src/Authoring/Studio/Utils/StudioUtils.cpp229
-rw-r--r--src/Authoring/Studio/Utils/StudioUtils.h69
-rw-r--r--src/Authoring/Studio/Utils/SystemPreferences.cpp105
-rw-r--r--src/Authoring/Studio/Utils/SystemPreferences.h49
-rw-r--r--src/Authoring/Studio/Utils/TickTock.cpp312
-rw-r--r--src/Authoring/Studio/Workspace/Dialogs.h188
-rw-r--r--src/Authoring/Studio/Workspace/Views/Views.h91
-rw-r--r--src/Authoring/Studio/_Win/Application/AboutDlg.cpp314
-rw-r--r--src/Authoring/Studio/_Win/Application/AboutDlg.h95
-rw-r--r--src/Authoring/Studio/_Win/Application/AboutDlg.ui180
-rw-r--r--src/Authoring/Studio/_Win/Application/BaseLink.cpp252
-rw-r--r--src/Authoring/Studio/_Win/Application/BaseLink.h76
-rw-r--r--src/Authoring/Studio/_Win/Application/MsgRouter.cpp131
-rw-r--r--src/Authoring/Studio/_Win/Application/StudioApp.cpp1835
-rw-r--r--src/Authoring/Studio/_Win/Application/StudioApp.h255
-rw-r--r--src/Authoring/Studio/_Win/Application/StudioColors.h137
-rw-r--r--src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp172
-rw-r--r--src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h82
-rw-r--r--src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui152
-rw-r--r--src/Authoring/Studio/_Win/Application/TextLink.cpp100
-rw-r--r--src/Authoring/Studio/_Win/Application/TextLink.h73
-rw-r--r--src/Authoring/Studio/_Win/Application/WebLink.cpp440
-rw-r--r--src/Authoring/Studio/_Win/Application/WebLink.h100
-rw-r--r--src/Authoring/Studio/_Win/Controls/AppFonts.cpp89
-rw-r--r--src/Authoring/Studio/_Win/Controls/AppFonts.h61
-rw-r--r--src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp214
-rw-r--r--src/Authoring/Studio/_Win/Controls/BufferedRenderer.h60
-rw-r--r--src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp278
-rw-r--r--src/Authoring/Studio/_Win/Controls/MFCEditControl.h85
-rw-r--r--src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp66
-rw-r--r--src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h61
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp144
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformEditControl.h85
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp68
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h66
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp96
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h69
-rw-r--r--src/Authoring/Studio/_Win/Controls/WinRenderer.cpp525
-rw-r--r--src/Authoring/Studio/_Win/Controls/WinRenderer.h130
-rw-r--r--src/Authoring/Studio/_Win/Controls/WndControl.cpp1006
-rw-r--r--src/Authoring/Studio/_Win/Controls/WndControl.h148
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp341
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/DropProxy.h82
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp119
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/WinDnd.h64
-rw-r--r--src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h39
-rw-r--r--src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp902
-rw-r--r--src/Authoring/Studio/_Win/Palettes/PaletteManager.h153
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp127
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h58
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp178
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h80
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp94
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h54
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp92
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h71
-rw-r--r--src/Authoring/Studio/_Win/Studio/stdafx.cpp33
-rw-r--r--src/Authoring/Studio/_Win/Studio/stdafx.h221
-rw-r--r--src/Authoring/Studio/_Win/UI/ContextMenu.cpp292
-rw-r--r--src/Authoring/Studio/_Win/UI/ControlButton.cpp471
-rw-r--r--src/Authoring/Studio/_Win/UI/ControlButton.h119
-rw-r--r--src/Authoring/Studio/_Win/UI/CrashDlg.cpp212
-rw-r--r--src/Authoring/Studio/_Win/UI/CrashDlg.h96
-rw-r--r--src/Authoring/Studio/_Win/UI/EditCameraBar.cpp226
-rw-r--r--src/Authoring/Studio/_Win/UI/EditCameraBar.h99
-rw-r--r--src/Authoring/Studio/_Win/UI/EditorPane.cpp90
-rw-r--r--src/Authoring/Studio/_Win/UI/EditorPane.h65
-rw-r--r--src/Authoring/Studio/_Win/UI/FileDialogEX.cpp451
-rw-r--r--src/Authoring/Studio/_Win/UI/FileDialogEX.h111
-rw-r--r--src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp91
-rw-r--r--src/Authoring/Studio/_Win/UI/GLVersionDlg.h75
-rw-r--r--src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp78
-rw-r--r--src/Authoring/Studio/_Win/UI/InterpolationDlg.h66
-rw-r--r--src/Authoring/Studio/_Win/UI/InterpolationDlg.ui305
-rw-r--r--src/Authoring/Studio/_Win/UI/MemoryDC.cpp258
-rw-r--r--src/Authoring/Studio/_Win/UI/MemoryDC.h91
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuEdit.cpp169
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuEdit.h72
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuItem.cpp58
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuItem.h60
-rw-r--r--src/Authoring/Studio/_Win/UI/NumericEdit.cpp347
-rw-r--r--src/Authoring/Studio/_Win/UI/NumericEdit.h101
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp510
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h106
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerWnd.cpp278
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerWnd.h99
-rw-r--r--src/Authoring/Studio/_Win/UI/PopupWnd.cpp248
-rw-r--r--src/Authoring/Studio/_Win/UI/PopupWnd.h104
-rw-r--r--src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp366
-rw-r--r--src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h92
-rw-r--r--src/Authoring/Studio/_Win/UI/RecentItems.cpp145
-rw-r--r--src/Authoring/Studio/_Win/UI/RecentItems.h88
-rw-r--r--src/Authoring/Studio/_Win/UI/ReportDlg.cpp198
-rw-r--r--src/Authoring/Studio/_Win/UI/ReportDlg.h100
-rw-r--r--src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp66
-rw-r--r--src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h57
-rw-r--r--src/Authoring/Studio/_Win/UI/SceneView.cpp861
-rw-r--r--src/Authoring/Studio/_Win/UI/SceneView.h174
-rw-r--r--src/Authoring/Studio/_Win/UI/StartupDlg.cpp174
-rw-r--r--src/Authoring/Studio/_Win/UI/StartupDlg.h114
-rw-r--r--src/Authoring/Studio/_Win/UI/StartupDlg.ui171
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp590
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h121
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui183
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp260
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPaletteBar.h88
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp155
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h105
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui102
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp385
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h103
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui125
-rw-r--r--src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp524
-rw-r--r--src/Authoring/Studio/_Win/UI/TimeEditDlg.h190
-rw-r--r--src/Authoring/Studio/_Win/UI/timeeditdlg.ui364
-rw-r--r--src/Authoring/Studio/_Win/Utils/MouseCursor.cpp199
-rw-r--r--src/Authoring/Studio/_Win/Utils/WinUtils.cpp600
-rw-r--r--src/Authoring/Studio/_Win/Utils/WinUtils.h65
-rw-r--r--src/Authoring/Studio/_Win/Workspace/Dialogs.cpp1332
-rw-r--r--src/Authoring/Studio/_Win/Workspace/Views.cpp195
-rw-r--r--src/Authoring/Studio/images.qrc179
-rw-r--r--src/Authoring/Studio/images/Action-Action.pngbin0 -> 2927 bytes
-rw-r--r--src/Authoring/Studio/images/Action-ChildAction.pngbin0 -> 2836 bytes
-rw-r--r--src/Authoring/Studio/images/Action-ChildMasterAction.pngbin0 -> 2840 bytes
-rw-r--r--src/Authoring/Studio/images/Action-ComponentAction.pngbin0 -> 2836 bytes
-rw-r--r--src/Authoring/Studio/images/Action-ComponentMasterAction.pngbin0 -> 2844 bytes
-rw-r--r--src/Authoring/Studio/images/Action-MasterAction.pngbin0 -> 2911 bytes
-rw-r--r--src/Authoring/Studio/images/Action-Trash-Disabled.pngbin0 -> 533 bytes
-rw-r--r--src/Authoring/Studio/images/Action-Trash-Disabled@2x.pngbin0 -> 656 bytes
-rw-r--r--src/Authoring/Studio/images/Action-Trash-Normal.pngbin0 -> 534 bytes
-rw-r--r--src/Authoring/Studio/images/Action-Trash-Normal@2x.pngbin0 -> 656 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Alias-Normal.pngbin0 -> 284 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Alias-Normal@2x.pngbin0 -> 545 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Camera-Normal.pngbin0 -> 347 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Camera-Normal@2x.pngbin0 -> 547 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Component-Normal.pngbin0 -> 402 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Component-Normal@2x.pngbin0 -> 797 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Cone-Normal.pngbin0 -> 517 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Cone-Normal@2x.pngbin0 -> 1001 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Cube-Normal.pngbin0 -> 550 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Cube-Normal@2x.pngbin0 -> 885 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Cylinder-Normal.pngbin0 -> 508 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Cylinder-Normal@2x.pngbin0 -> 938 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Group-Normal.pngbin0 -> 606 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Group-Normal@2x.pngbin0 -> 1206 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Layer-Normal.pngbin0 -> 181 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Layer-Normal@2x.pngbin0 -> 280 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Light-Normal.pngbin0 -> 517 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Light-Normal@2x.pngbin0 -> 923 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Rectangle-Normal.pngbin0 -> 248 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Rectangle-Normal@2x.pngbin0 -> 345 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Sphere-Normal.pngbin0 -> 421 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Sphere-Normal@2x.pngbin0 -> 672 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Text-Normal.pngbin0 -> 151 bytes
-rw-r--r--src/Authoring/Studio/images/Asset-Text-Normal@2x.pngbin0 -> 188 bytes
-rw-r--r--src/Authoring/Studio/images/Insert-Left.pngbin0 -> 273 bytes
-rw-r--r--src/Authoring/Studio/images/Insert-Rearrange-Left.pngbin0 -> 196 bytes
-rw-r--r--src/Authoring/Studio/images/Insert-Rearrange-Right.pngbin0 -> 196 bytes
-rw-r--r--src/Authoring/Studio/images/Insert-Right.pngbin0 -> 275 bytes
-rw-r--r--src/Authoring/Studio/images/Inspector-AnimateToggle-Active.pngbin0 -> 641 bytes
-rw-r--r--src/Authoring/Studio/images/Inspector-AnimateToggle-Active@2x.pngbin0 -> 972 bytes
-rw-r--r--src/Authoring/Studio/images/Inspector-AnimateToggle-Normal.pngbin0 -> 637 bytes
-rw-r--r--src/Authoring/Studio/images/Inspector-AnimateToggle-Normal@2x.pngbin0 -> 978 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-Master-Disabled.pngbin0 -> 3009 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-Master-Normal.pngbin0 -> 2924 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-Master-Selected.pngbin0 -> 2985 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterDynamic-Normal.pngbin0 -> 3010 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterDynamic-Selected.pngbin0 -> 2981 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterLeft-Normal.pngbin0 -> 2890 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterLeft-Selected.pngbin0 -> 2939 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterLeft-disabled.pngbin0 -> 2935 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Normal.pngbin0 -> 2957 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Selected.pngbin0 -> 2934 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterRight-Normal.pngbin0 -> 2879 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterRight-Selected.pngbin0 -> 2904 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterRight-disabled.pngbin0 -> 2918 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Normal.pngbin0 -> 2912 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Selected.pngbin0 -> 2904 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-Property-Disabled.pngbin0 -> 2989 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-Property-Normal.pngbin0 -> 2924 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-Property-Selected.pngbin0 -> 2981 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-PropertyDynamic-Normal.pngbin0 -> 2971 bytes
-rw-r--r--src/Authoring/Studio/images/Keyframe-PropertyDynamic-Selected.pngbin0 -> 2973 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Alias-Disabled.pngbin0 -> 555 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Alias-Disabled@2x.pngbin0 -> 621 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Alias-Normal.pngbin0 -> 241 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Alias-Normal@2x.pngbin0 -> 391 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Behavior-Disabled.pngbin0 -> 466 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Behavior-Disabled@2x.pngbin0 -> 507 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Behavior-Normal.pngbin0 -> 152 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Behavior-Normal@2x.pngbin0 -> 179 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Camera-Disabled.pngbin0 -> 542 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Camera-Disabled@2x.pngbin0 -> 653 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Camera-Normal.pngbin0 -> 259 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Camera-Normal@2x.pngbin0 -> 418 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Component-Disabled.pngbin0 -> 583 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Component-Disabled@2x.pngbin0 -> 726 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Component-Normal.pngbin0 -> 266 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Component-Normal@2x.pngbin0 -> 460 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Effect-Disabled.pngbin0 -> 631 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Effect-Disabled@2x.pngbin0 -> 869 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Effect-Normal.pngbin0 -> 381 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Effect-Normal@2x.pngbin0 -> 709 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Folder-Disabled.pngbin0 -> 468 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Folder-Disabled@2x.pngbin0 -> 499 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Folder-Normal.pngbin0 -> 469 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Folder-Normal@2x.pngbin0 -> 498 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Group-Disabled.pngbin0 -> 569 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Group-Disabled@2x.pngbin0 -> 836 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Group-Normal.pngbin0 -> 288 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Group-Normal@2x.pngbin0 -> 595 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Image-Disabled.pngbin0 -> 589 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Image-Disabled@2x.pngbin0 -> 704 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Image-Normal.pngbin0 -> 281 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Image-Normal@2.pngbin0 -> 457 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Layer-Disabled.pngbin0 -> 507 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Layer-Disabled@2x.pngbin0 -> 541 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Layer-Normal.pngbin0 -> 151 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Layer-Normal@2x.pngbin0 -> 203 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Light-Disabled.pngbin0 -> 606 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Light-Disabled@2x.pngbin0 -> 803 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Light-Normal.pngbin0 -> 325 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Light-Normal@2x.pngbin0 -> 640 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Material-Disabled.pngbin0 -> 610 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Material-Disabled@2x.pngbin0 -> 768 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Material-Normal.pngbin0 -> 287 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Material-Normal@2x.pngbin0 -> 511 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Model-Disabled.pngbin0 -> 636 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Model-Disabled@2x.pngbin0 -> 832 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Model-Normal.pngbin0 -> 336 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Model-Normal@2x.pngbin0 -> 545 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Property-Disabled.pngbin0 -> 480 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Property-Disabled@2x.pngbin0 -> 518 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Property-Normal.pngbin0 -> 481 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Property-Normal@2x.pngbin0 -> 515 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Scene-Disabled.pngbin0 -> 489 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Scene-Disabled@2x.pngbin0 -> 533 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Scene-Normal.pngbin0 -> 199 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Scene-Normal@2x.pngbin0 -> 282 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Text-Disabled.pngbin0 -> 470 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Text-Disabled@2x.pngbin0 -> 495 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Text-Normal.pngbin0 -> 151 bytes
-rw-r--r--src/Authoring/Studio/images/Objects-Text-Normal@2x.pngbin0 -> 188 bytes
-rw-r--r--src/Authoring/Studio/images/PlaybackHead.pngbin0 -> 233 bytes
-rw-r--r--src/Authoring/Studio/images/PlaybackHead@2x.pngbin0 -> 318 bytes
-rw-r--r--src/Authoring/Studio/images/Slide-Active.pngbin0 -> 1562 bytes
-rw-r--r--src/Authoring/Studio/images/Slide-Active@2x.pngbin0 -> 2663 bytes
-rw-r--r--src/Authoring/Studio/images/Slide-Master-Active.pngbin0 -> 1471 bytes
-rw-r--r--src/Authoring/Studio/images/Slide-Master-Active@2x.pngbin0 -> 4190 bytes
-rw-r--r--src/Authoring/Studio/images/Slide-Normal.pngbin0 -> 1461 bytes
-rw-r--r--src/Authoring/Studio/images/Slide-Normal@2x.pngbin0 -> 2534 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-Empty.pngbin0 -> 2855 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-HideShow-disabled.pngbin0 -> 238 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-HideShow-disabled@2x.pngbin0 -> 371 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-HideShow.pngbin0 -> 248 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-HideShow@2x.pngbin0 -> 454 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-Lock.pngbin0 -> 224 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-Lock@2x.pngbin0 -> 356 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-Shy.pngbin0 -> 289 bytes
-rw-r--r--src/Authoring/Studio/images/Toggle-Shy@2x.pngbin0 -> 485 bytes
-rw-r--r--src/Authoring/Studio/images/add.pngbin0 -> 454 bytes
-rw-r--r--src/Authoring/Studio/images/add@2x.pngbin0 -> 515 bytes
-rw-r--r--src/Authoring/Studio/images/arrow.pngbin0 -> 523 bytes
-rw-r--r--src/Authoring/Studio/images/arrow@2x.pngbin0 -> 600 bytes
-rw-r--r--src/Authoring/Studio/images/arrow_down.pngbin0 -> 533 bytes
-rw-r--r--src/Authoring/Studio/images/arrow_down@2x.pngbin0 -> 610 bytes
-rw-r--r--src/Authoring/Studio/images/breadcrumb_component_button.pngbin0 -> 3402 bytes
-rw-r--r--src/Authoring/Studio/images/breadcrumb_component_colon_button.pngbin0 -> 262 bytes
-rw-r--r--src/Authoring/Studio/images/breadcrumb_component_grey_button.pngbin0 -> 3374 bytes
-rw-r--r--src/Authoring/Studio/images/breadcrumb_component_scene.pngbin0 -> 3506 bytes
-rw-r--r--src/Authoring/Studio/images/checkbox-checked.pngbin0 -> 3196 bytes
-rw-r--r--src/Authoring/Studio/images/checkbox-unchecked.pngbin0 -> 2946 bytes
-rw-r--r--src/Authoring/Studio/images/empty-pixel.pngbin0 -> 154 bytes
-rw-r--r--src/Authoring/Studio/images/filter-shy-down.pngbin0 -> 289 bytes
-rw-r--r--src/Authoring/Studio/images/filter-shy-down@2x.pngbin0 -> 485 bytes
-rw-r--r--src/Authoring/Studio/images/filter-toggle-eye-down.pngbin0 -> 238 bytes
-rw-r--r--src/Authoring/Studio/images/filter-toggle-eye-down@2x.pngbin0 -> 371 bytes
-rw-r--r--src/Authoring/Studio/images/filter-toggle-eye-up.pngbin0 -> 248 bytes
-rw-r--r--src/Authoring/Studio/images/filter-toggle-eye-up@2x.pngbin0 -> 454 bytes
-rw-r--r--src/Authoring/Studio/images/obsolete_placeholder.pngbin0 -> 158 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-down-depressed.pngbin0 -> 2918 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-down-disabled.pngbin0 -> 2889 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-down-normal.pngbin0 -> 2893 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-left-depressed.pngbin0 -> 2914 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-left-disabled.pngbin0 -> 2886 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-left-normal.pngbin0 -> 2887 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-right-depressed.pngbin0 -> 2916 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-right-disabled.pngbin0 -> 2884 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-right-normal.pngbin0 -> 2885 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-up-depressed.pngbin0 -> 2917 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-up-disabled.pngbin0 -> 2881 bytes
-rw-r--r--src/Authoring/Studio/images/scrollbar-arrows-up-normal.pngbin0 -> 2879 bytes
-rw-r--r--src/Authoring/Studio/images/timebarhandle-disabled-left.pngbin0 -> 276 bytes
-rw-r--r--src/Authoring/Studio/images/timebarhandle-disabled-right.pngbin0 -> 283 bytes
-rw-r--r--src/Authoring/Studio/images/timebarhandle-left.pngbin0 -> 298 bytes
-rw-r--r--src/Authoring/Studio/images/timebarhandle-right.pngbin0 -> 297 bytes
-rw-r--r--src/Authoring/Studio/qt3dstudio.qrc16
-rw-r--r--src/Authoring/Studio/remoteproject.cpp202
-rw-r--r--src/Authoring/Studio/remoteproject.h61
-rw-r--r--src/Authoring/Studio/res/About Icon.bmpbin0 -> 297132 bytes
-rw-r--r--src/Authoring/Studio/res/Flippy-Right.bmpbin0 -> 824 bytes
-rw-r--r--src/Authoring/Studio/res/Flippy-down.bmpbin0 -> 824 bytes
-rw-r--r--src/Authoring/Studio/res/Studio.icobin0 -> 370070 bytes
-rw-r--r--src/Authoring/Studio/res/Studio.manifest22
-rw-r--r--src/Authoring/Studio/res/Studio.pngbin0 -> 16918 bytes
-rw-r--r--src/Authoring/Studio/res/StudioDoc.icobin0 -> 370070 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-00.pngbin0 -> 229 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-01.pngbin0 -> 190 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-02.pngbin0 -> 180 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-03.pngbin0 -> 169 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-04.pngbin0 -> 209 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-05.pngbin0 -> 230 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-06.pngbin0 -> 150 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar-07.pngbin0 -> 155 bytes
-rw-r--r--src/Authoring/Studio/res/Toolbar.bmpbin0 -> 1078 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/button_back.pngbin0 -> 807 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/button_back@2x.pngbin0 -> 1510 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/button_next.pngbin0 -> 782 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/button_next@2x.pngbin0 -> 1499 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/1.pngbin0 -> 79204 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/2.pngbin0 -> 128317 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/3.pngbin0 -> 113936 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/4.pngbin0 -> 108052 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/5.pngbin0 -> 100198 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/6.pngbin0 -> 98135 bytes
-rw-r--r--src/Authoring/Studio/res/Tutorial/screens/7.pngbin0 -> 99190 bytes
-rw-r--r--src/Authoring/Studio/res/arrow_down.pngbin0 -> 213 bytes
-rw-r--r--src/Authoring/Studio/res/arrow_down@2x.pngbin0 -> 273 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_grayed_out.bmpbin0 -> 5432 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-00.pngbin0 -> 302 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-00@2x.pngbin0 -> 465 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-01.pngbin0 -> 231 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-01@2x.pngbin0 -> 324 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-02.pngbin0 -> 311 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-02@2x.pngbin0 -> 554 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-03.pngbin0 -> 149 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-03@2x.pngbin0 -> 190 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-04.pngbin0 -> 349 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-04@2x.pngbin0 -> 848 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-05.pngbin0 -> 359 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-05@2x.pngbin0 -> 671 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-06.pngbin0 -> 162 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color-06@2x.pngbin0 -> 230 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_hi_color.bmpbin0 -> 5432 bytes
-rw-r--r--src/Authoring/Studio/res/client_tools_low_color.bmpbin0 -> 1014 bytes
-rw-r--r--src/Authoring/Studio/res/cursors.bmpbin0 -> 3190 bytes
-rw-r--r--src/Authoring/Studio/res/edit_camera_pan.pngbin0 -> 556 bytes
-rw-r--r--src/Authoring/Studio/res/edit_camera_rot.pngbin0 -> 567 bytes
-rw-r--r--src/Authoring/Studio/res/edit_camera_zoom.pngbin0 -> 567 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_disabled.bmpbin0 -> 4664 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-00.pngbin0 -> 324 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-00@2x.pngbin0 -> 623 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-00_disabled.pngbin0 -> 339 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-00_disabled@2x.pngbin0 -> 487 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-01.pngbin0 -> 395 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-01@2x.pngbin0 -> 730 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-01_disabled.pngbin0 -> 298 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-01_disabled@2x.pngbin0 -> 468 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-02.pngbin0 -> 670 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-02@2x.pngbin0 -> 972 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-02_disabled.pngbin0 -> 672 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-02_disabled@2x.pngbin0 -> 979 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-03.pngbin0 -> 494 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-03@2x.pngbin0 -> 966 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-03_disabled.pngbin0 -> 361 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-03_disabled@2x.pngbin0 -> 624 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-04.pngbin0 -> 341 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-04@2x.pngbin0 -> 774 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-04_disabled.pngbin0 -> 353 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-04_disabled@2x.pngbin0 -> 605 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-05.pngbin0 -> 328 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-05@2x.pngbin0 -> 720 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-05_disabled.pngbin0 -> 367 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi-05_disabled@2x.pngbin0 -> 582 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_hi.bmpbin0 -> 4664 bytes
-rw-r--r--src/Authoring/Studio/res/editcamera_tools_low.bmpbin0 -> 2614 bytes
-rw-r--r--src/Authoring/Studio/res/group_move.pngbin0 -> 560 bytes
-rw-r--r--src/Authoring/Studio/res/group_rotate.pngbin0 -> 570 bytes
-rw-r--r--src/Authoring/Studio/res/group_scale.pngbin0 -> 540 bytes
-rw-r--r--src/Authoring/Studio/res/item_move.pngbin0 -> 562 bytes
-rw-r--r--src/Authoring/Studio/res/item_rotate.pngbin0 -> 573 bytes
-rw-r--r--src/Authoring/Studio/res/item_scale.pngbin0 -> 536 bytes
-rw-r--r--src/Authoring/Studio/res/keyframe.bmpbin0 -> 978 bytes
-rw-r--r--src/Authoring/Studio/res/library_buttons_hi_color.bmpbin0 -> 10040 bytes
-rw-r--r--src/Authoring/Studio/res/library_buttons_low_color.bmpbin0 -> 1294 bytes
-rw-r--r--src/Authoring/Studio/res/libtoolb.bmpbin0 -> 1590 bytes
-rw-r--r--src/Authoring/Studio/res/menubtn_down.bmpbin0 -> 230 bytes
-rw-r--r--src/Authoring/Studio/res/menubtn_normal.bmpbin0 -> 180 bytes
-rw-r--r--src/Authoring/Studio/res/menubtn_selected.bmpbin0 -> 180 bytes
-rw-r--r--src/Authoring/Studio/res/menuedit.bmpbin0 -> 3894 bytes
-rw-r--r--src/Authoring/Studio/res/menutool.bmpbin0 -> 20790 bytes
-rw-r--r--src/Authoring/Studio/res/open_dialog.pngbin0 -> 42144 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_grayed.bmpbin0 -> 3128 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_hi.bmpbin0 -> 3128 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-00.pngbin0 -> 547 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-00@2x.pngbin0 -> 651 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-01.pngbin0 -> 437 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-01@2x.pngbin0 -> 457 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-02.pngbin0 -> 519 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-02@2x.pngbin0 -> 567 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-03.pngbin0 -> 578 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low-03@2x.pngbin0 -> 693 bytes
-rw-r--r--src/Authoring/Studio/res/playback_tools_low.bmpbin0 -> 630 bytes
-rw-r--r--src/Authoring/Studio/res/prefstab-00.pngbin0 -> 519 bytes
-rw-r--r--src/Authoring/Studio/res/prefstab-00@2x.pngbin0 -> 1037 bytes
-rw-r--r--src/Authoring/Studio/res/prefstab-01.pngbin0 -> 597 bytes
-rw-r--r--src/Authoring/Studio/res/prefstab-01@2x.pngbin0 -> 832 bytes
-rw-r--r--src/Authoring/Studio/res/prefstab.bmpbin0 -> 2102 bytes
-rw-r--r--src/Authoring/Studio/res/preview_tools.bmpbin0 -> 246 bytes
-rw-r--r--src/Authoring/Studio/res/project-icon-new.bmpbin0 -> 3128 bytes
-rw-r--r--src/Authoring/Studio/res/project-icon-open.bmpbin0 -> 3128 bytes
-rw-r--r--src/Authoring/Studio/res/qt3ds_header.bmpbin0 -> 192080 bytes
-rw-r--r--src/Authoring/Studio/res/separator.pngbin0 -> 522 bytes
-rw-r--r--src/Authoring/Studio/res/separator@2x.pngbin0 -> 526 bytes
-rw-r--r--src/Authoring/Studio/res/stmtool.bmpbin0 -> 3894 bytes
-rw-r--r--src/Authoring/Studio/res/storagep.bmpbin0 -> 1494 bytes
-rw-r--r--src/Authoring/Studio/res/tmchmenu.bmpbin0 -> 5094 bytes
-rw-r--r--src/Authoring/Studio/res/tmlntool.bmpbin0 -> 3126 bytes
-rw-r--r--src/Authoring/Studio/res/tmtbmenu.bmpbin0 -> 5094 bytes
-rw-r--r--src/Authoring/Studio/res/weblinkc.bmpbin0 -> 1494 bytes
-rw-r--r--src/Authoring/Studio/res/winxp1.bin22
-rw-r--r--src/Authoring/Studio/style.qss219
-rw-r--r--src/Authoring/Studio/version.h35
-rw-r--r--src/Authoring/UICDM.pri33
-rw-r--r--src/Authoring/UICDM.pro28
-rw-r--r--src/Authoring/UICDM/EASTL_new.cpp40
-rw-r--r--src/Authoring/UICDM/Systems/ActionSystem.cpp131
-rw-r--r--src/Authoring/UICDM/Systems/ActionSystem.h84
-rw-r--r--src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.cpp289
-rw-r--r--src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.h125
-rw-r--r--src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.cpp488
-rw-r--r--src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.h148
-rw-r--r--src/Authoring/UICDM/Systems/Cores/DataCoreProducer.cpp457
-rw-r--r--src/Authoring/UICDM/Systems/Cores/DataCoreProducer.h175
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleActionCore.cpp240
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleActionCore.h165
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.cpp618
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.h218
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleDataCore.cpp574
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleDataCore.h373
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.cpp408
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.h395
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.cpp169
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.h134
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.cpp555
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.h187
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.cpp245
-rw-r--r--src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.h98
-rw-r--r--src/Authoring/UICDM/Systems/HandleSystemBase.h169
-rw-r--r--src/Authoring/UICDM/Systems/HandleSystemTransactions.h88
-rw-r--r--src/Authoring/UICDM/Systems/SignalsImpl.cpp1527
-rw-r--r--src/Authoring/UICDM/Systems/SignalsImpl.h50
-rw-r--r--src/Authoring/UICDM/Systems/SlideSystem.cpp854
-rw-r--r--src/Authoring/UICDM/Systems/SlideSystem.h178
-rw-r--r--src/Authoring/UICDM/Systems/StandardExtensions.h196
-rw-r--r--src/Authoring/UICDM/Systems/StudioAnimationSystem.cpp601
-rw-r--r--src/Authoring/UICDM/Systems/StudioAnimationSystem.h131
-rw-r--r--src/Authoring/UICDM/Systems/StudioCoreSystem.cpp410
-rw-r--r--src/Authoring/UICDM/Systems/StudioCoreSystem.h94
-rw-r--r--src/Authoring/UICDM/Systems/StudioFullSystem.cpp647
-rw-r--r--src/Authoring/UICDM/Systems/StudioFullSystem.h164
-rw-r--r--src/Authoring/UICDM/Systems/StudioPropertySystem.cpp213
-rw-r--r--src/Authoring/UICDM/Systems/StudioPropertySystem.h129
-rw-r--r--src/Authoring/UICDM/Systems/UICDMActionCore.h99
-rw-r--r--src/Authoring/UICDM/Systems/UICDMActionInfo.h96
-rw-r--r--src/Authoring/UICDM/Systems/UICDMActionSystem.h68
-rw-r--r--src/Authoring/UICDM/Systems/UICDMAnimation.h828
-rw-r--r--src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.cpp561
-rw-r--r--src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.h922
-rw-r--r--src/Authoring/UICDM/Systems/UICDMDataCore.h316
-rw-r--r--src/Authoring/UICDM/Systems/UICDMDataTypes.h840
-rw-r--r--src/Authoring/UICDM/Systems/UICDMErrors.h308
-rw-r--r--src/Authoring/UICDM/Systems/UICDMGuides.cpp230
-rw-r--r--src/Authoring/UICDM/Systems/UICDMGuides.h102
-rw-r--r--src/Authoring/UICDM/Systems/UICDMHandles.cpp33
-rw-r--r--src/Authoring/UICDM/Systems/UICDMHandles.h459
-rw-r--r--src/Authoring/UICDM/Systems/UICDMMetaData.cpp4094
-rw-r--r--src/Authoring/UICDM/Systems/UICDMMetaData.h405
-rw-r--r--src/Authoring/UICDM/Systems/UICDMMetaDataTypes.h351
-rw-r--r--src/Authoring/UICDM/Systems/UICDMMetaDataValue.h251
-rw-r--r--src/Authoring/UICDM/Systems/UICDMPropertyDefinition.h75
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSignalStructImpl.h305
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSignalStructs.h89
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSignalSystem.cpp184
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSignalSystem.h52
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSignals.h597
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSlideCore.h232
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSlideGraphCore.h89
-rw-r--r--src/Authoring/UICDM/Systems/UICDMSlides.h201
-rw-r--r--src/Authoring/UICDM/Systems/UICDMStringTable.cpp85
-rw-r--r--src/Authoring/UICDM/Systems/UICDMStringTable.h70
-rw-r--r--src/Authoring/UICDM/Systems/UICDMTestOps.h61
-rw-r--r--src/Authoring/UICDM/Systems/UICDMTransactions.h253
-rw-r--r--src/Authoring/UICDM/Systems/UICDMValue.cpp167
-rw-r--r--src/Authoring/UICDM/Systems/UICDMValue.h326
-rw-r--r--src/Authoring/UICDM/Systems/UICDMWStrOps.h40
-rw-r--r--src/Authoring/UICDM/Systems/UICDMWStrOpsImpl.h745
-rw-r--r--src/Authoring/UICDM/Systems/UICDMWindowsCompatibility.h182
-rw-r--r--src/Authoring/UICDM/Systems/UICDMXML.cpp1317
-rw-r--r--src/Authoring/UICDM/Systems/UICDMXML.h506
-rw-r--r--src/Authoring/UICDM/Systems/VectorTransactions.h237
-rw-r--r--src/Authoring/UICDM/UICDMPrefix.cpp37
-rw-r--r--src/Authoring/UICDM/UICDMPrefix.h86
-rw-r--r--src/Authoring/UICIMP/ReadMe.txt30
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICFileToolsSeekableMeshBufIOStream.h58
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImport.cpp1942
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImport.h421
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.cpp189
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.h190
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportContainers.h88
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportErrorCodes.h67
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportImpl.h158
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.cpp37
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.h70
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportMesh.cpp831
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportMesh.h529
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportMeshBuilder.cpp599
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportMeshStudioOnly.cpp114
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportPath.cpp152
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportPath.h87
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.cpp263
-rw-r--r--src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.h254
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaAnimationUtils.h173
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaDOMUtils.h367
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaSGTranslation.cpp1634
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaTransformUtils.h69
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxDomUtils.h165
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxSGTranslation.cpp2412
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.cpp1155
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.h393
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslation.h146
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslationCommon.h57
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/stdafx.cpp36
-rw-r--r--src/Authoring/UICIMP/UICImportSGTranslation/stdafx.h67
-rw-r--r--src/Authoring/UICIMP/UICImportStudioLib/stdafx.cpp36
-rw-r--r--src/Authoring/UICIMP/UICImportStudioLib/stdafx.h45
-rw-r--r--src/Authoring/commoninclude.pri49
-rw-r--r--src/Authoring/configure.json60
-rw-r--r--src/Authoring/configure.pri53
-rw-r--r--src/Authoring/licensehandler.pro16
-rw-r--r--src/Authoring/mfcconsole.cpp66
-rw-r--r--src/Authoring/qml.qrc42
-rw-r--r--src/QtExtras/QtExtras.pro2
-rw-r--r--src/QtExtras/qmlstreamer/q3dsincubationcontroller.h55
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstream.cpp68
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstream.h68
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamer_global.h41
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.cpp67
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.h52
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.cpp53
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.h61
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.cpp206
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.h77
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.cpp447
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.h124
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlstreamservice.h79
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.cpp53
-rw-r--r--src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.h55
-rw-r--r--src/QtExtras/qmlstreamer/qmlstreamer.pro47
-rw-r--r--src/Runtime/AttributeHashes.pri1
-rw-r--r--src/Runtime/AttributeHashes.pro15
-rw-r--r--src/Runtime/Qt3DSRuntime.pro69
-rw-r--r--src/Runtime/Qt3DSRuntimeStatic.pro694
-rw-r--r--src/Runtime/Runtime.pro10
-rw-r--r--src/Runtime/SDKsAndTools/AttributeHashes/AttributeHashes.cpp361
-rw-r--r--src/Runtime/Source/Engine/Include/EnginePrefix.h144
-rw-r--r--src/Runtime/Source/Engine/Include/NVImageScaler.h311
-rw-r--r--src/Runtime/Source/Engine/Include/OpenKodeInclude.h49
-rw-r--r--src/Runtime/Source/Engine/Include/UICEGLInfo.h45
-rw-r--r--src/Runtime/Source/Engine/Include/UICEGLWindowSystem.h81
-rw-r--r--src/Runtime/Source/Engine/Include/UICPluginDLL.h139
-rw-r--r--src/Runtime/Source/Engine/Include/UICRenderRuntimeBinding.h82
-rw-r--r--src/Runtime/Source/Engine/Include/UICRenderRuntimeBindingImpl.h210
-rw-r--r--src/Runtime/Source/Engine/Include/UICTegraApplication.h325
-rw-r--r--src/Runtime/Source/Engine/Include/UICTegraInputEngine.h79
-rw-r--r--src/Runtime/Source/Engine/Include/UICWindowSystem.h65
-rw-r--r--src/Runtime/Source/Engine/Source/EnginePrefix.cpp31
-rw-r--r--src/Runtime/Source/Engine/Source/UICOSSpecificFunctions.cpp156
-rw-r--r--src/Runtime/Source/Engine/Source/UICRenderRuntimeBinding.cpp1997
-rw-r--r--src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplRenderer.cpp291
-rw-r--r--src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplTranslation.cpp1792
-rw-r--r--src/Runtime/Source/Engine/Source/UICTegraApplication.cpp754
-rw-r--r--src/Runtime/Source/Engine/Source/UICTegraInputEngine.cpp128
-rw-r--r--src/Runtime/Source/HDR/Include/CUDABSDFMipmap.h78
-rw-r--r--src/Runtime/Source/HDR/Include/GLComputeMipMap.h75
-rw-r--r--src/Runtime/Source/HDR/Include/HDR.h239
-rw-r--r--src/Runtime/Source/HDR/Include/MipmapBSDF.h105
-rw-r--r--src/Runtime/Source/HDR/Source/CUDABSDFMipmap.cpp145
-rw-r--r--src/Runtime/Source/HDR/Source/GLComputeMipmap.cpp394
-rw-r--r--src/Runtime/Source/HDR/Source/HDR.cpp30
-rw-r--r--src/Runtime/Source/HDR/Source/MipmapBSDF.cpp265
-rw-r--r--src/Runtime/Source/HDR/Source/MipmapBSDF.cu404
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/Android.mk164
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_color.h107
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_debug.h86
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.cpp890
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.h553
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.cpp290
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.h92
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_keycode_mapping.h151
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/scoped_profiler.h94
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_global.h36
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/NvVec.h316
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/misc.h130
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.cpp64
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.h45
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.cpp1030
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.h117
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.cpp198
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.h63
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.cpp195
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.h52
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.c161
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.h104
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.cpp142
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.h43
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_types.h81
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.cpp103
-rw-r--r--src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.h93
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_color.h107
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_debug.h86
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_global.h36
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/NvVec.h316
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/misc.h130
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.cpp64
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.h45
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.cpp1030
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.h118
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.cpp203
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.h64
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_types.h81
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.abcbin0 -> 2048 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.ddsbin0 -> 87509 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.abcbin0 -> 2048 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.ddsbin0 -> 349653 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/assets/font.frag39
-rw-r--r--src/Runtime/Source/PlatformSpecific/Linux/assets/font.vert49
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_color.h107
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_debug.h86
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_global.h36
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/NvVec.h316
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/misc.h130
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.cpp64
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.h45
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.cpp1030
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.h117
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.cpp199
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.h63
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_types.h81
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.abcbin0 -> 2048 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.ddsbin0 -> 87509 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.abcbin0 -> 2048 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.ddsbin0 -> 349653 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/assets/font.frag39
-rw-r--r--src/Runtime/Source/PlatformSpecific/Macos/assets/font.vert49
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_color.h107
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_config/nv_config.h278
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_debug.h86
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_global.h36
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/NvVec.h316
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/misc.h130
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.cpp64
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.h45
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.cpp1030
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.h117
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.cpp199
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.h63
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_types.h81
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/qt3ds_launcher_defs.h92
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/UICViewer/Resource.h43
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.abcbin0 -> 2048 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.ddsbin0 -> 87509 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.abcbin0 -> 2048 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.ddsbin0 -> 349653 bytes
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/assets/font.frag39
-rw-r--r--src/Runtime/Source/PlatformSpecific/Windows/assets/font.vert49
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/AutoDeallocatorAllocator.h99
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/ConvertUTF.h173
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/FastAllocator.h115
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/FileTools.h126
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/IOStreams.h278
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/LICENSE_CONVERTUTF.TXT19
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/PoolingAllocator.h177
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/PreAllocatedAllocator.h88
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DS.h59
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocator.h195
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocatorCallback.h100
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAssert.h128
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAtomic.h63
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBasicTemplates.h113
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBounds3.h443
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBroadcastingAllocator.h113
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSContainers.h129
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDataRef.h162
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDiscriminatedUnion.h335
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFPU.h97
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFastIPC.h57
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFlags.h360
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFoundation.h115
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIPC.h99
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIndexableLinkedList.h309
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIntrinsics.h50
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveLinkedList.h361
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveSet.h104
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSLogging.h57
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat33.h385
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat44.h497
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMath.h323
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMathUtils.h569
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMemoryBuffer.h160
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMutex.h372
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSNoCopy.h50
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSOption.h104
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPerfTimer.h107
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPlane.h134
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPool.h159
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPreprocessor.h359
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSQuat.h381
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSRefCounted.h199
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSemaphore.h67
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSimpleTypes.h117
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSStringTokenizer.h108
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSync.h70
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSystem.h58
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSThread.h205
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTime.h97
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTransform.h195
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUnionCast.h64
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUtilities.h189
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec2.h321
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec3.h377
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec4.h373
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVersionNumber.h67
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/SerializationTypes.h132
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Socket.h79
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/StrConvertUTF.h213
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversion.h226
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversionImpl.h213
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringTable.h291
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/TaggedPointer.h80
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/ThreadSafeQueue.h111
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/TrackingAllocator.h262
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/Utils.h382
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/XML.h680
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/LICENSE.TXT7
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxAoS.h157
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxFile.h48
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxInlineAoS.h2666
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxIntrinsics.h209
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxString.h202
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxTrigConstants.h96
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/qt_attribution.json10
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/qt_attribution.json10
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/LICENSE.TXT7
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsAoS.h126
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsFile.h48
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInclude.h93
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInlineAoS.h2715
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsIntrinsics.h222
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsString.h147
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsTrigConstants.h93
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/qt_attribution.json10
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/ConvertUTF.cpp657
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/EASTL_new.cpp76
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/FileTools.cpp553
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/IOStreams.cpp384
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/LICENCE_SOCKET.TXT20
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSFoundation.cpp237
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSLogging.cpp44
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSMathUtils.cpp181
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSPerfTimer.cpp163
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSSystem.cpp139
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/Socket.cpp472
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/StringTable.cpp670
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/XML.cpp1008
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxAtomic.cpp129
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxFPU.cpp52
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxMutex.cpp120
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSemaphore.cpp146
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSync.cpp137
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxThread.cpp384
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxTime.cpp111
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/SocketImpl.h424
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixAtomic.cpp89
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixFPU.cpp61
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixMutex.cpp120
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSemaphore.cpp146
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSync.cpp137
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixTime.cpp108
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/qt_attribution.json11
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsAtomic.cpp93
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsFPU.cpp61
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsMutex.cpp149
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSemaphore.cpp72
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSync.cpp74
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsThread.cpp236
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsTime.cpp92
-rw-r--r--src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/SocketImpl.h506
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderClearColorExample.cpp63
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.cpp491
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.h123
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.cpp188
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.h89
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderRenderToTextureExample.cpp178
-rw-r--r--src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderSpinningCubeExample.cpp104
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAtomicCounterBuffer.h182
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAttribLayout.h90
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderBaseTypes.h2050
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderComputeShader.h89
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderConstantBuffer.h248
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h1045
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDataBuffer.h188
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDepthStencilState.h134
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawIndirectBuffer.h152
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawable.h54
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFragmentShader.h89
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFrameBuffer.h277
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderGeometryShader.h89
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderImageTexture.h143
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderIndexBuffer.h138
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderInputAssembler.h157
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderOcclusionQuery.h120
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontSpecification.h165
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontText.h139
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathRender.h114
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathSpecification.h141
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderProgramPipeline.h138
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderQueryBase.h127
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRasterizerState.h94
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRenderBuffer.h158
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSampler.h124
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShader.h123
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h400
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h480
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderStorageBuffer.h158
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSync.h132
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTessellationShader.h132
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2D.h165
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2DArray.h106
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureBase.h177
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureCube.h106
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTimerQuery.h129
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexBuffer.h124
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexShader.h89
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h2239
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h360
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h48
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLTokens.h398
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h1932
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h171
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL4.h205
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h522
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h146
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h173
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h105
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h46
-rw-r--r--src/Runtime/Source/Qt3DSRender/Include/render/glg/Qt3DSGLImplObjects.h83
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAtomicCounterBuffer.cpp156
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAttribLayout.cpp57
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderComputeShader.cpp55
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp421
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderContext.cpp1105
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDataBuffer.cpp158
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDepthStencilState.cpp91
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDrawIndirectBuffer.cpp104
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFragmentShader.cpp55
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFrameBuffer.cpp300
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderGeometryShader.cpp55
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderImageTexture.cpp103
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderIndexBuffer.cpp100
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderInputAssembler.cpp105
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderOcclusionQuery.cpp82
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontSpecification.cpp145
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontText.cpp191
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathRender.cpp108
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathSpecification.cpp103
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderProgramPipeline.cpp134
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderQueryBase.cpp54
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRasterizerState.cpp71
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRenderBuffer.cpp114
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSampler.cpp84
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderShaderProgram.cpp1168
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderStorageBuffer.cpp120
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSync.cpp87
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTessellationShader.cpp74
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2D.cpp264
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2DArray.cpp123
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureBase.cpp167
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureCube.cpp119
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTimerQuery.cpp75
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexBuffer.cpp74
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexShader.cpp54
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp158
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp771
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp827
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp2160
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp78
-rw-r--r--src/Runtime/Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp588
-rw-r--r--src/Runtime/Source/Qt3DSState/Include/Qt3DSStateConfig.h43
-rw-r--r--src/Runtime/Source/Qt3DSState/Include/Qt3DSStateEngine.h103
-rw-r--r--src/Runtime/Source/Qt3DSState/Include/Qt3DSStateInputStreamFactory.h71
-rw-r--r--src/Runtime/Source/Qt3DSState/Include/Qt3DSStateScriptBridge.h124
-rw-r--r--src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateApplication.h48
-rw-r--r--src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateContext.h98
-rw-r--r--src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateFactory.h96
-rw-r--r--src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateLuaEngine.h91
-rw-r--r--src/Runtime/Source/Qt3DSState/Source/Qt3DSStateEngine.cpp1135
-rw-r--r--src/Runtime/Source/Qt3DSState/Source/Qt3DSStateFactory.cpp231
-rw-r--r--src/Runtime/Source/Qt3DSState/Source/Qt3DSStateInputStreamFactory.cpp231
-rw-r--r--src/Runtime/Source/Qt3DSState/Source/Qt3DSStateLuaEngine.cpp1573
-rw-r--r--src/Runtime/Source/Runtime/Include/RuntimePrefix.h105
-rw-r--r--src/Runtime/Source/Runtime/Include/UICActivationManager.h157
-rw-r--r--src/Runtime/Source/Runtime/Include/UICAnimationSystem.h72
-rw-r--r--src/Runtime/Source/Runtime/Include/UICApplication.h200
-rw-r--r--src/Runtime/Source/Runtime/Include/UICApplicationValues.h369
-rw-r--r--src/Runtime/Source/Runtime/Include/UICAttributeHashes.h262
-rw-r--r--src/Runtime/Source/Runtime/Include/UICAttributeHashes.txt226
-rw-r--r--src/Runtime/Source/Runtime/Include/UICBinarySerializationHelper.h71
-rw-r--r--src/Runtime/Source/Runtime/Include/UICBinarySerializer.h79
-rw-r--r--src/Runtime/Source/Runtime/Include/UICBinarySerializerImpl.h83
-rw-r--r--src/Runtime/Source/Runtime/Include/UICCommandEventTypes.h83
-rw-r--r--src/Runtime/Source/Runtime/Include/UICComponentManager.h143
-rw-r--r--src/Runtime/Source/Runtime/Include/UICElementSystem.h623
-rw-r--r--src/Runtime/Source/Runtime/Include/UICEvent.h62
-rw-r--r--src/Runtime/Source/Runtime/Include/UICEventCallbacks.h135
-rw-r--r--src/Runtime/Source/Runtime/Include/UICFrameworkTypes.h52
-rw-r--r--src/Runtime/Source/Runtime/Include/UICIComponentManager.h147
-rw-r--r--src/Runtime/Source/Runtime/Include/UICIInputSystem.h62
-rw-r--r--src/Runtime/Source/Runtime/Include/UICIScene.h177
-rw-r--r--src/Runtime/Source/Runtime/Include/UICIScriptBridge.h200
-rw-r--r--src/Runtime/Source/Runtime/Include/UICIStateful.h69
-rw-r--r--src/Runtime/Source/Runtime/Include/UICIText.h52
-rw-r--r--src/Runtime/Source/Runtime/Include/UICInputDefs.h413
-rw-r--r--src/Runtime/Source/Runtime/Include/UICInputEngine.h125
-rw-r--r--src/Runtime/Source/Runtime/Include/UICInputEventTypes.h96
-rw-r--r--src/Runtime/Source/Runtime/Include/UICInputFrame.h118
-rw-r--r--src/Runtime/Source/Runtime/Include/UICKernelTypes.h220
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLogicSystem.h60
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaAxis.h52
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaButton.h52
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaColor.h84
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaCommandHelper.h87
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaElementHelper.h83
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaEngine.h139
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaEventHelper.h89
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaHelper.h78
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaIncludes.h40
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaKeyboard.h53
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaMatrix.h96
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaRotation.h91
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaSceneHelper.h68
-rw-r--r--src/Runtime/Source/Runtime/Include/UICLuaVector.h110
-rw-r--r--src/Runtime/Source/Runtime/Include/UICOutputMemoryStream.h123
-rw-r--r--src/Runtime/Source/Runtime/Include/UICParametersSystem.h69
-rw-r--r--src/Runtime/Source/Runtime/Include/UICPickFrame.h70
-rw-r--r--src/Runtime/Source/Runtime/Include/UICPresentation.h228
-rw-r--r--src/Runtime/Source/Runtime/Include/UICPresentationFrameData.h87
-rw-r--r--src/Runtime/Source/Runtime/Include/UICQmlElementHelper.h65
-rw-r--r--src/Runtime/Source/Runtime/Include/UICQmlEngine.h223
-rw-r--r--src/Runtime/Source/Runtime/Include/UICRuntimeFactory.h137
-rw-r--r--src/Runtime/Source/Runtime/Include/UICSceneManager.h165
-rw-r--r--src/Runtime/Source/Runtime/Include/UICSlideSystem.h156
-rw-r--r--src/Runtime/Source/Runtime/Include/UICTimePolicy.h124
-rw-r--r--src/Runtime/Source/Runtime/Include/q3dsqmlscript.h102
-rw-r--r--src/Runtime/Source/Runtime/Source/RuntimePrefix.cpp31
-rw-r--r--src/Runtime/Source/Runtime/Source/UICActivationManager.cpp1027
-rw-r--r--src/Runtime/Source/Runtime/Source/UICAnimationSystem.cpp477
-rw-r--r--src/Runtime/Source/Runtime/Source/UICApplication.cpp2499
-rw-r--r--src/Runtime/Source/Runtime/Source/UICAttributeHashes.cpp480
-rw-r--r--src/Runtime/Source/Runtime/Source/UICBinarySerializerImpl.cpp334
-rw-r--r--src/Runtime/Source/Runtime/Source/UICComponentManager.cpp480
-rw-r--r--src/Runtime/Source/Runtime/Source/UICElementSystem.cpp997
-rw-r--r--src/Runtime/Source/Runtime/Source/UICEventCallbacks.cpp258
-rw-r--r--src/Runtime/Source/Runtime/Source/UICInputEngine.cpp849
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLogicSystem.cpp293
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaAxis.cpp64
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaButton.cpp65
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaColor.cpp311
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaCommandHelper.cpp278
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaElementHelper.cpp511
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaEngine.cpp3217
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaEventHelper.cpp815
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaHelper.cpp164
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaKeyboard.cpp218
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaMatrix.cpp628
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaRotation.cpp429
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaSceneHelper.cpp273
-rw-r--r--src/Runtime/Source/Runtime/Source/UICLuaVector.cpp644
-rw-r--r--src/Runtime/Source/Runtime/Source/UICOutputMemoryStream.cpp150
-rw-r--r--src/Runtime/Source/Runtime/Source/UICParametersSystem.cpp202
-rw-r--r--src/Runtime/Source/Runtime/Source/UICPresentation.cpp796
-rw-r--r--src/Runtime/Source/Runtime/Source/UICPresentationFrameData.cpp105
-rw-r--r--src/Runtime/Source/Runtime/Source/UICQmlElementHelper.cpp310
-rw-r--r--src/Runtime/Source/Runtime/Source/UICQmlEngine.cpp851
-rw-r--r--src/Runtime/Source/Runtime/Source/UICSlideSystem.cpp628
-rw-r--r--src/Runtime/Source/Runtime/Source/UICTimePolicy.cpp407
-rw-r--r--src/Runtime/Source/Runtime/Source/q3dsqmlscript.cpp384
-rw-r--r--src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerCustomMaterialParser.h80
-rw-r--r--src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerLuaParser.h248
-rw-r--r--src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerRenderPluginParser.h80
-rw-r--r--src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerScriptParser.h137
-rw-r--r--src/Runtime/Source/RuntimeUICDM/Include/UICMetadata.h390
-rw-r--r--src/Runtime/Source/RuntimeUICDM/Source/UICMetadata.cpp1047
-rw-r--r--src/Runtime/Source/System/Include/SystemPrefix.h92
-rw-r--r--src/Runtime/Source/System/Include/UICArray.h135
-rw-r--r--src/Runtime/Source/System/Include/UICArray.inl287
-rw-r--r--src/Runtime/Source/System/Include/UICAssert.h78
-rw-r--r--src/Runtime/Source/System/Include/UICAudioPlayer.h42
-rw-r--r--src/Runtime/Source/System/Include/UICBasicPluginDLL.h67
-rw-r--r--src/Runtime/Source/System/Include/UICBezierEval.h185
-rw-r--r--src/Runtime/Source/System/Include/UICBoundingBox.h85
-rw-r--r--src/Runtime/Source/System/Include/UICCircularArray.h102
-rw-r--r--src/Runtime/Source/System/Include/UICCircularArray.inl225
-rw-r--r--src/Runtime/Source/System/Include/UICColor.h85
-rw-r--r--src/Runtime/Source/System/Include/UICConfig.h49
-rw-r--r--src/Runtime/Source/System/Include/UICCubicRoots.h80
-rw-r--r--src/Runtime/Source/System/Include/UICCubicRootsImpl.h180
-rw-r--r--src/Runtime/Source/System/Include/UICDLLManager.h96
-rw-r--r--src/Runtime/Source/System/Include/UICDataLogger.h238
-rw-r--r--src/Runtime/Source/System/Include/UICDataLogger.hpp96
-rw-r--r--src/Runtime/Source/System/Include/UICDataLoggerEnums.h167
-rw-r--r--src/Runtime/Source/System/Include/UICDataLoggerViewer.h71
-rw-r--r--src/Runtime/Source/System/Include/UICEGLTimer.h70
-rw-r--r--src/Runtime/Source/System/Include/UICEndian.h38
-rw-r--r--src/Runtime/Source/System/Include/UICEulerAngles.h142
-rw-r--r--src/Runtime/Source/System/Include/UICFNDTimer.h44
-rw-r--r--src/Runtime/Source/System/Include/UICFile.h94
-rw-r--r--src/Runtime/Source/System/Include/UICFileStream.h93
-rw-r--r--src/Runtime/Source/System/Include/UICFixedArray.h89
-rw-r--r--src/Runtime/Source/System/Include/UICFixedArray.inl150
-rw-r--r--src/Runtime/Source/System/Include/UICFunctionWrappers.h416
-rw-r--r--src/Runtime/Source/System/Include/UICHash.h105
-rw-r--r--src/Runtime/Source/System/Include/UICIFileStream.h56
-rw-r--r--src/Runtime/Source/System/Include/UICIStream.h162
-rw-r--r--src/Runtime/Source/System/Include/UICITimer.h61
-rw-r--r--src/Runtime/Source/System/Include/UICMacros.h189
-rw-r--r--src/Runtime/Source/System/Include/UICMatrix.h146
-rw-r--r--src/Runtime/Source/System/Include/UICMemory.h183
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryFilter.h69
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryHeap.h133
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryManager.h133
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryPool.h104
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryProbe.h144
-rw-r--r--src/Runtime/Source/System/Include/UICMemorySettings.h131
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryStatistics.h137
-rw-r--r--src/Runtime/Source/System/Include/UICMemoryTracker.h104
-rw-r--r--src/Runtime/Source/System/Include/UICPlatformSpecific.h207
-rw-r--r--src/Runtime/Source/System/Include/UICSyncPrimitive.h122
-rw-r--r--src/Runtime/Source/System/Include/UICThreadManager.h129
-rw-r--r--src/Runtime/Source/System/Include/UICThreadSafeQueue.h85
-rw-r--r--src/Runtime/Source/System/Include/UICThreadSafeQueue.inl89
-rw-r--r--src/Runtime/Source/System/Include/UICThreadSafeScratchpad.h98
-rw-r--r--src/Runtime/Source/System/Include/UICThreadSafeScratchpad.inl161
-rw-r--r--src/Runtime/Source/System/Include/UICTimer.h142
-rw-r--r--src/Runtime/Source/System/Include/UICTypes.h236
-rw-r--r--src/Runtime/Source/System/Include/UICVector3.h117
-rw-r--r--src/Runtime/Source/System/Source/SystemPrefix.cpp31
-rw-r--r--src/Runtime/Source/System/Source/UICAssert.cpp93
-rw-r--r--src/Runtime/Source/System/Source/UICBoundingBox.cpp150
-rw-r--r--src/Runtime/Source/System/Source/UICColor.cpp95
-rw-r--r--src/Runtime/Source/System/Source/UICCubicRoots.cpp38
-rw-r--r--src/Runtime/Source/System/Source/UICDLLManager.cpp216
-rw-r--r--src/Runtime/Source/System/Source/UICDataLogger.cpp157
-rw-r--r--src/Runtime/Source/System/Source/UICEulerAngles.cpp390
-rw-r--r--src/Runtime/Source/System/Source/UICFile.cpp77
-rw-r--r--src/Runtime/Source/System/Source/UICFileStream.cpp235
-rw-r--r--src/Runtime/Source/System/Source/UICFunctionWrappers.cpp65
-rw-r--r--src/Runtime/Source/System/Source/UICMatrix.cpp897
-rw-r--r--src/Runtime/Source/System/Source/UICMemory.cpp137
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryFilter.cpp126
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryHeap.cpp236
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryManager.cpp453
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryPool.cpp298
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryProbe.cpp149
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryStatistics.cpp647
-rw-r--r--src/Runtime/Source/System/Source/UICMemoryTracker.cpp164
-rw-r--r--src/Runtime/Source/System/Source/UICSyncPrimitive.cpp83
-rw-r--r--src/Runtime/Source/System/Source/UICThreadManager.cpp188
-rw-r--r--src/Runtime/Source/System/Source/UICTimer.cpp116
-rw-r--r--src/Runtime/Source/System/Source/UICTypes.cpp54
-rw-r--r--src/Runtime/Source/System/Source/UICVector3.cpp466
-rw-r--r--src/Runtime/Source/UICCompiler/Source/UICCompilerMain.cpp154
-rw-r--r--src/Runtime/Source/UICEvent/Include/EventSystem.h73
-rw-r--r--src/Runtime/Source/UICEvent/Include/EventSystemC.h139
-rw-r--r--src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystem.h87
-rw-r--r--src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystemLuaBinding.h52
-rw-r--r--src/Runtime/Source/UICEvent/Source/EventFactory.cpp143
-rw-r--r--src/Runtime/Source/UICEvent/Source/EventFactory.h87
-rw-r--r--src/Runtime/Source/UICEvent/Source/EventPoller.cpp375
-rw-r--r--src/Runtime/Source/UICEvent/Source/EventPoller.h103
-rw-r--r--src/Runtime/Source/UICEvent/Source/EventPollingSystemLuaBinding.cpp190
-rw-r--r--src/Runtime/Source/UICEvent/Source/EventSystemC.cpp34
-rw-r--r--src/Runtime/Source/UICEvent/Test/CanProviderDemo.cpp259
-rw-r--r--src/Runtime/Source/UICEvent/Test/CanProviderDemo.h56
-rw-r--r--src/Runtime/Source/UICEvent/Test/EventSystemCppTester.cpp237
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.cpp473
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.h173
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderCustomMaterial.h147
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.cpp72
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.h144
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.cpp158
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.h112
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.cpp54
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.h84
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderGraphObject.h77
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.cpp135
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.h113
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.cpp105
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.h203
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.cpp54
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.h89
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.cpp41
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.h77
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderMaterialDirty.h61
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.cpp74
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.h75
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.cpp497
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.h307
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.cpp59
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.h156
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderPathSubPath.h65
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.cpp43
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.h91
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderReferencedMaterial.h63
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.cpp101
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.h78
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderText.cpp66
-rw-r--r--src/Runtime/Source/UICRender/GraphObjects/UICRenderText.h77
-rw-r--r--src/Runtime/Source/UICRender/Include/ANDROID/DynamicLibLoader.h30
-rw-r--r--src/Runtime/Source/UICRender/Include/LINUX/DynamicLibLoader.h92
-rw-r--r--src/Runtime/Source/UICRender/Include/OSX/DynamicLibLoader.h30
-rw-r--r--src/Runtime/Source/UICRender/Include/QNX/DynamicLibLoader.h30
-rw-r--r--src/Runtime/Source/UICRender/Include/UICOffscreenRenderKey.h153
-rw-r--r--src/Runtime/Source/UICRender/Include/UICOffscreenRenderManager.h235
-rw-r--r--src/Runtime/Source/UICRender/Include/UICOldNBustedRenderPlugin.h85
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRender.h254
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderClippingFrustum.h161
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderContext.h221
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialRenderContext.h91
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialShaderGenerator.h69
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialSystem.h172
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h117
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystem.h289
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemCommands.h647
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemUtil.h124
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderEffectSystem.h207
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderEulerAngles.h143
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderGraphObjectPickQuery.h124
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderGraphObjectSerializer.h69
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderGraphObjectTypes.h166
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderImageScaler.h121
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderImageTextureData.h102
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderInputStreamFactory.h69
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderMaterialHelpers.h94
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderMaterialShaderGenerator.h152
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderMesh.h187
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPathManager.h121
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPathMath.h713
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPathRenderContext.h94
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsRenderer.h54
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsTypes.h103
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPlugin.h149
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPluginCInterface.h340
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPluginGraphObject.h60
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderPluginPropertyValue.h182
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderProfiler.h112
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderRay.h101
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderRenderList.h121
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderRotationHelper.h193
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderShaderCache.h159
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGenerator.h175
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGeneratorV2.h132
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderShaderKeys.h796
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderShadowMap.h183
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderString.h70
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderSubPresentationHelper.h69
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderSubpresentation.h99
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderTaggedPointer.h85
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderTessModeValues.h74
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderTextTextureAtlas.h63
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderTextTextureCache.h74
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderTextTypes.h166
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderTextureAtlas.h102
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderThreadPool.h80
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderUIPLoader.h126
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderUIPSharedTranslation.h460
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderWidgets.h181
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderWindowDimensions.h55
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderableImage.h76
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRenderer.h244
-rw-r--r--src/Runtime/Source/UICRender/Include/UICRendererUtil.h62
-rw-r--r--src/Runtime/Source/UICRender/Include/UICTextRenderer.h146
-rw-r--r--src/Runtime/Source/UICRender/Include/WINDOWS/DynamicLibLoader.h80
-rw-r--r--src/Runtime/Source/UICRender/Include/q3dsqmlrender.h85
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.cpp529
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.h419
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp2007
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.h543
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp2117
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.h182
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.cpp259
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.h116
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp1432
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.h367
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp2964
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h450
-rw-r--r--src/Runtime/Source/UICRender/RendererImpl/UICVertexPipelineImpl.h425
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.cpp326
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.h85
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp874
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.h104
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.cpp521
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.h93
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.cpp679
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.h175
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureBMP.cpp1267
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.cpp693
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.h86
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureFreeImageCompat.h413
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureGIF.cpp849
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp249
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.cpp600
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.h129
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.cpp101
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.h96
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.cpp436
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.h81
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.cpp174
-rw-r--r--src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.h126
-rw-r--r--src/Runtime/Source/UICRender/Source/UICOffscreenRenderManager.cpp497
-rw-r--r--src/Runtime/Source/UICRender/Source/UICOldNBustedRenderPlugin.cpp116
-rw-r--r--src/Runtime/Source/UICRender/Source/UICOnscreenTextRenderer.cpp421
-rw-r--r--src/Runtime/Source/UICRender/Source/UICQtTextRenderer.cpp609
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderClippingFrustum.cpp85
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderContext.cpp928
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialShaderGenerator.cpp1101
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialSystem.cpp2909
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp1783
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderDynamicObjectSystem.cpp1560
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderEffectSystem.cpp1845
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderEulerAngles.cpp383
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderGpuProfiler.cpp285
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderGraphObjectSerializer.cpp668
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderImageScaler.cpp882
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderInputStreamFactory.cpp207
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderPathManager.cpp1948
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp311
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsTypes.cpp66
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderPlugin.cpp921
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderRay.cpp164
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderRenderList.cpp110
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp755
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGenerator.cpp526
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp627
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderShadowMap.cpp219
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderSubpresentation.cpp111
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp121
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderTextTextureCache.cpp276
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderTextureAtlas.cpp364
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderThreadPool.cpp327
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderUIPLoader.cpp2019
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderUIPSharedTranslation.cpp425
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRenderWidgets.cpp326
-rw-r--r--src/Runtime/Source/UICRender/Source/UICRendererUtil.cpp119
-rw-r--r--src/Runtime/Source/UICRender/Source/UICTextRenderer.cpp87
-rw-r--r--src/Runtime/Source/UICRender/Source/q3dsqmlrender.cpp125
-rw-r--r--src/Runtime/Source/UICState/Application/UICStateApplication.cpp200
-rw-r--r--src/Runtime/Source/UICState/Application/UICStateApplication.h50
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICLuaDatamodelCache.cpp518
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICLuaDebugger.h262
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICLuaDebuggerImpl.h47
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICLuaDebuggerProtocol.h710
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICLuaSideDebugger.cpp1176
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICSceneGraphDebugger.h111
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerProtocol.h375
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerValue.h190
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICSceneGraphRuntimeDebugger.cpp345
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDataTest.cpp368
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.cpp770
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.h141
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebuggedInterpreter.cpp302
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebugger.cpp320
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebugger.h391
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebuggerListener.cpp322
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebuggerProtocol.h925
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateDebuggerValues.h540
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateLuaTest.cpp231
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateTest.h95
-rw-r--r--src/Runtime/Source/UICState/Debugger/UICStateTestCommon.h100
-rw-r--r--src/Runtime/Source/UICState/Editor/UICLuaArchitectDebugger.cpp359
-rw-r--r--src/Runtime/Source/UICState/Editor/UICSceneGraphArchitectDebugger.cpp574
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateDebuggerMaster.cpp222
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditor.cpp1880
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditor.h315
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorEditorsImpl.h1772
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorFoundation.h81
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorImpl.h406
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorProperties.h599
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.cpp239
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.h195
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.cpp813
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.h467
-rw-r--r--src/Runtime/Source/UICState/Editor/UICStateEditorValue.h271
-rw-r--r--src/Runtime/Source/UICState/Editor/UICUIADatamodel.cpp2527
-rw-r--r--src/Runtime/Source/UICState/Editor/UICUIADatamodel.h174
-rw-r--r--src/Runtime/Source/UICState/Editor/UICUIADatamodelValue.h291
-rw-r--r--src/Runtime/Source/UICState/Include/UICState.h108
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateContext.h95
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateExecutionContext.h73
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateExecutionTypes.h392
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateIdValue.h173
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateInterpreter.h121
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateLuaScriptContext.h95
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateScriptContext.h128
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateSharedImpl.h117
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateSignalConnection.h49
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateTypes.h720
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateVisualBindingContext.h123
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateVisualBindingContextCommands.h348
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateVisualBindingContextValues.h253
-rw-r--r--src/Runtime/Source/UICState/Include/UICStateXMLIO.h112
-rw-r--r--src/Runtime/Source/UICState/Source/UICStateContext.cpp202
-rw-r--r--src/Runtime/Source/UICState/Source/UICStateExecutionContext.cpp332
-rw-r--r--src/Runtime/Source/UICState/Source/UICStateInterpreter.cpp2057
-rw-r--r--src/Runtime/Source/UICState/Source/UICStateLuaScriptContext.cpp1412
-rw-r--r--src/Runtime/Source/UICState/Source/UICStateVisualBindingContext.cpp657
-rw-r--r--src/Runtime/Source/UICState/Source/UICStateXMLIO.cpp1948
-rw-r--r--src/Runtime/Source/UIPParser/Include/UICIPresentation.h177
-rw-r--r--src/Runtime/Source/UIPParser/Include/UICUIPParser.h153
-rw-r--r--src/Runtime/Source/UIPParser/Include/UICUIPParserActionHelper.h172
-rw-r--r--src/Runtime/Source/UIPParser/Include/UICUIPParserImpl.h664
-rw-r--r--src/Runtime/Source/UIPParser/Include/UICUIPParserObjectRefHelper.h159
-rw-r--r--src/Runtime/Source/UIPParser/Source/UICUIPParserActionHelper.cpp746
-rw-r--r--src/Runtime/Source/UIPParser/Source/UICUIPParserImpl.cpp2574
-rw-r--r--src/Runtime/Source/UIPParser/Source/UICUIPParserObjectRefHelper.cpp1004
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.cpp241
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.h77
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.cpp255
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.h84
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.cpp476
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.h376
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClientStub.h59
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/TCPPerfLogCommon.h98
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.cpp157
-rw-r--r--src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.h58
-rw-r--r--src/Runtime/Source/Viewer/UICAudioPlayerImpl.cpp60
-rw-r--r--src/Runtime/Source/Viewer/UICAudioPlayerImpl.h48
-rw-r--r--src/Runtime/Source/Viewer/UICEmbeddedWatermark.h64
-rw-r--r--src/Runtime/Source/Viewer/UICViewerApp.cpp821
-rw-r--r--src/Runtime/Source/Viewer/UICViewerApp.h394
-rw-r--r--src/Runtime/Source/Viewer/UICViewerTimer.h120
-rw-r--r--src/Runtime/Source/Viewer/qt3dsruntimeglobal.h45
-rw-r--r--src/Runtime/commoninclude.pri87
-rw-r--r--src/Runtime/platformres.qrc4
-rw-r--r--src/Runtime/res.qrc98
-rw-r--r--src/Runtime/res/DataModelMetadata/en-us/MetaData.xml503
-rw-r--r--src/Runtime/res/Font/TitilliumWeb-Regular.ttfbin0 -> 63752 bytes
-rw-r--r--src/Runtime/res/effectlib/Fxaa3_11.glsllib2073
-rw-r--r--src/Runtime/res/effectlib/Fxaa3_8.glsllib1423
-rw-r--r--src/Runtime/res/effectlib/SMAA.glsllib1444
-rw-r--r--src/Runtime/res/effectlib/SSAOCustomMaterial.glsllib91
-rw-r--r--src/Runtime/res/effectlib/abbeNumberIOR.glsllib36
-rw-r--r--src/Runtime/res/effectlib/anisotropyConversion.glsllib46
-rw-r--r--src/Runtime/res/effectlib/average.glsllib35
-rw-r--r--src/Runtime/res/effectlib/blendColorLayers.glsllib45
-rw-r--r--src/Runtime/res/effectlib/blur.glsllib295
-rw-r--r--src/Runtime/res/effectlib/calculateRoughness.glsllib63
-rw-r--r--src/Runtime/res/effectlib/coordinateSource.glsllib55
-rw-r--r--src/Runtime/res/effectlib/cube.glsllib50
-rw-r--r--src/Runtime/res/effectlib/customCurveLayer.glsllib42
-rw-r--r--src/Runtime/res/effectlib/customMaterial.glsllib47
-rw-r--r--src/Runtime/res/effectlib/customMaterialFragBody.glsllib84
-rw-r--r--src/Runtime/res/effectlib/customMaterialFragBodyAO.glsllib90
-rw-r--r--src/Runtime/res/effectlib/defaultMaterialFresnel.glsllib45
-rw-r--r--src/Runtime/res/effectlib/defaultMaterialLighting.glsllib80
-rw-r--r--src/Runtime/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib43
-rw-r--r--src/Runtime/res/effectlib/depthpass.glsllib80
-rw-r--r--src/Runtime/res/effectlib/dfTint.glsllib35
-rw-r--r--src/Runtime/res/effectlib/diffuseReflectionBSDF.glsllib66
-rw-r--r--src/Runtime/res/effectlib/diffuseTransmissionBSDF.glsllib42
-rw-r--r--src/Runtime/res/effectlib/directionalFactor.glsllib42
-rw-r--r--src/Runtime/res/effectlib/effect.glsllib148
-rw-r--r--src/Runtime/res/effectlib/evalBakedShadowMap.glsllib36
-rw-r--r--src/Runtime/res/effectlib/evalEnvironmentMap.glsllib55
-rw-r--r--src/Runtime/res/effectlib/evalLightmaps.glsllib56
-rw-r--r--src/Runtime/res/effectlib/fileBumpTexture.glsllib119
-rw-r--r--src/Runtime/res/effectlib/fileDisplacementTexture.glsllib71
-rw-r--r--src/Runtime/res/effectlib/fileTexture.glsllib48
-rw-r--r--src/Runtime/res/effectlib/flakeNoiseBumpTexture.glsllib46
-rw-r--r--src/Runtime/res/effectlib/flakeNoiseTexture.glsllib66
-rw-r--r--src/Runtime/res/effectlib/fresnelLayer.glsllib109
-rw-r--r--src/Runtime/res/effectlib/funcareaLightVars.glsllib32
-rw-r--r--src/Runtime/res/effectlib/funccalculateDiffuseAreaOld.glsllib29
-rw-r--r--src/Runtime/res/effectlib/funccalculatePointLightAttenuation.glsllib4
-rw-r--r--src/Runtime/res/effectlib/funccomputeMicroHit.glsllib50
-rw-r--r--src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib43
-rw-r--r--src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib5
-rw-r--r--src/Runtime/res/effectlib/funcgetTransformedUVCoords.glsllib4
-rw-r--r--src/Runtime/res/effectlib/funcsampleAreaGlossyDefault.glsllib42
-rw-r--r--src/Runtime/res/effectlib/funcsampleLightVars.glsllib29
-rw-r--r--src/Runtime/res/effectlib/funcspecularBSDF.glsllib42
-rw-r--r--src/Runtime/res/effectlib/gradient3Recolor.glsllib73
-rw-r--r--src/Runtime/res/effectlib/gradient3Texture.glsllib36
-rw-r--r--src/Runtime/res/effectlib/gradientGetPosition.glsllib76
-rw-r--r--src/Runtime/res/effectlib/luminance.glsllib62
-rw-r--r--src/Runtime/res/effectlib/miNoise.glsllib113
-rw-r--r--src/Runtime/res/effectlib/microfacetBSDF.glsllib259
-rw-r--r--src/Runtime/res/effectlib/monoChannel.glsllib58
-rw-r--r--src/Runtime/res/effectlib/normalizedMix.glsllib42
-rw-r--r--src/Runtime/res/effectlib/perlinNoise.glsllib234
-rw-r--r--src/Runtime/res/effectlib/perlinNoiseBumpTexture.glsllib49
-rw-r--r--src/Runtime/res/effectlib/perlinNoiseTexture.glsllib11
-rw-r--r--src/Runtime/res/effectlib/physGlossyBSDF.glsllib159
-rw-r--r--src/Runtime/res/effectlib/random255.glsllib56
-rw-r--r--src/Runtime/res/effectlib/refraction.glsllib87
-rw-r--r--src/Runtime/res/effectlib/rotationTranslationScale.glsllib50
-rw-r--r--src/Runtime/res/effectlib/sampleArea.glsllib180
-rw-r--r--src/Runtime/res/effectlib/sampleLight.glsllib130
-rw-r--r--src/Runtime/res/effectlib/sampleProbe.glsllib467
-rw-r--r--src/Runtime/res/effectlib/screenSpaceAO.glsllib150
-rw-r--r--src/Runtime/res/effectlib/screenSpaceDO.glsllib158
-rw-r--r--src/Runtime/res/effectlib/shadowMapping.glsllib106
-rw-r--r--src/Runtime/res/effectlib/shadowMappingFragment.glsllib10
-rw-r--r--src/Runtime/res/effectlib/simpleGlossyBSDF.glsllib99
-rw-r--r--src/Runtime/res/effectlib/specularBSDF.glsllib47
-rw-r--r--src/Runtime/res/effectlib/spotEdf.glsllib42
-rw-r--r--src/Runtime/res/effectlib/square.glsllib35
-rw-r--r--src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib91
-rw-r--r--src/Runtime/res/effectlib/tessellationLinear.glsllib104
-rw-r--r--src/Runtime/res/effectlib/tessellationLinearCM.glsllib174
-rw-r--r--src/Runtime/res/effectlib/tessellationNPatch.glsllib290
-rw-r--r--src/Runtime/res/effectlib/tessellationNPatchCM.glsllib194
-rw-r--r--src/Runtime/res/effectlib/tessellationPath.glsllib183
-rw-r--r--src/Runtime/res/effectlib/tessellationPhong.glsllib170
-rw-r--r--src/Runtime/res/effectlib/tessellationPhongCM.glsllib179
-rw-r--r--src/Runtime/res/effectlib/textureCoordinateInfo.glsllib54
-rw-r--r--src/Runtime/res/effectlib/transformCoordinate.glsllib43
-rw-r--r--src/Runtime/res/effectlib/uicDefaultMaterialFileBumpTexture.glsllib40
-rw-r--r--src/Runtime/res/effectlib/uicDefaultMaterialFileDisplacementTexture.glsllib40
-rw-r--r--src/Runtime/res/effectlib/uicDefaultMaterialFileNormalTexture.glsllib40
-rw-r--r--src/Runtime/res/effectlib/vertexFragmentBase.glsllib61
-rw-r--r--src/Runtime/res/effectlib/viewProperties.glsllib41
-rw-r--r--src/Runtime/res/effectlib/weightedLayer.glsllib35
-rw-r--r--src/Runtime/res/effectlib/wireframeCM.glsllib173
-rw-r--r--src/Runtime/res/primitives/Cone.meshbin0 -> 5352 bytes
-rw-r--r--src/Runtime/res/primitives/Cube.meshbin0 -> 1764 bytes
-rw-r--r--src/Runtime/res/primitives/Cylinder.meshbin0 -> 15908 bytes
-rw-r--r--src/Runtime/res/primitives/Rectangle.meshbin0 -> 900 bytes
-rw-r--r--src/Runtime/res/primitives/Sphere.meshbin0 -> 177980 bytes
-rw-r--r--src/Runtime/testres.qrc14
-rw-r--r--src/Viewer/Qt3DViewer/Qt3DViewer.pro34
-rw-r--r--src/Viewer/Qt3DViewer/Viewer.qrc10
-rw-r--r--src/Viewer/Qt3DViewer/Viewer.rc54
-rw-r--r--src/Viewer/Qt3DViewer/android/AndroidManifest.xml77
-rw-r--r--src/Viewer/Qt3DViewer/main.cpp70
-rw-r--r--src/Viewer/Qt3DViewer/mainwindow.cpp456
-rw-r--r--src/Viewer/Qt3DViewer/mainwindow.h101
-rw-r--r--src/Viewer/Qt3DViewer/mainwindow.ui213
-rw-r--r--src/Viewer/Qt3DViewer/remoteproject.cpp176
-rw-r--r--src/Viewer/Qt3DViewer/remoteproject.h76
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/Viewer.icobin0 -> 370070 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/ViewerDoc.icobin0 -> 370070 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/viewer_icon.pngbin0 -> 8473 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/style/checkbox.pngbin0 -> 343 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/style/dark.qss459
-rw-r--r--src/Viewer/Qt3DViewer/resources/style/down_arrow.pngbin0 -> 1008 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/style/handle.pngbin0 -> 2837 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt81
-rw-r--r--src/Viewer/Qt3DViewer/viewer.qml39
-rw-r--r--src/Viewer/Viewer.pro9
-rw-r--r--src/Viewer/qmlviewer/Qt3DSRenderer.cpp318
-rw-r--r--src/Viewer/qmlviewer/Qt3DSRenderer.h89
-rw-r--r--src/Viewer/qmlviewer/Qt3DSView.cpp289
-rw-r--r--src/Viewer/qmlviewer/Qt3DSView.h105
-rw-r--r--src/Viewer/qmlviewer/Qt3DSViewPlugin.cpp74
-rw-r--r--src/Viewer/qmlviewer/Qt3DSViewPlugin.h60
-rw-r--r--src/Viewer/qmlviewer/q3dspresentationitem.cpp90
-rw-r--r--src/Viewer/qmlviewer/q3dspresentationitem.h65
-rw-r--r--src/Viewer/qmlviewer/qmldir3
-rw-r--r--src/Viewer/qmlviewer/qmlviewer.pro37
-rw-r--r--src/Viewer/studio3d/q3dscommandqueue.cpp229
-rw-r--r--src/Viewer/studio3d/q3dscommandqueue_p.h141
-rw-r--r--src/Viewer/studio3d/q3dselement.cpp154
-rw-r--r--src/Viewer/studio3d/q3dselement.h79
-rw-r--r--src/Viewer/studio3d/q3dselement_p.h77
-rw-r--r--src/Viewer/studio3d/q3dspresentation.cpp688
-rw-r--r--src/Viewer/studio3d/q3dspresentation.h99
-rw-r--r--src/Viewer/studio3d/q3dspresentation_p.h93
-rw-r--r--src/Viewer/studio3d/q3dssceneelement.cpp273
-rw-r--r--src/Viewer/studio3d/q3dssceneelement.h83
-rw-r--r--src/Viewer/studio3d/q3dssceneelement_p.h81
-rw-r--r--src/Viewer/studio3d/q3dssurfaceviewer.cpp410
-rw-r--r--src/Viewer/studio3d/q3dssurfaceviewer.h99
-rw-r--r--src/Viewer/studio3d/q3dssurfaceviewer_p.h101
-rw-r--r--src/Viewer/studio3d/q3dsviewersettings.cpp244
-rw-r--r--src/Viewer/studio3d/q3dsviewersettings.h101
-rw-r--r--src/Viewer/studio3d/q3dsviewersettings_p.h88
-rw-r--r--src/Viewer/studio3d/q3dswidget.cpp327
-rw-r--r--src/Viewer/studio3d/q3dswidget.h92
-rw-r--r--src/Viewer/studio3d/q3dswidget_p.h92
-rw-r--r--src/Viewer/studio3d/qstudio3dglobal.h49
-rw-r--r--src/Viewer/studio3d/studio3d.pri35
-rw-r--r--src/Viewer/studio3d/studio3d.pro21
-rw-r--r--src/Viewer/studio3d/studioutils.cpp56
-rw-r--r--src/Viewer/studio3d/studioutils_p.h52
-rw-r--r--src/Viewer/studio3d/viewerqmlstreamproxy.cpp59
-rw-r--r--src/Viewer/studio3d/viewerqmlstreamproxy_p.h57
-rw-r--r--src/commonplatform.pri194
-rw-r--r--src/src.pro11
-rw-r--r--src/utils.pri8
-rw-r--r--sync.profile10
-rw-r--r--tests/auto/auto.pro8
-rw-r--r--tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro18
-rw-r--r--tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp106
-rw-r--r--tests/auto/qtextras/qtextras.pro4
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestBase.cpp65
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestBase.h164
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp118
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestMathUtil.h50
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp248
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h59
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp251
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h59
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp332
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h62
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestClear.cpp131
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestClear.h56
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp847
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h63
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp358
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h60
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp321
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h77
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp401
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h60
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp288
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h67
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp436
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h64
-rw-r--r--tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp636
-rw-r--r--tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h61
-rw-r--r--tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp299
-rw-r--r--tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h67
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp390
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h60
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp367
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h66
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp560
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h60
-rw-r--r--tests/auto/runtime/images/NVRenderTestAttribBuffers.pngbin0 -> 3820 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestBackendQuery.pngbin0 -> 2355 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestClear.pngbin0 -> 2327 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestComputeShader.pngbin0 -> 3889 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.pngbin0 -> 2355 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestFboMsaa.pngbin0 -> 3168 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestGeometryShader.pngbin0 -> 3311 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestOcclusionQuery.pngbin0 -> 2355 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestProgramPipeline.pngbin0 -> 3224 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestTexture2D.pngbin0 -> 2991 bytes
-rw-r--r--tests/auto/runtime/runtime.pro92
-rw-r--r--tests/auto/runtime/runtime.qrc14
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp468
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h55
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp576
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h56
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp156
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h55
-rw-r--r--tests/auto/runtime/tst_qt3dsruntime.cpp685
-rw-r--r--tests/auto/runtime/tst_qt3dsruntime.h130
-rw-r--r--tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro10
-rw-r--r--tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp1478
-rw-r--r--tests/auto/studio3d/q3dswidget/q3dswidget.pro10
-rw-r--r--tests/auto/studio3d/q3dswidget/tst_q3dswidget.cpp1040
-rw-r--r--tests/auto/studio3d/shared/presentation/animation.uip35
-rw-r--r--tests/auto/studio3d/shared/presentation/blue.uip31
-rw-r--r--tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttfbin0 -> 63752 bytes
-rw-r--r--tests/auto/studio3d/shared/presentation/mixed.uip36
-rw-r--r--tests/auto/studio3d/shared/presentation/mixed_vertical.uip36
-rw-r--r--tests/auto/studio3d/shared/presentation/mouse.uip54
-rw-r--r--tests/auto/studio3d/shared/presentation/multislide.uip99
-rw-r--r--tests/auto/studio3d/shared/presentation/red.uip31
-rw-r--r--tests/auto/studio3d/shared/presentation/settings.uip31
-rw-r--r--tests/auto/studio3d/shared/shared_presentations.h38
-rw-r--r--tests/auto/studio3d/shared/shared_presentations.qrc12
-rw-r--r--tests/auto/studio3d/studio3d.pro5
-rw-r--r--tests/auto/viewer/simple_cube_animation/simple_cube_animation.uia6
-rw-r--r--tests/auto/viewer/simple_cube_animation/simple_cube_animation.uip50
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.cpp92
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.h51
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.qml60
-rw-r--r--tests/auto/viewer/viewer.pro21
-rw-r--r--tests/auto/viewer/viewer.qrc7
-rw-r--r--tests/tests.pro4
3060 files changed, 570322 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..9842d4e7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+*_crlf.* eol=crlf
+.tag export-subst
+.gitignore export-ignore
+.gitattributes export-ignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..5be57438
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+build-*
+*.pro.user*
+/*/Viewer/Shared/UICEmbeddedWatermark.cpp
+/.qmake.stash
+fontcache/
+mocinclude.opt
+/installerextras/*/
+/src/3rdparty/boost/
+/src/3rdparty/FBX/
+*.o
+Makefile
+Makefile.*
+.moc/
+.uic/
+.rcc/
+moc_*.cpp
+.DS_Store
+*.qmlc
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..9358ac2f
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "ColladaDOM"]
+ path = src/3rdparty/ColladaDOM
+ url = ../qt3dstudio-collada-dom.git
+[submodule "EASTL"]
+ path = src/3rdparty/EASTL
+ url = ../qt3dstudio-eastl.git
+[submodule "pcre"]
+ path = src/3rdparty/pcre
+ url = ../qt3dstudio-pcre.git
+[submodule "Lua"]
+ path = src/3rdparty/Lua
+ url = ../qt3dstudio-lua.git
diff --git a/.qmake.conf b/.qmake.conf
new file mode 100644
index 00000000..a088fffc
--- /dev/null
+++ b/.qmake.conf
@@ -0,0 +1,5 @@
+load(qt_build_config)
+
+MODULE_VERSION = 5.9.0
+
+CMAKE_MODULE_TESTS=-
diff --git a/Studio/Build Configurations/Viewer.build b/Studio/Build Configurations/Viewer.build
new file mode 100644
index 00000000..83d75beb
--- /dev/null
+++ b/Studio/Build Configurations/Viewer.build
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<project name="Viewer" default="uicpreview">
+ <!-- The following variables can be used to customize the way this script is executed. They can be configured either by the dropdown of Studio's toolbar or the environment variables in Studio Preferences.
+ BUILDFILE : path to this Nant file. This is auto-generated by Studio based on the configuration chosed.
+ UIPFILE : path to the UIC Project file.
+ MODE : Selected via Preview toolbar. It defines the C++ Build Configuration to executed, either ( Debug, Profile or Release )
+ PLATFORM : Selected via Preview toolbar. This defines the platform to preview the exported presentation.
+ FLOW : Configured via Studio's environment variable. Points to the location of the .xif file if previewing a Flow file
+ PREVIEW : Configured via Studio's environment variable. Alternative application to execute on preview.
+ -->
+ <uic:integration xmlns:uic="http://www.nvidia.com">
+ <uic:preview>"Build Configurations\Nant\bin\nant" -nologo -f:"%BUILDFILE%" -D:uipfile="%UIPFILE%" -D:mode=%MODE% -D:platform=%PLATFORM% -D:useflowfile="%FLOW%" -D:preview_app="%PREVIEW%"</uic:preview>
+ <uic:deploy>"Build Configurations\Nant\bin\nant" uicdeploy -nologo -f:"%BUILDFILE%" -D:uipfile="%UIPFILE%" -D:mode=%MODE% -D:platform=%PLATFORM% -D:useflowfile="%FLOW%"</uic:deploy>
+ <uic:property name="PLATFORM" label="Platform" help="Which box do you want to preview on?">
+ <uic:value name="PC" label="PC"/>
+ </uic:property>
+ <uic:property name="MODE" label="Release Mode">
+ <uic:value name="Release" label="Release"/>
+ <uic:value name="Debug" label="Debug"/>
+ </uic:property>
+ </uic:integration>
+
+ <property name="uicomposerpath" value="${ directory::get-parent-directory( directory::get-parent-directory( project::get-base-directory( ) ) ) }" />
+ <property name="status" value="0" />
+
+ <!--
+ Set default property values if they're not passed in.
+ Must do this before calculating what external file(s) to pull in.
+ -->
+ <property name="platform" value="PC" overwrite="false" />
+ <property name="mode" value="release" overwrite="false" />
+ <property name="varStudioName" value="Studio" overwrite="false" />
+
+ <property name="flowfile" value="${ path::combine( directory::get-current-directory( ), useflowfile ) }" unless="${ useflowfile == '_NULL_' }" />
+ <property name="flowfile" value="" if= "${ useflowfile == '_NULL_' }" />
+
+ <!-- Name of the executable viewer that is used for preview -->
+ <property name="Win32ViewerApp" value="${ 'UICViewerWin32' + mode + '.EXE' }" />
+
+ <!-- For conditioners/viewers that have additional DLL dependencies. -->
+ <setenv name="PATH" value="${ environment::get-variable( 'PATH' ) };${uicomposerpath}\Studio\Build Configurations\bin"/>
+
+ <!--
+ Bring in external NAnt files. Altogether, these must define
+ all main targets, "setup", "deploy", "preview".
+ -->
+ <include buildfile="Viewer/setup.include" />
+ <include buildfile="Viewer/deploy_${platform}.include" />
+ <include buildfile="Viewer/preview_${platform}.include" />
+
+ <!-- Defer to targets in external file(s), but using our dependencies. -->
+ <target
+ name="uicsetup"
+ description="E.g. ceate output folders, set up extra variables.">
+ <call target="setup" />
+ </target>
+ <target
+ name="uicdeploy" depends="uicsetup"
+ description="Copy all require files to necessary destination(s)">
+ <call target="deploy" />
+ </target>
+ <target
+ name="uicpreview" depends="uicdeploy"
+ description="Kick off the appropriate preview application.">
+ <call target="preview" />
+ </target>
+</project>
diff --git a/Studio/Build Configurations/Viewer/deploy_PC.include b/Studio/Build Configurations/Viewer/deploy_PC.include
new file mode 100644
index 00000000..7ed765dd
--- /dev/null
+++ b/Studio/Build Configurations/Viewer/deploy_PC.include
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<project name="Viewer">
+ <target name="deploy">
+ </target>
+</project> \ No newline at end of file
diff --git a/Studio/Build Configurations/Viewer/preview_PC.include b/Studio/Build Configurations/Viewer/preview_PC.include
new file mode 100644
index 00000000..335ddc6b
--- /dev/null
+++ b/Studio/Build Configurations/Viewer/preview_PC.include
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<project name="Viewer">
+ <target name="preview">
+ <if test="${preview_app=='_NULL_'}">
+ <echo message="Previewing ${ OutputFileName }" />
+ <if test="${ not property::exists('AbsoluteOutputPath')}">
+ <fail message="This script relies on setup.include to set up deploy parameters correctly." />
+ </if>
+
+ <property name="ViewerPath" value="${ path::combine( uicomposerpath, 'Runtime\Build\Bin\Win32\' ) }" />
+ <!-- preview app defaults to the one on the Deploy folder -->
+ <property name="ViewerArg" value="${ '&quot;' + path::combine( AbsoluteOutputPath, OutputFileName ) + '&quot;' }"/>
+ <echo message="ViewerPath = ${ ViewerPath }" />
+ <echo message="ViewerArg = ${ ViewerArg }" />
+ <exec program="${ path::combine( ViewerPath, Win32ViewerApp ) }" failonerror="false" commandline="${ ViewerArg }" resultproperty='status' />
+ <fail message="Unable to execute ${ Win32ViewerApp }" unless="${ status == '0' }" />
+ </if>
+
+ <if test="${preview_app != '_NULL_'}">
+ <exec program="${ preview_app }" failonerror="false" resultproperty='status' />
+ <fail message="Unable to execute ${ preview_app }" unless="${ status == '0' }" />
+ </if>
+ </target>
+</project>
diff --git a/Studio/Build Configurations/Viewer/setup.include b/Studio/Build Configurations/Viewer/setup.include
new file mode 100644
index 00000000..9b87c3b7
--- /dev/null
+++ b/Studio/Build Configurations/Viewer/setup.include
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<project name="Viewer">
+ <target name="setup">
+ <echo>Setting up directory structure...</echo>
+
+ <property name="UsingFlow" value="${ flowfile != '' }"/>
+
+ <property name="BaseFilePath" value="${ directory::get-current-directory( ) }" unless="${UsingFlow}"/>
+ <property name="BaseFilePath" value="${ path::get-directory-name( flowfile ) }" if= "${UsingFlow}"/>
+ <property name="AbsoluteOutputPath" value="${BaseFilePath}" />
+ <property name="OutputFileName" value="${ path::get-file-name( uipfile ) }" />
+
+ <if test="${ not UsingFlow}">
+ <echo message="No Flow"/>
+ </if>
+
+ <if test="${UsingFlow}">
+ <property name="OutputFileName" value="${ path::get-file-name( flowfile ) }" />
+ </if>
+ </target>
+</project>
diff --git a/Studio/Content/Effect Library/AdditiveColorGradient.effect b/Studio/Content/Effect Library/AdditiveColorGradient.effect
new file mode 100644
index 00000000..45965a4c
--- /dev/null
+++ b/Studio/Content/Effect Library/AdditiveColorGradient.effect
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property formalName="Top Color" name="top_color" type="Color" default="0.65 0.35 0.15" description="Top color of the gradient."/>
+ <Property formalName="Bottom Color" name="bottom_color" type="Color" default="0.05 0.35 0.75" description="Bottom color of the gradient."/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+void frag()
+{
+ vec4 origColor = texture2D_0(TexCoord);
+ vec2 uv = TexCoord.xy;
+
+ vec4 gradient = vec4(mix(vec4(bottom_color, 1.0), vec4(top_color, 1.0), uv.y));
+
+ gl_FragColor = origColor + gradient;
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/BaseEffect.effect b/Studio/Content/Effect Library/BaseEffect.effect
new file mode 100644
index 00000000..f0f53402
--- /dev/null
+++ b/Studio/Content/Effect Library/BaseEffect.effect
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+void frag()
+{
+ // save original fragments to a variable
+ vec4 original = texture2D_0(TexCoord);
+
+ //output the unmodified original fragments;
+ gl_FragColor = original;
+}
+
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/Bloom.effect b/Studio/Content/Effect Library/Bloom.effect
new file mode 100644
index 00000000..dda390e5
--- /dev/null
+++ b/Studio/Content/Effect Library/Bloom.effect
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="Threshold" formalName="Threshold of the luminocity pass" description="Objects brighter than this will be part of the filter" min=".1" max=".98" default=".8" />
+ <Property name="PoissonRotation" hidden="True" default="0"/>
+ <Property name="PoissonDistance" hidden="True" default="4"/>
+ <Property name="Downsample2" filter="linear" clamp="clamp" type="Texture" />
+ <Property name="Downsample4" filter="linear" clamp="clamp" type="Texture" />
+ <Property name="Downsample8" filter="linear" clamp="clamp" type="Texture" />
+ <Property name="Downsample16" filter="linear" clamp="clamp" type="Texture" />
+ <Property name="DepthSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+varying float range;
+ </Shared>
+ <Shader name="CLEARPASS">
+ <VertexShader>
+// Range of possible values that we care about.
+void vert ()
+{
+
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // Luminosity pass with exponential color channel decay based on the threshold above.
+{
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="STENCILPASS">
+ <VertexShader>
+// Range of possible values that we care about.
+void vert ()
+{
+
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // Luminosity pass with exponential color channel decay based on the threshold above.
+{
+ gl_FragColor = texture2D_0(TexCoord);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="LUMINOSITY">
+ <VertexShader>
+// No op
+void vert ()
+{
+
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // Luminosity pass with exponential color channel decay based on the threshold above.
+{
+ vec4 color = texture2D_0(TexCoord);
+ float luminosity = dot(color.rgb, vec3(0.299, 0.587, 0.114));
+ float decay = min( 1.0, max( 0.0, (luminosity - Threshold) / range ) );
+ decay = decay * decay;
+ gl_FragColor = vec4( color.rgb * decay, color.a );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLUR">
+ <VertexShader>
+
+vec2 ToRotatedPoissonTexCoord( vec3 poisson, vec2 inputTex, vec2 inc, mat2 rotation )
+{
+ vec2 rotatedPoisson = rotation * vec2( poisson.xy );
+ return vec2( inputTex.x + rotatedPoisson.x * inc.x, inputTex.y + rotatedPoisson.y * inc.y );
+}
+
+void SetupPoissonBlurCoordsRotation(float inBlurAmount, vec2 inTexInfo, float inRotationRadians )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ float rotCos = cos( inRotationRadians );
+ float rotSin = sin( inRotationRadians );
+ mat2 rotMatrix = mat2( rotCos, rotSin, -rotSin, rotCos );
+ vec2 incVec = vec2( incX, incY );
+
+ TexCoord0 = ToRotatedPoissonTexCoord( poisson0, TexCoord, incVec, rotMatrix );
+ TexCoord1 = ToRotatedPoissonTexCoord( poisson1, TexCoord, incVec, rotMatrix );
+ TexCoord2 = ToRotatedPoissonTexCoord( poisson2, TexCoord, incVec, rotMatrix );
+ TexCoord3 = ToRotatedPoissonTexCoord( poisson3, TexCoord, incVec, rotMatrix );
+ TexCoord4 = ToRotatedPoissonTexCoord( poisson4, TexCoord, incVec, rotMatrix );
+ TexCoord5 = ToRotatedPoissonTexCoord( poisson5, TexCoord, incVec, rotMatrix );
+ TexCoord6 = ToRotatedPoissonTexCoord( poisson6, TexCoord, incVec, rotMatrix );
+ TexCoord7 = ToRotatedPoissonTexCoord( poisson7, TexCoord, incVec, rotMatrix );
+}
+
+void vert ()
+{
+ SetupPoissonBlurCoordsRotation( PoissonDistance, Texture0Info.xy, PoissonRotation);
+}
+ </VertexShader>
+ <FragmentShader>
+vec4 PoissonBlur(sampler2D inSampler )
+{
+ float mult0 = (1.0 - poisson0.z);
+ float mult1 = (1.0 - poisson1.z);
+ float mult2 = (1.0 - poisson2.z);
+ float mult3 = (1.0 - poisson3.z);
+ float mult4 = (1.0 - poisson4.z);
+ float mult5 = (1.0 - poisson5.z);
+ float mult6 = (1.0 - poisson6.z);
+ float mult7 = (1.0 - poisson7.z);
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6 + mult7;
+ float multMultiplier = ( multTotal > 0.0 ? 1.0 / multTotal : 0.0 );
+
+ vec4 outColor = GetTextureValue( inSampler, TexCoord0, 1.0 ) * (mult0 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord1, 1.0 ) * (mult1 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord2, 1.0 ) * (mult2 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord3, 1.0 ) * (mult3 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord4, 1.0 ) * (mult4 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord5, 1.0 ) * (mult5 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord6, 1.0 ) * (mult6 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord7, 1.0 ) * (mult7 * multMultiplier);
+ return outColor;
+}
+
+void frag()
+{
+ //Passing in 1.0 means the value will not get alpha-multiplied again
+ gl_FragColor = PoissonBlur( Texture0 );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="COMBINER">
+ <FragmentShader>
+
+void frag()
+{
+ vec4 sourceColor = texture2D_0(TexCoord);
+
+
+ vec3 summation = texture2D_Downsample2(TexCoord).xyz
+ + texture2D_Downsample4(TexCoord).xyz
+ + texture2D_Downsample8(TexCoord).xyz
+ + texture2D_Downsample16(TexCoord).xyz;
+ gl_FragColor = vec4( clamp( sourceColor.x + summation.x, 0.0, sourceColor.a )
+ , clamp( sourceColor.y + summation.y, 0.0, sourceColor.a )
+ , clamp( sourceColor.z + summation.z, 0.0, sourceColor.a )
+ , sourceColor.a );
+
+ /*
+
+ gl_FragColor = vec4( texture2D_Downsample2(TexCoord).xyz
+ , sourceColor.a );
+ */
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="luminosity_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" lifetime="frame"/>
+ <Buffer name="luminosity_buffer2" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".5" lifetime="frame"/>
+ <Buffer name="downsample_buffer2" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".5" lifetime="frame"/>
+ <Buffer name="downsample_buffer4" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".25" lifetime="frame"/>
+ <Buffer name="downsample_buffer8" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".125" lifetime="frame"/>
+ <Buffer name="downsample_buffer16" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".0625" lifetime="frame"/>
+ <Pass shader="CLEARPASS" input="[source]" output="luminosity_buffer">
+ <RenderState name="Stencil" value="false"/>
+ </Pass>
+ <Pass shader="STENCILPASS" input="[source]" output="luminosity_buffer">
+ <RenderState name="Stencil" value="true"/>
+ </Pass>
+ <Pass shader="LUMINOSITY" input="luminosity_buffer" output="luminosity_buffer2">
+ <RenderState name="Stencil" value="false"/>
+ </Pass>
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer2">
+ <SetParam name="PoissonDistance" value="4"/>
+ <SetParam name="PoissonRotation" value="0"/>
+ </Pass>
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer4">
+ <SetParam name="PoissonDistance" value="4"/>
+ <SetParam name="PoissonRotation" value="0.62831"/>
+ </Pass>
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer8">
+ <SetParam name="PoissonDistance" value="6"/>
+ <SetParam name="PoissonRotation" value="1.25663"/>
+ </Pass>
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer16">
+ <SetParam name="PoissonDistance" value="10"/>
+ <SetParam name="PoissonRotation" value="1.88495"/>
+ </Pass>
+ <Pass shader="COMBINER" input="[source]">
+ <BufferInput param="Downsample2" value="downsample_buffer2"/>
+ <BufferInput param="Downsample4" value="downsample_buffer4"/>
+ <BufferInput param="Downsample8" value="downsample_buffer8"/>
+ <BufferInput param="Downsample16" value="downsample_buffer16"/>
+ <RenderState name="Stencil" value="false"/>
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/Blur.effect b/Studio/Content/Effect Library/Blur.effect
new file mode 100644
index 00000000..2b9b988f
--- /dev/null
+++ b/Studio/Content/Effect Library/Blur.effect
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="amount" formalName="Blur Amount" min="0" max="0.10" default="0.01" description="Amount of Blur"/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+void frag()
+{
+
+ vec4 c1 = texture2D_0(vec2(TexCoord.x - amount, TexCoord.y - amount));
+ vec4 c2 = texture2D_0(vec2(TexCoord.x + amount, TexCoord.y - amount));
+ vec4 c3 = texture2D_0(vec2(TexCoord.x - amount, TexCoord.y + amount));
+ vec4 c4 = texture2D_0(vec2(TexCoord.x + amount, TexCoord.y + amount));
+
+ vec4 f1 = vec4(mix(c1, c2, 0.5));
+ vec4 f2 = vec4(mix(c3, c4, 0.5));
+
+ vec4 c5 = texture2D_0(vec2(TexCoord.x - (amount * 2.0), TexCoord.y));
+ vec4 c6 = texture2D_0(vec2(TexCoord.x, TexCoord.y - (amount * 2.0)));
+ vec4 c7 = texture2D_0(vec2(TexCoord.x, TexCoord.y + (amount * 2.0)));
+ vec4 c8 = texture2D_0(vec2(TexCoord.x + (amount * 2.0), TexCoord.y));
+
+ vec4 f3 = vec4(mix(c5, c6, 0.5));
+ vec4 f4 = vec4(mix(c7, c8, 0.5));
+
+ vec4 r1 = vec4(mix(f1, f2, 0.5));
+ vec4 r2 = vec4(mix(f3, f4, 0.5));
+
+ gl_FragColor = vec4(mix(r1, r2, 0.5));
+
+
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/Brush Strokes.effect b/Studio/Content/Effect Library/Brush Strokes.effect
new file mode 100644
index 00000000..63022ecd
--- /dev/null
+++ b/Studio/Content/Effect Library/Brush Strokes.effect
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Simulates an artistic painting of the image-->
+ <Property name="NoiseSamp" formalName="Noise" filter="linear" clamp="repeat" type="Texture" default="./maps/effects/brushnoise.dds" description="Texture to be used for the brush texture"/>
+ <Property name="brushAngle" formalName="Brush Angle" default="45" description="Amount to rotate the noise texture."/>
+ <Property name="brushLen" formalName="Stroke Length" min="0" max="3" default="1" description="How far to offset the image/'brush'."/>
+ <Property name="brushSize" formalName="Stroke Size" min="10" max="200" default="100" description="Scale the brush. (Smaller values yield larger sizes.)"/>
+ </MetaData>
+ <Shaders>
+ <Shader>
+ <FragmentShader>
+void frag (void)
+{
+ if ( flagNoiseSamp != 0 ) {
+ float alpha = radians(brushAngle);
+ float cosAlpha = cos(alpha);
+ float sinAlpha = sin(alpha);
+ mat2 rotMat = mat2(cosAlpha, sinAlpha, -sinAlpha, cosAlpha);
+
+ vec2 uv0 = TexCoord / brushSize * 1000.0;
+ uv0 = (uv0.yx * rotMat).yx;
+
+ vec2 uv1 = texture2D_NoiseSamp(fract(uv0)).xy - 0.5;
+ uv1*= vec2(1.0, 0.01);
+ uv1*= rotMat;
+ vec2 uv2 = TexCoord + uv1 * 0.1 * brushLen;
+
+ vec2 halfPixelSize = 0.5 / Texture0Info.xy;
+ colorOutput(texture2D_0(clamp(uv2, halfPixelSize, 1.0-halfPixelSize)));
+ }
+ else
+ colorOutput(texture2D_0(TexCoord));
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Effect>
diff --git a/Studio/Content/Effect Library/ChromaticAberration.effect b/Studio/Content/Effect Library/ChromaticAberration.effect
new file mode 100644
index 00000000..3695cf7c
--- /dev/null
+++ b/Studio/Content/Effect Library/ChromaticAberration.effect
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="Dispersion" formalName="Aberration Amount" description="Amount of Chromatic Aberration" default="0"/>
+ <Property name="FocusDepth" formalName="Focus Depth" description="Dispersion will scale in relation to distance from this depth" default="0"/>
+ <Property name="MaskSampler" formalName="Effect Mask" description="Grayscale texture to control where and how strong on screen the aberration effect occurs" type="Texture" filter="linear" clamp="clamp" default="./maps/effects/white.png" />
+ <Property name="DepthDebug" formalName="Debug Dispersion Amount" type="Boolean" description="Allows you to see effect of controls. Black objects will disperse less and white will disperse more" default="False"/>
+ <Property name="DepthSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="SourceSampler" type="Texture" filter="linear" clamp="clamp"/>
+ </MetaData>
+ <Shaders>
+ <Shader Name="DISPERSE">
+ <FragmentShader>
+#include "depthpass.glsllib"
+
+uniform vec2 CameraClipRange;
+
+void frag()
+{
+ vec4 depthSample = texture(DepthSampler, TexCoord);
+ float depthVal = getDepthValue( depthSample, CameraClipRange );
+ float rawDepth = depthValueToLinearDistance( depthVal, CameraClipRange );
+
+ float depthScale = abs(CameraClipRange.y - CameraClipRange.x);
+ float depthDisp = abs(rawDepth - FocusDepth) / depthScale;
+ float finalDisperse = Dispersion * depthDisp;
+ float effectAmt = texture(MaskSampler, TexCoord).x;
+
+ if ( DepthDebug )
+ {
+ gl_FragColor.rgb = vec3( depthDisp * effectAmt );
+ return;
+ }
+
+ gl_FragColor = texture(SourceSampler, TexCoord);
+
+ ivec2 texSize = textureSize( SourceSampler, 0 );
+ vec2 dispDir = normalize( TexCoord.xy - vec2(0.5) );
+ dispDir /= 2.0 * vec2( texSize );
+ vec3 mixColor;
+ mixColor = gl_FragColor.rgb;
+ mixColor.r = texture(SourceSampler, TexCoord+dispDir*finalDisperse).r;
+ mixColor.b = texture(SourceSampler, TexCoord-dispDir*finalDisperse).b;
+
+ gl_FragColor.rgb = mix( gl_FragColor.rgb, mixColor, effectAmt );
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="DISPERSE">
+ <BufferInput value="[source]" param="SourceSampler" />
+ <DepthInput param="DepthSampler"/>
+ </Pass>
+ </Passes>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/ColorMaster.effect b/Studio/Content/Effect Library/ColorMaster.effect
new file mode 100644
index 00000000..efb6ab05
--- /dev/null
+++ b/Studio/Content/Effect Library/ColorMaster.effect
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="red" formalName="Red Amount" min="0" max="2.0" default="1.0" description="Amount of Red"/>
+ <Property name="green" formalName="Green Amount" min="0" max="2.0" default="1.0" description="Amount of Green"/>
+ <Property name="blue" formalName="Blue Amount" min="0" max="2.0" default="1.0" description="Amount of Blue"/>
+ <Property name="strength_gray" formalName="Saturation" min="-1" max="1" default="0.0" description="Strenght of Color"/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+vec4 desaturate(vec3 color, float strength)
+{
+ vec3 lum = vec3(0.299, 0.587, 0.114);
+ // lum values based on: ITU-R BT.601
+ vec3 gray = vec3(dot(lum, color));
+ return vec4(mix(color, gray, -strength), 1.0);
+}
+void frag()
+{
+ vec4 sourceColor = texture2D_0(TexCoord);
+ vec4 basecolor = vec4(sourceColor.r*red,sourceColor.g*green,sourceColor.b*blue,sourceColor.a);
+ gl_FragColor = desaturate(basecolor.rgb,strength_gray);
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/Corona.effect b/Studio/Content/Effect Library/Corona.effect
new file mode 100644
index 00000000..bdbd1b72
--- /dev/null
+++ b/Studio/Content/Effect Library/Corona.effect
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Creates a corona around a sprite.-->
+ <Property name="HBlurBias" formalName="Horizontal Blur" min="0" max="10" default="2" description="Amount of corona horizontally."/>
+ <Property name="VBlurBias" formalName="Vertical Blur" min="0" max="10" default="2" description="Amount of corona vertically."/>
+ <Property name="Trailfade" formalName="Fade Amount" min="0" max="1" default="0.8" description="0=no glow, 0.5=fade quickly, 1.0=persistent trails"/>
+ <Property name="GlowSampler" filter="nearest" clamp="clamp" type="Texture" />
+ <Property name="GlowCol" formalName="Glow Color" type="Color" default="1 0.6 0.0" description="The color to use for the glow."/>
+ <Property name="NoiseSamp" formalName="Noise" filter="linear" clamp="repeat" default="./maps/effects/noise.dds" type="Texture" description="Texture to be used for the noise texture"/>
+ <Property name="NoiseScale" formalName="Noise Density" min="0" max="10" default="2" description="The density of the noise in corona. The higher the value, the denser and smaller of the noise; the lower the value, the bigger of the noise scale."/>
+ <Property name="NoiseBright" formalName="Noise Brightness" min="0" max="5" default="4" description="Brightness of the noise."/>
+ <Property name="NoiseRatio" formalName="Noise Amount" min="0" max="1" default=".15" description="Magnitude of the noise."/>
+ <Property name="CrawlLen" formalName="Crawl Length" min="0" max="1" default=".3" description="Length of the corona trail in animation."/>
+ <Property name="CrawlAngle" formalName="Crawl Angle" default="0" description="Angle of the corona trail in animation."/>
+ <Property name="Sprite" filter="nearest" clamp="clamp" type="Texture" />
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+uniform float AppFrame; // frame number since app starts
+uniform float FPS;
+ </Shared>
+ <Shader name="CORONA_HBLUR">
+ <Shared>
+varying vec2 crawl; // corona crawl direction and magnitude
+ </Shared>
+ <VertexShader>
+void vert ()
+{
+ SetupHorizontalGaussianBlur(Texture0Info.x, HBlurBias, TexCoord);
+ // compute crawl
+ float alpha = radians(CrawlAngle + 180.0);
+ crawl = vec2(CrawlLen * sin(alpha), CrawlLen * cos(alpha));
+}
+ </VertexShader>
+ <FragmentShader>
+void frag()
+{
+ //Passing in 1.0 means the value will not get alpha-multiplied again
+ float OutCol = GaussianAlphaBlur( GlowSampler, 1.0 );
+ OutCol *= Trailfade; // fade away glow color
+ OutCol += texture2D_0( TexCoord ).a; // add glow color in the original tex area
+
+ vec2 nuv = NoiseScale * TexCoord3 + AppFrame / FPS * crawl;
+ vec4 noise = texture2D_NoiseSamp(fract(nuv));
+ float ns = (1.0 - NoiseRatio) + NoiseRatio * NoiseBright * noise.x;
+ OutCol *= ns;
+ gl_FragColor = vec4( OutCol );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="CORONA_VBLUR">
+ <VertexShader>
+void vert ()
+{
+ SetupVerticalGaussianBlur( Texture0Info.y, VBlurBias, TexCoord );
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // PS_Blur_Vertical_9tap
+{
+ float OutCol = GaussianAlphaBlur( Texture0, Texture0Info.z );
+ gl_FragColor = OutCol * vec4(GlowCol, 1.0);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="CORONA_BLEND">
+ <VertexShader>
+void vert()
+{
+}
+ </VertexShader>
+ <FragmentShader>
+void frag ()
+{
+ vec4 src = texture2D_0( TexCoord );
+ vec4 dst = texture2D_Sprite(TexCoord);
+ colorOutput( src * (1.0 - dst.a) + dst );
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="glow_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size="0.55" lifetime="scene"/>
+ <Buffer name="temp_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size="0.55" lifetime="frame"/>
+
+ <Pass shader="CORONA_HBLUR" input="[source]" output="temp_buffer">
+ <BufferInput param="GlowSampler" value="glow_buffer"/>
+ </Pass>
+ <Pass shader="CORONA_VBLUR" input="temp_buffer" output="glow_buffer"/>
+
+ <Pass shader="CORONA_BLEND" input="glow_buffer">
+ <BufferInput param="Sprite" value="[source]"/>
+ </Pass>
+ </Passes>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/Depth Of Field Bokeh.effect b/Studio/Content/Effect Library/Depth Of Field Bokeh.effect
new file mode 100644
index 00000000..c1278684
--- /dev/null
+++ b/Studio/Content/Effect Library/Depth Of Field Bokeh.effect
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="FocusDistance" formalName="Focus Distance" description="Objects exactly distance +- &quot;In Focus Width&quot; from the camera will be in focus" default="600"/>
+ <Property name="FocusWidth" formalName="Depth of Field" description="Objects within this range of Focus Distance will be in focus" default="20"/>
+ <Property name="MaxBokehRadius" formalName="Max Bokeh Radius" description="Maximum radius of a Bokeh sprite" default="15"/>
+ <Property name="MaxCoCRadius" formalName="Max CoC Radius" description="Maximum radius of a CoC" default="15"/>
+ <Property name="MinBokehThreshold" formalName="Min Bokeh Threshold" description="Minimum luminance difference for Bokeh detection" default="1.0"/>
+ <Property name="MaxBokehThreshold" formalName="Max Bokeh Threshold" description="Maximum luminance difference for Bokeh detection" default="1000.0"/>
+ <Property name="MinCoCThreshold" formalName="Min CoC Threshold" description="Minimum CoC radius for Bokeh detection" default="3.0"/>
+ <Property name="DepthDebug" formalName="Debug Focus Rendering" type="Boolean" description="Allows you to see exactly how the Focus variables work. Black objects are in focus, white are blurred" default="False"/>
+ <Property name="BokehShapeSampler" formalName="Bokeh shape" filter="linear" clamp="repeat" default="./maps/effects/HexagonalBokeh.png" type="Texture" description="Texture to be used for the bokeh shape"/>
+ <Property name="DepthSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="SourceSampler" type="Texture" filter="linear" clamp="clamp"/>
+ <Property name="BokehDetectSampler" type="Image2D" format="rgba32f" binding="1"/>
+ <Property name="BokehColorSampler" type="Image2D" format="rgba32f" binding="2"/>
+ <Property name="BokehSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="BokehPositionSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="BokehBufferSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="MergedBufferSampler" type="Texture" filter="linear" clamp="clamp"/>
+ <Property name="BokehCounter" type="Buffer" format="uvec4" usage="storage" binding="1" align="std140"/>
+
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+const float BlurAmount = 4.0;
+ </Shared>
+ <Shader name="CLEAR">
+ <VertexShader>
+void vert()
+{
+
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // Simple averaging box blur.
+{
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BOKEH_DETECT">
+ <VertexShader>
+
+void vert()
+{
+
+}
+
+ </VertexShader>
+ <FragmentShader>
+
+void frag() // Mix the input blur and the depth texture with the sprite
+{
+ vec4 sourceColor = textureLod(Texture0, TexCoord, 0.0);
+
+ float depthTap = getDepthValue( texture2D(DepthSampler, TexCoord), CameraClipRange );
+ float linearDepth = depthValueToLinearDistance( depthTap, CameraClipRange );
+ float FocusStart = FocusDistance - FocusWidth;
+ float FocusEnd = FocusDistance + FocusWidth;
+ float blur = clamp( abs(linearDepth - FocusDistance) / (FocusEnd-FocusStart), 0.00, 1.0);
+ //float blur = GetDepthMultiplier( TexCoord, DepthSampler, FocusDistance, FocusWidth, FocusWidth );
+ gl_FragColor = vec4( linearDepth, blur, 0.0, 1.0);
+
+ // use a 3x3 filter to compute luminance difference
+ vec3 avgColor = vec3(0);
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(1, 0)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(0, 1)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(-1, 0)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(0, -1)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(1, 1)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(1, -1)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(-1, -1)).xyz;
+ avgColor += textureLodOffset(Texture0, TexCoord, 0.0, ivec2(-1, 1)).xyz;
+ avgColor /= 8.0;
+
+ float currentLum = dot(vec3(0.2126, 0.7152, 0.0722), sourceColor.xyz);
+ float averageLum = dot(vec3(0.2126, 0.7152, 0.0722), avgColor);
+ //float currentLum = dot(vec3(1.0), sourceColor.xyz);
+ //float averageLum = dot(vec3(1.0), avgColor);
+ float lumDiff = max(currentLum - averageLum, 0.0);
+
+ float cocSize = blur * MaxCoCRadius;
+
+ if( lumDiff > MinBokehThreshold &amp;&amp; lumDiff &lt; MaxBokehThreshold &amp;&amp; cocSize > MinCoCThreshold )
+ {
+ ivec2 sourceSize, storeCoord;
+ sourceSize = ivec2(textureSize(Texture0, 0).xy);
+
+ uint add = uint(1);
+ int current = int(atomicAdd( BokehCounter_data[0].y, add));
+
+ storeCoord.y = int(floor(float(current/sourceSize.x)));
+ storeCoord.x = current - storeCoord.y*sourceSize.x;
+
+ imageStore(BokehDetectSampler, ivec2(storeCoord.xy), vec4(TexCoord.x * float(sourceSize.x), TexCoord.y * float(sourceSize.y), linearDepth, blur));
+
+ vec3 bokehColor = sourceColor.xyz / (cocSize);
+ imageStore(BokehColorSampler, ivec2(storeCoord.xy), vec4(bokehColor, 1.0));
+ }
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BOKEH_RENDER">
+ <VertexShader>
+out vec4 varColor;
+out float varRadius;
+out float varDepth;
+
+void vert()
+{
+ ivec2 bufSize, coord;
+ bufSize = textureSize(BokehPositionSampler,0).xy;
+ coord.y = int(floor(float(gl_InstanceID / bufSize.x)));
+ coord.x = gl_InstanceID - coord.y * bufSize.x;
+
+ varColor = texelFetch(BokehSampler, coord, 0);
+ vec4 pos = texelFetch(BokehPositionSampler, coord, 0);
+
+ varRadius = pos.w * MaxBokehRadius;
+ varDepth = pos.z;
+
+ // convert to NDC -1, 1 range
+ //pos.xy /= DestSize;
+ //pos.xy = pos.xy * 2.0 - 1.0;
+
+ vec4 pos1 = vec4( (attr_pos.xy + pos.xy) / DestSize.xy , 0.0, 1.0 );
+ gl_Position = pos1;
+}
+
+ </VertexShader>
+ <GeometryShader>
+#include "viewProperties.glsllib"
+
+in float varRadius[];
+in float varDepth[];
+in vec4 varColor[];
+out vec4 geColor;
+out float geDepth;
+out vec2 geUVPos;
+
+layout (points) in;
+layout (triangle_strip, max_vertices = 4) out;
+
+void main()
+{
+ gl_Layer = 0;
+ geColor = varColor[0];
+ geDepth = varDepth[0];
+ vec2 rcpSize = 1.0 / DestSize;
+
+ //emit triangle at pos.
+ vec2 offsetx = vec2(rcpSize.x * varRadius[0], 0.0);
+ vec2 offsety = vec2(0.0, rcpSize.y * varRadius[0]);
+ vec2 offsets = vec2(-1.0, -1.0); // Screen offset
+
+ // Expand point into a quad
+ gl_Position = vec4(offsets + 2.0*(gl_in[0].gl_Position.xy - offsetx - offsety),0.0 ,1.0);
+ geUVPos = vec2(0,0);
+ EmitVertex();
+ gl_Position = vec4(offsets + 2.0*(gl_in[0].gl_Position.xy + offsetx - offsety),0.0 ,1.0);
+ geUVPos = vec2(1,0);
+ EmitVertex();
+ gl_Position = vec4(offsets + 2.0*(gl_in[0].gl_Position.xy - offsetx + offsety),0.0 ,1.0);
+ geUVPos = vec2(0,1);
+ EmitVertex();
+ gl_Position = vec4(offsets + 2.0*(gl_in[0].gl_Position.xy + offsetx + offsety),0.0 ,1.0);
+ geUVPos = vec2(1,1);
+ EmitVertex();
+
+ EndPrimitive();
+}
+ </GeometryShader>
+ <FragmentShader>
+in vec4 geColor;
+in vec2 geUVPos;
+in float geDepth;
+
+void frag()
+{
+ float alpha = textureLod(BokehShapeSampler, geUVPos, 0.0 ).r;
+ vec2 bd = textureLod(Texture0, gl_FragCoord.xy/vec2(textureSize(Texture0, 0)), 0.0 ).xy;
+ float blur = bd.x;
+ float depth = bd.y;
+
+ float weight = clamp(depth - geDepth + 1.0, 0.0, 1.0);
+ weight = clamp( weight + blur, 0.0, 1.0);
+
+ gl_FragColor = vec4( geColor.xyz * alpha * weight, alpha * weight);
+}
+ </FragmentShader>
+ </Shader>
+
+<Shader name="MERGE">
+ <VertexShader>
+
+void vert()
+{
+ // reset bokeh counter
+ BokehCounter_data[0].y = uint(0);
+}
+ </VertexShader>
+ <FragmentShader>
+
+void frag() // Mix the input blur and the depth texture with the sprite
+{
+ vec4 sourceCol = texture2D( SourceSampler, TexCoord );
+
+ ivec2 storeCoord;
+ ivec2 sourceSize = textureSize(BokehBufferSampler, 0).xy;
+ storeCoord = ivec2(float(sourceSize.x) * TexCoord.x, float(sourceSize.y) * TexCoord.y);
+ vec4 bokehCol = texelFetch( BokehBufferSampler, storeCoord, 0 );
+ gl_FragColor = vec4( bokehCol.xyz + sourceCol.xyz, sourceCol.a );
+}
+ </FragmentShader>
+ </Shader>
+<Shader name="DOWNSAMPLE">
+ <VertexShader>
+void vert()
+{
+ SetupBoxBlurCoords(vec2(Texture0Info.xy));
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // Simple averaging box blur.
+{
+ gl_FragColor = BoxDepthBlur(DepthSampler, Texture0, Texture0Info.z, FocusDistance, FocusWidth, FocusWidth);
+}
+ </FragmentShader>
+ </Shader>
+<Shader name="BLUR">
+ <VertexShader>
+
+void vert()
+{
+ SetupPoissonBlurCoords( BlurAmount, DestSize.xy );
+}
+
+ </VertexShader>
+ <FragmentShader>
+
+void frag() // Mix the input blur and the depth texture with the sprite
+{
+ float centerMultiplier = GetDepthMultiplier( TexCoord, DepthSampler, FocusDistance, FocusWidth, FocusWidth );
+ if ( DepthDebug )
+ {
+ gl_FragColor = vec4( centerMultiplier,centerMultiplier,centerMultiplier, 1.0 );
+ }
+ else
+ {
+ vec4 blurColor = PoissonDepthBlur(Texture0, Texture0Info.z, DepthSampler, FocusDistance, FocusWidth, FocusWidth );
+ gl_FragColor = mix( texture2D(MergedBufferSampler,TexCoord), blurColor, centerMultiplier );
+ }
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+
+ <Passes>
+ <Buffer name="depthblur_buffer" type="fp16" format="rg" filter="nearest" wrap="clamp" size="1.0" lifetime="frame"/>
+ <Buffer name="bokeh_buffer" type="ubyte" format="rgba" filter="nearest" wrap="clamp" size="1.0" lifetime="scene"/>
+ <Buffer name="merged_buffer" type="ubyte" format="source" filter="nearest" wrap="clamp" size="1.0" lifetime="frame"/>
+ <Image name="bokeh_detect_image" type="fp16" format="rgba" filter="nearest" wrap="clamp" size="1.0" lifetime="scene" access="readwrite"/>
+ <Image name="bokeh_color_image" type="fp16" format="rgba" filter="nearest" wrap="clamp" size="1.0" lifetime="scene" access="readwrite"/>
+ <DataBuffer name="DrawIndirectBuffer" type="indirect" wrapName="BokehCounter" wrapType="storage" format="uint" size="4" lifetime="frame"/>
+ <Buffer name="downsample_buffer" type="ubyte" format="source" filter="linear" wrap="clamp" size=".5" lifetime="frame"/>
+
+ <Pass shader="CLEAR" input="[source]" output="bokeh_buffer">
+ </Pass>
+
+ <Pass shader="BOKEH_DETECT" input="[source]" output="depthblur_buffer">
+ <DepthInput param="DepthSampler"/>
+ <ImageInput value="bokeh_color_image" param="BokehColorSampler" usage="image"/>
+ <ImageInput value="bokeh_detect_image" param="BokehDetectSampler" usage="image"/>
+ <DataBufferInput param="BokehCounter" usage="storage"/>
+ </Pass>
+
+ <Pass shader="BOKEH_RENDER" input="depthblur_buffer" output="bokeh_buffer">
+ <ImageInput value="bokeh_color_image" param="BokehSampler" usage="texture" sync="true"/>
+ <ImageInput value="bokeh_detect_image" param="BokehPositionSampler" usage="texture" sync="true"/>
+ <DataBufferInput param="DrawIndirectBuffer" usage="indirect"/>
+ <Blending source="SrcAlpha" dest="One"/>
+ </Pass>
+
+ <Pass shader="MERGE" input="bokeh_buffer" output="merged_buffer">
+ <BufferInput value="[source]" param="SourceSampler" />
+ <BufferInput value="bokeh_buffer" param="BokehBufferSampler" />
+ <DataBufferInput param="BokehCounter" usage="storage"/>
+ </Pass>
+
+ <Pass shader="DOWNSAMPLE" input="merged_buffer" output="downsample_buffer">
+ <DepthInput param="DepthSampler"/>
+ </Pass>
+
+ <Pass shader="BLUR" input="downsample_buffer" output="[dest]" format="source">
+ <BufferInput value="merged_buffer" param="MergedBufferSampler" />
+ <DepthInput param="DepthSampler"/>
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/Depth Of Field HQ Blur.effect b/Studio/Content/Effect Library/Depth Of Field HQ Blur.effect
new file mode 100644
index 00000000..71250722
--- /dev/null
+++ b/Studio/Content/Effect Library/Depth Of Field HQ Blur.effect
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="FocusDistance" formalName="Focus Distance" description="Objects exactly distance +- &quot;In Focus Width&quot; from the camera will be in focus" default="600"/>
+ <Property name="FocusWidth" formalName="Depth of Field" description="Objects within this range of Focus Distance will be in focus" default="20"/>
+ <Property name="DepthDebug" formalName="Debug Focus Rendering" type="Boolean" description="Allows you to see exactly how the Focus variables work. Black objects are in focus, white are blurred" default="False"/>
+ <Property name="DepthSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="SourceSampler" type="Texture" filter="linear" clamp="clamp"/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+const float BlurAmount = 4.0;
+ </Shared>
+ <Shader name="DOWNSAMPLE">
+ <VertexShader>
+void vert()
+{
+ SetupBoxBlurCoords(vec2(Texture0Info.xy));
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // Simple averaging box blur.
+{
+ gl_FragColor = BoxDepthBlur(DepthSampler, Texture0, Texture0Info.z, FocusDistance, FocusWidth, FocusWidth);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLUR">
+ <VertexShader>
+
+void vert()
+{
+ SetupPoissonBlurCoords( BlurAmount, DestSize.xy );
+}
+
+ </VertexShader>
+ <FragmentShader>
+
+void frag() // Mix the input blur and the depth texture with the sprite
+{
+ float centerMultiplier = GetDepthMultiplier( TexCoord, DepthSampler, FocusDistance, FocusWidth, FocusWidth );
+ if ( DepthDebug )
+ {
+ gl_FragColor = vec4( centerMultiplier,centerMultiplier,centerMultiplier, 1.0 );
+ }
+ else
+ {
+ vec4 blurColor = PoissonDepthBlur(Texture0, Texture0Info.z, DepthSampler, FocusDistance, FocusWidth, FocusWidth );
+ gl_FragColor = mix( texture2D_SourceSampler(TexCoord), blurColor, centerMultiplier );
+ }
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="downsample_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".5" lifetime="frame"/>
+ <Pass shader="DOWNSAMPLE" input="[source]" output="downsample_buffer">
+ <DepthInput param="DepthSampler"/>
+ </Pass>
+ <Pass shader="BLUR" input="downsample_buffer">
+ <BufferInput value="[source]" param="SourceSampler" />
+ <DepthInput param="DepthSampler"/>
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/Desaturate.effect b/Studio/Content/Effect Library/Desaturate.effect
new file mode 100644
index 00000000..02c31191
--- /dev/null
+++ b/Studio/Content/Effect Library/Desaturate.effect
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="strenght_gray" formalName="Effect Strenght" min="0" max="1" default="1.0" description="Strenght of the Grayscale"/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+vec4 desaturate(vec3 color, float strenght)
+{
+ vec3 lum = vec3(0.299, 0.587, 0.114);
+ // lum values based on: ITU-R BT.601
+ vec3 gray = vec3(dot(lum, color));
+ return vec4(mix(color, gray, strenght), 1.0);
+}
+void frag()
+{
+ vec4 origColor = texture2D_0(TexCoord);
+
+ gl_FragColor = desaturate(origColor.rgb,strenght_gray);
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/Distortion Ripple.effect b/Studio/Content/Effect Library/Distortion Ripple.effect
new file mode 100644
index 00000000..b6d4b873
--- /dev/null
+++ b/Studio/Content/Effect Library/Distortion Ripple.effect
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Distorts the image in a ripple way.-->
+ <Property name="radius" formalName="Radius" min="0" max="100" default="100.0" description="Adjusts the spread between ripples."/>
+ <Property name="center" formalName="Center" type="Float2" default="0.5 0.5" description="Adjusts the focus point of the distortion."/>
+ <Property name="ripples" formalName="Wave Width" min="2" max="100" default="95.0" description="Adjusts the number of ripples."/>
+ <Property name="height" formalName="Wave Height" min="0" max="100" default="25.0" description="Adjusts the distortion amount."/>
+ <Property name="phase" formalName="Ripple Phase" default="0.0" description="The offset of each wave. Animate this property to see the waves move."/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+varying vec2 center_vec;
+float PI2 = radians(360.0);
+ </Shared>
+ <Shader>
+ <VertexShader>
+void vert ()
+{
+ center_vec = TexCoord - center;
+ //Multiply by x/y ratio so we see a sphere on the screen
+ //instead of an ellipse.
+ center_vec.y *= Texture0Info.y / Texture0Info.x;
+}
+ </VertexShader>
+ <FragmentShader>
+<![CDATA[
+void frag()
+{
+ float dist_to_center = length(center_vec) * 100.0 / radius;;
+
+ vec2 texc;
+ if(dist_to_center > 1.0) {
+ texc = TexCoord;
+ } else {
+ float r = PI2 * (1.0 - dist_to_center);
+ float distortion = sin(r * (100.0-ripples) + radians(phase));
+ texc = TexCoord - ( TexCoord - center ) * distortion * height / 800.0;
+ }
+
+ if ( texc.x < 0.0 || texc.x > 1.0 || texc.y < 0.0 || texc.y > 1.0 )
+ gl_FragColor = vec4(0.0);
+ else
+ colorOutput(texture2D_0(texc));
+}
+]]>
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/Distortion Sphere.effect b/Studio/Content/Effect Library/Distortion Sphere.effect
new file mode 100644
index 00000000..3ed1e70b
--- /dev/null
+++ b/Studio/Content/Effect Library/Distortion Sphere.effect
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Distorts the image in a spherical way.-->
+ <Property name="radius" formalName="Radius" min="0" max="1" default=".3" description="Adjusts the distorted area."/>
+ <Property name="height" formalName="Height" min="-1" max="1" default=".3" description="Adjusts the distortion amount."/>
+ <Property name="center" formalName="Center" type="Float2" default="0.5 0.5" description="Adjusts the focus point of the distortion."/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+varying vec2 center_vec;
+ </Shared>
+ <Shader>
+ <VertexShader>
+void vert ()
+{
+ center_vec = TexCoord - center;
+ //Multiply by x/y ratio so we see a sphere on the screen
+ //instead of an ellipse.
+ center_vec.y *= Texture0Info.y / Texture0Info.x;
+}
+ </VertexShader>
+ <FragmentShader>
+<![CDATA[
+void frag()
+{
+ float dist_to_center = length(center_vec) / radius;;
+
+ vec2 texc;
+ if(dist_to_center > 1.0) {
+ texc = TexCoord;
+ } else {
+ float distortion = 1.0 - dist_to_center * dist_to_center;
+ texc = TexCoord - (TexCoord - center) * distortion * height;
+ }
+
+ if ( texc.x < 0.0 || texc.x > 1.0 || texc.y < 0.0 || texc.y > 1.0 )
+ gl_FragColor = vec4(0.0);
+ else
+ colorOutput(texture2D_0(texc));
+}
+]]>
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/Distortion Spiral.effect b/Studio/Content/Effect Library/Distortion Spiral.effect
new file mode 100644
index 00000000..a5a96971
--- /dev/null
+++ b/Studio/Content/Effect Library/Distortion Spiral.effect
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Distorts the image in a spiraling way.-->
+ <Property name="radius" formalName="Radius" min="0" max="1" default=".3" description="Adjusts the distorted area."/>
+ <Property name="spiral" formalName="Spiral" min="-10" max="10" default="1.0" description="Adjusts the spiraling amount."/>
+ <Property name="center" formalName="Center" type="Float2" default="0.5 0.5" description="Adjusts the focus point of the distortion."/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+varying vec2 center_vec;
+float PI2 = radians(360.0);
+ </Shared>
+ <Shader>
+ <VertexShader>
+void vert ()
+{
+ center_vec = TexCoord - center;
+ //Multiply by x/y ratio so we see a sphere on the screen
+ //instead of an ellipse.
+ center_vec.y *= Texture0Info.y / Texture0Info.x;
+}
+ </VertexShader>
+ <FragmentShader>
+<![CDATA[
+void frag()
+{
+ float dist_to_center = length(center_vec) / radius;;
+
+ vec2 texc;
+ if(dist_to_center > 1.0) {
+ texc = TexCoord;
+ } else {
+ float rotation_amount = (1.0 - dist_to_center) * (1.0 - dist_to_center);
+ float r = PI2 * rotation_amount * spiral / 4.0;
+ float cos_r = cos(r);
+ float sin_r = sin(r);
+ mat2 rotation = mat2(cos_r, sin_r, -sin_r, cos_r);
+ texc = center + rotation * (TexCoord - center);
+ }
+
+ if ( texc.x < 0.0 || texc.x > 1.0 || texc.y < 0.0 || texc.y > 1.0 )
+ gl_FragColor = vec4(0.0);
+ else
+ colorOutput(texture2D_0(texc));
+}
+]]>
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/Edge Detect.effect b/Studio/Content/Effect Library/Edge Detect.effect
new file mode 100644
index 00000000..3fe10fed
--- /dev/null
+++ b/Studio/Content/Effect Library/Edge Detect.effect
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Smooth, unchanging areas of the image are turned black, while areas of the image with sharp color changes are brightened to highlight the 'edges' in the image.-->
+ <Property name="amount" formalName="Amount" min="0" max="1" default="1" description="0=no effect, 1=maximum effect"/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+////////////////////////////////////////////////////////////
+// vert / frag shaders.
+
+varying vec4 TexCoordBLL; //Bottom Left and Bottom Tap
+varying vec4 TexCoordTLT; //Top Left and Top Tap
+varying vec4 TexCoordTRR; //Upper Right and Right Tap
+varying vec4 TexCoordBRB; //Bottom Right and Bottom Tap
+ </Shared>
+ <Shader>
+ <VertexShader>
+void vert()
+{
+ //Pass Through the Texture Taps
+ float deltax = 1.0/Texture0Info.x;
+ float deltay = 1.0/Texture0Info.y;
+
+ //Bottom Left
+ TexCoordBLL.x = TexCoord.s - deltax;
+ TexCoordBLL.y = TexCoord.t - deltay;
+
+ //Left
+ TexCoordBLL.z = TexCoord.s - deltax;
+ TexCoordBLL.w = TexCoord.t;
+
+ //Top Left
+ TexCoordTLT.x = TexCoord.s - deltax;
+ TexCoordTLT.y = TexCoord.t + deltay;
+
+ //Top
+ TexCoordTLT.z = TexCoord.s;
+ TexCoordTLT.w = TexCoord.t + deltay;
+
+ //Upper Right
+ TexCoordTRR.x = TexCoord.s + deltax;
+ TexCoordTRR.y = TexCoord.t + deltay;
+
+ //Right
+ TexCoordTRR.z = TexCoord.s + deltax;
+ TexCoordTRR.w = TexCoord.t;
+
+ //Bottom Right
+ TexCoordBRB.x = TexCoord.s + deltax;
+ TexCoordBRB.y = TexCoord.t - deltay;
+
+ //Bottom
+ TexCoordBRB.z = TexCoord.s;
+ TexCoordBRB.w = TexCoord.t - deltay;
+}
+ </VertexShader>
+ <FragmentShader>
+void frag (void)
+{
+ vec4 centerTap = texture2D_0(TexCoord);
+ vec4 edgeTap = texture2D_0(TexCoordBLL.xy) +
+ texture2D_0(TexCoordBLL.zw) +
+ texture2D_0(TexCoordTLT.xy) +
+ texture2D_0(TexCoordTLT.zw) +
+ texture2D_0(TexCoordTRR.xy) +
+ texture2D_0(TexCoordTRR.zw) +
+ texture2D_0(TexCoordBRB.xy) +
+ texture2D_0(TexCoordBRB.zw);
+ vec3 edgeDetect = 8.0*(centerTap.rgb + -0.125*edgeTap.rgb);
+ edgeDetect = clamp(edgeDetect, 0.0, centerTap.a);
+
+ colorOutput(vec4(mix(centerTap.rgb, edgeDetect, amount), centerTap.a));
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Effect>
+
+
+
diff --git a/Studio/Content/Effect Library/Emboss.effect b/Studio/Content/Effect Library/Emboss.effect
new file mode 100644
index 00000000..876db3a5
--- /dev/null
+++ b/Studio/Content/Effect Library/Emboss.effect
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="amount" formalName="Amount" min="0" max="0.01" default="0.003" description="Amount"/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+void frag()
+{
+ vec4 origColor = texture2D_0(TexCoord);
+
+ float step_w = amount;
+ float step_h = amount;
+
+ vec4 t1 = texture2D_0(vec2(TexCoord.x - step_w, TexCoord.y - step_h));
+ vec4 t2 = texture2D_0(vec2(TexCoord.x, TexCoord.y - step_h));
+ vec4 t3 = texture2D_0(vec2(TexCoord.x - step_w, TexCoord.y));
+ vec4 t4 = texture2D_0(TexCoord);
+
+ vec3 rr = -4.0 * t1.rgb - 4.0 * t2.rgb - 4.0 * t3.rgb + 12.0 * t4.rgb;
+ float y = (rr.r + rr.g + rr.b) / 3.0;
+
+ vec4 result = vec4(vec3(y, y, y) + 0.3, origColor.a);
+
+ gl_FragColor = result;
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/FXAA.effect b/Studio/Content/Effect Library/FXAA.effect
new file mode 100644
index 00000000..0434a38e
--- /dev/null
+++ b/Studio/Content/Effect Library/FXAA.effect
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="Sprite" filter="nearest" clamp="clamp" type="Texture" />
+ </MetaData>
+ <Shaders>
+ <Shader name="RGBL">
+ <FragmentShader>
+void frag() // Create RGBL buffer
+{
+ vec4 color = texture2D_0(TexCoord);
+ color.a = dot(color.rgb, vec3(0.299, 0.587, 0.114));
+ gl_FragColor = color;
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLUR">
+ <FragmentShader>
+#define FXAA_VERION 311
+#define FXAA_PC 1
+#define FXAA_GLSL_130 1
+#define FXAA_LINEAR 1
+#if FXAA_VERION >= 311
+#include "Fxaa3_11.glsllib"
+#else
+#include "Fxaa3_8.glsllib"
+#endif
+
+void frag() // Mix the input blur and the depth texture with the sprite
+{
+ float sprightA = texture2D_Sprite( TexCoord ).a;
+#if FXAA_VERION >= 311
+ vec4 aaPix = FxaaPixelShader( TexCoord, vec4(0.0,0.0,0.0,0.0), Texture0, Texture0, Texture0, vec2(1.0 / DestSize.x, 1.0 / DestSize.y),
+ vec4(0,0,0,0), vec4(0,0,0,0), vec4(0,0,0,0), 0.75, 0.166, 0.0833, 8.0, 0.125, 0.05, vec4(0,0,0,0) );
+#else
+ vec4 aaPix = FxaaPixelShader( TexCoord, vec4(0.0,0.0,0.0,0.0), Texture0, vec2(1.0 / DestSize.x, 1.0 / DestSize.y), vec4(0,0,0,0) );
+#endif
+ gl_FragColor = vec4(aaPix.rgb, sprightA );
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="rgbl_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" lifetime="frame"/>
+ <Pass shader="RGBL" input="[source]" output="rgbl_buffer"/>
+ <Pass shader="BLUR" input="rgbl_buffer">
+ <BufferInput param="Sprite" value="[source]"/>
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/FrameFlipper.effect b/Studio/Content/Effect Library/FrameFlipper.effect
new file mode 100644
index 00000000..6529e6c8
--- /dev/null
+++ b/Studio/Content/Effect Library/FrameFlipper.effect
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="horflip" formalName="Flip Horizontally" type="Boolean" description="Flip Frame horizontally" default="False"/>
+ <Property name="verflip" formalName="Flip Vertically" type="Boolean" description="Flip Frame vertically" default="False"/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+void frag()
+{
+ float yflippedCoord = 1.0 - TexCoord.y;
+ float xflippedCoord = 1.0 - TexCoord.x;
+ vec2 flippedCoord = TexCoord;
+
+ if(horflip || verflip){
+ if(horflip){
+ flippedCoord.x = xflippedCoord;
+ }
+ if(verflip){
+ flippedCoord.y = yflippedCoord;
+ }
+ }
+
+ vec4 origColor = texture2D_0(flippedCoord);
+
+ gl_FragColor = origColor;
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/FullScreenTextureOverlay.effect b/Studio/Content/Effect Library/FullScreenTextureOverlay.effect
new file mode 100644
index 00000000..7c8325fe
--- /dev/null
+++ b/Studio/Content/Effect Library/FullScreenTextureOverlay.effect
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="Overlay" formalName="Overlay Texture" description="overlay texture" type="Texture" clamp="repeat" />
+ <Property name="overlay_repeat" formalName="Repeat" min="0" max="50" default="1" description="Times to repeat the image over screen."/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+void frag()
+{
+ vec4 smp = texture(Overlay, TexCoord.xy*overlay_repeat);
+ gl_FragColor = smp;
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/Gaussian Blur.effect b/Studio/Content/Effect Library/Gaussian Blur.effect
new file mode 100644
index 00000000..f76d505d
--- /dev/null
+++ b/Studio/Content/Effect Library/Gaussian Blur.effect
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Quickly blurs by an adjustable amount. Gaussian refers to the bell-shaped curve that is generated when the shader applies a weighted average to the pixels. The Gaussian Blur filter adds low-frequency detail and can produce a hazy effect.-->
+ <Property name="BlurBias" formalName="Blurriness" min="0" max="10" default="2" description="0=no blur, 10=maximum blur" />
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+ </Shared>
+ <Shader name="HBLUR">
+ <VertexShader>
+void vert()
+{
+ SetupHorizontalGaussianBlur(Texture0Info.x, BlurBias, TexCoord);
+}
+ </VertexShader>
+ <FragmentShader>
+void frag()
+{
+ gl_FragColor = GaussianBlur(Texture0, Texture0Info.z);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="VBLUR">
+ <VertexShader>
+void vert()
+{
+ SetupVerticalGaussianBlur(Texture0Info.y, BlurBias, TexCoord);
+}
+ </VertexShader>
+ <FragmentShader>
+
+void frag() // PS_Blur_Vertical_9tap
+{
+ vec4 fragColor = GaussianBlur(Texture0, Texture0Info.z);
+ colorOutput(fragColor);
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="temp_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size="1.0" lifetime="frame"/>
+ <Pass name="1" shader="HBLUR" input="[source]" output="temp_buffer"/>
+ <Pass name="2" shader="VBLUR" input="temp_buffer"/>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/HDRBloomTonemap.effect b/Studio/Content/Effect Library/HDRBloomTonemap.effect
new file mode 100644
index 00000000..c53ba0d0
--- /dev/null
+++ b/Studio/Content/Effect Library/HDRBloomTonemap.effect
@@ -0,0 +1,282 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="GammaValue" formalName="Gamma" default="2.2" min="0.1" max="4"/>
+ <Property name="Exposure" min="-9" max="9" default="0"/>
+
+ <Property name="BloomThreshold" formalName="Bloom Threshold" description="Objects brighter than this will generate a bloom" default="1.0" />
+ <Property name="BlurFalloff" formalName="Bloom Falloff" description="Size of the bloom (smaller is larger)" default="0" min="0" max="10"/>
+
+ <Property name="TonemappingLerp" formalName="Effect Amount" description="Adjust between no change and full effect." default="1" min="0" max="1" hidden="True"/>
+
+ <!--
+ <Property name="Key" formalName="Luminance Key" min="0" max="1" default="0.04"/>
+ <Property name="expLum" formalName="Exposure Luminance" default="2.0"/>
+ <Property name="TonemappingLod" formalName="Tonemapping adaptation rate" default="10" min="0" max="20"/>
+ -->
+ <Property name="ChannelThreshold" formalName="Channel Threshold" hidden="True" description="Channel threshold" default="1.0" />
+ <Property name="PoissonRotation" hidden="True" default="0"/>
+ <Property name="PoissonDistance" hidden="True" default="4"/>
+ <Property name="Downsample2" filter="linear" clamp="clamp" type="Texture" />
+ <Property name="Downsample4" filter="linear" clamp="clamp" type="Texture" />
+
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+#include "luminance.glsllib"
+float get_blur_falloff() { return exp2( -BlurFalloff ); }
+float get_exposure() { return exp2( Exposure ); }
+ </Shared>
+ <Shader name="LUMINOSITY">
+ <VertexShader>
+vec2 ToRotatedPoissonTexCoord( vec3 poisson, vec2 inputTex, vec2 inc, mat2 rotation )
+{
+ vec2 rotatedPoisson = rotation * vec2( poisson.xy );
+ return vec2( inputTex.x + rotatedPoisson.x * inc.x, inputTex.y + rotatedPoisson.y * inc.y );
+}
+
+void SetupPoissonBlurCoordsRotation(float inBlurAmount, vec2 inTexInfo, float inRotationRadians )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ float rotCos = cos( inRotationRadians );
+ float rotSin = sin( inRotationRadians );
+ mat2 rotMatrix = mat2( rotCos, rotSin, -rotSin, rotCos );
+ vec2 incVec = vec2( incX, incY );
+
+ TexCoord0 = ToRotatedPoissonTexCoord( poisson0, TexCoord, incVec, rotMatrix );
+ TexCoord1 = ToRotatedPoissonTexCoord( poisson1, TexCoord, incVec, rotMatrix );
+ TexCoord2 = ToRotatedPoissonTexCoord( poisson2, TexCoord, incVec, rotMatrix );
+ TexCoord3 = ToRotatedPoissonTexCoord( poisson3, TexCoord, incVec, rotMatrix );
+ TexCoord4 = ToRotatedPoissonTexCoord( poisson4, TexCoord, incVec, rotMatrix );
+ TexCoord5 = ToRotatedPoissonTexCoord( poisson5, TexCoord, incVec, rotMatrix );
+ TexCoord6 = ToRotatedPoissonTexCoord( poisson6, TexCoord, incVec, rotMatrix );
+ TexCoord7 = ToRotatedPoissonTexCoord( poisson7, TexCoord, incVec, rotMatrix );
+}
+// No op
+void vert ()
+{
+ SetupPoissonBlurCoordsRotation( 5.0 * get_blur_falloff(), Texture0Info.xy, 0.0);
+}
+ </VertexShader>
+ <FragmentShader>
+
+float cutoff( float color )
+{
+ return color >= BloomThreshold ? color : 0.0;
+}
+vec4 cutoffColor( sampler2D inSampler, vec2 texCoord )
+{
+ vec4 color = GetTextureValue(inSampler, texCoord, 1.0);
+ vec3 exposed_color = color.xyz * get_exposure();
+ vec3 cutoff_color = vec3( cutoff( color.x ), cutoff( color.y ), cutoff( color.z ) );
+ float pixelMult = dot( cutoff_color, cutoff_color ) > 0.0 ? 1.0 : 0.0;
+ return vec4( exposed_color.xyz, color.a ) * pixelMult;
+}
+
+vec4 PoissonBlur(sampler2D inSampler )
+{
+ //flatten out the poisson for this step, we really just want to smear.
+ float mult0 = 1.0;
+ float mult1 = mult0;
+ float mult2 = mult0;
+ float mult3 = mult2;
+ float mult4 = mult2;
+ float mult5 = mult2;
+ float mult6 = mult2;
+ float mult7 = mult2;
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6 + mult7;
+ float multMultiplier = ( multTotal > 0.0 ? 1.0 / multTotal : 0.0 );
+
+ vec4 outColor = cutoffColor( inSampler, TexCoord0 ) * (mult0 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord1 ) * (mult1 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord2 ) * (mult2 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord3 ) * (mult3 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord4 ) * (mult4 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord5 ) * (mult5 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord6 ) * (mult6 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord7 ) * (mult7 * multMultiplier);
+ return outColor;
+}
+
+void frag() // Luminosity pass with exponential color channel decay based on the threshold above.
+{
+ gl_FragColor = PoissonBlur( Texture0 );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLUR">
+ <VertexShader>
+
+vec2 ToRotatedPoissonTexCoord( vec3 poisson, vec2 inputTex, vec2 inc, mat2 rotation )
+{
+ vec2 rotatedPoisson = rotation * vec2( poisson.xy );
+ return vec2( inputTex.x + rotatedPoisson.x * inc.x, inputTex.y + rotatedPoisson.y * inc.y );
+}
+
+void SetupPoissonBlurCoordsRotation(float inBlurAmount, vec2 inTexInfo, float inRotationRadians )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ float rotCos = cos( inRotationRadians );
+ float rotSin = sin( inRotationRadians );
+ mat2 rotMatrix = mat2( rotCos, rotSin, -rotSin, rotCos );
+ vec2 incVec = vec2( incX, incY );
+
+ TexCoord0 = ToRotatedPoissonTexCoord( poisson0, TexCoord, incVec, rotMatrix );
+ TexCoord1 = ToRotatedPoissonTexCoord( poisson1, TexCoord, incVec, rotMatrix );
+ TexCoord2 = ToRotatedPoissonTexCoord( poisson2, TexCoord, incVec, rotMatrix );
+ TexCoord3 = ToRotatedPoissonTexCoord( poisson3, TexCoord, incVec, rotMatrix );
+ TexCoord4 = ToRotatedPoissonTexCoord( poisson4, TexCoord, incVec, rotMatrix );
+ TexCoord5 = ToRotatedPoissonTexCoord( poisson5, TexCoord, incVec, rotMatrix );
+ TexCoord6 = ToRotatedPoissonTexCoord( poisson6, TexCoord, incVec, rotMatrix );
+ TexCoord7 = ToRotatedPoissonTexCoord( poisson7, TexCoord, incVec, rotMatrix );
+}
+
+void vert ()
+{
+ SetupPoissonBlurCoordsRotation( PoissonDistance, Texture0Info.xy, PoissonRotation);
+}
+ </VertexShader>
+ <FragmentShader>
+vec4 PoissonBlur(sampler2D inSampler )
+{
+ float mult0 = (1.0 - poisson0.z);
+ float mult1 = (1.0 - poisson1.z);
+ float mult2 = (1.0 - poisson2.z);
+ float mult3 = (1.0 - poisson3.z);
+ float mult4 = (1.0 - poisson4.z);
+ float mult5 = (1.0 - poisson5.z);
+ float mult6 = (1.0 - poisson6.z);
+ float mult7 = (1.0 - poisson7.z);
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6 + mult7;
+ float multMultiplier = ( multTotal > 0.0 ? 1.0 / multTotal : 0.0 ) * get_blur_falloff();
+
+ vec4 outColor = GetTextureValue( inSampler, TexCoord0, 1.0 ) * (mult0 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord1, 1.0 ) * (mult1 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord2, 1.0 ) * (mult2 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord3, 1.0 ) * (mult3 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord4, 1.0 ) * (mult4 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord5, 1.0 ) * (mult5 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord6, 1.0 ) * (mult6 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord7, 1.0 ) * (mult7 * multMultiplier);
+ return outColor;
+}
+
+void frag()
+{
+ //Passing in 1.0 means the value will not get alpha-multiplied again
+ gl_FragColor = PoissonBlur( Texture0 );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="COMBINER">
+ <FragmentShader>
+ /*
+
+float GetAdaptedLuminance( sampler2D inSampler )
+{
+
+ vec3 col = textureLod( inSampler, TexCoord, TonemappingLod).rgb;
+ return luminance( col );
+}
+
+vec3 GetTonemappedReinhard( sampler2D inSampler, vec3 inSource, vec3 inBlurred )
+{
+ // adapted luminance value
+ float adpLm = GetAdaptedLuminance( inSampler );
+ // luminance of current color
+ float curLm = luminance( inSource.rgb );
+ // relative luminance
+ float relLm = Key/adpLm;
+ // displayable value D
+ float D = (relLm * (1.0 + relLm/(expLum*expLum)) / (1.0 + relLm));
+ // tone map result
+ vec3 color = inBlurred.xyz * relLm;
+ //vec3 gamaColor = pow(color, vec3(1.0/2.2));
+
+ //return gamaColor;
+ return vec3(relLm, relLm, relLm );
+}
+
+vec3 GetTonemappedReinhardSimple( vec3 inSource, vec3 inBlurred )
+{
+ vec3 texColor = inBlurred * 1.0; // Hardcoded Exposure Adjustment
+ texColor = texColor/(1.0 + texColor);
+ vec3 retColor = pow( texColor, vec3(1.0/2.2) );
+ return retColor;
+}
+*/
+
+void frag()
+{
+ vec4 sourceColor = texture2D_0(TexCoord);
+
+
+ vec4 summation = texture2D_Downsample2(TexCoord)
+ + texture2D_Downsample4(TexCoord);
+
+ vec3 bloom_result = sourceColor.xyz * get_exposure() + summation.xyz;
+
+ //Threshold defines the white point for the image which shouldn't be adaptive.
+ vec3 thresholded = clamp( bloom_result.xyz, 0.0, ChannelThreshold ) / ChannelThreshold;
+
+ vec3 tonemapped = pow( thresholded, vec3( 1.0 / GammaValue ) );
+
+ vec3 final_color = mix( thresholded, tonemapped, TonemappingLerp );
+
+ float resultAlpha = max( summation.a, sourceColor.a );
+
+ gl_FragColor = vec4( final_color, resultAlpha );
+
+ /*
+ gl_FragColor = vec4( texture2D_Downsample2(TexCoord).xyz
+ , 1.0 );
+ */
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="Passthrough">
+ <VertexShader>
+void vert ()
+{
+}
+ </VertexShader>
+ <FragmentShader>
+void frag()
+{
+ //Passing in 1.0 means the value will not get alpha-multiplied again
+ gl_FragColor = GetTextureValue( Texture0, TexCoord, 1.0 );
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="luminosity_buffer2" format="source" filter="linear" wrap="clamp" size=".5" lifetime="scene"/>
+ <Buffer name="downsample_buffer2" format="source" filter="linear" wrap="clamp" size=".5" lifetime="scene"/>
+ <Buffer name="downsample_buffer4" format="source" filter="linear" wrap="clamp" size=".25" lifetime="scene"/>
+ <Pass shader="LUMINOSITY" input="[source]" output='downsample_buffer2' >
+ </Pass>
+ <Pass shader="LUMINOSITY" input="downsample_buffer2" output='luminosity_buffer2' >
+ </Pass>
+ <!--<Pass shader='Passthrough' input='luminosity_buffer2' />-->
+
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer2">
+ <SetParam name="PoissonDistance" value="4"/>
+ <SetParam name="PoissonRotation" value="0"/>
+ </Pass>
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer4">
+ <SetParam name="PoissonDistance" value="4"/>
+ <SetParam name="PoissonRotation" value="0.62831"/>
+ </Pass>
+ <Pass shader="COMBINER" input="[source]">
+ <BufferInput param="Downsample2" value="downsample_buffer2"/>
+ <BufferInput param="Downsample4" value="downsample_buffer4"/>
+ <RenderState name="Stencil" value="false"/>
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/LightTable.effect b/Studio/Content/Effect Library/LightTable.effect
new file mode 100644
index 00000000..083ec84d
--- /dev/null
+++ b/Studio/Content/Effect Library/LightTable.effect
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="SurfDist" formalName="Distance to Surface" description="Distance from camera to the paper surface" default="100"/>
+ <Property name="BlurDist" formalName="Distance to Full Blur" description="Distance from the paper surface that corresponds to fully blurred" default="100"/>
+ <Property name="MaxBlur" formalName="Max Blur Radius" description="Blur radius defined as 'full blur'" min="1" max="100" default="50"/>
+ <Property name="OverlayDif" formalName="Diffuse Texture" description="Texture overlay color for the paper surface" type="Texture" clamp="repeat" />
+ <Property name="OverlayTrn" formalName="Translucent Texture" description="Texture overlay translucency for the paper surface" type="Texture" clamp="repeat" />
+ <Property name="OverlayNrm" formalName="Normal Texture" description="Texture overlay normal for the paper surface" type="Texture" clamp="repeat" />
+ <Property name="OverlayScale" formalName="Texture Scale" description="Texture overlay scaling factor" type="Float2" default="1 1"/>
+ <Property name="OverlayRot" formalName="Texture Rotation" description="Texture overlay rotation angle" default="0" min="0" max="360"/>
+ <Property name="OverlayTrans" formalName="Translucency blocking" description="How much translucency through the overlay" default="2.0"/>
+ <Property name="LightCol" formalName="Light Color" description="Color of the backlight" type="Color" default="1 1 1"/>
+ <Property name="LightBrt" formalName="Light Brightness" description="Brightness of the backlight" default="1.0"/>
+ <Property name="LightExp" formalName="Light Exposure" descriptoin="Pre-emptive exposure operation to prevent blowout" default="1.0"/>
+
+ <Property name="DimplePos" formalName="Dimple Position" description="On-screen position of a depth 'pressure dimple'" type="Float2" default="0 0"/>
+ <Property name="DimpleDepth" formalName="Dimple Pressure" description="How deep the 'pressure dimple' goes" default="0"/>
+ <Property name="DimpleSize" formalName="Dimple Size" description="How big the pressure dimple is in onscreen pixels" default="1" min="1" max="1000"/>
+
+ <!-- Internal buffers plus a few extra options -->
+ <Property name="DepthSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="DistBuffer" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="BlurBuffer" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="SrcSampler" type="Texture" filter="linear" clamp="clamp"/>
+ <Property name="HalfSampler" type="Texture" filter="linear" clamp="clamp"/>
+ <Property name="BlurDebug" formalName="Debug Blur Amt" type="Boolean" default="False"/>
+ <Property name="DepthDebug" formalName="Debug Depth Map" type="Boolean" default="False"/>
+ </MetaData>
+<Shaders>
+ <Shared>
+#include "depthpass.glsllib"
+
+uniform vec2 CameraClipRange;
+ </Shared>
+ <Shader name="DOWNSAMPALPHA">
+ <FragmentShader>
+void frag()
+{
+ // Simple averaging blur, but makes sure to include the alpha channel from the blur weights
+ // Only need to do this once to actually set the alphas in the blur buffers.
+ vec4 smp0 = textureOffset(Texture0, TexCoord.xy, ivec2(-1,-1));
+ vec4 smp1 = textureOffset(Texture0, TexCoord.xy, ivec2(0,-1));
+ vec4 smp2 = textureOffset(Texture0, TexCoord.xy, ivec2(-1,0));
+ vec4 smp3 = texture(Texture0, TexCoord.xy);
+
+ smp0.w *= textureOffset(DistBuffer, TexCoord.xy, ivec2(-1,-1)).w;
+ smp1.w *= textureOffset(DistBuffer, TexCoord.xy, ivec2(0,-1)).w;
+ smp2.w *= textureOffset(DistBuffer, TexCoord.xy, ivec2(-1,0)).w;
+ smp3.w *= texture(DistBuffer, TexCoord.xy).w;
+
+ gl_FragColor = 0.25 * (smp0 + smp1 + smp2 + smp3);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="DOWNSAMPLE">
+ <FragmentShader>
+void frag() // Simple averaging blur.
+{
+ vec4 smp0 = textureOffset(Texture0, TexCoord.xy, ivec2(-1,-1));
+ vec4 smp1 = textureOffset(Texture0, TexCoord.xy, ivec2(0,-1));
+ vec4 smp2 = textureOffset(Texture0, TexCoord.xy, ivec2(-1,0));
+ vec4 smp3 = texture(Texture0, TexCoord.xy);
+
+ gl_FragColor = 0.25 * (smp0 + smp1 + smp2 + smp3);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="FINDBLURAMT">
+ <FragmentShader>
+void frag()
+{
+ float planeDepth = SurfDist;
+
+ vec2 dvec = gl_FragCoord.xy - vec2(DimplePos);
+ float dimple = dot(dvec, dvec) / (DimpleSize * DimpleSize);
+ planeDepth += exp2(-dimple) * DimpleDepth;
+
+ vec4 depthSample = texture(DepthSampler, TexCoord);
+ float depthVal = getDepthValue( depthSample, CameraClipRange );
+ float rawDepth = depthValueToLinearDistance( depthVal, CameraClipRange );
+
+ if (DepthDebug)
+ {
+ gl_FragColor = vec4( (rawDepth - CameraClipRange.x) / (CameraClipRange.y - CameraClipRange.x) );
+ return;
+ }
+
+ float blurAmt = smoothstep(0.0, 1.0, (rawDepth - planeDepth) / BlurDist);
+ gl_FragColor = vec4(blurAmt, blurAmt, blurAmt, 1.0 - blurAmt);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLURX">
+ <FragmentShader>
+void frag()
+{
+ vec4 smp = texture(DistBuffer, TexCoord.xy);
+ float sigma = clamp(smp.x * MaxBlur * 0.25, 1.0, 25.0);
+ int smpCount = int(ceil( sigma ));
+ vec4 value = texture(BlurBuffer, TexCoord.xy);
+ float wtsum = 1.0;
+ for (int i = 1; i &lt;= smpCount; ++i)
+ {
+ // Base 2 Gaussian blur
+ float wt = float(i) / (sigma * 0.5);
+ wt = exp2( -wt*wt );
+ value += wt * textureOffset(BlurBuffer, TexCoord.xy, ivec2(-i,0));
+ value += wt * textureOffset(BlurBuffer, TexCoord.xy, ivec2(i,0));
+ wtsum += wt * 2.0;
+ }
+
+ gl_FragColor = value / wtsum;
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLURY">
+ <FragmentShader>
+void frag()
+{
+ vec4 smp = texture(DistBuffer, TexCoord.xy);
+
+ float sigma = clamp(smp.x * MaxBlur * 0.25, 1.0, 25.0);
+ int smpCount = int(ceil( sigma ));
+ vec4 value = texture(BlurBuffer, TexCoord.xy);
+ value.w *= smp.w;
+ float wtsum = 1.0;
+ for (int i = 1; i &lt;= smpCount; ++i)
+ {
+ // Base 2 Gaussian blur
+ float wt = float(i) / (sigma * 0.5);
+ wt = exp2( -wt*wt );
+ value += wt * textureOffset(BlurBuffer, TexCoord.xy, ivec2(0,-i));
+ value += wt * textureOffset(BlurBuffer, TexCoord.xy, ivec2(0,i));
+ wtsum += wt * 2.0;
+ }
+
+ gl_FragColor = value / wtsum;
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="COMBINE">
+ <FragmentShader>
+void frag()
+{
+ float blurFac = texture(DistBuffer, TexCoord.xy).x;
+ float lod = log2(MaxBlur * blurFac);
+ float fac0 = clamp(lod, 0.0, 1.0);
+ float fac1 = clamp(lod-1.0, 0.0, 1.0);
+
+ if (BlurDebug || DepthDebug)
+ {
+ gl_FragColor = vec4(blurFac);
+ return;
+ }
+
+ vec4 result = texture(SrcSampler, TexCoord.xy);
+ vec4 lvl1 = texture(HalfSampler, TexCoord.xy);
+ vec4 fullBlr = texture(BlurBuffer, TexCoord.xy);
+
+ // Basically this says that if the blur factor is really small (less than 2 pixels)
+ // we favor the full resolution. If it's between 2 and 4 pixels, we favor the half-res
+ // version (which is like one mip level down)... anything beyond that, we use the bottom
+ // level which actually has the proper local blur.
+ result = mix(mix(result, lvl1, fac0), fullBlr, fac1);
+
+ // Transform the texture (assuming rotation about the center of the texture)
+ float cosX = cos(OverlayRot * 0.01745329251);
+ float sinX = sin(OverlayRot * 0.01745329251);
+ mat3x3 texMat = mat3x3( 1.0, 0.0, -0.5, 0.0, 1.0, -0.5, 0.0, 0.0, 1.0 );
+ texMat *= mat3x3( cosX, -sinX, 0.0, sinX, cosX, 0.0, 0.0, 0.0, 1.0);
+ texMat *= mat3x3( 1.0, 0.0, 0.5, 0.0, 1.0, 0.5, 0.0, 0.0, 1.0 );
+ texMat *= mat3x3( OverlayScale.x, 0.0, 0.0, 0.0, OverlayScale.y, 0.0, 0.0, 0.0, 1.0);
+ vec3 texForm = texMat * vec3(TexCoord.xy, 1.0);
+ vec4 overSmp = texture(OverlayDif, texForm.xy);
+ float overTrn = 1.0 - texture(OverlayTrn, texForm.xy).x;
+ float nDotL = (texture(OverlayNrm, texForm.xy).z - 0.5) * 2.0;
+
+ // Want to see how much of a "difference" there is between the light
+ // color and the object color.
+ // We are basically acting as if the objects on the layer are occluders
+ // so the alpha as a result of blurring is like a transparency.
+ // The behavior is that the brighter the light is, the more of a "gap" there is
+ vec3 backlight = LightCol * LightBrt;
+
+ // Assume that the color map I'm using already tells us what N.dot.L is (for now)
+ float translucency = exp2( -overTrn * OverlayTrans );
+
+// vec3 colorDelta = backlight - result.rgb;
+// float deltaC = dot(colorDelta, colorDelta) * (1.0 - result.w) * LightBrt / LightExp;
+// result.rgb -= result.rgb * smoothstep(deltaC, 1.0, result.w);
+
+// gl_FragColor = vec4( result.rgb, 1.0 );
+// return;
+
+ backlight *= mix(vec3(1.0), result.rgb, result.w);
+ backlight *= nDotL * translucency * overSmp.rgb;
+
+ backlight = vec3(1.0) - exp2(-6.28*backlight/LightExp);
+
+ gl_FragColor = vec4(backlight, 1.0);
+}
+ </FragmentShader>
+ </Shader>
+</Shaders>
+<Passes>
+ <Buffer name="halfBuffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".5" lifetime="frame"/>
+ <Buffer name="qtrBuffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".25" lifetime="frame"/>
+ <Buffer name="tempqtr" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".25" lifetime="frame"/>
+ <Buffer name="blurweights" type="ubyte" format="rgba" filter="linear" wrap="clamp" size="1" lifetime="frame"/>
+ <Pass shader="FINDBLURAMT" output="blurweights">
+ <DepthInput param="DepthSampler"/>
+ </Pass>
+ <Pass shader="DOWNSAMPALPHA" input="[source]" output="halfBuffer">
+ <BufferInput param="DistBuffer" value="blurweights" />
+ </Pass>
+ <Pass shader="DOWNSAMPLE" input="halfBuffer" output="qtrBuffer"/>
+ <Pass shader="BLURX" output="tempqtr">
+ <BufferInput param="BlurBuffer" value="qtrBuffer" />
+ <BufferInput param="DistBuffer" value="blurweights" />
+ </Pass>
+ <Pass shader="BLURY" output="qtrBuffer">
+ <BufferInput param="BlurBuffer" value="tempqtr" />
+ <BufferInput param="DistBuffer" value="blurweights" />
+ </Pass>
+ <Pass shader="COMBINE">
+ <BufferInput param="SrcSampler" value="[source]" />
+ <BufferInput param="HalfSampler" value="halfBuffer" />
+ <BufferInput param="BlurBuffer" value="qtrBuffer" />
+ <BufferInput param="DistBuffer" value="blurweights" />
+ </Pass>
+</Passes>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/Motion Blur.effect b/Studio/Content/Effect Library/Motion Blur.effect
new file mode 100644
index 00000000..1dff00b1
--- /dev/null
+++ b/Studio/Content/Effect Library/Motion Blur.effect
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Create an apparent streaking for rapidly moving objects in the layer.-->
+ <Property name="fadeAmount" formalName="Fade Amount" min="0" max="1" default=".05" description="0=object trails persist, 1.0=object trails fade out immediately (no trail)" />
+ <Property name="GlowSampler" type="Texture" filter="nearest" clamp="clamp" />
+ <Property name="Sprite" type="Texture" filter="nearest" clamp="clamp" />
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+ </Shared>
+
+ <Shader name="HBLUR">
+ <VertexShader>
+void vert()
+{
+ SetupHorizontalGaussianBlur3Tap( Texture0Info.x, 1.0, TexCoord );
+}
+ </VertexShader>
+ <FragmentShader>
+void frag()
+{
+ vec4 src = texture2D_0(TexCoord);
+
+ float Trailfade = 1.0 - fadeAmount;
+ vec4 OutCol = GaussianBlur3TapPremultiplied( GlowSampler ) * Trailfade;
+
+ // change the color so that it looks different. saturate it a bit.
+ float srcSum = dot(vec3(1.0), src.rgb);
+ src.rgb = src.rgb * 0.7 + vec3(srcSum,srcSum,srcSum) * 0.3;
+ gl_FragColor.rgb = (1.0 - src.a) * OutCol.rgb + src.rgb;
+ gl_FragColor.a = src.a + OutCol.a;
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="VBLUR">
+ <VertexShader>
+void vert()
+{
+ SetupVerticalGaussianBlur3Tap( Texture0Info.y, 1.0, TexCoord );
+}
+ </VertexShader>
+ <FragmentShader>
+void frag() // PS_Blur_Vertical
+{
+ vec4 OutCol = GaussianBlur3TapPremultiplied( Texture0 );
+ gl_FragColor = OutCol;
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLEND">
+ <FragmentShader>
+void frag()
+{
+ vec4 src = texture2D_0(TexCoord);
+ vec4 dst = texture2D_Sprite(TexCoord);
+
+ colorOutput(src * (1.0-dst.a) + dst);
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="glow_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".25" lifetime="scene"/>
+ <Buffer name="temp_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".25" lifetime="frame"/>
+
+ <Pass name="1" shader="HBLUR" input="[source]" output="temp_buffer">
+ <BufferInput param="GlowSampler" value="glow_buffer"/>
+ </Pass>
+ <Pass name="2" shader="VBLUR" input="temp_buffer" output="glow_buffer"/>
+ <Pass name="pass3_Composite" shader="BLEND" input="glow_buffer">
+ <BufferInput param="Sprite" value="[source]"/>
+ </Pass>
+ </Passes>
+</Effect>
diff --git a/Studio/Content/Effect Library/SCurveTonemap.effect b/Studio/Content/Effect Library/SCurveTonemap.effect
new file mode 100644
index 00000000..fc0259b8
--- /dev/null
+++ b/Studio/Content/Effect Library/SCurveTonemap.effect
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="Shoulder" formalName="Shoulder Slope" type="Float" default="1" min="0" max="3"/>
+ <Property name="ShoulderWt" formalName="Shoulder Emphasis" type="Float" default="0" min="-1" max="1"/>
+ <Property name="Toe" formalName="Toe Slope" type="Float" default="1" min="0" max="3"/>
+ <Property name="ToeWt" formalName="Toe Emphasis" type="Float" default="0" min="-1" max="1"/>
+ <Property name="Contrast" formalName="Contrast Boost" type="Float" default="0" min="-1" max="2"/>
+ <Property name="Saturation" formalName="Saturation Level" type="Float" default="1" min="0" max="2"/>
+ <Property name="GammaValue" formalName="Gamma" type="Float" default="2.2" min="0.1" max="8"/>
+ <Property name="UseExposure" formalName="Use Exposure" type="Boolean" default="False"/>
+ <Property name="WhiteVal" formalName="White Point" type="Float" default="1.0" min="0.01" max="128.0">
+ <ShowIfEqual property="UseExposure" value="False"/>
+ </Property>
+ <Property name="ExposeVal" formalName="Exposure Value" type="Float" default="1.0" min="0.01" max="16.0">
+ <ShowIfEqual property="UseExposure" value="True"/>
+ </Property>
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "luminance.glsllib"
+
+float remapLum( float inLum, float whitePt )
+{
+ return clamp( inLum / whitePt, 0.0, 1.0 );
+}
+
+float exposeLum( float inLum, float exposure )
+{
+ return 1.0 - exp2( -inLum / exposure );
+}
+
+vec3 gammaCorrect( vec3 inColor, float gammaExp )
+{
+ return pow( inColor, vec3( 1.0 / gammaExp ) );
+}
+
+vec3 adjSaturation( vec3 inRGB, float satFactor )
+{
+ // Must be done in linear space (before gamma correction)
+ float P = sqrt( luminance( inRGB * inRGB ) );
+ vec3 outCol;
+ outCol = (inRGB - vec3(P)) * satFactor;
+ outCol += vec3(P);
+ return outCol;
+}
+
+ </Shared>
+<Shader name="TONEMAP">
+<FragmentShader>
+float curveCompute( float inLum, float slope0, float slope1 )
+{
+ float a1 = slope0;
+ float a2 = 3.0 - 2.0 * slope0 - slope1;
+ float a3 = slope1 + slope0 - 2.0;
+
+ // Cubic curve fit. This results in a curve that is 0 where inColor is 0
+ // equals 1 when inColor is 1, and the derivative at 0 is slope0 and the
+ // derivative at 1 is slope1
+ return ((((a3 * inLum) + a2)*inLum) + a1)*inLum;
+}
+
+float toeEmphasize( float inParam )
+{
+ float a1 = 1.0 - ToeWt;
+ float a2 = 2.0 * ToeWt;
+ float a3 = -ToeWt;
+
+ return ((((a3 * inParam) + a2) * inParam) + a1) * inParam;
+}
+
+float shoulderEmphasize( float inParam )
+{
+ float a1 = 1.0;
+ float a2 = ShoulderWt;
+ float a3 = -ShoulderWt;
+
+ return ((((a3 * inParam) + a2) * inParam) + a1) * inParam;
+}
+
+void frag()
+{
+ // k = shadow slope, m = midtone slope, n = highlight slope
+ float k = Toe;
+ float m = 1.0 + Contrast;
+ float n = Shoulder;
+
+ //vec4 sourceColor = texture(SourceSampler, TexCoord);
+ vec4 sourceColor = texture(Texture0, TexCoord);
+ vec3 sourceSep = RGBToYPbPr(sourceColor.rgb);
+
+ float lum = sourceSep.r;
+
+ if (UseExposure)
+ lum = exposeLum( lum, ExposeVal );
+ else
+ lum = remapLum( lum, WhiteVal );
+
+ float param0 = toeEmphasize( 2.0 * lum ); // Parametrization for Curve Part 1
+ float param1 = shoulderEmphasize( 2.0 * lum - 1.0 ); // Parametrization for Curve Part 2
+
+ float lum0 = 0.5 * curveCompute( param0, k, m );
+ float lum1 = 0.5 * curveCompute( param1, m, n ) + 0.5;
+ sourceSep.r = (lum > 0.5) ? lum1 : lum0;
+
+ // Convert back to RGB and gamma correct
+ vec3 finalColor = YPbPrToRGB( sourceSep );
+ finalColor = gammaCorrect( adjSaturation( finalColor, Saturation ), GammaValue );
+ gl_FragColor = vec4( finalColor, sourceColor.a );
+}
+</FragmentShader>
+</Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="TONEMAP" input="[source]" />
+ </Passes>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/SMAA1X.effect b/Studio/Content/Effect Library/SMAA1X.effect
new file mode 100644
index 00000000..f4f353a0
--- /dev/null
+++ b/Studio/Content/Effect Library/SMAA1X.effect
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="searchTex" filter="nearest" clamp="clamp" type="Texture" default="./maps/effects/SearchTex-yflipped.png" hidden="True"/>
+ <Property name="areaTex" filter="linear" clamp="clamp" type="Texture" default="./maps/effects/AreaTex-yflipped.dds" hidden="True"/>
+ <Property name="blendTex" filter="linear" clamp="clamp" type="Texture" hidden="True"/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+vec2 pixelIncrements;
+#define SMAA_PIXEL_SIZE pixelIncrements
+#define SMAA_HLSL_3 0
+#define SMAA_HLSL_4 0
+#define SMAA_HLSL_4_1 0
+#define SMAA_GLSL_3 1
+#define SMAA_GLSL_4 0
+#define SMAA_PRESET_LOW 0
+#define SMAA_PRESET_MEDIUM 0
+#define SMAA_PRESET_HIGH 1
+#define SMAA_PRESET_ULTRA 0
+#define SMAA_PRESET_CUSTOM 0
+ vec2 pixelSizes;
+ </Shared>
+ <Shader name="EdgeDetect">
+ <VertexShader>
+#define SMAA_ONLY_COMPILE_PS 0
+#include "SMAA.glsllib"
+
+out float4 svPosition;
+out float4 offset[3];
+
+void vert ()
+{
+ pixelIncrements = vec2( 1.0 / Texture0Info.x, 1.0 / Texture0Info.y );
+ float4 tempOffset[3];
+ float4 tempPos;
+ SMAAEdgeDetectionVS(gl_Position, tempPos, TexCoord, tempOffset);
+
+ offset[0] = tempOffset[0];
+ offset[1] = tempOffset[1];
+ offset[2] = tempOffset[2];
+ svPosition = tempPos;
+}
+ </VertexShader>
+ <FragmentShader>
+#define SMAA_ONLY_COMPILE_PS 1
+#include "SMAA.glsllib"
+
+in float4 svPosition;
+in float4 offset[3];
+
+
+void frag()
+{
+ pixelIncrements = vec2( 1.0 / Texture0Info.x, 1.0 / Texture0Info.y );
+ gl_FragColor = SMAALumaEdgeDetectionPS(TexCoord, offset, Texture0);
+}
+ </FragmentShader>
+ </Shader>
+
+ <Shader name="BlendingWeightCalculation">
+
+ <VertexShader>
+#define SMAA_ONLY_COMPILE_PS 0
+#include "SMAA.glsllib"
+out float4 svPosition;
+out float4 offset[3];
+out float2 pixcoord;
+void vert()
+{
+ pixelIncrements = vec2( 1.0 / Texture0Info.x, 1.0 / Texture0Info.y );
+ float4 tempOffset[3];
+ float4 tempPos;
+ float2 tempPixCoord;
+ SMAABlendingWeightCalculationVS(gl_Position, tempPos, TexCoord, tempPixCoord, tempOffset);
+
+
+ offset[0] = tempOffset[0];
+ offset[1] = tempOffset[1];
+ offset[2] = tempOffset[2];
+ svPosition = tempPos;
+ pixcoord = tempPixCoord;
+}
+ </VertexShader>
+ <FragmentShader>
+#define SMAA_ONLY_COMPILE_PS 1
+#include "SMAA.glsllib"
+in float4 svPosition;
+in float4 offset[3];
+in float2 pixcoord;
+//Required for temporal
+int4 subsampleIndices;
+
+void frag()
+{
+ pixelIncrements = vec2( 1.0 / Texture0Info.x, 1.0 / Texture0Info.y );
+ gl_FragColor = SMAABlendingWeightCalculationPS(TexCoord, pixcoord, offset, Texture0, areaTex, searchTex, subsampleIndices);
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="NeighborhoodBlending">
+ <VertexShader>
+#define SMAA_ONLY_COMPILE_PS 0
+#include "SMAA.glsllib"
+
+out float4 svPosition;
+out float4 offset[2];
+
+void vert ()
+{
+ pixelIncrements = vec2( 1.0 / Texture0Info.x, 1.0 / Texture0Info.y );
+ float4 tempOffset[2];
+ float4 tempPos;
+ SMAANeighborhoodBlendingVS(gl_Position, tempPos, TexCoord, tempOffset);
+ offset[0] = tempOffset[0];
+ offset[1] = tempOffset[1];
+ svPosition = tempPos;
+}
+ </VertexShader>
+ <FragmentShader>
+#define SMAA_ONLY_COMPILE_PS 1
+#include "SMAA.glsllib"
+
+in float4 svPosition;
+in float4 offset[2];
+void frag()
+{
+ pixelIncrements = vec2( 1.0 / Texture0Info.x, 1.0 / Texture0Info.y );
+ gl_FragColor = SMAANeighborhoodBlendingPS(TexCoord, offset, Texture0, blendTex);
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="edges_buffer" type="ubyte" format="rg" filter="linear" wrap="clamp" lifetime="scene"/>
+ <Buffer name="blend_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" lifetime="scene"/>
+ <Buffer name="stencil_buffer" format='depth24stencil8' lifetime="frame" />
+ <Pass shader="EdgeDetect" input='[source]' output='edges_buffer'>
+ <DepthStencil buffer='stencil_buffer' flags='clear-stencil' stencil-fail='replace' depth-fail='replace' depth-pass='replace' stencil-function='always' reference='1'/>
+ </Pass>
+ <Pass shader="BlendingWeightCalculation" input='edges_buffer' output='blend_buffer' >
+ <DepthStencil buffer='stencil_buffer' stencil-fail='keep' depth-fail='keep' depth-pass='keep' stencil-function='equal' reference='1'/>
+ </Pass>
+ <Pass shader='NeighborhoodBlending' input='[source]' >
+ <BufferInput param='blendTex' value="blend_buffer"/>
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/Screen Space AO.effect b/Studio/Content/Effect Library/Screen Space AO.effect
new file mode 100644
index 00000000..acc34cda
--- /dev/null
+++ b/Studio/Content/Effect Library/Screen Space AO.effect
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="FilterSize" formalName="Filter Size" description="Range to shoot samples for conversion" default="4"/>
+ <Property name="DistScale" formalName="Distance Scale" description="Divisor for distances during filtering -- larger equals more subtle" default="8"/>
+ <Property name="DistBias" formalName="Distance Bias" description="Depth bias to prevent self-shadowing artifacts" default="1"/>
+ <Property name="DebugView" formalName="Debug SSAO effect" type="Boolean" description="Allows you to see the effect of the filter directly to help setup parameters" default="False"/>
+ <Property name="DepthSampler" type="Texture" filter="nearest" clamp="clamp"/>
+ <Property name="SourceSampler" type="Texture" filter="linear" clamp="clamp"/>
+ </MetaData>
+
+ <Shaders>
+
+ <Shader name="SSAO">
+ <FragmentShader>
+#include "depthpass.glsllib"
+uniform vec2 CameraClipRange;
+
+void frag( void )
+{
+ float ret = 16.0;
+
+ vec3 kernel[16];
+
+ // Not particularly random set of samples, I know, which means some risk
+ // of artifacts due to regularity.
+ kernel[0] = vec3(0.355512, -0.709318, -0.102371);
+ kernel[1] = vec3(0.534186, 0.71511, -0.115167);
+ kernel[2] = vec3(-0.87866, 0.157139, -0.115167);
+ kernel[3] = vec3(0.140679, -0.475516, -0.0639818);
+ kernel[4] = vec3(-0.0796121, 0.158842, -0.677075);
+ kernel[5] = vec3(-0.0759516, -0.101676, -0.483625);
+ kernel[6] = vec3(0.12493, -0.0223423, -0.483625);
+ kernel[7] = vec3(-0.0720074, 0.243395, -0.967251);
+ kernel[8] = vec3(-0.207641, 0.414286, 0.187755);
+ kernel[9] = vec3(-0.277332, -0.371262, 0.187755);
+ kernel[10] = vec3(0.63864, -0.114214, 0.262857);
+ kernel[11] = vec3(-0.184051, 0.622119, 0.262857);
+ kernel[12] = vec3(0.110007, -0.219486, 0.435574);
+ kernel[13] = vec3(0.235085, 0.314707, 0.696918);
+ kernel[14] = vec3(-0.290012, 0.0518654, 0.522688);
+ kernel[15] = vec3(0.0975089, -0.329594, 0.609803);
+
+ ivec2 iCoords = ivec2( gl_FragCoord.xy + vec2(0.5, 0.5) );
+ float depth = getDepthValue(texelFetch(DepthSampler, iCoords, 0));
+ depth = depthValueToLinearDistance( depth, CameraClipRange );
+
+ for( int i = 15; i >= 0; --i )
+ {
+ // Note -- this cheap 2D trick is partially correct, but what we really need is to
+ // get the actual position, shoot the ray in 3d and re-project to get the actual
+ // 3D distance between points.
+ vec3 ray = kernel[i] * FilterSize;
+ ivec2 newSamp = ivec2( iCoords + ray.xy );
+ float sampleDepth = getDepthValue( texelFetch(DepthSampler, newSamp, 0) );
+ sampleDepth = depthValueToLinearDistance( sampleDepth, CameraClipRange );
+
+ // Occlusion is applied based on a Cauchy distribution filter
+ float occlDist = max(sampleDepth - depth - DistBias, 0.0) / DistScale;
+
+ // This gives us an occlusion based on distance where the closest stuff
+ // occludes the most, but the extra little subtraction of a yet tighter
+ // Cauchy lobe means that we avoid the super-close stuff in order to limit
+ // self occlusion. The 1.5 multiplier is to assure that the maximum possible
+ // effect of a given sample is 1.0 exactly.
+ float occlFactor = 1.0 / ( 1.0 + occlDist*occlDist*0.04 );
+ occlFactor -= 1.0 / ( 1.0 + occlDist*occlDist );
+ ret -= 1.5 * occlFactor;
+
+ }
+ ret /= 16.0;
+
+ vec4 backColor = texture2D_SourceSampler(TexCoord);
+ if (DebugView)
+ {
+ backColor = vec4( 1.0 );
+ }
+
+ gl_FragColor = vec4( ret,ret,ret, 1.0 ) * backColor;
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="SSAO">
+ <BufferInput value="[source]" param="SourceSampler" />
+ <DepthInput param="DepthSampler" />
+ </Pass>
+ </Passes>
+</Effect> \ No newline at end of file
diff --git a/Studio/Content/Effect Library/Sepia.effect b/Studio/Content/Effect Library/Sepia.effect
new file mode 100644
index 00000000..b3b92dee
--- /dev/null
+++ b/Studio/Content/Effect Library/Sepia.effect
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <!--Name of the effect is implicitly the file stem with extension -->
+ <!--Metadata stands for properties, events, and handlers and has the same format as the viewer's metadata file
+ and the data inserted at the top of lua files-->
+ <MetaData>
+ <!--Properties are automatically translated into the effect format when we generate the effect's GLSL file -->
+ <!--Colorizes the image to a faded brown color, simulating old film coloration.-->
+ <Property name="amount" formalName="Amount" min="0" max="1" default="1" description="0=no change to image, 1=full sepia effect." />
+ </MetaData>
+ <!-- default shader doesn't need to be named-->
+ <Shaders>
+ <!-- an implicit #include "effect.glsllib" is done at the top of all the produced shader files -->
+ <!-- Shared sections are pasted at the top of the files after the uniform declarations. Here you put your
+ varying declarations as well as functions that all the shaders need to use-->
+ <!--Sepia doesn't share anything so all of the shared sections could be omitted and you would get the same
+ code-->
+ <Shared></Shared>
+ <!--Shared data that you want all vertex shaders to see -->
+ <VertexShaderShared></VertexShaderShared>
+ <!--Shared data that you all fragment shaders to see -->
+ <FragmentShaderShared></FragmentShaderShared>
+ <!-- shaders can have names. No name means the shader gets its integer index as its name-->
+ <Shader name="main">
+ <!-- Shaders can also have Shared sections that are shared between the vertex and fragment shaders
+ of only precisely this shader-->
+ <!--no vertex shader or empty vertex shader means just output a vert(){} for the vertex shader-->
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+void frag()
+{
+ mat3 sepiaMat = mat3(0.0);
+
+ sepiaMat[0][0] = 0.393;
+ sepiaMat[1][0] = 0.769;
+ sepiaMat[2][0] = 0.189;
+
+ sepiaMat[0][1] = 0.349;
+ sepiaMat[1][1] = 0.686;
+ sepiaMat[2][1] = 0.168;
+
+ sepiaMat[0][2] = 0.272;
+ sepiaMat[1][2] = 0.534;
+ sepiaMat[2][2] = 0.131;
+
+ vec4 origColor = texture2D_0(TexCoord);
+ vec3 sepiaColor = sepiaMat*origColor.rgb;
+ sepiaColor = clamp( sepiaColor.rgb, 0.0, origColor.a );
+
+ colorOutput(vec4(mix( origColor.rgb, sepiaColor, amount ), origColor.a));
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <!-- if there is only one shader then we can assume there is only one pass and we can go from there -->
+ <!-- for this example, however, I am demonstrating the pass xml elements-->
+ <Passes>
+ <!-- single pass, input is the special source name and output is the special destination name which is assumed
+ for the last pass -->
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/Stylize - Scatter.effect b/Studio/Content/Effect Library/Stylize - Scatter.effect
new file mode 100644
index 00000000..b30df215
--- /dev/null
+++ b/Studio/Content/Effect Library/Stylize - Scatter.effect
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <!--Scatters the pixels in a layer, creating a blurry or smeared appearance. Without changing the color of each individual pixel, the Scatter effect redistributes the pixels randomly, but in the same general area as their original positions.-->
+ <Property name="NoiseSamp" formalName="Noise" filter="linear" clamp="repeat" type="Texture" default="./maps/effects/brushnoise.dds" hidden="True"/>
+ <Property name="Amount" formalName="Scatter Amount" min="0" max="127" default="20.0" description="Determines how much to scatter."/>
+ <Property name="dir" formalName="Grain" list="Both:Horizontal:Vertical" default="Both" description="The direction in which to scatter the pixels - horizontally or vertically. Select Both to scatter pixels in all directions."/>
+ <Property name="isRand" formalName="Randomize Every Frame" type="Boolean" default="False" description="Specifies whether scattering changes at each frame. To animate scattering without keyframes, select the Randomize Every Frame option."/>
+ </MetaData>
+ <Shaders>
+ <Shader>
+ <FragmentShader>
+uniform float AppFrame; // frame number since app starts
+void frag (void)
+{
+ float size = 15.0;
+ float amount = Amount / 127.0 * 0.4;
+
+ vec2 uv = TexCoord * size;
+ if (isRand)
+ uv = fract(uv + 0.031 * AppFrame);
+
+ uv = texture2D_NoiseSamp(fract(uv)).xy - 0.5;
+
+ if (dir == 0) { // both directions
+ uv *= (vec2(1.5, 0.15) * amount);
+
+ } else if (dir == 1) { // x direction
+ uv *= (vec2(1.3, 0.0) * amount);
+
+ } else { // y direction
+ uv *= (vec2(0.0, 0.29) * amount);
+ }
+
+ uv += TexCoord;
+
+ // shift half of a pixel size of the source to avoid the artifact on upper right borders.
+ // FBO size is bigger than the sprite, so clamping to [0, 1] will introduce artifacts
+ // (when OpenGL glTexParameter is set to linear). Lets not rely on OpenGL to clamp. we
+ // do it here.
+ vec2 halfPixelSize = 0.5 / Texture0Info.xy;
+ colorOutput(texture2D_0(clamp(uv, halfPixelSize, 1.0-halfPixelSize)));
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Effect>
diff --git a/Studio/Content/Effect Library/Tilt Shift.effect b/Studio/Content/Effect Library/Tilt Shift.effect
new file mode 100644
index 00000000..ac0423c3
--- /dev/null
+++ b/Studio/Content/Effect Library/Tilt Shift.effect
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="FocusPos" formalName="Focus Position" description="Height of the focus bar in normalized coordinates" min="0" max="1" default=".5"/>
+ <Property name="FocusWidth" formalName="Focus Width" description="Objects within this range of Focus Distance will be in focus" min="0" max="1" default=".2"/>
+ <Property name="BlurDebug" formalName="Debug Rendering" type="Boolean" description="Allows you to see exactly how the Focus variables work. Black objects are in focus, white are blurred" default="False"/>
+ <Property name="BlurAmount" formalName="Blur Amount" description="Increase the amount of blur. Amounts above 4 may cause artifacts" min="0" max="10" default="4" />
+ <Property name="SourceSampler" type="Texture" filter="linear" clamp="clamp"/>
+ <Property name="VerticalEffect" formalName="Vertical" type='Boolean' description="Makes the effect work vertically instead of horizontally" default="False"/>
+ <Property name="InvertBlur" formalName="Invert Blur" type="Boolean" description="Inverts the blur area so the center is blurred vs. the outer" default="False"/>
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+
+float AdvancedGetTiltShiftMultiplier(vec2 inTexCoord, float inFocusBarHeight, float inFocusWidth, bool inVertical, bool inInvert )
+{
+ //For now, you can't rotate the focus blur but in time you will be able to.
+ float texPos = inVertical ? inTexCoord.x : inTexCoord.y;
+ float focusDiff = max( 0.0, abs( texPos - inFocusBarHeight ) - (inFocusWidth/2.0) ) / inFocusWidth;
+ float retval = clamp( focusDiff, 0.0, 1.0 );
+ return inInvert ? 1.0 - retval : retval;
+}
+
+ </Shared>
+ <Shader name="DOWNSAMPLE">
+ <VertexShader>
+void vert()
+{
+ SetupBoxBlurCoords(vec2(Texture0Info.xy));
+}
+ </VertexShader>
+ <FragmentShader>
+
+vec4 AdvancedBoxTiltShiftBlur( sampler2D inBlurSampler, float inBlurSamplerAlphaFlag
+ , float inFocusBarHeight, float inFocusWidth
+ , bool inVertical, bool inInvert )
+{
+ float mult0 = .25 * AdvancedGetTiltShiftMultiplier( TexCoord0, inFocusBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult1 = .25 * AdvancedGetTiltShiftMultiplier( TexCoord1, inFocusBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult2 = .25 * AdvancedGetTiltShiftMultiplier( TexCoord2, inFocusBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult3 = .25 * AdvancedGetTiltShiftMultiplier( TexCoord3, inFocusBarHeight, inFocusWidth, inVertical, inInvert );
+ float multTotal = mult0 + mult1 + mult2 + mult3;
+ float totalDivisor = multTotal != 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = GetTextureValuePreMult(inBlurSampler, TexCoord0) * mult0;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord1) * mult1;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord2) * mult2;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord3) * mult3;
+ return OutCol * totalDivisor;
+}
+void frag() // Simple averaging box blur.
+{
+ gl_FragColor = AdvancedBoxTiltShiftBlur(Texture0, Texture0Info.z, FocusPos, FocusWidth, VerticalEffect, InvertBlur );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLUR">
+ <VertexShader>
+
+void vert()
+{
+ SetupPoissonBlurCoords( BlurAmount, DestSize.xy );
+}
+
+ </VertexShader>
+ <FragmentShader>
+
+vec4 AdvancedPoissonTiltShiftBlur(sampler2D inSampler, float inAlphaFlag, float inBarHeight, float inFocusWidth, bool inVertical, bool inInvert )
+{
+ float mult0 = (1.0 - poisson0.z) * AdvancedGetTiltShiftMultiplier( TexCoord0, inBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult1 = (1.0 - poisson1.z) * AdvancedGetTiltShiftMultiplier( TexCoord1, inBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult2 = (1.0 - poisson2.z) * AdvancedGetTiltShiftMultiplier( TexCoord2, inBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult3 = (1.0 - poisson3.z) * AdvancedGetTiltShiftMultiplier( TexCoord3, inBarHeight, inFocusWidth, inVertical, inInvert );
+ float mult4 = (1.0 - poisson4.z) * AdvancedGetTiltShiftMultiplier( TexCoord4, inBarHeight, inFocusWidth, inVertical, inInvert );
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+
+ vec4 outColor = GetTextureValuePreMult( inSampler, TexCoord0 ) * (mult0 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord1 ) * (mult1 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord2 ) * (mult2 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord3 ) * (mult3 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord4 ) * (mult4 * multMultiplier);
+ return outColor;
+}
+
+void frag() // Mix the input blur and the depth texture with the sprite
+{
+ float centerMultiplier = AdvancedGetTiltShiftMultiplier( TexCoord, FocusPos, FocusWidth, VerticalEffect, InvertBlur );
+ if ( BlurDebug )
+ {
+ gl_FragColor = vec4( centerMultiplier,centerMultiplier,centerMultiplier, 1.0 );
+ }
+ else
+ {
+ vec4 blurColor = AdvancedPoissonTiltShiftBlur(Texture0, Texture0Info.z, FocusPos, FocusWidth, VerticalEffect, InvertBlur );
+ gl_FragColor = mix( texture2D_SourceSampler(TexCoord), blurColor, centerMultiplier );
+ }
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="downsample_buffer" type="ubyte" format="rgba" filter="linear" wrap="clamp" size=".5" lifetime="frame"/>
+ <Pass shader="DOWNSAMPLE" input="[source]" output="downsample_buffer"/>
+ <Pass shader="BLUR" input="downsample_buffer">
+ <BufferInput value="[source]" param="SourceSampler" />
+ </Pass>
+ </Passes>
+</Effect>
+
diff --git a/Studio/Content/Effect Library/VignetteEffect.effect b/Studio/Content/Effect Library/VignetteEffect.effect
new file mode 100644
index 00000000..a4591208
--- /dev/null
+++ b/Studio/Content/Effect Library/VignetteEffect.effect
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="vig_color" formalName="Vignet Color" type="Color" default="0.5 0.5 0.5" description="The color to use for the Vignetting."/>
+ <Property name="vig_strenght" formalName="Strenght" min="0" max="15" default="15.0" description="Strenght of Vignetting."/>
+ <Property name="vig_radius" formalName="Radius" min="0" max="5" default="0.35" description="Size of Vignetting."/>
+ </MetaData>
+ <Shaders>
+ <Shared></Shared>
+ <VertexShaderShared></VertexShaderShared>
+ <FragmentShaderShared></FragmentShaderShared>
+ <Shader name="main">
+ <VertexShader></VertexShader>
+ <FragmentShader><![CDATA[
+
+void frag()
+{
+ float radius = vig_radius;
+ vec4 origColor = texture2D_0(TexCoord);
+ vec2 uv = TexCoord.xy;
+ vec2 center = vec2(0.5);
+
+ vec4 bg = origColor;
+
+ uv *= 1.0 - uv.yx;
+ float vig = uv.x*uv.y * vig_strenght;
+ vig = pow(vig, vig_radius);
+
+ vec4 vigmixcolor = vec4(vig_color,vig) * vec4(vig);
+ gl_FragColor = vec4(mix(origColor,vigmixcolor,1.0-vig));
+
+}
+ ]]></FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Pass shader="main" input="[source]" output="[dest]"/>
+ </Passes>
+</Effect>
+
+
diff --git a/Studio/Content/Effect Library/maps/effects/AreaTex-yflipped.dds b/Studio/Content/Effect Library/maps/effects/AreaTex-yflipped.dds
new file mode 100644
index 00000000..2f248cb7
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/AreaTex-yflipped.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/CircleBokeh.png b/Studio/Content/Effect Library/maps/effects/CircleBokeh.png
new file mode 100644
index 00000000..c7da55e7
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/CircleBokeh.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/HexagonalBokeh.png b/Studio/Content/Effect Library/maps/effects/HexagonalBokeh.png
new file mode 100644
index 00000000..5a2a7e66
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/HexagonalBokeh.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/SearchTex-yflipped.png b/Studio/Content/Effect Library/maps/effects/SearchTex-yflipped.png
new file mode 100644
index 00000000..b2f664c9
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/SearchTex-yflipped.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/brushnoise.dds b/Studio/Content/Effect Library/maps/effects/brushnoise.dds
new file mode 100644
index 00000000..4fdc7046
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/brushnoise.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/noise.dds b/Studio/Content/Effect Library/maps/effects/noise.dds
new file mode 100644
index 00000000..fdb5f205
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/noise.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/noise3.dds b/Studio/Content/Effect Library/maps/effects/noise3.dds
new file mode 100644
index 00000000..31156b57
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/noise3.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/noiseUniform.dds b/Studio/Content/Effect Library/maps/effects/noiseUniform.dds
new file mode 100644
index 00000000..760ed6c3
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/noiseUniform.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_cloudlet.png b/Studio/Content/Effect Library/maps/effects/ps_cloudlet.png
new file mode 100644
index 00000000..d7cc2d6e
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_cloudlet.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_glowDisc.png b/Studio/Content/Effect Library/maps/effects/ps_glowDisc.png
new file mode 100644
index 00000000..5cca9114
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_glowDisc.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_glowSphere.png b/Studio/Content/Effect Library/maps/effects/ps_glowSphere.png
new file mode 100644
index 00000000..15c3363f
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_glowSphere.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_rectangle.png b/Studio/Content/Effect Library/maps/effects/ps_rectangle.png
new file mode 100644
index 00000000..3f13ad16
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_rectangle.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_sphere.dds b/Studio/Content/Effect Library/maps/effects/ps_sphere.dds
new file mode 100644
index 00000000..5f58782f
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_sphere.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_sphere.png b/Studio/Content/Effect Library/maps/effects/ps_sphere.png
new file mode 100644
index 00000000..774c1f4c
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_sphere.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/ps_star.png b/Studio/Content/Effect Library/maps/effects/ps_star.png
new file mode 100644
index 00000000..3cd9da40
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/ps_star.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/snownoise.dds b/Studio/Content/Effect Library/maps/effects/snownoise.dds
new file mode 100644
index 00000000..070ba685
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/snownoise.dds
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/starBokeh.png b/Studio/Content/Effect Library/maps/effects/starBokeh.png
new file mode 100644
index 00000000..661d8683
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/starBokeh.png
Binary files differ
diff --git a/Studio/Content/Effect Library/maps/effects/white.png b/Studio/Content/Effect Library/maps/effects/white.png
new file mode 100644
index 00000000..18cca06b
--- /dev/null
+++ b/Studio/Content/Effect Library/maps/effects/white.png
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/DESCRIPTION.en_us.html b/Studio/Content/Font Library/titilliumweb/DESCRIPTION.en_us.html
new file mode 100644
index 00000000..99c6c3b9
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/DESCRIPTION.en_us.html
@@ -0,0 +1,22 @@
+<p>Titillium is born inside the Accademia di Belle Arti di Urbino as a
+didactic project Course Type design of the Master of Visual Design Campi
+Visivi.</p>
+
+<p>The aim of the project is the creation of a collective fonts released under
+OFL. Each academic year, a dozen students work on the project, developing it
+further and solving problems. Any type designer interested in the amendment or
+revision of Titillium is invited to co-operate with us, or develop their own
+variants of the typeface according to the terms specified in the Open Font
+license. We also ask all graphic designers who use Titillium in their projects
+to <a href="mailto:segreteria@accademiadiurbino.it">email us some examples</a>
+of the typeface family in use, in order to prepare a case histories
+database.</p>
+
+<p>Three years after the birth of Titillium, the project is still evolving,
+and even we don’t know what it will become in the future.</p>
+
+<p>Special thanks go to:<br/>
+Prof. Luciano Perondi, design and curation<br/>
+Prof. Marcello Signorile, coordination<br/>
+Prof. Manuel Zanettin, web project supervision<br/>
+Diego Giusti, design of the first prototype</p> \ No newline at end of file
diff --git a/Studio/Content/Font Library/titilliumweb/METADATA.pb b/Studio/Content/Font Library/titilliumweb/METADATA.pb
new file mode 100644
index 00000000..e4faa356
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/METADATA.pb
@@ -0,0 +1,107 @@
+name: "Titillium Web"
+designer: "Multiple Designers"
+license: "OFL"
+category: "SANS_SERIF"
+date_added: "2012-10-01"
+fonts {
+ name: "Titillium Web"
+ style: "normal"
+ weight: 200
+ filename: "TitilliumWeb-ExtraLight.ttf"
+ post_script_name: "TitilliumWeb-Thin"
+ full_name: "Titillium WebThin"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "italic"
+ weight: 200
+ filename: "TitilliumWeb-ExtraLightItalic.ttf"
+ post_script_name: "TitilliumWeb-ThinItalic"
+ full_name: "Titillium WebThin Italic"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "normal"
+ weight: 300
+ filename: "TitilliumWeb-Light.ttf"
+ post_script_name: "TitilliumWeb-Light"
+ full_name: "Titillium WebLight"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "italic"
+ weight: 300
+ filename: "TitilliumWeb-LightItalic.ttf"
+ post_script_name: "TitilliumWeb-LightItalic"
+ full_name: "Titillium WebLight Italic"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "normal"
+ weight: 400
+ filename: "TitilliumWeb-Regular.ttf"
+ post_script_name: "TitilliumWeb-Regular"
+ full_name: "Titillium Web"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "italic"
+ weight: 400
+ filename: "TitilliumWeb-Italic.ttf"
+ post_script_name: "TitilliumWeb-Italic"
+ full_name: "Titillium WebItalic"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "normal"
+ weight: 600
+ filename: "TitilliumWeb-SemiBold.ttf"
+ post_script_name: "TitilliumWeb-SemiBold"
+ full_name: "Titillium WebSemiBold"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "italic"
+ weight: 600
+ filename: "TitilliumWeb-SemiBoldItalic.ttf"
+ post_script_name: "TitilliumWeb-SemiBoldItalic"
+ full_name: "Titillium WebSemiBold Italic"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "normal"
+ weight: 700
+ filename: "TitilliumWeb-Bold.ttf"
+ post_script_name: "TitilliumWeb-Bold"
+ full_name: "Titillium WebBold"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "italic"
+ weight: 700
+ filename: "TitilliumWeb-BoldItalic.ttf"
+ post_script_name: "TitilliumWeb-BoldItalic"
+ full_name: "Titillium WebBold Italic"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+fonts {
+ name: "Titillium Web"
+ style: "normal"
+ weight: 900
+ filename: "TitilliumWeb-Black.ttf"
+ post_script_name: "TitilliumWeb-Black"
+ full_name: "Titillium WebBlack"
+ copyright: "Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino (titillium@campivisivi.net) and students of MA course of Visual design. Some rights reserved."
+}
+subsets: "menu"
+subsets: "latin"
+subsets: "latin-ext"
diff --git a/Studio/Content/Font Library/titilliumweb/OFL.txt b/Studio/Content/Font Library/titilliumweb/OFL.txt
new file mode 100644
index 00000000..bbaa23a6
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/OFL.txt
@@ -0,0 +1,93 @@
+Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino and students of MA course of Visual design. Some rights reserved.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Black.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Black.ttf
new file mode 100644
index 00000000..fc5c4b50
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Black.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Bold.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Bold.ttf
new file mode 100644
index 00000000..0af0fe7d
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Bold.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-BoldItalic.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-BoldItalic.ttf
new file mode 100644
index 00000000..77425eaa
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-BoldItalic.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLight.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLight.ttf
new file mode 100644
index 00000000..2b506ef2
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLight.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLightItalic.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLightItalic.ttf
new file mode 100644
index 00000000..c1be5ba1
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-ExtraLightItalic.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Italic.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Italic.ttf
new file mode 100644
index 00000000..42f2c10f
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Italic.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Light.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Light.ttf
new file mode 100644
index 00000000..ca679712
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Light.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-LightItalic.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-LightItalic.ttf
new file mode 100644
index 00000000..2ea724fe
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-LightItalic.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Regular.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Regular.ttf
new file mode 100644
index 00000000..6da82193
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-Regular.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBold.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBold.ttf
new file mode 100644
index 00000000..dfdcdbea
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBold.ttf
Binary files differ
diff --git a/Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBoldItalic.ttf b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBoldItalic.ttf
new file mode 100644
index 00000000..b68a6693
--- /dev/null
+++ b/Studio/Content/Font Library/titilliumweb/TitilliumWeb-SemiBoldItalic.ttf
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1-mirror.png
new file mode 100644
index 00000000..80b313c3
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1.png
new file mode 100644
index 00000000..7b195d71
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2-mirror.png
new file mode 100644
index 00000000..2af3c6d7
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2.png
new file mode 100644
index 00000000..43612728
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3-mirror.png
new file mode 100644
index 00000000..212ffaab
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3.png
new file mode 100644
index 00000000..39122779
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4-mirror.png
new file mode 100644
index 00000000..725f16af
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4.png
new file mode 100644
index 00000000..2df82291
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-4.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-1.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-1.png
new file mode 100644
index 00000000..46d3382c
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-2.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-2.png
new file mode 100644
index 00000000..335f51ab
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-3.png b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-3.png
new file mode 100644
index 00000000..0c5c019e
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-horizontal/horizontal-reflected-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1-inverse.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1-inverse.png
new file mode 100644
index 00000000..26f56a33
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1-inverse.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1.png
new file mode 100644
index 00000000..d0426aec
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2-inverse.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2-inverse.png
new file mode 100644
index 00000000..9636fac5
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2-inverse.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2.png
new file mode 100644
index 00000000..e684345f
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3-inverse.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3-inverse.png
new file mode 100644
index 00000000..d02fa209
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3-inverse.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3.png
new file mode 100644
index 00000000..c8f498f1
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4-inverse.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4-inverse.png
new file mode 100644
index 00000000..a6be42a6
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4-inverse.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4.png
new file mode 100644
index 00000000..7ee5ec72
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-4.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5-inverse.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5-inverse.png
new file mode 100644
index 00000000..60634901
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5-inverse.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5.png b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5.png
new file mode 100644
index 00000000..fa44f1b1
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-spherical/sphere-gradient-5.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1-mirror.png
new file mode 100644
index 00000000..7ad3eea6
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1.png
new file mode 100644
index 00000000..539db23a
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2-mirror.png
new file mode 100644
index 00000000..58c56cb7
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2.png
new file mode 100644
index 00000000..4930262d
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3-mirror.png
new file mode 100644
index 00000000..241f50d6
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3.png
new file mode 100644
index 00000000..ab0a8aa3
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4-mirror.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4-mirror.png
new file mode 100644
index 00000000..29da8cac
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4-mirror.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4.png
new file mode 100644
index 00000000..8f0de38d
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-4.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-1.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-1.png
new file mode 100644
index 00000000..ca40b4df
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-2.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-2.png
new file mode 100644
index 00000000..62c826dd
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-3.png b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-3.png
new file mode 100644
index 00000000..ce2f4b4c
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/gradients-vertical/vertical-reflected-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-1.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-1.png
new file mode 100644
index 00000000..62b35d13
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-2.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-2.png
new file mode 100644
index 00000000..6594540a
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-3.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-3.png
new file mode 100644
index 00000000..a8e0861d
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-4.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-4.png
new file mode 100644
index 00000000..407ee80b
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/circles-4.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-1.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-1.png
new file mode 100644
index 00000000..9956bef0
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-2.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-2.png
new file mode 100644
index 00000000..8c1cd63a
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-3.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-3.png
new file mode 100644
index 00000000..058fb0e1
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-1.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-1.png
new file mode 100644
index 00000000..d79b2333
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-2.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-2.png
new file mode 100644
index 00000000..6c996817
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-3.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-3.png
new file mode 100644
index 00000000..3836453c
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-radial-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-ripple.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-ripple.png
new file mode 100644
index 00000000..2a505a4e
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-ripple.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-twist.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-twist.png
new file mode 100644
index 00000000..0c918db1
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rays-twist.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-1.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-1.png
new file mode 100644
index 00000000..ce45c186
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-2.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-2.png
new file mode 100644
index 00000000..3c568b9a
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-3.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-3.png
new file mode 100644
index 00000000..b8a369f7
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/rounded-boxes-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/splatter-1.png b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/splatter-1.png
new file mode 100644
index 00000000..458c6203
--- /dev/null
+++ b/Studio/Content/Maps Library/Alpha Maps/misc alpha maps/splatter-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Automotive/indicators_icons.png b/Studio/Content/Maps Library/Automotive/indicators_icons.png
new file mode 100644
index 00000000..381065cb
--- /dev/null
+++ b/Studio/Content/Maps Library/Automotive/indicators_icons.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Automotive/indicators_icons_extended.png b/Studio/Content/Maps Library/Automotive/indicators_icons_extended.png
new file mode 100644
index 00000000..75980ae2
--- /dev/null
+++ b/Studio/Content/Maps Library/Automotive/indicators_icons_extended.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Automotive/large_tic_marks.png b/Studio/Content/Maps Library/Automotive/large_tic_marks.png
new file mode 100644
index 00000000..24c42682
--- /dev/null
+++ b/Studio/Content/Maps Library/Automotive/large_tic_marks.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Automotive/medium_tic_marks.png b/Studio/Content/Maps Library/Automotive/medium_tic_marks.png
new file mode 100644
index 00000000..b165ec35
--- /dev/null
+++ b/Studio/Content/Maps Library/Automotive/medium_tic_marks.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Automotive/small_tic_marks.png b/Studio/Content/Maps Library/Automotive/small_tic_marks.png
new file mode 100644
index 00000000..42d4e78b
--- /dev/null
+++ b/Studio/Content/Maps Library/Automotive/small_tic_marks.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Bump Maps/bump.dds b/Studio/Content/Maps Library/Bump Maps/bump.dds
new file mode 100644
index 00000000..97ddbf4a
--- /dev/null
+++ b/Studio/Content/Maps Library/Bump Maps/bump.dds
Binary files differ
diff --git a/Studio/Content/Maps Library/Bump Maps/rubber_hatch.dds b/Studio/Content/Maps Library/Bump Maps/rubber_hatch.dds
new file mode 100644
index 00000000..8c3b0a34
--- /dev/null
+++ b/Studio/Content/Maps Library/Bump Maps/rubber_hatch.dds
Binary files differ
diff --git a/Studio/Content/Maps Library/Concepting Maps/Finger-idle.png b/Studio/Content/Maps Library/Concepting Maps/Finger-idle.png
new file mode 100644
index 00000000..2c988fe7
--- /dev/null
+++ b/Studio/Content/Maps Library/Concepting Maps/Finger-idle.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Concepting Maps/Finger-pressureDown.png b/Studio/Content/Maps Library/Concepting Maps/Finger-pressureDown.png
new file mode 100644
index 00000000..0a60ef1c
--- /dev/null
+++ b/Studio/Content/Maps Library/Concepting Maps/Finger-pressureDown.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/LICENSE-OpenfootageNET.txt b/Studio/Content/Maps Library/Environments/LICENSE-OpenfootageNET.txt
new file mode 100644
index 00000000..eb66a5cf
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/LICENSE-OpenfootageNET.txt
@@ -0,0 +1,7 @@
+All HDRI maps from come from www.openfootage.net and are licensed under
+a Creative Commons Attribution 4.0 International License.
+http://creativecommons.org/licenses/by/4.0/
+
+All files have been (slightly) renamed for consistency.
+The -1024 and -512 images are simply smaller versions, useful for
+improved performance (and decreased max specular shininess). \ No newline at end of file
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-1024.hdr
new file mode 100644
index 00000000..bc65d427
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-512.hdr
new file mode 100644
index 00000000..7119b260
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Gerlos-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-1024.hdr
new file mode 100644
index 00000000..f58b29ae
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-512.hdr
new file mode 100644
index 00000000..c6531955
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Grado-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-1024.hdr
new file mode 100644
index 00000000..41e66640
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-512.hdr
new file mode 100644
index 00000000..ae610814
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Hintersee-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-1024.hdr
new file mode 100644
index 00000000..9e73ce72
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-512.hdr
new file mode 100644
index 00000000..655a217b
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Pinzgau-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-1024.hdr
new file mode 100644
index 00000000..84be86c0
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-512.hdr
new file mode 100644
index 00000000..3f935c44
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Streetautumn-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-1024.hdr
new file mode 100644
index 00000000..3072d3a8
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-512.hdr
new file mode 100644
index 00000000..4c331036
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_Thumersbach-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-1024.hdr
new file mode 100644
index 00000000..e2312817
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-512.hdr
new file mode 100644
index 00000000..abdebdb7
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_fieldairport-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_garage-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_garage-1024.hdr
new file mode 100644
index 00000000..01e9e38a
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_garage-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_garage-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_garage-512.hdr
new file mode 100644
index 00000000..015b4789
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_garage-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-1024.hdr
new file mode 100644
index 00000000..ac513a4b
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-512.hdr
new file mode 100644
index 00000000..df12f021
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_lowerAustria01-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-1024.hdr
new file mode 100644
index 00000000..e891be87
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-512.hdr
new file mode 100644
index 00000000..dec50402
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNET_trainstation-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-1024.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-1024.hdr
new file mode 100644
index 00000000..55d4107d
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-512.hdr b/Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-512.hdr
new file mode 100644
index 00000000..8c66ff8b
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/OpenfootageNet_LADEFENSE-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/TestEnvironment-1024.hdr b/Studio/Content/Maps Library/Environments/TestEnvironment-1024.hdr
new file mode 100644
index 00000000..34bd6b65
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/TestEnvironment-1024.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/TestEnvironment-2048.hdr b/Studio/Content/Maps Library/Environments/TestEnvironment-2048.hdr
new file mode 100644
index 00000000..6213f541
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/TestEnvironment-2048.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Environments/TestEnvironment-512.hdr b/Studio/Content/Maps Library/Environments/TestEnvironment-512.hdr
new file mode 100644
index 00000000..5885a917
--- /dev/null
+++ b/Studio/Content/Maps Library/Environments/TestEnvironment-512.hdr
Binary files differ
diff --git a/Studio/Content/Maps Library/Logos/Qt/QT-badge.png b/Studio/Content/Maps Library/Logos/Qt/QT-badge.png
new file mode 100644
index 00000000..04863100
--- /dev/null
+++ b/Studio/Content/Maps Library/Logos/Qt/QT-badge.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Logos/Qt/QT-symbol-flatWhite.png b/Studio/Content/Maps Library/Logos/Qt/QT-symbol-flatWhite.png
new file mode 100644
index 00000000..9b718ec2
--- /dev/null
+++ b/Studio/Content/Maps Library/Logos/Qt/QT-symbol-flatWhite.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Logos/Qt/QT-symbol.png b/Studio/Content/Maps Library/Logos/Qt/QT-symbol.png
new file mode 100644
index 00000000..752a2e2f
--- /dev/null
+++ b/Studio/Content/Maps Library/Logos/Qt/QT-symbol.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-128X128.png b/Studio/Content/Maps Library/Shapes/circles/circle-128X128.png
new file mode 100644
index 00000000..67da57eb
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-128X128.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-256X256.png b/Studio/Content/Maps Library/Shapes/circles/circle-256X256.png
new file mode 100644
index 00000000..bf79cf97
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-256X256.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-32X32.png b/Studio/Content/Maps Library/Shapes/circles/circle-32X32.png
new file mode 100644
index 00000000..b23983f2
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-32X32.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-64X64.png b/Studio/Content/Maps Library/Shapes/circles/circle-64X64.png
new file mode 100644
index 00000000..88d2b890
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-64X64.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-01p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-01p.png
new file mode 100644
index 00000000..747d23b4
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-01p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-02p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-02p.png
new file mode 100644
index 00000000..7185b47b
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-02p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-03p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-03p.png
new file mode 100644
index 00000000..9da886f0
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-03p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-05p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-05p.png
new file mode 100644
index 00000000..942e01d1
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-05p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-10p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-10p.png
new file mode 100644
index 00000000..36324011
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-10p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-15p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-15p.png
new file mode 100644
index 00000000..420a679f
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-15p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-20p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-20p.png
new file mode 100644
index 00000000..19936678
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-20p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-25p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-25p.png
new file mode 100644
index 00000000..80bce1e2
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-25p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-30p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-30p.png
new file mode 100644
index 00000000..356c1067
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-30p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/circles/circle-stroke-50p.png b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-50p.png
new file mode 100644
index 00000000..2d469662
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/circles/circle-stroke-50p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-01p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-01p.png
new file mode 100644
index 00000000..91df0ffc
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-01p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-02p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-02p.png
new file mode 100644
index 00000000..65b7ea4e
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-02p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-03p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-03p.png
new file mode 100644
index 00000000..4df981bf
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-03p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-05p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-05p.png
new file mode 100644
index 00000000..f29dd9fb
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-05p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-10p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-10p.png
new file mode 100644
index 00000000..1480345c
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-10p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-25p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-25p.png
new file mode 100644
index 00000000..803a1b6b
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-25p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Shapes/squares/square-stroke-50p.png b/Studio/Content/Maps Library/Shapes/squares/square-stroke-50p.png
new file mode 100644
index 00000000..cd3353ba
--- /dev/null
+++ b/Studio/Content/Maps Library/Shapes/squares/square-stroke-50p.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/flares/Flare1.png b/Studio/Content/Maps Library/Special Effects/flares/Flare1.png
new file mode 100644
index 00000000..bc3cdf63
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/flares/Flare1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/flares/Flare2.png b/Studio/Content/Maps Library/Special Effects/flares/Flare2.png
new file mode 100644
index 00000000..f804ccb6
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/flares/Flare2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/flares/Flare3.png b/Studio/Content/Maps Library/Special Effects/flares/Flare3.png
new file mode 100644
index 00000000..bcc5a960
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/flares/Flare3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/flares/Flare4.png b/Studio/Content/Maps Library/Special Effects/flares/Flare4.png
new file mode 100644
index 00000000..8885292c
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/flares/Flare4.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/flares/Flare5.png b/Studio/Content/Maps Library/Special Effects/flares/Flare5.png
new file mode 100644
index 00000000..7d10d4ba
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/flares/Flare5.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/flares/Thumbs.db b/Studio/Content/Maps Library/Special Effects/flares/Thumbs.db
new file mode 100644
index 00000000..33d42f71
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/flares/Thumbs.db
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/glows/Glow-CircleBorder-1.png b/Studio/Content/Maps Library/Special Effects/glows/Glow-CircleBorder-1.png
new file mode 100644
index 00000000..ebfe2e01
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/glows/Glow-CircleBorder-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-1.png b/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-1.png
new file mode 100644
index 00000000..a710707b
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-2.png b/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-2.png
new file mode 100644
index 00000000..dadc917a
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-3.png b/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-3.png
new file mode 100644
index 00000000..02545418
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/glows/Glow-circle-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/glows/Thumbs.db b/Studio/Content/Maps Library/Special Effects/glows/Thumbs.db
new file mode 100644
index 00000000..7913ae44
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/glows/Thumbs.db
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/grids/grid-01.png b/Studio/Content/Maps Library/Special Effects/grids/grid-01.png
new file mode 100644
index 00000000..43347f59
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/grids/grid-01.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/grids/grid-02.png b/Studio/Content/Maps Library/Special Effects/grids/grid-02.png
new file mode 100644
index 00000000..16fda6d9
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/grids/grid-02.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/grids/grid-03.png b/Studio/Content/Maps Library/Special Effects/grids/grid-03.png
new file mode 100644
index 00000000..e3d4aef6
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/grids/grid-03.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/grids/grid-04.png b/Studio/Content/Maps Library/Special Effects/grids/grid-04.png
new file mode 100644
index 00000000..ab3ee266
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/grids/grid-04.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Color.png b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Color.png
new file mode 100644
index 00000000..f08d7d24
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Color.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing.png b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing.png
new file mode 100644
index 00000000..59e3b6e9
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing2.png b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing2.png
new file mode 100644
index 00000000..03d2e3da
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_RainbowRing2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Ring.png b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Ring.png
new file mode 100644
index 00000000..98d7ae10
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/lens flares/LensFlare_Ring.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/cloudy_smoke.png b/Studio/Content/Maps Library/Special Effects/smoke/cloudy_smoke.png
new file mode 100644
index 00000000..3501fbf4
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/cloudy_smoke.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-1.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-1.png
new file mode 100644
index 00000000..520880a0
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-2.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-2.png
new file mode 100644
index 00000000..e2e658fc
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-3.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-3.png
new file mode 100644
index 00000000..a798d8ac
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-4.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-4.png
new file mode 100644
index 00000000..70b2327c
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-4.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-5.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-5.png
new file mode 100644
index 00000000..13582e2b
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-5.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-1.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-1.png
new file mode 100644
index 00000000..b0f0f199
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-2.png b/Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-2.png
new file mode 100644
index 00000000..f2f13d02
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/smoke/smoke-puff-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/streaks/streak_narrow.png b/Studio/Content/Maps Library/Special Effects/streaks/streak_narrow.png
new file mode 100644
index 00000000..222cefdf
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/streaks/streak_narrow.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Special Effects/streaks/streak_wide.png b/Studio/Content/Maps Library/Special Effects/streaks/streak_wide.png
new file mode 100644
index 00000000..c6fe1b6e
--- /dev/null
+++ b/Studio/Content/Maps Library/Special Effects/streaks/streak_wide.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_01.jpg b/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_01.jpg
new file mode 100644
index 00000000..1cd729c2
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_01.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_02.jpg b/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_02.jpg
new file mode 100644
index 00000000..299f6a2c
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_02.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_03.jpg b/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_03.jpg
new file mode 100644
index 00000000..0a96914a
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Chrome/Chrome_03.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_01.jpg b/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_01.jpg
new file mode 100644
index 00000000..0f8485d9
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_01.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_02.jpg b/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_02.jpg
new file mode 100644
index 00000000..c5ad0a7a
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_02.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_03.jpg b/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_03.jpg
new file mode 100644
index 00000000..74963de2
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Gold/Gold_03.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-1.jpg b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-1.jpg
new file mode 100644
index 00000000..8b1a8b0e
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-1.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-2.jpg b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-2.jpg
new file mode 100644
index 00000000..40747b6e
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-2.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-3.jpg b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-3.jpg
new file mode 100644
index 00000000..77cff7b5
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Environment-3.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Smear.jpg b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Smear.jpg
new file mode 100644
index 00000000..3d8c64ab
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Smear.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Underwater.jpg b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Underwater.jpg
new file mode 100644
index 00000000..49e6b627
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Underwater.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Window.jpg b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Window.jpg
new file mode 100644
index 00000000..f688c9ff
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Misc/Reflection_Window.jpg
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-ceiling_lights-1.png b/Studio/Content/Maps Library/Specular Reflection/Specular-ceiling_lights-1.png
new file mode 100644
index 00000000..443f8817
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-ceiling_lights-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-dull-1.png b/Studio/Content/Maps Library/Specular Reflection/Specular-dull-1.png
new file mode 100644
index 00000000..84772ffc
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-dull-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-dull-2.png b/Studio/Content/Maps Library/Specular Reflection/Specular-dull-2.png
new file mode 100644
index 00000000..5d893723
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-dull-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-dull-3.png b/Studio/Content/Maps Library/Specular Reflection/Specular-dull-3.png
new file mode 100644
index 00000000..bc9645d9
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-dull-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1-alpha-25_orange.png b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1-alpha-25_orange.png
new file mode 100644
index 00000000..9f2a64b1
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1-alpha-25_orange.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1.png b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1.png
new file mode 100644
index 00000000..2e2a2758
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-2.png b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-2.png
new file mode 100644
index 00000000..7e5af568
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-3.png b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-3.png
new file mode 100644
index 00000000..dbc17adb
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/Specular-shiny-3.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha01.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha01.png
new file mode 100644
index 00000000..9b5b3e9e
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha01.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha02.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha02.png
new file mode 100644
index 00000000..b808d122
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha02.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha03.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha03.png
new file mode 100644
index 00000000..ad218fce
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha03.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha04.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha04.png
new file mode 100644
index 00000000..d4a3db69
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha04.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha05.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha05.png
new file mode 100644
index 00000000..cca10676
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Glass-alpha05.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-100.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-100.png
new file mode 100644
index 00000000..13a5d114
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-100.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-25.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-25.png
new file mode 100644
index 00000000..77add09f
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-25.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-50.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-50.png
new file mode 100644
index 00000000..7fbef27b
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-50.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-75.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-75.png
new file mode 100644
index 00000000..52c595cd
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-75.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-90.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-90.png
new file mode 100644
index 00000000..1a38b49b
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-dull-1-alpha-90.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-100.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-100.png
new file mode 100644
index 00000000..81f09fe6
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-100.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25.png
new file mode 100644
index 00000000..54dc410b
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25_refIVI.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25_refIVI.png
new file mode 100644
index 00000000..54dc410b
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-25_refIVI.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50.png
new file mode 100644
index 00000000..3ffe405c
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50_green.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50_green.png
new file mode 100644
index 00000000..4cda0d34
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-50_green.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-75.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-75.png
new file mode 100644
index 00000000..b99c502d
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-75.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-90.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-90.png
new file mode 100644
index 00000000..9065eafe
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-90.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-blue.png b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-blue.png
new file mode 100644
index 00000000..35e07da1
--- /dev/null
+++ b/Studio/Content/Maps Library/Specular Reflection/With Alpha/Specular-shiny-1-alpha-blue.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Cork1.png b/Studio/Content/Maps Library/Texture Maps/Cork1.png
new file mode 100644
index 00000000..b27b27d4
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Cork1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Fabric1.png b/Studio/Content/Maps Library/Texture Maps/Fabric1.png
new file mode 100644
index 00000000..65dcf400
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Fabric1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Fabric2.png b/Studio/Content/Maps Library/Texture Maps/Fabric2.png
new file mode 100644
index 00000000..74156f69
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Fabric2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Grass2.png b/Studio/Content/Maps Library/Texture Maps/Grass2.png
new file mode 100644
index 00000000..ed8189d3
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Grass2.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Metal_Bronze.png b/Studio/Content/Maps Library/Texture Maps/Metal_Bronze.png
new file mode 100644
index 00000000..119cad6d
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Metal_Bronze.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Metal_Oxydized.png b/Studio/Content/Maps Library/Texture Maps/Metal_Oxydized.png
new file mode 100644
index 00000000..bca8c2f1
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Metal_Oxydized.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Metal_Streaks.png b/Studio/Content/Maps Library/Texture Maps/Metal_Streaks.png
new file mode 100644
index 00000000..f2a6d49b
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Metal_Streaks.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Paper05.png b/Studio/Content/Maps Library/Texture Maps/Paper05.png
new file mode 100644
index 00000000..e70749db
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Paper05.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Scratched_Aluminum.png b/Studio/Content/Maps Library/Texture Maps/Scratched_Aluminum.png
new file mode 100644
index 00000000..ebabbfeb
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Scratched_Aluminum.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Stone1.png b/Studio/Content/Maps Library/Texture Maps/Stone1.png
new file mode 100644
index 00000000..454ab58f
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Stone1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Water1.png b/Studio/Content/Maps Library/Texture Maps/Water1.png
new file mode 100644
index 00000000..2d0ea4e5
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Water1.png
Binary files differ
diff --git a/Studio/Content/Maps Library/Texture Maps/Wood7.png b/Studio/Content/Maps Library/Texture Maps/Wood7.png
new file mode 100644
index 00000000..9d9a219a
--- /dev/null
+++ b/Studio/Content/Maps Library/Texture Maps/Wood7.png
Binary files differ
diff --git a/Studio/Content/Maps Library/UV-Checker.png b/Studio/Content/Maps Library/UV-Checker.png
new file mode 100644
index 00000000..fd3fa9c6
--- /dev/null
+++ b/Studio/Content/Maps Library/UV-Checker.png
Binary files differ
diff --git a/Studio/Content/Material Library/aluminium_anodized.material b/Studio/Content/Material Library/aluminium_anodized.material
new file mode 100644
index 00000000..2a10018c
--- /dev/null
+++ b/Studio/Content/Material Library/aluminium_anodized.material
@@ -0,0 +1,178 @@
+<Material name="aluminium_anodized" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.300000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="base_color" type="Color" default="0.7 0.7 0.7" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( 22, 22, 22 ), 1.000000, vec4( base_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/aluminium_anodized_emissive.material b/Studio/Content/Material Library/aluminium_anodized_emissive.material
new file mode 100644
index 00000000..e59bdb46
--- /dev/null
+++ b/Studio/Content/Material Library/aluminium_anodized_emissive.material
@@ -0,0 +1,214 @@
+<Material name="aluminium_anodized_emissive" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.300000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="base_color" type="Color" default="0.7 0.7 0.7" description="Color of the material" category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" default="./maps/materials/emissive_mask.png" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+#include "monoChannel.glsllib"
+#include "fileTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color*( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint*fileTexture(emissive_mask_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( 22, 22, 22 ), 1.000000, vec4( base_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/aluminum.material b/Studio/Content/Material Library/aluminum.material
new file mode 100644
index 00000000..841b5910
--- /dev/null
+++ b/Studio/Content/Material Library/aluminum.material
@@ -0,0 +1,223 @@
+<Material name="aluminum" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Reflectivity Map" name="reflection_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/grunge_b.png" category="Material"/>
+ <Property formalName="Reflection Map Offset" name="reflection_map_offset" hidden="True" type="Float" default="0.500000" description="Reflection texture value offset." category="Material"/>
+ <Property formalName="Reflection Map Scale" name="reflection_map_scale" hidden="True" type="Float" default="0.300000" description="Reflection texture value scale." category="Material"/>
+ <Property formalName="Tiling" name="tiling" type="Vector" default="1 1 1" description="Texture Tiling size." category="Material"/>
+ <Property formalName="Roughness Map" name="roughness_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="roughness" default="./maps/materials/grunge_d.png" category="Material"/>
+ <Property formalName="Roughness Map Offset" name="roughness_map_offset" hidden="True" type="Float" default="0.160000" description="Roughness texture value offset." category="Material"/>
+ <Property formalName="Roughness Map Scale" name="roughness_map_scale" hidden="True" type="Float" default="0.400000" description="Roughness texture value scale." category="Material"/>
+ <Property formalName="Metal Color" name="metal_color" type="Color" default="0.95 0.95 0.95" description="Base color of the material." category="Material"/>
+ <Property formalName="Bump Map" name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/grunge_d.png" category="Material"/>
+ <Property formalName="Bump Amount" name="bump_amount" type="Float" min="0" max="2" default="0.500000" description="Scale value for bump amount." category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp1;
+float tmp2;
+float ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "weightedLayer.glsllib"
+#include "fileTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, tmp2, tmp2, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, tmp2, tmp2 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, tmp2, tmp2, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, tmp2, tmp2 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), tiling ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp2 = fileTexture(roughness_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp0 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( ftmp0, vec4( metal_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/aluminum_anisotropic.material b/Studio/Content/Material Library/aluminum_anisotropic.material
new file mode 100644
index 00000000..fb1d7200
--- /dev/null
+++ b/Studio/Content/Material Library/aluminum_anisotropic.material
@@ -0,0 +1,260 @@
+<Material name="aluminum_anisotropic" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="8.000000" category="Material"/>
+ <Property formalName="Diffuse Map" name="reflection_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/concentric_milled_steel.png" category="Material"/>
+ <Property formalName="Reflection Map Offset" name="reflection_map_offset" hidden="True" type="Float" default="1.000000" description="Reflection texture value offset." category="Material"/>
+ <Property formalName="Reflection Map Scale" name="reflection_map_scale" hidden="True" type="Float" default="1.000000" description="Reflection texture value scale." category="Material"/>
+ <Property formalName="Tiling" name="tiling" type="Float2" default="8 5" description="Texture Tiling size." category="Material"/>
+ <Property formalName="Roughness Map Offset" name="roughness_map_offset" hidden="True" type="Float" default="0.000000" description="Roughness texture value offset." category="Material"/>
+ <Property formalName="Roughness Map Scale" name="roughness_map_scale" hidden="True" type="Float" default="1.000000" description="Roughness texture value scale." category="Material"/>
+ <Property formalName="Anisotropy" name="anisotropy" type="Float" default="0.800000" description="Anisotropy." category="Material"/>
+ <Property formalName="Anisotropy Map" name="aniso_rot_texture" type="Texture" filter="linear" minfilter="linear" clamp="repeat" usage="anisotropy" default="./maps/materials/concentric_milled_steel_aniso.png" category="Material"/>
+ <Property formalName="Roughness Map Offset" name="aniso_tex_color_offset" hidden="True" type="Float" default="0.000000" description="Roughness texture value offset." category="Material"/>
+ <Property formalName="Roughness Map Scale" name="aniso_tex_color_scale" hidden="True" type="Float" default="1.000000" description="Roughness texture value scale." category="Material"/>
+ <Property name="base_weight" hidden="True" type="Float" default="1.000000" category="Material"/>
+ <Property formalName="Bump Map" name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/concentric_milled_steel.png" category="Material"/>
+ <Property formalName="Bump Amount" name="bump_amount" type="Float" min="0" max="2" default="0.000000" description="Scale value for bump amount." category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+struct anisotropy_return
+{
+ float roughness_u;
+ float roughness_v;
+ vec3 tangent_u;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+texture_return tmp4;
+anisotropy_return tmp5;
+vec3 tmp6;
+vec3 tmp8;
+float ftmp0;
+float ftmp1;
+vec3 ftmp2;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "fileTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "anisotropyConversion.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, ftmp0, ftmp1 );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, ftmp0, ftmp1, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp0, ftmp1 );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( tmp8 );
+}
+
+void computeTemporaries()
+{
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( tiling[0], tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp4 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
+ tmp5 = anisotropyConversion( fileTexture(reflection_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, anisotropy, fileTexture(aniso_rot_texture, vec3( aniso_tex_color_offset ), vec3( aniso_tex_color_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono, tangent, false );
+ tmp6 = tmp4.tint;
+ tmp8 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = tmp5.roughness_u;
+ ftmp1 = tmp5.roughness_v;
+ ftmp2 = tmp5.tangent_u;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( base_weight, vec4( tmp6, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp8, vec3( material_ior ), tmp4.mono, vec4( tmp6, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( ftmp2, cross(tmp8, ftmp2), tmp8 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/aluminum_brushed.material b/Studio/Content/Material Library/aluminum_brushed.material
new file mode 100644
index 00000000..9ea01def
--- /dev/null
+++ b/Studio/Content/Material Library/aluminum_brushed.material
@@ -0,0 +1,224 @@
+<Material name="aluminum_brushed" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="brush_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="brush" default="./maps/materials/brushed_full_contrast.png" category="Material"/>
+ <Property name="tiling" type="Vector" default="3 3 3" category="Material"/>
+ <Property name="roughness_texture_u" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="roughness" default="./maps/materials/brushed_full_contrast.png" category="Material"/>
+ <Property name="brushing_strength" type="Float" default="0.500000" category="Material"/>
+ <Property name="roughness_texture_v" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="roughness" default="./maps/materials/brushed_full_contrast.png" category="Material"/>
+ <Property name="reflection_stretch" type="Float" default="0.500000" category="Material"/>
+ <Property name="metal_color" type="Color" default="0.95 0.95 0.95" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/brushed_a.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="0.400000" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp1;
+float ftmp0;
+float ftmp1;
+float ftmp2;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "weightedLayer.glsllib"
+#include "fileTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp1, ftmp2, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, ftmp1, ftmp2 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, ftmp1, ftmp2, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp1, ftmp2 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), tiling ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ ftmp0 = fileTexture(brush_texture, vec3( 0.5, 0.5, 0.5 ), vec3( 0.5, 0.5, 0.5 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp1 = fileTexture(roughness_texture_u, vec3( 0.12, 0.12, 0.12 ), vec3( ( 0.800000*brushing_strength ) ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp2 = fileTexture(roughness_texture_v, vec3( ( 0.150000+( 0.400000*reflection_stretch ) ) ), vec3( ( 0.100000+( reflection_stretch*0.300000 ) ) ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( ftmp0, vec4( metal_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/aluminum_emissive.material b/Studio/Content/Material Library/aluminum_emissive.material
new file mode 100644
index 00000000..0dad1dcc
--- /dev/null
+++ b/Studio/Content/Material Library/aluminum_emissive.material
@@ -0,0 +1,231 @@
+<Material name="aluminum" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Reflectivity Map" name="reflection_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/grunge_b.png" category="Material"/>
+ <Property formalName="Reflection Map Offset" name="reflection_map_offset" hidden="True" type="Float" default="0.500000" description="Reflection texture value offset." category="Material"/>
+ <Property formalName="Reflection Map Scale" name="reflection_map_scale" hidden="True" type="Float" default="0.300000" description="Reflection texture value scale." category="Material"/>
+ <Property formalName="Tiling" name="tiling" type="Vector" default="1 1 1" description="Texture Tiling size." category="Material"/>
+ <Property formalName="Roughness Map" name="roughness_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="roughness" default="./maps/materials/grunge_d.png" category="Material"/>
+ <Property formalName="Roughness Map Offset" name="roughness_map_offset" hidden="True" type="Float" default="0.160000" description="Roughness texture value offset." category="Material"/>
+ <Property formalName="Roughness Map Scale" name="roughness_map_scale" hidden="True" type="Float" default="0.400000" description="Roughness texture value scale." category="Material"/>
+ <Property formalName="Metal Color" name="metal_color" type="Color" default="0.95 0.95 0.95" description="Base color of the material." category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" default="./maps/materials/emissive_mask.png" category="Material"/>
+ <Property name="emissive_mask_offset" type="Vector" default="0 0 0" category="Material"/>
+ <Property formalName="Bump Map" name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/grunge_d.png" category="Material"/>
+ <Property formalName="Bump Amount" name="bump_amount" type="Float" min="0" max="2" default="0.500000" description="Scale value for bump amount." category="Material"/>
+ <Property formalName="Emissive Mask Map" name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
+float tmp3;
+float ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "weightedLayer.glsllib"
+#include "fileTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color*( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp1 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint*fileTexture(emissive_mask_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), emissive_mask_offset, vec3( 1.000000, 1.000000, 1.000000 ) ), tmp1 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, tmp3, tmp3, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, tmp3, tmp3 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, tmp3, tmp3, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, tmp3, tmp3 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmp1 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), tiling ), tmp1 );
+ tmp3 = fileTexture(roughness_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp0 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( ftmp0, vec4( metal_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/aluminum_textured_aniso.material b/Studio/Content/Material Library/aluminum_textured_aniso.material
new file mode 100644
index 00000000..b57ab80f
--- /dev/null
+++ b/Studio/Content/Material Library/aluminum_textured_aniso.material
@@ -0,0 +1,263 @@
+<Material name="aluminum_anisotropic" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="8.000000" category="Material"/>
+ <Property formalName="Diffuse Map" name="reflection_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/concentric_milled_steel.png" category="Material"/>
+ <Property formalName="Reflection Map Offset" name="reflection_map_offset" hidden="True" type="Float" default="1.000000" description="Reflection texture value offset." category="Material"/>
+ <Property formalName="Reflection Map Scale" name="reflection_map_scale" hidden="True" type="Float" default="1.000000" description="Reflection texture value scale." category="Material"/>
+ <Property formalName="Tiling" name="tiling" type="Float2" default="1 1" description="Texture Tiling size." category="Material"/>
+ <Property formalName="Roughness Map Offset" name="roughness_map_offset" hidden="True" type="Float" default="0.000000" description="Roughness texture value offset." category="Material"/>
+ <Property formalName="Roughness Map Scale" name="roughness_map_scale" hidden="True" type="Float" default="1.000000" description="Roughness texture value scale." category="Material"/>
+ <Property formalName="Anisotropy" name="anisotropy" type="Float" default="0.800000" description="Anisotropy." category="Material"/>
+ <Property formalName="Anisotropy Map" name="aniso_rot_texture" type="Texture" filter="linear" minfilter="linear" clamp="repeat" usage="anisotropy" default="./maps/materials/concentric_milled_steel_aniso.png" category="Material"/>
+ <Property formalName="Roughness Map Offset" name="aniso_tex_color_offset" hidden="True" type="Float" default="0.000000" description="Roughness texture value offset." category="Material"/>
+ <Property formalName="Roughness Map Scale" name="aniso_tex_color_scale" hidden="True" type="Float" default="1.000000" description="Roughness texture value scale." category="Material"/>
+ <Property name="aniso_tiling" type="Float2" default="1 1" category="Material"/>
+ <Property name="base_weight" hidden="True" type="Float" default="1.000000" category="Material"/>
+ <Property formalName="Bump Map" name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/concentric_milled_steel.png" category="Material"/>
+ <Property formalName="Bump Amount" name="bump_amount" type="Float" min="0" max="2" default="0.000000" description="Scale value for bump amount." category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+struct anisotropy_return
+{
+ float roughness_u;
+ float roughness_v;
+ vec3 tangent_u;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+texture_coordinate_info tmp4;
+texture_return tmp5;
+anisotropy_return tmp7;
+vec3 tmp8;
+vec3 tmp10;
+float ftmp0;
+float ftmp1;
+vec3 ftmp2;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "fileTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "anisotropyConversion.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, ftmp0, ftmp1 );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, ftmp0, ftmp1, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp0, ftmp1 );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( tmp10 );
+}
+
+void computeTemporaries()
+{
+ tmp2 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ tmp4 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( tiling[0], tiling[1], 1.000000 ) ), tmp2 );
+ tmp5 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
+ tmp7 = anisotropyConversion( fileTexture(reflection_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, anisotropy, fileTexture(aniso_rot_texture, vec3( aniso_tex_color_offset ), vec3( aniso_tex_color_scale ), mono_luminance, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( aniso_tiling[0], aniso_tiling[1], 1.000000 ) ), tmp2 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono, tangent, false );
+ tmp8 = tmp5.tint;
+ tmp10 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = tmp7.roughness_u;
+ ftmp1 = tmp7.roughness_v;
+ ftmp2 = tmp7.tangent_u;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( base_weight, vec4( tmp8, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp10, vec3( material_ior ), tmp5.mono, vec4( tmp8, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( ftmp2, cross(tmp10, ftmp2), tmp10 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/asphalt.material b/Studio/Content/Material Library/asphalt.material
new file mode 100644
index 00000000..844648cd
--- /dev/null
+++ b/Studio/Content/Material Library/asphalt.material
@@ -0,0 +1,236 @@
+<Material name="asphalt" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="2.000000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.250000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/asphalt_bump.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="4 4" description="Scaling of the textures" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/asphalt.png" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/asphalt_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="7.000000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 tmp5;
+vec3 ftmp0;
+vec3 ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp1, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp5, vec3( material_ior ), 1.000000, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/bamboo_natural_matte.material b/Studio/Content/Material Library/bamboo_natural_matte.material
new file mode 100644
index 00000000..f2e55fdf
--- /dev/null
+++ b/Studio/Content/Material Library/bamboo_natural_matte.material
@@ -0,0 +1,236 @@
+<Material name="bamboo_natural_matte" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.500000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.300000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/bamboo_natural_spec.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="4 4" description="Scaling of the textures" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/bamboo_natural.png" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/bamboo_natural_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="0.150000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 tmp5;
+vec3 ftmp0;
+vec3 ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp1, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp5, vec3( material_ior ), 1.000000, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/bamboo_natural_matte_emissive.material b/Studio/Content/Material Library/bamboo_natural_matte_emissive.material
new file mode 100644
index 00000000..a5a06754
--- /dev/null
+++ b/Studio/Content/Material Library/bamboo_natural_matte_emissive.material
@@ -0,0 +1,242 @@
+<Material name="bamboo_natural_matte_emissive" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.500000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.300000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/bamboo_natural_spec.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="4 4" description="Scaling of the textures" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/bamboo_natural.png" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/bamboo_natural_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="0.150000" description="Value determining the bumpiness" category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property formalName="Emissive Mask Map" name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
+vec3 tmp6;
+vec3 ftmp0;
+vec3 ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color*fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp2 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), tmp2 );
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp1, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp6, vec3( material_ior ), 1.000000, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/carbon_fiber.material b/Studio/Content/Material Library/carbon_fiber.material
new file mode 100644
index 00000000..c60e3090
--- /dev/null
+++ b/Studio/Content/Material Library/carbon_fiber.material
@@ -0,0 +1,271 @@
+<Material name="carbon_fiber" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Coat ior" name="coat_ior" type="Float" default="1.250000" description="Index of refraction of the coating layer" category="Material"/>
+ <Property formalName="Coat Glossy weight" name="coat_weight" type="Float" min="0.000000" max="1.000000" default="1.000000" description="Strength of the coating's glossy reflection. A value of 0 means no reflection, 1 is maximum reflectivity" category="Material"/>
+ <Property formalName="Coat Roughness" name="coat_roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property formalName="Base ior" name="base_ior" type="Float" default="1.650000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glossy Weight" name="base_weight" type="Float" min="0.000000" max="1.000000" default="0.500000" description="Strength of glossy reflection at incident angles. A value of 0 means no reflection, 1 is maximum reflectivity" category="Material"/>
+ <Property formalName="Roughness" name="base_roughness" type="Float" min="0.000000" max="1.000000" default="0.100000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property formalName="Anisotropy" name="anisotropy" type="Float" min="0.000000" max="0.999000" default="0.800000" description="The anisotropy of the roughness" category="Material"/>
+ <Property formalName="Anisotropy Transformation Map" name="anisotropy_rotation_texture" type="Texture" filter="linear" minfilter="linear" clamp="repeat" usage="anisotropy" default="./maps/materials/carbon_fiber_aniso.png" category="Material"/>
+ <Property formalName="Tiling" name="texture_tiling" type="Float2" default="12 12" description="Scaling of the textures" category="Material"/>
+ <Property formalName="Reflectivity Map" name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/carbon_fiber_spec.png" category="Material"/>
+ <Property formalName="Diffuse Map" name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/carbon_fiber.png" category="Material"/>
+ <Property formalName="Bump Map" name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/carbon_fiber_bump.png" category="Material"/>
+ <Property formalName="Bump Amount" name="bump_amount" type="Float" default="1.000000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct anisotropy_return
+{
+ float roughness_u;
+ float roughness_v;
+ vec3 tangent_u;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+anisotropy_return tmp4;
+vec3 tmp6;
+float ftmp0;
+float ftmp1;
+vec3 ftmp2;
+vec3 ftmp3;
+vec3 ftmp4;
+ vec4 tmpShadowTerm;
+
+layer_result layers[3];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "fileTexture.glsllib"
+#include "anisotropyConversion.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, coat_roughness, coat_roughness, scatter_reflect );
+
+ layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, coat_roughness, coat_roughness );
+
+ layers[1].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[1].tanFrame, varWorldPos, lightIdx, viewDir, ftmp0, ftmp1 );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[2].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness, scatter_reflect );
+
+ layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, ftmp0, ftmp1, scatter_reflect );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness );
+
+ layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, ftmp0, ftmp1 );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * sampleDiffuse( layers[2].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp4 = anisotropyConversion( base_roughness, anisotropy, fileTexture(anisotropy_rotation_texture, vec3( 0, 0, 0 ), vec3( 3.14, 3.14, 3.14 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = tmp4.roughness_u;
+ ftmp1 = tmp4.roughness_v;
+ ftmp2 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp3 = tmp4.tangent_u;
+ ftmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp4, 1.0).rgb, layers[2].layer, layers[2].base, alpha );
+ color = fresnelLayer( tmp6, vec3( base_ior ), base_weight, vec4( ftmp2, 1.0).rgb, layers[1].layer, color, color.a );
+ color = fresnelLayer( normal, vec3( coat_ior ), coat_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( ftmp3, cross(tmp6, ftmp3), tmp6 ) );
+ layers[2].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[2].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[2].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="3"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/carbon_fiber_emissive.material b/Studio/Content/Material Library/carbon_fiber_emissive.material
new file mode 100644
index 00000000..6b80d8c8
--- /dev/null
+++ b/Studio/Content/Material Library/carbon_fiber_emissive.material
@@ -0,0 +1,277 @@
+<Material name="carbon_fiber" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Coat ior" name="coat_ior" type="Float" default="1.250000" description="Index of refraction of the coating layer" category="Material"/>
+ <Property formalName="Coat Glossy weight" name="coat_weight" type="Float" min="0.000000" max="1.000000" default="1.000000" description="Strength of the coating's glossy reflection. A value of 0 means no reflection, 1 is maximum reflectivity" category="Material"/>
+ <Property formalName="Coat Roughness" name="coat_roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property formalName="Base ior" name="base_ior" type="Float" default="1.650000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glossy Weight" name="base_weight" type="Float" min="0.000000" max="1.000000" default="0.500000" description="Strength of glossy reflection at incident angles. A value of 0 means no reflection, 1 is maximum reflectivity" category="Material"/>
+ <Property formalName="Roughness" name="base_roughness" type="Float" min="0.000000" max="1.000000" default="0.100000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property formalName="Anisotropy" name="anisotropy" type="Float" min="0.000000" max="0.999000" default="0.800000" description="The anisotropy of the roughness" category="Material"/>
+ <Property formalName="Anisotropy Transformation Map" name="anisotropy_rotation_texture" type="Texture" filter="linear" minfilter="linear" clamp="repeat" usage="anisotropy" default="./maps/materials/carbon_fiber_aniso.png" category="Material"/>
+ <Property formalName="Tiling" name="texture_tiling" type="Float2" default="12 12" description="Scaling of the textures" category="Material"/>
+ <Property formalName="Reflectivity Map" name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/carbon_fiber_spec.png" category="Material"/>
+ <Property formalName="Diffuse Map" name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/carbon_fiber.png" category="Material"/>
+ <Property formalName="Bump Map" name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/carbon_fiber_bump.png" category="Material"/>
+ <Property formalName="Bump Amount" name="bump_amount" type="Float" default="1.000000" description="Value determining the bumpiness" category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property formalName="Emissive Mask Map" name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct anisotropy_return
+{
+ float roughness_u;
+ float roughness_v;
+ vec3 tangent_u;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
+anisotropy_return tmp5;
+vec3 tmp7;
+float ftmp0;
+float ftmp1;
+vec3 ftmp2;
+vec3 ftmp3;
+vec3 ftmp4;
+ vec4 tmpShadowTerm;
+
+layer_result layers[3];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "fileTexture.glsllib"
+#include "anisotropyConversion.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color*fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, coat_roughness, coat_roughness, scatter_reflect );
+
+ layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp7, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, coat_roughness, coat_roughness );
+
+ layers[1].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[1].tanFrame, varWorldPos, lightIdx, viewDir, ftmp0, ftmp1 );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[2].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness, scatter_reflect );
+
+ layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, ftmp0, ftmp1, scatter_reflect );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp7, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness );
+
+ layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, ftmp0, ftmp1 );
+
+ layers[2].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[2].layer += tmpShadowTerm * sampleDiffuse( layers[2].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ tmp4 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), tmp3 );
+ tmp5 = anisotropyConversion( base_roughness, anisotropy, fileTexture(anisotropy_rotation_texture, vec3( 0, 0, 0 ), vec3( 3.14, 3.14, 3.14 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
+ tmp7 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = tmp5.roughness_u;
+ ftmp1 = tmp5.roughness_v;
+ ftmp2 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp3 = tmp5.tangent_u;
+ ftmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp4, 1.0).rgb, layers[2].layer, layers[2].base, alpha );
+ color = fresnelLayer( tmp7, vec3( base_ior ), base_weight, vec4( ftmp2, 1.0).rgb, layers[1].layer, color, color.a );
+ color = fresnelLayer( normal, vec3( coat_ior ), coat_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( ftmp3, cross(tmp7, ftmp3), tmp7 ) );
+ layers[2].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[2].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[2].tanFrame = orthoNormalize( mat3( tangent, cross(tmp7, tangent), tmp7 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="3"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/carpaint_blue_standard.material b/Studio/Content/Material Library/carpaint_blue_standard.material
new file mode 100644
index 00000000..fe5df31a
--- /dev/null
+++ b/Studio/Content/Material Library/carpaint_blue_standard.material
@@ -0,0 +1,231 @@
+<Material name="carpaint_blue_standard" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property formalName="Unit conversion factor" name="unit_conversion" type="Float" default="1.000000" category="Other"/>
+ <Property formalName="Normal Base Color" name="normal_base_color" type="Color" default="0.0427 0.1538 0.353" category="Material"/>
+ <Property formalName="Grazing Base Color" name="grazing_base_color" type="Color" default="0.0021 0.0074 0.017" category="Material"/>
+ <Property formalName="Orange Peel Amount" name="peel_amount" type="Float" default="0.100000" category="Material"/>
+ <Property formalName="Orange Peel Size" name="peel_size" type="Float" default="0.100000" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 ftmp0;
+float ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "coordinateSource.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "miNoise.glsllib"
+#include "flakeNoiseTexture.glsllib"
+#include "directionalFactor.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 ) );
+ layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.200000, 0.200000, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, 0.000000, 0.000000 );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx ) );
+ layers[1].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[1].tanFrame, varWorldPos, lightIdx, viewDir, 0.200000, 0.200000 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, 0.000000, 0.000000, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor );
+ layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, 0.200000, 0.200000, scatter_reflect );
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, sampleDiffuse( layers[1].tanFrame ) * aoFactor );
+ layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, 0.200000, 0.200000 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = coordinateSource(texture_coordinate_object, 0 );
+ ftmp0 = perlinNoiseBumpTexture( tmp2, ( peel_amount/10.000000 ), ( peel_size*unit_conversion ), false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.000000, 0.000000, 1.000000, normal );
+ ftmp1 = flakeNoiseTexture(tmp2, 0.000000, ( unit_conversion*0.002000 ), 0.350000 ).mono;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( ftmp1, vec4( vec3( 1, 0.117, 0.087 ), 1.0).rgb, layers[1].layer, layers[1].base * vec4( vec3( 1, 1, 1 ), 1.0), alpha );
+ color = fresnelLayer( ftmp0, vec3( 1.5, 1.5, 1.5 ), 1.000000, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(ftmp0, tangent), ftmp0 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/carpaint_color_peel_2_layer.material b/Studio/Content/Material Library/carpaint_color_peel_2_layer.material
new file mode 100644
index 00000000..17dd50d9
--- /dev/null
+++ b/Studio/Content/Material Library/carpaint_color_peel_2_layer.material
@@ -0,0 +1,255 @@
+<Material name="carpaint_color_peel_2_layer" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property formalName="Coat Index of refraction" name="coating_ior" type="Float" default="1.500000" category="Top coat"/>
+ <Property formalName="Coat Weight" name="coat_weight" type="Float" default="1.000000" category="Top coat"/>
+ <Property formalName="Coat Micro roughness" name="coat_roughness" type="Float" default="0.000000" category="Top coat"/>
+ <Property formalName="Coat Color" name="coat_color" type="Color" default="1 1 1" category="Top coat"/>
+ <Property formalName="Flake Weight" name="flake_intensity" type="Float" default="0.500000" category="Flake layer"/>
+ <Property formalName="Flake Flake size" name="flake_size" type="Float" default="0.002000" category="Flake layer"/>
+ <Property formalName="Flake Flake amount" name="flake_amount" type="Float" default="0.220000" category="Flake layer"/>
+ <Property formalName="Flake Micro roughness" name="flake_roughness" type="Float" default="0.200000" category="Flake layer"/>
+ <Property formalName="Flake Color" name="flake_color" type="Color" default="1 0.7 0.02" category="Flake layer"/>
+ <Property formalName="Base Color" name="base_color" type="Color" default="0.1 0.001 0.001" category="Base paint"/>
+ <Property formalName="Flake Macro roughness" name="flake_bumpiness" type="Float" default="0.600000" category="Flake layer"/>
+ <Property formalName="Orange peel strength" name="peel_amount" type="Float" default="1.000000" category="Top coat"/>
+ <Property formalName="Orange peel size" name="peel_size" type="Float" default="0.010000" category="Top coat"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 ftmp0;
+vec3 ftmp1;
+float ftmp2;
+float ftmp3;
+ vec4 tmpShadowTerm;
+
+layer_result layers[3];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "coordinateSource.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "miNoise.glsllib"
+#include "flakeNoiseBumpTexture.glsllib"
+#include "flakeNoiseTexture.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, coat_roughness, coat_roughness, scatter_reflect );
+
+ layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, flake_roughness, flake_roughness, scatter_reflect );
+
+ layers[2].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[2].layer += tmpShadowTerm * microfacetBSDF( layers[2].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.300000, 0.300000, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, coat_roughness, coat_roughness );
+
+ layers[1].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[1].tanFrame, varWorldPos, lightIdx, viewDir, flake_roughness, flake_roughness );
+
+ layers[2].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[2].tanFrame, varWorldPos, lightIdx );
+ layers[2].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[2].tanFrame, varWorldPos, lightIdx, viewDir, 0.300000, 0.300000 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness, scatter_reflect );
+
+ layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, flake_roughness, flake_roughness, scatter_reflect );
+
+ layers[2].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+ layers[2].layer += tmpShadowTerm * microfacetSampledBSDF( layers[2].tanFrame, viewDir, 0.300000, 0.300000, scatter_reflect );
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness );
+
+ layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, flake_roughness, flake_roughness );
+
+ layers[2].base += tmpShadowTerm * sampleDiffuse( layers[2].tanFrame ) * aoFactor;
+ layers[2].layer += tmpShadowTerm * sampleGlossyAniso( layers[2].tanFrame, viewDir, 0.300000, 0.300000 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = coordinateSource(texture_coordinate_object, 0 );
+ ftmp0 = perlinNoiseBumpTexture( tmp2, peel_amount, peel_size, false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.000000, 0.000000, 1.000000, normal );
+ ftmp1 = flakeNoiseBumpTexture(tmp2, flake_size, flake_bumpiness, normal );
+ ftmp2 = flakeNoiseTexture(tmp2, flake_intensity, flake_size, flake_amount ).mono;
+ ftmp3 = flakeNoiseTexture(tmp2, 0.000000, 0.002200, 1.000000 ).mono;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( ftmp3, vec4( vec3( 1, 0.01, 0.01 ), 1.0).rgb, layers[2].layer, layers[2].base * vec4( base_color, 1.0), alpha );
+ color = weightedLayer( ftmp2, vec4( flake_color, 1.0).rgb, layers[1].layer, color, color.a );
+ color = fresnelLayer( ftmp0, vec3( coating_ior ), coat_weight, vec4( coat_color, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(ftmp0, tangent), ftmp0 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(ftmp1, tangent), ftmp1 ) );
+ layers[2].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[2].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[2].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="3"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/carpaint_yellow_standard.material b/Studio/Content/Material Library/carpaint_yellow_standard.material
new file mode 100644
index 00000000..0116c348
--- /dev/null
+++ b/Studio/Content/Material Library/carpaint_yellow_standard.material
@@ -0,0 +1,231 @@
+<Material name="carpaint_yellow_standard" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property formalName="Unit conversion factor" name="unit_conversion" type="Float" default="1.000000" category="Other"/>
+ <Property formalName="Normal Base Color" name="normal_base_color" type="Color" default="0.659 0.4261 0.0494" category="Material"/>
+ <Property formalName="Grazing Base Color" name="grazing_base_color" type="Color" default="0.393 0.2654 0.0549" category="Material"/>
+ <Property formalName="Orange Peel Amount" name="peel_amount" type="Float" default="0.100000" category="Material"/>
+ <Property formalName="Orange Peel Size" name="peel_size" type="Float" default="0.100000" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 ftmp0;
+float ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "coordinateSource.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "miNoise.glsllib"
+#include "flakeNoiseTexture.glsllib"
+#include "directionalFactor.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 ) );
+ layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.200000, 0.200000, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, 0.000000, 0.000000 );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx ) );
+ layers[1].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[1].tanFrame, varWorldPos, lightIdx, viewDir, 0.200000, 0.200000 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, 0.000000, 0.000000, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor );
+ layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, 0.200000, 0.200000, scatter_reflect );
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color, grazing_base_color, 5.000000, sampleDiffuse( layers[1].tanFrame ) * aoFactor );
+ layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, 0.200000, 0.200000 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = coordinateSource(texture_coordinate_object, 0 );
+ ftmp0 = perlinNoiseBumpTexture( tmp2, ( peel_amount/10.000000 ), ( peel_size*unit_conversion ), false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.000000, 0.000000, 1.000000, normal );
+ ftmp1 = flakeNoiseTexture(tmp2, 0.000000, ( unit_conversion*0.002000 ), 0.350000 ).mono;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( ftmp1, vec4( vec3( 1, 0.117, 0.087 ), 1.0).rgb, layers[1].layer, layers[1].base * vec4( vec3( 1, 1, 1 ), 1.0), alpha );
+ color = fresnelLayer( ftmp0, vec3( 1.5, 1.5, 1.5 ), 1.000000, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(ftmp0, tangent), ftmp0 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/concrete.material b/Studio/Content/Material Library/concrete.material
new file mode 100644
index 00000000..ea7f43ed
--- /dev/null
+++ b/Studio/Content/Material Library/concrete.material
@@ -0,0 +1,235 @@
+<Material name="concrete" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.500000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.350000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/concrete_plain_bump.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="5 2" description="Scaling of the textures" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/concrete_plain.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="6.000000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+vec3 tmp6;
+vec3 ftmp0;
+vec3 ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(bump_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp1, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp6, vec3( material_ior ), 1.000000, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/copper.material b/Studio/Content/Material Library/copper.material
new file mode 100644
index 00000000..86c4e295
--- /dev/null
+++ b/Studio/Content/Material Library/copper.material
@@ -0,0 +1,178 @@
+<Material name="copper" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="metal_color" type="Color" default="0.805 0.395 0.305" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( 25.65, 25.65, 25.65 ), 1.000000, vec4( metal_color, 1.0).rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/leather_smoothed_black.material b/Studio/Content/Material Library/leather_smoothed_black.material
new file mode 100644
index 00000000..b1926c6f
--- /dev/null
+++ b/Studio/Content/Material Library/leather_smoothed_black.material
@@ -0,0 +1,236 @@
+<Material name="leather_smoothed_black" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.400000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.300000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/smooth_black_leather_spec.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="4 4" description="Scaling of the textures" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/smooth_black_leather.png" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/smooth_black_leather_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="2.000000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 tmp5;
+vec3 ftmp0;
+vec3 ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp1, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp5, vec3( material_ior ), 1.000000, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/maps/materials/art_paper_normal.png b/Studio/Content/Material Library/maps/materials/art_paper_normal.png
new file mode 100644
index 00000000..7a268603
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/art_paper_normal.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/art_paper_trans.png b/Studio/Content/Material Library/maps/materials/art_paper_trans.png
new file mode 100644
index 00000000..8465c27e
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/art_paper_trans.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/asphalt.png b/Studio/Content/Material Library/maps/materials/asphalt.png
new file mode 100644
index 00000000..f04e623a
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/asphalt.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/asphalt_bump.png b/Studio/Content/Material Library/maps/materials/asphalt_bump.png
new file mode 100644
index 00000000..002ba889
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/asphalt_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/bamboo_natural.png b/Studio/Content/Material Library/maps/materials/bamboo_natural.png
new file mode 100644
index 00000000..1e35a395
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/bamboo_natural.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/bamboo_natural_bump.png b/Studio/Content/Material Library/maps/materials/bamboo_natural_bump.png
new file mode 100644
index 00000000..07e813a7
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/bamboo_natural_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/bamboo_natural_spec.png b/Studio/Content/Material Library/maps/materials/bamboo_natural_spec.png
new file mode 100644
index 00000000..b139113d
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/bamboo_natural_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_a.png b/Studio/Content/Material Library/maps/materials/brushed_a.png
new file mode 100644
index 00000000..c0602ca5
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_a.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_a_full_contrast_scratched.png b/Studio/Content/Material Library/maps/materials/brushed_a_full_contrast_scratched.png
new file mode 100644
index 00000000..93c9ab85
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_a_full_contrast_scratched.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_a_scratched_50_percent.png b/Studio/Content/Material Library/maps/materials/brushed_a_scratched_50_percent.png
new file mode 100644
index 00000000..f132e25b
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_a_scratched_50_percent.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_chrome.png b/Studio/Content/Material Library/maps/materials/brushed_chrome.png
new file mode 100644
index 00000000..d262e81d
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_chrome.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_chrome_spec.png b/Studio/Content/Material Library/maps/materials/brushed_chrome_spec.png
new file mode 100644
index 00000000..93fca975
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_chrome_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_full_contrast.png b/Studio/Content/Material Library/maps/materials/brushed_full_contrast.png
new file mode 100644
index 00000000..a7864fe3
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_full_contrast.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/brushed_full_contrast_inverted.png b/Studio/Content/Material Library/maps/materials/brushed_full_contrast_inverted.png
new file mode 100644
index 00000000..928a0d65
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/brushed_full_contrast_inverted.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/bubinga.png b/Studio/Content/Material Library/maps/materials/bubinga.png
new file mode 100644
index 00000000..59d65d2e
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/bubinga.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/bubinga_bump.png b/Studio/Content/Material Library/maps/materials/bubinga_bump.png
new file mode 100644
index 00000000..cdb722c9
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/bubinga_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/bubinga_spec.png b/Studio/Content/Material Library/maps/materials/bubinga_spec.png
new file mode 100644
index 00000000..ebc7d650
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/bubinga_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/carbon_fiber.png b/Studio/Content/Material Library/maps/materials/carbon_fiber.png
new file mode 100644
index 00000000..69e2ba54
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/carbon_fiber.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/carbon_fiber_aniso.png b/Studio/Content/Material Library/maps/materials/carbon_fiber_aniso.png
new file mode 100644
index 00000000..8bd7a30d
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/carbon_fiber_aniso.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/carbon_fiber_bump.png b/Studio/Content/Material Library/maps/materials/carbon_fiber_bump.png
new file mode 100644
index 00000000..e1cca48e
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/carbon_fiber_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/carbon_fiber_spec.png b/Studio/Content/Material Library/maps/materials/carbon_fiber_spec.png
new file mode 100644
index 00000000..5c50a00a
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/carbon_fiber_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/concentric_milled_steel.png b/Studio/Content/Material Library/maps/materials/concentric_milled_steel.png
new file mode 100644
index 00000000..56101f25
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/concentric_milled_steel.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/concentric_milled_steel_aniso.png b/Studio/Content/Material Library/maps/materials/concentric_milled_steel_aniso.png
new file mode 100644
index 00000000..f6071d95
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/concentric_milled_steel_aniso.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/concrete_plain.png b/Studio/Content/Material Library/maps/materials/concrete_plain.png
new file mode 100644
index 00000000..fb16072a
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/concrete_plain.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/concrete_plain_bump.png b/Studio/Content/Material Library/maps/materials/concrete_plain_bump.png
new file mode 100644
index 00000000..e20f1cd3
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/concrete_plain_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing.png b/Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing.png
new file mode 100644
index 00000000..ab362049
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing_normal.png b/Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing_normal.png
new file mode 100644
index 00000000..3b96bbf7
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/cyclone_mesh_fencing_normal.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/emissive.png b/Studio/Content/Material Library/maps/materials/emissive.png
new file mode 100644
index 00000000..599b1ccc
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/emissive.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/emissive_mask.png b/Studio/Content/Material Library/maps/materials/emissive_mask.png
new file mode 100644
index 00000000..599b1ccc
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/emissive_mask.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/gentle_noise.png b/Studio/Content/Material Library/maps/materials/gentle_noise.png
new file mode 100644
index 00000000..a163c829
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/gentle_noise.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/granite_black.png b/Studio/Content/Material Library/maps/materials/granite_black.png
new file mode 100644
index 00000000..629cc910
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/granite_black.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/granite_yellow.png b/Studio/Content/Material Library/maps/materials/granite_yellow.png
new file mode 100644
index 00000000..cdf8c19a
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/granite_yellow.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/grunge_b.png b/Studio/Content/Material Library/maps/materials/grunge_b.png
new file mode 100644
index 00000000..fa43782b
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/grunge_b.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/grunge_b1.png b/Studio/Content/Material Library/maps/materials/grunge_b1.png
new file mode 100644
index 00000000..c4e44295
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/grunge_b1.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/grunge_d.png b/Studio/Content/Material Library/maps/materials/grunge_d.png
new file mode 100644
index 00000000..c62a5a01
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/grunge_d.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/grunge_texture_01.png b/Studio/Content/Material Library/maps/materials/grunge_texture_01.png
new file mode 100644
index 00000000..d2567191
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/grunge_texture_01.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/mahogany.png b/Studio/Content/Material Library/maps/materials/mahogany.png
new file mode 100644
index 00000000..f438a632
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/mahogany.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/mahogany_bump.png b/Studio/Content/Material Library/maps/materials/mahogany_bump.png
new file mode 100644
index 00000000..3f4f0d0c
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/mahogany_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/mahogany_floorboards.png b/Studio/Content/Material Library/maps/materials/mahogany_floorboards.png
new file mode 100644
index 00000000..c9fc35a4
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/mahogany_floorboards.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/mahogany_floorboards_bump.png b/Studio/Content/Material Library/maps/materials/mahogany_floorboards_bump.png
new file mode 100644
index 00000000..5a54372c
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/mahogany_floorboards_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/mahogany_floorboards_spec.png b/Studio/Content/Material Library/maps/materials/mahogany_floorboards_spec.png
new file mode 100644
index 00000000..0784bb87
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/mahogany_floorboards_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/mahogany_spec.png b/Studio/Content/Material Library/maps/materials/mahogany_spec.png
new file mode 100644
index 00000000..c82144db
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/mahogany_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/metal_mesh.png b/Studio/Content/Material Library/maps/materials/metal_mesh.png
new file mode 100644
index 00000000..f722347c
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/metal_mesh.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/metal_mesh_bump.png b/Studio/Content/Material Library/maps/materials/metal_mesh_bump.png
new file mode 100644
index 00000000..756d9c4c
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/metal_mesh_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/metal_mesh_spec.png b/Studio/Content/Material Library/maps/materials/metal_mesh_spec.png
new file mode 100644
index 00000000..7444604c
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/metal_mesh_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/paper_diffuse.png b/Studio/Content/Material Library/maps/materials/paper_diffuse.png
new file mode 100644
index 00000000..3fbd6534
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/paper_diffuse.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/paper_trans.png b/Studio/Content/Material Library/maps/materials/paper_trans.png
new file mode 100644
index 00000000..6bf7c50d
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/paper_trans.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/powdercoat_bump_01.png b/Studio/Content/Material Library/maps/materials/powdercoat_bump_01.png
new file mode 100644
index 00000000..769f549c
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/powdercoat_bump_01.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/randomGradient1D.png b/Studio/Content/Material Library/maps/materials/randomGradient1D.png
new file mode 100644
index 00000000..0d37132f
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/randomGradient1D.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/randomGradient2D.png b/Studio/Content/Material Library/maps/materials/randomGradient2D.png
new file mode 100644
index 00000000..8b60ca68
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/randomGradient2D.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/randomGradient3D.png b/Studio/Content/Material Library/maps/materials/randomGradient3D.png
new file mode 100644
index 00000000..c22e1ba8
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/randomGradient3D.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/randomGradient4D.png b/Studio/Content/Material Library/maps/materials/randomGradient4D.png
new file mode 100644
index 00000000..ad282d85
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/randomGradient4D.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/shadow.png b/Studio/Content/Material Library/maps/materials/shadow.png
new file mode 100644
index 00000000..599b1ccc
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/shadow.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/smooth_black_leather.png b/Studio/Content/Material Library/maps/materials/smooth_black_leather.png
new file mode 100644
index 00000000..ce826353
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/smooth_black_leather.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/smooth_black_leather_bump.png b/Studio/Content/Material Library/maps/materials/smooth_black_leather_bump.png
new file mode 100644
index 00000000..1c71529f
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/smooth_black_leather_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/smooth_black_leather_spec.png b/Studio/Content/Material Library/maps/materials/smooth_black_leather_spec.png
new file mode 100644
index 00000000..7e289c13
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/smooth_black_leather_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/spherical_checker.png b/Studio/Content/Material Library/maps/materials/spherical_checker.png
new file mode 100644
index 00000000..e42394dd
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/spherical_checker.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/studded_rubber_bump.png b/Studio/Content/Material Library/maps/materials/studded_rubber_bump.png
new file mode 100644
index 00000000..b7514764
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/studded_rubber_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/teak.png b/Studio/Content/Material Library/maps/materials/teak.png
new file mode 100644
index 00000000..5d1a63b8
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/teak.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/teak_bump.png b/Studio/Content/Material Library/maps/materials/teak_bump.png
new file mode 100644
index 00000000..cd2496a2
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/teak_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/teak_spec.png b/Studio/Content/Material Library/maps/materials/teak_spec.png
new file mode 100644
index 00000000..87512881
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/teak_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/walnut.png b/Studio/Content/Material Library/maps/materials/walnut.png
new file mode 100644
index 00000000..abe5704a
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/walnut.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/walnut_bump.png b/Studio/Content/Material Library/maps/materials/walnut_bump.png
new file mode 100644
index 00000000..a6434fd3
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/walnut_bump.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/walnut_spec.png b/Studio/Content/Material Library/maps/materials/walnut_spec.png
new file mode 100644
index 00000000..b03a1dca
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/walnut_spec.png
Binary files differ
diff --git a/Studio/Content/Material Library/maps/materials/white_marble.png b/Studio/Content/Material Library/maps/materials/white_marble.png
new file mode 100644
index 00000000..472b33eb
--- /dev/null
+++ b/Studio/Content/Material Library/maps/materials/white_marble.png
Binary files differ
diff --git a/Studio/Content/Material Library/mesh_fence.material b/Studio/Content/Material Library/mesh_fence.material
new file mode 100644
index 00000000..f284b29e
--- /dev/null
+++ b/Studio/Content/Material Library/mesh_fence.material
@@ -0,0 +1,236 @@
+<Material name="mesh_fence" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="15.000000" description="Index of refraction of the material" category="Material"/>
+ <Property name="glossy_weight" type="Float" min="0.000000" max="1.000000" default="0.500000" description="Reflectivity factor at incident angles" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.250000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/cyclone_mesh_fencing.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="3 3" description="Scaling of the textures" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/cyclone_mesh_fencing_normal.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="2.000000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+texture_return tmp4;
+vec3 tmp5;
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "tangentSpaceNormalTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( tmp4.mono );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb );
+ tmp5 = tangentSpaceNormalTexture( bump_texture, bump_amount, false, false, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat );
+ ftmp0 = tmp4.tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp0, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp5, vec3( material_ior ), glossy_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="13"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/metal_mesh_fine.material b/Studio/Content/Material Library/metal_mesh_fine.material
new file mode 100644
index 00000000..23a250ac
--- /dev/null
+++ b/Studio/Content/Material Library/metal_mesh_fine.material
@@ -0,0 +1,234 @@
+<Material name="metal_mesh_fine" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="15.000000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/metal_mesh.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="75 75" description="Scaling of the textures" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/metal_mesh_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="13.000000" description="Value determining the bumpiness" category="Material"/>
+ <Property name="cutout_opacity_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="cutout" default="./maps/materials/metal_mesh_spec.png" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 tmp4;
+vec3 tmp6;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( fileTexture(cutout_opacity_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( tmp4, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp6, vec3( material_ior ), 1.000000, vec4( tmp4, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp6, tangent), tmp6 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="13"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/paper_artistic.material b/Studio/Content/Material Library/paper_artistic.material
new file mode 100644
index 00000000..9c10d922
--- /dev/null
+++ b/Studio/Content/Material Library/paper_artistic.material
@@ -0,0 +1,257 @@
+<Material name="paper_artistic" version="1.0">
+ <MetaData >
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Translucent Falloff" name="uTranslucentFalloff" type="Float" default="0.0" category="Material"/>
+ <Property formalName="Diffuse Light Bend" name="uDiffuseLightWrap" type="Float" min="0.0" max="1.0" default="0.0" category="Material"/>
+ <Property formalName="Transparency" name="uOpacity" type="Float" min="0.0" max="100.0" default="100.0" category="Material"/>
+ <Property name="transmission_weight" type="Float" default="0.200000" description="Value determining transmission" category="Material"/>
+ <Property name="transmission_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="transmission" default="./maps/materials/art_paper_trans.png" category="Textures"/>
+ <Property name="texture_tiling" type="Float2" default="5 5" description="Scaling of the textures" category="Textures"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/paper_diffuse.png" category="Textures"/>
+ <Property name="reflection_weight" type="Float" default="0.800000" description="Value determining reflection" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/art_paper_normal.png" category="Textures"/>
+ <Property name="bump_amount" type="Float" default="0.500000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define color_layer_blend 0
+#define color_layer_add 1
+#define color_layer_multiply 2
+#define color_layer_screen 3
+#define color_layer_overlay 4
+#define color_layer_brightness 5
+#define color_layer_color 6
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct bsdf_component
+{
+ float weight;
+ vec4 component;
+};
+
+
+struct color_layer
+{
+ vec3 layer_color;
+ float weight;
+ int mode;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp1;
+vec3 tmp2;
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "tangentSpaceNormalTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "normalizedMix.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "diffuseTransmissionBSDF.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileTexture.glsllib"
+#include "blendColorLayers.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, diffuseTransmissionBSDF( -normal, lightDir, viewDir, lightDiffuse, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 )) ) );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, lightDiffuse * sampleAreaDiffuseTransmissive( layers[0].tanFrame, varWorldPos, lightIdx, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx )) ) );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+
+#endif
+}
+
+void computeFrontLayerRnmColor( in vec3 normal, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+#if UIC_ENABLE_RNM
+ layers[0].base += tmpShadowTerm * diffuseRNM( normal, rnmX, rnmY, rnmZ );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerRnmColor( in vec3 normal, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+#if UIC_ENABLE_RNM
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( tangentSpaceNormalTexture( bump_texture, bump_amount, false, false, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat ) );
+}
+
+void computeTemporaries()
+{
+ tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp2 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ ftmp0 = blendColorLayers( color_layer[1]( color_layer(blendColorLayers( color_layer[1]( color_layer(fileTexture(transmission_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint, 1.000000, color_layer_blend ) ), tmp2, mono_average ).tint, 1.000000, color_layer_multiply ) ), vec3( 1, 1, 1 ), mono_average ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( tmp2, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec4 computeOpacity(in vec4 color)
+{
+ vec4 rgba = color;
+ rgba.a = uOpacity * 0.01;
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="257"/>
+ <LayerKey count="1"/>
+ <Pass >
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/paper_office.material b/Studio/Content/Material Library/paper_office.material
new file mode 100644
index 00000000..18379cf1
--- /dev/null
+++ b/Studio/Content/Material Library/paper_office.material
@@ -0,0 +1,255 @@
+<Material name="paper_office" version="1.0">
+ <MetaData >
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Translucent Falloff" name="uTranslucentFalloff" type="Float" default="0.0" category="Material"/>
+ <Property formalName="Diffuse Light Bend" name="uDiffuseLightWrap" type="Float" min="0.0" max="1.0" default="0.0" category="Material"/>
+ <Property formalName="Transparency" name="uOpacity" type="Float" min="0.0" max="100.0" default="100.0" category="Material"/>
+ <Property name="transmission_weight" type="Float" default="0.200000" description="Value determining transmission" category="Material"/>
+ <Property name="transmission_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="transmission" default="./maps/materials/paper_trans.png" category="Textures"/>
+ <Property name="texture_tiling" type="Float2" default="1 1" description="Scaling of the textures" category="Textures"/>
+ <Property name="paper_color" type="Color" default="0.531 0.531 0.531" description="Color of the paper" category="Material"/>
+ <Property name="reflection_weight" type="Float" default="0.800000" description="Value determining reflection" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/paper_diffuse.png" category="Textures"/>
+ <Property name="bump_amount" type="Float" default="0.500000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define color_layer_blend 0
+#define color_layer_add 1
+#define color_layer_multiply 2
+#define color_layer_screen 3
+#define color_layer_overlay 4
+#define color_layer_brightness 5
+#define color_layer_color 6
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct bsdf_component
+{
+ float weight;
+ vec4 component;
+};
+
+
+struct color_layer
+{
+ vec3 layer_color;
+ float weight;
+ int mode;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp1;
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "normalizedMix.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "diffuseTransmissionBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "blendColorLayers.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, diffuseTransmissionBSDF( -normal, lightDir, viewDir, lightDiffuse, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 )) ) );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, lightDiffuse * sampleAreaDiffuseTransmissive( layers[0].tanFrame, varWorldPos, lightIdx, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx )) ) );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+
+#endif
+}
+
+void computeFrontLayerRnmColor( in vec3 normal, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+#if UIC_ENABLE_RNM
+ layers[0].base += tmpShadowTerm * diffuseRNM( normal, rnmX, rnmY, rnmZ );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerRnmColor( in vec3 normal, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+#if UIC_ENABLE_RNM
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ ftmp0 = blendColorLayers( color_layer[1]( color_layer(blendColorLayers( color_layer[1]( color_layer(fileTexture(transmission_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint, 0.700000, color_layer_blend ) ), paper_color, mono_average ).tint, 1.000000, color_layer_multiply ) ), vec3( 1, 1, 1 ), mono_average ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( paper_color, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec4 computeOpacity(in vec4 color)
+{
+ vec4 rgba = color;
+ rgba.a = uOpacity * 0.01;
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="257"/>
+ <LayerKey count="1"/>
+ <Pass >
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/plastic_structured_red.material b/Studio/Content/Material Library/plastic_structured_red.material
new file mode 100644
index 00000000..7dbb510a
--- /dev/null
+++ b/Studio/Content/Material Library/plastic_structured_red.material
@@ -0,0 +1,204 @@
+<Material name="plastic_structured_red" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property name="material_ior" type="Float" default="1.800000" category="Material"/>
+ <Property name="roughness" type="Float" default="0.250000" category="Material"/>
+ <Property name="diffuse_color" type="Color" default="0.451 0.04 0.035" category="Material"/>
+ <Property name="texture_scaling" type="Float" default="0.100000" category="Material"/>
+ <Property name="bump_factor" type="Float" default="0.400000" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "coordinateSource.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( perlinNoiseBumpTexture( transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( ( texture_scaling*10.000000 ) ) ), coordinateSource(texture_coordinate_object, 0 ) ), bump_factor, 1.000000, false, false, 0.000000, 6, true, vec3( 0.000000, 0.000000, 0.000000 ), 0.070000, 0.300000, 1.000000, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( material_ior ), 0.350000, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, layers[0].base * vec4( diffuse_color, 1.0), alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/plastic_structured_red_emissive.material b/Studio/Content/Material Library/plastic_structured_red_emissive.material
new file mode 100644
index 00000000..71ac694f
--- /dev/null
+++ b/Studio/Content/Material Library/plastic_structured_red_emissive.material
@@ -0,0 +1,228 @@
+<Material name="plastic_structured_red_emissive" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property name="material_ior" type="Float" default="1.800000" category="Material"/>
+ <Property name="roughness" type="Float" default="0.250000" category="Material"/>
+ <Property name="diffuse_color" type="Color" default="0.451 0.04 0.035" category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property name="texture_scaling" type="Float" default="0.100000" category="Material"/>
+ <Property name="bump_factor" type="Float" default="0.400000" category="Material"/>
+ <Property formalName="Emissive Mask Map" name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "coordinateSource.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+#include "monoChannel.glsllib"
+#include "fileTexture.glsllib"
+#include "textureCoordinateInfo.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color*fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( perlinNoiseBumpTexture( transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( ( texture_scaling*10.000000 ) ) ), coordinateSource(texture_coordinate_object, 0 ) ), bump_factor, 1.000000, false, false, 0.000000, 6, true, vec3( 0.000000, 0.000000, 0.000000 ), 0.070000, 0.300000, 1.000000, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( material_ior ), 0.350000, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, layers[0].base * vec4( diffuse_color, 1.0), alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/porcelain.material b/Studio/Content/Material Library/porcelain.material
new file mode 100644
index 00000000..d9186533
--- /dev/null
+++ b/Studio/Content/Material Library/porcelain.material
@@ -0,0 +1,181 @@
+<Material name="porcelain" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.500000" description="Index of refraction of the material" category="Material"/>
+ <Property name="glossy_weight" type="Float" min="0.000000" max="1.000000" default="1.000000" description="Strength of glossy reflection" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.150000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="porcelain_color" type="Color" default="0.92 0.92 0.92" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( material_ior ), glossy_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, layers[0].base * vec4( porcelain_color, 1.0), alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/powder_coat.material b/Studio/Content/Material Library/powder_coat.material
new file mode 100644
index 00000000..de34e6cc
--- /dev/null
+++ b/Studio/Content/Material Library/powder_coat.material
@@ -0,0 +1,221 @@
+<Material name="powder_coat" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="5.000000" category="Material"/>
+ <Property name="glossy_weight" type="Float" default="0.500000" category="Material"/>
+ <Property name="roughness" type="Float" default="0.100000" category="Material"/>
+ <Property name="reflectivity" type="Float" default="0.100000" category="Material"/>
+ <Property name="diffuse_weight" type="Float" default="1.000000" category="Material"/>
+ <Property name="powdercoat_diffuse_color" type="Color" default="0.046 0.046 0.054" category="Material"/>
+ <Property name="powdercoat_bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/powdercoat_bump_01.png" category="Material"/>
+ <Property name="bump_factor" type="Float" default="2.000000" category="Material"/>
+ <Property name="texture_scaling" type="Vector" default="3 3 3" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( fileBumpTexture(powdercoat_bump_texture, bump_factor, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), texture_scaling ), textureCoordinateInfo( texCoord0, tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+}
+
+void computeTemporaries()
+{
+ ftmp0 = vec3( reflectivity );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( diffuse_weight, vec4( powdercoat_diffuse_color, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( normal, vec3( material_ior ), glossy_weight, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/powder_coat_emissive.material b/Studio/Content/Material Library/powder_coat_emissive.material
new file mode 100644
index 00000000..af14c23b
--- /dev/null
+++ b/Studio/Content/Material Library/powder_coat_emissive.material
@@ -0,0 +1,256 @@
+<Material name="powder_coat_emisssive" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="5.000000" category="Material"/>
+ <Property name="glossy_weight" type="Float" default="0.500000" category="Material"/>
+ <Property name="roughness" type="Float" default="0.100000" category="Material"/>
+ <Property name="reflectivity" type="Float" default="0.100000" category="Material"/>
+ <Property name="diffuse_weight" type="Float" default="1.000000" category="Material"/>
+ <Property name="powdercoat_diffuse_color" type="Color" default="0.046 0.046 0.054" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="powdercoat_bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/powdercoat_bump_01.png" category="Material"/>
+ <Property name="bump_factor" type="Float" default="2.000000" category="Material"/>
+ <Property name="texture_scaling" type="Vector" default="3 3 3" category="Material"/>
+ <Property formalName="Emissive Mask Map" name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+#include "fileTexture.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( ( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint*emission_color )*intensity ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+void computeFrontLayerRnmColor( in vec3 normal, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+#if UIC_ENABLE_RNM
+ layers[0].layer += tmpShadowTerm * glossyRNM( normal, rnmX, rnmY, rnmZ );
+
+ layers[1].layer += tmpShadowTerm * diffuseRNM( normal, rnmX, rnmY, rnmZ );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerRnmColor( in vec3 normal, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+#if UIC_ENABLE_RNM
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( fileBumpTexture(powdercoat_bump_texture, bump_factor, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), texture_scaling ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmp3 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ ftmp0 = vec3( reflectivity );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( diffuse_weight, vec4( powdercoat_diffuse_color, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( normal, vec3( material_ior ), glossy_weight, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/rubber_studded_black.material b/Studio/Content/Material Library/rubber_studded_black.material
new file mode 100644
index 00000000..b1f46f6a
--- /dev/null
+++ b/Studio/Content/Material Library/rubber_studded_black.material
@@ -0,0 +1,219 @@
+<Material name="rubber_studded_black" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.800000" description="Index of refraction of the material" category="Material"/>
+ <Property name="glossy_weight" type="Float" min="0.000000" max="1.000000" default="0.500000" description="Reflectivity of the material at the incident lighting angles. 1.0 means totally reflective, 0.0 means no reflection" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.250000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="base_color" type="Color" default="0 0 0" description="Color of the material" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/studded_rubber_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="9.000000" description="Value determining the bumpiness" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="10 7" description="Scaling of the textures" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+// temporary declarations
+vec3 tmp4;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp4, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp4, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp4 = fileBumpTexture(bump_texture, bump_amount, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( base_color, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp4, vec3( material_ior ), glossy_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp4, tangent), tmp4 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp4, tangent), tmp4 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/rubber_studded_emissive.material b/Studio/Content/Material Library/rubber_studded_emissive.material
new file mode 100644
index 00000000..1c31859c
--- /dev/null
+++ b/Studio/Content/Material Library/rubber_studded_emissive.material
@@ -0,0 +1,238 @@
+<Material name="rubber_studded_emissive" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.800000" description="Index of refraction of the material" category="Material"/>
+ <Property name="glossy_weight" type="Float" min="0.000000" max="1.000000" default="0.500000" description="Reflectivity of the material at the incident lighting angles. 1.0 means totally reflective, 0.0 means no reflection" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.250000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="base_color" type="Color" default="0 0 0" description="Color of the material" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/studded_rubber_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="9.000000" description="Value determining the bumpiness" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="10 7" description="Scaling of the textures" category="Material"/>
+ <Property name="intensity" type="Float" default="1.000000" category="Material"/>
+ <Property name="emission_color" type="Color" default="0 0 0" category="Material"/>
+ <Property name="emissive_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
+ <Property name="emissive_mask_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" default="./maps/materials/emissive_mask.png" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+vec3 tmp5;
+texture_coordinate_info tmp6;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+#include "fileTexture.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color*( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp6, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint*fileTexture(emissive_mask_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp6, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmp6 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp3 );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( base_color, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp5, vec3( material_ior ), glossy_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/simple_glass.material b/Studio/Content/Material Library/simple_glass.material
new file mode 100644
index 00000000..2bb8654e
--- /dev/null
+++ b/Studio/Content/Material Library/simple_glass.material
@@ -0,0 +1,197 @@
+<Material name="simple_glass" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Fresnel Power" name="uFresnelPower" type="Float" default="1.0" category="Material"/>
+ <Property formalName="Minimum Opacity" name="uMinOpacity" type="Float" default="0.5" category="Material"/>
+ <Property formalName="Reflectivity" name="reflectivity_amount" type="Float" min="0.000000" max="1.000000" default="1.000000" description="reflectivity factor" category="Material"/>
+ <Property formalName="Glass ior" name="glass_ior" hidden="True" type="Float" default="1.100000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glass Color" name="glass_color" type="Color" default="0.9 0.9 0.9" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "abbeNumberIOR.glsllib"
+#include "fresnelLayer.glsllib"
+#include "refraction.glsllib"
+
+bool evalTwoSided()
+{
+ return( true );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect_transmit );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, 0.000000, 0.000000 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, 0.000000, 0.000000, scatter_reflect_transmit );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( true ? 1.0f : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ ftmp0 = vec3( reflectivity_amount );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( ftmp0, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color)
+{
+ vec4 rgba = color;
+ float ratio = simpleFresnel( normal, materialIOR, uFresnelPower );
+ vec3 absorb_color = ( log( glass_color )/-1.000000 );
+ // prevent log(0) -> inf number issue
+ if ( isinf(absorb_color.r) ) absorb_color.r = 1.0;
+ if ( isinf(absorb_color.g) ) absorb_color.g = 1.0;
+ if ( isinf(absorb_color.b) ) absorb_color.b = 1.0;
+ rgba.rgb = mix(vec3(1.0) - absorb_color, rgba.rgb * (vec3(1.0) - absorb_color), ratio);
+ rgba.a = mix(uMinOpacity, alpha, ratio);
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="36"/>
+ <LayerKey count="1"/>
+ <Pass >
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ <RenderState name="CullFace"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/steel_milled_concentric.material b/Studio/Content/Material Library/steel_milled_concentric.material
new file mode 100644
index 00000000..b6f6bfa3
--- /dev/null
+++ b/Studio/Content/Material Library/steel_milled_concentric.material
@@ -0,0 +1,237 @@
+<Material name="steel_milled_concentric" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="20.000000" description="Index of refraction of the material" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/concentric_milled_steel.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="8 5" description="Scaling of the textures" category="Material"/>
+ <Property name="anisotropy" type="Float" min="0.010000" max="100.000000" default="0.800000" description="The anisotropy of the roughness" category="Material"/>
+ <Property name="anisotropy_rot_texture" type="Texture" filter="linear" minfilter="linear" clamp="repeat" usage="anisotropy" default="./maps/materials/concentric_milled_steel_aniso.png" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct anisotropy_return
+{
+ float roughness_u;
+ float roughness_v;
+ vec3 tangent_u;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp3;
+texture_return tmp4;
+anisotropy_return tmp5;
+float ftmp0;
+float ftmp1;
+vec3 ftmp2;
+vec3 ftmp3;
+vec3 ftmp4;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "monoChannel.glsllib"
+#include "fileTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "anisotropyConversion.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, ftmp0, ftmp1 );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, ftmp0, ftmp1, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp0, ftmp1 );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
+ tmp5 = anisotropyConversion( tmp4.mono, anisotropy, fileTexture(anisotropy_rot_texture, vec3( -1, -1, -1 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
+ ftmp0 = tmp5.roughness_u;
+ ftmp1 = tmp5.roughness_v;
+ ftmp2 = fileTexture(diffuse_texture, vec3( 1, 1, 1 ), vec3( -1, -1, -1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp3 = tmp5.tangent_u;
+ ftmp4 = tmp4.tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( material_ior ), 1.000000, vec4( ftmp2, 1.0).rgb, layers[0].layer, layers[0].base * vec4( ftmp4, 1.0), alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( ftmp3, cross(normal, ftmp3), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/thin_glass_frosted.material b/Studio/Content/Material Library/thin_glass_frosted.material
new file mode 100644
index 00000000..38de93c8
--- /dev/null
+++ b/Studio/Content/Material Library/thin_glass_frosted.material
@@ -0,0 +1,485 @@
+<Material name="thin_glass_frosted" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Fresnel Power" name="uFresnelPower" type="Float" default="1.0" category="Material"/>
+ <Property formalName="Roughness" name="roughness" type="Float" min="0.000000" max="1.000000" default="1.000000" description="surface reflection roughness" category="Material"/>
+ <Property formalName="Reflectivity" name="reflectivity_amount" type="Float" min="0.000000" max="1.000000" default="0.100000" description="reflectivity factor" category="Material"/>
+ <Property formalName="Glass ior" name="glass_ior" type="Float" default="1.100000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glass Color" name="glass_color" type="Color" default="0.9 0.9 0.9" description="Color of the material" category="Material"/>
+ <Property formalName="Glass Bump map" name="glass_bump" description="Additional bump map for surface" type="Texture" clamp="repeat" category="Material"/>
+ <Property formalName="Glass Bump Factor" name="glass_bfactor" description="Bump map factor" default="0.0" category="Material"/>
+ <Property formalName="Glass Bump Inside" name="glass_binside" description="Use bump map for internal lighting only" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Blur Width" name="blur_size" type="Float" default="8" min="1" max="50" description="Amount of blurring behind the glass" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property formalName="Refract Depth" name="refract_depth" type="Float" default="5" min="0" max="20" description="Degree of bend from refraction. Allows control of refraction without affecting lighting" category="Refraction"/>
+ <Property name="bumpCoords" type="Vector" default="1 1 1" category="Refraction"/>
+ <Property name="bumpScale" type="Float" min="0.000000" max="5.000000" default="0.500000" category="Refraction"/>
+ <Property name="bumpBands" type="Long" min="1.000000" max="10.000000" default="1" category="Refraction"/>
+ <Property formalName="Light Position" name="intLightPos" type="Float2" description="Position in UV space of the band-light" default="0.5 0" category="Translucent Lighting"/>
+ <Property formalName="Light Color" name="intLightCol" type="Color" description="Color of the band-light" default="0.9 0.9 0.9" category="Translucent Lighting"/>
+ <Property formalName="Light Brightness" name="intLightBrt" type="Float" description="Brightness of the band-light" default="0" category="Translucent Lighting"/>
+ <Property formalName="Light Rotation" name="intLightRot" type="Float" description="Angle the lightsource is oriented (band is perpendicular to this)" default="0" min="0" max="360" category="Translucent Lighting"/>
+ <Property formalName="Falloff rate" name="intLightFall" type="Float" description="Rate at which intensity drops off" default="2.0" category="Translucent Lighting"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader name="MAIN">
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+// temporary declarations
+texture_coordinate_info tmp0;
+texture_coordinate_info tmp1;
+vec3 ftmp0;
+vec3 ftmp1;
+vec3 ftmp2;
+vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "coordinateSource.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "abbeNumberIOR.glsllib"
+#include "average.glsllib"
+#include "perlinNoiseTexture.glsllib"
+#include "fresnelLayer.glsllib"
+#include "refraction.glsllib"
+
+uniform sampler2D refractiveTexture;
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect_transmit );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ if ( glass_bfactor > 0.0 )
+ {
+ ftmp2 = fileBumpTexture(glass_bump, glass_bfactor, mono_average, tmp0, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ if (!glass_binside) { normal = ftmp2; }
+ }
+
+ return( perlinNoiseBumpTexture( tmp1, bumpScale, 1.000000, false, false, 0.000000, bumpBands, false, vec3( 0.000000, 0.000000, 0.000000 ), 0.5, 0.0, 1.000000, normal ) );
+}
+
+void computeTemporaries()
+{
+ //tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), refractCoords ), coordinateSource(texture_coordinate_world, 0 ) );
+ //ftmp1 = perlinNoiseBumpTexture( tmp0, refractScale, 1.000000, false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.0, 0.5, 1.000000, viewDir );
+ tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), coordinateSource(texture_coordinate_world, 0 ) );
+ ftmp1 = viewDir;
+ ftmp0 = vec3( reflectivity_amount );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( ftmp0, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec3 getRefractUV( in vec2 baseUV, in vec3 normal, in float materialIOR, in float refractDepth )
+{
+ // Real honest-to-goodness refraction!
+ vec3 refractedDir = refract( -viewDir, normal, 1.0 / materialIOR );
+ float thickness = refractDepth / clamp( dot(viewDir, normal), 0.0001, 1.0 );
+
+ // This will do an "AA" version of that loss due to critical angle and TIR
+ // fakes the same effect than using the glsl refract.
+ float weight = smoothstep( 0.0, 1.0, abs(dot(viewDir, normal)) * 100.0 );
+
+ // Trace out the refracted ray and the straight view ray
+ refractedDir *= thickness;
+ vec3 rawDir = -viewDir * thickness;
+
+ vec3 displace = refractedDir - rawDir;
+ vec3 newUV = vec3(baseUV + displace.xy, weight);
+ return newUV;
+}
+
+vec4 doFakeInnerLight( in vec3 normal, in vec3 absorb_color )
+{
+ vec3 lightColor = intLightCol * intLightBrt;
+
+ float cosRot = cos(intLightRot * 0.01745329251);
+ float sinRot = sin(intLightRot * 0.01745329251);
+ vec2 uvDir = vec2(sinRot, cosRot);
+
+ vec2 dvec = texCoord0.xy - intLightPos;
+ float dist = dot( dvec, uvDir );
+ float fallRate = log2( max( abs(intLightFall), 1.01 ) );
+ vec3 fallCol = exp2( -abs(dist) * fallRate / absorb_color );
+
+ vec3 projDir = (tangent * uvDir.x + binormal * uvDir.y) * dist * intLightFall - surfNormal * refract_depth;
+ projDir = normalize(projDir);
+
+ vec4 retVal = vec4(lightColor * fallCol, 1.0);
+ retVal *= abs(dot( projDir, -ftmp2 ));
+ retVal.a = pow( retVal.a, uFresnelPower );
+ retVal.a *= clamp( intLightBrt * exp2(-dist * fallRate), 0.0, 1.0 );
+
+ return retVal;
+}
+
+vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color)
+{
+ vec4 rgba = color;
+ float ratio = simpleFresnel( normal, materialIOR, uFresnelPower );
+ vec3 absorb_color = ( log( glass_color ) * -1.000000 );
+ // prevent log(0) -> inf number issue
+ if ( isinf(absorb_color.r) ) absorb_color.r = 1.0;
+ if ( isinf(absorb_color.g) ) absorb_color.g = 1.0;
+ if ( isinf(absorb_color.b) ) absorb_color.b = 1.0;
+ rgba.rgb *= (vec3(1.0) - absorb_color);
+
+ vec2 texSize = vec2( textureSize( refractiveTexture, 0 ) );
+ vec3 newUV = vec3((gl_FragCoord.xy * 0.5) / texSize, 0.0);
+ vec4 value = texture( refractiveTexture, newUV.xy );
+
+ newUV = getRefractUV( newUV.xy, normal, materialIOR, 0.01 * refract_depth );
+ vec4 refractValue = texture( refractiveTexture, newUV.xy );
+
+ vec3 refractColor = refractValue.a * refractValue.rgb + (1.0 - refractValue.a) * value.rgb;
+ refractColor = refractColor * (vec3(1.0) - absorb_color);
+ vec4 internalColor = doFakeInnerLight( normal, glass_color );
+ refractColor += internalColor.rgb * internalColor.a;
+
+ rgba = vec4(mix(refractColor, rgba.rgb, ratio), 1.0);
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ <Shader name="NOOP">
+<VertexShader>
+</VertexShader>
+<FragmentShader>
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+
+vec3 texCoord0;
+
+void main()
+{
+
+ // This is a bit silly, but the thing is that a buffer blit takes place on this
+ // pass, and if you do a buffer blit on a pass that outputs to lower-resolution,
+ // it only blits a smaller portion of the backbuffer that occupies that number of
+ // pixels. So we need a dummy no-op pass that is full-res in order to blit everything.
+</FragmentShader>
+ </Shader>
+ <Shader name="PREBLUR">
+<VertexShader>
+</VertexShader>
+<FragmentShader>
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+
+vec3 texCoord0;
+
+uniform sampler2D OriginBuffer;
+
+void main()
+{
+ vec2 texSize = vec2( textureSize( OriginBuffer, 0 ) );
+ texSize = vec2(1.0) / texSize;
+ texCoord0.z = 0.0;
+ texCoord0.xy = vec2(gl_FragCoord.xy * 2.0 * texSize);
+
+ float wtSum = 0.0;
+ vec4 totSum = vec4(0.0);
+ for (int ix = -1; ix &lt;= 1; ++ix)
+ {
+ for (int iy = -1; iy &lt;= 1; ++iy)
+ {
+ float wt = float(ix*ix + iy*iy) * 4.0;
+ wt = exp2( -wt );
+ vec2 texOfs = vec2(ix, iy) * texSize;
+ totSum += wt * texture( OriginBuffer, texCoord0.xy + texOfs );
+ wtSum += wt;
+ }
+ }
+
+ totSum /= wtSum;
+ gl_FragColor = totSum;
+ // No close paren because the generator adds it for us.
+
+</FragmentShader>
+ </Shader>
+ <Shader name="BLURX">
+<VertexShader>
+</VertexShader>
+<FragmentShader>
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+
+vec3 texCoord0;
+
+uniform sampler2D BlurBuffer;
+
+void main()
+{
+ vec2 texSize = vec2( textureSize( BlurBuffer, 0 ) );
+ texSize = vec2(1.0) / texSize;
+ texCoord0.z = 0.0;
+ texCoord0.xy = vec2(gl_FragCoord.xy * texSize);
+
+ float sigma = clamp(blur_size * 0.5, 0.5, 100.0);
+ int smpCount = int(ceil( sigma ));
+ vec4 value = texture(BlurBuffer, texCoord0.xy);
+ float wtsum = 1.0;
+ for (int i = 1; i &lt;= smpCount; ++i)
+ {
+ // Base 2 Gaussian blur
+ float wt = float(i) / (sigma * 0.5);
+ wt = exp2( -wt*wt );
+ vec2 texOfs = vec2(i, 0) * texSize;
+ value += wt * texture(BlurBuffer, texCoord0.xy+texOfs);
+ value += wt * texture(BlurBuffer, texCoord0.xy-texOfs);
+ wtsum += wt * 2.0;
+ }
+
+ gl_FragColor = value / wtsum;
+ gl_FragColor.a = 1.0;
+
+ // No close paren because the generator adds it for us.
+</FragmentShader>
+ </Shader>
+ <Shader name="BLURY">
+<VertexShader>
+</VertexShader>
+<FragmentShader>
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+
+vec3 texCoord0;
+
+uniform sampler2D BlurBuffer;
+uniform sampler2D OriginBuffer;
+
+void main()
+{
+ vec2 texSize = vec2( textureSize( BlurBuffer, 0 ) );
+ texSize = vec2(1.0) / texSize;
+ texCoord0.z = 0.0;
+ texCoord0.xy = vec2(gl_FragCoord.xy * texSize);
+
+ float sigma = clamp(blur_size * 0.5, 0.5, 100.0);
+ int smpCount = int(ceil( sigma ));
+ vec4 value = texture(BlurBuffer, texCoord0.xy);
+
+ float wtsum = 1.0;
+ for (int i = 1; i &lt;= smpCount; ++i)
+ {
+ // Base 2 Gaussian blur
+ float wt = float(i) / (sigma * 0.5);
+ wt = exp2( -wt*wt );
+ vec2 texOfs = vec2(0, i) * texSize;
+ vec4 posValue = texture(BlurBuffer, texCoord0.xy+texOfs);
+ vec4 negValue = texture(BlurBuffer, texCoord0.xy-texOfs);
+ posValue = posValue.a * posValue + (1.0 - posValue.a) * texture(OriginBuffer, texCoord0.xy+texOfs);
+ negValue = negValue.a * negValue + (1.0 - negValue.a) * texture(OriginBuffer, texCoord0.xy-texOfs);
+
+ value += wt * posValue;
+ value += wt * negValue;
+ wtsum += wt * 2.0;
+ }
+
+ gl_FragColor = (value / wtsum);
+ gl_FragColor.a = 1.0;
+
+ // No close paren because the generator adds it for us.
+</FragmentShader>
+ </Shader>
+
+ </Shaders>
+<Passes >
+ <ShaderKey value="20"/>
+ <LayerKey count="1"/>
+ <Buffer name="frame_buffer" format="source" filter="linear" wrap="clamp" size="1.0" lifetime="frame"/>
+ <Buffer name="dummy_buffer" type="ubyte" format="rgba" wrap="clamp" size="1.0" lifetime="frame"/>
+ <Buffer name="temp_buffer" type="fp16" format="rgba" filter="linear" wrap="clamp" size="0.5" lifetime="frame"/>
+ <Buffer name="temp_blurX" type="fp16" format="rgba" filter="linear" wrap="clamp" size="0.5" lifetime="frame"/>
+ <Buffer name="temp_blurY" type="fp16" format="rgba" filter="linear" wrap="clamp" size="0.5" lifetime="frame"/>
+ <Pass shader="NOOP" output="dummy_buffer">
+ <BufferBlit dest="frame_buffer"/>
+ </Pass>
+ <Pass shader="PREBLUR" output="temp_buffer">
+ <BufferInput value="frame_buffer" param="OriginBuffer"/>
+ </Pass>
+ <Pass shader="BLURX" output="temp_blurX">
+ <BufferInput value="temp_buffer" param="BlurBuffer"/>
+ </Pass>
+ <Pass shader="BLURY" output="temp_blurY">
+ <BufferInput value="temp_blurX" param="BlurBuffer"/>
+ <BufferInput value="temp_buffer" param="OriginBuffer"/>
+ </Pass>
+ <Pass shader="MAIN">
+ <BufferInput value="temp_blurY" param="refractiveTexture"/>
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/thin_glass_frosted_sp.material b/Studio/Content/Material Library/thin_glass_frosted_sp.material
new file mode 100644
index 00000000..dcc8f071
--- /dev/null
+++ b/Studio/Content/Material Library/thin_glass_frosted_sp.material
@@ -0,0 +1,246 @@
+<Material name="thin_glass_frosted_sp" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Gradient1D Map" hidden="True" name="randomGradient1D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient1D.png"/>
+ <Property formalName="Gradient2D Map" hidden="True" name="randomGradient2D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient2D.png"/>
+ <Property formalName="Gradient3D Map" hidden="True" name="randomGradient3D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient3D.png"/>
+ <Property formalName="Gradient4D Map" hidden="True" name="randomGradient4D" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="gradient" default="./maps/materials/randomGradient4D.png"/>
+ <Property name="noiseCoords" type="Vector" default="1 1 1" category="Material"/>
+ <Property name="noiseScale" type="Float" min="0.000000" max="40.000000" default="2.000000" category="Material"/>
+ <Property name="bumpCoords" type="Vector" default="1 1 1" category="Material"/>
+ <Property name="bumpScale" type="Float" min="0.000000" max="1.000000" default="0.500000" category="Material"/>
+ <Property name="bumpBands" type="Long" min="1.000000" max="10.000000" default="1" category="Material"/>
+ <Property formalName="Fresnel Power" name="uFresnelPower" type="Float" default="1.0" category="Material"/>
+ <Property formalName="Roughness" name="roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="surface reflection roughness" category="Material"/>
+ <Property formalName="Blur Width" name="blur_size" type="Float" default="8" min="0.000000" max="20.00000" category="Material"/>
+ <Property formalName="Reflectivity" name="reflectivity_amount" type="Float" min="0.000000" max="1.000000" default="1.000000" description="reflectivity factor" category="Material"/>
+ <Property formalName="Glass ior" name="glass_ior" type="Float" default="1.100000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glass Color" name="glass_color" type="Color" default="0.9 0.9 0.9" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define texture_coordinate_uvw 0
+#define texture_coordinate_world 1
+#define texture_coordinate_object 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+// add structure defines
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp0;
+texture_coordinate_info tmp1;
+vec3 ftmp0;
+vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "cube.glsllib"
+#include "random255.glsllib"
+#include "perlinNoise.glsllib"
+#include "perlinNoiseBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "coordinateSource.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "abbeNumberIOR.glsllib"
+#include "average.glsllib"
+#include "perlinNoiseTexture.glsllib"
+#include "fresnelLayer.glsllib"
+#include "refraction.glsllib"
+
+uniform sampler2D refractiveTexture;
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect_transmit );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ //return( normal );
+ return( perlinNoiseBumpTexture( tmp1, bumpScale, 1.000000, false, false, 0.000000, bumpBands, false, vec3( 0.000000, 0.000000, 0.000000 ), 0.5, 0.0, 1.000000, normal ) );
+}
+
+void computeTemporaries()
+{
+ tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), noiseCoords ), coordinateSource(texture_coordinate_world, 0 ) );
+ tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), coordinateSource(texture_coordinate_world, 0 ) );
+ ftmp0 = vec3( reflectivity_amount );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( ftmp0, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color)
+{
+ vec4 rgba = color;
+ float ratio = simpleFresnel( normal, materialIOR, uFresnelPower );
+ vec3 absorb_color = ( log( glass_color )/-1.000000 );
+ // prevent log(0) -> inf number issue
+ if ( isinf(absorb_color.r) ) absorb_color.r = 1.0;
+ if ( isinf(absorb_color.g) ) absorb_color.g = 1.0;
+ if ( isinf(absorb_color.b) ) absorb_color.b = 1.0;
+ rgba.rgb *= (vec3(1.0) - absorb_color);
+
+ vec3 refractDir = perlinNoiseBumpTexture( tmp0, noiseScale, 1.000000, false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.0, 0.5, 1.000000, normalize(viewDir) );
+
+ vec3 refractColor = refractBlur( refractiveTexture, normalize(refractDir), materialIOR, blur_size ) * (vec3(1.0) - absorb_color);
+ rgba = vec4(mix(refractColor, rgba.rgb, ratio), 1.0);
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="20"/>
+ <LayerKey count="1"/>
+ <Buffer name="temp_buffer" format="source" filter="linear" wrap="clamp" size="1.0" lifetime="frame"/>
+ <Pass >
+ <BufferBlit dest="temp_buffer"/>
+ <BufferInput value="temp_buffer" param="refractiveTexture"/>
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/thin_glass_refractive.material b/Studio/Content/Material Library/thin_glass_refractive.material
new file mode 100644
index 00000000..d78bdd42
--- /dev/null
+++ b/Studio/Content/Material Library/thin_glass_refractive.material
@@ -0,0 +1,202 @@
+<Material name="thin_glass_refractive" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Fresnel Power" name="uFresnelPower" type="Float" default="1.0" category="Material"/>
+ <Property formalName="Roughness" name="roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="surface reflection roughness" category="Material"/>
+ <Property formalName="Reflectivity" name="reflectivity_amount" type="Float" min="0.000000" max="1.000000" default="1.000000" description="reflectivity factor" category="Material"/>
+ <Property formalName="Glass ior" name="glass_ior" type="Float" default="1.100000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glass Color" name="glass_color" type="Color" default="0.9 0.9 0.9" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+vec3 ftmp0;
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "abbeNumberIOR.glsllib"
+#include "fresnelLayer.glsllib"
+#include "refraction.glsllib"
+
+uniform sampler2D refractiveTexture;
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect_transmit );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( abbeNumberIOR(glass_ior, 0.000000 ) ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ ftmp0 = vec3( reflectivity_amount );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = layers[0].base * vec4( ftmp0, 1.0);
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( tangentFrame( normal, varWorldPos ) );
+}
+
+vec4 computeGlass(in vec3 normal, in float materialIOR, in float alpha, in vec4 color)
+{
+ vec4 rgba = color;
+ float ratio = simpleFresnel( normal, materialIOR, uFresnelPower );
+ vec3 absorb_color = ( log( glass_color )/-1.000000 );
+ // prevent log(0) -> inf number issue
+ if ( isinf(absorb_color.r) ) absorb_color.r = 1.0;
+ if ( isinf(absorb_color.g) ) absorb_color.g = 1.0;
+ if ( isinf(absorb_color.b) ) absorb_color.b = 1.0;
+ rgba.rgb *= (vec3(1.0) - absorb_color);
+ vec3 refractColor = refraction( refractiveTexture, materialIOR ) * (vec3(1.0) - absorb_color);
+ rgba = vec4(mix(refractColor, rgba.rgb, ratio), 1.0);
+ return rgba;
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="20"/>
+ <LayerKey count="1"/>
+ <Buffer name="temp_buffer" format="source" filter="linear" wrap="clamp" size="1.0" lifetime="scene"/>
+ <Pass >
+ <BufferBlit dest="temp_buffer"/>
+ <BufferInput value="temp_buffer" param="refractiveTexture"/>
+ <Blending source="SrcAlpha" dest="OneMinusSrcAlpha"/>
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Material Library/walnut_matte.material b/Studio/Content/Material Library/walnut_matte.material
new file mode 100644
index 00000000..a8015fd4
--- /dev/null
+++ b/Studio/Content/Material Library/walnut_matte.material
@@ -0,0 +1,236 @@
+<Material name="walnut_matte" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Enable Shadow Mapping" name="uShadowMappingEnabled" type="Boolean" default="False" category="Material"/>
+ <Property name="material_ior" type="Float" default="1.500000" description="Index of refraction of the material" category="Material"/>
+ <Property name="roughness" type="Float" min="0.000000" max="1.000000" default="0.250000" description="Roughness of the material. A value of 0 makes it completely specular, 1 is completely diffuse" category="Material"/>
+ <Property name="reflect_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="specular" default="./maps/materials/walnut_spec.png" category="Material"/>
+ <Property name="texture_tiling" type="Float2" default="10 7" description="Scaling of the textures" category="Material"/>
+ <Property name="diffuse_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="diffuse" default="./maps/materials/walnut.png" category="Material"/>
+ <Property name="bump_texture" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="bump" default="./maps/materials/walnut_bump.png" category="Material"/>
+ <Property name="bump_amount" type="Float" default="0.400000" description="Value determining the bumpiness" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define gamma_default 0
+#define gamma_linear 1
+#define gamma_srgb 2
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define UIC_ENABLE_UV0 1
+#define UIC_ENABLE_WORLD_POSITION 1
+#define UIC_ENABLE_TEXTAN 1
+#define UIC_ENABLE_BINORMAL 1
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+
+struct texture_return
+{
+ vec3 tint;
+ float mono;
+};
+
+
+// temporary declarations
+texture_coordinate_info tmp2;
+vec3 tmp5;
+vec3 ftmp0;
+vec3 ftmp1;
+ vec4 tmpShadowTerm;
+
+layer_result layers[2];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "fileBumpTexture.glsllib"
+#include "transformCoordinate.glsllib"
+#include "rotationTranslationScale.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fileTexture.glsllib"
+#include "weightedLayer.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[1].tanFrame, varWorldPos, lightIdx );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
+
+#else
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+ layers[1].base += tmpShadowTerm * vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if UIC_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !UIC_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0f : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = weightedLayer( 1.000000, vec4( ftmp1, 1.0).rgb, layers[1].layer, layers[1].base, alpha );
+ color = fresnelLayer( tmp5, vec3( material_ior ), 1.000000, vec4( ftmp0, 1.0).rgb, layers[0].layer, color, color.a );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+ layers[1].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[1].tanFrame = orthoNormalize( mat3( tangent, cross(tmp5, tangent), tmp5 ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="2"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/Studio/Content/Models Library/Electronics/Headphones.dae b/Studio/Content/Models Library/Electronics/Headphones.dae
new file mode 100644
index 00000000..3ced1631
--- /dev/null
+++ b/Studio/Content/Models Library/Electronics/Headphones.dae
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/electronics/Headphones.mb</source_data>
+ </contributor>
+ <created>2008-09-23T20:27:03Z</created>
+ <modified>2008-09-23T20:27:03Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="headpiece" name="headpiece">
+ <instance_effect url="#headpiece-fx"/>
+ </material>
+ <material id="trim" name="trim">
+ <instance_effect url="#trim-fx"/>
+ </material>
+ <material id="plastic" name="plastic">
+ <instance_effect url="#plastic-fx"/>
+ </material>
+ <material id="phone" name="phone">
+ <instance_effect url="#phone-fx"/>
+ </material>
+ <material id="earpiece" name="earpiece">
+ <instance_effect url="#earpiece-fx"/>
+ </material>
+ <material id="foam" name="foam">
+ <instance_effect url="#foam-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="headpiece-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="trim-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="plastic-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="phone-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="earpiece-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="foam-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Headphones" name="Headphones">
+ <mesh>
+ <source id="Headphones-positions" name="position">
+ <float_array id="Headphones-positions-array" count="9042">41.0358 1.45843 3.02491 40.0585 -2.85087 5.11285 38.3141 -7.28645 6.05386 41.5534 5.08738 2.82599 39.0034 -2.78983 5.10091 38.2918 -2.86791 6.1526 39.4206 1.68737 4.63022 39.9566 1.81482 2.8632 37.4312 -6.96178 6.05155 36.8421 -6.79753 6.94469 40.2991 5.17249 2.74187 39.869 5.17153 4.35142 38.4357 -7.13643 7.60584 38.2967 -7.30787 4.23102 41.1984 1.75076 5.28422 40.0585 -2.85087 6.7955 40.0314 -2.94048 3.10001 40.6607 -0.506353 1.58287 41.6167 5.08303 5.07011 39.7611 5.18243 5.06932 39.3573 1.91479 5.28277 38.263 -2.5664 6.7955 36.7986 -6.57934 7.61329 39.8702 -2.88533 3.09597 40.4948 -0.469227 1.58351 38.1597 -7.21039 4.23068 37.6345 -7.00927 4.23014 39.2813 -2.79117 3.08937 39.8899 -0.404788 1.58456 37.6 -7.09958 3.86024 39.2542 -2.93965 2.73803 39.8555 -0.668652 1.30965 34.203 -16.9786 6.05386 34.3115 -16.826 7.60584 34.1875 -17.0004 4.23102 34.157 -16.7402 7.60733 34.0392 -16.9031 4.23068 33.2202 -16.6826 6.04405 33.4613 -16.7958 3.86024 33.4875 -16.7041 4.23014 32.6384 -16.4488 6.9325 32.5986 -16.2744 7.61329 38.0936 -2.66652 3.11071 36.7245 -6.59999 4.28698 32.3727 -16.3058 4.28279 38.7043 -0.35177 1.60975 38.2934 -2.85245 2.64585 36.8985 -6.72878 3.77432 32.5825 -16.3935 3.77215 38.8525 -0.713107 1.26675 38.8879 -2.88716 3.80686 37.3352 -6.94885 4.97355 33.1258 -16.6582 4.98199 39.7792 0.252845 2.02742 38.9115 -2.86728 4.07111 37.3548 -6.95149 5.19368 33.1451 -16.6631 5.19887 39.8436 0.526463 2.23323 39.6174 1.48775 4.26116 38.7586 -2.85196 5.93784 37.2839 -6.83107 6.76231 33.0787 -16.4966 6.75107 40.054 3.48323 3.90016 40.3843 3.94176 2.61978 32.7251 -16.5042 7.48569 34.0063 -16.9151 7.48043 34.0958 -16.9515 7.4507 34.0033 -17.0719 6.09107 33.9996 -17.0571 4.52725 33.9055 -17.0108 4.42492 33.2978 -16.7624 4.32589 33.2709 -16.8565 3.96545 32.6508 -16.5276 3.97262 32.5219 -16.5153 4.26848 33.1961 -16.8624 4.83592 33.2593 -16.8544 5.21753 33.3389 -16.8684 6.09099 33.1764 -16.6501 6.90681 32.7486 -16.6073 7.08346 34.4232 -16.5636 7.60584 34.3846 -16.5504 6.05386 34.3791 -16.5485 4.23102 34.2568 -16.5064 7.60733 34.2141 -16.4917 4.23068 33.66 -16.301 4.23014 33.6709 -16.3047 3.86024 32.8276 -16.0145 6.93305 32.7263 -15.9797 7.61329 32.8919 -15.9902 3.77224 32.677 -15.9163 4.28296 33.3299 -16.1874 4.98158 33.3486 -16.1938 5.19862 33.4211 -16.2188 6.04441 33.2284 -16.1525 6.75147 41.0358 1.45843 -3.02491 40.0585 -2.85087 -5.11285 38.3141 -7.28645 -6.05386 41.5534 5.08738 -2.82599 39.0034 -2.78983 -5.10091 38.2918 -2.86791 -6.1526 39.4206 1.68737 -4.63022 39.9566 1.81482 -2.8632 37.4312 -6.96178 -6.05155 36.8421 -6.79753 -6.94469 40.2991 5.17249 -2.74187 39.869 5.17153 -4.35142 38.4357 -7.13643 -7.60584 38.2967 -7.30787 -4.23102 41.1984 1.75076 -5.28422 40.0585 -2.85087 -6.7955 40.0314 -2.94048 -3.10001 40.6607 -0.506353 -1.58287 41.6167 5.08303 -5.07011 39.7611 5.18243 -5.06932 39.3573 1.91479 -5.28277 38.263 -2.5664 -6.7955 36.7986 -6.57934 -7.61329 39.8702 -2.88533 -3.09597 40.4948 -0.469227 -1.58351 38.1597 -7.21039 -4.23068 37.6345 -7.00927 -4.23014 39.2813 -2.79117 -3.08937 39.8899 -0.404788 -1.58456 37.6 -7.09958 -3.86024 39.2542 -2.93965 -2.73803 39.8555 -0.668652 -1.30965 34.203 -16.9786 -6.05386 34.3115 -16.826 -7.60584 34.1875 -17.0004 -4.23102 34.157 -16.7402 -7.60733 34.0392 -16.9031 -4.23068 33.2202 -16.6826 -6.04405 33.4613 -16.7958 -3.86024 33.4875 -16.7041 -4.23014 32.6384 -16.4488 -6.9325 32.5986 -16.2744 -7.61329 38.0936 -2.66652 -3.11071 36.7245 -6.59999 -4.28698 32.3727 -16.3058 -4.28279 38.7043 -0.35177 -1.60975 38.2934 -2.85245 -2.64586 36.8985 -6.72878 -3.77432 32.5825 -16.3935 -3.77215 38.8525 -0.713107 -1.26675 38.8879 -2.88716 -3.80686 37.3352 -6.94885 -4.97355 33.1258 -16.6582 -4.98199 39.7792 0.252845 -2.02742 38.9115 -2.86728 -4.07111 37.3548 -6.95149 -5.19368 33.1451 -16.6631 -5.19887 39.8436 0.526463 -2.23323 39.6174 1.48775 -4.26116 38.7586 -2.85196 -5.93784 37.2839 -6.83107 -6.76231 33.0787 -16.4966 -6.75107 40.054 3.48323 -3.90016 40.3843 3.94176 -2.61978 32.7251 -16.5042 -7.48569 34.0063 -16.9151 -7.48043 34.0958 -16.9515 -7.4507 34.0033 -17.0719 -6.09107 33.9996 -17.0571 -4.52725 33.9055 -17.0108 -4.42492 33.2978 -16.7624 -4.32589 33.2709 -16.8565 -3.96545 32.6508 -16.5276 -3.97262 32.5219 -16.5153 -4.26848 33.1961 -16.8624 -4.83592 33.2593 -16.8544 -5.21753 33.3389 -16.8684 -6.09099 33.1764 -16.6501 -6.90681 32.7486 -16.6073 -7.08346 34.4232 -16.5636 -7.60584 34.3846 -16.5504 -6.05386 34.3791 -16.5485 -4.23102 34.2568 -16.5064 -7.60733 34.2141 -16.4917 -4.23068 33.66 -16.301 -4.23014 33.6709 -16.3047 -3.86024 32.8276 -16.0145 -6.93305 32.7263 -15.9797 -7.61329 32.8919 -15.9902 -3.77224 32.677 -15.9163 -4.28296 33.3299 -16.1874 -4.98158 33.3486 -16.1938 -5.19862 33.4211 -16.2188 -6.04441 33.2284 -16.1525 -6.75147 41.2422 2.51901 0 41.6049 5.08889 0 40.2836 3.10687 0 40.4549 5.16806 0 40.7581 0.574058 0 40.5938 0.606495 0 39.9863 0.662585 0 39.9444 0.281999 0 38.7266 0.699332 0 38.8948 0.188449 0 39.8289 1.74732 0 39.9654 2.16694 0 40.5692 4.36144 0 31.7005 -8.70096 5.92036 31.9349 -8.05701 0 32.2328 -7.23853 0 31.9571 -7.99599 6.00027 31.0049 -10.6122 10.7946 31.2357 -9.97807 10.9907 31.1488 -10.2168 11.5916 30.904 -10.8894 11.5017 30.8822 -10.9492 5.23555 31.0735 -10.4236 0 29.6923 -14.2184 6.54629 29.8377 -13.819 6.23884 30.3692 -12.3586 9.13231 30.2735 -12.6215 9.85917 29.5747 -14.5415 0 29.5887 -14.5032 3.15953 29.3653 -15.1169 2.80102 29.3247 -15.2283 0 31.7005 -8.70096 -5.92036 31.9571 -7.99599 -6.00027 31.0049 -10.6122 -10.7946 30.904 -10.8894 -11.5017 31.1488 -10.2168 -11.5916 31.2357 -9.97807 -10.9907 30.8822 -10.9492 -5.23555 29.6923 -14.2184 -6.54629 30.2735 -12.6215 -9.85917 30.3692 -12.3586 -9.13231 29.8377 -13.819 -6.23884 29.3653 -15.1169 -2.80102 29.5887 -14.5032 -3.15953 32.9222 -7.63431 0 32.6463 -8.39208 6.00027 31.925 -10.374 10.9907 31.8382 -10.6126 11.5916 31.638 -11.1626 11.5017 30.4275 -14.4882 6.54629 31.0081 -12.8931 9.85917 30.1009 -15.3858 2.80102 30.0604 -15.4971 0 32.6463 -8.39208 -6.00027 31.638 -11.1626 -11.5017 31.8382 -10.6126 -11.5916 31.925 -10.374 -10.9907 30.4275 -14.4882 -6.54629 31.0081 -12.8931 -9.85917 30.1009 -15.3858 -2.80102 34.9157 -10.9246 4.4689 35.0873 -10.4533 4.52896 35.3116 -9.83695 0 34.3591 -12.4539 8.63155 34.2792 -12.6735 9.19695 34.438 -12.237 9.26884 34.5072 -12.047 8.78831 34.2619 -12.7208 3.95417 33.3333 -15.2723 5.23452 33.784 -14.034 7.88355 33.8587 -13.8288 7.30233 33.4456 -14.9638 4.98868 33.0506 -16.049 0 33.0817 -15.9635 2.12429 33.2534 -15.4917 2.39375 34.9157 -10.9246 -4.4689 35.0873 -10.4533 -4.52896 34.3591 -12.4539 -8.63155 34.5072 -12.047 -8.78831 34.438 -12.237 -9.26884 34.2792 -12.6735 -9.19695 34.2619 -12.7208 -3.95417 33.3333 -15.2723 -5.23452 33.4456 -14.9638 -4.98868 33.8587 -13.8288 -7.30233 33.784 -14.034 -7.88355 33.2534 -15.4917 -2.39375 33.0817 -15.9635 -2.12429 33.1792 -11.2899 10.8198 33.2601 -11.0675 10.2588 33.9349 -9.21368 5.60072 34.1938 -8.50223 0 33.9349 -9.21368 -5.60072 33.2601 -11.0675 -10.2588 33.1792 -11.2899 -10.8198 32.9928 -11.8019 -10.7358 32.4085 -13.4072 -9.20267 31.8722 -14.8808 -6.11039 31.5709 -15.7086 -2.61451 31.5335 -15.8112 0 31.5709 -15.7086 2.61451 31.8722 -14.8808 6.11039 32.4085 -13.4072 9.20267 32.9928 -11.8019 10.7358 34.8946 -10.2416 4.93291 35.125 -9.60879 0 34.8946 -10.2416 -4.93291 34.2984 -11.8798 -9.0356 34.2272 -12.0753 -9.52965 34.0637 -12.5245 -9.45574 33.5538 -13.9256 -8.10538 33.0891 -15.2022 -5.38181 32.8295 -15.9154 -2.30276 32.7974 -16.0037 0 32.8295 -15.9154 2.30276 33.0891 -15.2022 5.38181 33.5538 -13.9256 8.10538 34.0637 -12.5245 9.45574 34.2272 -12.0753 9.52965 34.2984 -11.8798 9.0356 37.3412 -12.1916 3.4624 37.517 -11.6753 3.51654 37.7416 -11.0558 -0.080431 37.5309 -11.6705 0 36.6875 -13.9879 3.07121 36.8392 -13.5711 0 35.6682 -16.7883 0 35.4343 -17.3658 -0.080428 35.4666 -17.2792 1.68651 35.679 -16.7587 1.88529 37.3412 -12.1916 -3.4624 37.517 -11.6753 -3.51655 36.6875 -13.9879 -3.07121 35.679 -16.7587 -1.88529 35.4664 -17.2793 -1.68654 37.2689 -11.5506 3.51567 37.4935 -10.9314 -0.080431 35.3353 -10.578 3.50892 35.5597 -9.96139 -0.080428 37.2689 -11.5505 -3.51568 35.3353 -10.578 -3.50892 37.0936 -12.0623 -3.4624 35.1633 -11.054 -3.4624 36.4398 -13.8585 -3.07121 34.5096 -12.8502 -3.07121 35.4313 -16.6294 -1.88529 33.5011 -15.6211 -1.88529 35.2229 -17.145 -1.68592 33.3252 -16.0979 -1.68112 35.1909 -17.2314 -0.080428 33.294 -16.1835 -0.080428 35.2231 -17.1449 1.6859 33.3252 -16.0979 1.68111 35.4313 -16.6294 1.88529 33.5011 -15.6211 1.88529 36.4398 -13.8585 3.07121 34.5096 -12.8502 3.07121 37.0936 -12.0623 3.4624 35.1633 -11.054 3.4624 18.31 -49.3874 5.82322 19.0787 -47.2753 11.2496 20.3017 -43.9154 15.9093 21.8954 -39.5367 19.4849 23.7513 -34.4376 21.7326 25.743 -28.9655 22.4992 27.7346 -23.4935 21.7326 29.5906 -18.3944 19.4849 31.1843 -14.0156 15.9093 22.6152 -48.5625 5.22096 23.3044 -46.6688 10.0861 24.4008 -43.6564 14.2639 25.8297 -39.7305 17.4697 27.4937 -35.1588 19.4849 29.2794 -30.2527 20.1722 31.065 -25.3466 19.4849 32.729 -20.7748 17.4697 34.1579 -16.849 14.2639 26.8748 -46.3078 4.26289 27.4376 -44.7617 8.23528 28.3328 -42.302 11.6464 29.4995 -39.0966 14.2639 30.8582 -35.3638 15.9093 32.3162 -31.358 16.4706 33.7742 -27.3521 15.9093 35.1328 -23.6193 14.2639 36.2995 -20.4139 11.6464 30.7988 -42.7773 3.01432 31.1967 -41.6839 5.82322 31.8297 -39.9447 8.23528 32.6547 -37.6781 10.0861 33.6154 -35.0386 11.2496 34.6464 -32.2061 11.6464 35.6773 -29.3736 11.2496 36.638 -26.7341 10.0861 37.463 -24.4675 8.23528 34.1195 -38.2113 1.56033 34.3255 -37.6453 3.01432 34.6532 -36.7451 4.26289 35.0802 -35.5718 5.22096 35.5775 -34.2055 5.82322 36.1112 -32.7392 6.02864 36.6448 -31.273 5.82322 37.1421 -29.9067 5.22096 37.5692 -28.7334 4.26289 37.8969 -27.8331 3.01432 38.1028 -27.2672 1.56033 31.604 -12.8625 14.3101 38.354 -23.6497 2.4942 34.5144 -15.8696 12.9056 36.659 -19.426 10.2764 38.0783 -22.7121 5.93795 29.7108 -14.1212 12.9056 27.6594 -19.7572 2.4942 28.8186 -16.5723 10.2764 27.9285 -19.0179 5.93795 30.4023 -12.2213 14.4563 31.1367 -13.1731 13.9634 37.6958 -23.4101 2.4942 33.4618 -15.4864 12.9056 35.9038 -19.1511 10.2764 37.4061 -22.4674 5.93795 38.2934 -24.5231 2.26873 34.3925 -16.2046 13.3702 31.4467 -13.2946 14.9094 36.5139 -19.8249 10.8296 29.4793 -12.1577 15.0574 37.9886 -23.3956 5.88247 30.29 -9.48098 11.4689 31.0737 -7.32768 5.93672 29.7153 -11.3786 14.0129 31.2132 -9.99323 11.3733 31.9904 -7.85789 5.88723 30.5442 -11.8313 13.9167 28.5406 -20.0779 2.4942 30.5919 -14.4419 12.9056 29.6998 -16.893 10.2764 28.8096 -19.3386 5.93795 31.0206 -10.5224 11.285 30.3423 -12.3859 13.6718 31.7865 -8.4181 5.80883 30.2186 -12.726 14.0444 28.236 -18.1732 5.85284 27.9841 -18.8652 2.75494 29.0839 -15.8435 10.3979 30.04 -13.2167 10.8358 29.8527 -13.7313 12.3979 30.3057 -12.4866 4.57892 28.9787 -16.1325 2.44005 32.1577 -14.6045 12.8849 33.1557 -17.0496 10.203 33.6844 -19.3192 5.77783 33.7619 -19.9753 2.2652 18.31 -49.3874 -5.82322 19.0787 -47.2753 -11.2496 20.3017 -43.9154 -15.9093 21.8954 -39.5367 -19.4849 23.7513 -34.4376 -21.7326 25.743 -28.9655 -22.4992 27.7346 -23.4935 -21.7326 29.5906 -18.3944 -19.4849 31.1843 -14.0156 -15.9093 22.6152 -48.5625 -5.22096 23.3044 -46.6688 -10.0861 24.4008 -43.6564 -14.2639 25.8297 -39.7305 -17.4697 27.4937 -35.1588 -19.4849 29.2794 -30.2527 -20.1722 31.065 -25.3466 -19.4849 32.729 -20.7748 -17.4697 34.1579 -16.849 -14.2639 26.8748 -46.3078 -4.26289 27.4376 -44.7617 -8.23528 28.3328 -42.302 -11.6464 29.4995 -39.0966 -14.2639 30.8582 -35.3638 -15.9093 32.3162 -31.358 -16.4706 33.7742 -27.3521 -15.9093 35.1328 -23.6193 -14.2639 36.2995 -20.4139 -11.6464 30.7988 -42.7773 -3.01432 31.1967 -41.6839 -5.82322 31.8297 -39.9447 -8.23528 32.6547 -37.6781 -10.0861 33.6154 -35.0386 -11.2496 34.6464 -32.2061 -11.6464 35.6773 -29.3736 -11.2496 36.638 -26.7341 -10.0861 37.463 -24.4675 -8.23528 34.1195 -38.2113 -1.56033 34.3255 -37.6453 -3.01432 34.6532 -36.7451 -4.26289 35.0802 -35.5718 -5.22096 35.5775 -34.2055 -5.82322 36.1112 -32.7392 -6.02864 36.6448 -31.273 -5.82322 37.1421 -29.9067 -5.22096 37.5692 -28.7334 -4.26289 37.8969 -27.8331 -3.01432 38.1028 -27.2672 -1.56033 31.604 -12.8625 -14.3101 38.354 -23.6497 -2.4942 34.5144 -15.8696 -12.9056 36.659 -19.426 -10.2764 38.0783 -22.7121 -5.93795 29.7108 -14.1212 -12.9056 27.6594 -19.7572 -2.4942 28.8186 -16.5723 -10.2764 27.9285 -19.0179 -5.93795 30.4023 -12.2213 -14.4563 31.1367 -13.1731 -13.9634 37.6958 -23.4101 -2.4942 33.4618 -15.4864 -12.9056 35.9038 -19.1511 -10.2764 37.4061 -22.4674 -5.93795 38.2934 -24.5231 -2.26873 34.3925 -16.2046 -13.3702 31.4467 -13.2946 -14.9094 36.5139 -19.8249 -10.8296 29.4793 -12.1577 -15.0574 37.9886 -23.3956 -5.88247 30.29 -9.48098 -11.4689 31.0737 -7.32768 -5.93672 29.7153 -11.3786 -14.0129 31.2132 -9.99323 -11.3733 31.9904 -7.85789 -5.88723 30.5442 -11.8313 -13.9167 28.5406 -20.0779 -2.4942 30.5919 -14.4419 -12.9056 29.6998 -16.893 -10.2764 28.8096 -19.3386 -5.93795 31.0206 -10.5224 -11.285 30.3423 -12.3859 -13.6718 31.7865 -8.4181 -5.80883 30.2186 -12.726 -14.0444 28.236 -18.1732 -5.85284 27.9841 -18.8652 -2.75494 29.0839 -15.8435 -10.3979 30.04 -13.2167 -10.8358 29.8527 -13.7313 -12.3979 30.3057 -12.4866 -4.57892 28.9787 -16.1325 -2.44005 32.1577 -14.6045 -12.8849 33.1557 -17.0496 -10.203 33.6844 -19.3192 -5.77783 33.7619 -19.9753 -2.2652 18.0478 -50.1079 0 27.5471 -20.0658 0 28.4283 -20.3865 0 27.9309 -19.0114 0 29.2586 -15.3636 0 30.5244 -11.8858 0 31.3411 -6.59322 0 32.2555 -7.12956 0 32.0119 -7.79891 0 22.3801 -49.2084 0 26.6829 -46.8352 0 30.663 -43.1502 0 34.0493 -38.4043 0 38.1731 -27.0742 0 38.413 -24.0206 0 37.7751 -23.7884 0 38.3476 -24.8528 0 33.7735 -20.2416 0 36.4569 -32.8651 -1.74677 36.3022 -33.2899 -1.68725 36.1581 -33.6858 -1.51274 36.0344 -34.0257 -1.23515 35.9395 -34.2866 -0.873384 35.8798 -34.4506 -0.452097 35.8594 -34.5065 0 35.8798 -34.4506 0.452097 35.9395 -34.2866 0.873384 36.0344 -34.0257 1.23515 36.1581 -33.6858 1.51274 36.3022 -33.2899 1.68725 36.4569 -32.8651 1.74677 36.6115 -32.4402 1.68725 36.7556 -32.0443 1.51274 36.8793 -31.7044 1.23515 36.9742 -31.4435 0.873384 37.0339 -31.2796 0.452096 37.0543 -31.2236 0 37.0339 -31.2796 -0.452096 36.9742 -31.4435 -0.873384 36.8793 -31.7044 -1.23515 36.7556 -32.0443 -1.51274 36.6115 -32.4402 -1.68725 36.5385 -32.8948 0 27.3075 -10.1328 14.1646 26.5263 -12.2791 16.7118 25.007 -16.4533 19.9408 27.9903 -8.25675 11.1334 28.6778 -6.3677 5.95345 28.9449 -5.63387 0 28.6778 -6.3677 -5.95345 27.9903 -8.25675 -11.1334 27.3075 -10.1328 -14.1646 26.5263 -12.2791 -16.7118 25.007 -16.4533 -19.9408 23.1095 -21.6667 -22.2353 21.0717 -27.2653 -23.0197 19.034 -32.864 -22.2353 17.1351 -38.0811 -19.9357 15.5045 -42.5611 -16.2774 14.2533 -45.9987 -11.5099 13.4668 -48.1597 -5.95794 13.1985 -48.8968 0 13.4668 -48.1597 5.95794 14.2533 -45.9987 11.5099 15.5045 -42.5611 16.2774 17.1351 -38.0811 19.9357 19.034 -32.864 22.2353 21.0717 -27.2653 23.0197 23.1095 -21.6667 22.2353 14.5629 -46.3631 -11.6464 13.767 -48.5498 -6.02864 13.4955 -49.2956 0 14.5629 -46.3631 11.6464 13.767 -48.5498 6.02864 15.8289 -42.8847 -16.4706 15.8289 -42.8847 16.4706 17.4788 -38.3515 -20.1722 17.4788 -38.3515 20.1722 19.4002 -33.0725 -22.4992 19.4002 -33.0725 22.4992 21.4622 -27.4074 -23.2929 21.4622 -27.4074 23.2929 23.5241 -21.7424 -22.4992 23.5241 -21.7424 22.4992 25.4455 -16.4634 -20.1722 25.4455 -16.4634 20.1722 27.0954 -11.9302 -16.4706 27.0954 -11.9302 16.4706 27.6852 -10.3097 -14.2232 28.3615 -8.45174 -11.6464 28.3615 -8.45174 11.6464 27.6852 -10.3097 14.2232 29.1573 -6.26511 -6.02864 29.4288 -5.51929 0 29.1573 -6.26511 6.02864 27.0498 -9.71303 14.4007 26.2527 -11.903 16.9997 24.7094 -16.1431 20.2797 27.7457 -7.80091 11.3112 28.4441 -5.8821 6.04968 28.7155 -5.13641 -0.000000 28.4441 -5.8821 -6.04968 27.7457 -7.80091 -11.3112 27.0498 -9.71303 -14.4007 26.2527 -11.903 -16.9997 24.7094 -16.1431 -20.2797 22.7814 -21.4403 -22.6111 20.7093 -27.1334 -23.4087 18.6371 -32.8267 -22.6111 16.7062 -38.1319 -20.2726 15.048 -42.6877 -16.5525 13.7757 -46.1834 -11.7044 12.9758 -48.3809 -6.05863 12.703 -49.1304 -0.000000 12.9758 -48.3809 6.05863 13.7757 -46.1834 11.7044 15.048 -42.6877 16.5525 16.7062 -38.1319 20.2726 18.6371 -32.8267 22.6111 20.7093 -27.1334 23.4087 22.7814 -21.4403 22.6111 26.2144 -9.18894 14.5601 25.4066 -11.4083 17.1941 23.8471 -15.693 20.5085 26.9192 -7.25247 11.4313 27.6249 -5.31357 6.11463 27.8993 -4.55988 0.000000 27.6249 -5.31357 -6.11463 26.9192 -7.25247 -11.4313 26.2144 -9.18894 -14.5601 25.4066 -11.4083 -17.1941 23.8471 -15.693 -20.5085 21.8986 -21.0467 -22.8648 19.8032 -26.8036 -23.6713 17.7078 -32.5607 -22.8648 15.7552 -37.9255 -20.5 14.0784 -42.5323 -16.7382 12.7918 -46.0673 -11.8357 11.983 -48.2895 -6.12659 11.7071 -49.0474 0.000000 11.983 -48.2895 6.1266 12.7918 -46.0673 11.8357 14.0784 -42.5323 16.7382 15.7552 -37.9255 20.5 17.7078 -32.5607 22.8648 19.8032 -26.8036 23.6713 21.8985 -21.0467 22.8648 25.2533 -9.01027 14.4361 24.4539 -11.2067 17.0429 22.907 -15.4568 20.3306 25.9512 -7.09274 11.3379 26.6513 -5.16946 6.06411 26.9233 -4.42199 0.000002 26.6513 -5.16946 -6.06411 25.9512 -7.09274 -11.3379 25.2533 -9.01027 -14.4361 24.4539 -11.2067 -17.0429 22.907 -15.4568 -20.3306 20.9744 -20.7665 -22.6675 18.8971 -26.4738 -23.4671 16.8198 -32.1813 -22.6675 14.884 -37.4998 -20.3231 13.2217 -42.0668 -16.5937 11.9462 -45.5713 -11.7335 11.1444 -47.7743 -6.07373 10.8709 -48.5257 0.000002 11.1444 -47.7743 6.07373 11.9462 -45.5713 11.7336 13.2217 -42.0668 16.5938 14.884 -37.4998 20.3231 16.8198 -32.1813 22.6675 18.8971 -26.4738 23.4671 20.9744 -20.7665 22.6675 24.794 -9.14461 14.2177 24.0092 -11.3007 16.7766 22.4845 -15.4898 20.0171 25.4797 -7.26045 11.1734 26.1697 -5.3647 5.9751 26.4378 -4.62821 0.000002 26.1697 -5.3647 -5.9751 25.4797 -7.26045 -11.1734 24.794 -9.14461 -14.2177 24.0092 -11.3007 -16.7766 22.4845 -15.4898 -20.0171 20.5801 -20.722 -22.3199 18.5347 -26.3419 -23.1072 16.4892 -31.9618 -22.3199 14.5831 -37.1988 -20.0115 12.9463 -41.6958 -16.3393 11.6903 -45.1465 -11.5536 10.9008 -47.3157 -5.98059 10.6315 -48.0556 0.000002 10.9008 -47.3157 5.9806 11.6903 -45.1465 11.5536 12.9463 -41.6958 16.3393 14.5831 -37.1988 20.0115 16.4892 -31.9618 22.3199 18.5347 -26.3419 23.1073 20.5801 -20.722 22.3199 24.5387 -8.77462 14.4184 23.7404 -10.9678 17.0213 22.1953 -15.2129 20.3052 25.2356 -6.8598 11.3246 25.9348 -4.93875 6.0569 26.2066 -4.19217 0.000003 25.9348 -4.93875 -6.05689 25.2356 -6.8598 -11.3246 24.5387 -8.77462 -14.4184 23.7404 -10.9678 -17.0213 22.1953 -15.2129 -20.3051 20.2651 -20.5163 -22.6393 18.1903 -26.2166 -23.4379 16.1156 -31.9169 -22.6393 14.1822 -37.2288 -20.2978 12.522 -41.7902 -16.5731 11.2481 -45.2903 -11.719 10.4472 -47.4906 -6.06618 10.1741 -48.241 0.000003 10.4472 -47.4906 6.06618 11.2481 -45.2903 11.719 12.522 -41.7902 16.5731 14.1822 -37.2288 20.2978 16.1156 -31.9169 22.6393 18.1903 -26.2166 23.4379 20.2651 -20.5163 22.6393 23.3031 -8.50421 14.2886 22.5136 -10.6734 16.863 20.9817 -14.8822 20.1187 23.9929 -6.60922 11.2268 24.6861 -4.70455 6.00397 24.9555 -3.96449 0.000004 24.6861 -4.70455 -6.00396 23.9929 -6.60922 -11.2267 23.3031 -8.50421 -14.2885 22.5136 -10.6734 -16.863 20.9817 -14.8822 -20.1187 19.0682 -20.1396 -22.4326 17.0124 -25.7879 -23.224 14.9566 -31.4362 -22.4326 13.0409 -36.6995 -20.1125 11.3958 -41.2193 -16.4218 10.1335 -44.6875 -11.612 9.34 -46.8676 -6.0108 9.06934 -47.6112 0.000004 9.34 -46.8676 6.01081 10.1335 -44.6875 11.612 11.3958 -41.2193 16.4218 13.0409 -36.6995 20.1125 14.9566 -31.4362 22.4326 17.0124 -25.7879 23.224 19.0682 -20.1396 22.4326 21.4425 -8.68268 13.6687 20.6946 -10.7373 16.1071 19.2257 -14.7731 19.2291 22.0977 -6.88237 10.7599 22.7625 -5.05583 5.75137 23.0205 -4.34691 0.000007 22.7625 -5.05583 -5.75135 22.0977 -6.88237 -10.7599 21.4425 -8.68268 -13.6687 20.6946 -10.7373 -16.1071 19.2257 -14.7731 -19.2291 17.3922 -19.8106 -21.4462 15.4267 -25.2107 -22.2028 13.4613 -30.6107 -21.4462 11.6298 -35.6426 -19.2281 10.0571 -39.9636 -15.6997 8.85032 -43.2793 -11.1014 8.09169 -45.3636 -5.74649 7.83294 -46.0745 0.000007 8.09169 -45.3636 5.7465 8.85032 -43.2793 11.1014 10.0571 -39.9636 15.6997 11.6298 -35.6426 19.2282 13.4613 -30.6107 21.4462 15.4267 -25.2107 22.2028 17.3922 -19.8106 21.4462 19.3772 -10.5226 11.7916 18.7558 -12.2301 13.818 17.4775 -15.742 16.5347 19.9281 -9.00902 9.34606 20.5068 -7.41909 4.98633 20.7305 -6.80447 0.00001 20.5068 -7.41909 -4.98631 19.9281 -9.00902 -9.34604 19.3772 -10.5226 -11.7915 18.7558 -12.2301 -13.818 17.4775 -15.742 -16.5347 15.8865 -20.1135 -18.4587 14.1944 -24.7622 -19.11 12.5028 -29.41 -18.4588 10.9264 -33.741 -16.5497 9.57279 -37.4601 -13.5128 8.5341 -40.3139 -9.55498 7.88115 -42.1078 -4.94602 7.65843 -42.7197 0.00001 7.88114 -42.1078 4.94604 8.53409 -40.3139 9.555 9.57278 -37.4601 13.5128 10.9264 -33.741 16.5497 12.5028 -29.4099 18.4588 14.1944 -24.7622 19.11 15.8864 -20.1135 18.4587 18.3016 -12.2092 10.2863 17.7814 -13.6384 11.9824 16.6561 -16.7302 14.3741 18.7688 -10.9256 8.2123 19.2784 -9.52541 4.37286 19.4746 -8.98641 0.000011 19.2784 -9.52541 -4.37284 18.7688 -10.9256 -8.21228 18.3016 -12.2092 -10.2863 17.7814 -13.6384 -11.9824 16.6561 -16.7302 -14.3741 15.2594 -20.5676 -16.063 13.7867 -24.6138 -16.6299 12.3146 -28.6584 -16.0633 10.9428 -32.4273 -14.4019 9.76484 -35.6638 -11.7591 8.86094 -38.1472 -8.31495 8.29273 -39.7083 -4.30413 8.09891 -40.2408 0.000012 8.29272 -39.7083 4.30415 8.86093 -38.1472 8.31498 9.76482 -35.6638 11.7591 10.9428 -32.4273 14.402 12.3146 -28.6584 16.0633 13.7867 -24.6138 16.6299 15.2594 -20.5676 16.0631 18.3733 -13.1399 9.63104 17.8972 -14.4479 11.1834 16.8384 -17.3569 13.4337 18.8041 -11.9564 7.71878 19.2836 -10.6388 4.10582 19.4678 -10.1327 0.000009 19.2837 -10.6388 -4.1058 18.8041 -11.9564 -7.71876 18.3733 -13.1399 -9.63102 17.8973 -14.4479 -11.1834 16.8385 -17.3569 -13.4336 15.5264 -20.9618 -15.0202 14.1492 -24.7457 -15.5504 12.7726 -28.5277 -15.0205 11.4899 -32.052 -13.467 10.3884 -35.0784 -10.9958 9.54314 -37.4006 -7.77518 9.01181 -38.8604 -4.02472 8.83058 -39.3583 0.000011 9.0118 -38.8604 4.02474 9.54312 -37.4006 7.7752 10.3883 -35.0784 10.9958 11.4898 -32.052 13.467 12.7726 -28.5277 15.0205 14.1491 -24.7457 15.5504 15.5263 -20.9618 15.0203 19.7795 -14.9149 8.71605 19.365 -16.0537 10.0676 18.3992 -18.7074 12.1204 20.1594 -13.8712 7.02962 20.597 -12.6689 3.73291 20.7645 -12.2088 0.000001 20.597 -12.6689 -3.73291 20.1594 -13.8712 -7.02962 19.7795 -14.9149 -8.71606 19.3651 -16.0537 -10.0676 18.3992 -18.7074 -12.1203 17.2053 -21.9876 -13.5641 15.9614 -25.4053 -14.0429 14.7183 -28.8207 -13.5644 13.5599 -32.0033 -12.1615 12.5651 -34.7363 -9.92982 11.8019 -36.8334 -7.02145 11.322 -38.1517 -3.63456 11.1584 -38.6013 0.000003 11.322 -38.1516 3.63457 11.8018 -36.8334 7.02145 12.5651 -34.7363 9.92982 13.5598 -32.0033 12.1615 14.7182 -28.8207 13.5644 15.9613 -25.4053 14.0429 17.2052 -21.9876 13.5641 20.8498 -15.0192 8.92266 20.4214 -16.1962 10.3196 19.4345 -18.9075 12.4169 21.2412 -13.9439 7.18523 21.6882 -12.7156 3.81711 21.8595 -12.2451 -0.000004 21.6883 -12.7156 -3.81712 21.2412 -13.9439 -7.18524 20.8498 -15.0192 -8.92267 20.4214 -16.1962 -10.3196 19.4346 -18.9075 -12.4169 18.214 -22.2611 -13.8929 16.9399 -25.7615 -14.3833 15.6667 -29.2596 -13.8932 14.4802 -32.5194 -12.4563 13.4614 -35.3186 -10.1705 12.6796 -37.4666 -7.19165 12.1882 -38.8168 -3.72267 12.0205 -39.2773 -0.000002 12.1882 -38.8168 3.72267 12.6796 -37.4666 7.19164 13.4614 -35.3186 10.1705 14.4802 -32.5194 12.4563 15.6667 -29.2596 13.8932 16.9399 -25.7615 14.3833 18.2139 -22.2611 13.8929 20.9041 -11.4576 3.94218 20.4718 -12.6451 7.27939 19.9923 -13.9626 9.47182 19.4148 -15.5493 11.2728 18.4457 -18.212 13.2813 17.1872 -21.6697 14.7675 15.8432 -25.3623 15.303 14.4961 -29.0634 14.769 13.2374 -32.5216 13.2357 12.1568 -35.4905 10.7965 11.3259 -37.7732 7.654 10.7908 -39.2436 3.95673 10.6173 -39.7203 -0.025641 10.8024 -39.2117 -3.96121 11.3223 -37.7831 -7.63933 12.1494 -35.5108 -10.7949 13.2383 -32.519 -13.2346 14.4979 -29.0583 -14.7602 15.8459 -25.3549 -15.2942 17.1857 -21.6737 -14.7708 18.4354 -18.2401 -13.2849 19.3971 -15.5979 -11.2852 19.9933 -13.96 -9.50144 20.4648 -12.6643 -7.2571 20.8936 -11.4864 -3.90658 21.0754 -10.9869 0.027026 22.9903 -11.6839 0.027026 22.8085 -12.1834 -3.90658 17.7581 -26.0592 15.303 19.1021 -22.3666 14.7675 13.2373 -38.4801 -7.63933 12.7173 -39.9086 -3.96121 13.2409 -38.4702 7.654 14.0717 -36.1875 10.7965 20.3504 -18.9371 -13.2849 19.1006 -22.3707 -14.7708 20.3606 -18.9089 13.2813 21.3297 -16.2463 11.2728 14.0643 -36.2078 -10.7949 22.3868 -13.3421 7.27939 22.819 -12.1546 3.94218 21.9082 -14.657 -9.50144 21.312 -16.2949 -11.2852 22.3798 -13.3613 -7.2571 15.1523 -33.2186 13.2357 16.411 -29.7604 14.769 17.7608 -26.0518 -15.2942 16.4129 -29.7553 -14.7602 12.7057 -39.9406 3.95673 21.9072 -14.6596 9.47182 15.1533 -33.216 -13.2346 12.5322 -40.4173 -0.025641 21.5594 -18.3316 -7.89785 22.3073 -16.2768 -4.24114 22.5432 -15.6285 1.50936 21.9674 -17.2105 6.36652 20.978 -19.9289 9.33162 19.1426 -24.9717 11.4278 17.1298 -30.5019 10.6428 15.5145 -34.9398 7.01224 14.7261 -37.1059 1.49487 14.9985 -36.3576 -4.40715 16.2384 -32.9509 -9.13015 18.1217 -27.7766 -11.4196 20.1271 -22.2668 -10.6601 17.4364 -30.5537 -5.65913 16.6677 -32.6659 -2.73086 16.9876 -31.7868 4.34916 17.9891 -29.0353 6.60013 20.9884 -20.7947 3.94881 21.3454 -19.8138 0.93737 21.1991 -20.2158 -2.62794 19.237 -25.6066 7.08683 20.375 -22.4801 5.78717 16.4988 -33.1298 0.928389 18.6041 -27.3456 -7.07858 20.7354 -21.4897 -4.8951 19.8474 -23.9296 -6.6077 19.0701 -26.0652 0.002965 31.8631 -13.5079 14.0306 38.9087 -22.8008 2.43989 34.8117 -16.1543 12.6529 37.0572 -19.2137 10.0738 38.5939 -22.0099 5.81801 30.1198 -14.4466 12.6529 28.4629 -18.9988 2.43989 29.3992 -16.4264 10.0738 28.6802 -18.4017 5.81801 30.6783 -12.912 14.174 31.4328 -13.7396 13.6906 38.2658 -22.5668 2.43989 33.7835 -15.7801 12.6529 36.3196 -18.9452 10.0738 37.9374 -21.771 5.81801 29.3235 -19.312 2.43989 30.9804 -14.7598 12.6529 30.2598 -16.7396 10.0738 29.5409 -18.7149 5.81801 30.5299 -13.3197 13.7699 29.5526 -16.005 2.34735 29.7388 -15.4933 5.37563 30.3548 -13.8009 8.51171 35.3295 -13.7814 10.3042 37.6569 -16.5918 8.1095 30.9722 -12.1046 10.5944 31.3236 -11.1391 11.4963 31.4507 -10.7898 11.8227 32.5681 -11.3376 11.7068 39.1871 -22.0359 2.43989 38.8723 -21.245 5.81801 37.3356 -18.4488 10.0738 35.0901 -15.3894 12.6529 32.1415 -12.743 14.0306 30.9567 -12.1471 14.174 30.8083 -12.5548 13.7699 30.3982 -13.6817 12.6529 29.6776 -15.6615 10.0738 28.9586 -17.6368 5.81801 28.7413 -18.2339 2.43989 32.3077 -15.474 12.6529 33.4553 -21.8718 2.43989 33.4346 -21.0798 5.81801 33.1002 -18.3632 10.0738 38.6078 -12.23 7.12674 40.1086 -7.27288 6.38726 38.9995 -19.1175 4.30809 40.4722 -14.3091 3.83942 41.5879 -9.21705 2.9614 35.3982 -11.7744 9.95378 37.4255 -10.2806 7.9831 32.4214 -11.8209 12.5059 31.248 -11.3468 12.7875 31.1306 -11.6692 12.3477 40.811 -8.02459 5.71511 41.2912 -4.07134 3.27877 41.7989 -5.05268 2.97755 42.1911 -6.57271 1.95967 30.8 -12.5778 11.2119 29.3092 -16.6737 2.37511 29.5047 -16.1364 5.50835 30.1516 -14.3591 8.98033 31.6429 -13.799 13.1096 31.1415 -13.4054 13.3999 31.2968 -13.0982 13.4908 31.9486 -13.507 13.2853 38.4029 -22.0228 2.34885 38.5788 -22.0843 2.36512 36.4374 -18.4987 9.73593 33.8969 -15.4176 12.2276 34.6447 -15.7551 12.1616 36.7916 -18.6421 9.71428 38.0623 -21.2475 5.6177 38.274 -21.3209 5.62813 29.2 -18.6717 2.41468 29.6735 -18.8353 2.50635 30.0479 -16.1823 9.70267 30.6965 -14.4078 12.3806 30.9659 -14.5535 12.1325 30.3909 -16.2614 9.53406 29.4753 -17.8323 5.67988 29.9103 -17.9699 5.73712 32.5052 -15.2826 12.0854 37.922 -21.6885 2.40367 37.9955 -18.8919 4.14823 37.7423 -20.9606 5.62625 36.7707 -18.4306 9.7123 37.1502 -16.6445 7.80245 34.6978 -15.5355 12.1746 34.8908 -13.9542 9.95446 32.0848 -13.1318 13.1425 32.3548 -12.4633 12.1694 31.3875 -12.7273 13.3917 31.6254 -12.1303 12.4919 31.2453 -12.8767 13.4893 31.5204 -12.174 12.3091 30.8616 -13.9478 12.4927 30.1769 -15.8769 9.89028 29.552 -17.6161 5.87996 29.2603 -18.4264 2.5163 33.6495 -21.3369 2.34382 33.6156 -20.5672 5.61126 33.2569 -17.9287 9.73011 39.5553 -14.0354 3.6229 38.3069 -12.2143 6.72532 40.8019 -9.05754 2.80834 37.3425 -10.284 7.8698 37.1764 -10.2908 7.64321 37.0934 -10.2942 7.52992 40.0165 -7.28835 6.29475 39.8323 -7.31929 6.10974 39.7402 -7.33476 6.01723 40.3016 -8.00008 5.38928 35.3158 -11.791 9.84028 35.1508 -11.8241 9.61327 35.0684 -11.8407 9.49977 32.5082 -11.4416 11.6322 32.3884 -11.6497 11.483 32.3285 -11.7538 11.4084 31.5477 -10.9322 11.7979 31.7416 -11.217 11.7484 31.774 -11.5368 11.5738 31.455 -11.187 11.4963 31.6532 -11.46 11.3466 31.7845 -11.5078 11.3466 31.3255 -12.769 11.2119 31.1035 -12.1525 10.5944 31.3663 -12.2481 10.5944 31.4977 -12.2959 10.5944 41.1742 -4.11559 3.21812 40.9403 -4.20407 3.09682 40.8233 -4.24832 3.03618 41.2813 -5.15996 2.75771 41.4687 -6.4954 1.80478 29.8347 -16.8649 2.37511 29.6839 -16.0528 2.34735 29.9467 -16.1484 2.34735 30.0781 -16.1963 2.34735 30.0303 -16.3276 5.50835 29.8702 -15.5412 5.37563 30.1329 -15.6368 5.37563 30.2643 -15.6846 5.37563 30.6772 -14.5504 8.98033 30.4861 -13.8488 8.51171 30.7489 -13.9444 8.51171 30.8803 -13.9922 8.51171 31.8631 -13.5079 -14.0306 38.9087 -22.8008 -2.43989 34.8117 -16.1543 -12.6529 37.0572 -19.2137 -10.0738 38.5939 -22.0099 -5.81801 30.1198 -14.4466 -12.6529 28.4629 -18.9988 -2.43989 29.3992 -16.4264 -10.0738 28.6802 -18.4017 -5.81801 30.6783 -12.912 -14.174 31.4328 -13.7396 -13.6906 38.2658 -22.5668 -2.43989 33.7835 -15.7801 -12.6529 36.3196 -18.9452 -10.0738 37.9374 -21.771 -5.81801 29.3235 -19.312 -2.43989 30.9804 -14.7598 -12.6529 30.2598 -16.7396 -10.0738 29.5409 -18.7149 -5.81801 30.5299 -13.3197 -13.7699 29.5526 -16.005 -2.34735 29.7388 -15.4933 -5.37563 30.3548 -13.8009 -8.51171 35.3295 -13.7814 -10.3042 37.6569 -16.5918 -8.1095 30.9722 -12.1046 -10.5943 31.3236 -11.1391 -11.4963 31.4507 -10.7898 -11.8227 32.5681 -11.3376 -11.7068 39.1871 -22.0359 -2.43989 38.8723 -21.245 -5.81801 37.3356 -18.4488 -10.0738 35.0901 -15.3894 -12.6529 32.1415 -12.743 -14.0306 30.9567 -12.1471 -14.174 30.8083 -12.5548 -13.7699 30.3982 -13.6817 -12.6529 29.6776 -15.6615 -10.0738 28.9586 -17.6368 -5.81801 28.7413 -18.2339 -2.43989 32.3077 -15.474 -12.6529 33.4553 -21.8718 -2.43989 33.4346 -21.0798 -5.81801 33.1002 -18.3632 -10.0738 38.6078 -12.23 -7.12674 40.1086 -7.27288 -6.38726 38.9995 -19.1175 -4.30809 40.4722 -14.3091 -3.83942 41.5879 -9.21705 -2.9614 35.3982 -11.7744 -9.95378 37.4255 -10.2806 -7.9831 32.4214 -11.8209 -12.5059 31.248 -11.3468 -12.7875 31.1306 -11.6692 -12.3477 40.811 -8.02459 -5.71511 41.2912 -4.07134 -3.27877 41.7989 -5.05268 -2.97755 42.1911 -6.57271 -1.95967 30.8 -12.5778 -11.2119 29.3092 -16.6737 -2.37511 29.5047 -16.1364 -5.50835 30.1516 -14.3591 -8.98033 31.6429 -13.799 -13.1096 31.1415 -13.4054 -13.3999 31.2968 -13.0982 -13.4908 31.9486 -13.507 -13.2853 38.4029 -22.0228 -2.34885 38.5788 -22.0843 -2.36512 36.4374 -18.4987 -9.73593 33.8969 -15.4176 -12.2276 34.6447 -15.7551 -12.1616 36.7916 -18.6421 -9.71428 38.0623 -21.2475 -5.6177 38.274 -21.3209 -5.62813 29.2 -18.6717 -2.41468 29.6735 -18.8353 -2.50635 30.0479 -16.1823 -9.70267 30.6965 -14.4078 -12.3806 30.9659 -14.5535 -12.1325 30.3909 -16.2614 -9.53406 29.4753 -17.8323 -5.67988 29.9103 -17.9699 -5.73712 32.5052 -15.2826 -12.0854 37.922 -21.6885 -2.40367 37.9955 -18.8919 -4.14823 37.7423 -20.9606 -5.62625 36.7707 -18.4306 -9.7123 37.1502 -16.6445 -7.80245 34.6978 -15.5355 -12.1746 34.8908 -13.9542 -9.95446 32.0848 -13.1318 -13.1425 32.3548 -12.4633 -12.1694 31.3875 -12.7273 -13.3917 31.6254 -12.1303 -12.4919 31.2453 -12.8767 -13.4893 31.5204 -12.174 -12.3091 30.8616 -13.9478 -12.4927 30.1769 -15.8769 -9.89028 29.552 -17.6161 -5.87996 29.2603 -18.4264 -2.5163 33.6495 -21.3369 -2.34382 33.6156 -20.5672 -5.61126 33.2569 -17.9287 -9.73011 39.5553 -14.0354 -3.6229 38.3069 -12.2143 -6.72532 40.8019 -9.05754 -2.80834 37.3425 -10.284 -7.8698 37.1764 -10.2908 -7.64321 37.0934 -10.2942 -7.52992 40.0165 -7.28835 -6.29475 39.8323 -7.31929 -6.10974 39.7402 -7.33476 -6.01723 40.3016 -8.00008 -5.38928 35.3158 -11.791 -9.84028 35.1508 -11.8241 -9.61327 35.0684 -11.8407 -9.49977 32.5082 -11.4416 -11.6322 32.3884 -11.6497 -11.483 32.3285 -11.7538 -11.4084 31.5477 -10.9322 -11.7979 31.7416 -11.217 -11.7484 31.774 -11.5368 -11.5738 31.455 -11.187 -11.4963 31.6532 -11.46 -11.3466 31.7845 -11.5078 -11.3466 31.3255 -12.769 -11.2119 31.1035 -12.1525 -10.5943 31.3663 -12.2481 -10.5943 31.4977 -12.2959 -10.5943 41.1742 -4.11559 -3.21812 40.9403 -4.20407 -3.09682 40.8233 -4.24832 -3.03618 41.2813 -5.15996 -2.75771 41.4687 -6.4954 -1.80478 29.8347 -16.8649 -2.37511 29.6839 -16.0528 -2.34735 29.9467 -16.1484 -2.34735 30.0781 -16.1963 -2.34735 30.0303 -16.3276 -5.50835 29.8702 -15.5412 -5.37563 30.1329 -15.6368 -5.37563 30.2643 -15.6846 -5.37563 30.6772 -14.5504 -8.98033 30.4861 -13.8488 -8.51171 30.7489 -13.9444 -8.51171 30.8803 -13.9922 -8.51171 28.3722 -19.248 0 29.2328 -19.5613 0 28.6506 -18.4831 0 29.4748 -16.2185 0 29.2276 -16.8979 0 29.1338 -18.8939 0 29.611 -19.0851 0 29.1856 -18.6361 0 29.7531 -17.0892 0 29.6062 -16.2663 0 29.869 -16.362 0 30.0004 -16.4098 0 38.9853 -23.1109 0 38.3622 -22.8841 0 39.2637 -22.346 0 33.4436 -22.1949 0 39.3089 -19.7951 0 38.4971 -22.3285 0 38.6526 -22.3851 0 38.1873 -19.4894 0 37.9641 -21.9707 0 33.6399 -21.6473 0 40.9589 -14.7996 0 39.8884 -14.4478 0 42.1476 -9.69492 0 41.1941 -9.44314 0 42.52 -6.10773 0 42.2528 -4.19503 0 41.7902 -3.43875 0 41.7184 -6.07298 0 41.6939 -4.37856 0 41.6841 -3.47806 0 41.4719 -3.5567 0 41.3658 -3.59602 0 2.26879 46.8666 0 2.26879 50.1374 0 6.65661 49.8534 0 12.7156 48.6616 0 18.5243 46.5662 0 23.9488 43.6156 0 28.8641 39.8777 0 33.1568 35.4388 0 36.728 30.4011 0 39.4954 24.8809 0 41.3952 19.0053 0 38.2156 18.2382 0 36.4687 23.6413 0 33.9238 28.7176 0 30.6398 33.3501 0 26.6923 37.432 0 22.1723 40.8693 0 17.184 43.5826 0 11.8425 45.5095 0 6.27078 46.6055 0 2.26879 46.8666 -5.55064 2.26879 47.7055 -6.38954 2.26879 49.2985 -6.38954 2.26879 50.1374 -5.55064 6.65661 49.8534 -5.55064 6.55765 49.0204 -6.38954 12.7156 48.6616 -5.55064 12.4916 47.8531 -6.38954 18.5243 46.5662 -5.55064 18.1805 45.801 -6.38954 23.9488 43.6156 -5.55064 23.4932 42.9112 -6.38954 28.8641 39.8777 -5.55064 28.307 39.2504 -6.38954 33.1568 35.4388 -5.55064 32.5112 34.9031 -6.38954 36.728 30.4011 -5.55064 36.0088 29.9693 -6.38954 39.4954 24.8809 -5.55064 38.7191 24.5629 -6.38954 41.3952 19.0053 -5.55064 40.5797 18.8085 -6.38954 41.5933 7.63018 -6.38954 42.4303 7.57383 -5.55064 39.1669 7.79354 -5.55064 40.0039 7.73718 -6.38954 39.0311 18.4349 -6.38954 38.2156 18.2382 -5.55064 37.245 23.9592 -6.38954 36.4687 23.6413 -5.55064 34.6431 29.1494 -6.38954 33.9238 28.7176 -5.55064 31.2854 33.8858 -6.38954 30.6398 33.3501 -5.55064 27.2493 38.0593 -6.38954 26.6923 37.432 -5.55064 22.6279 41.5737 -6.38954 22.1723 40.8693 -5.55064 17.5278 44.3479 -6.38954 17.184 43.5826 -5.55064 12.0664 46.318 -6.38954 11.8425 45.5095 -5.55064 6.36974 47.4385 -6.38954 6.27078 46.6055 -5.55064 2.26879 47.7055 6.38954 2.26879 46.8666 5.55064 2.26879 49.2985 6.38954 2.26879 50.1374 5.55064 6.55765 49.0204 6.38954 6.65661 49.8534 5.55064 12.4916 47.8531 6.38954 12.7156 48.6616 5.55064 18.1805 45.801 6.38954 18.5243 46.5662 5.55064 23.4932 42.9112 6.38954 23.9488 43.6156 5.55064 28.307 39.2504 6.38954 28.8641 39.8777 5.55064 32.5112 34.9031 6.38954 33.1568 35.4388 5.55064 36.0088 29.9693 6.38954 36.728 30.4011 5.55064 38.7191 24.5629 6.38954 39.4954 24.8809 5.55064 40.5797 18.8085 6.38954 41.3952 19.0053 5.55064 42.4303 7.57383 5.55064 41.5933 7.63018 6.38954 40.0039 7.73718 6.38954 39.1669 7.79354 5.55064 38.2156 18.2382 5.55064 39.0311 18.4349 6.38954 36.4687 23.6413 5.55064 37.245 23.9592 6.38954 33.9238 28.7176 5.55064 34.6431 29.1494 6.38954 30.6398 33.3501 5.55064 31.2854 33.8858 6.38954 26.6923 37.432 5.55064 27.2493 38.0593 6.38954 22.1723 40.8693 5.55064 22.6279 41.5737 6.38954 17.184 43.5826 5.55064 17.5278 44.3479 6.38954 11.8425 45.5095 5.55064 12.0664 46.318 6.38954 6.27078 46.6055 5.55064 6.36974 47.4385 6.38954 42.4303 7.57383 0 39.1669 7.79354 0 41.3577 7.10483 -5.90741 41.913 7.06745 -5.35093 39.6117 7.22239 -5.35093 40.1669 7.18501 -5.90741 41.913 7.06745 5.35093 41.3577 7.10483 5.90741 40.1669 7.18501 5.90741 39.6117 7.22239 5.35094 41.913 7.06745 0 39.6117 7.22239 0 41.7415 7.6825 0 41.6901 7.6783 2.82599 41.7536 7.67727 5.07011 39.8952 7.67941 5.06932 40.0036 7.67417 4.35142 40.433 7.69764 2.74187 40.5889 7.70137 0 40.433 7.69764 -2.74187 40.0036 7.67417 -4.35142 39.8952 7.67941 -5.06932 41.7536 7.67727 -5.07011 41.6901 7.6783 -2.82599 -2.26879 46.8666 0 -2.26879 50.1374 0 -6.65661 49.8534 0 -12.7156 48.6616 0 -18.5243 46.5662 0 -23.9488 43.6156 0 -28.8641 39.8777 0 -33.1568 35.4388 0 -36.728 30.4011 0 -39.4954 24.8809 0 -41.3952 19.0053 0 -38.2156 18.2382 0 -36.4687 23.6413 0 -33.9238 28.7176 0 -30.6398 33.3501 0 -26.6923 37.432 0 -22.1723 40.8693 0 -17.184 43.5826 0 -11.8425 45.5095 0 -6.27078 46.6055 0 -2.26879 46.8666 -5.55064 -2.26879 47.7055 -6.38954 -2.26879 49.2985 -6.38954 -2.26879 50.1374 -5.55064 -6.65661 49.8534 -5.55064 -6.55765 49.0204 -6.38954 -12.7156 48.6616 -5.55064 -12.4916 47.8531 -6.38954 -18.5243 46.5662 -5.55064 -18.1805 45.801 -6.38954 -23.9488 43.6156 -5.55064 -23.4932 42.9112 -6.38954 -28.8641 39.8777 -5.55064 -28.307 39.2504 -6.38954 -33.1568 35.4388 -5.55064 -32.5112 34.9031 -6.38954 -36.728 30.4011 -5.55064 -36.0088 29.9693 -6.38954 -39.4954 24.8809 -5.55064 -38.7191 24.5629 -6.38954 -41.3952 19.0053 -5.55064 -40.5797 18.8085 -6.38954 -41.5933 7.63018 -6.38954 -42.4303 7.57383 -5.55064 -39.1669 7.79354 -5.55064 -40.0039 7.73718 -6.38954 -39.0311 18.4349 -6.38954 -38.2156 18.2382 -5.55064 -37.245 23.9592 -6.38954 -36.4687 23.6413 -5.55064 -34.6431 29.1494 -6.38954 -33.9238 28.7176 -5.55064 -31.2854 33.8858 -6.38954 -30.6398 33.3501 -5.55064 -27.2493 38.0593 -6.38954 -26.6923 37.432 -5.55064 -22.6279 41.5737 -6.38954 -22.1723 40.8693 -5.55064 -17.5278 44.3479 -6.38954 -17.184 43.5826 -5.55064 -12.0664 46.318 -6.38954 -11.8425 45.5095 -5.55064 -6.36974 47.4385 -6.38954 -6.27078 46.6055 -5.55064 -2.26879 47.7055 6.38954 -2.26879 46.8666 5.55064 -2.26879 49.2985 6.38954 -2.26879 50.1374 5.55064 -6.55765 49.0204 6.38954 -6.65661 49.8534 5.55064 -12.4916 47.8531 6.38954 -12.7156 48.6616 5.55064 -18.1805 45.801 6.38954 -18.5243 46.5662 5.55064 -23.4932 42.9112 6.38954 -23.9488 43.6156 5.55064 -28.307 39.2504 6.38954 -28.8641 39.8777 5.55064 -32.5112 34.9031 6.38954 -33.1568 35.4388 5.55064 -36.0088 29.9693 6.38954 -36.728 30.4011 5.55064 -38.7191 24.5629 6.38954 -39.4954 24.8809 5.55064 -40.5797 18.8085 6.38954 -41.3952 19.0053 5.55064 -42.4303 7.57383 5.55064 -41.5933 7.63018 6.38954 -40.0039 7.73718 6.38954 -39.1669 7.79354 5.55064 -38.2156 18.2382 5.55064 -39.0311 18.4349 6.38954 -36.4687 23.6413 5.55064 -37.245 23.9592 6.38954 -33.9238 28.7176 5.55064 -34.6431 29.1494 6.38954 -30.6398 33.3501 5.55064 -31.2854 33.8858 6.38954 -26.6923 37.432 5.55064 -27.2493 38.0593 6.38954 -22.1723 40.8693 5.55064 -22.6279 41.5737 6.38954 -17.184 43.5826 5.55064 -17.5278 44.3479 6.38954 -11.8425 45.5095 5.55064 -12.0664 46.318 6.38954 -6.27078 46.6055 5.55064 -6.36974 47.4385 6.38954 -42.4303 7.57383 0 -39.1669 7.79354 0 -41.3577 7.10483 -5.90741 -41.913 7.06745 -5.35093 -39.6117 7.22239 -5.35093 -40.1669 7.18501 -5.90741 -41.913 7.06745 5.35093 -41.3577 7.10483 5.90741 -40.1669 7.18501 5.90741 -39.6117 7.22239 5.35094 -41.913 7.06745 0 -39.6117 7.22239 0 42.2569 13.6903 0 42.5045 12.1288 0 39.0173 11.8326 0 38.9979 13.4134 0 42.2569 13.6903 -5.55064 42.5045 12.1288 -5.93918 41.6101 12.0528 -6.8368 41.4211 13.6193 -6.38954 39.8338 13.4844 -6.38954 39.9117 11.9086 -6.8368 39.0173 11.8326 -5.93918 38.9979 13.4134 -5.55064 41.4211 13.6193 6.38954 41.6101 12.0528 6.8368 42.5045 12.1288 5.93918 42.2569 13.6903 5.55064 38.9979 13.4134 5.55064 39.0173 11.8326 5.93918 39.9117 11.9086 6.8368 39.8338 13.4844 6.38954 -42.5045 12.1288 0 -42.2569 13.6903 0 -38.9979 13.4134 0 -39.0173 11.8326 0 -42.2569 13.6903 -5.55064 -42.5045 12.1288 -5.93918 -41.4211 13.6193 -6.38954 -41.6101 12.0528 -6.8368 -39.9117 11.9086 -6.8368 -39.8338 13.4844 -6.38954 -39.0173 11.8326 -5.93918 -38.9979 13.4134 -5.55064 -41.6101 12.0528 6.8368 -41.4211 13.6193 6.38954 -42.2569 13.6903 5.55064 -42.5045 12.1288 5.93918 -39.0173 11.8326 5.93918 -38.9979 13.4134 5.55064 -39.9117 11.9086 6.8368 -39.8338 13.4844 6.38954 -42.5002 12.9197 0 -42.5002 12.9197 -5.92919 41.5891 12.8423 6.8253 42.5002 12.9197 5.92919 38.9479 12.6179 5.92919 38.9479 12.6179 0 -41.5891 12.8423 -6.8253 -39.859 12.6953 -6.8253 38.9479 12.6179 -5.92919 39.859 12.6953 -6.8253 -41.5891 12.8423 6.8253 -42.5002 12.9197 5.92919 39.859 12.6953 6.8253 -39.859 12.6953 6.8253 -38.9479 12.6179 0 -38.9479 12.6179 5.92919 -38.9479 12.6179 -5.92919 41.5891 12.8423 -6.8253 42.5002 12.9197 -5.92919 42.5002 12.9197 0 -41.0358 1.45843 3.02491 -40.0585 -2.85087 5.11285 -38.3141 -7.28645 6.05386 -41.5534 5.08738 2.82599 -39.0034 -2.78983 5.10091 -38.2918 -2.86791 6.1526 -39.4206 1.68737 4.63022 -39.9566 1.81482 2.8632 -37.4312 -6.96178 6.05155 -36.8421 -6.79753 6.94469 -40.2991 5.17249 2.74187 -39.869 5.17153 4.35142 -38.4357 -7.13643 7.60584 -38.2967 -7.30787 4.23102 -41.1984 1.75076 5.28422 -40.0585 -2.85087 6.7955 -40.0314 -2.94048 3.10001 -40.6607 -0.506353 1.58287 -41.6167 5.08303 5.07011 -39.7611 5.18243 5.06932 -39.3573 1.91479 5.28277 -38.263 -2.5664 6.7955 -36.7986 -6.57934 7.61329 -39.8702 -2.88533 3.09597 -40.4948 -0.469227 1.58351 -38.1597 -7.21039 4.23068 -37.6345 -7.00927 4.23014 -39.2813 -2.79117 3.08937 -39.8899 -0.404788 1.58456 -37.6 -7.09958 3.86024 -39.2542 -2.93965 2.73803 -39.8555 -0.668652 1.30965 -34.203 -16.9786 6.05386 -34.3115 -16.826 7.60584 -34.1875 -17.0004 4.23102 -34.157 -16.7402 7.60733 -34.0392 -16.9031 4.23068 -33.2202 -16.6826 6.04405 -33.4613 -16.7958 3.86024 -33.4875 -16.7041 4.23014 -32.6384 -16.4488 6.9325 -32.5986 -16.2744 7.61329 -38.0936 -2.66652 3.11071 -36.7245 -6.59999 4.28698 -32.3727 -16.3058 4.28279 -38.7043 -0.35177 1.60975 -38.2934 -2.85245 2.64585 -36.8985 -6.72878 3.77432 -32.5825 -16.3935 3.77215 -38.8525 -0.713107 1.26675 -38.8879 -2.88716 3.80686 -37.3352 -6.94885 4.97355 -33.1258 -16.6582 4.98199 -39.7792 0.252845 2.02742 -38.9115 -2.86728 4.07111 -37.3548 -6.95149 5.19368 -33.1451 -16.6631 5.19887 -39.8436 0.526463 2.23323 -39.6174 1.48775 4.26116 -38.7586 -2.85196 5.93784 -37.2839 -6.83107 6.76231 -33.0787 -16.4966 6.75107 -40.054 3.48323 3.90016 -40.3843 3.94176 2.61978 -32.7251 -16.5042 7.48569 -34.0063 -16.9151 7.48043 -34.0958 -16.9515 7.4507 -34.0033 -17.0719 6.09107 -33.9996 -17.0571 4.52725 -33.9055 -17.0108 4.42492 -33.2978 -16.7624 4.32589 -33.2709 -16.8565 3.96545 -32.6508 -16.5276 3.97262 -32.5219 -16.5153 4.26848 -33.1961 -16.8624 4.83592 -33.2593 -16.8544 5.21753 -33.3389 -16.8684 6.09099 -33.1764 -16.6501 6.90681 -32.7486 -16.6073 7.08346 -34.4232 -16.5636 7.60584 -34.3846 -16.5504 6.05386 -34.3791 -16.5485 4.23102 -34.2568 -16.5064 7.60733 -34.2141 -16.4917 4.23068 -33.66 -16.301 4.23014 -33.6709 -16.3047 3.86024 -32.8276 -16.0145 6.93305 -32.7263 -15.9797 7.61329 -32.8919 -15.9902 3.77224 -32.677 -15.9163 4.28296 -33.3299 -16.1874 4.98158 -33.3486 -16.1938 5.19862 -33.4211 -16.2188 6.04441 -33.2284 -16.1525 6.75147 -41.0358 1.45843 -3.02491 -40.0585 -2.85087 -5.11285 -38.3141 -7.28645 -6.05386 -41.5534 5.08738 -2.82599 -39.0034 -2.78983 -5.10091 -38.2918 -2.86791 -6.1526 -39.4206 1.68737 -4.63022 -39.9566 1.81482 -2.8632 -37.4312 -6.96178 -6.05155 -36.8421 -6.79753 -6.94469 -40.2991 5.17249 -2.74187 -39.869 5.17153 -4.35142 -38.4357 -7.13643 -7.60584 -38.2967 -7.30787 -4.23102 -41.1984 1.75076 -5.28422 -40.0585 -2.85087 -6.7955 -40.0314 -2.94048 -3.10001 -40.6607 -0.506353 -1.58287 -41.6167 5.08303 -5.07011 -39.7611 5.18243 -5.06932 -39.3573 1.91479 -5.28277 -38.263 -2.5664 -6.7955 -36.7986 -6.57934 -7.61329 -39.8702 -2.88533 -3.09597 -40.4948 -0.469227 -1.58351 -38.1597 -7.21039 -4.23068 -37.6345 -7.00927 -4.23014 -39.2813 -2.79117 -3.08937 -39.8899 -0.404788 -1.58456 -37.6 -7.09958 -3.86024 -39.2542 -2.93965 -2.73803 -39.8555 -0.668652 -1.30965 -34.203 -16.9786 -6.05386 -34.3115 -16.826 -7.60584 -34.1875 -17.0004 -4.23102 -34.157 -16.7402 -7.60733 -34.0392 -16.9031 -4.23068 -33.2202 -16.6826 -6.04405 -33.4613 -16.7958 -3.86024 -33.4875 -16.7041 -4.23014 -32.6384 -16.4488 -6.9325 -32.5986 -16.2744 -7.61329 -38.0936 -2.66652 -3.11071 -36.7245 -6.59999 -4.28698 -32.3727 -16.3058 -4.28279 -38.7043 -0.35177 -1.60975 -38.2934 -2.85245 -2.64586 -36.8985 -6.72878 -3.77432 -32.5825 -16.3935 -3.77215 -38.8525 -0.713107 -1.26675 -38.8879 -2.88716 -3.80686 -37.3352 -6.94885 -4.97355 -33.1258 -16.6582 -4.98199 -39.7792 0.252845 -2.02742 -38.9115 -2.86728 -4.07111 -37.3548 -6.95149 -5.19368 -33.1451 -16.6631 -5.19887 -39.8436 0.526463 -2.23323 -39.6174 1.48775 -4.26116 -38.7586 -2.85196 -5.93784 -37.2839 -6.83107 -6.76231 -33.0787 -16.4966 -6.75107 -40.054 3.48323 -3.90016 -40.3843 3.94176 -2.61978 -32.7251 -16.5042 -7.48569 -34.0063 -16.9151 -7.48043 -34.0958 -16.9515 -7.4507 -34.0033 -17.0719 -6.09107 -33.9996 -17.0571 -4.52725 -33.9055 -17.0108 -4.42492 -33.2978 -16.7624 -4.32589 -33.2709 -16.8565 -3.96545 -32.6508 -16.5276 -3.97262 -32.5219 -16.5153 -4.26848 -33.1961 -16.8624 -4.83592 -33.2593 -16.8544 -5.21753 -33.3389 -16.8684 -6.09099 -33.1764 -16.6501 -6.90681 -32.7486 -16.6073 -7.08346 -34.4232 -16.5636 -7.60584 -34.3846 -16.5504 -6.05386 -34.3791 -16.5485 -4.23102 -34.2568 -16.5064 -7.60733 -34.2141 -16.4917 -4.23068 -33.66 -16.301 -4.23014 -33.6709 -16.3047 -3.86024 -32.8276 -16.0145 -6.93305 -32.7263 -15.9797 -7.61329 -32.8919 -15.9902 -3.77224 -32.677 -15.9163 -4.28296 -33.3299 -16.1874 -4.98158 -33.3486 -16.1938 -5.19862 -33.4211 -16.2188 -6.04441 -33.2284 -16.1525 -6.75147 -41.2422 2.51901 0 -41.6049 5.08889 0 -40.2836 3.10687 0 -40.4549 5.16806 0 -40.7581 0.574058 0 -40.5938 0.606495 0 -39.9863 0.662585 0 -39.9444 0.281999 0 -38.7266 0.699332 0 -38.8948 0.188449 0 -39.8289 1.74732 0 -39.9654 2.16694 0 -40.5692 4.36144 0 -31.7005 -8.70096 5.92036 -31.9349 -8.05701 0 -32.2328 -7.23853 0 -31.9571 -7.99599 6.00027 -31.0049 -10.6122 10.7946 -31.2357 -9.97807 10.9907 -31.1488 -10.2168 11.5916 -30.904 -10.8894 11.5017 -30.8822 -10.9492 5.23555 -31.0735 -10.4236 0 -29.6923 -14.2184 6.54629 -29.8377 -13.819 6.23884 -30.3692 -12.3586 9.13231 -30.2735 -12.6215 9.85917 -29.5747 -14.5415 0 -29.5887 -14.5032 3.15953 -29.3653 -15.1169 2.80102 -29.3247 -15.2283 0 -31.7005 -8.70096 -5.92036 -31.9571 -7.99599 -6.00027 -31.0049 -10.6122 -10.7946 -30.904 -10.8894 -11.5017 -31.1488 -10.2168 -11.5916 -31.2357 -9.97807 -10.9907 -30.8822 -10.9492 -5.23555 -29.6923 -14.2184 -6.54629 -30.2735 -12.6215 -9.85917 -30.3692 -12.3586 -9.13231 -29.8377 -13.819 -6.23884 -29.3653 -15.1169 -2.80102 -29.5887 -14.5032 -3.15953 -32.9222 -7.63431 0 -32.6463 -8.39208 6.00027 -31.925 -10.374 10.9907 -31.8382 -10.6126 11.5916 -31.638 -11.1626 11.5017 -30.4275 -14.4882 6.54629 -31.0081 -12.8931 9.85917 -30.1009 -15.3858 2.80102 -30.0604 -15.4971 0 -32.6463 -8.39208 -6.00027 -31.638 -11.1626 -11.5017 -31.8382 -10.6126 -11.5916 -31.925 -10.374 -10.9907 -30.4275 -14.4882 -6.54629 -31.0081 -12.8931 -9.85917 -30.1009 -15.3858 -2.80102 -34.9157 -10.9246 4.4689 -35.0873 -10.4533 4.52896 -35.3116 -9.83695 0 -34.3591 -12.4539 8.63155 -34.2792 -12.6735 9.19695 -34.438 -12.237 9.26884 -34.5072 -12.047 8.78831 -34.2619 -12.7208 3.95417 -33.3333 -15.2723 5.23452 -33.784 -14.034 7.88355 -33.8587 -13.8288 7.30233 -33.4456 -14.9638 4.98868 -33.0506 -16.049 0 -33.0817 -15.9635 2.12429 -33.2534 -15.4917 2.39375 -34.9157 -10.9246 -4.4689 -35.0873 -10.4533 -4.52896 -34.3591 -12.4539 -8.63155 -34.5072 -12.047 -8.78831 -34.438 -12.237 -9.26884 -34.2792 -12.6735 -9.19695 -34.2619 -12.7208 -3.95417 -33.3333 -15.2723 -5.23452 -33.4456 -14.9638 -4.98868 -33.8587 -13.8288 -7.30233 -33.784 -14.034 -7.88355 -33.2534 -15.4917 -2.39375 -33.0817 -15.9635 -2.12429 -33.1792 -11.2899 10.8198 -33.2601 -11.0675 10.2588 -33.9349 -9.21368 5.60072 -34.1938 -8.50223 0 -33.9349 -9.21368 -5.60072 -33.2601 -11.0675 -10.2588 -33.1792 -11.2899 -10.8198 -32.9928 -11.8019 -10.7358 -32.4085 -13.4072 -9.20267 -31.8722 -14.8808 -6.11039 -31.5709 -15.7086 -2.61451 -31.5335 -15.8112 0 -31.5709 -15.7086 2.61451 -31.8722 -14.8808 6.11039 -32.4085 -13.4072 9.20267 -32.9928 -11.8019 10.7358 -34.8946 -10.2416 4.93291 -35.125 -9.60879 0 -34.8946 -10.2416 -4.93291 -34.2984 -11.8798 -9.0356 -34.2272 -12.0753 -9.52965 -34.0637 -12.5245 -9.45574 -33.5538 -13.9256 -8.10538 -33.0891 -15.2022 -5.38181 -32.8295 -15.9154 -2.30276 -32.7974 -16.0037 0 -32.8295 -15.9154 2.30276 -33.0891 -15.2022 5.38181 -33.5538 -13.9256 8.10538 -34.0637 -12.5245 9.45574 -34.2272 -12.0753 9.52965 -34.2984 -11.8798 9.0356 -37.3412 -12.1916 3.4624 -37.517 -11.6753 3.51654 -37.7416 -11.0558 -0.080431 -37.5309 -11.6705 0 -36.6875 -13.9879 3.07121 -36.8392 -13.5711 0 -35.6682 -16.7883 0 -35.4343 -17.3658 -0.080428 -35.4666 -17.2792 1.68651 -35.679 -16.7587 1.88529 -37.3412 -12.1916 -3.4624 -37.517 -11.6753 -3.51655 -36.6875 -13.9879 -3.07121 -35.679 -16.7587 -1.88529 -35.4664 -17.2793 -1.68654 -37.2689 -11.5506 3.51567 -37.4935 -10.9314 -0.080431 -35.3353 -10.578 3.50892 -35.5597 -9.96139 -0.080428 -37.2689 -11.5505 -3.51568 -35.3353 -10.578 -3.50892 -37.0936 -12.0623 -3.4624 -35.1633 -11.054 -3.4624 -36.4398 -13.8585 -3.07121 -34.5096 -12.8502 -3.07121 -35.4313 -16.6294 -1.88529 -33.5011 -15.6211 -1.88529 -35.2229 -17.145 -1.68592 -33.3252 -16.0979 -1.68112 -35.1909 -17.2314 -0.080428 -33.294 -16.1835 -0.080428 -35.2231 -17.1449 1.6859 -33.3252 -16.0979 1.68111 -35.4313 -16.6294 1.88529 -33.5011 -15.6211 1.88529 -36.4398 -13.8585 3.07121 -34.5096 -12.8502 3.07121 -37.0936 -12.0623 3.4624 -35.1633 -11.054 3.4624 -18.31 -49.3874 5.82322 -19.0787 -47.2753 11.2496 -20.3017 -43.9154 15.9093 -21.8954 -39.5367 19.4849 -23.7513 -34.4376 21.7326 -25.743 -28.9655 22.4992 -27.7346 -23.4935 21.7326 -29.5906 -18.3944 19.4849 -31.1843 -14.0156 15.9093 -22.6152 -48.5625 5.22096 -23.3044 -46.6688 10.0861 -24.4008 -43.6564 14.2639 -25.8297 -39.7305 17.4697 -27.4937 -35.1588 19.4849 -29.2794 -30.2527 20.1722 -31.065 -25.3466 19.4849 -32.729 -20.7748 17.4697 -34.1579 -16.849 14.2639 -26.8748 -46.3078 4.26289 -27.4376 -44.7617 8.23528 -28.3328 -42.302 11.6464 -29.4995 -39.0966 14.2639 -30.8582 -35.3638 15.9093 -32.3162 -31.358 16.4706 -33.7742 -27.3521 15.9093 -35.1328 -23.6193 14.2639 -36.2995 -20.4139 11.6464 -30.7988 -42.7773 3.01432 -31.1967 -41.6839 5.82322 -31.8297 -39.9447 8.23528 -32.6547 -37.6781 10.0861 -33.6154 -35.0386 11.2496 -34.6464 -32.2061 11.6464 -35.6773 -29.3736 11.2496 -36.638 -26.7341 10.0861 -37.463 -24.4675 8.23528 -34.1195 -38.2113 1.56033 -34.3255 -37.6453 3.01432 -34.6532 -36.7451 4.26289 -35.0802 -35.5718 5.22096 -35.5775 -34.2055 5.82322 -36.1112 -32.7392 6.02864 -36.6448 -31.273 5.82322 -37.1421 -29.9067 5.22096 -37.5692 -28.7334 4.26289 -37.8969 -27.8331 3.01432 -38.1028 -27.2672 1.56033 -31.604 -12.8625 14.3101 -38.354 -23.6497 2.4942 -34.5144 -15.8696 12.9056 -36.659 -19.426 10.2764 -38.0783 -22.7121 5.93795 -29.7108 -14.1212 12.9056 -27.6594 -19.7572 2.4942 -28.8186 -16.5723 10.2764 -27.9285 -19.0179 5.93795 -30.4023 -12.2213 14.4563 -31.1367 -13.1731 13.9634 -37.6958 -23.4101 2.4942 -33.4618 -15.4864 12.9056 -35.9038 -19.1511 10.2764 -37.4061 -22.4674 5.93795 -38.2934 -24.5231 2.26873 -34.3925 -16.2046 13.3702 -31.4467 -13.2946 14.9094 -36.5139 -19.8249 10.8296 -29.4793 -12.1577 15.0574 -37.9886 -23.3956 5.88247 -30.29 -9.48098 11.4689 -31.0737 -7.32768 5.93672 -29.7153 -11.3786 14.0129 -31.2132 -9.99323 11.3733 -31.9904 -7.85789 5.88723 -30.5442 -11.8313 13.9167 -28.5406 -20.0779 2.4942 -30.5919 -14.4419 12.9056 -29.6998 -16.893 10.2764 -28.8096 -19.3386 5.93795 -31.0206 -10.5224 11.285 -30.3423 -12.3859 13.6718 -31.7865 -8.4181 5.80883 -30.2186 -12.726 14.0444 -28.236 -18.1732 5.85284 -27.9841 -18.8652 2.75494 -29.0839 -15.8435 10.3979 -30.04 -13.2167 10.8358 -29.8527 -13.7313 12.3979 -30.3057 -12.4866 4.57892 -28.9787 -16.1325 2.44005 -32.1577 -14.6045 12.8849 -33.1557 -17.0496 10.203 -33.6844 -19.3192 5.77783 -33.7619 -19.9753 2.2652 -18.31 -49.3874 -5.82322 -19.0787 -47.2753 -11.2496 -20.3017 -43.9154 -15.9093 -21.8954 -39.5367 -19.4849 -23.7513 -34.4376 -21.7326 -25.743 -28.9655 -22.4992 -27.7346 -23.4935 -21.7326 -29.5906 -18.3944 -19.4849 -31.1843 -14.0156 -15.9093 -22.6152 -48.5625 -5.22096 -23.3044 -46.6688 -10.0861 -24.4008 -43.6564 -14.2639 -25.8297 -39.7305 -17.4697 -27.4937 -35.1588 -19.4849 -29.2794 -30.2527 -20.1722 -31.065 -25.3466 -19.4849 -32.729 -20.7748 -17.4697 -34.1579 -16.849 -14.2639 -26.8748 -46.3078 -4.26289 -27.4376 -44.7617 -8.23528 -28.3328 -42.302 -11.6464 -29.4995 -39.0966 -14.2639 -30.8582 -35.3638 -15.9093 -32.3162 -31.358 -16.4706 -33.7742 -27.3521 -15.9093 -35.1328 -23.6193 -14.2639 -36.2995 -20.4139 -11.6464 -30.7988 -42.7773 -3.01432 -31.1967 -41.6839 -5.82322 -31.8297 -39.9447 -8.23528 -32.6547 -37.6781 -10.0861 -33.6154 -35.0386 -11.2496 -34.6464 -32.2061 -11.6464 -35.6773 -29.3736 -11.2496 -36.638 -26.7341 -10.0861 -37.463 -24.4675 -8.23528 -34.1195 -38.2113 -1.56033 -34.3255 -37.6453 -3.01432 -34.6532 -36.7451 -4.26289 -35.0802 -35.5718 -5.22096 -35.5775 -34.2055 -5.82322 -36.1112 -32.7392 -6.02864 -36.6448 -31.273 -5.82322 -37.1421 -29.9067 -5.22096 -37.5692 -28.7334 -4.26289 -37.8969 -27.8331 -3.01432 -38.1028 -27.2672 -1.56033 -31.604 -12.8625 -14.3101 -38.354 -23.6497 -2.4942 -34.5144 -15.8696 -12.9056 -36.659 -19.426 -10.2764 -38.0783 -22.7121 -5.93795 -29.7108 -14.1212 -12.9056 -27.6594 -19.7572 -2.4942 -28.8186 -16.5723 -10.2764 -27.9285 -19.0179 -5.93795 -30.4023 -12.2213 -14.4563 -31.1367 -13.1731 -13.9634 -37.6958 -23.4101 -2.4942 -33.4618 -15.4864 -12.9056 -35.9038 -19.1511 -10.2764 -37.4061 -22.4674 -5.93795 -38.2934 -24.5231 -2.26873 -34.3925 -16.2046 -13.3702 -31.4467 -13.2946 -14.9094 -36.5139 -19.8249 -10.8296 -29.4793 -12.1577 -15.0574 -37.9886 -23.3956 -5.88247 -30.29 -9.48098 -11.4689 -31.0737 -7.32768 -5.93672 -29.7153 -11.3786 -14.0129 -31.2132 -9.99323 -11.3733 -31.9904 -7.85789 -5.88723 -30.5442 -11.8313 -13.9167 -28.5406 -20.0779 -2.4942 -30.5919 -14.4419 -12.9056 -29.6998 -16.893 -10.2764 -28.8096 -19.3386 -5.93795 -31.0206 -10.5224 -11.285 -30.3423 -12.3859 -13.6718 -31.7865 -8.4181 -5.80883 -30.2186 -12.726 -14.0444 -28.236 -18.1732 -5.85284 -27.9841 -18.8652 -2.75494 -29.0839 -15.8435 -10.3979 -30.04 -13.2167 -10.8358 -29.8527 -13.7313 -12.3979 -30.3057 -12.4866 -4.57892 -28.9787 -16.1325 -2.44005 -32.1577 -14.6045 -12.8849 -33.1557 -17.0496 -10.203 -33.6844 -19.3192 -5.77783 -33.7619 -19.9753 -2.2652 -18.0478 -50.1079 0 -27.5471 -20.0658 0 -28.4283 -20.3865 0 -27.9309 -19.0114 0 -29.2586 -15.3636 0 -30.5244 -11.8858 0 -31.3411 -6.59322 0 -32.2555 -7.12956 0 -32.0119 -7.79891 0 -22.3801 -49.2084 0 -26.6829 -46.8352 0 -30.663 -43.1502 0 -34.0493 -38.4043 0 -38.1731 -27.0742 0 -38.413 -24.0206 0 -37.7751 -23.7884 0 -38.3476 -24.8528 0 -33.7735 -20.2416 0 -36.4569 -32.8651 -1.74677 -36.3022 -33.2899 -1.68725 -36.1581 -33.6858 -1.51274 -36.0344 -34.0257 -1.23515 -35.9395 -34.2866 -0.873384 -35.8798 -34.4506 -0.452097 -35.8594 -34.5065 0 -35.8798 -34.4506 0.452097 -35.9395 -34.2866 0.873384 -36.0344 -34.0257 1.23515 -36.1581 -33.6858 1.51274 -36.3022 -33.2899 1.68725 -36.4569 -32.8651 1.74677 -36.6115 -32.4402 1.68725 -36.7556 -32.0443 1.51274 -36.8793 -31.7044 1.23515 -36.9742 -31.4435 0.873384 -37.0339 -31.2796 0.452096 -37.0543 -31.2236 0 -37.0339 -31.2796 -0.452096 -36.9742 -31.4435 -0.873384 -36.8793 -31.7044 -1.23515 -36.7556 -32.0443 -1.51274 -36.6115 -32.4402 -1.68725 -36.5385 -32.8948 0 -27.3075 -10.1328 14.1646 -26.5263 -12.2791 16.7118 -25.007 -16.4533 19.9408 -27.9903 -8.25675 11.1334 -28.6778 -6.3677 5.95345 -28.9449 -5.63387 0 -28.6778 -6.3677 -5.95345 -27.9903 -8.25675 -11.1334 -27.3075 -10.1328 -14.1646 -26.5263 -12.2791 -16.7118 -25.007 -16.4533 -19.9408 -23.1095 -21.6667 -22.2353 -21.0717 -27.2653 -23.0197 -19.034 -32.864 -22.2353 -17.1351 -38.0811 -19.9357 -15.5045 -42.5611 -16.2774 -14.2533 -45.9987 -11.5099 -13.4668 -48.1597 -5.95794 -13.1985 -48.8968 0 -13.4668 -48.1597 5.95794 -14.2533 -45.9987 11.5099 -15.5045 -42.5611 16.2774 -17.1351 -38.0811 19.9357 -19.034 -32.864 22.2353 -21.0717 -27.2653 23.0197 -23.1095 -21.6667 22.2353 -14.5629 -46.3631 -11.6464 -13.767 -48.5498 -6.02864 -13.4955 -49.2956 0 -14.5629 -46.3631 11.6464 -13.767 -48.5498 6.02864 -15.8289 -42.8847 -16.4706 -15.8289 -42.8847 16.4706 -17.4788 -38.3515 -20.1722 -17.4788 -38.3515 20.1722 -19.4002 -33.0725 -22.4992 -19.4002 -33.0725 22.4992 -21.4622 -27.4074 -23.2929 -21.4622 -27.4074 23.2929 -23.5241 -21.7424 -22.4992 -23.5241 -21.7424 22.4992 -25.4455 -16.4634 -20.1722 -25.4455 -16.4634 20.1722 -27.0954 -11.9302 -16.4706 -27.0954 -11.9302 16.4706 -27.6852 -10.3097 -14.2232 -28.3615 -8.45174 -11.6464 -28.3615 -8.45174 11.6464 -27.6852 -10.3097 14.2232 -29.1573 -6.26511 -6.02864 -29.4288 -5.51929 0 -29.1573 -6.26511 6.02864 -27.0498 -9.71303 14.4007 -26.2527 -11.903 16.9997 -24.7094 -16.1431 20.2797 -27.7457 -7.80091 11.3112 -28.4441 -5.8821 6.04968 -28.7155 -5.13641 -0.000000 -28.4441 -5.8821 -6.04968 -27.7457 -7.80091 -11.3112 -27.0498 -9.71303 -14.4007 -26.2527 -11.903 -16.9997 -24.7094 -16.1431 -20.2797 -22.7814 -21.4403 -22.6111 -20.7093 -27.1334 -23.4087 -18.6371 -32.8267 -22.6111 -16.7062 -38.1319 -20.2726 -15.048 -42.6877 -16.5525 -13.7757 -46.1834 -11.7044 -12.9758 -48.3809 -6.05863 -12.703 -49.1304 -0.000000 -12.9758 -48.3809 6.05863 -13.7757 -46.1834 11.7044 -15.048 -42.6877 16.5525 -16.7062 -38.1319 20.2726 -18.6371 -32.8267 22.6111 -20.7093 -27.1334 23.4087 -22.7814 -21.4403 22.6111 -26.2144 -9.18894 14.5601 -25.4066 -11.4083 17.1941 -23.8471 -15.693 20.5085 -26.9192 -7.25247 11.4313 -27.6249 -5.31357 6.11463 -27.8993 -4.55988 0.000000 -27.6249 -5.31357 -6.11463 -26.9192 -7.25247 -11.4313 -26.2144 -9.18894 -14.5601 -25.4066 -11.4083 -17.1941 -23.8471 -15.693 -20.5085 -21.8986 -21.0467 -22.8648 -19.8032 -26.8036 -23.6713 -17.7078 -32.5607 -22.8648 -15.7552 -37.9255 -20.5 -14.0784 -42.5323 -16.7382 -12.7918 -46.0673 -11.8357 -11.983 -48.2895 -6.12659 -11.7071 -49.0474 0.000000 -11.983 -48.2895 6.1266 -12.7918 -46.0673 11.8357 -14.0784 -42.5323 16.7382 -15.7552 -37.9255 20.5 -17.7078 -32.5607 22.8648 -19.8032 -26.8036 23.6713 -21.8985 -21.0467 22.8648 -25.2533 -9.01027 14.4361 -24.4539 -11.2067 17.0429 -22.907 -15.4568 20.3306 -25.9512 -7.09274 11.3379 -26.6513 -5.16946 6.06411 -26.9233 -4.42199 0.000002 -26.6513 -5.16946 -6.06411 -25.9512 -7.09274 -11.3379 -25.2533 -9.01027 -14.4361 -24.4539 -11.2067 -17.0429 -22.907 -15.4568 -20.3306 -20.9744 -20.7665 -22.6675 -18.8971 -26.4738 -23.4671 -16.8198 -32.1813 -22.6675 -14.884 -37.4998 -20.3231 -13.2217 -42.0668 -16.5937 -11.9462 -45.5713 -11.7335 -11.1444 -47.7743 -6.07373 -10.8709 -48.5257 0.000002 -11.1444 -47.7743 6.07373 -11.9462 -45.5713 11.7336 -13.2217 -42.0668 16.5938 -14.884 -37.4998 20.3231 -16.8198 -32.1813 22.6675 -18.8971 -26.4738 23.4671 -20.9744 -20.7665 22.6675 -24.794 -9.14461 14.2177 -24.0092 -11.3007 16.7766 -22.4845 -15.4898 20.0171 -25.4797 -7.26045 11.1734 -26.1697 -5.3647 5.9751 -26.4378 -4.62821 0.000002 -26.1697 -5.3647 -5.9751 -25.4797 -7.26045 -11.1734 -24.794 -9.14461 -14.2177 -24.0092 -11.3007 -16.7766 -22.4845 -15.4898 -20.0171 -20.5801 -20.722 -22.3199 -18.5347 -26.3419 -23.1072 -16.4892 -31.9618 -22.3199 -14.5831 -37.1988 -20.0115 -12.9463 -41.6958 -16.3393 -11.6903 -45.1465 -11.5536 -10.9008 -47.3157 -5.98059 -10.6315 -48.0556 0.000002 -10.9008 -47.3157 5.9806 -11.6903 -45.1465 11.5536 -12.9463 -41.6958 16.3393 -14.5831 -37.1988 20.0115 -16.4892 -31.9618 22.3199 -18.5347 -26.3419 23.1073 -20.5801 -20.722 22.3199 -24.5387 -8.77462 14.4184 -23.7404 -10.9678 17.0213 -22.1953 -15.2129 20.3052 -25.2356 -6.8598 11.3246 -25.9348 -4.93875 6.0569 -26.2066 -4.19217 0.000003 -25.9348 -4.93875 -6.05689 -25.2356 -6.8598 -11.3246 -24.5387 -8.77462 -14.4184 -23.7404 -10.9678 -17.0213 -22.1953 -15.2129 -20.3051 -20.2651 -20.5163 -22.6393 -18.1903 -26.2166 -23.4379 -16.1156 -31.9169 -22.6393 -14.1822 -37.2288 -20.2978 -12.522 -41.7902 -16.5731 -11.2481 -45.2903 -11.719 -10.4472 -47.4906 -6.06618 -10.1741 -48.241 0.000003 -10.4472 -47.4906 6.06618 -11.2481 -45.2903 11.719 -12.522 -41.7902 16.5731 -14.1822 -37.2288 20.2978 -16.1156 -31.9169 22.6393 -18.1903 -26.2166 23.4379 -20.2651 -20.5163 22.6393 -23.3031 -8.50421 14.2886 -22.5136 -10.6734 16.863 -20.9817 -14.8822 20.1187 -23.9929 -6.60922 11.2268 -24.6861 -4.70455 6.00397 -24.9555 -3.96449 0.000004 -24.6861 -4.70455 -6.00396 -23.9929 -6.60922 -11.2267 -23.3031 -8.50421 -14.2885 -22.5136 -10.6734 -16.863 -20.9817 -14.8822 -20.1187 -19.0682 -20.1396 -22.4326 -17.0124 -25.7879 -23.224 -14.9566 -31.4362 -22.4326 -13.0409 -36.6995 -20.1125 -11.3958 -41.2193 -16.4218 -10.1335 -44.6875 -11.612 -9.34 -46.8676 -6.0108 -9.06934 -47.6112 0.000004 -9.34 -46.8676 6.01081 -10.1335 -44.6875 11.612 -11.3958 -41.2193 16.4218 -13.0409 -36.6995 20.1125 -14.9566 -31.4362 22.4326 -17.0124 -25.7879 23.224 -19.0682 -20.1396 22.4326 -21.4425 -8.68268 13.6687 -20.6946 -10.7373 16.1071 -19.2257 -14.7731 19.2291 -22.0977 -6.88237 10.7599 -22.7625 -5.05583 5.75137 -23.0205 -4.34691 0.000007 -22.7625 -5.05583 -5.75135 -22.0977 -6.88237 -10.7599 -21.4425 -8.68268 -13.6687 -20.6946 -10.7373 -16.1071 -19.2257 -14.7731 -19.2291 -17.3922 -19.8106 -21.4462 -15.4267 -25.2107 -22.2028 -13.4613 -30.6107 -21.4462 -11.6298 -35.6426 -19.2281 -10.0571 -39.9636 -15.6997 -8.85032 -43.2793 -11.1014 -8.09169 -45.3636 -5.74649 -7.83294 -46.0745 0.000007 -8.09169 -45.3636 5.7465 -8.85032 -43.2793 11.1014 -10.0571 -39.9636 15.6997 -11.6298 -35.6426 19.2282 -13.4613 -30.6107 21.4462 -15.4267 -25.2107 22.2028 -17.3922 -19.8106 21.4462 -19.3772 -10.5226 11.7916 -18.7558 -12.2301 13.818 -17.4775 -15.742 16.5347 -19.9281 -9.00902 9.34606 -20.5068 -7.41909 4.98633 -20.7305 -6.80447 0.00001 -20.5068 -7.41909 -4.98631 -19.9281 -9.00902 -9.34604 -19.3772 -10.5226 -11.7915 -18.7558 -12.2301 -13.818 -17.4775 -15.742 -16.5347 -15.8865 -20.1135 -18.4587 -14.1944 -24.7622 -19.11 -12.5028 -29.41 -18.4588 -10.9264 -33.741 -16.5497 -9.57279 -37.4601 -13.5128 -8.5341 -40.3139 -9.55498 -7.88115 -42.1078 -4.94602 -7.65843 -42.7197 0.00001 -7.88114 -42.1078 4.94604 -8.53409 -40.3139 9.555 -9.57278 -37.4601 13.5128 -10.9264 -33.741 16.5497 -12.5028 -29.4099 18.4588 -14.1944 -24.7622 19.11 -15.8864 -20.1135 18.4587 -18.3016 -12.2092 10.2863 -17.7814 -13.6384 11.9824 -16.6561 -16.7302 14.3741 -18.7688 -10.9256 8.2123 -19.2784 -9.52541 4.37286 -19.4746 -8.98641 0.000011 -19.2784 -9.52541 -4.37284 -18.7688 -10.9256 -8.21228 -18.3016 -12.2092 -10.2863 -17.7814 -13.6384 -11.9824 -16.6561 -16.7302 -14.3741 -15.2594 -20.5676 -16.063 -13.7867 -24.6138 -16.6299 -12.3146 -28.6584 -16.0633 -10.9428 -32.4273 -14.4019 -9.76484 -35.6638 -11.7591 -8.86094 -38.1472 -8.31495 -8.29273 -39.7083 -4.30413 -8.09891 -40.2408 0.000012 -8.29272 -39.7083 4.30415 -8.86093 -38.1472 8.31498 -9.76482 -35.6638 11.7591 -10.9428 -32.4273 14.402 -12.3146 -28.6584 16.0633 -13.7867 -24.6138 16.6299 -15.2594 -20.5676 16.0631 -18.3733 -13.1399 9.63104 -17.8972 -14.4479 11.1834 -16.8384 -17.3569 13.4337 -18.8041 -11.9564 7.71878 -19.2836 -10.6388 4.10582 -19.4678 -10.1327 0.000009 -19.2837 -10.6388 -4.1058 -18.8041 -11.9564 -7.71876 -18.3733 -13.1399 -9.63102 -17.8973 -14.4479 -11.1834 -16.8385 -17.3569 -13.4336 -15.5264 -20.9618 -15.0202 -14.1492 -24.7457 -15.5504 -12.7726 -28.5277 -15.0205 -11.4899 -32.052 -13.467 -10.3884 -35.0784 -10.9958 -9.54314 -37.4006 -7.77518 -9.01181 -38.8604 -4.02472 -8.83058 -39.3583 0.000011 -9.0118 -38.8604 4.02474 -9.54312 -37.4006 7.7752 -10.3883 -35.0784 10.9958 -11.4898 -32.052 13.467 -12.7726 -28.5277 15.0205 -14.1491 -24.7457 15.5504 -15.5263 -20.9618 15.0203 -19.7795 -14.9149 8.71605 -19.365 -16.0537 10.0676 -18.3992 -18.7074 12.1204 -20.1594 -13.8712 7.02962 -20.597 -12.6689 3.73291 -20.7645 -12.2088 0.000001 -20.597 -12.6689 -3.73291 -20.1594 -13.8712 -7.02962 -19.7795 -14.9149 -8.71606 -19.3651 -16.0537 -10.0676 -18.3992 -18.7074 -12.1203 -17.2053 -21.9876 -13.5641 -15.9614 -25.4053 -14.0429 -14.7183 -28.8207 -13.5644 -13.5599 -32.0033 -12.1615 -12.5651 -34.7363 -9.92982 -11.8019 -36.8334 -7.02145 -11.322 -38.1517 -3.63456 -11.1584 -38.6013 0.000003 -11.322 -38.1516 3.63457 -11.8018 -36.8334 7.02145 -12.5651 -34.7363 9.92982 -13.5598 -32.0033 12.1615 -14.7182 -28.8207 13.5644 -15.9613 -25.4053 14.0429 -17.2052 -21.9876 13.5641 -20.8498 -15.0192 8.92266 -20.4214 -16.1962 10.3196 -19.4345 -18.9075 12.4169 -21.2412 -13.9439 7.18523 -21.6882 -12.7156 3.81711 -21.8595 -12.2451 -0.000004 -21.6883 -12.7156 -3.81712 -21.2412 -13.9439 -7.18524 -20.8498 -15.0192 -8.92267 -20.4214 -16.1962 -10.3196 -19.4346 -18.9075 -12.4169 -18.214 -22.2611 -13.8929 -16.9399 -25.7615 -14.3833 -15.6667 -29.2596 -13.8932 -14.4802 -32.5194 -12.4563 -13.4614 -35.3186 -10.1705 -12.6796 -37.4666 -7.19165 -12.1882 -38.8168 -3.72267 -12.0205 -39.2773 -0.000002 -12.1882 -38.8168 3.72267 -12.6796 -37.4666 7.19164 -13.4614 -35.3186 10.1705 -14.4802 -32.5194 12.4563 -15.6667 -29.2596 13.8932 -16.9399 -25.7615 14.3833 -18.2139 -22.2611 13.8929 -20.9041 -11.4576 3.94218 -20.4718 -12.6451 7.27939 -19.9923 -13.9626 9.47182 -19.4148 -15.5493 11.2728 -18.4457 -18.212 13.2813 -17.1872 -21.6697 14.7675 -15.8432 -25.3623 15.303 -14.4961 -29.0634 14.769 -13.2374 -32.5216 13.2357 -12.1568 -35.4905 10.7965 -11.3259 -37.7732 7.654 -10.7908 -39.2436 3.95673 -10.6173 -39.7203 -0.025641 -10.8024 -39.2117 -3.96121 -11.3223 -37.7831 -7.63933 -12.1494 -35.5108 -10.7949 -13.2383 -32.519 -13.2346 -14.4979 -29.0583 -14.7602 -15.8459 -25.3549 -15.2942 -17.1857 -21.6737 -14.7708 -18.4354 -18.2401 -13.2849 -19.3971 -15.5979 -11.2852 -19.9933 -13.96 -9.50144 -20.4648 -12.6643 -7.2571 -20.8936 -11.4864 -3.90658 -21.0754 -10.9869 0.027026 -22.9903 -11.6839 0.027026 -22.8085 -12.1834 -3.90658 -17.7581 -26.0592 15.303 -19.1021 -22.3666 14.7675 -13.2373 -38.4801 -7.63933 -12.7173 -39.9086 -3.96121 -13.2409 -38.4702 7.654 -14.0717 -36.1875 10.7965 -20.3504 -18.9371 -13.2849 -19.1006 -22.3707 -14.7708 -20.3606 -18.9089 13.2813 -21.3297 -16.2463 11.2728 -14.0643 -36.2078 -10.7949 -22.3868 -13.3421 7.27939 -22.819 -12.1546 3.94218 -21.9082 -14.657 -9.50144 -21.312 -16.2949 -11.2852 -22.3798 -13.3613 -7.2571 -15.1523 -33.2186 13.2357 -16.411 -29.7604 14.769 -17.7608 -26.0518 -15.2942 -16.4129 -29.7553 -14.7602 -12.7057 -39.9406 3.95673 -21.9072 -14.6596 9.47182 -15.1533 -33.216 -13.2346 -12.5322 -40.4173 -0.025641 -21.5594 -18.3316 -7.89785 -22.3073 -16.2768 -4.24114 -22.5432 -15.6285 1.50936 -21.9674 -17.2105 6.36652 -20.978 -19.9289 9.33162 -19.1426 -24.9717 11.4278 -17.1298 -30.5019 10.6428 -15.5145 -34.9398 7.01224 -14.7261 -37.1059 1.49487 -14.9985 -36.3576 -4.40715 -16.2384 -32.9509 -9.13015 -18.1217 -27.7766 -11.4196 -20.1271 -22.2668 -10.6601 -17.4364 -30.5537 -5.65913 -16.6677 -32.6659 -2.73086 -16.9876 -31.7868 4.34916 -17.9891 -29.0353 6.60013 -20.9884 -20.7947 3.94881 -21.3454 -19.8138 0.93737 -21.1991 -20.2158 -2.62794 -19.237 -25.6066 7.08683 -20.375 -22.4801 5.78717 -16.4988 -33.1298 0.928389 -18.6041 -27.3456 -7.07858 -20.7354 -21.4897 -4.8951 -19.8474 -23.9296 -6.6077 -19.0701 -26.0652 0.002965 -31.8631 -13.5079 14.0306 -38.9087 -22.8008 2.43989 -34.8117 -16.1543 12.6529 -37.0572 -19.2137 10.0738 -38.5939 -22.0099 5.81801 -30.1198 -14.4466 12.6529 -28.4629 -18.9988 2.43989 -29.3992 -16.4264 10.0738 -28.6802 -18.4017 5.81801 -30.6783 -12.912 14.174 -31.4328 -13.7396 13.6906 -38.2658 -22.5668 2.43989 -33.7835 -15.7801 12.6529 -36.3196 -18.9452 10.0738 -37.9374 -21.771 5.81801 -29.3235 -19.312 2.43989 -30.9804 -14.7598 12.6529 -30.2598 -16.7396 10.0738 -29.5409 -18.7149 5.81801 -30.5299 -13.3197 13.7699 -29.5526 -16.005 2.34735 -29.7388 -15.4933 5.37563 -30.3548 -13.8009 8.51171 -35.3295 -13.7814 10.3042 -37.6569 -16.5918 8.1095 -30.9722 -12.1046 10.5944 -31.3236 -11.1391 11.4963 -31.4507 -10.7898 11.8227 -32.5681 -11.3376 11.7068 -39.1871 -22.0359 2.43989 -38.8723 -21.245 5.81801 -37.3356 -18.4488 10.0738 -35.0901 -15.3894 12.6529 -32.1415 -12.743 14.0306 -30.9567 -12.1471 14.174 -30.8083 -12.5548 13.7699 -30.3982 -13.6817 12.6529 -29.6776 -15.6615 10.0738 -28.9586 -17.6368 5.81801 -28.7413 -18.2339 2.43989 -32.3077 -15.474 12.6529 -33.4553 -21.8718 2.43989 -33.4346 -21.0798 5.81801 -33.1002 -18.3632 10.0738 -38.6078 -12.23 7.12674 -40.1086 -7.27288 6.38726 -38.9995 -19.1175 4.30809 -40.4722 -14.3091 3.83942 -41.5879 -9.21705 2.9614 -35.3982 -11.7744 9.95378 -37.4255 -10.2806 7.9831 -32.4214 -11.8209 12.5059 -31.248 -11.3468 12.7875 -31.1306 -11.6692 12.3477 -40.811 -8.02459 5.71511 -41.2912 -4.07134 3.27877 -41.7989 -5.05268 2.97755 -42.1911 -6.57271 1.95967 -30.8 -12.5778 11.2119 -29.3092 -16.6737 2.37511 -29.5047 -16.1364 5.50835 -30.1516 -14.3591 8.98033 -31.6429 -13.799 13.1096 -31.1415 -13.4054 13.3999 -31.2968 -13.0982 13.4908 -31.9486 -13.507 13.2853 -38.4029 -22.0228 2.34885 -38.5788 -22.0843 2.36512 -36.4374 -18.4987 9.73593 -33.8969 -15.4176 12.2276 -34.6447 -15.7551 12.1616 -36.7916 -18.6421 9.71428 -38.0623 -21.2475 5.6177 -38.274 -21.3209 5.62813 -29.2 -18.6717 2.41468 -29.6735 -18.8353 2.50635 -30.0479 -16.1823 9.70267 -30.6965 -14.4078 12.3806 -30.9659 -14.5535 12.1325 -30.3909 -16.2614 9.53406 -29.4753 -17.8323 5.67988 -29.9103 -17.9699 5.73712 -32.5052 -15.2826 12.0854 -37.922 -21.6885 2.40367 -37.9955 -18.8919 4.14823 -37.7423 -20.9606 5.62625 -36.7707 -18.4306 9.7123 -37.1502 -16.6445 7.80245 -34.6978 -15.5355 12.1746 -34.8908 -13.9542 9.95446 -32.0848 -13.1318 13.1425 -32.3548 -12.4633 12.1694 -31.3875 -12.7273 13.3917 -31.6254 -12.1303 12.4919 -31.2453 -12.8767 13.4893 -31.5204 -12.174 12.3091 -30.8616 -13.9478 12.4927 -30.1769 -15.8769 9.89028 -29.552 -17.6161 5.87996 -29.2603 -18.4264 2.5163 -33.6495 -21.3369 2.34382 -33.6156 -20.5672 5.61126 -33.2569 -17.9287 9.73011 -39.5553 -14.0354 3.6229 -38.3069 -12.2143 6.72532 -40.8019 -9.05754 2.80834 -37.3425 -10.284 7.8698 -37.1764 -10.2908 7.64321 -37.0934 -10.2942 7.52992 -40.0165 -7.28835 6.29475 -39.8323 -7.31929 6.10974 -39.7402 -7.33476 6.01723 -40.3016 -8.00008 5.38928 -35.3158 -11.791 9.84028 -35.1508 -11.8241 9.61327 -35.0684 -11.8407 9.49977 -32.5082 -11.4416 11.6322 -32.3884 -11.6497 11.483 -32.3285 -11.7538 11.4084 -31.5477 -10.9322 11.7979 -31.7416 -11.217 11.7484 -31.774 -11.5368 11.5738 -31.455 -11.187 11.4963 -31.6532 -11.46 11.3466 -31.7845 -11.5078 11.3466 -31.3255 -12.769 11.2119 -31.1035 -12.1525 10.5944 -31.3663 -12.2481 10.5944 -31.4977 -12.2959 10.5944 -41.1742 -4.11559 3.21812 -40.9403 -4.20407 3.09682 -40.8233 -4.24832 3.03618 -41.2813 -5.15996 2.75771 -41.4687 -6.4954 1.80478 -29.8347 -16.8649 2.37511 -29.6839 -16.0528 2.34735 -29.9467 -16.1484 2.34735 -30.0781 -16.1963 2.34735 -30.0303 -16.3276 5.50835 -29.8702 -15.5412 5.37563 -30.1329 -15.6368 5.37563 -30.2643 -15.6846 5.37563 -30.6772 -14.5504 8.98033 -30.4861 -13.8488 8.51171 -30.7489 -13.9444 8.51171 -30.8803 -13.9922 8.51171 -31.8631 -13.5079 -14.0306 -38.9087 -22.8008 -2.43989 -34.8117 -16.1543 -12.6529 -37.0572 -19.2137 -10.0738 -38.5939 -22.0099 -5.81801 -30.1198 -14.4466 -12.6529 -28.4629 -18.9988 -2.43989 -29.3992 -16.4264 -10.0738 -28.6802 -18.4017 -5.81801 -30.6783 -12.912 -14.174 -31.4328 -13.7396 -13.6906 -38.2658 -22.5668 -2.43989 -33.7835 -15.7801 -12.6529 -36.3196 -18.9452 -10.0738 -37.9374 -21.771 -5.81801 -29.3235 -19.312 -2.43989 -30.9804 -14.7598 -12.6529 -30.2598 -16.7396 -10.0738 -29.5409 -18.7149 -5.81801 -30.5299 -13.3197 -13.7699 -29.5526 -16.005 -2.34735 -29.7388 -15.4933 -5.37563 -30.3548 -13.8009 -8.51171 -35.3295 -13.7814 -10.3042 -37.6569 -16.5918 -8.1095 -30.9722 -12.1046 -10.5943 -31.3236 -11.1391 -11.4963 -31.4507 -10.7898 -11.8227 -32.5681 -11.3376 -11.7068 -39.1871 -22.0359 -2.43989 -38.8723 -21.245 -5.81801 -37.3356 -18.4488 -10.0738 -35.0901 -15.3894 -12.6529 -32.1415 -12.743 -14.0306 -30.9567 -12.1471 -14.174 -30.8083 -12.5548 -13.7699 -30.3982 -13.6817 -12.6529 -29.6776 -15.6615 -10.0738 -28.9586 -17.6368 -5.81801 -28.7413 -18.2339 -2.43989 -32.3077 -15.474 -12.6529 -33.4553 -21.8718 -2.43989 -33.4346 -21.0798 -5.81801 -33.1002 -18.3632 -10.0738 -38.6078 -12.23 -7.12674 -40.1086 -7.27288 -6.38726 -38.9995 -19.1175 -4.30809 -40.4722 -14.3091 -3.83942 -41.5879 -9.21705 -2.9614 -35.3982 -11.7744 -9.95378 -37.4255 -10.2806 -7.9831 -32.4214 -11.8209 -12.5059 -31.248 -11.3468 -12.7875 -31.1306 -11.6692 -12.3477 -40.811 -8.02459 -5.71511 -41.2912 -4.07134 -3.27877 -41.7989 -5.05268 -2.97755 -42.1911 -6.57271 -1.95967 -30.8 -12.5778 -11.2119 -29.3092 -16.6737 -2.37511 -29.5047 -16.1364 -5.50835 -30.1516 -14.3591 -8.98033 -31.6429 -13.799 -13.1096 -31.1415 -13.4054 -13.3999 -31.2968 -13.0982 -13.4908 -31.9486 -13.507 -13.2853 -38.4029 -22.0228 -2.34885 -38.5788 -22.0843 -2.36512 -36.4374 -18.4987 -9.73593 -33.8969 -15.4176 -12.2276 -34.6447 -15.7551 -12.1616 -36.7916 -18.6421 -9.71428 -38.0623 -21.2475 -5.6177 -38.274 -21.3209 -5.62813 -29.2 -18.6717 -2.41468 -29.6735 -18.8353 -2.50635 -30.0479 -16.1823 -9.70267 -30.6965 -14.4078 -12.3806 -30.9659 -14.5535 -12.1325 -30.3909 -16.2614 -9.53406 -29.4753 -17.8323 -5.67988 -29.9103 -17.9699 -5.73712 -32.5052 -15.2826 -12.0854 -37.922 -21.6885 -2.40367 -37.9955 -18.8919 -4.14823 -37.7423 -20.9606 -5.62625 -36.7707 -18.4306 -9.7123 -37.1502 -16.6445 -7.80245 -34.6978 -15.5355 -12.1746 -34.8908 -13.9542 -9.95446 -32.0848 -13.1318 -13.1425 -32.3548 -12.4633 -12.1694 -31.3875 -12.7273 -13.3917 -31.6254 -12.1303 -12.4919 -31.2453 -12.8767 -13.4893 -31.5204 -12.174 -12.3091 -30.8616 -13.9478 -12.4927 -30.1769 -15.8769 -9.89028 -29.552 -17.6161 -5.87996 -29.2603 -18.4264 -2.5163 -33.6495 -21.3369 -2.34382 -33.6156 -20.5672 -5.61126 -33.2569 -17.9287 -9.73011 -39.5553 -14.0354 -3.6229 -38.3069 -12.2143 -6.72532 -40.8019 -9.05754 -2.80834 -37.3425 -10.284 -7.8698 -37.1764 -10.2908 -7.64321 -37.0934 -10.2942 -7.52992 -40.0165 -7.28835 -6.29475 -39.8323 -7.31929 -6.10974 -39.7402 -7.33476 -6.01723 -40.3016 -8.00008 -5.38928 -35.3158 -11.791 -9.84028 -35.1508 -11.8241 -9.61327 -35.0684 -11.8407 -9.49977 -32.5082 -11.4416 -11.6322 -32.3884 -11.6497 -11.483 -32.3285 -11.7538 -11.4084 -31.5477 -10.9322 -11.7979 -31.7416 -11.217 -11.7484 -31.774 -11.5368 -11.5738 -31.455 -11.187 -11.4963 -31.6532 -11.46 -11.3466 -31.7845 -11.5078 -11.3466 -31.3255 -12.769 -11.2119 -31.1035 -12.1525 -10.5943 -31.3663 -12.2481 -10.5943 -31.4977 -12.2959 -10.5943 -41.1742 -4.11559 -3.21812 -40.9403 -4.20407 -3.09682 -40.8233 -4.24832 -3.03618 -41.2813 -5.15996 -2.75771 -41.4687 -6.4954 -1.80478 -29.8347 -16.8649 -2.37511 -29.6839 -16.0528 -2.34735 -29.9467 -16.1484 -2.34735 -30.0781 -16.1963 -2.34735 -30.0303 -16.3276 -5.50835 -29.8702 -15.5412 -5.37563 -30.1329 -15.6368 -5.37563 -30.2643 -15.6846 -5.37563 -30.6772 -14.5504 -8.98033 -30.4861 -13.8488 -8.51171 -30.7489 -13.9444 -8.51171 -30.8803 -13.9922 -8.51171 -28.3722 -19.248 0 -29.2328 -19.5613 0 -28.6506 -18.4831 0 -29.4748 -16.2185 0 -29.2276 -16.8979 0 -29.1338 -18.8939 0 -29.611 -19.0851 0 -29.1856 -18.6361 0 -29.7531 -17.0892 0 -29.6062 -16.2663 0 -29.869 -16.362 0 -30.0004 -16.4098 0 -38.9853 -23.1109 0 -38.3622 -22.8841 0 -39.2637 -22.346 0 -33.4436 -22.1949 0 -39.3089 -19.7951 0 -38.4971 -22.3285 0 -38.6526 -22.3851 0 -38.1873 -19.4894 0 -37.9641 -21.9707 0 -33.6399 -21.6473 0 -40.9589 -14.7996 0 -39.8884 -14.4478 0 -42.1476 -9.69492 0 -41.1941 -9.44314 0 -42.52 -6.10773 0 -42.2528 -4.19503 0 -41.7902 -3.43875 0 -41.7184 -6.07298 0 -41.6939 -4.37856 0 -41.6841 -3.47806 0 -41.4719 -3.5567 0 -41.3658 -3.59602 0 -41.7415 7.6825 0 -41.6901 7.6783 2.82599 -41.7536 7.67727 5.07011 -39.8952 7.67941 5.06932 -40.0036 7.67417 4.35142 -40.433 7.69764 2.74187 -40.5889 7.70137 0 -40.433 7.69764 -2.74187 -40.0036 7.67417 -4.35142 -39.8952 7.67941 -5.06932 -41.7536 7.67727 -5.07011 -41.6901 7.6783 -2.82599</float_array>
+ <technique_common>
+ <accessor source="#Headphones-positions-array" count="3014" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Headphones-normals" name="normal">
+ <float_array id="Headphones-normals-array" count="11976">0.791994 0.475487 -0.382959 0.854851 0.350103 -0.382959 0.353879 0.14493 -0.923994 0.327858 0.196835 -0.923994 0.898001 0.216648 -0.382959 0.371741 0.089684 -0.923994 -0.898001 -0.216648 -0.38296 -0.854851 -0.350103 -0.38296 -0.353878 -0.14493 -0.923994 -0.371741 -0.089684 -0.923994 -0.791994 -0.475487 -0.382959 -0.327858 -0.196835 -0.923994 -0.710879 -0.589909 -0.382959 -0.29428 -0.244202 -0.923994 -0.613376 -0.690732 -0.38296 -0.253916 -0.285939 -0.923994 -0.2077 -0.321085 -0.923994 -0.501734 -0.775632 -0.382959 -0.156696 -0.348829 -0.923994 -0.378525 -0.842652 -0.382959 -0.102079 -0.368529 -0.923995 -0.246588 -0.890245 -0.38296 -0.049465 -0.379326 -0.92394 -0.119467 -0.916062 -0.382829 0.029864 0.92341 -0.382651 0.11925 0.91609 -0.382831 0.04939 0.379334 -0.923941 0.012381 0.382516 -0.923866 0.246589 0.890245 -0.382959 0.102079 0.368531 -0.923994 0.012381 0.382516 0.923866 0.04939 0.379334 0.923941 0.11925 0.91609 0.382831 0.029864 0.92341 0.382651 0.378524 0.842651 -0.38296 0.156696 0.348828 -0.923994 0.102079 0.368531 0.923994 0.246589 0.890245 0.382959 0.501734 0.775632 -0.38296 0.2077 0.321084 -0.923994 0.156696 0.348828 0.923994 0.378524 0.842651 0.38296 0.613376 0.690732 -0.38296 0.253916 0.285939 -0.923994 0.2077 0.321084 0.923994 0.501734 0.775632 0.38296 0.253916 0.285939 0.923994 0.613376 0.690732 0.38296 0.710879 0.589909 0.382959 0.294279 0.244202 0.923994 0.327858 0.196835 0.923994 0.791994 0.475487 0.382959 0.854851 0.350103 0.382959 0.353879 0.14493 0.923994 0.371741 0.089684 0.923994 0.898001 0.216648 0.382959 -0.030083 -0.923402 0.382654 -0.119467 -0.916062 0.382829 -0.049465 -0.379326 0.92394 -0.012456 -0.38251 0.923868 -0.371741 -0.089684 0.923994 -0.353878 -0.14493 0.923994 -0.854851 -0.350103 0.38296 -0.898001 -0.216648 0.38296 -0.791994 -0.475487 0.382959 -0.327858 -0.196835 0.923994 -0.29428 -0.244202 0.923994 -0.710879 -0.589909 0.382959 -0.253916 -0.285939 0.923994 -0.613376 -0.690732 0.38296 0.710879 0.589909 -0.382959 0.294279 0.244202 -0.923994 -0.2077 -0.321084 0.923994 -0.501734 -0.775632 0.38296 -0.378524 -0.842651 0.382959 -0.156696 -0.348828 0.923994 -0.246588 -0.890245 0.38296 -0.102079 -0.368529 0.923995 -0.030083 -0.923402 -0.382654 -0.012456 -0.38251 -0.923868 0.032305 0.999478 0 0.129063 0.991636 0 0.266939 0.963713 0 0.409762 0.912192 0 0.54314 0.839642 0 0.663996 0.747736 0 0.769545 0.638592 0 0.857354 0.514727 0 0.925398 0.378996 0 0.97211 0.234527 0 -0.97211 -0.234527 0 -0.925399 -0.378995 0 -0.857354 -0.514727 0 -0.769545 -0.638592 0 -0.663996 -0.747736 0 -0.54314 -0.839642 0 -0.409763 -0.912192 0 -0.266938 -0.963714 0 -0.129326 -0.991602 0 -0.03257 -0.999469 0 -0.791994 0.475487 -0.382959 -0.327858 0.196835 -0.923994 -0.353879 0.14493 -0.923994 -0.854851 0.350103 -0.382959 -0.371741 0.089684 -0.923994 -0.898001 0.216648 -0.382959 0.898001 -0.216648 -0.38296 0.371741 -0.089684 -0.923994 0.353878 -0.14493 -0.923994 0.854851 -0.350103 -0.38296 0.327858 -0.196835 -0.923994 0.791994 -0.475487 -0.382959 0.294279 -0.244202 -0.923994 0.710879 -0.589909 -0.382959 0.253916 -0.285938 -0.923995 0.613376 -0.690732 -0.38296 0.2077 -0.321084 -0.923994 0.501734 -0.775632 -0.38296 0.156696 -0.348828 -0.923994 0.378524 -0.842651 -0.38296 0.102079 -0.368529 -0.923995 0.246588 -0.890244 -0.382961 0.049465 -0.379326 -0.92394 0.119467 -0.916062 -0.382829 -0.029864 0.92341 -0.382651 -0.012381 0.382516 -0.923866 -0.04939 0.379334 -0.923941 -0.11925 0.916089 -0.382831 -0.102079 0.368531 -0.923994 -0.246589 0.890245 -0.382958 -0.012381 0.382516 0.923866 -0.029864 0.92341 0.382651 -0.11925 0.916089 0.382831 -0.04939 0.379334 0.923941 -0.156696 0.348828 -0.923994 -0.378524 0.842651 -0.38296 -0.246589 0.890245 0.382959 -0.102079 0.368531 0.923994 -0.2077 0.321084 -0.923994 -0.501734 0.775632 -0.38296 -0.378524 0.842651 0.38296 -0.156696 0.348827 0.923995 -0.253916 0.285939 -0.923994 -0.613377 0.690732 -0.38296 -0.501734 0.775632 0.38296 -0.2077 0.321084 0.923995 -0.613376 0.690732 0.38296 -0.253916 0.285939 0.923994 -0.710879 0.589909 0.382959 -0.294279 0.244202 0.923994 -0.791994 0.475487 0.382959 -0.327858 0.196835 0.923994 -0.854851 0.350103 0.382959 -0.353879 0.14493 0.923994 -0.898001 0.216648 0.382959 -0.371741 0.089684 0.923994 0.030083 -0.923402 0.382654 0.012456 -0.38251 0.923868 0.049465 -0.379326 0.92394 0.119467 -0.916062 0.382829 0.371741 -0.089684 0.923994 0.898001 -0.216648 0.38296 0.854851 -0.350103 0.38296 0.353878 -0.14493 0.923994 0.791994 -0.475487 0.382959 0.327858 -0.196835 0.923994 0.710879 -0.589909 0.382959 0.29428 -0.244202 0.923994 0.613376 -0.690732 0.38296 0.253916 -0.285939 0.923994 -0.294279 0.244202 -0.923994 -0.710879 0.589909 -0.382959 0.501734 -0.775632 0.38296 0.2077 -0.321085 0.923994 0.378525 -0.842651 0.382959 0.156696 -0.348829 0.923994 0.246588 -0.890244 0.382961 0.102079 -0.368529 0.923995 0.012456 -0.38251 -0.923868 0.030083 -0.923402 -0.382654 -0.129063 0.991636 0 -0.032305 0.999478 0 -0.266939 0.963713 0 -0.409762 0.912192 0 -0.54314 0.839642 0 -0.663996 0.747736 0 -0.769545 0.638592 0 -0.857354 0.514727 0 -0.925398 0.378996 0 -0.97211 0.234527 0 0.925399 -0.378995 0 0.97211 -0.234527 0 0.857354 -0.514727 0 0.769545 -0.638592 0 0.663996 -0.747736 0 0.54314 -0.839642 0 0.409763 -0.912192 0 0.266938 -0.963714 0 0.129326 -0.991602 0 0.03257 -0.999469 0 0.883161 0.291714 -0.367327 0.345159 0.300569 -0.889114 -0.393264 0.198279 -0.897791 -0.926581 0.037121 -0.374258 0.345159 0.300569 0.889114 0.883161 0.291714 0.367327 -0.926582 0.037121 0.374258 -0.393264 0.198278 0.897791 0.972918 0.231152 0 -0.998802 -0.048933 0 -0.345159 0.300569 -0.889114 -0.883161 0.291714 -0.367327 0.926581 0.037121 -0.374258 0.393264 0.198279 -0.897791 -0.345159 0.300569 0.889114 -0.883161 0.291714 0.367327 0.393264 0.198279 0.897791 0.926582 0.037121 0.374258 -0.972918 0.231152 0 0.998802 -0.048933 0 -0.227734 -0.625296 0.74642 -0.009523 -0.390135 0.920709 -0.070866 -0.364444 0.928525 -0.233388 -0.640431 0.731695 -0.242856 -0.970062 0 -0.34202 -0.939693 0 -0.338322 -0.929544 0.146579 -0.241349 -0.957044 0.160677 -0.212351 -0.783141 0.584464 0.259273 -0.642256 0.721307 0.120369 -0.481356 0.868221 -0.210322 -0.660264 0.720983 -0.336117 -0.923497 0.184875 -0.235089 -0.908055 0.346654 -0.30665 -0.842525 0.442852 -0.342023 -0.939691 0.000000 -0.437599 -0.89917 0 -0.431327 -0.889911 0.148381 -0.338327 -0.929542 0.14658 -0.287602 -0.79018 0.541203 -0.354888 -0.760917 0.543194 -0.273466 -0.659274 0.70041 -0.249676 -0.685699 0.683725 -0.408726 -0.854966 0.319338 -0.324402 -0.89129 0.316804 -0.241596 -0.651213 0.719411 0.989205 -0.146539 0 0.975296 -0.063957 0.211442 0.980671 -0.169326 0.098047 0.985413 -0.170182 0 0.932995 -0.339584 0.119178 0.939693 -0.342019 0.000000 0.956262 -0.13157 0.261252 0.926758 -0.337315 0.165341 0.871962 0.085321 0.482081 0.859323 -0.01228 0.511286 0.818477 -0.2979 0.491275 0.732153 0.264977 0.627487 0.688925 0.15459 0.708155 0.561815 0.595976 0.573739 0.449247 0.323427 0.83281 0.425114 0.740153 0.52101 0.302865 0.400265 0.864905 -0.939694 0.342017 -0.000000 -0.939693 0.342019 -0.000000 -0.939693 0.34202 -0.000001 -0.939693 0.342018 -0.000004 -0.939692 0.342023 -0.000004 -0.939692 0.342023 -0.00001 -0.939692 0.342022 -0.000000 -0.939691 0.342024 -0.000001 -0.939692 0.342022 -0.000001 -0.939691 0.342026 -0.000003 -0.939692 0.342022 -0.000000 -0.93969 0.342026 -0.000001 -0.939692 0.342023 0.000000 -0.939691 0.342025 -0.000000 -0.939692 0.342023 0 -0.939691 0.342025 0 -0.342215 -0.939622 0 -0.337795 -0.926781 0.164233 -0.322206 -0.878715 0.352197 -0.281111 -0.75735 0.589405 0.967709 -0.252069 0 0.921792 -0.212523 0.324242 0.747455 -0.059224 0.661667 0.986092 -0.166199 0 0.945447 -0.142711 0.292853 0.825623 -0.012411 0.564086 0.706372 0.097525 0.70109 0.625714 0.019086 0.779819 0.665497 0.092603 0.740633 0.621662 0.283323 0.73025 0.541873 0.532711 0.650071 0.421449 0.742152 0.521144 -0.939692 0.342021 -0.000002 -0.939692 0.342022 -0.000001 -0.939692 0.342021 -0.000000 -0.939692 0.342021 0.000000 0.920658 0.197718 0.336596 0.845881 0.349664 0.402766 0.972331 -0.014369 0.233167 0.954731 0.297469 0 0.890517 0.45495 0 0.999995 0.003239 0 -0.939693 0.342018 0.000000 -0.939694 0.342018 0 -0.939694 0.342016 0.000000 -0.939695 0.342015 0 -0.939693 0.342019 0.000000 -0.939693 0.342019 0.000000 -0.939693 0.342019 0.000000 -0.939693 0.34202 0 -0.211751 0.211768 -0.954105 0.075065 0.605301 -0.79245 -0.01183 0.417438 -0.908629 -0.169817 0.095818 -0.980806 0.340314 0.940312 0 0.241997 0.970277 0 0.240444 0.957257 -0.160763 0.336572 0.930183 -0.146559 -0.415917 0.483109 -0.770467 0.21515 0.7838 -0.582553 0.180729 0.657456 -0.731498 -0.220662 0.382544 -0.8972 0.236509 0.908048 -0.345706 0.327155 0.891186 -0.314256 0.447632 0.894218 0 0.881566 0.472061 -0.000000 0.884074 0.449195 -0.128989 0.443963 0.879055 -0.173663 0.264108 0.820266 -0.507356 0.06603 0.875026 -0.479552 -0.007252 0.79225 -0.610154 0.152132 0.7426 -0.652227 0.267633 0.902223 -0.338181 0.396445 0.854907 -0.334612 0.248438 0.677305 -0.692486 -0.977768 0.125084 -0.168297 -0.98167 0.190588 0 -0.887461 -0.460883 0 -0.889836 -0.454721 0.037678 -0.513938 -0.857827 0 -0.519694 -0.845526 0.122488 -0.908571 -0.41696 0.025338 -0.6193 -0.76227 0.18818 -0.891559 -0.043549 -0.450805 -0.912675 -0.27268 -0.304418 -0.730533 -0.257173 -0.632601 -0.714973 -0.230786 -0.659963 -0.640102 -0.483705 -0.596907 -0.545901 -0.366411 -0.753482 -0.546117 -0.617916 -0.565628 -0.546117 -0.617916 -0.565628 -0.211679 -0.090848 -0.973108 0.862212 -0.494635 -0.109206 0.649152 -0.706667 -0.281467 0.649152 -0.706667 -0.281467 0.883527 -0.444657 -0.147174 -0.00851 -0.008925 -0.999924 0.945479 -0.32451 -0.027626 0.960333 -0.228738 -0.159497 0.95161 -0.299397 -0.069278 0.932142 -0.361777 0.01514 0.927228 -0.373819 0.022535 0.940975 -0.338454 0.003941 0.944159 -0.329453 0.004899 0.955109 -0.29621 -0.005108 0.959754 -0.280841 0 0.344787 0.922718 -0.172376 0.344836 0.938663 0 0.337968 0.871069 -0.356393 0.296912 0.760997 -0.576825 -0.962089 0.272736 0 -0.93493 0.242494 -0.259042 -0.768191 0.076779 -0.6356 -0.978552 0.206001 0 -0.954189 0.187994 -0.232769 -0.850781 0.0445 -0.523633 -0.5799 0.052351 -0.813004 -0.5799 0.052351 -0.813004 -0.650353 -0.189217 -0.735689 -0.653963 -0.102946 -0.74949 -0.64177 -0.274042 -0.716263 -0.496722 -0.667782 -0.554377 -0.496722 -0.667782 -0.554377 -0.496722 -0.667782 -0.554377 -0.496722 -0.667782 -0.554377 0.830689 -0.529404 -0.172299 0.893986 -0.440715 -0.080995 0.830689 -0.529404 -0.172299 0.938317 -0.345635 0.009895 0.939471 -0.342575 0.005973 -0.943067 -0.130106 -0.306099 -0.816376 -0.221101 -0.533521 -0.868351 -0.302846 -0.392747 -0.978998 0.088926 -0.183451 -0.978406 -0.206692 0 -0.922033 -0.387111 0 -0.997057 0.076663 0 0.939184 -0.343414 0 0.939051 -0.343778 0.000515 0.939693 -0.342019 0 0.939693 -0.342019 0.000000 0.938706 -0.344716 0.001492 0.939693 -0.34202 0.000000 0.938285 -0.345842 0.003871 0.939693 -0.34202 -0.000000 -0.498052 0.803663 0.325684 -0.496916 0.804749 0.324736 -0.556659 0.697954 0.450546 -0.557123 0.697091 0.451308 -0.501424 0.800402 0.328527 -0.500307 0.801489 0.327579 -0.558056 0.695337 0.452858 -0.562944 0.715656 0.413438 -0.321475 0.940817 -0.107321 -0.42319 0.875937 0.231613 -0.350241 0.932882 -0.084036 -0.340743 0.93566 -0.091835 -0.084483 0.677319 -0.730822 -0.047204 0.677799 -0.733731 -0.157481 0.88114 -0.445862 -0.138935 0.736214 -0.662334 -0.130575 0.707088 -0.694965 0.069509 0.382022 -0.921536 0.069509 0.382022 -0.921536 -0.033817 0.508046 -0.860666 -0.033817 0.508046 -0.860666 0.366048 0.611518 -0.701466 0.318613 0.603823 -0.730673 0.408605 0.582064 -0.703024 0.408605 0.582064 -0.703024 0.571009 0.609081 -0.550426 0.491824 0.616373 -0.614975 0.709105 0.559505 -0.429096 0.824931 0.496082 -0.270908 0.248442 0.665327 -0.704 0.242608 0.666561 -0.704867 0.243883 0.670086 -0.701075 0.249079 0.66709 -0.702104 -0.477575 0.820679 0.313701 -0.477965 0.819903 0.315131 -0.55294 0.671787 0.492909 -0.478775 0.818303 0.31805 -0.479193 0.817478 0.319538 -0.379687 0.925115 0 -0.380087 0.924951 0 -0.380946 0.924597 0 -0.381404 0.924408 -0.000000 0.342009 0.939697 0 0.341995 0.939702 0 0.338784 0.93087 -0.136772 0.338793 0.930867 -0.136771 0.34204 0.939685 -0.000000 0.342031 0.939689 0 0.338813 0.930859 -0.136771 0.338824 0.930855 -0.136773 0.321314 0.882858 -0.342519 0.321322 0.882855 -0.342519 0.321334 0.88285 -0.342521 0.321338 0.882848 -0.342521 0.278806 0.766044 -0.579175 0.278814 0.766038 -0.57918 0.278815 0.766036 -0.579181 0.278809 0.766041 -0.579178 0.563169 0.599172 -0.569064 -0.032394 0.369551 -0.928646 -0.032394 0.369551 -0.928646 -0.227734 -0.625295 -0.74642 -0.233389 -0.64043 -0.731696 -0.070866 -0.364444 -0.928525 -0.009523 -0.390134 -0.920709 -0.241349 -0.957044 -0.160677 -0.338322 -0.929544 -0.146579 -0.212351 -0.783141 -0.584464 -0.210322 -0.660264 -0.720983 0.120369 -0.481356 -0.868221 0.259273 -0.642256 -0.721307 -0.235089 -0.908055 -0.346654 -0.336118 -0.923497 -0.184875 -0.30665 -0.842525 -0.442853 -0.338327 -0.929542 -0.14658 -0.431326 -0.889911 -0.148381 -0.287602 -0.79018 -0.541203 -0.249676 -0.685698 -0.683725 -0.273466 -0.659273 -0.700411 -0.354888 -0.760917 -0.543194 -0.324402 -0.89129 -0.316804 -0.408726 -0.854966 -0.319338 -0.241596 -0.651213 -0.719412 0.980671 -0.169326 -0.098047 0.975296 -0.063957 -0.211442 0.932995 -0.339584 -0.119178 0.956262 -0.13157 -0.261252 0.926758 -0.337315 -0.165341 0.859323 -0.01228 -0.511286 0.871962 0.085321 -0.48208 0.818477 -0.2979 -0.491275 0.688925 0.15459 -0.708155 0.732152 0.264978 -0.627487 0.449247 0.323428 -0.83281 0.561815 0.595976 -0.573739 0.302865 0.400265 -0.864905 0.425114 0.740153 -0.52101 -0.939693 0.342019 0.000000 -0.939693 0.342019 0.000004 -0.939693 0.34202 0.000001 -0.939693 0.34202 0.000000 -0.939692 0.342022 0.000009 -0.939692 0.342023 0.000004 -0.939691 0.342024 0.000001 -0.939692 0.342022 0.000000 -0.939691 0.342026 0.000003 -0.939692 0.342022 0.000001 -0.93969 0.342026 0.000001 -0.939692 0.342022 0.000000 -0.939691 0.342025 0.000000 -0.939692 0.342023 0 -0.337795 -0.926781 -0.164233 -0.322206 -0.878715 -0.352197 -0.281111 -0.75735 -0.589405 0.921792 -0.212523 -0.324242 0.747455 -0.059224 -0.661667 0.945447 -0.142712 -0.292853 0.625714 0.019086 -0.779819 0.706372 0.097526 -0.70109 0.825623 -0.012411 -0.564086 0.665497 0.092603 -0.740633 0.541873 0.53271 -0.650072 0.621662 0.283322 -0.73025 0.421449 0.742152 -0.521145 -0.939692 0.342022 0.000001 -0.939692 0.342023 0.000002 -0.939693 0.34202 -0.000000 -0.939692 0.342021 0.000000 0.845881 0.349664 -0.402766 0.920658 0.197719 -0.336596 0.972331 -0.014369 -0.233167 -0.939694 0.342018 -0.000000 -0.939695 0.342015 -0.000000 -0.939694 0.342018 -0.000000 -0.939694 0.342016 -0.000000 -0.939693 0.342019 -0.000000 -0.939693 0.342019 0 -0.211753 0.211768 0.954104 -0.169821 0.095817 0.980806 -0.011832 0.417438 0.908628 0.075065 0.605301 0.792449 0.336569 0.930184 0.146557 0.240443 0.957258 0.160763 -0.415921 0.48311 0.770464 -0.220662 0.382543 0.8972 0.180728 0.657456 0.731498 0.215148 0.783801 0.582552 0.327149 0.891189 0.314253 0.236507 0.908049 0.345704 0.443963 0.879055 0.173663 0.884073 0.449195 0.128989 0.264108 0.820266 0.507356 0.152132 0.742601 0.652227 -0.007253 0.79225 0.610153 0.066029 0.875025 0.479553 0.396445 0.854907 0.334613 0.267633 0.902223 0.338181 0.248438 0.677305 0.692486 -0.977768 0.125084 0.168297 -0.889836 -0.454722 -0.037677 -0.519693 -0.845527 -0.122488 -0.908571 -0.41696 -0.025338 -0.6193 -0.76227 -0.188181 -0.891559 -0.04355 0.450805 -0.912675 -0.27268 0.304418 -0.730533 -0.257173 0.632601 -0.714973 -0.230787 0.659963 -0.640103 -0.483705 0.596907 -0.545903 -0.366411 0.75348 -0.546119 -0.617915 0.565628 -0.546119 -0.617915 0.565628 -0.211684 -0.090849 0.973107 0.862214 -0.494633 0.109207 0.883528 -0.444655 0.147174 0.649155 -0.706663 0.281468 0.649155 -0.706663 0.281468 -0.008515 -0.008925 0.999924 0.945479 -0.324509 0.027626 0.95161 -0.299396 0.069278 0.960334 -0.228736 0.159497 0.932141 -0.361778 -0.01514 0.927227 -0.373821 -0.022535 0.940975 -0.338454 -0.003941 0.944159 -0.329453 -0.004899 0.955109 -0.29621 0.005108 0.344787 0.922718 0.172376 0.337968 0.871069 0.356393 0.296912 0.760997 0.576825 -0.93493 0.242494 0.259042 -0.768191 0.076779 0.6356 -0.954189 0.187994 0.232769 -0.850781 0.0445 0.523633 -0.5799 0.052351 0.813004 -0.5799 0.052351 0.813004 -0.653963 -0.102945 0.74949 -0.650352 -0.189217 0.735689 -0.641769 -0.274043 0.716263 -0.496724 -0.667781 0.554377 -0.496724 -0.667781 0.554377 -0.496724 -0.667781 0.554377 -0.496724 -0.667781 0.554377 0.830691 -0.529401 0.1723 0.830691 -0.529401 0.1723 0.893987 -0.440712 0.080995 0.939472 -0.342574 -0.005973 0.938318 -0.345633 -0.009895 -0.943067 -0.130106 0.306099 -0.868351 -0.302846 0.392747 -0.816376 -0.2211 0.533521 -0.978998 0.088926 0.18345 0.93905 -0.343779 -0.000515 0.939693 -0.34202 -0.000000 0.938706 -0.344717 -0.001492 0.939692 -0.342021 -0.000000 0.938285 -0.345843 -0.003871 0.939693 -0.34202 0.000000 -0.498054 0.803661 -0.325685 -0.557125 0.697088 -0.45131 -0.556664 0.697948 -0.450549 -0.496919 0.804746 -0.324738 -0.501426 0.800401 -0.328528 -0.562945 0.715655 -0.413438 -0.558056 0.695336 -0.452859 -0.500307 0.801489 -0.32758 -0.321476 0.940816 0.10732 -0.423197 0.875933 -0.231616 -0.350243 0.932882 0.084033 -0.340744 0.93566 0.091833 -0.084482 0.67732 0.730821 -0.15748 0.88114 0.445861 -0.047202 0.6778 0.733729 -0.138934 0.736215 0.662332 -0.130575 0.707089 0.694964 0.069511 0.382025 0.921534 0.069511 0.382025 0.921534 -0.033815 0.508049 0.860664 -0.033815 0.508049 0.860664 0.36605 0.611517 0.701466 0.40861 0.582063 0.703023 0.40861 0.582063 0.703023 0.318617 0.603819 0.730675 0.571008 0.609079 0.55043 0.82493 0.496083 0.27091 0.709104 0.559505 0.429098 0.491822 0.616372 0.614977 0.248441 0.665326 0.704001 0.242609 0.666558 0.70487 0.243884 0.670082 0.701078 0.249078 0.667089 0.702105 -0.477968 0.819901 -0.315132 -0.47758 0.820675 -0.313703 -0.552941 0.671785 -0.492911 -0.479194 0.817477 -0.31954 -0.478775 0.818302 -0.31805 0.338792 0.930867 0.13677 0.338781 0.930871 0.13677 0.338824 0.930855 0.136772 0.338813 0.930859 0.136771 0.321321 0.882856 0.342519 0.321311 0.88286 0.342518 0.321338 0.882848 0.342521 0.321334 0.88285 0.342521 0.278813 0.766038 0.57918 0.278805 0.766044 0.579176 0.278809 0.76604 0.579178 0.278815 0.766036 0.579182 0.563169 0.59917 0.569066 -0.032394 0.369551 0.928646 -0.032394 0.369551 0.928646 0.829617 -0.431975 -0.353741 0.918634 -0.395111 0 0.481089 -0.876672 0 0.411188 -0.890512 -0.194713 0.829617 -0.431975 0.353741 0.411187 -0.890512 0.194713 0.323555 -0.435495 0.840034 0.136444 -0.872014 0.470079 -0.368877 -0.416498 0.830939 -0.252103 -0.845854 0.470079 -0.856802 -0.383907 0.344248 -0.526847 -0.827357 0.194714 -0.939606 -0.342259 0 -0.594262 -0.804272 0 -0.856801 -0.383908 -0.344248 -0.526846 -0.827357 -0.194713 -0.368877 -0.416498 -0.830939 -0.252103 -0.845854 -0.47008 0.323555 -0.435495 -0.840033 0.136444 -0.872014 -0.470079 -0.829617 -0.431975 -0.353741 -0.411187 -0.890512 -0.194713 -0.481088 -0.876672 0 -0.918633 -0.395111 0 -0.411187 -0.890512 0.194713 -0.829617 -0.431975 0.353741 -0.136444 -0.872014 0.470079 -0.323555 -0.435495 0.840033 0.252103 -0.845854 0.47008 0.368877 -0.416498 0.830939 0.526846 -0.827357 0.194713 0.856801 -0.383908 0.344248 0.594262 -0.804272 0 0.939606 -0.342259 0 0.526846 -0.827357 -0.194713 0.856801 -0.383908 -0.344248 0.252103 -0.845854 -0.47008 0.368877 -0.416498 -0.830939 -0.136444 -0.872014 -0.470079 -0.323555 -0.435495 -0.840034 -0.923617 -0.016964 -0.382941 -0.999985 -0.005436 0 -0.987918 0.154974 0 -0.899513 0.227109 -0.373226 0.347845 0.280443 0.894626 0.899513 0.227108 0.373226 0.382066 -0.03813 0.923348 0.923617 -0.016965 0.382941 -0.99804 -0.062574 0 -0.921072 -0.071024 0.382859 -0.924618 0.075407 0.373358 -0.999919 -0.012692 0 0.380784 -0.061231 -0.922634 -0.382066 -0.038129 -0.923348 -0.347845 0.280444 -0.894626 0.391976 0.219925 -0.893302 -0.380784 -0.06123 -0.922634 -0.921072 -0.071023 -0.38286 -0.924618 0.075408 -0.373358 -0.391976 0.219925 -0.893302 -0.923617 -0.016965 0.382941 -0.382066 -0.03813 0.923348 -0.347845 0.280443 0.894626 -0.899513 0.227108 0.373226 -0.391976 0.219924 0.893302 -0.380784 -0.061231 0.922634 0.391976 0.219925 0.893302 0.380784 -0.06123 0.922634 0.921072 -0.071023 0.38286 0.99804 -0.062574 0 0.999919 -0.012692 0 0.924618 0.075408 0.373358 0.924618 0.075407 -0.373358 0.921072 -0.071024 -0.382859 0.347845 0.280444 -0.894626 0.382066 -0.038129 -0.923348 0.999985 -0.005435 0 0.923617 -0.016964 -0.382941 0.899513 0.227109 -0.373226 0.987919 0.154974 0 0.954244 -0.298979 -0.005498 0.982009 -0.188496 -0.011332 0.981689 -0.187837 -0.031672 0.953064 -0.302088 -0.020269 0.977003 -0.213145 -0.005778 0.955205 -0.295798 0.009286 0.925837 -0.377146 -0.024233 0.925668 -0.37811 -0.01308 0.925383 -0.379027 -0.001926 0.978977 -0.20397 0 0.985081 -0.172092 0 0.99534 -0.096424 0 0.995412 -0.095326 -0.008238 0.994952 -0.094176 -0.034658 -0.98576 0.083428 -0.146005 -0.959949 0.050781 -0.275536 -0.90861 0.068661 -0.411964 -0.977772 0.15179 -0.144647 -0.830891 0.096614 -0.547984 -0.955051 0.249322 -0.160364 -0.745638 0.235188 -0.623466 -0.920504 0.350687 -0.172311 -0.115486 -0.362168 -0.924931 -0.088474 -0.372261 -0.923901 -0.115502 -0.678935 -0.725056 -0.155519 -0.670365 -0.725551 -0.15368 -0.988121 -0.000000 -0.207393 -0.978258 -0.000000 -0.047391 -0.108799 -0.992933 -0.03768 -0.114001 -0.992766 -0.027961 -0.119192 -0.992477 -0.061398 -0.382042 -0.922103 -0.075324 -0.686363 -0.723348 -0.099502 -0.995037 -0.000000 0.926496 -0.375136 0.029629 0.933206 -0.35726 0.038615 0.933206 -0.35726 0.038615 0.926496 -0.375136 0.029629 0.973898 -0.22136 0.050229 0.973898 -0.22136 0.050229 0.973898 -0.22136 0.050229 0.973898 -0.22136 0.050229 0.99366 -0.111533 -0.014136 0.993759 -0.111547 0 0.993759 -0.111547 0 0.99366 -0.111533 -0.014136 0.026056 -0.278751 -0.96001 0.062257 -0.161531 -0.984902 -0.504188 0.075613 -0.860277 -0.546568 -0.199971 -0.813188 0.045724 -0.544969 -0.837209 0.045724 -0.544969 -0.837209 -0.741546 -0.333883 -0.581921 0.066704 -0.811752 -0.580181 0.066704 -0.811752 -0.580181 0.066704 -0.811752 -0.580181 0.066704 -0.811752 -0.580181 -0.90102 0.386253 0.197412 -0.912147 0.362732 0.190823 -0.940179 0.295974 0.168711 -0.967429 0.253142 0 -0.943609 -0.263678 -0.200188 -0.804177 0.437402 0.402466 -0.813745 0.392461 0.428712 -0.816865 0.46424 0.342363 -0.864447 0.502725 0 -0.920181 0.383489 0.078757 -0.951595 0.30634 0.024947 -0.926367 0.365689 -0.090082 -0.962866 0.243125 -0.117383 -0.97366 0.226115 0.029281 -0.98005 0.173345 -0.097232 -0.977169 0.212464 0 -0.980886 0.194582 0 -0.810648 0.063674 -0.582061 -0.894238 0.058535 -0.443748 -0.720435 0.222991 -0.656695 -0.93805 0.07016 -0.339322 -0.986739 -0.006785 -0.162175 -0.988329 0.062743 -0.138814 -0.999796 -0.020215 0 -0.998408 0.056396 0 -0.146147 -0.974276 -0.171543 -0.578912 -0.8151 0.021745 -0.52343 -0.808816 -0.268026 -0.123691 -0.985219 -0.118508 -0.526743 -0.834494 -0.161742 -0.493474 -0.782659 0.379379 -0.853097 -0.515247 0.082139 -0.853097 -0.515247 0.082139 -0.260361 -0.828037 0.496555 -0.165073 -0.536509 0.827592 -0.156923 -0.519015 0.840237 -0.118389 -0.943861 0.308399 -0.173136 -0.553718 0.814506 0.051963 -0.997426 0.049403 0.714001 -0.700118 0.006111 0.731428 -0.681778 0.013851 -0.118953 -0.984865 -0.126061 0.695717 -0.718314 -0.001785 -0.273117 -0.893822 -0.355653 -0.258848 -0.780903 -0.568497 -0.293123 -0.831968 -0.471072 -0.221137 -0.719472 -0.658376 0.387583 -0.899733 0.200651 0.387583 -0.899733 0.200651 -0.563981 -0.700193 -0.437785 -0.325377 -0.733064 -0.597283 -0.755519 -0.608889 -0.241753 -0.586343 -0.804006 0.098876 -0.904177 -0.076926 0.420174 -0.689029 -0.548775 0.473376 -0.612483 -0.788813 0.051368 -0.993431 -0.048914 0.10345 -0.615829 -0.786472 0.04708 -0.99589 -0.081035 -0.040455 -0.450727 -0.889909 -0.070052 -0.77658 -0.24958 -0.578475 -0.312719 -0.763605 -0.564902 0.920399 -0.390661 -0.015803 0.920023 -0.390851 -0.028167 0.920635 -0.39041 -0.003437 0.0078 -0.003324 0.999964 0.005854 -0.002481 0.99998 0.005033 -0.00214 0.999985 0.005595 -0.002391 0.999982 0.001773 -0.000752 -0.999998 0.001318 -0.00056 -0.999999 0.001335 -0.000567 -0.999999 0.001799 -0.000764 -0.999998 0.919122 -0.3927 0.031651 0.919262 -0.392778 0.026141 0.919262 -0.392778 0.026141 0.919122 -0.3927 0.031651 -0.906068 0.393915 -0.154505 -0.906068 0.393915 -0.154505 -0.90492 0.3933 -0.162588 -0.722286 0.314706 -0.615844 0.000862 -0.000367 -1 0.000871 -0.000371 -1 0.00339 -0.001458 0.999993 0.003649 -0.001548 0.999992 0.084544 -0.048968 -0.995216 -0.398638 0.31888 -0.859886 -0.432195 0.26086 -0.863226 0.091016 -0.045375 -0.994815 -0.855966 0.475217 0.203693 -0.727511 0.563293 -0.3917 -0.816593 0.378675 0.435639 -0.581084 0.34356 0.737772 -0.913864 0.396111 0.089152 -0.913458 0.396286 -0.092479 -0.689846 0.300453 -0.658666 -0.361531 0.158513 -0.918787 0.954244 -0.298978 0.005498 0.953065 -0.302088 0.020269 0.981689 -0.187837 0.031672 0.982009 -0.188496 0.011332 0.977004 -0.213145 0.005778 0.955206 -0.295798 -0.009286 0.925668 -0.37811 0.01308 0.925837 -0.377145 0.024234 0.925383 -0.379027 0.001926 0.995412 -0.095325 0.008238 0.994952 -0.094175 0.034658 -0.98576 0.083428 0.146005 -0.977772 0.15179 0.144647 -0.90861 0.068661 0.411964 -0.959949 0.05078 0.275536 -0.955051 0.249322 0.160365 -0.830891 0.096613 0.547984 -0.920504 0.350687 0.172312 -0.745638 0.235188 0.623466 -0.115485 -0.362167 0.924931 -0.155519 -0.670364 0.725552 -0.115502 -0.678935 0.725056 -0.088474 -0.372261 0.923902 -0.047388 -0.1088 0.992933 -0.037679 -0.114001 0.992766 -0.027962 -0.119191 0.992477 -0.061398 -0.382041 0.922103 -0.075324 -0.686363 0.723348 0.926496 -0.375136 -0.029629 0.926496 -0.375136 -0.029629 0.933206 -0.35726 -0.038615 0.933206 -0.35726 -0.038615 0.973898 -0.221359 -0.050229 0.973898 -0.221359 -0.050229 0.973898 -0.221359 -0.050229 0.973898 -0.221359 -0.050229 0.99366 -0.111538 0.014136 0.99366 -0.111538 0.014136 0.026055 -0.27875 0.96001 -0.546568 -0.19997 0.813188 -0.504188 0.075613 0.860277 0.062256 -0.16153 0.984902 0.045724 -0.54497 0.837208 -0.741546 -0.333883 0.581921 0.045724 -0.54497 0.837208 0.066704 -0.811751 0.580182 0.066704 -0.811751 0.580182 0.066704 -0.811751 0.580182 0.066704 -0.811751 0.580182 -0.912147 0.362733 -0.190823 -0.90102 0.386253 -0.197412 -0.940179 0.295975 -0.16871 -0.943609 -0.26368 0.200188 -0.804177 0.437401 -0.402466 -0.813745 0.39246 -0.428712 -0.816866 0.46424 -0.342363 -0.951596 0.306338 -0.024947 -0.920181 0.383488 -0.078757 -0.962866 0.243125 0.117383 -0.926367 0.365689 0.090082 -0.973661 0.226114 -0.029281 -0.98005 0.173345 0.097232 -0.894238 0.058535 0.443748 -0.810648 0.063673 0.582061 -0.720435 0.222991 0.656695 -0.93805 0.070159 0.339322 -0.988329 0.062742 0.138814 -0.986739 -0.006785 0.162175 -0.146146 -0.974276 0.171543 -0.123689 -0.985219 0.118507 -0.523431 -0.808816 0.268024 -0.578913 -0.8151 -0.021746 -0.526749 -0.83449 0.161743 -0.853107 -0.51523 -0.082141 -0.853107 -0.51523 -0.082141 -0.493479 -0.782655 -0.379381 -0.260362 -0.828035 -0.496558 -0.156921 -0.519013 -0.840239 -0.165073 -0.536506 -0.827594 -0.118388 -0.94386 -0.308402 -0.173138 -0.553714 -0.814509 0.051965 -0.997426 -0.049404 0.73143 -0.681776 -0.013852 0.714003 -0.700116 -0.006111 0.695717 -0.718313 0.001786 -0.118952 -0.984865 0.126059 -0.293122 -0.831971 0.471068 -0.258847 -0.780904 0.568495 -0.273117 -0.893823 0.355652 -0.221137 -0.719472 0.658376 0.387588 -0.89973 -0.200654 0.387588 -0.89973 -0.200654 -0.325378 -0.733064 0.597282 -0.563982 -0.700193 0.437783 -0.75552 -0.60889 0.24175 -0.586345 -0.804005 -0.098877 -0.68903 -0.548773 -0.473378 -0.904177 -0.076922 -0.420174 -0.993431 -0.048913 -0.10345 -0.612484 -0.788812 -0.051369 -0.61583 -0.786471 -0.04708 -0.99589 -0.081034 0.040456 -0.776581 -0.249577 0.578475 -0.450728 -0.889908 0.070052 -0.312719 -0.763603 0.564905 0.920023 -0.390851 0.028167 0.920399 -0.390661 0.015803 0.920635 -0.39041 0.003437 0.007805 -0.003324 -0.999964 0.005597 -0.002391 -0.999982 0.005034 -0.00214 -0.999985 0.005857 -0.002481 -0.99998 0.001775 -0.000753 0.999998 0.001802 -0.000765 0.999998 0.001336 -0.000568 0.999999 0.001318 -0.00056 0.999999 0.919122 -0.392699 -0.031652 0.919122 -0.392699 -0.031652 0.919262 -0.392778 -0.026142 0.919262 -0.392778 -0.026142 -0.90607 0.39391 0.154505 -0.722287 0.314704 0.615843 -0.904921 0.393297 0.162588 -0.90607 0.39391 0.154505 0.00087 -0.000371 1 0.000861 -0.000367 1 0.003389 -0.001458 -0.999993 0.003649 -0.001548 -0.999992 0.084544 -0.048968 0.995216 0.091016 -0.045375 0.994815 -0.432195 0.26086 0.863226 -0.398638 0.31888 0.859886 -0.855966 0.475217 -0.203693 -0.727511 0.563292 0.391702 -0.581084 0.343561 -0.737772 -0.816593 0.378676 -0.435639 -0.913864 0.396111 -0.089152 -0.913458 0.396285 0.092479 -0.689846 0.300453 0.658666 -0.361532 0.158514 0.918786 0.024708 0.087586 -0.995851 0.024708 0.087586 -0.995851 0.041507 0.242265 -0.969322 0.041507 0.242265 -0.969322 0.02091 0.187218 -0.982096 0.02091 0.187218 -0.982096 0.001773 0.032105 -0.999483 0.001773 0.032105 -0.999483 0.024708 0.087585 0.995851 0.024708 0.087585 0.995851 0.041507 0.242265 0.969322 0.041507 0.242265 0.969322 0.02091 0.187218 0.982096 0.02091 0.187218 0.982096 0.001772 0.032105 0.999483 0.001772 0.032105 0.999483 0.998615 -0.052621 0 0.9986 -0.052647 -0.005071 0.998213 -0.052652 -0.028264 -0.000423 0.000022 1 -0.000423 0.000022 1 -0.987371 0.053072 -0.149271 -0.977654 0.052384 -0.203589 -0.986078 0.05244 -0.157797 -0.998601 0.052887 0 -0.986078 0.05244 0.157797 -0.977654 0.052384 0.203589 -0.987371 0.053072 0.149271 -0.000423 0.000022 -1 -0.000423 0.000022 -1 0.998213 -0.052651 0.028264 0.9986 -0.052646 0.005071 0.480966 0.837282 0.260057 0.528606 0.809061 0.256896 0.531904 0.846804 0 0.49806 0.867143 0 0.253364 0.426929 0.868066 0.426779 0.3545 0.831979 0.521053 0.764754 0.379019 0.459812 0.800522 0.384366 -0.151499 -0.391106 0.907791 0.040367 -0.460206 0.886894 -0.322394 -0.877945 0.353942 -0.236194 -0.905901 0.351504 -0.148513 -0.782377 0.604838 -0.274127 -0.742075 0.611702 -0.343239 -0.939248 0 -0.276809 -0.960925 0 -0.268933 -0.952235 0.144648 -0.3399 -0.929133 0.145535 0.480966 0.837282 -0.260057 0.528606 0.809061 -0.256896 -0.151499 -0.391106 -0.907791 0.253364 0.426929 -0.868066 0.426779 0.354501 -0.831979 0.040367 -0.460206 -0.886894 0.459812 0.800523 -0.384366 0.521053 0.764754 -0.379019 -0.322394 -0.877945 -0.353942 -0.274127 -0.742075 -0.611702 -0.148513 -0.782377 -0.604839 -0.236194 -0.905901 -0.351504 -0.3399 -0.929133 -0.145535 -0.268933 -0.952235 -0.144648 -0.939694 0.342018 -0.000000 -0.939695 0.342014 -0.000001 -0.939696 0.342012 0 -0.939694 0.342017 0 0.943057 -0.332627 0.001655 0.943025 -0.332723 -0.000002 0.946264 -0.323394 -0.000005 0.946325 -0.3232 0.003311 -0.939693 0.342019 -0.000000 -0.939693 0.342019 0.000000 -0.939693 0.342019 0.000000 -0.939694 0.342017 -0.000000 0.939693 -0.34202 -0.000002 0.983175 0.071645 0.168027 0.914102 -0.064027 0.400398 0.78266 -0.492141 0.381106 -0.939693 0.34202 0.000000 -0.939692 0.342021 0 0.939693 -0.34202 -0.000000 0.939692 -0.34202 0 -0.939691 0.342023 -0.000001 -0.939693 0.34202 0 -0.939693 0.34202 0 -0.939692 0.342022 -0.000000 0.56053 -0.802487 0.204501 0.939694 -0.342016 -0.000001 0.939693 -0.342018 -0.000001 0.64519 -0.69364 0.320302 -0.939693 0.342019 0 -0.939693 0.342018 0 -0.939692 0.342022 -0.000000 -0.939692 0.342021 0 0.933166 -0.359445 -0.000024 0.933166 -0.359446 0.000523 0.926316 -0.376745 0.001048 0.926317 -0.376745 -0.000048 0.92231 -0.36092 0.138132 0.954438 0.234181 0.18495 0.873579 -0.430956 0.226133 0.903844 -0.394054 0.166696 0.939697 -0.342009 -0.000002 -0.939694 0.342017 0.000000 -0.939695 0.342014 0.000001 0.94299 -0.332819 -0.00166 0.946193 -0.323585 -0.003321 -0.939693 0.342018 0.000000 -0.939694 0.342017 0.000000 -0.939693 0.342018 -0.000000 -0.939693 0.342018 -0.000000 0.939693 -0.34202 0.000002 0.78266 -0.49214 -0.381106 0.914102 -0.064028 -0.400398 0.983175 0.071646 -0.168027 -0.939693 0.34202 -0.000000 0.939692 -0.342021 0.000000 -0.939692 0.342023 0.000000 -0.939692 0.342022 0.000000 -0.939693 0.342019 0 -0.939693 0.342019 0 0.56053 -0.802487 -0.2045 0.64519 -0.69364 -0.320302 0.939693 -0.342018 0.000002 0.939694 -0.342016 0.000001 -0.939692 0.342021 0 -0.939692 0.342022 0.000000 0.926317 -0.376744 -0.001144 0.933166 -0.359445 -0.000571 0.926616 -0.351645 -0.133148 0.92231 -0.36092 -0.138132 0.903844 -0.394054 -0.166696 0.87358 -0.430956 -0.226131 0.856894 -0.443764 -0.26231 0.704425 0.188071 0.684408 0.691549 0.631425 0.350803 0.684446 0.688553 0.239642 0.67204 0.740515 0 0.684446 0.688553 -0.239641 0.691549 0.631425 -0.350803 0.704425 0.188071 -0.684408 0.351262 -0.53297 -0.769778 0.064503 -0.820875 -0.567454 -0.099111 -0.935149 -0.340106 -0.163267 -0.976467 -0.14091 -0.180309 -0.98361 0 -0.163267 -0.976467 0.140911 -0.099111 -0.935149 0.340107 0.064503 -0.820875 0.567454 0.351262 -0.532971 0.769778 0.74671 0.665149 -0.001284 0.78758 0.616212 0 0.809839 0.547077 0.211822 0.837489 0.507896 -0.201629 0.809839 0.547077 -0.211822 0.808814 0.498137 -0.312536 0.802842 0.102849 -0.587253 0.463594 -0.546834 -0.697175 0.142368 -0.827322 -0.543387 -0.047994 -0.94253 -0.330657 -0.125474 -0.982907 -0.134721 -0.127675 -0.982349 -0.136713 -0.167742 -0.985831 -0.000000 -0.159595 -0.987183 -0.000000 -0.167601 -0.985 0.041036 -0.127675 -0.982349 0.136713 -0.082023 -0.970438 0.226985 -0.047994 -0.942529 0.330658 0.142368 -0.827322 0.543387 0.463594 -0.546835 0.697174 0.802842 0.102849 0.587254 0.808814 0.498138 0.312536 0.441345 0.879306 0.178987 0.448574 0.893736 -0.004108 0.448576 0.893735 -0.00411 0.441354 0.879319 0.178901 0.569319 0.82211 -0.003368 0.441363 0.879332 0.178814 0.683701 0.714934 0.146365 0.440649 0.877972 -0.187065 0.440657 0.877985 -0.186983 0.553787 0.81499 -0.17062 0.657477 0.7381 -0.151434 -0.046838 -0.08797 -0.995021 -0.07032 -0.133775 -0.988514 -0.069903 -0.132959 -0.988653 -0.045997 -0.086328 -0.995204 0.515542 -0.318344 -0.795534 0.538188 -0.277795 -0.795728 -0.134397 -0.257292 -0.956942 -0.134397 -0.257291 -0.956942 0.435259 -0.426428 -0.792912 -0.167277 -0.31497 -0.934244 -0.169618 -0.31933 -0.93234 0.340805 -0.481179 -0.807662 -0.385651 -0.702064 -0.598648 -0.387152 -0.704911 -0.594318 -0.169818 -0.314088 -0.934083 0.700383 -0.507347 -0.502058 -0.483351 -0.875423 -0.002516 -0.483355 -0.875421 -0.002525 -0.466728 -0.884399 -0.00175 -0.468801 -0.881747 -0.052429 -0.449937 -0.89306 -0.000966 -0.454865 -0.889242 -0.048443 -0.386368 -0.70344 0.596567 -0.387859 -0.706274 0.592235 -0.463452 -0.88477 0.048937 -0.443976 -0.89483 0.046513 -0.167306 -0.315038 0.934216 -0.169637 -0.319385 0.932318 0.340796 -0.481202 0.807652 -0.16984 -0.314172 0.934051 0.700379 -0.507345 0.502066 0.700379 -0.507345 0.502066 -0.134397 -0.257292 0.956942 -0.134397 -0.25729 0.956943 0.435259 -0.426428 0.792912 -0.070317 -0.13377 0.988514 -0.069901 -0.132955 0.988654 0.515543 -0.318341 0.795534 -0.046833 -0.087962 0.995022 -0.045992 -0.086322 0.995205 -0.045152 -0.084681 0.995385 0.89687 -0.354935 0.263903 -0.175657 -0.984451 0 0.014275 -0.999898 0 0.025168 -0.969969 0.241922 -0.164175 -0.952908 0.254978 0.057105 -0.882222 0.467357 -0.130513 -0.860425 0.492579 0.107911 -0.742637 0.660943 -0.076966 -0.713307 0.696613 -0.007184 -0.521578 0.853173 0.174121 -0.560726 0.809486 0.251224 -0.348886 0.902865 0.07408 -0.298305 0.951591 0.333966 -0.121554 0.934714 0.161288 -0.058703 0.98516 0.416708 0.105778 0.902865 0.248495 0.180897 0.951592 0.493812 0.317618 0.809487 0.32976 0.40417 0.853174 0.559918 0.497823 0.662318 0.203742 0.689424 0.695114 0.347173 -0.937801 0 0.356059 -0.913386 0.197351 0.382112 -0.841806 0.381253 0.423557 -0.727937 0.539173 0.477569 -0.579541 0.660348 0.540467 -0.40673 0.736523 0.607965 -0.221281 0.762505 0.675463 -0.035832 0.736523 0.738361 0.136979 0.660349 0.792373 0.285375 0.539172 0.585573 -0.81062 0 0.592116 -0.792642 0.145316 0.6113 -0.739935 0.280728 0.641817 -0.656091 0.397009 0.681587 -0.546822 0.486235 0.727901 -0.419576 0.542325 0.777601 -0.283025 0.561456 0.827303 -0.146472 0.542325 0.873616 -0.019226 0.486236 0.915667 0.094086 0.39077 0.750653 -0.660696 0.000000 0.754897 -0.649038 0.094239 0.767337 -0.614857 0.182057 0.787128 -0.560482 0.257467 0.81292 -0.489619 0.315332 0.842955 -0.407099 0.351706 0.875187 -0.318543 0.364113 0.907419 -0.229986 0.351706 0.937454 -0.147465 0.315331 0.965367 -0.072125 0.250727 0.864206 -0.503139 0.000000 0.866271 -0.497464 0.045867 0.872326 -0.480828 0.08861 0.881958 -0.454363 0.125313 0.894512 -0.419873 0.153477 0.909131 -0.379708 0.171182 0.924819 -0.336605 0.17722 0.940506 -0.293505 0.171181 0.955125 -0.25334 0.153476 0.967842 -0.218315 0.124978 0.812566 0.350317 0.465848 0.586876 0.574669 0.570379 0.928547 0.120082 0.351255 0.978318 -0.066909 0.196002 0.993042 -0.091645 0.073954 0.992417 -0.097224 0.075208 0.970705 -0.084446 0.224944 0.996929 -0.07831 0 0.996929 -0.078308 0 0.429665 0.673924 0.601012 0.219695 0.603178 -0.766753 0.208436 0.57182 -0.793459 0.208507 0.57175 -0.79349 0.208357 0.571898 -0.793423 0.511307 0.859398 0 0.504482 0.850735 -0.14747 0.336626 0.924888 -0.176819 0.342016 0.939694 -0.000000 0.427034 0.743586 -0.514511 0.313604 0.670313 -0.672557 0.226018 0.620982 -0.750532 0.27001 0.741845 -0.613809 0.482099 0.820329 -0.307637 0.317307 0.871798 -0.373207 0.977366 -0.191445 0.090028 0.983352 -0.175361 0.047626 0.985431 -0.170074 0 0.812566 0.350318 0.465848 0.588303 0.575535 0.568031 0.923823 0.093177 0.371307 0.435113 0.672738 0.598415 0.461071 0.738393 0.492127 0.494449 0.831091 0.254574 0.486331 0.835738 0.255 0.452961 0.742886 0.492897 0.47817 0.840311 0.255403 0.444811 0.747314 0.493625 0.505914 0.862584 0 0.497814 0.867284 0 0.48967 0.871908 0 0.427985 0.675623 0.600302 0.435918 0.671294 0.59945 0.207214 0.766164 0.608322 0.939692 -0.342021 0.000000 0.939692 -0.342021 0 0.939692 -0.342022 0 0.939692 -0.342021 0.000000 0.939693 -0.342019 0.000000 0.939694 -0.342018 0.000000 0.939693 -0.34202 0.000000 0.939694 -0.342018 0.000001 0.342021 0.939692 0.000000 0.336631 0.924886 -0.17682 0.159652 0.972391 -0.170196 0.160692 0.987005 0 0.270006 0.741846 -0.613808 0.226097 0.620906 -0.750571 0.185387 0.67071 -0.718178 0.145209 0.784997 -0.602242 0.317307 0.871799 -0.373207 0.156151 0.919375 -0.361064 0.939693 -0.34202 -0.000000 0.939693 -0.34202 0 0.939692 -0.342021 0.000000 0.939692 -0.342021 0.000002 0.939693 -0.342019 0.000001 0.939692 -0.342021 0.000000 0.279325 0.729583 -0.624248 0.939692 -0.342021 0 0.939692 -0.342022 0.000000 0.939691 -0.342025 0.000001 0.939692 -0.342022 0.000000 0.939693 -0.34202 0 0.939693 -0.34202 0 0.939692 -0.342021 0.000002 0.939692 -0.342023 0.000003 0.939692 -0.342021 0.000001 0.939693 -0.34202 -0.000000 0.939693 -0.34202 0 0.602984 0.728678 -0.324713 0.307512 0.802438 -0.511399 -0.009193 0.940845 -0.338713 0.654804 0.747295 -0.113057 0.649811 0.747553 -0.137512 -0.022631 0.987203 -0.157855 0.661987 0.749515 0 -0.026011 0.999662 0 -0.164175 -0.952907 -0.254979 0.025168 -0.969969 -0.241922 -0.130512 -0.860425 -0.49258 0.057105 -0.882222 -0.467357 -0.076966 -0.713307 -0.696613 0.107911 -0.742637 -0.660943 -0.007184 -0.521578 -0.853173 0.174121 -0.560726 -0.809486 0.07408 -0.298305 -0.951591 0.251224 -0.348886 -0.902865 0.161288 -0.058703 -0.98516 0.333966 -0.121554 -0.934715 0.248495 0.180897 -0.951592 0.416708 0.105778 -0.902865 0.32976 0.40417 -0.853174 0.493812 0.317618 -0.809487 0.407414 0.622996 -0.66775 0.559918 0.497823 -0.662318 0.356059 -0.913386 -0.197351 0.382112 -0.841806 -0.381253 0.423557 -0.727937 -0.539172 0.477569 -0.579541 -0.660348 0.540467 -0.40673 -0.736523 0.607965 -0.221281 -0.762505 0.675463 -0.035831 -0.736523 0.738361 0.136979 -0.660348 0.792373 0.285375 -0.539172 0.592116 -0.792642 -0.145316 0.6113 -0.739935 -0.280728 0.641817 -0.65609 -0.397009 0.681587 -0.546821 -0.486236 0.727901 -0.419576 -0.542325 0.777602 -0.283025 -0.561456 0.827303 -0.146472 -0.542325 0.873616 -0.019226 -0.486235 0.915667 0.094086 -0.39077 0.754897 -0.649038 -0.094239 0.767337 -0.614856 -0.182057 0.787128 -0.560482 -0.257467 0.81292 -0.489619 -0.315332 0.842955 -0.407099 -0.351706 0.875187 -0.318542 -0.364113 0.907419 -0.229986 -0.351706 0.937454 -0.147465 -0.315331 0.965367 -0.072125 -0.250727 0.866271 -0.497464 -0.045867 0.872326 -0.480829 -0.08861 0.881959 -0.454362 -0.125313 0.894512 -0.419872 -0.153477 0.909131 -0.379708 -0.171182 0.924819 -0.336605 -0.17722 0.940506 -0.293505 -0.171181 0.955125 -0.25334 -0.153476 0.967843 -0.218314 -0.124978 0.812566 0.350318 -0.465847 0.586876 0.574669 -0.570379 0.928547 0.120083 -0.351255 0.978318 -0.066908 -0.196002 0.970706 -0.084444 -0.224944 0.992417 -0.097222 -0.075208 0.993042 -0.091644 -0.073954 0.429665 0.673924 -0.601011 0.219695 0.603178 0.766753 0.208357 0.571898 0.793423 0.208507 0.57175 0.79349 0.208436 0.57182 0.793459 0.336626 0.924888 0.176819 0.504482 0.850735 0.14747 0.427034 0.743586 0.514511 0.270009 0.741845 0.613809 0.226018 0.620982 0.750532 0.313604 0.670313 0.672557 0.317307 0.871798 0.373207 0.482099 0.820329 0.307637 0.977366 -0.191445 -0.090028 0.983352 -0.175361 -0.047627 0.588303 0.575536 -0.568031 0.812566 0.350317 -0.465848 0.923823 0.093177 -0.371307 0.435114 0.672739 -0.598414 0.461071 0.738394 -0.492127 0.452961 0.742886 -0.492897 0.486331 0.835738 -0.255 0.494449 0.831091 -0.254574 0.194789 0.850499 -0.488578 0.47817 0.840311 -0.255403 0.435919 0.671294 -0.599449 0.427985 0.675623 -0.600302 0.207214 0.766163 -0.608322 0.939693 -0.34202 -0.000000 0.939693 -0.34202 -0.000000 0.939693 -0.34202 -0.000000 0.939693 -0.342019 -0.000000 0.939692 -0.342023 -0.000000 0.939692 -0.342022 -0.000001 0.159652 0.972391 0.170196 0.336631 0.924886 0.17682 0.270006 0.741846 0.613808 0.145209 0.784997 0.602242 0.185387 0.67071 0.718178 0.226097 0.620906 0.750571 0.156151 0.919375 0.361064 0.317307 0.871799 0.373207 0.939693 -0.34202 0.000000 0.939692 -0.342021 -0.000000 0.939692 -0.342022 -0.000002 0.939692 -0.342023 -0.000001 0.939691 -0.342024 -0.000000 0.279325 0.729583 0.624248 0.939692 -0.342021 0.000000 0.939692 -0.342022 -0.000000 0.93969 -0.342026 -0.000001 0.939692 -0.342023 -0.000000 0.939691 -0.342024 -0.000003 0.939692 -0.342022 -0.000002 0.939692 -0.342022 -0.000001 0.939693 -0.34202 0.000000 0.307512 0.802438 0.511399 0.602985 0.728678 0.324713 -0.009193 0.940845 0.338713 0.649812 0.747553 0.137512 0.654804 0.747295 0.113057 -0.022631 0.987203 0.157855 0.937541 -0.341231 -0.067659 0.931551 -0.35769 -0.065353 0.925969 -0.373025 -0.058594 0.921176 -0.386194 -0.04784 0.917499 -0.396298 -0.033828 0.915188 -0.402648 -0.017506 0.914398 -0.404817 0 0.915187 -0.402649 0.017506 0.917498 -0.396299 0.033828 0.921176 -0.386195 0.04784 0.925969 -0.373025 0.058594 0.931551 -0.35769 0.065353 0.937541 -0.341231 0.067659 0.943529 -0.324781 0.065355 0.94911 -0.309447 0.058594 0.953904 -0.296275 0.047842 0.957579 -0.286177 0.033835 0.959891 -0.279827 0.017516 0.960679 -0.27766 0 0.95989 -0.279828 -0.017516 0.957579 -0.286177 -0.033835 0.953904 -0.296273 -0.047842 0.94911 -0.309447 -0.058594 0.943528 -0.324782 -0.065355 0.939693 -0.34202 0 -0.179692 0.95797 0.223617 -0.179692 0.95797 0.223617 -0.069689 0.891449 0.447731 -0.069689 0.891449 0.447731 -0.016691 0.812011 0.583403 -0.120136 0.728214 0.674738 -0.213121 0.654765 0.725164 -0.213121 0.654765 0.725164 -0.401191 0.487576 0.775446 -0.401191 0.487576 0.775446 -0.441105 0.390891 0.807856 -0.441105 0.390891 0.807856 -0.516228 0.187892 0.835587 -0.516228 0.187892 0.835587 -0.590198 -0.015331 0.807113 -0.590198 -0.015331 0.807113 -0.659125 -0.204704 0.723637 -0.659125 -0.204704 0.723637 -0.718316 -0.367319 0.590846 -0.718316 -0.367319 0.590846 -0.763734 -0.492099 0.41779 -0.763734 -0.492099 0.41779 -0.79228 -0.570546 0.216265 -0.79228 -0.570546 0.216265 -0.802014 -0.597306 0.000000 -0.802014 -0.597306 0.000000 -0.79228 -0.570546 -0.216265 -0.79228 -0.570546 -0.216265 -0.763734 -0.4921 -0.417789 -0.763734 -0.4921 -0.417789 -0.718316 -0.36732 -0.590846 -0.718316 -0.36732 -0.590846 -0.659125 -0.204704 -0.723637 -0.659125 -0.204704 -0.723637 -0.590198 -0.015331 -0.807113 -0.590198 -0.015331 -0.807113 -0.516227 0.187892 -0.835587 -0.516227 0.187892 -0.835587 -0.441105 0.390891 -0.807856 -0.441105 0.390891 -0.807856 -0.309716 0.575931 -0.756558 -0.309716 0.575931 -0.756558 -0.120136 0.728214 -0.674738 -0.120136 0.728214 -0.674738 -0.016691 0.812011 -0.583403 -0.069689 0.891449 -0.44773 -0.129909 0.933408 -0.334473 -0.129909 0.933408 -0.334473 -0.226715 0.967806 -0.109323 -0.226715 0.967806 -0.109323 -0.228082 0.973642 0 -0.228082 0.973642 0 0.667311 -0.242881 0.704063 0.72956 -0.071811 0.680136 0.55002 0.037451 0.834311 0.473658 -0.172397 0.863671 0.784508 0.080753 0.614838 0.617449 0.224418 0.753919 0.827898 0.201412 0.523468 0.670657 0.372153 0.641655 0.856659 0.283358 0.431095 0.705899 0.472088 0.528053 0.880652 0.346313 0.323294 0.735324 0.549774 0.396291 0.900314 0.398719 0.174523 0.759454 0.614352 0.214012 0.908101 0.418751 0 0.769032 0.63921 0 0.900314 0.398718 -0.174522 0.759454 0.614352 -0.214012 0.880653 0.346312 -0.323294 0.735324 0.549774 -0.396292 0.856659 0.283359 -0.431095 0.705898 0.472088 -0.528053 0.827898 0.201413 -0.523467 0.670657 0.372154 -0.641655 0.78451 0.080753 -0.614836 0.617449 0.224418 -0.753918 0.729562 -0.071811 -0.680134 0.550021 0.037451 -0.834311 0.667312 -0.242882 -0.704062 0.473657 -0.172397 -0.863672 0.604987 -0.414117 -0.680072 0.397203 -0.382451 -0.834243 0.546909 -0.573684 -0.609735 0.32596 -0.57819 -0.747961 0.497037 -0.710706 -0.497847 0.264783 -0.746275 -0.610708 0.45877 -0.815846 -0.352031 0.217839 -0.875251 -0.431835 0.434712 -0.881941 -0.182225 0.188328 -0.956329 -0.223535 0.426504 -0.904486 0 0.178262 -0.983983 0 0.434712 -0.881941 0.182225 0.188329 -0.956329 0.223535 0.458769 -0.815846 0.352032 0.21784 -0.87525 0.431836 0.497036 -0.710706 0.497848 0.264783 -0.746275 0.610708 0.54691 -0.573683 0.609735 0.325961 -0.57819 0.747961 0.604989 -0.414117 0.68007 0.397205 -0.382451 0.834242 0.026874 -0.009781 -0.999591 0.11527 0.233084 -0.965601 -0.06161 -0.252892 -0.965531 -0.144064 -0.479435 -0.865672 -0.214869 -0.673973 -0.706818 -0.269202 -0.823247 -0.499796 -0.303356 -0.917084 -0.258714 -0.315004 -0.94909 0 -0.303355 -0.917084 0.258714 -0.2692 -0.823247 0.499796 -0.214868 -0.673974 0.706818 -0.144063 -0.479437 0.865671 -0.061608 -0.252894 0.965531 0.026877 -0.009782 0.999591 0.115272 0.233084 0.9656 0.193839 0.449076 0.872214 0.255851 0.619572 0.742072 0.297495 0.734222 0.610258 0.330625 0.825005 0.458316 0.358065 0.900267 0.247606 0.368754 0.929527 0 0.358064 0.900268 -0.247605 0.330624 0.825006 -0.458316 0.297494 0.734223 -0.610258 0.255849 0.619573 -0.742072 0.193836 0.449077 -0.872214 -0.191597 0.818167 0.542119 -0.229744 0.71636 0.658822 -0.16338 0.898746 0.406895 -0.139686 0.965503 0.219753 -0.13077 0.991413 0 -0.139687 0.965503 -0.219752 -0.163382 0.898745 -0.406895 -0.191599 0.818167 -0.542119 -0.229744 0.71636 -0.658822 -0.285359 0.565057 -0.774133 -0.355686 0.373489 -0.856734 -0.434128 0.158009 -0.886885 -0.512637 -0.05769 -0.856665 -0.585794 -0.25869 -0.768065 -0.648617 -0.431293 -0.627123 -0.696822 -0.563736 -0.443442 -0.727123 -0.646994 -0.229543 -0.737459 -0.675392 0 -0.727123 -0.646994 0.229544 -0.696821 -0.563737 0.443443 -0.648616 -0.431293 0.627123 -0.585794 -0.25869 0.768066 -0.512634 -0.05769 0.856667 -0.434126 0.158009 0.886887 -0.355684 0.373489 0.856735 -0.285358 0.565057 0.774132 -0.390933 0.920419 0 -0.398122 0.899251 0.181236 -0.398122 0.899251 -0.181236 -0.41748 0.844399 -0.335709 -0.440439 0.778247 -0.4476 -0.472225 0.693927 -0.543571 -0.518241 0.569005 -0.638483 -0.576367 0.41097 -0.706332 -0.641041 0.23332 -0.731183 -0.705766 0.055488 -0.706269 -0.766081 -0.110223 -0.633223 -0.817875 -0.252524 -0.517023 -0.857615 -0.361717 -0.365591 -0.882597 -0.43036 -0.189245 -0.891118 -0.453773 0.000000 -0.882597 -0.430358 0.189245 -0.857615 -0.361717 0.365592 -0.817874 -0.252524 0.517024 -0.76608 -0.110223 0.633223 -0.705764 0.055488 0.706271 -0.64104 0.233319 0.731184 -0.576367 0.41097 0.706332 -0.518243 0.569005 0.638481 -0.472227 0.693927 0.543569 -0.440437 0.778248 0.447599 -0.417478 0.8444 0.335708 -0.331712 -0.911364 0.243685 -0.331712 -0.911364 0.243685 -0.342019 -0.939687 0.003531 -0.342019 -0.939687 0.003531 -0.087813 -0.241267 -0.966478 -0.087813 -0.241267 -0.966478 -0.000116 -0.000321 -1 -0.000116 -0.000321 -1 0.330145 0.90706 0.26124 0.330145 0.90706 0.26124 0.296319 0.814129 0.499389 0.296319 0.814129 0.499389 0.24177 0.664258 -0.707325 0.24177 0.664258 -0.707325 0.295233 0.811147 -0.504855 0.295233 0.811147 -0.504855 -0.08777 -0.241146 0.966512 -0.08777 -0.241146 0.966512 -0.164638 -0.45234 0.876517 -0.164638 -0.45234 0.876517 -0.22478 -0.617578 -0.753705 -0.22478 -0.617578 -0.753705 -0.164044 -0.450708 -0.877469 -0.164044 -0.450708 -0.877469 0.241841 0.664457 0.707113 0.241841 0.664457 0.707113 -0.331837 -0.911717 -0.24219 -0.331837 -0.911717 -0.24219 -0.305633 -0.839719 -0.448844 -0.305633 -0.839719 -0.448844 -0.222308 -0.610789 0.759945 -0.222308 -0.610789 0.759945 -0.269693 -0.740975 0.614997 -0.269693 -0.740975 0.614997 -0.307306 -0.844311 0.438978 -0.307306 -0.844311 0.438978 0.0895 0.245901 -0.965154 0.0895 0.245901 -0.965154 0.171754 0.471891 -0.864765 0.171754 0.471891 -0.864765 0.089147 0.244934 0.965433 0.089147 0.244934 0.965433 0.000319 0.000877 1 0.000319 0.000877 1 0.330212 0.907251 -0.260491 0.330212 0.907251 -0.260491 -0.269972 -0.741739 -0.613953 -0.269972 -0.741739 -0.613953 0.170915 0.469589 0.866184 0.170915 0.469589 0.866184 0.342017 0.93968 0.004987 0.342017 0.93968 0.004987 -0.872996 0.443828 0.202226 -0.892487 0.431685 0.130822 -0.919373 0.357841 0.163409 -0.8931 0.388651 0.226546 -0.836219 0.544825 0.062478 -0.874717 0.480483 0.063292 -0.843885 0.523894 0.115728 -0.833441 0.552608 -0.000482 -0.871024 0.49078 -0.021287 -0.892174 0.391318 -0.2256 -0.905123 0.396964 -0.15222 -0.873687 0.441837 -0.203596 -0.882108 0.460141 -0.100775 -0.856401 0.489214 -0.165067 -0.84462 0.521911 -0.119273 -0.914227 0.330861 -0.233924 -0.933875 0.317692 -0.16416 -0.991386 0.117672 0.05751 -0.980419 0.18877 0.056082 -0.983232 0.181344 -0.019199 -0.993811 0.111072 -0.001466 -0.857281 0.487104 0.166729 -0.985481 0.133392 -0.105043 -0.975003 0.203603 -0.08897 -0.976746 0.156608 -0.146432 -0.965137 0.188646 0.18145 -0.967802 0.223375 0.116028 -0.976846 0.156838 0.145513 -0.934486 0.274951 0.226137 -0.947202 0.280423 0.15547 -0.950862 0.227127 0.210414 -0.912885 0.334385 0.234154 -0.951997 0.226039 -0.206416 -0.958687 0.248523 -0.138404 -0.933224 0.277263 -0.228513 -0.986082 0.13042 0.103116 -0.836257 0.545144 -0.0591 -0.991852 0.115055 -0.054696 -0.965627 0.186625 -0.180928 -0.9281 0.372089 0.013412 -0.92898 0.368288 0.036893 -0.934538 0.354403 -0.032217 -0.926051 0.376329 -0.028383 -0.950978 0.309235 -0.003683 -0.952104 0.304821 -0.024148 -0.953722 0.300321 0.014919 -0.945667 0.323838 -0.029018 -0.940569 0.336451 -0.046165 -0.927302 0.374287 -0.004549 -0.937543 0.346149 0.034559 -0.947654 0.318405 0.023879 -0.944194 0.32649 0.043624 -0.939693 0.34202 -0.000000 0.854491 0.392015 0.340836 0.875238 0.447325 0.184009 0.875238 0.447325 0.184009 0.854491 0.392015 0.340836 0.883466 0.468494 0.000000 0.883466 0.468494 0.000000 0.875238 0.447325 -0.184008 0.875238 0.447325 -0.184008 0.854491 0.392016 -0.340836 0.854491 0.392016 -0.340836 0.829169 0.325556 -0.454414 0.829169 0.325556 -0.454414 0.79887 0.239258 -0.551872 0.79887 0.239258 -0.551872 0.753134 0.112079 -0.648249 0.753134 0.112079 -0.648249 0.695204 -0.048762 -0.717156 0.695204 -0.048762 -0.717156 0.629568 -0.229143 -0.742386 0.629568 -0.229143 -0.742386 0.563851 -0.409699 -0.71709 0.563851 -0.409699 -0.71709 0.50261 -0.577951 -0.642927 0.50261 -0.577951 -0.642927 0.450025 -0.722432 -0.524948 0.450025 -0.722432 -0.524948 0.409673 -0.833297 -0.371194 0.409673 -0.833297 -0.371194 0.384304 -0.90299 -0.192145 0.384304 -0.90299 -0.192145 0.37565 -0.926762 0.000000 0.37565 -0.926762 0.000000 0.384304 -0.90299 0.192145 0.384304 -0.90299 0.192145 0.409674 -0.833297 0.371193 0.409674 -0.833297 0.371193 0.450027 -0.722432 0.524945 0.450027 -0.722432 0.524945 0.502613 -0.577952 0.642925 0.502613 -0.577952 0.642925 0.563851 -0.4097 0.71709 0.563851 -0.4097 0.71709 0.629568 -0.229144 0.742386 0.629568 -0.229144 0.742386 0.695207 -0.048763 0.717154 0.695207 -0.048763 0.717154 0.753139 0.112075 0.648245 0.753139 0.112075 0.648245 0.798872 0.239257 0.551869 0.798872 0.239257 0.551869 0.829169 0.325556 0.454413 0.829169 0.325556 0.454413 0.068251 0.678037 0.731852 0.109849 0.790981 0.601899 -0.072565 0.81672 0.572452 -0.112586 0.709293 0.695864 0.141985 0.880644 0.452003 -0.042486 0.901936 0.429774 0.168753 0.954933 0.244185 -0.017303 0.972528 0.232142 0.179043 0.983841 0.000000 -0.007748 0.99997 0.000000 0.168751 0.954933 -0.244184 -0.017304 0.972528 -0.232142 0.141984 0.880644 -0.452003 -0.042488 0.901936 -0.429774 0.109848 0.790981 -0.601899 -0.072567 0.816721 -0.572452 0.068249 0.678038 -0.731852 -0.112589 0.709294 -0.695864 0.00683 0.509965 -0.860168 -0.171208 0.549502 -0.817762 -0.070934 0.297047 -0.952224 -0.245373 0.347129 -0.905149 -0.158112 0.057548 -0.985743 -0.328245 0.119471 -0.937007 -0.245372 -0.182195 -0.952154 -0.41119 -0.108419 -0.905079 -0.326683 -0.4056 -0.853678 -0.488482 -0.320778 -0.811472 -0.396507 -0.597443 -0.697025 -0.554854 -0.503136 -0.662564 -0.450085 -0.744649 -0.492871 -0.605783 -0.643064 -0.468504 -0.483765 -0.837186 -0.25513 -0.637798 -0.731026 -0.242516 -0.495252 -0.868749 0.000000 -0.648718 -0.761029 0.000000 -0.483764 -0.837187 0.25513 -0.637797 -0.731027 0.242516 -0.450082 -0.74465 0.492872 -0.605781 -0.643065 0.468504 -0.396505 -0.597443 0.697026 -0.554852 -0.503137 0.662565 -0.326681 -0.405601 0.853679 -0.48848 -0.320779 0.811473 -0.245367 -0.182196 0.952155 -0.411187 -0.10842 0.90508 -0.158108 0.057546 0.985743 -0.328242 0.11947 0.937008 -0.070932 0.297046 0.952225 -0.24537 0.347128 0.90515 0.006833 0.509964 0.860168 -0.171205 0.549502 0.817763 -0.710784 0.258704 0.654108 -0.768687 0.099618 0.63182 -0.652928 0.417629 0.631878 -0.600917 0.559057 0.571274 -0.559726 0.670892 0.486426 -0.53123 0.746499 0.400667 -0.510735 0.805543 0.300416 -0.493446 0.854527 0.162155 -0.487042 0.873379 -0.000000 -0.493447 0.854527 -0.162155 -0.510737 0.805543 -0.300415 -0.531232 0.746498 -0.400666 -0.559728 0.670892 -0.486425 -0.60092 0.559056 -0.571272 -0.652931 0.417629 -0.631876 -0.710787 0.258705 -0.654105 -0.768689 0.09962 -0.631818 -0.822645 -0.048623 -0.566472 -0.868978 -0.175924 -0.462523 -0.904531 -0.273606 -0.327053 -0.92688 -0.335011 -0.169296 -0.934503 -0.355955 -0.000000 -0.92688 -0.335011 0.169296 -0.90453 -0.273607 0.327054 -0.868977 -0.175926 0.462524 -0.822643 -0.048626 0.566474 -0.823708 0.539726 0.173785 -0.835963 0.506696 0.210774 -0.814734 0.565035 0.13017 -0.807201 0.586084 0.070223 -0.804394 0.594097 -0.000000 -0.807202 0.586084 -0.070223 -0.814735 0.565033 -0.130169 -0.82371 0.539724 -0.173783 -0.835965 0.506693 -0.210771 -0.853753 0.458139 -0.247414 -0.8762 0.396817 -0.273513 -0.901241 0.328025 -0.283132 -0.926304 0.259165 -0.273485 -0.949659 0.194996 -0.2452 -0.969715 0.139893 -0.200206 -0.985104 0.097611 -0.141568 -0.994779 0.07103 -0.073281 -0.998078 0.061964 -0.000000 -0.994779 0.071029 0.073281 -0.985105 0.097608 0.141569 -0.969715 0.13989 0.200208 -0.949659 0.194993 0.245204 -0.926303 0.259163 0.27349 -0.90124 0.328024 0.283138 -0.876198 0.396819 0.273518 -0.853751 0.458142 0.247417 -0.964429 0.263503 -0.021028 -0.962132 0.269782 -0.038982 -0.965306 0.261123 -0.000001 -0.96443 0.2635 0.021027 -0.962133 0.26978 0.038983 -0.959368 0.277314 0.052054 -0.955774 0.287249 0.063122 -0.950485 0.30181 0.074089 -0.943807 0.320191 0.081895 -0.93631 0.340789 0.084774 -0.928805 0.361408 0.081884 -0.921813 0.38062 0.073415 -0.915808 0.397117 0.059942 -0.911201 0.409776 0.042384 -0.908305 0.417732 0.021938 -0.907318 0.420445 -0.000000 -0.908306 0.41773 -0.021939 -0.911203 0.409772 -0.042383 -0.91581 0.397113 -0.059939 -0.921815 0.380616 -0.073409 -0.928807 0.361406 -0.081878 -0.936311 0.340789 -0.084767 -0.943806 0.320194 -0.081887 -0.950484 0.301814 -0.074083 -0.955772 0.287255 -0.063118 -0.959367 0.277319 -0.052053 -0.919765 -0.159993 -0.358377 -0.895757 -0.091725 -0.434977 -0.939593 -0.212125 -0.268641 -0.955862 -0.255554 -0.144986 -0.962272 -0.272091 -0.000001 -0.955861 -0.255557 0.144984 -0.939592 -0.212129 0.268641 -0.919764 -0.159999 0.358377 -0.895755 -0.091731 0.43498 -0.859661 0.008583 0.510793 -0.813979 0.135358 0.564905 -0.762274 0.277445 0.584776 -0.710509 0.419669 0.564849 -0.662272 0.5522 0.506429 -0.620851 0.666007 0.413497 -0.589067 0.753333 0.292384 -0.569088 0.808228 0.151349 -0.562275 0.826951 -0.000000 -0.56909 0.808226 -0.151349 -0.589071 0.75333 -0.292384 -0.620856 0.666003 -0.413495 -0.662278 0.552198 -0.506424 -0.710514 0.419669 -0.564843 -0.762279 0.277447 -0.584769 -0.813982 0.135362 -0.564898 -0.859664 0.008588 -0.510787 -0.709852 -0.151442 0.687877 -0.758378 -0.286344 0.585552 -0.648374 0.019204 0.76108 -0.578714 0.210635 0.78786 -0.508972 0.402251 0.761014 -0.443984 0.580808 0.682306 -0.388177 0.734139 0.557099 -0.345355 0.851794 0.393927 -0.318436 0.925753 0.203911 -0.309255 0.950979 -0.000000 -0.318438 0.925752 -0.203912 -0.34536 0.851791 -0.393927 -0.388183 0.734136 -0.557098 -0.44399 0.580808 -0.682302 -0.508979 0.402253 -0.761008 -0.578721 0.210637 -0.787854 -0.64838 0.019208 -0.761075 -0.709856 -0.151438 -0.687874 -0.758381 -0.286338 -0.58555 -0.790511 -0.37778 -0.482053 -0.817394 -0.448424 -0.361639 -0.83942 -0.507195 -0.195261 -0.848164 -0.529735 -0.000001 -0.839419 -0.507196 0.19526 -0.817392 -0.448428 0.361639 -0.790508 -0.377786 0.482052 0.291962 -0.106265 0.950508 0.376101 0.124908 0.918121 0.376101 0.124908 0.918121 0.291962 -0.106265 0.950508 0.454506 0.340328 0.823165 0.454506 0.340328 0.823165 0.521834 0.525314 0.672112 0.521834 0.525314 0.672112 0.573496 0.667259 0.475255 0.573496 0.667259 0.475255 0.605971 0.75649 0.246011 0.605971 0.75649 0.246011 0.617047 0.786926 0.000000 0.617047 0.786926 0.000000 0.605969 0.756492 -0.24601 0.605969 0.756492 -0.24601 0.573491 0.667263 -0.475256 0.573491 0.667263 -0.475256 0.521828 0.525317 -0.672114 0.521828 0.525317 -0.672114 0.454499 0.340332 -0.823168 0.454499 0.340332 -0.823168 0.376092 0.124913 -0.918124 0.376092 0.124913 -0.918124 0.291951 -0.106261 -0.950512 0.291951 -0.106261 -0.950512 0.207887 -0.337201 -0.918193 0.207887 -0.337201 -0.918193 0.132705 -0.54249 -0.829514 0.132705 -0.54249 -0.829514 0.073292 -0.704571 -0.705838 0.073292 -0.704571 -0.705838 0.032798 -0.813517 -0.580615 0.032798 -0.813517 -0.580615 0.002188 -0.899976 -0.435934 0.002188 -0.899976 -0.435934 -0.023411 -0.971597 -0.235479 -0.023411 -0.971597 -0.235479 -0.033152 -0.99945 0.000000 -0.033152 -0.99945 0.000000 -0.023409 -0.971597 0.23548 -0.023409 -0.971597 0.23548 0.002193 -0.899976 0.435934 0.002193 -0.899976 0.435934 0.032803 -0.813518 0.580614 0.032803 -0.813518 0.580614 0.073299 -0.704572 0.705837 0.073299 -0.704572 0.705837 0.132715 -0.542491 0.829512 0.132715 -0.542491 0.829512 0.207898 -0.337203 0.91819 0.207898 -0.337203 0.91819 0.227734 -0.625295 0.74642 0.233389 -0.64043 0.731696 0.070866 -0.364444 0.928525 0.009523 -0.390134 0.920709 0.242856 -0.970062 0 0.241349 -0.957044 0.160677 0.338322 -0.929544 0.146579 0.34202 -0.939693 0 0.212351 -0.783141 0.584464 0.210322 -0.660264 0.720983 -0.120369 -0.481356 0.868221 -0.259273 -0.642256 0.721307 0.235089 -0.908055 0.346654 0.336118 -0.923497 0.184875 0.30665 -0.842525 0.442853 0.342023 -0.939691 -0.000000 0.338327 -0.929542 0.14658 0.431326 -0.889911 0.148381 0.437599 -0.89917 0 0.287602 -0.79018 0.541203 0.249676 -0.685698 0.683725 0.273466 -0.659273 0.700411 0.354888 -0.760917 0.543194 0.324402 -0.89129 0.316804 0.408726 -0.854966 0.319338 0.241596 -0.651213 0.719412 -0.989205 -0.146539 0 -0.985413 -0.170182 0 -0.980671 -0.169326 0.098047 -0.975296 -0.063957 0.211442 -0.939693 -0.342019 -0.000000 -0.932995 -0.339584 0.119178 -0.956262 -0.13157 0.261252 -0.926758 -0.337315 0.165341 -0.859323 -0.01228 0.511286 -0.871962 0.085321 0.48208 -0.818477 -0.2979 0.491275 -0.688925 0.154591 0.708155 -0.732152 0.264978 0.627487 -0.449247 0.323428 0.83281 -0.561815 0.595976 0.573739 -0.302865 0.400265 0.864905 -0.425114 0.740153 0.52101 0.939693 0.342019 -0.000000 0.939693 0.342019 -0.000004 0.939693 0.34202 -0.000001 0.939693 0.34202 -0.000000 0.939692 0.342022 -0.000009 0.939692 0.342023 -0.000004 0.939691 0.342024 -0.000001 0.939692 0.342022 -0.000000 0.939691 0.342026 -0.000003 0.939692 0.342022 -0.000001 0.93969 0.342026 -0.000001 0.939692 0.342022 -0.000000 0.939691 0.342025 -0.000000 0.939692 0.342023 0 0.939691 0.342025 0 0.939692 0.342023 0 0.337795 -0.926781 0.164233 0.342215 -0.939622 0 0.322206 -0.878715 0.352197 0.281111 -0.75735 0.589405 -0.921792 -0.212523 0.324242 -0.967709 -0.252069 0 -0.747455 -0.059224 0.661667 -0.945447 -0.142711 0.292853 -0.986092 -0.166199 0 -0.625714 0.019086 0.779819 -0.706372 0.097525 0.70109 -0.825623 -0.012411 0.564086 -0.665497 0.092603 0.740633 -0.541873 0.532711 0.650071 -0.621662 0.283323 0.73025 -0.421449 0.742151 0.521145 0.939692 0.342022 -0.000001 0.939692 0.342023 -0.000002 0.939692 0.342021 0.000000 0.939692 0.342022 -0.000000 -0.845881 0.349665 0.402766 -0.920658 0.197718 0.336596 -0.972331 -0.01437 0.233167 -0.890517 0.45495 0 -0.954731 0.297469 0 -0.999995 0.003238 0 0.939694 0.342018 0 0.939693 0.342018 0.000000 0.939695 0.342015 0 0.939694 0.342016 0.000000 0.939693 0.342019 0.000000 0.939693 0.342019 0.000000 0.939693 0.34202 0.000000 0.939692 0.342021 0 0.211752 0.211768 -0.954105 0.16982 0.095817 -0.980806 0.011832 0.417438 -0.908628 -0.075065 0.605301 -0.792449 -0.340314 0.940312 0 -0.336573 0.930182 -0.146559 -0.240444 0.957257 -0.160764 -0.241997 0.970277 0 0.415919 0.483109 -0.770466 0.220662 0.382543 -0.897201 -0.180728 0.657456 -0.731498 -0.215149 0.7838 -0.582553 -0.327154 0.891186 -0.314256 -0.236509 0.908048 -0.345706 -0.447632 0.894218 0 -0.443963 0.879055 -0.173663 -0.884073 0.449195 -0.128989 -0.881566 0.472061 0.000000 -0.264108 0.820266 -0.507356 -0.152132 0.742601 -0.652227 0.007253 0.79225 -0.610153 -0.066029 0.875025 -0.479553 -0.396445 0.854907 -0.334613 -0.267633 0.902223 -0.338181 -0.248438 0.677305 -0.692486 0.977768 0.125084 -0.168297 0.889836 -0.454721 0.037678 0.887461 -0.460883 0 0.98167 0.190588 0 0.519694 -0.845526 0.122488 0.513938 -0.857827 0 0.908572 -0.41696 0.025338 0.619301 -0.762269 0.188181 0.891559 -0.04355 -0.450805 0.912675 -0.27268 -0.304418 0.730533 -0.257173 -0.632601 0.714973 -0.230787 -0.659963 0.640102 -0.483706 -0.596907 0.545902 -0.366411 -0.753481 0.546117 -0.617917 -0.565628 0.546117 -0.617917 -0.565628 0.211683 -0.090848 -0.973107 -0.862214 -0.494633 -0.109206 -0.883528 -0.444655 -0.147174 -0.649155 -0.706663 -0.281468 -0.649155 -0.706663 -0.281468 0.008515 -0.008925 -0.999924 -0.945479 -0.324509 -0.027626 -0.95161 -0.299396 -0.069278 -0.960334 -0.228736 -0.159497 -0.932141 -0.361778 0.01514 -0.927227 -0.373821 0.022535 -0.940975 -0.338454 0.003941 -0.944159 -0.329453 0.004899 -0.955109 -0.29621 -0.005108 -0.959754 -0.280841 0 -0.344836 0.938663 0 -0.344787 0.922718 -0.172376 -0.337968 0.871069 -0.356393 -0.296912 0.760997 -0.576825 0.962089 0.272736 0 0.93493 0.242494 -0.259042 0.768191 0.076779 -0.6356 0.978552 0.206001 0 0.954189 0.187994 -0.232769 0.850781 0.044501 -0.523632 0.5799 0.052351 -0.813004 0.5799 0.052351 -0.813004 0.653963 -0.102945 -0.74949 0.650352 -0.189217 -0.735689 0.641769 -0.274043 -0.716263 0.496722 -0.667782 -0.554377 0.496722 -0.667782 -0.554377 0.496722 -0.667782 -0.554377 0.496722 -0.667782 -0.554377 -0.830692 -0.5294 -0.172299 -0.830692 -0.5294 -0.172299 -0.893987 -0.440713 -0.080995 -0.939472 -0.342575 0.005973 -0.938317 -0.345634 0.009895 0.943067 -0.130105 -0.306099 0.868352 -0.302845 -0.392747 0.816377 -0.221098 -0.533521 0.978998 0.088926 -0.18345 0.978406 -0.206692 0 0.922033 -0.387111 0 0.997057 0.076663 0 -0.939051 -0.343779 0.000515 -0.939184 -0.343414 0 -0.939693 -0.34202 0.000000 -0.939693 -0.342019 0 -0.938706 -0.344717 0.001492 -0.939692 -0.342021 0.000000 -0.938285 -0.345843 0.003871 -0.939693 -0.34202 -0.000000 0.498053 0.803662 0.325684 0.557123 0.69709 0.451309 0.55666 0.697952 0.450548 0.496917 0.804748 0.324738 0.501426 0.800401 0.328528 0.562945 0.715655 0.413438 0.558056 0.695336 0.452859 0.500307 0.801489 0.32758 0.321475 0.940816 -0.107321 0.423193 0.875935 0.231615 0.350243 0.932882 -0.084033 0.340744 0.93566 -0.091833 0.084483 0.677319 -0.730823 0.157482 0.881138 -0.445864 0.047203 0.677798 -0.733732 0.138935 0.736215 -0.662333 0.130575 0.707089 -0.694964 -0.069511 0.382022 -0.921535 -0.069511 0.382022 -0.921535 0.033817 0.508046 -0.860666 0.033817 0.508046 -0.860666 -0.36605 0.611517 -0.701466 -0.40861 0.582063 -0.703023 -0.40861 0.582063 -0.703023 -0.318616 0.603822 -0.730672 -0.571008 0.609082 -0.550427 -0.824931 0.496082 -0.270909 -0.709105 0.559505 -0.429098 -0.491823 0.616373 -0.614975 -0.248443 0.665327 -0.704 -0.24261 0.66656 -0.704867 -0.243882 0.670086 -0.701075 -0.249078 0.66709 -0.702105 0.477967 0.819902 0.315131 0.477576 0.820678 0.313702 0.552941 0.671785 0.492911 0.479193 0.817477 0.319539 0.478775 0.818302 0.31805 0.380088 0.92495 0.000000 0.379688 0.925115 0.000000 0.381403 0.924409 -0.000000 0.380946 0.924597 0 -0.342009 0.939697 0 -0.338793 0.930867 -0.136771 -0.338784 0.93087 -0.136772 -0.341995 0.939702 0 -0.34204 0.939685 0.000000 -0.338824 0.930855 -0.136772 -0.338813 0.930859 -0.136771 -0.342031 0.939689 0 -0.321322 0.882855 -0.34252 -0.321313 0.882858 -0.342519 -0.321338 0.882848 -0.342521 -0.321334 0.88285 -0.342521 -0.278814 0.766037 -0.57918 -0.278807 0.766044 -0.579175 -0.278809 0.76604 -0.579178 -0.278815 0.766036 -0.579182 -0.563169 0.59917 -0.569066 0.032394 0.369551 -0.928646 0.032394 0.369551 -0.928646 0.227734 -0.625296 -0.74642 0.009523 -0.390135 -0.920709 0.070866 -0.364444 -0.928525 0.233388 -0.640431 -0.731695 0.338322 -0.929544 -0.146579 0.241349 -0.957044 -0.160677 0.212351 -0.783141 -0.584464 -0.259273 -0.642256 -0.721307 -0.120369 -0.481356 -0.868221 0.210322 -0.660264 -0.720983 0.336117 -0.923497 -0.184875 0.235089 -0.908055 -0.346654 0.30665 -0.842525 -0.442852 0.431327 -0.889911 -0.148381 0.338327 -0.929542 -0.14658 0.287602 -0.79018 -0.541203 0.354888 -0.760917 -0.543194 0.273466 -0.659274 -0.70041 0.249676 -0.685699 -0.683725 0.408726 -0.854966 -0.319338 0.324402 -0.89129 -0.316804 0.241596 -0.651213 -0.719411 -0.975296 -0.063957 -0.211442 -0.980671 -0.169326 -0.098047 -0.932995 -0.339584 -0.119178 -0.956262 -0.13157 -0.261252 -0.926758 -0.337315 -0.165341 -0.871962 0.085321 -0.482081 -0.859323 -0.01228 -0.511286 -0.818477 -0.2979 -0.491275 -0.732153 0.264977 -0.627487 -0.688925 0.15459 -0.708155 -0.561815 0.595976 -0.573739 -0.449247 0.323427 -0.83281 -0.425114 0.740153 -0.52101 -0.302865 0.400265 -0.864905 0.939694 0.342017 0.000000 0.939693 0.342019 0.000000 0.939693 0.34202 0.000001 0.939693 0.342018 0.000004 0.939692 0.342023 0.000004 0.939692 0.342023 0.00001 0.939692 0.342022 0.000000 0.939691 0.342024 0.000001 0.939692 0.342023 0.000001 0.939691 0.342026 0.000003 0.939692 0.342023 0.000000 0.93969 0.342026 0.000001 0.939692 0.342023 -0.000000 0.939691 0.342025 0.000000 0.337795 -0.926781 -0.164233 0.322206 -0.878715 -0.352197 0.281111 -0.75735 -0.589405 -0.921792 -0.212523 -0.324242 -0.747455 -0.059224 -0.661667 -0.945447 -0.142712 -0.292853 -0.825623 -0.012411 -0.564086 -0.706372 0.097525 -0.70109 -0.625714 0.019086 -0.779819 -0.665497 0.092603 -0.740633 -0.621662 0.283322 -0.73025 -0.541873 0.532711 -0.650072 -0.421449 0.742152 -0.521145 0.939692 0.342021 0.000002 0.939692 0.342021 0.000001 0.939692 0.342021 0.000000 0.939692 0.342021 -0.000000 -0.920658 0.197718 -0.336596 -0.845881 0.349664 -0.402766 -0.972331 -0.01437 -0.233167 0.939694 0.342018 -0.000000 0.939695 0.342015 -0.000000 0.939694 0.342018 -0.000000 0.939694 0.342016 -0.000000 0.939693 0.342019 -0.000000 0.939693 0.342019 0 0.211752 0.211768 0.954104 -0.075065 0.605301 0.79245 0.01183 0.417438 0.908629 0.169819 0.095817 0.980806 -0.240442 0.957258 0.160762 -0.336569 0.930184 0.146557 0.415919 0.48311 0.770465 -0.215149 0.783801 0.582552 -0.180729 0.657456 0.731498 0.220661 0.382544 0.8972 -0.236506 0.908049 0.345704 -0.327149 0.89119 0.314252 -0.884074 0.449195 0.128989 -0.443963 0.879055 0.173663 -0.264108 0.820266 0.507356 -0.06603 0.875026 0.479552 0.007252 0.79225 0.610154 -0.152132 0.7426 0.652227 -0.267633 0.902223 0.338181 -0.396445 0.854907 0.334612 -0.248438 0.677305 0.692486 0.977768 0.125084 0.168297 0.889836 -0.454722 -0.037677 0.519693 -0.845527 -0.122488 0.908571 -0.416961 -0.025338 0.6193 -0.762271 -0.18818 0.891559 -0.043549 0.450805 0.912675 -0.27268 0.304418 0.730533 -0.257173 0.632601 0.714972 -0.230786 0.659964 0.640103 -0.483705 0.596907 0.545902 -0.36641 0.753481 0.546119 -0.617914 0.565629 0.546119 -0.617914 0.565629 0.211682 -0.090848 0.973107 -0.862212 -0.494635 0.109206 -0.649152 -0.706667 0.281467 -0.649152 -0.706667 0.281467 -0.883527 -0.444657 0.147174 0.00851 -0.008925 0.999924 -0.945479 -0.32451 0.027626 -0.960333 -0.228738 0.159497 -0.95161 -0.299397 0.069278 -0.932142 -0.361777 -0.01514 -0.927228 -0.373819 -0.022535 -0.940975 -0.338454 -0.003941 -0.944159 -0.329453 -0.004899 -0.955109 -0.296211 0.005108 -0.344787 0.922718 0.172376 -0.337968 0.871069 0.356393 -0.296912 0.760997 0.576825 0.93493 0.242494 0.259042 0.768191 0.076779 0.6356 0.954189 0.187994 0.232769 0.850781 0.0445 0.523633 0.5799 0.052351 0.813004 0.5799 0.052351 0.813004 0.650352 -0.189217 0.735689 0.653963 -0.102945 0.74949 0.641769 -0.274042 0.716263 0.496723 -0.667782 0.554377 0.496723 -0.667782 0.554377 0.496723 -0.667782 0.554377 0.496723 -0.667782 0.554377 -0.830688 -0.529405 0.172299 -0.893986 -0.440715 0.080995 -0.830688 -0.529405 0.172299 -0.938317 -0.345634 -0.009895 -0.939472 -0.342574 -0.005972 0.943067 -0.130105 0.306099 0.816377 -0.221099 0.533521 0.868352 -0.302845 0.392747 0.978998 0.088926 0.183451 -0.939051 -0.343779 -0.000515 -0.939693 -0.342019 -0.000000 -0.938706 -0.344717 -0.001492 -0.939692 -0.342021 -0.000000 -0.938285 -0.345843 -0.003871 -0.939693 -0.34202 0.000000 0.498054 0.803661 -0.325684 0.49692 0.804746 -0.324737 0.556663 0.697949 -0.450548 0.557125 0.697089 -0.451309 0.501424 0.800402 -0.328527 0.500307 0.801489 -0.327579 0.558056 0.695337 -0.452858 0.562944 0.715656 -0.413438 0.321477 0.940816 0.107321 0.423198 0.875932 -0.231616 0.350241 0.932882 0.084036 0.340743 0.93566 0.091835 0.084483 0.67732 0.730822 0.047203 0.6778 0.733729 0.15748 0.88114 0.445862 0.138934 0.736215 0.662333 0.130575 0.707089 0.694965 -0.069509 0.382025 0.921534 -0.069509 0.382025 0.921534 0.033815 0.508049 0.860664 0.033815 0.508049 0.860664 -0.366049 0.611517 0.701466 -0.318616 0.60382 0.730675 -0.408605 0.582064 0.703024 -0.408605 0.582064 0.703024 -0.571009 0.609078 0.55043 -0.491823 0.616372 0.614976 -0.709104 0.559506 0.429097 -0.82493 0.496083 0.270909 -0.248442 0.665327 0.704001 -0.242609 0.666558 0.704869 -0.243884 0.670082 0.701078 -0.249078 0.667089 0.702105 0.477579 0.820676 -0.313703 0.477968 0.819902 -0.315132 0.55294 0.671787 -0.492909 0.478774 0.818303 -0.31805 0.479193 0.817477 -0.319538 -0.338781 0.930871 0.13677 -0.338792 0.930867 0.13677 -0.338813 0.930859 0.136771 -0.338824 0.930855 0.136773 -0.321311 0.88286 0.342517 -0.321321 0.882855 0.342519 -0.321334 0.88285 0.342521 -0.321338 0.882848 0.342521 -0.278804 0.766045 0.579175 -0.278813 0.766038 0.57918 -0.278815 0.766036 0.579181 -0.278809 0.766041 0.579178 -0.563169 0.599172 0.569064 0.032394 0.369551 0.928646 0.032394 0.369551 0.928646 -0.954244 -0.298978 -0.005498 -0.953065 -0.302088 -0.020269 -0.981689 -0.187837 -0.031672 -0.982009 -0.188496 -0.011332 -0.977004 -0.213145 -0.005778 -0.955206 -0.295798 0.009286 -0.925668 -0.37811 -0.01308 -0.925837 -0.377145 -0.024234 -0.925383 -0.379027 -0.001926 -0.985081 -0.172092 0 -0.978977 -0.20397 0 -0.995412 -0.095326 -0.008238 -0.99534 -0.096424 0 -0.994952 -0.094176 -0.034658 0.98576 0.083428 -0.146005 0.977772 0.15179 -0.144647 0.90861 0.068662 -0.411964 0.959949 0.05078 -0.275536 0.955051 0.249322 -0.160364 0.830891 0.096614 -0.547984 0.920504 0.350687 -0.172311 0.745638 0.235188 -0.623466 0.115486 -0.362167 -0.924932 0.155519 -0.670364 -0.725552 0.115502 -0.678935 -0.725056 0.088475 -0.37226 -0.923902 0.207393 -0.978258 0.000000 0.15368 -0.988121 0.000000 0.04739 -0.108799 -0.992933 0.03768 -0.114001 -0.992766 0.027961 -0.119192 -0.992477 0.061398 -0.382041 -0.922103 0.075324 -0.686363 -0.723348 0.099502 -0.995037 0.000000 -0.926496 -0.375135 0.029629 -0.926496 -0.375135 0.029629 -0.933207 -0.357259 0.038615 -0.933207 -0.357259 0.038615 -0.973898 -0.221359 0.050229 -0.973898 -0.221359 0.050229 -0.973898 -0.221359 0.050229 -0.973898 -0.221359 0.050229 -0.99366 -0.111532 -0.014136 -0.99366 -0.111532 -0.014136 -0.993759 -0.111546 0 -0.993759 -0.111546 0 -0.026056 -0.278751 -0.96001 0.546568 -0.19997 -0.813188 0.504188 0.075613 -0.860277 -0.062257 -0.161531 -0.984902 -0.045724 -0.544969 -0.837209 0.741546 -0.333882 -0.581921 -0.045724 -0.544969 -0.837209 -0.066704 -0.811752 -0.580181 -0.066704 -0.811752 -0.580181 -0.066704 -0.811752 -0.580181 -0.066704 -0.811752 -0.580181 0.912147 0.362732 0.190823 0.90102 0.386253 0.197412 0.940179 0.295975 0.16871 0.943609 -0.263678 -0.200188 0.967429 0.253142 0.000000 0.804177 0.437402 0.402466 0.813745 0.392461 0.428712 0.816866 0.464239 0.342363 0.864447 0.502725 0.000000 0.951595 0.306339 0.024947 0.920181 0.383489 0.078757 0.962866 0.243125 -0.117383 0.926367 0.365689 -0.090082 0.973661 0.226114 0.029281 0.98005 0.173345 -0.097232 0.977169 0.212464 0 0.980886 0.194583 0 0.894238 0.058535 -0.443748 0.810648 0.063674 -0.582061 0.720435 0.222991 -0.656695 0.93805 0.070159 -0.339322 0.988329 0.062743 -0.138814 0.986739 -0.006785 -0.162175 0.998408 0.056396 0 0.999796 -0.020215 0 0.146146 -0.974276 -0.171543 0.123689 -0.985219 -0.118507 0.52343 -0.808816 -0.268025 0.578913 -0.8151 0.021746 0.526745 -0.834493 -0.161743 0.8531 -0.515242 0.08214 0.8531 -0.515242 0.08214 0.493475 -0.782658 0.37938 0.260362 -0.828035 0.496558 0.156921 -0.519014 0.840238 0.165073 -0.536506 0.827594 0.11839 -0.94386 0.308402 0.173138 -0.553714 0.814509 -0.051963 -0.997426 0.049404 -0.731429 -0.681777 0.013852 -0.714002 -0.700117 0.006111 -0.695717 -0.718313 -0.001786 0.118952 -0.984865 -0.126059 0.293122 -0.831971 -0.471068 0.258847 -0.780904 -0.568495 0.273117 -0.893823 -0.355652 0.221137 -0.719472 -0.658376 -0.387588 -0.89973 0.200654 -0.387588 -0.89973 0.200654 0.325376 -0.733064 -0.597283 0.563981 -0.700194 -0.437783 0.75552 -0.60889 -0.24175 0.586345 -0.804005 0.098877 0.68903 -0.548773 0.473378 0.904177 -0.076922 0.420174 0.993431 -0.048912 0.10345 0.612484 -0.788812 0.051369 0.615831 -0.786471 0.04708 0.99589 -0.081033 -0.040456 0.776581 -0.249576 -0.578475 0.450729 -0.889908 -0.070052 0.312719 -0.763603 -0.564905 -0.920023 -0.390851 -0.028167 -0.920399 -0.390661 -0.015803 -0.920635 -0.39041 -0.003437 -0.007805 -0.003324 0.999964 -0.005598 -0.002391 0.999982 -0.005035 -0.00214 0.999985 -0.005857 -0.002481 0.99998 -0.001772 -0.000752 -0.999998 -0.001799 -0.000764 -0.999998 -0.001335 -0.000567 -0.999999 -0.001317 -0.00056 -0.999999 -0.919122 -0.3927 0.031653 -0.919122 -0.3927 0.031653 -0.919262 -0.392778 0.026142 -0.919262 -0.392778 0.026142 0.906068 0.393916 -0.154505 0.722286 0.314706 -0.615843 0.90492 0.3933 -0.162588 0.906068 0.393916 -0.154505 -0.000871 -0.000371 -1 -0.000862 -0.000367 -1 -0.00339 -0.001458 0.999993 -0.003649 -0.001548 0.999992 -0.084544 -0.048968 -0.995216 -0.091016 -0.045375 -0.994815 0.432195 0.26086 -0.863226 0.398638 0.31888 -0.859886 0.855966 0.475217 0.203693 0.727511 0.563292 -0.391702 0.581084 0.343561 0.737772 0.816593 0.378676 0.435639 0.913864 0.396111 0.089152 0.913458 0.396286 -0.092479 0.689846 0.300453 -0.658666 0.361532 0.158514 -0.918786 -0.954244 -0.298979 0.005498 -0.982009 -0.188496 0.011332 -0.981689 -0.187837 0.031672 -0.953064 -0.302088 0.020269 -0.977003 -0.213145 0.005778 -0.955205 -0.295798 -0.009286 -0.925837 -0.377146 0.024233 -0.925668 -0.37811 0.01308 -0.925383 -0.379027 0.001926 -0.995412 -0.095325 0.008238 -0.994952 -0.094175 0.034658 0.98576 0.083428 0.146005 0.959949 0.050781 0.275536 0.90861 0.068661 0.411963 0.977772 0.15179 0.144647 0.830891 0.096613 0.547984 0.955051 0.249322 0.160365 0.745638 0.235188 0.623466 0.920504 0.350687 0.172312 0.115485 -0.362168 0.924931 0.088474 -0.372261 0.923901 0.115502 -0.678935 0.725056 0.155519 -0.670365 0.725551 0.047388 -0.1088 0.992934 0.03768 -0.114001 0.992766 0.027962 -0.119191 0.992477 0.061398 -0.382041 0.922103 0.075324 -0.686363 0.723348 -0.926496 -0.375136 -0.029629 -0.933206 -0.357261 -0.038615 -0.933206 -0.357261 -0.038615 -0.926496 -0.375136 -0.029629 -0.973898 -0.22136 -0.050229 -0.973898 -0.22136 -0.050229 -0.973898 -0.22136 -0.050229 -0.973898 -0.22136 -0.050229 -0.99366 -0.111538 0.014136 -0.99366 -0.111538 0.014136 -0.026055 -0.27875 0.96001 -0.062256 -0.16153 0.984902 0.504188 0.075613 0.860277 0.546568 -0.19997 0.813188 -0.045724 -0.54497 0.837208 -0.045724 -0.54497 0.837208 0.741546 -0.333882 0.581921 -0.066704 -0.811751 0.580182 -0.066704 -0.811751 0.580182 -0.066704 -0.811751 0.580182 -0.066704 -0.811751 0.580182 0.90102 0.386254 -0.197411 0.912147 0.362733 -0.190823 0.940178 0.295975 -0.16871 0.943609 -0.263678 0.200188 0.804177 0.437402 -0.402466 0.813745 0.39246 -0.428712 0.816865 0.46424 -0.342363 0.920182 0.383488 -0.078757 0.951596 0.306339 -0.024947 0.926367 0.365689 0.090082 0.962866 0.243125 0.117383 0.973661 0.226115 -0.029281 0.98005 0.173345 0.097232 0.810648 0.063673 0.582061 0.894238 0.058535 0.443748 0.720435 0.222991 0.656695 0.93805 0.07016 0.339322 0.986739 -0.006785 0.162175 0.988329 0.062743 0.138814 0.146147 -0.974276 0.171543 0.578912 -0.8151 -0.021745 0.523431 -0.808816 0.268025 0.123691 -0.985219 0.118508 0.526747 -0.834492 0.161742 0.493477 -0.782656 -0.37938 0.853104 -0.515235 -0.08214 0.853104 -0.515235 -0.08214 0.260361 -0.828037 -0.496555 0.165073 -0.536509 -0.827592 0.156922 -0.519014 -0.840238 0.118388 -0.943861 -0.308399 0.173136 -0.553718 -0.814506 -0.051964 -0.997426 -0.049403 -0.714002 -0.700116 -0.006111 -0.73143 -0.681776 -0.013851 0.118953 -0.984865 0.126061 -0.695717 -0.718314 0.001785 0.273117 -0.893822 0.355653 0.258848 -0.780903 0.568497 0.293123 -0.831968 0.471072 0.221137 -0.719472 0.658376 -0.387584 -0.899732 -0.200651 -0.387584 -0.899732 -0.200651 0.563981 -0.700193 0.437785 0.325378 -0.733064 0.597282 0.755519 -0.608889 0.241753 0.586343 -0.804006 -0.098876 0.904177 -0.076926 -0.420174 0.689029 -0.548775 -0.473376 0.612483 -0.788813 -0.051368 0.993431 -0.048915 -0.10345 0.615829 -0.786472 -0.04708 0.99589 -0.081036 0.040455 0.450727 -0.889909 0.070052 0.77658 -0.24958 0.578475 0.312719 -0.763605 0.564902 -0.920399 -0.390661 0.015803 -0.920023 -0.390851 0.028167 -0.920635 -0.39041 0.003437 -0.0078 -0.003324 -0.999964 -0.005854 -0.002481 -0.99998 -0.005032 -0.00214 -0.999985 -0.005595 -0.002391 -0.999982 -0.001776 -0.000753 0.999998 -0.001319 -0.00056 0.999999 -0.001336 -0.000568 0.999999 -0.001802 -0.000765 0.999998 -0.919122 -0.392699 -0.031651 -0.919262 -0.392778 -0.026141 -0.919262 -0.392778 -0.026141 -0.919122 -0.392699 -0.031651 0.90607 0.39391 0.154506 0.90607 0.39391 0.154506 0.904921 0.393297 0.162588 0.722287 0.314704 0.615844 -0.000861 -0.000367 1 -0.00087 -0.000371 1 -0.003389 -0.001458 -0.999993 -0.003648 -0.001548 -0.999992 -0.084544 -0.048968 0.995216 0.398638 0.31888 0.859886 0.432195 0.26086 0.863226 -0.091015 -0.045375 0.994815 0.855966 0.475217 -0.203693 0.727511 0.563293 0.3917 0.816593 0.378675 -0.435639 0.581084 0.34356 -0.737772 0.913865 0.39611 -0.089152 0.913458 0.396285 0.092479 0.689846 0.300453 0.658666 0.361531 0.158513 0.918787 -0.024708 0.087585 -0.995851 -0.024708 0.087585 -0.995851 -0.041507 0.242265 -0.969322 -0.041507 0.242265 -0.969322 -0.02091 0.187218 -0.982096 -0.02091 0.187218 -0.982096 -0.001772 0.032105 -0.999483 -0.001772 0.032105 -0.999483 -0.024708 0.087585 0.995851 -0.024708 0.087585 0.995851 -0.041507 0.242265 0.969322 -0.041507 0.242265 0.969322 -0.02091 0.187218 0.982096 -0.02091 0.187218 0.982096 -0.001772 0.032105 0.999483 -0.001772 0.032105 0.999483 -0.9986 -0.052647 -0.005071 -0.998615 -0.052621 0 -0.998213 -0.052652 -0.028264 0.000423 0.000022 1 0.000423 0.000022 1 0.977654 0.052384 -0.203589 0.987371 0.053072 -0.149271 0.986078 0.05244 -0.157797 0.998601 0.052887 0 0.986078 0.05244 0.157797 0.977654 0.052384 0.203589 0.987371 0.053072 0.149271 0.000423 0.000022 -1 0.000423 0.000022 -1 -0.9986 -0.052646 0.005071 -0.998213 -0.052651 0.028264 -0.480966 0.837282 0.260057 -0.49806 0.867143 0 -0.531904 0.846804 0 -0.528606 0.809061 0.256896 -0.253364 0.426929 0.868066 -0.459812 0.800523 0.384366 -0.521053 0.764754 0.37902 -0.426779 0.354501 0.831979 0.151499 -0.391106 0.907791 -0.040367 -0.460206 0.886894 0.322394 -0.877945 0.353942 0.274127 -0.742075 0.611702 0.148513 -0.782377 0.604838 0.236194 -0.905901 0.351504 0.343239 -0.939248 0 0.3399 -0.929133 0.145535 0.268933 -0.952235 0.144648 0.276809 -0.960925 0 -0.480966 0.837282 -0.260057 -0.528606 0.809061 -0.256895 0.151499 -0.391106 -0.907791 -0.040367 -0.460206 -0.886894 -0.426779 0.354501 -0.831979 -0.253364 0.426929 -0.868066 -0.521052 0.764754 -0.379019 -0.459812 0.800522 -0.384366 0.322394 -0.877945 -0.353942 0.236194 -0.905901 -0.351504 0.148513 -0.782377 -0.604839 0.274127 -0.742075 -0.611702 0.268933 -0.952235 -0.144648 0.3399 -0.929133 -0.145535 0.939694 0.342017 -0.000000 0.939694 0.342017 0 0.939696 0.342012 0 0.939695 0.342014 -0.000001 -0.943057 -0.332627 0.001655 -0.946325 -0.3232 0.003311 -0.946264 -0.323395 -0.000005 -0.943024 -0.332724 -0.000002 0.939693 0.342018 -0.000000 0.939694 0.342017 -0.000000 0.939693 0.342018 0.000000 0.939693 0.342018 0.000000 -0.939693 -0.34202 -0.000002 -0.782659 -0.492142 0.381105 -0.914102 -0.06403 0.400398 -0.983175 0.071644 0.168027 0.939693 0.34202 0.000000 0.939692 0.342021 0 -0.939692 -0.342021 -0.000000 -0.939693 -0.342021 0 0.939692 0.342023 -0.000000 0.939692 0.342022 -0.000000 0.939693 0.342019 0 0.939693 0.342019 0 -0.56053 -0.802487 0.204501 -0.64519 -0.693641 0.320301 -0.939693 -0.342018 -0.000002 -0.939694 -0.342016 -0.000001 0.939693 0.342019 0 0.939692 0.342021 0 0.939692 0.342022 -0.000000 0.939693 0.342018 0 -0.933166 -0.359445 -0.000024 -0.926317 -0.376744 -0.000048 -0.926317 -0.376743 0.001048 -0.933166 -0.359444 0.000523 -0.954438 0.234181 0.18495 -0.92231 -0.36092 0.138132 -0.903844 -0.394054 0.166696 -0.87358 -0.430955 0.226133 -0.939697 -0.342009 -0.000002 0.939694 0.342018 0.000000 0.939695 0.342014 0.000001 -0.942989 -0.332819 -0.001661 -0.946193 -0.323587 -0.003321 0.939693 0.342019 0.000000 0.939693 0.342019 -0.000000 0.939693 0.342019 -0.000000 0.939694 0.342017 0.000000 -0.939693 -0.34202 0.000002 -0.983176 0.071644 -0.168027 -0.914102 -0.06403 -0.400398 -0.782659 -0.492141 -0.381105 0.939693 0.34202 -0.000000 -0.939693 -0.34202 0.000000 0.939692 0.342023 0.000001 0.939693 0.34202 0 0.939693 0.34202 0 0.939692 0.342021 0.000000 -0.56053 -0.802487 -0.204501 -0.939694 -0.342016 0.000001 -0.939693 -0.342018 0.000001 -0.64519 -0.693641 -0.320301 0.939692 0.342022 0.000000 0.939693 0.342021 0 -0.933166 -0.359446 -0.000571 -0.926316 -0.376745 -0.001144 -0.92231 -0.360922 -0.138132 -0.926615 -0.351647 -0.133148 -0.87358 -0.430956 -0.226131 -0.903844 -0.394054 -0.166696 -0.856894 -0.443764 -0.26231 -0.704425 0.18807 0.684408 -0.691549 0.631425 0.350803 -0.684447 0.688553 0.239642 -0.67204 0.740515 0 -0.684446 0.688553 -0.239642 -0.691549 0.631425 -0.350803 -0.704425 0.18807 -0.684408 -0.351262 -0.532971 -0.769777 -0.064503 -0.820875 -0.567454 0.099111 -0.935149 -0.340106 0.163267 -0.976467 -0.14091 0.180309 -0.98361 0 0.163267 -0.976467 0.140911 0.099111 -0.935149 0.340107 -0.064503 -0.820875 0.567454 -0.351262 -0.532971 0.769778 -0.809839 0.547077 0.211822 -0.78758 0.616212 0 -0.746709 0.66515 -0.001284 -0.809839 0.547077 -0.211822 -0.837489 0.507896 -0.201629 -0.808815 0.498136 -0.312536 -0.802842 0.102846 -0.587253 -0.463594 -0.546836 -0.697174 -0.142368 -0.827323 -0.543386 0.047994 -0.94253 -0.330657 0.127675 -0.982349 -0.136713 0.125475 -0.982907 -0.134722 0.159595 -0.987183 0 0.167743 -0.985831 0 0.127675 -0.982349 0.136713 0.167601 -0.985 0.041036 0.082023 -0.970438 0.226985 0.047994 -0.94253 0.330657 -0.142368 -0.827323 0.543386 -0.463594 -0.546836 0.697174 -0.802842 0.102846 0.587254 -0.808815 0.498136 0.312536 -0.441344 0.879306 0.178987 -0.441353 0.879319 0.1789 -0.448576 0.893735 -0.00411 -0.448573 0.893737 -0.004108 -0.441363 0.879332 0.178814 -0.569318 0.82211 -0.003368 -0.683701 0.714934 0.146365 -0.440657 0.877986 -0.186983 -0.440648 0.877973 -0.187064 -0.553786 0.814991 -0.17062 -0.657474 0.738102 -0.151434 0.046838 -0.087969 -0.995021 0.045997 -0.086328 -0.995204 0.069903 -0.132958 -0.988653 0.07032 -0.133774 -0.988514 -0.538188 -0.277796 -0.795728 -0.515542 -0.318345 -0.795533 0.134397 -0.257291 -0.956943 0.134397 -0.257292 -0.956942 -0.435259 -0.426428 -0.792912 0.169617 -0.319329 -0.93234 0.167277 -0.314969 -0.934245 -0.340805 -0.481179 -0.807662 0.387152 -0.70491 -0.594319 0.385651 -0.702063 -0.598649 0.169817 -0.314088 -0.934083 -0.700383 -0.507348 -0.502058 0.483355 -0.875421 -0.002526 0.483351 -0.875423 -0.002516 0.4688 -0.881747 -0.052429 0.466729 -0.884399 -0.001751 0.454864 -0.889242 -0.048443 0.449937 -0.89306 -0.000966 0.387859 -0.706274 0.592235 0.386368 -0.70344 0.596567 0.463453 -0.884769 0.048937 0.443979 -0.894829 0.046513 0.169637 -0.319384 0.932318 0.167306 -0.315038 0.934216 0.16984 -0.314171 0.934051 -0.340797 -0.481201 0.807653 -0.70038 -0.507343 0.502066 -0.70038 -0.507343 0.502066 0.134397 -0.25729 0.956943 0.134397 -0.257291 0.956942 -0.435259 -0.426428 0.792912 0.069901 -0.132955 0.988654 0.070317 -0.13377 0.988514 -0.515543 -0.318342 0.795534 0.045992 -0.086322 0.995205 0.046832 -0.087962 0.995022 0.045152 -0.084682 0.995385 -0.896869 -0.354938 0.263902 0.175657 -0.984451 0 0.164175 -0.952907 0.254979 -0.025168 -0.969969 0.241922 -0.014275 -0.999898 0 0.130512 -0.860425 0.49258 -0.057105 -0.882222 0.467357 0.076966 -0.713307 0.696613 -0.107911 -0.742637 0.660943 0.007184 -0.521578 0.853173 -0.07408 -0.298305 0.951591 -0.251224 -0.348886 0.902865 -0.174121 -0.560726 0.809486 -0.161288 -0.058703 0.98516 -0.333966 -0.121554 0.934715 -0.248495 0.180897 0.951592 -0.416708 0.105778 0.902865 -0.32976 0.40417 0.853174 -0.493812 0.317618 0.809487 -0.203742 0.689424 0.695114 -0.559918 0.497823 0.662318 -0.356059 -0.913386 0.197351 -0.347173 -0.937801 0 -0.382112 -0.841806 0.381253 -0.423557 -0.727937 0.539172 -0.477569 -0.579541 0.660348 -0.540467 -0.40673 0.736523 -0.607965 -0.221281 0.762505 -0.675463 -0.035831 0.736523 -0.738361 0.136979 0.660348 -0.792373 0.285375 0.539172 -0.592116 -0.792642 0.145316 -0.585573 -0.81062 0 -0.6113 -0.739935 0.280728 -0.641817 -0.65609 0.397009 -0.681587 -0.546821 0.486236 -0.727901 -0.419576 0.542325 -0.777602 -0.283025 0.561456 -0.827303 -0.146472 0.542325 -0.873616 -0.019226 0.486235 -0.915667 0.094086 0.39077 -0.754897 -0.649038 0.094239 -0.750653 -0.660696 -0.000000 -0.767337 -0.614856 0.182057 -0.787128 -0.560482 0.257467 -0.81292 -0.489619 0.315332 -0.842955 -0.407099 0.351706 -0.875187 -0.318542 0.364113 -0.907419 -0.229986 0.351706 -0.937454 -0.147465 0.315331 -0.965367 -0.072125 0.250727 -0.866271 -0.497464 0.045866 -0.864206 -0.503139 -0.000000 -0.872326 -0.480828 0.08861 -0.881959 -0.454363 0.125314 -0.894512 -0.419872 0.153477 -0.909131 -0.379707 0.171182 -0.924819 -0.336605 0.17722 -0.940506 -0.293504 0.171181 -0.955125 -0.25334 0.153476 -0.967842 -0.218315 0.124978 -0.812566 0.350318 0.465847 -0.586876 0.574669 0.570379 -0.928547 0.120082 0.351255 -0.978318 -0.066908 0.196002 -0.970706 -0.084444 0.224944 -0.992417 -0.097222 0.075208 -0.993042 -0.091644 0.073954 -0.996929 -0.078308 0 -0.996929 -0.07831 0 -0.429665 0.673924 0.601011 -0.219695 0.603178 -0.766753 -0.208357 0.571898 -0.793423 -0.208507 0.57175 -0.79349 -0.208436 0.57182 -0.793459 -0.511307 0.859398 0 -0.342016 0.939694 0.000000 -0.336626 0.924888 -0.176819 -0.504482 0.850735 -0.14747 -0.427034 0.743586 -0.514511 -0.270009 0.741845 -0.613809 -0.226018 0.620982 -0.750532 -0.313604 0.670313 -0.672557 -0.317307 0.871798 -0.373207 -0.482099 0.820329 -0.307637 -0.977366 -0.191445 0.090028 -0.983352 -0.175361 0.047626 -0.985431 -0.170074 0 -0.588303 0.575536 0.568031 -0.812566 0.350317 0.465848 -0.923823 0.093177 0.371307 -0.435113 0.672739 0.598414 -0.461071 0.738394 0.492126 -0.452961 0.742886 0.492897 -0.486331 0.835737 0.255 -0.494449 0.831091 0.254574 -0.444811 0.747314 0.493625 -0.47817 0.840311 0.255403 -0.497814 0.867284 0 -0.505914 0.862584 0 -0.48967 0.871908 0 -0.435918 0.671295 0.599449 -0.427985 0.675624 0.600302 -0.207214 0.766163 0.608322 -0.939693 -0.34202 0.000000 -0.939693 -0.34202 0.000000 -0.939692 -0.342022 0 -0.939692 -0.342021 0 -0.939693 -0.342019 0.000000 -0.939694 -0.342017 0.000000 -0.939692 -0.342021 0.000000 -0.939694 -0.342018 0.000001 -0.342021 0.939692 -0.000000 -0.160692 0.987005 0 -0.159652 0.972391 -0.170196 -0.336631 0.924886 -0.17682 -0.270006 0.741846 -0.613808 -0.145209 0.784997 -0.602242 -0.185387 0.67071 -0.718178 -0.226097 0.620906 -0.750571 -0.156151 0.919375 -0.361064 -0.317307 0.871799 -0.373207 -0.939693 -0.34202 -0.000000 -0.939693 -0.34202 0 -0.939692 -0.342021 0.000000 -0.939692 -0.342022 0.000002 -0.939693 -0.342019 0.000001 -0.939692 -0.342021 0.000000 -0.279325 0.729583 -0.624248 -0.939692 -0.342021 -0.000000 -0.939692 -0.342022 0.000000 -0.93969 -0.342026 0.000001 -0.939692 -0.342023 0.000000 -0.939693 -0.34202 0 -0.939693 -0.34202 0 -0.939691 -0.342024 0.000003 -0.939692 -0.342022 0.000002 -0.939692 -0.342022 0.000001 -0.939693 -0.34202 -0.000000 -0.939693 -0.34202 0 -0.307512 0.802438 -0.511399 -0.602985 0.728678 -0.324713 0.009193 0.940845 -0.338713 -0.649812 0.747553 -0.137512 -0.654804 0.747295 -0.113057 0.022631 0.987203 -0.157855 -0.661987 0.749515 0 0.026011 0.999662 0 -0.025168 -0.969969 -0.241922 0.164175 -0.952908 -0.254978 -0.057105 -0.882222 -0.467357 0.130513 -0.860425 -0.492579 -0.107911 -0.742637 -0.660943 0.076966 -0.713307 -0.696613 -0.174121 -0.560726 -0.809486 0.007184 -0.521578 -0.853173 -0.251224 -0.348886 -0.902865 -0.07408 -0.298305 -0.951591 -0.333966 -0.121554 -0.934714 -0.161288 -0.058703 -0.98516 -0.416708 0.105778 -0.902865 -0.248495 0.180897 -0.951592 -0.493812 0.317618 -0.809487 -0.32976 0.40417 -0.853174 -0.559918 0.497823 -0.662318 -0.407414 0.622996 -0.667749 -0.356059 -0.913386 -0.197351 -0.382112 -0.841806 -0.381253 -0.423557 -0.727937 -0.539172 -0.477569 -0.579541 -0.660348 -0.540467 -0.40673 -0.736523 -0.607965 -0.221281 -0.762505 -0.675463 -0.035832 -0.736523 -0.738361 0.136979 -0.660349 -0.792373 0.285375 -0.539172 -0.592116 -0.792642 -0.145316 -0.6113 -0.739935 -0.280728 -0.641817 -0.656091 -0.397009 -0.681587 -0.546822 -0.486235 -0.727901 -0.419576 -0.542325 -0.777601 -0.283025 -0.561456 -0.827303 -0.146472 -0.542325 -0.873616 -0.019226 -0.486236 -0.915667 0.094086 -0.39077 -0.754897 -0.649038 -0.094239 -0.767337 -0.614857 -0.182057 -0.787128 -0.560482 -0.257467 -0.81292 -0.489619 -0.315332 -0.842955 -0.407099 -0.351706 -0.875187 -0.318543 -0.364113 -0.907419 -0.229986 -0.351706 -0.937454 -0.147465 -0.315331 -0.965367 -0.072125 -0.250727 -0.866271 -0.497464 -0.045867 -0.872326 -0.480829 -0.08861 -0.881959 -0.454363 -0.125313 -0.894512 -0.419873 -0.153478 -0.909131 -0.379708 -0.171182 -0.924819 -0.336605 -0.17722 -0.940506 -0.293505 -0.171181 -0.955125 -0.25334 -0.153477 -0.967843 -0.218314 -0.124978 -0.812566 0.350317 -0.465848 -0.586876 0.574669 -0.570379 -0.928547 0.120083 -0.351255 -0.978318 -0.066908 -0.196002 -0.993042 -0.091645 -0.073954 -0.992417 -0.097223 -0.075208 -0.970706 -0.084446 -0.224944 -0.429665 0.673924 -0.601011 -0.219695 0.603178 0.766753 -0.208436 0.57182 0.793459 -0.208507 0.57175 0.79349 -0.208357 0.571898 0.793423 -0.504482 0.850735 0.14747 -0.336626 0.924888 0.176819 -0.427034 0.743586 0.514511 -0.313604 0.670313 0.672557 -0.226018 0.620982 0.750532 -0.27001 0.741845 0.613809 -0.482099 0.820329 0.307637 -0.317307 0.871798 0.373207 -0.977366 -0.191445 -0.090028 -0.983352 -0.175361 -0.047626 -0.812566 0.350318 -0.465848 -0.588303 0.575535 -0.568031 -0.923823 0.093177 -0.371307 -0.435114 0.672738 -0.598414 -0.461071 0.738394 -0.492126 -0.494449 0.831091 -0.254574 -0.486331 0.835738 -0.255 -0.452961 0.742886 -0.492897 -0.47817 0.840311 -0.255403 -0.194789 0.850499 -0.488578 -0.427985 0.675624 -0.600301 -0.435918 0.671295 -0.599449 -0.207214 0.766164 -0.608322 -0.939692 -0.342021 -0.000000 -0.939692 -0.342021 -0.000000 -0.939693 -0.34202 -0.000000 -0.939693 -0.342019 -0.000000 -0.939692 -0.342022 -0.000000 -0.939692 -0.342021 -0.000001 -0.336631 0.924886 0.17682 -0.159652 0.972391 0.170196 -0.270006 0.741846 0.613808 -0.226097 0.620906 0.750571 -0.185387 0.67071 0.718178 -0.145209 0.784997 0.602242 -0.317307 0.871799 0.373207 -0.156151 0.919375 0.361064 -0.939693 -0.34202 0.000000 -0.939692 -0.342021 -0.000000 -0.939692 -0.342021 -0.000002 -0.939692 -0.342023 -0.000001 -0.939691 -0.342024 -0.000000 -0.279325 0.729583 0.624248 -0.939692 -0.342021 0 -0.939692 -0.342022 -0.000000 -0.939691 -0.342025 -0.000001 -0.939692 -0.342022 -0.000000 -0.939692 -0.342021 -0.000002 -0.939692 -0.342023 -0.000003 -0.939692 -0.342021 -0.000001 -0.939693 -0.34202 0.000000 -0.602984 0.728678 0.324713 -0.307512 0.802438 0.511399 0.009193 0.940845 0.338713 -0.654804 0.747295 0.113057 -0.649812 0.747553 0.137512 0.022631 0.987203 0.157855 -0.931551 -0.35769 -0.065353 -0.937542 -0.34123 -0.067659 -0.925969 -0.373024 -0.058595 -0.921176 -0.386195 -0.04784 -0.917498 -0.396299 -0.033828 -0.915188 -0.402648 -0.017506 -0.914398 -0.404817 -0.000000 -0.915187 -0.402649 0.017506 -0.917498 -0.396299 0.033828 -0.921176 -0.386194 0.047841 -0.92597 -0.373024 0.058594 -0.931551 -0.357689 0.065353 -0.937542 -0.34123 0.067659 -0.943529 -0.32478 0.065355 -0.94911 -0.309445 0.058594 -0.953904 -0.296274 0.047842 -0.957579 -0.286177 0.033835 -0.95989 -0.279827 0.017516 -0.960679 -0.27766 0.000000 -0.95989 -0.279828 -0.017516 -0.957579 -0.286177 -0.033835 -0.953904 -0.296273 -0.047842 -0.94911 -0.309445 -0.058594 -0.943529 -0.32478 -0.065355 -0.939693 -0.342019 0 0.179693 0.95797 0.223617 0.069688 0.891449 0.447731 0.069688 0.891449 0.447731 0.179693 0.95797 0.223617 0.016691 0.812011 0.583403 0.120136 0.728214 0.674738 0.213121 0.654765 0.725163 0.213121 0.654765 0.725163 0.401191 0.487576 0.775445 0.441105 0.390891 0.807855 0.441105 0.390891 0.807855 0.401191 0.487576 0.775445 0.516228 0.187892 0.835587 0.516228 0.187892 0.835587 0.590198 -0.015331 0.807113 0.590198 -0.015331 0.807113 0.659124 -0.204704 0.723638 0.659124 -0.204704 0.723638 0.718316 -0.367319 0.590846 0.718316 -0.367319 0.590846 0.763734 -0.4921 0.417789 0.763734 -0.4921 0.417789 0.79228 -0.570546 0.216265 0.79228 -0.570546 0.216265 0.802014 -0.597305 0 0.802014 -0.597305 0 0.79228 -0.570546 -0.216265 0.79228 -0.570546 -0.216265 0.763734 -0.4921 -0.417789 0.763734 -0.4921 -0.417789 0.718316 -0.367319 -0.590846 0.718316 -0.367319 -0.590846 0.659124 -0.204704 -0.723638 0.659124 -0.204704 -0.723638 0.590199 -0.015331 -0.807112 0.590199 -0.015331 -0.807112 0.516229 0.187892 -0.835586 0.516229 0.187892 -0.835586 0.441105 0.390891 -0.807855 0.441105 0.390891 -0.807855 0.309715 0.575931 -0.756558 0.309715 0.575931 -0.756558 0.120135 0.728214 -0.674738 0.120135 0.728214 -0.674738 0.016691 0.812012 -0.583402 0.069689 0.891449 -0.447731 0.129909 0.933408 -0.334474 0.129909 0.933408 -0.334474 0.226715 0.967806 -0.109323 0.228082 0.973642 0 0.228082 0.973642 0 0.226715 0.967806 -0.109323 -0.667311 -0.242882 0.704063 -0.473657 -0.172397 0.863671 -0.55002 0.037451 0.834311 -0.72956 -0.071811 0.680136 -0.617449 0.224418 0.753918 -0.784508 0.080754 0.614838 -0.670657 0.372153 0.641655 -0.827898 0.201412 0.523467 -0.705899 0.472088 0.528053 -0.85666 0.283357 0.431095 -0.735324 0.549774 0.396291 -0.880652 0.346313 0.323294 -0.759454 0.614352 0.214012 -0.900313 0.398721 0.174523 -0.769032 0.63921 0 -0.908101 0.41875 0 -0.759454 0.614351 -0.214012 -0.900314 0.398718 -0.174522 -0.735324 0.549774 -0.396292 -0.880652 0.346312 -0.323294 -0.705898 0.472088 -0.528053 -0.856659 0.283359 -0.431095 -0.670657 0.372154 -0.641655 -0.827898 0.201414 -0.523467 -0.617449 0.224418 -0.753918 -0.784509 0.080754 -0.614837 -0.55002 0.037451 -0.834311 -0.729561 -0.071811 -0.680135 -0.473656 -0.172397 -0.863672 -0.667311 -0.242882 -0.704062 -0.397204 -0.382451 -0.834242 -0.604988 -0.414118 -0.680071 -0.325961 -0.57819 -0.747961 -0.54691 -0.573683 -0.609735 -0.264782 -0.746275 -0.610708 -0.497037 -0.710705 -0.497848 -0.217839 -0.875251 -0.431836 -0.45877 -0.815846 -0.352032 -0.188328 -0.956329 -0.223535 -0.434712 -0.881941 -0.182225 -0.178262 -0.983983 0 -0.426504 -0.904486 0.000000 -0.188328 -0.956329 0.223535 -0.434711 -0.881941 0.182225 -0.21784 -0.87525 0.431836 -0.458769 -0.815846 0.352032 -0.264783 -0.746275 0.610708 -0.497036 -0.710706 0.497848 -0.325962 -0.57819 0.747961 -0.54691 -0.573683 0.609735 -0.397205 -0.382451 0.834242 -0.604988 -0.414117 0.680071 -0.11527 0.233084 -0.965601 -0.026874 -0.009781 -0.999591 0.06161 -0.252892 -0.965531 0.144064 -0.479435 -0.865671 0.214869 -0.673973 -0.706818 0.269201 -0.823247 -0.499796 0.303356 -0.917084 -0.258714 0.315004 -0.94909 0 0.303355 -0.917084 0.258714 0.2692 -0.823247 0.499796 0.214868 -0.673974 0.706818 0.144063 -0.479436 0.865671 0.061608 -0.252893 0.965531 -0.026877 -0.009782 0.999591 -0.115272 0.233084 0.9656 -0.193839 0.449076 0.872214 -0.255851 0.619572 0.742072 -0.297495 0.734223 0.610257 -0.330625 0.825005 0.458316 -0.358065 0.900267 0.247606 -0.368754 0.929527 0 -0.358064 0.900267 -0.247605 -0.330624 0.825006 -0.458316 -0.297494 0.734223 -0.610257 -0.255849 0.619573 -0.742072 -0.193837 0.449077 -0.872214 0.229744 0.716359 0.658822 0.191598 0.818167 0.54212 0.16338 0.898745 0.406895 0.139686 0.965503 0.219752 0.130769 0.991413 0 0.139687 0.965503 -0.219752 0.163381 0.898746 -0.406894 0.191598 0.818167 -0.542119 0.229744 0.71636 -0.658822 0.285358 0.565057 -0.774133 0.355685 0.373489 -0.856734 0.434128 0.15801 -0.886885 0.512636 -0.05769 -0.856665 0.585794 -0.25869 -0.768066 0.648617 -0.431293 -0.627122 0.696821 -0.563736 -0.443442 0.727123 -0.646994 -0.229543 0.737459 -0.675392 0 0.727123 -0.646994 0.229544 0.69682 -0.563737 0.443443 0.648616 -0.431293 0.627123 0.585793 -0.25869 0.768066 0.512634 -0.05769 0.856667 0.434126 0.158009 0.886886 0.355685 0.373489 0.856735 0.285358 0.565057 0.774133 0.398121 0.899252 0.181236 0.390932 0.92042 0 0.398122 0.899251 -0.181236 0.41748 0.844399 -0.335709 0.440438 0.778247 -0.4476 0.472225 0.693927 -0.54357 0.51824 0.569005 -0.638483 0.576366 0.41097 -0.706333 0.641041 0.23332 -0.731183 0.705765 0.055487 -0.706269 0.76608 -0.110224 -0.633223 0.817875 -0.252525 -0.517023 0.857615 -0.361717 -0.365591 0.882597 -0.43036 -0.189245 0.891118 -0.453772 0.000000 0.882597 -0.430358 0.189246 0.857614 -0.361717 0.365593 0.817873 -0.252525 0.517025 0.766079 -0.110223 0.633225 0.705763 0.055487 0.706272 0.64104 0.233319 0.731184 0.576368 0.410969 0.706332 0.518242 0.569004 0.638482 0.472227 0.693926 0.54357 0.440438 0.778246 0.447601 0.417479 0.8444 0.335709 0.331712 -0.911364 0.243685 0.342019 -0.939687 0.003531 0.342019 -0.939687 0.003531 0.331712 -0.911364 0.243685 0.087813 -0.241267 -0.966478 0.000116 -0.000321 -1 0.000116 -0.000321 -1 0.087813 -0.241267 -0.966478 -0.330145 0.90706 0.26124 -0.296319 0.814129 0.499389 -0.296319 0.814129 0.499389 -0.330145 0.90706 0.26124 -0.24177 0.664258 -0.707325 -0.295233 0.811147 -0.504855 -0.295233 0.811147 -0.504855 -0.24177 0.664258 -0.707325 0.08777 -0.241146 0.966512 0.164638 -0.45234 0.876517 0.164638 -0.45234 0.876517 0.08777 -0.241146 0.966512 0.22478 -0.617578 -0.753705 0.164044 -0.450708 -0.877469 0.164044 -0.450708 -0.877469 0.22478 -0.617578 -0.753705 -0.241841 0.664457 0.707114 -0.241841 0.664457 0.707114 0.331837 -0.911717 -0.24219 0.305633 -0.839719 -0.448844 0.305633 -0.839719 -0.448844 0.331837 -0.911717 -0.24219 0.222308 -0.610789 0.759945 0.269693 -0.740975 0.614997 0.269693 -0.740975 0.614997 0.222308 -0.610789 0.759945 0.307306 -0.844311 0.438979 0.307306 -0.844311 0.438979 -0.0895 0.245901 -0.965154 -0.171754 0.471891 -0.864765 -0.171754 0.471891 -0.864765 -0.0895 0.245901 -0.965154 -0.089148 0.244934 0.965433 -0.000319 0.000877 1 -0.000319 0.000877 1 -0.089148 0.244934 0.965433 -0.330212 0.907251 -0.260491 -0.330212 0.907251 -0.260491 0.269972 -0.741739 -0.613953 0.269972 -0.741739 -0.613953 -0.170915 0.469589 0.866184 -0.170915 0.469589 0.866184 -0.342017 0.939681 0.004987 -0.342017 0.939681 0.004987 0.872996 0.443828 0.202226 0.8931 0.388651 0.226546 0.919373 0.357841 0.163409 0.892487 0.431685 0.130822 0.836219 0.544825 0.062478 0.843885 0.523894 0.115728 0.874717 0.480483 0.063292 0.833441 0.552608 -0.000482 0.871024 0.49078 -0.021287 0.892174 0.391318 -0.2256 0.873687 0.441837 -0.203596 0.905123 0.396964 -0.15222 0.856401 0.489214 -0.165067 0.882108 0.460141 -0.100775 0.84462 0.521911 -0.119273 0.914227 0.33086 -0.233924 0.933875 0.317692 -0.16416 0.991386 0.117672 0.05751 0.993811 0.111073 -0.001466 0.983232 0.181344 -0.019199 0.980419 0.18877 0.056082 0.857282 0.487103 0.166729 0.985481 0.133392 -0.105043 0.976746 0.156608 -0.146432 0.975003 0.203603 -0.08897 0.965137 0.188646 0.18145 0.976846 0.156838 0.145513 0.967802 0.223375 0.116028 0.934486 0.274951 0.226137 0.950862 0.227127 0.210414 0.947202 0.280422 0.15547 0.912885 0.334385 0.234154 0.951997 0.226039 -0.206416 0.933224 0.277263 -0.228513 0.958687 0.248523 -0.138404 0.986082 0.13042 0.103116 0.836257 0.545144 -0.0591 0.991852 0.115055 -0.054696 0.965627 0.186625 -0.180927 0.92898 0.368287 0.036893 0.9281 0.372089 0.013412 0.926051 0.376329 -0.028384 0.934537 0.354403 -0.032217 0.952104 0.304821 -0.024148 0.950978 0.309235 -0.003683 0.953722 0.300321 0.014919 0.940569 0.336451 -0.046165 0.945667 0.323838 -0.029018 0.927302 0.374287 -0.004549 0.937543 0.346149 0.034559 0.947654 0.318405 0.023879 0.944194 0.326489 0.043624 0.939693 0.34202 -0.000000 -0.854491 0.392016 0.340836 -0.854491 0.392016 0.340836 -0.875237 0.447327 0.184009 -0.875237 0.447327 0.184009 -0.883466 0.468495 0.000000 -0.883466 0.468495 0.000000 -0.875238 0.447324 -0.184008 -0.875238 0.447324 -0.184008 -0.854491 0.392015 -0.340836 -0.854491 0.392015 -0.340836 -0.829169 0.325555 -0.454415 -0.829169 0.325555 -0.454415 -0.79887 0.239257 -0.551872 -0.79887 0.239257 -0.551872 -0.753134 0.11208 -0.648249 -0.753134 0.11208 -0.648249 -0.695204 -0.048761 -0.717156 -0.695204 -0.048761 -0.717156 -0.629566 -0.229143 -0.742388 -0.629566 -0.229143 -0.742388 -0.56385 -0.4097 -0.717091 -0.56385 -0.4097 -0.717091 -0.50261 -0.577951 -0.642927 -0.50261 -0.577951 -0.642927 -0.450025 -0.722432 -0.524948 -0.450025 -0.722432 -0.524948 -0.409673 -0.833296 -0.371194 -0.409673 -0.833296 -0.371194 -0.384304 -0.90299 -0.192144 -0.384304 -0.90299 -0.192144 -0.37565 -0.926762 0.000000 -0.37565 -0.926762 0.000000 -0.384303 -0.90299 0.192145 -0.384303 -0.90299 0.192145 -0.409674 -0.833297 0.371193 -0.409674 -0.833297 0.371193 -0.450027 -0.722432 0.524945 -0.450027 -0.722432 0.524945 -0.502612 -0.577951 0.642925 -0.502612 -0.577951 0.642925 -0.56385 -0.4097 0.717091 -0.56385 -0.4097 0.717091 -0.629567 -0.229144 0.742387 -0.629567 -0.229144 0.742387 -0.695207 -0.048763 0.717153 -0.695207 -0.048763 0.717153 -0.753139 0.112076 0.648245 -0.753139 0.112076 0.648245 -0.798872 0.239257 0.551869 -0.798872 0.239257 0.551869 -0.829169 0.325556 0.454413 -0.829169 0.325556 0.454413 -0.068251 0.678037 0.731852 0.112586 0.709294 0.695864 0.072565 0.816721 0.572452 -0.109849 0.790981 0.601899 0.042486 0.901936 0.429774 -0.141985 0.880644 0.452003 0.017303 0.972528 0.232142 -0.168753 0.954933 0.244185 0.007748 0.99997 0 -0.179043 0.983841 0.000000 0.017304 0.972528 -0.232142 -0.168751 0.954933 -0.244184 0.042488 0.901936 -0.429774 -0.141984 0.880644 -0.452003 0.072567 0.816721 -0.572452 -0.109847 0.790981 -0.601899 0.112589 0.709294 -0.695864 -0.068248 0.678038 -0.731852 0.171208 0.549502 -0.817762 -0.00683 0.509965 -0.860168 0.245372 0.347129 -0.905149 0.070934 0.297047 -0.952224 0.328245 0.119471 -0.937007 0.158111 0.057548 -0.985743 0.41119 -0.108418 -0.905079 0.245372 -0.182195 -0.952154 0.488482 -0.320778 -0.811472 0.326683 -0.4056 -0.853678 0.554854 -0.503136 -0.662564 0.396507 -0.597443 -0.697025 0.605783 -0.643064 -0.468504 0.450085 -0.744649 -0.492871 0.637798 -0.731026 -0.242516 0.483765 -0.837186 -0.25513 0.648718 -0.761029 0 0.495253 -0.868749 0 0.637797 -0.731027 0.242516 0.483764 -0.837187 0.255129 0.605781 -0.643065 0.468504 0.450082 -0.74465 0.492872 0.554852 -0.503137 0.662565 0.396505 -0.597443 0.697026 0.48848 -0.320779 0.811473 0.326681 -0.405601 0.853679 0.411187 -0.10842 0.90508 0.245367 -0.182196 0.952155 0.328242 0.11947 0.937008 0.158108 0.057546 0.985743 0.245371 0.347128 0.90515 0.070932 0.297046 0.952225 0.171205 0.549502 0.817763 -0.006833 0.509964 0.860168 0.768687 0.099618 0.63182 0.710785 0.258704 0.654108 0.652928 0.417629 0.631878 0.600917 0.559057 0.571274 0.559726 0.670893 0.486426 0.53123 0.746499 0.400667 0.510735 0.805543 0.300416 0.493446 0.854528 0.162155 0.487042 0.873379 -0.000000 0.493447 0.854527 -0.162155 0.510736 0.805543 -0.300415 0.531232 0.746498 -0.400666 0.559728 0.670891 -0.486425 0.60092 0.559056 -0.571272 0.652931 0.417629 -0.631876 0.710787 0.258705 -0.654105 0.768689 0.09962 -0.631818 0.822645 -0.048623 -0.566472 0.868978 -0.175924 -0.462523 0.904531 -0.273605 -0.327054 0.92688 -0.335011 -0.169296 0.934503 -0.355955 -0.000000 0.92688 -0.335011 0.169296 0.90453 -0.273607 0.327054 0.868977 -0.175926 0.462524 0.822644 -0.048626 0.566475 0.835963 0.506696 0.210773 0.823708 0.539726 0.173785 0.814734 0.565035 0.13017 0.807201 0.586085 0.070223 0.804394 0.594097 -0.000000 0.807202 0.586084 -0.070223 0.814735 0.565033 -0.130169 0.82371 0.539724 -0.173783 0.835965 0.506693 -0.210771 0.853753 0.458139 -0.247414 0.8762 0.396817 -0.273513 0.901241 0.328025 -0.283132 0.926304 0.259165 -0.273485 0.949659 0.194996 -0.2452 0.969715 0.139893 -0.200206 0.985104 0.097611 -0.141568 0.994779 0.07103 -0.073281 0.998078 0.061964 -0.000000 0.994779 0.071029 0.073281 0.985105 0.097608 0.141569 0.969715 0.13989 0.200208 0.949659 0.194993 0.245204 0.926303 0.259163 0.27349 0.90124 0.328024 0.283138 0.876198 0.396818 0.273518 0.853751 0.458142 0.247417 0.962132 0.269782 -0.038982 0.964429 0.263503 -0.021028 0.965306 0.261123 -0.000001 0.96443 0.2635 0.021027 0.962133 0.269779 0.038983 0.959368 0.277314 0.052054 0.955774 0.287249 0.063122 0.950485 0.30181 0.074089 0.943807 0.320191 0.081895 0.93631 0.340789 0.084774 0.928805 0.361408 0.081884 0.921813 0.38062 0.073415 0.915808 0.397117 0.059942 0.911201 0.409776 0.042384 0.908305 0.417732 0.021938 0.907318 0.420445 -0.000000 0.908306 0.41773 -0.021939 0.911203 0.409772 -0.042383 0.915811 0.397113 -0.059939 0.921815 0.380616 -0.07341 0.928807 0.361406 -0.081878 0.936311 0.340789 -0.084767 0.943806 0.320193 -0.081887 0.950484 0.301814 -0.074083 0.955772 0.287254 -0.063118 0.959367 0.277319 -0.052053 0.895758 -0.091725 -0.434977 0.919765 -0.159993 -0.358377 0.939593 -0.212125 -0.268641 0.955862 -0.255554 -0.144986 0.962272 -0.272091 -0.000001 0.955861 -0.255557 0.144984 0.939592 -0.212129 0.268641 0.919764 -0.159999 0.358377 0.895755 -0.091731 0.43498 0.859661 0.008583 0.510793 0.813978 0.135358 0.564905 0.762274 0.277445 0.584776 0.710509 0.41967 0.564849 0.662272 0.5522 0.506429 0.620851 0.666006 0.413497 0.589067 0.753333 0.292384 0.569088 0.808228 0.151349 0.562275 0.826951 -0.000000 0.56909 0.808226 -0.15135 0.589071 0.75333 -0.292384 0.620856 0.666002 -0.413495 0.662277 0.552198 -0.506425 0.710514 0.419669 -0.564843 0.762279 0.277446 -0.584769 0.813982 0.135362 -0.564898 0.859665 0.008588 -0.510787 0.758378 -0.286344 0.585552 0.709852 -0.151442 0.687877 0.648374 0.019204 0.76108 0.578714 0.210635 0.78786 0.508972 0.402251 0.761013 0.443984 0.580808 0.682306 0.388177 0.734139 0.557099 0.345355 0.851793 0.393927 0.318436 0.925753 0.203911 0.309255 0.950979 -0.000000 0.318438 0.925752 -0.203912 0.345359 0.851791 -0.393928 0.388183 0.734136 -0.557099 0.44399 0.580808 -0.682302 0.508979 0.402253 -0.761008 0.578721 0.210637 -0.787854 0.648379 0.019208 -0.761075 0.709856 -0.151438 -0.687874 0.758381 -0.286338 -0.58555 0.790511 -0.37778 -0.482053 0.817394 -0.448423 -0.361639 0.83942 -0.507195 -0.195261 0.848163 -0.529735 -0.000000 0.839419 -0.507197 0.19526 0.817392 -0.448428 0.361639 0.790509 -0.377786 0.482052 -0.291962 -0.106265 0.950508 -0.291962 -0.106265 0.950508 -0.376101 0.124908 0.918121 -0.376101 0.124908 0.918121 -0.454506 0.340328 0.823165 -0.454506 0.340328 0.823165 -0.521834 0.525314 0.672112 -0.521834 0.525314 0.672112 -0.573496 0.667259 0.475255 -0.573496 0.667259 0.475255 -0.605971 0.75649 0.246011 -0.605971 0.75649 0.246011 -0.617047 0.786926 0.000000 -0.617047 0.786926 0.000000 -0.605969 0.756492 -0.246011 -0.605969 0.756492 -0.246011 -0.573491 0.667263 -0.475256 -0.573491 0.667263 -0.475256 -0.521828 0.525317 -0.672114 -0.521828 0.525317 -0.672114 -0.454498 0.340332 -0.823168 -0.454498 0.340332 -0.823168 -0.376092 0.124913 -0.918124 -0.376092 0.124913 -0.918124 -0.291952 -0.106261 -0.950512 -0.291952 -0.106261 -0.950512 -0.207887 -0.337201 -0.918193 -0.207887 -0.337201 -0.918193 -0.132705 -0.54249 -0.829514 -0.132705 -0.54249 -0.829514 -0.073292 -0.704571 -0.705838 -0.073292 -0.704571 -0.705838 -0.032798 -0.813517 -0.580615 -0.032798 -0.813517 -0.580615 -0.002188 -0.899976 -0.435934 -0.002188 -0.899976 -0.435934 0.023411 -0.971598 -0.235479 0.023411 -0.971598 -0.235479 0.033152 -0.99945 0.000000 0.033152 -0.99945 0.000000 0.023409 -0.971597 0.23548 0.023409 -0.971597 0.23548 -0.002192 -0.899976 0.435934 -0.002192 -0.899976 0.435934 -0.032803 -0.813518 0.580614 -0.032803 -0.813518 0.580614 -0.073298 -0.704572 0.705837 -0.073298 -0.704572 0.705837 -0.132714 -0.542491 0.829512 -0.132714 -0.542491 0.829512 -0.207898 -0.337203 0.91819 -0.207898 -0.337203 0.91819</float_array>
+ <technique_common>
+ <accessor source="#Headphones-normals-array" count="3992" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Headphones-headphonesUV" name="headphonesUV">
+ <float_array id="Headphones-headphonesUV-array" count="3658">0.817372 0.157884 0.859071 0.156586 0.859328 0.164019 0.817592 0.165508 0.899633 0.155005 0.899935 0.162224 0.900854 0.18001 0.860133 0.182252 0.85975 0.174312 0.900411 0.172253 0.818284 0.184194 0.817954 0.176059 0.775464 0.185888 0.775181 0.17758 0.7318 0.187366 0.73156 0.178908 0.68721 0.180058 0.687411 0.188645 0.642244 0.181043 0.64241 0.189738 0.59677 0.181878 0.596916 0.190663 0.550949 0.182596 0.551154 0.191449 0.517539 0.163139 0.550456 0.162769 0.550624 0.171092 0.517801 0.171562 0.596504 0.162228 0.596602 0.170473 0.518134 0.077037 0.550834 0.077362 0.550631 0.08566 0.517814 0.085433 0.641955 0.1616 0.642063 0.169757 0.596665 0.077661 0.596556 0.085885 0.686859 0.160861 0.686991 0.168915 0.642002 0.077946 0.641906 0.086086 0.731137 0.16 0.731296 0.167932 0.686827 0.078267 0.686725 0.086308 0.731048 0.078656 0.730933 0.086577 0.774422 0.086916 0.774554 0.079135 0.817224 0.079734 0.81707 0.087352 0.85874 0.087929 0.858924 0.0805 0.899508 0.081556 0.899283 0.088774 0.519045 0.056752 0.551444 0.057084 0.551206 0.065898 0.518705 0.065526 0.899877 0.071529 0.859244 0.070212 0.859549 0.062276 0.900238 0.063774 0.817752 0.061065 0.817494 0.069192 0.774785 0.06837 0.775005 0.060075 0.731248 0.067699 0.731438 0.059258 0.774682 0.159011 0.774871 0.166801 0.687004 0.067148 0.68717 0.058583 0.642316 0.058021 0.642165 0.066689 0.596997 0.057538 0.596843 0.066291 0.518581 0.191938 0.518297 0.18312 0.517569 0.124256 0.550427 0.124188 0.596323 0.124034 0.641707 0.123825 0.686537 0.12357 0.730739 0.123277 0.774205 0.122956 0.816813 0.122612 0.858409 0.122255 0.898777 0.12189 0.903855 0.216837 0.862635 0.220052 0.861667 0.024505 0.902836 0.026952 0.820434 0.222884 0.819548 0.022432 0.861667 0.024505 0.777316 0.22538 0.776547 0.020668 0.819548 0.022432 0.73338 0.227562 0.732765 0.019178 0.776547 0.020668 0.688734 0.229443 0.688315 0.017934 0.732765 0.019178 0.643496 0.231039 0.643312 0.016903 0.688315 0.017934 0.597772 0.232373 0.59787 0.016049 0.643312 0.016903 0.55165 0.233455 0.552081 0.015342 0.59787 0.016049 0.518737 0.233984 0.519456 0.015006 0.552081 0.015342 0.183043 0.15764 0.182682 0.165284 0.140833 0.163465 0.141251 0.156012 0.100106 0.161234 0.100591 0.153995 0.098739 0.179085 0.099377 0.171297 0.140189 0.173793 0.139635 0.181765 0.182126 0.175869 0.181648 0.184034 0.225031 0.177616 0.224619 0.185951 0.268766 0.179081 0.268414 0.187563 0.313209 0.180292 0.312911 0.188899 0.35825 0.181277 0.357998 0.189988 0.40378 0.182065 0.403554 0.190861 0.449633 0.182705 0.449355 0.191564 0.483219 0.163173 0.482886 0.171598 0.450056 0.171193 0.450295 0.162866 0.404051 0.170649 0.404225 0.162397 0.48336 0.077072 0.483608 0.085467 0.450796 0.085754 0.450665 0.077458 0.358546 0.169975 0.358737 0.161808 0.40489 0.086048 0.404858 0.077829 0.313557 0.169128 0.313783 0.161061 0.359572 0.086285 0.359559 0.078152 0.269175 0.168079 0.269441 0.160131 0.314797 0.086495 0.314789 0.078465 0.270644 0.086692 0.270636 0.078783 0.22722 0.086886 0.22721 0.079118 0.184646 0.08709 0.184631 0.079488 0.143063 0.087345 0.143035 0.079933 0.102621 0.08777 0.10257 0.080571 0.482615 0.056792 0.482884 0.065564 0.450391 0.066001 0.450227 0.057192 0.102439 0.070576 0.102262 0.062851 0.14279 0.061767 0.14293 0.069674 0.184441 0.060872 0.184552 0.068973 0.227054 0.060104 0.227147 0.068377 0.270505 0.059425 0.270583 0.067847 0.225509 0.166807 0.22582 0.158999 0.314673 0.058814 0.314741 0.067362 0.359447 0.058254 0.359511 0.066909 0.404709 0.057725 0.404784 0.066468 0.482294 0.18316 0.481939 0.19198 0.450662 0.124276 0.48352 0.124287 0.404764 0.124187 0.359377 0.124009 0.314544 0.123738 0.270339 0.12337 0.226867 0.122899 0.184256 0.122322 0.142662 0.121636 0.102316 0.120844 0.136331 0.219788 0.094831 0.216133 0.141448 0.024185 0.10052 0.026224 0.178804 0.222934 0.18333 0.022417 0.141448 0.024185 0.222169 0.225631 0.226111 0.020859 0.18333 0.022417 0.266319 0.227919 0.269697 0.019486 0.226111 0.020859 0.311139 0.229827 0.313982 0.018281 0.269697 0.019486 0.356516 0.231389 0.358853 0.017225 0.313982 0.018281 0.40234 0.232642 0.4042 0.016298 0.358853 0.017225 0.448524 0.233611 0.449929 0.015487 0.4042 0.016298 0.481462 0.23404 0.482532 0.015059 0.449929 0.015487 0.482532 0.015059 0.519456 0.015006 0.933828 0.153051 0.934195 0.160309 0.934551 0.170183 0.934927 0.178005 0.933758 0.082825 0.933474 0.090085 0.934291 0.065135 0.934005 0.072955 0.932601 0.121571 0.93854 0.213537 0.937497 0.029588 0.902836 0.026952 0.065708 0.158844 0.066279 0.151569 0.064502 0.17661 0.065086 0.168753 0.068439 0.081397 0.068534 0.088634 0.068449 0.071567 0.068362 0.063785 0.068571 0.120074 0.059921 0.212348 0.066059 0.028436 0.10052 0.026224 0.593334 0.400911 0.597301 0.404806 0.598975 0.414824 0.59426 0.40797 0.4336 0.247163 0.4336 0.24335 0.462067 0.248564 0.462067 0.252498 0.551135 0.313388 0.551135 0.308874 0.581227 0.360312 0.581227 0.366604 0.501482 0.26186 0.501482 0.265878 0.4336 0.308297 0.4336 0.30303 0.462067 0.30722 0.462067 0.312487 0.551135 0.355737 0.551135 0.350471 0.581227 0.383757 0.581227 0.389024 0.501482 0.31726 0.501482 0.322527 0.581227 0.37175 0.4336 0.299099 0.483865 0.310491 0.462067 0.261424 0.4336 0.256211 0.501482 0.274721 0.528217 0.352956 0.551135 0.321735 0.553824 0.400208 0.581227 0.373172 0.579513 0.43317 0.597301 0.417667 0.582798 0.441141 0.598975 0.427685 0.577666 0.43572 0.59426 0.420831 0.581227 0.401884 0.551135 0.368598 0.501482 0.335387 0.462067 0.325347 0.4336 0.321157 0.4336 0.25875 0.462067 0.264183 0.501482 0.2775 0.551135 0.323173 0.4336 0.383089 0.478396 0.391335 0.516751 0.426291 0.4336 0.468914 0.468152 0.476949 0.500281 0.496998 0.508123 0.509636 0.526743 0.459067 0.549735 0.433951 0.570189 0.441296 0.571541 0.450505 0.567733 0.444633 0.557209 0.428399 0.564415 0.420445 0.468341 0.546965 0.471855 0.563464 0.456464 0.521408 0.4336 0.561384 0.4336 0.5741 0.4336 0.529226 0.461312 0.35158 0.4336 0.34781 0.460988 0.362822 0.4336 0.359232 0.497868 0.360613 0.49632 0.371425 0.538378 0.390495 0.53291 0.399879 0.588605 0.404822 0.586556 0.399912 0.589943 0.406529 0.591004 0.411695 0.4336 0.255552 0.4336 0.256504 0.461005 0.261644 0.461195 0.26061 0.546941 0.318484 0.547194 0.320896 0.576266 0.372699 0.575495 0.367024 0.499144 0.27468 0.499266 0.273445 0.4336 0.311035 0.4336 0.31425 0.461773 0.317986 0.462843 0.315237 0.544838 0.358511 0.546806 0.359842 0.578051 0.389677 0.575155 0.387227 0.49987 0.332099 0.500538 0.329786 0.574606 0.374969 0.481999 0.314284 0.4336 0.304238 0.4336 0.262519 0.461645 0.267265 0.499244 0.279502 0.524635 0.352071 0.546918 0.32204 0.549743 0.397303 0.575647 0.370716 0.575586 0.42237 0.58694 0.411129 0.579349 0.427968 0.589848 0.41793 0.577216 0.427233 0.590986 0.415418 0.579359 0.39741 0.548995 0.364975 0.502204 0.335735 0.462959 0.322111 0.4336 0.318586 0.460947 0.273177 0.4336 0.267957 0.499069 0.286118 0.547126 0.330479 0.4336 0.389004 0.47587 0.395937 0.512067 0.426556 0.4336 0.473148 0.466366 0.47963 0.496479 0.49741 0.521455 0.458838 0.503806 0.508596 0.544438 0.432837 0.566708 0.434298 0.568637 0.437946 0.565986 0.438434 0.564415 0.417229 0.557209 0.425183 0.465776 0.545161 0.469025 0.560489 0.454657 0.522708 0.4336 0.558299 0.4336 0.571456 0.4336 0.52981 0.4336 0.344594 0.461312 0.348364 0.4336 0.356016 0.460988 0.359606 0.497868 0.357397 0.49632 0.368209 0.538378 0.387279 0.53291 0.396663 0.525421 0.45901 0.507044 0.509376 0.522777 0.458896 0.504885 0.508856 0.548411 0.433673 0.545763 0.433115 0.569319 0.439547 0.567578 0.436048 0.571252 0.448111 0.570674 0.443323 0.567733 0.443829 0.565986 0.439238 0.557209 0.427595 0.557209 0.425987 0.471147 0.56272 0.469732 0.561233 0.4336 0.573439 0.4336 0.572117 0.4336 0.358428 0.460988 0.362018 0.4336 0.35682 0.460988 0.36041 0.49632 0.370621 0.49632 0.369013 0.53291 0.399075 0.53291 0.397467 0.273866 0.400911 0.27294 0.40797 0.268225 0.414824 0.269899 0.404806 0.405133 0.252498 0.405133 0.248564 0.316065 0.313388 0.285973 0.366604 0.285973 0.360312 0.316065 0.308874 0.365719 0.265878 0.365719 0.26186 0.405133 0.312487 0.405133 0.30722 0.316065 0.355737 0.285973 0.389024 0.285973 0.383757 0.316065 0.350471 0.365719 0.322527 0.365719 0.31726 0.285973 0.37175 0.405133 0.261424 0.383336 0.310491 0.365719 0.274721 0.316065 0.321735 0.338983 0.352956 0.285973 0.373172 0.313377 0.400208 0.269899 0.417667 0.287687 0.43317 0.268225 0.427685 0.284403 0.441141 0.27294 0.420831 0.289534 0.43572 0.285973 0.401884 0.316065 0.368598 0.365719 0.335387 0.405133 0.325347 0.405133 0.264183 0.365719 0.2775 0.316065 0.323173 0.388804 0.391335 0.350449 0.426291 0.399048 0.476949 0.340457 0.459067 0.359077 0.509636 0.366919 0.496998 0.317465 0.433951 0.297011 0.441296 0.29566 0.450505 0.299467 0.444633 0.302785 0.420445 0.309991 0.428399 0.395345 0.563464 0.39886 0.546965 0.410736 0.521408 0.405889 0.35158 0.406212 0.362822 0.369332 0.360613 0.37088 0.371425 0.328822 0.390495 0.33429 0.399879 0.278595 0.404822 0.276196 0.411695 0.277257 0.406529 0.280644 0.399912 0.406005 0.26061 0.406195 0.261644 0.320259 0.318484 0.291706 0.367024 0.290934 0.372699 0.320006 0.320896 0.367934 0.273445 0.368056 0.27468 0.404357 0.315237 0.405427 0.317986 0.322362 0.358511 0.292045 0.387227 0.289149 0.389677 0.320394 0.359842 0.366662 0.329786 0.36733 0.332099 0.292594 0.374969 0.385201 0.314284 0.405555 0.267265 0.367956 0.279502 0.342565 0.352071 0.320282 0.32204 0.317457 0.397303 0.291553 0.370716 0.291614 0.42237 0.280261 0.411129 0.287851 0.427968 0.277352 0.41793 0.289984 0.427233 0.276214 0.415418 0.287842 0.39741 0.318206 0.364975 0.364996 0.335735 0.404241 0.322111 0.406254 0.273177 0.368131 0.286118 0.320074 0.330479 0.39133 0.395937 0.355133 0.426556 0.400834 0.47963 0.370721 0.49741 0.363394 0.508596 0.345745 0.458838 0.322762 0.432837 0.300492 0.434298 0.298563 0.437946 0.301214 0.438434 0.309991 0.425183 0.302785 0.417229 0.401424 0.545161 0.398176 0.560489 0.412543 0.522708 0.405889 0.348364 0.406212 0.359606 0.369332 0.357397 0.37088 0.368209 0.328822 0.387279 0.33429 0.396663 0.341779 0.45901 0.360156 0.509376 0.362315 0.508856 0.344423 0.458896 0.318789 0.433673 0.321437 0.433115 0.297881 0.439547 0.299622 0.436048 0.295949 0.448111 0.296527 0.443323 0.299467 0.443829 0.301214 0.439238 0.309991 0.427595 0.309991 0.425987 0.396053 0.56272 0.397468 0.561233 0.406212 0.362018 0.406212 0.36041 0.37088 0.370621 0.37088 0.369013 0.33429 0.399075 0.33429 0.397467 0.968892 0.151846 0.968917 0.121224 0.973186 0.121183 0.972916 0.151495 0.968529 0.090611 0.972556 0.090884 0.969133 0.084912 0.974808 0.086217 0.969659 0.075688 0.975286 0.075979 0.970382 0.068801 0.975483 0.068794 0.975909 0.034233 0.980827 0.034884 0.976949 0.208143 0.971012 0.173638 0.976118 0.173546 0.981866 0.207396 0.970204 0.166758 0.975832 0.166355 0.969564 0.157537 0.975225 0.156118 0.983422 0.086657 0.986922 0.089865 0.987107 0.121048 0.987294 0.15223 0.983833 0.155507 0.031191 0.14974 0.027182 0.149305 0.027974 0.119008 0.032249 0.119126 0.029592 0.08879 0.033608 0.088593 0.027504 0.084103 0.033182 0.082915 0.027341 0.07395 0.032931 0.073752 0.027345 0.06683 0.032406 0.06691 0.02293 0.03311 0.027827 0.032531 0.021342 0.206305 0.016406 0.205473 0.023188 0.17144 0.028331 0.171619 0.023716 0.164182 0.029367 0.1647 0.024704 0.153885 0.030323 0.155436 0.01615 0.153076 0.012807 0.149734 0.014057 0.118607 0.015306 0.087479 0.018909 0.084347 0.056946 0.152393 0.058972 0.119836 0.063696 0.119954 0.061371 0.15281 0.938934 0.08274 0.938265 0.088679 0.943091 0.082773 0.942645 0.088941 0.948574 0.030771 0.944604 0.067589 0.939544 0.06735 0.943094 0.030181 0.937497 0.029588 0.055126 0.167152 0.056299 0.158568 0.060486 0.158748 0.05961 0.167615 0.944489 0.168747 0.945221 0.175351 0.94016 0.175687 0.94002 0.169136 0.059434 0.087357 0.059154 0.081208 0.063291 0.081237 0.063801 0.087161 0.93948 0.073896 0.943947 0.074199 0.062979 0.072427 0.058529 0.072664 0.05805 0.066082 0.055042 0.029467 0.060492 0.028952 0.063085 0.065915 0.066059 0.028436 0.054288 0.211557 0.059299 0.174196 0.054288 0.211557 0.048777 0.21077 0.054215 0.173779 0.949618 0.212139 0.944139 0.212836 0.944139 0.212836 0.939374 0.160295 0.943533 0.160183 0.942264 0.121477 0.943016 0.154019 0.938637 0.154365 0.937507 0.121523 0.976949 0.208143 0.949618 0.212139 0.048777 0.21077 0.021342 0.206305 0.837055 0.384384 0.794898 0.360133 0.792038 0.386374 0.837055 0.403927 0.814119 0.343384 0.837931 0.361005 0.878979 0.413338 0.880447 0.395313 0.880656 0.374141 0.80355 0.325 0.784523 0.325 0.759382 0.325 0.759397 0.357823 0.759439 0.383887 0.758467 0.383878 0.758574 0.37554 0.792658 0.378778 0.790434 0.386357 0.837221 0.39646 0.834272 0.403927 0.875664 0.40566 0.873529 0.413425 0.837392 0.360958 0.813756 0.343392 0.803232 0.325 0.879703 0.374138 0.877735 0.374131 0.836471 0.360882 0.813125 0.343404 0.802684 0.325 0.878619 0.369835 0.837923 0.356801 0.815707 0.340211 0.806407 0.325 0.874991 0.368837 0.83707 0.35573 0.816142 0.339713 0.807322 0.325 0.873731 0.374791 0.835251 0.361129 0.812607 0.343697 0.802324 0.325 0.83741 0.369215 0.877144 0.382766 0.806692 0.348548 0.792072 0.325 0.87717 0.385322 0.837215 0.372284 0.877271 0.395286 0.836458 0.384245 0.804015 0.350938 0.791411 0.358255 0.787967 0.325 0.778772 0.325 0.837065 0.393965 0.794611 0.374492 0.875992 0.403541 0.77509 0.370299 0.758564 0.356846 0.770604 0.355428 0.758608 0.325 0.766499 0.325 0.973148 0.375243 0.97073 0.374577 0.97085 0.37114 0.974068 0.371057 0.97163 0.407271 0.970622 0.411943 0.968373 0.413425 0.97008 0.405518 0.974641 0.411882 0.972931 0.413356 0.974997 0.411537 0.97377 0.413338 0.976175 0.395745 0.975263 0.395313 0.976031 0.377582 0.975476 0.374141 0.975578 0.376393 0.974524 0.374138 0.972577 0.374131 0.973474 0.369835 0.969538 0.368812 0.96868 0.374743 0.974126 0.381167 0.972128 0.382864 0.974047 0.385599 0.972176 0.385383 0.974184 0.395744 0.972367 0.395199 0.972049 0.40522 0.970547 0.403411 0.971073 0.395313 0.971203 0.413338 0.971055 0.374141 0.970643 0.413356 0.970499 0.374138 0.96867 0.369835 0.968634 0.374131 0.96549 0.413425 0.965831 0.405524 0.965594 0.368813 0.96487 0.374745 0.967523 0.382859 0.967585 0.38538 0.96783 0.395203 0.967181 0.403415 0.837055 0.265617 0.837055 0.246073 0.792038 0.263626 0.794898 0.289867 0.814119 0.306616 0.837931 0.288995 0.880447 0.254687 0.878979 0.236662 0.880656 0.275859 0.759397 0.292177 0.759439 0.266113 0.758467 0.266122 0.790434 0.263643 0.792658 0.271222 0.758574 0.27446 0.834272 0.246073 0.837221 0.25354 0.873529 0.236575 0.875664 0.24434 0.813756 0.306608 0.837392 0.289042 0.879703 0.275862 0.877735 0.275869 0.836471 0.289118 0.813125 0.306596 0.878619 0.280165 0.837923 0.293199 0.815707 0.309789 0.83707 0.29427 0.874991 0.281163 0.816142 0.310287 0.835251 0.28887 0.873731 0.275209 0.812607 0.306303 0.83741 0.280785 0.877144 0.267234 0.806692 0.301452 0.837215 0.277716 0.87717 0.264678 0.836458 0.265755 0.877271 0.254714 0.804015 0.299062 0.791411 0.291745 0.794611 0.275509 0.837065 0.256035 0.875992 0.246459 0.77509 0.279701 0.770604 0.294572 0.758564 0.293154 0.973148 0.274757 0.974068 0.278943 0.97085 0.27886 0.97073 0.275423 0.97163 0.242729 0.97008 0.244482 0.968373 0.236575 0.970622 0.238057 0.974641 0.238118 0.972931 0.236644 0.974997 0.238463 0.97377 0.236662 0.976175 0.254255 0.975263 0.254687 0.975476 0.275859 0.976031 0.272418 0.974524 0.275862 0.975578 0.273607 0.972577 0.275869 0.973474 0.280165 0.969538 0.281188 0.96868 0.275257 0.974126 0.268833 0.972128 0.267136 0.972176 0.264617 0.974047 0.264401 0.974184 0.254256 0.972367 0.254801 0.970547 0.246589 0.972049 0.24478 0.971203 0.236662 0.971073 0.254687 0.971055 0.275859 0.970643 0.236644 0.970499 0.275862 0.968634 0.275869 0.96867 0.280165 0.965831 0.244476 0.96549 0.236575 0.965594 0.281187 0.96487 0.275255 0.967523 0.267141 0.967585 0.26462 0.96783 0.254797 0.967181 0.246585 0.73401 0.325 0.734051 0.357823 0.734061 0.383887 0.73404 0.383878 0.734091 0.37554 0.733862 0.356846 0.733825 0.325 0.733862 0.293154 0.734091 0.27446 0.73404 0.266122 0.734061 0.266113 0.734051 0.292177 0.098804 0.42194 0.116821 0.42194 0.12403 0.365 0.10601 0.365 0.077677 0.475 0.095696 0.475 0.097965 0.469297 0.079947 0.469297 0.071277 0.474147 0.090463 0.474147 0.039607 0.427122 0.058825 0.427122 0.074 0.45856 0.054799 0.45856 0.03 0.365 0.049227 0.365 0.050286 0.391581 0.031059 0.391581 0.098804 0.30806 0.116821 0.30806 0.071277 0.255853 0.077677 0.255 0.095696 0.255 0.090463 0.255853 0.079947 0.260703 0.097965 0.260703 0.039607 0.302878 0.054799 0.27144 0.074 0.27144 0.058825 0.302878 0.031059 0.338419 0.050286 0.338419 0.092097 0.421182 0.098223 0.365 0.239536 0.397857 0.244494 0.365 0.25 0.364237 0.24413 0.398371 0.073915 0.467437 0.161589 0.44691 0.16546 0.448398 0.163652 0.452958 0.159499 0.452275 0.070708 0.414683 0.075709 0.365 0.222448 0.394145 0.226413 0.365 0.0573 0.451662 0.043407 0.424204 0.134776 0.414674 0.137711 0.412341 0.148509 0.434296 0.146556 0.439812 0.036533 0.365 0.036898 0.394983 0.195806 0.365 0.196087 0.382891 0.190538 0.381004 0.189692 0.364237 0.176137 0.407408 0.180622 0.407978 0.132688 0.387716 0.159049 0.402524 0.1282 0.385159 0.092097 0.308818 0.239536 0.332143 0.244129 0.331629 0.073915 0.262563 0.161589 0.28309 0.159499 0.277725 0.163652 0.277042 0.16546 0.281602 0.070708 0.315317 0.222448 0.335855 0.043407 0.305796 0.0573 0.278338 0.134776 0.315326 0.146556 0.290188 0.148509 0.295704 0.137711 0.317659 0.036898 0.335017 0.190532 0.348995 0.196087 0.347109 0.180622 0.322022 0.176137 0.322592 0.159049 0.327476 0.132688 0.342284 0.1282 0.344841 0.130748 0.467675 0.132864 0.462352 0.1505 0.418149 0.157268 0.365 0.1505 0.311851 0.132864 0.267648 0.130748 0.262325 0.125877 0.263121 0.110605 0.27767 0.096585 0.307015 0.08871 0.340189 0.087734 0.365 0.08871 0.389811 0.096585 0.422985 0.110605 0.45233 0.125877 0.466879 0.186485 0.365 0.181607 0.365 0.175586 0.411811 0.175586 0.318189 0.160002 0.279256 0.158142 0.274567 0.153868 0.275269 0.140539 0.288083 0.128394 0.313929 0.121608 0.343148 0.127387 0.365 0.120769 0.365 0.121608 0.386852 0.128394 0.416071 0.140539 0.441917 0.153868 0.454731 0.158142 0.455433 0.160002 0.450744 0.243515 0.364237 0.237645 0.398362 0.19297 0.364237 0.187106 0.398298 0.237645 0.331638 0.187106 0.331702 0.233063 0.332143 0.18261 0.332143 0.215975 0.335855 0.165522 0.335855 0.189614 0.347109 0.139161 0.347109 0.184167 0.349001 0.134564 0.349047 0.18333 0.364237 0.133748 0.364237 0.184173 0.380998 0.134564 0.380953 0.189614 0.382891 0.139161 0.382891 0.215975 0.394145 0.165522 0.394145 0.233063 0.397857 0.18261 0.397857 0.730143 0.451406 0.729839 0.501676 0.674663 0.510816 0.659572 0.465014 0.626063 0.535525 0.599512 0.497955 0.587596 0.571631 0.55322 0.543954 0.521979 0.598225 0.56103 0.615275 0.547092 0.66294 0.506177 0.656642 0.545784 0.711423 0.505505 0.715516 0.556596 0.757869 0.519054 0.771636 0.578871 0.799818 0.545537 0.822586 0.612972 0.835021 0.584311 0.867084 0.729595 0.541951 0.686227 0.548518 0.64726 0.567266 0.615767 0.595522 0.593559 0.630362 0.581528 0.668907 0.579872 0.708438 0.588269 0.746429 0.606017 0.780486 0.631937 0.807924 0.729354 0.581687 0.69721 0.58626 0.66792 0.599706 0.643799 0.620455 0.62642 0.646509 0.616671 0.675724 0.614854 0.705965 0.620765 0.73519 0.633724 0.761468 0.652453 0.783002 0.729109 0.621938 0.707951 0.624817 0.688475 0.633413 0.67217 0.646906 0.660159 0.664125 0.653154 0.683702 0.651463 0.704208 0.655004 0.724241 0.663339 0.742522 0.675698 0.757991 0.72886 0.662637 0.718451 0.664011 0.708798 0.668147 0.700604 0.674715 0.694436 0.683209 0.690694 0.693003 0.689585 0.703405 0.691127 0.713715 0.695159 0.723274 0.701363 0.731506 0.638263 0.811858 0.622071 0.840166 0.657782 0.786826 0.690677 0.765711 0.713762 0.760253 0.712221 0.765742 0.690378 0.770057 0.728266 0.759688 0.728225 0.766384 0.611421 0.859807 0.632111 0.844725 0.632021 0.854187 0.623794 0.855985 0.627405 0.84255 0.728205 0.769615 0.712503 0.770157 0.662156 0.794404 0.642338 0.821312 0.641534 0.813782 0.661367 0.789398 0.690907 0.774496 0.709309 0.73796 0.718502 0.742183 0.728364 0.743792 0.647892 0.885065 0.68612 0.907725 0.683624 0.914918 0.642546 0.891729 0.678272 0.931156 0.631552 0.907356 0.727273 0.915091 0.727226 0.922514 0.72712 0.939128 0.621732 0.869798 0.629049 0.863375 0.606171 0.887353 0.686983 0.903575 0.727304 0.910209 0.649458 0.8809 0.633455 0.859016 0.727805 0.833986 0.715662 0.83449 0.715358 0.829847 0.727831 0.829669 0.669864 0.841872 0.647214 0.848901 0.645554 0.842537 0.668761 0.83655 0.698113 0.835747 0.697316 0.831223 0.698292 0.875787 0.727508 0.8817 0.658427 0.861497 0.648949 0.853246 0.642018 0.832397 0.713825 0.83904 0.697369 0.8401 0.727773 0.839236 0.667162 0.845874 0.713959 0.854617 0.72766 0.859829 0.691919 0.804554 0.662493 0.816496 0.71386 0.801495 0.728012 0.800796 0.800546 0.465867 0.784901 0.511485 0.860206 0.499535 0.8332 0.536782 0.90594 0.546095 0.871227 0.573355 0.936521 0.600744 0.897262 0.61732 0.951614 0.659352 0.910622 0.665154 0.951573 0.718234 0.911341 0.713654 0.937346 0.774195 0.899965 0.759972 0.910244 0.824833 0.877177 0.801655 0.870921 0.868873 0.842638 0.83645 0.77288 0.549044 0.811618 0.568264 0.842768 0.596903 0.864551 0.632011 0.876113 0.670703 0.877288 0.710255 0.868428 0.748146 0.850263 0.78199 0.823998 0.809117 0.76144 0.586651 0.790565 0.600451 0.814432 0.621494 0.831493 0.647759 0.840887 0.677092 0.842336 0.707356 0.836068 0.736509 0.822787 0.762631 0.803792 0.783936 0.75023 0.625074 0.7696 0.633907 0.78574 0.647599 0.797541 0.664963 0.804306 0.684625 0.805748 0.705151 0.801962 0.725141 0.793402 0.743321 0.780854 0.758638 0.739253 0.664138 0.748854 0.668391 0.756968 0.675059 0.763032 0.683628 0.766654 0.693467 0.767636 0.703882 0.765967 0.714173 0.761819 0.723682 0.755514 0.731838 0.81762 0.812975 0.833473 0.841483 0.798417 0.787693 0.76578 0.766174 0.766025 0.770523 0.744235 0.76594 0.742762 0.760432 0.843891 0.861262 0.823371 0.845919 0.828106 0.843802 0.831559 0.857284 0.82335 0.855381 0.743899 0.770351 0.793951 0.795216 0.794801 0.790221 0.814324 0.814861 0.813424 0.822383 0.765442 0.774957 0.747489 0.738194 0.738245 0.742304 0.807129 0.886081 0.812381 0.892815 0.770938 0.915484 0.768528 0.908255 0.823171 0.90859 0.776087 0.9318 0.826216 0.864612 0.833459 0.871129 0.848809 0.888887 0.767715 0.904092 0.805624 0.881896 0.821859 0.860194 0.7403 0.830005 0.739938 0.834645 0.785618 0.8426 0.786785 0.837294 0.809973 0.843531 0.808216 0.849888 0.758318 0.83161 0.757466 0.836123 0.756815 0.87616 0.796801 0.862358 0.806415 0.854218 0.813592 0.833483 0.741718 0.839219 0.758156 0.840486 0.788272 0.846632 0.741392 0.854799 0.79335 0.817298 0.764058 0.805006 0.742155 0.801672 0.739879 0.703443 0.739544 0.700429 0.738459 0.697605 0.736692 0.695167 0.734362 0.693283 0.731629 0.692089 0.728683 0.691669 0.725733 0.692053 0.722985 0.693214 0.720632 0.695069 0.718836 0.697486 0.717716 0.700296 0.717345 0.703306 0.71774 0.706312 0.71887 0.709112 0.720653 0.711521 0.722966 0.713379 0.725655 0.714559 0.728541 0.714976 0.731431 0.714594 0.734134 0.713447 0.73647 0.711618 0.738282 0.70923 0.739447 0.706444 0.728612 0.703346 0.677147 0.935045 0.63309 0.913114 0.603885 0.891138 0.577299 0.866286 0.541588 0.825072 0.514674 0.773255 0.500796 0.716034 0.501372 0.65596 0.517362 0.596289 0.549111 0.540764 0.596273 0.493569 0.657649 0.459561 0.730181 0.445212 0.802536 0.460438 0.863499 0.495188 0.910087 0.542955 0.941161 0.598864 0.956427 0.658728 0.956276 0.71881 0.941706 0.775867 0.914164 0.827367 0.877946 0.86816 0.85105 0.892701 0.821556 0.914331 0.777162 0.935705 0.727094 0.943099 0.50967 0.775114 0.495409 0.716647 0.537141 0.828021 0.573291 0.870314 0.600272 0.895459 0.630335 0.917495 0.675775 0.939522 0.727063 0.947691 0.778477 0.940203 0.824255 0.918751 0.854611 0.89707 0.881907 0.872239 0.918577 0.83037 0.946688 0.777787 0.961656 0.719488 0.961943 0.658041 0.946493 0.596742 0.914874 0.539386 0.86733 0.49022 0.804892 0.454185 0.730225 0.437965 0.655368 0.45328 0.592502 0.488555 0.544368 0.537138 0.512057 0.594102 0.495866 0.655205 0.971604 0.720761 0.955894 0.781339 0.972151 0.656796 0.956376 0.592846 0.92377 0.532812 0.874484 0.481042 0.809341 0.442578 0.730307 0.424379 0.65106 0.441621 0.58546 0.479291 0.535553 0.530456 0.502222 0.590087 0.485673 0.653838 0.485447 0.7178 0.500423 0.778555 0.528882 0.833445 0.565805 0.877554 0.593676 0.903517 0.625458 0.925737 0.673278 0.947884 0.727007 0.956232 0.780866 0.948603 0.82903 0.927061 0.861112 0.905214 0.88931 0.879573 0.926772 0.835895 0.587032 0.911819 0.558096 0.884695 0.620756 0.934282 0.670791 0.956477 0.726948 0.964982 0.783241 0.957236 0.833626 0.935674 0.867659 0.913604 0.896936 0.886809 0.935128 0.841471 0.965246 0.784963 0.98172 0.722086 0.98255 0.65557 0.966465 0.588926 0.932882 0.526162 0.881864 0.471722 0.814014 0.430721 0.730392 0.410256 0.646532 0.429708 0.578194 0.469883 0.526523 0.523697 0.492182 0.586045 0.475291 0.652486 0.475317 0.719002 0.49103 0.782065 0.520462 0.838919 0.726915 0.969836 0.66944 0.96125 0.784529 0.96203 0.83604 0.940508 0.87127 0.918307 0.901217 0.890705 0.939744 0.84453 0.970403 0.786968 0.987305 0.722831 0.988297 0.654909 0.97205 0.58678 0.93794 0.522507 0.885981 0.466585 0.816662 0.424157 0.73044 0.402314 0.643964 0.423113 0.57414 0.464697 0.52151 0.519981 0.486624 0.583831 0.469553 0.651755 0.469725 0.719679 0.48585 0.784008 0.515811 0.841921 0.553771 0.888538 0.583368 0.916475 0.618283 0.939078 0.216383 0.815019 0.217099 0.812515 0.235103 0.81494 0.235108 0.817541 0.305273 0.763601 0.30257 0.763074 0.305022 0.745146 0.307822 0.744956 0.216123 0.675027 0.216849 0.677906 0.200015 0.684842 0.198615 0.68224 0.286371 0.693816 0.284395 0.695973 0.270012 0.68489 0.271413 0.68229 0.164669 0.763581 0.167374 0.763054 0.174175 0.779725 0.171742 0.780918 0.288639 0.794505 0.286575 0.792789 0.295768 0.779861 0.298199 0.78106 0.185572 0.695874 0.183594 0.693713 0.253744 0.815165 0.253023 0.812654 0.268298 0.806889 0.269629 0.809169 0.181261 0.794259 0.183328 0.792553 0.191492 0.800505 0.189751 0.802529 0.200435 0.809072 0.201764 0.806795 0.30528 0.726268 0.302577 0.727177 0.295559 0.710387 0.297982 0.708807 0.164719 0.726294 0.167423 0.727202 0.164978 0.745182 0.162178 0.744994 0.25309 0.677751 0.253813 0.674866 0.280066 0.802516 0.278332 0.800492 0.174405 0.7104 0.171981 0.70882 0.234862 0.675437 0.234857 0.672459 0.193191 0.711687 0.182712 0.736808 0.214808 0.695147 0.241822 0.691514 0.283692 0.723577 0.267075 0.70203 0.287285 0.750426 0.215568 0.79264 0.241888 0.795788 0.264119 0.788107 0.198831 0.782665 0.186188 0.763559 0.277691 0.77491 0.222481 0.713071 0.209078 0.723325 0.265188 0.730697 0.254886 0.717338 0.23927 0.775468 0.253053 0.770706 0.222952 0.773517 0.261468 0.762523 0.267416 0.747344 0.239229 0.710818 0.202581 0.738901 0.212575 0.767331 0.204736 0.755486 0.234993 0.745117 0.352961 0.948595 0.29969 0.972633 0.298279 0.96785 0.350482 0.944128 0.29969 0.972633 0.236996 0.983312 0.23697 0.978214 0.236996 0.983312 0.1742 0.973288 0.17556 0.968491 0.1742 0.973288 0.120687 0.949809 0.123119 0.945317 0.120687 0.949809 0.088063 0.925486 0.09168 0.921615 0.088063 0.925486 0.063365 0.89609 0.067634 0.893388 0.063365 0.89609 0.03675 0.846184 0.041245 0.844399 0.03675 0.846184 0.020267 0.78806 0.024949 0.787277 0.020267 0.78806 0.017118 0.728298 0.021803 0.728572 0.017118 0.728298 0.027284 0.67002 0.031728 0.671322 0.027284 0.67002 0.050082 0.616306 0.054046 0.61856 0.050082 0.616306 0.084282 0.570113 0.087538 0.5732 0.084282 0.570113 0.128117 0.534196 0.130458 0.53795 0.128117 0.534196 0.179226 0.51103 0.180472 0.515234 0.179226 0.51103 0.234521 0.50269 0.234544 0.507057 0.234521 0.50269 0.289898 0.510454 0.288696 0.51467 0.289898 0.510454 0.341241 0.533082 0.33894 0.53686 0.341241 0.533082 0.385441 0.568536 0.382217 0.571656 0.385441 0.568536 0.420115 0.614365 0.416175 0.61666 0.420115 0.614365 0.443469 0.667835 0.439037 0.669183 0.443469 0.667835 0.454237 0.726007 0.449555 0.726329 0.454237 0.726007 0.451702 0.785798 0.447013 0.785063 0.451702 0.785798 0.435823 0.844089 0.431309 0.842352 0.435823 0.844089 0.409726 0.894275 0.405429 0.891616 0.409726 0.894275 0.385331 0.923932 0.381674 0.920098 0.385331 0.923932 0.352961 0.948595 0.372668 0.910682 0.39491 0.88467 0.344033 0.933157 0.294694 0.955845 0.236903 0.965442 0.179019 0.95645 0.129453 0.934281 0.100587 0.912107 0.078079 0.886333 0.052555 0.839823 0.036776 0.785283 0.033642 0.729251 0.042962 0.674598 0.064062 0.624238 0.095761 0.580973 0.136362 0.547399 0.18361 0.525805 0.234601 0.518027 0.285669 0.525272 0.333135 0.546369 0.374077 0.579514 0.40622 0.62244 0.427839 0.672575 0.437723 0.72713 0.435166 0.783191 0.419951 0.837893 0.419923 0.72828 0.41099 0.677608 0.417362 0.780319 0.402983 0.831085 0.379561 0.874095 0.359572 0.896971 0.334293 0.917157 0.28935 0.938069 0.236805 0.946653 0.184178 0.938621 0.139025 0.918183 0.113534 0.898261 0.093316 0.875602 0.069451 0.832839 0.054549 0.782228 0.051453 0.730218 0.059864 0.679456 0.079125 0.632687 0.108111 0.592544 0.14521 0.561448 0.188295 0.541488 0.234686 0.534248 0.281148 0.541002 0.324435 0.560508 0.36185 0.591211 0.391247 0.631045 0.338414 0.874794 0.354583 0.856347 0.318068 0.891331 0.280494 0.909045 0.236645 0.916127 0.192726 0.909508 0.154975 0.892192 0.134463 0.875875 0.118105 0.857595 0.097585 0.820929 0.084484 0.776921 0.081543 0.731685 0.088436 0.687433 0.104574 0.646645 0.128939 0.611668 0.160083 0.584626 0.196135 0.567284 0.234825 0.560702 0.27358 0.566876 0.309807 0.583837 0.341226 0.610548 0.365948 0.645265 0.382504 0.685879 0.389851 0.730057 0.387374 0.775321 0.374725 0.819465 0.273981 0.887972 0.306104 0.872649 0.236528 0.894005 0.199016 0.888371 0.16674 0.87339 0.149826 0.859661 0.136453 0.844382 0.118722 0.812016 0.107215 0.772841 0.104481 0.732647 0.110247 0.693244 0.124002 0.656892 0.144825 0.625716 0.171407 0.601626 0.202088 0.586215 0.23493 0.580614 0.267827 0.585867 0.298664 0.600951 0.32549 0.624757 0.34663 0.655711 0.360755 0.691914 0.366924 0.731254 0.364601 0.771474 0.353496 0.810769 0.336096 0.843321 0.322881 0.858741 0.315855 0.85165 0.327681 0.837518 0.300706 0.864364 0.271061 0.878583 0.236475 0.884143 0.201836 0.878953 0.172052 0.865053 0.15677 0.852496 0.144808 0.838494 0.128435 0.80801 0.11772 0.770973 0.115103 0.733045 0.120358 0.69583 0.133014 0.661477 0.152196 0.632003 0.176661 0.609221 0.20485 0.594657 0.234977 0.589431 0.265155 0.594337 0.29349 0.6086 0.318186 0.631119 0.337667 0.660388 0.350672 0.694603 0.356307 0.73176 0.354078 0.769714 0.343741 0.806861 0.148898 0.799912 0.162219 0.826842 0.139898 0.767106 0.137556 0.733766 0.141757 0.701019 0.152107 0.670733 0.167829 0.644692 0.187818 0.624514 0.21072 0.611594 0.23507 0.607008 0.259465 0.611333 0.282497 0.624005 0.302689 0.643967 0.318674 0.669838 0.329331 0.70001 0.333864 0.73271 0.33186 0.766073 0.323193 0.798973 0.310144 0.826044 0.301459 0.837638 0.289784 0.84776 0.265153 0.859605 0.236368 0.864232 0.207539 0.859916 0.18279 0.848339 0.171029 0.838349 0.150763 0.703047 0.146992 0.734012 0.160162 0.674375 0.174445 0.649676 0.192562 0.63049 0.21323 0.618165 0.235107 0.613786 0.257027 0.617929 0.277819 0.630029 0.296127 0.649017 0.310659 0.67356 0.320347 0.702129 0.324431 0.733051 0.322509 0.76458 0.314464 0.795902 0.302587 0.821955 0.295756 0.832479 0.285736 0.841094 0.262826 0.852005 0.236325 0.85631 0.209782 0.852293 0.186765 0.841636 0.176675 0.833133 0.169733 0.822676 0.157593 0.796752 0.149232 0.765519 0.352961 0.948595 0.29969 0.972633 0.29969 0.972633 0.236996 0.983312 0.236996 0.983312 0.1742 0.973288 0.1742 0.973288 0.120687 0.949809 0.120687 0.949809 0.088063 0.925486 0.088063 0.925486 0.063365 0.89609 0.063365 0.89609 0.03675 0.846184 0.03675 0.846184 0.020267 0.78806 0.020267 0.78806 0.017118 0.728298 0.017118 0.728298 0.027284 0.67002 0.027284 0.67002 0.050082 0.616306 0.050082 0.616306 0.084282 0.570113 0.084282 0.570113 0.128117 0.534196 0.128117 0.534196 0.179226 0.51103 0.179226 0.51103 0.234521 0.50269 0.234521 0.50269 0.289898 0.510454 0.289898 0.510454 0.341241 0.533082 0.341241 0.533082 0.385441 0.568536 0.385441 0.568536 0.420115 0.614365 0.420115 0.614365 0.443469 0.667835 0.443469 0.667835 0.454237 0.726007 0.454237 0.726007 0.451702 0.785798 0.451702 0.785798 0.435823 0.844089 0.435823 0.844089 0.409726 0.894275 0.409726 0.894275 0.385331 0.923932 0.385331 0.923932 0.352961 0.948595</float_array>
+ <technique_common>
+ <accessor source="#Headphones-headphonesUV-array" count="1829" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Headphones-vertices">
+ <input semantic="POSITION" source="#Headphones-positions"/>
+ </vertices>
+ <triangles material="HeadphonesSG" count="420">
+ <input semantic="VERTEX" source="#Headphones-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Headphones-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Headphones-headphonesUV" offset="2" set="1"/>
+ <p>1381 0 0 1383 1 1 1382 3 3 1382 3 3 1383 1 1 1384 2 2 1383 1 1 1385 4 4 1384 2 2 1384 2 2 1385 4 4 1386 5 5 1392 6 6 1394 7 7 1391 9 9 1391 9 9 1394 7 7 1393 8 8 1394 7 7 1396 10 10 1393 8 8 1393 8 8 1396 10 10 1395 11 11 1396 10 10 1398 12 12 1395 11 11 1395 11 11 1398 12 12 1397 13 13 1398 12 12 1400 14 14 1397 13 13 1397 13 13 1400 14 14 1399 15 15 1401 16 16 1399 15 15 1402 17 17 1402 17 17 1399 15 15 1400 14 14 1403 18 18 1401 16 16 1404 19 19 1404 19 19 1401 16 16 1402 17 17 1405 20 20 1403 18 18 1406 21 21 1406 21 21 1403 18 18 1404 19 19 1407 22 22 1405 20 20 1408 23 23 1408 23 23 1405 20 20 1406 21 21 1368 24 24 1369 25 25 1367 27 27 1367 27 27 1369 25 25 1370 26 26 1369 25 25 1371 28 28 1370 26 26 1370 26 26 1371 28 28 1372 29 29 1413 31 31 1414 32 32 1411 30 30 1411 30 30 1414 32 32 1412 33 33 1371 28 28 1373 34 34 1372 29 29 1372 29 29 1373 34 34 1374 35 35 1413 31 31 1415 36 36 1414 32 32 1414 32 32 1415 36 36 1416 37 37 1373 34 34 1375 38 38 1374 35 35 1374 35 35 1375 38 38 1376 39 39 1415 36 36 1417 40 40 1416 37 37 1416 37 37 1417 40 40 1418 41 41 1375 38 38 1377 42 42 1376 39 39 1376 39 39 1377 42 42 1378 43 43 1417 40 40 1419 44 44 1418 41 41 1418 41 41 1419 44 44 1420 45 45 1419 44 44 1421 46 46 1420 45 45 1420 45 45 1421 46 46 1422 47 47 1424 48 48 1422 47 47 1423 49 49 1423 49 49 1422 47 47 1421 46 46 1423 49 49 1425 50 50 1424 48 48 1424 48 48 1425 50 50 1426 51 51 1428 52 52 1426 51 51 1427 53 53 1427 53 53 1426 51 51 1425 50 50 1427 53 53 1429 54 54 1428 52 52 1428 52 52 1429 54 54 1430 55 55 1451 57 57 1452 58 58 1410 56 56 1410 56 56 1452 58 58 1409 59 59 1436 60 60 1438 61 61 1435 63 63 1435 63 63 1438 61 61 1437 62 62 1439 64 64 1437 62 62 1440 65 65 1440 65 65 1437 62 62 1438 61 61 1440 65 65 1442 66 66 1439 64 64 1439 64 64 1442 66 66 1441 67 67 1442 66 66 1444 68 68 1441 67 67 1441 67 67 1444 68 68 1443 69 69 1377 42 42 1379 70 70 1378 43 43 1378 43 43 1379 70 70 1380 71 71 1444 68 68 1446 72 72 1443 69 69 1443 69 69 1446 72 72 1445 73 73 1447 74 74 1445 73 73 1448 75 75 1448 75 75 1445 73 73 1446 72 72 1449 76 76 1447 74 74 1450 77 77 1450 77 77 1447 74 74 1448 75 75 1451 57 57 1449 76 76 1452 58 58 1452 58 58 1449 76 76 1450 77 77 1408 23 23 1365 78 78 1407 22 22 1407 22 22 1365 78 78 1366 79 79 1379 70 70 1381 0 0 1380 71 71 1380 71 71 1381 0 0 1382 3 3 1367 27 27 1370 26 26 1366 79 79 1366 79 79 1370 26 26 1407 22 22 1370 26 26 1372 29 29 1407 22 22 1407 22 22 1372 29 29 1405 20 20 1372 29 29 1374 35 35 1405 20 20 1405 20 20 1374 35 35 1403 18 18 1374 35 35 1376 39 39 1403 18 18 1403 18 18 1376 39 39 1401 16 16 1376 39 39 1378 43 43 1401 16 16 1401 16 16 1378 43 43 1399 15 15 1378 43 43 1380 71 71 1399 15 15 1399 15 15 1380 71 71 1397 13 13 1380 71 71 1382 3 3 1397 13 13 1397 13 13 1382 3 3 1395 11 11 1382 3 3 1384 2 2 1395 11 11 1395 11 11 1384 2 2 1393 8 8 1384 2 2 1386 5 5 1393 8 8 1393 8 8 1386 5 5 1391 9 9 1452 58 58 1413 31 31 1409 59 59 1409 59 59 1413 31 31 1411 30 30 1450 77 77 1415 36 36 1452 58 58 1452 58 58 1415 36 36 1413 31 31 1448 75 75 1417 40 40 1450 77 77 1450 77 77 1417 40 40 1415 36 36 1446 72 72 1419 44 44 1448 75 75 1448 75 75 1419 44 44 1417 40 40 1444 68 68 1421 46 46 1446 72 72 1446 72 72 1421 46 46 1419 44 44 1442 66 66 1423 49 49 1444 68 68 1444 68 68 1423 49 49 1421 46 46 1440 65 65 1425 50 50 1442 66 66 1442 66 66 1425 50 50 1423 49 49 1438 61 61 1427 53 53 1440 65 65 1440 65 65 1427 53 53 1425 50 50 1436 60 60 1429 54 54 1438 61 61 1438 61 61 1429 54 54 1427 53 53 1368 24 24 1346 80 80 1369 25 25 1369 25 25 1346 80 80 1347 81 81 1347 81 81 1346 80 80 1414 32 32 1414 32 32 1346 80 80 1412 33 33 1369 25 25 1347 81 81 1371 28 28 1371 28 28 1347 81 81 1348 82 82 1348 82 82 1347 81 81 1416 37 37 1416 37 37 1347 81 81 1414 32 32 1371 28 28 1348 82 82 1373 34 34 1373 34 34 1348 82 82 1349 83 83 1349 83 83 1348 82 82 1418 41 41 1418 41 41 1348 82 82 1416 37 37 1373 34 34 1349 83 83 1375 38 38 1375 38 38 1349 83 83 1350 84 84 1350 84 84 1349 83 83 1420 45 45 1420 45 45 1349 83 83 1418 41 41 1375 38 38 1350 84 84 1377 42 42 1377 42 42 1350 84 84 1351 85 85 1351 85 85 1350 84 84 1422 47 47 1422 47 47 1350 84 84 1420 45 45 1377 42 42 1351 85 85 1379 70 70 1379 70 70 1351 85 85 1352 86 86 1352 86 86 1351 85 85 1424 48 48 1424 48 48 1351 85 85 1422 47 47 1379 70 70 1352 86 86 1381 0 0 1381 0 0 1352 86 86 1353 87 87 1353 87 87 1352 86 86 1426 51 51 1426 51 51 1352 86 86 1424 48 48 1381 0 0 1353 87 87 1383 1 1 1383 1 1 1353 87 87 1354 88 88 1354 88 88 1353 87 87 1428 52 52 1428 52 52 1353 87 87 1426 51 51 1383 1 1 1354 88 88 1385 4 4 1385 4 4 1354 88 88 1355 89 89 1355 89 89 1354 88 88 1430 55 55 1430 55 55 1354 88 88 1428 52 52 1392 6 6 1356 90 90 1394 7 7 1394 7 7 1356 90 90 1357 91 91 1357 91 92 1356 90 93 1437 62 62 1437 62 62 1356 90 93 1435 63 63 1394 7 7 1357 91 91 1396 10 10 1396 10 10 1357 91 91 1358 92 94 1358 92 95 1357 91 96 1439 64 64 1439 64 64 1357 91 96 1437 62 62 1396 10 10 1358 92 94 1398 12 12 1398 12 12 1358 92 94 1359 93 97 1359 93 98 1358 92 99 1441 67 67 1441 67 67 1358 92 99 1439 64 64 1398 12 12 1359 93 97 1400 14 14 1400 14 14 1359 93 97 1360 94 100 1360 94 101 1359 93 102 1443 69 69 1443 69 69 1359 93 102 1441 67 67 1400 14 14 1360 94 100 1402 17 17 1402 17 17 1360 94 100 1361 95 103 1361 95 104 1360 94 105 1445 73 73 1445 73 73 1360 94 105 1443 69 69 1402 17 17 1361 95 103 1404 19 19 1404 19 19 1361 95 103 1362 96 106 1362 96 107 1361 95 108 1447 74 74 1447 74 74 1361 95 108 1445 73 73 1404 19 19 1362 96 106 1406 21 21 1406 21 21 1362 96 106 1363 97 109 1363 97 110 1362 96 111 1449 76 76 1449 76 76 1362 96 111 1447 74 74 1406 21 21 1363 97 109 1408 23 23 1408 23 23 1363 97 109 1364 98 112 1364 98 113 1363 97 114 1451 57 57 1451 57 57 1363 97 114 1449 76 76 1408 23 23 1364 98 112 1365 78 78 1365 78 78 1364 98 112 1345 99 115 1345 99 116 1364 98 117 1410 56 56 1410 56 56 1364 98 117 1451 57 57 1513 100 118 1514 101 119 1515 103 121 1515 103 121 1514 101 119 1516 102 120 1515 103 121 1516 102 120 1517 105 123 1517 105 123 1516 102 120 1518 104 122 1524 106 124 1523 107 125 1526 109 127 1526 109 127 1523 107 125 1525 108 126 1526 109 127 1525 108 126 1528 111 129 1528 111 129 1525 108 126 1527 110 128 1528 111 129 1527 110 128 1530 113 131 1530 113 131 1527 110 128 1529 112 130 1530 113 131 1529 112 130 1532 115 133 1532 115 133 1529 112 130 1531 114 132 1533 116 134 1534 117 135 1531 114 132 1531 114 132 1534 117 135 1532 115 133 1535 118 136 1536 119 137 1533 116 134 1533 116 134 1536 119 137 1534 117 135 1537 120 138 1538 121 139 1535 118 136 1535 118 136 1538 121 139 1536 119 137 1539 122 140 1540 123 141 1537 120 138 1537 120 138 1540 123 141 1538 121 139 1500 124 142 1499 125 143 1501 127 145 1501 127 145 1499 125 143 1502 126 144 1501 127 145 1502 126 144 1503 129 147 1503 129 147 1502 126 144 1504 128 146 1544 131 149 1546 132 150 1543 130 148 1543 130 148 1546 132 150 1545 133 151 1503 129 147 1504 128 146 1505 135 153 1505 135 153 1504 128 146 1506 134 152 1545 133 151 1546 132 150 1547 137 155 1547 137 155 1546 132 150 1548 136 154 1505 135 153 1506 134 152 1507 139 157 1507 139 157 1506 134 152 1508 138 156 1547 137 155 1548 136 154 1549 141 159 1549 141 159 1548 136 154 1550 140 158 1507 139 157 1508 138 156 1509 143 161 1509 143 161 1508 138 156 1510 142 160 1549 141 159 1550 140 158 1551 145 163 1551 145 163 1550 140 158 1552 144 162 1551 145 163 1552 144 162 1553 147 165 1553 147 165 1552 144 162 1554 146 164 1556 148 166 1555 149 167 1554 146 164 1554 146 164 1555 149 167 1553 147 165 1555 149 167 1556 148 166 1557 151 169 1557 151 169 1556 148 166 1558 150 168 1560 152 170 1559 153 171 1558 150 168 1558 150 168 1559 153 171 1557 151 169 1559 153 171 1560 152 170 1561 155 173 1561 155 173 1560 152 170 1562 154 172 1541 157 175 1584 158 176 1542 156 174 1542 156 174 1584 158 176 1583 159 177 1568 160 178 1567 161 179 1570 163 181 1570 163 181 1567 161 179 1569 162 180 1571 164 182 1572 165 183 1569 162 180 1569 162 180 1572 165 183 1570 163 181 1572 165 183 1571 164 182 1574 167 185 1574 167 185 1571 164 182 1573 166 184 1574 167 185 1573 166 184 1576 169 187 1576 169 187 1573 166 184 1575 168 186 1509 143 161 1510 142 160 1511 171 189 1511 171 189 1510 142 160 1512 170 188 1576 169 187 1575 168 186 1578 173 191 1578 173 191 1575 168 186 1577 172 190 1579 174 192 1580 175 193 1577 172 190 1577 172 190 1580 175 193 1578 173 191 1581 176 194 1582 177 195 1579 174 192 1579 174 192 1582 177 195 1580 175 193 1583 159 177 1584 158 176 1581 176 194 1581 176 194 1584 158 176 1582 177 195 1540 123 141 1539 122 140 1497 179 197 1497 179 197 1539 122 140 1498 178 196 1511 171 189 1512 170 188 1513 100 118 1513 100 118 1512 170 188 1514 101 119 1499 125 143 1498 178 196 1502 126 144 1502 126 144 1498 178 196 1539 122 140 1502 126 144 1539 122 140 1504 128 146 1504 128 146 1539 122 140 1537 120 138 1504 128 146 1537 120 138 1506 134 152 1506 134 152 1537 120 138 1535 118 136 1506 134 152 1535 118 136 1508 138 156 1508 138 156 1535 118 136 1533 116 134 1508 138 156 1533 116 134 1510 142 160 1510 142 160 1533 116 134 1531 114 132 1510 142 160 1531 114 132 1512 170 188 1512 170 188 1531 114 132 1529 112 130 1512 170 188 1529 112 130 1514 101 119 1514 101 119 1529 112 130 1527 110 128 1514 101 119 1527 110 128 1516 102 120 1516 102 120 1527 110 128 1525 108 126 1516 102 120 1525 108 126 1518 104 122 1518 104 122 1525 108 126 1523 107 125 1584 158 176 1541 157 175 1545 133 151 1545 133 151 1541 157 175 1543 130 148 1582 177 195 1584 158 176 1547 137 155 1547 137 155 1584 158 176 1545 133 151 1580 175 193 1582 177 195 1549 141 159 1549 141 159 1582 177 195 1547 137 155 1578 173 191 1580 175 193 1551 145 163 1551 145 163 1580 175 193 1549 141 159 1576 169 187 1578 173 191 1553 147 165 1553 147 165 1578 173 191 1551 145 163 1574 167 185 1576 169 187 1555 149 167 1555 149 167 1576 169 187 1553 147 165 1572 165 183 1574 167 185 1557 151 169 1557 151 169 1574 167 185 1555 149 167 1570 163 181 1572 165 183 1559 153 171 1559 153 171 1572 165 183 1557 151 169 1568 160 178 1570 163 181 1561 155 173 1561 155 173 1570 163 181 1559 153 171 1500 124 142 1501 127 145 1478 181 199 1478 181 199 1501 127 145 1479 180 198 1479 180 198 1546 132 150 1478 181 199 1478 181 199 1546 132 150 1544 131 149 1501 127 145 1503 129 147 1479 180 198 1479 180 198 1503 129 147 1480 182 200 1480 182 200 1548 136 154 1479 180 198 1479 180 198 1548 136 154 1546 132 150 1503 129 147 1505 135 153 1480 182 200 1480 182 200 1505 135 153 1481 183 201 1481 183 201 1550 140 158 1480 182 200 1480 182 200 1550 140 158 1548 136 154 1505 135 153 1507 139 157 1481 183 201 1481 183 201 1507 139 157 1482 184 202 1482 184 202 1552 144 162 1481 183 201 1481 183 201 1552 144 162 1550 140 158 1507 139 157 1509 143 161 1482 184 202 1482 184 202 1509 143 161 1483 185 203 1483 185 203 1554 146 164 1482 184 202 1482 184 202 1554 146 164 1552 144 162 1509 143 161 1511 171 189 1483 185 203 1483 185 203 1511 171 189 1484 186 204 1484 186 204 1556 148 166 1483 185 203 1483 185 203 1556 148 166 1554 146 164 1511 171 189 1513 100 118 1484 186 204 1484 186 204 1513 100 118 1485 187 205 1485 187 205 1558 150 168 1484 186 204 1484 186 204 1558 150 168 1556 148 166 1513 100 118 1515 103 121 1485 187 205 1485 187 205 1515 103 121 1486 188 206 1486 188 206 1560 152 170 1485 187 205 1485 187 205 1560 152 170 1558 150 168 1515 103 121 1517 105 123 1486 188 206 1486 188 206 1517 105 123 1487 189 207 1487 189 207 1562 154 172 1486 188 206 1486 188 206 1562 154 172 1560 152 170 1524 106 124 1526 109 127 1488 191 209 1488 191 209 1526 109 127 1489 190 208 1489 190 210 1569 162 180 1488 191 211 1488 191 211 1569 162 180 1567 161 179 1526 109 127 1528 111 129 1489 190 208 1489 190 208 1528 111 129 1490 192 212 1490 192 213 1571 164 182 1489 190 214 1489 190 214 1571 164 182 1569 162 180 1528 111 129 1530 113 131 1490 192 212 1490 192 212 1530 113 131 1491 193 215 1491 193 216 1573 166 184 1490 192 217 1490 192 217 1573 166 184 1571 164 182 1530 113 131 1532 115 133 1491 193 215 1491 193 215 1532 115 133 1492 194 218 1492 194 219 1575 168 186 1491 193 220 1491 193 220 1575 168 186 1573 166 184 1532 115 133 1534 117 135 1492 194 218 1492 194 218 1534 117 135 1493 195 221 1493 195 222 1577 172 190 1492 194 223 1492 194 223 1577 172 190 1575 168 186 1534 117 135 1536 119 137 1493 195 221 1493 195 221 1536 119 137 1494 196 224 1494 196 225 1579 174 192 1493 195 226 1493 195 226 1579 174 192 1577 172 190 1536 119 137 1538 121 139 1494 196 224 1494 196 224 1538 121 139 1495 197 227 1495 197 228 1581 176 194 1494 196 229 1494 196 229 1581 176 194 1579 174 192 1538 121 139 1540 123 141 1495 197 227 1495 197 227 1540 123 141 1496 198 230 1496 198 231 1583 159 177 1495 197 232 1495 197 232 1583 159 177 1581 176 194 1540 123 141 1497 179 197 1496 198 230 1496 198 230 1497 179 197 1477 199 233 1477 199 234 1542 156 174 1496 198 235 1496 198 235 1542 156 174 1583 159 177 1498 178 196 1499 125 143 1366 79 79 1366 79 79 1499 125 143 1367 27 27 1499 125 143 1500 124 142 1367 27 27 1367 27 27 1500 124 142 1368 24 24 1500 124 142 1478 181 199 1368 24 24 1368 24 24 1478 181 199 1346 80 80 1478 181 199 1544 131 149 1346 80 80 1346 80 80 1544 131 149 1412 33 33 1544 131 149 1543 130 148 1412 33 33 1412 33 33 1543 130 148 1411 30 30 1543 130 148 1541 157 175 1411 30 30 1411 30 30 1541 157 175 1409 59 59 1541 157 175 1542 156 174 1409 59 59 1409 59 59 1542 156 174 1410 56 56 1542 156 174 1477 199 236 1410 56 56 1410 56 56 1477 199 236 1345 99 237 1477 199 233 1497 179 197 1345 99 115 1345 99 115 1497 179 197 1365 78 78 1497 179 197 1498 178 196 1365 78 78 1365 78 78 1498 178 196 1366 79 79 1601 200 238 1604 201 239 1385 4 4 1385 4 4 1604 201 239 1386 5 5 1605 202 240 1608 203 241 1391 9 9 1391 9 9 1608 203 241 1392 6 6 1430 55 55 1429 54 54 1612 205 243 1612 205 243 1429 54 54 1609 204 242 1613 206 244 1616 207 245 1435 63 63 1435 63 63 1616 207 245 1436 60 60 1604 201 239 1605 202 240 1386 5 5 1386 5 5 1605 202 240 1391 9 9 1609 204 242 1429 54 54 1616 207 245 1616 207 245 1429 54 54 1436 60 60 1355 89 89 1597 208 246 1385 4 4 1385 4 4 1597 208 246 1601 200 238 1355 89 89 1430 55 55 1597 208 246 1597 208 246 1430 55 55 1612 205 243 1600 209 247 1356 90 90 1608 203 241 1608 203 241 1356 90 90 1392 6 6 1600 209 248 1613 206 244 1356 90 249 1356 90 249 1613 206 244 1435 63 63 1518 104 122 1623 210 250 1517 105 123 1517 105 123 1623 210 250 1621 211 251 1524 106 124 1628 212 252 1523 107 125 1523 107 125 1628 212 252 1626 213 253 1630 214 254 1561 155 173 1631 215 255 1631 215 255 1561 155 173 1562 154 172 1568 160 178 1636 216 256 1567 161 179 1567 161 179 1636 216 256 1634 217 257 1523 107 125 1626 213 253 1518 104 122 1518 104 122 1626 213 253 1623 210 250 1568 160 178 1561 155 173 1636 216 256 1636 216 256 1561 155 173 1630 214 254 1621 211 251 1618 218 258 1517 105 123 1517 105 123 1618 218 258 1487 189 207 1631 215 255 1562 154 172 1618 218 258 1618 218 258 1562 154 172 1487 189 207 1524 106 124 1488 191 209 1628 212 252 1628 212 252 1488 191 209 1619 219 259 1567 161 179 1634 217 257 1488 191 261 1488 191 261 1634 217 257 1619 219 260</p>
+ </triangles>
+ <triangles material="HeadphonesSG1" count="1472">
+ <input semantic="VERTEX" source="#Headphones-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Headphones-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Headphones-headphonesUV" offset="2" set="1"/>
+ <p>1019 221 263 1028 222 264 1029 220 262 1029 220 262 1028 222 264 1038 223 265 1323 225 267 1020 226 268 1324 224 266 1324 224 266 1020 226 268 1030 227 269 1022 229 271 1021 230 272 1032 228 270 1032 228 270 1021 230 272 1031 231 273 1020 226 268 1023 232 274 1030 227 269 1030 227 269 1023 232 274 1033 233 275 1023 234 274 1022 229 271 1033 233 275 1033 233 275 1022 229 271 1032 228 270 1021 230 272 1019 221 263 1031 231 273 1031 231 273 1019 221 263 1029 220 262 1311 235 276 1312 236 277 1025 238 279 1025 238 279 1312 236 277 1034 237 278 1026 239 280 1036 240 281 1024 242 283 1024 242 283 1036 240 281 1035 241 282 1025 238 279 1034 237 278 1027 244 285 1027 244 285 1034 237 278 1037 243 284 1027 244 285 1037 243 284 1026 239 280 1026 239 280 1037 243 284 1036 240 281 1038 223 265 1024 242 283 1029 220 262 1029 220 262 1024 242 283 1035 241 282 1035 241 282 1059 245 286 1029 220 262 1029 220 262 1059 245 286 1031 231 273 1065 247 288 1048 248 289 1327 246 287 1327 246 287 1048 248 289 1325 249 290 1048 248 289 1020 250 268 1325 249 290 1325 249 290 1020 250 268 1323 251 267 1048 248 289 1065 247 288 1049 252 291 1049 252 291 1023 253 274 1048 248 289 1048 248 289 1023 253 274 1020 250 268 1065 247 288 1043 254 292 1049 252 291 1049 252 291 1043 254 292 1050 255 293 1050 255 293 1022 229 271 1049 252 291 1049 252 291 1022 229 271 1023 256 274 1043 254 292 1042 257 294 1050 255 293 1050 255 293 1042 257 294 1051 258 295 1051 258 295 1021 230 272 1050 255 293 1050 255 293 1021 230 272 1022 229 271 1042 257 294 1070 259 296 1051 258 295 1051 258 295 1070 259 296 1052 260 297 1052 260 297 1019 221 263 1051 258 295 1051 258 295 1019 221 263 1021 230 272 1070 259 296 1071 261 298 1052 260 297 1052 260 297 1071 261 298 1053 262 299 1053 262 299 1028 222 264 1052 260 297 1052 260 297 1028 222 264 1019 221 263 1072 264 300 1054 265 301 1071 263 298 1071 263 298 1054 265 301 1053 266 299 1053 266 299 1054 265 301 1028 268 264 1028 268 264 1054 265 301 1038 267 265 1054 265 301 1055 269 302 1038 267 265 1038 267 265 1055 269 302 1024 270 283 1055 269 302 1056 271 303 1024 270 283 1024 270 283 1056 271 303 1026 272 280 1056 271 303 1057 273 304 1026 272 280 1026 272 280 1057 273 304 1027 274 285 1057 273 304 1058 275 305 1027 274 285 1027 274 285 1058 275 305 1025 276 279 1058 275 305 1313 277 306 1025 276 279 1025 276 279 1313 277 306 1311 278 276 1034 237 278 1312 236 277 1060 280 308 1060 280 308 1312 236 277 1326 279 307 1060 280 308 1326 279 307 1030 227 269 1030 227 269 1326 279 307 1324 224 266 1037 243 284 1034 237 278 1061 281 309 1061 281 309 1034 237 278 1060 280 308 1061 281 309 1060 280 308 1033 233 275 1033 233 275 1060 280 308 1030 227 269 1036 240 281 1037 243 284 1062 282 310 1062 282 310 1037 243 284 1061 281 309 1062 282 310 1061 281 309 1032 228 270 1032 228 270 1061 281 309 1033 233 275 1035 241 282 1036 240 281 1059 245 286 1059 245 286 1036 240 281 1062 282 310 1059 245 286 1062 282 310 1031 231 273 1031 231 273 1062 282 310 1032 228 270 1327 246 287 1333 283 311 1065 247 288 1065 247 288 1333 283 311 1066 284 312 1065 247 288 1066 284 312 1043 254 292 1043 254 292 1066 284 312 1063 285 313 1333 283 311 1335 286 314 1066 284 312 1066 284 312 1335 286 314 1067 287 315 1063 285 313 1073 288 316 1069 290 318 1069 290 318 1073 288 316 1064 289 317 1043 254 292 1063 285 313 1042 257 294 1042 257 294 1063 285 313 1068 291 319 1068 291 319 1063 285 313 1069 290 318 1042 257 294 1068 292 319 1070 259 296 1070 259 296 1068 292 319 1047 293 320 1047 293 320 1046 294 321 1070 259 296 1070 259 296 1046 294 321 1071 261 298 1071 263 298 1046 295 321 1072 264 300 1072 264 300 1046 295 321 1045 296 322 1072 264 300 1045 296 322 1077 298 324 1077 298 324 1045 296 322 1044 297 323 1066 284 312 1067 287 315 1063 285 313 1063 285 313 1067 287 315 1073 288 316 1073 288 316 1075 299 325 1064 289 317 1064 289 317 1075 299 325 1074 300 326 1076 301 327 1075 299 325 1067 287 315 1067 287 315 1075 299 325 1073 288 316 1338 302 328 1339 303 329 1075 299 325 1075 299 325 1339 303 329 1074 300 326 1337 304 330 1338 302 328 1076 301 327 1076 301 327 1338 302 328 1075 299 325 1337 304 330 1076 301 327 1335 286 314 1335 286 314 1076 301 327 1067 287 315 1054 265 301 1072 264 300 1055 269 302 1055 269 302 1072 264 300 1077 298 324 1313 277 306 1058 275 305 1315 306 332 1315 306 332 1058 275 305 1078 305 331 1315 306 332 1078 305 331 1314 308 334 1314 308 334 1078 305 331 1039 307 333 1058 275 305 1057 273 304 1078 305 331 1078 305 331 1057 273 304 1079 309 335 1078 305 331 1079 309 335 1039 307 333 1039 307 333 1079 309 335 1040 310 336 1057 273 304 1056 271 303 1079 309 335 1079 309 335 1056 271 303 1080 311 337 1079 309 335 1080 311 337 1040 310 336 1040 310 336 1080 311 337 1041 312 338 1055 269 302 1077 298 324 1056 271 303 1056 271 303 1077 298 324 1080 311 337 1077 298 324 1044 297 323 1080 311 337 1080 311 337 1044 297 323 1041 312 338 1081 314 340 1082 315 341 1084 313 339 1084 313 339 1082 315 341 1083 316 342 1329 317 343 1328 318 344 1086 320 346 1086 320 346 1328 318 344 1085 319 345 1090 321 347 1087 322 348 1089 324 350 1089 324 350 1087 322 348 1088 323 349 1086 320 346 1085 319 345 1092 326 352 1092 326 352 1085 319 345 1091 325 351 1092 326 352 1091 325 351 1090 321 347 1090 321 347 1091 325 351 1087 322 348 1089 324 350 1088 323 349 1084 313 339 1084 313 339 1088 323 349 1081 314 340 1316 328 354 1093 329 355 1317 327 353 1317 327 353 1093 329 355 1094 330 356 1098 331 357 1095 332 358 1097 334 360 1097 334 360 1095 332 358 1096 333 359 1093 329 355 1099 335 361 1094 330 356 1094 330 356 1099 335 361 1100 336 362 1100 336 362 1099 335 361 1098 331 357 1098 331 357 1099 335 361 1095 332 358 1082 315 341 1081 314 340 1096 333 359 1096 333 359 1081 314 340 1097 334 360 1097 334 360 1081 314 340 1101 337 363 1101 337 363 1081 314 340 1088 323 349 1103 338 364 1330 339 365 1102 341 367 1102 341 367 1330 339 365 1331 340 366 1102 341 367 1331 340 366 1086 343 346 1086 343 346 1331 340 366 1329 342 343 1103 338 364 1102 341 367 1104 344 368 1104 344 368 1102 341 367 1092 345 352 1092 345 352 1102 341 367 1086 343 346 1103 338 364 1104 344 368 1106 346 369 1106 346 369 1104 344 368 1105 347 370 1105 347 370 1104 344 368 1090 321 347 1090 321 347 1104 344 368 1092 345 352 1106 346 369 1105 347 370 1108 348 371 1108 348 371 1105 347 370 1107 349 372 1107 349 372 1105 347 370 1089 324 350 1089 324 350 1105 347 370 1090 321 347 1108 348 371 1107 349 372 1110 350 373 1110 350 373 1107 349 372 1109 351 374 1109 351 374 1107 349 372 1084 313 339 1084 313 339 1107 349 372 1089 324 350 1110 350 373 1109 351 374 1112 352 375 1112 352 375 1109 351 374 1111 353 376 1111 354 376 1109 351 374 1083 316 342 1083 316 342 1109 351 374 1084 313 339 1112 356 375 1111 357 376 1114 355 377 1114 355 377 1111 357 376 1113 358 378 1111 354 376 1083 316 342 1113 359 378 1113 359 378 1083 316 342 1082 315 341 1113 358 378 1082 361 341 1115 360 379 1115 360 379 1082 361 341 1096 362 359 1115 360 379 1096 362 359 1116 363 380 1116 363 380 1096 362 359 1095 364 358 1116 363 380 1095 364 358 1117 365 381 1117 365 381 1095 364 358 1099 366 361 1117 365 381 1099 366 361 1118 367 382 1118 367 382 1099 366 361 1093 329 355 1118 367 382 1093 329 355 1318 368 383 1318 368 383 1093 329 355 1316 328 354 1094 330 356 1119 369 384 1317 327 353 1317 327 353 1119 369 384 1332 370 385 1119 369 384 1085 319 345 1332 370 385 1332 370 385 1085 319 345 1328 318 344 1100 336 362 1120 371 386 1094 330 356 1094 330 356 1120 371 386 1119 369 384 1120 371 386 1091 325 351 1119 369 384 1119 369 384 1091 325 351 1085 319 345 1098 331 357 1121 372 387 1100 336 362 1100 336 362 1121 372 387 1120 371 386 1121 372 387 1087 322 348 1120 371 386 1120 371 386 1087 322 348 1091 325 351 1097 334 360 1101 337 363 1098 331 357 1098 331 357 1101 337 363 1121 372 387 1101 337 363 1088 323 349 1121 372 387 1121 372 387 1088 323 349 1087 322 348 1330 339 365 1103 338 364 1334 373 388 1334 373 388 1103 338 364 1122 374 389 1103 338 364 1106 346 369 1122 374 389 1122 374 389 1106 346 369 1123 375 390 1334 373 388 1122 374 389 1336 376 391 1336 376 391 1122 374 389 1124 377 392 1123 375 390 1127 379 394 1131 378 393 1131 378 393 1127 379 394 1130 380 395 1123 375 390 1106 346 369 1108 348 371 1108 348 371 1134 381 396 1123 375 390 1123 375 390 1134 381 396 1127 382 394 1110 350 373 1137 383 397 1108 348 371 1108 348 371 1137 383 397 1134 381 396 1137 385 397 1110 386 373 1140 384 398 1140 384 398 1110 386 373 1112 387 375 1112 388 375 1114 355 377 1140 390 398 1140 390 398 1114 355 377 1143 389 399 1114 355 377 1144 391 400 1143 389 399 1143 389 399 1144 391 400 1147 392 401 1122 374 389 1123 375 390 1124 377 392 1124 377 392 1123 375 390 1131 378 393 1131 378 393 1130 394 395 1151 393 402 1151 393 402 1130 394 395 1150 395 403 1152 396 404 1124 377 392 1151 393 402 1151 393 402 1124 377 392 1131 378 393 1151 393 402 1150 395 403 1341 397 405 1341 397 405 1150 395 403 1344 398 406 1340 399 407 1152 396 404 1341 397 405 1341 397 405 1152 396 404 1151 393 402 1340 399 407 1336 376 391 1152 396 404 1152 396 404 1336 376 391 1124 377 392 1113 358 378 1115 360 379 1114 355 377 1114 355 377 1115 360 379 1144 391 400 1318 368 383 1319 400 408 1118 367 382 1118 367 382 1319 400 408 1153 401 409 1319 400 408 1322 402 410 1153 401 409 1153 401 409 1322 402 410 1156 403 411 1118 367 382 1153 401 409 1117 365 381 1117 365 381 1153 401 409 1157 404 412 1153 401 409 1156 403 411 1157 404 412 1157 404 412 1156 403 411 1160 405 413 1117 365 381 1157 404 412 1116 363 380 1116 363 380 1157 404 412 1161 406 414 1157 404 412 1160 405 413 1161 406 414 1161 406 414 1160 405 413 1164 407 415 1115 360 379 1116 363 380 1144 391 400 1144 391 400 1116 363 380 1161 406 414 1144 391 400 1161 406 414 1147 392 401 1147 392 401 1161 406 414 1164 407 415 1125 408 416 1069 409 318 1128 411 417 1128 411 417 1069 409 318 1064 410 317 1127 412 394 1126 413 418 1130 415 395 1130 415 395 1126 413 418 1129 414 419 1068 417 319 1069 409 318 1132 416 420 1132 416 420 1069 409 318 1125 408 416 1133 419 421 1126 413 418 1134 418 396 1134 418 396 1126 413 418 1127 412 394 1135 420 422 1047 421 320 1132 416 420 1132 416 420 1047 421 320 1068 422 319 1137 423 397 1136 424 423 1134 418 396 1134 418 396 1136 424 423 1133 419 421 1046 426 321 1047 421 320 1138 425 424 1138 425 424 1047 421 320 1135 420 422 1139 428 425 1136 424 423 1140 427 398 1140 427 398 1136 424 423 1137 423 397 1141 429 426 1045 430 322 1138 432 424 1138 432 424 1045 430 322 1046 431 321 1143 433 399 1142 434 427 1140 436 398 1140 436 398 1142 434 427 1139 435 425 1145 437 428 1044 438 323 1141 429 426 1141 429 426 1044 438 323 1045 430 322 1147 439 401 1146 440 429 1143 433 399 1143 433 399 1146 440 429 1142 434 427 1064 410 317 1074 441 326 1128 411 417 1128 411 417 1074 441 326 1148 442 430 1129 414 419 1149 444 431 1130 443 395 1130 443 395 1149 444 431 1150 445 403 1074 441 326 1339 446 329 1148 442 430 1148 442 430 1339 446 329 1342 447 432 1149 444 431 1343 448 433 1150 445 403 1150 445 403 1343 448 433 1344 449 406 1320 450 434 1314 451 334 1154 453 435 1154 453 435 1314 451 334 1039 452 333 1322 454 410 1321 455 436 1156 457 411 1156 457 411 1321 455 436 1155 456 437 1154 453 435 1039 452 333 1158 459 438 1158 459 438 1039 452 333 1040 458 336 1156 457 411 1155 456 437 1160 461 413 1160 461 413 1155 456 437 1159 460 439 1158 459 438 1040 458 336 1162 463 440 1162 463 440 1040 458 336 1041 462 338 1160 461 413 1159 460 439 1164 465 415 1164 465 415 1159 460 439 1163 464 441 1162 463 440 1041 462 338 1145 437 428 1145 437 428 1041 462 338 1044 438 323 1164 465 415 1163 464 441 1147 439 401 1147 439 401 1163 464 441 1146 440 429 1128 411 417 1148 442 430 1129 414 419 1129 414 419 1148 442 430 1149 444 431 1148 442 430 1342 447 432 1149 444 431 1149 444 431 1342 447 432 1343 448 433 1321 455 436 1320 450 434 1155 456 437 1155 456 437 1320 450 434 1154 453 435 1155 456 437 1154 453 435 1159 460 439 1159 460 439 1154 453 435 1158 459 438 1159 460 439 1158 459 438 1163 464 441 1163 464 441 1158 459 438 1162 463 440 1163 464 441 1162 463 440 1146 440 429 1146 440 429 1162 463 440 1145 437 428 1146 440 429 1145 437 428 1142 434 427 1142 434 427 1145 437 428 1141 429 426 1142 434 427 1141 429 426 1139 435 425 1139 435 425 1141 429 426 1138 466 424 1138 468 424 1135 420 422 1139 467 425 1139 467 425 1135 420 422 1136 424 423 1136 424 423 1135 420 422 1133 419 421 1133 419 421 1135 420 422 1132 416 420 1132 416 420 1125 408 416 1133 419 421 1133 419 421 1125 408 416 1126 413 418 1126 413 418 1125 408 416 1129 414 419 1129 414 419 1125 408 416 1128 411 417 1184 470 443 1174 471 444 1175 469 442 1175 469 442 1174 471 444 1165 472 445 1176 473 446 1166 474 447 1324 224 266 1324 224 266 1166 474 447 1323 225 267 1177 476 449 1167 477 450 1178 475 448 1178 475 448 1167 477 450 1168 478 451 1179 479 452 1169 480 453 1176 473 446 1176 473 446 1169 480 453 1166 474 447 1178 475 448 1168 478 451 1179 479 452 1179 479 452 1168 478 451 1169 481 453 1175 469 442 1165 472 445 1177 476 449 1177 476 449 1165 472 445 1167 477 450 1311 235 276 1171 482 454 1312 236 277 1312 236 277 1171 482 454 1180 483 455 1172 484 456 1170 485 457 1182 487 459 1182 487 459 1170 485 457 1181 486 458 1171 482 454 1173 488 460 1180 483 455 1180 483 455 1173 488 460 1183 489 461 1173 488 460 1172 484 456 1183 489 461 1183 489 461 1172 484 456 1182 487 459 1184 470 443 1175 469 442 1170 485 457 1170 485 457 1175 469 442 1181 486 458 1177 476 449 1205 490 462 1175 469 442 1175 469 442 1205 490 462 1181 486 458 1325 249 290 1194 491 463 1327 246 287 1327 246 287 1194 491 463 1211 492 464 1323 251 267 1166 493 447 1325 249 290 1325 249 290 1166 493 447 1194 491 463 1194 491 463 1195 494 465 1211 492 464 1166 493 447 1169 495 453 1194 491 463 1194 491 463 1169 495 453 1195 494 465 1211 492 464 1195 494 465 1189 497 467 1189 497 467 1195 494 465 1196 496 466 1169 498 453 1168 478 451 1195 494 465 1195 494 465 1168 478 451 1196 496 466 1189 497 467 1196 496 466 1188 500 469 1188 500 469 1196 496 466 1197 499 468 1168 478 451 1167 477 450 1196 496 466 1196 496 466 1167 477 450 1197 499 468 1188 500 469 1197 499 468 1216 502 471 1216 502 471 1197 499 468 1198 501 470 1167 477 450 1165 472 445 1197 499 468 1197 499 468 1165 472 445 1198 501 470 1216 502 471 1198 501 470 1217 504 473 1217 504 473 1198 501 470 1199 503 472 1165 472 445 1174 471 444 1198 501 470 1198 501 470 1174 471 444 1199 503 472 1199 506 472 1200 507 474 1217 505 473 1217 505 473 1200 507 474 1218 508 475 1199 506 472 1174 509 444 1200 507 474 1200 507 474 1174 509 444 1184 510 443 1200 507 474 1184 510 443 1201 512 476 1201 512 476 1184 510 443 1170 511 457 1201 512 476 1170 511 457 1202 514 477 1202 514 477 1170 511 457 1172 513 456 1202 514 477 1172 513 456 1203 516 478 1203 516 478 1172 513 456 1173 515 460 1203 516 478 1173 515 460 1204 518 479 1204 518 479 1173 515 460 1171 517 454 1204 518 479 1171 517 454 1313 277 306 1313 277 306 1171 517 454 1311 278 276 1180 483 455 1206 519 480 1312 236 277 1312 236 277 1206 519 480 1326 279 307 1206 519 480 1176 473 446 1326 279 307 1326 279 307 1176 473 446 1324 224 266 1183 489 461 1207 520 481 1180 483 455 1180 483 455 1207 520 481 1206 519 480 1207 520 481 1179 479 452 1206 519 480 1206 519 480 1179 479 452 1176 473 446 1182 487 459 1208 521 482 1183 489 461 1183 489 461 1208 521 482 1207 520 481 1208 521 482 1178 475 448 1207 520 481 1207 520 481 1178 475 448 1179 479 452 1181 486 458 1205 490 462 1182 487 459 1182 487 459 1205 490 462 1208 521 482 1205 490 462 1177 476 449 1208 521 482 1208 521 482 1177 476 449 1178 475 448 1327 246 287 1211 492 464 1333 283 311 1333 283 311 1211 492 464 1212 522 483 1211 492 464 1189 497 467 1212 522 483 1212 522 483 1189 497 467 1209 523 484 1333 283 311 1212 522 483 1335 286 314 1335 286 314 1212 522 483 1213 524 485 1209 523 484 1215 525 486 1219 527 488 1219 527 488 1215 525 486 1210 526 487 1189 497 467 1188 500 469 1209 523 484 1188 500 469 1214 528 489 1209 523 484 1209 523 484 1214 528 489 1215 525 486 1193 529 490 1214 530 489 1216 502 471 1216 502 471 1214 530 489 1188 500 469 1193 529 490 1216 502 471 1192 531 491 1192 531 491 1216 502 471 1217 504 473 1191 532 492 1192 533 491 1218 508 475 1218 508 475 1192 533 491 1217 505 473 1218 508 475 1223 534 493 1191 532 492 1191 532 492 1223 534 493 1190 535 494 1212 522 483 1209 523 484 1213 524 485 1213 524 485 1209 523 484 1219 527 488 1219 527 488 1210 526 487 1221 537 496 1221 537 496 1210 526 487 1220 536 495 1219 527 488 1221 537 496 1213 524 485 1213 524 485 1221 537 496 1222 538 497 1220 536 495 1339 303 329 1221 537 496 1221 537 496 1339 303 329 1338 302 328 1221 537 496 1338 302 328 1222 538 497 1222 538 497 1338 302 328 1337 304 330 1337 304 330 1335 286 314 1222 538 497 1222 538 497 1335 286 314 1213 524 485 1223 534 493 1218 508 475 1201 512 476 1201 512 476 1218 508 475 1200 507 474 1313 277 306 1315 306 332 1204 518 479 1204 518 479 1315 306 332 1224 539 498 1315 306 332 1314 308 334 1224 539 498 1224 539 498 1314 308 334 1185 540 499 1204 518 479 1224 539 498 1203 516 478 1203 516 478 1224 539 498 1225 541 500 1224 539 498 1185 540 499 1225 541 500 1225 541 500 1185 540 499 1186 542 501 1203 516 478 1225 541 500 1202 514 477 1202 514 477 1225 541 500 1226 543 502 1225 541 500 1186 542 501 1226 543 502 1226 543 502 1186 542 501 1187 544 503 1226 543 502 1223 534 493 1202 514 477 1202 514 477 1223 534 493 1201 512 476 1187 544 503 1190 535 494 1226 543 502 1226 543 502 1190 535 494 1223 534 493 1229 546 505 1228 547 506 1230 545 504 1230 545 504 1228 547 506 1227 548 507 1329 317 343 1232 549 508 1328 318 344 1328 318 344 1232 549 508 1231 550 509 1236 551 510 1235 552 511 1233 554 513 1233 554 513 1235 552 511 1234 553 512 1232 549 508 1238 555 514 1231 550 509 1231 550 509 1238 555 514 1237 556 515 1238 555 514 1236 551 510 1237 556 515 1237 556 515 1236 551 510 1233 554 513 1235 552 511 1230 545 504 1234 553 512 1234 553 512 1230 545 504 1227 548 507 1240 557 516 1239 558 517 1317 327 353 1317 327 353 1239 558 517 1316 328 354 1244 559 518 1243 560 519 1241 562 521 1241 562 521 1243 560 519 1242 561 520 1246 563 522 1245 564 523 1240 557 516 1240 557 516 1245 564 523 1239 558 517 1246 563 522 1244 559 518 1245 564 523 1245 564 523 1244 559 518 1241 562 521 1243 560 519 1227 548 507 1242 561 520 1242 561 520 1227 548 507 1228 547 506 1243 560 519 1247 565 524 1227 548 507 1227 548 507 1247 565 524 1234 553 512 1249 566 525 1248 567 526 1330 339 365 1330 339 365 1248 567 526 1331 340 366 1248 567 526 1232 568 508 1331 340 366 1331 340 366 1232 568 508 1329 342 343 1249 566 525 1250 569 527 1248 567 526 1250 569 527 1238 570 514 1248 567 526 1248 567 526 1238 570 514 1232 568 508 1251 572 529 1250 569 527 1252 571 528 1252 571 528 1250 569 527 1249 566 525 1251 572 529 1236 551 510 1250 569 527 1250 569 527 1236 551 510 1238 570 514 1253 574 531 1251 572 529 1254 573 530 1254 573 530 1251 572 529 1252 571 528 1253 574 531 1235 552 511 1251 572 529 1251 572 529 1235 552 511 1236 551 510 1255 576 533 1253 574 531 1256 575 532 1256 575 532 1253 574 531 1254 573 530 1255 576 533 1230 545 504 1253 574 531 1253 574 531 1230 545 504 1235 552 511 1257 578 535 1255 576 533 1258 577 534 1258 577 534 1255 576 533 1256 575 532 1257 579 535 1229 546 505 1255 576 533 1255 576 533 1229 546 505 1230 545 504 1259 581 537 1257 582 535 1260 580 536 1260 580 536 1257 582 535 1258 583 534 1228 547 506 1229 546 505 1259 584 537 1259 584 537 1229 546 505 1257 579 535 1242 586 520 1228 587 506 1261 585 538 1261 585 538 1228 587 506 1259 581 537 1241 589 521 1242 586 520 1262 588 539 1262 588 539 1242 586 520 1261 585 538 1245 591 523 1241 589 521 1263 590 540 1263 590 540 1241 589 521 1262 588 539 1239 558 517 1245 591 523 1264 592 541 1264 592 541 1245 591 523 1263 590 540 1316 328 354 1239 558 517 1318 368 383 1318 368 383 1239 558 517 1264 592 541 1332 370 385 1265 593 542 1317 327 353 1317 327 353 1265 593 542 1240 557 516 1328 318 344 1231 550 509 1332 370 385 1332 370 385 1231 550 509 1265 593 542 1265 593 542 1266 594 543 1240 557 516 1240 557 516 1266 594 543 1246 563 522 1231 550 509 1237 556 515 1265 593 542 1265 593 542 1237 556 515 1266 594 543 1266 594 543 1267 595 544 1246 563 522 1246 563 522 1267 595 544 1244 559 518 1237 556 515 1233 554 513 1266 594 543 1266 594 543 1233 554 513 1267 595 544 1267 595 544 1247 565 524 1244 559 518 1244 559 518 1247 565 524 1243 560 519 1233 554 513 1234 553 512 1267 595 544 1267 595 544 1234 553 512 1247 565 524 1268 596 545 1249 566 525 1334 373 388 1334 373 388 1249 566 525 1330 339 365 1269 597 546 1252 571 528 1268 596 545 1268 596 545 1252 571 528 1249 566 525 1270 598 547 1268 596 545 1336 376 391 1336 376 391 1268 596 545 1334 373 388 1276 600 549 1273 601 550 1277 599 548 1277 599 548 1273 601 550 1269 597 546 1269 597 546 1254 573 530 1252 571 528 1273 602 550 1280 603 551 1269 597 546 1269 597 546 1280 603 551 1254 573 530 1280 603 551 1283 604 552 1254 573 530 1254 573 530 1283 604 552 1256 575 532 1258 606 534 1256 607 532 1286 605 553 1286 605 553 1256 607 532 1283 608 552 1258 609 534 1286 610 553 1260 580 536 1260 580 536 1286 610 553 1289 611 554 1293 612 555 1290 613 556 1289 611 554 1289 611 554 1290 613 556 1260 580 536 1277 599 548 1269 597 546 1270 598 547 1270 598 547 1269 597 546 1268 596 545 1296 615 558 1276 616 549 1297 614 557 1297 614 557 1276 616 549 1277 599 548 1298 617 559 1297 614 557 1270 598 547 1270 598 547 1297 614 557 1277 599 548 1344 398 406 1296 615 558 1341 397 405 1341 397 405 1296 615 558 1297 614 557 1340 399 407 1341 397 405 1298 617 559 1298 617 559 1341 397 405 1297 614 557 1270 598 547 1336 376 391 1298 617 559 1298 617 559 1336 376 391 1340 399 407 1259 581 537 1260 580 536 1261 585 538 1261 585 538 1260 580 536 1290 613 556 1299 618 560 1319 400 408 1264 592 541 1264 592 541 1319 400 408 1318 368 383 1302 619 561 1322 402 410 1299 618 560 1299 618 560 1322 402 410 1319 400 408 1303 620 562 1299 618 560 1263 590 540 1263 590 540 1299 618 560 1264 592 541 1306 621 563 1302 619 561 1303 620 562 1303 620 562 1302 619 561 1299 618 560 1307 622 564 1303 620 562 1262 588 539 1262 588 539 1303 620 562 1263 590 540 1310 623 565 1306 621 563 1307 622 564 1307 622 564 1306 621 563 1303 620 562 1261 585 538 1290 613 556 1262 588 539 1262 588 539 1290 613 556 1307 622 564 1290 613 556 1293 612 555 1307 622 564 1307 622 564 1293 612 555 1310 623 565 1271 624 566 1274 625 567 1215 627 486 1215 627 486 1274 625 567 1210 626 487 1273 628 550 1276 629 549 1272 631 569 1272 631 569 1276 629 549 1275 630 568 1271 624 566 1215 627 486 1278 632 570 1278 632 570 1215 627 486 1214 633 489 1273 628 550 1272 631 569 1280 634 551 1280 634 551 1272 631 569 1279 635 571 1281 636 572 1278 632 570 1193 638 490 1193 638 490 1278 632 570 1214 637 489 1283 639 552 1280 634 551 1282 640 573 1282 640 573 1280 634 551 1279 635 571 1281 636 572 1193 638 490 1284 641 574 1284 641 574 1193 638 490 1192 642 491 1283 639 552 1282 640 573 1286 643 553 1286 643 553 1282 640 573 1285 644 575 1287 645 576 1284 646 574 1191 648 492 1191 648 492 1284 646 574 1192 647 491 1289 649 554 1286 650 553 1288 652 577 1288 652 577 1286 650 553 1285 651 575 1291 653 578 1287 645 576 1190 654 494 1190 654 494 1287 645 576 1191 648 492 1293 655 555 1289 649 554 1292 656 579 1292 656 579 1289 649 554 1288 652 577 1294 657 580 1220 658 495 1274 625 567 1274 625 567 1220 658 495 1210 626 487 1296 660 558 1295 661 581 1276 659 549 1276 659 549 1295 661 581 1275 630 568 1342 447 432 1339 446 329 1294 657 580 1294 657 580 1339 446 329 1220 658 495 1344 449 406 1343 448 433 1296 660 558 1296 660 558 1343 448 433 1295 661 581 1320 450 434 1300 662 582 1314 451 334 1314 451 334 1300 662 582 1185 663 499 1322 454 410 1302 664 561 1321 455 436 1321 455 436 1302 664 561 1301 665 583 1300 662 582 1304 666 584 1185 663 499 1185 663 499 1304 666 584 1186 667 501 1302 664 561 1306 668 563 1301 665 583 1301 665 583 1306 668 563 1305 669 585 1304 666 584 1308 670 586 1186 667 501 1186 667 501 1308 670 586 1187 671 503 1306 668 563 1310 672 565 1305 669 585 1305 669 585 1310 672 565 1309 673 587 1308 670 586 1291 653 578 1187 671 503 1187 671 503 1291 653 578 1190 654 494 1310 672 565 1293 655 555 1309 673 587 1309 673 587 1293 655 555 1292 656 579 1295 661 581 1294 657 580 1275 630 568 1275 630 568 1294 657 580 1274 625 567 1343 448 433 1342 447 432 1295 661 581 1295 661 581 1342 447 432 1294 657 580 1321 455 436 1301 665 583 1320 450 434 1320 450 434 1301 665 583 1300 662 582 1301 665 583 1305 669 585 1300 662 582 1300 662 582 1305 669 585 1304 666 584 1305 669 585 1309 673 587 1304 666 584 1304 666 584 1309 673 587 1308 670 586 1309 673 587 1292 656 579 1308 670 586 1308 670 586 1292 656 579 1291 653 578 1292 656 579 1288 652 577 1291 653 578 1291 653 578 1288 652 577 1287 645 576 1288 652 577 1285 651 575 1287 645 576 1287 645 576 1285 651 575 1284 674 574 1282 640 573 1281 636 572 1285 675 575 1285 675 575 1281 636 572 1284 676 574 1282 640 573 1279 635 571 1281 636 572 1281 636 572 1279 635 571 1278 632 570 1272 631 569 1271 624 566 1279 635 571 1279 635 571 1271 624 566 1278 632 570 1272 631 569 1275 630 568 1271 624 566 1271 624 566 1275 630 568 1274 625 567 1388 677 588 1453 678 589 1456 680 591 1456 680 591 1453 678 589 1463 679 590 1431 681 592 1459 682 593 1453 678 589 1453 678 589 1459 682 593 1463 679 590 1431 681 592 1432 683 594 1459 682 593 1459 682 593 1432 683 594 1460 684 595 1432 683 594 1433 685 596 1460 684 595 1460 684 595 1433 685 596 1461 686 597 1433 685 596 1434 687 598 1461 686 597 1461 686 597 1434 687 598 1462 688 599 1434 687 598 1454 689 600 1462 688 599 1462 688 599 1454 689 600 1464 690 601 1389 691 603 1457 692 604 1454 689 602 1454 689 602 1457 692 604 1464 690 605 1389 691 603 1390 693 606 1457 692 604 1457 692 604 1390 693 606 1458 694 607 1390 693 606 1387 695 608 1458 694 607 1458 694 607 1387 695 608 1455 696 609 1387 695 608 1388 677 588 1455 696 609 1455 696 609 1388 677 588 1456 680 591 1463 679 590 1459 682 593 1456 680 591 1464 690 612 1457 692 613 1462 688 611 1456 680 591 1459 682 593 1455 696 609 1462 688 611 1457 692 613 1461 686 610 1461 686 610 1457 692 613 1460 684 595 1455 696 609 1459 682 593 1458 694 614 1460 684 595 1457 692 613 1459 682 593 1459 682 593 1457 692 613 1458 694 614 1520 697 615 1588 698 616 1585 700 618 1585 700 618 1588 698 616 1595 699 617 1595 699 617 1591 701 619 1585 700 618 1585 700 618 1591 701 619 1563 702 620 1563 702 620 1591 701 619 1564 704 622 1564 704 622 1591 701 619 1592 703 621 1564 704 622 1592 703 621 1565 706 624 1565 706 624 1592 703 621 1593 705 623 1565 706 624 1593 705 623 1566 708 626 1566 708 626 1593 705 623 1594 707 625 1566 708 626 1594 707 625 1586 710 628 1586 710 628 1594 707 625 1596 709 627 1596 709 630 1589 711 631 1586 710 629 1586 710 629 1589 711 631 1521 712 632 1521 712 632 1589 711 631 1522 714 634 1522 714 634 1589 711 631 1590 713 633 1522 714 634 1590 713 633 1519 716 636 1519 716 636 1590 713 633 1587 715 635 1519 716 636 1587 715 635 1520 697 615 1520 697 615 1587 715 635 1588 698 616 1596 709 639 1594 707 640 1589 711 638 1595 699 617 1588 698 616 1591 701 619 1588 698 616 1587 715 635 1591 701 619 1589 711 638 1594 707 640 1590 713 637 1587 715 635 1590 713 637 1591 701 619 1594 707 640 1593 705 641 1590 713 637 1593 705 641 1592 703 621 1590 713 637 1590 713 637 1592 703 621 1591 701 619 1622 717 642 1617 718 643 1638 720 645 1638 720 645 1617 718 643 1637 719 644 1638 720 645 1637 719 644 1621 211 251 1621 211 251 1637 719 644 1618 218 258 1612 205 243 1609 204 242 1640 722 647 1640 722 647 1609 204 242 1639 721 646 1640 722 647 1639 721 646 1611 724 649 1611 724 649 1639 721 646 1610 723 648 1614 726 651 1641 727 652 1599 725 650 1599 725 650 1641 727 652 1642 728 653 1641 727 652 1613 206 244 1642 728 653 1642 728 653 1613 206 244 1600 209 654 1625 729 655 1624 730 656 1644 732 658 1644 732 658 1624 730 656 1643 731 657 1643 731 657 1623 210 250 1644 732 658 1644 732 658 1623 210 250 1626 213 253 1606 733 659 1607 734 660 1646 736 662 1646 736 662 1607 734 660 1645 735 661 1646 736 662 1645 735 661 1605 202 240 1605 202 240 1645 735 661 1608 203 241 1629 738 664 1647 739 665 1632 737 663 1632 737 663 1647 739 665 1648 740 666 1647 739 665 1630 214 254 1648 740 666 1648 740 666 1630 214 254 1631 215 255 1616 207 245 1649 741 667 1609 204 242 1609 204 242 1649 741 667 1639 721 646 1639 721 646 1649 741 667 1610 723 648 1610 723 648 1649 741 667 1615 742 668 1636 216 256 1630 214 254 1650 743 669 1650 743 669 1630 214 254 1647 739 665 1647 739 665 1629 738 664 1650 743 669 1650 743 669 1629 738 664 1635 744 670 1618 218 258 1637 719 644 1631 215 255 1631 215 255 1637 719 644 1648 740 666 1637 719 644 1617 718 643 1648 740 666 1648 740 666 1617 718 643 1632 737 663 1633 745 671 1620 746 672 1652 748 674 1652 748 674 1620 746 672 1651 747 673 1652 748 674 1651 747 673 1634 217 257 1634 217 257 1651 747 673 1619 219 675 1635 744 670 1633 745 671 1650 743 669 1650 743 669 1633 745 671 1652 748 674 1650 743 669 1652 748 674 1636 216 256 1636 216 256 1652 748 674 1634 217 257 1615 742 668 1649 741 667 1614 726 651 1614 726 651 1649 741 667 1641 727 652 1649 741 667 1616 207 245 1641 727 652 1641 727 652 1616 207 245 1613 206 244 1619 219 259 1651 747 676 1628 212 252 1628 212 252 1651 747 676 1653 749 677 1651 747 678 1620 746 679 1653 749 677 1653 749 677 1620 746 679 1627 750 680 1607 734 660 1599 725 681 1645 735 661 1645 735 661 1599 725 681 1642 728 682 1645 735 661 1642 728 683 1608 203 241 1608 203 241 1642 728 683 1600 209 247 1605 202 240 1604 201 239 1646 736 662 1646 736 662 1604 201 239 1654 751 684 1654 751 684 1603 752 685 1646 736 662 1646 736 662 1603 752 685 1606 733 659 1625 729 655 1644 732 658 1627 750 680 1627 750 680 1644 732 658 1653 749 677 1644 732 658 1626 213 253 1653 749 677 1653 749 677 1626 213 253 1628 212 252 1624 730 656 1622 717 642 1643 731 657 1643 731 657 1622 717 642 1638 720 645 1643 731 657 1638 720 645 1623 210 250 1623 210 250 1638 720 645 1621 211 251 1602 754 687 1655 755 688 1598 753 686 1598 753 686 1655 755 688 1656 756 689 1655 755 688 1601 200 238 1656 756 689 1656 756 689 1601 200 238 1597 208 246 1611 724 649 1598 753 686 1640 722 647 1640 722 647 1598 753 686 1656 756 689 1640 722 647 1656 756 689 1612 205 243 1612 205 243 1656 756 689 1597 208 246 1601 200 238 1655 755 688 1604 201 239 1604 201 239 1655 755 688 1654 751 684 1655 755 688 1602 754 687 1654 751 684 1654 751 684 1602 754 687 1603 752 685 1388 677 588 1387 695 608 1602 754 687 1602 754 687 1387 695 608 1603 752 685 1606 733 659 1390 693 606 1607 734 660 1607 734 660 1390 693 606 1389 691 603 1431 681 592 1611 724 649 1432 683 594 1432 683 594 1611 724 649 1610 723 648 1615 742 668 1614 726 651 1433 685 596 1433 685 596 1614 726 651 1434 687 598 1390 693 606 1606 733 659 1387 695 608 1387 695 608 1606 733 659 1603 752 685 1610 723 648 1615 742 668 1432 683 594 1432 683 594 1615 742 668 1433 685 596 1453 678 589 1388 677 588 1598 753 686 1598 753 686 1388 677 588 1602 754 687 1611 724 649 1431 681 592 1598 753 686 1598 753 686 1431 681 592 1453 678 589 1454 689 690 1599 725 691 1389 691 603 1389 691 603 1599 725 691 1607 734 660 1454 689 600 1434 687 598 1599 725 650 1599 725 650 1434 687 598 1614 726 651 1624 730 656 1519 716 636 1622 717 642 1622 717 642 1519 716 636 1520 697 615 1625 729 655 1627 750 680 1522 714 634 1522 714 634 1627 750 680 1521 712 632 1563 702 620 1564 704 622 1632 737 663 1632 737 663 1564 704 622 1629 738 664 1566 708 626 1633 745 671 1565 706 624 1565 706 624 1633 745 671 1635 744 670 1522 714 634 1519 716 636 1625 729 655 1625 729 655 1519 716 636 1624 730 656 1629 738 664 1564 704 622 1635 744 670 1635 744 670 1564 704 622 1565 706 624 1585 700 618 1617 718 643 1520 697 615 1520 697 615 1617 718 643 1622 717 642 1632 737 663 1617 718 643 1563 702 620 1563 702 620 1617 718 643 1585 700 618 1627 750 680 1620 746 692 1521 712 632 1521 712 632 1620 746 692 1586 710 693 1633 745 671 1566 708 626 1620 746 672 1620 746 672 1566 708 626 1586 710 628 2695 2147 265 2685 2148 264 2686 2146 262 2686 2146 262 2685 2148 264 2676 2149 263 2687 2151 269 2677 2152 268 2981 2150 266 2981 2150 266 2677 2152 268 2980 2153 267 2688 2155 273 2678 2156 272 2689 2154 270 2689 2154 270 2678 2156 272 2679 2157 271 2690 2158 275 2680 2159 274 2687 2151 269 2687 2151 269 2680 2159 274 2677 2152 268 2689 2154 270 2679 2157 271 2690 2158 275 2690 2158 275 2679 2157 271 2680 2160 274 2686 2146 262 2676 2149 263 2688 2155 273 2688 2155 273 2676 2149 263 2678 2156 272 2968 2161 276 2682 2162 279 2969 2164 277 2969 2164 277 2682 2162 279 2691 2163 278 2683 2165 280 2681 2166 283 2693 2168 281 2693 2168 281 2681 2166 283 2692 2167 282 2682 2162 279 2684 2169 285 2691 2163 278 2691 2163 278 2684 2169 285 2694 2170 284 2684 2169 285 2683 2165 280 2694 2170 284 2694 2170 284 2683 2165 280 2693 2168 281 2695 2147 265 2686 2146 262 2681 2166 283 2681 2166 283 2686 2146 262 2692 2167 282 2688 2155 273 2716 2171 286 2686 2146 262 2686 2146 262 2716 2171 286 2692 2167 282 2982 2173 290 2705 2174 289 2984 2172 287 2984 2172 287 2705 2174 289 2722 2175 288 2980 2176 267 2677 2177 268 2982 2173 290 2982 2173 290 2677 2177 268 2705 2174 289 2705 2174 289 2706 2178 291 2722 2175 288 2677 2177 268 2680 2179 274 2705 2174 289 2705 2174 289 2680 2179 274 2706 2178 291 2722 2175 288 2706 2178 291 2700 2181 292 2700 2181 292 2706 2178 291 2707 2180 293 2680 2182 274 2679 2157 271 2706 2178 291 2706 2178 291 2679 2157 271 2707 2180 293 2700 2181 292 2707 2180 293 2699 2184 294 2699 2184 294 2707 2180 293 2708 2183 295 2679 2157 271 2678 2156 272 2707 2180 293 2707 2180 293 2678 2156 272 2708 2183 295 2699 2184 294 2708 2183 295 2727 2186 296 2727 2186 296 2708 2183 295 2709 2185 297 2678 2156 272 2676 2149 263 2708 2183 295 2708 2183 295 2676 2149 263 2709 2185 297 2727 2186 296 2709 2185 297 2728 2188 298 2728 2188 298 2709 2185 297 2710 2187 299 2676 2149 263 2685 2148 264 2709 2185 297 2709 2185 297 2685 2148 264 2710 2187 299 2710 2190 299 2711 2191 301 2728 2189 298 2728 2189 298 2711 2191 301 2729 2192 300 2710 2190 299 2685 2193 264 2711 2191 301 2711 2191 301 2685 2193 264 2695 2194 265 2711 2191 301 2695 2194 265 2712 2196 302 2712 2196 302 2695 2194 265 2681 2195 283 2712 2196 302 2681 2195 283 2713 2198 303 2713 2198 303 2681 2195 283 2683 2197 280 2713 2198 303 2683 2197 280 2714 2200 304 2714 2200 304 2683 2197 280 2684 2199 285 2714 2200 304 2684 2199 285 2715 2202 305 2715 2202 305 2684 2199 285 2682 2201 279 2715 2202 305 2682 2201 279 2970 2204 306 2970 2204 306 2682 2201 279 2968 2203 276 2691 2163 278 2717 2205 308 2969 2164 277 2969 2164 277 2717 2205 308 2983 2206 307 2717 2205 308 2687 2151 269 2983 2206 307 2983 2206 307 2687 2151 269 2981 2150 266 2694 2170 284 2718 2207 309 2691 2163 278 2691 2163 278 2718 2207 309 2717 2205 308 2718 2207 309 2690 2158 275 2717 2205 308 2717 2205 308 2690 2158 275 2687 2151 269 2693 2168 281 2719 2208 310 2694 2170 284 2694 2170 284 2719 2208 310 2718 2207 309 2719 2208 310 2689 2154 270 2718 2207 309 2718 2207 309 2689 2154 270 2690 2158 275 2692 2167 282 2716 2171 286 2693 2168 281 2693 2168 281 2716 2171 286 2719 2208 310 2716 2171 286 2688 2155 273 2719 2208 310 2719 2208 310 2688 2155 273 2689 2154 270 2984 2172 287 2722 2175 288 2990 2210 311 2990 2210 311 2722 2175 288 2723 2209 312 2722 2175 288 2700 2181 292 2723 2209 312 2723 2209 312 2700 2181 292 2720 2211 313 2990 2210 311 2723 2209 312 2992 2213 314 2992 2213 314 2723 2209 312 2724 2212 315 2720 2211 313 2726 2214 318 2730 2216 316 2730 2216 316 2726 2214 318 2721 2215 317 2700 2181 292 2699 2184 294 2720 2211 313 2699 2184 294 2725 2217 319 2720 2211 313 2720 2211 313 2725 2217 319 2726 2214 318 2704 2218 320 2725 2219 319 2727 2186 296 2727 2186 296 2725 2219 319 2699 2184 294 2704 2218 320 2727 2186 296 2703 2220 321 2703 2220 321 2727 2186 296 2728 2188 298 2702 2221 322 2703 2222 321 2729 2192 300 2729 2192 300 2703 2222 321 2728 2189 298 2729 2192 300 2734 2223 324 2702 2221 322 2702 2221 322 2734 2223 324 2701 2224 323 2723 2209 312 2720 2211 313 2724 2212 315 2724 2212 315 2720 2211 313 2730 2216 316 2730 2216 316 2721 2215 317 2732 2226 325 2732 2226 325 2721 2215 317 2731 2225 326 2730 2216 316 2732 2226 325 2724 2212 315 2724 2212 315 2732 2226 325 2733 2227 327 2731 2225 326 2996 2228 329 2732 2226 325 2732 2226 325 2996 2228 329 2995 2229 328 2732 2226 325 2995 2229 328 2733 2227 327 2733 2227 327 2995 2229 328 2994 2230 330 2994 2230 330 2992 2213 314 2733 2227 327 2733 2227 327 2992 2213 314 2724 2212 315 2734 2223 324 2729 2192 300 2712 2196 302 2712 2196 302 2729 2192 300 2711 2191 301 2970 2204 306 2972 2231 332 2715 2202 305 2715 2202 305 2972 2231 332 2735 2232 331 2972 2231 332 2971 2233 334 2735 2232 331 2735 2232 331 2971 2233 334 2696 2234 333 2715 2202 305 2735 2232 331 2714 2200 304 2714 2200 304 2735 2232 331 2736 2235 335 2735 2232 331 2696 2234 333 2736 2235 335 2736 2235 335 2696 2234 333 2697 2236 336 2714 2200 304 2736 2235 335 2713 2198 303 2713 2198 303 2736 2235 335 2737 2237 337 2736 2235 335 2697 2236 336 2737 2237 337 2737 2237 337 2697 2236 336 2698 2238 338 2737 2237 337 2734 2223 324 2713 2198 303 2713 2198 303 2734 2223 324 2712 2196 302 2698 2238 338 2701 2224 323 2737 2237 337 2737 2237 337 2701 2224 323 2734 2223 324 2740 2240 342 2739 2241 341 2741 2239 339 2741 2239 339 2739 2241 341 2738 2242 340 2986 2243 343 2743 2244 346 2985 2246 344 2985 2246 344 2743 2244 346 2742 2245 345 2747 2247 347 2746 2248 350 2744 2250 348 2744 2250 348 2746 2248 350 2745 2249 349 2743 2244 346 2749 2251 352 2742 2245 345 2742 2245 345 2749 2251 352 2748 2252 351 2749 2251 352 2747 2247 347 2748 2252 351 2748 2252 351 2747 2247 347 2744 2250 348 2746 2248 350 2741 2239 339 2745 2249 349 2745 2249 349 2741 2239 339 2738 2242 340 2751 2254 356 2750 2255 355 2974 2253 353 2974 2253 353 2750 2255 355 2973 2256 354 2755 2257 357 2754 2258 360 2752 2260 358 2752 2260 358 2754 2258 360 2753 2259 359 2757 2261 362 2756 2262 361 2751 2254 356 2751 2254 356 2756 2262 361 2750 2255 355 2757 2261 362 2755 2257 357 2756 2262 361 2756 2262 361 2755 2257 357 2752 2260 358 2754 2258 360 2738 2242 340 2753 2259 359 2753 2259 359 2738 2242 340 2739 2241 341 2754 2258 360 2758 2263 363 2738 2242 340 2738 2242 340 2758 2263 363 2745 2249 349 2760 2264 364 2759 2265 367 2987 2267 365 2987 2267 365 2759 2265 367 2988 2266 366 2759 2265 367 2743 2268 346 2988 2266 366 2988 2266 366 2743 2268 346 2986 2269 343 2760 2264 364 2761 2270 368 2759 2265 367 2761 2270 368 2749 2271 352 2759 2265 367 2759 2265 367 2749 2271 352 2743 2268 346 2762 2273 370 2761 2270 368 2763 2272 369 2763 2272 369 2761 2270 368 2760 2264 364 2762 2273 370 2747 2247 347 2761 2270 368 2761 2270 368 2747 2247 347 2749 2271 352 2764 2275 372 2762 2273 370 2765 2274 371 2765 2274 371 2762 2273 370 2763 2272 369 2764 2275 372 2746 2248 350 2762 2273 370 2762 2273 370 2746 2248 350 2747 2247 347 2766 2277 374 2764 2275 372 2767 2276 373 2767 2276 373 2764 2275 372 2765 2274 371 2766 2277 374 2741 2239 339 2764 2275 372 2764 2275 372 2741 2239 339 2746 2248 350 2768 2279 376 2766 2277 374 2769 2278 375 2769 2278 375 2766 2277 374 2767 2276 373 2768 2280 376 2740 2240 342 2766 2277 374 2766 2277 374 2740 2240 342 2741 2239 339 2770 2282 378 2768 2283 376 2771 2281 377 2771 2281 377 2768 2283 376 2769 2284 375 2739 2241 341 2740 2240 342 2770 2285 378 2770 2285 378 2740 2240 342 2768 2280 376 2753 2287 359 2739 2288 341 2772 2286 379 2772 2286 379 2739 2288 341 2770 2282 378 2752 2290 358 2753 2287 359 2773 2289 380 2773 2289 380 2753 2287 359 2772 2286 379 2756 2292 361 2752 2290 358 2774 2291 381 2774 2291 381 2752 2290 358 2773 2289 380 2750 2255 355 2756 2292 361 2775 2293 382 2775 2293 382 2756 2292 361 2774 2291 381 2973 2256 354 2750 2255 355 2975 2294 383 2975 2294 383 2750 2255 355 2775 2293 382 2989 2295 385 2776 2296 384 2974 2253 353 2974 2253 353 2776 2296 384 2751 2254 356 2985 2246 344 2742 2245 345 2989 2295 385 2989 2295 385 2742 2245 345 2776 2296 384 2776 2296 384 2777 2297 386 2751 2254 356 2751 2254 356 2777 2297 386 2757 2261 362 2742 2245 345 2748 2252 351 2776 2296 384 2776 2296 384 2748 2252 351 2777 2297 386 2777 2297 386 2778 2298 387 2757 2261 362 2757 2261 362 2778 2298 387 2755 2257 357 2748 2252 351 2744 2250 348 2777 2297 386 2777 2297 386 2744 2250 348 2778 2298 387 2778 2298 387 2758 2263 363 2755 2257 357 2755 2257 357 2758 2263 363 2754 2258 360 2744 2250 348 2745 2249 349 2778 2298 387 2778 2298 387 2745 2249 349 2758 2263 363 2779 2300 389 2760 2264 364 2991 2299 388 2991 2299 388 2760 2264 364 2987 2267 365 2780 2301 390 2763 2272 369 2779 2300 389 2779 2300 389 2763 2272 369 2760 2264 364 2781 2303 392 2779 2300 389 2993 2302 391 2993 2302 391 2779 2300 389 2991 2299 388 2787 2305 395 2784 2306 394 2788 2304 393 2788 2304 393 2784 2306 394 2780 2301 390 2780 2301 390 2765 2274 371 2763 2272 369 2784 2307 394 2791 2308 396 2780 2301 390 2780 2301 390 2791 2308 396 2765 2274 371 2791 2308 396 2794 2309 397 2765 2274 371 2765 2274 371 2794 2309 397 2767 2276 373 2769 2311 375 2767 2312 373 2797 2310 398 2797 2310 398 2767 2312 373 2794 2313 397 2769 2314 375 2797 2315 398 2771 2281 377 2771 2281 377 2797 2315 398 2800 2316 399 2804 2317 401 2801 2318 400 2800 2316 399 2800 2316 399 2801 2318 400 2771 2281 377 2788 2304 393 2780 2301 390 2781 2303 392 2781 2303 392 2780 2301 390 2779 2300 389 2807 2320 403 2787 2321 395 2808 2319 402 2808 2319 402 2787 2321 395 2788 2304 393 2809 2322 404 2808 2319 402 2781 2303 392 2781 2303 392 2808 2319 402 2788 2304 393 3001 2324 406 2807 2320 403 2998 2323 405 2998 2323 405 2807 2320 403 2808 2319 402 2997 2325 407 2998 2323 405 2809 2322 404 2809 2322 404 2998 2323 405 2808 2319 402 2781 2303 392 2993 2302 391 2809 2322 404 2809 2322 404 2993 2302 391 2997 2325 407 2770 2282 378 2771 2281 377 2772 2286 379 2772 2286 379 2771 2281 377 2801 2318 400 2810 2326 409 2976 2327 408 2775 2293 382 2775 2293 382 2976 2327 408 2975 2294 383 2813 2328 411 2979 2329 410 2810 2326 409 2810 2326 409 2979 2329 410 2976 2327 408 2814 2330 412 2810 2326 409 2774 2291 381 2774 2291 381 2810 2326 409 2775 2293 382 2817 2331 413 2813 2328 411 2814 2330 412 2814 2330 412 2813 2328 411 2810 2326 409 2818 2332 414 2814 2330 412 2773 2289 380 2773 2289 380 2814 2330 412 2774 2291 381 2821 2333 415 2817 2331 413 2818 2332 414 2818 2332 414 2817 2331 413 2814 2330 412 2772 2286 379 2801 2318 400 2773 2289 380 2773 2289 380 2801 2318 400 2818 2332 414 2801 2318 400 2804 2317 401 2818 2332 414 2818 2332 414 2804 2317 401 2821 2333 415 2782 2334 416 2785 2335 417 2726 2337 318 2726 2337 318 2785 2335 417 2721 2336 317 2784 2338 394 2787 2339 395 2783 2341 418 2783 2341 418 2787 2339 395 2786 2340 419 2782 2334 416 2726 2337 318 2789 2342 420 2789 2342 420 2726 2337 318 2725 2343 319 2784 2338 394 2783 2341 418 2791 2344 396 2791 2344 396 2783 2341 418 2790 2345 421 2792 2346 422 2789 2342 420 2704 2348 320 2704 2348 320 2789 2342 420 2725 2347 319 2794 2349 397 2791 2344 396 2793 2350 423 2793 2350 423 2791 2344 396 2790 2345 421 2792 2346 422 2704 2348 320 2795 2351 424 2795 2351 424 2704 2348 320 2703 2352 321 2794 2349 397 2793 2350 423 2797 2353 398 2797 2353 398 2793 2350 423 2796 2354 425 2798 2355 426 2795 2356 424 2702 2358 322 2702 2358 322 2795 2356 424 2703 2357 321 2800 2359 399 2797 2360 398 2799 2362 427 2799 2362 427 2797 2360 398 2796 2361 425 2802 2363 428 2798 2355 426 2701 2364 323 2701 2364 323 2798 2355 426 2702 2358 322 2804 2365 401 2800 2359 399 2803 2366 429 2803 2366 429 2800 2359 399 2799 2362 427 2805 2367 430 2731 2368 326 2785 2335 417 2785 2335 417 2731 2368 326 2721 2336 317 2807 2370 403 2806 2371 431 2787 2369 395 2787 2369 395 2806 2371 431 2786 2340 419 2999 2372 432 2996 2373 329 2805 2367 430 2805 2367 430 2996 2373 329 2731 2368 326 3001 2374 406 3000 2375 433 2807 2370 403 2807 2370 403 3000 2375 433 2806 2371 431 2977 2376 434 2811 2377 435 2971 2379 334 2971 2379 334 2811 2377 435 2696 2378 333 2979 2380 410 2813 2381 411 2978 2383 436 2978 2383 436 2813 2381 411 2812 2382 437 2811 2377 435 2815 2384 438 2696 2378 333 2696 2378 333 2815 2384 438 2697 2385 336 2813 2381 411 2817 2386 413 2812 2382 437 2812 2382 437 2817 2386 413 2816 2387 439 2815 2384 438 2819 2388 440 2697 2385 336 2697 2385 336 2819 2388 440 2698 2389 338 2817 2386 413 2821 2390 415 2816 2387 439 2816 2387 439 2821 2390 415 2820 2391 441 2819 2388 440 2802 2363 428 2698 2389 338 2698 2389 338 2802 2363 428 2701 2364 323 2821 2390 415 2804 2365 401 2820 2391 441 2820 2391 441 2804 2365 401 2803 2366 429 2806 2371 431 2805 2367 430 2786 2340 419 2786 2340 419 2805 2367 430 2785 2335 417 3000 2375 433 2999 2372 432 2806 2371 431 2806 2371 431 2999 2372 432 2805 2367 430 2978 2383 436 2812 2382 437 2977 2376 434 2977 2376 434 2812 2382 437 2811 2377 435 2812 2382 437 2816 2387 439 2811 2377 435 2811 2377 435 2816 2387 439 2815 2384 438 2816 2387 439 2820 2391 441 2815 2384 438 2815 2384 438 2820 2391 441 2819 2388 440 2820 2391 441 2803 2366 429 2819 2388 440 2819 2388 440 2803 2366 429 2802 2363 428 2803 2366 429 2799 2362 427 2802 2363 428 2802 2363 428 2799 2362 427 2798 2355 426 2799 2362 427 2796 2361 425 2798 2355 426 2798 2355 426 2796 2361 425 2795 2392 424 2793 2350 423 2792 2346 422 2796 2393 425 2796 2393 425 2792 2346 422 2795 2394 424 2793 2350 423 2790 2345 421 2792 2346 422 2792 2346 422 2790 2345 421 2789 2342 420 2783 2341 418 2782 2334 416 2790 2345 421 2790 2345 421 2782 2334 416 2789 2342 420 2783 2341 418 2786 2340 419 2782 2334 416 2782 2334 416 2786 2340 419 2785 2335 417 2822 2396 445 2831 2397 444 2832 2395 442 2832 2395 442 2831 2397 444 2841 2398 443 2980 2153 267 2823 2399 447 2981 2150 266 2981 2150 266 2823 2399 447 2833 2400 446 2825 2402 451 2824 2403 450 2835 2401 448 2835 2401 448 2824 2403 450 2834 2404 449 2823 2399 447 2826 2405 453 2833 2400 446 2833 2400 446 2826 2405 453 2836 2406 452 2826 2407 453 2825 2402 451 2836 2406 452 2836 2406 452 2825 2402 451 2835 2401 448 2824 2403 450 2822 2396 445 2834 2404 449 2834 2404 449 2822 2396 445 2832 2395 442 2968 2161 276 2969 2164 277 2828 2409 454 2828 2409 454 2969 2164 277 2837 2408 455 2829 2410 456 2839 2411 459 2827 2413 457 2827 2413 457 2839 2411 459 2838 2412 458 2828 2409 454 2837 2408 455 2830 2415 460 2830 2415 460 2837 2408 455 2840 2414 461 2830 2415 460 2840 2414 461 2829 2410 456 2829 2410 456 2840 2414 461 2839 2411 459 2841 2398 443 2827 2413 457 2832 2395 442 2832 2395 442 2827 2413 457 2838 2412 458 2838 2412 458 2862 2416 462 2832 2395 442 2832 2395 442 2862 2416 462 2834 2404 449 2868 2417 464 2851 2418 463 2984 2172 287 2984 2172 287 2851 2418 463 2982 2173 290 2851 2418 463 2823 2419 447 2982 2173 290 2982 2173 290 2823 2419 447 2980 2176 267 2851 2418 463 2868 2417 464 2852 2420 465 2852 2420 465 2826 2421 453 2851 2418 463 2851 2418 463 2826 2421 453 2823 2419 447 2868 2417 464 2846 2422 467 2852 2420 465 2852 2420 465 2846 2422 467 2853 2423 466 2853 2423 466 2825 2402 451 2852 2420 465 2852 2420 465 2825 2402 451 2826 2424 453 2846 2422 467 2845 2425 469 2853 2423 466 2853 2423 466 2845 2425 469 2854 2426 468 2854 2426 468 2824 2403 450 2853 2423 466 2853 2423 466 2824 2403 450 2825 2402 451 2845 2425 469 2873 2427 471 2854 2426 468 2854 2426 468 2873 2427 471 2855 2428 470 2855 2428 470 2822 2396 445 2854 2426 468 2854 2426 468 2822 2396 445 2824 2403 450 2873 2427 471 2874 2429 473 2855 2428 470 2855 2428 470 2874 2429 473 2856 2430 472 2856 2430 472 2831 2397 444 2855 2428 470 2855 2428 470 2831 2397 444 2822 2396 445 2875 2432 475 2857 2433 474 2874 2431 473 2874 2431 473 2857 2433 474 2856 2434 472 2856 2434 472 2857 2433 474 2831 2436 444 2831 2436 444 2857 2433 474 2841 2435 443 2857 2433 474 2858 2437 476 2841 2435 443 2841 2435 443 2858 2437 476 2827 2438 457 2858 2437 476 2859 2439 477 2827 2438 457 2827 2438 457 2859 2439 477 2829 2440 456 2859 2439 477 2860 2441 478 2829 2440 456 2829 2440 456 2860 2441 478 2830 2442 460 2860 2441 478 2861 2443 479 2830 2442 460 2830 2442 460 2861 2443 479 2828 2444 454 2861 2443 479 2970 2204 306 2828 2444 454 2828 2444 454 2970 2204 306 2968 2203 276 2837 2408 455 2969 2164 277 2863 2445 480 2863 2445 480 2969 2164 277 2983 2206 307 2863 2445 480 2983 2206 307 2833 2400 446 2833 2400 446 2983 2206 307 2981 2150 266 2840 2414 461 2837 2408 455 2864 2446 481 2864 2446 481 2837 2408 455 2863 2445 480 2864 2446 481 2863 2445 480 2836 2406 452 2836 2406 452 2863 2445 480 2833 2400 446 2839 2411 459 2840 2414 461 2865 2447 482 2865 2447 482 2840 2414 461 2864 2446 481 2865 2447 482 2864 2446 481 2835 2401 448 2835 2401 448 2864 2446 481 2836 2406 452 2838 2412 458 2839 2411 459 2862 2416 462 2862 2416 462 2839 2411 459 2865 2447 482 2862 2416 462 2865 2447 482 2834 2404 449 2834 2404 449 2865 2447 482 2835 2401 448 2984 2172 287 2990 2210 311 2868 2417 464 2868 2417 464 2990 2210 311 2869 2448 483 2868 2417 464 2869 2448 483 2846 2422 467 2846 2422 467 2869 2448 483 2866 2449 484 2990 2210 311 2992 2213 314 2869 2448 483 2869 2448 483 2992 2213 314 2870 2450 485 2866 2449 484 2876 2451 488 2872 2453 486 2872 2453 486 2876 2451 488 2867 2452 487 2846 2422 467 2866 2449 484 2845 2425 469 2845 2425 469 2866 2449 484 2871 2454 489 2871 2454 489 2866 2449 484 2872 2453 486 2845 2425 469 2871 2455 489 2873 2427 471 2873 2427 471 2871 2455 489 2850 2456 490 2850 2456 490 2849 2457 491 2873 2427 471 2873 2427 471 2849 2457 491 2874 2429 473 2874 2431 473 2849 2458 491 2875 2432 475 2875 2432 475 2849 2458 491 2848 2459 492 2875 2432 475 2848 2459 492 2880 2461 493 2880 2461 493 2848 2459 492 2847 2460 494 2869 2448 483 2870 2450 485 2866 2449 484 2866 2449 484 2870 2450 485 2876 2451 488 2876 2451 488 2878 2462 496 2867 2452 487 2867 2452 487 2878 2462 496 2877 2463 495 2879 2464 497 2878 2462 496 2870 2450 485 2870 2450 485 2878 2462 496 2876 2451 488 2995 2229 328 2996 2228 329 2878 2462 496 2878 2462 496 2996 2228 329 2877 2463 495 2994 2230 330 2995 2229 328 2879 2464 497 2879 2464 497 2995 2229 328 2878 2462 496 2994 2230 330 2879 2464 497 2992 2213 314 2992 2213 314 2879 2464 497 2870 2450 485 2857 2433 474 2875 2432 475 2858 2437 476 2858 2437 476 2875 2432 475 2880 2461 493 2970 2204 306 2861 2443 479 2972 2231 332 2972 2231 332 2861 2443 479 2881 2465 498 2972 2231 332 2881 2465 498 2971 2233 334 2971 2233 334 2881 2465 498 2842 2466 499 2861 2443 479 2860 2441 478 2881 2465 498 2881 2465 498 2860 2441 478 2882 2467 500 2881 2465 498 2882 2467 500 2842 2466 499 2842 2466 499 2882 2467 500 2843 2468 501 2860 2441 478 2859 2439 477 2882 2467 500 2882 2467 500 2859 2439 477 2883 2469 502 2882 2467 500 2883 2469 502 2843 2468 501 2843 2468 501 2883 2469 502 2844 2470 503 2858 2437 476 2880 2461 493 2859 2439 477 2859 2439 477 2880 2461 493 2883 2469 502 2880 2461 493 2847 2460 494 2883 2469 502 2883 2469 502 2847 2460 494 2844 2470 503 2884 2472 507 2885 2473 506 2887 2471 504 2887 2471 504 2885 2473 506 2886 2474 505 2986 2243 343 2985 2246 344 2889 2476 508 2889 2476 508 2985 2246 344 2888 2475 509 2893 2477 510 2890 2478 513 2892 2480 511 2892 2480 511 2890 2478 513 2891 2479 512 2889 2476 508 2888 2475 509 2895 2482 514 2895 2482 514 2888 2475 509 2894 2481 515 2895 2482 514 2894 2481 515 2893 2477 510 2893 2477 510 2894 2481 515 2890 2478 513 2892 2480 511 2891 2479 512 2887 2471 504 2887 2471 504 2891 2479 512 2884 2472 507 2973 2256 354 2896 2483 517 2974 2253 353 2974 2253 353 2896 2483 517 2897 2484 516 2901 2485 518 2898 2486 521 2900 2488 519 2900 2488 519 2898 2486 521 2899 2487 520 2896 2483 517 2902 2489 523 2897 2484 516 2897 2484 516 2902 2489 523 2903 2490 522 2903 2490 522 2902 2489 523 2901 2485 518 2901 2485 518 2902 2489 523 2898 2486 521 2885 2473 506 2884 2472 507 2899 2487 520 2899 2487 520 2884 2472 507 2900 2488 519 2900 2488 519 2884 2472 507 2904 2491 524 2904 2491 524 2884 2472 507 2891 2479 512 2906 2492 525 2987 2267 365 2905 2493 526 2905 2493 526 2987 2267 365 2988 2266 366 2905 2493 526 2988 2266 366 2889 2494 508 2889 2494 508 2988 2266 366 2986 2269 343 2906 2492 525 2905 2493 526 2907 2495 527 2907 2495 527 2905 2493 526 2895 2496 514 2895 2496 514 2905 2493 526 2889 2494 508 2906 2492 525 2907 2495 527 2909 2497 528 2909 2497 528 2907 2495 527 2908 2498 529 2908 2498 529 2907 2495 527 2893 2477 510 2893 2477 510 2907 2495 527 2895 2496 514 2909 2497 528 2908 2498 529 2911 2499 530 2911 2499 530 2908 2498 529 2910 2500 531 2910 2500 531 2908 2498 529 2892 2480 511 2892 2480 511 2908 2498 529 2893 2477 510 2911 2499 530 2910 2500 531 2913 2501 532 2913 2501 532 2910 2500 531 2912 2502 533 2912 2502 533 2910 2500 531 2887 2471 504 2887 2471 504 2910 2500 531 2892 2480 511 2913 2501 532 2912 2502 533 2915 2503 534 2915 2503 534 2912 2502 533 2914 2504 535 2914 2505 535 2912 2502 533 2886 2474 505 2886 2474 505 2912 2502 533 2887 2471 504 2915 2507 534 2914 2508 535 2917 2506 536 2917 2506 536 2914 2508 535 2916 2509 537 2914 2505 535 2886 2474 505 2916 2510 537 2916 2510 537 2886 2474 505 2885 2473 506 2916 2509 537 2885 2512 506 2918 2511 538 2918 2511 538 2885 2512 506 2899 2513 520 2918 2511 538 2899 2513 520 2919 2514 539 2919 2514 539 2899 2513 520 2898 2515 521 2919 2514 539 2898 2515 521 2920 2516 540 2920 2516 540 2898 2515 521 2902 2517 523 2920 2516 540 2902 2517 523 2921 2518 541 2921 2518 541 2902 2517 523 2896 2483 517 2921 2518 541 2896 2483 517 2975 2294 383 2975 2294 383 2896 2483 517 2973 2256 354 2897 2484 516 2922 2519 542 2974 2253 353 2974 2253 353 2922 2519 542 2989 2295 385 2922 2519 542 2888 2475 509 2989 2295 385 2989 2295 385 2888 2475 509 2985 2246 344 2903 2490 522 2923 2520 543 2897 2484 516 2897 2484 516 2923 2520 543 2922 2519 542 2923 2520 543 2894 2481 515 2922 2519 542 2922 2519 542 2894 2481 515 2888 2475 509 2901 2485 518 2924 2521 544 2903 2490 522 2903 2490 522 2924 2521 544 2923 2520 543 2924 2521 544 2890 2478 513 2923 2520 543 2923 2520 543 2890 2478 513 2894 2481 515 2900 2488 519 2904 2491 524 2901 2485 518 2901 2485 518 2904 2491 524 2924 2521 544 2904 2491 524 2891 2479 512 2924 2521 544 2924 2521 544 2891 2479 512 2890 2478 513 2987 2267 365 2906 2492 525 2991 2299 388 2991 2299 388 2906 2492 525 2925 2522 545 2906 2492 525 2909 2497 528 2925 2522 545 2925 2522 545 2909 2497 528 2926 2523 546 2991 2299 388 2925 2522 545 2993 2302 391 2993 2302 391 2925 2522 545 2927 2524 547 2926 2523 546 2930 2526 550 2934 2525 548 2934 2525 548 2930 2526 550 2933 2527 549 2926 2523 546 2909 2497 528 2911 2499 530 2911 2499 530 2937 2528 551 2926 2523 546 2926 2523 546 2937 2528 551 2930 2529 550 2913 2501 532 2940 2530 552 2911 2499 530 2911 2499 530 2940 2530 552 2937 2528 551 2940 2532 552 2913 2533 532 2943 2531 553 2943 2531 553 2913 2533 532 2915 2534 534 2915 2535 534 2917 2506 536 2943 2537 553 2943 2537 553 2917 2506 536 2946 2536 554 2917 2506 536 2947 2538 556 2946 2536 554 2946 2536 554 2947 2538 556 2950 2539 555 2925 2522 545 2926 2523 546 2927 2524 547 2927 2524 547 2926 2523 546 2934 2525 548 2934 2525 548 2933 2541 549 2954 2540 557 2954 2540 557 2933 2541 549 2953 2542 558 2955 2543 559 2927 2524 547 2954 2540 557 2954 2540 557 2927 2524 547 2934 2525 548 2954 2540 557 2953 2542 558 2998 2323 405 2998 2323 405 2953 2542 558 3001 2324 406 2997 2325 407 2955 2543 559 2998 2323 405 2998 2323 405 2955 2543 559 2954 2540 557 2997 2325 407 2993 2302 391 2955 2543 559 2955 2543 559 2993 2302 391 2927 2524 547 2916 2509 537 2918 2511 538 2917 2506 536 2917 2506 536 2918 2511 538 2947 2538 556 2975 2294 383 2976 2327 408 2921 2518 541 2921 2518 541 2976 2327 408 2956 2544 560 2976 2327 408 2979 2329 410 2956 2544 560 2956 2544 560 2979 2329 410 2959 2545 561 2921 2518 541 2956 2544 560 2920 2516 540 2920 2516 540 2956 2544 560 2960 2546 562 2956 2544 560 2959 2545 561 2960 2546 562 2960 2546 562 2959 2545 561 2963 2547 563 2920 2516 540 2960 2546 562 2919 2514 539 2919 2514 539 2960 2546 562 2964 2548 564 2960 2546 562 2963 2547 563 2964 2548 564 2964 2548 564 2963 2547 563 2967 2549 565 2918 2511 538 2919 2514 539 2947 2538 556 2947 2538 556 2919 2514 539 2964 2548 564 2947 2538 556 2964 2548 564 2950 2539 555 2950 2539 555 2964 2548 564 2967 2549 565 2928 2550 566 2872 2551 486 2931 2553 567 2931 2553 567 2872 2551 486 2867 2552 487 2930 2554 550 2929 2555 569 2933 2557 549 2933 2557 549 2929 2555 569 2932 2556 568 2871 2559 489 2872 2551 486 2935 2558 570 2935 2558 570 2872 2551 486 2928 2550 566 2936 2561 571 2929 2555 569 2937 2560 551 2937 2560 551 2929 2555 569 2930 2554 550 2938 2562 572 2850 2563 490 2935 2558 570 2935 2558 570 2850 2563 490 2871 2564 489 2940 2565 552 2939 2566 573 2937 2560 551 2937 2560 551 2939 2566 573 2936 2561 571 2849 2568 491 2850 2563 490 2941 2567 574 2941 2567 574 2850 2563 490 2938 2562 572 2942 2570 575 2939 2566 573 2943 2569 553 2943 2569 553 2939 2566 573 2940 2565 552 2944 2571 576 2848 2572 492 2941 2574 574 2941 2574 574 2848 2572 492 2849 2573 491 2946 2575 554 2945 2576 577 2943 2578 553 2943 2578 553 2945 2576 577 2942 2577 575 2948 2579 578 2847 2580 494 2944 2571 576 2944 2571 576 2847 2580 494 2848 2572 492 2950 2581 555 2949 2582 579 2946 2575 554 2946 2575 554 2949 2582 579 2945 2576 577 2867 2552 487 2877 2583 495 2931 2553 567 2931 2553 567 2877 2583 495 2951 2584 580 2932 2556 568 2952 2586 581 2933 2585 549 2933 2585 549 2952 2586 581 2953 2587 558 2877 2583 495 2996 2373 329 2951 2584 580 2951 2584 580 2996 2373 329 2999 2372 432 2952 2586 581 3000 2375 433 2953 2587 558 2953 2587 558 3000 2375 433 3001 2374 406 2977 2376 434 2971 2379 334 2957 2589 582 2957 2589 582 2971 2379 334 2842 2588 499 2979 2380 410 2978 2383 436 2959 2591 561 2959 2591 561 2978 2383 436 2958 2590 583 2957 2589 582 2842 2588 499 2961 2593 584 2961 2593 584 2842 2588 499 2843 2592 501 2959 2591 561 2958 2590 583 2963 2595 563 2963 2595 563 2958 2590 583 2962 2594 585 2961 2593 584 2843 2592 501 2965 2597 586 2965 2597 586 2843 2592 501 2844 2596 503 2963 2595 563 2962 2594 585 2967 2599 565 2967 2599 565 2962 2594 585 2966 2598 587 2965 2597 586 2844 2596 503 2948 2579 578 2948 2579 578 2844 2596 503 2847 2580 494 2967 2599 565 2966 2598 587 2950 2581 555 2950 2581 555 2966 2598 587 2949 2582 579 2931 2553 567 2951 2584 580 2932 2556 568 2932 2556 568 2951 2584 580 2952 2586 581 2951 2584 580 2999 2372 432 2952 2586 581 2952 2586 581 2999 2372 432 3000 2375 433 2978 2383 436 2977 2376 434 2958 2590 583 2958 2590 583 2977 2376 434 2957 2589 582 2958 2590 583 2957 2589 582 2962 2594 585 2962 2594 585 2957 2589 582 2961 2593 584 2962 2594 585 2961 2593 584 2966 2598 587 2966 2598 587 2961 2593 584 2965 2597 586 2966 2598 587 2965 2597 586 2949 2582 579 2949 2582 579 2965 2597 586 2948 2579 578 2949 2582 579 2948 2579 578 2945 2576 577 2945 2576 577 2948 2579 578 2944 2571 576 2945 2576 577 2944 2571 576 2942 2577 575 2942 2577 575 2944 2571 576 2941 2600 574 2941 2602 574 2938 2562 572 2942 2601 575 2942 2601 575 2938 2562 572 2939 2566 573 2939 2566 573 2938 2562 572 2936 2561 571 2936 2561 571 2938 2562 572 2935 2558 570 2935 2558 570 2928 2550 566 2936 2561 571 2936 2561 571 2928 2550 566 2929 2555 569 2929 2555 569 2928 2550 566 2932 2556 568 2932 2556 568 2928 2550 566 2931 2553 567</p>
+ </triangles>
+ <triangles material="HeadphonesSG2" count="1400">
+ <input semantic="VERTEX" source="#Headphones-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Headphones-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Headphones-headphonesUV" offset="2" set="1"/>
+ <p>0 758 695 14 759 696 1 757 694 1 757 694 14 759 696 15 760 697 0 758 695 1 757 694 17 761 698 17 761 698 1 757 694 16 762 699 12 763 700 2 764 701 15 760 697 15 760 697 2 764 701 1 757 694 2 764 701 13 765 702 1 757 694 1 757 694 13 765 702 16 762 699 17 761 698 192 766 703 0 758 695 0 758 695 192 766 703 188 767 704 189 768 705 3 769 706 188 767 704 188 767 704 3 769 706 0 758 695 0 758 695 3 769 706 14 759 696 14 759 696 3 769 706 18 770 707 19 771 708 11 772 709 20 774 711 20 774 711 11 772 709 6 773 710 20 774 711 6 773 710 21 776 713 21 776 713 6 773 710 5 775 712 21 776 713 5 775 712 22 778 715 22 778 715 5 775 712 9 777 714 16 779 699 23 780 716 17 782 698 17 782 698 23 780 716 24 781 717 17 782 698 24 781 717 192 784 703 192 784 703 24 781 717 193 783 718 13 785 702 25 786 719 16 779 699 16 779 699 25 786 719 23 780 716 26 787 720 27 788 721 25 786 719 25 786 719 27 788 721 23 780 716 27 788 721 28 789 722 23 780 716 23 780 716 28 789 722 24 781 717 194 790 723 193 783 718 28 789 722 28 789 722 193 783 718 24 781 717 29 791 724 30 792 725 26 794 720 26 794 720 30 792 725 27 793 721 30 795 725 31 796 726 27 798 721 27 798 721 31 796 726 28 797 722 31 799 726 195 800 727 28 802 722 28 802 722 195 800 727 194 801 723 30 803 725 29 804 724 46 806 729 46 806 729 29 804 724 47 805 728 31 807 726 30 808 725 49 809 730 49 809 730 30 808 725 46 806 729 195 810 727 31 811 726 197 813 731 197 813 731 31 811 726 49 812 730 43 814 732 42 815 733 47 805 728 47 805 728 42 815 733 46 806 729 42 815 733 45 816 734 46 806 729 46 806 729 45 816 734 49 809 730 49 809 730 45 816 734 197 818 731 197 818 731 45 816 734 196 817 735 42 815 733 43 814 732 50 819 736 50 819 736 43 814 732 51 820 737 53 821 738 45 816 734 50 819 736 50 819 736 45 816 734 42 815 733 198 822 739 196 817 735 53 821 738 53 821 738 196 817 735 45 816 734 50 819 736 51 820 737 54 824 741 54 824 741 51 820 737 55 823 740 54 824 741 55 823 740 4 826 743 4 826 743 55 823 740 8 825 742 50 819 736 54 824 741 53 821 738 53 821 738 54 824 741 57 827 744 54 824 741 4 826 743 57 827 744 57 827 744 4 826 743 7 828 745 53 821 738 57 827 744 198 822 739 198 822 739 57 827 744 199 829 746 57 827 744 7 828 745 199 829 746 199 829 746 7 828 745 190 830 747 7 828 745 4 826 743 58 832 749 58 832 749 4 826 743 59 831 748 58 832 749 59 831 748 6 773 710 6 773 710 59 831 748 5 775 712 4 826 743 8 825 742 59 831 748 59 831 748 8 825 742 60 833 750 59 831 748 60 833 750 5 775 712 5 775 712 60 833 750 9 777 714 58 832 749 6 773 710 62 834 751 62 834 751 6 773 710 11 772 709 11 772 709 10 835 752 62 834 751 62 834 751 10 835 752 63 836 753 63 836 753 7 828 745 62 834 751 62 834 751 7 828 745 58 832 749 191 837 754 200 838 755 10 835 752 10 835 752 200 838 755 63 836 753 200 838 755 190 830 747 63 836 753 63 836 753 190 830 747 7 828 745 73 840 757 72 841 758 70 839 756 70 839 756 72 841 758 71 842 759 78 843 760 64 844 761 40 846 763 40 846 763 64 844 761 41 845 762 65 847 764 35 848 765 64 844 761 64 844 761 35 848 765 41 849 762 33 851 767 35 848 765 66 850 766 66 850 766 35 848 765 65 847 764 67 852 768 32 853 769 66 850 766 66 850 766 32 853 769 33 854 767 67 852 768 68 855 770 32 853 769 32 853 769 68 855 770 34 856 771 69 857 772 36 858 773 68 855 770 68 855 770 36 858 773 34 859 771 70 839 756 39 860 774 69 857 772 69 857 772 39 860 774 36 858 773 38 861 775 39 862 774 71 842 759 71 842 759 39 862 774 70 839 756 72 841 758 48 863 776 71 842 759 71 842 759 48 863 776 38 864 775 73 840 757 44 865 777 72 841 758 72 841 758 44 865 777 48 863 776 74 866 778 52 867 779 73 840 757 73 840 757 52 867 779 44 868 777 74 866 778 75 869 780 52 867 779 52 867 779 75 869 780 56 870 781 76 871 782 37 872 783 75 869 780 75 869 780 37 872 783 56 870 781 77 873 784 61 874 785 76 871 782 76 871 782 61 874 785 37 872 783 77 873 784 78 843 760 61 874 785 61 874 785 78 843 760 40 875 763 78 843 760 77 873 784 64 844 761 64 844 761 77 873 784 65 847 764 73 840 757 70 839 756 74 866 778 74 866 778 70 839 756 69 857 772 76 871 782 75 869 780 67 852 768 67 852 768 75 869 780 68 855 770 75 869 780 74 866 778 68 855 770 68 855 770 74 866 778 69 857 772 66 850 766 77 873 784 67 852 768 67 852 768 77 873 784 76 871 782 66 850 766 65 847 764 77 873 784 32 853 769 80 876 786 33 854 767 33 854 767 80 876 786 79 877 787 80 876 786 2 764 701 79 877 787 79 877 787 2 764 701 12 763 700 34 856 771 81 878 788 32 853 769 32 853 769 81 878 788 80 876 786 81 878 788 13 765 702 80 876 786 80 876 786 13 765 702 2 764 701 33 879 767 79 880 787 35 882 765 35 882 765 79 880 787 82 881 789 34 883 771 36 884 773 81 886 788 81 886 788 36 884 773 83 885 790 25 786 719 13 785 702 83 885 790 83 885 790 13 785 702 81 886 788 38 887 775 85 888 791 39 890 774 39 890 774 85 888 791 84 889 792 85 888 791 29 791 724 84 889 792 84 889 792 29 791 724 26 794 720 40 891 763 41 892 762 86 894 794 86 894 794 41 892 762 87 893 793 22 778 715 9 777 714 87 893 793 87 893 793 9 777 714 86 894 794 39 895 774 84 896 792 36 884 773 36 884 773 84 896 792 83 885 790 84 896 792 26 787 720 83 885 790 83 885 790 26 787 720 25 786 719 41 897 762 35 882 765 87 898 793 87 898 793 35 882 765 82 881 789 48 900 776 88 901 795 38 899 775 38 899 775 88 901 795 85 902 791 47 805 728 29 804 724 88 901 795 88 901 795 29 804 724 85 902 791 43 814 732 47 805 728 89 903 796 89 903 796 47 805 728 88 901 795 88 901 795 48 900 776 89 903 796 89 903 796 48 900 776 44 904 777 90 905 797 89 903 796 52 867 779 52 867 779 89 903 796 44 906 777 90 905 797 51 820 737 89 903 796 89 903 796 51 820 737 43 814 732 52 867 779 56 870 781 90 905 797 90 905 797 56 870 781 91 907 798 55 823 740 51 820 737 91 907 798 91 907 798 51 820 737 90 905 797 56 870 781 37 872 783 91 907 798 91 907 798 37 872 783 92 908 799 8 825 742 55 823 740 92 908 799 92 908 799 55 823 740 91 907 798 37 872 783 61 874 785 92 908 799 92 908 799 61 874 785 93 909 800 60 833 750 8 825 742 93 909 800 93 909 800 8 825 742 92 908 799 40 910 763 86 894 794 61 874 785 61 874 785 86 894 794 93 909 800 86 894 794 9 777 714 93 909 800 93 909 800 9 777 714 60 833 750 109 912 802 108 913 803 95 911 801 95 911 801 108 913 803 94 914 804 110 916 806 95 911 801 111 915 805 111 915 805 95 911 801 94 914 804 95 911 801 96 917 807 109 912 802 109 912 802 96 917 807 106 918 808 110 916 806 107 919 809 95 911 801 95 911 801 107 919 809 96 917 807 188 767 704 192 766 703 94 914 804 94 914 804 192 766 703 111 915 805 94 914 804 97 920 810 188 767 704 188 767 704 97 920 810 189 768 705 94 914 804 108 913 803 97 920 810 97 920 810 108 913 803 112 921 811 113 922 812 114 923 813 105 925 815 105 925 815 114 923 813 100 924 814 114 923 813 115 926 816 100 924 814 100 924 814 115 926 816 99 927 817 115 926 816 116 928 818 99 927 817 99 927 817 116 928 818 103 929 819 110 930 806 111 931 805 117 933 821 117 933 821 111 931 805 118 932 820 111 931 805 192 784 703 118 932 820 118 932 820 192 784 703 193 783 718 107 934 809 110 930 806 119 935 822 119 935 822 110 930 806 117 933 821 120 936 823 119 935 822 121 937 824 121 937 824 119 935 822 117 933 821 121 937 824 117 933 821 122 938 825 122 938 825 117 933 821 118 932 820 118 932 820 193 783 718 122 938 825 122 938 825 193 783 718 194 790 723 123 939 826 120 940 823 124 942 827 124 942 827 120 940 823 121 941 824 124 943 827 121 944 824 125 946 828 125 946 828 121 944 824 122 945 825 125 947 828 122 948 825 195 800 727 195 800 727 122 948 825 194 801 723 124 949 827 140 950 829 123 952 826 123 952 826 140 950 829 141 951 830 125 953 828 143 954 831 124 955 827 124 955 827 143 954 831 140 950 829 195 956 727 197 957 731 125 959 828 125 959 828 197 957 731 143 958 831 140 950 829 136 960 832 141 951 830 141 951 830 136 960 832 137 961 833 143 954 831 139 962 834 140 950 829 140 950 829 139 962 834 136 960 832 143 954 831 197 963 731 139 962 834 139 962 834 197 963 731 196 817 735 145 965 836 137 961 833 144 964 835 144 964 835 137 961 833 136 960 832 147 966 837 144 964 835 139 962 834 139 962 834 144 964 835 136 960 832 198 822 739 147 966 837 196 817 735 196 817 735 147 966 837 139 962 834 144 964 835 148 967 838 145 965 836 145 965 836 148 967 838 149 968 839 148 967 838 98 969 840 149 968 839 149 968 839 98 969 840 102 970 841 151 971 842 148 967 838 147 966 837 147 966 837 148 967 838 144 964 835 101 972 843 98 969 840 151 971 842 151 971 842 98 969 840 148 967 838 199 829 746 151 971 842 198 822 739 198 822 739 151 971 842 147 966 837 190 830 747 101 972 843 199 829 746 199 829 746 101 972 843 151 971 842 101 972 843 152 973 844 98 969 840 98 969 840 152 973 844 153 974 845 152 973 844 100 924 814 153 974 845 153 974 845 100 924 814 99 927 817 98 969 840 153 974 845 102 970 841 102 970 841 153 974 845 154 975 846 153 974 845 99 927 817 154 975 846 154 975 846 99 927 817 103 929 819 152 973 844 156 976 847 100 924 814 100 924 814 156 976 847 105 925 815 105 925 815 156 976 847 104 978 849 104 978 849 156 976 847 157 977 848 152 973 844 101 972 843 156 976 847 156 976 847 101 972 843 157 977 848 157 977 848 200 838 755 104 978 849 104 978 849 200 838 755 191 837 754 101 972 843 190 830 747 157 977 848 157 977 848 190 830 747 200 838 755 165 980 851 166 981 852 164 979 850 164 979 850 166 981 852 167 982 853 172 983 854 134 984 855 158 986 857 158 986 857 134 984 855 135 985 856 159 987 858 158 986 857 129 989 859 129 989 859 158 986 857 135 988 856 159 987 858 129 989 859 160 990 860 160 990 860 129 989 859 127 991 861 161 992 862 160 990 860 126 994 863 126 994 863 160 990 860 127 993 861 161 992 862 126 994 863 162 996 865 162 996 865 126 994 863 128 995 864 128 997 864 130 998 866 162 996 865 162 996 865 130 998 866 163 999 867 130 998 866 133 1000 868 163 999 867 163 999 867 133 1000 868 164 979 850 164 979 850 133 1001 868 165 980 851 165 980 851 133 1001 868 132 1002 869 132 1003 869 142 1004 870 165 980 851 165 980 851 142 1004 870 166 981 852 142 1004 870 138 1005 871 166 981 852 166 981 852 138 1005 871 167 982 853 168 1006 872 167 982 853 146 1008 873 146 1008 873 167 982 853 138 1007 871 168 1006 872 146 1008 873 169 1010 875 169 1010 875 146 1008 873 150 1009 874 170 1011 876 169 1010 875 131 1012 877 131 1012 877 169 1010 875 150 1009 874 131 1012 877 155 1013 878 170 1011 876 170 1011 876 155 1013 878 171 1014 879 171 1014 879 155 1013 878 172 983 854 172 983 854 155 1013 878 134 1015 855 159 987 858 171 1014 879 158 986 857 158 986 857 171 1014 879 172 983 854 163 999 867 164 979 850 168 1006 872 168 1006 872 164 979 850 167 982 853 162 996 865 169 1010 875 161 992 862 161 992 862 169 1010 875 170 1011 876 163 999 867 168 1006 872 162 996 865 162 996 865 168 1006 872 169 1010 875 170 1011 876 171 1014 879 161 992 862 161 992 862 171 1014 879 160 990 860 160 990 860 171 1014 879 159 987 858 126 994 863 127 993 861 174 1017 881 174 1017 881 127 993 861 173 1016 880 106 918 808 96 917 807 173 1016 880 173 1016 880 96 917 807 174 1017 881 128 995 864 126 994 863 175 1018 882 175 1018 882 126 994 863 174 1017 881 96 917 807 107 919 809 174 1017 881 174 1017 881 107 919 809 175 1018 882 127 1019 861 129 1020 859 173 1022 880 173 1022 880 129 1020 859 176 1021 883 128 1023 864 175 1024 882 130 1026 866 130 1026 866 175 1024 882 177 1025 884 175 1024 882 107 934 809 177 1025 884 177 1025 884 107 934 809 119 935 822 132 1027 869 133 1028 868 179 1030 886 179 1030 886 133 1028 868 178 1029 885 120 940 823 123 939 826 178 1029 885 178 1029 885 123 939 826 179 1030 886 134 1031 855 180 1032 887 135 1034 856 135 1034 856 180 1032 887 181 1033 888 180 1032 887 103 929 819 181 1033 888 181 1033 888 103 929 819 116 928 818 177 1025 884 178 1035 885 130 1026 866 130 1026 866 178 1035 885 133 1036 868 178 1035 885 177 1025 884 120 936 823 120 936 823 177 1025 884 119 935 822 135 1037 856 181 1038 888 129 1020 859 129 1020 859 181 1038 888 176 1021 883 179 1040 886 182 1041 889 132 1039 869 132 1039 869 182 1041 889 142 1042 870 179 1040 886 123 952 826 182 1041 889 182 1041 889 123 952 826 141 951 830 137 961 833 183 1043 890 141 951 830 141 951 830 183 1043 890 182 1041 889 182 1041 889 183 1043 890 142 1042 870 142 1042 870 183 1043 890 138 1044 871 138 1045 871 183 1043 890 146 1008 873 146 1008 873 183 1043 890 184 1046 891 137 961 833 145 965 836 183 1043 890 183 1043 890 145 965 836 184 1046 891 185 1047 892 150 1009 874 184 1046 891 184 1046 891 150 1009 874 146 1008 873 149 968 839 185 1047 892 145 965 836 145 965 836 185 1047 892 184 1046 891 186 1048 893 131 1012 877 185 1047 892 185 1047 892 131 1012 877 150 1009 874 102 970 841 186 1048 893 149 968 839 149 968 839 186 1048 893 185 1047 892 187 1049 894 155 1013 878 186 1048 893 186 1048 893 155 1013 878 131 1012 877 154 975 846 187 1049 894 102 970 841 102 970 841 187 1049 894 186 1048 893 134 1050 855 155 1013 878 180 1032 887 180 1032 887 155 1013 878 187 1049 894 154 975 846 103 929 819 187 1049 894 187 1049 894 103 929 819 180 1032 887 181 1038 888 116 1051 818 176 1021 883 106 1052 808 173 1022 880 116 1051 818 116 1051 818 173 1022 880 176 1021 883 109 1054 802 106 1052 808 115 1053 816 115 1053 816 106 1052 808 116 1051 818 108 1056 803 109 1054 802 114 1055 813 114 1055 813 109 1054 802 115 1053 816 114 1055 813 113 1057 812 108 1056 803 108 1056 803 113 1057 812 112 1058 811 87 898 793 82 881 789 22 1060 715 12 1059 700 22 1060 715 79 880 787 82 881 789 79 880 787 22 1060 715 22 1060 715 12 1059 700 21 1061 713 21 1061 713 12 1059 700 15 1062 697 21 1061 713 15 1062 697 20 1063 711 20 1063 711 15 1062 697 14 1064 696 20 1063 711 14 1064 696 19 1066 708 19 1066 708 14 1064 696 18 1065 707 1465 1067 895 1466 1068 896 189 768 705 189 768 705 1466 1068 896 3 769 706 3 769 706 1466 1068 896 18 770 707 18 770 707 1466 1068 896 1467 1069 897 1467 1070 897 1468 1071 898 18 1065 707 18 1065 707 1468 1071 898 19 1066 708 1468 1072 898 1469 1073 899 19 771 708 19 771 708 1469 1073 899 11 772 709 11 772 709 1469 1073 899 10 835 752 10 835 752 1469 1073 899 1470 1074 900 10 835 752 1470 1074 900 191 837 754 191 837 754 1470 1074 900 1471 1075 901 1471 1075 901 1472 1076 902 191 837 754 191 837 754 1472 1076 902 104 978 849 1472 1076 902 1473 1077 903 104 978 849 104 978 849 1473 1077 903 105 925 815 105 925 815 1473 1077 903 113 922 812 113 922 812 1473 1077 903 1474 1078 904 113 1057 812 1474 1079 904 112 1058 811 112 1058 811 1474 1079 904 1475 1080 905 112 921 811 1475 1081 905 97 920 810 97 920 810 1475 1081 905 1476 1082 906 97 920 810 1476 1082 906 189 768 705 189 768 705 1476 1082 906 1465 1067 895 233 1084 908 232 1085 909 204 1083 907 204 1083 907 232 1085 909 203 1086 910 235 1088 912 234 1089 913 207 1087 911 207 1087 911 234 1089 913 206 1090 914 236 1092 916 235 1088 912 208 1091 915 208 1091 915 235 1088 912 207 1087 911 237 1094 918 238 1095 919 211 1093 917 211 1093 917 238 1095 919 214 1096 920 218 1097 921 240 1098 922 217 1100 924 217 1100 924 240 1098 922 239 1099 923 238 1095 919 236 1092 916 214 1096 920 214 1096 920 236 1092 916 208 1091 915 234 1089 913 233 1084 908 206 1090 914 206 1090 914 233 1084 908 204 1083 907 217 1100 924 239 1099 923 211 1093 917 211 1093 917 239 1099 923 237 1094 918 203 1086 910 232 1085 909 220 1101 925 220 1101 925 232 1085 909 241 1102 926 223 1104 928 243 1105 929 222 1103 927 222 1103 927 243 1105 929 242 1106 930 224 1107 931 244 1108 932 223 1104 928 223 1104 928 244 1108 932 243 1105 929 227 1110 934 246 1111 935 226 1109 933 226 1109 933 246 1111 935 245 1112 936 218 1097 921 230 1113 937 240 1098 922 240 1098 922 230 1113 937 247 1114 938 222 1103 927 242 1106 930 227 1110 934 227 1110 934 242 1106 930 246 1111 935 220 1101 925 241 1102 926 224 1107 931 224 1107 931 241 1102 926 244 1108 932 230 1113 937 226 1109 933 247 1114 938 247 1114 938 226 1109 933 245 1112 936 201 1115 939 204 1116 907 202 1118 940 202 1118 940 204 1116 907 203 1117 910 308 1119 941 311 1120 942 309 1122 944 309 1122 944 311 1120 942 310 1121 943 208 1124 915 207 1125 911 205 1123 945 205 1123 945 207 1125 911 206 1126 914 254 1128 947 253 1129 948 251 1127 946 251 1127 946 253 1129 948 252 1130 949 201 1115 939 202 1118 940 209 1131 950 209 1131 950 202 1118 940 210 1132 951 312 1133 952 313 1134 953 308 1119 941 308 1119 941 313 1134 953 311 1120 942 214 1136 920 213 1137 954 211 1135 917 211 1135 917 213 1137 954 212 1138 955 259 1140 957 258 1141 958 256 1139 956 256 1139 956 258 1141 958 257 1142 959 218 1144 921 217 1145 924 215 1143 960 215 1143 960 217 1145 924 216 1146 961 317 1148 963 316 1149 964 314 1147 962 314 1147 962 316 1149 964 315 1150 965 213 1137 954 214 1136 920 205 1123 945 205 1123 945 214 1136 920 208 1124 915 258 1141 958 251 1127 946 257 1142 959 257 1142 959 251 1127 946 252 1130 949 204 1116 907 201 1115 939 206 1126 914 206 1126 914 201 1115 939 205 1123 945 251 1127 946 248 1151 966 254 1128 947 254 1128 947 248 1151 966 249 1152 967 213 1137 954 209 1131 950 212 1138 955 212 1138 955 209 1131 950 216 1146 961 258 1141 958 259 1140 957 255 1154 969 255 1154 969 259 1140 957 262 1153 968 209 1131 950 210 1132 951 216 1146 961 216 1146 961 210 1132 951 215 1143 960 314 1147 962 313 1134 953 317 1148 963 317 1148 963 313 1134 953 312 1133 952 205 1123 945 201 1115 939 213 1137 954 213 1137 954 201 1115 939 209 1131 950 251 1127 946 258 1141 958 248 1151 966 248 1151 966 258 1141 958 255 1154 969 212 1138 955 216 1146 961 211 1135 917 211 1135 917 216 1146 961 217 1145 924 259 1140 957 256 1139 956 262 1153 968 262 1153 968 256 1139 956 261 1155 970 219 1156 971 202 1118 940 220 1157 925 220 1157 925 202 1118 940 203 1117 910 318 1158 972 319 1159 973 311 1120 942 311 1120 942 319 1159 973 310 1121 943 224 1161 931 223 1162 928 221 1160 974 221 1160 974 223 1162 928 222 1163 927 268 1165 976 267 1166 977 265 1164 975 265 1164 975 267 1166 977 266 1167 978 210 1132 951 202 1118 940 225 1168 979 225 1168 979 202 1118 940 219 1156 971 320 1169 980 318 1158 972 313 1134 953 313 1134 953 318 1158 972 311 1120 942 229 1171 981 228 1172 982 226 1170 933 226 1170 933 228 1172 982 227 1173 934 273 1175 984 272 1176 985 270 1174 983 270 1174 983 272 1176 985 271 1177 986 231 1178 987 230 1179 937 215 1143 960 215 1143 960 230 1179 937 218 1144 921 315 1150 965 322 1180 988 314 1147 962 314 1147 962 322 1180 988 321 1181 989 228 1172 982 221 1160 974 227 1173 934 227 1173 934 221 1160 974 222 1163 927 272 1176 985 273 1175 984 265 1164 975 265 1164 975 273 1175 984 268 1165 976 221 1160 974 219 1156 971 224 1161 931 224 1161 931 219 1156 971 220 1157 925 264 1182 990 263 1183 991 266 1167 978 266 1167 978 263 1183 991 265 1164 975 228 1172 982 229 1171 981 225 1168 979 225 1168 979 229 1171 981 231 1178 987 272 1176 985 269 1184 992 271 1177 986 271 1177 986 269 1184 992 274 1185 993 215 1143 960 210 1132 951 231 1178 987 231 1178 987 210 1132 951 225 1168 979 320 1169 980 313 1134 953 321 1181 989 321 1181 989 313 1134 953 314 1147 962 221 1160 974 228 1172 982 219 1156 971 219 1156 971 228 1172 982 225 1168 979 265 1164 975 263 1183 991 272 1176 985 272 1176 985 263 1183 991 269 1184 992 229 1171 981 226 1170 933 231 1178 987 231 1178 987 226 1170 933 230 1179 937 271 1177 986 274 1185 993 270 1174 983 270 1174 983 274 1185 993 275 1186 994 277 1188 996 234 1089 913 276 1187 995 276 1187 995 234 1089 913 235 1088 912 278 1189 997 233 1084 908 277 1188 996 277 1188 996 233 1084 908 234 1089 913 279 1190 998 232 1085 909 278 1189 997 278 1189 997 232 1085 909 233 1084 908 279 1190 998 280 1191 999 232 1085 909 232 1085 909 280 1191 999 241 1102 926 280 1191 999 281 1192 1000 241 1102 926 241 1102 926 281 1192 1000 244 1108 932 281 1192 1000 282 1193 1001 244 1108 932 244 1108 932 282 1193 1001 243 1105 929 283 1194 1002 242 1106 930 282 1193 1001 282 1193 1001 242 1106 930 243 1105 929 284 1195 1003 246 1111 935 283 1194 1002 283 1194 1002 246 1111 935 242 1106 930 285 1196 1004 245 1112 936 284 1195 1003 284 1195 1003 245 1112 936 246 1111 935 286 1197 1005 247 1114 938 285 1196 1004 285 1196 1004 247 1114 938 245 1112 936 287 1198 1006 240 1098 922 286 1197 1005 286 1197 1005 240 1098 922 247 1114 938 287 1198 1006 288 1199 1007 240 1098 922 240 1098 922 288 1199 1007 239 1099 923 288 1199 1007 289 1200 1008 239 1099 923 239 1099 923 289 1200 1008 237 1094 918 289 1200 1008 290 1201 1009 237 1094 918 237 1094 918 290 1201 1009 238 1095 919 290 1201 1009 291 1202 1010 238 1095 919 238 1095 919 291 1202 1010 236 1092 916 291 1202 1010 276 1187 995 236 1092 916 236 1092 916 276 1187 995 235 1088 912 250 1203 1011 293 1204 1012 249 1152 967 249 1152 967 293 1204 1012 292 1205 1013 293 1204 1012 279 1190 998 292 1205 1013 292 1205 1013 279 1190 998 278 1189 997 250 1203 1011 264 1206 990 293 1204 1012 293 1204 1012 264 1206 990 294 1207 1014 293 1204 1012 294 1207 1014 279 1190 998 279 1190 998 294 1207 1014 280 1191 999 264 1206 990 266 1167 978 294 1207 1014 294 1207 1014 266 1167 978 295 1208 1015 294 1207 1014 295 1208 1015 280 1191 999 280 1191 999 295 1208 1015 281 1192 1000 266 1167 978 267 1166 977 295 1208 1015 295 1208 1015 267 1166 977 296 1209 1016 295 1208 1015 296 1209 1016 281 1192 1000 281 1192 1000 296 1209 1016 282 1193 1001 268 1165 976 297 1210 1017 267 1166 977 267 1166 977 297 1210 1017 296 1209 1016 297 1210 1017 283 1194 1002 296 1209 1016 296 1209 1016 283 1194 1002 282 1193 1001 273 1175 984 298 1211 1018 268 1165 976 268 1165 976 298 1211 1018 297 1210 1017 298 1211 1018 284 1195 1003 297 1210 1017 297 1210 1017 284 1195 1003 283 1194 1002 270 1174 983 299 1212 1019 273 1175 984 273 1175 984 299 1212 1019 298 1211 1018 299 1212 1019 285 1196 1004 298 1211 1018 298 1211 1018 285 1196 1004 284 1195 1003 275 1213 994 300 1214 1020 270 1174 983 270 1174 983 300 1214 1020 299 1212 1019 300 1214 1020 286 1197 1005 299 1212 1019 299 1212 1019 286 1197 1005 285 1196 1004 260 1215 1021 301 1216 1022 275 1213 994 275 1213 994 301 1216 1022 300 1214 1020 301 1216 1022 287 1198 1006 300 1214 1020 300 1214 1020 287 1198 1006 286 1197 1005 260 1215 1021 261 1217 970 301 1216 1022 301 1216 1022 261 1217 970 302 1218 1023 301 1216 1022 302 1218 1023 287 1198 1006 287 1198 1006 302 1218 1023 288 1199 1007 261 1219 970 256 1139 956 302 1218 1023 302 1218 1023 256 1139 956 303 1220 1024 302 1218 1023 303 1220 1024 288 1199 1007 288 1199 1007 303 1220 1024 289 1200 1008 256 1139 956 257 1142 959 303 1220 1024 303 1220 1024 257 1142 959 304 1221 1025 303 1220 1024 304 1221 1025 289 1200 1008 289 1200 1008 304 1221 1025 290 1201 1009 257 1142 959 252 1130 949 304 1221 1025 304 1221 1025 252 1130 949 305 1222 1026 304 1221 1025 305 1222 1026 290 1201 1009 290 1201 1009 305 1222 1026 291 1202 1010 252 1130 949 253 1129 948 305 1222 1026 305 1222 1026 253 1129 948 306 1223 1027 305 1222 1026 306 1223 1027 291 1202 1010 291 1202 1010 306 1223 1027 276 1187 995 254 1128 947 307 1224 1028 253 1129 948 253 1129 948 307 1224 1028 306 1223 1027 307 1224 1028 277 1188 996 306 1223 1027 306 1223 1027 277 1188 996 276 1187 995 249 1152 967 292 1205 1013 254 1128 947 254 1128 947 292 1205 1013 307 1224 1028 292 1205 1013 278 1189 997 307 1224 1028 307 1224 1028 278 1189 997 277 1188 996 309 1225 944 310 1226 943 323 1228 1030 323 1228 1030 310 1226 943 324 1227 1029 323 1228 1030 324 1227 1029 325 1230 1032 325 1230 1032 324 1227 1029 326 1229 1031 326 1229 1031 250 1203 1011 325 1231 1032 325 1231 1032 250 1203 1011 249 1152 967 319 1232 973 327 1233 1033 310 1226 943 310 1226 943 327 1233 1033 324 1227 1029 327 1233 1033 328 1234 1034 324 1227 1029 324 1227 1029 328 1234 1034 326 1229 1031 326 1229 1031 328 1234 1034 250 1203 1011 250 1203 1011 328 1234 1034 264 1235 990 318 1237 972 329 1238 1035 319 1236 973 319 1236 973 329 1238 1035 327 1239 1033 329 1238 1035 330 1240 1036 327 1239 1033 327 1239 1033 330 1240 1036 328 1241 1034 330 1240 1036 263 1183 991 328 1241 1034 328 1241 1034 263 1183 991 264 1182 990 320 1242 980 331 1243 1037 318 1237 972 318 1237 972 331 1243 1037 329 1238 1035 331 1243 1037 332 1244 1038 329 1238 1035 329 1238 1035 332 1244 1038 330 1240 1036 332 1244 1038 269 1184 992 330 1240 1036 330 1240 1036 269 1184 992 263 1183 991 321 1245 989 333 1246 1039 320 1242 980 320 1242 980 333 1246 1039 331 1243 1037 333 1246 1039 334 1247 1040 331 1243 1037 331 1243 1037 334 1247 1040 332 1244 1038 334 1247 1040 274 1185 993 332 1244 1038 332 1244 1038 274 1185 993 269 1184 992 322 1248 988 335 1249 1041 321 1245 989 321 1245 989 335 1249 1041 333 1246 1039 335 1249 1041 336 1250 1042 333 1246 1039 333 1246 1039 336 1250 1042 334 1247 1040 336 1251 1042 275 1186 994 334 1247 1040 334 1247 1040 275 1186 994 274 1185 993 315 1252 965 337 1253 1043 322 1248 988 322 1248 988 337 1253 1043 335 1249 1041 337 1253 1043 338 1254 1044 335 1249 1041 335 1249 1041 338 1254 1044 336 1255 1042 338 1254 1044 260 1256 1021 336 1255 1042 336 1255 1042 260 1256 1021 275 1257 994 315 1252 965 316 1258 964 337 1253 1043 337 1253 1043 316 1258 964 339 1259 1045 337 1253 1043 339 1259 1045 338 1254 1044 338 1254 1044 339 1259 1045 340 1260 1046 338 1254 1044 340 1260 1046 260 1256 1021 260 1256 1021 340 1260 1046 261 1261 970 316 1258 964 317 1262 963 339 1259 1045 339 1259 1045 317 1262 963 341 1263 1047 339 1259 1045 341 1263 1047 340 1265 1046 340 1265 1046 341 1263 1047 342 1264 1048 340 1266 1046 342 1264 1048 261 1267 970 261 1267 970 342 1264 1048 262 1153 968 317 1262 963 312 1268 952 341 1263 1047 341 1263 1047 312 1268 952 343 1269 1049 341 1263 1047 343 1269 1049 342 1264 1048 342 1264 1048 343 1269 1049 344 1270 1050 342 1264 1048 344 1270 1050 262 1153 968 262 1153 968 344 1270 1050 255 1154 969 312 1268 952 308 1271 941 343 1269 1049 343 1269 1049 308 1271 941 345 1272 1051 343 1269 1049 345 1272 1051 344 1270 1050 344 1270 1050 345 1272 1051 346 1273 1052 344 1270 1050 346 1273 1052 255 1154 969 255 1154 969 346 1273 1052 248 1151 966 308 1271 941 309 1274 944 345 1272 1051 345 1272 1051 309 1274 944 323 1275 1030 345 1272 1051 323 1275 1030 346 1273 1052 346 1273 1052 323 1275 1030 325 1276 1032 346 1273 1052 325 1277 1032 248 1151 966 248 1151 966 325 1277 1032 249 1152 967 1672 2604 697 1671 2605 696 1658 2603 694 1658 2603 694 1671 2605 696 1657 2606 695 1673 2608 699 1658 2603 694 1674 2607 698 1674 2607 698 1658 2603 694 1657 2606 695 1658 2603 694 1659 2609 701 1672 2604 697 1672 2604 697 1659 2609 701 1669 2610 700 1673 2608 699 1670 2611 702 1658 2603 694 1658 2603 694 1670 2611 702 1659 2609 701 1845 2612 704 1849 2613 703 1657 2606 695 1657 2606 695 1849 2613 703 1674 2607 698 1657 2606 695 1660 2614 706 1845 2612 704 1845 2612 704 1660 2614 706 1846 2615 705 1657 2606 695 1671 2605 696 1660 2614 706 1660 2614 706 1671 2605 696 1675 2616 707 1676 2617 708 1677 2618 711 1668 2620 709 1668 2620 709 1677 2618 711 1663 2619 710 1677 2618 711 1678 2621 713 1663 2619 710 1663 2619 710 1678 2621 713 1662 2622 712 1678 2621 713 1679 2623 715 1662 2622 712 1662 2622 712 1679 2623 715 1666 2624 714 1673 2625 699 1674 2626 698 1680 2628 716 1680 2628 716 1674 2626 698 1681 2627 717 1674 2626 698 1849 2629 703 1681 2627 717 1681 2627 717 1849 2629 703 1850 2630 718 1670 2631 702 1673 2625 699 1682 2632 719 1682 2632 719 1673 2625 699 1680 2628 716 1683 2633 720 1682 2632 719 1684 2634 721 1684 2634 721 1682 2632 719 1680 2628 716 1684 2634 721 1680 2628 716 1685 2635 722 1685 2635 722 1680 2628 716 1681 2627 717 1681 2627 717 1850 2630 718 1685 2635 722 1685 2635 722 1850 2630 718 1851 2636 723 1686 2637 724 1683 2638 720 1687 2640 725 1687 2640 725 1683 2638 720 1684 2639 721 1687 2641 725 1684 2642 721 1688 2644 726 1688 2644 726 1684 2642 721 1685 2643 722 1688 2645 726 1685 2646 722 1852 2648 727 1852 2648 727 1685 2646 722 1851 2647 723 1687 2649 725 1703 2650 729 1686 2652 724 1686 2652 724 1703 2650 729 1704 2651 728 1688 2653 726 1706 2654 730 1687 2655 725 1687 2655 725 1706 2654 730 1703 2650 729 1852 2656 727 1854 2657 731 1688 2659 726 1688 2659 726 1854 2657 731 1706 2658 730 1703 2650 729 1699 2660 733 1704 2651 728 1704 2651 728 1699 2660 733 1700 2661 732 1706 2654 730 1702 2662 734 1703 2650 729 1703 2650 729 1702 2662 734 1699 2660 733 1706 2654 730 1854 2663 731 1702 2662 734 1702 2662 734 1854 2663 731 1853 2664 735 1708 2666 737 1700 2661 732 1707 2665 736 1707 2665 736 1700 2661 732 1699 2660 733 1710 2667 738 1707 2665 736 1702 2662 734 1702 2662 734 1707 2665 736 1699 2660 733 1855 2668 739 1710 2667 738 1853 2664 735 1853 2664 735 1710 2667 738 1702 2662 734 1707 2665 736 1711 2669 741 1708 2666 737 1708 2666 737 1711 2669 741 1712 2670 740 1711 2669 741 1661 2671 743 1712 2670 740 1712 2670 740 1661 2671 743 1665 2672 742 1714 2673 744 1711 2669 741 1710 2667 738 1710 2667 738 1711 2669 741 1707 2665 736 1664 2674 745 1661 2671 743 1714 2673 744 1714 2673 744 1661 2671 743 1711 2669 741 1856 2675 746 1714 2673 744 1855 2668 739 1855 2668 739 1714 2673 744 1710 2667 738 1847 2676 747 1664 2674 745 1856 2675 746 1856 2675 746 1664 2674 745 1714 2673 744 1664 2674 745 1715 2677 749 1661 2671 743 1661 2671 743 1715 2677 749 1716 2678 748 1715 2677 749 1663 2619 710 1716 2678 748 1716 2678 748 1663 2619 710 1662 2622 712 1661 2671 743 1716 2678 748 1665 2672 742 1665 2672 742 1716 2678 748 1717 2679 750 1716 2678 748 1662 2622 712 1717 2679 750 1717 2679 750 1662 2622 712 1666 2624 714 1715 2677 749 1719 2680 751 1663 2619 710 1663 2619 710 1719 2680 751 1668 2620 709 1668 2620 709 1719 2680 751 1667 2682 752 1667 2682 752 1719 2680 751 1720 2681 753 1715 2677 749 1664 2674 745 1719 2680 751 1719 2680 751 1664 2674 745 1720 2681 753 1720 2681 753 1857 2683 755 1667 2682 752 1667 2682 752 1857 2683 755 1848 2684 754 1664 2674 745 1847 2676 747 1720 2681 753 1720 2681 753 1847 2676 747 1857 2683 755 1728 2686 759 1729 2687 758 1727 2685 756 1727 2685 756 1729 2687 758 1730 2688 757 1735 2689 760 1697 2690 763 1721 2692 761 1721 2692 761 1697 2690 763 1698 2691 762 1722 2693 764 1721 2692 761 1692 2695 765 1692 2695 765 1721 2692 761 1698 2694 762 1722 2693 764 1692 2695 765 1723 2696 766 1723 2696 766 1692 2695 765 1690 2697 767 1724 2698 768 1723 2696 766 1689 2700 769 1689 2700 769 1723 2696 766 1690 2699 767 1724 2698 768 1689 2700 769 1725 2702 770 1725 2702 770 1689 2700 769 1691 2701 771 1691 2703 771 1693 2704 773 1725 2702 770 1725 2702 770 1693 2704 773 1726 2705 772 1693 2704 773 1696 2706 774 1726 2705 772 1726 2705 772 1696 2706 774 1727 2685 756 1727 2685 756 1696 2707 774 1728 2686 759 1728 2686 759 1696 2707 774 1695 2708 775 1695 2709 775 1705 2710 776 1728 2686 759 1728 2686 759 1705 2710 776 1729 2687 758 1705 2710 776 1701 2711 777 1729 2687 758 1729 2687 758 1701 2711 777 1730 2688 757 1731 2712 778 1730 2688 757 1709 2714 779 1709 2714 779 1730 2688 757 1701 2713 777 1731 2712 778 1709 2714 779 1732 2716 780 1732 2716 780 1709 2714 779 1713 2715 781 1733 2717 782 1732 2716 780 1694 2718 783 1694 2718 783 1732 2716 780 1713 2715 781 1694 2718 783 1718 2719 785 1733 2717 782 1733 2717 782 1718 2719 785 1734 2720 784 1734 2720 784 1718 2719 785 1735 2689 760 1735 2689 760 1718 2719 785 1697 2721 763 1722 2693 764 1734 2720 784 1721 2692 761 1721 2692 761 1734 2720 784 1735 2689 760 1726 2705 772 1727 2685 756 1731 2712 778 1731 2712 778 1727 2685 756 1730 2688 757 1725 2702 770 1732 2716 780 1724 2698 768 1724 2698 768 1732 2716 780 1733 2717 782 1726 2705 772 1731 2712 778 1725 2702 770 1725 2702 770 1731 2712 778 1732 2716 780 1733 2717 782 1734 2720 784 1724 2698 768 1724 2698 768 1734 2720 784 1723 2696 766 1723 2696 766 1734 2720 784 1722 2693 764 1689 2700 769 1690 2699 767 1737 2723 786 1737 2723 786 1690 2699 767 1736 2722 787 1669 2610 700 1659 2609 701 1736 2722 787 1736 2722 787 1659 2609 701 1737 2723 786 1691 2701 771 1689 2700 769 1738 2724 788 1738 2724 788 1689 2700 769 1737 2723 786 1659 2609 701 1670 2611 702 1737 2723 786 1737 2723 786 1670 2611 702 1738 2724 788 1690 2725 767 1692 2726 765 1736 2728 787 1736 2728 787 1692 2726 765 1739 2727 789 1691 2729 771 1738 2730 788 1693 2732 773 1693 2732 773 1738 2730 788 1740 2731 790 1738 2730 788 1670 2631 702 1740 2731 790 1740 2731 790 1670 2631 702 1682 2632 719 1695 2733 775 1696 2734 774 1742 2736 791 1742 2736 791 1696 2734 774 1741 2735 792 1683 2638 720 1686 2637 724 1741 2735 792 1741 2735 792 1686 2637 724 1742 2736 791 1697 2737 763 1743 2738 794 1698 2740 762 1698 2740 762 1743 2738 794 1744 2739 793 1743 2738 794 1666 2624 714 1744 2739 793 1744 2739 793 1666 2624 714 1679 2623 715 1740 2731 790 1741 2741 792 1693 2732 773 1693 2732 773 1741 2741 792 1696 2742 774 1741 2741 792 1740 2731 790 1683 2633 720 1683 2633 720 1740 2731 790 1682 2632 719 1698 2743 762 1744 2744 793 1692 2726 765 1692 2726 765 1744 2744 793 1739 2727 789 1742 2746 791 1745 2747 795 1695 2745 775 1695 2745 775 1745 2747 795 1705 2748 776 1742 2746 791 1686 2652 724 1745 2747 795 1745 2747 795 1686 2652 724 1704 2651 728 1700 2661 732 1746 2749 796 1704 2651 728 1704 2651 728 1746 2749 796 1745 2747 795 1745 2747 795 1746 2749 796 1705 2748 776 1705 2748 776 1746 2749 796 1701 2750 777 1701 2751 777 1746 2749 796 1709 2714 779 1709 2714 779 1746 2749 796 1747 2752 797 1700 2661 732 1708 2666 737 1746 2749 796 1746 2749 796 1708 2666 737 1747 2752 797 1748 2753 798 1713 2715 781 1747 2752 797 1747 2752 797 1713 2715 781 1709 2714 779 1712 2670 740 1748 2753 798 1708 2666 737 1708 2666 737 1748 2753 798 1747 2752 797 1749 2754 799 1694 2718 783 1748 2753 798 1748 2753 798 1694 2718 783 1713 2715 781 1665 2672 742 1749 2754 799 1712 2670 740 1712 2670 740 1749 2754 799 1748 2753 798 1750 2755 800 1718 2719 785 1749 2754 799 1749 2754 799 1718 2719 785 1694 2718 783 1717 2679 750 1750 2755 800 1665 2672 742 1665 2672 742 1750 2755 800 1749 2754 799 1697 2756 763 1718 2719 785 1743 2738 794 1743 2738 794 1718 2719 785 1750 2755 800 1717 2679 750 1666 2624 714 1750 2755 800 1750 2755 800 1666 2624 714 1743 2738 794 1751 2758 804 1765 2759 803 1752 2757 801 1752 2757 801 1765 2759 803 1766 2760 802 1751 2758 804 1752 2757 801 1768 2761 805 1768 2761 805 1752 2757 801 1767 2762 806 1763 2763 808 1753 2764 807 1766 2760 802 1766 2760 802 1753 2764 807 1752 2757 801 1753 2764 807 1764 2765 809 1752 2757 801 1752 2757 801 1764 2765 809 1767 2762 806 1768 2761 805 1849 2613 703 1751 2758 804 1751 2758 804 1849 2613 703 1845 2612 704 1846 2615 705 1754 2766 810 1845 2612 704 1845 2612 704 1754 2766 810 1751 2758 804 1751 2758 804 1754 2766 810 1765 2759 803 1765 2759 803 1754 2766 810 1769 2767 811 1770 2768 812 1762 2769 815 1771 2771 813 1771 2771 813 1762 2769 815 1757 2770 814 1771 2771 813 1757 2770 814 1772 2773 816 1772 2773 816 1757 2770 814 1756 2772 817 1772 2773 816 1756 2772 817 1773 2775 818 1773 2775 818 1756 2772 817 1760 2774 819 1767 2776 806 1774 2777 821 1768 2779 805 1768 2779 805 1774 2777 821 1775 2778 820 1768 2779 805 1775 2778 820 1849 2629 703 1849 2629 703 1775 2778 820 1850 2630 718 1764 2780 809 1776 2781 822 1767 2776 806 1767 2776 806 1776 2781 822 1774 2777 821 1777 2782 823 1778 2783 824 1776 2781 822 1776 2781 822 1778 2783 824 1774 2777 821 1778 2783 824 1779 2784 825 1774 2777 821 1774 2777 821 1779 2784 825 1775 2778 820 1851 2636 723 1850 2630 718 1779 2784 825 1779 2784 825 1850 2630 718 1775 2778 820 1780 2785 826 1781 2786 827 1777 2788 823 1777 2788 823 1781 2786 827 1778 2787 824 1781 2789 827 1782 2790 828 1778 2792 824 1778 2792 824 1782 2790 828 1779 2791 825 1782 2793 828 1852 2648 727 1779 2794 825 1779 2794 825 1852 2648 727 1851 2647 723 1781 2795 827 1780 2796 826 1797 2798 829 1797 2798 829 1780 2796 826 1798 2797 830 1782 2799 828 1781 2800 827 1800 2801 831 1800 2801 831 1781 2800 827 1797 2798 829 1852 2802 727 1782 2803 828 1854 2805 731 1854 2805 731 1782 2803 828 1800 2804 831 1794 2806 833 1793 2807 832 1798 2797 830 1798 2797 830 1793 2807 832 1797 2798 829 1793 2807 832 1796 2808 834 1797 2798 829 1797 2798 829 1796 2808 834 1800 2801 831 1800 2801 831 1796 2808 834 1854 2809 731 1854 2809 731 1796 2808 834 1853 2664 735 1793 2807 832 1794 2806 833 1801 2810 835 1801 2810 835 1794 2806 833 1802 2811 836 1804 2812 837 1796 2808 834 1801 2810 835 1801 2810 835 1796 2808 834 1793 2807 832 1855 2668 739 1853 2664 735 1804 2812 837 1804 2812 837 1853 2664 735 1796 2808 834 1801 2810 835 1802 2811 836 1805 2814 838 1805 2814 838 1802 2811 836 1806 2813 839 1805 2814 838 1806 2813 839 1755 2816 840 1755 2816 840 1806 2813 839 1759 2815 841 1801 2810 835 1805 2814 838 1804 2812 837 1804 2812 837 1805 2814 838 1808 2817 842 1805 2814 838 1755 2816 840 1808 2817 842 1808 2817 842 1755 2816 840 1758 2818 843 1804 2812 837 1808 2817 842 1855 2668 739 1855 2668 739 1808 2817 842 1856 2675 746 1808 2817 842 1758 2818 843 1856 2675 746 1856 2675 746 1758 2818 843 1847 2676 747 1758 2818 843 1755 2816 840 1809 2820 844 1809 2820 844 1755 2816 840 1810 2819 845 1809 2820 844 1810 2819 845 1757 2770 814 1757 2770 814 1810 2819 845 1756 2772 817 1755 2816 840 1759 2815 841 1810 2819 845 1810 2819 845 1759 2815 841 1811 2821 846 1810 2819 845 1811 2821 846 1756 2772 817 1756 2772 817 1811 2821 846 1760 2774 819 1809 2820 844 1757 2770 814 1813 2822 847 1813 2822 847 1757 2770 814 1762 2769 815 1762 2769 815 1761 2823 849 1813 2822 847 1813 2822 847 1761 2823 849 1814 2824 848 1814 2824 848 1758 2818 843 1813 2822 847 1813 2822 847 1758 2818 843 1809 2820 844 1848 2684 754 1857 2683 755 1761 2823 849 1761 2823 849 1857 2683 755 1814 2824 848 1857 2683 755 1847 2676 747 1814 2824 848 1814 2824 848 1847 2676 747 1758 2818 843 1824 2826 853 1823 2827 852 1821 2825 850 1821 2825 850 1823 2827 852 1822 2828 851 1829 2829 854 1815 2830 857 1791 2832 855 1791 2832 855 1815 2830 857 1792 2831 856 1816 2833 858 1786 2834 859 1815 2830 857 1815 2830 857 1786 2834 859 1792 2835 856 1784 2837 861 1786 2834 859 1817 2836 860 1817 2836 860 1786 2834 859 1816 2833 858 1818 2838 862 1783 2839 863 1817 2836 860 1817 2836 860 1783 2839 863 1784 2840 861 1818 2838 862 1819 2841 865 1783 2839 863 1783 2839 863 1819 2841 865 1785 2842 864 1820 2843 867 1787 2844 866 1819 2841 865 1819 2841 865 1787 2844 866 1785 2845 864 1821 2825 850 1790 2846 868 1820 2843 867 1820 2843 867 1790 2846 868 1787 2844 866 1789 2847 869 1790 2848 868 1822 2828 851 1822 2828 851 1790 2848 868 1821 2825 850 1823 2827 852 1799 2849 870 1822 2828 851 1822 2828 851 1799 2849 870 1789 2850 869 1824 2826 853 1795 2851 871 1823 2827 852 1823 2827 852 1795 2851 871 1799 2849 870 1825 2852 872 1803 2853 873 1824 2826 853 1824 2826 853 1803 2853 873 1795 2854 871 1825 2852 872 1826 2855 875 1803 2853 873 1803 2853 873 1826 2855 875 1807 2856 874 1827 2857 876 1788 2858 877 1826 2855 875 1826 2855 875 1788 2858 877 1807 2856 874 1828 2859 879 1812 2860 878 1827 2857 876 1827 2857 876 1812 2860 878 1788 2858 877 1828 2859 879 1829 2829 854 1812 2860 878 1812 2860 878 1829 2829 854 1791 2861 855 1829 2829 854 1828 2859 879 1815 2830 857 1815 2830 857 1828 2859 879 1816 2833 858 1824 2826 853 1821 2825 850 1825 2852 872 1825 2852 872 1821 2825 850 1820 2843 867 1827 2857 876 1826 2855 875 1818 2838 862 1818 2838 862 1826 2855 875 1819 2841 865 1826 2855 875 1825 2852 872 1819 2841 865 1819 2841 865 1825 2852 872 1820 2843 867 1817 2836 860 1828 2859 879 1818 2838 862 1818 2838 862 1828 2859 879 1827 2857 876 1817 2836 860 1816 2833 858 1828 2859 879 1783 2839 863 1831 2862 881 1784 2840 861 1784 2840 861 1831 2862 881 1830 2863 880 1831 2862 881 1753 2764 807 1830 2863 880 1830 2863 880 1753 2764 807 1763 2763 808 1785 2842 864 1832 2864 882 1783 2839 863 1783 2839 863 1832 2864 882 1831 2862 881 1832 2864 882 1764 2765 809 1831 2862 881 1831 2862 881 1764 2765 809 1753 2764 807 1784 2865 861 1830 2866 880 1786 2868 859 1786 2868 859 1830 2866 880 1833 2867 883 1785 2869 864 1787 2870 866 1832 2872 882 1832 2872 882 1787 2870 866 1834 2871 884 1776 2781 822 1764 2780 809 1834 2871 884 1834 2871 884 1764 2780 809 1832 2872 882 1789 2873 869 1836 2874 886 1790 2876 868 1790 2876 868 1836 2874 886 1835 2875 885 1836 2874 886 1780 2785 826 1835 2875 885 1835 2875 885 1780 2785 826 1777 2788 823 1791 2877 855 1792 2878 856 1837 2880 887 1837 2880 887 1792 2878 856 1838 2879 888 1773 2775 818 1760 2774 819 1838 2879 888 1838 2879 888 1760 2774 819 1837 2880 887 1790 2881 868 1835 2882 885 1787 2870 866 1787 2870 866 1835 2882 885 1834 2871 884 1835 2882 885 1777 2782 823 1834 2871 884 1834 2871 884 1777 2782 823 1776 2781 822 1792 2883 856 1786 2868 859 1838 2884 888 1838 2884 888 1786 2868 859 1833 2867 883 1799 2886 870 1839 2887 889 1789 2885 869 1789 2885 869 1839 2887 889 1836 2888 886 1798 2797 830 1780 2796 826 1839 2887 889 1839 2887 889 1780 2796 826 1836 2888 886 1794 2806 833 1798 2797 830 1840 2889 890 1840 2889 890 1798 2797 830 1839 2887 889 1839 2887 889 1799 2886 870 1840 2889 890 1840 2889 890 1799 2886 870 1795 2890 871 1841 2891 891 1840 2889 890 1803 2853 873 1803 2853 873 1840 2889 890 1795 2892 871 1841 2891 891 1802 2811 836 1840 2889 890 1840 2889 890 1802 2811 836 1794 2806 833 1803 2853 873 1807 2856 874 1841 2891 891 1841 2891 891 1807 2856 874 1842 2893 892 1806 2813 839 1802 2811 836 1842 2893 892 1842 2893 892 1802 2811 836 1841 2891 891 1807 2856 874 1788 2858 877 1842 2893 892 1842 2893 892 1788 2858 877 1843 2894 893 1759 2815 841 1806 2813 839 1843 2894 893 1843 2894 893 1806 2813 839 1842 2893 892 1788 2858 877 1812 2860 878 1843 2894 893 1843 2894 893 1812 2860 878 1844 2895 894 1811 2821 846 1759 2815 841 1844 2895 894 1844 2895 894 1759 2815 841 1843 2894 893 1791 2896 855 1837 2880 887 1812 2860 878 1812 2860 878 1837 2880 887 1844 2895 894 1837 2880 887 1760 2774 819 1844 2895 894 1844 2895 894 1760 2774 819 1811 2821 846 1838 2884 888 1833 2867 883 1773 2898 818 1763 2897 808 1773 2898 818 1830 2866 880 1833 2867 883 1830 2866 880 1773 2898 818 1773 2898 818 1763 2897 808 1772 2899 816 1772 2899 816 1763 2897 808 1766 2900 802 1772 2899 816 1766 2900 802 1771 2901 813 1771 2901 813 1766 2900 802 1765 2902 803 1771 2901 813 1765 2902 803 1770 2904 812 1770 2904 812 1765 2902 803 1769 2903 811 1744 2744 793 1679 2905 715 1739 2727 789 1669 2906 700 1736 2728 787 1679 2905 715 1679 2905 715 1736 2728 787 1739 2727 789 1672 2908 697 1669 2906 700 1678 2907 713 1678 2907 713 1669 2906 700 1679 2905 715 1671 2910 696 1672 2908 697 1677 2909 711 1677 2909 711 1672 2908 697 1678 2907 713 1677 2909 711 1676 2911 708 1671 2910 696 1671 2910 696 1676 2911 708 1675 2912 707 1660 2614 706 3003 2913 896 1846 2615 705 1846 2615 705 3003 2913 896 3002 2914 895 1660 2614 706 1675 2616 707 3003 2913 896 3003 2913 896 1675 2616 707 3004 2915 897 1676 2911 708 3005 2916 898 1675 2912 707 1675 2912 707 3005 2916 898 3004 2917 897 1668 2620 709 3006 2918 899 1676 2617 708 1676 2617 708 3006 2918 899 3005 2919 898 1668 2620 709 1667 2682 752 3006 2918 899 3006 2918 899 1667 2682 752 3007 2920 900 1667 2682 752 1848 2684 754 3007 2920 900 3007 2920 900 1848 2684 754 3008 2921 901 1761 2823 849 3009 2922 902 1848 2684 754 1848 2684 754 3009 2922 902 3008 2921 901 1762 2769 815 3010 2923 903 1761 2823 849 1761 2823 849 3010 2923 903 3009 2922 902 1762 2769 815 1770 2768 812 3010 2923 903 3010 2923 903 1770 2768 812 3011 2924 904 1770 2904 812 1769 2903 811 3011 2926 904 3011 2926 904 1769 2903 811 3012 2925 905 1769 2767 811 1754 2766 810 3012 2928 905 3012 2928 905 1754 2766 810 3013 2927 906 1754 2766 810 1846 2615 705 3013 2927 906 3013 2927 906 1846 2615 705 3002 2914 895 1860 2930 910 1889 2931 909 1861 2929 907 1861 2929 907 1889 2931 909 1890 2932 908 1863 2934 914 1891 2935 913 1864 2933 911 1864 2933 911 1891 2935 913 1892 2936 912 1864 2933 911 1892 2936 912 1865 2937 915 1865 2937 915 1892 2936 912 1893 2938 916 1871 2940 920 1895 2941 919 1868 2939 917 1868 2939 917 1895 2941 919 1894 2942 918 1875 2943 921 1874 2944 924 1897 2946 922 1897 2946 922 1874 2944 924 1896 2945 923 1865 2937 915 1893 2938 916 1871 2940 920 1871 2940 920 1893 2938 916 1895 2941 919 1861 2929 907 1890 2932 908 1863 2934 914 1863 2934 914 1890 2932 908 1891 2935 913 1874 2944 924 1868 2939 917 1896 2945 923 1896 2945 923 1868 2939 917 1894 2942 918 1898 2948 926 1889 2931 909 1877 2947 925 1877 2947 925 1889 2931 909 1860 2930 910 1899 2950 930 1900 2951 929 1879 2949 927 1879 2949 927 1900 2951 929 1880 2952 928 1900 2951 929 1901 2953 932 1880 2952 928 1880 2952 928 1901 2953 932 1881 2954 931 1902 2956 936 1903 2957 935 1883 2955 933 1883 2955 933 1903 2957 935 1884 2958 934 1875 2943 921 1897 2946 922 1887 2960 937 1887 2960 937 1897 2946 922 1904 2959 938 1903 2957 935 1899 2950 930 1884 2958 934 1884 2958 934 1899 2950 930 1879 2949 927 1901 2953 932 1898 2948 926 1881 2954 931 1881 2954 931 1898 2948 926 1877 2947 925 1887 2960 937 1904 2959 938 1883 2955 933 1883 2955 933 1904 2959 938 1902 2956 936 1858 2961 939 1859 2962 940 1861 2964 907 1861 2964 907 1859 2962 940 1860 2963 910 1965 2965 941 1966 2966 944 1968 2968 942 1968 2968 942 1966 2966 944 1967 2967 943 1863 2970 914 1864 2971 911 1862 2969 945 1862 2969 945 1864 2971 911 1865 2972 915 1909 2974 949 1910 2975 948 1908 2973 946 1908 2973 946 1910 2975 948 1911 2976 947 1867 2978 951 1859 2962 940 1866 2977 950 1866 2977 950 1859 2962 940 1858 2961 939 1969 2979 952 1965 2965 941 1970 2980 953 1970 2980 953 1965 2965 941 1968 2968 942 1869 2982 955 1870 2983 954 1868 2981 917 1868 2981 917 1870 2983 954 1871 2984 920 1914 2986 959 1915 2987 958 1913 2985 956 1913 2985 956 1915 2987 958 1916 2988 957 1873 2990 961 1874 2991 924 1872 2989 960 1872 2989 960 1874 2991 924 1875 2992 921 1972 2994 965 1973 2995 964 1971 2993 962 1971 2993 962 1973 2995 964 1974 2996 963 1870 2983 954 1862 2969 945 1871 2984 920 1871 2984 920 1862 2969 945 1865 2972 915 1915 2987 958 1914 2986 959 1908 2973 946 1908 2973 946 1914 2986 959 1909 2974 949 1862 2969 945 1858 2961 939 1863 2970 914 1863 2970 914 1858 2961 939 1861 2964 907 1906 2997 967 1905 2998 966 1911 2976 947 1911 2976 947 1905 2998 966 1908 2973 946 1870 2983 954 1869 2982 955 1866 2977 950 1866 2977 950 1869 2982 955 1873 2990 961 1915 2987 958 1912 2999 969 1916 2988 957 1916 2988 957 1912 2999 969 1919 3000 968 1872 2989 960 1867 2978 951 1873 2990 961 1873 2990 961 1867 2978 951 1866 2977 950 1969 2979 952 1970 2980 953 1974 2996 963 1974 2996 963 1970 2980 953 1971 2993 962 1862 2969 945 1870 2983 954 1858 2961 939 1858 2961 939 1870 2983 954 1866 2977 950 1908 2973 946 1905 2998 966 1915 2987 958 1915 2987 958 1905 2998 966 1912 2999 969 1869 2982 955 1868 2981 917 1873 2990 961 1873 2990 961 1868 2981 917 1874 2991 924 1916 2988 957 1919 3000 968 1913 2985 956 1913 2985 956 1919 3000 968 1918 3001 970 1876 3002 971 1877 3003 925 1859 2962 940 1859 2962 940 1877 3003 925 1860 2963 910 1975 3004 972 1968 2968 942 1976 3005 973 1976 3005 973 1968 2968 942 1967 2967 943 1879 3007 927 1880 3008 928 1878 3006 974 1878 3006 974 1880 3008 928 1881 3009 931 1923 3011 978 1924 3012 977 1922 3010 975 1922 3010 975 1924 3012 977 1925 3013 976 1876 3002 971 1859 2962 940 1882 3014 979 1882 3014 979 1859 2962 940 1867 2978 951 1977 3015 980 1970 2980 953 1975 3004 972 1975 3004 972 1970 2980 953 1968 2968 942 1884 3017 934 1885 3018 982 1883 3016 933 1883 3016 933 1885 3018 982 1886 3019 981 1928 3021 986 1929 3022 985 1927 3020 983 1927 3020 983 1929 3022 985 1930 3023 984 1875 2992 921 1887 3024 937 1872 2989 960 1872 2989 960 1887 3024 937 1888 3025 987 1978 3026 989 1979 3027 988 1971 2993 962 1971 2993 962 1979 3027 988 1972 2994 965 1885 3018 982 1884 3017 934 1878 3006 974 1878 3006 974 1884 3017 934 1879 3007 927 1929 3022 985 1922 3010 975 1930 3023 984 1930 3023 984 1922 3010 975 1925 3013 976 1877 3003 925 1876 3002 971 1881 3009 931 1881 3009 931 1876 3002 971 1878 3006 974 1922 3010 975 1920 3028 991 1923 3011 978 1923 3011 978 1920 3028 991 1921 3029 990 1885 3018 982 1882 3014 979 1886 3019 981 1886 3019 981 1882 3014 979 1888 3025 987 1929 3022 985 1928 3021 986 1926 3031 992 1926 3031 992 1928 3021 986 1931 3030 993 1882 3014 979 1867 2978 951 1888 3025 987 1888 3025 987 1867 2978 951 1872 2989 960 1971 2993 962 1970 2980 953 1978 3026 989 1978 3026 989 1970 2980 953 1977 3015 980 1878 3006 974 1876 3002 971 1885 3018 982 1885 3018 982 1876 3002 971 1882 3014 979 1922 3010 975 1929 3022 985 1920 3028 991 1920 3028 991 1929 3022 985 1926 3031 992 1886 3019 981 1888 3025 987 1883 3016 933 1883 3016 933 1888 3025 987 1887 3024 937 1928 3021 986 1927 3020 983 1931 3030 993 1931 3030 993 1927 3020 983 1932 3032 994 1892 2936 912 1891 2935 913 1933 3033 995 1933 3033 995 1891 2935 913 1934 3034 996 1891 2935 913 1890 2932 908 1934 3034 996 1934 3034 996 1890 2932 908 1935 3035 997 1890 2932 908 1889 2931 909 1935 3035 997 1935 3035 997 1889 2931 909 1936 3036 998 1936 3036 998 1889 2931 909 1937 3037 999 1937 3037 999 1889 2931 909 1898 2948 926 1937 3037 999 1898 2948 926 1938 3038 1000 1938 3038 1000 1898 2948 926 1901 2953 932 1938 3038 1000 1901 2953 932 1939 3039 1001 1939 3039 1001 1901 2953 932 1900 2951 929 1900 2951 929 1899 2950 930 1939 3039 1001 1939 3039 1001 1899 2950 930 1940 3040 1002 1899 2950 930 1903 2957 935 1940 3040 1002 1940 3040 1002 1903 2957 935 1941 3041 1003 1903 2957 935 1902 2956 936 1941 3041 1003 1941 3041 1003 1902 2956 936 1942 3042 1004 1902 2956 936 1904 2959 938 1942 3042 1004 1942 3042 1004 1904 2959 938 1943 3043 1005 1904 2959 938 1897 2946 922 1943 3043 1005 1943 3043 1005 1897 2946 922 1944 3044 1006 1944 3044 1006 1897 2946 922 1945 3045 1007 1945 3045 1007 1897 2946 922 1896 2945 923 1945 3045 1007 1896 2945 923 1946 3046 1008 1946 3046 1008 1896 2945 923 1894 2942 918 1946 3046 1008 1894 2942 918 1947 3047 1009 1947 3047 1009 1894 2942 918 1895 2941 919 1947 3047 1009 1895 2941 919 1948 3048 1010 1948 3048 1010 1895 2941 919 1893 2938 916 1948 3048 1010 1893 2938 916 1933 3033 995 1933 3033 995 1893 2938 916 1892 2936 912 1949 3049 1013 1950 3050 1012 1906 2997 967 1906 2997 967 1950 3050 1012 1907 3051 1011 1935 3035 997 1936 3036 998 1949 3049 1013 1949 3049 1013 1936 3036 998 1950 3050 1012 1907 3051 1011 1950 3050 1012 1921 3053 990 1921 3053 990 1950 3050 1012 1951 3052 1014 1950 3050 1012 1936 3036 998 1951 3052 1014 1951 3052 1014 1936 3036 998 1937 3037 999 1921 3053 990 1951 3052 1014 1923 3011 978 1923 3011 978 1951 3052 1014 1952 3054 1015 1951 3052 1014 1937 3037 999 1952 3054 1015 1952 3054 1015 1937 3037 999 1938 3038 1000 1923 3011 978 1952 3054 1015 1924 3012 977 1924 3012 977 1952 3054 1015 1953 3055 1016 1952 3054 1015 1938 3038 1000 1953 3055 1016 1953 3055 1016 1938 3038 1000 1939 3039 1001 1953 3055 1016 1954 3056 1017 1924 3012 977 1924 3012 977 1954 3056 1017 1925 3013 976 1939 3039 1001 1940 3040 1002 1953 3055 1016 1953 3055 1016 1940 3040 1002 1954 3056 1017 1954 3056 1017 1955 3057 1018 1925 3013 976 1925 3013 976 1955 3057 1018 1930 3023 984 1940 3040 1002 1941 3041 1003 1954 3056 1017 1954 3056 1017 1941 3041 1003 1955 3057 1018 1955 3057 1018 1956 3058 1019 1930 3023 984 1930 3023 984 1956 3058 1019 1927 3020 983 1941 3041 1003 1942 3042 1004 1955 3057 1018 1955 3057 1018 1942 3042 1004 1956 3058 1019 1956 3058 1019 1957 3059 1020 1927 3020 983 1927 3020 983 1957 3059 1020 1932 3060 994 1942 3042 1004 1943 3043 1005 1956 3058 1019 1956 3058 1019 1943 3043 1005 1957 3059 1020 1957 3059 1020 1958 3061 1022 1932 3060 994 1932 3060 994 1958 3061 1022 1917 3062 1021 1943 3043 1005 1944 3044 1006 1957 3059 1020 1957 3059 1020 1944 3044 1006 1958 3061 1022 1917 3062 1021 1958 3061 1022 1918 3064 970 1918 3064 970 1958 3061 1022 1959 3063 1023 1958 3061 1022 1944 3044 1006 1959 3063 1023 1959 3063 1023 1944 3044 1006 1945 3045 1007 1918 3065 970 1959 3063 1023 1913 2985 956 1913 2985 956 1959 3063 1023 1960 3066 1024 1959 3063 1023 1945 3045 1007 1960 3066 1024 1960 3066 1024 1945 3045 1007 1946 3046 1008 1913 2985 956 1960 3066 1024 1914 2986 959 1914 2986 959 1960 3066 1024 1961 3067 1025 1960 3066 1024 1946 3046 1008 1961 3067 1025 1961 3067 1025 1946 3046 1008 1947 3047 1009 1914 2986 959 1961 3067 1025 1909 2974 949 1909 2974 949 1961 3067 1025 1962 3068 1026 1961 3067 1025 1947 3047 1009 1962 3068 1026 1962 3068 1026 1947 3047 1009 1948 3048 1010 1909 2974 949 1962 3068 1026 1910 2975 948 1910 2975 948 1962 3068 1026 1963 3069 1027 1962 3068 1026 1948 3048 1010 1963 3069 1027 1963 3069 1027 1948 3048 1010 1933 3033 995 1963 3069 1027 1964 3070 1028 1910 2975 948 1910 2975 948 1964 3070 1028 1911 2976 947 1933 3033 995 1934 3034 996 1963 3069 1027 1963 3069 1027 1934 3034 996 1964 3070 1028 1964 3070 1028 1949 3049 1013 1911 2976 947 1911 2976 947 1949 3049 1013 1906 2997 967 1934 3034 996 1935 3035 997 1964 3070 1028 1964 3070 1028 1935 3035 997 1949 3049 1013 1966 3071 944 1980 3072 1030 1967 3074 943 1967 3074 943 1980 3072 1030 1981 3073 1029 1980 3072 1030 1982 3075 1032 1981 3073 1029 1981 3073 1029 1982 3075 1032 1983 3076 1031 1906 2997 967 1907 3051 1011 1982 3077 1032 1982 3077 1032 1907 3051 1011 1983 3076 1031 1981 3073 1029 1984 3078 1033 1967 3074 943 1967 3074 943 1984 3078 1033 1976 3079 973 1983 3076 1031 1985 3080 1034 1981 3073 1029 1981 3073 1029 1985 3080 1034 1984 3078 1033 1983 3076 1031 1907 3051 1011 1985 3080 1034 1985 3080 1034 1907 3051 1011 1921 3081 990 1984 3083 1033 1986 3084 1035 1976 3082 973 1976 3082 973 1986 3084 1035 1975 3085 972 1985 3086 1034 1987 3087 1036 1984 3083 1033 1984 3083 1033 1987 3087 1036 1986 3084 1035 1921 3029 990 1920 3028 991 1985 3086 1034 1985 3086 1034 1920 3028 991 1987 3087 1036 1986 3084 1035 1988 3088 1037 1975 3085 972 1975 3085 972 1988 3088 1037 1977 3089 980 1987 3087 1036 1989 3090 1038 1986 3084 1035 1986 3084 1035 1989 3090 1038 1988 3088 1037 1920 3028 991 1926 3031 992 1987 3087 1036 1987 3087 1036 1926 3031 992 1989 3090 1038 1988 3088 1037 1990 3091 1039 1977 3089 980 1977 3089 980 1990 3091 1039 1978 3092 989 1989 3090 1038 1991 3093 1040 1988 3088 1037 1988 3088 1037 1991 3093 1040 1990 3091 1039 1926 3031 992 1931 3030 993 1989 3090 1038 1989 3090 1038 1931 3030 993 1991 3093 1040 1990 3091 1039 1992 3094 1041 1978 3092 989 1978 3092 989 1992 3094 1041 1979 3095 988 1991 3093 1040 1993 3096 1042 1990 3091 1039 1990 3091 1039 1993 3096 1042 1992 3094 1041 1931 3030 993 1932 3032 994 1991 3093 1040 1991 3093 1040 1932 3032 994 1993 3097 1042 1992 3094 1041 1994 3098 1043 1979 3095 988 1979 3095 988 1994 3098 1043 1972 3099 965 1993 3100 1042 1995 3101 1044 1992 3094 1041 1992 3094 1041 1995 3101 1044 1994 3098 1043 1932 3102 994 1917 3103 1021 1993 3100 1042 1993 3100 1042 1917 3103 1021 1995 3101 1044 1972 3099 965 1994 3098 1043 1973 3105 964 1973 3105 964 1994 3098 1043 1996 3104 1045 1994 3098 1043 1995 3101 1044 1996 3104 1045 1996 3104 1045 1995 3101 1044 1997 3106 1046 1995 3101 1044 1917 3103 1021 1997 3106 1046 1997 3106 1046 1917 3103 1021 1918 3107 970 1973 3105 964 1996 3104 1045 1974 3109 963 1974 3109 963 1996 3104 1045 1998 3108 1047 1996 3104 1045 1997 3110 1046 1998 3108 1047 1998 3108 1047 1997 3110 1046 1999 3111 1048 1997 3112 1046 1918 3113 970 1999 3111 1048 1999 3111 1048 1918 3113 970 1919 3000 968 1974 3109 963 1998 3108 1047 1969 3115 952 1969 3115 952 1998 3108 1047 2000 3114 1049 1998 3108 1047 1999 3111 1048 2000 3114 1049 2000 3114 1049 1999 3111 1048 2001 3116 1050 1999 3111 1048 1919 3000 968 2001 3116 1050 2001 3116 1050 1919 3000 968 1912 2999 969 1969 3115 952 2000 3114 1049 1965 3118 941 1965 3118 941 2000 3114 1049 2002 3117 1051 2000 3114 1049 2001 3116 1050 2002 3117 1051 2002 3117 1051 2001 3116 1050 2003 3119 1052 2001 3116 1050 1912 2999 969 2003 3119 1052 2003 3119 1052 1912 2999 969 1905 2998 966 1965 3118 941 2002 3117 1051 1966 3121 944 1966 3121 944 2002 3117 1051 1980 3120 1030 2002 3117 1051 2003 3119 1052 1980 3120 1030 1980 3120 1030 2003 3119 1052 1982 3122 1032 2003 3119 1052 1905 2998 966 1982 3123 1032 1982 3123 1032 1905 2998 966 1906 2997 967</p>
+ </triangles>
+ <triangles material="HeadphonesSG3" count="1484">
+ <input semantic="VERTEX" source="#Headphones-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Headphones-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Headphones-headphonesUV" offset="2" set="1"/>
+ <p>604 1278 1053 533 1279 1054 606 1281 1056 606 1281 1056 533 1279 1054 347 1280 1055 606 1281 1056 347 1280 1055 605 1283 1058 605 1283 1058 347 1280 1055 348 1282 1057 605 1283 1058 348 1282 1057 608 1285 1060 608 1285 1060 348 1282 1057 349 1284 1059 610 1286 1061 350 1287 1062 612 1289 1064 612 1289 1064 350 1287 1062 351 1288 1063 612 1289 1064 351 1288 1063 614 1291 1066 614 1291 1066 351 1288 1063 352 1290 1065 614 1291 1066 352 1290 1065 616 1293 1068 616 1293 1068 352 1290 1065 353 1292 1067 353 1292 1067 354 1294 1069 616 1293 1068 616 1293 1068 354 1294 1069 618 1295 1070 354 1294 1069 355 1296 1071 618 1295 1070 618 1295 1070 355 1296 1071 620 1297 1072 533 1279 1054 542 1298 1073 347 1280 1055 347 1280 1055 542 1298 1073 356 1299 1074 347 1280 1055 356 1299 1074 348 1282 1057 348 1282 1057 356 1299 1074 357 1300 1075 348 1282 1057 357 1300 1075 349 1284 1059 349 1284 1059 357 1300 1075 358 1301 1076 350 1287 1062 349 1284 1059 359 1302 1077 359 1302 1077 349 1284 1059 358 1301 1076 350 1287 1062 359 1302 1077 351 1288 1063 351 1288 1063 359 1302 1077 360 1303 1078 351 1288 1063 360 1303 1078 352 1290 1065 352 1290 1065 360 1303 1078 361 1304 1079 352 1290 1065 361 1304 1079 353 1292 1067 353 1292 1067 361 1304 1079 362 1305 1080 362 1305 1080 363 1306 1081 353 1292 1067 353 1292 1067 363 1306 1081 354 1294 1069 363 1306 1081 364 1307 1082 354 1294 1069 354 1294 1069 364 1307 1082 355 1296 1071 542 1298 1073 543 1308 1083 356 1299 1074 356 1299 1074 543 1308 1083 365 1309 1084 356 1299 1074 365 1309 1084 357 1300 1075 357 1300 1075 365 1309 1084 366 1310 1085 357 1300 1075 366 1310 1085 358 1301 1076 358 1301 1076 366 1310 1085 367 1311 1086 358 1301 1076 367 1311 1086 359 1302 1077 359 1302 1077 367 1311 1086 368 1312 1087 359 1302 1077 368 1312 1087 360 1303 1078 360 1303 1078 368 1312 1087 369 1313 1088 360 1303 1078 369 1313 1088 361 1304 1079 361 1304 1079 369 1313 1088 370 1314 1089 361 1304 1079 370 1314 1089 362 1305 1080 362 1305 1080 370 1314 1089 371 1315 1090 371 1315 1090 372 1316 1091 362 1305 1080 362 1305 1080 372 1316 1091 363 1306 1081 372 1316 1091 373 1317 1092 363 1306 1081 363 1306 1081 373 1317 1092 364 1307 1082 543 1308 1083 544 1318 1093 365 1309 1084 365 1309 1084 544 1318 1093 374 1319 1094 365 1309 1084 374 1319 1094 366 1310 1085 366 1310 1085 374 1319 1094 375 1320 1095 366 1310 1085 375 1320 1095 367 1311 1086 367 1311 1086 375 1320 1095 376 1321 1096 367 1311 1086 376 1321 1096 368 1312 1087 368 1312 1087 376 1321 1096 377 1322 1097 368 1312 1087 377 1322 1097 369 1313 1088 369 1313 1088 377 1322 1097 378 1323 1098 369 1313 1088 378 1323 1098 370 1314 1089 370 1314 1089 378 1323 1098 379 1324 1099 370 1314 1089 379 1324 1099 371 1315 1090 371 1315 1090 379 1324 1099 380 1325 1100 380 1325 1100 381 1326 1101 371 1315 1090 371 1315 1090 381 1326 1101 372 1316 1091 382 1327 1102 373 1317 1092 381 1326 1101 381 1326 1101 373 1317 1092 372 1316 1091 544 1318 1093 545 1328 1103 374 1319 1094 374 1319 1094 545 1328 1103 383 1329 1104 374 1319 1094 383 1329 1104 375 1320 1095 375 1320 1095 383 1329 1104 384 1330 1105 375 1320 1095 384 1330 1105 376 1321 1096 376 1321 1096 384 1330 1105 385 1331 1106 376 1321 1096 385 1331 1106 377 1322 1097 377 1322 1097 385 1331 1106 386 1332 1107 377 1322 1097 386 1332 1107 378 1323 1098 378 1323 1098 386 1332 1107 387 1333 1108 378 1323 1098 387 1333 1108 379 1324 1099 379 1324 1099 387 1333 1108 388 1334 1109 379 1324 1099 388 1334 1109 380 1325 1100 380 1325 1100 388 1334 1109 389 1335 1110 389 1335 1110 390 1336 1111 380 1325 1100 380 1325 1100 390 1336 1111 381 1326 1101 390 1336 1111 391 1337 1112 381 1326 1101 381 1326 1101 391 1337 1112 382 1327 1102 410 1338 1113 411 1339 1114 364 1307 1082 364 1307 1082 411 1339 1114 355 1296 1071 412 1340 1115 410 1338 1113 373 1317 1092 373 1317 1092 410 1338 1113 364 1307 1082 409 1342 1117 395 1343 1118 414 1341 1116 414 1341 1116 395 1343 1118 398 1344 1119 549 1345 1120 547 1346 1121 409 1342 1117 409 1342 1117 547 1346 1121 395 1343 1118 411 1339 1114 413 1347 1122 355 1296 1071 355 1296 1071 413 1347 1122 620 1297 1072 428 1349 1124 403 1350 1125 404 1348 1123 404 1348 1123 403 1350 1125 394 1351 1126 405 1353 1128 395 1354 1118 548 1352 1127 548 1352 1127 395 1354 1118 547 1355 1121 406 1357 1130 396 1358 1131 407 1356 1129 407 1356 1129 396 1358 1131 397 1359 1132 408 1360 1133 398 1361 1119 405 1353 1128 405 1353 1128 398 1361 1119 395 1354 1118 407 1356 1129 397 1359 1132 408 1360 1133 408 1360 1133 397 1359 1132 398 1361 1119 404 1348 1123 394 1351 1126 406 1357 1130 406 1357 1130 394 1351 1126 396 1358 1131 392 1362 1134 414 1341 1116 391 1337 1112 391 1337 1112 414 1341 1116 382 1327 1102 414 1341 1116 412 1340 1115 382 1327 1102 382 1327 1102 412 1340 1115 373 1317 1092 393 1363 1135 409 1342 1117 392 1362 1134 392 1362 1134 409 1342 1117 414 1341 1116 409 1342 1117 393 1363 1135 549 1345 1120 549 1345 1120 393 1363 1135 546 1364 1136 411 1339 1114 410 1338 1113 394 1366 1126 394 1366 1126 410 1338 1113 396 1365 1131 410 1338 1113 412 1340 1115 396 1365 1131 396 1365 1131 412 1340 1115 397 1367 1132 414 1341 1116 398 1344 1119 412 1340 1115 412 1340 1115 398 1344 1119 397 1367 1132 413 1347 1122 411 1339 1114 403 1368 1125 403 1368 1125 411 1339 1114 394 1366 1126 418 1369 1137 419 1370 1138 415 1372 1140 415 1372 1140 419 1370 1138 416 1371 1139 415 1372 1140 416 1371 1139 623 1374 1142 623 1374 1142 416 1371 1139 627 1373 1141 419 1370 1138 540 1375 1143 416 1371 1139 416 1371 1139 540 1375 1143 539 1376 1144 416 1371 1139 539 1376 1144 627 1373 1141 627 1373 1141 539 1376 1144 626 1377 1145 415 1372 1140 417 1378 1146 418 1369 1137 418 1369 1137 417 1378 1146 420 1379 1147 413 1347 1122 403 1368 1125 417 1378 1146 417 1378 1146 403 1368 1125 420 1379 1147 417 1378 1146 415 1372 1140 624 1380 1148 624 1380 1148 415 1372 1140 623 1374 1142 620 1297 1072 413 1347 1122 624 1380 1148 624 1380 1148 413 1347 1122 417 1378 1146 427 1381 1149 541 1382 1150 419 1384 1138 419 1384 1138 541 1382 1150 540 1383 1143 425 1385 1151 427 1381 1149 418 1386 1137 418 1386 1137 427 1381 1149 419 1384 1138 426 1387 1152 425 1385 1151 420 1388 1147 420 1388 1147 425 1385 1151 418 1386 1137 534 1389 1153 400 1390 1154 535 1392 1156 535 1392 1156 400 1390 1154 421 1391 1155 401 1393 1157 399 1394 1158 423 1396 1160 423 1396 1160 399 1394 1158 422 1395 1159 400 1390 1154 402 1397 1161 421 1391 1155 421 1391 1155 402 1397 1161 424 1398 1162 402 1397 1161 401 1393 1157 424 1398 1162 424 1398 1162 401 1393 1157 423 1396 1160 538 1400 1164 541 1382 1150 434 1399 1163 434 1399 1163 541 1382 1150 427 1381 1149 432 1401 1165 434 1399 1163 425 1385 1151 425 1385 1151 434 1399 1163 427 1381 1149 433 1402 1166 432 1401 1165 426 1387 1152 426 1387 1152 432 1401 1165 425 1385 1151 428 1349 1124 404 1348 1123 399 1394 1158 399 1394 1158 404 1348 1123 422 1395 1159 428 1404 1124 426 1387 1152 403 1403 1125 403 1403 1125 426 1387 1152 420 1388 1147 406 1357 1130 436 1405 1167 404 1348 1123 404 1348 1123 436 1405 1167 422 1395 1159 429 1407 1169 402 1408 1161 430 1406 1168 430 1406 1168 402 1408 1161 400 1409 1154 430 1406 1168 400 1409 1154 536 1410 1170 536 1410 1170 400 1409 1154 534 1411 1153 431 1412 1171 401 1413 1157 429 1407 1169 429 1407 1169 401 1413 1157 402 1408 1161 426 1387 1152 428 1404 1124 433 1402 1166 433 1402 1166 428 1404 1124 399 1414 1158 430 1406 1168 435 1415 1172 429 1407 1169 429 1407 1169 435 1415 1172 434 1399 1163 537 1416 1173 435 1415 1172 536 1410 1170 536 1410 1170 435 1415 1172 430 1406 1168 432 1401 1165 431 1412 1171 434 1399 1163 434 1399 1163 431 1412 1171 429 1407 1169 432 1401 1165 433 1402 1166 431 1412 1171 433 1402 1166 399 1414 1158 431 1412 1171 431 1412 1171 399 1414 1158 401 1413 1157 537 1416 1173 538 1400 1164 435 1415 1172 435 1415 1172 538 1400 1164 434 1399 1163 408 1360 1133 438 1417 1174 407 1356 1129 407 1356 1129 438 1417 1174 437 1418 1175 437 1418 1175 438 1419 1174 423 1396 1160 423 1396 1160 438 1419 1174 424 1398 1162 405 1353 1128 439 1420 1176 408 1360 1133 408 1360 1133 439 1420 1176 438 1421 1174 439 1422 1176 421 1391 1155 438 1419 1174 438 1419 1174 421 1391 1155 424 1398 1162 548 1352 1127 550 1423 1177 405 1353 1128 405 1353 1128 550 1423 1177 439 1420 1176 439 1422 1176 550 1424 1177 421 1391 1155 421 1391 1155 550 1424 1177 535 1392 1156 407 1356 1129 437 1418 1175 406 1357 1130 406 1357 1130 437 1418 1175 436 1405 1167 437 1418 1175 423 1396 1160 436 1405 1167 436 1405 1167 423 1396 1160 422 1395 1159 604 1278 1053 603 1425 1178 533 1279 1054 533 1279 1054 603 1425 1178 440 1426 1179 603 1425 1178 602 1427 1180 440 1426 1179 440 1426 1179 602 1427 1180 441 1428 1181 602 1427 1180 607 1429 1182 441 1428 1181 441 1428 1181 607 1429 1182 442 1430 1183 607 1429 1182 609 1431 1184 442 1430 1183 442 1430 1183 609 1431 1184 443 1432 1185 609 1431 1184 611 1433 1186 443 1432 1185 443 1432 1185 611 1433 1186 444 1434 1187 611 1433 1186 613 1435 1188 444 1434 1187 444 1434 1187 613 1435 1188 445 1436 1189 613 1435 1188 615 1437 1190 445 1436 1189 445 1436 1189 615 1437 1190 446 1438 1191 446 1438 1191 615 1437 1190 447 1440 1193 447 1440 1193 615 1437 1190 617 1439 1192 447 1440 1193 617 1439 1192 448 1442 1195 448 1442 1195 617 1439 1192 619 1441 1194 533 1279 1054 440 1426 1179 542 1298 1073 542 1298 1073 440 1426 1179 449 1443 1196 440 1426 1179 441 1428 1181 449 1443 1196 449 1443 1196 441 1428 1181 450 1444 1197 441 1428 1181 442 1430 1183 450 1444 1197 450 1444 1197 442 1430 1183 451 1445 1198 442 1430 1183 443 1432 1185 451 1445 1198 451 1445 1198 443 1432 1185 452 1446 1199 443 1432 1185 444 1434 1187 452 1446 1199 452 1446 1199 444 1434 1187 453 1447 1200 444 1434 1187 445 1436 1189 453 1447 1200 453 1447 1200 445 1436 1189 454 1448 1201 445 1436 1189 446 1438 1191 454 1448 1201 454 1448 1201 446 1438 1191 455 1449 1202 455 1449 1202 446 1438 1191 456 1450 1203 456 1450 1203 446 1438 1191 447 1440 1193 456 1450 1203 447 1440 1193 457 1451 1204 457 1451 1204 447 1440 1193 448 1442 1195 542 1298 1073 449 1443 1196 543 1308 1083 543 1308 1083 449 1443 1196 458 1452 1205 449 1443 1196 450 1444 1197 458 1452 1205 458 1452 1205 450 1444 1197 459 1453 1206 450 1444 1197 451 1445 1198 459 1453 1206 459 1453 1206 451 1445 1198 460 1454 1207 451 1445 1198 452 1446 1199 460 1454 1207 460 1454 1207 452 1446 1199 461 1455 1208 452 1446 1199 453 1447 1200 461 1455 1208 461 1455 1208 453 1447 1200 462 1456 1209 453 1447 1200 454 1448 1201 462 1456 1209 462 1456 1209 454 1448 1201 463 1457 1210 454 1448 1201 455 1449 1202 463 1457 1210 463 1457 1210 455 1449 1202 464 1458 1211 464 1458 1211 455 1449 1202 465 1459 1212 465 1459 1212 455 1449 1202 456 1450 1203 465 1459 1212 456 1450 1203 466 1460 1213 466 1460 1213 456 1450 1203 457 1451 1204 543 1308 1083 458 1452 1205 544 1318 1093 544 1318 1093 458 1452 1205 467 1461 1214 458 1452 1205 459 1453 1206 467 1461 1214 467 1461 1214 459 1453 1206 468 1462 1215 459 1453 1206 460 1454 1207 468 1462 1215 468 1462 1215 460 1454 1207 469 1463 1216 460 1454 1207 461 1455 1208 469 1463 1216 469 1463 1216 461 1455 1208 470 1464 1217 461 1455 1208 462 1456 1209 470 1464 1217 470 1464 1217 462 1456 1209 471 1465 1218 462 1456 1209 463 1457 1210 471 1465 1218 471 1465 1218 463 1457 1210 472 1466 1219 463 1457 1210 464 1458 1211 472 1466 1219 472 1466 1219 464 1458 1211 473 1467 1220 473 1467 1220 464 1458 1211 474 1468 1221 474 1468 1221 464 1458 1211 465 1459 1212 475 1469 1222 474 1468 1221 466 1460 1213 466 1460 1213 474 1468 1221 465 1459 1212 544 1318 1093 467 1461 1214 545 1328 1103 545 1328 1103 467 1461 1214 476 1470 1223 467 1461 1214 468 1462 1215 476 1470 1223 476 1470 1223 468 1462 1215 477 1471 1224 468 1462 1215 469 1463 1216 477 1471 1224 477 1471 1224 469 1463 1216 478 1472 1225 469 1463 1216 470 1464 1217 478 1472 1225 478 1472 1225 470 1464 1217 479 1473 1226 470 1464 1217 471 1465 1218 479 1473 1226 479 1473 1226 471 1465 1218 480 1474 1227 471 1465 1218 472 1466 1219 480 1474 1227 480 1474 1227 472 1466 1219 481 1475 1228 472 1466 1219 473 1467 1220 481 1475 1228 481 1475 1228 473 1467 1220 482 1476 1229 482 1476 1229 473 1467 1220 483 1477 1230 483 1477 1230 473 1467 1220 474 1468 1221 483 1477 1230 474 1468 1221 484 1478 1231 484 1478 1231 474 1468 1221 475 1469 1222 503 1479 1232 457 1451 1204 504 1480 1233 504 1480 1233 457 1451 1204 448 1442 1195 505 1481 1234 466 1460 1213 503 1479 1232 503 1479 1232 466 1460 1213 457 1451 1204 491 1483 1236 488 1484 1237 507 1482 1235 507 1482 1235 488 1484 1237 502 1485 1238 488 1484 1237 547 1346 1121 502 1485 1238 502 1485 1238 547 1346 1121 549 1345 1120 619 1441 1194 506 1486 1239 448 1442 1195 448 1442 1195 506 1486 1239 504 1480 1233 487 1488 1241 496 1489 1242 497 1487 1240 497 1487 1240 496 1489 1242 521 1490 1243 547 1355 1121 488 1491 1237 548 1352 1127 548 1352 1127 488 1491 1237 498 1492 1244 490 1494 1246 489 1495 1247 500 1493 1245 500 1493 1245 489 1495 1247 499 1496 1248 488 1491 1237 491 1497 1236 498 1492 1244 498 1492 1244 491 1497 1236 501 1498 1249 491 1497 1236 490 1494 1246 501 1498 1249 501 1498 1249 490 1494 1246 500 1493 1245 489 1495 1247 487 1488 1241 499 1496 1248 499 1496 1248 487 1488 1241 497 1487 1240 475 1469 1222 507 1482 1235 484 1478 1231 484 1478 1231 507 1482 1235 485 1499 1250 466 1460 1213 505 1481 1234 475 1469 1222 475 1469 1222 505 1481 1234 507 1482 1235 507 1482 1235 502 1485 1238 485 1499 1250 485 1499 1250 502 1485 1238 486 1500 1251 546 1364 1136 486 1500 1251 549 1345 1120 549 1345 1120 486 1500 1251 502 1485 1238 504 1480 1233 487 1501 1241 503 1479 1232 503 1479 1232 487 1501 1241 489 1502 1247 503 1479 1232 489 1502 1247 505 1481 1234 505 1481 1234 489 1502 1247 490 1503 1246 490 1503 1246 491 1483 1236 505 1481 1234 505 1481 1234 491 1483 1236 507 1482 1235 506 1486 1239 496 1504 1242 504 1480 1233 504 1480 1233 496 1504 1242 487 1501 1241 511 1505 1252 508 1506 1253 512 1508 1255 512 1508 1255 508 1506 1253 509 1507 1254 508 1506 1253 622 1509 1256 509 1507 1254 509 1507 1254 622 1509 1256 625 1510 1257 512 1508 1255 509 1507 1254 540 1375 1143 540 1375 1143 509 1507 1254 539 1376 1144 509 1507 1254 625 1510 1257 539 1376 1144 539 1376 1144 625 1510 1257 626 1377 1145 508 1506 1253 511 1505 1252 510 1512 1259 510 1512 1259 511 1505 1252 513 1511 1258 513 1511 1258 496 1504 1242 510 1512 1259 510 1512 1259 496 1504 1242 506 1486 1239 622 1509 1256 508 1506 1253 621 1513 1260 621 1513 1260 508 1506 1253 510 1512 1259 619 1441 1194 621 1513 1260 506 1486 1239 506 1486 1239 621 1513 1260 510 1512 1259 520 1514 1261 512 1515 1255 541 1382 1150 541 1382 1150 512 1515 1255 540 1383 1143 518 1516 1262 511 1517 1252 520 1514 1261 520 1514 1261 511 1517 1252 512 1515 1255 519 1518 1263 513 1519 1258 518 1516 1262 518 1516 1262 513 1519 1258 511 1517 1252 534 1389 1153 535 1392 1156 493 1521 1265 493 1521 1265 535 1392 1156 514 1520 1264 494 1522 1266 516 1523 1267 492 1525 1269 492 1525 1269 516 1523 1267 515 1524 1268 493 1521 1265 514 1520 1264 495 1527 1271 495 1527 1271 514 1520 1264 517 1526 1270 495 1527 1271 517 1526 1270 494 1522 1266 494 1522 1266 517 1526 1270 516 1523 1267 520 1514 1261 541 1382 1150 527 1528 1272 527 1528 1272 541 1382 1150 538 1400 1164 525 1529 1273 518 1516 1262 527 1528 1272 527 1528 1272 518 1516 1262 520 1514 1261 526 1530 1274 519 1518 1263 525 1529 1273 525 1529 1273 519 1518 1263 518 1516 1262 521 1490 1243 492 1525 1269 497 1487 1240 497 1487 1240 492 1525 1269 515 1524 1268 513 1519 1258 519 1518 1263 496 1531 1242 496 1531 1242 519 1518 1263 521 1532 1243 515 1524 1268 529 1533 1275 497 1487 1240 497 1487 1240 529 1533 1275 499 1496 1248 493 1535 1265 495 1536 1271 523 1534 1276 523 1534 1276 495 1536 1271 522 1537 1277 534 1411 1153 493 1535 1265 536 1410 1170 536 1410 1170 493 1535 1265 523 1534 1276 495 1536 1271 494 1538 1266 522 1537 1277 522 1537 1277 494 1538 1266 524 1539 1278 492 1540 1269 521 1532 1243 526 1530 1274 526 1530 1274 521 1532 1243 519 1518 1263 523 1534 1276 522 1537 1277 528 1541 1279 528 1541 1279 522 1537 1277 527 1528 1272 537 1416 1173 536 1410 1170 528 1541 1279 528 1541 1279 536 1410 1170 523 1534 1276 522 1537 1277 524 1539 1278 527 1528 1272 527 1528 1272 524 1539 1278 525 1529 1273 525 1529 1273 524 1539 1278 526 1530 1274 526 1530 1274 524 1539 1278 492 1540 1269 492 1540 1269 524 1539 1278 494 1538 1266 527 1528 1272 538 1400 1164 528 1541 1279 528 1541 1279 538 1400 1164 537 1416 1173 530 1542 1280 531 1543 1281 500 1493 1245 500 1493 1245 531 1543 1281 501 1498 1249 530 1542 1280 516 1523 1267 531 1544 1281 531 1544 1281 516 1523 1267 517 1526 1270 531 1545 1281 532 1546 1282 501 1498 1249 501 1498 1249 532 1546 1282 498 1492 1244 517 1526 1270 514 1520 1264 531 1544 1281 531 1544 1281 514 1520 1264 532 1547 1282 532 1546 1282 550 1423 1177 498 1492 1244 498 1492 1244 550 1423 1177 548 1352 1127 532 1547 1282 514 1520 1264 550 1424 1177 550 1424 1177 514 1520 1264 535 1392 1156 529 1533 1275 530 1542 1280 499 1496 1248 499 1496 1248 530 1542 1280 500 1493 1245 515 1524 1268 516 1523 1267 529 1533 1275 529 1533 1275 516 1523 1267 530 1542 1280 481 1475 1228 551 1548 1283 480 1474 1227 480 1474 1227 551 1548 1283 552 1549 1284 480 1474 1227 552 1549 1284 479 1473 1226 479 1473 1226 552 1549 1284 553 1550 1285 479 1473 1226 553 1550 1285 478 1472 1225 478 1472 1225 553 1550 1285 554 1551 1286 478 1472 1225 554 1551 1286 477 1471 1224 477 1471 1224 554 1551 1286 555 1552 1287 477 1471 1224 555 1552 1287 476 1470 1223 476 1470 1223 555 1552 1287 556 1553 1288 476 1470 1223 556 1553 1288 545 1328 1103 545 1328 1103 556 1553 1288 557 1554 1289 545 1328 1103 557 1554 1289 383 1329 1104 383 1329 1104 557 1554 1289 558 1555 1290 383 1329 1104 558 1555 1290 384 1330 1105 384 1330 1105 558 1555 1290 559 1556 1291 384 1330 1105 559 1556 1291 385 1331 1106 385 1331 1106 559 1556 1291 560 1557 1292 385 1331 1106 560 1557 1292 386 1332 1107 386 1332 1107 560 1557 1292 561 1558 1293 386 1332 1107 561 1558 1293 387 1333 1108 387 1333 1108 561 1558 1293 562 1559 1294 387 1333 1108 562 1559 1294 388 1334 1109 388 1334 1109 562 1559 1294 563 1560 1295 388 1334 1109 563 1560 1295 389 1335 1110 389 1335 1110 563 1560 1295 564 1561 1296 389 1335 1110 564 1561 1296 390 1336 1111 390 1336 1111 564 1561 1296 565 1562 1297 390 1336 1111 565 1562 1297 391 1337 1112 391 1337 1112 565 1562 1297 566 1563 1298 391 1337 1112 566 1563 1298 392 1362 1134 392 1362 1134 566 1563 1298 567 1564 1299 392 1362 1134 567 1564 1299 393 1363 1135 393 1363 1135 567 1564 1299 568 1565 1300 393 1363 1135 568 1565 1300 546 1364 1136 546 1364 1136 568 1565 1300 569 1566 1301 546 1364 1136 569 1566 1301 486 1500 1251 486 1500 1251 569 1566 1301 570 1567 1302 486 1500 1251 570 1567 1302 485 1499 1250 485 1499 1250 570 1567 1302 571 1568 1303 485 1499 1250 571 1568 1303 484 1478 1231 484 1478 1231 571 1568 1303 572 1569 1304 484 1478 1231 572 1569 1304 483 1477 1230 483 1477 1230 572 1569 1304 573 1570 1305 483 1477 1230 573 1570 1305 482 1476 1229 482 1476 1229 573 1570 1305 574 1571 1306 482 1476 1229 574 1571 1306 481 1475 1228 481 1475 1228 574 1571 1306 551 1548 1283 551 1548 1283 575 1572 1307 552 1549 1284 552 1549 1284 575 1572 1307 553 1550 1285 553 1550 1285 575 1572 1307 554 1551 1286 554 1551 1286 575 1572 1307 555 1552 1287 555 1552 1287 575 1572 1307 556 1553 1288 556 1553 1288 575 1572 1307 557 1554 1289 557 1554 1289 575 1572 1307 558 1555 1290 558 1555 1290 575 1572 1307 559 1556 1291 559 1556 1291 575 1572 1307 560 1557 1292 560 1557 1292 575 1572 1307 561 1558 1293 561 1558 1293 575 1572 1307 562 1559 1294 562 1559 1294 575 1572 1307 563 1560 1295 563 1560 1295 575 1572 1307 564 1561 1296 564 1561 1296 575 1572 1307 565 1562 1297 565 1562 1297 575 1572 1307 566 1563 1298 566 1563 1298 575 1572 1307 567 1564 1299 567 1564 1299 575 1572 1307 568 1565 1300 568 1565 1300 575 1572 1307 569 1566 1301 569 1566 1301 575 1572 1307 570 1567 1302 570 1567 1302 575 1572 1307 571 1568 1303 571 1568 1303 575 1572 1307 572 1569 1304 572 1569 1304 575 1572 1307 573 1570 1305 573 1570 1305 575 1572 1307 574 1571 1306 574 1571 1306 575 1572 1307 551 1548 1283 580 1574 1308 579 1575 1309 627 1573 1141 627 1573 1141 579 1575 1309 623 1576 1142 579 1575 1309 576 1577 1310 623 1576 1142 623 1576 1142 576 1577 1310 624 1380 1148 624 1380 1148 576 1577 1310 620 1297 1072 620 1297 1072 576 1577 1310 577 1578 1311 620 1297 1072 577 1578 1311 618 1580 1070 618 1580 1070 577 1578 1311 578 1579 1312 618 1581 1070 578 1582 1312 616 1584 1068 616 1584 1068 578 1582 1312 601 1583 1313 616 1584 1068 601 1583 1313 614 1586 1066 614 1586 1066 601 1583 1313 600 1585 1314 614 1586 1066 600 1585 1314 612 1588 1064 612 1588 1064 600 1585 1314 599 1587 1315 612 1588 1064 599 1587 1315 610 1590 1061 610 1590 1061 599 1587 1315 598 1589 1316 610 1590 1061 598 1589 1316 608 1592 1060 608 1592 1060 598 1589 1316 597 1591 1317 608 1592 1060 597 1591 1317 605 1594 1058 605 1594 1058 597 1591 1317 596 1593 1318 605 1594 1058 596 1593 1318 606 1596 1056 606 1596 1056 596 1593 1318 595 1595 1319 606 1596 1056 595 1595 1319 604 1598 1053 604 1598 1053 595 1595 1319 594 1597 1320 604 1598 1053 594 1597 1320 603 1600 1178 603 1600 1178 594 1597 1320 593 1599 1321 603 1600 1178 593 1599 1321 602 1602 1180 602 1602 1180 593 1599 1321 592 1601 1322 602 1602 1180 592 1601 1322 607 1604 1182 607 1604 1182 592 1601 1322 591 1603 1323 607 1604 1182 591 1603 1323 609 1606 1184 609 1606 1184 591 1603 1323 590 1605 1324 609 1606 1184 590 1605 1324 611 1608 1186 611 1608 1186 590 1605 1324 589 1607 1325 611 1608 1186 589 1607 1325 613 1610 1188 613 1610 1188 589 1607 1325 588 1609 1326 613 1610 1188 588 1609 1326 615 1612 1190 615 1612 1190 588 1609 1326 587 1611 1327 587 1611 1327 586 1613 1328 615 1612 1190 615 1612 1190 586 1613 1328 617 1614 1192 586 1613 1328 585 1615 1329 617 1614 1192 617 1614 1192 585 1615 1329 619 1616 1194 585 1615 1329 584 1617 1330 619 1616 1194 619 1616 1194 584 1617 1330 621 1513 1260 621 1513 1260 584 1617 1330 622 1509 1256 622 1509 1256 584 1617 1330 583 1618 1331 622 1509 1256 583 1618 1331 625 1620 1257 625 1620 1257 583 1618 1331 582 1619 1332 625 1621 1257 582 1622 1332 626 1624 1145 626 1624 1145 582 1622 1332 581 1623 1333 581 1623 1333 580 1574 1308 626 1624 1145 626 1624 1145 580 1574 1308 627 1573 1141 349 1284 1059 350 1287 1062 608 1285 1060 608 1285 1060 350 1287 1062 610 1286 1061 600 1625 1314 601 1626 1313 652 1628 1335 652 1628 1335 601 1626 1313 653 1627 1334 578 1629 1312 630 1630 1336 601 1626 1313 601 1626 1313 630 1630 1336 653 1627 1334 577 1631 1311 629 1632 1337 578 1629 1312 578 1629 1312 629 1632 1337 630 1630 1336 576 1633 1310 628 1634 1338 577 1631 1311 577 1631 1311 628 1634 1338 629 1632 1337 576 1633 1310 579 1635 1309 628 1634 1338 628 1634 1338 579 1635 1309 631 1636 1339 579 1635 1309 580 1637 1308 631 1636 1339 631 1636 1339 580 1637 1308 632 1638 1340 580 1637 1308 581 1639 1333 632 1638 1340 632 1638 1340 581 1639 1333 633 1640 1341 582 1641 1332 634 1642 1342 581 1639 1333 581 1639 1333 634 1642 1342 633 1640 1341 583 1643 1331 635 1644 1343 582 1641 1332 582 1641 1332 635 1644 1343 634 1642 1342 584 1645 1330 636 1646 1344 583 1643 1331 583 1643 1331 636 1646 1344 635 1644 1343 584 1645 1330 585 1647 1329 636 1646 1344 636 1646 1344 585 1647 1329 637 1648 1345 585 1647 1329 586 1649 1328 637 1648 1345 637 1648 1345 586 1649 1328 638 1650 1346 586 1649 1328 587 1651 1327 638 1650 1346 638 1650 1346 587 1651 1327 639 1652 1347 587 1651 1327 588 1653 1326 639 1652 1347 639 1652 1347 588 1653 1326 640 1654 1348 588 1653 1326 589 1655 1325 640 1654 1348 640 1654 1348 589 1655 1325 641 1656 1349 589 1655 1325 590 1657 1324 641 1656 1349 641 1656 1349 590 1657 1324 642 1658 1350 590 1657 1324 591 1659 1323 642 1658 1350 642 1658 1350 591 1659 1323 643 1660 1351 591 1659 1323 592 1661 1322 643 1660 1351 643 1660 1351 592 1661 1322 644 1662 1352 592 1661 1322 593 1663 1321 644 1662 1352 644 1662 1352 593 1663 1321 645 1664 1353 593 1663 1321 594 1665 1320 645 1664 1353 645 1664 1353 594 1665 1320 646 1666 1354 594 1665 1320 595 1667 1319 646 1666 1354 646 1666 1354 595 1667 1319 647 1668 1355 595 1667 1319 596 1669 1318 647 1668 1355 647 1668 1355 596 1669 1318 648 1670 1356 596 1669 1318 597 1671 1317 648 1670 1356 648 1670 1356 597 1671 1317 649 1672 1357 597 1671 1317 598 1673 1316 649 1672 1357 649 1672 1357 598 1673 1316 650 1674 1358 598 1673 1316 599 1675 1315 650 1674 1358 650 1674 1358 599 1675 1315 651 1676 1359 599 1675 1315 600 1625 1314 651 1676 1359 651 1676 1359 600 1625 1314 652 1628 1335 639 1652 1347 640 1654 1348 665 1678 1361 665 1678 1361 640 1654 1348 666 1677 1360 640 1654 1348 641 1656 1349 666 1677 1360 666 1677 1360 641 1656 1349 667 1679 1362 641 1656 1349 642 1658 1350 667 1679 1362 667 1679 1362 642 1658 1350 668 1680 1363 642 1658 1350 643 1660 1351 668 1680 1363 668 1680 1363 643 1660 1351 669 1681 1364 643 1660 1351 644 1662 1352 669 1681 1364 669 1681 1364 644 1662 1352 670 1682 1365 644 1662 1352 645 1664 1353 670 1682 1365 670 1682 1365 645 1664 1353 671 1683 1366 645 1664 1353 646 1666 1354 671 1683 1366 671 1683 1366 646 1666 1354 672 1684 1367 646 1666 1354 647 1668 1355 672 1684 1367 672 1684 1367 647 1668 1355 673 1685 1368 647 1668 1355 648 1670 1356 673 1685 1368 673 1685 1368 648 1670 1356 674 1686 1369 648 1670 1356 649 1672 1357 674 1686 1369 674 1686 1369 649 1672 1357 675 1687 1370 649 1672 1357 650 1674 1358 675 1687 1370 675 1687 1370 650 1674 1358 676 1688 1371 650 1674 1358 651 1676 1359 676 1688 1371 676 1688 1371 651 1676 1359 677 1689 1372 651 1676 1359 652 1628 1335 677 1689 1372 677 1689 1372 652 1628 1335 678 1690 1373 652 1628 1335 653 1627 1334 678 1690 1373 678 1690 1373 653 1627 1334 679 1691 1374 630 1630 1336 656 1692 1375 653 1627 1334 653 1627 1334 656 1692 1375 679 1691 1374 629 1632 1337 655 1693 1376 630 1630 1336 630 1630 1336 655 1693 1376 656 1692 1375 628 1634 1338 654 1694 1377 629 1632 1337 629 1632 1337 654 1694 1377 655 1693 1376 628 1634 1338 631 1636 1339 654 1694 1377 654 1694 1377 631 1636 1339 657 1695 1378 631 1636 1339 632 1638 1340 657 1695 1378 657 1695 1378 632 1638 1340 658 1696 1379 632 1638 1340 633 1640 1341 658 1696 1379 658 1696 1379 633 1640 1341 659 1697 1380 633 1640 1341 634 1642 1342 659 1697 1380 659 1697 1380 634 1642 1342 660 1698 1381 635 1644 1343 661 1699 1382 634 1642 1342 634 1642 1342 661 1699 1382 660 1698 1381 636 1646 1344 662 1700 1383 635 1644 1343 635 1644 1343 662 1700 1383 661 1699 1382 636 1646 1344 637 1648 1345 662 1700 1383 662 1700 1383 637 1648 1345 663 1701 1384 637 1648 1345 638 1650 1346 663 1701 1384 663 1701 1384 638 1650 1346 664 1702 1385 638 1650 1346 639 1652 1347 664 1702 1385 664 1702 1385 639 1652 1347 665 1678 1361 655 1693 1376 654 1694 1377 681 1704 1387 681 1704 1387 654 1694 1377 680 1703 1386 657 1695 1378 683 1705 1388 654 1694 1377 654 1694 1377 683 1705 1388 680 1703 1386 657 1695 1378 658 1696 1379 683 1705 1388 683 1705 1388 658 1696 1379 684 1706 1389 658 1696 1379 659 1697 1380 684 1706 1389 684 1706 1389 659 1697 1380 685 1707 1390 659 1697 1380 660 1698 1381 685 1707 1390 685 1707 1390 660 1698 1381 686 1708 1391 660 1698 1381 661 1699 1382 686 1708 1391 686 1708 1391 661 1699 1382 687 1709 1392 661 1699 1382 662 1700 1383 687 1709 1392 687 1709 1392 662 1700 1383 688 1710 1393 663 1701 1384 689 1711 1394 662 1700 1383 662 1700 1383 689 1711 1394 688 1710 1393 663 1701 1384 664 1702 1385 689 1711 1394 689 1711 1394 664 1702 1385 690 1712 1395 664 1702 1385 665 1678 1361 690 1712 1395 690 1712 1395 665 1678 1361 691 1713 1396 665 1678 1361 666 1677 1360 691 1713 1396 691 1713 1396 666 1677 1360 692 1714 1397 666 1677 1360 667 1679 1362 692 1714 1397 692 1714 1397 667 1679 1362 693 1715 1398 667 1679 1362 668 1680 1363 693 1715 1398 693 1715 1398 668 1680 1363 694 1716 1399 668 1680 1363 669 1681 1364 694 1716 1399 694 1716 1399 669 1681 1364 695 1717 1400 669 1681 1364 670 1682 1365 695 1717 1400 695 1717 1400 670 1682 1365 696 1718 1401 670 1682 1365 671 1683 1366 696 1718 1401 696 1718 1401 671 1683 1366 697 1719 1402 671 1683 1366 672 1684 1367 697 1719 1402 697 1719 1402 672 1684 1367 698 1720 1403 672 1684 1367 673 1685 1368 698 1720 1403 698 1720 1403 673 1685 1368 699 1721 1404 673 1685 1368 674 1686 1369 699 1721 1404 699 1721 1404 674 1686 1369 700 1722 1405 674 1686 1369 675 1687 1370 700 1722 1405 700 1722 1405 675 1687 1370 701 1723 1406 675 1687 1370 676 1688 1371 701 1723 1406 701 1723 1406 676 1688 1371 702 1724 1407 676 1688 1371 677 1689 1372 702 1724 1407 702 1724 1407 677 1689 1372 703 1725 1408 677 1689 1372 678 1690 1373 703 1725 1408 703 1725 1408 678 1690 1373 704 1726 1409 678 1690 1373 679 1691 1374 704 1726 1409 704 1726 1409 679 1691 1374 705 1727 1410 679 1691 1374 656 1692 1375 705 1727 1410 705 1727 1410 656 1692 1375 682 1728 1411 656 1692 1375 655 1693 1376 682 1728 1411 682 1728 1411 655 1693 1376 681 1704 1387 685 1707 1390 711 1729 1412 684 1706 1389 684 1706 1389 711 1729 1412 710 1730 1413 685 1707 1390 686 1708 1391 711 1729 1412 711 1729 1412 686 1708 1391 712 1731 1414 686 1708 1391 687 1709 1392 712 1731 1414 712 1731 1414 687 1709 1392 713 1732 1415 687 1709 1392 688 1710 1393 713 1732 1415 713 1732 1415 688 1710 1393 714 1733 1416 689 1711 1394 715 1734 1417 688 1710 1393 688 1710 1393 715 1734 1417 714 1733 1416 690 1712 1395 716 1735 1418 689 1711 1394 689 1711 1394 716 1735 1418 715 1734 1417 691 1713 1396 717 1736 1419 690 1712 1395 690 1712 1395 717 1736 1419 716 1735 1418 691 1713 1396 692 1714 1397 717 1736 1419 717 1736 1419 692 1714 1397 718 1737 1420 692 1714 1397 693 1715 1398 718 1737 1420 718 1737 1420 693 1715 1398 719 1738 1421 693 1715 1398 694 1716 1399 719 1738 1421 719 1738 1421 694 1716 1399 720 1739 1422 694 1716 1399 695 1717 1400 720 1739 1422 720 1739 1422 695 1717 1400 721 1740 1423 695 1717 1400 696 1718 1401 721 1740 1423 721 1740 1423 696 1718 1401 722 1741 1424 696 1718 1401 697 1719 1402 722 1741 1424 722 1741 1424 697 1719 1402 723 1742 1425 697 1719 1402 698 1720 1403 723 1742 1425 723 1742 1425 698 1720 1403 724 1743 1426 698 1720 1403 699 1721 1404 724 1743 1426 724 1743 1426 699 1721 1404 725 1744 1427 699 1721 1404 700 1722 1405 725 1744 1427 725 1744 1427 700 1722 1405 726 1745 1428 700 1722 1405 701 1723 1406 726 1745 1428 726 1745 1428 701 1723 1406 727 1746 1429 701 1723 1406 702 1724 1407 727 1746 1429 727 1746 1429 702 1724 1407 728 1747 1430 702 1724 1407 703 1725 1408 728 1747 1430 728 1747 1430 703 1725 1408 729 1748 1431 703 1725 1408 704 1726 1409 729 1748 1431 729 1748 1431 704 1726 1409 730 1749 1432 704 1726 1409 705 1727 1410 730 1749 1432 730 1749 1432 705 1727 1410 731 1750 1433 705 1727 1410 682 1728 1411 731 1750 1433 731 1750 1433 682 1728 1411 708 1751 1434 682 1728 1411 681 1704 1387 708 1751 1434 708 1751 1434 681 1704 1387 707 1752 1435 681 1704 1387 680 1703 1386 707 1752 1435 707 1752 1435 680 1703 1386 706 1753 1436 683 1705 1388 709 1754 1437 680 1703 1386 680 1703 1386 709 1754 1437 706 1753 1436 684 1706 1389 710 1730 1413 683 1705 1388 683 1705 1388 710 1730 1413 709 1754 1437 2261 3124 1053 2263 3125 1056 2190 3127 1054 2190 3127 1054 2263 3125 1056 2004 3126 1055 2263 3125 1056 2262 3128 1058 2004 3126 1055 2004 3126 1055 2262 3128 1058 2005 3129 1057 2262 3128 1058 2265 3130 1060 2005 3129 1057 2005 3129 1057 2265 3130 1060 2006 3131 1059 2267 3132 1061 2269 3133 1064 2007 3135 1062 2007 3135 1062 2269 3133 1064 2008 3134 1063 2269 3133 1064 2271 3136 1066 2008 3134 1063 2008 3134 1063 2271 3136 1066 2009 3137 1065 2271 3136 1066 2273 3138 1068 2009 3137 1065 2009 3137 1065 2273 3138 1068 2010 3139 1067 2010 3139 1067 2273 3138 1068 2011 3141 1069 2011 3141 1069 2273 3138 1068 2275 3140 1070 2011 3141 1069 2275 3140 1070 2012 3143 1071 2012 3143 1071 2275 3140 1070 2277 3142 1072 2190 3127 1054 2004 3126 1055 2199 3145 1073 2199 3145 1073 2004 3126 1055 2013 3144 1074 2004 3126 1055 2005 3129 1057 2013 3144 1074 2013 3144 1074 2005 3129 1057 2014 3146 1075 2005 3129 1057 2006 3131 1059 2014 3146 1075 2014 3146 1075 2006 3131 1059 2015 3147 1076 2007 3135 1062 2016 3148 1077 2006 3131 1059 2006 3131 1059 2016 3148 1077 2015 3147 1076 2007 3135 1062 2008 3134 1063 2016 3148 1077 2016 3148 1077 2008 3134 1063 2017 3149 1078 2008 3134 1063 2009 3137 1065 2017 3149 1078 2017 3149 1078 2009 3137 1065 2018 3150 1079 2009 3137 1065 2010 3139 1067 2018 3150 1079 2018 3150 1079 2010 3139 1067 2019 3151 1080 2019 3151 1080 2010 3139 1067 2020 3152 1081 2020 3152 1081 2010 3139 1067 2011 3141 1069 2020 3152 1081 2011 3141 1069 2021 3153 1082 2021 3153 1082 2011 3141 1069 2012 3143 1071 2199 3145 1073 2013 3144 1074 2200 3155 1083 2200 3155 1083 2013 3144 1074 2022 3154 1084 2013 3144 1074 2014 3146 1075 2022 3154 1084 2022 3154 1084 2014 3146 1075 2023 3156 1085 2014 3146 1075 2015 3147 1076 2023 3156 1085 2023 3156 1085 2015 3147 1076 2024 3157 1086 2015 3147 1076 2016 3148 1077 2024 3157 1086 2024 3157 1086 2016 3148 1077 2025 3158 1087 2016 3148 1077 2017 3149 1078 2025 3158 1087 2025 3158 1087 2017 3149 1078 2026 3159 1088 2017 3149 1078 2018 3150 1079 2026 3159 1088 2026 3159 1088 2018 3150 1079 2027 3160 1089 2018 3150 1079 2019 3151 1080 2027 3160 1089 2027 3160 1089 2019 3151 1080 2028 3161 1090 2028 3161 1090 2019 3151 1080 2029 3162 1091 2029 3162 1091 2019 3151 1080 2020 3152 1081 2029 3162 1091 2020 3152 1081 2030 3163 1092 2030 3163 1092 2020 3152 1081 2021 3153 1082 2200 3155 1083 2022 3154 1084 2201 3165 1093 2201 3165 1093 2022 3154 1084 2031 3164 1094 2022 3154 1084 2023 3156 1085 2031 3164 1094 2031 3164 1094 2023 3156 1085 2032 3166 1095 2023 3156 1085 2024 3157 1086 2032 3166 1095 2032 3166 1095 2024 3157 1086 2033 3167 1096 2024 3157 1086 2025 3158 1087 2033 3167 1096 2033 3167 1096 2025 3158 1087 2034 3168 1097 2025 3158 1087 2026 3159 1088 2034 3168 1097 2034 3168 1097 2026 3159 1088 2035 3169 1098 2026 3159 1088 2027 3160 1089 2035 3169 1098 2035 3169 1098 2027 3160 1089 2036 3170 1099 2027 3160 1089 2028 3161 1090 2036 3170 1099 2036 3170 1099 2028 3161 1090 2037 3171 1100 2037 3171 1100 2028 3161 1090 2038 3172 1101 2038 3172 1101 2028 3161 1090 2029 3162 1091 2039 3173 1102 2038 3172 1101 2030 3163 1092 2030 3163 1092 2038 3172 1101 2029 3162 1091 2201 3165 1093 2031 3164 1094 2202 3175 1103 2202 3175 1103 2031 3164 1094 2040 3174 1104 2031 3164 1094 2032 3166 1095 2040 3174 1104 2040 3174 1104 2032 3166 1095 2041 3176 1105 2032 3166 1095 2033 3167 1096 2041 3176 1105 2041 3176 1105 2033 3167 1096 2042 3177 1106 2033 3167 1096 2034 3168 1097 2042 3177 1106 2042 3177 1106 2034 3168 1097 2043 3178 1107 2034 3168 1097 2035 3169 1098 2043 3178 1107 2043 3178 1107 2035 3169 1098 2044 3179 1108 2035 3169 1098 2036 3170 1099 2044 3179 1108 2044 3179 1108 2036 3170 1099 2045 3180 1109 2036 3170 1099 2037 3171 1100 2045 3180 1109 2045 3180 1109 2037 3171 1100 2046 3181 1110 2046 3181 1110 2037 3171 1100 2047 3182 1111 2047 3182 1111 2037 3171 1100 2038 3172 1101 2047 3182 1111 2038 3172 1101 2048 3183 1112 2048 3183 1112 2038 3172 1101 2039 3173 1102 2067 3184 1113 2021 3153 1082 2068 3185 1114 2068 3185 1114 2021 3153 1082 2012 3143 1071 2069 3186 1115 2030 3163 1092 2067 3184 1113 2067 3184 1113 2030 3163 1092 2021 3153 1082 2055 3188 1119 2052 3189 1118 2071 3187 1116 2071 3187 1116 2052 3189 1118 2066 3190 1117 2052 3189 1118 2204 3191 1121 2066 3190 1117 2066 3190 1117 2204 3191 1121 2206 3192 1120 2277 3142 1072 2070 3193 1122 2012 3143 1071 2012 3143 1071 2070 3193 1122 2068 3185 1114 2051 3195 1126 2060 3196 1125 2061 3194 1123 2061 3194 1123 2060 3196 1125 2085 3197 1124 2204 3199 1121 2052 3200 1118 2205 3198 1127 2205 3198 1127 2052 3200 1118 2062 3201 1128 2054 3203 1132 2053 3204 1131 2064 3202 1129 2064 3202 1129 2053 3204 1131 2063 3205 1130 2052 3200 1118 2055 3206 1119 2062 3201 1128 2062 3201 1128 2055 3206 1119 2065 3207 1133 2055 3206 1119 2054 3203 1132 2065 3207 1133 2065 3207 1133 2054 3203 1132 2064 3202 1129 2053 3204 1131 2051 3195 1126 2063 3205 1130 2063 3205 1130 2051 3195 1126 2061 3194 1123 2039 3173 1102 2071 3187 1116 2048 3183 1112 2048 3183 1112 2071 3187 1116 2049 3208 1134 2030 3163 1092 2069 3186 1115 2039 3173 1102 2039 3173 1102 2069 3186 1115 2071 3187 1116 2071 3187 1116 2066 3190 1117 2049 3208 1134 2049 3208 1134 2066 3190 1117 2050 3209 1135 2203 3210 1136 2050 3209 1135 2206 3192 1120 2206 3192 1120 2050 3209 1135 2066 3190 1117 2068 3185 1114 2051 3211 1126 2067 3184 1113 2067 3184 1113 2051 3211 1126 2053 3212 1131 2067 3184 1113 2053 3212 1131 2069 3186 1115 2069 3186 1115 2053 3212 1131 2054 3213 1132 2054 3213 1132 2055 3188 1119 2069 3186 1115 2069 3186 1115 2055 3188 1119 2071 3187 1116 2070 3193 1122 2060 3214 1125 2068 3185 1114 2068 3185 1114 2060 3214 1125 2051 3211 1126 2075 3215 1137 2072 3216 1140 2076 3218 1138 2076 3218 1138 2072 3216 1140 2073 3217 1139 2072 3216 1140 2280 3219 1142 2073 3217 1139 2073 3217 1139 2280 3219 1142 2284 3220 1141 2076 3218 1138 2073 3217 1139 2197 3222 1143 2197 3222 1143 2073 3217 1139 2196 3221 1144 2073 3217 1139 2284 3220 1141 2196 3221 1144 2196 3221 1144 2284 3220 1141 2283 3223 1145 2072 3216 1140 2075 3215 1137 2074 3225 1146 2074 3225 1146 2075 3215 1137 2077 3224 1147 2077 3224 1147 2060 3214 1125 2074 3225 1146 2074 3225 1146 2060 3214 1125 2070 3193 1122 2280 3219 1142 2072 3216 1140 2281 3226 1148 2281 3226 1148 2072 3216 1140 2074 3225 1146 2277 3142 1072 2281 3226 1148 2070 3193 1122 2070 3193 1122 2281 3226 1148 2074 3225 1146 2084 3227 1149 2076 3228 1138 2198 3230 1150 2198 3230 1150 2076 3228 1138 2197 3229 1143 2082 3231 1151 2075 3232 1137 2084 3227 1149 2084 3227 1149 2075 3232 1137 2076 3228 1138 2083 3233 1152 2077 3234 1147 2082 3231 1151 2082 3231 1151 2077 3234 1147 2075 3232 1137 2191 3235 1153 2192 3236 1156 2057 3238 1154 2057 3238 1154 2192 3236 1156 2078 3237 1155 2058 3239 1157 2080 3240 1160 2056 3242 1158 2056 3242 1158 2080 3240 1160 2079 3241 1159 2057 3238 1154 2078 3237 1155 2059 3244 1161 2059 3244 1161 2078 3237 1155 2081 3243 1162 2059 3244 1161 2081 3243 1162 2058 3239 1157 2058 3239 1157 2081 3243 1162 2080 3240 1160 2084 3227 1149 2198 3230 1150 2091 3245 1163 2091 3245 1163 2198 3230 1150 2195 3246 1164 2089 3247 1165 2082 3231 1151 2091 3245 1163 2091 3245 1163 2082 3231 1151 2084 3227 1149 2090 3248 1166 2083 3233 1152 2089 3247 1165 2089 3247 1165 2083 3233 1152 2082 3231 1151 2085 3197 1124 2056 3242 1158 2061 3194 1123 2061 3194 1123 2056 3242 1158 2079 3241 1159 2077 3234 1147 2083 3233 1152 2060 3249 1125 2060 3249 1125 2083 3233 1152 2085 3250 1124 2079 3241 1159 2093 3251 1167 2061 3194 1123 2061 3194 1123 2093 3251 1167 2063 3205 1130 2057 3253 1154 2059 3254 1161 2087 3252 1168 2087 3252 1168 2059 3254 1161 2086 3255 1169 2191 3257 1153 2057 3253 1154 2193 3256 1170 2193 3256 1170 2057 3253 1154 2087 3252 1168 2059 3254 1161 2058 3258 1157 2086 3255 1169 2086 3255 1169 2058 3258 1157 2088 3259 1171 2056 3260 1158 2085 3250 1124 2090 3248 1166 2090 3248 1166 2085 3250 1124 2083 3233 1152 2087 3252 1168 2086 3255 1169 2092 3261 1172 2092 3261 1172 2086 3255 1169 2091 3245 1163 2194 3262 1173 2193 3256 1170 2092 3261 1172 2092 3261 1172 2193 3256 1170 2087 3252 1168 2086 3255 1169 2088 3259 1171 2091 3245 1163 2091 3245 1163 2088 3259 1171 2089 3247 1165 2089 3247 1165 2088 3259 1171 2090 3248 1166 2090 3248 1166 2088 3259 1171 2056 3260 1158 2056 3260 1158 2088 3259 1171 2058 3258 1157 2091 3245 1163 2195 3246 1164 2092 3261 1172 2092 3261 1172 2195 3246 1164 2194 3262 1173 2094 3263 1175 2095 3264 1174 2064 3202 1129 2064 3202 1129 2095 3264 1174 2065 3207 1133 2094 3263 1175 2080 3240 1160 2095 3265 1174 2095 3265 1174 2080 3240 1160 2081 3243 1162 2095 3266 1174 2096 3267 1176 2065 3207 1133 2065 3207 1133 2096 3267 1176 2062 3201 1128 2081 3243 1162 2078 3237 1155 2095 3265 1174 2095 3265 1174 2078 3237 1155 2096 3268 1176 2096 3267 1176 2207 3269 1177 2062 3201 1128 2062 3201 1128 2207 3269 1177 2205 3198 1127 2096 3268 1176 2078 3237 1155 2207 3270 1177 2207 3270 1177 2078 3237 1155 2192 3236 1156 2093 3251 1167 2094 3263 1175 2063 3205 1130 2063 3205 1130 2094 3263 1175 2064 3202 1129 2079 3241 1159 2080 3240 1160 2093 3251 1167 2093 3251 1167 2080 3240 1160 2094 3263 1175 2261 3124 1053 2190 3127 1054 2260 3272 1178 2260 3272 1178 2190 3127 1054 2097 3271 1179 2260 3272 1178 2097 3271 1179 2259 3274 1180 2259 3274 1180 2097 3271 1179 2098 3273 1181 2259 3274 1180 2098 3273 1181 2264 3276 1182 2264 3276 1182 2098 3273 1181 2099 3275 1183 2264 3276 1182 2099 3275 1183 2266 3278 1184 2266 3278 1184 2099 3275 1183 2100 3277 1185 2266 3278 1184 2100 3277 1185 2268 3280 1186 2268 3280 1186 2100 3277 1185 2101 3279 1187 2268 3280 1186 2101 3279 1187 2270 3282 1188 2270 3282 1188 2101 3279 1187 2102 3281 1189 2270 3282 1188 2102 3281 1189 2272 3284 1190 2272 3284 1190 2102 3281 1189 2103 3283 1191 2103 3283 1191 2104 3285 1193 2272 3284 1190 2272 3284 1190 2104 3285 1193 2274 3286 1192 2104 3285 1193 2105 3287 1195 2274 3286 1192 2274 3286 1192 2105 3287 1195 2276 3288 1194 2190 3127 1054 2199 3145 1073 2097 3271 1179 2097 3271 1179 2199 3145 1073 2106 3289 1196 2097 3271 1179 2106 3289 1196 2098 3273 1181 2098 3273 1181 2106 3289 1196 2107 3290 1197 2098 3273 1181 2107 3290 1197 2099 3275 1183 2099 3275 1183 2107 3290 1197 2108 3291 1198 2099 3275 1183 2108 3291 1198 2100 3277 1185 2100 3277 1185 2108 3291 1198 2109 3292 1199 2100 3277 1185 2109 3292 1199 2101 3279 1187 2101 3279 1187 2109 3292 1199 2110 3293 1200 2101 3279 1187 2110 3293 1200 2102 3281 1189 2102 3281 1189 2110 3293 1200 2111 3294 1201 2102 3281 1189 2111 3294 1201 2103 3283 1191 2103 3283 1191 2111 3294 1201 2112 3295 1202 2112 3295 1202 2113 3296 1203 2103 3283 1191 2103 3283 1191 2113 3296 1203 2104 3285 1193 2113 3296 1203 2114 3297 1204 2104 3285 1193 2104 3285 1193 2114 3297 1204 2105 3287 1195 2199 3145 1073 2200 3155 1083 2106 3289 1196 2106 3289 1196 2200 3155 1083 2115 3298 1205 2106 3289 1196 2115 3298 1205 2107 3290 1197 2107 3290 1197 2115 3298 1205 2116 3299 1206 2107 3290 1197 2116 3299 1206 2108 3291 1198 2108 3291 1198 2116 3299 1206 2117 3300 1207 2108 3291 1198 2117 3300 1207 2109 3292 1199 2109 3292 1199 2117 3300 1207 2118 3301 1208 2109 3292 1199 2118 3301 1208 2110 3293 1200 2110 3293 1200 2118 3301 1208 2119 3302 1209 2110 3293 1200 2119 3302 1209 2111 3294 1201 2111 3294 1201 2119 3302 1209 2120 3303 1210 2111 3294 1201 2120 3303 1210 2112 3295 1202 2112 3295 1202 2120 3303 1210 2121 3304 1211 2121 3304 1211 2122 3305 1212 2112 3295 1202 2112 3295 1202 2122 3305 1212 2113 3296 1203 2122 3305 1212 2123 3306 1213 2113 3296 1203 2113 3296 1203 2123 3306 1213 2114 3297 1204 2200 3155 1083 2201 3165 1093 2115 3298 1205 2115 3298 1205 2201 3165 1093 2124 3307 1214 2115 3298 1205 2124 3307 1214 2116 3299 1206 2116 3299 1206 2124 3307 1214 2125 3308 1215 2116 3299 1206 2125 3308 1215 2117 3300 1207 2117 3300 1207 2125 3308 1215 2126 3309 1216 2117 3300 1207 2126 3309 1216 2118 3301 1208 2118 3301 1208 2126 3309 1216 2127 3310 1217 2118 3301 1208 2127 3310 1217 2119 3302 1209 2119 3302 1209 2127 3310 1217 2128 3311 1218 2119 3302 1209 2128 3311 1218 2120 3303 1210 2120 3303 1210 2128 3311 1218 2129 3312 1219 2120 3303 1210 2129 3312 1219 2121 3304 1211 2121 3304 1211 2129 3312 1219 2130 3313 1220 2130 3313 1220 2131 3314 1221 2121 3304 1211 2121 3304 1211 2131 3314 1221 2122 3305 1212 2132 3315 1222 2123 3306 1213 2131 3314 1221 2131 3314 1221 2123 3306 1213 2122 3305 1212 2201 3165 1093 2202 3175 1103 2124 3307 1214 2124 3307 1214 2202 3175 1103 2133 3316 1223 2124 3307 1214 2133 3316 1223 2125 3308 1215 2125 3308 1215 2133 3316 1223 2134 3317 1224 2125 3308 1215 2134 3317 1224 2126 3309 1216 2126 3309 1216 2134 3317 1224 2135 3318 1225 2126 3309 1216 2135 3318 1225 2127 3310 1217 2127 3310 1217 2135 3318 1225 2136 3319 1226 2127 3310 1217 2136 3319 1226 2128 3311 1218 2128 3311 1218 2136 3319 1226 2137 3320 1227 2128 3311 1218 2137 3320 1227 2129 3312 1219 2129 3312 1219 2137 3320 1227 2138 3321 1228 2129 3312 1219 2138 3321 1228 2130 3313 1220 2130 3313 1220 2138 3321 1228 2139 3322 1229 2139 3322 1229 2140 3323 1230 2130 3313 1220 2130 3313 1220 2140 3323 1230 2131 3314 1221 2140 3323 1230 2141 3324 1231 2131 3314 1221 2131 3314 1221 2141 3324 1231 2132 3315 1222 2160 3325 1232 2161 3326 1233 2114 3297 1204 2114 3297 1204 2161 3326 1233 2105 3287 1195 2162 3327 1234 2160 3325 1232 2123 3306 1213 2123 3306 1213 2160 3325 1232 2114 3297 1204 2159 3329 1238 2145 3330 1237 2164 3328 1235 2164 3328 1235 2145 3330 1237 2148 3331 1236 2206 3192 1120 2204 3191 1121 2159 3329 1238 2159 3329 1238 2204 3191 1121 2145 3330 1237 2161 3326 1233 2163 3332 1239 2105 3287 1195 2105 3287 1195 2163 3332 1239 2276 3288 1194 2178 3334 1243 2153 3335 1242 2154 3333 1240 2154 3333 1240 2153 3335 1242 2144 3336 1241 2155 3337 1244 2145 3338 1237 2205 3198 1127 2205 3198 1127 2145 3338 1237 2204 3199 1121 2156 3340 1248 2146 3341 1247 2157 3339 1245 2157 3339 1245 2146 3341 1247 2147 3342 1246 2158 3343 1249 2148 3344 1236 2155 3337 1244 2155 3337 1244 2148 3344 1236 2145 3338 1237 2157 3339 1245 2147 3342 1246 2158 3343 1249 2158 3343 1249 2147 3342 1246 2148 3344 1236 2154 3333 1240 2144 3336 1241 2156 3340 1248 2156 3340 1248 2144 3336 1241 2146 3341 1247 2142 3345 1250 2164 3328 1235 2141 3324 1231 2141 3324 1231 2164 3328 1235 2132 3315 1222 2164 3328 1235 2162 3327 1234 2132 3315 1222 2132 3315 1222 2162 3327 1234 2123 3306 1213 2143 3346 1251 2159 3329 1238 2142 3345 1250 2142 3345 1250 2159 3329 1238 2164 3328 1235 2159 3329 1238 2143 3346 1251 2206 3192 1120 2206 3192 1120 2143 3346 1251 2203 3210 1136 2161 3326 1233 2160 3325 1232 2144 3348 1241 2144 3348 1241 2160 3325 1232 2146 3347 1247 2160 3325 1232 2162 3327 1234 2146 3347 1247 2146 3347 1247 2162 3327 1234 2147 3349 1246 2164 3328 1235 2148 3331 1236 2162 3327 1234 2162 3327 1234 2148 3331 1236 2147 3349 1246 2163 3332 1239 2161 3326 1233 2153 3350 1242 2153 3350 1242 2161 3326 1233 2144 3348 1241 2168 3351 1252 2169 3352 1255 2165 3354 1253 2165 3354 1253 2169 3352 1255 2166 3353 1254 2165 3354 1253 2166 3353 1254 2279 3356 1256 2279 3356 1256 2166 3353 1254 2282 3355 1257 2169 3352 1255 2197 3222 1143 2166 3353 1254 2166 3353 1254 2197 3222 1143 2196 3221 1144 2166 3353 1254 2196 3221 1144 2282 3355 1257 2282 3355 1257 2196 3221 1144 2283 3223 1145 2165 3354 1253 2167 3357 1259 2168 3351 1252 2168 3351 1252 2167 3357 1259 2170 3358 1258 2163 3332 1239 2153 3350 1242 2167 3357 1259 2167 3357 1259 2153 3350 1242 2170 3358 1258 2167 3357 1259 2165 3354 1253 2278 3359 1260 2278 3359 1260 2165 3354 1253 2279 3356 1256 2276 3288 1194 2163 3332 1239 2278 3359 1260 2278 3359 1260 2163 3332 1239 2167 3357 1259 2177 3360 1261 2198 3230 1150 2169 3361 1255 2169 3361 1255 2198 3230 1150 2197 3229 1143 2175 3362 1262 2177 3360 1261 2168 3363 1252 2168 3363 1252 2177 3360 1261 2169 3361 1255 2176 3364 1263 2175 3362 1262 2170 3365 1258 2170 3365 1258 2175 3362 1262 2168 3363 1252 2191 3235 1153 2150 3366 1265 2192 3236 1156 2192 3236 1156 2150 3366 1265 2171 3367 1264 2151 3368 1266 2149 3369 1269 2173 3371 1267 2173 3371 1267 2149 3369 1269 2172 3370 1268 2150 3366 1265 2152 3372 1271 2171 3367 1264 2171 3367 1264 2152 3372 1271 2174 3373 1270 2152 3372 1271 2151 3368 1266 2174 3373 1270 2174 3373 1270 2151 3368 1266 2173 3371 1267 2195 3246 1164 2198 3230 1150 2184 3374 1272 2184 3374 1272 2198 3230 1150 2177 3360 1261 2182 3375 1273 2184 3374 1272 2175 3362 1262 2175 3362 1262 2184 3374 1272 2177 3360 1261 2183 3376 1274 2182 3375 1273 2176 3364 1263 2176 3364 1263 2182 3375 1273 2175 3362 1262 2178 3334 1243 2154 3333 1240 2149 3369 1269 2149 3369 1269 2154 3333 1240 2172 3370 1268 2178 3378 1243 2176 3364 1263 2153 3377 1242 2153 3377 1242 2176 3364 1263 2170 3365 1258 2156 3340 1248 2186 3379 1275 2154 3333 1240 2154 3333 1240 2186 3379 1275 2172 3370 1268 2179 3381 1277 2152 3382 1271 2180 3380 1276 2180 3380 1276 2152 3382 1271 2150 3383 1265 2180 3380 1276 2150 3383 1265 2193 3256 1170 2193 3256 1170 2150 3383 1265 2191 3257 1153 2181 3384 1278 2151 3385 1266 2179 3381 1277 2179 3381 1277 2151 3385 1266 2152 3382 1271 2176 3364 1263 2178 3378 1243 2183 3376 1274 2183 3376 1274 2178 3378 1243 2149 3386 1269 2180 3380 1276 2185 3387 1279 2179 3381 1277 2179 3381 1277 2185 3387 1279 2184 3374 1272 2194 3262 1173 2185 3387 1279 2193 3256 1170 2193 3256 1170 2185 3387 1279 2180 3380 1276 2182 3375 1273 2181 3384 1278 2184 3374 1272 2184 3374 1272 2181 3384 1278 2179 3381 1277 2182 3375 1273 2183 3376 1274 2181 3384 1278 2183 3376 1274 2149 3386 1269 2181 3384 1278 2181 3384 1278 2149 3386 1269 2151 3385 1266 2194 3262 1173 2195 3246 1164 2185 3387 1279 2185 3387 1279 2195 3246 1164 2184 3374 1272 2158 3343 1249 2188 3388 1281 2157 3339 1245 2157 3339 1245 2188 3388 1281 2187 3389 1280 2187 3389 1280 2188 3390 1281 2173 3371 1267 2173 3371 1267 2188 3390 1281 2174 3373 1270 2155 3337 1244 2189 3391 1282 2158 3343 1249 2158 3343 1249 2189 3391 1282 2188 3392 1281 2189 3393 1282 2171 3367 1264 2188 3390 1281 2188 3390 1281 2171 3367 1264 2174 3373 1270 2205 3198 1127 2207 3269 1177 2155 3337 1244 2155 3337 1244 2207 3269 1177 2189 3391 1282 2189 3393 1282 2207 3270 1177 2171 3367 1264 2171 3367 1264 2207 3270 1177 2192 3236 1156 2157 3339 1245 2187 3389 1280 2156 3340 1248 2156 3340 1248 2187 3389 1280 2186 3379 1275 2187 3389 1280 2173 3371 1267 2186 3379 1275 2186 3379 1275 2173 3371 1267 2172 3370 1268 2138 3321 1228 2137 3320 1227 2208 3395 1283 2208 3395 1283 2137 3320 1227 2209 3394 1284 2137 3320 1227 2136 3319 1226 2209 3394 1284 2209 3394 1284 2136 3319 1226 2210 3396 1285 2136 3319 1226 2135 3318 1225 2210 3396 1285 2210 3396 1285 2135 3318 1225 2211 3397 1286 2135 3318 1225 2134 3317 1224 2211 3397 1286 2211 3397 1286 2134 3317 1224 2212 3398 1287 2134 3317 1224 2133 3316 1223 2212 3398 1287 2212 3398 1287 2133 3316 1223 2213 3399 1288 2133 3316 1223 2202 3175 1103 2213 3399 1288 2213 3399 1288 2202 3175 1103 2214 3400 1289 2202 3175 1103 2040 3174 1104 2214 3400 1289 2214 3400 1289 2040 3174 1104 2215 3401 1290 2040 3174 1104 2041 3176 1105 2215 3401 1290 2215 3401 1290 2041 3176 1105 2216 3402 1291 2041 3176 1105 2042 3177 1106 2216 3402 1291 2216 3402 1291 2042 3177 1106 2217 3403 1292 2042 3177 1106 2043 3178 1107 2217 3403 1292 2217 3403 1292 2043 3178 1107 2218 3404 1293 2043 3178 1107 2044 3179 1108 2218 3404 1293 2218 3404 1293 2044 3179 1108 2219 3405 1294 2044 3179 1108 2045 3180 1109 2219 3405 1294 2219 3405 1294 2045 3180 1109 2220 3406 1295 2045 3180 1109 2046 3181 1110 2220 3406 1295 2220 3406 1295 2046 3181 1110 2221 3407 1296 2046 3181 1110 2047 3182 1111 2221 3407 1296 2221 3407 1296 2047 3182 1111 2222 3408 1297 2047 3182 1111 2048 3183 1112 2222 3408 1297 2222 3408 1297 2048 3183 1112 2223 3409 1298 2048 3183 1112 2049 3208 1134 2223 3409 1298 2223 3409 1298 2049 3208 1134 2224 3410 1299 2049 3208 1134 2050 3209 1135 2224 3410 1299 2224 3410 1299 2050 3209 1135 2225 3411 1300 2050 3209 1135 2203 3210 1136 2225 3411 1300 2225 3411 1300 2203 3210 1136 2226 3412 1301 2203 3210 1136 2143 3346 1251 2226 3412 1301 2226 3412 1301 2143 3346 1251 2227 3413 1302 2143 3346 1251 2142 3345 1250 2227 3413 1302 2227 3413 1302 2142 3345 1250 2228 3414 1303 2142 3345 1250 2141 3324 1231 2228 3414 1303 2228 3414 1303 2141 3324 1231 2229 3415 1304 2141 3324 1231 2140 3323 1230 2229 3415 1304 2229 3415 1304 2140 3323 1230 2230 3416 1305 2140 3323 1230 2139 3322 1229 2230 3416 1305 2230 3416 1305 2139 3322 1229 2231 3417 1306 2139 3322 1229 2138 3321 1228 2231 3417 1306 2231 3417 1306 2138 3321 1228 2208 3395 1283 2208 3395 1283 2209 3394 1284 2232 3418 1307 2209 3394 1284 2210 3396 1285 2232 3418 1307 2210 3396 1285 2211 3397 1286 2232 3418 1307 2211 3397 1286 2212 3398 1287 2232 3418 1307 2212 3398 1287 2213 3399 1288 2232 3418 1307 2213 3399 1288 2214 3400 1289 2232 3418 1307 2214 3400 1289 2215 3401 1290 2232 3418 1307 2215 3401 1290 2216 3402 1291 2232 3418 1307 2216 3402 1291 2217 3403 1292 2232 3418 1307 2217 3403 1292 2218 3404 1293 2232 3418 1307 2218 3404 1293 2219 3405 1294 2232 3418 1307 2219 3405 1294 2220 3406 1295 2232 3418 1307 2220 3406 1295 2221 3407 1296 2232 3418 1307 2221 3407 1296 2222 3408 1297 2232 3418 1307 2222 3408 1297 2223 3409 1298 2232 3418 1307 2223 3409 1298 2224 3410 1299 2232 3418 1307 2224 3410 1299 2225 3411 1300 2232 3418 1307 2225 3411 1300 2226 3412 1301 2232 3418 1307 2226 3412 1301 2227 3413 1302 2232 3418 1307 2227 3413 1302 2228 3414 1303 2232 3418 1307 2228 3414 1303 2229 3415 1304 2232 3418 1307 2229 3415 1304 2230 3416 1305 2232 3418 1307 2230 3416 1305 2231 3417 1306 2232 3418 1307 2231 3417 1306 2208 3395 1283 2232 3418 1307 2280 3420 1142 2236 3421 1309 2284 3419 1141 2284 3419 1141 2236 3421 1309 2237 3422 1308 2281 3226 1148 2233 3423 1310 2280 3420 1142 2280 3420 1142 2233 3423 1310 2236 3421 1309 2281 3226 1148 2277 3142 1072 2233 3423 1310 2233 3423 1310 2277 3142 1072 2234 3424 1311 2277 3142 1072 2275 3425 1070 2234 3424 1311 2234 3424 1311 2275 3425 1070 2235 3426 1312 2275 3427 1070 2273 3428 1068 2235 3430 1312 2235 3430 1312 2273 3428 1068 2258 3429 1313 2273 3428 1068 2271 3431 1066 2258 3429 1313 2258 3429 1313 2271 3431 1066 2257 3432 1314 2271 3431 1066 2269 3433 1064 2257 3432 1314 2257 3432 1314 2269 3433 1064 2256 3434 1315 2269 3433 1064 2267 3435 1061 2256 3434 1315 2256 3434 1315 2267 3435 1061 2255 3436 1316 2267 3435 1061 2265 3437 1060 2255 3436 1316 2255 3436 1316 2265 3437 1060 2254 3438 1317 2265 3437 1060 2262 3439 1058 2254 3438 1317 2254 3438 1317 2262 3439 1058 2253 3440 1318 2262 3439 1058 2263 3441 1056 2253 3440 1318 2253 3440 1318 2263 3441 1056 2252 3442 1319 2263 3441 1056 2261 3443 1053 2252 3442 1319 2252 3442 1319 2261 3443 1053 2251 3444 1320 2261 3443 1053 2260 3445 1178 2251 3444 1320 2251 3444 1320 2260 3445 1178 2250 3446 1321 2260 3445 1178 2259 3447 1180 2250 3446 1321 2250 3446 1321 2259 3447 1180 2249 3448 1322 2259 3447 1180 2264 3449 1182 2249 3448 1322 2249 3448 1322 2264 3449 1182 2248 3450 1323 2264 3449 1182 2266 3451 1184 2248 3450 1323 2248 3450 1323 2266 3451 1184 2247 3452 1324 2266 3451 1184 2268 3453 1186 2247 3452 1324 2247 3452 1324 2268 3453 1186 2246 3454 1325 2268 3453 1186 2270 3455 1188 2246 3454 1325 2246 3454 1325 2270 3455 1188 2245 3456 1326 2270 3455 1188 2272 3457 1190 2245 3456 1326 2245 3456 1326 2272 3457 1190 2244 3458 1327 2274 3459 1192 2243 3460 1328 2272 3457 1190 2272 3457 1190 2243 3460 1328 2244 3458 1327 2276 3461 1194 2242 3462 1329 2274 3459 1192 2274 3459 1192 2242 3462 1329 2243 3460 1328 2278 3359 1260 2241 3463 1330 2276 3461 1194 2276 3461 1194 2241 3463 1330 2242 3462 1329 2278 3359 1260 2279 3356 1256 2241 3463 1330 2241 3463 1330 2279 3356 1256 2240 3464 1331 2279 3356 1256 2282 3465 1257 2240 3464 1331 2240 3464 1331 2282 3465 1257 2239 3466 1332 2282 3467 1257 2283 3468 1145 2239 3470 1332 2239 3470 1332 2283 3468 1145 2238 3469 1333 2284 3419 1141 2237 3422 1308 2283 3468 1145 2283 3468 1145 2237 3422 1308 2238 3469 1333 2006 3131 1059 2265 3130 1060 2007 3135 1062 2007 3135 1062 2265 3130 1060 2267 3132 1061 2257 3471 1314 2309 3472 1335 2258 3474 1313 2258 3474 1313 2309 3472 1335 2310 3473 1334 2310 3473 1334 2287 3475 1336 2258 3474 1313 2258 3474 1313 2287 3475 1336 2235 3476 1312 2287 3475 1336 2286 3477 1337 2235 3476 1312 2235 3476 1312 2286 3477 1337 2234 3478 1311 2286 3477 1337 2285 3479 1338 2234 3478 1311 2234 3478 1311 2285 3479 1338 2233 3480 1310 2233 3480 1310 2285 3479 1338 2236 3482 1309 2236 3482 1309 2285 3479 1338 2288 3481 1339 2236 3482 1309 2288 3481 1339 2237 3484 1308 2237 3484 1308 2288 3481 1339 2289 3483 1340 2237 3484 1308 2289 3483 1340 2238 3486 1333 2238 3486 1333 2289 3483 1340 2290 3485 1341 2290 3485 1341 2291 3487 1342 2238 3486 1333 2238 3486 1333 2291 3487 1342 2239 3488 1332 2291 3487 1342 2292 3489 1343 2239 3488 1332 2239 3488 1332 2292 3489 1343 2240 3490 1331 2292 3489 1343 2293 3491 1344 2240 3490 1331 2240 3490 1331 2293 3491 1344 2241 3492 1330 2241 3492 1330 2293 3491 1344 2242 3494 1329 2242 3494 1329 2293 3491 1344 2294 3493 1345 2242 3494 1329 2294 3493 1345 2243 3496 1328 2243 3496 1328 2294 3493 1345 2295 3495 1346 2243 3496 1328 2295 3495 1346 2244 3498 1327 2244 3498 1327 2295 3495 1346 2296 3497 1347 2244 3498 1327 2296 3497 1347 2245 3500 1326 2245 3500 1326 2296 3497 1347 2297 3499 1348 2245 3500 1326 2297 3499 1348 2246 3502 1325 2246 3502 1325 2297 3499 1348 2298 3501 1349 2246 3502 1325 2298 3501 1349 2247 3504 1324 2247 3504 1324 2298 3501 1349 2299 3503 1350 2247 3504 1324 2299 3503 1350 2248 3506 1323 2248 3506 1323 2299 3503 1350 2300 3505 1351 2248 3506 1323 2300 3505 1351 2249 3508 1322 2249 3508 1322 2300 3505 1351 2301 3507 1352 2249 3508 1322 2301 3507 1352 2250 3510 1321 2250 3510 1321 2301 3507 1352 2302 3509 1353 2250 3510 1321 2302 3509 1353 2251 3512 1320 2251 3512 1320 2302 3509 1353 2303 3511 1354 2251 3512 1320 2303 3511 1354 2252 3514 1319 2252 3514 1319 2303 3511 1354 2304 3513 1355 2252 3514 1319 2304 3513 1355 2253 3516 1318 2253 3516 1318 2304 3513 1355 2305 3515 1356 2253 3516 1318 2305 3515 1356 2254 3518 1317 2254 3518 1317 2305 3515 1356 2306 3517 1357 2254 3518 1317 2306 3517 1357 2255 3520 1316 2255 3520 1316 2306 3517 1357 2307 3519 1358 2255 3520 1316 2307 3519 1358 2256 3522 1315 2256 3522 1315 2307 3519 1358 2308 3521 1359 2256 3522 1315 2308 3521 1359 2257 3471 1314 2257 3471 1314 2308 3521 1359 2309 3472 1335 2296 3497 1347 2322 3523 1361 2297 3499 1348 2297 3499 1348 2322 3523 1361 2323 3524 1360 2297 3499 1348 2323 3524 1360 2298 3501 1349 2298 3501 1349 2323 3524 1360 2324 3525 1362 2298 3501 1349 2324 3525 1362 2299 3503 1350 2299 3503 1350 2324 3525 1362 2325 3526 1363 2299 3503 1350 2325 3526 1363 2300 3505 1351 2300 3505 1351 2325 3526 1363 2326 3527 1364 2300 3505 1351 2326 3527 1364 2301 3507 1352 2301 3507 1352 2326 3527 1364 2327 3528 1365 2301 3507 1352 2327 3528 1365 2302 3509 1353 2302 3509 1353 2327 3528 1365 2328 3529 1366 2302 3509 1353 2328 3529 1366 2303 3511 1354 2303 3511 1354 2328 3529 1366 2329 3530 1367 2303 3511 1354 2329 3530 1367 2304 3513 1355 2304 3513 1355 2329 3530 1367 2330 3531 1368 2304 3513 1355 2330 3531 1368 2305 3515 1356 2305 3515 1356 2330 3531 1368 2331 3532 1369 2305 3515 1356 2331 3532 1369 2306 3517 1357 2306 3517 1357 2331 3532 1369 2332 3533 1370 2306 3517 1357 2332 3533 1370 2307 3519 1358 2307 3519 1358 2332 3533 1370 2333 3534 1371 2307 3519 1358 2333 3534 1371 2308 3521 1359 2308 3521 1359 2333 3534 1371 2334 3535 1372 2308 3521 1359 2334 3535 1372 2309 3472 1335 2309 3472 1335 2334 3535 1372 2335 3536 1373 2309 3472 1335 2335 3536 1373 2310 3473 1334 2310 3473 1334 2335 3536 1373 2336 3537 1374 2336 3537 1374 2313 3538 1375 2310 3473 1334 2310 3473 1334 2313 3538 1375 2287 3475 1336 2313 3538 1375 2312 3539 1376 2287 3475 1336 2287 3475 1336 2312 3539 1376 2286 3477 1337 2312 3539 1376 2311 3540 1377 2286 3477 1337 2286 3477 1337 2311 3540 1377 2285 3479 1338 2285 3479 1338 2311 3540 1377 2288 3481 1339 2288 3481 1339 2311 3540 1377 2314 3541 1378 2288 3481 1339 2314 3541 1378 2289 3483 1340 2289 3483 1340 2314 3541 1378 2315 3542 1379 2289 3483 1340 2315 3542 1379 2290 3485 1341 2290 3485 1341 2315 3542 1379 2316 3543 1380 2290 3485 1341 2316 3543 1380 2291 3487 1342 2291 3487 1342 2316 3543 1380 2317 3544 1381 2317 3544 1381 2318 3545 1382 2291 3487 1342 2291 3487 1342 2318 3545 1382 2292 3489 1343 2318 3545 1382 2319 3546 1383 2292 3489 1343 2292 3489 1343 2319 3546 1383 2293 3491 1344 2293 3491 1344 2319 3546 1383 2294 3493 1345 2294 3493 1345 2319 3546 1383 2320 3547 1384 2294 3493 1345 2320 3547 1384 2295 3495 1346 2295 3495 1346 2320 3547 1384 2321 3548 1385 2295 3495 1346 2321 3548 1385 2296 3497 1347 2296 3497 1347 2321 3548 1385 2322 3523 1361 2312 3539 1376 2338 3549 1387 2311 3540 1377 2311 3540 1377 2338 3549 1387 2337 3550 1386 2337 3550 1386 2340 3551 1388 2311 3540 1377 2311 3540 1377 2340 3551 1388 2314 3541 1378 2314 3541 1378 2340 3551 1388 2315 3542 1379 2315 3542 1379 2340 3551 1388 2341 3552 1389 2315 3542 1379 2341 3552 1389 2316 3543 1380 2316 3543 1380 2341 3552 1389 2342 3553 1390 2316 3543 1380 2342 3553 1390 2317 3544 1381 2317 3544 1381 2342 3553 1390 2343 3554 1391 2317 3544 1381 2343 3554 1391 2318 3545 1382 2318 3545 1382 2343 3554 1391 2344 3555 1392 2318 3545 1382 2344 3555 1392 2319 3546 1383 2319 3546 1383 2344 3555 1392 2345 3556 1393 2345 3556 1393 2346 3557 1394 2319 3546 1383 2319 3546 1383 2346 3557 1394 2320 3547 1384 2320 3547 1384 2346 3557 1394 2321 3548 1385 2321 3548 1385 2346 3557 1394 2347 3558 1395 2321 3548 1385 2347 3558 1395 2322 3523 1361 2322 3523 1361 2347 3558 1395 2348 3559 1396 2322 3523 1361 2348 3559 1396 2323 3524 1360 2323 3524 1360 2348 3559 1396 2349 3560 1397 2323 3524 1360 2349 3560 1397 2324 3525 1362 2324 3525 1362 2349 3560 1397 2350 3561 1398 2324 3525 1362 2350 3561 1398 2325 3526 1363 2325 3526 1363 2350 3561 1398 2351 3562 1399 2325 3526 1363 2351 3562 1399 2326 3527 1364 2326 3527 1364 2351 3562 1399 2352 3563 1400 2326 3527 1364 2352 3563 1400 2327 3528 1365 2327 3528 1365 2352 3563 1400 2353 3564 1401 2327 3528 1365 2353 3564 1401 2328 3529 1366 2328 3529 1366 2353 3564 1401 2354 3565 1402 2328 3529 1366 2354 3565 1402 2329 3530 1367 2329 3530 1367 2354 3565 1402 2355 3566 1403 2329 3530 1367 2355 3566 1403 2330 3531 1368 2330 3531 1368 2355 3566 1403 2356 3567 1404 2330 3531 1368 2356 3567 1404 2331 3532 1369 2331 3532 1369 2356 3567 1404 2357 3568 1405 2331 3532 1369 2357 3568 1405 2332 3533 1370 2332 3533 1370 2357 3568 1405 2358 3569 1406 2332 3533 1370 2358 3569 1406 2333 3534 1371 2333 3534 1371 2358 3569 1406 2359 3570 1407 2333 3534 1371 2359 3570 1407 2334 3535 1372 2334 3535 1372 2359 3570 1407 2360 3571 1408 2334 3535 1372 2360 3571 1408 2335 3536 1373 2335 3536 1373 2360 3571 1408 2361 3572 1409 2335 3536 1373 2361 3572 1409 2336 3537 1374 2336 3537 1374 2361 3572 1409 2362 3573 1410 2336 3537 1374 2362 3573 1410 2313 3538 1375 2313 3538 1375 2362 3573 1410 2339 3574 1411 2313 3538 1375 2339 3574 1411 2312 3539 1376 2312 3539 1376 2339 3574 1411 2338 3549 1387 2367 3575 1413 2368 3576 1412 2341 3552 1389 2341 3552 1389 2368 3576 1412 2342 3553 1390 2342 3553 1390 2368 3576 1412 2343 3554 1391 2343 3554 1391 2368 3576 1412 2369 3577 1414 2343 3554 1391 2369 3577 1414 2344 3555 1392 2344 3555 1392 2369 3577 1414 2370 3578 1415 2344 3555 1392 2370 3578 1415 2345 3556 1393 2345 3556 1393 2370 3578 1415 2371 3579 1416 2371 3579 1416 2372 3580 1417 2345 3556 1393 2345 3556 1393 2372 3580 1417 2346 3557 1394 2372 3580 1417 2373 3581 1418 2346 3557 1394 2346 3557 1394 2373 3581 1418 2347 3558 1395 2373 3581 1418 2374 3582 1419 2347 3558 1395 2347 3558 1395 2374 3582 1419 2348 3559 1396 2348 3559 1396 2374 3582 1419 2349 3560 1397 2349 3560 1397 2374 3582 1419 2375 3583 1420 2349 3560 1397 2375 3583 1420 2350 3561 1398 2350 3561 1398 2375 3583 1420 2376 3584 1421 2350 3561 1398 2376 3584 1421 2351 3562 1399 2351 3562 1399 2376 3584 1421 2377 3585 1422 2351 3562 1399 2377 3585 1422 2352 3563 1400 2352 3563 1400 2377 3585 1422 2378 3586 1423 2352 3563 1400 2378 3586 1423 2353 3564 1401 2353 3564 1401 2378 3586 1423 2379 3587 1424 2353 3564 1401 2379 3587 1424 2354 3565 1402 2354 3565 1402 2379 3587 1424 2380 3588 1425 2354 3565 1402 2380 3588 1425 2355 3566 1403 2355 3566 1403 2380 3588 1425 2381 3589 1426 2355 3566 1403 2381 3589 1426 2356 3567 1404 2356 3567 1404 2381 3589 1426 2382 3590 1427 2356 3567 1404 2382 3590 1427 2357 3568 1405 2357 3568 1405 2382 3590 1427 2383 3591 1428 2357 3568 1405 2383 3591 1428 2358 3569 1406 2358 3569 1406 2383 3591 1428 2384 3592 1429 2358 3569 1406 2384 3592 1429 2359 3570 1407 2359 3570 1407 2384 3592 1429 2385 3593 1430 2359 3570 1407 2385 3593 1430 2360 3571 1408 2360 3571 1408 2385 3593 1430 2386 3594 1431 2360 3571 1408 2386 3594 1431 2361 3572 1409 2361 3572 1409 2386 3594 1431 2387 3595 1432 2361 3572 1409 2387 3595 1432 2362 3573 1410 2362 3573 1410 2387 3595 1432 2388 3596 1433 2362 3573 1410 2388 3596 1433 2339 3574 1411 2339 3574 1411 2388 3596 1433 2365 3597 1434 2339 3574 1411 2365 3597 1434 2338 3549 1387 2338 3549 1387 2365 3597 1434 2364 3598 1435 2338 3549 1387 2364 3598 1435 2337 3550 1386 2337 3550 1386 2364 3598 1435 2363 3599 1436 2363 3599 1436 2366 3600 1437 2337 3550 1386 2337 3550 1386 2366 3600 1437 2340 3551 1388 2366 3600 1437 2367 3575 1413 2340 3551 1388 2340 3551 1388 2367 3575 1413 2341 3552 1389</p>
+ </triangles>
+ <triangles material="HeadphonesSG4" count="260">
+ <input semantic="VERTEX" source="#Headphones-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Headphones-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Headphones-headphonesUV" offset="2" set="1"/>
+ <p>964 1755 1438 967 1756 1439 965 1758 1441 965 1758 1441 967 1756 1439 966 1757 1440 945 1759 1442 969 1760 1443 946 1762 1445 946 1762 1445 969 1760 1443 968 1761 1444 953 1763 1446 971 1764 1447 954 1766 1449 954 1766 1449 971 1764 1447 970 1765 1448 949 1767 1450 973 1768 1451 950 1770 1453 950 1770 1453 973 1768 1451 972 1769 1452 959 1771 1454 975 1772 1455 960 1774 1457 960 1774 1457 975 1772 1455 974 1773 1456 943 1775 1458 977 1776 1459 944 1778 1461 944 1778 1461 977 1776 1459 976 1777 1460 954 1766 1449 970 1765 1448 955 1780 1463 955 1780 1463 970 1765 1448 978 1779 1462 940 1781 1464 980 1782 1465 941 1784 1467 941 1784 1467 980 1782 1465 979 1783 1466 961 1785 1468 982 1786 1469 962 1788 1471 962 1788 1471 982 1786 1469 981 1787 1470 960 1774 1457 974 1773 1456 961 1785 1468 961 1785 1468 974 1773 1456 982 1786 1469 963 1789 1472 983 1790 1473 964 1755 1438 964 1755 1438 983 1790 1473 967 1756 1439 947 1791 1474 985 1792 1475 948 1794 1477 948 1794 1477 985 1792 1475 984 1793 1476 957 1795 1478 987 1796 1479 958 1798 1481 958 1798 1481 987 1796 1479 986 1797 1480 950 1770 1453 972 1769 1452 951 1800 1483 951 1800 1483 972 1769 1452 988 1799 1482 962 1788 1471 981 1787 1470 963 1789 1472 963 1789 1472 981 1787 1470 983 1790 1473 942 1801 1484 989 1802 1485 943 1775 1458 943 1775 1458 989 1802 1485 977 1776 1459 958 1798 1481 986 1797 1480 959 1771 1454 959 1771 1454 986 1797 1480 975 1772 1455 955 1780 1463 978 1779 1462 956 1804 1487 956 1804 1487 978 1779 1462 990 1803 1486 951 1800 1483 988 1799 1482 952 1806 1489 952 1806 1489 988 1799 1482 991 1805 1488 944 1778 1461 976 1777 1460 945 1759 1442 945 1759 1442 976 1777 1460 969 1760 1443 956 1804 1487 990 1803 1486 957 1795 1478 957 1795 1478 990 1803 1486 987 1796 1479 941 1784 1467 979 1783 1466 942 1801 1484 942 1801 1484 979 1783 1466 989 1802 1485 948 1794 1477 984 1793 1476 949 1767 1450 949 1767 1450 984 1793 1476 973 1768 1451 952 1806 1489 991 1805 1488 953 1763 1446 953 1763 1446 991 1805 1488 971 1764 1447 946 1762 1445 968 1761 1444 947 1791 1474 947 1791 1474 968 1761 1444 985 1792 1475 965 1758 1441 966 1757 1440 940 1781 1464 940 1781 1464 966 1757 1440 980 1782 1465 1002 1808 1490 1003 1809 1491 990 1807 1486 990 1807 1486 1003 1809 1491 987 1810 1479 971 1811 1447 1001 1812 1492 970 1813 1448 991 1814 1488 1000 1815 1493 971 1811 1447 971 1811 1447 1000 1815 1493 1001 1812 1492 985 1816 1475 998 1817 1494 984 1818 1476 984 1818 1476 998 1817 1494 973 1820 1451 973 1820 1451 998 1817 1494 999 1819 1495 973 1820 1451 999 1819 1495 972 1821 1452 968 1822 1444 997 1823 1496 985 1816 1475 985 1816 1475 997 1823 1496 998 1817 1494 967 1824 1439 993 1825 1497 966 1827 1440 966 1827 1440 993 1825 1497 994 1826 1498 970 1813 1448 1001 1812 1492 978 1828 1462 978 1828 1462 1001 1812 1492 1002 1808 1490 978 1828 1462 1002 1808 1490 990 1807 1486 979 1829 1466 995 1830 1499 989 1831 1485 982 1832 1469 992 1833 1500 981 1834 1470 975 1835 1455 1004 1836 1501 974 1837 1456 986 1838 1480 1003 1809 1491 975 1835 1455 975 1835 1455 1003 1809 1491 1004 1836 1501 976 1839 1460 996 1840 1502 969 1841 1443 969 1841 1443 996 1840 1502 997 1823 1496 981 1834 1470 992 1833 1500 983 1842 1473 983 1842 1473 992 1833 1500 993 1825 1497 999 1819 1495 1000 1815 1493 972 1821 1452 972 1821 1452 1000 1815 1493 988 1843 1482 987 1810 1479 1003 1809 1491 986 1838 1480 966 1827 1440 994 1826 1498 980 1844 1465 977 1845 1459 996 1840 1502 976 1839 1460 989 1831 1485 995 1830 1499 977 1845 1459 977 1845 1459 995 1830 1499 996 1840 1502 1004 1836 1501 992 1833 1500 974 1837 1456 974 1837 1456 992 1833 1500 982 1832 1469 988 1843 1482 1000 1815 1493 991 1814 1488 969 1841 1443 997 1823 1496 968 1822 1444 983 1842 1473 993 1825 1497 967 1824 1439 994 1826 1498 995 1830 1499 980 1844 1465 980 1844 1465 995 1830 1499 979 1829 1466 1001 1812 1492 1006 1846 1503 1002 1808 1490 1002 1808 1490 1006 1846 1503 1005 1847 1504 998 1817 1494 1008 1848 1505 999 1819 1495 999 1819 1495 1008 1848 1505 1007 1849 1506 1010 1850 1507 1009 1851 1508 994 1826 1498 994 1826 1498 1009 1851 1508 995 1830 1499 993 1825 1497 1011 1852 1509 994 1826 1498 994 1826 1498 1011 1852 1509 1010 1850 1507 996 1840 1502 1013 1853 1510 997 1823 1496 997 1823 1496 1013 1853 1510 1012 1854 1511 997 1823 1496 1012 1854 1511 998 1817 1494 998 1817 1494 1012 1854 1511 1008 1848 1505 1007 1849 1506 1014 1855 1512 999 1819 1495 999 1819 1495 1014 1855 1512 1000 1815 1493 995 1830 1499 1009 1851 1508 996 1840 1502 996 1840 1502 1009 1851 1508 1013 1853 1510 1000 1815 1493 1014 1855 1512 1001 1812 1492 1001 1812 1492 1014 1855 1512 1006 1846 1503 1005 1847 1504 1015 1856 1513 1002 1808 1490 1002 1808 1490 1015 1856 1513 1003 1809 1491 992 1833 1500 1016 1857 1514 993 1825 1497 993 1825 1497 1016 1857 1514 1011 1852 1509 1017 1858 1515 1016 1857 1514 1004 1836 1501 1004 1836 1501 1016 1857 1514 992 1833 1500 1003 1809 1491 1015 1856 1513 1004 1836 1501 1004 1836 1501 1015 1856 1513 1017 1858 1515 1007 1849 1506 1008 1848 1505 1014 1855 1512 1014 1855 1512 1008 1848 1505 1018 1859 1516 1013 1853 1510 1009 1851 1508 1018 1859 1516 1018 1859 1516 1009 1851 1508 1010 1850 1507 1010 1850 1507 1011 1852 1509 1018 1859 1516 1018 1859 1516 1011 1852 1509 1016 1857 1514 1015 1856 1513 1018 1859 1516 1017 1858 1515 1018 1859 1516 1016 1857 1514 1017 1858 1515 1014 1855 1512 1018 1859 1516 1006 1846 1503 1005 1847 1504 1006 1846 1503 1015 1856 1513 1015 1856 1513 1006 1846 1503 1018 1859 1516 1012 1854 1511 1013 1853 1510 1008 1848 1505 1008 1848 1505 1013 1853 1510 1018 1859 1516 2621 3601 1438 2622 3602 1441 2624 3604 1439 2624 3604 1439 2622 3602 1441 2623 3603 1440 2602 3605 1442 2603 3606 1445 2626 3608 1443 2626 3608 1443 2603 3606 1445 2625 3607 1444 2610 3609 1446 2611 3610 1449 2628 3612 1447 2628 3612 1447 2611 3610 1449 2627 3611 1448 2606 3613 1450 2607 3614 1453 2630 3616 1451 2630 3616 1451 2607 3614 1453 2629 3615 1452 2616 3617 1454 2617 3618 1457 2632 3620 1455 2632 3620 1455 2617 3618 1457 2631 3619 1456 2600 3621 1458 2601 3622 1461 2634 3624 1459 2634 3624 1459 2601 3622 1461 2633 3623 1460 2611 3610 1449 2612 3625 1463 2627 3611 1448 2627 3611 1448 2612 3625 1463 2635 3626 1462 2597 3627 1464 2598 3628 1467 2637 3630 1465 2637 3630 1465 2598 3628 1467 2636 3629 1466 2618 3631 1468 2619 3632 1471 2639 3634 1469 2639 3634 1469 2619 3632 1471 2638 3633 1470 2617 3618 1457 2618 3631 1468 2631 3619 1456 2631 3619 1456 2618 3631 1468 2639 3634 1469 2620 3635 1472 2621 3601 1438 2640 3636 1473 2640 3636 1473 2621 3601 1438 2624 3604 1439 2604 3637 1474 2605 3638 1477 2642 3640 1475 2642 3640 1475 2605 3638 1477 2641 3639 1476 2614 3641 1478 2615 3642 1481 2644 3644 1479 2644 3644 1479 2615 3642 1481 2643 3643 1480 2607 3614 1453 2608 3645 1483 2629 3615 1452 2629 3615 1452 2608 3645 1483 2645 3646 1482 2619 3632 1471 2620 3635 1472 2638 3633 1470 2638 3633 1470 2620 3635 1472 2640 3636 1473 2599 3647 1484 2600 3621 1458 2646 3648 1485 2646 3648 1485 2600 3621 1458 2634 3624 1459 2615 3642 1481 2616 3617 1454 2643 3643 1480 2643 3643 1480 2616 3617 1454 2632 3620 1455 2612 3625 1463 2613 3649 1487 2635 3626 1462 2635 3626 1462 2613 3649 1487 2647 3650 1486 2608 3645 1483 2609 3651 1489 2645 3646 1482 2645 3646 1482 2609 3651 1489 2648 3652 1488 2601 3622 1461 2602 3605 1442 2633 3623 1460 2633 3623 1460 2602 3605 1442 2626 3608 1443 2613 3649 1487 2614 3641 1478 2647 3650 1486 2647 3650 1486 2614 3641 1478 2644 3644 1479 2598 3628 1467 2599 3647 1484 2636 3629 1466 2636 3629 1466 2599 3647 1484 2646 3648 1485 2605 3638 1477 2606 3613 1450 2641 3639 1476 2641 3639 1476 2606 3613 1450 2630 3616 1451 2609 3651 1489 2610 3609 1446 2648 3652 1488 2648 3652 1488 2610 3609 1446 2628 3612 1447 2603 3606 1445 2604 3637 1474 2625 3607 1444 2625 3607 1444 2604 3637 1474 2642 3640 1475 2622 3602 1441 2597 3627 1464 2623 3603 1440 2623 3603 1440 2597 3627 1464 2637 3630 1465 2644 3654 1479 2660 3655 1491 2647 3653 1486 2647 3653 1486 2660 3655 1491 2659 3656 1490 2628 3657 1447 2627 3658 1448 2658 3659 1492 2648 3660 1488 2628 3657 1447 2657 3661 1493 2657 3661 1493 2628 3657 1447 2658 3659 1492 2642 3662 1475 2641 3663 1476 2655 3664 1494 2641 3663 1476 2630 3665 1451 2655 3664 1494 2655 3664 1494 2630 3665 1451 2656 3666 1495 2630 3665 1451 2629 3667 1452 2656 3666 1495 2625 3668 1444 2642 3662 1475 2654 3669 1496 2654 3669 1496 2642 3662 1475 2655 3664 1494 2624 3670 1439 2623 3671 1440 2650 3673 1497 2650 3673 1497 2623 3671 1440 2651 3672 1498 2627 3658 1448 2635 3674 1462 2658 3659 1492 2658 3659 1492 2635 3674 1462 2659 3656 1490 2635 3674 1462 2647 3653 1486 2659 3656 1490 2636 3675 1466 2646 3676 1485 2652 3677 1499 2639 3678 1469 2638 3679 1470 2649 3680 1500 2632 3681 1455 2631 3682 1456 2661 3683 1501 2643 3684 1480 2632 3681 1455 2660 3655 1491 2660 3655 1491 2632 3681 1455 2661 3683 1501 2633 3685 1460 2626 3686 1443 2653 3687 1502 2653 3687 1502 2626 3686 1443 2654 3669 1496 2638 3679 1470 2640 3688 1473 2649 3680 1500 2649 3680 1500 2640 3688 1473 2650 3673 1497 2645 3689 1482 2657 3661 1493 2629 3667 1452 2629 3667 1452 2657 3661 1493 2656 3666 1495 2644 3654 1479 2643 3684 1480 2660 3655 1491 2623 3671 1440 2637 3690 1465 2651 3672 1498 2634 3691 1459 2633 3685 1460 2653 3687 1502 2646 3676 1485 2634 3691 1459 2652 3677 1499 2652 3677 1499 2634 3691 1459 2653 3687 1502 2639 3678 1469 2649 3680 1500 2631 3682 1456 2631 3682 1456 2649 3680 1500 2661 3683 1501 2645 3689 1482 2648 3660 1488 2657 3661 1493 2626 3686 1443 2625 3668 1444 2654 3669 1496 2640 3688 1473 2624 3670 1439 2650 3673 1497 2636 3675 1466 2652 3677 1499 2637 3690 1465 2637 3690 1465 2652 3677 1499 2651 3672 1498 2658 3659 1492 2659 3656 1490 2663 3693 1503 2663 3693 1503 2659 3656 1490 2662 3692 1504 2655 3664 1494 2656 3666 1495 2665 3695 1505 2665 3695 1505 2656 3666 1495 2664 3694 1506 2652 3677 1499 2666 3696 1508 2651 3672 1498 2651 3672 1498 2666 3696 1508 2667 3697 1507 2650 3673 1497 2651 3672 1498 2668 3698 1509 2668 3698 1509 2651 3672 1498 2667 3697 1507 2653 3687 1502 2654 3669 1496 2670 3700 1510 2670 3700 1510 2654 3669 1496 2669 3699 1511 2654 3669 1496 2655 3664 1494 2669 3699 1511 2669 3699 1511 2655 3664 1494 2665 3695 1505 2657 3661 1493 2671 3701 1512 2656 3666 1495 2656 3666 1495 2671 3701 1512 2664 3694 1506 2652 3677 1499 2653 3687 1502 2666 3696 1508 2666 3696 1508 2653 3687 1502 2670 3700 1510 2657 3661 1493 2658 3659 1492 2671 3701 1512 2671 3701 1512 2658 3659 1492 2663 3693 1503 2660 3655 1491 2672 3702 1513 2659 3656 1490 2659 3656 1490 2672 3702 1513 2662 3692 1504 2649 3680 1500 2650 3673 1497 2673 3703 1514 2673 3703 1514 2650 3673 1497 2668 3698 1509 2649 3680 1500 2673 3703 1514 2661 3683 1501 2661 3683 1501 2673 3703 1514 2674 3704 1515 2660 3655 1491 2661 3683 1501 2672 3702 1513 2672 3702 1513 2661 3683 1501 2674 3704 1515 2675 3705 1516 2665 3695 1505 2671 3701 1512 2671 3701 1512 2665 3695 1505 2664 3694 1506 2667 3697 1507 2666 3696 1508 2675 3705 1516 2675 3705 1516 2666 3696 1508 2670 3700 1510 2667 3697 1507 2675 3705 1516 2668 3698 1509 2675 3705 1516 2673 3703 1514 2668 3698 1509 2672 3702 1513 2674 3704 1515 2675 3705 1516 2675 3705 1516 2674 3704 1515 2673 3703 1514 2671 3701 1512 2663 3693 1503 2675 3705 1516 2662 3692 1504 2672 3702 1513 2663 3693 1503 2663 3693 1503 2672 3702 1513 2675 3705 1516 2675 3705 1516 2670 3700 1510 2665 3695 1505 2665 3695 1505 2670 3700 1510 2669 3699 1511</p>
+ </triangles>
+ <triangles material="HeadphonesSG5" count="832">
+ <input semantic="VERTEX" source="#Headphones-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Headphones-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Headphones-headphonesUV" offset="2" set="1"/>
+ <p>709 1860 1517 710 1861 1518 735 1863 1520 735 1863 1520 710 1861 1518 736 1862 1519 710 1861 1521 711 1864 1522 736 1862 1519 736 1862 1519 711 1864 1522 737 1865 1523 712 1866 1525 738 1867 1526 711 1864 1524 711 1864 1524 738 1867 1526 737 1865 1523 713 1868 1528 739 1869 1529 712 1866 1527 712 1866 1527 739 1869 1529 738 1867 1526 714 1870 1531 740 1871 1532 713 1868 1530 713 1868 1530 740 1871 1532 739 1869 1529 714 1870 1533 715 1872 1534 740 1871 1532 740 1871 1532 715 1872 1534 741 1873 1535 715 1872 1536 716 1874 1537 741 1873 1535 741 1873 1535 716 1874 1537 742 1875 1538 716 1874 1539 717 1876 1540 742 1875 1538 742 1875 1538 717 1876 1540 743 1877 1541 717 1876 1542 718 1878 1543 743 1877 1541 743 1877 1541 718 1878 1543 744 1879 1544 718 1878 1545 719 1880 1546 744 1879 1544 744 1879 1544 719 1880 1546 745 1881 1547 719 1880 1548 720 1882 1549 745 1881 1547 745 1881 1547 720 1882 1549 746 1883 1550 720 1882 1551 721 1884 1552 746 1883 1550 746 1883 1550 721 1884 1552 747 1885 1553 721 1884 1554 722 1886 1555 747 1885 1553 747 1885 1553 722 1886 1555 748 1887 1556 722 1886 1557 723 1888 1558 748 1887 1556 748 1887 1556 723 1888 1558 749 1889 1559 723 1888 1560 724 1890 1561 749 1889 1559 749 1889 1559 724 1890 1561 750 1891 1562 724 1890 1563 725 1892 1564 750 1891 1562 750 1891 1562 725 1892 1564 751 1893 1565 725 1892 1566 726 1894 1567 751 1893 1565 751 1893 1565 726 1894 1567 752 1895 1568 726 1894 1569 727 1896 1570 752 1895 1568 752 1895 1568 727 1896 1570 753 1897 1571 727 1896 1572 728 1898 1573 753 1897 1571 753 1897 1571 728 1898 1573 754 1899 1574 728 1898 1575 729 1900 1576 754 1899 1574 754 1899 1574 729 1900 1576 755 1901 1577 729 1900 1578 730 1902 1579 755 1901 1577 755 1901 1577 730 1902 1579 756 1903 1580 730 1902 1581 731 1904 1582 756 1903 1580 756 1903 1580 731 1904 1582 757 1905 1583 708 1906 1585 734 1907 1586 731 1904 1584 731 1904 1584 734 1907 1586 757 1905 1583 707 1908 1588 733 1909 1589 708 1906 1587 708 1906 1587 733 1909 1589 734 1907 1586 706 1910 1591 732 1911 1592 707 1908 1590 707 1908 1590 732 1911 1592 733 1909 1589 706 1910 1593 709 1860 1594 732 1911 1592 732 1911 1592 709 1860 1594 735 1863 1520 733 1912 1589 732 1913 1592 759 1915 1596 759 1915 1596 732 1913 1592 758 1914 1595 735 1916 1520 761 1917 1597 732 1913 1592 732 1913 1592 761 1917 1597 758 1914 1595 736 1918 1519 762 1919 1598 735 1916 1520 735 1916 1520 762 1919 1598 761 1917 1597 736 1918 1519 737 1920 1523 762 1919 1598 762 1919 1598 737 1920 1523 763 1921 1599 737 1920 1523 738 1922 1526 763 1921 1599 763 1921 1599 738 1922 1526 764 1923 1600 738 1922 1526 739 1924 1529 764 1923 1600 764 1923 1600 739 1924 1529 765 1925 1601 739 1924 1529 740 1926 1532 765 1925 1601 765 1925 1601 740 1926 1532 766 1927 1602 741 1928 1535 767 1929 1603 740 1926 1532 740 1926 1532 767 1929 1603 766 1927 1602 741 1928 1535 742 1930 1538 767 1929 1603 767 1929 1603 742 1930 1538 768 1931 1604 742 1930 1538 743 1932 1541 768 1931 1604 768 1931 1604 743 1932 1541 769 1933 1605 743 1932 1541 744 1934 1544 769 1933 1605 769 1933 1605 744 1934 1544 770 1935 1606 744 1934 1544 745 1936 1547 770 1935 1606 770 1935 1606 745 1936 1547 771 1937 1607 745 1936 1547 746 1938 1550 771 1937 1607 771 1937 1607 746 1938 1550 772 1939 1608 746 1938 1550 747 1940 1553 772 1939 1608 772 1939 1608 747 1940 1553 773 1941 1609 747 1940 1553 748 1942 1556 773 1941 1609 773 1941 1609 748 1942 1556 774 1943 1610 748 1942 1556 749 1944 1559 774 1943 1610 774 1943 1610 749 1944 1559 775 1945 1611 749 1944 1559 750 1946 1562 775 1945 1611 775 1945 1611 750 1946 1562 776 1947 1612 750 1946 1562 751 1948 1565 776 1947 1612 776 1947 1612 751 1948 1565 777 1949 1613 751 1948 1565 752 1950 1568 777 1949 1613 777 1949 1613 752 1950 1568 778 1951 1614 752 1950 1568 753 1952 1571 778 1951 1614 778 1951 1614 753 1952 1571 779 1953 1615 753 1952 1571 754 1954 1574 779 1953 1615 779 1953 1615 754 1954 1574 780 1955 1616 754 1954 1574 755 1956 1577 780 1955 1616 780 1955 1616 755 1956 1577 781 1957 1617 755 1956 1577 756 1958 1580 781 1957 1617 781 1957 1617 756 1958 1580 782 1959 1618 756 1958 1580 757 1960 1583 782 1959 1618 782 1959 1618 757 1960 1583 783 1961 1619 757 1960 1583 734 1962 1586 783 1961 1619 783 1961 1619 734 1962 1586 760 1963 1620 734 1962 1586 733 1912 1589 760 1963 1620 760 1963 1620 733 1912 1589 759 1915 1596 781 1957 1617 782 1959 1618 807 1965 1622 807 1965 1622 782 1959 1618 808 1964 1621 782 1959 1618 783 1961 1619 808 1964 1621 808 1964 1621 783 1961 1619 809 1966 1623 783 1961 1619 760 1963 1620 809 1966 1623 809 1966 1623 760 1963 1620 786 1967 1624 760 1963 1620 759 1915 1596 786 1967 1624 786 1967 1624 759 1915 1596 785 1968 1625 759 1915 1596 758 1914 1595 785 1968 1625 785 1968 1625 758 1914 1595 784 1969 1626 761 1917 1597 787 1970 1627 758 1914 1595 758 1914 1595 787 1970 1627 784 1969 1626 762 1919 1598 788 1971 1628 761 1917 1597 761 1917 1597 788 1971 1628 787 1970 1627 763 1921 1599 789 1972 1629 762 1919 1598 762 1919 1598 789 1972 1629 788 1971 1628 763 1921 1599 764 1923 1600 789 1972 1629 789 1972 1629 764 1923 1600 790 1973 1630 764 1923 1600 765 1925 1601 790 1973 1630 790 1973 1630 765 1925 1601 791 1974 1631 765 1925 1601 766 1927 1602 791 1974 1631 791 1974 1631 766 1927 1602 792 1975 1632 767 1929 1603 793 1976 1633 766 1927 1602 766 1927 1602 793 1976 1633 792 1975 1632 768 1931 1604 794 1977 1634 767 1929 1603 767 1929 1603 794 1977 1634 793 1976 1633 769 1933 1605 795 1978 1635 768 1931 1604 768 1931 1604 795 1978 1635 794 1977 1634 769 1933 1605 770 1935 1606 795 1978 1635 795 1978 1635 770 1935 1606 796 1979 1636 770 1935 1606 771 1937 1607 796 1979 1636 796 1979 1636 771 1937 1607 797 1980 1637 771 1937 1607 772 1939 1608 797 1980 1637 797 1980 1637 772 1939 1608 798 1981 1638 772 1939 1608 773 1941 1609 798 1981 1638 798 1981 1638 773 1941 1609 799 1982 1639 773 1941 1609 774 1943 1610 799 1982 1639 799 1982 1639 774 1943 1610 800 1983 1640 774 1943 1610 775 1945 1611 800 1983 1640 800 1983 1640 775 1945 1611 801 1984 1641 775 1945 1611 776 1947 1612 801 1984 1641 801 1984 1641 776 1947 1612 802 1985 1642 776 1947 1612 777 1949 1613 802 1985 1642 802 1985 1642 777 1949 1613 803 1986 1643 777 1949 1613 778 1951 1614 803 1986 1643 803 1986 1643 778 1951 1614 804 1987 1644 778 1951 1614 779 1953 1615 804 1987 1644 804 1987 1644 779 1953 1615 805 1988 1645 779 1953 1615 780 1955 1616 805 1988 1645 805 1988 1645 780 1955 1616 806 1989 1646 780 1955 1616 781 1957 1617 806 1989 1646 806 1989 1646 781 1957 1617 807 1965 1622 785 1968 1625 784 1969 1626 811 1991 1648 811 1991 1648 784 1969 1626 810 1990 1647 787 1970 1627 813 1992 1649 784 1969 1626 784 1969 1626 813 1992 1649 810 1990 1647 788 1971 1628 814 1993 1650 787 1970 1627 787 1970 1627 814 1993 1650 813 1992 1649 789 1972 1629 815 1994 1651 788 1971 1628 788 1971 1628 815 1994 1651 814 1993 1650 789 1972 1629 790 1973 1630 815 1994 1651 815 1994 1651 790 1973 1630 816 1995 1652 790 1973 1630 791 1974 1631 816 1995 1652 816 1995 1652 791 1974 1631 817 1996 1653 791 1974 1631 792 1975 1632 817 1996 1653 817 1996 1653 792 1975 1632 818 1997 1654 793 1976 1633 819 1998 1655 792 1975 1632 792 1975 1632 819 1998 1655 818 1997 1654 794 1977 1634 820 1999 1656 793 1976 1633 793 1976 1633 820 1999 1656 819 1998 1655 795 1978 1635 821 2000 1657 794 1977 1634 794 1977 1634 821 2000 1657 820 1999 1656 795 1978 1635 796 1979 1636 821 2000 1657 821 2000 1657 796 1979 1636 822 2001 1658 796 1979 1636 797 1980 1637 822 2001 1658 822 2001 1658 797 1980 1637 823 2002 1659 797 1980 1637 798 1981 1638 823 2002 1659 823 2002 1659 798 1981 1638 824 2003 1660 798 1981 1638 799 1982 1639 824 2003 1660 824 2003 1660 799 1982 1639 825 2004 1661 799 1982 1639 800 1983 1640 825 2004 1661 825 2004 1661 800 1983 1640 826 2005 1662 800 1983 1640 801 1984 1641 826 2005 1662 826 2005 1662 801 1984 1641 827 2006 1663 801 1984 1641 802 1985 1642 827 2006 1663 827 2006 1663 802 1985 1642 828 2007 1664 802 1985 1642 803 1986 1643 828 2007 1664 828 2007 1664 803 1986 1643 829 2008 1665 803 1986 1643 804 1987 1644 829 2008 1665 829 2008 1665 804 1987 1644 830 2009 1666 804 1987 1644 805 1988 1645 830 2009 1666 830 2009 1666 805 1988 1645 831 2010 1667 805 1988 1645 806 1989 1646 831 2010 1667 831 2010 1667 806 1989 1646 832 2011 1668 806 1989 1646 807 1965 1622 832 2011 1668 832 2011 1668 807 1965 1622 833 2012 1669 807 1965 1622 808 1964 1621 833 2012 1669 833 2012 1669 808 1964 1621 834 2013 1670 808 1964 1621 809 1966 1623 834 2013 1670 834 2013 1670 809 1966 1623 835 2014 1671 809 1966 1623 786 1967 1624 835 2014 1671 835 2014 1671 786 1967 1624 812 2015 1672 786 1967 1624 785 1968 1625 812 2015 1672 812 2015 1672 785 1968 1625 811 1991 1648 814 1993 1650 840 2016 1673 813 1992 1649 813 1992 1649 840 2016 1673 839 2017 1674 815 1994 1651 841 2018 1675 814 1993 1650 814 1993 1650 841 2018 1675 840 2016 1673 815 1994 1651 816 1995 1652 841 2018 1675 841 2018 1675 816 1995 1652 842 2019 1676 816 1995 1652 817 1996 1653 842 2019 1676 842 2019 1676 817 1996 1653 843 2020 1677 817 1996 1653 818 1997 1654 843 2020 1677 843 2020 1677 818 1997 1654 844 2021 1678 819 1998 1655 845 2022 1679 818 1997 1654 818 1997 1654 845 2022 1679 844 2021 1678 820 1999 1656 846 2023 1680 819 1998 1655 819 1998 1655 846 2023 1680 845 2022 1679 821 2000 1657 847 2024 1681 820 1999 1656 820 1999 1656 847 2024 1681 846 2023 1680 821 2000 1657 822 2001 1658 847 2024 1681 847 2024 1681 822 2001 1658 848 2025 1682 822 2001 1658 823 2002 1659 848 2025 1682 848 2025 1682 823 2002 1659 849 2026 1683 823 2002 1659 824 2003 1660 849 2026 1683 849 2026 1683 824 2003 1660 850 2027 1684 824 2003 1660 825 2004 1661 850 2027 1684 850 2027 1684 825 2004 1661 851 2028 1685 825 2004 1661 826 2005 1662 851 2028 1685 851 2028 1685 826 2005 1662 852 2029 1686 826 2005 1662 827 2006 1663 852 2029 1686 852 2029 1686 827 2006 1663 853 2030 1687 827 2006 1663 828 2007 1664 853 2030 1687 853 2030 1687 828 2007 1664 854 2031 1688 828 2007 1664 829 2008 1665 854 2031 1688 854 2031 1688 829 2008 1665 855 2032 1689 829 2008 1665 830 2009 1666 855 2032 1689 855 2032 1689 830 2009 1666 856 2033 1690 830 2009 1666 831 2010 1667 856 2033 1690 856 2033 1690 831 2010 1667 857 2034 1691 831 2010 1667 832 2011 1668 857 2034 1691 857 2034 1691 832 2011 1668 858 2035 1692 832 2011 1668 833 2012 1669 858 2035 1692 858 2035 1692 833 2012 1669 859 2036 1693 833 2012 1669 834 2013 1670 859 2036 1693 859 2036 1693 834 2013 1670 860 2037 1694 834 2013 1670 835 2014 1671 860 2037 1694 860 2037 1694 835 2014 1671 861 2038 1695 835 2014 1671 812 2015 1672 861 2038 1695 861 2038 1695 812 2015 1672 838 2039 1696 812 2015 1672 811 1991 1648 838 2039 1696 838 2039 1696 811 1991 1648 837 2040 1697 811 1991 1648 810 1990 1647 837 2040 1697 837 2040 1697 810 1990 1647 836 2041 1698 813 1992 1649 839 2017 1674 810 1990 1647 810 1990 1647 839 2017 1674 836 2041 1698 837 2040 1697 836 2041 1698 863 2043 1700 863 2043 1700 836 2041 1698 862 2042 1699 839 2017 1674 865 2044 1701 836 2041 1698 836 2041 1698 865 2044 1701 862 2042 1699 840 2016 1673 866 2045 1702 839 2017 1674 839 2017 1674 866 2045 1702 865 2044 1701 841 2018 1675 867 2046 1703 840 2016 1673 840 2016 1673 867 2046 1703 866 2045 1702 841 2018 1675 842 2019 1676 867 2046 1703 867 2046 1703 842 2019 1676 868 2047 1704 842 2019 1676 843 2020 1677 868 2047 1704 868 2047 1704 843 2020 1677 869 2048 1705 843 2020 1677 844 2021 1678 869 2048 1705 869 2048 1705 844 2021 1678 870 2049 1706 845 2022 1679 871 2050 1707 844 2021 1678 844 2021 1678 871 2050 1707 870 2049 1706 846 2023 1680 872 2051 1708 845 2022 1679 845 2022 1679 872 2051 1708 871 2050 1707 847 2024 1681 873 2052 1709 846 2023 1680 846 2023 1680 873 2052 1709 872 2051 1708 847 2024 1681 848 2025 1682 873 2052 1709 873 2052 1709 848 2025 1682 874 2053 1710 848 2025 1682 849 2026 1683 874 2053 1710 874 2053 1710 849 2026 1683 875 2054 1711 849 2026 1683 850 2027 1684 875 2054 1711 875 2054 1711 850 2027 1684 876 2055 1712 850 2027 1684 851 2028 1685 876 2055 1712 876 2055 1712 851 2028 1685 877 2056 1713 851 2028 1685 852 2029 1686 877 2056 1713 877 2056 1713 852 2029 1686 878 2057 1714 852 2029 1686 853 2030 1687 878 2057 1714 878 2057 1714 853 2030 1687 879 2058 1715 853 2030 1687 854 2031 1688 879 2058 1715 879 2058 1715 854 2031 1688 880 2059 1716 854 2031 1688 855 2032 1689 880 2059 1716 880 2059 1716 855 2032 1689 881 2060 1717 855 2032 1689 856 2033 1690 881 2060 1717 881 2060 1717 856 2033 1690 882 2061 1718 856 2033 1690 857 2034 1691 882 2061 1718 882 2061 1718 857 2034 1691 883 2062 1719 857 2034 1691 858 2035 1692 883 2062 1719 883 2062 1719 858 2035 1692 884 2063 1720 858 2035 1692 859 2036 1693 884 2063 1720 884 2063 1720 859 2036 1693 885 2064 1721 859 2036 1693 860 2037 1694 885 2064 1721 885 2064 1721 860 2037 1694 886 2065 1722 860 2037 1694 861 2038 1695 886 2065 1722 886 2065 1722 861 2038 1695 887 2066 1723 861 2038 1695 838 2039 1696 887 2066 1723 887 2066 1723 838 2039 1696 864 2067 1724 838 2039 1696 837 2040 1697 864 2067 1724 864 2067 1724 837 2040 1697 863 2043 1700 872 2051 1708 898 2068 1725 871 2050 1707 871 2050 1707 898 2068 1725 897 2069 1726 873 2052 1709 899 2070 1727 872 2051 1708 872 2051 1708 899 2070 1727 898 2068 1725 873 2052 1709 874 2053 1710 899 2070 1727 899 2070 1727 874 2053 1710 900 2071 1728 874 2053 1710 875 2054 1711 900 2071 1728 900 2071 1728 875 2054 1711 901 2072 1729 875 2054 1711 876 2055 1712 901 2072 1729 901 2072 1729 876 2055 1712 902 2073 1730 876 2055 1712 877 2056 1713 902 2073 1730 902 2073 1730 877 2056 1713 903 2074 1731 877 2056 1713 878 2057 1714 903 2074 1731 903 2074 1731 878 2057 1714 904 2075 1732 878 2057 1714 879 2058 1715 904 2075 1732 904 2075 1732 879 2058 1715 905 2076 1733 879 2058 1715 880 2059 1716 905 2076 1733 905 2076 1733 880 2059 1716 906 2077 1734 880 2059 1716 881 2060 1717 906 2077 1734 906 2077 1734 881 2060 1717 907 2078 1735 881 2060 1717 882 2061 1718 907 2078 1735 907 2078 1735 882 2061 1718 908 2079 1736 882 2061 1718 883 2062 1719 908 2079 1736 908 2079 1736 883 2062 1719 909 2080 1737 883 2062 1719 884 2063 1720 909 2080 1737 909 2080 1737 884 2063 1720 910 2081 1738 884 2063 1720 885 2064 1721 910 2081 1738 910 2081 1738 885 2064 1721 911 2082 1739 885 2064 1721 886 2065 1722 911 2082 1739 911 2082 1739 886 2065 1722 912 2083 1740 886 2065 1722 887 2066 1723 912 2083 1740 912 2083 1740 887 2066 1723 913 2084 1741 887 2066 1723 864 2067 1724 913 2084 1741 913 2084 1741 864 2067 1724 890 2085 1742 864 2067 1724 863 2043 1700 890 2085 1742 890 2085 1742 863 2043 1700 889 2086 1743 863 2043 1700 862 2042 1699 889 2086 1743 889 2086 1743 862 2042 1699 888 2087 1744 865 2044 1701 891 2088 1745 862 2042 1699 862 2042 1699 891 2088 1745 888 2087 1744 866 2045 1702 892 2089 1746 865 2044 1701 865 2044 1701 892 2089 1746 891 2088 1745 867 2046 1703 893 2090 1747 866 2045 1702 866 2045 1702 893 2090 1747 892 2089 1746 867 2046 1703 868 2047 1704 893 2090 1747 893 2090 1747 868 2047 1704 894 2091 1748 868 2047 1704 869 2048 1705 894 2091 1748 894 2091 1748 869 2048 1705 895 2092 1749 869 2048 1705 870 2049 1706 895 2092 1749 895 2092 1749 870 2049 1706 896 2093 1750 871 2050 1707 897 2069 1726 870 2049 1706 870 2049 1706 897 2069 1726 896 2093 1750 900 2094 1728 901 2095 1729 926 2097 1752 926 2097 1752 901 2095 1729 927 2096 1751 901 2095 1729 902 2098 1730 927 2096 1751 927 2096 1751 902 2098 1730 928 2099 1753 902 2098 1730 903 2100 1731 928 2099 1753 928 2099 1753 903 2100 1731 929 2101 1754 903 2100 1731 904 2102 1732 929 2101 1754 929 2101 1754 904 2102 1732 930 2103 1755 904 2102 1732 905 2104 1733 930 2103 1755 930 2103 1755 905 2104 1733 931 2105 1756 905 2104 1733 906 2106 1734 931 2105 1756 931 2105 1756 906 2106 1734 932 2107 1757 906 2106 1734 907 2108 1735 932 2107 1757 932 2107 1757 907 2108 1735 933 2109 1758 907 2108 1735 908 2110 1736 933 2109 1758 933 2109 1758 908 2110 1736 934 2111 1759 908 2110 1736 909 2112 1737 934 2111 1759 934 2111 1759 909 2112 1737 935 2113 1760 909 2112 1737 910 2114 1738 935 2113 1760 935 2113 1760 910 2114 1738 936 2115 1761 910 2114 1738 911 2116 1739 936 2115 1761 936 2115 1761 911 2116 1739 937 2117 1762 911 2116 1739 912 2118 1740 937 2117 1762 937 2117 1762 912 2118 1740 938 2119 1763 912 2118 1740 913 2120 1741 938 2119 1763 938 2119 1763 913 2120 1741 939 2121 1764 890 2122 1742 916 2123 1765 913 2120 1741 913 2120 1741 916 2123 1765 939 2121 1764 889 2124 1743 915 2125 1766 890 2122 1742 890 2122 1742 915 2125 1766 916 2123 1765 888 2126 1744 914 2127 1767 889 2124 1743 889 2124 1743 914 2127 1767 915 2125 1766 888 2126 1744 891 2128 1745 914 2127 1767 914 2127 1767 891 2128 1745 917 2129 1768 891 2128 1745 892 2130 1746 917 2129 1768 917 2129 1768 892 2130 1746 918 2131 1769 892 2130 1746 893 2132 1747 918 2131 1769 918 2131 1769 893 2132 1747 919 2133 1770 894 2134 1748 920 2135 1771 893 2132 1747 893 2132 1747 920 2135 1771 919 2133 1770 895 2136 1749 921 2137 1772 894 2134 1748 894 2134 1748 921 2137 1772 920 2135 1771 896 2138 1750 922 2139 1773 895 2136 1749 895 2136 1749 922 2139 1773 921 2137 1772 896 2138 1750 897 2140 1726 922 2139 1773 922 2139 1773 897 2140 1726 923 2141 1774 897 2140 1726 898 2142 1725 923 2141 1774 923 2141 1774 898 2142 1725 924 2143 1775 898 2142 1725 899 2144 1727 924 2143 1775 924 2143 1775 899 2144 1727 925 2145 1776 899 2144 1727 900 2094 1728 925 2145 1776 925 2145 1776 900 2094 1728 926 2097 1752 2366 3706 1777 2392 3707 1520 2367 3709 1778 2367 3709 1778 2392 3707 1520 2393 3708 1519 2367 3709 1779 2393 3708 1519 2368 3711 1780 2368 3711 1780 2393 3708 1519 2394 3710 1523 2394 3710 1523 2395 3712 1526 2368 3711 1781 2368 3711 1781 2395 3712 1526 2369 3713 1782 2395 3712 1526 2396 3714 1529 2369 3713 1783 2369 3713 1783 2396 3714 1529 2370 3715 1784 2396 3714 1529 2397 3716 1532 2370 3715 1785 2370 3715 1785 2397 3716 1532 2371 3717 1786 2371 3717 1787 2397 3716 1532 2372 3719 1788 2372 3719 1788 2397 3716 1532 2398 3718 1535 2372 3719 1789 2398 3718 1535 2373 3721 1790 2373 3721 1790 2398 3718 1535 2399 3720 1538 2373 3721 1791 2399 3720 1538 2374 3723 1792 2374 3723 1792 2399 3720 1538 2400 3722 1541 2374 3723 1793 2400 3722 1541 2375 3725 1794 2375 3725 1794 2400 3722 1541 2401 3724 1544 2375 3725 1795 2401 3724 1544 2376 3727 1796 2376 3727 1796 2401 3724 1544 2402 3726 1547 2376 3727 1797 2402 3726 1547 2377 3729 1798 2377 3729 1798 2402 3726 1547 2403 3728 1550 2377 3729 1799 2403 3728 1550 2378 3731 1800 2378 3731 1800 2403 3728 1550 2404 3730 1553 2378 3731 1801 2404 3730 1553 2379 3733 1802 2379 3733 1802 2404 3730 1553 2405 3732 1556 2379 3733 1803 2405 3732 1556 2380 3735 1804 2380 3735 1804 2405 3732 1556 2406 3734 1559 2380 3735 1805 2406 3734 1559 2381 3737 1806 2381 3737 1806 2406 3734 1559 2407 3736 1562 2381 3737 1807 2407 3736 1562 2382 3739 1808 2382 3739 1808 2407 3736 1562 2408 3738 1565 2382 3739 1809 2408 3738 1565 2383 3741 1810 2383 3741 1810 2408 3738 1565 2409 3740 1568 2383 3741 1811 2409 3740 1568 2384 3743 1812 2384 3743 1812 2409 3740 1568 2410 3742 1571 2384 3743 1813 2410 3742 1571 2385 3745 1814 2385 3745 1814 2410 3742 1571 2411 3744 1574 2385 3745 1815 2411 3744 1574 2386 3747 1816 2386 3747 1816 2411 3744 1574 2412 3746 1577 2386 3747 1817 2412 3746 1577 2387 3749 1818 2387 3749 1818 2412 3746 1577 2413 3748 1580 2387 3749 1819 2413 3748 1580 2388 3751 1820 2388 3751 1820 2413 3748 1580 2414 3750 1583 2414 3750 1583 2391 3752 1586 2388 3751 1821 2388 3751 1821 2391 3752 1586 2365 3753 1822 2391 3752 1586 2390 3754 1589 2365 3753 1823 2365 3753 1823 2390 3754 1589 2364 3755 1824 2390 3754 1589 2389 3756 1592 2364 3755 1825 2364 3755 1825 2389 3756 1592 2363 3757 1826 2363 3757 1827 2389 3756 1592 2366 3706 1828 2366 3706 1828 2389 3756 1592 2392 3707 1520 2390 3758 1589 2416 3759 1596 2389 3761 1592 2389 3761 1592 2416 3759 1596 2415 3760 1595 2415 3760 1595 2418 3762 1597 2389 3761 1592 2389 3761 1592 2418 3762 1597 2392 3763 1520 2418 3762 1597 2419 3764 1598 2392 3763 1520 2392 3763 1520 2419 3764 1598 2393 3765 1519 2393 3765 1519 2419 3764 1598 2394 3767 1523 2394 3767 1523 2419 3764 1598 2420 3766 1599 2394 3767 1523 2420 3766 1599 2395 3769 1526 2395 3769 1526 2420 3766 1599 2421 3768 1600 2395 3769 1526 2421 3768 1600 2396 3771 1529 2396 3771 1529 2421 3768 1600 2422 3770 1601 2396 3771 1529 2422 3770 1601 2397 3773 1532 2397 3773 1532 2422 3770 1601 2423 3772 1602 2423 3772 1602 2424 3774 1603 2397 3773 1532 2397 3773 1532 2424 3774 1603 2398 3775 1535 2398 3775 1535 2424 3774 1603 2399 3777 1538 2399 3777 1538 2424 3774 1603 2425 3776 1604 2399 3777 1538 2425 3776 1604 2400 3779 1541 2400 3779 1541 2425 3776 1604 2426 3778 1605 2400 3779 1541 2426 3778 1605 2401 3781 1544 2401 3781 1544 2426 3778 1605 2427 3780 1606 2401 3781 1544 2427 3780 1606 2402 3783 1547 2402 3783 1547 2427 3780 1606 2428 3782 1607 2402 3783 1547 2428 3782 1607 2403 3785 1550 2403 3785 1550 2428 3782 1607 2429 3784 1608 2403 3785 1550 2429 3784 1608 2404 3787 1553 2404 3787 1553 2429 3784 1608 2430 3786 1609 2404 3787 1553 2430 3786 1609 2405 3789 1556 2405 3789 1556 2430 3786 1609 2431 3788 1610 2405 3789 1556 2431 3788 1610 2406 3791 1559 2406 3791 1559 2431 3788 1610 2432 3790 1611 2406 3791 1559 2432 3790 1611 2407 3793 1562 2407 3793 1562 2432 3790 1611 2433 3792 1612 2407 3793 1562 2433 3792 1612 2408 3795 1565 2408 3795 1565 2433 3792 1612 2434 3794 1613 2408 3795 1565 2434 3794 1613 2409 3797 1568 2409 3797 1568 2434 3794 1613 2435 3796 1614 2409 3797 1568 2435 3796 1614 2410 3799 1571 2410 3799 1571 2435 3796 1614 2436 3798 1615 2410 3799 1571 2436 3798 1615 2411 3801 1574 2411 3801 1574 2436 3798 1615 2437 3800 1616 2411 3801 1574 2437 3800 1616 2412 3803 1577 2412 3803 1577 2437 3800 1616 2438 3802 1617 2412 3803 1577 2438 3802 1617 2413 3805 1580 2413 3805 1580 2438 3802 1617 2439 3804 1618 2413 3805 1580 2439 3804 1618 2414 3807 1583 2414 3807 1583 2439 3804 1618 2440 3806 1619 2414 3807 1583 2440 3806 1619 2391 3809 1586 2391 3809 1586 2440 3806 1619 2417 3808 1620 2391 3809 1586 2417 3808 1620 2390 3758 1589 2390 3758 1589 2417 3808 1620 2416 3759 1596 2438 3802 1617 2464 3810 1622 2439 3804 1618 2439 3804 1618 2464 3810 1622 2465 3811 1621 2439 3804 1618 2465 3811 1621 2440 3806 1619 2440 3806 1619 2465 3811 1621 2466 3812 1623 2440 3806 1619 2466 3812 1623 2417 3808 1620 2417 3808 1620 2466 3812 1623 2443 3813 1624 2417 3808 1620 2443 3813 1624 2416 3759 1596 2416 3759 1596 2443 3813 1624 2442 3814 1625 2416 3759 1596 2442 3814 1625 2415 3760 1595 2415 3760 1595 2442 3814 1625 2441 3815 1626 2441 3815 1626 2444 3816 1627 2415 3760 1595 2415 3760 1595 2444 3816 1627 2418 3762 1597 2444 3816 1627 2445 3817 1628 2418 3762 1597 2418 3762 1597 2445 3817 1628 2419 3764 1598 2445 3817 1628 2446 3818 1629 2419 3764 1598 2419 3764 1598 2446 3818 1629 2420 3766 1599 2420 3766 1599 2446 3818 1629 2421 3768 1600 2421 3768 1600 2446 3818 1629 2447 3819 1630 2421 3768 1600 2447 3819 1630 2422 3770 1601 2422 3770 1601 2447 3819 1630 2448 3820 1631 2422 3770 1601 2448 3820 1631 2423 3772 1602 2423 3772 1602 2448 3820 1631 2449 3821 1632 2449 3821 1632 2450 3822 1633 2423 3772 1602 2423 3772 1602 2450 3822 1633 2424 3774 1603 2450 3822 1633 2451 3823 1634 2424 3774 1603 2424 3774 1603 2451 3823 1634 2425 3776 1604 2451 3823 1634 2452 3824 1635 2425 3776 1604 2425 3776 1604 2452 3824 1635 2426 3778 1605 2426 3778 1605 2452 3824 1635 2427 3780 1606 2427 3780 1606 2452 3824 1635 2453 3825 1636 2427 3780 1606 2453 3825 1636 2428 3782 1607 2428 3782 1607 2453 3825 1636 2454 3826 1637 2428 3782 1607 2454 3826 1637 2429 3784 1608 2429 3784 1608 2454 3826 1637 2455 3827 1638 2429 3784 1608 2455 3827 1638 2430 3786 1609 2430 3786 1609 2455 3827 1638 2456 3828 1639 2430 3786 1609 2456 3828 1639 2431 3788 1610 2431 3788 1610 2456 3828 1639 2457 3829 1640 2431 3788 1610 2457 3829 1640 2432 3790 1611 2432 3790 1611 2457 3829 1640 2458 3830 1641 2432 3790 1611 2458 3830 1641 2433 3792 1612 2433 3792 1612 2458 3830 1641 2459 3831 1642 2433 3792 1612 2459 3831 1642 2434 3794 1613 2434 3794 1613 2459 3831 1642 2460 3832 1643 2434 3794 1613 2460 3832 1643 2435 3796 1614 2435 3796 1614 2460 3832 1643 2461 3833 1644 2435 3796 1614 2461 3833 1644 2436 3798 1615 2436 3798 1615 2461 3833 1644 2462 3834 1645 2436 3798 1615 2462 3834 1645 2437 3800 1616 2437 3800 1616 2462 3834 1645 2463 3835 1646 2437 3800 1616 2463 3835 1646 2438 3802 1617 2438 3802 1617 2463 3835 1646 2464 3810 1622 2442 3814 1625 2468 3836 1648 2441 3815 1626 2441 3815 1626 2468 3836 1648 2467 3837 1647 2467 3837 1647 2470 3838 1649 2441 3815 1626 2441 3815 1626 2470 3838 1649 2444 3816 1627 2470 3838 1649 2471 3839 1650 2444 3816 1627 2444 3816 1627 2471 3839 1650 2445 3817 1628 2471 3839 1650 2472 3840 1651 2445 3817 1628 2445 3817 1628 2472 3840 1651 2446 3818 1629 2446 3818 1629 2472 3840 1651 2447 3819 1630 2447 3819 1630 2472 3840 1651 2473 3841 1652 2447 3819 1630 2473 3841 1652 2448 3820 1631 2448 3820 1631 2473 3841 1652 2474 3842 1653 2448 3820 1631 2474 3842 1653 2449 3821 1632 2449 3821 1632 2474 3842 1653 2475 3843 1654 2475 3843 1654 2476 3844 1655 2449 3821 1632 2449 3821 1632 2476 3844 1655 2450 3822 1633 2476 3844 1655 2477 3845 1656 2450 3822 1633 2450 3822 1633 2477 3845 1656 2451 3823 1634 2477 3845 1656 2478 3846 1657 2451 3823 1634 2451 3823 1634 2478 3846 1657 2452 3824 1635 2452 3824 1635 2478 3846 1657 2453 3825 1636 2453 3825 1636 2478 3846 1657 2479 3847 1658 2453 3825 1636 2479 3847 1658 2454 3826 1637 2454 3826 1637 2479 3847 1658 2480 3848 1659 2454 3826 1637 2480 3848 1659 2455 3827 1638 2455 3827 1638 2480 3848 1659 2481 3849 1660 2455 3827 1638 2481 3849 1660 2456 3828 1639 2456 3828 1639 2481 3849 1660 2482 3850 1661 2456 3828 1639 2482 3850 1661 2457 3829 1640 2457 3829 1640 2482 3850 1661 2483 3851 1662 2457 3829 1640 2483 3851 1662 2458 3830 1641 2458 3830 1641 2483 3851 1662 2484 3852 1663 2458 3830 1641 2484 3852 1663 2459 3831 1642 2459 3831 1642 2484 3852 1663 2485 3853 1664 2459 3831 1642 2485 3853 1664 2460 3832 1643 2460 3832 1643 2485 3853 1664 2486 3854 1665 2460 3832 1643 2486 3854 1665 2461 3833 1644 2461 3833 1644 2486 3854 1665 2487 3855 1666 2461 3833 1644 2487 3855 1666 2462 3834 1645 2462 3834 1645 2487 3855 1666 2488 3856 1667 2462 3834 1645 2488 3856 1667 2463 3835 1646 2463 3835 1646 2488 3856 1667 2489 3857 1668 2463 3835 1646 2489 3857 1668 2464 3810 1622 2464 3810 1622 2489 3857 1668 2490 3858 1669 2464 3810 1622 2490 3858 1669 2465 3811 1621 2465 3811 1621 2490 3858 1669 2491 3859 1670 2465 3811 1621 2491 3859 1670 2466 3812 1623 2466 3812 1623 2491 3859 1670 2492 3860 1671 2466 3812 1623 2492 3860 1671 2443 3813 1624 2443 3813 1624 2492 3860 1671 2469 3861 1672 2443 3813 1624 2469 3861 1672 2442 3814 1625 2442 3814 1625 2469 3861 1672 2468 3836 1648 2496 3862 1674 2497 3863 1673 2470 3838 1649 2470 3838 1649 2497 3863 1673 2471 3839 1650 2497 3863 1673 2498 3864 1675 2471 3839 1650 2471 3839 1650 2498 3864 1675 2472 3840 1651 2472 3840 1651 2498 3864 1675 2473 3841 1652 2473 3841 1652 2498 3864 1675 2499 3865 1676 2473 3841 1652 2499 3865 1676 2474 3842 1653 2474 3842 1653 2499 3865 1676 2500 3866 1677 2474 3842 1653 2500 3866 1677 2475 3843 1654 2475 3843 1654 2500 3866 1677 2501 3867 1678 2501 3867 1678 2502 3868 1679 2475 3843 1654 2475 3843 1654 2502 3868 1679 2476 3844 1655 2502 3868 1679 2503 3869 1680 2476 3844 1655 2476 3844 1655 2503 3869 1680 2477 3845 1656 2503 3869 1680 2504 3870 1681 2477 3845 1656 2477 3845 1656 2504 3870 1681 2478 3846 1657 2478 3846 1657 2504 3870 1681 2479 3847 1658 2479 3847 1658 2504 3870 1681 2505 3871 1682 2479 3847 1658 2505 3871 1682 2480 3848 1659 2480 3848 1659 2505 3871 1682 2506 3872 1683 2480 3848 1659 2506 3872 1683 2481 3849 1660 2481 3849 1660 2506 3872 1683 2507 3873 1684 2481 3849 1660 2507 3873 1684 2482 3850 1661 2482 3850 1661 2507 3873 1684 2508 3874 1685 2482 3850 1661 2508 3874 1685 2483 3851 1662 2483 3851 1662 2508 3874 1685 2509 3875 1686 2483 3851 1662 2509 3875 1686 2484 3852 1663 2484 3852 1663 2509 3875 1686 2510 3876 1687 2484 3852 1663 2510 3876 1687 2485 3853 1664 2485 3853 1664 2510 3876 1687 2511 3877 1688 2485 3853 1664 2511 3877 1688 2486 3854 1665 2486 3854 1665 2511 3877 1688 2512 3878 1689 2486 3854 1665 2512 3878 1689 2487 3855 1666 2487 3855 1666 2512 3878 1689 2513 3879 1690 2487 3855 1666 2513 3879 1690 2488 3856 1667 2488 3856 1667 2513 3879 1690 2514 3880 1691 2488 3856 1667 2514 3880 1691 2489 3857 1668 2489 3857 1668 2514 3880 1691 2515 3881 1692 2489 3857 1668 2515 3881 1692 2490 3858 1669 2490 3858 1669 2515 3881 1692 2516 3882 1693 2490 3858 1669 2516 3882 1693 2491 3859 1670 2491 3859 1670 2516 3882 1693 2517 3883 1694 2491 3859 1670 2517 3883 1694 2492 3860 1671 2492 3860 1671 2517 3883 1694 2518 3884 1695 2492 3860 1671 2518 3884 1695 2469 3861 1672 2469 3861 1672 2518 3884 1695 2495 3885 1696 2469 3861 1672 2495 3885 1696 2468 3836 1648 2468 3836 1648 2495 3885 1696 2494 3886 1697 2468 3836 1648 2494 3886 1697 2467 3837 1647 2467 3837 1647 2494 3886 1697 2493 3887 1698 2493 3887 1698 2496 3862 1674 2467 3837 1647 2467 3837 1647 2496 3862 1674 2470 3838 1649 2494 3886 1697 2520 3888 1700 2493 3887 1698 2493 3887 1698 2520 3888 1700 2519 3889 1699 2519 3889 1699 2522 3890 1701 2493 3887 1698 2493 3887 1698 2522 3890 1701 2496 3862 1674 2522 3890 1701 2523 3891 1702 2496 3862 1674 2496 3862 1674 2523 3891 1702 2497 3863 1673 2523 3891 1702 2524 3892 1703 2497 3863 1673 2497 3863 1673 2524 3892 1703 2498 3864 1675 2498 3864 1675 2524 3892 1703 2499 3865 1676 2499 3865 1676 2524 3892 1703 2525 3893 1704 2499 3865 1676 2525 3893 1704 2500 3866 1677 2500 3866 1677 2525 3893 1704 2526 3894 1705 2500 3866 1677 2526 3894 1705 2501 3867 1678 2501 3867 1678 2526 3894 1705 2527 3895 1706 2527 3895 1706 2528 3896 1707 2501 3867 1678 2501 3867 1678 2528 3896 1707 2502 3868 1679 2528 3896 1707 2529 3897 1708 2502 3868 1679 2502 3868 1679 2529 3897 1708 2503 3869 1680 2529 3897 1708 2530 3898 1709 2503 3869 1680 2503 3869 1680 2530 3898 1709 2504 3870 1681 2504 3870 1681 2530 3898 1709 2505 3871 1682 2505 3871 1682 2530 3898 1709 2531 3899 1710 2505 3871 1682 2531 3899 1710 2506 3872 1683 2506 3872 1683 2531 3899 1710 2532 3900 1711 2506 3872 1683 2532 3900 1711 2507 3873 1684 2507 3873 1684 2532 3900 1711 2533 3901 1712 2507 3873 1684 2533 3901 1712 2508 3874 1685 2508 3874 1685 2533 3901 1712 2534 3902 1713 2508 3874 1685 2534 3902 1713 2509 3875 1686 2509 3875 1686 2534 3902 1713 2535 3903 1714 2509 3875 1686 2535 3903 1714 2510 3876 1687 2510 3876 1687 2535 3903 1714 2536 3904 1715 2510 3876 1687 2536 3904 1715 2511 3877 1688 2511 3877 1688 2536 3904 1715 2537 3905 1716 2511 3877 1688 2537 3905 1716 2512 3878 1689 2512 3878 1689 2537 3905 1716 2538 3906 1717 2512 3878 1689 2538 3906 1717 2513 3879 1690 2513 3879 1690 2538 3906 1717 2539 3907 1718 2513 3879 1690 2539 3907 1718 2514 3880 1691 2514 3880 1691 2539 3907 1718 2540 3908 1719 2514 3880 1691 2540 3908 1719 2515 3881 1692 2515 3881 1692 2540 3908 1719 2541 3909 1720 2515 3881 1692 2541 3909 1720 2516 3882 1693 2516 3882 1693 2541 3909 1720 2542 3910 1721 2516 3882 1693 2542 3910 1721 2517 3883 1694 2517 3883 1694 2542 3910 1721 2543 3911 1722 2517 3883 1694 2543 3911 1722 2518 3884 1695 2518 3884 1695 2543 3911 1722 2544 3912 1723 2518 3884 1695 2544 3912 1723 2495 3885 1696 2495 3885 1696 2544 3912 1723 2521 3913 1724 2495 3885 1696 2521 3913 1724 2494 3886 1697 2494 3886 1697 2521 3913 1724 2520 3888 1700 2554 3914 1726 2555 3915 1725 2528 3896 1707 2528 3896 1707 2555 3915 1725 2529 3897 1708 2555 3915 1725 2556 3916 1727 2529 3897 1708 2529 3897 1708 2556 3916 1727 2530 3898 1709 2530 3898 1709 2556 3916 1727 2531 3899 1710 2531 3899 1710 2556 3916 1727 2557 3917 1728 2531 3899 1710 2557 3917 1728 2532 3900 1711 2532 3900 1711 2557 3917 1728 2558 3918 1729 2532 3900 1711 2558 3918 1729 2533 3901 1712 2533 3901 1712 2558 3918 1729 2559 3919 1730 2533 3901 1712 2559 3919 1730 2534 3902 1713 2534 3902 1713 2559 3919 1730 2560 3920 1731 2534 3902 1713 2560 3920 1731 2535 3903 1714 2535 3903 1714 2560 3920 1731 2561 3921 1732 2535 3903 1714 2561 3921 1732 2536 3904 1715 2536 3904 1715 2561 3921 1732 2562 3922 1733 2536 3904 1715 2562 3922 1733 2537 3905 1716 2537 3905 1716 2562 3922 1733 2563 3923 1734 2537 3905 1716 2563 3923 1734 2538 3906 1717 2538 3906 1717 2563 3923 1734 2564 3924 1735 2538 3906 1717 2564 3924 1735 2539 3907 1718 2539 3907 1718 2564 3924 1735 2565 3925 1736 2539 3907 1718 2565 3925 1736 2540 3908 1719 2540 3908 1719 2565 3925 1736 2566 3926 1737 2540 3908 1719 2566 3926 1737 2541 3909 1720 2541 3909 1720 2566 3926 1737 2567 3927 1738 2541 3909 1720 2567 3927 1738 2542 3910 1721 2542 3910 1721 2567 3927 1738 2568 3928 1739 2542 3910 1721 2568 3928 1739 2543 3911 1722 2543 3911 1722 2568 3928 1739 2569 3929 1740 2543 3911 1722 2569 3929 1740 2544 3912 1723 2544 3912 1723 2569 3929 1740 2570 3930 1741 2544 3912 1723 2570 3930 1741 2521 3913 1724 2521 3913 1724 2570 3930 1741 2547 3931 1742 2521 3913 1724 2547 3931 1742 2520 3888 1700 2520 3888 1700 2547 3931 1742 2546 3932 1743 2520 3888 1700 2546 3932 1743 2519 3889 1699 2519 3889 1699 2546 3932 1743 2545 3933 1744 2545 3933 1744 2548 3934 1745 2519 3889 1699 2519 3889 1699 2548 3934 1745 2522 3890 1701 2548 3934 1745 2549 3935 1746 2522 3890 1701 2522 3890 1701 2549 3935 1746 2523 3891 1702 2549 3935 1746 2550 3936 1747 2523 3891 1702 2523 3891 1702 2550 3936 1747 2524 3892 1703 2524 3892 1703 2550 3936 1747 2525 3893 1704 2525 3893 1704 2550 3936 1747 2551 3937 1748 2525 3893 1704 2551 3937 1748 2526 3894 1705 2526 3894 1705 2551 3937 1748 2552 3938 1749 2526 3894 1705 2552 3938 1749 2527 3895 1706 2527 3895 1706 2552 3938 1749 2553 3939 1750 2553 3939 1750 2554 3914 1726 2527 3895 1706 2527 3895 1706 2554 3914 1726 2528 3896 1707 2557 3940 1728 2583 3941 1752 2558 3943 1729 2558 3943 1729 2583 3941 1752 2584 3942 1751 2558 3943 1729 2584 3942 1751 2559 3945 1730 2559 3945 1730 2584 3942 1751 2585 3944 1753 2559 3945 1730 2585 3944 1753 2560 3947 1731 2560 3947 1731 2585 3944 1753 2586 3946 1754 2560 3947 1731 2586 3946 1754 2561 3949 1732 2561 3949 1732 2586 3946 1754 2587 3948 1755 2561 3949 1732 2587 3948 1755 2562 3951 1733 2562 3951 1733 2587 3948 1755 2588 3950 1756 2562 3951 1733 2588 3950 1756 2563 3953 1734 2563 3953 1734 2588 3950 1756 2589 3952 1757 2563 3953 1734 2589 3952 1757 2564 3955 1735 2564 3955 1735 2589 3952 1757 2590 3954 1758 2564 3955 1735 2590 3954 1758 2565 3957 1736 2565 3957 1736 2590 3954 1758 2591 3956 1759 2565 3957 1736 2591 3956 1759 2566 3959 1737 2566 3959 1737 2591 3956 1759 2592 3958 1760 2566 3959 1737 2592 3958 1760 2567 3961 1738 2567 3961 1738 2592 3958 1760 2593 3960 1761 2567 3961 1738 2593 3960 1761 2568 3963 1739 2568 3963 1739 2593 3960 1761 2594 3962 1762 2568 3963 1739 2594 3962 1762 2569 3965 1740 2569 3965 1740 2594 3962 1762 2595 3964 1763 2569 3965 1740 2595 3964 1763 2570 3967 1741 2570 3967 1741 2595 3964 1763 2596 3966 1764 2596 3966 1764 2573 3968 1765 2570 3967 1741 2570 3967 1741 2573 3968 1765 2547 3969 1742 2573 3968 1765 2572 3970 1766 2547 3969 1742 2547 3969 1742 2572 3970 1766 2546 3971 1743 2572 3970 1766 2571 3972 1767 2546 3971 1743 2546 3971 1743 2571 3972 1767 2545 3973 1744 2545 3973 1744 2571 3972 1767 2548 3975 1745 2548 3975 1745 2571 3972 1767 2574 3974 1768 2548 3975 1745 2574 3974 1768 2549 3977 1746 2549 3977 1746 2574 3974 1768 2575 3976 1769 2549 3977 1746 2575 3976 1769 2550 3979 1747 2550 3979 1747 2575 3976 1769 2576 3978 1770 2576 3978 1770 2577 3980 1771 2550 3979 1747 2550 3979 1747 2577 3980 1771 2551 3981 1748 2577 3980 1771 2578 3982 1772 2551 3981 1748 2551 3981 1748 2578 3982 1772 2552 3983 1749 2578 3982 1772 2579 3984 1773 2552 3983 1749 2552 3983 1749 2579 3984 1773 2553 3985 1750 2553 3985 1750 2579 3984 1773 2554 3987 1726 2554 3987 1726 2579 3984 1773 2580 3986 1774 2554 3987 1726 2580 3986 1774 2555 3989 1725 2555 3989 1725 2580 3986 1774 2581 3988 1775 2555 3989 1725 2581 3988 1775 2556 3991 1727 2556 3991 1727 2581 3988 1775 2582 3990 1776 2556 3991 1727 2582 3990 1776 2557 3940 1728 2557 3940 1728 2582 3990 1776 2583 3941 1752</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Headphones">
+ <node id="_Headphones" name="Headphones" type="NODE">
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <instance_geometry url="#Headphones">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="HeadphonesSG" target="#headpiece"/>
+ <instance_material symbol="HeadphonesSG1" target="#trim"/>
+ <instance_material symbol="HeadphonesSG2" target="#plastic"/>
+ <instance_material symbol="HeadphonesSG3" target="#phone"/>
+ <instance_material symbol="HeadphonesSG4" target="#earpiece"/>
+ <instance_material symbol="HeadphonesSG5" target="#foam"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Logos/NVIDIA/NVIDIA_symbol.dae b/Studio/Content/Models Library/Logos/NVIDIA/NVIDIA_symbol.dae
new file mode 100644
index 00000000..ecd884ac
--- /dev/null
+++ b/Studio/Content/Models Library/Logos/NVIDIA/NVIDIA_symbol.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/logos/NVIDIA/NVIDIA_symbol.mb</source_data>
+ </contributor>
+ <created>2008-10-21T23:36:05Z</created>
+ <modified>2008-10-21T23:36:05Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="NVIDIA" name="NVIDIA">
+ <instance_effect url="#NVIDIA-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="NVIDIA-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>0.392157 0.784314 0 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="NVIDIA_symbol" name="NVIDIA_symbol">
+ <mesh>
+ <source id="NVIDIA_symbol-positions" name="position">
+ <float_array id="NVIDIA_symbol-positions-array" count="3441">-39.7894 4.59975 5.71497 -12.6923 19.3211 4.29981 -12.6923 24.1617 3.45395 -12.6923 -9.955 5.40174 -12.6923 13.3424 5.0846 -12.6923 33.0891 1.4 -36.6796 8.41347 5.51553 -32.6384 11.8997 5.23094 -27.5125 14.9873 4.89733 -22.5011 17.0863 4.62678 -18.0776 18.3819 4.44212 -14.7155 19.0591 4.34021 -12.6923 24.1577 3.45472 -14.5384 23.9201 3.50064 -18.2389 23.1844 3.6399 -23.4866 21.7064 3.90653 -37.037 15.5635 4.82659 -44.5461 10.4183 5.36381 -50.0036 5.62217 5.67298 -48.2192 1.13284 5.79484 -39.2215 -12.0305 5.21837 -33.2588 -17.0911 4.62613 -19.9237 -23.6933 3.54404 -15.2005 -24.9251 3.30337 -12.6923 -25.329 3.2218 -12.693 -20.1871 4.16232 -13.8839 -19.9703 4.19731 -16.9471 -19.1349 4.32858 -21.2973 -17.3807 4.586 -26.349 -14.4073 4.96584 -31.0303 -10.4217 5.36353 -34.9287 -5.648 5.67181 -37.9912 -0.154721 5.7999 -10.7226 24.2684 3.43318 -8.48226 24.1918 3.4481 -4.20276 23.7002 3.54272 1.5795 22.4271 3.77871 15.5075 16.0711 4.76206 21.9327 10.894 5.32307 26.6199 5.62001 5.67307 23.7834 2.35981 5.77762 16.5551 -4.41342 5.72172 9.68747 -9.15591 5.46311 3.50309 -12.2296 5.19896 -1.6755 -13.9963 5.01276 -5.52576 -14.818 4.91761 -7.72525 -15.0565 4.88897 -9.74575 -15.0196 4.89344 -12.6923 -14.6908 4.93269 -12.6923 -20.1743 4.1644 -7.53679 -20.4147 4.12518 -0.83377 -19.7349 4.23487 5.39738 -18.1669 4.47369 16.7373 -12.848 5.13664 21.9926 -9.33753 5.44961 31.2233 -2.14163 5.78157 42.3893 -8.87011 5.48382 40.9993 -10.0862 5.39118 35.0324 -13.8183 5.03265 27.8578 -17.2047 4.61046 19.9251 -20.1469 4.16883 11.6837 -22.5464 3.75714 3.5831 -24.3048 3.42607 -3.92713 -25.3237 3.22287 -8.80592 -25.5437 3.1779 -10.5711 -25.4922 3.18845 -12.6919 -25.3322 3.22113 -12.6923 -33.0862 1.40077 49.8558 -33.0891 1.4 49.9552 33.0891 1.4 -9.16866 19.3508 4.29519 -6.08891 18.9717 4.35358 -1.92544 18.004 4.49737 2.93747 16.175 4.7486 8.11541 13.2119 5.09852 15.8477 4.95013 5.70153 6.03857 -5.07341 5.69656 1.58113 -7.859 5.55179 -2.26899 -9.53575 5.43458 -5.2799 -10.3851 5.36658 -7.21964 -10.6885 5.34089 -8.65891 -10.708 5.33922 -10.1 -10.5701 5.351 -11.4557 -10.3108 5.37277 -12.6923 8.16942 5.5318 -9.68309 7.54246 5.57138 -8.13229 6.88839 5.60931 -6.8453 6.04721 5.65304 -5.5871 4.85498 5.70528 -4.29726 3.19849 5.75889 -2.98798 1.1636 5.79456 -1.1999 -1.76997 5.78741 6.98162 5.12901 5.69428 7.20257 5.50339 5.67829 4.8985 7.98162 5.54398 2.08386 10.0864 5.39116 -1.08961 11.7048 5.24943 -4.07774 12.7165 5.15015 -6.62283 13.264 5.09298 -8.46719 13.4898 5.0687 -10.7127 13.5028 5.06729 -12.6923 -9.955 5.40174 -12.6923 -14.6659 4.93563 -14.1654 -14.3005 4.97816 -16.7958 -13.3778 5.08079 -20.2229 -11.6974 5.25013 -23.9872 -9.07678 5.46891 -29.5198 -2.54985 5.77387 -31.4331 1.53351 5.79055 -32.1097 3.99308 5.73592 -29.0464 6.7998 5.61419 -21.6871 10.9306 5.31986 -18.2772 12.1208 5.2096 -15.4437 12.8555 5.13586 -12.6959 13.342 5.08464 -12.6933 8.17237 5.5316 -14.424 8.16469 5.53211 -16.0501 7.92369 5.54769 -18.0169 7.35145 5.58282 -20.1881 6.31681 5.63965 -22.2789 4.81825 5.70671 -24.0846 2.96159 5.76475 -22.8368 -0.378247 5.79942 -21.0569 -3.38052 5.75407 -16.7397 -7.71313 5.56092 -14.8196 -8.95182 5.47796 -12.6919 -26.3797 3.00344 50.0036 -26.3797 3.00344 50.0036 -21.2891 3.97863 16.0021 -21.2891 3.97863 50.0036 -16.1985 4.74554 -12.6923 -16.1985 4.74554 10.3128 -16.1985 4.74554 29.9897 -16.1985 4.74554 50.0036 -11.1078 5.30416 5.76005 -11.1078 5.30416 19.3423 -11.1078 5.30416 39.3659 -11.1078 5.30416 50.0036 -6.01721 5.6545 14.2326 -6.01721 5.6545 26.2955 -6.01721 5.6545 37.6549 -6.01721 5.6545 50.0036 -0.926582 5.79655 20.2762 -0.926582 5.79655 50.0036 4.16405 5.73032 25.3532 4.16405 5.73032 50.0036 9.25468 5.4558 23.3896 9.25468 5.4558 50.0036 14.3453 4.973 17.6493 14.3453 4.973 50.0036 19.4359 4.28192 9.36868 19.4359 4.28192 50.0036 24.5266 3.38256 50.0036 29.6172 2.27491 -12.6923 29.6172 2.27491 -26.0238 -21.2891 3.97863 -12.6929 -21.2891 3.97863 -34.3105 -16.1985 4.74554 -23.3058 -16.1985 4.74554 -39.9859 -11.1078 5.30416 -30.2243 -11.1078 5.30416 -44.1745 -6.01721 5.6545 -34.6272 -6.01721 5.6545 -47.0542 -0.926582 5.79655 -37.5609 -0.926582 5.79655 -49.424 4.16405 5.73032 -39.6246 4.16405 5.73032 -45.8702 9.25468 5.4558 -35.7045 9.25468 5.4558 -28.5783 14.3453 4.973 -38.8149 14.3453 4.973 -29.3914 19.4359 4.28192 -21.0697 -11.1078 5.30416 -12.6923 -11.1078 5.30416 -18.7419 -6.01721 5.6545 -30.2804 -0.926582 5.79655 -22.5117 -0.926582 5.79655 -31.9231 4.16405 5.73032 -22.9152 4.16405 5.73032 -25.2367 9.25468 5.4558 -12.6938 9.25468 5.4558 -12.6923 -6.01721 5.6545 4.52832 -6.01721 5.6545 -0.199725 -0.926582 5.79655 -1.71396 -0.926582 5.79655 -12.6923 -0.926582 5.79655 10.8378 -0.926582 5.79655 15.1788 4.16405 5.73032 5.83727 4.16405 5.73032 -5.04911 4.16405 5.73032 -12.6923 4.16405 5.73032 12.8031 9.25468 5.4558 3.1961 9.25468 5.4558 6.13483 14.3453 4.973 -12.6923 14.3453 4.973 -13.1923 -10.3014 5.8818 -13.1923 -14.0806 5.49892 -14.0213 -13.8752 5.5249 -16.6014 -12.9702 5.62594 -19.9677 -11.3196 5.79227 -23.6654 -8.72268 5.99246 -29.0857 -2.30647 6.28049 -30.9623 1.70836 6.2933 -28.7397 6.42513 6.13226 -21.4969 10.5146 5.86019 -18.1312 11.6894 5.75096 -15.3367 12.414 5.67801 -13.1956 12.7928 5.63657 -13.1935 8.69169 6.00937 -14.462 8.68605 6.00972 -16.1573 8.4348 6.0257 -18.1956 7.8417 6.06171 -20.4435 6.77054 6.12029 -22.6065 5.22026 6.18978 -24.6638 3.08441 6.26454 -23.2896 -0.593718 6.30152 -21.4633 -3.68405 6.25063 -17.0385 -8.14499 6.03636 -15.0633 -9.41915 5.95068 -20.7833 -10.7425 5.83758 -13.1923 -11.1547 5.80198 -19.0935 -6.39749 6.13738 -29.8276 -0.717325 6.29778 -22.9418 -1.18718 6.29365 -23.2737 4.52855 6.21879 -24.993 8.85432 5.9863 -13.1938 9.29451 5.95424 -31.5852 3.81499 6.24411 -12.1923 18.8968 4.86176 -12.1923 -9.6117 5.92481 -12.1923 13.9365 5.52186 -9.19754 18.9221 4.85784 -6.17724 18.5503 4.91516 -2.07199 17.5962 5.05718 2.7225 15.793 5.30531 7.8267 12.8589 5.64201 15.2155 5.00705 6.19916 5.74076 -4.68408 6.20897 1.3472 -7.44852 6.07969 -2.43786 -9.0969 5.96384 -5.38711 -9.92884 5.89693 -7.26201 -10.2221 5.87196 -8.63835 -10.2407 5.87035 -10.0288 -10.1077 5.88179 -11.339 -9.85706 5.90296 -12.1923 7.57978 6.06164 -9.83287 7.08829 6.09451 -8.36838 6.47064 6.13066 -7.15675 5.67872 6.17214 -5.95854 4.54333 6.22182 -4.70561 2.91564 6.26529 -3.41176 0.905721 6.37634 -1.32335 -2.54173 6.26614 7.36909 4.83076 6.21216 7.82257 5.59883 6.17369 5.23435 8.38268 6.02259 2.34963 10.5646 5.84205 -0.894179 12.2187 5.69608 -3.94394 13.2512 5.59413 -6.53925 13.8095 5.53565 -8.43506 14.0416 5.51065 -10.7316 14.0549 5.50921 -12.1923 -6.04021 6.15405 4.2631 -5.61894 6.17511 0.122597 -1.30828 6.297 -2.14091 -1.18928 6.29527 -12.1923 -0.930305 6.29664 10.482 -0.575946 6.29859 14.7981 4.50054 6.22216 6.15965 3.79456 6.23982 -5.4437 3.87358 6.24015 -12.1923 4.17968 6.23016 12.4313 8.95199 5.97952 3.49605 9.69029 5.92514 5.88523 13.9729 5.51986 -12.1923 14.4065 5.46928 -12.694 19.3209 4.29984 -40.3589 4.7219 6.20871 -37.0397 8.79238 5.99519 -32.9336 12.3531 5.68966 -27.7406 15.4902 5.34073 -22.6698 17.6141 5.06711 -18.1986 18.9237 4.8806 -14.798 19.6088 4.77788 -13.1924 23.6824 4.04541 -14.4562 23.52 4.07812 -18.1203 22.7916 4.21617 -23.3267 21.3254 4.48135 -36.78 15.1962 5.37556 -44.238 10.0752 5.9036 -49.409 5.50964 6.1807 -47.7672 1.35738 6.29568 -38.8636 -11.7374 5.75686 -32.9667 -16.771 5.18822 -19.766 -23.3181 4.12335 -15.0955 -24.536 3.88495 -13.1924 -24.8423 3.82168 -13.193 -20.6799 4.58708 -13.996 -20.5336 4.61038 -17.1085 -19.6849 4.74425 -21.5204 -17.9059 5.00622 -26.6413 -14.8692 5.41783 -31.3894 -10.8061 5.83968 -35.344 -5.94382 6.16582 -38.4458 -0.357903 6.30694 -25.838 -20.9185 4.55146 -13.1929 -21.3763 4.47099 -33.9855 -15.8827 5.2884 -23.561 -16.6889 5.18644 -39.5998 -10.8315 5.82819 -30.5493 -11.5332 5.7662 -43.7606 -5.75787 6.16772 -35.0147 -6.36086 6.13591 -46.619 -0.687207 6.29989 -37.9976 -1.17769 6.29278 -48.9594 4.36373 6.22452 -40.0923 4.0001 6.23471 -45.5397 8.91503 5.98061 -36.0317 9.67053 5.9249 -28.8374 14.8258 5.42247 -38.5311 13.9907 5.51499 -29.1862 19.0601 4.84527 -13.1938 19.8351 4.72203 -12.1923 24.7843 3.83018 -12.1923 32.7264 2.00702 -10.7277 24.8552 3.82833 -8.44444 24.7772 3.84342 -4.11886 24.2803 3.93914 1.72018 22.9948 4.17804 15.7883 16.5507 5.20264 22.2795 11.3022 5.78851 27.2854 5.65026 6.17221 24.1439 2.01901 6.28742 16.8699 -4.81748 6.21238 9.94255 -9.61747 5.93662 3.69666 -12.7499 5.63901 -1.54141 -14.5369 5.44982 -5.4459 -15.3701 5.35296 -7.70262 -15.6148 5.32351 -9.77834 -15.5769 5.3281 -12.1923 -15.3075 5.35998 -12.1923 -19.7886 4.72609 -7.56454 -19.9925 4.69226 -0.921454 -19.3188 4.801 5.24131 -17.7681 5.03757 16.4778 -12.4853 5.68924 21.7002 -8.96359 5.98061 31.1856 -1.54924 6.2983 43.2327 -8.82973 5.98779 41.299 -10.5218 5.86253 35.2736 -14.3094 5.48346 28.0535 -17.7349 5.03779 20.0838 -20.6907 4.59357 11.8086 -23.1164 4.15769 3.67142 -24.8827 3.82458 -3.88128 -25.9073 3.62017 -8.80186 -26.1292 3.57487 -10.5977 -26.0768 3.58559 -12.1919 -25.9566 3.61067 -12.1923 -32.7162 2.00328 49.3664 -32.719 2.00253 49.4619 32.7264 2.00702 -12.1919 -26.4888 3.49147 49.5036 -26.4797 3.49351 49.5036 -21.3734 4.47157 16.1437 -21.8462 4.39048 49.5036 -16.263 5.24146 -12.1923 -16.2654 5.24106 10.1255 -15.8051 5.30246 30.2045 -16.7096 5.18447 49.5036 -11.1523 5.80228 5.98327 -11.5972 5.76322 19.0638 -10.7387 5.83909 39.6319 -11.5756 5.76297 49.5036 -6.04136 6.15402 14.517 -6.45362 6.13273 25.988 -5.64697 6.17259 37.9132 -5.61267 6.17381 49.5036 -0.930305 6.29664 20.6181 -1.29534 6.29372 49.5036 4.18077 6.23014 25.7305 3.85251 6.24081 49.5036 9.29177 5.95453 23.7637 9.62066 5.93132 49.5036 14.4026 5.46982 17.9642 14.7869 5.42677 49.5036 19.5131 4.77603 9.61109 19.9428 4.71124 49.5036 24.6233 3.87322 49.5036 29.7282 2.76251 -12.1923 29.7311 2.76183 -12.6923 33.0891 0 49.9552 33.0891 0 49.8558 -33.0891 0 50.0036 -26.3797 0 50.0036 -21.2891 0 50.0036 -16.1985 0 50.0036 -11.1078 0 50.0036 -6.01721 0 50.0036 -0.926582 0 50.0036 4.16405 0 50.0036 9.25468 0 50.0036 14.3453 0 50.0036 19.4359 0 50.0036 24.5266 0 50.0036 29.6172 0 -12.6923 29.6172 0 -12.6923 -14.6908 0 -9.74575 -15.0196 0 -7.72525 -15.0565 0 -5.52576 -14.818 0 -1.6755 -13.9963 0 3.50309 -12.2296 0 5.76005 -11.1078 0 9.68747 -9.15591 0 14.2326 -6.01721 0 16.5551 -4.41342 0 20.2762 -0.926582 0 23.7834 2.35981 0 25.3532 4.16405 0 26.6199 5.62001 0 23.3896 9.25468 0 21.9327 10.894 0 17.6493 14.3453 0 15.5075 16.0711 0 9.36868 19.4359 0 1.5795 22.4271 0 -4.20276 23.7002 0 -8.48226 24.1918 0 -10.7226 24.2684 0 -12.6923 24.1617 0 -12.6923 -20.1743 0 -12.6923 -16.1985 0 -12.6919 -25.3322 0 -10.5711 -25.4922 0 -8.80592 -25.5437 0 -3.92713 -25.3237 0 3.5831 -24.3048 0 11.6837 -22.5464 0 16.0021 -21.2891 0 19.9251 -20.1469 0 27.8578 -17.2047 0 29.9897 -16.1985 0 35.0324 -13.8183 0 39.3659 -11.1078 0 40.9993 -10.0862 0 42.3893 -8.87011 0 37.6549 -6.01721 0 31.2233 -2.14163 0 -12.6923 -33.0862 0 -12.6919 -26.3797 0 -12.6923 19.3211 0 -12.6923 14.3453 0 -12.6923 13.3424 0 -10.7127 13.5028 0 -8.46719 13.4898 0 -6.62283 13.264 0 -4.07774 12.7165 0 -1.08961 11.7048 0 2.08386 10.0864 0 3.1961 9.25468 0 4.8985 7.98162 0 7.20257 5.50339 0 6.98162 5.12902 0 5.83727 4.16405 0 -0.199725 -0.926582 0 -1.1999 -1.76997 0 -1.71396 -0.926582 0 -2.98798 1.1636 0 -4.29726 3.19849 0 -5.04911 4.16405 0 -5.5871 4.85498 0 -6.8453 6.04721 0 -8.13229 6.88839 0 -9.68309 7.54246 0 -12.6923 8.16942 0 -12.6923 4.16405 0 -12.6923 -0.926582 0 -12.6923 -6.01721 0 -12.6923 -9.955 0 -11.4557 -10.3108 0 -10.1 -10.5701 0 -8.65891 -10.708 0 -7.21964 -10.6885 0 -5.2799 -10.3851 0 -2.26899 -9.53575 0 1.58113 -7.859 0 4.52832 -6.01721 0 6.03857 -5.07341 0 10.8378 -0.926582 0 15.1788 4.16405 0 15.8477 4.95013 0 -12.6923 -14.6659 0 -12.6923 -11.1078 0 -12.6923 -9.955 0 -14.8196 -8.95182 0 -16.7397 -7.71313 0 -18.7419 -6.01721 0 -21.0569 -3.38052 0 -22.5117 -0.926582 0 -22.8368 -0.378247 0 -24.0846 2.96159 0 -22.9152 4.16405 0 -22.2789 4.81825 0 -20.1881 6.31681 0 -18.0169 7.35145 0 -16.0501 7.92369 0 -14.424 8.16469 0 -12.6933 8.17237 0 -12.6938 9.25468 0 -12.6959 13.342 0 -12.6923 -25.329 0 -12.6923 24.1577 0 -12.693 -20.1871 0 -12.6929 -21.2891 0 -12.694 19.3209 0 50.0036 -0.926582 0 20.2762 -0.926582 0 -0.199725 -0.926582 0 -1.71396 -0.926582 0 -12.6923 -0.926582 0 10.8378 -0.926582 0 -22.5117 -0.926582 0 -22.8368 -0.378247 0 -48.2192 1.13284 5.79484 -39.2215 -12.0305 5.21837 -33.2588 -17.0911 4.62613 -19.9237 -23.6933 3.54404 -15.2005 -24.9251 3.30337 -12.6923 -25.329 3.2218 -26.0238 -21.2891 3.97863 -44.1745 -6.01721 5.6545 -47.0542 -0.926582 5.79655 -49.424 4.16405 5.73032 -12.6923 -25.329 0 -15.2005 -24.9251 0 -19.9237 -23.6933 0 -26.0238 -21.2891 0 -33.2588 -17.0911 0 -39.2215 -12.0305 0 -44.1745 -6.01721 0 -47.0542 -0.926582 0 -48.2192 1.13284 0 -49.424 4.16405 0 -47.0542 -0.926582 0 -12.6923 24.1577 3.45472 -14.5384 23.9201 3.50064 -18.2389 23.1844 3.6399 -23.4866 21.7064 3.90653 -37.037 15.5635 4.82659 -44.5461 10.4183 5.36381 -45.8702 9.25468 5.4558 -38.8149 14.3453 4.973 -29.3914 19.4359 4.28192 -44.5461 10.4183 0 -38.8149 14.3453 0 -37.037 15.5635 0 -29.3914 19.4359 0 -23.4866 21.7064 0 -18.2389 23.1844 0 -14.5384 23.9201 0 -12.6923 24.1577 0 -29.0464 6.7998 5.61419 -21.6871 10.9306 5.31986 -18.2772 12.1208 5.2096 -15.4437 12.8555 5.13586 -12.6959 13.342 5.08464 -25.2367 9.25468 5.4558 -12.6959 13.342 0 -15.4437 12.8555 0 -18.2772 12.1208 0 -21.6871 10.9306 0 -25.2367 9.25468 0 -29.0464 6.7998 0 -12.6923 19.3211 4.29981 -9.16866 19.3508 4.29519 -6.08891 18.9717 4.35358 -1.92544 18.004 4.49737 2.93747 16.175 4.7486 8.11541 13.2119 5.09852 15.8477 4.95013 5.70153 12.8031 9.25468 5.4558 6.13483 14.3453 4.973 -9.16866 19.3508 0 -12.6923 19.3211 0 15.8477 4.95013 0 12.8031 9.25468 0 8.11541 13.2119 0 6.13483 14.3453 0 2.93747 16.175 0 -1.92544 18.004 0 -6.08891 18.9717 0 -12.6923 -20.1743 4.1644 -7.53679 -20.4147 4.12518 -0.83377 -19.7349 4.23487 5.39738 -18.1669 4.47369 16.7373 -12.848 5.13664 21.9926 -9.33753 5.44961 31.2233 -2.14163 5.78157 10.3128 -16.1985 4.74554 19.3423 -11.1078 5.30416 26.2955 -6.01721 5.6545 -12.6923 -20.1743 0 31.2233 -2.14163 0 26.2955 -6.01721 0 21.9926 -9.33753 0 19.3423 -11.1078 0 16.7373 -12.848 0 10.3128 -16.1985 0 5.39738 -18.1669 0 -0.83377 -19.7349 0 -7.53679 -20.4147 0 -12.693 -20.1871 4.16232 -13.8839 -19.9703 4.19731 -16.9471 -19.1349 4.32858 -21.2973 -17.3807 4.586 -26.349 -14.4073 4.96584 -31.0303 -10.4217 5.36353 -34.9287 -5.648 5.67181 -37.9912 -0.154721 5.7999 -23.3058 -16.1985 4.74554 -37.5609 -0.926582 5.79655 -39.6246 4.16405 5.73032 -39.6246 4.16405 0 -37.9912 -0.154721 0 -37.5609 -0.926582 0 -34.9287 -5.648 0 -31.0303 -10.4217 0 -26.349 -14.4073 0 -23.3058 -16.1985 0 -21.2973 -17.3807 0 -16.9471 -19.1349 0 -13.8839 -19.9703 0 -12.693 -20.1871 0 -37.9912 -0.15472 0 -37.5609 -0.926582 0 -36.6796 8.41347 5.51553 -32.6384 11.8997 5.23094 -27.5125 14.9873 4.89733 -22.5011 17.0863 4.62678 -18.0776 18.3819 4.44212 -14.7155 19.0591 4.34021 -12.694 19.3209 4.29984 -14.7155 19.0591 0 -18.0776 18.3819 0 -22.5011 17.0863 0 -27.5125 14.9873 0 -32.6384 11.8997 0 -36.6796 8.41347 0 -12.694 19.3209 0 -27.0744 -6.01404 5.65465 -30.2804 -0.926582 0 -26.7065 -5.69295 6.167 -12.6923 -14.6659 4.93563 -14.1654 -14.3005 4.97816 -16.7958 -13.3778 5.08079 -20.2229 -11.6974 5.25013 -23.9872 -9.07678 5.46891 -29.5198 -2.54985 5.77387 -31.4331 1.53351 5.79055 -30.2804 -0.926582 5.79655 -12.6923 -14.6659 0 -31.4331 1.53351 0 -30.2804 -0.926582 0 -29.5198 -2.54985 0 -23.9872 -9.07678 0 -20.2229 -11.6974 0 -16.7958 -13.3778 0 -14.1654 -14.3005 0 -27.0744 -6.01404 5.65465 -27.0744 -6.01404 0 -39.7894 4.59975 -5.71497 -12.6923 19.3211 -4.29981 -12.6923 24.1617 -3.45395 -12.6923 -9.955 -5.40174 -12.6923 13.3424 -5.0846 -12.6923 33.0891 -1.4 -36.6796 8.41347 -5.51553 -32.6384 11.8997 -5.23094 -27.5125 14.9873 -4.89733 -22.5011 17.0863 -4.62678 -18.0776 18.3819 -4.44212 -14.7155 19.0591 -4.34021 -12.6923 24.1577 -3.45472 -14.5384 23.9201 -3.50064 -18.2389 23.1844 -3.6399 -23.4866 21.7064 -3.90653 -37.037 15.5635 -4.82659 -44.5461 10.4183 -5.36381 -50.0036 5.62217 -5.67298 -48.2192 1.13284 -5.79484 -39.2215 -12.0305 -5.21837 -33.2588 -17.0911 -4.62613 -19.9237 -23.6933 -3.54404 -15.2005 -24.9251 -3.30337 -12.6923 -25.329 -3.2218 -12.693 -20.1871 -4.16232 -13.8839 -19.9703 -4.19731 -16.9471 -19.1349 -4.32858 -21.2973 -17.3807 -4.586 -26.349 -14.4073 -4.96584 -31.0303 -10.4217 -5.36353 -34.9287 -5.648 -5.67181 -37.9912 -0.154721 -5.7999 -10.7226 24.2684 -3.43318 -8.48226 24.1918 -3.4481 -4.20276 23.7002 -3.54272 1.5795 22.4271 -3.77871 15.5075 16.0711 -4.76206 21.9327 10.894 -5.32307 26.6199 5.62001 -5.67307 23.7834 2.35981 -5.77762 16.5551 -4.41342 -5.72172 9.68747 -9.15591 -5.46311 3.50309 -12.2296 -5.19896 -1.6755 -13.9963 -5.01276 -5.52576 -14.818 -4.91761 -7.72525 -15.0565 -4.88897 -9.74575 -15.0196 -4.89344 -12.6923 -14.6908 -4.93269 -12.6923 -20.1743 -4.1644 -7.53679 -20.4147 -4.12518 -0.83377 -19.7349 -4.23487 5.39738 -18.1669 -4.47369 16.7373 -12.848 -5.13664 21.9926 -9.33753 -5.44961 31.2233 -2.14163 -5.78157 42.3893 -8.87011 -5.48382 40.9993 -10.0862 -5.39118 35.0324 -13.8183 -5.03265 27.8578 -17.2047 -4.61046 19.9251 -20.1469 -4.16883 11.6837 -22.5464 -3.75714 3.5831 -24.3048 -3.42607 -3.92713 -25.3237 -3.22287 -8.80592 -25.5437 -3.1779 -10.5711 -25.4922 -3.18845 -12.6919 -25.3322 -3.22113 -12.6923 -33.0862 -1.40077 49.8558 -33.0891 -1.4 49.9552 33.0891 -1.4 -9.16866 19.3508 -4.29519 -6.08891 18.9717 -4.35358 -1.92544 18.004 -4.49737 2.93747 16.175 -4.7486 8.11541 13.2119 -5.09852 15.8477 4.95013 -5.70153 6.03857 -5.07341 -5.69656 1.58113 -7.859 -5.55179 -2.26899 -9.53575 -5.43458 -5.2799 -10.3851 -5.36658 -7.21964 -10.6885 -5.34089 -8.65891 -10.708 -5.33922 -10.1 -10.5701 -5.351 -11.4557 -10.3108 -5.37277 -12.6923 8.16942 -5.5318 -9.68309 7.54246 -5.57138 -8.13229 6.88839 -5.60931 -6.8453 6.04721 -5.65304 -5.5871 4.85498 -5.70528 -4.29726 3.19849 -5.75889 -2.98798 1.1636 -5.79456 -1.1999 -1.76997 -5.78741 6.98162 5.12901 -5.69428 7.20257 5.50339 -5.67829 4.8985 7.98162 -5.54398 2.08386 10.0864 -5.39116 -1.08961 11.7048 -5.24943 -4.07774 12.7165 -5.15015 -6.62283 13.264 -5.09298 -8.46719 13.4898 -5.0687 -10.7127 13.5028 -5.06729 -12.6923 -9.955 -5.40174 -12.6923 -14.6659 -4.93563 -14.1654 -14.3005 -4.97816 -16.7958 -13.3778 -5.08079 -20.2229 -11.6974 -5.25013 -23.9872 -9.07678 -5.46891 -29.5198 -2.54985 -5.77387 -31.4331 1.53351 -5.79055 -32.1097 3.99308 -5.73592 -29.0464 6.7998 -5.61419 -21.6871 10.9306 -5.31986 -18.2772 12.1208 -5.2096 -15.4437 12.8555 -5.13586 -12.6959 13.342 -5.08464 -12.6933 8.17237 -5.5316 -14.424 8.16469 -5.53211 -16.0501 7.92369 -5.54769 -18.0169 7.35145 -5.58282 -20.1881 6.31681 -5.63965 -22.2789 4.81825 -5.70671 -24.0846 2.96159 -5.76475 -22.8368 -0.378247 -5.79942 -21.0569 -3.38052 -5.75407 -16.7397 -7.71313 -5.56092 -14.8196 -8.95182 -5.47796 -12.6919 -26.3797 -3.00344 50.0036 -26.3797 -3.00344 50.0036 -21.2891 -3.97863 16.0021 -21.2891 -3.97863 50.0036 -16.1985 -4.74554 -12.6923 -16.1985 -4.74554 10.3128 -16.1985 -4.74554 29.9897 -16.1985 -4.74554 50.0036 -11.1078 -5.30416 5.76005 -11.1078 -5.30416 19.3423 -11.1078 -5.30416 39.3659 -11.1078 -5.30416 50.0036 -6.01721 -5.6545 14.2326 -6.01721 -5.6545 26.2955 -6.01721 -5.6545 37.6549 -6.01721 -5.6545 50.0036 -0.926582 -5.79655 20.2762 -0.926582 -5.79655 50.0036 4.16405 -5.73032 25.3532 4.16405 -5.73032 50.0036 9.25468 -5.4558 23.3896 9.25468 -5.4558 50.0036 14.3453 -4.973 17.6493 14.3453 -4.973 50.0036 19.4359 -4.28192 9.36868 19.4359 -4.28192 50.0036 24.5266 -3.38256 50.0036 29.6172 -2.27491 -12.6923 29.6172 -2.27491 -26.0238 -21.2891 -3.97863 -12.6929 -21.2891 -3.97863 -34.3105 -16.1985 -4.74554 -23.3058 -16.1985 -4.74554 -39.9859 -11.1078 -5.30416 -30.2243 -11.1078 -5.30416 -44.1745 -6.01721 -5.6545 -34.6272 -6.01721 -5.6545 -47.0542 -0.926582 -5.79655 -37.5609 -0.926582 -5.79655 -49.424 4.16405 -5.73032 -39.6246 4.16405 -5.73032 -45.8702 9.25468 -5.4558 -35.7045 9.25468 -5.4558 -28.5783 14.3453 -4.973 -38.8149 14.3453 -4.973 -29.3914 19.4359 -4.28192 -21.0697 -11.1078 -5.30416 -12.6923 -11.1078 -5.30416 -18.7419 -6.01721 -5.6545 -30.2804 -0.926582 -5.79655 -22.5117 -0.926582 -5.79655 -31.9231 4.16405 -5.73032 -22.9152 4.16405 -5.73032 -25.2367 9.25468 -5.4558 -12.6938 9.25468 -5.4558 -12.6923 -6.01721 -5.6545 4.52832 -6.01721 -5.6545 -0.199725 -0.926582 -5.79655 -1.71396 -0.926582 -5.79655 -12.6923 -0.926582 -5.79655 10.8378 -0.926582 -5.79655 15.1788 4.16405 -5.73032 5.83727 4.16405 -5.73032 -5.04911 4.16405 -5.73032 -12.6923 4.16405 -5.73032 12.8031 9.25468 -5.4558 3.1961 9.25468 -5.4558 6.13483 14.3453 -4.973 -12.6923 14.3453 -4.973 -13.1923 -10.3014 -5.8818 -13.1923 -14.0806 -5.49892 -14.0213 -13.8752 -5.5249 -16.6014 -12.9702 -5.62594 -19.9677 -11.3196 -5.79227 -23.6654 -8.72268 -5.99246 -29.0857 -2.30647 -6.28049 -30.9623 1.70836 -6.2933 -28.7397 6.42513 -6.13226 -21.4969 10.5146 -5.86019 -18.1312 11.6894 -5.75096 -15.3367 12.414 -5.67801 -13.1956 12.7928 -5.63657 -13.1935 8.69169 -6.00937 -14.462 8.68605 -6.00972 -16.1573 8.4348 -6.0257 -18.1956 7.8417 -6.06171 -20.4435 6.77054 -6.12029 -22.6065 5.22026 -6.18978 -24.6638 3.08441 -6.26454 -23.2896 -0.593718 -6.30152 -21.4633 -3.68405 -6.25063 -17.0385 -8.14499 -6.03636 -15.0633 -9.41915 -5.95068 -20.7833 -10.7425 -5.83758 -13.1923 -11.1547 -5.80198 -19.0935 -6.39749 -6.13738 -29.8276 -0.717325 -6.29778 -22.9418 -1.18718 -6.29365 -23.2737 4.52855 -6.21879 -24.993 8.85432 -5.9863 -13.1938 9.29451 -5.95424 -31.5852 3.81499 -6.24411 -12.1923 18.8968 -4.86176 -12.1923 -9.6117 -5.92481 -12.1923 13.9365 -5.52186 -9.19754 18.9221 -4.85784 -6.17724 18.5503 -4.91516 -2.07199 17.5962 -5.05718 2.7225 15.793 -5.30531 7.8267 12.8589 -5.64201 15.2155 5.00705 -6.19916 5.74076 -4.68408 -6.20897 1.3472 -7.44852 -6.07969 -2.43786 -9.0969 -5.96384 -5.38711 -9.92884 -5.89693 -7.26201 -10.2221 -5.87196 -8.63835 -10.2407 -5.87035 -10.0288 -10.1077 -5.88179 -11.339 -9.85706 -5.90296 -12.1923 7.57978 -6.06164 -9.83287 7.08829 -6.09451 -8.36838 6.47064 -6.13066 -7.15675 5.67872 -6.17214 -5.95854 4.54333 -6.22182 -4.70561 2.91564 -6.26529 -3.41176 0.905721 -6.37634 -1.32335 -2.54173 -6.26614 7.36909 4.83076 -6.21216 7.82257 5.59883 -6.17369 5.23435 8.38268 -6.02259 2.34963 10.5646 -5.84205 -0.894179 12.2187 -5.69608 -3.94394 13.2512 -5.59413 -6.53925 13.8095 -5.53565 -8.43506 14.0416 -5.51065 -10.7316 14.0549 -5.50921 -12.1923 -6.04021 -6.15405 4.2631 -5.61894 -6.17511 0.122597 -1.30828 -6.297 -2.14091 -1.18928 -6.29527 -12.1923 -0.930305 -6.29664 10.482 -0.575946 -6.29859 14.7981 4.50054 -6.22216 6.15965 3.79456 -6.23982 -5.4437 3.87358 -6.24015 -12.1923 4.17968 -6.23016 12.4313 8.95199 -5.97952 3.49605 9.69029 -5.92514 5.88523 13.9729 -5.51986 -12.1923 14.4065 -5.46928 -12.694 19.3209 -4.29984 -40.3589 4.7219 -6.20871 -37.0397 8.79238 -5.99519 -32.9336 12.3531 -5.68966 -27.7406 15.4902 -5.34073 -22.6698 17.6141 -5.06711 -18.1986 18.9237 -4.8806 -14.798 19.6088 -4.77788 -13.1924 23.6824 -4.04541 -14.4562 23.52 -4.07812 -18.1203 22.7916 -4.21617 -23.3267 21.3254 -4.48135 -36.78 15.1962 -5.37556 -44.238 10.0752 -5.9036 -49.409 5.50964 -6.1807 -47.7672 1.35738 -6.29568 -38.8636 -11.7374 -5.75686 -32.9667 -16.771 -5.18822 -19.766 -23.3181 -4.12335 -15.0955 -24.536 -3.88495 -13.1924 -24.8423 -3.82168 -13.193 -20.6799 -4.58708 -13.996 -20.5336 -4.61038 -17.1085 -19.6849 -4.74425 -21.5204 -17.9059 -5.00622 -26.6413 -14.8692 -5.41783 -31.3894 -10.8061 -5.83968 -35.344 -5.94382 -6.16582 -38.4458 -0.357903 -6.30694 -25.838 -20.9185 -4.55146 -13.1929 -21.3763 -4.47099 -33.9855 -15.8827 -5.2884 -23.561 -16.6889 -5.18644 -39.5998 -10.8315 -5.82819 -30.5493 -11.5332 -5.7662 -43.7606 -5.75787 -6.16772 -35.0147 -6.36086 -6.13591 -46.619 -0.687207 -6.29989 -37.9976 -1.17769 -6.29278 -48.9594 4.36373 -6.22452 -40.0923 4.0001 -6.23471 -45.5397 8.91503 -5.98061 -36.0317 9.67053 -5.9249 -28.8374 14.8258 -5.42247 -38.5311 13.9907 -5.51499 -29.1862 19.0601 -4.84527 -13.1938 19.8351 -4.72203 -12.1923 24.7843 -3.83018 -12.1923 32.7264 -2.00702 -10.7277 24.8552 -3.82833 -8.44444 24.7772 -3.84342 -4.11886 24.2803 -3.93914 1.72018 22.9948 -4.17804 15.7883 16.5507 -5.20264 22.2795 11.3022 -5.78851 27.2854 5.65026 -6.17221 24.1439 2.01901 -6.28742 16.8699 -4.81748 -6.21238 9.94255 -9.61747 -5.93662 3.69666 -12.7499 -5.63901 -1.54141 -14.5369 -5.44982 -5.4459 -15.3701 -5.35296 -7.70262 -15.6148 -5.32351 -9.77834 -15.5769 -5.3281 -12.1923 -15.3075 -5.35998 -12.1923 -19.7886 -4.72609 -7.56454 -19.9925 -4.69226 -0.921454 -19.3188 -4.801 5.24131 -17.7681 -5.03757 16.4778 -12.4853 -5.68924 21.7002 -8.96359 -5.98061 31.1856 -1.54924 -6.2983 43.2327 -8.82973 -5.98779 41.299 -10.5218 -5.86253 35.2736 -14.3094 -5.48346 28.0535 -17.7349 -5.03779 20.0838 -20.6907 -4.59357 11.8086 -23.1164 -4.15769 3.67142 -24.8827 -3.82458 -3.88128 -25.9073 -3.62017 -8.80186 -26.1292 -3.57487 -10.5977 -26.0768 -3.58559 -12.1919 -25.9566 -3.61067 -12.1923 -32.7162 -2.00328 49.3664 -32.719 -2.00253 49.4619 32.7264 -2.00702 -12.1919 -26.4888 -3.49147 49.5036 -26.4797 -3.49351 49.5036 -21.3734 -4.47157 16.1437 -21.8462 -4.39048 49.5036 -16.263 -5.24146 -12.1923 -16.2654 -5.24106 10.1255 -15.8051 -5.30246 30.2045 -16.7096 -5.18447 49.5036 -11.1523 -5.80228 5.98327 -11.5972 -5.76322 19.0638 -10.7387 -5.83909 39.6319 -11.5756 -5.76297 49.5036 -6.04136 -6.15402 14.517 -6.45362 -6.13273 25.988 -5.64697 -6.17259 37.9132 -5.61267 -6.17381 49.5036 -0.930305 -6.29664 20.6181 -1.29534 -6.29372 49.5036 4.18077 -6.23014 25.7305 3.85251 -6.24081 49.5036 9.29177 -5.95453 23.7637 9.62066 -5.93132 49.5036 14.4026 -5.46982 17.9642 14.7869 -5.42677 49.5036 19.5131 -4.77603 9.61109 19.9428 -4.71124 49.5036 24.6233 -3.87322 49.5036 29.7282 -2.76251 -12.1923 29.7311 -2.76183 -48.2192 1.13284 -5.79484 -39.2215 -12.0305 -5.21837 -33.2588 -17.0911 -4.62613 -19.9237 -23.6933 -3.54404 -15.2005 -24.9251 -3.30337 -12.6923 -25.329 -3.2218 -26.0238 -21.2891 -3.97863 -44.1745 -6.01721 -5.6545 -47.0542 -0.926582 -5.79655 -49.424 4.16405 -5.73032 -12.6923 24.1577 -3.45472 -14.5384 23.9201 -3.50064 -18.2389 23.1844 -3.6399 -23.4866 21.7064 -3.90653 -37.037 15.5635 -4.82659 -44.5461 10.4183 -5.36381 -45.8702 9.25468 -5.4558 -38.8149 14.3453 -4.973 -29.3914 19.4359 -4.28192 -29.0464 6.7998 -5.61419 -21.6871 10.9306 -5.31986 -18.2772 12.1208 -5.2096 -15.4437 12.8555 -5.13586 -12.6959 13.342 -5.08464 -25.2367 9.25468 -5.4558 -12.6923 19.3211 -4.29981 -9.16866 19.3508 -4.29519 -6.08891 18.9717 -4.35358 -1.92544 18.004 -4.49737 2.93747 16.175 -4.7486 8.11541 13.2119 -5.09852 15.8477 4.95013 -5.70153 12.8031 9.25468 -5.4558 6.13483 14.3453 -4.973 -12.6923 -20.1743 -4.1644 -7.53679 -20.4147 -4.12518 -0.83377 -19.7349 -4.23487 5.39738 -18.1669 -4.47369 16.7373 -12.848 -5.13664 21.9926 -9.33753 -5.44961 31.2233 -2.14163 -5.78157 10.3128 -16.1985 -4.74554 19.3423 -11.1078 -5.30416 26.2955 -6.01721 -5.6545 -12.693 -20.1871 -4.16232 -13.8839 -19.9703 -4.19731 -16.9471 -19.1349 -4.32858 -21.2973 -17.3807 -4.586 -26.349 -14.4073 -4.96584 -31.0303 -10.4217 -5.36353 -34.9287 -5.648 -5.67181 -37.9912 -0.154721 -5.7999 -23.3058 -16.1985 -4.74554 -37.5609 -0.926582 -5.79655 -39.6246 4.16405 -5.73032 -36.6796 8.41347 -5.51553 -32.6384 11.8997 -5.23094 -27.5125 14.9873 -4.89733 -22.5011 17.0863 -4.62678 -18.0776 18.3819 -4.44212 -14.7155 19.0591 -4.34021 -12.694 19.3209 -4.29984 -27.0744 -6.01404 -5.65465 -26.7065 -5.69295 -6.167 -12.6923 -14.6659 -4.93563 -14.1654 -14.3005 -4.97816 -16.7958 -13.3778 -5.08079 -20.2229 -11.6974 -5.25013 -23.9872 -9.07678 -5.46891 -29.5198 -2.54985 -5.77387 -31.4331 1.53351 -5.79055 -30.2804 -0.926582 -5.79655 -27.0744 -6.01404 -5.65465 -50.0036 5.62217 0 -50.0036 5.62217 -5.67298 -50.0036 5.62217 5.67298 -39.7894 4.59975 0 -39.7894 4.59975 -5.71497 -39.7894 4.59975 5.71497 -31.9231 4.16405 0 -31.9231 4.16405 -5.73032 -31.9231 4.16405 5.73032 -32.1097 3.99308 0 -32.1097 3.99308 -5.73592 -32.1097 3.99308 5.73592</float_array>
+ <technique_common>
+ <accessor source="#NVIDIA_symbol-positions-array" count="1147" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="NVIDIA_symbol-normals" name="normal">
+ <float_array id="NVIDIA_symbol-normals-array" count="5847">0.461413 -0.504438 0.729823 0.360691 -0.575011 0.734346 0.360691 -0.575011 0.734346 0.461413 -0.504438 0.729823 0.254709 -0.626621 0.736525 0.254709 -0.626621 0.736525 0.15368 -0.657548 0.737572 0.15368 -0.657548 0.737572 0.054634 -0.672272 0.738286 0.054634 -0.672272 0.738286 0.00321 -0.675371 0.737471 0.00321 -0.675371 0.737471 0.712897 0.054681 0.699134 0.710015 0.059495 0.701669 0.710015 0.059495 0.701669 0.712897 0.054681 0.699134 0.707106 0.064306 0.704178 0.707106 0.064306 0.704178 -0.121845 0.757095 0.641842 -0.149308 0.751776 0.642293 -0.149308 0.751776 0.642293 -0.121845 0.757095 0.641842 -0.205194 0.737684 0.643209 -0.205194 0.737684 0.643209 -0.269173 0.712005 0.648533 -0.269173 0.712005 0.648533 -0.344331 0.665362 0.662367 -0.344331 0.665362 0.662367 -0.431369 0.594047 0.678991 -0.431369 0.594047 0.678991 -0.673028 -0.242024 0.698898 -0.641779 -0.303926 0.704094 -0.641779 -0.303926 0.704094 -0.673028 -0.242024 0.698898 -0.610943 -0.370445 0.699656 -0.610943 -0.370445 0.699656 -0.450925 -0.586187 0.673091 -0.407423 -0.635713 0.655649 -0.407423 -0.635713 0.655649 -0.450925 -0.586187 0.673091 -0.362615 -0.673077 0.644576 -0.362615 -0.673077 0.644576 -0.273805 -0.720825 0.636743 -0.273805 -0.720825 0.636743 -0.201134 -0.746408 0.634367 -0.201134 -0.746408 0.634367 -0.168392 -0.755175 0.633526 -0.168392 -0.755175 0.633526 0.707108 -0.072849 0.703343 0.70865 -0.067432 0.702331 0.70865 -0.067432 0.702331 0.707108 -0.072849 0.703343 0.710168 -0.062012 0.701296 0.710168 -0.062012 0.701296 0.306394 0.592423 0.745089 0.346633 0.571223 0.744009 0.346633 0.571223 0.744009 0.306394 0.592423 0.745089 0.423039 0.524635 0.73878 0.423039 0.524635 0.73878 0.497695 0.4702 0.728843 0.497695 0.4702 0.728843 0.573464 0.395143 0.717636 0.573464 0.395143 0.717636 0.610434 0.351231 0.709935 0.610434 0.351231 0.709935 0.637401 0.304412 0.707852 0.637401 0.304412 0.707852 0.661782 0.254451 0.705194 0.661782 0.254451 0.705194 0.511099 -0.472538 0.717974 0.509813 -0.46833 0.721635 0.509813 -0.46833 0.721635 0.511099 -0.472538 0.717974 0.000218 0.07063 0.997503 0.001455 0.084409 0.99643 0.001455 0.084409 0.99643 0.001455 0.084409 0.99643 0.001455 0.084409 0.99643 0.000218 0.07063 0.997503 0.000343 -0.083223 0.996531 0.000343 -0.083223 0.996531 0.001959 -0.096721 0.99531 0.001959 -0.096721 0.99531 0.001959 -0.096721 0.99531 0.001959 -0.096721 0.99531 -0.47869 0.54843 0.685624 -0.47869 0.54843 0.685624 -0.479811 0.546175 0.68664 -0.700747 -0.183762 0.689337 -0.700747 -0.183762 0.689337 -0.000004 -0.007819 0.999969 -0.000004 -0.007819 0.999969 0.000582 0.013085 0.999914 0.000582 0.013085 0.999914 -0.000217 0.03497 0.999388 -0.000217 0.03497 0.999388 0.000582 0.013085 0.999914 -0.001017 0.056839 0.998383 -0.001017 0.056839 0.998383 -0.001017 0.056839 0.998383 -0.001017 0.056839 0.998383 -0.001017 0.056839 0.998383 -0.001017 0.056839 0.998383 -0.001017 0.056839 0.998383 0.329649 -0.666446 0.668716 0.376644 -0.632179 0.677118 0.376644 -0.632179 0.677118 0.329649 -0.666446 0.668716 0.419427 -0.588543 0.691157 0.419427 -0.588543 0.691157 0.501581 -0.500383 0.705715 0.501581 -0.500383 0.705715 0.541049 -0.438202 0.717806 0.541049 -0.438202 0.717806 0.541889 -0.426411 0.724244 0.541889 -0.426411 0.724244 0.580944 0.448782 0.679043 0.522864 0.52743 0.66965 0.522864 0.52743 0.66965 0.580944 0.448782 0.679043 0.408071 0.646197 0.644909 0.408071 0.646197 0.644909 0.35508 0.691671 0.628895 0.35508 0.691671 0.628895 0.303663 0.723925 0.619452 0.303663 0.723925 0.619452 0.205338 0.764717 0.610774 0.205338 0.764717 0.610774 0.122815 0.784471 0.607882 0.122815 0.784471 0.607882 0.039976 0.793802 0.606861 0.039976 0.793802 0.606861 -0.005915 0.795553 0.605856 -0.005915 0.795553 0.605856 -0.707106 0.094803 0.700723 -0.707198 0.086561 0.701696 -0.707198 0.086561 0.701696 -0.707106 0.094803 0.700723 -0.707242 0.078312 0.702621 -0.707242 0.078312 0.702621 0.057263 -0.622612 0.780433 0.026587 -0.624085 0.780904 0.026587 -0.624085 0.780904 0.057263 -0.622612 0.780433 -0.04518 -0.622886 0.781007 -0.04518 -0.622886 0.781007 -0.117447 -0.614859 0.779843 -0.117447 -0.614859 0.779843 -0.187037 -0.599483 0.778227 -0.187037 -0.599483 0.778227 -0.270851 -0.570804 0.775128 -0.270851 -0.570804 0.775128 -0.371351 -0.525658 0.765364 -0.371351 -0.525658 0.765364 -0.426372 -0.507046 0.749074 -0.426372 -0.507046 0.749074 -0.473244 -0.479692 0.738875 -0.473244 -0.479692 0.738875 -0.51758 -0.441456 0.732958 -0.51758 -0.441456 0.732958 -0.611302 0.393607 0.686574 -0.539641 0.481939 0.690306 -0.539641 0.481939 0.690306 -0.611302 0.393607 0.686574 -0.458789 0.556663 0.69256 -0.458789 0.556663 0.69256 -0.458053 0.538379 0.707344 -0.458053 0.538379 0.707344 -0.459491 0.52743 0.714623 -0.459491 0.52743 0.714623 0.603809 0.35372 0.714351 0.618858 0.363177 0.696503 0.618858 0.363177 0.696503 0.603809 0.35372 0.714351 0.621981 0.394853 0.676188 0.621981 0.394853 0.676188 0.584441 0.434664 0.685198 0.584441 0.434664 0.685198 0.560529 0.454633 0.692182 0.560529 0.454633 0.692182 0.52671 0.502397 0.685692 0.52671 0.502397 0.685692 0.43856 0.587361 0.6802 0.43856 0.587361 0.6802 0.330388 0.657884 0.67678 0.330388 0.657884 0.67678 0.208083 0.708015 0.674846 0.208083 0.708015 0.674846 0.142214 0.726213 0.672599 0.142214 0.726213 0.672599 -0.707107 0.035004 0.70624 -0.707165 0.022103 0.706703 -0.707165 0.022103 0.706703 -0.707107 0.035004 0.70624 -0.70718 -0.005263 0.707014 -0.70718 -0.005263 0.707014 -0.707165 -0.032511 0.706301 -0.707165 -0.032511 0.706301 -0.707108 -0.045293 0.705653 -0.707108 -0.045293 0.705653 -0.192458 -0.725009 0.661303 -0.16166 -0.732287 0.66153 -0.16166 -0.732287 0.66153 -0.192458 -0.725009 0.661303 -0.09846 -0.743771 0.661144 -0.09846 -0.743771 0.661144 -0.028384 -0.749974 0.660858 -0.028384 -0.749974 0.660858 0.058466 -0.747784 0.661363 0.058466 -0.747784 0.661363 0.14862 -0.734625 0.661995 0.14862 -0.734625 0.661995 0.235802 -0.709842 0.663718 0.235802 -0.709842 0.663718 -0.000454 -0.045408 0.998968 -0.000454 -0.045408 0.998968 -0.000337 -0.027387 0.999625 -0.000248 -0.007051 0.999975 -0.000248 -0.007051 0.999975 -0.000337 -0.027387 0.999625 -0.002981 -0.009479 0.999951 -0.002981 -0.009479 0.999951 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.000571 -0.063415 0.997987 -0.005625 0.008431 0.999949 -0.005625 0.008431 0.999949 -0.004025 0.026461 0.999642 -0.004025 0.026461 0.999642 0.000444 0.074688 0.997207 0.000444 0.074688 0.997207 0.000887 0.054416 0.998518 0.000887 0.054416 0.998518 0.000887 0.054416 0.998518 0.000363 0.033859 0.999426 0.000363 0.033859 0.999426 0.000887 0.054416 0.998518 -0.000581 0.112316 0.993672 -0.000581 0.112316 0.993672 -0.001165 0.129668 0.991557 -0.001165 0.129668 0.991557 -0.001165 0.129668 0.991557 -0.001165 0.129668 0.991557 -0.001165 0.129668 0.991557 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 0.000001 0.09493 0.995484 -0.002424 0.044482 0.999007 -0.002424 0.044482 0.999007 -0.002424 0.044482 0.999007 -0.002424 0.044482 0.999007 -0.002424 0.044482 0.999007 0.368139 -0.522548 0.769036 0.323584 -0.540438 0.776672 0.323584 -0.540438 0.776672 0.368139 -0.522548 0.769036 0.241221 -0.575053 0.781746 0.241221 -0.575053 0.781746 0.175058 -0.595494 0.784054 0.175058 -0.595494 0.784054 0.123046 -0.597291 0.792529 0.123046 -0.597291 0.792529 0.100852 -0.591462 0.800001 0.100852 -0.591462 0.800001 0.708688 0.121531 0.694976 0.708688 0.121531 0.694976 0.708688 0.121531 0.694976 0.708688 0.121531 0.694976 -0.089919 0.812182 0.576433 -0.114129 0.808746 0.576979 -0.114129 0.808746 0.576979 -0.089919 0.812182 0.576433 -0.165973 0.798668 0.578431 -0.165973 0.798668 0.578431 -0.225709 0.778645 0.585463 -0.225709 0.778645 0.585463 -0.290097 0.742815 0.603382 -0.290097 0.742815 0.603382 -0.362281 0.690637 0.625918 -0.362281 0.690637 0.625918 -0.402536 0.655953 0.638507 -0.402536 0.655953 0.638507 -0.43946 0.618856 0.65107 -0.43946 0.618856 0.65107 -0.471778 0.578632 0.66529 -0.471778 0.578632 0.66529 -0.469255 0.573395 0.671578 -0.469255 0.573395 0.671578 -0.658189 -0.232309 0.716114 -0.65839 -0.2389 0.713757 -0.65839 -0.2389 0.713757 -0.658189 -0.232309 0.716114 -0.638984 -0.296696 0.709698 -0.638984 -0.296696 0.709698 -0.617401 -0.357196 0.700876 -0.617401 -0.357196 0.700876 -0.583171 -0.432022 0.687945 -0.583171 -0.432022 0.687945 -0.549066 -0.502115 0.668136 -0.549066 -0.502115 0.668136 -0.508162 -0.564261 0.650678 -0.508162 -0.564261 0.650678 -0.466498 -0.620336 0.630526 -0.466498 -0.620336 0.630526 -0.419218 -0.673691 0.608602 -0.419218 -0.673691 0.608602 -0.314839 -0.7468 0.585804 -0.222177 -0.787969 0.574232 -0.222177 -0.787969 0.574232 -0.314839 -0.7468 0.585804 -0.146564 -0.80962 0.568361 -0.146564 -0.80962 0.568361 -0.112725 -0.815914 0.567078 -0.112725 -0.815914 0.567078 0.707108 -0.130111 0.695032 0.707125 -0.123139 0.696284 0.707125 -0.123139 0.696284 0.707108 -0.130111 0.695032 0.707106 -0.116161 0.697501 0.707106 -0.116161 0.697501 0.127506 0.570023 0.811675 0.157111 0.563639 0.810943 0.157111 0.563639 0.810943 0.127506 0.570023 0.811675 0.224601 0.544837 0.807903 0.224601 0.544837 0.807903 0.31223 0.515835 0.797764 0.31223 0.515835 0.797764 0.361976 0.508101 0.781541 0.361976 0.508101 0.781541 0.412066 0.490445 0.767897 0.412066 0.490445 0.767897 0.463204 0.466994 0.753232 0.463204 0.466994 0.753232 0.508863 0.437094 0.741625 0.508863 0.437094 0.741625 0.554097 0.40227 0.728804 0.554097 0.40227 0.728804 0.589772 0.365829 0.719957 0.589772 0.365829 0.719957 0.621579 0.331334 0.709829 0.621579 0.331334 0.709829 0.644071 0.299565 0.703871 0.644071 0.299565 0.703871 0.662687 0.266962 0.699698 0.662687 0.266962 0.699698 0.661643 0.271572 0.698912 0.661643 0.271572 0.698912 0.546554 -0.407351 0.731672 0.507285 -0.445341 0.737789 0.507285 -0.445341 0.737789 0.546554 -0.407351 0.731672 0.464638 -0.476283 0.746503 0.464638 -0.476283 0.746503 0.415657 -0.499665 0.759976 0.415657 -0.499665 0.759976 -0.00076 0.117176 0.993111 0.00003 0.09402 0.99557 0.000173 0.073966 0.997261 0.000173 0.073966 0.997261 0.00003 0.09402 0.99557 -0.00076 0.117176 0.993111 0.000316 0.053882 0.998547 0.00046 0.03366 0.999433 0.00046 0.03366 0.999433 0.000316 0.053882 0.998547 0.000316 0.053882 0.998547 0.000603 0.013424 0.99991 0.00002 -0.007535 0.999972 0.00002 -0.007535 0.999972 0.000603 0.013424 0.99991 -0.000833 -0.049246 0.998786 -0.000833 -0.049246 0.998786 -0.000562 -0.028491 0.999594 0.000117 -0.128675 0.991687 0.000117 -0.128675 0.991687 -0.000188 -0.109483 0.993989 -0.000646 -0.089749 0.995964 -0.000646 -0.089749 0.995964 -0.000188 -0.109483 0.993989 0.000759 -0.163708 0.986508 0.000759 -0.163708 0.986508 0.001095 -0.179555 0.983747 0.001095 -0.179555 0.983747 0.001095 -0.179555 0.983747 -0.000138 0.153407 0.988163 0.001273 0.166518 0.986038 0.001273 0.166518 0.986038 0.001273 0.166518 0.986038 0.001273 0.166518 0.986038 -0.000138 0.153407 0.988163 -0.00155 0.140269 0.990112 -0.00155 0.140269 0.990112 -0.00155 0.140269 0.990112 -0.00155 0.140269 0.990112 -0.00155 0.140269 0.990112 -0.001103 -0.06998 0.997548 0.707198 -0.119191 0.696896 0.707179 -0.091243 0.701123 0.707179 -0.091243 0.701123 0.707198 -0.119191 0.696896 0.70718 -0.062846 0.704235 0.70718 -0.062846 0.704235 0.70718 -0.03414 0.706209 0.70718 -0.03414 0.706209 0.707181 -0.005263 0.707013 0.707181 -0.005263 0.707013 0.707181 0.02364 0.706637 0.707181 0.02364 0.706637 0.70718 0.052424 0.705087 0.70718 0.052424 0.705087 0.707179 0.08095 0.702385 0.707179 0.08095 0.702385 0.707176 0.109082 0.698572 0.707176 0.109082 0.698572 0.707183 0.136689 0.693692 0.707183 0.136689 0.693692 0.70715 0.166216 0.687249 0.70715 0.166216 0.687249 0.706988 0.182058 0.683391 0.706988 0.182058 0.683391 0 0.963965 0.266027 0 0.963965 0.266027 0 0.858459 0.512883 0 0.858459 0.512883 -0.707107 0.172787 0.685671 -0.70702 0.161096 0.6886 -0.70702 0.161096 0.6886 -0.707107 0.172787 0.685671 -0.706831 0.149381 0.691429 -0.706831 0.149381 0.691429 0.033816 -0.547248 0.836287 0.004618 -0.553097 0.833104 0.004618 -0.553097 0.833104 0.033816 -0.547248 0.836287 -0.053305 -0.556526 0.829119 -0.053305 -0.556526 0.829119 -0.11767 -0.548715 0.827687 -0.11767 -0.548715 0.827687 -0.205838 -0.537384 0.817832 -0.205838 -0.537384 0.817832 -0.300812 -0.521968 0.798162 -0.395796 -0.485618 0.779436 -0.395796 -0.485618 0.779436 -0.300812 -0.521968 0.798162 -0.446295 -0.465851 0.76407 -0.446295 -0.465851 0.76407 -0.488826 -0.442042 0.752096 -0.488826 -0.442042 0.752096 -0.529339 -0.41641 0.739191 -0.529339 -0.41641 0.739191 -0.527935 -0.424394 0.735646 -0.527935 -0.424394 0.735646 -0.534468 0.490127 0.688564 -0.534486 0.485912 0.691531 -0.534486 0.485912 0.691531 -0.534468 0.490127 0.688564 -0.509859 0.500669 0.699553 -0.509859 0.500669 0.699553 -0.48532 0.510523 0.70981 -0.48532 0.510523 0.70981 -0.446029 0.527334 0.723171 -0.446029 0.527334 0.723171 -0.404776 0.545676 0.733753 -0.404776 0.545676 0.733753 -0.3622 0.558877 0.745968 -0.3622 0.558877 0.745968 -0.317901 0.565781 0.760809 -0.317901 0.565781 0.760809 -0.271344 0.567167 0.777621 -0.271344 0.567167 0.777621 -0.186637 0.589374 0.786006 -0.186637 0.589374 0.786006 -0.112009 0.605322 0.788061 -0.112009 0.605322 0.788061 -0.031784 0.61312 0.78935 -0.031784 0.61312 0.78935 0.045784 0.61265 0.789027 0.045784 0.61265 0.789027 0.078536 0.610142 0.78839 0.078536 0.610142 0.78839 -0.707106 -0.087107 0.701722 -0.707127 -0.094692 0.700718 -0.707127 -0.094692 0.700718 -0.707106 -0.087107 0.701722 -0.707106 -0.102271 0.699673 -0.707106 -0.102271 0.699673 0.397809 -0.648475 0.649022 0.41358 -0.620916 0.665894 0.41358 -0.620916 0.665894 0.397809 -0.648475 0.649022 0.436024 -0.590005 0.679542 0.436024 -0.590005 0.679542 0.439488 -0.579865 0.686009 0.439488 -0.579865 0.686009 -0.367015 -0.630022 0.684377 -0.365921 -0.63692 0.678554 -0.365921 -0.63692 0.678554 -0.367015 -0.630022 0.684377 -0.364798 -0.643765 0.672674 -0.364798 -0.643765 0.672674 -0.467928 0.479145 0.742606 -0.42471 0.508843 0.748799 -0.42471 0.508843 0.748799 -0.467928 0.479145 0.742606 -0.378683 0.53092 0.758105 -0.378683 0.53092 0.758105 -0.341463 0.538106 0.770613 -0.341463 0.538106 0.770613 -0.305478 0.542832 0.782315 -0.305478 0.542832 0.782315 -0.277158 0.542866 0.792767 -0.277158 0.542866 0.792767 -0.225809 0.553701 0.801514 -0.225809 0.553701 0.801514 -0.201954 0.548944 0.811095 -0.201954 0.548944 0.811095 -0.176573 0.543464 0.820652 -0.176573 0.543464 0.820652 -0.124922 0.550381 0.825515 -0.124922 0.550381 0.825515 -0.0653 0.558069 0.827221 -0.0653 0.558069 0.827221 -0.005806 0.561138 0.827702 -0.005806 0.561138 0.827702 0.038187 0.560468 0.827295 0.038187 0.560468 0.827295 0.055066 0.559619 0.826919 0.055066 0.559619 0.826919 -0.711047 -0.146622 0.687687 -0.709106 -0.155475 0.687747 -0.709106 -0.155475 0.687747 -0.711047 -0.146622 0.687687 -0.707107 -0.164314 0.687751 -0.707107 -0.164314 0.687751 -0.00004 -0.962313 0.271944 -0.00004 -0.962313 0.271944 -0.000032 -0.852093 0.523391 -0.000032 -0.852093 0.523391 0.706819 -0.179105 0.684345 0.707181 -0.156107 0.689583 0.707181 -0.156107 0.689583 0.706819 -0.179105 0.684345 0.000203 -0.211888 0.977294 0.000508 -0.171875 0.985119 0.000508 -0.171875 0.985119 0.000405 -0.191256 0.98154 0.000405 -0.191256 0.98154 0.000405 -0.191256 0.98154 0.000405 -0.191256 0.98154 0.000405 -0.191256 0.98154 0.000405 -0.191256 0.98154 0.000203 -0.211888 0.977294 0.000826 -0.132426 0.991192 0.000826 -0.132426 0.991192 0.00061 -0.152428 0.988314 0.00061 -0.152428 0.988314 0.001274 -0.090516 0.995894 0.001274 -0.090516 0.995894 0.001041 -0.11237 0.993666 0.001043 -0.048222 0.998836 0.001043 -0.048222 0.998836 0.001507 -0.068618 0.997642 0.001507 -0.068618 0.997642 0.000401 -0.048473 0.998824 0.000401 -0.048473 0.998824 0.000224 -0.069119 0.997608 -0.000152 -0.08889 0.996041 -0.000152 -0.08889 0.996041 0.000224 -0.069119 0.997608 0.000554 -0.008346 0.999965 0.000444 0.032503 0.999471 0.000444 0.032503 0.999471 0.000528 0.011116 0.999938 0.000554 -0.008346 0.999965 0.00039 0.07508 0.997177 0.00039 0.07508 0.997177 0.000359 0.053875 0.998548 0.000385 0.116397 0.993203 0.000385 0.116397 0.993203 0.000421 0.096251 0.995357 0.000302 0.156323 0.987706 0.000302 0.156323 0.987706 0.000348 0.136494 0.990641 -0.00003 0.228758 0.973483 -0.00003 0.228758 0.973483 0.000000 0.244348 0.969688 0.000000 0.244348 0.969688 0.000001 -0.232426 0.972614 0.000001 -0.232426 0.972614 -0.00006 0.213109 0.977029 0.000098 0.194633 0.980876 0.000098 0.194633 0.980876 0.000579 -0.027806 0.999613 0.000579 -0.027806 0.999613 0.000423 -0.147819 0.989014 0.000423 -0.147819 0.989014 0.000423 -0.147819 0.989014 0.000423 -0.147819 0.989014 0.000423 -0.147819 0.989014 0 1 0 0 1 0 0.999939 -0.011017 0 0.999939 -0.011017 0 0.999757 -0.022033 0 0.999757 -0.022033 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0.000000 0 1 0 0 1 0 0 1 -0.000000 0 1 -0.000000 0 1 -0.000000 0 1 -0.000000 0 1 0.000000 0 1 0.000000 0 0.999976 0.006975 0 0.999976 0.006975 0 0.999903 0.01395 0 0.999903 0.01395 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 0.11088 0.993834 0 0.11088 0.993834 0 0.064651 0.997908 0 0.064651 0.997908 0 -0.044859 0.998993 0 -0.044859 0.998993 0 -0.158474 0.987363 0 -0.158474 0.987363 0 -0.266266 0.9639 0 -0.266266 0.9639 0 -0.38482 0.922992 0 -0.38482 0.922992 0 -0.445065 0.895498 0 -0.445065 0.895498 0 -0.507952 0.861386 0 -0.507952 0.861386 0 -0.568238 0.822864 0 -0.568238 0.822864 0 -0.62773 0.778431 0 -0.62773 0.778431 0 -0.683761 0.729706 0 -0.683761 0.729706 0 -0.720029 0.693944 0 -0.720029 0.693944 0 -0.754429 0.656382 0 -0.754429 0.656382 0 -0.754428 0.656383 0 -0.754428 0.656383 0 -0.747461 -0.664305 0 -0.747461 -0.664305 0 -0.747462 -0.664305 0 -0.747462 -0.664305 0 -0.689816 -0.723985 0 -0.689816 -0.723985 0 -0.62742 -0.778681 0 -0.62742 -0.778681 0 -0.556214 -0.831039 0 -0.556214 -0.831039 0 -0.42053 -0.907279 0 -0.42053 -0.907278 0 -0.287562 -0.957762 0 -0.287562 -0.957762 0 -0.164792 -0.986328 0 -0.164792 -0.986328 0 -0.07421 -0.997243 0 -0.07421 -0.997243 0 0.009972 -0.99995 0 0.009972 -0.99995 0 0.054094 -0.998536 0 0.054094 -0.998536 0 -1 0 0 -1 0 0 -1 0.000000 0 -1 0 0 -1 0 0 -1 0 0 0.075237 0.997166 0 0.075237 0.997166 0 0.052198 0.998637 0 0.052198 0.998637 0 -0.007962 0.999968 0 -0.007962 0.999968 0 -0.089828 0.995957 0 -0.089828 0.995957 0 -0.173415 0.984849 0 -0.173415 0.984849 0 -0.245989 0.969273 0 -0.245989 0.969273 0 -0.279547 0.960132 0 -0.279547 0.960132 0 -0.313848 0.949473 0 -0.313848 0.949473 0 -0.38765 0.921807 0 -0.38765 0.921807 0 -0.426842 0.904326 0 -0.426842 0.904326 0 -0.479397 0.877598 0 -0.479397 0.877598 0 -0.530285 0.847819 0 -0.530285 0.847819 0 -0.596279 0.802777 0 -0.596279 0.802777 0 -0.658466 0.75261 0 -0.658466 0.75261 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -1 0.000056 0 -1 0.000056 0 -1 0.000056 0 -1 0.000056 0 -1 0.000056 0 -1 0.000057 0 -1 0 0 -1 0.000000 0 -1 0.000000 0 -1 0 0 -1 0 0 -1 0 0 0.080788 -0.996731 0 0.080788 -0.996731 0 0.037531 -0.999295 0 0.037531 -0.999295 0 -0.063779 -0.997964 0 -0.063779 -0.997964 0 -0.166099 -0.986109 0 -0.166099 -0.986109 0 -0.265935 -0.963991 0 -0.265935 -0.963991 0 -0.388515 -0.921443 0 -0.388515 -0.921443 0 -0.528507 -0.848929 0 -0.528507 -0.848929 0 -0.598874 -0.800843 0 -0.598874 -0.800843 0 -0.668319 -0.743875 0 -0.668319 -0.743875 0 -0.732372 -0.680905 0 -0.732372 -0.680905 0 -0.763746 0.645517 0 -0.861205 0.508258 0 -0.861205 0.508258 0 -0.763746 0.645517 0 -0.644643 0.764484 0 -0.644643 0.764484 0 -0.644643 0.764484 0 -0.644643 0.764484 0 -0.644643 0.764484 0 -0.644643 0.764484 0 0.853884 0.520463 0 0.853884 0.520463 0 0.853884 0.520463 0 0.853884 0.520463 0 0.847487 0.530817 0 0.847487 0.530817 0 0.815813 0.578315 0 0.815813 0.578315 0 0.789016 0.614372 0 0.789016 0.614372 0 0.74052 0.672034 0 0.74052 0.672034 0 0.619963 0.784631 0 0.619963 0.784631 0 0.469757 0.882796 0 0.469757 0.882796 0 0.297684 0.954664 0 0.297684 0.954664 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -0.276483 -0.961019 0 -0.276483 -0.961019 0 -0.232434 -0.972612 0 -0.232434 -0.972612 0 -0.141714 -0.989908 0 -0.141714 -0.989908 0 -0.040904 -0.999163 0 -0.040904 -0.999163 0 0.08424 -0.996445 0 0.08424 -0.996445 0 0.213397 -0.976966 0 0.213397 -0.976966 0 0.336165 -0.941803 0 0.336165 -0.941803 0 0.465892 -0.884842 0 0.465892 -0.884842 0 0.529956 -0.848025 0 0.529956 -0.848025 0 0.593642 -0.804729 0 0.593642 -0.804729 0 0.709408 -0.704798 0 0.709408 -0.704798 0 0.761237 -0.648474 0 0.761237 -0.648474 0 0.761565 -0.648089 0 0.761565 -0.648089 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0.000000 0 0.485371 0.874308 0 0.426526 0.904475 0 0.426526 0.904475 0 0.485371 0.874308 0 0.59547 0.803377 0 0.59547 0.803377 0 0.700806 0.713351 0 0.700806 0.713351 0 0.860189 0.509975 0 0.809301 0.587395 0 0.809301 0.587395 0 0.860189 0.509975 0 0.902026 0.431682 0 0.902026 0.431682 0 0.936755 0.349986 0 0.936755 0.349986 0 0.716877 -0.697199 0 0.716877 -0.6972 0 0.716877 -0.697199 0 0.716877 -0.697199 0 0.652278 -0.75798 0 0.652278 -0.75798 0 0.508357 -0.861147 0 0.508357 -0.861147 0 0.355938 -0.934509 0 0.355938 -0.934509 0 0.213481 -0.976947 0 0.213481 -0.976947 0 0.075712 -0.99713 0 0.075712 -0.99713 0 0.004441 -0.99999 0 0.004441 -0.99999 0 1 0.000511 0 1 0.00051 0 1 0.000511 0 1 0.000511 0 1 0.000512 0 1 0.000512 0 1 0.000138 0 1 0.000138 0 1 0.000138 0 1 0.000138 0 1 0.000138 0 1 0.000138 0 0.203968 0.978978 0 0.203968 0.978978 0 1 -0.00035 0 1 -0.00035 0 1 -0.00035 0 1 -0.00035 0 -0.000045 -1 0 -0.000045 -1 0 -1 0 0 -1 0 0 -0.000508 -0.125393 0.992107 -0.000508 -0.125393 0.992107 -0.00053 -0.108627 0.994083 -0.00053 -0.108627 0.994083 -0.00053 -0.108627 0.994083 -0.00053 -0.108627 0.994083 -0.00053 -0.108627 0.994083 -0.00053 -0.108627 0.994083 -0.00053 -0.108627 0.994083 -0.000485 -0.142123 0.989849 -0.000485 -0.142123 0.989849 -0.000485 -0.142123 0.989849 -0.000485 -0.142123 0.989849 0.019512 -0.803456 0.595044 -0.032216 -0.806327 0.590592 -0.032216 -0.806327 0.590592 0.019512 -0.803456 0.595044 0.122461 -0.790602 0.599959 0.122461 -0.790602 0.599959 0.220085 -0.76467 0.605675 0.220085 -0.76467 0.605675 0.300116 -0.729489 0.614635 0.300116 -0.729489 0.614635 0.367775 -0.684044 0.629941 0.367775 -0.684044 0.629941 0.000257 0.176089 0.984374 0.000257 0.176089 0.984374 0.000257 0.176089 0.984374 -0.205905 -0.978572 0 -0.205905 -0.978572 0 -0.158988 -0.98728 0 -0.158988 -0.98728 0 -0.310072 -0.950713 0 -0.310072 -0.950713 0 -0.435501 -0.900188 0 -0.435501 -0.900188 0 -0.870389 -0.492366 0 -0.870389 -0.492366 0 -0.824255 -0.566218 0 -0.824255 -0.566218 0 -0.901934 -0.431875 0 -0.901934 -0.431875 0 -0.92928 -0.369377 0 -0.92928 -0.369377 0 -0.576757 -0.816916 0 -0.576757 -0.816916 0 -0.712295 -0.701881 0 -0.712295 -0.701881 0 -0.61379 0.789469 0 -0.61379 0.789469 0 -0.565232 0.824932 0 -0.565232 0.824932 0 -0.509645 0.860385 0 -0.509645 0.860385 0 -0.405896 0.913919 0 -0.405896 0.913919 0 -0.315332 0.948981 0 -0.315332 0.948981 0 -0.233218 0.972424 0 -0.233218 0.972424 0 -0.161428 0.986884 0 -0.161428 0.986884 0 -0.127677 0.991816 0 -0.127677 0.991816 0 -0.212821 0.977091 0 -0.174323 0.984689 0 -0.174323 0.984689 0 -0.21282 0.977091 0 -0.290516 0.95687 0 -0.290516 0.95687 0 -0.378776 0.925488 0 -0.378776 0.925488 0 -0.485349 0.874321 0 -0.485349 0.874321 0 -0.610793 0.79179 0 -0.610793 0.79179 0 -0.008433 0.999964 0 0.05699 0.998375 0 0.05699 0.998375 0 -0.008433 0.999964 0 0.81642 0.577459 0 0.81642 0.577459 0 0.736679 0.676242 0 0.736679 0.676242 0 0.573223 0.819399 0 0.573223 0.819399 0 0.49667 0.86794 0 0.49667 0.86794 0 0.425716 0.904857 0 0.425716 0.904857 0 0.289842 0.957074 0 0.289842 0.957074 0 0.174528 0.984652 0 0.174528 0.984652 0 0.614555 -0.788874 0 0.614555 -0.788874 0 0.583524 -0.812096 0 0.583524 -0.812096 0 0.555457 -0.831546 0 0.555457 -0.831546 0 0.509683 -0.860362 0 0.509683 -0.860362 0 0.41761 -0.908627 0 0.41761 -0.908627 0 0.308589 -0.951196 0 0.308589 -0.951196 0 0.172919 -0.984936 0 0.172919 -0.984936 0 0.02723 -0.999629 0 0.02723 -0.999629 0 0.618186 -0.786032 0 0.618186 -0.786032 0 -0.046588 -0.998914 0 -0.046588 -0.998914 0 0.906835 0.421486 0 0.906835 0.421486 0 0.935334 0.353766 0 0.935334 0.353766 0 0.87344 0.486931 0 0.87344 0.486931 0 0.827198 0.561911 0 0.827198 0.561911 0 0.579933 0.814664 0 0.579933 0.814664 0 0.507246 0.861801 0 0.507246 0.861801 0 0.44184 0.897094 0 0.44184 0.897094 0 0.319092 0.947724 0 0.319092 0.947724 0 0.221301 0.975205 0 0.221301 0.975205 0 0.179093 0.983832 0 0.179093 0.983832 0 0.714315 0.699825 0 0.714315 0.699825 0 0.2395 -0.970896 0 0.2395 -0.970896 0 0.16305 -0.986618 0 0.16305 -0.986618 0 0.334227 -0.942493 0 0.334227 -0.942493 0 0.452349 -0.891841 0 0.452349 -0.891841 0 0.128425 -0.991719 0 0.128425 -0.991719 0 0.586695 -0.809808 0 0.586695 -0.809808 0 0.716841 -0.697236 0 0.716841 -0.697236 0 -0.000932 -0.049225 0.998787 -0.001272 -0.069709 0.997567 -0.001272 -0.069709 0.997567 -0.001272 -0.069709 0.997567 -0.001272 -0.069709 0.997567 -0.000932 -0.049225 0.998787 -0.000592 -0.028721 0.999587 -0.000592 -0.028721 0.999587 -0.538021 -0.485817 0.688851 -0.538021 -0.485817 0.688851 -0.905525 -0.424293 0 -0.93823 -0.346014 0 -0.938229 -0.346014 0 -0.905525 -0.424293 0 -0.864605 -0.502452 0 -0.864605 -0.502453 0 -0.507276 -0.861784 0 -0.507276 -0.861784 0 -0.386316 -0.922366 0 -0.386316 -0.922366 0 -0.286195 -0.958171 0 -0.286195 -0.958171 0 -0.240746 -0.970588 0 -0.240746 -0.970588 0 -0.763536 -0.645766 0 -0.763536 -0.645766 0 -0.640223 -0.768189 0 -0.640223 -0.768189 0 0.461412 -0.504438 -0.729823 0.461412 -0.504438 -0.729823 0.360692 -0.575011 -0.734346 0.360692 -0.575011 -0.734346 0.25471 -0.626621 -0.736525 0.25471 -0.626621 -0.736525 0.15368 -0.657548 -0.737572 0.15368 -0.657548 -0.737572 0.054634 -0.672272 -0.738286 0.054634 -0.672272 -0.738286 0.00321 -0.675371 -0.737471 0.00321 -0.675371 -0.737471 0.712897 0.05468 -0.699134 0.712897 0.05468 -0.699134 0.710015 0.059494 -0.701669 0.710015 0.059494 -0.701669 0.707106 0.064306 -0.704178 0.707106 0.064306 -0.704178 -0.121844 0.757095 -0.641842 -0.121844 0.757095 -0.641842 -0.149308 0.751776 -0.642293 -0.149308 0.751776 -0.642293 -0.205194 0.737684 -0.643209 -0.205194 0.737684 -0.643209 -0.269173 0.712005 -0.648533 -0.269173 0.712005 -0.648533 -0.344331 0.665362 -0.662367 -0.344331 0.665362 -0.662367 -0.431369 0.594047 -0.678991 -0.431369 0.594047 -0.678991 -0.673028 -0.242024 -0.698898 -0.673028 -0.242024 -0.698898 -0.641779 -0.303926 -0.704095 -0.641779 -0.303926 -0.704095 -0.610943 -0.370445 -0.699656 -0.610943 -0.370445 -0.699656 -0.450926 -0.586187 -0.673091 -0.450926 -0.586187 -0.673091 -0.407423 -0.635713 -0.65565 -0.407423 -0.635713 -0.65565 -0.362615 -0.673077 -0.644576 -0.362615 -0.673077 -0.644576 -0.273805 -0.720825 -0.636743 -0.273805 -0.720825 -0.636743 -0.201134 -0.746408 -0.634366 -0.201134 -0.746408 -0.634366 -0.168392 -0.755176 -0.633525 -0.168392 -0.755176 -0.633525 0.707108 -0.072849 -0.703343 0.707108 -0.072849 -0.703343 0.70865 -0.067432 -0.702331 0.70865 -0.067432 -0.702331 0.710168 -0.062012 -0.701296 0.710168 -0.062012 -0.701296 0.306394 0.592423 -0.745089 0.306394 0.592423 -0.745089 0.346633 0.571223 -0.744009 0.346633 0.571223 -0.744009 0.423039 0.524635 -0.73878 0.423039 0.524635 -0.73878 0.497695 0.4702 -0.728843 0.497695 0.4702 -0.728843 0.573464 0.395143 -0.717636 0.573464 0.395143 -0.717636 0.610434 0.351232 -0.709934 0.610434 0.351232 -0.709934 0.637401 0.304412 -0.707851 0.637401 0.304412 -0.707851 0.661782 0.254451 -0.705194 0.661782 0.254451 -0.705194 0.511098 -0.472538 -0.717974 0.511098 -0.472538 -0.717974 0.509813 -0.46833 -0.721636 0.509813 -0.46833 -0.721636 0.000218 0.07063 -0.997503 0.000218 0.07063 -0.997503 0.001455 0.084409 -0.99643 0.001455 0.084409 -0.99643 0.001455 0.084409 -0.99643 0.001455 0.084409 -0.99643 0.000343 -0.083223 -0.996531 0.001958 -0.096721 -0.99531 0.001958 -0.096721 -0.99531 0.001958 -0.096721 -0.99531 0.001958 -0.096721 -0.99531 0.000343 -0.083223 -0.996531 -0.47869 0.548432 -0.685623 -0.47869 0.548432 -0.685623 -0.47981 0.546178 -0.686638 -0.700747 -0.183761 -0.689337 -0.700747 -0.183761 -0.689337 -0.000004 -0.007819 -0.999969 0.000582 0.013085 -0.999914 -0.000217 0.03497 -0.999388 -0.000217 0.03497 -0.999388 0.000582 0.013085 -0.999914 0.000582 0.013085 -0.999914 -0.000004 -0.007819 -0.999969 -0.001017 0.056839 -0.998383 -0.001017 0.056839 -0.998383 -0.001017 0.056839 -0.998383 -0.001017 0.056839 -0.998383 -0.001017 0.056839 -0.998383 -0.001017 0.056839 -0.998383 -0.001017 0.056839 -0.998383 0.329649 -0.666446 -0.668716 0.329649 -0.666446 -0.668716 0.376645 -0.632179 -0.677118 0.376645 -0.632179 -0.677118 0.419427 -0.588543 -0.691157 0.419427 -0.588543 -0.691157 0.501581 -0.500383 -0.705715 0.501581 -0.500383 -0.705715 0.541049 -0.438202 -0.717806 0.541049 -0.438202 -0.717806 0.541889 -0.426412 -0.724244 0.541889 -0.426412 -0.724244 0.580944 0.448782 -0.679043 0.580944 0.448782 -0.679043 0.522864 0.52743 -0.66965 0.522864 0.52743 -0.66965 0.408071 0.646197 -0.644909 0.408071 0.646197 -0.644909 0.355079 0.691671 -0.628896 0.355079 0.691671 -0.628896 0.303663 0.723925 -0.619452 0.303663 0.723925 -0.619452 0.205338 0.764717 -0.610774 0.205338 0.764717 -0.610774 0.122815 0.784471 -0.607883 0.122815 0.784471 -0.607883 0.039976 0.793801 -0.606862 0.039976 0.793801 -0.606862 -0.005914 0.795552 -0.605857 -0.005914 0.795552 -0.605857 -0.707106 0.094804 -0.700723 -0.707106 0.094804 -0.700723 -0.707198 0.086561 -0.701696 -0.707198 0.086561 -0.701696 -0.707242 0.078312 -0.702621 -0.707242 0.078312 -0.702621 0.057263 -0.622612 -0.780433 0.057263 -0.622612 -0.780433 0.026587 -0.624084 -0.780904 0.026587 -0.624084 -0.780904 -0.04518 -0.622887 -0.781007 -0.04518 -0.622887 -0.781007 -0.117447 -0.614859 -0.779843 -0.117447 -0.614859 -0.779843 -0.187037 -0.599483 -0.778227 -0.187037 -0.599483 -0.778227 -0.270851 -0.570804 -0.775127 -0.270851 -0.570804 -0.775127 -0.371351 -0.525658 -0.765364 -0.371351 -0.525658 -0.765364 -0.426371 -0.507046 -0.749074 -0.426371 -0.507046 -0.749074 -0.473244 -0.479692 -0.738875 -0.473244 -0.479692 -0.738875 -0.51758 -0.441456 -0.732958 -0.51758 -0.441456 -0.732958 -0.611302 0.393608 -0.686574 -0.611302 0.393608 -0.686574 -0.539641 0.481939 -0.690306 -0.539641 0.481939 -0.690306 -0.458789 0.556663 -0.69256 -0.458789 0.556663 -0.69256 -0.458053 0.538379 -0.707344 -0.458053 0.538379 -0.707344 -0.459491 0.52743 -0.714623 -0.459491 0.52743 -0.714623 0.603809 0.35372 -0.714351 0.603809 0.35372 -0.714351 0.618858 0.363177 -0.696503 0.618858 0.363177 -0.696503 0.621981 0.394853 -0.676188 0.621981 0.394853 -0.676188 0.584441 0.434664 -0.685198 0.584441 0.434664 -0.685198 0.560529 0.454633 -0.692183 0.560529 0.454633 -0.692183 0.52671 0.502397 -0.685692 0.52671 0.502397 -0.685692 0.43856 0.587361 -0.6802 0.43856 0.587361 -0.6802 0.330388 0.657884 -0.676781 0.330388 0.657884 -0.676781 0.208083 0.708014 -0.674846 0.208083 0.708014 -0.674846 0.142214 0.726214 -0.672599 0.142214 0.726214 -0.672599 -0.707107 0.035004 -0.70624 -0.707107 0.035004 -0.70624 -0.707165 0.022103 -0.706703 -0.707165 0.022103 -0.706703 -0.70718 -0.005263 -0.707014 -0.70718 -0.005263 -0.707014 -0.707165 -0.032511 -0.706301 -0.707165 -0.032511 -0.706301 -0.707108 -0.045293 -0.705653 -0.707108 -0.045293 -0.705653 -0.192458 -0.725009 -0.661303 -0.192458 -0.725009 -0.661303 -0.16166 -0.732287 -0.66153 -0.16166 -0.732287 -0.66153 -0.09846 -0.743771 -0.661144 -0.09846 -0.743771 -0.661144 -0.028384 -0.749974 -0.660857 -0.028384 -0.749974 -0.660857 0.058466 -0.747784 -0.661363 0.058466 -0.747784 -0.661363 0.14862 -0.734626 -0.661995 0.14862 -0.734626 -0.661995 0.235802 -0.709842 -0.663718 0.235802 -0.709842 -0.663718 -0.000454 -0.045408 -0.998968 -0.002982 -0.009479 -0.999951 -0.002982 -0.009479 -0.999951 -0.000337 -0.027387 -0.999625 -0.000248 -0.007051 -0.999975 -0.000248 -0.007051 -0.999975 -0.000337 -0.027387 -0.999625 -0.000454 -0.045408 -0.998968 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.000571 -0.063415 -0.997987 -0.004025 0.026461 -0.999642 -0.004025 0.026461 -0.999642 -0.005625 0.008431 -0.999949 -0.005625 0.008431 -0.999949 0.000444 0.074688 -0.997207 0.000887 0.054416 -0.998518 0.000363 0.033859 -0.999427 0.000363 0.033859 -0.999427 0.000887 0.054416 -0.998518 0.000887 0.054416 -0.998518 0.000887 0.054416 -0.998518 0.000444 0.074688 -0.997207 -0.000581 0.112316 -0.993672 -0.001165 0.129668 -0.991557 -0.001165 0.129668 -0.991557 -0.001165 0.129668 -0.991557 -0.001165 0.129668 -0.991557 -0.001165 0.129668 -0.991557 -0.000581 0.112316 -0.993672 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 0.000001 0.09493 -0.995484 -0.002424 0.044482 -0.999007 -0.002424 0.044482 -0.999007 -0.002424 0.044482 -0.999007 -0.002424 0.044482 -0.999007 -0.002424 0.044482 -0.999007 0.368139 -0.522548 -0.769036 0.368139 -0.522548 -0.769036 0.323584 -0.540438 -0.776672 0.323584 -0.540438 -0.776672 0.241221 -0.575053 -0.781746 0.241221 -0.575053 -0.781746 0.175058 -0.595494 -0.784054 0.175058 -0.595494 -0.784054 0.123046 -0.597291 -0.792529 0.123046 -0.597291 -0.792529 0.100852 -0.591462 -0.800001 0.100852 -0.591462 -0.800001 0.708688 0.121531 -0.694976 0.708688 0.121531 -0.694976 0.708688 0.121531 -0.694976 0.708688 0.121531 -0.694976 -0.089919 0.812182 -0.576433 -0.089919 0.812182 -0.576433 -0.114129 0.808746 -0.576979 -0.114129 0.808746 -0.576979 -0.165973 0.798668 -0.578431 -0.165973 0.798668 -0.578431 -0.225709 0.778645 -0.585463 -0.225709 0.778645 -0.585463 -0.290097 0.742814 -0.603382 -0.290097 0.742814 -0.603382 -0.362281 0.690637 -0.625918 -0.362281 0.690637 -0.625918 -0.402536 0.655953 -0.638507 -0.402536 0.655953 -0.638507 -0.43946 0.618856 -0.65107 -0.43946 0.618856 -0.65107 -0.471779 0.578632 -0.66529 -0.471779 0.578632 -0.66529 -0.469256 0.573395 -0.671578 -0.469256 0.573395 -0.671578 -0.658189 -0.232309 -0.716114 -0.658189 -0.232309 -0.716114 -0.65839 -0.2389 -0.713757 -0.65839 -0.2389 -0.713757 -0.638984 -0.296696 -0.709698 -0.638984 -0.296696 -0.709698 -0.6174 -0.357197 -0.700876 -0.6174 -0.357197 -0.700876 -0.583171 -0.432022 -0.687945 -0.583171 -0.432022 -0.687945 -0.549066 -0.502116 -0.668136 -0.549066 -0.502116 -0.668136 -0.508162 -0.564261 -0.650678 -0.508162 -0.564261 -0.650678 -0.466498 -0.620335 -0.630527 -0.466498 -0.620335 -0.630527 -0.419218 -0.673691 -0.608602 -0.419218 -0.673691 -0.608602 -0.314839 -0.7468 -0.585804 -0.314839 -0.7468 -0.585804 -0.222177 -0.787969 -0.574231 -0.222177 -0.787969 -0.574231 -0.146564 -0.80962 -0.568361 -0.146564 -0.80962 -0.568361 -0.112725 -0.815914 -0.567078 -0.112725 -0.815914 -0.567078 0.707109 -0.130111 -0.695031 0.707109 -0.130111 -0.695031 0.707125 -0.123139 -0.696284 0.707125 -0.123139 -0.696284 0.707106 -0.116161 -0.697502 0.707106 -0.116161 -0.697502 0.127506 0.570023 -0.811675 0.127506 0.570023 -0.811675 0.15711 0.563638 -0.810943 0.15711 0.563638 -0.810943 0.224601 0.544836 -0.807903 0.224601 0.544836 -0.807903 0.31223 0.515835 -0.797764 0.31223 0.515835 -0.797764 0.361976 0.508101 -0.781541 0.361976 0.508101 -0.781541 0.412065 0.490445 -0.767897 0.412065 0.490445 -0.767897 0.463204 0.466993 -0.753233 0.463204 0.466993 -0.753233 0.508863 0.437094 -0.741625 0.508863 0.437094 -0.741625 0.554098 0.40227 -0.728804 0.554098 0.40227 -0.728804 0.589772 0.365829 -0.719957 0.589772 0.365829 -0.719957 0.621579 0.331333 -0.709829 0.621579 0.331333 -0.709829 0.644071 0.299565 -0.703871 0.644071 0.299565 -0.703871 0.662687 0.266962 -0.699698 0.662687 0.266962 -0.699698 0.661643 0.271572 -0.698911 0.661643 0.271572 -0.698911 0.546555 -0.407351 -0.731672 0.546555 -0.407351 -0.731672 0.507285 -0.445341 -0.737789 0.507285 -0.445341 -0.737789 0.464638 -0.476283 -0.746503 0.464638 -0.476283 -0.746503 0.415657 -0.499665 -0.759976 0.415657 -0.499665 -0.759976 -0.00076 0.117176 -0.993111 -0.00076 0.117176 -0.993111 0.00003 0.09402 -0.99557 0.000173 0.073966 -0.997261 0.000173 0.073966 -0.997261 0.00003 0.09402 -0.99557 0.000316 0.053882 -0.998547 0.000316 0.053882 -0.998547 0.00046 0.03366 -0.999433 0.00046 0.03366 -0.999433 0.000316 0.053882 -0.998547 0.000603 0.013424 -0.99991 0.00002 -0.007535 -0.999972 0.00002 -0.007535 -0.999972 0.000603 0.013424 -0.99991 -0.000833 -0.049246 -0.998786 -0.000562 -0.028491 -0.999594 -0.000833 -0.049246 -0.998786 0.000117 -0.128675 -0.991687 -0.000188 -0.109483 -0.993989 -0.000646 -0.089749 -0.995964 -0.000646 -0.089749 -0.995964 -0.000188 -0.109483 -0.993989 0.000117 -0.128675 -0.991687 0.000759 -0.163708 -0.986508 0.001095 -0.179555 -0.983747 0.001095 -0.179555 -0.983747 0.001095 -0.179555 -0.983747 0.000759 -0.163708 -0.986508 -0.000138 0.153407 -0.988163 -0.000138 0.153407 -0.988163 0.001273 0.166518 -0.986038 0.001273 0.166518 -0.986038 0.001273 0.166518 -0.986038 0.001273 0.166518 -0.986038 -0.00155 0.140269 -0.990112 -0.00155 0.140269 -0.990112 -0.00155 0.140269 -0.990112 -0.00155 0.140269 -0.990112 -0.00155 0.140269 -0.990112 -0.001103 -0.06998 -0.997548 0.707198 -0.119191 -0.696896 0.707198 -0.119191 -0.696896 0.707179 -0.091243 -0.701123 0.707179 -0.091243 -0.701123 0.70718 -0.062846 -0.704235 0.70718 -0.062846 -0.704235 0.70718 -0.034139 -0.706209 0.70718 -0.034139 -0.706209 0.707181 -0.005263 -0.707013 0.707181 -0.005263 -0.707013 0.707181 0.02364 -0.706637 0.707181 0.02364 -0.706637 0.70718 0.052424 -0.705087 0.70718 0.052424 -0.705087 0.707179 0.08095 -0.702385 0.707179 0.08095 -0.702385 0.707176 0.109082 -0.698572 0.707176 0.109082 -0.698572 0.707183 0.136689 -0.693692 0.707183 0.136689 -0.693692 0.70715 0.166217 -0.687249 0.70715 0.166217 -0.687249 0.706988 0.182058 -0.683391 0.706988 0.182058 -0.683391 0 0.963965 -0.266028 0 0.858459 -0.512883 0 0.858459 -0.512883 0 0.963965 -0.266028 -0.707107 0.172787 -0.685671 -0.707107 0.172787 -0.685671 -0.70702 0.161096 -0.6886 -0.70702 0.161096 -0.6886 -0.706831 0.149381 -0.691429 -0.706831 0.149381 -0.691429 0.033815 -0.547248 -0.836287 0.033815 -0.547248 -0.836287 0.004617 -0.553097 -0.833104 0.004617 -0.553097 -0.833104 -0.053305 -0.556525 -0.829119 -0.053305 -0.556525 -0.829119 -0.11767 -0.548715 -0.827687 -0.11767 -0.548715 -0.827687 -0.205838 -0.537384 -0.817832 -0.205838 -0.537384 -0.817832 -0.300812 -0.521968 -0.798162 -0.300812 -0.521968 -0.798162 -0.395796 -0.485618 -0.779436 -0.395796 -0.485618 -0.779436 -0.446295 -0.465851 -0.764071 -0.446295 -0.465851 -0.764071 -0.488825 -0.442042 -0.752096 -0.488825 -0.442042 -0.752096 -0.529339 -0.41641 -0.739191 -0.529339 -0.41641 -0.739191 -0.527935 -0.424394 -0.735646 -0.527935 -0.424394 -0.735646 -0.534468 0.490127 -0.688564 -0.534468 0.490127 -0.688564 -0.534485 0.485912 -0.691531 -0.534485 0.485912 -0.691531 -0.509859 0.500669 -0.699553 -0.509859 0.500669 -0.699553 -0.48532 0.510523 -0.70981 -0.48532 0.510523 -0.70981 -0.446029 0.527334 -0.723171 -0.446029 0.527334 -0.723171 -0.404776 0.545676 -0.733753 -0.404776 0.545676 -0.733753 -0.3622 0.558877 -0.745968 -0.3622 0.558877 -0.745968 -0.317901 0.565781 -0.760809 -0.317901 0.565781 -0.760809 -0.271344 0.567167 -0.777621 -0.271344 0.567167 -0.777621 -0.186637 0.589374 -0.786006 -0.186637 0.589374 -0.786006 -0.112009 0.605322 -0.78806 -0.112009 0.605322 -0.78806 -0.031785 0.61312 -0.78935 -0.031785 0.61312 -0.78935 0.045784 0.612651 -0.789027 0.045784 0.612651 -0.789027 0.078536 0.610142 -0.78839 0.078536 0.610142 -0.78839 -0.707106 -0.087107 -0.701721 -0.707106 -0.087107 -0.701721 -0.707127 -0.094692 -0.700718 -0.707127 -0.094692 -0.700718 -0.707106 -0.102271 -0.699673 -0.707106 -0.102271 -0.699673 0.397809 -0.648475 -0.649022 0.397809 -0.648475 -0.649022 0.41358 -0.620916 -0.665894 0.41358 -0.620916 -0.665894 0.436024 -0.590005 -0.679542 0.436024 -0.590005 -0.679542 0.439488 -0.579864 -0.686009 0.439488 -0.579864 -0.686009 -0.367016 -0.630022 -0.684377 -0.367016 -0.630022 -0.684377 -0.365922 -0.63692 -0.678553 -0.365922 -0.63692 -0.678553 -0.364798 -0.643765 -0.672674 -0.364798 -0.643765 -0.672674 -0.467927 0.479146 -0.742606 -0.467927 0.479146 -0.742606 -0.42471 0.508844 -0.748799 -0.42471 0.508844 -0.748799 -0.378683 0.53092 -0.758105 -0.378683 0.53092 -0.758105 -0.341463 0.538106 -0.770613 -0.341463 0.538106 -0.770613 -0.305478 0.542832 -0.782315 -0.305478 0.542832 -0.782315 -0.277158 0.542866 -0.792767 -0.277158 0.542866 -0.792767 -0.225809 0.553701 -0.801514 -0.225809 0.553701 -0.801514 -0.201954 0.548944 -0.811095 -0.201954 0.548944 -0.811095 -0.176573 0.543463 -0.820652 -0.176573 0.543463 -0.820652 -0.124922 0.550381 -0.825515 -0.124922 0.550381 -0.825515 -0.0653 0.558069 -0.827221 -0.0653 0.558069 -0.827221 -0.005806 0.561138 -0.827702 -0.005806 0.561138 -0.827702 0.038187 0.560468 -0.827295 0.038187 0.560468 -0.827295 0.055066 0.559619 -0.826919 0.055066 0.559619 -0.826919 -0.711047 -0.146622 -0.687687 -0.711047 -0.146622 -0.687687 -0.709106 -0.155475 -0.687747 -0.709106 -0.155475 -0.687747 -0.707106 -0.164314 -0.687751 -0.707106 -0.164314 -0.687751 -0.00004 -0.962313 -0.271944 -0.000032 -0.852093 -0.523391 -0.000032 -0.852093 -0.523391 -0.00004 -0.962313 -0.271944 0.706819 -0.179105 -0.684345 0.706819 -0.179105 -0.684345 0.707181 -0.156107 -0.689583 0.707181 -0.156107 -0.689583 0.000203 -0.211888 -0.977294 0.000203 -0.211888 -0.977294 0.000405 -0.191256 -0.98154 0.000405 -0.191256 -0.98154 0.000405 -0.191256 -0.98154 0.000405 -0.191256 -0.98154 0.000405 -0.191256 -0.98154 0.000405 -0.191256 -0.98154 0.000508 -0.171875 -0.985119 0.000508 -0.171875 -0.985119 0.00061 -0.152428 -0.988314 0.00061 -0.152428 -0.988314 0.000826 -0.132426 -0.991192 0.000826 -0.132426 -0.991192 0.001041 -0.11237 -0.993666 0.001274 -0.090516 -0.995894 0.001274 -0.090516 -0.995894 0.001043 -0.048222 -0.998836 0.001507 -0.068618 -0.997642 0.001507 -0.068618 -0.997642 0.001043 -0.048222 -0.998836 0.000401 -0.048473 -0.998824 0.000224 -0.069119 -0.997608 -0.000152 -0.08889 -0.996041 -0.000152 -0.08889 -0.996041 0.000224 -0.069119 -0.997608 0.000401 -0.048473 -0.998824 0.000554 -0.008346 -0.999965 0.000554 -0.008346 -0.999965 0.000528 0.011116 -0.999938 0.000444 0.032503 -0.999471 0.000444 0.032503 -0.999471 0.00039 0.07508 -0.997177 0.000359 0.053875 -0.998548 0.00039 0.07508 -0.997177 0.000385 0.116397 -0.993203 0.000421 0.096251 -0.995357 0.000385 0.116397 -0.993203 0.000302 0.156323 -0.987706 0.000348 0.136494 -0.990641 0.000302 0.156323 -0.987706 -0.00003 0.228758 -0.973483 0.000000 0.244348 -0.969688 0.000000 0.244348 -0.969688 -0.00003 0.228758 -0.973483 0.000001 -0.232426 -0.972614 0.000001 -0.232426 -0.972614 0.000098 0.194633 -0.980876 0.000098 0.194633 -0.980876 -0.00006 0.213109 -0.977029 0.000579 -0.027806 -0.999613 0.000579 -0.027806 -0.999613 0.000423 -0.147819 -0.989014 0.000423 -0.147819 -0.989014 0.000423 -0.147819 -0.989014 0.000423 -0.147819 -0.989014 0.000423 -0.147819 -0.989014 0.999757 -0.022033 0 0.999939 -0.011017 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 -0.000000 0 1 -0.000000 0 1 0.000000 0 0.999976 0.006975 0 0.999903 0.01395 0 -1 0 0 -1 0 0 0.064651 0.997908 0 0.11088 0.993834 0 -0.044859 0.998993 0 -0.158474 0.987363 0 -0.266266 0.9639 0 -0.38482 0.922992 0 -0.445065 0.895498 0 -0.507952 0.861386 0 -0.568238 0.822864 0 -0.62773 0.778431 0 -0.683761 0.729706 0 -0.720029 0.693944 0 -0.754429 0.656382 0 -0.754428 0.656383 0 -0.747462 -0.664305 0 -0.747461 -0.664305 0 -0.689816 -0.723985 0 -0.62742 -0.778681 0 -0.556214 -0.831039 0 -0.42053 -0.907278 0 -0.164792 -0.986328 0 -0.287562 -0.957762 0 -0.07421 -0.997243 0 0.009972 -0.99995 0 0.054094 -0.998536 0 -1 0 0 -1 0.000000 0 -1 0 0 0.052198 0.998637 0 0.075237 0.997166 0 -0.007962 0.999968 0 -0.089828 0.995957 0 -0.173415 0.984849 0 -0.245989 0.969273 0 -0.279547 0.960132 0 -0.313848 0.949473 0 -0.387649 0.921807 0 -0.426842 0.904326 0 -0.479397 0.877598 0 -0.530286 0.847819 0 -0.596279 0.802777 0 -0.658466 0.75261 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -0.516125 -0.856513 0 -1 0.000057 0 -1 0.000056 0 -1 0.000057 0 -1 0 0 -1 0 0 -1 0 0 0.080788 -0.996731 0 0.037531 -0.999295 0 -0.063779 -0.997964 0 -0.166099 -0.986109 0 -0.265935 -0.963991 0 -0.388515 -0.921443 0 -0.528507 -0.848929 0 -0.598874 -0.800843 0 -0.668319 -0.743875 0 -0.732372 -0.680905 0 -0.763746 0.645517 0 -0.861205 0.508258 0 -0.644643 0.764484 0 -0.644643 0.764484 0 -0.644643 0.764484 0 0.853884 0.520463 0 0.853884 0.520463 0 0.847487 0.530817 0 0.815813 0.578315 0 0.789016 0.614372 0 0.74052 0.672034 0 0.619963 0.784631 0 0.469757 0.882796 0 0.297684 0.954664 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -0.276483 -0.961019 0 -0.232434 -0.972612 0 -0.141714 -0.989908 0 -0.040904 -0.999163 0 0.08424 -0.996445 0 0.213397 -0.976966 0 0.336165 -0.941803 0 0.465892 -0.884842 0 0.529956 -0.848025 0 0.593642 -0.804729 0 0.709408 -0.704798 0 0.761237 -0.648474 0 0.761565 -0.648089 0 1 0.000000 0 1 -0.000000 0 1 0.000000 0 0.485371 0.874308 0 0.426526 0.904475 0 0.59547 0.803377 0 0.700806 0.713352 0 0.86019 0.509974 0 0.809301 0.587395 0 0.902026 0.431681 0 0.936755 0.349986 0 0.716877 -0.6972 0 0.716877 -0.697199 0 0.652278 -0.75798 0 0.508357 -0.861147 0 0.355938 -0.934509 0 0.213481 -0.976947 0 0.075712 -0.99713 0 0.004441 -0.99999 0 1 0.00051 0 1 0.000511 0 1 0.000512 0 1 0.000138 0 1 0.000138 0 1 0.000138 0 0.203968 0.978978 0 1 -0.00035 0 1 -0.00035 0 -1 0 0 -0.000508 -0.125393 -0.992107 -0.00053 -0.108627 -0.994083 -0.00053 -0.108627 -0.994083 -0.00053 -0.108627 -0.994083 -0.00053 -0.108627 -0.994083 -0.00053 -0.108627 -0.994083 -0.00053 -0.108627 -0.994083 -0.00053 -0.108627 -0.994083 -0.000508 -0.125393 -0.992107 -0.000485 -0.142123 -0.989849 -0.000485 -0.142123 -0.989849 -0.000485 -0.142123 -0.989849 -0.000485 -0.142123 -0.989849 0.019512 -0.803456 -0.595044 0.019512 -0.803456 -0.595044 -0.032215 -0.806328 -0.590591 -0.032215 -0.806328 -0.590591 0.122461 -0.790602 -0.599959 0.122461 -0.790602 -0.599959 0.220085 -0.764671 -0.605675 0.220085 -0.764671 -0.605675 0.300116 -0.729489 -0.614635 0.300116 -0.729489 -0.614635 0.367775 -0.684044 -0.629941 0.367775 -0.684044 -0.629941 0.000257 0.176089 -0.984374 0.000257 0.176089 -0.984374 0.000257 0.176089 -0.984374 -0.205905 -0.978572 0 -0.158988 -0.98728 0 -0.310072 -0.950713 0 -0.435501 -0.900188 0 -0.870389 -0.492366 0 -0.824255 -0.566218 0 -0.901934 -0.431875 0 -0.92928 -0.369377 0 -0.576757 -0.816916 0 -0.712295 -0.701881 0 -0.565232 0.824932 0 -0.61379 0.789469 0 -0.509645 0.860385 0 -0.315332 0.948981 0 -0.405896 0.913919 0 -0.233218 0.972424 0 -0.161428 0.986884 0 -0.127677 0.991816 0 -0.21282 0.977091 0 -0.174323 0.984689 0 -0.290516 0.95687 0 -0.378776 0.925488 0 -0.485349 0.874321 0 -0.610793 0.79179 0 -0.008433 0.999965 0 0.05699 0.998375 0 0.81642 0.577459 0 0.736679 0.676242 0 0.573223 0.819399 0 0.49667 0.867939 0 0.425716 0.904857 0 0.289842 0.957074 0 0.174528 0.984652 0 0.583524 -0.812096 0 0.614555 -0.788874 0 0.555457 -0.831546 0 0.509683 -0.860362 0 0.308589 -0.951196 0 0.41761 -0.908627 0 0.172919 -0.984936 0 0.02723 -0.999629 0 0.618186 -0.786032 0 -0.046588 -0.998914 0 0.906835 0.421486 0 0.935334 0.353767 0 0.87344 0.486931 0 0.827198 0.561911 0 0.507246 0.861801 0 0.579933 0.814664 0 0.44184 0.897094 0 0.319092 0.947724 0 0.221301 0.975205 0 0.179093 0.983832 0 0.714315 0.699825 0 0.2395 -0.970896 0 0.16305 -0.986618 0 0.334227 -0.942493 0 0.452349 -0.891841 0 0.128425 -0.991719 0 0.586695 -0.809808 0 0.716841 -0.697236 0 -0.000932 -0.049225 -0.998787 -0.000932 -0.049225 -0.998787 -0.001272 -0.069709 -0.997567 -0.001272 -0.069709 -0.997567 -0.001272 -0.069709 -0.997567 -0.001272 -0.069709 -0.997567 -0.000592 -0.028721 -0.999587 -0.000592 -0.028721 -0.999587 -0.538021 -0.485817 -0.688851 -0.538021 -0.485817 -0.688851 -0.905525 -0.424293 0 -0.938229 -0.346014 0 -0.864605 -0.502452 0 -0.507276 -0.861784 0 -0.386316 -0.922366 0 -0.286195 -0.958171 0 -0.240746 -0.970588 0 -0.763536 -0.645766 0 -0.640223 -0.768189 0 -0.929279 -0.369379 0 -0.929279 -0.369379 0 -0.660129 0.751152 0 -0.660129 0.751152 0 -0.660129 0.751152 0 -0.929279 -0.369379 0 -0.660129 0.751152 0 -0.660129 0.751152 0 0.935334 0.353765 0 0.935335 0.353764 0 0.775005 -0.631955 0 0.775005 -0.631955 0 0.935334 0.353766 0 0.775005 -0.631955 0 -0.675554 0.737311 0 -0.675554 0.737311 0 -0.675554 0.737311 0 -0.964181 -0.265245 0 -0.964181 -0.265244 0 -0.964181 -0.265244 0 -0.675552 0.737312 0 -0.675552 0.737312 0 -0.675552 0.737312 0</float_array>
+ <technique_common>
+ <accessor source="#NVIDIA_symbol-normals-array" count="1949" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="NVIDIA_symbol-Texture" name="Texture">
+ <float_array id="NVIDIA_symbol-Texture-array" count="784">0.277227 0.572807 0.298134 0.595451 0.29558 0.602308 0.273951 0.578882 0.319845 0.611086 0.318057 0.618494 0.33951 0.619733 0.338439 0.627456 0.35577 0.623374 0.35539 0.631252 0.373077 0.62349 0.368075 0.631337 0.373071 0.639845 0.368072 0.640447 0.37305 0.701607 0.368054 0.693309 0.345575 0.694256 0.346645 0.687584 0.317241 0.683154 0.318701 0.676635 0.283145 0.665169 0.285047 0.658883 0.247652 0.639845 0.250088 0.633795 0.209557 0.60275 0.212624 0.597088 0.185692 0.523172 0.197218 0.485999 0.201745 0.489161 0.1904 0.525814 0.204824 0.46147 0.209164 0.465147 0.260145 0.362843 0.289318 0.332152 0.292182 0.337672 0.263363 0.368194 0.297786 0.323244 0.300338 0.328953 0.332055 0.297851 0.333999 0.30401 0.358356 0.283909 0.359797 0.290335 0.373086 0.278387 0.368087 0.287231 0.373086 0.332152 0.368087 0.331444 0.373086 0.349573 0.368087 0.344339 0.351815 0.364732 0.349378 0.35767 0.332615 0.383449 0.329628 0.376923 0.312594 0.409075 0.309079 0.403329 0.289446 0.448918 0.285382 0.444331 0.274899 0.485999 0.270598 0.482061 0.271648 0.494284 0.267121 0.491028 0.259171 0.544752 0.25338 0.546607 0.270865 0.562922 0.26728 0.568429 0.180792 0.562922 0.184171 0.557647 0.178926 0.560338 0.51581 0.381245 0.54528 0.409075 0.542628 0.415094 0.513471 0.387447 0.560381 0.423337 0.557403 0.42922 0.60837 0.485999 0.604813 0.491297 0.651777 0.562922 0.64797 0.568006 0.658466 0.5748 0.652144 0.57566 0.628021 0.639845 0.624304 0.635271 0.581148 0.699642 0.578261 0.694307 0.561344 0.716768 0.558848 0.711141 0.529373 0.744415 0.527223 0.738643 0.480747 0.772053 0.479282 0.765891 0.439115 0.786676 0.438232 0.780309 0.40832 0.792404 0.408031 0.785926 0.373086 0.791955 0.378086 0.785545 0.373086 0.716768 0.378086 0.717692 0.373086 0.701613 0.378086 0.710591 0.392881 0.704037 0.392692 0.71238 0.415334 0.703841 0.415656 0.712179 0.433777 0.700428 0.434612 0.708671 0.459226 0.692155 0.460563 0.700235 0.489105 0.676867 0.491059 0.684633 0.520837 0.652413 0.523495 0.659639 0.531959 0.639845 0.534958 0.646427 0.548981 0.620608 0.55234 0.626668 0.57202 0.58316 0.57822 0.584602 0.569811 0.577503 0.573686 0.572996 0.558368 0.562922 0.561592 0.557338 0.498003 0.485999 0.501226 0.480231 0.488002 0.473254 0.486767 0.461593 0.482862 0.485999 0.478592 0.482029 0.470122 0.517583 0.465885 0.513686 0.45703 0.548331 0.452947 0.544057 0.449513 0.562922 0.445567 0.558532 0.444133 0.573362 0.440419 0.568653 0.431552 0.591377 0.428438 0.585809 0.418683 0.604088 0.416322 0.597776 0.403176 0.613972 0.401678 0.607109 0.373086 0.623446 0.378086 0.614536 0.373086 0.562922 0.378086 0.563158 0.373086 0.485999 0.378086 0.485942 0.373086 0.409075 0.378086 0.408728 0.378086 0.35476 0.385451 0.344197 0.386618 0.351053 0.399008 0.340278 0.399719 0.347265 0.413417 0.338195 0.413623 0.345255 0.427809 0.338489 0.427385 0.345537 0.447205 0.343074 0.446133 0.349968 0.477312 0.355908 0.475623 0.362539 0.214238 0.716768 0.224895 0.726468 0.222614 0.734068 0.211647 0.724028 0.275005 0.758186 0.273318 0.766162 0.319237 0.777763 0.318027 0.78595 0.352856 0.787997 0.352031 0.796302 0.373069 0.791953 0.368071 0.799722 0.373086 0.86504 0.368085 0.857858 0.354627 0.861449 0.355449 0.855404 0.317624 0.850332 0.31881 0.844397 0.265151 0.828 0.26675 0.822242 0.206108 0.793691 0.208159 0.788012 0.129657 0.735176 0.132226 0.729625 0.111879 0.716768 0.114717 0.711409 0.05457 0.657428 0.057652 0.652244 0.041331 0.639845 0.044635 0.634712 0 0.584955 0.005946 0.583255 0.005795 0.562922 0.010441 0.565939 0.017843 0.517118 0.022363 0.520511 0.029492 0.485999 0.033843 0.489616 0.058287 0.409075 0.062425 0.412994 0.10017 0.332152 0.10403 0.336329 0.107814 0.318211 0.111392 0.322639 0.15692 0.255229 0.160169 0.260001 0.167436 0.241741 0.170357 0.246578 0.239781 0.178306 0.300777 0.141978 0.302355 0.147647 0.241639 0.183907 0.348006 0.123364 0.349056 0.129243 0.373086 0.117261 0.368086 0.124616 0.373081 0.178306 0.368081 0.176988 0.373079 0.194959 0.36808 0.187513 0.361171 0.198235 0.36005 0.189722 0.330541 0.210857 0.328927 0.202547 0.287043 0.237365 0.284811 0.229429 0.266959 0.255229 0.264407 0.247819 0.236529 0.282295 0.233607 0.275316 0.197778 0.332152 0.194529 0.325725 0.18972 0.342521 0.186129 0.336712 0.153753 0.409075 0.149878 0.403883 0.150738 0.414655 0.146586 0.410185 0.124419 0.485999 0.120052 0.482204 0.120116 0.497662 0.11557 0.494592 0.103782 0.562922 0.099106 0.560444 0.102135 0.569505 0.09644 0.571351 0.13323 0.627133 0.129629 0.632859 0.142981 0.639845 0.13971 0.646128 0.17364 0.679813 0.170688 0.686664 1 0.178306 1 0.255229 0.995 0.254254 0.995 0.177032 1 0.332152 0.995 0.331481 1 0.409075 0.995 0.408711 1 0.485999 0.995 0.485942 1 0.562922 0.995 0.563174 1 0.639845 0.995 0.640405 1 0.716768 0.995 0.717633 1 0.793691 0.995 0.794857 1 0.870614 0.995 0.872075 1 0.947537 0.995 0.949214 0.999516 1 0.994583 0.99452 0.373086 1 0.378086 0.99452 0.373086 0.947537 0.378086 0.949259 0.373086 0.8651 0.378086 0.874508 0.392782 0.866713 0.392731 0.87558 0.415184 0.865555 0.415562 0.874401 0.457975 0.858126 0.458814 0.866893 0.515794 0.838889 0.517201 0.847468 0.59368 0.793691 0.655064 0.742845 0.657872 0.750093 0.596104 0.80135 0.67648 0.716768 0.679629 0.72344 0.719311 0.664615 0.722779 0.670785 0.733879 0.639845 0.73762 0.645375 0.76618 0.584922 0.772834 0.585379 0.753513 0.562922 0.757286 0.558214 0.737817 0.535658 0.741422 0.530509 0.702747 0.485999 0.706166 0.480426 0.665539 0.43331 0.668687 0.427204 0.642316 0.409075 0.645159 0.402481 0.596868 0.361648 0.599418 0.354673 0.557596 0.332152 0.559828 0.324758 0.535028 0.315202 0.536964 0.307339 0.483246 0.288506 0.484587 0.280338 0.444746 0.27609 0.445545 0.267747 0.422753 0.272485 0.422979 0.264049 0.40255 0.273043 0.402224 0.264623 0.373086 0.278011 0.378086 0.268693 0.373086 0.255229 0.378086 0.254217 0.373086 0.195152 0.378086 0.200981 0.693409 0.332152 0.71991 0.358903 0.716986 0.364554 0.690625 0.337731 0.762936 0.409075 0.759861 0.41467 0.812211 0.467638 0.811834 0.47659 0.876522 0.409075 0.879104 0.415188 0.923862 0.365966 0.932296 0.366576 0.909964 0.34759 0.91296 0.341008 0.893631 0.332152 0.89629 0.325085 0.850299 0.291195 0.852711 0.283775 0.799875 0.255229 0.802024 0.247506 0.778558 0.240024 0.780514 0.232012 0.699236 0.195566 0.700824 0.187348 0.660009 0.178306 0.661425 0.169888 0.616828 0.159307 0.618078 0.150694 0.535828 0.132736 0.536712 0.124005 0.460732 0.117341 0.46119 0.108522 0.411947 0.114017 0.411988 0.105169 0.394297 0.114794 0.39403 0.10596 0.373091 0.117212 0.37809 0.107776 0.37309 0.101383 0.37809 0.099735 0.373086 0.000043 0.378086 0.005635 0.998522 0 0.993628 0.005592 1 0.101383 0.995 0.099872 0.601248 0.261174 0.664766 0.311339 0.42436 0.197899 0.490786 0.208079 0.552409 0.231511 0.424638 0.191519 0.491663 0.201792 0.55397 0.225484 0.603121 0.255229 0.667361 0.305858 0.232955 0.413975 0.229276 0.409123</float_array>
+ <technique_common>
+ <accessor source="#NVIDIA_symbol-Texture-array" count="392" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="NVIDIA_symbol-vertices">
+ <input semantic="POSITION" source="#NVIDIA_symbol-positions"/>
+ </vertices>
+ <triangles material="NVIDIA_symbolSG" count="1920">
+ <input semantic="VERTEX" source="#NVIDIA_symbol-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#NVIDIA_symbol-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#NVIDIA_symbol-Texture" offset="2" set="1"/>
+ <p>120 0 0 119 1 1 213 3 3 213 3 3 119 1 1 212 2 2 118 4 4 211 5 5 119 1 1 119 1 1 211 5 5 212 2 2 117 6 6 210 7 7 118 4 4 118 4 4 210 7 7 211 5 5 116 8 8 209 9 9 117 6 6 117 6 6 209 9 9 210 7 7 115 10 10 208 11 11 116 8 8 116 8 8 208 11 11 209 9 9 115 12 10 180 13 12 208 15 11 208 15 11 180 13 12 226 14 13 114 16 14 207 17 15 180 13 12 180 13 12 207 17 15 226 14 13 114 18 14 113 19 16 207 21 15 207 21 15 113 19 16 206 20 17 113 19 16 112 22 18 206 20 17 206 20 17 112 22 18 205 23 19 111 24 20 204 25 21 112 22 18 112 22 18 204 25 21 205 23 19 179 26 22 225 27 23 111 24 20 111 24 20 225 27 23 204 25 21 110 28 24 203 29 25 179 26 22 179 26 22 203 29 25 225 27 23 108 30 26 175 31 27 202 33 29 202 33 29 175 31 27 222 32 28 107 34 30 201 35 31 175 31 27 175 31 27 201 35 31 222 32 28 106 36 32 172 37 33 200 39 35 200 39 35 172 37 33 219 38 34 105 40 36 199 41 37 172 37 33 172 37 33 199 41 37 219 38 34 105 40 36 104 42 38 199 41 37 199 41 37 104 42 38 198 43 39 104 42 38 103 44 40 198 43 39 198 43 39 103 44 40 197 45 41 102 46 42 196 47 43 103 44 40 103 44 40 196 47 43 197 45 41 102 48 42 173 49 44 196 51 43 196 51 43 173 49 44 220 50 45 101 52 46 195 53 47 173 49 44 173 49 44 195 53 47 220 50 45 101 54 46 125 55 48 195 57 47 195 57 47 125 55 48 218 56 49 125 55 48 124 58 50 218 56 49 218 56 49 124 58 50 217 59 51 124 58 50 174 60 52 217 59 51 217 59 51 174 60 52 221 61 53 174 60 52 123 62 54 221 61 53 221 61 53 123 62 54 216 63 55 176 64 56 223 65 57 123 62 54 123 62 54 223 65 57 216 63 55 176 64 56 122 66 58 223 65 57 223 65 57 122 66 58 215 67 59 122 66 58 121 68 60 215 67 59 215 67 59 121 68 60 214 69 61 178 71 62 224 72 63 121 70 60 121 70 60 224 72 63 214 73 61 178 71 62 120 0 0 224 72 63 224 72 63 120 0 0 213 3 3 225 79 23 226 74 13 204 78 21 204 78 21 226 74 13 205 77 19 205 77 19 226 74 13 206 76 17 226 74 13 207 75 15 206 76 17 219 81 34 199 82 37 220 80 45 199 82 37 198 83 39 220 80 45 196 85 43 220 80 45 197 84 41 220 80 45 198 83 39 197 84 41 110 28 24 177 86 64 203 29 25 203 29 25 177 86 64 227 87 65 177 86 64 109 88 66 227 87 65 109 89 66 108 30 26 227 90 65 227 90 65 108 30 26 202 33 29 224 95 63 227 96 65 214 94 61 223 92 57 215 93 59 222 91 28 227 96 65 202 97 29 214 94 61 215 93 59 214 94 61 222 91 28 222 91 28 214 94 61 202 97 29 227 96 65 224 95 63 203 104 25 203 104 25 224 95 63 225 79 23 224 95 63 213 98 3 225 79 23 213 98 3 212 99 2 225 79 23 226 74 13 225 79 23 208 103 11 208 103 11 225 79 23 209 102 9 209 102 9 225 79 23 210 101 7 210 101 7 225 79 23 211 100 5 212 99 2 211 100 5 225 79 23 77 105 67 182 106 68 238 108 70 238 108 70 182 106 68 263 107 69 76 109 71 237 110 72 182 106 68 182 106 68 237 110 72 263 107 69 76 109 71 186 111 73 237 110 72 237 110 72 186 111 73 267 112 74 186 111 73 187 113 75 267 112 74 267 112 74 187 113 75 268 114 76 75 115 77 236 116 78 187 113 75 187 113 75 236 116 78 268 114 76 75 117 77 191 118 79 236 120 78 236 120 78 191 118 79 272 119 80 191 118 79 74 121 81 272 119 80 272 119 80 74 121 81 235 122 82 74 121 81 193 123 83 235 122 82 235 122 82 193 123 83 274 124 84 73 125 85 234 126 86 193 123 83 193 123 83 234 126 86 274 124 84 73 125 85 72 127 87 234 126 86 234 126 86 72 127 87 233 128 88 72 127 87 71 129 89 233 128 88 233 128 88 71 129 89 232 130 90 70 131 91 231 132 92 71 129 89 71 129 89 231 132 92 232 130 90 1 133 93 228 134 94 70 131 91 70 131 91 228 134 94 231 132 92 1 135 93 194 136 95 228 138 94 228 138 94 194 136 95 275 137 96 4 139 97 230 140 98 194 136 95 194 136 95 230 140 98 275 137 96 4 141 97 100 142 99 230 144 98 230 144 98 100 142 99 261 143 100 100 142 99 99 145 101 261 143 100 261 143 100 99 145 101 260 146 102 98 147 103 259 148 104 99 145 101 99 145 101 259 148 104 260 146 102 98 147 103 97 149 105 259 148 104 259 148 104 97 149 105 258 150 106 97 149 105 96 151 107 258 150 106 258 150 106 96 151 107 257 152 108 95 153 109 256 154 110 96 151 107 96 151 107 256 154 110 257 152 108 192 155 111 273 156 112 95 153 109 95 153 109 273 156 112 256 154 110 192 155 111 94 157 113 273 156 112 273 156 112 94 157 113 255 158 114 94 157 113 93 159 115 255 158 114 255 158 114 93 159 115 254 160 116 92 162 117 253 163 118 93 161 115 93 161 115 253 163 118 254 164 116 188 165 119 269 166 120 92 162 117 92 162 117 269 166 120 253 163 118 188 165 119 183 167 121 269 166 120 269 166 120 183 167 121 264 168 122 183 167 121 91 169 123 264 168 122 264 168 122 91 169 123 252 170 124 184 172 125 265 173 126 91 171 123 91 171 123 265 173 126 252 174 124 184 172 125 90 175 127 265 173 126 265 173 126 90 175 127 251 176 128 89 177 129 250 178 130 90 175 127 90 175 127 250 178 130 251 176 128 89 177 129 189 179 131 250 178 130 250 178 130 189 179 131 270 180 132 88 181 133 249 182 134 189 179 131 189 179 131 249 182 134 270 180 132 87 183 135 248 184 136 88 181 133 88 181 133 248 184 136 249 182 134 86 185 137 247 186 138 87 183 135 87 183 135 247 186 138 248 184 136 85 187 139 246 188 140 86 185 137 86 185 137 246 188 140 247 186 138 84 189 141 245 190 142 85 187 139 85 187 139 245 190 142 246 188 140 84 191 141 190 192 143 245 194 142 245 194 142 190 192 143 271 193 144 190 192 143 185 195 145 271 193 144 271 193 144 185 195 145 266 196 146 185 195 145 181 197 147 266 196 146 266 196 146 181 197 147 262 198 148 3 199 46 229 200 149 181 197 147 181 197 147 229 200 149 262 198 148 3 201 46 83 202 150 229 204 149 229 204 149 83 202 150 244 203 151 82 205 152 243 206 153 83 202 150 83 202 150 243 206 153 244 203 151 81 207 154 242 208 155 82 205 152 82 205 152 242 208 155 243 206 153 80 209 156 241 210 157 81 207 154 81 207 154 241 210 157 242 208 155 80 209 156 79 211 158 241 210 157 241 210 157 79 211 158 240 212 159 79 211 158 78 213 160 240 212 159 240 212 159 78 213 160 239 214 161 78 213 160 77 105 67 239 214 161 239 214 161 77 105 67 238 108 70 267 218 74 264 219 122 237 217 72 237 217 72 264 219 122 263 216 69 262 215 148 263 216 69 266 222 146 264 219 122 252 220 124 263 216 69 263 216 69 252 220 124 266 222 146 252 220 124 265 221 126 266 222 146 263 216 69 262 215 148 238 230 70 238 230 70 262 215 148 239 229 161 239 229 161 262 215 148 240 228 159 240 228 159 262 215 148 241 227 157 241 227 157 262 215 148 242 226 155 242 226 155 262 215 148 243 225 153 243 225 153 262 215 148 244 224 151 262 215 148 229 223 149 244 224 151 265 221 126 251 231 128 266 222 146 251 231 128 250 232 130 266 222 146 250 232 130 270 233 132 266 222 146 266 222 146 270 233 132 271 234 144 273 236 112 255 237 114 272 235 80 269 240 120 268 241 76 253 239 118 255 237 114 254 238 116 272 235 80 253 239 118 268 241 76 254 238 116 272 235 80 254 238 116 236 242 78 254 238 116 268 241 76 236 242 78 274 244 84 234 245 86 275 243 96 234 245 86 233 246 88 275 243 96 233 246 88 232 247 90 275 243 96 232 247 90 231 248 92 275 243 96 275 243 96 231 248 92 228 249 94 264 219 122 267 218 74 269 240 120 269 240 120 267 218 74 268 241 76 272 235 80 235 257 82 273 236 112 235 257 82 274 244 84 273 236 112 273 236 112 274 244 84 256 256 110 230 250 98 261 251 100 275 243 96 275 243 96 261 251 100 274 244 84 261 251 100 260 252 102 274 244 84 260 252 102 259 253 104 274 244 84 259 253 104 258 254 106 274 244 84 258 254 106 257 255 108 274 244 84 274 244 84 257 255 108 256 256 110 270 233 132 249 258 134 271 234 144 249 258 134 248 259 136 271 234 144 248 259 136 247 260 138 271 234 144 247 260 138 246 261 140 271 234 144 271 234 144 246 261 140 245 262 142 169 263 162 8 264 163 319 266 165 319 266 165 8 264 163 280 265 164 9 267 166 281 268 167 8 264 163 8 264 163 281 268 167 280 265 164 10 269 168 282 270 169 9 267 166 9 267 166 282 270 169 281 268 167 11 271 170 283 272 171 10 269 168 10 269 168 283 272 171 282 270 169 276 273 172 322 274 173 11 271 170 11 271 170 322 274 173 283 272 171 12 276 174 284 277 175 276 275 172 276 275 172 284 277 175 322 278 173 12 279 174 13 280 176 284 282 175 284 282 175 13 280 176 285 281 177 13 280 176 14 283 178 285 281 177 285 281 177 14 283 178 286 284 179 14 283 178 15 285 180 286 284 179 286 284 179 15 285 180 287 286 181 15 285 180 171 287 182 287 286 181 287 286 181 171 287 182 321 288 183 16 289 184 288 290 185 171 287 182 171 287 182 288 290 185 321 288 183 16 289 184 170 291 186 288 290 185 288 290 185 170 291 186 320 292 187 17 293 188 289 294 189 170 291 186 170 291 186 289 294 189 320 292 187 17 293 188 167 295 190 289 294 189 289 294 189 167 295 190 317 296 191 18 297 192 290 298 193 167 295 190 167 295 190 290 298 193 317 296 191 18 299 192 165 300 194 290 302 193 290 302 193 165 300 194 315 301 195 19 303 196 291 304 197 165 300 194 165 300 194 291 304 197 315 301 195 19 303 196 163 305 198 291 304 197 291 304 197 163 305 198 313 306 199 161 307 200 311 308 201 163 305 198 163 305 198 311 308 201 313 306 199 161 307 200 159 309 202 311 308 201 311 308 201 159 309 202 309 310 203 20 311 204 292 312 205 159 309 202 159 309 202 292 312 205 309 310 203 20 311 204 157 313 206 292 312 205 292 312 205 157 313 206 307 314 207 21 315 208 293 316 209 157 313 206 157 313 206 293 316 209 307 314 207 22 318 211 294 319 212 155 317 210 155 317 210 294 319 212 305 320 213 22 318 211 23 321 214 294 319 212 294 319 212 23 321 214 295 322 215 24 323 216 296 324 217 23 321 214 23 321 214 296 324 217 295 322 215 24 325 216 156 326 218 296 328 217 296 328 217 156 326 218 306 327 219 25 329 220 297 330 221 156 326 218 156 326 218 297 330 221 306 327 219 25 331 220 26 332 222 297 334 221 297 334 221 26 332 222 298 333 223 26 332 222 27 335 224 298 333 223 298 333 223 27 335 224 299 336 225 27 335 224 28 337 226 299 336 225 299 336 225 28 337 226 300 338 227 158 339 228 308 340 229 28 337 226 28 337 226 308 340 229 300 338 227 158 339 228 29 341 230 308 340 229 308 340 229 29 341 230 301 342 231 160 343 232 310 344 233 29 341 230 29 341 230 310 344 233 301 342 231 160 343 232 30 345 234 310 344 233 310 344 233 30 345 234 302 346 235 162 347 236 312 348 237 30 345 234 30 345 234 312 348 237 302 346 235 162 347 236 31 349 238 312 348 237 312 348 237 31 349 238 303 350 239 164 351 240 314 352 241 31 349 238 31 349 238 314 352 241 303 350 239 164 351 240 32 353 242 314 352 241 314 352 241 32 353 242 304 354 243 166 355 244 316 356 245 32 353 242 32 353 242 316 356 245 304 354 243 166 355 244 0 357 246 316 356 245 316 356 245 0 357 246 277 358 247 6 360 248 278 361 249 0 359 246 0 359 246 278 361 249 277 362 247 168 363 250 318 364 251 6 360 248 6 360 248 318 364 251 278 361 249 168 363 250 7 365 252 318 364 251 318 364 251 7 365 252 279 366 253 169 263 162 319 266 165 7 365 252 7 365 252 319 266 165 279 366 253 319 372 165 320 367 187 279 371 253 317 369 191 318 370 251 289 368 189 289 368 189 318 370 251 320 367 187 320 367 187 318 370 251 279 371 253 318 370 251 317 369 191 278 377 249 278 377 249 317 369 191 277 376 247 316 375 245 277 376 247 315 374 195 317 369 191 290 373 193 277 376 247 290 373 193 315 374 195 277 376 247 314 380 241 304 381 243 313 379 199 315 374 195 291 378 197 316 375 245 304 381 243 316 375 245 313 379 199 316 375 245 291 378 197 313 379 199 312 383 237 303 384 239 311 382 201 313 379 199 311 382 201 314 380 241 311 382 201 303 384 239 314 380 241 308 386 229 301 387 231 307 385 207 309 389 203 292 390 205 310 388 233 292 390 205 307 385 207 310 388 233 307 385 207 301 387 231 310 388 233 305 392 213 294 393 212 306 391 219 294 393 212 295 394 215 306 391 219 306 391 219 295 394 215 296 395 217 321 401 183 322 396 173 287 400 181 287 400 181 322 396 173 286 399 179 286 399 179 322 396 173 285 398 177 322 396 173 284 397 175 285 398 177 322 396 173 321 401 183 283 405 171 283 405 171 321 401 183 282 404 169 282 404 169 321 401 183 281 403 167 320 367 187 319 372 165 288 406 185 288 406 185 319 372 165 321 401 183 281 403 167 321 401 183 280 402 164 319 372 165 280 402 164 321 401 183 310 388 233 302 407 235 309 389 203 311 382 201 309 389 203 312 383 237 309 389 203 302 407 235 312 383 237 128 408 254 130 409 255 364 411 257 364 411 257 130 409 255 366 410 256 130 409 255 134 412 258 366 410 256 366 410 256 134 412 258 370 413 259 134 412 258 138 414 260 370 413 259 370 413 259 138 414 260 374 415 261 138 414 260 142 416 262 374 415 261 374 415 261 142 416 262 378 417 263 142 416 262 144 418 264 378 417 263 378 417 263 144 418 264 380 419 265 144 418 264 146 420 266 380 419 265 380 419 265 146 420 266 382 421 267 146 420 266 148 422 268 382 421 267 382 421 267 148 422 268 384 423 269 148 422 268 150 424 270 384 423 269 384 423 269 150 424 270 386 425 271 150 424 270 152 426 272 386 425 271 386 425 271 152 426 272 388 427 273 153 428 274 389 429 275 152 426 272 152 426 272 389 429 275 388 427 273 69 430 276 361 431 277 153 428 274 153 428 274 361 431 277 389 429 275 69 432 276 5 433 278 361 435 277 361 435 277 5 433 278 324 434 279 5 436 278 154 437 280 324 439 279 324 439 279 154 437 280 390 438 281 2 440 282 323 441 283 154 437 280 154 437 280 323 441 283 390 438 281 2 442 282 33 443 284 323 445 283 323 445 283 33 443 284 325 444 285 34 446 286 326 447 287 33 443 284 33 443 284 326 447 287 325 444 285 34 446 286 35 448 288 326 447 287 326 447 287 35 448 288 327 449 289 35 448 288 36 450 290 327 449 289 327 449 289 36 450 290 328 451 291 151 452 292 37 453 293 387 455 295 387 455 295 37 453 293 329 454 294 149 456 296 385 457 297 37 453 293 37 453 293 385 457 297 329 454 294 149 456 296 38 458 298 385 457 297 385 457 297 38 458 298 330 459 299 147 460 300 383 461 301 38 458 298 38 458 298 383 461 301 330 459 299 147 460 300 39 462 302 383 461 301 383 461 301 39 462 302 331 463 303 145 465 304 381 466 305 39 464 302 39 464 302 381 466 305 331 467 303 145 465 304 40 468 306 381 466 305 381 466 305 40 468 306 332 469 307 143 470 308 379 471 309 40 468 306 40 468 306 379 471 309 332 469 307 143 470 308 41 472 310 379 471 309 379 471 309 41 472 310 333 473 311 139 474 312 375 475 313 41 472 310 41 472 310 375 475 313 333 473 311 139 474 312 42 476 314 375 475 313 375 475 313 42 476 314 334 477 315 135 478 316 371 479 317 42 476 314 42 476 314 371 479 317 334 477 315 135 478 316 43 480 318 371 479 317 371 479 317 43 480 318 335 481 319 43 480 318 44 482 320 335 481 319 335 481 319 44 482 320 336 483 321 45 484 322 337 485 323 44 482 320 44 482 320 337 485 323 336 483 321 45 484 322 46 486 324 337 485 323 337 485 323 46 486 324 338 487 325 47 488 326 339 489 327 46 486 324 46 486 324 339 489 327 338 487 325 48 490 328 340 491 329 47 488 326 47 488 326 340 491 329 339 489 327 48 492 328 131 493 330 340 495 329 340 495 329 131 493 330 367 494 331 49 496 332 341 497 333 131 493 330 131 493 330 341 497 333 367 494 331 54 499 335 346 500 336 136 498 334 136 498 334 346 500 336 372 501 337 54 499 335 140 502 338 346 500 336 346 500 336 140 502 338 376 503 339 140 502 338 55 504 340 376 503 339 376 503 339 55 504 340 347 505 341 141 507 342 377 508 343 55 506 340 55 506 340 377 508 343 347 509 341 141 507 342 56 510 344 377 508 343 377 508 343 56 510 344 348 511 345 57 513 346 349 514 347 56 512 344 56 512 344 349 514 347 348 515 345 137 516 348 373 517 349 57 513 346 57 513 346 373 517 349 349 514 347 137 516 348 58 518 350 373 517 349 373 517 349 58 518 350 350 519 351 133 520 352 369 521 353 58 518 350 58 518 350 369 521 353 350 519 351 133 520 352 59 522 354 369 521 353 369 521 353 59 522 354 351 523 355 59 522 354 60 524 356 351 523 355 351 523 355 60 524 356 352 525 357 129 526 358 365 527 359 60 524 356 60 524 356 365 527 359 352 525 357 129 526 358 61 528 360 365 527 359 365 527 359 61 528 360 353 529 361 61 528 360 62 530 362 353 529 361 353 529 361 62 530 362 354 531 363 62 530 362 63 532 364 354 531 363 354 531 363 63 532 364 355 533 365 64 534 366 356 535 367 63 532 364 63 532 364 356 535 367 355 533 365 65 536 368 357 537 369 64 534 366 64 534 366 357 537 369 356 535 367 66 538 370 358 539 371 65 536 368 65 536 368 358 539 371 357 537 369 66 540 370 126 541 372 358 543 371 358 543 371 126 541 372 362 542 373 67 544 374 359 545 375 126 541 372 126 541 372 359 545 375 362 542 373 67 546 374 68 547 376 359 549 375 359 549 375 68 547 376 360 548 377 68 550 376 127 551 378 360 553 377 360 553 377 127 551 378 363 552 379 127 551 378 128 408 254 363 552 379 363 552 379 128 408 254 364 411 257 358 562 371 362 563 373 357 561 369 364 555 257 365 556 359 363 554 379 365 556 359 353 557 361 363 554 379 357 561 369 362 563 373 356 560 367 362 563 373 363 554 379 356 560 367 356 560 367 363 554 379 355 559 365 355 559 365 363 554 379 354 558 363 363 554 379 353 557 361 354 558 363 365 556 359 364 555 257 352 567 357 352 567 357 364 555 257 351 566 355 351 566 355 364 555 257 369 565 353 364 555 257 366 564 256 369 565 353 369 565 353 366 564 256 350 570 351 350 570 351 366 564 256 373 569 349 366 564 256 370 568 259 373 569 349 377 572 343 348 573 345 374 571 261 373 569 349 370 568 259 349 574 347 349 574 347 370 568 259 348 573 345 374 571 261 348 573 345 370 568 259 371 578 317 372 579 337 334 577 315 376 575 339 375 576 313 346 580 336 334 577 315 372 579 337 375 576 313 375 576 313 372 579 337 346 580 336 379 585 309 378 581 263 332 584 307 332 584 307 378 581 263 381 583 305 378 581 263 380 582 265 381 583 305 383 587 301 331 588 303 382 586 267 381 583 305 380 582 265 331 588 303 382 586 267 331 588 303 380 582 265 385 590 297 330 591 299 384 589 269 330 591 299 383 587 301 384 589 269 384 589 269 383 587 301 382 586 267 387 593 295 329 594 294 386 592 271 329 594 294 385 590 297 386 592 271 386 592 271 385 590 297 384 589 269 389 596 275 361 597 277 390 595 281 390 595 281 361 597 277 324 598 279 359 599 375 360 600 377 362 563 373 362 563 373 360 600 377 363 554 379 323 601 283 325 602 285 390 595 281 390 595 281 325 602 285 389 596 275 389 596 275 325 602 285 388 603 273 375 576 313 376 575 339 333 604 311 333 604 311 376 575 339 379 585 309 374 571 261 378 581 263 377 572 343 376 575 339 347 605 341 379 585 309 379 585 309 347 605 341 378 581 263 378 581 263 347 605 341 377 572 343 155 317 210 305 320 213 21 315 208 21 315 208 305 320 213 293 316 209 307 385 207 293 610 209 308 386 229 293 610 209 305 392 213 308 386 229 306 391 219 297 606 221 305 392 213 297 606 221 298 607 223 305 392 213 298 607 223 299 608 225 305 392 213 299 608 225 300 609 227 305 392 213 300 609 227 308 386 229 305 392 213 69 432 276 392 611 276 5 433 278 5 433 278 392 611 276 391 612 278 127 614 378 68 615 376 394 613 378 394 613 378 68 615 376 393 616 376 128 618 254 127 614 378 395 617 254 395 617 254 127 614 378 394 613 378 130 620 255 128 618 254 396 619 255 396 619 255 128 618 254 395 617 254 134 622 258 130 620 255 397 621 258 397 621 258 130 620 255 396 619 255 138 624 260 134 622 258 398 623 260 398 623 260 134 622 258 397 621 258 142 626 262 138 624 260 399 625 262 399 625 262 138 624 260 398 623 260 142 626 262 399 625 262 144 628 264 144 628 264 399 625 262 400 627 264 144 628 264 400 627 264 146 630 266 146 630 266 400 627 264 401 629 266 146 630 266 401 629 266 148 632 268 148 632 268 401 629 266 402 631 268 148 632 268 402 631 268 150 634 270 150 634 270 402 631 268 403 633 270 150 634 270 403 633 270 152 636 272 152 636 272 403 633 270 404 635 272 152 636 272 404 635 272 153 638 274 153 638 274 404 635 272 405 637 274 153 638 274 405 637 274 69 640 276 69 640 276 405 637 274 392 639 276 154 642 280 5 643 278 406 641 280 406 641 280 5 643 278 391 644 278 48 646 328 47 647 326 407 645 328 407 645 328 47 647 326 408 648 326 47 647 326 46 649 324 408 648 326 408 648 326 46 649 324 409 650 324 45 651 322 410 652 322 46 649 324 46 649 324 410 652 322 409 650 324 44 653 320 411 654 320 45 651 322 45 651 322 411 654 320 410 652 322 43 655 318 412 656 318 44 653 320 44 653 320 412 656 318 411 654 320 135 657 316 413 658 316 43 655 318 43 655 318 413 658 316 412 656 318 42 659 314 414 660 314 135 657 316 135 657 316 414 660 314 413 658 316 139 661 312 415 662 312 42 659 314 42 659 314 415 662 312 414 660 314 41 663 310 416 664 310 139 661 312 139 661 312 416 664 310 415 662 312 143 665 308 417 666 308 41 663 310 41 663 310 417 666 308 416 664 310 143 665 308 40 667 306 417 666 308 417 666 308 40 667 306 418 668 306 40 667 306 145 669 304 418 668 306 418 668 306 145 669 304 419 670 304 145 669 304 39 671 302 419 670 304 419 670 304 39 671 302 420 672 302 39 674 302 147 675 300 420 673 302 420 673 302 147 675 300 421 676 300 147 675 300 38 677 298 421 676 300 421 676 300 38 677 298 422 678 298 38 677 298 149 679 296 422 678 298 422 678 298 149 679 296 423 680 296 149 679 296 37 681 293 423 680 296 423 680 296 37 681 293 424 682 293 37 681 293 151 683 292 424 682 293 424 682 293 151 683 292 425 684 292 36 686 290 35 687 288 426 685 290 426 685 290 35 687 288 427 688 288 35 687 288 34 689 286 427 688 288 427 688 288 34 689 286 428 690 286 34 689 286 33 691 284 428 690 286 428 690 286 33 691 284 429 692 284 2 693 282 430 694 282 33 691 284 33 691 284 430 694 282 429 692 284 131 695 330 432 696 330 49 698 332 49 698 332 432 696 330 431 697 332 48 699 328 407 700 328 131 695 330 131 695 330 407 700 328 432 696 330 66 702 370 65 703 368 433 701 370 433 701 370 65 703 368 434 704 368 65 703 368 64 705 366 434 704 368 434 704 368 64 705 366 435 706 366 63 707 364 436 708 364 64 705 366 64 705 366 436 708 364 435 706 366 62 709 362 437 710 362 63 707 364 63 707 364 437 710 362 436 708 364 61 711 360 438 712 360 62 709 362 62 709 362 438 712 360 437 710 362 129 713 358 439 714 358 61 711 360 61 711 360 439 714 358 438 712 360 60 715 356 440 716 356 129 713 358 129 713 358 440 716 356 439 714 358 59 717 354 441 718 354 60 715 356 60 715 356 441 718 354 440 716 356 133 719 352 442 720 352 59 717 354 59 717 354 442 720 352 441 718 354 58 721 350 443 722 350 133 719 352 133 719 352 443 722 350 442 720 352 137 723 348 444 724 348 58 721 350 58 721 350 444 724 348 443 722 350 57 725 346 445 726 346 137 723 348 137 723 348 445 726 346 444 724 348 56 727 344 446 728 344 57 725 346 57 725 346 446 728 344 445 726 346 141 729 342 447 730 342 56 732 344 56 732 344 447 730 342 446 731 344 55 733 340 448 734 340 141 729 342 141 729 342 448 734 340 447 730 342 126 735 372 450 736 372 67 738 374 67 738 374 450 736 372 449 737 374 66 739 370 433 740 370 126 735 372 126 735 372 433 740 370 450 736 372 194 741 95 1 742 93 452 744 95 452 744 95 1 742 93 451 743 93 4 745 97 194 741 95 453 746 97 453 746 97 194 741 95 452 744 95 4 747 97 453 748 97 100 750 99 100 750 99 453 748 97 454 749 99 99 751 101 100 750 99 455 752 101 455 752 101 100 750 99 454 749 99 98 753 103 99 751 101 456 754 103 456 754 103 99 751 101 455 752 101 97 755 105 98 753 103 457 756 105 457 756 105 98 753 103 456 754 103 96 757 107 97 755 105 458 758 107 458 758 107 97 755 105 457 756 105 95 759 109 96 757 107 459 760 109 459 760 109 96 757 107 458 758 107 192 761 111 95 759 109 460 762 111 460 762 111 95 759 109 459 760 109 94 763 113 192 761 111 461 764 113 461 764 113 192 761 111 460 762 111 93 765 115 94 763 113 462 766 115 462 766 115 94 763 113 461 764 113 92 767 117 93 768 115 463 770 117 463 770 117 93 768 115 462 769 115 188 771 119 92 767 117 464 772 119 464 772 119 92 767 117 463 770 117 183 773 121 188 771 119 465 774 121 465 774 121 188 771 119 464 772 119 466 775 123 91 776 123 465 774 121 465 774 121 91 776 123 183 773 121 184 778 125 91 779 123 467 777 125 467 777 125 91 779 123 466 780 123 184 778 125 467 777 125 90 782 127 90 782 127 467 777 125 468 781 127 90 782 127 468 781 127 89 784 129 89 784 129 468 781 127 469 783 129 89 784 129 469 783 129 189 786 131 189 786 131 469 783 129 470 785 131 189 786 131 470 785 131 88 788 133 88 788 133 470 785 131 471 787 133 88 788 133 471 787 133 87 790 135 87 790 135 471 787 133 472 789 135 87 790 135 472 789 135 86 792 137 86 792 137 472 789 135 473 791 137 86 792 137 473 791 137 85 794 139 85 794 139 473 791 137 474 793 139 190 795 143 84 796 141 476 798 143 476 798 143 84 796 141 475 797 141 185 799 145 190 795 143 477 800 145 477 800 145 190 795 143 476 798 143 478 801 147 181 802 147 477 800 145 477 800 145 181 802 147 185 799 145 181 802 147 478 801 147 3 804 46 3 804 46 478 801 147 479 803 46 3 805 46 479 806 46 83 808 150 83 808 150 479 806 46 480 807 150 83 808 150 480 807 150 82 810 152 82 810 152 480 807 150 481 809 152 82 810 152 481 809 152 81 812 154 81 812 154 481 809 152 482 811 154 80 813 156 81 812 154 483 814 156 483 814 156 81 812 154 482 811 154 79 815 158 80 813 156 484 816 158 484 816 158 80 813 156 483 814 156 78 817 160 79 815 158 485 818 160 485 818 160 79 815 158 484 816 158 77 819 67 78 817 160 486 820 67 486 820 67 78 817 160 485 818 160 182 821 68 77 819 67 487 822 68 487 822 68 77 819 67 486 820 67 76 823 71 182 821 68 488 824 71 488 824 71 182 821 68 487 822 68 186 825 73 76 823 71 489 826 73 489 826 73 76 823 71 488 824 71 187 827 75 490 828 75 75 830 77 75 830 77 490 828 75 491 829 77 173 831 44 102 832 42 493 834 44 493 834 44 102 832 42 492 833 42 101 835 46 173 831 44 494 836 46 494 836 46 173 831 44 493 834 44 125 837 48 101 838 46 495 840 48 495 840 48 101 838 46 494 839 46 124 841 50 125 837 48 496 842 50 496 842 50 125 837 48 495 840 48 174 843 52 124 841 50 497 844 52 497 844 52 124 841 50 496 842 50 176 845 56 123 846 54 499 848 56 499 848 56 123 846 54 498 847 54 122 849 58 176 845 56 500 850 58 500 850 58 176 845 56 499 848 56 122 849 58 500 850 58 121 852 60 121 852 60 500 850 58 501 851 60 121 853 60 501 854 60 178 856 62 178 856 62 501 854 60 502 855 62 178 856 62 502 855 62 120 858 0 120 858 0 502 855 62 503 857 0 120 858 0 503 857 0 119 860 1 119 860 1 503 857 0 504 859 1 119 860 1 504 859 1 118 862 4 118 862 4 504 859 1 505 861 4 118 862 4 505 861 4 117 864 6 117 864 6 505 861 4 506 863 6 117 864 6 506 863 6 116 866 8 116 866 8 506 863 6 507 865 8 116 866 8 507 865 8 115 868 10 115 868 10 507 865 8 508 867 10 115 869 10 508 870 10 180 872 12 180 872 12 508 870 10 509 871 12 180 872 12 509 871 12 114 874 14 114 874 14 509 871 12 510 873 14 25 876 220 156 877 218 513 875 220 513 875 220 156 877 218 514 878 218 156 877 218 24 879 216 514 878 218 514 878 218 24 879 216 511 880 216 123 846 54 174 843 52 498 847 54 498 847 54 174 843 52 497 844 52 186 825 73 489 826 73 187 827 75 187 827 75 489 826 73 490 828 75 85 794 139 474 793 139 84 882 141 84 882 141 474 793 139 475 881 141 276 883 172 515 884 172 12 886 174 12 886 174 515 884 172 512 885 174 67 546 374 449 887 374 68 547 376 68 547 376 449 887 374 393 888 376 2 890 282 154 642 280 430 889 282 430 889 282 154 642 280 406 641 280 372 579 337 371 578 317 345 893 381 345 893 381 371 578 317 368 892 380 340 899 329 367 891 331 339 898 327 371 578 317 335 894 319 368 892 380 335 894 319 336 895 321 368 892 380 339 898 327 367 891 331 338 897 325 367 891 331 368 892 380 338 897 325 338 897 325 368 892 380 337 896 323 368 892 380 336 895 321 337 896 323 368 892 380 367 891 331 344 903 384 344 903 384 367 891 331 343 902 383 343 902 383 367 891 331 342 901 382 367 891 331 341 900 333 342 901 382 342 904 382 341 905 333 50 907 385 50 907 385 341 905 333 49 906 332 342 904 382 50 907 385 343 908 383 343 908 383 50 907 385 51 909 386 344 910 384 343 908 383 52 911 387 52 911 387 343 908 383 51 909 386 368 912 380 344 910 384 132 913 388 132 913 388 344 910 384 52 911 387 372 501 337 345 914 381 136 498 334 136 498 334 345 914 381 53 915 389 345 914 381 368 912 380 53 915 389 53 915 389 368 912 380 132 913 388 36 450 290 151 452 292 328 451 291 328 451 291 151 452 292 387 455 295 426 685 290 425 684 292 36 686 290 36 686 290 425 684 292 151 683 292 325 602 285 326 916 287 388 603 273 326 916 287 327 917 289 388 603 273 327 917 289 328 918 291 388 603 273 328 918 291 387 593 295 388 603 273 387 593 295 386 592 271 388 603 273 528 919 214 535 920 214 529 922 216 529 922 216 535 920 214 534 921 216 527 923 211 536 924 211 528 919 214 528 919 214 536 924 211 535 920 214 530 925 210 537 926 210 527 923 211 527 923 211 537 926 210 536 924 211 532 927 198 541 928 198 531 930 200 531 930 200 541 928 198 540 929 200 541 928 198 532 927 198 542 932 196 542 932 196 532 927 198 524 931 196 524 931 196 533 933 194 542 932 196 542 932 196 533 933 194 543 934 194 526 935 208 538 936 208 530 925 210 530 925 210 538 936 208 537 926 210 531 930 200 540 929 200 525 938 204 525 938 204 540 929 200 539 937 204 525 938 204 539 937 204 526 935 208 526 935 208 539 937 204 538 936 208 550 940 188 552 941 186 554 939 188 554 939 188 552 941 186 555 942 186 552 941 186 549 943 184 555 942 186 555 942 186 549 943 184 556 944 184 553 946 182 548 947 180 557 945 182 557 945 182 548 947 180 558 948 180 548 947 180 547 949 178 558 948 180 558 948 180 547 949 178 559 950 178 547 949 178 546 951 176 559 950 178 559 950 178 546 951 176 560 952 176 546 951 176 545 953 174 560 952 176 560 952 176 545 953 174 561 954 174 549 943 184 553 946 182 556 944 184 556 944 184 553 946 182 557 945 182 565 955 16 566 956 14 569 958 16 569 958 16 566 956 14 568 957 14 564 959 18 565 955 16 570 960 18 570 960 18 565 955 16 569 958 16 563 961 20 564 959 18 571 962 20 571 962 20 564 959 18 570 960 18 567 963 22 563 961 20 572 964 22 572 964 22 563 961 20 571 962 20 562 966 24 567 963 22 573 965 24 573 965 24 567 963 22 572 964 22 574 967 93 575 968 91 584 970 93 584 970 93 575 968 91 583 969 91 580 971 77 585 972 77 581 974 79 581 974 79 585 972 77 586 973 79 579 975 81 587 976 81 582 978 83 582 978 83 587 976 81 588 977 83 582 978 83 588 977 83 578 980 85 578 980 85 588 977 83 589 979 85 578 980 85 589 979 85 577 982 87 577 982 87 589 979 85 590 981 87 577 982 87 590 981 87 576 984 89 576 984 89 590 981 87 591 983 89 576 984 89 591 983 89 575 968 91 575 968 91 591 983 89 583 969 91 581 974 79 586 973 79 579 975 81 579 975 81 586 973 79 587 976 81 601 986 338 597 987 335 604 985 338 604 985 338 597 987 335 605 988 335 597 987 335 600 989 334 605 988 335 605 988 335 600 989 334 606 990 334 600 989 334 596 991 389 606 990 334 606 990 334 596 991 389 607 992 389 599 994 388 595 995 387 608 993 388 608 993 388 595 995 387 609 996 387 595 995 387 594 997 386 609 996 387 609 996 387 594 997 386 610 998 386 594 997 386 593 999 385 610 998 386 610 998 386 593 999 385 611 1000 385 598 1002 340 601 986 338 603 1001 340 603 1001 340 601 986 338 604 985 338 596 991 389 599 994 388 607 992 389 607 992 389 599 994 388 608 993 388 592 1003 332 602 1004 332 593 999 385 593 999 385 602 1004 332 611 1000 385 619 1005 242 624 1006 242 622 1008 244 622 1008 244 624 1006 242 623 1007 244 619 1005 242 621 1009 240 624 1006 242 624 1006 242 621 1009 240 625 1010 240 621 1009 240 618 1011 238 625 1010 240 625 1010 240 618 1011 238 626 1012 238 616 1014 230 620 1015 228 628 1013 230 628 1013 230 620 1015 228 629 1016 228 620 1015 228 615 1017 226 629 1016 228 629 1016 228 615 1017 226 630 1018 226 615 1017 226 614 1019 224 630 1018 226 630 1018 226 614 1019 224 631 1020 224 614 1019 224 613 1021 222 631 1020 224 631 1020 224 613 1021 222 632 1022 222 613 1021 222 612 1023 220 632 1022 222 632 1022 222 612 1023 220 633 1024 220 628 1013 230 627 1025 234 616 1014 230 616 1014 230 627 1025 234 617 1026 234 627 1025 234 626 1012 238 617 1026 234 617 1026 234 626 1012 238 618 1011 238 640 1027 168 644 1028 168 641 1030 170 641 1030 170 644 1028 168 643 1029 170 639 1031 166 645 1032 166 640 1027 168 640 1027 168 645 1032 166 644 1028 168 638 1033 163 646 1034 163 639 1031 166 639 1031 166 646 1034 163 645 1032 166 641 1030 170 643 1029 170 642 1036 172 642 1036 172 643 1029 170 649 1035 172 637 1037 252 647 1038 252 638 1033 163 638 1033 163 647 1038 252 646 1034 163 647 1038 252 637 1037 252 648 1040 248 648 1040 248 637 1037 252 636 1039 248 652 1041 390 200 1042 35 221 1046 53 200 1042 35 219 81 34 221 1046 53 221 1046 53 219 81 34 217 1045 51 220 80 45 195 1043 47 219 81 34 195 1043 47 218 1044 49 219 81 34 219 81 34 218 1044 49 217 1045 51 221 1046 53 216 1048 55 652 1041 390 222 91 28 201 1047 31 223 92 57 201 1047 31 652 1041 390 223 92 57 223 92 57 652 1041 390 216 1048 55 650 1049 391 652 1050 390 107 34 30 107 34 30 652 1050 390 201 35 31 106 36 32 200 39 35 650 1049 391 650 1049 391 200 39 35 652 1050 390 660 1051 27 659 1052 26 663 1054 27 663 1054 27 659 1052 26 662 1053 26 660 1051 27 663 1054 27 658 1056 30 658 1056 30 663 1054 27 664 1055 30 656 1057 36 666 1058 36 655 1060 38 655 1060 38 666 1058 36 667 1059 38 655 1060 38 667 1059 38 654 1062 40 654 1062 40 667 1059 38 668 1061 40 654 1062 40 668 1061 40 653 1064 42 653 1064 42 668 1061 40 661 1063 42 658 1056 30 664 1055 30 669 1066 391 669 1066 391 664 1055 30 670 1065 391 669 1066 391 670 1065 391 657 1068 32 657 1068 32 670 1065 391 665 1067 32 657 1068 32 665 1067 32 656 1057 36 656 1057 36 665 1067 32 666 1058 36 791 1069 0 884 1070 3 790 1072 1 790 1072 1 884 1070 3 883 1071 2 883 1071 2 882 1073 5 790 1072 1 790 1072 1 882 1073 5 789 1074 4 882 1073 5 881 1075 7 789 1074 4 789 1074 4 881 1075 7 788 1076 6 881 1075 7 880 1077 9 788 1076 6 788 1076 6 880 1077 9 787 1078 8 880 1077 9 879 1079 11 787 1078 8 787 1078 8 879 1079 11 786 1080 10 786 1081 10 879 1082 11 851 1084 12 851 1084 12 879 1082 11 897 1083 13 897 1083 13 878 1085 15 851 1084 12 851 1084 12 878 1085 15 785 1086 14 785 1087 14 878 1088 15 784 1090 16 784 1090 16 878 1088 15 877 1089 17 784 1090 16 877 1089 17 783 1092 18 783 1092 18 877 1089 17 876 1091 19 876 1091 19 875 1093 21 783 1092 18 783 1092 18 875 1093 21 782 1094 20 875 1093 21 896 1095 23 782 1094 20 782 1094 20 896 1095 23 850 1096 22 896 1095 23 874 1097 25 850 1096 22 850 1096 22 874 1097 25 781 1098 24 779 1099 26 873 1100 29 846 1102 27 846 1102 27 873 1100 29 893 1101 28 893 1101 28 872 1103 31 846 1102 27 846 1102 27 872 1103 31 778 1104 30 777 1105 32 871 1106 35 843 1108 33 843 1108 33 871 1106 35 890 1107 34 890 1107 34 870 1109 37 843 1108 33 843 1108 33 870 1109 37 776 1110 36 776 1110 36 870 1109 37 775 1112 38 775 1112 38 870 1109 37 869 1111 39 775 1112 38 869 1111 39 774 1114 40 774 1114 40 869 1111 39 868 1113 41 868 1113 41 867 1115 43 774 1114 40 774 1114 40 867 1115 43 773 1116 42 773 1117 42 867 1118 43 844 1120 44 844 1120 44 867 1118 43 891 1119 45 891 1119 45 866 1121 47 844 1120 44 844 1120 44 866 1121 47 772 1122 46 772 1123 46 866 1124 47 796 1126 48 796 1126 48 866 1124 47 889 1125 49 796 1126 48 889 1125 49 795 1128 50 795 1128 50 889 1125 49 888 1127 51 795 1128 50 888 1127 51 845 1130 52 845 1130 52 888 1127 51 892 1129 53 845 1130 52 892 1129 53 794 1132 54 794 1132 54 892 1129 53 887 1131 55 887 1131 55 894 1133 57 794 1132 54 794 1132 54 894 1133 57 847 1134 56 847 1134 56 894 1133 57 793 1136 58 793 1136 58 894 1133 57 886 1135 59 793 1136 58 886 1135 59 792 1138 60 792 1138 60 886 1135 59 885 1137 61 885 1140 61 895 1141 63 792 1139 60 792 1139 60 895 1141 63 849 1142 62 849 1142 62 895 1141 63 791 1069 0 791 1069 0 895 1141 63 884 1070 3 896 1144 23 875 1145 21 897 1143 13 875 1145 21 876 1146 19 897 1143 13 876 1146 19 877 1147 17 897 1143 13 897 1143 13 877 1147 17 878 1148 15 890 1154 34 891 1149 45 870 1153 37 870 1153 37 891 1149 45 869 1152 39 867 1150 43 868 1151 41 891 1149 45 891 1149 45 868 1151 41 869 1152 39 781 1098 24 874 1097 25 848 1156 64 848 1156 64 874 1097 25 898 1155 65 848 1156 64 898 1155 65 780 1157 66 780 1158 66 898 1159 65 779 1099 26 779 1099 26 898 1159 65 873 1100 29 895 1163 63 885 1164 61 898 1162 65 894 1166 57 893 1160 28 886 1165 59 898 1162 65 885 1164 61 873 1161 29 886 1165 59 893 1160 28 885 1164 61 893 1160 28 873 1161 29 885 1164 61 898 1162 65 874 1167 25 895 1163 63 874 1167 25 896 1144 23 895 1163 63 895 1163 63 896 1144 23 884 1173 3 897 1143 13 879 1168 11 896 1144 23 879 1168 11 880 1169 9 896 1144 23 880 1169 9 881 1170 7 896 1144 23 881 1170 7 882 1171 5 896 1144 23 882 1171 5 883 1172 2 896 1144 23 896 1144 23 883 1172 2 884 1173 3 748 1174 67 909 1175 70 853 1177 68 853 1177 68 909 1175 70 934 1176 69 934 1176 69 908 1178 72 853 1177 68 853 1177 68 908 1178 72 747 1179 71 747 1179 71 908 1178 72 857 1181 73 857 1181 73 908 1178 72 938 1180 74 857 1181 73 938 1180 74 858 1183 75 858 1183 75 938 1180 74 939 1182 76 939 1182 76 907 1184 78 858 1183 75 858 1183 75 907 1184 78 746 1185 77 746 1186 77 907 1187 78 862 1189 79 862 1189 79 907 1187 78 943 1188 80 862 1189 79 943 1188 80 745 1191 81 745 1191 81 943 1188 80 906 1190 82 745 1191 81 906 1190 82 864 1193 83 864 1193 83 906 1190 82 945 1192 84 945 1192 84 905 1194 86 864 1193 83 864 1193 83 905 1194 86 744 1195 85 744 1195 85 905 1194 86 743 1197 87 743 1197 87 905 1194 86 904 1196 88 743 1197 87 904 1196 88 742 1199 89 742 1199 89 904 1196 88 903 1198 90 903 1198 90 902 1200 92 742 1199 89 742 1199 89 902 1200 92 741 1201 91 902 1200 92 899 1202 94 741 1201 91 741 1201 91 899 1202 94 672 1203 93 672 1204 93 899 1205 94 865 1207 95 865 1207 95 899 1205 94 946 1206 96 946 1206 96 901 1208 98 865 1207 95 865 1207 95 901 1208 98 675 1209 97 675 1210 97 901 1211 98 771 1213 99 771 1213 99 901 1211 98 932 1212 100 771 1213 99 932 1212 100 770 1215 101 770 1215 101 932 1212 100 931 1214 102 931 1214 102 930 1216 104 770 1215 101 770 1215 101 930 1216 104 769 1217 103 769 1217 103 930 1216 104 768 1219 105 768 1219 105 930 1216 104 929 1218 106 768 1219 105 929 1218 106 767 1221 107 767 1221 107 929 1218 106 928 1220 108 928 1220 108 927 1222 110 767 1221 107 767 1221 107 927 1222 110 766 1223 109 927 1222 110 944 1224 112 766 1223 109 766 1223 109 944 1224 112 863 1225 111 863 1225 111 944 1224 112 765 1227 113 765 1227 113 944 1224 112 926 1226 114 765 1227 113 926 1226 114 764 1229 115 764 1229 115 926 1226 114 925 1228 116 925 1231 116 924 1232 118 764 1230 115 764 1230 115 924 1232 118 763 1233 117 924 1232 118 940 1234 120 763 1233 117 763 1233 117 940 1234 120 859 1235 119 859 1235 119 940 1234 120 854 1237 121 854 1237 121 940 1234 120 935 1236 122 854 1237 121 935 1236 122 762 1239 123 762 1239 123 935 1236 122 923 1238 124 923 1241 124 936 1242 126 762 1240 123 762 1240 123 936 1242 126 855 1243 125 855 1243 125 936 1242 126 761 1245 127 761 1245 127 936 1242 126 922 1244 128 922 1244 128 921 1246 130 761 1245 127 761 1245 127 921 1246 130 760 1247 129 760 1247 129 921 1246 130 860 1249 131 860 1249 131 921 1246 130 941 1248 132 941 1248 132 920 1250 134 860 1249 131 860 1249 131 920 1250 134 759 1251 133 920 1250 134 919 1252 136 759 1251 133 759 1251 133 919 1252 136 758 1253 135 919 1252 136 918 1254 138 758 1253 135 758 1253 135 918 1254 138 757 1255 137 918 1254 138 917 1256 140 757 1255 137 757 1255 137 917 1256 140 756 1257 139 917 1256 140 916 1258 142 756 1257 139 756 1257 139 916 1258 142 755 1259 141 755 1260 141 916 1261 142 861 1263 143 861 1263 143 916 1261 142 942 1262 144 861 1263 143 942 1262 144 856 1265 145 856 1265 145 942 1262 144 937 1264 146 856 1265 145 937 1264 146 852 1267 147 852 1267 147 937 1264 146 933 1266 148 933 1266 148 900 1268 149 852 1267 147 852 1267 147 900 1268 149 674 1269 46 674 1270 46 900 1271 149 754 1273 150 754 1273 150 900 1271 149 915 1272 151 915 1272 151 914 1274 153 754 1273 150 754 1273 150 914 1274 153 753 1275 152 914 1274 153 913 1276 155 753 1275 152 753 1275 152 913 1276 155 752 1277 154 913 1276 155 912 1278 157 752 1277 154 752 1277 154 912 1278 157 751 1279 156 751 1279 156 912 1278 157 750 1281 158 750 1281 158 912 1278 157 911 1280 159 750 1281 158 911 1280 159 749 1283 160 749 1283 160 911 1280 159 910 1282 161 749 1283 160 910 1282 161 748 1174 67 748 1174 67 910 1282 161 909 1175 70 938 1289 74 908 1290 72 935 1288 122 908 1290 72 934 1291 69 935 1288 122 933 1284 148 937 1285 146 934 1291 69 935 1288 122 934 1291 69 923 1287 124 934 1291 69 937 1285 146 923 1287 124 937 1285 146 936 1286 126 923 1287 124 934 1291 69 909 1292 70 933 1284 148 909 1292 70 910 1293 161 933 1284 148 910 1293 161 911 1294 159 933 1284 148 911 1294 159 912 1295 157 933 1284 148 912 1295 157 913 1296 155 933 1284 148 913 1296 155 914 1297 153 933 1284 148 914 1297 153 915 1298 151 933 1284 148 933 1284 148 915 1298 151 900 1299 149 936 1286 126 937 1285 146 922 1303 128 922 1303 128 937 1285 146 921 1302 130 921 1302 130 937 1285 146 941 1301 132 937 1285 146 942 1300 144 941 1301 132 944 1311 112 943 1304 80 926 1310 114 940 1307 120 924 1308 118 939 1306 76 926 1310 114 943 1304 80 925 1309 116 924 1308 118 925 1309 116 939 1306 76 943 1304 80 907 1305 78 925 1309 116 907 1305 78 939 1306 76 925 1309 116 945 1318 84 946 1312 96 905 1317 86 905 1317 86 946 1312 96 904 1316 88 904 1316 88 946 1312 96 903 1315 90 903 1315 90 946 1312 96 902 1314 92 946 1312 96 899 1313 94 902 1314 92 935 1288 122 940 1307 120 938 1289 74 938 1289 74 940 1307 120 939 1306 76 943 1304 80 944 1311 112 906 1319 82 906 1319 82 944 1311 112 945 1318 84 944 1311 112 927 1320 110 945 1318 84 901 1326 98 946 1312 96 932 1325 100 946 1312 96 945 1318 84 932 1325 100 932 1325 100 945 1318 84 931 1324 102 931 1324 102 945 1318 84 930 1323 104 930 1323 104 945 1318 84 929 1322 106 929 1322 106 945 1318 84 928 1321 108 945 1318 84 927 1320 110 928 1321 108 941 1301 132 942 1300 144 920 1331 134 920 1331 134 942 1300 144 919 1330 136 919 1330 136 942 1300 144 918 1329 138 918 1329 138 942 1300 144 917 1328 140 942 1300 144 916 1327 142 917 1328 140 840 1332 162 990 1333 165 679 1335 163 679 1335 163 990 1333 165 951 1334 164 951 1334 164 952 1336 167 679 1335 163 679 1335 163 952 1336 167 680 1337 166 952 1336 167 953 1338 169 680 1337 166 680 1337 166 953 1338 169 681 1339 168 953 1338 169 954 1340 171 681 1339 168 681 1339 168 954 1340 171 682 1341 170 954 1340 171 993 1342 173 682 1341 170 682 1341 170 993 1342 173 947 1343 172 993 1345 173 955 1346 175 947 1344 172 947 1344 172 955 1346 175 683 1347 174 683 1348 174 955 1349 175 684 1351 176 684 1351 176 955 1349 175 956 1350 177 684 1351 176 956 1350 177 685 1353 178 685 1353 178 956 1350 177 957 1352 179 685 1353 178 957 1352 179 686 1355 180 686 1355 180 957 1352 179 958 1354 181 686 1355 180 958 1354 181 842 1357 182 842 1357 182 958 1354 181 992 1356 183 992 1356 183 959 1358 185 842 1357 182 842 1357 182 959 1358 185 687 1359 184 687 1359 184 959 1358 185 841 1361 186 841 1361 186 959 1358 185 991 1360 187 991 1360 187 960 1362 189 841 1361 186 841 1361 186 960 1362 189 688 1363 188 688 1363 188 960 1362 189 838 1365 190 838 1365 190 960 1362 189 988 1364 191 988 1364 191 961 1366 193 838 1365 190 838 1365 190 961 1366 193 689 1367 192 689 1368 192 961 1369 193 836 1371 194 836 1371 194 961 1369 193 986 1370 195 986 1370 195 962 1372 197 836 1371 194 836 1371 194 962 1372 197 690 1373 196 690 1373 196 962 1372 197 834 1375 198 834 1375 198 962 1372 197 984 1374 199 984 1374 199 982 1376 201 834 1375 198 834 1375 198 982 1376 201 832 1377 200 832 1377 200 982 1376 201 830 1379 202 830 1379 202 982 1376 201 980 1378 203 980 1378 203 963 1380 205 830 1379 202 830 1379 202 963 1380 205 691 1381 204 691 1381 204 963 1380 205 828 1383 206 828 1383 206 963 1380 205 978 1382 207 978 1382 207 964 1384 209 828 1383 206 828 1383 206 964 1384 209 692 1385 208 976 1387 213 965 1388 212 826 1386 210 826 1386 210 965 1388 212 693 1389 211 693 1389 211 965 1388 212 694 1391 214 694 1391 214 965 1388 212 966 1390 215 966 1390 215 967 1392 217 694 1391 214 694 1391 214 967 1392 217 695 1393 216 695 1394 216 967 1395 217 827 1397 218 827 1397 218 967 1395 217 977 1396 219 977 1396 219 968 1398 221 827 1397 218 827 1397 218 968 1398 221 696 1399 220 696 1400 220 968 1401 221 697 1403 222 697 1403 222 968 1401 221 969 1402 223 697 1403 222 969 1402 223 698 1405 224 698 1405 224 969 1402 223 970 1404 225 698 1405 224 970 1404 225 699 1407 226 699 1407 226 970 1404 225 971 1406 227 971 1406 227 979 1408 229 699 1407 226 699 1407 226 979 1408 229 829 1409 228 829 1409 228 979 1408 229 700 1411 230 700 1411 230 979 1408 229 972 1410 231 972 1410 231 981 1412 233 700 1411 230 700 1411 230 981 1412 233 831 1413 232 831 1413 232 981 1412 233 701 1415 234 701 1415 234 981 1412 233 973 1414 235 973 1414 235 983 1416 237 701 1415 234 701 1415 234 983 1416 237 833 1417 236 833 1417 236 983 1416 237 702 1419 238 702 1419 238 983 1416 237 974 1418 239 974 1418 239 985 1420 241 702 1419 238 702 1419 238 985 1420 241 835 1421 240 835 1421 240 985 1420 241 703 1423 242 703 1423 242 985 1420 241 975 1422 243 975 1422 243 987 1424 245 703 1423 242 703 1423 242 987 1424 245 837 1425 244 837 1425 244 987 1424 245 671 1427 246 671 1427 246 987 1424 245 948 1426 247 948 1429 247 949 1430 249 671 1428 246 671 1428 246 949 1430 249 677 1431 248 949 1430 249 989 1432 251 677 1431 248 677 1431 248 989 1432 251 839 1433 250 839 1433 250 989 1432 251 678 1435 252 678 1435 252 989 1432 251 950 1434 253 950 1434 253 990 1333 165 678 1435 252 678 1435 252 990 1333 165 840 1332 162 990 1437 165 950 1438 253 991 1436 187 988 1440 191 960 1441 189 989 1439 251 960 1441 189 991 1436 187 989 1439 251 991 1436 187 950 1438 253 989 1439 251 989 1439 251 949 1442 249 988 1440 191 949 1442 249 948 1443 247 988 1440 191 987 1444 245 986 1445 195 948 1443 247 988 1440 191 948 1443 247 961 1446 193 948 1443 247 986 1445 195 961 1446 193 985 1448 241 984 1449 199 975 1447 243 986 1445 195 987 1444 245 962 1450 197 975 1447 243 984 1449 199 987 1444 245 987 1444 245 984 1449 199 962 1450 197 983 1453 237 982 1451 201 974 1452 239 984 1449 199 985 1448 241 982 1451 201 982 1451 201 985 1448 241 974 1452 239 979 1459 229 978 1454 207 972 1458 231 980 1456 203 981 1457 233 963 1455 205 963 1455 205 981 1457 233 978 1454 207 978 1454 207 981 1457 233 972 1458 231 976 1464 213 977 1460 219 965 1463 212 965 1463 212 977 1460 219 966 1462 215 977 1460 219 967 1461 217 966 1462 215 992 1466 183 958 1467 181 993 1465 173 958 1467 181 957 1468 179 993 1465 173 957 1468 179 956 1469 177 993 1465 173 993 1465 173 956 1469 177 955 1470 175 993 1465 173 954 1472 171 992 1466 183 954 1472 171 953 1473 169 992 1466 183 953 1473 169 952 1474 167 992 1466 183 991 1436 187 959 1471 185 990 1437 165 959 1471 185 992 1466 183 990 1437 165 952 1474 167 951 1475 164 992 1466 183 992 1466 183 951 1475 164 990 1437 165 981 1457 233 980 1456 203 973 1476 235 982 1451 201 983 1453 237 980 1456 203 980 1456 203 983 1453 237 973 1476 235 799 1477 254 1035 1478 257 801 1480 255 801 1480 255 1035 1478 257 1037 1479 256 801 1480 255 1037 1479 256 805 1482 258 805 1482 258 1037 1479 256 1041 1481 259 805 1482 258 1041 1481 259 809 1484 260 809 1484 260 1041 1481 259 1045 1483 261 809 1484 260 1045 1483 261 813 1486 262 813 1486 262 1045 1483 261 1049 1485 263 813 1486 262 1049 1485 263 815 1488 264 815 1488 264 1049 1485 263 1051 1487 265 815 1488 264 1051 1487 265 817 1490 266 817 1490 266 1051 1487 265 1053 1489 267 817 1490 266 1053 1489 267 819 1492 268 819 1492 268 1053 1489 267 1055 1491 269 819 1492 268 1055 1491 269 821 1494 270 821 1494 270 1055 1491 269 1057 1493 271 821 1494 270 1057 1493 271 823 1496 272 823 1496 272 1057 1493 271 1059 1495 273 1059 1495 273 1060 1497 275 823 1496 272 823 1496 272 1060 1497 275 824 1498 274 1060 1497 275 1032 1499 277 824 1498 274 824 1498 274 1032 1499 277 740 1500 276 740 1501 276 1032 1502 277 676 1504 278 676 1504 278 1032 1502 277 995 1503 279 676 1505 278 995 1506 279 825 1508 280 825 1508 280 995 1506 279 1061 1507 281 1061 1507 281 994 1509 283 825 1508 280 825 1508 280 994 1509 283 673 1510 282 673 1511 282 994 1512 283 704 1514 284 704 1514 284 994 1512 283 996 1513 285 996 1513 285 997 1515 287 704 1514 284 704 1514 284 997 1515 287 705 1516 286 705 1516 286 997 1515 287 706 1518 288 706 1518 288 997 1515 287 998 1517 289 706 1518 288 998 1517 289 707 1520 290 707 1520 290 998 1517 289 999 1519 291 822 1521 292 1058 1522 295 708 1524 293 708 1524 293 1058 1522 295 1000 1523 294 1000 1523 294 1056 1525 297 708 1524 293 708 1524 293 1056 1525 297 820 1526 296 820 1526 296 1056 1525 297 709 1528 298 709 1528 298 1056 1525 297 1001 1527 299 1001 1527 299 1054 1529 301 709 1528 298 709 1528 298 1054 1529 301 818 1530 300 818 1530 300 1054 1529 301 710 1532 302 710 1532 302 1054 1529 301 1002 1531 303 1002 1534 303 1052 1535 305 710 1533 302 710 1533 302 1052 1535 305 816 1536 304 816 1536 304 1052 1535 305 711 1538 306 711 1538 306 1052 1535 305 1003 1537 307 1003 1537 307 1050 1539 309 711 1538 306 711 1538 306 1050 1539 309 814 1540 308 814 1540 308 1050 1539 309 712 1542 310 712 1542 310 1050 1539 309 1004 1541 311 1004 1541 311 1046 1543 313 712 1542 310 712 1542 310 1046 1543 313 810 1544 312 810 1544 312 1046 1543 313 713 1546 314 713 1546 314 1046 1543 313 1005 1545 315 1005 1545 315 1042 1547 317 713 1546 314 713 1546 314 1042 1547 317 806 1548 316 806 1548 316 1042 1547 317 714 1550 318 714 1550 318 1042 1547 317 1006 1549 319 714 1550 318 1006 1549 319 715 1552 320 715 1552 320 1006 1549 319 1007 1551 321 1007 1551 321 1008 1553 323 715 1552 320 715 1552 320 1008 1553 323 716 1554 322 716 1554 322 1008 1553 323 717 1556 324 717 1556 324 1008 1553 323 1009 1555 325 1009 1555 325 1010 1557 327 717 1556 324 717 1556 324 1010 1557 327 718 1558 326 1010 1557 327 1011 1559 329 718 1558 326 718 1558 326 1011 1559 329 719 1560 328 719 1561 328 1011 1562 329 802 1564 330 802 1564 330 1011 1562 329 1038 1563 331 1038 1563 331 1012 1565 333 802 1564 330 802 1564 330 1012 1565 333 720 1566 332 1043 1568 337 1017 1569 336 807 1567 334 807 1567 334 1017 1569 336 725 1570 335 725 1570 335 1017 1569 336 811 1572 338 811 1572 338 1017 1569 336 1047 1571 339 811 1572 338 1047 1571 339 726 1574 340 726 1574 340 1047 1571 339 1018 1573 341 1018 1576 341 1048 1577 343 726 1575 340 726 1575 340 1048 1577 343 812 1578 342 812 1578 342 1048 1577 343 727 1580 344 727 1580 344 1048 1577 343 1019 1579 345 1019 1582 345 1020 1583 347 727 1581 344 727 1581 344 1020 1583 347 728 1584 346 1020 1583 347 1044 1585 349 728 1584 346 728 1584 346 1044 1585 349 808 1586 348 808 1586 348 1044 1585 349 729 1588 350 729 1588 350 1044 1585 349 1021 1587 351 1021 1587 351 1040 1589 353 729 1588 350 729 1588 350 1040 1589 353 804 1590 352 804 1590 352 1040 1589 353 730 1592 354 730 1592 354 1040 1589 353 1022 1591 355 730 1592 354 1022 1591 355 731 1594 356 731 1594 356 1022 1591 355 1023 1593 357 1023 1593 357 1036 1595 359 731 1594 356 731 1594 356 1036 1595 359 800 1596 358 800 1596 358 1036 1595 359 732 1598 360 732 1598 360 1036 1595 359 1024 1597 361 732 1598 360 1024 1597 361 733 1600 362 733 1600 362 1024 1597 361 1025 1599 363 733 1600 362 1025 1599 363 734 1602 364 734 1602 364 1025 1599 363 1026 1601 365 1026 1601 365 1027 1603 367 734 1602 364 734 1602 364 1027 1603 367 735 1604 366 1027 1603 367 1028 1605 369 735 1604 366 735 1604 366 1028 1605 369 736 1606 368 1028 1605 369 1029 1607 371 736 1606 368 736 1606 368 1029 1607 371 737 1608 370 737 1609 370 1029 1610 371 797 1612 372 797 1612 372 1029 1610 371 1033 1611 373 1033 1611 373 1030 1613 375 797 1612 372 797 1612 372 1030 1613 375 738 1614 374 738 1615 374 1030 1616 375 739 1618 376 739 1618 376 1030 1616 375 1031 1617 377 739 1619 376 1031 1620 377 798 1622 378 798 1622 378 1031 1620 377 1034 1621 379 798 1622 378 1034 1621 379 799 1477 254 799 1477 254 1034 1621 379 1035 1478 257 1029 1625 371 1028 1626 369 1033 1624 373 1035 1632 257 1034 1623 379 1036 1631 359 1036 1631 359 1034 1623 379 1024 1630 361 1028 1626 369 1027 1627 367 1033 1624 373 1033 1624 373 1027 1627 367 1034 1623 379 1027 1627 367 1026 1628 365 1034 1623 379 1026 1628 365 1025 1629 363 1034 1623 379 1034 1623 379 1025 1629 363 1024 1630 361 1036 1631 359 1023 1633 357 1035 1632 257 1023 1633 357 1022 1634 355 1035 1632 257 1022 1634 355 1040 1635 353 1035 1632 257 1035 1632 257 1040 1635 353 1037 1636 256 1040 1635 353 1021 1637 351 1037 1636 256 1021 1637 351 1044 1638 349 1037 1636 256 1037 1636 256 1044 1638 349 1041 1639 259 1044 1638 349 1020 1641 347 1041 1639 259 1048 1643 343 1045 1640 261 1019 1642 345 1020 1641 347 1019 1642 345 1041 1639 259 1045 1640 261 1041 1639 259 1019 1642 345 1042 1647 317 1005 1648 315 1043 1646 337 1047 1644 339 1017 1645 336 1046 1649 313 1005 1648 315 1046 1649 313 1043 1646 337 1017 1645 336 1043 1646 337 1046 1649 313 1050 1651 309 1003 1652 307 1049 1650 263 1003 1652 307 1052 1653 305 1049 1650 263 1049 1650 263 1052 1653 305 1051 1654 265 1052 1653 305 1002 1656 303 1051 1654 265 1054 1657 301 1053 1655 267 1002 1656 303 1053 1655 267 1051 1654 265 1002 1656 303 1056 1660 297 1055 1658 269 1001 1659 299 1001 1659 299 1055 1658 269 1054 1657 301 1055 1658 269 1053 1655 267 1054 1657 301 1058 1663 295 1057 1661 271 1000 1662 294 1000 1662 294 1057 1661 271 1056 1660 297 1057 1661 271 1055 1658 269 1056 1660 297 995 1665 279 1032 1666 277 1061 1664 281 1061 1664 281 1032 1666 277 1060 1667 275 1034 1623 379 1031 1668 377 1033 1624 373 1033 1624 373 1031 1668 377 1030 1669 375 994 1672 283 1061 1664 281 996 1671 285 1061 1664 281 1060 1667 275 996 1671 285 1060 1667 275 1059 1670 273 996 1671 285 1046 1649 313 1004 1674 311 1047 1644 339 1004 1674 311 1050 1651 309 1047 1644 339 1045 1640 261 1048 1643 343 1049 1650 263 1047 1644 339 1050 1651 309 1018 1673 341 1050 1651 309 1049 1650 263 1018 1673 341 1049 1650 263 1048 1643 343 1018 1673 341 964 1384 209 976 1387 213 692 1385 208 692 1385 208 976 1387 213 826 1386 210 978 1454 207 979 1459 229 964 1675 209 964 1675 209 979 1459 229 976 1464 213 977 1460 219 976 1464 213 968 1679 221 968 1679 221 976 1464 213 969 1678 223 969 1678 223 976 1464 213 970 1677 225 970 1677 225 976 1464 213 971 1676 227 976 1464 213 979 1459 229 971 1676 227 740 1501 276 676 1504 278 392 611 276 392 611 276 676 1504 278 391 612 278 393 616 376 739 1680 376 394 613 378 394 613 378 739 1680 376 798 1681 378 394 613 378 798 1681 378 395 617 254 395 617 254 798 1681 378 799 1682 254 395 617 254 799 1682 254 396 619 255 396 619 255 799 1682 254 801 1683 255 396 619 255 801 1683 255 397 621 258 397 621 258 801 1683 255 805 1684 258 397 621 258 805 1684 258 398 623 260 398 623 260 805 1684 258 809 1685 260 398 623 260 809 1685 260 399 625 262 399 625 262 809 1685 260 813 1686 262 813 1686 262 815 1687 264 399 625 262 399 625 262 815 1687 264 400 627 264 815 1687 264 817 1688 266 400 627 264 400 627 264 817 1688 266 401 629 266 817 1688 266 819 1689 268 401 629 266 401 629 266 819 1689 268 402 631 268 819 1689 268 821 1690 270 402 631 268 402 631 268 821 1690 270 403 633 270 821 1690 270 823 1691 272 403 633 270 403 633 270 823 1691 272 404 635 272 823 1691 272 824 1692 274 404 635 272 404 635 272 824 1692 274 405 637 274 824 1692 274 740 1693 276 405 637 274 405 637 274 740 1693 276 392 639 276 391 644 278 676 1694 278 406 641 280 406 641 280 676 1694 278 825 1695 280 408 648 326 718 1696 326 407 645 328 407 645 328 718 1696 326 719 1697 328 409 650 324 717 1698 324 408 648 326 408 648 326 717 1698 324 718 1696 326 716 1699 322 717 1698 324 410 652 322 410 652 322 717 1698 324 409 650 324 715 1700 320 716 1699 322 411 654 320 411 654 320 716 1699 322 410 652 322 714 1701 318 715 1700 320 412 656 318 412 656 318 715 1700 320 411 654 320 806 1702 316 714 1701 318 413 658 316 413 658 316 714 1701 318 412 656 318 713 1703 314 806 1702 316 414 660 314 414 660 314 806 1702 316 413 658 316 810 1704 312 713 1703 314 415 662 312 415 662 312 713 1703 314 414 660 314 712 1705 310 810 1704 312 416 664 310 416 664 310 810 1704 312 415 662 312 814 1706 308 712 1705 310 417 666 308 417 666 308 712 1705 310 416 664 310 418 668 306 711 1707 306 417 666 308 417 666 308 711 1707 306 814 1706 308 419 670 304 816 1708 304 418 668 306 418 668 306 816 1708 304 711 1707 306 420 672 302 710 1709 302 419 670 304 419 670 304 710 1709 302 816 1708 304 421 676 300 818 1710 300 420 673 302 420 673 302 818 1710 300 710 1711 302 422 678 298 709 1712 298 421 676 300 421 676 300 709 1712 298 818 1710 300 423 680 296 820 1713 296 422 678 298 422 678 298 820 1713 296 709 1712 298 424 682 293 708 1714 293 423 680 296 423 680 296 708 1714 293 820 1713 296 425 684 292 822 1715 292 424 682 293 424 682 293 822 1715 292 708 1714 293 427 688 288 706 1716 288 426 685 290 426 685 290 706 1716 288 707 1717 290 428 690 286 705 1718 286 427 688 288 427 688 288 705 1718 286 706 1716 288 429 692 284 704 1719 284 428 690 286 428 690 286 704 1719 284 705 1718 286 673 1720 282 704 1719 284 430 694 282 430 694 282 704 1719 284 429 692 284 802 1721 330 720 1722 332 432 696 330 432 696 330 720 1722 332 431 697 332 719 1723 328 802 1721 330 407 700 328 407 700 328 802 1721 330 432 696 330 434 704 368 736 1724 368 433 701 370 433 701 370 736 1724 368 737 1725 370 435 706 366 735 1726 366 434 704 368 434 704 368 735 1726 366 736 1724 368 734 1727 364 735 1726 366 436 708 364 436 708 364 735 1726 366 435 706 366 733 1728 362 734 1727 364 437 710 362 437 710 362 734 1727 364 436 708 364 732 1729 360 733 1728 362 438 712 360 438 712 360 733 1728 362 437 710 362 800 1730 358 732 1729 360 439 714 358 439 714 358 732 1729 360 438 712 360 731 1731 356 800 1730 358 440 716 356 440 716 356 800 1730 358 439 714 358 730 1732 354 731 1731 356 441 718 354 441 718 354 731 1731 356 440 716 356 804 1733 352 730 1732 354 442 720 352 442 720 352 730 1732 354 441 718 354 729 1734 350 804 1733 352 443 722 350 443 722 350 804 1733 352 442 720 352 808 1735 348 729 1734 350 444 724 348 444 724 348 729 1734 350 443 722 350 728 1736 346 808 1735 348 445 726 346 445 726 346 808 1735 348 444 724 348 727 1737 344 728 1736 346 446 728 344 446 728 344 728 1736 346 445 726 346 812 1738 342 727 1739 344 447 730 342 447 730 342 727 1739 344 446 731 344 726 1740 340 812 1738 342 448 734 340 448 734 340 812 1738 342 447 730 342 797 1741 372 738 1742 374 450 736 372 450 736 372 738 1742 374 449 737 374 737 1743 370 797 1741 372 433 740 370 433 740 370 797 1741 372 450 736 372 865 1744 95 452 744 95 672 1745 93 672 1745 93 452 744 95 451 743 93 675 1746 97 453 746 97 865 1744 95 865 1744 95 453 746 97 452 744 95 675 1747 97 771 1748 99 453 748 97 453 748 97 771 1748 99 454 749 99 770 1749 101 455 752 101 771 1748 99 771 1748 99 455 752 101 454 749 99 769 1750 103 456 754 103 770 1749 101 770 1749 101 456 754 103 455 752 101 768 1751 105 457 756 105 769 1750 103 769 1750 103 457 756 105 456 754 103 767 1752 107 458 758 107 768 1751 105 768 1751 105 458 758 107 457 756 105 766 1753 109 459 760 109 767 1752 107 767 1752 107 459 760 109 458 758 107 863 1754 111 460 762 111 766 1753 109 766 1753 109 460 762 111 459 760 109 765 1755 113 461 764 113 863 1754 111 863 1754 111 461 764 113 460 762 111 764 1756 115 462 766 115 765 1755 113 765 1755 113 462 766 115 461 764 113 763 1757 117 463 770 117 764 1758 115 764 1758 115 463 770 117 462 769 115 859 1759 119 464 772 119 763 1757 117 763 1757 117 464 772 119 463 770 117 854 1760 121 465 774 121 859 1759 119 859 1759 119 465 774 121 464 772 119 854 1760 121 762 1761 123 465 774 121 465 774 121 762 1761 123 466 775 123 466 780 123 762 1762 123 467 777 125 467 777 125 762 1762 123 855 1763 125 855 1763 125 761 1764 127 467 777 125 467 777 125 761 1764 127 468 781 127 761 1764 127 760 1765 129 468 781 127 468 781 127 760 1765 129 469 783 129 760 1765 129 860 1766 131 469 783 129 469 783 129 860 1766 131 470 785 131 860 1766 131 759 1767 133 470 785 131 470 785 131 759 1767 133 471 787 133 759 1767 133 758 1768 135 471 787 133 471 787 133 758 1768 135 472 789 135 758 1768 135 757 1769 137 472 789 135 472 789 135 757 1769 137 473 791 137 757 1769 137 756 1770 139 473 791 137 473 791 137 756 1770 139 474 793 139 861 1771 143 476 798 143 755 1772 141 755 1772 141 476 798 143 475 797 141 856 1773 145 477 800 145 861 1771 143 861 1771 143 477 800 145 476 798 143 856 1773 145 852 1774 147 477 800 145 477 800 145 852 1774 147 478 801 147 852 1774 147 674 1775 46 478 801 147 478 801 147 674 1775 46 479 803 46 674 1776 46 754 1777 150 479 806 46 479 806 46 754 1777 150 480 807 150 754 1777 150 753 1778 152 480 807 150 480 807 150 753 1778 152 481 809 152 753 1778 152 752 1779 154 481 809 152 481 809 152 752 1779 154 482 811 154 751 1780 156 483 814 156 752 1779 154 752 1779 154 483 814 156 482 811 154 750 1781 158 484 816 158 751 1780 156 751 1780 156 484 816 158 483 814 156 749 1782 160 485 818 160 750 1781 158 750 1781 158 485 818 160 484 816 158 748 1783 67 486 820 67 749 1782 160 749 1782 160 486 820 67 485 818 160 853 1784 68 487 822 68 748 1783 67 748 1783 67 487 822 68 486 820 67 747 1785 71 488 824 71 853 1784 68 853 1784 68 488 824 71 487 822 68 857 1786 73 489 826 73 747 1785 71 747 1785 71 489 826 73 488 824 71 858 1787 75 746 1788 77 490 828 75 490 828 75 746 1788 77 491 829 77 844 1789 44 493 834 44 773 1790 42 773 1790 42 493 834 44 492 833 42 772 1791 46 494 836 46 844 1789 44 844 1789 44 494 836 46 493 834 44 796 1792 48 495 840 48 772 1793 46 772 1793 46 495 840 48 494 839 46 795 1794 50 496 842 50 796 1792 48 796 1792 48 496 842 50 495 840 48 845 1795 52 497 844 52 795 1794 50 795 1794 50 497 844 52 496 842 50 847 1796 56 499 848 56 794 1797 54 794 1797 54 499 848 56 498 847 54 793 1798 58 500 850 58 847 1796 56 847 1796 56 500 850 58 499 848 56 793 1798 58 792 1799 60 500 850 58 500 850 58 792 1799 60 501 851 60 792 1800 60 849 1801 62 501 854 60 501 854 60 849 1801 62 502 855 62 849 1801 62 791 1802 0 502 855 62 502 855 62 791 1802 0 503 857 0 791 1802 0 790 1803 1 503 857 0 503 857 0 790 1803 1 504 859 1 790 1803 1 789 1804 4 504 859 1 504 859 1 789 1804 4 505 861 4 789 1804 4 788 1805 6 505 861 4 505 861 4 788 1805 6 506 863 6 788 1805 6 787 1806 8 506 863 6 506 863 6 787 1806 8 507 865 8 787 1806 8 786 1807 10 507 865 8 507 865 8 786 1807 10 508 867 10 786 1808 10 851 1809 12 508 870 10 508 870 10 851 1809 12 509 871 12 851 1809 12 785 1810 14 509 871 12 509 871 12 785 1810 14 510 873 14 514 878 218 827 1811 218 513 875 220 513 875 220 827 1811 218 696 1812 220 511 880 216 695 1813 216 514 878 218 514 878 218 695 1813 216 827 1811 218 497 844 52 845 1795 52 498 847 54 498 847 54 845 1795 52 794 1797 54 857 1786 73 858 1787 75 489 826 73 489 826 73 858 1787 75 490 828 75 756 1770 139 755 1814 141 474 793 139 474 793 139 755 1814 141 475 881 141 947 1815 172 683 1816 174 515 884 172 515 884 172 683 1816 174 512 885 174 738 1615 374 739 1618 376 449 887 374 449 887 374 739 1618 376 393 888 376 406 641 280 825 1695 280 430 889 282 430 889 282 825 1695 280 673 1817 282 1043 1646 337 1016 1825 381 1042 1647 317 1016 1825 381 1039 1826 380 1042 1647 317 1011 1819 329 1010 1820 327 1038 1818 331 1042 1647 317 1039 1826 380 1006 1824 319 1006 1824 319 1039 1826 380 1007 1823 321 1010 1820 327 1009 1821 325 1038 1818 331 1038 1818 331 1009 1821 325 1039 1826 380 1009 1821 325 1008 1822 323 1039 1826 380 1008 1822 323 1007 1823 321 1039 1826 380 1039 1826 380 1015 1827 384 1038 1818 331 1015 1827 384 1014 1828 383 1038 1818 331 1014 1828 383 1013 1829 382 1038 1818 331 1038 1818 331 1013 1829 382 1012 1830 333 1013 1831 382 721 1832 385 1012 1834 333 1012 1834 333 721 1832 385 720 1833 332 722 1836 386 721 1832 385 1014 1835 383 1014 1835 383 721 1832 385 1013 1831 382 1015 1837 384 723 1838 387 1014 1835 383 1014 1835 383 723 1838 387 722 1836 386 1039 1839 380 803 1840 388 1015 1837 384 1015 1837 384 803 1840 388 723 1838 387 1043 1568 337 807 1567 334 1016 1842 381 1016 1842 381 807 1567 334 724 1841 389 1016 1842 381 724 1841 389 1039 1839 380 1039 1839 380 724 1841 389 803 1840 388 1058 1522 295 822 1521 292 999 1519 291 999 1519 291 822 1521 292 707 1520 290 822 1715 292 425 684 292 707 1717 290 707 1717 290 425 684 292 426 685 290 996 1671 285 1059 1670 273 997 1845 287 997 1845 287 1059 1670 273 998 1844 289 998 1844 289 1059 1670 273 999 1843 291 999 1843 291 1059 1670 273 1058 1663 295 1059 1670 273 1057 1661 271 1058 1663 295 1066 1846 214 1067 1847 216 535 920 214 535 920 214 1067 1847 216 534 921 216 1065 1848 211 1066 1846 214 536 924 211 536 924 211 1066 1846 214 535 920 214 1068 1849 210 1065 1848 211 537 926 210 537 926 210 1065 1848 211 536 924 211 1070 1850 198 1069 1851 200 541 928 198 541 928 198 1069 1851 200 540 929 200 541 928 198 542 932 196 1070 1850 198 1070 1850 198 542 932 196 1062 1852 196 543 934 194 1071 1853 194 542 932 196 542 932 196 1071 1853 194 1062 1852 196 1064 1854 208 1068 1849 210 538 936 208 538 936 208 1068 1849 210 537 926 210 1069 1851 200 1063 1855 204 540 929 200 540 929 200 1063 1855 204 539 937 204 1063 1855 204 1064 1854 208 539 937 204 539 937 204 1064 1854 208 538 936 208 555 942 186 1079 1856 186 554 939 188 554 939 188 1079 1856 186 1077 1857 188 556 944 184 1076 1858 184 555 942 186 555 942 186 1076 1858 184 1079 1856 186 558 948 180 1075 1859 180 557 945 182 557 945 182 1075 1859 180 1080 1860 182 559 950 178 1074 1861 178 558 948 180 558 948 180 1074 1861 178 1075 1859 180 560 952 176 1073 1862 176 559 950 178 559 950 178 1073 1862 176 1074 1861 178 561 954 174 1072 1863 174 560 952 176 560 952 176 1072 1863 174 1073 1862 176 557 945 182 1080 1860 182 556 944 184 556 944 184 1080 1860 182 1076 1858 184 1084 1864 16 569 958 16 1085 1865 14 1085 1865 14 569 958 16 568 957 14 1083 1866 18 570 960 18 1084 1864 16 1084 1864 16 570 960 18 569 958 16 1082 1867 20 571 962 20 1083 1866 18 1083 1866 18 571 962 20 570 960 18 1086 1868 22 572 964 22 1082 1867 20 1082 1867 20 572 964 22 571 962 20 572 964 22 1086 1868 22 573 965 24 573 965 24 1086 1868 22 1081 1869 24 1087 1870 93 584 970 93 1088 1871 91 1088 1871 91 584 970 93 583 969 91 1093 1872 77 1094 1873 79 585 972 77 585 972 77 1094 1873 79 586 973 79 1092 1874 81 1095 1875 83 587 976 81 587 976 81 1095 1875 83 588 977 83 1095 1875 83 1091 1876 85 588 977 83 588 977 83 1091 1876 85 589 979 85 1091 1876 85 1090 1877 87 589 979 85 589 979 85 1090 1877 87 590 981 87 1090 1877 87 1089 1878 89 590 981 87 590 981 87 1089 1878 89 591 983 89 1089 1878 89 1088 1871 91 591 983 89 591 983 89 1088 1871 91 583 969 91 1094 1873 79 1092 1874 81 586 973 79 586 973 79 1092 1874 81 587 976 81 605 988 335 1101 1879 335 604 985 338 604 985 338 1101 1879 335 1105 1880 338 606 990 334 1104 1881 334 605 988 335 605 988 335 1104 1881 334 1101 1879 335 607 992 389 1100 1882 389 606 990 334 606 990 334 1100 1882 389 1104 1881 334 609 996 387 1099 1883 387 608 993 388 608 993 388 1099 1883 387 1103 1884 388 610 998 386 1098 1885 386 609 996 387 609 996 387 1098 1885 386 1099 1883 387 611 1000 385 1097 1886 385 610 998 386 610 998 386 1097 1886 385 1098 1885 386 604 985 338 1105 1880 338 603 1001 340 603 1001 340 1105 1880 338 1102 1887 340 608 993 388 1103 1884 388 607 992 389 607 992 389 1103 1884 388 1100 1882 389 1096 1888 332 1097 1886 385 602 1004 332 602 1004 332 1097 1886 385 611 1000 385 1113 1889 242 1116 1890 244 624 1006 242 624 1006 242 1116 1890 244 623 1007 244 625 1010 240 1115 1891 240 624 1006 242 624 1006 242 1115 1891 240 1113 1889 242 1115 1891 240 625 1010 240 1112 1892 238 1112 1892 238 625 1010 240 626 1012 238 629 1016 228 1114 1893 228 628 1013 230 628 1013 230 1114 1893 228 1110 1894 230 630 1018 226 1109 1895 226 629 1016 228 629 1016 228 1109 1895 226 1114 1893 228 631 1020 224 1108 1896 224 630 1018 226 630 1018 226 1108 1896 224 1109 1895 226 632 1022 222 1107 1897 222 631 1020 224 631 1020 224 1107 1897 222 1108 1896 224 633 1024 220 1106 1898 220 632 1022 222 632 1022 222 1106 1898 220 1107 1897 222 1111 1899 234 627 1025 234 1110 1894 230 1110 1894 230 627 1025 234 628 1013 230 1112 1892 238 626 1012 238 1111 1899 234 1111 1899 234 626 1012 238 627 1025 234 1121 1900 168 1122 1901 170 644 1028 168 644 1028 168 1122 1901 170 643 1029 170 1120 1902 166 1121 1900 168 645 1032 166 645 1032 166 1121 1900 168 644 1028 168 1119 1903 163 1120 1902 166 646 1034 163 646 1034 163 1120 1902 166 645 1032 166 1122 1901 170 1123 1904 172 643 1029 170 643 1029 170 1123 1904 172 649 1035 172 1118 1905 252 1119 1903 163 647 1038 252 647 1038 252 1119 1903 163 646 1034 163 647 1038 252 648 1040 248 1118 1905 252 1118 1905 252 648 1040 248 1117 1906 248 1125 1907 390 892 1908 53 871 1912 35 871 1912 35 892 1908 53 890 1154 34 892 1908 53 888 1909 51 890 1154 34 891 1149 45 890 1154 34 866 1911 47 866 1911 47 890 1154 34 889 1910 49 888 1909 51 889 1910 49 890 1154 34 892 1908 53 1125 1907 390 887 1913 55 893 1160 28 894 1166 57 872 1914 31 872 1914 31 894 1166 57 1125 1907 390 894 1166 57 887 1913 55 1125 1907 390 872 1103 31 1125 1915 390 778 1104 30 778 1104 30 1125 1915 390 1124 1916 391 1125 1915 390 871 1106 35 1124 1916 391 1124 1916 391 871 1106 35 777 1105 32 1133 1917 27 663 1054 27 1132 1918 26 1132 1918 26 663 1054 27 662 1053 26 1133 1917 27 1131 1919 30 663 1054 27 663 1054 27 1131 1919 30 664 1055 30 1129 1920 36 1128 1921 38 666 1058 36 666 1058 36 1128 1921 38 667 1059 38 1128 1921 38 1127 1922 40 667 1059 38 667 1059 38 1127 1922 40 668 1061 40 1127 1922 40 1126 1923 42 668 1061 40 668 1061 40 1126 1923 42 661 1063 42 1131 1919 30 1134 1924 391 664 1055 30 664 1055 30 1134 1924 391 670 1065 391 1134 1924 391 1130 1925 32 670 1065 391 670 1065 391 1130 1925 32 665 1067 32 1130 1925 32 1129 1920 36 665 1067 32 665 1067 32 1129 1920 36 666 1058 36 533 933 194 1137 1926 192 543 934 194 543 934 194 1137 1926 192 1135 1927 192 1137 1929 192 551 1930 190 1135 1928 192 554 939 188 1135 1928 192 550 940 188 1135 1928 192 551 1930 190 550 940 188 1135 1927 192 1136 1931 192 543 934 194 543 934 194 1136 1931 192 1071 1853 194 1136 1933 192 1135 1928 192 1078 1932 190 554 939 188 1077 1857 188 1135 1928 192 1135 1928 192 1077 1857 188 1078 1932 190 622 1008 244 623 1007 244 1140 1935 246 1140 1935 246 623 1007 244 1138 1934 246 1140 1936 246 1138 1937 246 636 1039 248 636 1039 248 1138 1937 246 648 1040 248 1116 1890 244 1139 1938 246 623 1007 244 623 1007 244 1139 1938 246 1138 1934 246 1139 1939 246 1117 1906 248 1138 1937 246 1138 1937 246 1117 1906 248 648 1040 248 1143 1940 64 562 966 24 1141 1941 64 1141 1941 64 562 966 24 573 965 24 1142 1942 64 1141 1941 64 1081 1869 24 1081 1869 24 1141 1941 64 573 965 24 659 1052 26 1146 1943 66 662 1053 26 662 1053 26 1146 1943 66 1144 1944 66 1132 1918 26 662 1053 26 1145 1945 66 1145 1945 66 662 1053 26 1144 1944 66 1146 1946 66 1143 1940 64 1144 1947 66 1144 1947 66 1143 1940 64 1141 1941 64 1145 1948 66 1144 1947 66 1142 1942 64 1142 1942 64 1144 1947 66 1141 1941 64</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="NVIDIA_symbol">
+ <node id="_NVIDIA_symbol" name="NVIDIA_symbol" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#NVIDIA_symbol">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="NVIDIA_symbolSG" target="#NVIDIA"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Media/DVD_cover-reflection.dae b/Studio/Content/Models Library/Media/DVD_cover-reflection.dae
new file mode 100644
index 00000000..47dc36b6
--- /dev/null
+++ b/Studio/Content/Models Library/Media/DVD_cover-reflection.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/media/DVD_cover-reflection.mb</source_data>
+ </contributor>
+ <created>2008-10-01T19:20:36Z</created>
+ <modified>2008-10-01T19:20:36Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="DVD_reflection_material" name="DVD_reflection_material">
+ <instance_effect url="#DVD_reflection_material-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="DVD_reflection_material-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="DVD_cover_reflection" name="DVD_cover_reflection">
+ <mesh>
+ <source id="DVD_cover_reflection-positions" name="position">
+ <float_array id="DVD_cover_reflection-positions-array" count="456">-35 -48 -1.65 -33 -48 -3.85 -33 -50 -1.65 33 -48 -3.85 35 -48 -1.65 33 -50 -1.65 35 -48 1.65 33 -48 3.85 33 -50 1.65 -33 -50 1.65 -33 -48 3.85 -35 -48 1.65 -35 48 -1.65 -33 50 -1.65 -33 48 -3.85 33 50 -1.65 35 48 -1.65 33 48 -3.85 33 50 1.65 33 48 3.85 35 48 1.65 -33 50 1.65 -35 48 1.65 -33 48 3.85 -33 -48.7654 3.68253 33 -48.7654 3.68253 -33 -49.4142 3.20564 33 -49.4142 3.20564 -33 -49.8478 2.4919 33 -49.8478 2.4919 -34.8478 -48.7654 -1.65 -34.8478 -48.7654 1.65 -34.4142 -49.4142 -1.65 -34.4142 -49.4142 1.65 -33.7654 -49.8478 -1.65 -33.7654 -49.8478 1.65 34.8478 -48.7654 1.65 34.8478 -48.7654 -1.65 34.4142 -49.4142 1.65 34.4142 -49.4142 -1.65 33.7654 -49.8478 1.65 33.7654 -49.8478 -1.65 33 -48.7654 -3.68253 -33 -48.7654 -3.68253 33 -49.4142 -3.20564 -33 -49.4142 -3.20564 33 -49.8478 -2.4919 -33 -49.8478 -2.4919 -34.8478 -48 2.4919 -34.8478 48 2.4919 -34.4142 -48 3.20564 -34.4142 48 3.20564 -33.7654 -48 3.68253 -33.7654 48 3.68253 33.7654 -48 3.68253 33.7654 48 3.68253 34.4142 -48 3.20564 34.4142 48 3.20564 34.8478 -48 2.4919 34.8478 48 2.4919 34.8478 -48 -2.4919 34.8478 48 -2.4919 34.4142 -48 -3.20564 34.4142 48 -3.20564 33.7654 -48 -3.68253 33.7654 48 -3.68253 -34.8478 48 -2.4919 -34.8478 -48 -2.4919 -34.4142 48 -3.20564 -34.4142 -48 -3.20564 -33.7654 48 -3.68253 -33.7654 -48 -3.68253 -33 49.8478 2.4919 33 49.8478 2.4919 -33 49.4142 3.20564 33 49.4142 3.20564 -33 48.7654 3.68253 33 48.7654 3.68253 -33.7654 49.8478 -1.65 -33.7654 49.8478 1.65 -34.4142 49.4142 -1.65 -34.4142 49.4142 1.65 -34.8478 48.7654 -1.65 -34.8478 48.7654 1.65 33.7654 49.8478 1.65 33.7654 49.8478 -1.65 34.4142 49.4142 1.65 34.4142 49.4142 -1.65 34.8478 48.7654 1.65 34.8478 48.7654 -1.65 33 49.8478 -2.4919 -33 49.8478 -2.4919 33 49.4142 -3.20564 -33 49.4142 -3.20564 33 48.7654 -3.68253 -33 48.7654 -3.68253 -34.2189 -49.2189 -2.99085 -34.3654 -49.3654 -2.44085 -34.7078 -48.7803 -2.50838 -34.3654 -48.7189 -3.15194 -33.7803 -48.7803 -3.52863 -33.7189 -49.3654 -3.15194 -33.7803 -49.7078 -2.50838 34.2189 -49.2189 -2.99085 33.7189 -49.3654 -3.15194 33.7803 -48.7803 -3.52863 34.3654 -48.7189 -3.15194 34.7078 -48.7803 -2.50838 34.3654 -49.3654 -2.44085 33.7803 -49.7078 -2.50838 34.2189 -49.2189 2.99085 34.3654 -49.3654 2.44085 34.7078 -48.7803 2.50838 34.3654 -48.7189 3.15194 33.7803 -48.7803 3.52863 33.7189 -49.3654 3.15194 33.7803 -49.7078 2.50838 -34.2189 -49.2189 2.99085 -34.3654 -49.3654 2.44085 -33.7803 -49.7078 2.50838 -33.7189 -49.3654 3.15194 -33.7803 -48.7803 3.52863 -34.3654 -48.7189 3.15194 -34.7078 -48.7803 2.50838 -34.2189 49.2189 -2.99085 -34.3654 48.7189 -3.15194 -34.7078 48.7803 -2.50838 -34.3654 49.3654 -2.44085 -33.7803 49.7078 -2.50838 -33.7189 49.3654 -3.15194 -33.7803 48.7803 -3.52863 34.2189 49.2189 -2.99085 33.7189 49.3654 -3.15194 33.7803 49.7078 -2.50838 34.3654 49.3654 -2.44085 34.7078 48.7803 -2.50838 34.3654 48.7189 -3.15194 33.7803 48.7803 -3.52863 34.2189 49.2189 2.99085 34.3654 49.3654 2.44085 33.7803 49.7078 2.50838 33.7189 49.3654 3.15194 33.7803 48.7803 3.52863 34.3654 48.7189 3.15194 34.7078 48.7803 2.50838 -34.2189 49.2189 2.99085 -33.7189 49.3654 3.15194 -33.7803 49.7078 2.50838 -34.3654 49.3654 2.44085 -34.7078 48.7803 2.50838 -34.3654 48.7189 3.15194 -33.7803 48.7803 3.52863</float_array>
+ <technique_common>
+ <accessor source="#DVD_cover_reflection-positions-array" count="152" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="DVD_cover_reflection-normals" name="normal">
+ <float_array id="DVD_cover_reflection-normals-array" count="456">-0.991724 -0.094924 -0.086442 -0.103983 -0.103983 -0.989128 -0.094922 -0.991724 -0.086442 0.103983 -0.103983 -0.989128 0.991724 -0.094924 -0.086442 0.094922 -0.991724 -0.086442 0.991724 -0.094924 0.086442 0.103983 -0.103983 0.989128 0.094922 -0.991724 0.086442 -0.094922 -0.991724 0.086442 -0.103983 -0.103983 0.989128 -0.991724 -0.094924 0.086442 -0.991724 0.094924 -0.086442 -0.094922 0.991724 -0.086442 -0.103983 0.103983 -0.989128 0.094922 0.991724 -0.086442 0.991724 0.094924 -0.086442 0.103983 0.103983 -0.989128 0.094922 0.991724 0.086442 0.103983 0.103983 0.989128 0.991724 0.094924 0.086442 -0.094922 0.991724 0.086442 -0.991724 0.094924 0.086442 -0.103983 0.103983 0.989128 -0.082821 -0.403027 0.911433 0.082821 -0.403026 0.911433 -0.062938 -0.735781 0.674289 0.062938 -0.735781 0.674289 -0.076983 -0.934922 0.346401 0.076983 -0.934922 0.346401 -0.924699 -0.374309 -0.06945 -0.924699 -0.374309 0.06945 -0.706048 -0.706046 -0.054732 -0.706048 -0.706046 0.054732 -0.374309 -0.924699 -0.069452 -0.374309 -0.924699 0.069452 0.924699 -0.374309 0.06945 0.924699 -0.374309 -0.06945 0.706048 -0.706046 0.054732 0.706048 -0.706046 -0.054732 0.374309 -0.924699 0.069452 0.374309 -0.924699 -0.069452 0.082821 -0.403027 -0.911433 -0.082821 -0.403026 -0.911433 0.062938 -0.735781 -0.674289 -0.062938 -0.735781 -0.674289 0.076983 -0.934922 -0.346401 -0.076983 -0.934922 -0.346401 -0.934923 -0.076983 0.3464 -0.934923 0.076984 0.346399 -0.735783 -0.062938 0.674287 -0.735783 0.062939 0.674287 -0.403028 -0.082821 0.911432 -0.403028 0.082821 0.911432 0.403028 -0.082821 0.911432 0.403028 0.082821 0.911432 0.735783 -0.062939 0.674287 0.735783 0.062938 0.674287 0.934923 -0.076984 0.346399 0.934923 0.076983 0.3464 0.934923 -0.076983 -0.3464 0.934923 0.076984 -0.346399 0.735783 -0.062938 -0.674287 0.735783 0.062939 -0.674287 0.403028 -0.082821 -0.911432 0.403028 0.082821 -0.911432 -0.934923 0.076983 -0.3464 -0.934923 -0.076984 -0.346399 -0.735783 0.062938 -0.674287 -0.735783 -0.062939 -0.674287 -0.403028 0.082821 -0.911432 -0.403028 -0.082821 -0.911432 -0.076983 0.934922 0.346401 0.076983 0.934922 0.346401 -0.062938 0.735781 0.674289 0.062938 0.735781 0.674289 -0.082821 0.403026 0.911433 0.082821 0.403027 0.911433 -0.374309 0.924699 -0.069452 -0.374309 0.924699 0.069452 -0.706048 0.706046 -0.054732 -0.706048 0.706046 0.054732 -0.924699 0.374309 -0.06945 -0.924699 0.374309 0.06945 0.374309 0.924699 0.069452 0.374309 0.924699 -0.069452 0.706048 0.706046 0.054732 0.706048 0.706046 -0.054732 0.924699 0.374309 0.06945 0.924699 0.374309 -0.06945 0.076983 0.934922 -0.346401 -0.076983 0.934922 -0.346401 0.062938 0.735781 -0.674289 -0.062938 0.735781 -0.674289 0.082821 0.403026 -0.911433 -0.082821 0.403027 -0.911433 -0.593351 -0.593351 -0.543938 -0.681524 -0.681524 -0.266553 -0.894051 -0.330281 -0.302633 -0.702338 -0.301373 -0.6449 -0.351747 -0.351747 -0.867495 -0.301373 -0.702339 -0.644899 -0.330282 -0.894051 -0.302632 0.593352 -0.59335 -0.543939 0.301373 -0.702338 -0.644899 0.351748 -0.351747 -0.867495 0.702338 -0.301372 -0.6449 0.894051 -0.330281 -0.302634 0.681524 -0.681523 -0.266553 0.330282 -0.894051 -0.302633 0.593351 -0.593351 0.543938 0.681524 -0.681524 0.266553 0.894051 -0.330281 0.302633 0.702338 -0.301373 0.6449 0.351747 -0.351747 0.867495 0.301373 -0.702339 0.644899 0.330282 -0.894051 0.302632 -0.593352 -0.59335 0.543939 -0.681524 -0.681523 0.266553 -0.330282 -0.894051 0.302633 -0.301373 -0.702338 0.644899 -0.351748 -0.351747 0.867495 -0.702338 -0.301372 0.6449 -0.894051 -0.330281 0.302634 -0.593352 0.59335 -0.543939 -0.702338 0.301372 -0.6449 -0.894051 0.330281 -0.302634 -0.681524 0.681523 -0.266553 -0.330282 0.894051 -0.302633 -0.301373 0.702338 -0.644899 -0.351748 0.351747 -0.867495 0.593351 0.593351 -0.543938 0.301373 0.702339 -0.644899 0.330282 0.894051 -0.302632 0.681524 0.681524 -0.266553 0.894051 0.330281 -0.302633 0.702338 0.301373 -0.6449 0.351747 0.351747 -0.867495 0.593352 0.59335 0.543939 0.681524 0.681523 0.266553 0.330282 0.894051 0.302633 0.301373 0.702338 0.644899 0.351748 0.351747 0.867495 0.702338 0.301372 0.6449 0.894051 0.330281 0.302634 -0.593351 0.593351 0.543938 -0.301373 0.702339 0.644899 -0.330282 0.894051 0.302632 -0.681524 0.681524 0.266553 -0.894051 0.330281 0.302633 -0.702338 0.301373 0.6449 -0.351747 0.351747 0.867495</float_array>
+ <technique_common>
+ <accessor source="#DVD_cover_reflection-normals-array" count="152" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="DVD_cover_reflection-DVD_Box-UV" name="DVD_Box-UV">
+ <float_array id="DVD_cover_reflection-DVD_Box-UV-array" count="566">0.68017 0.973548 0.026593 0.973548 0.026593 0.981099 0.68017 0.981099 0.026593 0.9875 0.68017 0.9875 0.870362 0.825253 0.870362 0.172675 0.862028 0.172675 0.862028 0.825253 0.852197 0.172675 0.852197 0.825253 0.764669 0.973319 0.726217 0.973319 0.726217 0.980857 0.764669 0.980857 0.726217 0.987248 0.764669 0.987248 0.852197 0.158692 0.813662 0.158692 0.813662 0.165107 0.852197 0.165107 0.813662 0.172675 0.726217 0.973319 0.726217 0.980857 0.726217 0.987248 0.813662 0.839236 0.852197 0.839236 0.852197 0.83282 0.813662 0.83282 0.813662 0.825253 0.679924 0.973548 0.026346 0.973548 0.026346 0.981099 0.679924 0.981099 0.026346 0.9875 0.679924 0.9875 0.795497 0.172675 0.795497 0.825253 0.803831 0.825253 0.803831 0.172675 0.764669 0.02778 0.774479 0.973319 0.774479 0.02778 0.782795 0.973319 0.782795 0.02778 0.012588 0.026452 0.012588 0.973548 0.019013 0.973548 0.019013 0.026452 0.026593 0.026452 0.68017 0.026452 0.687749 0.973548 0.687749 0.026452 0.694175 0.973548 0.694175 0.026452 0.708091 0.02778 0.708091 0.973319 0.716407 0.973319 0.716407 0.02778 0.726217 0.02778 0.774479 0.973319 0.774479 0.02778 0.782795 0.973319 0.782795 0.02778 0.012342 0.026452 0.012342 0.973548 0.018767 0.973548 0.018767 0.026452 0.026346 0.026452 0.726217 0.02778 0.716407 0.02778 0.716407 0.973319 0.708091 0.02778 0.708091 0.973319 0.693928 0.973548 0.693928 0.026452 0.687503 0.026452 0.687503 0.973548 0.679924 0.026452 0.852197 0.172824 0.852197 0.825402 0.862028 0.825402 0.862028 0.172824 0.870362 0.825402 0.870362 0.172824 0.68017 0.0125 0.026593 0.0125 0.026593 0.018901 0.68017 0.018901 0.813662 0.825402 0.813662 0.832969 0.852197 0.832969 0.813662 0.839385 0.852197 0.839385 0.764669 0.013851 0.726217 0.013851 0.726217 0.020242 0.764669 0.020242 0.813662 0.172824 0.852197 0.165256 0.813662 0.165256 0.852197 0.158841 0.813662 0.158841 0.764669 0.013851 0.726217 0.013851 0.726217 0.020242 0.803831 0.172824 0.803831 0.825402 0.795497 0.172824 0.795497 0.825402 0.679924 0.0125 0.026346 0.0125 0.026346 0.018901 0.679924 0.018901 0.716215 0.981004 0.717002 0.986767 0.708717 0.9804 0.710594 0.985324 0.687651 0.981247 0.693445 0.980641 0.693928 0.973548 0.687043 0.987018 0.691994 0.985574 0.693445 0.980641 0.803639 0.164959 0.796124 0.165567 0.795497 0.172675 0.813662 0.158692 0.804428 0.159175 0.804428 0.159175 0.798005 0.160622 0.796124 0.165567 0.018619 0.981247 0.019227 0.987018 0.012342 0.973548 0.012825 0.980641 0.014275 0.985574 0.774671 0.981004 0.782169 0.9804 0.773884 0.986767 0.780292 0.985324 0.782169 0.9804 0.803639 0.832968 0.804428 0.838753 0.813662 0.839236 0.795497 0.825253 0.796124 0.832361 0.796124 0.832361 0.798005 0.837305 0.804428 0.838753 0.717002 0.986767 0.708091 0.973319 0.708716 0.9804 0.710594 0.985324 0.687898 0.981247 0.693691 0.980641 0.68729 0.987018 0.692241 0.985574 0.693691 0.980641 0.86222 0.832968 0.869735 0.832361 0.870362 0.825253 0.852197 0.839236 0.861431 0.838753 0.861431 0.838753 0.867854 0.837305 0.869735 0.832361 0.86222 0.164959 0.861431 0.159175 0.852197 0.158692 0.870362 0.172675 0.869735 0.165567 0.867854 0.160622 0.018865 0.981247 0.019473 0.987018 0.012588 0.973548 0.013071 0.980641 0.014522 0.985574 0.019473 0.987018 0.774671 0.981004 0.782169 0.9804 0.773884 0.986767 0.773884 0.986767 0.780292 0.985324 0.782169 0.9804 0.716215 0.020094 0.708717 0.020699 0.726217 0.013851 0.717002 0.014332 0.710594 0.015774 0.803639 0.833117 0.804428 0.838902 0.796124 0.83251 0.798005 0.837454 0.804428 0.838902 0.687651 0.018753 0.687043 0.012981 0.679924 0.0125 0.693928 0.026452 0.693445 0.019359 0.693445 0.019359 0.691994 0.014426 0.687043 0.012981 0.803639 0.165109 0.796124 0.165715 0.804428 0.159324 0.798005 0.160771 0.774671 0.020094 0.773884 0.014332 0.764669 0.013851 0.782169 0.020699 0.780292 0.015774 0.773884 0.014332 0.018619 0.018753 0.012825 0.019359 0.012342 0.026452 0.026346 0.0125 0.019227 0.012981 0.019227 0.012981 0.014275 0.014426 0.012825 0.019359 0.86222 0.165109 0.861431 0.159324 0.869735 0.165715 0.867854 0.160771 0.687898 0.018753 0.68729 0.012981 0.68017 0.0125 0.693691 0.019359 0.692241 0.014426 0.68729 0.012981 0.708716 0.020699 0.708091 0.02778 0.726217 0.013851 0.717002 0.014332 0.717002 0.014332 0.710594 0.015774 0.708716 0.020699 0.86222 0.833117 0.869735 0.83251 0.861431 0.838902 0.867854 0.837454 0.774671 0.020094 0.773884 0.014332 0.764669 0.013851 0.782169 0.020699 0.780292 0.015774 0.773884 0.014332 0.018865 0.018753 0.013071 0.019359 0.012588 0.026452 0.026593 0.0125 0.019473 0.012981 0.019473 0.012981 0.014522 0.014426 0.013071 0.019359 0.764669 0.973319 0.764669 0.980857 0.764669 0.980857 0.764669 0.987248 0.764669 0.02778 0.764669 0.973319 0.764669 0.020242 0.764669 0.020242 0.764669 0.02778 0.764669 0.973319 0.764669 0.980857 0.764669 0.980857 0.764669 0.987248 0.716215 0.981004 0.716215 0.981004 0.716215 0.981004 0.716215 0.981004 0.764669 0.02778 0.764669 0.020242 0.764669 0.020242 0.716215 0.020094 0.716215 0.020094 0.716215 0.020094 0.716215 0.020094 0.764669 0.973319 0.764669 0.02778</float_array>
+ <technique_common>
+ <accessor source="#DVD_cover_reflection-DVD_Box-UV-array" count="283" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="DVD_cover_reflection-vertices">
+ <input semantic="POSITION" source="#DVD_cover_reflection-positions"/>
+ <input semantic="NORMAL" source="#DVD_cover_reflection-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="300">
+ <input semantic="VERTEX" source="#DVD_cover_reflection-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#DVD_cover_reflection-DVD_Box-UV" offset="1" set="1"/>
+ <p>7 0 10 1 25 3 25 3 10 1 24 2 25 3 24 2 27 5 27 5 24 2 26 4 27 6 26 7 29 9 29 9 26 7 28 8 29 9 28 8 8 11 8 11 28 8 9 10 11 12 0 13 31 15 31 15 0 13 30 14 31 15 30 14 33 17 33 17 30 14 32 16 33 18 32 19 35 21 35 21 32 19 34 20 35 21 34 20 9 10 9 10 34 20 2 22 4 257 6 23 37 258 37 258 6 23 36 24 37 259 36 24 39 260 39 260 36 24 38 25 39 26 38 27 41 29 41 29 38 27 40 28 41 29 40 28 5 30 5 30 40 28 8 11 1 31 3 32 43 34 43 34 3 32 42 33 43 34 42 33 45 36 45 36 42 33 44 35 45 37 44 38 47 40 47 40 44 38 46 39 47 40 46 39 2 22 2 22 46 39 5 30 22 41 11 12 49 43 49 43 11 12 48 42 49 43 48 42 51 45 51 45 48 42 50 44 51 46 50 47 53 49 53 49 50 47 52 48 53 49 52 48 23 50 23 50 52 48 10 1 19 51 7 0 55 53 55 53 7 0 54 52 55 53 54 52 57 55 57 55 54 52 56 54 57 56 56 57 59 59 59 59 56 57 58 58 59 59 58 58 20 60 20 60 58 58 6 23 16 261 4 262 61 62 61 62 4 262 60 61 61 62 60 61 63 64 63 64 60 61 62 63 63 65 62 66 65 68 65 68 62 66 64 67 65 68 64 67 17 69 17 69 64 67 3 32 0 13 12 70 67 72 67 72 12 70 66 71 67 72 66 71 69 74 69 74 66 71 68 73 69 75 68 76 71 78 71 78 68 76 70 77 71 78 70 77 1 31 1 31 70 77 14 79 18 80 21 81 73 83 73 83 21 81 72 82 73 83 72 82 75 85 75 85 72 82 74 84 75 86 74 87 77 89 77 89 74 87 76 88 77 89 76 88 19 51 19 51 76 88 23 50 21 81 13 90 79 92 79 92 13 90 78 91 79 92 78 91 81 94 81 94 78 91 80 93 81 95 80 96 83 98 83 98 80 96 82 97 83 98 82 97 22 41 22 41 82 97 12 70 15 99 18 80 85 101 85 101 18 80 84 100 85 101 84 100 87 103 87 103 84 100 86 102 87 104 86 105 89 263 89 263 86 105 88 106 89 264 88 106 16 265 16 265 88 106 20 60 13 90 15 99 91 108 91 108 15 99 90 107 91 108 90 107 93 110 93 110 90 107 92 109 93 111 92 112 95 114 95 114 92 112 94 113 95 114 94 113 14 79 14 79 94 113 17 69 0 13 67 72 30 14 30 14 67 72 98 115 98 115 97 116 30 14 30 14 97 116 32 16 67 72 69 74 98 115 98 115 69 74 99 117 99 117 96 118 98 115 98 115 96 118 97 116 1 31 43 34 71 78 71 78 43 34 100 119 71 78 100 119 69 121 69 121 100 119 99 120 43 34 45 36 100 119 100 119 45 36 101 122 101 122 96 123 100 119 100 119 96 123 99 124 2 22 34 20 47 40 47 40 34 20 102 125 47 40 102 125 45 127 45 127 102 125 101 126 32 128 97 129 34 20 34 20 97 129 102 125 97 130 96 131 102 125 102 125 96 131 101 132 3 32 64 67 42 33 42 33 64 67 105 133 42 33 105 133 44 35 44 35 105 133 104 134 64 67 62 135 105 133 105 133 62 135 106 136 106 136 103 137 105 133 105 133 103 137 104 134 4 266 37 267 60 61 60 61 37 267 107 138 60 61 107 138 62 63 62 63 107 138 106 139 39 269 108 140 37 268 37 268 108 140 107 138 108 140 103 141 107 138 107 138 103 141 106 142 5 30 46 39 41 29 41 29 46 39 109 143 109 143 108 144 41 29 41 29 108 144 39 145 46 39 44 146 109 143 109 143 44 146 104 147 104 148 103 149 109 143 109 143 103 149 108 150 6 23 58 58 36 24 36 24 58 58 112 270 112 271 111 151 36 24 36 24 111 151 38 25 58 58 56 152 112 272 112 272 56 152 113 153 113 153 110 154 112 273 112 273 110 154 111 151 7 0 25 3 54 52 54 52 25 3 114 155 54 52 114 155 56 54 56 54 114 155 113 156 25 3 27 5 114 155 114 155 27 5 115 157 115 157 110 158 114 155 114 155 110 158 113 159 8 11 40 28 29 9 29 9 40 28 116 160 29 9 116 160 27 162 27 162 116 160 115 161 38 163 111 164 40 28 40 28 111 164 116 160 111 165 110 166 116 160 116 160 110 166 115 167 9 10 28 8 35 21 35 21 28 8 119 168 119 168 118 169 35 21 35 21 118 169 33 170 28 8 26 171 119 168 119 168 26 171 120 172 120 172 117 173 119 168 119 168 117 173 118 169 10 1 52 48 24 2 24 2 52 48 121 174 24 2 121 174 26 4 26 4 121 174 120 175 52 48 50 176 121 174 121 174 50 176 122 177 122 177 117 178 121 174 121 174 117 178 120 179 11 12 31 15 48 42 48 42 31 15 123 180 48 42 123 180 50 44 50 44 123 180 122 181 33 17 118 182 31 15 31 15 118 182 123 180 118 183 117 184 123 180 123 180 117 184 122 185 12 70 82 97 66 71 66 71 82 97 126 186 66 71 126 186 68 73 68 73 126 186 125 187 80 188 127 189 82 97 82 97 127 189 126 186 127 189 124 190 126 186 126 186 124 190 125 187 13 90 91 108 78 91 78 91 91 108 128 191 128 191 127 192 78 91 78 91 127 192 80 93 91 108 93 110 128 191 128 191 93 110 129 193 129 193 124 194 128 191 128 191 124 194 127 195 14 79 70 77 95 114 95 114 70 77 130 196 95 114 130 196 93 198 93 198 130 196 129 197 70 77 68 199 130 196 130 196 68 199 125 200 125 201 124 202 130 196 130 196 124 202 129 203 15 99 85 101 90 107 90 107 85 101 133 204 90 107 133 204 92 109 92 109 133 204 132 205 87 103 134 206 85 101 85 101 134 206 133 204 134 206 131 207 133 204 133 204 131 207 132 205 16 274 61 62 89 275 89 275 61 62 135 208 135 208 134 209 89 276 89 276 134 209 87 210 61 62 63 64 135 208 135 208 63 64 136 211 136 211 131 212 135 208 135 208 131 212 134 213 17 69 94 113 65 68 65 68 94 113 137 214 65 68 137 214 63 216 63 216 137 214 136 215 94 113 92 217 137 214 137 214 92 217 132 218 132 219 131 220 137 214 137 214 131 220 136 221 18 80 73 83 84 100 84 100 73 83 140 222 140 222 139 223 84 100 84 100 139 223 86 102 73 83 75 85 140 222 140 222 75 85 141 224 141 224 138 225 140 222 140 222 138 225 139 223 19 51 55 53 77 89 77 89 55 53 142 226 77 89 142 226 75 228 75 228 142 226 141 227 55 53 57 55 142 226 142 226 57 55 143 229 143 229 138 230 142 226 142 226 138 230 141 231 20 60 88 106 59 59 59 59 88 106 144 277 59 59 144 278 57 233 57 233 144 278 143 232 86 234 139 235 88 106 88 106 139 235 144 279 139 236 138 237 144 280 144 280 138 237 143 238 21 81 79 92 72 82 72 82 79 92 147 239 72 82 147 239 74 84 74 84 147 239 146 240 81 94 148 241 79 92 79 92 148 241 147 239 148 241 145 242 147 239 147 239 145 242 146 240 22 41 49 43 83 98 83 98 49 43 149 243 149 243 148 244 83 98 83 98 148 244 81 245 49 43 51 45 149 243 149 243 51 45 150 246 150 246 145 247 149 243 149 243 145 247 148 248 23 50 76 88 53 49 53 49 76 88 151 249 53 49 151 249 51 251 51 251 151 249 150 250 76 88 74 252 151 249 151 249 74 252 146 253 146 254 145 255 151 249 151 249 145 255 150 256 5 30 8 11 2 22 2 22 8 11 9 10 17 69 3 32 14 79 14 79 3 32 1 31 20 60 6 23 16 282 16 282 6 23 4 281 23 50 10 1 19 51 19 51 10 1 7 0 12 70 0 13 22 41 22 41 0 13 11 12 21 81 18 80 13 90 13 90 18 80 15 99</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="DVD_cover-reflection">
+ <node id="DVD_Box_reflection" name="DVD_Box_reflection" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#DVD_cover_reflection">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#DVD_reflection_material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Media/DVD_cover.dae b/Studio/Content/Models Library/Media/DVD_cover.dae
new file mode 100644
index 00000000..80ebc029
--- /dev/null
+++ b/Studio/Content/Models Library/Media/DVD_cover.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/media/DVD_cover.mb</source_data>
+ </contributor>
+ <created>2008-10-01T19:19:54Z</created>
+ <modified>2008-10-01T19:19:54Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="DVD_material" name="DVD_material">
+ <instance_effect url="#DVD_material-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="DVD_material-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="DVD_cover" name="DVD_cover">
+ <mesh>
+ <source id="DVD_cover-positions" name="position">
+ <float_array id="DVD_cover-positions-array" count="456">-35 -48 -1.65 -33 -48 -3.85 -33 -50 -1.65 33 -48 -3.85 35 -48 -1.65 33 -50 -1.65 35 -48 1.65 33 -48 3.85 33 -50 1.65 -33 -50 1.65 -33 -48 3.85 -35 -48 1.65 -35 48 -1.65 -33 50 -1.65 -33 48 -3.85 33 50 -1.65 35 48 -1.65 33 48 -3.85 33 50 1.65 33 48 3.85 35 48 1.65 -33 50 1.65 -35 48 1.65 -33 48 3.85 -33 -48.7654 3.68253 33 -48.7654 3.68253 -33 -49.4142 3.20564 33 -49.4142 3.20564 -33 -49.8478 2.4919 33 -49.8478 2.4919 -34.8478 -48.7654 -1.65 -34.8478 -48.7654 1.65 -34.4142 -49.4142 -1.65 -34.4142 -49.4142 1.65 -33.7654 -49.8478 -1.65 -33.7654 -49.8478 1.65 34.8478 -48.7654 1.65 34.8478 -48.7654 -1.65 34.4142 -49.4142 1.65 34.4142 -49.4142 -1.65 33.7654 -49.8478 1.65 33.7654 -49.8478 -1.65 33 -48.7654 -3.68253 -33 -48.7654 -3.68253 33 -49.4142 -3.20564 -33 -49.4142 -3.20564 33 -49.8478 -2.4919 -33 -49.8478 -2.4919 -34.8478 -48 2.4919 -34.8478 48 2.4919 -34.4142 -48 3.20564 -34.4142 48 3.20564 -33.7654 -48 3.68253 -33.7654 48 3.68253 33.7654 -48 3.68253 33.7654 48 3.68253 34.4142 -48 3.20564 34.4142 48 3.20564 34.8478 -48 2.4919 34.8478 48 2.4919 34.8478 -48 -2.4919 34.8478 48 -2.4919 34.4142 -48 -3.20564 34.4142 48 -3.20564 33.7654 -48 -3.68253 33.7654 48 -3.68253 -34.8478 48 -2.4919 -34.8478 -48 -2.4919 -34.4142 48 -3.20564 -34.4142 -48 -3.20564 -33.7654 48 -3.68253 -33.7654 -48 -3.68253 -33 49.8478 2.4919 33 49.8478 2.4919 -33 49.4142 3.20564 33 49.4142 3.20564 -33 48.7654 3.68253 33 48.7654 3.68253 -33.7654 49.8478 -1.65 -33.7654 49.8478 1.65 -34.4142 49.4142 -1.65 -34.4142 49.4142 1.65 -34.8478 48.7654 -1.65 -34.8478 48.7654 1.65 33.7654 49.8478 1.65 33.7654 49.8478 -1.65 34.4142 49.4142 1.65 34.4142 49.4142 -1.65 34.8478 48.7654 1.65 34.8478 48.7654 -1.65 33 49.8478 -2.4919 -33 49.8478 -2.4919 33 49.4142 -3.20564 -33 49.4142 -3.20564 33 48.7654 -3.68253 -33 48.7654 -3.68253 -34.2189 -49.2189 -2.99085 -34.3654 -49.3654 -2.44085 -34.7078 -48.7803 -2.50838 -34.3654 -48.7189 -3.15194 -33.7803 -48.7803 -3.52863 -33.7189 -49.3654 -3.15194 -33.7803 -49.7078 -2.50838 34.2189 -49.2189 -2.99085 33.7189 -49.3654 -3.15194 33.7803 -48.7803 -3.52863 34.3654 -48.7189 -3.15194 34.7078 -48.7803 -2.50838 34.3654 -49.3654 -2.44085 33.7803 -49.7078 -2.50838 34.2189 -49.2189 2.99085 34.3654 -49.3654 2.44085 34.7078 -48.7803 2.50838 34.3654 -48.7189 3.15194 33.7803 -48.7803 3.52863 33.7189 -49.3654 3.15194 33.7803 -49.7078 2.50838 -34.2189 -49.2189 2.99085 -34.3654 -49.3654 2.44085 -33.7803 -49.7078 2.50838 -33.7189 -49.3654 3.15194 -33.7803 -48.7803 3.52863 -34.3654 -48.7189 3.15194 -34.7078 -48.7803 2.50838 -34.2189 49.2189 -2.99085 -34.3654 48.7189 -3.15194 -34.7078 48.7803 -2.50838 -34.3654 49.3654 -2.44085 -33.7803 49.7078 -2.50838 -33.7189 49.3654 -3.15194 -33.7803 48.7803 -3.52863 34.2189 49.2189 -2.99085 33.7189 49.3654 -3.15194 33.7803 49.7078 -2.50838 34.3654 49.3654 -2.44085 34.7078 48.7803 -2.50838 34.3654 48.7189 -3.15194 33.7803 48.7803 -3.52863 34.2189 49.2189 2.99085 34.3654 49.3654 2.44085 33.7803 49.7078 2.50838 33.7189 49.3654 3.15194 33.7803 48.7803 3.52863 34.3654 48.7189 3.15194 34.7078 48.7803 2.50838 -34.2189 49.2189 2.99085 -33.7189 49.3654 3.15194 -33.7803 49.7078 2.50838 -34.3654 49.3654 2.44085 -34.7078 48.7803 2.50838 -34.3654 48.7189 3.15194 -33.7803 48.7803 3.52863</float_array>
+ <technique_common>
+ <accessor source="#DVD_cover-positions-array" count="152" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="DVD_cover-normals" name="normal">
+ <float_array id="DVD_cover-normals-array" count="456">-0.991724 -0.094924 -0.086442 -0.103983 -0.103983 -0.989128 -0.094922 -0.991724 -0.086442 0.103983 -0.103983 -0.989128 0.991724 -0.094924 -0.086442 0.094922 -0.991724 -0.086442 0.991724 -0.094924 0.086442 0.103983 -0.103983 0.989128 0.094922 -0.991724 0.086442 -0.094922 -0.991724 0.086442 -0.103983 -0.103983 0.989128 -0.991724 -0.094924 0.086442 -0.991724 0.094924 -0.086442 -0.094922 0.991724 -0.086442 -0.103983 0.103983 -0.989128 0.094922 0.991724 -0.086442 0.991724 0.094924 -0.086442 0.103983 0.103983 -0.989128 0.094922 0.991724 0.086442 0.103983 0.103983 0.989128 0.991724 0.094924 0.086442 -0.094922 0.991724 0.086442 -0.991724 0.094924 0.086442 -0.103983 0.103983 0.989128 -0.082821 -0.403027 0.911433 0.082821 -0.403026 0.911433 -0.062938 -0.735781 0.674289 0.062938 -0.735781 0.674289 -0.076983 -0.934922 0.346401 0.076983 -0.934922 0.346401 -0.924699 -0.374309 -0.06945 -0.924699 -0.374309 0.06945 -0.706048 -0.706046 -0.054732 -0.706048 -0.706046 0.054732 -0.374309 -0.924699 -0.069452 -0.374309 -0.924699 0.069452 0.924699 -0.374309 0.06945 0.924699 -0.374309 -0.06945 0.706048 -0.706046 0.054732 0.706048 -0.706046 -0.054732 0.374309 -0.924699 0.069452 0.374309 -0.924699 -0.069452 0.082821 -0.403027 -0.911433 -0.082821 -0.403026 -0.911433 0.062938 -0.735781 -0.674289 -0.062938 -0.735781 -0.674289 0.076983 -0.934922 -0.346401 -0.076983 -0.934922 -0.346401 -0.934923 -0.076983 0.3464 -0.934923 0.076984 0.346399 -0.735783 -0.062938 0.674287 -0.735783 0.062939 0.674287 -0.403028 -0.082821 0.911432 -0.403028 0.082821 0.911432 0.403028 -0.082821 0.911432 0.403028 0.082821 0.911432 0.735783 -0.062939 0.674287 0.735783 0.062938 0.674287 0.934923 -0.076984 0.346399 0.934923 0.076983 0.3464 0.934923 -0.076983 -0.3464 0.934923 0.076984 -0.346399 0.735783 -0.062938 -0.674287 0.735783 0.062939 -0.674287 0.403028 -0.082821 -0.911432 0.403028 0.082821 -0.911432 -0.934923 0.076983 -0.3464 -0.934923 -0.076984 -0.346399 -0.735783 0.062938 -0.674287 -0.735783 -0.062939 -0.674287 -0.403028 0.082821 -0.911432 -0.403028 -0.082821 -0.911432 -0.076983 0.934922 0.346401 0.076983 0.934922 0.346401 -0.062938 0.735781 0.674289 0.062938 0.735781 0.674289 -0.082821 0.403026 0.911433 0.082821 0.403027 0.911433 -0.374309 0.924699 -0.069452 -0.374309 0.924699 0.069452 -0.706048 0.706046 -0.054732 -0.706048 0.706046 0.054732 -0.924699 0.374309 -0.06945 -0.924699 0.374309 0.06945 0.374309 0.924699 0.069452 0.374309 0.924699 -0.069452 0.706048 0.706046 0.054732 0.706048 0.706046 -0.054732 0.924699 0.374309 0.06945 0.924699 0.374309 -0.06945 0.076983 0.934922 -0.346401 -0.076983 0.934922 -0.346401 0.062938 0.735781 -0.674289 -0.062938 0.735781 -0.674289 0.082821 0.403026 -0.911433 -0.082821 0.403027 -0.911433 -0.593351 -0.593351 -0.543938 -0.681524 -0.681524 -0.266553 -0.894051 -0.330281 -0.302633 -0.702338 -0.301373 -0.6449 -0.351747 -0.351747 -0.867495 -0.301373 -0.702339 -0.644899 -0.330282 -0.894051 -0.302632 0.593352 -0.59335 -0.543939 0.301373 -0.702338 -0.644899 0.351748 -0.351747 -0.867495 0.702338 -0.301372 -0.6449 0.894051 -0.330281 -0.302634 0.681524 -0.681523 -0.266553 0.330282 -0.894051 -0.302633 0.593351 -0.593351 0.543938 0.681524 -0.681524 0.266553 0.894051 -0.330281 0.302633 0.702338 -0.301373 0.6449 0.351747 -0.351747 0.867495 0.301373 -0.702339 0.644899 0.330282 -0.894051 0.302632 -0.593352 -0.59335 0.543939 -0.681524 -0.681523 0.266553 -0.330282 -0.894051 0.302633 -0.301373 -0.702338 0.644899 -0.351748 -0.351747 0.867495 -0.702338 -0.301372 0.6449 -0.894051 -0.330281 0.302634 -0.593352 0.59335 -0.543939 -0.702338 0.301372 -0.6449 -0.894051 0.330281 -0.302634 -0.681524 0.681523 -0.266553 -0.330282 0.894051 -0.302633 -0.301373 0.702338 -0.644899 -0.351748 0.351747 -0.867495 0.593351 0.593351 -0.543938 0.301373 0.702339 -0.644899 0.330282 0.894051 -0.302632 0.681524 0.681524 -0.266553 0.894051 0.330281 -0.302633 0.702338 0.301373 -0.6449 0.351747 0.351747 -0.867495 0.593352 0.59335 0.543939 0.681524 0.681523 0.266553 0.330282 0.894051 0.302633 0.301373 0.702338 0.644899 0.351748 0.351747 0.867495 0.702338 0.301372 0.6449 0.894051 0.330281 0.302634 -0.593351 0.593351 0.543938 -0.301373 0.702339 0.644899 -0.330282 0.894051 0.302632 -0.681524 0.681524 0.266553 -0.894051 0.330281 0.302633 -0.702338 0.301373 0.6449 -0.351747 0.351747 0.867495</float_array>
+ <technique_common>
+ <accessor source="#DVD_cover-normals-array" count="152" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="DVD_cover-DVD_Box-UV" name="DVD_Box-UV">
+ <float_array id="DVD_cover-DVD_Box-UV-array" count="566">0.68017 0.026452 0.026593 0.026452 0.026593 0.018901 0.68017 0.018901 0.026593 0.0125 0.68017 0.0125 0.870362 0.174748 0.870362 0.827325 0.862028 0.827325 0.862028 0.174748 0.852197 0.827325 0.852197 0.174748 0.764669 0.026681 0.726217 0.026681 0.726217 0.019143 0.764669 0.019143 0.726217 0.012752 0.764669 0.012752 0.852197 0.841308 0.813662 0.841308 0.813662 0.834893 0.852197 0.834893 0.813662 0.827325 0.726217 0.026681 0.726217 0.019143 0.726217 0.012752 0.813662 0.160764 0.852197 0.160764 0.852197 0.16718 0.813662 0.16718 0.813662 0.174748 0.679924 0.026452 0.026346 0.026452 0.026346 0.018901 0.679924 0.018901 0.026346 0.0125 0.679924 0.0125 0.795497 0.827325 0.795497 0.174748 0.803831 0.174748 0.803831 0.827325 0.764669 0.97222 0.774479 0.026681 0.774479 0.97222 0.782795 0.026681 0.782795 0.97222 0.012588 0.973548 0.012588 0.026452 0.019013 0.026452 0.019013 0.973548 0.026593 0.973548 0.68017 0.973548 0.687749 0.026452 0.687749 0.973548 0.694175 0.026452 0.694175 0.973548 0.708091 0.97222 0.708091 0.026681 0.716407 0.026681 0.716407 0.97222 0.726217 0.97222 0.774479 0.026681 0.774479 0.97222 0.782795 0.026681 0.782795 0.97222 0.012342 0.973548 0.012342 0.026452 0.018767 0.026452 0.018767 0.973548 0.026346 0.973548 0.726217 0.97222 0.716407 0.97222 0.716407 0.026681 0.708091 0.97222 0.708091 0.026681 0.693928 0.026452 0.693928 0.973548 0.687503 0.973548 0.687503 0.026452 0.679924 0.973548 0.852197 0.827176 0.852197 0.174599 0.862028 0.174599 0.862028 0.827176 0.870362 0.174599 0.870362 0.827176 0.68017 0.9875 0.026593 0.9875 0.026593 0.981099 0.68017 0.981099 0.813662 0.174599 0.813662 0.167031 0.852197 0.167031 0.813662 0.160615 0.852197 0.160615 0.764669 0.986149 0.726217 0.986149 0.726217 0.979758 0.764669 0.979758 0.813662 0.827176 0.852197 0.834744 0.813662 0.834744 0.852197 0.841159 0.813662 0.841159 0.764669 0.986149 0.726217 0.986149 0.726217 0.979758 0.803831 0.827176 0.803831 0.174599 0.795497 0.827176 0.795497 0.174599 0.679924 0.9875 0.026346 0.9875 0.026346 0.981099 0.679924 0.981099 0.716215 0.018995 0.717002 0.013233 0.708717 0.0196 0.710594 0.014675 0.687651 0.018753 0.693445 0.019359 0.693928 0.026452 0.687043 0.012981 0.691994 0.014426 0.693445 0.019359 0.803639 0.835041 0.796124 0.834433 0.795497 0.827325 0.813662 0.841308 0.804428 0.840826 0.804428 0.840826 0.798005 0.839378 0.796124 0.834433 0.018619 0.018753 0.019227 0.012981 0.012342 0.026452 0.012825 0.019359 0.014275 0.014426 0.774671 0.018995 0.782169 0.0196 0.773884 0.013233 0.780292 0.014675 0.782169 0.0196 0.803639 0.167032 0.804428 0.161247 0.813662 0.160764 0.795497 0.174748 0.796124 0.167639 0.796124 0.167639 0.798005 0.162695 0.804428 0.161247 0.717002 0.013233 0.708091 0.026681 0.708716 0.0196 0.710594 0.014675 0.687898 0.018753 0.693691 0.019359 0.68729 0.012981 0.692241 0.014426 0.693691 0.019359 0.86222 0.167032 0.869735 0.167639 0.870362 0.174748 0.852197 0.160764 0.861431 0.161247 0.861431 0.161247 0.867854 0.162695 0.869735 0.167639 0.86222 0.835041 0.861431 0.840826 0.852197 0.841308 0.870362 0.827325 0.869735 0.834433 0.867854 0.839378 0.018865 0.018753 0.019473 0.012981 0.012588 0.026452 0.013071 0.019359 0.014522 0.014426 0.019473 0.012981 0.774671 0.018995 0.782169 0.0196 0.773884 0.013233 0.773884 0.013233 0.780292 0.014675 0.782169 0.0196 0.716215 0.979905 0.708717 0.979301 0.726217 0.986149 0.717002 0.985668 0.710594 0.984226 0.803639 0.166883 0.804428 0.161098 0.796124 0.16749 0.798005 0.162546 0.804428 0.161098 0.687651 0.981246 0.687043 0.987018 0.679924 0.9875 0.693928 0.973548 0.693445 0.980641 0.693445 0.980641 0.691994 0.985574 0.687043 0.987018 0.803639 0.834892 0.796124 0.834285 0.804428 0.840676 0.798005 0.839229 0.774671 0.979905 0.773884 0.985668 0.764669 0.986149 0.782169 0.979301 0.780292 0.984226 0.773884 0.985668 0.018619 0.981246 0.012825 0.980641 0.012342 0.973548 0.026346 0.9875 0.019227 0.987018 0.019227 0.987018 0.014275 0.985574 0.012825 0.980641 0.86222 0.834892 0.861431 0.840676 0.869735 0.834285 0.867854 0.839229 0.687898 0.981246 0.68729 0.987018 0.68017 0.9875 0.693691 0.980641 0.692241 0.985574 0.68729 0.987018 0.708716 0.979301 0.708091 0.97222 0.726217 0.986149 0.717002 0.985668 0.717002 0.985668 0.710594 0.984226 0.708716 0.979301 0.86222 0.166883 0.869735 0.16749 0.861431 0.161098 0.867854 0.162546 0.774671 0.979905 0.773884 0.985668 0.764669 0.986149 0.782169 0.979301 0.780292 0.984226 0.773884 0.985668 0.018865 0.981246 0.013071 0.980641 0.012588 0.973548 0.026593 0.9875 0.019473 0.987018 0.019473 0.987018 0.014522 0.985574 0.013071 0.980641 0.764669 0.026681 0.764669 0.019143 0.764669 0.019143 0.764669 0.012752 0.764669 0.97222 0.764669 0.026681 0.764669 0.979758 0.764669 0.979758 0.764669 0.97222 0.764669 0.026681 0.764669 0.019143 0.764669 0.019143 0.764669 0.012752 0.716215 0.018995 0.716215 0.018995 0.716215 0.018995 0.716215 0.018995 0.764669 0.97222 0.764669 0.979758 0.764669 0.979758 0.716215 0.979905 0.716215 0.979905 0.716215 0.979905 0.716215 0.979905 0.764669 0.026681 0.764669 0.97222</float_array>
+ <technique_common>
+ <accessor source="#DVD_cover-DVD_Box-UV-array" count="283" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="DVD_cover-vertices">
+ <input semantic="POSITION" source="#DVD_cover-positions"/>
+ <input semantic="NORMAL" source="#DVD_cover-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="300">
+ <input semantic="VERTEX" source="#DVD_cover-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#DVD_cover-DVD_Box-UV" offset="1" set="1"/>
+ <p>7 0 10 1 25 3 25 3 10 1 24 2 25 3 24 2 27 5 27 5 24 2 26 4 27 6 26 7 29 9 29 9 26 7 28 8 29 9 28 8 8 11 8 11 28 8 9 10 11 12 0 13 31 15 31 15 0 13 30 14 31 15 30 14 33 17 33 17 30 14 32 16 33 18 32 19 35 21 35 21 32 19 34 20 35 21 34 20 9 10 9 10 34 20 2 22 4 257 6 23 37 258 37 258 6 23 36 24 37 259 36 24 39 260 39 260 36 24 38 25 39 26 38 27 41 29 41 29 38 27 40 28 41 29 40 28 5 30 5 30 40 28 8 11 1 31 3 32 43 34 43 34 3 32 42 33 43 34 42 33 45 36 45 36 42 33 44 35 45 37 44 38 47 40 47 40 44 38 46 39 47 40 46 39 2 22 2 22 46 39 5 30 22 41 11 12 49 43 49 43 11 12 48 42 49 43 48 42 51 45 51 45 48 42 50 44 51 46 50 47 53 49 53 49 50 47 52 48 53 49 52 48 23 50 23 50 52 48 10 1 19 51 7 0 55 53 55 53 7 0 54 52 55 53 54 52 57 55 57 55 54 52 56 54 57 56 56 57 59 59 59 59 56 57 58 58 59 59 58 58 20 60 20 60 58 58 6 23 16 261 4 262 61 62 61 62 4 262 60 61 61 62 60 61 63 64 63 64 60 61 62 63 63 65 62 66 65 68 65 68 62 66 64 67 65 68 64 67 17 69 17 69 64 67 3 32 0 13 12 70 67 72 67 72 12 70 66 71 67 72 66 71 69 74 69 74 66 71 68 73 69 75 68 76 71 78 71 78 68 76 70 77 71 78 70 77 1 31 1 31 70 77 14 79 18 80 21 81 73 83 73 83 21 81 72 82 73 83 72 82 75 85 75 85 72 82 74 84 75 86 74 87 77 89 77 89 74 87 76 88 77 89 76 88 19 51 19 51 76 88 23 50 21 81 13 90 79 92 79 92 13 90 78 91 79 92 78 91 81 94 81 94 78 91 80 93 81 95 80 96 83 98 83 98 80 96 82 97 83 98 82 97 22 41 22 41 82 97 12 70 15 99 18 80 85 101 85 101 18 80 84 100 85 101 84 100 87 103 87 103 84 100 86 102 87 104 86 105 89 263 89 263 86 105 88 106 89 264 88 106 16 265 16 265 88 106 20 60 13 90 15 99 91 108 91 108 15 99 90 107 91 108 90 107 93 110 93 110 90 107 92 109 93 111 92 112 95 114 95 114 92 112 94 113 95 114 94 113 14 79 14 79 94 113 17 69 0 13 67 72 30 14 30 14 67 72 98 115 98 115 97 116 30 14 30 14 97 116 32 16 67 72 69 74 98 115 98 115 69 74 99 117 99 117 96 118 98 115 98 115 96 118 97 116 1 31 43 34 71 78 71 78 43 34 100 119 71 78 100 119 69 121 69 121 100 119 99 120 43 34 45 36 100 119 100 119 45 36 101 122 101 122 96 123 100 119 100 119 96 123 99 124 2 22 34 20 47 40 47 40 34 20 102 125 47 40 102 125 45 127 45 127 102 125 101 126 32 128 97 129 34 20 34 20 97 129 102 125 97 130 96 131 102 125 102 125 96 131 101 132 3 32 64 67 42 33 42 33 64 67 105 133 42 33 105 133 44 35 44 35 105 133 104 134 64 67 62 135 105 133 105 133 62 135 106 136 106 136 103 137 105 133 105 133 103 137 104 134 4 266 37 267 60 61 60 61 37 267 107 138 60 61 107 138 62 63 62 63 107 138 106 139 39 269 108 140 37 268 37 268 108 140 107 138 108 140 103 141 107 138 107 138 103 141 106 142 5 30 46 39 41 29 41 29 46 39 109 143 109 143 108 144 41 29 41 29 108 144 39 145 46 39 44 146 109 143 109 143 44 146 104 147 104 148 103 149 109 143 109 143 103 149 108 150 6 23 58 58 36 24 36 24 58 58 112 270 112 271 111 151 36 24 36 24 111 151 38 25 58 58 56 152 112 272 112 272 56 152 113 153 113 153 110 154 112 273 112 273 110 154 111 151 7 0 25 3 54 52 54 52 25 3 114 155 54 52 114 155 56 54 56 54 114 155 113 156 25 3 27 5 114 155 114 155 27 5 115 157 115 157 110 158 114 155 114 155 110 158 113 159 8 11 40 28 29 9 29 9 40 28 116 160 29 9 116 160 27 162 27 162 116 160 115 161 38 163 111 164 40 28 40 28 111 164 116 160 111 165 110 166 116 160 116 160 110 166 115 167 9 10 28 8 35 21 35 21 28 8 119 168 119 168 118 169 35 21 35 21 118 169 33 170 28 8 26 171 119 168 119 168 26 171 120 172 120 172 117 173 119 168 119 168 117 173 118 169 10 1 52 48 24 2 24 2 52 48 121 174 24 2 121 174 26 4 26 4 121 174 120 175 52 48 50 176 121 174 121 174 50 176 122 177 122 177 117 178 121 174 121 174 117 178 120 179 11 12 31 15 48 42 48 42 31 15 123 180 48 42 123 180 50 44 50 44 123 180 122 181 33 17 118 182 31 15 31 15 118 182 123 180 118 183 117 184 123 180 123 180 117 184 122 185 12 70 82 97 66 71 66 71 82 97 126 186 66 71 126 186 68 73 68 73 126 186 125 187 80 188 127 189 82 97 82 97 127 189 126 186 127 189 124 190 126 186 126 186 124 190 125 187 13 90 91 108 78 91 78 91 91 108 128 191 128 191 127 192 78 91 78 91 127 192 80 93 91 108 93 110 128 191 128 191 93 110 129 193 129 193 124 194 128 191 128 191 124 194 127 195 14 79 70 77 95 114 95 114 70 77 130 196 95 114 130 196 93 198 93 198 130 196 129 197 70 77 68 199 130 196 130 196 68 199 125 200 125 201 124 202 130 196 130 196 124 202 129 203 15 99 85 101 90 107 90 107 85 101 133 204 90 107 133 204 92 109 92 109 133 204 132 205 87 103 134 206 85 101 85 101 134 206 133 204 134 206 131 207 133 204 133 204 131 207 132 205 16 274 61 62 89 275 89 275 61 62 135 208 135 208 134 209 89 276 89 276 134 209 87 210 61 62 63 64 135 208 135 208 63 64 136 211 136 211 131 212 135 208 135 208 131 212 134 213 17 69 94 113 65 68 65 68 94 113 137 214 65 68 137 214 63 216 63 216 137 214 136 215 94 113 92 217 137 214 137 214 92 217 132 218 132 219 131 220 137 214 137 214 131 220 136 221 18 80 73 83 84 100 84 100 73 83 140 222 140 222 139 223 84 100 84 100 139 223 86 102 73 83 75 85 140 222 140 222 75 85 141 224 141 224 138 225 140 222 140 222 138 225 139 223 19 51 55 53 77 89 77 89 55 53 142 226 77 89 142 226 75 228 75 228 142 226 141 227 55 53 57 55 142 226 142 226 57 55 143 229 143 229 138 230 142 226 142 226 138 230 141 231 20 60 88 106 59 59 59 59 88 106 144 277 59 59 144 278 57 233 57 233 144 278 143 232 86 234 139 235 88 106 88 106 139 235 144 279 139 236 138 237 144 280 144 280 138 237 143 238 21 81 79 92 72 82 72 82 79 92 147 239 72 82 147 239 74 84 74 84 147 239 146 240 81 94 148 241 79 92 79 92 148 241 147 239 148 241 145 242 147 239 147 239 145 242 146 240 22 41 49 43 83 98 83 98 49 43 149 243 149 243 148 244 83 98 83 98 148 244 81 245 49 43 51 45 149 243 149 243 51 45 150 246 150 246 145 247 149 243 149 243 145 247 148 248 23 50 76 88 53 49 53 49 76 88 151 249 53 49 151 249 51 251 51 251 151 249 150 250 76 88 74 252 151 249 151 249 74 252 146 253 146 254 145 255 151 249 151 249 145 255 150 256 5 30 8 11 2 22 2 22 8 11 9 10 17 69 3 32 14 79 14 79 3 32 1 31 20 60 6 23 16 282 16 282 6 23 4 281 23 50 10 1 19 51 19 51 10 1 7 0 12 70 0 13 22 41 22 41 0 13 11 12 21 81 18 80 13 90 13 90 18 80 15 99</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="DVD_cover">
+ <node id="DVD_Box" name="DVD_Box" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#DVD_cover">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#DVD_material"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-1.dae b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-1.dae
new file mode 100644
index 00000000..613c91e8
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-1.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/cubes/RoundedCube-1.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:59:58Z</created>
+ <modified>2008-09-19T17:59:58Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="RoundedCube" name="RoundedCube">
+ <mesh>
+ <source id="RoundedCube-positions" name="position">
+ <float_array id="RoundedCube-positions-array" count="744">-50 -40 -40 -50 -40 40 -50 40 40 -50 40 -40 -50 -42.7493 -40 -50 -42.7493 40 -50 -42.7493 40.7559 -50 -42.4822 41.7526 -50 -41.7526 42.4822 -50 -40.7559 42.7493 -50 -40 42.7493 -50 40 42.7493 -50 40.7559 42.7493 -50 41.7526 42.4822 -50 42.4822 41.7526 -50 42.7493 40.7559 -50 42.7493 40 -50 42.7493 -40 -50 42.7493 -40.7559 -50 42.4822 -41.7526 -50 41.7526 -42.4822 -50 40.7559 -42.7493 -50 40 -42.7493 -50 -40 -42.7493 -50 -40.7559 -42.7493 -50 -41.7526 -42.4822 -50 -42.4822 -41.7526 -50 -42.7493 -40.7559 -49.0286 -46.3746 -40 -49.0286 -46.3746 40 -49.0286 -46.3746 41.7526 -49.0286 -45.7554 44.0636 -49.0286 -44.0636 45.7554 -49.0286 -41.7526 46.3746 -49.0286 -40 46.3746 -49.0286 40 46.3746 -49.0286 41.7526 46.3746 -49.0286 44.0636 45.7554 -49.0286 45.7554 44.0636 -49.0286 46.3746 41.7526 -49.0286 46.3746 40 -49.0286 46.3746 -40 -49.0286 46.3746 -41.7526 -49.0286 45.7554 -44.0636 -49.0286 44.0636 -45.7554 -49.0286 41.7526 -46.3746 -49.0286 40 -46.3746 -49.0286 -40 -46.3746 -49.0286 -41.7526 -46.3746 -49.0286 -44.0636 -45.7554 -49.0286 -45.7554 -44.0636 -49.0286 -46.3746 -41.7526 -46.3746 -49.0286 -40 -46.3746 -49.0286 40 -46.3746 -49.0286 42.4822 -46.3746 -48.1515 45.7554 -46.3746 -45.7554 48.1515 -46.3746 -42.4822 49.0286 -46.3746 -40 49.0286 -46.3746 40 49.0286 -46.3746 42.4822 49.0286 -46.3746 45.7554 48.1515 -46.3746 48.1515 45.7554 -46.3746 49.0286 42.4822 -46.3746 49.0286 40 -46.3746 49.0286 -40 -46.3746 49.0286 -42.4822 -46.3746 48.1515 -45.7554 -46.3746 45.7554 -48.1515 -46.3746 42.4822 -49.0286 -46.3746 40 -49.0286 -46.3746 -40 -49.0286 -46.3746 -42.4822 -49.0286 -46.3746 -45.7554 -48.1515 -46.3746 -48.1515 -45.7554 -46.3746 -49.0286 -42.4822 -42.7493 -50 -40 -42.7493 -50 40 -42.7493 -50 42.7493 -42.7493 -49.0286 46.3746 -42.7493 -46.3746 49.0286 -42.7493 -42.7493 50 -42.7493 -40 50 -42.7493 40 50 -42.7493 42.7493 50 -42.7493 46.3746 49.0286 -42.7493 49.0286 46.3746 -42.7493 50 42.7493 -42.7493 50 40 -42.7493 50 -40 -42.7493 50 -42.7493 -42.7493 49.0286 -46.3746 -42.7493 46.3746 -49.0286 -42.7493 42.7493 -50 -42.7493 40 -50 -42.7493 -40 -50 -42.7493 -42.7493 -50 -42.7493 -46.3746 -49.0286 -42.7493 -49.0286 -46.3746 -42.7493 -50 -42.7493 -40 -50 -40 -40 -50 40 -40 -50 42.7493 -40 -49.0286 46.3746 -40 -46.3746 49.0286 -40 -42.7493 50 -40 -40 50 -40 40 50 -40 42.7493 50 -40 46.3746 49.0286 -40 49.0286 46.3746 -40 50 42.7493 -40 50 40 -40 50 -40 -40 50 -42.7493 -40 49.0286 -46.3746 -40 46.3746 -49.0286 -40 42.7493 -50 -40 40 -50 -40 -40 -50 -40 -42.7493 -50 -40 -46.3746 -49.0286 -40 -49.0286 -46.3746 -40 -50 -42.7493 40 -50 -40 40 -50 40 40 -50 42.7493 40 -49.0286 46.3746 40 -46.3746 49.0286 40 -42.7493 50 40 -40 50 40 40 50 40 42.7493 50 40 46.3746 49.0286 40 49.0286 46.3746 40 50 42.7493 40 50 40 40 50 -40 40 50 -42.7493 40 49.0286 -46.3746 40 46.3746 -49.0286 40 42.7493 -50 40 40 -50 40 -40 -50 40 -42.7493 -50 40 -46.3746 -49.0286 40 -49.0286 -46.3746 40 -50 -42.7493 42.7493 -50 -40 42.7493 -50 40 42.7493 -50 42.7493 42.7493 -49.0286 46.3746 42.7493 -46.3746 49.0286 42.7493 -42.7493 50 42.7493 -40 50 42.7493 40 50 42.7493 42.7493 50 42.7493 46.3746 49.0286 42.7493 49.0286 46.3746 42.7493 50 42.7493 42.7493 50 40 42.7493 50 -40 42.7493 50 -42.7493 42.7493 49.0286 -46.3746 42.7493 46.3746 -49.0286 42.7493 42.7493 -50 42.7493 40 -50 42.7493 -40 -50 42.7493 -42.7493 -50 42.7493 -46.3746 -49.0286 42.7493 -49.0286 -46.3746 42.7493 -50 -42.7493 46.3746 -49.0286 -40 46.3746 -49.0286 40 46.3746 -49.0286 42.4822 46.3746 -48.1515 45.7554 46.3746 -45.7554 48.1515 46.3746 -42.4822 49.0286 46.3746 -40 49.0286 46.3746 40 49.0286 46.3746 42.4822 49.0286 46.3746 45.7554 48.1515 46.3746 48.1515 45.7554 46.3746 49.0286 42.4822 46.3746 49.0286 40 46.3746 49.0286 -40 46.3746 49.0286 -42.4822 46.3746 48.1515 -45.7554 46.3746 45.7554 -48.1515 46.3746 42.4822 -49.0286 46.3746 40 -49.0286 46.3746 -40 -49.0286 46.3746 -42.4822 -49.0286 46.3746 -45.7554 -48.1515 46.3746 -48.1515 -45.7554 46.3746 -49.0286 -42.4822 49.0286 -46.3746 -40 49.0286 -46.3746 40 49.0286 -46.3746 41.7526 49.0286 -45.7554 44.0636 49.0286 -44.0636 45.7554 49.0286 -41.7526 46.3746 49.0286 -40 46.3746 49.0286 40 46.3746 49.0286 41.7526 46.3746 49.0286 44.0636 45.7554 49.0286 45.7554 44.0636 49.0286 46.3746 41.7526 49.0286 46.3746 40 49.0286 46.3746 -40 49.0286 46.3746 -41.7526 49.0286 45.7554 -44.0636 49.0286 44.0636 -45.7554 49.0286 41.7526 -46.3746 49.0286 40 -46.3746 49.0286 -40 -46.3746 49.0286 -41.7526 -46.3746 49.0286 -44.0636 -45.7554 49.0286 -45.7554 -44.0636 49.0286 -46.3746 -41.7526 50 -42.7493 -40 50 -42.7493 40 50 -42.7493 40.7559 50 -42.4822 41.7526 50 -41.7526 42.4822 50 -40.7559 42.7493 50 -40 42.7493 50 40 42.7493 50 40.7559 42.7493 50 41.7526 42.4822 50 42.4822 41.7526 50 42.7493 40.7559 50 42.7493 40 50 42.7493 -40 50 42.7493 -40.7559 50 42.4822 -41.7526 50 41.7526 -42.4822 50 40.7559 -42.7493 50 40 -42.7493 50 -40 -42.7493 50 -40.7559 -42.7493 50 -41.7526 -42.4822 50 -42.4822 -41.7526 50 -42.7493 -40.7559 50 -40 -40 50 -40 40 50 40 40 50 40 -40</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-positions-array" count="248" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-normals" name="normal">
+ <float_array id="RoundedCube-normals-array" count="816">-0.994537 -0.104385 0 -0.988123 -0.153111 0.013056 -1 -0.000000 0 -0.98733 -0.137909 0.078491 -0.989489 -0.060171 0.131498 -0.988123 -0.013058 0.15311 -0.987666 0 0.156577 -0.994537 0 0.104385 -0.988123 0.013056 0.15311 -1 0 0 -0.989489 0.060169 0.131498 -0.98733 0.137909 0.078491 -0.988123 0.15311 0.013056 -0.987666 0.156577 0 -0.994537 0.104384 0 -0.988123 0.15311 -0.013056 -1 -0.000000 0 -0.98733 0.137909 -0.078491 -0.989489 0.060167 -0.131499 -0.988123 0.013054 -0.15311 -0.987666 0 -0.156577 -0.994537 0 -0.104385 -0.988123 -0.013055 -0.15311 -1 0 0 -0.98733 -0.07849 -0.137908 -0.989489 -0.131499 -0.060168 -0.988123 -0.15311 -0.013056 -0.987666 -0.156577 0 1 -0.000000 0 0.988123 -0.15311 0.013056 0.987666 -0.156577 0 0.989489 -0.131498 0.060168 0.98733 -0.078492 0.137908 0.988123 -0.013057 0.15311 0.994537 0 0.104385 1 0 0 0.988123 0.013057 0.15311 0.987666 0 0.156577 0.989489 0.06017 0.131498 0.98733 0.137909 0.078491 0.988123 0.153111 0.013056 0.994537 0.104385 0 1 -0.000000 0 0.988123 0.15311 -0.013056 0.987666 0.156577 0 0.98733 0.137909 -0.078491 0.989489 0.060167 -0.131499 0.988123 0.013054 -0.15311 0.994537 0 -0.104385 1 0 0 0.988123 -0.013055 -0.15311 0.987666 0 -0.156577 0.989489 -0.060168 -0.131499 0.98733 -0.137909 -0.078491 0.988123 -0.15311 -0.013056 0.994537 -0.104384 0 -0.870789 -0.488742 0.05345 -0.907073 -0.420974 0 -0.841132 -0.469421 0.268592 -0.883262 -0.215339 0.416507 -0.870789 -0.053451 0.488743 -0.866026 0 0.5 -0.870789 0.05345 0.488743 -0.907073 0 0.420974 -0.857096 0.464349 0.223082 -0.866739 0.255759 0.428194 -0.870789 0.488743 0.05345 -0.866025 0.5 0 -0.870789 0.488743 -0.05345 -0.907073 0.420974 0 -0.841132 0.469421 -0.268591 -0.883262 0.215338 -0.416507 -0.870789 0.053449 -0.488743 -0.866026 0 -0.5 -0.870789 -0.053449 -0.488743 -0.907073 0 -0.420974 -0.841132 -0.268591 -0.469421 -0.883262 -0.416507 -0.215338 -0.870789 -0.488743 -0.05345 -0.866025 -0.5 0 -0.5098 -0.85376 0.105826 -0.575061 -0.818111 0 -0.736618 -0.478222 0.478224 -0.736617 -0.478224 0.478223 -0.509799 -0.105826 0.85376 -0.5 0 0.866026 -0.509799 0.105826 0.85376 -0.575061 0 0.81811 -0.736617 0.478224 0.478223 -0.736618 0.478223 0.478224 -0.509799 0.85376 0.105826 -0.5 0.866026 0 -0.509799 0.85376 -0.105826 -0.575061 0.81811 0 -0.736617 0.478223 -0.478223 -0.736617 0.478223 -0.478223 -0.509799 0.105825 -0.85376 -0.5 0 -0.866026 -0.5098 -0.105825 -0.85376 -0.575061 0 -0.81811 -0.736617 -0.478225 -0.478223 -0.736617 -0.478224 -0.478223 -0.509799 -0.85376 -0.105826 -0.5 -0.866026 0 -0.134586 -0.975822 0.172215 -0.149146 -0.988815 0 -0.114286 -0.832191 0.542583 -0.144186 -0.493073 0.857956 -0.280157 -0.678789 0.678791 -0.280157 -0.678789 0.678791 -0.134713 -0.128482 0.98252 -0.130526 0 0.991445 -0.134586 0.172215 0.975822 -0.149146 0 0.988815 -0.114287 0.542584 0.83219 -0.144186 0.857957 0.493073 -0.280157 0.678789 0.678791 -0.280156 0.678788 0.678793 -0.134713 0.98252 0.128482 -0.130526 0.991445 0 -0.134586 0.975822 -0.172215 -0.149146 0.988815 0 -0.114286 0.832191 -0.542583 -0.144186 0.493073 -0.857956 -0.280157 0.67879 -0.678791 -0.280156 0.678789 -0.678791 -0.134713 0.128481 -0.98252 -0.130526 0 -0.991445 -0.134586 -0.172215 -0.975822 -0.149146 0 -0.988815 -0.114286 -0.542584 -0.83219 -0.144186 -0.857957 -0.493073 -0.280157 -0.67879 -0.678791 -0.280157 -0.678789 -0.678792 -0.134713 -0.98252 -0.128482 -0.130526 -0.991445 0 0 -1 0 0 -0.991445 0.130526 0 -0.866025 0.5 0 -0.5 0.866025 0 -0.130526 0.991445 0 0 1 0 0 1 0 0.130526 0.991445 0 0.5 0.866026 0 0.866026 0.5 0 0.991445 0.130526 0 1 0 0 1 0 0 0.991445 -0.130526 0 0.866025 -0.5 0 0.5 -0.866025 0 0.130526 -0.991445 0 0 -1 0 0 -1 0 -0.130526 -0.991445 0 -0.5 -0.866026 0 -0.866026 -0.5 0 -0.991445 -0.130526 0 -1 0 0 -1 0 0 -0.991445 0.130526 0 -0.866026 0.5 0 -0.5 0.866026 0 -0.130526 0.991445 0 0 1 0 0 1 0 0.130526 0.991445 0 0.5 0.866026 0 0.866025 0.5 0 0.991445 0.130526 0 1 0 0 1 0 0 0.991445 -0.130526 0 0.866026 -0.5 0 0.5 -0.866026 0 0.130526 -0.991445 0 0 -1 0 0 -1 0 -0.130526 -0.991445 0 -0.5 -0.866026 0 -0.866025 -0.5 0 -0.991445 -0.130526 0 -1 0 0.130526 -0.991445 0 0.134713 -0.98252 0.128482 0.144186 -0.857957 0.493073 0.114287 -0.542584 0.83219 0.134586 -0.172215 0.975822 0.149146 0 0.988815 0.130526 0 0.991445 0.134713 0.128482 0.98252 0.144186 0.493073 0.857956 0.114286 0.832191 0.542583 0.134586 0.975822 0.172215 0.149146 0.988815 0 0.130526 0.991445 0 0.134713 0.98252 -0.128482 0.144186 0.857957 -0.493073 0.114286 0.542584 -0.83219 0.134586 0.172215 -0.975822 0.149146 0 -0.988815 0.130526 0 -0.991445 0.134713 -0.128482 -0.98252 0.144186 -0.493073 -0.857956 0.114286 -0.832191 -0.542583 0.134586 -0.975822 -0.172215 0.149146 -0.988815 0 0.509799 -0.85376 0.105826 0.5 -0.866026 0 0.45181 -0.44507 0.773163 0.5338 -0.739301 0.410477 0.509799 -0.105826 0.85376 0.575061 0 0.818111 0.509799 0.105826 0.85376 0.5 0 0.866026 0.45181 0.773163 0.445069 0.5338 0.410477 0.739301 0.5098 0.85376 0.105826 0.575061 0.818111 0 0.509799 0.85376 -0.105826 0.5 0.866026 0 0.451809 0.445069 -0.773163 0.5338 0.739301 -0.410477 0.5098 0.105825 -0.85376 0.575061 0 -0.818111 0.509799 -0.105825 -0.85376 0.5 0 -0.866026 0.45181 -0.773163 -0.445069 0.5338 -0.410477 -0.739301 0.509799 -0.85376 -0.105826 0.575061 -0.81811 0 0.870789 -0.488743 0.05345 0.866025 -0.5 0 0.841132 -0.268592 0.469421 0.883262 -0.416507 0.215338 0.870789 -0.05345 0.488743 0.907073 0 0.420974 0.870789 0.053451 0.488743 0.866026 0 0.5 0.841132 0.46942 0.268592 0.883262 0.215338 0.416507 0.870789 0.488743 0.05345 0.907073 0.420974 0 0.870789 0.488743 -0.05345 0.866025 0.5 0 0.86674 0.255759 -0.428194 0.857096 0.46435 -0.223082 0.870789 0.053449 -0.488743 0.907073 0 -0.420974 0.870789 -0.053449 -0.488743 0.866026 0 -0.5 0.841132 -0.469421 -0.268591 0.883262 -0.215338 -0.416507 0.870789 -0.488743 -0.05345 0.907073 -0.420974 0 -0.719859 -0.670469 0.179651 -0.719859 -0.179653 0.670469 -0.719859 0.179653 0.670468 -0.719859 0.670469 0.179651 -0.71986 0.670468 -0.179651 -0.71986 0.179651 -0.670468 -0.71986 -0.179651 -0.670468 -0.71986 -0.670468 -0.179651 -0.267741 -0.930661 0.249369 -0.267741 -0.24937 0.930661 -0.267741 0.24937 0.930661 -0.26774 0.930661 0.249369 -0.26774 0.930661 -0.249369 -0.26774 0.249369 -0.930661 -0.267739 -0.249369 -0.930662 -0.26774 -0.930661 -0.249369</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-normals-array" count="272" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-Texture" name="Texture">
+ <float_array id="RoundedCube-Texture-array" count="692">0.907925 0.064037 0.915634 0.064037 0.907925 0.092074 0.925798 0.06676 0.933239 0.074201 0.935963 0.084366 0.935963 0.092074 0.935963 0.907925 0.935963 0.915634 0.907925 0.907925 0.933239 0.925798 0.925798 0.933239 0.915634 0.935963 0.907925 0.935963 0.092074 0.935963 0.084366 0.935963 0.092074 0.907925 0.074201 0.933239 0.06676 0.925798 0.064037 0.915634 0.064037 0.907925 0.064037 0.092074 0.064037 0.084366 0.092074 0.092074 0.06676 0.074201 0.074201 0.06676 0.084366 0.064037 0.092074 0.064037 0.092074 0.092074 0.092074 0.064037 0.074201 0.06676 0.06676 0.074201 0.092074 0.907925 0.06676 0.925798 0.074201 0.933239 0.092074 0.935963 0.907925 0.907925 0.907925 0.935963 0.925798 0.933239 0.933239 0.925798 0.907925 0.092074 0.933239 0.074201 0.925798 0.06676 0.907925 0.064037 0.925798 0.027065 0.907925 0.027065 0.949366 0.03338 0.966619 0.050633 0.972935 0.074201 0.972935 0.092074 0.972935 0.925798 0.972935 0.907925 0.949366 0.96662 0.966619 0.949366 0.925798 0.972935 0.907925 0.972935 0.074201 0.972935 0.092074 0.972935 0.050633 0.96662 0.03338 0.949366 0.027065 0.925798 0.027065 0.907925 0.027065 0.074201 0.027065 0.092074 0.03338 0.050633 0.050633 0.03338 0.074201 0.027065 0.092074 0.027065 0.027065 0.933239 0 0.925798 0 0.907925 0 0.925798 0.966619 0.008944 0.991056 0.03338 0.027065 0.06676 0 0.074201 0 0.092074 0 0.074201 0.027065 0.933239 0 0.925798 0 0.907925 0 0.925798 0.991056 0.96662 0.966619 0.991056 0.972935 0.933239 1 0.925798 1 0.907925 1 0.925798 0.972935 0.06676 1 0.074201 0.972935 0.092074 1 0.092074 1 0.074201 0.03338 0.991056 0.008944 0.96662 0.972935 0.933239 1 0.925798 1 0.907925 1 0.925798 0.972935 0.06676 1 0.074201 1 0.092074 1 0.074201 0.008944 0.03338 0.03338 0.008944 0.027065 0.06676 0.027065 0.092074 0 0.074201 0 0.092074 0 0.074201 0.064037 0.935963 0.064037 0 0.064037 0.027065 0.027065 0.008944 0.027065 0.03338 0.027065 0.008944 0.064037 0.064037 0.027065 0.06676 0.027065 0.06676 0.064037 0.972935 0.064037 1 0.027065 0.96662 0.027065 0.991056 0.027065 0.96662 0.935963 0.935963 0.972935 0.933239 0.972935 0.933239 0.935963 0.064037 0.935963 0.092074 0.935963 1 0.935963 0.972935 0.972935 0.991056 0.972935 0.96662 0.972935 0.991056 0.972935 0.933239 0.972935 0.933239 0.935963 0.027065 0.935963 0 0.972935 0.03338 0.972935 0.008944 0.972935 0.03338 0.064037 0.092074 0.027065 0.06676 0.027065 0.06676 0.092074 0.907925 0.092074 0.935963 0.092074 0 0.092074 0.027065 0.064037 0 0.064037 0 0.092074 0.064037 0.092074 0.092074 0.092074 0.972935 0.092074 1 0.907925 0.092074 0.907925 1 0.935963 1 0.935963 1 0.907925 0 0.092074 0.092074 0.907925 0 0.092074 0 0.092074 0 0.092074 1 0.907925 1 0.907925 1 0.935963 0 0.907925 0 0.907925 0 0.064037 1 0.092074 1 0.092074 1 0.935963 0 0.972935 0.008944 0.935963 0 0.064037 1 0.027065 0.991056 0.064037 1 0.008944 0.03338 0.03338 0.008944 0.03338 0.050633 0.050633 0.03338 0.03338 0.008944 1 0.074201 1 0.074201 0.03338 0.991056 0.008944 0.96662 0.050633 0.96662 0.03338 0.949366 0.008944 0.96662 0 0.925798 0 0.925798 0.991056 0.96662 0.96662 0.991056 0.96662 0.949366 0.949366 0.96662 0.96662 0.991056 0 0.925798 0 0.925798 0.96662 0.008944 0.991056 0.03338 0.949366 0.03338 0.96662 0.050633 0.991056 0.03338 1 0.074201 1 0.074201 0.074201 0.027065 0.092074 0.027065 0.092074 0.027065 0.027065 0.092074 0.027065 0.092074 0.027065 0.925798 0.027065 0.907925 0.027065 0.907925 0.074201 0.972935 0.092074 0.972935 0.092074 0.972935 0.925798 0.972935 0.907925 0.972935 0.907925 0.972935 0.972935 0.907925 0.972935 0.907925 0.972935 0.074201 0.972935 0.092074 0.972935 0.092074 0.925798 0.027065 0.907925 0.027065 0.907925 0.027065 0 0.092074 0 0.907925 0 0.092074 0.933239 0 0.933239 0 1 0.06676 0 0.092074 0 0.907925 0 0.092074 1 0.933239 1 0.933239 0.933239 1 1 0.907925 1 0.092074 1 0.907925 0.06676 1 0.06676 1 0 0.933239 1 0.907925 1 0.092074 1 0.907925 0 0.06676 0 0.06676 0.06676 0 0.027065 0.966619 0.027065 0.966619 0.027065 0.03338 0.027065 0.06676 0.027065 0.03338 0.027065 0.96662 0.027065 0.96662 0.935963 0.972935 0.972935 0.966619 0.972935 0.933239 0.972935 0.966619 0.972935 0.03338 0.972935 0.03338 0.972935 0.96662 0.972935 0.933239 0.972935 0.96662 0.972935 0.03338 0.972935 0.03338 0.064037 0.027065 0.027065 0.03338 0.027065 0.06676 0.027065 0.03338 0.907925 0.972935 0.935963 0.972935 0.935963 0.972935 0.092074 0.027065 0.064037 0.027065 0.064037 0.027065 0.092074 0.972935 0.907925 0.972935 0.907925 0.972935 0.907925 0.027065 0.092074 0.027065 0.092074 0.027065 0.064037 0.972935 0.092074 0.972935 0.092074 0.972935 0.935963 0.027065 0.907925 0.027065 0.907925 0.027065 0.064037 0.972935 0.027065 0.966619 0.027065 0.966619 0.935963 0.027065 0.972935 0.03338 0.972935 0.03338 0.03338 0.008944 0.06676 0 0.074201 0.027065 0.06676 0 0.008944 0.03338 0 0.06676 0 0.06676 0.008944 0.96662 0 0.933239 0.027065 0.925798 0 0.933239 0.03338 0.991056 0.06676 1 0.06676 1 0.96662 0.991056 0.933239 1 0.925798 0.972935 0.933239 1 0.991056 0.96662 1 0.933239 1 0.933239 0.991056 0.03338 1 0.06676 0.972935 0.074201 1 0.06676 0.96662 0.008944 0.933239 0 0.933239 0 0.907925 0.027065 0.092074 0.027065 0.907925 0.027065 0.074201 0.027065 0.074201 0.027065 0.027065 0.092074 0.027065 0.907925 0.027065 0.092074 0.027065 0.925798 0.027065 0.925798 0.092074 0.972935 0.907925 0.972935 0.092074 0.972935 0.925798 0.972935 0.925798 0.972935 0.972935 0.907925 0.972935 0.092074 0.972935 0.907925 0.972935 0.074201 0.972935 0.074201</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-Texture-array" count="346" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="RoundedCube-vertices">
+ <input semantic="POSITION" source="#RoundedCube-positions"/>
+ </vertices>
+ <triangles material="lambert2SG" count="492">
+ <input semantic="VERTEX" source="#RoundedCube-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#RoundedCube-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#RoundedCube-Texture" offset="2" set="1"/>
+ <p>5 0 0 6 1 1 1 2 2 6 1 1 7 3 3 1 2 2 7 3 3 8 4 4 1 2 2 8 4 4 9 5 5 1 2 2 9 5 5 10 6 6 1 2 2 11 7 7 12 8 8 2 9 9 12 8 8 13 10 10 2 9 9 13 10 10 14 11 11 2 9 9 14 11 11 15 12 12 2 9 9 15 12 12 16 13 13 2 9 9 17 14 14 18 15 15 3 16 16 18 15 15 19 17 17 3 16 16 19 17 17 20 18 18 3 16 16 20 18 18 21 19 19 3 16 16 21 19 19 22 20 20 3 16 16 23 21 21 24 22 22 0 23 23 24 22 22 25 24 24 0 23 23 25 24 24 26 25 25 0 23 23 26 25 25 27 26 26 0 23 23 27 26 26 4 27 27 0 23 23 245 28 28 222 29 26 221 30 29 245 28 28 223 31 30 222 29 26 245 28 28 224 32 31 223 31 30 245 28 28 225 33 22 224 32 31 245 28 28 226 34 21 225 33 22 246 35 32 228 36 19 227 37 20 246 35 32 229 38 33 228 36 19 246 35 32 230 39 34 229 38 33 246 35 32 231 40 15 230 39 34 246 35 32 232 41 35 231 40 15 247 42 36 234 43 12 233 44 37 247 42 36 235 45 38 234 43 12 247 42 36 236 46 39 235 45 38 247 42 36 237 47 8 236 46 39 247 42 36 238 48 7 237 47 8 244 49 40 240 50 5 239 51 6 244 49 40 241 52 41 240 50 5 244 49 40 242 53 42 241 52 41 244 49 40 243 54 1 242 53 42 244 49 40 220 55 43 243 54 1 0 23 23 1 2 2 3 16 16 2 9 9 3 16 16 1 2 2 30 56 44 6 1 1 29 57 45 5 0 0 29 57 45 6 1 1 31 58 46 32 59 47 7 3 3 8 4 4 7 3 3 32 59 47 33 60 48 34 61 49 9 5 5 10 6 6 9 5 5 34 61 49 36 62 50 12 8 8 35 63 51 11 7 7 35 63 51 12 8 8 38 64 52 14 11 11 37 65 53 13 10 10 37 65 53 14 11 11 39 66 54 40 67 55 15 12 12 16 13 13 15 12 12 40 67 55 42 68 56 18 15 15 41 69 57 17 14 14 41 69 57 18 15 15 43 70 58 44 71 59 19 17 17 20 18 18 19 17 17 44 71 59 45 72 60 46 73 61 21 19 19 22 20 20 21 19 19 46 73 61 48 74 62 24 22 22 47 75 63 23 21 21 47 75 63 24 22 22 49 76 64 50 77 65 25 24 24 26 25 25 25 24 24 50 77 65 51 78 66 28 79 67 27 26 26 4 27 27 27 26 26 28 79 67 54 80 68 30 56 69 53 81 61 29 57 70 53 81 61 30 56 71 55 82 72 56 83 73 31 58 46 32 59 47 31 58 46 56 83 73 57 84 74 58 85 63 33 60 75 34 61 76 33 60 77 58 85 63 60 86 78 36 62 79 59 87 61 35 63 80 59 87 61 36 62 81 61 88 82 62 89 83 37 65 53 38 64 52 37 65 53 62 89 83 63 90 84 64 91 51 39 66 85 40 67 86 39 66 87 64 91 51 66 92 88 42 68 89 65 93 90 41 69 91 65 93 90 42 68 92 67 94 93 68 95 94 43 70 58 44 71 59 43 70 58 68 95 94 69 96 95 70 97 51 45 72 96 46 73 97 45 72 98 70 97 51 72 98 99 48 74 100 71 99 49 47 75 101 71 99 49 48 74 102 73 100 103 74 101 104 49 76 64 50 77 65 49 76 64 74 101 104 75 102 105 52 103 106 51 78 107 28 79 108 51 78 109 52 103 106 78 104 110 54 80 68 77 105 20 53 81 61 77 105 20 54 80 68 79 106 111 80 107 112 55 108 113 56 109 114 55 108 115 80 107 112 81 110 116 82 111 21 57 84 117 58 85 63 57 84 118 82 111 21 84 112 110 60 86 78 83 113 20 59 87 61 83 113 20 60 86 78 85 114 119 86 115 120 61 116 121 62 117 122 61 116 123 86 115 120 87 118 124 88 119 7 63 90 125 64 91 51 63 90 126 88 119 7 90 120 127 66 92 88 89 121 128 65 93 90 89 121 128 66 92 88 91 122 129 92 123 130 67 124 131 68 125 132 67 124 133 92 123 130 93 126 124 94 127 7 69 96 134 70 97 51 69 96 135 94 127 7 96 128 127 72 98 99 95 129 6 71 99 49 95 129 6 72 98 99 97 130 136 98 131 137 73 132 138 74 133 139 73 132 140 98 131 137 99 134 116 76 135 141 75 102 142 52 103 106 75 102 143 76 135 141 101 136 144 102 137 145 77 105 20 78 104 110 77 105 20 102 137 145 103 138 146 104 139 147 79 106 148 80 107 112 79 106 149 104 139 147 105 140 150 106 141 151 81 110 116 82 111 21 81 110 116 106 141 151 107 142 144 108 143 145 83 113 20 84 112 110 83 113 20 108 143 145 109 144 152 110 145 153 85 114 119 86 115 120 85 114 119 110 145 153 111 146 13 112 147 9 87 118 124 88 119 7 87 118 124 112 147 9 113 148 154 114 149 0 89 121 128 90 120 127 89 121 128 114 149 0 115 150 155 116 151 55 91 122 156 92 123 130 91 122 157 116 151 55 117 152 13 118 153 9 93 126 124 94 127 7 93 126 124 118 153 9 119 154 2 120 155 0 95 129 6 96 128 127 95 129 6 120 155 0 121 156 45 122 157 158 97 130 136 98 131 137 97 130 136 122 157 158 123 158 150 100 159 159 99 134 116 76 135 141 99 134 116 100 159 159 125 160 9 126 161 13 101 136 144 102 137 145 101 136 144 126 161 13 127 162 160 128 163 45 103 138 161 104 139 147 103 138 162 128 163 45 129 164 0 130 165 2 105 140 150 106 141 151 105 140 150 130 165 2 131 166 9 132 167 13 107 142 144 108 143 145 107 142 144 132 167 13 133 168 55 134 169 155 109 144 152 110 145 153 109 144 152 134 169 155 135 170 145 136 171 144 111 146 13 112 147 9 111 146 13 136 171 144 137 172 159 138 173 150 113 148 154 114 149 0 113 148 154 138 173 150 139 174 163 140 175 152 115 150 164 116 151 55 115 150 165 140 175 152 141 176 145 142 177 144 117 152 13 118 153 9 117 152 13 142 177 144 143 178 151 144 179 150 119 154 2 120 155 0 119 154 2 144 179 150 145 180 147 146 181 146 121 156 45 122 157 158 121 156 45 146 181 146 147 182 0 124 183 154 123 158 150 100 159 159 123 158 150 124 183 154 149 184 7 150 185 124 125 160 9 126 161 13 125 160 9 150 185 124 151 186 166 152 187 136 127 162 167 128 163 45 127 162 168 152 187 136 153 188 127 154 189 6 129 164 0 130 165 2 129 164 0 154 189 6 155 190 7 156 191 124 131 166 9 132 167 13 131 166 9 156 191 124 157 192 130 158 193 129 133 168 55 134 169 155 133 168 55 158 193 129 159 194 110 160 195 20 135 170 145 136 171 144 135 170 145 160 195 20 161 196 141 162 197 116 137 172 159 138 173 150 137 172 159 162 197 116 163 198 169 164 199 119 139 174 170 140 175 152 139 174 171 164 199 119 165 200 110 166 201 20 141 176 145 142 177 144 141 176 145 166 201 20 167 202 21 168 203 116 143 178 151 144 179 150 143 178 151 168 203 116 169 204 112 170 205 111 145 180 147 146 181 146 145 180 147 170 205 111 171 206 127 148 207 128 147 182 0 124 183 154 147 182 0 148 207 128 150 185 124 149 184 7 174 208 84 173 209 51 174 208 84 149 184 7 152 187 136 151 186 172 176 210 138 175 211 173 176 210 138 151 186 174 153 188 127 177 212 99 154 189 6 178 213 49 154 189 6 177 212 99 156 191 124 155 190 7 180 214 95 179 215 51 180 214 95 155 190 7 158 193 129 157 192 130 182 216 131 181 217 132 182 216 131 157 192 130 159 194 110 183 218 68 160 195 20 184 219 61 160 195 20 183 218 68 162 197 116 161 196 141 186 220 105 185 221 106 186 220 105 161 196 141 164 199 119 163 198 175 188 222 121 187 223 176 188 222 121 163 198 177 165 200 110 189 224 78 166 201 20 190 225 61 166 201 20 189 224 78 168 203 116 167 202 21 192 226 74 191 227 63 192 226 74 167 202 21 170 205 111 169 204 112 194 228 113 193 229 114 194 228 113 169 204 112 171 206 127 195 230 88 148 207 128 172 231 90 148 207 128 195 230 88 174 208 84 173 209 51 198 232 85 197 233 86 198 232 85 173 209 51 176 210 178 175 211 179 200 234 180 199 235 181 200 234 180 175 211 182 177 212 99 201 236 183 178 213 49 202 237 101 178 213 49 201 236 184 180 214 95 179 215 51 204 238 96 203 239 86 204 238 96 179 215 51 182 216 185 181 217 186 206 240 187 205 241 188 206 240 187 181 217 189 183 218 68 207 242 190 184 219 61 208 243 70 184 219 61 207 242 191 186 220 105 185 221 106 210 244 107 209 245 108 210 244 107 185 221 106 188 222 192 187 223 193 212 246 194 211 247 195 212 246 194 187 223 196 189 224 78 213 248 197 190 225 61 214 249 70 190 225 61 213 248 198 192 226 74 191 227 63 216 250 75 215 251 76 216 250 75 191 227 63 194 228 199 193 229 200 218 252 201 217 253 202 218 252 201 193 229 203 195 230 88 219 254 204 172 231 90 196 255 91 172 231 90 219 254 205 198 232 206 197 233 207 222 29 26 221 30 29 222 29 26 197 233 208 200 234 180 199 235 181 224 32 31 223 31 30 224 32 31 199 235 181 201 236 62 225 33 22 202 237 209 226 34 21 202 237 210 225 33 22 204 238 211 203 239 212 228 36 19 227 37 20 228 36 19 203 239 213 206 240 187 205 241 188 230 39 34 229 38 33 230 39 34 205 241 188 207 242 214 231 40 15 208 243 215 232 41 35 208 243 216 231 40 15 210 244 217 209 245 218 234 43 12 233 44 37 234 43 12 209 245 219 211 247 195 235 45 38 212 246 194 236 46 39 212 246 194 235 45 38 213 248 50 237 47 8 214 249 220 238 48 7 214 249 221 237 47 8 216 250 222 215 251 223 240 50 5 239 51 6 240 50 5 215 251 224 218 252 201 217 253 202 242 53 42 241 52 41 242 53 42 217 253 202 219 254 225 243 54 1 196 255 226 220 55 43 196 255 227 243 54 1 4 27 27 5 0 0 0 23 23 1 2 2 0 23 23 5 0 0 10 6 6 11 7 7 1 2 2 2 9 9 1 2 2 11 7 7 16 13 13 17 14 14 2 9 9 3 16 16 2 9 9 17 14 14 22 20 20 23 21 21 3 16 16 0 23 23 3 16 16 23 21 21 28 79 67 29 57 45 4 27 27 5 0 0 4 27 27 29 57 45 31 58 46 7 3 3 30 56 44 6 1 1 30 56 44 7 3 3 32 59 47 33 60 48 8 4 4 9 5 5 8 4 4 33 60 48 34 61 49 35 63 51 10 6 6 11 7 7 10 6 6 35 63 51 37 65 53 13 10 10 36 62 50 12 8 8 36 62 50 13 10 10 38 64 52 39 66 54 14 11 11 15 12 12 14 11 11 39 66 54 40 67 55 41 69 57 16 13 13 17 14 14 16 13 13 41 69 57 43 70 58 19 17 17 42 68 56 18 15 15 42 68 56 19 17 17 44 71 59 45 72 60 20 18 18 21 19 19 20 18 18 45 72 60 46 73 61 47 75 63 22 20 20 23 21 21 22 20 20 47 75 63 49 76 64 25 24 24 48 74 62 24 22 22 48 74 62 25 24 24 50 77 65 51 78 66 26 25 25 27 26 26 26 25 25 51 78 66 52 103 106 53 81 61 28 79 228 29 57 229 28 79 230 53 81 61 55 256 72 31 58 46 54 80 231 30 56 44 54 80 232 31 58 46 56 257 73 57 84 233 32 59 47 33 60 48 32 59 47 57 84 233 58 85 63 59 87 61 34 61 234 35 63 235 34 61 236 59 87 61 61 258 82 37 65 53 60 86 237 36 62 50 60 86 238 37 65 53 62 259 83 63 90 239 38 64 52 39 66 54 38 64 52 63 90 239 64 91 51 65 93 90 40 67 240 41 69 241 40 67 242 65 93 90 67 260 93 43 70 58 66 92 243 42 68 56 66 92 244 43 70 58 68 261 94 69 96 245 44 71 59 45 72 60 44 71 59 69 96 245 70 97 51 71 99 49 46 73 246 47 75 247 46 73 248 71 99 49 73 262 103 49 76 64 72 98 249 48 74 62 72 98 250 49 76 64 74 263 104 75 102 251 50 77 65 51 78 66 50 77 65 75 102 251 76 135 141 77 105 20 52 103 106 53 81 61 52 103 106 77 105 20 79 106 119 55 264 252 78 104 110 54 80 68 78 104 110 55 264 253 80 107 112 81 110 116 56 265 254 57 84 255 56 265 256 81 110 116 82 111 21 83 113 20 58 85 63 59 87 61 58 85 63 83 113 20 85 114 119 61 266 257 84 112 110 60 86 78 84 112 110 61 266 258 86 115 259 87 118 124 62 267 260 63 90 261 62 267 262 87 118 124 88 119 7 89 121 128 64 91 51 65 93 90 64 91 51 89 121 128 91 122 136 67 268 263 90 120 127 66 92 88 90 120 127 67 268 264 92 123 130 93 126 124 68 269 265 69 96 266 68 269 267 93 126 124 94 127 7 95 129 6 70 97 51 71 99 49 70 97 51 95 129 6 97 130 136 73 270 268 96 128 127 72 98 99 96 128 127 73 270 269 98 131 270 99 134 116 74 271 271 75 102 272 74 271 273 99 134 116 100 159 159 101 136 144 76 135 141 77 105 20 76 135 141 101 136 144 102 137 145 103 138 152 78 104 110 79 106 119 78 104 110 103 138 152 104 139 147 105 140 150 80 107 112 81 110 116 80 107 112 105 140 150 106 141 151 107 142 144 82 111 21 83 113 20 82 111 21 107 142 144 108 143 145 109 144 152 84 112 110 85 114 119 84 112 110 109 144 152 110 145 274 111 146 13 86 115 275 87 118 124 86 115 276 111 146 13 112 147 9 113 148 154 88 119 7 89 121 128 88 119 7 113 148 154 114 149 0 115 150 45 90 120 127 91 122 136 90 120 127 115 150 45 116 151 55 117 152 13 92 123 130 93 126 124 92 123 130 117 152 13 118 153 9 119 154 2 94 127 7 95 129 6 94 127 7 119 154 2 120 155 0 121 156 45 96 128 127 97 130 136 96 128 127 121 156 45 122 157 277 123 158 150 98 131 278 99 134 116 98 131 279 123 158 150 124 183 154 125 160 9 100 159 159 101 136 144 100 159 159 125 160 9 126 161 13 127 162 55 102 137 145 103 138 152 102 137 145 127 162 55 128 163 45 129 164 0 104 139 147 105 140 150 104 139 147 129 164 0 130 165 2 131 166 9 106 141 151 107 142 144 106 141 151 131 166 9 132 167 13 133 168 55 108 143 145 109 144 152 108 143 145 133 168 55 134 169 280 135 170 145 110 145 281 111 146 13 110 145 282 135 170 145 136 171 144 137 172 159 112 147 9 113 148 154 112 147 9 137 172 159 138 173 150 139 174 147 114 149 0 115 150 45 114 149 0 139 174 147 140 175 152 141 176 145 116 151 55 117 152 13 116 151 55 141 176 145 142 177 144 143 178 151 118 153 9 119 154 2 118 153 9 143 178 151 144 179 150 145 180 147 120 155 0 121 156 45 120 155 0 145 180 147 146 181 283 147 182 0 122 157 284 123 158 150 122 157 285 147 182 0 148 207 128 149 184 7 124 183 154 125 160 9 124 183 154 149 184 7 150 185 124 151 186 130 126 161 13 127 162 55 126 161 13 151 186 130 152 187 136 153 188 127 128 163 45 129 164 0 128 163 45 153 188 127 154 189 6 155 190 7 130 165 2 131 166 9 130 165 2 155 190 7 156 191 124 157 192 130 132 167 13 133 168 55 132 167 13 157 192 130 158 193 286 159 194 110 134 169 287 135 170 145 134 169 288 159 194 110 160 195 20 161 196 141 136 171 144 137 172 159 136 171 144 161 196 141 162 197 116 163 198 112 138 173 150 139 174 147 138 173 150 163 198 112 164 199 119 165 200 110 140 175 152 141 176 145 140 175 152 165 200 110 166 201 20 167 202 21 142 177 144 143 178 151 142 177 144 167 202 21 168 203 116 169 204 112 144 179 150 145 180 147 144 179 150 169 204 112 170 205 289 171 206 127 146 181 290 147 182 0 146 181 291 171 206 127 172 231 90 173 209 51 148 207 128 149 184 7 148 207 128 173 209 51 151 186 130 150 185 124 175 211 260 174 208 84 175 211 260 150 185 124 152 187 136 176 210 138 153 188 127 177 212 99 153 188 127 176 210 138 178 213 49 179 215 51 154 189 6 155 190 7 154 189 6 179 215 51 157 192 130 156 191 124 181 217 132 180 214 95 181 217 132 156 191 124 158 193 292 182 216 293 159 194 110 183 218 68 159 194 110 182 216 294 184 219 61 185 221 106 160 195 20 161 196 141 160 195 20 185 221 106 163 198 112 162 197 116 187 223 271 186 220 105 187 223 271 162 197 116 164 199 119 188 222 121 165 200 110 189 224 78 165 200 110 188 222 121 190 225 61 191 227 63 166 201 20 167 202 21 166 201 20 191 227 63 169 204 112 168 203 116 193 229 114 192 226 74 193 229 114 168 203 116 170 205 295 194 228 296 171 206 127 195 230 88 171 206 127 194 228 297 196 255 91 197 233 86 172 231 90 173 209 51 172 231 90 197 233 86 175 211 298 174 208 299 199 235 181 198 232 300 199 235 181 174 208 301 176 210 302 200 234 180 177 212 303 201 236 62 177 212 304 200 234 180 202 237 101 203 239 86 178 213 49 179 215 51 178 213 49 203 239 86 181 217 305 180 214 306 205 241 188 204 238 307 205 241 188 180 214 308 182 216 309 206 240 187 183 218 310 207 242 214 183 218 311 206 240 187 208 243 70 209 245 108 184 219 61 185 221 106 184 219 61 209 245 108 187 223 312 186 220 313 211 247 195 210 244 314 211 247 195 186 220 315 188 222 316 212 246 194 189 224 317 213 248 50 189 224 318 212 246 194 214 249 70 215 251 76 190 225 61 191 227 63 190 225 61 215 251 76 193 229 319 192 226 320 217 253 202 216 250 321 217 253 202 192 226 322 194 228 323 218 252 201 195 230 324 219 254 225 195 230 325 218 252 201 220 55 43 221 30 29 196 255 326 197 233 327 196 255 328 221 30 29 199 235 181 198 232 329 223 31 30 222 29 26 223 31 30 198 232 330 200 234 180 224 32 31 201 236 62 225 33 22 201 236 62 224 32 31 226 34 21 227 37 20 202 237 331 203 239 332 202 237 333 227 37 20 205 241 188 204 238 334 229 38 33 228 36 19 229 38 33 204 238 335 206 240 187 230 39 34 207 242 214 231 40 15 207 242 214 230 39 34 232 41 35 233 44 37 208 243 336 209 245 337 208 243 338 233 44 37 211 247 195 210 244 339 235 45 38 234 43 12 235 45 38 210 244 340 212 246 194 236 46 39 213 248 50 237 47 8 213 248 50 236 46 39 238 48 7 239 51 6 214 249 341 215 251 342 214 249 343 239 51 6 217 253 202 216 250 344 241 52 41 240 50 5 241 52 41 216 250 345 218 252 201 242 53 42 219 254 225 243 54 1 219 254 225 242 53 42 244 49 40 245 28 28 220 55 43 221 30 29 220 55 43 245 28 28 245 28 28 246 35 32 226 34 21 227 37 20 226 34 21 246 35 32 246 35 32 247 42 36 232 41 35 233 44 37 232 41 35 247 42 36 247 42 36 244 49 40 238 48 7 239 51 6 238 48 7 244 49 40 244 49 40 247 42 36 245 28 28 246 35 32 245 28 28 247 42 36</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="RoundedCube-1">
+ <node id="_RoundedCube" name="RoundedCube" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#RoundedCube">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-2.dae b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-2.dae
new file mode 100644
index 00000000..3ecce5d2
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-2.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/cubes/RoundedCube-2.mb</source_data>
+ </contributor>
+ <created>2008-09-19T18:03:47Z</created>
+ <modified>2008-09-19T18:03:48Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="RoundedCube" name="RoundedCube">
+ <mesh>
+ <source id="RoundedCube-positions" name="position">
+ <float_array id="RoundedCube-positions-array" count="744">-50 -30 -30 -50 -30 30 -50 30 30 -50 30 -30 -50 -35.4985 -30 -50 -35.4985 30 -50 -35.4985 31.5117 -50 -34.9644 33.5051 -50 -33.5051 34.9644 -50 -31.5117 35.4985 -50 -30 35.4985 -50 30 35.4985 -50 31.5117 35.4985 -50 33.5051 34.9644 -50 34.9644 33.5051 -50 35.4985 31.5117 -50 35.4985 30 -50 35.4985 -30 -50 35.4985 -31.5117 -50 34.9644 -33.5051 -50 33.5051 -34.9644 -50 31.5117 -35.4985 -50 30 -35.4985 -50 -30 -35.4985 -50 -31.5117 -35.4985 -50 -33.5051 -34.9644 -50 -34.9644 -33.5051 -50 -35.4985 -31.5117 -48.0572 -42.7493 -30 -48.0572 -42.7493 30 -48.0572 -42.7493 33.5051 -48.0572 -41.5108 38.1272 -48.0572 -38.1272 41.5108 -48.0572 -33.5051 42.7493 -48.0572 -30 42.7493 -48.0572 30 42.7493 -48.0572 33.5051 42.7493 -48.0572 38.1272 41.5108 -48.0572 41.5108 38.1272 -48.0572 42.7493 33.5051 -48.0572 42.7493 30 -48.0572 42.7493 -30 -48.0572 42.7493 -33.5051 -48.0572 41.5108 -38.1272 -48.0572 38.1272 -41.5108 -48.0572 33.5051 -42.7493 -48.0572 30 -42.7493 -48.0572 -30 -42.7493 -48.0572 -33.5051 -42.7493 -48.0572 -38.1272 -41.5108 -48.0572 -41.5108 -38.1272 -48.0572 -42.7493 -33.5051 -42.7493 -48.0572 -30 -42.7493 -48.0572 30 -42.7493 -48.0572 34.9644 -42.7493 -46.3031 41.5108 -42.7493 -41.5108 46.3031 -42.7493 -34.9644 48.0572 -42.7493 -30 48.0572 -42.7493 30 48.0572 -42.7493 34.9644 48.0572 -42.7493 41.5108 46.3031 -42.7493 46.3031 41.5108 -42.7493 48.0572 34.9644 -42.7493 48.0572 30 -42.7493 48.0572 -30 -42.7493 48.0572 -34.9644 -42.7493 46.3031 -41.5108 -42.7493 41.5108 -46.3031 -42.7493 34.9644 -48.0572 -42.7493 30 -48.0572 -42.7493 -30 -48.0572 -42.7493 -34.9644 -48.0572 -42.7493 -41.5108 -46.3031 -42.7493 -46.3031 -41.5108 -42.7493 -48.0572 -34.9644 -35.4985 -50 -30 -35.4985 -50 30 -35.4985 -50 35.4985 -35.4985 -48.0572 42.7493 -35.4985 -42.7493 48.0572 -35.4985 -35.4985 50 -35.4985 -30 50 -35.4985 30 50 -35.4985 35.4985 50 -35.4985 42.7493 48.0572 -35.4985 48.0572 42.7493 -35.4985 50 35.4985 -35.4985 50 30 -35.4985 50 -30 -35.4985 50 -35.4985 -35.4985 48.0572 -42.7493 -35.4985 42.7493 -48.0572 -35.4985 35.4985 -50 -35.4985 30 -50 -35.4985 -30 -50 -35.4985 -35.4985 -50 -35.4985 -42.7493 -48.0572 -35.4985 -48.0572 -42.7493 -35.4985 -50 -35.4985 -30 -50 -30 -30 -50 30 -30 -50 35.4985 -30 -48.0572 42.7493 -30 -42.7493 48.0572 -30 -35.4985 50 -30 -30 50 -30 30 50 -30 35.4985 50 -30 42.7493 48.0572 -30 48.0572 42.7493 -30 50 35.4985 -30 50 30 -30 50 -30 -30 50 -35.4985 -30 48.0572 -42.7493 -30 42.7493 -48.0572 -30 35.4985 -50 -30 30 -50 -30 -30 -50 -30 -35.4985 -50 -30 -42.7493 -48.0572 -30 -48.0572 -42.7493 -30 -50 -35.4985 30 -50 -30 30 -50 30 30 -50 35.4985 30 -48.0572 42.7493 30 -42.7493 48.0572 30 -35.4985 50 30 -30 50 30 30 50 30 35.4985 50 30 42.7493 48.0572 30 48.0572 42.7493 30 50 35.4985 30 50 30 30 50 -30 30 50 -35.4985 30 48.0572 -42.7493 30 42.7493 -48.0572 30 35.4985 -50 30 30 -50 30 -30 -50 30 -35.4985 -50 30 -42.7493 -48.0572 30 -48.0572 -42.7493 30 -50 -35.4985 35.4985 -50 -30 35.4985 -50 30 35.4985 -50 35.4985 35.4985 -48.0572 42.7493 35.4985 -42.7493 48.0572 35.4985 -35.4985 50 35.4985 -30 50 35.4985 30 50 35.4985 35.4985 50 35.4985 42.7493 48.0572 35.4985 48.0572 42.7493 35.4985 50 35.4985 35.4985 50 30 35.4985 50 -30 35.4985 50 -35.4985 35.4985 48.0572 -42.7493 35.4985 42.7493 -48.0572 35.4985 35.4985 -50 35.4985 30 -50 35.4985 -30 -50 35.4985 -35.4985 -50 35.4985 -42.7493 -48.0572 35.4985 -48.0572 -42.7493 35.4985 -50 -35.4985 42.7493 -48.0572 -30 42.7493 -48.0572 30 42.7493 -48.0572 34.9644 42.7493 -46.3031 41.5108 42.7493 -41.5108 46.3031 42.7493 -34.9644 48.0572 42.7493 -30 48.0572 42.7493 30 48.0572 42.7493 34.9644 48.0572 42.7493 41.5108 46.3031 42.7493 46.3031 41.5108 42.7493 48.0572 34.9644 42.7493 48.0572 30 42.7493 48.0572 -30 42.7493 48.0572 -34.9644 42.7493 46.3031 -41.5108 42.7493 41.5108 -46.3031 42.7493 34.9644 -48.0572 42.7493 30 -48.0572 42.7493 -30 -48.0572 42.7493 -34.9644 -48.0572 42.7493 -41.5108 -46.3031 42.7493 -46.3031 -41.5108 42.7493 -48.0572 -34.9644 48.0572 -42.7493 -30 48.0572 -42.7493 30 48.0572 -42.7493 33.5051 48.0572 -41.5108 38.1272 48.0572 -38.1272 41.5108 48.0572 -33.5051 42.7493 48.0572 -30 42.7493 48.0572 30 42.7493 48.0572 33.5051 42.7493 48.0572 38.1272 41.5108 48.0572 41.5108 38.1272 48.0572 42.7493 33.5051 48.0572 42.7493 30 48.0572 42.7493 -30 48.0572 42.7493 -33.5051 48.0572 41.5108 -38.1272 48.0572 38.1272 -41.5108 48.0572 33.5051 -42.7493 48.0572 30 -42.7493 48.0572 -30 -42.7493 48.0572 -33.5051 -42.7493 48.0572 -38.1272 -41.5108 48.0572 -41.5108 -38.1272 48.0572 -42.7493 -33.5051 50 -35.4985 -30 50 -35.4985 30 50 -35.4985 31.5117 50 -34.9644 33.5051 50 -33.5051 34.9644 50 -31.5117 35.4985 50 -30 35.4985 50 30 35.4985 50 31.5117 35.4985 50 33.5051 34.9644 50 34.9644 33.5051 50 35.4985 31.5117 50 35.4985 30 50 35.4985 -30 50 35.4985 -31.5117 50 34.9644 -33.5051 50 33.5051 -34.9644 50 31.5117 -35.4985 50 30 -35.4985 50 -30 -35.4985 50 -31.5117 -35.4985 50 -33.5051 -34.9644 50 -34.9644 -33.5051 50 -35.4985 -31.5117 50 -30 -30 50 -30 30 50 30 30 50 30 -30</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-positions-array" count="248" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-normals" name="normal">
+ <float_array id="RoundedCube-normals-array" count="744">-1 0 0 -1 -0.000000 0 -1 0 0 -1 0.000000 0 -0.987666 -0.156577 0 -0.994537 -0.104384 0 -0.988123 -0.15311 0.013055 -0.98733 -0.137909 0.07849 -0.989489 -0.060168 0.131499 -0.988123 -0.013056 0.153111 -0.987666 0 0.156577 -0.994537 0 0.104385 -0.988123 0.013055 0.15311 -0.98733 0.07849 0.137909 -0.989489 0.131499 0.060167 -0.988123 0.15311 0.013055 -0.987666 0.156577 0 -0.994537 0.104384 0 -0.988123 0.15311 -0.013055 -0.989489 0.131499 -0.060167 -0.98733 0.078491 -0.137909 -0.988123 0.013056 -0.153111 -0.987666 0 -0.156577 -0.994537 0 -0.104385 -0.988123 -0.013055 -0.15311 -0.98733 -0.07849 -0.137909 -0.989489 -0.131499 -0.060167 -0.988123 -0.15311 -0.013055 -0.866026 -0.5 0 -0.907073 -0.420973 0 -0.870789 -0.488743 0.05345 -0.841132 -0.469421 0.268591 -0.883262 -0.215337 0.416507 -0.870789 -0.05345 0.488743 -0.866026 0 0.5 -0.907073 0 0.420974 -0.870789 0.05345 0.488743 -0.841132 0.268591 0.469421 -0.883262 0.416507 0.215337 -0.870789 0.488743 0.05345 -0.866026 0.5 0 -0.907073 0.420973 0 -0.870789 0.488743 -0.05345 -0.86674 0.428194 -0.255759 -0.857096 0.223082 -0.46435 -0.870789 0.05345 -0.488743 -0.866026 0 -0.5 -0.907073 0 -0.420974 -0.870789 -0.05345 -0.488743 -0.841132 -0.268591 -0.469421 -0.883262 -0.416507 -0.215337 -0.870789 -0.488743 -0.05345 -0.5 -0.866025 0 -0.575061 -0.818111 0 -0.509799 -0.85376 0.105826 -0.45181 -0.773163 0.44507 -0.5338 -0.410477 0.739301 -0.509799 -0.105825 0.85376 -0.5 0 0.866025 -0.575061 0 0.818111 -0.509799 0.105825 0.85376 -0.45181 0.44507 0.773163 -0.5338 0.739301 0.410477 -0.509799 0.85376 0.105826 -0.5 0.866025 0 -0.575061 0.818111 0 -0.509799 0.85376 -0.105826 -0.45181 0.773163 -0.44507 -0.5338 0.410477 -0.739301 -0.509799 0.105825 -0.85376 -0.5 0 -0.866025 -0.575061 0 -0.818111 -0.509799 -0.105825 -0.85376 -0.45181 -0.44507 -0.773163 -0.5338 -0.739301 -0.410477 -0.509799 -0.85376 -0.105826 -0.130526 -0.991445 0 -0.149146 -0.988815 0 -0.134586 -0.975822 0.172215 -0.114286 -0.832191 0.542584 -0.144186 -0.493073 0.857956 -0.134713 -0.128482 0.98252 -0.130526 0 0.991445 -0.149146 0 0.988815 -0.134586 0.172215 0.975822 -0.114286 0.542584 0.832191 -0.144186 0.857956 0.493073 -0.134713 0.98252 0.128482 -0.130526 0.991445 0 -0.149146 0.988815 0 -0.134586 0.975822 -0.172215 -0.114286 0.832191 -0.542584 -0.144186 0.493073 -0.857956 -0.134713 0.128482 -0.98252 -0.130526 0 -0.991445 -0.149146 0 -0.988815 -0.134586 -0.172215 -0.975822 -0.114286 -0.542584 -0.832191 -0.144186 -0.857956 -0.493073 -0.134713 -0.98252 -0.128482 0 -1 0 0 -1 0 0 -0.991445 0.130526 0 -0.866025 0.5 0 -0.5 0.866026 0 -0.130526 0.991445 0 0 1 0 0 1 0 0.130526 0.991445 0 0.5 0.866025 0 0.866025 0.5 0 0.991445 0.130526 0 1 0 0 1 0 0 0.991445 -0.130526 0 0.866025 -0.5 0 0.5 -0.866026 0 0.130526 -0.991445 0 0 -1 0 0 -1 0 -0.130526 -0.991445 0 -0.5 -0.866025 0 -0.866025 -0.5 0 -0.991445 -0.130526 0 -1 0 0 -1 0 0 -0.991445 0.130526 0 -0.866025 0.5 0 -0.5 0.866025 0 -0.130526 0.991445 0 0 1 0 0 1 0 0.130526 0.991445 0 0.5 0.866025 0 0.866025 0.5 0 0.991445 0.130526 0 1 0 0 1 0 0 0.991445 -0.130526 0 0.866025 -0.5 0 0.5 -0.866025 0 0.130526 -0.991445 0 0 -1 0 0 -1 0 -0.130526 -0.991445 0 -0.5 -0.866025 0 -0.866025 -0.5 0 -0.991445 -0.130526 0.149146 -0.988815 0 0.130526 -0.991445 0 0.134713 -0.98252 0.128482 0.144186 -0.857956 0.493073 0.114286 -0.542584 0.832191 0.134586 -0.172215 0.975822 0.149146 0 0.988815 0.130526 0 0.991445 0.134713 0.128482 0.98252 0.144186 0.493073 0.857956 0.114286 0.832191 0.542584 0.134586 0.975822 0.172215 0.149146 0.988815 0 0.130526 0.991445 0 0.134713 0.98252 -0.128482 0.144186 0.857956 -0.493073 0.114286 0.542584 -0.832191 0.134586 0.172215 -0.975822 0.149146 0 -0.988815 0.130526 0 -0.991445 0.134713 -0.128482 -0.98252 0.144186 -0.493073 -0.857956 0.114286 -0.832191 -0.542584 0.134586 -0.975822 -0.172215 0.575061 -0.818111 0 0.5 -0.866026 0 0.509799 -0.85376 0.105826 0.5338 -0.739301 0.410477 0.45181 -0.44507 0.773163 0.509799 -0.105825 0.85376 0.575061 0 0.818111 0.5 0 0.866025 0.509799 0.105825 0.85376 0.5338 0.410477 0.739301 0.45181 0.773163 0.445069 0.509799 0.85376 0.105826 0.575061 0.818111 0 0.5 0.866026 0 0.509799 0.85376 -0.105826 0.5338 0.739301 -0.410477 0.45181 0.44507 -0.773163 0.509799 0.105825 -0.85376 0.575061 0 -0.818111 0.5 0 -0.866025 0.509799 -0.105825 -0.85376 0.5338 -0.410477 -0.739301 0.45181 -0.773163 -0.445069 0.509799 -0.85376 -0.105826 0.907073 -0.420973 0 0.866026 -0.5 0 0.870789 -0.488743 0.05345 0.857096 -0.46435 0.223082 0.86674 -0.255759 0.428194 0.870789 -0.05345 0.488743 0.907073 0 0.420974 0.866026 0 0.5 0.870789 0.05345 0.488743 0.883262 0.215337 0.416507 0.841132 0.469421 0.268591 0.870789 0.488743 0.05345 0.907073 0.420973 0 0.866026 0.5 0 0.870789 0.488743 -0.05345 0.883262 0.416507 -0.215337 0.841132 0.268591 -0.469421 0.870789 0.05345 -0.488743 0.907073 0 -0.420974 0.866026 0 -0.5 0.870789 -0.05345 -0.488743 0.883262 -0.215337 -0.416507 0.841132 -0.469421 -0.268591 0.870789 -0.488743 -0.05345 0.994537 -0.104384 0 0.987666 -0.156577 0 0.988123 -0.15311 0.013055 0.98733 -0.137909 0.07849 0.989489 -0.060168 0.131499 0.988123 -0.013056 0.15311 0.994537 0 0.104385 0.987666 0 0.156577 0.988123 0.013055 0.153111 0.989489 0.060168 0.131499 0.98733 0.137909 0.07849 0.988123 0.15311 0.013055 0.994537 0.104384 0 0.987666 0.156577 0 0.988123 0.15311 -0.013055 0.989489 0.131499 -0.060167 0.98733 0.078491 -0.137909 0.988123 0.013056 -0.15311 0.994537 0 -0.104385 0.987666 0 -0.156577 0.988123 -0.013055 -0.153111 0.989489 -0.060168 -0.131499 0.98733 -0.137909 -0.07849 0.988123 -0.15311 -0.013055 1 0 0 1 -0.000000 0 1 0 0 1 0.000000 0</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-normals-array" count="248" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-Texture" name="Texture">
+ <float_array id="RoundedCube-Texture-array" count="620">0.812128 0.130663 0.827856 0.130663 0.812128 0.187872 0.848596 0.136221 0.863779 0.151404 0.869337 0.172144 0.869337 0.187872 0.869337 0.812128 0.869337 0.827856 0.812128 0.812128 0.863779 0.848596 0.848596 0.863779 0.827856 0.869337 0.812128 0.869337 0.187872 0.869337 0.172144 0.869337 0.187872 0.812128 0.151404 0.863779 0.136221 0.848596 0.130663 0.827856 0.130663 0.812128 0.130663 0.187872 0.130663 0.172144 0.187872 0.187872 0.136221 0.151404 0.151404 0.136221 0.172144 0.130663 0.187872 0.130663 0.187872 0.055224 0.812128 0.055224 0.896686 0.06811 0.848596 0.055224 0.93189 0.103314 0.944775 0.151404 0.944775 0.187872 0.944775 0.812128 0.93189 0.896686 0.944775 0.848596 0.896686 0.93189 0.848596 0.944775 0.812128 0.944775 0.187872 0.944775 0.103314 0.93189 0.151404 0.944775 0.06811 0.896686 0.055224 0.848596 0.055224 0.812128 0.055224 0.187872 0.06811 0.103314 0.055224 0.151404 0.103314 0.06811 0.151404 0.055224 0 0.187872 0 0.812128 0 0.187872 0.93189 0.01825 0.863779 0 0.863779 0 0.98175 0.06811 1 0.136221 0 0.187872 0 0.812128 0 0.187872 0.98175 0.93189 1 0.863779 1 0.863779 0.93189 0.98175 0.863779 1 1 0.812128 1 0.187872 1 0.812128 0.06811 0.98175 0.136221 1 0.136221 1 0.01825 0.93189 0 0.863779 1 0.812128 1 0.187872 1 0.812128 0.01825 0.06811 0 0.136221 0 0.136221 0.06811 0.01825 0.136221 0 0.130663 0.944775 0.055224 0.93189 0.130663 0.869337 0.055224 0.863779 0.055224 0.93189 0.130663 0.055224 0.130663 0.130663 0.055224 0.06811 0.055224 0.136221 0.055224 0.06811 0.055224 0.93189 0.055224 0.93189 0.869337 0.944775 0.869337 0.869337 0.944775 0.93189 0.944775 0.863779 0.944775 0.93189 0.869337 0.055224 0.944775 0.06811 0.869337 0.130663 0.944775 0.136221 0.944775 0.06811 0.944775 0.93189 0.944775 0.863779 0.944775 0.93189 0.944775 0.06811 0.944775 0.06811 0.130663 0.055224 0.055224 0.06811 0.055224 0.136221 0.055224 0.06811 0.130663 0.055224 0.130663 0.055224 0.812128 0.944775 0.869337 0.944775 0.869337 0.944775 0.187872 0.055224 0.130663 0.055224 0.130663 0.055224 0.187872 0.944775 0.812128 0.944775 0.812128 0.944775 0.812128 0.055224 0.187872 0.055224 0.187872 0.055224 0.130663 0.944775 0.187872 0.944775 0.187872 0.944775 0.869337 0.055224 0.812128 0.055224 0.812128 0.055224 0.944775 0.06811 0.944775 0.06811 0.130663 0.944775 0.055224 0.93189 0.055224 0.93189 0.869337 0.055224 0.944775 0.06811 0.944775 0.06811 0.06811 0.01825 0.136221 0 0.151404 0.055224 0.136221 0 0.01825 0.06811 0.06811 0.103314 0 0.136221 0 0.136221 0.01825 0.93189 0 0.863779 0.06811 0.896686 0.055224 0.848596 0 0.863779 0.06811 0.98175 0.136221 1 0.136221 1 0.93189 0.98175 0.863779 1 0.848596 0.944775 0.863779 1 0.98175 0.93189 1 0.863779 1 0.863779 0.98175 0.06811 1 0.136221 0.944775 0.151404 1 0.136221 0.93189 0.01825 0.863779 0 0.863779 0 0.812128 0.055224 0.187872 0.055224 0.812128 0.055224 0.151404 0.055224 0.151404 0.055224 0.055224 0.187872 0.055224 0.812128 0.055224 0.187872 0.055224 0.848596 0.055224 0.848596 0.187872 0.944775 0.812128 0.944775 0.187872 0.944775 0.848596 0.944775 0.848596 0.944775 0.944775 0.812128 0.944775 0.187872 0.944775 0.812128 0.944775 0.151404 0.944775 0.151404 0 0.848596 0 0.812128 0 0.848596 0.055224 0.136221 0 0.151404 0 0.187872 0 0.151404 0 0.848596 0 0.812128 0 0.848596 0.944775 0.863779 1 0.848596 1 0.812128 1 0.848596 1 0.151404 1 0.187872 1 0.151404 0.944775 0.863779 1 0.848596 1 0.812128 1 0.848596 1 0.151404 1 0.187872 1 0.151404 0.055224 0.136221 0 0.151404 0 0.187872 0 0.151404 0.130663 1 0.055224 0.93189 0.055224 0.98175 0.055224 0.93189 0.055224 0.136221 0.055224 0.136221 0.055224 0.93189 0.055224 0.98175 0.055224 0.93189 0.944775 0.863779 0.944775 0.863779 0.869337 1 0.944775 0.98175 0.944775 0.93189 0.944775 0.98175 0.944775 0.863779 0.944775 0.863779 0.869337 0 0.944775 0.06811 0.944775 0.01825 0.944775 0.06811 0.055224 0.136221 0.055224 0.136221 0.187872 0 0.130663 0 0.130663 0.055224 0.130663 0 0.187872 1 0.812128 1 0.869337 1 0.869337 1 0.812128 0 0.812128 0 0.187872 0 0.187872 0 0.187872 1 0.812128 1 0.812128 1 0.869337 0 0.812128 0 0.812128 0 0.130663 1 0.187872 1 0.187872 1 0.869337 1 0.130663 1 0.055224 0.98175 0.130663 1 0.055224 0.01825 0.01825 0.06811 0.06811 0.01825 0.06811 0.01825 1 0.151404 1 0.151404 0.06811 0.98175 0.01825 0.93189 0.01825 0.93189 0 0.848596 0 0.848596 0.98175 0.93189 0.93189 0.98175 0.93189 0.98175 0 0.848596 0 0.848596 0.93189 0.01825 0.98175 0.06811 0.98175 0.06811 1 0.151404 1 0.151404 0.151404 0.055224 0.187872 0.055224 0.187872 0.055224 0.055224 0.187872 0.055224 0.187872 0.055224 0.848596 0.055224 0.812128 0.055224 0.812128 0.187872 0.944775 0.187872 0.944775 0.848596 0.944775 0.812128 0.944775 0.812128 0.944775 0.944775 0.812128 0.944775 0.812128 0.944775 0.151404 0.944775 0.187872 0.944775 0.187872 0.812128 0.055224 0.812128 0.055224</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-Texture-array" count="310" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="RoundedCube-vertices">
+ <input semantic="POSITION" source="#RoundedCube-positions"/>
+ <input semantic="NORMAL" source="#RoundedCube-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="492">
+ <input semantic="VERTEX" source="#RoundedCube-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#RoundedCube-Texture" offset="1" set="1"/>
+ <p>5 0 6 1 1 2 6 1 7 3 1 2 7 3 8 4 1 2 8 4 9 5 1 2 9 5 10 6 1 2 11 7 12 8 2 9 12 8 13 10 2 9 13 10 14 11 2 9 14 11 15 12 2 9 15 12 16 13 2 9 17 14 18 15 3 16 18 15 19 17 3 16 19 17 20 18 3 16 20 18 21 19 3 16 21 19 22 20 3 16 23 21 24 22 0 23 24 22 25 24 0 23 25 24 26 25 0 23 26 25 27 26 0 23 27 26 4 27 0 23 245 23 222 26 221 27 245 23 223 25 222 26 245 23 224 24 223 25 245 23 225 22 224 24 245 23 226 21 225 22 246 16 228 19 227 20 246 16 229 18 228 19 246 16 230 17 229 18 246 16 231 15 230 17 246 16 232 14 231 15 247 9 234 12 233 13 247 9 235 11 234 12 247 9 236 10 235 11 247 9 237 8 236 10 247 9 238 7 237 8 244 2 240 5 239 6 244 2 241 4 240 5 244 2 242 3 241 4 244 2 243 1 242 3 244 2 220 0 243 1 4 27 5 0 0 23 1 2 0 23 5 0 10 6 11 7 1 2 2 9 1 2 11 7 16 13 17 14 2 9 3 16 2 9 17 14 22 20 23 21 3 16 0 23 3 16 23 21 28 28 29 29 4 27 5 0 4 27 29 29 31 30 7 3 30 31 6 1 30 31 7 3 32 32 33 33 8 4 9 5 8 4 33 33 34 34 35 35 10 6 11 7 10 6 35 35 37 36 13 10 36 37 12 8 36 37 13 10 38 38 39 39 14 11 15 12 14 11 39 39 40 40 41 41 16 13 17 14 16 13 41 41 43 42 19 17 42 43 18 15 42 43 19 17 44 44 45 45 20 18 21 19 20 18 45 45 46 46 47 47 22 20 23 21 22 20 47 47 49 48 25 24 48 49 24 22 48 49 25 24 50 50 51 51 26 25 27 26 26 25 51 51 52 47 53 46 28 52 29 53 28 54 53 46 55 55 31 30 54 56 30 31 54 57 31 30 56 58 57 59 32 32 33 33 32 32 57 59 58 47 59 46 34 60 35 61 34 62 59 46 61 63 37 36 60 64 36 37 60 65 37 36 62 66 63 67 38 38 39 39 38 38 63 67 64 35 65 34 40 68 41 69 40 70 65 34 67 71 43 42 66 72 42 43 66 73 43 42 68 74 69 75 44 44 45 45 44 44 69 75 70 35 71 34 46 76 47 77 46 78 71 34 73 79 49 48 72 80 48 49 72 81 49 48 74 82 75 83 50 50 51 51 50 50 75 83 76 21 77 20 52 47 53 46 52 47 77 20 79 84 55 85 78 86 54 87 78 86 55 88 80 89 81 90 56 91 57 92 56 93 81 90 82 21 83 20 58 47 59 46 58 47 83 20 85 84 61 94 84 86 60 87 84 86 61 95 86 96 87 97 62 98 63 99 62 100 87 97 88 7 89 6 64 35 65 34 64 35 89 6 91 101 67 102 90 103 66 104 90 103 67 105 92 96 93 97 68 106 69 107 68 108 93 97 94 7 95 6 70 35 71 34 70 35 95 6 97 101 73 109 96 103 72 104 96 103 73 110 98 111 99 90 74 112 75 113 74 114 99 90 100 23 101 16 76 21 77 20 76 21 101 16 102 14 103 41 78 86 79 84 78 86 103 41 104 28 105 27 80 115 81 90 80 116 105 27 106 23 107 16 82 21 83 20 82 21 107 16 108 14 109 41 84 86 85 84 84 86 109 41 110 117 111 13 86 118 87 97 86 119 111 13 112 9 113 2 88 7 89 6 88 7 113 2 114 0 115 29 90 103 91 101 90 103 115 29 116 40 117 13 92 96 93 97 92 96 117 13 118 9 119 2 94 7 95 6 94 7 119 2 120 0 121 29 96 103 97 101 96 103 121 29 122 120 123 27 98 121 99 90 98 122 123 27 124 2 125 9 100 23 101 16 100 23 125 9 126 13 127 40 102 14 103 41 102 14 127 40 128 29 129 0 104 28 105 27 104 28 129 0 130 2 131 9 106 23 107 16 106 23 131 9 132 13 133 40 108 14 109 41 108 14 133 40 134 123 135 14 110 124 111 13 110 125 135 14 136 16 137 23 112 9 113 2 112 9 137 23 138 27 139 28 114 0 115 29 114 0 139 28 140 41 141 14 116 40 117 13 116 40 141 14 142 16 143 23 118 9 119 2 118 9 143 23 144 27 145 28 120 0 121 29 120 0 145 28 146 126 147 0 122 127 123 27 122 128 147 0 148 6 149 7 124 2 125 9 124 2 149 7 150 97 151 96 126 13 127 40 126 13 151 96 152 101 153 103 128 29 129 0 128 29 153 103 154 6 155 7 130 2 131 9 130 2 155 7 156 97 157 96 132 13 133 40 132 13 157 96 158 129 159 86 134 130 135 14 134 131 159 86 160 20 161 21 136 16 137 23 136 16 161 21 162 90 163 89 138 27 139 28 138 27 163 89 164 84 165 86 140 41 141 14 140 41 165 86 166 20 167 21 142 16 143 23 142 16 167 21 168 90 169 89 144 27 145 28 144 27 169 89 170 132 171 103 146 133 147 0 146 134 171 103 172 34 173 35 148 6 149 7 148 6 173 35 151 96 150 97 175 98 174 99 175 98 150 97 152 101 176 135 153 103 177 104 153 103 176 136 178 34 179 35 154 6 155 7 154 6 179 35 157 96 156 97 181 98 180 99 181 98 156 97 158 137 182 138 159 86 183 87 159 86 182 139 184 46 185 47 160 20 161 21 160 20 185 47 163 89 162 90 187 91 186 92 187 91 162 90 164 84 188 85 165 86 189 87 165 86 188 85 190 46 191 47 166 20 167 21 166 20 191 47 169 89 168 90 193 91 192 92 193 91 168 90 170 140 194 141 171 103 195 104 171 103 194 142 196 69 197 68 172 34 173 35 172 34 197 68 175 143 174 144 199 50 198 145 199 50 174 146 176 147 200 148 177 149 201 49 177 150 200 148 202 69 203 68 178 34 179 35 178 34 203 68 181 151 180 152 205 153 204 154 205 153 180 155 182 156 206 42 183 157 207 43 183 158 206 42 208 53 209 52 184 46 185 47 184 46 209 52 187 159 186 160 211 38 210 161 211 38 186 162 188 163 212 36 189 164 213 37 189 165 212 36 214 53 215 52 190 46 191 47 190 46 215 52 193 166 192 167 217 32 216 168 217 32 192 169 194 170 218 30 195 171 219 31 195 172 218 30 220 0 221 27 196 173 197 174 196 175 221 27 199 50 198 176 223 25 222 26 223 25 198 177 200 148 224 24 201 49 225 22 201 49 224 24 226 21 227 20 202 178 203 179 202 180 227 20 205 153 204 181 229 18 228 19 229 18 204 182 206 42 230 17 207 43 231 15 207 43 230 17 232 14 233 13 208 183 209 184 208 185 233 13 211 38 210 186 235 11 234 12 235 11 210 187 212 36 236 10 213 37 237 8 213 37 236 10 238 7 239 6 214 188 215 189 214 190 239 6 217 32 216 191 241 4 240 5 241 4 216 192 218 30 242 3 219 31 243 1 219 31 242 3 244 2 245 23 220 0 221 27 220 0 245 23 245 23 246 16 226 21 227 20 226 21 246 16 246 16 247 9 232 14 233 13 232 14 247 9 247 9 244 2 238 7 239 6 238 7 244 2 244 2 247 9 245 23 246 16 245 23 247 9 0 23 1 2 3 16 2 9 3 16 1 2 30 31 6 1 29 29 5 0 29 29 6 1 31 30 32 32 7 3 8 4 7 3 32 32 33 33 34 34 9 5 10 6 9 5 34 34 36 37 12 8 35 35 11 7 35 35 12 8 37 36 38 38 13 10 14 11 13 10 38 38 39 39 40 40 15 12 16 13 15 12 40 40 42 43 18 15 41 41 17 14 41 41 18 15 44 44 20 18 43 42 19 17 43 42 20 18 45 45 46 46 21 19 22 20 21 19 46 46 48 49 24 22 47 47 23 21 47 47 24 22 49 48 50 50 25 24 26 25 25 24 50 50 51 51 28 28 27 26 4 27 27 26 28 28 54 87 30 193 53 46 29 194 53 46 30 195 55 55 56 58 31 30 32 32 31 30 56 58 57 196 58 47 33 197 34 198 33 199 58 47 60 87 36 200 59 46 35 201 59 46 36 202 61 63 62 66 37 36 38 38 37 36 62 66 63 203 64 35 39 204 40 205 39 206 64 35 66 104 42 207 65 34 41 208 65 34 42 209 67 71 68 74 43 42 44 44 43 42 68 74 69 210 70 35 45 211 46 212 45 213 70 35 72 104 48 214 71 34 47 215 71 34 48 216 73 79 74 82 49 48 50 50 49 48 74 82 75 217 52 47 51 218 28 219 51 220 52 47 78 86 54 87 77 20 53 46 77 20 54 87 79 84 80 221 55 222 56 223 55 224 80 221 81 90 82 21 57 225 58 47 57 226 82 21 84 86 60 87 83 20 59 46 83 20 60 87 85 84 86 221 61 227 62 228 61 229 86 221 87 97 88 7 63 230 64 35 63 231 88 7 90 103 66 104 89 6 65 34 89 6 66 104 91 232 92 96 67 233 68 234 67 235 92 96 93 97 94 7 69 236 70 35 69 237 94 7 96 103 72 104 95 6 71 34 95 6 72 104 97 101 98 238 73 239 74 240 73 241 98 238 99 90 76 21 75 242 52 47 75 243 76 21 101 16 102 14 77 20 78 86 77 20 102 14 103 244 104 28 79 245 80 246 79 247 104 28 105 27 106 23 81 90 82 21 81 90 106 23 107 16 108 14 83 20 84 86 83 20 108 14 109 41 110 248 85 84 86 221 85 84 110 248 111 13 112 9 87 97 88 7 87 97 112 9 113 2 114 0 89 6 90 103 89 6 114 0 115 249 116 40 91 250 92 96 91 251 116 40 117 13 118 9 93 97 94 7 93 97 118 9 119 2 120 0 95 6 96 103 95 6 120 0 121 29 122 252 97 101 98 238 97 101 122 252 123 27 100 23 99 90 76 21 99 90 100 23 125 9 126 13 101 16 102 14 101 16 126 13 127 253 128 29 103 254 104 28 103 255 128 29 129 0 130 2 105 27 106 23 105 27 130 2 131 9 132 13 107 16 108 14 107 16 132 13 133 40 134 249 109 41 110 248 109 41 134 249 135 14 136 16 111 13 112 9 111 13 136 16 137 23 138 27 113 2 114 0 113 2 138 27 139 256 140 41 115 257 116 40 115 258 140 41 141 14 142 16 117 13 118 9 117 13 142 16 143 23 144 27 119 2 120 0 119 2 144 27 145 28 146 244 121 29 122 252 121 29 146 244 147 0 124 2 123 27 100 23 123 27 124 2 149 7 150 97 125 9 126 13 125 9 150 97 151 259 152 101 127 260 128 29 127 261 152 101 153 103 154 6 129 0 130 2 129 0 154 6 155 7 156 97 131 9 132 13 131 9 156 97 157 96 158 232 133 40 134 249 133 40 158 232 159 86 160 20 135 14 136 16 135 14 160 20 161 21 162 90 137 23 138 27 137 23 162 90 163 262 164 84 139 263 140 41 139 264 164 84 165 86 166 20 141 14 142 16 141 14 166 20 167 21 168 90 143 23 144 27 143 23 168 90 169 89 170 245 145 28 146 244 145 28 170 245 171 103 148 6 147 0 124 2 147 0 148 6 150 97 149 7 174 99 173 35 174 99 149 7 152 265 151 96 176 233 175 98 176 233 151 96 153 103 177 104 154 6 178 34 154 6 177 104 156 97 155 7 180 99 179 35 180 99 155 7 158 232 157 96 182 233 181 98 182 233 157 96 159 86 183 87 160 20 184 46 160 20 183 87 162 90 161 21 186 92 185 47 186 92 161 21 164 84 163 266 188 85 187 267 188 85 163 268 165 86 189 87 166 20 190 46 166 20 189 87 168 90 167 21 192 92 191 47 192 92 167 21 170 245 169 89 194 269 193 91 194 269 169 89 171 103 195 104 148 6 172 34 148 6 195 104 174 99 173 35 198 204 197 68 198 204 173 35 176 270 175 271 200 148 199 50 200 148 175 272 177 104 201 273 178 34 202 69 178 34 201 274 180 99 179 35 204 204 203 68 204 204 179 35 182 275 181 276 206 42 205 153 206 42 181 277 183 87 207 278 184 46 208 53 184 46 207 279 186 92 185 47 210 197 209 52 210 197 185 47 188 280 187 281 212 36 211 38 212 36 187 282 189 87 213 283 190 46 214 53 190 46 213 284 192 92 191 47 216 197 215 52 216 197 191 47 194 285 193 286 218 30 217 32 218 30 193 287 195 104 219 288 172 34 196 69 172 34 219 289 198 290 197 291 222 26 221 27 222 26 197 292 199 50 223 25 200 148 224 24 200 148 223 25 201 49 225 22 202 293 226 21 202 294 225 22 204 295 203 296 228 19 227 20 228 19 203 297 206 42 205 153 230 17 229 18 230 17 205 153 207 43 231 15 208 298 232 14 208 299 231 15 210 300 209 301 234 12 233 13 234 12 209 302 212 36 211 38 236 10 235 11 236 10 211 38 213 37 237 8 214 303 238 7 214 304 237 8 216 305 215 306 240 5 239 6 240 5 215 307 218 30 217 32 242 3 241 4 242 3 217 32 219 31 243 1 196 308 220 0 196 309 243 1</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="RoundedCube-2">
+ <node id="_RoundedCube" name="RoundedCube" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#RoundedCube">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-3.dae b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-3.dae
new file mode 100644
index 00000000..88b6e86a
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-3.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/cubes/RoundedCube-3.mb</source_data>
+ </contributor>
+ <created>2008-09-19T18:05:45Z</created>
+ <modified>2008-09-19T18:05:45Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="RoundedCube" name="RoundedCube">
+ <mesh>
+ <source id="RoundedCube-positions" name="position">
+ <float_array id="RoundedCube-positions-array" count="1032">-50 -20 -20 -50 -20 20 -50 20 20 -50 20 -20 -50 -26.7673 -20 -50 -26.7673 20 -50 -26.7673 21.5265 -50 -26.3683 23.5321 -50 -25.2323 25.2323 -50 -23.5321 26.3683 -50 -21.5265 26.7673 -50 -20 26.7673 -50 20 26.7673 -50 21.5265 26.7673 -50 23.5321 26.3683 -50 25.2323 25.2323 -50 26.3683 23.5321 -50 26.7673 21.5265 -50 26.7673 20 -50 26.7673 -20 -50 26.7673 -21.5265 -50 26.3683 -23.5321 -50 25.2323 -25.2323 -50 23.5321 -26.3683 -50 21.5265 -26.7673 -50 20 -26.7673 -50 -20 -26.7673 -50 -21.5265 -26.7673 -50 -23.5321 -26.3683 -50 -25.2323 -25.2323 -50 -26.3683 -23.5321 -50 -26.7673 -21.5265 -48.2315 -35.6581 -20 -48.2315 -35.6581 20 -48.2315 -35.6581 23.5321 -48.2315 -34.735 28.1725 -48.2315 -32.1064 32.1064 -48.2315 -28.1725 34.735 -48.2315 -23.5321 35.6581 -48.2315 -20 35.6581 -48.2315 20 35.6581 -48.2315 23.5321 35.6581 -48.2315 28.1725 34.735 -48.2315 32.1064 32.1064 -48.2315 34.735 28.1725 -48.2315 35.6581 23.5321 -48.2315 35.6581 20 -48.2315 35.6581 -20 -48.2315 35.6581 -23.5321 -48.2315 34.735 -28.1725 -48.2315 32.1064 -32.1064 -48.2315 28.1725 -34.735 -48.2315 23.5321 -35.6581 -48.2315 20 -35.6581 -48.2315 -20 -35.6581 -48.2315 -23.5321 -35.6581 -48.2315 -28.1725 -34.735 -48.2315 -32.1064 -32.1064 -48.2315 -34.735 -28.1725 -48.2315 -35.6581 -23.5321 -43.1953 -43.1953 -20 -43.1953 -43.1953 20 -43.1953 -43.1953 25.2323 -43.1953 -41.8279 32.1064 -43.1953 -37.9341 37.9341 -43.1953 -32.1064 41.8279 -43.1953 -25.2323 43.1953 -43.1953 -20 43.1953 -43.1953 20 43.1953 -43.1953 25.2323 43.1953 -43.1953 32.1064 41.8279 -43.1953 37.9341 37.9341 -43.1953 41.8279 32.1064 -43.1953 43.1953 25.2323 -43.1953 43.1953 20 -43.1953 43.1953 -20 -43.1953 43.1953 -25.2323 -43.1953 41.8279 -32.1064 -43.1953 37.9341 -37.9341 -43.1953 32.1064 -41.8279 -43.1953 25.2323 -43.1953 -43.1953 20 -43.1953 -43.1953 -20 -43.1953 -43.1953 -25.2323 -43.1953 -43.1953 -32.1064 -41.8279 -43.1953 -37.9341 -37.9341 -43.1953 -41.8279 -32.1064 -43.1953 -43.1953 -25.2323 -35.6581 -48.2315 -20 -35.6581 -48.2315 20 -35.6581 -48.2315 26.3683 -35.6581 -46.5673 34.735 -35.6581 -41.8279 41.8279 -35.6581 -34.735 46.5673 -35.6581 -26.3683 48.2315 -35.6581 -20 48.2315 -35.6581 20 48.2315 -35.6581 26.3683 48.2315 -35.6581 34.735 46.5673 -35.6581 41.8279 41.8279 -35.6581 46.5673 34.735 -35.6581 48.2315 26.3683 -35.6581 48.2315 20 -35.6581 48.2315 -20 -35.6581 48.2315 -26.3683 -35.6581 46.5673 -34.735 -35.6581 41.8279 -41.8279 -35.6581 34.735 -46.5673 -35.6581 26.3683 -48.2315 -35.6581 20 -48.2315 -35.6581 -20 -48.2315 -35.6581 -26.3683 -48.2315 -35.6581 -34.735 -46.5673 -35.6581 -41.8279 -41.8279 -35.6581 -46.5673 -34.735 -35.6581 -48.2315 -26.3683 -26.7673 -50 -20 -26.7673 -50 20 -26.7673 -50 26.7673 -26.7673 -48.2315 35.6581 -26.7673 -43.1953 43.1953 -26.7673 -35.6581 48.2315 -26.7673 -26.7673 50 -26.7673 -20 50 -26.7673 20 50 -26.7673 26.7673 50 -26.7673 35.6581 48.2315 -26.7673 43.1953 43.1953 -26.7673 48.2315 35.6581 -26.7673 50 26.7673 -26.7673 50 20 -26.7673 50 -20 -26.7673 50 -26.7673 -26.7673 48.2315 -35.6581 -26.7673 43.1953 -43.1953 -26.7673 35.6581 -48.2315 -26.7673 26.7673 -50 -26.7673 20 -50 -26.7673 -20 -50 -26.7673 -26.7673 -50 -26.7673 -35.6581 -48.2315 -26.7673 -43.1953 -43.1953 -26.7673 -48.2315 -35.6581 -26.7673 -50 -26.7673 -20 -50 -20 -20 -50 20 -20 -50 26.7673 -20 -48.2315 35.6581 -20 -43.1953 43.1953 -20 -35.6581 48.2315 -20 -26.7673 50 -20 -20 50 -20 20 50 -20 26.7673 50 -20 35.6581 48.2315 -20 43.1953 43.1953 -20 48.2315 35.6581 -20 50 26.7673 -20 50 20 -20 50 -20 -20 50 -26.7673 -20 48.2315 -35.6581 -20 43.1953 -43.1953 -20 35.6581 -48.2315 -20 26.7673 -50 -20 20 -50 -20 -20 -50 -20 -26.7673 -50 -20 -35.6581 -48.2315 -20 -43.1953 -43.1953 -20 -48.2315 -35.6581 -20 -50 -26.7673 20 -50 -20 20 -50 20 20 -50 26.7673 20 -48.2315 35.6581 20 -43.1953 43.1953 20 -35.6581 48.2315 20 -26.7673 50 20 -20 50 20 20 50 20 26.7673 50 20 35.6581 48.2315 20 43.1953 43.1953 20 48.2315 35.6581 20 50 26.7673 20 50 20 20 50 -20 20 50 -26.7673 20 48.2315 -35.6581 20 43.1953 -43.1953 20 35.6581 -48.2315 20 26.7673 -50 20 20 -50 20 -20 -50 20 -26.7673 -50 20 -35.6581 -48.2315 20 -43.1953 -43.1953 20 -48.2315 -35.6581 20 -50 -26.7673 26.7673 -50 -20 26.7673 -50 20 26.7673 -50 26.7673 26.7673 -48.2315 35.6581 26.7673 -43.1953 43.1953 26.7673 -35.6581 48.2315 26.7673 -26.7673 50 26.7673 -20 50 26.7673 20 50 26.7673 26.7673 50 26.7673 35.6581 48.2315 26.7673 43.1953 43.1953 26.7673 48.2315 35.6581 26.7673 50 26.7673 26.7673 50 20 26.7673 50 -20 26.7673 50 -26.7673 26.7673 48.2315 -35.6581 26.7673 43.1953 -43.1953 26.7673 35.6581 -48.2315 26.7673 26.7673 -50 26.7673 20 -50 26.7673 -20 -50 26.7673 -26.7673 -50 26.7673 -35.6581 -48.2315 26.7673 -43.1953 -43.1953 26.7673 -48.2315 -35.6581 26.7673 -50 -26.7673 35.6581 -48.2315 -20 35.6581 -48.2315 20 35.6581 -48.2315 26.3683 35.6581 -46.5673 34.735 35.6581 -41.8279 41.8279 35.6581 -34.735 46.5673 35.6581 -26.3683 48.2315 35.6581 -20 48.2315 35.6581 20 48.2315 35.6581 26.3683 48.2315 35.6581 34.735 46.5673 35.6581 41.8279 41.8279 35.6581 46.5673 34.735 35.6581 48.2315 26.3683 35.6581 48.2315 20 35.6581 48.2315 -20 35.6581 48.2315 -26.3683 35.6581 46.5673 -34.735 35.6581 41.8279 -41.8279 35.6581 34.735 -46.5673 35.6581 26.3683 -48.2315 35.6581 20 -48.2315 35.6581 -20 -48.2315 35.6581 -26.3683 -48.2315 35.6581 -34.735 -46.5673 35.6581 -41.8279 -41.8279 35.6581 -46.5673 -34.735 35.6581 -48.2315 -26.3683 43.1953 -43.1953 -20 43.1953 -43.1953 20 43.1953 -43.1953 25.2323 43.1953 -41.8279 32.1064 43.1953 -37.9341 37.9341 43.1953 -32.1064 41.8279 43.1953 -25.2323 43.1953 43.1953 -20 43.1953 43.1953 20 43.1953 43.1953 25.2323 43.1953 43.1953 32.1064 41.8279 43.1953 37.9341 37.9341 43.1953 41.8279 32.1064 43.1953 43.1953 25.2323 43.1953 43.1953 20 43.1953 43.1953 -20 43.1953 43.1953 -25.2323 43.1953 41.8279 -32.1064 43.1953 37.9341 -37.9341 43.1953 32.1064 -41.8279 43.1953 25.2323 -43.1953 43.1953 20 -43.1953 43.1953 -20 -43.1953 43.1953 -25.2323 -43.1953 43.1953 -32.1064 -41.8279 43.1953 -37.9341 -37.9341 43.1953 -41.8279 -32.1064 43.1953 -43.1953 -25.2323 48.2315 -35.6581 -20 48.2315 -35.6581 20 48.2315 -35.6581 23.5321 48.2315 -34.735 28.1725 48.2315 -32.1064 32.1064 48.2315 -28.1725 34.735 48.2315 -23.5321 35.6581 48.2315 -20 35.6581 48.2315 20 35.6581 48.2315 23.5321 35.6581 48.2315 28.1725 34.735 48.2315 32.1064 32.1064 48.2315 34.735 28.1725 48.2315 35.6581 23.5321 48.2315 35.6581 20 48.2315 35.6581 -20 48.2315 35.6581 -23.5321 48.2315 34.735 -28.1725 48.2315 32.1064 -32.1064 48.2315 28.1725 -34.735 48.2315 23.5321 -35.6581 48.2315 20 -35.6581 48.2315 -20 -35.6581 48.2315 -23.5321 -35.6581 48.2315 -28.1725 -34.735 48.2315 -32.1064 -32.1064 48.2315 -34.735 -28.1725 48.2315 -35.6581 -23.5321 50 -26.7673 -20 50 -26.7673 20 50 -26.7673 21.5265 50 -26.3683 23.5321 50 -25.2323 25.2323 50 -23.5321 26.3683 50 -21.5265 26.7673 50 -20 26.7673 50 20 26.7673 50 21.5265 26.7673 50 23.5321 26.3683 50 25.2323 25.2323 50 26.3683 23.5321 50 26.7673 21.5265 50 26.7673 20 50 26.7673 -20 50 26.7673 -21.5265 50 26.3683 -23.5321 50 25.2323 -25.2323 50 23.5321 -26.3683 50 21.5265 -26.7673 50 20 -26.7673 50 -20 -26.7673 50 -21.5265 -26.7673 50 -23.5321 -26.3683 50 -25.2323 -25.2323 50 -26.3683 -23.5321 50 -26.7673 -21.5265 50 -20 -20 50 -20 20 50 20 20 50 20 -20</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-positions-array" count="344" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-normals" name="normal">
+ <float_array id="RoundedCube-normals-array" count="1032">-1 0 0 -1 0 0 -1 0 0 -1 0 0 -0.993061 -0.117598 0 -0.996922 -0.078398 0 -0.993227 -0.115947 0.007469 -0.993787 -0.105555 0.035291 -0.992807 -0.084657 0.084657 -0.993787 -0.035291 0.105555 -0.993227 -0.007469 0.115947 -0.993061 0 0.117598 -0.996922 0 0.078398 -0.993227 0.007469 0.115947 -0.993787 0.035292 0.105554 -0.992807 0.084657 0.084657 -0.993787 0.105555 0.035291 -0.993227 0.115947 0.007469 -0.993061 0.117598 0 -0.996922 0.078398 0 -0.993227 0.115947 -0.007469 -0.993787 0.105554 -0.035291 -0.992807 0.084657 -0.084657 -0.993787 0.035291 -0.105554 -0.993227 0.007469 -0.115947 -0.993061 0 -0.117598 -0.996922 0 -0.078398 -0.993227 -0.007469 -0.115947 -0.993787 -0.035292 -0.105555 -0.992807 -0.084657 -0.084657 -0.993787 -0.105554 -0.035291 -0.993227 -0.115947 -0.007469 -0.92388 -0.382683 0 -0.947173 -0.320722 0 -0.925806 -0.376745 0.030759 -0.922055 -0.356058 0.15178 -0.920436 -0.261123 0.290881 -0.931551 -0.127114 0.340669 -0.925806 -0.030759 0.376745 -0.92388 0 0.382683 -0.947173 0 0.320722 -0.925806 0.030759 0.376745 -0.922055 0.15178 0.356058 -0.920436 0.290881 0.261123 -0.931551 0.340669 0.127114 -0.925806 0.376745 0.030759 -0.92388 0.382683 0 -0.947173 0.320722 0 -0.925806 0.376745 -0.030759 -0.922055 0.356058 -0.15178 -0.920436 0.261123 -0.290881 -0.931551 0.127114 -0.340669 -0.925806 0.030759 -0.376745 -0.92388 0 -0.382683 -0.947173 0 -0.320722 -0.925806 -0.030759 -0.376745 -0.922055 -0.15178 -0.356058 -0.920436 -0.290881 -0.261123 -0.931551 -0.340669 -0.127114 -0.925806 -0.376745 -0.030759 -0.707107 -0.707107 0 -0.752339 -0.658776 0 -0.712775 -0.698491 0.063742 -0.682181 -0.676059 0.278518 -0.73611 -0.471849 0.485284 -0.728929 -0.251867 0.636573 -0.712774 -0.063742 0.698491 -0.707107 0 0.707107 -0.752339 0 0.658776 -0.712775 0.063742 0.698491 -0.682181 0.278518 0.676059 -0.73611 0.485284 0.471849 -0.728929 0.636573 0.251867 -0.712774 0.698491 0.063742 -0.707107 0.707107 0 -0.752339 0.658776 0 -0.712775 0.698491 -0.063742 -0.682181 0.676059 -0.278518 -0.73611 0.471848 -0.485284 -0.728929 0.251867 -0.636573 -0.712775 0.063742 -0.698491 -0.707107 0 -0.707107 -0.752339 0 -0.658776 -0.712774 -0.063742 -0.698491 -0.682181 -0.278518 -0.676059 -0.73611 -0.485284 -0.471849 -0.728929 -0.636573 -0.251867 -0.712775 -0.698491 -0.063742 -0.382683 -0.92388 0 -0.442968 -0.896538 0 -0.388497 -0.917276 0.087603 -0.339221 -0.869305 0.359496 -0.410659 -0.640778 0.648662 -0.404562 -0.344312 0.847218 -0.388497 -0.087603 0.917276 -0.382683 0 0.92388 -0.442968 0 0.896538 -0.388497 0.087603 0.917276 -0.339221 0.359496 0.869305 -0.410659 0.648662 0.640778 -0.404562 0.847218 0.344312 -0.388497 0.917276 0.087603 -0.382683 0.92388 0 -0.442968 0.896538 0 -0.388497 0.917276 -0.087603 -0.339221 0.869305 -0.359496 -0.410659 0.640778 -0.648662 -0.404562 0.344312 -0.847218 -0.388497 0.087603 -0.917276 -0.382683 0 -0.92388 -0.442968 0 -0.896538 -0.388497 -0.087603 -0.917276 -0.339221 -0.359496 -0.869305 -0.410659 -0.648662 -0.640778 -0.404562 -0.847218 -0.344312 -0.388497 -0.917276 -0.087603 -0.098017 -0.995185 0 -0.112009 -0.993707 0 -0.100013 -0.986464 0.129944 -0.083619 -0.904647 0.417876 -0.106923 -0.702534 0.703572 -0.105389 -0.379818 0.919039 -0.100066 -0.097179 0.990224 -0.098017 0 0.995185 -0.112009 0 0.993707 -0.100013 0.129944 0.986464 -0.083619 0.417877 0.904647 -0.106923 0.703572 0.702534 -0.105389 0.919039 0.379817 -0.100066 0.990224 0.097179 -0.098017 0.995185 0 -0.112009 0.993707 0 -0.100013 0.986464 -0.129944 -0.083619 0.904647 -0.417876 -0.106923 0.702534 -0.703572 -0.105389 0.379818 -0.919039 -0.100066 0.097179 -0.990224 -0.098017 0 -0.995185 -0.112009 0 -0.993707 -0.100013 -0.129944 -0.986464 -0.083619 -0.417877 -0.904647 -0.106923 -0.703572 -0.702534 -0.105389 -0.919039 -0.379817 -0.100066 -0.990224 -0.097179 0 -1 0 0 -1 0 0 -0.995185 0.098017 0 -0.92388 0.382683 0 -0.707107 0.707107 0 -0.382683 0.92388 0 -0.098017 0.995185 0 0 1 0 0 1 0 0.098017 0.995185 0 0.382683 0.92388 0 0.707107 0.707107 0 0.92388 0.382683 0 0.995185 0.098017 0 1 0 0 1 0 0 0.995185 -0.098017 0 0.92388 -0.382683 0 0.707107 -0.707107 0 0.382683 -0.92388 0 0.098017 -0.995185 0 0 -1 0 0 -1 0 -0.098017 -0.995185 0 -0.382683 -0.92388 0 -0.707107 -0.707107 0 -0.92388 -0.382683 0 -0.995185 -0.098017 0 -1 0 0 -1 0 0 -0.995185 0.098017 0 -0.92388 0.382683 0 -0.707107 0.707107 0 -0.382683 0.92388 0 -0.098017 0.995185 0 0 1 0 0 1 0 0.098017 0.995185 0 0.382683 0.92388 0 0.707107 0.707107 0 0.92388 0.382683 0 0.995185 0.098017 0 1 0 0 1 0 0 0.995185 -0.098017 0 0.92388 -0.382683 0 0.707107 -0.707107 0 0.382683 -0.92388 0 0.098017 -0.995185 0 0 -1 0 0 -1 0 -0.098017 -0.995185 0 -0.382683 -0.92388 0 -0.707107 -0.707107 0 -0.92388 -0.382683 0 -0.995185 -0.098017 0.112009 -0.993707 0 0.098017 -0.995185 0 0.100066 -0.990224 0.097178 0.105389 -0.919039 0.379817 0.106923 -0.703572 0.702534 0.083619 -0.417877 0.904647 0.100013 -0.129944 0.986464 0.112009 0 0.993707 0.098017 0 0.995185 0.100066 0.097179 0.990224 0.105389 0.379818 0.919039 0.106923 0.702534 0.703572 0.083619 0.904647 0.417876 0.100013 0.986464 0.129944 0.112009 0.993707 0 0.098017 0.995185 0 0.100066 0.990224 -0.097178 0.105389 0.919039 -0.379817 0.106923 0.703572 -0.702534 0.083619 0.417877 -0.904647 0.100013 0.129944 -0.986464 0.112009 0 -0.993707 0.098017 0 -0.995185 0.100066 -0.097179 -0.990224 0.105389 -0.379818 -0.919039 0.106923 -0.702534 -0.703572 0.083619 -0.904647 -0.417876 0.100013 -0.986464 -0.129944 0.442968 -0.896538 0 0.382683 -0.92388 0 0.388497 -0.917276 0.087603 0.404562 -0.847218 0.344312 0.410659 -0.648662 0.640778 0.339221 -0.359496 0.869305 0.388497 -0.087603 0.917276 0.442968 0 0.896538 0.382683 0 0.92388 0.388497 0.087603 0.917276 0.404562 0.344312 0.847218 0.410659 0.640778 0.648662 0.339221 0.869305 0.359496 0.388497 0.917276 0.087603 0.442968 0.896538 0 0.382683 0.92388 0 0.388497 0.917276 -0.087603 0.404562 0.847218 -0.344312 0.410659 0.648662 -0.640778 0.339221 0.359496 -0.869305 0.388497 0.087603 -0.917276 0.442968 0 -0.896538 0.382683 0 -0.92388 0.388497 -0.087603 -0.917276 0.404562 -0.344312 -0.847218 0.410659 -0.640778 -0.648662 0.339221 -0.869305 -0.359496 0.388497 -0.917276 -0.087603 0.752339 -0.658776 0 0.707107 -0.707107 0 0.712774 -0.698491 0.063742 0.728929 -0.636573 0.251867 0.73611 -0.485284 0.471849 0.682181 -0.278518 0.676059 0.712774 -0.063742 0.698491 0.752339 0 0.658776 0.707107 0 0.707107 0.712775 0.063742 0.698491 0.728929 0.251867 0.636573 0.73611 0.471849 0.485284 0.682181 0.676059 0.278518 0.712775 0.698491 0.063742 0.752339 0.658776 0 0.707107 0.707107 0 0.712774 0.698491 -0.063742 0.728929 0.636573 -0.251867 0.73611 0.485284 -0.471849 0.682181 0.278518 -0.676059 0.712775 0.063742 -0.698491 0.752339 0 -0.658776 0.707107 0 -0.707107 0.712775 -0.063742 -0.698491 0.728929 -0.251867 -0.636573 0.73611 -0.471849 -0.485284 0.682181 -0.676059 -0.278518 0.712775 -0.698491 -0.063742 0.947173 -0.320722 0 0.92388 -0.382683 0 0.925806 -0.376745 0.030759 0.931551 -0.340669 0.127114 0.920436 -0.290881 0.261123 0.922055 -0.15178 0.356058 0.925806 -0.030759 0.376745 0.947173 0 0.320722 0.92388 0 0.382683 0.925806 0.030759 0.376745 0.931551 0.127114 0.340669 0.920436 0.261123 0.290881 0.922055 0.356058 0.15178 0.925806 0.376745 0.030759 0.947173 0.320722 0 0.92388 0.382683 0 0.925806 0.376745 -0.030759 0.931551 0.340669 -0.127114 0.920436 0.290881 -0.261123 0.922055 0.15178 -0.356058 0.925806 0.030759 -0.376745 0.947173 0 -0.320722 0.92388 0 -0.382683 0.925806 -0.030759 -0.376745 0.931551 -0.127114 -0.340669 0.920436 -0.261123 -0.290881 0.922055 -0.356058 -0.15178 0.925806 -0.376745 -0.030759 0.996922 -0.078398 0 0.993061 -0.117598 0 0.993227 -0.115947 0.007469 0.993787 -0.105555 0.035291 0.992807 -0.084657 0.084657 0.993787 -0.035292 0.105555 0.993227 -0.007469 0.115947 0.996922 0 0.078398 0.993061 0 0.117598 0.993227 0.007469 0.115947 0.993787 0.035291 0.105554 0.992807 0.084657 0.084657 0.993787 0.105555 0.035291 0.993227 0.115947 0.007469 0.996922 0.078398 0 0.993061 0.117598 0 0.993227 0.115947 -0.007469 0.993787 0.105554 -0.035291 0.992807 0.084657 -0.084657 0.993787 0.035292 -0.105554 0.993227 0.007469 -0.115947 0.996922 0 -0.078398 0.993061 0 -0.117598 0.993227 -0.007469 -0.115947 0.993787 -0.035291 -0.105555 0.992807 -0.084657 -0.084657 0.993787 -0.105554 -0.035291 0.993227 -0.115947 -0.007469 1 0 0 1 0 0 1 0 0 1 0 0</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-normals-array" count="344" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-Texture" name="Texture">
+ <float_array id="RoundedCube-Texture-array" count="752">0.731507 0.19016 0.749177 0.19016 0.731507 0.268493 0.772392 0.194778 0.792072 0.207928 0.805222 0.227608 0.80984 0.250823 0.80984 0.268493 0.80984 0.731507 0.80984 0.749177 0.731507 0.731507 0.805222 0.772392 0.792072 0.792072 0.772392 0.805222 0.749177 0.80984 0.731507 0.80984 0.268493 0.80984 0.250823 0.80984 0.268493 0.731507 0.227608 0.805222 0.207928 0.792072 0.194778 0.772392 0.19016 0.749177 0.19016 0.731507 0.19016 0.268493 0.19016 0.250823 0.268493 0.268493 0.194778 0.227608 0.207928 0.207928 0.227608 0.194778 0.250823 0.19016 0.268493 0.19016 0.772392 0.087246 0.731507 0.087246 0.871643 0.128357 0.826106 0.09793 0.902069 0.173894 0.912754 0.227608 0.912754 0.268493 0.912754 0.731507 0.902069 0.826106 0.912754 0.772392 0.871643 0.871643 0.826106 0.902069 0.772392 0.912754 0.731507 0.912754 0.227608 0.912754 0.268493 0.912754 0.128357 0.871643 0.173894 0.902069 0.09793 0.826106 0.087246 0.772392 0.087246 0.731507 0.087246 0.268493 0.09793 0.173894 0.087246 0.227608 0.128357 0.128357 0.173894 0.09793 0.227608 0.087246 0.268493 0.087246 0.792072 0 0.731507 0 0.871643 0.015827 0.939099 0.0609 0.984172 0.128357 1 0.207928 1 0.268493 1 0.731507 0.984172 0.871643 1 0.792072 0.939099 0.939099 0.871643 0.984172 0.792072 1 0.731507 1 0.207928 1 0.268493 1 0.128357 0.984172 0.0609 0.939099 0.015827 0.871643 0 0.792072 0 0.731507 0 0.268493 0.015827 0.128357 0 0.207928 0.0609 0.0609 0.128357 0.015827 0.207928 0 0.268493 0 0.087246 0.805222 0 0.792072 0 0.731507 0 0.792072 0.087246 0.902069 0.087246 0.984172 0 0.871643 0 0.939099 0 0.871643 0.087246 0.09793 0.087246 0.194778 0 0.128357 0 0.207928 0 0.128357 0 0.268493 0 0.731507 0 0.268493 0 0.871643 0 0.792072 0 0.871643 0.912754 0.984172 0.912754 0.902069 1 0.939099 1 0.871643 1 0.939099 0.912754 0.805222 0.912754 0.731507 1 0.792072 1 0.731507 1 0.792072 0.912754 0.194778 1 0.207928 0.912754 0.268493 1 0.268493 1 0.207928 0.912754 0.09793 0.912754 0.015827 1 0.128357 1 0.0609 1 0.128357 1 0.871643 1 0.792072 1 0.871643 1 0.731507 1 0.268493 1 0.731507 1 0.128357 1 0.207928 1 0.128357 0.087246 0.015827 0 0.0609 0 0.128357 0 0.0609 0 0.207928 0 0.268493 0 0.207928 0.19016 0.80984 0.19016 0.912754 0.19016 1 0.19016 0.087246 0.19016 0.19016 0.80984 1 0.80984 0.912754 0.912754 0.984172 0.912754 0.984172 0.80984 0.80984 0.80984 0.19016 0.80984 0.087246 0.80984 0 0.19016 0 0.087246 0.015827 0.087246 0.015827 0.731507 1 0.80984 1 0.80984 1 0.268493 0 0.19016 0 0.19016 0 0.268493 1 0.731507 1 0.731507 1 0.731507 0 0.268493 0 0.268493 0 0.19016 1 0.268493 1 0.268493 1 0.80984 0 0.731507 0 0.731507 0 0.912754 0.805222 0.912754 0.984172 0.912754 0.902069 0.912754 0.194778 0.912754 0.09793 0.19016 1 0.087246 0.902069 0.087246 0.984172 0.19016 1 0.087246 0.805222 0.087246 0.731507 0.087246 0.194778 0.087246 0.268493 0.087246 0.015827 0.087246 0.09793 0.80984 0 0.912754 0.015827 0.80984 0 0.087246 0.984172 0 0.939099 0.087246 0.984172 0.912754 0.015827 1 0.0609 0.912754 0.015827 0.207928 0 0.268493 0 0.268493 0 0.0609 0.0609 0.128357 0.015827 0.128357 0.128357 0.173894 0.09793 0.128357 0.015827 0.015827 0.128357 0 0.207928 0.087246 0.227608 0 0.207928 0 0.268493 0 0.731507 0 0.268493 0.015827 0.871643 0 0.792072 0.087246 0.772392 0 0.792072 0.128357 0.984172 0.0609 0.939099 0.173894 0.902069 0.128357 0.871643 0.0609 0.939099 0.207928 1 0.268493 1 0.268493 1 0.792072 1 0.731507 1 0.731507 1 0.939099 0.939099 0.871643 0.984172 0.826106 0.902069 0.871643 0.984172 0.984172 0.871643 1 0.792072 0.912754 0.772392 1 0.792072 1 0.731507 1 0.268493 1 0.731507 0.984172 0.128357 1 0.207928 0.912754 0.227608 1 0.207928 0.871643 0.015827 0.939099 0.0609 0.826106 0.09793 0.939099 0.0609 0.792072 0 0.731507 0 0.731507 0 0 0.268493 0 0.731507 0 0.268493 0 0.871643 0 0.792072 0 0.871643 0.087246 0.015827 0 0.0609 0 0.128357 0 0.0609 0 0.207928 0 0.268493 0 0.207928 0 0.792072 0 0.731507 0 0.792072 0 0.871643 0 0.939099 0 0.871643 1 0.871643 1 0.792072 1 0.871643 1 0.731507 1 0.268493 1 0.731507 1 0.128357 1 0.207928 1 0.128357 0.912754 0.984172 1 0.939099 1 0.871643 1 0.939099 1 0.792072 1 0.731507 1 0.792072 1 0.207928 1 0.268493 1 0.207928 1 0.128357 1 0.0609 1 0.128357 0 0.128357 0 0.207928 0 0.128357 0.19016 0 0.087246 0.015827 0.087246 0.015827 0.80984 1 0.912754 0.984172 0.912754 0.984172 0.268493 0 0.19016 0 0.19016 0 0.731507 1 0.80984 1 0.80984 1 0.731507 0 0.268493 0 0.268493 0 0.268493 1 0.731507 1 0.731507 1 0.80984 0 0.731507 0 0.731507 0 0.19016 1 0.268493 1 0.268493 1 0.80984 0 0.912754 0.015827 0.80984 0 0.19016 1 0.087246 0.984172 0.19016 1 0.912754 0.015827 1 0.0609 0.912754 0.015827 0.087246 0.984172 0 0.939099 0.087246 0.984172 0.731507 0 0.268493 0 0.731507 0 0.128357 0.015827 0.207928 0 0.207928 0 0.015827 0.128357 0.0609 0.0609 0.0609 0.0609 0 0.207928 0 0.268493 0 0.268493 0 0.792072 0 0.731507 0 0.731507 0.0609 0.939099 0.015827 0.871643 0.015827 0.871643 0.128357 0.984172 0.207928 1 0.207928 1 0.268493 1 0.731507 1 0.268493 1 0.871643 0.984172 0.792072 1 0.792072 1 0.984172 0.871643 0.939099 0.939099 0.939099 0.939099 1 0.792072 1 0.731507 1 0.731507 1 0.207928 1 0.268493 1 0.268493 0.939099 0.0609 0.984172 0.128357 0.984172 0.128357 0.871643 0.015827 0.792072 0 0.792072 0</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-Texture-array" count="376" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="RoundedCube-vertices">
+ <input semantic="POSITION" source="#RoundedCube-positions"/>
+ <input semantic="NORMAL" source="#RoundedCube-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="684">
+ <input semantic="VERTEX" source="#RoundedCube-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#RoundedCube-Texture" offset="1" set="1"/>
+ <p>5 0 6 1 1 2 6 1 7 3 1 2 7 3 8 4 1 2 8 4 9 5 1 2 9 5 10 6 1 2 10 6 11 7 1 2 12 8 13 9 2 10 13 9 14 11 2 10 14 11 15 12 2 10 15 12 16 13 2 10 16 13 17 14 2 10 17 14 18 15 2 10 19 16 20 17 3 18 20 17 21 19 3 18 21 19 22 20 3 18 22 20 23 21 3 18 23 21 24 22 3 18 24 22 25 23 3 18 26 24 27 25 0 26 27 25 28 27 0 26 28 27 29 28 0 26 29 28 30 29 0 26 30 29 31 30 0 26 31 30 4 31 0 26 341 26 314 30 313 31 341 26 315 29 314 30 341 26 316 28 315 29 341 26 317 27 316 28 341 26 318 25 317 27 341 26 319 24 318 25 342 18 321 22 320 23 342 18 322 21 321 22 342 18 323 20 322 21 342 18 324 19 323 20 342 18 325 17 324 19 342 18 326 16 325 17 343 10 328 14 327 15 343 10 329 13 328 14 343 10 330 12 329 13 343 10 331 11 330 12 343 10 332 9 331 11 343 10 333 8 332 9 340 2 335 6 334 7 340 2 336 5 335 6 340 2 337 4 336 5 340 2 338 3 337 4 340 2 339 1 338 3 340 2 312 0 339 1 0 26 1 2 3 18 2 10 3 18 1 2 11 7 12 8 1 2 2 10 1 2 12 8 25 23 26 24 3 18 0 26 3 18 26 24 34 32 6 1 33 33 5 0 33 33 6 1 36 34 8 4 35 35 7 3 35 35 8 4 37 36 38 37 9 5 10 6 9 5 38 37 39 38 40 39 11 7 12 8 11 7 40 39 42 40 14 11 41 41 13 9 41 41 14 11 43 42 44 43 15 12 16 13 15 12 44 43 45 44 46 45 17 14 18 15 17 14 46 45 48 46 20 17 47 47 19 16 47 47 20 17 50 48 22 20 49 49 21 19 49 49 22 20 51 50 52 51 23 21 24 22 23 21 52 51 53 52 54 53 25 23 26 24 25 23 54 53 56 54 28 27 55 55 27 25 55 55 28 27 57 56 58 57 29 28 30 29 29 28 58 57 59 58 32 59 31 30 4 31 31 30 32 59 62 60 34 32 61 61 33 33 61 61 34 32 63 62 64 63 35 35 36 34 35 35 64 63 65 64 66 65 37 36 38 37 37 36 66 65 67 66 68 67 39 38 40 39 39 38 68 67 70 68 42 40 69 69 41 41 69 69 42 40 71 70 72 71 43 42 44 43 43 42 72 71 73 72 74 73 45 44 46 45 45 44 74 73 76 74 48 46 75 75 47 47 75 75 48 46 77 76 78 77 49 49 50 48 49 49 78 77 79 78 80 79 51 50 52 51 51 50 80 79 81 80 82 81 53 52 54 53 53 52 82 81 84 82 56 54 83 83 55 55 83 83 56 54 85 84 86 85 57 56 58 57 57 56 86 85 87 86 60 87 59 58 32 59 59 58 60 87 90 88 62 89 89 52 61 90 89 52 62 91 91 92 92 93 63 94 64 95 63 96 92 93 93 97 94 98 65 99 66 100 65 101 94 98 95 53 96 52 67 102 68 103 67 104 96 52 98 92 70 105 97 88 69 106 97 88 70 107 99 108 100 109 71 110 72 111 71 112 100 109 101 113 102 114 73 115 74 116 73 117 102 114 104 118 76 119 103 120 75 121 103 120 76 122 105 123 106 124 77 125 78 126 77 127 106 124 107 109 108 113 79 128 80 129 79 130 108 113 109 114 110 120 81 131 82 132 81 133 110 120 112 123 84 134 111 118 83 135 111 118 84 136 113 137 114 97 85 138 86 139 85 140 114 97 115 98 88 53 87 141 60 142 87 143 88 53 118 144 90 88 117 23 89 52 117 23 90 88 119 145 120 146 91 92 92 93 91 92 120 146 121 147 122 148 93 97 94 98 93 97 122 148 123 24 124 23 95 53 96 52 95 53 124 23 126 145 98 92 125 144 97 88 125 144 98 92 127 149 128 150 99 151 100 109 99 152 128 150 129 153 130 8 101 113 102 114 101 113 130 8 132 154 104 118 131 7 103 120 131 7 104 118 133 155 134 156 105 123 106 124 105 123 134 156 135 150 136 153 107 109 108 113 107 109 136 153 137 8 138 7 109 114 110 120 109 114 138 7 140 155 112 123 139 154 111 118 139 154 112 123 141 157 142 147 113 158 114 97 113 159 142 147 143 148 116 24 115 98 88 53 115 98 116 24 145 18 146 16 117 23 118 144 117 23 146 16 147 47 148 75 119 145 120 146 119 145 148 75 149 59 150 31 121 147 122 148 121 147 150 31 151 26 152 18 123 24 124 23 123 24 152 18 153 16 154 47 125 144 126 145 125 144 154 47 155 160 156 45 127 161 128 150 127 162 156 45 157 15 158 10 129 153 130 8 129 153 158 10 159 2 160 0 131 7 132 154 131 7 160 0 161 33 162 61 133 155 134 156 133 155 162 61 163 45 164 15 135 150 136 153 135 150 164 15 165 10 166 2 137 8 138 7 137 8 166 2 167 0 168 33 139 154 140 155 139 154 168 33 169 163 170 59 141 164 142 147 141 165 170 59 171 31 144 26 143 148 116 24 143 148 144 26 173 10 174 15 145 18 146 16 145 18 174 15 175 45 176 73 147 47 148 75 147 47 176 73 177 33 178 0 149 59 150 31 149 59 178 0 179 2 180 10 151 26 152 18 151 26 180 10 181 15 182 45 153 16 154 47 153 16 182 45 183 166 184 47 155 167 156 45 155 168 184 47 185 16 186 18 157 15 158 10 157 15 186 18 187 26 188 31 159 2 160 0 159 2 188 31 189 59 190 87 161 33 162 61 161 33 190 87 191 47 192 16 163 45 164 15 163 45 192 16 193 18 194 26 165 10 166 2 165 10 194 26 195 31 196 59 167 0 168 33 167 0 196 59 197 169 198 33 169 170 170 59 169 171 198 33 199 0 172 2 171 31 144 26 171 31 172 2 201 8 202 153 173 10 174 15 173 10 202 153 203 150 204 149 175 45 176 73 175 45 204 149 205 155 206 154 177 33 178 0 177 33 206 154 207 7 208 8 179 2 180 10 179 2 208 8 209 153 210 150 181 15 182 45 181 15 210 150 211 172 212 145 183 173 184 47 183 174 212 145 213 144 214 23 185 16 186 18 185 16 214 23 215 24 216 148 187 26 188 31 187 26 216 148 217 147 218 157 189 59 190 87 189 59 218 157 219 145 220 144 191 47 192 16 191 47 220 144 221 23 222 24 193 18 194 26 193 18 222 24 223 148 224 147 195 31 196 59 195 31 224 147 225 175 226 155 197 176 198 33 197 177 226 155 227 154 200 7 199 0 172 2 199 0 200 7 202 153 201 8 230 178 229 39 230 178 201 8 204 149 203 150 232 179 231 180 232 179 203 150 234 181 206 154 233 182 205 155 233 182 206 154 235 38 236 39 207 7 208 8 207 7 236 39 237 178 238 180 209 153 210 150 209 153 238 180 212 145 211 183 240 184 239 185 240 184 211 186 213 144 241 187 214 23 242 188 214 23 241 187 216 148 215 24 244 189 243 190 244 189 215 24 218 157 217 147 246 191 245 192 246 191 217 147 248 187 220 144 247 184 219 145 247 184 220 144 249 188 250 190 221 23 222 24 221 23 250 190 251 189 252 192 223 148 224 147 223 148 252 192 226 155 225 193 254 182 253 194 254 182 225 195 227 154 255 181 200 7 228 38 200 7 255 181 230 178 229 39 258 69 257 67 258 69 229 39 232 179 231 180 260 110 259 111 260 110 231 180 233 182 261 125 234 181 262 65 234 181 261 125 263 66 264 67 235 38 236 39 235 38 264 67 238 180 237 178 266 111 265 69 266 111 237 178 240 184 239 196 268 94 267 197 268 94 239 198 241 187 269 79 242 188 270 80 242 188 269 79 244 189 243 190 272 83 271 81 272 83 243 190 246 191 245 192 274 138 273 99 274 138 245 192 247 184 275 94 248 187 276 79 248 187 275 94 277 80 278 81 249 188 250 190 249 188 278 81 252 192 251 189 280 99 279 83 280 99 251 189 254 182 253 199 282 125 281 200 282 125 253 201 255 181 283 65 228 38 256 66 228 38 283 65 258 202 257 203 286 58 285 59 286 58 257 204 260 205 259 206 288 207 287 208 288 207 259 209 261 210 289 54 262 211 290 212 262 213 289 54 291 190 292 188 263 214 264 215 263 216 292 188 266 217 265 218 294 50 293 219 294 50 265 220 268 221 267 222 296 223 295 224 296 223 267 225 269 226 297 46 270 227 298 47 270 228 297 46 272 229 271 230 300 44 299 45 300 44 271 231 274 232 273 233 302 42 301 234 302 42 273 235 275 236 303 40 276 237 304 238 276 239 303 40 305 114 306 120 277 240 278 241 277 242 306 120 280 243 279 244 308 36 307 245 308 36 279 246 282 247 281 248 310 249 309 34 310 249 281 250 283 251 311 32 256 252 284 33 256 253 311 32 286 58 285 59 314 30 313 31 314 30 285 59 288 207 287 208 316 28 315 29 316 28 287 208 289 54 317 27 290 212 318 25 290 212 317 27 319 24 320 23 291 190 292 188 291 190 320 23 294 50 293 219 322 21 321 22 322 21 293 219 295 224 323 20 296 223 324 19 296 223 323 20 297 46 325 17 298 47 326 16 298 47 325 17 300 44 299 45 328 14 327 15 328 14 299 45 302 42 301 234 330 12 329 13 330 12 301 234 303 40 331 11 304 238 332 9 304 238 331 11 333 8 334 7 305 114 306 120 305 114 334 7 308 36 307 245 336 5 335 6 336 5 307 245 309 34 337 4 310 249 338 3 310 249 337 4 311 32 339 1 284 33 312 0 284 33 339 1 341 26 342 18 319 24 320 23 319 24 342 18 343 10 340 2 333 8 334 7 333 8 340 2 4 31 5 0 0 26 1 2 0 26 5 0 18 15 19 16 2 10 3 18 2 10 19 16 32 59 33 33 4 31 5 0 4 31 33 33 35 35 7 3 34 32 6 1 34 32 7 3 36 34 37 36 8 4 9 5 8 4 37 36 38 37 39 38 10 6 11 7 10 6 39 38 41 41 13 9 40 39 12 8 40 39 13 9 43 42 15 12 42 40 14 11 42 40 15 12 44 43 45 44 16 13 17 14 16 13 45 44 46 45 47 47 18 15 19 16 18 15 47 47 49 49 21 19 48 46 20 17 48 46 21 19 50 48 51 50 22 20 23 21 22 20 51 50 52 51 53 52 24 22 25 23 24 22 53 52 55 55 27 25 54 53 26 24 54 53 27 25 57 56 29 28 56 54 28 27 56 54 29 28 58 57 59 58 30 29 31 30 30 29 59 58 60 87 61 61 32 59 33 33 32 59 61 61 63 62 35 35 62 60 34 32 62 60 35 35 64 63 65 64 36 34 37 36 36 34 65 64 66 65 67 66 38 37 39 38 38 37 67 66 69 69 41 41 68 67 40 39 68 67 41 41 70 68 71 70 42 40 43 42 42 40 71 70 72 71 73 72 44 43 45 44 44 43 73 72 74 73 75 75 46 45 47 47 46 45 75 75 77 76 49 49 76 74 48 46 76 74 49 49 78 77 79 78 50 48 51 50 50 48 79 78 80 79 81 80 52 51 53 52 52 51 81 80 83 83 55 55 82 81 54 53 82 81 55 55 84 82 85 84 56 54 57 56 56 54 85 84 86 85 87 86 58 57 59 58 58 57 87 86 88 53 89 52 60 254 61 255 60 256 89 52 91 92 63 257 90 88 62 258 90 88 63 259 92 260 93 97 64 261 65 262 64 263 93 97 94 98 95 53 66 264 67 265 66 266 95 53 97 88 69 267 96 52 68 268 96 52 69 269 98 92 99 93 70 270 71 271 70 272 99 93 100 109 101 113 72 273 73 274 72 275 101 113 102 114 103 120 74 276 75 277 74 278 103 120 105 123 77 279 104 118 76 280 104 118 77 281 106 282 107 109 78 283 79 284 78 285 107 109 108 113 109 114 80 286 81 287 80 288 109 114 111 118 83 289 110 120 82 290 110 120 83 291 112 123 113 124 84 292 85 293 84 294 113 124 114 97 115 98 86 295 87 296 86 297 115 98 116 24 117 23 88 53 89 52 88 53 117 23 119 145 91 92 118 144 90 88 118 144 91 92 120 298 121 147 92 299 93 97 92 300 121 147 122 148 123 24 94 98 95 53 94 98 123 24 125 144 97 88 124 23 96 52 124 23 97 88 126 145 127 146 98 92 99 93 98 92 127 146 128 150 129 153 100 109 101 113 100 109 129 153 130 8 131 7 102 114 103 120 102 114 131 7 133 155 105 123 132 154 104 118 132 154 105 123 134 301 135 150 106 302 107 109 106 303 135 150 136 153 137 8 108 113 109 114 108 113 137 8 139 154 111 118 138 7 110 120 138 7 111 118 140 155 141 156 112 123 113 124 112 123 141 156 142 147 143 148 114 97 115 98 114 97 143 148 144 26 145 18 116 24 117 23 116 24 145 18 146 16 147 47 118 144 119 145 118 144 147 47 148 304 149 59 120 305 121 147 120 306 149 59 150 31 151 26 122 148 123 24 122 148 151 26 152 18 153 16 124 23 125 144 124 23 153 16 154 47 155 75 126 145 127 146 126 145 155 75 156 45 157 15 128 150 129 153 128 150 157 15 158 10 159 2 130 8 131 7 130 8 159 2 160 0 161 33 132 154 133 155 132 154 161 33 162 307 163 45 134 308 135 150 134 309 163 45 164 15 165 10 136 153 137 8 136 153 165 10 166 2 167 0 138 7 139 154 138 7 167 0 168 33 169 61 140 155 141 156 140 155 169 61 170 59 171 31 142 147 143 148 142 147 171 31 172 2 173 10 144 26 145 18 144 26 173 10 174 15 175 45 146 16 147 47 146 16 175 45 176 310 177 33 148 311 149 59 148 312 177 33 178 0 179 2 150 31 151 26 150 31 179 2 180 10 181 15 152 18 153 16 152 18 181 15 182 45 183 73 154 47 155 75 154 47 183 73 184 47 185 16 156 45 157 15 156 45 185 16 186 18 187 26 158 10 159 2 158 10 187 26 188 31 189 59 160 0 161 33 160 0 189 59 190 313 191 47 162 314 163 45 162 315 191 47 192 16 193 18 164 15 165 10 164 15 193 18 194 26 195 31 166 2 167 0 166 2 195 31 196 59 197 87 168 33 169 61 168 33 197 87 198 33 199 0 170 59 171 31 170 59 199 0 200 7 201 8 172 2 173 10 172 2 201 8 202 153 203 150 174 15 175 45 174 15 203 150 204 316 205 155 176 317 177 33 176 318 205 155 206 154 207 7 178 0 179 2 178 0 207 7 208 8 209 153 180 10 181 15 180 10 209 153 210 150 211 149 182 45 183 73 182 45 211 149 212 145 213 144 184 47 185 16 184 47 213 144 214 23 215 24 186 18 187 26 186 18 215 24 216 148 217 147 188 31 189 59 188 31 217 147 218 319 219 145 190 320 191 47 190 321 219 145 220 144 221 23 192 16 193 18 192 16 221 23 222 24 223 148 194 26 195 31 194 26 223 148 224 147 225 157 196 59 197 87 196 59 225 157 226 155 227 154 198 33 199 0 198 33 227 154 228 38 229 39 200 7 201 8 200 7 229 39 230 178 231 180 202 153 203 150 202 153 231 180 205 155 204 322 233 182 232 323 233 182 204 324 206 154 234 181 207 7 235 38 207 7 234 181 209 153 208 8 237 178 236 39 237 178 208 8 211 149 210 150 239 179 238 180 239 179 210 150 241 187 213 144 240 184 212 145 240 184 213 144 242 188 243 190 214 23 215 24 214 23 243 190 244 189 245 192 216 148 217 147 216 148 245 192 219 145 218 325 247 184 246 326 247 184 218 327 220 144 248 187 221 23 249 188 221 23 248 187 223 148 222 24 251 189 250 190 251 189 222 24 225 157 224 147 253 191 252 192 253 191 224 147 255 181 227 154 254 182 226 155 254 182 227 154 256 66 257 67 228 38 229 39 228 38 257 67 231 180 230 178 259 111 258 69 259 111 230 178 233 182 232 328 261 125 260 329 261 125 232 330 234 181 262 65 235 38 263 66 235 38 262 65 237 178 236 39 265 69 264 67 265 69 236 39 239 179 238 180 267 110 266 111 267 110 238 180 240 184 268 94 241 187 269 79 241 187 268 94 270 80 271 81 242 188 243 190 242 188 271 81 245 192 244 189 273 99 272 83 273 99 244 189 247 184 246 331 275 94 274 332 275 94 246 333 248 187 276 79 249 188 277 80 249 188 276 79 251 189 250 190 279 83 278 81 279 83 250 190 253 191 252 192 281 138 280 99 281 138 252 192 254 182 282 125 255 181 283 65 255 181 282 125 284 33 285 59 256 334 257 335 256 336 285 59 259 337 258 338 287 208 286 58 287 208 258 339 261 340 260 341 289 54 288 207 289 54 260 342 262 343 290 212 263 344 291 190 263 345 290 212 265 346 264 347 293 219 292 188 293 219 264 348 267 349 266 350 295 224 294 50 295 224 266 351 268 352 296 223 269 353 297 46 269 354 296 223 298 47 299 45 270 355 271 356 270 357 299 45 273 358 272 359 301 234 300 44 301 234 272 360 275 361 274 362 303 40 302 42 303 40 274 363 276 364 304 238 277 365 305 114 277 366 304 238 279 367 278 368 307 245 306 120 307 245 278 369 281 370 280 371 309 34 308 36 309 34 280 372 282 373 310 249 283 374 311 32 283 375 310 249 312 0 313 31 284 33 285 59 284 33 313 31 287 208 286 58 315 29 314 30 315 29 286 58 288 207 316 28 289 54 317 27 289 54 316 28 290 212 318 25 291 190 319 24 291 190 318 25 293 219 292 188 321 22 320 23 321 22 292 188 295 224 294 50 323 20 322 21 323 20 294 50 296 223 324 19 297 46 325 17 297 46 324 19 326 16 327 15 298 47 299 45 298 47 327 15 301 234 300 44 329 13 328 14 329 13 300 44 302 42 330 12 303 40 331 11 303 40 330 12 304 238 332 9 305 114 333 8 305 114 332 9 307 245 306 120 335 6 334 7 335 6 306 120 309 34 308 36 337 4 336 5 337 4 308 36 310 249 338 3 311 32 339 1 311 32 338 3 340 2 341 26 312 0 313 31 312 0 341 26 342 18 343 10 326 16 327 15 326 16 343 10 340 2 343 10 341 26 342 18 341 26 343 10</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="RoundedCube-3">
+ <node id="_RoundedCube" name="RoundedCube" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#RoundedCube">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-4.dae b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-4.dae
new file mode 100644
index 00000000..3fa9d975
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-4.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T18:06:38Z</created>
+ <modified>2008-09-19T18:06:38Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="RoundedCube" name="RoundedCube">
+ <mesh>
+ <source id="RoundedCube-positions" name="position">
+ <float_array id="RoundedCube-positions-array" count="1032">-50 -10 -10 -50 -10 10 -50 10 10 -50 10 -10 -50 -19.023 -10 -50 -19.023 10 -50 -19.023 12.0354 -50 -18.4911 14.7094 -50 -16.9764 16.9764 -50 -14.7094 18.4911 -50 -12.0354 19.023 -50 -10 19.023 -50 10 19.023 -50 12.0354 19.023 -50 14.7094 18.4911 -50 16.9764 16.9764 -50 18.4911 14.7094 -50 19.023 12.0354 -50 19.023 10 -50 19.023 -10 -50 19.023 -12.0354 -50 18.4911 -14.7094 -50 16.9764 -16.9764 -50 14.7094 -18.4911 -50 12.0354 -19.023 -50 10 -19.023 -50 -10 -19.023 -50 -12.0354 -19.023 -50 -14.7094 -18.4911 -50 -16.9764 -16.9764 -50 -18.4911 -14.7094 -50 -19.023 -12.0354 -47.642 -30.8774 -10 -47.642 -30.8774 10 -47.642 -30.8774 14.7094 -47.642 -29.6467 20.8966 -47.642 -26.1419 26.1419 -47.642 -20.8967 29.6467 -47.642 -14.7094 30.8774 -47.642 -10 30.8774 -47.642 10 30.8774 -47.642 14.7094 30.8774 -47.642 20.8966 29.6467 -47.642 26.1419 26.1419 -47.642 29.6467 20.8966 -47.642 30.8774 14.7094 -47.642 30.8774 10 -47.642 30.8774 -10 -47.642 30.8774 -14.7094 -47.642 29.6467 -20.8967 -47.642 26.1419 -26.1419 -47.642 20.8966 -29.6467 -47.642 14.7094 -30.8774 -47.642 10 -30.8774 -47.642 -10 -30.8774 -47.642 -14.7094 -30.8774 -47.642 -20.8967 -29.6467 -47.642 -26.1419 -26.1419 -47.642 -29.6467 -20.8967 -47.642 -30.8774 -14.7094 -40.9271 -40.9271 -10 -40.9271 -40.9271 10 -40.9271 -40.9271 16.9764 -40.9271 -39.1039 26.1419 -40.9271 -33.9121 33.9121 -40.9271 -26.1419 39.1039 -40.9271 -16.9764 40.9271 -40.9271 -10 40.9271 -40.9271 10 40.9271 -40.9271 16.9764 40.9271 -40.9271 26.1419 39.1039 -40.9271 33.9121 33.9121 -40.9271 39.1039 26.1419 -40.9271 40.9271 16.9764 -40.9271 40.9271 10 -40.9271 40.9271 -10 -40.9271 40.9271 -16.9764 -40.9271 39.1039 -26.1419 -40.9271 33.9121 -33.9121 -40.9271 26.1419 -39.1039 -40.9271 16.9764 -40.9271 -40.9271 10 -40.9271 -40.9271 -10 -40.9271 -40.9271 -16.9764 -40.9271 -40.9271 -26.1419 -39.1039 -40.9271 -33.9121 -33.9121 -40.9271 -39.1039 -26.1419 -40.9271 -40.9271 -16.9764 -30.8774 -47.642 -10 -30.8774 -47.642 10 -30.8774 -47.642 18.4911 -30.8774 -45.423 29.6467 -30.8774 -39.1039 39.1039 -30.8774 -29.6467 45.423 -30.8774 -18.4911 47.642 -30.8774 -10 47.642 -30.8774 10 47.642 -30.8774 18.4911 47.642 -30.8774 29.6467 45.423 -30.8774 39.1039 39.1039 -30.8774 45.423 29.6467 -30.8774 47.642 18.4911 -30.8774 47.642 10 -30.8774 47.642 -10 -30.8774 47.642 -18.4911 -30.8774 45.423 -29.6467 -30.8774 39.1039 -39.1039 -30.8774 29.6467 -45.423 -30.8774 18.4911 -47.642 -30.8774 10 -47.642 -30.8774 -10 -47.642 -30.8774 -18.4911 -47.642 -30.8774 -29.6467 -45.423 -30.8774 -39.1039 -39.1039 -30.8774 -45.423 -29.6467 -30.8774 -47.642 -18.4911 -19.023 -50 -10 -19.023 -50 10 -19.023 -50 19.023 -19.023 -47.642 30.8774 -19.023 -40.9271 40.9271 -19.023 -30.8774 47.642 -19.023 -19.023 50 -19.023 -10 50 -19.023 10 50 -19.023 19.023 50 -19.023 30.8774 47.642 -19.023 40.9271 40.9271 -19.023 47.642 30.8774 -19.023 50 19.023 -19.023 50 10 -19.023 50 -10 -19.023 50 -19.023 -19.023 47.642 -30.8774 -19.023 40.9271 -40.9271 -19.023 30.8774 -47.642 -19.023 19.023 -50 -19.023 10 -50 -19.023 -10 -50 -19.023 -19.023 -50 -19.023 -30.8774 -47.642 -19.023 -40.9271 -40.9271 -19.023 -47.642 -30.8774 -19.023 -50 -19.023 -10 -50 -10 -10 -50 10 -10 -50 19.023 -10 -47.642 30.8774 -10 -40.9271 40.9271 -10 -30.8774 47.642 -10 -19.023 50 -10 -10 50 -10 10 50 -10 19.023 50 -10 30.8774 47.642 -10 40.9271 40.9271 -10 47.642 30.8774 -10 50 19.023 -10 50 10 -10 50 -10 -10 50 -19.023 -10 47.642 -30.8774 -10 40.9271 -40.9271 -10 30.8774 -47.642 -10 19.023 -50 -10 10 -50 -10 -10 -50 -10 -19.023 -50 -10 -30.8774 -47.642 -10 -40.9271 -40.9271 -10 -47.642 -30.8774 -10 -50 -19.023 10 -50 -10 10 -50 10 10 -50 19.023 10 -47.642 30.8774 10 -40.9271 40.9271 10 -30.8774 47.642 10 -19.023 50 10 -10 50 10 10 50 10 19.023 50 10 30.8774 47.642 10 40.9271 40.9271 10 47.642 30.8774 10 50 19.023 10 50 10 10 50 -10 10 50 -19.023 10 47.642 -30.8774 10 40.9271 -40.9271 10 30.8774 -47.642 10 19.023 -50 10 10 -50 10 -10 -50 10 -19.023 -50 10 -30.8774 -47.642 10 -40.9271 -40.9271 10 -47.642 -30.8774 10 -50 -19.023 19.023 -50 -10 19.023 -50 10 19.023 -50 19.023 19.023 -47.642 30.8774 19.023 -40.9271 40.9271 19.023 -30.8774 47.642 19.023 -19.023 50 19.023 -10 50 19.023 10 50 19.023 19.023 50 19.023 30.8774 47.642 19.023 40.9271 40.9271 19.023 47.642 30.8774 19.023 50 19.023 19.023 50 10 19.023 50 -10 19.023 50 -19.023 19.023 47.642 -30.8774 19.023 40.9271 -40.9271 19.023 30.8774 -47.642 19.023 19.023 -50 19.023 10 -50 19.023 -10 -50 19.023 -19.023 -50 19.023 -30.8774 -47.642 19.023 -40.9271 -40.9271 19.023 -47.642 -30.8774 19.023 -50 -19.023 30.8774 -47.642 -10 30.8774 -47.642 10 30.8774 -47.642 18.4911 30.8774 -45.423 29.6467 30.8774 -39.1039 39.1039 30.8774 -29.6467 45.423 30.8774 -18.4911 47.642 30.8774 -10 47.642 30.8774 10 47.642 30.8774 18.4911 47.642 30.8774 29.6467 45.423 30.8774 39.1039 39.1039 30.8774 45.423 29.6467 30.8774 47.642 18.4911 30.8774 47.642 10 30.8774 47.642 -10 30.8774 47.642 -18.4911 30.8774 45.423 -29.6467 30.8774 39.1039 -39.1039 30.8774 29.6467 -45.423 30.8774 18.4911 -47.642 30.8774 10 -47.642 30.8774 -10 -47.642 30.8774 -18.4911 -47.642 30.8774 -29.6467 -45.423 30.8774 -39.1039 -39.1039 30.8774 -45.423 -29.6467 30.8774 -47.642 -18.4911 40.9271 -40.9271 -10 40.9271 -40.9271 10 40.9271 -40.9271 16.9764 40.9271 -39.1039 26.1419 40.9271 -33.9121 33.9121 40.9271 -26.1419 39.1039 40.9271 -16.9764 40.9271 40.9271 -10 40.9271 40.9271 10 40.9271 40.9271 16.9764 40.9271 40.9271 26.1419 39.1039 40.9271 33.9121 33.9121 40.9271 39.1039 26.1419 40.9271 40.9271 16.9764 40.9271 40.9271 10 40.9271 40.9271 -10 40.9271 40.9271 -16.9764 40.9271 39.1039 -26.1419 40.9271 33.9121 -33.9121 40.9271 26.1419 -39.1039 40.9271 16.9764 -40.9271 40.9271 10 -40.9271 40.9271 -10 -40.9271 40.9271 -16.9764 -40.9271 40.9271 -26.1419 -39.1039 40.9271 -33.9121 -33.9121 40.9271 -39.1039 -26.1419 40.9271 -40.9271 -16.9764 47.642 -30.8774 -10 47.642 -30.8774 10 47.642 -30.8774 14.7094 47.642 -29.6467 20.8966 47.642 -26.1419 26.1419 47.642 -20.8967 29.6467 47.642 -14.7094 30.8774 47.642 -10 30.8774 47.642 10 30.8774 47.642 14.7094 30.8774 47.642 20.8966 29.6467 47.642 26.1419 26.1419 47.642 29.6467 20.8966 47.642 30.8774 14.7094 47.642 30.8774 10 47.642 30.8774 -10 47.642 30.8774 -14.7094 47.642 29.6467 -20.8967 47.642 26.1419 -26.1419 47.642 20.8966 -29.6467 47.642 14.7094 -30.8774 47.642 10 -30.8774 47.642 -10 -30.8774 47.642 -14.7094 -30.8774 47.642 -20.8967 -29.6467 47.642 -26.1419 -26.1419 47.642 -29.6467 -20.8967 47.642 -30.8774 -14.7094 50 -19.023 -10 50 -19.023 10 50 -19.023 12.0354 50 -18.4911 14.7094 50 -16.9764 16.9764 50 -14.7094 18.4911 50 -12.0354 19.023 50 -10 19.023 50 10 19.023 50 12.0354 19.023 50 14.7094 18.4911 50 16.9764 16.9764 50 18.4911 14.7094 50 19.023 12.0354 50 19.023 10 50 19.023 -10 50 19.023 -12.0354 50 18.4911 -14.7094 50 16.9764 -16.9764 50 14.7094 -18.4911 50 12.0354 -19.023 50 10 -19.023 50 -10 -19.023 50 -12.0354 -19.023 50 -14.7094 -18.4911 50 -16.9764 -16.9764 50 -18.4911 -14.7094 50 -19.023 -12.0354 50 -10 -10 50 -10 10 50 10 10 50 10 -10</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-positions-array" count="344" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-normals" name="normal">
+ <float_array id="RoundedCube-normals-array" count="1032">-1 -0.000000 0 -1 -0.000000 0 -1 0.000000 0 -1 0 0 -0.993061 -0.117598 0 -0.996922 -0.078398 0 -0.993227 -0.115947 0.007469 -0.993787 -0.105554 0.035291 -0.992807 -0.084657 0.084657 -0.993787 -0.035292 0.105554 -0.993227 -0.007469 0.115947 -0.993061 0 0.117598 -0.996922 0 0.078398 -0.993227 0.007469 0.115947 -0.993787 0.035291 0.105554 -0.992807 0.084657 0.084657 -0.993787 0.105554 0.035291 -0.993227 0.115947 0.007469 -0.993061 0.117598 0 -0.996922 0.078398 0 -0.993227 0.115947 -0.007469 -0.993787 0.105554 -0.035291 -0.992807 0.084657 -0.084657 -0.993787 0.035291 -0.105554 -0.993227 0.007469 -0.115947 -0.993061 0 -0.117598 -0.996922 0 -0.078398 -0.993227 -0.007469 -0.115947 -0.993787 -0.035291 -0.105554 -0.992807 -0.084657 -0.084657 -0.993787 -0.105555 -0.035291 -0.993227 -0.115947 -0.007469 -0.92388 -0.382683 0 -0.947173 -0.320722 0 -0.925806 -0.376745 0.030759 -0.922055 -0.356058 0.15178 -0.920436 -0.261123 0.290881 -0.931551 -0.127114 0.340669 -0.925806 -0.030759 0.376745 -0.92388 0 0.382683 -0.947173 0 0.320722 -0.925806 0.030759 0.376745 -0.922055 0.15178 0.356058 -0.920436 0.290881 0.261123 -0.931551 0.340669 0.127114 -0.925806 0.376745 0.030759 -0.92388 0.382683 0 -0.947173 0.320722 0 -0.925806 0.376745 -0.030759 -0.922055 0.356058 -0.15178 -0.920436 0.261123 -0.290881 -0.931551 0.127114 -0.340669 -0.925806 0.030759 -0.376745 -0.92388 0 -0.382683 -0.947173 0 -0.320722 -0.925806 -0.030759 -0.376745 -0.922055 -0.15178 -0.356058 -0.920436 -0.290881 -0.261123 -0.931551 -0.340669 -0.127114 -0.925806 -0.376745 -0.030759 -0.707107 -0.707107 0 -0.752339 -0.658776 0 -0.712774 -0.698491 0.063742 -0.682181 -0.676059 0.278518 -0.73611 -0.471849 0.485284 -0.728929 -0.251867 0.636573 -0.712774 -0.063742 0.698491 -0.707107 0 0.707107 -0.752339 0 0.658776 -0.712774 0.063742 0.698491 -0.682181 0.278518 0.676059 -0.73611 0.485284 0.471849 -0.728929 0.636573 0.251867 -0.712775 0.698491 0.063742 -0.707107 0.707107 0 -0.752339 0.658776 0 -0.712775 0.698491 -0.063742 -0.682181 0.676059 -0.278519 -0.73611 0.471849 -0.485284 -0.728929 0.251867 -0.636573 -0.712775 0.063742 -0.698491 -0.707107 0 -0.707107 -0.752339 0 -0.658776 -0.712775 -0.063742 -0.698491 -0.682181 -0.278518 -0.676059 -0.73611 -0.485284 -0.471849 -0.728929 -0.636573 -0.251867 -0.712775 -0.698491 -0.063742 -0.382683 -0.92388 0 -0.442968 -0.896538 0 -0.388497 -0.917276 0.087603 -0.339221 -0.869305 0.359496 -0.410659 -0.640778 0.648662 -0.404562 -0.344312 0.847218 -0.388497 -0.087603 0.917276 -0.382683 0 0.92388 -0.442968 0 0.896538 -0.388497 0.087603 0.917276 -0.339221 0.359496 0.869305 -0.410659 0.648662 0.640778 -0.404562 0.847218 0.344312 -0.388497 0.917276 0.087603 -0.382683 0.92388 0 -0.442968 0.896538 0 -0.388497 0.917276 -0.087603 -0.339221 0.869305 -0.359496 -0.410659 0.640778 -0.648662 -0.404562 0.344312 -0.847218 -0.388497 0.087603 -0.917276 -0.382683 0 -0.92388 -0.442968 0 -0.896538 -0.388497 -0.087603 -0.917276 -0.339221 -0.359496 -0.869305 -0.410659 -0.648662 -0.640778 -0.404562 -0.847218 -0.344312 -0.388497 -0.917276 -0.087603 -0.098017 -0.995185 0 -0.112008 -0.993707 0 -0.100013 -0.986464 0.129944 -0.083619 -0.904647 0.417877 -0.106923 -0.702534 0.703572 -0.105389 -0.379817 0.919039 -0.100066 -0.097179 0.990224 -0.098017 0 0.995185 -0.112008 0 0.993707 -0.100013 0.129944 0.986464 -0.083619 0.417876 0.904648 -0.106923 0.703572 0.702534 -0.105389 0.919039 0.379817 -0.100066 0.990224 0.097178 -0.098017 0.995185 0 -0.112008 0.993707 0 -0.100013 0.986464 -0.129944 -0.083619 0.904647 -0.417877 -0.106923 0.702534 -0.703572 -0.105389 0.379817 -0.919039 -0.100066 0.097179 -0.990224 -0.098017 0 -0.995185 -0.112008 0 -0.993707 -0.100013 -0.129944 -0.986464 -0.083619 -0.417876 -0.904648 -0.106923 -0.703572 -0.702534 -0.105389 -0.919039 -0.379818 -0.100066 -0.990224 -0.097178 0 -1 0 0 -1 0 0 -0.995185 0.098017 0 -0.92388 0.382683 0 -0.707107 0.707107 0 -0.382683 0.92388 0 -0.098017 0.995185 0 0 1 0 0 1 0 0.098017 0.995185 0 0.382683 0.92388 0 0.707107 0.707107 0 0.92388 0.382683 0 0.995185 0.098017 0 1 0 0 1 0 0 0.995185 -0.098017 0 0.92388 -0.382683 0 0.707107 -0.707107 0 0.382683 -0.92388 0 0.098017 -0.995185 0 0 -1 0 0 -1 0 -0.098017 -0.995185 0 -0.382683 -0.92388 0 -0.707107 -0.707107 0 -0.92388 -0.382683 0 -0.995185 -0.098017 0 -1 0 0 -1 0 0 -0.995185 0.098017 0 -0.92388 0.382683 0 -0.707107 0.707107 0 -0.382683 0.92388 0 -0.098017 0.995185 0 0 1 0 0 1 0 0.098017 0.995185 0 0.382683 0.92388 0 0.707107 0.707107 0 0.92388 0.382683 0 0.995185 0.098017 0 1 0 0 1 0 0 0.995185 -0.098017 0 0.92388 -0.382683 0 0.707107 -0.707107 0 0.382683 -0.92388 0 0.098017 -0.995185 0 0 -1 0 0 -1 0 -0.098017 -0.995185 0 -0.382683 -0.92388 0 -0.707107 -0.707107 0 -0.92388 -0.382683 0 -0.995185 -0.098017 0.112008 -0.993707 0 0.098017 -0.995185 0 0.100066 -0.990224 0.097178 0.105389 -0.919039 0.379818 0.106923 -0.703572 0.702534 0.083619 -0.417876 0.904648 0.100013 -0.129944 0.986464 0.112008 0 0.993707 0.098017 0 0.995185 0.100066 0.097179 0.990224 0.105389 0.379817 0.919039 0.106923 0.702534 0.703572 0.083619 0.904647 0.417877 0.100013 0.986465 0.129944 0.112008 0.993707 0 0.098017 0.995185 0 0.100066 0.990224 -0.097178 0.105389 0.919039 -0.379818 0.106923 0.703572 -0.702534 0.083619 0.417876 -0.904648 0.100013 0.129944 -0.986464 0.112008 0 -0.993707 0.098017 0 -0.995185 0.100066 -0.097179 -0.990224 0.105389 -0.379817 -0.919039 0.106923 -0.702534 -0.703572 0.083619 -0.904647 -0.417877 0.100013 -0.986465 -0.129944 0.442968 -0.896538 0 0.382683 -0.92388 0 0.388497 -0.917276 0.087603 0.404562 -0.847218 0.344312 0.410659 -0.648662 0.640778 0.33922 -0.359496 0.869305 0.388497 -0.087603 0.917276 0.442968 0 0.896538 0.382683 0 0.92388 0.388497 0.087603 0.917276 0.404562 0.344312 0.847218 0.410659 0.640778 0.648662 0.339221 0.869305 0.359496 0.388497 0.917276 0.087603 0.442968 0.896538 0 0.382683 0.92388 0 0.388497 0.917276 -0.087603 0.404562 0.847218 -0.344312 0.410659 0.648662 -0.640778 0.339221 0.359496 -0.869305 0.388497 0.087603 -0.917276 0.442968 0 -0.896538 0.382683 0 -0.92388 0.388497 -0.087603 -0.917276 0.404562 -0.344312 -0.847218 0.410659 -0.640778 -0.648662 0.339221 -0.869305 -0.359496 0.388497 -0.917276 -0.087603 0.752339 -0.658776 0 0.707107 -0.707107 0 0.712774 -0.698491 0.063742 0.728929 -0.636573 0.251867 0.73611 -0.485284 0.471849 0.682181 -0.278518 0.676059 0.712775 -0.063742 0.698491 0.752339 0 0.658776 0.707107 0 0.707107 0.712774 0.063742 0.698491 0.728929 0.251867 0.636573 0.73611 0.471849 0.485284 0.682181 0.676059 0.278518 0.712775 0.698491 0.063742 0.752339 0.658776 0 0.707107 0.707107 0 0.712775 0.698491 -0.063742 0.728929 0.636573 -0.251867 0.73611 0.485284 -0.471849 0.682181 0.278518 -0.676059 0.712774 0.063742 -0.698491 0.752339 0 -0.658776 0.707107 0 -0.707107 0.712775 -0.063742 -0.698491 0.728929 -0.251867 -0.636573 0.73611 -0.471849 -0.485284 0.682181 -0.676059 -0.278518 0.712775 -0.698491 -0.063742 0.947173 -0.320722 0 0.92388 -0.382683 0 0.925806 -0.376745 0.030759 0.931551 -0.340669 0.127114 0.920436 -0.290881 0.261123 0.922055 -0.15178 0.356058 0.925806 -0.030759 0.376745 0.947173 0 0.320722 0.92388 0 0.382683 0.925806 0.030759 0.376745 0.931551 0.127114 0.340669 0.920436 0.261123 0.290881 0.922055 0.356058 0.15178 0.925806 0.376745 0.030759 0.947173 0.320722 0 0.92388 0.382683 0 0.925806 0.376745 -0.030759 0.931551 0.340669 -0.127114 0.920436 0.290881 -0.261123 0.922055 0.15178 -0.356058 0.925806 0.030759 -0.376745 0.947173 0 -0.320722 0.92388 0 -0.382683 0.925806 -0.030759 -0.376745 0.931551 -0.127114 -0.340669 0.920436 -0.261123 -0.290881 0.922055 -0.356058 -0.15178 0.925806 -0.376745 -0.030759 0.996922 -0.078398 0 0.993061 -0.117598 0 0.993227 -0.115947 0.007469 0.993787 -0.105554 0.035291 0.992807 -0.084657 0.084657 0.993787 -0.035292 0.105554 0.993227 -0.007469 0.115947 0.996922 0 0.078398 0.993061 0 0.117598 0.993227 0.007469 0.115947 0.993787 0.035291 0.105554 0.992807 0.084656 0.084657 0.993787 0.105554 0.035291 0.993227 0.115947 0.007469 0.996922 0.078398 0 0.993061 0.117598 0 0.993227 0.115947 -0.007469 0.993787 0.105555 -0.035291 0.992807 0.084657 -0.084657 0.993787 0.035291 -0.105554 0.993227 0.007469 -0.115947 0.996922 0 -0.078398 0.993061 0 -0.117598 0.993227 -0.007469 -0.115947 0.993787 -0.035291 -0.105554 0.992807 -0.084657 -0.084657 0.993787 -0.105555 -0.035291 0.993227 -0.115947 -0.007469 1 -0.000000 0 1 -0.000000 0 1 0.000000 0 1 0 0</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-normals-array" count="344" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-Texture" name="Texture">
+ <float_array id="RoundedCube-Texture-array" count="768">0.622169 0.267598 0.647035 0.267598 0.622169 0.377831 0.679703 0.274096 0.707398 0.292602 0.725904 0.320297 0.732402 0.352966 0.732402 0.377831 0.732402 0.622169 0.732402 0.647035 0.622169 0.622169 0.725904 0.679703 0.707398 0.707398 0.679703 0.725904 0.647035 0.732402 0.622169 0.732402 0.377831 0.732402 0.352966 0.732402 0.377831 0.622169 0.320297 0.725904 0.292602 0.707398 0.274096 0.679703 0.267598 0.647035 0.267598 0.622169 0.267598 0.377831 0.267598 0.352966 0.377831 0.377831 0.274096 0.320297 0.292602 0.292602 0.320297 0.274096 0.352966 0.267598 0.377831 0.267598 0.320297 0.274096 0.292602 0.292602 0.267598 0.352966 0.267598 0.377831 0.267598 0.647035 0.267598 0.622169 0.292602 0.707398 0.320297 0.725904 0.647034 0.732402 0.707398 0.707398 0.732402 0.647035 0.732402 0.622169 0.732402 0.352966 0.732402 0.377831 0.707398 0.292602 0.647034 0.267598 0.377831 0.122775 0.622169 0.122775 0.755291 0.137811 0.679703 0.122775 0.819372 0.180628 0.862189 0.244709 0.877225 0.320297 0.877225 0.377831 0.877225 0.679703 0.877225 0.622169 0.819372 0.819372 0.862189 0.755291 0.755291 0.862189 0.679703 0.877225 0.622169 0.877225 0.377831 0.877225 0.244709 0.862189 0.320297 0.877225 0.180628 0.819372 0.137811 0.755291 0.122775 0.679703 0.122775 0.622169 0.122775 0.320297 0.122775 0.377831 0.180628 0.180628 0.137811 0.244709 0.244709 0.137811 0.320297 0.122775 0.377831 0 0.622169 0 0.819372 0.022273 0.707398 0 0.914299 0.085701 0.977727 0.180628 1 0.292602 1 0.377831 1 0.707398 1 0.622169 0.977727 0.819372 0.914299 0.914299 0.819372 0.977727 0.707398 1 0.622169 1 0.377831 1 0.180628 0.977727 0.292602 1 0.085701 0.914299 0.022273 0.819372 0 0.707398 0 0.622169 0 0.292602 0 0.377831 0.022273 0.180628 0.085701 0.085701 0.180628 0.022273 0.292602 0 0 0.377831 0 0.622169 0 0.377831 0.122775 0.862189 0 0.819372 0.122775 0.725904 0 0.707398 0 0.819372 0.122775 0.022273 0.122775 0.137811 0 0.085701 0 0.180628 0 0.085701 0.122775 0.274096 0 0.292602 0 0.377831 0 0.292602 0 0.707398 0 0.622169 0 0.707398 0.122775 0.977727 0 0.819372 0 0.914299 0 0.819372 0.877225 0.862189 0.877225 0.725904 1 0.819372 1 0.707398 1 0.819372 1 0.622169 1 0.377831 1 0.622169 0.877225 0.137811 1 0.180628 0.877225 0.274096 1 0.292602 1 0.180628 0.877225 0.977727 1 0.914299 1 0.819372 1 0.914299 1 0.707398 1 0.622169 1 0.707398 1 0.292602 1 0.377831 1 0.292602 0.877225 0.022273 1 0.180628 1 0.085701 1 0.180628 0 0.180628 0 0.292602 0 0.180628 0.267598 0.877225 0.267598 0.732402 0.267598 0 0.267598 0.122775 0.122775 0.022273 0.122775 0.022273 0.267598 0.267598 0.267598 1 0.732402 0.877225 0.732402 0.732402 0.732402 0.122775 0.732402 0.267598 0.732402 1 0.877225 0.977727 0.877225 0.977727 0.732402 0 0.377831 0 0.267598 0 0.267598 0 0.622169 1 0.732402 1 0.732402 1 0.622169 0 0.377831 0 0.377831 0 0.377831 1 0.622169 1 0.622169 1 0.732402 0.732402 0.732402 0.877225 0.732402 0 0.732402 0.122775 0.622169 0 0.622169 0 0.732402 0.267598 0.732402 1 0.267598 0.877225 0.267598 0.732402 0.267598 0.267598 0.267598 0.122775 0.267598 1 0.377831 1 0.377831 1 0.267598 0 0.732402 0 0.877225 0.022273 0.732402 0 0.267598 1 0.122775 0.977727 0.267598 1 0.877225 0.022273 1 0.085701 0.877225 0.022273 0.122775 0.977727 0 0.914299 0.122775 0.977727 0.622169 0 0.377831 0 0.622169 0 0.180628 0.022273 0.292602 0 0.244709 0.137811 0.320297 0.122775 0.292602 0 0.022273 0.180628 0.085701 0.085701 0.180628 0.180628 0.085701 0.085701 0 0.292602 0 0.377831 0 0.377831 0 0.707398 0 0.622169 0 0.622169 0.085701 0.914299 0.022273 0.819372 0.180628 0.819372 0.022273 0.819372 0.180628 0.977727 0.244709 0.862189 0.292602 1 0.320297 0.877225 0.292602 1 0.377831 1 0.622169 1 0.377831 1 0.819372 0.977727 0.707398 1 0.707398 1 0.977727 0.819372 0.914299 0.914299 0.914299 0.914299 1 0.707398 1 0.622169 1 0.622169 1 0.292602 1 0.377831 1 0.377831 0.914299 0.085701 0.977727 0.180628 0.977727 0.180628 0.819372 0.022273 0.707398 0 0.707398 0 0 0.707398 0 0.622169 0 0.707398 0 0.819372 0 0.914299 0 0.819372 0 0.180628 0 0.292602 0 0.180628 0 0.377831 0 0.622169 0 0.377831 0 0.819372 0 0.707398 0 0.819372 0.877225 0.977727 1 0.914299 1 0.819372 1 0.914299 1 0.707398 1 0.622169 1 0.707398 1 0.292602 1 0.377831 1 0.292602 1 0.180628 1 0.085701 1 0.180628 1 0.819372 1 0.707398 1 0.819372 1 0.622169 1 0.377831 1 0.622169 1 0.180628 1 0.292602 1 0.180628 0.122775 0.022273 0 0.085701 0 0.180628 0 0.085701 0 0.292602 0 0.377831 0 0.292602 0.732402 1 0.877225 0.977727 0.877225 0.977727 0.267598 0 0.122775 0.022273 0.122775 0.022273 0.622169 1 0.732402 1 0.732402 1 0.377831 0 0.267598 0 0.267598 0 0.377831 1 0.622169 1 0.622169 1 0.622169 0 0.377831 0 0.377831 0 0.267598 1 0.377831 1 0.377831 1 0.732402 0 0.622169 0 0.622169 0 0.267598 1 0.122775 0.977727 0.267598 1 0.732402 0 0.877225 0.022273 0.732402 0 0.122775 0.977727 0 0.914299 0.122775 0.977727 0.877225 0.022273 1 0.085701 0.877225 0.022273 0.292602 0 0.377831 0 0.377831 0 0.085701 0.085701 0.180628 0.022273 0.180628 0.022273 0.022273 0.180628 0 0.292602 0 0.292602 0 0.377831 0 0.622169 0 0.377831 0.022273 0.819372 0 0.707398 0 0.707398 0.180628 0.977727 0.085701 0.914299 0.085701 0.914299 0.292602 1 0.377831 1 0.377831 1 0.707398 1 0.622169 1 0.622169 1 0.914299 0.914299 0.819372 0.977727 0.819372 0.977727 0.977727 0.819372 1 0.707398 1 0.707398 1 0.622169 1 0.377831 1 0.622169 0.977727 0.180628 1 0.292602 1 0.292602 0.819372 0.022273 0.914299 0.085701 0.914299 0.085701 0.707398 0 0.622169 0 0.622169 0</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-Texture-array" count="384" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="RoundedCube-vertices">
+ <input semantic="POSITION" source="#RoundedCube-positions"/>
+ <input semantic="NORMAL" source="#RoundedCube-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="684">
+ <input semantic="VERTEX" source="#RoundedCube-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#RoundedCube-Texture" offset="1" set="1"/>
+ <p>5 0 6 1 1 2 6 1 7 3 1 2 7 3 8 4 1 2 8 4 9 5 1 2 9 5 10 6 1 2 10 6 11 7 1 2 12 8 13 9 2 10 13 9 14 11 2 10 14 11 15 12 2 10 15 12 16 13 2 10 16 13 17 14 2 10 17 14 18 15 2 10 19 16 20 17 3 18 20 17 21 19 3 18 21 19 22 20 3 18 22 20 23 21 3 18 23 21 24 22 3 18 24 22 25 23 3 18 26 24 27 25 0 26 27 25 28 27 0 26 28 27 29 28 0 26 29 28 30 29 0 26 30 29 31 30 0 26 31 30 4 31 0 26 341 26 314 30 313 31 341 26 315 32 314 30 341 26 316 33 315 32 341 26 317 27 316 33 341 26 318 34 317 27 341 26 319 35 318 34 342 18 321 36 320 37 342 18 322 21 321 36 342 18 323 38 322 21 342 18 324 39 323 38 342 18 325 17 324 39 342 18 326 16 325 17 343 10 328 40 327 15 343 10 329 13 328 40 343 10 330 41 329 13 343 10 331 11 330 41 343 10 332 42 331 11 343 10 333 43 332 42 340 2 335 44 334 45 340 2 336 5 335 44 340 2 337 46 336 5 340 2 338 3 337 46 340 2 339 47 338 3 340 2 312 0 339 47 4 31 5 0 0 26 1 2 0 26 5 0 18 15 19 16 2 10 3 18 2 10 19 16 32 48 33 49 4 31 5 0 4 31 33 49 35 50 7 3 34 51 6 1 34 51 7 3 36 52 37 53 8 4 9 5 8 4 37 53 38 54 39 55 10 6 11 7 10 6 39 55 41 56 13 9 40 57 12 8 40 57 13 9 43 58 15 12 42 59 14 11 42 59 15 12 44 60 45 61 16 13 17 14 16 13 45 61 46 62 47 63 18 15 19 16 18 15 47 63 49 64 21 19 48 65 20 17 48 65 21 19 50 66 51 67 22 20 23 21 22 20 51 67 52 68 53 69 24 22 25 23 24 22 53 69 55 70 27 25 54 71 26 24 54 71 27 25 57 72 29 28 56 73 28 27 56 73 29 28 58 74 59 75 30 29 31 30 30 29 59 75 60 76 61 77 32 48 33 49 32 48 61 77 63 78 35 50 62 79 34 51 62 79 35 50 64 80 65 81 36 52 37 53 36 52 65 81 66 82 67 83 38 54 39 55 38 54 67 83 69 84 41 56 68 85 40 57 68 85 41 56 70 86 71 87 42 59 43 58 42 59 71 87 72 88 73 89 44 60 45 61 44 60 73 89 74 90 75 91 46 62 47 63 46 62 75 91 77 92 49 64 76 93 48 65 76 93 49 64 78 94 79 95 50 66 51 67 50 66 79 95 80 96 81 97 52 68 53 69 52 68 81 97 83 98 55 70 82 99 54 71 82 99 55 70 84 100 85 101 56 73 57 72 56 73 85 101 86 102 87 103 58 74 59 75 58 74 87 103 88 71 89 69 60 104 61 105 60 106 89 69 91 107 63 108 90 109 62 110 90 109 63 111 92 112 93 113 64 114 65 115 64 116 93 113 94 117 95 71 66 118 67 119 66 120 95 71 97 109 69 121 96 69 68 122 96 69 69 123 98 107 99 124 70 125 71 126 70 127 99 124 100 128 101 129 72 130 73 131 72 132 101 129 102 57 103 55 74 133 75 134 74 135 103 55 105 136 77 137 104 138 76 139 104 138 77 140 106 141 107 128 78 142 79 143 78 144 107 128 108 129 109 57 80 145 81 146 80 147 109 57 111 138 83 148 110 55 82 149 110 55 83 150 112 136 113 151 84 152 85 153 84 154 113 151 114 113 115 117 86 155 87 156 86 157 115 117 116 24 117 23 88 71 89 69 88 71 117 23 119 158 91 107 118 159 90 109 118 159 91 107 120 160 121 161 92 162 93 113 92 163 121 161 122 164 123 24 94 117 95 71 94 117 123 24 125 159 97 109 124 23 96 69 124 23 97 109 126 158 127 165 98 107 99 124 98 107 127 165 128 166 129 167 100 128 101 129 100 128 129 167 130 43 131 45 102 57 103 55 102 57 131 45 133 168 105 136 132 169 104 138 132 169 105 136 134 170 135 166 106 171 107 128 106 172 135 166 136 167 137 43 108 129 109 57 108 129 137 43 139 169 111 138 138 45 110 55 138 45 111 138 140 168 141 173 112 136 113 151 112 136 141 173 142 161 143 164 114 113 115 117 114 113 143 164 144 26 145 18 116 24 117 23 116 24 145 18 146 16 147 63 118 159 119 158 118 159 147 63 148 174 149 48 120 175 121 161 120 176 149 48 150 31 151 26 122 164 123 24 122 164 151 26 152 18 153 16 124 23 125 159 124 23 153 16 154 63 155 91 126 158 127 165 126 158 155 91 156 62 157 15 128 166 129 167 128 166 157 15 158 10 159 2 130 43 131 45 130 43 159 2 160 0 161 49 132 169 133 168 132 169 161 49 162 177 163 62 134 178 135 166 134 179 163 62 164 15 165 10 136 167 137 43 136 167 165 10 166 2 167 0 138 45 139 169 138 45 167 0 168 49 169 77 140 168 141 173 140 168 169 77 170 48 171 31 142 161 143 164 142 161 171 31 172 2 173 10 144 26 145 18 144 26 173 10 174 15 175 62 146 16 147 63 146 16 175 62 176 180 177 49 148 181 149 48 148 182 177 49 178 0 179 2 150 31 151 26 150 31 179 2 180 10 181 15 152 18 153 16 152 18 181 15 182 62 183 90 154 63 155 91 154 63 183 90 184 63 185 16 156 62 157 15 156 62 185 16 186 18 187 26 158 10 159 2 158 10 187 26 188 31 189 48 160 0 161 49 160 0 189 48 190 183 191 63 162 184 163 62 162 185 191 63 192 16 193 18 164 15 165 10 164 15 193 18 194 26 195 31 166 2 167 0 166 2 195 31 196 48 197 76 168 49 169 77 168 49 197 76 198 49 199 0 170 48 171 31 170 48 199 0 200 7 201 8 172 2 173 10 172 2 201 8 202 186 203 187 174 15 175 62 174 15 203 187 204 188 205 189 176 190 177 49 176 191 205 189 206 192 207 7 178 0 179 2 178 0 207 7 208 8 209 186 180 10 181 15 180 10 209 186 210 187 211 193 182 62 183 90 182 62 211 193 212 194 213 195 184 63 185 16 184 63 213 195 214 37 215 35 186 18 187 26 186 18 215 35 216 196 217 197 188 31 189 48 188 31 217 197 218 198 219 194 190 199 191 63 190 200 219 194 220 195 221 37 192 16 193 18 192 16 221 37 222 35 223 196 194 26 195 31 194 26 223 196 224 197 225 201 196 48 197 76 196 48 225 201 226 189 227 192 198 49 199 0 198 49 227 192 228 55 229 57 200 7 201 8 200 7 229 57 230 129 231 128 202 186 203 187 202 186 231 128 205 189 204 202 233 136 232 203 233 136 204 204 206 192 234 138 207 7 235 55 207 7 234 138 209 186 208 8 237 129 236 57 237 129 208 8 211 193 210 187 239 141 238 128 239 141 210 187 241 109 213 195 240 107 212 194 240 107 213 195 242 69 243 71 214 37 215 35 214 37 243 71 244 117 245 113 216 196 217 197 216 196 245 113 219 194 218 205 247 107 246 206 247 107 218 207 220 195 248 109 221 37 249 69 221 37 248 109 223 196 222 35 251 117 250 71 251 117 222 35 225 201 224 197 253 112 252 113 253 112 224 197 255 138 227 192 254 136 226 189 254 136 227 192 256 83 257 85 228 55 229 57 228 55 257 85 231 128 230 129 259 130 258 84 259 130 230 129 233 136 232 208 261 137 260 209 261 137 232 210 234 138 262 82 235 55 263 83 235 55 262 82 237 129 236 57 265 84 264 85 265 84 236 57 239 141 238 128 267 142 266 130 267 142 238 128 240 107 268 108 241 109 269 96 241 109 268 108 270 97 271 99 242 69 243 71 242 69 271 99 245 113 244 117 273 115 272 98 273 115 244 117 247 107 246 211 275 108 274 212 275 108 246 213 248 109 276 96 249 69 277 97 249 69 276 96 251 117 250 71 279 98 278 99 279 98 250 71 253 112 252 113 281 114 280 115 281 114 252 113 254 136 282 137 255 138 283 82 255 138 282 137 284 49 285 48 256 214 257 215 256 216 285 48 259 217 258 218 287 219 286 220 287 219 258 221 261 222 260 223 289 73 288 224 289 73 260 225 262 226 290 70 263 227 291 71 263 228 290 70 265 229 264 230 293 68 292 69 293 68 264 231 267 232 266 233 295 234 294 67 295 234 266 235 268 236 296 237 269 238 297 239 269 240 296 237 298 63 299 62 270 241 271 242 270 243 299 62 273 244 272 245 301 60 300 61 301 60 272 246 275 247 274 248 303 59 302 58 303 59 274 249 276 250 304 56 277 251 305 57 277 252 304 56 279 253 278 254 307 54 306 55 307 54 278 255 281 256 280 257 309 52 308 53 309 52 280 258 282 259 310 50 283 260 311 51 283 261 310 50 312 0 313 31 284 49 285 48 284 49 313 31 287 219 286 220 315 32 314 30 315 32 286 220 288 224 316 33 289 73 317 27 289 73 316 33 290 70 318 34 291 71 319 35 291 71 318 34 293 68 292 69 321 36 320 37 321 36 292 69 295 234 294 67 323 38 322 21 323 38 294 67 296 237 324 39 297 239 325 17 297 239 324 39 326 16 327 15 298 63 299 62 298 63 327 15 301 60 300 61 329 13 328 40 329 13 300 61 302 58 330 41 303 59 331 11 303 59 330 41 304 56 332 42 305 57 333 43 305 57 332 42 307 54 306 55 335 44 334 45 335 44 306 55 309 52 308 53 337 46 336 5 337 46 308 53 310 50 338 3 311 51 339 47 311 51 338 3 340 2 341 26 312 0 313 31 312 0 341 26 342 18 343 10 326 16 327 15 326 16 343 10 340 2 343 10 341 26 342 18 341 26 343 10 0 26 1 2 3 18 2 10 3 18 1 2 11 7 12 8 1 2 2 10 1 2 12 8 25 23 26 24 3 18 0 26 3 18 26 24 34 51 6 1 33 49 5 0 33 49 6 1 36 52 8 4 35 50 7 3 35 50 8 4 37 53 38 54 9 5 10 6 9 5 38 54 39 55 40 57 11 7 12 8 11 7 40 57 42 59 14 11 41 56 13 9 41 56 14 11 43 58 44 60 15 12 16 13 15 12 44 60 45 61 46 62 17 14 18 15 17 14 46 62 48 65 20 17 47 63 19 16 47 63 20 17 50 66 22 20 49 64 21 19 49 64 22 20 51 67 52 68 23 21 24 22 23 21 52 68 53 69 54 71 25 23 26 24 25 23 54 71 56 73 28 27 55 70 27 25 55 70 28 27 57 72 58 74 29 28 30 29 29 28 58 74 59 75 32 48 31 30 4 31 31 30 32 48 62 79 34 51 61 77 33 49 61 77 34 51 63 78 64 80 35 50 36 52 35 50 64 80 65 81 66 82 37 53 38 54 37 53 66 82 67 83 68 85 39 55 40 57 39 55 68 85 70 86 42 59 69 84 41 56 69 84 42 59 71 87 72 88 43 58 44 60 43 58 72 88 73 89 74 90 45 61 46 62 45 61 74 90 76 93 48 65 75 91 47 63 75 91 48 65 77 92 78 94 49 64 50 66 49 64 78 94 79 95 80 96 51 67 52 68 51 67 80 96 81 97 82 99 53 69 54 71 53 69 82 99 84 100 56 73 83 98 55 70 83 98 56 73 85 101 86 102 57 72 58 74 57 72 86 102 87 103 60 76 59 75 32 48 59 75 60 76 90 109 62 262 89 69 61 263 89 69 62 264 91 107 92 124 63 265 64 266 63 267 92 124 93 113 94 117 65 268 66 269 65 270 94 117 95 71 96 69 67 271 68 272 67 273 96 69 98 107 70 274 97 109 69 275 97 109 70 276 99 277 100 128 71 278 72 279 71 280 100 128 101 129 102 57 73 281 74 282 73 283 102 57 104 138 76 284 103 55 75 285 103 55 76 286 105 136 106 151 77 287 78 288 77 289 106 151 107 128 108 129 79 290 80 291 79 292 108 129 109 57 110 55 81 293 82 294 81 295 110 55 112 136 84 296 111 138 83 297 111 138 84 298 113 299 114 113 85 300 86 301 85 302 114 113 115 117 88 71 87 303 60 304 87 305 88 71 118 159 90 109 117 23 89 69 117 23 90 109 119 158 120 165 91 107 92 124 91 107 120 165 121 161 122 164 93 113 94 117 93 113 122 164 123 24 124 23 95 71 96 69 95 71 124 23 126 158 98 107 125 159 97 109 125 159 98 107 127 306 128 166 99 307 100 128 99 308 128 166 129 167 130 43 101 129 102 57 101 129 130 43 132 169 104 138 131 45 103 55 131 45 104 138 133 168 134 173 105 136 106 151 105 136 134 173 135 166 136 167 107 128 108 129 107 128 136 167 137 43 138 45 109 57 110 55 109 57 138 45 140 168 112 136 139 169 111 138 139 169 112 136 141 309 142 161 113 310 114 113 113 311 142 161 143 164 116 24 115 117 88 71 115 117 116 24 145 18 146 16 117 23 118 159 117 23 146 16 147 63 148 91 119 158 120 165 119 158 148 91 149 48 150 31 121 161 122 164 121 161 150 31 151 26 152 18 123 24 124 23 123 24 152 18 153 16 154 63 125 159 126 158 125 159 154 63 155 312 156 62 127 313 128 166 127 314 156 62 157 15 158 10 129 167 130 43 129 167 158 10 159 2 160 0 131 45 132 169 131 45 160 0 161 49 162 77 133 168 134 173 133 168 162 77 163 62 164 15 135 166 136 167 135 166 164 15 165 10 166 2 137 43 138 45 137 43 166 2 167 0 168 49 139 169 140 168 139 169 168 49 169 315 170 48 141 316 142 161 141 317 170 48 171 31 144 26 143 164 116 24 143 164 144 26 173 10 174 15 145 18 146 16 145 18 174 15 175 62 176 90 147 63 148 91 147 63 176 90 177 49 178 0 149 48 150 31 149 48 178 0 179 2 180 10 151 26 152 18 151 26 180 10 181 15 182 62 153 16 154 63 153 16 182 62 183 318 184 63 155 319 156 62 155 320 184 63 185 16 186 18 157 15 158 10 157 15 186 18 187 26 188 31 159 2 160 0 159 2 188 31 189 48 190 76 161 49 162 77 161 49 190 76 191 63 192 16 163 62 164 15 163 62 192 16 193 18 194 26 165 10 166 2 165 10 194 26 195 31 196 48 167 0 168 49 167 0 196 48 197 321 198 49 169 322 170 48 169 323 198 49 199 0 172 2 171 31 144 26 171 31 172 2 201 8 202 186 173 10 174 15 173 10 202 186 203 187 204 193 175 62 176 90 175 62 204 193 205 189 206 192 177 49 178 0 177 49 206 192 207 7 208 8 179 2 180 10 179 2 208 8 209 186 210 187 181 15 182 62 181 15 210 187 211 324 212 194 183 325 184 63 183 326 212 194 213 195 214 37 185 16 186 18 185 16 214 37 215 35 216 196 187 26 188 31 187 26 216 196 217 197 218 201 189 48 190 76 189 48 218 201 219 194 220 195 191 63 192 16 191 63 220 195 221 37 222 35 193 18 194 26 193 18 222 35 223 196 224 197 195 31 196 48 195 31 224 197 225 327 226 189 197 328 198 49 197 329 226 189 227 192 200 7 199 0 172 2 199 0 200 7 202 186 201 8 230 129 229 57 230 129 201 8 204 193 203 187 232 141 231 128 232 141 203 187 234 138 206 192 233 136 205 189 233 136 206 192 235 55 236 57 207 7 208 8 207 7 236 57 237 129 238 128 209 186 210 187 209 186 238 128 212 194 211 330 240 107 239 331 240 107 211 332 213 195 241 109 214 37 242 69 214 37 241 109 216 196 215 35 244 117 243 71 244 117 215 35 218 201 217 197 246 112 245 113 246 112 217 197 248 109 220 195 247 107 219 194 247 107 220 195 249 69 250 71 221 37 222 35 221 37 250 71 251 117 252 113 223 196 224 197 223 196 252 113 226 189 225 333 254 136 253 334 254 136 225 335 227 192 255 138 200 7 228 55 200 7 255 138 230 129 229 57 258 84 257 85 258 84 229 57 232 141 231 128 260 142 259 130 260 142 231 128 233 136 261 137 234 138 262 82 234 138 261 137 263 83 264 85 235 55 236 57 235 55 264 85 238 128 237 129 266 130 265 84 266 130 237 129 240 107 239 336 268 108 267 337 268 108 239 338 241 109 269 96 242 69 270 97 242 69 269 96 244 117 243 71 272 98 271 99 272 98 243 71 246 112 245 113 274 114 273 115 274 114 245 113 247 107 275 108 248 109 276 96 248 109 275 108 277 97 278 99 249 69 250 71 249 69 278 99 252 113 251 117 280 115 279 98 280 115 251 117 254 136 253 339 282 137 281 340 282 137 253 341 255 138 283 82 228 55 256 83 228 55 283 82 258 342 257 343 286 220 285 48 286 220 257 344 260 345 259 346 288 224 287 219 288 224 259 347 261 348 289 73 262 349 290 70 262 350 289 73 291 71 292 69 263 351 264 352 263 353 292 69 266 354 265 355 294 67 293 68 294 67 265 356 268 357 267 358 296 237 295 234 296 237 267 359 269 360 297 239 270 361 298 63 270 362 297 239 272 363 271 364 300 61 299 62 300 61 271 365 274 366 273 367 302 58 301 60 302 58 273 368 275 369 303 59 276 370 304 56 276 371 303 59 305 57 306 55 277 372 278 373 277 374 306 55 280 375 279 376 308 53 307 54 308 53 279 377 282 378 281 379 310 50 309 52 310 50 281 380 283 381 311 51 256 382 284 49 256 383 311 51 286 220 285 48 314 30 313 31 314 30 285 48 288 224 287 219 316 33 315 32 316 33 287 219 289 73 317 27 290 70 318 34 290 70 317 27 319 35 320 37 291 71 292 69 291 71 320 37 294 67 293 68 322 21 321 36 322 21 293 68 295 234 323 38 296 237 324 39 296 237 323 38 297 239 325 17 298 63 326 16 298 63 325 17 300 61 299 62 328 40 327 15 328 40 299 62 302 58 301 60 330 41 329 13 330 41 301 60 303 59 331 11 304 56 332 42 304 56 331 11 333 43 334 45 305 57 306 55 305 57 334 45 308 53 307 54 336 5 335 44 336 5 307 54 309 52 337 46 310 50 338 3 310 50 337 46 311 51 339 47 284 49 312 0 284 49 339 47 341 26 342 18 319 35 320 37 319 35 342 18 343 10 340 2 333 43 334 45 333 43 340 2</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="_RoundedCube" name="RoundedCube" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#RoundedCube">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-5.dae b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-5.dae
new file mode 100644
index 00000000..66c1029d
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Cubes/RoundedCube-5.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/cubes/RoundedCube-5.mb</source_data>
+ </contributor>
+ <created>2008-09-19T18:07:45Z</created>
+ <modified>2008-09-19T18:07:45Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="RoundedCube" name="RoundedCube">
+ <mesh>
+ <source id="RoundedCube-positions" name="position">
+ <float_array id="RoundedCube-positions-array" count="1098">-50 -9.56229 1.82875 -50 -9.18378 4.21854 -50 -8.08531 6.37441 -50 -6.37441 8.08532 -50 -4.21854 9.18378 -50 -1.82875 9.56229 -50 1.82875 9.56229 -50 4.21854 9.18378 -50 6.37441 8.08532 -50 8.08532 6.37441 -50 9.18378 4.21854 -50 9.56229 1.82875 -50 9.56229 -1.82875 -50 9.18378 -4.21854 -50 8.08532 -6.37441 -50 6.37441 -8.08531 -50 4.21854 -9.18378 -50 1.82875 -9.56229 -50 -1.82875 -9.56229 -50 -4.21854 -9.18378 -50 -6.37441 -8.08531 -50 -8.08531 -6.37441 -50 -9.18378 -4.21854 -50 -9.56229 -1.82875 -48.0208 -22.0582 4.21854 -48.0208 -21.1851 9.73131 -48.0208 -18.6512 14.7044 -48.0208 -14.7044 18.6512 -48.0208 -9.73131 21.1851 -48.0208 -4.21854 22.0582 -48.0208 4.21854 22.0582 -48.0208 9.73131 21.1851 -48.0208 14.7044 18.6512 -48.0208 18.6512 14.7044 -48.0208 21.1851 9.73131 -48.0208 22.0582 4.21854 -48.0208 22.0582 -4.21854 -48.0208 21.1851 -9.73131 -48.0208 18.6512 -14.7044 -48.0208 14.7044 -18.6512 -48.0208 9.73131 -21.1851 -48.0208 4.21854 -22.0582 -48.0208 -4.21854 -22.0582 -48.0208 -9.73131 -21.1851 -48.0208 -14.7044 -18.6512 -48.0208 -18.6512 -14.7044 -48.0208 -21.1851 -9.73131 -48.0208 -22.0582 -4.21854 -42.2771 -33.331 6.37441 -42.2771 -32.0116 14.7044 -42.2771 -28.1827 22.2191 -42.2771 -22.2191 28.1827 -42.2771 -14.7044 32.0116 -42.2771 -6.37441 33.331 -42.2771 6.37441 33.331 -42.2771 14.7044 32.0116 -42.2771 22.2191 28.1827 -42.2771 28.1827 22.2191 -42.2771 32.0116 14.7044 -42.2771 33.331 6.37441 -42.2771 33.331 -6.37441 -42.2771 32.0116 -14.7044 -42.2771 28.1827 -22.2191 -42.2771 22.2191 -28.1827 -42.2771 14.7044 -32.0116 -42.2771 6.37441 -33.331 -42.2771 -6.37441 -33.331 -42.2771 -14.7044 -32.0116 -42.2771 -22.2191 -28.1827 -42.2771 -28.1827 -22.2191 -42.2771 -32.0116 -14.7044 -42.2771 -33.331 -6.37441 -33.331 -42.2771 8.08532 -33.331 -40.6036 18.6512 -33.331 -35.747 28.1827 -33.331 -28.1827 35.747 -33.331 -18.6512 40.6036 -33.331 -8.08531 42.2771 -33.331 8.08532 42.2771 -33.331 18.6512 40.6036 -33.331 28.1827 35.747 -33.331 35.747 28.1827 -33.331 40.6036 18.6512 -33.331 42.2771 8.08532 -33.331 42.2771 -8.08531 -33.331 40.6036 -18.6512 -33.331 35.747 -28.1827 -33.331 28.1827 -35.747 -33.331 18.6512 -40.6036 -33.331 8.08532 -42.2771 -33.331 -8.08531 -42.2771 -33.331 -18.6512 -40.6036 -33.331 -28.1827 -35.747 -33.331 -35.747 -28.1827 -33.331 -40.6036 -18.6512 -33.331 -42.2771 -8.08531 -22.0582 -48.0208 9.18378 -22.0582 -46.12 21.1851 -22.0582 -40.6036 32.0116 -22.0582 -32.0116 40.6036 -22.0582 -21.1851 46.12 -22.0582 -9.18378 48.0208 -22.0582 9.18378 48.0208 -22.0582 21.1851 46.12 -22.0582 32.0116 40.6036 -22.0582 40.6036 32.0116 -22.0582 46.12 21.1851 -22.0582 48.0208 9.18378 -22.0582 48.0208 -9.18378 -22.0582 46.12 -21.1851 -22.0582 40.6036 -32.0116 -22.0582 32.0116 -40.6036 -22.0582 21.1851 -46.12 -22.0582 9.18378 -48.0208 -22.0582 -9.18378 -48.0208 -22.0582 -21.1851 -46.12 -22.0582 -32.0116 -40.6036 -22.0582 -40.6036 -32.0116 -22.0582 -46.12 -21.1851 -22.0582 -48.0208 -9.18378 -9.56229 -50 9.56229 -9.56229 -48.0208 22.0582 -9.56229 -42.2771 33.331 -9.56229 -33.331 42.2771 -9.56229 -22.0582 48.0208 -9.56229 -9.56229 50 -9.56229 9.56229 50 -9.56229 22.0582 48.0208 -9.56229 33.331 42.2771 -9.56229 42.2771 33.331 -9.56229 48.0208 22.0582 -9.56229 50 9.56229 -9.56229 50 -9.56229 -9.56229 48.0208 -22.0582 -9.56229 42.2771 -33.331 -9.56229 33.331 -42.2771 -9.56229 22.0582 -48.0208 -9.56229 9.56229 -50 -9.56229 -9.56229 -50 -9.56229 -22.0582 -48.0208 -9.56229 -33.331 -42.2771 -9.56229 -42.2771 -33.331 -9.56229 -48.0208 -22.0582 -9.56229 -50 -9.56229 9.56229 -50 9.56229 9.56229 -48.0208 22.0582 9.56229 -42.2771 33.331 9.56229 -33.331 42.2771 9.56229 -22.0582 48.0208 9.56229 -9.56229 50 9.56229 9.56229 50 9.56229 22.0582 48.0208 9.56229 33.331 42.2771 9.56229 42.2771 33.331 9.56229 48.0208 22.0582 9.56229 50 9.56229 9.56229 50 -9.56229 9.56229 48.0208 -22.0582 9.56229 42.2771 -33.331 9.56229 33.331 -42.2771 9.56229 22.0582 -48.0208 9.56229 9.56229 -50 9.56229 -9.56229 -50 9.56229 -22.0582 -48.0208 9.56229 -33.331 -42.2771 9.56229 -42.2771 -33.331 9.56229 -48.0208 -22.0582 9.56229 -50 -9.56229 22.0582 -48.0208 9.18378 22.0582 -46.12 21.1851 22.0582 -40.6036 32.0116 22.0582 -32.0116 40.6036 22.0582 -21.1851 46.12 22.0582 -9.18378 48.0208 22.0582 9.18378 48.0208 22.0582 21.1851 46.12 22.0582 32.0116 40.6036 22.0582 40.6036 32.0116 22.0582 46.12 21.1851 22.0582 48.0208 9.18378 22.0582 48.0208 -9.18378 22.0582 46.12 -21.1851 22.0582 40.6036 -32.0116 22.0582 32.0116 -40.6036 22.0582 21.1851 -46.12 22.0582 9.18378 -48.0208 22.0582 -9.18378 -48.0208 22.0582 -21.1851 -46.12 22.0582 -32.0116 -40.6036 22.0582 -40.6036 -32.0116 22.0582 -46.12 -21.1851 22.0582 -48.0208 -9.18378 33.331 -42.2771 8.08532 33.331 -40.6036 18.6512 33.331 -35.747 28.1827 33.331 -28.1827 35.747 33.331 -18.6512 40.6036 33.331 -8.08531 42.2771 33.331 8.08532 42.2771 33.331 18.6512 40.6036 33.331 28.1827 35.747 33.331 35.747 28.1827 33.331 40.6036 18.6512 33.331 42.2771 8.08532 33.331 42.2771 -8.08531 33.331 40.6036 -18.6512 33.331 35.747 -28.1827 33.331 28.1827 -35.747 33.331 18.6512 -40.6036 33.331 8.08532 -42.2771 33.331 -8.08531 -42.2771 33.331 -18.6512 -40.6036 33.331 -28.1827 -35.747 33.331 -35.747 -28.1827 33.331 -40.6036 -18.6512 33.331 -42.2771 -8.08531 42.2771 -33.331 6.37441 42.2771 -32.0116 14.7044 42.2771 -28.1827 22.2191 42.2771 -22.2191 28.1827 42.2771 -14.7044 32.0116 42.2771 -6.37441 33.331 42.2771 6.37441 33.331 42.2771 14.7044 32.0116 42.2771 22.2191 28.1827 42.2771 28.1827 22.2191 42.2771 32.0116 14.7044 42.2771 33.331 6.37441 42.2771 33.331 -6.37441 42.2771 32.0116 -14.7044 42.2771 28.1827 -22.2191 42.2771 22.2191 -28.1827 42.2771 14.7044 -32.0116 42.2771 6.37441 -33.331 42.2771 -6.37441 -33.331 42.2771 -14.7044 -32.0116 42.2771 -22.2191 -28.1827 42.2771 -28.1827 -22.2191 42.2771 -32.0116 -14.7044 42.2771 -33.331 -6.37441 48.0208 -22.0582 4.21854 48.0208 -21.1851 9.73131 48.0208 -18.6512 14.7044 48.0208 -14.7044 18.6512 48.0208 -9.73131 21.1851 48.0208 -4.21854 22.0582 48.0208 4.21854 22.0582 48.0208 9.73131 21.1851 48.0208 14.7044 18.6512 48.0208 18.6512 14.7044 48.0208 21.1851 9.73131 48.0208 22.0582 4.21854 48.0208 22.0582 -4.21854 48.0208 21.1851 -9.73131 48.0208 18.6512 -14.7044 48.0208 14.7044 -18.6512 48.0208 9.73131 -21.1851 48.0208 4.21854 -22.0582 48.0208 -4.21854 -22.0582 48.0208 -9.73131 -21.1851 48.0208 -14.7044 -18.6512 48.0208 -18.6512 -14.7044 48.0208 -21.1851 -9.73131 48.0208 -22.0582 -4.21854 50 -9.56229 1.82875 50 -9.18378 4.21854 50 -8.08531 6.37441 50 -6.37441 8.08532 50 -4.21854 9.18378 50 -1.82875 9.56229 50 1.82875 9.56229 50 4.21854 9.18378 50 6.37441 8.08532 50 8.08532 6.37441 50 9.18378 4.21854 50 9.56229 1.82875 50 9.56229 -1.82875 50 9.18378 -4.21854 50 8.08532 -6.37441 50 6.37441 -8.08531 50 4.21854 -9.18378 50 1.82875 -9.56229 50 -1.82875 -9.56229 50 -4.21854 -9.18378 50 -6.37441 -8.08531 50 -8.08531 -6.37441 50 -9.18378 -4.21854 50 -9.56229 -1.82875 0 -33.331 -42.2771 0 -42.2771 -33.331 -42.2771 0 -33.331 -33.331 0 -42.2771 -22.0582 0 -48.0208 -9.56229 0 -50 0 0 -50 0 -9.56229 -50 0 -22.0582 -48.0208 9.56229 0 -50 22.0582 0 -48.0208 33.331 0 -42.2771 42.2771 0 -33.331 0 22.0582 -48.0208 0 9.56229 -50 0 42.2771 -33.331 0 33.331 -42.2771 -42.2771 -33.331 0 -33.331 -42.2771 0 -22.0582 -48.0208 0 -9.56229 -50 0 0 -50 0 0 -48.0208 -22.0582 0 -50 -9.56229 9.56229 -50 0 22.0582 -48.0208 0 33.331 -42.2771 0 42.2771 -33.331 0 -50 0 0 -50 -9.56229 0 -50 0 -9.56229 -48.0208 -22.0582 0 -48.0208 0 -22.0582 48.0208 -22.0582 0 48.0208 0 -22.0582 50 -9.56229 0 50 0 -9.56229 50 0 0 -50 9.56229 0 -48.0208 22.0582 0 48.0208 22.0582 0 50 9.56229 0 -42.2771 33.331 0 -33.331 42.2771 0 -22.0582 48.0208 0 -9.56229 50 0 0 50 0 0 50 -9.56229 0 48.0208 -22.0582 9.56229 50 0 22.0582 48.0208 0 33.331 42.2771 0 42.2771 33.331 0 0 -50 9.56229 0 -48.0208 22.0582 -50 0 9.56229 -48.0208 0 22.0582 48.0208 0 22.0582 50 0 9.56229 0 48.0208 22.0582 0 50 9.56229 0 -42.2771 33.331 0 -33.331 42.2771 -42.2771 0 33.331 -33.331 0 42.2771 -22.0582 0 48.0208 -9.56229 0 50 0 -22.0582 48.0208 0 -9.56229 50 0 0 50 9.56229 0 50 22.0582 0 48.0208 33.331 0 42.2771 42.2771 0 33.331 0 9.56229 50 0 22.0582 48.0208 0 33.331 42.2771 0 42.2771 33.331</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-positions-array" count="366" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-normals" name="normal">
+ <float_array id="RoundedCube-normals-array" count="1098">-0.995633 -0.093228 0.004825 -0.9959 -0.087443 0.023157 -0.995253 -0.078789 0.057128 -0.996129 -0.047786 0.073785 -0.9959 -0.023156 0.087443 -0.995633 -0.004825 0.093228 -0.995633 0.004825 0.093228 -0.9959 0.023157 0.087443 -0.995253 0.057127 0.078789 -0.996128 0.073785 0.047787 -0.9959 0.087443 0.023157 -0.995633 0.093228 0.004825 -0.995633 0.093228 -0.004825 -0.9959 0.087443 -0.023157 -0.995253 0.07879 -0.057128 -0.996129 0.047786 -0.073785 -0.9959 0.023159 -0.087443 -0.995633 0.004827 -0.093228 -0.995633 -0.004827 -0.093228 -0.9959 -0.023158 -0.087443 -0.995253 -0.057128 -0.078789 -0.996128 -0.073786 -0.047787 -0.9959 -0.087443 -0.023157 -0.995633 -0.093228 -0.004825 -0.95196 -0.305572 0.019942 -0.954862 -0.284995 0.083767 -0.941486 -0.272843 0.197888 -0.956966 -0.164232 0.239258 -0.954862 -0.083767 0.284995 -0.95196 -0.019942 0.305572 -0.95196 0.019942 0.305572 -0.954862 0.083767 0.284995 -0.941486 0.197888 0.272843 -0.956966 0.239258 0.164232 -0.954862 0.284995 0.083767 -0.95196 0.305572 0.019942 -0.95196 0.305572 -0.019942 -0.954862 0.284995 -0.083767 -0.941486 0.272844 -0.197888 -0.956966 0.164232 -0.239258 -0.954862 0.083767 -0.284995 -0.95196 0.019943 -0.305572 -0.95196 -0.019943 -0.305572 -0.954862 -0.083767 -0.284995 -0.941486 -0.197888 -0.272843 -0.956966 -0.239258 -0.164232 -0.954862 -0.284995 -0.083767 -0.95196 -0.305572 -0.019942 -0.812092 -0.582002 0.04219 -0.80943 -0.55564 0.189967 -0.810428 -0.461046 0.361445 -0.827886 -0.323952 0.457885 -0.821536 -0.168789 0.544599 -0.812092 -0.04219 0.582002 -0.812092 0.04219 0.582002 -0.80943 0.189967 0.55564 -0.810429 0.361445 0.461046 -0.827886 0.457885 0.323952 -0.821537 0.544599 0.168789 -0.812092 0.582002 0.04219 -0.812092 0.582002 -0.04219 -0.80943 0.55564 -0.189967 -0.810428 0.461046 -0.361445 -0.827886 0.323952 -0.457885 -0.821537 0.168788 -0.544599 -0.812092 0.042189 -0.582002 -0.812092 -0.042189 -0.582002 -0.80943 -0.189967 -0.55564 -0.810428 -0.361445 -0.461046 -0.827886 -0.457885 -0.323952 -0.821536 -0.544599 -0.168789 -0.812092 -0.582002 -0.04219 -0.592275 -0.803455 0.060577 -0.562273 -0.786704 0.254843 -0.614617 -0.63529 0.467602 -0.614748 -0.459184 0.641276 -0.605902 -0.240241 0.758398 -0.592275 -0.060577 0.803455 -0.592275 0.060577 0.803455 -0.562274 0.254843 0.786704 -0.614617 0.467602 0.63529 -0.614748 0.641276 0.459184 -0.605902 0.758398 0.240241 -0.592275 0.803455 0.060577 -0.592275 0.803455 -0.060577 -0.562274 0.786704 -0.254843 -0.614617 0.63529 -0.467602 -0.614748 0.459184 -0.641276 -0.605902 0.240241 -0.758398 -0.592275 0.060577 -0.803455 -0.592275 -0.060577 -0.803455 -0.562273 -0.254843 -0.786704 -0.614617 -0.467602 -0.63529 -0.614748 -0.641276 -0.459184 -0.605902 -0.758398 -0.240241 -0.592275 -0.803455 -0.060577 -0.312566 -0.947075 0.073156 -0.269894 -0.915838 0.297319 -0.328823 -0.762415 0.557314 -0.329327 -0.552594 0.765626 -0.323021 -0.289533 0.901015 -0.312565 -0.073156 0.947075 -0.312565 0.073156 0.947075 -0.269894 0.297319 0.915837 -0.328822 0.557314 0.762416 -0.329327 0.765626 0.552594 -0.323022 0.901015 0.289533 -0.312565 0.947075 0.073156 -0.312565 0.947075 -0.073156 -0.269894 0.915838 -0.297319 -0.328822 0.762416 -0.557314 -0.329327 0.552594 -0.765627 -0.323022 0.289533 -0.901015 -0.312565 0.073156 -0.947075 -0.312565 -0.073156 -0.947075 -0.269894 -0.297319 -0.915838 -0.328823 -0.557314 -0.762416 -0.329327 -0.765626 -0.552594 -0.323022 -0.901015 -0.289534 -0.312566 -0.947075 -0.073156 -0.079579 -0.991364 0.104237 -0.065797 -0.938711 0.338368 -0.084134 -0.80594 0.585988 -0.084477 -0.585376 0.806349 -0.082795 -0.307587 0.947911 -0.079606 -0.078037 0.993767 -0.079579 0.104237 0.991364 -0.065797 0.338368 0.938711 -0.084134 0.585988 0.80594 -0.084477 0.806349 0.585376 -0.082795 0.947911 0.307587 -0.079606 0.993767 0.078037 -0.079579 0.991364 -0.104237 -0.065797 0.938711 -0.338368 -0.084134 0.80594 -0.585988 -0.084477 0.585376 -0.806349 -0.082795 0.307587 -0.947911 -0.079606 0.078037 -0.993767 -0.079579 -0.104237 -0.991364 -0.065797 -0.338368 -0.938711 -0.084134 -0.585988 -0.805941 -0.084477 -0.806349 -0.585376 -0.082795 -0.947911 -0.307587 -0.079606 -0.993767 -0.078037 0.079606 -0.993767 0.078037 0.082795 -0.947911 0.307587 0.084477 -0.806349 0.585376 0.084134 -0.585988 0.80594 0.065797 -0.338368 0.938711 0.079579 -0.104237 0.991364 0.079606 0.078037 0.993767 0.082795 0.307587 0.947911 0.084477 0.585376 0.806349 0.084134 0.80594 0.585988 0.065797 0.938711 0.338368 0.079579 0.991364 0.104237 0.079606 0.993767 -0.078037 0.082795 0.947911 -0.307587 0.084477 0.806349 -0.585376 0.084134 0.585988 -0.80594 0.065797 0.338368 -0.938711 0.079579 0.104237 -0.991364 0.079606 -0.078037 -0.993767 0.082795 -0.307587 -0.947911 0.084477 -0.585376 -0.806349 0.084134 -0.805941 -0.585987 0.065797 -0.938711 -0.338368 0.079579 -0.991364 -0.104237 0.312566 -0.947075 0.073156 0.323022 -0.901015 0.289533 0.329327 -0.765626 0.552594 0.328822 -0.557314 0.762416 0.269894 -0.297319 0.915837 0.312565 -0.073156 0.947075 0.312565 0.073156 0.947075 0.323022 0.289534 0.901015 0.329327 0.552594 0.765626 0.328823 0.762416 0.557314 0.269894 0.915837 0.297319 0.312565 0.947075 0.073156 0.312565 0.947075 -0.073156 0.323022 0.901015 -0.289533 0.329327 0.765627 -0.552594 0.328822 0.557314 -0.762415 0.269894 0.297319 -0.915838 0.312565 0.073156 -0.947075 0.312566 -0.073156 -0.947075 0.323022 -0.289533 -0.901015 0.329327 -0.552594 -0.765627 0.328823 -0.762415 -0.557314 0.269894 -0.915838 -0.297319 0.312566 -0.947075 -0.073156 0.592275 -0.803455 0.060577 0.605902 -0.758398 0.240241 0.614748 -0.641276 0.459184 0.614617 -0.467602 0.63529 0.562273 -0.254843 0.786704 0.592275 -0.060577 0.803455 0.592275 0.060577 0.803455 0.605902 0.240241 0.758398 0.614748 0.459184 0.641276 0.614617 0.63529 0.467602 0.562274 0.786704 0.254843 0.592275 0.803455 0.060577 0.592275 0.803455 -0.060577 0.605902 0.758398 -0.240241 0.614748 0.641276 -0.459184 0.614617 0.467602 -0.635291 0.562274 0.254843 -0.786704 0.592275 0.060577 -0.803455 0.592275 -0.060577 -0.803455 0.605902 -0.240241 -0.758398 0.614748 -0.459184 -0.641276 0.614617 -0.63529 -0.467602 0.562274 -0.786704 -0.254843 0.592275 -0.803455 -0.060577 0.812092 -0.582002 0.04219 0.821536 -0.544599 0.168789 0.827886 -0.457885 0.323953 0.810428 -0.361445 0.461046 0.80943 -0.189967 0.55564 0.812092 -0.04219 0.582002 0.812092 0.04219 0.582002 0.821536 0.168789 0.544599 0.827886 0.323953 0.457885 0.810428 0.461046 0.361445 0.80943 0.55564 0.189967 0.812092 0.582002 0.04219 0.812092 0.582002 -0.04219 0.821536 0.544599 -0.168789 0.827886 0.457885 -0.323953 0.810428 0.361445 -0.461046 0.80943 0.189967 -0.55564 0.812092 0.04219 -0.582002 0.812092 -0.042189 -0.582002 0.821536 -0.168788 -0.544599 0.827886 -0.323953 -0.457885 0.810428 -0.461046 -0.361445 0.80943 -0.55564 -0.189967 0.812092 -0.582002 -0.04219 0.95196 -0.305572 0.019942 0.954862 -0.284995 0.083767 0.956966 -0.239258 0.164232 0.941486 -0.197888 0.272844 0.954862 -0.083767 0.284995 0.95196 -0.019942 0.305572 0.95196 0.019942 0.305572 0.954862 0.083767 0.284995 0.956966 0.164232 0.239258 0.941486 0.272843 0.197888 0.954862 0.284995 0.083767 0.95196 0.305572 0.019942 0.95196 0.305572 -0.019942 0.954862 0.284995 -0.083767 0.956966 0.239258 -0.164232 0.941486 0.197888 -0.272843 0.954862 0.083767 -0.284995 0.95196 0.019942 -0.305572 0.95196 -0.019942 -0.305572 0.954862 -0.083767 -0.284995 0.956966 -0.164232 -0.239258 0.941486 -0.272844 -0.197888 0.954862 -0.284995 -0.083767 0.95196 -0.305572 -0.019942 0.995633 -0.093228 0.004825 0.9959 -0.087442 0.023157 0.996129 -0.073785 0.047786 0.995253 -0.057128 0.078789 0.9959 -0.023157 0.087443 0.995633 -0.004825 0.093228 0.995633 0.004825 0.093228 0.9959 0.023156 0.087443 0.996128 0.047786 0.073785 0.995253 0.078789 0.057128 0.9959 0.087443 0.023157 0.995633 0.093228 0.004825 0.995633 0.093228 -0.004825 0.9959 0.087442 -0.023157 0.996129 0.073786 -0.047787 0.995253 0.057128 -0.078789 0.9959 0.023157 -0.087443 0.995633 0.004826 -0.093228 0.995633 -0.004826 -0.093228 0.9959 -0.023158 -0.087443 0.996129 -0.047786 -0.073785 0.995253 -0.078789 -0.057128 0.9959 -0.087442 -0.023157 0.995633 -0.093228 -0.004825 0 -0.587785 -0.809017 0 -0.809017 -0.587785 -0.838881 0 -0.544315 -0.62962 0 -0.776903 -0.358728 0 -0.933442 -0.089662 0 -0.995972 0 0 -1 0 -0.078459 -0.996917 0 -0.309017 -0.951056 0.089662 0 -0.995972 0.358728 0 -0.933442 0.62962 0 -0.776903 0.838881 0 -0.544315 0 0.309017 -0.951056 0 0.078459 -0.996917 0 0.809017 -0.587785 0 0.587785 -0.809017 -0.838881 -0.544315 0 -0.62962 -0.776903 0 -0.358728 -0.933442 0 -0.089661 -0.995972 0 0 -1 0 0 -0.951056 -0.309017 0 -0.996917 -0.078459 0.089661 -0.995972 0 0.358728 -0.933442 0 0.62962 -0.776903 0 0.838881 -0.544315 0 -1 0 0 -0.996917 -0.078459 0 -0.996917 0 -0.078459 -0.966026 -0.258446 0 -0.966026 0 -0.258446 0.966026 -0.258446 0 0.966026 0 -0.258446 0.996917 -0.078459 0 0.996917 0 -0.078459 1 0 0 -0.996917 0.078459 0 -0.966026 0.258446 0 0.966026 0.258446 0 0.996917 0.078459 0 -0.838881 0.544315 0 -0.62962 0.776903 0 -0.358728 0.933442 0 -0.089661 0.995972 0 0 1 0 0 0.996917 -0.078459 0 0.951056 -0.309017 0.089661 0.995972 0 0.358728 0.933442 0 0.62962 0.776903 0 0.838881 0.544315 0 0 -0.996917 0.078459 0 -0.951057 0.309017 -0.996917 0 0.078459 -0.966026 0 0.258446 0.966026 0 0.258446 0.996917 0 0.078459 0 0.951056 0.309017 0 0.996917 0.078458 0 -0.809017 0.587785 0 -0.587785 0.809017 -0.838881 0 0.544315 -0.62962 0 0.776903 -0.358728 0 0.933442 -0.089661 0 0.995972 0 -0.309017 0.951056 0 -0.078459 0.996917 0 0 1 0.089661 0 0.995972 0.358728 0 0.933442 0.62962 0 0.776903 0.838881 0 0.544315 0 0.078459 0.996917 0 0.309017 0.951056 0 0.587785 0.809017 0 0.809017 0.587785</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-normals-array" count="366" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="RoundedCube-Texture" name="Texture">
+ <float_array id="RoundedCube-Texture-array" count="818">0.5 0.404377 0.518287 0.404377 0.5 0.5 0.542185 0.408162 0.563744 0.419147 0.580853 0.436256 0.591838 0.457815 0.595623 0.481713 0.595623 0.5 0.595623 0.518287 0.591838 0.542185 0.580853 0.563744 0.563744 0.580853 0.542185 0.591838 0.518287 0.595623 0.5 0.595623 0.481713 0.595623 0.457815 0.591838 0.436256 0.580853 0.419147 0.563744 0.408162 0.542185 0.404377 0.518287 0.404377 0.5 0.404377 0.481713 0.408162 0.457815 0.419147 0.436256 0.436256 0.419147 0.457815 0.408162 0.481713 0.404377 0.436256 0.419147 0.419147 0.436256 0.419147 0.563744 0.436256 0.580853 0.597313 0.288149 0.542185 0.279418 0.647044 0.313488 0.686512 0.352956 0.711851 0.402687 0.720582 0.457815 0.686512 0.647044 0.711851 0.597313 0.647044 0.686512 0.597313 0.711851 0.402687 0.711851 0.457815 0.720582 0.352956 0.686512 0.313488 0.647044 0.288149 0.597313 0.279418 0.542185 0.313488 0.352956 0.288149 0.402687 0.352956 0.313488 0.402687 0.288149 0.647044 0.179884 0.563744 0.16669 0.722191 0.218173 0.781827 0.277809 0.820116 0.352956 0.83331 0.436256 0.781827 0.722191 0.820116 0.647044 0.722191 0.781827 0.647044 0.820116 0.352956 0.820116 0.436256 0.83331 0.277809 0.781827 0.218173 0.722191 0.179884 0.647044 0.16669 0.563744 0.218173 0.277809 0.179884 0.352956 0.277809 0.218173 0.352956 0.179884 0.686512 0.093963 0.580853 0.077229 0.580853 0.077229 0.781827 0.14253 0.85747 0.218173 0.906036 0.313488 0.922771 0.419147 0.906036 0.686512 0.85747 0.781827 0.781827 0.85747 0.686512 0.906036 0.313488 0.906036 0.419147 0.922771 0.218173 0.85747 0.14253 0.781827 0.093963 0.686512 0.077229 0.580853 0.093963 0.313488 0.14253 0.218173 0.218173 0.14253 0.313488 0.093963 0.279418 0.711851 0.16669 0.686512 0.279418 0.591838 0.16669 0.580853 0.16669 0.686512 0.279418 0.820116 0.279418 0.906036 0.16669 0.781827 0.16669 0.85747 0.16669 0.781827 0.279418 0.288149 0.279418 0.408162 0.16669 0.313488 0.16669 0.419147 0.16669 0.313488 0.16669 0.686512 0.16669 0.781827 0.16669 0.686512 0.720582 0.820116 0.720582 0.711851 0.83331 0.781827 0.83331 0.686512 0.83331 0.781827 0.720582 0.288149 0.83331 0.313488 0.720582 0.408162 0.83331 0.419147 0.83331 0.313488 0.720582 0.906036 0.83331 0.85747 0.83331 0.781827 0.83331 0.85747 0.720582 0.591838 0.83331 0.686512 0.83331 0.580853 0.83331 0.686512 0.720582 0.179884 0.83331 0.313488 0.83331 0.218173 0.83331 0.313488 0.279418 0.179884 0.16669 0.218173 0.16669 0.313488 0.16669 0.218173 0.404377 0.720582 0.404377 0.595623 0.404377 0.83331 0.404377 0.922771 0.404377 0.279418 0.404377 0.404377 0.595623 0.83331 0.595623 0.720582 0.720582 0.820116 0.720582 0.820116 0.595623 0.279418 0.595623 0.404377 0.595623 0.922771 0.720582 0.906036 0.720582 0.906036 0.595623 0.595623 0.595623 0.16669 0.404377 0.16669 0.279418 0.179884 0.279418 0.179884 0.404377 0.83331 0.279418 0.820116 0.404377 0.83331 0.404377 0.922771 0.279418 0.906036 0.404377 0.922771 0.595623 0.16669 0.720582 0.179884 0.595623 0.16669 0.279418 0.820116 0.16669 0.686512 0.16669 0.781827 0.279418 0.820116 0.16669 0.313488 0.16669 0.419147 0.279418 0.906036 0.16669 0.85747 0.279418 0.906036 0.16669 0.580853 0.16669 0.218173 0.720582 0.179884 0.83331 0.218173 0.720582 0.179884 0.313488 0.093963 0.419147 0.077229 0.436256 0.16669 0.419147 0.077229 0.14253 0.218173 0.218173 0.14253 0.277809 0.218173 0.218173 0.14253 0.093963 0.313488 0.179884 0.352956 0.077229 0.419147 0.16669 0.436256 0.077229 0.419147 0.14253 0.781827 0.093963 0.686512 0.179884 0.647044 0.093963 0.686512 0.313488 0.906036 0.218173 0.85747 0.277809 0.781827 0.218173 0.85747 0.686512 0.906036 0.580853 0.922771 0.563744 0.83331 0.580853 0.922771 0.85747 0.781827 0.781827 0.85747 0.781827 0.85747 0.906036 0.686512 0.922771 0.580853 0.83331 0.563744 0.922771 0.580853 0.85747 0.218173 0.906036 0.313488 0.906036 0.313488 0.686512 0.093963 0.781827 0.14253 0.781827 0.14253 0.436256 0.16669 0.457815 0.279418 0.436256 0.16669 0.279418 0.457815 0.563744 0.83331 0.542185 0.720582 0.563744 0.83331 0.720582 0.542185 0.5 0.279418 0.720582 0.5 0.5 0.720582 0.279418 0.5 0.5 0.16669 0.83331 0.5 0.5 0.83331 0.16669 0.436256 0.16669 0.5 0.077229 0.563744 0.077229 0.5 0.077229 0.563744 0.922771 0.5 0.5 0.922771 0.922771 0.436256 0.922771 0.5 0.922771 0.436256 0.16669 0.580853 0.16669 0.5 0.16669 0.580853 0.83331 0.419147 0.83331 0.5 0.83331 0.419147 0.5 0.16669 0.404377 0.16669 0.404377 0.16669 0.5 0.077229 0.595623 0.077229 0.595623 0.16669 0.5 0.16669 0.5 0.16669 0.404377 0.077229 0.16669 0.5 0.922771 0.563744 0.077229 0.436256 0.436256 0.16669 0.5 0.16669 0.5 0.16669 0.16669 0.563744 0.16669 0.5 0.16669 0.5 0.563744 0.83331 0.5 0.83331 0.5 0.83331 0.83331 0.436256 0.83331 0.5 0.83331 0.5 0.436256 0.16669 0.077229 0.419147 0.077229 0.419147 0.419147 0.077229 0.16669 0.686512 0.16669 0.781827 0.16669 0.686512 0.279418 0.179884 0.16669 0.218173 0.16669 0.313488 0.16669 0.218173 0.16669 0.686512 0.16669 0.580853 0.16669 0.686512 0.16669 0.781827 0.16669 0.85747 0.16669 0.781827 0.83331 0.686512 0.83331 0.580853 0.83331 0.686512 0.83331 0.313488 0.83331 0.218173 0.83331 0.313488 0.83331 0.781827 0.83331 0.686512 0.83331 0.781827 0.83331 0.313488 0.83331 0.313488 0.720582 0.093963 0.83331 0.218173 0.83331 0.14253 0.83331 0.218173 0.16669 0.313488 0.16669 0.419147 0.16669 0.313488 0.404377 0.16669 0.279418 0.179884 0.279418 0.179884 0.595623 0.16669 0.720582 0.179884 0.595623 0.16669 0.279418 0.093963 0.720582 0.179884 0.83331 0.218173 0.720582 0.179884 0.16669 0.14253 0.218173 0.14253 0.313488 0.093963 0.313488 0.093963 0.093963 0.313488 0.14253 0.218173 0.14253 0.218173 0.093963 0.686512 0.077229 0.580853 0.16669 0.563744 0.077229 0.580853 0.218173 0.85747 0.14253 0.781827 0.14253 0.781827 0.313488 0.906036 0.419147 0.922771 0.436256 0.83331 0.419147 0.922771 0.781827 0.85747 0.686512 0.906036 0.686512 0.906036 0.906036 0.686512 0.85747 0.781827 0.85747 0.781827 0.906036 0.313488 0.922771 0.419147 0.83331 0.436256 0.922771 0.419147 0.781827 0.14253 0.85747 0.218173 0.85747 0.218173 0.686512 0.093963 0.580853 0.077229 0.580853 0.077229 0.16669 0.563744 0.16669 0.563744 0.83331 0.436256 0.83331 0.436256 0.83331 0.580853 0.922771 0.563744 0.922771 0.5 0.922771 0.563744 0.16669 0.419147 0.077229 0.436256 0.077229 0.5 0.077229 0.436256 0.16669 0.419147 0.16669 0.5 0.16669 0.419147 0.83331 0.580853 0.83331 0.5 0.83331 0.580853 0.83331 0.580853 0.83331 0.580853 0.16669 0.419147 0.16669 0.419147 0.5 0.83331 0.595623 0.83331 0.595623 0.83331 0.5 0.922771 0.595623 0.922771 0.595623 0.922771 0.5 0.16669 0.404377 0.16669 0.404377 0.16669 0.404377 0.83331 0.5 0.83331 0.5 0.83331 0.404377 0.922771 0.5 0.922771 0.5 0.922771 0.595623 0.16669 0.5 0.16669 0.5 0.16669 0.922771 0.436256 0.922771 0.436256 0.077229 0.563744 0.077229 0.563744 0.077229 0.563744 0.077229 0.563744 0.922771 0.436256 0.922771 0.436256 0.16669 0.5 0.16669 0.5 0.5 0.83331 0.5 0.83331 0.83331 0.5 0.83331 0.5 0.5 0.16669 0.5 0.16669</float_array>
+ <technique_common>
+ <accessor source="#RoundedCube-Texture-array" count="409" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="RoundedCube-vertices">
+ <input semantic="POSITION" source="#RoundedCube-positions"/>
+ <input semantic="NORMAL" source="#RoundedCube-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="728">
+ <input semantic="VERTEX" source="#RoundedCube-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#RoundedCube-Texture" offset="1" set="1"/>
+ <p>317 0 0 1 316 2 0 1 1 3 316 2 1 3 2 4 316 2 2 4 3 5 316 2 3 5 4 6 316 2 4 6 5 7 316 2 5 7 343 8 316 2 343 8 6 9 316 2 6 9 7 10 316 2 7 10 8 11 316 2 8 11 9 12 316 2 9 12 10 13 316 2 10 13 11 14 316 2 11 14 326 15 316 2 326 15 12 16 316 2 12 16 13 17 316 2 13 17 14 18 316 2 14 18 15 19 316 2 15 19 16 20 316 2 16 20 17 21 316 2 17 21 318 22 316 2 318 22 18 23 316 2 18 23 19 24 316 2 19 24 20 25 316 2 20 25 21 26 316 2 21 26 22 27 316 2 22 27 23 28 316 2 23 28 317 0 316 2 325 2 264 28 323 0 325 2 265 27 264 28 325 2 266 29 265 27 325 2 267 30 266 29 325 2 268 24 267 30 325 2 269 23 268 24 325 2 346 22 269 23 325 2 270 21 346 22 325 2 271 20 270 21 325 2 272 31 271 20 325 2 273 32 272 31 325 2 274 17 273 32 325 2 275 16 274 17 325 2 329 15 275 16 325 2 276 14 329 15 325 2 277 13 276 14 325 2 278 12 277 13 325 2 279 11 278 12 325 2 280 10 279 11 325 2 281 9 280 10 325 2 324 8 281 9 325 2 282 7 324 8 325 2 283 6 282 7 325 2 284 5 283 6 325 2 285 4 284 5 325 2 286 3 285 4 325 2 287 1 286 3 325 2 323 0 287 1 25 33 1 3 24 34 0 1 24 34 1 3 26 35 27 36 2 4 3 5 2 4 27 36 28 37 29 38 4 6 5 7 4 6 29 38 32 39 8 11 31 40 7 10 31 40 8 11 33 41 34 42 9 12 10 13 9 12 34 42 37 43 13 17 36 44 12 16 36 44 13 17 38 45 39 46 14 18 15 19 14 18 39 46 40 47 41 48 16 20 17 21 16 20 41 48 44 49 20 25 43 50 19 24 43 50 20 25 45 51 46 52 21 26 22 27 21 26 46 52 49 53 25 33 48 54 24 34 48 54 25 33 50 55 51 56 26 35 27 36 26 35 51 56 52 57 53 58 28 37 29 38 28 37 53 58 56 59 32 39 55 60 31 40 55 60 32 39 57 61 58 62 33 41 34 42 33 41 58 62 61 63 37 43 60 64 36 44 60 64 37 43 62 65 63 66 38 45 39 46 38 45 63 66 64 67 65 68 40 47 41 48 40 47 65 68 68 69 44 49 67 70 43 50 67 70 44 49 69 71 70 72 45 51 46 52 45 51 70 72 73 73 49 53 72 74 48 54 72 75 49 53 74 76 75 77 50 55 51 56 50 55 75 77 76 78 77 79 52 57 53 58 52 57 77 79 79 80 80 81 55 60 56 59 55 60 80 81 81 82 82 83 57 61 58 62 57 61 82 83 85 84 61 63 84 85 60 64 84 85 61 63 86 86 87 87 62 65 63 66 62 65 87 87 88 88 89 89 64 67 65 68 64 67 89 89 91 90 92 91 67 70 68 69 67 70 92 91 93 92 94 93 69 71 70 72 69 71 94 93 97 94 73 95 96 96 72 97 96 96 73 98 98 99 99 100 74 101 75 102 74 103 99 100 100 104 101 105 76 106 77 107 76 108 101 105 103 94 104 99 79 109 80 110 79 111 104 99 105 112 106 113 81 114 82 115 81 116 106 113 109 117 85 118 108 119 84 120 108 119 85 121 110 122 111 112 86 123 87 124 86 125 111 112 112 113 113 126 88 127 89 128 88 129 113 126 115 117 116 130 91 131 92 132 91 133 116 130 117 134 118 104 93 135 94 136 93 137 118 104 121 138 97 94 120 139 96 96 120 139 97 94 122 140 123 141 98 99 99 100 98 99 123 141 124 142 125 143 100 104 101 105 100 104 125 143 127 138 128 140 103 94 104 99 103 94 128 140 129 144 130 145 105 146 106 113 105 147 130 145 133 148 109 117 132 149 108 119 132 149 109 117 134 150 135 144 110 151 111 112 110 152 135 144 136 145 137 153 112 113 113 126 112 113 137 153 139 148 140 154 115 117 116 130 115 117 140 154 141 155 142 142 117 156 118 104 117 157 142 142 168 126 169 113 144 153 145 145 144 153 169 113 147 150 146 144 171 122 170 112 171 122 146 144 173 119 149 149 172 117 148 148 172 117 149 149 152 144 151 145 176 112 175 113 176 112 151 145 154 138 153 158 178 94 177 159 178 94 153 160 180 105 181 104 156 143 157 142 156 143 181 104 159 140 158 161 183 99 182 162 183 99 158 163 185 96 161 139 184 94 160 138 184 94 161 139 164 155 163 142 188 134 187 104 188 134 163 142 166 148 165 164 190 117 189 165 190 117 165 166 169 113 168 126 193 115 192 128 193 115 168 126 171 122 170 112 195 123 194 114 195 123 170 112 172 117 196 118 173 119 197 120 173 119 196 118 176 112 175 113 200 114 199 115 200 114 175 113 178 94 177 167 202 168 201 169 202 168 177 170 181 104 180 105 205 171 204 172 205 171 180 105 183 99 182 173 207 169 206 174 207 169 182 175 184 94 208 168 185 96 209 176 185 96 208 168 188 134 187 104 212 177 211 171 212 177 187 104 190 117 189 178 214 118 213 179 214 118 189 180 193 181 192 182 217 72 216 183 217 72 192 184 195 185 194 186 219 69 218 187 219 69 194 188 196 189 220 190 197 191 221 192 197 193 220 190 200 194 199 195 224 66 223 196 224 66 199 197 202 198 201 199 226 63 225 200 226 63 201 201 205 202 204 203 229 62 228 204 229 62 204 205 207 206 206 207 231 59 230 61 231 59 206 208 208 209 232 60 209 210 233 211 209 212 232 60 212 213 211 214 236 56 235 57 236 56 211 215 214 216 213 217 238 53 237 55 238 53 213 218 217 72 216 219 241 52 240 220 241 52 216 221 219 69 218 187 243 49 242 51 243 49 218 187 220 190 244 50 221 192 245 222 221 192 244 50 224 66 223 196 248 46 247 47 248 46 223 196 225 200 249 45 226 63 250 43 226 63 249 45 229 62 228 223 253 42 252 224 253 42 228 225 231 59 230 61 255 39 254 41 255 39 230 61 232 60 256 40 233 211 257 226 233 211 256 40 236 56 235 57 260 36 259 37 260 36 235 57 237 55 261 35 238 53 262 33 238 53 261 35 241 52 240 220 265 27 264 28 265 27 240 220 243 49 242 51 267 30 266 29 267 30 242 51 244 50 268 24 245 222 269 23 245 222 268 24 248 46 247 47 272 31 271 20 272 31 247 47 249 45 273 32 250 43 274 17 250 43 273 32 253 42 252 224 277 13 276 14 277 13 252 224 255 39 254 41 279 11 278 12 279 11 254 41 256 40 280 10 257 226 281 9 257 226 280 10 260 36 259 37 284 5 283 6 284 5 259 37 261 35 285 4 262 33 286 3 262 33 285 4 24 34 0 1 319 227 317 0 319 227 0 1 30 226 6 9 344 228 343 8 344 228 6 9 36 44 12 16 327 229 326 15 327 229 12 16 42 222 18 23 320 230 318 22 320 230 18 23 48 54 24 34 305 231 319 227 305 231 24 34 54 211 30 226 351 232 344 228 351 232 30 226 60 64 36 44 330 233 327 229 330 233 36 44 66 234 42 222 290 235 320 230 290 235 42 222 72 97 48 236 306 235 305 237 306 235 48 238 78 210 54 211 352 239 351 232 352 239 54 211 84 85 60 64 331 240 330 233 331 240 60 64 90 120 66 241 291 232 290 242 291 232 66 243 96 96 72 97 307 230 306 235 307 230 72 97 102 96 78 244 353 230 352 245 353 230 78 246 108 119 84 247 332 228 331 248 332 228 84 249 114 119 90 120 292 228 291 232 292 228 90 120 120 139 96 96 308 22 307 230 308 22 96 96 126 139 102 96 354 22 353 230 354 22 102 96 132 149 108 119 333 8 332 228 333 8 108 119 138 149 114 119 293 8 292 228 293 8 114 119 309 2 341 15 308 22 120 139 308 22 341 15 342 229 349 233 121 138 122 140 121 138 349 233 350 250 355 227 123 251 124 142 123 252 355 227 356 0 357 2 125 143 354 22 125 143 357 2 362 15 363 229 126 139 127 138 126 139 363 229 364 233 365 240 128 140 129 141 128 140 365 240 347 229 348 15 130 145 131 153 130 145 348 15 334 2 335 0 333 8 132 149 333 8 335 0 336 227 303 231 133 148 134 154 133 148 303 231 304 233 301 229 135 144 136 145 135 144 301 229 302 15 294 2 137 153 293 8 137 153 294 2 295 0 296 227 138 149 139 148 138 149 296 227 288 231 289 253 140 154 141 254 140 154 289 253 310 227 311 0 142 142 143 143 142 142 311 0 312 8 144 153 309 2 341 15 309 2 144 153 145 145 146 144 342 229 349 233 342 229 146 144 147 255 148 148 350 256 355 227 350 257 148 148 149 149 358 8 356 0 357 2 356 0 358 8 150 153 151 145 362 15 363 229 362 15 151 145 152 144 153 150 364 233 365 240 364 233 153 150 154 138 155 139 347 229 348 15 347 229 155 139 337 22 156 143 334 2 335 0 334 2 156 143 157 142 158 155 336 227 303 231 336 227 158 155 159 140 160 138 304 233 301 229 304 233 160 138 161 139 297 22 302 15 294 2 302 15 297 22 162 143 163 142 295 0 296 227 295 0 163 142 164 155 165 258 288 231 289 253 288 231 165 258 166 148 167 149 310 227 311 0 310 227 167 149 144 153 312 8 168 126 313 228 168 126 312 8 150 153 358 8 174 126 359 228 174 126 358 8 156 143 337 22 180 105 338 230 180 105 337 22 162 143 297 22 186 105 298 230 186 105 297 22 168 126 313 228 192 128 314 232 192 128 313 228 174 126 359 228 198 128 360 232 198 128 359 228 180 105 338 230 204 172 339 259 204 172 338 230 186 105 298 230 210 172 299 259 210 172 298 230 192 128 314 232 216 260 315 239 216 260 314 232 198 128 360 232 222 260 361 239 222 260 360 232 204 172 339 259 228 261 340 237 228 261 339 259 210 172 299 259 234 261 300 237 234 261 299 259 216 262 315 263 240 220 321 227 240 220 315 264 222 265 361 266 246 48 345 230 246 48 361 267 228 268 340 269 252 224 328 229 252 224 340 270 234 271 300 272 258 38 322 228 258 38 300 273 240 220 321 227 264 28 323 0 264 28 321 227 246 48 345 230 270 21 346 22 270 21 345 230 252 224 328 229 276 14 329 15 276 14 328 229 258 38 322 228 282 7 324 8 282 7 322 228 26 35 2 4 25 33 1 3 25 33 2 4 27 36 28 37 3 5 4 6 3 5 28 37 31 40 7 10 30 226 6 9 30 226 7 10 32 39 33 41 8 11 9 12 8 11 33 41 34 42 35 224 10 13 11 14 10 13 35 224 38 45 14 18 37 43 13 17 37 43 14 18 39 46 40 47 15 19 16 20 15 19 40 47 43 50 19 24 42 222 18 23 42 222 19 24 44 49 45 51 20 25 21 26 20 25 45 51 46 52 47 220 22 27 23 28 22 27 47 220 50 55 26 35 49 53 25 33 49 53 26 35 51 56 52 57 27 36 28 37 27 36 52 57 55 60 31 40 54 211 30 226 54 211 31 40 56 59 57 61 32 39 33 41 32 39 57 61 58 62 59 204 34 42 35 224 34 42 59 204 62 65 38 45 61 63 37 43 61 63 38 45 63 66 64 67 39 46 40 47 39 46 64 67 67 70 43 50 66 234 42 222 66 234 43 50 68 69 69 71 44 49 45 51 44 49 69 71 70 72 71 274 46 52 47 220 46 52 71 274 73 73 74 76 49 53 50 55 49 53 74 76 75 77 76 78 51 56 52 57 51 56 76 78 79 80 55 60 78 210 54 211 78 210 55 60 80 81 81 82 56 59 57 61 56 59 81 82 82 83 83 203 58 62 59 204 58 62 83 203 85 84 86 86 61 63 62 65 61 63 86 86 87 87 88 88 63 66 64 67 63 66 88 88 91 90 67 70 90 275 66 234 90 276 67 70 92 91 93 92 68 69 69 71 68 69 93 92 94 93 95 277 70 72 71 274 70 72 95 277 97 94 98 99 73 278 74 279 73 280 98 99 99 281 100 104 75 282 76 283 75 284 100 104 103 94 79 285 102 96 78 286 102 96 79 287 104 99 105 100 80 288 81 289 80 290 105 100 106 113 107 126 82 291 83 292 82 293 107 126 109 117 110 130 85 294 86 295 85 296 110 130 111 112 112 113 87 297 88 298 87 299 112 113 115 117 91 300 114 119 90 120 114 119 91 301 116 130 117 302 92 303 93 304 92 305 117 302 118 104 119 105 94 306 95 307 94 308 119 105 121 138 122 140 97 94 98 99 97 94 122 140 123 309 124 142 99 310 100 104 99 311 124 142 127 138 103 94 126 139 102 96 126 139 103 94 128 140 129 141 104 99 105 100 104 99 129 141 130 145 131 153 106 113 107 126 106 113 131 153 133 148 134 154 109 117 110 130 109 117 134 154 135 144 136 145 111 112 112 113 111 112 136 145 139 148 115 117 138 149 114 119 138 149 115 117 140 154 141 254 116 130 117 302 116 130 141 254 142 142 143 143 118 104 119 105 118 104 143 143 146 144 145 145 170 112 169 113 170 112 145 145 148 148 147 312 172 117 171 313 172 117 147 314 174 126 175 113 150 153 151 145 150 153 175 113 153 150 152 144 177 122 176 112 177 122 152 144 179 96 155 139 178 94 154 138 178 94 155 139 158 155 157 142 182 134 181 104 182 134 157 142 160 138 159 140 184 94 183 99 184 94 159 140 186 105 187 104 162 143 163 142 162 143 187 104 165 258 164 155 189 315 188 134 189 315 164 155 191 119 167 149 190 117 166 148 190 117 167 149 170 112 169 113 194 114 193 115 194 114 169 113 172 117 171 316 196 118 195 317 196 118 171 318 175 113 174 126 199 115 198 128 199 115 174 126 177 122 176 112 201 123 200 114 201 123 176 112 178 94 202 168 179 96 203 176 179 96 202 168 182 134 181 104 206 177 205 171 206 177 181 104 184 94 183 99 208 168 207 169 208 168 183 99 187 104 186 105 211 171 210 172 211 171 186 105 189 315 188 134 213 319 212 177 213 319 188 134 190 117 214 118 191 119 215 120 191 119 214 118 194 320 193 321 218 187 217 72 218 187 193 322 196 323 195 324 220 190 219 69 220 190 195 325 199 326 198 327 223 196 222 328 223 196 198 329 201 330 200 331 225 200 224 66 225 200 200 332 202 333 226 63 203 334 227 335 203 336 226 63 206 337 205 338 230 61 229 62 230 61 205 339 208 340 207 341 232 60 231 59 232 60 207 342 211 343 210 344 235 57 234 345 235 57 210 346 213 347 212 348 237 55 236 56 237 55 212 349 214 350 238 53 215 351 239 54 215 352 238 53 218 187 217 72 242 51 241 52 242 51 217 72 219 69 243 49 220 190 244 50 220 190 243 49 223 196 222 353 247 47 246 48 247 47 222 354 225 200 224 66 249 45 248 46 249 45 224 66 226 63 250 43 227 335 251 44 227 335 250 43 230 61 229 62 254 41 253 42 254 41 229 62 231 59 255 39 232 60 256 40 232 60 255 39 235 57 234 355 259 37 258 38 259 37 234 356 237 55 236 56 261 35 260 36 261 35 236 56 238 53 262 33 239 54 263 34 239 54 262 33 242 51 241 52 266 29 265 27 266 29 241 52 243 49 267 30 244 50 268 24 244 50 267 30 247 47 246 48 271 20 270 21 271 20 246 48 249 45 248 46 273 32 272 31 273 32 248 46 250 43 274 17 251 44 275 16 251 44 274 17 254 41 253 42 278 12 277 13 278 12 253 42 255 39 279 11 256 40 280 10 256 40 279 11 259 37 258 38 283 6 282 7 283 6 258 38 261 35 260 36 285 4 284 5 285 4 260 36 262 33 286 3 263 34 287 1 263 34 286 3 29 38 344 228 5 7 343 8 5 7 344 228 35 224 327 229 11 14 326 15 11 14 327 229 41 48 320 230 17 21 318 22 17 21 320 230 47 220 319 227 23 28 317 0 23 28 319 227 53 58 351 232 29 38 344 228 29 38 351 232 59 204 330 233 35 224 327 229 35 224 330 233 65 68 290 235 41 48 320 230 41 48 290 235 71 274 305 231 47 220 319 227 47 220 305 231 77 79 352 239 53 58 351 232 53 58 352 239 83 203 331 240 59 204 330 233 59 204 331 240 89 357 291 232 65 358 290 359 65 360 291 232 95 361 306 235 71 362 305 363 71 364 306 235 101 105 353 230 77 365 352 366 77 367 353 230 107 126 332 228 83 368 331 369 83 370 332 228 113 126 292 228 89 371 291 232 89 372 292 228 119 105 307 230 95 373 306 235 95 374 307 230 125 143 354 22 101 105 353 230 101 105 354 22 131 153 333 8 107 126 332 228 107 126 333 8 137 153 293 8 113 126 292 228 113 126 293 8 143 143 308 22 119 105 307 230 119 105 308 22 341 15 342 229 120 139 121 138 120 139 342 229 349 233 350 240 122 140 123 141 122 140 350 240 355 227 356 0 124 142 125 143 124 142 356 0 357 2 362 15 354 22 126 139 354 22 362 15 363 229 364 233 127 138 128 140 127 138 364 233 365 375 347 229 129 376 130 145 129 377 347 229 348 15 334 2 131 153 333 8 131 153 334 2 335 0 336 227 132 149 133 148 132 149 336 227 303 378 304 233 134 379 135 144 134 380 304 233 301 229 302 15 136 145 137 153 136 145 302 15 294 2 295 0 293 8 138 149 293 8 295 0 296 227 288 231 139 148 140 154 139 148 288 231 289 381 310 227 141 382 142 142 141 383 310 227 311 0 309 2 143 143 308 22 143 143 309 2 144 153 145 145 341 15 342 229 341 15 145 145 146 144 147 150 349 233 350 240 349 233 147 150 148 148 149 149 355 227 356 0 355 227 149 149 358 8 150 153 357 2 362 15 357 2 150 153 151 145 152 144 363 229 364 233 363 229 152 144 153 384 154 138 365 385 347 229 365 386 154 138 155 139 337 22 348 15 334 2 348 15 337 22 156 143 157 142 335 0 336 227 335 0 157 142 158 387 159 140 303 388 304 233 303 389 159 140 160 138 161 139 301 229 302 15 301 229 161 139 297 22 162 143 294 2 295 0 294 2 162 143 163 142 164 155 296 227 288 231 296 227 164 155 165 390 166 148 289 391 310 227 289 392 166 148 167 149 312 8 311 0 309 2 311 0 312 8 149 149 173 119 358 8 359 228 358 8 173 119 155 139 179 96 337 22 338 230 337 22 179 96 161 139 185 96 297 22 298 230 297 22 185 96 167 149 191 119 312 8 313 228 312 8 191 119 173 119 197 120 359 228 360 232 359 228 197 120 179 96 203 176 338 230 339 259 338 230 203 176 185 96 209 176 298 230 299 259 298 230 209 176 191 119 215 120 313 228 314 232 313 228 215 120 197 120 221 393 360 232 361 239 360 232 221 394 203 176 227 395 339 259 340 237 339 259 227 396 209 176 233 397 299 259 300 237 299 259 233 398 215 120 239 399 314 232 315 239 314 232 239 400 221 192 245 222 361 401 345 230 361 402 245 222 227 335 251 44 340 403 328 229 340 404 251 44 233 211 257 226 300 405 322 228 300 406 257 226 239 54 263 34 315 407 321 227 315 408 263 34 245 222 269 23 345 230 346 22 345 230 269 23 251 44 275 16 328 229 329 15 328 229 275 16 257 226 281 9 322 228 324 8 322 228 281 9 263 34 287 1 321 227 323 0 321 227 287 1</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="RoundedCube-5">
+ <node id="_RoundedCube" name="RoundedCube" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#RoundedCube">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided-mirroredUVs.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided-mirroredUVs.dae
new file mode 100644
index 00000000..c0364045
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided-mirroredUVs.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-10-16T17:45:36Z</created>
+ <modified>2008-10-16T17:45:36Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="plane" name="plane">
+ <instance_effect url="#plane-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="plane-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane_doubleSided" name="Plane_doubleSided">
+ <mesh>
+ <source id="Plane_doubleSided-positions" name="position">
+ <float_array id="Plane_doubleSided-positions-array" count="24">50 -50 0 -50 -50 0 50 50 0 -50 50 0 -50 -50 0 50 -50 0 -50 50 0 50 50 0</float_array>
+ <technique_common>
+ <accessor source="#Plane_doubleSided-positions-array" count="8" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane_doubleSided-normals" name="normal">
+ <float_array id="Plane_doubleSided-normals-array" count="24">0 0 1 0 0 1 0 0 1 0 0 1 0 0 -1 0 0 -1 0 0 -1 0 0 -1</float_array>
+ <technique_common>
+ <accessor source="#Plane_doubleSided-normals-array" count="8" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane_doubleSided-Texture" name="Texture">
+ <float_array id="Plane_doubleSided-Texture-array" count="8">1 0 0 0 0 1 1 1</float_array>
+ <technique_common>
+ <accessor source="#Plane_doubleSided-Texture-array" count="4" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane_doubleSided-vertices">
+ <input semantic="POSITION" source="#Plane_doubleSided-positions"/>
+ <input semantic="NORMAL" source="#Plane_doubleSided-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="4">
+ <input semantic="VERTEX" source="#Plane_doubleSided-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane_doubleSided-Texture" offset="1" set="1"/>
+ <p>2 0 3 1 0 3 0 3 3 1 1 2 6 0 7 1 4 3 4 3 7 1 5 2</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="_Plane_doubleSided" name="Plane_doubleSided" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane_doubleSided">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#plane"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided.dae
new file mode 100644
index 00000000..b84c198e
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-DoubleSided.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-DoubleSided.mb</source_data>
+ </contributor>
+ <created>2008-10-13T20:21:17Z</created>
+ <modified>2008-10-13T20:21:17Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="plane" name="plane">
+ <instance_effect url="#plane-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="plane-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane_doubleSided" name="Plane_doubleSided">
+ <mesh>
+ <source id="Plane_doubleSided-positions" name="position">
+ <float_array id="Plane_doubleSided-positions-array" count="24">50 -50 0 -50 -50 0 50 50 0 -50 50 0 -50 -50 0 50 -50 0 -50 50 0 50 50 0</float_array>
+ <technique_common>
+ <accessor source="#Plane_doubleSided-positions-array" count="8" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane_doubleSided-normals" name="normal">
+ <float_array id="Plane_doubleSided-normals-array" count="24">0 0 1 0 0 1 0 0 1 0 0 1 0 0 -1 0 0 -1 0 0 -1 0 0 -1</float_array>
+ <technique_common>
+ <accessor source="#Plane_doubleSided-normals-array" count="8" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane_doubleSided-Texture" name="Texture">
+ <float_array id="Plane_doubleSided-Texture-array" count="8">1 1 0 1 0 0 1 0</float_array>
+ <technique_common>
+ <accessor source="#Plane_doubleSided-Texture-array" count="4" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane_doubleSided-vertices">
+ <input semantic="POSITION" source="#Plane_doubleSided-positions"/>
+ <input semantic="NORMAL" source="#Plane_doubleSided-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="4">
+ <input semantic="VERTEX" source="#Plane_doubleSided-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane_doubleSided-Texture" offset="1" set="1"/>
+ <p>2 0 3 1 0 3 0 3 3 1 1 2 6 0 7 1 4 3 4 3 7 1 5 2</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-DoubleSided">
+ <node id="_Plane_doubleSided" name="Plane_doubleSided" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane_doubleSided">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#plane"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-16X16.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-16X16.dae
new file mode 100644
index 00000000..9ca0f7f0
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-16X16.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided-16X16.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:35:55Z</created>
+ <modified>2008-09-19T17:35:55Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane16X16" name="Plane16X16">
+ <mesh>
+ <source id="Plane16X16-positions" name="position">
+ <float_array id="Plane16X16-positions-array" count="867">50 -50 0 -50 -50 0 50 50 0 -50 50 0 0 50 0 -50 0 0 0 -50 0 50 0 0 0 0 0 25 50 0 0 25 0 25 0 0 50 25 0 25 25 0 -50 25 0 -25 0 0 -25 50 0 -25 25 0 -25 -50 0 0 -25 0 -50 -25 0 -25 -25 0 50 -25 0 25 -50 0 25 -25 0 37.5 50 0 25 37.5 0 37.5 25 0 50 37.5 0 37.5 37.5 0 0 37.5 0 12.5 25 0 12.5 50 0 12.5 37.5 0 12.5 0 0 25 12.5 0 0 12.5 0 12.5 12.5 0 50 12.5 0 37.5 0 0 37.5 12.5 0 -50 37.5 0 -37.5 25 0 -25 37.5 0 -37.5 50 0 -37.5 37.5 0 -37.5 0 0 -25 12.5 0 -50 12.5 0 -37.5 12.5 0 -12.5 25 0 -12.5 0 0 -12.5 12.5 0 -12.5 50 0 -12.5 37.5 0 -37.5 -50 0 -25 -37.5 0 -37.5 -25 0 -50 -37.5 0 -37.5 -37.5 0 0 -37.5 0 -12.5 -25 0 -12.5 -50 0 -12.5 -37.5 0 -25 -12.5 0 0 -12.5 0 -12.5 -12.5 0 -50 -12.5 0 -37.5 -12.5 0 50 -37.5 0 37.5 -25 0 25 -37.5 0 37.5 -50 0 37.5 -37.5 0 25 -12.5 0 50 -12.5 0 37.5 -12.5 0 12.5 -25 0 12.5 -12.5 0 12.5 -50 0 12.5 -37.5 0 43.75 50 0 37.5 43.75 0 43.75 37.5 0 50 43.75 0 43.75 43.75 0 25 43.75 0 31.25 37.5 0 31.25 50 0 31.25 43.75 0 31.25 25 0 37.5 31.25 0 25 31.25 0 31.25 31.25 0 50 31.25 0 43.75 25 0 43.75 31.25 0 0 43.75 0 6.25 37.5 0 12.5 43.75 0 6.25 50 0 6.25 43.75 0 6.25 25 0 12.5 31.25 0 0 31.25 0 6.25 31.25 0 18.75 37.5 0 18.75 25 0 18.75 31.25 0 18.75 50 0 18.75 43.75 0 6.25 0 0 12.5 6.25 0 6.25 12.5 0 0 6.25 0 6.25 6.25 0 25 6.25 0 18.75 12.5 0 18.75 0 0 18.75 6.25 0 12.5 18.75 0 25 18.75 0 18.75 18.75 0 0 18.75 0 6.25 18.75 0 50 6.25 0 43.75 12.5 0 37.5 6.25 0 43.75 0 0 43.75 6.25 0 37.5 18.75 0 50 18.75 0 43.75 18.75 0 31.25 12.5 0 31.25 18.75 0 31.25 0 0 31.25 6.25 0 -50 43.75 0 -43.75 37.5 0 -37.5 43.75 0 -43.75 50 0 -43.75 43.75 0 -43.75 25 0 -37.5 31.25 0 -50 31.25 0 -43.75 31.25 0 -25 31.25 0 -31.25 37.5 0 -31.25 25 0 -31.25 31.25 0 -31.25 50 0 -25 43.75 0 -31.25 43.75 0 -43.75 0 0 -37.5 6.25 0 -43.75 12.5 0 -50 6.25 0 -43.75 6.25 0 -25 6.25 0 -31.25 12.5 0 -31.25 0 0 -31.25 6.25 0 -37.5 18.75 0 -25 18.75 0 -31.25 18.75 0 -50 18.75 0 -43.75 18.75 0 -6.25 12.5 0 -12.5 6.25 0 -6.25 0 0 -6.25 6.25 0 -6.25 25 0 -12.5 18.75 0 -6.25 18.75 0 -18.75 12.5 0 -18.75 25 0 -18.75 18.75 0 -18.75 0 0 -18.75 6.25 0 -6.25 50 0 -12.5 43.75 0 -6.25 37.5 0 -6.25 43.75 0 -18.75 37.5 0 -18.75 50 0 -18.75 43.75 0 -12.5 31.25 0 -18.75 31.25 0 -6.25 31.25 0 -43.75 -50 0 -37.5 -43.75 0 -43.75 -37.5 0 -50 -43.75 0 -43.75 -43.75 0 -25 -43.75 0 -31.25 -37.5 0 -31.25 -50 0 -31.25 -43.75 0 -31.25 -25 0 -37.5 -31.25 0 -25 -31.25 0 -31.25 -31.25 0 -50 -31.25 0 -43.75 -25 0 -43.75 -31.25 0 0 -43.75 0 -6.25 -37.5 0 -12.5 -43.75 0 -6.25 -50 0 -6.25 -43.75 0 -6.25 -25 0 -12.5 -31.25 0 0 -31.25 0 -6.25 -31.25 0 -18.75 -37.5 0 -18.75 -25 0 -18.75 -31.25 0 -18.75 -50 0 -18.75 -43.75 0 -12.5 -6.25 0 -6.25 -12.5 0 0 -6.25 0 -6.25 -6.25 0 -25 -6.25 0 -18.75 -12.5 0 -18.75 -6.25 0 -12.5 -18.75 0 -25 -18.75 0 -18.75 -18.75 0 0 -18.75 0 -6.25 -18.75 0 -50 -6.25 0 -43.75 -12.5 0 -37.5 -6.25 0 -43.75 -6.25 0 -37.5 -18.75 0 -50 -18.75 0 -43.75 -18.75 0 -31.25 -12.5 0 -31.25 -18.75 0 -31.25 -6.25 0 50 -43.75 0 43.75 -37.5 0 37.5 -43.75 0 43.75 -50 0 43.75 -43.75 0 43.75 -25 0 37.5 -31.25 0 50 -31.25 0 43.75 -31.25 0 25 -31.25 0 31.25 -37.5 0 31.25 -25 0 31.25 -31.25 0 31.25 -50 0 25 -43.75 0 31.25 -43.75 0 37.5 -6.25 0 43.75 -12.5 0 50 -6.25 0 43.75 -6.25 0 25 -6.25 0 31.25 -12.5 0 31.25 -6.25 0 37.5 -18.75 0 25 -18.75 0 31.25 -18.75 0 50 -18.75 0 43.75 -18.75 0 6.25 -12.5 0 12.5 -6.25 0 6.25 -6.25 0 6.25 -25 0 12.5 -18.75 0 6.25 -18.75 0 18.75 -12.5 0 18.75 -25 0 18.75 -18.75 0 18.75 -6.25 0 6.25 -50 0 12.5 -43.75 0 6.25 -37.5 0 6.25 -43.75 0 18.75 -37.5 0 18.75 -50 0 18.75 -43.75 0 12.5 -31.25 0 18.75 -31.25 0 6.25 -31.25 0</float_array>
+ <technique_common>
+ <accessor source="#Plane16X16-positions-array" count="289" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane16X16-normals" name="normal">
+ <float_array id="Plane16X16-normals-array" count="867">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Plane16X16-normals-array" count="289" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane16X16-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="Plane16X16-Rectangle-UV-array" count="578">0.875 1 0.875 0.9375 0.9375 1 0.9375 0.9375 1 0.875 1 0.9375 0.9375 0.875 0.75 0.875 0.8125 0.875 0.75 0.9375 0.8125 0.9375 0.8125 1 0.875 0.75 0.875 0.8125 0.8125 0.75 0.8125 0.8125 0.75 0.8125 1 0.8125 0.9375 0.8125 0.9375 0.75 0.5 0.875 0.5625 0.875 0.5 0.9375 0.5625 0.9375 0.625 1 0.5625 1 0.625 0.9375 0.625 0.75 0.625 0.8125 0.5625 0.75 0.5625 0.8125 0.5 0.8125 0.6875 0.875 0.6875 0.8125 0.6875 0.75 0.6875 1 0.6875 0.9375 0.625 0.5 0.625 0.5625 0.5625 0.5 0.5625 0.5625 0.5 0.625 0.5 0.5625 0.5625 0.625 0.75 0.625 0.6875 0.625 0.75 0.5625 0.6875 0.5625 0.6875 0.5 0.625 0.6875 0.6875 0.6875 0.75 0.6875 0.5 0.6875 0.5625 0.6875 1 0.625 0.9375 0.625 1 0.5625 0.9375 0.5625 0.875 0.5 0.9375 0.5 0.875 0.5625 0.875 0.6875 0.9375 0.6875 1 0.6875 0.8125 0.625 0.8125 0.6875 0.8125 0.5 0.8125 0.5625 0 0.875 0.0625 0.875 0 0.9375 0.0625 0.9375 0.125 1 0.0625 1 0.125 0.9375 0.125 0.75 0.125 0.8125 0.0625 0.75 0.0625 0.8125 0 0.8125 0.25 0.875 0.1875 0.875 0.25 0.8125 0.1875 0.8125 0.1875 0.75 0.1875 1 0.1875 0.9375 0.25 0.9375 0.125 0.5 0.125 0.5625 0.0625 0.5 0.0625 0.5625 0 0.625 0 0.5625 0.0625 0.625 0.25 0.625 0.1875 0.625 0.25 0.5625 0.1875 0.5625 0.1875 0.5 0.125 0.6875 0.1875 0.6875 0.25 0.6875 0 0.6875 0.0625 0.6875 0.4375 0.625 0.4375 0.5625 0.375 0.5 0.4375 0.5 0.375 0.5625 0.375 0.75 0.375 0.6875 0.4375 0.75 0.4375 0.6875 0.3125 0.625 0.3125 0.6875 0.3125 0.75 0.3125 0.5 0.3125 0.5625 0.375 1 0.375 0.9375 0.4375 1 0.4375 0.9375 0.4375 0.875 0.3125 0.875 0.3125 0.9375 0.3125 1 0.375 0.8125 0.3125 0.8125 0.4375 0.8125 0.125 0 0.125 0.0625 0.0625 0 0.0625 0.0625 0 0.125 0 0.0625 0.0625 0.125 0.25 0.125 0.1875 0.125 0.25 0.0625 0.1875 0.0625 0.1875 0 0.125 0.25 0.125 0.1875 0.1875 0.25 0.1875 0.1875 0.25 0.1875 0 0.1875 0.0625 0.1875 0.0625 0.25 0.5 0.125 0.4375 0.125 0.5 0.0625 0.4375 0.0625 0.375 0 0.4375 0 0.375 0.0625 0.375 0.25 0.375 0.1875 0.4375 0.25 0.4375 0.1875 0.5 0.1875 0.3125 0.125 0.3125 0.1875 0.3125 0.25 0.3125 0 0.3125 0.0625 0.375 0.4375 0.4375 0.4375 0.5 0.375 0.5 0.4375 0.4375 0.375 0.25 0.375 0.3125 0.375 0.25 0.4375 0.3125 0.4375 0.375 0.3125 0.3125 0.3125 0.25 0.3125 0.5 0.3125 0.4375 0.3125 0 0.375 0.0625 0.375 0 0.4375 0.0625 0.4375 0.125 0.4375 0.125 0.3125 0.0625 0.3125 0 0.3125 0.1875 0.375 0.1875 0.3125 0.1875 0.4375 1 0.125 0.9375 0.125 1 0.0625 0.9375 0.0625 0.875 0 0.9375 0 0.875 0.0625 0.875 0.25 0.875 0.1875 0.9375 0.25 0.9375 0.1875 1 0.1875 0.75 0.125 0.8125 0.125 0.75 0.1875 0.8125 0.1875 0.8125 0.25 0.8125 0 0.8125 0.0625 0.75 0.0625 0.875 0.4375 0.9375 0.4375 1 0.375 1 0.4375 0.9375 0.375 0.75 0.375 0.8125 0.375 0.75 0.4375 0.8125 0.4375 0.875 0.3125 0.8125 0.3125 0.75 0.3125 1 0.3125 0.9375 0.3125 0.5625 0.375 0.5625 0.4375 0.625 0.4375 0.625 0.25 0.625 0.3125 0.5625 0.25 0.5625 0.3125 0.6875 0.375 0.6875 0.3125 0.6875 0.25 0.6875 0.4375 0.625 0 0.625 0.0625 0.5625 0 0.5625 0.0625 0.5625 0.125 0.6875 0.125 0.6875 0.0625 0.6875 0 0.625 0.1875 0.6875 0.1875 0.5625 0.1875 1 1 0.875 0.875 0.75 1 0.75 0.75 1 0.75 0.5 1 0.625 0.875 0.5 0.75 0.5 0.5 0.625 0.625 0.75 0.5 1 0.5 0.875 0.625 0 1 0.125 0.875 0 0.75 0.25 0.75 0.25 1 0 0.5 0.125 0.625 0.25 0.5 0.375 0.625 0.375 0.875 0 0 0.125 0.125 0.25 0 0.25 0.25 0 0.25 0.5 0 0.375 0.125 0.5 0.25 0.375 0.375 0.125 0.375 1 0 0.875 0.125 1 0.25 0.75 0.25 0.75 0 0.875 0.375 0.625 0.375 0.625 0.125</float_array>
+ <technique_common>
+ <accessor source="#Plane16X16-Rectangle-UV-array" count="289" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane16X16-vertices">
+ <input semantic="POSITION" source="#Plane16X16-positions"/>
+ <input semantic="NORMAL" source="#Plane16X16-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="512">
+ <input semantic="VERTEX" source="#Plane16X16-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane16X16-Rectangle-UV" offset="1" set="1"/>
+ <p>25 0 82 1 81 2 85 3 81 2 82 1 28 4 84 5 83 6 85 3 83 6 84 5 26 7 87 8 86 9 89 10 86 9 87 8 25 0 88 11 82 1 89 10 82 1 88 11 27 12 91 13 90 14 93 15 90 14 91 13 26 7 92 16 87 8 93 15 87 8 92 16 28 4 83 6 94 17 96 18 94 17 83 6 27 12 95 19 91 13 96 18 91 13 95 19 30 20 98 21 97 22 101 23 97 22 98 21 32 24 100 25 99 26 101 23 99 26 100 25 31 27 103 28 102 29 105 30 102 29 103 28 30 20 104 31 98 21 105 30 98 21 104 31 26 7 106 32 92 16 108 33 92 16 106 32 31 27 107 34 103 28 108 33 103 28 107 34 32 24 99 26 109 35 110 36 109 35 99 26 26 7 86 9 106 32 110 36 106 32 86 9 34 37 112 38 111 39 115 40 111 39 112 38 36 41 114 42 113 43 115 40 113 43 114 42 35 44 117 45 116 46 119 47 116 46 117 45 34 37 118 48 112 38 119 47 112 38 118 48 31 27 120 49 107 34 122 50 107 34 120 49 35 44 121 51 117 45 122 50 117 45 121 51 36 41 113 43 123 52 124 53 123 52 113 43 31 27 102 29 120 49 124 53 120 49 102 29 38 54 126 55 125 56 129 57 125 56 126 55 39 58 128 59 127 60 129 57 127 60 128 59 27 12 130 61 95 19 132 62 95 19 130 61 38 54 131 63 126 55 132 62 126 55 131 63 35 44 133 64 121 51 134 65 121 51 133 64 27 12 90 14 130 61 134 65 130 61 90 14 39 58 127 60 135 66 136 67 135 66 127 60 35 44 116 46 133 64 136 67 133 64 116 46 41 68 138 69 137 70 141 71 137 70 138 69 44 72 140 73 139 74 141 71 139 74 140 73 42 75 143 76 142 77 145 78 142 77 143 76 41 68 144 79 138 69 145 78 138 69 144 79 43 80 147 81 146 82 149 83 146 82 147 81 42 75 148 84 143 76 149 83 143 76 148 84 44 72 139 74 150 85 152 86 150 85 139 74 43 80 151 87 147 81 152 86 147 81 151 87 46 88 154 89 153 90 157 91 153 90 154 89 48 92 156 93 155 94 157 91 155 94 156 93 47 95 159 96 158 97 161 98 158 97 159 96 46 88 160 99 154 89 161 98 154 89 160 99 42 75 162 100 148 84 164 101 148 84 162 100 47 95 163 102 159 96 164 101 159 96 163 102 48 92 155 94 165 103 166 104 165 103 155 94 42 75 142 77 162 100 166 104 162 100 142 77 36 41 167 105 114 42 170 106 114 42 167 105 51 107 169 108 168 109 170 106 168 109 169 108 50 110 172 111 171 112 173 113 171 112 172 111 36 41 123 52 167 105 173 113 167 105 123 52 47 95 174 114 163 102 176 115 163 102 174 114 50 110 175 116 172 111 176 115 172 111 175 116 51 107 168 109 177 117 178 118 177 117 168 109 47 95 158 97 174 114 178 118 174 114 158 97 53 119 180 120 179 121 182 122 179 121 180 120 30 20 97 22 181 123 182 122 181 123 97 22 43 80 183 124 151 87 185 125 151 87 183 124 53 119 184 126 180 120 185 125 180 120 184 126 50 110 186 127 175 116 187 128 175 116 186 127 43 80 146 82 183 124 187 128 183 124 146 82 30 20 181 123 104 31 188 129 104 31 181 123 50 110 171 112 186 127 188 129 186 127 171 112 55 130 190 131 189 132 193 133 189 132 190 131 58 134 192 135 191 136 193 133 191 136 192 135 56 137 195 138 194 139 197 140 194 139 195 138 55 130 196 141 190 131 197 140 190 131 196 141 57 142 199 143 198 144 201 145 198 144 199 143 56 137 200 146 195 138 201 145 195 138 200 146 58 134 191 136 202 147 204 148 202 147 191 136 57 142 203 149 199 143 204 148 199 143 203 149 60 150 206 151 205 152 209 153 205 152 206 151 62 154 208 155 207 156 209 153 207 156 208 155 61 157 211 158 210 159 213 160 210 159 211 158 60 150 212 161 206 151 213 160 206 151 212 161 56 137 214 162 200 146 216 163 200 146 214 162 61 157 215 164 211 158 216 163 211 158 215 164 62 154 207 156 217 165 218 166 217 165 207 156 56 137 194 139 214 162 218 166 214 162 194 139 51 107 219 167 169 108 222 168 169 108 219 167 65 169 221 170 220 171 222 168 220 171 221 170 64 172 224 173 223 174 225 175 223 174 224 173 51 107 177 117 219 167 225 175 219 167 177 117 61 157 226 176 215 164 228 177 215 164 226 176 64 172 227 178 224 173 228 177 224 173 227 178 65 169 220 171 229 179 230 180 229 179 220 171 61 157 210 159 226 176 230 180 226 176 210 159 67 181 232 182 231 183 234 184 231 183 232 182 46 88 153 90 233 185 234 184 233 185 153 90 57 142 235 186 203 149 237 187 203 149 235 186 67 181 236 188 232 182 237 187 232 182 236 188 64 172 238 189 227 178 239 190 227 178 238 189 57 142 198 144 235 186 239 190 235 186 198 144 46 88 233 185 160 99 240 191 160 99 233 185 64 172 223 174 238 189 240 191 238 189 223 174 69 192 242 193 241 194 245 195 241 194 242 193 72 196 244 197 243 198 245 195 243 198 244 197 70 199 247 200 246 201 249 202 246 201 247 200 69 192 248 203 242 193 249 202 242 193 248 203 71 204 251 205 250 206 253 207 250 206 251 205 70 199 252 208 247 200 253 207 247 200 252 208 72 196 243 198 254 209 256 210 254 209 243 198 71 204 255 211 251 205 256 210 251 205 255 211 39 58 257 212 128 59 260 213 128 59 257 212 75 214 259 215 258 216 260 213 258 216 259 215 74 217 262 218 261 219 263 220 261 219 262 218 39 58 135 66 257 212 263 220 257 212 135 66 70 199 264 221 252 208 266 222 252 208 264 221 74 217 265 223 262 218 266 222 262 218 265 223 75 214 258 216 267 224 268 225 267 224 258 216 70 199 246 201 264 221 268 225 264 221 246 201 65 169 269 226 221 170 271 227 221 170 269 226 34 37 111 39 270 228 271 227 270 228 111 39 77 229 273 230 272 231 274 232 272 231 273 230 65 169 229 179 269 226 274 232 269 226 229 179 74 217 275 233 265 223 277 234 265 223 275 233 77 229 276 235 273 230 277 234 273 230 276 235 34 37 270 228 118 48 278 236 118 48 270 228 74 217 261 219 275 233 278 236 275 233 261 219 79 237 280 238 279 239 282 240 279 239 280 238 60 150 205 152 281 241 282 240 281 241 205 152 71 204 283 242 255 211 285 243 255 211 283 242 79 237 284 244 280 238 285 243 280 238 284 244 77 229 286 245 276 235 287 246 276 235 286 245 71 204 250 206 283 242 287 246 283 242 250 206 60 150 281 241 212 161 288 247 212 161 281 241 77 229 272 231 286 245 288 247 286 245 272 231 2 248 81 2 84 5 85 3 84 5 81 2 29 249 83 6 82 1 85 3 82 1 83 6 9 250 86 9 88 11 89 10 88 11 86 9 29 249 82 1 87 8 89 10 87 8 82 1 13 251 90 14 92 16 93 15 92 16 90 14 29 249 87 8 91 13 93 15 91 13 87 8 12 252 94 17 95 19 96 18 95 19 94 17 29 249 91 13 83 6 96 18 83 6 91 13 4 253 97 22 100 25 101 23 100 25 97 22 33 254 99 26 98 21 101 23 98 21 99 26 10 255 102 29 104 31 105 30 104 31 102 29 33 254 98 21 103 28 105 30 103 28 98 21 13 251 92 16 107 34 108 33 107 34 92 16 33 254 103 28 106 32 108 33 106 32 103 28 9 250 109 35 86 9 110 36 86 9 109 35 33 254 106 32 99 26 110 36 99 26 106 32 8 256 111 39 114 42 115 40 114 42 111 39 37 257 113 43 112 38 115 40 112 38 113 43 11 258 116 46 118 48 119 47 118 48 116 46 37 257 112 38 117 45 119 47 117 45 112 38 13 251 107 34 121 51 122 50 121 51 107 34 37 257 117 45 120 49 122 50 120 49 117 45 10 255 123 52 102 29 124 53 102 29 123 52 37 257 120 49 113 43 124 53 113 43 120 49 7 259 125 56 128 59 129 57 128 59 125 56 40 260 127 60 126 55 129 57 126 55 127 60 12 252 95 19 131 63 132 62 131 63 95 19 40 260 126 55 130 61 132 62 130 61 126 55 13 251 121 51 90 14 134 65 90 14 121 51 40 260 130 61 133 64 134 65 133 64 130 61 11 258 135 66 116 46 136 67 116 46 135 66 40 260 133 64 127 60 136 67 127 60 133 64 3 261 137 70 140 73 141 71 140 73 137 70 45 262 139 74 138 69 141 71 138 69 139 74 14 263 142 77 144 79 145 78 144 79 142 77 45 262 138 69 143 76 145 78 143 76 138 69 17 264 146 82 148 84 149 83 148 84 146 82 45 262 143 76 147 81 149 83 147 81 143 76 16 265 150 85 151 87 152 86 151 87 150 85 45 262 147 81 139 74 152 86 139 74 147 81 5 266 153 90 156 93 157 91 156 93 153 90 49 267 155 94 154 89 157 91 154 89 155 94 15 268 158 97 160 99 161 98 160 99 158 97 49 267 154 89 159 96 161 98 159 96 154 89 17 264 148 84 163 102 164 101 163 102 148 84 49 267 159 96 162 100 164 101 162 100 159 96 14 263 165 103 142 77 166 104 142 77 165 103 49 267 162 100 155 94 166 104 155 94 162 100 8 256 114 42 169 108 170 106 169 108 114 42 52 269 168 109 167 105 170 106 167 105 168 109 10 255 171 112 123 52 173 113 123 52 171 112 52 269 167 105 172 111 173 113 172 111 167 105 17 264 163 102 175 116 176 115 175 116 163 102 52 269 172 111 174 114 176 115 174 114 172 111 15 268 177 117 158 97 178 118 158 97 177 117 52 269 174 114 168 109 178 118 168 109 174 114 4 253 179 121 97 22 182 122 97 22 179 121 54 270 181 123 180 120 182 122 180 120 181 123 16 265 151 87 184 126 185 125 184 126 151 87 54 270 180 120 183 124 185 125 183 124 180 120 17 264 175 116 146 82 187 128 146 82 175 116 54 270 183 124 186 127 187 128 186 127 183 124 10 255 104 31 171 112 188 129 171 112 104 31 54 270 186 127 181 123 188 129 181 123 186 127 1 271 189 132 192 135 193 133 192 135 189 132 59 272 191 136 190 131 193 133 190 131 191 136 18 273 194 139 196 141 197 140 196 141 194 139 59 272 190 131 195 138 197 140 195 138 190 131 21 274 198 144 200 146 201 145 200 146 198 144 59 272 195 138 199 143 201 145 199 143 195 138 20 275 202 147 203 149 204 148 203 149 202 147 59 272 199 143 191 136 204 148 191 136 199 143 6 276 205 152 208 155 209 153 208 155 205 152 63 277 207 156 206 151 209 153 206 151 207 156 19 278 210 159 212 161 213 160 212 161 210 159 63 277 206 151 211 158 213 160 211 158 206 151 21 274 200 146 215 164 216 163 215 164 200 146 63 277 211 158 214 162 216 163 214 162 211 158 18 273 217 165 194 139 218 166 194 139 217 165 63 277 214 162 207 156 218 166 207 156 214 162 8 256 169 108 221 170 222 168 221 170 169 108 66 279 220 171 219 167 222 168 219 167 220 171 15 268 223 174 177 117 225 175 177 117 223 174 66 279 219 167 224 173 225 175 224 173 219 167 21 274 215 164 227 178 228 177 227 178 215 164 66 279 224 173 226 176 228 177 226 176 224 173 19 278 229 179 210 159 230 180 210 159 229 179 66 279 226 176 220 171 230 180 220 171 226 176 5 266 231 183 153 90 234 184 153 90 231 183 68 280 233 185 232 182 234 184 232 182 233 185 20 275 203 149 236 188 237 187 236 188 203 149 68 280 232 182 235 186 237 187 235 186 232 182 21 274 227 178 198 144 239 190 198 144 227 178 68 280 235 186 238 189 239 190 238 189 235 186 15 268 160 99 223 174 240 191 223 174 160 99 68 280 238 189 233 185 240 191 233 185 238 189 0 281 241 194 244 197 245 195 244 197 241 194 73 282 243 198 242 193 245 195 242 193 243 198 22 283 246 201 248 203 249 202 248 203 246 201 73 282 242 193 247 200 249 202 247 200 242 193 24 284 250 206 252 208 253 207 252 208 250 206 73 282 247 200 251 205 253 207 251 205 247 200 23 285 254 209 255 211 256 210 255 211 254 209 73 282 251 205 243 198 256 210 243 198 251 205 7 259 128 59 259 215 260 213 259 215 128 59 76 286 258 216 257 212 260 213 257 212 258 216 11 258 261 219 135 66 263 220 135 66 261 219 76 286 257 212 262 218 263 220 262 218 257 212 24 284 252 208 265 223 266 222 265 223 252 208 76 286 262 218 264 221 266 222 264 221 262 218 22 283 267 224 246 201 268 225 246 201 267 224 76 286 264 221 258 216 268 225 258 216 264 221 8 256 221 170 111 39 271 227 111 39 221 170 78 287 270 228 269 226 271 227 269 226 270 228 19 278 272 231 229 179 274 232 229 179 272 231 78 287 269 226 273 230 274 232 273 230 269 226 24 284 265 223 276 235 277 234 276 235 265 223 78 287 273 230 275 233 277 234 275 233 273 230 11 258 118 48 261 219 278 236 261 219 118 48 78 287 275 233 270 228 278 236 270 228 275 233 6 276 279 239 205 152 282 240 205 152 279 239 80 288 281 241 280 238 282 240 280 238 281 241 23 285 255 211 284 244 285 243 284 244 255 211 80 288 280 238 283 242 285 243 283 242 280 238 24 284 276 235 250 206 287 246 250 206 276 235 80 288 283 242 286 245 287 246 286 245 283 242 19 278 212 161 272 231 288 247 272 231 212 161 80 288 286 245 281 241 288 247 281 241 286 245</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided-16X16">
+ <node id="Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane16X16">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-2X2.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-2X2.dae
new file mode 100644
index 00000000..2efa3894
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-2X2.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided-2X2.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:32:28Z</created>
+ <modified>2008-09-19T17:32:28Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane2X2" name="Plane2X2">
+ <mesh>
+ <source id="Plane2X2-positions" name="position">
+ <float_array id="Plane2X2-positions-array" count="27">50 -50 0 -50 -50 0 50 50 0 -50 50 0 0 50 0 -50 0 0 0 -50 0 50 0 0 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#Plane2X2-positions-array" count="9" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane2X2-normals" name="normal">
+ <float_array id="Plane2X2-normals-array" count="27">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Plane2X2-normals-array" count="9" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane2X2-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="Plane2X2-Rectangle-UV-array" count="18">0 1 0 0.5 0.5 1 0.5 0.5 1 0 1 0.5 0.5 0 1 1 0 0</float_array>
+ <technique_common>
+ <accessor source="#Plane2X2-Rectangle-UV-array" count="9" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane2X2-vertices">
+ <input semantic="POSITION" source="#Plane2X2-positions"/>
+ <input semantic="NORMAL" source="#Plane2X2-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="8">
+ <input semantic="VERTEX" source="#Plane2X2-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane2X2-Rectangle-UV" offset="1" set="1"/>
+ <p>3 0 5 1 4 2 8 3 4 2 5 1 0 4 7 5 6 6 8 3 6 6 7 5 2 7 4 2 7 5 8 3 7 5 4 2 1 8 6 6 5 1 8 3 5 1 6 6</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided-2X2">
+ <node id="Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane2X2">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-32X32.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-32X32.dae
new file mode 100644
index 00000000..deebe786
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-32X32.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided-32X32.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:36:33Z</created>
+ <modified>2008-09-19T17:36:33Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane32X32" name="Plane32X32">
+ <mesh>
+ <source id="Plane32X32-positions" name="position">
+ <float_array id="Plane32X32-positions-array" count="3267">50 -50 0 -50 -50 0 50 50 0 -50 50 0 0 50 0 -50 0 0 0 -50 0 50 0 0 0 0 0 25 50 0 0 25 0 25 0 0 50 25 0 25 25 0 -50 25 0 -25 0 0 -25 50 0 -25 25 0 -25 -50 0 0 -25 0 -50 -25 0 -25 -25 0 50 -25 0 25 -50 0 25 -25 0 37.5 50 0 25 37.5 0 37.5 25 0 50 37.5 0 37.5 37.5 0 0 37.5 0 12.5 25 0 12.5 50 0 12.5 37.5 0 12.5 0 0 25 12.5 0 0 12.5 0 12.5 12.5 0 50 12.5 0 37.5 0 0 37.5 12.5 0 -50 37.5 0 -37.5 25 0 -25 37.5 0 -37.5 50 0 -37.5 37.5 0 -37.5 0 0 -25 12.5 0 -50 12.5 0 -37.5 12.5 0 -12.5 25 0 -12.5 0 0 -12.5 12.5 0 -12.5 50 0 -12.5 37.5 0 -37.5 -50 0 -25 -37.5 0 -37.5 -25 0 -50 -37.5 0 -37.5 -37.5 0 0 -37.5 0 -12.5 -25 0 -12.5 -50 0 -12.5 -37.5 0 -25 -12.5 0 0 -12.5 0 -12.5 -12.5 0 -50 -12.5 0 -37.5 -12.5 0 50 -37.5 0 37.5 -25 0 25 -37.5 0 37.5 -50 0 37.5 -37.5 0 25 -12.5 0 50 -12.5 0 37.5 -12.5 0 12.5 -25 0 12.5 -12.5 0 12.5 -50 0 12.5 -37.5 0 43.75 50 0 37.5 43.75 0 43.75 37.5 0 50 43.75 0 43.75 43.75 0 25 43.75 0 31.25 37.5 0 31.25 50 0 31.25 43.75 0 31.25 25 0 37.5 31.25 0 25 31.25 0 31.25 31.25 0 50 31.25 0 43.75 25 0 43.75 31.25 0 0 43.75 0 6.25 37.5 0 12.5 43.75 0 6.25 50 0 6.25 43.75 0 6.25 25 0 12.5 31.25 0 0 31.25 0 6.25 31.25 0 18.75 37.5 0 18.75 25 0 18.75 31.25 0 18.75 50 0 18.75 43.75 0 6.25 0 0 12.5 6.25 0 6.25 12.5 0 0 6.25 0 6.25 6.25 0 25 6.25 0 18.75 12.5 0 18.75 0 0 18.75 6.25 0 12.5 18.75 0 25 18.75 0 18.75 18.75 0 0 18.75 0 6.25 18.75 0 50 6.25 0 43.75 12.5 0 37.5 6.25 0 43.75 0 0 43.75 6.25 0 37.5 18.75 0 50 18.75 0 43.75 18.75 0 31.25 12.5 0 31.25 18.75 0 31.25 0 0 31.25 6.25 0 -50 43.75 0 -43.75 37.5 0 -37.5 43.75 0 -43.75 50 0 -43.75 43.75 0 -43.75 25 0 -37.5 31.25 0 -50 31.25 0 -43.75 31.25 0 -25 31.25 0 -31.25 37.5 0 -31.25 25 0 -31.25 31.25 0 -31.25 50 0 -25 43.75 0 -31.25 43.75 0 -43.75 0 0 -37.5 6.25 0 -43.75 12.5 0 -50 6.25 0 -43.75 6.25 0 -25 6.25 0 -31.25 12.5 0 -31.25 0 0 -31.25 6.25 0 -37.5 18.75 0 -25 18.75 0 -31.25 18.75 0 -50 18.75 0 -43.75 18.75 0 -6.25 12.5 0 -12.5 6.25 0 -6.25 0 0 -6.25 6.25 0 -6.25 25 0 -12.5 18.75 0 -6.25 18.75 0 -18.75 12.5 0 -18.75 25 0 -18.75 18.75 0 -18.75 0 0 -18.75 6.25 0 -6.25 50 0 -12.5 43.75 0 -6.25 37.5 0 -6.25 43.75 0 -18.75 37.5 0 -18.75 50 0 -18.75 43.75 0 -12.5 31.25 0 -18.75 31.25 0 -6.25 31.25 0 -43.75 -50 0 -37.5 -43.75 0 -43.75 -37.5 0 -50 -43.75 0 -43.75 -43.75 0 -25 -43.75 0 -31.25 -37.5 0 -31.25 -50 0 -31.25 -43.75 0 -31.25 -25 0 -37.5 -31.25 0 -25 -31.25 0 -31.25 -31.25 0 -50 -31.25 0 -43.75 -25 0 -43.75 -31.25 0 0 -43.75 0 -6.25 -37.5 0 -12.5 -43.75 0 -6.25 -50 0 -6.25 -43.75 0 -6.25 -25 0 -12.5 -31.25 0 0 -31.25 0 -6.25 -31.25 0 -18.75 -37.5 0 -18.75 -25 0 -18.75 -31.25 0 -18.75 -50 0 -18.75 -43.75 0 -12.5 -6.25 0 -6.25 -12.5 0 0 -6.25 0 -6.25 -6.25 0 -25 -6.25 0 -18.75 -12.5 0 -18.75 -6.25 0 -12.5 -18.75 0 -25 -18.75 0 -18.75 -18.75 0 0 -18.75 0 -6.25 -18.75 0 -50 -6.25 0 -43.75 -12.5 0 -37.5 -6.25 0 -43.75 -6.25 0 -37.5 -18.75 0 -50 -18.75 0 -43.75 -18.75 0 -31.25 -12.5 0 -31.25 -18.75 0 -31.25 -6.25 0 50 -43.75 0 43.75 -37.5 0 37.5 -43.75 0 43.75 -50 0 43.75 -43.75 0 43.75 -25 0 37.5 -31.25 0 50 -31.25 0 43.75 -31.25 0 25 -31.25 0 31.25 -37.5 0 31.25 -25 0 31.25 -31.25 0 31.25 -50 0 25 -43.75 0 31.25 -43.75 0 37.5 -6.25 0 43.75 -12.5 0 50 -6.25 0 43.75 -6.25 0 25 -6.25 0 31.25 -12.5 0 31.25 -6.25 0 37.5 -18.75 0 25 -18.75 0 31.25 -18.75 0 50 -18.75 0 43.75 -18.75 0 6.25 -12.5 0 12.5 -6.25 0 6.25 -6.25 0 6.25 -25 0 12.5 -18.75 0 6.25 -18.75 0 18.75 -12.5 0 18.75 -25 0 18.75 -18.75 0 18.75 -6.25 0 6.25 -50 0 12.5 -43.75 0 6.25 -37.5 0 6.25 -43.75 0 18.75 -37.5 0 18.75 -50 0 18.75 -43.75 0 12.5 -31.25 0 18.75 -31.25 0 6.25 -31.25 0 46.875 50 0 43.75 46.875 0 46.875 43.75 0 50 46.875 0 46.875 46.875 0 37.5 46.875 0 40.625 43.75 0 40.625 50 0 40.625 46.875 0 40.625 37.5 0 43.75 40.625 0 37.5 40.625 0 40.625 40.625 0 50 40.625 0 46.875 37.5 0 46.875 40.625 0 25 46.875 0 28.125 43.75 0 31.25 46.875 0 28.125 50 0 28.125 46.875 0 28.125 37.5 0 31.25 40.625 0 25 40.625 0 28.125 40.625 0 34.375 43.75 0 34.375 37.5 0 34.375 40.625 0 34.375 50 0 34.375 46.875 0 28.125 25 0 31.25 28.125 0 28.125 31.25 0 25 28.125 0 28.125 28.125 0 37.5 28.125 0 34.375 31.25 0 34.375 25 0 34.375 28.125 0 31.25 34.375 0 37.5 34.375 0 34.375 34.375 0 25 34.375 0 28.125 34.375 0 50 28.125 0 46.875 31.25 0 43.75 28.125 0 46.875 25 0 46.875 28.125 0 43.75 34.375 0 50 34.375 0 46.875 34.375 0 40.625 31.25 0 40.625 34.375 0 40.625 25 0 40.625 28.125 0 0 46.875 0 3.125 43.75 0 6.25 46.875 0 3.125 50 0 3.125 46.875 0 3.125 37.5 0 6.25 40.625 0 0 40.625 0 3.125 40.625 0 12.5 40.625 0 9.375 43.75 0 9.375 37.5 0 9.375 40.625 0 9.375 50 0 12.5 46.875 0 9.375 46.875 0 3.125 25 0 6.25 28.125 0 3.125 31.25 0 0 28.125 0 3.125 28.125 0 12.5 28.125 0 9.375 31.25 0 9.375 25 0 9.375 28.125 0 6.25 34.375 0 12.5 34.375 0 9.375 34.375 0 0 34.375 0 3.125 34.375 0 21.875 31.25 0 18.75 28.125 0 21.875 25 0 21.875 28.125 0 21.875 37.5 0 18.75 34.375 0 21.875 34.375 0 15.625 31.25 0 15.625 37.5 0 15.625 34.375 0 15.625 25 0 15.625 28.125 0 21.875 50 0 18.75 46.875 0 21.875 43.75 0 21.875 46.875 0 15.625 43.75 0 15.625 50 0 15.625 46.875 0 18.75 40.625 0 15.625 40.625 0 21.875 40.625 0 3.125 0 0 6.25 3.125 0 3.125 6.25 0 0 3.125 0 3.125 3.125 0 12.5 3.125 0 9.375 6.25 0 9.375 0 0 9.375 3.125 0 9.375 12.5 0 6.25 9.375 0 12.5 9.375 0 9.375 9.375 0 0 9.375 0 3.125 12.5 0 3.125 9.375 0 25 3.125 0 21.875 6.25 0 18.75 3.125 0 21.875 0 0 21.875 3.125 0 21.875 12.5 0 18.75 9.375 0 25 9.375 0 21.875 9.375 0 15.625 6.25 0 15.625 12.5 0 15.625 9.375 0 15.625 0 0 15.625 3.125 0 18.75 21.875 0 21.875 18.75 0 25 21.875 0 21.875 21.875 0 12.5 21.875 0 15.625 18.75 0 15.625 21.875 0 18.75 15.625 0 12.5 15.625 0 15.625 15.625 0 25 15.625 0 21.875 15.625 0 0 21.875 0 3.125 18.75 0 6.25 21.875 0 3.125 21.875 0 6.25 15.625 0 0 15.625 0 3.125 15.625 0 9.375 18.75 0 9.375 15.625 0 9.375 21.875 0 50 3.125 0 46.875 6.25 0 43.75 3.125 0 46.875 0 0 46.875 3.125 0 46.875 12.5 0 43.75 9.375 0 50 9.375 0 46.875 9.375 0 37.5 9.375 0 40.625 6.25 0 40.625 12.5 0 40.625 9.375 0 40.625 0 0 37.5 3.125 0 40.625 3.125 0 43.75 21.875 0 46.875 18.75 0 50 21.875 0 46.875 21.875 0 37.5 21.875 0 40.625 18.75 0 40.625 21.875 0 43.75 15.625 0 37.5 15.625 0 40.625 15.625 0 50 15.625 0 46.875 15.625 0 28.125 18.75 0 31.25 21.875 0 28.125 21.875 0 28.125 12.5 0 31.25 15.625 0 28.125 15.625 0 34.375 18.75 0 34.375 12.5 0 34.375 15.625 0 34.375 21.875 0 28.125 0 0 31.25 3.125 0 28.125 6.25 0 28.125 3.125 0 34.375 6.25 0 34.375 0 0 34.375 3.125 0 31.25 9.375 0 34.375 9.375 0 28.125 9.375 0 -50 46.875 0 -46.875 43.75 0 -43.75 46.875 0 -46.875 50 0 -46.875 46.875 0 -46.875 37.5 0 -43.75 40.625 0 -50 40.625 0 -46.875 40.625 0 -37.5 40.625 0 -40.625 43.75 0 -40.625 37.5 0 -40.625 40.625 0 -40.625 50 0 -37.5 46.875 0 -40.625 46.875 0 -46.875 25 0 -43.75 28.125 0 -46.875 31.25 0 -50 28.125 0 -46.875 28.125 0 -37.5 28.125 0 -40.625 31.25 0 -40.625 25 0 -40.625 28.125 0 -43.75 34.375 0 -37.5 34.375 0 -40.625 34.375 0 -50 34.375 0 -46.875 34.375 0 -25 28.125 0 -28.125 31.25 0 -31.25 28.125 0 -28.125 25 0 -28.125 28.125 0 -28.125 37.5 0 -31.25 34.375 0 -25 34.375 0 -28.125 34.375 0 -34.375 31.25 0 -34.375 37.5 0 -34.375 34.375 0 -34.375 25 0 -34.375 28.125 0 -28.125 50 0 -31.25 46.875 0 -28.125 43.75 0 -25 46.875 0 -28.125 46.875 0 -34.375 43.75 0 -34.375 50 0 -34.375 46.875 0 -31.25 40.625 0 -34.375 40.625 0 -25 40.625 0 -28.125 40.625 0 -46.875 0 0 -43.75 3.125 0 -46.875 6.25 0 -50 3.125 0 -46.875 3.125 0 -37.5 3.125 0 -40.625 6.25 0 -40.625 0 0 -40.625 3.125 0 -40.625 12.5 0 -43.75 9.375 0 -37.5 9.375 0 -40.625 9.375 0 -50 9.375 0 -46.875 12.5 0 -46.875 9.375 0 -25 3.125 0 -28.125 6.25 0 -31.25 3.125 0 -28.125 0 0 -28.125 3.125 0 -28.125 12.5 0 -31.25 9.375 0 -25 9.375 0 -28.125 9.375 0 -34.375 6.25 0 -34.375 12.5 0 -34.375 9.375 0 -34.375 0 0 -34.375 3.125 0 -31.25 21.875 0 -28.125 18.75 0 -25 21.875 0 -28.125 21.875 0 -37.5 21.875 0 -34.375 18.75 0 -34.375 21.875 0 -31.25 15.625 0 -37.5 15.625 0 -34.375 15.625 0 -25 15.625 0 -28.125 15.625 0 -50 21.875 0 -46.875 18.75 0 -43.75 21.875 0 -46.875 21.875 0 -43.75 15.625 0 -50 15.625 0 -46.875 15.625 0 -40.625 18.75 0 -40.625 15.625 0 -40.625 21.875 0 -3.125 6.25 0 -6.25 3.125 0 -3.125 0 0 -3.125 3.125 0 -3.125 12.5 0 -6.25 9.375 0 -3.125 9.375 0 -12.5 9.375 0 -9.375 6.25 0 -9.375 12.5 0 -9.375 9.375 0 -9.375 0 0 -12.5 3.125 0 -9.375 3.125 0 -3.125 25 0 -6.25 21.875 0 -3.125 18.75 0 -3.125 21.875 0 -12.5 21.875 0 -9.375 18.75 0 -9.375 25 0 -9.375 21.875 0 -6.25 15.625 0 -12.5 15.625 0 -9.375 15.625 0 -3.125 15.625 0 -21.875 18.75 0 -18.75 21.875 0 -21.875 25 0 -21.875 21.875 0 -21.875 12.5 0 -18.75 15.625 0 -21.875 15.625 0 -15.625 18.75 0 -15.625 12.5 0 -15.625 15.625 0 -15.625 25 0 -15.625 21.875 0 -21.875 0 0 -18.75 3.125 0 -21.875 6.25 0 -21.875 3.125 0 -15.625 6.25 0 -15.625 0 0 -15.625 3.125 0 -18.75 9.375 0 -15.625 9.375 0 -21.875 9.375 0 -3.125 50 0 -6.25 46.875 0 -3.125 43.75 0 -3.125 46.875 0 -12.5 46.875 0 -9.375 43.75 0 -9.375 50 0 -9.375 46.875 0 -9.375 37.5 0 -6.25 40.625 0 -12.5 40.625 0 -9.375 40.625 0 -3.125 37.5 0 -3.125 40.625 0 -21.875 43.75 0 -18.75 46.875 0 -21.875 50 0 -21.875 46.875 0 -21.875 37.5 0 -18.75 40.625 0 -21.875 40.625 0 -15.625 43.75 0 -15.625 37.5 0 -15.625 40.625 0 -15.625 50 0 -15.625 46.875 0 -18.75 28.125 0 -21.875 31.25 0 -21.875 28.125 0 -12.5 28.125 0 -15.625 31.25 0 -15.625 28.125 0 -18.75 34.375 0 -12.5 34.375 0 -15.625 34.375 0 -21.875 34.375 0 -3.125 31.25 0 -6.25 28.125 0 -3.125 28.125 0 -6.25 34.375 0 -3.125 34.375 0 -9.375 31.25 0 -9.375 34.375 0 -9.375 28.125 0 -46.875 -50 0 -43.75 -46.875 0 -46.875 -43.75 0 -50 -46.875 0 -46.875 -46.875 0 -37.5 -46.875 0 -40.625 -43.75 0 -40.625 -50 0 -40.625 -46.875 0 -40.625 -37.5 0 -43.75 -40.625 0 -37.5 -40.625 0 -40.625 -40.625 0 -50 -40.625 0 -46.875 -37.5 0 -46.875 -40.625 0 -25 -46.875 0 -28.125 -43.75 0 -31.25 -46.875 0 -28.125 -50 0 -28.125 -46.875 0 -28.125 -37.5 0 -31.25 -40.625 0 -25 -40.625 0 -28.125 -40.625 0 -34.375 -43.75 0 -34.375 -37.5 0 -34.375 -40.625 0 -34.375 -50 0 -34.375 -46.875 0 -28.125 -25 0 -31.25 -28.125 0 -28.125 -31.25 0 -25 -28.125 0 -28.125 -28.125 0 -37.5 -28.125 0 -34.375 -31.25 0 -34.375 -25 0 -34.375 -28.125 0 -31.25 -34.375 0 -37.5 -34.375 0 -34.375 -34.375 0 -25 -34.375 0 -28.125 -34.375 0 -50 -28.125 0 -46.875 -31.25 0 -43.75 -28.125 0 -46.875 -25 0 -46.875 -28.125 0 -43.75 -34.375 0 -50 -34.375 0 -46.875 -34.375 0 -40.625 -31.25 0 -40.625 -34.375 0 -40.625 -25 0 -40.625 -28.125 0 0 -46.875 0 -3.125 -43.75 0 -6.25 -46.875 0 -3.125 -50 0 -3.125 -46.875 0 -3.125 -37.5 0 -6.25 -40.625 0 0 -40.625 0 -3.125 -40.625 0 -12.5 -40.625 0 -9.375 -43.75 0 -9.375 -37.5 0 -9.375 -40.625 0 -9.375 -50 0 -12.5 -46.875 0 -9.375 -46.875 0 -3.125 -25 0 -6.25 -28.125 0 -3.125 -31.25 0 0 -28.125 0 -3.125 -28.125 0 -12.5 -28.125 0 -9.375 -31.25 0 -9.375 -25 0 -9.375 -28.125 0 -6.25 -34.375 0 -12.5 -34.375 0 -9.375 -34.375 0 0 -34.375 0 -3.125 -34.375 0 -21.875 -31.25 0 -18.75 -28.125 0 -21.875 -25 0 -21.875 -28.125 0 -21.875 -37.5 0 -18.75 -34.375 0 -21.875 -34.375 0 -15.625 -31.25 0 -15.625 -37.5 0 -15.625 -34.375 0 -15.625 -25 0 -15.625 -28.125 0 -21.875 -50 0 -18.75 -46.875 0 -21.875 -43.75 0 -21.875 -46.875 0 -15.625 -43.75 0 -15.625 -50 0 -15.625 -46.875 0 -18.75 -40.625 0 -15.625 -40.625 0 -21.875 -40.625 0 -6.25 -3.125 0 -3.125 -6.25 0 0 -3.125 0 -3.125 -3.125 0 -12.5 -3.125 0 -9.375 -6.25 0 -9.375 -3.125 0 -9.375 -12.5 0 -6.25 -9.375 0 -12.5 -9.375 0 -9.375 -9.375 0 0 -9.375 0 -3.125 -12.5 0 -3.125 -9.375 0 -25 -3.125 0 -21.875 -6.25 0 -18.75 -3.125 0 -21.875 -3.125 0 -21.875 -12.5 0 -18.75 -9.375 0 -25 -9.375 0 -21.875 -9.375 0 -15.625 -6.25 0 -15.625 -12.5 0 -15.625 -9.375 0 -15.625 -3.125 0 -18.75 -21.875 0 -21.875 -18.75 0 -25 -21.875 0 -21.875 -21.875 0 -12.5 -21.875 0 -15.625 -18.75 0 -15.625 -21.875 0 -18.75 -15.625 0 -12.5 -15.625 0 -15.625 -15.625 0 -25 -15.625 0 -21.875 -15.625 0 0 -21.875 0 -3.125 -18.75 0 -6.25 -21.875 0 -3.125 -21.875 0 -6.25 -15.625 0 0 -15.625 0 -3.125 -15.625 0 -9.375 -18.75 0 -9.375 -15.625 0 -9.375 -21.875 0 -50 -3.125 0 -46.875 -6.25 0 -43.75 -3.125 0 -46.875 -3.125 0 -46.875 -12.5 0 -43.75 -9.375 0 -50 -9.375 0 -46.875 -9.375 0 -37.5 -9.375 0 -40.625 -6.25 0 -40.625 -12.5 0 -40.625 -9.375 0 -37.5 -3.125 0 -40.625 -3.125 0 -43.75 -21.875 0 -46.875 -18.75 0 -50 -21.875 0 -46.875 -21.875 0 -37.5 -21.875 0 -40.625 -18.75 0 -40.625 -21.875 0 -43.75 -15.625 0 -37.5 -15.625 0 -40.625 -15.625 0 -50 -15.625 0 -46.875 -15.625 0 -28.125 -18.75 0 -31.25 -21.875 0 -28.125 -21.875 0 -28.125 -12.5 0 -31.25 -15.625 0 -28.125 -15.625 0 -34.375 -18.75 0 -34.375 -12.5 0 -34.375 -15.625 0 -34.375 -21.875 0 -31.25 -3.125 0 -28.125 -6.25 0 -28.125 -3.125 0 -34.375 -6.25 0 -34.375 -3.125 0 -31.25 -9.375 0 -34.375 -9.375 0 -28.125 -9.375 0 50 -46.875 0 46.875 -43.75 0 43.75 -46.875 0 46.875 -50 0 46.875 -46.875 0 46.875 -37.5 0 43.75 -40.625 0 50 -40.625 0 46.875 -40.625 0 37.5 -40.625 0 40.625 -43.75 0 40.625 -37.5 0 40.625 -40.625 0 40.625 -50 0 37.5 -46.875 0 40.625 -46.875 0 46.875 -25 0 43.75 -28.125 0 46.875 -31.25 0 50 -28.125 0 46.875 -28.125 0 37.5 -28.125 0 40.625 -31.25 0 40.625 -25 0 40.625 -28.125 0 43.75 -34.375 0 37.5 -34.375 0 40.625 -34.375 0 50 -34.375 0 46.875 -34.375 0 25 -28.125 0 28.125 -31.25 0 31.25 -28.125 0 28.125 -25 0 28.125 -28.125 0 28.125 -37.5 0 31.25 -34.375 0 25 -34.375 0 28.125 -34.375 0 34.375 -31.25 0 34.375 -37.5 0 34.375 -34.375 0 34.375 -25 0 34.375 -28.125 0 28.125 -50 0 31.25 -46.875 0 28.125 -43.75 0 25 -46.875 0 28.125 -46.875 0 34.375 -43.75 0 34.375 -50 0 34.375 -46.875 0 31.25 -40.625 0 34.375 -40.625 0 25 -40.625 0 28.125 -40.625 0 43.75 -3.125 0 46.875 -6.25 0 50 -3.125 0 46.875 -3.125 0 37.5 -3.125 0 40.625 -6.25 0 40.625 -3.125 0 40.625 -12.5 0 43.75 -9.375 0 37.5 -9.375 0 40.625 -9.375 0 50 -9.375 0 46.875 -12.5 0 46.875 -9.375 0 25 -3.125 0 28.125 -6.25 0 31.25 -3.125 0 28.125 -3.125 0 28.125 -12.5 0 31.25 -9.375 0 25 -9.375 0 28.125 -9.375 0 34.375 -6.25 0 34.375 -12.5 0 34.375 -9.375 0 34.375 -3.125 0 31.25 -21.875 0 28.125 -18.75 0 25 -21.875 0 28.125 -21.875 0 37.5 -21.875 0 34.375 -18.75 0 34.375 -21.875 0 31.25 -15.625 0 37.5 -15.625 0 34.375 -15.625 0 25 -15.625 0 28.125 -15.625 0 50 -21.875 0 46.875 -18.75 0 43.75 -21.875 0 46.875 -21.875 0 43.75 -15.625 0 50 -15.625 0 46.875 -15.625 0 40.625 -18.75 0 40.625 -15.625 0 40.625 -21.875 0 3.125 -6.25 0 6.25 -3.125 0 3.125 -3.125 0 3.125 -12.5 0 6.25 -9.375 0 3.125 -9.375 0 12.5 -9.375 0 9.375 -6.25 0 9.375 -12.5 0 9.375 -9.375 0 12.5 -3.125 0 9.375 -3.125 0 3.125 -25 0 6.25 -21.875 0 3.125 -18.75 0 3.125 -21.875 0 12.5 -21.875 0 9.375 -18.75 0 9.375 -25 0 9.375 -21.875 0 6.25 -15.625 0 12.5 -15.625 0 9.375 -15.625 0 3.125 -15.625 0 21.875 -18.75 0 18.75 -21.875 0 21.875 -25 0 21.875 -21.875 0 21.875 -12.5 0 18.75 -15.625 0 21.875 -15.625 0 15.625 -18.75 0 15.625 -12.5 0 15.625 -15.625 0 15.625 -25 0 15.625 -21.875 0 18.75 -3.125 0 21.875 -6.25 0 21.875 -3.125 0 15.625 -6.25 0 15.625 -3.125 0 18.75 -9.375 0 15.625 -9.375 0 21.875 -9.375 0 3.125 -50 0 6.25 -46.875 0 3.125 -43.75 0 3.125 -46.875 0 12.5 -46.875 0 9.375 -43.75 0 9.375 -50 0 9.375 -46.875 0 9.375 -37.5 0 6.25 -40.625 0 12.5 -40.625 0 9.375 -40.625 0 3.125 -37.5 0 3.125 -40.625 0 21.875 -43.75 0 18.75 -46.875 0 21.875 -50 0 21.875 -46.875 0 21.875 -37.5 0 18.75 -40.625 0 21.875 -40.625 0 15.625 -43.75 0 15.625 -37.5 0 15.625 -40.625 0 15.625 -50 0 15.625 -46.875 0 18.75 -28.125 0 21.875 -31.25 0 21.875 -28.125 0 12.5 -28.125 0 15.625 -31.25 0 15.625 -28.125 0 18.75 -34.375 0 12.5 -34.375 0 15.625 -34.375 0 21.875 -34.375 0 3.125 -31.25 0 6.25 -28.125 0 3.125 -28.125 0 6.25 -34.375 0 3.125 -34.375 0 9.375 -31.25 0 9.375 -34.375 0 9.375 -28.125 0</float_array>
+ <technique_common>
+ <accessor source="#Plane32X32-positions-array" count="1089" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane32X32-normals" name="normal">
+ <float_array id="Plane32X32-normals-array" count="3267">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Plane32X32-normals-array" count="1089" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane32X32-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="Plane32X32-Rectangle-UV-array" count="2178">1 1 0.96875 1 1 0.96875 0.96875 0.96875 0.9375 0.9375 0.96875 0.9375 0.9375 0.96875 0.875 1 0.875 0.96875 0.90625 1 0.90625 0.96875 0.90625 0.9375 0.875 0.875 0.90625 0.875 0.875 0.90625 0.90625 0.90625 0.9375 0.90625 1 0.875 1 0.90625 0.96875 0.875 0.96875 0.90625 0.75 1 0.75 0.96875 0.78125 1 0.78125 0.96875 0.8125 0.9375 0.8125 0.96875 0.78125 0.9375 0.75 0.875 0.78125 0.875 0.75 0.90625 0.78125 0.90625 0.8125 0.90625 0.84375 0.875 0.84375 0.90625 0.84375 0.9375 0.84375 1 0.84375 0.96875 0.75 0.75 0.78125 0.75 0.75 0.78125 0.78125 0.78125 0.8125 0.8125 0.78125 0.8125 0.8125 0.78125 0.875 0.75 0.875 0.78125 0.84375 0.75 0.84375 0.78125 0.84375 0.8125 0.875 0.84375 0.84375 0.84375 0.8125 0.84375 0.75 0.84375 0.78125 0.84375 1 0.75 1 0.78125 0.96875 0.75 0.96875 0.78125 0.9375 0.8125 0.9375 0.78125 0.96875 0.8125 1 0.84375 0.96875 0.84375 0.9375 0.84375 0.90625 0.84375 0.90625 0.8125 0.90625 0.75 0.90625 0.78125 0.5 1 0.5 0.96875 0.53125 1 0.53125 0.96875 0.5625 0.9375 0.5625 0.96875 0.53125 0.9375 0.5 0.875 0.53125 0.875 0.5 0.90625 0.53125 0.90625 0.5625 0.90625 0.625 0.875 0.625 0.90625 0.59375 0.875 0.59375 0.90625 0.59375 0.9375 0.625 1 0.59375 1 0.625 0.96875 0.59375 0.96875 0.5 0.75 0.53125 0.75 0.5 0.78125 0.53125 0.78125 0.5625 0.8125 0.53125 0.8125 0.5625 0.78125 0.625 0.75 0.625 0.78125 0.59375 0.75 0.59375 0.78125 0.59375 0.8125 0.625 0.84375 0.59375 0.84375 0.5625 0.84375 0.5 0.84375 0.53125 0.84375 0.71875 0.75 0.71875 0.78125 0.6875 0.8125 0.6875 0.78125 0.71875 0.8125 0.71875 0.875 0.71875 0.84375 0.6875 0.84375 0.65625 0.875 0.65625 0.84375 0.65625 0.8125 0.65625 0.75 0.65625 0.78125 0.71875 1 0.71875 0.96875 0.6875 0.9375 0.71875 0.9375 0.6875 0.96875 0.65625 1 0.65625 0.96875 0.65625 0.9375 0.65625 0.90625 0.6875 0.90625 0.71875 0.90625 0.5 0.5 0.53125 0.5 0.5 0.53125 0.53125 0.53125 0.5625 0.5625 0.53125 0.5625 0.5625 0.53125 0.625 0.5 0.625 0.53125 0.59375 0.5 0.59375 0.53125 0.59375 0.5625 0.625 0.625 0.59375 0.625 0.625 0.59375 0.59375 0.59375 0.5625 0.59375 0.5 0.625 0.5 0.59375 0.53125 0.625 0.53125 0.59375 0.75 0.5 0.75 0.53125 0.71875 0.5 0.71875 0.53125 0.6875 0.5625 0.6875 0.53125 0.71875 0.5625 0.75 0.625 0.71875 0.625 0.75 0.59375 0.71875 0.59375 0.6875 0.59375 0.65625 0.625 0.65625 0.59375 0.65625 0.5625 0.65625 0.5 0.65625 0.53125 0.75 0.71875 0.71875 0.71875 0.6875 0.6875 0.71875 0.6875 0.6875 0.71875 0.625 0.71875 0.65625 0.71875 0.65625 0.6875 0.625 0.65625 0.65625 0.65625 0.6875 0.65625 0.75 0.65625 0.71875 0.65625 0.5 0.71875 0.53125 0.71875 0.5625 0.6875 0.5625 0.71875 0.53125 0.6875 0.5 0.65625 0.53125 0.65625 0.5625 0.65625 0.59375 0.65625 0.59375 0.6875 0.59375 0.71875 1 0.5 1 0.53125 0.96875 0.5 0.96875 0.53125 0.9375 0.5625 0.9375 0.53125 0.96875 0.5625 1 0.625 0.96875 0.625 1 0.59375 0.96875 0.59375 0.9375 0.59375 0.875 0.625 0.875 0.59375 0.90625 0.625 0.90625 0.59375 0.90625 0.5625 0.875 0.5 0.90625 0.5 0.875 0.53125 0.90625 0.53125 1 0.71875 0.96875 0.71875 0.9375 0.6875 0.96875 0.6875 0.9375 0.71875 0.875 0.71875 0.90625 0.71875 0.90625 0.6875 0.875 0.65625 0.90625 0.65625 0.9375 0.65625 1 0.65625 0.96875 0.65625 0.78125 0.71875 0.8125 0.6875 0.8125 0.71875 0.78125 0.6875 0.78125 0.625 0.78125 0.65625 0.8125 0.65625 0.84375 0.625 0.84375 0.65625 0.84375 0.6875 0.84375 0.71875 0.78125 0.5 0.78125 0.53125 0.8125 0.5625 0.78125 0.5625 0.8125 0.53125 0.84375 0.5 0.84375 0.53125 0.84375 0.5625 0.84375 0.59375 0.8125 0.59375 0.78125 0.59375 0 1 0 0.96875 0.03125 1 0.03125 0.96875 0.0625 0.9375 0.0625 0.96875 0.03125 0.9375 0 0.875 0.03125 0.875 0 0.90625 0.03125 0.90625 0.0625 0.90625 0.125 0.875 0.125 0.90625 0.09375 0.875 0.09375 0.90625 0.09375 0.9375 0.125 1 0.09375 1 0.125 0.96875 0.09375 0.96875 0 0.75 0.03125 0.75 0 0.78125 0.03125 0.78125 0.0625 0.8125 0.03125 0.8125 0.0625 0.78125 0.125 0.75 0.125 0.78125 0.09375 0.75 0.09375 0.78125 0.09375 0.8125 0.125 0.84375 0.09375 0.84375 0.0625 0.84375 0 0.84375 0.03125 0.84375 0.25 0.75 0.25 0.78125 0.21875 0.75 0.21875 0.78125 0.1875 0.8125 0.1875 0.78125 0.21875 0.8125 0.25 0.875 0.21875 0.875 0.25 0.84375 0.21875 0.84375 0.1875 0.84375 0.15625 0.875 0.15625 0.84375 0.15625 0.8125 0.15625 0.75 0.15625 0.78125 0.25 1 0.21875 1 0.25 0.96875 0.21875 0.96875 0.1875 0.9375 0.21875 0.9375 0.1875 0.96875 0.15625 1 0.15625 0.96875 0.15625 0.9375 0.15625 0.90625 0.1875 0.90625 0.25 0.90625 0.21875 0.90625 0 0.5 0.03125 0.5 0 0.53125 0.03125 0.53125 0.0625 0.5625 0.03125 0.5625 0.0625 0.53125 0.125 0.5 0.125 0.53125 0.09375 0.5 0.09375 0.53125 0.09375 0.5625 0.125 0.625 0.09375 0.625 0.125 0.59375 0.09375 0.59375 0.0625 0.59375 0 0.625 0 0.59375 0.03125 0.625 0.03125 0.59375 0.25 0.5 0.25 0.53125 0.21875 0.5 0.21875 0.53125 0.1875 0.5625 0.1875 0.53125 0.21875 0.5625 0.25 0.625 0.21875 0.625 0.25 0.59375 0.21875 0.59375 0.1875 0.59375 0.15625 0.625 0.15625 0.59375 0.15625 0.5625 0.15625 0.5 0.15625 0.53125 0.25 0.71875 0.21875 0.71875 0.1875 0.6875 0.21875 0.6875 0.1875 0.71875 0.125 0.71875 0.15625 0.71875 0.15625 0.6875 0.125 0.65625 0.15625 0.65625 0.1875 0.65625 0.25 0.65625 0.21875 0.65625 0 0.71875 0.03125 0.71875 0.0625 0.6875 0.0625 0.71875 0.03125 0.6875 0 0.65625 0.03125 0.65625 0.0625 0.65625 0.09375 0.65625 0.09375 0.6875 0.09375 0.71875 0.46875 0.5 0.46875 0.53125 0.4375 0.5625 0.4375 0.53125 0.46875 0.5625 0.46875 0.625 0.46875 0.59375 0.4375 0.59375 0.375 0.625 0.375 0.59375 0.40625 0.625 0.40625 0.59375 0.40625 0.5625 0.375 0.5 0.40625 0.5 0.375 0.53125 0.40625 0.53125 0.46875 0.75 0.46875 0.71875 0.4375 0.6875 0.46875 0.6875 0.4375 0.71875 0.375 0.75 0.375 0.71875 0.40625 0.75 0.40625 0.71875 0.40625 0.6875 0.375 0.65625 0.40625 0.65625 0.4375 0.65625 0.46875 0.65625 0.28125 0.75 0.28125 0.71875 0.3125 0.6875 0.3125 0.71875 0.28125 0.6875 0.28125 0.625 0.28125 0.65625 0.3125 0.65625 0.34375 0.625 0.34375 0.65625 0.34375 0.6875 0.34375 0.75 0.34375 0.71875 0.28125 0.5 0.28125 0.53125 0.3125 0.5625 0.28125 0.5625 0.3125 0.53125 0.34375 0.5 0.34375 0.53125 0.34375 0.5625 0.34375 0.59375 0.3125 0.59375 0.28125 0.59375 0.46875 1 0.46875 0.96875 0.4375 0.9375 0.46875 0.9375 0.4375 0.96875 0.375 1 0.375 0.96875 0.40625 1 0.40625 0.96875 0.40625 0.9375 0.375 0.875 0.40625 0.875 0.375 0.90625 0.40625 0.90625 0.4375 0.90625 0.46875 0.875 0.46875 0.90625 0.28125 1 0.28125 0.96875 0.3125 0.9375 0.3125 0.96875 0.28125 0.9375 0.28125 0.875 0.28125 0.90625 0.3125 0.90625 0.34375 0.875 0.34375 0.90625 0.34375 0.9375 0.34375 1 0.34375 0.96875 0.28125 0.78125 0.3125 0.8125 0.28125 0.8125 0.3125 0.78125 0.375 0.78125 0.34375 0.78125 0.34375 0.8125 0.375 0.84375 0.34375 0.84375 0.3125 0.84375 0.28125 0.84375 0.46875 0.78125 0.4375 0.8125 0.4375 0.78125 0.46875 0.8125 0.46875 0.84375 0.4375 0.84375 0.40625 0.84375 0.40625 0.8125 0.40625 0.78125 0 0 0.03125 0 0 0.03125 0.03125 0.03125 0.0625 0.0625 0.03125 0.0625 0.0625 0.03125 0.125 0 0.125 0.03125 0.09375 0 0.09375 0.03125 0.09375 0.0625 0.125 0.125 0.09375 0.125 0.125 0.09375 0.09375 0.09375 0.0625 0.09375 0 0.125 0 0.09375 0.03125 0.125 0.03125 0.09375 0.25 0 0.25 0.03125 0.21875 0 0.21875 0.03125 0.1875 0.0625 0.1875 0.03125 0.21875 0.0625 0.25 0.125 0.21875 0.125 0.25 0.09375 0.21875 0.09375 0.1875 0.09375 0.15625 0.125 0.15625 0.09375 0.15625 0.0625 0.15625 0 0.15625 0.03125 0.25 0.25 0.21875 0.25 0.25 0.21875 0.21875 0.21875 0.1875 0.1875 0.21875 0.1875 0.1875 0.21875 0.125 0.25 0.125 0.21875 0.15625 0.25 0.15625 0.21875 0.15625 0.1875 0.125 0.15625 0.15625 0.15625 0.1875 0.15625 0.25 0.15625 0.21875 0.15625 0 0.25 0 0.21875 0.03125 0.25 0.03125 0.21875 0.0625 0.1875 0.0625 0.21875 0.03125 0.1875 0 0.15625 0.03125 0.15625 0.0625 0.15625 0.09375 0.15625 0.09375 0.1875 0.09375 0.25 0.09375 0.21875 0.5 0 0.5 0.03125 0.46875 0 0.46875 0.03125 0.4375 0.0625 0.4375 0.03125 0.46875 0.0625 0.5 0.125 0.46875 0.125 0.5 0.09375 0.46875 0.09375 0.4375 0.09375 0.375 0.125 0.375 0.09375 0.40625 0.125 0.40625 0.09375 0.40625 0.0625 0.375 0 0.40625 0 0.375 0.03125 0.40625 0.03125 0.5 0.25 0.46875 0.25 0.5 0.21875 0.46875 0.21875 0.4375 0.1875 0.46875 0.1875 0.4375 0.21875 0.375 0.25 0.375 0.21875 0.40625 0.25 0.40625 0.21875 0.40625 0.1875 0.375 0.15625 0.40625 0.15625 0.4375 0.15625 0.5 0.15625 0.46875 0.15625 0.28125 0.25 0.28125 0.21875 0.3125 0.1875 0.3125 0.21875 0.28125 0.1875 0.28125 0.125 0.28125 0.15625 0.3125 0.15625 0.34375 0.125 0.34375 0.15625 0.34375 0.1875 0.34375 0.25 0.34375 0.21875 0.28125 0 0.28125 0.03125 0.3125 0.0625 0.28125 0.0625 0.3125 0.03125 0.34375 0 0.34375 0.03125 0.34375 0.0625 0.34375 0.09375 0.3125 0.09375 0.28125 0.09375 0.5 0.46875 0.46875 0.46875 0.4375 0.4375 0.46875 0.4375 0.4375 0.46875 0.375 0.46875 0.40625 0.46875 0.40625 0.4375 0.375 0.375 0.40625 0.375 0.375 0.40625 0.40625 0.40625 0.4375 0.40625 0.5 0.375 0.5 0.40625 0.46875 0.375 0.46875 0.40625 0.25 0.46875 0.28125 0.46875 0.3125 0.4375 0.3125 0.46875 0.28125 0.4375 0.25 0.375 0.28125 0.375 0.25 0.40625 0.28125 0.40625 0.3125 0.40625 0.34375 0.375 0.34375 0.40625 0.34375 0.4375 0.34375 0.46875 0.25 0.28125 0.28125 0.28125 0.3125 0.3125 0.28125 0.3125 0.3125 0.28125 0.375 0.28125 0.34375 0.28125 0.34375 0.3125 0.375 0.34375 0.34375 0.34375 0.3125 0.34375 0.25 0.34375 0.28125 0.34375 0.5 0.28125 0.46875 0.28125 0.4375 0.3125 0.4375 0.28125 0.46875 0.3125 0.5 0.34375 0.46875 0.34375 0.4375 0.34375 0.40625 0.34375 0.40625 0.3125 0.40625 0.28125 0 0.46875 0.03125 0.46875 0.0625 0.4375 0.0625 0.46875 0.03125 0.4375 0 0.375 0.03125 0.375 0 0.40625 0.03125 0.40625 0.0625 0.40625 0.125 0.375 0.125 0.40625 0.09375 0.375 0.09375 0.40625 0.09375 0.4375 0.125 0.46875 0.09375 0.46875 0 0.28125 0.03125 0.28125 0.0625 0.3125 0.03125 0.3125 0.0625 0.28125 0.125 0.28125 0.09375 0.28125 0.09375 0.3125 0.125 0.34375 0.09375 0.34375 0.0625 0.34375 0 0.34375 0.03125 0.34375 0.21875 0.28125 0.1875 0.3125 0.1875 0.28125 0.21875 0.3125 0.21875 0.375 0.21875 0.34375 0.1875 0.34375 0.15625 0.375 0.15625 0.34375 0.15625 0.3125 0.15625 0.28125 0.21875 0.46875 0.1875 0.4375 0.21875 0.4375 0.1875 0.46875 0.15625 0.46875 0.15625 0.4375 0.15625 0.40625 0.1875 0.40625 0.21875 0.40625 1 0 1 0.03125 0.96875 0 0.96875 0.03125 0.9375 0.0625 0.9375 0.03125 0.96875 0.0625 1 0.125 0.96875 0.125 1 0.09375 0.96875 0.09375 0.9375 0.09375 0.875 0.125 0.875 0.09375 0.90625 0.125 0.90625 0.09375 0.90625 0.0625 0.875 0 0.90625 0 0.875 0.03125 0.90625 0.03125 1 0.25 0.96875 0.25 1 0.21875 0.96875 0.21875 0.9375 0.1875 0.96875 0.1875 0.9375 0.21875 0.875 0.25 0.875 0.21875 0.90625 0.25 0.90625 0.21875 0.90625 0.1875 0.875 0.15625 0.90625 0.15625 0.9375 0.15625 1 0.15625 0.96875 0.15625 0.75 0.25 0.75 0.21875 0.78125 0.25 0.78125 0.21875 0.8125 0.1875 0.8125 0.21875 0.78125 0.1875 0.75 0.125 0.78125 0.125 0.75 0.15625 0.78125 0.15625 0.8125 0.15625 0.84375 0.125 0.84375 0.15625 0.84375 0.1875 0.84375 0.25 0.84375 0.21875 0.75 0 0.78125 0 0.75 0.03125 0.78125 0.03125 0.8125 0.0625 0.78125 0.0625 0.8125 0.03125 0.84375 0 0.84375 0.03125 0.84375 0.0625 0.84375 0.09375 0.8125 0.09375 0.75 0.09375 0.78125 0.09375 1 0.46875 0.96875 0.46875 0.9375 0.4375 0.96875 0.4375 0.9375 0.46875 0.875 0.46875 0.90625 0.46875 0.90625 0.4375 0.875 0.375 0.90625 0.375 0.875 0.40625 0.90625 0.40625 0.9375 0.40625 1 0.375 1 0.40625 0.96875 0.375 0.96875 0.40625 0.75 0.46875 0.78125 0.46875 0.8125 0.4375 0.8125 0.46875 0.78125 0.4375 0.75 0.375 0.78125 0.375 0.75 0.40625 0.78125 0.40625 0.8125 0.40625 0.84375 0.375 0.84375 0.40625 0.84375 0.4375 0.84375 0.46875 0.75 0.28125 0.78125 0.28125 0.8125 0.3125 0.78125 0.3125 0.8125 0.28125 0.875 0.28125 0.84375 0.28125 0.84375 0.3125 0.875 0.34375 0.84375 0.34375 0.8125 0.34375 0.75 0.34375 0.78125 0.34375 1 0.28125 0.96875 0.28125 0.9375 0.3125 0.9375 0.28125 0.96875 0.3125 1 0.34375 0.96875 0.34375 0.9375 0.34375 0.90625 0.34375 0.90625 0.3125 0.90625 0.28125 0.53125 0.46875 0.5625 0.4375 0.5625 0.46875 0.53125 0.4375 0.53125 0.375 0.53125 0.40625 0.5625 0.40625 0.625 0.375 0.625 0.40625 0.59375 0.375 0.59375 0.40625 0.59375 0.4375 0.625 0.46875 0.59375 0.46875 0.53125 0.25 0.53125 0.28125 0.5625 0.3125 0.53125 0.3125 0.5625 0.28125 0.625 0.25 0.625 0.28125 0.59375 0.25 0.59375 0.28125 0.59375 0.3125 0.625 0.34375 0.59375 0.34375 0.5625 0.34375 0.53125 0.34375 0.71875 0.25 0.71875 0.28125 0.6875 0.3125 0.6875 0.28125 0.71875 0.3125 0.71875 0.375 0.71875 0.34375 0.6875 0.34375 0.65625 0.375 0.65625 0.34375 0.65625 0.3125 0.65625 0.25 0.65625 0.28125 0.71875 0.46875 0.6875 0.4375 0.71875 0.4375 0.6875 0.46875 0.65625 0.46875 0.65625 0.4375 0.65625 0.40625 0.6875 0.40625 0.71875 0.40625 0.53125 0 0.53125 0.03125 0.5625 0.0625 0.53125 0.0625 0.5625 0.03125 0.625 0 0.625 0.03125 0.59375 0 0.59375 0.03125 0.59375 0.0625 0.625 0.125 0.59375 0.125 0.625 0.09375 0.59375 0.09375 0.5625 0.09375 0.53125 0.125 0.53125 0.09375 0.71875 0 0.71875 0.03125 0.6875 0.0625 0.6875 0.03125 0.71875 0.0625 0.71875 0.125 0.71875 0.09375 0.6875 0.09375 0.65625 0.125 0.65625 0.09375 0.65625 0.0625 0.65625 0 0.65625 0.03125 0.71875 0.21875 0.6875 0.1875 0.71875 0.1875 0.6875 0.21875 0.625 0.21875 0.65625 0.21875 0.65625 0.1875 0.625 0.15625 0.65625 0.15625 0.6875 0.15625 0.71875 0.15625 0.53125 0.21875 0.5625 0.1875 0.5625 0.21875 0.53125 0.1875 0.53125 0.15625 0.5625 0.15625 0.59375 0.15625 0.59375 0.1875 0.59375 0.21875 0.9375 1 1 0.9375 0.875 0.9375 0.9375 0.875 0.75 0.9375 0.8125 1 0.8125 0.875 0.8125 0.75 0.75 0.8125 0.875 0.8125 1 0.8125 0.9375 0.75 0.5 0.9375 0.5625 1 0.5625 0.875 0.625 0.9375 0.5625 0.75 0.5 0.8125 0.625 0.8125 0.6875 0.75 0.6875 0.875 0.6875 1 0.5625 0.5 0.5 0.5625 0.625 0.5625 0.5625 0.625 0.75 0.5625 0.6875 0.5 0.6875 0.625 0.75 0.6875 0.625 0.6875 0.5 0.6875 1 0.5625 0.9375 0.5 0.9375 0.625 0.875 0.5625 1 0.6875 0.875 0.6875 0.8125 0.625 0.8125 0.5 0 0.9375 0.0625 1 0.0625 0.875 0.125 0.9375 0.0625 0.75 0 0.8125 0.125 0.8125 0.25 0.8125 0.1875 0.75 0.1875 0.875 0.1875 1 0.25 0.9375 0.0625 0.5 0 0.5625 0.125 0.5625 0.0625 0.625 0.25 0.5625 0.1875 0.5 0.1875 0.625 0.25 0.6875 0.125 0.6875 0 0.6875 0.4375 0.5 0.4375 0.625 0.375 0.5625 0.4375 0.75 0.375 0.6875 0.3125 0.75 0.3125 0.625 0.3125 0.5 0.4375 1 0.375 0.9375 0.4375 0.875 0.3125 1 0.3125 0.875 0.375 0.8125 0.0625 0 0 0.0625 0.125 0.0625 0.0625 0.125 0.25 0.0625 0.1875 0 0.1875 0.125 0.1875 0.25 0.25 0.1875 0.125 0.1875 0 0.1875 0.0625 0.25 0.5 0.0625 0.4375 0 0.4375 0.125 0.375 0.0625 0.4375 0.25 0.5 0.1875 0.375 0.1875 0.3125 0.25 0.3125 0.125 0.3125 0 0.5 0.4375 0.375 0.4375 0.4375 0.375 0.25 0.4375 0.3125 0.375 0.25 0.3125 0.375 0.3125 0.5 0.3125 0 0.4375 0.0625 0.375 0.125 0.4375 0 0.3125 0.125 0.3125 0.1875 0.375 1 0.0625 0.9375 0 0.9375 0.125 0.875 0.0625 0.9375 0.25 1 0.1875 0.875 0.1875 0.75 0.1875 0.8125 0.25 0.8125 0.125 0.8125 0 0.75 0.0625 1 0.4375 0.875 0.4375 0.9375 0.375 0.75 0.4375 0.8125 0.375 0.75 0.3125 0.875 0.3125 1 0.3125 0.5625 0.375 0.625 0.4375 0.5625 0.25 0.625 0.3125 0.6875 0.25 0.6875 0.375 0.5625 0 0.625 0.0625 0.5625 0.125 0.6875 0 0.6875 0.125 0.625 0.1875</float_array>
+ <technique_common>
+ <accessor source="#Plane32X32-Rectangle-UV-array" count="1089" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane32X32-vertices">
+ <input semantic="POSITION" source="#Plane32X32-positions"/>
+ <input semantic="NORMAL" source="#Plane32X32-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="2048">
+ <input semantic="VERTEX" source="#Plane32X32-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane32X32-Rectangle-UV" offset="1" set="1"/>
+ <p>2 0 289 1 292 2 293 3 292 2 289 1 85 4 291 5 290 6 293 3 290 6 291 5 25 7 294 8 296 9 297 10 296 9 294 8 85 4 290 6 295 11 297 10 295 11 290 6 29 12 298 13 300 14 301 15 300 14 298 13 85 4 295 11 299 16 301 15 299 16 295 11 28 17 302 18 303 19 304 20 303 19 302 18 85 4 299 16 291 5 304 20 291 5 299 16 9 21 305 22 308 23 309 24 308 23 305 22 89 25 307 26 306 27 309 24 306 27 307 26 26 28 310 29 312 30 313 31 312 30 310 29 89 25 306 27 311 32 313 31 311 32 306 27 29 12 300 14 315 33 316 34 315 33 300 14 89 25 311 32 314 35 316 34 314 35 311 32 25 7 317 36 294 8 318 37 294 8 317 36 89 25 314 35 307 26 318 37 307 26 314 35 13 38 319 39 322 40 323 41 322 40 319 39 93 42 321 43 320 44 323 41 320 44 321 43 27 45 324 46 326 47 327 48 326 47 324 46 93 42 320 44 325 49 327 48 325 49 320 44 29 12 315 33 329 50 330 51 329 50 315 33 93 42 325 49 328 52 330 51 328 52 325 49 26 28 331 53 310 29 332 54 310 29 331 53 93 42 328 52 321 43 332 54 321 43 328 52 12 55 333 56 336 57 337 58 336 57 333 56 96 59 335 60 334 61 337 58 334 61 335 60 28 17 303 19 339 62 340 63 339 62 303 19 96 59 334 61 338 64 340 63 338 64 334 61 29 12 329 50 298 13 342 65 298 13 329 50 96 59 338 64 341 66 342 65 341 66 338 64 27 45 343 67 324 46 344 68 324 46 343 67 96 59 341 66 335 60 344 68 335 60 341 66 4 69 345 70 348 71 349 72 348 71 345 70 101 73 347 74 346 75 349 72 346 75 347 74 30 76 350 77 352 78 353 79 352 78 350 77 101 73 346 75 351 80 353 79 351 80 346 75 33 81 354 82 356 83 357 84 356 83 354 82 101 73 351 80 355 85 357 84 355 85 351 80 32 86 358 87 359 88 360 89 359 88 358 87 101 73 355 85 347 74 360 89 347 74 355 85 10 90 361 91 364 92 365 93 364 92 361 91 105 94 363 95 362 96 365 93 362 96 363 95 31 97 366 98 368 99 369 100 368 99 366 98 105 94 362 96 367 101 369 100 367 101 362 96 33 81 356 83 371 102 372 103 371 102 356 83 105 94 367 101 370 104 372 103 370 104 367 101 30 76 373 105 350 77 374 106 350 77 373 105 105 94 370 104 363 95 374 106 363 95 370 104 13 38 322 40 377 107 378 108 377 107 322 40 108 109 376 110 375 111 378 108 375 111 376 110 26 28 379 112 331 53 381 113 331 53 379 112 108 109 375 111 380 114 381 113 380 114 375 111 33 81 371 102 383 115 384 116 383 115 371 102 108 109 380 114 382 117 384 116 382 117 380 114 31 97 385 118 366 98 386 119 366 98 385 118 108 109 382 117 376 110 386 119 376 110 382 117 9 21 387 120 305 22 390 121 305 22 387 120 110 122 389 123 388 124 390 121 388 124 389 123 32 86 359 88 392 125 393 126 392 125 359 88 110 122 388 124 391 127 393 126 391 127 388 124 33 81 383 115 354 82 395 128 354 82 383 115 110 122 391 127 394 129 395 128 394 129 391 127 26 28 312 30 379 112 396 130 379 112 312 30 110 122 394 129 389 123 396 130 389 123 394 129 8 131 397 132 400 133 401 134 400 133 397 132 115 135 399 136 398 137 401 134 398 137 399 136 34 138 402 139 404 140 405 141 404 140 402 139 115 135 398 137 403 142 405 141 403 142 398 137 37 143 406 144 408 145 409 146 408 145 406 144 115 135 403 142 407 147 409 146 407 147 403 142 36 148 410 149 411 150 412 151 411 150 410 149 115 135 407 147 399 136 412 151 399 136 407 147 11 152 413 153 416 154 417 155 416 154 413 153 119 156 415 157 414 158 417 155 414 158 415 157 35 159 418 160 420 161 421 162 420 161 418 160 119 156 414 158 419 163 421 162 419 163 414 158 37 143 408 145 423 164 424 165 423 164 408 145 119 156 419 163 422 166 424 165 422 166 419 163 34 138 425 167 402 139 426 168 402 139 425 167 119 156 422 166 415 157 426 168 415 157 422 166 13 38 377 107 429 169 430 170 429 169 377 107 122 171 428 172 427 173 430 170 427 173 428 172 31 97 431 174 385 118 433 175 385 118 431 174 122 171 427 173 432 176 433 175 432 176 427 173 37 143 423 164 435 177 436 178 435 177 423 164 122 171 432 176 434 179 436 178 434 179 432 176 35 159 437 180 418 160 438 181 418 160 437 180 122 171 434 179 428 172 438 181 428 172 434 179 10 90 439 182 361 91 442 183 361 91 439 182 124 184 441 185 440 186 442 183 440 186 441 185 36 148 411 150 444 187 445 188 444 187 411 150 124 184 440 186 443 189 445 188 443 189 440 186 37 143 435 177 406 144 447 190 406 144 435 177 124 184 443 189 446 191 447 190 446 191 443 189 31 97 368 99 431 174 448 192 431 174 368 99 124 184 446 191 441 185 448 192 441 185 446 191 7 193 449 194 452 195 453 196 452 195 449 194 129 197 451 198 450 199 453 196 450 199 451 198 38 200 454 201 456 202 457 203 456 202 454 201 129 197 450 199 455 204 457 203 455 204 450 199 40 205 458 206 460 207 461 208 460 207 458 206 129 197 455 204 459 209 461 208 459 209 455 204 39 210 462 211 463 212 464 213 463 212 462 211 129 197 459 209 451 198 464 213 451 198 459 209 12 55 336 57 467 214 468 215 467 214 336 57 132 216 466 217 465 218 468 215 465 218 466 217 27 45 469 219 343 67 471 220 343 67 469 219 132 216 465 218 470 221 471 220 470 221 465 218 40 205 460 207 473 222 474 223 473 222 460 207 132 216 470 221 472 224 474 223 472 224 470 221 38 200 475 225 454 201 476 226 454 201 475 225 132 216 472 224 466 217 476 226 466 217 472 224 13 38 429 169 319 39 479 227 319 39 429 169 134 228 478 229 477 230 479 227 477 230 478 229 35 159 480 231 437 180 482 232 437 180 480 231 134 228 477 230 481 233 482 232 481 233 477 230 40 205 473 222 484 234 485 235 484 234 473 222 134 228 481 233 483 236 485 235 483 236 481 233 27 45 326 47 469 219 486 237 469 219 326 47 134 228 483 236 478 229 486 237 478 229 483 236 11 152 487 238 413 153 490 239 413 153 487 238 136 240 489 241 488 242 490 239 488 242 489 241 39 210 463 212 492 243 493 244 492 243 463 212 136 240 488 242 491 245 493 244 491 245 488 242 40 205 484 234 458 206 495 246 458 206 484 234 136 240 491 245 494 247 495 246 494 247 491 245 35 159 420 161 480 231 496 248 480 231 420 161 136 240 494 247 489 241 496 248 489 241 494 247 3 249 497 250 500 251 501 252 500 251 497 250 141 253 499 254 498 255 501 252 498 255 499 254 41 256 502 257 504 258 505 259 504 258 502 257 141 253 498 255 503 260 505 259 503 260 498 255 45 261 506 262 508 263 509 264 508 263 506 262 141 253 503 260 507 265 509 264 507 265 503 260 44 266 510 267 511 268 512 269 511 268 510 267 141 253 507 265 499 254 512 269 499 254 507 265 14 270 513 271 516 272 517 273 516 272 513 271 145 274 515 275 514 276 517 273 514 276 515 275 42 277 518 278 520 279 521 280 520 279 518 278 145 274 514 276 519 281 521 280 519 281 514 276 45 261 508 263 523 282 524 283 523 282 508 263 145 274 519 281 522 284 524 283 522 284 519 281 41 256 525 285 502 257 526 286 502 257 525 285 145 274 522 284 515 275 526 286 515 275 522 284 17 287 527 288 530 289 531 290 530 289 527 288 149 291 529 292 528 293 531 290 528 293 529 292 43 294 532 295 534 296 535 297 534 296 532 295 149 291 528 293 533 298 535 297 533 298 528 293 45 261 523 282 537 299 538 300 537 299 523 282 149 291 533 298 536 301 538 300 536 301 533 298 42 277 539 302 518 278 540 303 518 278 539 302 149 291 536 301 529 292 540 303 529 292 536 301 16 304 541 305 544 306 545 307 544 306 541 305 152 308 543 309 542 310 545 307 542 310 543 309 44 266 511 268 547 311 548 312 547 311 511 268 152 308 542 310 546 313 548 312 546 313 542 310 45 261 537 299 506 262 550 314 506 262 537 299 152 308 546 313 549 315 550 314 549 315 546 313 43 294 551 316 532 295 552 317 532 295 551 316 152 308 549 315 543 309 552 317 543 309 549 315 5 318 553 319 556 320 557 321 556 320 553 319 157 322 555 323 554 324 557 321 554 324 555 323 46 325 558 326 560 327 561 328 560 327 558 326 157 322 554 324 559 329 561 328 559 329 554 324 49 330 562 331 564 332 565 333 564 332 562 331 157 322 559 329 563 334 565 333 563 334 559 329 48 335 566 336 567 337 568 338 567 337 566 336 157 322 563 334 555 323 568 338 555 323 563 334 15 339 569 340 572 341 573 342 572 341 569 340 161 343 571 344 570 345 573 342 570 345 571 344 47 346 574 347 576 348 577 349 576 348 574 347 161 343 570 345 575 350 577 349 575 350 570 345 49 330 564 332 579 351 580 352 579 351 564 332 161 343 575 350 578 353 580 352 578 353 575 350 46 325 581 354 558 326 582 355 558 326 581 354 161 343 578 353 571 344 582 355 571 344 578 353 17 287 530 289 585 356 586 357 585 356 530 289 164 358 584 359 583 360 586 357 583 360 584 359 42 277 587 361 539 302 589 362 539 302 587 361 164 358 583 360 588 363 589 362 588 363 583 360 49 330 579 351 591 364 592 365 591 364 579 351 164 358 588 363 590 366 592 365 590 366 588 363 47 346 593 367 574 347 594 368 574 347 593 367 164 358 590 366 584 359 594 368 584 359 590 366 14 270 595 369 513 271 598 370 513 271 595 369 166 371 597 372 596 373 598 370 596 373 597 372 48 335 567 337 600 374 601 375 600 374 567 337 166 371 596 373 599 376 601 375 599 376 596 373 49 330 591 364 562 331 603 377 562 331 591 364 166 371 599 376 602 378 603 377 602 378 599 376 42 277 520 279 587 361 604 379 587 361 520 279 166 371 602 378 597 372 604 379 597 372 602 378 8 131 400 133 607 380 608 381 607 380 400 133 170 382 606 383 605 384 608 381 605 384 606 383 36 148 609 385 410 149 611 386 410 149 609 385 170 382 605 384 610 387 611 386 610 387 605 384 52 388 612 389 614 390 615 391 614 390 612 389 170 382 610 387 613 392 615 391 613 392 610 387 51 393 616 394 617 395 618 396 617 395 616 394 170 382 613 392 606 383 618 396 606 383 613 392 10 90 619 397 439 182 622 398 439 182 619 397 173 399 621 400 620 401 622 398 620 401 621 400 50 402 623 403 625 404 626 405 625 404 623 403 173 399 620 401 624 406 626 405 624 406 620 401 52 388 614 390 628 407 629 408 628 407 614 390 173 399 624 406 627 409 629 408 627 409 624 406 36 148 444 187 609 385 630 410 609 385 444 187 173 399 627 409 621 400 630 410 621 400 627 409 17 287 585 356 633 411 634 412 633 411 585 356 176 413 632 414 631 415 634 412 631 415 632 414 47 346 635 416 593 367 637 417 593 367 635 416 176 413 631 415 636 418 637 417 636 418 631 415 52 388 628 407 639 419 640 420 639 419 628 407 176 413 636 418 638 421 640 420 638 421 636 418 50 402 641 422 623 403 642 423 623 403 641 422 176 413 638 421 632 414 642 423 632 414 638 421 15 339 643 424 569 340 646 425 569 340 643 424 178 426 645 427 644 428 646 425 644 428 645 427 51 393 617 395 648 429 649 430 648 429 617 395 178 426 644 428 647 431 649 430 647 431 644 428 52 388 639 419 612 389 651 432 612 389 639 419 178 426 647 431 650 433 651 432 650 433 647 431 47 346 576 348 635 416 652 434 635 416 576 348 178 426 650 433 645 427 652 434 645 427 650 433 4 69 653 435 345 70 656 436 345 70 653 435 182 437 655 438 654 439 656 436 654 439 655 438 53 440 657 441 659 442 660 443 659 442 657 441 182 437 654 439 658 444 660 443 658 444 654 439 54 445 661 446 663 447 664 448 663 447 661 446 182 437 658 444 662 449 664 448 662 449 658 444 30 76 352 78 665 450 666 451 665 450 352 78 182 437 662 449 655 438 666 451 655 438 662 449 16 304 544 306 669 452 670 453 669 452 544 306 185 454 668 455 667 456 670 453 667 456 668 455 43 294 671 457 551 316 673 458 551 316 671 457 185 454 667 456 672 459 673 458 672 459 667 456 54 445 663 447 675 460 676 461 675 460 663 447 185 454 672 459 674 462 676 461 674 462 672 459 53 440 677 463 657 441 678 464 657 441 677 463 185 454 674 462 668 455 678 464 668 455 674 462 17 287 633 411 527 288 681 465 527 288 633 411 187 466 680 467 679 468 681 465 679 468 680 467 50 402 682 469 641 422 684 470 641 422 682 469 187 466 679 468 683 471 684 470 683 471 679 468 54 445 675 460 686 472 687 473 686 472 675 460 187 466 683 471 685 474 687 473 685 474 683 471 43 294 534 296 671 457 688 475 671 457 534 296 187 466 685 474 680 467 688 475 680 467 685 474 10 90 364 92 619 397 691 476 619 397 364 92 188 477 690 478 689 479 691 476 689 479 690 478 30 76 665 450 373 105 693 480 373 105 665 450 188 477 689 479 692 481 693 480 692 481 689 479 54 445 686 472 661 446 695 482 661 446 686 472 188 477 692 481 694 483 695 482 694 483 692 481 50 402 625 404 682 469 696 484 682 469 625 404 188 477 694 483 690 478 696 484 690 478 694 483 1 485 697 486 700 487 701 488 700 487 697 486 193 489 699 490 698 491 701 488 698 491 699 490 55 492 702 493 704 494 705 495 704 494 702 493 193 489 698 491 703 496 705 495 703 496 698 491 59 497 706 498 708 499 709 500 708 499 706 498 193 489 703 496 707 501 709 500 707 501 703 496 58 502 710 503 711 504 712 505 711 504 710 503 193 489 707 501 699 490 712 505 699 490 707 501 18 506 713 507 716 508 717 509 716 508 713 507 197 510 715 511 714 512 717 509 714 512 715 511 56 513 718 514 720 515 721 516 720 515 718 514 197 510 714 512 719 517 721 516 719 517 714 512 59 497 708 499 723 518 724 519 723 518 708 499 197 510 719 517 722 520 724 519 722 520 719 517 55 492 725 521 702 493 726 522 702 493 725 521 197 510 722 520 715 511 726 522 715 511 722 520 21 523 727 524 730 525 731 526 730 525 727 524 201 527 729 528 728 529 731 526 728 529 729 528 57 530 732 531 734 532 735 533 734 532 732 531 201 527 728 529 733 534 735 533 733 534 728 529 59 497 723 518 737 535 738 536 737 535 723 518 201 527 733 534 736 537 738 536 736 537 733 534 56 513 739 538 718 514 740 539 718 514 739 538 201 527 736 537 729 528 740 539 729 528 736 537 20 540 741 541 744 542 745 543 744 542 741 541 204 544 743 545 742 546 745 543 742 546 743 545 58 502 711 504 747 547 748 548 747 547 711 504 204 544 742 546 746 549 748 548 746 549 742 546 59 497 737 535 706 498 750 550 706 498 737 535 204 544 746 549 749 551 750 550 749 551 746 549 57 530 751 552 732 531 752 553 732 531 751 552 204 544 749 551 743 545 752 553 743 545 749 551 6 554 753 555 756 556 757 557 756 556 753 555 209 558 755 559 754 560 757 557 754 560 755 559 60 561 758 562 760 563 761 564 760 563 758 562 209 558 754 560 759 565 761 564 759 565 754 560 63 566 762 567 764 568 765 569 764 568 762 567 209 558 759 565 763 570 765 569 763 570 759 565 62 571 766 572 767 573 768 574 767 573 766 572 209 558 763 570 755 559 768 574 755 559 763 570 19 575 769 576 772 577 773 578 772 577 769 576 213 579 771 580 770 581 773 578 770 581 771 580 61 582 774 583 776 584 777 585 776 584 774 583 213 579 770 581 775 586 777 585 775 586 770 581 63 566 764 568 779 587 780 588 779 587 764 568 213 579 775 586 778 589 780 588 778 589 775 586 60 561 781 590 758 562 782 591 758 562 781 590 213 579 778 589 771 580 782 591 771 580 778 589 21 523 730 525 785 592 786 593 785 592 730 525 216 594 784 595 783 596 786 593 783 596 784 595 56 513 787 597 739 538 789 598 739 538 787 597 216 594 783 596 788 599 789 598 788 599 783 596 63 566 779 587 791 600 792 601 791 600 779 587 216 594 788 599 790 602 792 601 790 602 788 599 61 582 793 603 774 583 794 604 774 583 793 603 216 594 790 602 784 595 794 604 784 595 790 602 18 506 795 605 713 507 798 606 713 507 795 605 218 607 797 608 796 609 798 606 796 609 797 608 62 571 767 573 800 610 801 611 800 610 767 573 218 607 796 609 799 612 801 611 799 612 796 609 63 566 791 600 762 567 803 613 762 567 791 600 218 607 799 612 802 614 803 613 802 614 799 612 56 513 720 515 787 597 804 615 787 597 720 515 218 607 802 614 797 608 804 615 797 608 802 614 8 131 607 380 807 616 808 617 807 616 607 380 222 618 806 619 805 620 808 617 805 620 806 619 51 393 809 621 616 394 811 622 616 394 809 621 222 618 805 620 810 623 811 622 810 623 805 620 66 624 812 625 814 626 815 627 814 626 812 625 222 618 810 623 813 628 815 627 813 628 810 623 65 629 816 630 817 631 818 632 817 631 816 630 222 618 813 628 806 619 818 632 806 619 813 628 15 339 819 633 643 424 822 634 643 424 819 633 225 635 821 636 820 637 822 634 820 637 821 636 64 638 823 639 825 640 826 641 825 640 823 639 225 635 820 637 824 642 826 641 824 642 820 637 66 624 814 626 828 643 829 644 828 643 814 626 225 635 824 642 827 645 829 644 827 645 824 642 51 393 648 429 809 621 830 646 809 621 648 429 225 635 827 645 821 636 830 646 821 636 827 645 21 523 785 592 833 647 834 648 833 647 785 592 228 649 832 650 831 651 834 648 831 651 832 650 61 582 835 652 793 603 837 653 793 603 835 652 228 649 831 651 836 654 837 653 836 654 831 651 66 624 828 643 839 655 840 656 839 655 828 643 228 649 836 654 838 657 840 656 838 657 836 654 64 638 841 658 823 639 842 659 823 639 841 658 228 649 838 657 832 650 842 659 832 650 838 657 19 575 843 660 769 576 846 661 769 576 843 660 230 662 845 663 844 664 846 661 844 664 845 663 65 629 817 631 848 665 849 666 848 665 817 631 230 662 844 664 847 667 849 666 847 667 844 664 66 624 839 655 812 625 851 668 812 625 839 655 230 662 847 667 850 669 851 668 850 669 847 667 61 582 776 584 835 652 852 670 835 652 776 584 230 662 850 669 845 663 852 670 845 663 850 669 5 318 853 671 553 319 856 672 553 319 853 671 234 673 855 674 854 675 856 672 854 675 855 674 67 676 857 677 859 678 860 679 859 678 857 677 234 673 854 675 858 680 860 679 858 680 854 675 68 681 861 682 863 683 864 684 863 683 861 682 234 673 858 680 862 685 864 684 862 685 858 680 46 325 560 327 865 686 866 687 865 686 560 327 234 673 862 685 855 674 866 687 855 674 862 685 20 540 744 542 869 688 870 689 869 688 744 542 237 690 868 691 867 692 870 689 867 692 868 691 57 530 871 693 751 552 873 694 751 552 871 693 237 690 867 692 872 695 873 694 872 695 867 692 68 681 863 683 875 696 876 697 875 696 863 683 237 690 872 695 874 698 876 697 874 698 872 695 67 676 877 699 857 677 878 700 857 677 877 699 237 690 874 698 868 691 878 700 868 691 874 698 21 523 833 647 727 524 881 701 727 524 833 647 239 702 880 703 879 704 881 701 879 704 880 703 64 638 882 705 841 658 884 706 841 658 882 705 239 702 879 704 883 707 884 706 883 707 879 704 68 681 875 696 886 708 887 709 886 708 875 696 239 702 883 707 885 710 887 709 885 710 883 707 57 530 734 532 871 693 888 711 871 693 734 532 239 702 885 710 880 703 888 711 880 703 885 710 15 339 572 341 819 633 891 712 819 633 572 341 240 713 890 714 889 715 891 712 889 715 890 714 46 325 865 686 581 354 893 716 581 354 865 686 240 713 889 715 892 717 893 716 892 717 889 715 68 681 886 708 861 682 895 718 861 682 886 708 240 713 892 717 894 719 895 718 894 719 892 717 64 638 825 640 882 705 896 720 882 705 825 640 240 713 894 719 890 714 896 720 890 714 894 719 0 721 897 722 900 723 901 724 900 723 897 722 245 725 899 726 898 727 901 724 898 727 899 726 69 728 902 729 904 730 905 731 904 730 902 729 245 725 898 727 903 732 905 731 903 732 898 727 73 733 906 734 908 735 909 736 908 735 906 734 245 725 903 732 907 737 909 736 907 737 903 732 72 738 910 739 911 740 912 741 911 740 910 739 245 725 907 737 899 726 912 741 899 726 907 737 22 742 913 743 916 744 917 745 916 744 913 743 249 746 915 747 914 748 917 745 914 748 915 747 70 749 918 750 920 751 921 752 920 751 918 750 249 746 914 748 919 753 921 752 919 753 914 748 73 733 908 735 923 754 924 755 923 754 908 735 249 746 919 753 922 756 924 755 922 756 919 753 69 728 925 757 902 729 926 758 902 729 925 757 249 746 922 756 915 747 926 758 915 747 922 756 24 759 927 760 930 761 931 762 930 761 927 760 253 763 929 764 928 765 931 762 928 765 929 764 71 766 932 767 934 768 935 769 934 768 932 767 253 763 928 765 933 770 935 769 933 770 928 765 73 733 923 754 937 771 938 772 937 771 923 754 253 763 933 770 936 773 938 772 936 773 933 770 70 749 939 774 918 750 940 775 918 750 939 774 253 763 936 773 929 764 940 775 929 764 936 773 23 776 941 777 944 778 945 779 944 778 941 777 256 780 943 781 942 782 945 779 942 782 943 781 72 738 911 740 947 783 948 784 947 783 911 740 256 780 942 782 946 785 948 784 946 785 942 782 73 733 937 771 906 734 950 786 906 734 937 771 256 780 946 785 949 787 950 786 949 787 946 785 71 766 951 788 932 767 952 789 932 767 951 788 256 780 949 787 943 781 952 789 943 781 949 787 7 193 452 195 955 790 956 791 955 790 452 195 260 792 954 793 953 794 956 791 953 794 954 793 39 210 957 795 462 211 959 796 462 211 957 795 260 792 953 794 958 797 959 796 958 797 953 794 76 798 960 799 962 800 963 801 962 800 960 799 260 792 958 797 961 802 963 801 961 802 958 797 75 803 964 804 965 805 966 806 965 805 964 804 260 792 961 802 954 793 966 806 954 793 961 802 11 152 967 807 487 238 970 808 487 238 967 807 263 809 969 810 968 811 970 808 968 811 969 810 74 812 971 813 973 814 974 815 973 814 971 813 263 809 968 811 972 816 974 815 972 816 968 811 76 798 962 800 976 817 977 818 976 817 962 800 263 809 972 816 975 819 977 818 975 819 972 816 39 210 492 243 957 795 978 820 957 795 492 243 263 809 975 819 969 810 978 820 969 810 975 819 24 759 930 761 981 821 982 822 981 821 930 761 266 823 980 824 979 825 982 822 979 825 980 824 70 749 983 826 939 774 985 827 939 774 983 826 266 823 979 825 984 828 985 827 984 828 979 825 76 798 976 817 987 829 988 830 987 829 976 817 266 823 984 828 986 831 988 830 986 831 984 828 74 812 989 832 971 813 990 833 971 813 989 832 266 823 986 831 980 824 990 833 980 824 986 831 22 742 991 834 913 743 994 835 913 743 991 834 268 836 993 837 992 838 994 835 992 838 993 837 75 803 965 805 996 839 997 840 996 839 965 805 268 836 992 838 995 841 997 840 995 841 992 838 76 798 987 829 960 799 999 842 960 799 987 829 268 836 995 841 998 843 999 842 998 843 995 841 70 749 920 751 983 826 1000 844 983 826 920 751 268 836 998 843 993 837 1000 844 993 837 998 843 8 131 807 616 397 132 1003 845 397 132 807 616 271 846 1002 847 1001 848 1003 845 1001 848 1002 847 65 629 1004 849 816 630 1006 850 816 630 1004 849 271 846 1001 848 1005 851 1006 850 1005 851 1001 848 78 852 1007 853 1009 854 1010 855 1009 854 1007 853 271 846 1005 851 1008 856 1010 855 1008 856 1005 851 34 138 404 140 1011 857 1012 858 1011 857 404 140 271 846 1008 856 1002 847 1012 858 1002 847 1008 856 19 575 1013 859 843 660 1016 860 843 660 1013 859 274 861 1015 862 1014 863 1016 860 1014 863 1015 862 77 864 1017 865 1019 866 1020 867 1019 866 1017 865 274 861 1014 863 1018 868 1020 867 1018 868 1014 863 78 852 1009 854 1022 869 1023 870 1022 869 1009 854 274 861 1018 868 1021 871 1023 870 1021 871 1018 868 65 629 848 665 1004 849 1024 872 1004 849 848 665 274 861 1021 871 1015 862 1024 872 1015 862 1021 871 24 759 981 821 1027 873 1028 874 1027 873 981 821 277 875 1026 876 1025 877 1028 874 1025 877 1026 876 74 812 1029 878 989 832 1031 879 989 832 1029 878 277 875 1025 877 1030 880 1031 879 1030 880 1025 877 78 852 1022 869 1033 881 1034 882 1033 881 1022 869 277 875 1030 880 1032 883 1034 882 1032 883 1030 880 77 864 1035 884 1017 865 1036 885 1017 865 1035 884 277 875 1032 883 1026 876 1036 885 1026 876 1032 883 11 152 416 154 967 807 1039 886 967 807 416 154 278 887 1038 888 1037 889 1039 886 1037 889 1038 888 34 138 1011 857 425 167 1041 890 425 167 1011 857 278 887 1037 889 1040 891 1041 890 1040 891 1037 889 78 852 1033 881 1007 853 1043 892 1007 853 1033 881 278 887 1040 891 1042 893 1043 892 1042 893 1040 891 74 812 973 814 1029 878 1044 894 1029 878 973 814 278 887 1042 893 1038 888 1044 894 1038 888 1042 893 6 554 1045 895 753 555 1048 896 753 555 1045 895 282 897 1047 898 1046 899 1048 896 1046 899 1047 898 79 900 1049 901 1051 902 1052 903 1051 902 1049 901 282 897 1046 899 1050 904 1052 903 1050 904 1046 899 80 905 1053 906 1055 907 1056 908 1055 907 1053 906 282 897 1050 904 1054 909 1056 908 1054 909 1050 904 60 561 760 563 1057 910 1058 911 1057 910 760 563 282 897 1054 909 1047 898 1058 911 1047 898 1054 909 23 776 944 778 1061 912 1062 913 1061 912 944 778 285 914 1060 915 1059 916 1062 913 1059 916 1060 915 71 766 1063 917 951 788 1065 918 951 788 1063 917 285 914 1059 916 1064 919 1065 918 1064 919 1059 916 80 905 1055 907 1067 920 1068 921 1067 920 1055 907 285 914 1064 919 1066 922 1068 921 1066 922 1064 919 79 900 1069 923 1049 901 1070 924 1049 901 1069 923 285 914 1066 922 1060 915 1070 924 1060 915 1066 922 24 759 1027 873 927 760 1073 925 927 760 1027 873 287 926 1072 927 1071 928 1073 925 1071 928 1072 927 77 864 1074 929 1035 884 1076 930 1035 884 1074 929 287 926 1071 928 1075 931 1076 930 1075 931 1071 928 80 905 1067 920 1078 932 1079 933 1078 932 1067 920 287 926 1075 931 1077 934 1079 933 1077 934 1075 931 71 766 934 768 1063 917 1080 935 1063 917 934 768 287 926 1077 934 1072 927 1080 935 1072 927 1077 934 19 575 772 577 1013 859 1083 936 1013 859 772 577 288 937 1082 938 1081 939 1083 936 1081 939 1082 938 60 561 1057 910 781 590 1085 940 781 590 1057 910 288 937 1081 939 1084 941 1085 940 1084 941 1081 939 80 905 1078 932 1053 906 1087 942 1053 906 1078 932 288 937 1084 941 1086 943 1087 942 1086 943 1084 941 77 864 1019 866 1074 929 1088 944 1074 929 1019 866 288 937 1086 943 1082 938 1088 944 1082 938 1086 943 81 945 290 6 289 1 293 3 289 1 290 6 84 946 292 2 291 5 293 3 291 5 292 2 82 947 295 11 294 8 297 10 294 8 295 11 81 945 296 9 290 6 297 10 290 6 296 9 83 948 299 16 298 13 301 15 298 13 299 16 82 947 300 14 295 11 301 15 295 11 300 14 84 946 291 5 302 18 304 20 302 18 291 5 83 948 303 19 299 16 304 20 299 16 303 19 86 949 306 27 305 22 309 24 305 22 306 27 88 950 308 23 307 26 309 24 307 26 308 23 87 951 311 32 310 29 313 31 310 29 311 32 86 949 312 30 306 27 313 31 306 27 312 30 82 947 314 35 300 14 316 34 300 14 314 35 87 951 315 33 311 32 316 34 311 32 315 33 88 950 307 26 317 36 318 37 317 36 307 26 82 947 294 8 314 35 318 37 314 35 294 8 90 952 320 44 319 39 323 41 319 39 320 44 92 953 322 40 321 43 323 41 321 43 322 40 91 954 325 49 324 46 327 48 324 46 325 49 90 952 326 47 320 44 327 48 320 44 326 47 87 951 328 52 315 33 330 51 315 33 328 52 91 954 329 50 325 49 330 51 325 49 329 50 92 953 321 43 331 53 332 54 331 53 321 43 87 951 310 29 328 52 332 54 328 52 310 29 94 955 334 61 333 56 337 58 333 56 334 61 95 956 336 57 335 60 337 58 335 60 336 57 83 948 338 64 303 19 340 63 303 19 338 64 94 955 339 62 334 61 340 63 334 61 339 62 91 954 341 66 329 50 342 65 329 50 341 66 83 948 298 13 338 64 342 65 338 64 298 13 95 956 335 60 343 67 344 68 343 67 335 60 91 954 324 46 341 66 344 68 341 66 324 46 97 957 346 75 345 70 349 72 345 70 346 75 100 958 348 71 347 74 349 72 347 74 348 71 98 959 351 80 350 77 353 79 350 77 351 80 97 957 352 78 346 75 353 79 346 75 352 78 99 960 355 85 354 82 357 84 354 82 355 85 98 959 356 83 351 80 357 84 351 80 356 83 100 958 347 74 358 87 360 89 358 87 347 74 99 960 359 88 355 85 360 89 355 85 359 88 102 961 362 96 361 91 365 93 361 91 362 96 104 962 364 92 363 95 365 93 363 95 364 92 103 963 367 101 366 98 369 100 366 98 367 101 102 961 368 99 362 96 369 100 362 96 368 99 98 959 370 104 356 83 372 103 356 83 370 104 103 963 371 102 367 101 372 103 367 101 371 102 104 962 363 95 373 105 374 106 373 105 363 95 98 959 350 77 370 104 374 106 370 104 350 77 92 953 375 111 322 40 378 108 322 40 375 111 107 964 377 107 376 110 378 108 376 110 377 107 106 965 380 114 379 112 381 113 379 112 380 114 92 953 331 53 375 111 381 113 375 111 331 53 103 963 382 117 371 102 384 116 371 102 382 117 106 965 383 115 380 114 384 116 380 114 383 115 107 964 376 110 385 118 386 119 385 118 376 110 103 963 366 98 382 117 386 119 382 117 366 98 109 966 388 124 387 120 390 121 387 120 388 124 86 949 305 22 389 123 390 121 389 123 305 22 99 960 391 127 359 88 393 126 359 88 391 127 109 966 392 125 388 124 393 126 388 124 392 125 106 965 394 129 383 115 395 128 383 115 394 129 99 960 354 82 391 127 395 128 391 127 354 82 86 949 389 123 312 30 396 130 312 30 389 123 106 965 379 112 394 129 396 130 394 129 379 112 111 967 398 137 397 132 401 134 397 132 398 137 114 968 400 133 399 136 401 134 399 136 400 133 112 969 403 142 402 139 405 141 402 139 403 142 111 967 404 140 398 137 405 141 398 137 404 140 113 970 407 147 406 144 409 146 406 144 407 147 112 969 408 145 403 142 409 146 403 142 408 145 114 968 399 136 410 149 412 151 410 149 399 136 113 970 411 150 407 147 412 151 407 147 411 150 116 971 414 158 413 153 417 155 413 153 414 158 118 972 416 154 415 157 417 155 415 157 416 154 117 973 419 163 418 160 421 162 418 160 419 163 116 971 420 161 414 158 421 162 414 158 420 161 112 969 422 166 408 145 424 165 408 145 422 166 117 973 423 164 419 163 424 165 419 163 423 164 118 972 415 157 425 167 426 168 425 167 415 157 112 969 402 139 422 166 426 168 422 166 402 139 107 964 427 173 377 107 430 170 377 107 427 173 121 974 429 169 428 172 430 170 428 172 429 169 120 975 432 176 431 174 433 175 431 174 432 176 107 964 385 118 427 173 433 175 427 173 385 118 117 973 434 179 423 164 436 178 423 164 434 179 120 975 435 177 432 176 436 178 432 176 435 177 121 974 428 172 437 180 438 181 437 180 428 172 117 973 418 160 434 179 438 181 434 179 418 160 123 976 440 186 439 182 442 183 439 182 440 186 102 961 361 91 441 185 442 183 441 185 361 91 113 970 443 189 411 150 445 188 411 150 443 189 123 976 444 187 440 186 445 188 440 186 444 187 120 975 446 191 435 177 447 190 435 177 446 191 113 970 406 144 443 189 447 190 443 189 406 144 102 961 441 185 368 99 448 192 368 99 441 185 120 975 431 174 446 191 448 192 446 191 431 174 125 977 450 199 449 194 453 196 449 194 450 199 128 978 452 195 451 198 453 196 451 198 452 195 126 979 455 204 454 201 457 203 454 201 455 204 125 977 456 202 450 199 457 203 450 199 456 202 127 980 459 209 458 206 461 208 458 206 459 209 126 979 460 207 455 204 461 208 455 204 460 207 128 978 451 198 462 211 464 213 462 211 451 198 127 980 463 212 459 209 464 213 459 209 463 212 95 956 465 218 336 57 468 215 336 57 465 218 131 981 467 214 466 217 468 215 466 217 467 214 130 982 470 221 469 219 471 220 469 219 470 221 95 956 343 67 465 218 471 220 465 218 343 67 126 979 472 224 460 207 474 223 460 207 472 224 130 982 473 222 470 221 474 223 470 221 473 222 131 981 466 217 475 225 476 226 475 225 466 217 126 979 454 201 472 224 476 226 472 224 454 201 121 974 477 230 429 169 479 227 429 169 477 230 90 952 319 39 478 229 479 227 478 229 319 39 133 983 481 233 480 231 482 232 480 231 481 233 121 974 437 180 477 230 482 232 477 230 437 180 130 982 483 236 473 222 485 235 473 222 483 236 133 983 484 234 481 233 485 235 481 233 484 234 90 952 478 229 326 47 486 237 326 47 478 229 130 982 469 219 483 236 486 237 483 236 469 219 135 984 488 242 487 238 490 239 487 238 488 242 116 971 413 153 489 241 490 239 489 241 413 153 127 980 491 245 463 212 493 244 463 212 491 245 135 984 492 243 488 242 493 244 488 242 492 243 133 983 494 247 484 234 495 246 484 234 494 247 127 980 458 206 491 245 495 246 491 245 458 206 116 971 489 241 420 161 496 248 420 161 489 241 133 983 480 231 494 247 496 248 494 247 480 231 137 985 498 255 497 250 501 252 497 250 498 255 140 986 500 251 499 254 501 252 499 254 500 251 138 987 503 260 502 257 505 259 502 257 503 260 137 985 504 258 498 255 505 259 498 255 504 258 139 988 507 265 506 262 509 264 506 262 507 265 138 987 508 263 503 260 509 264 503 260 508 263 140 986 499 254 510 267 512 269 510 267 499 254 139 988 511 268 507 265 512 269 507 265 511 268 142 989 514 276 513 271 517 273 513 271 514 276 144 990 516 272 515 275 517 273 515 275 516 272 143 991 519 281 518 278 521 280 518 278 519 281 142 989 520 279 514 276 521 280 514 276 520 279 138 987 522 284 508 263 524 283 508 263 522 284 143 991 523 282 519 281 524 283 519 281 523 282 144 990 515 275 525 285 526 286 525 285 515 275 138 987 502 257 522 284 526 286 522 284 502 257 146 992 528 293 527 288 531 290 527 288 528 293 148 993 530 289 529 292 531 290 529 292 530 289 147 994 533 298 532 295 535 297 532 295 533 298 146 992 534 296 528 293 535 297 528 293 534 296 143 991 536 301 523 282 538 300 523 282 536 301 147 994 537 299 533 298 538 300 533 298 537 299 148 993 529 292 539 302 540 303 539 302 529 292 143 991 518 278 536 301 540 303 536 301 518 278 150 995 542 310 541 305 545 307 541 305 542 310 151 996 544 306 543 309 545 307 543 309 544 306 139 988 546 313 511 268 548 312 511 268 546 313 150 995 547 311 542 310 548 312 542 310 547 311 147 994 549 315 537 299 550 314 537 299 549 315 139 988 506 262 546 313 550 314 546 313 506 262 151 996 543 309 551 316 552 317 551 316 543 309 147 994 532 295 549 315 552 317 549 315 532 295 153 997 554 324 553 319 557 321 553 319 554 324 156 998 556 320 555 323 557 321 555 323 556 320 154 999 559 329 558 326 561 328 558 326 559 329 153 997 560 327 554 324 561 328 554 324 560 327 155 1000 563 334 562 331 565 333 562 331 563 334 154 999 564 332 559 329 565 333 559 329 564 332 156 998 555 323 566 336 568 338 566 336 555 323 155 1000 567 337 563 334 568 338 563 334 567 337 158 1001 570 345 569 340 573 342 569 340 570 345 160 1002 572 341 571 344 573 342 571 344 572 341 159 1003 575 350 574 347 577 349 574 347 575 350 158 1001 576 348 570 345 577 349 570 345 576 348 154 999 578 353 564 332 580 352 564 332 578 353 159 1003 579 351 575 350 580 352 575 350 579 351 160 1002 571 344 581 354 582 355 581 354 571 344 154 999 558 326 578 353 582 355 578 353 558 326 148 993 583 360 530 289 586 357 530 289 583 360 163 1004 585 356 584 359 586 357 584 359 585 356 162 1005 588 363 587 361 589 362 587 361 588 363 148 993 539 302 583 360 589 362 583 360 539 302 159 1003 590 366 579 351 592 365 579 351 590 366 162 1005 591 364 588 363 592 365 588 363 591 364 163 1004 584 359 593 367 594 368 593 367 584 359 159 1003 574 347 590 366 594 368 590 366 574 347 165 1006 596 373 595 369 598 370 595 369 596 373 142 989 513 271 597 372 598 370 597 372 513 271 155 1000 599 376 567 337 601 375 567 337 599 376 165 1006 600 374 596 373 601 375 596 373 600 374 162 1005 602 378 591 364 603 377 591 364 602 378 155 1000 562 331 599 376 603 377 599 376 562 331 142 989 597 372 520 279 604 379 520 279 597 372 162 1005 587 361 602 378 604 379 602 378 587 361 114 968 605 384 400 133 608 381 400 133 605 384 169 1007 607 380 606 383 608 381 606 383 607 380 167 1008 610 387 609 385 611 386 609 385 610 387 114 968 410 149 605 384 611 386 605 384 410 149 168 1009 613 392 612 389 615 391 612 389 613 392 167 1008 614 390 610 387 615 391 610 387 614 390 169 1007 606 383 616 394 618 396 616 394 606 383 168 1009 617 395 613 392 618 396 613 392 617 395 171 1010 620 401 619 397 622 398 619 397 620 401 123 976 439 182 621 400 622 398 621 400 439 182 172 1011 624 406 623 403 626 405 623 403 624 406 171 1010 625 404 620 401 626 405 620 401 625 404 167 1008 627 409 614 390 629 408 614 390 627 409 172 1011 628 407 624 406 629 408 624 406 628 407 123 976 621 400 444 187 630 410 444 187 621 400 167 1008 609 385 627 409 630 410 627 409 609 385 163 1004 631 415 585 356 634 412 585 356 631 415 175 1012 633 411 632 414 634 412 632 414 633 411 174 1013 636 418 635 416 637 417 635 416 636 418 163 1004 593 367 631 415 637 417 631 415 593 367 172 1011 638 421 628 407 640 420 628 407 638 421 174 1013 639 419 636 418 640 420 636 418 639 419 175 1012 632 414 641 422 642 423 641 422 632 414 172 1011 623 403 638 421 642 423 638 421 623 403 177 1014 644 428 643 424 646 425 643 424 644 428 158 1001 569 340 645 427 646 425 645 427 569 340 168 1009 647 431 617 395 649 430 617 395 647 431 177 1014 648 429 644 428 649 430 644 428 648 429 174 1013 650 433 639 419 651 432 639 419 650 433 168 1009 612 389 647 431 651 432 647 431 612 389 158 1001 645 427 576 348 652 434 576 348 645 427 174 1013 635 416 650 433 652 434 650 433 635 416 179 1015 654 439 653 435 656 436 653 435 654 439 97 957 345 70 655 438 656 436 655 438 345 70 180 1016 658 444 657 441 660 443 657 441 658 444 179 1015 659 442 654 439 660 443 654 439 659 442 181 1017 662 449 661 446 664 448 661 446 662 449 180 1016 663 447 658 444 664 448 658 444 663 447 97 957 655 438 352 78 666 451 352 78 655 438 181 1017 665 450 662 449 666 451 662 449 665 450 151 996 667 456 544 306 670 453 544 306 667 456 184 1018 669 452 668 455 670 453 668 455 669 452 183 1019 672 459 671 457 673 458 671 457 672 459 151 996 551 316 667 456 673 458 667 456 551 316 180 1016 674 462 663 447 676 461 663 447 674 462 183 1019 675 460 672 459 676 461 672 459 675 460 184 1018 668 455 677 463 678 464 677 463 668 455 180 1016 657 441 674 462 678 464 674 462 657 441 175 1012 679 468 633 411 681 465 633 411 679 468 146 992 527 288 680 467 681 465 680 467 527 288 186 1020 683 471 682 469 684 470 682 469 683 471 175 1012 641 422 679 468 684 470 679 468 641 422 183 1019 685 474 675 460 687 473 675 460 685 474 186 1020 686 472 683 471 687 473 683 471 686 472 146 992 680 467 534 296 688 475 534 296 680 467 183 1019 671 457 685 474 688 475 685 474 671 457 104 962 689 479 364 92 691 476 364 92 689 479 171 1010 619 397 690 478 691 476 690 478 619 397 181 1017 692 481 665 450 693 480 665 450 692 481 104 962 373 105 689 479 693 480 689 479 373 105 186 1020 694 483 686 472 695 482 686 472 694 483 181 1017 661 446 692 481 695 482 692 481 661 446 171 1010 690 478 625 404 696 484 625 404 690 478 186 1020 682 469 694 483 696 484 694 483 682 469 189 1021 698 491 697 486 701 488 697 486 698 491 192 1022 700 487 699 490 701 488 699 490 700 487 190 1023 703 496 702 493 705 495 702 493 703 496 189 1021 704 494 698 491 705 495 698 491 704 494 191 1024 707 501 706 498 709 500 706 498 707 501 190 1023 708 499 703 496 709 500 703 496 708 499 192 1022 699 490 710 503 712 505 710 503 699 490 191 1024 711 504 707 501 712 505 707 501 711 504 194 1025 714 512 713 507 717 509 713 507 714 512 196 1026 716 508 715 511 717 509 715 511 716 508 195 1027 719 517 718 514 721 516 718 514 719 517 194 1025 720 515 714 512 721 516 714 512 720 515 190 1023 722 520 708 499 724 519 708 499 722 520 195 1027 723 518 719 517 724 519 719 517 723 518 196 1026 715 511 725 521 726 522 725 521 715 511 190 1023 702 493 722 520 726 522 722 520 702 493 198 1028 728 529 727 524 731 526 727 524 728 529 200 1029 730 525 729 528 731 526 729 528 730 525 199 1030 733 534 732 531 735 533 732 531 733 534 198 1028 734 532 728 529 735 533 728 529 734 532 195 1027 736 537 723 518 738 536 723 518 736 537 199 1030 737 535 733 534 738 536 733 534 737 535 200 1029 729 528 739 538 740 539 739 538 729 528 195 1027 718 514 736 537 740 539 736 537 718 514 202 1031 742 546 741 541 745 543 741 541 742 546 203 1032 744 542 743 545 745 543 743 545 744 542 191 1024 746 549 711 504 748 548 711 504 746 549 202 1031 747 547 742 546 748 548 742 546 747 547 199 1030 749 551 737 535 750 550 737 535 749 551 191 1024 706 498 746 549 750 550 746 549 706 498 203 1032 743 545 751 552 752 553 751 552 743 545 199 1030 732 531 749 551 752 553 749 551 732 531 205 1033 754 560 753 555 757 557 753 555 754 560 208 1034 756 556 755 559 757 557 755 559 756 556 206 1035 759 565 758 562 761 564 758 562 759 565 205 1033 760 563 754 560 761 564 754 560 760 563 207 1036 763 570 762 567 765 569 762 567 763 570 206 1035 764 568 759 565 765 569 759 565 764 568 208 1034 755 559 766 572 768 574 766 572 755 559 207 1036 767 573 763 570 768 574 763 570 767 573 210 1037 770 581 769 576 773 578 769 576 770 581 212 1038 772 577 771 580 773 578 771 580 772 577 211 1039 775 586 774 583 777 585 774 583 775 586 210 1037 776 584 770 581 777 585 770 581 776 584 206 1035 778 589 764 568 780 588 764 568 778 589 211 1039 779 587 775 586 780 588 775 586 779 587 212 1038 771 580 781 590 782 591 781 590 771 580 206 1035 758 562 778 589 782 591 778 589 758 562 200 1029 783 596 730 525 786 593 730 525 783 596 215 1040 785 592 784 595 786 593 784 595 785 592 214 1041 788 599 787 597 789 598 787 597 788 599 200 1029 739 538 783 596 789 598 783 596 739 538 211 1039 790 602 779 587 792 601 779 587 790 602 214 1041 791 600 788 599 792 601 788 599 791 600 215 1040 784 595 793 603 794 604 793 603 784 595 211 1039 774 583 790 602 794 604 790 602 774 583 217 1042 796 609 795 605 798 606 795 605 796 609 194 1025 713 507 797 608 798 606 797 608 713 507 207 1036 799 612 767 573 801 611 767 573 799 612 217 1042 800 610 796 609 801 611 796 609 800 610 214 1041 802 614 791 600 803 613 791 600 802 614 207 1036 762 567 799 612 803 613 799 612 762 567 194 1025 797 608 720 515 804 615 720 515 797 608 214 1041 787 597 802 614 804 615 802 614 787 597 169 1007 805 620 607 380 808 617 607 380 805 620 221 1043 807 616 806 619 808 617 806 619 807 616 219 1044 810 623 809 621 811 622 809 621 810 623 169 1007 616 394 805 620 811 622 805 620 616 394 220 1045 813 628 812 625 815 627 812 625 813 628 219 1044 814 626 810 623 815 627 810 623 814 626 221 1043 806 619 816 630 818 632 816 630 806 619 220 1045 817 631 813 628 818 632 813 628 817 631 223 1046 820 637 819 633 822 634 819 633 820 637 177 1014 643 424 821 636 822 634 821 636 643 424 224 1047 824 642 823 639 826 641 823 639 824 642 223 1046 825 640 820 637 826 641 820 637 825 640 219 1044 827 645 814 626 829 644 814 626 827 645 224 1047 828 643 824 642 829 644 824 642 828 643 177 1014 821 636 648 429 830 646 648 429 821 636 219 1044 809 621 827 645 830 646 827 645 809 621 215 1040 831 651 785 592 834 648 785 592 831 651 227 1048 833 647 832 650 834 648 832 650 833 647 226 1049 836 654 835 652 837 653 835 652 836 654 215 1040 793 603 831 651 837 653 831 651 793 603 224 1047 838 657 828 643 840 656 828 643 838 657 226 1049 839 655 836 654 840 656 836 654 839 655 227 1048 832 650 841 658 842 659 841 658 832 650 224 1047 823 639 838 657 842 659 838 657 823 639 229 1050 844 664 843 660 846 661 843 660 844 664 210 1037 769 576 845 663 846 661 845 663 769 576 220 1045 847 667 817 631 849 666 817 631 847 667 229 1050 848 665 844 664 849 666 844 664 848 665 226 1049 850 669 839 655 851 668 839 655 850 669 220 1045 812 625 847 667 851 668 847 667 812 625 210 1037 845 663 776 584 852 670 776 584 845 663 226 1049 835 652 850 669 852 670 850 669 835 652 231 1051 854 675 853 671 856 672 853 671 854 675 153 997 553 319 855 674 856 672 855 674 553 319 232 1052 858 680 857 677 860 679 857 677 858 680 231 1051 859 678 854 675 860 679 854 675 859 678 233 1053 862 685 861 682 864 684 861 682 862 685 232 1052 863 683 858 680 864 684 858 680 863 683 153 997 855 674 560 327 866 687 560 327 855 674 233 1053 865 686 862 685 866 687 862 685 865 686 203 1032 867 692 744 542 870 689 744 542 867 692 236 1054 869 688 868 691 870 689 868 691 869 688 235 1055 872 695 871 693 873 694 871 693 872 695 203 1032 751 552 867 692 873 694 867 692 751 552 232 1052 874 698 863 683 876 697 863 683 874 698 235 1055 875 696 872 695 876 697 872 695 875 696 236 1054 868 691 877 699 878 700 877 699 868 691 232 1052 857 677 874 698 878 700 874 698 857 677 227 1048 879 704 833 647 881 701 833 647 879 704 198 1028 727 524 880 703 881 701 880 703 727 524 238 1056 883 707 882 705 884 706 882 705 883 707 227 1048 841 658 879 704 884 706 879 704 841 658 235 1055 885 710 875 696 887 709 875 696 885 710 238 1056 886 708 883 707 887 709 883 707 886 708 198 1028 880 703 734 532 888 711 734 532 880 703 235 1055 871 693 885 710 888 711 885 710 871 693 160 1002 889 715 572 341 891 712 572 341 889 715 223 1046 819 633 890 714 891 712 890 714 819 633 233 1053 892 717 865 686 893 716 865 686 892 717 160 1002 581 354 889 715 893 716 889 715 581 354 238 1056 894 719 886 708 895 718 886 708 894 719 233 1053 861 682 892 717 895 718 892 717 861 682 223 1046 890 714 825 640 896 720 825 640 890 714 238 1056 882 705 894 719 896 720 894 719 882 705 241 1057 898 727 897 722 901 724 897 722 898 727 244 1058 900 723 899 726 901 724 899 726 900 723 242 1059 903 732 902 729 905 731 902 729 903 732 241 1057 904 730 898 727 905 731 898 727 904 730 243 1060 907 737 906 734 909 736 906 734 907 737 242 1059 908 735 903 732 909 736 903 732 908 735 244 1058 899 726 910 739 912 741 910 739 899 726 243 1060 911 740 907 737 912 741 907 737 911 740 246 1061 914 748 913 743 917 745 913 743 914 748 248 1062 916 744 915 747 917 745 915 747 916 744 247 1063 919 753 918 750 921 752 918 750 919 753 246 1061 920 751 914 748 921 752 914 748 920 751 242 1059 922 756 908 735 924 755 908 735 922 756 247 1063 923 754 919 753 924 755 919 753 923 754 248 1062 915 747 925 757 926 758 925 757 915 747 242 1059 902 729 922 756 926 758 922 756 902 729 250 1064 928 765 927 760 931 762 927 760 928 765 252 1065 930 761 929 764 931 762 929 764 930 761 251 1066 933 770 932 767 935 769 932 767 933 770 250 1064 934 768 928 765 935 769 928 765 934 768 247 1063 936 773 923 754 938 772 923 754 936 773 251 1066 937 771 933 770 938 772 933 770 937 771 252 1065 929 764 939 774 940 775 939 774 929 764 247 1063 918 750 936 773 940 775 936 773 918 750 254 1067 942 782 941 777 945 779 941 777 942 782 255 1068 944 778 943 781 945 779 943 781 944 778 243 1060 946 785 911 740 948 784 911 740 946 785 254 1067 947 783 942 782 948 784 942 782 947 783 251 1066 949 787 937 771 950 786 937 771 949 787 243 1060 906 734 946 785 950 786 946 785 906 734 255 1068 943 781 951 788 952 789 951 788 943 781 251 1066 932 767 949 787 952 789 949 787 932 767 128 978 953 794 452 195 956 791 452 195 953 794 259 1069 955 790 954 793 956 791 954 793 955 790 257 1070 958 797 957 795 959 796 957 795 958 797 128 978 462 211 953 794 959 796 953 794 462 211 258 1071 961 802 960 799 963 801 960 799 961 802 257 1070 962 800 958 797 963 801 958 797 962 800 259 1069 954 793 964 804 966 806 964 804 954 793 258 1071 965 805 961 802 966 806 961 802 965 805 261 1072 968 811 967 807 970 808 967 807 968 811 135 984 487 238 969 810 970 808 969 810 487 238 262 1073 972 816 971 813 974 815 971 813 972 816 261 1072 973 814 968 811 974 815 968 811 973 814 257 1070 975 819 962 800 977 818 962 800 975 819 262 1073 976 817 972 816 977 818 972 816 976 817 135 984 969 810 492 243 978 820 492 243 969 810 257 1070 957 795 975 819 978 820 975 819 957 795 252 1065 979 825 930 761 982 822 930 761 979 825 265 1074 981 821 980 824 982 822 980 824 981 821 264 1075 984 828 983 826 985 827 983 826 984 828 252 1065 939 774 979 825 985 827 979 825 939 774 262 1073 986 831 976 817 988 830 976 817 986 831 264 1075 987 829 984 828 988 830 984 828 987 829 265 1074 980 824 989 832 990 833 989 832 980 824 262 1073 971 813 986 831 990 833 986 831 971 813 267 1076 992 838 991 834 994 835 991 834 992 838 246 1061 913 743 993 837 994 835 993 837 913 743 258 1071 995 841 965 805 997 840 965 805 995 841 267 1076 996 839 992 838 997 840 992 838 996 839 264 1075 998 843 987 829 999 842 987 829 998 843 258 1071 960 799 995 841 999 842 995 841 960 799 246 1061 993 837 920 751 1000 844 920 751 993 837 264 1075 983 826 998 843 1000 844 998 843 983 826 221 1043 1001 848 807 616 1003 845 807 616 1001 848 111 967 397 132 1002 847 1003 845 1002 847 397 132 269 1077 1005 851 1004 849 1006 850 1004 849 1005 851 221 1043 816 630 1001 848 1006 850 1001 848 816 630 270 1078 1008 856 1007 853 1010 855 1007 853 1008 856 269 1077 1009 854 1005 851 1010 855 1005 851 1009 854 111 967 1002 847 404 140 1012 858 404 140 1002 847 270 1078 1011 857 1008 856 1012 858 1008 856 1011 857 272 1079 1014 863 1013 859 1016 860 1013 859 1014 863 229 1050 843 660 1015 862 1016 860 1015 862 843 660 273 1080 1018 868 1017 865 1020 867 1017 865 1018 868 272 1079 1019 866 1014 863 1020 867 1014 863 1019 866 269 1077 1021 871 1009 854 1023 870 1009 854 1021 871 273 1080 1022 869 1018 868 1023 870 1018 868 1022 869 229 1050 1015 862 848 665 1024 872 848 665 1015 862 269 1077 1004 849 1021 871 1024 872 1021 871 1004 849 265 1074 1025 877 981 821 1028 874 981 821 1025 877 276 1081 1027 873 1026 876 1028 874 1026 876 1027 873 275 1082 1030 880 1029 878 1031 879 1029 878 1030 880 265 1074 989 832 1025 877 1031 879 1025 877 989 832 273 1080 1032 883 1022 869 1034 882 1022 869 1032 883 275 1082 1033 881 1030 880 1034 882 1030 880 1033 881 276 1081 1026 876 1035 884 1036 885 1035 884 1026 876 273 1080 1017 865 1032 883 1036 885 1032 883 1017 865 118 972 1037 889 416 154 1039 886 416 154 1037 889 261 1072 967 807 1038 888 1039 886 1038 888 967 807 270 1078 1040 891 1011 857 1041 890 1011 857 1040 891 118 972 425 167 1037 889 1041 890 1037 889 425 167 275 1082 1042 893 1033 881 1043 892 1033 881 1042 893 270 1078 1007 853 1040 891 1043 892 1040 891 1007 853 261 1072 1038 888 973 814 1044 894 973 814 1038 888 275 1082 1029 878 1042 893 1044 894 1042 893 1029 878 279 1083 1046 899 1045 895 1048 896 1045 895 1046 899 205 1033 753 555 1047 898 1048 896 1047 898 753 555 280 1084 1050 904 1049 901 1052 903 1049 901 1050 904 279 1083 1051 902 1046 899 1052 903 1046 899 1051 902 281 1085 1054 909 1053 906 1056 908 1053 906 1054 909 280 1084 1055 907 1050 904 1056 908 1050 904 1055 907 205 1033 1047 898 760 563 1058 911 760 563 1047 898 281 1085 1057 910 1054 909 1058 911 1054 909 1057 910 255 1068 1059 916 944 778 1062 913 944 778 1059 916 284 1086 1061 912 1060 915 1062 913 1060 915 1061 912 283 1087 1064 919 1063 917 1065 918 1063 917 1064 919 255 1068 951 788 1059 916 1065 918 1059 916 951 788 280 1084 1066 922 1055 907 1068 921 1055 907 1066 922 283 1087 1067 920 1064 919 1068 921 1064 919 1067 920 284 1086 1060 915 1069 923 1070 924 1069 923 1060 915 280 1084 1049 901 1066 922 1070 924 1066 922 1049 901 276 1081 1071 928 1027 873 1073 925 1027 873 1071 928 250 1064 927 760 1072 927 1073 925 1072 927 927 760 286 1088 1075 931 1074 929 1076 930 1074 929 1075 931 276 1081 1035 884 1071 928 1076 930 1071 928 1035 884 283 1087 1077 934 1067 920 1079 933 1067 920 1077 934 286 1088 1078 932 1075 931 1079 933 1075 931 1078 932 250 1064 1072 927 934 768 1080 935 934 768 1072 927 283 1087 1063 917 1077 934 1080 935 1077 934 1063 917 212 1038 1081 939 772 577 1083 936 772 577 1081 939 272 1079 1013 859 1082 938 1083 936 1082 938 1013 859 281 1085 1084 941 1057 910 1085 940 1057 910 1084 941 212 1038 781 590 1081 939 1085 940 1081 939 781 590 286 1088 1086 943 1078 932 1087 942 1078 932 1086 943 281 1085 1053 906 1084 941 1087 942 1084 941 1053 906 272 1079 1082 938 1019 866 1088 944 1019 866 1082 938 286 1088 1074 929 1086 943 1088 944 1086 943 1074 929</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided-32X32">
+ <node id="Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane32X32">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-4X4.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-4X4.dae
new file mode 100644
index 00000000..0b47e3bb
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-4X4.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided-4X4.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:34:40Z</created>
+ <modified>2008-09-19T17:34:40Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane4X4" name="Plane4X4">
+ <mesh>
+ <source id="Plane4X4-positions" name="position">
+ <float_array id="Plane4X4-positions-array" count="75">50 -50 0 -50 -50 0 50 50 0 -50 50 0 0 50 0 -50 0 0 0 -50 0 50 0 0 0 0 0 25 50 0 0 25 0 25 0 0 50 25 0 25 25 0 -50 25 0 -25 0 0 -25 50 0 -25 25 0 -25 -50 0 0 -25 0 -50 -25 0 -25 -25 0 50 -25 0 25 -50 0 25 -25 0</float_array>
+ <technique_common>
+ <accessor source="#Plane4X4-positions-array" count="25" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane4X4-normals" name="normal">
+ <float_array id="Plane4X4-normals-array" count="75">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Plane4X4-normals-array" count="25" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane4X4-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="Plane4X4-Rectangle-UV-array" count="50">0.5 1 0.5 0.75 0.75 1 0.75 0.75 1 0.5 1 0.75 0.75 0.5 0 0.5 0.25 0.5 0 0.75 0.25 0.75 0.25 1 0.5 0 0.5 0.25 0.25 0 0.25 0.25 0 0.25 1 0.25 0.75 0.25 0.75 0 1 1 0.5 0.5 0 1 0 0 1 0</float_array>
+ <technique_common>
+ <accessor source="#Plane4X4-Rectangle-UV-array" count="25" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane4X4-vertices">
+ <input semantic="POSITION" source="#Plane4X4-positions"/>
+ <input semantic="NORMAL" source="#Plane4X4-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="32">
+ <input semantic="VERTEX" source="#Plane4X4-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane4X4-Rectangle-UV" offset="1" set="1"/>
+ <p>4 0 10 1 9 2 13 3 9 2 10 1 7 4 12 5 11 6 13 3 11 6 12 5 5 7 15 8 14 9 17 10 14 9 15 8 4 0 16 11 10 1 17 10 10 1 16 11 6 12 19 13 18 14 21 15 18 14 19 13 5 7 20 16 15 8 21 15 15 8 20 16 7 4 11 6 22 17 24 18 22 17 11 6 6 12 23 19 19 13 24 18 19 13 23 19 2 20 9 2 12 5 13 3 12 5 9 2 8 21 11 6 10 1 13 3 10 1 11 6 3 22 14 9 16 11 17 10 16 11 14 9 8 21 10 1 15 8 17 10 15 8 10 1 1 23 18 14 20 16 21 15 20 16 18 14 8 21 15 8 19 13 21 15 19 13 15 8 0 24 22 17 23 19 24 18 23 19 22 17 8 21 19 13 11 6 24 18 11 6 19 13</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided-4X4">
+ <node id="Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane4X4">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-8X8.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-8X8.dae
new file mode 100644
index 00000000..25629829
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-8X8.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided-8X8.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:35:19Z</created>
+ <modified>2008-09-19T17:35:19Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane8X8" name="Plane8X8">
+ <mesh>
+ <source id="Plane8X8-positions" name="position">
+ <float_array id="Plane8X8-positions-array" count="243">50 -50 0 -50 -50 0 50 50 0 -50 50 0 0 50 0 -50 0 0 0 -50 0 50 0 0 0 0 0 25 50 0 0 25 0 25 0 0 50 25 0 25 25 0 -50 25 0 -25 0 0 -25 50 0 -25 25 0 -25 -50 0 0 -25 0 -50 -25 0 -25 -25 0 50 -25 0 25 -50 0 25 -25 0 37.5 50 0 25 37.5 0 37.5 25 0 50 37.5 0 37.5 37.5 0 0 37.5 0 12.5 25 0 12.5 50 0 12.5 37.5 0 12.5 0 0 25 12.5 0 0 12.5 0 12.5 12.5 0 50 12.5 0 37.5 0 0 37.5 12.5 0 -50 37.5 0 -37.5 25 0 -25 37.5 0 -37.5 50 0 -37.5 37.5 0 -37.5 0 0 -25 12.5 0 -50 12.5 0 -37.5 12.5 0 -12.5 25 0 -12.5 0 0 -12.5 12.5 0 -12.5 50 0 -12.5 37.5 0 -37.5 -50 0 -25 -37.5 0 -37.5 -25 0 -50 -37.5 0 -37.5 -37.5 0 0 -37.5 0 -12.5 -25 0 -12.5 -50 0 -12.5 -37.5 0 -25 -12.5 0 0 -12.5 0 -12.5 -12.5 0 -50 -12.5 0 -37.5 -12.5 0 50 -37.5 0 37.5 -25 0 25 -37.5 0 37.5 -50 0 37.5 -37.5 0 25 -12.5 0 50 -12.5 0 37.5 -12.5 0 12.5 -25 0 12.5 -12.5 0 12.5 -50 0 12.5 -37.5 0</float_array>
+ <technique_common>
+ <accessor source="#Plane8X8-positions-array" count="81" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane8X8-normals" name="normal">
+ <float_array id="Plane8X8-normals-array" count="243">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Plane8X8-normals-array" count="81" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane8X8-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="Plane8X8-Rectangle-UV-array" count="162">0.75 1 0.75 0.875 0.875 1 0.875 0.875 1 0.75 1 0.875 0.875 0.75 0.5 0.75 0.625 0.75 0.5 0.875 0.625 0.875 0.625 1 0.75 0.5 0.75 0.625 0.625 0.5 0.625 0.625 0.5 0.625 1 0.625 0.875 0.625 0.875 0.5 0 0.75 0.125 0.75 0 0.875 0.125 0.875 0.25 1 0.125 1 0.25 0.875 0.25 0.5 0.25 0.625 0.125 0.5 0.125 0.625 0 0.625 0.375 0.75 0.375 0.625 0.375 0.5 0.375 1 0.375 0.875 0.25 0 0.25 0.125 0.125 0 0.125 0.125 0 0.25 0 0.125 0.125 0.25 0.5 0.25 0.375 0.25 0.5 0.125 0.375 0.125 0.375 0 0.25 0.375 0.375 0.375 0.5 0.375 0 0.375 0.125 0.375 1 0.25 0.875 0.25 1 0.125 0.875 0.125 0.75 0 0.875 0 0.75 0.125 0.75 0.375 0.875 0.375 1 0.375 0.625 0.25 0.625 0.375 0.625 0 0.625 0.125 1 1 0.75 0.75 0.5 1 0.5 0.5 1 0.5 0 1 0.25 0.75 0 0.5 0 0 0.25 0.25 0.5 0 1 0 0.75 0.25</float_array>
+ <technique_common>
+ <accessor source="#Plane8X8-Rectangle-UV-array" count="81" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane8X8-vertices">
+ <input semantic="POSITION" source="#Plane8X8-positions"/>
+ <input semantic="NORMAL" source="#Plane8X8-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="128">
+ <input semantic="VERTEX" source="#Plane8X8-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane8X8-Rectangle-UV" offset="1" set="1"/>
+ <p>9 0 26 1 25 2 29 3 25 2 26 1 12 4 28 5 27 6 29 3 27 6 28 5 10 7 31 8 30 9 33 10 30 9 31 8 9 0 32 11 26 1 33 10 26 1 32 11 11 12 35 13 34 14 37 15 34 14 35 13 10 7 36 16 31 8 37 15 31 8 36 16 12 4 27 6 38 17 40 18 38 17 27 6 11 12 39 19 35 13 40 18 35 13 39 19 14 20 42 21 41 22 45 23 41 22 42 21 16 24 44 25 43 26 45 23 43 26 44 25 15 27 47 28 46 29 49 30 46 29 47 28 14 20 48 31 42 21 49 30 42 21 48 31 10 7 50 32 36 16 52 33 36 16 50 32 15 27 51 34 47 28 52 33 47 28 51 34 16 24 43 26 53 35 54 36 53 35 43 26 10 7 30 9 50 32 54 36 50 32 30 9 18 37 56 38 55 39 59 40 55 39 56 38 20 41 58 42 57 43 59 40 57 43 58 42 19 44 61 45 60 46 63 47 60 46 61 45 18 37 62 48 56 38 63 47 56 38 62 48 15 27 64 49 51 34 66 50 51 34 64 49 19 44 65 51 61 45 66 50 61 45 65 51 20 41 57 43 67 52 68 53 67 52 57 43 15 27 46 29 64 49 68 53 64 49 46 29 22 54 70 55 69 56 73 57 69 56 70 55 23 58 72 59 71 60 73 57 71 60 72 59 11 12 74 61 39 19 76 62 39 19 74 61 22 54 75 63 70 55 76 62 70 55 75 63 19 44 77 64 65 51 78 65 65 51 77 64 11 12 34 14 74 61 78 65 74 61 34 14 23 58 71 60 79 66 80 67 79 66 71 60 19 44 60 46 77 64 80 67 77 64 60 46 2 68 25 2 28 5 29 3 28 5 25 2 13 69 27 6 26 1 29 3 26 1 27 6 4 70 30 9 32 11 33 10 32 11 30 9 13 69 26 1 31 8 33 10 31 8 26 1 8 71 34 14 36 16 37 15 36 16 34 14 13 69 31 8 35 13 37 15 35 13 31 8 7 72 38 17 39 19 40 18 39 19 38 17 13 69 35 13 27 6 40 18 27 6 35 13 3 73 41 22 44 25 45 23 44 25 41 22 17 74 43 26 42 21 45 23 42 21 43 26 5 75 46 29 48 31 49 30 48 31 46 29 17 74 42 21 47 28 49 30 47 28 42 21 8 71 36 16 51 34 52 33 51 34 36 16 17 74 47 28 50 32 52 33 50 32 47 28 4 70 53 35 30 9 54 36 30 9 53 35 17 74 50 32 43 26 54 36 43 26 50 32 1 76 55 39 58 42 59 40 58 42 55 39 21 77 57 43 56 38 59 40 56 38 57 43 6 78 60 46 62 48 63 47 62 48 60 46 21 77 56 38 61 45 63 47 61 45 56 38 8 71 51 34 65 51 66 50 65 51 51 34 21 77 61 45 64 49 66 50 64 49 61 45 5 75 67 52 46 29 68 53 46 29 67 52 21 77 64 49 57 43 68 53 57 43 64 49 0 79 69 56 72 59 73 57 72 59 69 56 24 80 71 60 70 55 73 57 70 55 71 60 7 72 39 19 75 63 76 62 75 63 39 19 24 80 70 55 74 61 76 62 74 61 70 55 8 71 65 51 34 14 78 65 34 14 65 51 24 80 74 61 77 64 78 65 77 64 74 61 6 78 79 66 60 46 80 67 60 46 79 66 24 80 77 64 71 60 80 67 71 60 77 64</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided-8X8">
+ <node id="Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane8X8">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-mirroredUVs.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-mirroredUVs.dae
new file mode 100644
index 00000000..9ad4ada2
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided-mirroredUVs.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided-mirrored-UVs.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:41:42Z</created>
+ <modified>2008-09-19T17:41:42Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="polySurfaceShape1" name="polySurfaceShape1">
+ <mesh>
+ <source id="polySurfaceShape1-positions" name="position">
+ <float_array id="polySurfaceShape1-positions-array" count="12">50 -50 0 -50 -50 0 50 50 0 -50 50 0</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-positions-array" count="4" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-normals" name="normal">
+ <float_array id="polySurfaceShape1-normals-array" count="12">0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-normals-array" count="4" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="polySurfaceShape1-Rectangle-UV-array" count="8">1 0 0 0 1 1 0 1</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-Rectangle-UV-array" count="4" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="polySurfaceShape1-vertices">
+ <input semantic="POSITION" source="#polySurfaceShape1-positions"/>
+ <input semantic="NORMAL" source="#polySurfaceShape1-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="2">
+ <input semantic="VERTEX" source="#polySurfaceShape1-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#polySurfaceShape1-Rectangle-UV" offset="1" set="1"/>
+ <p>2 0 3 1 0 2 1 3 0 2 3 1</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided-mirrored-UVs">
+ <node id="Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#polySurfaceShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided.dae b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided.dae
new file mode 100644
index 00000000..fb800e5a
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/Plane-SingleSided.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/planes/Plane-SingleSided.mb</source_data>
+ </contributor>
+ <created>2008-09-19T17:40:13Z</created>
+ <modified>2008-09-19T17:40:13Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Plane" name="Plane">
+ <mesh>
+ <source id="Plane-positions" name="position">
+ <float_array id="Plane-positions-array" count="12">50 -50 0 -50 -50 0 50 50 0 -50 50 0</float_array>
+ <technique_common>
+ <accessor source="#Plane-positions-array" count="4" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane-normals" name="normal">
+ <float_array id="Plane-normals-array" count="12">0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#Plane-normals-array" count="4" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Plane-Rectangle-UV" name="Rectangle-UV">
+ <float_array id="Plane-Rectangle-UV-array" count="8">1 1 0 1 1 0 0 0</float_array>
+ <technique_common>
+ <accessor source="#Plane-Rectangle-UV-array" count="4" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Plane-vertices">
+ <input semantic="POSITION" source="#Plane-positions"/>
+ <input semantic="NORMAL" source="#Plane-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="2">
+ <input semantic="VERTEX" source="#Plane-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Plane-Rectangle-UV" offset="1" set="1"/>
+ <p>2 0 3 1 0 2 1 3 0 2 3 1</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Plane-SingleSided">
+ <node id="_Plane" name="Plane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Plane">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-1.dae b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-1.dae
new file mode 100644
index 00000000..69f27423
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-1.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T17:45:23Z</created>
+ <modified>2008-09-19T17:45:23Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="polySurfaceShape1" name="polySurfaceShape1">
+ <mesh>
+ <source id="polySurfaceShape1-positions" name="position">
+ <float_array id="polySurfaceShape1-positions-array" count="96">-50 -32.5 0 -50 32.5 0 -50 36.4476 0 -48.9684 41.6339 0 -46.0306 46.0306 0 -41.6339 48.9684 0 -36.4476 50 0 -32.5 50 0 32.5 50 0 36.4476 50 0 41.6339 48.9684 0 46.0306 46.0306 0 48.9684 41.6339 0 50 36.4476 0 50 32.5 0 50 -32.5 0 50 -36.4476 0 48.9684 -41.6339 0 46.0306 -46.0306 0 41.6339 -48.9684 0 36.4476 -50 0 32.5 -50 0 -32.5 -50 0 -36.4476 -50 0 -41.6339 -48.9684 0 -46.0306 -46.0306 0 -48.9684 -41.6339 0 -50 -36.4476 0 -32.5 -32.5 0 32.5 -32.5 0 -32.5 32.5 0 32.5 32.5 0</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-positions-array" count="32" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-normals" name="normal">
+ <float_array id="polySurfaceShape1-normals-array" count="96">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-normals-array" count="32" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-Texture" name="Texture">
+ <float_array id="polySurfaceShape1-Texture-array" count="64">0 0.825 0.175 0.825 0 0.864476 0.010316 0.916339 0.039694 0.960306 0.083661 0.989684 0.135524 1 0.175 1 0.825 1 0.825 0.825 0.864476 1 0.916339 0.989684 0.960306 0.960306 0.989684 0.916339 1 0.864476 1 0.825 1 0.175 0.825 0.175 1 0.135524 0.989684 0.083661 0.960306 0.039694 0.916339 0.010316 0.864476 0 0.825 0 0.175 0 0.175 0.175 0.135524 0 0.083661 0.010316 0.039694 0.039694 0.010316 0.083661 0 0.135524 0 0.175</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-Texture-array" count="32" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="polySurfaceShape1-vertices">
+ <input semantic="POSITION" source="#polySurfaceShape1-positions"/>
+ <input semantic="NORMAL" source="#polySurfaceShape1-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="34">
+ <input semantic="VERTEX" source="#polySurfaceShape1-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#polySurfaceShape1-Texture" offset="1" set="1"/>
+ <p>1 0 30 1 2 2 2 2 30 1 3 3 3 3 30 1 4 4 4 4 30 1 5 5 5 5 30 1 6 6 6 6 30 1 7 7 8 8 31 9 9 10 9 10 31 9 10 11 10 11 31 9 11 12 11 12 31 9 12 13 12 13 31 9 13 14 13 14 31 9 14 15 15 16 29 17 16 18 16 18 29 17 17 19 17 19 29 17 18 20 18 20 29 17 19 21 19 21 29 17 20 22 20 22 29 17 21 23 22 24 28 25 23 26 23 26 28 25 24 27 24 27 28 25 25 28 25 28 28 25 26 29 26 29 28 25 27 30 27 30 28 25 0 31 0 31 28 25 1 0 30 1 1 0 28 25 14 15 31 9 15 16 29 17 15 16 31 9 28 25 29 17 30 1 31 9 30 1 29 17 7 7 30 1 8 8 31 9 8 8 30 1 21 23 29 17 22 24 28 25 22 24 29 17</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="RoundedPlane" name="RoundedPlane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#polySurfaceShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-2.dae b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-2.dae
new file mode 100644
index 00000000..5b38d1b3
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-2.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T17:46:34Z</created>
+ <modified>2008-09-19T17:46:34Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="polySurfaceShape1" name="polySurfaceShape1">
+ <mesh>
+ <source id="polySurfaceShape1-positions" name="position">
+ <float_array id="polySurfaceShape1-positions-array" count="108">-50 -25 0 -50 25 0 -50 29.7811 0 -49.0104 36.0291 0 -46.1385 41.6655 0 -41.6655 46.1385 0 -36.0291 49.0104 0 -29.7811 50 0 -25 50 0 25 50 0 29.7811 50 0 36.0291 49.0104 0 41.6655 46.1385 0 46.1385 41.6655 0 49.0104 36.0291 0 50 29.7811 0 50 25 0 50 -25 0 50 -29.7811 0 49.0104 -36.0291 0 46.1385 -41.6655 0 41.6655 -46.1385 0 36.0291 -49.0104 0 29.7811 -50 0 25 -50 0 -25 -50 0 -29.7811 -50 0 -36.0291 -49.0104 0 -41.6655 -46.1385 0 -46.1385 -41.6655 0 -49.0104 -36.0291 0 -50 -29.7811 0 -25 -25 0 25 -25 0 -25 25 0 25 25 0</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-positions-array" count="36" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-normals" name="normal">
+ <float_array id="polySurfaceShape1-normals-array" count="108">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-normals-array" count="36" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-Texture" name="Texture">
+ <float_array id="polySurfaceShape1-Texture-array" count="72">0 0.75 0.25 0.75 0 0.797811 0.009895 0.860291 0.038614 0.916655 0.083345 0.961385 0.139709 0.990104 0.202189 1 0.25 1 0.75 1 0.75 0.75 0.797811 1 0.860291 0.990104 0.916655 0.961385 0.961385 0.916655 0.990104 0.860291 1 0.797811 1 0.75 1 0.25 0.75 0.25 1 0.202189 0.990104 0.139709 0.961385 0.083345 0.916655 0.038614 0.860291 0.009895 0.797811 0 0.75 0 0.25 0 0.25 0.25 0.202189 0 0.139709 0.009895 0.083345 0.038614 0.038614 0.083345 0.009895 0.139709 0 0.202189 0 0.25</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-Texture-array" count="36" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="polySurfaceShape1-vertices">
+ <input semantic="POSITION" source="#polySurfaceShape1-positions"/>
+ <input semantic="NORMAL" source="#polySurfaceShape1-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="38">
+ <input semantic="VERTEX" source="#polySurfaceShape1-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#polySurfaceShape1-Texture" offset="1" set="1"/>
+ <p>1 0 34 1 2 2 2 2 34 1 3 3 3 3 34 1 4 4 4 4 34 1 5 5 5 5 34 1 6 6 6 6 34 1 7 7 7 7 34 1 8 8 9 9 35 10 10 11 10 11 35 10 11 12 11 12 35 10 12 13 12 13 35 10 13 14 13 14 35 10 14 15 14 15 35 10 15 16 15 16 35 10 16 17 17 18 33 19 18 20 18 20 33 19 19 21 19 21 33 19 20 22 20 22 33 19 21 23 21 23 33 19 22 24 22 24 33 19 23 25 23 25 33 19 24 26 25 27 32 28 26 29 26 29 32 28 27 30 27 30 32 28 28 31 28 31 32 28 29 32 29 32 32 28 30 33 30 33 32 28 31 34 31 34 32 28 0 35 0 35 32 28 1 0 34 1 1 0 32 28 8 8 34 1 9 9 35 10 9 9 34 1 16 17 35 10 17 18 33 19 17 18 35 10 24 26 33 19 25 27 32 28 25 27 33 19 32 28 33 19 34 1 35 10 34 1 33 19</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="RoundedPlane" name="RoundedPlane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#polySurfaceShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3a.dae b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3a.dae
new file mode 100644
index 00000000..f9de3a89
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3a.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T17:47:28Z</created>
+ <modified>2008-09-19T17:47:28Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="polySurfaceShape1" name="polySurfaceShape1">
+ <mesh>
+ <source id="polySurfaceShape1-positions" name="position">
+ <float_array id="polySurfaceShape1-positions-array" count="120">-50 -7.5 0 -50 7.5 0 -50 14.5544 0 -48.7922 23.7284 0 -45.2512 32.2772 0 -39.6182 39.6182 0 -32.2772 45.2512 0 -23.7284 48.7922 0 -14.5544 50 0 -7.5 50 0 7.5 50 0 14.5544 50 0 23.7284 48.7922 0 32.2772 45.2512 0 39.6182 39.6182 0 45.2512 32.2772 0 48.7922 23.7284 0 50 14.5544 0 50 7.5 0 50 -7.5 0 50 -14.5544 0 48.7922 -23.7284 0 45.2512 -32.2772 0 39.6182 -39.6182 0 32.2772 -45.2512 0 23.7284 -48.7922 0 14.5544 -50 0 7.5 -50 0 -7.5 -50 0 -14.5544 -50 0 -23.7284 -48.7922 0 -32.2772 -45.2512 0 -39.6182 -39.6182 0 -45.2512 -32.2772 0 -48.7922 -23.7284 0 -50 -14.5544 0 -7.5 -7.5 0 7.5 -7.5 0 -7.5 7.5 0 7.5 7.5 0</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-positions-array" count="40" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-normals" name="normal">
+ <float_array id="polySurfaceShape1-normals-array" count="120">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-normals-array" count="40" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-Texture" name="Texture">
+ <float_array id="polySurfaceShape1-Texture-array" count="80">0 0.575 0.425 0.575 0 0.645544 0.012077 0.737284 0.047488 0.822772 0.103818 0.896182 0.177228 0.952512 0.262716 0.987922 0.354456 1 0.425 1 0.575 1 0.575 0.575 0.645544 1 0.737284 0.987922 0.822772 0.952512 0.896182 0.896182 0.952512 0.822772 0.987922 0.737284 1 0.645544 1 0.575 1 0.425 0.575 0.425 1 0.354456 0.987922 0.262716 0.952512 0.177228 0.896182 0.103818 0.822772 0.047488 0.737284 0.012077 0.645544 0 0.575 0 0.425 0 0.425 0.425 0.354456 0 0.262716 0.012077 0.177228 0.047488 0.103818 0.103818 0.047488 0.177228 0.012077 0.262716 0 0.354456 0 0.425</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-Texture-array" count="40" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="polySurfaceShape1-vertices">
+ <input semantic="POSITION" source="#polySurfaceShape1-positions"/>
+ <input semantic="NORMAL" source="#polySurfaceShape1-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="42">
+ <input semantic="VERTEX" source="#polySurfaceShape1-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#polySurfaceShape1-Texture" offset="1" set="1"/>
+ <p>1 0 38 1 2 2 2 2 38 1 3 3 3 3 38 1 4 4 4 4 38 1 5 5 5 5 38 1 6 6 6 6 38 1 7 7 7 7 38 1 8 8 8 8 38 1 9 9 10 10 39 11 11 12 11 12 39 11 12 13 12 13 39 11 13 14 13 14 39 11 14 15 14 15 39 11 15 16 15 16 39 11 16 17 16 17 39 11 17 18 17 18 39 11 18 19 19 20 37 21 20 22 20 22 37 21 21 23 21 23 37 21 22 24 22 24 37 21 23 25 23 25 37 21 24 26 24 26 37 21 25 27 25 27 37 21 26 28 26 28 37 21 27 29 28 30 36 31 29 32 29 32 36 31 30 33 30 33 36 31 31 34 31 34 36 31 32 35 32 35 36 31 33 36 33 36 36 31 34 37 34 37 36 31 35 38 35 38 36 31 0 39 0 39 36 31 1 0 38 1 1 0 36 31 18 19 39 11 19 20 37 21 19 20 39 11 36 31 37 21 38 1 39 11 38 1 37 21 9 9 38 1 10 10 39 11 10 10 38 1 27 29 37 21 28 30 36 31 28 30 37 21</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="RoundedPlane" name="RoundedPlane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#polySurfaceShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3b.dae b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3b.dae
new file mode 100644
index 00000000..41fd5f24
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Planes/RoundedPlane-3b.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T17:48:26Z</created>
+ <modified>2008-09-19T17:48:26Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="polySurfaceShape1" name="polySurfaceShape1">
+ <mesh>
+ <source id="polySurfaceShape1-positions" name="position">
+ <float_array id="polySurfaceShape1-positions-array" count="144">-50 -7.5 0 -50 7.5 0 -50 13.0802 0 -49.2906 20.2829 0 -47.1896 27.2088 0 -43.7779 33.5917 0 -39.1864 39.1864 0 -33.5917 43.7779 0 -27.2088 47.1897 0 -20.2829 49.2906 0 -13.0802 50 0 -7.5 50 0 7.5 50 0 13.0802 50 0 20.2829 49.2906 0 27.2088 47.1897 0 33.5917 43.7779 0 39.1864 39.1864 0 43.7779 33.5917 0 47.1897 27.2088 0 49.2906 20.2829 0 50 13.0802 0 50 7.5 0 50 -7.5 0 50 -13.0802 0 49.2906 -20.2829 0 47.1897 -27.2088 0 43.7779 -33.5917 0 39.1864 -39.1864 0 33.5917 -43.7779 0 27.2088 -47.1896 0 20.2829 -49.2906 0 13.0802 -50 0 7.5 -50 0 -7.5 -50 0 -13.0802 -50 0 -20.2829 -49.2906 0 -27.2088 -47.1896 0 -33.5917 -43.7779 0 -39.1864 -39.1864 0 -43.7779 -33.5917 0 -47.1896 -27.2088 0 -49.2906 -20.2829 0 -50 -13.0802 0 -7.5 -7.5 0 7.5 -7.5 0 -7.5 7.5 0 7.5 7.5 0</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-positions-array" count="48" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-normals" name="normal">
+ <float_array id="polySurfaceShape1-normals-array" count="144">0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-normals-array" count="48" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="polySurfaceShape1-Texture" name="Texture">
+ <float_array id="polySurfaceShape1-Texture-array" count="96">0 0.575 0.425 0.575 0 0.630802 0.007094 0.702829 0.028103 0.772088 0.062221 0.835917 0.108136 0.891864 0.164083 0.937779 0.227912 0.971897 0.297171 0.992906 0.369198 1 0.425 1 0.575 1 0.575 0.575 0.630802 1 0.702829 0.992906 0.772088 0.971897 0.835917 0.937779 0.891864 0.891864 0.937779 0.835917 0.971897 0.772088 0.992906 0.702829 1 0.630802 1 0.575 1 0.425 0.575 0.425 1 0.369198 0.992906 0.297171 0.971897 0.227912 0.937779 0.164083 0.891864 0.108136 0.835917 0.062221 0.772088 0.028103 0.702829 0.007094 0.630802 0 0.575 0 0.425 0 0.425 0.425 0.369198 0 0.297171 0.007094 0.227912 0.028103 0.164083 0.062221 0.108136 0.108136 0.062221 0.164083 0.028103 0.227912 0.007094 0.297171 0 0.369198 0 0.425</float_array>
+ <technique_common>
+ <accessor source="#polySurfaceShape1-Texture-array" count="48" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="polySurfaceShape1-vertices">
+ <input semantic="POSITION" source="#polySurfaceShape1-positions"/>
+ <input semantic="NORMAL" source="#polySurfaceShape1-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="50">
+ <input semantic="VERTEX" source="#polySurfaceShape1-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#polySurfaceShape1-Texture" offset="1" set="1"/>
+ <p>1 0 46 1 2 2 2 2 46 1 3 3 3 3 46 1 4 4 4 4 46 1 5 5 5 5 46 1 6 6 6 6 46 1 7 7 7 7 46 1 8 8 8 8 46 1 9 9 9 9 46 1 10 10 10 10 46 1 11 11 12 12 47 13 13 14 13 14 47 13 14 15 14 15 47 13 15 16 15 16 47 13 16 17 16 17 47 13 17 18 17 18 47 13 18 19 18 19 47 13 19 20 19 20 47 13 20 21 20 21 47 13 21 22 21 22 47 13 22 23 23 24 45 25 24 26 24 26 45 25 25 27 25 27 45 25 26 28 26 28 45 25 27 29 27 29 45 25 28 30 28 30 45 25 29 31 29 31 45 25 30 32 30 32 45 25 31 33 31 33 45 25 32 34 32 34 45 25 33 35 34 36 44 37 35 38 35 38 44 37 36 39 36 39 44 37 37 40 37 40 44 37 38 41 38 41 44 37 39 42 39 42 44 37 40 43 40 43 44 37 41 44 41 44 44 37 42 45 42 45 44 37 43 46 43 46 44 37 0 47 0 47 44 37 1 0 46 1 1 0 44 37 22 23 47 13 23 24 45 25 23 24 47 13 44 37 45 25 46 1 47 13 46 1 45 25 11 11 46 1 12 12 47 13 12 12 46 1 33 35 45 25 34 36 44 37 34 36 45 25</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="RoundedPlane" name="RoundedPlane" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#polySurfaceShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-high-doublesided.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-high-doublesided.dae
new file mode 100644
index 00000000..2e904ce5
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-high-doublesided.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-high-doublesided.mb</source_data>
+ </contributor>
+ <created>2008-09-19T22:05:55Z</created>
+ <modified>2008-09-19T22:05:55Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="2172">0 50 0 8.72494 49.1512 2.8349 0 49.1512 9.17395 17.1537 46.6335 5.57358 8.84255 47.6832 12.1707 0 46.6335 18.0365 25 42.5325 8.12299 17.2996 44.4764 14.919 8.84298 44.4764 21.0631 0 42.5325 26.2866 31.9975 36.9875 10.3966 26.1426 38.7299 17.7923 17.8411 39.7327 24.5562 8.84298 38.7299 30.3612 0 36.9875 33.6441 37.9086 30.1865 12.3172 32.6527 32.2104 19.9071 26.1426 33.2344 26.6841 17.2996 33.2344 33.1089 8.84255 32.2104 37.2062 0 30.1865 39.8594 42.5325 22.3607 13.8197 37.9086 24.5167 21.4912 31.9975 25.8403 28.4331 25 26.2866 34.4095 17.1537 25.8403 39.2177 8.72494 24.5167 42.6943 0 22.3607 44.7214 5.39231 49.1512 -7.42188 10.6016 46.6335 -14.5918 14.3075 47.6832 -4.6488 15.4509 42.5325 -21.2663 19.5347 44.4764 -11.8426 22.7648 44.4764 -1.90132 19.7755 36.9875 -27.2187 25 38.7299 -19.3649 28.8675 39.7327 -9.37962 31.6078 38.7299 0.971941 23.4288 30.1865 -32.247 29.023 32.2104 -24.9029 33.4566 33.2344 -16.6172 36.8343 33.2344 -6.22166 38.1177 32.2104 3.08758 26.2866 22.3607 -36.1803 32.1537 24.5167 -29.4121 36.9292 25.8403 -21.6451 40.4509 26.2866 -13.1433 42.599 25.8403 -4.19521 43.3009 24.5167 4.89537 -5.39231 49.1512 -7.42188 -10.6016 46.6335 -14.5918 0 47.6832 -15.0438 -15.4509 42.5325 -21.2663 -5.22646 44.4764 -22.2382 5.22646 44.4764 -22.2382 -19.7755 36.9875 -27.2187 -10.6917 38.7299 -29.7605 0 39.7327 -30.3531 10.6917 38.7299 -29.7605 -23.4288 30.1865 -32.247 -14.7155 32.2104 -35.298 -5.46526 33.2344 -36.9541 5.46526 33.2344 -36.9541 14.7155 32.2104 -35.298 -26.2866 22.3607 -36.1803 -18.0365 24.5167 -39.6688 -9.17395 25.8403 -41.8105 0 26.2866 -42.5325 9.17395 25.8403 -41.8105 18.0365 24.5167 -39.6688 -8.72494 49.1512 2.8349 -17.1537 46.6335 5.57358 -14.3075 47.6832 -4.6488 -25 42.5325 8.12299 -22.7648 44.4764 -1.90132 -19.5347 44.4764 -11.8426 -31.9975 36.9875 10.3966 -31.6078 38.7299 0.971941 -28.8675 39.7327 -9.37962 -25 38.7299 -19.3649 -37.9086 30.1865 12.3172 -38.1177 32.2104 3.08758 -36.8343 33.2344 -6.22166 -33.4566 33.2344 -16.6172 -29.023 32.2104 -24.9029 -42.5325 22.3607 13.8197 -43.3009 24.5167 4.89537 -42.599 25.8403 -4.19521 -40.4509 26.2866 -13.1433 -36.9292 25.8403 -21.6451 -32.1537 24.5167 -29.4121 -8.84255 47.6832 12.1707 -8.84298 44.4764 21.0631 -17.2996 44.4764 14.919 -8.84298 38.7299 30.3612 -17.8411 39.7327 24.5562 -26.1426 38.7299 17.7923 -8.84255 32.2104 37.2062 -17.2996 33.2344 33.1089 -26.1426 33.2344 26.6841 -32.6527 32.2104 19.9071 -8.72494 24.5167 42.6943 -17.1537 25.8403 39.2177 -25 26.2866 34.4095 -31.9975 25.8403 28.4331 -37.9086 24.5167 21.4912 0 -50 0 5.39231 -49.1512 7.42188 8.72494 -49.1512 -2.8349 10.6016 -46.6335 14.5918 14.3075 -47.6832 4.6488 17.1537 -46.6335 -5.57358 15.4509 -42.5325 21.2663 19.5347 -44.4764 11.8426 22.7648 -44.4764 1.90132 25 -42.5325 -8.12299 19.7755 -36.9875 27.2187 25 -38.7299 19.3649 28.8675 -39.7327 9.37962 31.6078 -38.7299 -0.971941 31.9975 -36.9875 -10.3966 23.4288 -30.1865 32.247 29.023 -32.2104 24.9029 33.4566 -33.2344 16.6172 36.8343 -33.2344 6.22166 38.1177 -32.2104 -3.08758 37.9086 -30.1865 -12.3172 26.2866 -22.3607 36.1803 32.1537 -24.5167 29.4121 36.9292 -25.8403 21.6451 40.4509 -26.2866 13.1433 42.599 -25.8403 4.19521 43.3009 -24.5167 -4.89537 42.5325 -22.3607 -13.8197 0 -49.1512 -9.17395 8.84255 -47.6832 -12.1707 0 -46.6335 -18.0365 17.2996 -44.4764 -14.919 8.84298 -44.4764 -21.0631 0 -42.5325 -26.2866 26.1426 -38.7299 -17.7923 17.8411 -39.7327 -24.5562 8.84298 -38.7299 -30.3612 0 -36.9875 -33.6441 32.6527 -32.2104 -19.9071 26.1426 -33.2344 -26.6841 17.2996 -33.2344 -33.1089 8.84255 -32.2104 -37.2062 0 -30.1865 -39.8594 37.9086 -24.5167 -21.4912 31.9975 -25.8403 -28.4331 25 -26.2866 -34.4095 17.1537 -25.8403 -39.2177 8.72494 -24.5167 -42.6943 0 -22.3607 -44.7214 -8.72494 -49.1512 -2.8349 -8.84255 -47.6832 -12.1707 -17.1537 -46.6335 -5.57358 -8.84298 -44.4764 -21.0631 -17.2996 -44.4764 -14.919 -25 -42.5325 -8.12299 -8.84298 -38.7299 -30.3612 -17.8411 -39.7327 -24.5562 -26.1426 -38.7299 -17.7923 -31.9975 -36.9875 -10.3966 -8.84255 -32.2104 -37.2062 -17.2996 -33.2344 -33.1089 -26.1426 -33.2344 -26.6841 -32.6527 -32.2104 -19.9071 -37.9086 -30.1865 -12.3172 -8.72494 -24.5167 -42.6943 -17.1537 -25.8403 -39.2177 -25 -26.2866 -34.4095 -31.9975 -25.8403 -28.4331 -37.9086 -24.5167 -21.4912 -42.5325 -22.3607 -13.8197 -5.39231 -49.1512 7.42188 -14.3075 -47.6832 4.6488 -10.6016 -46.6335 14.5918 -22.7648 -44.4764 1.90132 -19.5347 -44.4764 11.8426 -15.4509 -42.5325 21.2663 -31.6078 -38.7299 -0.971941 -28.8675 -39.7327 9.37962 -25 -38.7299 19.3649 -19.7755 -36.9875 27.2187 -38.1177 -32.2104 -3.08758 -36.8343 -33.2344 6.22166 -33.4566 -33.2344 16.6172 -29.023 -32.2104 24.9029 -23.4288 -30.1865 32.247 -43.3009 -24.5167 -4.89537 -42.599 -25.8403 4.19521 -40.4509 -26.2866 13.1433 -36.9292 -25.8403 21.6451 -32.1537 -24.5167 29.4121 -26.2866 -22.3607 36.1803 0 -47.6832 15.0438 -5.22646 -44.4764 22.2382 5.22646 -44.4764 22.2382 -10.6917 -38.7299 29.7605 0 -39.7327 30.3531 10.6917 -38.7299 29.7605 -14.7155 -32.2104 35.298 -5.46526 -33.2344 36.9541 5.46526 -33.2344 36.9541 14.7155 -32.2104 35.298 -18.0365 -24.5167 39.6688 -9.17395 -25.8403 41.8105 0 -26.2866 42.5325 9.17395 -25.8403 41.8105 18.0365 -24.5167 39.6688 5.39231 15.3427 47.2813 14.3075 17.1665 44.7281 10.6016 7.80382 48.236 22.7648 18.1898 40.6312 19.5347 9.29806 45.0771 15.4509 0 47.5528 31.6078 18.1898 34.2064 28.8675 9.37962 39.7327 25 0 43.3013 19.7755 -7.80382 45.2552 38.1177 17.1665 27.429 36.8343 9.29806 32.5082 33.4566 0 37.1572 29.023 -7.86893 39.9468 23.4288 -15.3427 41.4209 43.3009 15.3427 19.7391 42.599 7.80382 24.9884 40.4509 0 29.3893 36.9292 -7.80382 32.7923 32.1537 -15.3427 35.0819 46.6335 15.3427 9.48234 46.9602 17.1665 0.214459 49.1512 7.80382 4.82303 45.6773 18.1898 -9.09492 48.9074 9.29806 -4.64903 50 0 0 42.2995 18.1898 -19.4905 46.7086 9.37962 -15.1765 48.9074 0 -10.3955 49.1512 -7.80382 -4.82303 37.8656 17.1665 -27.776 42.2995 9.29806 -24.9859 45.6773 0 -20.3369 46.9602 -7.86893 -15.2583 46.6335 -15.3427 -9.48234 32.1537 15.3427 -35.0819 36.9292 7.80382 -32.7923 40.4509 0 -29.3893 42.599 -7.80382 -24.9884 43.3009 -15.3427 -19.7391 23.4288 15.3427 -41.4209 14.7155 17.1665 -44.5956 19.7755 7.80382 -45.2552 5.46526 18.1898 -46.2521 10.6917 9.29806 -47.9503 15.4509 0 -47.5528 -5.46526 18.1898 -46.2521 0 9.37962 -49.1123 5.22646 0 -49.7261 10.6016 -7.80382 -48.236 -14.7155 17.1665 -44.5956 -10.6917 9.29806 -47.9503 -5.22646 0 -49.7261 0 -7.86893 -49.3769 5.39231 -15.3427 -47.2813 -23.4288 15.3427 -41.4209 -19.7755 7.80382 -45.2552 -15.4509 0 -47.5528 -10.6016 -7.80382 -48.236 -5.39231 -15.3427 -47.2813 -32.1537 15.3427 -35.0819 -37.8656 17.1665 -27.776 -36.9292 7.80382 -32.7923 -42.2995 18.1898 -19.4905 -42.2995 9.29806 -24.9859 -40.4509 0 -29.3893 -45.6773 18.1898 -9.09492 -46.7086 9.37962 -15.1765 -45.6773 0 -20.3369 -42.599 -7.80382 -24.9884 -46.9602 17.1665 0.214459 -48.9074 9.29806 -4.64903 -48.9074 0 -10.3955 -46.9602 -7.86893 -15.2583 -43.3009 -15.3427 -19.7391 -46.6335 15.3427 9.48234 -49.1512 7.80382 4.82303 -50 0 0 -49.1512 -7.80382 -4.82303 -46.6335 -15.3427 -9.48234 -43.3009 15.3427 19.7391 -38.1177 17.1665 27.429 -42.599 7.80382 24.9884 -31.6078 18.1898 34.2064 -36.8343 9.29806 32.5082 -40.4509 0 29.3893 -22.7648 18.1898 40.6312 -28.8675 9.37962 39.7327 -33.4566 0 37.1572 -36.9292 -7.80382 32.7923 -14.3075 17.1665 44.7281 -19.5347 9.29806 45.0771 -25 0 43.3013 -29.023 -7.86893 39.9468 -32.1537 -15.3427 35.0819 -5.39231 15.3427 47.2813 -10.6016 7.80382 48.236 -15.4509 0 47.5528 -19.7755 -7.80382 45.2552 -23.4288 -15.3427 41.4209 46.9602 -17.1665 -0.214459 45.6773 -18.1898 9.09492 48.9074 -9.29806 4.64903 42.2995 -18.1898 19.4905 46.7086 -9.37962 15.1765 48.9074 0 10.3955 37.8656 -17.1665 27.776 42.2995 -9.29806 24.9859 45.6773 0 20.3369 46.9602 7.86893 15.2583 14.3075 -17.1665 -44.7281 22.7648 -18.1898 -40.6312 19.5347 -9.29806 -45.0771 31.6078 -18.1898 -34.2064 28.8675 -9.37962 -39.7327 25 0 -43.3013 38.1177 -17.1665 -27.429 36.8343 -9.29806 -32.5082 33.4566 0 -37.1572 29.023 7.86893 -39.9468 -38.1177 -17.1665 -27.429 -31.6078 -18.1898 -34.2064 -36.8343 -9.29806 -32.5082 -22.7648 -18.1898 -40.6312 -28.8675 -9.37962 -39.7327 -33.4566 0 -37.1572 -14.3075 -17.1665 -44.7281 -19.5347 -9.29806 -45.0771 -25 0 -43.3013 -29.023 7.86893 -39.9468 -37.8656 -17.1665 27.776 -42.2995 -18.1898 19.4905 -42.2995 -9.29806 24.9859 -45.6773 -18.1898 9.09492 -46.7086 -9.37962 15.1765 -45.6773 0 20.3369 -46.9602 -17.1665 -0.214459 -48.9074 -9.29806 4.64903 -48.9074 0 10.3955 -46.9602 7.86893 15.2583 14.7155 -17.1665 44.5956 5.46526 -18.1898 46.2521 10.6917 -9.29806 47.9503 -5.46526 -18.1898 46.2521 0 -9.37962 49.1123 5.22646 0 49.7261 -14.7155 -17.1665 44.5956 -10.6917 -9.29806 47.9503 -5.22646 0 49.7261 0 7.86893 49.3769 0 50 0 8.72494 49.1512 2.8349 0 49.1512 9.17395 17.1537 46.6335 5.57358 8.84255 47.6832 12.1707 0 46.6335 18.0365 25 42.5325 8.12299 17.2996 44.4764 14.919 8.84298 44.4764 21.0631 0 42.5325 26.2866 31.9975 36.9875 10.3966 26.1426 38.7299 17.7923 17.8411 39.7327 24.5562 8.84298 38.7299 30.3612 0 36.9875 33.6441 37.9086 30.1865 12.3172 32.6527 32.2104 19.9071 26.1426 33.2344 26.6841 17.2996 33.2344 33.1089 8.84255 32.2104 37.2062 0 30.1865 39.8594 42.5325 22.3607 13.8197 37.9086 24.5167 21.4912 31.9975 25.8403 28.4331 25 26.2866 34.4095 17.1537 25.8403 39.2177 8.72494 24.5167 42.6943 0 22.3607 44.7214 5.39231 49.1512 -7.42188 10.6016 46.6335 -14.5918 14.3075 47.6832 -4.6488 15.4509 42.5325 -21.2663 19.5347 44.4764 -11.8426 22.7648 44.4764 -1.90132 19.7755 36.9875 -27.2187 25 38.7299 -19.3649 28.8675 39.7327 -9.37962 31.6078 38.7299 0.971941 23.4288 30.1865 -32.247 29.023 32.2104 -24.9029 33.4566 33.2344 -16.6172 36.8343 33.2344 -6.22166 38.1177 32.2104 3.08758 26.2866 22.3607 -36.1803 32.1537 24.5167 -29.4121 36.9292 25.8403 -21.6451 40.4509 26.2866 -13.1433 42.599 25.8403 -4.19521 43.3009 24.5167 4.89537 -5.39231 49.1512 -7.42188 -10.6016 46.6335 -14.5918 0 47.6832 -15.0438 -15.4509 42.5325 -21.2663 -5.22646 44.4764 -22.2382 5.22646 44.4764 -22.2382 -19.7755 36.9875 -27.2187 -10.6917 38.7299 -29.7605 0 39.7327 -30.3531 10.6917 38.7299 -29.7605 -23.4288 30.1865 -32.247 -14.7155 32.2104 -35.298 -5.46526 33.2344 -36.9541 5.46526 33.2344 -36.9541 14.7155 32.2104 -35.298 -26.2866 22.3607 -36.1803 -18.0365 24.5167 -39.6688 -9.17395 25.8403 -41.8105 0 26.2866 -42.5325 9.17395 25.8403 -41.8105 18.0365 24.5167 -39.6688 -8.72494 49.1512 2.8349 -17.1537 46.6335 5.57358 -14.3075 47.6832 -4.6488 -25 42.5325 8.12299 -22.7648 44.4764 -1.90132 -19.5347 44.4764 -11.8426 -31.9975 36.9875 10.3966 -31.6078 38.7299 0.971941 -28.8675 39.7327 -9.37962 -25 38.7299 -19.3649 -37.9086 30.1865 12.3172 -38.1177 32.2104 3.08758 -36.8343 33.2344 -6.22166 -33.4566 33.2344 -16.6172 -29.023 32.2104 -24.9029 -42.5325 22.3607 13.8197 -43.3009 24.5167 4.89537 -42.599 25.8403 -4.19521 -40.4509 26.2866 -13.1433 -36.9292 25.8403 -21.6451 -32.1537 24.5167 -29.4121 -8.84255 47.6832 12.1707 -8.84298 44.4764 21.0631 -17.2996 44.4764 14.919 -8.84298 38.7299 30.3612 -17.8411 39.7327 24.5562 -26.1426 38.7299 17.7923 -8.84255 32.2104 37.2062 -17.2996 33.2344 33.1089 -26.1426 33.2344 26.6841 -32.6527 32.2104 19.9071 -8.72494 24.5167 42.6943 -17.1537 25.8403 39.2177 -25 26.2866 34.4095 -31.9975 25.8403 28.4331 -37.9086 24.5167 21.4912 0 -50 0 5.39231 -49.1512 7.42188 8.72494 -49.1512 -2.8349 10.6016 -46.6335 14.5918 14.3075 -47.6832 4.6488 17.1537 -46.6335 -5.57358 15.4509 -42.5325 21.2663 19.5347 -44.4764 11.8426 22.7648 -44.4764 1.90132 25 -42.5325 -8.12299 19.7755 -36.9875 27.2187 25 -38.7299 19.3649 28.8675 -39.7327 9.37962 31.6078 -38.7299 -0.971941 31.9975 -36.9875 -10.3966 23.4288 -30.1865 32.247 29.023 -32.2104 24.9029 33.4566 -33.2344 16.6172 36.8343 -33.2344 6.22166 38.1177 -32.2104 -3.08758 37.9086 -30.1865 -12.3172 26.2866 -22.3607 36.1803 32.1537 -24.5167 29.4121 36.9292 -25.8403 21.6451 40.4509 -26.2866 13.1433 42.599 -25.8403 4.19521 43.3009 -24.5167 -4.89537 42.5325 -22.3607 -13.8197 0 -49.1512 -9.17395 8.84255 -47.6832 -12.1707 0 -46.6335 -18.0365 17.2996 -44.4764 -14.919 8.84298 -44.4764 -21.0631 0 -42.5325 -26.2866 26.1426 -38.7299 -17.7923 17.8411 -39.7327 -24.5562 8.84298 -38.7299 -30.3612 0 -36.9875 -33.6441 32.6527 -32.2104 -19.9071 26.1426 -33.2344 -26.6841 17.2996 -33.2344 -33.1089 8.84255 -32.2104 -37.2062 0 -30.1865 -39.8594 37.9086 -24.5167 -21.4912 31.9975 -25.8403 -28.4331 25 -26.2866 -34.4095 17.1537 -25.8403 -39.2177 8.72494 -24.5167 -42.6943 0 -22.3607 -44.7214 -8.72494 -49.1512 -2.8349 -8.84255 -47.6832 -12.1707 -17.1537 -46.6335 -5.57358 -8.84298 -44.4764 -21.0631 -17.2996 -44.4764 -14.919 -25 -42.5325 -8.12299 -8.84298 -38.7299 -30.3612 -17.8411 -39.7327 -24.5562 -26.1426 -38.7299 -17.7923 -31.9975 -36.9875 -10.3966 -8.84255 -32.2104 -37.2062 -17.2996 -33.2344 -33.1089 -26.1426 -33.2344 -26.6841 -32.6527 -32.2104 -19.9071 -37.9086 -30.1865 -12.3172 -8.72494 -24.5167 -42.6943 -17.1537 -25.8403 -39.2177 -25 -26.2866 -34.4095 -31.9975 -25.8403 -28.4331 -37.9086 -24.5167 -21.4912 -42.5325 -22.3607 -13.8197 -5.39231 -49.1512 7.42188 -14.3075 -47.6832 4.6488 -10.6016 -46.6335 14.5918 -22.7648 -44.4764 1.90132 -19.5347 -44.4764 11.8426 -15.4509 -42.5325 21.2663 -31.6078 -38.7299 -0.971941 -28.8675 -39.7327 9.37962 -25 -38.7299 19.3649 -19.7755 -36.9875 27.2187 -38.1177 -32.2104 -3.08758 -36.8343 -33.2344 6.22166 -33.4566 -33.2344 16.6172 -29.023 -32.2104 24.9029 -23.4288 -30.1865 32.247 -43.3009 -24.5167 -4.89537 -42.599 -25.8403 4.19521 -40.4509 -26.2866 13.1433 -36.9292 -25.8403 21.6451 -32.1537 -24.5167 29.4121 -26.2866 -22.3607 36.1803 0 -47.6832 15.0438 -5.22646 -44.4764 22.2382 5.22646 -44.4764 22.2382 -10.6917 -38.7299 29.7605 0 -39.7327 30.3531 10.6917 -38.7299 29.7605 -14.7155 -32.2104 35.298 -5.46526 -33.2344 36.9541 5.46526 -33.2344 36.9541 14.7155 -32.2104 35.298 -18.0365 -24.5167 39.6688 -9.17395 -25.8403 41.8105 0 -26.2866 42.5325 9.17395 -25.8403 41.8105 18.0365 -24.5167 39.6688 5.39231 15.3427 47.2813 14.3075 17.1665 44.7281 10.6016 7.80382 48.236 22.7648 18.1898 40.6312 19.5347 9.29806 45.0771 15.4509 0 47.5528 31.6078 18.1898 34.2064 28.8675 9.37962 39.7327 25 0 43.3013 19.7755 -7.80382 45.2552 38.1177 17.1665 27.429 36.8343 9.29806 32.5082 33.4566 0 37.1572 29.023 -7.86893 39.9468 23.4288 -15.3427 41.4209 43.3009 15.3427 19.7391 42.599 7.80382 24.9884 40.4509 0 29.3893 36.9292 -7.80382 32.7923 32.1537 -15.3427 35.0819 46.6335 15.3427 9.48234 46.9602 17.1665 0.214459 49.1512 7.80382 4.82303 45.6773 18.1898 -9.09492 48.9074 9.29806 -4.64903 50 0 0 42.2995 18.1898 -19.4905 46.7086 9.37962 -15.1765 48.9074 0 -10.3955 49.1512 -7.80382 -4.82303 37.8656 17.1665 -27.776 42.2995 9.29806 -24.9859 45.6773 0 -20.3369 46.9602 -7.86893 -15.2583 46.6335 -15.3427 -9.48234 32.1537 15.3427 -35.0819 36.9292 7.80382 -32.7923 40.4509 0 -29.3893 42.599 -7.80382 -24.9884 43.3009 -15.3427 -19.7391 23.4288 15.3427 -41.4209 14.7155 17.1665 -44.5956 19.7755 7.80382 -45.2552 5.46526 18.1898 -46.2521 10.6917 9.29806 -47.9503 15.4509 0 -47.5528 -5.46526 18.1898 -46.2521 0 9.37962 -49.1123 5.22646 0 -49.7261 10.6016 -7.80382 -48.236 -14.7155 17.1665 -44.5956 -10.6917 9.29806 -47.9503 -5.22646 0 -49.7261 0 -7.86893 -49.3769 5.39231 -15.3427 -47.2813 -23.4288 15.3427 -41.4209 -19.7755 7.80382 -45.2552 -15.4509 0 -47.5528 -10.6016 -7.80382 -48.236 -5.39231 -15.3427 -47.2813 -32.1537 15.3427 -35.0819 -37.8656 17.1665 -27.776 -36.9292 7.80382 -32.7923 -42.2995 18.1898 -19.4905 -42.2995 9.29806 -24.9859 -40.4509 0 -29.3893 -45.6773 18.1898 -9.09492 -46.7086 9.37962 -15.1765 -45.6773 0 -20.3369 -42.599 -7.80382 -24.9884 -46.9602 17.1665 0.214459 -48.9074 9.29806 -4.64903 -48.9074 0 -10.3955 -46.9602 -7.86893 -15.2583 -43.3009 -15.3427 -19.7391 -46.6335 15.3427 9.48234 -49.1512 7.80382 4.82303 -50 0 0 -49.1512 -7.80382 -4.82303 -46.6335 -15.3427 -9.48234 -43.3009 15.3427 19.7391 -38.1177 17.1665 27.429 -42.599 7.80382 24.9884 -31.6078 18.1898 34.2064 -36.8343 9.29806 32.5082 -40.4509 0 29.3893 -22.7648 18.1898 40.6312 -28.8675 9.37962 39.7327 -33.4566 0 37.1572 -36.9292 -7.80382 32.7923 -14.3075 17.1665 44.7281 -19.5347 9.29806 45.0771 -25 0 43.3013 -29.023 -7.86893 39.9468 -32.1537 -15.3427 35.0819 -5.39231 15.3427 47.2813 -10.6016 7.80382 48.236 -15.4509 0 47.5528 -19.7755 -7.80382 45.2552 -23.4288 -15.3427 41.4209 46.9602 -17.1665 -0.214459 45.6773 -18.1898 9.09492 48.9074 -9.29806 4.64903 42.2995 -18.1898 19.4905 46.7086 -9.37962 15.1765 48.9074 0 10.3955 37.8656 -17.1665 27.776 42.2995 -9.29806 24.9859 45.6773 0 20.3369 46.9602 7.86893 15.2583 14.3075 -17.1665 -44.7281 22.7648 -18.1898 -40.6312 19.5347 -9.29806 -45.0771 31.6078 -18.1898 -34.2064 28.8675 -9.37962 -39.7327 25 0 -43.3013 38.1177 -17.1665 -27.429 36.8343 -9.29806 -32.5082 33.4566 0 -37.1572 29.023 7.86893 -39.9468 -38.1177 -17.1665 -27.429 -31.6078 -18.1898 -34.2064 -36.8343 -9.29806 -32.5082 -22.7648 -18.1898 -40.6312 -28.8675 -9.37962 -39.7327 -33.4566 0 -37.1572 -14.3075 -17.1665 -44.7281 -19.5347 -9.29806 -45.0771 -25 0 -43.3013 -29.023 7.86893 -39.9468 -37.8656 -17.1665 27.776 -42.2995 -18.1898 19.4905 -42.2995 -9.29806 24.9859 -45.6773 -18.1898 9.09492 -46.7086 -9.37962 15.1765 -45.6773 0 20.3369 -46.9602 -17.1665 -0.214459 -48.9074 -9.29806 4.64903 -48.9074 0 10.3955 -46.9602 7.86893 15.2583 14.7155 -17.1665 44.5956 5.46526 -18.1898 46.2521 10.6917 -9.29806 47.9503 -5.46526 -18.1898 46.2521 0 -9.37962 49.1123 5.22646 0 49.7261 -14.7155 -17.1665 44.5956 -10.6917 -9.29806 47.9503 -5.22646 0 49.7261 0 7.86893 49.3769</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="724" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="2172">0 1 -0.000000 0.165156 0.984806 0.053662 0 0.984806 0.173655 0.33628 0.935402 0.109264 0.1769 0.953637 0.243482 0 0.935402 0.353586 0.5 0.850651 0.16246 0.351546 0.885484 0.303864 0.180358 0.885484 0.428239 0 0.850651 0.525731 0.645311 0.734581 0.209674 0.515363 0.77903 0.357091 0.356822 0.794655 0.491123 0.180358 0.77903 0.600487 0 0.734581 0.678521 0.763866 0.595741 0.248195 0.652988 0.644256 0.398172 0.515363 0.667784 0.537089 0.351546 0.667784 0.656109 0.1769 0.644256 0.74407 0 0.595741 0.803176 0.850651 0.447214 0.276393 0.763866 0.488416 0.421851 0.645312 0.516053 0.56326 0.5 0.525731 0.688191 0.33628 0.516053 0.787785 0.165156 0.488416 0.856839 0 0.447214 0.894427 0.102072 0.984806 -0.14049 0.207833 0.935402 -0.286057 0.28623 0.953637 -0.093001 0.309017 0.850651 -0.425326 0.397625 0.885484 -0.240441 0.463014 0.885484 -0.039197 0.398825 0.734581 -0.548935 0.49887 0.77903 -0.379792 0.57735 0.794654 -0.187592 0.62683 0.77903 0.01403 0.472095 0.595741 -0.649783 0.580469 0.644256 -0.497986 0.670058 0.667784 -0.32417 0.732631 0.667785 -0.131591 0.762318 0.644256 0.061688 0.525731 0.447214 -0.723607 0.637252 0.488416 -0.596121 0.735105 0.516053 -0.439671 0.809017 0.525731 -0.262865 0.853144 0.516053 -0.076382 0.865939 0.488416 0.107705 -0.102072 0.984806 -0.14049 -0.207833 0.935402 -0.286057 0 0.953637 -0.30096 -0.309017 0.850651 -0.425326 -0.105801 0.885484 -0.452465 0.105801 0.885484 -0.452465 -0.398825 0.734581 -0.548935 -0.207045 0.77903 -0.591815 0 0.794654 -0.607062 0.207045 0.77903 -0.591815 -0.472095 0.595741 -0.649783 -0.294238 0.644256 -0.705945 -0.101244 0.667784 -0.737437 0.101244 0.667784 -0.737437 0.294238 0.644256 -0.705945 -0.525731 0.447214 -0.723607 -0.370023 0.488416 -0.790274 -0.190992 0.516053 -0.834992 0 0.525731 -0.850651 0.190992 0.516053 -0.834992 0.370023 0.488416 -0.790274 -0.165156 0.984806 0.053662 -0.33628 0.935402 0.109264 -0.28623 0.953637 -0.093001 -0.5 0.850651 0.16246 -0.463014 0.885484 -0.039197 -0.397625 0.885484 -0.240441 -0.645311 0.734581 0.209674 -0.62683 0.77903 0.01403 -0.57735 0.794654 -0.187592 -0.49887 0.77903 -0.379792 -0.763866 0.595741 0.248195 -0.762318 0.644256 0.061688 -0.732631 0.667785 -0.131591 -0.670058 0.667784 -0.32417 -0.580469 0.644256 -0.497986 -0.850651 0.447214 0.276393 -0.865939 0.488416 0.107705 -0.853144 0.516053 -0.076382 -0.809017 0.525731 -0.262865 -0.735105 0.516053 -0.439671 -0.637252 0.488416 -0.596121 -0.1769 0.953637 0.243482 -0.180358 0.885484 0.428239 -0.351546 0.885484 0.303864 -0.180358 0.77903 0.600487 -0.356822 0.794655 0.491123 -0.515363 0.77903 0.357091 -0.1769 0.644256 0.74407 -0.351546 0.667785 0.656109 -0.515363 0.667784 0.537089 -0.652988 0.644256 0.398172 -0.165156 0.488416 0.856839 -0.33628 0.516053 0.787785 -0.5 0.525731 0.688191 -0.645312 0.516053 0.56326 -0.763866 0.488416 0.421851 0 -1 0.000000 0.102072 -0.984806 0.14049 0.165156 -0.984806 -0.053662 0.207833 -0.935402 0.286057 0.28623 -0.953637 0.093001 0.33628 -0.935402 -0.109264 0.309017 -0.850651 0.425326 0.397625 -0.885484 0.240441 0.463014 -0.885484 0.039197 0.5 -0.850651 -0.16246 0.398825 -0.734581 0.548935 0.49887 -0.77903 0.379792 0.57735 -0.794654 0.187592 0.62683 -0.77903 -0.01403 0.645311 -0.734581 -0.209674 0.472095 -0.595741 0.649783 0.580469 -0.644256 0.497986 0.670058 -0.667784 0.32417 0.732631 -0.667785 0.131591 0.762318 -0.644256 -0.061688 0.763866 -0.595741 -0.248195 0.525731 -0.447214 0.723607 0.637252 -0.488416 0.596121 0.735105 -0.516053 0.439671 0.809017 -0.525731 0.262865 0.853144 -0.516053 0.076382 0.865939 -0.488416 -0.107705 0.850651 -0.447214 -0.276393 0 -0.984806 -0.173655 0.1769 -0.953637 -0.243482 0 -0.935402 -0.353586 0.351546 -0.885484 -0.303864 0.180358 -0.885484 -0.428239 0 -0.850651 -0.525731 0.515363 -0.77903 -0.357091 0.356822 -0.794655 -0.491123 0.180358 -0.77903 -0.600487 0 -0.734581 -0.678521 0.652988 -0.644256 -0.398172 0.515363 -0.667784 -0.537089 0.351546 -0.667784 -0.656109 0.1769 -0.644256 -0.74407 0 -0.595741 -0.803176 0.763866 -0.488416 -0.421851 0.645312 -0.516053 -0.56326 0.5 -0.525731 -0.688191 0.33628 -0.516053 -0.787785 0.165156 -0.488416 -0.856839 0 -0.447214 -0.894427 -0.165156 -0.984806 -0.053662 -0.1769 -0.953637 -0.243482 -0.33628 -0.935402 -0.109264 -0.180358 -0.885484 -0.428239 -0.351546 -0.885484 -0.303864 -0.5 -0.850651 -0.16246 -0.180358 -0.77903 -0.600487 -0.356822 -0.794655 -0.491123 -0.515363 -0.77903 -0.357091 -0.645311 -0.734581 -0.209674 -0.1769 -0.644256 -0.74407 -0.351546 -0.667785 -0.656109 -0.515363 -0.667784 -0.537089 -0.652988 -0.644256 -0.398172 -0.763866 -0.595741 -0.248195 -0.165156 -0.488416 -0.856839 -0.33628 -0.516053 -0.787785 -0.5 -0.525731 -0.688191 -0.645312 -0.516053 -0.56326 -0.763866 -0.488416 -0.421851 -0.850651 -0.447214 -0.276393 -0.102072 -0.984806 0.14049 -0.28623 -0.953637 0.093001 -0.207833 -0.935402 0.286057 -0.463014 -0.885484 0.039197 -0.397625 -0.885484 0.240441 -0.309017 -0.850651 0.425326 -0.62683 -0.77903 -0.01403 -0.57735 -0.794654 0.187592 -0.49887 -0.77903 0.379792 -0.398825 -0.734581 0.548935 -0.762318 -0.644256 -0.061688 -0.732631 -0.667785 0.131591 -0.670058 -0.667784 0.32417 -0.580469 -0.644256 0.497986 -0.472095 -0.595741 0.649783 -0.865939 -0.488416 -0.107705 -0.853144 -0.516053 0.076382 -0.809017 -0.525731 0.262865 -0.735105 -0.516053 0.439671 -0.637252 -0.488416 0.596121 -0.525731 -0.447214 0.723607 0 -0.953637 0.30096 -0.105801 -0.885484 0.452465 0.105801 -0.885484 0.452465 -0.207045 -0.77903 0.591815 0 -0.794654 0.607062 0.207045 -0.77903 0.591815 -0.294238 -0.644256 0.705945 -0.101244 -0.667784 0.737437 0.101244 -0.667784 0.737437 0.294238 -0.644256 0.705945 -0.370023 -0.488416 0.790274 -0.190992 -0.516053 0.834992 0 -0.525731 0.850651 0.190992 -0.516053 0.834992 0.370023 -0.488416 0.790274 0.102072 0.31476 0.943667 0.28623 0.343296 0.89455 0.207832 0.162468 0.964578 0.463014 0.360942 0.80953 0.397625 0.180943 0.89953 0.309017 0 0.951057 0.62683 0.360942 0.690511 0.57735 0.187592 0.794654 0.49887 0.008696 0.866633 0.398824 -0.162468 0.902521 0.762318 0.343296 0.548653 0.73263 0.180943 0.656134 0.670058 0.008696 0.742258 0.580469 -0.157292 0.798946 0.472095 -0.31476 0.823439 0.865939 0.31476 0.388686 0.853144 0.162468 0.495731 0.809017 0 0.587785 0.735104 -0.162467 0.658199 0.637252 -0.31476 0.703446 0.929023 0.31476 0.194533 0.939218 0.343296 0.004209 0.981592 0.162467 0.10041 0.912988 0.360942 -0.190193 0.978377 0.180943 -0.100194 1 0 0 0.850416 0.360942 -0.382771 0.934172 0.187592 -0.303531 0.978377 0.008696 -0.206649 0.981592 -0.162467 -0.10041 0.757369 0.343296 -0.555464 0.850416 0.180943 -0.494017 0.912988 0.008695 -0.407893 0.939218 -0.157292 -0.30517 0.929023 -0.31476 -0.194533 0.637252 0.31476 -0.703446 0.735104 0.162467 -0.658199 0.809017 0 -0.587785 0.853144 -0.162468 -0.495731 0.865938 -0.31476 -0.388686 0.472095 0.31476 -0.823439 0.294238 0.343296 -0.891948 0.398824 0.162468 -0.902521 0.101244 0.360941 -0.927076 0.207045 0.180943 -0.961453 0.309017 0 -0.951057 -0.101244 0.360941 -0.927076 0 0.187592 -0.982247 0.1058 0.008696 -0.994349 0.207832 -0.162468 -0.964578 -0.294238 0.343296 -0.891948 -0.207045 0.180943 -0.961453 -0.1058 0.008696 -0.994349 0 -0.157292 -0.987552 0.102072 -0.31476 -0.943667 -0.472095 0.31476 -0.823439 -0.398825 0.162468 -0.902521 -0.309017 0 -0.951057 -0.207832 -0.162468 -0.964578 -0.102072 -0.31476 -0.943667 -0.637252 0.31476 -0.703446 -0.757369 0.343296 -0.555464 -0.735105 0.162467 -0.658199 -0.850416 0.360942 -0.382771 -0.850416 0.180943 -0.494017 -0.809017 0 -0.587785 -0.912988 0.360942 -0.190193 -0.934172 0.187592 -0.303531 -0.912988 0.008695 -0.407893 -0.853144 -0.162468 -0.495731 -0.939218 0.343296 0.004209 -0.978377 0.180943 -0.100194 -0.978377 0.008696 -0.206649 -0.939218 -0.157292 -0.30517 -0.865938 -0.31476 -0.388686 -0.929023 0.31476 0.194533 -0.981592 0.162467 0.10041 -1 0 0 -0.981592 -0.162467 -0.10041 -0.929023 -0.31476 -0.194533 -0.865938 0.31476 0.388686 -0.762318 0.343296 0.548653 -0.853144 0.162468 0.495731 -0.62683 0.360942 0.690511 -0.73263 0.180943 0.656134 -0.809017 0 0.587785 -0.463014 0.360942 0.80953 -0.57735 0.187592 0.794654 -0.670058 0.008696 0.742258 -0.735105 -0.162467 0.658199 -0.28623 0.343296 0.89455 -0.397625 0.180943 0.89953 -0.49887 0.008696 0.866633 -0.580469 -0.157292 0.798946 -0.637252 -0.31476 0.703446 -0.102072 0.31476 0.943667 -0.207832 0.162468 0.964578 -0.309017 0 0.951057 -0.398825 -0.162468 0.902521 -0.472095 -0.31476 0.823439 0.939218 -0.343296 -0.004209 0.912988 -0.360942 0.190193 0.978377 -0.180943 0.100194 0.850416 -0.360942 0.382771 0.934172 -0.187592 0.303531 0.978377 -0.008696 0.206649 0.757369 -0.343296 0.555464 0.850416 -0.180943 0.494017 0.912988 -0.008695 0.407893 0.939218 0.157292 0.30517 0.28623 -0.343296 -0.89455 0.463014 -0.360942 -0.80953 0.397625 -0.180943 -0.89953 0.62683 -0.360942 -0.690511 0.57735 -0.187592 -0.794654 0.49887 -0.008696 -0.866633 0.762318 -0.343296 -0.548653 0.73263 -0.180943 -0.656134 0.670058 -0.008696 -0.742258 0.580469 0.157292 -0.798946 -0.762318 -0.343296 -0.548653 -0.62683 -0.360942 -0.690511 -0.73263 -0.180943 -0.656134 -0.463014 -0.360942 -0.80953 -0.57735 -0.187592 -0.794654 -0.670058 -0.008696 -0.742258 -0.28623 -0.343296 -0.89455 -0.397625 -0.180943 -0.89953 -0.49887 -0.008696 -0.866633 -0.580469 0.157292 -0.798946 -0.757369 -0.343296 0.555464 -0.850416 -0.360942 0.382771 -0.850416 -0.180943 0.494017 -0.912988 -0.360942 0.190193 -0.934172 -0.187592 0.303531 -0.912988 -0.008695 0.407893 -0.939218 -0.343296 -0.004209 -0.978377 -0.180943 0.100194 -0.978377 -0.008696 0.206649 -0.939218 0.157292 0.30517 0.294238 -0.343296 0.891948 0.101244 -0.360941 0.927076 0.207045 -0.180943 0.961453 -0.101244 -0.360941 0.927076 0 -0.187592 0.982247 0.1058 -0.008696 0.994349 -0.294238 -0.343296 0.891948 -0.207045 -0.180943 0.961453 -0.1058 -0.008696 0.994349 0 0.157292 0.987552 0 -1 0.000000 -0.165156 -0.984806 -0.053662 0 -0.984806 -0.173655 -0.33628 -0.935402 -0.109264 -0.1769 -0.953637 -0.243482 0 -0.935402 -0.353586 -0.5 -0.850651 -0.16246 -0.351546 -0.885484 -0.303864 -0.180358 -0.885484 -0.42824 0 -0.850651 -0.525731 -0.645311 -0.734581 -0.209674 -0.515363 -0.779029 -0.357091 -0.356822 -0.794654 -0.491124 -0.180358 -0.77903 -0.600487 0 -0.734581 -0.678521 -0.763866 -0.595741 -0.248195 -0.652988 -0.644256 -0.398172 -0.515363 -0.667784 -0.537089 -0.351546 -0.667784 -0.656109 -0.1769 -0.644256 -0.74407 0 -0.595741 -0.803176 -0.850651 -0.447214 -0.276393 -0.763866 -0.488416 -0.421851 -0.645312 -0.516053 -0.56326 -0.5 -0.525731 -0.688191 -0.33628 -0.516053 -0.787785 -0.165156 -0.488416 -0.856839 0 -0.447214 -0.894427 -0.102072 -0.984806 0.14049 -0.207833 -0.935402 0.286057 -0.28623 -0.953637 0.093001 -0.309017 -0.850651 0.425326 -0.397625 -0.885484 0.240441 -0.463014 -0.885484 0.039197 -0.398825 -0.734581 0.548935 -0.49887 -0.77903 0.379792 -0.57735 -0.794654 0.187592 -0.62683 -0.77903 -0.01403 -0.472095 -0.595741 0.649783 -0.580469 -0.644256 0.497986 -0.670058 -0.667784 0.32417 -0.732631 -0.667784 0.131591 -0.762318 -0.644256 -0.061688 -0.525731 -0.447214 0.723607 -0.637252 -0.488416 0.596121 -0.735105 -0.516053 0.439671 -0.809017 -0.525731 0.262865 -0.853144 -0.516053 0.076382 -0.865939 -0.488416 -0.107705 0.102072 -0.984806 0.14049 0.207833 -0.935402 0.286057 0 -0.953637 0.30096 0.309017 -0.850651 0.425325 0.105801 -0.885484 0.452465 -0.105801 -0.885484 0.452464 0.398825 -0.734581 0.548935 0.207045 -0.77903 0.591815 0 -0.794654 0.607062 -0.207045 -0.77903 0.591816 0.472095 -0.595741 0.649783 0.294238 -0.644256 0.705945 0.101244 -0.667784 0.737437 -0.101244 -0.667784 0.737437 -0.294238 -0.644256 0.705945 0.525731 -0.447214 0.723607 0.370023 -0.488416 0.790274 0.190992 -0.516053 0.834992 0 -0.525731 0.850651 -0.190992 -0.516053 0.834992 -0.370023 -0.488416 0.790274 0.165156 -0.984806 -0.053662 0.33628 -0.935402 -0.109264 0.28623 -0.953637 0.093002 0.5 -0.850651 -0.16246 0.463014 -0.885484 0.039197 0.397625 -0.885484 0.240441 0.645311 -0.734581 -0.209674 0.62683 -0.77903 -0.01403 0.57735 -0.794654 0.187592 0.49887 -0.77903 0.379792 0.763866 -0.595741 -0.248195 0.762318 -0.644256 -0.061688 0.732631 -0.667785 0.131592 0.670058 -0.667784 0.32417 0.580469 -0.644256 0.497986 0.850651 -0.447214 -0.276393 0.865938 -0.488416 -0.107705 0.853144 -0.516053 0.076382 0.809017 -0.525731 0.262865 0.735105 -0.516053 0.439671 0.637252 -0.488416 0.596121 0.1769 -0.953637 -0.243482 0.180358 -0.885484 -0.42824 0.351546 -0.885484 -0.303864 0.180358 -0.77903 -0.600487 0.356822 -0.794654 -0.491123 0.515363 -0.779029 -0.357091 0.1769 -0.644256 -0.74407 0.351547 -0.667784 -0.656109 0.515363 -0.667784 -0.537089 0.652988 -0.644256 -0.398172 0.165156 -0.488416 -0.856839 0.33628 -0.516053 -0.787785 0.5 -0.525731 -0.688191 0.645312 -0.516053 -0.56326 0.763866 -0.488416 -0.421851 0 1 -0.000000 -0.102072 0.984806 -0.14049 -0.165156 0.984806 0.053662 -0.207833 0.935402 -0.286057 -0.28623 0.953637 -0.093001 -0.33628 0.935402 0.109264 -0.309017 0.850651 -0.425326 -0.397625 0.885484 -0.240441 -0.463014 0.885484 -0.039197 -0.5 0.850651 0.16246 -0.398825 0.734581 -0.548935 -0.49887 0.77903 -0.379792 -0.57735 0.794654 -0.187592 -0.62683 0.77903 0.01403 -0.645312 0.734581 0.209674 -0.472095 0.595741 -0.649783 -0.580469 0.644256 -0.497986 -0.670058 0.667784 -0.32417 -0.732631 0.667784 -0.131591 -0.762318 0.644256 0.061688 -0.763866 0.595741 0.248195 -0.525731 0.447214 -0.723607 -0.637252 0.488416 -0.596121 -0.735105 0.516053 -0.439671 -0.809017 0.525731 -0.262865 -0.853144 0.516053 -0.076382 -0.865939 0.488416 0.107705 -0.850651 0.447214 0.276393 0 0.984806 0.173655 -0.1769 0.953637 0.243482 0 0.935402 0.353586 -0.351546 0.885484 0.303864 -0.180358 0.885484 0.42824 0 0.850651 0.525731 -0.515363 0.779029 0.357091 -0.356822 0.794654 0.491124 -0.180358 0.77903 0.600487 0 0.734581 0.678521 -0.652988 0.644256 0.398172 -0.515363 0.667784 0.537089 -0.351546 0.667784 0.656109 -0.1769 0.644256 0.74407 0 0.595741 0.803176 -0.763866 0.488416 0.421851 -0.645312 0.516053 0.56326 -0.5 0.525731 0.688191 -0.33628 0.516053 0.787785 -0.165156 0.488416 0.856839 0 0.447214 0.894427 0.165156 0.984806 0.053662 0.1769 0.953637 0.243482 0.33628 0.935402 0.109264 0.180358 0.885484 0.42824 0.351546 0.885484 0.303864 0.5 0.850651 0.16246 0.180358 0.77903 0.600487 0.356822 0.794654 0.491123 0.515363 0.779029 0.357091 0.645312 0.734581 0.209674 0.1769 0.644256 0.74407 0.351547 0.667784 0.656109 0.515363 0.667784 0.537089 0.652988 0.644256 0.398172 0.763866 0.595741 0.248195 0.165156 0.488416 0.856839 0.33628 0.516053 0.787785 0.5 0.525731 0.688191 0.645312 0.516053 0.56326 0.763866 0.488416 0.421851 0.850651 0.447214 0.276393 0.102072 0.984806 -0.14049 0.28623 0.953637 -0.093002 0.207833 0.935402 -0.286057 0.463014 0.885484 -0.039197 0.397625 0.885484 -0.240441 0.309017 0.850651 -0.425326 0.62683 0.77903 0.01403 0.57735 0.794654 -0.187592 0.49887 0.77903 -0.379792 0.398825 0.734581 -0.548935 0.762318 0.644256 0.061688 0.732631 0.667785 -0.131592 0.670058 0.667784 -0.32417 0.580469 0.644256 -0.497986 0.472095 0.595741 -0.649783 0.865938 0.488416 0.107705 0.853144 0.516053 -0.076382 0.809017 0.525731 -0.262865 0.735105 0.516053 -0.439671 0.637252 0.488416 -0.596121 0.525731 0.447214 -0.723607 0 0.953637 -0.30096 0.105801 0.885484 -0.452465 -0.105801 0.885484 -0.452464 0.207045 0.77903 -0.591815 0 0.794654 -0.607062 -0.207045 0.77903 -0.591816 0.294238 0.644256 -0.705945 0.101244 0.667784 -0.737437 -0.101244 0.667784 -0.737437 -0.294238 0.644256 -0.705945 0.370023 0.488416 -0.790274 0.190992 0.516053 -0.834992 0 0.525731 -0.850651 -0.190992 0.516053 -0.834992 -0.370023 0.488416 -0.790274 -0.102072 -0.31476 -0.943667 -0.28623 -0.343296 -0.89455 -0.207832 -0.162468 -0.964578 -0.463014 -0.360942 -0.80953 -0.397625 -0.180943 -0.89953 -0.309017 0 -0.951057 -0.62683 -0.360942 -0.690511 -0.57735 -0.187592 -0.794654 -0.49887 -0.008696 -0.866633 -0.398824 0.162468 -0.902521 -0.762318 -0.343296 -0.548653 -0.73263 -0.180943 -0.656134 -0.670058 -0.008696 -0.742258 -0.580469 0.157292 -0.798946 -0.472095 0.31476 -0.823439 -0.865938 -0.31476 -0.388686 -0.853144 -0.162468 -0.495731 -0.809017 0 -0.587785 -0.735105 0.162468 -0.658199 -0.637252 0.31476 -0.703446 -0.929023 -0.31476 -0.194533 -0.939218 -0.343296 -0.004209 -0.981592 -0.162467 -0.10041 -0.912988 -0.360942 0.190193 -0.978377 -0.180943 0.100194 -1 0 0 -0.850416 -0.360942 0.382771 -0.934172 -0.187592 0.303531 -0.978377 -0.008696 0.206649 -0.981592 0.162467 0.10041 -0.757369 -0.343296 0.555464 -0.850416 -0.180943 0.494017 -0.912988 -0.008695 0.407893 -0.939218 0.157292 0.30517 -0.929023 0.31476 0.194533 -0.637252 -0.31476 0.703446 -0.735105 -0.162468 0.658199 -0.809017 0 0.587785 -0.853144 0.162468 0.495731 -0.865938 0.31476 0.388686 -0.472095 -0.31476 0.823439 -0.294238 -0.343296 0.891948 -0.398825 -0.162468 0.902521 -0.101244 -0.360942 0.927077 -0.207045 -0.180943 0.961453 -0.309017 0 0.951057 0.101244 -0.360942 0.927077 0 -0.187592 0.982247 -0.1058 -0.008696 0.994349 -0.207832 0.162468 0.964578 0.294238 -0.343296 0.891948 0.207045 -0.180943 0.961453 0.1058 -0.008696 0.994349 0 0.157292 0.987552 -0.102072 0.31476 0.943667 0.472095 -0.31476 0.823439 0.398825 -0.162468 0.902521 0.309017 0 0.951057 0.207832 0.162468 0.964578 0.102072 0.31476 0.943667 0.637252 -0.31476 0.703446 0.757369 -0.343296 0.555464 0.735105 -0.162468 0.658199 0.850416 -0.360942 0.382771 0.850416 -0.180943 0.494017 0.809017 0 0.587785 0.912988 -0.360942 0.190193 0.934172 -0.187592 0.303531 0.912988 -0.008695 0.407893 0.853144 0.162468 0.495731 0.939218 -0.343296 -0.004209 0.978377 -0.180943 0.100194 0.978377 -0.008696 0.206649 0.939218 0.157292 0.30517 0.865938 0.31476 0.388686 0.929023 -0.31476 -0.194533 0.981592 -0.162467 -0.10041 1 0 0 0.981592 0.162467 0.10041 0.929023 0.31476 0.194533 0.865938 -0.31476 -0.388686 0.762318 -0.343296 -0.548653 0.853144 -0.162468 -0.495731 0.62683 -0.360942 -0.690511 0.73263 -0.180943 -0.656134 0.809017 0 -0.587785 0.463014 -0.360941 -0.80953 0.57735 -0.187592 -0.794654 0.670058 -0.008696 -0.742258 0.735105 0.162468 -0.658199 0.28623 -0.343296 -0.89455 0.397625 -0.180943 -0.89953 0.49887 -0.008696 -0.866633 0.580469 0.157292 -0.798946 0.637252 0.31476 -0.703446 0.102072 -0.31476 -0.943667 0.207832 -0.162468 -0.964578 0.309017 0 -0.951057 0.398824 0.162468 -0.902521 0.472095 0.31476 -0.823439 -0.939218 0.343296 0.004209 -0.912988 0.360942 -0.190193 -0.978377 0.180943 -0.100194 -0.850416 0.360942 -0.382771 -0.934172 0.187592 -0.303531 -0.978377 0.008696 -0.206649 -0.757369 0.343296 -0.555464 -0.850416 0.180943 -0.494017 -0.912988 0.008695 -0.407893 -0.939218 -0.157292 -0.30517 -0.28623 0.343296 0.89455 -0.463014 0.360942 0.80953 -0.397625 0.180943 0.89953 -0.62683 0.360942 0.690511 -0.57735 0.187592 0.794654 -0.49887 0.008696 0.866633 -0.762318 0.343296 0.548653 -0.73263 0.180943 0.656134 -0.670058 0.008696 0.742258 -0.580469 -0.157292 0.798946 0.762318 0.343296 0.548653 0.62683 0.360942 0.690511 0.73263 0.180943 0.656134 0.463014 0.360941 0.80953 0.57735 0.187592 0.794654 0.670058 0.008696 0.742258 0.28623 0.343296 0.89455 0.397625 0.180943 0.89953 0.49887 0.008696 0.866633 0.580469 -0.157292 0.798946 0.757369 0.343296 -0.555464 0.850416 0.360942 -0.382771 0.850416 0.180943 -0.494017 0.912988 0.360942 -0.190193 0.934172 0.187592 -0.303531 0.912988 0.008695 -0.407893 0.939218 0.343296 0.004209 0.978377 0.180943 -0.100194 0.978377 0.008696 -0.206649 0.939218 -0.157292 -0.30517 -0.294238 0.343296 -0.891948 -0.101244 0.360942 -0.927077 -0.207045 0.180943 -0.961453 0.101244 0.360942 -0.927077 0 0.187592 -0.982247 -0.1058 0.008696 -0.994349 0.294238 0.343296 -0.891948 0.207045 0.180943 -0.961453 0.1058 0.008696 -0.994349 0 -0.157292 -0.987552</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="724" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="1436">0.106061 0.944444 0.075757 0.944444 0.090909 1 0.121212 0.888889 0.090909 0.888889 0.060606 0.888889 0.136364 0.833333 0.106061 0.833333 0.075757 0.833333 0.045454 0.833333 0.151515 0.777778 0.121212 0.777778 0.090909 0.777778 0.060606 0.777778 0.030303 0.777778 0.166667 0.722222 0.136364 0.722222 0.106061 0.722222 0.075757 0.722222 0.045454 0.722222 0.015151 0.722222 0.181818 0.666667 0.151515 0.666667 0.121212 0.666667 0.090909 0.666667 0.060606 0.666667 0.030303 0.666667 0 0.666667 0.287879 0.944444 0.257576 0.944444 0.272727 1 0.30303 0.888889 0.272727 0.888889 0.242424 0.888889 0.257576 0.944444 0.257576 0.944444 0.318182 0.833333 0.287879 0.833333 0.257576 0.833333 0.227273 0.833333 0.242424 0.888889 0.242424 0.888889 0.333333 0.777778 0.30303 0.777778 0.272727 0.777778 0.242424 0.777778 0.212121 0.777778 0.227273 0.833333 0.227273 0.833333 0.348485 0.722222 0.318182 0.722222 0.287879 0.722222 0.257576 0.722222 0.227273 0.722222 0.19697 0.722222 0.212121 0.777778 0.212121 0.777778 0.363636 0.666667 0.333333 0.666667 0.30303 0.666667 0.272727 0.666667 0.242424 0.666667 0.212121 0.666667 0.19697 0.722222 0.19697 0.722222 0.469697 0.944444 0.439394 0.944444 0.454545 1 0.484848 0.888889 0.454545 0.888889 0.424242 0.888889 0.439394 0.944444 0.439394 0.944444 0.5 0.833333 0.469697 0.833333 0.439394 0.833333 0.409091 0.833333 0.424242 0.888889 0.424242 0.888889 0.515152 0.777778 0.484848 0.777778 0.454545 0.777778 0.424242 0.777778 0.393939 0.777778 0.409091 0.833333 0.409091 0.833333 0.530303 0.722222 0.5 0.722222 0.469697 0.722222 0.439394 0.722222 0.409091 0.722222 0.378788 0.722222 0.393939 0.777778 0.393939 0.777778 0.545455 0.666667 0.515152 0.666667 0.484848 0.666667 0.454545 0.666667 0.424242 0.666667 0.393939 0.666667 0.378788 0.722222 0.378788 0.722222 0.651515 0.944444 0.621212 0.944444 0.636364 1 0.666667 0.888889 0.636364 0.888889 0.606061 0.888889 0.621212 0.944444 0.621212 0.944444 0.681818 0.833333 0.651515 0.833333 0.621212 0.833333 0.590909 0.833333 0.606061 0.888889 0.606061 0.888889 0.69697 0.777778 0.666667 0.777778 0.636364 0.777778 0.606061 0.777778 0.575758 0.777778 0.590909 0.833333 0.590909 0.833333 0.712121 0.722222 0.681818 0.722222 0.651515 0.722222 0.621212 0.722222 0.590909 0.722222 0.560606 0.722222 0.575758 0.777778 0.575758 0.777778 0.727273 0.666667 0.69697 0.666667 0.666667 0.666667 0.636364 0.666667 0.606061 0.666667 0.575758 0.666667 0.560606 0.722222 0.560606 0.722222 0.833333 0.944444 0.80303 0.944444 0.818182 1 0.848485 0.888889 0.818182 0.888889 0.833333 0.944444 0.787879 0.888889 0.80303 0.944444 0.80303 0.944444 0.833333 0.944444 0.863636 0.833333 0.833333 0.833333 0.848485 0.888889 0.80303 0.833333 0.772727 0.833333 0.787879 0.888889 0.848485 0.888889 0.787879 0.888889 0.878788 0.777778 0.848485 0.777778 0.863636 0.833333 0.818182 0.777778 0.787879 0.777778 0.757576 0.777778 0.772727 0.833333 0.863636 0.833333 0.772727 0.833333 0.893939 0.722222 0.863636 0.722222 0.878788 0.777778 0.833333 0.722222 0.80303 0.722222 0.772727 0.722222 0.742424 0.722222 0.757576 0.777778 0.878788 0.777778 0.757576 0.777778 0.909091 0.666667 0.878788 0.666667 0.893939 0.722222 0.848485 0.666667 0.818182 0.666667 0.787879 0.666667 0.757576 0.666667 0.742424 0.722222 0.893939 0.722222 0.742424 0.722222 0.166667 0.055555 0.19697 0.055555 0.181818 0 0.151515 0.111111 0.181818 0.111111 0.212121 0.111111 0.136364 0.166667 0.166667 0.166667 0.19697 0.166667 0.227273 0.166667 0.121212 0.222222 0.151515 0.222222 0.181818 0.222222 0.212121 0.222222 0.242424 0.222222 0.106061 0.277778 0.136364 0.277778 0.166667 0.277778 0.19697 0.277778 0.227273 0.277778 0.257576 0.277778 0.090909 0.333333 0.121212 0.333333 0.151515 0.333333 0.181818 0.333333 0.212121 0.333333 0.242424 0.333333 0.272727 0.333333 0.348485 0.055555 0.378788 0.055555 0.363636 0 0.333333 0.111111 0.363636 0.111111 0.348485 0.055555 0.393939 0.111111 0.348485 0.055555 0.318182 0.166667 0.348485 0.166667 0.333333 0.111111 0.378788 0.166667 0.409091 0.166667 0.333333 0.111111 0.30303 0.222222 0.333333 0.222222 0.318182 0.166667 0.363636 0.222222 0.393939 0.222222 0.424242 0.222222 0.318182 0.166667 0.287879 0.277778 0.318182 0.277778 0.30303 0.222222 0.348485 0.277778 0.378788 0.277778 0.409091 0.277778 0.439394 0.277778 0.30303 0.222222 0.30303 0.333333 0.287879 0.277778 0.333333 0.333333 0.363636 0.333333 0.393939 0.333333 0.424242 0.333333 0.454545 0.333333 0.287879 0.277778 0.530303 0.055555 0.560606 0.055555 0.545455 0 0.515152 0.111111 0.545455 0.111111 0.530303 0.055555 0.575758 0.111111 0.530303 0.055555 0.5 0.166667 0.530303 0.166667 0.515152 0.111111 0.560606 0.166667 0.590909 0.166667 0.515152 0.111111 0.484848 0.222222 0.515152 0.222222 0.5 0.166667 0.545455 0.222222 0.575758 0.222222 0.606061 0.222222 0.5 0.166667 0.469697 0.277778 0.5 0.277778 0.484848 0.222222 0.530303 0.277778 0.560606 0.277778 0.590909 0.277778 0.621212 0.277778 0.484848 0.222222 0.484848 0.333333 0.469697 0.277778 0.515152 0.333333 0.545455 0.333333 0.575758 0.333333 0.606061 0.333333 0.636364 0.333333 0.469697 0.277778 0.712121 0.055555 0.742424 0.055555 0.727273 0 0.69697 0.111111 0.727273 0.111111 0.712121 0.055555 0.757576 0.111111 0.712121 0.055555 0.681818 0.166667 0.712121 0.166667 0.69697 0.111111 0.742424 0.166667 0.772727 0.166667 0.69697 0.111111 0.666667 0.222222 0.69697 0.222222 0.681818 0.166667 0.727273 0.222222 0.757576 0.222222 0.787879 0.222222 0.681818 0.166667 0.651515 0.277778 0.681818 0.277778 0.666667 0.222222 0.712121 0.277778 0.742424 0.277778 0.772727 0.277778 0.80303 0.277778 0.666667 0.222222 0.666667 0.333333 0.651515 0.277778 0.69697 0.333333 0.727273 0.333333 0.757576 0.333333 0.787879 0.333333 0.818182 0.333333 0.651515 0.277778 0.893939 0.055555 0.924242 0.055555 0.909091 0 0.878788 0.111111 0.909091 0.111111 0.893939 0.055555 0.939394 0.111111 0.924242 0.055555 0.924242 0.055555 0.893939 0.055555 0.863636 0.166667 0.893939 0.166667 0.878788 0.111111 0.924242 0.166667 0.954545 0.166667 0.939394 0.111111 0.878788 0.111111 0.939394 0.111111 0.848485 0.222222 0.878788 0.222222 0.863636 0.166667 0.909091 0.222222 0.939394 0.222222 0.969697 0.222222 0.954545 0.166667 0.863636 0.166667 0.954545 0.166667 0.833333 0.277778 0.863636 0.277778 0.848485 0.222222 0.893939 0.277778 0.924242 0.277778 0.954545 0.277778 0.984848 0.277778 0.969697 0.222222 0.848485 0.222222 0.969697 0.222222 0.848485 0.333333 0.833333 0.277778 0.878788 0.333333 0.909091 0.333333 0.939394 0.333333 0.969697 0.333333 1 0.333333 0.984848 0.277778 0.833333 0.277778 0.984848 0.277778 0.015151 0.611111 0.045454 0.611111 0.030303 0.555556 0.075757 0.611111 0.060606 0.555556 0.045454 0.5 0.106061 0.611111 0.090909 0.555556 0.075757 0.5 0.060606 0.444444 0.136364 0.611111 0.121212 0.555556 0.106061 0.5 0.090909 0.444444 0.075757 0.388889 0.166667 0.611111 0.151515 0.555556 0.136364 0.5 0.121212 0.444444 0.106061 0.388889 0.19697 0.611111 0.227273 0.611111 0.212121 0.555556 0.257576 0.611111 0.242424 0.555556 0.227273 0.5 0.287879 0.611111 0.272727 0.555556 0.257576 0.5 0.242424 0.444444 0.318182 0.611111 0.30303 0.555556 0.287879 0.5 0.272727 0.444444 0.257576 0.388889 0.348485 0.611111 0.333333 0.555556 0.318182 0.5 0.30303 0.444444 0.287879 0.388889 0.378788 0.611111 0.409091 0.611111 0.393939 0.555556 0.439394 0.611111 0.424242 0.555556 0.409091 0.5 0.469697 0.611111 0.454545 0.555556 0.439394 0.5 0.424242 0.444444 0.5 0.611111 0.484848 0.555556 0.469697 0.5 0.454545 0.444444 0.439394 0.388889 0.530303 0.611111 0.515152 0.555556 0.5 0.5 0.484848 0.444444 0.469697 0.388889 0.560606 0.611111 0.590909 0.611111 0.575758 0.555556 0.621212 0.611111 0.606061 0.555556 0.590909 0.5 0.651515 0.611111 0.636364 0.555556 0.621212 0.5 0.606061 0.444444 0.681818 0.611111 0.666667 0.555556 0.651515 0.5 0.636364 0.444444 0.621212 0.388889 0.712121 0.611111 0.69697 0.555556 0.681818 0.5 0.666667 0.444444 0.651515 0.388889 0.742424 0.611111 0.772727 0.611111 0.757576 0.555556 0.80303 0.611111 0.787879 0.555556 0.772727 0.5 0.833333 0.611111 0.818182 0.555556 0.80303 0.5 0.787879 0.444444 0.863636 0.611111 0.848485 0.555556 0.833333 0.5 0.818182 0.444444 0.80303 0.388889 0.909091 0.666667 0.893939 0.611111 0.878788 0.555556 0.863636 0.5 0.848485 0.444444 0.833333 0.388889 0.227273 0.388889 0.19697 0.388889 0.212121 0.444444 0.166667 0.388889 0.181818 0.444444 0.19697 0.5 0.136364 0.388889 0.151515 0.444444 0.166667 0.5 0.181818 0.555556 0.409091 0.388889 0.378788 0.388889 0.393939 0.444444 0.348485 0.388889 0.363636 0.444444 0.378788 0.5 0.318182 0.388889 0.333333 0.444444 0.348485 0.5 0.363636 0.555556 0.590909 0.388889 0.560606 0.388889 0.575758 0.444444 0.530303 0.388889 0.545455 0.444444 0.560606 0.5 0.5 0.388889 0.515152 0.444444 0.530303 0.5 0.545455 0.555556 0.772727 0.388889 0.742424 0.388889 0.757576 0.444444 0.712121 0.388889 0.727273 0.444444 0.742424 0.5 0.681818 0.388889 0.69697 0.444444 0.712121 0.5 0.727273 0.555556 0.984848 0.388889 1 0.333333 0.954545 0.388889 0.969697 0.444444 0.984848 0.388889 0.984848 0.388889 0.924242 0.388889 0.939394 0.444444 0.954545 0.5 0.969697 0.444444 0.969697 0.444444 0.893939 0.388889 0.909091 0.444444 0.924242 0.5 0.939394 0.555556 0.954545 0.5 0.954545 0.5 0.863636 0.388889 0.878788 0.444444 0.893939 0.5 0.909091 0.555556 0.924242 0.611111 0.939394 0.555556 0.939394 0.555556 0.909091 0.666667 0.924242 0.611111 0.924242 0.611111 0.272727 1 0.257576 0.944444 0.257576 0.944444 0.242424 0.888889 0.257576 0.944444 0.242424 0.888889 0.227273 0.833333 0.242424 0.888889 0.227273 0.833333 0.212121 0.777778 0.227273 0.833333 0.212121 0.777778 0.19697 0.722222 0.212121 0.777778 0.19697 0.722222 0.19697 0.722222 0.454545 1 0.439394 0.944444 0.439394 0.944444 0.424242 0.888889 0.439394 0.944444 0.424242 0.888889 0.409091 0.833333 0.424242 0.888889 0.409091 0.833333 0.393939 0.777778 0.409091 0.833333 0.393939 0.777778 0.378788 0.722222 0.393939 0.777778 0.378788 0.722222 0.378788 0.722222 0.636364 1 0.621212 0.944444 0.621212 0.944444 0.606061 0.888889 0.621212 0.944444 0.606061 0.888889 0.590909 0.833333 0.606061 0.888889 0.590909 0.833333 0.575758 0.777778 0.590909 0.833333 0.575758 0.777778 0.560606 0.722222 0.575758 0.777778 0.560606 0.722222 0.560606 0.722222 0.833333 0.944444 0.818182 1 0.80303 0.944444 0.848485 0.888889 0.833333 0.944444 0.80303 0.944444 0.787879 0.888889 0.80303 0.944444 0.833333 0.944444 0.863636 0.833333 0.848485 0.888889 0.787879 0.888889 0.772727 0.833333 0.848485 0.888889 0.787879 0.888889 0.878788 0.777778 0.863636 0.833333 0.772727 0.833333 0.757576 0.777778 0.863636 0.833333 0.772727 0.833333 0.893939 0.722222 0.878788 0.777778 0.757576 0.777778 0.742424 0.722222 0.878788 0.777778 0.757576 0.777778 0.909091 0.666667 0.893939 0.722222 0.742424 0.722222 0.893939 0.722222 0.742424 0.722222 0.348485 0.055555 0.363636 0 0.333333 0.111111 0.348485 0.055555 0.348485 0.055555 0.318182 0.166667 0.333333 0.111111 0.333333 0.111111 0.30303 0.222222 0.318182 0.166667 0.318182 0.166667 0.287879 0.277778 0.30303 0.222222 0.30303 0.222222 0.287879 0.277778 0.287879 0.277778 0.530303 0.055555 0.545455 0 0.515152 0.111111 0.530303 0.055555 0.530303 0.055555 0.5 0.166667 0.515152 0.111111 0.515152 0.111111 0.484848 0.222222 0.5 0.166667 0.5 0.166667 0.469697 0.277778 0.484848 0.222222 0.484848 0.222222 0.469697 0.277778 0.469697 0.277778 0.712121 0.055555 0.727273 0 0.69697 0.111111 0.712121 0.055555 0.712121 0.055555 0.681818 0.166667 0.69697 0.111111 0.69697 0.111111 0.666667 0.222222 0.681818 0.166667 0.681818 0.166667 0.651515 0.277778 0.666667 0.222222 0.666667 0.222222 0.651515 0.277778 0.651515 0.277778 0.893939 0.055555 0.909091 0 0.924242 0.055555 0.878788 0.111111 0.893939 0.055555 0.924242 0.055555 0.939394 0.111111 0.924242 0.055555 0.893939 0.055555 0.863636 0.166667 0.878788 0.111111 0.939394 0.111111 0.954545 0.166667 0.878788 0.111111 0.939394 0.111111 0.848485 0.222222 0.863636 0.166667 0.954545 0.166667 0.969697 0.222222 0.863636 0.166667 0.954545 0.166667 0.833333 0.277778 0.848485 0.222222 0.969697 0.222222 0.984848 0.277778 0.848485 0.222222 0.969697 0.222222 0.833333 0.277778 0.984848 0.277778 1 0.333333 0.833333 0.277778 0.984848 0.277778 0.909091 0.666667 1 0.333333 0.984848 0.388889 0.984848 0.388889 0.969697 0.444444 0.984848 0.388889 0.969697 0.444444 0.954545 0.5 0.969697 0.444444 0.954545 0.5 0.939394 0.555556 0.954545 0.5 0.939394 0.555556 0.924242 0.611111 0.939394 0.555556 0.924242 0.611111 0.909091 0.666667 0.924242 0.611111</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="718" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="1440">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>363 0 364 1 362 2 365 3 366 4 363 0 366 4 367 5 364 1 364 1 363 0 366 4 368 6 369 7 365 3 369 7 370 8 366 4 370 8 371 9 367 5 366 4 365 3 369 7 367 5 366 4 370 8 372 10 373 11 368 6 373 11 374 12 369 7 374 12 375 13 370 8 375 13 376 14 371 9 369 7 368 6 373 11 370 8 369 7 374 12 371 9 370 8 375 13 377 15 378 16 372 10 378 16 379 17 373 11 379 17 380 18 374 12 380 18 381 19 375 13 381 19 382 20 376 14 373 11 372 10 378 16 374 12 373 11 379 17 375 13 374 12 380 18 376 14 375 13 381 19 383 21 384 22 377 15 384 22 385 23 378 16 385 23 386 24 379 17 386 24 387 25 380 18 387 25 388 26 381 19 388 26 389 27 382 20 378 16 377 15 384 22 379 17 378 16 385 23 380 18 379 17 386 24 381 19 380 18 387 25 382 20 381 19 388 26 390 28 363 29 362 30 391 31 392 32 390 28 392 32 365 33 363 34 363 35 390 28 392 32 393 36 394 37 391 31 394 37 395 38 392 32 395 38 368 39 365 40 392 32 391 31 394 37 365 41 392 32 395 38 396 42 397 43 393 36 397 43 398 44 394 37 398 44 399 45 395 38 399 45 372 46 368 47 394 37 393 36 397 43 395 38 394 37 398 44 368 48 395 38 399 45 400 49 401 50 396 42 401 50 402 51 397 43 402 51 403 52 398 44 403 52 404 53 399 45 404 53 377 54 372 55 397 43 396 42 401 50 398 44 397 43 402 51 399 45 398 44 403 52 372 56 399 45 404 53 405 57 406 58 400 49 406 58 407 59 401 50 407 59 408 60 402 51 408 60 409 61 403 52 409 61 410 62 404 53 410 62 383 21 377 63 401 50 400 49 406 58 402 51 401 50 407 59 403 52 402 51 408 60 404 53 403 52 409 61 377 64 404 53 410 62 411 65 390 66 362 67 412 68 413 69 411 65 413 69 391 70 390 71 390 72 411 65 413 69 414 73 415 74 412 68 415 74 416 75 413 69 416 75 393 76 391 77 413 69 412 68 415 74 391 78 413 69 416 75 417 79 418 80 414 73 418 80 419 81 415 74 419 81 420 82 416 75 420 82 396 83 393 84 415 74 414 73 418 80 416 75 415 74 419 81 393 85 416 75 420 82 421 86 422 87 417 79 422 87 423 88 418 80 423 88 424 89 419 81 424 89 425 90 420 82 425 90 400 91 396 92 418 80 417 79 422 87 419 81 418 80 423 88 420 82 419 81 424 89 396 93 420 82 425 90 426 94 427 95 421 86 427 95 428 96 422 87 428 96 429 97 423 88 429 97 430 98 424 89 430 98 431 99 425 90 431 99 405 57 400 100 422 87 421 86 427 95 423 88 422 87 428 96 424 89 423 88 429 97 425 90 424 89 430 98 400 101 425 90 431 99 432 102 411 103 362 104 433 105 434 106 432 102 434 106 412 107 411 108 411 109 432 102 434 106 435 110 436 111 433 105 436 111 437 112 434 106 437 112 414 113 412 114 434 106 433 105 436 111 412 115 434 106 437 112 438 116 439 117 435 110 439 117 440 118 436 111 440 118 441 119 437 112 441 119 417 120 414 121 436 111 435 110 439 117 437 112 436 111 440 118 414 122 437 112 441 119 442 123 443 124 438 116 443 124 444 125 439 117 444 125 445 126 440 118 445 126 446 127 441 119 446 127 421 128 417 129 439 117 438 116 443 124 440 118 439 117 444 125 441 119 440 118 445 126 417 130 441 119 446 127 447 131 448 132 442 123 448 132 449 133 443 124 449 133 450 134 444 125 450 134 451 135 445 126 451 135 452 136 446 127 452 136 426 94 421 137 443 124 442 123 448 132 444 125 443 124 449 133 445 126 444 125 450 134 446 127 445 126 451 135 421 138 446 127 452 136 364 139 432 140 362 141 367 142 453 143 364 144 453 143 433 145 432 146 432 147 364 148 453 143 371 149 454 150 367 151 454 150 455 152 453 143 455 152 435 153 433 154 453 143 367 155 454 150 433 156 453 143 455 152 376 157 456 158 371 159 456 158 457 160 454 150 457 160 458 161 455 152 458 161 438 162 435 163 454 150 371 164 456 158 455 152 454 150 457 160 435 165 455 152 458 161 382 166 459 167 376 168 459 167 460 169 456 158 460 169 461 170 457 160 461 170 462 171 458 161 462 171 442 172 438 173 456 158 376 174 459 167 457 160 456 158 460 169 458 161 457 160 461 170 438 175 458 161 462 171 389 176 463 177 382 178 463 177 464 179 459 167 464 179 465 180 460 169 465 180 466 181 461 170 466 181 467 182 462 171 467 182 447 131 442 183 459 167 382 184 463 177 460 169 459 167 464 179 461 170 460 169 465 180 462 171 461 170 466 181 442 185 462 171 467 182 469 186 470 187 468 188 471 189 472 190 469 186 472 190 473 191 470 187 470 187 469 186 472 190 474 192 475 193 471 189 475 193 476 194 472 190 476 194 477 195 473 191 472 190 471 189 475 193 473 191 472 190 476 194 478 196 479 197 474 192 479 197 480 198 475 193 480 198 481 199 476 194 481 199 482 200 477 195 475 193 474 192 479 197 476 194 475 193 480 198 477 195 476 194 481 199 483 201 484 202 478 196 484 202 485 203 479 197 485 203 486 204 480 198 486 204 487 205 481 199 487 205 488 206 482 200 479 197 478 196 484 202 480 198 479 197 485 203 481 199 480 198 486 204 482 200 481 199 487 205 489 207 490 208 483 201 490 208 491 209 484 202 491 209 492 210 485 203 492 210 493 211 486 204 493 211 494 212 487 205 494 212 495 213 488 206 484 202 483 201 490 208 485 203 484 202 491 209 486 204 485 203 492 210 487 205 486 204 493 211 488 206 487 205 494 212 470 214 496 215 468 216 473 217 497 218 470 219 497 218 498 220 496 215 496 215 470 221 497 218 477 222 499 223 473 224 499 223 500 225 497 218 500 225 501 226 498 220 497 218 473 227 499 223 498 220 497 218 500 225 482 228 502 229 477 230 502 229 503 231 499 223 503 231 504 232 500 225 504 232 505 233 501 226 499 223 477 234 502 229 500 225 499 223 503 231 501 226 500 225 504 232 488 235 506 236 482 237 506 236 507 238 502 229 507 238 508 239 503 231 508 239 509 240 504 232 509 240 510 241 505 233 502 229 482 242 506 236 503 231 502 229 507 238 504 232 503 231 508 239 505 233 504 232 509 240 495 213 511 243 488 244 511 243 512 245 506 236 512 245 513 246 507 238 513 246 514 247 508 239 514 247 515 248 509 240 515 248 516 249 510 241 506 236 488 250 511 243 507 238 506 236 512 245 508 239 507 238 513 246 509 240 508 239 514 247 510 241 509 240 515 248 496 251 517 252 468 253 498 254 518 255 496 256 518 255 519 257 517 252 517 252 496 258 518 255 501 259 520 260 498 261 520 260 521 262 518 255 521 262 522 263 519 257 518 255 498 264 520 260 519 257 518 255 521 262 505 265 523 266 501 267 523 266 524 268 520 260 524 268 525 269 521 262 525 269 526 270 522 263 520 260 501 271 523 266 521 262 520 260 524 268 522 263 521 262 525 269 510 272 527 273 505 274 527 273 528 275 523 266 528 275 529 276 524 268 529 276 530 277 525 269 530 277 531 278 526 270 523 266 505 279 527 273 524 268 523 266 528 275 525 269 524 268 529 276 526 270 525 269 530 277 516 249 532 280 510 281 532 280 533 282 527 273 533 282 534 283 528 275 534 283 535 284 529 276 535 284 536 285 530 277 536 285 537 286 531 278 527 273 510 287 532 280 528 275 527 273 533 282 529 276 528 275 534 283 530 277 529 276 535 284 531 278 530 277 536 285 517 288 538 289 468 290 519 291 539 292 517 293 539 292 540 294 538 289 538 289 517 295 539 292 522 296 541 297 519 298 541 297 542 299 539 292 542 299 543 300 540 294 539 292 519 301 541 297 540 294 539 292 542 299 526 302 544 303 522 304 544 303 545 305 541 297 545 305 546 306 542 299 546 306 547 307 543 300 541 297 522 308 544 303 542 299 541 297 545 305 543 300 542 299 546 306 531 309 548 310 526 311 548 310 549 312 544 303 549 312 550 313 545 305 550 313 551 314 546 306 551 314 552 315 547 307 544 303 526 316 548 310 545 305 544 303 549 312 546 306 545 305 550 313 547 307 546 306 551 314 537 286 553 317 531 318 553 317 554 319 548 310 554 319 555 320 549 312 555 320 556 321 550 313 556 321 557 322 551 314 557 322 558 323 552 315 548 310 531 324 553 317 549 312 548 310 554 319 550 313 549 312 555 320 551 314 550 313 556 321 552 315 551 314 557 322 538 325 469 326 468 327 540 328 559 329 538 330 559 329 471 331 469 332 469 333 538 334 559 329 543 335 560 336 540 337 560 336 561 338 559 329 561 338 474 339 471 340 559 329 540 341 560 336 471 342 559 329 561 338 547 343 562 344 543 345 562 344 563 346 560 336 563 346 564 347 561 338 564 347 478 348 474 349 560 336 543 350 562 344 561 338 560 336 563 346 474 351 561 338 564 347 552 352 565 353 547 354 565 353 566 355 562 344 566 355 567 356 563 346 567 356 568 357 564 347 568 357 483 358 478 359 562 344 547 360 565 353 563 346 562 344 566 355 564 347 563 346 567 356 478 361 564 347 568 357 558 323 569 362 552 363 569 362 570 364 565 353 570 364 571 365 566 355 571 365 572 366 567 356 572 366 573 367 568 357 573 367 489 368 483 369 565 353 552 370 569 362 566 355 565 353 570 364 567 356 566 355 571 365 568 357 567 356 572 366 483 371 568 357 573 367 388 26 574 372 389 27 387 25 575 373 388 26 575 373 576 374 574 372 574 372 388 26 575 373 386 24 577 375 387 25 577 375 578 376 575 373 578 376 579 377 576 374 575 373 387 25 577 375 576 374 575 373 578 376 385 23 580 378 386 24 580 378 581 379 577 375 581 379 582 380 578 376 582 380 583 381 579 377 577 375 386 24 580 378 578 376 577 375 581 379 579 377 578 376 582 380 384 22 584 382 385 23 584 382 585 383 580 378 585 383 586 384 581 379 586 384 587 385 582 380 587 385 588 386 583 381 580 378 385 23 584 382 581 379 580 378 585 383 582 380 581 379 586 384 583 381 582 380 587 385 383 21 589 387 384 22 589 387 590 388 584 382 590 388 591 389 585 383 591 389 592 390 586 384 592 390 593 391 587 385 593 391 489 207 588 386 584 382 384 22 589 387 585 383 584 382 590 388 586 384 585 383 591 389 587 385 586 384 592 390 588 386 587 385 593 391 410 62 594 392 383 21 409 61 595 393 410 62 595 393 596 394 594 392 594 392 410 62 595 393 408 60 597 395 409 61 597 395 598 396 595 393 598 396 599 397 596 394 595 393 409 61 597 395 596 394 595 393 598 396 407 59 600 398 408 60 600 398 601 399 597 395 601 399 602 400 598 396 602 400 603 401 599 397 597 395 408 60 600 398 598 396 597 395 601 399 599 397 598 396 602 400 406 58 604 402 407 59 604 402 605 403 600 398 605 403 606 404 601 399 606 404 607 405 602 400 607 405 608 406 603 401 600 398 407 59 604 402 601 399 600 398 605 403 602 400 601 399 606 404 603 401 602 400 607 405 405 57 609 407 406 58 609 407 610 408 604 402 610 408 611 409 605 403 611 409 612 410 606 404 612 410 613 411 607 405 613 411 495 213 608 406 604 402 406 58 609 407 605 403 604 402 610 408 606 404 605 403 611 409 607 405 606 404 612 410 608 406 607 405 613 411 431 99 614 412 405 57 430 98 615 413 431 99 615 413 616 414 614 412 614 412 431 99 615 413 429 97 617 415 430 98 617 415 618 416 615 413 618 416 619 417 616 414 615 413 430 98 617 415 616 414 615 413 618 416 428 96 620 418 429 97 620 418 621 419 617 415 621 419 622 420 618 416 622 420 623 421 619 417 617 415 429 97 620 418 618 416 617 415 621 419 619 417 618 416 622 420 427 95 624 422 428 96 624 422 625 423 620 418 625 423 626 424 621 419 626 424 627 425 622 420 627 425 628 426 623 421 620 418 428 96 624 422 621 419 620 418 625 423 622 420 621 419 626 424 623 421 622 420 627 425 426 94 629 427 427 95 629 427 630 428 624 422 630 428 631 429 625 423 631 429 632 430 626 424 632 430 633 431 627 425 633 431 516 249 628 426 624 422 427 95 629 427 625 423 624 422 630 428 626 424 625 423 631 429 627 425 626 424 632 430 628 426 627 425 633 431 452 136 634 432 426 94 451 135 635 433 452 136 635 433 636 434 634 432 634 432 452 136 635 433 450 134 637 435 451 135 637 435 638 436 635 433 638 436 639 437 636 434 635 433 451 135 637 435 636 434 635 433 638 436 449 133 640 438 450 134 640 438 641 439 637 435 641 439 642 440 638 436 642 440 643 441 639 437 637 435 450 134 640 438 638 436 637 435 641 439 639 437 638 436 642 440 448 132 644 442 449 133 644 442 645 443 640 438 645 443 646 444 641 439 646 444 647 445 642 440 647 445 648 446 643 441 640 438 449 133 644 442 641 439 640 438 645 443 642 440 641 439 646 444 643 441 642 440 647 445 447 131 649 447 448 132 649 447 650 448 644 442 650 448 651 449 645 443 651 449 652 450 646 444 652 450 653 451 647 445 653 451 537 286 648 446 644 442 448 132 649 447 645 443 644 442 650 448 646 444 645 443 651 449 647 445 646 444 652 450 648 446 647 445 653 451 467 182 654 452 447 131 466 181 655 453 467 182 655 453 656 454 654 452 654 452 467 182 655 453 465 180 657 455 466 181 657 455 658 456 655 453 658 456 659 457 656 454 655 453 466 181 657 455 656 454 655 453 658 456 464 179 660 458 465 180 660 458 661 459 657 455 661 459 662 460 658 456 662 460 663 461 659 457 657 455 465 180 660 458 658 456 657 455 661 459 659 457 658 456 662 460 463 177 664 462 464 179 664 462 665 463 660 458 665 463 666 464 661 459 666 464 667 465 662 460 667 465 668 466 663 461 660 458 464 179 664 462 661 459 660 458 665 463 662 460 661 459 666 464 663 461 662 460 667 465 389 467 669 468 463 177 669 468 670 469 664 462 670 469 671 470 665 463 671 470 672 471 666 464 672 471 673 472 667 465 673 472 558 323 668 466 664 462 463 177 669 468 665 463 664 462 670 469 666 464 665 463 671 470 667 465 666 464 672 471 668 466 667 465 673 472 494 212 608 406 495 213 493 211 674 473 494 212 674 473 603 401 608 406 608 406 494 212 674 473 492 210 675 474 493 211 675 474 676 475 674 473 676 475 599 397 603 401 674 473 493 211 675 474 603 401 674 473 676 475 491 209 677 476 492 210 677 476 678 477 675 474 678 477 679 478 676 475 679 478 596 394 599 397 675 474 492 210 677 476 676 475 675 474 678 477 599 397 676 475 679 478 490 208 680 479 491 209 680 479 681 480 677 476 681 480 682 481 678 477 682 481 683 482 679 478 683 482 594 392 596 394 677 476 491 209 680 479 678 477 677 476 681 480 679 478 678 477 682 481 596 394 679 478 683 482 489 207 593 391 490 208 593 391 592 390 680 479 592 390 591 389 681 480 591 389 590 388 682 481 590 388 589 387 683 482 589 387 383 21 594 392 680 479 490 208 593 391 681 480 680 479 592 390 682 481 681 480 591 389 683 482 682 481 590 388 594 392 683 482 589 387 515 248 628 426 516 249 514 247 684 483 515 248 684 483 623 421 628 426 628 426 515 248 684 483 513 246 685 484 514 247 685 484 686 485 684 483 686 485 619 417 623 421 684 483 514 247 685 484 623 421 684 483 686 485 512 245 687 486 513 246 687 486 688 487 685 484 688 487 689 488 686 485 689 488 616 414 619 417 685 484 513 246 687 486 686 485 685 484 688 487 619 417 686 485 689 488 511 243 690 489 512 245 690 489 691 490 687 486 691 490 692 491 688 487 692 491 693 492 689 488 693 492 614 412 616 414 687 486 512 245 690 489 688 487 687 486 691 490 689 488 688 487 692 491 616 414 689 488 693 492 495 213 613 411 511 243 613 411 612 410 690 489 612 410 611 409 691 490 611 409 610 408 692 491 610 408 609 407 693 492 609 407 405 57 614 412 690 489 511 243 613 411 691 490 690 489 612 410 692 491 691 490 611 409 693 492 692 491 610 408 614 412 693 492 609 407 536 285 648 446 537 286 535 284 694 493 536 285 694 493 643 441 648 446 648 446 536 285 694 493 534 283 695 494 535 284 695 494 696 495 694 493 696 495 639 437 643 441 694 493 535 284 695 494 643 441 694 493 696 495 533 282 697 496 534 283 697 496 698 497 695 494 698 497 699 498 696 495 699 498 636 434 639 437 695 494 534 283 697 496 696 495 695 494 698 497 639 437 696 495 699 498 532 280 700 499 533 282 700 499 701 500 697 496 701 500 702 501 698 497 702 501 703 502 699 498 703 502 634 432 636 434 697 496 533 282 700 499 698 497 697 496 701 500 699 498 698 497 702 501 636 434 699 498 703 502 516 249 633 431 532 280 633 431 632 430 700 499 632 430 631 429 701 500 631 429 630 428 702 501 630 428 629 427 703 502 629 427 426 94 634 432 700 499 532 280 633 431 701 500 700 499 632 430 702 501 701 500 631 429 703 502 702 501 630 428 634 432 703 502 629 427 557 322 668 466 558 323 556 321 704 503 557 322 704 503 663 461 668 466 668 466 557 322 704 503 555 320 705 504 556 321 705 504 706 505 704 503 706 505 659 457 663 461 704 503 556 321 705 504 663 461 704 503 706 505 554 319 707 506 555 320 707 506 708 507 705 504 708 507 709 508 706 505 709 508 656 454 659 457 705 504 555 320 707 506 706 505 705 504 708 507 659 457 706 505 709 508 553 317 710 509 554 319 710 509 711 510 707 506 711 510 712 511 708 507 712 511 713 512 709 508 713 512 654 452 656 454 707 506 554 319 710 509 708 507 707 506 711 510 709 508 708 507 712 511 656 454 709 508 713 512 537 286 653 451 553 317 653 451 652 450 710 509 652 450 651 449 711 510 651 449 650 448 712 511 650 448 649 447 713 512 649 447 447 131 654 452 710 509 553 317 653 451 711 510 710 509 652 450 712 511 711 510 651 449 713 512 712 511 650 448 654 452 713 512 649 447 573 367 588 513 489 514 572 366 714 515 573 367 714 515 583 516 588 517 588 518 573 367 714 515 571 365 715 519 572 366 715 519 716 520 714 515 716 520 579 521 583 522 714 515 572 366 715 519 583 523 714 515 716 520 570 364 717 524 571 365 717 524 718 525 715 519 718 525 719 526 716 520 719 526 576 527 579 528 715 519 571 365 717 524 716 520 715 519 718 525 579 529 716 520 719 526 569 362 720 530 570 364 720 530 721 531 717 524 721 531 722 532 718 525 722 532 723 533 719 526 723 533 574 534 576 535 717 524 570 364 720 530 718 525 717 524 721 531 719 526 718 525 722 532 576 536 719 526 723 533 558 323 673 472 569 362 673 472 672 471 720 530 672 471 671 470 721 531 671 470 670 469 722 532 670 469 669 468 723 533 669 468 389 537 574 538 720 530 569 362 673 472 721 531 720 530 672 471 722 532 721 531 671 470 723 533 722 532 670 469 574 539 723 533 669 468 1 0 0 2 2 1 3 3 1 0 4 4 4 4 2 1 5 5 2 1 4 4 1 0 6 6 3 3 7 7 7 7 4 4 8 8 8 8 5 5 9 9 4 4 7 7 3 3 5 5 8 8 4 4 10 10 6 6 11 11 11 11 7 7 12 12 12 12 8 8 13 13 13 13 9 9 14 14 7 7 11 11 6 6 8 8 12 12 7 7 9 9 13 13 8 8 15 15 10 10 16 16 16 16 11 11 17 17 17 17 12 12 18 18 18 18 13 13 19 19 19 19 14 14 20 20 11 11 16 16 10 10 12 12 17 17 11 11 13 13 18 18 12 12 14 14 19 19 13 13 21 21 15 15 22 22 22 22 16 16 23 23 23 23 17 17 24 24 24 24 18 18 25 25 25 25 19 19 26 26 26 26 20 20 27 27 16 16 22 22 15 15 17 17 23 23 16 16 18 18 24 24 17 17 19 19 25 25 18 18 20 20 26 26 19 19 28 28 0 540 1 541 29 31 28 28 30 32 30 32 1 542 3 543 1 544 30 32 28 28 31 36 29 31 32 37 32 37 30 32 33 38 33 38 3 545 6 546 30 32 32 37 29 31 3 547 33 38 30 32 34 42 31 36 35 43 35 43 32 37 36 44 36 44 33 38 37 45 37 45 6 548 10 549 32 37 35 43 31 36 33 38 36 44 32 37 6 550 37 45 33 38 38 49 34 42 39 50 39 50 35 43 40 51 40 51 36 44 41 52 41 52 37 45 42 53 42 53 10 551 15 552 35 43 39 50 34 42 36 44 40 51 35 43 37 45 41 52 36 44 10 553 42 53 37 45 43 57 38 49 44 58 44 58 39 50 45 59 45 59 40 51 46 60 46 60 41 52 47 61 47 61 42 53 48 62 48 62 15 554 21 21 39 50 44 58 38 49 40 51 45 59 39 50 41 52 46 60 40 51 42 53 47 61 41 52 15 555 48 62 42 53 49 65 0 556 28 557 50 68 49 65 51 69 51 69 28 558 29 559 28 560 51 69 49 65 52 73 50 68 53 74 53 74 51 69 54 75 54 75 29 561 31 562 51 69 53 74 50 68 29 563 54 75 51 69 55 79 52 73 56 80 56 80 53 74 57 81 57 81 54 75 58 82 58 82 31 564 34 565 53 74 56 80 52 73 54 75 57 81 53 74 31 566 58 82 54 75 59 86 55 79 60 87 60 87 56 80 61 88 61 88 57 81 62 89 62 89 58 82 63 90 63 90 34 567 38 568 56 80 60 87 55 79 57 81 61 88 56 80 58 82 62 89 57 81 34 569 63 90 58 82 64 94 59 86 65 95 65 95 60 87 66 96 66 96 61 88 67 97 67 97 62 89 68 98 68 98 63 90 69 99 69 99 38 570 43 57 60 87 65 95 59 86 61 88 66 96 60 87 62 89 67 97 61 88 63 90 68 98 62 89 38 571 69 99 63 90 70 102 0 572 49 573 71 105 70 102 72 106 72 106 49 574 50 575 49 576 72 106 70 102 73 110 71 105 74 111 74 111 72 106 75 112 75 112 50 577 52 578 72 106 74 111 71 105 50 579 75 112 72 106 76 116 73 110 77 117 77 117 74 111 78 118 78 118 75 112 79 119 79 119 52 580 55 581 74 111 77 117 73 110 75 112 78 118 74 111 52 582 79 119 75 112 80 123 76 116 81 124 81 124 77 117 82 125 82 125 78 118 83 126 83 126 79 119 84 127 84 127 55 583 59 584 77 117 81 124 76 116 78 118 82 125 77 117 79 119 83 126 78 118 55 585 84 127 79 119 85 131 80 123 86 132 86 132 81 124 87 133 87 133 82 125 88 134 88 134 83 126 89 135 89 135 84 127 90 136 90 136 59 586 64 94 81 124 86 132 80 123 82 125 87 133 81 124 83 126 88 134 82 125 84 127 89 135 83 126 59 587 90 136 84 127 2 588 0 589 70 590 5 591 2 592 91 143 91 143 70 593 71 594 70 595 91 143 2 596 9 597 5 598 92 150 92 150 91 143 93 152 93 152 71 599 73 600 91 143 92 150 5 601 71 602 93 152 91 143 14 603 9 604 94 158 94 158 92 150 95 160 95 160 93 152 96 161 96 161 73 605 76 606 92 150 94 158 9 607 93 152 95 160 92 150 73 608 96 161 93 152 20 609 14 610 97 167 97 167 94 158 98 169 98 169 95 160 99 170 99 170 96 161 100 171 100 171 76 611 80 612 94 158 97 167 14 613 95 160 98 169 94 158 96 161 99 170 95 160 76 614 100 171 96 161 27 615 20 616 101 177 101 177 97 167 102 179 102 179 98 169 103 180 103 180 99 170 104 181 104 181 100 171 105 182 105 182 80 617 85 131 97 167 101 177 20 618 98 169 102 179 97 167 99 170 103 180 98 169 100 171 104 181 99 170 80 619 105 182 100 171 107 186 106 188 108 187 109 189 107 186 110 190 110 190 108 187 111 191 108 187 110 190 107 186 112 192 109 189 113 193 113 193 110 190 114 194 114 194 111 191 115 195 110 190 113 193 109 189 111 191 114 194 110 190 116 196 112 192 117 197 117 197 113 193 118 198 118 198 114 194 119 199 119 199 115 195 120 200 113 193 117 197 112 192 114 194 118 198 113 193 115 195 119 199 114 194 121 201 116 196 122 202 122 202 117 197 123 203 123 203 118 198 124 204 124 204 119 199 125 205 125 205 120 200 126 206 117 197 122 202 116 196 118 198 123 203 117 197 119 199 124 204 118 198 120 200 125 205 119 199 127 207 121 201 128 208 128 208 122 202 129 209 129 209 123 203 130 210 130 210 124 204 131 211 131 211 125 205 132 212 132 212 126 206 133 213 122 202 128 208 121 201 123 203 129 209 122 202 124 204 130 210 123 203 125 205 131 211 124 204 126 206 132 212 125 205 108 620 106 621 134 215 111 622 108 623 135 218 135 218 134 215 136 220 134 215 135 218 108 624 115 625 111 626 137 223 137 223 135 218 138 225 138 225 136 220 139 226 135 218 137 223 111 627 136 220 138 225 135 218 120 628 115 629 140 229 140 229 137 223 141 231 141 231 138 225 142 232 142 232 139 226 143 233 137 223 140 229 115 630 138 225 141 231 137 223 139 226 142 232 138 225 126 631 120 632 144 236 144 236 140 229 145 238 145 238 141 231 146 239 146 239 142 232 147 240 147 240 143 233 148 241 140 229 144 236 120 633 141 231 145 238 140 229 142 232 146 239 141 231 143 233 147 240 142 232 133 213 126 634 149 243 149 243 144 236 150 245 150 245 145 238 151 246 151 246 146 239 152 247 152 247 147 240 153 248 153 248 148 241 154 249 144 236 149 243 126 635 145 238 150 245 144 236 146 239 151 246 145 238 147 240 152 247 146 239 148 241 153 248 147 240 134 636 106 637 155 252 136 638 134 639 156 255 156 255 155 252 157 257 155 252 156 255 134 640 139 641 136 642 158 260 158 260 156 255 159 262 159 262 157 257 160 263 156 255 158 260 136 643 157 257 159 262 156 255 143 644 139 645 161 266 161 266 158 260 162 268 162 268 159 262 163 269 163 269 160 263 164 270 158 260 161 266 139 646 159 262 162 268 158 260 160 263 163 269 159 262 148 647 143 648 165 273 165 273 161 266 166 275 166 275 162 268 167 276 167 276 163 269 168 277 168 277 164 270 169 278 161 266 165 273 143 649 162 268 166 275 161 266 163 269 167 276 162 268 164 270 168 277 163 269 154 249 148 650 170 280 170 280 165 273 171 282 171 282 166 275 172 283 172 283 167 276 173 284 173 284 168 277 174 285 174 285 169 278 175 286 165 273 170 280 148 651 166 275 171 282 165 273 167 276 172 283 166 275 168 277 173 284 167 276 169 278 174 285 168 277 155 652 106 653 176 289 157 654 155 655 177 292 177 292 176 289 178 294 176 289 177 292 155 656 160 657 157 658 179 297 179 297 177 292 180 299 180 299 178 294 181 300 177 292 179 297 157 659 178 294 180 299 177 292 164 660 160 661 182 303 182 303 179 297 183 305 183 305 180 299 184 306 184 306 181 300 185 307 179 297 182 303 160 662 180 299 183 305 179 297 181 300 184 306 180 299 169 663 164 664 186 310 186 310 182 303 187 312 187 312 183 305 188 313 188 313 184 306 189 314 189 314 185 307 190 315 182 303 186 310 164 665 183 305 187 312 182 303 184 306 188 313 183 305 185 307 189 314 184 306 175 286 169 666 191 317 191 317 186 310 192 319 192 319 187 312 193 320 193 320 188 313 194 321 194 321 189 314 195 322 195 322 190 315 196 323 186 310 191 317 169 667 187 312 192 319 186 310 188 313 193 320 187 312 189 314 194 321 188 313 190 315 195 322 189 314 176 668 106 669 107 670 178 671 176 672 197 329 197 329 107 673 109 674 107 675 197 329 176 676 181 677 178 678 198 336 198 336 197 329 199 338 199 338 109 679 112 680 197 329 198 336 178 681 109 682 199 338 197 329 185 683 181 684 200 344 200 344 198 336 201 346 201 346 199 338 202 347 202 347 112 685 116 686 198 336 200 344 181 687 199 338 201 346 198 336 112 688 202 347 199 338 190 689 185 690 203 353 203 353 200 344 204 355 204 355 201 346 205 356 205 356 202 347 206 357 206 357 116 691 121 692 200 344 203 353 185 693 201 346 204 355 200 344 202 347 205 356 201 346 116 694 206 357 202 347 196 323 190 695 207 362 207 362 203 353 208 364 208 364 204 355 209 365 209 365 205 356 210 366 210 366 206 357 211 367 211 367 121 696 127 697 203 353 207 362 190 698 204 355 208 364 203 353 205 356 209 365 204 355 206 357 210 366 205 356 121 699 211 367 206 357 26 26 27 27 212 372 25 25 26 26 213 373 213 373 212 372 214 374 212 372 213 373 26 26 24 24 25 25 215 375 215 375 213 373 216 376 216 376 214 374 217 377 213 373 215 375 25 25 214 374 216 376 213 373 23 23 24 24 218 378 218 378 215 375 219 379 219 379 216 376 220 380 220 380 217 377 221 381 215 375 218 378 24 24 216 376 219 379 215 375 217 377 220 380 216 376 22 22 23 23 222 382 222 382 218 378 223 383 223 383 219 379 224 384 224 384 220 380 225 385 225 385 221 381 226 386 218 378 222 382 23 23 219 379 223 383 218 378 220 380 224 384 219 379 221 381 225 385 220 380 21 21 22 22 227 387 227 387 222 382 228 388 228 388 223 383 229 389 229 389 224 384 230 390 230 390 225 385 231 391 231 391 226 386 127 207 222 382 227 387 22 22 223 383 228 388 222 382 224 384 229 389 223 383 225 385 230 390 224 384 226 386 231 391 225 385 48 62 21 21 232 392 47 61 48 62 233 393 233 393 232 392 234 394 232 392 233 393 48 62 46 60 47 61 235 395 235 395 233 393 236 396 236 396 234 394 237 397 233 393 235 395 47 61 234 394 236 396 233 393 45 59 46 60 238 398 238 398 235 395 239 399 239 399 236 396 240 400 240 400 237 397 241 401 235 395 238 398 46 60 236 396 239 399 235 395 237 397 240 400 236 396 44 58 45 59 242 402 242 402 238 398 243 403 243 403 239 399 244 404 244 404 240 400 245 405 245 405 241 401 246 406 238 398 242 402 45 59 239 399 243 403 238 398 240 400 244 404 239 399 241 401 245 405 240 400 43 57 44 58 247 407 247 407 242 402 248 408 248 408 243 403 249 409 249 409 244 404 250 410 250 410 245 405 251 411 251 411 246 406 133 213 242 402 247 407 44 58 243 403 248 408 242 402 244 404 249 409 243 403 245 405 250 410 244 404 246 406 251 411 245 405 69 99 43 57 252 412 68 98 69 99 253 413 253 413 252 412 254 414 252 412 253 413 69 99 67 97 68 98 255 415 255 415 253 413 256 416 256 416 254 414 257 417 253 413 255 415 68 98 254 414 256 416 253 413 66 96 67 97 258 418 258 418 255 415 259 419 259 419 256 416 260 420 260 420 257 417 261 421 255 415 258 418 67 97 256 416 259 419 255 415 257 417 260 420 256 416 65 95 66 96 262 422 262 422 258 418 263 423 263 423 259 419 264 424 264 424 260 420 265 425 265 425 261 421 266 426 258 418 262 422 66 96 259 419 263 423 258 418 260 420 264 424 259 419 261 421 265 425 260 420 64 94 65 95 267 427 267 427 262 422 268 428 268 428 263 423 269 429 269 429 264 424 270 430 270 430 265 425 271 431 271 431 266 426 154 249 262 422 267 427 65 95 263 423 268 428 262 422 264 424 269 429 263 423 265 425 270 430 264 424 266 426 271 431 265 425 90 136 64 94 272 432 89 135 90 136 273 433 273 433 272 432 274 434 272 432 273 433 90 136 88 134 89 135 275 435 275 435 273 433 276 436 276 436 274 434 277 437 273 433 275 435 89 135 274 434 276 436 273 433 87 133 88 134 278 438 278 438 275 435 279 439 279 439 276 436 280 440 280 440 277 437 281 441 275 435 278 438 88 134 276 436 279 439 275 435 277 437 280 440 276 436 86 132 87 133 282 442 282 442 278 438 283 443 283 443 279 439 284 444 284 444 280 440 285 445 285 445 281 441 286 446 278 438 282 442 87 133 279 439 283 443 278 438 280 440 284 444 279 439 281 441 285 445 280 440 85 131 86 132 287 447 287 447 282 442 288 448 288 448 283 443 289 449 289 449 284 444 290 450 290 450 285 445 291 451 291 451 286 446 175 286 282 442 287 447 86 132 283 443 288 448 282 442 284 444 289 449 283 443 285 445 290 450 284 444 286 446 291 451 285 445 105 182 85 131 292 452 104 181 105 182 293 453 293 453 292 452 294 454 292 452 293 453 105 182 103 180 104 181 295 455 295 455 293 453 296 456 296 456 294 454 297 457 293 453 295 455 104 181 294 454 296 456 293 453 102 179 103 180 298 458 298 458 295 455 299 459 299 459 296 456 300 460 300 460 297 457 301 461 295 455 298 458 103 180 296 456 299 459 295 455 297 457 300 460 296 456 101 177 102 179 302 462 302 462 298 458 303 463 303 463 299 459 304 464 304 464 300 460 305 465 305 465 301 461 306 466 298 458 302 462 102 179 299 459 303 463 298 458 300 460 304 464 299 459 301 461 305 465 300 460 27 700 101 177 307 468 307 468 302 462 308 469 308 469 303 463 309 470 309 470 304 464 310 471 310 471 305 465 311 472 311 472 306 466 196 323 302 462 307 468 101 177 303 463 308 469 302 462 304 464 309 470 303 463 305 465 310 471 304 464 306 466 311 472 305 465 132 212 133 213 246 406 131 211 132 212 312 473 312 473 246 406 241 401 246 406 312 473 132 212 130 210 131 211 313 474 313 474 312 473 314 475 314 475 241 401 237 397 312 473 313 474 131 211 241 401 314 475 312 473 129 209 130 210 315 476 315 476 313 474 316 477 316 477 314 475 317 478 317 478 237 397 234 394 313 474 315 476 130 210 314 475 316 477 313 474 237 397 317 478 314 475 128 208 129 209 318 479 318 479 315 476 319 480 319 480 316 477 320 481 320 481 317 478 321 482 321 482 234 394 232 392 315 476 318 479 129 209 316 477 319 480 315 476 317 478 320 481 316 477 234 394 321 482 317 478 127 207 128 208 231 391 231 391 318 479 230 390 230 390 319 480 229 389 229 389 320 481 228 388 228 388 321 482 227 387 227 387 232 392 21 21 318 479 231 391 128 208 319 480 230 390 318 479 320 481 229 389 319 480 321 482 228 388 320 481 232 392 227 387 321 482 153 248 154 249 266 426 152 247 153 248 322 483 322 483 266 426 261 421 266 426 322 483 153 248 151 246 152 247 323 484 323 484 322 483 324 485 324 485 261 421 257 417 322 483 323 484 152 247 261 421 324 485 322 483 150 245 151 246 325 486 325 486 323 484 326 487 326 487 324 485 327 488 327 488 257 417 254 414 323 484 325 486 151 246 324 485 326 487 323 484 257 417 327 488 324 485 149 243 150 245 328 489 328 489 325 486 329 490 329 490 326 487 330 491 330 491 327 488 331 492 331 492 254 414 252 412 325 486 328 489 150 245 326 487 329 490 325 486 327 488 330 491 326 487 254 414 331 492 327 488 133 213 149 243 251 411 251 411 328 489 250 410 250 410 329 490 249 409 249 409 330 491 248 408 248 408 331 492 247 407 247 407 252 412 43 57 328 489 251 411 149 243 329 490 250 410 328 489 330 491 249 409 329 490 331 492 248 408 330 491 252 412 247 407 331 492 174 285 175 286 286 446 173 284 174 285 332 493 332 493 286 446 281 441 286 446 332 493 174 285 172 283 173 284 333 494 333 494 332 493 334 495 334 495 281 441 277 437 332 493 333 494 173 284 281 441 334 495 332 493 171 282 172 283 335 496 335 496 333 494 336 497 336 497 334 495 337 498 337 498 277 437 274 434 333 494 335 496 172 283 334 495 336 497 333 494 277 437 337 498 334 495 170 280 171 282 338 499 338 499 335 496 339 500 339 500 336 497 340 501 340 501 337 498 341 502 341 502 274 434 272 432 335 496 338 499 171 282 336 497 339 500 335 496 337 498 340 501 336 497 274 434 341 502 337 498 154 249 170 280 271 431 271 431 338 499 270 430 270 430 339 500 269 429 269 429 340 501 268 428 268 428 341 502 267 427 267 427 272 432 64 94 338 499 271 431 170 280 339 500 270 430 338 499 340 501 269 429 339 500 341 502 268 428 340 501 272 432 267 427 341 502 195 322 196 323 306 466 194 321 195 322 342 503 342 503 306 466 301 461 306 466 342 503 195 322 193 320 194 321 343 504 343 504 342 503 344 505 344 505 301 461 297 457 342 503 343 504 194 321 301 461 344 505 342 503 192 319 193 320 345 506 345 506 343 504 346 507 346 507 344 505 347 508 347 508 297 457 294 454 343 504 345 506 193 320 344 505 346 507 343 504 297 457 347 508 344 505 191 317 192 319 348 509 348 509 345 506 349 510 349 510 346 507 350 511 350 511 347 508 351 512 351 512 294 454 292 452 345 506 348 509 192 319 346 507 349 510 345 506 347 508 350 511 346 507 294 454 351 512 347 508 175 286 191 317 291 451 291 451 348 509 290 450 290 450 349 510 289 449 289 449 350 511 288 448 288 448 351 512 287 447 287 447 292 452 85 131 348 509 291 451 191 317 349 510 290 450 348 509 350 511 289 449 349 510 351 512 288 448 350 511 292 452 287 447 351 512 211 367 127 701 226 702 210 366 211 367 352 515 352 515 226 703 221 704 226 705 352 515 211 367 209 365 210 366 353 519 353 519 352 515 354 520 354 520 221 706 217 707 352 515 353 519 210 366 221 708 354 520 352 515 208 364 209 365 355 524 355 524 353 519 356 525 356 525 354 520 357 526 357 526 217 709 214 710 353 519 355 524 209 365 354 520 356 525 353 519 217 711 357 526 354 520 207 362 208 364 358 530 358 530 355 524 359 531 359 531 356 525 360 532 360 532 357 526 361 533 361 533 214 712 212 713 355 524 358 530 208 364 356 525 359 531 355 524 357 526 360 532 356 525 214 714 361 533 357 526 196 323 207 362 311 472 311 472 358 530 310 471 310 471 359 531 309 470 309 470 360 532 308 469 308 469 361 533 307 468 307 468 212 715 27 716 358 530 311 472 207 362 359 531 310 471 358 530 360 532 309 470 359 531 361 533 308 469 360 532 212 717 307 468 361 533</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-high-doublesided">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-high-inverted.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-high-inverted.dae
new file mode 100644
index 00000000..0881cd11
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-high-inverted.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-high-inverted.mb</source_data>
+ </contributor>
+ <created>2008-09-19T22:05:04Z</created>
+ <modified>2008-09-19T22:05:04Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="1086">0 50 0 8.72494 49.1512 2.8349 0 49.1512 9.17395 17.1537 46.6335 5.57358 8.84255 47.6832 12.1707 0 46.6335 18.0365 25 42.5325 8.12299 17.2996 44.4764 14.919 8.84298 44.4764 21.0631 0 42.5325 26.2866 31.9975 36.9875 10.3966 26.1426 38.7299 17.7923 17.8411 39.7327 24.5562 8.84298 38.7299 30.3612 0 36.9875 33.6441 37.9086 30.1865 12.3172 32.6527 32.2104 19.9071 26.1426 33.2344 26.6841 17.2996 33.2344 33.1089 8.84255 32.2104 37.2062 0 30.1865 39.8594 42.5325 22.3607 13.8197 37.9086 24.5167 21.4912 31.9975 25.8403 28.4331 25 26.2866 34.4095 17.1537 25.8403 39.2177 8.72494 24.5167 42.6943 0 22.3607 44.7214 5.39231 49.1512 -7.42188 10.6016 46.6335 -14.5918 14.3075 47.6832 -4.6488 15.4509 42.5325 -21.2663 19.5347 44.4764 -11.8426 22.7648 44.4764 -1.90132 19.7755 36.9875 -27.2187 25 38.7299 -19.3649 28.8675 39.7327 -9.37962 31.6078 38.7299 0.971941 23.4288 30.1865 -32.247 29.023 32.2104 -24.9029 33.4566 33.2344 -16.6172 36.8343 33.2344 -6.22166 38.1177 32.2104 3.08758 26.2866 22.3607 -36.1803 32.1537 24.5167 -29.4121 36.9292 25.8403 -21.6451 40.4509 26.2866 -13.1433 42.599 25.8403 -4.19521 43.3009 24.5167 4.89537 -5.39231 49.1512 -7.42188 -10.6016 46.6335 -14.5918 0 47.6832 -15.0438 -15.4509 42.5325 -21.2663 -5.22646 44.4764 -22.2382 5.22646 44.4764 -22.2382 -19.7755 36.9875 -27.2187 -10.6917 38.7299 -29.7605 0 39.7327 -30.3531 10.6917 38.7299 -29.7605 -23.4288 30.1865 -32.247 -14.7155 32.2104 -35.298 -5.46526 33.2344 -36.9541 5.46526 33.2344 -36.9541 14.7155 32.2104 -35.298 -26.2866 22.3607 -36.1803 -18.0365 24.5167 -39.6688 -9.17395 25.8403 -41.8105 0 26.2866 -42.5325 9.17395 25.8403 -41.8105 18.0365 24.5167 -39.6688 -8.72494 49.1512 2.8349 -17.1537 46.6335 5.57358 -14.3075 47.6832 -4.6488 -25 42.5325 8.12299 -22.7648 44.4764 -1.90132 -19.5347 44.4764 -11.8426 -31.9975 36.9875 10.3966 -31.6078 38.7299 0.971941 -28.8675 39.7327 -9.37962 -25 38.7299 -19.3649 -37.9086 30.1865 12.3172 -38.1177 32.2104 3.08758 -36.8343 33.2344 -6.22166 -33.4566 33.2344 -16.6172 -29.023 32.2104 -24.9029 -42.5325 22.3607 13.8197 -43.3009 24.5167 4.89537 -42.599 25.8403 -4.19521 -40.4509 26.2866 -13.1433 -36.9292 25.8403 -21.6451 -32.1537 24.5167 -29.4121 -8.84255 47.6832 12.1707 -8.84298 44.4764 21.0631 -17.2996 44.4764 14.919 -8.84298 38.7299 30.3612 -17.8411 39.7327 24.5562 -26.1426 38.7299 17.7923 -8.84255 32.2104 37.2062 -17.2996 33.2344 33.1089 -26.1426 33.2344 26.6841 -32.6527 32.2104 19.9071 -8.72494 24.5167 42.6943 -17.1537 25.8403 39.2177 -25 26.2866 34.4095 -31.9975 25.8403 28.4331 -37.9086 24.5167 21.4912 0 -50 0 5.39231 -49.1512 7.42188 8.72494 -49.1512 -2.8349 10.6016 -46.6335 14.5918 14.3075 -47.6832 4.6488 17.1537 -46.6335 -5.57358 15.4509 -42.5325 21.2663 19.5347 -44.4764 11.8426 22.7648 -44.4764 1.90132 25 -42.5325 -8.12299 19.7755 -36.9875 27.2187 25 -38.7299 19.3649 28.8675 -39.7327 9.37962 31.6078 -38.7299 -0.971941 31.9975 -36.9875 -10.3966 23.4288 -30.1865 32.247 29.023 -32.2104 24.9029 33.4566 -33.2344 16.6172 36.8343 -33.2344 6.22166 38.1177 -32.2104 -3.08758 37.9086 -30.1865 -12.3172 26.2866 -22.3607 36.1803 32.1537 -24.5167 29.4121 36.9292 -25.8403 21.6451 40.4509 -26.2866 13.1433 42.599 -25.8403 4.19521 43.3009 -24.5167 -4.89537 42.5325 -22.3607 -13.8197 0 -49.1512 -9.17395 8.84255 -47.6832 -12.1707 0 -46.6335 -18.0365 17.2996 -44.4764 -14.919 8.84298 -44.4764 -21.0631 0 -42.5325 -26.2866 26.1426 -38.7299 -17.7923 17.8411 -39.7327 -24.5562 8.84298 -38.7299 -30.3612 0 -36.9875 -33.6441 32.6527 -32.2104 -19.9071 26.1426 -33.2344 -26.6841 17.2996 -33.2344 -33.1089 8.84255 -32.2104 -37.2062 0 -30.1865 -39.8594 37.9086 -24.5167 -21.4912 31.9975 -25.8403 -28.4331 25 -26.2866 -34.4095 17.1537 -25.8403 -39.2177 8.72494 -24.5167 -42.6943 0 -22.3607 -44.7214 -8.72494 -49.1512 -2.8349 -8.84255 -47.6832 -12.1707 -17.1537 -46.6335 -5.57358 -8.84298 -44.4764 -21.0631 -17.2996 -44.4764 -14.919 -25 -42.5325 -8.12299 -8.84298 -38.7299 -30.3612 -17.8411 -39.7327 -24.5562 -26.1426 -38.7299 -17.7923 -31.9975 -36.9875 -10.3966 -8.84255 -32.2104 -37.2062 -17.2996 -33.2344 -33.1089 -26.1426 -33.2344 -26.6841 -32.6527 -32.2104 -19.9071 -37.9086 -30.1865 -12.3172 -8.72494 -24.5167 -42.6943 -17.1537 -25.8403 -39.2177 -25 -26.2866 -34.4095 -31.9975 -25.8403 -28.4331 -37.9086 -24.5167 -21.4912 -42.5325 -22.3607 -13.8197 -5.39231 -49.1512 7.42188 -14.3075 -47.6832 4.6488 -10.6016 -46.6335 14.5918 -22.7648 -44.4764 1.90132 -19.5347 -44.4764 11.8426 -15.4509 -42.5325 21.2663 -31.6078 -38.7299 -0.971941 -28.8675 -39.7327 9.37962 -25 -38.7299 19.3649 -19.7755 -36.9875 27.2187 -38.1177 -32.2104 -3.08758 -36.8343 -33.2344 6.22166 -33.4566 -33.2344 16.6172 -29.023 -32.2104 24.9029 -23.4288 -30.1865 32.247 -43.3009 -24.5167 -4.89537 -42.599 -25.8403 4.19521 -40.4509 -26.2866 13.1433 -36.9292 -25.8403 21.6451 -32.1537 -24.5167 29.4121 -26.2866 -22.3607 36.1803 0 -47.6832 15.0438 -5.22646 -44.4764 22.2382 5.22646 -44.4764 22.2382 -10.6917 -38.7299 29.7605 0 -39.7327 30.3531 10.6917 -38.7299 29.7605 -14.7155 -32.2104 35.298 -5.46526 -33.2344 36.9541 5.46526 -33.2344 36.9541 14.7155 -32.2104 35.298 -18.0365 -24.5167 39.6688 -9.17395 -25.8403 41.8105 0 -26.2866 42.5325 9.17395 -25.8403 41.8105 18.0365 -24.5167 39.6688 5.39231 15.3427 47.2813 14.3075 17.1665 44.7281 10.6016 7.80382 48.236 22.7648 18.1898 40.6312 19.5347 9.29806 45.0771 15.4509 0 47.5528 31.6078 18.1898 34.2064 28.8675 9.37962 39.7327 25 0 43.3013 19.7755 -7.80382 45.2552 38.1177 17.1665 27.429 36.8343 9.29806 32.5082 33.4566 0 37.1572 29.023 -7.86893 39.9468 23.4288 -15.3427 41.4209 43.3009 15.3427 19.7391 42.599 7.80382 24.9884 40.4509 0 29.3893 36.9292 -7.80382 32.7923 32.1537 -15.3427 35.0819 46.6335 15.3427 9.48234 46.9602 17.1665 0.214459 49.1512 7.80382 4.82303 45.6773 18.1898 -9.09492 48.9074 9.29806 -4.64903 50 0 0 42.2995 18.1898 -19.4905 46.7086 9.37962 -15.1765 48.9074 0 -10.3955 49.1512 -7.80382 -4.82303 37.8656 17.1665 -27.776 42.2995 9.29806 -24.9859 45.6773 0 -20.3369 46.9602 -7.86893 -15.2583 46.6335 -15.3427 -9.48234 32.1537 15.3427 -35.0819 36.9292 7.80382 -32.7923 40.4509 0 -29.3893 42.599 -7.80382 -24.9884 43.3009 -15.3427 -19.7391 23.4288 15.3427 -41.4209 14.7155 17.1665 -44.5956 19.7755 7.80382 -45.2552 5.46526 18.1898 -46.2521 10.6917 9.29806 -47.9503 15.4509 0 -47.5528 -5.46526 18.1898 -46.2521 0 9.37962 -49.1123 5.22646 0 -49.7261 10.6016 -7.80382 -48.236 -14.7155 17.1665 -44.5956 -10.6917 9.29806 -47.9503 -5.22646 0 -49.7261 0 -7.86893 -49.3769 5.39231 -15.3427 -47.2813 -23.4288 15.3427 -41.4209 -19.7755 7.80382 -45.2552 -15.4509 0 -47.5528 -10.6016 -7.80382 -48.236 -5.39231 -15.3427 -47.2813 -32.1537 15.3427 -35.0819 -37.8656 17.1665 -27.776 -36.9292 7.80382 -32.7923 -42.2995 18.1898 -19.4905 -42.2995 9.29806 -24.9859 -40.4509 0 -29.3893 -45.6773 18.1898 -9.09492 -46.7086 9.37962 -15.1765 -45.6773 0 -20.3369 -42.599 -7.80382 -24.9884 -46.9602 17.1665 0.214459 -48.9074 9.29806 -4.64903 -48.9074 0 -10.3955 -46.9602 -7.86893 -15.2583 -43.3009 -15.3427 -19.7391 -46.6335 15.3427 9.48234 -49.1512 7.80382 4.82303 -50 0 0 -49.1512 -7.80382 -4.82303 -46.6335 -15.3427 -9.48234 -43.3009 15.3427 19.7391 -38.1177 17.1665 27.429 -42.599 7.80382 24.9884 -31.6078 18.1898 34.2064 -36.8343 9.29806 32.5082 -40.4509 0 29.3893 -22.7648 18.1898 40.6312 -28.8675 9.37962 39.7327 -33.4566 0 37.1572 -36.9292 -7.80382 32.7923 -14.3075 17.1665 44.7281 -19.5347 9.29806 45.0771 -25 0 43.3013 -29.023 -7.86893 39.9468 -32.1537 -15.3427 35.0819 -5.39231 15.3427 47.2813 -10.6016 7.80382 48.236 -15.4509 0 47.5528 -19.7755 -7.80382 45.2552 -23.4288 -15.3427 41.4209 46.9602 -17.1665 -0.214459 45.6773 -18.1898 9.09492 48.9074 -9.29806 4.64903 42.2995 -18.1898 19.4905 46.7086 -9.37962 15.1765 48.9074 0 10.3955 37.8656 -17.1665 27.776 42.2995 -9.29806 24.9859 45.6773 0 20.3369 46.9602 7.86893 15.2583 14.3075 -17.1665 -44.7281 22.7648 -18.1898 -40.6312 19.5347 -9.29806 -45.0771 31.6078 -18.1898 -34.2064 28.8675 -9.37962 -39.7327 25 0 -43.3013 38.1177 -17.1665 -27.429 36.8343 -9.29806 -32.5082 33.4566 0 -37.1572 29.023 7.86893 -39.9468 -38.1177 -17.1665 -27.429 -31.6078 -18.1898 -34.2064 -36.8343 -9.29806 -32.5082 -22.7648 -18.1898 -40.6312 -28.8675 -9.37962 -39.7327 -33.4566 0 -37.1572 -14.3075 -17.1665 -44.7281 -19.5347 -9.29806 -45.0771 -25 0 -43.3013 -29.023 7.86893 -39.9468 -37.8656 -17.1665 27.776 -42.2995 -18.1898 19.4905 -42.2995 -9.29806 24.9859 -45.6773 -18.1898 9.09492 -46.7086 -9.37962 15.1765 -45.6773 0 20.3369 -46.9602 -17.1665 -0.214459 -48.9074 -9.29806 4.64903 -48.9074 0 10.3955 -46.9602 7.86893 15.2583 14.7155 -17.1665 44.5956 5.46526 -18.1898 46.2521 10.6917 -9.29806 47.9503 -5.46526 -18.1898 46.2521 0 -9.37962 49.1123 5.22646 0 49.7261 -14.7155 -17.1665 44.5956 -10.6917 -9.29806 47.9503 -5.22646 0 49.7261 0 7.86893 49.3769</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="362" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="1086">0 -1 0.000000 -0.165156 -0.984806 -0.053662 0 -0.984806 -0.173655 -0.33628 -0.935402 -0.109264 -0.1769 -0.953637 -0.243482 0 -0.935402 -0.353586 -0.5 -0.850651 -0.16246 -0.351546 -0.885484 -0.303864 -0.180358 -0.885484 -0.42824 0 -0.850651 -0.525731 -0.645311 -0.734581 -0.209674 -0.515363 -0.779029 -0.357091 -0.356822 -0.794654 -0.491124 -0.180358 -0.77903 -0.600487 0 -0.734581 -0.678521 -0.763866 -0.595741 -0.248195 -0.652988 -0.644256 -0.398172 -0.515363 -0.667784 -0.537089 -0.351546 -0.667784 -0.656109 -0.1769 -0.644256 -0.74407 0 -0.595741 -0.803176 -0.850651 -0.447214 -0.276393 -0.763866 -0.488416 -0.421851 -0.645312 -0.516053 -0.56326 -0.5 -0.525731 -0.688191 -0.33628 -0.516053 -0.787785 -0.165156 -0.488416 -0.856839 0 -0.447214 -0.894427 -0.102072 -0.984806 0.14049 -0.207833 -0.935402 0.286057 -0.28623 -0.953637 0.093001 -0.309017 -0.850651 0.425326 -0.397625 -0.885484 0.240441 -0.463014 -0.885484 0.039197 -0.398825 -0.734581 0.548935 -0.49887 -0.77903 0.379792 -0.57735 -0.794654 0.187592 -0.62683 -0.77903 -0.01403 -0.472095 -0.595741 0.649783 -0.580469 -0.644256 0.497986 -0.670058 -0.667784 0.32417 -0.732631 -0.667784 0.131591 -0.762318 -0.644256 -0.061688 -0.525731 -0.447214 0.723607 -0.637252 -0.488416 0.596121 -0.735105 -0.516053 0.439671 -0.809017 -0.525731 0.262865 -0.853144 -0.516053 0.076382 -0.865939 -0.488416 -0.107705 0.102072 -0.984806 0.14049 0.207833 -0.935402 0.286057 0 -0.953637 0.30096 0.309017 -0.850651 0.425325 0.105801 -0.885484 0.452465 -0.105801 -0.885484 0.452464 0.398825 -0.734581 0.548935 0.207045 -0.77903 0.591815 0 -0.794654 0.607062 -0.207045 -0.77903 0.591816 0.472095 -0.595741 0.649783 0.294238 -0.644256 0.705945 0.101244 -0.667784 0.737437 -0.101244 -0.667784 0.737437 -0.294238 -0.644256 0.705945 0.525731 -0.447214 0.723607 0.370023 -0.488416 0.790274 0.190992 -0.516053 0.834992 0 -0.525731 0.850651 -0.190992 -0.516053 0.834992 -0.370023 -0.488416 0.790274 0.165156 -0.984806 -0.053662 0.33628 -0.935402 -0.109264 0.28623 -0.953637 0.093002 0.5 -0.850651 -0.16246 0.463014 -0.885484 0.039197 0.397625 -0.885484 0.240441 0.645311 -0.734581 -0.209674 0.62683 -0.77903 -0.01403 0.57735 -0.794654 0.187592 0.49887 -0.77903 0.379792 0.763866 -0.595741 -0.248195 0.762318 -0.644256 -0.061688 0.732631 -0.667785 0.131592 0.670058 -0.667784 0.32417 0.580469 -0.644256 0.497986 0.850651 -0.447214 -0.276393 0.865938 -0.488416 -0.107705 0.853144 -0.516053 0.076382 0.809017 -0.525731 0.262865 0.735105 -0.516053 0.439671 0.637252 -0.488416 0.596121 0.1769 -0.953637 -0.243482 0.180358 -0.885484 -0.42824 0.351546 -0.885484 -0.303864 0.180358 -0.77903 -0.600487 0.356822 -0.794654 -0.491123 0.515363 -0.779029 -0.357091 0.1769 -0.644256 -0.74407 0.351547 -0.667784 -0.656109 0.515363 -0.667784 -0.537089 0.652988 -0.644256 -0.398172 0.165156 -0.488416 -0.856839 0.33628 -0.516053 -0.787785 0.5 -0.525731 -0.688191 0.645312 -0.516053 -0.56326 0.763866 -0.488416 -0.421851 0 1 -0.000000 -0.102072 0.984806 -0.14049 -0.165156 0.984806 0.053662 -0.207833 0.935402 -0.286057 -0.28623 0.953637 -0.093001 -0.33628 0.935402 0.109264 -0.309017 0.850651 -0.425326 -0.397625 0.885484 -0.240441 -0.463014 0.885484 -0.039197 -0.5 0.850651 0.16246 -0.398825 0.734581 -0.548935 -0.49887 0.77903 -0.379792 -0.57735 0.794654 -0.187592 -0.62683 0.77903 0.01403 -0.645312 0.734581 0.209674 -0.472095 0.595741 -0.649783 -0.580469 0.644256 -0.497986 -0.670058 0.667784 -0.32417 -0.732631 0.667784 -0.131591 -0.762318 0.644256 0.061688 -0.763866 0.595741 0.248195 -0.525731 0.447214 -0.723607 -0.637252 0.488416 -0.596121 -0.735105 0.516053 -0.439671 -0.809017 0.525731 -0.262865 -0.853144 0.516053 -0.076382 -0.865939 0.488416 0.107705 -0.850651 0.447214 0.276393 0 0.984806 0.173655 -0.1769 0.953637 0.243482 0 0.935402 0.353586 -0.351546 0.885484 0.303864 -0.180358 0.885484 0.42824 0 0.850651 0.525731 -0.515363 0.779029 0.357091 -0.356822 0.794654 0.491124 -0.180358 0.77903 0.600487 0 0.734581 0.678521 -0.652988 0.644256 0.398172 -0.515363 0.667784 0.537089 -0.351546 0.667784 0.656109 -0.1769 0.644256 0.74407 0 0.595741 0.803176 -0.763866 0.488416 0.421851 -0.645312 0.516053 0.56326 -0.5 0.525731 0.688191 -0.33628 0.516053 0.787785 -0.165156 0.488416 0.856839 0 0.447214 0.894427 0.165156 0.984806 0.053662 0.1769 0.953637 0.243482 0.33628 0.935402 0.109264 0.180358 0.885484 0.42824 0.351546 0.885484 0.303864 0.5 0.850651 0.16246 0.180358 0.77903 0.600487 0.356822 0.794654 0.491123 0.515363 0.779029 0.357091 0.645312 0.734581 0.209674 0.1769 0.644256 0.74407 0.351547 0.667784 0.656109 0.515363 0.667784 0.537089 0.652988 0.644256 0.398172 0.763866 0.595741 0.248195 0.165156 0.488416 0.856839 0.33628 0.516053 0.787785 0.5 0.525731 0.688191 0.645312 0.516053 0.56326 0.763866 0.488416 0.421851 0.850651 0.447214 0.276393 0.102072 0.984806 -0.14049 0.28623 0.953637 -0.093002 0.207833 0.935402 -0.286057 0.463014 0.885484 -0.039197 0.397625 0.885484 -0.240441 0.309017 0.850651 -0.425326 0.62683 0.77903 0.01403 0.57735 0.794654 -0.187592 0.49887 0.77903 -0.379792 0.398825 0.734581 -0.548935 0.762318 0.644256 0.061688 0.732631 0.667785 -0.131592 0.670058 0.667784 -0.32417 0.580469 0.644256 -0.497986 0.472095 0.595741 -0.649783 0.865938 0.488416 0.107705 0.853144 0.516053 -0.076382 0.809017 0.525731 -0.262865 0.735105 0.516053 -0.439671 0.637252 0.488416 -0.596121 0.525731 0.447214 -0.723607 0 0.953637 -0.30096 0.105801 0.885484 -0.452465 -0.105801 0.885484 -0.452464 0.207045 0.77903 -0.591815 0 0.794654 -0.607062 -0.207045 0.77903 -0.591816 0.294238 0.644256 -0.705945 0.101244 0.667784 -0.737437 -0.101244 0.667784 -0.737437 -0.294238 0.644256 -0.705945 0.370023 0.488416 -0.790274 0.190992 0.516053 -0.834992 0 0.525731 -0.850651 -0.190992 0.516053 -0.834992 -0.370023 0.488416 -0.790274 -0.102072 -0.31476 -0.943667 -0.28623 -0.343296 -0.89455 -0.207832 -0.162468 -0.964578 -0.463014 -0.360942 -0.80953 -0.397625 -0.180943 -0.89953 -0.309017 0 -0.951057 -0.62683 -0.360942 -0.690511 -0.57735 -0.187592 -0.794654 -0.49887 -0.008696 -0.866633 -0.398824 0.162468 -0.902521 -0.762318 -0.343296 -0.548653 -0.73263 -0.180943 -0.656134 -0.670058 -0.008696 -0.742258 -0.580469 0.157292 -0.798946 -0.472095 0.31476 -0.823439 -0.865938 -0.31476 -0.388686 -0.853144 -0.162468 -0.495731 -0.809017 0 -0.587785 -0.735105 0.162468 -0.658199 -0.637252 0.31476 -0.703446 -0.929023 -0.31476 -0.194533 -0.939218 -0.343296 -0.004209 -0.981592 -0.162467 -0.10041 -0.912988 -0.360942 0.190193 -0.978377 -0.180943 0.100194 -1 0 0 -0.850416 -0.360942 0.382771 -0.934172 -0.187592 0.303531 -0.978377 -0.008696 0.206649 -0.981592 0.162467 0.10041 -0.757369 -0.343296 0.555464 -0.850416 -0.180943 0.494017 -0.912988 -0.008695 0.407893 -0.939218 0.157292 0.30517 -0.929023 0.31476 0.194533 -0.637252 -0.31476 0.703446 -0.735105 -0.162468 0.658199 -0.809017 0 0.587785 -0.853144 0.162468 0.495731 -0.865938 0.31476 0.388686 -0.472095 -0.31476 0.823439 -0.294238 -0.343296 0.891948 -0.398825 -0.162468 0.902521 -0.101244 -0.360942 0.927077 -0.207045 -0.180943 0.961453 -0.309017 0 0.951057 0.101244 -0.360942 0.927077 0 -0.187592 0.982247 -0.1058 -0.008696 0.994349 -0.207832 0.162468 0.964578 0.294238 -0.343296 0.891948 0.207045 -0.180943 0.961453 0.1058 -0.008696 0.994349 0 0.157292 0.987552 -0.102072 0.31476 0.943667 0.472095 -0.31476 0.823439 0.398825 -0.162468 0.902521 0.309017 0 0.951057 0.207832 0.162468 0.964578 0.102072 0.31476 0.943667 0.637252 -0.31476 0.703446 0.757369 -0.343296 0.555464 0.735105 -0.162468 0.658199 0.850416 -0.360942 0.382771 0.850416 -0.180943 0.494017 0.809017 0 0.587785 0.912988 -0.360942 0.190193 0.934172 -0.187592 0.303531 0.912988 -0.008695 0.407893 0.853144 0.162468 0.495731 0.939218 -0.343296 -0.004209 0.978377 -0.180943 0.100194 0.978377 -0.008696 0.206649 0.939218 0.157292 0.30517 0.865938 0.31476 0.388686 0.929023 -0.31476 -0.194533 0.981592 -0.162467 -0.10041 1 0 0 0.981592 0.162467 0.10041 0.929023 0.31476 0.194533 0.865938 -0.31476 -0.388686 0.762318 -0.343296 -0.548653 0.853144 -0.162468 -0.495731 0.62683 -0.360942 -0.690511 0.73263 -0.180943 -0.656134 0.809017 0 -0.587785 0.463014 -0.360941 -0.80953 0.57735 -0.187592 -0.794654 0.670058 -0.008696 -0.742258 0.735105 0.162468 -0.658199 0.28623 -0.343296 -0.89455 0.397625 -0.180943 -0.89953 0.49887 -0.008696 -0.866633 0.580469 0.157292 -0.798946 0.637252 0.31476 -0.703446 0.102072 -0.31476 -0.943667 0.207832 -0.162468 -0.964578 0.309017 0 -0.951057 0.398824 0.162468 -0.902521 0.472095 0.31476 -0.823439 -0.939218 0.343296 0.004209 -0.912988 0.360942 -0.190193 -0.978377 0.180943 -0.100194 -0.850416 0.360942 -0.382771 -0.934172 0.187592 -0.303531 -0.978377 0.008696 -0.206649 -0.757369 0.343296 -0.555464 -0.850416 0.180943 -0.494017 -0.912988 0.008695 -0.407893 -0.939218 -0.157292 -0.30517 -0.28623 0.343296 0.89455 -0.463014 0.360942 0.80953 -0.397625 0.180943 0.89953 -0.62683 0.360942 0.690511 -0.57735 0.187592 0.794654 -0.49887 0.008696 0.866633 -0.762318 0.343296 0.548653 -0.73263 0.180943 0.656134 -0.670058 0.008696 0.742258 -0.580469 -0.157292 0.798946 0.762318 0.343296 0.548653 0.62683 0.360942 0.690511 0.73263 0.180943 0.656134 0.463014 0.360941 0.80953 0.57735 0.187592 0.794654 0.670058 0.008696 0.742258 0.28623 0.343296 0.89455 0.397625 0.180943 0.89953 0.49887 0.008696 0.866633 0.580469 -0.157292 0.798946 0.757369 0.343296 -0.555464 0.850416 0.360942 -0.382771 0.850416 0.180943 -0.494017 0.912988 0.360942 -0.190193 0.934172 0.187592 -0.303531 0.912988 0.008695 -0.407893 0.939218 0.343296 0.004209 0.978377 0.180943 -0.100194 0.978377 0.008696 -0.206649 0.939218 -0.157292 -0.30517 -0.294238 0.343296 -0.891948 -0.101244 0.360942 -0.927077 -0.207045 0.180943 -0.961453 0.101244 0.360942 -0.927077 0 0.187592 -0.982247 -0.1058 0.008696 -0.994349 0.294238 0.343296 -0.891948 0.207045 0.180943 -0.961453 0.1058 0.008696 -0.994349 0 -0.157292 -0.987552</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="362" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="1080">0.106061 0.944444 0.075757 0.944444 0.090909 1 0.121212 0.888889 0.090909 0.888889 0.060606 0.888889 0.136364 0.833333 0.106061 0.833333 0.075757 0.833333 0.045454 0.833333 0.151515 0.777778 0.121212 0.777778 0.090909 0.777778 0.060606 0.777778 0.030303 0.777778 0.166667 0.722222 0.136364 0.722222 0.106061 0.722222 0.075757 0.722222 0.045454 0.722222 0.015151 0.722222 0.181818 0.666667 0.151515 0.666667 0.121212 0.666667 0.090909 0.666667 0.060606 0.666667 0.030303 0.666667 0 0.666667 0.287879 0.944444 0.257576 0.944444 0.272727 1 0.30303 0.888889 0.272727 0.888889 0.242424 0.888889 0.257576 0.944444 0.257576 0.944444 0.318182 0.833333 0.287879 0.833333 0.257576 0.833333 0.227273 0.833333 0.242424 0.888889 0.242424 0.888889 0.333333 0.777778 0.30303 0.777778 0.272727 0.777778 0.242424 0.777778 0.212121 0.777778 0.227273 0.833333 0.227273 0.833333 0.348485 0.722222 0.318182 0.722222 0.287879 0.722222 0.257576 0.722222 0.227273 0.722222 0.19697 0.722222 0.212121 0.777778 0.212121 0.777778 0.363636 0.666667 0.333333 0.666667 0.30303 0.666667 0.272727 0.666667 0.242424 0.666667 0.212121 0.666667 0.19697 0.722222 0.19697 0.722222 0.469697 0.944444 0.439394 0.944444 0.454545 1 0.484848 0.888889 0.454545 0.888889 0.424242 0.888889 0.439394 0.944444 0.439394 0.944444 0.5 0.833333 0.469697 0.833333 0.439394 0.833333 0.409091 0.833333 0.424242 0.888889 0.424242 0.888889 0.515152 0.777778 0.484848 0.777778 0.454545 0.777778 0.424242 0.777778 0.393939 0.777778 0.409091 0.833333 0.409091 0.833333 0.530303 0.722222 0.5 0.722222 0.469697 0.722222 0.439394 0.722222 0.409091 0.722222 0.378788 0.722222 0.393939 0.777778 0.393939 0.777778 0.545455 0.666667 0.515152 0.666667 0.484848 0.666667 0.454545 0.666667 0.424242 0.666667 0.393939 0.666667 0.378788 0.722222 0.378788 0.722222 0.651515 0.944444 0.621212 0.944444 0.636364 1 0.666667 0.888889 0.636364 0.888889 0.606061 0.888889 0.621212 0.944444 0.621212 0.944444 0.681818 0.833333 0.651515 0.833333 0.621212 0.833333 0.590909 0.833333 0.606061 0.888889 0.606061 0.888889 0.69697 0.777778 0.666667 0.777778 0.636364 0.777778 0.606061 0.777778 0.575758 0.777778 0.590909 0.833333 0.590909 0.833333 0.712121 0.722222 0.681818 0.722222 0.651515 0.722222 0.621212 0.722222 0.590909 0.722222 0.560606 0.722222 0.575758 0.777778 0.575758 0.777778 0.727273 0.666667 0.69697 0.666667 0.666667 0.666667 0.636364 0.666667 0.606061 0.666667 0.575758 0.666667 0.560606 0.722222 0.560606 0.722222 0.833333 0.944444 0.80303 0.944444 0.818182 1 0.848485 0.888889 0.818182 0.888889 0.833333 0.944444 0.787879 0.888889 0.80303 0.944444 0.80303 0.944444 0.833333 0.944444 0.863636 0.833333 0.833333 0.833333 0.848485 0.888889 0.80303 0.833333 0.772727 0.833333 0.787879 0.888889 0.848485 0.888889 0.787879 0.888889 0.878788 0.777778 0.848485 0.777778 0.863636 0.833333 0.818182 0.777778 0.787879 0.777778 0.757576 0.777778 0.772727 0.833333 0.863636 0.833333 0.772727 0.833333 0.893939 0.722222 0.863636 0.722222 0.878788 0.777778 0.833333 0.722222 0.80303 0.722222 0.772727 0.722222 0.742424 0.722222 0.757576 0.777778 0.878788 0.777778 0.757576 0.777778 0.909091 0.666667 0.878788 0.666667 0.893939 0.722222 0.848485 0.666667 0.818182 0.666667 0.787879 0.666667 0.757576 0.666667 0.742424 0.722222 0.893939 0.722222 0.742424 0.722222 0.166667 0.055555 0.19697 0.055555 0.181818 0 0.151515 0.111111 0.181818 0.111111 0.212121 0.111111 0.136364 0.166667 0.166667 0.166667 0.19697 0.166667 0.227273 0.166667 0.121212 0.222222 0.151515 0.222222 0.181818 0.222222 0.212121 0.222222 0.242424 0.222222 0.106061 0.277778 0.136364 0.277778 0.166667 0.277778 0.19697 0.277778 0.227273 0.277778 0.257576 0.277778 0.090909 0.333333 0.121212 0.333333 0.151515 0.333333 0.181818 0.333333 0.212121 0.333333 0.242424 0.333333 0.272727 0.333333 0.348485 0.055555 0.378788 0.055555 0.363636 0 0.333333 0.111111 0.363636 0.111111 0.348485 0.055555 0.393939 0.111111 0.348485 0.055555 0.318182 0.166667 0.348485 0.166667 0.333333 0.111111 0.378788 0.166667 0.409091 0.166667 0.333333 0.111111 0.30303 0.222222 0.333333 0.222222 0.318182 0.166667 0.363636 0.222222 0.393939 0.222222 0.424242 0.222222 0.318182 0.166667 0.287879 0.277778 0.318182 0.277778 0.30303 0.222222 0.348485 0.277778 0.378788 0.277778 0.409091 0.277778 0.439394 0.277778 0.30303 0.222222 0.30303 0.333333 0.287879 0.277778 0.333333 0.333333 0.363636 0.333333 0.393939 0.333333 0.424242 0.333333 0.454545 0.333333 0.287879 0.277778 0.530303 0.055555 0.560606 0.055555 0.545455 0 0.515152 0.111111 0.545455 0.111111 0.530303 0.055555 0.575758 0.111111 0.530303 0.055555 0.5 0.166667 0.530303 0.166667 0.515152 0.111111 0.560606 0.166667 0.590909 0.166667 0.515152 0.111111 0.484848 0.222222 0.515152 0.222222 0.5 0.166667 0.545455 0.222222 0.575758 0.222222 0.606061 0.222222 0.5 0.166667 0.469697 0.277778 0.5 0.277778 0.484848 0.222222 0.530303 0.277778 0.560606 0.277778 0.590909 0.277778 0.621212 0.277778 0.484848 0.222222 0.484848 0.333333 0.469697 0.277778 0.515152 0.333333 0.545455 0.333333 0.575758 0.333333 0.606061 0.333333 0.636364 0.333333 0.469697 0.277778 0.712121 0.055555 0.742424 0.055555 0.727273 0 0.69697 0.111111 0.727273 0.111111 0.712121 0.055555 0.757576 0.111111 0.712121 0.055555 0.681818 0.166667 0.712121 0.166667 0.69697 0.111111 0.742424 0.166667 0.772727 0.166667 0.69697 0.111111 0.666667 0.222222 0.69697 0.222222 0.681818 0.166667 0.727273 0.222222 0.757576 0.222222 0.787879 0.222222 0.681818 0.166667 0.651515 0.277778 0.681818 0.277778 0.666667 0.222222 0.712121 0.277778 0.742424 0.277778 0.772727 0.277778 0.80303 0.277778 0.666667 0.222222 0.666667 0.333333 0.651515 0.277778 0.69697 0.333333 0.727273 0.333333 0.757576 0.333333 0.787879 0.333333 0.818182 0.333333 0.651515 0.277778 0.893939 0.055555 0.924242 0.055555 0.909091 0 0.878788 0.111111 0.909091 0.111111 0.893939 0.055555 0.939394 0.111111 0.924242 0.055555 0.924242 0.055555 0.893939 0.055555 0.863636 0.166667 0.893939 0.166667 0.878788 0.111111 0.924242 0.166667 0.954545 0.166667 0.939394 0.111111 0.878788 0.111111 0.939394 0.111111 0.848485 0.222222 0.878788 0.222222 0.863636 0.166667 0.909091 0.222222 0.939394 0.222222 0.969697 0.222222 0.954545 0.166667 0.863636 0.166667 0.954545 0.166667 0.833333 0.277778 0.863636 0.277778 0.848485 0.222222 0.893939 0.277778 0.924242 0.277778 0.954545 0.277778 0.984848 0.277778 0.969697 0.222222 0.848485 0.222222 0.969697 0.222222 0.848485 0.333333 0.833333 0.277778 0.878788 0.333333 0.909091 0.333333 0.939394 0.333333 0.969697 0.333333 1 0.333333 0.984848 0.277778 0.833333 0.277778 0.984848 0.277778 0.015151 0.611111 0.045454 0.611111 0.030303 0.555556 0.075757 0.611111 0.060606 0.555556 0.045454 0.5 0.106061 0.611111 0.090909 0.555556 0.075757 0.5 0.060606 0.444444 0.136364 0.611111 0.121212 0.555556 0.106061 0.5 0.090909 0.444444 0.075757 0.388889 0.166667 0.611111 0.151515 0.555556 0.136364 0.5 0.121212 0.444444 0.106061 0.388889 0.19697 0.611111 0.227273 0.611111 0.212121 0.555556 0.257576 0.611111 0.242424 0.555556 0.227273 0.5 0.287879 0.611111 0.272727 0.555556 0.257576 0.5 0.242424 0.444444 0.318182 0.611111 0.30303 0.555556 0.287879 0.5 0.272727 0.444444 0.257576 0.388889 0.348485 0.611111 0.333333 0.555556 0.318182 0.5 0.30303 0.444444 0.287879 0.388889 0.378788 0.611111 0.409091 0.611111 0.393939 0.555556 0.439394 0.611111 0.424242 0.555556 0.409091 0.5 0.469697 0.611111 0.454545 0.555556 0.439394 0.5 0.424242 0.444444 0.5 0.611111 0.484848 0.555556 0.469697 0.5 0.454545 0.444444 0.439394 0.388889 0.530303 0.611111 0.515152 0.555556 0.5 0.5 0.484848 0.444444 0.469697 0.388889 0.560606 0.611111 0.590909 0.611111 0.575758 0.555556 0.621212 0.611111 0.606061 0.555556 0.590909 0.5 0.651515 0.611111 0.636364 0.555556 0.621212 0.5 0.606061 0.444444 0.681818 0.611111 0.666667 0.555556 0.651515 0.5 0.636364 0.444444 0.621212 0.388889 0.712121 0.611111 0.69697 0.555556 0.681818 0.5 0.666667 0.444444 0.651515 0.388889 0.742424 0.611111 0.772727 0.611111 0.757576 0.555556 0.80303 0.611111 0.787879 0.555556 0.772727 0.5 0.833333 0.611111 0.818182 0.555556 0.80303 0.5 0.787879 0.444444 0.863636 0.611111 0.848485 0.555556 0.833333 0.5 0.818182 0.444444 0.80303 0.388889 0.909091 0.666667 0.893939 0.611111 0.878788 0.555556 0.863636 0.5 0.848485 0.444444 0.833333 0.388889 0.227273 0.388889 0.19697 0.388889 0.212121 0.444444 0.166667 0.388889 0.181818 0.444444 0.19697 0.5 0.136364 0.388889 0.151515 0.444444 0.166667 0.5 0.181818 0.555556 0.409091 0.388889 0.378788 0.388889 0.393939 0.444444 0.348485 0.388889 0.363636 0.444444 0.378788 0.5 0.318182 0.388889 0.333333 0.444444 0.348485 0.5 0.363636 0.555556 0.590909 0.388889 0.560606 0.388889 0.575758 0.444444 0.530303 0.388889 0.545455 0.444444 0.560606 0.5 0.5 0.388889 0.515152 0.444444 0.530303 0.5 0.545455 0.555556 0.772727 0.388889 0.742424 0.388889 0.757576 0.444444 0.712121 0.388889 0.727273 0.444444 0.742424 0.5 0.681818 0.388889 0.69697 0.444444 0.712121 0.5 0.727273 0.555556 0.984848 0.388889 1 0.333333 0.954545 0.388889 0.969697 0.444444 0.984848 0.388889 0.984848 0.388889 0.924242 0.388889 0.939394 0.444444 0.954545 0.5 0.969697 0.444444 0.969697 0.444444 0.893939 0.388889 0.909091 0.444444 0.924242 0.5 0.939394 0.555556 0.954545 0.5 0.954545 0.5 0.863636 0.388889 0.878788 0.444444 0.893939 0.5 0.909091 0.555556 0.924242 0.611111 0.939394 0.555556 0.939394 0.555556 0.909091 0.666667 0.924242 0.611111 0.924242 0.611111</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="540" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="720">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 2 1 0 2 3 3 4 4 1 0 4 4 5 5 2 1 2 1 1 0 4 4 6 6 7 7 3 3 7 7 8 8 4 4 8 8 9 9 5 5 4 4 3 3 7 7 5 5 4 4 8 8 10 10 11 11 6 6 11 11 12 12 7 7 12 12 13 13 8 8 13 13 14 14 9 9 7 7 6 6 11 11 8 8 7 7 12 12 9 9 8 8 13 13 15 15 16 16 10 10 16 16 17 17 11 11 17 17 18 18 12 12 18 18 19 19 13 13 19 19 20 20 14 14 11 11 10 10 16 16 12 12 11 11 17 17 13 13 12 12 18 18 14 14 13 13 19 19 21 21 22 22 15 15 22 22 23 23 16 16 23 23 24 24 17 17 24 24 25 25 18 18 25 25 26 26 19 19 26 26 27 27 20 20 16 16 15 15 22 22 17 17 16 16 23 23 18 18 17 17 24 24 19 19 18 18 25 25 20 20 19 19 26 26 28 28 1 29 0 30 29 31 30 32 28 28 30 32 3 33 1 34 1 35 28 28 30 32 31 36 32 37 29 31 32 37 33 38 30 32 33 38 6 39 3 40 30 32 29 31 32 37 3 41 30 32 33 38 34 42 35 43 31 36 35 43 36 44 32 37 36 44 37 45 33 38 37 45 10 46 6 47 32 37 31 36 35 43 33 38 32 37 36 44 6 48 33 38 37 45 38 49 39 50 34 42 39 50 40 51 35 43 40 51 41 52 36 44 41 52 42 53 37 45 42 53 15 54 10 55 35 43 34 42 39 50 36 44 35 43 40 51 37 45 36 44 41 52 10 56 37 45 42 53 43 57 44 58 38 49 44 58 45 59 39 50 45 59 46 60 40 51 46 60 47 61 41 52 47 61 48 62 42 53 48 62 21 21 15 63 39 50 38 49 44 58 40 51 39 50 45 59 41 52 40 51 46 60 42 53 41 52 47 61 15 64 42 53 48 62 49 65 28 66 0 67 50 68 51 69 49 65 51 69 29 70 28 71 28 72 49 65 51 69 52 73 53 74 50 68 53 74 54 75 51 69 54 75 31 76 29 77 51 69 50 68 53 74 29 78 51 69 54 75 55 79 56 80 52 73 56 80 57 81 53 74 57 81 58 82 54 75 58 82 34 83 31 84 53 74 52 73 56 80 54 75 53 74 57 81 31 85 54 75 58 82 59 86 60 87 55 79 60 87 61 88 56 80 61 88 62 89 57 81 62 89 63 90 58 82 63 90 38 91 34 92 56 80 55 79 60 87 57 81 56 80 61 88 58 82 57 81 62 89 34 93 58 82 63 90 64 94 65 95 59 86 65 95 66 96 60 87 66 96 67 97 61 88 67 97 68 98 62 89 68 98 69 99 63 90 69 99 43 57 38 100 60 87 59 86 65 95 61 88 60 87 66 96 62 89 61 88 67 97 63 90 62 89 68 98 38 101 63 90 69 99 70 102 49 103 0 104 71 105 72 106 70 102 72 106 50 107 49 108 49 109 70 102 72 106 73 110 74 111 71 105 74 111 75 112 72 106 75 112 52 113 50 114 72 106 71 105 74 111 50 115 72 106 75 112 76 116 77 117 73 110 77 117 78 118 74 111 78 118 79 119 75 112 79 119 55 120 52 121 74 111 73 110 77 117 75 112 74 111 78 118 52 122 75 112 79 119 80 123 81 124 76 116 81 124 82 125 77 117 82 125 83 126 78 118 83 126 84 127 79 119 84 127 59 128 55 129 77 117 76 116 81 124 78 118 77 117 82 125 79 119 78 118 83 126 55 130 79 119 84 127 85 131 86 132 80 123 86 132 87 133 81 124 87 133 88 134 82 125 88 134 89 135 83 126 89 135 90 136 84 127 90 136 64 94 59 137 81 124 80 123 86 132 82 125 81 124 87 133 83 126 82 125 88 134 84 127 83 126 89 135 59 138 84 127 90 136 2 139 70 140 0 141 5 142 91 143 2 144 91 143 71 145 70 146 70 147 2 148 91 143 9 149 92 150 5 151 92 150 93 152 91 143 93 152 73 153 71 154 91 143 5 155 92 150 71 156 91 143 93 152 14 157 94 158 9 159 94 158 95 160 92 150 95 160 96 161 93 152 96 161 76 162 73 163 92 150 9 164 94 158 93 152 92 150 95 160 73 165 93 152 96 161 20 166 97 167 14 168 97 167 98 169 94 158 98 169 99 170 95 160 99 170 100 171 96 161 100 171 80 172 76 173 94 158 14 174 97 167 95 160 94 158 98 169 96 161 95 160 99 170 76 175 96 161 100 171 27 176 101 177 20 178 101 177 102 179 97 167 102 179 103 180 98 169 103 180 104 181 99 170 104 181 105 182 100 171 105 182 85 131 80 183 97 167 20 184 101 177 98 169 97 167 102 179 99 170 98 169 103 180 100 171 99 170 104 181 80 185 100 171 105 182 107 186 108 187 106 188 109 189 110 190 107 186 110 190 111 191 108 187 108 187 107 186 110 190 112 192 113 193 109 189 113 193 114 194 110 190 114 194 115 195 111 191 110 190 109 189 113 193 111 191 110 190 114 194 116 196 117 197 112 192 117 197 118 198 113 193 118 198 119 199 114 194 119 199 120 200 115 195 113 193 112 192 117 197 114 194 113 193 118 198 115 195 114 194 119 199 121 201 122 202 116 196 122 202 123 203 117 197 123 203 124 204 118 198 124 204 125 205 119 199 125 205 126 206 120 200 117 197 116 196 122 202 118 198 117 197 123 203 119 199 118 198 124 204 120 200 119 199 125 205 127 207 128 208 121 201 128 208 129 209 122 202 129 209 130 210 123 203 130 210 131 211 124 204 131 211 132 212 125 205 132 212 133 213 126 206 122 202 121 201 128 208 123 203 122 202 129 209 124 204 123 203 130 210 125 205 124 204 131 211 126 206 125 205 132 212 108 214 134 215 106 216 111 217 135 218 108 219 135 218 136 220 134 215 134 215 108 221 135 218 115 222 137 223 111 224 137 223 138 225 135 218 138 225 139 226 136 220 135 218 111 227 137 223 136 220 135 218 138 225 120 228 140 229 115 230 140 229 141 231 137 223 141 231 142 232 138 225 142 232 143 233 139 226 137 223 115 234 140 229 138 225 137 223 141 231 139 226 138 225 142 232 126 235 144 236 120 237 144 236 145 238 140 229 145 238 146 239 141 231 146 239 147 240 142 232 147 240 148 241 143 233 140 229 120 242 144 236 141 231 140 229 145 238 142 232 141 231 146 239 143 233 142 232 147 240 133 213 149 243 126 244 149 243 150 245 144 236 150 245 151 246 145 238 151 246 152 247 146 239 152 247 153 248 147 240 153 248 154 249 148 241 144 236 126 250 149 243 145 238 144 236 150 245 146 239 145 238 151 246 147 240 146 239 152 247 148 241 147 240 153 248 134 251 155 252 106 253 136 254 156 255 134 256 156 255 157 257 155 252 155 252 134 258 156 255 139 259 158 260 136 261 158 260 159 262 156 255 159 262 160 263 157 257 156 255 136 264 158 260 157 257 156 255 159 262 143 265 161 266 139 267 161 266 162 268 158 260 162 268 163 269 159 262 163 269 164 270 160 263 158 260 139 271 161 266 159 262 158 260 162 268 160 263 159 262 163 269 148 272 165 273 143 274 165 273 166 275 161 266 166 275 167 276 162 268 167 276 168 277 163 269 168 277 169 278 164 270 161 266 143 279 165 273 162 268 161 266 166 275 163 269 162 268 167 276 164 270 163 269 168 277 154 249 170 280 148 281 170 280 171 282 165 273 171 282 172 283 166 275 172 283 173 284 167 276 173 284 174 285 168 277 174 285 175 286 169 278 165 273 148 287 170 280 166 275 165 273 171 282 167 276 166 275 172 283 168 277 167 276 173 284 169 278 168 277 174 285 155 288 176 289 106 290 157 291 177 292 155 293 177 292 178 294 176 289 176 289 155 295 177 292 160 296 179 297 157 298 179 297 180 299 177 292 180 299 181 300 178 294 177 292 157 301 179 297 178 294 177 292 180 299 164 302 182 303 160 304 182 303 183 305 179 297 183 305 184 306 180 299 184 306 185 307 181 300 179 297 160 308 182 303 180 299 179 297 183 305 181 300 180 299 184 306 169 309 186 310 164 311 186 310 187 312 182 303 187 312 188 313 183 305 188 313 189 314 184 306 189 314 190 315 185 307 182 303 164 316 186 310 183 305 182 303 187 312 184 306 183 305 188 313 185 307 184 306 189 314 175 286 191 317 169 318 191 317 192 319 186 310 192 319 193 320 187 312 193 320 194 321 188 313 194 321 195 322 189 314 195 322 196 323 190 315 186 310 169 324 191 317 187 312 186 310 192 319 188 313 187 312 193 320 189 314 188 313 194 321 190 315 189 314 195 322 176 325 107 326 106 327 178 328 197 329 176 330 197 329 109 331 107 332 107 333 176 334 197 329 181 335 198 336 178 337 198 336 199 338 197 329 199 338 112 339 109 340 197 329 178 341 198 336 109 342 197 329 199 338 185 343 200 344 181 345 200 344 201 346 198 336 201 346 202 347 199 338 202 347 116 348 112 349 198 336 181 350 200 344 199 338 198 336 201 346 112 351 199 338 202 347 190 352 203 353 185 354 203 353 204 355 200 344 204 355 205 356 201 346 205 356 206 357 202 347 206 357 121 358 116 359 200 344 185 360 203 353 201 346 200 344 204 355 202 347 201 346 205 356 116 361 202 347 206 357 196 323 207 362 190 363 207 362 208 364 203 353 208 364 209 365 204 355 209 365 210 366 205 356 210 366 211 367 206 357 211 367 127 368 121 369 203 353 190 370 207 362 204 355 203 353 208 364 205 356 204 355 209 365 206 357 205 356 210 366 121 371 206 357 211 367 26 26 212 372 27 27 25 25 213 373 26 26 213 373 214 374 212 372 212 372 26 26 213 373 24 24 215 375 25 25 215 375 216 376 213 373 216 376 217 377 214 374 213 373 25 25 215 375 214 374 213 373 216 376 23 23 218 378 24 24 218 378 219 379 215 375 219 379 220 380 216 376 220 380 221 381 217 377 215 375 24 24 218 378 216 376 215 375 219 379 217 377 216 376 220 380 22 22 222 382 23 23 222 382 223 383 218 378 223 383 224 384 219 379 224 384 225 385 220 380 225 385 226 386 221 381 218 378 23 23 222 382 219 379 218 378 223 383 220 380 219 379 224 384 221 381 220 380 225 385 21 21 227 387 22 22 227 387 228 388 222 382 228 388 229 389 223 383 229 389 230 390 224 384 230 390 231 391 225 385 231 391 127 207 226 386 222 382 22 22 227 387 223 383 222 382 228 388 224 384 223 383 229 389 225 385 224 384 230 390 226 386 225 385 231 391 48 62 232 392 21 21 47 61 233 393 48 62 233 393 234 394 232 392 232 392 48 62 233 393 46 60 235 395 47 61 235 395 236 396 233 393 236 396 237 397 234 394 233 393 47 61 235 395 234 394 233 393 236 396 45 59 238 398 46 60 238 398 239 399 235 395 239 399 240 400 236 396 240 400 241 401 237 397 235 395 46 60 238 398 236 396 235 395 239 399 237 397 236 396 240 400 44 58 242 402 45 59 242 402 243 403 238 398 243 403 244 404 239 399 244 404 245 405 240 400 245 405 246 406 241 401 238 398 45 59 242 402 239 399 238 398 243 403 240 400 239 399 244 404 241 401 240 400 245 405 43 57 247 407 44 58 247 407 248 408 242 402 248 408 249 409 243 403 249 409 250 410 244 404 250 410 251 411 245 405 251 411 133 213 246 406 242 402 44 58 247 407 243 403 242 402 248 408 244 404 243 403 249 409 245 405 244 404 250 410 246 406 245 405 251 411 69 99 252 412 43 57 68 98 253 413 69 99 253 413 254 414 252 412 252 412 69 99 253 413 67 97 255 415 68 98 255 415 256 416 253 413 256 416 257 417 254 414 253 413 68 98 255 415 254 414 253 413 256 416 66 96 258 418 67 97 258 418 259 419 255 415 259 419 260 420 256 416 260 420 261 421 257 417 255 415 67 97 258 418 256 416 255 415 259 419 257 417 256 416 260 420 65 95 262 422 66 96 262 422 263 423 258 418 263 423 264 424 259 419 264 424 265 425 260 420 265 425 266 426 261 421 258 418 66 96 262 422 259 419 258 418 263 423 260 420 259 419 264 424 261 421 260 420 265 425 64 94 267 427 65 95 267 427 268 428 262 422 268 428 269 429 263 423 269 429 270 430 264 424 270 430 271 431 265 425 271 431 154 249 266 426 262 422 65 95 267 427 263 423 262 422 268 428 264 424 263 423 269 429 265 425 264 424 270 430 266 426 265 425 271 431 90 136 272 432 64 94 89 135 273 433 90 136 273 433 274 434 272 432 272 432 90 136 273 433 88 134 275 435 89 135 275 435 276 436 273 433 276 436 277 437 274 434 273 433 89 135 275 435 274 434 273 433 276 436 87 133 278 438 88 134 278 438 279 439 275 435 279 439 280 440 276 436 280 440 281 441 277 437 275 435 88 134 278 438 276 436 275 435 279 439 277 437 276 436 280 440 86 132 282 442 87 133 282 442 283 443 278 438 283 443 284 444 279 439 284 444 285 445 280 440 285 445 286 446 281 441 278 438 87 133 282 442 279 439 278 438 283 443 280 440 279 439 284 444 281 441 280 440 285 445 85 131 287 447 86 132 287 447 288 448 282 442 288 448 289 449 283 443 289 449 290 450 284 444 290 450 291 451 285 445 291 451 175 286 286 446 282 442 86 132 287 447 283 443 282 442 288 448 284 444 283 443 289 449 285 445 284 444 290 450 286 446 285 445 291 451 105 182 292 452 85 131 104 181 293 453 105 182 293 453 294 454 292 452 292 452 105 182 293 453 103 180 295 455 104 181 295 455 296 456 293 453 296 456 297 457 294 454 293 453 104 181 295 455 294 454 293 453 296 456 102 179 298 458 103 180 298 458 299 459 295 455 299 459 300 460 296 456 300 460 301 461 297 457 295 455 103 180 298 458 296 456 295 455 299 459 297 457 296 456 300 460 101 177 302 462 102 179 302 462 303 463 298 458 303 463 304 464 299 459 304 464 305 465 300 460 305 465 306 466 301 461 298 458 102 179 302 462 299 459 298 458 303 463 300 460 299 459 304 464 301 461 300 460 305 465 27 467 307 468 101 177 307 468 308 469 302 462 308 469 309 470 303 463 309 470 310 471 304 464 310 471 311 472 305 465 311 472 196 323 306 466 302 462 101 177 307 468 303 463 302 462 308 469 304 464 303 463 309 470 305 465 304 464 310 471 306 466 305 465 311 472 132 212 246 406 133 213 131 211 312 473 132 212 312 473 241 401 246 406 246 406 132 212 312 473 130 210 313 474 131 211 313 474 314 475 312 473 314 475 237 397 241 401 312 473 131 211 313 474 241 401 312 473 314 475 129 209 315 476 130 210 315 476 316 477 313 474 316 477 317 478 314 475 317 478 234 394 237 397 313 474 130 210 315 476 314 475 313 474 316 477 237 397 314 475 317 478 128 208 318 479 129 209 318 479 319 480 315 476 319 480 320 481 316 477 320 481 321 482 317 478 321 482 232 392 234 394 315 476 129 209 318 479 316 477 315 476 319 480 317 478 316 477 320 481 234 394 317 478 321 482 127 207 231 391 128 208 231 391 230 390 318 479 230 390 229 389 319 480 229 389 228 388 320 481 228 388 227 387 321 482 227 387 21 21 232 392 318 479 128 208 231 391 319 480 318 479 230 390 320 481 319 480 229 389 321 482 320 481 228 388 232 392 321 482 227 387 153 248 266 426 154 249 152 247 322 483 153 248 322 483 261 421 266 426 266 426 153 248 322 483 151 246 323 484 152 247 323 484 324 485 322 483 324 485 257 417 261 421 322 483 152 247 323 484 261 421 322 483 324 485 150 245 325 486 151 246 325 486 326 487 323 484 326 487 327 488 324 485 327 488 254 414 257 417 323 484 151 246 325 486 324 485 323 484 326 487 257 417 324 485 327 488 149 243 328 489 150 245 328 489 329 490 325 486 329 490 330 491 326 487 330 491 331 492 327 488 331 492 252 412 254 414 325 486 150 245 328 489 326 487 325 486 329 490 327 488 326 487 330 491 254 414 327 488 331 492 133 213 251 411 149 243 251 411 250 410 328 489 250 410 249 409 329 490 249 409 248 408 330 491 248 408 247 407 331 492 247 407 43 57 252 412 328 489 149 243 251 411 329 490 328 489 250 410 330 491 329 490 249 409 331 492 330 491 248 408 252 412 331 492 247 407 174 285 286 446 175 286 173 284 332 493 174 285 332 493 281 441 286 446 286 446 174 285 332 493 172 283 333 494 173 284 333 494 334 495 332 493 334 495 277 437 281 441 332 493 173 284 333 494 281 441 332 493 334 495 171 282 335 496 172 283 335 496 336 497 333 494 336 497 337 498 334 495 337 498 274 434 277 437 333 494 172 283 335 496 334 495 333 494 336 497 277 437 334 495 337 498 170 280 338 499 171 282 338 499 339 500 335 496 339 500 340 501 336 497 340 501 341 502 337 498 341 502 272 432 274 434 335 496 171 282 338 499 336 497 335 496 339 500 337 498 336 497 340 501 274 434 337 498 341 502 154 249 271 431 170 280 271 431 270 430 338 499 270 430 269 429 339 500 269 429 268 428 340 501 268 428 267 427 341 502 267 427 64 94 272 432 338 499 170 280 271 431 339 500 338 499 270 430 340 501 339 500 269 429 341 502 340 501 268 428 272 432 341 502 267 427 195 322 306 466 196 323 194 321 342 503 195 322 342 503 301 461 306 466 306 466 195 322 342 503 193 320 343 504 194 321 343 504 344 505 342 503 344 505 297 457 301 461 342 503 194 321 343 504 301 461 342 503 344 505 192 319 345 506 193 320 345 506 346 507 343 504 346 507 347 508 344 505 347 508 294 454 297 457 343 504 193 320 345 506 344 505 343 504 346 507 297 457 344 505 347 508 191 317 348 509 192 319 348 509 349 510 345 506 349 510 350 511 346 507 350 511 351 512 347 508 351 512 292 452 294 454 345 506 192 319 348 509 346 507 345 506 349 510 347 508 346 507 350 511 294 454 347 508 351 512 175 286 291 451 191 317 291 451 290 450 348 509 290 450 289 449 349 510 289 449 288 448 350 511 288 448 287 447 351 512 287 447 85 131 292 452 348 509 191 317 291 451 349 510 348 509 290 450 350 511 349 510 289 449 351 512 350 511 288 448 292 452 351 512 287 447 211 367 226 513 127 514 210 366 352 515 211 367 352 515 221 516 226 517 226 518 211 367 352 515 209 365 353 519 210 366 353 519 354 520 352 515 354 520 217 521 221 522 352 515 210 366 353 519 221 523 352 515 354 520 208 364 355 524 209 365 355 524 356 525 353 519 356 525 357 526 354 520 357 526 214 527 217 528 353 519 209 365 355 524 354 520 353 519 356 525 217 529 354 520 357 526 207 362 358 530 208 364 358 530 359 531 355 524 359 531 360 532 356 525 360 532 361 533 357 526 361 533 212 534 214 535 355 524 208 364 358 530 356 525 355 524 359 531 357 526 356 525 360 532 214 536 357 526 361 533 196 323 311 472 207 362 311 472 310 471 358 530 310 471 309 470 359 531 309 470 308 469 360 532 308 469 307 468 361 533 307 468 27 537 212 538 358 530 207 362 311 472 359 531 358 530 310 471 360 532 359 531 309 470 361 533 360 532 308 469 212 539 361 533 307 468</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-high-inverted">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-high.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-high.dae
new file mode 100644
index 00000000..44a68b62
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-high.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-high.mb</source_data>
+ </contributor>
+ <created>2008-09-19T22:04:03Z</created>
+ <modified>2008-09-19T22:04:03Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="1086">0 50 0 8.72494 49.1512 2.8349 0 49.1512 9.17395 17.1537 46.6335 5.57358 8.84255 47.6832 12.1707 0 46.6335 18.0365 25 42.5325 8.12299 17.2996 44.4764 14.919 8.84298 44.4764 21.0631 0 42.5325 26.2866 31.9975 36.9875 10.3966 26.1426 38.7299 17.7923 17.8411 39.7327 24.5562 8.84298 38.7299 30.3612 0 36.9875 33.6441 37.9086 30.1865 12.3172 32.6527 32.2104 19.9071 26.1426 33.2344 26.6841 17.2996 33.2344 33.1089 8.84255 32.2104 37.2062 0 30.1865 39.8594 42.5325 22.3607 13.8197 37.9086 24.5167 21.4912 31.9975 25.8403 28.4331 25 26.2866 34.4095 17.1537 25.8403 39.2177 8.72494 24.5167 42.6943 0 22.3607 44.7214 5.39231 49.1512 -7.42188 10.6016 46.6335 -14.5918 14.3075 47.6832 -4.6488 15.4509 42.5325 -21.2663 19.5347 44.4764 -11.8426 22.7648 44.4764 -1.90132 19.7755 36.9875 -27.2187 25 38.7299 -19.3649 28.8675 39.7327 -9.37962 31.6078 38.7299 0.971941 23.4288 30.1865 -32.247 29.023 32.2104 -24.9029 33.4566 33.2344 -16.6172 36.8343 33.2344 -6.22166 38.1177 32.2104 3.08758 26.2866 22.3607 -36.1803 32.1537 24.5167 -29.4121 36.9292 25.8403 -21.6451 40.4509 26.2866 -13.1433 42.599 25.8403 -4.19521 43.3009 24.5167 4.89537 -5.39231 49.1512 -7.42188 -10.6016 46.6335 -14.5918 0 47.6832 -15.0438 -15.4509 42.5325 -21.2663 -5.22646 44.4764 -22.2382 5.22646 44.4764 -22.2382 -19.7755 36.9875 -27.2187 -10.6917 38.7299 -29.7605 0 39.7327 -30.3531 10.6917 38.7299 -29.7605 -23.4288 30.1865 -32.247 -14.7155 32.2104 -35.298 -5.46526 33.2344 -36.9541 5.46526 33.2344 -36.9541 14.7155 32.2104 -35.298 -26.2866 22.3607 -36.1803 -18.0365 24.5167 -39.6688 -9.17395 25.8403 -41.8105 0 26.2866 -42.5325 9.17395 25.8403 -41.8105 18.0365 24.5167 -39.6688 -8.72494 49.1512 2.8349 -17.1537 46.6335 5.57358 -14.3075 47.6832 -4.6488 -25 42.5325 8.12299 -22.7648 44.4764 -1.90132 -19.5347 44.4764 -11.8426 -31.9975 36.9875 10.3966 -31.6078 38.7299 0.971941 -28.8675 39.7327 -9.37962 -25 38.7299 -19.3649 -37.9086 30.1865 12.3172 -38.1177 32.2104 3.08758 -36.8343 33.2344 -6.22166 -33.4566 33.2344 -16.6172 -29.023 32.2104 -24.9029 -42.5325 22.3607 13.8197 -43.3009 24.5167 4.89537 -42.599 25.8403 -4.19521 -40.4509 26.2866 -13.1433 -36.9292 25.8403 -21.6451 -32.1537 24.5167 -29.4121 -8.84255 47.6832 12.1707 -8.84298 44.4764 21.0631 -17.2996 44.4764 14.919 -8.84298 38.7299 30.3612 -17.8411 39.7327 24.5562 -26.1426 38.7299 17.7923 -8.84255 32.2104 37.2062 -17.2996 33.2344 33.1089 -26.1426 33.2344 26.6841 -32.6527 32.2104 19.9071 -8.72494 24.5167 42.6943 -17.1537 25.8403 39.2177 -25 26.2866 34.4095 -31.9975 25.8403 28.4331 -37.9086 24.5167 21.4912 0 -50 0 5.39231 -49.1512 7.42188 8.72494 -49.1512 -2.8349 10.6016 -46.6335 14.5918 14.3075 -47.6832 4.6488 17.1537 -46.6335 -5.57358 15.4509 -42.5325 21.2663 19.5347 -44.4764 11.8426 22.7648 -44.4764 1.90132 25 -42.5325 -8.12299 19.7755 -36.9875 27.2187 25 -38.7299 19.3649 28.8675 -39.7327 9.37962 31.6078 -38.7299 -0.971941 31.9975 -36.9875 -10.3966 23.4288 -30.1865 32.247 29.023 -32.2104 24.9029 33.4566 -33.2344 16.6172 36.8343 -33.2344 6.22166 38.1177 -32.2104 -3.08758 37.9086 -30.1865 -12.3172 26.2866 -22.3607 36.1803 32.1537 -24.5167 29.4121 36.9292 -25.8403 21.6451 40.4509 -26.2866 13.1433 42.599 -25.8403 4.19521 43.3009 -24.5167 -4.89537 42.5325 -22.3607 -13.8197 0 -49.1512 -9.17395 8.84255 -47.6832 -12.1707 0 -46.6335 -18.0365 17.2996 -44.4764 -14.919 8.84298 -44.4764 -21.0631 0 -42.5325 -26.2866 26.1426 -38.7299 -17.7923 17.8411 -39.7327 -24.5562 8.84298 -38.7299 -30.3612 0 -36.9875 -33.6441 32.6527 -32.2104 -19.9071 26.1426 -33.2344 -26.6841 17.2996 -33.2344 -33.1089 8.84255 -32.2104 -37.2062 0 -30.1865 -39.8594 37.9086 -24.5167 -21.4912 31.9975 -25.8403 -28.4331 25 -26.2866 -34.4095 17.1537 -25.8403 -39.2177 8.72494 -24.5167 -42.6943 0 -22.3607 -44.7214 -8.72494 -49.1512 -2.8349 -8.84255 -47.6832 -12.1707 -17.1537 -46.6335 -5.57358 -8.84298 -44.4764 -21.0631 -17.2996 -44.4764 -14.919 -25 -42.5325 -8.12299 -8.84298 -38.7299 -30.3612 -17.8411 -39.7327 -24.5562 -26.1426 -38.7299 -17.7923 -31.9975 -36.9875 -10.3966 -8.84255 -32.2104 -37.2062 -17.2996 -33.2344 -33.1089 -26.1426 -33.2344 -26.6841 -32.6527 -32.2104 -19.9071 -37.9086 -30.1865 -12.3172 -8.72494 -24.5167 -42.6943 -17.1537 -25.8403 -39.2177 -25 -26.2866 -34.4095 -31.9975 -25.8403 -28.4331 -37.9086 -24.5167 -21.4912 -42.5325 -22.3607 -13.8197 -5.39231 -49.1512 7.42188 -14.3075 -47.6832 4.6488 -10.6016 -46.6335 14.5918 -22.7648 -44.4764 1.90132 -19.5347 -44.4764 11.8426 -15.4509 -42.5325 21.2663 -31.6078 -38.7299 -0.971941 -28.8675 -39.7327 9.37962 -25 -38.7299 19.3649 -19.7755 -36.9875 27.2187 -38.1177 -32.2104 -3.08758 -36.8343 -33.2344 6.22166 -33.4566 -33.2344 16.6172 -29.023 -32.2104 24.9029 -23.4288 -30.1865 32.247 -43.3009 -24.5167 -4.89537 -42.599 -25.8403 4.19521 -40.4509 -26.2866 13.1433 -36.9292 -25.8403 21.6451 -32.1537 -24.5167 29.4121 -26.2866 -22.3607 36.1803 0 -47.6832 15.0438 -5.22646 -44.4764 22.2382 5.22646 -44.4764 22.2382 -10.6917 -38.7299 29.7605 0 -39.7327 30.3531 10.6917 -38.7299 29.7605 -14.7155 -32.2104 35.298 -5.46526 -33.2344 36.9541 5.46526 -33.2344 36.9541 14.7155 -32.2104 35.298 -18.0365 -24.5167 39.6688 -9.17395 -25.8403 41.8105 0 -26.2866 42.5325 9.17395 -25.8403 41.8105 18.0365 -24.5167 39.6688 5.39231 15.3427 47.2813 14.3075 17.1665 44.7281 10.6016 7.80382 48.236 22.7648 18.1898 40.6312 19.5347 9.29806 45.0771 15.4509 0 47.5528 31.6078 18.1898 34.2064 28.8675 9.37962 39.7327 25 0 43.3013 19.7755 -7.80382 45.2552 38.1177 17.1665 27.429 36.8343 9.29806 32.5082 33.4566 0 37.1572 29.023 -7.86893 39.9468 23.4288 -15.3427 41.4209 43.3009 15.3427 19.7391 42.599 7.80382 24.9884 40.4509 0 29.3893 36.9292 -7.80382 32.7923 32.1537 -15.3427 35.0819 46.6335 15.3427 9.48234 46.9602 17.1665 0.214459 49.1512 7.80382 4.82303 45.6773 18.1898 -9.09492 48.9074 9.29806 -4.64903 50 0 0 42.2995 18.1898 -19.4905 46.7086 9.37962 -15.1765 48.9074 0 -10.3955 49.1512 -7.80382 -4.82303 37.8656 17.1665 -27.776 42.2995 9.29806 -24.9859 45.6773 0 -20.3369 46.9602 -7.86893 -15.2583 46.6335 -15.3427 -9.48234 32.1537 15.3427 -35.0819 36.9292 7.80382 -32.7923 40.4509 0 -29.3893 42.599 -7.80382 -24.9884 43.3009 -15.3427 -19.7391 23.4288 15.3427 -41.4209 14.7155 17.1665 -44.5956 19.7755 7.80382 -45.2552 5.46526 18.1898 -46.2521 10.6917 9.29806 -47.9503 15.4509 0 -47.5528 -5.46526 18.1898 -46.2521 0 9.37962 -49.1123 5.22646 0 -49.7261 10.6016 -7.80382 -48.236 -14.7155 17.1665 -44.5956 -10.6917 9.29806 -47.9503 -5.22646 0 -49.7261 0 -7.86893 -49.3769 5.39231 -15.3427 -47.2813 -23.4288 15.3427 -41.4209 -19.7755 7.80382 -45.2552 -15.4509 0 -47.5528 -10.6016 -7.80382 -48.236 -5.39231 -15.3427 -47.2813 -32.1537 15.3427 -35.0819 -37.8656 17.1665 -27.776 -36.9292 7.80382 -32.7923 -42.2995 18.1898 -19.4905 -42.2995 9.29806 -24.9859 -40.4509 0 -29.3893 -45.6773 18.1898 -9.09492 -46.7086 9.37962 -15.1765 -45.6773 0 -20.3369 -42.599 -7.80382 -24.9884 -46.9602 17.1665 0.214459 -48.9074 9.29806 -4.64903 -48.9074 0 -10.3955 -46.9602 -7.86893 -15.2583 -43.3009 -15.3427 -19.7391 -46.6335 15.3427 9.48234 -49.1512 7.80382 4.82303 -50 0 0 -49.1512 -7.80382 -4.82303 -46.6335 -15.3427 -9.48234 -43.3009 15.3427 19.7391 -38.1177 17.1665 27.429 -42.599 7.80382 24.9884 -31.6078 18.1898 34.2064 -36.8343 9.29806 32.5082 -40.4509 0 29.3893 -22.7648 18.1898 40.6312 -28.8675 9.37962 39.7327 -33.4566 0 37.1572 -36.9292 -7.80382 32.7923 -14.3075 17.1665 44.7281 -19.5347 9.29806 45.0771 -25 0 43.3013 -29.023 -7.86893 39.9468 -32.1537 -15.3427 35.0819 -5.39231 15.3427 47.2813 -10.6016 7.80382 48.236 -15.4509 0 47.5528 -19.7755 -7.80382 45.2552 -23.4288 -15.3427 41.4209 46.9602 -17.1665 -0.214459 45.6773 -18.1898 9.09492 48.9074 -9.29806 4.64903 42.2995 -18.1898 19.4905 46.7086 -9.37962 15.1765 48.9074 0 10.3955 37.8656 -17.1665 27.776 42.2995 -9.29806 24.9859 45.6773 0 20.3369 46.9602 7.86893 15.2583 14.3075 -17.1665 -44.7281 22.7648 -18.1898 -40.6312 19.5347 -9.29806 -45.0771 31.6078 -18.1898 -34.2064 28.8675 -9.37962 -39.7327 25 0 -43.3013 38.1177 -17.1665 -27.429 36.8343 -9.29806 -32.5082 33.4566 0 -37.1572 29.023 7.86893 -39.9468 -38.1177 -17.1665 -27.429 -31.6078 -18.1898 -34.2064 -36.8343 -9.29806 -32.5082 -22.7648 -18.1898 -40.6312 -28.8675 -9.37962 -39.7327 -33.4566 0 -37.1572 -14.3075 -17.1665 -44.7281 -19.5347 -9.29806 -45.0771 -25 0 -43.3013 -29.023 7.86893 -39.9468 -37.8656 -17.1665 27.776 -42.2995 -18.1898 19.4905 -42.2995 -9.29806 24.9859 -45.6773 -18.1898 9.09492 -46.7086 -9.37962 15.1765 -45.6773 0 20.3369 -46.9602 -17.1665 -0.214459 -48.9074 -9.29806 4.64903 -48.9074 0 10.3955 -46.9602 7.86893 15.2583 14.7155 -17.1665 44.5956 5.46526 -18.1898 46.2521 10.6917 -9.29806 47.9503 -5.46526 -18.1898 46.2521 0 -9.37962 49.1123 5.22646 0 49.7261 -14.7155 -17.1665 44.5956 -10.6917 -9.29806 47.9503 -5.22646 0 49.7261 0 7.86893 49.3769</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="362" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="1086">0 1 -0.000000 0.165156 0.984806 0.053662 0 0.984806 0.173655 0.33628 0.935402 0.109264 0.1769 0.953637 0.243482 0 0.935402 0.353586 0.5 0.850651 0.16246 0.351546 0.885484 0.303864 0.180358 0.885484 0.428239 0 0.850651 0.525731 0.645311 0.734581 0.209674 0.515363 0.77903 0.357091 0.356822 0.794655 0.491123 0.180358 0.77903 0.600487 0 0.734581 0.678521 0.763866 0.595741 0.248195 0.652988 0.644256 0.398172 0.515363 0.667784 0.537089 0.351546 0.667784 0.656109 0.1769 0.644256 0.74407 0 0.595741 0.803176 0.850651 0.447214 0.276393 0.763866 0.488416 0.421851 0.645312 0.516053 0.56326 0.5 0.525731 0.688191 0.33628 0.516053 0.787785 0.165156 0.488416 0.856839 0 0.447214 0.894427 0.102072 0.984806 -0.14049 0.207833 0.935402 -0.286057 0.28623 0.953637 -0.093001 0.309017 0.850651 -0.425326 0.397625 0.885484 -0.240441 0.463014 0.885484 -0.039197 0.398825 0.734581 -0.548935 0.49887 0.77903 -0.379792 0.57735 0.794654 -0.187592 0.62683 0.77903 0.01403 0.472095 0.595741 -0.649783 0.580469 0.644256 -0.497986 0.670058 0.667784 -0.32417 0.732631 0.667785 -0.131591 0.762318 0.644256 0.061688 0.525731 0.447214 -0.723607 0.637252 0.488416 -0.596121 0.735105 0.516053 -0.439671 0.809017 0.525731 -0.262865 0.853144 0.516053 -0.076382 0.865939 0.488416 0.107705 -0.102072 0.984806 -0.14049 -0.207833 0.935402 -0.286057 0 0.953637 -0.30096 -0.309017 0.850651 -0.425326 -0.105801 0.885484 -0.452465 0.105801 0.885484 -0.452465 -0.398825 0.734581 -0.548935 -0.207045 0.77903 -0.591815 0 0.794654 -0.607062 0.207045 0.77903 -0.591815 -0.472095 0.595741 -0.649783 -0.294238 0.644256 -0.705945 -0.101244 0.667784 -0.737437 0.101244 0.667784 -0.737437 0.294238 0.644256 -0.705945 -0.525731 0.447214 -0.723607 -0.370023 0.488416 -0.790274 -0.190992 0.516053 -0.834992 0 0.525731 -0.850651 0.190992 0.516053 -0.834992 0.370023 0.488416 -0.790274 -0.165156 0.984806 0.053662 -0.33628 0.935402 0.109264 -0.28623 0.953637 -0.093001 -0.5 0.850651 0.16246 -0.463014 0.885484 -0.039197 -0.397625 0.885484 -0.240441 -0.645311 0.734581 0.209674 -0.62683 0.77903 0.01403 -0.57735 0.794654 -0.187592 -0.49887 0.77903 -0.379792 -0.763866 0.595741 0.248195 -0.762318 0.644256 0.061688 -0.732631 0.667785 -0.131591 -0.670058 0.667784 -0.32417 -0.580469 0.644256 -0.497986 -0.850651 0.447214 0.276393 -0.865939 0.488416 0.107705 -0.853144 0.516053 -0.076382 -0.809017 0.525731 -0.262865 -0.735105 0.516053 -0.439671 -0.637252 0.488416 -0.596121 -0.1769 0.953637 0.243482 -0.180358 0.885484 0.428239 -0.351546 0.885484 0.303864 -0.180358 0.77903 0.600487 -0.356822 0.794655 0.491123 -0.515363 0.77903 0.357091 -0.1769 0.644256 0.74407 -0.351546 0.667785 0.656109 -0.515363 0.667784 0.537089 -0.652988 0.644256 0.398172 -0.165156 0.488416 0.856839 -0.33628 0.516053 0.787785 -0.5 0.525731 0.688191 -0.645312 0.516053 0.56326 -0.763866 0.488416 0.421851 0 -1 0.000000 0.102072 -0.984806 0.14049 0.165156 -0.984806 -0.053662 0.207833 -0.935402 0.286057 0.28623 -0.953637 0.093001 0.33628 -0.935402 -0.109264 0.309017 -0.850651 0.425326 0.397625 -0.885484 0.240441 0.463014 -0.885484 0.039197 0.5 -0.850651 -0.16246 0.398825 -0.734581 0.548935 0.49887 -0.77903 0.379792 0.57735 -0.794654 0.187592 0.62683 -0.77903 -0.01403 0.645311 -0.734581 -0.209674 0.472095 -0.595741 0.649783 0.580469 -0.644256 0.497986 0.670058 -0.667784 0.32417 0.732631 -0.667785 0.131591 0.762318 -0.644256 -0.061688 0.763866 -0.595741 -0.248195 0.525731 -0.447214 0.723607 0.637252 -0.488416 0.596121 0.735105 -0.516053 0.439671 0.809017 -0.525731 0.262865 0.853144 -0.516053 0.076382 0.865939 -0.488416 -0.107705 0.850651 -0.447214 -0.276393 0 -0.984806 -0.173655 0.1769 -0.953637 -0.243482 0 -0.935402 -0.353586 0.351546 -0.885484 -0.303864 0.180358 -0.885484 -0.428239 0 -0.850651 -0.525731 0.515363 -0.77903 -0.357091 0.356822 -0.794655 -0.491123 0.180358 -0.77903 -0.600487 0 -0.734581 -0.678521 0.652988 -0.644256 -0.398172 0.515363 -0.667784 -0.537089 0.351546 -0.667784 -0.656109 0.1769 -0.644256 -0.74407 0 -0.595741 -0.803176 0.763866 -0.488416 -0.421851 0.645312 -0.516053 -0.56326 0.5 -0.525731 -0.688191 0.33628 -0.516053 -0.787785 0.165156 -0.488416 -0.856839 0 -0.447214 -0.894427 -0.165156 -0.984806 -0.053662 -0.1769 -0.953637 -0.243482 -0.33628 -0.935402 -0.109264 -0.180358 -0.885484 -0.428239 -0.351546 -0.885484 -0.303864 -0.5 -0.850651 -0.16246 -0.180358 -0.77903 -0.600487 -0.356822 -0.794655 -0.491123 -0.515363 -0.77903 -0.357091 -0.645311 -0.734581 -0.209674 -0.1769 -0.644256 -0.74407 -0.351546 -0.667785 -0.656109 -0.515363 -0.667784 -0.537089 -0.652988 -0.644256 -0.398172 -0.763866 -0.595741 -0.248195 -0.165156 -0.488416 -0.856839 -0.33628 -0.516053 -0.787785 -0.5 -0.525731 -0.688191 -0.645312 -0.516053 -0.56326 -0.763866 -0.488416 -0.421851 -0.850651 -0.447214 -0.276393 -0.102072 -0.984806 0.14049 -0.28623 -0.953637 0.093001 -0.207833 -0.935402 0.286057 -0.463014 -0.885484 0.039197 -0.397625 -0.885484 0.240441 -0.309017 -0.850651 0.425326 -0.62683 -0.77903 -0.01403 -0.57735 -0.794654 0.187592 -0.49887 -0.77903 0.379792 -0.398825 -0.734581 0.548935 -0.762318 -0.644256 -0.061688 -0.732631 -0.667785 0.131591 -0.670058 -0.667784 0.32417 -0.580469 -0.644256 0.497986 -0.472095 -0.595741 0.649783 -0.865939 -0.488416 -0.107705 -0.853144 -0.516053 0.076382 -0.809017 -0.525731 0.262865 -0.735105 -0.516053 0.439671 -0.637252 -0.488416 0.596121 -0.525731 -0.447214 0.723607 0 -0.953637 0.30096 -0.105801 -0.885484 0.452465 0.105801 -0.885484 0.452465 -0.207045 -0.77903 0.591815 0 -0.794654 0.607062 0.207045 -0.77903 0.591815 -0.294238 -0.644256 0.705945 -0.101244 -0.667784 0.737437 0.101244 -0.667784 0.737437 0.294238 -0.644256 0.705945 -0.370023 -0.488416 0.790274 -0.190992 -0.516053 0.834992 0 -0.525731 0.850651 0.190992 -0.516053 0.834992 0.370023 -0.488416 0.790274 0.102072 0.31476 0.943667 0.28623 0.343296 0.89455 0.207832 0.162468 0.964578 0.463014 0.360942 0.80953 0.397625 0.180943 0.89953 0.309017 0 0.951057 0.62683 0.360942 0.690511 0.57735 0.187592 0.794654 0.49887 0.008696 0.866633 0.398824 -0.162468 0.902521 0.762318 0.343296 0.548653 0.73263 0.180943 0.656134 0.670058 0.008696 0.742258 0.580469 -0.157292 0.798946 0.472095 -0.31476 0.823439 0.865939 0.31476 0.388686 0.853144 0.162468 0.495731 0.809017 0 0.587785 0.735104 -0.162467 0.658199 0.637252 -0.31476 0.703446 0.929023 0.31476 0.194533 0.939218 0.343296 0.004209 0.981592 0.162467 0.10041 0.912988 0.360942 -0.190193 0.978377 0.180943 -0.100194 1 0 0 0.850416 0.360942 -0.382771 0.934172 0.187592 -0.303531 0.978377 0.008696 -0.206649 0.981592 -0.162467 -0.10041 0.757369 0.343296 -0.555464 0.850416 0.180943 -0.494017 0.912988 0.008695 -0.407893 0.939218 -0.157292 -0.30517 0.929023 -0.31476 -0.194533 0.637252 0.31476 -0.703446 0.735104 0.162467 -0.658199 0.809017 0 -0.587785 0.853144 -0.162468 -0.495731 0.865938 -0.31476 -0.388686 0.472095 0.31476 -0.823439 0.294238 0.343296 -0.891948 0.398824 0.162468 -0.902521 0.101244 0.360941 -0.927076 0.207045 0.180943 -0.961453 0.309017 0 -0.951057 -0.101244 0.360941 -0.927076 0 0.187592 -0.982247 0.1058 0.008696 -0.994349 0.207832 -0.162468 -0.964578 -0.294238 0.343296 -0.891948 -0.207045 0.180943 -0.961453 -0.1058 0.008696 -0.994349 0 -0.157292 -0.987552 0.102072 -0.31476 -0.943667 -0.472095 0.31476 -0.823439 -0.398825 0.162468 -0.902521 -0.309017 0 -0.951057 -0.207832 -0.162468 -0.964578 -0.102072 -0.31476 -0.943667 -0.637252 0.31476 -0.703446 -0.757369 0.343296 -0.555464 -0.735105 0.162467 -0.658199 -0.850416 0.360942 -0.382771 -0.850416 0.180943 -0.494017 -0.809017 0 -0.587785 -0.912988 0.360942 -0.190193 -0.934172 0.187592 -0.303531 -0.912988 0.008695 -0.407893 -0.853144 -0.162468 -0.495731 -0.939218 0.343296 0.004209 -0.978377 0.180943 -0.100194 -0.978377 0.008696 -0.206649 -0.939218 -0.157292 -0.30517 -0.865938 -0.31476 -0.388686 -0.929023 0.31476 0.194533 -0.981592 0.162467 0.10041 -1 0 0 -0.981592 -0.162467 -0.10041 -0.929023 -0.31476 -0.194533 -0.865938 0.31476 0.388686 -0.762318 0.343296 0.548653 -0.853144 0.162468 0.495731 -0.62683 0.360942 0.690511 -0.73263 0.180943 0.656134 -0.809017 0 0.587785 -0.463014 0.360942 0.80953 -0.57735 0.187592 0.794654 -0.670058 0.008696 0.742258 -0.735105 -0.162467 0.658199 -0.28623 0.343296 0.89455 -0.397625 0.180943 0.89953 -0.49887 0.008696 0.866633 -0.580469 -0.157292 0.798946 -0.637252 -0.31476 0.703446 -0.102072 0.31476 0.943667 -0.207832 0.162468 0.964578 -0.309017 0 0.951057 -0.398825 -0.162468 0.902521 -0.472095 -0.31476 0.823439 0.939218 -0.343296 -0.004209 0.912988 -0.360942 0.190193 0.978377 -0.180943 0.100194 0.850416 -0.360942 0.382771 0.934172 -0.187592 0.303531 0.978377 -0.008696 0.206649 0.757369 -0.343296 0.555464 0.850416 -0.180943 0.494017 0.912988 -0.008695 0.407893 0.939218 0.157292 0.30517 0.28623 -0.343296 -0.89455 0.463014 -0.360942 -0.80953 0.397625 -0.180943 -0.89953 0.62683 -0.360942 -0.690511 0.57735 -0.187592 -0.794654 0.49887 -0.008696 -0.866633 0.762318 -0.343296 -0.548653 0.73263 -0.180943 -0.656134 0.670058 -0.008696 -0.742258 0.580469 0.157292 -0.798946 -0.762318 -0.343296 -0.548653 -0.62683 -0.360942 -0.690511 -0.73263 -0.180943 -0.656134 -0.463014 -0.360942 -0.80953 -0.57735 -0.187592 -0.794654 -0.670058 -0.008696 -0.742258 -0.28623 -0.343296 -0.89455 -0.397625 -0.180943 -0.89953 -0.49887 -0.008696 -0.866633 -0.580469 0.157292 -0.798946 -0.757369 -0.343296 0.555464 -0.850416 -0.360942 0.382771 -0.850416 -0.180943 0.494017 -0.912988 -0.360942 0.190193 -0.934172 -0.187592 0.303531 -0.912988 -0.008695 0.407893 -0.939218 -0.343296 -0.004209 -0.978377 -0.180943 0.100194 -0.978377 -0.008696 0.206649 -0.939218 0.157292 0.30517 0.294238 -0.343296 0.891948 0.101244 -0.360941 0.927076 0.207045 -0.180943 0.961453 -0.101244 -0.360941 0.927076 0 -0.187592 0.982247 0.1058 -0.008696 0.994349 -0.294238 -0.343296 0.891948 -0.207045 -0.180943 0.961453 -0.1058 -0.008696 0.994349 0 0.157292 0.987552</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="362" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="1080">0.106061 0.944444 0.090909 1 0.075757 0.944444 0.121212 0.888889 0.090909 0.888889 0.060606 0.888889 0.136364 0.833333 0.106061 0.833333 0.075757 0.833333 0.045454 0.833333 0.151515 0.777778 0.121212 0.777778 0.090909 0.777778 0.060606 0.777778 0.030303 0.777778 0.166667 0.722222 0.136364 0.722222 0.106061 0.722222 0.075757 0.722222 0.045454 0.722222 0.015151 0.722222 0.181818 0.666667 0.151515 0.666667 0.121212 0.666667 0.090909 0.666667 0.060606 0.666667 0.030303 0.666667 0 0.666667 0.287879 0.944444 0.272727 1 0.257576 0.944444 0.30303 0.888889 0.272727 0.888889 0.257576 0.944444 0.242424 0.888889 0.257576 0.944444 0.318182 0.833333 0.287879 0.833333 0.257576 0.833333 0.242424 0.888889 0.227273 0.833333 0.242424 0.888889 0.333333 0.777778 0.30303 0.777778 0.272727 0.777778 0.242424 0.777778 0.227273 0.833333 0.212121 0.777778 0.227273 0.833333 0.348485 0.722222 0.318182 0.722222 0.287879 0.722222 0.257576 0.722222 0.227273 0.722222 0.212121 0.777778 0.19697 0.722222 0.212121 0.777778 0.363636 0.666667 0.333333 0.666667 0.30303 0.666667 0.272727 0.666667 0.242424 0.666667 0.212121 0.666667 0.19697 0.722222 0.19697 0.722222 0.469697 0.944444 0.454545 1 0.439394 0.944444 0.484848 0.888889 0.454545 0.888889 0.439394 0.944444 0.424242 0.888889 0.439394 0.944444 0.5 0.833333 0.469697 0.833333 0.439394 0.833333 0.424242 0.888889 0.409091 0.833333 0.424242 0.888889 0.515152 0.777778 0.484848 0.777778 0.454545 0.777778 0.424242 0.777778 0.409091 0.833333 0.393939 0.777778 0.409091 0.833333 0.530303 0.722222 0.5 0.722222 0.469697 0.722222 0.439394 0.722222 0.409091 0.722222 0.393939 0.777778 0.378788 0.722222 0.393939 0.777778 0.545455 0.666667 0.515152 0.666667 0.484848 0.666667 0.454545 0.666667 0.424242 0.666667 0.393939 0.666667 0.378788 0.722222 0.378788 0.722222 0.651515 0.944444 0.636364 1 0.621212 0.944444 0.666667 0.888889 0.636364 0.888889 0.621212 0.944444 0.606061 0.888889 0.621212 0.944444 0.681818 0.833333 0.651515 0.833333 0.621212 0.833333 0.606061 0.888889 0.590909 0.833333 0.606061 0.888889 0.69697 0.777778 0.666667 0.777778 0.636364 0.777778 0.606061 0.777778 0.590909 0.833333 0.575758 0.777778 0.590909 0.833333 0.712121 0.722222 0.681818 0.722222 0.651515 0.722222 0.621212 0.722222 0.590909 0.722222 0.575758 0.777778 0.560606 0.722222 0.575758 0.777778 0.727273 0.666667 0.69697 0.666667 0.666667 0.666667 0.636364 0.666667 0.606061 0.666667 0.575758 0.666667 0.560606 0.722222 0.560606 0.722222 0.833333 0.944444 0.818182 1 0.80303 0.944444 0.848485 0.888889 0.833333 0.944444 0.818182 0.888889 0.80303 0.944444 0.787879 0.888889 0.80303 0.944444 0.833333 0.944444 0.863636 0.833333 0.848485 0.888889 0.833333 0.833333 0.80303 0.833333 0.787879 0.888889 0.772727 0.833333 0.848485 0.888889 0.787879 0.888889 0.878788 0.777778 0.863636 0.833333 0.848485 0.777778 0.818182 0.777778 0.787879 0.777778 0.772727 0.833333 0.757576 0.777778 0.863636 0.833333 0.772727 0.833333 0.893939 0.722222 0.878788 0.777778 0.863636 0.722222 0.833333 0.722222 0.80303 0.722222 0.772727 0.722222 0.757576 0.777778 0.742424 0.722222 0.878788 0.777778 0.757576 0.777778 0.909091 0.666667 0.893939 0.722222 0.878788 0.666667 0.848485 0.666667 0.818182 0.666667 0.787879 0.666667 0.757576 0.666667 0.742424 0.722222 0.893939 0.722222 0.742424 0.722222 0.166667 0.055555 0.181818 0 0.19697 0.055555 0.151515 0.111111 0.181818 0.111111 0.212121 0.111111 0.136364 0.166667 0.166667 0.166667 0.19697 0.166667 0.227273 0.166667 0.121212 0.222222 0.151515 0.222222 0.181818 0.222222 0.212121 0.222222 0.242424 0.222222 0.106061 0.277778 0.136364 0.277778 0.166667 0.277778 0.19697 0.277778 0.227273 0.277778 0.257576 0.277778 0.090909 0.333333 0.121212 0.333333 0.151515 0.333333 0.181818 0.333333 0.212121 0.333333 0.242424 0.333333 0.272727 0.333333 0.348485 0.055555 0.363636 0 0.378788 0.055555 0.333333 0.111111 0.348485 0.055555 0.363636 0.111111 0.393939 0.111111 0.348485 0.055555 0.318182 0.166667 0.333333 0.111111 0.348485 0.166667 0.378788 0.166667 0.409091 0.166667 0.333333 0.111111 0.30303 0.222222 0.318182 0.166667 0.333333 0.222222 0.363636 0.222222 0.393939 0.222222 0.424242 0.222222 0.318182 0.166667 0.287879 0.277778 0.30303 0.222222 0.318182 0.277778 0.348485 0.277778 0.378788 0.277778 0.409091 0.277778 0.439394 0.277778 0.30303 0.222222 0.287879 0.277778 0.30303 0.333333 0.333333 0.333333 0.363636 0.333333 0.393939 0.333333 0.424242 0.333333 0.454545 0.333333 0.287879 0.277778 0.530303 0.055555 0.545455 0 0.560606 0.055555 0.515152 0.111111 0.530303 0.055555 0.545455 0.111111 0.575758 0.111111 0.530303 0.055555 0.5 0.166667 0.515152 0.111111 0.530303 0.166667 0.560606 0.166667 0.590909 0.166667 0.515152 0.111111 0.484848 0.222222 0.5 0.166667 0.515152 0.222222 0.545455 0.222222 0.575758 0.222222 0.606061 0.222222 0.5 0.166667 0.469697 0.277778 0.484848 0.222222 0.5 0.277778 0.530303 0.277778 0.560606 0.277778 0.590909 0.277778 0.621212 0.277778 0.484848 0.222222 0.469697 0.277778 0.484848 0.333333 0.515152 0.333333 0.545455 0.333333 0.575758 0.333333 0.606061 0.333333 0.636364 0.333333 0.469697 0.277778 0.712121 0.055555 0.727273 0 0.742424 0.055555 0.69697 0.111111 0.712121 0.055555 0.727273 0.111111 0.757576 0.111111 0.712121 0.055555 0.681818 0.166667 0.69697 0.111111 0.712121 0.166667 0.742424 0.166667 0.772727 0.166667 0.69697 0.111111 0.666667 0.222222 0.681818 0.166667 0.69697 0.222222 0.727273 0.222222 0.757576 0.222222 0.787879 0.222222 0.681818 0.166667 0.651515 0.277778 0.666667 0.222222 0.681818 0.277778 0.712121 0.277778 0.742424 0.277778 0.772727 0.277778 0.80303 0.277778 0.666667 0.222222 0.651515 0.277778 0.666667 0.333333 0.69697 0.333333 0.727273 0.333333 0.757576 0.333333 0.787879 0.333333 0.818182 0.333333 0.651515 0.277778 0.893939 0.055555 0.909091 0 0.924242 0.055555 0.878788 0.111111 0.893939 0.055555 0.909091 0.111111 0.924242 0.055555 0.939394 0.111111 0.924242 0.055555 0.893939 0.055555 0.863636 0.166667 0.878788 0.111111 0.893939 0.166667 0.924242 0.166667 0.939394 0.111111 0.954545 0.166667 0.878788 0.111111 0.939394 0.111111 0.848485 0.222222 0.863636 0.166667 0.878788 0.222222 0.909091 0.222222 0.939394 0.222222 0.954545 0.166667 0.969697 0.222222 0.863636 0.166667 0.954545 0.166667 0.833333 0.277778 0.848485 0.222222 0.863636 0.277778 0.893939 0.277778 0.924242 0.277778 0.954545 0.277778 0.969697 0.222222 0.984848 0.277778 0.848485 0.222222 0.969697 0.222222 0.833333 0.277778 0.848485 0.333333 0.878788 0.333333 0.909091 0.333333 0.939394 0.333333 0.969697 0.333333 0.984848 0.277778 1 0.333333 0.833333 0.277778 0.984848 0.277778 0.015151 0.611111 0.045454 0.611111 0.030303 0.555556 0.075757 0.611111 0.060606 0.555556 0.045454 0.5 0.106061 0.611111 0.090909 0.555556 0.075757 0.5 0.060606 0.444444 0.136364 0.611111 0.121212 0.555556 0.106061 0.5 0.090909 0.444444 0.075757 0.388889 0.166667 0.611111 0.151515 0.555556 0.136364 0.5 0.121212 0.444444 0.106061 0.388889 0.19697 0.611111 0.227273 0.611111 0.212121 0.555556 0.257576 0.611111 0.242424 0.555556 0.227273 0.5 0.287879 0.611111 0.272727 0.555556 0.257576 0.5 0.242424 0.444444 0.318182 0.611111 0.30303 0.555556 0.287879 0.5 0.272727 0.444444 0.257576 0.388889 0.348485 0.611111 0.333333 0.555556 0.318182 0.5 0.30303 0.444444 0.287879 0.388889 0.378788 0.611111 0.409091 0.611111 0.393939 0.555556 0.439394 0.611111 0.424242 0.555556 0.409091 0.5 0.469697 0.611111 0.454545 0.555556 0.439394 0.5 0.424242 0.444444 0.5 0.611111 0.484848 0.555556 0.469697 0.5 0.454545 0.444444 0.439394 0.388889 0.530303 0.611111 0.515152 0.555556 0.5 0.5 0.484848 0.444444 0.469697 0.388889 0.560606 0.611111 0.590909 0.611111 0.575758 0.555556 0.621212 0.611111 0.606061 0.555556 0.590909 0.5 0.651515 0.611111 0.636364 0.555556 0.621212 0.5 0.606061 0.444444 0.681818 0.611111 0.666667 0.555556 0.651515 0.5 0.636364 0.444444 0.621212 0.388889 0.712121 0.611111 0.69697 0.555556 0.681818 0.5 0.666667 0.444444 0.651515 0.388889 0.742424 0.611111 0.772727 0.611111 0.757576 0.555556 0.80303 0.611111 0.787879 0.555556 0.772727 0.5 0.833333 0.611111 0.818182 0.555556 0.80303 0.5 0.787879 0.444444 0.863636 0.611111 0.848485 0.555556 0.833333 0.5 0.818182 0.444444 0.80303 0.388889 0.909091 0.666667 0.893939 0.611111 0.878788 0.555556 0.863636 0.5 0.848485 0.444444 0.833333 0.388889 0.227273 0.388889 0.19697 0.388889 0.212121 0.444444 0.166667 0.388889 0.181818 0.444444 0.19697 0.5 0.136364 0.388889 0.151515 0.444444 0.166667 0.5 0.181818 0.555556 0.409091 0.388889 0.378788 0.388889 0.393939 0.444444 0.348485 0.388889 0.363636 0.444444 0.378788 0.5 0.318182 0.388889 0.333333 0.444444 0.348485 0.5 0.363636 0.555556 0.590909 0.388889 0.560606 0.388889 0.575758 0.444444 0.530303 0.388889 0.545455 0.444444 0.560606 0.5 0.5 0.388889 0.515152 0.444444 0.530303 0.5 0.545455 0.555556 0.772727 0.388889 0.742424 0.388889 0.757576 0.444444 0.712121 0.388889 0.727273 0.444444 0.742424 0.5 0.681818 0.388889 0.69697 0.444444 0.712121 0.5 0.727273 0.555556 1 0.333333 0.984848 0.388889 0.954545 0.388889 0.984848 0.388889 0.969697 0.444444 0.984848 0.388889 0.924242 0.388889 0.939394 0.444444 0.969697 0.444444 0.954545 0.5 0.969697 0.444444 0.893939 0.388889 0.909091 0.444444 0.924242 0.5 0.954545 0.5 0.939394 0.555556 0.954545 0.5 0.863636 0.388889 0.878788 0.444444 0.893939 0.5 0.909091 0.555556 0.939394 0.555556 0.924242 0.611111 0.939394 0.555556 0.924242 0.611111 0.909091 0.666667 0.924242 0.611111</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="540" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="720">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 0 1 2 2 3 3 1 0 4 4 4 4 2 2 5 5 2 2 4 4 1 0 6 6 3 3 7 7 7 7 4 4 8 8 8 8 5 5 9 9 4 4 7 7 3 3 5 5 8 8 4 4 10 10 6 6 11 11 11 11 7 7 12 12 12 12 8 8 13 13 13 13 9 9 14 14 7 7 11 11 6 6 8 8 12 12 7 7 9 9 13 13 8 8 15 15 10 10 16 16 16 16 11 11 17 17 17 17 12 12 18 18 18 18 13 13 19 19 19 19 14 14 20 20 11 11 16 16 10 10 12 12 17 17 11 11 13 13 18 18 12 12 14 14 19 19 13 13 21 21 15 15 22 22 22 22 16 16 23 23 23 23 17 17 24 24 24 24 18 18 25 25 25 25 19 19 26 26 26 26 20 20 27 27 16 16 22 22 15 15 17 17 23 23 16 16 18 18 24 24 17 17 19 19 25 25 18 18 20 20 26 26 19 19 28 28 0 29 1 30 29 31 28 28 30 32 30 32 1 33 3 34 1 35 30 32 28 28 31 36 29 31 32 37 32 37 30 32 33 38 33 38 3 39 6 40 30 32 32 37 29 31 3 41 33 38 30 32 34 42 31 36 35 43 35 43 32 37 36 44 36 44 33 38 37 45 37 45 6 46 10 47 32 37 35 43 31 36 33 38 36 44 32 37 6 48 37 45 33 38 38 49 34 42 39 50 39 50 35 43 40 51 40 51 36 44 41 52 41 52 37 45 42 53 42 53 10 54 15 55 35 43 39 50 34 42 36 44 40 51 35 43 37 45 41 52 36 44 10 56 42 53 37 45 43 57 38 49 44 58 44 58 39 50 45 59 45 59 40 51 46 60 46 60 41 52 47 61 47 61 42 53 48 62 48 62 15 63 21 21 39 50 44 58 38 49 40 51 45 59 39 50 41 52 46 60 40 51 42 53 47 61 41 52 15 64 48 62 42 53 49 65 0 66 28 67 50 68 49 65 51 69 51 69 28 70 29 71 28 72 51 69 49 65 52 73 50 68 53 74 53 74 51 69 54 75 54 75 29 76 31 77 51 69 53 74 50 68 29 78 54 75 51 69 55 79 52 73 56 80 56 80 53 74 57 81 57 81 54 75 58 82 58 82 31 83 34 84 53 74 56 80 52 73 54 75 57 81 53 74 31 85 58 82 54 75 59 86 55 79 60 87 60 87 56 80 61 88 61 88 57 81 62 89 62 89 58 82 63 90 63 90 34 91 38 92 56 80 60 87 55 79 57 81 61 88 56 80 58 82 62 89 57 81 34 93 63 90 58 82 64 94 59 86 65 95 65 95 60 87 66 96 66 96 61 88 67 97 67 97 62 89 68 98 68 98 63 90 69 99 69 99 38 100 43 57 60 87 65 95 59 86 61 88 66 96 60 87 62 89 67 97 61 88 63 90 68 98 62 89 38 101 69 99 63 90 70 102 0 103 49 104 71 105 70 102 72 106 72 106 49 107 50 108 49 109 72 106 70 102 73 110 71 105 74 111 74 111 72 106 75 112 75 112 50 113 52 114 72 106 74 111 71 105 50 115 75 112 72 106 76 116 73 110 77 117 77 117 74 111 78 118 78 118 75 112 79 119 79 119 52 120 55 121 74 111 77 117 73 110 75 112 78 118 74 111 52 122 79 119 75 112 80 123 76 116 81 124 81 124 77 117 82 125 82 125 78 118 83 126 83 126 79 119 84 127 84 127 55 128 59 129 77 117 81 124 76 116 78 118 82 125 77 117 79 119 83 126 78 118 55 130 84 127 79 119 85 131 80 123 86 132 86 132 81 124 87 133 87 133 82 125 88 134 88 134 83 126 89 135 89 135 84 127 90 136 90 136 59 137 64 94 81 124 86 132 80 123 82 125 87 133 81 124 83 126 88 134 82 125 84 127 89 135 83 126 59 138 90 136 84 127 2 139 0 140 70 141 5 142 2 143 91 144 91 144 70 145 71 146 70 147 91 144 2 148 9 149 5 150 92 151 92 151 91 144 93 152 93 152 71 153 73 154 91 144 92 151 5 155 71 156 93 152 91 144 14 157 9 158 94 159 94 159 92 151 95 160 95 160 93 152 96 161 96 161 73 162 76 163 92 151 94 159 9 164 93 152 95 160 92 151 73 165 96 161 93 152 20 166 14 167 97 168 97 168 94 159 98 169 98 169 95 160 99 170 99 170 96 161 100 171 100 171 76 172 80 173 94 159 97 168 14 174 95 160 98 169 94 159 96 161 99 170 95 160 76 175 100 171 96 161 27 176 20 177 101 178 101 178 97 168 102 179 102 179 98 169 103 180 103 180 99 170 104 181 104 181 100 171 105 182 105 182 80 183 85 131 97 168 101 178 20 184 98 169 102 179 97 168 99 170 103 180 98 169 100 171 104 181 99 170 80 185 105 182 100 171 107 186 106 187 108 188 109 189 107 186 110 190 110 190 108 188 111 191 108 188 110 190 107 186 112 192 109 189 113 193 113 193 110 190 114 194 114 194 111 191 115 195 110 190 113 193 109 189 111 191 114 194 110 190 116 196 112 192 117 197 117 197 113 193 118 198 118 198 114 194 119 199 119 199 115 195 120 200 113 193 117 197 112 192 114 194 118 198 113 193 115 195 119 199 114 194 121 201 116 196 122 202 122 202 117 197 123 203 123 203 118 198 124 204 124 204 119 199 125 205 125 205 120 200 126 206 117 197 122 202 116 196 118 198 123 203 117 197 119 199 124 204 118 198 120 200 125 205 119 199 127 207 121 201 128 208 128 208 122 202 129 209 129 209 123 203 130 210 130 210 124 204 131 211 131 211 125 205 132 212 132 212 126 206 133 213 122 202 128 208 121 201 123 203 129 209 122 202 124 204 130 210 123 203 125 205 131 211 124 204 126 206 132 212 125 205 108 214 106 215 134 216 111 217 108 218 135 219 135 219 134 216 136 220 134 216 135 219 108 221 115 222 111 223 137 224 137 224 135 219 138 225 138 225 136 220 139 226 135 219 137 224 111 227 136 220 138 225 135 219 120 228 115 229 140 230 140 230 137 224 141 231 141 231 138 225 142 232 142 232 139 226 143 233 137 224 140 230 115 234 138 225 141 231 137 224 139 226 142 232 138 225 126 235 120 236 144 237 144 237 140 230 145 238 145 238 141 231 146 239 146 239 142 232 147 240 147 240 143 233 148 241 140 230 144 237 120 242 141 231 145 238 140 230 142 232 146 239 141 231 143 233 147 240 142 232 133 213 126 243 149 244 149 244 144 237 150 245 150 245 145 238 151 246 151 246 146 239 152 247 152 247 147 240 153 248 153 248 148 241 154 249 144 237 149 244 126 250 145 238 150 245 144 237 146 239 151 246 145 238 147 240 152 247 146 239 148 241 153 248 147 240 134 251 106 252 155 253 136 254 134 255 156 256 156 256 155 253 157 257 155 253 156 256 134 258 139 259 136 260 158 261 158 261 156 256 159 262 159 262 157 257 160 263 156 256 158 261 136 264 157 257 159 262 156 256 143 265 139 266 161 267 161 267 158 261 162 268 162 268 159 262 163 269 163 269 160 263 164 270 158 261 161 267 139 271 159 262 162 268 158 261 160 263 163 269 159 262 148 272 143 273 165 274 165 274 161 267 166 275 166 275 162 268 167 276 167 276 163 269 168 277 168 277 164 270 169 278 161 267 165 274 143 279 162 268 166 275 161 267 163 269 167 276 162 268 164 270 168 277 163 269 154 249 148 280 170 281 170 281 165 274 171 282 171 282 166 275 172 283 172 283 167 276 173 284 173 284 168 277 174 285 174 285 169 278 175 286 165 274 170 281 148 287 166 275 171 282 165 274 167 276 172 283 166 275 168 277 173 284 167 276 169 278 174 285 168 277 155 288 106 289 176 290 157 291 155 292 177 293 177 293 176 290 178 294 176 290 177 293 155 295 160 296 157 297 179 298 179 298 177 293 180 299 180 299 178 294 181 300 177 293 179 298 157 301 178 294 180 299 177 293 164 302 160 303 182 304 182 304 179 298 183 305 183 305 180 299 184 306 184 306 181 300 185 307 179 298 182 304 160 308 180 299 183 305 179 298 181 300 184 306 180 299 169 309 164 310 186 311 186 311 182 304 187 312 187 312 183 305 188 313 188 313 184 306 189 314 189 314 185 307 190 315 182 304 186 311 164 316 183 305 187 312 182 304 184 306 188 313 183 305 185 307 189 314 184 306 175 286 169 317 191 318 191 318 186 311 192 319 192 319 187 312 193 320 193 320 188 313 194 321 194 321 189 314 195 322 195 322 190 315 196 323 186 311 191 318 169 324 187 312 192 319 186 311 188 313 193 320 187 312 189 314 194 321 188 313 190 315 195 322 189 314 176 325 106 326 107 327 178 328 176 329 197 330 197 330 107 331 109 332 107 333 197 330 176 334 181 335 178 336 198 337 198 337 197 330 199 338 199 338 109 339 112 340 197 330 198 337 178 341 109 342 199 338 197 330 185 343 181 344 200 345 200 345 198 337 201 346 201 346 199 338 202 347 202 347 112 348 116 349 198 337 200 345 181 350 199 338 201 346 198 337 112 351 202 347 199 338 190 352 185 353 203 354 203 354 200 345 204 355 204 355 201 346 205 356 205 356 202 347 206 357 206 357 116 358 121 359 200 345 203 354 185 360 201 346 204 355 200 345 202 347 205 356 201 346 116 361 206 357 202 347 196 323 190 362 207 363 207 363 203 354 208 364 208 364 204 355 209 365 209 365 205 356 210 366 210 366 206 357 211 367 211 367 121 368 127 369 203 354 207 363 190 370 204 355 208 364 203 354 205 356 209 365 204 355 206 357 210 366 205 356 121 371 211 367 206 357 26 26 27 27 212 372 25 25 26 26 213 373 213 373 212 372 214 374 212 372 213 373 26 26 24 24 25 25 215 375 215 375 213 373 216 376 216 376 214 374 217 377 213 373 215 375 25 25 214 374 216 376 213 373 23 23 24 24 218 378 218 378 215 375 219 379 219 379 216 376 220 380 220 380 217 377 221 381 215 375 218 378 24 24 216 376 219 379 215 375 217 377 220 380 216 376 22 22 23 23 222 382 222 382 218 378 223 383 223 383 219 379 224 384 224 384 220 380 225 385 225 385 221 381 226 386 218 378 222 382 23 23 219 379 223 383 218 378 220 380 224 384 219 379 221 381 225 385 220 380 21 21 22 22 227 387 227 387 222 382 228 388 228 388 223 383 229 389 229 389 224 384 230 390 230 390 225 385 231 391 231 391 226 386 127 207 222 382 227 387 22 22 223 383 228 388 222 382 224 384 229 389 223 383 225 385 230 390 224 384 226 386 231 391 225 385 48 62 21 21 232 392 47 61 48 62 233 393 233 393 232 392 234 394 232 392 233 393 48 62 46 60 47 61 235 395 235 395 233 393 236 396 236 396 234 394 237 397 233 393 235 395 47 61 234 394 236 396 233 393 45 59 46 60 238 398 238 398 235 395 239 399 239 399 236 396 240 400 240 400 237 397 241 401 235 395 238 398 46 60 236 396 239 399 235 395 237 397 240 400 236 396 44 58 45 59 242 402 242 402 238 398 243 403 243 403 239 399 244 404 244 404 240 400 245 405 245 405 241 401 246 406 238 398 242 402 45 59 239 399 243 403 238 398 240 400 244 404 239 399 241 401 245 405 240 400 43 57 44 58 247 407 247 407 242 402 248 408 248 408 243 403 249 409 249 409 244 404 250 410 250 410 245 405 251 411 251 411 246 406 133 213 242 402 247 407 44 58 243 403 248 408 242 402 244 404 249 409 243 403 245 405 250 410 244 404 246 406 251 411 245 405 69 99 43 57 252 412 68 98 69 99 253 413 253 413 252 412 254 414 252 412 253 413 69 99 67 97 68 98 255 415 255 415 253 413 256 416 256 416 254 414 257 417 253 413 255 415 68 98 254 414 256 416 253 413 66 96 67 97 258 418 258 418 255 415 259 419 259 419 256 416 260 420 260 420 257 417 261 421 255 415 258 418 67 97 256 416 259 419 255 415 257 417 260 420 256 416 65 95 66 96 262 422 262 422 258 418 263 423 263 423 259 419 264 424 264 424 260 420 265 425 265 425 261 421 266 426 258 418 262 422 66 96 259 419 263 423 258 418 260 420 264 424 259 419 261 421 265 425 260 420 64 94 65 95 267 427 267 427 262 422 268 428 268 428 263 423 269 429 269 429 264 424 270 430 270 430 265 425 271 431 271 431 266 426 154 249 262 422 267 427 65 95 263 423 268 428 262 422 264 424 269 429 263 423 265 425 270 430 264 424 266 426 271 431 265 425 90 136 64 94 272 432 89 135 90 136 273 433 273 433 272 432 274 434 272 432 273 433 90 136 88 134 89 135 275 435 275 435 273 433 276 436 276 436 274 434 277 437 273 433 275 435 89 135 274 434 276 436 273 433 87 133 88 134 278 438 278 438 275 435 279 439 279 439 276 436 280 440 280 440 277 437 281 441 275 435 278 438 88 134 276 436 279 439 275 435 277 437 280 440 276 436 86 132 87 133 282 442 282 442 278 438 283 443 283 443 279 439 284 444 284 444 280 440 285 445 285 445 281 441 286 446 278 438 282 442 87 133 279 439 283 443 278 438 280 440 284 444 279 439 281 441 285 445 280 440 85 131 86 132 287 447 287 447 282 442 288 448 288 448 283 443 289 449 289 449 284 444 290 450 290 450 285 445 291 451 291 451 286 446 175 286 282 442 287 447 86 132 283 443 288 448 282 442 284 444 289 449 283 443 285 445 290 450 284 444 286 446 291 451 285 445 105 182 85 131 292 452 104 181 105 182 293 453 293 453 292 452 294 454 292 452 293 453 105 182 103 180 104 181 295 455 295 455 293 453 296 456 296 456 294 454 297 457 293 453 295 455 104 181 294 454 296 456 293 453 102 179 103 180 298 458 298 458 295 455 299 459 299 459 296 456 300 460 300 460 297 457 301 461 295 455 298 458 103 180 296 456 299 459 295 455 297 457 300 460 296 456 101 178 102 179 302 462 302 462 298 458 303 463 303 463 299 459 304 464 304 464 300 460 305 465 305 465 301 461 306 466 298 458 302 462 102 179 299 459 303 463 298 458 300 460 304 464 299 459 301 461 305 465 300 460 27 467 101 178 307 468 307 468 302 462 308 469 308 469 303 463 309 470 309 470 304 464 310 471 310 471 305 465 311 472 311 472 306 466 196 323 302 462 307 468 101 178 303 463 308 469 302 462 304 464 309 470 303 463 305 465 310 471 304 464 306 466 311 472 305 465 132 212 133 213 246 406 131 211 132 212 312 473 312 473 246 406 241 401 246 406 312 473 132 212 130 210 131 211 313 474 313 474 312 473 314 475 314 475 241 401 237 397 312 473 313 474 131 211 241 401 314 475 312 473 129 209 130 210 315 476 315 476 313 474 316 477 316 477 314 475 317 478 317 478 237 397 234 394 313 474 315 476 130 210 314 475 316 477 313 474 237 397 317 478 314 475 128 208 129 209 318 479 318 479 315 476 319 480 319 480 316 477 320 481 320 481 317 478 321 482 321 482 234 394 232 392 315 476 318 479 129 209 316 477 319 480 315 476 317 478 320 481 316 477 234 394 321 482 317 478 127 207 128 208 231 391 231 391 318 479 230 390 230 390 319 480 229 389 229 389 320 481 228 388 228 388 321 482 227 387 227 387 232 392 21 21 318 479 231 391 128 208 319 480 230 390 318 479 320 481 229 389 319 480 321 482 228 388 320 481 232 392 227 387 321 482 153 248 154 249 266 426 152 247 153 248 322 483 322 483 266 426 261 421 266 426 322 483 153 248 151 246 152 247 323 484 323 484 322 483 324 485 324 485 261 421 257 417 322 483 323 484 152 247 261 421 324 485 322 483 150 245 151 246 325 486 325 486 323 484 326 487 326 487 324 485 327 488 327 488 257 417 254 414 323 484 325 486 151 246 324 485 326 487 323 484 257 417 327 488 324 485 149 244 150 245 328 489 328 489 325 486 329 490 329 490 326 487 330 491 330 491 327 488 331 492 331 492 254 414 252 412 325 486 328 489 150 245 326 487 329 490 325 486 327 488 330 491 326 487 254 414 331 492 327 488 133 213 149 244 251 411 251 411 328 489 250 410 250 410 329 490 249 409 249 409 330 491 248 408 248 408 331 492 247 407 247 407 252 412 43 57 328 489 251 411 149 244 329 490 250 410 328 489 330 491 249 409 329 490 331 492 248 408 330 491 252 412 247 407 331 492 174 285 175 286 286 446 173 284 174 285 332 493 332 493 286 446 281 441 286 446 332 493 174 285 172 283 173 284 333 494 333 494 332 493 334 495 334 495 281 441 277 437 332 493 333 494 173 284 281 441 334 495 332 493 171 282 172 283 335 496 335 496 333 494 336 497 336 497 334 495 337 498 337 498 277 437 274 434 333 494 335 496 172 283 334 495 336 497 333 494 277 437 337 498 334 495 170 281 171 282 338 499 338 499 335 496 339 500 339 500 336 497 340 501 340 501 337 498 341 502 341 502 274 434 272 432 335 496 338 499 171 282 336 497 339 500 335 496 337 498 340 501 336 497 274 434 341 502 337 498 154 249 170 281 271 431 271 431 338 499 270 430 270 430 339 500 269 429 269 429 340 501 268 428 268 428 341 502 267 427 267 427 272 432 64 94 338 499 271 431 170 281 339 500 270 430 338 499 340 501 269 429 339 500 341 502 268 428 340 501 272 432 267 427 341 502 195 322 196 323 306 466 194 321 195 322 342 503 342 503 306 466 301 461 306 466 342 503 195 322 193 320 194 321 343 504 343 504 342 503 344 505 344 505 301 461 297 457 342 503 343 504 194 321 301 461 344 505 342 503 192 319 193 320 345 506 345 506 343 504 346 507 346 507 344 505 347 508 347 508 297 457 294 454 343 504 345 506 193 320 344 505 346 507 343 504 297 457 347 508 344 505 191 318 192 319 348 509 348 509 345 506 349 510 349 510 346 507 350 511 350 511 347 508 351 512 351 512 294 454 292 452 345 506 348 509 192 319 346 507 349 510 345 506 347 508 350 511 346 507 294 454 351 512 347 508 175 286 191 318 291 451 291 451 348 509 290 450 290 450 349 510 289 449 289 449 350 511 288 448 288 448 351 512 287 447 287 447 292 452 85 131 348 509 291 451 191 318 349 510 290 450 348 509 350 511 289 449 349 510 351 512 288 448 350 511 292 452 287 447 351 512 211 367 127 513 226 514 210 366 211 367 352 515 352 515 226 516 221 517 226 518 352 515 211 367 209 365 210 366 353 519 353 519 352 515 354 520 354 520 221 521 217 522 352 515 353 519 210 366 221 523 354 520 352 515 208 364 209 365 355 524 355 524 353 519 356 525 356 525 354 520 357 526 357 526 217 527 214 528 353 519 355 524 209 365 354 520 356 525 353 519 217 529 357 526 354 520 207 363 208 364 358 530 358 530 355 524 359 531 359 531 356 525 360 532 360 532 357 526 361 533 361 533 214 534 212 535 355 524 358 530 208 364 356 525 359 531 355 524 357 526 360 532 356 525 214 536 361 533 357 526 196 323 207 363 311 472 311 472 358 530 310 471 310 471 359 531 309 470 309 470 360 532 308 469 308 469 361 533 307 468 307 468 212 537 27 538 358 530 311 472 207 363 359 531 310 471 358 530 360 532 309 470 359 531 361 533 308 469 360 532 212 539 307 468 361 533</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-high">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-low-doublesided.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-low-doublesided.dae
new file mode 100644
index 00000000..d9ca1c44
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-low-doublesided.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-low-doublesided.mb</source_data>
+ </contributor>
+ <created>2008-09-19T21:54:57Z</created>
+ <modified>2008-09-19T21:54:57Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="252">0 50 0 25 42.5325 8.12299 0 42.5325 26.2866 42.5325 22.3607 13.8197 25 26.2866 34.4095 0 22.3607 44.7214 15.4509 42.5325 -21.2663 26.2866 22.3607 -36.1803 40.4509 26.2866 -13.1433 -15.4509 42.5325 -21.2663 -26.2866 22.3607 -36.1803 0 26.2866 -42.5325 -25 42.5325 8.12299 -42.5325 22.3607 13.8197 -40.4509 26.2866 -13.1433 -25 26.2866 34.4095 0 -50 0 15.4509 -42.5325 21.2663 25 -42.5325 -8.12299 26.2866 -22.3607 36.1803 40.4509 -26.2866 13.1433 42.5325 -22.3607 -13.8197 0 -42.5325 -26.2866 25 -26.2866 -34.4095 0 -22.3607 -44.7214 -25 -42.5325 -8.12299 -25 -26.2866 -34.4095 -42.5325 -22.3607 -13.8197 -15.4509 -42.5325 21.2663 -40.4509 -26.2866 13.1433 -26.2866 -22.3607 36.1803 0 -26.2866 42.5325 15.4509 0 47.5528 40.4509 0 29.3893 50 0 0 40.4509 0 -29.3893 15.4509 0 -47.5528 -15.4509 0 -47.5528 -40.4509 0 -29.3893 -50 0 0 -40.4509 0 29.3893 -15.4509 0 47.5528 0 50 0 25 42.5325 8.12299 0 42.5325 26.2866 42.5325 22.3607 13.8197 25 26.2866 34.4095 0 22.3607 44.7214 15.4509 42.5325 -21.2663 26.2866 22.3607 -36.1803 40.4509 26.2866 -13.1433 -15.4509 42.5325 -21.2663 -26.2866 22.3607 -36.1803 0 26.2866 -42.5325 -25 42.5325 8.12299 -42.5325 22.3607 13.8197 -40.4509 26.2866 -13.1433 -25 26.2866 34.4095 0 -50 0 15.4509 -42.5325 21.2663 25 -42.5325 -8.12299 26.2866 -22.3607 36.1803 40.4509 -26.2866 13.1433 42.5325 -22.3607 -13.8197 0 -42.5325 -26.2866 25 -26.2866 -34.4095 0 -22.3607 -44.7214 -25 -42.5325 -8.12299 -25 -26.2866 -34.4095 -42.5325 -22.3607 -13.8197 -15.4509 -42.5325 21.2663 -40.4509 -26.2866 13.1433 -26.2866 -22.3607 36.1803 0 -26.2866 42.5325 15.4509 0 47.5528 40.4509 0 29.3893 50 0 0 40.4509 0 -29.3893 15.4509 0 -47.5528 -15.4509 0 -47.5528 -40.4509 0 -29.3893 -50 0 0 -40.4509 0 29.3893 -15.4509 0 47.5528</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="84" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="252">0 1 0 0.5 0.850651 0.16246 0 0.850651 0.525731 0.850651 0.447214 0.276393 0.5 0.525731 0.688191 0 0.447214 0.894427 0.309017 0.850651 -0.425325 0.525731 0.447214 -0.723607 0.809017 0.525731 -0.262866 -0.309017 0.850651 -0.425325 -0.525731 0.447214 -0.723607 0 0.525731 -0.850651 -0.5 0.850651 0.16246 -0.850651 0.447214 0.276393 -0.809017 0.525731 -0.262866 -0.5 0.525731 0.688191 0 -1 0 0.309017 -0.850651 0.425325 0.5 -0.850651 -0.16246 0.525731 -0.447214 0.723607 0.809017 -0.525731 0.262866 0.850651 -0.447214 -0.276393 0 -0.850651 -0.525731 0.5 -0.525731 -0.688191 0 -0.447214 -0.894427 -0.5 -0.850651 -0.16246 -0.5 -0.525731 -0.688191 -0.850651 -0.447214 -0.276393 -0.309017 -0.850651 0.425325 -0.809017 -0.525731 0.262866 -0.525731 -0.447214 0.723607 0 -0.525731 0.850651 0.309017 0 0.951057 0.809017 0 0.587785 1 0 0 0.809017 0 -0.587785 0.309017 0 -0.951057 -0.309017 0 -0.951057 -0.809017 0 -0.587785 -1 0 0 -0.809017 0 0.587785 -0.309017 0 0.951057 0 -1 0 -0.5 -0.850651 -0.16246 0 -0.850651 -0.525731 -0.850651 -0.447214 -0.276393 -0.5 -0.525731 -0.688191 0 -0.447214 -0.894427 -0.309017 -0.850651 0.425325 -0.525731 -0.447214 0.723607 -0.809017 -0.525731 0.262866 0.309017 -0.850651 0.425325 0.525731 -0.447214 0.723607 0 -0.525731 0.850651 0.5 -0.850651 -0.16246 0.850651 -0.447214 -0.276393 0.809017 -0.525731 0.262866 0.5 -0.525731 -0.688191 0 1 0 -0.309017 0.850651 -0.425325 -0.5 0.850651 0.16246 -0.525731 0.447214 -0.723607 -0.809017 0.525731 -0.262866 -0.850651 0.447214 0.276393 0 0.850651 0.525731 -0.5 0.525731 0.688191 0 0.447214 0.894427 0.5 0.850651 0.16246 0.5 0.525731 0.688191 0.850651 0.447214 0.276393 0.309017 0.850651 -0.425325 0.809017 0.525731 -0.262866 0.525731 0.447214 -0.723607 0 0.525731 -0.850651 -0.309017 0 -0.951057 -0.809017 0 -0.587785 -1 0 0 -0.809017 0 0.587785 -0.309017 0 0.951057 0.309017 0 0.951057 0.809017 0 0.587785 1 0 0 0.809017 0 -0.587785 0.309017 0 -0.951057</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="84" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="268">0.136364 0.833333 0.045454 0.833333 0.090909 1 0.181818 0.666667 0.090909 0.666667 0 0.666667 0.318182 0.833333 0.227273 0.833333 0.272727 1 0.363636 0.666667 0.272727 0.666667 0.227273 0.833333 0.227273 0.833333 0.5 0.833333 0.409091 0.833333 0.454545 1 0.545455 0.666667 0.454545 0.666667 0.409091 0.833333 0.409091 0.833333 0.681818 0.833333 0.590909 0.833333 0.636364 1 0.727273 0.666667 0.636364 0.666667 0.590909 0.833333 0.590909 0.833333 0.863636 0.833333 0.772727 0.833333 0.818182 1 0.909091 0.666667 0.818182 0.666667 0.863636 0.833333 0.772727 0.833333 0.772727 0.833333 0.863636 0.833333 0.136364 0.166667 0.227273 0.166667 0.181818 0 0.090909 0.333333 0.181818 0.333333 0.272727 0.333333 0.318182 0.166667 0.409091 0.166667 0.363636 0 0.363636 0.333333 0.318182 0.166667 0.454545 0.333333 0.318182 0.166667 0.5 0.166667 0.590909 0.166667 0.545455 0 0.545455 0.333333 0.5 0.166667 0.636364 0.333333 0.5 0.166667 0.681818 0.166667 0.772727 0.166667 0.727273 0 0.727273 0.333333 0.681818 0.166667 0.818182 0.333333 0.681818 0.166667 0.863636 0.166667 0.954545 0.166667 0.909091 0 0.909091 0.333333 0.863636 0.166667 1 0.333333 0.954545 0.166667 0.954545 0.166667 0.863636 0.166667 0.045454 0.5 0.136364 0.5 0.227273 0.5 0.318182 0.5 0.409091 0.5 0.5 0.5 0.590909 0.5 0.681818 0.5 0.772727 0.5 0.909091 0.666667 0.863636 0.5 0.954545 0.5 1 0.333333 0.909091 0.666667 0.954545 0.5 0.954545 0.5 0.272727 1 0.227273 0.833333 0.227273 0.833333 0.227273 0.833333 0.454545 1 0.409091 0.833333 0.409091 0.833333 0.409091 0.833333 0.636364 1 0.590909 0.833333 0.590909 0.833333 0.590909 0.833333 0.863636 0.833333 0.818182 1 0.772727 0.833333 0.909091 0.666667 0.863636 0.833333 0.772727 0.833333 0.772727 0.833333 0.863636 0.833333 0.318182 0.166667 0.363636 0 0.318182 0.166667 0.318182 0.166667 0.5 0.166667 0.545455 0 0.5 0.166667 0.5 0.166667 0.681818 0.166667 0.727273 0 0.681818 0.166667 0.681818 0.166667 0.863636 0.166667 0.909091 0 0.954545 0.166667 0.863636 0.166667 0.954545 0.166667 1 0.333333 0.954545 0.166667 0.863636 0.166667 0.909091 0.666667 1 0.333333 0.954545 0.5 0.954545 0.5 0.909091 0.666667 0.954545 0.5</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="134" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="160">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>43 0 44 1 42 2 45 3 46 4 43 0 46 4 47 5 44 1 44 1 43 0 46 4 48 6 43 7 42 8 49 9 50 10 48 6 50 10 45 3 43 11 43 12 48 6 50 10 51 13 48 14 42 15 52 16 53 17 51 13 53 17 49 9 48 18 48 19 51 13 53 17 54 20 51 21 42 22 55 23 56 24 54 20 56 24 52 16 51 25 51 26 54 20 56 24 44 27 54 28 42 29 47 30 57 31 44 32 57 31 55 23 54 33 54 34 44 35 57 31 59 36 60 37 58 38 61 39 62 40 59 36 62 40 63 41 60 37 60 37 59 36 62 40 60 42 64 43 58 44 63 41 65 45 60 46 65 45 66 47 64 43 64 43 60 48 65 45 64 49 67 50 58 51 66 47 68 52 64 53 68 52 69 54 67 50 67 50 64 55 68 52 67 56 70 57 58 58 69 54 71 59 67 60 71 59 72 61 70 57 70 57 67 62 71 59 70 63 59 64 58 65 72 61 73 66 70 67 73 66 61 68 59 69 59 70 70 71 73 66 46 4 74 72 47 5 45 3 75 73 46 4 75 73 61 39 74 72 74 72 46 4 75 73 50 10 76 74 45 3 49 9 77 75 50 10 77 75 63 41 76 74 76 74 50 10 77 75 53 17 78 76 49 9 52 16 79 77 53 17 79 77 66 47 78 76 78 76 53 17 79 77 56 24 80 78 52 16 55 23 81 79 56 24 81 79 69 54 80 78 80 78 56 24 81 79 57 31 82 80 55 23 47 81 83 82 57 31 83 82 72 61 82 80 82 80 57 31 83 82 62 40 76 74 63 41 61 39 75 73 62 40 75 73 45 3 76 74 76 74 62 40 75 73 65 45 78 76 66 47 63 41 77 75 65 45 77 75 49 9 78 76 78 76 65 45 77 75 68 52 80 78 69 54 66 47 79 77 68 52 79 77 52 16 80 78 80 78 68 52 79 77 71 59 82 80 72 61 69 54 81 79 71 59 81 79 55 23 82 80 82 80 71 59 81 79 73 66 74 83 61 84 72 61 83 82 73 66 83 82 47 85 74 86 74 87 73 66 83 82 1 0 0 2 2 1 3 3 1 0 4 4 4 4 2 1 5 5 2 1 4 4 1 0 6 6 0 88 1 89 7 9 6 6 8 10 8 10 1 90 3 3 1 91 8 10 6 6 9 13 0 92 6 93 10 16 9 13 11 17 11 17 6 94 7 9 6 95 11 17 9 13 12 20 0 96 9 97 13 23 12 20 14 24 14 24 9 98 10 16 9 99 14 24 12 20 2 100 0 101 12 102 5 103 2 104 15 31 15 31 12 105 13 23 12 106 15 31 2 107 17 36 16 38 18 37 19 39 17 36 20 40 20 40 18 37 21 41 18 37 20 40 17 36 18 108 16 109 22 43 21 41 18 110 23 45 23 45 22 43 24 47 22 43 23 45 18 111 22 112 16 113 25 50 24 47 22 114 26 52 26 52 25 50 27 54 25 50 26 52 22 115 25 116 16 117 28 57 27 54 25 118 29 59 29 59 28 57 30 61 28 57 29 59 25 119 28 120 16 121 17 122 30 61 28 123 31 66 31 66 17 124 19 125 17 126 31 66 28 127 4 4 5 5 32 72 3 3 4 4 33 73 33 73 32 72 19 39 32 72 33 73 4 4 8 10 3 3 34 74 7 9 8 10 35 75 35 75 34 74 21 41 34 74 35 75 8 10 11 17 7 9 36 76 10 16 11 17 37 77 37 77 36 76 24 47 36 76 37 77 11 17 14 24 10 16 38 78 13 23 14 24 39 79 39 79 38 78 27 54 38 78 39 79 14 24 15 31 13 23 40 80 5 128 15 31 41 82 41 82 40 80 30 61 40 80 41 82 15 31 20 40 21 41 34 74 19 39 20 40 33 73 33 73 34 74 3 3 34 74 33 73 20 40 23 45 24 47 36 76 21 41 23 45 35 75 35 75 36 76 7 9 36 76 35 75 23 45 26 52 27 54 38 78 24 47 26 52 37 77 37 77 38 78 10 16 38 78 37 77 26 52 29 59 30 61 40 80 27 54 29 59 39 79 39 79 40 80 13 23 40 80 39 79 29 59 31 66 19 129 32 130 30 61 31 66 41 82 41 82 32 131 5 132 32 133 41 82 31 66</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-low-doublesided">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-low-inverted.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-low-inverted.dae
new file mode 100644
index 00000000..68da7620
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-low-inverted.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-low-inverted.mb</source_data>
+ </contributor>
+ <created>2008-09-19T21:52:39Z</created>
+ <modified>2008-09-19T21:52:39Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="126">0 50 0 25 42.5325 8.12299 0 42.5325 26.2866 42.5325 22.3607 13.8197 25 26.2866 34.4095 0 22.3607 44.7214 15.4509 42.5325 -21.2663 26.2866 22.3607 -36.1803 40.4509 26.2866 -13.1433 -15.4509 42.5325 -21.2663 -26.2866 22.3607 -36.1803 0 26.2866 -42.5325 -25 42.5325 8.12299 -42.5325 22.3607 13.8197 -40.4509 26.2866 -13.1433 -25 26.2866 34.4095 0 -50 0 15.4509 -42.5325 21.2663 25 -42.5325 -8.12299 26.2866 -22.3607 36.1803 40.4509 -26.2866 13.1433 42.5325 -22.3607 -13.8197 0 -42.5325 -26.2866 25 -26.2866 -34.4095 0 -22.3607 -44.7214 -25 -42.5325 -8.12299 -25 -26.2866 -34.4095 -42.5325 -22.3607 -13.8197 -15.4509 -42.5325 21.2663 -40.4509 -26.2866 13.1433 -26.2866 -22.3607 36.1803 0 -26.2866 42.5325 15.4509 0 47.5528 40.4509 0 29.3893 50 0 0 40.4509 0 -29.3893 15.4509 0 -47.5528 -15.4509 0 -47.5528 -40.4509 0 -29.3893 -50 0 0 -40.4509 0 29.3893 -15.4509 0 47.5528</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="42" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="126">0 -1 0 -0.5 -0.850651 -0.16246 0 -0.850651 -0.525731 -0.850651 -0.447214 -0.276393 -0.5 -0.525731 -0.688191 0 -0.447214 -0.894427 -0.309017 -0.850651 0.425325 -0.525731 -0.447214 0.723607 -0.809017 -0.525731 0.262866 0.309017 -0.850651 0.425325 0.525731 -0.447214 0.723607 0 -0.525731 0.850651 0.5 -0.850651 -0.16246 0.850651 -0.447214 -0.276393 0.809017 -0.525731 0.262866 0.5 -0.525731 -0.688191 0 1 0 -0.309017 0.850651 -0.425325 -0.5 0.850651 0.16246 -0.525731 0.447214 -0.723607 -0.809017 0.525731 -0.262866 -0.850651 0.447214 0.276393 0 0.850651 0.525731 -0.5 0.525731 0.688191 0 0.447214 0.894427 0.5 0.850651 0.16246 0.5 0.525731 0.688191 0.850651 0.447214 0.276393 0.309017 0.850651 -0.425325 0.809017 0.525731 -0.262866 0.525731 0.447214 -0.723607 0 0.525731 -0.850651 -0.309017 0 -0.951057 -0.809017 0 -0.587785 -1 0 0 -0.809017 0 0.587785 -0.309017 0 0.951057 0.309017 0 0.951057 0.809017 0 0.587785 1 0 0 0.809017 0 -0.587785 0.309017 0 -0.951057</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="42" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="176">0.136364 0.833333 0.045454 0.833333 0.090909 1 0.181818 0.666667 0.090909 0.666667 0 0.666667 0.318182 0.833333 0.227273 0.833333 0.272727 1 0.363636 0.666667 0.272727 0.666667 0.227273 0.833333 0.227273 0.833333 0.5 0.833333 0.409091 0.833333 0.454545 1 0.545455 0.666667 0.454545 0.666667 0.409091 0.833333 0.409091 0.833333 0.681818 0.833333 0.590909 0.833333 0.636364 1 0.727273 0.666667 0.636364 0.666667 0.590909 0.833333 0.590909 0.833333 0.863636 0.833333 0.772727 0.833333 0.818182 1 0.909091 0.666667 0.818182 0.666667 0.863636 0.833333 0.772727 0.833333 0.772727 0.833333 0.863636 0.833333 0.136364 0.166667 0.227273 0.166667 0.181818 0 0.090909 0.333333 0.181818 0.333333 0.272727 0.333333 0.318182 0.166667 0.409091 0.166667 0.363636 0 0.363636 0.333333 0.318182 0.166667 0.454545 0.333333 0.318182 0.166667 0.5 0.166667 0.590909 0.166667 0.545455 0 0.545455 0.333333 0.5 0.166667 0.636364 0.333333 0.5 0.166667 0.681818 0.166667 0.772727 0.166667 0.727273 0 0.727273 0.333333 0.681818 0.166667 0.818182 0.333333 0.681818 0.166667 0.863636 0.166667 0.954545 0.166667 0.909091 0 0.909091 0.333333 0.863636 0.166667 1 0.333333 0.954545 0.166667 0.954545 0.166667 0.863636 0.166667 0.045454 0.5 0.136364 0.5 0.227273 0.5 0.318182 0.5 0.409091 0.5 0.5 0.5 0.590909 0.5 0.681818 0.5 0.772727 0.5 0.909091 0.666667 0.863636 0.5 0.954545 0.5 1 0.333333 0.909091 0.666667 0.954545 0.5 0.954545 0.5</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="88" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="80">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 2 1 0 2 3 3 4 4 1 0 4 4 5 5 2 1 2 1 1 0 4 4 6 6 1 7 0 8 7 9 8 10 6 6 8 10 3 3 1 11 1 12 6 6 8 10 9 13 6 14 0 15 10 16 11 17 9 13 11 17 7 9 6 18 6 19 9 13 11 17 12 20 9 21 0 22 13 23 14 24 12 20 14 24 10 16 9 25 9 26 12 20 14 24 2 27 12 28 0 29 5 30 15 31 2 32 15 31 13 23 12 33 12 34 2 35 15 31 17 36 18 37 16 38 19 39 20 40 17 36 20 40 21 41 18 37 18 37 17 36 20 40 18 42 22 43 16 44 21 41 23 45 18 46 23 45 24 47 22 43 22 43 18 48 23 45 22 49 25 50 16 51 24 47 26 52 22 53 26 52 27 54 25 50 25 50 22 55 26 52 25 56 28 57 16 58 27 54 29 59 25 60 29 59 30 61 28 57 28 57 25 62 29 59 28 63 17 64 16 65 30 61 31 66 28 67 31 66 19 68 17 69 17 70 28 71 31 66 4 4 32 72 5 5 3 3 33 73 4 4 33 73 19 39 32 72 32 72 4 4 33 73 8 10 34 74 3 3 7 9 35 75 8 10 35 75 21 41 34 74 34 74 8 10 35 75 11 17 36 76 7 9 10 16 37 77 11 17 37 77 24 47 36 76 36 76 11 17 37 77 14 24 38 78 10 16 13 23 39 79 14 24 39 79 27 54 38 78 38 78 14 24 39 79 15 31 40 80 13 23 5 81 41 82 15 31 41 82 30 61 40 80 40 80 15 31 41 82 20 40 34 74 21 41 19 39 33 73 20 40 33 73 3 3 34 74 34 74 20 40 33 73 23 45 36 76 24 47 21 41 35 75 23 45 35 75 7 9 36 76 36 76 23 45 35 75 26 52 38 78 27 54 24 47 37 77 26 52 37 77 10 16 38 78 38 78 26 52 37 77 29 59 40 80 30 61 27 54 39 79 29 59 39 79 13 23 40 80 40 80 29 59 39 79 31 66 32 83 19 84 30 61 41 82 31 66 41 82 5 85 32 86 32 87 31 66 41 82</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-low-inverted">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-low.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-low.dae
new file mode 100644
index 00000000..2dc7d56e
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-low.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T21:48:50Z</created>
+ <modified>2008-09-19T21:48:50Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="126">0 50 0 25 42.5325 8.12299 0 42.5325 26.2866 42.5325 22.3607 13.8197 25 26.2866 34.4095 0 22.3607 44.7214 15.4509 42.5325 -21.2663 26.2866 22.3607 -36.1803 40.4509 26.2866 -13.1433 -15.4509 42.5325 -21.2663 -26.2866 22.3607 -36.1803 0 26.2866 -42.5325 -25 42.5325 8.12299 -42.5325 22.3607 13.8197 -40.4509 26.2866 -13.1433 -25 26.2866 34.4095 0 -50 0 15.4509 -42.5325 21.2663 25 -42.5325 -8.12299 26.2866 -22.3607 36.1803 40.4509 -26.2866 13.1433 42.5325 -22.3607 -13.8197 0 -42.5325 -26.2866 25 -26.2866 -34.4095 0 -22.3607 -44.7214 -25 -42.5325 -8.12299 -25 -26.2866 -34.4095 -42.5325 -22.3607 -13.8197 -15.4509 -42.5325 21.2663 -40.4509 -26.2866 13.1433 -26.2866 -22.3607 36.1803 0 -26.2866 42.5325 15.4509 0 47.5528 40.4509 0 29.3893 50 0 0 40.4509 0 -29.3893 15.4509 0 -47.5528 -15.4509 0 -47.5528 -40.4509 0 -29.3893 -50 0 0 -40.4509 0 29.3893 -15.4509 0 47.5528</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="42" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="126">0 1 0 0.5 0.850651 0.16246 0 0.850651 0.525731 0.850651 0.447214 0.276393 0.5 0.525731 0.688191 0 0.447214 0.894427 0.309017 0.850651 -0.425325 0.525731 0.447214 -0.723607 0.809017 0.525731 -0.262866 -0.309017 0.850651 -0.425325 -0.525731 0.447214 -0.723607 0 0.525731 -0.850651 -0.5 0.850651 0.16246 -0.850651 0.447214 0.276393 -0.809017 0.525731 -0.262866 -0.5 0.525731 0.688191 0 -1 0 0.309017 -0.850651 0.425325 0.5 -0.850651 -0.16246 0.525731 -0.447214 0.723607 0.809017 -0.525731 0.262866 0.850651 -0.447214 -0.276393 0 -0.850651 -0.525731 0.5 -0.525731 -0.688191 0 -0.447214 -0.894427 -0.5 -0.850651 -0.16246 -0.5 -0.525731 -0.688191 -0.850651 -0.447214 -0.276393 -0.309017 -0.850651 0.425325 -0.809017 -0.525731 0.262866 -0.525731 -0.447214 0.723607 0 -0.525731 0.850651 0.309017 0 0.951057 0.809017 0 0.587785 1 0 0 0.809017 0 -0.587785 0.309017 0 -0.951057 -0.309017 0 -0.951057 -0.809017 0 -0.587785 -1 0 0 -0.809017 0 0.587785 -0.309017 0 0.951057</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="42" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="176">0.136364 0.833333 0.090909 1 0.045454 0.833333 0.181818 0.666667 0.090909 0.666667 0 0.666667 0.318182 0.833333 0.272727 1 0.227273 0.833333 0.363636 0.666667 0.272727 0.666667 0.227273 0.833333 0.227273 0.833333 0.5 0.833333 0.454545 1 0.409091 0.833333 0.545455 0.666667 0.454545 0.666667 0.409091 0.833333 0.409091 0.833333 0.681818 0.833333 0.636364 1 0.590909 0.833333 0.727273 0.666667 0.636364 0.666667 0.590909 0.833333 0.590909 0.833333 0.863636 0.833333 0.818182 1 0.772727 0.833333 0.909091 0.666667 0.863636 0.833333 0.818182 0.666667 0.772727 0.833333 0.772727 0.833333 0.863636 0.833333 0.136364 0.166667 0.181818 0 0.227273 0.166667 0.090909 0.333333 0.181818 0.333333 0.272727 0.333333 0.318182 0.166667 0.363636 0 0.409091 0.166667 0.318182 0.166667 0.363636 0.333333 0.454545 0.333333 0.318182 0.166667 0.5 0.166667 0.545455 0 0.590909 0.166667 0.5 0.166667 0.545455 0.333333 0.636364 0.333333 0.5 0.166667 0.681818 0.166667 0.727273 0 0.772727 0.166667 0.681818 0.166667 0.727273 0.333333 0.818182 0.333333 0.681818 0.166667 0.863636 0.166667 0.909091 0 0.954545 0.166667 0.863636 0.166667 0.909091 0.333333 0.954545 0.166667 1 0.333333 0.954545 0.166667 0.863636 0.166667 0.045454 0.5 0.136364 0.5 0.227273 0.5 0.318182 0.5 0.409091 0.5 0.5 0.5 0.590909 0.5 0.681818 0.5 0.772727 0.5 0.909091 0.666667 0.863636 0.5 1 0.333333 0.954545 0.5 0.954545 0.5 0.909091 0.666667 0.954545 0.5</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="88" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="80">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 0 1 2 2 3 3 1 0 4 4 4 4 2 2 5 5 2 2 4 4 1 0 6 6 0 7 1 8 7 9 6 6 8 10 8 10 1 11 3 3 1 12 8 10 6 6 9 13 0 14 6 15 10 16 9 13 11 17 11 17 6 18 7 9 6 19 11 17 9 13 12 20 0 21 9 22 13 23 12 20 14 24 14 24 9 25 10 16 9 26 14 24 12 20 2 27 0 28 12 29 5 30 2 31 15 32 15 32 12 33 13 23 12 34 15 32 2 35 17 36 16 37 18 38 19 39 17 36 20 40 20 40 18 38 21 41 18 38 20 40 17 36 18 42 16 43 22 44 21 41 18 45 23 46 23 46 22 44 24 47 22 44 23 46 18 48 22 49 16 50 25 51 24 47 22 52 26 53 26 53 25 51 27 54 25 51 26 53 22 55 25 56 16 57 28 58 27 54 25 59 29 60 29 60 28 58 30 61 28 58 29 60 25 62 28 63 16 64 17 65 30 61 28 66 31 67 31 67 17 68 19 69 17 70 31 67 28 71 4 4 5 5 32 72 3 3 4 4 33 73 33 73 32 72 19 39 32 72 33 73 4 4 8 10 3 3 34 74 7 9 8 10 35 75 35 75 34 74 21 41 34 74 35 75 8 10 11 17 7 9 36 76 10 16 11 17 37 77 37 77 36 76 24 47 36 76 37 77 11 17 14 24 10 16 38 78 13 23 14 24 39 79 39 79 38 78 27 54 38 78 39 79 14 24 15 32 13 23 40 80 5 81 15 32 41 82 41 82 40 80 30 61 40 80 41 82 15 32 20 40 21 41 34 74 19 39 20 40 33 73 33 73 34 74 3 3 34 74 33 73 20 40 23 46 24 47 36 76 21 41 23 46 35 75 35 75 36 76 7 9 36 76 35 75 23 46 26 53 27 54 38 78 24 47 26 53 37 77 37 77 38 78 10 16 38 78 37 77 26 53 29 60 30 61 40 80 27 54 29 60 39 79 39 79 40 80 13 23 40 80 39 79 29 60 31 67 19 83 32 84 30 61 31 67 41 82 41 82 32 85 5 86 32 87 41 82 31 67</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-doublesided.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-doublesided.dae
new file mode 100644
index 00000000..bc6374e0
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-doublesided.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-medium-doublesided.mb</source_data>
+ </contributor>
+ <created>2008-09-19T22:02:13Z</created>
+ <modified>2008-09-19T22:02:13Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="552">0 50 0 17.1537 46.6335 5.57358 0 46.6335 18.0365 31.9975 36.9875 10.3966 17.8411 39.7327 24.5562 0 36.9875 33.6441 42.5325 22.3607 13.8197 31.9975 25.8403 28.4331 17.1537 25.8403 39.2177 0 22.3607 44.7214 10.6016 46.6335 -14.5918 19.7755 36.9875 -27.2187 28.8675 39.7327 -9.37962 26.2866 22.3607 -36.1803 36.9292 25.8403 -21.6451 42.599 25.8403 -4.19521 -10.6016 46.6335 -14.5918 -19.7755 36.9875 -27.2187 0 39.7327 -30.3531 -26.2866 22.3607 -36.1803 -9.17395 25.8403 -41.8105 9.17395 25.8403 -41.8105 -17.1537 46.6335 5.57358 -31.9975 36.9875 10.3966 -28.8675 39.7327 -9.37962 -42.5325 22.3607 13.8197 -42.599 25.8403 -4.19521 -36.9292 25.8403 -21.6451 -17.8411 39.7327 24.5562 -17.1537 25.8403 39.2177 -31.9975 25.8403 28.4331 0 -50 0 10.6016 -46.6335 14.5918 17.1537 -46.6335 -5.57358 19.7755 -36.9875 27.2187 28.8675 -39.7327 9.37962 31.9975 -36.9875 -10.3966 26.2866 -22.3607 36.1803 36.9292 -25.8403 21.6451 42.599 -25.8403 4.19521 42.5325 -22.3607 -13.8197 0 -46.6335 -18.0365 17.8411 -39.7327 -24.5562 0 -36.9875 -33.6441 31.9975 -25.8403 -28.4331 17.1537 -25.8403 -39.2177 0 -22.3607 -44.7214 -17.1537 -46.6335 -5.57358 -17.8411 -39.7327 -24.5562 -31.9975 -36.9875 -10.3966 -17.1537 -25.8403 -39.2177 -31.9975 -25.8403 -28.4331 -42.5325 -22.3607 -13.8197 -10.6016 -46.6335 14.5918 -28.8675 -39.7327 9.37962 -19.7755 -36.9875 27.2187 -42.599 -25.8403 4.19521 -36.9292 -25.8403 21.6451 -26.2866 -22.3607 36.1803 0 -39.7327 30.3531 -9.17395 -25.8403 41.8105 9.17395 -25.8403 41.8105 10.6016 7.80382 48.236 28.8675 9.37962 39.7327 19.7755 -7.80382 45.2552 42.599 7.80382 24.9884 36.9292 -7.80382 32.7923 49.1512 7.80382 4.82303 46.7086 9.37962 -15.1765 49.1512 -7.80382 -4.82303 36.9292 7.80382 -32.7923 42.599 -7.80382 -24.9884 19.7755 7.80382 -45.2552 0 9.37962 -49.1123 10.6016 -7.80382 -48.236 -19.7755 7.80382 -45.2552 -10.6016 -7.80382 -48.236 -36.9292 7.80382 -32.7923 -46.7086 9.37962 -15.1765 -42.599 -7.80382 -24.9884 -49.1512 7.80382 4.82303 -49.1512 -7.80382 -4.82303 -42.599 7.80382 24.9884 -28.8675 9.37962 39.7327 -36.9292 -7.80382 32.7923 -10.6016 7.80382 48.236 -19.7755 -7.80382 45.2552 46.7086 -9.37962 15.1765 28.8675 -9.37962 -39.7327 -28.8675 -9.37962 -39.7327 -46.7086 -9.37962 15.1765 0 -9.37962 49.1123 0 50 0 17.1537 46.6335 5.57358 0 46.6335 18.0365 31.9975 36.9875 10.3966 17.8411 39.7327 24.5562 0 36.9875 33.6441 42.5325 22.3607 13.8197 31.9975 25.8403 28.4331 17.1537 25.8403 39.2177 0 22.3607 44.7214 10.6016 46.6335 -14.5918 19.7755 36.9875 -27.2187 28.8675 39.7327 -9.37962 26.2866 22.3607 -36.1803 36.9292 25.8403 -21.6451 42.599 25.8403 -4.19521 -10.6016 46.6335 -14.5918 -19.7755 36.9875 -27.2187 0 39.7327 -30.3531 -26.2866 22.3607 -36.1803 -9.17395 25.8403 -41.8105 9.17395 25.8403 -41.8105 -17.1537 46.6335 5.57358 -31.9975 36.9875 10.3966 -28.8675 39.7327 -9.37962 -42.5325 22.3607 13.8197 -42.599 25.8403 -4.19521 -36.9292 25.8403 -21.6451 -17.8411 39.7327 24.5562 -17.1537 25.8403 39.2177 -31.9975 25.8403 28.4331 0 -50 0 10.6016 -46.6335 14.5918 17.1537 -46.6335 -5.57358 19.7755 -36.9875 27.2187 28.8675 -39.7327 9.37962 31.9975 -36.9875 -10.3966 26.2866 -22.3607 36.1803 36.9292 -25.8403 21.6451 42.599 -25.8403 4.19521 42.5325 -22.3607 -13.8197 0 -46.6335 -18.0365 17.8411 -39.7327 -24.5562 0 -36.9875 -33.6441 31.9975 -25.8403 -28.4331 17.1537 -25.8403 -39.2177 0 -22.3607 -44.7214 -17.1537 -46.6335 -5.57358 -17.8411 -39.7327 -24.5562 -31.9975 -36.9875 -10.3966 -17.1537 -25.8403 -39.2177 -31.9975 -25.8403 -28.4331 -42.5325 -22.3607 -13.8197 -10.6016 -46.6335 14.5918 -28.8675 -39.7327 9.37962 -19.7755 -36.9875 27.2187 -42.599 -25.8403 4.19521 -36.9292 -25.8403 21.6451 -26.2866 -22.3607 36.1803 0 -39.7327 30.3531 -9.17395 -25.8403 41.8105 9.17395 -25.8403 41.8105 10.6016 7.80382 48.236 28.8675 9.37962 39.7327 19.7755 -7.80382 45.2552 42.599 7.80382 24.9884 36.9292 -7.80382 32.7923 49.1512 7.80382 4.82303 46.7086 9.37962 -15.1765 49.1512 -7.80382 -4.82303 36.9292 7.80382 -32.7923 42.599 -7.80382 -24.9884 19.7755 7.80382 -45.2552 0 9.37962 -49.1123 10.6016 -7.80382 -48.236 -19.7755 7.80382 -45.2552 -10.6016 -7.80382 -48.236 -36.9292 7.80382 -32.7923 -46.7086 9.37962 -15.1765 -42.599 -7.80382 -24.9884 -49.1512 7.80382 4.82303 -49.1512 -7.80382 -4.82303 -42.599 7.80382 24.9884 -28.8675 9.37962 39.7327 -36.9292 -7.80382 32.7923 -10.6016 7.80382 48.236 -19.7755 -7.80382 45.2552 46.7086 -9.37962 15.1765 28.8675 -9.37962 -39.7327 -28.8675 -9.37962 -39.7327 -46.7086 -9.37962 15.1765 0 -9.37962 49.1123</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="184" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="552">0 1 0 0.334582 0.936075 0.108712 0 0.936075 0.351801 0.646643 0.733285 0.210107 0.356822 0.794655 0.491123 0 0.733285 0.679921 0.850651 0.447214 0.276393 0.646644 0.515861 0.561907 0.334582 0.515861 0.788633 0 0.447213 0.894427 0.206783 0.936075 -0.284613 0.399648 0.733285 -0.550068 0.57735 0.794654 -0.187592 0.525731 0.447214 -0.723607 0.73423 0.515861 -0.441355 0.853426 0.515861 -0.074505 -0.206783 0.936075 -0.284613 -0.399648 0.733285 -0.550068 0 0.794654 -0.607062 -0.525731 0.447214 -0.723607 -0.192864 0.515861 -0.83468 0.192864 0.515861 -0.83468 -0.334582 0.936075 0.108712 -0.646643 0.733285 0.210107 -0.57735 0.794654 -0.187592 -0.850651 0.447214 0.276393 -0.853426 0.515861 -0.074505 -0.73423 0.515861 -0.441355 -0.356822 0.794654 0.491123 -0.334582 0.515861 0.788633 -0.646644 0.515861 0.561907 0 -1 0 0.206783 -0.936075 0.284613 0.334582 -0.936075 -0.108712 0.399648 -0.733285 0.550068 0.57735 -0.794654 0.187592 0.646643 -0.733285 -0.210107 0.525731 -0.447214 0.723607 0.73423 -0.515861 0.441355 0.853426 -0.515861 0.074505 0.850651 -0.447214 -0.276393 0 -0.936075 -0.351801 0.356822 -0.794655 -0.491123 0 -0.733285 -0.679921 0.646644 -0.515861 -0.561907 0.334582 -0.515861 -0.788633 0 -0.447213 -0.894427 -0.334582 -0.936075 -0.108712 -0.356822 -0.794654 -0.491123 -0.646643 -0.733285 -0.210107 -0.334582 -0.515861 -0.788633 -0.646644 -0.515861 -0.561907 -0.850651 -0.447214 -0.276393 -0.206783 -0.936075 0.284613 -0.57735 -0.794654 0.187592 -0.399648 -0.733285 0.550068 -0.853426 -0.515861 0.074505 -0.73423 -0.515861 0.441355 -0.525731 -0.447214 0.723607 0 -0.794654 0.607062 -0.192864 -0.515861 0.83468 0.192864 -0.515861 0.83468 0.206783 0.16406 0.964534 0.57735 0.187592 0.794654 0.399647 -0.16406 0.901868 0.853426 0.16406 0.49472 0.73423 -0.16406 0.65878 0.981225 0.16406 0.101395 0.934172 0.187593 -0.303531 0.981225 -0.16406 -0.101395 0.73423 0.16406 -0.65878 0.853426 -0.16406 -0.49472 0.399647 0.16406 -0.901868 0 0.187592 -0.982247 0.206783 -0.16406 -0.964534 -0.399647 0.16406 -0.901868 -0.206783 -0.16406 -0.964534 -0.73423 0.16406 -0.65878 -0.934172 0.187593 -0.303531 -0.853426 -0.16406 -0.49472 -0.981225 0.16406 0.101395 -0.981225 -0.16406 -0.101395 -0.853426 0.16406 0.49472 -0.57735 0.187592 0.794654 -0.73423 -0.16406 0.65878 -0.206783 0.16406 0.964534 -0.399647 -0.16406 0.901868 0.934172 -0.187593 0.303531 0.57735 -0.187592 -0.794654 -0.57735 -0.187592 -0.794654 -0.934172 -0.187593 0.303531 0 -0.187592 0.982247 0 -1 -0.000000 -0.334582 -0.936075 -0.108712 0 -0.936075 -0.3518 -0.646643 -0.733285 -0.210107 -0.356822 -0.794655 -0.491123 0 -0.733285 -0.679921 -0.850651 -0.447214 -0.276393 -0.646644 -0.515861 -0.561907 -0.334582 -0.515861 -0.788633 0 -0.447213 -0.894427 -0.206783 -0.936075 0.284613 -0.399648 -0.733285 0.550068 -0.57735 -0.794654 0.187592 -0.525731 -0.447214 0.723607 -0.73423 -0.515861 0.441355 -0.853426 -0.515861 0.074505 0.206783 -0.936075 0.284613 0.399648 -0.733285 0.550068 0 -0.794654 0.607062 0.525731 -0.447214 0.723607 0.192864 -0.515861 0.83468 -0.192864 -0.515861 0.83468 0.334582 -0.936075 -0.108712 0.646643 -0.733285 -0.210107 0.57735 -0.794654 0.187592 0.850651 -0.447214 -0.276393 0.853426 -0.515861 0.074505 0.73423 -0.515861 0.441355 0.356822 -0.794655 -0.491123 0.334582 -0.515861 -0.788633 0.646644 -0.515861 -0.561907 0 1 0.000000 -0.206783 0.936075 -0.284613 -0.334582 0.936075 0.108712 -0.399648 0.733285 -0.550068 -0.57735 0.794654 -0.187592 -0.646643 0.733285 0.210107 -0.525731 0.447214 -0.723607 -0.73423 0.515861 -0.441355 -0.853426 0.515861 -0.074505 -0.850651 0.447214 0.276393 0 0.936075 0.3518 -0.356822 0.794655 0.491123 0 0.733285 0.679921 -0.646644 0.515861 0.561907 -0.334582 0.515861 0.788633 0 0.447213 0.894427 0.334582 0.936075 0.108712 0.356822 0.794655 0.491123 0.646643 0.733285 0.210107 0.334582 0.515861 0.788633 0.646644 0.515861 0.561907 0.850651 0.447214 0.276393 0.206783 0.936075 -0.284613 0.57735 0.794654 -0.187592 0.399648 0.733285 -0.550068 0.853426 0.515861 -0.074505 0.73423 0.515861 -0.441355 0.525731 0.447214 -0.723607 0 0.794654 -0.607062 0.192864 0.515861 -0.83468 -0.192864 0.515861 -0.83468 -0.206783 -0.16406 -0.964534 -0.57735 -0.187592 -0.794654 -0.399647 0.16406 -0.901868 -0.853426 -0.16406 -0.49472 -0.73423 0.16406 -0.65878 -0.981225 -0.16406 -0.101395 -0.934172 -0.187593 0.303531 -0.981225 0.16406 0.101395 -0.73423 -0.16406 0.65878 -0.853426 0.16406 0.49472 -0.399647 -0.16406 0.901868 0 -0.187592 0.982247 -0.206783 0.16406 0.964534 0.399647 -0.16406 0.901868 0.206783 0.16406 0.964534 0.73423 -0.16406 0.65878 0.934172 -0.187593 0.303531 0.853426 0.16406 0.49472 0.981225 -0.16406 -0.101395 0.981225 0.16406 0.101395 0.853426 -0.16406 -0.49472 0.57735 -0.187592 -0.794654 0.73423 0.16406 -0.65878 0.206783 -0.16406 -0.964534 0.399647 0.16406 -0.901868 -0.934172 0.187593 -0.303531 -0.57735 0.187592 0.794654 0.57735 0.187592 0.794654 0.934172 0.187593 -0.303531 0 0.187592 -0.982247</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="184" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="500">0.121212 0.888889 0.060606 0.888889 0.090909 1 0.151515 0.777778 0.090909 0.777778 0.030303 0.777778 0.181818 0.666667 0.121212 0.666667 0.060606 0.666667 0 0.666667 0.30303 0.888889 0.242424 0.888889 0.272727 1 0.333333 0.777778 0.272727 0.777778 0.212121 0.777778 0.242424 0.888889 0.242424 0.888889 0.363636 0.666667 0.30303 0.666667 0.242424 0.666667 0.212121 0.777778 0.212121 0.777778 0.484848 0.888889 0.424242 0.888889 0.454545 1 0.515152 0.777778 0.454545 0.777778 0.393939 0.777778 0.424242 0.888889 0.424242 0.888889 0.545455 0.666667 0.484848 0.666667 0.424242 0.666667 0.393939 0.777778 0.393939 0.777778 0.666667 0.888889 0.606061 0.888889 0.636364 1 0.69697 0.777778 0.636364 0.777778 0.575758 0.777778 0.606061 0.888889 0.606061 0.888889 0.727273 0.666667 0.666667 0.666667 0.606061 0.666667 0.575758 0.777778 0.575758 0.777778 0.848485 0.888889 0.787879 0.888889 0.818182 1 0.878788 0.777778 0.818182 0.777778 0.848485 0.888889 0.757576 0.777778 0.787879 0.888889 0.787879 0.888889 0.848485 0.888889 0.909091 0.666667 0.848485 0.666667 0.878788 0.777778 0.787879 0.666667 0.757576 0.777778 0.878788 0.777778 0.757576 0.777778 0.151515 0.111111 0.212121 0.111111 0.181818 0 0.121212 0.222222 0.181818 0.222222 0.242424 0.222222 0.090909 0.333333 0.151515 0.333333 0.212121 0.333333 0.272727 0.333333 0.333333 0.111111 0.393939 0.111111 0.363636 0 0.30303 0.222222 0.363636 0.222222 0.333333 0.111111 0.424242 0.222222 0.333333 0.111111 0.333333 0.333333 0.30303 0.222222 0.393939 0.333333 0.454545 0.333333 0.30303 0.222222 0.515152 0.111111 0.575758 0.111111 0.545455 0 0.484848 0.222222 0.545455 0.222222 0.515152 0.111111 0.606061 0.222222 0.515152 0.111111 0.515152 0.333333 0.484848 0.222222 0.575758 0.333333 0.636364 0.333333 0.484848 0.222222 0.69697 0.111111 0.757576 0.111111 0.727273 0 0.666667 0.222222 0.727273 0.222222 0.69697 0.111111 0.787879 0.222222 0.69697 0.111111 0.69697 0.333333 0.666667 0.222222 0.757576 0.333333 0.818182 0.333333 0.666667 0.222222 0.878788 0.111111 0.939394 0.111111 0.909091 0 0.848485 0.222222 0.909091 0.222222 0.878788 0.111111 0.969697 0.222222 0.939394 0.111111 0.939394 0.111111 0.878788 0.111111 0.878788 0.333333 0.848485 0.222222 0.939394 0.333333 1 0.333333 0.969697 0.222222 0.848485 0.222222 0.969697 0.222222 0.030303 0.555556 0.090909 0.555556 0.060606 0.444444 0.151515 0.555556 0.121212 0.444444 0.212121 0.555556 0.272727 0.555556 0.242424 0.444444 0.333333 0.555556 0.30303 0.444444 0.393939 0.555556 0.454545 0.555556 0.424242 0.444444 0.515152 0.555556 0.484848 0.444444 0.575758 0.555556 0.636364 0.555556 0.606061 0.444444 0.69697 0.555556 0.666667 0.444444 0.757576 0.555556 0.818182 0.555556 0.787879 0.444444 0.909091 0.666667 0.878788 0.555556 0.848485 0.444444 0.181818 0.444444 0.363636 0.444444 0.545455 0.444444 0.727273 0.444444 0.969697 0.444444 1 0.333333 0.909091 0.444444 0.939394 0.555556 0.969697 0.444444 0.969697 0.444444 0.909091 0.666667 0.939394 0.555556 0.939394 0.555556 0.272727 1 0.242424 0.888889 0.242424 0.888889 0.212121 0.777778 0.242424 0.888889 0.212121 0.777778 0.212121 0.777778 0.454545 1 0.424242 0.888889 0.424242 0.888889 0.393939 0.777778 0.424242 0.888889 0.393939 0.777778 0.393939 0.777778 0.636364 1 0.606061 0.888889 0.606061 0.888889 0.575758 0.777778 0.606061 0.888889 0.575758 0.777778 0.575758 0.777778 0.848485 0.888889 0.818182 1 0.787879 0.888889 0.878788 0.777778 0.848485 0.888889 0.787879 0.888889 0.757576 0.777778 0.787879 0.888889 0.848485 0.888889 0.909091 0.666667 0.878788 0.777778 0.757576 0.777778 0.878788 0.777778 0.757576 0.777778 0.333333 0.111111 0.363636 0 0.30303 0.222222 0.333333 0.111111 0.333333 0.111111 0.30303 0.222222 0.30303 0.222222 0.515152 0.111111 0.545455 0 0.484848 0.222222 0.515152 0.111111 0.515152 0.111111 0.484848 0.222222 0.484848 0.222222 0.69697 0.111111 0.727273 0 0.666667 0.222222 0.69697 0.111111 0.69697 0.111111 0.666667 0.222222 0.666667 0.222222 0.878788 0.111111 0.909091 0 0.939394 0.111111 0.848485 0.222222 0.878788 0.111111 0.939394 0.111111 0.969697 0.222222 0.939394 0.111111 0.878788 0.111111 0.848485 0.222222 0.969697 0.222222 1 0.333333 0.848485 0.222222 0.969697 0.222222 0.909091 0.666667 1 0.333333 0.969697 0.444444 0.969697 0.444444 0.939394 0.555556 0.969697 0.444444 0.939394 0.555556 0.909091 0.666667 0.939394 0.555556</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="250" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="360">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>93 0 94 1 92 2 95 3 96 4 93 0 96 4 97 5 94 1 94 1 93 0 96 4 98 6 99 7 95 3 99 7 100 8 96 4 100 8 101 9 97 5 96 4 95 3 99 7 97 5 96 4 100 8 102 10 93 11 92 12 103 13 104 14 102 10 104 14 95 15 93 16 93 17 102 10 104 14 105 18 106 19 103 13 106 19 107 20 104 14 107 20 98 6 95 21 104 14 103 13 106 19 95 22 104 14 107 20 108 23 102 24 92 25 109 26 110 27 108 23 110 27 103 28 102 29 102 30 108 23 110 27 111 31 112 32 109 26 112 32 113 33 110 27 113 33 105 18 103 34 110 27 109 26 112 32 103 35 110 27 113 33 114 36 108 37 92 38 115 39 116 40 114 36 116 40 109 41 108 42 108 43 114 36 116 40 117 44 118 45 115 39 118 45 119 46 116 40 119 46 111 31 109 47 116 40 115 39 118 45 109 48 116 40 119 46 94 49 114 50 92 51 97 52 120 53 94 54 120 53 115 55 114 56 114 57 94 58 120 53 101 59 121 60 97 61 121 60 122 62 120 53 122 62 117 44 115 63 120 53 97 64 121 60 115 65 120 53 122 62 124 66 125 67 123 68 126 69 127 70 124 66 127 70 128 71 125 67 125 67 124 66 127 70 129 72 130 73 126 69 130 73 131 74 127 70 131 74 132 75 128 71 127 70 126 69 130 73 128 71 127 70 131 74 125 76 133 77 123 78 128 79 134 80 125 81 134 80 135 82 133 77 133 77 125 83 134 80 132 75 136 84 128 85 136 84 137 86 134 80 137 86 138 87 135 82 134 80 128 88 136 84 135 82 134 80 137 86 133 89 139 90 123 91 135 92 140 93 133 94 140 93 141 95 139 90 139 90 133 96 140 93 138 87 142 97 135 98 142 97 143 99 140 93 143 99 144 100 141 95 140 93 135 101 142 97 141 95 140 93 143 99 139 102 145 103 123 104 141 105 146 106 139 107 146 106 147 108 145 103 145 103 139 109 146 106 144 100 148 110 141 111 148 110 149 112 146 106 149 112 150 113 147 108 146 106 141 114 148 110 147 108 146 106 149 112 145 115 124 116 123 117 147 118 151 119 145 120 151 119 126 121 124 122 124 123 145 124 151 119 150 113 152 125 147 126 152 125 153 127 151 119 153 127 129 128 126 129 151 119 147 130 152 125 126 131 151 119 153 127 100 8 154 132 101 9 99 7 155 133 100 8 155 133 156 134 154 132 154 132 100 8 155 133 98 6 157 135 99 7 157 135 158 136 155 133 158 136 129 72 156 134 155 133 99 7 157 135 156 134 155 133 158 136 107 20 159 137 98 6 106 19 160 138 107 20 160 138 161 139 159 137 159 137 107 20 160 138 105 18 162 140 106 19 162 140 163 141 160 138 163 141 132 75 161 139 160 138 106 19 162 140 161 139 160 138 163 141 113 33 164 142 105 18 112 32 165 143 113 33 165 143 166 144 164 142 164 142 113 33 165 143 111 31 167 145 112 32 167 145 168 146 165 143 168 146 138 87 166 144 165 143 112 32 167 145 166 144 165 143 168 146 119 46 169 147 111 31 118 45 170 148 119 46 170 148 171 149 169 147 169 147 119 46 170 148 117 44 172 150 118 45 172 150 173 151 170 148 173 151 144 100 171 149 170 148 118 45 172 150 171 149 170 148 173 151 122 62 174 152 117 44 121 60 175 153 122 62 175 153 176 154 174 152 174 152 122 62 175 153 101 155 177 156 121 60 177 156 178 157 175 153 178 157 150 113 176 154 175 153 121 60 177 156 176 154 175 153 178 157 131 74 161 139 132 75 130 73 179 158 131 74 179 158 159 137 161 139 161 139 131 74 179 158 129 72 158 136 130 73 158 136 157 135 179 158 157 135 98 6 159 137 179 158 130 73 158 136 159 137 179 158 157 135 137 86 166 144 138 87 136 84 180 159 137 86 180 159 164 142 166 144 166 144 137 86 180 159 132 75 163 141 136 84 163 141 162 140 180 159 162 140 105 18 164 142 180 159 136 84 163 141 164 142 180 159 162 140 143 99 171 149 144 100 142 97 181 160 143 99 181 160 169 147 171 149 171 149 143 99 181 160 138 87 168 146 142 97 168 146 167 145 181 160 167 145 111 31 169 147 181 160 142 97 168 146 169 147 181 160 167 145 149 112 176 154 150 113 148 110 182 161 149 112 182 161 174 152 176 154 176 154 149 112 182 161 144 100 173 151 148 110 173 151 172 150 182 161 172 150 117 44 174 152 182 161 148 110 173 151 174 152 182 161 172 150 153 127 156 162 129 163 152 125 183 164 153 127 183 164 154 165 156 166 156 167 153 127 183 164 150 113 178 157 152 125 178 157 177 156 183 164 177 156 101 168 154 169 183 164 152 125 178 157 154 170 183 164 177 156 1 0 0 2 2 1 3 3 1 0 4 4 4 4 2 1 5 5 2 1 4 4 1 0 6 6 3 3 7 7 7 7 4 4 8 8 8 8 5 5 9 9 4 4 7 7 3 3 5 5 8 8 4 4 10 10 0 171 1 172 11 13 10 10 12 14 12 14 1 173 3 174 1 175 12 14 10 10 13 18 11 13 14 19 14 19 12 14 15 20 15 20 3 176 6 6 12 14 14 19 11 13 3 177 15 20 12 14 16 23 0 178 10 179 17 26 16 23 18 27 18 27 10 180 11 181 10 182 18 27 16 23 19 31 17 26 20 32 20 32 18 27 21 33 21 33 11 183 13 18 18 27 20 32 17 26 11 184 21 33 18 27 22 36 0 185 16 186 23 39 22 36 24 40 24 40 16 187 17 188 16 189 24 40 22 36 25 44 23 39 26 45 26 45 24 40 27 46 27 46 17 190 19 31 24 40 26 45 23 39 17 191 27 46 24 40 2 192 0 193 22 194 5 195 2 196 28 53 28 53 22 197 23 198 22 199 28 53 2 200 9 201 5 202 29 60 29 60 28 53 30 62 30 62 23 203 25 44 28 53 29 60 5 204 23 205 30 62 28 53 32 66 31 68 33 67 34 69 32 66 35 70 35 70 33 67 36 71 33 67 35 70 32 66 37 72 34 69 38 73 38 73 35 70 39 74 39 74 36 71 40 75 35 70 38 73 34 69 36 71 39 74 35 70 33 206 31 207 41 77 36 208 33 209 42 80 42 80 41 77 43 82 41 77 42 80 33 210 40 75 36 211 44 84 44 84 42 80 45 86 45 86 43 82 46 87 42 80 44 84 36 212 43 82 45 86 42 80 41 213 31 214 47 90 43 215 41 216 48 93 48 93 47 90 49 95 47 90 48 93 41 217 46 87 43 218 50 97 50 97 48 93 51 99 51 99 49 95 52 100 48 93 50 97 43 219 49 95 51 99 48 93 47 220 31 221 53 103 49 222 47 223 54 106 54 106 53 103 55 108 53 103 54 106 47 224 52 100 49 225 56 110 56 110 54 106 57 112 57 112 55 108 58 113 54 106 56 110 49 226 55 108 57 112 54 106 53 227 31 228 32 229 55 230 53 231 59 119 59 119 32 232 34 233 32 234 59 119 53 235 58 113 55 236 60 125 60 125 59 119 61 127 61 127 34 237 37 238 59 119 60 125 55 239 34 240 61 127 59 119 8 8 9 9 62 132 7 7 8 8 63 133 63 133 62 132 64 134 62 132 63 133 8 8 6 6 7 7 65 135 65 135 63 133 66 136 66 136 64 134 37 72 63 133 65 135 7 7 64 134 66 136 63 133 15 20 6 6 67 137 14 19 15 20 68 138 68 138 67 137 69 139 67 137 68 138 15 20 13 18 14 19 70 140 70 140 68 138 71 141 71 141 69 139 40 75 68 138 70 140 14 19 69 139 71 141 68 138 21 33 13 18 72 142 20 32 21 33 73 143 73 143 72 142 74 144 72 142 73 143 21 33 19 31 20 32 75 145 75 145 73 143 76 146 76 146 74 144 46 87 73 143 75 145 20 32 74 144 76 146 73 143 27 46 19 31 77 147 26 45 27 46 78 148 78 148 77 147 79 149 77 147 78 148 27 46 25 44 26 45 80 150 80 150 78 148 81 151 81 151 79 149 52 100 78 148 80 150 26 45 79 149 81 151 78 148 30 62 25 44 82 152 29 60 30 62 83 153 83 153 82 152 84 154 82 152 83 153 30 62 9 241 29 60 85 156 85 156 83 153 86 157 86 157 84 154 58 113 83 153 85 156 29 60 84 154 86 157 83 153 39 74 40 75 69 139 38 73 39 74 87 158 87 158 69 139 67 137 69 139 87 158 39 74 37 72 38 73 66 136 66 136 87 158 65 135 65 135 67 137 6 6 87 158 66 136 38 73 67 137 65 135 87 158 45 86 46 87 74 144 44 84 45 86 88 159 88 159 74 144 72 142 74 144 88 159 45 86 40 75 44 84 71 141 71 141 88 159 70 140 70 140 72 142 13 18 88 159 71 141 44 84 72 142 70 140 88 159 51 99 52 100 79 149 50 97 51 99 89 160 89 160 79 149 77 147 79 149 89 160 51 99 46 87 50 97 76 146 76 146 89 160 75 145 75 145 77 147 19 31 89 160 76 146 50 97 77 147 75 145 89 160 57 112 58 113 84 154 56 110 57 112 90 161 90 161 84 154 82 152 84 154 90 161 57 112 52 100 56 110 81 151 81 151 90 161 80 150 80 150 82 152 25 44 90 161 81 151 56 110 82 152 80 150 90 161 61 127 37 242 64 243 60 125 61 127 91 164 91 164 64 244 62 245 64 246 91 164 61 127 58 113 60 125 86 157 86 157 91 164 85 156 85 156 62 247 9 248 91 164 86 157 60 125 62 249 85 156 91 164</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-medium-doublesided">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-inverted.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-inverted.dae
new file mode 100644
index 00000000..4af5f465
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium-inverted.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-09-19T22:01:10Z</created>
+ <modified>2008-09-19T22:01:10Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="276">0 50 0 17.1537 46.6335 5.57358 0 46.6335 18.0365 31.9975 36.9875 10.3966 17.8411 39.7327 24.5562 0 36.9875 33.6441 42.5325 22.3607 13.8197 31.9975 25.8403 28.4331 17.1537 25.8403 39.2177 0 22.3607 44.7214 10.6016 46.6335 -14.5918 19.7755 36.9875 -27.2187 28.8675 39.7327 -9.37962 26.2866 22.3607 -36.1803 36.9292 25.8403 -21.6451 42.599 25.8403 -4.19521 -10.6016 46.6335 -14.5918 -19.7755 36.9875 -27.2187 0 39.7327 -30.3531 -26.2866 22.3607 -36.1803 -9.17395 25.8403 -41.8105 9.17395 25.8403 -41.8105 -17.1537 46.6335 5.57358 -31.9975 36.9875 10.3966 -28.8675 39.7327 -9.37962 -42.5325 22.3607 13.8197 -42.599 25.8403 -4.19521 -36.9292 25.8403 -21.6451 -17.8411 39.7327 24.5562 -17.1537 25.8403 39.2177 -31.9975 25.8403 28.4331 0 -50 0 10.6016 -46.6335 14.5918 17.1537 -46.6335 -5.57358 19.7755 -36.9875 27.2187 28.8675 -39.7327 9.37962 31.9975 -36.9875 -10.3966 26.2866 -22.3607 36.1803 36.9292 -25.8403 21.6451 42.599 -25.8403 4.19521 42.5325 -22.3607 -13.8197 0 -46.6335 -18.0365 17.8411 -39.7327 -24.5562 0 -36.9875 -33.6441 31.9975 -25.8403 -28.4331 17.1537 -25.8403 -39.2177 0 -22.3607 -44.7214 -17.1537 -46.6335 -5.57358 -17.8411 -39.7327 -24.5562 -31.9975 -36.9875 -10.3966 -17.1537 -25.8403 -39.2177 -31.9975 -25.8403 -28.4331 -42.5325 -22.3607 -13.8197 -10.6016 -46.6335 14.5918 -28.8675 -39.7327 9.37962 -19.7755 -36.9875 27.2187 -42.599 -25.8403 4.19521 -36.9292 -25.8403 21.6451 -26.2866 -22.3607 36.1803 0 -39.7327 30.3531 -9.17395 -25.8403 41.8105 9.17395 -25.8403 41.8105 10.6016 7.80382 48.236 28.8675 9.37962 39.7327 19.7755 -7.80382 45.2552 42.599 7.80382 24.9884 36.9292 -7.80382 32.7923 49.1512 7.80382 4.82303 46.7086 9.37962 -15.1765 49.1512 -7.80382 -4.82303 36.9292 7.80382 -32.7923 42.599 -7.80382 -24.9884 19.7755 7.80382 -45.2552 0 9.37962 -49.1123 10.6016 -7.80382 -48.236 -19.7755 7.80382 -45.2552 -10.6016 -7.80382 -48.236 -36.9292 7.80382 -32.7923 -46.7086 9.37962 -15.1765 -42.599 -7.80382 -24.9884 -49.1512 7.80382 4.82303 -49.1512 -7.80382 -4.82303 -42.599 7.80382 24.9884 -28.8675 9.37962 39.7327 -36.9292 -7.80382 32.7923 -10.6016 7.80382 48.236 -19.7755 -7.80382 45.2552 46.7086 -9.37962 15.1765 28.8675 -9.37962 -39.7327 -28.8675 -9.37962 -39.7327 -46.7086 -9.37962 15.1765 0 -9.37962 49.1123</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="92" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="276">0 -1 -0.000000 -0.334582 -0.936075 -0.108712 0 -0.936075 -0.3518 -0.646643 -0.733285 -0.210107 -0.356822 -0.794655 -0.491123 0 -0.733285 -0.679921 -0.850651 -0.447214 -0.276393 -0.646644 -0.515861 -0.561907 -0.334582 -0.515861 -0.788633 0 -0.447213 -0.894427 -0.206783 -0.936075 0.284613 -0.399648 -0.733285 0.550068 -0.57735 -0.794654 0.187592 -0.525731 -0.447214 0.723607 -0.73423 -0.515861 0.441355 -0.853426 -0.515861 0.074505 0.206783 -0.936075 0.284613 0.399648 -0.733285 0.550068 0 -0.794654 0.607062 0.525731 -0.447214 0.723607 0.192864 -0.515861 0.83468 -0.192864 -0.515861 0.83468 0.334582 -0.936075 -0.108712 0.646643 -0.733285 -0.210107 0.57735 -0.794654 0.187592 0.850651 -0.447214 -0.276393 0.853426 -0.515861 0.074505 0.73423 -0.515861 0.441355 0.356822 -0.794655 -0.491123 0.334582 -0.515861 -0.788633 0.646644 -0.515861 -0.561907 0 1 0.000000 -0.206783 0.936075 -0.284613 -0.334582 0.936075 0.108712 -0.399648 0.733285 -0.550068 -0.57735 0.794654 -0.187592 -0.646643 0.733285 0.210107 -0.525731 0.447214 -0.723607 -0.73423 0.515861 -0.441355 -0.853426 0.515861 -0.074505 -0.850651 0.447214 0.276393 0 0.936075 0.3518 -0.356822 0.794655 0.491123 0 0.733285 0.679921 -0.646644 0.515861 0.561907 -0.334582 0.515861 0.788633 0 0.447213 0.894427 0.334582 0.936075 0.108712 0.356822 0.794655 0.491123 0.646643 0.733285 0.210107 0.334582 0.515861 0.788633 0.646644 0.515861 0.561907 0.850651 0.447214 0.276393 0.206783 0.936075 -0.284613 0.57735 0.794654 -0.187592 0.399648 0.733285 -0.550068 0.853426 0.515861 -0.074505 0.73423 0.515861 -0.441355 0.525731 0.447214 -0.723607 0 0.794654 -0.607062 0.192864 0.515861 -0.83468 -0.192864 0.515861 -0.83468 -0.206783 -0.16406 -0.964534 -0.57735 -0.187592 -0.794654 -0.399647 0.16406 -0.901868 -0.853426 -0.16406 -0.49472 -0.73423 0.16406 -0.65878 -0.981225 -0.16406 -0.101395 -0.934172 -0.187593 0.303531 -0.981225 0.16406 0.101395 -0.73423 -0.16406 0.65878 -0.853426 0.16406 0.49472 -0.399647 -0.16406 0.901868 0 -0.187592 0.982247 -0.206783 0.16406 0.964534 0.399647 -0.16406 0.901868 0.206783 0.16406 0.964534 0.73423 -0.16406 0.65878 0.934172 -0.187593 0.303531 0.853426 0.16406 0.49472 0.981225 -0.16406 -0.101395 0.981225 0.16406 0.101395 0.853426 -0.16406 -0.49472 0.57735 -0.187592 -0.794654 0.73423 0.16406 -0.65878 0.206783 -0.16406 -0.964534 0.399647 0.16406 -0.901868 -0.934172 0.187593 -0.303531 -0.57735 0.187592 0.794654 0.57735 0.187592 0.794654 0.934172 0.187593 -0.303531 0 0.187592 -0.982247</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="92" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="342">0.121212 0.888889 0.060606 0.888889 0.090909 1 0.151515 0.777778 0.090909 0.777778 0.030303 0.777778 0.181818 0.666667 0.121212 0.666667 0.060606 0.666667 0 0.666667 0.30303 0.888889 0.242424 0.888889 0.272727 1 0.333333 0.777778 0.272727 0.777778 0.212121 0.777778 0.242424 0.888889 0.242424 0.888889 0.363636 0.666667 0.30303 0.666667 0.242424 0.666667 0.212121 0.777778 0.212121 0.777778 0.484848 0.888889 0.424242 0.888889 0.454545 1 0.515152 0.777778 0.454545 0.777778 0.393939 0.777778 0.424242 0.888889 0.424242 0.888889 0.545455 0.666667 0.484848 0.666667 0.424242 0.666667 0.393939 0.777778 0.393939 0.777778 0.666667 0.888889 0.606061 0.888889 0.636364 1 0.69697 0.777778 0.636364 0.777778 0.575758 0.777778 0.606061 0.888889 0.606061 0.888889 0.727273 0.666667 0.666667 0.666667 0.606061 0.666667 0.575758 0.777778 0.575758 0.777778 0.848485 0.888889 0.787879 0.888889 0.818182 1 0.878788 0.777778 0.818182 0.777778 0.848485 0.888889 0.757576 0.777778 0.787879 0.888889 0.787879 0.888889 0.848485 0.888889 0.909091 0.666667 0.848485 0.666667 0.878788 0.777778 0.787879 0.666667 0.757576 0.777778 0.878788 0.777778 0.757576 0.777778 0.151515 0.111111 0.212121 0.111111 0.181818 0 0.121212 0.222222 0.181818 0.222222 0.242424 0.222222 0.090909 0.333333 0.151515 0.333333 0.212121 0.333333 0.272727 0.333333 0.333333 0.111111 0.393939 0.111111 0.363636 0 0.30303 0.222222 0.363636 0.222222 0.333333 0.111111 0.424242 0.222222 0.333333 0.111111 0.333333 0.333333 0.30303 0.222222 0.393939 0.333333 0.454545 0.333333 0.30303 0.222222 0.515152 0.111111 0.575758 0.111111 0.545455 0 0.484848 0.222222 0.545455 0.222222 0.515152 0.111111 0.606061 0.222222 0.515152 0.111111 0.515152 0.333333 0.484848 0.222222 0.575758 0.333333 0.636364 0.333333 0.484848 0.222222 0.69697 0.111111 0.757576 0.111111 0.727273 0 0.666667 0.222222 0.727273 0.222222 0.69697 0.111111 0.787879 0.222222 0.69697 0.111111 0.69697 0.333333 0.666667 0.222222 0.757576 0.333333 0.818182 0.333333 0.666667 0.222222 0.878788 0.111111 0.939394 0.111111 0.909091 0 0.848485 0.222222 0.909091 0.222222 0.878788 0.111111 0.969697 0.222222 0.939394 0.111111 0.939394 0.111111 0.878788 0.111111 0.878788 0.333333 0.848485 0.222222 0.939394 0.333333 1 0.333333 0.969697 0.222222 0.848485 0.222222 0.969697 0.222222 0.030303 0.555556 0.090909 0.555556 0.060606 0.444444 0.151515 0.555556 0.121212 0.444444 0.212121 0.555556 0.272727 0.555556 0.242424 0.444444 0.333333 0.555556 0.30303 0.444444 0.393939 0.555556 0.454545 0.555556 0.424242 0.444444 0.515152 0.555556 0.484848 0.444444 0.575758 0.555556 0.636364 0.555556 0.606061 0.444444 0.69697 0.555556 0.666667 0.444444 0.757576 0.555556 0.818182 0.555556 0.787879 0.444444 0.909091 0.666667 0.878788 0.555556 0.848485 0.444444 0.181818 0.444444 0.363636 0.444444 0.545455 0.444444 0.727273 0.444444 0.969697 0.444444 1 0.333333 0.909091 0.444444 0.939394 0.555556 0.969697 0.444444 0.969697 0.444444 0.909091 0.666667 0.939394 0.555556 0.939394 0.555556</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="171" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="180">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 2 1 0 2 3 3 4 4 1 0 4 4 5 5 2 1 2 1 1 0 4 4 6 6 7 7 3 3 7 7 8 8 4 4 8 8 9 9 5 5 4 4 3 3 7 7 5 5 4 4 8 8 10 10 1 11 0 12 11 13 12 14 10 10 12 14 3 15 1 16 1 17 10 10 12 14 13 18 14 19 11 13 14 19 15 20 12 14 15 20 6 6 3 21 12 14 11 13 14 19 3 22 12 14 15 20 16 23 10 24 0 25 17 26 18 27 16 23 18 27 11 28 10 29 10 30 16 23 18 27 19 31 20 32 17 26 20 32 21 33 18 27 21 33 13 18 11 34 18 27 17 26 20 32 11 35 18 27 21 33 22 36 16 37 0 38 23 39 24 40 22 36 24 40 17 41 16 42 16 43 22 36 24 40 25 44 26 45 23 39 26 45 27 46 24 40 27 46 19 31 17 47 24 40 23 39 26 45 17 48 24 40 27 46 2 49 22 50 0 51 5 52 28 53 2 54 28 53 23 55 22 56 22 57 2 58 28 53 9 59 29 60 5 61 29 60 30 62 28 53 30 62 25 44 23 63 28 53 5 64 29 60 23 65 28 53 30 62 32 66 33 67 31 68 34 69 35 70 32 66 35 70 36 71 33 67 33 67 32 66 35 70 37 72 38 73 34 69 38 73 39 74 35 70 39 74 40 75 36 71 35 70 34 69 38 73 36 71 35 70 39 74 33 76 41 77 31 78 36 79 42 80 33 81 42 80 43 82 41 77 41 77 33 83 42 80 40 75 44 84 36 85 44 84 45 86 42 80 45 86 46 87 43 82 42 80 36 88 44 84 43 82 42 80 45 86 41 89 47 90 31 91 43 92 48 93 41 94 48 93 49 95 47 90 47 90 41 96 48 93 46 87 50 97 43 98 50 97 51 99 48 93 51 99 52 100 49 95 48 93 43 101 50 97 49 95 48 93 51 99 47 102 53 103 31 104 49 105 54 106 47 107 54 106 55 108 53 103 53 103 47 109 54 106 52 100 56 110 49 111 56 110 57 112 54 106 57 112 58 113 55 108 54 106 49 114 56 110 55 108 54 106 57 112 53 115 32 116 31 117 55 118 59 119 53 120 59 119 34 121 32 122 32 123 53 124 59 119 58 113 60 125 55 126 60 125 61 127 59 119 61 127 37 128 34 129 59 119 55 130 60 125 34 131 59 119 61 127 8 8 62 132 9 9 7 7 63 133 8 8 63 133 64 134 62 132 62 132 8 8 63 133 6 6 65 135 7 7 65 135 66 136 63 133 66 136 37 72 64 134 63 133 7 7 65 135 64 134 63 133 66 136 15 20 67 137 6 6 14 19 68 138 15 20 68 138 69 139 67 137 67 137 15 20 68 138 13 18 70 140 14 19 70 140 71 141 68 138 71 141 40 75 69 139 68 138 14 19 70 140 69 139 68 138 71 141 21 33 72 142 13 18 20 32 73 143 21 33 73 143 74 144 72 142 72 142 21 33 73 143 19 31 75 145 20 32 75 145 76 146 73 143 76 146 46 87 74 144 73 143 20 32 75 145 74 144 73 143 76 146 27 46 77 147 19 31 26 45 78 148 27 46 78 148 79 149 77 147 77 147 27 46 78 148 25 44 80 150 26 45 80 150 81 151 78 148 81 151 52 100 79 149 78 148 26 45 80 150 79 149 78 148 81 151 30 62 82 152 25 44 29 60 83 153 30 62 83 153 84 154 82 152 82 152 30 62 83 153 9 155 85 156 29 60 85 156 86 157 83 153 86 157 58 113 84 154 83 153 29 60 85 156 84 154 83 153 86 157 39 74 69 139 40 75 38 73 87 158 39 74 87 158 67 137 69 139 69 139 39 74 87 158 37 72 66 136 38 73 66 136 65 135 87 158 65 135 6 6 67 137 87 158 38 73 66 136 67 137 87 158 65 135 45 86 74 144 46 87 44 84 88 159 45 86 88 159 72 142 74 144 74 144 45 86 88 159 40 75 71 141 44 84 71 141 70 140 88 159 70 140 13 18 72 142 88 159 44 84 71 141 72 142 88 159 70 140 51 99 79 149 52 100 50 97 89 160 51 99 89 160 77 147 79 149 79 149 51 99 89 160 46 87 76 146 50 97 76 146 75 145 89 160 75 145 19 31 77 147 89 160 50 97 76 146 77 147 89 160 75 145 57 112 84 154 58 113 56 110 90 161 57 112 90 161 82 152 84 154 84 154 57 112 90 161 52 100 81 151 56 110 81 151 80 150 90 161 80 150 25 44 82 152 90 161 56 110 81 151 82 152 90 161 80 150 61 127 64 162 37 163 60 125 91 164 61 127 91 164 62 165 64 166 64 167 61 127 91 164 58 113 86 157 60 125 86 157 85 156 91 164 85 156 9 168 62 169 91 164 60 125 86 157 62 170 91 164 85 156</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium.dae
new file mode 100644
index 00000000..4e1446e8
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-medium.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/spheres/Sphere-medium.mb</source_data>
+ </contributor>
+ <created>2008-09-19T21:56:36Z</created>
+ <modified>2008-09-19T21:56:36Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert1" name="lambert1">
+ <instance_effect url="#lambert1-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert1-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="276">0 50 0 17.1537 46.6335 5.57358 0 46.6335 18.0365 31.9975 36.9875 10.3966 17.8411 39.7327 24.5562 0 36.9875 33.6441 42.5325 22.3607 13.8197 31.9975 25.8403 28.4331 17.1537 25.8403 39.2177 0 22.3607 44.7214 10.6016 46.6335 -14.5918 19.7755 36.9875 -27.2187 28.8675 39.7327 -9.37962 26.2866 22.3607 -36.1803 36.9292 25.8403 -21.6451 42.599 25.8403 -4.19521 -10.6016 46.6335 -14.5918 -19.7755 36.9875 -27.2187 0 39.7327 -30.3531 -26.2866 22.3607 -36.1803 -9.17395 25.8403 -41.8105 9.17395 25.8403 -41.8105 -17.1537 46.6335 5.57358 -31.9975 36.9875 10.3966 -28.8675 39.7327 -9.37962 -42.5325 22.3607 13.8197 -42.599 25.8403 -4.19521 -36.9292 25.8403 -21.6451 -17.8411 39.7327 24.5562 -17.1537 25.8403 39.2177 -31.9975 25.8403 28.4331 0 -50 0 10.6016 -46.6335 14.5918 17.1537 -46.6335 -5.57358 19.7755 -36.9875 27.2187 28.8675 -39.7327 9.37962 31.9975 -36.9875 -10.3966 26.2866 -22.3607 36.1803 36.9292 -25.8403 21.6451 42.599 -25.8403 4.19521 42.5325 -22.3607 -13.8197 0 -46.6335 -18.0365 17.8411 -39.7327 -24.5562 0 -36.9875 -33.6441 31.9975 -25.8403 -28.4331 17.1537 -25.8403 -39.2177 0 -22.3607 -44.7214 -17.1537 -46.6335 -5.57358 -17.8411 -39.7327 -24.5562 -31.9975 -36.9875 -10.3966 -17.1537 -25.8403 -39.2177 -31.9975 -25.8403 -28.4331 -42.5325 -22.3607 -13.8197 -10.6016 -46.6335 14.5918 -28.8675 -39.7327 9.37962 -19.7755 -36.9875 27.2187 -42.599 -25.8403 4.19521 -36.9292 -25.8403 21.6451 -26.2866 -22.3607 36.1803 0 -39.7327 30.3531 -9.17395 -25.8403 41.8105 9.17395 -25.8403 41.8105 10.6016 7.80382 48.236 28.8675 9.37962 39.7327 19.7755 -7.80382 45.2552 42.599 7.80382 24.9884 36.9292 -7.80382 32.7923 49.1512 7.80382 4.82303 46.7086 9.37962 -15.1765 49.1512 -7.80382 -4.82303 36.9292 7.80382 -32.7923 42.599 -7.80382 -24.9884 19.7755 7.80382 -45.2552 0 9.37962 -49.1123 10.6016 -7.80382 -48.236 -19.7755 7.80382 -45.2552 -10.6016 -7.80382 -48.236 -36.9292 7.80382 -32.7923 -46.7086 9.37962 -15.1765 -42.599 -7.80382 -24.9884 -49.1512 7.80382 4.82303 -49.1512 -7.80382 -4.82303 -42.599 7.80382 24.9884 -28.8675 9.37962 39.7327 -36.9292 -7.80382 32.7923 -10.6016 7.80382 48.236 -19.7755 -7.80382 45.2552 46.7086 -9.37962 15.1765 28.8675 -9.37962 -39.7327 -28.8675 -9.37962 -39.7327 -46.7086 -9.37962 15.1765 0 -9.37962 49.1123</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="92" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="276">0 1 0 0.334582 0.936075 0.108712 0 0.936075 0.351801 0.646643 0.733285 0.210107 0.356822 0.794655 0.491123 0 0.733285 0.679921 0.850651 0.447214 0.276393 0.646644 0.515861 0.561907 0.334582 0.515861 0.788633 0 0.447213 0.894427 0.206783 0.936075 -0.284613 0.399648 0.733285 -0.550068 0.57735 0.794654 -0.187592 0.525731 0.447214 -0.723607 0.73423 0.515861 -0.441355 0.853426 0.515861 -0.074505 -0.206783 0.936075 -0.284613 -0.399648 0.733285 -0.550068 0 0.794654 -0.607062 -0.525731 0.447214 -0.723607 -0.192864 0.515861 -0.83468 0.192864 0.515861 -0.83468 -0.334582 0.936075 0.108712 -0.646643 0.733285 0.210107 -0.57735 0.794654 -0.187592 -0.850651 0.447214 0.276393 -0.853426 0.515861 -0.074505 -0.73423 0.515861 -0.441355 -0.356822 0.794654 0.491123 -0.334582 0.515861 0.788633 -0.646644 0.515861 0.561907 0 -1 0 0.206783 -0.936075 0.284613 0.334582 -0.936075 -0.108712 0.399648 -0.733285 0.550068 0.57735 -0.794654 0.187592 0.646643 -0.733285 -0.210107 0.525731 -0.447214 0.723607 0.73423 -0.515861 0.441355 0.853426 -0.515861 0.074505 0.850651 -0.447214 -0.276393 0 -0.936075 -0.351801 0.356822 -0.794655 -0.491123 0 -0.733285 -0.679921 0.646644 -0.515861 -0.561907 0.334582 -0.515861 -0.788633 0 -0.447213 -0.894427 -0.334582 -0.936075 -0.108712 -0.356822 -0.794654 -0.491123 -0.646643 -0.733285 -0.210107 -0.334582 -0.515861 -0.788633 -0.646644 -0.515861 -0.561907 -0.850651 -0.447214 -0.276393 -0.206783 -0.936075 0.284613 -0.57735 -0.794654 0.187592 -0.399648 -0.733285 0.550068 -0.853426 -0.515861 0.074505 -0.73423 -0.515861 0.441355 -0.525731 -0.447214 0.723607 0 -0.794654 0.607062 -0.192864 -0.515861 0.83468 0.192864 -0.515861 0.83468 0.206783 0.16406 0.964534 0.57735 0.187592 0.794654 0.399647 -0.16406 0.901868 0.853426 0.16406 0.49472 0.73423 -0.16406 0.65878 0.981225 0.16406 0.101395 0.934172 0.187593 -0.303531 0.981225 -0.16406 -0.101395 0.73423 0.16406 -0.65878 0.853426 -0.16406 -0.49472 0.399647 0.16406 -0.901868 0 0.187592 -0.982247 0.206783 -0.16406 -0.964534 -0.399647 0.16406 -0.901868 -0.206783 -0.16406 -0.964534 -0.73423 0.16406 -0.65878 -0.934172 0.187593 -0.303531 -0.853426 -0.16406 -0.49472 -0.981225 0.16406 0.101395 -0.981225 -0.16406 -0.101395 -0.853426 0.16406 0.49472 -0.57735 0.187592 0.794654 -0.73423 -0.16406 0.65878 -0.206783 0.16406 0.964534 -0.399647 -0.16406 0.901868 0.934172 -0.187593 0.303531 0.57735 -0.187592 -0.794654 -0.57735 -0.187592 -0.794654 -0.934172 -0.187593 0.303531 0 -0.187592 0.982247</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="92" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="342">0.121212 0.888889 0.090909 1 0.060606 0.888889 0.151515 0.777778 0.090909 0.777778 0.030303 0.777778 0.181818 0.666667 0.121212 0.666667 0.060606 0.666667 0 0.666667 0.30303 0.888889 0.272727 1 0.242424 0.888889 0.333333 0.777778 0.272727 0.777778 0.242424 0.888889 0.212121 0.777778 0.242424 0.888889 0.363636 0.666667 0.30303 0.666667 0.242424 0.666667 0.212121 0.777778 0.212121 0.777778 0.484848 0.888889 0.454545 1 0.424242 0.888889 0.515152 0.777778 0.454545 0.777778 0.424242 0.888889 0.393939 0.777778 0.424242 0.888889 0.545455 0.666667 0.484848 0.666667 0.424242 0.666667 0.393939 0.777778 0.393939 0.777778 0.666667 0.888889 0.636364 1 0.606061 0.888889 0.69697 0.777778 0.636364 0.777778 0.606061 0.888889 0.575758 0.777778 0.606061 0.888889 0.727273 0.666667 0.666667 0.666667 0.606061 0.666667 0.575758 0.777778 0.575758 0.777778 0.848485 0.888889 0.818182 1 0.787879 0.888889 0.878788 0.777778 0.848485 0.888889 0.818182 0.777778 0.787879 0.888889 0.757576 0.777778 0.787879 0.888889 0.848485 0.888889 0.909091 0.666667 0.878788 0.777778 0.848485 0.666667 0.787879 0.666667 0.757576 0.777778 0.878788 0.777778 0.757576 0.777778 0.151515 0.111111 0.181818 0 0.212121 0.111111 0.121212 0.222222 0.181818 0.222222 0.242424 0.222222 0.090909 0.333333 0.151515 0.333333 0.212121 0.333333 0.272727 0.333333 0.333333 0.111111 0.363636 0 0.393939 0.111111 0.30303 0.222222 0.333333 0.111111 0.363636 0.222222 0.424242 0.222222 0.333333 0.111111 0.30303 0.222222 0.333333 0.333333 0.393939 0.333333 0.454545 0.333333 0.30303 0.222222 0.515152 0.111111 0.545455 0 0.575758 0.111111 0.484848 0.222222 0.515152 0.111111 0.545455 0.222222 0.606061 0.222222 0.515152 0.111111 0.484848 0.222222 0.515152 0.333333 0.575758 0.333333 0.636364 0.333333 0.484848 0.222222 0.69697 0.111111 0.727273 0 0.757576 0.111111 0.666667 0.222222 0.69697 0.111111 0.727273 0.222222 0.787879 0.222222 0.69697 0.111111 0.666667 0.222222 0.69697 0.333333 0.757576 0.333333 0.818182 0.333333 0.666667 0.222222 0.878788 0.111111 0.909091 0 0.939394 0.111111 0.848485 0.222222 0.878788 0.111111 0.909091 0.222222 0.939394 0.111111 0.969697 0.222222 0.939394 0.111111 0.878788 0.111111 0.848485 0.222222 0.878788 0.333333 0.939394 0.333333 0.969697 0.222222 1 0.333333 0.848485 0.222222 0.969697 0.222222 0.030303 0.555556 0.090909 0.555556 0.060606 0.444444 0.151515 0.555556 0.121212 0.444444 0.212121 0.555556 0.272727 0.555556 0.242424 0.444444 0.333333 0.555556 0.30303 0.444444 0.393939 0.555556 0.454545 0.555556 0.424242 0.444444 0.515152 0.555556 0.484848 0.444444 0.575758 0.555556 0.636364 0.555556 0.606061 0.444444 0.69697 0.555556 0.666667 0.444444 0.757576 0.555556 0.818182 0.555556 0.787879 0.444444 0.909091 0.666667 0.878788 0.555556 0.848485 0.444444 0.181818 0.444444 0.363636 0.444444 0.545455 0.444444 0.727273 0.444444 1 0.333333 0.969697 0.444444 0.909091 0.444444 0.969697 0.444444 0.939394 0.555556 0.969697 0.444444 0.939394 0.555556 0.909091 0.666667 0.939394 0.555556</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="171" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="initialShadingGroup" count="180">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 0 1 2 2 3 3 1 0 4 4 4 4 2 2 5 5 2 2 4 4 1 0 6 6 3 3 7 7 7 7 4 4 8 8 8 8 5 5 9 9 4 4 7 7 3 3 5 5 8 8 4 4 10 10 0 11 1 12 11 13 10 10 12 14 12 14 1 15 3 16 1 17 12 14 10 10 13 18 11 13 14 19 14 19 12 14 15 20 15 20 3 21 6 6 12 14 14 19 11 13 3 22 15 20 12 14 16 23 0 24 10 25 17 26 16 23 18 27 18 27 10 28 11 29 10 30 18 27 16 23 19 31 17 26 20 32 20 32 18 27 21 33 21 33 11 34 13 18 18 27 20 32 17 26 11 35 21 33 18 27 22 36 0 37 16 38 23 39 22 36 24 40 24 40 16 41 17 42 16 43 24 40 22 36 25 44 23 39 26 45 26 45 24 40 27 46 27 46 17 47 19 31 24 40 26 45 23 39 17 48 27 46 24 40 2 49 0 50 22 51 5 52 2 53 28 54 28 54 22 55 23 56 22 57 28 54 2 58 9 59 5 60 29 61 29 61 28 54 30 62 30 62 23 63 25 44 28 54 29 61 5 64 23 65 30 62 28 54 32 66 31 67 33 68 34 69 32 66 35 70 35 70 33 68 36 71 33 68 35 70 32 66 37 72 34 69 38 73 38 73 35 70 39 74 39 74 36 71 40 75 35 70 38 73 34 69 36 71 39 74 35 70 33 76 31 77 41 78 36 79 33 80 42 81 42 81 41 78 43 82 41 78 42 81 33 83 40 75 36 84 44 85 44 85 42 81 45 86 45 86 43 82 46 87 42 81 44 85 36 88 43 82 45 86 42 81 41 89 31 90 47 91 43 92 41 93 48 94 48 94 47 91 49 95 47 91 48 94 41 96 46 87 43 97 50 98 50 98 48 94 51 99 51 99 49 95 52 100 48 94 50 98 43 101 49 95 51 99 48 94 47 102 31 103 53 104 49 105 47 106 54 107 54 107 53 104 55 108 53 104 54 107 47 109 52 100 49 110 56 111 56 111 54 107 57 112 57 112 55 108 58 113 54 107 56 111 49 114 55 108 57 112 54 107 53 115 31 116 32 117 55 118 53 119 59 120 59 120 32 121 34 122 32 123 59 120 53 124 58 113 55 125 60 126 60 126 59 120 61 127 61 127 34 128 37 129 59 120 60 126 55 130 34 131 61 127 59 120 8 8 9 9 62 132 7 7 8 8 63 133 63 133 62 132 64 134 62 132 63 133 8 8 6 6 7 7 65 135 65 135 63 133 66 136 66 136 64 134 37 72 63 133 65 135 7 7 64 134 66 136 63 133 15 20 6 6 67 137 14 19 15 20 68 138 68 138 67 137 69 139 67 137 68 138 15 20 13 18 14 19 70 140 70 140 68 138 71 141 71 141 69 139 40 75 68 138 70 140 14 19 69 139 71 141 68 138 21 33 13 18 72 142 20 32 21 33 73 143 73 143 72 142 74 144 72 142 73 143 21 33 19 31 20 32 75 145 75 145 73 143 76 146 76 146 74 144 46 87 73 143 75 145 20 32 74 144 76 146 73 143 27 46 19 31 77 147 26 45 27 46 78 148 78 148 77 147 79 149 77 147 78 148 27 46 25 44 26 45 80 150 80 150 78 148 81 151 81 151 79 149 52 100 78 148 80 150 26 45 79 149 81 151 78 148 30 62 25 44 82 152 29 61 30 62 83 153 83 153 82 152 84 154 82 152 83 153 30 62 9 155 29 61 85 156 85 156 83 153 86 157 86 157 84 154 58 113 83 153 85 156 29 61 84 154 86 157 83 153 39 74 40 75 69 139 38 73 39 74 87 158 87 158 69 139 67 137 69 139 87 158 39 74 37 72 38 73 66 136 66 136 87 158 65 135 65 135 67 137 6 6 87 158 66 136 38 73 67 137 65 135 87 158 45 86 46 87 74 144 44 85 45 86 88 159 88 159 74 144 72 142 74 144 88 159 45 86 40 75 44 85 71 141 71 141 88 159 70 140 70 140 72 142 13 18 88 159 71 141 44 85 72 142 70 140 88 159 51 99 52 100 79 149 50 98 51 99 89 160 89 160 79 149 77 147 79 149 89 160 51 99 46 87 50 98 76 146 76 146 89 160 75 145 75 145 77 147 19 31 89 160 76 146 50 98 77 147 75 145 89 160 57 112 58 113 84 154 56 111 57 112 90 161 90 161 84 154 82 152 84 154 90 161 57 112 52 100 56 111 81 151 81 151 90 161 80 150 80 150 82 152 25 44 90 161 81 151 56 111 82 152 80 150 90 161 61 127 37 162 64 163 60 126 61 127 91 164 91 164 64 165 62 166 64 167 91 164 61 127 58 113 60 126 86 157 86 157 91 164 85 156 85 156 62 168 9 169 91 164 86 157 60 126 62 170 85 156 91 164</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Sphere-medium">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="initialShadingGroup" target="#lambert1"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Spheres/Sphere-planerUVprojection.dae b/Studio/Content/Models Library/Primitives/Spheres/Sphere-planerUVprojection.dae
new file mode 100644
index 00000000..fe6c0965
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Spheres/Sphere-planerUVprojection.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Documents%20and%20Settings/jgiles/My%20Documents/maya/projects/default/untitled</source_data>
+ </contributor>
+ <created>2008-10-21T18:16:28Z</created>
+ <modified>2008-10-21T18:16:28Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="spherePlanerProjection" name="spherePlanerProjection">
+ <instance_effect url="#spherePlanerProjection-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="spherePlanerProjection-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0.2 0.2 0.2 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Sphere" name="Sphere">
+ <mesh>
+ <source id="Sphere-positions" name="position">
+ <float_array id="Sphere-positions-array" count="486">0 50 0 12.9946 48.0969 4.2222 0 48.0969 13.6633 25 42.5325 8.12299 13.1433 44.7214 18.0902 0 42.5325 26.2866 35.1023 33.7304 11.4054 26.2866 36.1803 22.3607 13.1433 36.1803 31.9098 0 33.7304 36.9088 42.5325 22.3607 13.8197 35.1023 25.286 25.0688 25 26.2866 34.4095 12.9946 25.286 41.131 0 22.3607 44.7214 8.0311 48.0969 -11.0539 15.4509 42.5325 -21.2663 21.2663 44.7214 -6.90983 21.6944 33.7304 -29.8598 29.3893 36.1803 -18.0902 34.4095 36.1803 -2.63932 26.2866 22.3607 -36.1803 34.689 25.286 -25.6376 40.4509 26.2866 -13.1433 43.1334 25.286 0.351573 -8.0311 48.0969 -11.0539 -15.4509 42.5325 -21.2663 0 44.7214 -22.3607 -21.6944 33.7304 -29.8598 -8.12299 36.1803 -33.541 8.12299 36.1803 -33.541 -26.2866 22.3607 -36.1803 -13.6633 25.286 -40.9137 0 26.2866 -42.5325 13.6633 25.286 -40.9137 -12.9946 48.0969 4.2222 -25 42.5325 8.12299 -21.2663 44.7214 -6.90983 -35.1023 33.7304 11.4054 -34.4095 36.1803 -2.63932 -29.3893 36.1803 -18.0902 -42.5325 22.3607 13.8197 -43.1334 25.286 0.351573 -40.4509 26.2866 -13.1433 -34.689 25.286 -25.6376 -13.1433 44.7214 18.0902 -13.1433 36.1803 31.9098 -26.2866 36.1803 22.3607 -12.9946 25.286 41.131 -25 26.2866 34.4095 -35.1023 25.286 25.0688 0 -50 0 8.0311 -48.0969 11.0539 12.9946 -48.0969 -4.2222 15.4509 -42.5325 21.2663 21.2663 -44.7214 6.90983 25 -42.5325 -8.12299 21.6944 -33.7304 29.8598 29.3893 -36.1803 18.0902 34.4095 -36.1803 2.63932 35.1023 -33.7304 -11.4054 26.2866 -22.3607 36.1803 34.689 -25.286 25.6376 40.4509 -26.2866 13.1433 43.1334 -25.286 -0.351573 42.5325 -22.3607 -13.8197 0 -48.0969 -13.6633 13.1433 -44.7214 -18.0902 0 -42.5325 -26.2866 26.2866 -36.1803 -22.3607 13.1433 -36.1803 -31.9098 0 -33.7304 -36.9088 35.1023 -25.286 -25.0688 25 -26.2866 -34.4095 12.9946 -25.286 -41.131 0 -22.3607 -44.7214 -12.9946 -48.0969 -4.2222 -13.1433 -44.7214 -18.0902 -25 -42.5325 -8.12299 -13.1433 -36.1803 -31.9098 -26.2866 -36.1803 -22.3607 -35.1023 -33.7304 -11.4054 -12.9946 -25.286 -41.131 -25 -26.2866 -34.4095 -35.1023 -25.286 -25.0688 -42.5325 -22.3607 -13.8197 -8.0311 -48.0969 11.0539 -21.2663 -44.7214 6.90983 -15.4509 -42.5325 21.2663 -34.4095 -36.1803 2.63932 -29.3893 -36.1803 18.0902 -21.6944 -33.7304 29.8598 -43.1334 -25.286 -0.351573 -40.4509 -26.2866 13.1433 -34.689 -25.286 25.6376 -26.2866 -22.3607 36.1803 0 -44.7214 22.3607 -8.12299 -36.1803 33.541 8.12299 -36.1803 33.541 -13.6633 -25.286 40.9137 0 -26.2866 42.5325 13.6633 -25.286 40.9137 8.0311 11.6227 47.9626 21.2663 13.8197 43.0902 15.4509 0 47.5528 34.4095 13.8197 33.541 29.3893 0 40.4509 21.6944 -11.6227 43.5231 43.1334 11.6227 22.4593 40.4509 0 29.3893 34.689 -11.6227 34.082 48.0969 11.6227 7.18324 47.5528 13.8197 -6.90983 50 0 0 42.5325 13.8197 -22.3607 47.5528 0 -15.4509 48.0969 -11.6227 -7.18324 34.689 11.6227 -34.082 40.4509 0 -29.3893 43.1334 -11.6227 -22.4593 21.6944 11.6227 -43.5231 8.12299 13.8197 -47.3607 15.4509 0 -47.5528 -8.12299 13.8197 -47.3607 0 0 -50 8.0311 -11.6227 -47.9626 -21.6944 11.6227 -43.5231 -15.4509 0 -47.5528 -8.0311 -11.6227 -47.9626 -34.689 11.6227 -34.082 -42.5325 13.8197 -22.3607 -40.4509 0 -29.3893 -47.5528 13.8197 -6.90983 -47.5528 0 -15.4509 -43.1334 -11.6227 -22.4593 -48.0969 11.6227 7.18324 -50 0 0 -48.0969 -11.6227 -7.18324 -43.1334 11.6227 22.4593 -34.4095 13.8197 33.541 -40.4509 0 29.3893 -21.2663 13.8197 43.0902 -29.3893 0 40.4509 -34.689 -11.6227 34.082 -8.0311 11.6227 47.9626 -15.4509 0 47.5528 -21.6944 -11.6227 43.5231 47.5528 -13.8197 6.90983 42.5325 -13.8197 22.3607 47.5528 0 15.4509 21.2663 -13.8197 -43.0902 34.4095 -13.8197 -33.541 29.3893 0 -40.4509 -34.4095 -13.8197 -33.541 -21.2663 -13.8197 -43.0902 -29.3893 0 -40.4509 -42.5325 -13.8197 22.3607 -47.5528 -13.8197 6.90983 -47.5528 0 15.4509 8.12299 -13.8197 47.3607 -8.12299 -13.8197 47.3607 0 0 50</float_array>
+ <technique_common>
+ <accessor source="#Sphere-positions-array" count="162" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-normals" name="normal">
+ <float_array id="Sphere-normals-array" count="486">0 1 0 0.247736 0.965478 0.080494 0 0.965478 0.260485 0.5 0.850651 0.16246 0.269751 0.888474 0.37128 0 0.850651 0.525731 0.710494 0.664759 0.230853 0.514508 0.729421 0.450807 0.269751 0.729421 0.628633 0 0.66476 0.747057 0.850651 0.447214 0.276393 0.710494 0.503771 0.491338 0.5 0.525731 0.688191 0.247736 0.503771 0.827552 0 0.447214 0.894427 0.153109 0.965478 -0.210737 0.309017 0.850651 -0.425326 0.436466 0.888474 -0.141816 0.439109 0.66476 -0.604382 0.587735 0.729421 -0.35002 0.681224 0.729421 -0.062289 0.525731 0.447214 -0.723607 0.686845 0.503771 -0.523888 0.809017 0.525731 -0.262865 0.863603 0.503771 0.020116 -0.153109 0.965478 -0.210737 -0.309017 0.850651 -0.425326 0 0.888474 -0.458928 -0.439109 0.66476 -0.604382 -0.151268 0.729421 -0.667131 0.151268 0.729421 -0.667131 -0.525731 0.447214 -0.723607 -0.286 0.503771 -0.815119 0 0.525731 -0.850651 0.286 0.503771 -0.815119 -0.247736 0.965478 0.080494 -0.5 0.850651 0.16246 -0.436466 0.888474 -0.141816 -0.710494 0.66476 0.230853 -0.681224 0.729421 -0.062289 -0.587735 0.729421 -0.35002 -0.850651 0.447214 0.276393 -0.863603 0.503771 0.020116 -0.809017 0.525731 -0.262865 -0.686845 0.503771 -0.523888 -0.269751 0.888474 0.37128 -0.269751 0.729421 0.628633 -0.514508 0.729421 0.450807 -0.247736 0.503771 0.827552 -0.5 0.525731 0.688191 -0.710494 0.503771 0.491338 0 -1 0 0.153109 -0.965478 0.210737 0.247736 -0.965478 -0.080494 0.309017 -0.850651 0.425326 0.436466 -0.888474 0.141816 0.5 -0.850651 -0.16246 0.439109 -0.66476 0.604382 0.587735 -0.729421 0.35002 0.681224 -0.729421 0.062289 0.710494 -0.66476 -0.230853 0.525731 -0.447214 0.723607 0.686845 -0.503771 0.523888 0.809017 -0.525731 0.262865 0.863603 -0.503771 -0.020116 0.850651 -0.447214 -0.276393 0 -0.965478 -0.260485 0.269751 -0.888474 -0.37128 0 -0.850651 -0.525731 0.514508 -0.729421 -0.450807 0.269751 -0.729421 -0.628633 0 -0.66476 -0.747057 0.710494 -0.503771 -0.491338 0.5 -0.525731 -0.688191 0.247736 -0.503771 -0.827552 0 -0.447214 -0.894427 -0.247736 -0.965478 -0.080494 -0.269751 -0.888474 -0.37128 -0.5 -0.850651 -0.16246 -0.269751 -0.729421 -0.628633 -0.514508 -0.729421 -0.450807 -0.710494 -0.664759 -0.230853 -0.247736 -0.503771 -0.827552 -0.5 -0.525731 -0.688191 -0.710494 -0.503771 -0.491338 -0.850651 -0.447214 -0.276393 -0.153109 -0.965478 0.210737 -0.436466 -0.888474 0.141816 -0.309017 -0.850651 0.425326 -0.681224 -0.729421 0.062289 -0.587735 -0.729421 0.35002 -0.439109 -0.66476 0.604382 -0.863603 -0.503771 -0.020116 -0.809017 -0.525731 0.262865 -0.686845 -0.503771 0.523888 -0.525731 -0.447214 0.723607 0 -0.888474 0.458928 -0.151268 -0.729421 0.667131 0.151268 -0.729421 0.667131 -0.286 -0.503771 0.815119 0 -0.525731 0.850651 0.286 -0.503771 0.815119 0.153109 0.243286 0.957794 0.436466 0.270493 0.858097 0.309017 0 0.951057 0.681224 0.270493 0.680271 0.587735 0.013139 0.808947 0.439109 -0.243286 0.864867 0.863603 0.243286 0.44159 0.809017 0.000000 0.587785 0.686845 -0.243286 0.684876 0.95823 0.243286 0.150359 0.950974 0.270493 -0.149937 1 0 0 0.857485 0.270493 -0.437667 0.950975 0.01314 -0.30899 0.95823 -0.243286 -0.150359 0.686845 0.243286 -0.684876 0.809017 -0.000000 -0.587785 0.863603 -0.243286 -0.44159 0.439109 0.243286 -0.864867 0.151268 0.270493 -0.950764 0.309017 0 -0.951057 -0.151268 0.270493 -0.950764 0 0.013139 -0.999914 0.153109 -0.243286 -0.957794 -0.439109 0.243286 -0.864867 -0.309017 0 -0.951057 -0.153109 -0.243286 -0.957794 -0.686845 0.243286 -0.684876 -0.857485 0.270493 -0.437667 -0.809017 -0.000000 -0.587785 -0.950974 0.270493 -0.149937 -0.950975 0.01314 -0.30899 -0.863603 -0.243286 -0.44159 -0.95823 0.243286 0.150359 -1 0 0 -0.95823 -0.243286 -0.150359 -0.863603 0.243286 0.44159 -0.681224 0.270493 0.680271 -0.809017 0.000000 0.587785 -0.436466 0.270493 0.858097 -0.587735 0.013139 0.808947 -0.686845 -0.243286 0.684876 -0.153109 0.243286 0.957794 -0.309017 0 0.951057 -0.439109 -0.243286 0.864867 0.950974 -0.270493 0.149937 0.857485 -0.270493 0.437667 0.950975 -0.01314 0.30899 0.436466 -0.270493 -0.858097 0.681224 -0.270493 -0.680271 0.587735 -0.013139 -0.808947 -0.681224 -0.270493 -0.680271 -0.436466 -0.270493 -0.858097 -0.587735 -0.013139 -0.808947 -0.857485 -0.270493 0.437667 -0.950974 -0.270493 0.149937 -0.950975 -0.01314 0.30899 0.151268 -0.270493 0.950764 -0.151268 -0.270493 0.950764 0 -0.013139 0.999914</float_array>
+ <technique_common>
+ <accessor source="#Sphere-normals-array" count="162" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Sphere-Texture" name="Texture">
+ <float_array id="Sphere-Texture-array" count="306">0.629946 0.980969 0.5 1 0.5 0.980969 0.75 0.925325 0.631433 0.947214 0.5 0.925325 0.851023 0.837304 0.762866 0.861803 0.631433 0.861803 0.5 0.837304 0.925325 0.723607 0.851023 0.75286 0.75 0.762866 0.629946 0.75286 0.5 0.723607 0.580311 0.980969 0.654508 0.925325 0.712663 0.947214 0.716944 0.837304 0.793893 0.861803 0.844095 0.861803 0.762866 0.723607 0.84689 0.75286 0.904508 0.762866 0.931334 0.75286 0.419689 0.980969 0.345491 0.925325 0.5 0.947214 0.283056 0.837304 0.41877 0.861803 0.58123 0.861803 0.237134 0.723607 0.363367 0.75286 0.5 0.762866 0.636633 0.75286 0.370054 0.980969 0.25 0.925325 0.287337 0.947214 0.148977 0.837304 0.155905 0.861803 0.206107 0.861803 0.074674 0.723607 0.068665 0.75286 0.095491 0.762866 0.15311 0.75286 0.368567 0.947214 0.368567 0.861803 0.237134 0.861803 0.370054 0.75286 0.25 0.762866 0.148977 0.75286 0.580311 0.01903 0.5 0 0.629946 0.01903 0.654508 0.074674 0.712663 0.052786 0.75 0.074674 0.716944 0.162696 0.793893 0.138197 0.844095 0.138197 0.851023 0.162696 0.762866 0.276393 0.84689 0.24714 0.904508 0.237134 0.931334 0.24714 0.925325 0.276393 0.5 0.01903 0.631433 0.052786 0.5 0.074674 0.762866 0.138197 0.631433 0.138197 0.5 0.162696 0.851023 0.24714 0.75 0.237134 0.629946 0.24714 0.5 0.276393 0.370054 0.01903 0.368567 0.052786 0.25 0.074674 0.368567 0.138197 0.237134 0.138197 0.148977 0.162696 0.370054 0.24714 0.25 0.237134 0.148977 0.24714 0.074674 0.276393 0.419689 0.01903 0.287337 0.052786 0.345491 0.074674 0.155905 0.138197 0.206107 0.138197 0.283056 0.162696 0.068665 0.24714 0.095491 0.237134 0.15311 0.24714 0.237134 0.276393 0.5 0.052786 0.41877 0.138197 0.58123 0.138197 0.363367 0.24714 0.5 0.237134 0.636633 0.24714 0.580311 0.616227 0.712663 0.638197 0.654508 0.5 0.844095 0.638197 0.793893 0.5 0.716944 0.383773 0.931334 0.616227 0.904508 0.5 0.84689 0.383773 0.980969 0.616227 0.975528 0.638197 1 0.5 0.925325 0.638197 0.975528 0.5 0.980969 0.383773 0.84689 0.616227 0.931334 0.383773 0.716944 0.616227 0.58123 0.638197 0.41877 0.638197 0.5 0.5 0.580311 0.383773 0.283056 0.616227 0.345491 0.5 0.419689 0.383773 0.15311 0.616227 0.074674 0.638197 0.095491 0.5 0.024471 0.638197 0.024471 0.5 0.068665 0.383773 0.01903 0.616227 0 0.5 0.01903 0.383773 0.068665 0.616227 0.155905 0.638197 0.287337 0.638197 0.206107 0.5 0.15311 0.383773 0.419689 0.616227 0.283056 0.383773 0.975528 0.361803 0.925325 0.361803 0.712663 0.361803 0.844095 0.361803 0.155905 0.361803 0.287337 0.361803 0.074674 0.361803 0.024471 0.361803 0.58123 0.361803 0.41877 0.361803</float_array>
+ <technique_common>
+ <accessor source="#Sphere-Texture-array" count="153" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Sphere-vertices">
+ <input semantic="POSITION" source="#Sphere-positions"/>
+ <input semantic="NORMAL" source="#Sphere-normals"/>
+ </vertices>
+ <triangles material="SphereSG" count="320">
+ <input semantic="VERTEX" source="#Sphere-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Sphere-Texture" offset="1" set="1"/>
+ <p>1 0 0 1 2 2 3 3 1 0 4 4 4 4 2 2 5 5 2 2 4 4 1 0 6 6 3 3 7 7 7 7 4 4 8 8 8 8 5 5 9 9 4 4 7 7 3 3 5 5 8 8 4 4 10 10 6 6 11 11 11 11 7 7 12 12 12 12 8 8 13 13 13 13 9 9 14 14 7 7 11 11 6 6 8 8 12 12 7 7 9 9 13 13 8 8 15 15 0 1 1 0 16 16 15 15 17 17 17 17 1 0 3 3 1 0 17 17 15 15 18 18 16 16 19 19 19 19 17 17 20 20 20 20 3 3 6 6 17 17 19 19 16 16 3 3 20 20 17 17 21 21 18 18 22 22 22 22 19 19 23 23 23 23 20 20 24 24 24 24 6 6 10 10 19 19 22 22 18 18 20 20 23 23 19 19 6 6 24 24 20 20 25 25 0 1 15 15 26 26 25 25 27 27 27 27 15 15 16 16 15 15 27 27 25 25 28 28 26 26 29 29 29 29 27 27 30 30 30 30 16 16 18 18 27 27 29 29 26 26 16 16 30 30 27 27 31 31 28 28 32 32 32 32 29 29 33 33 33 33 30 30 34 34 34 34 18 18 21 21 29 29 32 32 28 28 30 30 33 33 29 29 18 18 34 34 30 30 35 35 0 1 25 25 36 36 35 35 37 37 37 37 25 25 26 26 25 25 37 37 35 35 38 38 36 36 39 39 39 39 37 37 40 40 40 40 26 26 28 28 37 37 39 39 36 36 26 26 40 40 37 37 41 41 38 38 42 42 42 42 39 39 43 43 43 43 40 40 44 44 44 44 28 28 31 31 39 39 42 42 38 38 40 40 43 43 39 39 28 28 44 44 40 40 2 2 0 1 35 35 5 5 2 2 45 45 45 45 35 35 36 36 35 35 45 45 2 2 9 9 5 5 46 46 46 46 45 45 47 47 47 47 36 36 38 38 45 45 46 46 5 5 36 36 47 47 45 45 14 14 9 9 48 48 48 48 46 46 49 49 49 49 47 47 50 50 50 50 38 38 41 41 46 46 48 48 9 9 47 47 49 49 46 46 38 38 50 50 47 47 52 51 51 52 53 53 54 54 52 51 55 55 55 55 53 53 56 56 53 53 55 55 52 51 57 57 54 54 58 58 58 58 55 55 59 59 59 59 56 56 60 60 55 55 58 58 54 54 56 56 59 59 55 55 61 61 57 57 62 62 62 62 58 58 63 63 63 63 59 59 64 64 64 64 60 60 65 65 58 58 62 62 57 57 59 59 63 63 58 58 60 60 64 64 59 59 53 53 51 52 66 66 56 56 53 53 67 67 67 67 66 66 68 68 66 66 67 67 53 53 60 60 56 56 69 69 69 69 67 67 70 70 70 70 68 68 71 71 67 67 69 69 56 56 68 68 70 70 67 67 65 65 60 60 72 72 72 72 69 69 73 73 73 73 70 70 74 74 74 74 71 71 75 75 69 69 72 72 60 60 70 70 73 73 69 69 71 71 74 74 70 70 66 66 51 52 76 76 68 68 66 66 77 77 77 77 76 76 78 78 76 76 77 77 66 66 71 71 68 68 79 79 79 79 77 77 80 80 80 80 78 78 81 81 77 77 79 79 68 68 78 78 80 80 77 77 75 75 71 71 82 82 82 82 79 79 83 83 83 83 80 80 84 84 84 84 81 81 85 85 79 79 82 82 71 71 80 80 83 83 79 79 81 81 84 84 80 80 76 76 51 52 86 86 78 78 76 76 87 87 87 87 86 86 88 88 86 86 87 87 76 76 81 81 78 78 89 89 89 89 87 87 90 90 90 90 88 88 91 91 87 87 89 89 78 78 88 88 90 90 87 87 85 85 81 81 92 92 92 92 89 89 93 93 93 93 90 90 94 94 94 94 91 91 95 95 89 89 92 92 81 81 90 90 93 93 89 89 91 91 94 94 90 90 86 86 51 52 52 51 88 88 86 86 96 96 96 96 52 51 54 54 52 51 96 96 86 86 91 91 88 88 97 97 97 97 96 96 98 98 98 98 54 54 57 57 96 96 97 97 88 88 54 54 98 98 96 96 95 95 91 91 99 99 99 99 97 97 100 100 100 100 98 98 101 101 101 101 57 57 61 61 97 97 99 99 91 91 98 98 100 100 97 97 57 57 101 101 98 98 13 13 14 14 102 102 12 12 13 13 103 103 103 103 102 102 104 104 102 102 103 103 13 13 11 11 12 12 105 105 105 105 103 103 106 106 106 106 104 104 107 107 103 103 105 105 12 12 104 104 106 106 103 103 10 10 11 11 108 108 108 108 105 105 109 109 109 109 106 106 110 110 110 110 107 107 61 61 105 105 108 108 11 11 106 106 109 109 105 105 107 107 110 110 106 106 24 24 10 10 111 111 23 23 24 24 112 112 112 112 111 111 113 113 111 111 112 112 24 24 22 22 23 23 114 114 114 114 112 112 115 115 115 115 113 113 116 116 112 112 114 114 23 23 113 113 115 115 112 112 21 21 22 22 117 117 117 117 114 114 118 109 118 109 115 115 119 118 119 118 116 116 65 65 114 114 117 117 22 22 115 115 118 109 114 114 116 116 119 118 115 115 34 34 21 21 120 119 33 33 34 34 121 120 121 120 120 119 122 104 120 119 121 120 34 34 32 32 33 33 123 121 123 121 121 120 124 122 124 122 122 104 125 123 121 120 123 121 33 33 122 104 124 122 121 120 31 31 32 32 126 124 126 124 123 121 127 125 127 125 124 122 128 126 128 126 125 123 75 75 123 121 126 124 32 32 124 122 127 125 123 121 125 123 128 126 124 122 44 44 31 31 129 127 43 43 44 44 130 128 130 128 129 127 131 129 129 127 130 128 44 44 42 42 43 43 132 130 132 130 130 128 133 131 133 131 131 129 134 132 130 128 132 130 43 43 131 129 133 131 130 128 41 41 42 42 135 133 135 133 132 130 136 134 136 134 133 131 137 135 137 135 134 132 85 85 132 130 135 133 42 42 133 131 136 134 132 130 134 132 137 135 133 131 50 50 41 41 138 136 49 49 50 50 139 137 139 137 138 136 140 129 138 136 139 137 50 50 48 48 49 49 141 138 141 138 139 137 142 139 142 139 140 129 143 140 139 137 141 138 49 49 140 129 142 139 139 137 14 14 48 48 144 141 144 141 141 138 145 125 145 125 142 139 146 142 146 142 143 140 95 95 141 138 144 141 48 48 142 139 145 125 141 138 143 140 146 142 142 139 64 64 65 65 116 116 63 63 64 64 147 143 147 143 116 116 113 113 116 116 147 143 64 64 62 62 63 63 148 144 148 144 147 143 149 115 149 115 113 113 111 111 147 143 148 144 63 63 113 113 149 115 147 143 61 61 62 62 110 110 110 110 148 144 109 109 109 109 149 115 108 108 108 108 111 111 10 10 148 144 110 110 62 62 149 115 109 109 148 144 111 111 108 108 149 115 74 74 75 75 125 123 73 73 74 74 150 145 150 145 125 123 122 104 125 123 150 145 74 74 72 72 73 73 151 146 151 146 150 145 152 106 152 106 122 104 120 119 150 145 151 146 73 73 122 104 152 106 150 145 65 65 72 72 119 118 119 118 151 146 118 109 118 109 152 106 117 117 117 117 120 119 21 21 151 146 119 118 72 72 152 106 118 109 151 146 120 119 117 117 152 106 84 84 85 85 134 132 83 83 84 84 153 147 153 147 134 132 131 129 134 132 153 147 84 84 82 82 83 83 154 148 154 148 153 147 155 139 155 139 131 129 129 127 153 147 154 148 83 83 131 129 155 139 153 147 75 75 82 82 128 126 128 126 154 148 127 125 127 125 155 139 126 124 126 124 129 127 31 31 154 148 128 126 82 82 155 139 127 125 154 148 129 127 126 124 155 139 94 94 95 95 143 140 93 93 94 94 156 149 156 149 143 140 140 129 143 140 156 149 94 94 92 92 93 93 157 150 157 150 156 149 158 131 158 131 140 129 138 136 156 149 157 150 93 93 140 129 158 131 156 149 85 85 92 92 137 135 137 135 157 150 136 134 136 134 158 131 135 133 135 133 138 136 41 41 157 150 137 135 92 92 158 131 136 134 157 150 138 136 135 133 158 131 101 101 61 61 107 107 100 100 101 101 159 151 159 151 107 107 104 104 107 107 159 151 101 101 99 99 100 100 160 152 160 152 159 151 161 122 161 122 104 104 102 102 159 151 160 152 100 100 104 104 161 122 159 151 95 95 99 99 146 142 146 142 160 152 145 125 145 125 161 122 144 141 144 141 102 102 14 14 160 152 146 142 99 99 161 122 145 125 160 152 102 102 144 141 161 122</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="untitled">
+ <node id="_Sphere" name="Sphere" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Sphere">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="SphereSG" target="#spherePlanerProjection"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-1.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-1.DAE
new file mode 100644
index 00000000..97666112
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-1.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-1.max</source_data>
+ </contributor>
+ <created>2008-10-31T15:58:11Z</created>
+ <modified>2008-10-31T15:58:26Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="4320">29.798338 -0.005190 15.656205 31.396685 -3.472341 19.151783 30.672070 -6.009082 23.605412 27.818653 -6.935693 27.823742 23.601004 -6.003891 30.676479 19.149239 -3.463352 31.399231 15.656206 0.005189 29.798340 14.057859 3.472340 26.302761 14.782473 6.009080 21.849134 17.635889 6.935693 17.630806 21.853535 6.003894 14.778067 26.305300 3.463356 14.055312 31.398304 1.638942 17.148842 33.119843 -1.148603 21.156437 32.486954 -2.943101 25.970390 29.669222 -3.263716 30.300808 25.421656 -2.024540 32.987358 20.882387 0.442389 33.310181 17.267710 3.476061 31.182777 15.546171 6.263606 27.175186 16.179056 8.058104 22.361231 18.996786 8.378720 18.030815 23.244350 7.139547 15.344261 27.783619 4.672618 15.021437 32.915474 3.736625 18.279196 34.847492 1.852942 22.696659 34.372246 0.945802 27.770727 31.617083 1.258272 32.141808 27.320242 2.706627 34.638672 22.633060 4.902780 34.592293 18.811462 7.258274 32.015095 16.879446 9.141957 27.597633 17.354687 10.049098 22.523567 20.109850 9.736629 18.152487 24.406689 8.288276 15.655617 29.093870 6.092123 15.701994 34.275383 6.367074 18.861647 36.470741 5.596050 23.485590 36.191425 5.696714 28.653450 33.512283 6.642095 32.980499 29.151186 8.178876 35.307312 24.276688 9.895280 35.010422 20.194906 11.331397 32.169376 17.999552 12.102421 27.545433 18.278864 12.001757 22.377575 20.958006 11.056377 18.050524 25.319099 9.519597 15.723707 30.193598 7.803193 16.020597 35.370987 9.556320 18.679157 37.807228 10.019417 23.222855 37.704590 11.177790 28.266918 35.090572 12.721052 32.459789 30.665604 14.235689 34.677998 25.615349 15.315855 34.327171 21.293018 15.672121 31.501318 18.856779 15.209024 26.957621 18.959415 14.050653 21.913559 21.573429 12.507390 17.720688 25.998396 10.992753 15.502477 31.048651 9.912586 15.853300 36.057991 13.256317 17.511818 38.632168 14.927196 21.680355 38.626736 17.085424 26.385347 36.043148 19.152706 30.366093 31.573677 20.575115 32.555958 26.415915 20.971516 32.368168 21.951880 20.235699 29.853043 19.377703 18.564821 25.684507 19.383133 16.406593 20.979517 21.966719 14.339313 16.998772 26.436186 12.916903 14.808905 31.593948 12.520498 14.996691 36.162621 17.336857 15.172624 38.734211 20.054415 18.749876 38.719170 23.059748 22.964453 36.121525 25.547581 26.687065 31.637312 26.851301 28.920238 26.468075 26.621580 29.065599 21.998905 24.919968 27.084198 19.427313 22.202412 23.506948 19.442354 19.197079 19.292372 22.039997 16.709246 15.569759 26.524208 15.405522 13.336582 31.693445 15.635244 13.191218 35.506596 21.572290 11.561490 37.945908 25.115690 14.440550 37.823685 28.777868 18.096836 35.172672 31.577545 21.550653 30.703203 32.764549 23.876553 25.612877 32.020828 24.451311 21.265635 29.545656 23.120922 18.826319 26.002260 20.241863 18.948542 22.340082 16.585577 21.599554 19.540403 13.131761 26.069017 18.353397 10.805860 31.159346 19.097116 10.231100 33.948502 25.653332 6.720037 36.156372 29.810152 8.874346 35.853962 33.951111 11.965617 33.122295 36.966633 15.165545 28.693323 38.048717 17.616713 23.753786 36.907417 18.662333 19.627228 33.848549 18.022232 17.419353 29.691725 15.867924 17.721764 25.550770 12.776653 20.453426 22.535246 9.576726 24.882397 21.453161 7.125555 29.821934 22.594458 6.079935 31.434988 29.218554 0.878888 33.336872 33.812801 2.317860 32.801880 38.287518 4.864546 29.973364 41.443710 7.836563 25.609222 42.435673 10.437560 20.878824 40.997616 11.970606 17.049673 37.514862 12.024919 15.147789 32.920612 10.585948 15.682779 28.445896 8.039264 18.511293 25.289705 5.067247 22.875433 24.297741 2.466248 27.605831 25.735796 0.933203 28.039013 31.924191 -5.547154 29.571203 36.813080 -4.808184 28.762089 41.506718 -2.780864 25.828470 44.747448 -0.008415 21.556408 45.666920 2.766289 17.090601 44.018761 4.799767 13.627653 40.244595 5.547151 12.095461 35.355709 4.808181 12.904573 30.662071 2.780863 15.838189 27.421339 0.008414 20.110250 26.501865 -2.766289 24.576059 28.150023 -4.799768 23.963612 33.522957 -12.025459 25.059511 38.581791 -11.979461 23.935650 43.398411 -10.452358 20.893166 46.682205 -7.853338 16.747288 47.553284 -4.878806 12.608905 45.778240 -2.325786 9.586888 41.832703 -0.878355 8.490987 36.773869 -0.924353 9.614846 31.957253 -2.451454 12.657330 28.673456 -5.050473 16.803205 27.802376 -8.025005 20.941591 29.577412 -10.578027 19.499128 33.921886 -18.023392 20.078209 39.024746 -18.671764 18.592186 43.872974 -17.631889 15.439236 47.167488 -15.182400 11.464190 48.025532 -11.979634 7.732161 46.217182 -8.881773 5.243139 42.226994 -6.718884 4.664058 37.124134 -6.070511 6.150080 32.275909 -7.110385 9.303028 28.981392 -9.559873 13.278072 28.123350 -12.762636 17.010103 29.931692 -15.860498 14.952111 33.188789 -23.123337 14.913963 38.188961 -24.461887 13.007593 42.967712 -23.892456 9.743811 46.244568 -21.567625 5.997143 47.141506 -18.110327 2.771508 45.418190 -14.446945 0.931211 41.536377 -11.559078 0.969357 36.536205 -10.220528 2.875726 31.757460 -10.789957 6.139508 28.480600 -13.114787 9.886174 27.583660 -16.572084 13.111811 29.306974 -20.235466 10.579253 31.510542 -27.086445 9.808814 36.227139 -29.075180 7.416893 40.815586 -28.934584 4.044401 44.046417 -26.702332 0.594997 45.053928 -22.976549 -2.007055 43.568165 -18.755562 -3.064538 39.987232 -15.170376 -2.294100 35.270638 -13.181642 0.097821 30.682188 -13.322235 3.470311 27.451357 -15.554486 6.919715 26.443840 -19.280266 9.521769 27.929604 -23.501253 6.544839 29.126806 -29.855762 4.939646 33.353615 -32.376144 2.010878 37.617512 -32.567055 -1.456703 40.775982 -30.377337 -4.533962 41.982716 -26.393723 -6.396350 40.914379 -21.683619 -6.544842 37.857216 -17.509096 -4.939650 33.630409 -14.988712 -2.010883 29.366514 -14.797799 1.456697 26.208044 -16.987516 4.533957 25.001307 -20.971128 6.396346 26.069645 -25.681232 2.920587 26.273342 -31.504322 0.440484 29.829641 -34.332176 -3.026275 33.657558 -34.683659 -6.550776 36.731411 -32.464592 -9.188629 38.227558 -28.269571 -10.233027 37.745110 -23.222652 -9.404122 35.413342 -18.676151 -6.924020 31.857044 -15.848299 -3.457262 28.029125 -15.496814 0.067238 24.955275 -17.715878 2.705093 23.459124 -21.910896 3.749492 23.941570 -26.957815 -0.291039 23.150927 -32.172245 -3.584448 25.959192 -35.011616 -7.512753 29.317226 -35.306511 -11.023368 32.325241 -32.977917 -13.175626 34.177242 -28.649776 -13.392831 34.376991 -23.481815 -11.616785 32.870964 -18.858782 -8.323378 30.062698 -16.019409 -4.395073 26.704666 -15.724512 -0.884459 23.696651 -18.053104 1.267801 21.844648 -22.381243 1.485008 21.644897 -27.549204 -3.128228 19.915319 -32.017403 -7.085955 22.039740 -34.589981 -11.334366 24.996786 -34.632359 -14.735103 27.994122 -32.133183 -16.376942 30.228611 -27.762102 -15.819952 31.101526 -22.690346 -13.213382 30.378969 -18.276890 -9.255656 28.254551 -15.704311 -5.007245 25.297504 -15.661932 -1.606508 22.300169 -18.161106 0.035333 20.065680 -22.532185 -0.521654 19.192762 -27.603939 -5.632783 16.686794 -31.184052 -10.072082 18.295391 -33.305363 -14.479108 20.990887 -32.977737 -17.673004 24.051025 -30.288967 -18.797968 26.655846 -25.959497 -17.552567 28.107384 -21.149414 -14.270504 28.016708 -17.147568 -9.831207 26.408113 -15.026257 -5.424181 23.712620 -15.353878 -2.230284 20.652479 -18.042648 -1.105318 18.047661 -22.372116 -2.350717 16.596119 -27.182199 -7.832913 13.555894 -29.798338 -12.586268 14.843616 -31.392799 -17.012020 17.427885 -30.665340 -19.924292 20.616247 -27.810883 -20.542742 23.554386 -23.594275 -18.701660 25.455025 -19.145355 -14.894361 25.808895 -15.656206 -10.141008 24.521173 -14.061743 -5.715257 21.936905 -14.789200 -2.802984 18.748543 -17.643658 -2.184530 15.810406 -21.860264 -4.025610 13.909765 -26.309183 -9.735031 10.587971 -27.974195 -14.669402 11.721512 -29.052155 -19.014959 14.313932 -27.961094 -21.607313 17.670597 -24.993362 -21.751844 20.892088 -20.944160 -19.409830 23.115211 -16.898472 -15.208808 23.744282 -13.940332 -10.274439 22.610741 -12.862375 -5.928882 20.018322 -13.953433 -3.336527 16.661659 -16.921162 -3.191991 13.440168 -20.970362 -5.534004 11.217043 -25.016052 -11.333332 7.821912 -25.820749 -16.354595 8.914133 -26.444366 -20.566629 11.586010 -25.060616 -22.840824 15.121614 -22.040276 -22.567812 18.573584 -18.192640 -19.820745 21.016966 -14.548684 -15.335700 21.797058 -12.084799 -10.314440 20.704838 -11.461182 -6.102405 18.032963 -12.844930 -3.828208 14.497360 -15.865270 -4.101217 11.045391 -19.712902 -6.848281 8.602007 -23.356859 -12.629478 5.268320 -23.440256 -17.678659 6.380333 -23.693466 -21.742285 9.160543 -22.095877 -23.731510 12.863996 -19.075554 -23.113321 16.498352 -15.441793 -20.053366 19.089790 -12.168258 -15.371554 19.943937 -10.132090 -10.322374 18.831924 -9.878878 -6.258749 16.051716 -11.476468 -4.269523 12.348266 -14.496789 -4.887707 8.713909 -18.130548 -7.947661 6.122469 -21.404083 -13.639122 2.917055 -20.920912 -18.685339 4.070110 -20.888077 -22.612785 6.957346 -19.146250 -24.369104 10.805131 -16.162157 -23.483692 14.582453 -12.735379 -20.193794 17.277182 -9.784122 -15.380938 18.167269 -8.099169 -10.334722 17.014215 -8.132005 -6.407275 14.126981 -9.873828 -4.650954 10.279197 -12.857922 -5.536363 6.501875 -16.284698 -8.826259 3.807144 -19.235956 -14.390182 0.746928 -18.332632 -19.421907 1.937199 -18.087826 -23.240641 4.912662 -16.255119 -24.823158 8.876041 -13.325584 -23.745426 12.765358 -10.084189 -20.296221 15.538467 -7.399465 -15.399755 16.452320 -5.990776 -10.368032 15.262052 -6.235583 -6.549297 12.286591 -8.068289 -4.966777 8.323212 -10.997821 -6.044507 4.433896 -14.239214 -9.493711 1.660785 -16.923943 -14.923439 -1.270719 -15.722205 -19.940144 -0.059334 -15.322033 -23.681408 2.978921 -13.433416 -25.144760 7.029950 -10.562408 -23.938097 11.008282 -7.478292 -20.384747 13.847925 -5.007458 -15.436823 14.788001 -3.811959 -10.420119 13.576618 -4.212131 -6.678855 10.538364 -6.100747 -5.215501 6.487337 -8.971753 -6.422159 2.509006 -12.055868 -9.975509 -0.330640 -14.526705 -15.276306 -3.160922 -13.123853 -20.282560 -1.949135 -12.610126 -23.976316 1.124307 -10.685279 -25.367836 5.235878 -7.865071 -24.084261 9.283888 -4.905176 -20.469528 12.183672 -2.598695 -15.492199 13.158240 -1.563647 -10.485946 11.946455 -2.077373 -6.792189 8.873014 -4.002219 -5.400668 4.761444 -6.822426 -6.684238 0.713435 -9.782320 -10.298970 -2.186352 -12.088802 -15.489143 -4.950829 -10.554756 -20.490181 -3.757617 -9.954102 -24.159718 -0.673565 -8.000116 -25.514500 3.474957 -5.216369 -24.191519 7.576356 -2.348763 -20.545265 10.531666 -0.165672 -15.552750 11.549015 0.747949 -10.551712 10.355804 0.147295 -6.882176 7.271754 -1.806690 -5.527391 3.123233 -4.590436 -6.850369 -0.978167 -7.458041 -10.496621 -3.933478 -9.641133 -15.595454 -6.663393 -8.026957 -20.595238 -5.504448 -7.353207 -24.256395 -2.431267 -5.366652 -25.597923 1.732695 -2.599588 -24.260361 5.871707 0.206553 -20.602108 8.876723 2.299867 -15.603388 9.942554 3.119453 -10.603606 8.783611 2.445704 -6.942447 5.710432 0.459150 -5.600917 1.546471 -2.307914 -6.938477 -2.592541 -5.114054 -10.596728 -5.597559 -7.207369 -15.624999 -8.320971 -5.546305 -20.624998 -7.206468 -4.802797 -24.285254 -4.160995 -2.772391 -25.625000 -0.000581 0.000866 -24.285254 4.159993 2.773884 -20.625002 7.205904 4.803633 -15.625003 8.321005 5.546246 -10.625004 7.206504 4.802739 -6.964748 4.161032 2.772334 -5.625000 0.000620 -0.000923 -6.964742 -4.159954 -2.773940 -10.624993 -7.205867 -4.803691 -15.603543 -9.942065 -3.120182 -20.602221 -8.876910 -2.299463 -24.260405 -5.872509 -0.205137 -25.597883 -1.733890 2.601622 -24.256283 2.430009 5.368745 -20.595085 5.503473 7.354784 -15.595304 6.662972 8.027583 -10.596626 5.597819 7.206865 -6.938442 2.593421 5.112540 -5.600961 -1.545198 2.305782 -6.942558 -5.709097 -0.461341 -10.603755 -8.782563 -2.447382 -15.553334 -11.548116 -0.749250 -20.545729 -10.531341 0.165675 -24.191738 -7.576682 2.350058 -25.514414 -3.475837 5.218597 -24.159351 0.672376 8.002667 -20.489635 3.756446 9.956282 -15.488564 4.950000 10.555969 -10.496171 3.933227 9.641045 -6.850162 0.978570 7.456663 -5.527482 -3.122274 4.588125 -6.882542 -7.270487 1.804054 -10.552257 -10.354559 -0.149560 -15.493553 -13.156838 1.561694 -20.470613 -12.182793 2.598527 -24.084789 -9.283756 4.906825 -25.367662 -5.236521 7.868082 -23.975491 -1.125540 10.688829 -20.281305 1.947649 12.613253 -15.274960 3.159593 13.125703 -10.297900 2.185549 12.088871 -6.683724 -0.713487 9.780574 -5.400848 -4.760721 6.819319 -6.793016 -8.871700 3.998570 -10.487201 -11.944893 2.074146 -15.439208 -14.786095 3.809488 -20.386648 -13.846434 5.007315 -23.939009 -11.007595 7.480504 -25.144432 -7.030242 10.566363 -23.679932 -2.980103 13.438042 -19.937920 0.057589 15.326073 -14.921061 1.268890 15.724562 -9.973621 0.329231 14.526735 -6.421262 -2.509607 12.053549 -5.215835 -6.486959 8.967690 -6.680331 -10.537098 6.096012 -10.422343 -13.574791 4.207979 -15.403617 -16.449736 5.987804 -20.299295 -15.535939 7.399270 -23.746891 -12.763553 10.086812 -24.822622 -8.875435 13.330306 -23.238249 -4.913403 16.260662 -19.418303 -1.939080 18.092691 -14.386335 -0.749434 18.335505 -9.490659 -1.663229 16.924042 -6.043063 -4.435613 14.236501 -4.967330 -8.323730 10.993006 -6.551699 -12.285763 8.062651 -10.371643 -15.260086 6.230618 -15.386561 -18.163895 8.095926 -20.198053 -17.274187 9.784978 -23.485445 -14.580626 12.740093 -24.367884 -10.804952 16.169451 -22.608921 -6.958851 19.154160 -18.679871 -4.072886 20.894466 -13.633516 -2.920345 20.924059 -8.822026 -3.810051 19.235008 -5.534634 -6.503611 16.279894 -4.652193 -10.279284 12.850536 -6.411152 -14.125385 9.865829 -10.340201 -17.011353 8.125521 -15.378310 -19.940105 10.129260 -20.058220 -19.086521 12.170035 -23.114977 -16.496510 15.447687 -23.729523 -12.864063 19.083971 -21.737194 -9.162489 22.104551 -17.671833 -6.383625 23.700062 -12.622748 -5.272062 23.442989 -7.942839 -6.125645 21.402218 -4.886082 -8.715654 18.124567 -4.271533 -12.348101 14.488281 -6.263858 -16.049675 11.467702 -10.329219 -18.828541 9.872189 -15.343148 -21.792896 12.082738 -19.825615 -21.014008 14.551692 -22.568802 -18.572609 18.199902 -22.837673 -15.122873 22.049828 -20.560184 -11.589151 25.069891 -16.346590 -8.918303 26.450863 -11.325915 -7.825978 25.822720 -6.843448 -8.604865 23.353765 -4.100260 -11.046261 19.705559 -3.831387 -14.495997 15.855632 -6.108872 -18.029718 12.835569 -10.322467 -20.700569 11.454594 -15.218573 -23.738758 13.938974 -19.415474 -23.112019 16.903454 -21.751862 -20.892071 20.954138 -21.601702 -17.673744 25.005648 -19.005228 -14.319386 27.972385 -14.658168 -11.727798 29.059418 -9.725308 -10.593390 27.975473 -5.528407 -11.220129 25.010998 -3.192019 -13.440077 20.960314 -3.342177 -16.658401 16.908804 -5.938647 -20.012760 13.942064 -10.285707 -22.604351 12.855030 -14.904174 -25.803188 15.656172 -18.705839 -25.453775 19.151909 -20.540174 -23.557909 23.605652 -19.915670 -20.623589 27.824024 -16.999664 -17.437059 30.676718 -12.573496 -14.852152 31.399353 -7.823155 -13.561488 29.798304 -4.021490 -13.910901 26.302570 -2.187153 -15.806767 21.848827 -2.811655 -18.741087 17.630455 -5.727659 -21.927614 14.777760 -10.153826 -24.512524 14.055120 -14.279753 -28.011177 17.148804 -17.554651 -28.108269 21.156364 -18.792339 -26.662888 25.970295 -17.661179 -24.062325 30.300705 -14.464264 -21.003399 32.987270 -10.058206 -18.305748 33.310123 -5.623603 -16.692204 31.182758 -2.348704 -16.595114 27.175201 -1.111014 -18.040491 22.361271 -2.242173 -20.641054 18.030861 -5.439086 -23.699978 15.344293 -9.845144 -26.397631 15.021437 -13.222122 -30.373669 18.279278 -15.819350 -31.104956 22.696806 -16.367168 -30.239836 27.770893 -14.718791 -28.010113 32.141949 -11.315896 -25.013243 34.638744 -7.070291 -22.052233 34.592270 -3.119578 -19.920483 32.014980 -0.522350 -19.189194 27.597454 0.025470 -20.054314 22.523367 -1.622906 -22.284037 18.152313 -5.025798 -25.280905 15.655514 -9.271404 -28.241917 15.701984 -11.622940 -32.867275 18.861326 -13.388689 -34.382896 23.485172 -13.162313 -34.191143 28.653044 -11.004466 -32.343388 32.980217 -7.493344 -29.334740 35.307224 -3.569749 -25.971365 35.010555 -0.285004 -23.154472 32.169697 1.480745 -21.638851 27.545853 1.254370 -21.830606 22.377983 -0.903475 -23.678358 18.050810 -4.414595 -26.687002 15.723795 -8.338190 -30.050379 16.020462 -9.408913 -35.410622 18.678814 -10.226686 -37.751522 23.222637 -9.172878 -38.241367 28.266886 -6.529854 -36.748894 32.459961 -3.005809 -33.674015 34.678329 0.454989 -29.840645 34.327579 2.925225 -26.275921 31.501698 3.743000 -23.935019 26.957872 2.689193 -23.445175 21.913624 0.046170 -24.937645 17.720551 -3.477874 -28.012520 15.502180 -6.938673 -31.845894 15.852926 -6.549235 -37.855000 17.512192 -6.388803 -40.920033 21.680498 -4.516522 -41.994713 26.385235 -1.434068 -40.791080 30.365770 2.032618 -37.631653 32.555527 4.954639 -33.362995 32.367760 6.549044 -29.128887 29.852777 6.388613 -26.063858 25.684471 4.516333 -24.989176 20.979736 1.433880 -26.192804 16.999201 -2.032805 -29.352228 14.809442 -4.954827 -33.620888 14.997208 -3.067703 -39.985950 15.173099 -1.999528 -43.572010 18.749979 0.611169 -45.061859 22.964186 4.064856 -44.056290 26.686523 7.436118 -40.824745 28.919598 9.821630 -36.233112 29.065054 10.582195 -31.511715 27.083920 9.514022 -27.925655 23.507042 6.903326 -26.435802 19.292835 3.449641 -27.441374 15.570498 0.078378 -30.672916 13.337423 -2.307135 -35.264549 13.191963 0.929404 -41.535904 11.560925 2.778284 -45.420078 14.440116 6.010653 -47.145245 18.096687 9.760400 -46.249146 21.550861 13.022783 -42.971889 23.877098 14.923650 -38.191616 24.452080 14.953666 -33.189194 23.121746 13.104787 -29.305019 20.242558 9.872419 -27.579853 16.585987 6.122673 -28.475950 13.131811 2.860289 -31.753201 10.805574 0.959420 -36.533470 10.230589 5.242403 -42.226944 6.719768 7.738253 -46.217419 8.874240 11.475444 -48.025990 11.965745 15.452598 -47.168049 15.165916 18.604040 -43.873478 17.617271 20.085344 -39.025059 18.662971 19.499596 -33.921921 18.022820 17.003748 -29.931444 15.868350 13.266559 -28.122873 12.776846 9.289405 -28.980814 9.576674 6.137961 -32.275383 7.125319 4.656655 -37.123798 6.079618 9.586010 -41.832882 0.879621 12.613850 -45.777077 2.318518 16.756697 -47.551098 4.865005 20.904478 -46.679588 7.836756 23.945801 -43.396072 10.437490 25.065742 -38.580372 11.970344 23.964218 -33.522839 12.024591 20.936380 -29.578644 10.585695 16.793535 -27.804626 8.039209 12.645753 -28.676130 5.067459 9.604430 -31.959642 2.466724 8.484486 -36.775345 0.933869 13.627075 -40.244926 -5.546140 17.094902 -44.016277 -4.807204 21.564405 -45.662300 -2.780122 25.837984 -44.741951 -0.008049 28.770538 -41.501839 2.766242 29.576292 -36.810139 4.799380 28.039345 -31.923996 5.546588 24.571522 -28.152649 4.807654 20.102018 -26.506620 2.780573 15.828439 -27.426968 0.008500 12.895883 -30.667082 -2.765790 12.090126 -35.358776 -4.798930 17.050053 -37.514427 -12.025733 20.883198 -40.992905 -11.979778 25.616392 -42.427975 -10.452579 29.981382 -41.435120 -7.853344 32.808571 -38.280369 -4.878541 33.340416 -33.809036 -2.325263 31.434412 -29.219210 -0.877658 27.601269 -25.740734 -0.923613 22.868074 -24.305658 -2.450811 18.503084 -25.298513 -5.050044 15.675893 -28.453262 -8.024847 15.144045 -32.924595 -10.578126 19.627777 -33.847412 -18.023758 23.757448 -36.900333 -18.672153 28.699097 -38.037617 -17.632145 33.128613 -36.954529 -15.182405 35.859112 -33.941280 -11.979339 36.158955 -29.805273 -8.881205 33.947807 -25.654743 -6.718144 29.818140 -22.601820 -6.069750 24.876492 -21.464535 -7.109756 20.446976 -22.547621 -9.559495 17.716476 -25.560867 -12.762561 17.416626 -29.696875 -15.860697 21.265779 -29.545151 -23.121429 25.615034 -32.012558 -24.459637 30.706787 -32.750778 -23.890421 35.176708 -31.562000 -21.566301 37.827084 -28.764757 -18.110022 37.947750 -25.108572 -14.447694 35.506374 -21.573112 -11.560630 31.157122 -19.105705 -10.222422 26.065369 -18.367485 -10.791637 21.595449 -19.556261 -13.115756 18.945070 -22.353500 -16.572035 18.824402 -26.009686 -20.234364 21.999350 -24.916931 -27.086649 26.469280 -26.607889 -29.075445 31.638952 -26.830671 -28.934805 36.123158 -25.525579 -26.702415 38.720356 -23.042315 -22.976442 38.734631 -20.046267 -18.755259 36.162159 -17.340221 -15.169924 31.692230 -15.649263 -13.181129 26.522558 -15.426480 -13.321766 22.038353 -16.731571 -15.554154 19.441153 -19.214834 -19.280127 19.426874 -22.210884 -23.501310 21.952211 -20.230556 -29.856327 26.415369 -20.953518 -32.376740 31.572403 -20.549124 -32.567497 36.041489 -19.125732 -30.377487 38.625141 -17.064737 -26.393524 38.631069 -14.918384 -21.683105 36.057690 -13.261784 -17.508385 31.594534 -12.538822 -14.987974 26.437500 -12.943215 -14.797215 21.968414 -14.366606 -16.987221 19.384760 -16.427599 -20.971182 19.378828 -18.573954 -25.681601 21.293129 -15.666029 -31.504343 25.612968 -15.296051 -34.332245 30.661381 -14.207521 -34.683750 35.085648 -12.692111 -32.464672 37.700291 -11.155869 -28.269611 37.804718 -10.010435 -23.222633 35.370953 -9.562723 -18.676071 31.051113 -9.932700 -15.848169 26.002701 -11.021229 -15.496663 21.578434 -12.536640 -17.715736 18.963789 -14.072881 -21.910795 18.859358 -15.218317 -26.957771 20.194855 -11.322945 -32.172474 24.273500 -9.874395 -35.011711 29.145731 -8.151194 -35.306454 33.506035 -6.615071 -32.977722 36.186073 -5.677630 -28.649498 36.467735 -5.590056 -23.481529 34.275543 -6.375816 -18.858566 30.196899 -7.824365 -16.019325 25.324671 -9.547565 -15.724583 20.964365 -11.083689 -18.053310 18.284325 -12.021131 -22.381533 18.002663 -12.108706 -27.549501 18.811378 -7.250381 -32.017021 22.630205 -4.886063 -34.590244 27.315399 -2.685599 -34.633205 31.611565 -1.238604 -32.134388 34.367550 -0.932798 -27.763351 34.844887 -1.850122 -22.691315 32.915680 -3.744779 -18.277321 29.096855 -6.109097 -15.704098 24.411663 -8.309561 -15.661136 20.115498 -9.756557 -18.159950 17.359510 -10.062364 -22.530985 16.882170 -9.145041 -27.603024 17.267645 -3.465125 -31.184134 20.880400 -0.424838 -33.305351 25.418297 2.043972 -32.977654 29.665411 3.279789 -30.288841 32.483727 2.951477 -25.959381 33.118084 1.147008 -21.149351 31.398506 -1.650113 -17.147593 27.785751 -4.690400 -15.026374 23.247854 -7.159210 -15.354071 19.000742 -8.395027 -18.042881 16.182423 -8.066718 -22.372339 15.548064 -6.262249 -27.182369 15.656277 0.005568 -29.798409 19.148335 3.477995 -31.392994 23.599384 6.018469 -30.665623 27.816771 6.946270 -27.811199 30.670450 6.012796 -23.594557 31.395781 3.468171 -19.145546 29.798410 -0.005776 -15.656277 26.306355 -3.478203 -14.061693 21.855305 -6.018677 -14.789061 17.637917 -6.946479 -17.643482 14.784237 -6.013008 -21.860123 14.058905 -3.468383 -26.309132 14.037041 3.136751 -27.974276 17.485878 6.843308 -29.052183 21.903740 9.310476 -27.961086 26.106867 9.877178 -24.993343 28.969032 8.391568 -20.944160 29.723322 5.251715 -16.898512 28.167625 1.298939 -13.940424 24.718792 -2.407618 -12.862516 20.300930 -4.874786 -13.953610 16.097803 -5.441491 -16.921352 13.235636 -3.955883 -20.970533 12.481343 -0.816031 -25.016184 12.440699 5.903224 -25.821009 15.896967 9.705875 -26.444683 20.316713 12.018015 -25.060930 24.515673 12.220106 -22.040531 27.368734 10.257998 -18.192791 28.111425 6.657437 -14.548717 26.544741 2.383191 -12.084730 23.088474 -1.419460 -11.461056 18.668728 -3.731600 -12.844805 14.469770 -3.933692 -15.865206 11.616706 -1.971587 -19.712942 10.874014 1.628972 -23.357018 10.877306 8.303156 -23.440378 14.364908 12.119886 -23.693598 18.804440 14.249016 -22.096006 23.006330 14.120043 -19.075674 25.844687 11.767527 -15.441898 26.558975 7.821825 -12.168348 24.957804 3.340183 -10.132166 21.470203 -0.476548 -9.878945 17.030674 -2.605677 -11.476537 12.828784 -2.476707 -14.496867 9.990424 -0.124194 -18.130640 9.276134 3.821507 -21.404192 9.345882 10.352356 -20.921444 12.867456 14.146084 -20.888954 17.331516 16.104048 -19.147270 21.541922 15.701609 -16.163069 24.370495 13.046600 -12.735966 25.059326 8.850435 -9.784253 23.423841 4.237467 -8.098836 19.902267 0.443739 -8.131323 15.438209 -1.514224 -9.873009 11.227804 -1.111788 -12.857208 8.399228 1.543216 -16.284309 7.710396 5.739382 -19.236023 7.842031 12.088509 -18.332884 11.388534 15.851120 -18.087948 15.874602 17.670681 -16.255106 20.098200 17.059641 -13.325467 22.927614 14.181726 -10.084026 23.604708 9.808075 -7.399324 21.948055 5.110601 -5.990725 18.401554 1.347989 -6.235661 13.915487 -0.471573 -8.068501 9.691892 0.139466 -10.998138 6.862474 3.017377 -14.239579 6.185378 7.391027 -16.924282 6.361202 13.560130 -15.721714 9.918825 17.298847 -15.321430 14.420824 19.019417 -13.432892 18.660892 18.260809 -10.562131 21.502905 15.226295 -7.478367 22.185349 10.728970 -5.007891 20.525364 5.973888 -3.812664 16.967743 2.235170 -4.212948 12.465745 0.514601 -6.101484 8.225678 1.273207 -8.972244 5.383663 4.307718 -12.056008 4.701217 8.805042 -14.526485 4.900838 14.809858 -13.124192 8.453462 18.539482 -12.610685 12.962046 20.201691 -10.685936 17.218517 19.351093 -7.865679 20.082361 16.215609 -4.905602 20.786209 11.635389 -2.598853 19.141470 6.837698 -1.563523 15.588848 3.108075 -2.077030 11.080265 1.445866 -4.001778 6.823792 2.296461 -6.822033 3.959948 5.431942 -9.782111 3.256097 10.012161 -12.088861 3.457189 15.889164 -10.555134 6.990893 19.623711 -9.954275 11.496379 21.259741 -8.000070 15.766405 20.358883 -5.216143 18.656824 17.162521 -2.348448 19.393147 12.527119 -0.165381 17.778080 7.694727 0.748109 14.244377 3.960182 0.147252 9.738893 2.324150 -1.806953 5.468866 3.225006 -4.590878 2.578446 6.421365 -7.458573 1.842121 11.056767 -9.641642 2.026373 16.838568 -8.025473 5.530158 20.588852 -7.351844 10.022550 22.222559 -5.365808 14.299816 21.301931 -2.599519 17.215868 18.073654 0.205797 17.989349 13.402745 2.298457 16.413010 8.540764 3.117736 12.909227 4.790480 2.444109 8.416837 3.156774 0.458072 4.139570 4.077398 -2.308215 1.223517 7.305672 -5.113531 0.450032 11.976582 -7.206192 0.607076 17.691700 -5.547601 4.072214 21.464603 -4.804006 8.539578 23.111866 -2.773220 12.812144 22.192108 0.000612 15.745080 18.951771 2.774242 16.552507 14.259106 4.804479 15.018080 9.371506 5.547323 11.552944 5.598601 4.803730 7.085581 3.951336 2.772945 2.813015 4.871095 -0.000886 -0.119923 8.111428 -2.774517 -0.927353 12.804092 -4.804755 -0.808108 18.484035 -3.120488 2.613694 22.280428 -2.299756 7.044643 23.946304 -0.205368 11.297472 23.035294 2.601485 14.232637 19.791504 5.368711 15.063665 15.084102 7.354833 13.567883 10.174435 8.027671 10.146083 6.378042 7.206940 5.715135 4.712164 5.112553 1.462306 5.623172 2.305700 -1.472862 8.866961 -0.461526 -2.303892 13.574360 -2.447649 -2.223995 19.243624 -0.749640 1.152842 23.058712 0.165232 5.534657 24.738867 2.349653 9.747347 23.833893 5.218308 12.662125 20.586275 8.002544 13.497978 15.866213 9.956327 12.030942 10.938440 10.556142 8.654107 7.123352 9.641271 4.272294 5.443194 7.456851 0.059604 6.348167 4.588196 -2.855176 9.595782 1.803960 -3.691032 14.315844 -0.149824 -3.647139 19.996244 1.561420 -0.315061 23.819460 2.598336 4.002621 25.499882 4.906740 8.148988 24.587238 7.868098 11.013023 21.326071 10.688917 11.827312 16.590214 12.613359 10.373667 11.648628 13.125774 7.041591 7.825412 12.088861 2.723910 6.144990 9.780457 -1.422457 7.057631 6.819100 -4.286495 10.318794 3.998281 -5.100786 15.054652 2.073836 -5.086255 20.763441 3.810067 -1.798816 24.578371 5.007552 2.436047 26.235582 7.480305 6.483606 25.291027 10.565753 9.259321 21.997793 13.437154 10.019443 17.238308 15.325118 8.560296 12.287865 15.723767 5.272859 8.472934 14.526283 1.037997 6.815722 12.053533 -3.009562 7.760276 8.968084 -5.785279 11.053505 6.096683 -6.545403 15.812991 4.208718 -6.543874 21.564823 5.987609 -3.304612 25.347664 7.399071 0.820147 26.947128 10.086636 4.725177 25.934639 13.330170 7.364130 22.581491 16.260574 8.029899 17.786163 18.092648 6.544093 12.833558 18.335487 3.304833 9.050718 16.924026 -0.819926 7.451253 14.236465 -4.724956 8.463740 10.992930 -7.363910 11.816882 8.062526 -8.029681 16.612209 6.230451 -8.036623 22.407301 8.095596 -4.860265 26.129194 9.784735 -0.883912 27.629227 12.739972 2.826977 26.505466 16.169458 5.278073 23.059021 19.154266 5.812605 18.213366 20.894615 4.287348 13.266891 20.924185 1.110992 9.544997 19.235050 -2.865361 8.044963 16.279812 -6.576250 9.168723 12.850326 -9.027347 12.615164 9.865519 -9.561881 17.460817 8.125166 -9.581348 23.286871 10.129976 -6.502129 26.913506 12.169794 -2.730179 28.266407 15.446525 0.723807 26.983072 19.082174 2.934339 23.407368 22.102571 3.309106 18.497398 23.698404 1.747690 13.568790 23.442068 -1.331529 9.942157 21.402252 -5.103477 8.589252 18.125523 -8.557464 9.872585 14.489873 -10.767997 13.448288 11.469475 -11.142766 18.358255 9.873642 -11.200872 24.184383 12.082476 -8.285387 27.676737 14.551956 -4.799867 28.831505 18.200598 -1.678255 27.339266 22.050751 0.243015 23.599863 25.070770 0.449142 18.615271 26.451443 -1.115106 13.721106 25.822821 -4.030590 10.228751 23.353344 -7.516109 9.073982 19.704702 -10.637721 10.566218 15.854549 -12.558993 14.305618 12.834528 -12.765121 19.290209 11.453854 -12.948956 25.049057 13.938903 -10.307741 28.370300 16.903400 -7.217029 29.283686 20.954098 -4.504974 27.544466 25.005615 -2.898269 23.618668 27.972351 -2.827429 18.558207 29.059372 -4.311435 13.719027 27.975410 -6.952649 10.397781 25.010918 -10.043360 9.484396 20.960220 -12.755415 11.223613 16.908703 -14.362122 15.149408 13.941964 -14.432963 20.209869 12.854942 -14.894463 25.808739 15.656119 -12.690886 28.926497 19.151653 -10.131633 29.567301 23.605249 -7.902454 27.559450 27.823570 -6.600656 23.440947 30.676317 -6.575054 18.315340 31.399101 -7.832507 13.556032 29.798252 -10.036083 10.438274 26.302719 -12.595335 9.797468 21.849125 -14.824514 11.805316 17.630806 -16.126314 15.923818 14.778057 -16.151918 21.049423 14.055270 -17.117718 26.372618 17.148870 -15.564696 29.257080 21.156729 -13.694559 29.605984 25.970850 -12.008410 27.325844 30.301296 -10.958050 23.027617 32.987732 -10.824923 17.863014 33.310322 -11.644700 13.215885 31.182631 -13.197721 10.331421 27.174776 -15.067858 9.982515 22.360655 -16.754007 12.262654 18.030209 -17.804369 16.560877 15.343773 -17.937496 21.725481 15.021179 -19.693884 26.637177 18.279083 -19.028460 29.252291 22.696472 -18.005070 29.294403 27.770504 -16.897928 26.752228 32.141602 -16.003693 22.306934 34.638531 -15.561975 17.149645 34.592243 -15.691131 12.662245 32.015141 -16.356552 10.047129 27.597755 -17.379944 10.005014 22.523722 -18.487083 12.547190 18.152626 -19.381319 16.992477 15.655692 -19.823038 22.149769 15.701979 -22.653763 26.498627 18.860743 -23.082878 28.786093 23.484407 -23.029205 28.494724 28.652302 -22.507122 25.702589 32.979694 -21.656523 21.157837 35.307064 -20.705324 16.078238 35.010796 -19.908398 11.824859 32.170269 -19.479282 9.537390 27.546606 -19.532955 9.828757 22.378710 -20.055037 12.620890 18.051319 -20.905636 17.165638 15.723945 -21.856836 22.245239 16.020214 -25.961336 25.854073 18.679205 -27.580385 27.732403 23.222933 -28.532158 27.064350 28.267014 -28.561632 24.028919 32.459888 -27.660908 19.439447 34.678082 -26.071335 14.525686 34.327225 -24.218836 10.604267 31.501339 -22.599789 8.725935 26.957611 -21.648014 9.393986 21.913532 -21.618540 12.429417 17.720657 -22.519262 17.018887 15.502462 -24.108835 21.932650 15.853312 -29.507601 24.600073 17.513083 -32.242981 25.993141 21.681053 -34.110687 24.908464 26.385315 -34.610279 21.636681 30.365358 -33.607883 17.054461 32.554741 -31.372095 12.389607 32.366814 -28.501989 8.892065 29.851936 -25.766613 7.498997 25.683966 -23.898903 8.583672 20.979706 -23.399311 11.855454 16.999662 -24.401705 16.437672 14.810279 -26.637493 21.102524 14.998202 -33.095337 22.649410 15.172739 -36.734535 23.517740 18.750048 -39.329666 22.002077 22.964666 -40.185356 18.508539 26.687286 -39.072330 13.973219 28.920437 -36.288826 9.611353 29.065750 -32.580673 6.591696 27.084284 -28.941475 5.723364 23.506977 -26.346348 7.239027 19.292360 -25.490652 10.732563 15.569739 -26.603674 15.267881 13.336585 -29.387180 19.629749 13.191273 -36.436714 19.962187 11.559688 -40.724354 20.303692 14.439691 -43.833916 18.367634 18.097181 -44.932186 14.672773 21.552137 -43.724888 10.209146 23.878809 -40.535515 6.172781 24.453762 -36.218662 3.645214 23.122940 -31.931019 3.303707 20.242939 -28.821461 5.239766 16.585451 -27.723188 8.934624 13.130494 -28.930483 13.398249 10.803822 -32.119850 17.434616 10.228867 -39.190659 16.573643 6.720101 -43.894531 16.407267 8.874359 -47.329506 14.074881 11.965610 -48.575184 10.201441 15.165558 -47.297787 5.824833 17.616781 -43.839592 2.117769 18.662472 -39.127220 0.073549 18.022442 -34.423347 0.239923 15.868188 -30.988373 2.572309 12.776937 -29.742695 6.445747 9.576989 -31.020088 10.822353 7.125766 -34.478283 14.529419 6.080071 -41.021034 12.615633 0.881013 -45.950825 11.965251 2.319444 -49.558750 9.263976 4.865205 -50.878071 5.235611 7.836164 -49.555271 0.959555 10.436253 -45.944801 -2.418427 11.968781 -41.014080 -3.993210 12.023109 -36.084290 -3.342830 10.584681 -32.476360 -0.641556 8.038919 -31.157042 3.386807 5.067962 -32.479836 7.662864 2.467872 -36.090305 11.040848 0.935342 -41.666664 8.320580 -5.546885 -46.666660 7.203043 -4.807930 -50.326916 4.155477 -2.780662 -51.666660 -0.005525 -0.008286 -50.326912 -4.165025 2.766341 -46.666664 -7.208488 4.799761 -41.666664 -8.320424 5.547121 -36.666668 -7.202887 4.808166 -33.006416 -4.155323 2.780900 -31.666668 0.005678 0.008525 -33.006413 4.165178 -2.766103 -36.666660 7.208643 -4.799524 -41.013111 3.990373 -12.027334 -45.942123 2.409980 -11.981455 -49.551617 -0.971310 -10.453918 -50.874424 -5.247483 -7.854026 -49.556107 -9.272743 -4.878419 -45.949902 -11.968523 -2.324408 -41.022095 -12.612494 -0.876337 -36.093082 -11.032103 -0.922215 -32.483589 -7.650815 -2.449751 -31.160778 -3.374642 -5.049642 -32.479092 0.650618 -8.025249 -36.085293 3.346401 -10.579261 -39.126732 -0.074268 -18.023489 -43.835480 -2.124205 -18.671869 -47.291172 -5.835226 -17.631958 -48.567863 -10.212967 -15.182396 -47.323467 -14.084417 -11.979543 -43.891415 -16.412224 -8.881601 -39.191322 -16.572653 -6.718661 -34.482578 -14.522718 -6.070279 -31.026882 -10.811699 -7.110190 -29.750189 -6.433958 -9.559751 -30.994583 -2.562507 -12.762602 -34.426636 -0.234699 -15.860544 -36.219883 -3.643983 -23.121227 -40.531456 -6.176739 -24.459295 -43.716663 -10.217204 -23.890064 -44.922028 -14.682739 -21.566057 -43.824581 -18.376808 -18.109993 -40.718380 -20.309587 -14.447920 -36.435726 -19.963192 -11.561086 -32.124157 -17.430437 -10.223018 -28.938950 -13.389973 -10.792248 -27.733580 -8.924438 -13.116252 -28.831024 -5.230369 -16.572315 -31.937225 -3.297587 -20.234388 -32.578503 -6.593410 -27.086502 -36.278030 -9.618895 -29.075186 -39.055843 -13.984545 -28.934536 -40.167625 -18.520588 -26.702236 -39.315479 -22.011597 -22.976431 -36.727734 -23.522158 -18.755449 -33.097775 -22.647518 -15.170296 -29.398247 -19.622036 -13.181612 -26.620436 -15.256388 -13.322262 -25.508652 -10.720345 -15.554559 -26.360796 -7.229334 -19.280361 -28.948540 -5.718770 -23.501343 -28.494896 -8.896778 -29.857346 -31.352125 -12.400813 -32.377838 -33.580429 -17.069141 -32.568409 -34.582733 -21.650883 -30.377987 -34.090469 -24.918365 -26.393497 -32.235542 -25.996071 -21.682585 -29.514978 -24.595230 -17.507530 -26.657749 -21.091198 -14.987037 -24.429445 -16.422873 -14.796466 -23.427141 -11.841130 -16.986885 -23.919401 -8.573645 -20.971373 -25.774326 -7.495935 -25.682285 -24.213945 -10.607207 -31.504166 -26.053619 -14.533190 -34.332092 -27.635155 -19.449495 -34.683674 -28.534777 -24.038803 -32.464699 -28.511435 -27.071415 -28.269745 -27.571383 -27.734739 -23.222845 -25.966505 -25.851044 -18.676310 -24.126831 -21.925064 -15.848381 -22.545298 -17.008760 -15.496799 -21.645674 -12.419452 -17.715769 -21.669016 -9.386840 -21.910723 -22.609068 -8.723511 -26.957623 -19.905249 -11.826674 -32.171623 -20.690994 -16.082664 -35.011353 -21.634890 -21.163687 -35.306679 -22.484016 -25.708281 -32.978466 -23.010855 -28.498728 -28.650560 -23.074236 -28.787331 -23.482620 -22.657179 -26.496761 -18.859392 -21.871433 -22.240770 -16.019663 -20.927538 -17.159752 -15.724335 -20.078411 -12.615156 -18.052544 -19.551573 -9.824706 -22.380445 -19.488192 -9.536101 -27.548386 -15.683434 -12.666561 -32.017284 -15.544940 -17.156143 -34.590103 -15.981918 -22.313871 -34.632687 -16.877279 -26.757736 -32.133625 -17.991116 -29.297009 -27.762539 -19.024971 -29.251289 -22.690659 -19.701828 -26.632837 -18.276993 -19.840322 -22.143257 -15.704172 -19.403345 -16.985531 -15.661587 -18.507982 -12.541664 -18.160645 -17.394148 -10.002390 -22.531729 -16.360292 -10.048105 -27.603607 -11.633666 -13.222141 -31.184183 -10.807022 -17.871170 -33.305058 -10.938109 -23.035486 -32.977077 -11.991804 -27.331316 -30.288118 -13.685768 -29.607595 -25.958691 -15.566105 -29.254396 -21.148857 -17.128981 -26.366362 -17.147409 -17.955626 -21.717333 -15.026535 -17.824539 -16.553017 -15.354514 -16.770845 -12.257188 -18.043470 -15.076882 -9.980907 -22.372896 -13.196545 -10.334103 -27.182732 -7.823611 -13.561234 -29.798311 -6.562028 -18.321558 -31.392876 -6.587018 -23.446518 -30.665489 -7.891887 -27.562881 -27.811058 -10.126996 -29.567675 -23.594423 -12.693447 -28.923716 -19.145428 -14.903564 -25.803553 -15.656179 -16.165148 -21.043228 -14.061615 -16.140160 -15.918270 -14.789000 -14.835291 -11.801906 -17.643429 -12.600184 -9.797109 -21.860062 -10.033732 -10.441066 -26.309055 -4.301488 -13.724998 -27.974102 -2.816119 -18.565123 -29.051964 -2.888653 -23.624680 -27.960846 -4.499653 -27.547966 -24.993114 -7.217454 -29.283737 -20.943970 -10.313823 -28.366898 -16.898376 -12.959089 -25.043112 -13.940349 -14.444459 -20.202988 -12.862489 -14.371926 -15.143431 -13.953603 -12.760927 -11.220146 -16.921333 -10.043128 -9.484371 -20.970476 -6.946759 -10.401209 -25.016071 -1.105855 -13.726733 -25.820316 0.458666 -18.621531 -26.443325 0.250238 -23.605082 -25.059237 -1.675292 -27.342045 -22.038912 -4.801980 -28.831106 -18.191648 -8.292031 -27.673275 -14.548316 -11.210291 -24.178787 -12.085140 -12.774813 -19.283989 -11.462132 -12.566386 -14.300438 -12.846218 -10.640858 -10.563475 -15.866542 -7.514171 -9.074409 -19.713804 -4.024120 -10.232241 -23.357136 1.751035 -13.570839 -23.440718 3.312894 -18.499443 -23.694420 2.937535 -23.408865 -22.097044 0.725533 -26.983627 -19.076607 -2.730407 -28.265875 -15.442430 -6.504267 -26.912033 -12.168289 -9.584846 -23.284861 -10.131487 -11.146707 -18.356256 -9.877784 -10.771349 -13.446836 -11.475158 -8.559348 -9.872072 -14.495595 -5.103411 -8.589822 -18.129770 -1.329550 -9.943663 -21.403912 4.294730 -13.271091 -20.920074 5.818930 -18.217869 -20.886723 5.281629 -23.062626 -19.144720 2.826796 -26.507210 -16.160839 -0.887800 -27.628649 -12.734606 -4.866833 -26.126455 -9.784078 -8.044127 -22.403141 -8.099846 -9.568329 -17.456364 -8.133198 -9.031029 -12.611606 -9.875198 -6.576197 -9.167021 -12.859078 -2.861603 -8.045579 -16.285311 1.117431 -9.547771 -19.235840 6.550520 -12.836811 -18.330976 8.034844 -17.789738 -18.085596 7.366256 -22.584435 -16.252892 4.723900 -25.936161 -13.323933 0.815796 -26.946829 -10.083534 -3.310883 -25.345631 -7.399956 -6.550398 -21.561605 -5.992260 -8.034723 -16.608679 -6.237640 -7.366136 -11.813985 -8.070343 -4.723783 -8.462255 -10.999301 -0.815680 -7.451584 -14.239699 3.311000 -9.052780 -16.923279 8.559740 -12.287674 -15.724259 10.019855 -17.237747 -15.324565 9.260584 -21.997019 -13.435716 6.485368 -25.290249 -10.563827 2.437826 -26.235014 -7.478418 -1.797505 -24.578171 -5.006225 -5.085774 -20.763666 -3.809665 -6.545891 -15.813594 -4.209359 -5.786620 -11.054321 -6.098206 -3.011406 -7.761092 -8.970095 1.036134 -6.816322 -12.055502 5.271466 -8.473166 -14.527699 10.374134 -11.648773 -13.125299 11.828353 -16.590067 -12.611694 11.014350 -21.325676 -10.686516 8.150236 -24.586700 -7.865613 4.003450 -25.499352 -4.904844 -0.314880 -23.819082 -2.597546 -3.647663 -19.996122 -1.561955 -5.101882 -15.054832 -2.075558 -4.287881 -10.319221 -4.000735 -1.423770 -7.058196 -6.821638 2.723015 -6.145543 -9.782406 7.041346 -7.825809 -12.089706 12.030798 -10.938441 -10.556322 13.498433 -15.865925 -9.955592 12.663052 -20.585777 -8.001101 9.748491 -23.833321 -5.216549 5.535707 -24.738377 -2.348058 1.153512 -23.058437 -0.164236 -2.223890 -19.243641 0.749763 -3.691527 -14.316159 0.149035 -2.856147 -9.596306 -1.805456 0.058411 -6.348763 -4.590006 4.271194 -5.443703 -7.458498 8.653390 -7.123641 -9.642321 13.569963 -10.174023 -8.024686 15.065849 -15.083549 -7.351054 14.234336 -19.790962 -5.365159 11.298224 -23.034912 -2.599120 7.044246 -23.946182 0.205906 2.612251 -22.280602 2.298314 -0.810214 -18.484463 3.117445 -2.306100 -13.574936 2.443815 -1.474588 -8.867524 0.457921 1.461521 -5.623574 -2.308118 5.715498 -4.712300 -5.113144 10.147494 -6.377878 -7.205553 15.019448 -9.370708 -5.544965 16.554142 -14.258156 -4.801669 15.746539 -18.950926 -2.771739 12.813036 -22.191593 0.000905 8.539662 -23.111824 2.773336 4.071466 -21.465042 4.802683 0.605696 -17.692505 5.545186 -0.928998 -12.805058 4.801889 -0.121397 -8.112289 2.771961 2.812104 -4.871621 -0.000683 7.085476 -3.951388 -2.773114 11.553673 -5.598166 -4.802462 16.411146 -8.542888 -3.121722 17.988007 -13.404404 -2.300686 17.215405 -18.074406 -0.205672 14.300358 -21.301571 2.601965 10.023951 -22.221182 5.369920 5.532044 -20.586834 7.356521 2.028239 -16.836445 8.029461 0.451377 -11.974930 7.208426 1.223978 -7.304929 5.113413 4.139023 -4.077763 2.305777 8.415428 -3.158148 -0.462178 12.907336 -4.792495 -2.448780 17.778435 -7.694009 -0.747132 19.394234 -12.525992 0.167225 18.658350 -17.161289 2.350671 15.767965 -20.357872 5.218153 11.497554 -21.259218 8.001331 6.991373 -19.623817 9.954455 3.456845 -15.889874 10.554189 1.841046 -11.057892 9.639832 2.576927 -6.422596 7.456388 5.467310 -3.226012 4.588907 9.737719 -2.324661 1.805728 14.243902 -3.960059 -0.147397 19.141571 -6.837359 1.563875 20.786924 -11.634661 2.600040 20.083500 -16.214685 4.907311 17.219780 -19.350216 7.867458 12.963096 -20.201092 10.687311 8.454024 -18.539324 12.611292 4.900765 -14.810179 13.123875 3.255411 -10.012879 12.087709 3.958834 -5.432857 9.780439 6.822552 -2.297323 6.820294 11.079234 -1.446443 4.000441 15.588306 -3.108210 2.076458 20.524488 -5.980209 3.807610 22.183979 -10.734537 5.006513 21.501413 -15.229613 7.481046 18.659683 -18.260984 10.568161 14.420228 -19.016397 13.440669 9.919009 -17.293440 15.328881 6.362121 -13.553778 15.726856 4.702630 -8.799450 14.527954 5.385194 -4.304374 12.053423 8.226922 -1.273003 8.966308 12.466374 -0.517587 6.093800 16.967594 -2.240542 4.205586 21.947735 -5.116407 5.987090 23.603893 -9.813029 7.399107 22.926533 -14.184496 10.087301 20.097147 -17.059475 13.331370 15.873868 -17.667620 16.262070 11.388324 -15.845978 18.094122 7.842407 -12.082657 18.336630 6.186246 -7.386036 16.924614 6.863606 -3.014569 14.236421 9.692990 -0.139589 10.992352 13.916266 0.468559 8.061650 18.401812 -1.353081 6.229598 23.423786 -4.244947 8.095219 25.058573 -8.856600 9.784908 24.369257 -13.049791 12.740734 21.540537 -15.700957 16.170687 17.330366 -16.099722 19.155712 12.866860 -14.139237 20.895975 9.346008 -10.344812 20.925175 7.711221 -5.733160 19.235487 8.400537 -1.539970 16.279661 11.229255 1.111198 12.849710 15.439423 1.509966 9.864683 19.902929 -0.450518 8.124418 24.957916 -3.346223 10.130033 26.558876 -7.826197 12.170057 25.844412 -11.769047 15.447004 23.005962 -14.118289 19.082825 18.804090 -14.244447 22.103300 14.364684 -12.113718 23.699099 10.877277 -8.297028 23.442625 9.276318 -3.817055 21.402605 9.990781 0.125795 18.125656 12.829227 2.475038 14.489837 17.031097 2.601200 11.469360 21.470505 0.470472 9.873562 26.544920 -2.390386 12.083067 28.111742 -6.661820 14.551840 27.369120 -10.258378 18.199881 24.516035 -12.216366 22.049700 20.316969 -12.011140 25.069742 15.897061 -9.697695 26.450788 12.440619 -5.895913 25.822790 10.873796 -1.624480 23.354019 11.616417 1.972078 19.705978 14.469501 3.930067 15.856160 18.668564 3.724845 12.836119 23.088472 1.411400 11.455069 28.167831 -1.310941 13.939068 29.723341 -5.258778 16.903841 28.968876 -8.391780 20.954769 26.106592 -9.870459 25.006405 21.903439 -9.298606 27.973120 17.485645 -6.829449 29.059980 14.036955 -3.124596 27.975769 12.481443 0.823240 25.010998 13.235907 3.956242 20.960072 16.098188 5.434922 16.908436 20.301340 4.863071 13.941719 24.719135 2.393916 12.854855</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="1440" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="4320">0.711029 -0.012962 -0.703043 0.712312 -0.107338 -0.693606 0.878988 -0.380802 -0.287003 0.866840 -0.357365 -0.347677 0.811136 -0.552187 0.192736 0.790661 -0.604342 0.098118 0.530355 -0.578876 0.619376 0.506044 -0.691282 0.515799 0.111412 -0.455314 0.883333 0.089131 -0.597257 0.797082 -0.337285 -0.213395 0.916898 -0.351405 -0.347054 0.869522 -0.699237 0.085184 0.709796 -0.700655 -0.004954 0.713483 -0.877527 0.363015 0.313315 -0.865356 0.340260 0.367944 -0.820639 0.545750 -0.169433 -0.798611 0.596880 -0.077170 -0.539730 0.581171 -0.609041 -0.514964 0.693845 -0.503380 -0.109244 0.453369 -0.884603 -0.089357 0.599836 -0.795117 0.351030 0.198193 -0.915149 0.361081 0.338650 -0.868871 0.714099 -0.190650 -0.673584 0.900042 -0.371867 -0.227245 0.846724 -0.454915 0.275883 0.572214 -0.419954 0.704422 0.149328 -0.276940 0.949213 -0.313366 -0.062356 0.947583 -0.696384 0.169219 0.697434 -0.897004 0.357444 0.260035 -0.856522 0.450903 -0.251109 -0.580435 0.420332 -0.697435 -0.142347 0.268832 -0.952611 0.333473 0.043078 -0.941775 0.716271 -0.257405 -0.648613 0.926808 -0.327873 -0.183101 0.891637 -0.312756 0.327365 0.624520 -0.217361 0.750153 0.196158 -0.066667 0.978303 -0.284229 0.101065 0.953415 -0.693212 0.242858 0.678585 -0.921107 0.320869 0.220467 -0.900701 0.311972 -0.302343 -0.630267 0.214445 -0.746175 -0.183192 0.054410 -0.981570 0.310989 -0.118299 -0.943022 0.718100 -0.307551 -0.624296 0.951852 -0.256899 -0.167273 0.933384 -0.140013 0.330440 0.672634 0.011947 0.739879 0.238596 0.160117 0.957828 -0.258488 0.266825 0.928433 -0.691227 0.303910 0.655625 -0.943623 0.259689 0.205273 -0.941271 0.143152 -0.305804 -0.676868 -0.015990 -0.735931 -0.223104 -0.171077 -0.959665 0.288764 -0.276946 -0.916469 0.719521 -0.344264 -0.603135 0.967347 -0.175155 -0.183195 0.958693 0.038025 0.281891 0.701133 0.239858 0.671477 0.262816 0.379243 0.887188 -0.244924 0.420512 0.873603 -0.691824 0.351409 0.630786 -0.957985 0.187142 0.217353 -0.965393 -0.030876 -0.258964 -0.705024 -0.242907 -0.666287 -0.248035 -0.386993 -0.888096 0.275192 -0.422942 -0.863359 0.721022 -0.370405 -0.585600 0.969579 -0.098086 -0.224268 0.960963 0.197590 0.193671 0.702398 0.440265 0.559289 0.262225 0.568598 0.779701 -0.247408 0.549417 0.798079 -0.695222 0.385411 0.606733 -0.960782 0.116404 0.251689 -0.966677 -0.187388 -0.174414 -0.705454 -0.441636 -0.554340 -0.248266 -0.573140 -0.780944 0.275717 -0.545716 -0.791312 0.722974 -0.387898 -0.571702 0.959415 -0.033688 -0.279978 0.941381 0.326780 0.083759 0.677936 0.600423 0.424141 0.238564 0.717851 0.654047 -0.264311 0.648350 0.713990 -0.700464 0.407338 0.586025 -0.952252 0.055085 0.300302 -0.946538 -0.315150 -0.068894 -0.680013 -0.600529 -0.420651 -0.225334 -0.719851 -0.656536 0.289814 -0.640575 -0.711106 0.725160 -0.398235 -0.561741 0.939349 0.017030 -0.342539 0.904460 0.425183 -0.034212 0.633353 0.720682 0.281924 0.197356 0.828265 0.524431 -0.291530 0.719452 0.630396 -0.706071 0.419789 0.570299 -0.934110 0.005351 0.356944 -0.909430 -0.413384 0.045288 -0.634669 -0.720279 -0.279988 -0.184850 -0.828670 -0.528334 0.314234 -0.709287 -0.631006 0.726831 -0.402952 -0.556189 0.911004 0.055868 -0.408597 0.853774 0.497350 -0.153990 0.573362 0.807238 0.140080 0.143349 0.906328 0.397518 -0.325502 0.768075 0.551461 -0.710677 0.425650 0.560142 -0.907602 -0.033286 0.418511 -0.858809 -0.485922 0.162256 -0.574083 -0.806842 -0.139405 -0.131331 -0.905818 -0.402798 0.345958 -0.756417 -0.555109 0.726879 -0.403781 -0.555525 0.874357 0.084299 -0.477905 0.790421 0.547530 -0.274675 0.499916 0.866074 -0.000157 0.078836 0.958368 0.274437 -0.364223 0.799388 0.477829 -0.713128 0.427589 0.555532 -0.872714 -0.061446 0.484350 -0.795764 -0.536513 0.280916 -0.500147 -0.865941 -0.000229 -0.066960 -0.957295 -0.281251 0.383094 -0.786476 -0.484452 0.723973 -0.402626 -0.560138 0.827859 0.102165 -0.551554 0.713058 0.577341 -0.397776 0.412199 0.900209 -0.140409 0.003680 0.988103 0.153750 -0.407170 0.816896 0.408527 -0.712386 0.427962 0.556197 -0.828141 -0.078595 0.554983 -0.719064 -0.566575 0.402418 -0.412073 -0.900498 0.138918 0.008332 -0.986659 -0.162589 0.424918 -0.802630 -0.418603 0.716591 -0.401563 -0.570303 0.768725 0.107257 -0.630522 0.618378 0.585029 -0.524737 0.307173 0.908820 -0.282297 -0.084203 0.995870 0.033949 -0.454983 0.822012 0.342471 -0.707467 0.428869 0.561749 -0.771519 -0.082539 0.630830 -0.625633 -0.574427 0.527842 -0.306981 -0.909780 0.279398 0.096372 -0.994298 -0.045657 0.471620 -0.806288 -0.357035 0.702999 -0.402924 -0.586042 0.693472 0.095244 -0.714160 0.502033 0.565422 -0.654417 0.180608 0.887198 -0.424572 -0.187961 0.978573 -0.084052 -0.508956 0.814010 0.279914 -0.697428 0.432129 0.571716 -0.699907 -0.069417 0.710853 -0.511429 -0.555255 0.655845 -0.180927 -0.889372 0.419861 0.199834 -0.977436 0.068443 0.523745 -0.797151 -0.300403 0.681373 -0.409330 -0.606779 0.599247 0.060359 -0.798286 0.360782 0.511149 -0.780105 0.029505 0.828143 -0.559740 -0.309750 0.930824 -0.193964 -0.569842 0.790572 0.224224 -0.681311 0.439148 0.585632 -0.610870 -0.034381 0.790984 -0.373390 -0.502165 0.780007 -0.031171 -0.832399 0.553300 0.320292 -0.931228 0.173861 0.581090 -0.773899 -0.251821 0.650189 -0.423356 -0.630891 0.486242 -0.002013 -0.873822 0.196317 0.416812 -0.887540 -0.143599 0.726649 -0.671834 -0.446917 0.848937 -0.282083 -0.635493 0.750049 0.183237 -0.657916 0.450847 0.603227 -0.504490 0.026216 0.863020 -0.213006 -0.409684 0.887010 0.139933 -0.733510 0.665118 0.454922 -0.852228 0.258367 0.640940 -0.736118 -0.217545 0.608673 -0.446558 -0.655823 0.359790 -0.090661 -0.928618 0.018513 0.286147 -0.958007 -0.326837 0.587878 -0.739985 -0.588495 0.737913 -0.330391 -0.698511 0.695724 0.167484 -0.625362 0.467892 0.624499 -0.384980 0.110546 0.916281 -0.039058 -0.281203 0.958853 0.321867 -0.596748 0.735046 0.593509 -0.744688 0.305267 0.696583 -0.687395 -0.205575 0.556655 -0.478802 -0.678884 0.228984 -0.195846 -0.953526 -0.156727 0.136003 -0.978233 -0.501353 0.431581 -0.749922 -0.717154 0.615432 -0.327008 -0.747354 0.638580 0.183515 -0.580914 0.491321 0.648955 -0.258620 0.208806 0.943141 0.136410 -0.134552 0.981472 0.498513 -0.441672 0.745930 0.719672 -0.625236 0.301916 0.738283 -0.637288 -0.220911 0.494298 -0.518393 -0.697810 0.101922 -0.302737 -0.947609 -0.315403 -0.009548 -0.948910 -0.650544 0.285181 -0.703892 -0.817655 0.505640 -0.275261 -0.771908 0.593507 0.227831 -0.521838 0.522811 0.674057 -0.129728 0.308928 0.942197 0.302630 0.008262 0.953072 0.652953 -0.295116 0.697538 0.818272 -0.517304 0.250653 0.757834 -0.598130 -0.260631 0.422792 -0.562927 -0.710183 -0.016982 -0.398884 -0.916844 -0.450856 -0.131350 -0.882880 -0.767089 0.169751 -0.618676 -0.883914 0.426427 -0.191980 -0.768947 0.570939 0.287662 -0.448610 0.562967 0.694130 -0.003752 0.401907 0.915673 0.446785 0.129946 0.885154 0.772693 -0.178651 0.609121 0.882690 -0.438556 0.168900 0.752808 -0.578528 -0.313983 0.345350 -0.609299 -0.713784 -0.125668 -0.477896 -0.869381 -0.562537 -0.221460 -0.796560 -0.852124 0.092690 -0.515067 -0.918701 0.382761 -0.097374 -0.742498 0.572179 0.348294 -0.366187 0.609051 0.703536 0.113070 0.481070 0.869360 0.564167 0.221040 0.795523 0.858265 -0.100295 0.503311 0.916007 -0.393777 0.076618 0.726910 -0.579456 -0.368554 0.267292 -0.654262 -0.707457 -0.222045 -0.538916 -0.812567 -0.652052 -0.281696 -0.703901 -0.910667 0.049766 -0.410133 -0.929472 0.368820 -0.007354 -0.701007 0.591037 0.399080 -0.282488 0.655790 0.700100 0.215721 0.543292 0.811356 0.656292 0.282250 0.699726 0.915945 -0.055853 0.397399 0.925906 -0.377598 -0.010888 0.687480 -0.596027 -0.414877 0.194767 -0.695182 -0.691945 -0.303671 -0.584432 -0.752478 -0.721309 -0.319124 -0.614714 -0.948648 0.030914 -0.314821 -0.924931 0.373821 0.068999 -0.654026 0.618532 0.435509 -0.205434 0.698275 0.685718 0.301017 0.589386 0.749675 0.726033 0.320100 0.608615 0.952539 -0.035672 0.302318 0.920971 -0.380317 -0.084683 0.642875 -0.621152 -0.448198 0.132571 -0.730433 -0.669995 -0.369170 -0.618021 -0.694092 -0.772751 -0.341632 -0.534924 -0.971812 0.025876 -0.234334 -0.912752 0.387679 0.128797 -0.609146 0.647366 0.458102 -0.140148 0.734108 0.664413 0.368231 0.622720 0.690380 0.776890 0.342576 0.528283 0.974360 -0.029626 0.223036 0.908785 -0.392398 -0.141894 0.600131 -0.648412 -0.468407 0.083231 -0.759546 -0.645107 -0.418741 -0.643235 -0.641018 -0.809305 -0.355860 -0.467321 -0.985114 0.026652 -0.169826 -0.898626 0.403168 0.172996 -0.571132 0.673115 0.469814 -0.088861 0.763006 0.640255 0.418393 0.647222 0.637221 0.812522 0.356582 0.461147 0.986626 -0.029678 0.160276 0.894924 -0.406704 -0.183584 0.563854 -0.673429 -0.478080 0.047203 -0.782894 -0.620361 -0.453834 -0.663044 -0.595321 -0.833986 -0.366590 -0.412406 -0.992377 0.027938 -0.120028 -0.886133 0.415925 0.204388 -0.542223 0.693613 0.474231 -0.051714 0.785630 0.616531 0.453431 0.666136 0.592168 0.836232 0.367028 0.407439 0.993174 -0.030490 0.112588 0.882850 -0.418831 -0.212503 0.536280 -0.693884 -0.480550 0.022889 -0.800975 -0.598260 -0.477092 -0.679115 -0.557840 -0.849830 -0.376153 -0.369186 -0.996222 0.027453 -0.082384 -0.876694 0.424442 0.226399 -0.522108 0.708606 0.474639 -0.026660 0.803045 0.595322 0.476489 0.681531 0.555404 0.851305 0.376506 0.365409 0.996612 -0.029501 0.076770 0.873927 -0.426836 -0.232515 0.517258 -0.708944 -0.479419 0.008456 -0.814509 -0.580090 -0.490880 -0.692707 -0.528388 -0.859123 -0.386018 -0.336003 -0.998246 0.023912 -0.054155 -0.870756 0.427960 0.242146 -0.509934 0.718045 0.473686 -0.011798 0.815893 0.578082 0.489937 0.694551 0.526840 0.859931 0.386366 0.333526 0.998409 -0.025517 0.050291 0.868523 -0.430024 -0.246470 0.505947 -0.718616 -0.477083 0.001202 -0.823894 -0.566743 -0.497959 -0.704025 -0.506345 -0.863964 -0.396109 -0.310909 -0.999312 0.017701 -0.032592 -0.867670 0.427105 0.254423 -0.503667 0.722637 0.473408 -0.004261 0.824755 0.565474 0.496661 0.705507 0.505556 0.864224 0.396617 0.309536 0.999369 -0.018787 0.030155 0.865966 -0.428811 -0.257340 0.500406 -0.723370 -0.475742 -0.001279 -0.829486 -0.558525 -0.500620 -0.713086 -0.490803 -0.865924 -0.406098 -0.291994 -0.999839 0.009397 -0.015267 -0.866575 0.422539 0.265533 -0.501400 0.722925 0.475371 -0.001626 0.829894 0.557918 0.498926 0.714309 0.490750 0.865688 0.406840 0.291662 0.999851 -0.009951 0.014101 0.865377 -0.423908 -0.267254 0.498743 -0.723813 -0.476812 -0.001425 -0.831464 -0.555577 -0.501068 -0.719552 -0.480809 -0.866381 -0.415218 -0.277451 -1.000000 -0.000006 0.000006 -0.866382 0.415208 0.277460 -0.501071 0.719546 0.480814 -0.001429 0.831461 0.555581 0.498926 0.720587 0.481484 0.865667 0.416250 0.278131 1.000000 -0.000004 0.000009 0.865669 -0.416256 -0.278116 0.498930 -0.720590 -0.481475 -0.001636 -0.829899 -0.557912 -0.501409 -0.722924 -0.475363 -0.866581 -0.422536 -0.265519 -0.999839 -0.009397 0.015288 -0.865918 0.406097 0.292014 -0.500610 0.713085 0.490815 -0.001268 0.829484 0.558529 0.498753 0.723807 0.476812 0.865383 0.423894 0.267257 0.999851 0.009931 -0.014091 0.865683 -0.406859 -0.291648 0.498917 -0.714322 -0.490740 -0.004308 -0.824764 -0.565461 -0.503709 -0.722621 -0.473388 -0.867694 -0.427075 -0.254389 -0.999311 -0.017671 0.032637 -0.863938 0.396130 0.310955 -0.497915 0.704034 0.506376 0.001251 0.823888 0.566751 0.500448 0.723348 0.475731 0.865991 0.428771 0.257324 0.999369 0.018734 -0.030162 0.864201 -0.396669 -0.309532 0.496621 -0.705542 -0.505547 -0.011914 -0.815908 -0.578058 -0.510035 -0.718003 -0.473642 -0.870814 -0.427882 -0.242075 -0.998243 -0.023829 0.054245 -0.859060 0.386081 0.336091 -0.490775 0.692737 0.528446 0.008575 0.814500 0.580100 0.506050 0.718567 0.477048 0.868582 0.429936 0.246415 0.998409 0.025404 -0.050336 0.859874 -0.386477 -0.333544 0.489838 -0.694625 -0.526834 -0.026860 -0.803076 -0.595272 -0.522282 -0.708535 -0.474551 -0.876792 -0.424307 -0.226273 -0.996214 -0.027306 0.082537 -0.849717 0.376267 0.369331 -0.476905 0.679170 0.557933 0.023100 0.800961 0.598271 0.517437 0.708859 0.479351 0.874029 0.426685 0.232407 0.996611 0.029307 -0.076861 0.851203 -0.376697 -0.365448 0.476316 -0.681662 -0.555392 -0.052040 -0.785679 -0.616442 -0.542506 -0.693496 -0.474079 -0.886287 -0.415701 -0.204175 -0.992354 -0.027695 0.120275 -0.833794 0.366777 0.412629 -0.453527 0.663136 0.595454 0.047542 0.782875 0.620360 0.536564 0.693753 0.480423 0.883005 0.418598 0.212314 0.993165 0.030190 -0.112747 0.836066 -0.367329 -0.407508 0.453151 -0.666346 -0.592146 -0.089346 -0.763063 -0.640119 -0.571538 -0.672932 -0.469581 -0.898833 -0.402843 -0.172676 -0.985061 -0.026312 0.170185 -0.809011 0.356121 0.467631 -0.418288 0.643366 0.641182 0.083724 0.759528 0.645064 0.564261 0.673256 0.477846 0.895139 0.406378 0.183258 0.986594 0.029241 -0.160550 0.812257 -0.357025 -0.461272 0.417963 -0.647525 -0.637196 -0.140708 -0.734186 -0.664208 -0.609607 -0.647157 -0.457786 -0.912965 -0.387317 -0.128378 -0.971712 -0.025511 0.234789 -0.772372 0.341899 0.535301 -0.368617 0.618148 0.694272 0.133150 0.730404 0.669912 0.600589 0.648215 0.468093 0.909011 0.392021 0.141491 0.974307 0.029097 -0.223338 0.776581 -0.343134 -0.528376 0.367738 -0.623107 -0.690294 -0.205964 -0.698422 -0.685409 -0.654464 -0.618356 -0.435100 -0.925098 -0.373502 -0.068482 -0.948475 -0.030615 0.315369 -0.720846 0.319316 0.615157 -0.303051 0.584496 0.752678 0.195382 0.695117 0.691837 0.643337 0.620931 0.447842 0.921186 0.379886 0.084277 0.952497 0.035021 -0.302528 0.725775 -0.320827 -0.608540 0.300579 -0.589911 -0.749438 -0.283249 -0.655900 -0.699689 -0.701583 -0.590738 -0.398510 -0.929636 -0.368390 0.008059 -0.910368 -0.049400 0.410839 -0.651395 0.281927 0.704415 -0.221226 0.539023 0.812720 0.268059 0.654253 0.707176 0.688018 0.595836 0.414259 0.926122 0.377087 0.010224 0.915845 0.054953 -0.397755 0.655906 -0.283288 -0.699668 0.215069 -0.543975 -0.811071 -0.366821 -0.609254 -0.703031 -0.742956 -0.571975 -0.347650 -0.918725 -0.382507 0.098145 -0.851685 -0.092552 0.515816 -0.561783 0.221488 0.797084 -0.124825 0.477893 0.869504 0.346065 0.609290 0.713446 0.727367 0.579306 0.367888 0.916210 0.393183 -0.077244 0.858321 0.099048 -0.503463 0.564059 -0.222529 -0.795184 0.112635 -0.482013 -0.868894 -0.449082 -0.563234 -0.693609 -0.769263 -0.570841 -0.287009 -0.883771 -0.426384 0.192731 -0.766498 -0.169875 0.619373 -0.450020 0.131158 0.883334 -0.016164 0.398781 0.916904 0.423390 0.562952 0.709807 0.753146 0.578441 0.313332 0.882964 0.437808 -0.169408 0.773206 0.176818 -0.609006 0.447308 -0.132102 -0.884571 -0.003821 -0.403125 -0.915137 -0.522200 -0.523095 -0.673557 -0.772089 -0.593507 -0.227217 -0.817339 -0.505800 0.275904 -0.649798 -0.285542 0.704435 -0.314494 0.009182 0.949215 0.102692 0.302592 0.947572 0.494749 0.518501 0.697409 0.758056 0.598123 0.259998 0.818733 0.516331 -0.251156 0.654171 0.292520 -0.697490 0.303892 -0.011130 -0.952641 -0.129504 -0.310332 -0.941766 -0.581017 -0.491594 -0.648655 -0.747332 -0.638710 -0.183152 -0.716682 -0.615816 0.327319 -0.500534 -0.432182 0.750123 -0.155860 -0.136556 0.978294 0.229599 0.195602 0.953428 0.556907 0.478887 0.678617 0.738439 0.637244 0.220516 0.720547 0.624049 -0.302284 0.500863 0.438669 -0.746127 0.138736 0.131532 -0.981556 -0.257908 -0.210124 -0.943044 -0.625387 -0.468097 -0.624321 -0.698404 -0.695875 -0.167300 -0.587961 -0.738326 0.330420 -0.326002 -0.588487 0.739869 0.019328 -0.286686 0.957830 0.360290 0.090438 0.928446 0.608796 0.446649 0.655647 0.696716 0.687342 0.205300 0.594615 0.743596 -0.305774 0.324562 0.594239 -0.735893 -0.036637 0.278840 -0.959638 -0.384229 -0.111546 -0.916475 -0.657908 -0.450998 -0.603123 -0.635366 -0.750171 -0.183178 -0.446409 -0.849263 0.281905 -0.142831 -0.727125 0.671483 0.197037 -0.417223 0.887187 0.486639 0.001861 0.873601 0.650237 0.423445 0.630782 0.641056 0.736078 0.217339 0.455957 0.851484 -0.258995 0.142159 0.731988 -0.666322 -0.211116 0.408267 -0.888115 -0.503872 -0.026869 -0.863360 -0.681289 -0.439230 -0.585595 -0.569734 -0.790639 -0.224262 -0.309355 -0.931017 0.193669 0.030097 -0.828433 0.559279 0.361325 -0.511397 0.779691 0.599523 -0.060444 0.798072 0.681386 0.409381 0.606728 0.581201 0.773861 0.251682 0.321081 0.930849 -0.174435 -0.029687 0.831734 -0.554381 -0.372173 0.501546 -0.780985 -0.610443 0.034058 -0.791327 -0.697416 -0.432165 -0.571703 -0.508880 -0.814034 -0.279983 -0.187689 -0.978651 0.083753 0.181012 -0.887322 0.424139 0.502392 -0.565527 0.654050 0.693639 -0.095273 0.713994 0.702997 0.402951 0.586025 0.523839 0.797129 0.300296 0.200358 0.977297 -0.068904 -0.180051 0.889172 -0.420661 -0.510738 0.555069 -0.656541 -0.699662 0.069300 -0.711105 -0.707462 -0.428888 -0.561741 -0.454925 -0.822015 -0.342540 -0.084011 -0.995877 -0.034210 0.307450 -0.908840 0.281930 0.618615 -0.585047 0.524439 0.768823 -0.107253 0.630403 0.716582 0.401580 0.570301 0.471693 0.806287 0.356940 0.096718 0.994281 0.045281 -0.306446 0.909777 -0.279992 -0.625228 0.574418 -0.528331 -0.771381 0.082510 -0.631002 -0.712383 -0.427976 -0.556190 -0.407124 -0.816886 -0.408593 0.003826 -0.988066 -0.153984 0.412405 -0.900166 0.140084 0.713228 -0.577308 0.397518 0.827924 -0.102147 0.551459 0.723964 0.402637 0.560143 0.424975 0.802648 0.418514 0.008584 0.986711 0.162257 -0.411701 0.900593 -0.139411 -0.718789 0.566647 -0.402806 -0.828051 0.078604 -0.555116 -0.713124 -0.427606 -0.555524 -0.364176 -0.799368 -0.477898 0.078960 -0.958292 -0.274667 0.500081 -0.865979 -0.000153 0.790552 -0.547459 0.274438 0.874403 -0.084267 0.477827 0.726867 0.403794 0.555532 0.383141 0.786516 0.484352 -0.066753 0.957408 0.280917 -0.499850 0.866112 -0.000232 -0.795556 0.536641 -0.281259 -0.872651 0.061472 -0.484459 -0.710671 -0.425667 -0.560138 -0.325452 -0.768029 -0.551555 0.143462 -0.906197 -0.397777 0.573502 -0.807082 -0.140408 0.853879 -0.497242 0.153754 0.911036 -0.055831 0.408530 0.726819 0.402964 0.556196 0.346009 0.756492 0.554975 -0.131129 0.906021 0.402408 -0.573811 0.807121 0.138911 -0.858635 0.486117 -0.162592 -0.907558 0.033325 -0.418603 -0.706063 -0.419801 -0.570300 -0.291480 -0.719365 -0.630518 0.197458 -0.828050 -0.524732 0.633473 -0.720433 -0.282290 0.904549 -0.425015 0.033954 0.939375 -0.016983 0.342472 0.725148 0.398244 0.561749 0.314283 0.709419 0.630833 -0.184651 0.829025 0.527846 -0.634404 0.720742 0.279396 -0.909272 0.413690 -0.045663 -0.934075 -0.005287 -0.357037 -0.700444 -0.407352 -0.586040 -0.264259 -0.648201 -0.714145 0.238646 -0.717505 -0.654396 0.678026 -0.600026 -0.424558 0.941449 -0.326511 -0.084052 0.959434 0.033767 0.279905 0.722952 0.387924 0.571714 0.289835 0.640829 0.710868 -0.225156 0.720514 0.655870 -0.679757 0.601360 0.419877 -0.946400 0.315664 0.068442 -0.952224 -0.054988 -0.300409 -0.695170 -0.385426 -0.606783 -0.247343 -0.549146 -0.798286 0.262280 -0.568024 -0.780102 0.702441 -0.439628 -0.559736 0.960992 -0.197166 -0.193960 0.969575 0.098211 0.224230 0.720961 0.370468 0.585635 0.275649 0.546238 0.790975 -0.248195 0.574474 0.779986 -0.705288 0.443217 0.553288 -0.966612 0.188242 0.173858 -0.960760 -0.116291 -0.251826 -0.691714 -0.351409 -0.630907 -0.244843 -0.420077 -0.873835 0.262832 -0.378396 -0.887545 0.701111 -0.238944 -0.671825 0.958667 -0.037421 -0.282060 0.967303 0.175325 0.183265 0.719384 0.344357 0.603245 0.274915 0.423841 0.863007 -0.248331 0.389399 0.886961 -0.705231 0.245639 0.665065 -0.965520 0.032148 0.258335 -0.957959 -0.187028 -0.217564 -0.691068 -0.303837 -0.655827 -0.258413 -0.266233 -0.928624 0.238549 -0.159073 -0.958014 0.672531 -0.010860 -0.739989 0.933296 0.140712 -0.330393 0.951769 0.257070 0.167485 0.717884 0.307650 0.624495 0.288214 0.278203 0.916262 -0.224018 0.174584 0.958820 -0.677752 0.019779 0.735025 -0.941684 -0.141590 0.305260 -0.943595 -0.259550 -0.205577 -0.692951 -0.242697 -0.678909 -0.284065 -0.100397 -0.953534 0.196179 0.067720 -0.978227 0.624467 0.218385 -0.749899 0.891576 0.313339 -0.326972 0.926707 0.327905 0.183557 0.715935 0.257372 0.648996 0.310086 0.119481 0.943171 -0.184834 -0.050983 0.981447 -0.631838 -0.210972 0.745836 -0.901322 -0.310670 0.301833 -0.921030 -0.320751 -0.220959 -0.696171 -0.168894 -0.697726 -0.313230 0.063056 -0.947581 0.149347 0.277872 -0.948937 0.572176 0.420775 -0.703962 0.846679 0.455317 -0.275356 0.899940 0.371819 0.227726 0.713745 0.190644 0.673960 0.332561 -0.041957 0.942148 -0.143928 -0.266039 0.953157 -0.581902 -0.417793 0.697739 -0.857110 -0.449936 0.250839 -0.896960 -0.357218 -0.260494 -0.698876 -0.084696 -0.710211 -0.336915 0.214127 -0.916863 0.111714 0.456096 -0.882891 0.530586 0.579407 -0.618681 0.811277 0.552245 -0.191977 0.878932 0.380423 0.287675 0.711843 0.106964 0.694145 0.349914 -0.197832 0.915654 -0.110877 -0.452092 0.885053 -0.541059 -0.579985 0.608993 -0.821130 -0.545203 0.168820 -0.877403 -0.362700 -0.314027 -0.700340 0.005574 -0.713787 -0.351026 0.347781 -0.869384 0.089493 0.597897 -0.796561 0.506347 0.691607 -0.515065 0.790841 0.604227 -0.097369 0.866770 0.356925 0.348302 0.710540 0.012602 0.703544 0.360078 -0.338445 0.869367 -0.090656 -0.599086 0.795536 -0.515989 -0.693124 0.503324 -0.799027 -0.596393 0.076623 -0.865281 -0.339789 -0.368555 -0.700244 0.095646 -0.707468 -0.355681 0.461749 -0.812575 0.082083 0.705534 -0.703906 0.498443 0.763768 -0.410137 0.784153 0.620524 -0.007357 0.862363 0.311555 0.399078 0.709177 -0.083276 0.700095 0.362639 -0.458492 0.811343 -0.083718 -0.709512 0.699703 -0.506347 -0.765314 0.397375 -0.789960 -0.613062 -0.010905 -0.859908 -0.297364 -0.414889 -0.699465 0.178880 -0.691918 -0.354351 0.555176 -0.752473 0.084225 0.784229 -0.614728 0.501041 0.806120 -0.314847 0.786167 0.614154 0.068969 0.862668 0.257209 0.435485 0.707462 -0.171147 0.685716 0.359956 -0.555311 0.749708 -0.085760 -0.788768 0.608679 -0.507136 -0.807075 0.302394 -0.789844 -0.607443 -0.084614 -0.859387 -0.246205 -0.448148 -0.698843 0.250395 -0.670015 -0.350621 0.628708 -0.694112 0.090530 0.840025 -0.534941 0.508331 0.828662 -0.234348 0.792132 0.596609 0.128785 0.865223 0.203827 0.458088 0.705839 -0.245716 0.664391 0.355179 -0.630291 0.690348 -0.091764 -0.844117 0.528247 -0.512833 -0.829018 0.223005 -0.794210 -0.590838 -0.141918 -0.861593 -0.195531 -0.468428 -0.699448 0.307637 -0.645083 -0.347751 0.684222 -0.641023 0.096400 0.878803 -0.467346 0.515578 0.839838 -0.169860 0.798428 0.576712 0.172963 0.868496 0.158141 0.469794 0.705246 -0.304462 0.640259 0.351377 -0.685885 0.637257 -0.097384 -0.881929 0.461213 -0.518966 -0.839619 0.160358 -0.799663 -0.571720 -0.183509 -0.865153 -0.151657 -0.478027 -0.701617 0.350553 -0.620360 -0.347312 0.724543 -0.595325 0.099498 0.905546 -0.412415 0.520366 0.845464 -0.120039 0.803258 0.559469 0.204378 0.871798 0.122794 0.474225 0.706241 -0.348010 0.616532 0.350189 -0.725738 0.592175 -0.100247 -0.907709 0.407450 -0.522982 -0.844873 0.112602 -0.804138 -0.555166 -0.212491 -0.869063 -0.117506 -0.480543 -0.705065 0.380711 -0.598283 -0.349524 0.752757 -0.557844 0.099224 0.924048 -0.369174 0.521945 0.848993 -0.082364 0.805961 0.546956 0.226417 0.874729 0.097779 0.474645 0.708759 -0.378507 0.595310 0.351927 -0.753467 0.555369 -0.099644 -0.925520 0.365353 -0.523894 -0.848323 0.076706 -0.806626 -0.543382 -0.232575 -0.872574 -0.093434 -0.479464 -0.709630 0.399917 -0.580079 -0.354483 0.771461 -0.528385 0.095238 0.937033 -0.336005 0.519812 0.852562 -0.054159 0.805989 0.540138 0.242143 0.876808 0.082620 0.473689 0.712490 -0.397702 0.578093 0.356545 -0.771554 0.526858 -0.095346 -0.937898 0.333550 -0.521291 -0.851894 0.050317 -0.806671 -0.537165 -0.246446 -0.875322 -0.078873 -0.477064 -0.714124 0.410896 -0.566738 -0.360739 0.783252 -0.506344 0.088925 0.946270 -0.310912 0.514971 0.856587 -0.032596 0.803710 0.537886 0.254419 0.877654 0.074887 0.473409 0.716394 -0.408672 0.565480 0.362666 -0.782863 0.505568 -0.088622 -0.946744 0.309552 -0.515946 -0.856090 0.030171 -0.804342 -0.535553 -0.257327 -0.876663 -0.071691 -0.475733 -0.717691 0.415882 -0.558535 -0.367205 0.790111 -0.490800 0.081310 0.952961 -0.291983 0.508093 0.861167 -0.015255 0.799238 0.539171 0.265543 0.876774 0.072719 0.475373 0.719506 -0.413578 0.557911 0.369117 -0.789262 0.490732 -0.080544 -0.953133 0.291634 -0.508570 -0.860906 0.014068 -0.799813 -0.537455 -0.267285 -0.876203 -0.069982 -0.476834 -0.719362 0.416965 -0.555571 -0.372621 0.793712 -0.480805 0.073596 0.957918 -0.277448 0.499990 0.866031 0.000008 0.792768 0.542709 0.277463 0.873678 0.074173 0.480817 0.720781 -0.414487 0.555585 0.374585 -0.792373 0.481489 -0.072349 -0.957813 0.278137 -0.500003 -0.866024 0.000017 -0.793324 -0.541565 -0.278108 -0.873519 -0.071793 -0.481467 -0.717894 0.416370 -0.557910 -0.375362 0.795697 -0.475362 0.067367 0.961749 -0.265518 0.491785 0.870583 0.015289 0.784650 0.546856 0.292016 0.867854 0.076995 0.490818 0.718986 -0.413647 0.558530 0.377456 -0.793838 0.476811 -0.065591 -0.961391 0.267255 -0.491328 -0.870861 -0.014092 -0.785194 -0.546270 -0.291648 -0.868081 -0.074910 -0.490738 -0.712107 0.416124 -0.565460 -0.373943 0.797542 -0.473385 0.064002 0.964983 -0.254385 0.484363 0.874258 0.032642 0.775033 0.550116 0.310959 0.858669 0.079178 0.506378 0.712877 -0.413039 0.566749 0.376204 -0.795082 0.475726 -0.061679 -0.964357 0.257316 -0.483469 -0.874841 -0.030171 -0.775631 -0.550076 -0.309538 -0.859328 -0.077303 -0.505548 -0.700623 0.418288 -0.578068 -0.366768 0.800713 -0.473645 0.064874 0.968086 -0.242076 0.478505 0.876408 0.054244 0.763900 0.550910 0.336088 0.845322 0.078635 0.528439 0.701089 -0.414696 0.580088 0.369264 -0.797550 0.477031 -0.061966 -0.967187 0.246394 -0.477213 -0.877344 -0.050359 -0.764637 -0.551420 -0.333566 -0.846474 -0.076881 -0.526851 -0.682108 0.424732 -0.595258 -0.352545 0.806539 -0.474560 0.070856 0.971478 -0.226295 0.474395 0.876437 0.082511 0.750678 0.547806 0.369312 0.826625 0.073501 0.557932 0.682125 -0.420417 0.598293 0.355214 -0.802496 0.479399 -0.067445 -0.970261 0.232473 -0.472885 -0.877772 -0.076789 -0.751816 -0.548877 -0.365386 -0.828515 -0.071748 -0.555352 -0.654384 0.437922 -0.616446 -0.329315 0.816579 -0.474079 0.083154 0.975397 -0.204173 0.472209 0.873243 0.120276 0.734547 0.538683 0.412627 0.801061 0.061182 0.595448 0.654218 -0.432624 0.620352 0.332521 -0.811563 0.480411 -0.078993 -0.974007 0.212299 -0.470444 -0.875195 -0.112764 -0.736151 -0.540377 -0.407523 -0.803641 -0.059250 -0.592157 -0.616077 0.458966 -0.640156 -0.296919 0.831459 -0.469591 0.100624 0.979825 -0.172676 0.469811 0.866208 0.170181 0.712964 0.522511 0.467616 0.766344 0.040504 0.641152 0.615915 -0.452328 0.645017 0.300917 -0.825333 0.477780 -0.095650 -0.978416 0.183173 -0.467978 -0.869015 -0.160651 -0.715298 -0.524867 -0.461371 -0.769697 -0.038132 -0.637270 -0.565682 0.488744 -0.664179 -0.255895 0.851415 -0.457833 0.120829 0.984326 -0.128459 0.463589 0.854398 0.234712 0.682179 0.498125 0.535260 0.719617 0.010365 0.694294 0.566014 -0.480325 0.670012 0.261157 -0.844106 0.468275 -0.114917 -0.983211 0.141738 -0.461899 -0.858424 -0.223063 -0.685478 -0.501188 -0.528139 -0.723625 -0.007174 -0.690156 -0.501741 0.527669 -0.685435 -0.208156 0.875995 -0.435091 0.139192 0.987896 -0.068460 0.447803 0.836662 0.315387 0.637012 0.464542 0.615155 0.657745 -0.029878 0.752648 0.504310 -0.516837 0.691774 0.216070 -0.867663 0.447745 -0.131614 -0.987723 0.084148 -0.445919 -0.842344 -0.302676 -0.640686 -0.468014 -0.608674 -0.661068 0.034771 -0.749520 -0.426411 0.573252 -0.699683 -0.160807 0.902958 -0.398506 0.145780 0.989284 0.008062 0.412400 0.813102 0.410842 0.569851 0.423160 0.704419 0.577417 -0.077927 0.812722 0.432567 -0.559275 0.707176 0.171997 -0.893759 0.414260 -0.136499 -0.990587 0.010229 -0.410340 -0.820621 -0.397745 -0.573301 -0.426389 -0.699656 -0.578645 0.085732 -0.811061 -0.344283 0.622256 -0.703041 -0.123919 0.929391 -0.347674 0.128060 0.986901 0.098121 0.345660 0.783882 0.515799 0.472685 0.375811 0.797079 0.476268 -0.130805 0.869517 0.354621 -0.604312 0.713478 0.138004 -0.919551 0.367942 -0.117614 -0.990057 -0.077165 -0.343424 -0.792896 -0.503365 -0.474817 -0.377306 -0.795103 -0.473829 0.143382 -0.868866 -0.263154 0.670605 -0.693570 -0.109663 0.951645 -0.286959 0.072681 0.978547 0.192777 0.236173 0.748706 0.619405 0.338625 0.324096 0.883343 0.353458 -0.185450 0.916883 0.275855 -0.648190 0.709756 0.124389 -0.941489 0.313250 -0.062310 -0.983555 -0.169517 -0.233435 -0.757938 -0.609129 -0.337983 -0.321184 -0.884652 -0.347120 0.204999 -0.915141 -0.191934 0.713747 -0.673592 -0.127977 0.965388 -0.227262 -0.029391 0.960748 0.275860 0.077601 0.705546 0.704402 0.165202 0.267813 0.949202 0.210715 -0.240188 0.947580 0.201664 -0.687686 0.697438 0.138951 -0.955547 0.260045 0.037773 -0.967225 -0.251097 -0.073754 -0.712837 -0.697440 -0.161566 -0.257679 -0.952627 -0.204002 0.267261 -0.941783 -0.135232 0.748903 -0.648735 -0.179504 0.966541 -0.183238 -0.175003 0.928594 0.327243 -0.124033 0.649622 0.750072 -0.040339 0.203333 0.978278 0.054589 -0.296563 0.953452 0.136254 -0.721685 0.678680 0.182607 -0.958117 0.220607 0.180112 -0.936081 -0.302179 0.129437 -0.653213 -0.746029 0.044569 -0.186072 -0.981525 -0.052990 0.328295 -0.943088 -0.092685 0.775675 -0.624290 -0.253435 0.952782 -0.167263 -0.345431 0.878339 0.330451 -0.346656 0.576540 0.739886 -0.257952 0.126571 0.957831 -0.101821 -0.357263 0.928437 0.082432 -0.750568 0.655631 0.246921 -0.947045 0.205270 0.346653 -0.886736 -0.305830 0.352270 -0.578158 -0.735961 0.259723 -0.107638 -0.959666 0.095486 0.388565 -0.916461 -0.061645 0.795283 -0.603096 -0.331985 0.925335 -0.183141 -0.512283 0.811222 0.281931 -0.558309 0.487227 0.671491 -0.459862 0.037931 0.887180 -0.241712 -0.422410 0.873582 0.041613 -0.774863 0.630758 0.316962 -0.923205 0.217317 0.509428 -0.820604 -0.259022 0.562772 -0.489116 -0.666373 0.459021 -0.021306 -0.888170 0.228595 0.449816 -0.863371 -0.039743 0.809625 -0.585600 -0.399843 0.888723 -0.224269 -0.651596 0.733427 0.193667 -0.732479 0.388167 0.559286 -0.623534 -0.057206 0.779700 -0.352105 -0.488977 0.798075 0.013836 -0.794791 0.606725 0.379576 -0.890267 0.251686 0.645607 -0.743487 -0.174410 0.735174 -0.390151 -0.554348 0.620462 0.071547 -0.780966 0.334721 0.511634 -0.791323 -0.025552 0.820062 -0.571704 -0.450535 0.847717 -0.279990 -0.753687 0.651874 0.083759 -0.858934 0.286916 0.424159 -0.740938 -0.152300 0.654076 -0.429318 -0.553058 0.714012 -0.002535 -0.810286 0.586030 0.428410 -0.852226 0.300294 0.746195 -0.662153 -0.068892 0.860101 -0.288625 -0.420621 0.736108 0.164810 -0.656492 0.409869 0.571289 -0.711081 -0.017693 0.827123 -0.561742 -0.484423 0.804985 -0.342540 -0.820451 0.570693 -0.034208 -0.940803 0.188159 0.281931 -0.815973 -0.243212 0.524438 -0.477298 -0.612191 0.630403 -0.010516 -0.821366 0.570305 0.462419 -0.811640 0.356944 0.812717 -0.580897 0.045281 0.941114 -0.189494 -0.279992 0.810076 0.254254 -0.528329 0.457151 0.626777 -0.631002 -0.014445 0.830929 -0.556190 -0.503880 0.761026 -0.408588 -0.857602 0.490722 -0.153985 -0.985771 0.092928 0.140074 -0.856582 -0.329026 0.397503 -0.502429 -0.665936 0.551448 -0.013291 -0.828290 0.560141 0.482625 -0.769360 0.418520 0.850224 -0.500790 0.162261 0.985785 -0.093764 -0.139417 0.850125 0.339152 -0.402820 0.482098 0.677803 -0.555126 -0.013759 0.831387 -0.555523 -0.510185 0.715067 -0.477902 -0.869384 0.410762 -0.274674 -1.000000 -0.000094 -0.000159 -0.869390 -0.410909 0.274436 -0.510178 -0.715121 0.477828 -0.013734 -0.831383 0.555531 0.489574 -0.725070 0.484346 0.862515 -0.420900 0.280911 1.000000 -0.000178 -0.000233 0.862523 0.420654 -0.281255 0.489559 0.725007 -0.484455 -0.013298 0.828292 -0.560139 -0.502400 0.665858 -0.551568 -0.856515 0.328850 -0.397794 -0.985703 -0.093130 -0.140418 -0.857565 -0.490858 0.153753 -0.503873 -0.761060 0.408534 -0.014437 -0.830926 0.556196 0.482134 -0.677908 0.554966 0.850202 -0.339461 0.402396 0.985894 0.093368 0.138907 0.850307 0.500543 -0.162585 0.482641 0.769309 -0.418595 -0.010526 0.821369 -0.570300 -0.477248 0.612112 -0.630519 -0.815841 0.243019 -0.524732 -0.940649 -0.188392 -0.282291 -0.820346 -0.570858 0.033953 -0.484393 -0.805032 0.342471 -0.017686 -0.827118 0.561750 0.457230 -0.626885 0.630838 0.810280 -0.254594 0.527853 0.941380 0.189046 0.279400 0.812899 0.580612 -0.045661 0.462458 0.811577 -0.357036 -0.002555 0.810279 -0.586038 -0.429233 0.552960 -0.714139 -0.740707 0.152085 -0.654388 -0.858655 -0.287170 -0.424553 -0.753492 -0.652063 -0.084053 -0.450472 -0.847780 0.279901 -0.025526 -0.820056 0.571713 0.410046 -0.571411 0.710881 0.736543 -0.165249 0.655894 0.860656 0.288023 0.419898 0.746566 0.661781 0.068450 0.428491 0.852144 -0.300408 0.013803 0.794744 -0.606788 -0.351894 0.488775 -0.798292 -0.623055 0.056870 -0.780108 -0.731945 -0.388515 -0.559744 -0.651245 -0.733660 -0.193969 -0.399733 -0.888784 0.224223 -0.039641 -0.809609 0.585629 0.335240 -0.511844 0.790968 0.621611 -0.072305 0.779982 0.736480 0.389178 0.553298 0.646327 0.742987 0.173872 0.379672 0.890188 -0.251822 0.041504 0.774730 -0.630929 -0.241378 0.422045 -0.873851 -0.459106 -0.038461 -0.887549 -0.557476 -0.487741 -0.671810 -0.511737 -0.811533 -0.282027 -0.331814 -0.925364 0.183306 -0.061458 -0.795159 0.603279 0.229634 -0.449970 0.863015 0.461441 0.020399 0.886937 0.565359 0.487965 0.665026 0.510573 0.820119 0.258303 0.316969 0.923139 -0.217589 0.082403 0.750416 -0.655809 -0.101367 0.356932 -0.928614 -0.257051 -0.127034 -0.958012 -0.345684 -0.576988 -0.739991 -0.344793 -0.878610 -0.330398 -0.253261 -0.952791 0.167474 -0.092541 -0.775534 0.624487 0.096733 -0.388690 0.916276 0.263049 0.106776 0.958856 0.355882 0.577125 0.735034 0.348180 0.886333 0.305260 0.247017 0.946956 -0.205562 0.136345 0.721536 -0.678819 0.055105 0.296314 -0.953500 -0.039438 -0.203644 -0.978250 -0.123092 -0.649910 -0.749977 -0.174386 -0.928764 -0.327089 -0.179321 -0.966540 0.183424 -0.135039 -0.748818 0.648873 -0.051604 -0.328484 0.943099 0.048156 0.185291 0.981503 0.133136 0.652478 0.746021 0.181638 0.935838 0.302019 0.182803 0.958030 -0.220820 0.201793 0.687288 -0.697792 0.211202 0.239661 -0.947606 0.165946 -0.268344 -0.948922 0.078281 -0.705955 -0.703917 -0.029067 -0.960921 -0.275292 -0.128017 -0.965255 0.227802 -0.191824 -0.713359 0.674034 -0.202687 -0.266858 0.942181 -0.158550 0.257894 0.953076 -0.070983 0.712988 0.697574 0.038835 0.967286 0.250699 0.139083 0.955377 -0.260598 0.276101 0.647542 -0.710252 0.353916 0.184648 -0.916869 0.339146 -0.324860 -0.882863 0.236480 -0.749251 -0.618627 0.072585 -0.978724 -0.191912 -0.110064 -0.951365 0.287735 -0.263338 -0.669893 0.694188 -0.346295 -0.204029 0.915670 -0.336046 0.322154 0.885037 -0.231714 0.758617 0.608941 -0.061584 0.983734 0.168745 0.124597 0.941180 -0.314096 0.355015 0.603767 -0.713744 0.476734 0.130157 -0.869358 0.473098 -0.376405 -0.796553 0.345839 -0.784280 -0.515074 0.127926 -0.986990 -0.097392 -0.124206 -0.929127 0.348275 -0.344278 -0.621705 0.703531 -0.473056 -0.142699 0.869399 -0.473417 0.377978 0.795618 -0.342219 0.793384 0.503417 -0.116957 0.990171 0.076700 0.138385 0.919272 -0.368495 0.432983 0.558587 -0.707465 0.577753 0.077131 -0.812559 0.569987 -0.423872 -0.703880 0.412229 -0.813560 -0.410106 0.145317 -0.989358 -0.007325 -0.161359 -0.902594 0.399107 -0.426684 -0.572511 0.700123 -0.578347 -0.084798 0.811372 -0.572560 0.427263 0.699730 -0.409583 0.821173 0.397388 -0.135925 0.990659 -0.010909 0.172456 0.893376 -0.414896 0.504682 0.516136 -0.692026 0.657952 0.029087 -0.752498 0.636958 -0.465237 -0.614686 0.447435 -0.837095 -0.314761 0.138570 -0.987942 0.069066 -0.208828 -0.875605 0.435554 -0.502172 -0.526902 0.685710 -0.661047 -0.033811 0.749583 -0.640272 0.468883 0.608441 -0.445357 0.842844 0.302110 -0.131077 0.987733 -0.084872 0.216538 0.867239 -0.448339 0.566287 0.480168 -0.669894 0.719853 -0.010546 -0.694046 0.682336 -0.498271 -0.534923 0.463646 -0.854463 -0.234363 0.120825 -0.984288 0.128760 -0.255854 -0.851289 0.458090 -0.565487 -0.488581 0.664465 -0.723271 0.007338 0.690525 -0.685075 0.501353 0.528505 -0.461542 0.858561 0.223277 -0.114612 0.983255 -0.141683 0.261441 0.844033 -0.468249 0.616216 0.451735 -0.645146 0.766430 -0.041150 -0.641008 0.712787 -0.523056 -0.467277 0.469380 -0.866523 -0.169766 0.100036 -0.979819 0.173054 -0.297493 -0.831106 0.469852 -0.616446 -0.458334 0.640254 -0.769745 0.038876 0.637166 -0.715049 0.525496 0.461040 -0.467548 0.869341 0.160143 -0.095165 0.978363 -0.183711 0.301354 0.824948 -0.478171 0.654467 0.432122 -0.620438 0.801111 -0.061733 -0.595323 0.734358 -0.539151 -0.412351 0.471801 -0.873508 -0.119947 0.082624 -0.975381 0.204461 -0.329813 -0.816271 0.474262 -0.654695 -0.437392 0.616492 -0.803679 0.059857 0.592044 -0.735936 0.540880 0.407243 -0.470069 0.875448 0.112362 -0.078569 0.973951 -0.212711 0.332899 0.811236 -0.480702 0.682152 0.420531 -0.598183 0.826700 -0.073379 -0.557837 0.750796 -0.547697 -0.369235 0.474542 -0.876362 -0.082456 0.071021 -0.971457 0.226334 -0.352373 -0.806583 0.474613 -0.681953 -0.424829 0.595366 -0.828403 0.071636 0.555533 -0.751765 0.548799 0.365609 -0.472886 0.877753 0.077002 -0.067469 0.970301 -0.232300 0.355201 0.802582 -0.479264 0.701099 0.414653 -0.580106 0.845321 -0.078678 -0.528434 0.763886 -0.550943 -0.336066 0.478475 -0.876426 -0.054219 0.064829 -0.968085 0.242091 -0.366816 -0.800692 0.473644 -0.700656 -0.418249 0.578056 -0.846479 0.076928 0.526835 -0.764616 0.551460 0.333547 -0.477178 0.877364 0.050333 -0.061933 0.967180 -0.246428 0.369287 0.797519 -0.477065 0.712878 0.413057 -0.566735 0.858681 -0.079156 -0.506360 0.775056 -0.550095 -0.310940 0.484390 -0.874244 -0.032627 0.064028 -0.964979 0.254394 -0.373920 -0.797548 0.473394 -0.712085 -0.416136 0.565478 -0.859309 0.077290 0.505582 -0.775619 0.550067 0.309583 -0.483467 0.874841 0.030212 -0.061684 0.964364 -0.257288 0.376199 0.795095 -0.475709 0.719014 0.413576 -0.558545 0.867855 -0.077069 -0.490804 0.784621 -0.546915 -0.291983 0.491727 -0.870616 -0.015254 0.067292 -0.961748 0.265541 -0.375434 -0.795660 0.475368 -0.717940 -0.416305 0.557900 -0.868087 0.074984 0.490715 -0.785164 0.546333 0.291612 -0.491274 0.870892 0.014044 -0.065533 0.961380 -0.267309 0.377504 0.793789 -0.476853 0.720784 0.414511 -0.555564 0.873691 -0.074147 -0.480797 0.792791 -0.542687 -0.277441 0.500017 -0.866015 0.000013 0.073623 -0.957910 0.277465 -0.372597 -0.793715 0.480820 -0.719341 -0.416974 0.555591 -0.873502 0.071783 0.481498 -0.793314 0.541560 0.278147 -0.499998 0.866026 0.000024 -0.072350 0.957823 -0.278103 0.374582 0.792390 -0.481463 0.719548 0.413478 -0.557930 0.876768 -0.072829 -0.475367 0.799188 -0.539261 -0.265512 0.508010 -0.861215 0.015298 0.081214 -0.952958 0.292020 -0.367296 -0.790063 0.490810 -0.717758 -0.415803 0.558508 -0.876228 0.070072 0.476776 -0.799787 0.537531 0.267209 -0.508500 0.860946 -0.014143 -0.080455 0.953122 -0.291696 0.369195 0.789199 -0.490775 0.716374 0.408728 -0.565464 0.877658 -0.074828 -0.473410 0.803743 -0.537834 -0.254424 0.515027 -0.856554 0.032595 0.088990 -0.946262 0.310917 -0.360683 -0.783270 0.506356 -0.714087 -0.410933 0.566757 -0.876649 0.071647 0.475766 -0.804348 0.535518 0.257379 -0.515970 0.856077 -0.030104 -0.088656 0.946761 -0.309489 0.362632 0.782906 -0.505526 0.712487 0.397815 -0.578019 0.876840 -0.082513 -0.473649 0.806055 -0.540053 -0.242111 0.519904 -0.852503 0.054202 0.095340 -0.937002 0.336062 -0.354387 -0.771460 0.528450 -0.709555 -0.399944 0.580152 -0.875278 0.078832 0.477153 -0.806657 0.537135 0.246559 -0.521300 0.851897 -0.050178 -0.095370 0.937948 -0.333405 0.356521 0.771646 -0.526740 0.709012 0.378042 -0.595304 0.874740 -0.098289 -0.474519 0.805742 -0.547370 -0.226199 0.521567 -0.849200 0.082621 0.098786 -0.924007 0.369394 -0.349923 -0.752497 0.557945 -0.705341 -0.380312 0.598211 -0.872662 0.093865 0.479219 -0.806489 0.543736 0.232221 -0.523550 0.848502 -0.077064 -0.099185 0.925464 -0.365621 0.352353 0.753172 -0.555499 0.706504 0.347713 -0.616399 0.871860 -0.123148 -0.474020 0.803128 -0.559757 -0.204103 0.520107 -0.845579 0.120355 0.099193 -0.905447 0.412705 -0.347585 -0.724260 0.595510 -0.701792 -0.350165 0.620381 -0.869086 0.117901 0.480405 -0.803977 0.555483 0.212272 -0.522652 0.845053 -0.112786 -0.099821 0.907724 -0.407520 0.350590 0.725584 -0.592128 0.705572 0.303952 -0.640142 0.868528 -0.158698 -0.469547 0.798195 -0.577138 -0.172614 0.515174 -0.840007 0.170248 0.095935 -0.878680 0.467672 -0.348175 -0.683858 0.641180 -0.699740 -0.307140 0.645003 -0.865233 0.152160 0.477722 -0.799478 0.572114 0.183085 -0.518528 0.839816 -0.160742 -0.096801 0.881875 -0.461438 0.351918 0.685570 -0.637297 0.706126 0.245442 -0.664188 0.865286 -0.204166 -0.457816 0.792005 -0.596853 -0.128432 0.508086 -0.828702 0.234738 0.090244 -0.839842 0.535277 -0.350883 -0.628359 0.694295 -0.699017 -0.249975 0.669990 -0.861613 0.195928 0.468226 -0.794022 0.591151 0.141664 -0.512441 0.829221 -0.223152 -0.091261 0.844190 -0.528219 0.355640 0.630191 -0.690203 0.707808 0.170877 -0.685426 0.862743 -0.257567 -0.435125 0.786031 -0.614379 -0.068508 0.500784 -0.806084 0.315347 0.083926 -0.783936 0.615143 -0.354627 -0.554721 0.752678 -0.699654 -0.178384 0.691855 -0.859402 0.246650 0.447875 -0.789596 0.607807 0.084316 -0.506608 0.807369 -0.302494 -0.085087 0.788962 -0.608523 0.360545 0.555290 -0.749440 0.709666 0.082515 -0.699690 0.862362 -0.312324 -0.398479 0.783801 -0.620960 0.008099 0.497896 -0.763731 0.410872 0.081465 -0.705085 0.704428 -0.356267 -0.461073 0.812703 -0.700685 -0.094947 0.707125 -0.860050 0.297949 0.414174 -0.789629 0.613501 0.010109 -0.505480 0.765622 -0.397886 -0.082564 0.709570 -0.699781 0.363610 0.458102 -0.811129</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="1440" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="4719">0 0 0 0 0.083333 0 0 0.166667 0 0 0.250000 0 0 0.333333 0 0 0.416667 0 0 0.500000 0 0 0.583333 0 0 0.666667 0 0 0.750000 0 0 0.833333 0 0 0.916667 0 0 1.000000 0 0.008333 0 0 0.008333 0.083333 0 0.008333 0.166667 0 0.008333 0.250000 0 0.008333 0.333333 0 0.008333 0.416667 0 0.008333 0.500000 0 0.008333 0.583333 0 0.008333 0.666667 0 0.008333 0.750000 0 0.008333 0.833333 0 0.008333 0.916667 0 0.008333 1.000000 0 0.016667 0 0 0.016667 0.083333 0 0.016667 0.166667 0 0.016667 0.250000 0 0.016667 0.333333 0 0.016667 0.416667 0 0.016667 0.500000 0 0.016667 0.583333 0 0.016667 0.666667 0 0.016667 0.750000 0 0.016667 0.833333 0 0.016667 0.916667 0 0.016667 1.000000 0 0.025000 0 0 0.025000 0.083333 0 0.025000 0.166667 0 0.025000 0.250000 0 0.025000 0.333333 0 0.025000 0.416667 0 0.025000 0.500000 0 0.025000 0.583333 0 0.025000 0.666667 0 0.025000 0.750000 0 0.025000 0.833333 0 0.025000 0.916667 0 0.025000 1.000000 0 0.033333 0 0 0.033333 0.083333 0 0.033333 0.166667 0 0.033333 0.250000 0 0.033333 0.333333 0 0.033333 0.416667 0 0.033333 0.500000 0 0.033333 0.583333 0 0.033333 0.666667 0 0.033333 0.750000 0 0.033333 0.833333 0 0.033333 0.916667 0 0.033333 1.000000 0 0.041667 0 0 0.041667 0.083333 0 0.041667 0.166667 0 0.041667 0.250000 0 0.041667 0.333333 0 0.041667 0.416667 0 0.041667 0.500000 0 0.041667 0.583333 0 0.041667 0.666667 0 0.041667 0.750000 0 0.041667 0.833333 0 0.041667 0.916667 0 0.041667 1.000000 0 0.050000 0 0 0.050000 0.083333 0 0.050000 0.166667 0 0.050000 0.250000 0 0.050000 0.333333 0 0.050000 0.416667 0 0.050000 0.500000 0 0.050000 0.583333 0 0.050000 0.666667 0 0.050000 0.750000 0 0.050000 0.833333 0 0.050000 0.916667 0 0.050000 1.000000 0 0.058333 0 0 0.058333 0.083333 0 0.058333 0.166667 0 0.058333 0.250000 0 0.058333 0.333333 0 0.058333 0.416667 0 0.058333 0.500000 0 0.058333 0.583333 0 0.058333 0.666667 0 0.058333 0.750000 0 0.058333 0.833333 0 0.058333 0.916667 0 0.058333 1.000000 0 0.066667 0 0 0.066667 0.083333 0 0.066667 0.166667 0 0.066667 0.250000 0 0.066667 0.333333 0 0.066667 0.416667 0 0.066667 0.500000 0 0.066667 0.583333 0 0.066667 0.666667 0 0.066667 0.750000 0 0.066667 0.833333 0 0.066667 0.916667 0 0.066667 1.000000 0 0.075000 0 0 0.075000 0.083333 0 0.075000 0.166667 0 0.075000 0.250000 0 0.075000 0.333333 0 0.075000 0.416667 0 0.075000 0.500000 0 0.075000 0.583333 0 0.075000 0.666667 0 0.075000 0.750000 0 0.075000 0.833333 0 0.075000 0.916667 0 0.075000 1.000000 0 0.083333 0 0 0.083333 0.083333 0 0.083333 0.166667 0 0.083333 0.250000 0 0.083333 0.333333 0 0.083333 0.416667 0 0.083333 0.500000 0 0.083333 0.583333 0 0.083333 0.666667 0 0.083333 0.750000 0 0.083333 0.833333 0 0.083333 0.916667 0 0.083333 1.000000 0 0.091667 0 0 0.091667 0.083333 0 0.091667 0.166667 0 0.091667 0.250000 0 0.091667 0.333333 0 0.091667 0.416667 0 0.091667 0.500000 0 0.091667 0.583333 0 0.091667 0.666667 0 0.091667 0.750000 0 0.091667 0.833333 0 0.091667 0.916667 0 0.091667 1.000000 0 0.100000 0 0 0.100000 0.083333 0 0.100000 0.166667 0 0.100000 0.250000 0 0.100000 0.333333 0 0.100000 0.416667 0 0.100000 0.500000 0 0.100000 0.583333 0 0.100000 0.666667 0 0.100000 0.750000 0 0.100000 0.833333 0 0.100000 0.916667 0 0.100000 1.000000 0 0.108333 0 0 0.108333 0.083333 0 0.108333 0.166667 0 0.108333 0.250000 0 0.108333 0.333333 0 0.108333 0.416667 0 0.108333 0.500000 0 0.108333 0.583333 0 0.108333 0.666667 0 0.108333 0.750000 0 0.108333 0.833333 0 0.108333 0.916667 0 0.108333 1.000000 0 0.116667 0 0 0.116667 0.083333 0 0.116667 0.166667 0 0.116667 0.250000 0 0.116667 0.333333 0 0.116667 0.416667 0 0.116667 0.500000 0 0.116667 0.583333 0 0.116667 0.666667 0 0.116667 0.750000 0 0.116667 0.833333 0 0.116667 0.916667 0 0.116667 1.000000 0 0.125000 0 0 0.125000 0.083333 0 0.125000 0.166667 0 0.125000 0.250000 0 0.125000 0.333333 0 0.125000 0.416667 0 0.125000 0.500000 0 0.125000 0.583333 0 0.125000 0.666667 0 0.125000 0.750000 0 0.125000 0.833333 0 0.125000 0.916667 0 0.125000 1.000000 0 0.133333 0 0 0.133333 0.083333 0 0.133333 0.166667 0 0.133333 0.250000 0 0.133333 0.333333 0 0.133333 0.416667 0 0.133333 0.500000 0 0.133333 0.583333 0 0.133333 0.666667 0 0.133333 0.750000 0 0.133333 0.833333 0 0.133333 0.916667 0 0.133333 1.000000 0 0.141667 0 0 0.141667 0.083333 0 0.141667 0.166667 0 0.141667 0.250000 0 0.141667 0.333333 0 0.141667 0.416667 0 0.141667 0.500000 0 0.141667 0.583333 0 0.141667 0.666667 0 0.141667 0.750000 0 0.141667 0.833333 0 0.141667 0.916667 0 0.141667 1.000000 0 0.150000 0 0 0.150000 0.083333 0 0.150000 0.166667 0 0.150000 0.250000 0 0.150000 0.333333 0 0.150000 0.416667 0 0.150000 0.500000 0 0.150000 0.583333 0 0.150000 0.666667 0 0.150000 0.750000 0 0.150000 0.833333 0 0.150000 0.916667 0 0.150000 1.000000 0 0.158333 0 0 0.158333 0.083333 0 0.158333 0.166667 0 0.158333 0.250000 0 0.158333 0.333333 0 0.158333 0.416667 0 0.158333 0.500000 0 0.158333 0.583333 0 0.158333 0.666667 0 0.158333 0.750000 0 0.158333 0.833333 0 0.158333 0.916667 0 0.158333 1.000000 0 0.166667 0 0 0.166667 0.083333 0 0.166667 0.166667 0 0.166667 0.250000 0 0.166667 0.333333 0 0.166667 0.416667 0 0.166667 0.500000 0 0.166667 0.583333 0 0.166667 0.666667 0 0.166667 0.750000 0 0.166667 0.833333 0 0.166667 0.916667 0 0.166667 1.000000 0 0.175000 0 0 0.175000 0.083333 0 0.175000 0.166667 0 0.175000 0.250000 0 0.175000 0.333333 0 0.175000 0.416667 0 0.175000 0.500000 0 0.175000 0.583333 0 0.175000 0.666667 0 0.175000 0.750000 0 0.175000 0.833333 0 0.175000 0.916667 0 0.175000 1.000000 0 0.183333 0 0 0.183333 0.083333 0 0.183333 0.166667 0 0.183333 0.250000 0 0.183333 0.333333 0 0.183333 0.416667 0 0.183333 0.500000 0 0.183333 0.583333 0 0.183333 0.666667 0 0.183333 0.750000 0 0.183333 0.833333 0 0.183333 0.916667 0 0.183333 1.000000 0 0.191667 0 0 0.191667 0.083333 0 0.191667 0.166667 0 0.191667 0.250000 0 0.191667 0.333333 0 0.191667 0.416667 0 0.191667 0.500000 0 0.191667 0.583333 0 0.191667 0.666667 0 0.191667 0.750000 0 0.191667 0.833333 0 0.191667 0.916667 0 0.191667 1.000000 0 0.200000 0 0 0.200000 0.083333 0 0.200000 0.166667 0 0.200000 0.250000 0 0.200000 0.333333 0 0.200000 0.416667 0 0.200000 0.500000 0 0.200000 0.583333 0 0.200000 0.666667 0 0.200000 0.750000 0 0.200000 0.833333 0 0.200000 0.916667 0 0.200000 1.000000 0 0.208333 0 0 0.208333 0.083333 0 0.208333 0.166667 0 0.208333 0.250000 0 0.208333 0.333333 0 0.208333 0.416667 0 0.208333 0.500000 0 0.208333 0.583333 0 0.208333 0.666667 0 0.208333 0.750000 0 0.208333 0.833333 0 0.208333 0.916667 0 0.208333 1.000000 0 0.216667 0 0 0.216667 0.083333 0 0.216667 0.166667 0 0.216667 0.250000 0 0.216667 0.333333 0 0.216667 0.416667 0 0.216667 0.500000 0 0.216667 0.583333 0 0.216667 0.666667 0 0.216667 0.750000 0 0.216667 0.833333 0 0.216667 0.916667 0 0.216667 1.000000 0 0.225000 0 0 0.225000 0.083333 0 0.225000 0.166667 0 0.225000 0.250000 0 0.225000 0.333333 0 0.225000 0.416667 0 0.225000 0.500000 0 0.225000 0.583333 0 0.225000 0.666667 0 0.225000 0.750000 0 0.225000 0.833333 0 0.225000 0.916667 0 0.225000 1.000000 0 0.233333 0 0 0.233333 0.083333 0 0.233333 0.166667 0 0.233333 0.250000 0 0.233333 0.333333 0 0.233333 0.416667 0 0.233333 0.500000 0 0.233333 0.583333 0 0.233333 0.666667 0 0.233333 0.750000 0 0.233333 0.833333 0 0.233333 0.916667 0 0.233333 1.000000 0 0.241667 0 0 0.241667 0.083333 0 0.241667 0.166667 0 0.241667 0.250000 0 0.241667 0.333333 0 0.241667 0.416667 0 0.241667 0.500000 0 0.241667 0.583333 0 0.241667 0.666667 0 0.241667 0.750000 0 0.241667 0.833333 0 0.241667 0.916667 0 0.241667 1.000000 0 0.250000 0 0 0.250000 0.083333 0 0.250000 0.166667 0 0.250000 0.250000 0 0.250000 0.333333 0 0.250000 0.416667 0 0.250000 0.500000 0 0.250000 0.583333 0 0.250000 0.666667 0 0.250000 0.750000 0 0.250000 0.833333 0 0.250000 0.916667 0 0.250000 1.000000 0 0.258333 0 0 0.258333 0.083333 0 0.258333 0.166667 0 0.258333 0.250000 0 0.258333 0.333333 0 0.258333 0.416667 0 0.258333 0.500000 0 0.258333 0.583333 0 0.258333 0.666667 0 0.258333 0.750000 0 0.258333 0.833333 0 0.258333 0.916667 0 0.258333 1.000000 0 0.266667 0 0 0.266667 0.083333 0 0.266667 0.166667 0 0.266667 0.250000 0 0.266667 0.333333 0 0.266667 0.416667 0 0.266667 0.500000 0 0.266667 0.583333 0 0.266667 0.666667 0 0.266667 0.750000 0 0.266667 0.833333 0 0.266667 0.916667 0 0.266667 1.000000 0 0.275000 0 0 0.275000 0.083333 0 0.275000 0.166667 0 0.275000 0.250000 0 0.275000 0.333333 0 0.275000 0.416667 0 0.275000 0.500000 0 0.275000 0.583333 0 0.275000 0.666667 0 0.275000 0.750000 0 0.275000 0.833333 0 0.275000 0.916667 0 0.275000 1.000000 0 0.283333 0 0 0.283333 0.083333 0 0.283333 0.166667 0 0.283333 0.250000 0 0.283333 0.333333 0 0.283333 0.416667 0 0.283333 0.500000 0 0.283333 0.583333 0 0.283333 0.666667 0 0.283333 0.750000 0 0.283333 0.833333 0 0.283333 0.916667 0 0.283333 1.000000 0 0.291667 0 0 0.291667 0.083333 0 0.291667 0.166667 0 0.291667 0.250000 0 0.291667 0.333333 0 0.291667 0.416667 0 0.291667 0.500000 0 0.291667 0.583333 0 0.291667 0.666667 0 0.291667 0.750000 0 0.291667 0.833333 0 0.291667 0.916667 0 0.291667 1.000000 0 0.300000 0 0 0.300000 0.083333 0 0.300000 0.166667 0 0.300000 0.250000 0 0.300000 0.333333 0 0.300000 0.416667 0 0.300000 0.500000 0 0.300000 0.583333 0 0.300000 0.666667 0 0.300000 0.750000 0 0.300000 0.833333 0 0.300000 0.916667 0 0.300000 1.000000 0 0.308333 0 0 0.308333 0.083333 0 0.308333 0.166667 0 0.308333 0.250000 0 0.308333 0.333333 0 0.308333 0.416667 0 0.308333 0.500000 0 0.308333 0.583333 0 0.308333 0.666667 0 0.308333 0.750000 0 0.308333 0.833333 0 0.308333 0.916667 0 0.308333 1.000000 0 0.316666 0 0 0.316666 0.083333 0 0.316666 0.166667 0 0.316666 0.250000 0 0.316666 0.333333 0 0.316666 0.416667 0 0.316666 0.500000 0 0.316666 0.583333 0 0.316666 0.666667 0 0.316666 0.750000 0 0.316666 0.833333 0 0.316666 0.916667 0 0.316666 1.000000 0 0.325000 0 0 0.325000 0.083333 0 0.325000 0.166667 0 0.325000 0.250000 0 0.325000 0.333333 0 0.325000 0.416667 0 0.325000 0.500000 0 0.325000 0.583333 0 0.325000 0.666667 0 0.325000 0.750000 0 0.325000 0.833333 0 0.325000 0.916667 0 0.325000 1.000000 0 0.333333 0 0 0.333333 0.083333 0 0.333333 0.166667 0 0.333333 0.250000 0 0.333333 0.333333 0 0.333333 0.416667 0 0.333333 0.500000 0 0.333333 0.583333 0 0.333333 0.666667 0 0.333333 0.750000 0 0.333333 0.833333 0 0.333333 0.916667 0 0.333333 1.000000 0 0.341666 0 0 0.341666 0.083333 0 0.341666 0.166667 0 0.341666 0.250000 0 0.341666 0.333333 0 0.341666 0.416667 0 0.341666 0.500000 0 0.341666 0.583333 0 0.341666 0.666667 0 0.341666 0.750000 0 0.341666 0.833333 0 0.341666 0.916667 0 0.341666 1.000000 0 0.350000 0 0 0.350000 0.083333 0 0.350000 0.166667 0 0.350000 0.250000 0 0.350000 0.333333 0 0.350000 0.416667 0 0.350000 0.500000 0 0.350000 0.583333 0 0.350000 0.666667 0 0.350000 0.750000 0 0.350000 0.833333 0 0.350000 0.916667 0 0.350000 1.000000 0 0.358333 0 0 0.358333 0.083333 0 0.358333 0.166667 0 0.358333 0.250000 0 0.358333 0.333333 0 0.358333 0.416667 0 0.358333 0.500000 0 0.358333 0.583333 0 0.358333 0.666667 0 0.358333 0.750000 0 0.358333 0.833333 0 0.358333 0.916667 0 0.358333 1.000000 0 0.366666 0 0 0.366666 0.083333 0 0.366666 0.166667 0 0.366666 0.250000 0 0.366666 0.333333 0 0.366666 0.416667 0 0.366666 0.500000 0 0.366666 0.583333 0 0.366666 0.666667 0 0.366666 0.750000 0 0.366666 0.833333 0 0.366666 0.916667 0 0.366666 1.000000 0 0.375000 0 0 0.375000 0.083333 0 0.375000 0.166667 0 0.375000 0.250000 0 0.375000 0.333333 0 0.375000 0.416667 0 0.375000 0.500000 0 0.375000 0.583333 0 0.375000 0.666667 0 0.375000 0.750000 0 0.375000 0.833333 0 0.375000 0.916667 0 0.375000 1.000000 0 0.383333 0 0 0.383333 0.083333 0 0.383333 0.166667 0 0.383333 0.250000 0 0.383333 0.333333 0 0.383333 0.416667 0 0.383333 0.500000 0 0.383333 0.583333 0 0.383333 0.666667 0 0.383333 0.750000 0 0.383333 0.833333 0 0.383333 0.916667 0 0.383333 1.000000 0 0.391666 0 0 0.391666 0.083333 0 0.391666 0.166667 0 0.391666 0.250000 0 0.391666 0.333333 0 0.391666 0.416667 0 0.391666 0.500000 0 0.391666 0.583333 0 0.391666 0.666667 0 0.391666 0.750000 0 0.391666 0.833333 0 0.391666 0.916667 0 0.391666 1.000000 0 0.400000 0 0 0.400000 0.083333 0 0.400000 0.166667 0 0.400000 0.250000 0 0.400000 0.333333 0 0.400000 0.416667 0 0.400000 0.500000 0 0.400000 0.583333 0 0.400000 0.666667 0 0.400000 0.750000 0 0.400000 0.833333 0 0.400000 0.916667 0 0.400000 1.000000 0 0.408333 0 0 0.408333 0.083333 0 0.408333 0.166667 0 0.408333 0.250000 0 0.408333 0.333333 0 0.408333 0.416667 0 0.408333 0.500000 0 0.408333 0.583333 0 0.408333 0.666667 0 0.408333 0.750000 0 0.408333 0.833333 0 0.408333 0.916667 0 0.408333 1.000000 0 0.416666 0 0 0.416666 0.083333 0 0.416666 0.166667 0 0.416666 0.250000 0 0.416666 0.333333 0 0.416666 0.416667 0 0.416666 0.500000 0 0.416666 0.583333 0 0.416666 0.666667 0 0.416666 0.750000 0 0.416666 0.833333 0 0.416666 0.916667 0 0.416666 1.000000 0 0.425000 0 0 0.425000 0.083333 0 0.425000 0.166667 0 0.425000 0.250000 0 0.425000 0.333333 0 0.425000 0.416667 0 0.425000 0.500000 0 0.425000 0.583333 0 0.425000 0.666667 0 0.425000 0.750000 0 0.425000 0.833333 0 0.425000 0.916667 0 0.425000 1.000000 0 0.433333 0 0 0.433333 0.083333 0 0.433333 0.166667 0 0.433333 0.250000 0 0.433333 0.333333 0 0.433333 0.416667 0 0.433333 0.500000 0 0.433333 0.583333 0 0.433333 0.666667 0 0.433333 0.750000 0 0.433333 0.833333 0 0.433333 0.916667 0 0.433333 1.000000 0 0.441666 0 0 0.441666 0.083333 0 0.441666 0.166667 0 0.441666 0.250000 0 0.441666 0.333333 0 0.441666 0.416667 0 0.441666 0.500000 0 0.441666 0.583333 0 0.441666 0.666667 0 0.441666 0.750000 0 0.441666 0.833333 0 0.441666 0.916667 0 0.441666 1.000000 0 0.450000 0 0 0.450000 0.083333 0 0.450000 0.166667 0 0.450000 0.250000 0 0.450000 0.333333 0 0.450000 0.416667 0 0.450000 0.500000 0 0.450000 0.583333 0 0.450000 0.666667 0 0.450000 0.750000 0 0.450000 0.833333 0 0.450000 0.916667 0 0.450000 1.000000 0 0.458333 0 0 0.458333 0.083333 0 0.458333 0.166667 0 0.458333 0.250000 0 0.458333 0.333333 0 0.458333 0.416667 0 0.458333 0.500000 0 0.458333 0.583333 0 0.458333 0.666667 0 0.458333 0.750000 0 0.458333 0.833333 0 0.458333 0.916667 0 0.458333 1.000000 0 0.466666 0 0 0.466666 0.083333 0 0.466666 0.166667 0 0.466666 0.250000 0 0.466666 0.333333 0 0.466666 0.416667 0 0.466666 0.500000 0 0.466666 0.583333 0 0.466666 0.666667 0 0.466666 0.750000 0 0.466666 0.833333 0 0.466666 0.916667 0 0.466666 1.000000 0 0.475000 0 0 0.475000 0.083333 0 0.475000 0.166667 0 0.475000 0.250000 0 0.475000 0.333333 0 0.475000 0.416667 0 0.475000 0.500000 0 0.475000 0.583333 0 0.475000 0.666667 0 0.475000 0.750000 0 0.475000 0.833333 0 0.475000 0.916667 0 0.475000 1.000000 0 0.483333 0 0 0.483333 0.083333 0 0.483333 0.166667 0 0.483333 0.250000 0 0.483333 0.333333 0 0.483333 0.416667 0 0.483333 0.500000 0 0.483333 0.583333 0 0.483333 0.666667 0 0.483333 0.750000 0 0.483333 0.833333 0 0.483333 0.916667 0 0.483333 1.000000 0 0.491666 0 0 0.491666 0.083333 0 0.491666 0.166667 0 0.491666 0.250000 0 0.491666 0.333333 0 0.491666 0.416667 0 0.491666 0.500000 0 0.491666 0.583333 0 0.491666 0.666667 0 0.491666 0.750000 0 0.491666 0.833333 0 0.491666 0.916667 0 0.491666 1.000000 0 0.500000 0 0 0.500000 0.083333 0 0.500000 0.166667 0 0.500000 0.250000 0 0.500000 0.333333 0 0.500000 0.416667 0 0.500000 0.500000 0 0.500000 0.583333 0 0.500000 0.666667 0 0.500000 0.750000 0 0.500000 0.833333 0 0.500000 0.916667 0 0.500000 1.000000 0 0.508333 0 0 0.508333 0.083333 0 0.508333 0.166667 0 0.508333 0.250000 0 0.508333 0.333333 0 0.508333 0.416667 0 0.508333 0.500000 0 0.508333 0.583333 0 0.508333 0.666667 0 0.508333 0.750000 0 0.508333 0.833333 0 0.508333 0.916667 0 0.508333 1.000000 0 0.516666 0 0 0.516666 0.083333 0 0.516666 0.166667 0 0.516666 0.250000 0 0.516666 0.333333 0 0.516666 0.416667 0 0.516666 0.500000 0 0.516666 0.583333 0 0.516666 0.666667 0 0.516666 0.750000 0 0.516666 0.833333 0 0.516666 0.916667 0 0.516666 1.000000 0 0.525000 0 0 0.525000 0.083333 0 0.525000 0.166667 0 0.525000 0.250000 0 0.525000 0.333333 0 0.525000 0.416667 0 0.525000 0.500000 0 0.525000 0.583333 0 0.525000 0.666667 0 0.525000 0.750000 0 0.525000 0.833333 0 0.525000 0.916667 0 0.525000 1.000000 0 0.533333 0 0 0.533333 0.083333 0 0.533333 0.166667 0 0.533333 0.250000 0 0.533333 0.333333 0 0.533333 0.416667 0 0.533333 0.500000 0 0.533333 0.583333 0 0.533333 0.666667 0 0.533333 0.750000 0 0.533333 0.833333 0 0.533333 0.916667 0 0.533333 1.000000 0 0.541666 0 0 0.541666 0.083333 0 0.541666 0.166667 0 0.541666 0.250000 0 0.541666 0.333333 0 0.541666 0.416667 0 0.541666 0.500000 0 0.541666 0.583333 0 0.541666 0.666667 0 0.541666 0.750000 0 0.541666 0.833333 0 0.541666 0.916667 0 0.541666 1.000000 0 0.550000 0 0 0.550000 0.083333 0 0.550000 0.166667 0 0.550000 0.250000 0 0.550000 0.333333 0 0.550000 0.416667 0 0.550000 0.500000 0 0.550000 0.583333 0 0.550000 0.666667 0 0.550000 0.750000 0 0.550000 0.833333 0 0.550000 0.916667 0 0.550000 1.000000 0 0.558333 0 0 0.558333 0.083333 0 0.558333 0.166667 0 0.558333 0.250000 0 0.558333 0.333333 0 0.558333 0.416667 0 0.558333 0.500000 0 0.558333 0.583333 0 0.558333 0.666667 0 0.558333 0.750000 0 0.558333 0.833333 0 0.558333 0.916667 0 0.558333 1.000000 0 0.566666 0 0 0.566666 0.083333 0 0.566666 0.166667 0 0.566666 0.250000 0 0.566666 0.333333 0 0.566666 0.416667 0 0.566666 0.500000 0 0.566666 0.583333 0 0.566666 0.666667 0 0.566666 0.750000 0 0.566666 0.833333 0 0.566666 0.916667 0 0.566666 1.000000 0 0.575000 0 0 0.575000 0.083333 0 0.575000 0.166667 0 0.575000 0.250000 0 0.575000 0.333333 0 0.575000 0.416667 0 0.575000 0.500000 0 0.575000 0.583333 0 0.575000 0.666667 0 0.575000 0.750000 0 0.575000 0.833333 0 0.575000 0.916667 0 0.575000 1.000000 0 0.583333 0 0 0.583333 0.083333 0 0.583333 0.166667 0 0.583333 0.250000 0 0.583333 0.333333 0 0.583333 0.416667 0 0.583333 0.500000 0 0.583333 0.583333 0 0.583333 0.666667 0 0.583333 0.750000 0 0.583333 0.833333 0 0.583333 0.916667 0 0.583333 1.000000 0 0.591666 0 0 0.591666 0.083333 0 0.591666 0.166667 0 0.591666 0.250000 0 0.591666 0.333333 0 0.591666 0.416667 0 0.591666 0.500000 0 0.591666 0.583333 0 0.591666 0.666667 0 0.591666 0.750000 0 0.591666 0.833333 0 0.591666 0.916667 0 0.591666 1.000000 0 0.599999 0 0 0.599999 0.083333 0 0.599999 0.166667 0 0.599999 0.250000 0 0.599999 0.333333 0 0.599999 0.416667 0 0.599999 0.500000 0 0.599999 0.583333 0 0.599999 0.666667 0 0.599999 0.750000 0 0.599999 0.833333 0 0.599999 0.916667 0 0.599999 1.000000 0 0.608333 0 0 0.608333 0.083333 0 0.608333 0.166667 0 0.608333 0.250000 0 0.608333 0.333333 0 0.608333 0.416667 0 0.608333 0.500000 0 0.608333 0.583333 0 0.608333 0.666667 0 0.608333 0.750000 0 0.608333 0.833333 0 0.608333 0.916667 0 0.608333 1.000000 0 0.616666 0 0 0.616666 0.083333 0 0.616666 0.166667 0 0.616666 0.250000 0 0.616666 0.333333 0 0.616666 0.416667 0 0.616666 0.500000 0 0.616666 0.583333 0 0.616666 0.666667 0 0.616666 0.750000 0 0.616666 0.833333 0 0.616666 0.916667 0 0.616666 1.000000 0 0.624999 0 0 0.624999 0.083333 0 0.624999 0.166667 0 0.624999 0.250000 0 0.624999 0.333333 0 0.624999 0.416667 0 0.624999 0.500000 0 0.624999 0.583333 0 0.624999 0.666667 0 0.624999 0.750000 0 0.624999 0.833333 0 0.624999 0.916667 0 0.624999 1.000000 0 0.633333 0 0 0.633333 0.083333 0 0.633333 0.166667 0 0.633333 0.250000 0 0.633333 0.333333 0 0.633333 0.416667 0 0.633333 0.500000 0 0.633333 0.583333 0 0.633333 0.666667 0 0.633333 0.750000 0 0.633333 0.833333 0 0.633333 0.916667 0 0.633333 1.000000 0 0.641666 0 0 0.641666 0.083333 0 0.641666 0.166667 0 0.641666 0.250000 0 0.641666 0.333333 0 0.641666 0.416667 0 0.641666 0.500000 0 0.641666 0.583333 0 0.641666 0.666667 0 0.641666 0.750000 0 0.641666 0.833333 0 0.641666 0.916667 0 0.641666 1.000000 0 0.649999 0 0 0.649999 0.083333 0 0.649999 0.166667 0 0.649999 0.250000 0 0.649999 0.333333 0 0.649999 0.416667 0 0.649999 0.500000 0 0.649999 0.583333 0 0.649999 0.666667 0 0.649999 0.750000 0 0.649999 0.833333 0 0.649999 0.916667 0 0.649999 1.000000 0 0.658333 0 0 0.658333 0.083333 0 0.658333 0.166667 0 0.658333 0.250000 0 0.658333 0.333333 0 0.658333 0.416667 0 0.658333 0.500000 0 0.658333 0.583333 0 0.658333 0.666667 0 0.658333 0.750000 0 0.658333 0.833333 0 0.658333 0.916667 0 0.658333 1.000000 0 0.666666 0 0 0.666666 0.083333 0 0.666666 0.166667 0 0.666666 0.250000 0 0.666666 0.333333 0 0.666666 0.416667 0 0.666666 0.500000 0 0.666666 0.583333 0 0.666666 0.666667 0 0.666666 0.750000 0 0.666666 0.833333 0 0.666666 0.916667 0 0.666666 1.000000 0 0.675000 0 0 0.675000 0.083333 0 0.675000 0.166667 0 0.675000 0.250000 0 0.675000 0.333333 0 0.675000 0.416667 0 0.675000 0.500000 0 0.675000 0.583333 0 0.675000 0.666667 0 0.675000 0.750000 0 0.675000 0.833333 0 0.675000 0.916667 0 0.675000 1.000000 0 0.683333 0 0 0.683333 0.083333 0 0.683333 0.166667 0 0.683333 0.250000 0 0.683333 0.333333 0 0.683333 0.416667 0 0.683333 0.500000 0 0.683333 0.583333 0 0.683333 0.666667 0 0.683333 0.750000 0 0.683333 0.833333 0 0.683333 0.916667 0 0.683333 1.000000 0 0.691666 0 0 0.691666 0.083333 0 0.691666 0.166667 0 0.691666 0.250000 0 0.691666 0.333333 0 0.691666 0.416667 0 0.691666 0.500000 0 0.691666 0.583333 0 0.691666 0.666667 0 0.691666 0.750000 0 0.691666 0.833333 0 0.691666 0.916667 0 0.691666 1.000000 0 0.700000 0 0 0.700000 0.083333 0 0.700000 0.166667 0 0.700000 0.250000 0 0.700000 0.333333 0 0.700000 0.416667 0 0.700000 0.500000 0 0.700000 0.583333 0 0.700000 0.666667 0 0.700000 0.750000 0 0.700000 0.833333 0 0.700000 0.916667 0 0.700000 1.000000 0 0.708333 0 0 0.708333 0.083333 0 0.708333 0.166667 0 0.708333 0.250000 0 0.708333 0.333333 0 0.708333 0.416667 0 0.708333 0.500000 0 0.708333 0.583333 0 0.708333 0.666667 0 0.708333 0.750000 0 0.708333 0.833333 0 0.708333 0.916667 0 0.708333 1.000000 0 0.716666 0 0 0.716666 0.083333 0 0.716666 0.166667 0 0.716666 0.250000 0 0.716666 0.333333 0 0.716666 0.416667 0 0.716666 0.500000 0 0.716666 0.583333 0 0.716666 0.666667 0 0.716666 0.750000 0 0.716666 0.833333 0 0.716666 0.916667 0 0.716666 1.000000 0 0.725000 0 0 0.725000 0.083333 0 0.725000 0.166667 0 0.725000 0.250000 0 0.725000 0.333333 0 0.725000 0.416667 0 0.725000 0.500000 0 0.725000 0.583333 0 0.725000 0.666667 0 0.725000 0.750000 0 0.725000 0.833333 0 0.725000 0.916667 0 0.725000 1.000000 0 0.733333 0 0 0.733333 0.083333 0 0.733333 0.166667 0 0.733333 0.250000 0 0.733333 0.333333 0 0.733333 0.416667 0 0.733333 0.500000 0 0.733333 0.583333 0 0.733333 0.666667 0 0.733333 0.750000 0 0.733333 0.833333 0 0.733333 0.916667 0 0.733333 1.000000 0 0.741666 0 0 0.741666 0.083333 0 0.741666 0.166667 0 0.741666 0.250000 0 0.741666 0.333333 0 0.741666 0.416667 0 0.741666 0.500000 0 0.741666 0.583333 0 0.741666 0.666667 0 0.741666 0.750000 0 0.741666 0.833333 0 0.741666 0.916667 0 0.741666 1.000000 0 0.750000 0 0 0.750000 0.083333 0 0.750000 0.166667 0 0.750000 0.250000 0 0.750000 0.333333 0 0.750000 0.416667 0 0.750000 0.500000 0 0.750000 0.583333 0 0.750000 0.666667 0 0.750000 0.750000 0 0.750000 0.833333 0 0.750000 0.916667 0 0.750000 1.000000 0 0.758333 0 0 0.758333 0.083333 0 0.758333 0.166667 0 0.758333 0.250000 0 0.758333 0.333333 0 0.758333 0.416667 0 0.758333 0.500000 0 0.758333 0.583333 0 0.758333 0.666667 0 0.758333 0.750000 0 0.758333 0.833333 0 0.758333 0.916667 0 0.758333 1.000000 0 0.766667 0 0 0.766667 0.083333 0 0.766667 0.166667 0 0.766667 0.250000 0 0.766667 0.333333 0 0.766667 0.416667 0 0.766667 0.500000 0 0.766667 0.583333 0 0.766667 0.666667 0 0.766667 0.750000 0 0.766667 0.833333 0 0.766667 0.916667 0 0.766667 1.000000 0 0.775000 0 0 0.775000 0.083333 0 0.775000 0.166667 0 0.775000 0.250000 0 0.775000 0.333333 0 0.775000 0.416667 0 0.775000 0.500000 0 0.775000 0.583333 0 0.775000 0.666667 0 0.775000 0.750000 0 0.775000 0.833333 0 0.775000 0.916667 0 0.775000 1.000000 0 0.783333 0 0 0.783333 0.083333 0 0.783333 0.166667 0 0.783333 0.250000 0 0.783333 0.333333 0 0.783333 0.416667 0 0.783333 0.500000 0 0.783333 0.583333 0 0.783333 0.666667 0 0.783333 0.750000 0 0.783333 0.833333 0 0.783333 0.916667 0 0.783333 1.000000 0 0.791667 0 0 0.791667 0.083333 0 0.791667 0.166667 0 0.791667 0.250000 0 0.791667 0.333333 0 0.791667 0.416667 0 0.791667 0.500000 0 0.791667 0.583333 0 0.791667 0.666667 0 0.791667 0.750000 0 0.791667 0.833333 0 0.791667 0.916667 0 0.791667 1.000000 0 0.800000 0 0 0.800000 0.083333 0 0.800000 0.166667 0 0.800000 0.250000 0 0.800000 0.333333 0 0.800000 0.416667 0 0.800000 0.500000 0 0.800000 0.583333 0 0.800000 0.666667 0 0.800000 0.750000 0 0.800000 0.833333 0 0.800000 0.916667 0 0.800000 1.000000 0 0.808333 0 0 0.808333 0.083333 0 0.808333 0.166667 0 0.808333 0.250000 0 0.808333 0.333333 0 0.808333 0.416667 0 0.808333 0.500000 0 0.808333 0.583333 0 0.808333 0.666667 0 0.808333 0.750000 0 0.808333 0.833333 0 0.808333 0.916667 0 0.808333 1.000000 0 0.816667 0 0 0.816667 0.083333 0 0.816667 0.166667 0 0.816667 0.250000 0 0.816667 0.333333 0 0.816667 0.416667 0 0.816667 0.500000 0 0.816667 0.583333 0 0.816667 0.666667 0 0.816667 0.750000 0 0.816667 0.833333 0 0.816667 0.916667 0 0.816667 1.000000 0 0.825000 0 0 0.825000 0.083333 0 0.825000 0.166667 0 0.825000 0.250000 0 0.825000 0.333333 0 0.825000 0.416667 0 0.825000 0.500000 0 0.825000 0.583333 0 0.825000 0.666667 0 0.825000 0.750000 0 0.825000 0.833333 0 0.825000 0.916667 0 0.825000 1.000000 0 0.833333 0 0 0.833333 0.083333 0 0.833333 0.166667 0 0.833333 0.250000 0 0.833333 0.333333 0 0.833333 0.416667 0 0.833333 0.500000 0 0.833333 0.583333 0 0.833333 0.666667 0 0.833333 0.750000 0 0.833333 0.833333 0 0.833333 0.916667 0 0.833333 1.000000 0 0.841667 0 0 0.841667 0.083333 0 0.841667 0.166667 0 0.841667 0.250000 0 0.841667 0.333333 0 0.841667 0.416667 0 0.841667 0.500000 0 0.841667 0.583333 0 0.841667 0.666667 0 0.841667 0.750000 0 0.841667 0.833333 0 0.841667 0.916667 0 0.841667 1.000000 0 0.850000 0 0 0.850000 0.083333 0 0.850000 0.166667 0 0.850000 0.250000 0 0.850000 0.333333 0 0.850000 0.416667 0 0.850000 0.500000 0 0.850000 0.583333 0 0.850000 0.666667 0 0.850000 0.750000 0 0.850000 0.833333 0 0.850000 0.916667 0 0.850000 1.000000 0 0.858334 0 0 0.858334 0.083333 0 0.858334 0.166667 0 0.858334 0.250000 0 0.858334 0.333333 0 0.858334 0.416667 0 0.858334 0.500000 0 0.858334 0.583333 0 0.858334 0.666667 0 0.858334 0.750000 0 0.858334 0.833333 0 0.858334 0.916667 0 0.858334 1.000000 0 0.866667 0 0 0.866667 0.083333 0 0.866667 0.166667 0 0.866667 0.250000 0 0.866667 0.333333 0 0.866667 0.416667 0 0.866667 0.500000 0 0.866667 0.583333 0 0.866667 0.666667 0 0.866667 0.750000 0 0.866667 0.833333 0 0.866667 0.916667 0 0.866667 1.000000 0 0.875000 0 0 0.875000 0.083333 0 0.875000 0.166667 0 0.875000 0.250000 0 0.875000 0.333333 0 0.875000 0.416667 0 0.875000 0.500000 0 0.875000 0.583333 0 0.875000 0.666667 0 0.875000 0.750000 0 0.875000 0.833333 0 0.875000 0.916667 0 0.875000 1.000000 0 0.883334 0 0 0.883334 0.083333 0 0.883334 0.166667 0 0.883334 0.250000 0 0.883334 0.333333 0 0.883334 0.416667 0 0.883334 0.500000 0 0.883334 0.583333 0 0.883334 0.666667 0 0.883334 0.750000 0 0.883334 0.833333 0 0.883334 0.916667 0 0.883334 1.000000 0 0.891667 0 0 0.891667 0.083333 0 0.891667 0.166667 0 0.891667 0.250000 0 0.891667 0.333333 0 0.891667 0.416667 0 0.891667 0.500000 0 0.891667 0.583333 0 0.891667 0.666667 0 0.891667 0.750000 0 0.891667 0.833333 0 0.891667 0.916667 0 0.891667 1.000000 0 0.900000 0 0 0.900000 0.083333 0 0.900000 0.166667 0 0.900000 0.250000 0 0.900000 0.333333 0 0.900000 0.416667 0 0.900000 0.500000 0 0.900000 0.583333 0 0.900000 0.666667 0 0.900000 0.750000 0 0.900000 0.833333 0 0.900000 0.916667 0 0.900000 1.000000 0 0.908334 0 0 0.908334 0.083333 0 0.908334 0.166667 0 0.908334 0.250000 0 0.908334 0.333333 0 0.908334 0.416667 0 0.908334 0.500000 0 0.908334 0.583333 0 0.908334 0.666667 0 0.908334 0.750000 0 0.908334 0.833333 0 0.908334 0.916667 0 0.908334 1.000000 0 0.916667 0 0 0.916667 0.083333 0 0.916667 0.166667 0 0.916667 0.250000 0 0.916667 0.333333 0 0.916667 0.416667 0 0.916667 0.500000 0 0.916667 0.583333 0 0.916667 0.666667 0 0.916667 0.750000 0 0.916667 0.833333 0 0.916667 0.916667 0 0.916667 1.000000 0 0.925000 0 0 0.925000 0.083333 0 0.925000 0.166667 0 0.925000 0.250000 0 0.925000 0.333333 0 0.925000 0.416667 0 0.925000 0.500000 0 0.925000 0.583333 0 0.925000 0.666667 0 0.925000 0.750000 0 0.925000 0.833333 0 0.925000 0.916667 0 0.925000 1.000000 0 0.933334 0 0 0.933334 0.083333 0 0.933334 0.166667 0 0.933334 0.250000 0 0.933334 0.333333 0 0.933334 0.416667 0 0.933334 0.500000 0 0.933334 0.583333 0 0.933334 0.666667 0 0.933334 0.750000 0 0.933334 0.833333 0 0.933334 0.916667 0 0.933334 1.000000 0 0.941667 0 0 0.941667 0.083333 0 0.941667 0.166667 0 0.941667 0.250000 0 0.941667 0.333333 0 0.941667 0.416667 0 0.941667 0.500000 0 0.941667 0.583333 0 0.941667 0.666667 0 0.941667 0.750000 0 0.941667 0.833333 0 0.941667 0.916667 0 0.941667 1.000000 0 0.950001 0 0 0.950001 0.083333 0 0.950001 0.166667 0 0.950001 0.250000 0 0.950001 0.333333 0 0.950001 0.416667 0 0.950001 0.500000 0 0.950001 0.583333 0 0.950001 0.666667 0 0.950001 0.750000 0 0.950001 0.833333 0 0.950001 0.916667 0 0.950001 1.000000 0 0.958334 0 0 0.958334 0.083333 0 0.958334 0.166667 0 0.958334 0.250000 0 0.958334 0.333333 0 0.958334 0.416667 0 0.958334 0.500000 0 0.958334 0.583333 0 0.958334 0.666667 0 0.958334 0.750000 0 0.958334 0.833333 0 0.958334 0.916667 0 0.958334 1.000000 0 0.966667 0 0 0.966667 0.083333 0 0.966667 0.166667 0 0.966667 0.250000 0 0.966667 0.333333 0 0.966667 0.416667 0 0.966667 0.500000 0 0.966667 0.583333 0 0.966667 0.666667 0 0.966667 0.750000 0 0.966667 0.833333 0 0.966667 0.916667 0 0.966667 1.000000 0 0.975001 0 0 0.975001 0.083333 0 0.975001 0.166667 0 0.975001 0.250000 0 0.975001 0.333333 0 0.975001 0.416667 0 0.975001 0.500000 0 0.975001 0.583333 0 0.975001 0.666667 0 0.975001 0.750000 0 0.975001 0.833333 0 0.975001 0.916667 0 0.975001 1.000000 0 0.983334 0 0 0.983334 0.083333 0 0.983334 0.166667 0 0.983334 0.250000 0 0.983334 0.333333 0 0.983334 0.416667 0 0.983334 0.500000 0 0.983334 0.583333 0 0.983334 0.666667 0 0.983334 0.750000 0 0.983334 0.833333 0 0.983334 0.916667 0 0.983334 1.000000 0 0.991667 0 0 0.991667 0.083333 0 0.991667 0.166667 0 0.991667 0.250000 0 0.991667 0.333333 0 0.991667 0.416667 0 0.991667 0.500000 0 0.991667 0.583333 0 0.991667 0.666667 0 0.991667 0.750000 0 0.991667 0.833333 0 0.991667 0.916667 0 0.991667 1.000000 0 1.000001 0 0 1.000001 0.083333 0 1.000001 0.166667 0 1.000001 0.250000 0 1.000001 0.333333 0 1.000001 0.416667 0 1.000001 0.500000 0 1.000001 0.583333 0 1.000001 0.666667 0 1.000001 0.750000 0 1.000001 0.833333 0 1.000001 0.916667 0 1.000001 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="1573" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="2880">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 12 1 13 13 2 14 0 0 0 13 2 14 1 3 1 1 3 1 13 2 14 14 4 15 1 3 1 14 4 15 2 5 2 2 5 2 14 4 15 15 6 16 2 5 2 15 6 16 3 7 3 3 7 3 15 6 16 16 8 17 3 7 3 16 8 17 4 9 4 4 9 4 16 8 17 17 10 18 4 9 4 17 10 18 5 11 5 5 11 5 17 10 18 18 12 19 5 11 5 18 12 19 6 13 6 6 13 6 18 12 19 19 14 20 6 13 6 19 14 20 7 15 7 7 15 7 19 14 20 20 16 21 7 15 7 20 16 21 8 17 8 8 17 8 20 16 21 21 18 22 8 17 8 21 18 22 9 19 9 9 19 9 21 18 22 22 20 23 9 19 9 22 20 23 10 21 10 10 21 10 22 20 23 23 22 24 10 21 10 23 22 24 11 23 11 11 23 11 23 22 24 12 1 25 11 23 11 12 1 25 0 0 12 12 1 13 24 24 26 25 25 27 12 1 13 25 25 27 13 2 14 13 2 14 25 25 27 26 26 28 13 2 14 26 26 28 14 4 15 14 4 15 26 26 28 27 27 29 14 4 15 27 27 29 15 6 16 15 6 16 27 27 29 28 28 30 15 6 16 28 28 30 16 8 17 16 8 17 28 28 30 29 29 31 16 8 17 29 29 31 17 10 18 17 10 18 29 29 31 30 30 32 17 10 18 30 30 32 18 12 19 18 12 19 30 30 32 31 31 33 18 12 19 31 31 33 19 14 20 19 14 20 31 31 33 32 32 34 19 14 20 32 32 34 20 16 21 20 16 21 32 32 34 33 33 35 20 16 21 33 33 35 21 18 22 21 18 22 33 33 35 34 34 36 21 18 22 34 34 36 22 20 23 22 20 23 34 34 36 35 35 37 22 20 23 35 35 37 23 22 24 23 22 24 35 35 37 24 24 38 23 22 24 24 24 38 12 1 25 24 24 26 36 36 39 37 37 40 24 24 26 37 37 40 25 25 27 25 25 27 37 37 40 38 38 41 25 25 27 38 38 41 26 26 28 26 26 28 38 38 41 39 39 42 26 26 28 39 39 42 27 27 29 27 27 29 39 39 42 40 40 43 27 27 29 40 40 43 28 28 30 28 28 30 40 40 43 41 41 44 28 28 30 41 41 44 29 29 31 29 29 31 41 41 44 42 42 45 29 29 31 42 42 45 30 30 32 30 30 32 42 42 45 43 43 46 30 30 32 43 43 46 31 31 33 31 31 33 43 43 46 44 44 47 31 31 33 44 44 47 32 32 34 32 32 34 44 44 47 45 45 48 32 32 34 45 45 48 33 33 35 33 33 35 45 45 48 46 46 49 33 33 35 46 46 49 34 34 36 34 34 36 46 46 49 47 47 50 34 34 36 47 47 50 35 35 37 35 35 37 47 47 50 36 36 51 35 35 37 36 36 51 24 24 38 36 36 39 48 48 52 49 49 53 36 36 39 49 49 53 37 37 40 37 37 40 49 49 53 50 50 54 37 37 40 50 50 54 38 38 41 38 38 41 50 50 54 51 51 55 38 38 41 51 51 55 39 39 42 39 39 42 51 51 55 52 52 56 39 39 42 52 52 56 40 40 43 40 40 43 52 52 56 53 53 57 40 40 43 53 53 57 41 41 44 41 41 44 53 53 57 54 54 58 41 41 44 54 54 58 42 42 45 42 42 45 54 54 58 55 55 59 42 42 45 55 55 59 43 43 46 43 43 46 55 55 59 56 56 60 43 43 46 56 56 60 44 44 47 44 44 47 56 56 60 57 57 61 44 44 47 57 57 61 45 45 48 45 45 48 57 57 61 58 58 62 45 45 48 58 58 62 46 46 49 46 46 49 58 58 62 59 59 63 46 46 49 59 59 63 47 47 50 47 47 50 59 59 63 48 48 64 47 47 50 48 48 64 36 36 51 48 48 52 60 60 65 61 61 66 48 48 52 61 61 66 49 49 53 49 49 53 61 61 66 62 62 67 49 49 53 62 62 67 50 50 54 50 50 54 62 62 67 63 63 68 50 50 54 63 63 68 51 51 55 51 51 55 63 63 68 64 64 69 51 51 55 64 64 69 52 52 56 52 52 56 64 64 69 65 65 70 52 52 56 65 65 70 53 53 57 53 53 57 65 65 70 66 66 71 53 53 57 66 66 71 54 54 58 54 54 58 66 66 71 67 67 72 54 54 58 67 67 72 55 55 59 55 55 59 67 67 72 68 68 73 55 55 59 68 68 73 56 56 60 56 56 60 68 68 73 69 69 74 56 56 60 69 69 74 57 57 61 57 57 61 69 69 74 70 70 75 57 57 61 70 70 75 58 58 62 58 58 62 70 70 75 71 71 76 58 58 62 71 71 76 59 59 63 59 59 63 71 71 76 60 60 77 59 59 63 60 60 77 48 48 64 60 60 65 72 72 78 73 73 79 60 60 65 73 73 79 61 61 66 61 61 66 73 73 79 74 74 80 61 61 66 74 74 80 62 62 67 62 62 67 74 74 80 75 75 81 62 62 67 75 75 81 63 63 68 63 63 68 75 75 81 76 76 82 63 63 68 76 76 82 64 64 69 64 64 69 76 76 82 77 77 83 64 64 69 77 77 83 65 65 70 65 65 70 77 77 83 78 78 84 65 65 70 78 78 84 66 66 71 66 66 71 78 78 84 79 79 85 66 66 71 79 79 85 67 67 72 67 67 72 79 79 85 80 80 86 67 67 72 80 80 86 68 68 73 68 68 73 80 80 86 81 81 87 68 68 73 81 81 87 69 69 74 69 69 74 81 81 87 82 82 88 69 69 74 82 82 88 70 70 75 70 70 75 82 82 88 83 83 89 70 70 75 83 83 89 71 71 76 71 71 76 83 83 89 72 72 90 71 71 76 72 72 90 60 60 77 72 72 78 84 84 91 85 85 92 72 72 78 85 85 92 73 73 79 73 73 79 85 85 92 86 86 93 73 73 79 86 86 93 74 74 80 74 74 80 86 86 93 87 87 94 74 74 80 87 87 94 75 75 81 75 75 81 87 87 94 88 88 95 75 75 81 88 88 95 76 76 82 76 76 82 88 88 95 89 89 96 76 76 82 89 89 96 77 77 83 77 77 83 89 89 96 90 90 97 77 77 83 90 90 97 78 78 84 78 78 84 90 90 97 91 91 98 78 78 84 91 91 98 79 79 85 79 79 85 91 91 98 92 92 99 79 79 85 92 92 99 80 80 86 80 80 86 92 92 99 93 93 100 80 80 86 93 93 100 81 81 87 81 81 87 93 93 100 94 94 101 81 81 87 94 94 101 82 82 88 82 82 88 94 94 101 95 95 102 82 82 88 95 95 102 83 83 89 83 83 89 95 95 102 84 84 103 83 83 89 84 84 103 72 72 90 84 84 91 96 96 104 97 97 105 84 84 91 97 97 105 85 85 92 85 85 92 97 97 105 98 98 106 85 85 92 98 98 106 86 86 93 86 86 93 98 98 106 99 99 107 86 86 93 99 99 107 87 87 94 87 87 94 99 99 107 100 100 108 87 87 94 100 100 108 88 88 95 88 88 95 100 100 108 101 101 109 88 88 95 101 101 109 89 89 96 89 89 96 101 101 109 102 102 110 89 89 96 102 102 110 90 90 97 90 90 97 102 102 110 103 103 111 90 90 97 103 103 111 91 91 98 91 91 98 103 103 111 104 104 112 91 91 98 104 104 112 92 92 99 92 92 99 104 104 112 105 105 113 92 92 99 105 105 113 93 93 100 93 93 100 105 105 113 106 106 114 93 93 100 106 106 114 94 94 101 94 94 101 106 106 114 107 107 115 94 94 101 107 107 115 95 95 102 95 95 102 107 107 115 96 96 116 95 95 102 96 96 116 84 84 103 96 96 104 108 108 117 109 109 118 96 96 104 109 109 118 97 97 105 97 97 105 109 109 118 110 110 119 97 97 105 110 110 119 98 98 106 98 98 106 110 110 119 111 111 120 98 98 106 111 111 120 99 99 107 99 99 107 111 111 120 112 112 121 99 99 107 112 112 121 100 100 108 100 100 108 112 112 121 113 113 122 100 100 108 113 113 122 101 101 109 101 101 109 113 113 122 114 114 123 101 101 109 114 114 123 102 102 110 102 102 110 114 114 123 115 115 124 102 102 110 115 115 124 103 103 111 103 103 111 115 115 124 116 116 125 103 103 111 116 116 125 104 104 112 104 104 112 116 116 125 117 117 126 104 104 112 117 117 126 105 105 113 105 105 113 117 117 126 118 118 127 105 105 113 118 118 127 106 106 114 106 106 114 118 118 127 119 119 128 106 106 114 119 119 128 107 107 115 107 107 115 119 119 128 108 108 129 107 107 115 108 108 129 96 96 116 108 108 117 120 120 130 121 121 131 108 108 117 121 121 131 109 109 118 109 109 118 121 121 131 122 122 132 109 109 118 122 122 132 110 110 119 110 110 119 122 122 132 123 123 133 110 110 119 123 123 133 111 111 120 111 111 120 123 123 133 124 124 134 111 111 120 124 124 134 112 112 121 112 112 121 124 124 134 125 125 135 112 112 121 125 125 135 113 113 122 113 113 122 125 125 135 126 126 136 113 113 122 126 126 136 114 114 123 114 114 123 126 126 136 127 127 137 114 114 123 127 127 137 115 115 124 115 115 124 127 127 137 128 128 138 115 115 124 128 128 138 116 116 125 116 116 125 128 128 138 129 129 139 116 116 125 129 129 139 117 117 126 117 117 126 129 129 139 130 130 140 117 117 126 130 130 140 118 118 127 118 118 127 130 130 140 131 131 141 118 118 127 131 131 141 119 119 128 119 119 128 131 131 141 120 120 142 119 119 128 120 120 142 108 108 129 120 120 130 132 132 143 133 133 144 120 120 130 133 133 144 121 121 131 121 121 131 133 133 144 134 134 145 121 121 131 134 134 145 122 122 132 122 122 132 134 134 145 135 135 146 122 122 132 135 135 146 123 123 133 123 123 133 135 135 146 136 136 147 123 123 133 136 136 147 124 124 134 124 124 134 136 136 147 137 137 148 124 124 134 137 137 148 125 125 135 125 125 135 137 137 148 138 138 149 125 125 135 138 138 149 126 126 136 126 126 136 138 138 149 139 139 150 126 126 136 139 139 150 127 127 137 127 127 137 139 139 150 140 140 151 127 127 137 140 140 151 128 128 138 128 128 138 140 140 151 141 141 152 128 128 138 141 141 152 129 129 139 129 129 139 141 141 152 142 142 153 129 129 139 142 142 153 130 130 140 130 130 140 142 142 153 143 143 154 130 130 140 143 143 154 131 131 141 131 131 141 143 143 154 132 132 155 131 131 141 132 132 155 120 120 142 132 132 143 144 144 156 145 145 157 132 132 143 145 145 157 133 133 144 133 133 144 145 145 157 146 146 158 133 133 144 146 146 158 134 134 145 134 134 145 146 146 158 147 147 159 134 134 145 147 147 159 135 135 146 135 135 146 147 147 159 148 148 160 135 135 146 148 148 160 136 136 147 136 136 147 148 148 160 149 149 161 136 136 147 149 149 161 137 137 148 137 137 148 149 149 161 150 150 162 137 137 148 150 150 162 138 138 149 138 138 149 150 150 162 151 151 163 138 138 149 151 151 163 139 139 150 139 139 150 151 151 163 152 152 164 139 139 150 152 152 164 140 140 151 140 140 151 152 152 164 153 153 165 140 140 151 153 153 165 141 141 152 141 141 152 153 153 165 154 154 166 141 141 152 154 154 166 142 142 153 142 142 153 154 154 166 155 155 167 142 142 153 155 155 167 143 143 154 143 143 154 155 155 167 144 144 168 143 143 154 144 144 168 132 132 155 144 144 156 156 156 169 157 157 170 144 144 156 157 157 170 145 145 157 145 145 157 157 157 170 158 158 171 145 145 157 158 158 171 146 146 158 146 146 158 158 158 171 159 159 172 146 146 158 159 159 172 147 147 159 147 147 159 159 159 172 160 160 173 147 147 159 160 160 173 148 148 160 148 148 160 160 160 173 161 161 174 148 148 160 161 161 174 149 149 161 149 149 161 161 161 174 162 162 175 149 149 161 162 162 175 150 150 162 150 150 162 162 162 175 163 163 176 150 150 162 163 163 176 151 151 163 151 151 163 163 163 176 164 164 177 151 151 163 164 164 177 152 152 164 152 152 164 164 164 177 165 165 178 152 152 164 165 165 178 153 153 165 153 153 165 165 165 178 166 166 179 153 153 165 166 166 179 154 154 166 154 154 166 166 166 179 167 167 180 154 154 166 167 167 180 155 155 167 155 155 167 167 167 180 156 156 181 155 155 167 156 156 181 144 144 168 156 156 169 168 168 182 169 169 183 156 156 169 169 169 183 157 157 170 157 157 170 169 169 183 170 170 184 157 157 170 170 170 184 158 158 171 158 158 171 170 170 184 171 171 185 158 158 171 171 171 185 159 159 172 159 159 172 171 171 185 172 172 186 159 159 172 172 172 186 160 160 173 160 160 173 172 172 186 173 173 187 160 160 173 173 173 187 161 161 174 161 161 174 173 173 187 174 174 188 161 161 174 174 174 188 162 162 175 162 162 175 174 174 188 175 175 189 162 162 175 175 175 189 163 163 176 163 163 176 175 175 189 176 176 190 163 163 176 176 176 190 164 164 177 164 164 177 176 176 190 177 177 191 164 164 177 177 177 191 165 165 178 165 165 178 177 177 191 178 178 192 165 165 178 178 178 192 166 166 179 166 166 179 178 178 192 179 179 193 166 166 179 179 179 193 167 167 180 167 167 180 179 179 193 168 168 194 167 167 180 168 168 194 156 156 181 168 168 182 180 180 195 181 181 196 168 168 182 181 181 196 169 169 183 169 169 183 181 181 196 182 182 197 169 169 183 182 182 197 170 170 184 170 170 184 182 182 197 183 183 198 170 170 184 183 183 198 171 171 185 171 171 185 183 183 198 184 184 199 171 171 185 184 184 199 172 172 186 172 172 186 184 184 199 185 185 200 172 172 186 185 185 200 173 173 187 173 173 187 185 185 200 186 186 201 173 173 187 186 186 201 174 174 188 174 174 188 186 186 201 187 187 202 174 174 188 187 187 202 175 175 189 175 175 189 187 187 202 188 188 203 175 175 189 188 188 203 176 176 190 176 176 190 188 188 203 189 189 204 176 176 190 189 189 204 177 177 191 177 177 191 189 189 204 190 190 205 177 177 191 190 190 205 178 178 192 178 178 192 190 190 205 191 191 206 178 178 192 191 191 206 179 179 193 179 179 193 191 191 206 180 180 207 179 179 193 180 180 207 168 168 194 180 180 195 192 192 208 193 193 209 180 180 195 193 193 209 181 181 196 181 181 196 193 193 209 194 194 210 181 181 196 194 194 210 182 182 197 182 182 197 194 194 210 195 195 211 182 182 197 195 195 211 183 183 198 183 183 198 195 195 211 196 196 212 183 183 198 196 196 212 184 184 199 184 184 199 196 196 212 197 197 213 184 184 199 197 197 213 185 185 200 185 185 200 197 197 213 198 198 214 185 185 200 198 198 214 186 186 201 186 186 201 198 198 214 199 199 215 186 186 201 199 199 215 187 187 202 187 187 202 199 199 215 200 200 216 187 187 202 200 200 216 188 188 203 188 188 203 200 200 216 201 201 217 188 188 203 201 201 217 189 189 204 189 189 204 201 201 217 202 202 218 189 189 204 202 202 218 190 190 205 190 190 205 202 202 218 203 203 219 190 190 205 203 203 219 191 191 206 191 191 206 203 203 219 192 192 220 191 191 206 192 192 220 180 180 207 192 192 208 204 204 221 205 205 222 192 192 208 205 205 222 193 193 209 193 193 209 205 205 222 206 206 223 193 193 209 206 206 223 194 194 210 194 194 210 206 206 223 207 207 224 194 194 210 207 207 224 195 195 211 195 195 211 207 207 224 208 208 225 195 195 211 208 208 225 196 196 212 196 196 212 208 208 225 209 209 226 196 196 212 209 209 226 197 197 213 197 197 213 209 209 226 210 210 227 197 197 213 210 210 227 198 198 214 198 198 214 210 210 227 211 211 228 198 198 214 211 211 228 199 199 215 199 199 215 211 211 228 212 212 229 199 199 215 212 212 229 200 200 216 200 200 216 212 212 229 213 213 230 200 200 216 213 213 230 201 201 217 201 201 217 213 213 230 214 214 231 201 201 217 214 214 231 202 202 218 202 202 218 214 214 231 215 215 232 202 202 218 215 215 232 203 203 219 203 203 219 215 215 232 204 204 233 203 203 219 204 204 233 192 192 220 204 204 221 216 216 234 217 217 235 204 204 221 217 217 235 205 205 222 205 205 222 217 217 235 218 218 236 205 205 222 218 218 236 206 206 223 206 206 223 218 218 236 219 219 237 206 206 223 219 219 237 207 207 224 207 207 224 219 219 237 220 220 238 207 207 224 220 220 238 208 208 225 208 208 225 220 220 238 221 221 239 208 208 225 221 221 239 209 209 226 209 209 226 221 221 239 222 222 240 209 209 226 222 222 240 210 210 227 210 210 227 222 222 240 223 223 241 210 210 227 223 223 241 211 211 228 211 211 228 223 223 241 224 224 242 211 211 228 224 224 242 212 212 229 212 212 229 224 224 242 225 225 243 212 212 229 225 225 243 213 213 230 213 213 230 225 225 243 226 226 244 213 213 230 226 226 244 214 214 231 214 214 231 226 226 244 227 227 245 214 214 231 227 227 245 215 215 232 215 215 232 227 227 245 216 216 246 215 215 232 216 216 246 204 204 233 216 216 234 228 228 247 229 229 248 216 216 234 229 229 248 217 217 235 217 217 235 229 229 248 230 230 249 217 217 235 230 230 249 218 218 236 218 218 236 230 230 249 231 231 250 218 218 236 231 231 250 219 219 237 219 219 237 231 231 250 232 232 251 219 219 237 232 232 251 220 220 238 220 220 238 232 232 251 233 233 252 220 220 238 233 233 252 221 221 239 221 221 239 233 233 252 234 234 253 221 221 239 234 234 253 222 222 240 222 222 240 234 234 253 235 235 254 222 222 240 235 235 254 223 223 241 223 223 241 235 235 254 236 236 255 223 223 241 236 236 255 224 224 242 224 224 242 236 236 255 237 237 256 224 224 242 237 237 256 225 225 243 225 225 243 237 237 256 238 238 257 225 225 243 238 238 257 226 226 244 226 226 244 238 238 257 239 239 258 226 226 244 239 239 258 227 227 245 227 227 245 239 239 258 228 228 259 227 227 245 228 228 259 216 216 246 228 228 247 240 240 260 241 241 261 228 228 247 241 241 261 229 229 248 229 229 248 241 241 261 242 242 262 229 229 248 242 242 262 230 230 249 230 230 249 242 242 262 243 243 263 230 230 249 243 243 263 231 231 250 231 231 250 243 243 263 244 244 264 231 231 250 244 244 264 232 232 251 232 232 251 244 244 264 245 245 265 232 232 251 245 245 265 233 233 252 233 233 252 245 245 265 246 246 266 233 233 252 246 246 266 234 234 253 234 234 253 246 246 266 247 247 267 234 234 253 247 247 267 235 235 254 235 235 254 247 247 267 248 248 268 235 235 254 248 248 268 236 236 255 236 236 255 248 248 268 249 249 269 236 236 255 249 249 269 237 237 256 237 237 256 249 249 269 250 250 270 237 237 256 250 250 270 238 238 257 238 238 257 250 250 270 251 251 271 238 238 257 251 251 271 239 239 258 239 239 258 251 251 271 240 240 272 239 239 258 240 240 272 228 228 259 240 240 260 252 252 273 253 253 274 240 240 260 253 253 274 241 241 261 241 241 261 253 253 274 254 254 275 241 241 261 254 254 275 242 242 262 242 242 262 254 254 275 255 255 276 242 242 262 255 255 276 243 243 263 243 243 263 255 255 276 256 256 277 243 243 263 256 256 277 244 244 264 244 244 264 256 256 277 257 257 278 244 244 264 257 257 278 245 245 265 245 245 265 257 257 278 258 258 279 245 245 265 258 258 279 246 246 266 246 246 266 258 258 279 259 259 280 246 246 266 259 259 280 247 247 267 247 247 267 259 259 280 260 260 281 247 247 267 260 260 281 248 248 268 248 248 268 260 260 281 261 261 282 248 248 268 261 261 282 249 249 269 249 249 269 261 261 282 262 262 283 249 249 269 262 262 283 250 250 270 250 250 270 262 262 283 263 263 284 250 250 270 263 263 284 251 251 271 251 251 271 263 263 284 252 252 285 251 251 271 252 252 285 240 240 272 252 252 273 264 264 286 265 265 287 252 252 273 265 265 287 253 253 274 253 253 274 265 265 287 266 266 288 253 253 274 266 266 288 254 254 275 254 254 275 266 266 288 267 267 289 254 254 275 267 267 289 255 255 276 255 255 276 267 267 289 268 268 290 255 255 276 268 268 290 256 256 277 256 256 277 268 268 290 269 269 291 256 256 277 269 269 291 257 257 278 257 257 278 269 269 291 270 270 292 257 257 278 270 270 292 258 258 279 258 258 279 270 270 292 271 271 293 258 258 279 271 271 293 259 259 280 259 259 280 271 271 293 272 272 294 259 259 280 272 272 294 260 260 281 260 260 281 272 272 294 273 273 295 260 260 281 273 273 295 261 261 282 261 261 282 273 273 295 274 274 296 261 261 282 274 274 296 262 262 283 262 262 283 274 274 296 275 275 297 262 262 283 275 275 297 263 263 284 263 263 284 275 275 297 264 264 298 263 263 284 264 264 298 252 252 285 264 264 286 276 276 299 277 277 300 264 264 286 277 277 300 265 265 287 265 265 287 277 277 300 278 278 301 265 265 287 278 278 301 266 266 288 266 266 288 278 278 301 279 279 302 266 266 288 279 279 302 267 267 289 267 267 289 279 279 302 280 280 303 267 267 289 280 280 303 268 268 290 268 268 290 280 280 303 281 281 304 268 268 290 281 281 304 269 269 291 269 269 291 281 281 304 282 282 305 269 269 291 282 282 305 270 270 292 270 270 292 282 282 305 283 283 306 270 270 292 283 283 306 271 271 293 271 271 293 283 283 306 284 284 307 271 271 293 284 284 307 272 272 294 272 272 294 284 284 307 285 285 308 272 272 294 285 285 308 273 273 295 273 273 295 285 285 308 286 286 309 273 273 295 286 286 309 274 274 296 274 274 296 286 286 309 287 287 310 274 274 296 287 287 310 275 275 297 275 275 297 287 287 310 276 276 311 275 275 297 276 276 311 264 264 298 276 276 299 288 288 312 289 289 313 276 276 299 289 289 313 277 277 300 277 277 300 289 289 313 290 290 314 277 277 300 290 290 314 278 278 301 278 278 301 290 290 314 291 291 315 278 278 301 291 291 315 279 279 302 279 279 302 291 291 315 292 292 316 279 279 302 292 292 316 280 280 303 280 280 303 292 292 316 293 293 317 280 280 303 293 293 317 281 281 304 281 281 304 293 293 317 294 294 318 281 281 304 294 294 318 282 282 305 282 282 305 294 294 318 295 295 319 282 282 305 295 295 319 283 283 306 283 283 306 295 295 319 296 296 320 283 283 306 296 296 320 284 284 307 284 284 307 296 296 320 297 297 321 284 284 307 297 297 321 285 285 308 285 285 308 297 297 321 298 298 322 285 285 308 298 298 322 286 286 309 286 286 309 298 298 322 299 299 323 286 286 309 299 299 323 287 287 310 287 287 310 299 299 323 288 288 324 287 287 310 288 288 324 276 276 311 288 288 312 300 300 325 301 301 326 288 288 312 301 301 326 289 289 313 289 289 313 301 301 326 302 302 327 289 289 313 302 302 327 290 290 314 290 290 314 302 302 327 303 303 328 290 290 314 303 303 328 291 291 315 291 291 315 303 303 328 304 304 329 291 291 315 304 304 329 292 292 316 292 292 316 304 304 329 305 305 330 292 292 316 305 305 330 293 293 317 293 293 317 305 305 330 306 306 331 293 293 317 306 306 331 294 294 318 294 294 318 306 306 331 307 307 332 294 294 318 307 307 332 295 295 319 295 295 319 307 307 332 308 308 333 295 295 319 308 308 333 296 296 320 296 296 320 308 308 333 309 309 334 296 296 320 309 309 334 297 297 321 297 297 321 309 309 334 310 310 335 297 297 321 310 310 335 298 298 322 298 298 322 310 310 335 311 311 336 298 298 322 311 311 336 299 299 323 299 299 323 311 311 336 300 300 337 299 299 323 300 300 337 288 288 324 300 300 325 312 312 338 313 313 339 300 300 325 313 313 339 301 301 326 301 301 326 313 313 339 314 314 340 301 301 326 314 314 340 302 302 327 302 302 327 314 314 340 315 315 341 302 302 327 315 315 341 303 303 328 303 303 328 315 315 341 316 316 342 303 303 328 316 316 342 304 304 329 304 304 329 316 316 342 317 317 343 304 304 329 317 317 343 305 305 330 305 305 330 317 317 343 318 318 344 305 305 330 318 318 344 306 306 331 306 306 331 318 318 344 319 319 345 306 306 331 319 319 345 307 307 332 307 307 332 319 319 345 320 320 346 307 307 332 320 320 346 308 308 333 308 308 333 320 320 346 321 321 347 308 308 333 321 321 347 309 309 334 309 309 334 321 321 347 322 322 348 309 309 334 322 322 348 310 310 335 310 310 335 322 322 348 323 323 349 310 310 335 323 323 349 311 311 336 311 311 336 323 323 349 312 312 350 311 311 336 312 312 350 300 300 337 312 312 338 324 324 351 325 325 352 312 312 338 325 325 352 313 313 339 313 313 339 325 325 352 326 326 353 313 313 339 326 326 353 314 314 340 314 314 340 326 326 353 327 327 354 314 314 340 327 327 354 315 315 341 315 315 341 327 327 354 328 328 355 315 315 341 328 328 355 316 316 342 316 316 342 328 328 355 329 329 356 316 316 342 329 329 356 317 317 343 317 317 343 329 329 356 330 330 357 317 317 343 330 330 357 318 318 344 318 318 344 330 330 357 331 331 358 318 318 344 331 331 358 319 319 345 319 319 345 331 331 358 332 332 359 319 319 345 332 332 359 320 320 346 320 320 346 332 332 359 333 333 360 320 320 346 333 333 360 321 321 347 321 321 347 333 333 360 334 334 361 321 321 347 334 334 361 322 322 348 322 322 348 334 334 361 335 335 362 322 322 348 335 335 362 323 323 349 323 323 349 335 335 362 324 324 363 323 323 349 324 324 363 312 312 350 324 324 351 336 336 364 337 337 365 324 324 351 337 337 365 325 325 352 325 325 352 337 337 365 338 338 366 325 325 352 338 338 366 326 326 353 326 326 353 338 338 366 339 339 367 326 326 353 339 339 367 327 327 354 327 327 354 339 339 367 340 340 368 327 327 354 340 340 368 328 328 355 328 328 355 340 340 368 341 341 369 328 328 355 341 341 369 329 329 356 329 329 356 341 341 369 342 342 370 329 329 356 342 342 370 330 330 357 330 330 357 342 342 370 343 343 371 330 330 357 343 343 371 331 331 358 331 331 358 343 343 371 344 344 372 331 331 358 344 344 372 332 332 359 332 332 359 344 344 372 345 345 373 332 332 359 345 345 373 333 333 360 333 333 360 345 345 373 346 346 374 333 333 360 346 346 374 334 334 361 334 334 361 346 346 374 347 347 375 334 334 361 347 347 375 335 335 362 335 335 362 347 347 375 336 336 376 335 335 362 336 336 376 324 324 363 336 336 364 348 348 377 349 349 378 336 336 364 349 349 378 337 337 365 337 337 365 349 349 378 350 350 379 337 337 365 350 350 379 338 338 366 338 338 366 350 350 379 351 351 380 338 338 366 351 351 380 339 339 367 339 339 367 351 351 380 352 352 381 339 339 367 352 352 381 340 340 368 340 340 368 352 352 381 353 353 382 340 340 368 353 353 382 341 341 369 341 341 369 353 353 382 354 354 383 341 341 369 354 354 383 342 342 370 342 342 370 354 354 383 355 355 384 342 342 370 355 355 384 343 343 371 343 343 371 355 355 384 356 356 385 343 343 371 356 356 385 344 344 372 344 344 372 356 356 385 357 357 386 344 344 372 357 357 386 345 345 373 345 345 373 357 357 386 358 358 387 345 345 373 358 358 387 346 346 374 346 346 374 358 358 387 359 359 388 346 346 374 359 359 388 347 347 375 347 347 375 359 359 388 348 348 389 347 347 375 348 348 389 336 336 376 348 348 377 360 360 390 361 361 391 348 348 377 361 361 391 349 349 378 349 349 378 361 361 391 362 362 392 349 349 378 362 362 392 350 350 379 350 350 379 362 362 392 363 363 393 350 350 379 363 363 393 351 351 380 351 351 380 363 363 393 364 364 394 351 351 380 364 364 394 352 352 381 352 352 381 364 364 394 365 365 395 352 352 381 365 365 395 353 353 382 353 353 382 365 365 395 366 366 396 353 353 382 366 366 396 354 354 383 354 354 383 366 366 396 367 367 397 354 354 383 367 367 397 355 355 384 355 355 384 367 367 397 368 368 398 355 355 384 368 368 398 356 356 385 356 356 385 368 368 398 369 369 399 356 356 385 369 369 399 357 357 386 357 357 386 369 369 399 370 370 400 357 357 386 370 370 400 358 358 387 358 358 387 370 370 400 371 371 401 358 358 387 371 371 401 359 359 388 359 359 388 371 371 401 360 360 402 359 359 388 360 360 402 348 348 389 360 360 390 372 372 403 373 373 404 360 360 390 373 373 404 361 361 391 361 361 391 373 373 404 374 374 405 361 361 391 374 374 405 362 362 392 362 362 392 374 374 405 375 375 406 362 362 392 375 375 406 363 363 393 363 363 393 375 375 406 376 376 407 363 363 393 376 376 407 364 364 394 364 364 394 376 376 407 377 377 408 364 364 394 377 377 408 365 365 395 365 365 395 377 377 408 378 378 409 365 365 395 378 378 409 366 366 396 366 366 396 378 378 409 379 379 410 366 366 396 379 379 410 367 367 397 367 367 397 379 379 410 380 380 411 367 367 397 380 380 411 368 368 398 368 368 398 380 380 411 381 381 412 368 368 398 381 381 412 369 369 399 369 369 399 381 381 412 382 382 413 369 369 399 382 382 413 370 370 400 370 370 400 382 382 413 383 383 414 370 370 400 383 383 414 371 371 401 371 371 401 383 383 414 372 372 415 371 371 401 372 372 415 360 360 402 372 372 403 384 384 416 385 385 417 372 372 403 385 385 417 373 373 404 373 373 404 385 385 417 386 386 418 373 373 404 386 386 418 374 374 405 374 374 405 386 386 418 387 387 419 374 374 405 387 387 419 375 375 406 375 375 406 387 387 419 388 388 420 375 375 406 388 388 420 376 376 407 376 376 407 388 388 420 389 389 421 376 376 407 389 389 421 377 377 408 377 377 408 389 389 421 390 390 422 377 377 408 390 390 422 378 378 409 378 378 409 390 390 422 391 391 423 378 378 409 391 391 423 379 379 410 379 379 410 391 391 423 392 392 424 379 379 410 392 392 424 380 380 411 380 380 411 392 392 424 393 393 425 380 380 411 393 393 425 381 381 412 381 381 412 393 393 425 394 394 426 381 381 412 394 394 426 382 382 413 382 382 413 394 394 426 395 395 427 382 382 413 395 395 427 383 383 414 383 383 414 395 395 427 384 384 428 383 383 414 384 384 428 372 372 415 384 384 416 396 396 429 397 397 430 384 384 416 397 397 430 385 385 417 385 385 417 397 397 430 398 398 431 385 385 417 398 398 431 386 386 418 386 386 418 398 398 431 399 399 432 386 386 418 399 399 432 387 387 419 387 387 419 399 399 432 400 400 433 387 387 419 400 400 433 388 388 420 388 388 420 400 400 433 401 401 434 388 388 420 401 401 434 389 389 421 389 389 421 401 401 434 402 402 435 389 389 421 402 402 435 390 390 422 390 390 422 402 402 435 403 403 436 390 390 422 403 403 436 391 391 423 391 391 423 403 403 436 404 404 437 391 391 423 404 404 437 392 392 424 392 392 424 404 404 437 405 405 438 392 392 424 405 405 438 393 393 425 393 393 425 405 405 438 406 406 439 393 393 425 406 406 439 394 394 426 394 394 426 406 406 439 407 407 440 394 394 426 407 407 440 395 395 427 395 395 427 407 407 440 396 396 441 395 395 427 396 396 441 384 384 428 396 396 429 408 408 442 409 409 443 396 396 429 409 409 443 397 397 430 397 397 430 409 409 443 410 410 444 397 397 430 410 410 444 398 398 431 398 398 431 410 410 444 411 411 445 398 398 431 411 411 445 399 399 432 399 399 432 411 411 445 412 412 446 399 399 432 412 412 446 400 400 433 400 400 433 412 412 446 413 413 447 400 400 433 413 413 447 401 401 434 401 401 434 413 413 447 414 414 448 401 401 434 414 414 448 402 402 435 402 402 435 414 414 448 415 415 449 402 402 435 415 415 449 403 403 436 403 403 436 415 415 449 416 416 450 403 403 436 416 416 450 404 404 437 404 404 437 416 416 450 417 417 451 404 404 437 417 417 451 405 405 438 405 405 438 417 417 451 418 418 452 405 405 438 418 418 452 406 406 439 406 406 439 418 418 452 419 419 453 406 406 439 419 419 453 407 407 440 407 407 440 419 419 453 408 408 454 407 407 440 408 408 454 396 396 441 408 408 442 420 420 455 421 421 456 408 408 442 421 421 456 409 409 443 409 409 443 421 421 456 422 422 457 409 409 443 422 422 457 410 410 444 410 410 444 422 422 457 423 423 458 410 410 444 423 423 458 411 411 445 411 411 445 423 423 458 424 424 459 411 411 445 424 424 459 412 412 446 412 412 446 424 424 459 425 425 460 412 412 446 425 425 460 413 413 447 413 413 447 425 425 460 426 426 461 413 413 447 426 426 461 414 414 448 414 414 448 426 426 461 427 427 462 414 414 448 427 427 462 415 415 449 415 415 449 427 427 462 428 428 463 415 415 449 428 428 463 416 416 450 416 416 450 428 428 463 429 429 464 416 416 450 429 429 464 417 417 451 417 417 451 429 429 464 430 430 465 417 417 451 430 430 465 418 418 452 418 418 452 430 430 465 431 431 466 418 418 452 431 431 466 419 419 453 419 419 453 431 431 466 420 420 467 419 419 453 420 420 467 408 408 454 420 420 455 432 432 468 433 433 469 420 420 455 433 433 469 421 421 456 421 421 456 433 433 469 434 434 470 421 421 456 434 434 470 422 422 457 422 422 457 434 434 470 435 435 471 422 422 457 435 435 471 423 423 458 423 423 458 435 435 471 436 436 472 423 423 458 436 436 472 424 424 459 424 424 459 436 436 472 437 437 473 424 424 459 437 437 473 425 425 460 425 425 460 437 437 473 438 438 474 425 425 460 438 438 474 426 426 461 426 426 461 438 438 474 439 439 475 426 426 461 439 439 475 427 427 462 427 427 462 439 439 475 440 440 476 427 427 462 440 440 476 428 428 463 428 428 463 440 440 476 441 441 477 428 428 463 441 441 477 429 429 464 429 429 464 441 441 477 442 442 478 429 429 464 442 442 478 430 430 465 430 430 465 442 442 478 443 443 479 430 430 465 443 443 479 431 431 466 431 431 466 443 443 479 432 432 480 431 431 466 432 432 480 420 420 467 432 432 468 444 444 481 445 445 482 432 432 468 445 445 482 433 433 469 433 433 469 445 445 482 446 446 483 433 433 469 446 446 483 434 434 470 434 434 470 446 446 483 447 447 484 434 434 470 447 447 484 435 435 471 435 435 471 447 447 484 448 448 485 435 435 471 448 448 485 436 436 472 436 436 472 448 448 485 449 449 486 436 436 472 449 449 486 437 437 473 437 437 473 449 449 486 450 450 487 437 437 473 450 450 487 438 438 474 438 438 474 450 450 487 451 451 488 438 438 474 451 451 488 439 439 475 439 439 475 451 451 488 452 452 489 439 439 475 452 452 489 440 440 476 440 440 476 452 452 489 453 453 490 440 440 476 453 453 490 441 441 477 441 441 477 453 453 490 454 454 491 441 441 477 454 454 491 442 442 478 442 442 478 454 454 491 455 455 492 442 442 478 455 455 492 443 443 479 443 443 479 455 455 492 444 444 493 443 443 479 444 444 493 432 432 480 444 444 481 456 456 494 457 457 495 444 444 481 457 457 495 445 445 482 445 445 482 457 457 495 458 458 496 445 445 482 458 458 496 446 446 483 446 446 483 458 458 496 459 459 497 446 446 483 459 459 497 447 447 484 447 447 484 459 459 497 460 460 498 447 447 484 460 460 498 448 448 485 448 448 485 460 460 498 461 461 499 448 448 485 461 461 499 449 449 486 449 449 486 461 461 499 462 462 500 449 449 486 462 462 500 450 450 487 450 450 487 462 462 500 463 463 501 450 450 487 463 463 501 451 451 488 451 451 488 463 463 501 464 464 502 451 451 488 464 464 502 452 452 489 452 452 489 464 464 502 465 465 503 452 452 489 465 465 503 453 453 490 453 453 490 465 465 503 466 466 504 453 453 490 466 466 504 454 454 491 454 454 491 466 466 504 467 467 505 454 454 491 467 467 505 455 455 492 455 455 492 467 467 505 456 456 506 455 455 492 456 456 506 444 444 493 456 456 494 468 468 507 469 469 508 456 456 494 469 469 508 457 457 495 457 457 495 469 469 508 470 470 509 457 457 495 470 470 509 458 458 496 458 458 496 470 470 509 471 471 510 458 458 496 471 471 510 459 459 497 459 459 497 471 471 510 472 472 511 459 459 497 472 472 511 460 460 498 460 460 498 472 472 511 473 473 512 460 460 498 473 473 512 461 461 499 461 461 499 473 473 512 474 474 513 461 461 499 474 474 513 462 462 500 462 462 500 474 474 513 475 475 514 462 462 500 475 475 514 463 463 501 463 463 501 475 475 514 476 476 515 463 463 501 476 476 515 464 464 502 464 464 502 476 476 515 477 477 516 464 464 502 477 477 516 465 465 503 465 465 503 477 477 516 478 478 517 465 465 503 478 478 517 466 466 504 466 466 504 478 478 517 479 479 518 466 466 504 479 479 518 467 467 505 467 467 505 479 479 518 468 468 519 467 467 505 468 468 519 456 456 506 468 468 507 480 480 520 481 481 521 468 468 507 481 481 521 469 469 508 469 469 508 481 481 521 482 482 522 469 469 508 482 482 522 470 470 509 470 470 509 482 482 522 483 483 523 470 470 509 483 483 523 471 471 510 471 471 510 483 483 523 484 484 524 471 471 510 484 484 524 472 472 511 472 472 511 484 484 524 485 485 525 472 472 511 485 485 525 473 473 512 473 473 512 485 485 525 486 486 526 473 473 512 486 486 526 474 474 513 474 474 513 486 486 526 487 487 527 474 474 513 487 487 527 475 475 514 475 475 514 487 487 527 488 488 528 475 475 514 488 488 528 476 476 515 476 476 515 488 488 528 489 489 529 476 476 515 489 489 529 477 477 516 477 477 516 489 489 529 490 490 530 477 477 516 490 490 530 478 478 517 478 478 517 490 490 530 491 491 531 478 478 517 491 491 531 479 479 518 479 479 518 491 491 531 480 480 532 479 479 518 480 480 532 468 468 519 480 480 520 492 492 533 493 493 534 480 480 520 493 493 534 481 481 521 481 481 521 493 493 534 494 494 535 481 481 521 494 494 535 482 482 522 482 482 522 494 494 535 495 495 536 482 482 522 495 495 536 483 483 523 483 483 523 495 495 536 496 496 537 483 483 523 496 496 537 484 484 524 484 484 524 496 496 537 497 497 538 484 484 524 497 497 538 485 485 525 485 485 525 497 497 538 498 498 539 485 485 525 498 498 539 486 486 526 486 486 526 498 498 539 499 499 540 486 486 526 499 499 540 487 487 527 487 487 527 499 499 540 500 500 541 487 487 527 500 500 541 488 488 528 488 488 528 500 500 541 501 501 542 488 488 528 501 501 542 489 489 529 489 489 529 501 501 542 502 502 543 489 489 529 502 502 543 490 490 530 490 490 530 502 502 543 503 503 544 490 490 530 503 503 544 491 491 531 491 491 531 503 503 544 492 492 545 491 491 531 492 492 545 480 480 532 492 492 533 504 504 546 505 505 547 492 492 533 505 505 547 493 493 534 493 493 534 505 505 547 506 506 548 493 493 534 506 506 548 494 494 535 494 494 535 506 506 548 507 507 549 494 494 535 507 507 549 495 495 536 495 495 536 507 507 549 508 508 550 495 495 536 508 508 550 496 496 537 496 496 537 508 508 550 509 509 551 496 496 537 509 509 551 497 497 538 497 497 538 509 509 551 510 510 552 497 497 538 510 510 552 498 498 539 498 498 539 510 510 552 511 511 553 498 498 539 511 511 553 499 499 540 499 499 540 511 511 553 512 512 554 499 499 540 512 512 554 500 500 541 500 500 541 512 512 554 513 513 555 500 500 541 513 513 555 501 501 542 501 501 542 513 513 555 514 514 556 501 501 542 514 514 556 502 502 543 502 502 543 514 514 556 515 515 557 502 502 543 515 515 557 503 503 544 503 503 544 515 515 557 504 504 558 503 503 544 504 504 558 492 492 545 504 504 546 516 516 559 517 517 560 504 504 546 517 517 560 505 505 547 505 505 547 517 517 560 518 518 561 505 505 547 518 518 561 506 506 548 506 506 548 518 518 561 519 519 562 506 506 548 519 519 562 507 507 549 507 507 549 519 519 562 520 520 563 507 507 549 520 520 563 508 508 550 508 508 550 520 520 563 521 521 564 508 508 550 521 521 564 509 509 551 509 509 551 521 521 564 522 522 565 509 509 551 522 522 565 510 510 552 510 510 552 522 522 565 523 523 566 510 510 552 523 523 566 511 511 553 511 511 553 523 523 566 524 524 567 511 511 553 524 524 567 512 512 554 512 512 554 524 524 567 525 525 568 512 512 554 525 525 568 513 513 555 513 513 555 525 525 568 526 526 569 513 513 555 526 526 569 514 514 556 514 514 556 526 526 569 527 527 570 514 514 556 527 527 570 515 515 557 515 515 557 527 527 570 516 516 571 515 515 557 516 516 571 504 504 558 516 516 559 528 528 572 529 529 573 516 516 559 529 529 573 517 517 560 517 517 560 529 529 573 530 530 574 517 517 560 530 530 574 518 518 561 518 518 561 530 530 574 531 531 575 518 518 561 531 531 575 519 519 562 519 519 562 531 531 575 532 532 576 519 519 562 532 532 576 520 520 563 520 520 563 532 532 576 533 533 577 520 520 563 533 533 577 521 521 564 521 521 564 533 533 577 534 534 578 521 521 564 534 534 578 522 522 565 522 522 565 534 534 578 535 535 579 522 522 565 535 535 579 523 523 566 523 523 566 535 535 579 536 536 580 523 523 566 536 536 580 524 524 567 524 524 567 536 536 580 537 537 581 524 524 567 537 537 581 525 525 568 525 525 568 537 537 581 538 538 582 525 525 568 538 538 582 526 526 569 526 526 569 538 538 582 539 539 583 526 526 569 539 539 583 527 527 570 527 527 570 539 539 583 528 528 584 527 527 570 528 528 584 516 516 571 528 528 572 540 540 585 541 541 586 528 528 572 541 541 586 529 529 573 529 529 573 541 541 586 542 542 587 529 529 573 542 542 587 530 530 574 530 530 574 542 542 587 543 543 588 530 530 574 543 543 588 531 531 575 531 531 575 543 543 588 544 544 589 531 531 575 544 544 589 532 532 576 532 532 576 544 544 589 545 545 590 532 532 576 545 545 590 533 533 577 533 533 577 545 545 590 546 546 591 533 533 577 546 546 591 534 534 578 534 534 578 546 546 591 547 547 592 534 534 578 547 547 592 535 535 579 535 535 579 547 547 592 548 548 593 535 535 579 548 548 593 536 536 580 536 536 580 548 548 593 549 549 594 536 536 580 549 549 594 537 537 581 537 537 581 549 549 594 550 550 595 537 537 581 550 550 595 538 538 582 538 538 582 550 550 595 551 551 596 538 538 582 551 551 596 539 539 583 539 539 583 551 551 596 540 540 597 539 539 583 540 540 597 528 528 584 540 540 585 552 552 598 553 553 599 540 540 585 553 553 599 541 541 586 541 541 586 553 553 599 554 554 600 541 541 586 554 554 600 542 542 587 542 542 587 554 554 600 555 555 601 542 542 587 555 555 601 543 543 588 543 543 588 555 555 601 556 556 602 543 543 588 556 556 602 544 544 589 544 544 589 556 556 602 557 557 603 544 544 589 557 557 603 545 545 590 545 545 590 557 557 603 558 558 604 545 545 590 558 558 604 546 546 591 546 546 591 558 558 604 559 559 605 546 546 591 559 559 605 547 547 592 547 547 592 559 559 605 560 560 606 547 547 592 560 560 606 548 548 593 548 548 593 560 560 606 561 561 607 548 548 593 561 561 607 549 549 594 549 549 594 561 561 607 562 562 608 549 549 594 562 562 608 550 550 595 550 550 595 562 562 608 563 563 609 550 550 595 563 563 609 551 551 596 551 551 596 563 563 609 552 552 610 551 551 596 552 552 610 540 540 597 552 552 598 564 564 611 565 565 612 552 552 598 565 565 612 553 553 599 553 553 599 565 565 612 566 566 613 553 553 599 566 566 613 554 554 600 554 554 600 566 566 613 567 567 614 554 554 600 567 567 614 555 555 601 555 555 601 567 567 614 568 568 615 555 555 601 568 568 615 556 556 602 556 556 602 568 568 615 569 569 616 556 556 602 569 569 616 557 557 603 557 557 603 569 569 616 570 570 617 557 557 603 570 570 617 558 558 604 558 558 604 570 570 617 571 571 618 558 558 604 571 571 618 559 559 605 559 559 605 571 571 618 572 572 619 559 559 605 572 572 619 560 560 606 560 560 606 572 572 619 573 573 620 560 560 606 573 573 620 561 561 607 561 561 607 573 573 620 574 574 621 561 561 607 574 574 621 562 562 608 562 562 608 574 574 621 575 575 622 562 562 608 575 575 622 563 563 609 563 563 609 575 575 622 564 564 623 563 563 609 564 564 623 552 552 610 564 564 611 576 576 624 577 577 625 564 564 611 577 577 625 565 565 612 565 565 612 577 577 625 578 578 626 565 565 612 578 578 626 566 566 613 566 566 613 578 578 626 579 579 627 566 566 613 579 579 627 567 567 614 567 567 614 579 579 627 580 580 628 567 567 614 580 580 628 568 568 615 568 568 615 580 580 628 581 581 629 568 568 615 581 581 629 569 569 616 569 569 616 581 581 629 582 582 630 569 569 616 582 582 630 570 570 617 570 570 617 582 582 630 583 583 631 570 570 617 583 583 631 571 571 618 571 571 618 583 583 631 584 584 632 571 571 618 584 584 632 572 572 619 572 572 619 584 584 632 585 585 633 572 572 619 585 585 633 573 573 620 573 573 620 585 585 633 586 586 634 573 573 620 586 586 634 574 574 621 574 574 621 586 586 634 587 587 635 574 574 621 587 587 635 575 575 622 575 575 622 587 587 635 576 576 636 575 575 622 576 576 636 564 564 623 576 576 624 588 588 637 589 589 638 576 576 624 589 589 638 577 577 625 577 577 625 589 589 638 590 590 639 577 577 625 590 590 639 578 578 626 578 578 626 590 590 639 591 591 640 578 578 626 591 591 640 579 579 627 579 579 627 591 591 640 592 592 641 579 579 627 592 592 641 580 580 628 580 580 628 592 592 641 593 593 642 580 580 628 593 593 642 581 581 629 581 581 629 593 593 642 594 594 643 581 581 629 594 594 643 582 582 630 582 582 630 594 594 643 595 595 644 582 582 630 595 595 644 583 583 631 583 583 631 595 595 644 596 596 645 583 583 631 596 596 645 584 584 632 584 584 632 596 596 645 597 597 646 584 584 632 597 597 646 585 585 633 585 585 633 597 597 646 598 598 647 585 585 633 598 598 647 586 586 634 586 586 634 598 598 647 599 599 648 586 586 634 599 599 648 587 587 635 587 587 635 599 599 648 588 588 649 587 587 635 588 588 649 576 576 636 588 588 637 600 600 650 601 601 651 588 588 637 601 601 651 589 589 638 589 589 638 601 601 651 602 602 652 589 589 638 602 602 652 590 590 639 590 590 639 602 602 652 603 603 653 590 590 639 603 603 653 591 591 640 591 591 640 603 603 653 604 604 654 591 591 640 604 604 654 592 592 641 592 592 641 604 604 654 605 605 655 592 592 641 605 605 655 593 593 642 593 593 642 605 605 655 606 606 656 593 593 642 606 606 656 594 594 643 594 594 643 606 606 656 607 607 657 594 594 643 607 607 657 595 595 644 595 595 644 607 607 657 608 608 658 595 595 644 608 608 658 596 596 645 596 596 645 608 608 658 609 609 659 596 596 645 609 609 659 597 597 646 597 597 646 609 609 659 610 610 660 597 597 646 610 610 660 598 598 647 598 598 647 610 610 660 611 611 661 598 598 647 611 611 661 599 599 648 599 599 648 611 611 661 600 600 662 599 599 648 600 600 662 588 588 649 600 600 650 612 612 663 613 613 664 600 600 650 613 613 664 601 601 651 601 601 651 613 613 664 614 614 665 601 601 651 614 614 665 602 602 652 602 602 652 614 614 665 615 615 666 602 602 652 615 615 666 603 603 653 603 603 653 615 615 666 616 616 667 603 603 653 616 616 667 604 604 654 604 604 654 616 616 667 617 617 668 604 604 654 617 617 668 605 605 655 605 605 655 617 617 668 618 618 669 605 605 655 618 618 669 606 606 656 606 606 656 618 618 669 619 619 670 606 606 656 619 619 670 607 607 657 607 607 657 619 619 670 620 620 671 607 607 657 620 620 671 608 608 658 608 608 658 620 620 671 621 621 672 608 608 658 621 621 672 609 609 659 609 609 659 621 621 672 622 622 673 609 609 659 622 622 673 610 610 660 610 610 660 622 622 673 623 623 674 610 610 660 623 623 674 611 611 661 611 611 661 623 623 674 612 612 675 611 611 661 612 612 675 600 600 662 612 612 663 624 624 676 625 625 677 612 612 663 625 625 677 613 613 664 613 613 664 625 625 677 626 626 678 613 613 664 626 626 678 614 614 665 614 614 665 626 626 678 627 627 679 614 614 665 627 627 679 615 615 666 615 615 666 627 627 679 628 628 680 615 615 666 628 628 680 616 616 667 616 616 667 628 628 680 629 629 681 616 616 667 629 629 681 617 617 668 617 617 668 629 629 681 630 630 682 617 617 668 630 630 682 618 618 669 618 618 669 630 630 682 631 631 683 618 618 669 631 631 683 619 619 670 619 619 670 631 631 683 632 632 684 619 619 670 632 632 684 620 620 671 620 620 671 632 632 684 633 633 685 620 620 671 633 633 685 621 621 672 621 621 672 633 633 685 634 634 686 621 621 672 634 634 686 622 622 673 622 622 673 634 634 686 635 635 687 622 622 673 635 635 687 623 623 674 623 623 674 635 635 687 624 624 688 623 623 674 624 624 688 612 612 675 624 624 676 636 636 689 637 637 690 624 624 676 637 637 690 625 625 677 625 625 677 637 637 690 638 638 691 625 625 677 638 638 691 626 626 678 626 626 678 638 638 691 639 639 692 626 626 678 639 639 692 627 627 679 627 627 679 639 639 692 640 640 693 627 627 679 640 640 693 628 628 680 628 628 680 640 640 693 641 641 694 628 628 680 641 641 694 629 629 681 629 629 681 641 641 694 642 642 695 629 629 681 642 642 695 630 630 682 630 630 682 642 642 695 643 643 696 630 630 682 643 643 696 631 631 683 631 631 683 643 643 696 644 644 697 631 631 683 644 644 697 632 632 684 632 632 684 644 644 697 645 645 698 632 632 684 645 645 698 633 633 685 633 633 685 645 645 698 646 646 699 633 633 685 646 646 699 634 634 686 634 634 686 646 646 699 647 647 700 634 634 686 647 647 700 635 635 687 635 635 687 647 647 700 636 636 701 635 635 687 636 636 701 624 624 688 636 636 689 648 648 702 649 649 703 636 636 689 649 649 703 637 637 690 637 637 690 649 649 703 650 650 704 637 637 690 650 650 704 638 638 691 638 638 691 650 650 704 651 651 705 638 638 691 651 651 705 639 639 692 639 639 692 651 651 705 652 652 706 639 639 692 652 652 706 640 640 693 640 640 693 652 652 706 653 653 707 640 640 693 653 653 707 641 641 694 641 641 694 653 653 707 654 654 708 641 641 694 654 654 708 642 642 695 642 642 695 654 654 708 655 655 709 642 642 695 655 655 709 643 643 696 643 643 696 655 655 709 656 656 710 643 643 696 656 656 710 644 644 697 644 644 697 656 656 710 657 657 711 644 644 697 657 657 711 645 645 698 645 645 698 657 657 711 658 658 712 645 645 698 658 658 712 646 646 699 646 646 699 658 658 712 659 659 713 646 646 699 659 659 713 647 647 700 647 647 700 659 659 713 648 648 714 647 647 700 648 648 714 636 636 701 648 648 702 660 660 715 661 661 716 648 648 702 661 661 716 649 649 703 649 649 703 661 661 716 662 662 717 649 649 703 662 662 717 650 650 704 650 650 704 662 662 717 663 663 718 650 650 704 663 663 718 651 651 705 651 651 705 663 663 718 664 664 719 651 651 705 664 664 719 652 652 706 652 652 706 664 664 719 665 665 720 652 652 706 665 665 720 653 653 707 653 653 707 665 665 720 666 666 721 653 653 707 666 666 721 654 654 708 654 654 708 666 666 721 667 667 722 654 654 708 667 667 722 655 655 709 655 655 709 667 667 722 668 668 723 655 655 709 668 668 723 656 656 710 656 656 710 668 668 723 669 669 724 656 656 710 669 669 724 657 657 711 657 657 711 669 669 724 670 670 725 657 657 711 670 670 725 658 658 712 658 658 712 670 670 725 671 671 726 658 658 712 671 671 726 659 659 713 659 659 713 671 671 726 660 660 727 659 659 713 660 660 727 648 648 714 660 660 715 672 672 728 673 673 729 660 660 715 673 673 729 661 661 716 661 661 716 673 673 729 674 674 730 661 661 716 674 674 730 662 662 717 662 662 717 674 674 730 675 675 731 662 662 717 675 675 731 663 663 718 663 663 718 675 675 731 676 676 732 663 663 718 676 676 732 664 664 719 664 664 719 676 676 732 677 677 733 664 664 719 677 677 733 665 665 720 665 665 720 677 677 733 678 678 734 665 665 720 678 678 734 666 666 721 666 666 721 678 678 734 679 679 735 666 666 721 679 679 735 667 667 722 667 667 722 679 679 735 680 680 736 667 667 722 680 680 736 668 668 723 668 668 723 680 680 736 681 681 737 668 668 723 681 681 737 669 669 724 669 669 724 681 681 737 682 682 738 669 669 724 682 682 738 670 670 725 670 670 725 682 682 738 683 683 739 670 670 725 683 683 739 671 671 726 671 671 726 683 683 739 672 672 740 671 671 726 672 672 740 660 660 727 672 672 728 684 684 741 685 685 742 672 672 728 685 685 742 673 673 729 673 673 729 685 685 742 686 686 743 673 673 729 686 686 743 674 674 730 674 674 730 686 686 743 687 687 744 674 674 730 687 687 744 675 675 731 675 675 731 687 687 744 688 688 745 675 675 731 688 688 745 676 676 732 676 676 732 688 688 745 689 689 746 676 676 732 689 689 746 677 677 733 677 677 733 689 689 746 690 690 747 677 677 733 690 690 747 678 678 734 678 678 734 690 690 747 691 691 748 678 678 734 691 691 748 679 679 735 679 679 735 691 691 748 692 692 749 679 679 735 692 692 749 680 680 736 680 680 736 692 692 749 693 693 750 680 680 736 693 693 750 681 681 737 681 681 737 693 693 750 694 694 751 681 681 737 694 694 751 682 682 738 682 682 738 694 694 751 695 695 752 682 682 738 695 695 752 683 683 739 683 683 739 695 695 752 684 684 753 683 683 739 684 684 753 672 672 740 684 684 741 696 696 754 697 697 755 684 684 741 697 697 755 685 685 742 685 685 742 697 697 755 698 698 756 685 685 742 698 698 756 686 686 743 686 686 743 698 698 756 699 699 757 686 686 743 699 699 757 687 687 744 687 687 744 699 699 757 700 700 758 687 687 744 700 700 758 688 688 745 688 688 745 700 700 758 701 701 759 688 688 745 701 701 759 689 689 746 689 689 746 701 701 759 702 702 760 689 689 746 702 702 760 690 690 747 690 690 747 702 702 760 703 703 761 690 690 747 703 703 761 691 691 748 691 691 748 703 703 761 704 704 762 691 691 748 704 704 762 692 692 749 692 692 749 704 704 762 705 705 763 692 692 749 705 705 763 693 693 750 693 693 750 705 705 763 706 706 764 693 693 750 706 706 764 694 694 751 694 694 751 706 706 764 707 707 765 694 694 751 707 707 765 695 695 752 695 695 752 707 707 765 696 696 766 695 695 752 696 696 766 684 684 753 696 696 754 708 708 767 709 709 768 696 696 754 709 709 768 697 697 755 697 697 755 709 709 768 710 710 769 697 697 755 710 710 769 698 698 756 698 698 756 710 710 769 711 711 770 698 698 756 711 711 770 699 699 757 699 699 757 711 711 770 712 712 771 699 699 757 712 712 771 700 700 758 700 700 758 712 712 771 713 713 772 700 700 758 713 713 772 701 701 759 701 701 759 713 713 772 714 714 773 701 701 759 714 714 773 702 702 760 702 702 760 714 714 773 715 715 774 702 702 760 715 715 774 703 703 761 703 703 761 715 715 774 716 716 775 703 703 761 716 716 775 704 704 762 704 704 762 716 716 775 717 717 776 704 704 762 717 717 776 705 705 763 705 705 763 717 717 776 718 718 777 705 705 763 718 718 777 706 706 764 706 706 764 718 718 777 719 719 778 706 706 764 719 719 778 707 707 765 707 707 765 719 719 778 708 708 779 707 707 765 708 708 779 696 696 766 708 708 767 720 720 780 721 721 781 708 708 767 721 721 781 709 709 768 709 709 768 721 721 781 722 722 782 709 709 768 722 722 782 710 710 769 710 710 769 722 722 782 723 723 783 710 710 769 723 723 783 711 711 770 711 711 770 723 723 783 724 724 784 711 711 770 724 724 784 712 712 771 712 712 771 724 724 784 725 725 785 712 712 771 725 725 785 713 713 772 713 713 772 725 725 785 726 726 786 713 713 772 726 726 786 714 714 773 714 714 773 726 726 786 727 727 787 714 714 773 727 727 787 715 715 774 715 715 774 727 727 787 728 728 788 715 715 774 728 728 788 716 716 775 716 716 775 728 728 788 729 729 789 716 716 775 729 729 789 717 717 776 717 717 776 729 729 789 730 730 790 717 717 776 730 730 790 718 718 777 718 718 777 730 730 790 731 731 791 718 718 777 731 731 791 719 719 778 719 719 778 731 731 791 720 720 792 719 719 778 720 720 792 708 708 779 720 720 780 732 732 793 733 733 794 720 720 780 733 733 794 721 721 781 721 721 781 733 733 794 734 734 795 721 721 781 734 734 795 722 722 782 722 722 782 734 734 795 735 735 796 722 722 782 735 735 796 723 723 783 723 723 783 735 735 796 736 736 797 723 723 783 736 736 797 724 724 784 724 724 784 736 736 797 737 737 798 724 724 784 737 737 798 725 725 785 725 725 785 737 737 798 738 738 799 725 725 785 738 738 799 726 726 786 726 726 786 738 738 799 739 739 800 726 726 786 739 739 800 727 727 787 727 727 787 739 739 800 740 740 801 727 727 787 740 740 801 728 728 788 728 728 788 740 740 801 741 741 802 728 728 788 741 741 802 729 729 789 729 729 789 741 741 802 742 742 803 729 729 789 742 742 803 730 730 790 730 730 790 742 742 803 743 743 804 730 730 790 743 743 804 731 731 791 731 731 791 743 743 804 732 732 805 731 731 791 732 732 805 720 720 792 732 732 793 744 744 806 745 745 807 732 732 793 745 745 807 733 733 794 733 733 794 745 745 807 746 746 808 733 733 794 746 746 808 734 734 795 734 734 795 746 746 808 747 747 809 734 734 795 747 747 809 735 735 796 735 735 796 747 747 809 748 748 810 735 735 796 748 748 810 736 736 797 736 736 797 748 748 810 749 749 811 736 736 797 749 749 811 737 737 798 737 737 798 749 749 811 750 750 812 737 737 798 750 750 812 738 738 799 738 738 799 750 750 812 751 751 813 738 738 799 751 751 813 739 739 800 739 739 800 751 751 813 752 752 814 739 739 800 752 752 814 740 740 801 740 740 801 752 752 814 753 753 815 740 740 801 753 753 815 741 741 802 741 741 802 753 753 815 754 754 816 741 741 802 754 754 816 742 742 803 742 742 803 754 754 816 755 755 817 742 742 803 755 755 817 743 743 804 743 743 804 755 755 817 744 744 818 743 743 804 744 744 818 732 732 805 744 744 806 756 756 819 757 757 820 744 744 806 757 757 820 745 745 807 745 745 807 757 757 820 758 758 821 745 745 807 758 758 821 746 746 808 746 746 808 758 758 821 759 759 822 746 746 808 759 759 822 747 747 809 747 747 809 759 759 822 760 760 823 747 747 809 760 760 823 748 748 810 748 748 810 760 760 823 761 761 824 748 748 810 761 761 824 749 749 811 749 749 811 761 761 824 762 762 825 749 749 811 762 762 825 750 750 812 750 750 812 762 762 825 763 763 826 750 750 812 763 763 826 751 751 813 751 751 813 763 763 826 764 764 827 751 751 813 764 764 827 752 752 814 752 752 814 764 764 827 765 765 828 752 752 814 765 765 828 753 753 815 753 753 815 765 765 828 766 766 829 753 753 815 766 766 829 754 754 816 754 754 816 766 766 829 767 767 830 754 754 816 767 767 830 755 755 817 755 755 817 767 767 830 756 756 831 755 755 817 756 756 831 744 744 818 756 756 819 768 768 832 769 769 833 756 756 819 769 769 833 757 757 820 757 757 820 769 769 833 770 770 834 757 757 820 770 770 834 758 758 821 758 758 821 770 770 834 771 771 835 758 758 821 771 771 835 759 759 822 759 759 822 771 771 835 772 772 836 759 759 822 772 772 836 760 760 823 760 760 823 772 772 836 773 773 837 760 760 823 773 773 837 761 761 824 761 761 824 773 773 837 774 774 838 761 761 824 774 774 838 762 762 825 762 762 825 774 774 838 775 775 839 762 762 825 775 775 839 763 763 826 763 763 826 775 775 839 776 776 840 763 763 826 776 776 840 764 764 827 764 764 827 776 776 840 777 777 841 764 764 827 777 777 841 765 765 828 765 765 828 777 777 841 778 778 842 765 765 828 778 778 842 766 766 829 766 766 829 778 778 842 779 779 843 766 766 829 779 779 843 767 767 830 767 767 830 779 779 843 768 768 844 767 767 830 768 768 844 756 756 831 768 768 832 780 780 845 781 781 846 768 768 832 781 781 846 769 769 833 769 769 833 781 781 846 782 782 847 769 769 833 782 782 847 770 770 834 770 770 834 782 782 847 783 783 848 770 770 834 783 783 848 771 771 835 771 771 835 783 783 848 784 784 849 771 771 835 784 784 849 772 772 836 772 772 836 784 784 849 785 785 850 772 772 836 785 785 850 773 773 837 773 773 837 785 785 850 786 786 851 773 773 837 786 786 851 774 774 838 774 774 838 786 786 851 787 787 852 774 774 838 787 787 852 775 775 839 775 775 839 787 787 852 788 788 853 775 775 839 788 788 853 776 776 840 776 776 840 788 788 853 789 789 854 776 776 840 789 789 854 777 777 841 777 777 841 789 789 854 790 790 855 777 777 841 790 790 855 778 778 842 778 778 842 790 790 855 791 791 856 778 778 842 791 791 856 779 779 843 779 779 843 791 791 856 780 780 857 779 779 843 780 780 857 768 768 844 780 780 845 792 792 858 793 793 859 780 780 845 793 793 859 781 781 846 781 781 846 793 793 859 794 794 860 781 781 846 794 794 860 782 782 847 782 782 847 794 794 860 795 795 861 782 782 847 795 795 861 783 783 848 783 783 848 795 795 861 796 796 862 783 783 848 796 796 862 784 784 849 784 784 849 796 796 862 797 797 863 784 784 849 797 797 863 785 785 850 785 785 850 797 797 863 798 798 864 785 785 850 798 798 864 786 786 851 786 786 851 798 798 864 799 799 865 786 786 851 799 799 865 787 787 852 787 787 852 799 799 865 800 800 866 787 787 852 800 800 866 788 788 853 788 788 853 800 800 866 801 801 867 788 788 853 801 801 867 789 789 854 789 789 854 801 801 867 802 802 868 789 789 854 802 802 868 790 790 855 790 790 855 802 802 868 803 803 869 790 790 855 803 803 869 791 791 856 791 791 856 803 803 869 792 792 870 791 791 856 792 792 870 780 780 857 792 792 858 804 804 871 805 805 872 792 792 858 805 805 872 793 793 859 793 793 859 805 805 872 806 806 873 793 793 859 806 806 873 794 794 860 794 794 860 806 806 873 807 807 874 794 794 860 807 807 874 795 795 861 795 795 861 807 807 874 808 808 875 795 795 861 808 808 875 796 796 862 796 796 862 808 808 875 809 809 876 796 796 862 809 809 876 797 797 863 797 797 863 809 809 876 810 810 877 797 797 863 810 810 877 798 798 864 798 798 864 810 810 877 811 811 878 798 798 864 811 811 878 799 799 865 799 799 865 811 811 878 812 812 879 799 799 865 812 812 879 800 800 866 800 800 866 812 812 879 813 813 880 800 800 866 813 813 880 801 801 867 801 801 867 813 813 880 814 814 881 801 801 867 814 814 881 802 802 868 802 802 868 814 814 881 815 815 882 802 802 868 815 815 882 803 803 869 803 803 869 815 815 882 804 804 883 803 803 869 804 804 883 792 792 870 804 804 871 816 816 884 817 817 885 804 804 871 817 817 885 805 805 872 805 805 872 817 817 885 818 818 886 805 805 872 818 818 886 806 806 873 806 806 873 818 818 886 819 819 887 806 806 873 819 819 887 807 807 874 807 807 874 819 819 887 820 820 888 807 807 874 820 820 888 808 808 875 808 808 875 820 820 888 821 821 889 808 808 875 821 821 889 809 809 876 809 809 876 821 821 889 822 822 890 809 809 876 822 822 890 810 810 877 810 810 877 822 822 890 823 823 891 810 810 877 823 823 891 811 811 878 811 811 878 823 823 891 824 824 892 811 811 878 824 824 892 812 812 879 812 812 879 824 824 892 825 825 893 812 812 879 825 825 893 813 813 880 813 813 880 825 825 893 826 826 894 813 813 880 826 826 894 814 814 881 814 814 881 826 826 894 827 827 895 814 814 881 827 827 895 815 815 882 815 815 882 827 827 895 816 816 896 815 815 882 816 816 896 804 804 883 816 816 884 828 828 897 829 829 898 816 816 884 829 829 898 817 817 885 817 817 885 829 829 898 830 830 899 817 817 885 830 830 899 818 818 886 818 818 886 830 830 899 831 831 900 818 818 886 831 831 900 819 819 887 819 819 887 831 831 900 832 832 901 819 819 887 832 832 901 820 820 888 820 820 888 832 832 901 833 833 902 820 820 888 833 833 902 821 821 889 821 821 889 833 833 902 834 834 903 821 821 889 834 834 903 822 822 890 822 822 890 834 834 903 835 835 904 822 822 890 835 835 904 823 823 891 823 823 891 835 835 904 836 836 905 823 823 891 836 836 905 824 824 892 824 824 892 836 836 905 837 837 906 824 824 892 837 837 906 825 825 893 825 825 893 837 837 906 838 838 907 825 825 893 838 838 907 826 826 894 826 826 894 838 838 907 839 839 908 826 826 894 839 839 908 827 827 895 827 827 895 839 839 908 828 828 909 827 827 895 828 828 909 816 816 896 828 828 897 840 840 910 841 841 911 828 828 897 841 841 911 829 829 898 829 829 898 841 841 911 842 842 912 829 829 898 842 842 912 830 830 899 830 830 899 842 842 912 843 843 913 830 830 899 843 843 913 831 831 900 831 831 900 843 843 913 844 844 914 831 831 900 844 844 914 832 832 901 832 832 901 844 844 914 845 845 915 832 832 901 845 845 915 833 833 902 833 833 902 845 845 915 846 846 916 833 833 902 846 846 916 834 834 903 834 834 903 846 846 916 847 847 917 834 834 903 847 847 917 835 835 904 835 835 904 847 847 917 848 848 918 835 835 904 848 848 918 836 836 905 836 836 905 848 848 918 849 849 919 836 836 905 849 849 919 837 837 906 837 837 906 849 849 919 850 850 920 837 837 906 850 850 920 838 838 907 838 838 907 850 850 920 851 851 921 838 838 907 851 851 921 839 839 908 839 839 908 851 851 921 840 840 922 839 839 908 840 840 922 828 828 909 840 840 910 852 852 923 853 853 924 840 840 910 853 853 924 841 841 911 841 841 911 853 853 924 854 854 925 841 841 911 854 854 925 842 842 912 842 842 912 854 854 925 855 855 926 842 842 912 855 855 926 843 843 913 843 843 913 855 855 926 856 856 927 843 843 913 856 856 927 844 844 914 844 844 914 856 856 927 857 857 928 844 844 914 857 857 928 845 845 915 845 845 915 857 857 928 858 858 929 845 845 915 858 858 929 846 846 916 846 846 916 858 858 929 859 859 930 846 846 916 859 859 930 847 847 917 847 847 917 859 859 930 860 860 931 847 847 917 860 860 931 848 848 918 848 848 918 860 860 931 861 861 932 848 848 918 861 861 932 849 849 919 849 849 919 861 861 932 862 862 933 849 849 919 862 862 933 850 850 920 850 850 920 862 862 933 863 863 934 850 850 920 863 863 934 851 851 921 851 851 921 863 863 934 852 852 935 851 851 921 852 852 935 840 840 922 852 852 923 864 864 936 865 865 937 852 852 923 865 865 937 853 853 924 853 853 924 865 865 937 866 866 938 853 853 924 866 866 938 854 854 925 854 854 925 866 866 938 867 867 939 854 854 925 867 867 939 855 855 926 855 855 926 867 867 939 868 868 940 855 855 926 868 868 940 856 856 927 856 856 927 868 868 940 869 869 941 856 856 927 869 869 941 857 857 928 857 857 928 869 869 941 870 870 942 857 857 928 870 870 942 858 858 929 858 858 929 870 870 942 871 871 943 858 858 929 871 871 943 859 859 930 859 859 930 871 871 943 872 872 944 859 859 930 872 872 944 860 860 931 860 860 931 872 872 944 873 873 945 860 860 931 873 873 945 861 861 932 861 861 932 873 873 945 874 874 946 861 861 932 874 874 946 862 862 933 862 862 933 874 874 946 875 875 947 862 862 933 875 875 947 863 863 934 863 863 934 875 875 947 864 864 948 863 863 934 864 864 948 852 852 935 864 864 936 876 876 949 877 877 950 864 864 936 877 877 950 865 865 937 865 865 937 877 877 950 878 878 951 865 865 937 878 878 951 866 866 938 866 866 938 878 878 951 879 879 952 866 866 938 879 879 952 867 867 939 867 867 939 879 879 952 880 880 953 867 867 939 880 880 953 868 868 940 868 868 940 880 880 953 881 881 954 868 868 940 881 881 954 869 869 941 869 869 941 881 881 954 882 882 955 869 869 941 882 882 955 870 870 942 870 870 942 882 882 955 883 883 956 870 870 942 883 883 956 871 871 943 871 871 943 883 883 956 884 884 957 871 871 943 884 884 957 872 872 944 872 872 944 884 884 957 885 885 958 872 872 944 885 885 958 873 873 945 873 873 945 885 885 958 886 886 959 873 873 945 886 886 959 874 874 946 874 874 946 886 886 959 887 887 960 874 874 946 887 887 960 875 875 947 875 875 947 887 887 960 876 876 961 875 875 947 876 876 961 864 864 948 876 876 949 888 888 962 889 889 963 876 876 949 889 889 963 877 877 950 877 877 950 889 889 963 890 890 964 877 877 950 890 890 964 878 878 951 878 878 951 890 890 964 891 891 965 878 878 951 891 891 965 879 879 952 879 879 952 891 891 965 892 892 966 879 879 952 892 892 966 880 880 953 880 880 953 892 892 966 893 893 967 880 880 953 893 893 967 881 881 954 881 881 954 893 893 967 894 894 968 881 881 954 894 894 968 882 882 955 882 882 955 894 894 968 895 895 969 882 882 955 895 895 969 883 883 956 883 883 956 895 895 969 896 896 970 883 883 956 896 896 970 884 884 957 884 884 957 896 896 970 897 897 971 884 884 957 897 897 971 885 885 958 885 885 958 897 897 971 898 898 972 885 885 958 898 898 972 886 886 959 886 886 959 898 898 972 899 899 973 886 886 959 899 899 973 887 887 960 887 887 960 899 899 973 888 888 974 887 887 960 888 888 974 876 876 961 888 888 962 900 900 975 901 901 976 888 888 962 901 901 976 889 889 963 889 889 963 901 901 976 902 902 977 889 889 963 902 902 977 890 890 964 890 890 964 902 902 977 903 903 978 890 890 964 903 903 978 891 891 965 891 891 965 903 903 978 904 904 979 891 891 965 904 904 979 892 892 966 892 892 966 904 904 979 905 905 980 892 892 966 905 905 980 893 893 967 893 893 967 905 905 980 906 906 981 893 893 967 906 906 981 894 894 968 894 894 968 906 906 981 907 907 982 894 894 968 907 907 982 895 895 969 895 895 969 907 907 982 908 908 983 895 895 969 908 908 983 896 896 970 896 896 970 908 908 983 909 909 984 896 896 970 909 909 984 897 897 971 897 897 971 909 909 984 910 910 985 897 897 971 910 910 985 898 898 972 898 898 972 910 910 985 911 911 986 898 898 972 911 911 986 899 899 973 899 899 973 911 911 986 900 900 987 899 899 973 900 900 987 888 888 974 900 900 975 912 912 988 913 913 989 900 900 975 913 913 989 901 901 976 901 901 976 913 913 989 914 914 990 901 901 976 914 914 990 902 902 977 902 902 977 914 914 990 915 915 991 902 902 977 915 915 991 903 903 978 903 903 978 915 915 991 916 916 992 903 903 978 916 916 992 904 904 979 904 904 979 916 916 992 917 917 993 904 904 979 917 917 993 905 905 980 905 905 980 917 917 993 918 918 994 905 905 980 918 918 994 906 906 981 906 906 981 918 918 994 919 919 995 906 906 981 919 919 995 907 907 982 907 907 982 919 919 995 920 920 996 907 907 982 920 920 996 908 908 983 908 908 983 920 920 996 921 921 997 908 908 983 921 921 997 909 909 984 909 909 984 921 921 997 922 922 998 909 909 984 922 922 998 910 910 985 910 910 985 922 922 998 923 923 999 910 910 985 923 923 999 911 911 986 911 911 986 923 923 999 912 912 1000 911 911 986 912 912 1000 900 900 987 912 912 988 924 924 1001 925 925 1002 912 912 988 925 925 1002 913 913 989 913 913 989 925 925 1002 926 926 1003 913 913 989 926 926 1003 914 914 990 914 914 990 926 926 1003 927 927 1004 914 914 990 927 927 1004 915 915 991 915 915 991 927 927 1004 928 928 1005 915 915 991 928 928 1005 916 916 992 916 916 992 928 928 1005 929 929 1006 916 916 992 929 929 1006 917 917 993 917 917 993 929 929 1006 930 930 1007 917 917 993 930 930 1007 918 918 994 918 918 994 930 930 1007 931 931 1008 918 918 994 931 931 1008 919 919 995 919 919 995 931 931 1008 932 932 1009 919 919 995 932 932 1009 920 920 996 920 920 996 932 932 1009 933 933 1010 920 920 996 933 933 1010 921 921 997 921 921 997 933 933 1010 934 934 1011 921 921 997 934 934 1011 922 922 998 922 922 998 934 934 1011 935 935 1012 922 922 998 935 935 1012 923 923 999 923 923 999 935 935 1012 924 924 1013 923 923 999 924 924 1013 912 912 1000 924 924 1001 936 936 1014 937 937 1015 924 924 1001 937 937 1015 925 925 1002 925 925 1002 937 937 1015 938 938 1016 925 925 1002 938 938 1016 926 926 1003 926 926 1003 938 938 1016 939 939 1017 926 926 1003 939 939 1017 927 927 1004 927 927 1004 939 939 1017 940 940 1018 927 927 1004 940 940 1018 928 928 1005 928 928 1005 940 940 1018 941 941 1019 928 928 1005 941 941 1019 929 929 1006 929 929 1006 941 941 1019 942 942 1020 929 929 1006 942 942 1020 930 930 1007 930 930 1007 942 942 1020 943 943 1021 930 930 1007 943 943 1021 931 931 1008 931 931 1008 943 943 1021 944 944 1022 931 931 1008 944 944 1022 932 932 1009 932 932 1009 944 944 1022 945 945 1023 932 932 1009 945 945 1023 933 933 1010 933 933 1010 945 945 1023 946 946 1024 933 933 1010 946 946 1024 934 934 1011 934 934 1011 946 946 1024 947 947 1025 934 934 1011 947 947 1025 935 935 1012 935 935 1012 947 947 1025 936 936 1026 935 935 1012 936 936 1026 924 924 1013 936 936 1014 948 948 1027 949 949 1028 936 936 1014 949 949 1028 937 937 1015 937 937 1015 949 949 1028 950 950 1029 937 937 1015 950 950 1029 938 938 1016 938 938 1016 950 950 1029 951 951 1030 938 938 1016 951 951 1030 939 939 1017 939 939 1017 951 951 1030 952 952 1031 939 939 1017 952 952 1031 940 940 1018 940 940 1018 952 952 1031 953 953 1032 940 940 1018 953 953 1032 941 941 1019 941 941 1019 953 953 1032 954 954 1033 941 941 1019 954 954 1033 942 942 1020 942 942 1020 954 954 1033 955 955 1034 942 942 1020 955 955 1034 943 943 1021 943 943 1021 955 955 1034 956 956 1035 943 943 1021 956 956 1035 944 944 1022 944 944 1022 956 956 1035 957 957 1036 944 944 1022 957 957 1036 945 945 1023 945 945 1023 957 957 1036 958 958 1037 945 945 1023 958 958 1037 946 946 1024 946 946 1024 958 958 1037 959 959 1038 946 946 1024 959 959 1038 947 947 1025 947 947 1025 959 959 1038 948 948 1039 947 947 1025 948 948 1039 936 936 1026 948 948 1027 960 960 1040 961 961 1041 948 948 1027 961 961 1041 949 949 1028 949 949 1028 961 961 1041 962 962 1042 949 949 1028 962 962 1042 950 950 1029 950 950 1029 962 962 1042 963 963 1043 950 950 1029 963 963 1043 951 951 1030 951 951 1030 963 963 1043 964 964 1044 951 951 1030 964 964 1044 952 952 1031 952 952 1031 964 964 1044 965 965 1045 952 952 1031 965 965 1045 953 953 1032 953 953 1032 965 965 1045 966 966 1046 953 953 1032 966 966 1046 954 954 1033 954 954 1033 966 966 1046 967 967 1047 954 954 1033 967 967 1047 955 955 1034 955 955 1034 967 967 1047 968 968 1048 955 955 1034 968 968 1048 956 956 1035 956 956 1035 968 968 1048 969 969 1049 956 956 1035 969 969 1049 957 957 1036 957 957 1036 969 969 1049 970 970 1050 957 957 1036 970 970 1050 958 958 1037 958 958 1037 970 970 1050 971 971 1051 958 958 1037 971 971 1051 959 959 1038 959 959 1038 971 971 1051 960 960 1052 959 959 1038 960 960 1052 948 948 1039 960 960 1040 972 972 1053 973 973 1054 960 960 1040 973 973 1054 961 961 1041 961 961 1041 973 973 1054 974 974 1055 961 961 1041 974 974 1055 962 962 1042 962 962 1042 974 974 1055 975 975 1056 962 962 1042 975 975 1056 963 963 1043 963 963 1043 975 975 1056 976 976 1057 963 963 1043 976 976 1057 964 964 1044 964 964 1044 976 976 1057 977 977 1058 964 964 1044 977 977 1058 965 965 1045 965 965 1045 977 977 1058 978 978 1059 965 965 1045 978 978 1059 966 966 1046 966 966 1046 978 978 1059 979 979 1060 966 966 1046 979 979 1060 967 967 1047 967 967 1047 979 979 1060 980 980 1061 967 967 1047 980 980 1061 968 968 1048 968 968 1048 980 980 1061 981 981 1062 968 968 1048 981 981 1062 969 969 1049 969 969 1049 981 981 1062 982 982 1063 969 969 1049 982 982 1063 970 970 1050 970 970 1050 982 982 1063 983 983 1064 970 970 1050 983 983 1064 971 971 1051 971 971 1051 983 983 1064 972 972 1065 971 971 1051 972 972 1065 960 960 1052 972 972 1053 984 984 1066 985 985 1067 972 972 1053 985 985 1067 973 973 1054 973 973 1054 985 985 1067 986 986 1068 973 973 1054 986 986 1068 974 974 1055 974 974 1055 986 986 1068 987 987 1069 974 974 1055 987 987 1069 975 975 1056 975 975 1056 987 987 1069 988 988 1070 975 975 1056 988 988 1070 976 976 1057 976 976 1057 988 988 1070 989 989 1071 976 976 1057 989 989 1071 977 977 1058 977 977 1058 989 989 1071 990 990 1072 977 977 1058 990 990 1072 978 978 1059 978 978 1059 990 990 1072 991 991 1073 978 978 1059 991 991 1073 979 979 1060 979 979 1060 991 991 1073 992 992 1074 979 979 1060 992 992 1074 980 980 1061 980 980 1061 992 992 1074 993 993 1075 980 980 1061 993 993 1075 981 981 1062 981 981 1062 993 993 1075 994 994 1076 981 981 1062 994 994 1076 982 982 1063 982 982 1063 994 994 1076 995 995 1077 982 982 1063 995 995 1077 983 983 1064 983 983 1064 995 995 1077 984 984 1078 983 983 1064 984 984 1078 972 972 1065 984 984 1066 996 996 1079 997 997 1080 984 984 1066 997 997 1080 985 985 1067 985 985 1067 997 997 1080 998 998 1081 985 985 1067 998 998 1081 986 986 1068 986 986 1068 998 998 1081 999 999 1082 986 986 1068 999 999 1082 987 987 1069 987 987 1069 999 999 1082 1000 1000 1083 987 987 1069 1000 1000 1083 988 988 1070 988 988 1070 1000 1000 1083 1001 1001 1084 988 988 1070 1001 1001 1084 989 989 1071 989 989 1071 1001 1001 1084 1002 1002 1085 989 989 1071 1002 1002 1085 990 990 1072 990 990 1072 1002 1002 1085 1003 1003 1086 990 990 1072 1003 1003 1086 991 991 1073 991 991 1073 1003 1003 1086 1004 1004 1087 991 991 1073 1004 1004 1087 992 992 1074 992 992 1074 1004 1004 1087 1005 1005 1088 992 992 1074 1005 1005 1088 993 993 1075 993 993 1075 1005 1005 1088 1006 1006 1089 993 993 1075 1006 1006 1089 994 994 1076 994 994 1076 1006 1006 1089 1007 1007 1090 994 994 1076 1007 1007 1090 995 995 1077 995 995 1077 1007 1007 1090 996 996 1091 995 995 1077 996 996 1091 984 984 1078 996 996 1079 1008 1008 1092 1009 1009 1093 996 996 1079 1009 1009 1093 997 997 1080 997 997 1080 1009 1009 1093 1010 1010 1094 997 997 1080 1010 1010 1094 998 998 1081 998 998 1081 1010 1010 1094 1011 1011 1095 998 998 1081 1011 1011 1095 999 999 1082 999 999 1082 1011 1011 1095 1012 1012 1096 999 999 1082 1012 1012 1096 1000 1000 1083 1000 1000 1083 1012 1012 1096 1013 1013 1097 1000 1000 1083 1013 1013 1097 1001 1001 1084 1001 1001 1084 1013 1013 1097 1014 1014 1098 1001 1001 1084 1014 1014 1098 1002 1002 1085 1002 1002 1085 1014 1014 1098 1015 1015 1099 1002 1002 1085 1015 1015 1099 1003 1003 1086 1003 1003 1086 1015 1015 1099 1016 1016 1100 1003 1003 1086 1016 1016 1100 1004 1004 1087 1004 1004 1087 1016 1016 1100 1017 1017 1101 1004 1004 1087 1017 1017 1101 1005 1005 1088 1005 1005 1088 1017 1017 1101 1018 1018 1102 1005 1005 1088 1018 1018 1102 1006 1006 1089 1006 1006 1089 1018 1018 1102 1019 1019 1103 1006 1006 1089 1019 1019 1103 1007 1007 1090 1007 1007 1090 1019 1019 1103 1008 1008 1104 1007 1007 1090 1008 1008 1104 996 996 1091 1008 1008 1092 1020 1020 1105 1021 1021 1106 1008 1008 1092 1021 1021 1106 1009 1009 1093 1009 1009 1093 1021 1021 1106 1022 1022 1107 1009 1009 1093 1022 1022 1107 1010 1010 1094 1010 1010 1094 1022 1022 1107 1023 1023 1108 1010 1010 1094 1023 1023 1108 1011 1011 1095 1011 1011 1095 1023 1023 1108 1024 1024 1109 1011 1011 1095 1024 1024 1109 1012 1012 1096 1012 1012 1096 1024 1024 1109 1025 1025 1110 1012 1012 1096 1025 1025 1110 1013 1013 1097 1013 1013 1097 1025 1025 1110 1026 1026 1111 1013 1013 1097 1026 1026 1111 1014 1014 1098 1014 1014 1098 1026 1026 1111 1027 1027 1112 1014 1014 1098 1027 1027 1112 1015 1015 1099 1015 1015 1099 1027 1027 1112 1028 1028 1113 1015 1015 1099 1028 1028 1113 1016 1016 1100 1016 1016 1100 1028 1028 1113 1029 1029 1114 1016 1016 1100 1029 1029 1114 1017 1017 1101 1017 1017 1101 1029 1029 1114 1030 1030 1115 1017 1017 1101 1030 1030 1115 1018 1018 1102 1018 1018 1102 1030 1030 1115 1031 1031 1116 1018 1018 1102 1031 1031 1116 1019 1019 1103 1019 1019 1103 1031 1031 1116 1020 1020 1117 1019 1019 1103 1020 1020 1117 1008 1008 1104 1020 1020 1105 1032 1032 1118 1033 1033 1119 1020 1020 1105 1033 1033 1119 1021 1021 1106 1021 1021 1106 1033 1033 1119 1034 1034 1120 1021 1021 1106 1034 1034 1120 1022 1022 1107 1022 1022 1107 1034 1034 1120 1035 1035 1121 1022 1022 1107 1035 1035 1121 1023 1023 1108 1023 1023 1108 1035 1035 1121 1036 1036 1122 1023 1023 1108 1036 1036 1122 1024 1024 1109 1024 1024 1109 1036 1036 1122 1037 1037 1123 1024 1024 1109 1037 1037 1123 1025 1025 1110 1025 1025 1110 1037 1037 1123 1038 1038 1124 1025 1025 1110 1038 1038 1124 1026 1026 1111 1026 1026 1111 1038 1038 1124 1039 1039 1125 1026 1026 1111 1039 1039 1125 1027 1027 1112 1027 1027 1112 1039 1039 1125 1040 1040 1126 1027 1027 1112 1040 1040 1126 1028 1028 1113 1028 1028 1113 1040 1040 1126 1041 1041 1127 1028 1028 1113 1041 1041 1127 1029 1029 1114 1029 1029 1114 1041 1041 1127 1042 1042 1128 1029 1029 1114 1042 1042 1128 1030 1030 1115 1030 1030 1115 1042 1042 1128 1043 1043 1129 1030 1030 1115 1043 1043 1129 1031 1031 1116 1031 1031 1116 1043 1043 1129 1032 1032 1130 1031 1031 1116 1032 1032 1130 1020 1020 1117 1032 1032 1118 1044 1044 1131 1045 1045 1132 1032 1032 1118 1045 1045 1132 1033 1033 1119 1033 1033 1119 1045 1045 1132 1046 1046 1133 1033 1033 1119 1046 1046 1133 1034 1034 1120 1034 1034 1120 1046 1046 1133 1047 1047 1134 1034 1034 1120 1047 1047 1134 1035 1035 1121 1035 1035 1121 1047 1047 1134 1048 1048 1135 1035 1035 1121 1048 1048 1135 1036 1036 1122 1036 1036 1122 1048 1048 1135 1049 1049 1136 1036 1036 1122 1049 1049 1136 1037 1037 1123 1037 1037 1123 1049 1049 1136 1050 1050 1137 1037 1037 1123 1050 1050 1137 1038 1038 1124 1038 1038 1124 1050 1050 1137 1051 1051 1138 1038 1038 1124 1051 1051 1138 1039 1039 1125 1039 1039 1125 1051 1051 1138 1052 1052 1139 1039 1039 1125 1052 1052 1139 1040 1040 1126 1040 1040 1126 1052 1052 1139 1053 1053 1140 1040 1040 1126 1053 1053 1140 1041 1041 1127 1041 1041 1127 1053 1053 1140 1054 1054 1141 1041 1041 1127 1054 1054 1141 1042 1042 1128 1042 1042 1128 1054 1054 1141 1055 1055 1142 1042 1042 1128 1055 1055 1142 1043 1043 1129 1043 1043 1129 1055 1055 1142 1044 1044 1143 1043 1043 1129 1044 1044 1143 1032 1032 1130 1044 1044 1131 1056 1056 1144 1057 1057 1145 1044 1044 1131 1057 1057 1145 1045 1045 1132 1045 1045 1132 1057 1057 1145 1058 1058 1146 1045 1045 1132 1058 1058 1146 1046 1046 1133 1046 1046 1133 1058 1058 1146 1059 1059 1147 1046 1046 1133 1059 1059 1147 1047 1047 1134 1047 1047 1134 1059 1059 1147 1060 1060 1148 1047 1047 1134 1060 1060 1148 1048 1048 1135 1048 1048 1135 1060 1060 1148 1061 1061 1149 1048 1048 1135 1061 1061 1149 1049 1049 1136 1049 1049 1136 1061 1061 1149 1062 1062 1150 1049 1049 1136 1062 1062 1150 1050 1050 1137 1050 1050 1137 1062 1062 1150 1063 1063 1151 1050 1050 1137 1063 1063 1151 1051 1051 1138 1051 1051 1138 1063 1063 1151 1064 1064 1152 1051 1051 1138 1064 1064 1152 1052 1052 1139 1052 1052 1139 1064 1064 1152 1065 1065 1153 1052 1052 1139 1065 1065 1153 1053 1053 1140 1053 1053 1140 1065 1065 1153 1066 1066 1154 1053 1053 1140 1066 1066 1154 1054 1054 1141 1054 1054 1141 1066 1066 1154 1067 1067 1155 1054 1054 1141 1067 1067 1155 1055 1055 1142 1055 1055 1142 1067 1067 1155 1056 1056 1156 1055 1055 1142 1056 1056 1156 1044 1044 1143 1056 1056 1144 1068 1068 1157 1069 1069 1158 1056 1056 1144 1069 1069 1158 1057 1057 1145 1057 1057 1145 1069 1069 1158 1070 1070 1159 1057 1057 1145 1070 1070 1159 1058 1058 1146 1058 1058 1146 1070 1070 1159 1071 1071 1160 1058 1058 1146 1071 1071 1160 1059 1059 1147 1059 1059 1147 1071 1071 1160 1072 1072 1161 1059 1059 1147 1072 1072 1161 1060 1060 1148 1060 1060 1148 1072 1072 1161 1073 1073 1162 1060 1060 1148 1073 1073 1162 1061 1061 1149 1061 1061 1149 1073 1073 1162 1074 1074 1163 1061 1061 1149 1074 1074 1163 1062 1062 1150 1062 1062 1150 1074 1074 1163 1075 1075 1164 1062 1062 1150 1075 1075 1164 1063 1063 1151 1063 1063 1151 1075 1075 1164 1076 1076 1165 1063 1063 1151 1076 1076 1165 1064 1064 1152 1064 1064 1152 1076 1076 1165 1077 1077 1166 1064 1064 1152 1077 1077 1166 1065 1065 1153 1065 1065 1153 1077 1077 1166 1078 1078 1167 1065 1065 1153 1078 1078 1167 1066 1066 1154 1066 1066 1154 1078 1078 1167 1079 1079 1168 1066 1066 1154 1079 1079 1168 1067 1067 1155 1067 1067 1155 1079 1079 1168 1068 1068 1169 1067 1067 1155 1068 1068 1169 1056 1056 1156 1068 1068 1157 1080 1080 1170 1081 1081 1171 1068 1068 1157 1081 1081 1171 1069 1069 1158 1069 1069 1158 1081 1081 1171 1082 1082 1172 1069 1069 1158 1082 1082 1172 1070 1070 1159 1070 1070 1159 1082 1082 1172 1083 1083 1173 1070 1070 1159 1083 1083 1173 1071 1071 1160 1071 1071 1160 1083 1083 1173 1084 1084 1174 1071 1071 1160 1084 1084 1174 1072 1072 1161 1072 1072 1161 1084 1084 1174 1085 1085 1175 1072 1072 1161 1085 1085 1175 1073 1073 1162 1073 1073 1162 1085 1085 1175 1086 1086 1176 1073 1073 1162 1086 1086 1176 1074 1074 1163 1074 1074 1163 1086 1086 1176 1087 1087 1177 1074 1074 1163 1087 1087 1177 1075 1075 1164 1075 1075 1164 1087 1087 1177 1088 1088 1178 1075 1075 1164 1088 1088 1178 1076 1076 1165 1076 1076 1165 1088 1088 1178 1089 1089 1179 1076 1076 1165 1089 1089 1179 1077 1077 1166 1077 1077 1166 1089 1089 1179 1090 1090 1180 1077 1077 1166 1090 1090 1180 1078 1078 1167 1078 1078 1167 1090 1090 1180 1091 1091 1181 1078 1078 1167 1091 1091 1181 1079 1079 1168 1079 1079 1168 1091 1091 1181 1080 1080 1182 1079 1079 1168 1080 1080 1182 1068 1068 1169 1080 1080 1170 1092 1092 1183 1093 1093 1184 1080 1080 1170 1093 1093 1184 1081 1081 1171 1081 1081 1171 1093 1093 1184 1094 1094 1185 1081 1081 1171 1094 1094 1185 1082 1082 1172 1082 1082 1172 1094 1094 1185 1095 1095 1186 1082 1082 1172 1095 1095 1186 1083 1083 1173 1083 1083 1173 1095 1095 1186 1096 1096 1187 1083 1083 1173 1096 1096 1187 1084 1084 1174 1084 1084 1174 1096 1096 1187 1097 1097 1188 1084 1084 1174 1097 1097 1188 1085 1085 1175 1085 1085 1175 1097 1097 1188 1098 1098 1189 1085 1085 1175 1098 1098 1189 1086 1086 1176 1086 1086 1176 1098 1098 1189 1099 1099 1190 1086 1086 1176 1099 1099 1190 1087 1087 1177 1087 1087 1177 1099 1099 1190 1100 1100 1191 1087 1087 1177 1100 1100 1191 1088 1088 1178 1088 1088 1178 1100 1100 1191 1101 1101 1192 1088 1088 1178 1101 1101 1192 1089 1089 1179 1089 1089 1179 1101 1101 1192 1102 1102 1193 1089 1089 1179 1102 1102 1193 1090 1090 1180 1090 1090 1180 1102 1102 1193 1103 1103 1194 1090 1090 1180 1103 1103 1194 1091 1091 1181 1091 1091 1181 1103 1103 1194 1092 1092 1195 1091 1091 1181 1092 1092 1195 1080 1080 1182 1092 1092 1183 1104 1104 1196 1105 1105 1197 1092 1092 1183 1105 1105 1197 1093 1093 1184 1093 1093 1184 1105 1105 1197 1106 1106 1198 1093 1093 1184 1106 1106 1198 1094 1094 1185 1094 1094 1185 1106 1106 1198 1107 1107 1199 1094 1094 1185 1107 1107 1199 1095 1095 1186 1095 1095 1186 1107 1107 1199 1108 1108 1200 1095 1095 1186 1108 1108 1200 1096 1096 1187 1096 1096 1187 1108 1108 1200 1109 1109 1201 1096 1096 1187 1109 1109 1201 1097 1097 1188 1097 1097 1188 1109 1109 1201 1110 1110 1202 1097 1097 1188 1110 1110 1202 1098 1098 1189 1098 1098 1189 1110 1110 1202 1111 1111 1203 1098 1098 1189 1111 1111 1203 1099 1099 1190 1099 1099 1190 1111 1111 1203 1112 1112 1204 1099 1099 1190 1112 1112 1204 1100 1100 1191 1100 1100 1191 1112 1112 1204 1113 1113 1205 1100 1100 1191 1113 1113 1205 1101 1101 1192 1101 1101 1192 1113 1113 1205 1114 1114 1206 1101 1101 1192 1114 1114 1206 1102 1102 1193 1102 1102 1193 1114 1114 1206 1115 1115 1207 1102 1102 1193 1115 1115 1207 1103 1103 1194 1103 1103 1194 1115 1115 1207 1104 1104 1208 1103 1103 1194 1104 1104 1208 1092 1092 1195 1104 1104 1196 1116 1116 1209 1117 1117 1210 1104 1104 1196 1117 1117 1210 1105 1105 1197 1105 1105 1197 1117 1117 1210 1118 1118 1211 1105 1105 1197 1118 1118 1211 1106 1106 1198 1106 1106 1198 1118 1118 1211 1119 1119 1212 1106 1106 1198 1119 1119 1212 1107 1107 1199 1107 1107 1199 1119 1119 1212 1120 1120 1213 1107 1107 1199 1120 1120 1213 1108 1108 1200 1108 1108 1200 1120 1120 1213 1121 1121 1214 1108 1108 1200 1121 1121 1214 1109 1109 1201 1109 1109 1201 1121 1121 1214 1122 1122 1215 1109 1109 1201 1122 1122 1215 1110 1110 1202 1110 1110 1202 1122 1122 1215 1123 1123 1216 1110 1110 1202 1123 1123 1216 1111 1111 1203 1111 1111 1203 1123 1123 1216 1124 1124 1217 1111 1111 1203 1124 1124 1217 1112 1112 1204 1112 1112 1204 1124 1124 1217 1125 1125 1218 1112 1112 1204 1125 1125 1218 1113 1113 1205 1113 1113 1205 1125 1125 1218 1126 1126 1219 1113 1113 1205 1126 1126 1219 1114 1114 1206 1114 1114 1206 1126 1126 1219 1127 1127 1220 1114 1114 1206 1127 1127 1220 1115 1115 1207 1115 1115 1207 1127 1127 1220 1116 1116 1221 1115 1115 1207 1116 1116 1221 1104 1104 1208 1116 1116 1209 1128 1128 1222 1129 1129 1223 1116 1116 1209 1129 1129 1223 1117 1117 1210 1117 1117 1210 1129 1129 1223 1130 1130 1224 1117 1117 1210 1130 1130 1224 1118 1118 1211 1118 1118 1211 1130 1130 1224 1131 1131 1225 1118 1118 1211 1131 1131 1225 1119 1119 1212 1119 1119 1212 1131 1131 1225 1132 1132 1226 1119 1119 1212 1132 1132 1226 1120 1120 1213 1120 1120 1213 1132 1132 1226 1133 1133 1227 1120 1120 1213 1133 1133 1227 1121 1121 1214 1121 1121 1214 1133 1133 1227 1134 1134 1228 1121 1121 1214 1134 1134 1228 1122 1122 1215 1122 1122 1215 1134 1134 1228 1135 1135 1229 1122 1122 1215 1135 1135 1229 1123 1123 1216 1123 1123 1216 1135 1135 1229 1136 1136 1230 1123 1123 1216 1136 1136 1230 1124 1124 1217 1124 1124 1217 1136 1136 1230 1137 1137 1231 1124 1124 1217 1137 1137 1231 1125 1125 1218 1125 1125 1218 1137 1137 1231 1138 1138 1232 1125 1125 1218 1138 1138 1232 1126 1126 1219 1126 1126 1219 1138 1138 1232 1139 1139 1233 1126 1126 1219 1139 1139 1233 1127 1127 1220 1127 1127 1220 1139 1139 1233 1128 1128 1234 1127 1127 1220 1128 1128 1234 1116 1116 1221 1128 1128 1222 1140 1140 1235 1141 1141 1236 1128 1128 1222 1141 1141 1236 1129 1129 1223 1129 1129 1223 1141 1141 1236 1142 1142 1237 1129 1129 1223 1142 1142 1237 1130 1130 1224 1130 1130 1224 1142 1142 1237 1143 1143 1238 1130 1130 1224 1143 1143 1238 1131 1131 1225 1131 1131 1225 1143 1143 1238 1144 1144 1239 1131 1131 1225 1144 1144 1239 1132 1132 1226 1132 1132 1226 1144 1144 1239 1145 1145 1240 1132 1132 1226 1145 1145 1240 1133 1133 1227 1133 1133 1227 1145 1145 1240 1146 1146 1241 1133 1133 1227 1146 1146 1241 1134 1134 1228 1134 1134 1228 1146 1146 1241 1147 1147 1242 1134 1134 1228 1147 1147 1242 1135 1135 1229 1135 1135 1229 1147 1147 1242 1148 1148 1243 1135 1135 1229 1148 1148 1243 1136 1136 1230 1136 1136 1230 1148 1148 1243 1149 1149 1244 1136 1136 1230 1149 1149 1244 1137 1137 1231 1137 1137 1231 1149 1149 1244 1150 1150 1245 1137 1137 1231 1150 1150 1245 1138 1138 1232 1138 1138 1232 1150 1150 1245 1151 1151 1246 1138 1138 1232 1151 1151 1246 1139 1139 1233 1139 1139 1233 1151 1151 1246 1140 1140 1247 1139 1139 1233 1140 1140 1247 1128 1128 1234 1140 1140 1235 1152 1152 1248 1153 1153 1249 1140 1140 1235 1153 1153 1249 1141 1141 1236 1141 1141 1236 1153 1153 1249 1154 1154 1250 1141 1141 1236 1154 1154 1250 1142 1142 1237 1142 1142 1237 1154 1154 1250 1155 1155 1251 1142 1142 1237 1155 1155 1251 1143 1143 1238 1143 1143 1238 1155 1155 1251 1156 1156 1252 1143 1143 1238 1156 1156 1252 1144 1144 1239 1144 1144 1239 1156 1156 1252 1157 1157 1253 1144 1144 1239 1157 1157 1253 1145 1145 1240 1145 1145 1240 1157 1157 1253 1158 1158 1254 1145 1145 1240 1158 1158 1254 1146 1146 1241 1146 1146 1241 1158 1158 1254 1159 1159 1255 1146 1146 1241 1159 1159 1255 1147 1147 1242 1147 1147 1242 1159 1159 1255 1160 1160 1256 1147 1147 1242 1160 1160 1256 1148 1148 1243 1148 1148 1243 1160 1160 1256 1161 1161 1257 1148 1148 1243 1161 1161 1257 1149 1149 1244 1149 1149 1244 1161 1161 1257 1162 1162 1258 1149 1149 1244 1162 1162 1258 1150 1150 1245 1150 1150 1245 1162 1162 1258 1163 1163 1259 1150 1150 1245 1163 1163 1259 1151 1151 1246 1151 1151 1246 1163 1163 1259 1152 1152 1260 1151 1151 1246 1152 1152 1260 1140 1140 1247 1152 1152 1248 1164 1164 1261 1165 1165 1262 1152 1152 1248 1165 1165 1262 1153 1153 1249 1153 1153 1249 1165 1165 1262 1166 1166 1263 1153 1153 1249 1166 1166 1263 1154 1154 1250 1154 1154 1250 1166 1166 1263 1167 1167 1264 1154 1154 1250 1167 1167 1264 1155 1155 1251 1155 1155 1251 1167 1167 1264 1168 1168 1265 1155 1155 1251 1168 1168 1265 1156 1156 1252 1156 1156 1252 1168 1168 1265 1169 1169 1266 1156 1156 1252 1169 1169 1266 1157 1157 1253 1157 1157 1253 1169 1169 1266 1170 1170 1267 1157 1157 1253 1170 1170 1267 1158 1158 1254 1158 1158 1254 1170 1170 1267 1171 1171 1268 1158 1158 1254 1171 1171 1268 1159 1159 1255 1159 1159 1255 1171 1171 1268 1172 1172 1269 1159 1159 1255 1172 1172 1269 1160 1160 1256 1160 1160 1256 1172 1172 1269 1173 1173 1270 1160 1160 1256 1173 1173 1270 1161 1161 1257 1161 1161 1257 1173 1173 1270 1174 1174 1271 1161 1161 1257 1174 1174 1271 1162 1162 1258 1162 1162 1258 1174 1174 1271 1175 1175 1272 1162 1162 1258 1175 1175 1272 1163 1163 1259 1163 1163 1259 1175 1175 1272 1164 1164 1273 1163 1163 1259 1164 1164 1273 1152 1152 1260 1164 1164 1261 1176 1176 1274 1177 1177 1275 1164 1164 1261 1177 1177 1275 1165 1165 1262 1165 1165 1262 1177 1177 1275 1178 1178 1276 1165 1165 1262 1178 1178 1276 1166 1166 1263 1166 1166 1263 1178 1178 1276 1179 1179 1277 1166 1166 1263 1179 1179 1277 1167 1167 1264 1167 1167 1264 1179 1179 1277 1180 1180 1278 1167 1167 1264 1180 1180 1278 1168 1168 1265 1168 1168 1265 1180 1180 1278 1181 1181 1279 1168 1168 1265 1181 1181 1279 1169 1169 1266 1169 1169 1266 1181 1181 1279 1182 1182 1280 1169 1169 1266 1182 1182 1280 1170 1170 1267 1170 1170 1267 1182 1182 1280 1183 1183 1281 1170 1170 1267 1183 1183 1281 1171 1171 1268 1171 1171 1268 1183 1183 1281 1184 1184 1282 1171 1171 1268 1184 1184 1282 1172 1172 1269 1172 1172 1269 1184 1184 1282 1185 1185 1283 1172 1172 1269 1185 1185 1283 1173 1173 1270 1173 1173 1270 1185 1185 1283 1186 1186 1284 1173 1173 1270 1186 1186 1284 1174 1174 1271 1174 1174 1271 1186 1186 1284 1187 1187 1285 1174 1174 1271 1187 1187 1285 1175 1175 1272 1175 1175 1272 1187 1187 1285 1176 1176 1286 1175 1175 1272 1176 1176 1286 1164 1164 1273 1176 1176 1274 1188 1188 1287 1189 1189 1288 1176 1176 1274 1189 1189 1288 1177 1177 1275 1177 1177 1275 1189 1189 1288 1190 1190 1289 1177 1177 1275 1190 1190 1289 1178 1178 1276 1178 1178 1276 1190 1190 1289 1191 1191 1290 1178 1178 1276 1191 1191 1290 1179 1179 1277 1179 1179 1277 1191 1191 1290 1192 1192 1291 1179 1179 1277 1192 1192 1291 1180 1180 1278 1180 1180 1278 1192 1192 1291 1193 1193 1292 1180 1180 1278 1193 1193 1292 1181 1181 1279 1181 1181 1279 1193 1193 1292 1194 1194 1293 1181 1181 1279 1194 1194 1293 1182 1182 1280 1182 1182 1280 1194 1194 1293 1195 1195 1294 1182 1182 1280 1195 1195 1294 1183 1183 1281 1183 1183 1281 1195 1195 1294 1196 1196 1295 1183 1183 1281 1196 1196 1295 1184 1184 1282 1184 1184 1282 1196 1196 1295 1197 1197 1296 1184 1184 1282 1197 1197 1296 1185 1185 1283 1185 1185 1283 1197 1197 1296 1198 1198 1297 1185 1185 1283 1198 1198 1297 1186 1186 1284 1186 1186 1284 1198 1198 1297 1199 1199 1298 1186 1186 1284 1199 1199 1298 1187 1187 1285 1187 1187 1285 1199 1199 1298 1188 1188 1299 1187 1187 1285 1188 1188 1299 1176 1176 1286 1188 1188 1287 1200 1200 1300 1201 1201 1301 1188 1188 1287 1201 1201 1301 1189 1189 1288 1189 1189 1288 1201 1201 1301 1202 1202 1302 1189 1189 1288 1202 1202 1302 1190 1190 1289 1190 1190 1289 1202 1202 1302 1203 1203 1303 1190 1190 1289 1203 1203 1303 1191 1191 1290 1191 1191 1290 1203 1203 1303 1204 1204 1304 1191 1191 1290 1204 1204 1304 1192 1192 1291 1192 1192 1291 1204 1204 1304 1205 1205 1305 1192 1192 1291 1205 1205 1305 1193 1193 1292 1193 1193 1292 1205 1205 1305 1206 1206 1306 1193 1193 1292 1206 1206 1306 1194 1194 1293 1194 1194 1293 1206 1206 1306 1207 1207 1307 1194 1194 1293 1207 1207 1307 1195 1195 1294 1195 1195 1294 1207 1207 1307 1208 1208 1308 1195 1195 1294 1208 1208 1308 1196 1196 1295 1196 1196 1295 1208 1208 1308 1209 1209 1309 1196 1196 1295 1209 1209 1309 1197 1197 1296 1197 1197 1296 1209 1209 1309 1210 1210 1310 1197 1197 1296 1210 1210 1310 1198 1198 1297 1198 1198 1297 1210 1210 1310 1211 1211 1311 1198 1198 1297 1211 1211 1311 1199 1199 1298 1199 1199 1298 1211 1211 1311 1200 1200 1312 1199 1199 1298 1200 1200 1312 1188 1188 1299 1200 1200 1300 1212 1212 1313 1213 1213 1314 1200 1200 1300 1213 1213 1314 1201 1201 1301 1201 1201 1301 1213 1213 1314 1214 1214 1315 1201 1201 1301 1214 1214 1315 1202 1202 1302 1202 1202 1302 1214 1214 1315 1215 1215 1316 1202 1202 1302 1215 1215 1316 1203 1203 1303 1203 1203 1303 1215 1215 1316 1216 1216 1317 1203 1203 1303 1216 1216 1317 1204 1204 1304 1204 1204 1304 1216 1216 1317 1217 1217 1318 1204 1204 1304 1217 1217 1318 1205 1205 1305 1205 1205 1305 1217 1217 1318 1218 1218 1319 1205 1205 1305 1218 1218 1319 1206 1206 1306 1206 1206 1306 1218 1218 1319 1219 1219 1320 1206 1206 1306 1219 1219 1320 1207 1207 1307 1207 1207 1307 1219 1219 1320 1220 1220 1321 1207 1207 1307 1220 1220 1321 1208 1208 1308 1208 1208 1308 1220 1220 1321 1221 1221 1322 1208 1208 1308 1221 1221 1322 1209 1209 1309 1209 1209 1309 1221 1221 1322 1222 1222 1323 1209 1209 1309 1222 1222 1323 1210 1210 1310 1210 1210 1310 1222 1222 1323 1223 1223 1324 1210 1210 1310 1223 1223 1324 1211 1211 1311 1211 1211 1311 1223 1223 1324 1212 1212 1325 1211 1211 1311 1212 1212 1325 1200 1200 1312 1212 1212 1313 1224 1224 1326 1225 1225 1327 1212 1212 1313 1225 1225 1327 1213 1213 1314 1213 1213 1314 1225 1225 1327 1226 1226 1328 1213 1213 1314 1226 1226 1328 1214 1214 1315 1214 1214 1315 1226 1226 1328 1227 1227 1329 1214 1214 1315 1227 1227 1329 1215 1215 1316 1215 1215 1316 1227 1227 1329 1228 1228 1330 1215 1215 1316 1228 1228 1330 1216 1216 1317 1216 1216 1317 1228 1228 1330 1229 1229 1331 1216 1216 1317 1229 1229 1331 1217 1217 1318 1217 1217 1318 1229 1229 1331 1230 1230 1332 1217 1217 1318 1230 1230 1332 1218 1218 1319 1218 1218 1319 1230 1230 1332 1231 1231 1333 1218 1218 1319 1231 1231 1333 1219 1219 1320 1219 1219 1320 1231 1231 1333 1232 1232 1334 1219 1219 1320 1232 1232 1334 1220 1220 1321 1220 1220 1321 1232 1232 1334 1233 1233 1335 1220 1220 1321 1233 1233 1335 1221 1221 1322 1221 1221 1322 1233 1233 1335 1234 1234 1336 1221 1221 1322 1234 1234 1336 1222 1222 1323 1222 1222 1323 1234 1234 1336 1235 1235 1337 1222 1222 1323 1235 1235 1337 1223 1223 1324 1223 1223 1324 1235 1235 1337 1224 1224 1338 1223 1223 1324 1224 1224 1338 1212 1212 1325 1224 1224 1326 1236 1236 1339 1237 1237 1340 1224 1224 1326 1237 1237 1340 1225 1225 1327 1225 1225 1327 1237 1237 1340 1238 1238 1341 1225 1225 1327 1238 1238 1341 1226 1226 1328 1226 1226 1328 1238 1238 1341 1239 1239 1342 1226 1226 1328 1239 1239 1342 1227 1227 1329 1227 1227 1329 1239 1239 1342 1240 1240 1343 1227 1227 1329 1240 1240 1343 1228 1228 1330 1228 1228 1330 1240 1240 1343 1241 1241 1344 1228 1228 1330 1241 1241 1344 1229 1229 1331 1229 1229 1331 1241 1241 1344 1242 1242 1345 1229 1229 1331 1242 1242 1345 1230 1230 1332 1230 1230 1332 1242 1242 1345 1243 1243 1346 1230 1230 1332 1243 1243 1346 1231 1231 1333 1231 1231 1333 1243 1243 1346 1244 1244 1347 1231 1231 1333 1244 1244 1347 1232 1232 1334 1232 1232 1334 1244 1244 1347 1245 1245 1348 1232 1232 1334 1245 1245 1348 1233 1233 1335 1233 1233 1335 1245 1245 1348 1246 1246 1349 1233 1233 1335 1246 1246 1349 1234 1234 1336 1234 1234 1336 1246 1246 1349 1247 1247 1350 1234 1234 1336 1247 1247 1350 1235 1235 1337 1235 1235 1337 1247 1247 1350 1236 1236 1351 1235 1235 1337 1236 1236 1351 1224 1224 1338 1236 1236 1339 1248 1248 1352 1249 1249 1353 1236 1236 1339 1249 1249 1353 1237 1237 1340 1237 1237 1340 1249 1249 1353 1250 1250 1354 1237 1237 1340 1250 1250 1354 1238 1238 1341 1238 1238 1341 1250 1250 1354 1251 1251 1355 1238 1238 1341 1251 1251 1355 1239 1239 1342 1239 1239 1342 1251 1251 1355 1252 1252 1356 1239 1239 1342 1252 1252 1356 1240 1240 1343 1240 1240 1343 1252 1252 1356 1253 1253 1357 1240 1240 1343 1253 1253 1357 1241 1241 1344 1241 1241 1344 1253 1253 1357 1254 1254 1358 1241 1241 1344 1254 1254 1358 1242 1242 1345 1242 1242 1345 1254 1254 1358 1255 1255 1359 1242 1242 1345 1255 1255 1359 1243 1243 1346 1243 1243 1346 1255 1255 1359 1256 1256 1360 1243 1243 1346 1256 1256 1360 1244 1244 1347 1244 1244 1347 1256 1256 1360 1257 1257 1361 1244 1244 1347 1257 1257 1361 1245 1245 1348 1245 1245 1348 1257 1257 1361 1258 1258 1362 1245 1245 1348 1258 1258 1362 1246 1246 1349 1246 1246 1349 1258 1258 1362 1259 1259 1363 1246 1246 1349 1259 1259 1363 1247 1247 1350 1247 1247 1350 1259 1259 1363 1248 1248 1364 1247 1247 1350 1248 1248 1364 1236 1236 1351 1248 1248 1352 1260 1260 1365 1261 1261 1366 1248 1248 1352 1261 1261 1366 1249 1249 1353 1249 1249 1353 1261 1261 1366 1262 1262 1367 1249 1249 1353 1262 1262 1367 1250 1250 1354 1250 1250 1354 1262 1262 1367 1263 1263 1368 1250 1250 1354 1263 1263 1368 1251 1251 1355 1251 1251 1355 1263 1263 1368 1264 1264 1369 1251 1251 1355 1264 1264 1369 1252 1252 1356 1252 1252 1356 1264 1264 1369 1265 1265 1370 1252 1252 1356 1265 1265 1370 1253 1253 1357 1253 1253 1357 1265 1265 1370 1266 1266 1371 1253 1253 1357 1266 1266 1371 1254 1254 1358 1254 1254 1358 1266 1266 1371 1267 1267 1372 1254 1254 1358 1267 1267 1372 1255 1255 1359 1255 1255 1359 1267 1267 1372 1268 1268 1373 1255 1255 1359 1268 1268 1373 1256 1256 1360 1256 1256 1360 1268 1268 1373 1269 1269 1374 1256 1256 1360 1269 1269 1374 1257 1257 1361 1257 1257 1361 1269 1269 1374 1270 1270 1375 1257 1257 1361 1270 1270 1375 1258 1258 1362 1258 1258 1362 1270 1270 1375 1271 1271 1376 1258 1258 1362 1271 1271 1376 1259 1259 1363 1259 1259 1363 1271 1271 1376 1260 1260 1377 1259 1259 1363 1260 1260 1377 1248 1248 1364 1260 1260 1365 1272 1272 1378 1273 1273 1379 1260 1260 1365 1273 1273 1379 1261 1261 1366 1261 1261 1366 1273 1273 1379 1274 1274 1380 1261 1261 1366 1274 1274 1380 1262 1262 1367 1262 1262 1367 1274 1274 1380 1275 1275 1381 1262 1262 1367 1275 1275 1381 1263 1263 1368 1263 1263 1368 1275 1275 1381 1276 1276 1382 1263 1263 1368 1276 1276 1382 1264 1264 1369 1264 1264 1369 1276 1276 1382 1277 1277 1383 1264 1264 1369 1277 1277 1383 1265 1265 1370 1265 1265 1370 1277 1277 1383 1278 1278 1384 1265 1265 1370 1278 1278 1384 1266 1266 1371 1266 1266 1371 1278 1278 1384 1279 1279 1385 1266 1266 1371 1279 1279 1385 1267 1267 1372 1267 1267 1372 1279 1279 1385 1280 1280 1386 1267 1267 1372 1280 1280 1386 1268 1268 1373 1268 1268 1373 1280 1280 1386 1281 1281 1387 1268 1268 1373 1281 1281 1387 1269 1269 1374 1269 1269 1374 1281 1281 1387 1282 1282 1388 1269 1269 1374 1282 1282 1388 1270 1270 1375 1270 1270 1375 1282 1282 1388 1283 1283 1389 1270 1270 1375 1283 1283 1389 1271 1271 1376 1271 1271 1376 1283 1283 1389 1272 1272 1390 1271 1271 1376 1272 1272 1390 1260 1260 1377 1272 1272 1378 1284 1284 1391 1285 1285 1392 1272 1272 1378 1285 1285 1392 1273 1273 1379 1273 1273 1379 1285 1285 1392 1286 1286 1393 1273 1273 1379 1286 1286 1393 1274 1274 1380 1274 1274 1380 1286 1286 1393 1287 1287 1394 1274 1274 1380 1287 1287 1394 1275 1275 1381 1275 1275 1381 1287 1287 1394 1288 1288 1395 1275 1275 1381 1288 1288 1395 1276 1276 1382 1276 1276 1382 1288 1288 1395 1289 1289 1396 1276 1276 1382 1289 1289 1396 1277 1277 1383 1277 1277 1383 1289 1289 1396 1290 1290 1397 1277 1277 1383 1290 1290 1397 1278 1278 1384 1278 1278 1384 1290 1290 1397 1291 1291 1398 1278 1278 1384 1291 1291 1398 1279 1279 1385 1279 1279 1385 1291 1291 1398 1292 1292 1399 1279 1279 1385 1292 1292 1399 1280 1280 1386 1280 1280 1386 1292 1292 1399 1293 1293 1400 1280 1280 1386 1293 1293 1400 1281 1281 1387 1281 1281 1387 1293 1293 1400 1294 1294 1401 1281 1281 1387 1294 1294 1401 1282 1282 1388 1282 1282 1388 1294 1294 1401 1295 1295 1402 1282 1282 1388 1295 1295 1402 1283 1283 1389 1283 1283 1389 1295 1295 1402 1284 1284 1403 1283 1283 1389 1284 1284 1403 1272 1272 1390 1284 1284 1391 1296 1296 1404 1297 1297 1405 1284 1284 1391 1297 1297 1405 1285 1285 1392 1285 1285 1392 1297 1297 1405 1298 1298 1406 1285 1285 1392 1298 1298 1406 1286 1286 1393 1286 1286 1393 1298 1298 1406 1299 1299 1407 1286 1286 1393 1299 1299 1407 1287 1287 1394 1287 1287 1394 1299 1299 1407 1300 1300 1408 1287 1287 1394 1300 1300 1408 1288 1288 1395 1288 1288 1395 1300 1300 1408 1301 1301 1409 1288 1288 1395 1301 1301 1409 1289 1289 1396 1289 1289 1396 1301 1301 1409 1302 1302 1410 1289 1289 1396 1302 1302 1410 1290 1290 1397 1290 1290 1397 1302 1302 1410 1303 1303 1411 1290 1290 1397 1303 1303 1411 1291 1291 1398 1291 1291 1398 1303 1303 1411 1304 1304 1412 1291 1291 1398 1304 1304 1412 1292 1292 1399 1292 1292 1399 1304 1304 1412 1305 1305 1413 1292 1292 1399 1305 1305 1413 1293 1293 1400 1293 1293 1400 1305 1305 1413 1306 1306 1414 1293 1293 1400 1306 1306 1414 1294 1294 1401 1294 1294 1401 1306 1306 1414 1307 1307 1415 1294 1294 1401 1307 1307 1415 1295 1295 1402 1295 1295 1402 1307 1307 1415 1296 1296 1416 1295 1295 1402 1296 1296 1416 1284 1284 1403 1296 1296 1404 1308 1308 1417 1309 1309 1418 1296 1296 1404 1309 1309 1418 1297 1297 1405 1297 1297 1405 1309 1309 1418 1310 1310 1419 1297 1297 1405 1310 1310 1419 1298 1298 1406 1298 1298 1406 1310 1310 1419 1311 1311 1420 1298 1298 1406 1311 1311 1420 1299 1299 1407 1299 1299 1407 1311 1311 1420 1312 1312 1421 1299 1299 1407 1312 1312 1421 1300 1300 1408 1300 1300 1408 1312 1312 1421 1313 1313 1422 1300 1300 1408 1313 1313 1422 1301 1301 1409 1301 1301 1409 1313 1313 1422 1314 1314 1423 1301 1301 1409 1314 1314 1423 1302 1302 1410 1302 1302 1410 1314 1314 1423 1315 1315 1424 1302 1302 1410 1315 1315 1424 1303 1303 1411 1303 1303 1411 1315 1315 1424 1316 1316 1425 1303 1303 1411 1316 1316 1425 1304 1304 1412 1304 1304 1412 1316 1316 1425 1317 1317 1426 1304 1304 1412 1317 1317 1426 1305 1305 1413 1305 1305 1413 1317 1317 1426 1318 1318 1427 1305 1305 1413 1318 1318 1427 1306 1306 1414 1306 1306 1414 1318 1318 1427 1319 1319 1428 1306 1306 1414 1319 1319 1428 1307 1307 1415 1307 1307 1415 1319 1319 1428 1308 1308 1429 1307 1307 1415 1308 1308 1429 1296 1296 1416 1308 1308 1417 1320 1320 1430 1321 1321 1431 1308 1308 1417 1321 1321 1431 1309 1309 1418 1309 1309 1418 1321 1321 1431 1322 1322 1432 1309 1309 1418 1322 1322 1432 1310 1310 1419 1310 1310 1419 1322 1322 1432 1323 1323 1433 1310 1310 1419 1323 1323 1433 1311 1311 1420 1311 1311 1420 1323 1323 1433 1324 1324 1434 1311 1311 1420 1324 1324 1434 1312 1312 1421 1312 1312 1421 1324 1324 1434 1325 1325 1435 1312 1312 1421 1325 1325 1435 1313 1313 1422 1313 1313 1422 1325 1325 1435 1326 1326 1436 1313 1313 1422 1326 1326 1436 1314 1314 1423 1314 1314 1423 1326 1326 1436 1327 1327 1437 1314 1314 1423 1327 1327 1437 1315 1315 1424 1315 1315 1424 1327 1327 1437 1328 1328 1438 1315 1315 1424 1328 1328 1438 1316 1316 1425 1316 1316 1425 1328 1328 1438 1329 1329 1439 1316 1316 1425 1329 1329 1439 1317 1317 1426 1317 1317 1426 1329 1329 1439 1330 1330 1440 1317 1317 1426 1330 1330 1440 1318 1318 1427 1318 1318 1427 1330 1330 1440 1331 1331 1441 1318 1318 1427 1331 1331 1441 1319 1319 1428 1319 1319 1428 1331 1331 1441 1320 1320 1442 1319 1319 1428 1320 1320 1442 1308 1308 1429 1320 1320 1430 1332 1332 1443 1333 1333 1444 1320 1320 1430 1333 1333 1444 1321 1321 1431 1321 1321 1431 1333 1333 1444 1334 1334 1445 1321 1321 1431 1334 1334 1445 1322 1322 1432 1322 1322 1432 1334 1334 1445 1335 1335 1446 1322 1322 1432 1335 1335 1446 1323 1323 1433 1323 1323 1433 1335 1335 1446 1336 1336 1447 1323 1323 1433 1336 1336 1447 1324 1324 1434 1324 1324 1434 1336 1336 1447 1337 1337 1448 1324 1324 1434 1337 1337 1448 1325 1325 1435 1325 1325 1435 1337 1337 1448 1338 1338 1449 1325 1325 1435 1338 1338 1449 1326 1326 1436 1326 1326 1436 1338 1338 1449 1339 1339 1450 1326 1326 1436 1339 1339 1450 1327 1327 1437 1327 1327 1437 1339 1339 1450 1340 1340 1451 1327 1327 1437 1340 1340 1451 1328 1328 1438 1328 1328 1438 1340 1340 1451 1341 1341 1452 1328 1328 1438 1341 1341 1452 1329 1329 1439 1329 1329 1439 1341 1341 1452 1342 1342 1453 1329 1329 1439 1342 1342 1453 1330 1330 1440 1330 1330 1440 1342 1342 1453 1343 1343 1454 1330 1330 1440 1343 1343 1454 1331 1331 1441 1331 1331 1441 1343 1343 1454 1332 1332 1455 1331 1331 1441 1332 1332 1455 1320 1320 1442 1332 1332 1443 1344 1344 1456 1345 1345 1457 1332 1332 1443 1345 1345 1457 1333 1333 1444 1333 1333 1444 1345 1345 1457 1346 1346 1458 1333 1333 1444 1346 1346 1458 1334 1334 1445 1334 1334 1445 1346 1346 1458 1347 1347 1459 1334 1334 1445 1347 1347 1459 1335 1335 1446 1335 1335 1446 1347 1347 1459 1348 1348 1460 1335 1335 1446 1348 1348 1460 1336 1336 1447 1336 1336 1447 1348 1348 1460 1349 1349 1461 1336 1336 1447 1349 1349 1461 1337 1337 1448 1337 1337 1448 1349 1349 1461 1350 1350 1462 1337 1337 1448 1350 1350 1462 1338 1338 1449 1338 1338 1449 1350 1350 1462 1351 1351 1463 1338 1338 1449 1351 1351 1463 1339 1339 1450 1339 1339 1450 1351 1351 1463 1352 1352 1464 1339 1339 1450 1352 1352 1464 1340 1340 1451 1340 1340 1451 1352 1352 1464 1353 1353 1465 1340 1340 1451 1353 1353 1465 1341 1341 1452 1341 1341 1452 1353 1353 1465 1354 1354 1466 1341 1341 1452 1354 1354 1466 1342 1342 1453 1342 1342 1453 1354 1354 1466 1355 1355 1467 1342 1342 1453 1355 1355 1467 1343 1343 1454 1343 1343 1454 1355 1355 1467 1344 1344 1468 1343 1343 1454 1344 1344 1468 1332 1332 1455 1344 1344 1456 1356 1356 1469 1357 1357 1470 1344 1344 1456 1357 1357 1470 1345 1345 1457 1345 1345 1457 1357 1357 1470 1358 1358 1471 1345 1345 1457 1358 1358 1471 1346 1346 1458 1346 1346 1458 1358 1358 1471 1359 1359 1472 1346 1346 1458 1359 1359 1472 1347 1347 1459 1347 1347 1459 1359 1359 1472 1360 1360 1473 1347 1347 1459 1360 1360 1473 1348 1348 1460 1348 1348 1460 1360 1360 1473 1361 1361 1474 1348 1348 1460 1361 1361 1474 1349 1349 1461 1349 1349 1461 1361 1361 1474 1362 1362 1475 1349 1349 1461 1362 1362 1475 1350 1350 1462 1350 1350 1462 1362 1362 1475 1363 1363 1476 1350 1350 1462 1363 1363 1476 1351 1351 1463 1351 1351 1463 1363 1363 1476 1364 1364 1477 1351 1351 1463 1364 1364 1477 1352 1352 1464 1352 1352 1464 1364 1364 1477 1365 1365 1478 1352 1352 1464 1365 1365 1478 1353 1353 1465 1353 1353 1465 1365 1365 1478 1366 1366 1479 1353 1353 1465 1366 1366 1479 1354 1354 1466 1354 1354 1466 1366 1366 1479 1367 1367 1480 1354 1354 1466 1367 1367 1480 1355 1355 1467 1355 1355 1467 1367 1367 1480 1356 1356 1481 1355 1355 1467 1356 1356 1481 1344 1344 1468 1356 1356 1469 1368 1368 1482 1369 1369 1483 1356 1356 1469 1369 1369 1483 1357 1357 1470 1357 1357 1470 1369 1369 1483 1370 1370 1484 1357 1357 1470 1370 1370 1484 1358 1358 1471 1358 1358 1471 1370 1370 1484 1371 1371 1485 1358 1358 1471 1371 1371 1485 1359 1359 1472 1359 1359 1472 1371 1371 1485 1372 1372 1486 1359 1359 1472 1372 1372 1486 1360 1360 1473 1360 1360 1473 1372 1372 1486 1373 1373 1487 1360 1360 1473 1373 1373 1487 1361 1361 1474 1361 1361 1474 1373 1373 1487 1374 1374 1488 1361 1361 1474 1374 1374 1488 1362 1362 1475 1362 1362 1475 1374 1374 1488 1375 1375 1489 1362 1362 1475 1375 1375 1489 1363 1363 1476 1363 1363 1476 1375 1375 1489 1376 1376 1490 1363 1363 1476 1376 1376 1490 1364 1364 1477 1364 1364 1477 1376 1376 1490 1377 1377 1491 1364 1364 1477 1377 1377 1491 1365 1365 1478 1365 1365 1478 1377 1377 1491 1378 1378 1492 1365 1365 1478 1378 1378 1492 1366 1366 1479 1366 1366 1479 1378 1378 1492 1379 1379 1493 1366 1366 1479 1379 1379 1493 1367 1367 1480 1367 1367 1480 1379 1379 1493 1368 1368 1494 1367 1367 1480 1368 1368 1494 1356 1356 1481 1368 1368 1482 1380 1380 1495 1381 1381 1496 1368 1368 1482 1381 1381 1496 1369 1369 1483 1369 1369 1483 1381 1381 1496 1382 1382 1497 1369 1369 1483 1382 1382 1497 1370 1370 1484 1370 1370 1484 1382 1382 1497 1383 1383 1498 1370 1370 1484 1383 1383 1498 1371 1371 1485 1371 1371 1485 1383 1383 1498 1384 1384 1499 1371 1371 1485 1384 1384 1499 1372 1372 1486 1372 1372 1486 1384 1384 1499 1385 1385 1500 1372 1372 1486 1385 1385 1500 1373 1373 1487 1373 1373 1487 1385 1385 1500 1386 1386 1501 1373 1373 1487 1386 1386 1501 1374 1374 1488 1374 1374 1488 1386 1386 1501 1387 1387 1502 1374 1374 1488 1387 1387 1502 1375 1375 1489 1375 1375 1489 1387 1387 1502 1388 1388 1503 1375 1375 1489 1388 1388 1503 1376 1376 1490 1376 1376 1490 1388 1388 1503 1389 1389 1504 1376 1376 1490 1389 1389 1504 1377 1377 1491 1377 1377 1491 1389 1389 1504 1390 1390 1505 1377 1377 1491 1390 1390 1505 1378 1378 1492 1378 1378 1492 1390 1390 1505 1391 1391 1506 1378 1378 1492 1391 1391 1506 1379 1379 1493 1379 1379 1493 1391 1391 1506 1380 1380 1507 1379 1379 1493 1380 1380 1507 1368 1368 1494 1380 1380 1495 1392 1392 1508 1393 1393 1509 1380 1380 1495 1393 1393 1509 1381 1381 1496 1381 1381 1496 1393 1393 1509 1394 1394 1510 1381 1381 1496 1394 1394 1510 1382 1382 1497 1382 1382 1497 1394 1394 1510 1395 1395 1511 1382 1382 1497 1395 1395 1511 1383 1383 1498 1383 1383 1498 1395 1395 1511 1396 1396 1512 1383 1383 1498 1396 1396 1512 1384 1384 1499 1384 1384 1499 1396 1396 1512 1397 1397 1513 1384 1384 1499 1397 1397 1513 1385 1385 1500 1385 1385 1500 1397 1397 1513 1398 1398 1514 1385 1385 1500 1398 1398 1514 1386 1386 1501 1386 1386 1501 1398 1398 1514 1399 1399 1515 1386 1386 1501 1399 1399 1515 1387 1387 1502 1387 1387 1502 1399 1399 1515 1400 1400 1516 1387 1387 1502 1400 1400 1516 1388 1388 1503 1388 1388 1503 1400 1400 1516 1401 1401 1517 1388 1388 1503 1401 1401 1517 1389 1389 1504 1389 1389 1504 1401 1401 1517 1402 1402 1518 1389 1389 1504 1402 1402 1518 1390 1390 1505 1390 1390 1505 1402 1402 1518 1403 1403 1519 1390 1390 1505 1403 1403 1519 1391 1391 1506 1391 1391 1506 1403 1403 1519 1392 1392 1520 1391 1391 1506 1392 1392 1520 1380 1380 1507 1392 1392 1508 1404 1404 1521 1405 1405 1522 1392 1392 1508 1405 1405 1522 1393 1393 1509 1393 1393 1509 1405 1405 1522 1406 1406 1523 1393 1393 1509 1406 1406 1523 1394 1394 1510 1394 1394 1510 1406 1406 1523 1407 1407 1524 1394 1394 1510 1407 1407 1524 1395 1395 1511 1395 1395 1511 1407 1407 1524 1408 1408 1525 1395 1395 1511 1408 1408 1525 1396 1396 1512 1396 1396 1512 1408 1408 1525 1409 1409 1526 1396 1396 1512 1409 1409 1526 1397 1397 1513 1397 1397 1513 1409 1409 1526 1410 1410 1527 1397 1397 1513 1410 1410 1527 1398 1398 1514 1398 1398 1514 1410 1410 1527 1411 1411 1528 1398 1398 1514 1411 1411 1528 1399 1399 1515 1399 1399 1515 1411 1411 1528 1412 1412 1529 1399 1399 1515 1412 1412 1529 1400 1400 1516 1400 1400 1516 1412 1412 1529 1413 1413 1530 1400 1400 1516 1413 1413 1530 1401 1401 1517 1401 1401 1517 1413 1413 1530 1414 1414 1531 1401 1401 1517 1414 1414 1531 1402 1402 1518 1402 1402 1518 1414 1414 1531 1415 1415 1532 1402 1402 1518 1415 1415 1532 1403 1403 1519 1403 1403 1519 1415 1415 1532 1404 1404 1533 1403 1403 1519 1404 1404 1533 1392 1392 1520 1404 1404 1521 1416 1416 1534 1417 1417 1535 1404 1404 1521 1417 1417 1535 1405 1405 1522 1405 1405 1522 1417 1417 1535 1418 1418 1536 1405 1405 1522 1418 1418 1536 1406 1406 1523 1406 1406 1523 1418 1418 1536 1419 1419 1537 1406 1406 1523 1419 1419 1537 1407 1407 1524 1407 1407 1524 1419 1419 1537 1420 1420 1538 1407 1407 1524 1420 1420 1538 1408 1408 1525 1408 1408 1525 1420 1420 1538 1421 1421 1539 1408 1408 1525 1421 1421 1539 1409 1409 1526 1409 1409 1526 1421 1421 1539 1422 1422 1540 1409 1409 1526 1422 1422 1540 1410 1410 1527 1410 1410 1527 1422 1422 1540 1423 1423 1541 1410 1410 1527 1423 1423 1541 1411 1411 1528 1411 1411 1528 1423 1423 1541 1424 1424 1542 1411 1411 1528 1424 1424 1542 1412 1412 1529 1412 1412 1529 1424 1424 1542 1425 1425 1543 1412 1412 1529 1425 1425 1543 1413 1413 1530 1413 1413 1530 1425 1425 1543 1426 1426 1544 1413 1413 1530 1426 1426 1544 1414 1414 1531 1414 1414 1531 1426 1426 1544 1427 1427 1545 1414 1414 1531 1427 1427 1545 1415 1415 1532 1415 1415 1532 1427 1427 1545 1416 1416 1546 1415 1415 1532 1416 1416 1546 1404 1404 1533 1416 1416 1534 1428 1428 1547 1429 1429 1548 1416 1416 1534 1429 1429 1548 1417 1417 1535 1417 1417 1535 1429 1429 1548 1430 1430 1549 1417 1417 1535 1430 1430 1549 1418 1418 1536 1418 1418 1536 1430 1430 1549 1431 1431 1550 1418 1418 1536 1431 1431 1550 1419 1419 1537 1419 1419 1537 1431 1431 1550 1432 1432 1551 1419 1419 1537 1432 1432 1551 1420 1420 1538 1420 1420 1538 1432 1432 1551 1433 1433 1552 1420 1420 1538 1433 1433 1552 1421 1421 1539 1421 1421 1539 1433 1433 1552 1434 1434 1553 1421 1421 1539 1434 1434 1553 1422 1422 1540 1422 1422 1540 1434 1434 1553 1435 1435 1554 1422 1422 1540 1435 1435 1554 1423 1423 1541 1423 1423 1541 1435 1435 1554 1436 1436 1555 1423 1423 1541 1436 1436 1555 1424 1424 1542 1424 1424 1542 1436 1436 1555 1437 1437 1556 1424 1424 1542 1437 1437 1556 1425 1425 1543 1425 1425 1543 1437 1437 1556 1438 1438 1557 1425 1425 1543 1438 1438 1557 1426 1426 1544 1426 1426 1544 1438 1438 1557 1439 1439 1558 1426 1426 1544 1439 1439 1558 1427 1427 1545 1427 1427 1545 1439 1439 1558 1428 1428 1559 1427 1427 1545 1428 1428 1559 1416 1416 1546 1428 1428 1547 0 0 1560 1 3 1561 1428 1428 1547 1 3 1561 1429 1429 1548 1429 1429 1548 1 3 1561 2 5 1562 1429 1429 1548 2 5 1562 1430 1430 1549 1430 1430 1549 2 5 1562 3 7 1563 1430 1430 1549 3 7 1563 1431 1431 1550 1431 1431 1550 3 7 1563 4 9 1564 1431 1431 1550 4 9 1564 1432 1432 1551 1432 1432 1551 4 9 1564 5 11 1565 1432 1432 1551 5 11 1565 1433 1433 1552 1433 1433 1552 5 11 1565 6 13 1566 1433 1433 1552 6 13 1566 1434 1434 1553 1434 1434 1553 6 13 1566 7 15 1567 1434 1434 1553 7 15 1567 1435 1435 1554 1435 1435 1554 7 15 1567 8 17 1568 1435 1435 1554 8 17 1568 1436 1436 1555 1436 1436 1555 8 17 1568 9 19 1569 1436 1436 1555 9 19 1569 1437 1437 1556 1437 1437 1556 9 19 1569 10 21 1570 1437 1437 1556 10 21 1570 1438 1438 1557 1438 1438 1557 10 21 1570 11 23 1571 1438 1438 1557 11 23 1571 1439 1439 1558 1439 1439 1558 11 23 1571 0 0 1572 1439 1439 1558 0 0 1572 1428 1428 1559</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-1_max" name="Torus_Knot-1_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-1_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-2.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-2.DAE
new file mode 100644
index 00000000..85627388
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-2.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-2.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:02:11Z</created>
+ <modified>2008-10-31T16:02:12Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="4320">25.477133 -0.002018 19.977411 28.316290 -4.371233 23.556599 29.657873 -7.569179 26.913568 29.142408 -8.738970 29.148823 26.908012 -7.567160 29.663429 23.553392 -4.367737 28.319496 19.977413 0.002017 25.477135 17.138256 4.371231 21.897947 15.796671 7.569177 18.540979 16.312134 8.738970 16.305723 18.546528 7.567163 15.791115 21.901148 4.367742 17.135044 26.968250 2.319252 21.315863 30.205357 -1.341455 25.326075 31.868971 -3.957439 29.025393 31.513329 -4.827750 31.422590 29.233727 -3.719189 31.875340 25.640980 -0.928794 30.262327 21.697763 2.795751 27.015759 18.460657 6.456457 23.005547 16.797043 9.072441 19.306231 17.152681 9.942754 16.909031 19.432281 8.834195 16.456280 23.025028 6.043802 18.069290 28.357008 4.988758 22.206573 32.092251 2.284904 26.530756 34.158497 0.441848 30.484200 34.002094 -0.046562 33.007584 31.664957 0.950540 33.424770 27.773314 3.165983 31.623974 23.369930 6.006141 28.087717 19.634687 8.709995 23.763535 17.568439 10.553051 19.810091 17.724838 11.041462 17.286705 20.061975 10.044362 16.869516 23.953617 7.828919 18.670311 29.557436 8.030107 22.505615 33.846058 6.521844 26.898144 36.363289 5.637204 30.920197 36.434643 5.613225 33.494064 34.040997 6.456332 33.930088 29.823732 7.940616 32.111435 24.912857 9.668364 28.525408 20.624237 11.176626 24.132881 18.107004 12.061267 20.110828 18.035648 12.085247 17.536957 20.429289 11.242140 17.100929 24.646553 9.757856 18.919582 30.463106 11.442386 22.055658 35.264442 11.264678 26.163822 38.208237 11.448579 29.984324 38.505699 11.944813 32.493458 36.077129 12.620415 33.018902 31.573261 13.294355 31.419868 26.200899 13.786056 28.124817 21.399565 13.963763 24.016651 18.455770 13.779863 20.196152 18.158302 13.283628 17.687019 20.586870 12.608027 17.161572 25.090738 11.934086 18.760603 30.945921 15.192908 20.691792 36.118904 16.296526 24.153536 39.385708 17.520578 27.489048 39.870991 18.537088 29.804581 37.444721 19.073679 30.479687 32.757019 18.986570 29.333475 27.063950 18.299107 26.673069 21.890965 17.195492 23.211327 18.624163 15.971437 19.875816 18.138878 14.954928 17.560282 20.565144 14.418338 16.885174 25.252844 14.505445 18.031384 30.853916 19.195019 18.257629 36.213638 21.363714 20.813316 39.662113 23.469360 23.453434 40.275326 24.947754 25.470564 37.888962 25.402756 26.324217 33.142448 24.712450 25.785658 27.307611 23.061806 23.999193 21.947889 20.893110 21.443504 18.499413 18.787464 18.803389 17.886200 17.309072 16.786259 20.272560 16.854069 15.932604 25.019070 17.544373 16.471161 30.025459 23.272793 14.656176 35.404984 26.218857 16.186813 38.903805 28.988106 18.026773 39.584419 30.838524 19.683031 37.264458 31.274290 20.711803 32.565552 30.178640 20.837423 26.746771 27.845156 20.026237 21.367249 24.899092 18.495598 17.868425 22.129843 16.655640 17.187807 20.279425 14.999380 19.507765 19.843658 13.970611 24.206669 20.939304 13.844987 28.329855 27.153845 9.921474 33.603813 30.604673 10.409883 37.051445 33.826748 11.423808 37.748959 35.956707 12.691568 35.509453 36.423840 13.873468 30.933006 35.102974 14.652819 25.245872 32.348030 14.820794 19.971912 28.897203 14.332385 16.524282 25.675133 13.318460 15.826767 23.545170 12.050700 18.066269 23.078037 10.868800 22.642714 24.398901 10.089449 25.722780 30.503351 4.276375 30.798662 34.234432 3.751136 34.117779 37.733009 3.949566 34.790779 40.061638 4.818495 32.637329 40.596363 6.125095 28.234447 39.193913 7.519262 22.761883 36.230064 8.627432 17.686001 32.498985 9.152671 14.366883 29.000408 8.954241 13.693882 26.671778 8.085312 15.847328 26.137049 6.778713 20.250208 27.539499 5.384546 22.288839 32.998806 -1.866579 27.088953 36.828255 -3.368448 30.212879 40.458393 -3.967744 30.823563 42.916519 -3.503887 28.757372 43.543980 -2.101167 24.567942 42.172653 -0.135441 19.377827 39.169983 1.866575 14.577712 35.340527 3.368444 11.453787 31.710394 3.967741 10.843101 29.252268 3.503885 12.909289 28.624804 2.101165 17.098717 29.996130 0.135440 18.247540 34.415554 -7.972891 22.692532 38.184559 -10.421992 25.551991 41.817783 -11.807312 26.059731 44.341709 -11.757656 24.079699 45.080055 -10.286328 20.142448 43.834984 -7.787571 15.302959 40.940105 -4.930924 10.857970 37.171104 -2.481823 7.998509 33.537880 -1.096502 7.490769 31.013950 -1.146158 9.470797 30.275600 -2.617484 13.408045 31.520672 -5.116240 13.912412 34.689453 -13.506830 17.909201 38.239796 -16.880577 20.422070 41.745834 -19.046024 20.777697 44.268120 -19.422939 18.880791 45.130817 -17.910330 15.239630 44.102764 -14.913500 10.829858 41.459431 -11.235446 6.833069 37.909088 -7.861699 4.320200 34.403049 -5.696253 3.964571 31.880760 -5.319335 5.861473 31.018061 -6.831942 9.502633 32.046112 -9.828772 9.619333 33.927425 -18.054348 13.056349 37.081493 -22.320517 15.122888 40.310879 -25.252483 15.265223 42.750271 -26.064631 13.445214 43.746037 -24.539345 10.150535 43.031361 -21.085323 6.263989 40.797741 -16.628069 2.826974 37.643677 -12.361901 0.760435 34.414291 -9.429932 0.618098 31.974897 -8.617785 2.438104 30.979130 -10.143068 5.732782 31.693802 -13.597088 5.654198 32.364838 -21.399857 8.410243 34.916275 -26.484715 9.919551 37.690811 -30.134356 9.777703 39.945015 -31.370861 8.022710 41.074863 -29.862911 5.124819 40.777618 -26.014559 1.860519 39.132935 -20.856968 -0.895526 36.581497 -15.772109 -2.404834 33.806961 -12.122467 -2.262989 31.552761 -10.885958 -0.507997 30.422913 -12.393908 2.389893 30.720150 -16.242258 2.200311 30.288651 -23.539001 4.172174 32.018063 -29.290724 5.026107 34.142418 -33.539711 4.533297 36.092499 -35.147442 2.825794 37.345779 -33.683136 0.361121 37.566444 -29.539146 -2.200314 36.695374 -23.825855 -4.172177 34.965961 -18.074135 -5.026110 32.841610 -13.825150 -4.533301 30.891529 -12.217415 -2.825799 29.638245 -13.681719 -0.361127 29.417578 -17.825705 -0.681908 27.952492 -24.628099 0.465314 28.682333 -30.801643 0.619227 29.991213 -35.444820 -0.261411 31.528425 -37.313492 -1.940632 32.882065 -35.906956 -3.968492 33.689434 -31.602087 -5.801626 33.734192 -25.552376 -6.948848 33.004353 -19.378834 -7.102761 31.695469 -14.735658 -6.222126 30.158262 -12.866980 -4.542905 28.804619 -14.273516 -2.515045 27.997252 -18.578381 -3.035895 25.517643 -24.889339 -2.664178 25.182703 -31.191010 -3.173943 25.605589 -35.971939 -4.428598 26.672989 -37.951073 -6.091959 28.098890 -36.598110 -7.718331 29.501230 -32.275574 -8.871928 30.504248 -26.141687 -9.243646 30.839184 -19.840017 -8.733881 30.416298 -15.059092 -7.479227 29.348902 -13.079952 -5.815866 27.922998 -14.432911 -4.189494 26.520660 -18.755444 -4.952910 23.055527 -24.519640 -5.244713 21.723440 -30.692307 -6.320560 21.308731 -35.379154 -7.892178 21.922523 -37.324341 -9.538454 23.400349 -36.006660 -10.818269 25.346228 -31.779179 -11.388699 27.238762 -25.774652 -11.096895 28.570848 -19.601988 -10.021049 28.985558 -14.915142 -8.449431 28.371767 -12.969952 -6.803156 26.893942 -14.287631 -5.523340 24.948065 -18.515106 -6.518570 20.597672 -23.655235 -7.345964 18.422583 -29.532806 -8.871548 17.300312 -33.972294 -10.686543 17.531570 -35.784142 -12.304621 19.054392 -34.482864 -13.292221 21.460739 -30.417145 -13.384716 24.105831 -24.676384 -12.557323 26.280918 -18.798817 -11.031739 27.403191 -14.359328 -9.216745 27.171934 -12.547478 -7.598667 25.649113 -13.848751 -6.611066 23.242767 -17.914469 -7.793983 18.176619 -22.390102 -9.042483 15.329926 -27.894556 -10.912934 13.649472 -32.014439 -12.904151 13.585536 -33.645836 -14.482589 15.155248 -32.351608 -15.225305 17.938004 -28.478548 -14.933291 21.188168 -23.064442 -13.684792 24.034861 -17.559990 -11.814341 25.715315 -13.440105 -9.823125 25.779253 -11.808710 -8.244687 24.209543 -13.102933 -7.501969 21.426788 -16.975988 -8.823277 15.829939 -20.797598 -10.388645 12.460699 -25.912210 -12.512224 10.352274 -29.699150 -14.625004 10.069614 -31.143707 -16.160866 11.688461 -29.858816 -16.708277 14.775043 -26.188761 -16.120560 18.502312 -21.116932 -14.555194 21.871552 -16.002319 -12.431616 23.979977 -12.215382 -10.318836 24.262638 -10.770822 -8.782974 22.643793 -12.055710 -8.235561 19.557215 -15.725762 -9.640692 13.593333 -18.942230 -11.419758 9.814666 -23.687544 -13.711881 7.374357 -27.164183 -15.902889 6.926284 -28.440580 -17.405704 8.590509 -27.174726 -17.817648 11.921103 -23.705811 -17.028339 16.025637 -18.963320 -15.249274 19.804304 -14.218005 -12.957152 22.244614 -10.741368 -10.766143 22.692688 -9.464968 -9.263328 21.028465 -10.730818 -8.851383 17.697872 -14.199734 -10.276514 11.489870 -16.882341 -12.166037 7.381869 -21.299969 -14.547107 4.673702 -24.508129 -16.781717 4.091023 -25.647198 -18.271109 5.789961 -24.411961 -18.616198 9.315283 -21.133402 -17.724518 13.722385 -16.690006 -15.834996 17.830387 -12.272377 -13.453927 20.538553 -9.064218 -11.219316 21.121235 -7.925148 -9.729924 19.422300 -9.160382 -9.384834 15.896979 -12.438939 -10.758936 9.528566 -14.669413 -12.659042 5.146857 -18.810867 -15.055119 2.210816 -21.799919 -17.305138 1.507154 -22.835653 -18.806211 3.224412 -21.640547 -19.156124 6.902456 -18.534826 -18.261122 11.555756 -14.350669 -16.361017 15.937464 -10.209215 -13.964941 18.873507 -7.220163 -11.714921 19.577171 -6.184426 -10.213848 17.859915 -7.379531 -9.863933 14.181873 -10.485250 -11.114755 7.705402 -12.345623 -12.932881 3.091652 -16.265972 -15.276747 -0.046241 -19.086590 -17.518316 -0.867481 -20.051685 -19.056959 0.847982 -18.902670 -19.480402 4.640491 -15.947417 -18.675180 9.493846 -11.977787 -16.857056 14.107595 -8.057437 -14.513191 17.245487 -5.236822 -12.271623 18.066730 -4.271722 -10.732978 16.351273 -5.420737 -10.309534 12.558764 -8.375987 -11.368921 6.006227 -9.946047 -13.026557 1.194614 -13.695988 -15.261241 -2.126122 -16.393181 -17.474192 -3.066193 -17.314915 -19.072449 -1.373706 -16.214214 -19.627764 2.497834 -13.386011 -18.991339 7.511055 -9.588119 -17.333704 12.322666 -5.838179 -15.099021 15.643402 -3.140986 -12.886071 16.583475 -2.219249 -11.287812 14.890993 -3.319947 -10.732496 11.019454 -6.148149 -11.542978 4.411149 -7.495147 -12.974364 -0.564006 -11.122872 -15.051477 -4.048648 -13.737985 -17.217756 -5.109073 -14.639767 -18.892750 -3.461138 -13.586588 -19.627644 0.453592 -10.860645 -19.225525 5.586168 -7.192354 -17.794140 10.561322 -3.564630 -15.717028 14.045965 -0.949516 -13.550748 15.106391 -0.047733 -11.875754 13.458460 -1.100910 -11.140860 9.543732 -3.826851 -11.654559 2.895715 -5.012090 -12.810739 -2.207637 -8.558985 -14.693115 -5.835466 -11.126370 -16.797308 -7.015697 -12.026316 -18.559502 -5.432087 -11.017683 -19.507515 -1.508968 -8.370735 -19.387333 3.702468 -4.794719 -18.231153 8.805820 -1.247824 -16.348778 12.433649 1.319561 -14.244584 13.613883 2.219509 -12.482391 12.030277 1.210878 -11.534376 8.107159 -1.436069 -11.716360 1.434428 -2.510548 -12.563766 -3.758718 -6.014052 -14.224574 -7.505396 -8.563578 -16.253771 -8.801683 -9.475980 -18.107635 -7.300242 -8.506782 -19.289425 -3.403385 -5.915680 -19.482481 1.844731 -2.396958 -18.635075 7.037878 1.106547 -16.974268 10.784555 3.656073 -14.945072 12.080845 4.568476 -13.091208 10.579407 3.599280 -11.909417 6.682552 1.008179 -11.736110 0.000248 -0.000379 -12.257125 -5.242002 -3.494484 -13.680559 -9.079659 -6.052253 -15.625006 -10.484423 -6.988334 -17.569450 -9.079888 -6.051903 -18.992880 -5.242403 -3.493879 -19.513891 -0.000215 0.000319 -18.992876 5.242034 3.494424 -17.569443 9.079690 6.052192 -15.624996 10.484457 6.988275 -13.680552 9.079926 6.051847 -12.257120 5.242443 3.493824 -11.716375 -1.433929 2.509698 -11.909535 -6.681782 -1.009414 -13.091398 -10.578572 -3.600586 -14.945284 -12.080157 -4.569518 -16.974445 -10.784189 -3.656583 -18.635170 -7.037922 -1.106404 -19.482470 -1.845165 2.397702 -19.289310 3.402687 5.916813 -18.107449 7.299478 8.507986 -16.253563 8.801065 9.476919 -14.224401 7.505100 8.563987 -12.563676 3.758836 6.013809 -11.654572 -2.895365 5.011216 -11.534764 -8.106243 1.434372 -12.483052 -12.029041 -1.212959 -14.245341 -13.612646 -2.221427 -16.349428 -12.432734 -1.320815 -18.231525 -8.805461 1.247559 -19.387325 -3.702752 4.795502 -19.507132 1.508126 8.372345 -18.558846 5.430923 11.019676 -16.796556 7.014531 12.028147 -14.692471 5.834621 11.127536 -12.810373 2.207350 8.559163 -11.542967 -4.410938 7.494033 -11.141715 -9.542624 3.824398 -11.877248 -13.456747 1.097756 -13.552481 -15.104524 0.044710 -15.718536 -14.044432 0.947423 -17.795021 -10.560524 3.564011 -19.225544 -5.586309 7.193363 -19.626797 -0.454625 10.862997 -18.891264 3.459500 13.589640 -17.216032 5.107278 14.642687 -15.049977 4.047189 13.739977 -12.973492 0.563283 11.123390 -11.368857 -6.006216 9.944656 -10.733959 -11.018240 6.144928 -11.290411 -14.888899 3.315737 -12.889111 -16.581051 2.215164 -15.101687 -15.641285 3.138106 -17.335285 -12.321413 5.837260 -18.991409 -7.510991 9.589393 -19.626308 -2.498967 13.389120 -19.069857 1.371691 16.218311 -17.471159 3.063845 17.318886 -15.258583 2.124082 16.395947 -13.024985 -1.195787 13.696793 -11.114578 -7.705835 12.344072 -10.311825 -12.557673 8.372086 -10.737122 -16.348944 5.415510 -12.276513 -18.063780 4.266559 -14.517519 -17.242695 5.233093 -16.859665 -14.105694 8.056129 -18.675373 -9.493336 11.979235 -19.478127 -4.641499 15.951221 -19.052830 -0.850228 18.907797 -17.513439 0.864611 20.056749 -15.272435 0.043527 19.090218 -12.930289 -3.093471 16.267185 -10.758725 -9.528978 14.667030 -9.867362 -14.180251 10.479840 -10.220000 -17.856689 7.372526 -11.722152 -19.573195 6.177691 -13.971314 -18.869829 7.215489 -16.364828 -15.935063 10.207844 -18.261351 -11.555263 14.352954 -19.152714 -6.903991 18.540142 -18.800077 -3.227554 21.647457 -17.297928 -1.511046 22.842295 -15.048765 -2.214408 21.804497 -12.655252 -5.149172 18.812147 -10.276311 -11.490316 16.879604 -9.389086 -15.895103 12.433022 -9.737492 -19.418598 9.152847 -11.228175 -21.116688 7.918005 -13.461709 -20.534367 9.059368 -15.839619 -17.827669 12.271111 -17.724745 -13.721852 16.692646 -18.611971 -9.317067 21.139229 -18.263565 -5.793571 24.419401 -16.772882 -4.095481 25.654245 -14.539351 -4.677800 24.512884 -12.161441 -7.384494 21.301146 -9.640656 -13.593473 18.939089 -8.856450 -17.695282 14.193394 -9.272142 -21.023830 10.722960 -10.776349 -22.687237 9.457684 -12.966019 -22.239792 10.736599 -15.254430 -19.801392 14.217018 -17.028406 -16.025400 18.966366 -17.812613 -11.923594 23.712061 -17.396919 -8.595046 27.182495 -15.892714 -6.931639 28.447773 -13.703046 -7.379080 27.168861 -11.414634 -9.817478 23.688444 -8.823529 -15.829748 20.793516 -8.242869 -19.553055 15.717962 -8.795385 -22.636770 12.046265 -10.333032 -24.254620 10.762252 -12.443797 -23.973097 12.209972 -14.562102 -21.867640 16.001513 -16.120350 -18.502403 21.120930 -16.701010 -14.779097 26.196484 -16.148495 -11.695381 29.868179 -14.610850 -10.077530 31.152197 -12.500086 -10.359051 29.704479 -10.381780 -12.464506 25.912941 -7.795019 -18.175175 22.385628 -7.510939 -21.420115 16.967964 -8.259194 -24.199421 13.093494 -9.839290 -25.768379 11.800377 -11.827840 -25.706585 13.435102 -13.692014 -24.030602 17.559650 -14.932308 -21.189505 23.068844 -15.216389 -17.944565 28.486509 -14.468134 -15.165258 32.360977 -12.888040 -13.596300 33.654099 -10.899490 -13.658091 32.019375 -9.035316 -15.334072 27.894833 -6.520520 -20.595066 23.651096 -6.621703 -23.233715 17.907516 -7.615150 -25.636026 13.840834 -9.234668 -27.158302 12.540712 -11.046308 -27.392649 14.355518 -12.564642 -26.276278 18.798977 -13.382834 -24.108316 24.680464 -13.281651 -21.469666 30.424044 -12.288205 -19.067356 34.490726 -10.668689 -17.545078 35.790852 -8.857049 -17.310730 33.976048 -7.338714 -18.427101 29.532593 -4.956114 -23.051601 24.516304 -5.536617 -24.936043 18.510199 -6.822959 -26.877031 14.282452 -8.470469 -28.354477 12.965888 -10.037695 -28.972504 14.913276 -11.104702 -28.565510 19.602818 -11.385585 -27.242548 25.777950 -10.805083 -25.358110 31.784058 -9.518741 -23.417122 36.011803 -7.871233 -21.939674 37.328373 -6.304006 -21.321648 35.380985 -5.236999 -21.728642 30.691448 -3.040195 -25.512951 24.888014 -4.203731 -26.507599 18.754639 -5.836244 -27.905046 14.432835 -7.500301 -29.330853 13.080624 -8.750021 -30.402969 15.060333 -9.250542 -30.834127 19.841496 -8.867749 -30.508797 26.143007 -7.704213 -29.514151 32.276379 -6.071701 -28.116701 36.598183 -4.407643 -26.690897 37.950397 -3.157924 -25.618778 35.970692 -2.657402 -25.187620 31.189531 -0.686827 -27.948034 24.628767 -2.530377 -27.984747 18.582163 -4.564564 -28.787399 14.279398 -6.244329 -30.140921 12.873394 -7.119580 -31.682636 14.740888 -6.955795 -32.999443 19.381483 -5.796861 -33.738506 25.551741 -3.953311 -33.701794 31.598341 -1.919125 -32.899143 35.901108 -0.239359 -31.545624 37.307114 0.635893 -30.003910 35.439625 0.472109 -28.687099 30.799030 2.195147 -30.285002 23.541412 -0.377654 -29.406700 17.834337 -2.849289 -29.623037 13.694269 -4.557485 -30.876045 12.230534 -5.044532 -32.829979 13.835341 -4.179927 -34.961285 18.078678 -2.195339 -36.698887 23.823553 0.377462 -37.577187 29.530628 2.849097 -37.360847 33.670696 4.557293 -36.107845 35.134434 5.044341 -34.153908 33.529629 4.179738 -32.022602 29.286293 5.649614 -32.362553 21.403332 2.374993 -30.713007 16.253839 -0.529256 -30.412807 12.410510 -2.284940 -31.542391 10.903162 -2.421623 -33.799088 12.135689 -0.902686 -36.578217 15.777834 1.864877 -39.135113 20.853687 5.139498 -40.784660 26.003178 8.043746 -41.084858 29.846508 9.799431 -39.955273 31.353857 9.936116 -37.698582 30.121334 8.417180 -34.919456 26.479191 9.615621 -33.926392 18.058086 5.720701 -31.690481 13.609297 2.420851 -30.974394 10.160503 0.600265 -31.970011 8.635809 0.746766 -34.410553 9.443754 2.821098 -37.642082 12.367848 6.267447 -40.798706 16.624584 10.162367 -43.034618 21.073372 13.462215 -43.750702 24.522163 15.282804 -42.755089 26.046860 15.136305 -40.314545 25.238918 13.061975 -37.083023 22.314825 13.909377 -34.689327 13.510557 9.492887 -32.045708 9.840773 5.847585 -31.017483 6.849037 3.950227 -31.880163 5.336987 4.309208 -34.402588 5.709774 6.828338 -37.908886 7.867509 10.832621 -41.459538 11.232029 15.249109 -44.103153 14.901814 18.894411 -45.131382 17.893549 20.791771 -44.268707 19.405602 20.432793 -41.746277 19.032814 17.913664 -38.239983 16.875082 18.245218 -34.416096 7.976294 13.399714 -31.522604 5.128447 9.458646 -30.278412 2.635272 7.478020 -31.016895 1.164816 7.988544 -33.540180 1.111085 10.853419 -37.172150 2.488475 15.305009 -40.939625 4.927917 20.150513 -43.833115 7.775764 24.091579 -45.077309 10.268938 26.072206 -44.338829 11.739395 25.561687 -41.815544 11.793128 22.696814 -38.183578 10.415739 22.286991 -32.999863 1.869779 17.091703 -30.000185 -0.123289 12.898947 -28.630783 -2.083262 10.832171 -29.258589 -3.484967 11.445166 -31.715382 -3.952817 14.573678 -35.342865 -3.361453 19.379427 -39.169060 -1.869331 24.574715 -42.168739 0.123737 28.767469 -43.538139 2.083710 30.834248 -42.910336 3.485414 30.221256 -40.453545 3.953265 27.092747 -36.826057 3.361903 25.721077 -30.505180 -4.272814 20.244301 -27.545837 -5.372193 15.838768 -26.146219 -6.760825 13.684937 -26.681358 -8.066626 14.359924 -29.007858 -8.939707 17.682865 -32.502338 -9.146128 22.763384 -36.228451 -8.630578 28.240158 -39.187798 -7.531199 32.645691 -40.587414 -6.142567 34.799526 -40.052280 -4.836766 34.124542 -37.725784 -3.963684 30.801601 -34.231304 -3.757263 28.328547 -27.156366 -9.917988 22.638056 -24.407833 -10.077043 18.059484 -23.091019 -10.850748 15.819655 -23.558758 -12.031791 16.518730 -25.685726 -13.303711 19.969391 -28.902000 -14.325700 25.247036 -32.345783 -14.823915 30.937525 -35.094318 -14.664861 35.516098 -36.411133 -13.891157 37.755928 -35.943394 -12.710114 37.056858 -33.816425 -11.438192 33.606201 -30.600157 -10.416204 30.024780 -23.275375 -14.653544 24.203722 -20.950659 -13.833543 19.503323 -19.860779 -13.953369 17.183050 -20.297768 -14.980917 17.864620 -22.144535 -16.640854 21.365404 -24.906240 -18.488403 26.747370 -27.842888 -20.028515 32.568428 -30.167604 -20.848518 37.268826 -31.257484 -20.728691 39.589100 -30.820496 -19.701145 38.907536 -28.973730 -18.041208 35.406754 -26.212025 -16.193657 30.853533 -19.199026 -18.254688 25.017843 -17.560530 -16.459841 20.270807 -16.878090 -15.915896 17.884390 -17.334562 -16.768610 18.498028 -18.807640 -18.789495 21.947298 -20.902607 -21.437056 27.307972 -23.058125 -24.001883 33.143658 -24.696621 -25.796734 37.890697 -25.379063 -26.340675 40.277115 -24.922590 -25.487965 39.663483 -23.449514 -23.467081 36.214214 -21.354546 -20.819519 30.945978 -15.197793 -20.689295 25.253965 -14.525350 -18.022793 20.567026 -14.447972 -16.872766 18.141022 -14.986396 -17.547363 18.625998 -15.996349 -19.865826 21.892004 -17.207216 -23.206924 27.063919 -18.294548 -26.675415 32.755932 -18.966991 -29.341917 37.442871 -19.044369 -30.491945 39.868877 -18.505947 -29.817348 39.383904 -17.495993 -27.498888 36.117901 -16.285126 -24.157791 30.463511 -11.447270 -22.054062 25.094158 -11.955453 -18.756603 20.592394 -12.640194 -17.156227 18.164463 -13.318016 -17.681755 18.460924 -13.807299 -20.192373 21.402342 -13.976939 -24.015358 26.200567 -13.781482 -28.126348 31.569916 -13.273299 -31.423807 36.071682 -12.588559 -33.024185 38.499615 -11.910737 -32.498661 38.203156 -11.421454 -29.988045 35.261742 -11.251813 -26.165060 29.557907 -8.035209 -22.504601 24.650877 -9.778354 -18.920759 20.436314 -11.272580 -17.103975 18.043507 -12.117512 -17.541061 18.113605 -12.086750 -20.114895 20.627829 -11.188539 -24.135818 24.912489 -9.663552 -28.526434 29.819519 -7.920409 -32.110279 34.034081 -6.426183 -33.927059 36.426891 -5.581250 -33.489975 36.356792 -5.612010 -30.916147 33.842575 -6.510220 -26.895222 28.357347 -4.992801 -22.206160 23.957401 -7.844313 -18.674759 20.068201 -10.067019 -16.877636 17.731855 -11.065349 -17.296328 17.574385 -10.571799 -19.818649 19.637983 -8.718617 -23.768740 23.369711 -6.002361 -28.088181 27.769653 -3.150850 -31.619579 31.658854 -0.928142 -33.416702 33.995201 0.070188 -32.998016 34.152676 -0.423360 -30.475698 32.089077 -2.276541 -26.525608 26.968445 -2.323997 -21.315649 23.027637 -6.057745 -18.076731 19.436621 -8.853638 -16.469393 17.157606 -9.962516 -16.924316 16.801252 -9.087259 -19.319607 18.463043 -6.462391 -23.013447 21.697704 -2.791242 -27.016075 25.638510 0.942505 -30.254992 29.229525 3.738397 -31.862333 31.508541 4.847278 -31.407412 31.864897 3.972022 -29.012123 30.203110 1.347156 -25.318285 25.477198 -0.002317 -19.977478 21.902439 -4.378234 -17.143072 18.548712 -7.581036 -15.804968 16.314646 -8.752532 -16.321709 15.798856 -7.578823 -18.554834 17.139549 -4.374403 -21.905979 19.977486 0.002106 -25.477207 23.552244 4.378023 -28.311611 26.905972 7.580825 -29.649717 29.140039 8.752324 -29.132978 29.655830 7.578617 -26.899855 28.315140 4.374199 -23.548712 23.948034 2.016864 -18.314423 20.651194 -2.805273 -15.897968 17.475233 -6.281468 -14.837171 15.271152 -7.480281 -15.416269 14.629532 -6.080487 -17.480097 15.722293 -2.457164 -20.475651 18.256630 2.418823 -23.600273 21.553471 7.240959 -26.016729 24.729429 10.717155 -27.077528 26.933512 11.915969 -26.498432 27.575134 10.516178 -24.434607 26.482376 6.892858 -21.439053 22.424330 3.790823 -16.422068 19.348829 -1.338436 -14.374284 16.311884 -4.998895 -13.553329 14.127242 -6.209732 -14.179176 13.380275 -4.646509 -16.084131 14.271132 -0.728090 -18.757761 16.561110 4.495589 -21.483671 19.636608 9.624848 -23.531456 22.673553 13.285305 -24.352409 24.858196 14.496146 -23.726564 25.605164 12.932926 -21.821609 24.714310 9.014510 -19.147980 20.931297 5.373355 -14.369696 18.054907 0.025251 -12.613113 15.141712 -3.769707 -11.974726 12.972302 -4.994664 -12.625587 12.127970 -3.321393 -14.391302 12.834950 0.801753 -16.798746 14.903811 6.269980 -19.202848 17.780201 11.618084 -20.959429 20.693396 15.413042 -21.597820 22.862806 16.638000 -20.946957 23.707140 14.964733 -19.181244 23.000160 10.841590 -16.773802 19.479393 6.811598 -12.204982 16.808838 1.295393 -10.655456 14.024679 -2.613246 -10.138788 11.872929 -3.867004 -10.793421 10.930147 -2.129933 -12.443946 11.448952 2.132515 -14.648105 13.290328 7.778222 -16.815296 15.960882 13.294427 -18.364822 18.745041 17.203068 -18.881491 20.896791 18.456825 -18.226858 21.839575 16.719759 -16.576336 21.320772 12.457314 -14.372177 18.068127 8.140486 -9.960835 15.626744 2.484854 -8.541359 12.989304 -1.532348 -8.091979 10.862504 -2.834715 -8.733106 9.816220 -1.073278 -10.292950 10.130803 3.279984 -12.353551 11.721959 9.058621 -14.362774 14.163342 14.714251 -15.782248 16.800781 18.731453 -16.231630 18.927582 20.033825 -15.590504 19.973866 18.272390 -14.030662 19.659285 13.919129 -11.970060 16.689644 9.384820 -7.660404 14.507235 3.608388 -6.307136 12.039739 -0.517848 -5.880986 9.948323 -1.888264 -6.496142 8.793379 -0.135659 -7.987772 8.884372 4.270357 -9.956196 10.196922 10.149195 -11.873974 12.379331 15.925627 -13.227242 14.846826 20.051865 -13.653391 16.938242 21.422281 -13.038237 18.093187 19.669680 -11.546608 18.002195 15.263668 -9.578185 15.330580 10.564998 -5.317975 13.437894 4.684338 -3.977453 11.165594 0.448735 -3.538955 9.122540 -1.006881 -4.119979 7.856168 0.707517 -5.564838 7.705800 5.132558 -7.486384 8.711727 11.082557 -9.369740 10.604412 16.963215 -10.710262 12.876711 21.198818 -11.148760 14.919765 22.654438 -10.567738 16.186138 20.940044 -9.122879 16.336508 16.515003 -7.201334 13.975917 11.691404 -2.945121 12.397509 5.724428 -1.579381 10.342183 1.383238 -1.104339 8.360665 -0.168947 -1.647283 6.983901 1.483781 -3.062731 6.580791 5.898571 -4.971414 7.259351 11.892485 -6.861903 8.837759 17.859459 -8.227643 10.893083 22.200649 -8.702685 12.874600 23.752838 -8.159743 14.251366 22.100115 -6.744297 14.654476 17.685328 -4.835613 12.609100 12.772562 -0.549004 11.360732 6.740455 0.871098 9.538674 2.302434 1.400279 7.631146 0.647666 0.896744 6.149266 2.219540 -0.504586 5.490105 6.596875 -2.428223 5.830282 12.606769 -4.358732 7.078649 18.638874 -5.778834 8.900706 23.076895 -6.308015 10.808234 24.731667 -5.804482 12.290114 23.159796 -4.403153 12.949278 18.782461 -2.479516 11.211440 13.814508 1.868328 10.298053 7.741040 3.365033 8.718685 3.219148 3.960043 6.896526 1.460470 3.493925 5.319822 2.936242 2.091576 4.411051 7.251031 0.128754 4.413715 13.248693 -1.868605 5.327101 19.322161 -3.365309 6.906469 23.844053 -3.960320 8.728628 25.602734 -3.494203 10.305331 24.126966 -2.091855 11.214104 19.812180 -0.129034 9.765815 14.818116 4.302904 9.180266 8.727057 5.889585 7.844359 4.137095 6.555594 6.116047 2.278112 6.122475 4.458431 3.648216 4.706281 3.315668 7.880289 2.686481 2.993959 13.840351 0.604279 3.579507 19.931408 -0.982402 4.915413 24.521370 -1.648411 6.643725 26.380356 -1.215293 8.301341 25.010256 0.200900 9.444105 20.778185 2.220699 8.253130 15.783012 6.753772 7.974852 9.696511 8.438553 6.873600 5.055467 9.176052 5.244453 3.103445 8.768658 3.523942 4.363487 7.325531 2.173075 8.497964 5.233356 1.553816 14.399049 3.052730 1.832095 20.485548 1.367949 2.933347 25.126591 0.630449 4.562491 27.078617 1.037842 6.283002 25.818579 2.480968 7.633870 21.684105 4.573142 6.653211 16.706060 9.219476 6.648753 10.641614 11.003819 5.763950 5.965364 11.807409 4.235886 3.930308 11.414925 2.474002 5.081738 9.931531 0.950396 9.111128 7.754703 0.073316 14.938807 5.467720 0.077774 21.003254 3.683376 0.962575 25.679504 2.879785 2.490640 27.714561 3.272269 4.252522 26.563137 4.755661 5.776129 22.533749 6.932488 4.944098 17.581821 11.696327 5.168520 11.550085 13.574948 4.473474 6.851547 14.433211 3.045197 4.745179 14.041143 1.266395 5.795381 12.503801 -0.386303 9.720748 10.233112 -1.470058 15.469482 7.837508 -1.694480 21.501217 5.958887 -0.999434 26.199753 5.100624 0.428842 28.306124 5.492690 2.207643 27.255924 7.030031 3.860342 23.330563 9.300719 3.098943 18.400816 14.180655 3.494047 12.403591 16.139891 2.952954 7.691343 17.033133 1.620647 5.526714 16.621037 -0.145881 6.489717 15.014025 -1.873291 10.322313 12.642695 -3.098725 15.997561 10.142443 -3.493829 21.994785 8.183208 -2.952735 26.707035 7.289966 -1.620430 28.871666 7.702060 0.146097 27.908667 9.309070 1.873507 24.076073 11.680399 1.087592 19.153002 16.658623 1.593661 13.182844 18.674194 1.170403 8.459788 19.573942 -0.068772 6.249376 19.116779 -1.791826 7.143882 17.425207 -3.537071 10.903625 14.952478 -4.836867 16.521187 12.361158 -5.342937 22.491344 10.345589 -4.919679 27.214399 9.445841 -3.680506 29.424816 9.903000 -1.957451 28.530313 11.594570 -0.212207 24.770571 14.067300 -1.128007 19.824232 19.108950 -0.568176 13.866238 21.146177 -0.905614 9.130515 22.015104 -2.049905 6.886003 21.482903 -3.694436 7.734114 19.692175 -5.398558 11.447596 17.122747 -6.705652 17.031425 14.463093 -7.265483 22.989420 12.425868 -6.928046 27.725142 11.556941 -5.783756 29.969656 12.089142 -4.139225 29.121550 13.879866 -2.435103 25.408072 16.449293 -3.595865 20.395416 21.497778 -3.027745 14.430097 23.511133 -3.298371 9.676615 24.303047 -4.335230 7.408665 23.661325 -5.860496 8.233942 21.757917 -7.465474 11.931312 19.102840 -8.720114 17.510069 16.407520 -9.288235 23.475389 14.394163 -9.017609 28.228870 13.602248 -7.980751 30.496820 14.243968 -6.455485 29.671549 16.147377 -4.850507 25.974180 18.802452 -6.370023 20.845678 23.764061 -5.806425 14.856642 25.707056 -5.999455 10.080720 26.377323 -6.897389 7.797615 25.595259 -8.259628 8.619083 23.570417 -9.721160 12.325013 20.845356 -10.890368 17.922403 18.150253 -11.453966 23.911438 16.207256 -11.260937 28.687359 15.536993 -10.363003 30.970467 16.319056 -9.000765 30.149000 18.343893 -7.539233 26.443073 21.068953 -9.511271 21.144037 25.818520 -8.923167 15.124420 27.656929 -8.988944 10.326103 28.174419 -9.690977 8.034797 27.232327 -10.841158 8.864451 25.083084 -12.131295 12.592762 22.302584 -13.215699 18.220728 19.635853 -13.803803 24.240345 17.797443 -13.738027 29.038662 17.279953 -13.035994 31.329971 18.222046 -11.885814 30.500320 20.371284 -10.595676 26.772013 23.151785 -13.075891 21.242537 27.530581 -12.393333 15.201694 29.263725 -12.243426 10.391426 29.630873 -12.666337 8.100637 28.533644 -13.548745 8.943143 26.266043 -14.654212 12.693192 23.435669 -15.686528 18.345964 20.800920 -16.369085 24.386803 19.067776 -16.518991 29.197071 18.700628 -16.096083 31.487862 19.797855 -15.213675 30.645361 22.065456 -14.108208 26.895313 24.895828 -17.093649 21.067751 28.718386 -16.225630 15.036267 30.400394 -15.750659 10.240950 30.674793 -15.796005 7.966702 29.468050 -16.349518 8.822910 27.103518 -17.262882 12.580147 24.214767 -18.291365 18.231665 21.575840 -19.159384 24.263149 19.893829 -19.634354 29.058466 19.619432 -19.589008 31.332714 20.826172 -19.035498 30.476513 23.190702 -18.122133 26.719278 26.079453 -21.534901 20.513939 29.152893 -20.416739 14.540809 30.894396 -19.530174 9.805853 31.194626 -19.112766 7.577798 29.973141 -19.276356 8.453652 27.557238 -19.977108 12.198730 24.594252 -21.027260 17.809540 21.878115 -22.145422 23.782673 20.136616 -23.031984 28.517628 19.836382 -23.449394 30.745686 21.057865 -23.285807 29.869833 23.473770 -22.585052 26.124758 26.436754 -26.269354 19.457922 28.586409 -24.913492 13.595619 30.524569 -23.604948 8.974874 31.006615 -22.694345 6.833808 29.903383 -22.425680 7.746122 27.510481 -22.870941 11.467359 24.469084 -23.910818 17.000418 21.594135 -25.266680 22.862717 19.655973 -26.575222 27.483463 19.173925 -27.485825 29.624531 20.277159 -27.754492 28.712221 22.670059 -27.309233 24.990988 25.711454 -31.059818 17.792643 26.813808 -29.564510 12.075562 29.058905 -27.919226 7.609938 29.863401 -26.564821 5.592335 29.011730 -25.864204 6.563367 26.732101 -26.005106 10.262844 23.635334 -26.949772 15.699495 20.551208 -28.445080 21.416574 18.306112 -30.090363 25.882198 17.501617 -31.444769 27.899803 18.353285 -32.145386 26.928776 20.632912 -32.004486 23.229300 23.729677 -35.612064 15.450332 23.724575 -34.119438 9.882250 26.318789 -32.283455 5.583793 27.522276 -30.596062 3.706729 27.012556 -29.509396 4.754015 24.926212 -29.314629 8.445030 21.822279 -30.063946 13.790772 18.532450 -31.556570 19.358854 15.938233 -33.392555 23.657310 14.734747 -35.079948 25.534378 15.244466 -36.166615 24.487095 17.330807 -36.361382 20.796082 20.434740 -39.626049 12.409383 19.310429 -38.268299 6.968914 22.229200 -36.390564 2.823920 23.838266 -34.495979 1.085053 23.706478 -33.092197 2.218239 21.869152 -32.555367 5.919841 18.818594 -33.029320 11.198017 15.372201 -34.387074 16.638485 12.453430 -36.264809 20.783478 10.844364 -38.159393 22.522346 10.976149 -39.563171 21.389164 12.813475 -40.100006 17.687565 15.864031 -42.799465 8.714500 13.681709 -41.671757 3.369412 16.862862 -39.870743 -0.648207 18.840496 -37.879002 -2.261837 19.084707 -36.230217 -1.039111 17.530060 -35.366184 2.692346 14.593119 -35.518414 7.932690 11.060836 -36.646122 13.277777 7.879683 -38.447136 17.295395 5.902048 -40.438877 18.909029 5.657835 -42.087658 17.686306 7.212482 -42.951694 13.954851 10.149422 -44.846874 4.501185 7.102975 -44.006531 -0.779359 10.475080 -42.365295 -4.695889 12.769220 -40.362930 -6.198974 13.370684 -38.535973 -4.885862 12.118307 -37.373955 -1.108404 9.347665 -37.188236 4.121236 5.801149 -38.028580 9.401779 2.429044 -39.669815 13.318310 0.134902 -41.672176 14.821398 -0.466562 -43.499134 13.508288 0.785813 -44.661156 9.730832 3.556453 -45.555553 -0.002103 -0.003149 -45.034534 -5.243725 3.491900 -43.611099 -9.080275 6.051328 -41.666653 -10.483750 6.989339 -39.722210 -9.078091 6.054594 -38.298782 -5.239946 3.497557 -37.777775 0.002259 0.003385 -38.298794 5.243880 -3.491663 -39.722229 9.080429 -6.051091 -41.666676 10.483907 -6.989103 -43.611118 9.078252 -6.054360 -45.034546 5.240108 -3.497325 -44.845467 -4.505770 -7.109861 -44.660446 -9.733292 -3.560185 -43.499329 -13.507933 -0.785325 -41.673233 -14.818277 0.471199 -39.671463 -13.313222 -0.127299 -38.030388 -9.396046 -2.420451 -37.189735 -4.116352 -5.793809 -37.374756 1.111169 -9.343485 -38.535873 4.885808 -12.118345 -40.361965 6.196157 -13.374870 -42.363739 4.691105 -12.776374 -44.004814 0.773931 -10.483223 -42.796665 -8.718917 -13.688147 -42.949142 -13.958883 -10.155313 -42.086063 -17.688845 -7.216191 -40.438686 -18.909357 -5.658316 -38.448425 -17.293388 -5.899119 -36.648571 -13.273935 -7.874077 -35.521389 -7.928007 -11.054001 -35.368912 -2.688040 -14.586835 -36.231991 1.041921 -17.525955 -37.879364 2.262436 -19.083832 -39.869625 0.646470 -18.843031 -41.669483 -3.372981 -16.868076 -39.622292 -12.413079 -19.315578 -40.095055 -17.692432 -15.870825 -39.558388 -21.393875 -12.820044 -38.156090 -22.525608 -10.980692 -36.263905 -20.784382 -10.845621 -34.388840 -16.636761 -12.451023 -33.033318 -11.194097 -15.366732 -32.560555 -5.914744 -18.811485 -33.097218 -2.213301 -21.862267 -34.499516 -1.081566 -23.701620 -36.391705 -2.822787 -23.836691 -38.266769 -6.970406 -22.231293 -35.605217 -15.455013 -23.730375 -36.354542 -20.800592 -20.440283 -36.161648 -24.490211 -17.334568 -35.078224 -25.535240 -15.245411 -33.394569 -23.655663 -14.732594 -31.561821 -19.355112 -15.933527 -30.071062 -13.785917 -18.526421 -29.321737 -8.440338 -21.816513 -29.514629 -4.750720 -24.922226 -30.598053 -3.705688 -27.011385 -32.281704 -5.585262 -27.524204 -34.114452 -9.885810 -26.323273 -31.048832 -17.798424 -26.819057 -31.994871 -23.233709 -23.732943 -32.139759 -26.930620 -20.633295 -31.444675 -27.898571 -18.350664 -30.095863 -25.878201 -17.496677 -28.454741 -21.410866 -18.300159 -26.961040 -15.693586 -20.545818 -26.015001 -10.258303 -23.631931 -25.870113 -6.561391 -26.731579 -26.565197 -5.593437 -29.014212 -27.914007 -7.613805 -29.868198 -29.555130 -12.081137 -29.064718 -26.258905 -19.461916 -28.588505 -27.297956 -24.994576 -25.712488 -27.745447 -28.714436 -22.669739 -27.481474 -29.624769 -20.275560 -26.576767 -27.481647 -19.171471 -25.273743 -22.859322 -19.653307 -23.921545 -16.996338 -21.591967 -22.882494 -11.463679 -24.467983 -22.435003 -7.743816 -27.510731 -22.698977 -6.833482 -29.904911 -23.603682 -8.976601 -31.009003 -24.906706 -13.598925 -30.527164 -21.526140 -20.516254 -29.152636 -22.574167 -26.126955 -26.435450 -23.275747 -29.871326 -23.471764 -23.442894 -30.746065 -21.055700 -23.030821 -28.516787 -19.834637 -22.149940 -23.780827 -20.135757 -21.036287 -17.807180 -21.878378 -19.988262 -12.196480 -24.595564 -19.286680 -8.452108 -27.559246 -19.119534 -7.577369 -29.975313 -19.531607 -9.806643 -31.196377 -20.412485 -14.542601 -30.895258 -17.085157 -21.070391 -28.715899 -18.113974 -26.720476 -26.074026 -19.029892 -30.475952 -23.183792 -19.587492 -31.330542 -20.819633 -19.637365 -29.055258 -19.615028 -19.166149 -24.259764 -19.892746 -18.300104 -18.229006 -21.578373 -17.271288 -12.578922 -24.220247 -16.355370 -8.823446 -27.110477 -15.797770 -7.968855 -29.474636 -15.747895 -10.244135 -30.679245 -16.219112 -15.039627 -30.401529 -13.068244 -21.245543 -27.526308 -14.103080 -26.895962 -24.887501 -15.212470 -30.643482 -22.055311 -16.099155 -31.483959 -19.788626 -16.525551 -29.192188 -18.694799 -16.377399 -24.382250 -19.066921 -15.694404 -18.342960 -20.805283 -14.659569 -12.692542 -23.444090 -13.550179 -8.945022 -26.276279 -12.663492 -8.104540 -28.542967 -12.237098 -10.396307 -29.636793 -12.385247 -15.206244 -29.264673 -9.506032 -21.146215 -25.814342 -10.592706 -26.772135 -23.144213 -11.885937 -30.498363 -20.362354 -13.039205 -31.326460 -18.214169 -13.743493 -29.034538 -17.275257 -13.810087 -24.236717 -17.797201 -13.221145 -18.218571 -19.640146 -12.134472 -12.592652 -22.310278 -10.841241 -8.866424 -25.092133 -9.687972 -8.038323 -27.240322 -8.983685 -10.330242 -28.179234 -8.917089 -15.128059 -27.657291 -6.366224 -20.848097 -23.759735 -7.539409 -26.443207 -21.061625 -9.004894 -30.146824 -18.335541 -10.370004 -30.966564 -16.311935 -11.268959 -28.682781 -15.533033 -11.460884 -23.907412 -16.207537 -10.894354 -17.920013 -18.154715 -9.721170 -12.324903 -20.852825 -8.255686 -8.621286 -23.578907 -6.890575 -7.801543 -25.602512 -5.991621 -10.085324 -26.381418 -5.799694 -14.860689 -25.706917 -3.592857 -20.397593 -21.493515 -4.851548 -25.974218 -18.795671 -6.460322 -29.669451 -16.139912 -7.988108 -30.493153 -14.237844 -9.025537 -28.224617 -13.599126 -9.294633 -23.471695 -14.394899 -8.723289 -17.507927 -16.411942 -7.464599 -11.931302 -19.109785 -5.855826 -8.236069 -21.765543 -4.328040 -7.412364 -23.667612 -3.290610 -9.680897 -24.306330 -3.021513 -14.433816 -23.510559 -1.126703 -19.824917 -19.106972 -2.434951 -25.407873 -16.446047 -4.140288 -29.120537 -13.876242 -5.785770 -29.968105 -12.086132 -6.930491 -27.723467 -11.555374 -7.267725 -22.988079 -12.426184 -6.707110 -17.030783 -14.465233 -5.398862 -11.447827 -17.126156 -3.693526 -7.735164 -19.695961 -2.048044 -6.887594 -21.486073 -0.903322 -9.132225 -22.016830 -0.566087 -13.867611 -21.146021 1.089432 -19.154613 -16.655092 -0.214164 -24.770729 -14.062542 -1.962698 -28.528988 -11.589876 -3.687654 -29.422365 -9.899645 -4.926829 -27.211487 -9.444744 -5.348189 -22.488752 -10.347065 -4.838830 -16.519615 -12.364828 -3.535235 -10.903502 -14.957376 -1.786701 -7.145245 -17.430042 -0.061747 -6.251863 -19.120274 1.177430 -8.462738 -19.575176 1.598790 -13.185470 -18.672857 3.100337 -18.402143 -14.177729 1.871270 -24.076443 -11.677104 0.140814 -27.907995 -9.306304 -1.627356 -28.870134 -7.700584 -2.959461 -26.705059 -7.290194 -3.498566 -21.992899 -8.185099 -3.100216 -15.996273 -10.145507 -1.871150 -10.321973 -12.646132 -0.140695 -6.490422 -15.016931 1.627476 -5.528279 -16.622652 2.959582 -7.693351 -17.033043 3.498687 -12.405509 -16.138140 4.944380 -17.581575 -11.695987 3.861636 -23.330059 -9.299318 2.209594 -27.255314 -7.027955 0.430916 -28.305565 -5.490507 -0.997803 -26.199406 -5.098930 -1.693738 -21.501179 -5.958149 -1.470414 -15.469765 -7.837937 -0.387672 -9.721282 -10.234605 1.264370 -5.796028 -12.505968 3.043049 -4.745772 -14.043417 4.471767 -6.851928 -14.434994 5.167703 -11.550155 -13.575776 6.653645 -16.705984 -9.218736 5.776927 -22.533352 -6.930822 4.253461 -26.562542 -4.753518 2.491461 -27.713928 -3.270233 0.963051 -25.679003 -2.878409 0.077769 -21.003025 -3.683038 0.072825 -14.938913 -5.468517 0.949543 -9.111545 -7.756431 2.473008 -5.082356 -9.933734 4.235008 -3.930966 -11.417021 5.763418 -5.965888 -11.808845 6.648701 -10.641865 -11.004218 8.253338 -15.782888 -6.753438 7.634685 -21.683697 -4.571891 6.284200 -25.818008 -2.479139 4.563746 -27.078037 -1.035934 2.934316 -25.126160 -0.628981 1.832515 -20.485382 -1.367322 1.553569 -14.399194 -3.053120 2.172221 -8.498387 -5.234666 3.522705 -4.364075 -7.327418 5.243159 -3.104043 -8.770624 6.872590 -5.055918 -9.177578 7.974391 -9.696693 -8.439238 9.766647 -14.817905 -4.301442 9.444510 -20.777935 -2.219208 8.301205 -25.010042 -0.199783 6.643081 -26.380239 1.215727 4.914432 -24.521378 1.648039 3.578446 -19.931543 0.981315 2.993102 -13.840580 -0.605797 3.315240 -7.880552 -2.688032 4.458544 -3.648444 -4.707456 6.116667 -2.278246 -6.122967 7.845316 -4.137102 -6.555279 9.181301 -8.726932 -5.888556 11.212072 -13.814142 -1.867252 11.214707 -19.811825 0.130051 10.305743 -24.126728 2.092536 8.728736 -25.602676 3.494358 6.906243 -23.844191 3.959898 5.326601 -19.322456 3.364417 4.413072 -13.249070 1.867473 4.410436 -7.251388 -0.129830 5.319400 -2.936486 -2.092315 6.896406 -1.460534 -3.494137 8.718899 -3.219017 -3.959678 10.298542 -7.740747 -3.364198 12.608550 -12.773234 0.548056 12.949639 -18.782228 2.481205 12.291292 -23.158726 4.407030 10.809912 -24.730047 5.809507 8.902433 -23.075157 6.312843 7.079965 -18.637486 5.782171 5.830834 -12.606100 4.359684 5.489745 -6.597106 2.426535 6.148092 -2.220608 0.500711 7.629471 -0.649284 -0.901767 9.536949 -2.304171 -1.405105 11.359418 -6.741840 -0.874434 13.976293 -11.690985 2.945793 14.655608 -17.684561 4.837095 14.252954 -22.099211 6.746197 12.876220 -23.752039 8.161558 10.894300 -22.200165 8.703932 8.838251 -17.859419 8.227991 7.258987 -11.892898 6.861263 6.579670 -5.899324 4.969963 6.982325 -1.484673 3.060861 8.359057 0.168156 1.645500 10.340976 -1.383712 1.103125 12.397026 -5.724456 1.579064 15.330800 -10.564746 5.318358 16.337416 -16.514341 7.202624 16.187498 -20.939152 9.124739 14.921214 -22.653555 10.569671 12.877866 -21.198174 11.150254 10.604966 -16.962982 10.710920 8.711536 -11.082793 9.369390 7.704919 -5.133199 7.485126 7.854837 -0.708387 5.563012 9.121119 1.006018 4.118079 11.164467 -0.449359 3.537495 13.437366 -4.684548 3.976827 16.689184 -9.387169 7.659281 18.001242 -15.264573 9.581793 18.092003 -19.668903 11.553993 16.937149 -21.420027 13.047433 14.846122 -20.048727 13.661945 12.379211 -15.922447 13.232874 10.197424 -10.146818 11.875186 8.885367 -4.269415 9.952674 8.794605 0.134917 7.980474 9.949458 1.886042 6.487034 12.040483 0.514746 5.872520 14.507394 -3.611532 6.301592 18.067913 -8.142633 9.960091 19.658508 -13.919944 11.973578 19.972744 -18.271654 14.037516 18.926420 -20.031725 15.598871 16.799900 -18.728548 16.239285 14.162983 -14.711313 15.787153 11.722228 -9.056430 14.363628 10.131633 -3.279122 12.350142 9.817397 1.072587 10.286205 10.863719 2.832662 8.724849 12.990237 1.529491 8.084435 15.627154 -2.487743 8.536565 19.479279 -6.814370 12.204252 21.319818 -12.458337 14.376686 21.838051 -16.718760 16.584892 20.895113 -18.454062 18.237190 18.743668 -17.199268 18.890841 15.960193 -13.290604 18.370701 13.290517 -7.775390 16.816143 11.449977 -2.131424 14.643709 10.931745 2.128999 12.435501 11.874680 3.864302 10.783205 14.026123 2.609513 10.129555 16.809599 -1.299149 10.649692 20.931341 -5.375540 14.369343 22.999947 -10.841805 16.778124 23.706741 -14.962917 19.189102 22.862341 -16.634628 20.956261 20.692997 -15.409002 21.606089 17.779989 -11.614447 20.964468 14.903854 -6.267711 19.203316 12.835247 -0.801446 16.794537 12.128451 3.319666 14.383557 12.972852 4.991379 12.616399 15.142193 3.765756 11.966568 18.055201 -0.028797 12.608190 22.424438 -3.793416 16.421827 24.714603 -9.013955 19.153591 25.605583 -12.929366 21.831589 24.858639 -14.490516 23.738251 22.673914 -13.279098 24.362690 19.636805 -9.619711 23.537588 16.561100 -4.492884 21.484032 14.270935 0.727655 18.752266 13.379956 4.643065 16.074270 14.126899 6.204218 14.167607 16.311623 4.992803 13.543167 19.348730 1.333419 14.368268 23.948141 -2.021338 18.314199 26.482267 -6.892138 21.447077 27.574862 -10.510445 24.448751 26.933163 -11.906735 26.514925 24.729113 -10.706875 27.091969 21.553288 -7.232366 26.025267 18.256645 -2.414200 23.600637 15.722518 2.456600 20.467760 14.629923 6.074907 17.466089 15.271621 7.471200 15.399914 17.475668 6.271342 14.822868 20.651493 2.796835 15.889570</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="1440" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="4320">0.707578 -0.003730 -0.706625 0.677872 -0.065107 -0.732291 0.777600 -0.170680 -0.605150 0.799245 -0.124726 -0.587920 0.884178 -0.371881 -0.282726 0.880257 -0.372132 -0.294390 0.558754 -0.581163 0.591646 0.500073 -0.690638 0.522443 -0.251836 -0.274679 0.927971 -0.316641 -0.391234 0.864103 -0.554998 -0.057089 0.829891 -0.600707 -0.142010 0.786756 -0.674450 0.058364 0.736010 -0.704714 -0.001199 0.709491 -0.766792 0.173202 0.618086 -0.778223 0.144187 0.611211 -0.870242 0.376476 0.317717 -0.849122 0.400673 0.344169 -0.573484 0.583139 -0.575382 -0.518839 0.692693 -0.500982 0.253756 0.244506 -0.935855 0.295704 0.337942 -0.893507 0.552806 0.037870 -0.832449 0.586083 0.108647 -0.802934 0.641857 -0.135163 -0.754818 0.750948 -0.223659 -0.621333 0.889607 -0.363161 -0.276972 0.634038 -0.432440 0.641086 -0.171070 -0.123205 0.977525 -0.497982 0.049738 0.865760 -0.636856 0.127562 0.760356 -0.754109 0.192796 0.627813 -0.902540 0.308805 0.300102 -0.639796 0.437353 -0.631967 0.210575 0.162677 -0.963947 0.515150 -0.033223 -0.856456 0.599097 -0.214612 -0.771378 0.720768 -0.280819 -0.633746 0.895800 -0.343364 -0.282213 0.718034 -0.247539 0.650501 -0.082209 0.058690 0.994886 -0.433898 0.175832 0.883638 -0.591664 0.207973 0.778897 -0.731977 0.212011 0.647503 -0.923445 0.214630 0.318094 -0.725131 0.258189 -0.638376 0.148262 0.077252 -0.985926 0.466147 -0.112895 -0.877475 0.551701 -0.303616 -0.776817 0.688679 -0.340172 -0.640316 0.898696 -0.316763 -0.303325 0.795667 -0.043705 0.604156 0.001781 0.256931 0.966428 -0.370400 0.313618 0.874327 -0.541851 0.299944 0.785131 -0.696174 0.247572 0.673832 -0.915050 0.147208 0.375516 -0.818116 0.050678 -0.572816 0.058142 -0.061442 -0.996416 0.404042 -0.216463 -0.888760 0.504164 -0.399117 -0.765849 0.656185 -0.400438 -0.639587 0.893609 -0.293006 -0.340016 0.851780 0.151177 0.501613 0.068387 0.449814 0.890500 -0.315490 0.450852 0.834984 -0.493070 0.399179 0.773006 -0.651515 0.307385 0.693572 -0.885161 0.136288 0.444877 -0.877578 -0.141639 -0.458034 -0.035492 -0.262520 -0.964274 0.337876 -0.346583 -0.875054 0.461336 -0.494855 -0.736401 0.624625 -0.460671 -0.630575 0.878719 -0.281090 -0.385800 0.879572 0.312237 0.358972 0.111993 0.617643 0.778444 -0.273569 0.575737 0.770511 -0.450525 0.497872 0.741047 -0.606886 0.383649 0.696063 -0.848417 0.164344 0.503170 -0.901067 -0.294881 -0.317998 -0.105601 -0.471554 -0.875492 0.280670 -0.485064 -0.828213 0.426416 -0.584583 -0.690241 0.595475 -0.519970 -0.612406 0.855893 -0.284689 -0.431740 0.881353 0.428839 0.198279 0.134148 0.751283 0.646203 -0.244917 0.681952 0.689171 -0.416818 0.589088 0.692270 -0.568097 0.463540 0.679997 -0.811592 0.207883 0.545988 -0.898586 -0.406616 -0.164943 -0.146353 -0.646297 -0.748920 0.239085 -0.611667 -0.754123 0.400604 -0.664514 -0.630823 0.570337 -0.577245 -0.584383 0.828725 -0.302464 -0.470882 0.863343 0.503347 0.035791 0.139092 0.851665 0.505293 -0.228030 0.768879 0.597351 -0.392336 0.669390 0.630865 -0.536711 0.538923 0.649233 -0.776103 0.256481 0.576091 -0.877796 -0.478940 -0.009498 -0.163613 -0.778355 -0.606130 0.212928 -0.717381 -0.663345 0.384110 -0.733356 -0.560936 0.550779 -0.631178 -0.546130 0.800587 -0.330742 -0.499670 0.830731 0.543338 -0.121118 0.129776 0.923698 0.360472 -0.221919 0.838383 0.497862 -0.376828 0.738110 0.559637 -0.512386 0.607001 0.607462 -0.741777 0.307265 0.596117 -0.843692 -0.517689 0.142065 -0.163622 -0.873527 -0.458453 0.199857 -0.801864 -0.563091 0.377294 -0.790930 -0.481746 0.538343 -0.680289 -0.497387 0.773879 -0.365697 -0.517085 0.785935 0.555642 -0.271234 0.106677 0.971436 0.211972 -0.226957 0.892037 0.390847 -0.370569 0.795500 0.479435 -0.494760 0.667540 0.556420 -0.708116 0.359857 0.607515 -0.798443 -0.528627 0.288169 -0.149813 -0.939078 -0.309336 0.198343 -0.867518 -0.456151 0.381448 -0.836654 -0.393073 0.534893 -0.722631 -0.437829 0.750238 -0.404083 -0.523316 0.728776 0.543977 -0.415902 0.067973 0.995981 0.058316 -0.245043 0.929620 0.275248 -0.374960 0.841154 0.389698 -0.484322 0.720668 0.496055 -0.674686 0.414717 0.610580 -0.741835 -0.515038 0.429438 -0.122881 -0.979689 -0.158459 0.208568 -0.916072 -0.342508 0.399170 -0.868327 -0.294402 0.542908 -0.755126 -0.367472 0.730937 -0.443044 -0.519079 0.657269 0.508489 -0.556270 0.010085 0.994814 -0.101211 -0.279511 0.948286 0.150422 -0.392839 0.872830 0.289559 -0.482904 0.765489 0.425241 -0.641478 0.472504 0.604356 -0.672077 -0.477170 0.566235 -0.081514 -0.996661 -0.004711 0.232520 -0.947099 -0.221219 0.434179 -0.881278 -0.186647 0.565233 -0.773030 -0.287987 0.717013 -0.479748 -0.505702 0.568887 0.446138 -0.690890 -0.071149 0.961950 -0.263799 -0.334429 0.942241 0.018415 -0.428300 0.885589 0.179699 -0.494127 0.798911 0.342899 -0.609737 0.533320 0.586337 -0.586980 -0.412729 0.696497 -0.023176 -0.988175 0.151567 0.273802 -0.957345 -0.092325 0.489942 -0.868542 -0.074777 0.603657 -0.770513 -0.204715 0.708921 -0.511473 -0.485620 0.462809 0.352421 -0.813393 -0.177832 0.889900 -0.420065 -0.412452 0.903928 -0.113122 -0.485236 0.871947 0.065232 -0.523388 0.814515 0.250261 -0.583875 0.594813 0.552528 -0.485913 -0.318298 0.813987 0.055354 -0.950098 0.307001 0.337089 -0.940585 0.040876 0.566499 -0.823523 0.029809 0.656350 -0.743555 -0.127790 0.705928 -0.536437 -0.462493 0.343010 0.225614 -0.911835 -0.305991 0.774959 -0.552998 -0.511089 0.828364 -0.229351 -0.563814 0.824855 -0.041571 -0.575875 0.802759 0.154747 -0.574511 0.647934 0.500119 -0.372487 -0.190748 0.908223 0.159772 -0.875886 0.455299 0.426870 -0.888327 0.169282 0.656826 -0.745888 0.110597 0.716126 -0.694495 -0.069568 0.705848 -0.554822 -0.440398 0.219749 0.072539 -0.972856 -0.443127 0.624553 -0.643095 -0.619938 0.719908 -0.312106 -0.656437 0.744302 -0.122906 -0.650637 0.755886 0.072857 -0.595550 0.674191 0.436793 -0.256845 -0.030860 0.965960 0.301461 -0.752773 0.585196 0.543589 -0.792783 0.275690 0.747164 -0.646640 0.153633 0.772556 -0.633796 -0.038204 0.705501 -0.569082 -0.422391 0.105842 -0.090072 -0.990295 -0.571906 0.459467 -0.679569 -0.723430 0.595199 -0.349839 -0.748460 0.642475 -0.164416 -0.734972 0.677659 0.024395 -0.645656 0.658558 0.386561 -0.154864 0.137521 0.978317 0.479906 -0.568968 0.667806 0.674836 -0.656475 0.337100 0.823766 -0.544936 0.156379 0.817669 -0.574726 -0.033279 0.702329 -0.582092 -0.409761 0.009167 -0.242408 -0.970131 -0.679463 0.304740 -0.667431 -0.809009 0.475944 -0.344937 -0.825639 0.539654 -0.164598 -0.809139 0.587334 0.018255 -0.697498 0.612896 0.371289 -0.064793 0.277317 0.958591 0.654152 -0.351600 0.669673 0.794069 -0.503725 0.340171 0.879724 -0.457730 0.128724 0.849192 -0.525907 -0.047901 0.695786 -0.594985 -0.402335 -0.069414 -0.371645 -0.925776 -0.762529 0.176124 -0.622519 -0.872655 0.376906 -0.310507 -0.881353 0.452835 -0.134752 -0.859830 0.508594 0.044996 -0.724774 0.570366 0.386505 0.023498 0.390703 0.920217 0.779454 -0.161744 0.605219 0.880341 -0.369716 0.297170 0.915852 -0.392253 0.085749 0.869324 -0.488672 -0.073998 0.687396 -0.606329 -0.399814 -0.132458 -0.474640 -0.870156 -0.824544 0.075608 -0.560723 -0.917185 0.301023 -0.261067 -0.916901 0.388688 -0.090633 -0.886265 0.455307 0.085029 -0.725118 0.553549 0.409618 0.101867 0.486171 0.867906 0.853111 -0.031409 0.520784 0.932420 -0.274001 0.235621 0.937136 -0.346572 0.040801 0.881974 -0.459452 -0.105004 0.679949 -0.613294 -0.401920 -0.181276 -0.554866 -0.811950 -0.870142 -0.003848 -0.492787 -0.947682 0.242832 -0.207201 -0.937668 0.344550 -0.045439 -0.895761 0.427842 0.120677 -0.710565 0.563289 0.421668 0.162655 0.563706 0.809802 0.892940 0.045854 0.447834 0.960129 -0.215188 0.178453 0.949417 -0.314007 0.002621 0.890867 -0.433459 -0.135897 0.676248 -0.613598 -0.407660 -0.214932 -0.618107 -0.756140 -0.902272 -0.071132 -0.425259 -0.968490 0.194550 -0.155494 -0.949677 0.313146 -0.007320 -0.897373 0.417686 0.142340 -0.693823 0.588311 0.415330 0.203066 0.625136 0.753637 0.913178 0.089377 0.397640 0.973805 -0.181298 0.137240 0.957564 -0.287143 -0.024900 0.898865 -0.406698 -0.163213 0.678175 -0.606183 -0.415477 -0.232452 -0.669320 -0.705675 -0.922515 -0.132801 -0.362394 -0.982583 0.149873 -0.109860 -0.957731 0.286954 0.020229 -0.898006 0.414289 0.148156 -0.683047 0.616041 0.392351 0.223586 0.674335 0.703763 0.921667 0.116938 0.369939 0.980615 -0.159115 0.114352 0.964704 -0.260085 -0.041246 0.907811 -0.376379 -0.184982 0.686614 -0.590784 -0.423716 -0.233766 -0.711879 -0.662255 -0.931978 -0.192734 -0.307035 -0.991869 0.104662 -0.072395 -0.964853 0.260194 0.036834 -0.901501 0.409281 0.140657 -0.681944 0.637632 0.358298 0.225780 0.714939 0.661729 0.922230 0.140606 0.360169 0.984484 -0.138735 0.107445 0.972222 -0.229159 -0.047655 0.918436 -0.341282 -0.200005 0.701502 -0.568037 -0.430383 -0.219491 -0.747739 -0.626666 -0.931649 -0.252382 -0.261406 -0.997398 0.056957 -0.044200 -0.972378 0.229258 0.043839 -0.909255 0.397223 0.124379 -0.691341 0.647906 0.319789 0.211437 0.749303 0.627566 0.916835 0.167540 0.362415 0.987130 -0.114000 0.112155 0.980167 -0.192680 -0.046337 0.930548 -0.301025 -0.208482 0.721691 -0.538707 -0.434691 -0.192528 -0.777365 -0.598863 -0.922878 -0.311626 -0.226241 -0.999662 0.006351 -0.025226 -0.980294 0.192769 0.043165 -0.920791 0.376090 0.103439 -0.709711 0.645597 0.281984 0.184165 0.777970 0.600705 0.906615 0.200204 0.371440 0.988850 -0.082358 0.124065 0.987839 -0.150460 -0.039182 0.943447 -0.255953 -0.210703 0.745995 -0.503554 -0.435804 -0.154500 -0.800961 -0.578439 -0.906820 -0.370116 -0.201721 -0.998786 -0.046964 -0.014851 -0.987931 0.150455 0.036830 -0.934878 0.345575 0.081125 -0.735034 0.630987 0.248155 0.145952 0.801097 0.580466 0.891988 0.238743 0.383873 0.989207 -0.043546 0.139905 0.994254 -0.103289 -0.028129 0.956087 -0.207066 -0.207415 0.772619 -0.463786 -0.433547 -0.108837 -0.818133 -0.564635 -0.884856 -0.426433 -0.187575 -0.994733 -0.101754 -0.012338 -0.994299 0.103264 0.026557 -0.949921 0.306695 0.059896 -0.764741 0.605426 0.220523 0.100141 0.818081 0.566317 0.873488 0.281885 0.396938 0.987619 0.001467 0.156863 0.998510 -0.052572 -0.014641 0.967471 -0.155529 -0.199527 0.800005 -0.420322 -0.428160 -0.057894 -0.828585 -0.556862 -0.858214 -0.479571 -0.182975 -0.987490 -0.156810 -0.016525 -0.998522 0.052546 0.013860 -0.964434 0.261084 0.041261 -0.796502 0.570609 0.199974 0.049163 0.828520 0.557797 0.851499 0.327717 0.409329 0.983552 0.050892 0.173310 1.000000 -0.000005 0.000003 0.976791 -0.102888 -0.187865 0.826688 -0.374462 -0.419958 -0.004426 -0.832079 -0.554639 -0.828256 -0.528123 -0.187290 -0.977234 -0.210504 -0.026482 -1.000000 0 0.000006 -0.977237 0.210491 0.026505 -0.828271 0.528087 0.187324 -0.004447 0.832083 0.554633 0.826702 0.374475 0.419920 0.976794 0.102887 0.187852 0.998511 0.052551 0.014638 0.983555 -0.050928 -0.173281 0.851497 -0.327754 -0.409305 0.049177 -0.828517 -0.557800 -0.796500 -0.570602 -0.200004 -0.964439 -0.261063 -0.041281 -0.998523 -0.052535 -0.013841 -0.987493 0.156787 0.016601 -0.858223 0.479515 0.183079 -0.057888 0.828586 0.556861 0.800040 0.420361 0.428057 0.967483 0.155540 0.199460 0.994260 0.103235 0.028104 0.987629 -0.001562 -0.156804 0.873488 -0.281995 -0.396860 0.100125 -0.818085 -0.566314 -0.764769 -0.605360 -0.220606 -0.949943 -0.306619 -0.059942 -0.994305 -0.103221 -0.026515 -0.994733 0.101738 0.012482 -0.884847 0.426369 0.187763 -0.108794 0.818132 0.564644 0.772684 0.463838 0.433375 0.956115 0.207070 0.207283 0.987858 0.150352 0.039117 0.989224 0.043367 -0.139837 0.891983 -0.238955 -0.383754 0.145879 -0.801122 -0.580451 -0.735117 -0.630843 -0.248274 -0.934930 -0.345422 -0.081182 -0.987948 -0.150359 -0.036749 -0.998782 0.046976 0.015077 -0.906778 0.370066 0.202004 -0.154377 0.800963 0.578469 0.746109 0.503603 0.435552 0.943499 0.255933 0.210493 0.980208 0.192500 0.046215 0.988885 0.082057 -0.123990 0.906608 -0.200563 -0.371264 0.184027 -0.778033 -0.600665 -0.709873 -0.645354 -0.282132 -0.920889 -0.375836 -0.103487 -0.980333 -0.192606 -0.043023 -0.999654 -0.006300 0.025549 -0.922792 0.311598 0.226630 -0.192323 0.777376 0.598914 0.721862 0.538751 0.434354 0.930633 0.300973 0.208176 0.972295 0.228889 0.047446 0.987186 0.113552 -0.112111 0.916815 -0.168089 -0.362211 0.211173 -0.749443 -0.627487 -0.691619 -0.647538 -0.319935 -0.909420 -0.396841 -0.124392 -0.972447 -0.229007 -0.043613 -0.997384 -0.056851 0.044643 -0.931501 0.252393 0.261924 -0.219154 0.747766 0.626752 0.701748 0.568067 0.429943 0.918563 0.341185 0.199584 0.964813 0.259733 0.040926 0.984552 0.138187 -0.107529 0.922166 -0.141297 -0.360062 0.225329 -0.715198 -0.661603 -0.682339 -0.637203 -0.358310 -0.901730 -0.408815 -0.140549 -0.964958 -0.259852 -0.036512 -0.991854 -0.104450 0.072907 -0.931762 0.192860 0.307611 -0.233233 0.711944 0.662373 0.686958 0.590730 0.423234 0.907988 0.376196 0.184486 0.957695 0.286741 0.024499 0.980684 0.158528 -0.114575 0.921568 -0.117687 -0.369950 0.223068 -0.674706 -0.703571 -0.683494 -0.615667 -0.392161 -0.898264 -0.413828 -0.147881 -0.957853 -0.286573 -0.019814 -0.982568 -0.149581 0.110392 -0.922263 0.133021 0.362954 -0.231851 0.669387 0.705809 0.678574 0.606039 0.415035 0.899075 0.406436 0.162709 0.949564 0.313559 -0.003084 0.973925 0.180509 -0.137427 0.913161 -0.090450 -0.397437 0.202757 -0.625648 -0.753295 -0.694337 -0.587832 -0.415150 -0.897678 -0.417144 -0.142005 -0.949795 -0.312774 0.007842 -0.968428 -0.194329 0.156154 -0.901947 0.071242 0.425930 -0.214357 0.618100 0.756309 0.676628 0.613518 0.407149 0.891066 0.433239 0.135296 0.937280 0.346107 -0.041428 0.960257 0.214317 -0.178817 0.892903 -0.047220 -0.447766 0.161897 -0.564586 -0.809341 -0.711212 -0.562795 -0.421235 -0.896111 -0.427250 -0.120176 -0.937793 -0.344124 0.046085 -0.947587 -0.242549 0.207962 -0.869701 0.004041 0.493562 -0.180373 0.554932 0.812106 0.680430 0.613180 0.401280 0.882184 0.459217 0.104266 0.915985 0.391803 -0.086389 0.932527 0.273215 -0.236106 0.853150 0.030032 -0.520800 0.101555 -0.487476 -0.867210 -0.725558 -0.553519 -0.408879 -0.886506 -0.454969 -0.084325 -0.916967 -0.388366 0.091346 -0.917064 -0.300758 0.261799 -0.824086 -0.075435 0.561419 -0.131590 0.474572 0.870325 0.687898 0.606107 0.399287 0.869548 0.488372 0.073335 0.879841 0.457335 -0.129321 0.880558 0.368861 -0.297589 0.779922 0.159934 -0.605097 0.023913 -0.392599 -0.919399 -0.725006 -0.570566 -0.385773 -0.859981 -0.508398 -0.044313 -0.881335 -0.452663 0.135444 -0.872443 -0.376815 0.311213 -0.761988 -0.176156 0.623173 -0.068557 0.371436 0.925924 0.696225 0.594819 0.401823 0.849360 0.525694 0.047266 0.823873 0.544624 -0.156899 0.794422 0.502922 -0.340535 0.655244 0.349499 -0.669705 -0.063530 -0.279903 -0.957924 -0.697413 -0.613370 -0.370665 -0.809173 -0.587304 -0.017693 -0.825543 -0.539622 0.165186 -0.808726 -0.475988 0.345539 -0.678853 -0.304922 0.667968 0.010088 0.242123 0.970193 0.702732 0.581962 0.409252 0.817791 0.574585 0.032700 0.747311 0.646385 -0.153990 0.675459 0.655694 -0.337374 0.481845 0.566930 -0.668144 -0.152376 -0.139910 -0.978370 -0.645271 -0.659081 -0.386313 -0.734909 -0.677737 -0.024096 -0.748283 -0.642591 0.164771 -0.723074 -0.595420 0.350198 -0.571277 -0.459863 0.679830 0.106619 0.089613 0.990253 0.705795 0.568999 0.422010 0.772626 0.633736 0.037788 0.656978 0.745715 -0.110857 0.544459 0.792075 -0.276010 0.303804 0.751161 -0.586055 -0.254197 0.028951 -0.966719 -0.595288 -0.674404 -0.436819 -0.650677 -0.755862 -0.072756 -0.656245 -0.744445 0.123062 -0.619497 -0.720231 0.312234 -0.442413 -0.625067 0.643088 0.220500 -0.072992 0.972652 0.705985 0.554889 0.440095 0.716074 0.694578 0.069279 0.566627 0.823428 -0.030002 0.427707 0.887853 -0.169659 0.161805 0.874961 -0.456358 -0.370274 0.189657 -0.909356 -0.574375 -0.647958 -0.500244 -0.575988 -0.802681 -0.154728 -0.563658 -0.824960 0.041600 -0.510663 -0.828638 0.229309 -0.305301 -0.775390 0.552776 0.343729 -0.225941 0.911483 0.705985 0.536573 0.462250 0.656239 0.743684 0.127608 0.490041 0.868497 0.074653 0.337737 0.940337 -0.041223 0.056812 0.949704 -0.307953 -0.484456 0.317828 -0.815039 -0.583875 -0.594724 -0.552624 -0.523534 -0.814420 -0.250265 -0.485139 -0.871997 -0.065278 -0.412127 -0.904094 0.112981 -0.177297 -0.890164 0.419730 0.463377 -0.352612 0.812986 0.708945 0.511599 0.485451 0.603553 0.770618 0.204626 0.434247 0.881261 0.186568 0.274240 0.957246 0.092048 -0.022268 0.988086 -0.152282 -0.586131 0.412626 -0.697274 -0.609796 -0.533211 -0.586375 -0.494270 -0.798828 -0.342886 -0.428251 -0.885601 -0.179756 -0.334201 -0.942319 -0.018577 -0.070773 -0.962071 0.263459 0.569285 -0.446206 0.690518 0.717008 0.479858 0.505605 0.565143 0.773106 0.287959 0.399214 0.868326 0.294345 0.232806 0.947079 0.221003 -0.080959 0.996709 0.004190 -0.671555 0.477233 -0.566800 -0.641529 -0.472408 -0.604377 -0.483016 -0.765433 -0.425215 -0.392812 -0.872828 -0.289604 -0.279345 -0.948312 -0.150569 0.010359 -0.994842 0.100906 0.657548 -0.508475 0.555953 0.730911 0.443140 0.519033 0.542828 0.755183 0.367473 0.381477 0.836663 0.393028 0.208780 0.916093 0.342323 -0.122486 0.979807 0.158034 -0.741449 0.515210 -0.429898 -0.674726 -0.414625 -0.610599 -0.484412 -0.720629 -0.496024 -0.374941 -0.841147 -0.389731 -0.244909 -0.929616 -0.275380 0.068193 -0.995950 -0.058592 0.728994 -0.543907 0.415611 0.750205 0.404167 0.523299 0.534818 0.722675 0.437848 0.377314 0.790946 0.481704 0.198518 0.867571 0.455974 -0.149491 0.939261 0.308936 -0.798126 0.528875 -0.288595 -0.708158 -0.359769 -0.607518 -0.494842 -0.667515 -0.556377 -0.370553 -0.795491 -0.479463 -0.226839 -0.892010 -0.390975 0.106864 -0.971358 -0.212237 0.786119 -0.555521 0.270951 0.773845 0.365779 0.517078 0.538272 0.680326 0.497412 0.384128 0.733382 0.560888 0.200022 0.801959 0.562898 -0.163334 0.873804 0.458027 -0.843398 0.518047 -0.142502 -0.741824 -0.307160 -0.596112 -0.512467 -0.606984 -0.607411 -0.376813 -0.738094 -0.559669 -0.221809 -0.838327 -0.498005 0.129942 -0.923563 -0.360759 0.830887 -0.543167 0.120819 0.800551 0.330823 0.499674 0.550709 0.631209 0.546164 0.400617 0.664553 0.630773 0.213097 0.717550 0.663107 -0.163325 0.778815 0.605617 -0.877485 0.479519 0.008992 -0.776161 -0.256341 -0.576077 -0.536800 -0.538914 -0.649167 -0.392321 -0.669364 -0.630902 -0.227920 -0.768779 -0.597521 0.139251 -0.851442 -0.505624 0.863480 -0.503088 -0.036134 0.828684 0.302544 0.470903 0.570259 0.577262 0.584443 0.426413 0.584649 0.690187 0.239254 0.611981 0.753814 -0.146075 0.647132 0.748253 -0.898241 0.407638 0.164299 -0.811666 -0.207706 -0.545946 -0.568192 -0.463575 -0.679895 -0.416794 -0.589051 -0.692316 -0.244796 -0.681771 -0.689393 0.134301 -0.750909 -0.646606 0.881461 -0.428426 -0.198691 0.855844 0.284772 0.431782 0.595381 0.519964 0.612502 0.461282 0.494975 0.736355 0.280780 0.485709 0.827798 -0.105435 0.473271 0.874584 -0.900695 0.296826 0.317243 -0.848519 -0.164163 -0.503056 -0.606970 -0.383788 -0.695912 -0.450476 -0.497817 -0.741114 -0.273439 -0.575417 -0.770796 0.112124 -0.617018 -0.778920 0.879628 -0.311574 -0.359411 0.878643 0.281178 0.385909 0.624495 0.460621 0.630741 0.504015 0.399270 0.765867 0.337796 0.347695 0.874644 -0.035751 0.265752 0.963378 -0.877402 0.145112 0.457283 -0.885251 -0.136187 -0.444728 -0.651526 -0.307685 -0.693429 -0.492969 -0.399105 -0.773109 -0.315354 -0.450376 -0.835292 0.068474 -0.448913 -0.890948 0.851759 -0.150217 -0.501938 0.893496 0.293104 0.340227 0.656014 0.400312 0.639841 0.551443 0.303752 0.776946 0.403615 0.218034 0.888570 0.057107 0.066463 0.996153 -0.818468 -0.045440 0.572753 -0.915046 -0.147405 -0.375451 -0.696025 -0.248056 -0.673809 -0.541688 -0.299821 -0.785290 -0.370284 -0.312975 -0.874606 0.001781 -0.255799 -0.966728 0.795535 0.044843 -0.604246 0.898574 0.316797 0.303654 0.688499 0.339919 0.640644 0.598752 0.214605 0.771648 0.465434 0.114273 0.877674 0.146537 -0.072309 0.986559 -0.726970 -0.252413 0.638594 -0.923274 -0.214862 -0.318431 -0.731646 -0.212464 -0.647729 -0.591406 -0.207807 -0.779137 -0.433728 -0.175172 -0.883852 -0.082159 -0.057570 -0.994955 0.717963 0.248645 -0.650158 0.895656 0.343325 0.282715 0.720560 0.280470 0.634137 0.641470 0.135054 0.755167 0.514224 0.034289 0.856970 0.208646 -0.158911 0.964994 -0.641781 -0.433290 0.632753 -0.902271 -0.308986 -0.300725 -0.753663 -0.193044 -0.628272 -0.636585 -0.127256 -0.760635 -0.497859 -0.049002 -0.865872 -0.171091 0.124272 -0.977386 0.633906 0.433296 -0.640638 0.889549 0.362951 0.277433 0.750794 0.223204 0.621682 0.677449 0.064740 0.732715 0.551865 -0.037451 0.833092 0.251908 -0.242586 0.936853 -0.575549 -0.581161 0.575322 -0.869902 -0.376446 -0.318684 -0.766251 -0.173205 -0.618757 -0.674072 -0.057940 -0.736390 -0.554742 0.057864 -0.830008 -0.251625 0.275693 -0.927727 0.558971 0.581764 -0.590849 0.884183 0.371412 0.283327 0.777434 0.170034 0.605545 0.707148 0.003254 0.707058 0.585261 -0.108712 0.803524 0.294372 -0.337238 0.894212 -0.520127 -0.691628 0.501118 -0.849017 -0.400225 -0.344949 -0.777803 -0.143800 -0.611836 -0.704353 0.001773 -0.709847 -0.600413 0.142771 -0.786842 -0.316362 0.392088 -0.863818 0.500312 0.691021 -0.521706 0.880281 0.371632 0.294949 0.799059 0.124083 0.588309 0.732329 -0.048426 0.679227 0.619076 -0.176727 0.765188 0.340611 -0.430510 0.835850 -0.476418 -0.767987 0.428044 -0.845327 -0.394490 -0.360278 -0.793351 -0.107699 -0.599162 -0.729498 0.051645 -0.682030 -0.634763 0.205914 -0.744765 -0.364187 0.475404 -0.800848 0.457323 0.767189 -0.449752 0.876137 0.369588 0.309497 0.815094 0.088290 0.572562 0.754872 -0.087717 0.649980 0.654700 -0.234655 0.718543 0.390094 -0.510105 0.766564 -0.440439 -0.819550 0.366541 -0.854338 -0.377284 -0.357442 -0.813778 -0.072868 -0.576589 -0.751963 0.089713 -0.653072 -0.660619 0.248491 -0.708403 -0.399129 0.530171 -0.748074 0.423617 0.819593 -0.385766 0.869651 0.371255 0.325387 0.826096 0.065154 0.559750 0.776197 -0.112507 0.620371 0.691704 -0.277041 0.666929 0.441251 -0.569822 0.693254 -0.407379 -0.855605 0.319346 -0.868858 -0.361899 -0.337810 -0.837200 -0.046976 -0.544875 -0.773311 0.113776 -0.623735 -0.681361 0.272152 -0.679471 -0.426420 0.561592 -0.709070 0.393050 0.856582 -0.334333 0.859665 0.380008 0.341423 0.833329 0.055651 0.549969 0.796928 -0.121655 0.591698 0.728978 -0.301038 0.614791 0.493061 -0.607662 0.622606 -0.372099 -0.882715 0.286978 -0.882939 -0.356081 -0.305981 -0.861149 -0.034769 -0.507162 -0.794307 0.122639 -0.595009 -0.699974 0.278732 -0.657529 -0.451099 0.574166 -0.683259 0.360288 0.884326 -0.296918 0.845837 0.397385 0.355872 0.838022 0.059839 0.542345 0.816906 -0.115636 0.565060 0.765015 -0.306473 0.566415 0.544078 -0.624614 0.560211 -0.332171 -0.904618 0.267073 -0.892270 -0.363053 -0.268416 -0.883026 -0.037995 -0.467783 -0.814705 0.116559 -0.568040 -0.718227 0.270524 -0.641067 -0.476459 0.571932 -0.667743 0.322906 0.906346 -0.272525 0.828645 0.422794 0.366867 0.841085 0.076439 0.535475 0.835417 -0.096035 0.541162 0.798747 -0.295357 0.524182 0.593462 -0.623825 0.508572 -0.287382 -0.922732 0.256859 -0.895027 -0.382218 -0.229860 -0.901139 -0.055692 -0.429938 -0.833619 0.096916 -0.543771 -0.736238 0.249623 -0.629000 -0.503350 0.557765 -0.659952 0.280649 0.924234 -0.258895 0.808206 0.455048 0.373812 0.842461 0.103835 0.528657 0.851357 -0.064730 0.520578 0.828902 -0.269956 0.489945 0.640368 -0.607937 0.469406 -0.236922 -0.937539 0.254730 -0.890280 -0.412097 -0.193850 -0.914203 -0.085948 -0.396038 -0.850078 0.065672 -0.522546 -0.753863 0.218254 -0.619723 -0.532316 0.533913 -0.656945 0.232838 0.938565 -0.254720 0.784741 0.492832 0.375896 0.841817 0.140211 0.521234 0.863648 -0.024403 0.503505 0.854272 -0.233292 0.464537 0.683347 -0.580212 0.443160 -0.183090 -0.948539 0.258364 -0.877950 -0.449970 -0.163493 -0.921162 -0.126058 -0.368199 -0.862797 0.025343 -0.504915 -0.770113 0.178915 -0.612304 -0.562235 0.502829 -0.656548 0.181697 0.949139 -0.257141 0.758874 0.533742 0.373135 0.838776 0.182995 0.512804 0.871296 0.022460 0.490244 0.874028 -0.188267 0.447918 0.721551 -0.543393 0.429055 -0.127126 -0.955392 0.266579 -0.858723 -0.493056 -0.139610 -0.921770 -0.173075 -0.346967 -0.870839 -0.021552 -0.491095 -0.783716 0.133656 -0.606569 -0.591525 0.465995 -0.657987 0.128436 0.955730 -0.264733 0.730461 0.576286 0.366498 0.832530 0.230159 0.503905 0.873570 0.073442 0.481125 0.887266 -0.137420 0.440312 0.753758 -0.499713 0.426773 -0.070697 -0.957872 0.278357 -0.833151 -0.539119 -0.123328 -0.915746 -0.224456 -0.333211 -0.873515 -0.072554 -0.481359 -0.793940 0.084746 -0.602061 -0.619156 0.425253 -0.660156 0.074579 0.958150 -0.276383 0.700136 0.618742 0.356327 0.822850 0.279520 0.494759 0.870043 0.126032 0.476593 0.893194 -0.083330 0.441883 0.778548 -0.451456 0.435949 -0.016002 -0.956044 0.292787 -0.801954 -0.586090 -0.115626 -0.903002 -0.277755 -0.327780 -0.870356 -0.125188 -0.476244 -0.800119 0.034523 -0.598847 -0.643896 0.382667 -0.662544 0.022541 0.956593 -0.290554 0.668905 0.659280 0.343387 0.809807 0.328807 0.485900 0.860512 0.177903 0.477356 0.891132 -0.028435 0.452852 0.794490 -0.400812 0.456218 0.034828 -0.950374 0.309153 -0.765887 -0.632205 -0.117191 -0.883659 -0.330711 -0.331327 -0.861197 -0.177102 -0.476418 -0.801787 -0.014790 -0.597427 -0.664678 0.340155 -0.665205 -0.025783 0.951551 -0.306407 0.637742 0.696523 0.328847 0.793608 0.376015 0.478330 0.844954 0.226874 0.484336 0.880464 0.024873 0.473459 0.800089 -0.350112 0.487113 0.079584 -0.941768 0.326709 -0.725639 -0.675927 -0.128727 -0.857808 -0.381282 -0.344659 -0.846003 -0.226121 -0.482854 -0.798689 -0.060996 -0.598644 -0.680617 0.299861 -0.668464 -0.068167 0.944012 -0.322792 0.607913 0.729206 0.314165 0.774687 0.419284 0.473352 0.823260 0.270966 0.498819 0.860194 0.074401 0.504510 0.793398 -0.301494 0.528792 0.116754 -0.931361 0.344870 -0.681259 -0.716206 -0.151446 -0.825186 -0.427698 -0.368975 -0.824778 -0.270221 -0.496710 -0.790902 -0.101930 -0.603394 -0.691328 0.263933 -0.672611 -0.103014 0.935170 -0.338889 0.580812 0.756366 0.300945 0.753612 0.456939 0.472521 0.795230 0.308200 0.522132 0.829669 0.117493 0.545752 0.772822 -0.258242 0.579704 0.143071 -0.921199 0.361833 -0.633197 -0.751312 -0.185988 -0.785437 -0.467965 -0.405090 -0.797075 -0.307525 -0.519712 -0.777593 -0.135662 -0.613958 -0.695209 0.234714 -0.679407 -0.127481 0.927096 -0.352479 0.557167 0.777154 0.292568 0.730343 0.487543 0.478435 0.759716 0.337532 0.555791 0.788001 0.152290 0.596542 0.737504 -0.222633 0.637591 0.158761 -0.912664 0.376617 -0.581127 -0.780232 -0.231363 -0.737850 -0.500658 -0.452680 -0.761876 -0.336927 -0.553196 -0.757154 -0.161285 -0.633012 -0.690246 0.213127 -0.691475 -0.141196 0.921209 -0.362544 0.535419 0.791994 0.293381 0.703247 0.510766 0.494532 0.714496 0.358328 0.600914 0.733387 0.177445 0.656244 0.686081 -0.196644 0.700446 0.163827 -0.907230 0.387421 -0.523197 -0.802262 -0.287471 -0.680187 -0.524836 -0.511755 -0.716874 -0.357810 -0.598385 -0.727069 -0.178384 -0.662986 -0.673983 0.199860 -0.711198 -0.144056 0.918911 -0.367219 0.512835 0.801499 0.307569 0.669614 0.526616 0.523729 0.655881 0.370584 0.657638 0.664673 0.192006 0.722041 0.619482 -0.182241 0.763564 0.159442 -0.906446 0.391067 -0.458175 -0.816354 -0.351628 -0.610158 -0.539729 -0.579999 -0.657892 -0.370249 -0.655816 -0.681373 -0.187720 -0.707454 -0.640460 0.194622 -0.742922 -0.136358 0.921474 -0.363720 0.482287 0.807043 0.340707 0.623374 0.535994 0.569312 0.577766 0.376010 0.724433 0.579925 0.197383 0.790397 0.539960 -0.178102 0.822631 0.151342 -0.909198 0.387885 -0.383705 -0.823236 -0.418395 -0.524914 -0.546293 -0.652709 -0.579004 -0.375806 -0.723550 -0.611457 -0.191647 -0.767718 -0.582194 0.194758 -0.789379 -0.124348 0.927810 -0.351718 0.431329 0.811072 0.395118 0.554643 0.541088 0.632135 0.472443 0.376687 0.796808 0.475446 0.196403 0.857541 0.448653 -0.180954 0.875195 0.145540 -0.913620 0.379627 -0.295559 -0.824530 -0.482489 -0.419860 -0.546643 -0.724499 -0.472481 -0.376472 -0.796888 -0.507121 -0.192110 -0.840192 -0.491360 0.198297 -0.848082 -0.116096 0.936094 -0.332040 0.346277 0.814213 0.465992 0.452249 0.543303 0.707314 0.331697 0.373902 0.866126 0.346125 0.192180 0.918294 0.345080 -0.186126 0.919933 0.147569 -0.916602 0.371569 -0.189216 -0.822165 -0.536882 -0.290148 -0.543137 -0.787919 -0.330311 -0.373446 -0.866852 -0.358093 -0.189150 -0.914326 -0.360915 0.204675 -0.909862 -0.120943 0.943083 -0.309786 0.214368 0.814242 0.539496 0.305435 0.542069 0.782860 0.150169 0.366435 0.918245 0.185528 0.186054 0.964864 0.223848 -0.189495 0.956025 0.159114 -0.914147 0.372851 -0.058534 -0.817229 -0.573333 -0.130197 -0.536807 -0.833599 -0.147696 -0.365513 -0.919014 -0.161193 -0.179533 -0.970456 -0.190938 0.215478 -0.957660 -0.144267 0.944158 -0.296232 0.032225 0.805459 0.591774 0.110242 0.533633 0.838500 -0.067952 0.349464 0.934483 -0.008883 0.174804 0.984563 0.076684 -0.192157 0.978364 0.174680 -0.903909 0.390429 0.102132 -0.806975 -0.581688 0.063621 -0.524463 -0.849053 0.070957 -0.347984 -0.934811 0.071576 -0.157588 -0.984908 0.006361 0.234341 -0.972134 -0.179966 0.935801 -0.303131 -0.185619 0.780754 0.596632 -0.122791 0.511702 0.850343 -0.303554 0.317765 0.898265 -0.226908 0.152331 0.961930 -0.096990 -0.200720 0.974836 0.183200 -0.887039 0.423793 0.287692 -0.784858 -0.548845 0.283249 -0.499364 -0.818783 0.306378 -0.315837 -0.897986 0.312230 -0.120234 -0.942367 0.208301 0.263232 -0.941977 -0.212345 0.917901 -0.335213 -0.407895 0.737153 0.538728 -0.366868 0.472034 0.801619 -0.526774 0.271077 0.805622 -0.444439 0.115423 0.888342 -0.282673 -0.221402 0.933315 0.175247 -0.867992 0.464627 0.475166 -0.746301 -0.466104 0.503207 -0.457439 -0.733166 0.528635 -0.269109 -0.805062 0.528712 -0.071064 -0.845821 0.390930 0.299445 -0.870348 -0.225464 0.894511 -0.386026 -0.598927 0.679731 0.423381 -0.587701 0.417241 0.693194 -0.711514 0.215070 0.668949 -0.634859 0.066971 0.769720 -0.456955 -0.254591 0.852277 0.149847 -0.851567 0.502374 0.634273 -0.694325 -0.340015 0.692154 -0.402338 -0.599205 0.712277 -0.213561 -0.668620 0.701595 -0.017322 -0.712366 0.540597 0.338192 -0.770312 -0.213534 0.871593 -0.441280 -0.736821 0.618412 0.273241 -0.760422 0.355603 0.543420 -0.846894 0.157025 0.508049 -0.782611 0.013489 0.622365 -0.601934 -0.295317 0.741932 0.112115 -0.839756 0.531262 0.746722 -0.637500 -0.189738 0.831779 -0.342513 -0.436840 0.847000 -0.156176 -0.508134 0.827731 0.035605 -0.559995 0.655779 0.376506 -0.654368 -0.181325 0.853157 -0.489127 -0.820257 0.560915 0.112040 -0.878896 0.294998 0.374858 -0.935401 0.101549 0.338693 -0.885943 -0.039595 0.462102 -0.712110 -0.338117 0.615285 0.066946 -0.832358 0.550180 0.811630 -0.583202 -0.033648 0.921296 -0.284678 -0.264900 0.935306 -0.101234 -0.339048 0.912388 0.085776 -0.400239 0.740326 0.413903 -0.529719 -0.136781 0.840269 -0.524632 -0.859003 0.509864 -0.046406 -0.949613 0.239086 0.202666 -0.984410 0.049641 0.168737 -0.950256 -0.090189 0.298127 -0.790018 -0.380290 0.480887 0.017497 -0.828800 0.559272 0.836914 -0.534461 0.118010 0.968369 -0.231254 -0.093716 0.984354 -0.049607 -0.169076 0.962008 0.133805 -0.237983 0.798081 0.451498 -0.399019 -0.086417 0.832424 -0.547360 -0.863378 0.464276 -0.197552 -0.981666 0.187721 0.033067 -1.000000 -0.000034 -0.000066 -0.981295 -0.138906 0.133290 -0.839794 -0.421807 0.341795 -0.034212 -0.828774 0.558537 0.830748 -0.491115 0.262037 0.980602 -0.181654 0.073627 1.000000 -0.000058 -0.000078 0.980608 0.181560 -0.073783 0.830722 0.491086 -0.262173 -0.034256 0.828793 -0.558506 -0.839768 0.421818 -0.341846 -0.981285 0.138864 -0.133401 -0.984380 -0.049724 -0.168888 -0.981653 -0.187763 -0.033196 -0.863410 -0.464251 0.197471 -0.086459 -0.832402 0.547387 0.798120 -0.451557 0.398875 0.962037 -0.133932 0.237796 0.984391 0.049475 0.168897 0.968398 0.231186 0.093581 0.836888 0.534484 -0.118091 0.017456 0.828821 -0.559241 -0.789964 0.380257 -0.481000 -0.950217 0.090110 -0.298276 -0.935332 -0.101659 -0.338850 -0.949552 -0.239186 -0.202834 -0.858983 -0.509911 0.046250 -0.136809 -0.840250 0.524656 0.740382 -0.413875 0.529663 0.912448 -0.085851 0.400085 0.935396 0.101095 0.338843 0.921382 0.284570 0.264716 0.811648 0.583184 0.033525 0.066947 0.832385 -0.550140 -0.712031 0.338104 -0.615384 -0.885871 0.039514 -0.462245 -0.846767 -0.157146 -0.508223 -0.878760 -0.295136 -0.375067 -0.820170 -0.561004 -0.112233 -0.181293 -0.853145 0.489159 0.655855 -0.376435 0.654333 0.827835 -0.035667 0.559837 0.847171 0.156004 0.507902 0.831990 0.342322 0.436588 0.746881 0.637379 0.189519 0.112137 0.839787 -0.531209 -0.601893 0.295376 -0.741942 -0.782525 -0.013534 -0.622473 -0.711262 -0.215259 -0.669156 -0.760129 -0.355814 -0.543692 -0.736622 -0.618539 -0.273492 -0.213514 -0.871578 0.441320 0.540743 -0.338093 0.770254 0.701838 0.017242 0.712127 0.712657 0.213343 0.668285 0.692617 0.402093 0.598834 0.634636 0.694168 0.339659 0.149778 0.851594 -0.502349 -0.456991 0.254660 -0.852237 -0.634740 -0.067050 -0.769811 -0.526392 -0.271408 -0.805760 -0.587278 -0.417565 -0.693357 -0.598606 -0.679943 -0.423496 -0.225379 -0.894432 0.386258 0.391180 -0.299185 0.870326 0.529161 0.071081 0.845539 0.529311 0.268961 0.804667 0.503916 0.457314 0.732757 0.475580 0.746323 0.465647 0.175000 0.867909 -0.464874 -0.282670 0.221290 -0.933343 -0.444203 -0.115671 -0.888428 -0.303088 -0.318102 -0.898303 -0.366395 -0.472356 -0.801645 -0.407530 -0.737366 -0.538712 -0.212305 -0.917823 0.335451 0.208516 -0.262953 0.942007 0.312770 0.120315 0.942178 0.307233 0.315765 0.897720 0.284122 0.499306 0.818516 0.288194 0.784903 0.548518 0.183123 0.886962 -0.423986 -0.096855 0.200571 -0.974880 -0.226546 -0.152609 -0.961971 -0.067479 -0.349759 -0.934407 -0.122082 -0.512024 -0.850252 -0.184903 -0.780990 -0.596545 -0.179912 -0.935799 0.303168 0.006130 -0.234056 0.972204 0.071797 0.157794 0.984858 0.071818 0.348031 0.934728 0.064905 0.524417 0.848984 0.103242 0.806901 0.581594 0.174697 0.903910 -0.390419 0.076416 0.192089 -0.978398 -0.008775 -0.175017 -0.984526 0.150496 -0.366930 -0.917994 0.110973 -0.534122 -0.838093 0.033034 -0.805829 -0.591227 -0.144307 -0.943982 0.296772 -0.191547 -0.214862 0.957677 -0.161301 0.180061 0.970340 -0.146966 0.365910 0.918973 -0.128778 0.537099 0.833631 -0.057092 0.817422 0.573204 0.159179 0.913890 -0.373453 0.223200 0.189055 -0.956264 0.185318 -0.186522 -0.964814 0.331864 -0.374610 -0.865756 0.305663 -0.542717 -0.782323 0.214455 -0.814725 -0.538732 -0.121402 -0.942707 0.310749 -0.361107 -0.203813 0.909979 -0.357902 0.189911 0.914243 -0.329762 0.374144 0.866760 -0.289386 0.543775 0.787759 -0.188467 0.822653 0.536398 0.147863 0.916130 -0.372616 0.344971 0.185298 -0.920141 0.346139 -0.192934 -0.918131 0.472590 -0.377359 -0.796404 0.452338 -0.543905 -0.706794 0.346203 -0.814610 -0.465353 -0.116342 -0.935887 0.332535 -0.491373 -0.197632 0.848230 -0.506838 0.192843 0.840195 -0.472033 0.377187 0.796816 -0.419383 0.547277 0.724297 -0.295124 0.824926 0.482078 0.145855 0.913380 -0.380083 0.448854 0.180253 -0.875237 0.475607 -0.197119 -0.857287 0.577771 -0.376746 -0.724047 0.554595 -0.541750 -0.631610 0.431089 -0.811541 -0.394414 -0.124955 -0.927463 0.352418 -0.582409 -0.193933 0.789424 -0.611369 0.192455 0.767586 -0.578722 0.376583 0.723372 -0.524513 0.546999 0.652440 -0.383198 0.823727 0.417892 0.151858 0.908801 -0.388614 0.540104 0.177257 -0.822720 0.579955 -0.198178 -0.790176 0.655807 -0.371256 -0.657333 0.622870 -0.536684 -0.569212 0.481380 -0.807635 -0.340586 -0.137206 -0.921068 0.364428 -0.640118 -0.193700 0.743458 -0.680928 0.188534 0.707666 -0.657726 0.370941 0.655591 -0.610304 0.540295 0.579319 -0.458295 0.816741 0.350571 0.160140 0.905985 -0.391851 0.620153 0.181540 -0.763186 0.665008 -0.192661 -0.721558 0.714566 -0.358679 -0.600621 0.669542 -0.526942 -0.523495 0.512674 -0.801651 -0.307443 -0.143757 -0.919000 0.367114 -0.673784 -0.199583 0.711464 -0.726815 0.178833 0.663143 -0.716664 0.358238 0.598379 -0.680048 0.525177 0.511590 -0.523125 0.802378 0.287279 0.163684 0.907369 -0.387155 0.686364 0.196465 -0.700218 0.733587 -0.177778 -0.655930 0.759626 -0.338063 -0.555592 0.703184 -0.511219 -0.494153 0.535217 -0.792334 -0.292829 -0.141957 -0.920882 0.363077 -0.690660 -0.212518 0.691249 -0.757300 0.161817 0.632703 -0.761795 0.337457 0.552984 -0.737549 0.501203 0.452567 -0.580570 0.780707 0.231159 0.159478 0.912300 -0.377193 0.737501 0.221937 -0.637837 0.787874 -0.152898 -0.596554 0.795154 -0.308636 -0.521991 0.729821 -0.488066 -0.478699 0.556316 -0.777634 -0.292914 -0.128119 -0.926840 0.352922 -0.694860 -0.234001 0.680009 -0.777236 0.136242 0.614282 -0.797029 0.307950 0.519530 -0.785682 0.468222 0.404318 -0.633397 0.751431 0.184823 0.143843 0.920911 -0.362261 0.773483 0.257928 -0.578962 0.830013 -0.117811 -0.545159 0.823316 -0.271001 -0.498708 0.753404 -0.457054 -0.472740 0.580523 -0.756418 -0.301370 -0.102674 -0.935304 0.338621 -0.690882 -0.263834 0.673108 -0.790579 0.102099 0.603788 -0.824710 0.270305 0.496778 -0.825358 0.427641 0.368657 -0.681605 0.715973 0.150987 0.116250 0.931516 -0.344621 0.793729 0.301769 -0.528137 0.860485 -0.074299 -0.504028 0.844947 -0.226891 -0.484340 0.774695 -0.419304 -0.473320 0.607917 -0.729228 -0.314109 -0.068254 -0.943980 0.322867 -0.680679 -0.299814 0.668422 -0.798721 0.061021 0.598599 -0.846006 0.226134 0.482842 -0.857788 0.381298 0.344690 -0.725592 0.675971 0.128764 0.079692 0.941746 -0.326747 0.800060 0.350081 -0.487183 0.880439 -0.024888 -0.473506 0.860522 -0.177909 -0.477337 0.793629 -0.376019 -0.478291 0.637759 -0.696514 -0.328833 -0.025752 -0.951559 0.306387 -0.664674 -0.340131 0.665222 -0.801781 0.014818 0.597435 -0.861185 0.177119 0.476434 -0.883630 0.330730 0.331386 -0.765853 0.632226 0.117299 0.034698 0.950389 -0.309122 0.794434 0.400829 -0.456301 0.891113 0.028430 -0.452890 0.870036 -0.126072 -0.476595 0.809795 -0.328846 -0.485893 0.668870 -0.659318 -0.343384 0.022442 -0.956570 0.290637 -0.643922 -0.382577 0.662570 -0.800123 -0.034464 0.598845 -0.870362 0.125226 0.476223 -0.902995 0.277799 0.327761 -0.801898 0.586170 0.115608 -0.015817 0.956030 -0.292844 0.778540 0.451398 -0.436022 0.893177 0.083287 -0.441925 0.873584 -0.073458 -0.481098 0.822879 -0.279529 -0.494706 0.700218 -0.618698 -0.356241 0.074695 -0.958175 0.276263 -0.619233 -0.425288 0.660061 -0.793987 -0.084735 0.602001 -0.873505 0.072583 0.481373 -0.915731 0.224477 0.333237 -0.833163 0.539110 0.123288 -0.070721 0.957878 -0.278332 0.753793 0.499768 -0.426648 0.887301 0.137439 -0.440236 0.871290 -0.022519 -0.490252 0.832495 -0.230256 -0.503919 0.730387 -0.576409 -0.366453 0.128187 -0.955699 0.264968 -0.591615 -0.465892 0.657979 -0.783755 -0.133592 0.606532 -0.870861 0.021585 0.491056 -0.921795 0.173073 0.346899 -0.858742 0.493052 0.139509 -0.127033 0.955402 -0.266589 0.721614 0.543384 -0.428961 0.874055 0.188253 -0.447872 0.863653 0.024428 -0.503495 0.838739 -0.183010 -0.512859 0.758813 -0.533747 -0.373252 0.181823 -0.949136 0.257064 -0.562094 -0.502772 0.656712 -0.770025 -0.178862 0.612429 -0.862784 -0.025350 0.504937 -0.921195 0.125997 0.368138 -0.878002 0.449888 0.163443 -0.183208 0.948532 -0.258306 0.683333 0.580291 -0.443079 0.854283 0.233355 -0.464485 0.851400 0.064707 -0.520510 0.842086 -0.140093 -0.520832 0.785140 -0.492585 -0.375387 0.233119 -0.938549 0.254521 -0.532613 -0.534153 0.656508 -0.754093 -0.218342 0.619412 -0.850059 -0.065604 0.522586 -0.913992 0.086146 0.396481 -0.890046 0.412301 0.194488 -0.237225 0.937508 -0.254566 0.640124 0.607839 -0.469864 0.828772 0.269828 -0.490234 0.835490 0.095668 -0.541113 0.842681 -0.104107 -0.528253 0.808378 -0.455301 -0.373130 0.280009 -0.924277 0.259435 -0.504019 -0.557639 0.659549 -0.736663 -0.249432 0.628579 -0.833754 -0.096598 0.543621 -0.901031 0.056133 0.430106 -0.894725 0.382772 0.230115 -0.286674 0.922876 -0.257134 0.593553 0.623326 -0.509077 0.798719 0.294895 -0.524486 0.817067 0.115240 -0.564908 0.841217 -0.076827 -0.535212 0.828646 -0.423108 -0.366504 0.322671 -0.906350 0.272787 -0.476778 -0.571643 0.667762 -0.718457 -0.270127 0.640977 -0.814833 -0.116132 0.567944 -0.883043 0.038429 0.467717 -0.892126 0.363443 0.268364 -0.331887 0.904699 -0.267153 0.544347 0.624318 -0.560279 0.765198 0.306085 -0.566378 0.797106 0.121178 -0.591556 0.838122 -0.060344 -0.542135 0.845763 -0.397867 -0.355509 0.359762 -0.884372 0.297419 -0.451508 -0.573754 0.683335 -0.700249 -0.278266 0.657434 -0.794506 -0.122177 0.594839 -0.861269 0.035211 0.506927 -0.882875 0.356526 0.305648 -0.371422 0.882886 -0.287328 0.493531 0.607325 -0.622562 0.729245 0.300612 -0.614683 0.776408 0.112115 -0.620178 0.833430 -0.056080 -0.549773 0.859614 -0.380368 -0.341150 0.392861 -0.856539 0.334667 -0.426651 -0.561202 0.709240 -0.681550 -0.271695 0.679464 -0.773478 -0.113336 0.623607 -0.837328 0.047382 0.544643 -0.868822 0.362250 0.337526 -0.407040 0.855769 -0.319341 0.441716 0.569694 -0.693062 0.692036 0.276732 -0.666712 0.755147 0.087289 -0.649718 0.826399 -0.065429 -0.559270 0.869832 -0.371386 -0.324752 0.423435 -0.819482 0.386201 -0.399589 -0.529919 0.748007 -0.661000 -0.248132 0.708173 -0.752178 -0.089207 0.652894 -0.813735 0.073582 0.576560 -0.853904 0.378128 0.357584 -0.439973 0.819877 -0.366368 0.390307 0.509584 -0.766801 0.654898 0.234059 -0.718558 0.732692 0.047795 -0.678880 0.815378 -0.088874 -0.572066 0.876207 -0.370067 -0.308727 0.456664 -0.767060 0.450641 -0.364828 -0.474814 0.800907 -0.635260 -0.205327 0.744504 -0.729889 -0.051041 0.681657 -0.793584 0.108384 0.598730 -0.845139 0.395381 0.359741 -0.475051 0.768459 -0.428716 0.341433 0.430058 -0.835747 0.619541 0.176090 -0.764958</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="1440" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="4719">0 0 0 0 0.083333 0 0 0.166667 0 0 0.250000 0 0 0.333333 0 0 0.416667 0 0 0.500000 0 0 0.583333 0 0 0.666667 0 0 0.750000 0 0 0.833333 0 0 0.916667 0 0 1.000000 0 0.008333 0 0 0.008333 0.083333 0 0.008333 0.166667 0 0.008333 0.250000 0 0.008333 0.333333 0 0.008333 0.416667 0 0.008333 0.500000 0 0.008333 0.583333 0 0.008333 0.666667 0 0.008333 0.750000 0 0.008333 0.833333 0 0.008333 0.916667 0 0.008333 1.000000 0 0.016667 0 0 0.016667 0.083333 0 0.016667 0.166667 0 0.016667 0.250000 0 0.016667 0.333333 0 0.016667 0.416667 0 0.016667 0.500000 0 0.016667 0.583333 0 0.016667 0.666667 0 0.016667 0.750000 0 0.016667 0.833333 0 0.016667 0.916667 0 0.016667 1.000000 0 0.025000 0 0 0.025000 0.083333 0 0.025000 0.166667 0 0.025000 0.250000 0 0.025000 0.333333 0 0.025000 0.416667 0 0.025000 0.500000 0 0.025000 0.583333 0 0.025000 0.666667 0 0.025000 0.750000 0 0.025000 0.833333 0 0.025000 0.916667 0 0.025000 1.000000 0 0.033333 0 0 0.033333 0.083333 0 0.033333 0.166667 0 0.033333 0.250000 0 0.033333 0.333333 0 0.033333 0.416667 0 0.033333 0.500000 0 0.033333 0.583333 0 0.033333 0.666667 0 0.033333 0.750000 0 0.033333 0.833333 0 0.033333 0.916667 0 0.033333 1.000000 0 0.041667 0 0 0.041667 0.083333 0 0.041667 0.166667 0 0.041667 0.250000 0 0.041667 0.333333 0 0.041667 0.416667 0 0.041667 0.500000 0 0.041667 0.583333 0 0.041667 0.666667 0 0.041667 0.750000 0 0.041667 0.833333 0 0.041667 0.916667 0 0.041667 1.000000 0 0.050000 0 0 0.050000 0.083333 0 0.050000 0.166667 0 0.050000 0.250000 0 0.050000 0.333333 0 0.050000 0.416667 0 0.050000 0.500000 0 0.050000 0.583333 0 0.050000 0.666667 0 0.050000 0.750000 0 0.050000 0.833333 0 0.050000 0.916667 0 0.050000 1.000000 0 0.058333 0 0 0.058333 0.083333 0 0.058333 0.166667 0 0.058333 0.250000 0 0.058333 0.333333 0 0.058333 0.416667 0 0.058333 0.500000 0 0.058333 0.583333 0 0.058333 0.666667 0 0.058333 0.750000 0 0.058333 0.833333 0 0.058333 0.916667 0 0.058333 1.000000 0 0.066667 0 0 0.066667 0.083333 0 0.066667 0.166667 0 0.066667 0.250000 0 0.066667 0.333333 0 0.066667 0.416667 0 0.066667 0.500000 0 0.066667 0.583333 0 0.066667 0.666667 0 0.066667 0.750000 0 0.066667 0.833333 0 0.066667 0.916667 0 0.066667 1.000000 0 0.075000 0 0 0.075000 0.083333 0 0.075000 0.166667 0 0.075000 0.250000 0 0.075000 0.333333 0 0.075000 0.416667 0 0.075000 0.500000 0 0.075000 0.583333 0 0.075000 0.666667 0 0.075000 0.750000 0 0.075000 0.833333 0 0.075000 0.916667 0 0.075000 1.000000 0 0.083333 0 0 0.083333 0.083333 0 0.083333 0.166667 0 0.083333 0.250000 0 0.083333 0.333333 0 0.083333 0.416667 0 0.083333 0.500000 0 0.083333 0.583333 0 0.083333 0.666667 0 0.083333 0.750000 0 0.083333 0.833333 0 0.083333 0.916667 0 0.083333 1.000000 0 0.091667 0 0 0.091667 0.083333 0 0.091667 0.166667 0 0.091667 0.250000 0 0.091667 0.333333 0 0.091667 0.416667 0 0.091667 0.500000 0 0.091667 0.583333 0 0.091667 0.666667 0 0.091667 0.750000 0 0.091667 0.833333 0 0.091667 0.916667 0 0.091667 1.000000 0 0.100000 0 0 0.100000 0.083333 0 0.100000 0.166667 0 0.100000 0.250000 0 0.100000 0.333333 0 0.100000 0.416667 0 0.100000 0.500000 0 0.100000 0.583333 0 0.100000 0.666667 0 0.100000 0.750000 0 0.100000 0.833333 0 0.100000 0.916667 0 0.100000 1.000000 0 0.108333 0 0 0.108333 0.083333 0 0.108333 0.166667 0 0.108333 0.250000 0 0.108333 0.333333 0 0.108333 0.416667 0 0.108333 0.500000 0 0.108333 0.583333 0 0.108333 0.666667 0 0.108333 0.750000 0 0.108333 0.833333 0 0.108333 0.916667 0 0.108333 1.000000 0 0.116667 0 0 0.116667 0.083333 0 0.116667 0.166667 0 0.116667 0.250000 0 0.116667 0.333333 0 0.116667 0.416667 0 0.116667 0.500000 0 0.116667 0.583333 0 0.116667 0.666667 0 0.116667 0.750000 0 0.116667 0.833333 0 0.116667 0.916667 0 0.116667 1.000000 0 0.125000 0 0 0.125000 0.083333 0 0.125000 0.166667 0 0.125000 0.250000 0 0.125000 0.333333 0 0.125000 0.416667 0 0.125000 0.500000 0 0.125000 0.583333 0 0.125000 0.666667 0 0.125000 0.750000 0 0.125000 0.833333 0 0.125000 0.916667 0 0.125000 1.000000 0 0.133333 0 0 0.133333 0.083333 0 0.133333 0.166667 0 0.133333 0.250000 0 0.133333 0.333333 0 0.133333 0.416667 0 0.133333 0.500000 0 0.133333 0.583333 0 0.133333 0.666667 0 0.133333 0.750000 0 0.133333 0.833333 0 0.133333 0.916667 0 0.133333 1.000000 0 0.141667 0 0 0.141667 0.083333 0 0.141667 0.166667 0 0.141667 0.250000 0 0.141667 0.333333 0 0.141667 0.416667 0 0.141667 0.500000 0 0.141667 0.583333 0 0.141667 0.666667 0 0.141667 0.750000 0 0.141667 0.833333 0 0.141667 0.916667 0 0.141667 1.000000 0 0.150000 0 0 0.150000 0.083333 0 0.150000 0.166667 0 0.150000 0.250000 0 0.150000 0.333333 0 0.150000 0.416667 0 0.150000 0.500000 0 0.150000 0.583333 0 0.150000 0.666667 0 0.150000 0.750000 0 0.150000 0.833333 0 0.150000 0.916667 0 0.150000 1.000000 0 0.158333 0 0 0.158333 0.083333 0 0.158333 0.166667 0 0.158333 0.250000 0 0.158333 0.333333 0 0.158333 0.416667 0 0.158333 0.500000 0 0.158333 0.583333 0 0.158333 0.666667 0 0.158333 0.750000 0 0.158333 0.833333 0 0.158333 0.916667 0 0.158333 1.000000 0 0.166667 0 0 0.166667 0.083333 0 0.166667 0.166667 0 0.166667 0.250000 0 0.166667 0.333333 0 0.166667 0.416667 0 0.166667 0.500000 0 0.166667 0.583333 0 0.166667 0.666667 0 0.166667 0.750000 0 0.166667 0.833333 0 0.166667 0.916667 0 0.166667 1.000000 0 0.175000 0 0 0.175000 0.083333 0 0.175000 0.166667 0 0.175000 0.250000 0 0.175000 0.333333 0 0.175000 0.416667 0 0.175000 0.500000 0 0.175000 0.583333 0 0.175000 0.666667 0 0.175000 0.750000 0 0.175000 0.833333 0 0.175000 0.916667 0 0.175000 1.000000 0 0.183333 0 0 0.183333 0.083333 0 0.183333 0.166667 0 0.183333 0.250000 0 0.183333 0.333333 0 0.183333 0.416667 0 0.183333 0.500000 0 0.183333 0.583333 0 0.183333 0.666667 0 0.183333 0.750000 0 0.183333 0.833333 0 0.183333 0.916667 0 0.183333 1.000000 0 0.191667 0 0 0.191667 0.083333 0 0.191667 0.166667 0 0.191667 0.250000 0 0.191667 0.333333 0 0.191667 0.416667 0 0.191667 0.500000 0 0.191667 0.583333 0 0.191667 0.666667 0 0.191667 0.750000 0 0.191667 0.833333 0 0.191667 0.916667 0 0.191667 1.000000 0 0.200000 0 0 0.200000 0.083333 0 0.200000 0.166667 0 0.200000 0.250000 0 0.200000 0.333333 0 0.200000 0.416667 0 0.200000 0.500000 0 0.200000 0.583333 0 0.200000 0.666667 0 0.200000 0.750000 0 0.200000 0.833333 0 0.200000 0.916667 0 0.200000 1.000000 0 0.208333 0 0 0.208333 0.083333 0 0.208333 0.166667 0 0.208333 0.250000 0 0.208333 0.333333 0 0.208333 0.416667 0 0.208333 0.500000 0 0.208333 0.583333 0 0.208333 0.666667 0 0.208333 0.750000 0 0.208333 0.833333 0 0.208333 0.916667 0 0.208333 1.000000 0 0.216667 0 0 0.216667 0.083333 0 0.216667 0.166667 0 0.216667 0.250000 0 0.216667 0.333333 0 0.216667 0.416667 0 0.216667 0.500000 0 0.216667 0.583333 0 0.216667 0.666667 0 0.216667 0.750000 0 0.216667 0.833333 0 0.216667 0.916667 0 0.216667 1.000000 0 0.225000 0 0 0.225000 0.083333 0 0.225000 0.166667 0 0.225000 0.250000 0 0.225000 0.333333 0 0.225000 0.416667 0 0.225000 0.500000 0 0.225000 0.583333 0 0.225000 0.666667 0 0.225000 0.750000 0 0.225000 0.833333 0 0.225000 0.916667 0 0.225000 1.000000 0 0.233333 0 0 0.233333 0.083333 0 0.233333 0.166667 0 0.233333 0.250000 0 0.233333 0.333333 0 0.233333 0.416667 0 0.233333 0.500000 0 0.233333 0.583333 0 0.233333 0.666667 0 0.233333 0.750000 0 0.233333 0.833333 0 0.233333 0.916667 0 0.233333 1.000000 0 0.241667 0 0 0.241667 0.083333 0 0.241667 0.166667 0 0.241667 0.250000 0 0.241667 0.333333 0 0.241667 0.416667 0 0.241667 0.500000 0 0.241667 0.583333 0 0.241667 0.666667 0 0.241667 0.750000 0 0.241667 0.833333 0 0.241667 0.916667 0 0.241667 1.000000 0 0.250000 0 0 0.250000 0.083333 0 0.250000 0.166667 0 0.250000 0.250000 0 0.250000 0.333333 0 0.250000 0.416667 0 0.250000 0.500000 0 0.250000 0.583333 0 0.250000 0.666667 0 0.250000 0.750000 0 0.250000 0.833333 0 0.250000 0.916667 0 0.250000 1.000000 0 0.258333 0 0 0.258333 0.083333 0 0.258333 0.166667 0 0.258333 0.250000 0 0.258333 0.333333 0 0.258333 0.416667 0 0.258333 0.500000 0 0.258333 0.583333 0 0.258333 0.666667 0 0.258333 0.750000 0 0.258333 0.833333 0 0.258333 0.916667 0 0.258333 1.000000 0 0.266667 0 0 0.266667 0.083333 0 0.266667 0.166667 0 0.266667 0.250000 0 0.266667 0.333333 0 0.266667 0.416667 0 0.266667 0.500000 0 0.266667 0.583333 0 0.266667 0.666667 0 0.266667 0.750000 0 0.266667 0.833333 0 0.266667 0.916667 0 0.266667 1.000000 0 0.275000 0 0 0.275000 0.083333 0 0.275000 0.166667 0 0.275000 0.250000 0 0.275000 0.333333 0 0.275000 0.416667 0 0.275000 0.500000 0 0.275000 0.583333 0 0.275000 0.666667 0 0.275000 0.750000 0 0.275000 0.833333 0 0.275000 0.916667 0 0.275000 1.000000 0 0.283333 0 0 0.283333 0.083333 0 0.283333 0.166667 0 0.283333 0.250000 0 0.283333 0.333333 0 0.283333 0.416667 0 0.283333 0.500000 0 0.283333 0.583333 0 0.283333 0.666667 0 0.283333 0.750000 0 0.283333 0.833333 0 0.283333 0.916667 0 0.283333 1.000000 0 0.291667 0 0 0.291667 0.083333 0 0.291667 0.166667 0 0.291667 0.250000 0 0.291667 0.333333 0 0.291667 0.416667 0 0.291667 0.500000 0 0.291667 0.583333 0 0.291667 0.666667 0 0.291667 0.750000 0 0.291667 0.833333 0 0.291667 0.916667 0 0.291667 1.000000 0 0.300000 0 0 0.300000 0.083333 0 0.300000 0.166667 0 0.300000 0.250000 0 0.300000 0.333333 0 0.300000 0.416667 0 0.300000 0.500000 0 0.300000 0.583333 0 0.300000 0.666667 0 0.300000 0.750000 0 0.300000 0.833333 0 0.300000 0.916667 0 0.300000 1.000000 0 0.308333 0 0 0.308333 0.083333 0 0.308333 0.166667 0 0.308333 0.250000 0 0.308333 0.333333 0 0.308333 0.416667 0 0.308333 0.500000 0 0.308333 0.583333 0 0.308333 0.666667 0 0.308333 0.750000 0 0.308333 0.833333 0 0.308333 0.916667 0 0.308333 1.000000 0 0.316666 0 0 0.316666 0.083333 0 0.316666 0.166667 0 0.316666 0.250000 0 0.316666 0.333333 0 0.316666 0.416667 0 0.316666 0.500000 0 0.316666 0.583333 0 0.316666 0.666667 0 0.316666 0.750000 0 0.316666 0.833333 0 0.316666 0.916667 0 0.316666 1.000000 0 0.325000 0 0 0.325000 0.083333 0 0.325000 0.166667 0 0.325000 0.250000 0 0.325000 0.333333 0 0.325000 0.416667 0 0.325000 0.500000 0 0.325000 0.583333 0 0.325000 0.666667 0 0.325000 0.750000 0 0.325000 0.833333 0 0.325000 0.916667 0 0.325000 1.000000 0 0.333333 0 0 0.333333 0.083333 0 0.333333 0.166667 0 0.333333 0.250000 0 0.333333 0.333333 0 0.333333 0.416667 0 0.333333 0.500000 0 0.333333 0.583333 0 0.333333 0.666667 0 0.333333 0.750000 0 0.333333 0.833333 0 0.333333 0.916667 0 0.333333 1.000000 0 0.341666 0 0 0.341666 0.083333 0 0.341666 0.166667 0 0.341666 0.250000 0 0.341666 0.333333 0 0.341666 0.416667 0 0.341666 0.500000 0 0.341666 0.583333 0 0.341666 0.666667 0 0.341666 0.750000 0 0.341666 0.833333 0 0.341666 0.916667 0 0.341666 1.000000 0 0.350000 0 0 0.350000 0.083333 0 0.350000 0.166667 0 0.350000 0.250000 0 0.350000 0.333333 0 0.350000 0.416667 0 0.350000 0.500000 0 0.350000 0.583333 0 0.350000 0.666667 0 0.350000 0.750000 0 0.350000 0.833333 0 0.350000 0.916667 0 0.350000 1.000000 0 0.358333 0 0 0.358333 0.083333 0 0.358333 0.166667 0 0.358333 0.250000 0 0.358333 0.333333 0 0.358333 0.416667 0 0.358333 0.500000 0 0.358333 0.583333 0 0.358333 0.666667 0 0.358333 0.750000 0 0.358333 0.833333 0 0.358333 0.916667 0 0.358333 1.000000 0 0.366666 0 0 0.366666 0.083333 0 0.366666 0.166667 0 0.366666 0.250000 0 0.366666 0.333333 0 0.366666 0.416667 0 0.366666 0.500000 0 0.366666 0.583333 0 0.366666 0.666667 0 0.366666 0.750000 0 0.366666 0.833333 0 0.366666 0.916667 0 0.366666 1.000000 0 0.375000 0 0 0.375000 0.083333 0 0.375000 0.166667 0 0.375000 0.250000 0 0.375000 0.333333 0 0.375000 0.416667 0 0.375000 0.500000 0 0.375000 0.583333 0 0.375000 0.666667 0 0.375000 0.750000 0 0.375000 0.833333 0 0.375000 0.916667 0 0.375000 1.000000 0 0.383333 0 0 0.383333 0.083333 0 0.383333 0.166667 0 0.383333 0.250000 0 0.383333 0.333333 0 0.383333 0.416667 0 0.383333 0.500000 0 0.383333 0.583333 0 0.383333 0.666667 0 0.383333 0.750000 0 0.383333 0.833333 0 0.383333 0.916667 0 0.383333 1.000000 0 0.391666 0 0 0.391666 0.083333 0 0.391666 0.166667 0 0.391666 0.250000 0 0.391666 0.333333 0 0.391666 0.416667 0 0.391666 0.500000 0 0.391666 0.583333 0 0.391666 0.666667 0 0.391666 0.750000 0 0.391666 0.833333 0 0.391666 0.916667 0 0.391666 1.000000 0 0.400000 0 0 0.400000 0.083333 0 0.400000 0.166667 0 0.400000 0.250000 0 0.400000 0.333333 0 0.400000 0.416667 0 0.400000 0.500000 0 0.400000 0.583333 0 0.400000 0.666667 0 0.400000 0.750000 0 0.400000 0.833333 0 0.400000 0.916667 0 0.400000 1.000000 0 0.408333 0 0 0.408333 0.083333 0 0.408333 0.166667 0 0.408333 0.250000 0 0.408333 0.333333 0 0.408333 0.416667 0 0.408333 0.500000 0 0.408333 0.583333 0 0.408333 0.666667 0 0.408333 0.750000 0 0.408333 0.833333 0 0.408333 0.916667 0 0.408333 1.000000 0 0.416666 0 0 0.416666 0.083333 0 0.416666 0.166667 0 0.416666 0.250000 0 0.416666 0.333333 0 0.416666 0.416667 0 0.416666 0.500000 0 0.416666 0.583333 0 0.416666 0.666667 0 0.416666 0.750000 0 0.416666 0.833333 0 0.416666 0.916667 0 0.416666 1.000000 0 0.425000 0 0 0.425000 0.083333 0 0.425000 0.166667 0 0.425000 0.250000 0 0.425000 0.333333 0 0.425000 0.416667 0 0.425000 0.500000 0 0.425000 0.583333 0 0.425000 0.666667 0 0.425000 0.750000 0 0.425000 0.833333 0 0.425000 0.916667 0 0.425000 1.000000 0 0.433333 0 0 0.433333 0.083333 0 0.433333 0.166667 0 0.433333 0.250000 0 0.433333 0.333333 0 0.433333 0.416667 0 0.433333 0.500000 0 0.433333 0.583333 0 0.433333 0.666667 0 0.433333 0.750000 0 0.433333 0.833333 0 0.433333 0.916667 0 0.433333 1.000000 0 0.441666 0 0 0.441666 0.083333 0 0.441666 0.166667 0 0.441666 0.250000 0 0.441666 0.333333 0 0.441666 0.416667 0 0.441666 0.500000 0 0.441666 0.583333 0 0.441666 0.666667 0 0.441666 0.750000 0 0.441666 0.833333 0 0.441666 0.916667 0 0.441666 1.000000 0 0.450000 0 0 0.450000 0.083333 0 0.450000 0.166667 0 0.450000 0.250000 0 0.450000 0.333333 0 0.450000 0.416667 0 0.450000 0.500000 0 0.450000 0.583333 0 0.450000 0.666667 0 0.450000 0.750000 0 0.450000 0.833333 0 0.450000 0.916667 0 0.450000 1.000000 0 0.458333 0 0 0.458333 0.083333 0 0.458333 0.166667 0 0.458333 0.250000 0 0.458333 0.333333 0 0.458333 0.416667 0 0.458333 0.500000 0 0.458333 0.583333 0 0.458333 0.666667 0 0.458333 0.750000 0 0.458333 0.833333 0 0.458333 0.916667 0 0.458333 1.000000 0 0.466666 0 0 0.466666 0.083333 0 0.466666 0.166667 0 0.466666 0.250000 0 0.466666 0.333333 0 0.466666 0.416667 0 0.466666 0.500000 0 0.466666 0.583333 0 0.466666 0.666667 0 0.466666 0.750000 0 0.466666 0.833333 0 0.466666 0.916667 0 0.466666 1.000000 0 0.475000 0 0 0.475000 0.083333 0 0.475000 0.166667 0 0.475000 0.250000 0 0.475000 0.333333 0 0.475000 0.416667 0 0.475000 0.500000 0 0.475000 0.583333 0 0.475000 0.666667 0 0.475000 0.750000 0 0.475000 0.833333 0 0.475000 0.916667 0 0.475000 1.000000 0 0.483333 0 0 0.483333 0.083333 0 0.483333 0.166667 0 0.483333 0.250000 0 0.483333 0.333333 0 0.483333 0.416667 0 0.483333 0.500000 0 0.483333 0.583333 0 0.483333 0.666667 0 0.483333 0.750000 0 0.483333 0.833333 0 0.483333 0.916667 0 0.483333 1.000000 0 0.491666 0 0 0.491666 0.083333 0 0.491666 0.166667 0 0.491666 0.250000 0 0.491666 0.333333 0 0.491666 0.416667 0 0.491666 0.500000 0 0.491666 0.583333 0 0.491666 0.666667 0 0.491666 0.750000 0 0.491666 0.833333 0 0.491666 0.916667 0 0.491666 1.000000 0 0.500000 0 0 0.500000 0.083333 0 0.500000 0.166667 0 0.500000 0.250000 0 0.500000 0.333333 0 0.500000 0.416667 0 0.500000 0.500000 0 0.500000 0.583333 0 0.500000 0.666667 0 0.500000 0.750000 0 0.500000 0.833333 0 0.500000 0.916667 0 0.500000 1.000000 0 0.508333 0 0 0.508333 0.083333 0 0.508333 0.166667 0 0.508333 0.250000 0 0.508333 0.333333 0 0.508333 0.416667 0 0.508333 0.500000 0 0.508333 0.583333 0 0.508333 0.666667 0 0.508333 0.750000 0 0.508333 0.833333 0 0.508333 0.916667 0 0.508333 1.000000 0 0.516666 0 0 0.516666 0.083333 0 0.516666 0.166667 0 0.516666 0.250000 0 0.516666 0.333333 0 0.516666 0.416667 0 0.516666 0.500000 0 0.516666 0.583333 0 0.516666 0.666667 0 0.516666 0.750000 0 0.516666 0.833333 0 0.516666 0.916667 0 0.516666 1.000000 0 0.525000 0 0 0.525000 0.083333 0 0.525000 0.166667 0 0.525000 0.250000 0 0.525000 0.333333 0 0.525000 0.416667 0 0.525000 0.500000 0 0.525000 0.583333 0 0.525000 0.666667 0 0.525000 0.750000 0 0.525000 0.833333 0 0.525000 0.916667 0 0.525000 1.000000 0 0.533333 0 0 0.533333 0.083333 0 0.533333 0.166667 0 0.533333 0.250000 0 0.533333 0.333333 0 0.533333 0.416667 0 0.533333 0.500000 0 0.533333 0.583333 0 0.533333 0.666667 0 0.533333 0.750000 0 0.533333 0.833333 0 0.533333 0.916667 0 0.533333 1.000000 0 0.541666 0 0 0.541666 0.083333 0 0.541666 0.166667 0 0.541666 0.250000 0 0.541666 0.333333 0 0.541666 0.416667 0 0.541666 0.500000 0 0.541666 0.583333 0 0.541666 0.666667 0 0.541666 0.750000 0 0.541666 0.833333 0 0.541666 0.916667 0 0.541666 1.000000 0 0.550000 0 0 0.550000 0.083333 0 0.550000 0.166667 0 0.550000 0.250000 0 0.550000 0.333333 0 0.550000 0.416667 0 0.550000 0.500000 0 0.550000 0.583333 0 0.550000 0.666667 0 0.550000 0.750000 0 0.550000 0.833333 0 0.550000 0.916667 0 0.550000 1.000000 0 0.558333 0 0 0.558333 0.083333 0 0.558333 0.166667 0 0.558333 0.250000 0 0.558333 0.333333 0 0.558333 0.416667 0 0.558333 0.500000 0 0.558333 0.583333 0 0.558333 0.666667 0 0.558333 0.750000 0 0.558333 0.833333 0 0.558333 0.916667 0 0.558333 1.000000 0 0.566666 0 0 0.566666 0.083333 0 0.566666 0.166667 0 0.566666 0.250000 0 0.566666 0.333333 0 0.566666 0.416667 0 0.566666 0.500000 0 0.566666 0.583333 0 0.566666 0.666667 0 0.566666 0.750000 0 0.566666 0.833333 0 0.566666 0.916667 0 0.566666 1.000000 0 0.575000 0 0 0.575000 0.083333 0 0.575000 0.166667 0 0.575000 0.250000 0 0.575000 0.333333 0 0.575000 0.416667 0 0.575000 0.500000 0 0.575000 0.583333 0 0.575000 0.666667 0 0.575000 0.750000 0 0.575000 0.833333 0 0.575000 0.916667 0 0.575000 1.000000 0 0.583333 0 0 0.583333 0.083333 0 0.583333 0.166667 0 0.583333 0.250000 0 0.583333 0.333333 0 0.583333 0.416667 0 0.583333 0.500000 0 0.583333 0.583333 0 0.583333 0.666667 0 0.583333 0.750000 0 0.583333 0.833333 0 0.583333 0.916667 0 0.583333 1.000000 0 0.591666 0 0 0.591666 0.083333 0 0.591666 0.166667 0 0.591666 0.250000 0 0.591666 0.333333 0 0.591666 0.416667 0 0.591666 0.500000 0 0.591666 0.583333 0 0.591666 0.666667 0 0.591666 0.750000 0 0.591666 0.833333 0 0.591666 0.916667 0 0.591666 1.000000 0 0.599999 0 0 0.599999 0.083333 0 0.599999 0.166667 0 0.599999 0.250000 0 0.599999 0.333333 0 0.599999 0.416667 0 0.599999 0.500000 0 0.599999 0.583333 0 0.599999 0.666667 0 0.599999 0.750000 0 0.599999 0.833333 0 0.599999 0.916667 0 0.599999 1.000000 0 0.608333 0 0 0.608333 0.083333 0 0.608333 0.166667 0 0.608333 0.250000 0 0.608333 0.333333 0 0.608333 0.416667 0 0.608333 0.500000 0 0.608333 0.583333 0 0.608333 0.666667 0 0.608333 0.750000 0 0.608333 0.833333 0 0.608333 0.916667 0 0.608333 1.000000 0 0.616666 0 0 0.616666 0.083333 0 0.616666 0.166667 0 0.616666 0.250000 0 0.616666 0.333333 0 0.616666 0.416667 0 0.616666 0.500000 0 0.616666 0.583333 0 0.616666 0.666667 0 0.616666 0.750000 0 0.616666 0.833333 0 0.616666 0.916667 0 0.616666 1.000000 0 0.624999 0 0 0.624999 0.083333 0 0.624999 0.166667 0 0.624999 0.250000 0 0.624999 0.333333 0 0.624999 0.416667 0 0.624999 0.500000 0 0.624999 0.583333 0 0.624999 0.666667 0 0.624999 0.750000 0 0.624999 0.833333 0 0.624999 0.916667 0 0.624999 1.000000 0 0.633333 0 0 0.633333 0.083333 0 0.633333 0.166667 0 0.633333 0.250000 0 0.633333 0.333333 0 0.633333 0.416667 0 0.633333 0.500000 0 0.633333 0.583333 0 0.633333 0.666667 0 0.633333 0.750000 0 0.633333 0.833333 0 0.633333 0.916667 0 0.633333 1.000000 0 0.641666 0 0 0.641666 0.083333 0 0.641666 0.166667 0 0.641666 0.250000 0 0.641666 0.333333 0 0.641666 0.416667 0 0.641666 0.500000 0 0.641666 0.583333 0 0.641666 0.666667 0 0.641666 0.750000 0 0.641666 0.833333 0 0.641666 0.916667 0 0.641666 1.000000 0 0.649999 0 0 0.649999 0.083333 0 0.649999 0.166667 0 0.649999 0.250000 0 0.649999 0.333333 0 0.649999 0.416667 0 0.649999 0.500000 0 0.649999 0.583333 0 0.649999 0.666667 0 0.649999 0.750000 0 0.649999 0.833333 0 0.649999 0.916667 0 0.649999 1.000000 0 0.658333 0 0 0.658333 0.083333 0 0.658333 0.166667 0 0.658333 0.250000 0 0.658333 0.333333 0 0.658333 0.416667 0 0.658333 0.500000 0 0.658333 0.583333 0 0.658333 0.666667 0 0.658333 0.750000 0 0.658333 0.833333 0 0.658333 0.916667 0 0.658333 1.000000 0 0.666666 0 0 0.666666 0.083333 0 0.666666 0.166667 0 0.666666 0.250000 0 0.666666 0.333333 0 0.666666 0.416667 0 0.666666 0.500000 0 0.666666 0.583333 0 0.666666 0.666667 0 0.666666 0.750000 0 0.666666 0.833333 0 0.666666 0.916667 0 0.666666 1.000000 0 0.675000 0 0 0.675000 0.083333 0 0.675000 0.166667 0 0.675000 0.250000 0 0.675000 0.333333 0 0.675000 0.416667 0 0.675000 0.500000 0 0.675000 0.583333 0 0.675000 0.666667 0 0.675000 0.750000 0 0.675000 0.833333 0 0.675000 0.916667 0 0.675000 1.000000 0 0.683333 0 0 0.683333 0.083333 0 0.683333 0.166667 0 0.683333 0.250000 0 0.683333 0.333333 0 0.683333 0.416667 0 0.683333 0.500000 0 0.683333 0.583333 0 0.683333 0.666667 0 0.683333 0.750000 0 0.683333 0.833333 0 0.683333 0.916667 0 0.683333 1.000000 0 0.691666 0 0 0.691666 0.083333 0 0.691666 0.166667 0 0.691666 0.250000 0 0.691666 0.333333 0 0.691666 0.416667 0 0.691666 0.500000 0 0.691666 0.583333 0 0.691666 0.666667 0 0.691666 0.750000 0 0.691666 0.833333 0 0.691666 0.916667 0 0.691666 1.000000 0 0.700000 0 0 0.700000 0.083333 0 0.700000 0.166667 0 0.700000 0.250000 0 0.700000 0.333333 0 0.700000 0.416667 0 0.700000 0.500000 0 0.700000 0.583333 0 0.700000 0.666667 0 0.700000 0.750000 0 0.700000 0.833333 0 0.700000 0.916667 0 0.700000 1.000000 0 0.708333 0 0 0.708333 0.083333 0 0.708333 0.166667 0 0.708333 0.250000 0 0.708333 0.333333 0 0.708333 0.416667 0 0.708333 0.500000 0 0.708333 0.583333 0 0.708333 0.666667 0 0.708333 0.750000 0 0.708333 0.833333 0 0.708333 0.916667 0 0.708333 1.000000 0 0.716666 0 0 0.716666 0.083333 0 0.716666 0.166667 0 0.716666 0.250000 0 0.716666 0.333333 0 0.716666 0.416667 0 0.716666 0.500000 0 0.716666 0.583333 0 0.716666 0.666667 0 0.716666 0.750000 0 0.716666 0.833333 0 0.716666 0.916667 0 0.716666 1.000000 0 0.725000 0 0 0.725000 0.083333 0 0.725000 0.166667 0 0.725000 0.250000 0 0.725000 0.333333 0 0.725000 0.416667 0 0.725000 0.500000 0 0.725000 0.583333 0 0.725000 0.666667 0 0.725000 0.750000 0 0.725000 0.833333 0 0.725000 0.916667 0 0.725000 1.000000 0 0.733333 0 0 0.733333 0.083333 0 0.733333 0.166667 0 0.733333 0.250000 0 0.733333 0.333333 0 0.733333 0.416667 0 0.733333 0.500000 0 0.733333 0.583333 0 0.733333 0.666667 0 0.733333 0.750000 0 0.733333 0.833333 0 0.733333 0.916667 0 0.733333 1.000000 0 0.741666 0 0 0.741666 0.083333 0 0.741666 0.166667 0 0.741666 0.250000 0 0.741666 0.333333 0 0.741666 0.416667 0 0.741666 0.500000 0 0.741666 0.583333 0 0.741666 0.666667 0 0.741666 0.750000 0 0.741666 0.833333 0 0.741666 0.916667 0 0.741666 1.000000 0 0.750000 0 0 0.750000 0.083333 0 0.750000 0.166667 0 0.750000 0.250000 0 0.750000 0.333333 0 0.750000 0.416667 0 0.750000 0.500000 0 0.750000 0.583333 0 0.750000 0.666667 0 0.750000 0.750000 0 0.750000 0.833333 0 0.750000 0.916667 0 0.750000 1.000000 0 0.758333 0 0 0.758333 0.083333 0 0.758333 0.166667 0 0.758333 0.250000 0 0.758333 0.333333 0 0.758333 0.416667 0 0.758333 0.500000 0 0.758333 0.583333 0 0.758333 0.666667 0 0.758333 0.750000 0 0.758333 0.833333 0 0.758333 0.916667 0 0.758333 1.000000 0 0.766667 0 0 0.766667 0.083333 0 0.766667 0.166667 0 0.766667 0.250000 0 0.766667 0.333333 0 0.766667 0.416667 0 0.766667 0.500000 0 0.766667 0.583333 0 0.766667 0.666667 0 0.766667 0.750000 0 0.766667 0.833333 0 0.766667 0.916667 0 0.766667 1.000000 0 0.775000 0 0 0.775000 0.083333 0 0.775000 0.166667 0 0.775000 0.250000 0 0.775000 0.333333 0 0.775000 0.416667 0 0.775000 0.500000 0 0.775000 0.583333 0 0.775000 0.666667 0 0.775000 0.750000 0 0.775000 0.833333 0 0.775000 0.916667 0 0.775000 1.000000 0 0.783333 0 0 0.783333 0.083333 0 0.783333 0.166667 0 0.783333 0.250000 0 0.783333 0.333333 0 0.783333 0.416667 0 0.783333 0.500000 0 0.783333 0.583333 0 0.783333 0.666667 0 0.783333 0.750000 0 0.783333 0.833333 0 0.783333 0.916667 0 0.783333 1.000000 0 0.791667 0 0 0.791667 0.083333 0 0.791667 0.166667 0 0.791667 0.250000 0 0.791667 0.333333 0 0.791667 0.416667 0 0.791667 0.500000 0 0.791667 0.583333 0 0.791667 0.666667 0 0.791667 0.750000 0 0.791667 0.833333 0 0.791667 0.916667 0 0.791667 1.000000 0 0.800000 0 0 0.800000 0.083333 0 0.800000 0.166667 0 0.800000 0.250000 0 0.800000 0.333333 0 0.800000 0.416667 0 0.800000 0.500000 0 0.800000 0.583333 0 0.800000 0.666667 0 0.800000 0.750000 0 0.800000 0.833333 0 0.800000 0.916667 0 0.800000 1.000000 0 0.808333 0 0 0.808333 0.083333 0 0.808333 0.166667 0 0.808333 0.250000 0 0.808333 0.333333 0 0.808333 0.416667 0 0.808333 0.500000 0 0.808333 0.583333 0 0.808333 0.666667 0 0.808333 0.750000 0 0.808333 0.833333 0 0.808333 0.916667 0 0.808333 1.000000 0 0.816667 0 0 0.816667 0.083333 0 0.816667 0.166667 0 0.816667 0.250000 0 0.816667 0.333333 0 0.816667 0.416667 0 0.816667 0.500000 0 0.816667 0.583333 0 0.816667 0.666667 0 0.816667 0.750000 0 0.816667 0.833333 0 0.816667 0.916667 0 0.816667 1.000000 0 0.825000 0 0 0.825000 0.083333 0 0.825000 0.166667 0 0.825000 0.250000 0 0.825000 0.333333 0 0.825000 0.416667 0 0.825000 0.500000 0 0.825000 0.583333 0 0.825000 0.666667 0 0.825000 0.750000 0 0.825000 0.833333 0 0.825000 0.916667 0 0.825000 1.000000 0 0.833333 0 0 0.833333 0.083333 0 0.833333 0.166667 0 0.833333 0.250000 0 0.833333 0.333333 0 0.833333 0.416667 0 0.833333 0.500000 0 0.833333 0.583333 0 0.833333 0.666667 0 0.833333 0.750000 0 0.833333 0.833333 0 0.833333 0.916667 0 0.833333 1.000000 0 0.841667 0 0 0.841667 0.083333 0 0.841667 0.166667 0 0.841667 0.250000 0 0.841667 0.333333 0 0.841667 0.416667 0 0.841667 0.500000 0 0.841667 0.583333 0 0.841667 0.666667 0 0.841667 0.750000 0 0.841667 0.833333 0 0.841667 0.916667 0 0.841667 1.000000 0 0.850000 0 0 0.850000 0.083333 0 0.850000 0.166667 0 0.850000 0.250000 0 0.850000 0.333333 0 0.850000 0.416667 0 0.850000 0.500000 0 0.850000 0.583333 0 0.850000 0.666667 0 0.850000 0.750000 0 0.850000 0.833333 0 0.850000 0.916667 0 0.850000 1.000000 0 0.858334 0 0 0.858334 0.083333 0 0.858334 0.166667 0 0.858334 0.250000 0 0.858334 0.333333 0 0.858334 0.416667 0 0.858334 0.500000 0 0.858334 0.583333 0 0.858334 0.666667 0 0.858334 0.750000 0 0.858334 0.833333 0 0.858334 0.916667 0 0.858334 1.000000 0 0.866667 0 0 0.866667 0.083333 0 0.866667 0.166667 0 0.866667 0.250000 0 0.866667 0.333333 0 0.866667 0.416667 0 0.866667 0.500000 0 0.866667 0.583333 0 0.866667 0.666667 0 0.866667 0.750000 0 0.866667 0.833333 0 0.866667 0.916667 0 0.866667 1.000000 0 0.875000 0 0 0.875000 0.083333 0 0.875000 0.166667 0 0.875000 0.250000 0 0.875000 0.333333 0 0.875000 0.416667 0 0.875000 0.500000 0 0.875000 0.583333 0 0.875000 0.666667 0 0.875000 0.750000 0 0.875000 0.833333 0 0.875000 0.916667 0 0.875000 1.000000 0 0.883334 0 0 0.883334 0.083333 0 0.883334 0.166667 0 0.883334 0.250000 0 0.883334 0.333333 0 0.883334 0.416667 0 0.883334 0.500000 0 0.883334 0.583333 0 0.883334 0.666667 0 0.883334 0.750000 0 0.883334 0.833333 0 0.883334 0.916667 0 0.883334 1.000000 0 0.891667 0 0 0.891667 0.083333 0 0.891667 0.166667 0 0.891667 0.250000 0 0.891667 0.333333 0 0.891667 0.416667 0 0.891667 0.500000 0 0.891667 0.583333 0 0.891667 0.666667 0 0.891667 0.750000 0 0.891667 0.833333 0 0.891667 0.916667 0 0.891667 1.000000 0 0.900000 0 0 0.900000 0.083333 0 0.900000 0.166667 0 0.900000 0.250000 0 0.900000 0.333333 0 0.900000 0.416667 0 0.900000 0.500000 0 0.900000 0.583333 0 0.900000 0.666667 0 0.900000 0.750000 0 0.900000 0.833333 0 0.900000 0.916667 0 0.900000 1.000000 0 0.908334 0 0 0.908334 0.083333 0 0.908334 0.166667 0 0.908334 0.250000 0 0.908334 0.333333 0 0.908334 0.416667 0 0.908334 0.500000 0 0.908334 0.583333 0 0.908334 0.666667 0 0.908334 0.750000 0 0.908334 0.833333 0 0.908334 0.916667 0 0.908334 1.000000 0 0.916667 0 0 0.916667 0.083333 0 0.916667 0.166667 0 0.916667 0.250000 0 0.916667 0.333333 0 0.916667 0.416667 0 0.916667 0.500000 0 0.916667 0.583333 0 0.916667 0.666667 0 0.916667 0.750000 0 0.916667 0.833333 0 0.916667 0.916667 0 0.916667 1.000000 0 0.925000 0 0 0.925000 0.083333 0 0.925000 0.166667 0 0.925000 0.250000 0 0.925000 0.333333 0 0.925000 0.416667 0 0.925000 0.500000 0 0.925000 0.583333 0 0.925000 0.666667 0 0.925000 0.750000 0 0.925000 0.833333 0 0.925000 0.916667 0 0.925000 1.000000 0 0.933334 0 0 0.933334 0.083333 0 0.933334 0.166667 0 0.933334 0.250000 0 0.933334 0.333333 0 0.933334 0.416667 0 0.933334 0.500000 0 0.933334 0.583333 0 0.933334 0.666667 0 0.933334 0.750000 0 0.933334 0.833333 0 0.933334 0.916667 0 0.933334 1.000000 0 0.941667 0 0 0.941667 0.083333 0 0.941667 0.166667 0 0.941667 0.250000 0 0.941667 0.333333 0 0.941667 0.416667 0 0.941667 0.500000 0 0.941667 0.583333 0 0.941667 0.666667 0 0.941667 0.750000 0 0.941667 0.833333 0 0.941667 0.916667 0 0.941667 1.000000 0 0.950001 0 0 0.950001 0.083333 0 0.950001 0.166667 0 0.950001 0.250000 0 0.950001 0.333333 0 0.950001 0.416667 0 0.950001 0.500000 0 0.950001 0.583333 0 0.950001 0.666667 0 0.950001 0.750000 0 0.950001 0.833333 0 0.950001 0.916667 0 0.950001 1.000000 0 0.958334 0 0 0.958334 0.083333 0 0.958334 0.166667 0 0.958334 0.250000 0 0.958334 0.333333 0 0.958334 0.416667 0 0.958334 0.500000 0 0.958334 0.583333 0 0.958334 0.666667 0 0.958334 0.750000 0 0.958334 0.833333 0 0.958334 0.916667 0 0.958334 1.000000 0 0.966667 0 0 0.966667 0.083333 0 0.966667 0.166667 0 0.966667 0.250000 0 0.966667 0.333333 0 0.966667 0.416667 0 0.966667 0.500000 0 0.966667 0.583333 0 0.966667 0.666667 0 0.966667 0.750000 0 0.966667 0.833333 0 0.966667 0.916667 0 0.966667 1.000000 0 0.975001 0 0 0.975001 0.083333 0 0.975001 0.166667 0 0.975001 0.250000 0 0.975001 0.333333 0 0.975001 0.416667 0 0.975001 0.500000 0 0.975001 0.583333 0 0.975001 0.666667 0 0.975001 0.750000 0 0.975001 0.833333 0 0.975001 0.916667 0 0.975001 1.000000 0 0.983334 0 0 0.983334 0.083333 0 0.983334 0.166667 0 0.983334 0.250000 0 0.983334 0.333333 0 0.983334 0.416667 0 0.983334 0.500000 0 0.983334 0.583333 0 0.983334 0.666667 0 0.983334 0.750000 0 0.983334 0.833333 0 0.983334 0.916667 0 0.983334 1.000000 0 0.991667 0 0 0.991667 0.083333 0 0.991667 0.166667 0 0.991667 0.250000 0 0.991667 0.333333 0 0.991667 0.416667 0 0.991667 0.500000 0 0.991667 0.583333 0 0.991667 0.666667 0 0.991667 0.750000 0 0.991667 0.833333 0 0.991667 0.916667 0 0.991667 1.000000 0 1.000001 0 0 1.000001 0.083333 0 1.000001 0.166667 0 1.000001 0.250000 0 1.000001 0.333333 0 1.000001 0.416667 0 1.000001 0.500000 0 1.000001 0.583333 0 1.000001 0.666667 0 1.000001 0.750000 0 1.000001 0.833333 0 1.000001 0.916667 0 1.000001 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="1573" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="2880">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 12 1 13 13 2 14 0 0 0 13 2 14 1 3 1 1 3 1 13 2 14 14 4 15 1 3 1 14 4 15 2 5 2 2 5 2 14 4 15 15 6 16 2 5 2 15 6 16 3 7 3 3 7 3 15 6 16 16 8 17 3 7 3 16 8 17 4 9 4 4 9 4 16 8 17 17 10 18 4 9 4 17 10 18 5 11 5 5 11 5 17 10 18 18 12 19 5 11 5 18 12 19 6 13 6 6 13 6 18 12 19 19 14 20 6 13 6 19 14 20 7 15 7 7 15 7 19 14 20 20 16 21 7 15 7 20 16 21 8 17 8 8 17 8 20 16 21 21 18 22 8 17 8 21 18 22 9 19 9 9 19 9 21 18 22 22 20 23 9 19 9 22 20 23 10 21 10 10 21 10 22 20 23 23 22 24 10 21 10 23 22 24 11 23 11 11 23 11 23 22 24 12 1 25 11 23 11 12 1 25 0 0 12 12 1 13 24 24 26 25 25 27 12 1 13 25 25 27 13 2 14 13 2 14 25 25 27 26 26 28 13 2 14 26 26 28 14 4 15 14 4 15 26 26 28 27 27 29 14 4 15 27 27 29 15 6 16 15 6 16 27 27 29 28 28 30 15 6 16 28 28 30 16 8 17 16 8 17 28 28 30 29 29 31 16 8 17 29 29 31 17 10 18 17 10 18 29 29 31 30 30 32 17 10 18 30 30 32 18 12 19 18 12 19 30 30 32 31 31 33 18 12 19 31 31 33 19 14 20 19 14 20 31 31 33 32 32 34 19 14 20 32 32 34 20 16 21 20 16 21 32 32 34 33 33 35 20 16 21 33 33 35 21 18 22 21 18 22 33 33 35 34 34 36 21 18 22 34 34 36 22 20 23 22 20 23 34 34 36 35 35 37 22 20 23 35 35 37 23 22 24 23 22 24 35 35 37 24 24 38 23 22 24 24 24 38 12 1 25 24 24 26 36 36 39 37 37 40 24 24 26 37 37 40 25 25 27 25 25 27 37 37 40 38 38 41 25 25 27 38 38 41 26 26 28 26 26 28 38 38 41 39 39 42 26 26 28 39 39 42 27 27 29 27 27 29 39 39 42 40 40 43 27 27 29 40 40 43 28 28 30 28 28 30 40 40 43 41 41 44 28 28 30 41 41 44 29 29 31 29 29 31 41 41 44 42 42 45 29 29 31 42 42 45 30 30 32 30 30 32 42 42 45 43 43 46 30 30 32 43 43 46 31 31 33 31 31 33 43 43 46 44 44 47 31 31 33 44 44 47 32 32 34 32 32 34 44 44 47 45 45 48 32 32 34 45 45 48 33 33 35 33 33 35 45 45 48 46 46 49 33 33 35 46 46 49 34 34 36 34 34 36 46 46 49 47 47 50 34 34 36 47 47 50 35 35 37 35 35 37 47 47 50 36 36 51 35 35 37 36 36 51 24 24 38 36 36 39 48 48 52 49 49 53 36 36 39 49 49 53 37 37 40 37 37 40 49 49 53 50 50 54 37 37 40 50 50 54 38 38 41 38 38 41 50 50 54 51 51 55 38 38 41 51 51 55 39 39 42 39 39 42 51 51 55 52 52 56 39 39 42 52 52 56 40 40 43 40 40 43 52 52 56 53 53 57 40 40 43 53 53 57 41 41 44 41 41 44 53 53 57 54 54 58 41 41 44 54 54 58 42 42 45 42 42 45 54 54 58 55 55 59 42 42 45 55 55 59 43 43 46 43 43 46 55 55 59 56 56 60 43 43 46 56 56 60 44 44 47 44 44 47 56 56 60 57 57 61 44 44 47 57 57 61 45 45 48 45 45 48 57 57 61 58 58 62 45 45 48 58 58 62 46 46 49 46 46 49 58 58 62 59 59 63 46 46 49 59 59 63 47 47 50 47 47 50 59 59 63 48 48 64 47 47 50 48 48 64 36 36 51 48 48 52 60 60 65 61 61 66 48 48 52 61 61 66 49 49 53 49 49 53 61 61 66 62 62 67 49 49 53 62 62 67 50 50 54 50 50 54 62 62 67 63 63 68 50 50 54 63 63 68 51 51 55 51 51 55 63 63 68 64 64 69 51 51 55 64 64 69 52 52 56 52 52 56 64 64 69 65 65 70 52 52 56 65 65 70 53 53 57 53 53 57 65 65 70 66 66 71 53 53 57 66 66 71 54 54 58 54 54 58 66 66 71 67 67 72 54 54 58 67 67 72 55 55 59 55 55 59 67 67 72 68 68 73 55 55 59 68 68 73 56 56 60 56 56 60 68 68 73 69 69 74 56 56 60 69 69 74 57 57 61 57 57 61 69 69 74 70 70 75 57 57 61 70 70 75 58 58 62 58 58 62 70 70 75 71 71 76 58 58 62 71 71 76 59 59 63 59 59 63 71 71 76 60 60 77 59 59 63 60 60 77 48 48 64 60 60 65 72 72 78 73 73 79 60 60 65 73 73 79 61 61 66 61 61 66 73 73 79 74 74 80 61 61 66 74 74 80 62 62 67 62 62 67 74 74 80 75 75 81 62 62 67 75 75 81 63 63 68 63 63 68 75 75 81 76 76 82 63 63 68 76 76 82 64 64 69 64 64 69 76 76 82 77 77 83 64 64 69 77 77 83 65 65 70 65 65 70 77 77 83 78 78 84 65 65 70 78 78 84 66 66 71 66 66 71 78 78 84 79 79 85 66 66 71 79 79 85 67 67 72 67 67 72 79 79 85 80 80 86 67 67 72 80 80 86 68 68 73 68 68 73 80 80 86 81 81 87 68 68 73 81 81 87 69 69 74 69 69 74 81 81 87 82 82 88 69 69 74 82 82 88 70 70 75 70 70 75 82 82 88 83 83 89 70 70 75 83 83 89 71 71 76 71 71 76 83 83 89 72 72 90 71 71 76 72 72 90 60 60 77 72 72 78 84 84 91 85 85 92 72 72 78 85 85 92 73 73 79 73 73 79 85 85 92 86 86 93 73 73 79 86 86 93 74 74 80 74 74 80 86 86 93 87 87 94 74 74 80 87 87 94 75 75 81 75 75 81 87 87 94 88 88 95 75 75 81 88 88 95 76 76 82 76 76 82 88 88 95 89 89 96 76 76 82 89 89 96 77 77 83 77 77 83 89 89 96 90 90 97 77 77 83 90 90 97 78 78 84 78 78 84 90 90 97 91 91 98 78 78 84 91 91 98 79 79 85 79 79 85 91 91 98 92 92 99 79 79 85 92 92 99 80 80 86 80 80 86 92 92 99 93 93 100 80 80 86 93 93 100 81 81 87 81 81 87 93 93 100 94 94 101 81 81 87 94 94 101 82 82 88 82 82 88 94 94 101 95 95 102 82 82 88 95 95 102 83 83 89 83 83 89 95 95 102 84 84 103 83 83 89 84 84 103 72 72 90 84 84 91 96 96 104 97 97 105 84 84 91 97 97 105 85 85 92 85 85 92 97 97 105 98 98 106 85 85 92 98 98 106 86 86 93 86 86 93 98 98 106 99 99 107 86 86 93 99 99 107 87 87 94 87 87 94 99 99 107 100 100 108 87 87 94 100 100 108 88 88 95 88 88 95 100 100 108 101 101 109 88 88 95 101 101 109 89 89 96 89 89 96 101 101 109 102 102 110 89 89 96 102 102 110 90 90 97 90 90 97 102 102 110 103 103 111 90 90 97 103 103 111 91 91 98 91 91 98 103 103 111 104 104 112 91 91 98 104 104 112 92 92 99 92 92 99 104 104 112 105 105 113 92 92 99 105 105 113 93 93 100 93 93 100 105 105 113 106 106 114 93 93 100 106 106 114 94 94 101 94 94 101 106 106 114 107 107 115 94 94 101 107 107 115 95 95 102 95 95 102 107 107 115 96 96 116 95 95 102 96 96 116 84 84 103 96 96 104 108 108 117 109 109 118 96 96 104 109 109 118 97 97 105 97 97 105 109 109 118 110 110 119 97 97 105 110 110 119 98 98 106 98 98 106 110 110 119 111 111 120 98 98 106 111 111 120 99 99 107 99 99 107 111 111 120 112 112 121 99 99 107 112 112 121 100 100 108 100 100 108 112 112 121 113 113 122 100 100 108 113 113 122 101 101 109 101 101 109 113 113 122 114 114 123 101 101 109 114 114 123 102 102 110 102 102 110 114 114 123 115 115 124 102 102 110 115 115 124 103 103 111 103 103 111 115 115 124 116 116 125 103 103 111 116 116 125 104 104 112 104 104 112 116 116 125 117 117 126 104 104 112 117 117 126 105 105 113 105 105 113 117 117 126 118 118 127 105 105 113 118 118 127 106 106 114 106 106 114 118 118 127 119 119 128 106 106 114 119 119 128 107 107 115 107 107 115 119 119 128 108 108 129 107 107 115 108 108 129 96 96 116 108 108 117 120 120 130 121 121 131 108 108 117 121 121 131 109 109 118 109 109 118 121 121 131 122 122 132 109 109 118 122 122 132 110 110 119 110 110 119 122 122 132 123 123 133 110 110 119 123 123 133 111 111 120 111 111 120 123 123 133 124 124 134 111 111 120 124 124 134 112 112 121 112 112 121 124 124 134 125 125 135 112 112 121 125 125 135 113 113 122 113 113 122 125 125 135 126 126 136 113 113 122 126 126 136 114 114 123 114 114 123 126 126 136 127 127 137 114 114 123 127 127 137 115 115 124 115 115 124 127 127 137 128 128 138 115 115 124 128 128 138 116 116 125 116 116 125 128 128 138 129 129 139 116 116 125 129 129 139 117 117 126 117 117 126 129 129 139 130 130 140 117 117 126 130 130 140 118 118 127 118 118 127 130 130 140 131 131 141 118 118 127 131 131 141 119 119 128 119 119 128 131 131 141 120 120 142 119 119 128 120 120 142 108 108 129 120 120 130 132 132 143 133 133 144 120 120 130 133 133 144 121 121 131 121 121 131 133 133 144 134 134 145 121 121 131 134 134 145 122 122 132 122 122 132 134 134 145 135 135 146 122 122 132 135 135 146 123 123 133 123 123 133 135 135 146 136 136 147 123 123 133 136 136 147 124 124 134 124 124 134 136 136 147 137 137 148 124 124 134 137 137 148 125 125 135 125 125 135 137 137 148 138 138 149 125 125 135 138 138 149 126 126 136 126 126 136 138 138 149 139 139 150 126 126 136 139 139 150 127 127 137 127 127 137 139 139 150 140 140 151 127 127 137 140 140 151 128 128 138 128 128 138 140 140 151 141 141 152 128 128 138 141 141 152 129 129 139 129 129 139 141 141 152 142 142 153 129 129 139 142 142 153 130 130 140 130 130 140 142 142 153 143 143 154 130 130 140 143 143 154 131 131 141 131 131 141 143 143 154 132 132 155 131 131 141 132 132 155 120 120 142 132 132 143 144 144 156 145 145 157 132 132 143 145 145 157 133 133 144 133 133 144 145 145 157 146 146 158 133 133 144 146 146 158 134 134 145 134 134 145 146 146 158 147 147 159 134 134 145 147 147 159 135 135 146 135 135 146 147 147 159 148 148 160 135 135 146 148 148 160 136 136 147 136 136 147 148 148 160 149 149 161 136 136 147 149 149 161 137 137 148 137 137 148 149 149 161 150 150 162 137 137 148 150 150 162 138 138 149 138 138 149 150 150 162 151 151 163 138 138 149 151 151 163 139 139 150 139 139 150 151 151 163 152 152 164 139 139 150 152 152 164 140 140 151 140 140 151 152 152 164 153 153 165 140 140 151 153 153 165 141 141 152 141 141 152 153 153 165 154 154 166 141 141 152 154 154 166 142 142 153 142 142 153 154 154 166 155 155 167 142 142 153 155 155 167 143 143 154 143 143 154 155 155 167 144 144 168 143 143 154 144 144 168 132 132 155 144 144 156 156 156 169 157 157 170 144 144 156 157 157 170 145 145 157 145 145 157 157 157 170 158 158 171 145 145 157 158 158 171 146 146 158 146 146 158 158 158 171 159 159 172 146 146 158 159 159 172 147 147 159 147 147 159 159 159 172 160 160 173 147 147 159 160 160 173 148 148 160 148 148 160 160 160 173 161 161 174 148 148 160 161 161 174 149 149 161 149 149 161 161 161 174 162 162 175 149 149 161 162 162 175 150 150 162 150 150 162 162 162 175 163 163 176 150 150 162 163 163 176 151 151 163 151 151 163 163 163 176 164 164 177 151 151 163 164 164 177 152 152 164 152 152 164 164 164 177 165 165 178 152 152 164 165 165 178 153 153 165 153 153 165 165 165 178 166 166 179 153 153 165 166 166 179 154 154 166 154 154 166 166 166 179 167 167 180 154 154 166 167 167 180 155 155 167 155 155 167 167 167 180 156 156 181 155 155 167 156 156 181 144 144 168 156 156 169 168 168 182 169 169 183 156 156 169 169 169 183 157 157 170 157 157 170 169 169 183 170 170 184 157 157 170 170 170 184 158 158 171 158 158 171 170 170 184 171 171 185 158 158 171 171 171 185 159 159 172 159 159 172 171 171 185 172 172 186 159 159 172 172 172 186 160 160 173 160 160 173 172 172 186 173 173 187 160 160 173 173 173 187 161 161 174 161 161 174 173 173 187 174 174 188 161 161 174 174 174 188 162 162 175 162 162 175 174 174 188 175 175 189 162 162 175 175 175 189 163 163 176 163 163 176 175 175 189 176 176 190 163 163 176 176 176 190 164 164 177 164 164 177 176 176 190 177 177 191 164 164 177 177 177 191 165 165 178 165 165 178 177 177 191 178 178 192 165 165 178 178 178 192 166 166 179 166 166 179 178 178 192 179 179 193 166 166 179 179 179 193 167 167 180 167 167 180 179 179 193 168 168 194 167 167 180 168 168 194 156 156 181 168 168 182 180 180 195 181 181 196 168 168 182 181 181 196 169 169 183 169 169 183 181 181 196 182 182 197 169 169 183 182 182 197 170 170 184 170 170 184 182 182 197 183 183 198 170 170 184 183 183 198 171 171 185 171 171 185 183 183 198 184 184 199 171 171 185 184 184 199 172 172 186 172 172 186 184 184 199 185 185 200 172 172 186 185 185 200 173 173 187 173 173 187 185 185 200 186 186 201 173 173 187 186 186 201 174 174 188 174 174 188 186 186 201 187 187 202 174 174 188 187 187 202 175 175 189 175 175 189 187 187 202 188 188 203 175 175 189 188 188 203 176 176 190 176 176 190 188 188 203 189 189 204 176 176 190 189 189 204 177 177 191 177 177 191 189 189 204 190 190 205 177 177 191 190 190 205 178 178 192 178 178 192 190 190 205 191 191 206 178 178 192 191 191 206 179 179 193 179 179 193 191 191 206 180 180 207 179 179 193 180 180 207 168 168 194 180 180 195 192 192 208 193 193 209 180 180 195 193 193 209 181 181 196 181 181 196 193 193 209 194 194 210 181 181 196 194 194 210 182 182 197 182 182 197 194 194 210 195 195 211 182 182 197 195 195 211 183 183 198 183 183 198 195 195 211 196 196 212 183 183 198 196 196 212 184 184 199 184 184 199 196 196 212 197 197 213 184 184 199 197 197 213 185 185 200 185 185 200 197 197 213 198 198 214 185 185 200 198 198 214 186 186 201 186 186 201 198 198 214 199 199 215 186 186 201 199 199 215 187 187 202 187 187 202 199 199 215 200 200 216 187 187 202 200 200 216 188 188 203 188 188 203 200 200 216 201 201 217 188 188 203 201 201 217 189 189 204 189 189 204 201 201 217 202 202 218 189 189 204 202 202 218 190 190 205 190 190 205 202 202 218 203 203 219 190 190 205 203 203 219 191 191 206 191 191 206 203 203 219 192 192 220 191 191 206 192 192 220 180 180 207 192 192 208 204 204 221 205 205 222 192 192 208 205 205 222 193 193 209 193 193 209 205 205 222 206 206 223 193 193 209 206 206 223 194 194 210 194 194 210 206 206 223 207 207 224 194 194 210 207 207 224 195 195 211 195 195 211 207 207 224 208 208 225 195 195 211 208 208 225 196 196 212 196 196 212 208 208 225 209 209 226 196 196 212 209 209 226 197 197 213 197 197 213 209 209 226 210 210 227 197 197 213 210 210 227 198 198 214 198 198 214 210 210 227 211 211 228 198 198 214 211 211 228 199 199 215 199 199 215 211 211 228 212 212 229 199 199 215 212 212 229 200 200 216 200 200 216 212 212 229 213 213 230 200 200 216 213 213 230 201 201 217 201 201 217 213 213 230 214 214 231 201 201 217 214 214 231 202 202 218 202 202 218 214 214 231 215 215 232 202 202 218 215 215 232 203 203 219 203 203 219 215 215 232 204 204 233 203 203 219 204 204 233 192 192 220 204 204 221 216 216 234 217 217 235 204 204 221 217 217 235 205 205 222 205 205 222 217 217 235 218 218 236 205 205 222 218 218 236 206 206 223 206 206 223 218 218 236 219 219 237 206 206 223 219 219 237 207 207 224 207 207 224 219 219 237 220 220 238 207 207 224 220 220 238 208 208 225 208 208 225 220 220 238 221 221 239 208 208 225 221 221 239 209 209 226 209 209 226 221 221 239 222 222 240 209 209 226 222 222 240 210 210 227 210 210 227 222 222 240 223 223 241 210 210 227 223 223 241 211 211 228 211 211 228 223 223 241 224 224 242 211 211 228 224 224 242 212 212 229 212 212 229 224 224 242 225 225 243 212 212 229 225 225 243 213 213 230 213 213 230 225 225 243 226 226 244 213 213 230 226 226 244 214 214 231 214 214 231 226 226 244 227 227 245 214 214 231 227 227 245 215 215 232 215 215 232 227 227 245 216 216 246 215 215 232 216 216 246 204 204 233 216 216 234 228 228 247 229 229 248 216 216 234 229 229 248 217 217 235 217 217 235 229 229 248 230 230 249 217 217 235 230 230 249 218 218 236 218 218 236 230 230 249 231 231 250 218 218 236 231 231 250 219 219 237 219 219 237 231 231 250 232 232 251 219 219 237 232 232 251 220 220 238 220 220 238 232 232 251 233 233 252 220 220 238 233 233 252 221 221 239 221 221 239 233 233 252 234 234 253 221 221 239 234 234 253 222 222 240 222 222 240 234 234 253 235 235 254 222 222 240 235 235 254 223 223 241 223 223 241 235 235 254 236 236 255 223 223 241 236 236 255 224 224 242 224 224 242 236 236 255 237 237 256 224 224 242 237 237 256 225 225 243 225 225 243 237 237 256 238 238 257 225 225 243 238 238 257 226 226 244 226 226 244 238 238 257 239 239 258 226 226 244 239 239 258 227 227 245 227 227 245 239 239 258 228 228 259 227 227 245 228 228 259 216 216 246 228 228 247 240 240 260 241 241 261 228 228 247 241 241 261 229 229 248 229 229 248 241 241 261 242 242 262 229 229 248 242 242 262 230 230 249 230 230 249 242 242 262 243 243 263 230 230 249 243 243 263 231 231 250 231 231 250 243 243 263 244 244 264 231 231 250 244 244 264 232 232 251 232 232 251 244 244 264 245 245 265 232 232 251 245 245 265 233 233 252 233 233 252 245 245 265 246 246 266 233 233 252 246 246 266 234 234 253 234 234 253 246 246 266 247 247 267 234 234 253 247 247 267 235 235 254 235 235 254 247 247 267 248 248 268 235 235 254 248 248 268 236 236 255 236 236 255 248 248 268 249 249 269 236 236 255 249 249 269 237 237 256 237 237 256 249 249 269 250 250 270 237 237 256 250 250 270 238 238 257 238 238 257 250 250 270 251 251 271 238 238 257 251 251 271 239 239 258 239 239 258 251 251 271 240 240 272 239 239 258 240 240 272 228 228 259 240 240 260 252 252 273 253 253 274 240 240 260 253 253 274 241 241 261 241 241 261 253 253 274 254 254 275 241 241 261 254 254 275 242 242 262 242 242 262 254 254 275 255 255 276 242 242 262 255 255 276 243 243 263 243 243 263 255 255 276 256 256 277 243 243 263 256 256 277 244 244 264 244 244 264 256 256 277 257 257 278 244 244 264 257 257 278 245 245 265 245 245 265 257 257 278 258 258 279 245 245 265 258 258 279 246 246 266 246 246 266 258 258 279 259 259 280 246 246 266 259 259 280 247 247 267 247 247 267 259 259 280 260 260 281 247 247 267 260 260 281 248 248 268 248 248 268 260 260 281 261 261 282 248 248 268 261 261 282 249 249 269 249 249 269 261 261 282 262 262 283 249 249 269 262 262 283 250 250 270 250 250 270 262 262 283 263 263 284 250 250 270 263 263 284 251 251 271 251 251 271 263 263 284 252 252 285 251 251 271 252 252 285 240 240 272 252 252 273 264 264 286 265 265 287 252 252 273 265 265 287 253 253 274 253 253 274 265 265 287 266 266 288 253 253 274 266 266 288 254 254 275 254 254 275 266 266 288 267 267 289 254 254 275 267 267 289 255 255 276 255 255 276 267 267 289 268 268 290 255 255 276 268 268 290 256 256 277 256 256 277 268 268 290 269 269 291 256 256 277 269 269 291 257 257 278 257 257 278 269 269 291 270 270 292 257 257 278 270 270 292 258 258 279 258 258 279 270 270 292 271 271 293 258 258 279 271 271 293 259 259 280 259 259 280 271 271 293 272 272 294 259 259 280 272 272 294 260 260 281 260 260 281 272 272 294 273 273 295 260 260 281 273 273 295 261 261 282 261 261 282 273 273 295 274 274 296 261 261 282 274 274 296 262 262 283 262 262 283 274 274 296 275 275 297 262 262 283 275 275 297 263 263 284 263 263 284 275 275 297 264 264 298 263 263 284 264 264 298 252 252 285 264 264 286 276 276 299 277 277 300 264 264 286 277 277 300 265 265 287 265 265 287 277 277 300 278 278 301 265 265 287 278 278 301 266 266 288 266 266 288 278 278 301 279 279 302 266 266 288 279 279 302 267 267 289 267 267 289 279 279 302 280 280 303 267 267 289 280 280 303 268 268 290 268 268 290 280 280 303 281 281 304 268 268 290 281 281 304 269 269 291 269 269 291 281 281 304 282 282 305 269 269 291 282 282 305 270 270 292 270 270 292 282 282 305 283 283 306 270 270 292 283 283 306 271 271 293 271 271 293 283 283 306 284 284 307 271 271 293 284 284 307 272 272 294 272 272 294 284 284 307 285 285 308 272 272 294 285 285 308 273 273 295 273 273 295 285 285 308 286 286 309 273 273 295 286 286 309 274 274 296 274 274 296 286 286 309 287 287 310 274 274 296 287 287 310 275 275 297 275 275 297 287 287 310 276 276 311 275 275 297 276 276 311 264 264 298 276 276 299 288 288 312 289 289 313 276 276 299 289 289 313 277 277 300 277 277 300 289 289 313 290 290 314 277 277 300 290 290 314 278 278 301 278 278 301 290 290 314 291 291 315 278 278 301 291 291 315 279 279 302 279 279 302 291 291 315 292 292 316 279 279 302 292 292 316 280 280 303 280 280 303 292 292 316 293 293 317 280 280 303 293 293 317 281 281 304 281 281 304 293 293 317 294 294 318 281 281 304 294 294 318 282 282 305 282 282 305 294 294 318 295 295 319 282 282 305 295 295 319 283 283 306 283 283 306 295 295 319 296 296 320 283 283 306 296 296 320 284 284 307 284 284 307 296 296 320 297 297 321 284 284 307 297 297 321 285 285 308 285 285 308 297 297 321 298 298 322 285 285 308 298 298 322 286 286 309 286 286 309 298 298 322 299 299 323 286 286 309 299 299 323 287 287 310 287 287 310 299 299 323 288 288 324 287 287 310 288 288 324 276 276 311 288 288 312 300 300 325 301 301 326 288 288 312 301 301 326 289 289 313 289 289 313 301 301 326 302 302 327 289 289 313 302 302 327 290 290 314 290 290 314 302 302 327 303 303 328 290 290 314 303 303 328 291 291 315 291 291 315 303 303 328 304 304 329 291 291 315 304 304 329 292 292 316 292 292 316 304 304 329 305 305 330 292 292 316 305 305 330 293 293 317 293 293 317 305 305 330 306 306 331 293 293 317 306 306 331 294 294 318 294 294 318 306 306 331 307 307 332 294 294 318 307 307 332 295 295 319 295 295 319 307 307 332 308 308 333 295 295 319 308 308 333 296 296 320 296 296 320 308 308 333 309 309 334 296 296 320 309 309 334 297 297 321 297 297 321 309 309 334 310 310 335 297 297 321 310 310 335 298 298 322 298 298 322 310 310 335 311 311 336 298 298 322 311 311 336 299 299 323 299 299 323 311 311 336 300 300 337 299 299 323 300 300 337 288 288 324 300 300 325 312 312 338 313 313 339 300 300 325 313 313 339 301 301 326 301 301 326 313 313 339 314 314 340 301 301 326 314 314 340 302 302 327 302 302 327 314 314 340 315 315 341 302 302 327 315 315 341 303 303 328 303 303 328 315 315 341 316 316 342 303 303 328 316 316 342 304 304 329 304 304 329 316 316 342 317 317 343 304 304 329 317 317 343 305 305 330 305 305 330 317 317 343 318 318 344 305 305 330 318 318 344 306 306 331 306 306 331 318 318 344 319 319 345 306 306 331 319 319 345 307 307 332 307 307 332 319 319 345 320 320 346 307 307 332 320 320 346 308 308 333 308 308 333 320 320 346 321 321 347 308 308 333 321 321 347 309 309 334 309 309 334 321 321 347 322 322 348 309 309 334 322 322 348 310 310 335 310 310 335 322 322 348 323 323 349 310 310 335 323 323 349 311 311 336 311 311 336 323 323 349 312 312 350 311 311 336 312 312 350 300 300 337 312 312 338 324 324 351 325 325 352 312 312 338 325 325 352 313 313 339 313 313 339 325 325 352 326 326 353 313 313 339 326 326 353 314 314 340 314 314 340 326 326 353 327 327 354 314 314 340 327 327 354 315 315 341 315 315 341 327 327 354 328 328 355 315 315 341 328 328 355 316 316 342 316 316 342 328 328 355 329 329 356 316 316 342 329 329 356 317 317 343 317 317 343 329 329 356 330 330 357 317 317 343 330 330 357 318 318 344 318 318 344 330 330 357 331 331 358 318 318 344 331 331 358 319 319 345 319 319 345 331 331 358 332 332 359 319 319 345 332 332 359 320 320 346 320 320 346 332 332 359 333 333 360 320 320 346 333 333 360 321 321 347 321 321 347 333 333 360 334 334 361 321 321 347 334 334 361 322 322 348 322 322 348 334 334 361 335 335 362 322 322 348 335 335 362 323 323 349 323 323 349 335 335 362 324 324 363 323 323 349 324 324 363 312 312 350 324 324 351 336 336 364 337 337 365 324 324 351 337 337 365 325 325 352 325 325 352 337 337 365 338 338 366 325 325 352 338 338 366 326 326 353 326 326 353 338 338 366 339 339 367 326 326 353 339 339 367 327 327 354 327 327 354 339 339 367 340 340 368 327 327 354 340 340 368 328 328 355 328 328 355 340 340 368 341 341 369 328 328 355 341 341 369 329 329 356 329 329 356 341 341 369 342 342 370 329 329 356 342 342 370 330 330 357 330 330 357 342 342 370 343 343 371 330 330 357 343 343 371 331 331 358 331 331 358 343 343 371 344 344 372 331 331 358 344 344 372 332 332 359 332 332 359 344 344 372 345 345 373 332 332 359 345 345 373 333 333 360 333 333 360 345 345 373 346 346 374 333 333 360 346 346 374 334 334 361 334 334 361 346 346 374 347 347 375 334 334 361 347 347 375 335 335 362 335 335 362 347 347 375 336 336 376 335 335 362 336 336 376 324 324 363 336 336 364 348 348 377 349 349 378 336 336 364 349 349 378 337 337 365 337 337 365 349 349 378 350 350 379 337 337 365 350 350 379 338 338 366 338 338 366 350 350 379 351 351 380 338 338 366 351 351 380 339 339 367 339 339 367 351 351 380 352 352 381 339 339 367 352 352 381 340 340 368 340 340 368 352 352 381 353 353 382 340 340 368 353 353 382 341 341 369 341 341 369 353 353 382 354 354 383 341 341 369 354 354 383 342 342 370 342 342 370 354 354 383 355 355 384 342 342 370 355 355 384 343 343 371 343 343 371 355 355 384 356 356 385 343 343 371 356 356 385 344 344 372 344 344 372 356 356 385 357 357 386 344 344 372 357 357 386 345 345 373 345 345 373 357 357 386 358 358 387 345 345 373 358 358 387 346 346 374 346 346 374 358 358 387 359 359 388 346 346 374 359 359 388 347 347 375 347 347 375 359 359 388 348 348 389 347 347 375 348 348 389 336 336 376 348 348 377 360 360 390 361 361 391 348 348 377 361 361 391 349 349 378 349 349 378 361 361 391 362 362 392 349 349 378 362 362 392 350 350 379 350 350 379 362 362 392 363 363 393 350 350 379 363 363 393 351 351 380 351 351 380 363 363 393 364 364 394 351 351 380 364 364 394 352 352 381 352 352 381 364 364 394 365 365 395 352 352 381 365 365 395 353 353 382 353 353 382 365 365 395 366 366 396 353 353 382 366 366 396 354 354 383 354 354 383 366 366 396 367 367 397 354 354 383 367 367 397 355 355 384 355 355 384 367 367 397 368 368 398 355 355 384 368 368 398 356 356 385 356 356 385 368 368 398 369 369 399 356 356 385 369 369 399 357 357 386 357 357 386 369 369 399 370 370 400 357 357 386 370 370 400 358 358 387 358 358 387 370 370 400 371 371 401 358 358 387 371 371 401 359 359 388 359 359 388 371 371 401 360 360 402 359 359 388 360 360 402 348 348 389 360 360 390 372 372 403 373 373 404 360 360 390 373 373 404 361 361 391 361 361 391 373 373 404 374 374 405 361 361 391 374 374 405 362 362 392 362 362 392 374 374 405 375 375 406 362 362 392 375 375 406 363 363 393 363 363 393 375 375 406 376 376 407 363 363 393 376 376 407 364 364 394 364 364 394 376 376 407 377 377 408 364 364 394 377 377 408 365 365 395 365 365 395 377 377 408 378 378 409 365 365 395 378 378 409 366 366 396 366 366 396 378 378 409 379 379 410 366 366 396 379 379 410 367 367 397 367 367 397 379 379 410 380 380 411 367 367 397 380 380 411 368 368 398 368 368 398 380 380 411 381 381 412 368 368 398 381 381 412 369 369 399 369 369 399 381 381 412 382 382 413 369 369 399 382 382 413 370 370 400 370 370 400 382 382 413 383 383 414 370 370 400 383 383 414 371 371 401 371 371 401 383 383 414 372 372 415 371 371 401 372 372 415 360 360 402 372 372 403 384 384 416 385 385 417 372 372 403 385 385 417 373 373 404 373 373 404 385 385 417 386 386 418 373 373 404 386 386 418 374 374 405 374 374 405 386 386 418 387 387 419 374 374 405 387 387 419 375 375 406 375 375 406 387 387 419 388 388 420 375 375 406 388 388 420 376 376 407 376 376 407 388 388 420 389 389 421 376 376 407 389 389 421 377 377 408 377 377 408 389 389 421 390 390 422 377 377 408 390 390 422 378 378 409 378 378 409 390 390 422 391 391 423 378 378 409 391 391 423 379 379 410 379 379 410 391 391 423 392 392 424 379 379 410 392 392 424 380 380 411 380 380 411 392 392 424 393 393 425 380 380 411 393 393 425 381 381 412 381 381 412 393 393 425 394 394 426 381 381 412 394 394 426 382 382 413 382 382 413 394 394 426 395 395 427 382 382 413 395 395 427 383 383 414 383 383 414 395 395 427 384 384 428 383 383 414 384 384 428 372 372 415 384 384 416 396 396 429 397 397 430 384 384 416 397 397 430 385 385 417 385 385 417 397 397 430 398 398 431 385 385 417 398 398 431 386 386 418 386 386 418 398 398 431 399 399 432 386 386 418 399 399 432 387 387 419 387 387 419 399 399 432 400 400 433 387 387 419 400 400 433 388 388 420 388 388 420 400 400 433 401 401 434 388 388 420 401 401 434 389 389 421 389 389 421 401 401 434 402 402 435 389 389 421 402 402 435 390 390 422 390 390 422 402 402 435 403 403 436 390 390 422 403 403 436 391 391 423 391 391 423 403 403 436 404 404 437 391 391 423 404 404 437 392 392 424 392 392 424 404 404 437 405 405 438 392 392 424 405 405 438 393 393 425 393 393 425 405 405 438 406 406 439 393 393 425 406 406 439 394 394 426 394 394 426 406 406 439 407 407 440 394 394 426 407 407 440 395 395 427 395 395 427 407 407 440 396 396 441 395 395 427 396 396 441 384 384 428 396 396 429 408 408 442 409 409 443 396 396 429 409 409 443 397 397 430 397 397 430 409 409 443 410 410 444 397 397 430 410 410 444 398 398 431 398 398 431 410 410 444 411 411 445 398 398 431 411 411 445 399 399 432 399 399 432 411 411 445 412 412 446 399 399 432 412 412 446 400 400 433 400 400 433 412 412 446 413 413 447 400 400 433 413 413 447 401 401 434 401 401 434 413 413 447 414 414 448 401 401 434 414 414 448 402 402 435 402 402 435 414 414 448 415 415 449 402 402 435 415 415 449 403 403 436 403 403 436 415 415 449 416 416 450 403 403 436 416 416 450 404 404 437 404 404 437 416 416 450 417 417 451 404 404 437 417 417 451 405 405 438 405 405 438 417 417 451 418 418 452 405 405 438 418 418 452 406 406 439 406 406 439 418 418 452 419 419 453 406 406 439 419 419 453 407 407 440 407 407 440 419 419 453 408 408 454 407 407 440 408 408 454 396 396 441 408 408 442 420 420 455 421 421 456 408 408 442 421 421 456 409 409 443 409 409 443 421 421 456 422 422 457 409 409 443 422 422 457 410 410 444 410 410 444 422 422 457 423 423 458 410 410 444 423 423 458 411 411 445 411 411 445 423 423 458 424 424 459 411 411 445 424 424 459 412 412 446 412 412 446 424 424 459 425 425 460 412 412 446 425 425 460 413 413 447 413 413 447 425 425 460 426 426 461 413 413 447 426 426 461 414 414 448 414 414 448 426 426 461 427 427 462 414 414 448 427 427 462 415 415 449 415 415 449 427 427 462 428 428 463 415 415 449 428 428 463 416 416 450 416 416 450 428 428 463 429 429 464 416 416 450 429 429 464 417 417 451 417 417 451 429 429 464 430 430 465 417 417 451 430 430 465 418 418 452 418 418 452 430 430 465 431 431 466 418 418 452 431 431 466 419 419 453 419 419 453 431 431 466 420 420 467 419 419 453 420 420 467 408 408 454 420 420 455 432 432 468 433 433 469 420 420 455 433 433 469 421 421 456 421 421 456 433 433 469 434 434 470 421 421 456 434 434 470 422 422 457 422 422 457 434 434 470 435 435 471 422 422 457 435 435 471 423 423 458 423 423 458 435 435 471 436 436 472 423 423 458 436 436 472 424 424 459 424 424 459 436 436 472 437 437 473 424 424 459 437 437 473 425 425 460 425 425 460 437 437 473 438 438 474 425 425 460 438 438 474 426 426 461 426 426 461 438 438 474 439 439 475 426 426 461 439 439 475 427 427 462 427 427 462 439 439 475 440 440 476 427 427 462 440 440 476 428 428 463 428 428 463 440 440 476 441 441 477 428 428 463 441 441 477 429 429 464 429 429 464 441 441 477 442 442 478 429 429 464 442 442 478 430 430 465 430 430 465 442 442 478 443 443 479 430 430 465 443 443 479 431 431 466 431 431 466 443 443 479 432 432 480 431 431 466 432 432 480 420 420 467 432 432 468 444 444 481 445 445 482 432 432 468 445 445 482 433 433 469 433 433 469 445 445 482 446 446 483 433 433 469 446 446 483 434 434 470 434 434 470 446 446 483 447 447 484 434 434 470 447 447 484 435 435 471 435 435 471 447 447 484 448 448 485 435 435 471 448 448 485 436 436 472 436 436 472 448 448 485 449 449 486 436 436 472 449 449 486 437 437 473 437 437 473 449 449 486 450 450 487 437 437 473 450 450 487 438 438 474 438 438 474 450 450 487 451 451 488 438 438 474 451 451 488 439 439 475 439 439 475 451 451 488 452 452 489 439 439 475 452 452 489 440 440 476 440 440 476 452 452 489 453 453 490 440 440 476 453 453 490 441 441 477 441 441 477 453 453 490 454 454 491 441 441 477 454 454 491 442 442 478 442 442 478 454 454 491 455 455 492 442 442 478 455 455 492 443 443 479 443 443 479 455 455 492 444 444 493 443 443 479 444 444 493 432 432 480 444 444 481 456 456 494 457 457 495 444 444 481 457 457 495 445 445 482 445 445 482 457 457 495 458 458 496 445 445 482 458 458 496 446 446 483 446 446 483 458 458 496 459 459 497 446 446 483 459 459 497 447 447 484 447 447 484 459 459 497 460 460 498 447 447 484 460 460 498 448 448 485 448 448 485 460 460 498 461 461 499 448 448 485 461 461 499 449 449 486 449 449 486 461 461 499 462 462 500 449 449 486 462 462 500 450 450 487 450 450 487 462 462 500 463 463 501 450 450 487 463 463 501 451 451 488 451 451 488 463 463 501 464 464 502 451 451 488 464 464 502 452 452 489 452 452 489 464 464 502 465 465 503 452 452 489 465 465 503 453 453 490 453 453 490 465 465 503 466 466 504 453 453 490 466 466 504 454 454 491 454 454 491 466 466 504 467 467 505 454 454 491 467 467 505 455 455 492 455 455 492 467 467 505 456 456 506 455 455 492 456 456 506 444 444 493 456 456 494 468 468 507 469 469 508 456 456 494 469 469 508 457 457 495 457 457 495 469 469 508 470 470 509 457 457 495 470 470 509 458 458 496 458 458 496 470 470 509 471 471 510 458 458 496 471 471 510 459 459 497 459 459 497 471 471 510 472 472 511 459 459 497 472 472 511 460 460 498 460 460 498 472 472 511 473 473 512 460 460 498 473 473 512 461 461 499 461 461 499 473 473 512 474 474 513 461 461 499 474 474 513 462 462 500 462 462 500 474 474 513 475 475 514 462 462 500 475 475 514 463 463 501 463 463 501 475 475 514 476 476 515 463 463 501 476 476 515 464 464 502 464 464 502 476 476 515 477 477 516 464 464 502 477 477 516 465 465 503 465 465 503 477 477 516 478 478 517 465 465 503 478 478 517 466 466 504 466 466 504 478 478 517 479 479 518 466 466 504 479 479 518 467 467 505 467 467 505 479 479 518 468 468 519 467 467 505 468 468 519 456 456 506 468 468 507 480 480 520 481 481 521 468 468 507 481 481 521 469 469 508 469 469 508 481 481 521 482 482 522 469 469 508 482 482 522 470 470 509 470 470 509 482 482 522 483 483 523 470 470 509 483 483 523 471 471 510 471 471 510 483 483 523 484 484 524 471 471 510 484 484 524 472 472 511 472 472 511 484 484 524 485 485 525 472 472 511 485 485 525 473 473 512 473 473 512 485 485 525 486 486 526 473 473 512 486 486 526 474 474 513 474 474 513 486 486 526 487 487 527 474 474 513 487 487 527 475 475 514 475 475 514 487 487 527 488 488 528 475 475 514 488 488 528 476 476 515 476 476 515 488 488 528 489 489 529 476 476 515 489 489 529 477 477 516 477 477 516 489 489 529 490 490 530 477 477 516 490 490 530 478 478 517 478 478 517 490 490 530 491 491 531 478 478 517 491 491 531 479 479 518 479 479 518 491 491 531 480 480 532 479 479 518 480 480 532 468 468 519 480 480 520 492 492 533 493 493 534 480 480 520 493 493 534 481 481 521 481 481 521 493 493 534 494 494 535 481 481 521 494 494 535 482 482 522 482 482 522 494 494 535 495 495 536 482 482 522 495 495 536 483 483 523 483 483 523 495 495 536 496 496 537 483 483 523 496 496 537 484 484 524 484 484 524 496 496 537 497 497 538 484 484 524 497 497 538 485 485 525 485 485 525 497 497 538 498 498 539 485 485 525 498 498 539 486 486 526 486 486 526 498 498 539 499 499 540 486 486 526 499 499 540 487 487 527 487 487 527 499 499 540 500 500 541 487 487 527 500 500 541 488 488 528 488 488 528 500 500 541 501 501 542 488 488 528 501 501 542 489 489 529 489 489 529 501 501 542 502 502 543 489 489 529 502 502 543 490 490 530 490 490 530 502 502 543 503 503 544 490 490 530 503 503 544 491 491 531 491 491 531 503 503 544 492 492 545 491 491 531 492 492 545 480 480 532 492 492 533 504 504 546 505 505 547 492 492 533 505 505 547 493 493 534 493 493 534 505 505 547 506 506 548 493 493 534 506 506 548 494 494 535 494 494 535 506 506 548 507 507 549 494 494 535 507 507 549 495 495 536 495 495 536 507 507 549 508 508 550 495 495 536 508 508 550 496 496 537 496 496 537 508 508 550 509 509 551 496 496 537 509 509 551 497 497 538 497 497 538 509 509 551 510 510 552 497 497 538 510 510 552 498 498 539 498 498 539 510 510 552 511 511 553 498 498 539 511 511 553 499 499 540 499 499 540 511 511 553 512 512 554 499 499 540 512 512 554 500 500 541 500 500 541 512 512 554 513 513 555 500 500 541 513 513 555 501 501 542 501 501 542 513 513 555 514 514 556 501 501 542 514 514 556 502 502 543 502 502 543 514 514 556 515 515 557 502 502 543 515 515 557 503 503 544 503 503 544 515 515 557 504 504 558 503 503 544 504 504 558 492 492 545 504 504 546 516 516 559 517 517 560 504 504 546 517 517 560 505 505 547 505 505 547 517 517 560 518 518 561 505 505 547 518 518 561 506 506 548 506 506 548 518 518 561 519 519 562 506 506 548 519 519 562 507 507 549 507 507 549 519 519 562 520 520 563 507 507 549 520 520 563 508 508 550 508 508 550 520 520 563 521 521 564 508 508 550 521 521 564 509 509 551 509 509 551 521 521 564 522 522 565 509 509 551 522 522 565 510 510 552 510 510 552 522 522 565 523 523 566 510 510 552 523 523 566 511 511 553 511 511 553 523 523 566 524 524 567 511 511 553 524 524 567 512 512 554 512 512 554 524 524 567 525 525 568 512 512 554 525 525 568 513 513 555 513 513 555 525 525 568 526 526 569 513 513 555 526 526 569 514 514 556 514 514 556 526 526 569 527 527 570 514 514 556 527 527 570 515 515 557 515 515 557 527 527 570 516 516 571 515 515 557 516 516 571 504 504 558 516 516 559 528 528 572 529 529 573 516 516 559 529 529 573 517 517 560 517 517 560 529 529 573 530 530 574 517 517 560 530 530 574 518 518 561 518 518 561 530 530 574 531 531 575 518 518 561 531 531 575 519 519 562 519 519 562 531 531 575 532 532 576 519 519 562 532 532 576 520 520 563 520 520 563 532 532 576 533 533 577 520 520 563 533 533 577 521 521 564 521 521 564 533 533 577 534 534 578 521 521 564 534 534 578 522 522 565 522 522 565 534 534 578 535 535 579 522 522 565 535 535 579 523 523 566 523 523 566 535 535 579 536 536 580 523 523 566 536 536 580 524 524 567 524 524 567 536 536 580 537 537 581 524 524 567 537 537 581 525 525 568 525 525 568 537 537 581 538 538 582 525 525 568 538 538 582 526 526 569 526 526 569 538 538 582 539 539 583 526 526 569 539 539 583 527 527 570 527 527 570 539 539 583 528 528 584 527 527 570 528 528 584 516 516 571 528 528 572 540 540 585 541 541 586 528 528 572 541 541 586 529 529 573 529 529 573 541 541 586 542 542 587 529 529 573 542 542 587 530 530 574 530 530 574 542 542 587 543 543 588 530 530 574 543 543 588 531 531 575 531 531 575 543 543 588 544 544 589 531 531 575 544 544 589 532 532 576 532 532 576 544 544 589 545 545 590 532 532 576 545 545 590 533 533 577 533 533 577 545 545 590 546 546 591 533 533 577 546 546 591 534 534 578 534 534 578 546 546 591 547 547 592 534 534 578 547 547 592 535 535 579 535 535 579 547 547 592 548 548 593 535 535 579 548 548 593 536 536 580 536 536 580 548 548 593 549 549 594 536 536 580 549 549 594 537 537 581 537 537 581 549 549 594 550 550 595 537 537 581 550 550 595 538 538 582 538 538 582 550 550 595 551 551 596 538 538 582 551 551 596 539 539 583 539 539 583 551 551 596 540 540 597 539 539 583 540 540 597 528 528 584 540 540 585 552 552 598 553 553 599 540 540 585 553 553 599 541 541 586 541 541 586 553 553 599 554 554 600 541 541 586 554 554 600 542 542 587 542 542 587 554 554 600 555 555 601 542 542 587 555 555 601 543 543 588 543 543 588 555 555 601 556 556 602 543 543 588 556 556 602 544 544 589 544 544 589 556 556 602 557 557 603 544 544 589 557 557 603 545 545 590 545 545 590 557 557 603 558 558 604 545 545 590 558 558 604 546 546 591 546 546 591 558 558 604 559 559 605 546 546 591 559 559 605 547 547 592 547 547 592 559 559 605 560 560 606 547 547 592 560 560 606 548 548 593 548 548 593 560 560 606 561 561 607 548 548 593 561 561 607 549 549 594 549 549 594 561 561 607 562 562 608 549 549 594 562 562 608 550 550 595 550 550 595 562 562 608 563 563 609 550 550 595 563 563 609 551 551 596 551 551 596 563 563 609 552 552 610 551 551 596 552 552 610 540 540 597 552 552 598 564 564 611 565 565 612 552 552 598 565 565 612 553 553 599 553 553 599 565 565 612 566 566 613 553 553 599 566 566 613 554 554 600 554 554 600 566 566 613 567 567 614 554 554 600 567 567 614 555 555 601 555 555 601 567 567 614 568 568 615 555 555 601 568 568 615 556 556 602 556 556 602 568 568 615 569 569 616 556 556 602 569 569 616 557 557 603 557 557 603 569 569 616 570 570 617 557 557 603 570 570 617 558 558 604 558 558 604 570 570 617 571 571 618 558 558 604 571 571 618 559 559 605 559 559 605 571 571 618 572 572 619 559 559 605 572 572 619 560 560 606 560 560 606 572 572 619 573 573 620 560 560 606 573 573 620 561 561 607 561 561 607 573 573 620 574 574 621 561 561 607 574 574 621 562 562 608 562 562 608 574 574 621 575 575 622 562 562 608 575 575 622 563 563 609 563 563 609 575 575 622 564 564 623 563 563 609 564 564 623 552 552 610 564 564 611 576 576 624 577 577 625 564 564 611 577 577 625 565 565 612 565 565 612 577 577 625 578 578 626 565 565 612 578 578 626 566 566 613 566 566 613 578 578 626 579 579 627 566 566 613 579 579 627 567 567 614 567 567 614 579 579 627 580 580 628 567 567 614 580 580 628 568 568 615 568 568 615 580 580 628 581 581 629 568 568 615 581 581 629 569 569 616 569 569 616 581 581 629 582 582 630 569 569 616 582 582 630 570 570 617 570 570 617 582 582 630 583 583 631 570 570 617 583 583 631 571 571 618 571 571 618 583 583 631 584 584 632 571 571 618 584 584 632 572 572 619 572 572 619 584 584 632 585 585 633 572 572 619 585 585 633 573 573 620 573 573 620 585 585 633 586 586 634 573 573 620 586 586 634 574 574 621 574 574 621 586 586 634 587 587 635 574 574 621 587 587 635 575 575 622 575 575 622 587 587 635 576 576 636 575 575 622 576 576 636 564 564 623 576 576 624 588 588 637 589 589 638 576 576 624 589 589 638 577 577 625 577 577 625 589 589 638 590 590 639 577 577 625 590 590 639 578 578 626 578 578 626 590 590 639 591 591 640 578 578 626 591 591 640 579 579 627 579 579 627 591 591 640 592 592 641 579 579 627 592 592 641 580 580 628 580 580 628 592 592 641 593 593 642 580 580 628 593 593 642 581 581 629 581 581 629 593 593 642 594 594 643 581 581 629 594 594 643 582 582 630 582 582 630 594 594 643 595 595 644 582 582 630 595 595 644 583 583 631 583 583 631 595 595 644 596 596 645 583 583 631 596 596 645 584 584 632 584 584 632 596 596 645 597 597 646 584 584 632 597 597 646 585 585 633 585 585 633 597 597 646 598 598 647 585 585 633 598 598 647 586 586 634 586 586 634 598 598 647 599 599 648 586 586 634 599 599 648 587 587 635 587 587 635 599 599 648 588 588 649 587 587 635 588 588 649 576 576 636 588 588 637 600 600 650 601 601 651 588 588 637 601 601 651 589 589 638 589 589 638 601 601 651 602 602 652 589 589 638 602 602 652 590 590 639 590 590 639 602 602 652 603 603 653 590 590 639 603 603 653 591 591 640 591 591 640 603 603 653 604 604 654 591 591 640 604 604 654 592 592 641 592 592 641 604 604 654 605 605 655 592 592 641 605 605 655 593 593 642 593 593 642 605 605 655 606 606 656 593 593 642 606 606 656 594 594 643 594 594 643 606 606 656 607 607 657 594 594 643 607 607 657 595 595 644 595 595 644 607 607 657 608 608 658 595 595 644 608 608 658 596 596 645 596 596 645 608 608 658 609 609 659 596 596 645 609 609 659 597 597 646 597 597 646 609 609 659 610 610 660 597 597 646 610 610 660 598 598 647 598 598 647 610 610 660 611 611 661 598 598 647 611 611 661 599 599 648 599 599 648 611 611 661 600 600 662 599 599 648 600 600 662 588 588 649 600 600 650 612 612 663 613 613 664 600 600 650 613 613 664 601 601 651 601 601 651 613 613 664 614 614 665 601 601 651 614 614 665 602 602 652 602 602 652 614 614 665 615 615 666 602 602 652 615 615 666 603 603 653 603 603 653 615 615 666 616 616 667 603 603 653 616 616 667 604 604 654 604 604 654 616 616 667 617 617 668 604 604 654 617 617 668 605 605 655 605 605 655 617 617 668 618 618 669 605 605 655 618 618 669 606 606 656 606 606 656 618 618 669 619 619 670 606 606 656 619 619 670 607 607 657 607 607 657 619 619 670 620 620 671 607 607 657 620 620 671 608 608 658 608 608 658 620 620 671 621 621 672 608 608 658 621 621 672 609 609 659 609 609 659 621 621 672 622 622 673 609 609 659 622 622 673 610 610 660 610 610 660 622 622 673 623 623 674 610 610 660 623 623 674 611 611 661 611 611 661 623 623 674 612 612 675 611 611 661 612 612 675 600 600 662 612 612 663 624 624 676 625 625 677 612 612 663 625 625 677 613 613 664 613 613 664 625 625 677 626 626 678 613 613 664 626 626 678 614 614 665 614 614 665 626 626 678 627 627 679 614 614 665 627 627 679 615 615 666 615 615 666 627 627 679 628 628 680 615 615 666 628 628 680 616 616 667 616 616 667 628 628 680 629 629 681 616 616 667 629 629 681 617 617 668 617 617 668 629 629 681 630 630 682 617 617 668 630 630 682 618 618 669 618 618 669 630 630 682 631 631 683 618 618 669 631 631 683 619 619 670 619 619 670 631 631 683 632 632 684 619 619 670 632 632 684 620 620 671 620 620 671 632 632 684 633 633 685 620 620 671 633 633 685 621 621 672 621 621 672 633 633 685 634 634 686 621 621 672 634 634 686 622 622 673 622 622 673 634 634 686 635 635 687 622 622 673 635 635 687 623 623 674 623 623 674 635 635 687 624 624 688 623 623 674 624 624 688 612 612 675 624 624 676 636 636 689 637 637 690 624 624 676 637 637 690 625 625 677 625 625 677 637 637 690 638 638 691 625 625 677 638 638 691 626 626 678 626 626 678 638 638 691 639 639 692 626 626 678 639 639 692 627 627 679 627 627 679 639 639 692 640 640 693 627 627 679 640 640 693 628 628 680 628 628 680 640 640 693 641 641 694 628 628 680 641 641 694 629 629 681 629 629 681 641 641 694 642 642 695 629 629 681 642 642 695 630 630 682 630 630 682 642 642 695 643 643 696 630 630 682 643 643 696 631 631 683 631 631 683 643 643 696 644 644 697 631 631 683 644 644 697 632 632 684 632 632 684 644 644 697 645 645 698 632 632 684 645 645 698 633 633 685 633 633 685 645 645 698 646 646 699 633 633 685 646 646 699 634 634 686 634 634 686 646 646 699 647 647 700 634 634 686 647 647 700 635 635 687 635 635 687 647 647 700 636 636 701 635 635 687 636 636 701 624 624 688 636 636 689 648 648 702 649 649 703 636 636 689 649 649 703 637 637 690 637 637 690 649 649 703 650 650 704 637 637 690 650 650 704 638 638 691 638 638 691 650 650 704 651 651 705 638 638 691 651 651 705 639 639 692 639 639 692 651 651 705 652 652 706 639 639 692 652 652 706 640 640 693 640 640 693 652 652 706 653 653 707 640 640 693 653 653 707 641 641 694 641 641 694 653 653 707 654 654 708 641 641 694 654 654 708 642 642 695 642 642 695 654 654 708 655 655 709 642 642 695 655 655 709 643 643 696 643 643 696 655 655 709 656 656 710 643 643 696 656 656 710 644 644 697 644 644 697 656 656 710 657 657 711 644 644 697 657 657 711 645 645 698 645 645 698 657 657 711 658 658 712 645 645 698 658 658 712 646 646 699 646 646 699 658 658 712 659 659 713 646 646 699 659 659 713 647 647 700 647 647 700 659 659 713 648 648 714 647 647 700 648 648 714 636 636 701 648 648 702 660 660 715 661 661 716 648 648 702 661 661 716 649 649 703 649 649 703 661 661 716 662 662 717 649 649 703 662 662 717 650 650 704 650 650 704 662 662 717 663 663 718 650 650 704 663 663 718 651 651 705 651 651 705 663 663 718 664 664 719 651 651 705 664 664 719 652 652 706 652 652 706 664 664 719 665 665 720 652 652 706 665 665 720 653 653 707 653 653 707 665 665 720 666 666 721 653 653 707 666 666 721 654 654 708 654 654 708 666 666 721 667 667 722 654 654 708 667 667 722 655 655 709 655 655 709 667 667 722 668 668 723 655 655 709 668 668 723 656 656 710 656 656 710 668 668 723 669 669 724 656 656 710 669 669 724 657 657 711 657 657 711 669 669 724 670 670 725 657 657 711 670 670 725 658 658 712 658 658 712 670 670 725 671 671 726 658 658 712 671 671 726 659 659 713 659 659 713 671 671 726 660 660 727 659 659 713 660 660 727 648 648 714 660 660 715 672 672 728 673 673 729 660 660 715 673 673 729 661 661 716 661 661 716 673 673 729 674 674 730 661 661 716 674 674 730 662 662 717 662 662 717 674 674 730 675 675 731 662 662 717 675 675 731 663 663 718 663 663 718 675 675 731 676 676 732 663 663 718 676 676 732 664 664 719 664 664 719 676 676 732 677 677 733 664 664 719 677 677 733 665 665 720 665 665 720 677 677 733 678 678 734 665 665 720 678 678 734 666 666 721 666 666 721 678 678 734 679 679 735 666 666 721 679 679 735 667 667 722 667 667 722 679 679 735 680 680 736 667 667 722 680 680 736 668 668 723 668 668 723 680 680 736 681 681 737 668 668 723 681 681 737 669 669 724 669 669 724 681 681 737 682 682 738 669 669 724 682 682 738 670 670 725 670 670 725 682 682 738 683 683 739 670 670 725 683 683 739 671 671 726 671 671 726 683 683 739 672 672 740 671 671 726 672 672 740 660 660 727 672 672 728 684 684 741 685 685 742 672 672 728 685 685 742 673 673 729 673 673 729 685 685 742 686 686 743 673 673 729 686 686 743 674 674 730 674 674 730 686 686 743 687 687 744 674 674 730 687 687 744 675 675 731 675 675 731 687 687 744 688 688 745 675 675 731 688 688 745 676 676 732 676 676 732 688 688 745 689 689 746 676 676 732 689 689 746 677 677 733 677 677 733 689 689 746 690 690 747 677 677 733 690 690 747 678 678 734 678 678 734 690 690 747 691 691 748 678 678 734 691 691 748 679 679 735 679 679 735 691 691 748 692 692 749 679 679 735 692 692 749 680 680 736 680 680 736 692 692 749 693 693 750 680 680 736 693 693 750 681 681 737 681 681 737 693 693 750 694 694 751 681 681 737 694 694 751 682 682 738 682 682 738 694 694 751 695 695 752 682 682 738 695 695 752 683 683 739 683 683 739 695 695 752 684 684 753 683 683 739 684 684 753 672 672 740 684 684 741 696 696 754 697 697 755 684 684 741 697 697 755 685 685 742 685 685 742 697 697 755 698 698 756 685 685 742 698 698 756 686 686 743 686 686 743 698 698 756 699 699 757 686 686 743 699 699 757 687 687 744 687 687 744 699 699 757 700 700 758 687 687 744 700 700 758 688 688 745 688 688 745 700 700 758 701 701 759 688 688 745 701 701 759 689 689 746 689 689 746 701 701 759 702 702 760 689 689 746 702 702 760 690 690 747 690 690 747 702 702 760 703 703 761 690 690 747 703 703 761 691 691 748 691 691 748 703 703 761 704 704 762 691 691 748 704 704 762 692 692 749 692 692 749 704 704 762 705 705 763 692 692 749 705 705 763 693 693 750 693 693 750 705 705 763 706 706 764 693 693 750 706 706 764 694 694 751 694 694 751 706 706 764 707 707 765 694 694 751 707 707 765 695 695 752 695 695 752 707 707 765 696 696 766 695 695 752 696 696 766 684 684 753 696 696 754 708 708 767 709 709 768 696 696 754 709 709 768 697 697 755 697 697 755 709 709 768 710 710 769 697 697 755 710 710 769 698 698 756 698 698 756 710 710 769 711 711 770 698 698 756 711 711 770 699 699 757 699 699 757 711 711 770 712 712 771 699 699 757 712 712 771 700 700 758 700 700 758 712 712 771 713 713 772 700 700 758 713 713 772 701 701 759 701 701 759 713 713 772 714 714 773 701 701 759 714 714 773 702 702 760 702 702 760 714 714 773 715 715 774 702 702 760 715 715 774 703 703 761 703 703 761 715 715 774 716 716 775 703 703 761 716 716 775 704 704 762 704 704 762 716 716 775 717 717 776 704 704 762 717 717 776 705 705 763 705 705 763 717 717 776 718 718 777 705 705 763 718 718 777 706 706 764 706 706 764 718 718 777 719 719 778 706 706 764 719 719 778 707 707 765 707 707 765 719 719 778 708 708 779 707 707 765 708 708 779 696 696 766 708 708 767 720 720 780 721 721 781 708 708 767 721 721 781 709 709 768 709 709 768 721 721 781 722 722 782 709 709 768 722 722 782 710 710 769 710 710 769 722 722 782 723 723 783 710 710 769 723 723 783 711 711 770 711 711 770 723 723 783 724 724 784 711 711 770 724 724 784 712 712 771 712 712 771 724 724 784 725 725 785 712 712 771 725 725 785 713 713 772 713 713 772 725 725 785 726 726 786 713 713 772 726 726 786 714 714 773 714 714 773 726 726 786 727 727 787 714 714 773 727 727 787 715 715 774 715 715 774 727 727 787 728 728 788 715 715 774 728 728 788 716 716 775 716 716 775 728 728 788 729 729 789 716 716 775 729 729 789 717 717 776 717 717 776 729 729 789 730 730 790 717 717 776 730 730 790 718 718 777 718 718 777 730 730 790 731 731 791 718 718 777 731 731 791 719 719 778 719 719 778 731 731 791 720 720 792 719 719 778 720 720 792 708 708 779 720 720 780 732 732 793 733 733 794 720 720 780 733 733 794 721 721 781 721 721 781 733 733 794 734 734 795 721 721 781 734 734 795 722 722 782 722 722 782 734 734 795 735 735 796 722 722 782 735 735 796 723 723 783 723 723 783 735 735 796 736 736 797 723 723 783 736 736 797 724 724 784 724 724 784 736 736 797 737 737 798 724 724 784 737 737 798 725 725 785 725 725 785 737 737 798 738 738 799 725 725 785 738 738 799 726 726 786 726 726 786 738 738 799 739 739 800 726 726 786 739 739 800 727 727 787 727 727 787 739 739 800 740 740 801 727 727 787 740 740 801 728 728 788 728 728 788 740 740 801 741 741 802 728 728 788 741 741 802 729 729 789 729 729 789 741 741 802 742 742 803 729 729 789 742 742 803 730 730 790 730 730 790 742 742 803 743 743 804 730 730 790 743 743 804 731 731 791 731 731 791 743 743 804 732 732 805 731 731 791 732 732 805 720 720 792 732 732 793 744 744 806 745 745 807 732 732 793 745 745 807 733 733 794 733 733 794 745 745 807 746 746 808 733 733 794 746 746 808 734 734 795 734 734 795 746 746 808 747 747 809 734 734 795 747 747 809 735 735 796 735 735 796 747 747 809 748 748 810 735 735 796 748 748 810 736 736 797 736 736 797 748 748 810 749 749 811 736 736 797 749 749 811 737 737 798 737 737 798 749 749 811 750 750 812 737 737 798 750 750 812 738 738 799 738 738 799 750 750 812 751 751 813 738 738 799 751 751 813 739 739 800 739 739 800 751 751 813 752 752 814 739 739 800 752 752 814 740 740 801 740 740 801 752 752 814 753 753 815 740 740 801 753 753 815 741 741 802 741 741 802 753 753 815 754 754 816 741 741 802 754 754 816 742 742 803 742 742 803 754 754 816 755 755 817 742 742 803 755 755 817 743 743 804 743 743 804 755 755 817 744 744 818 743 743 804 744 744 818 732 732 805 744 744 806 756 756 819 757 757 820 744 744 806 757 757 820 745 745 807 745 745 807 757 757 820 758 758 821 745 745 807 758 758 821 746 746 808 746 746 808 758 758 821 759 759 822 746 746 808 759 759 822 747 747 809 747 747 809 759 759 822 760 760 823 747 747 809 760 760 823 748 748 810 748 748 810 760 760 823 761 761 824 748 748 810 761 761 824 749 749 811 749 749 811 761 761 824 762 762 825 749 749 811 762 762 825 750 750 812 750 750 812 762 762 825 763 763 826 750 750 812 763 763 826 751 751 813 751 751 813 763 763 826 764 764 827 751 751 813 764 764 827 752 752 814 752 752 814 764 764 827 765 765 828 752 752 814 765 765 828 753 753 815 753 753 815 765 765 828 766 766 829 753 753 815 766 766 829 754 754 816 754 754 816 766 766 829 767 767 830 754 754 816 767 767 830 755 755 817 755 755 817 767 767 830 756 756 831 755 755 817 756 756 831 744 744 818 756 756 819 768 768 832 769 769 833 756 756 819 769 769 833 757 757 820 757 757 820 769 769 833 770 770 834 757 757 820 770 770 834 758 758 821 758 758 821 770 770 834 771 771 835 758 758 821 771 771 835 759 759 822 759 759 822 771 771 835 772 772 836 759 759 822 772 772 836 760 760 823 760 760 823 772 772 836 773 773 837 760 760 823 773 773 837 761 761 824 761 761 824 773 773 837 774 774 838 761 761 824 774 774 838 762 762 825 762 762 825 774 774 838 775 775 839 762 762 825 775 775 839 763 763 826 763 763 826 775 775 839 776 776 840 763 763 826 776 776 840 764 764 827 764 764 827 776 776 840 777 777 841 764 764 827 777 777 841 765 765 828 765 765 828 777 777 841 778 778 842 765 765 828 778 778 842 766 766 829 766 766 829 778 778 842 779 779 843 766 766 829 779 779 843 767 767 830 767 767 830 779 779 843 768 768 844 767 767 830 768 768 844 756 756 831 768 768 832 780 780 845 781 781 846 768 768 832 781 781 846 769 769 833 769 769 833 781 781 846 782 782 847 769 769 833 782 782 847 770 770 834 770 770 834 782 782 847 783 783 848 770 770 834 783 783 848 771 771 835 771 771 835 783 783 848 784 784 849 771 771 835 784 784 849 772 772 836 772 772 836 784 784 849 785 785 850 772 772 836 785 785 850 773 773 837 773 773 837 785 785 850 786 786 851 773 773 837 786 786 851 774 774 838 774 774 838 786 786 851 787 787 852 774 774 838 787 787 852 775 775 839 775 775 839 787 787 852 788 788 853 775 775 839 788 788 853 776 776 840 776 776 840 788 788 853 789 789 854 776 776 840 789 789 854 777 777 841 777 777 841 789 789 854 790 790 855 777 777 841 790 790 855 778 778 842 778 778 842 790 790 855 791 791 856 778 778 842 791 791 856 779 779 843 779 779 843 791 791 856 780 780 857 779 779 843 780 780 857 768 768 844 780 780 845 792 792 858 793 793 859 780 780 845 793 793 859 781 781 846 781 781 846 793 793 859 794 794 860 781 781 846 794 794 860 782 782 847 782 782 847 794 794 860 795 795 861 782 782 847 795 795 861 783 783 848 783 783 848 795 795 861 796 796 862 783 783 848 796 796 862 784 784 849 784 784 849 796 796 862 797 797 863 784 784 849 797 797 863 785 785 850 785 785 850 797 797 863 798 798 864 785 785 850 798 798 864 786 786 851 786 786 851 798 798 864 799 799 865 786 786 851 799 799 865 787 787 852 787 787 852 799 799 865 800 800 866 787 787 852 800 800 866 788 788 853 788 788 853 800 800 866 801 801 867 788 788 853 801 801 867 789 789 854 789 789 854 801 801 867 802 802 868 789 789 854 802 802 868 790 790 855 790 790 855 802 802 868 803 803 869 790 790 855 803 803 869 791 791 856 791 791 856 803 803 869 792 792 870 791 791 856 792 792 870 780 780 857 792 792 858 804 804 871 805 805 872 792 792 858 805 805 872 793 793 859 793 793 859 805 805 872 806 806 873 793 793 859 806 806 873 794 794 860 794 794 860 806 806 873 807 807 874 794 794 860 807 807 874 795 795 861 795 795 861 807 807 874 808 808 875 795 795 861 808 808 875 796 796 862 796 796 862 808 808 875 809 809 876 796 796 862 809 809 876 797 797 863 797 797 863 809 809 876 810 810 877 797 797 863 810 810 877 798 798 864 798 798 864 810 810 877 811 811 878 798 798 864 811 811 878 799 799 865 799 799 865 811 811 878 812 812 879 799 799 865 812 812 879 800 800 866 800 800 866 812 812 879 813 813 880 800 800 866 813 813 880 801 801 867 801 801 867 813 813 880 814 814 881 801 801 867 814 814 881 802 802 868 802 802 868 814 814 881 815 815 882 802 802 868 815 815 882 803 803 869 803 803 869 815 815 882 804 804 883 803 803 869 804 804 883 792 792 870 804 804 871 816 816 884 817 817 885 804 804 871 817 817 885 805 805 872 805 805 872 817 817 885 818 818 886 805 805 872 818 818 886 806 806 873 806 806 873 818 818 886 819 819 887 806 806 873 819 819 887 807 807 874 807 807 874 819 819 887 820 820 888 807 807 874 820 820 888 808 808 875 808 808 875 820 820 888 821 821 889 808 808 875 821 821 889 809 809 876 809 809 876 821 821 889 822 822 890 809 809 876 822 822 890 810 810 877 810 810 877 822 822 890 823 823 891 810 810 877 823 823 891 811 811 878 811 811 878 823 823 891 824 824 892 811 811 878 824 824 892 812 812 879 812 812 879 824 824 892 825 825 893 812 812 879 825 825 893 813 813 880 813 813 880 825 825 893 826 826 894 813 813 880 826 826 894 814 814 881 814 814 881 826 826 894 827 827 895 814 814 881 827 827 895 815 815 882 815 815 882 827 827 895 816 816 896 815 815 882 816 816 896 804 804 883 816 816 884 828 828 897 829 829 898 816 816 884 829 829 898 817 817 885 817 817 885 829 829 898 830 830 899 817 817 885 830 830 899 818 818 886 818 818 886 830 830 899 831 831 900 818 818 886 831 831 900 819 819 887 819 819 887 831 831 900 832 832 901 819 819 887 832 832 901 820 820 888 820 820 888 832 832 901 833 833 902 820 820 888 833 833 902 821 821 889 821 821 889 833 833 902 834 834 903 821 821 889 834 834 903 822 822 890 822 822 890 834 834 903 835 835 904 822 822 890 835 835 904 823 823 891 823 823 891 835 835 904 836 836 905 823 823 891 836 836 905 824 824 892 824 824 892 836 836 905 837 837 906 824 824 892 837 837 906 825 825 893 825 825 893 837 837 906 838 838 907 825 825 893 838 838 907 826 826 894 826 826 894 838 838 907 839 839 908 826 826 894 839 839 908 827 827 895 827 827 895 839 839 908 828 828 909 827 827 895 828 828 909 816 816 896 828 828 897 840 840 910 841 841 911 828 828 897 841 841 911 829 829 898 829 829 898 841 841 911 842 842 912 829 829 898 842 842 912 830 830 899 830 830 899 842 842 912 843 843 913 830 830 899 843 843 913 831 831 900 831 831 900 843 843 913 844 844 914 831 831 900 844 844 914 832 832 901 832 832 901 844 844 914 845 845 915 832 832 901 845 845 915 833 833 902 833 833 902 845 845 915 846 846 916 833 833 902 846 846 916 834 834 903 834 834 903 846 846 916 847 847 917 834 834 903 847 847 917 835 835 904 835 835 904 847 847 917 848 848 918 835 835 904 848 848 918 836 836 905 836 836 905 848 848 918 849 849 919 836 836 905 849 849 919 837 837 906 837 837 906 849 849 919 850 850 920 837 837 906 850 850 920 838 838 907 838 838 907 850 850 920 851 851 921 838 838 907 851 851 921 839 839 908 839 839 908 851 851 921 840 840 922 839 839 908 840 840 922 828 828 909 840 840 910 852 852 923 853 853 924 840 840 910 853 853 924 841 841 911 841 841 911 853 853 924 854 854 925 841 841 911 854 854 925 842 842 912 842 842 912 854 854 925 855 855 926 842 842 912 855 855 926 843 843 913 843 843 913 855 855 926 856 856 927 843 843 913 856 856 927 844 844 914 844 844 914 856 856 927 857 857 928 844 844 914 857 857 928 845 845 915 845 845 915 857 857 928 858 858 929 845 845 915 858 858 929 846 846 916 846 846 916 858 858 929 859 859 930 846 846 916 859 859 930 847 847 917 847 847 917 859 859 930 860 860 931 847 847 917 860 860 931 848 848 918 848 848 918 860 860 931 861 861 932 848 848 918 861 861 932 849 849 919 849 849 919 861 861 932 862 862 933 849 849 919 862 862 933 850 850 920 850 850 920 862 862 933 863 863 934 850 850 920 863 863 934 851 851 921 851 851 921 863 863 934 852 852 935 851 851 921 852 852 935 840 840 922 852 852 923 864 864 936 865 865 937 852 852 923 865 865 937 853 853 924 853 853 924 865 865 937 866 866 938 853 853 924 866 866 938 854 854 925 854 854 925 866 866 938 867 867 939 854 854 925 867 867 939 855 855 926 855 855 926 867 867 939 868 868 940 855 855 926 868 868 940 856 856 927 856 856 927 868 868 940 869 869 941 856 856 927 869 869 941 857 857 928 857 857 928 869 869 941 870 870 942 857 857 928 870 870 942 858 858 929 858 858 929 870 870 942 871 871 943 858 858 929 871 871 943 859 859 930 859 859 930 871 871 943 872 872 944 859 859 930 872 872 944 860 860 931 860 860 931 872 872 944 873 873 945 860 860 931 873 873 945 861 861 932 861 861 932 873 873 945 874 874 946 861 861 932 874 874 946 862 862 933 862 862 933 874 874 946 875 875 947 862 862 933 875 875 947 863 863 934 863 863 934 875 875 947 864 864 948 863 863 934 864 864 948 852 852 935 864 864 936 876 876 949 877 877 950 864 864 936 877 877 950 865 865 937 865 865 937 877 877 950 878 878 951 865 865 937 878 878 951 866 866 938 866 866 938 878 878 951 879 879 952 866 866 938 879 879 952 867 867 939 867 867 939 879 879 952 880 880 953 867 867 939 880 880 953 868 868 940 868 868 940 880 880 953 881 881 954 868 868 940 881 881 954 869 869 941 869 869 941 881 881 954 882 882 955 869 869 941 882 882 955 870 870 942 870 870 942 882 882 955 883 883 956 870 870 942 883 883 956 871 871 943 871 871 943 883 883 956 884 884 957 871 871 943 884 884 957 872 872 944 872 872 944 884 884 957 885 885 958 872 872 944 885 885 958 873 873 945 873 873 945 885 885 958 886 886 959 873 873 945 886 886 959 874 874 946 874 874 946 886 886 959 887 887 960 874 874 946 887 887 960 875 875 947 875 875 947 887 887 960 876 876 961 875 875 947 876 876 961 864 864 948 876 876 949 888 888 962 889 889 963 876 876 949 889 889 963 877 877 950 877 877 950 889 889 963 890 890 964 877 877 950 890 890 964 878 878 951 878 878 951 890 890 964 891 891 965 878 878 951 891 891 965 879 879 952 879 879 952 891 891 965 892 892 966 879 879 952 892 892 966 880 880 953 880 880 953 892 892 966 893 893 967 880 880 953 893 893 967 881 881 954 881 881 954 893 893 967 894 894 968 881 881 954 894 894 968 882 882 955 882 882 955 894 894 968 895 895 969 882 882 955 895 895 969 883 883 956 883 883 956 895 895 969 896 896 970 883 883 956 896 896 970 884 884 957 884 884 957 896 896 970 897 897 971 884 884 957 897 897 971 885 885 958 885 885 958 897 897 971 898 898 972 885 885 958 898 898 972 886 886 959 886 886 959 898 898 972 899 899 973 886 886 959 899 899 973 887 887 960 887 887 960 899 899 973 888 888 974 887 887 960 888 888 974 876 876 961 888 888 962 900 900 975 901 901 976 888 888 962 901 901 976 889 889 963 889 889 963 901 901 976 902 902 977 889 889 963 902 902 977 890 890 964 890 890 964 902 902 977 903 903 978 890 890 964 903 903 978 891 891 965 891 891 965 903 903 978 904 904 979 891 891 965 904 904 979 892 892 966 892 892 966 904 904 979 905 905 980 892 892 966 905 905 980 893 893 967 893 893 967 905 905 980 906 906 981 893 893 967 906 906 981 894 894 968 894 894 968 906 906 981 907 907 982 894 894 968 907 907 982 895 895 969 895 895 969 907 907 982 908 908 983 895 895 969 908 908 983 896 896 970 896 896 970 908 908 983 909 909 984 896 896 970 909 909 984 897 897 971 897 897 971 909 909 984 910 910 985 897 897 971 910 910 985 898 898 972 898 898 972 910 910 985 911 911 986 898 898 972 911 911 986 899 899 973 899 899 973 911 911 986 900 900 987 899 899 973 900 900 987 888 888 974 900 900 975 912 912 988 913 913 989 900 900 975 913 913 989 901 901 976 901 901 976 913 913 989 914 914 990 901 901 976 914 914 990 902 902 977 902 902 977 914 914 990 915 915 991 902 902 977 915 915 991 903 903 978 903 903 978 915 915 991 916 916 992 903 903 978 916 916 992 904 904 979 904 904 979 916 916 992 917 917 993 904 904 979 917 917 993 905 905 980 905 905 980 917 917 993 918 918 994 905 905 980 918 918 994 906 906 981 906 906 981 918 918 994 919 919 995 906 906 981 919 919 995 907 907 982 907 907 982 919 919 995 920 920 996 907 907 982 920 920 996 908 908 983 908 908 983 920 920 996 921 921 997 908 908 983 921 921 997 909 909 984 909 909 984 921 921 997 922 922 998 909 909 984 922 922 998 910 910 985 910 910 985 922 922 998 923 923 999 910 910 985 923 923 999 911 911 986 911 911 986 923 923 999 912 912 1000 911 911 986 912 912 1000 900 900 987 912 912 988 924 924 1001 925 925 1002 912 912 988 925 925 1002 913 913 989 913 913 989 925 925 1002 926 926 1003 913 913 989 926 926 1003 914 914 990 914 914 990 926 926 1003 927 927 1004 914 914 990 927 927 1004 915 915 991 915 915 991 927 927 1004 928 928 1005 915 915 991 928 928 1005 916 916 992 916 916 992 928 928 1005 929 929 1006 916 916 992 929 929 1006 917 917 993 917 917 993 929 929 1006 930 930 1007 917 917 993 930 930 1007 918 918 994 918 918 994 930 930 1007 931 931 1008 918 918 994 931 931 1008 919 919 995 919 919 995 931 931 1008 932 932 1009 919 919 995 932 932 1009 920 920 996 920 920 996 932 932 1009 933 933 1010 920 920 996 933 933 1010 921 921 997 921 921 997 933 933 1010 934 934 1011 921 921 997 934 934 1011 922 922 998 922 922 998 934 934 1011 935 935 1012 922 922 998 935 935 1012 923 923 999 923 923 999 935 935 1012 924 924 1013 923 923 999 924 924 1013 912 912 1000 924 924 1001 936 936 1014 937 937 1015 924 924 1001 937 937 1015 925 925 1002 925 925 1002 937 937 1015 938 938 1016 925 925 1002 938 938 1016 926 926 1003 926 926 1003 938 938 1016 939 939 1017 926 926 1003 939 939 1017 927 927 1004 927 927 1004 939 939 1017 940 940 1018 927 927 1004 940 940 1018 928 928 1005 928 928 1005 940 940 1018 941 941 1019 928 928 1005 941 941 1019 929 929 1006 929 929 1006 941 941 1019 942 942 1020 929 929 1006 942 942 1020 930 930 1007 930 930 1007 942 942 1020 943 943 1021 930 930 1007 943 943 1021 931 931 1008 931 931 1008 943 943 1021 944 944 1022 931 931 1008 944 944 1022 932 932 1009 932 932 1009 944 944 1022 945 945 1023 932 932 1009 945 945 1023 933 933 1010 933 933 1010 945 945 1023 946 946 1024 933 933 1010 946 946 1024 934 934 1011 934 934 1011 946 946 1024 947 947 1025 934 934 1011 947 947 1025 935 935 1012 935 935 1012 947 947 1025 936 936 1026 935 935 1012 936 936 1026 924 924 1013 936 936 1014 948 948 1027 949 949 1028 936 936 1014 949 949 1028 937 937 1015 937 937 1015 949 949 1028 950 950 1029 937 937 1015 950 950 1029 938 938 1016 938 938 1016 950 950 1029 951 951 1030 938 938 1016 951 951 1030 939 939 1017 939 939 1017 951 951 1030 952 952 1031 939 939 1017 952 952 1031 940 940 1018 940 940 1018 952 952 1031 953 953 1032 940 940 1018 953 953 1032 941 941 1019 941 941 1019 953 953 1032 954 954 1033 941 941 1019 954 954 1033 942 942 1020 942 942 1020 954 954 1033 955 955 1034 942 942 1020 955 955 1034 943 943 1021 943 943 1021 955 955 1034 956 956 1035 943 943 1021 956 956 1035 944 944 1022 944 944 1022 956 956 1035 957 957 1036 944 944 1022 957 957 1036 945 945 1023 945 945 1023 957 957 1036 958 958 1037 945 945 1023 958 958 1037 946 946 1024 946 946 1024 958 958 1037 959 959 1038 946 946 1024 959 959 1038 947 947 1025 947 947 1025 959 959 1038 948 948 1039 947 947 1025 948 948 1039 936 936 1026 948 948 1027 960 960 1040 961 961 1041 948 948 1027 961 961 1041 949 949 1028 949 949 1028 961 961 1041 962 962 1042 949 949 1028 962 962 1042 950 950 1029 950 950 1029 962 962 1042 963 963 1043 950 950 1029 963 963 1043 951 951 1030 951 951 1030 963 963 1043 964 964 1044 951 951 1030 964 964 1044 952 952 1031 952 952 1031 964 964 1044 965 965 1045 952 952 1031 965 965 1045 953 953 1032 953 953 1032 965 965 1045 966 966 1046 953 953 1032 966 966 1046 954 954 1033 954 954 1033 966 966 1046 967 967 1047 954 954 1033 967 967 1047 955 955 1034 955 955 1034 967 967 1047 968 968 1048 955 955 1034 968 968 1048 956 956 1035 956 956 1035 968 968 1048 969 969 1049 956 956 1035 969 969 1049 957 957 1036 957 957 1036 969 969 1049 970 970 1050 957 957 1036 970 970 1050 958 958 1037 958 958 1037 970 970 1050 971 971 1051 958 958 1037 971 971 1051 959 959 1038 959 959 1038 971 971 1051 960 960 1052 959 959 1038 960 960 1052 948 948 1039 960 960 1040 972 972 1053 973 973 1054 960 960 1040 973 973 1054 961 961 1041 961 961 1041 973 973 1054 974 974 1055 961 961 1041 974 974 1055 962 962 1042 962 962 1042 974 974 1055 975 975 1056 962 962 1042 975 975 1056 963 963 1043 963 963 1043 975 975 1056 976 976 1057 963 963 1043 976 976 1057 964 964 1044 964 964 1044 976 976 1057 977 977 1058 964 964 1044 977 977 1058 965 965 1045 965 965 1045 977 977 1058 978 978 1059 965 965 1045 978 978 1059 966 966 1046 966 966 1046 978 978 1059 979 979 1060 966 966 1046 979 979 1060 967 967 1047 967 967 1047 979 979 1060 980 980 1061 967 967 1047 980 980 1061 968 968 1048 968 968 1048 980 980 1061 981 981 1062 968 968 1048 981 981 1062 969 969 1049 969 969 1049 981 981 1062 982 982 1063 969 969 1049 982 982 1063 970 970 1050 970 970 1050 982 982 1063 983 983 1064 970 970 1050 983 983 1064 971 971 1051 971 971 1051 983 983 1064 972 972 1065 971 971 1051 972 972 1065 960 960 1052 972 972 1053 984 984 1066 985 985 1067 972 972 1053 985 985 1067 973 973 1054 973 973 1054 985 985 1067 986 986 1068 973 973 1054 986 986 1068 974 974 1055 974 974 1055 986 986 1068 987 987 1069 974 974 1055 987 987 1069 975 975 1056 975 975 1056 987 987 1069 988 988 1070 975 975 1056 988 988 1070 976 976 1057 976 976 1057 988 988 1070 989 989 1071 976 976 1057 989 989 1071 977 977 1058 977 977 1058 989 989 1071 990 990 1072 977 977 1058 990 990 1072 978 978 1059 978 978 1059 990 990 1072 991 991 1073 978 978 1059 991 991 1073 979 979 1060 979 979 1060 991 991 1073 992 992 1074 979 979 1060 992 992 1074 980 980 1061 980 980 1061 992 992 1074 993 993 1075 980 980 1061 993 993 1075 981 981 1062 981 981 1062 993 993 1075 994 994 1076 981 981 1062 994 994 1076 982 982 1063 982 982 1063 994 994 1076 995 995 1077 982 982 1063 995 995 1077 983 983 1064 983 983 1064 995 995 1077 984 984 1078 983 983 1064 984 984 1078 972 972 1065 984 984 1066 996 996 1079 997 997 1080 984 984 1066 997 997 1080 985 985 1067 985 985 1067 997 997 1080 998 998 1081 985 985 1067 998 998 1081 986 986 1068 986 986 1068 998 998 1081 999 999 1082 986 986 1068 999 999 1082 987 987 1069 987 987 1069 999 999 1082 1000 1000 1083 987 987 1069 1000 1000 1083 988 988 1070 988 988 1070 1000 1000 1083 1001 1001 1084 988 988 1070 1001 1001 1084 989 989 1071 989 989 1071 1001 1001 1084 1002 1002 1085 989 989 1071 1002 1002 1085 990 990 1072 990 990 1072 1002 1002 1085 1003 1003 1086 990 990 1072 1003 1003 1086 991 991 1073 991 991 1073 1003 1003 1086 1004 1004 1087 991 991 1073 1004 1004 1087 992 992 1074 992 992 1074 1004 1004 1087 1005 1005 1088 992 992 1074 1005 1005 1088 993 993 1075 993 993 1075 1005 1005 1088 1006 1006 1089 993 993 1075 1006 1006 1089 994 994 1076 994 994 1076 1006 1006 1089 1007 1007 1090 994 994 1076 1007 1007 1090 995 995 1077 995 995 1077 1007 1007 1090 996 996 1091 995 995 1077 996 996 1091 984 984 1078 996 996 1079 1008 1008 1092 1009 1009 1093 996 996 1079 1009 1009 1093 997 997 1080 997 997 1080 1009 1009 1093 1010 1010 1094 997 997 1080 1010 1010 1094 998 998 1081 998 998 1081 1010 1010 1094 1011 1011 1095 998 998 1081 1011 1011 1095 999 999 1082 999 999 1082 1011 1011 1095 1012 1012 1096 999 999 1082 1012 1012 1096 1000 1000 1083 1000 1000 1083 1012 1012 1096 1013 1013 1097 1000 1000 1083 1013 1013 1097 1001 1001 1084 1001 1001 1084 1013 1013 1097 1014 1014 1098 1001 1001 1084 1014 1014 1098 1002 1002 1085 1002 1002 1085 1014 1014 1098 1015 1015 1099 1002 1002 1085 1015 1015 1099 1003 1003 1086 1003 1003 1086 1015 1015 1099 1016 1016 1100 1003 1003 1086 1016 1016 1100 1004 1004 1087 1004 1004 1087 1016 1016 1100 1017 1017 1101 1004 1004 1087 1017 1017 1101 1005 1005 1088 1005 1005 1088 1017 1017 1101 1018 1018 1102 1005 1005 1088 1018 1018 1102 1006 1006 1089 1006 1006 1089 1018 1018 1102 1019 1019 1103 1006 1006 1089 1019 1019 1103 1007 1007 1090 1007 1007 1090 1019 1019 1103 1008 1008 1104 1007 1007 1090 1008 1008 1104 996 996 1091 1008 1008 1092 1020 1020 1105 1021 1021 1106 1008 1008 1092 1021 1021 1106 1009 1009 1093 1009 1009 1093 1021 1021 1106 1022 1022 1107 1009 1009 1093 1022 1022 1107 1010 1010 1094 1010 1010 1094 1022 1022 1107 1023 1023 1108 1010 1010 1094 1023 1023 1108 1011 1011 1095 1011 1011 1095 1023 1023 1108 1024 1024 1109 1011 1011 1095 1024 1024 1109 1012 1012 1096 1012 1012 1096 1024 1024 1109 1025 1025 1110 1012 1012 1096 1025 1025 1110 1013 1013 1097 1013 1013 1097 1025 1025 1110 1026 1026 1111 1013 1013 1097 1026 1026 1111 1014 1014 1098 1014 1014 1098 1026 1026 1111 1027 1027 1112 1014 1014 1098 1027 1027 1112 1015 1015 1099 1015 1015 1099 1027 1027 1112 1028 1028 1113 1015 1015 1099 1028 1028 1113 1016 1016 1100 1016 1016 1100 1028 1028 1113 1029 1029 1114 1016 1016 1100 1029 1029 1114 1017 1017 1101 1017 1017 1101 1029 1029 1114 1030 1030 1115 1017 1017 1101 1030 1030 1115 1018 1018 1102 1018 1018 1102 1030 1030 1115 1031 1031 1116 1018 1018 1102 1031 1031 1116 1019 1019 1103 1019 1019 1103 1031 1031 1116 1020 1020 1117 1019 1019 1103 1020 1020 1117 1008 1008 1104 1020 1020 1105 1032 1032 1118 1033 1033 1119 1020 1020 1105 1033 1033 1119 1021 1021 1106 1021 1021 1106 1033 1033 1119 1034 1034 1120 1021 1021 1106 1034 1034 1120 1022 1022 1107 1022 1022 1107 1034 1034 1120 1035 1035 1121 1022 1022 1107 1035 1035 1121 1023 1023 1108 1023 1023 1108 1035 1035 1121 1036 1036 1122 1023 1023 1108 1036 1036 1122 1024 1024 1109 1024 1024 1109 1036 1036 1122 1037 1037 1123 1024 1024 1109 1037 1037 1123 1025 1025 1110 1025 1025 1110 1037 1037 1123 1038 1038 1124 1025 1025 1110 1038 1038 1124 1026 1026 1111 1026 1026 1111 1038 1038 1124 1039 1039 1125 1026 1026 1111 1039 1039 1125 1027 1027 1112 1027 1027 1112 1039 1039 1125 1040 1040 1126 1027 1027 1112 1040 1040 1126 1028 1028 1113 1028 1028 1113 1040 1040 1126 1041 1041 1127 1028 1028 1113 1041 1041 1127 1029 1029 1114 1029 1029 1114 1041 1041 1127 1042 1042 1128 1029 1029 1114 1042 1042 1128 1030 1030 1115 1030 1030 1115 1042 1042 1128 1043 1043 1129 1030 1030 1115 1043 1043 1129 1031 1031 1116 1031 1031 1116 1043 1043 1129 1032 1032 1130 1031 1031 1116 1032 1032 1130 1020 1020 1117 1032 1032 1118 1044 1044 1131 1045 1045 1132 1032 1032 1118 1045 1045 1132 1033 1033 1119 1033 1033 1119 1045 1045 1132 1046 1046 1133 1033 1033 1119 1046 1046 1133 1034 1034 1120 1034 1034 1120 1046 1046 1133 1047 1047 1134 1034 1034 1120 1047 1047 1134 1035 1035 1121 1035 1035 1121 1047 1047 1134 1048 1048 1135 1035 1035 1121 1048 1048 1135 1036 1036 1122 1036 1036 1122 1048 1048 1135 1049 1049 1136 1036 1036 1122 1049 1049 1136 1037 1037 1123 1037 1037 1123 1049 1049 1136 1050 1050 1137 1037 1037 1123 1050 1050 1137 1038 1038 1124 1038 1038 1124 1050 1050 1137 1051 1051 1138 1038 1038 1124 1051 1051 1138 1039 1039 1125 1039 1039 1125 1051 1051 1138 1052 1052 1139 1039 1039 1125 1052 1052 1139 1040 1040 1126 1040 1040 1126 1052 1052 1139 1053 1053 1140 1040 1040 1126 1053 1053 1140 1041 1041 1127 1041 1041 1127 1053 1053 1140 1054 1054 1141 1041 1041 1127 1054 1054 1141 1042 1042 1128 1042 1042 1128 1054 1054 1141 1055 1055 1142 1042 1042 1128 1055 1055 1142 1043 1043 1129 1043 1043 1129 1055 1055 1142 1044 1044 1143 1043 1043 1129 1044 1044 1143 1032 1032 1130 1044 1044 1131 1056 1056 1144 1057 1057 1145 1044 1044 1131 1057 1057 1145 1045 1045 1132 1045 1045 1132 1057 1057 1145 1058 1058 1146 1045 1045 1132 1058 1058 1146 1046 1046 1133 1046 1046 1133 1058 1058 1146 1059 1059 1147 1046 1046 1133 1059 1059 1147 1047 1047 1134 1047 1047 1134 1059 1059 1147 1060 1060 1148 1047 1047 1134 1060 1060 1148 1048 1048 1135 1048 1048 1135 1060 1060 1148 1061 1061 1149 1048 1048 1135 1061 1061 1149 1049 1049 1136 1049 1049 1136 1061 1061 1149 1062 1062 1150 1049 1049 1136 1062 1062 1150 1050 1050 1137 1050 1050 1137 1062 1062 1150 1063 1063 1151 1050 1050 1137 1063 1063 1151 1051 1051 1138 1051 1051 1138 1063 1063 1151 1064 1064 1152 1051 1051 1138 1064 1064 1152 1052 1052 1139 1052 1052 1139 1064 1064 1152 1065 1065 1153 1052 1052 1139 1065 1065 1153 1053 1053 1140 1053 1053 1140 1065 1065 1153 1066 1066 1154 1053 1053 1140 1066 1066 1154 1054 1054 1141 1054 1054 1141 1066 1066 1154 1067 1067 1155 1054 1054 1141 1067 1067 1155 1055 1055 1142 1055 1055 1142 1067 1067 1155 1056 1056 1156 1055 1055 1142 1056 1056 1156 1044 1044 1143 1056 1056 1144 1068 1068 1157 1069 1069 1158 1056 1056 1144 1069 1069 1158 1057 1057 1145 1057 1057 1145 1069 1069 1158 1070 1070 1159 1057 1057 1145 1070 1070 1159 1058 1058 1146 1058 1058 1146 1070 1070 1159 1071 1071 1160 1058 1058 1146 1071 1071 1160 1059 1059 1147 1059 1059 1147 1071 1071 1160 1072 1072 1161 1059 1059 1147 1072 1072 1161 1060 1060 1148 1060 1060 1148 1072 1072 1161 1073 1073 1162 1060 1060 1148 1073 1073 1162 1061 1061 1149 1061 1061 1149 1073 1073 1162 1074 1074 1163 1061 1061 1149 1074 1074 1163 1062 1062 1150 1062 1062 1150 1074 1074 1163 1075 1075 1164 1062 1062 1150 1075 1075 1164 1063 1063 1151 1063 1063 1151 1075 1075 1164 1076 1076 1165 1063 1063 1151 1076 1076 1165 1064 1064 1152 1064 1064 1152 1076 1076 1165 1077 1077 1166 1064 1064 1152 1077 1077 1166 1065 1065 1153 1065 1065 1153 1077 1077 1166 1078 1078 1167 1065 1065 1153 1078 1078 1167 1066 1066 1154 1066 1066 1154 1078 1078 1167 1079 1079 1168 1066 1066 1154 1079 1079 1168 1067 1067 1155 1067 1067 1155 1079 1079 1168 1068 1068 1169 1067 1067 1155 1068 1068 1169 1056 1056 1156 1068 1068 1157 1080 1080 1170 1081 1081 1171 1068 1068 1157 1081 1081 1171 1069 1069 1158 1069 1069 1158 1081 1081 1171 1082 1082 1172 1069 1069 1158 1082 1082 1172 1070 1070 1159 1070 1070 1159 1082 1082 1172 1083 1083 1173 1070 1070 1159 1083 1083 1173 1071 1071 1160 1071 1071 1160 1083 1083 1173 1084 1084 1174 1071 1071 1160 1084 1084 1174 1072 1072 1161 1072 1072 1161 1084 1084 1174 1085 1085 1175 1072 1072 1161 1085 1085 1175 1073 1073 1162 1073 1073 1162 1085 1085 1175 1086 1086 1176 1073 1073 1162 1086 1086 1176 1074 1074 1163 1074 1074 1163 1086 1086 1176 1087 1087 1177 1074 1074 1163 1087 1087 1177 1075 1075 1164 1075 1075 1164 1087 1087 1177 1088 1088 1178 1075 1075 1164 1088 1088 1178 1076 1076 1165 1076 1076 1165 1088 1088 1178 1089 1089 1179 1076 1076 1165 1089 1089 1179 1077 1077 1166 1077 1077 1166 1089 1089 1179 1090 1090 1180 1077 1077 1166 1090 1090 1180 1078 1078 1167 1078 1078 1167 1090 1090 1180 1091 1091 1181 1078 1078 1167 1091 1091 1181 1079 1079 1168 1079 1079 1168 1091 1091 1181 1080 1080 1182 1079 1079 1168 1080 1080 1182 1068 1068 1169 1080 1080 1170 1092 1092 1183 1093 1093 1184 1080 1080 1170 1093 1093 1184 1081 1081 1171 1081 1081 1171 1093 1093 1184 1094 1094 1185 1081 1081 1171 1094 1094 1185 1082 1082 1172 1082 1082 1172 1094 1094 1185 1095 1095 1186 1082 1082 1172 1095 1095 1186 1083 1083 1173 1083 1083 1173 1095 1095 1186 1096 1096 1187 1083 1083 1173 1096 1096 1187 1084 1084 1174 1084 1084 1174 1096 1096 1187 1097 1097 1188 1084 1084 1174 1097 1097 1188 1085 1085 1175 1085 1085 1175 1097 1097 1188 1098 1098 1189 1085 1085 1175 1098 1098 1189 1086 1086 1176 1086 1086 1176 1098 1098 1189 1099 1099 1190 1086 1086 1176 1099 1099 1190 1087 1087 1177 1087 1087 1177 1099 1099 1190 1100 1100 1191 1087 1087 1177 1100 1100 1191 1088 1088 1178 1088 1088 1178 1100 1100 1191 1101 1101 1192 1088 1088 1178 1101 1101 1192 1089 1089 1179 1089 1089 1179 1101 1101 1192 1102 1102 1193 1089 1089 1179 1102 1102 1193 1090 1090 1180 1090 1090 1180 1102 1102 1193 1103 1103 1194 1090 1090 1180 1103 1103 1194 1091 1091 1181 1091 1091 1181 1103 1103 1194 1092 1092 1195 1091 1091 1181 1092 1092 1195 1080 1080 1182 1092 1092 1183 1104 1104 1196 1105 1105 1197 1092 1092 1183 1105 1105 1197 1093 1093 1184 1093 1093 1184 1105 1105 1197 1106 1106 1198 1093 1093 1184 1106 1106 1198 1094 1094 1185 1094 1094 1185 1106 1106 1198 1107 1107 1199 1094 1094 1185 1107 1107 1199 1095 1095 1186 1095 1095 1186 1107 1107 1199 1108 1108 1200 1095 1095 1186 1108 1108 1200 1096 1096 1187 1096 1096 1187 1108 1108 1200 1109 1109 1201 1096 1096 1187 1109 1109 1201 1097 1097 1188 1097 1097 1188 1109 1109 1201 1110 1110 1202 1097 1097 1188 1110 1110 1202 1098 1098 1189 1098 1098 1189 1110 1110 1202 1111 1111 1203 1098 1098 1189 1111 1111 1203 1099 1099 1190 1099 1099 1190 1111 1111 1203 1112 1112 1204 1099 1099 1190 1112 1112 1204 1100 1100 1191 1100 1100 1191 1112 1112 1204 1113 1113 1205 1100 1100 1191 1113 1113 1205 1101 1101 1192 1101 1101 1192 1113 1113 1205 1114 1114 1206 1101 1101 1192 1114 1114 1206 1102 1102 1193 1102 1102 1193 1114 1114 1206 1115 1115 1207 1102 1102 1193 1115 1115 1207 1103 1103 1194 1103 1103 1194 1115 1115 1207 1104 1104 1208 1103 1103 1194 1104 1104 1208 1092 1092 1195 1104 1104 1196 1116 1116 1209 1117 1117 1210 1104 1104 1196 1117 1117 1210 1105 1105 1197 1105 1105 1197 1117 1117 1210 1118 1118 1211 1105 1105 1197 1118 1118 1211 1106 1106 1198 1106 1106 1198 1118 1118 1211 1119 1119 1212 1106 1106 1198 1119 1119 1212 1107 1107 1199 1107 1107 1199 1119 1119 1212 1120 1120 1213 1107 1107 1199 1120 1120 1213 1108 1108 1200 1108 1108 1200 1120 1120 1213 1121 1121 1214 1108 1108 1200 1121 1121 1214 1109 1109 1201 1109 1109 1201 1121 1121 1214 1122 1122 1215 1109 1109 1201 1122 1122 1215 1110 1110 1202 1110 1110 1202 1122 1122 1215 1123 1123 1216 1110 1110 1202 1123 1123 1216 1111 1111 1203 1111 1111 1203 1123 1123 1216 1124 1124 1217 1111 1111 1203 1124 1124 1217 1112 1112 1204 1112 1112 1204 1124 1124 1217 1125 1125 1218 1112 1112 1204 1125 1125 1218 1113 1113 1205 1113 1113 1205 1125 1125 1218 1126 1126 1219 1113 1113 1205 1126 1126 1219 1114 1114 1206 1114 1114 1206 1126 1126 1219 1127 1127 1220 1114 1114 1206 1127 1127 1220 1115 1115 1207 1115 1115 1207 1127 1127 1220 1116 1116 1221 1115 1115 1207 1116 1116 1221 1104 1104 1208 1116 1116 1209 1128 1128 1222 1129 1129 1223 1116 1116 1209 1129 1129 1223 1117 1117 1210 1117 1117 1210 1129 1129 1223 1130 1130 1224 1117 1117 1210 1130 1130 1224 1118 1118 1211 1118 1118 1211 1130 1130 1224 1131 1131 1225 1118 1118 1211 1131 1131 1225 1119 1119 1212 1119 1119 1212 1131 1131 1225 1132 1132 1226 1119 1119 1212 1132 1132 1226 1120 1120 1213 1120 1120 1213 1132 1132 1226 1133 1133 1227 1120 1120 1213 1133 1133 1227 1121 1121 1214 1121 1121 1214 1133 1133 1227 1134 1134 1228 1121 1121 1214 1134 1134 1228 1122 1122 1215 1122 1122 1215 1134 1134 1228 1135 1135 1229 1122 1122 1215 1135 1135 1229 1123 1123 1216 1123 1123 1216 1135 1135 1229 1136 1136 1230 1123 1123 1216 1136 1136 1230 1124 1124 1217 1124 1124 1217 1136 1136 1230 1137 1137 1231 1124 1124 1217 1137 1137 1231 1125 1125 1218 1125 1125 1218 1137 1137 1231 1138 1138 1232 1125 1125 1218 1138 1138 1232 1126 1126 1219 1126 1126 1219 1138 1138 1232 1139 1139 1233 1126 1126 1219 1139 1139 1233 1127 1127 1220 1127 1127 1220 1139 1139 1233 1128 1128 1234 1127 1127 1220 1128 1128 1234 1116 1116 1221 1128 1128 1222 1140 1140 1235 1141 1141 1236 1128 1128 1222 1141 1141 1236 1129 1129 1223 1129 1129 1223 1141 1141 1236 1142 1142 1237 1129 1129 1223 1142 1142 1237 1130 1130 1224 1130 1130 1224 1142 1142 1237 1143 1143 1238 1130 1130 1224 1143 1143 1238 1131 1131 1225 1131 1131 1225 1143 1143 1238 1144 1144 1239 1131 1131 1225 1144 1144 1239 1132 1132 1226 1132 1132 1226 1144 1144 1239 1145 1145 1240 1132 1132 1226 1145 1145 1240 1133 1133 1227 1133 1133 1227 1145 1145 1240 1146 1146 1241 1133 1133 1227 1146 1146 1241 1134 1134 1228 1134 1134 1228 1146 1146 1241 1147 1147 1242 1134 1134 1228 1147 1147 1242 1135 1135 1229 1135 1135 1229 1147 1147 1242 1148 1148 1243 1135 1135 1229 1148 1148 1243 1136 1136 1230 1136 1136 1230 1148 1148 1243 1149 1149 1244 1136 1136 1230 1149 1149 1244 1137 1137 1231 1137 1137 1231 1149 1149 1244 1150 1150 1245 1137 1137 1231 1150 1150 1245 1138 1138 1232 1138 1138 1232 1150 1150 1245 1151 1151 1246 1138 1138 1232 1151 1151 1246 1139 1139 1233 1139 1139 1233 1151 1151 1246 1140 1140 1247 1139 1139 1233 1140 1140 1247 1128 1128 1234 1140 1140 1235 1152 1152 1248 1153 1153 1249 1140 1140 1235 1153 1153 1249 1141 1141 1236 1141 1141 1236 1153 1153 1249 1154 1154 1250 1141 1141 1236 1154 1154 1250 1142 1142 1237 1142 1142 1237 1154 1154 1250 1155 1155 1251 1142 1142 1237 1155 1155 1251 1143 1143 1238 1143 1143 1238 1155 1155 1251 1156 1156 1252 1143 1143 1238 1156 1156 1252 1144 1144 1239 1144 1144 1239 1156 1156 1252 1157 1157 1253 1144 1144 1239 1157 1157 1253 1145 1145 1240 1145 1145 1240 1157 1157 1253 1158 1158 1254 1145 1145 1240 1158 1158 1254 1146 1146 1241 1146 1146 1241 1158 1158 1254 1159 1159 1255 1146 1146 1241 1159 1159 1255 1147 1147 1242 1147 1147 1242 1159 1159 1255 1160 1160 1256 1147 1147 1242 1160 1160 1256 1148 1148 1243 1148 1148 1243 1160 1160 1256 1161 1161 1257 1148 1148 1243 1161 1161 1257 1149 1149 1244 1149 1149 1244 1161 1161 1257 1162 1162 1258 1149 1149 1244 1162 1162 1258 1150 1150 1245 1150 1150 1245 1162 1162 1258 1163 1163 1259 1150 1150 1245 1163 1163 1259 1151 1151 1246 1151 1151 1246 1163 1163 1259 1152 1152 1260 1151 1151 1246 1152 1152 1260 1140 1140 1247 1152 1152 1248 1164 1164 1261 1165 1165 1262 1152 1152 1248 1165 1165 1262 1153 1153 1249 1153 1153 1249 1165 1165 1262 1166 1166 1263 1153 1153 1249 1166 1166 1263 1154 1154 1250 1154 1154 1250 1166 1166 1263 1167 1167 1264 1154 1154 1250 1167 1167 1264 1155 1155 1251 1155 1155 1251 1167 1167 1264 1168 1168 1265 1155 1155 1251 1168 1168 1265 1156 1156 1252 1156 1156 1252 1168 1168 1265 1169 1169 1266 1156 1156 1252 1169 1169 1266 1157 1157 1253 1157 1157 1253 1169 1169 1266 1170 1170 1267 1157 1157 1253 1170 1170 1267 1158 1158 1254 1158 1158 1254 1170 1170 1267 1171 1171 1268 1158 1158 1254 1171 1171 1268 1159 1159 1255 1159 1159 1255 1171 1171 1268 1172 1172 1269 1159 1159 1255 1172 1172 1269 1160 1160 1256 1160 1160 1256 1172 1172 1269 1173 1173 1270 1160 1160 1256 1173 1173 1270 1161 1161 1257 1161 1161 1257 1173 1173 1270 1174 1174 1271 1161 1161 1257 1174 1174 1271 1162 1162 1258 1162 1162 1258 1174 1174 1271 1175 1175 1272 1162 1162 1258 1175 1175 1272 1163 1163 1259 1163 1163 1259 1175 1175 1272 1164 1164 1273 1163 1163 1259 1164 1164 1273 1152 1152 1260 1164 1164 1261 1176 1176 1274 1177 1177 1275 1164 1164 1261 1177 1177 1275 1165 1165 1262 1165 1165 1262 1177 1177 1275 1178 1178 1276 1165 1165 1262 1178 1178 1276 1166 1166 1263 1166 1166 1263 1178 1178 1276 1179 1179 1277 1166 1166 1263 1179 1179 1277 1167 1167 1264 1167 1167 1264 1179 1179 1277 1180 1180 1278 1167 1167 1264 1180 1180 1278 1168 1168 1265 1168 1168 1265 1180 1180 1278 1181 1181 1279 1168 1168 1265 1181 1181 1279 1169 1169 1266 1169 1169 1266 1181 1181 1279 1182 1182 1280 1169 1169 1266 1182 1182 1280 1170 1170 1267 1170 1170 1267 1182 1182 1280 1183 1183 1281 1170 1170 1267 1183 1183 1281 1171 1171 1268 1171 1171 1268 1183 1183 1281 1184 1184 1282 1171 1171 1268 1184 1184 1282 1172 1172 1269 1172 1172 1269 1184 1184 1282 1185 1185 1283 1172 1172 1269 1185 1185 1283 1173 1173 1270 1173 1173 1270 1185 1185 1283 1186 1186 1284 1173 1173 1270 1186 1186 1284 1174 1174 1271 1174 1174 1271 1186 1186 1284 1187 1187 1285 1174 1174 1271 1187 1187 1285 1175 1175 1272 1175 1175 1272 1187 1187 1285 1176 1176 1286 1175 1175 1272 1176 1176 1286 1164 1164 1273 1176 1176 1274 1188 1188 1287 1189 1189 1288 1176 1176 1274 1189 1189 1288 1177 1177 1275 1177 1177 1275 1189 1189 1288 1190 1190 1289 1177 1177 1275 1190 1190 1289 1178 1178 1276 1178 1178 1276 1190 1190 1289 1191 1191 1290 1178 1178 1276 1191 1191 1290 1179 1179 1277 1179 1179 1277 1191 1191 1290 1192 1192 1291 1179 1179 1277 1192 1192 1291 1180 1180 1278 1180 1180 1278 1192 1192 1291 1193 1193 1292 1180 1180 1278 1193 1193 1292 1181 1181 1279 1181 1181 1279 1193 1193 1292 1194 1194 1293 1181 1181 1279 1194 1194 1293 1182 1182 1280 1182 1182 1280 1194 1194 1293 1195 1195 1294 1182 1182 1280 1195 1195 1294 1183 1183 1281 1183 1183 1281 1195 1195 1294 1196 1196 1295 1183 1183 1281 1196 1196 1295 1184 1184 1282 1184 1184 1282 1196 1196 1295 1197 1197 1296 1184 1184 1282 1197 1197 1296 1185 1185 1283 1185 1185 1283 1197 1197 1296 1198 1198 1297 1185 1185 1283 1198 1198 1297 1186 1186 1284 1186 1186 1284 1198 1198 1297 1199 1199 1298 1186 1186 1284 1199 1199 1298 1187 1187 1285 1187 1187 1285 1199 1199 1298 1188 1188 1299 1187 1187 1285 1188 1188 1299 1176 1176 1286 1188 1188 1287 1200 1200 1300 1201 1201 1301 1188 1188 1287 1201 1201 1301 1189 1189 1288 1189 1189 1288 1201 1201 1301 1202 1202 1302 1189 1189 1288 1202 1202 1302 1190 1190 1289 1190 1190 1289 1202 1202 1302 1203 1203 1303 1190 1190 1289 1203 1203 1303 1191 1191 1290 1191 1191 1290 1203 1203 1303 1204 1204 1304 1191 1191 1290 1204 1204 1304 1192 1192 1291 1192 1192 1291 1204 1204 1304 1205 1205 1305 1192 1192 1291 1205 1205 1305 1193 1193 1292 1193 1193 1292 1205 1205 1305 1206 1206 1306 1193 1193 1292 1206 1206 1306 1194 1194 1293 1194 1194 1293 1206 1206 1306 1207 1207 1307 1194 1194 1293 1207 1207 1307 1195 1195 1294 1195 1195 1294 1207 1207 1307 1208 1208 1308 1195 1195 1294 1208 1208 1308 1196 1196 1295 1196 1196 1295 1208 1208 1308 1209 1209 1309 1196 1196 1295 1209 1209 1309 1197 1197 1296 1197 1197 1296 1209 1209 1309 1210 1210 1310 1197 1197 1296 1210 1210 1310 1198 1198 1297 1198 1198 1297 1210 1210 1310 1211 1211 1311 1198 1198 1297 1211 1211 1311 1199 1199 1298 1199 1199 1298 1211 1211 1311 1200 1200 1312 1199 1199 1298 1200 1200 1312 1188 1188 1299 1200 1200 1300 1212 1212 1313 1213 1213 1314 1200 1200 1300 1213 1213 1314 1201 1201 1301 1201 1201 1301 1213 1213 1314 1214 1214 1315 1201 1201 1301 1214 1214 1315 1202 1202 1302 1202 1202 1302 1214 1214 1315 1215 1215 1316 1202 1202 1302 1215 1215 1316 1203 1203 1303 1203 1203 1303 1215 1215 1316 1216 1216 1317 1203 1203 1303 1216 1216 1317 1204 1204 1304 1204 1204 1304 1216 1216 1317 1217 1217 1318 1204 1204 1304 1217 1217 1318 1205 1205 1305 1205 1205 1305 1217 1217 1318 1218 1218 1319 1205 1205 1305 1218 1218 1319 1206 1206 1306 1206 1206 1306 1218 1218 1319 1219 1219 1320 1206 1206 1306 1219 1219 1320 1207 1207 1307 1207 1207 1307 1219 1219 1320 1220 1220 1321 1207 1207 1307 1220 1220 1321 1208 1208 1308 1208 1208 1308 1220 1220 1321 1221 1221 1322 1208 1208 1308 1221 1221 1322 1209 1209 1309 1209 1209 1309 1221 1221 1322 1222 1222 1323 1209 1209 1309 1222 1222 1323 1210 1210 1310 1210 1210 1310 1222 1222 1323 1223 1223 1324 1210 1210 1310 1223 1223 1324 1211 1211 1311 1211 1211 1311 1223 1223 1324 1212 1212 1325 1211 1211 1311 1212 1212 1325 1200 1200 1312 1212 1212 1313 1224 1224 1326 1225 1225 1327 1212 1212 1313 1225 1225 1327 1213 1213 1314 1213 1213 1314 1225 1225 1327 1226 1226 1328 1213 1213 1314 1226 1226 1328 1214 1214 1315 1214 1214 1315 1226 1226 1328 1227 1227 1329 1214 1214 1315 1227 1227 1329 1215 1215 1316 1215 1215 1316 1227 1227 1329 1228 1228 1330 1215 1215 1316 1228 1228 1330 1216 1216 1317 1216 1216 1317 1228 1228 1330 1229 1229 1331 1216 1216 1317 1229 1229 1331 1217 1217 1318 1217 1217 1318 1229 1229 1331 1230 1230 1332 1217 1217 1318 1230 1230 1332 1218 1218 1319 1218 1218 1319 1230 1230 1332 1231 1231 1333 1218 1218 1319 1231 1231 1333 1219 1219 1320 1219 1219 1320 1231 1231 1333 1232 1232 1334 1219 1219 1320 1232 1232 1334 1220 1220 1321 1220 1220 1321 1232 1232 1334 1233 1233 1335 1220 1220 1321 1233 1233 1335 1221 1221 1322 1221 1221 1322 1233 1233 1335 1234 1234 1336 1221 1221 1322 1234 1234 1336 1222 1222 1323 1222 1222 1323 1234 1234 1336 1235 1235 1337 1222 1222 1323 1235 1235 1337 1223 1223 1324 1223 1223 1324 1235 1235 1337 1224 1224 1338 1223 1223 1324 1224 1224 1338 1212 1212 1325 1224 1224 1326 1236 1236 1339 1237 1237 1340 1224 1224 1326 1237 1237 1340 1225 1225 1327 1225 1225 1327 1237 1237 1340 1238 1238 1341 1225 1225 1327 1238 1238 1341 1226 1226 1328 1226 1226 1328 1238 1238 1341 1239 1239 1342 1226 1226 1328 1239 1239 1342 1227 1227 1329 1227 1227 1329 1239 1239 1342 1240 1240 1343 1227 1227 1329 1240 1240 1343 1228 1228 1330 1228 1228 1330 1240 1240 1343 1241 1241 1344 1228 1228 1330 1241 1241 1344 1229 1229 1331 1229 1229 1331 1241 1241 1344 1242 1242 1345 1229 1229 1331 1242 1242 1345 1230 1230 1332 1230 1230 1332 1242 1242 1345 1243 1243 1346 1230 1230 1332 1243 1243 1346 1231 1231 1333 1231 1231 1333 1243 1243 1346 1244 1244 1347 1231 1231 1333 1244 1244 1347 1232 1232 1334 1232 1232 1334 1244 1244 1347 1245 1245 1348 1232 1232 1334 1245 1245 1348 1233 1233 1335 1233 1233 1335 1245 1245 1348 1246 1246 1349 1233 1233 1335 1246 1246 1349 1234 1234 1336 1234 1234 1336 1246 1246 1349 1247 1247 1350 1234 1234 1336 1247 1247 1350 1235 1235 1337 1235 1235 1337 1247 1247 1350 1236 1236 1351 1235 1235 1337 1236 1236 1351 1224 1224 1338 1236 1236 1339 1248 1248 1352 1249 1249 1353 1236 1236 1339 1249 1249 1353 1237 1237 1340 1237 1237 1340 1249 1249 1353 1250 1250 1354 1237 1237 1340 1250 1250 1354 1238 1238 1341 1238 1238 1341 1250 1250 1354 1251 1251 1355 1238 1238 1341 1251 1251 1355 1239 1239 1342 1239 1239 1342 1251 1251 1355 1252 1252 1356 1239 1239 1342 1252 1252 1356 1240 1240 1343 1240 1240 1343 1252 1252 1356 1253 1253 1357 1240 1240 1343 1253 1253 1357 1241 1241 1344 1241 1241 1344 1253 1253 1357 1254 1254 1358 1241 1241 1344 1254 1254 1358 1242 1242 1345 1242 1242 1345 1254 1254 1358 1255 1255 1359 1242 1242 1345 1255 1255 1359 1243 1243 1346 1243 1243 1346 1255 1255 1359 1256 1256 1360 1243 1243 1346 1256 1256 1360 1244 1244 1347 1244 1244 1347 1256 1256 1360 1257 1257 1361 1244 1244 1347 1257 1257 1361 1245 1245 1348 1245 1245 1348 1257 1257 1361 1258 1258 1362 1245 1245 1348 1258 1258 1362 1246 1246 1349 1246 1246 1349 1258 1258 1362 1259 1259 1363 1246 1246 1349 1259 1259 1363 1247 1247 1350 1247 1247 1350 1259 1259 1363 1248 1248 1364 1247 1247 1350 1248 1248 1364 1236 1236 1351 1248 1248 1352 1260 1260 1365 1261 1261 1366 1248 1248 1352 1261 1261 1366 1249 1249 1353 1249 1249 1353 1261 1261 1366 1262 1262 1367 1249 1249 1353 1262 1262 1367 1250 1250 1354 1250 1250 1354 1262 1262 1367 1263 1263 1368 1250 1250 1354 1263 1263 1368 1251 1251 1355 1251 1251 1355 1263 1263 1368 1264 1264 1369 1251 1251 1355 1264 1264 1369 1252 1252 1356 1252 1252 1356 1264 1264 1369 1265 1265 1370 1252 1252 1356 1265 1265 1370 1253 1253 1357 1253 1253 1357 1265 1265 1370 1266 1266 1371 1253 1253 1357 1266 1266 1371 1254 1254 1358 1254 1254 1358 1266 1266 1371 1267 1267 1372 1254 1254 1358 1267 1267 1372 1255 1255 1359 1255 1255 1359 1267 1267 1372 1268 1268 1373 1255 1255 1359 1268 1268 1373 1256 1256 1360 1256 1256 1360 1268 1268 1373 1269 1269 1374 1256 1256 1360 1269 1269 1374 1257 1257 1361 1257 1257 1361 1269 1269 1374 1270 1270 1375 1257 1257 1361 1270 1270 1375 1258 1258 1362 1258 1258 1362 1270 1270 1375 1271 1271 1376 1258 1258 1362 1271 1271 1376 1259 1259 1363 1259 1259 1363 1271 1271 1376 1260 1260 1377 1259 1259 1363 1260 1260 1377 1248 1248 1364 1260 1260 1365 1272 1272 1378 1273 1273 1379 1260 1260 1365 1273 1273 1379 1261 1261 1366 1261 1261 1366 1273 1273 1379 1274 1274 1380 1261 1261 1366 1274 1274 1380 1262 1262 1367 1262 1262 1367 1274 1274 1380 1275 1275 1381 1262 1262 1367 1275 1275 1381 1263 1263 1368 1263 1263 1368 1275 1275 1381 1276 1276 1382 1263 1263 1368 1276 1276 1382 1264 1264 1369 1264 1264 1369 1276 1276 1382 1277 1277 1383 1264 1264 1369 1277 1277 1383 1265 1265 1370 1265 1265 1370 1277 1277 1383 1278 1278 1384 1265 1265 1370 1278 1278 1384 1266 1266 1371 1266 1266 1371 1278 1278 1384 1279 1279 1385 1266 1266 1371 1279 1279 1385 1267 1267 1372 1267 1267 1372 1279 1279 1385 1280 1280 1386 1267 1267 1372 1280 1280 1386 1268 1268 1373 1268 1268 1373 1280 1280 1386 1281 1281 1387 1268 1268 1373 1281 1281 1387 1269 1269 1374 1269 1269 1374 1281 1281 1387 1282 1282 1388 1269 1269 1374 1282 1282 1388 1270 1270 1375 1270 1270 1375 1282 1282 1388 1283 1283 1389 1270 1270 1375 1283 1283 1389 1271 1271 1376 1271 1271 1376 1283 1283 1389 1272 1272 1390 1271 1271 1376 1272 1272 1390 1260 1260 1377 1272 1272 1378 1284 1284 1391 1285 1285 1392 1272 1272 1378 1285 1285 1392 1273 1273 1379 1273 1273 1379 1285 1285 1392 1286 1286 1393 1273 1273 1379 1286 1286 1393 1274 1274 1380 1274 1274 1380 1286 1286 1393 1287 1287 1394 1274 1274 1380 1287 1287 1394 1275 1275 1381 1275 1275 1381 1287 1287 1394 1288 1288 1395 1275 1275 1381 1288 1288 1395 1276 1276 1382 1276 1276 1382 1288 1288 1395 1289 1289 1396 1276 1276 1382 1289 1289 1396 1277 1277 1383 1277 1277 1383 1289 1289 1396 1290 1290 1397 1277 1277 1383 1290 1290 1397 1278 1278 1384 1278 1278 1384 1290 1290 1397 1291 1291 1398 1278 1278 1384 1291 1291 1398 1279 1279 1385 1279 1279 1385 1291 1291 1398 1292 1292 1399 1279 1279 1385 1292 1292 1399 1280 1280 1386 1280 1280 1386 1292 1292 1399 1293 1293 1400 1280 1280 1386 1293 1293 1400 1281 1281 1387 1281 1281 1387 1293 1293 1400 1294 1294 1401 1281 1281 1387 1294 1294 1401 1282 1282 1388 1282 1282 1388 1294 1294 1401 1295 1295 1402 1282 1282 1388 1295 1295 1402 1283 1283 1389 1283 1283 1389 1295 1295 1402 1284 1284 1403 1283 1283 1389 1284 1284 1403 1272 1272 1390 1284 1284 1391 1296 1296 1404 1297 1297 1405 1284 1284 1391 1297 1297 1405 1285 1285 1392 1285 1285 1392 1297 1297 1405 1298 1298 1406 1285 1285 1392 1298 1298 1406 1286 1286 1393 1286 1286 1393 1298 1298 1406 1299 1299 1407 1286 1286 1393 1299 1299 1407 1287 1287 1394 1287 1287 1394 1299 1299 1407 1300 1300 1408 1287 1287 1394 1300 1300 1408 1288 1288 1395 1288 1288 1395 1300 1300 1408 1301 1301 1409 1288 1288 1395 1301 1301 1409 1289 1289 1396 1289 1289 1396 1301 1301 1409 1302 1302 1410 1289 1289 1396 1302 1302 1410 1290 1290 1397 1290 1290 1397 1302 1302 1410 1303 1303 1411 1290 1290 1397 1303 1303 1411 1291 1291 1398 1291 1291 1398 1303 1303 1411 1304 1304 1412 1291 1291 1398 1304 1304 1412 1292 1292 1399 1292 1292 1399 1304 1304 1412 1305 1305 1413 1292 1292 1399 1305 1305 1413 1293 1293 1400 1293 1293 1400 1305 1305 1413 1306 1306 1414 1293 1293 1400 1306 1306 1414 1294 1294 1401 1294 1294 1401 1306 1306 1414 1307 1307 1415 1294 1294 1401 1307 1307 1415 1295 1295 1402 1295 1295 1402 1307 1307 1415 1296 1296 1416 1295 1295 1402 1296 1296 1416 1284 1284 1403 1296 1296 1404 1308 1308 1417 1309 1309 1418 1296 1296 1404 1309 1309 1418 1297 1297 1405 1297 1297 1405 1309 1309 1418 1310 1310 1419 1297 1297 1405 1310 1310 1419 1298 1298 1406 1298 1298 1406 1310 1310 1419 1311 1311 1420 1298 1298 1406 1311 1311 1420 1299 1299 1407 1299 1299 1407 1311 1311 1420 1312 1312 1421 1299 1299 1407 1312 1312 1421 1300 1300 1408 1300 1300 1408 1312 1312 1421 1313 1313 1422 1300 1300 1408 1313 1313 1422 1301 1301 1409 1301 1301 1409 1313 1313 1422 1314 1314 1423 1301 1301 1409 1314 1314 1423 1302 1302 1410 1302 1302 1410 1314 1314 1423 1315 1315 1424 1302 1302 1410 1315 1315 1424 1303 1303 1411 1303 1303 1411 1315 1315 1424 1316 1316 1425 1303 1303 1411 1316 1316 1425 1304 1304 1412 1304 1304 1412 1316 1316 1425 1317 1317 1426 1304 1304 1412 1317 1317 1426 1305 1305 1413 1305 1305 1413 1317 1317 1426 1318 1318 1427 1305 1305 1413 1318 1318 1427 1306 1306 1414 1306 1306 1414 1318 1318 1427 1319 1319 1428 1306 1306 1414 1319 1319 1428 1307 1307 1415 1307 1307 1415 1319 1319 1428 1308 1308 1429 1307 1307 1415 1308 1308 1429 1296 1296 1416 1308 1308 1417 1320 1320 1430 1321 1321 1431 1308 1308 1417 1321 1321 1431 1309 1309 1418 1309 1309 1418 1321 1321 1431 1322 1322 1432 1309 1309 1418 1322 1322 1432 1310 1310 1419 1310 1310 1419 1322 1322 1432 1323 1323 1433 1310 1310 1419 1323 1323 1433 1311 1311 1420 1311 1311 1420 1323 1323 1433 1324 1324 1434 1311 1311 1420 1324 1324 1434 1312 1312 1421 1312 1312 1421 1324 1324 1434 1325 1325 1435 1312 1312 1421 1325 1325 1435 1313 1313 1422 1313 1313 1422 1325 1325 1435 1326 1326 1436 1313 1313 1422 1326 1326 1436 1314 1314 1423 1314 1314 1423 1326 1326 1436 1327 1327 1437 1314 1314 1423 1327 1327 1437 1315 1315 1424 1315 1315 1424 1327 1327 1437 1328 1328 1438 1315 1315 1424 1328 1328 1438 1316 1316 1425 1316 1316 1425 1328 1328 1438 1329 1329 1439 1316 1316 1425 1329 1329 1439 1317 1317 1426 1317 1317 1426 1329 1329 1439 1330 1330 1440 1317 1317 1426 1330 1330 1440 1318 1318 1427 1318 1318 1427 1330 1330 1440 1331 1331 1441 1318 1318 1427 1331 1331 1441 1319 1319 1428 1319 1319 1428 1331 1331 1441 1320 1320 1442 1319 1319 1428 1320 1320 1442 1308 1308 1429 1320 1320 1430 1332 1332 1443 1333 1333 1444 1320 1320 1430 1333 1333 1444 1321 1321 1431 1321 1321 1431 1333 1333 1444 1334 1334 1445 1321 1321 1431 1334 1334 1445 1322 1322 1432 1322 1322 1432 1334 1334 1445 1335 1335 1446 1322 1322 1432 1335 1335 1446 1323 1323 1433 1323 1323 1433 1335 1335 1446 1336 1336 1447 1323 1323 1433 1336 1336 1447 1324 1324 1434 1324 1324 1434 1336 1336 1447 1337 1337 1448 1324 1324 1434 1337 1337 1448 1325 1325 1435 1325 1325 1435 1337 1337 1448 1338 1338 1449 1325 1325 1435 1338 1338 1449 1326 1326 1436 1326 1326 1436 1338 1338 1449 1339 1339 1450 1326 1326 1436 1339 1339 1450 1327 1327 1437 1327 1327 1437 1339 1339 1450 1340 1340 1451 1327 1327 1437 1340 1340 1451 1328 1328 1438 1328 1328 1438 1340 1340 1451 1341 1341 1452 1328 1328 1438 1341 1341 1452 1329 1329 1439 1329 1329 1439 1341 1341 1452 1342 1342 1453 1329 1329 1439 1342 1342 1453 1330 1330 1440 1330 1330 1440 1342 1342 1453 1343 1343 1454 1330 1330 1440 1343 1343 1454 1331 1331 1441 1331 1331 1441 1343 1343 1454 1332 1332 1455 1331 1331 1441 1332 1332 1455 1320 1320 1442 1332 1332 1443 1344 1344 1456 1345 1345 1457 1332 1332 1443 1345 1345 1457 1333 1333 1444 1333 1333 1444 1345 1345 1457 1346 1346 1458 1333 1333 1444 1346 1346 1458 1334 1334 1445 1334 1334 1445 1346 1346 1458 1347 1347 1459 1334 1334 1445 1347 1347 1459 1335 1335 1446 1335 1335 1446 1347 1347 1459 1348 1348 1460 1335 1335 1446 1348 1348 1460 1336 1336 1447 1336 1336 1447 1348 1348 1460 1349 1349 1461 1336 1336 1447 1349 1349 1461 1337 1337 1448 1337 1337 1448 1349 1349 1461 1350 1350 1462 1337 1337 1448 1350 1350 1462 1338 1338 1449 1338 1338 1449 1350 1350 1462 1351 1351 1463 1338 1338 1449 1351 1351 1463 1339 1339 1450 1339 1339 1450 1351 1351 1463 1352 1352 1464 1339 1339 1450 1352 1352 1464 1340 1340 1451 1340 1340 1451 1352 1352 1464 1353 1353 1465 1340 1340 1451 1353 1353 1465 1341 1341 1452 1341 1341 1452 1353 1353 1465 1354 1354 1466 1341 1341 1452 1354 1354 1466 1342 1342 1453 1342 1342 1453 1354 1354 1466 1355 1355 1467 1342 1342 1453 1355 1355 1467 1343 1343 1454 1343 1343 1454 1355 1355 1467 1344 1344 1468 1343 1343 1454 1344 1344 1468 1332 1332 1455 1344 1344 1456 1356 1356 1469 1357 1357 1470 1344 1344 1456 1357 1357 1470 1345 1345 1457 1345 1345 1457 1357 1357 1470 1358 1358 1471 1345 1345 1457 1358 1358 1471 1346 1346 1458 1346 1346 1458 1358 1358 1471 1359 1359 1472 1346 1346 1458 1359 1359 1472 1347 1347 1459 1347 1347 1459 1359 1359 1472 1360 1360 1473 1347 1347 1459 1360 1360 1473 1348 1348 1460 1348 1348 1460 1360 1360 1473 1361 1361 1474 1348 1348 1460 1361 1361 1474 1349 1349 1461 1349 1349 1461 1361 1361 1474 1362 1362 1475 1349 1349 1461 1362 1362 1475 1350 1350 1462 1350 1350 1462 1362 1362 1475 1363 1363 1476 1350 1350 1462 1363 1363 1476 1351 1351 1463 1351 1351 1463 1363 1363 1476 1364 1364 1477 1351 1351 1463 1364 1364 1477 1352 1352 1464 1352 1352 1464 1364 1364 1477 1365 1365 1478 1352 1352 1464 1365 1365 1478 1353 1353 1465 1353 1353 1465 1365 1365 1478 1366 1366 1479 1353 1353 1465 1366 1366 1479 1354 1354 1466 1354 1354 1466 1366 1366 1479 1367 1367 1480 1354 1354 1466 1367 1367 1480 1355 1355 1467 1355 1355 1467 1367 1367 1480 1356 1356 1481 1355 1355 1467 1356 1356 1481 1344 1344 1468 1356 1356 1469 1368 1368 1482 1369 1369 1483 1356 1356 1469 1369 1369 1483 1357 1357 1470 1357 1357 1470 1369 1369 1483 1370 1370 1484 1357 1357 1470 1370 1370 1484 1358 1358 1471 1358 1358 1471 1370 1370 1484 1371 1371 1485 1358 1358 1471 1371 1371 1485 1359 1359 1472 1359 1359 1472 1371 1371 1485 1372 1372 1486 1359 1359 1472 1372 1372 1486 1360 1360 1473 1360 1360 1473 1372 1372 1486 1373 1373 1487 1360 1360 1473 1373 1373 1487 1361 1361 1474 1361 1361 1474 1373 1373 1487 1374 1374 1488 1361 1361 1474 1374 1374 1488 1362 1362 1475 1362 1362 1475 1374 1374 1488 1375 1375 1489 1362 1362 1475 1375 1375 1489 1363 1363 1476 1363 1363 1476 1375 1375 1489 1376 1376 1490 1363 1363 1476 1376 1376 1490 1364 1364 1477 1364 1364 1477 1376 1376 1490 1377 1377 1491 1364 1364 1477 1377 1377 1491 1365 1365 1478 1365 1365 1478 1377 1377 1491 1378 1378 1492 1365 1365 1478 1378 1378 1492 1366 1366 1479 1366 1366 1479 1378 1378 1492 1379 1379 1493 1366 1366 1479 1379 1379 1493 1367 1367 1480 1367 1367 1480 1379 1379 1493 1368 1368 1494 1367 1367 1480 1368 1368 1494 1356 1356 1481 1368 1368 1482 1380 1380 1495 1381 1381 1496 1368 1368 1482 1381 1381 1496 1369 1369 1483 1369 1369 1483 1381 1381 1496 1382 1382 1497 1369 1369 1483 1382 1382 1497 1370 1370 1484 1370 1370 1484 1382 1382 1497 1383 1383 1498 1370 1370 1484 1383 1383 1498 1371 1371 1485 1371 1371 1485 1383 1383 1498 1384 1384 1499 1371 1371 1485 1384 1384 1499 1372 1372 1486 1372 1372 1486 1384 1384 1499 1385 1385 1500 1372 1372 1486 1385 1385 1500 1373 1373 1487 1373 1373 1487 1385 1385 1500 1386 1386 1501 1373 1373 1487 1386 1386 1501 1374 1374 1488 1374 1374 1488 1386 1386 1501 1387 1387 1502 1374 1374 1488 1387 1387 1502 1375 1375 1489 1375 1375 1489 1387 1387 1502 1388 1388 1503 1375 1375 1489 1388 1388 1503 1376 1376 1490 1376 1376 1490 1388 1388 1503 1389 1389 1504 1376 1376 1490 1389 1389 1504 1377 1377 1491 1377 1377 1491 1389 1389 1504 1390 1390 1505 1377 1377 1491 1390 1390 1505 1378 1378 1492 1378 1378 1492 1390 1390 1505 1391 1391 1506 1378 1378 1492 1391 1391 1506 1379 1379 1493 1379 1379 1493 1391 1391 1506 1380 1380 1507 1379 1379 1493 1380 1380 1507 1368 1368 1494 1380 1380 1495 1392 1392 1508 1393 1393 1509 1380 1380 1495 1393 1393 1509 1381 1381 1496 1381 1381 1496 1393 1393 1509 1394 1394 1510 1381 1381 1496 1394 1394 1510 1382 1382 1497 1382 1382 1497 1394 1394 1510 1395 1395 1511 1382 1382 1497 1395 1395 1511 1383 1383 1498 1383 1383 1498 1395 1395 1511 1396 1396 1512 1383 1383 1498 1396 1396 1512 1384 1384 1499 1384 1384 1499 1396 1396 1512 1397 1397 1513 1384 1384 1499 1397 1397 1513 1385 1385 1500 1385 1385 1500 1397 1397 1513 1398 1398 1514 1385 1385 1500 1398 1398 1514 1386 1386 1501 1386 1386 1501 1398 1398 1514 1399 1399 1515 1386 1386 1501 1399 1399 1515 1387 1387 1502 1387 1387 1502 1399 1399 1515 1400 1400 1516 1387 1387 1502 1400 1400 1516 1388 1388 1503 1388 1388 1503 1400 1400 1516 1401 1401 1517 1388 1388 1503 1401 1401 1517 1389 1389 1504 1389 1389 1504 1401 1401 1517 1402 1402 1518 1389 1389 1504 1402 1402 1518 1390 1390 1505 1390 1390 1505 1402 1402 1518 1403 1403 1519 1390 1390 1505 1403 1403 1519 1391 1391 1506 1391 1391 1506 1403 1403 1519 1392 1392 1520 1391 1391 1506 1392 1392 1520 1380 1380 1507 1392 1392 1508 1404 1404 1521 1405 1405 1522 1392 1392 1508 1405 1405 1522 1393 1393 1509 1393 1393 1509 1405 1405 1522 1406 1406 1523 1393 1393 1509 1406 1406 1523 1394 1394 1510 1394 1394 1510 1406 1406 1523 1407 1407 1524 1394 1394 1510 1407 1407 1524 1395 1395 1511 1395 1395 1511 1407 1407 1524 1408 1408 1525 1395 1395 1511 1408 1408 1525 1396 1396 1512 1396 1396 1512 1408 1408 1525 1409 1409 1526 1396 1396 1512 1409 1409 1526 1397 1397 1513 1397 1397 1513 1409 1409 1526 1410 1410 1527 1397 1397 1513 1410 1410 1527 1398 1398 1514 1398 1398 1514 1410 1410 1527 1411 1411 1528 1398 1398 1514 1411 1411 1528 1399 1399 1515 1399 1399 1515 1411 1411 1528 1412 1412 1529 1399 1399 1515 1412 1412 1529 1400 1400 1516 1400 1400 1516 1412 1412 1529 1413 1413 1530 1400 1400 1516 1413 1413 1530 1401 1401 1517 1401 1401 1517 1413 1413 1530 1414 1414 1531 1401 1401 1517 1414 1414 1531 1402 1402 1518 1402 1402 1518 1414 1414 1531 1415 1415 1532 1402 1402 1518 1415 1415 1532 1403 1403 1519 1403 1403 1519 1415 1415 1532 1404 1404 1533 1403 1403 1519 1404 1404 1533 1392 1392 1520 1404 1404 1521 1416 1416 1534 1417 1417 1535 1404 1404 1521 1417 1417 1535 1405 1405 1522 1405 1405 1522 1417 1417 1535 1418 1418 1536 1405 1405 1522 1418 1418 1536 1406 1406 1523 1406 1406 1523 1418 1418 1536 1419 1419 1537 1406 1406 1523 1419 1419 1537 1407 1407 1524 1407 1407 1524 1419 1419 1537 1420 1420 1538 1407 1407 1524 1420 1420 1538 1408 1408 1525 1408 1408 1525 1420 1420 1538 1421 1421 1539 1408 1408 1525 1421 1421 1539 1409 1409 1526 1409 1409 1526 1421 1421 1539 1422 1422 1540 1409 1409 1526 1422 1422 1540 1410 1410 1527 1410 1410 1527 1422 1422 1540 1423 1423 1541 1410 1410 1527 1423 1423 1541 1411 1411 1528 1411 1411 1528 1423 1423 1541 1424 1424 1542 1411 1411 1528 1424 1424 1542 1412 1412 1529 1412 1412 1529 1424 1424 1542 1425 1425 1543 1412 1412 1529 1425 1425 1543 1413 1413 1530 1413 1413 1530 1425 1425 1543 1426 1426 1544 1413 1413 1530 1426 1426 1544 1414 1414 1531 1414 1414 1531 1426 1426 1544 1427 1427 1545 1414 1414 1531 1427 1427 1545 1415 1415 1532 1415 1415 1532 1427 1427 1545 1416 1416 1546 1415 1415 1532 1416 1416 1546 1404 1404 1533 1416 1416 1534 1428 1428 1547 1429 1429 1548 1416 1416 1534 1429 1429 1548 1417 1417 1535 1417 1417 1535 1429 1429 1548 1430 1430 1549 1417 1417 1535 1430 1430 1549 1418 1418 1536 1418 1418 1536 1430 1430 1549 1431 1431 1550 1418 1418 1536 1431 1431 1550 1419 1419 1537 1419 1419 1537 1431 1431 1550 1432 1432 1551 1419 1419 1537 1432 1432 1551 1420 1420 1538 1420 1420 1538 1432 1432 1551 1433 1433 1552 1420 1420 1538 1433 1433 1552 1421 1421 1539 1421 1421 1539 1433 1433 1552 1434 1434 1553 1421 1421 1539 1434 1434 1553 1422 1422 1540 1422 1422 1540 1434 1434 1553 1435 1435 1554 1422 1422 1540 1435 1435 1554 1423 1423 1541 1423 1423 1541 1435 1435 1554 1436 1436 1555 1423 1423 1541 1436 1436 1555 1424 1424 1542 1424 1424 1542 1436 1436 1555 1437 1437 1556 1424 1424 1542 1437 1437 1556 1425 1425 1543 1425 1425 1543 1437 1437 1556 1438 1438 1557 1425 1425 1543 1438 1438 1557 1426 1426 1544 1426 1426 1544 1438 1438 1557 1439 1439 1558 1426 1426 1544 1439 1439 1558 1427 1427 1545 1427 1427 1545 1439 1439 1558 1428 1428 1559 1427 1427 1545 1428 1428 1559 1416 1416 1546 1428 1428 1547 0 0 1560 1 3 1561 1428 1428 1547 1 3 1561 1429 1429 1548 1429 1429 1548 1 3 1561 2 5 1562 1429 1429 1548 2 5 1562 1430 1430 1549 1430 1430 1549 2 5 1562 3 7 1563 1430 1430 1549 3 7 1563 1431 1431 1550 1431 1431 1550 3 7 1563 4 9 1564 1431 1431 1550 4 9 1564 1432 1432 1551 1432 1432 1551 4 9 1564 5 11 1565 1432 1432 1551 5 11 1565 1433 1433 1552 1433 1433 1552 5 11 1565 6 13 1566 1433 1433 1552 6 13 1566 1434 1434 1553 1434 1434 1553 6 13 1566 7 15 1567 1434 1434 1553 7 15 1567 1435 1435 1554 1435 1435 1554 7 15 1567 8 17 1568 1435 1435 1554 8 17 1568 1436 1436 1555 1436 1436 1555 8 17 1568 9 19 1569 1436 1436 1555 9 19 1569 1437 1437 1556 1437 1437 1556 9 19 1569 10 21 1570 1437 1437 1556 10 21 1570 1438 1438 1557 1438 1438 1557 10 21 1570 11 23 1571 1438 1438 1557 11 23 1571 1439 1439 1558 1439 1439 1558 11 23 1571 0 0 1572 1439 1439 1558 0 0 1572 1428 1428 1559</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-2_max" name="Torus_Knot-2_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-2_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-3.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-3.DAE
new file mode 100644
index 00000000..31e5842f
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-3.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-3.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:19:36Z</created>
+ <modified>2008-10-31T16:19:38Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="6480">31.726814 -0.006605 13.727729 31.854496 -0.919483 14.941559 30.881302 -1.721458 17.094463 28.924608 -2.315799 19.926765 26.220427 -2.630821 23.096849 23.094917 -2.628527 26.222359 19.925066 -2.309194 28.926308 17.093203 -1.711338 30.882561 14.940891 -0.907069 31.855167 13.727730 0.006605 31.726814 13.600047 0.919483 30.512985 14.573242 1.721457 28.360083 16.529932 2.315799 25.527782 19.234114 2.630821 22.357698 22.359619 2.628527 19.232191 25.529472 2.309195 16.528240 28.361336 1.711339 14.571986 30.513649 0.907071 13.599378 30.786390 3.735097 13.259359 31.352966 2.897694 14.399877 31.072830 2.019259 16.718313 29.979773 1.205744 19.935024 28.205629 0.555271 23.662033 25.964392 0.146297 27.449804 23.526386 0.028149 30.841475 21.185671 0.215079 33.427963 19.224569 0.684540 34.897301 17.879622 1.379907 35.072258 17.313046 2.217310 33.931744 17.593182 3.095744 31.613310 18.686237 3.909259 28.396599 20.460379 4.559732 24.669594 22.701614 4.968707 20.881823 25.139622 5.086854 17.490150 27.480337 4.899925 14.903660 29.441439 4.430465 13.434322 28.820398 6.855691 12.842863 29.800817 6.185897 13.798473 30.306332 5.433066 16.122902 30.275972 4.688000 19.535786 29.713400 4.040566 23.625481 28.686468 3.568854 27.898714 27.319040 3.329759 31.840065 25.776051 3.352119 34.974152 24.243605 3.633238 36.922958 22.906538 4.139208 37.451424 21.926121 4.809002 36.495815 21.420605 5.561833 34.171391 21.450964 6.306899 30.758507 22.013535 6.954332 26.668812 23.040466 7.426045 22.395580 24.407892 7.665141 18.454227 25.950882 7.642780 15.320143 27.483330 7.361662 13.371334 26.038576 9.264955 12.851428 27.346571 8.804632 13.484112 28.641127 8.349689 15.567957 29.766098 7.954998 18.851625 30.585802 7.668165 22.939054 31.001366 7.523787 27.337246 30.962667 7.539279 31.515707 30.474377 7.712769 34.970455 29.595385 8.023335 37.284798 28.431715 8.433516 38.179592 27.123722 8.893839 37.546913 25.829166 9.348783 35.463066 24.704193 9.743473 32.179401 23.884491 10.030306 28.091972 23.468925 10.174684 23.693781 23.507622 10.159193 19.515322 23.995913 9.985703 16.060570 24.874903 9.675138 13.746226 22.919579 11.282253 13.648422 24.402512 10.983977 13.835441 26.359400 10.882333 15.379955 28.554211 10.989581 18.095673 30.722221 11.292784 21.655039 32.601936 11.755372 25.628738 33.966633 12.321548 29.537489 34.651714 12.923027 32.909832 34.574539 13.487258 35.339016 33.744427 13.946188 36.532051 32.261494 14.244464 36.345036 30.304607 14.346108 34.800522 28.109797 14.238860 32.084805 25.941786 13.935658 28.525442 24.062071 13.473071 24.551743 22.697372 12.906894 20.642992 22.012293 12.305415 17.270647 22.089464 11.741184 14.841459 20.047205 13.682938 15.175947 21.516153 13.408149 14.876420 23.888359 13.535955 15.639026 26.877699 14.050941 17.371786 30.123613 14.890992 19.865704 33.234600 15.954785 22.819975 35.835426 17.114012 25.878269 37.612396 18.228851 28.671713 38.351177 19.164839 30.863377 37.962662 19.809078 32.188911 36.493717 20.083868 32.488441 34.121513 19.956060 31.725836 31.132174 19.441074 29.993076 27.886259 18.601025 27.499161 24.775272 17.537233 24.544891 22.174446 16.378006 21.486597 20.397476 15.263166 18.693151 19.658693 14.327180 16.501488 17.773115 17.270491 16.742393 19.055439 16.848503 16.034857 21.546965 16.942738 15.941678 24.947178 17.541828 16.474096 28.845963 18.573513 17.567892 32.773067 19.913355 19.091139 36.254826 21.399752 20.860113 38.871284 22.853418 22.661446 40.306866 24.099028 24.277872 40.388412 24.986334 25.514427 39.106087 25.408319 26.221964 36.614563 25.314085 26.315142 33.214352 24.714996 25.782726 29.315569 23.683313 24.688931 25.388466 22.343472 23.165684 21.906706 20.857077 21.396711 19.290245 19.403408 19.595379 17.854664 18.157799 17.978952 16.071514 22.344303 17.330664 17.047451 21.647644 16.389786 19.390995 21.422750 15.563663 22.819485 21.696747 14.951938 26.919392 22.436584 14.628393 31.196209 23.553028 14.632054 35.134083 24.911419 14.962479 38.258057 26.347912 15.579813 40.191326 27.689251 16.409597 40.700714 28.773643 17.351748 39.724781 29.470303 18.292625 37.381233 29.695194 19.118748 33.952747 29.421200 19.730473 29.852842 28.681362 20.054016 25.576027 27.564922 20.050356 21.638151 26.206532 19.719933 18.514177 24.770035 19.102600 16.580906 23.428699 18.272816 14.676125 28.572083 16.099361 15.285969 27.557344 15.139450 17.283110 26.807186 13.845638 20.426666 26.412088 12.373980 24.337475 26.419704 10.901978 28.543839 26.829117 9.607178 32.538403 27.590944 8.645752 35.839371 28.613300 8.133661 38.048588 29.772869 8.132673 38.899601 30.929794 8.642906 38.289757 31.944530 9.602818 36.292618 32.694691 10.896628 33.149063 33.089790 12.368286 29.238256 33.082172 13.840288 25.031895 32.672760 15.135088 21.037327 31.910934 16.096516 17.736362 30.888580 16.608604 15.527139 29.729010 16.609594 13.282096 35.211140 12.653103 13.518038 33.919609 11.878950 15.047488 32.561394 10.450216 17.685972 31.300304 8.539226 21.115252 30.288456 6.376473 24.921701 29.647892 4.222819 28.646208 29.455872 2.338026 31.839542 29.735554 0.949427 34.116543 30.453207 0.224507 35.202564 31.522272 0.250704 34.966625 32.813801 1.024856 33.437176 34.172020 2.453589 30.798691 35.433105 4.364578 27.369415 36.444958 6.527330 23.562967 37.085522 8.680984 19.838459 37.277542 10.565778 16.645124 36.997860 11.954378 14.368123 36.280209 12.679298 11.662464 41.379196 7.060013 11.557786 39.919147 6.635350 12.571877 37.996574 5.410366 14.582420 35.843361 3.532811 17.346916 33.719223 1.229146 20.531925 31.880356 -1.222771 23.753288 30.548559 -3.527204 26.622461 29.884464 -5.406205 28.793379 29.968174 -6.633137 30.004200 30.789589 -7.060017 30.108877 32.249634 -6.635354 29.094788 34.172211 -5.410370 27.084246 36.325420 -3.532817 24.319752 38.449562 -1.229154 21.134745 40.288425 1.222763 17.913382 41.620228 3.527197 15.044208 42.284321 5.406198 12.873287 42.200615 6.633132 9.693753 46.248405 -0.256655 9.312621 44.772961 -0.227977 9.831593 42.441734 -0.949997 11.188072 39.535912 -2.335630 13.218448 36.405975 -4.217746 15.677826 33.429443 -6.369334 18.269569 30.965332 -8.530882 20.681076 29.310844 -10.441675 22.621481 28.665541 -11.871243 23.856745 29.107252 -12.647160 24.237879 30.582699 -12.675838 23.718906 32.913925 -11.953817 22.362429 35.819744 -10.568187 20.332054 38.949684 -8.686072 17.872677 41.926212 -6.534484 15.280934 44.390324 -4.372936 12.869428 46.044811 -2.462143 10.929021 46.690121 -1.032573 7.326954 49.152576 -8.654326 6.752618 47.837208 -8.141521 6.855957 45.344303 -8.138869 7.624508 41.974545 -8.646692 8.965573 38.134377 -9.603738 10.717399 34.286976 -10.894573 12.668689 30.896406 -12.363503 14.584089 28.371611 -13.833354 16.232574 27.017118 -15.126841 17.415314 26.996304 -16.087948 17.989649 28.311672 -16.600754 17.886311 30.804577 -16.603405 17.117760 34.174332 -16.095585 15.776697 38.014496 -15.138539 14.024872 41.861893 -13.847705 12.073583 45.252468 -12.378775 10.158182 47.777267 -10.908923 8.509696 49.131760 -9.615437 4.552809 49.630367 -17.367418 3.870878 48.647713 -16.422752 3.679944 46.303902 -15.588865 4.003036 42.881638 -14.966338 4.801185 38.793697 -14.630255 5.978121 34.533138 -14.621153 7.391889 30.613855 -14.940128 8.871967 27.508566 -15.548710 10.239837 25.591820 -16.373493 11.330513 25.094799 -17.314997 12.012444 26.077452 -18.259663 12.203377 28.421259 -19.093548 11.880286 31.843523 -19.716076 11.082138 35.931465 -20.052160 9.905203 40.192020 -20.061264 8.491435 44.111305 -19.742289 7.011357 47.216595 -19.133705 5.643487 49.133347 -18.308924 1.421793 47.459431 -25.532022 0.696638 46.946350 -24.293505 0.340652 45.082687 -22.673229 0.396771 42.093227 -20.866625 0.858226 38.338551 -19.091595 1.669359 34.271519 -17.562237 2.732336 30.382683 -16.463011 3.918945 27.141087 -15.926502 5.086065 24.937723 -16.017420 6.092923 24.038342 -16.724798 6.818077 24.551424 -17.963316 7.174064 26.415085 -19.583591 7.117946 29.404539 -21.390196 6.656490 33.159218 -23.165222 5.845358 37.226246 -24.694582 4.782382 41.115086 -25.793808 3.595773 44.356678 -26.330318 2.428653 46.560047 -26.239403 -1.853985 42.762520 -32.203224 -2.603986 42.778240 -30.876469 -3.039907 41.673904 -28.682003 -3.109172 39.582710 -25.884516 -2.803424 36.756889 -22.821424 -2.159542 33.537277 -19.862183 -1.255188 30.312204 -17.363720 -0.199440 27.470661 -15.627386 0.880363 25.355383 -14.862608 1.853981 24.221504 -15.161632 2.603982 24.205784 -16.488388 3.039904 25.310118 -18.682852 3.109169 27.401310 -21.480337 2.803422 30.227129 -24.543428 2.159541 33.446743 -27.502670 1.255187 36.671814 -30.001133 0.199439 39.513359 -31.737469 -0.880364 41.628635 -32.502247 -4.823488 36.173115 -36.539043 -5.634474 36.663593 -35.345409 -6.156865 36.452068 -32.914848 -6.327651 35.564041 -29.540525 -6.126234 34.106632 -25.629431 -5.576909 32.255619 -21.653299 -4.745930 30.234268 -18.091717 -3.733528 28.286377 -15.374257 -2.661811 26.646896 -13.828688 -1.660047 25.513567 -13.641427 -0.849060 25.023088 -14.835061 -0.326670 25.234617 -17.265621 -0.155883 26.122641 -20.639944 -0.357299 27.580050 -24.551039 -0.906625 29.431061 -28.527166 -1.737603 31.452412 -32.088753 -2.750005 33.400303 -34.806213 -3.821721 35.039787 -36.351784 -6.937376 28.817459 -38.179077 -7.873696 29.620474 -37.283810 -8.578462 30.229355 -34.969109 -8.966667 30.570665 -31.514170 -8.991490 30.603233 -27.335701 -8.649937 30.323135 -22.937689 -7.983203 29.764151 -18.850603 -7.071707 28.993704 -15.567404 -6.025388 28.104723 -13.484092 -4.970448 27.204430 -12.851947 -4.034129 26.401417 -13.747212 -3.329363 25.792532 -16.061909 -2.941157 25.451223 -19.516851 -2.916333 25.418653 -23.695318 -3.257886 25.698753 -28.093327 -3.924619 26.257736 -32.180416 -4.836115 27.028183 -35.463615 -5.882433 27.917164 -37.546928 -7.889362 21.889946 -37.447350 -8.995914 22.794601 -36.918030 -10.002944 23.983006 -34.968967 -10.788991 25.311825 -31.835251 -11.259247 26.620779 -27.894848 -11.356991 27.751991 -23.623030 -11.070433 28.569021 -19.535046 -10.434138 28.973322 -16.123962 -9.524852 28.916128 -13.801210 -8.452247 28.404343 -12.846941 -7.345696 27.499689 -13.376261 -6.338665 26.311283 -15.325321 -5.552618 24.982466 -18.459040 -5.082362 23.673512 -22.399441 -4.984617 22.542297 -26.671255 -5.271174 21.725269 -30.759239 -5.907469 21.320967 -34.170322 -6.816755 21.378159 -36.493080 -7.760707 16.162996 -35.069145 -9.035542 16.979540 -34.892838 -10.420874 18.444052 -33.422691 -11.749608 20.379890 -30.836029 -12.861482 22.553564 -27.444839 -13.622386 24.702896 -23.658154 -13.940544 26.568642 -19.932695 -13.777582 27.925774 -16.717815 -13.153155 28.610594 -14.401273 -12.142579 28.540506 -13.262478 -10.867745 27.723965 -13.438782 -9.482414 26.259453 -14.908927 -8.153679 24.323614 -17.495586 -7.041806 22.149942 -20.886774 -6.280901 20.000612 -24.673460 -5.962742 18.134861 -28.398916 -6.125703 16.777731 -31.613798 -6.750128 16.092911 -33.930344 -6.869986 11.885027 -31.726812 -8.268233 12.478233 -31.853474 -10.039833 13.940369 -30.879377 -11.971102 16.095076 -28.922018 -13.829103 18.682467 -26.217482 -15.389731 21.390463 -23.091972 -16.464754 23.892443 -19.922478 -16.924505 25.886627 -17.091282 -16.713535 27.132490 -14.939869 -15.857289 27.479761 -13.727732 -14.459042 26.886555 -13.601070 -12.687443 25.424419 -14.575165 -10.756174 23.269714 -16.532524 -8.898174 20.682325 -19.237059 -7.337545 17.974329 -22.362566 -6.262522 15.472349 -25.532063 -5.802769 13.478165 -28.363258 -6.013737 12.232300 -30.514671 -5.566194 9.005283 -27.863438 -7.015347 9.292950 -28.237919 -9.122643 10.530238 -27.734245 -11.633911 12.567912 -26.413172 -14.246256 15.160198 -24.434032 -16.644588 17.994429 -22.035543 -18.539637 20.728752 -19.506998 -19.702827 23.033371 -17.153378 -19.993864 24.630316 -15.258562 -19.377645 25.326969 -14.051093 -17.928492 25.039303 -13.676610 -15.821197 23.802015 -14.180281 -13.309930 21.764343 -15.501356 -10.697586 19.172058 -17.480494 -8.299253 16.337830 -19.878979 -6.404204 13.603504 -22.407524 -5.241013 11.298884 -24.761147 -4.949974 9.701940 -26.655964 -4.162405 7.381169 -23.714716 -5.573366 7.321577 -24.288013 -7.920436 8.165138 -24.217804 -10.920525 9.810104 -23.512554 -14.211776 12.058069 -22.257326 -17.397217 14.637897 -20.603519 -20.092634 17.238420 -18.750612 -21.972925 19.545979 -16.922087 -22.811295 21.282244 -15.338492 -22.506626 22.237801 -14.190834 -21.095667 22.297394 -13.617535 -18.748596 21.453835 -13.687744 -15.748510 19.808868 -14.392993 -12.457260 17.560905 -15.648219 -9.271820 14.981078 -17.302023 -6.576400 12.380555 -19.154932 -4.696110 10.072998 -20.983456 -3.857737 8.336729 -22.567053 -2.955263 6.851263 -19.406757 -4.228479 6.436589 -20.134766 -6.680349 6.766053 -20.458885 -10.015138 7.799917 -20.340023 -13.830623 9.413481 -19.792513 -17.666599 11.412125 -18.882393 -21.060390 13.554783 -17.719439 -23.602659 15.583019 -16.443918 -24.986765 17.252199 -15.209680 -25.045771 18.360994 -14.165589 -23.772552 18.775669 -13.437580 -21.320686 18.446205 -13.113461 -17.985899 17.412342 -13.232324 -14.170415 15.798779 -13.779833 -10.334439 13.800137 -14.689952 -6.940646 11.657478 -15.852905 -4.398378 9.629242 -17.128426 -3.014268 7.960061 -18.362663 -2.233730 7.224931 -15.031631 -3.266190 6.480771 -15.870253 -5.654822 6.226475 -16.544813 -9.111522 6.492713 -16.973949 -13.219363 7.247375 -17.105904 -17.482878 8.399439 -16.924757 -21.387821 9.809944 -16.452360 -24.463202 11.308766 -15.745691 -26.338083 12.715124 -14.889983 -26.786327 13.859392 -13.988451 -25.753870 14.603553 -13.149828 -23.365238 14.857849 -12.475267 -19.908541 14.591612 -12.046130 -15.800701 13.836949 -11.914177 -11.537188 12.684889 -12.095324 -7.632244 11.274383 -12.567720 -4.556861 9.775560 -13.274388 -2.681977 8.369202 -14.130095 -2.259084 8.247806 -10.680413 -2.954654 7.234997 -11.582319 -5.090402 6.386784 -12.554109 -8.408727 5.805472 -13.478568 -12.509387 5.561176 -14.244194 -16.897783 5.683361 -14.758640 -21.044611 6.157291 -14.959859 -24.449699 6.925802 -14.823578 -26.702347 7.896201 -14.366236 -27.530851 8.951444 -13.642995 -26.835283 9.964252 -12.741089 -24.699535 10.812465 -11.769300 -21.381214 11.393777 -10.844841 -17.280556 11.638075 -10.079215 -12.892160 11.515888 -9.564768 -8.745333 11.041960 -9.363549 -5.340242 10.273449 -9.499829 -3.087592 9.303050 -9.957170 -3.219531 9.588124 -6.462287 -3.503232 8.400906 -7.375007 -5.195341 7.015604 -8.576246 -8.091761 5.599310 -9.921118 -11.843143 4.322848 -11.247410 -15.997017 3.340179 -12.395154 -20.052361 2.769826 -13.225913 -23.520041 2.680584 -13.639486 -25.981804 3.083216 -13.585990 -27.140728 3.929158 -13.071878 -26.857027 5.116376 -12.159159 -25.164921 6.501677 -10.957920 -22.268503 7.917971 -9.613049 -18.517122 9.194433 -8.286757 -14.363251 10.177103 -7.139013 -10.307907 10.747456 -6.308253 -6.840226 10.836699 -5.894679 -4.378459 10.434068 -5.948174 -5.185308 10.858491 -2.482939 -5.016171 9.617501 -3.351485 -6.097577 7.819412 -4.701558 -8.299094 5.681098 -6.370317 -11.355186 3.460472 -8.156487 -14.897243 1.425374 -9.844629 -18.498039 -0.178733 -11.231127 -21.723265 -1.158370 -12.148751 -24.183914 -1.395379 -12.486820 -25.583195 -0.861173 -12.204561 -25.752333 0.379816 -11.336016 -24.670927 2.177905 -9.985943 -22.469412 4.316218 -8.317185 -19.413322 6.536843 -6.531015 -15.871267 8.571941 -4.842874 -12.270472 10.176050 -3.456374 -9.045243 11.155687 -2.538751 -6.584592 11.392696 -2.200679 -8.077580 11.662115 1.149674 -7.459403 10.500497 0.380563 -7.813565 8.470284 -1.025873 -9.097352 5.816347 -2.899996 -11.155920 2.858793 -5.015760 -13.740973 -0.045654 -7.117973 -16.540718 -2.546675 -8.953074 -19.217463 -4.342610 -10.299726 -21.448353 -5.216844 -10.995502 -22.964310 -5.063930 -10.956482 -23.582489 -3.902312 -10.187371 -23.228327 -1.872099 -8.780935 -21.944540 0.781835 -6.906814 -19.885975 3.739388 -4.791050 -17.300922 6.643835 -2.688839 -14.501179 9.144856 -0.853735 -11.824433 10.940793 0.492917 -9.593542 11.815028 1.188695 -11.671829 11.653167 4.349606 -10.656389 10.699757 3.730797 -10.237152 8.653555 2.366040 -10.464684 5.761364 0.419946 -11.311541 2.372026 -1.872760 -12.675580 -1.105656 -4.235541 -14.392276 -4.252222 -6.383412 -16.254572 -6.688149 -8.057308 -18.037846 -8.119630 -9.055332 -19.527012 -8.374006 -9.257111 -20.542452 -7.420596 -8.638302 -20.961689 -5.374395 -7.273546 -20.734158 -2.482206 -5.327452 -19.887302 0.907131 -3.034748 -18.523264 4.384812 -0.671967 -16.806568 7.531379 1.475905 -14.944273 9.967306 3.149802 -13.160997 11.398789 4.147828 -15.624960 10.590368 7.058868 -14.308185 9.951767 6.633044 -13.150237 8.112837 5.407174 -12.290783 5.295383 3.529114 -11.833485 1.839228 1.225388 -11.833498 -1.838763 -1.226142 -12.290824 -5.294968 -3.529784 -13.150299 -8.112521 -5.407686 -14.308261 -9.951581 -6.633344 -15.625040 -10.590334 -7.058928 -16.941814 -9.951734 -6.633104 -18.099762 -8.112804 -5.407234 -18.959217 -5.295352 -3.529176 -19.416515 -1.839199 -1.225451 -19.416502 1.838791 1.226078 -18.959177 5.294997 3.529721 -18.099703 8.112551 5.407623 -16.941742 9.951613 6.633283 -19.526730 8.373028 9.258712 -18.037579 8.118843 9.056598 -16.254349 6.687651 8.058077 -14.392126 4.252076 6.383584 -12.675521 1.105884 4.235090 -11.311582 -2.371447 1.871734 -10.464819 -5.760499 -0.421428 -10.237365 -8.652504 -2.367806 -10.656654 -10.698642 -3.732641 -11.672114 -11.652121 -4.351311 -13.161265 -11.397936 -4.149197 -14.944494 -9.966744 -3.150676 -16.806717 -7.531171 -1.476185 -18.523321 -4.384981 0.672308 -19.887262 -0.907652 3.035663 -20.734026 2.481401 5.328825 -20.961479 5.373406 7.275205 -20.542192 7.419547 8.640039 -22.963579 5.062431 10.959457 -21.447624 5.215464 10.998146 -19.216825 4.341518 10.301716 -16.540249 2.546007 8.954163 -13.740730 0.045494 7.118023 -11.155931 -2.858422 5.014762 -9.097619 -5.815483 2.898065 -7.814055 -8.469027 1.023236 -7.460055 -10.498996 -0.383593 -8.078318 -11.660546 -1.152738 -9.594272 -11.813580 -1.191429 -11.825069 -10.939634 -0.494998 -14.501644 -9.144124 0.852554 -17.301163 -6.643613 2.688693 -19.885962 -3.739699 4.791953 -21.944275 -0.782637 6.908650 -23.227840 1.870906 8.783480 -23.581841 3.900877 10.190310 -25.581957 0.859544 12.209121 -24.182613 1.393755 12.491066 -21.722059 1.156950 12.152162 -18.497072 0.177691 11.233287 -14.896633 -1.425906 9.845268 -11.355008 -3.460427 8.155525 -8.299371 -5.680476 6.367864 -6.098275 -7.818283 4.697903 -5.017205 -9.615998 3.347063 -5.186554 -10.856790 2.478277 -6.585895 -11.391000 2.196332 -9.046450 -11.154196 2.535234 -12.271435 -10.174938 3.454109 -15.871873 -8.571342 4.842125 -19.413496 -6.536823 6.531868 -22.469135 -4.316774 8.319530 -24.670231 -2.178967 9.989491 -25.751305 -0.381251 11.340332 -27.139366 -3.930191 13.077672 -25.980232 -3.084406 13.591568 -23.518448 -2.681785 13.644169 -20.050938 -2.770887 13.229127 -15.995936 -3.340967 12.396505 -11.842538 -4.323264 11.246730 -8.091703 -5.599299 9.918481 -5.195838 -7.015163 8.571963 -3.504226 -8.400082 7.369588 -3.220900 -9.587013 6.456378 -4.380033 -10.432798 5.942482 -6.841818 -10.835421 5.889882 -10.309326 -10.746319 6.304922 -14.364325 -10.176240 7.137543 -18.517723 -9.193943 8.287317 -22.268559 -7.917909 9.615567 -25.164425 -6.502045 10.962085 -26.856039 -5.117126 12.164460 -27.530163 -8.950616 13.649069 -26.701183 -7.895757 14.372325 -24.448202 -6.925789 14.828941 -21.042961 -6.157705 14.963843 -16.896181 -5.684149 14.760760 -12.508026 -5.562237 14.244185 -8.407774 -5.806674 13.476428 -5.089974 -6.387977 12.550090 -2.954802 -7.236032 11.576900 -2.259789 -8.248553 10.674241 -3.088766 -9.303411 9.950985 -5.341747 -10.273379 9.494369 -8.746986 -11.041463 9.359467 -12.893764 -11.515020 9.562550 -17.281918 -11.636933 10.079123 -21.382170 -11.392497 10.846879 -24.699972 -10.811193 11.773217 -26.835148 -9.963139 12.746408 -26.787075 -13.857814 13.996091 -26.338026 -12.714049 14.897859 -24.462345 -11.308317 15.752846 -21.386271 -9.810170 16.457926 -17.480820 -8.400307 16.928059 -13.217049 -7.248778 17.106533 -9.109233 -6.494476 16.971828 -5.652833 -6.228378 16.540190 -3.264743 -6.482582 15.863680 -2.233001 -7.226425 15.023895 -2.682050 -8.370190 14.122127 -4.557730 -9.775922 13.267139 -7.633803 -11.274069 12.562059 -11.539251 -12.683931 12.091928 -15.803020 -13.835459 11.913451 -19.910837 -14.589764 12.048155 -23.367237 -14.855862 12.479794 -25.755329 -14.601658 13.156304 -25.048807 -18.358185 14.172234 -24.988741 -17.249964 15.216874 -23.603334 -15.581624 16.450790 -21.059687 -13.554388 17.725151 -17.664598 -11.412774 18.886251 -13.827571 -9.415091 19.794048 -10.011406 -7.802289 20.339043 -6.676387 -6.768894 20.455503 -4.224768 -6.439552 20.129383 -2.952249 -6.853983 19.400017 -3.012315 -7.962203 18.355377 -4.397722 -9.630543 17.121462 -6.941368 -11.657776 15.847101 -10.336452 -13.799390 14.686000 -14.173478 -15.797074 13.778205 -17.989645 -17.409878 13.233209 -21.324663 -18.443272 13.116747 -23.776285 -18.772615 13.442865 -22.511982 -22.234463 14.195948 -22.815411 -21.279556 15.344477 -21.975304 -19.544258 16.928215 -20.092993 -17.237871 18.756138 -17.395512 -14.638579 20.607775 -14.208216 -12.059895 22.259789 -10.915542 -9.812847 23.512918 -7.914633 -8.168461 24.216026 -5.567444 -7.325074 24.284302 -4.157080 -7.384411 23.709509 -3.853651 -8.339316 22.560982 -4.693757 -10.074614 20.977243 -6.576066 -12.380999 19.149319 -9.273546 -14.980290 17.297686 -12.460840 -17.558975 15.645672 -15.753514 -19.806023 14.392538 -18.754423 -21.450411 13.689431 -21.101614 -22.293798 13.621157 -19.387312 -25.321537 14.054355 -20.001844 -24.625830 15.263227 -19.708158 -23.030363 17.158878 -18.541677 -20.727575 19.512667 -16.643097 -17.995220 22.040691 -14.241414 -15.162857 24.438032 -11.626306 -12.572111 26.415535 -9.113194 -10.535467 27.734688 -7.005196 -9.298573 28.236378 -5.556568 -9.010612 27.860092 -4.942036 -9.706320 26.651222 -5.235721 -11.301785 24.755569 -6.402200 -13.604572 22.401783 -8.300779 -16.336926 19.873760 -10.702462 -19.169289 17.476419 -13.317570 -21.760035 15.498915 -15.830682 -23.796679 14.179762 -17.938681 -25.033577 13.678071 -15.869843 -27.472523 13.727739 -16.724194 -27.126654 14.941615 -16.931984 -25.882889 17.094553 -16.468153 -23.891247 19.926874 -15.388645 -21.391949 23.096962 -13.823666 -18.686447 26.222454 -11.961973 -16.101065 28.926373 -10.028116 -13.947635 30.882584 -8.255346 -12.485897 31.855137 -6.857485 -11.892155 31.726736 -6.003135 -12.238024 30.512859 -5.795344 -13.481787 28.359924 -6.259174 -15.473427 25.527605 -7.338680 -17.972725 22.357519 -8.903659 -20.678226 19.232027 -10.765350 -23.263609 16.528107 -12.699207 -25.417040 14.571895 -14.471978 -26.878778 13.599338 -12.158510 -28.529387 13.259381 -13.167016 -28.601337 14.399896 -13.787704 -27.919487 16.718319 -13.945712 -26.566080 19.935017 -13.621980 -24.704355 23.662008 -12.855555 -22.558865 27.449760 -11.738879 -20.388386 30.841417 -10.406641 -18.454708 33.427895 -9.019527 -16.991068 34.897221 -7.744845 -16.173994 35.072182 -6.736339 -16.102043 33.931667 -6.115650 -16.783892 31.613245 -5.957643 -18.137299 28.396549 -6.281374 -19.999022 24.669559 -7.047799 -22.144512 20.881807 -8.164474 -24.314991 17.490150 -9.496711 -26.248669 14.903674 -10.883825 -27.712311 13.434341 -8.473561 -28.386921 12.842847 -9.543814 -28.901058 13.798491 -10.448466 -28.962412 16.122948 -11.078404 -28.563576 19.535854 -11.357650 -27.752663 23.625565 -11.252519 -26.627476 27.898796 -10.775694 -25.323732 31.840137 -9.984687 -23.998682 34.974201 -8.974903 -22.812141 36.922977 -7.868139 -21.907232 37.451412 -6.797887 -21.393093 36.495770 -5.893234 -21.331741 34.171310 -5.263296 -21.730574 30.758408 -4.984050 -22.541487 26.668701 -5.089180 -23.666674 22.395470 -5.566005 -24.970417 18.454126 -6.357012 -26.295469 15.320063 -7.366795 -27.482008 13.371284 -4.994665 -27.182959 12.851474 -6.047331 -28.085567 13.484106 -7.088737 -28.979168 15.567904 -7.993272 -29.755978 18.851530 -8.651838 -30.322300 22.938931 -8.985003 -30.609835 27.337107 -8.952579 -30.583893 31.515570 -8.558479 -30.247606 34.970337 -7.850238 -29.641539 37.284710 -6.913279 -28.838791 38.179546 -5.860614 -27.936180 37.546917 -4.819209 -27.042582 35.463120 -3.914672 -26.265772 32.179493 -3.256106 -25.699448 28.092096 -2.922942 -25.411915 23.693922 -2.955364 -25.437855 19.515459 -3.349463 -25.774139 16.060692 -4.057704 -26.380207 13.746314 -1.687464 -25.491268 13.648071 -2.687317 -26.626324 13.835084 -3.754055 -28.270006 15.379635 -4.759012 -30.224064 18.095432 -5.580976 -32.252804 21.654907 -6.120807 -34.111534 25.628736 -6.313392 -35.576065 29.537613 -6.135503 -36.469749 32.910076 -5.608596 -36.684799 35.339352 -4.796224 -36.195271 36.532436 -3.796371 -35.060219 36.345425 -2.729634 -33.416534 34.800873 -1.724676 -31.462481 32.085079 -0.902712 -29.433741 28.525608 -0.362881 -27.575010 24.551779 -0.170295 -26.110479 20.642900 -0.348184 -25.216793 17.270437 -0.875090 -25.001743 14.841160 1.824890 -24.202177 15.176413 0.852453 -25.336945 14.876908 -0.222815 -27.455322 15.639488 -1.271219 -30.301809 17.372169 -2.166307 -33.533073 19.865971 -2.800118 -36.759377 22.820099 -3.096204 -39.591576 25.878242 -3.018855 -41.688072 28.671545 -2.577398 -42.795994 30.863092 -1.825081 -42.781712 32.188557 -0.852644 -41.646942 32.488060 0.222623 -39.528564 31.725481 1.271027 -36.682079 29.992798 2.166115 -33.450817 27.499001 2.799926 -30.224516 24.544874 3.096014 -27.392313 21.486731 3.018664 -25.295818 18.693428 2.577209 -24.187893 16.501877 6.069046 -24.026768 16.743036 5.062400 -24.926298 16.035545 3.898333 -27.131184 15.942338 2.717249 -30.375484 16.474663 1.661604 -34.267891 17.568308 0.858725 -38.338924 19.091366 0.405450 -42.097549 20.860134 0.356451 -45.090427 22.661272 0.717638 -46.956573 24.277538 1.445446 -47.470898 25.513981 2.452092 -46.571369 26.221476 3.616159 -44.366486 26.314682 4.797242 -41.122185 25.782358 5.852887 -37.229778 24.688715 6.655767 -33.158749 23.165655 7.109042 -29.400122 21.396889 7.158042 -26.407244 19.595751 6.796855 -24.541098 17.979485 11.314355 -25.090321 17.331146 10.223169 -25.587217 16.390167 8.856786 -27.504393 15.563913 7.380009 -30.610605 14.952042 5.970961 -34.531204 14.628354 4.799592 -38.793308 14.631891 4.007189 -42.882835 14.962230 3.689326 -46.306538 15.579521 3.884341 -48.651459 16.409313 4.568714 -49.634773 17.351524 5.659899 -49.137882 18.292503 7.026282 -47.220707 19.118757 8.503058 -44.114494 19.730629 9.912107 -40.193897 20.054316 11.083475 -35.931801 20.050779 11.875879 -31.842272 19.720444 12.193743 -28.418568 19.103149 11.998729 -26.073641 18.273357 17.405622 -26.995857 16.099737 16.221972 -27.016645 15.139753 14.573834 -28.371166 13.845852 12.660005 -30.896048 12.374097 10.711316 -34.286747 10.902004 8.962810 -38.134296 9.607129 7.625381 -41.974625 8.645655 6.860344 -45.344532 8.133545 6.759974 -47.837559 8.132572 7.336376 -49.153008 8.642851 8.520027 -49.132217 9.602835 10.168162 -47.777702 10.896736 12.081992 -45.252823 12.368489 14.030681 -41.862125 13.840582 15.779186 -38.014576 15.135456 17.116615 -34.174248 16.096931 17.881653 -30.804340 16.609041 17.982025 -28.311310 16.610016 23.852930 -29.108049 12.652629 22.616417 -28.666641 11.878533 20.675356 -29.312117 10.449930 18.263868 -30.966625 8.539131 15.672814 -33.430607 6.376606 13.214714 -36.406868 4.223186 11.186051 -39.536430 2.338609 9.831512 -42.441822 0.950179 9.314474 -44.772614 0.225363 9.697298 -46.247665 0.251583 10.933811 -46.689079 1.025678 12.874871 -46.043602 2.454280 15.286358 -44.389099 4.365079 17.877411 -41.925117 6.527603 20.335510 -38.948856 8.681022 22.364174 -35.819294 10.565600 23.718714 -32.913898 11.954031 24.235754 -30.583111 12.678848 30.004591 -30.789207 7.059236 28.792463 -29.968557 6.634607 26.620331 -29.885578 5.409774 23.750185 -30.550272 3.532469 20.528210 -31.882469 1.229123 17.343023 -33.721497 -1.222446 14.578804 -35.845524 -3.526542 12.568958 -37.998375 -5.405259 11.555904 -39.920376 -6.631994 11.661828 -41.379715 -7.058787 12.873956 -42.200367 -6.634159 15.046088 -42.283344 -5.409326 17.916231 -41.618652 -3.532023 21.138205 -40.286453 -1.228678 24.323393 -38.447430 1.222890 27.087612 -36.323402 3.526987 29.097458 -34.170551 5.405704 30.110516 -32.248547 6.632441 35.205036 -31.519501 -0.255899 34.117809 -30.451725 -0.227214 31.839443 -29.735550 -0.949295 28.644739 -29.457357 -2.335044 24.919029 -29.650709 -4.217324 21.111687 -30.292274 -6.369101 17.681934 -31.304676 -8.530840 15.043451 -32.565804 -10.441803 13.514476 -33.923542 -11.871501 13.279426 -35.214134 -12.647491 14.366651 -36.281910 -12.676176 16.645018 -36.998085 -11.954098 19.839720 -37.276276 -10.568348 23.565428 -37.082928 -8.686070 27.372770 -36.441360 -6.534293 30.802523 -35.428959 -4.372554 33.441006 -34.167831 -2.461590 34.969986 -32.810097 -1.031891 38.903656 -30.921968 -8.653635 38.051655 -29.766928 -8.140801 35.841064 -28.609970 -8.138186 32.538517 -27.590649 -8.646105 28.542345 -26.831907 -9.603294 24.334549 -26.425259 -10.894304 20.422653 -26.419754 -12.363420 17.278484 -26.816055 -13.833444 15.281281 -27.566364 -15.127069 14.671929 -28.580181 -16.088268 15.523930 -29.735226 -16.601103 17.734520 -30.892179 -16.603718 21.037064 -31.911503 -16.095800 25.033234 -32.670246 -15.138611 29.241028 -33.076893 -13.847601 33.152927 -33.082397 -12.378486 36.297092 -32.686096 -10.908462 38.294300 -31.935789 -9.614836 40.704758 -28.758032 -17.367249 40.194775 -27.675873 -16.422857 38.260490 -26.338402 -15.589209 35.135201 -24.906939 -14.966857 31.195871 -23.554140 -14.630864 26.917639 -22.443172 -14.621759 22.816521 -21.708036 -14.940638 19.387175 -21.437397 -15.549039 17.043228 -21.663904 -16.373581 16.067394 -22.360229 -17.314810 16.577377 -23.442390 -18.259203 18.511662 -24.779861 -19.092850 21.636946 -26.211323 -19.715202 25.576275 -27.564121 -20.051193 29.854507 -28.675089 -20.060301 33.955624 -29.410225 -19.741425 37.384972 -29.680862 -19.133022 39.728920 -29.454361 -18.308483 40.390278 -24.960855 -25.531912 40.308479 -24.076389 -24.293339 38.872456 -22.836376 -22.673010 36.255405 -21.390379 -20.866367 32.772987 -19.912804 -19.091316 28.845228 -18.581865 -17.561953 24.945881 -17.558102 -16.462742 21.545259 -16.964987 -15.926265 19.053530 -16.874065 -16.017227 17.771231 -17.296297 -16.724661 17.853025 -18.180759 -17.963234 19.289051 -19.420773 -19.583561 21.906099 -20.866772 -21.390205 25.388515 -22.344349 -23.165257 29.316271 -23.675285 -24.694618 33.215618 -24.699051 -25.793829 36.616241 -25.292164 -26.330307 39.107971 -25.383087 -26.239346 37.960655 -19.774651 -32.203342 38.349239 -19.133192 -30.876478 37.610760 -18.203821 -28.681896 35.834297 -17.098639 -25.884298 33.234112 -15.950941 -22.821112 30.123827 -14.899159 -19.861803 26.878590 -14.070157 -17.363312 23.889824 -13.563919 -15.626990 21.518017 -13.441508 -14.862263 20.049244 -13.717689 -15.161370 19.660662 -14.359148 -16.488234 20.399137 -15.288517 -18.682812 22.175600 -16.393702 -21.480412 24.775784 -17.541397 -24.543596 27.886066 -18.593178 -27.502903 31.131304 -19.422182 -30.001396 34.120071 -19.928419 -31.737719 36.491879 -20.050831 -32.502449 33.738621 -13.908622 -36.539108 34.568871 -13.451563 -35.345451 34.646866 -12.893527 -32.914860 33.963200 -12.301822 -29.540499 32.600330 -11.747815 -25.629368 30.722643 -11.298328 -21.653206 28.556614 -11.007576 -18.091597 26.363499 -10.910628 -15.374123 24.407818 -11.019177 -13.828555 22.925455 -11.320130 -13.641304 22.095207 -11.777189 -14.834959 22.017212 -12.335224 -17.265551 22.700878 -12.926929 -20.639908 24.063745 -13.480936 -24.551039 25.941431 -13.930423 -28.527199 28.107460 -14.221175 -32.088810 30.300575 -14.318124 -34.806286 32.256256 -14.209576 -36.351856 28.425356 -8.399202 -38.179024 29.588934 -7.989913 -37.283707 30.468618 -7.684288 -34.968967 30.958303 -7.519190 -31.514006 30.998928 -7.514533 -27.335533 30.585592 -7.670878 -22.937546 29.768148 -7.969369 -18.850496 28.645193 -8.374002 -15.567348 27.352173 -8.835971 -13.484097 26.045042 -9.299559 -12.852011 24.881464 -9.708848 -13.747329 24.001780 -10.014473 -16.062065 23.512094 -10.179571 -19.517027 23.471470 -10.184228 -23.695496 23.884806 -10.027883 -28.093485 24.702248 -9.729393 -32.180534 25.825203 -9.324761 -35.463680 27.118223 -8.862791 -37.546936 22.902422 -4.116192 -37.447868 24.239161 -3.610131 -36.918663 25.771824 -3.331725 -34.969635 27.315548 -3.314553 -31.835876 28.684137 -3.560686 -27.895361 29.712519 -4.040437 -23.623373 30.276655 -4.695942 -19.535179 30.308504 -5.448135 -16.123875 29.804224 -6.206293 -13.800909 28.824638 -6.878969 -12.846472 27.487898 -7.385029 -13.375680 25.955236 -7.663436 -15.324703 24.411512 -7.680609 -18.458460 23.042923 -7.434476 -22.398973 22.014542 -6.954725 -26.670961 21.450403 -6.299221 -30.759155 21.418554 -5.547027 -34.170464 21.922834 -4.788870 -36.493427 17.878126 -1.360176 -35.069229 19.222696 -0.664430 -34.892879 21.183655 -0.197030 -33.422695 23.524479 -0.014352 -30.835999 25.962833 -0.138429 -27.444786 28.204613 -0.554297 -23.658089 29.979429 -1.211795 -19.932634 31.073210 -2.031619 -16.717773 31.354033 -2.914886 -14.401260 30.788023 -3.755063 -13.262499 29.443453 -4.450809 -13.438848 27.482496 -4.918209 -14.909030 25.141672 -5.100887 -17.495724 22.703320 -4.976810 -20.886934 20.461540 -4.560943 -24.673632 18.686724 -3.903445 -28.399086 17.592939 -3.083621 -31.613949 17.312117 -2.200354 -33.930462 13.727890 0.007237 -31.726974 14.940800 0.921477 -31.853647 17.092884 1.724561 -30.879555 19.924564 2.319624 -28.922184 23.094303 2.634894 -26.217625 26.219780 2.632345 -23.092083 28.924017 2.312283 -19.922552 30.880844 1.713313 -17.091318 31.854239 0.907680 -14.939875 31.726795 -0.007445 -13.727711 30.513885 -0.921685 -13.601038 28.361803 -1.724769 -14.575130 25.530125 -2.319833 -16.532501 22.360388 -2.635103 -19.237059 19.234911 -2.632554 -22.362597 16.530672 -2.312493 -25.532129 14.573844 -1.713523 -28.363361 13.600447 -0.907890 -30.514809 10.582041 0.317885 -27.863663 11.555747 1.429061 -28.238115 13.680915 2.635376 -27.734398 16.701214 3.791331 -26.413269 20.252354 4.757500 -24.434074 23.906013 5.417349 -22.035538 27.221508 5.691290 -19.506954 29.798939 5.546283 -17.153313 31.327431 4.999817 -15.258491 31.622625 4.117804 -14.051036 30.648920 3.006628 -13.676583 28.523752 1.800313 -14.180302 25.503456 0.644359 -15.501429 21.952318 -0.321810 -17.480621 18.298658 -0.981660 -19.879156 14.983164 -1.255602 -22.407740 12.405731 -1.110595 -24.761383 10.877237 -0.564130 -26.656204 8.473923 -0.086689 -23.714977 9.127733 1.165062 -24.288288 11.031713 2.776021 -24.218069 13.956216 4.551883 -23.512789 17.548504 6.278452 -22.257517 21.375292 7.747479 -20.603653 24.975014 8.781777 -18.750683 27.913490 9.256598 -16.922098 29.836296 9.114666 -15.338453 30.511517 8.373103 -14.190763 29.857708 7.121353 -13.617451 27.953728 5.510394 -13.687670 25.029226 3.734534 -14.392948 21.436941 2.007964 -15.648222 17.610153 0.538937 -17.302082 14.010432 -0.495363 -19.155054 11.071955 -0.970182 -20.983637 9.149145 -0.828252 -22.567284 7.411061 -0.866313 -19.406971 7.688565 0.443662 -20.134974 9.199835 2.402305 -20.459074 11.762591 4.773374 -20.340179 15.067727 7.270883 -19.792633 18.716595 9.593595 -18.882471 22.269085 11.461356 -17.719481 25.296717 12.648888 -16.443930 27.434313 13.012957 -15.209672 28.424047 12.509651 -14.165574 28.146545 11.199677 -13.437571 26.635277 9.241034 -13.113471 24.072523 6.869967 -13.232365 20.767387 4.372458 -13.779911 17.118523 2.049746 -14.690070 13.566031 0.181983 -15.853062 10.538399 -1.005549 -17.128611 8.400801 -1.369620 -18.362869 7.374080 -1.678274 -15.031033 7.245843 -0.412145 -15.869783 8.219906 1.783570 -16.544540 10.178783 4.644034 -16.973919 12.886206 7.824234 -17.106131 16.015617 10.940589 -16.925226 19.189566 13.617220 -16.453026 22.025223 15.531288 -15.746485 24.180571 16.451927 -14.890823 25.395641 16.268097 -13.989247 25.523880 15.001968 -13.150496 24.549816 12.806253 -12.475738 22.590940 9.945790 -12.046359 19.883520 6.765593 -11.914148 16.754110 3.649239 -12.095053 13.580162 0.972605 -12.567251 10.744504 -0.941463 -13.273792 8.589154 -1.862105 -14.129454 8.272704 -2.167763 -10.680900 7.743366 -1.058980 -11.582806 8.076626 1.214765 -12.554547 9.232288 4.379226 -13.478917 11.070962 8.052719 -14.244425 13.370876 11.792171 -14.758739 15.854628 15.146544 -14.959822 18.222637 17.711250 -14.823424 20.189291 19.176956 -14.365995 21.517382 19.366871 -13.642710 22.046721 18.258089 -12.740804 21.713461 15.984345 -11.769062 20.557800 12.819885 -10.844691 18.719128 9.146394 -10.079185 16.419214 5.406944 -9.564871 13.935464 2.052570 -9.363787 11.567452 -0.512140 -9.500184 9.600798 -1.977847 -9.957612 9.912877 -2.005986 -6.463190 9.026575 -1.166563 -7.375807 8.672993 0.991611 -8.576860 8.894778 4.208227 -9.921484 9.665180 8.095314 -11.247499 10.891277 12.184033 -12.394964 12.425184 15.981222 -13.225483 14.081888 19.028887 -13.638880 15.661567 20.959431 -13.585294 16.973688 21.540005 -13.071188 17.859991 20.700583 -12.158572 18.213573 18.542410 -10.957519 17.991789 15.325794 -9.612895 17.221388 11.438708 -8.286881 15.995292 7.349991 -7.139414 14.461385 3.552802 -6.308896 12.804681 0.505137 -5.895498 11.225001 -1.425410 -5.949083 11.996103 -0.938429 -2.482436 10.836823 -0.464425 -3.351012 9.820391 1.371102 -4.701184 9.069404 4.346763 -6.370101 8.674441 8.103647 -8.156468 8.683141 12.188619 -9.844823 9.094454 16.108971 -11.231524 9.858770 19.391850 -12.149315 10.883903 21.641293 -12.487495 12.046204 22.585985 -12.205279 13.205482 22.111982 -11.336704 14.221915 20.276455 -9.986532 14.972902 17.300798 -8.317616 15.367867 13.543916 -6.531249 15.359167 9.458944 -4.842896 14.947854 5.538592 -3.456194 14.183537 2.255713 -2.538403 13.158406 0.006267 -2.200220 14.138521 1.164269 1.149538 12.823478 1.209700 0.380363 11.242377 2.531507 -1.026125 9.585923 4.970259 -2.900284 8.053908 8.231808 -5.016061 6.831117 11.922761 -7.118264 6.065036 15.597936 -8.953335 5.848065 18.814051 -10.299936 6.206374 21.183197 -10.995650 7.096746 22.419621 -10.956563 8.411789 22.374191 -10.187389 9.992888 21.052385 -8.780901 11.649343 18.613636 -6.906743 13.181357 15.352089 -4.790967 14.404149 11.661137 -2.688764 15.170231 7.985962 -0.853693 15.387202 4.769846 0.492909 15.028894 2.400697 1.188625 15.928606 4.280380 4.347451 14.595098 3.877818 3.728798 12.613235 4.538096 2.364423 10.222062 6.181574 0.418891 7.709987 8.610023 -1.873137 5.380005 11.530538 -4.235211 3.513147 14.590859 -6.382428 2.334582 17.421869 -8.055803 1.986462 19.682106 -9.053502 2.510777 21.098951 -9.255188 3.844285 21.501514 -8.636535 5.826146 20.841236 -7.272161 8.217318 19.197760 -5.326631 10.729392 16.769312 -3.034603 13.059373 13.848799 -0.672530 14.926232 10.788477 1.474688 16.104799 7.957467 3.148063 16.452919 5.697229 4.145764 16.983110 8.236740 7.060270 15.771711 7.415674 6.634364 13.600323 7.332279 5.408238 10.730848 7.996613 3.529783 7.509386 9.328548 1.225567 4.324493 11.167435 -1.226487 1.560316 13.291473 -3.530625 -0.449746 15.444475 -5.408935 -1.463251 17.366756 -6.634863 -1.357955 18.826462 -7.060547 -0.146557 19.647530 -6.634642 2.024831 19.730927 -5.408517 4.894304 19.066591 -3.530063 8.115765 17.734657 -1.225848 11.300656 15.895772 1.226206 14.064835 13.771733 3.530344 16.074898 11.618731 5.408655 17.088406 9.696449 6.634584 17.014498 12.723945 9.258860 16.049774 11.561411 9.056730 13.918718 10.732718 8.058167 10.878368 10.337818 6.383607 7.295435 10.424341 4.235030 3.602073 10.981853 1.871585 0.243757 11.943108 -0.421661 -2.374450 13.192163 -2.368109 -3.936757 14.578367 -3.732989 -4.254724 15.934523 -4.351676 -3.290001 17.097057 -4.149549 -1.158946 17.925751 -3.150984 1.881402 18.320650 -1.476426 5.464334 18.234127 0.672150 9.157695 17.676617 3.035594 12.516012 16.715363 5.328840 15.134220 15.466306 7.275288 16.696529 14.080103 8.640169 15.865992 17.355515 10.959558 15.240489 15.966170 10.998268 13.368189 14.471271 10.301828 10.474919 13.051122 8.954241 6.909651 11.877017 7.118043 3.102407 11.090570 5.014709 -0.487600 10.786638 2.897932 -3.427364 11.001879 1.023026 -5.362307 11.710332 -0.383868 -6.059045 12.826548 -1.153058 -5.433543 14.215892 -1.191767 -3.561243 15.710792 -0.495328 -0.667976 17.130939 0.852259 2.897291 18.305042 2.688455 6.704533 19.091492 4.791788 10.294540 19.395424 6.908565 13.234305 19.180183 8.783472 15.169250 18.471731 10.190367 13.535406 21.724602 12.209349 13.298341 20.245632 12.491276 11.862957 18.233160 12.152317 9.402385 15.929919 11.233355 6.213406 13.613713 9.845232 2.680657 11.563912 8.155374 -0.769758 10.027754 6.367604 -3.721671 9.190516 4.697555 -5.819035 9.153189 3.346656 -6.808879 9.920269 2.477847 -6.571814 11.399239 2.195920 -5.136432 13.411709 2.534878 -2.675862 15.714950 3.453838 0.513116 18.031153 4.841961 4.045863 20.080956 6.531817 7.496279 21.617115 8.319587 10.448192 22.454351 9.989637 12.545558 22.491682 11.340537 10.166134 25.468718 13.076781 10.319137 24.041986 13.590654 9.437010 21.708675 13.643329 7.626151 18.750216 13.228451 5.104975 15.523441 12.396059 2.177574 12.417547 11.246555 -0.802963 9.807151 9.918585 -3.477141 8.007107 8.572322 -5.522414 7.234523 7.370144 -6.692093 7.582587 6.457053 -6.845097 9.009315 5.943180 -5.962970 11.342626 5.890506 -4.152113 14.301085 6.305384 -1.630939 17.527859 7.137774 1.296460 20.633751 8.287277 4.276998 23.244148 9.615246 6.951176 25.044193 10.961510 8.996451 25.816778 12.163688 6.013992 28.316931 13.649035 6.512996 27.071569 14.372295 6.226449 24.635456 14.828908 5.188913 21.302416 14.963797 3.525532 17.474468 14.760694 1.436931 13.613317 14.244095 -0.824970 10.184676 13.476311 -2.987355 7.602088 12.549947 -4.789407 6.177053 11.576736 -6.013774 6.081449 10.674063 -6.512778 7.326807 9.950802 -6.226232 9.762922 9.494190 -5.188697 13.095960 9.359300 -3.525316 16.923906 9.562403 -1.436718 20.785057 10.079000 0.825184 24.213699 10.846785 2.987569 26.796288 11.773149 4.789622 28.221327 12.746360 1.393072 30.126997 13.996147 2.158993 29.166183 14.897941 2.438400 26.838911 15.752931 2.197590 23.425890 16.457989 1.465609 19.338776 16.928080 0.330746 15.070538 17.106501 -1.070120 11.135986 16.971733 -2.568022 8.009690 16.540030 -3.982291 6.068723 15.863462 -5.142347 5.547193 15.023633 -5.908269 6.508007 14.121840 -6.187675 8.835277 13.266851 -5.946866 12.248297 12.561791 -5.214887 16.335409 12.091702 -4.080024 20.603645 11.913280 -2.679159 24.538198 12.048048 -1.181257 27.664497 12.479751 0.233013 29.605467 13.156319 -3.375949 30.871838 14.171118 -2.445954 30.265875 15.215605 -1.693368 28.232069 16.449507 -1.208964 25.015730 17.723999 -1.051169 21.004791 18.885355 -1.239015 16.683033 19.793503 -1.749845 12.571722 20.338902 -2.522045 9.166746 20.455772 -3.462476 6.878793 20.130016 -4.457709 5.983823 19.400927 -5.387704 6.589783 18.356440 -6.140291 8.623587 17.122540 -6.624694 11.839926 15.848047 -6.782490 15.850863 14.686690 -6.594645 20.172619 13.778543 -6.083816 24.283932 13.233143 -5.311616 27.688908 13.116272 -4.371184 29.976864 13.442026 -7.999032 30.613510 14.196533 -7.020466 30.398750 15.345151 -5.937873 28.803432 16.928883 -4.881829 26.019976 18.756714 -3.979708 22.384106 20.608175 -3.340321 18.334366 22.259956 -3.040786 14.359209 23.512829 -3.117232 10.938101 24.215673 -3.560437 8.483677 24.283720 -4.316946 7.291976 23.708763 -5.295512 7.506735 22.560146 -6.378105 9.102053 20.976414 -7.434149 11.885507 19.148586 -8.336269 15.521375 17.297123 -8.975657 19.571115 15.645342 -9.275193 23.546272 14.392469 -9.198748 26.967381 13.689623 -8.755543 29.421806 13.621574 -12.235234 29.450766 14.054381 -11.325471 29.635090 15.263260 -10.090617 28.582987 17.158907 -8.679615 26.421356 19.512678 -7.262652 23.410919 22.040676 -6.010635 19.914782 24.437984 -5.074576 16.354630 26.415455 -4.567377 13.159870 27.734573 -4.550214 10.715838 28.236237 -5.025156 9.317316 27.859936 -5.934920 9.132991 26.651056 -7.169774 10.185093 24.755409 -8.580775 12.346724 22.401640 -9.997738 15.357158 19.873642 -11.249755 18.853294 17.476334 -12.185814 22.413445 15.498863 -12.693013 25.608206 14.179743 -12.710177 28.052240 13.678079 -15.857386 27.479731 13.727750 -15.130622 28.046713 14.941578 -13.949486 27.604836 17.094465 -12.456440 26.207392 19.926741 -10.831568 24.022938 23.096792 -9.270852 21.314947 26.222265 -7.962540 18.410046 28.926178 -7.064431 15.658609 30.882402 -6.684852 13.392498 31.854984 -6.869585 11.885040 31.726624 -7.596348 11.318057 30.512794 -8.777484 11.759934 28.359909 -10.270529 13.157374 25.527634 -11.895401 15.341827 22.357584 -13.456116 18.049816 19.232113 -14.764429 20.954718 16.528198 -15.662539 23.706154 14.571975 -16.042118 25.972267 13.599389 -18.626760 24.794989 13.259263 -18.184914 25.704281 14.399872 -17.284283 25.900738 16.718391 -16.033499 25.360661 19.935173 -14.583426 24.149191 23.662224 -13.108961 22.412453 27.450008 -11.787949 20.359921 30.841661 -10.779722 18.239161 33.428101 -10.205888 16.305969 34.897366 -10.135658 14.793512 35.072239 -10.577505 13.884221 33.931629 -11.478135 13.687765 31.613111 -12.728918 14.227840 28.396332 -14.178991 15.439308 24.669283 -15.653456 17.176044 20.881500 -16.974468 19.228577 17.489845 -17.982695 21.349337 14.903405 -18.556530 23.282532 13.434137 -20.347668 21.531267 12.842909 -20.257793 22.715237 13.798508 -19.858509 23.529461 16.122915 -19.197973 23.875729 19.535776 -18.355856 23.712275 23.625444 -17.433727 23.058817 27.898651 -16.542814 21.994171 31.839979 -15.790568 20.646748 34.974049 -15.267726 19.179066 36.922844 -15.037347 17.768152 37.451317 -15.127219 16.584183 36.495720 -15.526504 15.769960 34.171310 -16.187038 15.423691 30.758451 -17.029156 15.587143 26.668785 -17.951284 16.240601 22.395580 -18.842199 17.305246 18.454250 -19.594444 18.652668 15.320179 -20.117287 20.120350 13.371380 -21.045597 17.915722 12.851557 -21.300924 19.278713 13.484091 -21.553856 20.627594 15.567791 -21.773890 21.799673 18.851332 -21.934481 22.653578 22.938671 -22.016264 23.086317 27.336815 -22.009371 23.045692 31.515280 -21.914637 22.536608 34.970081 -21.743486 21.620462 37.284527 -21.516563 20.407761 38.179451 -21.261236 19.044771 37.546921 -21.008305 17.695889 35.463223 -20.788273 16.523809 32.179684 -20.627680 15.669905 28.092346 -20.545897 15.237166 23.694204 -20.552790 15.277790 19.515738 -20.647522 15.786874 16.060932 -20.818674 16.703018 13.746487 -21.230688 14.207916 13.648324 -21.713812 15.641317 13.835369 -22.604164 17.386852 15.379923 -23.794355 19.233982 18.095688 -25.140831 20.959919 21.655104 -26.481186 22.356483 25.628851 -27.653753 23.255236 29.537636 -28.517105 23.547770 32.910004 -28.967106 23.198803 35.339195 -28.949484 22.250423 36.532219 -28.466360 20.817024 36.345173 -27.576008 19.071487 34.800621 -26.385818 17.224360 32.084858 -25.039343 15.498425 28.525446 -23.698988 14.101858 24.551699 -22.526421 13.203106 20.642914 -21.663069 12.910571 17.270546 -21.213066 13.259538 14.841350 -21.870548 10.521764 15.176973 -22.367012 11.931339 14.877554 -23.664091 13.921643 15.640141 -25.605337 16.252613 17.372759 -27.956610 18.643103 19.866423 -30.434307 20.804781 22.820364 -32.739586 22.476919 25.878292 -34.594391 23.457832 28.671377 -35.775009 23.629208 30.862730 -36.139042 22.970375 32.188046 -35.642578 21.560801 32.487465 -34.345501 19.570498 31.724874 -32.404255 17.239527 29.992262 -30.052984 14.849039 27.498596 -27.575287 12.687360 24.544657 -25.270010 11.015221 21.486729 -23.415201 10.034307 18.693645 -22.234583 9.862930 16.502291 -23.843273 6.756771 16.742249 -24.118990 8.078296 16.034729 -25.446346 10.188913 15.941593 -27.665249 12.834053 16.474075 -30.508060 15.694670 17.567953 -33.631897 18.425734 19.091288 -36.659981 20.697836 20.860340 -39.227074 22.236927 22.661736 -41.023556 22.857372 24.278206 -41.832737 22.484335 25.514774 -41.557022 21.162811 26.222296 -40.229664 19.052195 26.315430 -38.010765 16.407057 25.782948 -35.167953 13.546439 24.689070 -32.044117 10.815376 23.165739 -29.016035 8.543275 21.396687 -26.448938 7.004181 19.595287 -24.652458 6.383735 17.978821 -27.386375 2.746305 17.330704 -27.271252 3.939600 16.389521 -28.248468 6.081421 15.563135 -30.200159 8.913434 14.951226 -32.890919 12.094055 14.627598 -35.996204 15.239656 14.631282 -39.141472 17.970829 14.961838 -41.947353 19.958155 15.579391 -44.075420 20.961933 16.409460 -45.268997 20.861095 17.351925 -45.384121 19.667803 18.293110 -44.406906 17.525982 19.119492 -42.455215 14.693971 19.731401 -39.764458 11.513350 20.055033 -36.659176 8.367750 20.051346 -33.513908 5.636576 19.720793 -30.708025 3.649249 19.103237 -28.579956 2.645468 18.273170 -32.082001 -1.575897 16.099613 -31.508144 -0.540384 15.139698 -31.857088 1.564256 13.845872 -33.086742 4.484173 12.374186 -35.048794 7.867181 10.902149 -37.506588 11.305239 9.607309 -40.163681 14.383667 8.645845 -42.699589 16.731159 8.133722 -44.808441 18.064579 8.132710 -46.235878 18.223089 8.642932 -46.809734 17.187576 9.602846 -46.460793 15.082937 10.896672 -45.231140 12.163022 12.368357 -43.269089 8.780015 13.840393 -40.811295 5.341959 15.135233 -38.154202 2.263530 16.096697 -35.618294 -0.083965 16.608820 -33.509441 -1.417384 16.609833 -37.135181 -6.104305 12.651072 -36.134598 -5.254019 11.877197 -35.722973 -3.250025 10.448971 -35.949955 -0.334033 8.538657 -36.788162 3.142244 6.376670 -38.136497 6.759516 4.223776 -39.832329 10.081485 2.339646 -41.671120 12.707474 0.951535 -43.431076 14.320751 0.226867 -44.899929 14.726729 0.253050 -45.900513 13.876444 1.026925 -46.312138 11.872450 2.455151 -46.085155 8.956459 4.365463 -45.246952 5.480184 6.527450 -43.898617 1.862914 8.680343 -42.202785 -1.459056 10.564473 -40.363995 -4.085047 11.952585 -38.604038 -5.698325 12.677254 -41.666592 -10.589655 7.059942 -40.349819 -9.950272 6.635285 -39.191879 -8.110729 5.410329 -38.332432 -5.292904 3.532821 -37.875145 -1.836666 1.229218 -37.875168 1.841110 -1.222634 -38.332504 5.296829 -3.527003 -39.191990 8.113683 -5.405950 -40.349957 9.951917 -6.632844 -41.666737 10.589811 -7.059707 -42.983509 9.950430 -6.635050 -44.141449 8.110888 -5.410095 -45.000896 5.293065 -3.532588 -45.458183 1.836829 -1.228985 -45.458160 -1.840946 1.222865 -45.000824 -5.296667 3.527235 -44.141342 -8.113522 5.406182 -42.983376 -9.951756 6.633078 -44.899616 -14.727714 -0.254508 -43.431286 -14.320027 -0.225784 -41.671825 -12.705112 -0.948014 -39.833458 -10.077749 -2.334086 -38.137917 -6.754840 -4.216820 -36.789707 -3.137174 -6.369130 -35.951443 0.338903 -8.531414 -35.724232 3.254126 -10.442871 -36.135479 5.256875 -11.872950 -37.135586 6.105592 -12.649163 -38.603916 5.697906 -12.677887 -40.363373 4.082992 -11.955658 -42.201740 1.455632 -10.569587 -43.897285 -1.867276 -8.686854 -45.245495 -5.484941 -6.534545 -46.083759 -8.961018 -4.372260 -46.310970 -11.876242 -2.460804 -45.899723 -13.878994 -1.030723 -46.230907 -18.230846 -8.654118 -44.804600 -18.070538 -8.141304 -42.697353 -16.734591 -8.138662 -40.163330 -14.384134 -8.646513 -37.508175 -11.302671 -9.603600 -35.052135 -7.861873 -10.894485 -33.091450 -4.476748 -12.363469 -31.862600 -1.555594 -13.833370 -31.513811 0.549255 -15.126897 -32.087147 1.583925 -16.088032 -33.513454 1.423619 -16.600845 -35.620701 0.087670 -16.603487 -38.154720 -2.262784 -16.095638 -40.809875 -5.344245 -15.138552 -43.265915 -8.785043 -13.847667 -45.226604 -12.170168 -12.378683 -46.455452 -15.091322 -10.908781 -46.804245 -17.196173 -9.615254 -45.257637 -20.872269 -17.367323 -44.065422 -20.971754 -16.422997 -41.939930 -19.965424 -15.589415 -39.137535 -17.974657 -14.967118 -35.996246 -15.239567 -14.631166 -32.894947 -12.090046 -14.622078 -30.207705 -8.905976 -14.940950 -28.258633 -6.071400 -15.549324 -27.282824 -3.928210 -16.373819 -27.397970 -2.734907 -17.314987 -28.590189 -2.635419 -18.259315 -30.715675 -3.641748 -19.092896 -33.518070 -5.632514 -19.715193 -36.659359 -8.367602 -20.051146 -39.760654 -11.517121 -20.060236 -42.447903 -14.701192 -19.741362 -44.396973 -17.535769 -19.132990 -45.372784 -19.678959 -18.308495 -41.812122 -22.498322 -25.531870 -41.005199 -22.869780 -24.293354 -39.213203 -22.246250 -22.673096 -36.652283 -20.702938 -20.866528 -33.631321 -18.425987 -19.091541 -30.514688 -15.690037 -17.562233 -27.678299 -12.825080 -16.463055 -25.464262 -10.176673 -15.926588 -24.139624 -8.064253 -16.017536 -23.864153 -6.742608 -16.724926 -24.671080 -6.371148 -17.963444 -26.463072 -6.994678 -19.583698 -29.023991 -8.537990 -21.390270 -32.044952 -10.814938 -23.165253 -35.161583 -13.550887 -24.694563 -37.997974 -16.415844 -25.793741 -40.212009 -19.064251 -26.330208 -41.536652 -21.176674 -26.239264 -36.103951 -22.988581 -32.204048 -35.742989 -23.645676 -30.877033 -34.569317 -23.470566 -28.682243 -32.724499 -22.484379 -25.884403 -30.431049 -20.806057 -22.820976 -27.965586 -18.638031 -19.861454 -25.625486 -16.241802 -17.362797 -23.692997 -13.906386 -15.626382 -22.401205 -11.913470 -14.861648 -21.905922 -10.503428 -15.160830 -22.266882 -9.846333 -16.487843 -23.440554 -10.021441 -18.682631 -25.285370 -11.007628 -21.480467 -27.578819 -12.685949 -24.543896 -30.044281 -14.853972 -27.503420 -32.384384 -17.250202 -30.002075 -34.316872 -19.585619 -31.738491 -35.608665 -21.578535 -32.503227 -28.914995 -22.263700 -36.539116 -28.934235 -23.211302 -35.345505 -28.489828 -23.557978 -32.914955 -27.635380 -23.261915 -29.540627 -26.473949 -22.358826 -25.629515 -25.145620 -20.957634 -21.653360 -23.810610 -19.227341 -18.091743 -22.629940 -17.376652 -15.374249 -21.746017 -15.628782 -13.828644 -21.265455 -14.194552 -13.641354 -21.246216 -13.246951 -14.834967 -21.690620 -12.900274 -17.265518 -22.545069 -13.196335 -20.639845 -23.706499 -14.099422 -24.550953 -25.034828 -15.500616 -28.527107 -26.369839 -17.230906 -32.088726 -27.550508 -19.081596 -34.806221 -28.434431 -20.829468 -36.351830 -21.490339 -20.415142 -38.179184 -21.717403 -21.627640 -37.284023 -21.891857 -22.542715 -34.969402 -21.992657 -23.049990 -31.514502 -22.007647 -23.088282 -27.336035 -21.935019 -22.652971 -22.937984 -21.783531 -21.796566 -18.850822 -21.571457 -20.622356 -15.567519 -21.324375 -19.271975 -13.484091 -21.072088 -17.908293 -12.851828 -20.845024 -16.695793 -13.746990 -20.670572 -15.780719 -16.061609 -20.569771 -15.273443 -19.516506 -20.554781 -15.235150 -23.694973 -20.627409 -15.670460 -28.093021 -20.778896 -16.526867 -32.180183 -20.990971 -17.701075 -35.463490 -21.238050 -19.051456 -37.546921 -15.013886 -17.776873 -37.447559 -15.244083 -19.187513 -36.918285 -15.769610 -20.653902 -34.969238 -16.527082 -21.999168 -31.835503 -17.425137 -23.061056 -27.895050 -18.355455 -23.711481 -23.623156 -19.205828 -23.871998 -19.535080 -19.873686 -23.523241 -16.123898 -20.278475 -22.707279 -13.801054 -20.371376 -21.522528 -12.846714 -20.141178 -20.111885 -13.375986 -19.615652 -18.645494 -15.325031 -18.858179 -17.300228 -18.458769 -17.960125 -16.238340 -22.399220 -17.029808 -15.587915 -26.671110 -16.179436 -15.427399 -30.759188 -15.511578 -15.776155 -34.170368 -15.106787 -16.592117 -36.493217 -10.115683 -14.803371 -35.068962 -10.185488 -16.315670 -34.892559 -10.761373 -18.247534 -33.422348 -11.773877 -20.365957 -30.835663 -13.100879 -22.415422 -27.444494 -14.582320 -24.148737 -23.657864 -16.039518 -25.356834 -19.932499 -17.296715 -25.894005 -16.717731 -18.202271 -25.695452 -14.401312 -18.646965 -24.785130 -13.262632 -18.577160 -23.272835 -13.439034 -18.001276 -21.340969 -14.909241 -16.988771 -19.222546 -17.495924 -15.661772 -17.173080 -20.887094 -14.180330 -15.439767 -24.673723 -12.723131 -14.231667 -28.399088 -11.465935 -13.694498 -31.613855 -10.560378 -13.893049 -33.930275 -6.858185 -11.891773 -31.726753 -6.672746 -13.399284 -31.853447 -7.053092 -15.664634 -30.879385 -7.953347 -18.414583 -28.922054 -9.264928 -21.317448 -26.217539 -10.829638 -24.023102 -23.092041 -12.458751 -26.205202 -19.922546 -13.955770 -27.600555 -17.091339 -15.140134 -28.040859 -14.939904 -15.868992 -27.473011 -13.727737 -16.054432 -25.965500 -13.601043 -15.674086 -23.700153 -14.575105 -14.773830 -20.950205 -16.532433 -13.462251 -18.047340 -19.236948 -11.897541 -15.341686 -22.362444 -10.268429 -13.159586 -25.531939 -8.771409 -11.764231 -28.363148 -7.587044 -11.323924 -30.514584 -5.015151 -9.323261 -27.863365 -4.539734 -10.722114 -28.237827 -4.557699 -13.165724 -27.734138 -5.066879 -16.359360 -26.413055 -6.005858 -19.917814 -24.433918 -7.261383 -23.411894 -22.035442 -8.682017 -26.420153 -19.506916 -10.096413 -28.579758 -17.153318 -11.333972 -29.630222 -15.258530 -12.245427 -29.444849 -14.051087 -12.720843 -28.045998 -13.676626 -12.702879 -25.602385 -14.180311 -12.193701 -22.408752 -15.501394 -11.254722 -18.850296 -17.480528 -9.999198 -15.356220 -19.879005 -8.578564 -12.347960 -22.407532 -7.164168 -10.188354 -24.761129 -5.926608 -9.137888 -26.655920 -4.309603 -7.295757 -23.715191 -3.552497 -8.487972 -24.288292 -3.109661 -10.942396 -24.217846 -3.034510 -14.362988 -23.512346 -3.336106 -18.337175 -22.256891 -3.978073 -22.385609 -20.602905 -4.882980 -26.019991 -18.749886 -5.941682 -28.801960 -16.921329 -7.026484 -30.395969 -15.337790 -8.006543 -30.609762 -14.190266 -8.763649 -29.417545 -13.617165 -9.206485 -26.963123 -13.687611 -9.281637 -23.542534 -14.393108 -8.980042 -19.568348 -15.648563 -8.338075 -15.519916 -17.302549 -7.433168 -11.885533 -19.155569 -6.374467 -9.103563 -20.984125 -5.289664 -7.509550 -22.567665 -4.456978 -5.984826 -19.405848 -3.461288 -6.880007 -20.134054 -2.520553 -9.168030 -20.458447 -1.748239 -12.572924 -20.339903 -1.237498 -16.684008 -19.792717 -1.049933 -21.005424 -18.882889 -1.208168 -25.015947 -17.720158 -1.693116 -28.231848 -16.444765 -2.446285 -30.265244 -15.210543 -3.376834 -30.870872 -14.166357 -4.372523 -29.975691 -13.438150 -5.313259 -27.687670 -13.113756 -6.085573 -24.282780 -13.232302 -6.596314 -20.171696 -13.779488 -6.783880 -15.850280 -14.689314 -6.625646 -11.839757 -15.852045 -6.140698 -8.623856 -17.127438 -5.387529 -6.590458 -18.361658 -5.139244 -5.546748 -15.032660 -3.978448 -6.068910 -15.871071 -2.563909 -8.010492 -16.545313 -1.066242 -11.137310 -16.974058 0.333914 -15.072225 -17.105600 1.467679 -19.340624 -16.924068 2.198303 -23.427677 -16.451359 2.437663 -26.840427 -15.744489 2.156889 -29.167244 -14.888716 1.389846 -30.127481 -13.987261 0.229050 -29.605320 -13.148849 -1.185488 -27.663738 -12.474609 -2.683155 -24.536922 -12.045862 -4.083311 -20.602011 -11.914321 -5.217075 -16.333612 -12.095852 -5.947701 -12.246558 -12.568561 -6.187061 -8.833809 -13.275430 -5.906288 -6.506988 -14.131202 -6.012189 -6.079504 -10.682225 -4.787064 -6.175660 -11.583809 -2.984539 -7.601421 -12.555084 -0.822029 -10.184816 -13.478903 1.439638 -13.614250 -14.243836 3.527671 -17.476084 -14.757626 5.190221 -21.304520 -14.958296 6.226762 -24.637798 -14.821647 6.512270 -27.073868 -14.364159 6.012311 -28.318911 -13.641011 4.787186 -28.222755 -12.739429 2.984662 -26.796995 -11.768152 0.822152 -24.213602 -10.844334 -1.439514 -20.784168 -10.079400 -3.527546 -16.922338 -9.565612 -5.190098 -13.093901 -9.364940 -6.226639 -9.760624 -9.501589 -6.512149 -7.324551 -9.959077 -6.694061 -7.583588 -6.459356 -5.524398 -7.235477 -7.372450 -3.478905 -8.007902 -8.574357 -0.804299 -9.807694 -9.920111 2.176823 -12.417773 -11.247393 5.104894 -15.523327 -12.396112 7.626744 -18.749777 -13.227716 9.438204 -21.707964 -13.641904 10.320781 -24.041092 -13.588717 10.168027 -25.467751 -13.074569 8.998364 -25.815861 -12.161475 6.952873 -25.043438 -10.959568 4.278267 -23.243647 -9.613815 1.297147 -20.633568 -8.286534 -1.630924 -17.528017 -7.137815 -4.152776 -14.301569 -6.306209 -5.964235 -11.343380 -5.892020 -6.846815 -9.010250 -5.945207 -6.810575 -9.920686 -2.480874 -5.820670 -9.153641 -3.349645 -3.723051 -9.190952 -4.700150 -0.770720 -10.028120 -6.369497 2.680226 -11.564169 -8.156339 6.213553 -13.613831 -9.845155 9.403090 -15.929883 -11.232249 11.864130 -18.232977 -12.150320 13.299838 -20.245325 -12.488632 13.537045 -21.724209 -12.206380 12.547141 -22.491255 -11.337609 10.449523 -22.453943 -9.987104 7.497195 -21.616777 -8.317759 4.046250 -20.080730 -6.530918 0.512923 -18.031071 -4.842102 -2.676614 -15.715017 -3.455006 -5.137655 -13.411924 -2.536936 -6.573366 -11.399574 -2.198622 -6.059808 -12.826948 1.151831 -5.363154 -11.710772 0.382509 -3.428196 -11.002307 -1.024357 -0.488317 -10.787002 -2.899079 3.101889 -11.090828 -5.015536 6.909390 -11.877139 -7.118454 10.474944 -13.051094 -8.954189 13.368495 -14.471096 -10.301325 15.241036 -15.965872 -10.997375 15.866715 -17.355133 -10.958389 15.170062 -18.471310 -10.189068 13.235105 -19.179773 -8.782203 10.295227 -19.395079 -6.907482 6.705023 -19.091255 -4.791025 2.897524 -18.304945 -2.688108 -0.668032 -17.130991 -0.852372 -3.561583 -15.710988 0.494763 -5.434128 -14.216211 1.190816 -4.257581 -15.935158 4.347052 -3.939451 -14.578997 3.728463 -2.376657 -13.192711 2.364223 0.242304 -11.943508 0.418881 3.601546 -10.982059 -1.872929 7.295897 -10.424331 -4.234777 10.879760 -10.337591 -6.381792 13.920871 -10.732305 -8.055011 16.052425 -11.560860 -9.052620 17.017330 -12.723324 -9.254293 16.699202 -14.079486 -8.635704 15.136407 -15.465772 -7.271465 12.517449 -16.714973 -5.326123 9.158208 -17.676422 -3.034315 5.463860 -18.234152 -0.672467 1.879995 -18.320892 1.474548 -1.161116 -17.926182 3.147768 -3.292675 -17.097626 4.145378 -1.359717 -18.827473 7.057481 -1.465026 -17.367775 6.631776 -0.451318 -15.445376 5.406195 1.559136 -13.292151 3.528560 4.323847 -11.167807 1.225341 7.509350 -9.328571 -1.225658 10.731425 -7.996284 -3.528811 13.601444 -7.331638 -5.406325 15.773239 -7.414802 -6.631742 16.984861 -8.235739 -7.057261 17.090170 -9.695436 -6.631557 16.076464 -11.617834 -5.405976 14.066010 -13.771057 -3.528342 11.301301 -15.895401 -1.225125 8.115800 -17.734638 1.225874 4.893724 -19.066925 3.529027 2.023705 -19.731571 5.406542 -0.148092 -19.648411 6.631960 2.513249 -21.096239 9.260976 1.988793 -19.679518 9.058798 2.336491 -17.419716 8.059967 3.514404 -14.589398 6.384958 5.380460 -11.529947 4.235802 7.709583 -8.610374 1.871718 10.220848 -6.182826 -0.422148 12.611358 -4.540097 -2.369125 14.592784 -3.880326 -3.734378 15.926135 -4.283092 -4.353237 16.450592 -5.699814 -4.151059 16.102894 -7.959615 -3.152229 14.924982 -10.789929 -1.477221 13.058928 -13.849380 0.671934 10.729806 -16.768953 3.036016 8.218541 -19.196503 5.329884 5.828031 -20.839231 7.276861 3.846604 -21.499004 8.642115 7.097570 -22.419605 10.957074 6.206955 -21.183348 10.995846 5.848334 -18.814346 10.299795 6.064961 -15.598340 8.952874 6.830709 -11.923224 7.117542 8.053216 -8.232275 5.015168 9.585031 -4.970675 2.899328 11.241392 -2.531819 1.025225 12.822520 -1.209870 -0.381098 14.137708 -1.164275 -1.150017 15.028323 -2.400532 -1.188790 15.386945 -4.769533 -0.492739 15.170319 -7.985537 0.854181 14.404572 -11.660650 2.689511 13.182065 -15.351601 4.791885 11.650251 -18.613203 6.907725 9.993890 -21.052059 8.781828 8.412761 -22.374010 10.188152 12.047471 -22.585335 12.206842 10.884989 -21.640785 12.488794 9.859546 -19.391546 12.150195 9.094827 -16.108908 11.231881 8.683067 -12.188801 9.844616 8.673932 -8.104052 8.155725 9.068523 -4.347341 6.368913 9.819247 -1.371784 4.699696 10.835554 0.463725 3.349406 11.994864 0.937797 2.480907 13.157346 -0.006749 2.198954 14.182789 -2.255988 2.537554 14.947509 -5.538626 3.455866 15.359267 -9.458731 4.843131 15.368403 -13.543479 6.532021 14.973813 -17.300190 8.318832 14.223090 -20.275749 9.988050 13.206783 -22.111259 11.338341 16.972622 -21.537722 13.080452 15.660729 -20.956490 13.594398 14.081384 -19.025637 13.646731 12.425076 -15.978056 13.231140 10.891581 -12.181329 12.397751 9.665861 -8.093397 11.247082 8.895758 -4.207327 9.917921 8.674155 -0.991834 8.570586 9.027781 1.165246 7.367584 9.913985 2.003737 6.454014 11.225878 1.422505 5.940068 12.805223 -0.508346 5.887734 14.461531 -3.555925 6.303324 15.995026 -7.352651 7.136714 17.220745 -11.440580 8.287382 17.990850 -15.326652 9.616542 18.212454 -18.542145 10.963878 17.858828 -20.699228 12.166880 21.516088 -19.366642 13.650161 20.188129 -19.175980 14.373487 18.221746 -17.709641 14.830060 15.854119 -15.144489 14.964808 13.370816 -11.789918 14.761478 11.071361 -8.050539 14.244596 9.233101 -4.377378 13.476507 8.077759 -1.213471 12.549850 7.744684 1.059568 11.576398 8.274051 2.167579 10.673559 9.602011 1.976918 9.950232 11.568391 0.510580 9.493659 13.936018 -2.054571 9.358911 16.419321 -5.409140 9.562240 18.718777 -9.148517 10.079121 20.557037 -12.821678 10.847210 21.712379 -15.985586 11.773867 22.045456 -18.258627 12.747319 25.393970 -16.270220 13.996949 24.178963 -16.452963 14.898832 22.023876 -15.531104 15.753842 19.188646 -13.615835 16.458851 16.015242 -10.938168 16.928822 12.886422 -7.821064 17.107069 10.179572 -4.640495 16.972097 8.221175 -1.780085 16.540184 7.247445 0.415160 15.863424 7.375824 1.680461 15.023444 8.590830 1.863204 14.121560 10.745916 0.941347 13.266551 13.581145 -0.973919 12.561543 16.754549 -3.651587 12.091573 19.883368 -6.768688 11.913323 22.590218 -9.949257 12.048296 24.548616 -12.809669 12.480209 25.522350 -15.004915 13.156969 28.423754 -12.512323 14.171221 27.434010 -13.014691 15.215762 25.296444 -12.649470 16.449736 22.268881 -11.460710 17.724308 18.716490 -9.591791 18.885746 15.067739 -7.268135 19.793964 11.762725 -4.770010 20.339417 9.200079 -2.398725 20.456314 7.688894 -0.440292 20.130558 7.411440 0.869074 19.401438 8.401184 1.371443 18.356897 10.538748 1.006220 17.122923 13.566308 -0.182539 15.848351 17.118698 -2.051455 14.686913 20.767448 -4.375110 13.778695 24.072464 -6.873235 13.233242 26.635111 -9.244520 13.116344 28.146299 -11.202955 13.442100 30.511934 -8.377662 14.195780 29.836729 -9.117996 15.344269 27.913887 -9.258291 16.928020 24.975334 -8.781625 18.756004 21.375504 -7.745489 20.607738 17.548588 -6.274858 22.259878 13.956169 -4.547112 23.513153 11.031547 -2.770642 24.216396 9.127472 -1.159717 24.284788 8.473603 0.091363 23.710079 9.148809 0.831698 22.561588 11.071650 0.971994 20.977839 14.010200 0.495328 19.149857 17.610029 -0.540807 17.298120 21.436945 -2.011437 15.645981 25.029364 -3.739183 14.392706 27.953987 -5.515653 13.689461 29.858065 -7.126579 13.621070 31.622692 -4.129625 14.054400 31.327463 -5.009600 15.263334 29.798939 -5.552838 17.159058 27.221481 -5.693818 19.512918 23.905972 -5.415534 22.041008 20.252310 -4.751553 24.438400 16.701180 -3.781960 26.415936 13.680902 -2.623703 27.735092 11.555765 -1.416483 28.236763 10.582091 -0.305911 27.860435 10.877320 0.574063 26.651505 12.405846 1.117302 24.755781 14.983299 1.258282 22.401922 18.298807 0.979999 19.873833 21.952469 0.316018 17.476440 25.503597 -0.653574 15.498903 28.523876 -1.811831 14.179747 30.649015 -3.019050 13.678075</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="2160" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="6480">0.742838 0.034130 -0.668600 0.553596 0.168309 -0.815600 0.966540 0.250659 -0.054507 0.989081 -0.001672 0.147362 0.965262 0.101118 0.240922 0.883274 -0.128780 0.450825 0.927453 -0.166826 0.334663 0.772587 -0.345139 0.532906 0.808700 -0.459718 0.366966 0.608911 -0.587383 0.533112 0.632664 -0.678914 0.372574 0.402329 -0.774582 0.488011 0.452687 -0.801384 0.390971 0.194914 -0.873088 0.446907 0.270784 -0.841688 0.467158 -0.012703 -0.887175 0.461258 -0.013302 -0.726325 0.687223 -0.316974 -0.729747 0.605803 -0.501520 -0.124810 0.856096 -0.710597 -0.036058 0.702674 -0.632513 0.616025 0.469511 -0.580336 0.738663 0.342908 -0.563844 0.813796 0.140769 -0.402573 0.913877 0.052563 -0.581682 0.811618 -0.054056 -0.388561 0.909359 -0.148614 -0.671723 0.697071 -0.250759 -0.462221 0.801377 -0.379665 -0.777287 0.419550 -0.468831 -0.555376 0.546130 -0.627136 -0.778773 0.047000 -0.625542 -0.570859 0.225452 -0.789488 -0.674689 -0.205650 -0.708875 -0.485938 0.004524 -0.873982 -0.419102 -0.241892 -0.875124 -0.172671 -0.065575 -0.982794 0.265519 0.223692 -0.937796 0.829120 0.491713 -0.266041 0.938339 0.345389 -0.015026 0.996736 0.033487 0.073454 0.940274 -0.310884 0.138695 0.806916 -0.556660 0.197527 0.668641 -0.692112 0.271845 0.533050 -0.743634 0.403568 0.305721 -0.648919 0.696734 -0.220987 -0.130806 0.966465 -0.593564 0.520092 0.614155 -0.654541 0.705638 0.271387 -0.713037 0.695526 0.088442 -0.818198 0.570879 -0.068184 -0.932061 0.271974 -0.239358 -0.912241 -0.155469 -0.379006 -0.769257 -0.448077 -0.455490 -0.589456 -0.495904 -0.637668 -0.090855 0.110492 -0.989716 0.600379 0.645894 -0.471557 0.796613 0.524323 -0.300821 0.951202 0.192573 -0.241101 0.971204 -0.188203 -0.146091 0.893742 -0.447272 -0.034250 0.808966 -0.581258 0.087824 0.735598 -0.625288 0.260598 0.599832 -0.519357 0.608662 0.104661 -0.046645 0.993414 -0.455308 0.487046 0.745305 -0.649151 0.627958 0.429268 -0.753741 0.598325 0.271812 -0.871853 0.462116 0.162237 -0.985975 0.158186 0.053204 -0.954557 -0.291940 -0.059930 -0.776366 -0.612734 -0.147692 -0.643133 -0.690036 -0.332009 -0.419280 -0.161428 -0.893390 0.343080 0.635194 -0.691972 0.587042 0.547997 -0.595886 0.791594 0.229541 -0.566295 0.881448 -0.148594 -0.448296 0.869450 -0.398691 -0.291723 0.845092 -0.516974 -0.136227 0.841445 -0.537591 0.054458 0.821049 -0.388973 0.417826 0.429358 0.099849 0.897598 -0.233667 0.536081 0.811182 -0.538618 0.618418 0.572232 -0.685365 0.563423 0.461335 -0.812102 0.418383 0.406751 -0.921163 0.133099 0.365710 -0.912139 -0.286005 0.293605 -0.765271 -0.617282 0.182547 -0.687986 -0.723910 -0.051279 -0.696207 -0.370035 -0.615118 0.048591 0.406335 -0.912431 0.341740 0.372199 -0.862949 0.547021 0.099725 -0.831158 0.680602 -0.225765 -0.697001 0.734431 -0.441343 -0.515584 0.771141 -0.534225 -0.346331 0.834820 -0.525298 -0.164735 0.933971 -0.319852 0.159348 0.700896 0.244188 0.670162 0.029241 0.645870 0.762887 -0.343281 0.685487 0.642080 -0.517145 0.612297 0.598041 -0.644902 0.467792 0.604378 -0.746566 0.219077 0.628208 -0.778262 -0.130241 0.614284 -0.730600 -0.445464 0.517480 -0.759323 -0.601422 0.248435 -0.882653 -0.391307 -0.260389 -0.291216 0.040226 -0.955811 0.052401 0.047405 -0.997500 0.250922 -0.155093 -0.955502 0.407207 -0.399202 -0.821474 0.516045 -0.565474 -0.643378 0.607685 -0.630999 -0.482245 0.728610 -0.598389 -0.333254 0.931815 -0.349001 -0.099598 0.882393 0.315064 0.349452 0.283337 0.758605 0.586718 -0.105400 0.795412 0.596834 -0.285044 0.723873 0.628298 -0.404225 0.594937 0.694732 -0.496139 0.392313 0.774556 -0.557794 0.121783 0.820996 -0.605641 -0.147899 0.781872 -0.757769 -0.350100 0.550651 -0.955643 -0.284878 0.074768 -0.589072 -0.256649 -0.766241 -0.249689 -0.282560 -0.926183 -0.055483 -0.429042 -0.901579 0.110649 -0.603137 -0.789925 0.255782 -0.725704 -0.638693 0.389841 -0.770778 -0.503910 0.553622 -0.729055 -0.402468 0.833520 -0.469792 -0.290756 0.962178 0.272375 0.005121 0.491372 0.813333 0.311517 0.131301 0.891971 0.432607 -0.033603 0.846112 0.531945 -0.135197 0.748456 0.649258 -0.214101 0.596586 0.773463 -0.288595 0.398109 0.870759 -0.393135 0.186430 0.900382 -0.645679 -0.030288 0.763008 -0.932637 -0.094131 0.348320 -0.799242 -0.390492 -0.456868 -0.513784 -0.503731 -0.694464 -0.332718 -0.631775 -0.700113 -0.168114 -0.767512 -0.618598 -0.005727 -0.865091 -0.501583 0.155038 -0.902881 -0.400960 0.345486 -0.870261 -0.351121 0.670798 -0.643384 -0.368900 0.948606 0.118518 -0.293430 0.633819 0.773392 -0.011722 0.334096 0.925736 0.177180 0.199603 0.924618 0.324407 0.122788 0.869869 0.477757 0.061068 0.771019 0.633878 -0.012638 0.637604 0.770261 -0.141137 0.487665 0.861547 -0.456413 0.295178 0.839379 -0.837367 0.156475 0.523767 -0.920862 -0.366985 -0.131661 -0.714394 -0.582738 -0.387373 -0.557273 -0.721038 -0.411767 -0.402868 -0.845116 -0.351391 -0.236626 -0.936022 -0.260521 -0.062861 -0.979940 -0.189117 0.138943 -0.973185 -0.183316 0.478729 -0.818809 -0.316814 0.860458 -0.115312 -0.496301 0.702811 0.629913 -0.330556 0.481301 0.867328 -0.126852 0.387895 0.920711 0.042760 0.341719 0.914778 0.215430 0.302085 0.869500 0.390787 0.239733 0.797467 0.553691 0.109736 0.713361 0.692152 -0.232545 0.583137 0.778379 -0.694442 0.431319 0.575947 -0.965097 -0.220590 0.141167 -0.845674 -0.528195 -0.076461 -0.719029 -0.688136 -0.097293 -0.579296 -0.814098 -0.040737 -0.415459 -0.908706 0.040589 -0.236384 -0.966786 0.097198 -0.034347 -0.996486 0.076387 0.291860 -0.945973 -0.141254 0.720769 -0.385801 -0.575890 0.697199 0.393939 -0.598937 0.559543 0.707041 -0.432440 0.514289 0.815163 -0.266487 0.504100 0.858841 -0.090969 0.491651 0.866043 0.090820 0.448780 0.853050 0.266275 0.332626 0.838216 0.432149 -0.007224 0.800948 0.598690 -0.530110 0.687515 0.496292 -0.948455 0.004725 0.316876 -0.912120 -0.366655 0.183308 -0.817122 -0.544588 0.189039 -0.692343 -0.672953 0.260377 -0.530602 -0.771414 0.351258 -0.345910 -0.843115 0.411708 -0.147415 -0.910080 0.387328 0.142829 -0.980977 0.131471 0.554168 -0.647047 -0.523668 0.621224 0.089703 -0.778482 0.562920 0.451370 -0.692377 0.570744 0.606196 -0.553875 0.601899 0.696344 -0.390925 0.621232 0.753389 -0.215583 0.603253 0.796391 -0.042992 0.510360 0.850603 0.126517 0.194130 0.923734 0.330195 -0.371820 0.880748 0.293315 -0.892635 0.258745 0.369125 -0.926273 -0.136481 0.351272 -0.859305 -0.317514 0.400974 -0.746343 -0.437606 0.501471 -0.580824 -0.529268 0.618481 -0.381014 -0.603881 0.700112 -0.179473 -0.696732 0.694517 0.061458 -0.887525 0.456643 0.384625 -0.854886 -0.348185 0.483700 -0.248345 -0.839261 0.492914 0.120990 -0.861625 0.558536 0.307527 -0.770367 0.637141 0.438309 -0.633985 0.691757 0.541350 -0.477924 0.700659 0.635336 -0.324692 0.634349 0.752371 -0.177592 0.352648 0.935689 0.011238 -0.245593 0.969358 -0.005377 -0.823757 0.486482 0.291136 -0.908089 0.114278 0.402883 -0.862278 -0.048257 0.504131 -0.756351 -0.141536 0.638671 -0.577887 -0.205605 0.789793 -0.344153 -0.262161 0.901571 -0.120083 -0.357096 0.926317 0.072036 -0.638686 0.766088 0.230561 -0.970194 -0.074605 0.296211 -0.575138 -0.762545 0.357936 -0.248187 -0.900159 0.489123 -0.051431 -0.870697 0.623692 0.112717 -0.773501 0.715571 0.257251 -0.649446 0.749165 0.394188 -0.532323 0.706310 0.559917 -0.433151 0.458179 0.832245 -0.312153 -0.169102 0.921426 -0.349827 -0.768462 0.632028 0.100034 -0.882508 0.331172 0.333924 -0.850155 0.210246 0.482736 -0.747672 0.163920 0.643519 -0.549538 0.153268 0.821290 -0.260174 0.140540 0.955279 0.014552 0.070126 0.997432 0.179868 -0.232114 0.955913 0.101380 -0.960043 0.260843 0.074937 -0.831985 -0.549714 0.174477 -0.599570 -0.781072 0.384401 -0.422909 -0.820600 0.587840 -0.233707 -0.774484 0.717132 -0.052434 -0.694962 0.768958 0.115400 -0.628798 0.740878 0.306715 -0.597516 0.514496 0.624663 -0.587444 -0.140068 0.728567 -0.670501 -0.744543 0.648390 -0.158893 -0.872481 0.459744 0.165568 -0.848163 0.400224 0.347046 -0.749353 0.415103 0.515907 -0.535970 0.476740 0.696746 -0.187582 0.524531 0.830470 0.151026 0.483519 0.862207 0.326790 0.245844 0.912562 0.026400 -0.787334 0.615961 -0.142106 -0.958473 -0.247255 -0.020742 -0.856350 -0.515979 0.276386 -0.739824 -0.613409 0.563064 -0.537173 -0.628016 0.727392 -0.324383 -0.604712 0.788388 -0.141339 -0.598722 0.764565 0.045778 -0.642919 0.543725 0.348189 -0.763628 -0.129491 0.421096 -0.897725 -0.748174 0.515885 -0.417251 -0.886647 0.459343 -0.053493 -0.870356 0.472948 0.137116 -0.779978 0.553388 0.292228 -0.569500 0.689128 0.448076 -0.197573 0.800897 0.565269 0.180098 0.783596 0.594594 0.377184 0.615635 0.691899 0.069443 -0.442213 0.894218 -0.283288 -0.957608 0.052291 -0.151627 -0.971781 -0.180698 0.208582 -0.933272 -0.292398 0.575881 -0.731287 -0.365485 0.768242 -0.493896 -0.407272 0.830254 -0.311454 -0.462249 0.804216 -0.156883 -0.573257 0.580081 0.065673 -0.811907 -0.093898 0.066764 -0.993341 -0.750541 0.259111 -0.607905 -0.909807 0.323892 -0.259510 -0.908120 0.409613 -0.086802 -0.834302 0.550200 0.034931 -0.648650 0.746935 0.146087 -0.309328 0.920123 0.240187 0.054608 0.952556 0.299424 0.257568 0.843651 0.471075 0.140068 -0.022266 0.989892 -0.275399 -0.901807 0.333016 -0.141459 -0.978608 0.149387 0.224877 -0.972473 0.061043 0.629940 -0.774827 -0.053081 0.836009 -0.523961 -0.162956 0.894764 -0.353397 -0.272961 0.867860 -0.247942 -0.430515 0.648534 -0.150716 -0.746116 -0.003868 -0.257102 -0.966376 -0.715651 -0.060205 -0.695859 -0.911083 0.089473 -0.402397 -0.934074 0.232827 -0.270734 -0.885735 0.420452 -0.196709 -0.739449 0.658829 -0.138416 -0.469695 0.879730 -0.073907 -0.170993 0.985173 0.014007 0.009922 0.964092 0.265383 0.060384 0.342320 0.937641 -0.133824 -0.758228 0.638108 -0.002275 -0.889697 0.456545 0.321949 -0.867333 0.379582 0.701474 -0.671337 0.239251 0.903420 -0.423429 0.067375 0.958711 -0.269859 -0.089719 0.937959 -0.214002 -0.272831 0.746360 -0.253931 -0.615195 0.141753 -0.496858 -0.856177 -0.623079 -0.374989 -0.686408 -0.864881 -0.186523 -0.466037 -0.920820 -0.008674 -0.389892 -0.904608 0.208579 -0.371724 -0.802628 0.470618 -0.366480 -0.608393 0.719634 -0.334643 -0.395600 0.886145 -0.241346 -0.266979 0.962182 0.054112 -0.131187 0.563386 0.815712 0.001151 -0.483792 0.875182 0.160305 -0.686543 0.709197 0.430560 -0.650599 0.625572 0.751968 -0.463683 0.468553 0.939596 -0.233752 0.250037 0.993747 -0.098340 0.052871 0.986465 -0.081635 -0.142207 0.849064 -0.239831 -0.470713 0.323411 -0.633392 -0.703008 -0.474028 -0.639435 -0.605327 -0.762485 -0.454540 -0.460445 -0.854073 -0.267570 -0.446055 -0.872398 -0.038587 -0.487270 -0.813425 0.233894 -0.532573 -0.685381 0.496547 -0.532630 -0.553391 0.700353 -0.450848 -0.496216 0.855577 -0.147504 -0.341489 0.660276 0.668896 0.030586 -0.182470 0.982735 0.247710 -0.418344 0.873858 0.481135 -0.381625 0.789222 0.750813 -0.208379 0.626784 0.925335 -0.000354 0.379150 0.982020 0.117475 0.147771 0.992736 0.107672 -0.053688 0.929392 -0.133713 -0.344023 0.517354 -0.669720 -0.532747 -0.282108 -0.831836 -0.477979 -0.608278 -0.683827 -0.402961 -0.731523 -0.511295 -0.451055 -0.782241 -0.286766 -0.553050 -0.762206 -0.012595 -0.647212 -0.689399 0.255444 -0.677847 -0.626901 0.477449 -0.615661 -0.651424 0.683946 -0.328428 -0.541988 0.665570 0.513095 -0.041745 0.058810 0.997396 0.234329 -0.158808 0.959098 0.450029 -0.117420 0.885261 0.685460 0.049688 0.726413 0.853054 0.242754 0.461920 0.916812 0.344852 0.201328 0.947958 0.318358 -0.004947 0.968859 0.032204 -0.245510 0.702030 -0.615444 -0.358307 -0.065076 -0.944177 -0.322948 -0.413219 -0.856648 -0.308875 -0.557444 -0.718423 -0.416083 -0.633853 -0.512783 -0.579038 -0.647747 -0.243427 -0.721919 -0.622031 0.024777 -0.782601 -0.619513 0.250660 -0.743891 -0.730482 0.477821 -0.487937 -0.722299 0.594282 0.353713 -0.181700 0.213890 0.959810 0.137115 0.049802 0.989302 0.343356 0.108235 0.932948 0.555743 0.282322 0.781949 0.721366 0.471704 0.507076 0.797527 0.560880 0.222181 0.851481 0.524238 0.012460 0.957760 0.229114 -0.173789 0.856043 -0.482265 -0.186042 0.157307 -0.975502 -0.153785 -0.192594 -0.962592 -0.190588 -0.341138 -0.872672 -0.349383 -0.431556 -0.698175 -0.571236 -0.473558 -0.439589 -0.763220 -0.489575 -0.175951 -0.854024 -0.539495 0.041702 -0.840955 -0.735323 0.258243 -0.626586 -0.868961 0.455546 0.193352 -0.356873 0.280422 0.891070 -0.018237 0.190759 0.981467 0.176567 0.277870 0.944252 0.367900 0.470751 0.801899 0.533039 0.667200 0.520301 0.627661 0.747545 0.217297 0.707984 0.706190 0.007381 0.892945 0.432933 -0.123364 0.958326 -0.284929 -0.020677 0.365202 -0.930736 0.018907 0.035675 -0.997653 -0.058444 -0.097113 -0.961460 -0.257223 -0.185270 -0.826092 -0.532210 -0.248195 -0.583796 -0.773034 -0.302013 -0.329914 -0.894396 -0.396995 -0.131423 -0.908363 -0.667877 0.044290 -0.742953 -0.964875 0.260341 0.035210 -0.538526 0.262041 0.800827 -0.206495 0.257218 0.944033 -0.031894 0.380191 0.924358 0.133436 0.599332 0.789301 0.296031 0.811386 0.504003 0.414770 0.889574 0.191371 0.525504 0.850692 -0.013019 0.776155 0.624309 -0.088439 0.990125 -0.043991 0.133107 0.540902 -0.820076 0.186816 0.253503 -0.964117 0.078833 0.155553 -0.977048 -0.145534 0.088104 -0.881871 -0.463185 0.013023 -0.660481 -0.750730 -0.074743 -0.422414 -0.903316 -0.206212 -0.252746 -0.945302 -0.532963 -0.144047 -0.833787 -0.992819 0.025676 -0.116834 -0.699839 0.166400 0.694648 -0.402497 0.247253 0.881398 -0.260370 0.407381 0.875356 -0.129888 0.654676 0.744667 0.024978 0.888192 0.458794 0.170621 0.974312 0.146986 0.313724 0.948478 -0.044356 0.612096 0.788105 -0.065038 0.938757 0.213987 0.270084 0.670039 -0.657555 0.344484 0.444666 -0.869458 0.215208 0.395146 -0.918402 -0.019923 0.364916 -0.856098 -0.365969 0.287697 -0.657917 -0.695971 0.170936 -0.441955 -0.880600 0.013362 -0.308636 -0.951086 -0.341631 -0.285884 -0.895298 -0.940223 -0.225553 -0.255159 -0.815497 0.006373 0.578727 -0.580248 0.163992 0.797758 -0.483595 0.356397 0.799448 -0.397823 0.628218 0.668640 -0.258227 0.886080 0.384942 -0.088457 0.992448 0.084982 0.083772 0.992835 -0.085213 0.407730 0.911625 -0.051929 0.800788 0.458781 0.385042 0.741732 -0.459296 0.488754 0.595629 -0.724316 0.347263 0.600244 -0.791592 0.114414 0.617387 -0.747917 -0.243831 0.548298 -0.572350 -0.609742 0.409578 -0.384442 -0.827315 0.237889 -0.292080 -0.926336 -0.111955 -0.363545 -0.924825 -0.802628 -0.464704 -0.373951 -0.865543 -0.198454 0.459838 -0.715527 0.017469 0.698366 -0.675174 0.231406 0.700422 -0.642310 0.519181 0.563816 -0.526778 0.801161 0.283983 -0.342447 0.939522 0.005271 -0.151416 0.978944 -0.136900 0.172130 0.983742 -0.051204 0.583960 0.660303 0.472218 0.747657 -0.243539 0.617817 0.694604 -0.541648 0.473437 0.751647 -0.609268 0.252626 0.817591 -0.566622 -0.102393 0.765779 -0.409960 -0.495495 0.614661 -0.255040 -0.746422 0.441622 -0.205070 -0.873451 0.131226 -0.366738 -0.921023 -0.586941 -0.662720 -0.465083 -0.837981 -0.422027 0.345949 -0.788582 -0.173921 0.589822 -0.810549 0.045997 0.583862 -0.834926 0.337153 0.435001 -0.752054 0.639533 0.159411 -0.568381 0.817628 -0.091802 -0.375310 0.904671 -0.201773 -0.080713 0.994484 -0.066987 0.307032 0.792853 0.526417 0.683486 -0.030962 0.729306 0.731781 -0.337126 0.592319 0.834217 -0.389668 0.390180 0.942031 -0.331612 0.051094 0.914316 -0.187442 -0.359015 0.763067 -0.067921 -0.642740 0.601511 -0.058370 -0.796729 0.360692 -0.294393 -0.885005 -0.311063 -0.793526 -0.523027 -0.731588 -0.636277 0.244808 -0.787731 -0.386552 0.479642 -0.871301 -0.178578 0.457104 -0.951817 0.101524 0.289374 -0.908476 0.417594 0.016963 -0.743412 0.636861 -0.204323 -0.568586 0.773005 -0.281378 -0.331415 0.937796 -0.103449 -0.002265 0.839354 0.543580 0.551178 0.155905 0.819693 0.700956 -0.129736 0.701305 0.838674 -0.155430 0.521985 0.975641 -0.069913 0.207935 0.975636 0.069920 -0.207955 0.838596 0.155487 -0.522093 0.700794 0.129832 -0.701449 0.551013 -0.155795 -0.819825 -0.002266 -0.839343 -0.543597 -0.556286 -0.814871 0.162883 -0.711439 -0.594297 0.375054 -0.848313 -0.415571 0.328126 -0.977683 -0.160447 0.135618 -0.977690 0.160440 -0.135577 -0.848387 0.415503 -0.328020 -0.711592 0.594207 -0.374906 -0.556440 0.814795 -0.162740 -0.311015 0.793510 0.523078 0.360887 0.294495 0.884891 0.601716 0.058444 0.796569 0.763190 0.067951 0.642591 0.914342 0.187426 0.358956 0.942031 0.331615 -0.051085 0.834167 0.389734 -0.390221 0.731663 0.337226 -0.592408 0.683363 0.031052 -0.729418 0.307050 -0.792801 -0.526486 -0.331258 -0.937844 0.103525 -0.568431 -0.773093 0.281449 -0.743336 -0.636935 0.204365 -0.908472 -0.417603 -0.016949 -0.951838 -0.101508 -0.289309 -0.871387 0.178548 -0.456953 -0.787881 0.386493 -0.479445 -0.731714 0.636205 -0.244619 -0.586855 0.662744 0.465157 0.131438 0.366872 0.920939 0.441877 0.205160 0.873300 0.614854 0.255071 0.746253 0.765857 0.409927 0.495401 0.817598 0.566608 0.102416 0.751599 0.609334 -0.252609 0.694493 0.541759 -0.473472 0.747552 0.243639 -0.617904 0.583965 -0.660259 -0.472275 -0.080595 -0.994491 0.067028 -0.375162 -0.904729 0.201792 -0.568303 -0.817682 0.091802 -0.752065 -0.639523 -0.159404 -0.834996 -0.337108 -0.434901 -0.810692 -0.045992 -0.583664 -0.788778 0.173896 -0.589568 -0.838108 0.421985 -0.345692 -0.802505 0.464765 0.374139 -0.111722 0.363722 0.924784 0.238207 0.292213 0.926212 0.409861 0.384501 0.827147 0.548466 0.572315 0.609623 0.617435 0.747870 0.243853 0.600204 0.791631 -0.114346 0.595519 0.724419 -0.347238 0.741634 0.459399 -0.488806 0.800763 -0.458721 -0.385166 0.172176 -0.983734 0.051205 -0.151298 -0.978966 0.136873 -0.342393 -0.939542 -0.005303 -0.526834 -0.801126 -0.283978 -0.642467 -0.519122 -0.563693 -0.675418 -0.231383 -0.700194 -0.715818 -0.017468 -0.698069 -0.865722 0.198463 -0.459498 -0.940110 0.225695 0.255449 -0.341397 0.286065 0.895330 0.013710 0.308789 0.951032 0.171295 0.442058 0.880479 0.287978 0.657915 0.695856 0.365063 0.856017 0.366012 0.395184 0.918382 0.020108 0.444640 0.869519 -0.215015 0.670020 0.657618 -0.344401 0.938704 -0.213933 -0.270310 0.407680 -0.911657 0.051758 0.083798 -0.992847 0.085045 -0.088489 -0.992436 -0.085090 -0.258372 -0.886040 -0.384937 -0.398091 -0.628178 -0.668518 -0.483952 -0.356361 -0.799248 -0.580639 -0.163937 -0.797486 -0.815754 -0.006267 -0.578366 -0.992801 -0.025367 0.117058 -0.532809 0.144344 0.833834 -0.205888 0.253028 0.945297 -0.074333 0.422640 0.903244 0.013423 0.660563 0.750650 0.088385 0.881811 0.463246 0.155686 0.976998 0.145731 0.253525 0.964127 -0.078644 0.540897 0.820092 -0.186762 0.990123 0.043735 -0.133208 0.611900 -0.788275 0.064808 0.313601 -0.948528 0.044148 0.170454 -0.974321 -0.147120 0.024697 -0.888195 -0.458802 -0.130292 -0.654728 -0.744550 -0.260860 -0.407471 -0.875169 -0.403039 -0.247334 -0.881127 -0.700269 -0.166354 -0.694226 -0.964971 -0.260058 -0.034654 -0.667741 -0.043953 0.743095 -0.396674 0.131769 0.908453 -0.301566 0.330231 0.894430 -0.247703 0.583991 0.773045 -0.184848 0.826120 0.532313 -0.096851 0.961429 0.257436 0.035779 0.997637 0.058653 0.365237 0.930723 -0.018865 0.958385 0.284757 0.020306 0.775907 -0.624664 0.088113 0.525257 -0.850848 0.012776 0.414466 -0.889685 -0.191517 0.295619 -0.811516 -0.504036 0.132916 -0.599501 -0.789260 -0.032510 -0.380358 -0.924268 -0.207201 -0.257347 -0.943843 -0.539197 -0.262019 -0.800383 -0.869235 -0.455212 -0.192908 -0.735221 -0.258023 0.626797 -0.539188 -0.041479 0.841164 -0.489138 0.176229 0.854217 -0.473043 0.439854 0.763386 -0.431055 0.698327 0.571429 -0.340757 0.872716 0.349646 -0.192355 0.962587 0.190854 0.157481 0.975460 0.153877 0.856296 0.481952 0.185688 0.892787 -0.433419 0.122797 0.707691 -0.706478 -0.007822 0.627283 -0.747785 -0.217562 0.532584 -0.667486 -0.520401 0.367373 -0.471056 -0.801962 0.175935 -0.278086 -0.944307 -0.018985 -0.190880 -0.981430 -0.357665 -0.280396 -0.890760 -0.722725 -0.593976 -0.353357 -0.730530 -0.477611 0.488071 -0.619381 -0.250406 0.744086 -0.621738 -0.024413 0.782844 -0.647288 0.243786 0.722210 -0.633316 0.512985 0.579446 -0.556975 0.718471 0.416627 -0.412865 0.856617 0.309434 -0.064789 0.944100 0.323230 0.702358 0.615353 0.357818 0.957802 -0.229564 0.172960 0.851239 -0.524613 -0.013153 0.797137 -0.561257 -0.222627 0.720923 -0.472165 -0.507277 0.555305 -0.282782 -0.782094 0.342820 -0.108541 -0.933110 0.136417 -0.049996 -0.989389 -0.182555 -0.214008 -0.959622 -0.542534 -0.665480 -0.512633 -0.651466 -0.683853 0.328538 -0.626836 -0.477296 0.615846 -0.689217 -0.255087 0.678167 -0.761828 0.013036 0.647648 -0.781699 0.287081 0.553652 -0.730957 0.511429 0.451821 -0.607748 0.683837 0.403744 -0.281556 0.831748 0.478458 0.518114 0.669429 0.532374 0.969131 -0.032747 0.244362 0.947783 -0.318892 0.003903 0.916438 -0.345417 -0.202059 0.852652 -0.243389 -0.462327 0.685100 -0.050219 -0.726716 0.449512 0.117169 -0.885557 0.233575 0.158688 -0.959302 -0.042763 -0.059075 -0.997337 -0.341889 -0.660375 -0.668593 -0.496004 -0.855720 0.147388 -0.553183 -0.700521 0.450841 -0.685213 -0.496472 0.532915 -0.813152 -0.233602 0.533117 -0.871962 0.038884 0.488026 -0.853552 0.267744 0.446947 -0.761933 0.454580 0.461319 -0.473428 0.639362 0.605873 0.324208 0.633328 0.702698 0.929897 0.133273 0.342825 0.992737 -0.108258 0.052477 0.981802 -0.118144 -0.148684 0.925108 -0.000380 -0.379703 0.750644 0.207889 -0.627149 0.480684 0.381620 -0.789499 0.246899 0.418537 -0.873996 0.029545 0.182277 -0.982803 -0.131017 -0.563627 -0.815573 -0.266204 -0.962374 -0.054512 -0.395065 -0.886499 0.240921 -0.608198 -0.719786 0.334668 -0.802472 -0.470496 0.366978 -0.904286 -0.208441 0.372585 -0.920361 0.008666 0.390973 -0.864315 0.186356 0.467152 -0.622376 0.374702 0.687202 0.142621 0.496775 0.856081 0.849746 0.239747 0.469524 0.986691 0.081376 0.140779 0.993726 0.097915 -0.054053 0.939546 0.233172 -0.250765 0.751988 0.463361 -0.468839 0.430093 0.650934 -0.625543 0.159245 0.687127 -0.708871 0.000058 0.483911 -0.875117 0.060777 -0.341669 -0.937853 0.011196 -0.963896 -0.266042 -0.170112 -0.985310 -0.015009 -0.469387 -0.879930 0.073476 -0.739377 -0.658849 0.138711 -0.885549 -0.420453 0.197540 -0.933715 -0.232958 0.271858 -0.910531 -0.089760 0.403579 -0.714821 0.059748 0.696750 -0.002698 0.256771 0.966469 0.747235 0.253957 0.614122 0.938388 0.213987 0.271361 0.958873 0.269713 0.088423 0.903497 0.423134 -0.068198 0.701550 0.671213 -0.239374 0.321490 0.867744 -0.379031 -0.003330 0.890212 -0.455534 -0.134596 0.758365 -0.637782 0.141016 0.023422 -0.989730 0.258919 -0.842854 -0.471761 0.055589 -0.952043 -0.300872 -0.308878 -0.920034 -0.241107 -0.648582 -0.746990 -0.146112 -0.834229 -0.550350 -0.034289 -0.907898 -0.409899 0.087771 -0.909363 -0.324319 0.260531 -0.749771 -0.259712 0.608599 -0.092816 -0.067293 0.993407 0.649442 0.150713 0.745326 0.868416 0.248102 0.429300 0.895055 0.353515 0.271853 0.836150 0.523950 0.162266 0.629992 0.774777 0.053196 0.224547 0.972616 -0.059973 -0.142229 0.978738 -0.147794 -0.275727 0.901984 -0.332263 0.070641 0.443371 -0.893550 0.378661 -0.614741 -0.691888 0.181184 -0.782429 -0.595799 -0.196962 -0.800334 -0.566278 -0.569408 -0.689060 -0.448297 -0.779988 -0.553625 -0.291751 -0.870237 -0.473406 -0.136287 -0.886275 -0.459955 0.054382 -0.747400 -0.516590 0.417765 -0.128320 -0.421733 0.897594 0.581008 -0.065650 0.811246 0.804815 0.157273 0.572309 0.830582 0.311847 0.461394 0.768366 0.494108 0.406780 0.575851 0.731195 0.365718 0.208330 0.932951 0.293599 -0.152137 0.971362 0.182511 -0.283254 0.957679 -0.051167 0.027127 0.788134 -0.614905 0.328045 -0.245566 -0.912186 0.151830 -0.482159 -0.862827 -0.186970 -0.523675 -0.831148 -0.535798 -0.476566 -0.696997 -0.749429 -0.415386 -0.515569 -0.848204 -0.400765 -0.346319 -0.872294 -0.460402 -0.164724 -0.743922 -0.648987 0.159365 -0.138891 -0.729093 0.670173 0.544710 -0.348198 0.762921 0.765260 -0.045375 0.642120 0.788808 0.141777 0.598064 0.727553 0.324635 0.604383 0.563006 0.537008 0.628209 0.276278 0.739126 0.614298 -0.020691 0.855426 0.517512 -0.141476 0.958235 0.248537 0.102454 0.960061 -0.260357 0.180449 0.232063 -0.955816 0.014840 -0.069058 -0.997502 -0.259778 -0.139744 -0.955503 -0.549318 -0.153060 -0.821476 -0.747737 -0.164197 -0.643372 -0.850307 -0.210806 -0.482224 -0.882525 -0.331837 -0.333218 -0.768136 -0.632499 -0.099562 -0.168307 -0.921714 0.349450 0.515340 -0.624678 0.586687 0.741581 -0.306414 0.596798 0.769440 -0.115065 0.628269 0.717354 0.052614 0.694719 0.587813 0.233518 0.774561 0.384342 0.422158 0.821014 0.174725 0.598414 0.781903 0.075706 0.831269 0.550691 0.231129 0.970047 0.074752 0.072267 0.638506 -0.766216 -0.119883 0.357560 -0.926163 -0.343837 0.262597 -0.901565 -0.577663 0.205750 -0.789920 -0.756371 0.141329 -0.638693 -0.862437 0.047761 -0.503906 -0.908195 -0.114934 -0.402458 -0.823615 -0.486955 -0.290747 -0.245192 -0.969461 0.005119 0.458712 -0.832193 0.311508 0.706847 -0.559673 0.432589 0.749576 -0.393936 0.531931 0.715790 -0.257129 0.649253 0.623706 -0.112864 0.773468 0.489055 0.050883 0.870767 0.358010 0.247252 0.900386 0.296614 0.574327 0.762999 0.384799 0.854752 0.348321 0.061436 0.887421 -0.456847 -0.179360 0.696825 -0.694453 -0.380776 0.604030 -0.700113 -0.580629 0.529341 -0.618602 -0.746334 0.437496 -0.501580 -0.859449 0.317161 -0.400945 -0.926422 0.135919 -0.351095 -0.892593 -0.259244 -0.368878 -0.371646 -0.880784 -0.293427 0.352894 -0.935590 -0.011724 0.634681 -0.752188 0.177181 0.700950 -0.635157 0.324414 0.691937 -0.541260 0.477766 0.637190 -0.438385 0.633882 0.558510 -0.307850 0.770256 0.492921 -0.121598 0.861535 0.483859 0.247686 0.839364 0.554190 0.646960 0.523752 0.142572 0.980990 -0.131653 -0.147510 0.910047 -0.387369 -0.345824 0.843120 -0.411771 -0.530465 0.771443 -0.351401 -0.692306 0.672932 -0.260528 -0.817224 0.544410 -0.189113 -0.912278 0.366265 -0.183299 -0.948480 -0.005188 -0.316795 -0.530106 -0.687521 -0.496289 0.194112 -0.923606 -0.330563 0.510475 -0.850483 -0.126861 0.603411 -0.796283 0.042760 0.621363 -0.753323 0.215437 0.601973 -0.696354 0.390794 0.570778 -0.606333 0.553690 0.562949 -0.451696 0.692141 0.621311 -0.090161 0.778360 0.720750 0.385785 0.575925 0.291496 0.946103 0.141135 -0.034612 0.996469 -0.076491 -0.236444 0.966760 -0.097313 -0.415391 0.908730 -0.040748 -0.579231 0.814153 0.040578 -0.719056 0.688124 0.097180 -0.845792 0.528019 0.076362 -0.965158 0.220255 -0.141276 -0.694519 -0.431301 -0.575867 -0.007462 -0.800782 -0.598910 0.332524 -0.838118 -0.432419 0.448797 -0.852979 -0.266474 0.491728 -0.865985 -0.090959 0.504197 -0.858798 0.090833 0.514382 -0.815167 0.266296 0.559609 -0.707150 0.432177 0.697254 -0.394189 0.598708 0.860453 0.115319 0.496308 0.478326 0.819032 0.316844 0.138541 0.973252 0.183268 -0.063058 0.979948 0.189010 -0.236624 0.936067 0.260359 -0.402772 0.845223 0.351244 -0.557215 0.721128 0.411687 -0.714458 0.582712 0.387293 -0.920972 0.366795 0.131427 -0.837425 -0.156419 -0.523691 -0.232925 -0.582874 -0.778462 0.109438 -0.713213 -0.692351 0.239613 -0.797390 -0.553854 0.302107 -0.869435 -0.390914 0.341839 -0.914698 -0.215576 0.388063 -0.920630 -0.042982 0.481448 -0.867293 0.126534 0.702890 -0.630002 0.330217 0.948653 -0.118381 0.293332 0.670390 0.643668 0.369146 0.344933 0.870410 0.351294 0.154668 0.902931 0.400991 -0.005819 0.865155 0.501471 -0.167962 0.767653 0.618465 -0.332488 0.631921 0.700091 -0.513676 0.503792 0.694500 -0.799368 0.390515 0.456628 -0.932654 0.094347 -0.348218 -0.456897 -0.294699 -0.839284 -0.141651 -0.487343 -0.861645 -0.012925 -0.637455 -0.770379 0.061024 -0.770936 -0.633983 0.122944 -0.869763 -0.477910 0.199882 -0.924464 -0.324675 0.334388 -0.925553 -0.177583 0.633998 -0.773253 0.011241 0.962289 -0.271977 -0.005372 0.833202 0.470123 0.291134 0.553029 0.729270 0.402895 0.389351 0.770873 0.504143 0.255603 0.725778 0.638681 0.110890 0.603249 0.789807 -0.054947 0.429091 0.901588 -0.249174 0.282497 0.926341 -0.589072 0.256924 0.766149 -0.955492 0.285426 -0.074616 -0.646141 0.031014 -0.762587 -0.393861 -0.185910 -0.900173 -0.289074 -0.397894 -0.870699 -0.214208 -0.596502 -0.773499 -0.134980 -0.748333 -0.649444 -0.033181 -0.845892 -0.532321 0.131785 -0.891638 -0.433145 0.491694 -0.812902 -0.312134 0.882535 -0.314260 -0.349819 0.931578 0.349497 0.100067 0.728040 0.598697 0.333946 0.607134 0.631148 0.482743 0.515774 0.565562 0.643519 0.407486 0.399279 0.821299 0.251779 0.154992 0.955293 0.053435 -0.047762 0.997428 -0.290972 -0.039780 0.955904 -0.882106 0.392248 0.260826 -0.757988 0.351109 -0.549706 -0.606505 0.148656 -0.781059 -0.558464 -0.121495 -0.820584 -0.496310 -0.392257 -0.774475 -0.403960 -0.594830 -0.694977 -0.284523 -0.723612 -0.628834 -0.104800 -0.794947 -0.597558 0.283737 -0.757872 -0.587472 0.701025 -0.242922 -0.670487 0.933791 0.320635 -0.158832 0.834365 0.525738 0.165632 0.770656 0.534429 0.347096 0.734138 0.441416 0.515939 0.680835 0.225810 0.696759 0.548044 -0.099787 0.830476 0.343227 -0.372526 0.862218 0.049452 -0.405856 0.912598 -0.695046 0.370731 0.616011 -0.758994 0.602343 -0.247208 -0.731251 0.446178 -0.515943 -0.778902 0.130575 -0.613401 -0.746728 -0.219047 -0.628026 -0.644592 -0.467760 -0.604733 -0.516560 -0.612099 -0.598749 -0.342600 -0.685014 -0.642947 0.029712 -0.644947 -0.763649 0.429427 -0.098401 -0.897725 0.820862 0.390005 -0.417230 0.841126 0.538191 -0.053456 0.844756 0.517277 0.137153 0.869227 0.398788 0.292254 0.881551 0.148642 0.448077 0.792402 -0.229357 0.565238 0.588583 -0.547812 0.594535 0.344591 -0.634542 0.691819 -0.417620 0.161239 0.894201 -0.687617 0.724188 0.052301 -0.765740 0.617257 -0.180652 -0.912522 0.286042 -0.292376 -0.921250 -0.133071 -0.365500 -0.811835 -0.418363 -0.407304 -0.684839 -0.563282 -0.462287 -0.537957 -0.618009 -0.573295 -0.233155 -0.535174 -0.811928 0.104836 0.048114 -0.993325 0.599617 0.520594 -0.607817 0.735323 0.626094 -0.259435 0.808744 0.581729 -0.086751 0.893629 0.447443 0.034962 0.971191 0.188255 0.146113 0.951520 -0.192082 0.240239 0.797781 -0.523262 0.299571 0.602017 -0.644410 0.471499 -0.089211 -0.111296 0.989775 -0.643503 0.689126 0.333182 -0.776985 0.611519 0.149465 -0.954673 0.291333 0.061025 -0.985988 -0.158142 -0.053093 -0.871734 -0.462080 -0.162979 -0.753331 -0.598300 -0.273000 -0.648505 -0.627749 -0.430550 -0.454650 -0.486370 -0.746149 -0.220810 0.131545 -0.966405 0.305610 0.649781 -0.695979 0.532957 0.744277 -0.402504 0.668616 0.692537 -0.270823 0.806956 0.556872 -0.196762 0.940277 0.310991 -0.138434 0.996717 -0.033059 -0.073904 0.938710 -0.344421 0.014054 0.830001 -0.490534 0.265473 0.265994 -0.222247 0.938005 -0.589748 0.494450 0.638527 -0.769496 0.446502 0.456630 -0.912122 0.154672 0.379619 -0.932117 -0.271837 0.239294 -0.818419 -0.570648 0.067455 -0.713075 -0.695341 -0.089587 -0.654337 -0.705335 -0.272665 -0.593142 -0.519534 -0.615034 -0.501139 0.125811 -0.856172 -0.013077 0.727026 -0.686486 0.271052 0.842167 -0.466139 0.453005 0.801696 -0.389961 0.632983 0.679066 -0.371755 0.808883 0.459784 -0.366479 0.927426 0.167056 -0.334623 0.965217 -0.100580 -0.241331 0.966718 -0.250063 0.054071 0.553600 -0.168391 0.815580 -0.419665 0.241289 0.875021 -0.674728 0.204766 0.709093 -0.778757 -0.047431 0.625530 -0.777561 -0.419391 0.468519 -0.672252 -0.696820 0.250038 -0.582127 -0.811374 0.052909 -0.564072 -0.813394 -0.142170 -0.632357 -0.615267 -0.470713 -0.710228 0.036630 -0.703018 -0.316732 0.730261 -0.605309 -0.012383 0.887615 -0.460420 0.195331 0.873442 -0.446032 0.402802 0.774814 -0.487252 0.609292 0.587492 -0.532556 0.772729 0.345271 -0.532614 0.883231 0.129064 -0.450828 0.989064 0.001936 -0.147474 0.742546 -0.034407 0.668911 -0.173305 0.064735 0.982738 -0.486149 -0.005361 0.873860 -0.571070 -0.225865 0.789217 -0.555878 -0.546032 0.626776 -0.462984 -0.801189 0.379132 -0.389274 -0.909196 0.147744 -0.403110 -0.913574 -0.053714 -0.580478 -0.738025 -0.344041 -0.838692 -0.113121 -0.532728 -0.579353 0.660267 -0.477909 -0.288094 0.868719 -0.402901 -0.077046 0.889180 -0.451023 0.142779 0.820826 -0.553045 0.370214 0.666375 -0.647214 0.565936 0.469305 -0.677842 0.726943 0.304191 -0.615647 0.918032 0.222189 -0.328405 0.847385 0.136587 0.513111 0.071788 0.006739 0.997397 -0.254719 -0.123522 0.959094 -0.326730 -0.330999 0.885261 -0.299719 -0.618454 0.726418 -0.216284 -0.860161 0.461892 -0.159707 -0.966431 0.201257 -0.198201 -0.980148 -0.005033 -0.456480 -0.855170 -0.245582 -0.883932 -0.300403 -0.358361 -0.785175 0.528392 -0.322958 -0.535309 0.786156 -0.308875 -0.343487 0.841958 -0.416082 -0.127184 0.805320 -0.579037 0.113041 0.682679 -0.721922 0.332463 0.526303 -0.782607 0.526828 0.411180 -0.743897 0.779037 0.393705 -0.487953 0.875815 0.328401 0.353696 0.276102 0.050418 0.959805 -0.025421 -0.143646 0.989303 -0.077938 -0.351465 0.932951 -0.033369 -0.622432 0.781963 0.047834 -0.860557 0.507104 0.086996 -0.971108 0.222217 0.028298 -0.999521 0.012501 -0.280414 -0.944022 -0.173753 -0.845735 -0.500145 -0.185974 -0.923455 0.351525 -0.153820 -0.737326 0.648082 -0.190628 -0.585187 0.731760 -0.349404 -0.388865 0.722811 -0.571251 -0.143907 0.629882 -0.763243 0.092441 0.511915 -0.854048 0.305902 0.446306 -0.840973 0.591338 0.507643 -0.626593 0.828967 0.524790 0.193413 0.421227 0.168880 0.891093 0.174278 -0.079554 0.981478 0.152344 -0.291835 0.944258 0.223741 -0.553992 0.801893 0.311301 -0.795223 0.520301 0.333553 -0.917338 0.217333 0.257561 -0.966233 0.007440 -0.071593 -0.989783 -0.123307 -0.725898 -0.687492 -0.020650 -0.988641 0.149097 0.018955 -0.881837 0.467924 -0.058397 -0.784114 0.564817 -0.257190 -0.622808 0.573481 -0.532194 -0.381514 0.506830 -0.773027 -0.134744 0.426501 -0.894394 0.084641 0.409522 -0.908365 0.372256 0.556253 -0.742973 0.707929 0.705414 0.035041 0.496247 0.335417 0.800771 0.326045 0.050269 0.944017 0.345229 -0.162434 0.924355 0.452337 -0.415188 0.789309 0.554694 -0.662035 0.504008 0.563049 -0.803966 0.191350 0.474022 -0.880416 -0.013061 0.152679 -0.984307 -0.088477 -0.533088 -0.835537 0.133022 -0.980663 -0.058426 0.186780 -0.961716 0.262485 0.078764 -0.923922 0.353783 -0.145621 -0.807758 0.364623 -0.463225 -0.578536 0.318992 -0.750693 -0.328535 0.276017 -0.903260 -0.115871 0.305073 -0.945254 0.141671 0.533688 -0.833730 0.518631 0.846984 -0.116786 0.494123 0.522846 0.694604 0.415474 0.224896 0.881365 0.483045 0.021753 0.875326 0.631924 -0.214864 0.744651 0.756706 -0.465715 0.458810 0.758477 -0.634903 0.147009 0.664563 -0.745916 -0.044339 0.376498 -0.924133 -0.065025 -0.284120 -0.919962 0.270084 -0.904502 -0.251535 0.344393 -0.975329 0.049614 0.215110 -0.992931 0.116999 -0.020000 -0.923842 0.112037 -0.366009 -0.713589 0.079826 -0.696001 -0.468150 0.072962 -0.880632 -0.273881 0.142750 -0.951111 -0.076686 0.438804 -0.895304 0.274773 0.927086 -0.254971 0.413221 0.702990 0.578838 0.432087 0.420456 0.797820 0.550411 0.240558 0.799487 0.742955 0.030363 0.668652 0.896466 -0.219458 0.384950 0.903693 -0.419652 0.085037 0.817916 -0.569007 -0.085114 0.585558 -0.808973 -0.051812 -0.003154 -0.922856 0.385132 -0.768637 -0.412695 0.488754 -0.925089 -0.153634 0.347284 -0.985660 -0.123992 0.114459 -0.956420 -0.160690 -0.243801 -0.769804 -0.188664 -0.609761 -0.537670 -0.162511 -0.827346 -0.371827 -0.060029 -0.926359 -0.258809 0.278660 -0.924860 -0.001075 0.927381 -0.374116 0.260860 0.848821 0.459843 0.372835 0.610946 0.698383 0.537953 0.469028 0.700442 0.770765 0.296665 0.563836 0.957212 0.055610 0.283993 0.984871 -0.173211 0.005277 0.923490 -0.358365 -0.136897 0.765866 -0.640958 -0.051208 0.279815 -0.835858 0.472277 -0.584767 -0.525568 0.617921 -0.816368 -0.330613 0.473539 -0.903465 -0.346270 0.252682 -0.899513 -0.424725 -0.102398 -0.737974 -0.458162 -0.495461 -0.528356 -0.404748 -0.746337 -0.398637 -0.279861 -0.873365 -0.383413 0.069816 -0.920934 -0.280412 0.839624 -0.465189 0.053638 0.936778 0.345790 0.243822 0.769926 0.589715 0.445201 0.678951 0.583799 0.709460 0.554486 0.434985 0.929883 0.331536 0.159381 0.992269 0.083383 -0.091920 0.971076 -0.127358 -0.201971 0.901581 -0.427358 -0.067212 0.533353 -0.662436 0.526035 -0.368477 -0.576546 0.729259 -0.657810 -0.465282 0.592283 -0.754557 -0.527672 0.390135 -0.758200 -0.650020 0.051065 -0.619476 -0.698087 -0.359058 -0.440305 -0.626819 -0.642829 -0.351204 -0.491648 -0.796830 -0.435193 -0.165089 -0.885072 -0.531837 0.666393 -0.522561 -0.185205 0.951668 0.245003 0.059126 0.875400 0.479770 0.281019 0.843810 0.457178 0.563863 0.773503 0.289399 0.815897 0.577947 0.017001 0.923245 0.325427 -0.204247 0.953756 0.105999 -0.281271 0.977886 -0.181827 -0.103337 0.727804 -0.417672 0.543922 -0.140549 -0.555450 0.819586 -0.462841 -0.542332 0.701181 -0.553946 -0.648670 0.521891 -0.548370 -0.809978 0.207911 -0.427267 -0.879881 -0.207971 -0.284565 -0.803981 -0.522147 -0.237802 -0.671819 -0.701506 -0.410237 -0.399340 -0.819898 -0.725572 0.421463 -0.543980 -0.427657 0.889120 0.163017 -0.159092 0.913192 0.375194 0.064172 0.942415 0.328231 0.349883 0.926917 0.135669 0.627809 0.766473 -0.135557 0.784049 0.526988 -0.327948 0.870438 0.319190 -0.374773 0.983883 0.074511 -0.162552 0.842748 -0.127445 0.523005 0.074518 -0.459717 0.884934 -0.250318 -0.550237 0.796605 -0.322807 -0.694868 0.642615 -0.294893 -0.885546 0.358951 -0.183846 -0.981627 -0.051080 -0.079598 -0.917296 -0.390169 -0.073850 -0.802296 -0.592341 -0.314879 -0.607360 -0.729360 -0.840151 0.130532 -0.526410 -0.646531 0.755847 0.103402 -0.385259 0.878879 0.281331 -0.179898 0.962239 0.204288 0.092596 0.995559 -0.016969 0.388031 0.875064 -0.289301 0.590358 0.665330 -0.456961 0.728683 0.489006 -0.479473 0.916838 0.315506 -0.244673 0.867384 0.176833 0.465162 0.251998 -0.297276 0.920936 -0.043279 -0.485267 0.873294 -0.086549 -0.660024 0.746242 -0.027940 -0.868223 0.495387 0.081885 -0.991367 0.102405 0.151892 -0.955571 -0.252614 0.121929 -0.872328 -0.473474 -0.162775 -0.769217 -0.617907 -0.863796 -0.175570 -0.472262 -0.820938 0.567070 0.067030 -0.595919 0.777279 0.201788 -0.423962 0.901016 0.091800 -0.177788 0.971074 -0.159396 0.125577 0.891687 -0.434884 0.365540 0.725081 -0.583642 0.545014 0.596155 -0.589542 0.784527 0.514817 -0.345661 0.803702 0.462599 0.374253 0.370755 -0.085088 0.924825 0.133865 -0.352353 0.926244 0.127988 -0.547161 0.827185 0.221383 -0.761137 0.609639 0.338965 -0.908658 0.243810 0.385477 -0.915598 -0.114402 0.329605 -0.877934 -0.347265 0.027018 -0.871972 -0.488809 -0.797638 -0.464113 -0.385192 -0.938021 0.342776 0.051196 -0.772150 0.620526 0.136862 -0.642458 0.766303 -0.005307 -0.430365 0.856821 -0.283977 -0.128314 0.815948 -0.563706 0.137374 0.700589 -0.700217 0.342839 0.628590 -0.698095 0.604785 0.650446 -0.459517 0.665576 0.701322 0.255257 0.418441 0.152670 0.895321 0.260556 -0.166219 0.951042 0.297181 -0.369333 0.880498 0.425774 -0.578330 0.695881 0.558795 -0.744154 0.366036 0.597749 -0.801430 0.020133 0.530699 -0.819840 -0.214991 0.234492 -0.909073 -0.344382 -0.654597 -0.705998 -0.270314 -0.993367 0.102708 0.051711 -0.901744 0.423829 0.085011 -0.815243 0.572832 -0.085105 -0.638169 0.666758 -0.384934 -0.345006 0.658829 -0.668517 -0.066678 0.597268 -0.799266 0.148302 0.584777 -0.797523 0.402402 0.709557 -0.578448 0.474425 0.872471 0.117117 0.391491 0.389225 0.833810 0.322178 0.051751 0.945263 0.403269 -0.146990 0.903199 0.565386 -0.341931 0.750614 0.719456 -0.517457 0.463273 0.768226 -0.623352 0.145811 0.708162 -0.701666 -0.078563 0.439730 -0.878508 -0.186709 -0.457208 -0.879327 -0.133208 -0.988622 -0.135761 0.064774 -0.978246 0.202705 0.044117 -0.928999 0.339571 -0.147145 -0.781530 0.422730 -0.458813 -0.501867 0.440216 -0.744540 -0.222478 0.429673 -0.875149 -0.012717 0.472752 -0.881104 0.206041 0.689677 -0.694185 0.257219 0.965737 -0.034505 0.295690 0.600221 0.743170 0.312316 0.277636 0.908503 0.436663 0.096058 0.894482 0.629581 -0.077473 0.773062 0.807922 -0.253000 0.532215 0.881095 -0.396871 0.257226 0.846102 -0.529810 0.058414 0.623406 -0.781667 -0.019033 -0.232807 -0.972308 0.020446 -0.928966 -0.359493 0.088245 -0.999485 -0.029381 0.012901 -0.977735 0.085946 -0.191437 -0.850603 0.149761 -0.504030 -0.585590 0.184644 -0.789298 -0.313059 0.218328 -0.924298 -0.119173 0.308098 -0.943861 0.042766 0.597966 -0.800380 0.040451 0.980318 -0.193239 0.144190 0.765813 0.626689 0.233696 0.487765 0.841113 0.397187 0.335569 0.854187 0.617412 0.189817 0.763395 0.820266 0.024226 0.571470 0.926173 -0.141156 0.349683 0.929831 -0.314611 0.190877 0.766123 -0.624005 0.153858 -0.010306 -0.982588 0.185512 -0.821622 -0.556627 0.122899 -0.965642 -0.259763 -0.007715 -0.961246 -0.169451 -0.217468 -0.844385 -0.127569 -0.520326 -0.591684 -0.082710 -0.801916 -0.328859 -0.013420 -0.944284 -0.155895 0.111765 -0.981430 -0.064086 0.449788 -0.890833 -0.153114 0.922950 -0.353157 -0.048266 0.871457 0.488092 0.092987 0.661601 0.744068 0.289882 0.550625 0.782803 0.534857 0.438647 0.722161 0.760904 0.291969 0.579465 0.900643 0.123131 0.416749 0.948226 -0.070757 0.309615 0.849919 -0.415982 0.323413 0.181473 -0.915945 0.357929 -0.677722 -0.714725 0.172803 -0.879924 -0.474927 -0.013321 -0.884592 -0.409727 -0.222758 -0.769330 -0.388245 -0.507343 -0.522557 -0.339487 -0.782102 -0.265462 -0.242570 -0.933107 -0.111580 -0.093065 -0.989388 -0.094135 0.265226 -0.959580 -0.305029 0.802589 -0.512649 -0.266542 0.906091 0.328564 -0.100005 0.781468 0.615878 0.123626 0.724400 0.678205 0.392177 0.653232 0.647677 0.639499 0.533410 0.553638 0.808443 0.377275 0.451755 0.896145 0.184368 0.403648 0.861136 -0.172065 0.478370 0.320683 -0.783429 0.532355 -0.512981 -0.822874 0.244397 -0.750102 -0.661310 0.003948 -0.757393 -0.620920 -0.202026 -0.637128 -0.616709 -0.462319 -0.386041 -0.568190 -0.726727 -0.123274 -0.447854 -0.885568 0.020658 -0.281608 -0.959307 -0.029751 0.066582 -0.997337 -0.400991 0.626268 -0.668577 -0.493089 0.857403 0.147386 -0.330078 0.829335 0.450835 -0.087338 0.841654 0.532909 0.204272 0.821011 0.533117 0.469627 0.735707 0.488043 0.658603 0.605352 0.446980 0.774595 0.432603 0.461364 0.790394 0.090366 0.605898 0.386504 -0.597382 0.702673 -0.349445 -0.871981 0.342836 -0.590072 -0.805644 0.052474 -0.593190 -0.791213 -0.148688 -0.462887 -0.800979 -0.379695 -0.195302 -0.754028 -0.627135 0.090173 -0.607101 -0.789492 0.239081 -0.423081 -0.873981 0.143170 -0.116739 -0.982789 -0.422418 0.395318 -0.815651 -0.700309 0.711756 -0.054507 -0.570167 0.785405 0.240933 -0.319223 0.886613 0.334685 -0.006194 0.930203 0.366993 0.271662 0.887336 0.372606 0.467716 0.792690 0.391006 0.593568 0.655294 0.467190 0.635676 0.351568 0.687253 0.358736 -0.372032 0.856097 -0.217312 -0.855807 0.469436 -0.422899 -0.895187 0.140701 -0.412080 -0.909539 -0.054112 -0.267839 -0.930247 -0.250804 0.025295 -0.882906 -0.468869 0.348646 -0.697932 -0.625569 0.515368 -0.481502 -0.708909 0.418900 -0.242009 -0.875188 -0.326254 0.118261 -0.937855 -0.840214 0.472425 -0.266185 -0.768162 0.640079 -0.015051 -0.527348 0.846468 0.073461 -0.200925 0.969739 0.138690 0.078681 0.977141 0.197496 0.265213 0.925093 0.271782 0.377679 0.833408 0.403473 0.409307 0.589196 0.696647 0.223787 -0.125989 0.966460 -0.153821 -0.774039 0.614168 -0.284048 -0.919589 0.271429 -0.245997 -0.965222 0.088497 -0.085366 -0.994016 -0.068151 0.230523 -0.943166 -0.239368 0.590684 -0.712329 -0.379051 0.772461 -0.442386 -0.455629 0.723810 -0.262793 -0.637996 -0.051107 -0.134360 -0.989614 -0.859473 0.197015 -0.471689 -0.852381 0.427723 -0.300832 -0.642383 0.727461 -0.241133 -0.322633 0.935173 -0.146151 -0.059540 0.997635 -0.034354 0.098898 0.991227 0.087679 0.173733 0.949734 0.260427 0.149929 0.779261 0.608502 -0.011753 0.114196 0.993389 -0.194102 -0.637708 0.745421 -0.219270 -0.876087 0.429408 -0.141329 -0.951878 0.271945 0.035678 -0.986092 0.162328 0.355956 -0.932985 0.053235 0.730102 -0.680703 -0.059944 0.918842 -0.365919 -0.147756 0.919227 -0.211762 -0.331930 0.349232 -0.282457 -0.893451 -0.722174 -0.020929 -0.691395 -0.768436 0.233949 -0.595629 -0.594770 0.570620 -0.566252 -0.312054 0.837655 -0.448282 -0.089484 0.952308 -0.291723 0.025047 0.990357 -0.136254 0.044662 0.997519 0.054423 -0.073839 0.905529 0.417810 -0.301156 0.321889 0.897604 -0.347249 -0.470391 0.811265 -0.266042 -0.775665 0.572333 -0.145080 -0.875250 0.461400 0.043799 -0.912478 0.406775 0.345290 -0.864305 0.365721 0.703814 -0.646863 0.293623 0.917370 -0.353689 0.182582 0.971094 -0.233189 -0.050986 0.669267 -0.417415 -0.614691 -0.376599 -0.161190 -0.912245 -0.493357 0.109707 -0.862881 -0.359984 0.423807 -0.831144 -0.144831 0.702310 -0.696982 0.014965 0.856740 -0.515532 0.077029 0.934977 -0.346242 0.037435 0.985647 -0.164617 -0.190080 0.968732 0.159463 -0.562033 0.484744 0.670181 -0.573960 -0.297704 0.762851 -0.421963 -0.640103 0.642040 -0.271636 -0.754060 0.598003 -0.082625 -0.792422 0.604352 0.183569 -0.756085 0.628202 0.501915 -0.608857 0.614308 0.751060 -0.409929 0.517559 0.900500 -0.356802 0.248580 0.780033 -0.568905 -0.260570 0.111056 -0.272168 -0.955820 -0.066984 0.021865 -0.997514 0.009004 0.294955 -0.955469 0.142138 0.552272 -0.821457 0.231674 0.729651 -0.643379 0.242614 0.841780 -0.482229 0.153938 0.930199 -0.333216 -0.163617 0.981487 -0.099559 -0.714028 0.606670 0.349450 -0.798685 -0.133957 0.586650 -0.636202 -0.489029 0.596739 -0.484416 -0.608832 0.628223 -0.313132 -0.647565 0.694699 -0.091654 -0.625822 0.774562 0.173459 -0.543930 0.821007 0.430878 -0.450580 0.781870 0.682017 -0.481333 0.550609 0.724531 -0.685178 0.074738 0.516840 -0.381890 -0.766183 0.369588 -0.074991 -0.926165 0.399334 0.166468 -0.901566 0.467029 0.397400 -0.789910 0.500599 0.584368 -0.638682 0.472604 0.722995 -0.503908 0.354595 0.843963 -0.402478 -0.009872 0.956739 -0.290781 -0.716977 0.697078 0.005124 -0.950041 0.018841 0.311555 -0.838098 -0.332299 0.432631 -0.715935 -0.452168 0.531960 -0.580569 -0.491319 0.649266 -0.409588 -0.483718 0.773469 -0.200438 -0.448992 0.870765 0.035176 -0.433687 0.900376 0.349145 -0.544038 0.762968 0.547833 -0.760609 0.348358 0.737826 -0.496900 -0.456841 0.693138 -0.193073 -0.694465 0.713474 0.027745 -0.700132 0.748728 0.238165 -0.618614 0.752054 0.427599 -0.501572 0.704403 0.585732 -0.400917 0.580929 0.734355 -0.351061 0.221785 0.902639 -0.368854 -0.576964 0.762242 -0.293426 -0.986690 0.162187 -0.011729 -0.968756 -0.173540 0.177186 -0.900538 -0.289445 0.324426 -0.814714 -0.328594 0.477774 -0.698254 -0.332634 0.633874 -0.545881 -0.329785 0.770231 -0.351798 -0.366123 0.861506 -0.027457 -0.542903 0.839347 0.283220 -0.803446 0.523699 0.778295 -0.613934 -0.131691 0.861884 -0.327237 -0.387392 0.903075 -0.122043 -0.411778 0.933320 0.073678 -0.351404 0.928931 0.263072 -0.260537 0.880096 0.435500 -0.189130 0.773355 0.606889 -0.183324 0.469768 0.823984 -0.316811 -0.330306 0.802885 -0.496259 -0.896903 0.293756 -0.330564 -0.991776 -0.016796 -0.126875 -0.991311 -0.124401 0.042744 -0.963083 -0.161444 0.215424 -0.904049 -0.173147 0.390790 -0.810485 -0.191147 0.553695 -0.672645 -0.261686 0.692148 -0.388729 -0.493001 0.778357 -0.026294 -0.817068 0.575942 0.673572 -0.725532 0.141083 0.880244 -0.468308 -0.076540 0.955448 -0.278647 -0.097337 0.994677 -0.094639 -0.040749 0.994693 0.094550 0.040577 0.955464 0.278655 0.097157 0.880183 0.468459 0.076311 0.673326 0.725711 -0.141335 -0.026281 0.817108 -0.575885 -0.689784 0.406873 -0.598876 -0.892108 0.131102 -0.432384 -0.963104 0.037827 -0.266457 -0.995829 0.007148 -0.090962 -0.995840 -0.007238 0.090827 -0.963145 -0.037857 0.266304 -0.892208 -0.131012 0.432204 -0.690004 -0.406690 0.598747 -0.330410 -0.802797 0.496333 0.470117 -0.823764 0.316866 0.773570 -0.606626 0.183288 0.880175 -0.435388 0.189021 0.928966 -0.263126 0.260361 0.933371 -0.073796 0.351244 0.903115 0.122033 0.411692 0.861847 0.327443 0.387299 0.778098 0.614239 0.131427 0.283230 0.803421 -0.523733 -0.388307 0.493115 -0.778495 -0.672370 0.261792 -0.692376 -0.810361 0.191161 -0.553871 -0.904003 0.173081 -0.390925 -0.963066 0.161320 -0.215591 -0.991316 0.124269 -0.043007 -0.991825 0.016739 0.126499 -0.897067 -0.293676 0.330191 -0.576830 -0.762385 0.293321 0.222230 -0.902400 0.369171 0.581320 -0.733916 0.351332 0.704616 -0.585404 0.401022 0.752145 -0.427537 0.501487 0.748782 -0.238373 0.618469 0.713498 -0.028024 0.700096 0.693118 0.192957 0.694517 0.737857 0.497011 0.456669 0.548046 0.760543 -0.348166 -0.026742 0.543011 -0.839300 -0.351197 0.366312 -0.861671 -0.545571 0.329900 -0.770401 -0.698155 0.332614 -0.633994 -0.814707 0.328411 -0.477911 -0.900549 0.289131 -0.324675 -0.968747 0.173182 -0.177589 -0.986653 -0.162450 0.011230 -0.716689 -0.697372 -0.005381 -0.009476 -0.956642 0.291112 0.355039 -0.843586 0.402877 0.472910 -0.722636 0.504136 0.500730 -0.584253 0.638685 0.466972 -0.397659 0.789813 0.399070 -0.166966 0.901591 0.369237 0.074524 0.926342 0.517038 0.381665 0.766162 0.724933 0.684765 -0.074622 0.349909 0.544077 -0.762590 0.035914 0.434057 -0.900169 -0.200051 0.449298 -0.870695 -0.409477 0.483768 -0.773497 -0.580581 0.491073 -0.649441 -0.715972 0.451694 -0.532312 -0.838076 0.331701 -0.433132 -0.949845 -0.019360 -0.312122 -0.713449 -0.607130 -0.349835 -0.163169 -0.981510 0.100068 0.154425 -0.929853 0.333957 0.243001 -0.841373 0.482745 0.231893 -0.729463 0.643513 0.142009 -0.552534 0.821304 0.008228 -0.295490 0.955310 -0.068265 -0.022285 0.997418 0.110819 0.271959 0.955907 0.780867 0.567694 0.260710 0.683102 0.480794 -0.549735 0.432015 0.450891 -0.781064 0.174008 0.544399 -0.820579 -0.091552 0.625947 -0.774473 -0.313133 0.647246 -0.694996 -0.484362 0.608200 -0.628877 -0.635999 0.488223 -0.597615 -0.798172 0.133211 -0.587517 -0.560806 -0.485745 -0.670484 -0.189148 -0.969028 -0.158770 0.038170 -0.985439 0.165690 0.077530 -0.934605 0.347136 0.015221 -0.856476 0.515962 -0.144838 -0.702520 0.696769 -0.360367 -0.424763 0.830489 -0.494115 -0.111074 0.862272 -0.375924 0.160041 0.912726 0.668084 0.416922 0.616311 0.901147 0.356196 -0.247102 0.752045 0.410224 -0.515892 0.502550 0.609269 -0.613379 0.183667 0.756215 -0.628017 -0.082820 0.792110 -0.604733 -0.271848 0.753386 -0.598756 -0.421969 0.639180 -0.642956 -0.573394 0.296698 -0.763668 -0.299928 -0.322680 -0.897731 -0.072524 -0.905876 -0.417288 0.045683 -0.997520 -0.053540 0.025697 -0.990227 0.137076 -0.089231 -0.952182 0.292211 -0.312041 -0.837775 0.448067 -0.594647 -0.571709 0.565282 -0.768369 -0.236262 0.594802 -0.721280 0.018393 0.692399 0.348283 0.281267 0.894197 0.970798 0.234069 0.052559 0.917268 0.354947 -0.180645 0.703904 0.647331 -0.292374 0.345410 0.864362 -0.365474 0.043549 0.912280 -0.407245 -0.145548 0.874758 -0.462185 -0.266428 0.774920 -0.573163 -0.347066 0.469552 -0.811829 -0.010995 -0.114528 -0.993359 0.150853 -0.779456 -0.608023 0.174425 -0.949822 -0.259644 0.099351 -0.991249 -0.086921 -0.059315 -0.997631 0.034844 -0.322527 -0.935226 0.146042 -0.642154 -0.727977 0.240182 -0.852181 -0.429066 0.299481 -0.859362 -0.198854 0.471120 -0.050138 0.132114 0.989966 0.918526 0.212749 0.333240 0.918133 0.367041 0.149374 0.729657 0.681084 0.061036 0.356044 0.932962 -0.053047 0.035784 0.985998 -0.162871 -0.141323 0.951622 -0.272843 -0.219223 0.875618 -0.430388 -0.193801 0.637105 -0.746015 0.224499 0.125268 -0.966389 0.409759 -0.589671 -0.695978 0.377857 -0.833788 -0.402520 0.265263 -0.925361 -0.270820 0.078700 -0.977290 -0.196752 -0.200805 -0.969802 -0.138425 -0.527035 -0.846625 -0.073899 -0.767812 -0.640523 0.013996 -0.840069 -0.473200 0.265263 -0.326482 -0.118823 0.937705 0.723807 0.263000 0.637914 0.771816 0.442683 0.456434 0.590214 0.712449 0.379556 0.230620 0.943172 0.239252 -0.084947 0.994101 0.067426 -0.245484 0.965249 -0.089626 -0.283433 0.919392 -0.272734 -0.153098 0.773422 -0.615126 0.359639 0.371022 -0.856156 0.636300 -0.352211 -0.686346 0.593932 -0.655816 -0.465994 0.467871 -0.793164 -0.389856 0.271622 -0.887729 -0.371698 -0.006286 -0.930413 -0.366459 -0.319057 -0.886697 -0.334620 -0.569675 -0.785640 -0.241331 -0.699852 -0.712236 0.054106 -0.422614 -0.395245 0.815585 0.418679 0.242845 0.875063 0.514605 0.481993 0.709129 0.348281 0.698139 0.625541 0.025593 0.883084 0.468517 -0.267387 0.930601 0.249973 -0.411713 0.909783 0.052783 -0.422512 0.895115 -0.142313 -0.216751 0.855187 -0.470823 0.386650 0.596854 -0.703041 0.790806 -0.090737 -0.605304 0.774944 -0.433012 -0.460394 0.658817 -0.605831 -0.446014 0.469658 -0.736214 -0.487248 0.204165 -0.821390 -0.532574 -0.087335 -0.841819 -0.532647 -0.329818 -0.829419 -0.450871 -0.492822 -0.857533 -0.147529 -0.401034 -0.625887 0.668907 0.142630 0.117711 0.982752 0.238361 0.423699 0.873878 0.089902 0.607475 0.789235 -0.194924 0.754404 0.626801 -0.462351 0.801542 0.379159 -0.592769 0.791700 0.147768 -0.589662 0.805863 -0.053690 -0.348988 0.871703 -0.344007 0.321323 0.782877 -0.532781 0.861377 0.171553 -0.478121 0.896271 -0.184948 -0.403103 0.808477 -0.377938 -0.451140 0.639428 -0.534095 -0.553060 0.392047 -0.653811 -0.647171 0.123561 -0.724785 -0.677805 -0.099960 -0.781667 -0.615633 -0.266574 -0.906137 -0.328411 -0.305442 -0.802156 0.513080 -0.030081 -0.065543 0.997396 0.020342 0.282354 0.959095 -0.123359 0.448468 0.885245 -0.385775 0.568803 0.726389 -0.636716 0.617423 0.461932 -0.756978 0.621631 0.201395 -0.749587 0.661888 -0.004857 -0.512201 0.823048 -0.245444 0.182338 0.915671 -0.358188 0.850330 0.415641 -0.322772 0.948549 0.070411 -0.308701 0.900945 -0.123591 -0.415961 0.761014 -0.292590 -0.579007 0.534606 -0.439306 -0.721946 0.289425 -0.551123 -0.782622 0.092551 -0.661858 -0.743894 -0.048647 -0.871542 -0.487901 -0.153470 -0.922602 0.353910 -0.094333 -0.264160 0.959854 -0.111633 0.093932 0.989300 -0.265372 0.243304 0.932942 -0.522368 0.340183 0.781925 -0.769227 0.388916 0.506985 -0.884528 0.410268 0.222016 -0.879742 0.475293 0.012253 -0.677237 0.714898 -0.173985 -0.010804 0.982443 -0.186250 0.766088 0.624073 -0.153758 0.929915 0.314580 -0.190519 0.926338 0.140965 -0.349323 0.820456 -0.024608 -0.571180 0.617534 -0.190276 -0.763182 0.397229 -0.335954 -0.854016 0.233693 -0.488011 -0.840971 0.144047 -0.765863 -0.626661 0.039868 -0.980385 0.193020 -0.064419 -0.449426 0.890992 -0.156081 -0.111274 0.981456 -0.328902 0.013906 0.944262 -0.591585 0.083188 0.801939 -0.844305 0.127981 0.520356 -0.961231 0.169723 0.217323 -0.965601 0.259923 0.007386 -0.821515 0.556682 -0.123363 -0.232248 0.972437 -0.020668 0.623414 0.781669 0.018674 0.846132 0.529724 -0.058758 0.881153 0.396560 -0.257507 0.808003 0.252507 -0.532327 0.629772 0.076906 -0.772964 0.436964 -0.096619 -0.894275 0.312605 -0.278137 -0.908250 0.295800 -0.600603 -0.742818 0.256978 -0.965769 0.035402 0.042100 -0.597394 0.800842 -0.119742 -0.307422 0.944009 -0.313484 -0.217668 0.924310 -0.585837 -0.184038 0.789256 -0.850696 -0.149245 0.504026 -0.977769 -0.085495 0.191464 -0.999470 0.029882 -0.012898 -0.928683 0.360203 -0.088328 -0.456741 0.879571 0.133201 0.439848 0.878409 0.186899 0.708277 0.701501 0.078993 0.768469 0.623161 -0.145345 0.719730 0.517193 -0.463141 0.565361 0.341386 -0.750881 0.402895 0.146246 -0.903486 0.321612 -0.052434 -0.945419 0.390947 -0.389706 -0.833840 0.474279 -0.872656 -0.116325 0.205843 -0.688973 0.694942 -0.012807 -0.471924 0.881546 -0.222582 -0.428998 0.875453 -0.502077 -0.439723 0.744690 -0.781774 -0.422363 0.458737 -0.929143 -0.339266 0.146944 -0.978298 -0.202396 -0.044364 -0.988536 0.136263 -0.065030 -0.654856 0.705860 0.270046 0.234419 0.909029 0.344550 0.530649 0.819770 0.215380 0.597800 0.801404 -0.019657 0.558970 0.744155 -0.365768 0.425810 0.578178 -0.695986 0.296959 0.369010 -0.880708 0.260195 0.165881 -0.951200 0.418014 -0.152852 -0.895489 0.665289 -0.701411 -0.255760 0.402588 -0.709306 0.578626 0.148486 -0.584412 0.797756 -0.066542 -0.596997 0.799479 -0.344958 -0.658696 0.668673 -0.638167 -0.666759 0.384936 -0.815191 -0.572924 0.084978 -0.901651 -0.423988 -0.085203 -0.993332 -0.102921 -0.051946 -0.797723 0.464044 0.385099 0.026919 0.872022 0.488726 0.329464 0.878018 0.347185 0.385368 0.915652 0.114339 0.338919 0.908667 -0.243840 0.221416 0.761102 -0.609671 0.128075 0.547059 -0.827238 0.133970 0.352195 -0.926289 0.370847 0.084928 -0.924802 0.803820 -0.462625 -0.373967 0.604748 -0.650383 0.459654 0.342759 -0.628507 0.698209 0.137291 -0.700528 0.700294 -0.128372 -0.815925 0.563726 -0.430348 -0.856831 0.283975 -0.642369 -0.766377 0.005336 -0.772050 -0.620664 -0.136805 -0.937979 -0.342903 -0.051120 -0.863631 0.175648 0.472535 -0.162702 0.769197 0.617951 0.121890 0.872305 0.473525 0.151818 0.955573 0.252648 0.081864 0.991369 -0.102404 -0.027829 0.868242 -0.495360 -0.086345 0.660110 -0.746190 -0.043015 0.485385 -0.873242 0.252223 0.297334 -0.920856 0.867192 -0.176899 -0.465495 0.784528 -0.514888 0.345553 0.544957 -0.596204 0.589544 0.365469 -0.725083 0.583684 0.125550 -0.891669 0.434929 -0.177761 -0.971087 0.159343 -0.423910 -0.901021 -0.091985 -0.595838 -0.777270 -0.202058 -0.820877 -0.567125 -0.067304 -0.840341 -0.130701 0.526065 -0.314771 0.607276 0.729476 -0.073851 0.802177 0.592501 -0.079637 0.917245 0.390281 -0.183861 0.981624 0.051082 -0.294804 0.885555 -0.359004 -0.322575 0.694926 -0.642669 -0.249980 0.550319 -0.796655 0.074897 0.459742 -0.884888 0.843072 0.127409 -0.522490 0.916764 -0.315681 0.244722 0.728520 -0.489185 0.479538 0.590195 -0.665432 0.457024 0.387945 -0.875091 0.289333 0.092592 -0.995560 0.016924 -0.179847 -0.962211 -0.204463 -0.385156 -0.878835 -0.281608 -0.646460 -0.755866 -0.103710 -0.725873 -0.421785 0.543328 -0.410999 0.399315 0.819528 -0.238475 0.671933 0.701167 -0.284927 0.804025 0.521881 -0.427314 0.879868 0.207931 -0.548389 0.809945 -0.207988 -0.553981 0.648338 -0.522267 -0.462878 0.541666 -0.701671 -0.140725 0.554757 -0.820025 0.728127 0.417741 -0.543436 0.983791 -0.074161 0.163266 0.870332 -0.318773 0.375374 0.784050 -0.526754 0.328324 0.627798 -0.766461 0.135677 0.349937 -0.926917 -0.135534 0.064531 -0.942513 -0.327880 -0.158556 -0.913498 -0.374676 -0.427223 -0.889429 -0.162467 -0.531420 -0.665792 0.523750 -0.435394 0.165388 0.884917 -0.351410 0.491932 0.796564 -0.440411 0.626979 0.642600 -0.619510 0.698110 0.358957 -0.758221 0.649992 -0.051106 -0.754617 0.527531 -0.390209 -0.657923 0.465040 -0.592348 -0.368634 0.576318 -0.729360 0.532714 0.662188 -0.526994 0.977819 0.182084 0.103513 0.953735 -0.105675 0.281465 0.923275 -0.325247 0.204395 0.815896 -0.577951 -0.016933 0.563794 -0.773567 -0.289362 0.280962 -0.843916 -0.457018 0.059073 -0.875555 -0.479493 -0.185245 -0.951766 -0.244592 -0.280570 -0.839821 0.464738 -0.383040 -0.069597 0.921106 -0.398171 0.280037 0.873521 -0.528027 0.404871 0.746503 -0.737861 0.458245 0.495553 -0.899527 0.424695 0.102398 -0.903500 0.346226 -0.252617 -0.816411 0.330682 -0.473416 -0.584716 0.525778 -0.617790 0.279984 0.835992 -0.471939 0.901569 0.427454 0.066755 0.971158 0.127397 0.201548 0.992298 -0.083346 0.091643 0.929891 -0.331471 -0.159469 0.709460 -0.554483 -0.434989 0.445089 -0.678969 -0.583863 0.243629 -0.769870 -0.589869 0.053486 -0.936669 -0.346108 -0.001282 -0.927584 0.373612 -0.259444 -0.278993 0.924582 -0.372563 0.059865 0.926074 -0.538206 0.162465 0.827006 -0.769926 0.188714 0.609591 -0.956349 0.160780 0.244020 -0.985688 0.123997 -0.114207 -0.925124 0.153511 -0.347246 -0.768668 0.412470 -0.488896 -0.003196 0.922860 -0.385123 0.765754 0.641079 0.051366 0.923397 0.358550 0.137041 0.984847 0.173345 -0.005216 0.957219 -0.055603 -0.283972 0.770888 -0.296691 -0.563654 0.538358 -0.469048 -0.700118 0.373455 -0.611016 -0.697991 0.261400 -0.848856 -0.459471 0.274654 -0.926821 0.256063 -0.077340 -0.438760 0.895270 -0.274668 -0.142621 0.950903 -0.468817 -0.072733 0.880296 -0.713913 -0.079570 0.695699 -0.923862 -0.111795 0.366035 -0.992943 -0.116857 0.020232 -0.975368 -0.049630 -0.214926 -0.904528 0.251462 -0.344378 -0.284035 0.919895 -0.270403 0.585830 0.808772 0.051875 0.817986 0.568903 0.085139 0.903767 0.419490 -0.085050 0.896545 0.219140 -0.384948 0.743089 -0.030784 -0.668484 0.550711 -0.241049 -0.799133 0.432490 -0.421035 -0.797297 0.413486 -0.703509 -0.578017 0.518271 -0.847173 0.117015 0.141446 -0.533500 0.833889 -0.116109 -0.304664 0.945356 -0.328807 -0.275545 0.903306 -0.578795 -0.318532 0.750689 -0.807907 -0.364272 0.463241 -0.923968 -0.353616 0.145737 -0.961732 -0.262477 -0.078595 -0.980676 0.058398 -0.186719 -0.532910 0.835606 -0.133302 0.376780 0.924044 0.064649 0.664701 0.745813 0.044006 0.758596 0.634716 -0.147198 0.756896 0.465417 -0.458797 0.632207 0.214443 -0.744532 0.483306 -0.022298 -0.875167 0.415651 -0.225518 -0.881122 0.494085 -0.523400 -0.694214 0.707732 -0.705642 -0.034427 0.371975 -0.556121 0.743212 0.084307 -0.409209 0.908538 -0.135132 -0.426117 0.894518 -0.381905 -0.506447 0.773084 -0.623105 -0.573148 0.532204 -0.784277 -0.564585 0.257203 -0.881893 -0.467819 0.058401 -0.988649 -0.149034 -0.019038 -0.725580 0.687834 0.020442 0.153237 0.984246 0.088190 0.474354 0.880240 0.012850 0.563341 0.803732 -0.191470 0.555034 0.661723 -0.504043 0.452728 0.414763 -0.789310 0.345611 0.161878 -0.924310 0.326390 -0.050938 -0.943862 0.496445 -0.336121 -0.800353 0.828781 -0.525165 -0.193195 0.591178 -0.507639 0.626746 0.305664 -0.446104 0.841166 0.092120 -0.511633 0.854252 -0.144270 -0.629567 0.763434 -0.389186 -0.722520 0.571401 -0.585393 -0.731549 0.349501 -0.737411 -0.647977 0.190658 -0.923482 -0.351508 0.153697 -0.845734 0.500302 0.185560 -0.071127 0.989854 0.123002 0.257932 0.966133 -0.007610 0.333912 0.917193 -0.217396 0.311717 0.795050 -0.520314 0.224178 0.553736 -0.801948 0.152743 0.291440 -0.944316 0.174652 0.079042 -0.981452 0.421493 -0.169466 -0.890856 0.875772 -0.328858 -0.353377 0.778896 -0.393917 0.488006 0.526547 -0.411320 0.744019 0.332004 -0.526351 0.782770 0.112546 -0.682516 0.722154 -0.127504 -0.804952 0.579479 -0.343594 -0.841573 0.416771 -0.535304 -0.785856 0.309645 -0.785140 -0.528158 0.323426 -0.884113 0.300478 0.357852 -0.280276 0.944222 0.172885 0.028546 0.999505 -0.013258 0.087371 0.970963 -0.222705 0.048363 0.860417 -0.507290 -0.032802 0.622341 -0.782058 -0.077437 0.351234 -0.933080 -0.024924 0.143219 -0.989377 0.276611 -0.051008 -0.959627 0.847610 -0.137098 -0.512603 0.917963 -0.222257 0.328551 0.726765 -0.304215 0.615846 0.565516 -0.469348 0.678163 0.369618 -0.666294 0.647637 0.142223 -0.820519 0.553643 -0.077444 -0.888739 0.451825 -0.288364 -0.868230 0.403760 -0.579559 -0.659658 0.478500 -0.838720 0.114205 0.532453 -0.456168 0.855701 0.244309 -0.197716 0.980252 0.003850 -0.159085 0.966358 -0.202100 -0.215565 0.860094 -0.462354 -0.299074 0.618402 -0.726729 -0.326224 0.330697 -0.885560 -0.254199 0.122948 -0.959305 0.072581 -0.007482 -0.997335</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="2160" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="6897">0 0 0 0 0.055556 0 0 0.111111 0 0 0.166667 0 0 0.222222 0 0 0.277778 0 0 0.333333 0 0 0.388889 0 0 0.444444 0 0 0.500000 0 0 0.555556 0 0 0.611111 0 0 0.666667 0 0 0.722222 0 0 0.777778 0 0 0.833333 0 0 0.888889 0 0 0.944444 0 0 1.000000 0 0.008333 0 0 0.008333 0.055556 0 0.008333 0.111111 0 0.008333 0.166667 0 0.008333 0.222222 0 0.008333 0.277778 0 0.008333 0.333333 0 0.008333 0.388889 0 0.008333 0.444444 0 0.008333 0.500000 0 0.008333 0.555556 0 0.008333 0.611111 0 0.008333 0.666667 0 0.008333 0.722222 0 0.008333 0.777778 0 0.008333 0.833333 0 0.008333 0.888889 0 0.008333 0.944444 0 0.008333 1.000000 0 0.016667 0 0 0.016667 0.055556 0 0.016667 0.111111 0 0.016667 0.166667 0 0.016667 0.222222 0 0.016667 0.277778 0 0.016667 0.333333 0 0.016667 0.388889 0 0.016667 0.444444 0 0.016667 0.500000 0 0.016667 0.555556 0 0.016667 0.611111 0 0.016667 0.666667 0 0.016667 0.722222 0 0.016667 0.777778 0 0.016667 0.833333 0 0.016667 0.888889 0 0.016667 0.944444 0 0.016667 1.000000 0 0.025000 0 0 0.025000 0.055556 0 0.025000 0.111111 0 0.025000 0.166667 0 0.025000 0.222222 0 0.025000 0.277778 0 0.025000 0.333333 0 0.025000 0.388889 0 0.025000 0.444444 0 0.025000 0.500000 0 0.025000 0.555556 0 0.025000 0.611111 0 0.025000 0.666667 0 0.025000 0.722222 0 0.025000 0.777778 0 0.025000 0.833333 0 0.025000 0.888889 0 0.025000 0.944444 0 0.025000 1.000000 0 0.033333 0 0 0.033333 0.055556 0 0.033333 0.111111 0 0.033333 0.166667 0 0.033333 0.222222 0 0.033333 0.277778 0 0.033333 0.333333 0 0.033333 0.388889 0 0.033333 0.444444 0 0.033333 0.500000 0 0.033333 0.555556 0 0.033333 0.611111 0 0.033333 0.666667 0 0.033333 0.722222 0 0.033333 0.777778 0 0.033333 0.833333 0 0.033333 0.888889 0 0.033333 0.944444 0 0.033333 1.000000 0 0.041667 0 0 0.041667 0.055556 0 0.041667 0.111111 0 0.041667 0.166667 0 0.041667 0.222222 0 0.041667 0.277778 0 0.041667 0.333333 0 0.041667 0.388889 0 0.041667 0.444444 0 0.041667 0.500000 0 0.041667 0.555556 0 0.041667 0.611111 0 0.041667 0.666667 0 0.041667 0.722222 0 0.041667 0.777778 0 0.041667 0.833333 0 0.041667 0.888889 0 0.041667 0.944444 0 0.041667 1.000000 0 0.050000 0 0 0.050000 0.055556 0 0.050000 0.111111 0 0.050000 0.166667 0 0.050000 0.222222 0 0.050000 0.277778 0 0.050000 0.333333 0 0.050000 0.388889 0 0.050000 0.444444 0 0.050000 0.500000 0 0.050000 0.555556 0 0.050000 0.611111 0 0.050000 0.666667 0 0.050000 0.722222 0 0.050000 0.777778 0 0.050000 0.833333 0 0.050000 0.888889 0 0.050000 0.944444 0 0.050000 1.000000 0 0.058333 0 0 0.058333 0.055556 0 0.058333 0.111111 0 0.058333 0.166667 0 0.058333 0.222222 0 0.058333 0.277778 0 0.058333 0.333333 0 0.058333 0.388889 0 0.058333 0.444444 0 0.058333 0.500000 0 0.058333 0.555556 0 0.058333 0.611111 0 0.058333 0.666667 0 0.058333 0.722222 0 0.058333 0.777778 0 0.058333 0.833333 0 0.058333 0.888889 0 0.058333 0.944444 0 0.058333 1.000000 0 0.066667 0 0 0.066667 0.055556 0 0.066667 0.111111 0 0.066667 0.166667 0 0.066667 0.222222 0 0.066667 0.277778 0 0.066667 0.333333 0 0.066667 0.388889 0 0.066667 0.444444 0 0.066667 0.500000 0 0.066667 0.555556 0 0.066667 0.611111 0 0.066667 0.666667 0 0.066667 0.722222 0 0.066667 0.777778 0 0.066667 0.833333 0 0.066667 0.888889 0 0.066667 0.944444 0 0.066667 1.000000 0 0.075000 0 0 0.075000 0.055556 0 0.075000 0.111111 0 0.075000 0.166667 0 0.075000 0.222222 0 0.075000 0.277778 0 0.075000 0.333333 0 0.075000 0.388889 0 0.075000 0.444444 0 0.075000 0.500000 0 0.075000 0.555556 0 0.075000 0.611111 0 0.075000 0.666667 0 0.075000 0.722222 0 0.075000 0.777778 0 0.075000 0.833333 0 0.075000 0.888889 0 0.075000 0.944444 0 0.075000 1.000000 0 0.083333 0 0 0.083333 0.055556 0 0.083333 0.111111 0 0.083333 0.166667 0 0.083333 0.222222 0 0.083333 0.277778 0 0.083333 0.333333 0 0.083333 0.388889 0 0.083333 0.444444 0 0.083333 0.500000 0 0.083333 0.555556 0 0.083333 0.611111 0 0.083333 0.666667 0 0.083333 0.722222 0 0.083333 0.777778 0 0.083333 0.833333 0 0.083333 0.888889 0 0.083333 0.944444 0 0.083333 1.000000 0 0.091667 0 0 0.091667 0.055556 0 0.091667 0.111111 0 0.091667 0.166667 0 0.091667 0.222222 0 0.091667 0.277778 0 0.091667 0.333333 0 0.091667 0.388889 0 0.091667 0.444444 0 0.091667 0.500000 0 0.091667 0.555556 0 0.091667 0.611111 0 0.091667 0.666667 0 0.091667 0.722222 0 0.091667 0.777778 0 0.091667 0.833333 0 0.091667 0.888889 0 0.091667 0.944444 0 0.091667 1.000000 0 0.100000 0 0 0.100000 0.055556 0 0.100000 0.111111 0 0.100000 0.166667 0 0.100000 0.222222 0 0.100000 0.277778 0 0.100000 0.333333 0 0.100000 0.388889 0 0.100000 0.444444 0 0.100000 0.500000 0 0.100000 0.555556 0 0.100000 0.611111 0 0.100000 0.666667 0 0.100000 0.722222 0 0.100000 0.777778 0 0.100000 0.833333 0 0.100000 0.888889 0 0.100000 0.944444 0 0.100000 1.000000 0 0.108333 0 0 0.108333 0.055556 0 0.108333 0.111111 0 0.108333 0.166667 0 0.108333 0.222222 0 0.108333 0.277778 0 0.108333 0.333333 0 0.108333 0.388889 0 0.108333 0.444444 0 0.108333 0.500000 0 0.108333 0.555556 0 0.108333 0.611111 0 0.108333 0.666667 0 0.108333 0.722222 0 0.108333 0.777778 0 0.108333 0.833333 0 0.108333 0.888889 0 0.108333 0.944444 0 0.108333 1.000000 0 0.116667 0 0 0.116667 0.055556 0 0.116667 0.111111 0 0.116667 0.166667 0 0.116667 0.222222 0 0.116667 0.277778 0 0.116667 0.333333 0 0.116667 0.388889 0 0.116667 0.444444 0 0.116667 0.500000 0 0.116667 0.555556 0 0.116667 0.611111 0 0.116667 0.666667 0 0.116667 0.722222 0 0.116667 0.777778 0 0.116667 0.833333 0 0.116667 0.888889 0 0.116667 0.944444 0 0.116667 1.000000 0 0.125000 0 0 0.125000 0.055556 0 0.125000 0.111111 0 0.125000 0.166667 0 0.125000 0.222222 0 0.125000 0.277778 0 0.125000 0.333333 0 0.125000 0.388889 0 0.125000 0.444444 0 0.125000 0.500000 0 0.125000 0.555556 0 0.125000 0.611111 0 0.125000 0.666667 0 0.125000 0.722222 0 0.125000 0.777778 0 0.125000 0.833333 0 0.125000 0.888889 0 0.125000 0.944444 0 0.125000 1.000000 0 0.133333 0 0 0.133333 0.055556 0 0.133333 0.111111 0 0.133333 0.166667 0 0.133333 0.222222 0 0.133333 0.277778 0 0.133333 0.333333 0 0.133333 0.388889 0 0.133333 0.444444 0 0.133333 0.500000 0 0.133333 0.555556 0 0.133333 0.611111 0 0.133333 0.666667 0 0.133333 0.722222 0 0.133333 0.777778 0 0.133333 0.833333 0 0.133333 0.888889 0 0.133333 0.944444 0 0.133333 1.000000 0 0.141667 0 0 0.141667 0.055556 0 0.141667 0.111111 0 0.141667 0.166667 0 0.141667 0.222222 0 0.141667 0.277778 0 0.141667 0.333333 0 0.141667 0.388889 0 0.141667 0.444444 0 0.141667 0.500000 0 0.141667 0.555556 0 0.141667 0.611111 0 0.141667 0.666667 0 0.141667 0.722222 0 0.141667 0.777778 0 0.141667 0.833333 0 0.141667 0.888889 0 0.141667 0.944444 0 0.141667 1.000000 0 0.150000 0 0 0.150000 0.055556 0 0.150000 0.111111 0 0.150000 0.166667 0 0.150000 0.222222 0 0.150000 0.277778 0 0.150000 0.333333 0 0.150000 0.388889 0 0.150000 0.444444 0 0.150000 0.500000 0 0.150000 0.555556 0 0.150000 0.611111 0 0.150000 0.666667 0 0.150000 0.722222 0 0.150000 0.777778 0 0.150000 0.833333 0 0.150000 0.888889 0 0.150000 0.944444 0 0.150000 1.000000 0 0.158333 0 0 0.158333 0.055556 0 0.158333 0.111111 0 0.158333 0.166667 0 0.158333 0.222222 0 0.158333 0.277778 0 0.158333 0.333333 0 0.158333 0.388889 0 0.158333 0.444444 0 0.158333 0.500000 0 0.158333 0.555556 0 0.158333 0.611111 0 0.158333 0.666667 0 0.158333 0.722222 0 0.158333 0.777778 0 0.158333 0.833333 0 0.158333 0.888889 0 0.158333 0.944444 0 0.158333 1.000000 0 0.166667 0 0 0.166667 0.055556 0 0.166667 0.111111 0 0.166667 0.166667 0 0.166667 0.222222 0 0.166667 0.277778 0 0.166667 0.333333 0 0.166667 0.388889 0 0.166667 0.444444 0 0.166667 0.500000 0 0.166667 0.555556 0 0.166667 0.611111 0 0.166667 0.666667 0 0.166667 0.722222 0 0.166667 0.777778 0 0.166667 0.833333 0 0.166667 0.888889 0 0.166667 0.944444 0 0.166667 1.000000 0 0.175000 0 0 0.175000 0.055556 0 0.175000 0.111111 0 0.175000 0.166667 0 0.175000 0.222222 0 0.175000 0.277778 0 0.175000 0.333333 0 0.175000 0.388889 0 0.175000 0.444444 0 0.175000 0.500000 0 0.175000 0.555556 0 0.175000 0.611111 0 0.175000 0.666667 0 0.175000 0.722222 0 0.175000 0.777778 0 0.175000 0.833333 0 0.175000 0.888889 0 0.175000 0.944444 0 0.175000 1.000000 0 0.183333 0 0 0.183333 0.055556 0 0.183333 0.111111 0 0.183333 0.166667 0 0.183333 0.222222 0 0.183333 0.277778 0 0.183333 0.333333 0 0.183333 0.388889 0 0.183333 0.444444 0 0.183333 0.500000 0 0.183333 0.555556 0 0.183333 0.611111 0 0.183333 0.666667 0 0.183333 0.722222 0 0.183333 0.777778 0 0.183333 0.833333 0 0.183333 0.888889 0 0.183333 0.944444 0 0.183333 1.000000 0 0.191667 0 0 0.191667 0.055556 0 0.191667 0.111111 0 0.191667 0.166667 0 0.191667 0.222222 0 0.191667 0.277778 0 0.191667 0.333333 0 0.191667 0.388889 0 0.191667 0.444444 0 0.191667 0.500000 0 0.191667 0.555556 0 0.191667 0.611111 0 0.191667 0.666667 0 0.191667 0.722222 0 0.191667 0.777778 0 0.191667 0.833333 0 0.191667 0.888889 0 0.191667 0.944444 0 0.191667 1.000000 0 0.200000 0 0 0.200000 0.055556 0 0.200000 0.111111 0 0.200000 0.166667 0 0.200000 0.222222 0 0.200000 0.277778 0 0.200000 0.333333 0 0.200000 0.388889 0 0.200000 0.444444 0 0.200000 0.500000 0 0.200000 0.555556 0 0.200000 0.611111 0 0.200000 0.666667 0 0.200000 0.722222 0 0.200000 0.777778 0 0.200000 0.833333 0 0.200000 0.888889 0 0.200000 0.944444 0 0.200000 1.000000 0 0.208333 0 0 0.208333 0.055556 0 0.208333 0.111111 0 0.208333 0.166667 0 0.208333 0.222222 0 0.208333 0.277778 0 0.208333 0.333333 0 0.208333 0.388889 0 0.208333 0.444444 0 0.208333 0.500000 0 0.208333 0.555556 0 0.208333 0.611111 0 0.208333 0.666667 0 0.208333 0.722222 0 0.208333 0.777778 0 0.208333 0.833333 0 0.208333 0.888889 0 0.208333 0.944444 0 0.208333 1.000000 0 0.216667 0 0 0.216667 0.055556 0 0.216667 0.111111 0 0.216667 0.166667 0 0.216667 0.222222 0 0.216667 0.277778 0 0.216667 0.333333 0 0.216667 0.388889 0 0.216667 0.444444 0 0.216667 0.500000 0 0.216667 0.555556 0 0.216667 0.611111 0 0.216667 0.666667 0 0.216667 0.722222 0 0.216667 0.777778 0 0.216667 0.833333 0 0.216667 0.888889 0 0.216667 0.944444 0 0.216667 1.000000 0 0.225000 0 0 0.225000 0.055556 0 0.225000 0.111111 0 0.225000 0.166667 0 0.225000 0.222222 0 0.225000 0.277778 0 0.225000 0.333333 0 0.225000 0.388889 0 0.225000 0.444444 0 0.225000 0.500000 0 0.225000 0.555556 0 0.225000 0.611111 0 0.225000 0.666667 0 0.225000 0.722222 0 0.225000 0.777778 0 0.225000 0.833333 0 0.225000 0.888889 0 0.225000 0.944444 0 0.225000 1.000000 0 0.233333 0 0 0.233333 0.055556 0 0.233333 0.111111 0 0.233333 0.166667 0 0.233333 0.222222 0 0.233333 0.277778 0 0.233333 0.333333 0 0.233333 0.388889 0 0.233333 0.444444 0 0.233333 0.500000 0 0.233333 0.555556 0 0.233333 0.611111 0 0.233333 0.666667 0 0.233333 0.722222 0 0.233333 0.777778 0 0.233333 0.833333 0 0.233333 0.888889 0 0.233333 0.944444 0 0.233333 1.000000 0 0.241667 0 0 0.241667 0.055556 0 0.241667 0.111111 0 0.241667 0.166667 0 0.241667 0.222222 0 0.241667 0.277778 0 0.241667 0.333333 0 0.241667 0.388889 0 0.241667 0.444444 0 0.241667 0.500000 0 0.241667 0.555556 0 0.241667 0.611111 0 0.241667 0.666667 0 0.241667 0.722222 0 0.241667 0.777778 0 0.241667 0.833333 0 0.241667 0.888889 0 0.241667 0.944444 0 0.241667 1.000000 0 0.250000 0 0 0.250000 0.055556 0 0.250000 0.111111 0 0.250000 0.166667 0 0.250000 0.222222 0 0.250000 0.277778 0 0.250000 0.333333 0 0.250000 0.388889 0 0.250000 0.444444 0 0.250000 0.500000 0 0.250000 0.555556 0 0.250000 0.611111 0 0.250000 0.666667 0 0.250000 0.722222 0 0.250000 0.777778 0 0.250000 0.833333 0 0.250000 0.888889 0 0.250000 0.944444 0 0.250000 1.000000 0 0.258333 0 0 0.258333 0.055556 0 0.258333 0.111111 0 0.258333 0.166667 0 0.258333 0.222222 0 0.258333 0.277778 0 0.258333 0.333333 0 0.258333 0.388889 0 0.258333 0.444444 0 0.258333 0.500000 0 0.258333 0.555556 0 0.258333 0.611111 0 0.258333 0.666667 0 0.258333 0.722222 0 0.258333 0.777778 0 0.258333 0.833333 0 0.258333 0.888889 0 0.258333 0.944444 0 0.258333 1.000000 0 0.266667 0 0 0.266667 0.055556 0 0.266667 0.111111 0 0.266667 0.166667 0 0.266667 0.222222 0 0.266667 0.277778 0 0.266667 0.333333 0 0.266667 0.388889 0 0.266667 0.444444 0 0.266667 0.500000 0 0.266667 0.555556 0 0.266667 0.611111 0 0.266667 0.666667 0 0.266667 0.722222 0 0.266667 0.777778 0 0.266667 0.833333 0 0.266667 0.888889 0 0.266667 0.944444 0 0.266667 1.000000 0 0.275000 0 0 0.275000 0.055556 0 0.275000 0.111111 0 0.275000 0.166667 0 0.275000 0.222222 0 0.275000 0.277778 0 0.275000 0.333333 0 0.275000 0.388889 0 0.275000 0.444444 0 0.275000 0.500000 0 0.275000 0.555556 0 0.275000 0.611111 0 0.275000 0.666667 0 0.275000 0.722222 0 0.275000 0.777778 0 0.275000 0.833333 0 0.275000 0.888889 0 0.275000 0.944444 0 0.275000 1.000000 0 0.283333 0 0 0.283333 0.055556 0 0.283333 0.111111 0 0.283333 0.166667 0 0.283333 0.222222 0 0.283333 0.277778 0 0.283333 0.333333 0 0.283333 0.388889 0 0.283333 0.444444 0 0.283333 0.500000 0 0.283333 0.555556 0 0.283333 0.611111 0 0.283333 0.666667 0 0.283333 0.722222 0 0.283333 0.777778 0 0.283333 0.833333 0 0.283333 0.888889 0 0.283333 0.944444 0 0.283333 1.000000 0 0.291667 0 0 0.291667 0.055556 0 0.291667 0.111111 0 0.291667 0.166667 0 0.291667 0.222222 0 0.291667 0.277778 0 0.291667 0.333333 0 0.291667 0.388889 0 0.291667 0.444444 0 0.291667 0.500000 0 0.291667 0.555556 0 0.291667 0.611111 0 0.291667 0.666667 0 0.291667 0.722222 0 0.291667 0.777778 0 0.291667 0.833333 0 0.291667 0.888889 0 0.291667 0.944444 0 0.291667 1.000000 0 0.300000 0 0 0.300000 0.055556 0 0.300000 0.111111 0 0.300000 0.166667 0 0.300000 0.222222 0 0.300000 0.277778 0 0.300000 0.333333 0 0.300000 0.388889 0 0.300000 0.444444 0 0.300000 0.500000 0 0.300000 0.555556 0 0.300000 0.611111 0 0.300000 0.666667 0 0.300000 0.722222 0 0.300000 0.777778 0 0.300000 0.833333 0 0.300000 0.888889 0 0.300000 0.944444 0 0.300000 1.000000 0 0.308333 0 0 0.308333 0.055556 0 0.308333 0.111111 0 0.308333 0.166667 0 0.308333 0.222222 0 0.308333 0.277778 0 0.308333 0.333333 0 0.308333 0.388889 0 0.308333 0.444444 0 0.308333 0.500000 0 0.308333 0.555556 0 0.308333 0.611111 0 0.308333 0.666667 0 0.308333 0.722222 0 0.308333 0.777778 0 0.308333 0.833333 0 0.308333 0.888889 0 0.308333 0.944444 0 0.308333 1.000000 0 0.316666 0 0 0.316666 0.055556 0 0.316666 0.111111 0 0.316666 0.166667 0 0.316666 0.222222 0 0.316666 0.277778 0 0.316666 0.333333 0 0.316666 0.388889 0 0.316666 0.444444 0 0.316666 0.500000 0 0.316666 0.555556 0 0.316666 0.611111 0 0.316666 0.666667 0 0.316666 0.722222 0 0.316666 0.777778 0 0.316666 0.833333 0 0.316666 0.888889 0 0.316666 0.944444 0 0.316666 1.000000 0 0.325000 0 0 0.325000 0.055556 0 0.325000 0.111111 0 0.325000 0.166667 0 0.325000 0.222222 0 0.325000 0.277778 0 0.325000 0.333333 0 0.325000 0.388889 0 0.325000 0.444444 0 0.325000 0.500000 0 0.325000 0.555556 0 0.325000 0.611111 0 0.325000 0.666667 0 0.325000 0.722222 0 0.325000 0.777778 0 0.325000 0.833333 0 0.325000 0.888889 0 0.325000 0.944444 0 0.325000 1.000000 0 0.333333 0 0 0.333333 0.055556 0 0.333333 0.111111 0 0.333333 0.166667 0 0.333333 0.222222 0 0.333333 0.277778 0 0.333333 0.333333 0 0.333333 0.388889 0 0.333333 0.444444 0 0.333333 0.500000 0 0.333333 0.555556 0 0.333333 0.611111 0 0.333333 0.666667 0 0.333333 0.722222 0 0.333333 0.777778 0 0.333333 0.833333 0 0.333333 0.888889 0 0.333333 0.944444 0 0.333333 1.000000 0 0.341666 0 0 0.341666 0.055556 0 0.341666 0.111111 0 0.341666 0.166667 0 0.341666 0.222222 0 0.341666 0.277778 0 0.341666 0.333333 0 0.341666 0.388889 0 0.341666 0.444444 0 0.341666 0.500000 0 0.341666 0.555556 0 0.341666 0.611111 0 0.341666 0.666667 0 0.341666 0.722222 0 0.341666 0.777778 0 0.341666 0.833333 0 0.341666 0.888889 0 0.341666 0.944444 0 0.341666 1.000000 0 0.350000 0 0 0.350000 0.055556 0 0.350000 0.111111 0 0.350000 0.166667 0 0.350000 0.222222 0 0.350000 0.277778 0 0.350000 0.333333 0 0.350000 0.388889 0 0.350000 0.444444 0 0.350000 0.500000 0 0.350000 0.555556 0 0.350000 0.611111 0 0.350000 0.666667 0 0.350000 0.722222 0 0.350000 0.777778 0 0.350000 0.833333 0 0.350000 0.888889 0 0.350000 0.944444 0 0.350000 1.000000 0 0.358333 0 0 0.358333 0.055556 0 0.358333 0.111111 0 0.358333 0.166667 0 0.358333 0.222222 0 0.358333 0.277778 0 0.358333 0.333333 0 0.358333 0.388889 0 0.358333 0.444444 0 0.358333 0.500000 0 0.358333 0.555556 0 0.358333 0.611111 0 0.358333 0.666667 0 0.358333 0.722222 0 0.358333 0.777778 0 0.358333 0.833333 0 0.358333 0.888889 0 0.358333 0.944444 0 0.358333 1.000000 0 0.366666 0 0 0.366666 0.055556 0 0.366666 0.111111 0 0.366666 0.166667 0 0.366666 0.222222 0 0.366666 0.277778 0 0.366666 0.333333 0 0.366666 0.388889 0 0.366666 0.444444 0 0.366666 0.500000 0 0.366666 0.555556 0 0.366666 0.611111 0 0.366666 0.666667 0 0.366666 0.722222 0 0.366666 0.777778 0 0.366666 0.833333 0 0.366666 0.888889 0 0.366666 0.944444 0 0.366666 1.000000 0 0.375000 0 0 0.375000 0.055556 0 0.375000 0.111111 0 0.375000 0.166667 0 0.375000 0.222222 0 0.375000 0.277778 0 0.375000 0.333333 0 0.375000 0.388889 0 0.375000 0.444444 0 0.375000 0.500000 0 0.375000 0.555556 0 0.375000 0.611111 0 0.375000 0.666667 0 0.375000 0.722222 0 0.375000 0.777778 0 0.375000 0.833333 0 0.375000 0.888889 0 0.375000 0.944444 0 0.375000 1.000000 0 0.383333 0 0 0.383333 0.055556 0 0.383333 0.111111 0 0.383333 0.166667 0 0.383333 0.222222 0 0.383333 0.277778 0 0.383333 0.333333 0 0.383333 0.388889 0 0.383333 0.444444 0 0.383333 0.500000 0 0.383333 0.555556 0 0.383333 0.611111 0 0.383333 0.666667 0 0.383333 0.722222 0 0.383333 0.777778 0 0.383333 0.833333 0 0.383333 0.888889 0 0.383333 0.944444 0 0.383333 1.000000 0 0.391666 0 0 0.391666 0.055556 0 0.391666 0.111111 0 0.391666 0.166667 0 0.391666 0.222222 0 0.391666 0.277778 0 0.391666 0.333333 0 0.391666 0.388889 0 0.391666 0.444444 0 0.391666 0.500000 0 0.391666 0.555556 0 0.391666 0.611111 0 0.391666 0.666667 0 0.391666 0.722222 0 0.391666 0.777778 0 0.391666 0.833333 0 0.391666 0.888889 0 0.391666 0.944444 0 0.391666 1.000000 0 0.400000 0 0 0.400000 0.055556 0 0.400000 0.111111 0 0.400000 0.166667 0 0.400000 0.222222 0 0.400000 0.277778 0 0.400000 0.333333 0 0.400000 0.388889 0 0.400000 0.444444 0 0.400000 0.500000 0 0.400000 0.555556 0 0.400000 0.611111 0 0.400000 0.666667 0 0.400000 0.722222 0 0.400000 0.777778 0 0.400000 0.833333 0 0.400000 0.888889 0 0.400000 0.944444 0 0.400000 1.000000 0 0.408333 0 0 0.408333 0.055556 0 0.408333 0.111111 0 0.408333 0.166667 0 0.408333 0.222222 0 0.408333 0.277778 0 0.408333 0.333333 0 0.408333 0.388889 0 0.408333 0.444444 0 0.408333 0.500000 0 0.408333 0.555556 0 0.408333 0.611111 0 0.408333 0.666667 0 0.408333 0.722222 0 0.408333 0.777778 0 0.408333 0.833333 0 0.408333 0.888889 0 0.408333 0.944444 0 0.408333 1.000000 0 0.416666 0 0 0.416666 0.055556 0 0.416666 0.111111 0 0.416666 0.166667 0 0.416666 0.222222 0 0.416666 0.277778 0 0.416666 0.333333 0 0.416666 0.388889 0 0.416666 0.444444 0 0.416666 0.500000 0 0.416666 0.555556 0 0.416666 0.611111 0 0.416666 0.666667 0 0.416666 0.722222 0 0.416666 0.777778 0 0.416666 0.833333 0 0.416666 0.888889 0 0.416666 0.944444 0 0.416666 1.000000 0 0.425000 0 0 0.425000 0.055556 0 0.425000 0.111111 0 0.425000 0.166667 0 0.425000 0.222222 0 0.425000 0.277778 0 0.425000 0.333333 0 0.425000 0.388889 0 0.425000 0.444444 0 0.425000 0.500000 0 0.425000 0.555556 0 0.425000 0.611111 0 0.425000 0.666667 0 0.425000 0.722222 0 0.425000 0.777778 0 0.425000 0.833333 0 0.425000 0.888889 0 0.425000 0.944444 0 0.425000 1.000000 0 0.433333 0 0 0.433333 0.055556 0 0.433333 0.111111 0 0.433333 0.166667 0 0.433333 0.222222 0 0.433333 0.277778 0 0.433333 0.333333 0 0.433333 0.388889 0 0.433333 0.444444 0 0.433333 0.500000 0 0.433333 0.555556 0 0.433333 0.611111 0 0.433333 0.666667 0 0.433333 0.722222 0 0.433333 0.777778 0 0.433333 0.833333 0 0.433333 0.888889 0 0.433333 0.944444 0 0.433333 1.000000 0 0.441666 0 0 0.441666 0.055556 0 0.441666 0.111111 0 0.441666 0.166667 0 0.441666 0.222222 0 0.441666 0.277778 0 0.441666 0.333333 0 0.441666 0.388889 0 0.441666 0.444444 0 0.441666 0.500000 0 0.441666 0.555556 0 0.441666 0.611111 0 0.441666 0.666667 0 0.441666 0.722222 0 0.441666 0.777778 0 0.441666 0.833333 0 0.441666 0.888889 0 0.441666 0.944444 0 0.441666 1.000000 0 0.450000 0 0 0.450000 0.055556 0 0.450000 0.111111 0 0.450000 0.166667 0 0.450000 0.222222 0 0.450000 0.277778 0 0.450000 0.333333 0 0.450000 0.388889 0 0.450000 0.444444 0 0.450000 0.500000 0 0.450000 0.555556 0 0.450000 0.611111 0 0.450000 0.666667 0 0.450000 0.722222 0 0.450000 0.777778 0 0.450000 0.833333 0 0.450000 0.888889 0 0.450000 0.944444 0 0.450000 1.000000 0 0.458333 0 0 0.458333 0.055556 0 0.458333 0.111111 0 0.458333 0.166667 0 0.458333 0.222222 0 0.458333 0.277778 0 0.458333 0.333333 0 0.458333 0.388889 0 0.458333 0.444444 0 0.458333 0.500000 0 0.458333 0.555556 0 0.458333 0.611111 0 0.458333 0.666667 0 0.458333 0.722222 0 0.458333 0.777778 0 0.458333 0.833333 0 0.458333 0.888889 0 0.458333 0.944444 0 0.458333 1.000000 0 0.466666 0 0 0.466666 0.055556 0 0.466666 0.111111 0 0.466666 0.166667 0 0.466666 0.222222 0 0.466666 0.277778 0 0.466666 0.333333 0 0.466666 0.388889 0 0.466666 0.444444 0 0.466666 0.500000 0 0.466666 0.555556 0 0.466666 0.611111 0 0.466666 0.666667 0 0.466666 0.722222 0 0.466666 0.777778 0 0.466666 0.833333 0 0.466666 0.888889 0 0.466666 0.944444 0 0.466666 1.000000 0 0.475000 0 0 0.475000 0.055556 0 0.475000 0.111111 0 0.475000 0.166667 0 0.475000 0.222222 0 0.475000 0.277778 0 0.475000 0.333333 0 0.475000 0.388889 0 0.475000 0.444444 0 0.475000 0.500000 0 0.475000 0.555556 0 0.475000 0.611111 0 0.475000 0.666667 0 0.475000 0.722222 0 0.475000 0.777778 0 0.475000 0.833333 0 0.475000 0.888889 0 0.475000 0.944444 0 0.475000 1.000000 0 0.483333 0 0 0.483333 0.055556 0 0.483333 0.111111 0 0.483333 0.166667 0 0.483333 0.222222 0 0.483333 0.277778 0 0.483333 0.333333 0 0.483333 0.388889 0 0.483333 0.444444 0 0.483333 0.500000 0 0.483333 0.555556 0 0.483333 0.611111 0 0.483333 0.666667 0 0.483333 0.722222 0 0.483333 0.777778 0 0.483333 0.833333 0 0.483333 0.888889 0 0.483333 0.944444 0 0.483333 1.000000 0 0.491666 0 0 0.491666 0.055556 0 0.491666 0.111111 0 0.491666 0.166667 0 0.491666 0.222222 0 0.491666 0.277778 0 0.491666 0.333333 0 0.491666 0.388889 0 0.491666 0.444444 0 0.491666 0.500000 0 0.491666 0.555556 0 0.491666 0.611111 0 0.491666 0.666667 0 0.491666 0.722222 0 0.491666 0.777778 0 0.491666 0.833333 0 0.491666 0.888889 0 0.491666 0.944444 0 0.491666 1.000000 0 0.500000 0 0 0.500000 0.055556 0 0.500000 0.111111 0 0.500000 0.166667 0 0.500000 0.222222 0 0.500000 0.277778 0 0.500000 0.333333 0 0.500000 0.388889 0 0.500000 0.444444 0 0.500000 0.500000 0 0.500000 0.555556 0 0.500000 0.611111 0 0.500000 0.666667 0 0.500000 0.722222 0 0.500000 0.777778 0 0.500000 0.833333 0 0.500000 0.888889 0 0.500000 0.944444 0 0.500000 1.000000 0 0.508333 0 0 0.508333 0.055556 0 0.508333 0.111111 0 0.508333 0.166667 0 0.508333 0.222222 0 0.508333 0.277778 0 0.508333 0.333333 0 0.508333 0.388889 0 0.508333 0.444444 0 0.508333 0.500000 0 0.508333 0.555556 0 0.508333 0.611111 0 0.508333 0.666667 0 0.508333 0.722222 0 0.508333 0.777778 0 0.508333 0.833333 0 0.508333 0.888889 0 0.508333 0.944444 0 0.508333 1.000000 0 0.516666 0 0 0.516666 0.055556 0 0.516666 0.111111 0 0.516666 0.166667 0 0.516666 0.222222 0 0.516666 0.277778 0 0.516666 0.333333 0 0.516666 0.388889 0 0.516666 0.444444 0 0.516666 0.500000 0 0.516666 0.555556 0 0.516666 0.611111 0 0.516666 0.666667 0 0.516666 0.722222 0 0.516666 0.777778 0 0.516666 0.833333 0 0.516666 0.888889 0 0.516666 0.944444 0 0.516666 1.000000 0 0.525000 0 0 0.525000 0.055556 0 0.525000 0.111111 0 0.525000 0.166667 0 0.525000 0.222222 0 0.525000 0.277778 0 0.525000 0.333333 0 0.525000 0.388889 0 0.525000 0.444444 0 0.525000 0.500000 0 0.525000 0.555556 0 0.525000 0.611111 0 0.525000 0.666667 0 0.525000 0.722222 0 0.525000 0.777778 0 0.525000 0.833333 0 0.525000 0.888889 0 0.525000 0.944444 0 0.525000 1.000000 0 0.533333 0 0 0.533333 0.055556 0 0.533333 0.111111 0 0.533333 0.166667 0 0.533333 0.222222 0 0.533333 0.277778 0 0.533333 0.333333 0 0.533333 0.388889 0 0.533333 0.444444 0 0.533333 0.500000 0 0.533333 0.555556 0 0.533333 0.611111 0 0.533333 0.666667 0 0.533333 0.722222 0 0.533333 0.777778 0 0.533333 0.833333 0 0.533333 0.888889 0 0.533333 0.944444 0 0.533333 1.000000 0 0.541666 0 0 0.541666 0.055556 0 0.541666 0.111111 0 0.541666 0.166667 0 0.541666 0.222222 0 0.541666 0.277778 0 0.541666 0.333333 0 0.541666 0.388889 0 0.541666 0.444444 0 0.541666 0.500000 0 0.541666 0.555556 0 0.541666 0.611111 0 0.541666 0.666667 0 0.541666 0.722222 0 0.541666 0.777778 0 0.541666 0.833333 0 0.541666 0.888889 0 0.541666 0.944444 0 0.541666 1.000000 0 0.550000 0 0 0.550000 0.055556 0 0.550000 0.111111 0 0.550000 0.166667 0 0.550000 0.222222 0 0.550000 0.277778 0 0.550000 0.333333 0 0.550000 0.388889 0 0.550000 0.444444 0 0.550000 0.500000 0 0.550000 0.555556 0 0.550000 0.611111 0 0.550000 0.666667 0 0.550000 0.722222 0 0.550000 0.777778 0 0.550000 0.833333 0 0.550000 0.888889 0 0.550000 0.944444 0 0.550000 1.000000 0 0.558333 0 0 0.558333 0.055556 0 0.558333 0.111111 0 0.558333 0.166667 0 0.558333 0.222222 0 0.558333 0.277778 0 0.558333 0.333333 0 0.558333 0.388889 0 0.558333 0.444444 0 0.558333 0.500000 0 0.558333 0.555556 0 0.558333 0.611111 0 0.558333 0.666667 0 0.558333 0.722222 0 0.558333 0.777778 0 0.558333 0.833333 0 0.558333 0.888889 0 0.558333 0.944444 0 0.558333 1.000000 0 0.566666 0 0 0.566666 0.055556 0 0.566666 0.111111 0 0.566666 0.166667 0 0.566666 0.222222 0 0.566666 0.277778 0 0.566666 0.333333 0 0.566666 0.388889 0 0.566666 0.444444 0 0.566666 0.500000 0 0.566666 0.555556 0 0.566666 0.611111 0 0.566666 0.666667 0 0.566666 0.722222 0 0.566666 0.777778 0 0.566666 0.833333 0 0.566666 0.888889 0 0.566666 0.944444 0 0.566666 1.000000 0 0.575000 0 0 0.575000 0.055556 0 0.575000 0.111111 0 0.575000 0.166667 0 0.575000 0.222222 0 0.575000 0.277778 0 0.575000 0.333333 0 0.575000 0.388889 0 0.575000 0.444444 0 0.575000 0.500000 0 0.575000 0.555556 0 0.575000 0.611111 0 0.575000 0.666667 0 0.575000 0.722222 0 0.575000 0.777778 0 0.575000 0.833333 0 0.575000 0.888889 0 0.575000 0.944444 0 0.575000 1.000000 0 0.583333 0 0 0.583333 0.055556 0 0.583333 0.111111 0 0.583333 0.166667 0 0.583333 0.222222 0 0.583333 0.277778 0 0.583333 0.333333 0 0.583333 0.388889 0 0.583333 0.444444 0 0.583333 0.500000 0 0.583333 0.555556 0 0.583333 0.611111 0 0.583333 0.666667 0 0.583333 0.722222 0 0.583333 0.777778 0 0.583333 0.833333 0 0.583333 0.888889 0 0.583333 0.944444 0 0.583333 1.000000 0 0.591666 0 0 0.591666 0.055556 0 0.591666 0.111111 0 0.591666 0.166667 0 0.591666 0.222222 0 0.591666 0.277778 0 0.591666 0.333333 0 0.591666 0.388889 0 0.591666 0.444444 0 0.591666 0.500000 0 0.591666 0.555556 0 0.591666 0.611111 0 0.591666 0.666667 0 0.591666 0.722222 0 0.591666 0.777778 0 0.591666 0.833333 0 0.591666 0.888889 0 0.591666 0.944444 0 0.591666 1.000000 0 0.599999 0 0 0.599999 0.055556 0 0.599999 0.111111 0 0.599999 0.166667 0 0.599999 0.222222 0 0.599999 0.277778 0 0.599999 0.333333 0 0.599999 0.388889 0 0.599999 0.444444 0 0.599999 0.500000 0 0.599999 0.555556 0 0.599999 0.611111 0 0.599999 0.666667 0 0.599999 0.722222 0 0.599999 0.777778 0 0.599999 0.833333 0 0.599999 0.888889 0 0.599999 0.944444 0 0.599999 1.000000 0 0.608333 0 0 0.608333 0.055556 0 0.608333 0.111111 0 0.608333 0.166667 0 0.608333 0.222222 0 0.608333 0.277778 0 0.608333 0.333333 0 0.608333 0.388889 0 0.608333 0.444444 0 0.608333 0.500000 0 0.608333 0.555556 0 0.608333 0.611111 0 0.608333 0.666667 0 0.608333 0.722222 0 0.608333 0.777778 0 0.608333 0.833333 0 0.608333 0.888889 0 0.608333 0.944444 0 0.608333 1.000000 0 0.616666 0 0 0.616666 0.055556 0 0.616666 0.111111 0 0.616666 0.166667 0 0.616666 0.222222 0 0.616666 0.277778 0 0.616666 0.333333 0 0.616666 0.388889 0 0.616666 0.444444 0 0.616666 0.500000 0 0.616666 0.555556 0 0.616666 0.611111 0 0.616666 0.666667 0 0.616666 0.722222 0 0.616666 0.777778 0 0.616666 0.833333 0 0.616666 0.888889 0 0.616666 0.944444 0 0.616666 1.000000 0 0.624999 0 0 0.624999 0.055556 0 0.624999 0.111111 0 0.624999 0.166667 0 0.624999 0.222222 0 0.624999 0.277778 0 0.624999 0.333333 0 0.624999 0.388889 0 0.624999 0.444444 0 0.624999 0.500000 0 0.624999 0.555556 0 0.624999 0.611111 0 0.624999 0.666667 0 0.624999 0.722222 0 0.624999 0.777778 0 0.624999 0.833333 0 0.624999 0.888889 0 0.624999 0.944444 0 0.624999 1.000000 0 0.633333 0 0 0.633333 0.055556 0 0.633333 0.111111 0 0.633333 0.166667 0 0.633333 0.222222 0 0.633333 0.277778 0 0.633333 0.333333 0 0.633333 0.388889 0 0.633333 0.444444 0 0.633333 0.500000 0 0.633333 0.555556 0 0.633333 0.611111 0 0.633333 0.666667 0 0.633333 0.722222 0 0.633333 0.777778 0 0.633333 0.833333 0 0.633333 0.888889 0 0.633333 0.944444 0 0.633333 1.000000 0 0.641666 0 0 0.641666 0.055556 0 0.641666 0.111111 0 0.641666 0.166667 0 0.641666 0.222222 0 0.641666 0.277778 0 0.641666 0.333333 0 0.641666 0.388889 0 0.641666 0.444444 0 0.641666 0.500000 0 0.641666 0.555556 0 0.641666 0.611111 0 0.641666 0.666667 0 0.641666 0.722222 0 0.641666 0.777778 0 0.641666 0.833333 0 0.641666 0.888889 0 0.641666 0.944444 0 0.641666 1.000000 0 0.649999 0 0 0.649999 0.055556 0 0.649999 0.111111 0 0.649999 0.166667 0 0.649999 0.222222 0 0.649999 0.277778 0 0.649999 0.333333 0 0.649999 0.388889 0 0.649999 0.444444 0 0.649999 0.500000 0 0.649999 0.555556 0 0.649999 0.611111 0 0.649999 0.666667 0 0.649999 0.722222 0 0.649999 0.777778 0 0.649999 0.833333 0 0.649999 0.888889 0 0.649999 0.944444 0 0.649999 1.000000 0 0.658333 0 0 0.658333 0.055556 0 0.658333 0.111111 0 0.658333 0.166667 0 0.658333 0.222222 0 0.658333 0.277778 0 0.658333 0.333333 0 0.658333 0.388889 0 0.658333 0.444444 0 0.658333 0.500000 0 0.658333 0.555556 0 0.658333 0.611111 0 0.658333 0.666667 0 0.658333 0.722222 0 0.658333 0.777778 0 0.658333 0.833333 0 0.658333 0.888889 0 0.658333 0.944444 0 0.658333 1.000000 0 0.666666 0 0 0.666666 0.055556 0 0.666666 0.111111 0 0.666666 0.166667 0 0.666666 0.222222 0 0.666666 0.277778 0 0.666666 0.333333 0 0.666666 0.388889 0 0.666666 0.444444 0 0.666666 0.500000 0 0.666666 0.555556 0 0.666666 0.611111 0 0.666666 0.666667 0 0.666666 0.722222 0 0.666666 0.777778 0 0.666666 0.833333 0 0.666666 0.888889 0 0.666666 0.944444 0 0.666666 1.000000 0 0.675000 0 0 0.675000 0.055556 0 0.675000 0.111111 0 0.675000 0.166667 0 0.675000 0.222222 0 0.675000 0.277778 0 0.675000 0.333333 0 0.675000 0.388889 0 0.675000 0.444444 0 0.675000 0.500000 0 0.675000 0.555556 0 0.675000 0.611111 0 0.675000 0.666667 0 0.675000 0.722222 0 0.675000 0.777778 0 0.675000 0.833333 0 0.675000 0.888889 0 0.675000 0.944444 0 0.675000 1.000000 0 0.683333 0 0 0.683333 0.055556 0 0.683333 0.111111 0 0.683333 0.166667 0 0.683333 0.222222 0 0.683333 0.277778 0 0.683333 0.333333 0 0.683333 0.388889 0 0.683333 0.444444 0 0.683333 0.500000 0 0.683333 0.555556 0 0.683333 0.611111 0 0.683333 0.666667 0 0.683333 0.722222 0 0.683333 0.777778 0 0.683333 0.833333 0 0.683333 0.888889 0 0.683333 0.944444 0 0.683333 1.000000 0 0.691666 0 0 0.691666 0.055556 0 0.691666 0.111111 0 0.691666 0.166667 0 0.691666 0.222222 0 0.691666 0.277778 0 0.691666 0.333333 0 0.691666 0.388889 0 0.691666 0.444444 0 0.691666 0.500000 0 0.691666 0.555556 0 0.691666 0.611111 0 0.691666 0.666667 0 0.691666 0.722222 0 0.691666 0.777778 0 0.691666 0.833333 0 0.691666 0.888889 0 0.691666 0.944444 0 0.691666 1.000000 0 0.700000 0 0 0.700000 0.055556 0 0.700000 0.111111 0 0.700000 0.166667 0 0.700000 0.222222 0 0.700000 0.277778 0 0.700000 0.333333 0 0.700000 0.388889 0 0.700000 0.444444 0 0.700000 0.500000 0 0.700000 0.555556 0 0.700000 0.611111 0 0.700000 0.666667 0 0.700000 0.722222 0 0.700000 0.777778 0 0.700000 0.833333 0 0.700000 0.888889 0 0.700000 0.944444 0 0.700000 1.000000 0 0.708333 0 0 0.708333 0.055556 0 0.708333 0.111111 0 0.708333 0.166667 0 0.708333 0.222222 0 0.708333 0.277778 0 0.708333 0.333333 0 0.708333 0.388889 0 0.708333 0.444444 0 0.708333 0.500000 0 0.708333 0.555556 0 0.708333 0.611111 0 0.708333 0.666667 0 0.708333 0.722222 0 0.708333 0.777778 0 0.708333 0.833333 0 0.708333 0.888889 0 0.708333 0.944444 0 0.708333 1.000000 0 0.716666 0 0 0.716666 0.055556 0 0.716666 0.111111 0 0.716666 0.166667 0 0.716666 0.222222 0 0.716666 0.277778 0 0.716666 0.333333 0 0.716666 0.388889 0 0.716666 0.444444 0 0.716666 0.500000 0 0.716666 0.555556 0 0.716666 0.611111 0 0.716666 0.666667 0 0.716666 0.722222 0 0.716666 0.777778 0 0.716666 0.833333 0 0.716666 0.888889 0 0.716666 0.944444 0 0.716666 1.000000 0 0.725000 0 0 0.725000 0.055556 0 0.725000 0.111111 0 0.725000 0.166667 0 0.725000 0.222222 0 0.725000 0.277778 0 0.725000 0.333333 0 0.725000 0.388889 0 0.725000 0.444444 0 0.725000 0.500000 0 0.725000 0.555556 0 0.725000 0.611111 0 0.725000 0.666667 0 0.725000 0.722222 0 0.725000 0.777778 0 0.725000 0.833333 0 0.725000 0.888889 0 0.725000 0.944444 0 0.725000 1.000000 0 0.733333 0 0 0.733333 0.055556 0 0.733333 0.111111 0 0.733333 0.166667 0 0.733333 0.222222 0 0.733333 0.277778 0 0.733333 0.333333 0 0.733333 0.388889 0 0.733333 0.444444 0 0.733333 0.500000 0 0.733333 0.555556 0 0.733333 0.611111 0 0.733333 0.666667 0 0.733333 0.722222 0 0.733333 0.777778 0 0.733333 0.833333 0 0.733333 0.888889 0 0.733333 0.944444 0 0.733333 1.000000 0 0.741666 0 0 0.741666 0.055556 0 0.741666 0.111111 0 0.741666 0.166667 0 0.741666 0.222222 0 0.741666 0.277778 0 0.741666 0.333333 0 0.741666 0.388889 0 0.741666 0.444444 0 0.741666 0.500000 0 0.741666 0.555556 0 0.741666 0.611111 0 0.741666 0.666667 0 0.741666 0.722222 0 0.741666 0.777778 0 0.741666 0.833333 0 0.741666 0.888889 0 0.741666 0.944444 0 0.741666 1.000000 0 0.750000 0 0 0.750000 0.055556 0 0.750000 0.111111 0 0.750000 0.166667 0 0.750000 0.222222 0 0.750000 0.277778 0 0.750000 0.333333 0 0.750000 0.388889 0 0.750000 0.444444 0 0.750000 0.500000 0 0.750000 0.555556 0 0.750000 0.611111 0 0.750000 0.666667 0 0.750000 0.722222 0 0.750000 0.777778 0 0.750000 0.833333 0 0.750000 0.888889 0 0.750000 0.944444 0 0.750000 1.000000 0 0.758333 0 0 0.758333 0.055556 0 0.758333 0.111111 0 0.758333 0.166667 0 0.758333 0.222222 0 0.758333 0.277778 0 0.758333 0.333333 0 0.758333 0.388889 0 0.758333 0.444444 0 0.758333 0.500000 0 0.758333 0.555556 0 0.758333 0.611111 0 0.758333 0.666667 0 0.758333 0.722222 0 0.758333 0.777778 0 0.758333 0.833333 0 0.758333 0.888889 0 0.758333 0.944444 0 0.758333 1.000000 0 0.766667 0 0 0.766667 0.055556 0 0.766667 0.111111 0 0.766667 0.166667 0 0.766667 0.222222 0 0.766667 0.277778 0 0.766667 0.333333 0 0.766667 0.388889 0 0.766667 0.444444 0 0.766667 0.500000 0 0.766667 0.555556 0 0.766667 0.611111 0 0.766667 0.666667 0 0.766667 0.722222 0 0.766667 0.777778 0 0.766667 0.833333 0 0.766667 0.888889 0 0.766667 0.944444 0 0.766667 1.000000 0 0.775000 0 0 0.775000 0.055556 0 0.775000 0.111111 0 0.775000 0.166667 0 0.775000 0.222222 0 0.775000 0.277778 0 0.775000 0.333333 0 0.775000 0.388889 0 0.775000 0.444444 0 0.775000 0.500000 0 0.775000 0.555556 0 0.775000 0.611111 0 0.775000 0.666667 0 0.775000 0.722222 0 0.775000 0.777778 0 0.775000 0.833333 0 0.775000 0.888889 0 0.775000 0.944444 0 0.775000 1.000000 0 0.783333 0 0 0.783333 0.055556 0 0.783333 0.111111 0 0.783333 0.166667 0 0.783333 0.222222 0 0.783333 0.277778 0 0.783333 0.333333 0 0.783333 0.388889 0 0.783333 0.444444 0 0.783333 0.500000 0 0.783333 0.555556 0 0.783333 0.611111 0 0.783333 0.666667 0 0.783333 0.722222 0 0.783333 0.777778 0 0.783333 0.833333 0 0.783333 0.888889 0 0.783333 0.944444 0 0.783333 1.000000 0 0.791667 0 0 0.791667 0.055556 0 0.791667 0.111111 0 0.791667 0.166667 0 0.791667 0.222222 0 0.791667 0.277778 0 0.791667 0.333333 0 0.791667 0.388889 0 0.791667 0.444444 0 0.791667 0.500000 0 0.791667 0.555556 0 0.791667 0.611111 0 0.791667 0.666667 0 0.791667 0.722222 0 0.791667 0.777778 0 0.791667 0.833333 0 0.791667 0.888889 0 0.791667 0.944444 0 0.791667 1.000000 0 0.800000 0 0 0.800000 0.055556 0 0.800000 0.111111 0 0.800000 0.166667 0 0.800000 0.222222 0 0.800000 0.277778 0 0.800000 0.333333 0 0.800000 0.388889 0 0.800000 0.444444 0 0.800000 0.500000 0 0.800000 0.555556 0 0.800000 0.611111 0 0.800000 0.666667 0 0.800000 0.722222 0 0.800000 0.777778 0 0.800000 0.833333 0 0.800000 0.888889 0 0.800000 0.944444 0 0.800000 1.000000 0 0.808333 0 0 0.808333 0.055556 0 0.808333 0.111111 0 0.808333 0.166667 0 0.808333 0.222222 0 0.808333 0.277778 0 0.808333 0.333333 0 0.808333 0.388889 0 0.808333 0.444444 0 0.808333 0.500000 0 0.808333 0.555556 0 0.808333 0.611111 0 0.808333 0.666667 0 0.808333 0.722222 0 0.808333 0.777778 0 0.808333 0.833333 0 0.808333 0.888889 0 0.808333 0.944444 0 0.808333 1.000000 0 0.816667 0 0 0.816667 0.055556 0 0.816667 0.111111 0 0.816667 0.166667 0 0.816667 0.222222 0 0.816667 0.277778 0 0.816667 0.333333 0 0.816667 0.388889 0 0.816667 0.444444 0 0.816667 0.500000 0 0.816667 0.555556 0 0.816667 0.611111 0 0.816667 0.666667 0 0.816667 0.722222 0 0.816667 0.777778 0 0.816667 0.833333 0 0.816667 0.888889 0 0.816667 0.944444 0 0.816667 1.000000 0 0.825000 0 0 0.825000 0.055556 0 0.825000 0.111111 0 0.825000 0.166667 0 0.825000 0.222222 0 0.825000 0.277778 0 0.825000 0.333333 0 0.825000 0.388889 0 0.825000 0.444444 0 0.825000 0.500000 0 0.825000 0.555556 0 0.825000 0.611111 0 0.825000 0.666667 0 0.825000 0.722222 0 0.825000 0.777778 0 0.825000 0.833333 0 0.825000 0.888889 0 0.825000 0.944444 0 0.825000 1.000000 0 0.833333 0 0 0.833333 0.055556 0 0.833333 0.111111 0 0.833333 0.166667 0 0.833333 0.222222 0 0.833333 0.277778 0 0.833333 0.333333 0 0.833333 0.388889 0 0.833333 0.444444 0 0.833333 0.500000 0 0.833333 0.555556 0 0.833333 0.611111 0 0.833333 0.666667 0 0.833333 0.722222 0 0.833333 0.777778 0 0.833333 0.833333 0 0.833333 0.888889 0 0.833333 0.944444 0 0.833333 1.000000 0 0.841667 0 0 0.841667 0.055556 0 0.841667 0.111111 0 0.841667 0.166667 0 0.841667 0.222222 0 0.841667 0.277778 0 0.841667 0.333333 0 0.841667 0.388889 0 0.841667 0.444444 0 0.841667 0.500000 0 0.841667 0.555556 0 0.841667 0.611111 0 0.841667 0.666667 0 0.841667 0.722222 0 0.841667 0.777778 0 0.841667 0.833333 0 0.841667 0.888889 0 0.841667 0.944444 0 0.841667 1.000000 0 0.850000 0 0 0.850000 0.055556 0 0.850000 0.111111 0 0.850000 0.166667 0 0.850000 0.222222 0 0.850000 0.277778 0 0.850000 0.333333 0 0.850000 0.388889 0 0.850000 0.444444 0 0.850000 0.500000 0 0.850000 0.555556 0 0.850000 0.611111 0 0.850000 0.666667 0 0.850000 0.722222 0 0.850000 0.777778 0 0.850000 0.833333 0 0.850000 0.888889 0 0.850000 0.944444 0 0.850000 1.000000 0 0.858334 0 0 0.858334 0.055556 0 0.858334 0.111111 0 0.858334 0.166667 0 0.858334 0.222222 0 0.858334 0.277778 0 0.858334 0.333333 0 0.858334 0.388889 0 0.858334 0.444444 0 0.858334 0.500000 0 0.858334 0.555556 0 0.858334 0.611111 0 0.858334 0.666667 0 0.858334 0.722222 0 0.858334 0.777778 0 0.858334 0.833333 0 0.858334 0.888889 0 0.858334 0.944444 0 0.858334 1.000000 0 0.866667 0 0 0.866667 0.055556 0 0.866667 0.111111 0 0.866667 0.166667 0 0.866667 0.222222 0 0.866667 0.277778 0 0.866667 0.333333 0 0.866667 0.388889 0 0.866667 0.444444 0 0.866667 0.500000 0 0.866667 0.555556 0 0.866667 0.611111 0 0.866667 0.666667 0 0.866667 0.722222 0 0.866667 0.777778 0 0.866667 0.833333 0 0.866667 0.888889 0 0.866667 0.944444 0 0.866667 1.000000 0 0.875000 0 0 0.875000 0.055556 0 0.875000 0.111111 0 0.875000 0.166667 0 0.875000 0.222222 0 0.875000 0.277778 0 0.875000 0.333333 0 0.875000 0.388889 0 0.875000 0.444444 0 0.875000 0.500000 0 0.875000 0.555556 0 0.875000 0.611111 0 0.875000 0.666667 0 0.875000 0.722222 0 0.875000 0.777778 0 0.875000 0.833333 0 0.875000 0.888889 0 0.875000 0.944444 0 0.875000 1.000000 0 0.883334 0 0 0.883334 0.055556 0 0.883334 0.111111 0 0.883334 0.166667 0 0.883334 0.222222 0 0.883334 0.277778 0 0.883334 0.333333 0 0.883334 0.388889 0 0.883334 0.444444 0 0.883334 0.500000 0 0.883334 0.555556 0 0.883334 0.611111 0 0.883334 0.666667 0 0.883334 0.722222 0 0.883334 0.777778 0 0.883334 0.833333 0 0.883334 0.888889 0 0.883334 0.944444 0 0.883334 1.000000 0 0.891667 0 0 0.891667 0.055556 0 0.891667 0.111111 0 0.891667 0.166667 0 0.891667 0.222222 0 0.891667 0.277778 0 0.891667 0.333333 0 0.891667 0.388889 0 0.891667 0.444444 0 0.891667 0.500000 0 0.891667 0.555556 0 0.891667 0.611111 0 0.891667 0.666667 0 0.891667 0.722222 0 0.891667 0.777778 0 0.891667 0.833333 0 0.891667 0.888889 0 0.891667 0.944444 0 0.891667 1.000000 0 0.900000 0 0 0.900000 0.055556 0 0.900000 0.111111 0 0.900000 0.166667 0 0.900000 0.222222 0 0.900000 0.277778 0 0.900000 0.333333 0 0.900000 0.388889 0 0.900000 0.444444 0 0.900000 0.500000 0 0.900000 0.555556 0 0.900000 0.611111 0 0.900000 0.666667 0 0.900000 0.722222 0 0.900000 0.777778 0 0.900000 0.833333 0 0.900000 0.888889 0 0.900000 0.944444 0 0.900000 1.000000 0 0.908334 0 0 0.908334 0.055556 0 0.908334 0.111111 0 0.908334 0.166667 0 0.908334 0.222222 0 0.908334 0.277778 0 0.908334 0.333333 0 0.908334 0.388889 0 0.908334 0.444444 0 0.908334 0.500000 0 0.908334 0.555556 0 0.908334 0.611111 0 0.908334 0.666667 0 0.908334 0.722222 0 0.908334 0.777778 0 0.908334 0.833333 0 0.908334 0.888889 0 0.908334 0.944444 0 0.908334 1.000000 0 0.916667 0 0 0.916667 0.055556 0 0.916667 0.111111 0 0.916667 0.166667 0 0.916667 0.222222 0 0.916667 0.277778 0 0.916667 0.333333 0 0.916667 0.388889 0 0.916667 0.444444 0 0.916667 0.500000 0 0.916667 0.555556 0 0.916667 0.611111 0 0.916667 0.666667 0 0.916667 0.722222 0 0.916667 0.777778 0 0.916667 0.833333 0 0.916667 0.888889 0 0.916667 0.944444 0 0.916667 1.000000 0 0.925000 0 0 0.925000 0.055556 0 0.925000 0.111111 0 0.925000 0.166667 0 0.925000 0.222222 0 0.925000 0.277778 0 0.925000 0.333333 0 0.925000 0.388889 0 0.925000 0.444444 0 0.925000 0.500000 0 0.925000 0.555556 0 0.925000 0.611111 0 0.925000 0.666667 0 0.925000 0.722222 0 0.925000 0.777778 0 0.925000 0.833333 0 0.925000 0.888889 0 0.925000 0.944444 0 0.925000 1.000000 0 0.933334 0 0 0.933334 0.055556 0 0.933334 0.111111 0 0.933334 0.166667 0 0.933334 0.222222 0 0.933334 0.277778 0 0.933334 0.333333 0 0.933334 0.388889 0 0.933334 0.444444 0 0.933334 0.500000 0 0.933334 0.555556 0 0.933334 0.611111 0 0.933334 0.666667 0 0.933334 0.722222 0 0.933334 0.777778 0 0.933334 0.833333 0 0.933334 0.888889 0 0.933334 0.944444 0 0.933334 1.000000 0 0.941667 0 0 0.941667 0.055556 0 0.941667 0.111111 0 0.941667 0.166667 0 0.941667 0.222222 0 0.941667 0.277778 0 0.941667 0.333333 0 0.941667 0.388889 0 0.941667 0.444444 0 0.941667 0.500000 0 0.941667 0.555556 0 0.941667 0.611111 0 0.941667 0.666667 0 0.941667 0.722222 0 0.941667 0.777778 0 0.941667 0.833333 0 0.941667 0.888889 0 0.941667 0.944444 0 0.941667 1.000000 0 0.950001 0 0 0.950001 0.055556 0 0.950001 0.111111 0 0.950001 0.166667 0 0.950001 0.222222 0 0.950001 0.277778 0 0.950001 0.333333 0 0.950001 0.388889 0 0.950001 0.444444 0 0.950001 0.500000 0 0.950001 0.555556 0 0.950001 0.611111 0 0.950001 0.666667 0 0.950001 0.722222 0 0.950001 0.777778 0 0.950001 0.833333 0 0.950001 0.888889 0 0.950001 0.944444 0 0.950001 1.000000 0 0.958334 0 0 0.958334 0.055556 0 0.958334 0.111111 0 0.958334 0.166667 0 0.958334 0.222222 0 0.958334 0.277778 0 0.958334 0.333333 0 0.958334 0.388889 0 0.958334 0.444444 0 0.958334 0.500000 0 0.958334 0.555556 0 0.958334 0.611111 0 0.958334 0.666667 0 0.958334 0.722222 0 0.958334 0.777778 0 0.958334 0.833333 0 0.958334 0.888889 0 0.958334 0.944444 0 0.958334 1.000000 0 0.966667 0 0 0.966667 0.055556 0 0.966667 0.111111 0 0.966667 0.166667 0 0.966667 0.222222 0 0.966667 0.277778 0 0.966667 0.333333 0 0.966667 0.388889 0 0.966667 0.444444 0 0.966667 0.500000 0 0.966667 0.555556 0 0.966667 0.611111 0 0.966667 0.666667 0 0.966667 0.722222 0 0.966667 0.777778 0 0.966667 0.833333 0 0.966667 0.888889 0 0.966667 0.944444 0 0.966667 1.000000 0 0.975001 0 0 0.975001 0.055556 0 0.975001 0.111111 0 0.975001 0.166667 0 0.975001 0.222222 0 0.975001 0.277778 0 0.975001 0.333333 0 0.975001 0.388889 0 0.975001 0.444444 0 0.975001 0.500000 0 0.975001 0.555556 0 0.975001 0.611111 0 0.975001 0.666667 0 0.975001 0.722222 0 0.975001 0.777778 0 0.975001 0.833333 0 0.975001 0.888889 0 0.975001 0.944444 0 0.975001 1.000000 0 0.983334 0 0 0.983334 0.055556 0 0.983334 0.111111 0 0.983334 0.166667 0 0.983334 0.222222 0 0.983334 0.277778 0 0.983334 0.333333 0 0.983334 0.388889 0 0.983334 0.444444 0 0.983334 0.500000 0 0.983334 0.555556 0 0.983334 0.611111 0 0.983334 0.666667 0 0.983334 0.722222 0 0.983334 0.777778 0 0.983334 0.833333 0 0.983334 0.888889 0 0.983334 0.944444 0 0.983334 1.000000 0 0.991667 0 0 0.991667 0.055556 0 0.991667 0.111111 0 0.991667 0.166667 0 0.991667 0.222222 0 0.991667 0.277778 0 0.991667 0.333333 0 0.991667 0.388889 0 0.991667 0.444444 0 0.991667 0.500000 0 0.991667 0.555556 0 0.991667 0.611111 0 0.991667 0.666667 0 0.991667 0.722222 0 0.991667 0.777778 0 0.991667 0.833333 0 0.991667 0.888889 0 0.991667 0.944444 0 0.991667 1.000000 0 1.000001 0 0 1.000001 0.055556 0 1.000001 0.111111 0 1.000001 0.166667 0 1.000001 0.222222 0 1.000001 0.277778 0 1.000001 0.333333 0 1.000001 0.388889 0 1.000001 0.444444 0 1.000001 0.500000 0 1.000001 0.555556 0 1.000001 0.611111 0 1.000001 0.666667 0 1.000001 0.722222 0 1.000001 0.777778 0 1.000001 0.833333 0 1.000001 0.888889 0 1.000001 0.944444 0 1.000001 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="2299" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="4320">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 18 1 19 19 2 20 0 0 0 19 2 20 1 3 1 1 3 1 19 2 20 20 4 21 1 3 1 20 4 21 2 5 2 2 5 2 20 4 21 21 6 22 2 5 2 21 6 22 3 7 3 3 7 3 21 6 22 22 8 23 3 7 3 22 8 23 4 9 4 4 9 4 22 8 23 23 10 24 4 9 4 23 10 24 5 11 5 5 11 5 23 10 24 24 12 25 5 11 5 24 12 25 6 13 6 6 13 6 24 12 25 25 14 26 6 13 6 25 14 26 7 15 7 7 15 7 25 14 26 26 16 27 7 15 7 26 16 27 8 17 8 8 17 8 26 16 27 27 18 28 8 17 8 27 18 28 9 19 9 9 19 9 27 18 28 28 20 29 9 19 9 28 20 29 10 21 10 10 21 10 28 20 29 29 22 30 10 21 10 29 22 30 11 23 11 11 23 11 29 22 30 30 24 31 11 23 11 30 24 31 12 25 12 12 25 12 30 24 31 31 26 32 12 25 12 31 26 32 13 27 13 13 27 13 31 26 32 32 28 33 13 27 13 32 28 33 14 29 14 14 29 14 32 28 33 33 30 34 14 29 14 33 30 34 15 31 15 15 31 15 33 30 34 34 32 35 15 31 15 34 32 35 16 33 16 16 33 16 34 32 35 35 34 36 16 33 16 35 34 36 17 35 17 17 35 17 35 34 36 18 1 37 17 35 17 18 1 37 0 0 18 18 1 19 36 36 38 37 37 39 18 1 19 37 37 39 19 2 20 19 2 20 37 37 39 38 38 40 19 2 20 38 38 40 20 4 21 20 4 21 38 38 40 39 39 41 20 4 21 39 39 41 21 6 22 21 6 22 39 39 41 40 40 42 21 6 22 40 40 42 22 8 23 22 8 23 40 40 42 41 41 43 22 8 23 41 41 43 23 10 24 23 10 24 41 41 43 42 42 44 23 10 24 42 42 44 24 12 25 24 12 25 42 42 44 43 43 45 24 12 25 43 43 45 25 14 26 25 14 26 43 43 45 44 44 46 25 14 26 44 44 46 26 16 27 26 16 27 44 44 46 45 45 47 26 16 27 45 45 47 27 18 28 27 18 28 45 45 47 46 46 48 27 18 28 46 46 48 28 20 29 28 20 29 46 46 48 47 47 49 28 20 29 47 47 49 29 22 30 29 22 30 47 47 49 48 48 50 29 22 30 48 48 50 30 24 31 30 24 31 48 48 50 49 49 51 30 24 31 49 49 51 31 26 32 31 26 32 49 49 51 50 50 52 31 26 32 50 50 52 32 28 33 32 28 33 50 50 52 51 51 53 32 28 33 51 51 53 33 30 34 33 30 34 51 51 53 52 52 54 33 30 34 52 52 54 34 32 35 34 32 35 52 52 54 53 53 55 34 32 35 53 53 55 35 34 36 35 34 36 53 53 55 36 36 56 35 34 36 36 36 56 18 1 37 36 36 38 54 54 57 55 55 58 36 36 38 55 55 58 37 37 39 37 37 39 55 55 58 56 56 59 37 37 39 56 56 59 38 38 40 38 38 40 56 56 59 57 57 60 38 38 40 57 57 60 39 39 41 39 39 41 57 57 60 58 58 61 39 39 41 58 58 61 40 40 42 40 40 42 58 58 61 59 59 62 40 40 42 59 59 62 41 41 43 41 41 43 59 59 62 60 60 63 41 41 43 60 60 63 42 42 44 42 42 44 60 60 63 61 61 64 42 42 44 61 61 64 43 43 45 43 43 45 61 61 64 62 62 65 43 43 45 62 62 65 44 44 46 44 44 46 62 62 65 63 63 66 44 44 46 63 63 66 45 45 47 45 45 47 63 63 66 64 64 67 45 45 47 64 64 67 46 46 48 46 46 48 64 64 67 65 65 68 46 46 48 65 65 68 47 47 49 47 47 49 65 65 68 66 66 69 47 47 49 66 66 69 48 48 50 48 48 50 66 66 69 67 67 70 48 48 50 67 67 70 49 49 51 49 49 51 67 67 70 68 68 71 49 49 51 68 68 71 50 50 52 50 50 52 68 68 71 69 69 72 50 50 52 69 69 72 51 51 53 51 51 53 69 69 72 70 70 73 51 51 53 70 70 73 52 52 54 52 52 54 70 70 73 71 71 74 52 52 54 71 71 74 53 53 55 53 53 55 71 71 74 54 54 75 53 53 55 54 54 75 36 36 56 54 54 57 72 72 76 73 73 77 54 54 57 73 73 77 55 55 58 55 55 58 73 73 77 74 74 78 55 55 58 74 74 78 56 56 59 56 56 59 74 74 78 75 75 79 56 56 59 75 75 79 57 57 60 57 57 60 75 75 79 76 76 80 57 57 60 76 76 80 58 58 61 58 58 61 76 76 80 77 77 81 58 58 61 77 77 81 59 59 62 59 59 62 77 77 81 78 78 82 59 59 62 78 78 82 60 60 63 60 60 63 78 78 82 79 79 83 60 60 63 79 79 83 61 61 64 61 61 64 79 79 83 80 80 84 61 61 64 80 80 84 62 62 65 62 62 65 80 80 84 81 81 85 62 62 65 81 81 85 63 63 66 63 63 66 81 81 85 82 82 86 63 63 66 82 82 86 64 64 67 64 64 67 82 82 86 83 83 87 64 64 67 83 83 87 65 65 68 65 65 68 83 83 87 84 84 88 65 65 68 84 84 88 66 66 69 66 66 69 84 84 88 85 85 89 66 66 69 85 85 89 67 67 70 67 67 70 85 85 89 86 86 90 67 67 70 86 86 90 68 68 71 68 68 71 86 86 90 87 87 91 68 68 71 87 87 91 69 69 72 69 69 72 87 87 91 88 88 92 69 69 72 88 88 92 70 70 73 70 70 73 88 88 92 89 89 93 70 70 73 89 89 93 71 71 74 71 71 74 89 89 93 72 72 94 71 71 74 72 72 94 54 54 75 72 72 76 90 90 95 91 91 96 72 72 76 91 91 96 73 73 77 73 73 77 91 91 96 92 92 97 73 73 77 92 92 97 74 74 78 74 74 78 92 92 97 93 93 98 74 74 78 93 93 98 75 75 79 75 75 79 93 93 98 94 94 99 75 75 79 94 94 99 76 76 80 76 76 80 94 94 99 95 95 100 76 76 80 95 95 100 77 77 81 77 77 81 95 95 100 96 96 101 77 77 81 96 96 101 78 78 82 78 78 82 96 96 101 97 97 102 78 78 82 97 97 102 79 79 83 79 79 83 97 97 102 98 98 103 79 79 83 98 98 103 80 80 84 80 80 84 98 98 103 99 99 104 80 80 84 99 99 104 81 81 85 81 81 85 99 99 104 100 100 105 81 81 85 100 100 105 82 82 86 82 82 86 100 100 105 101 101 106 82 82 86 101 101 106 83 83 87 83 83 87 101 101 106 102 102 107 83 83 87 102 102 107 84 84 88 84 84 88 102 102 107 103 103 108 84 84 88 103 103 108 85 85 89 85 85 89 103 103 108 104 104 109 85 85 89 104 104 109 86 86 90 86 86 90 104 104 109 105 105 110 86 86 90 105 105 110 87 87 91 87 87 91 105 105 110 106 106 111 87 87 91 106 106 111 88 88 92 88 88 92 106 106 111 107 107 112 88 88 92 107 107 112 89 89 93 89 89 93 107 107 112 90 90 113 89 89 93 90 90 113 72 72 94 90 90 95 108 108 114 109 109 115 90 90 95 109 109 115 91 91 96 91 91 96 109 109 115 110 110 116 91 91 96 110 110 116 92 92 97 92 92 97 110 110 116 111 111 117 92 92 97 111 111 117 93 93 98 93 93 98 111 111 117 112 112 118 93 93 98 112 112 118 94 94 99 94 94 99 112 112 118 113 113 119 94 94 99 113 113 119 95 95 100 95 95 100 113 113 119 114 114 120 95 95 100 114 114 120 96 96 101 96 96 101 114 114 120 115 115 121 96 96 101 115 115 121 97 97 102 97 97 102 115 115 121 116 116 122 97 97 102 116 116 122 98 98 103 98 98 103 116 116 122 117 117 123 98 98 103 117 117 123 99 99 104 99 99 104 117 117 123 118 118 124 99 99 104 118 118 124 100 100 105 100 100 105 118 118 124 119 119 125 100 100 105 119 119 125 101 101 106 101 101 106 119 119 125 120 120 126 101 101 106 120 120 126 102 102 107 102 102 107 120 120 126 121 121 127 102 102 107 121 121 127 103 103 108 103 103 108 121 121 127 122 122 128 103 103 108 122 122 128 104 104 109 104 104 109 122 122 128 123 123 129 104 104 109 123 123 129 105 105 110 105 105 110 123 123 129 124 124 130 105 105 110 124 124 130 106 106 111 106 106 111 124 124 130 125 125 131 106 106 111 125 125 131 107 107 112 107 107 112 125 125 131 108 108 132 107 107 112 108 108 132 90 90 113 108 108 114 126 126 133 127 127 134 108 108 114 127 127 134 109 109 115 109 109 115 127 127 134 128 128 135 109 109 115 128 128 135 110 110 116 110 110 116 128 128 135 129 129 136 110 110 116 129 129 136 111 111 117 111 111 117 129 129 136 130 130 137 111 111 117 130 130 137 112 112 118 112 112 118 130 130 137 131 131 138 112 112 118 131 131 138 113 113 119 113 113 119 131 131 138 132 132 139 113 113 119 132 132 139 114 114 120 114 114 120 132 132 139 133 133 140 114 114 120 133 133 140 115 115 121 115 115 121 133 133 140 134 134 141 115 115 121 134 134 141 116 116 122 116 116 122 134 134 141 135 135 142 116 116 122 135 135 142 117 117 123 117 117 123 135 135 142 136 136 143 117 117 123 136 136 143 118 118 124 118 118 124 136 136 143 137 137 144 118 118 124 137 137 144 119 119 125 119 119 125 137 137 144 138 138 145 119 119 125 138 138 145 120 120 126 120 120 126 138 138 145 139 139 146 120 120 126 139 139 146 121 121 127 121 121 127 139 139 146 140 140 147 121 121 127 140 140 147 122 122 128 122 122 128 140 140 147 141 141 148 122 122 128 141 141 148 123 123 129 123 123 129 141 141 148 142 142 149 123 123 129 142 142 149 124 124 130 124 124 130 142 142 149 143 143 150 124 124 130 143 143 150 125 125 131 125 125 131 143 143 150 126 126 151 125 125 131 126 126 151 108 108 132 126 126 133 144 144 152 145 145 153 126 126 133 145 145 153 127 127 134 127 127 134 145 145 153 146 146 154 127 127 134 146 146 154 128 128 135 128 128 135 146 146 154 147 147 155 128 128 135 147 147 155 129 129 136 129 129 136 147 147 155 148 148 156 129 129 136 148 148 156 130 130 137 130 130 137 148 148 156 149 149 157 130 130 137 149 149 157 131 131 138 131 131 138 149 149 157 150 150 158 131 131 138 150 150 158 132 132 139 132 132 139 150 150 158 151 151 159 132 132 139 151 151 159 133 133 140 133 133 140 151 151 159 152 152 160 133 133 140 152 152 160 134 134 141 134 134 141 152 152 160 153 153 161 134 134 141 153 153 161 135 135 142 135 135 142 153 153 161 154 154 162 135 135 142 154 154 162 136 136 143 136 136 143 154 154 162 155 155 163 136 136 143 155 155 163 137 137 144 137 137 144 155 155 163 156 156 164 137 137 144 156 156 164 138 138 145 138 138 145 156 156 164 157 157 165 138 138 145 157 157 165 139 139 146 139 139 146 157 157 165 158 158 166 139 139 146 158 158 166 140 140 147 140 140 147 158 158 166 159 159 167 140 140 147 159 159 167 141 141 148 141 141 148 159 159 167 160 160 168 141 141 148 160 160 168 142 142 149 142 142 149 160 160 168 161 161 169 142 142 149 161 161 169 143 143 150 143 143 150 161 161 169 144 144 170 143 143 150 144 144 170 126 126 151 144 144 152 162 162 171 163 163 172 144 144 152 163 163 172 145 145 153 145 145 153 163 163 172 164 164 173 145 145 153 164 164 173 146 146 154 146 146 154 164 164 173 165 165 174 146 146 154 165 165 174 147 147 155 147 147 155 165 165 174 166 166 175 147 147 155 166 166 175 148 148 156 148 148 156 166 166 175 167 167 176 148 148 156 167 167 176 149 149 157 149 149 157 167 167 176 168 168 177 149 149 157 168 168 177 150 150 158 150 150 158 168 168 177 169 169 178 150 150 158 169 169 178 151 151 159 151 151 159 169 169 178 170 170 179 151 151 159 170 170 179 152 152 160 152 152 160 170 170 179 171 171 180 152 152 160 171 171 180 153 153 161 153 153 161 171 171 180 172 172 181 153 153 161 172 172 181 154 154 162 154 154 162 172 172 181 173 173 182 154 154 162 173 173 182 155 155 163 155 155 163 173 173 182 174 174 183 155 155 163 174 174 183 156 156 164 156 156 164 174 174 183 175 175 184 156 156 164 175 175 184 157 157 165 157 157 165 175 175 184 176 176 185 157 157 165 176 176 185 158 158 166 158 158 166 176 176 185 177 177 186 158 158 166 177 177 186 159 159 167 159 159 167 177 177 186 178 178 187 159 159 167 178 178 187 160 160 168 160 160 168 178 178 187 179 179 188 160 160 168 179 179 188 161 161 169 161 161 169 179 179 188 162 162 189 161 161 169 162 162 189 144 144 170 162 162 171 180 180 190 181 181 191 162 162 171 181 181 191 163 163 172 163 163 172 181 181 191 182 182 192 163 163 172 182 182 192 164 164 173 164 164 173 182 182 192 183 183 193 164 164 173 183 183 193 165 165 174 165 165 174 183 183 193 184 184 194 165 165 174 184 184 194 166 166 175 166 166 175 184 184 194 185 185 195 166 166 175 185 185 195 167 167 176 167 167 176 185 185 195 186 186 196 167 167 176 186 186 196 168 168 177 168 168 177 186 186 196 187 187 197 168 168 177 187 187 197 169 169 178 169 169 178 187 187 197 188 188 198 169 169 178 188 188 198 170 170 179 170 170 179 188 188 198 189 189 199 170 170 179 189 189 199 171 171 180 171 171 180 189 189 199 190 190 200 171 171 180 190 190 200 172 172 181 172 172 181 190 190 200 191 191 201 172 172 181 191 191 201 173 173 182 173 173 182 191 191 201 192 192 202 173 173 182 192 192 202 174 174 183 174 174 183 192 192 202 193 193 203 174 174 183 193 193 203 175 175 184 175 175 184 193 193 203 194 194 204 175 175 184 194 194 204 176 176 185 176 176 185 194 194 204 195 195 205 176 176 185 195 195 205 177 177 186 177 177 186 195 195 205 196 196 206 177 177 186 196 196 206 178 178 187 178 178 187 196 196 206 197 197 207 178 178 187 197 197 207 179 179 188 179 179 188 197 197 207 180 180 208 179 179 188 180 180 208 162 162 189 180 180 190 198 198 209 199 199 210 180 180 190 199 199 210 181 181 191 181 181 191 199 199 210 200 200 211 181 181 191 200 200 211 182 182 192 182 182 192 200 200 211 201 201 212 182 182 192 201 201 212 183 183 193 183 183 193 201 201 212 202 202 213 183 183 193 202 202 213 184 184 194 184 184 194 202 202 213 203 203 214 184 184 194 203 203 214 185 185 195 185 185 195 203 203 214 204 204 215 185 185 195 204 204 215 186 186 196 186 186 196 204 204 215 205 205 216 186 186 196 205 205 216 187 187 197 187 187 197 205 205 216 206 206 217 187 187 197 206 206 217 188 188 198 188 188 198 206 206 217 207 207 218 188 188 198 207 207 218 189 189 199 189 189 199 207 207 218 208 208 219 189 189 199 208 208 219 190 190 200 190 190 200 208 208 219 209 209 220 190 190 200 209 209 220 191 191 201 191 191 201 209 209 220 210 210 221 191 191 201 210 210 221 192 192 202 192 192 202 210 210 221 211 211 222 192 192 202 211 211 222 193 193 203 193 193 203 211 211 222 212 212 223 193 193 203 212 212 223 194 194 204 194 194 204 212 212 223 213 213 224 194 194 204 213 213 224 195 195 205 195 195 205 213 213 224 214 214 225 195 195 205 214 214 225 196 196 206 196 196 206 214 214 225 215 215 226 196 196 206 215 215 226 197 197 207 197 197 207 215 215 226 198 198 227 197 197 207 198 198 227 180 180 208 198 198 209 216 216 228 217 217 229 198 198 209 217 217 229 199 199 210 199 199 210 217 217 229 218 218 230 199 199 210 218 218 230 200 200 211 200 200 211 218 218 230 219 219 231 200 200 211 219 219 231 201 201 212 201 201 212 219 219 231 220 220 232 201 201 212 220 220 232 202 202 213 202 202 213 220 220 232 221 221 233 202 202 213 221 221 233 203 203 214 203 203 214 221 221 233 222 222 234 203 203 214 222 222 234 204 204 215 204 204 215 222 222 234 223 223 235 204 204 215 223 223 235 205 205 216 205 205 216 223 223 235 224 224 236 205 205 216 224 224 236 206 206 217 206 206 217 224 224 236 225 225 237 206 206 217 225 225 237 207 207 218 207 207 218 225 225 237 226 226 238 207 207 218 226 226 238 208 208 219 208 208 219 226 226 238 227 227 239 208 208 219 227 227 239 209 209 220 209 209 220 227 227 239 228 228 240 209 209 220 228 228 240 210 210 221 210 210 221 228 228 240 229 229 241 210 210 221 229 229 241 211 211 222 211 211 222 229 229 241 230 230 242 211 211 222 230 230 242 212 212 223 212 212 223 230 230 242 231 231 243 212 212 223 231 231 243 213 213 224 213 213 224 231 231 243 232 232 244 213 213 224 232 232 244 214 214 225 214 214 225 232 232 244 233 233 245 214 214 225 233 233 245 215 215 226 215 215 226 233 233 245 216 216 246 215 215 226 216 216 246 198 198 227 216 216 228 234 234 247 235 235 248 216 216 228 235 235 248 217 217 229 217 217 229 235 235 248 236 236 249 217 217 229 236 236 249 218 218 230 218 218 230 236 236 249 237 237 250 218 218 230 237 237 250 219 219 231 219 219 231 237 237 250 238 238 251 219 219 231 238 238 251 220 220 232 220 220 232 238 238 251 239 239 252 220 220 232 239 239 252 221 221 233 221 221 233 239 239 252 240 240 253 221 221 233 240 240 253 222 222 234 222 222 234 240 240 253 241 241 254 222 222 234 241 241 254 223 223 235 223 223 235 241 241 254 242 242 255 223 223 235 242 242 255 224 224 236 224 224 236 242 242 255 243 243 256 224 224 236 243 243 256 225 225 237 225 225 237 243 243 256 244 244 257 225 225 237 244 244 257 226 226 238 226 226 238 244 244 257 245 245 258 226 226 238 245 245 258 227 227 239 227 227 239 245 245 258 246 246 259 227 227 239 246 246 259 228 228 240 228 228 240 246 246 259 247 247 260 228 228 240 247 247 260 229 229 241 229 229 241 247 247 260 248 248 261 229 229 241 248 248 261 230 230 242 230 230 242 248 248 261 249 249 262 230 230 242 249 249 262 231 231 243 231 231 243 249 249 262 250 250 263 231 231 243 250 250 263 232 232 244 232 232 244 250 250 263 251 251 264 232 232 244 251 251 264 233 233 245 233 233 245 251 251 264 234 234 265 233 233 245 234 234 265 216 216 246 234 234 247 252 252 266 253 253 267 234 234 247 253 253 267 235 235 248 235 235 248 253 253 267 254 254 268 235 235 248 254 254 268 236 236 249 236 236 249 254 254 268 255 255 269 236 236 249 255 255 269 237 237 250 237 237 250 255 255 269 256 256 270 237 237 250 256 256 270 238 238 251 238 238 251 256 256 270 257 257 271 238 238 251 257 257 271 239 239 252 239 239 252 257 257 271 258 258 272 239 239 252 258 258 272 240 240 253 240 240 253 258 258 272 259 259 273 240 240 253 259 259 273 241 241 254 241 241 254 259 259 273 260 260 274 241 241 254 260 260 274 242 242 255 242 242 255 260 260 274 261 261 275 242 242 255 261 261 275 243 243 256 243 243 256 261 261 275 262 262 276 243 243 256 262 262 276 244 244 257 244 244 257 262 262 276 263 263 277 244 244 257 263 263 277 245 245 258 245 245 258 263 263 277 264 264 278 245 245 258 264 264 278 246 246 259 246 246 259 264 264 278 265 265 279 246 246 259 265 265 279 247 247 260 247 247 260 265 265 279 266 266 280 247 247 260 266 266 280 248 248 261 248 248 261 266 266 280 267 267 281 248 248 261 267 267 281 249 249 262 249 249 262 267 267 281 268 268 282 249 249 262 268 268 282 250 250 263 250 250 263 268 268 282 269 269 283 250 250 263 269 269 283 251 251 264 251 251 264 269 269 283 252 252 284 251 251 264 252 252 284 234 234 265 252 252 266 270 270 285 271 271 286 252 252 266 271 271 286 253 253 267 253 253 267 271 271 286 272 272 287 253 253 267 272 272 287 254 254 268 254 254 268 272 272 287 273 273 288 254 254 268 273 273 288 255 255 269 255 255 269 273 273 288 274 274 289 255 255 269 274 274 289 256 256 270 256 256 270 274 274 289 275 275 290 256 256 270 275 275 290 257 257 271 257 257 271 275 275 290 276 276 291 257 257 271 276 276 291 258 258 272 258 258 272 276 276 291 277 277 292 258 258 272 277 277 292 259 259 273 259 259 273 277 277 292 278 278 293 259 259 273 278 278 293 260 260 274 260 260 274 278 278 293 279 279 294 260 260 274 279 279 294 261 261 275 261 261 275 279 279 294 280 280 295 261 261 275 280 280 295 262 262 276 262 262 276 280 280 295 281 281 296 262 262 276 281 281 296 263 263 277 263 263 277 281 281 296 282 282 297 263 263 277 282 282 297 264 264 278 264 264 278 282 282 297 283 283 298 264 264 278 283 283 298 265 265 279 265 265 279 283 283 298 284 284 299 265 265 279 284 284 299 266 266 280 266 266 280 284 284 299 285 285 300 266 266 280 285 285 300 267 267 281 267 267 281 285 285 300 286 286 301 267 267 281 286 286 301 268 268 282 268 268 282 286 286 301 287 287 302 268 268 282 287 287 302 269 269 283 269 269 283 287 287 302 270 270 303 269 269 283 270 270 303 252 252 284 270 270 285 288 288 304 289 289 305 270 270 285 289 289 305 271 271 286 271 271 286 289 289 305 290 290 306 271 271 286 290 290 306 272 272 287 272 272 287 290 290 306 291 291 307 272 272 287 291 291 307 273 273 288 273 273 288 291 291 307 292 292 308 273 273 288 292 292 308 274 274 289 274 274 289 292 292 308 293 293 309 274 274 289 293 293 309 275 275 290 275 275 290 293 293 309 294 294 310 275 275 290 294 294 310 276 276 291 276 276 291 294 294 310 295 295 311 276 276 291 295 295 311 277 277 292 277 277 292 295 295 311 296 296 312 277 277 292 296 296 312 278 278 293 278 278 293 296 296 312 297 297 313 278 278 293 297 297 313 279 279 294 279 279 294 297 297 313 298 298 314 279 279 294 298 298 314 280 280 295 280 280 295 298 298 314 299 299 315 280 280 295 299 299 315 281 281 296 281 281 296 299 299 315 300 300 316 281 281 296 300 300 316 282 282 297 282 282 297 300 300 316 301 301 317 282 282 297 301 301 317 283 283 298 283 283 298 301 301 317 302 302 318 283 283 298 302 302 318 284 284 299 284 284 299 302 302 318 303 303 319 284 284 299 303 303 319 285 285 300 285 285 300 303 303 319 304 304 320 285 285 300 304 304 320 286 286 301 286 286 301 304 304 320 305 305 321 286 286 301 305 305 321 287 287 302 287 287 302 305 305 321 288 288 322 287 287 302 288 288 322 270 270 303 288 288 304 306 306 323 307 307 324 288 288 304 307 307 324 289 289 305 289 289 305 307 307 324 308 308 325 289 289 305 308 308 325 290 290 306 290 290 306 308 308 325 309 309 326 290 290 306 309 309 326 291 291 307 291 291 307 309 309 326 310 310 327 291 291 307 310 310 327 292 292 308 292 292 308 310 310 327 311 311 328 292 292 308 311 311 328 293 293 309 293 293 309 311 311 328 312 312 329 293 293 309 312 312 329 294 294 310 294 294 310 312 312 329 313 313 330 294 294 310 313 313 330 295 295 311 295 295 311 313 313 330 314 314 331 295 295 311 314 314 331 296 296 312 296 296 312 314 314 331 315 315 332 296 296 312 315 315 332 297 297 313 297 297 313 315 315 332 316 316 333 297 297 313 316 316 333 298 298 314 298 298 314 316 316 333 317 317 334 298 298 314 317 317 334 299 299 315 299 299 315 317 317 334 318 318 335 299 299 315 318 318 335 300 300 316 300 300 316 318 318 335 319 319 336 300 300 316 319 319 336 301 301 317 301 301 317 319 319 336 320 320 337 301 301 317 320 320 337 302 302 318 302 302 318 320 320 337 321 321 338 302 302 318 321 321 338 303 303 319 303 303 319 321 321 338 322 322 339 303 303 319 322 322 339 304 304 320 304 304 320 322 322 339 323 323 340 304 304 320 323 323 340 305 305 321 305 305 321 323 323 340 306 306 341 305 305 321 306 306 341 288 288 322 306 306 323 324 324 342 325 325 343 306 306 323 325 325 343 307 307 324 307 307 324 325 325 343 326 326 344 307 307 324 326 326 344 308 308 325 308 308 325 326 326 344 327 327 345 308 308 325 327 327 345 309 309 326 309 309 326 327 327 345 328 328 346 309 309 326 328 328 346 310 310 327 310 310 327 328 328 346 329 329 347 310 310 327 329 329 347 311 311 328 311 311 328 329 329 347 330 330 348 311 311 328 330 330 348 312 312 329 312 312 329 330 330 348 331 331 349 312 312 329 331 331 349 313 313 330 313 313 330 331 331 349 332 332 350 313 313 330 332 332 350 314 314 331 314 314 331 332 332 350 333 333 351 314 314 331 333 333 351 315 315 332 315 315 332 333 333 351 334 334 352 315 315 332 334 334 352 316 316 333 316 316 333 334 334 352 335 335 353 316 316 333 335 335 353 317 317 334 317 317 334 335 335 353 336 336 354 317 317 334 336 336 354 318 318 335 318 318 335 336 336 354 337 337 355 318 318 335 337 337 355 319 319 336 319 319 336 337 337 355 338 338 356 319 319 336 338 338 356 320 320 337 320 320 337 338 338 356 339 339 357 320 320 337 339 339 357 321 321 338 321 321 338 339 339 357 340 340 358 321 321 338 340 340 358 322 322 339 322 322 339 340 340 358 341 341 359 322 322 339 341 341 359 323 323 340 323 323 340 341 341 359 324 324 360 323 323 340 324 324 360 306 306 341 324 324 342 342 342 361 343 343 362 324 324 342 343 343 362 325 325 343 325 325 343 343 343 362 344 344 363 325 325 343 344 344 363 326 326 344 326 326 344 344 344 363 345 345 364 326 326 344 345 345 364 327 327 345 327 327 345 345 345 364 346 346 365 327 327 345 346 346 365 328 328 346 328 328 346 346 346 365 347 347 366 328 328 346 347 347 366 329 329 347 329 329 347 347 347 366 348 348 367 329 329 347 348 348 367 330 330 348 330 330 348 348 348 367 349 349 368 330 330 348 349 349 368 331 331 349 331 331 349 349 349 368 350 350 369 331 331 349 350 350 369 332 332 350 332 332 350 350 350 369 351 351 370 332 332 350 351 351 370 333 333 351 333 333 351 351 351 370 352 352 371 333 333 351 352 352 371 334 334 352 334 334 352 352 352 371 353 353 372 334 334 352 353 353 372 335 335 353 335 335 353 353 353 372 354 354 373 335 335 353 354 354 373 336 336 354 336 336 354 354 354 373 355 355 374 336 336 354 355 355 374 337 337 355 337 337 355 355 355 374 356 356 375 337 337 355 356 356 375 338 338 356 338 338 356 356 356 375 357 357 376 338 338 356 357 357 376 339 339 357 339 339 357 357 357 376 358 358 377 339 339 357 358 358 377 340 340 358 340 340 358 358 358 377 359 359 378 340 340 358 359 359 378 341 341 359 341 341 359 359 359 378 342 342 379 341 341 359 342 342 379 324 324 360 342 342 361 360 360 380 361 361 381 342 342 361 361 361 381 343 343 362 343 343 362 361 361 381 362 362 382 343 343 362 362 362 382 344 344 363 344 344 363 362 362 382 363 363 383 344 344 363 363 363 383 345 345 364 345 345 364 363 363 383 364 364 384 345 345 364 364 364 384 346 346 365 346 346 365 364 364 384 365 365 385 346 346 365 365 365 385 347 347 366 347 347 366 365 365 385 366 366 386 347 347 366 366 366 386 348 348 367 348 348 367 366 366 386 367 367 387 348 348 367 367 367 387 349 349 368 349 349 368 367 367 387 368 368 388 349 349 368 368 368 388 350 350 369 350 350 369 368 368 388 369 369 389 350 350 369 369 369 389 351 351 370 351 351 370 369 369 389 370 370 390 351 351 370 370 370 390 352 352 371 352 352 371 370 370 390 371 371 391 352 352 371 371 371 391 353 353 372 353 353 372 371 371 391 372 372 392 353 353 372 372 372 392 354 354 373 354 354 373 372 372 392 373 373 393 354 354 373 373 373 393 355 355 374 355 355 374 373 373 393 374 374 394 355 355 374 374 374 394 356 356 375 356 356 375 374 374 394 375 375 395 356 356 375 375 375 395 357 357 376 357 357 376 375 375 395 376 376 396 357 357 376 376 376 396 358 358 377 358 358 377 376 376 396 377 377 397 358 358 377 377 377 397 359 359 378 359 359 378 377 377 397 360 360 398 359 359 378 360 360 398 342 342 379 360 360 380 378 378 399 379 379 400 360 360 380 379 379 400 361 361 381 361 361 381 379 379 400 380 380 401 361 361 381 380 380 401 362 362 382 362 362 382 380 380 401 381 381 402 362 362 382 381 381 402 363 363 383 363 363 383 381 381 402 382 382 403 363 363 383 382 382 403 364 364 384 364 364 384 382 382 403 383 383 404 364 364 384 383 383 404 365 365 385 365 365 385 383 383 404 384 384 405 365 365 385 384 384 405 366 366 386 366 366 386 384 384 405 385 385 406 366 366 386 385 385 406 367 367 387 367 367 387 385 385 406 386 386 407 367 367 387 386 386 407 368 368 388 368 368 388 386 386 407 387 387 408 368 368 388 387 387 408 369 369 389 369 369 389 387 387 408 388 388 409 369 369 389 388 388 409 370 370 390 370 370 390 388 388 409 389 389 410 370 370 390 389 389 410 371 371 391 371 371 391 389 389 410 390 390 411 371 371 391 390 390 411 372 372 392 372 372 392 390 390 411 391 391 412 372 372 392 391 391 412 373 373 393 373 373 393 391 391 412 392 392 413 373 373 393 392 392 413 374 374 394 374 374 394 392 392 413 393 393 414 374 374 394 393 393 414 375 375 395 375 375 395 393 393 414 394 394 415 375 375 395 394 394 415 376 376 396 376 376 396 394 394 415 395 395 416 376 376 396 395 395 416 377 377 397 377 377 397 395 395 416 378 378 417 377 377 397 378 378 417 360 360 398 378 378 399 396 396 418 397 397 419 378 378 399 397 397 419 379 379 400 379 379 400 397 397 419 398 398 420 379 379 400 398 398 420 380 380 401 380 380 401 398 398 420 399 399 421 380 380 401 399 399 421 381 381 402 381 381 402 399 399 421 400 400 422 381 381 402 400 400 422 382 382 403 382 382 403 400 400 422 401 401 423 382 382 403 401 401 423 383 383 404 383 383 404 401 401 423 402 402 424 383 383 404 402 402 424 384 384 405 384 384 405 402 402 424 403 403 425 384 384 405 403 403 425 385 385 406 385 385 406 403 403 425 404 404 426 385 385 406 404 404 426 386 386 407 386 386 407 404 404 426 405 405 427 386 386 407 405 405 427 387 387 408 387 387 408 405 405 427 406 406 428 387 387 408 406 406 428 388 388 409 388 388 409 406 406 428 407 407 429 388 388 409 407 407 429 389 389 410 389 389 410 407 407 429 408 408 430 389 389 410 408 408 430 390 390 411 390 390 411 408 408 430 409 409 431 390 390 411 409 409 431 391 391 412 391 391 412 409 409 431 410 410 432 391 391 412 410 410 432 392 392 413 392 392 413 410 410 432 411 411 433 392 392 413 411 411 433 393 393 414 393 393 414 411 411 433 412 412 434 393 393 414 412 412 434 394 394 415 394 394 415 412 412 434 413 413 435 394 394 415 413 413 435 395 395 416 395 395 416 413 413 435 396 396 436 395 395 416 396 396 436 378 378 417 396 396 418 414 414 437 415 415 438 396 396 418 415 415 438 397 397 419 397 397 419 415 415 438 416 416 439 397 397 419 416 416 439 398 398 420 398 398 420 416 416 439 417 417 440 398 398 420 417 417 440 399 399 421 399 399 421 417 417 440 418 418 441 399 399 421 418 418 441 400 400 422 400 400 422 418 418 441 419 419 442 400 400 422 419 419 442 401 401 423 401 401 423 419 419 442 420 420 443 401 401 423 420 420 443 402 402 424 402 402 424 420 420 443 421 421 444 402 402 424 421 421 444 403 403 425 403 403 425 421 421 444 422 422 445 403 403 425 422 422 445 404 404 426 404 404 426 422 422 445 423 423 446 404 404 426 423 423 446 405 405 427 405 405 427 423 423 446 424 424 447 405 405 427 424 424 447 406 406 428 406 406 428 424 424 447 425 425 448 406 406 428 425 425 448 407 407 429 407 407 429 425 425 448 426 426 449 407 407 429 426 426 449 408 408 430 408 408 430 426 426 449 427 427 450 408 408 430 427 427 450 409 409 431 409 409 431 427 427 450 428 428 451 409 409 431 428 428 451 410 410 432 410 410 432 428 428 451 429 429 452 410 410 432 429 429 452 411 411 433 411 411 433 429 429 452 430 430 453 411 411 433 430 430 453 412 412 434 412 412 434 430 430 453 431 431 454 412 412 434 431 431 454 413 413 435 413 413 435 431 431 454 414 414 455 413 413 435 414 414 455 396 396 436 414 414 437 432 432 456 433 433 457 414 414 437 433 433 457 415 415 438 415 415 438 433 433 457 434 434 458 415 415 438 434 434 458 416 416 439 416 416 439 434 434 458 435 435 459 416 416 439 435 435 459 417 417 440 417 417 440 435 435 459 436 436 460 417 417 440 436 436 460 418 418 441 418 418 441 436 436 460 437 437 461 418 418 441 437 437 461 419 419 442 419 419 442 437 437 461 438 438 462 419 419 442 438 438 462 420 420 443 420 420 443 438 438 462 439 439 463 420 420 443 439 439 463 421 421 444 421 421 444 439 439 463 440 440 464 421 421 444 440 440 464 422 422 445 422 422 445 440 440 464 441 441 465 422 422 445 441 441 465 423 423 446 423 423 446 441 441 465 442 442 466 423 423 446 442 442 466 424 424 447 424 424 447 442 442 466 443 443 467 424 424 447 443 443 467 425 425 448 425 425 448 443 443 467 444 444 468 425 425 448 444 444 468 426 426 449 426 426 449 444 444 468 445 445 469 426 426 449 445 445 469 427 427 450 427 427 450 445 445 469 446 446 470 427 427 450 446 446 470 428 428 451 428 428 451 446 446 470 447 447 471 428 428 451 447 447 471 429 429 452 429 429 452 447 447 471 448 448 472 429 429 452 448 448 472 430 430 453 430 430 453 448 448 472 449 449 473 430 430 453 449 449 473 431 431 454 431 431 454 449 449 473 432 432 474 431 431 454 432 432 474 414 414 455 432 432 456 450 450 475 451 451 476 432 432 456 451 451 476 433 433 457 433 433 457 451 451 476 452 452 477 433 433 457 452 452 477 434 434 458 434 434 458 452 452 477 453 453 478 434 434 458 453 453 478 435 435 459 435 435 459 453 453 478 454 454 479 435 435 459 454 454 479 436 436 460 436 436 460 454 454 479 455 455 480 436 436 460 455 455 480 437 437 461 437 437 461 455 455 480 456 456 481 437 437 461 456 456 481 438 438 462 438 438 462 456 456 481 457 457 482 438 438 462 457 457 482 439 439 463 439 439 463 457 457 482 458 458 483 439 439 463 458 458 483 440 440 464 440 440 464 458 458 483 459 459 484 440 440 464 459 459 484 441 441 465 441 441 465 459 459 484 460 460 485 441 441 465 460 460 485 442 442 466 442 442 466 460 460 485 461 461 486 442 442 466 461 461 486 443 443 467 443 443 467 461 461 486 462 462 487 443 443 467 462 462 487 444 444 468 444 444 468 462 462 487 463 463 488 444 444 468 463 463 488 445 445 469 445 445 469 463 463 488 464 464 489 445 445 469 464 464 489 446 446 470 446 446 470 464 464 489 465 465 490 446 446 470 465 465 490 447 447 471 447 447 471 465 465 490 466 466 491 447 447 471 466 466 491 448 448 472 448 448 472 466 466 491 467 467 492 448 448 472 467 467 492 449 449 473 449 449 473 467 467 492 450 450 493 449 449 473 450 450 493 432 432 474 450 450 475 468 468 494 469 469 495 450 450 475 469 469 495 451 451 476 451 451 476 469 469 495 470 470 496 451 451 476 470 470 496 452 452 477 452 452 477 470 470 496 471 471 497 452 452 477 471 471 497 453 453 478 453 453 478 471 471 497 472 472 498 453 453 478 472 472 498 454 454 479 454 454 479 472 472 498 473 473 499 454 454 479 473 473 499 455 455 480 455 455 480 473 473 499 474 474 500 455 455 480 474 474 500 456 456 481 456 456 481 474 474 500 475 475 501 456 456 481 475 475 501 457 457 482 457 457 482 475 475 501 476 476 502 457 457 482 476 476 502 458 458 483 458 458 483 476 476 502 477 477 503 458 458 483 477 477 503 459 459 484 459 459 484 477 477 503 478 478 504 459 459 484 478 478 504 460 460 485 460 460 485 478 478 504 479 479 505 460 460 485 479 479 505 461 461 486 461 461 486 479 479 505 480 480 506 461 461 486 480 480 506 462 462 487 462 462 487 480 480 506 481 481 507 462 462 487 481 481 507 463 463 488 463 463 488 481 481 507 482 482 508 463 463 488 482 482 508 464 464 489 464 464 489 482 482 508 483 483 509 464 464 489 483 483 509 465 465 490 465 465 490 483 483 509 484 484 510 465 465 490 484 484 510 466 466 491 466 466 491 484 484 510 485 485 511 466 466 491 485 485 511 467 467 492 467 467 492 485 485 511 468 468 512 467 467 492 468 468 512 450 450 493 468 468 494 486 486 513 487 487 514 468 468 494 487 487 514 469 469 495 469 469 495 487 487 514 488 488 515 469 469 495 488 488 515 470 470 496 470 470 496 488 488 515 489 489 516 470 470 496 489 489 516 471 471 497 471 471 497 489 489 516 490 490 517 471 471 497 490 490 517 472 472 498 472 472 498 490 490 517 491 491 518 472 472 498 491 491 518 473 473 499 473 473 499 491 491 518 492 492 519 473 473 499 492 492 519 474 474 500 474 474 500 492 492 519 493 493 520 474 474 500 493 493 520 475 475 501 475 475 501 493 493 520 494 494 521 475 475 501 494 494 521 476 476 502 476 476 502 494 494 521 495 495 522 476 476 502 495 495 522 477 477 503 477 477 503 495 495 522 496 496 523 477 477 503 496 496 523 478 478 504 478 478 504 496 496 523 497 497 524 478 478 504 497 497 524 479 479 505 479 479 505 497 497 524 498 498 525 479 479 505 498 498 525 480 480 506 480 480 506 498 498 525 499 499 526 480 480 506 499 499 526 481 481 507 481 481 507 499 499 526 500 500 527 481 481 507 500 500 527 482 482 508 482 482 508 500 500 527 501 501 528 482 482 508 501 501 528 483 483 509 483 483 509 501 501 528 502 502 529 483 483 509 502 502 529 484 484 510 484 484 510 502 502 529 503 503 530 484 484 510 503 503 530 485 485 511 485 485 511 503 503 530 486 486 531 485 485 511 486 486 531 468 468 512 486 486 513 504 504 532 505 505 533 486 486 513 505 505 533 487 487 514 487 487 514 505 505 533 506 506 534 487 487 514 506 506 534 488 488 515 488 488 515 506 506 534 507 507 535 488 488 515 507 507 535 489 489 516 489 489 516 507 507 535 508 508 536 489 489 516 508 508 536 490 490 517 490 490 517 508 508 536 509 509 537 490 490 517 509 509 537 491 491 518 491 491 518 509 509 537 510 510 538 491 491 518 510 510 538 492 492 519 492 492 519 510 510 538 511 511 539 492 492 519 511 511 539 493 493 520 493 493 520 511 511 539 512 512 540 493 493 520 512 512 540 494 494 521 494 494 521 512 512 540 513 513 541 494 494 521 513 513 541 495 495 522 495 495 522 513 513 541 514 514 542 495 495 522 514 514 542 496 496 523 496 496 523 514 514 542 515 515 543 496 496 523 515 515 543 497 497 524 497 497 524 515 515 543 516 516 544 497 497 524 516 516 544 498 498 525 498 498 525 516 516 544 517 517 545 498 498 525 517 517 545 499 499 526 499 499 526 517 517 545 518 518 546 499 499 526 518 518 546 500 500 527 500 500 527 518 518 546 519 519 547 500 500 527 519 519 547 501 501 528 501 501 528 519 519 547 520 520 548 501 501 528 520 520 548 502 502 529 502 502 529 520 520 548 521 521 549 502 502 529 521 521 549 503 503 530 503 503 530 521 521 549 504 504 550 503 503 530 504 504 550 486 486 531 504 504 532 522 522 551 523 523 552 504 504 532 523 523 552 505 505 533 505 505 533 523 523 552 524 524 553 505 505 533 524 524 553 506 506 534 506 506 534 524 524 553 525 525 554 506 506 534 525 525 554 507 507 535 507 507 535 525 525 554 526 526 555 507 507 535 526 526 555 508 508 536 508 508 536 526 526 555 527 527 556 508 508 536 527 527 556 509 509 537 509 509 537 527 527 556 528 528 557 509 509 537 528 528 557 510 510 538 510 510 538 528 528 557 529 529 558 510 510 538 529 529 558 511 511 539 511 511 539 529 529 558 530 530 559 511 511 539 530 530 559 512 512 540 512 512 540 530 530 559 531 531 560 512 512 540 531 531 560 513 513 541 513 513 541 531 531 560 532 532 561 513 513 541 532 532 561 514 514 542 514 514 542 532 532 561 533 533 562 514 514 542 533 533 562 515 515 543 515 515 543 533 533 562 534 534 563 515 515 543 534 534 563 516 516 544 516 516 544 534 534 563 535 535 564 516 516 544 535 535 564 517 517 545 517 517 545 535 535 564 536 536 565 517 517 545 536 536 565 518 518 546 518 518 546 536 536 565 537 537 566 518 518 546 537 537 566 519 519 547 519 519 547 537 537 566 538 538 567 519 519 547 538 538 567 520 520 548 520 520 548 538 538 567 539 539 568 520 520 548 539 539 568 521 521 549 521 521 549 539 539 568 522 522 569 521 521 549 522 522 569 504 504 550 522 522 551 540 540 570 541 541 571 522 522 551 541 541 571 523 523 552 523 523 552 541 541 571 542 542 572 523 523 552 542 542 572 524 524 553 524 524 553 542 542 572 543 543 573 524 524 553 543 543 573 525 525 554 525 525 554 543 543 573 544 544 574 525 525 554 544 544 574 526 526 555 526 526 555 544 544 574 545 545 575 526 526 555 545 545 575 527 527 556 527 527 556 545 545 575 546 546 576 527 527 556 546 546 576 528 528 557 528 528 557 546 546 576 547 547 577 528 528 557 547 547 577 529 529 558 529 529 558 547 547 577 548 548 578 529 529 558 548 548 578 530 530 559 530 530 559 548 548 578 549 549 579 530 530 559 549 549 579 531 531 560 531 531 560 549 549 579 550 550 580 531 531 560 550 550 580 532 532 561 532 532 561 550 550 580 551 551 581 532 532 561 551 551 581 533 533 562 533 533 562 551 551 581 552 552 582 533 533 562 552 552 582 534 534 563 534 534 563 552 552 582 553 553 583 534 534 563 553 553 583 535 535 564 535 535 564 553 553 583 554 554 584 535 535 564 554 554 584 536 536 565 536 536 565 554 554 584 555 555 585 536 536 565 555 555 585 537 537 566 537 537 566 555 555 585 556 556 586 537 537 566 556 556 586 538 538 567 538 538 567 556 556 586 557 557 587 538 538 567 557 557 587 539 539 568 539 539 568 557 557 587 540 540 588 539 539 568 540 540 588 522 522 569 540 540 570 558 558 589 559 559 590 540 540 570 559 559 590 541 541 571 541 541 571 559 559 590 560 560 591 541 541 571 560 560 591 542 542 572 542 542 572 560 560 591 561 561 592 542 542 572 561 561 592 543 543 573 543 543 573 561 561 592 562 562 593 543 543 573 562 562 593 544 544 574 544 544 574 562 562 593 563 563 594 544 544 574 563 563 594 545 545 575 545 545 575 563 563 594 564 564 595 545 545 575 564 564 595 546 546 576 546 546 576 564 564 595 565 565 596 546 546 576 565 565 596 547 547 577 547 547 577 565 565 596 566 566 597 547 547 577 566 566 597 548 548 578 548 548 578 566 566 597 567 567 598 548 548 578 567 567 598 549 549 579 549 549 579 567 567 598 568 568 599 549 549 579 568 568 599 550 550 580 550 550 580 568 568 599 569 569 600 550 550 580 569 569 600 551 551 581 551 551 581 569 569 600 570 570 601 551 551 581 570 570 601 552 552 582 552 552 582 570 570 601 571 571 602 552 552 582 571 571 602 553 553 583 553 553 583 571 571 602 572 572 603 553 553 583 572 572 603 554 554 584 554 554 584 572 572 603 573 573 604 554 554 584 573 573 604 555 555 585 555 555 585 573 573 604 574 574 605 555 555 585 574 574 605 556 556 586 556 556 586 574 574 605 575 575 606 556 556 586 575 575 606 557 557 587 557 557 587 575 575 606 558 558 607 557 557 587 558 558 607 540 540 588 558 558 589 576 576 608 577 577 609 558 558 589 577 577 609 559 559 590 559 559 590 577 577 609 578 578 610 559 559 590 578 578 610 560 560 591 560 560 591 578 578 610 579 579 611 560 560 591 579 579 611 561 561 592 561 561 592 579 579 611 580 580 612 561 561 592 580 580 612 562 562 593 562 562 593 580 580 612 581 581 613 562 562 593 581 581 613 563 563 594 563 563 594 581 581 613 582 582 614 563 563 594 582 582 614 564 564 595 564 564 595 582 582 614 583 583 615 564 564 595 583 583 615 565 565 596 565 565 596 583 583 615 584 584 616 565 565 596 584 584 616 566 566 597 566 566 597 584 584 616 585 585 617 566 566 597 585 585 617 567 567 598 567 567 598 585 585 617 586 586 618 567 567 598 586 586 618 568 568 599 568 568 599 586 586 618 587 587 619 568 568 599 587 587 619 569 569 600 569 569 600 587 587 619 588 588 620 569 569 600 588 588 620 570 570 601 570 570 601 588 588 620 589 589 621 570 570 601 589 589 621 571 571 602 571 571 602 589 589 621 590 590 622 571 571 602 590 590 622 572 572 603 572 572 603 590 590 622 591 591 623 572 572 603 591 591 623 573 573 604 573 573 604 591 591 623 592 592 624 573 573 604 592 592 624 574 574 605 574 574 605 592 592 624 593 593 625 574 574 605 593 593 625 575 575 606 575 575 606 593 593 625 576 576 626 575 575 606 576 576 626 558 558 607 576 576 608 594 594 627 595 595 628 576 576 608 595 595 628 577 577 609 577 577 609 595 595 628 596 596 629 577 577 609 596 596 629 578 578 610 578 578 610 596 596 629 597 597 630 578 578 610 597 597 630 579 579 611 579 579 611 597 597 630 598 598 631 579 579 611 598 598 631 580 580 612 580 580 612 598 598 631 599 599 632 580 580 612 599 599 632 581 581 613 581 581 613 599 599 632 600 600 633 581 581 613 600 600 633 582 582 614 582 582 614 600 600 633 601 601 634 582 582 614 601 601 634 583 583 615 583 583 615 601 601 634 602 602 635 583 583 615 602 602 635 584 584 616 584 584 616 602 602 635 603 603 636 584 584 616 603 603 636 585 585 617 585 585 617 603 603 636 604 604 637 585 585 617 604 604 637 586 586 618 586 586 618 604 604 637 605 605 638 586 586 618 605 605 638 587 587 619 587 587 619 605 605 638 606 606 639 587 587 619 606 606 639 588 588 620 588 588 620 606 606 639 607 607 640 588 588 620 607 607 640 589 589 621 589 589 621 607 607 640 608 608 641 589 589 621 608 608 641 590 590 622 590 590 622 608 608 641 609 609 642 590 590 622 609 609 642 591 591 623 591 591 623 609 609 642 610 610 643 591 591 623 610 610 643 592 592 624 592 592 624 610 610 643 611 611 644 592 592 624 611 611 644 593 593 625 593 593 625 611 611 644 594 594 645 593 593 625 594 594 645 576 576 626 594 594 627 612 612 646 613 613 647 594 594 627 613 613 647 595 595 628 595 595 628 613 613 647 614 614 648 595 595 628 614 614 648 596 596 629 596 596 629 614 614 648 615 615 649 596 596 629 615 615 649 597 597 630 597 597 630 615 615 649 616 616 650 597 597 630 616 616 650 598 598 631 598 598 631 616 616 650 617 617 651 598 598 631 617 617 651 599 599 632 599 599 632 617 617 651 618 618 652 599 599 632 618 618 652 600 600 633 600 600 633 618 618 652 619 619 653 600 600 633 619 619 653 601 601 634 601 601 634 619 619 653 620 620 654 601 601 634 620 620 654 602 602 635 602 602 635 620 620 654 621 621 655 602 602 635 621 621 655 603 603 636 603 603 636 621 621 655 622 622 656 603 603 636 622 622 656 604 604 637 604 604 637 622 622 656 623 623 657 604 604 637 623 623 657 605 605 638 605 605 638 623 623 657 624 624 658 605 605 638 624 624 658 606 606 639 606 606 639 624 624 658 625 625 659 606 606 639 625 625 659 607 607 640 607 607 640 625 625 659 626 626 660 607 607 640 626 626 660 608 608 641 608 608 641 626 626 660 627 627 661 608 608 641 627 627 661 609 609 642 609 609 642 627 627 661 628 628 662 609 609 642 628 628 662 610 610 643 610 610 643 628 628 662 629 629 663 610 610 643 629 629 663 611 611 644 611 611 644 629 629 663 612 612 664 611 611 644 612 612 664 594 594 645 612 612 646 630 630 665 631 631 666 612 612 646 631 631 666 613 613 647 613 613 647 631 631 666 632 632 667 613 613 647 632 632 667 614 614 648 614 614 648 632 632 667 633 633 668 614 614 648 633 633 668 615 615 649 615 615 649 633 633 668 634 634 669 615 615 649 634 634 669 616 616 650 616 616 650 634 634 669 635 635 670 616 616 650 635 635 670 617 617 651 617 617 651 635 635 670 636 636 671 617 617 651 636 636 671 618 618 652 618 618 652 636 636 671 637 637 672 618 618 652 637 637 672 619 619 653 619 619 653 637 637 672 638 638 673 619 619 653 638 638 673 620 620 654 620 620 654 638 638 673 639 639 674 620 620 654 639 639 674 621 621 655 621 621 655 639 639 674 640 640 675 621 621 655 640 640 675 622 622 656 622 622 656 640 640 675 641 641 676 622 622 656 641 641 676 623 623 657 623 623 657 641 641 676 642 642 677 623 623 657 642 642 677 624 624 658 624 624 658 642 642 677 643 643 678 624 624 658 643 643 678 625 625 659 625 625 659 643 643 678 644 644 679 625 625 659 644 644 679 626 626 660 626 626 660 644 644 679 645 645 680 626 626 660 645 645 680 627 627 661 627 627 661 645 645 680 646 646 681 627 627 661 646 646 681 628 628 662 628 628 662 646 646 681 647 647 682 628 628 662 647 647 682 629 629 663 629 629 663 647 647 682 630 630 683 629 629 663 630 630 683 612 612 664 630 630 665 648 648 684 649 649 685 630 630 665 649 649 685 631 631 666 631 631 666 649 649 685 650 650 686 631 631 666 650 650 686 632 632 667 632 632 667 650 650 686 651 651 687 632 632 667 651 651 687 633 633 668 633 633 668 651 651 687 652 652 688 633 633 668 652 652 688 634 634 669 634 634 669 652 652 688 653 653 689 634 634 669 653 653 689 635 635 670 635 635 670 653 653 689 654 654 690 635 635 670 654 654 690 636 636 671 636 636 671 654 654 690 655 655 691 636 636 671 655 655 691 637 637 672 637 637 672 655 655 691 656 656 692 637 637 672 656 656 692 638 638 673 638 638 673 656 656 692 657 657 693 638 638 673 657 657 693 639 639 674 639 639 674 657 657 693 658 658 694 639 639 674 658 658 694 640 640 675 640 640 675 658 658 694 659 659 695 640 640 675 659 659 695 641 641 676 641 641 676 659 659 695 660 660 696 641 641 676 660 660 696 642 642 677 642 642 677 660 660 696 661 661 697 642 642 677 661 661 697 643 643 678 643 643 678 661 661 697 662 662 698 643 643 678 662 662 698 644 644 679 644 644 679 662 662 698 663 663 699 644 644 679 663 663 699 645 645 680 645 645 680 663 663 699 664 664 700 645 645 680 664 664 700 646 646 681 646 646 681 664 664 700 665 665 701 646 646 681 665 665 701 647 647 682 647 647 682 665 665 701 648 648 702 647 647 682 648 648 702 630 630 683 648 648 684 666 666 703 667 667 704 648 648 684 667 667 704 649 649 685 649 649 685 667 667 704 668 668 705 649 649 685 668 668 705 650 650 686 650 650 686 668 668 705 669 669 706 650 650 686 669 669 706 651 651 687 651 651 687 669 669 706 670 670 707 651 651 687 670 670 707 652 652 688 652 652 688 670 670 707 671 671 708 652 652 688 671 671 708 653 653 689 653 653 689 671 671 708 672 672 709 653 653 689 672 672 709 654 654 690 654 654 690 672 672 709 673 673 710 654 654 690 673 673 710 655 655 691 655 655 691 673 673 710 674 674 711 655 655 691 674 674 711 656 656 692 656 656 692 674 674 711 675 675 712 656 656 692 675 675 712 657 657 693 657 657 693 675 675 712 676 676 713 657 657 693 676 676 713 658 658 694 658 658 694 676 676 713 677 677 714 658 658 694 677 677 714 659 659 695 659 659 695 677 677 714 678 678 715 659 659 695 678 678 715 660 660 696 660 660 696 678 678 715 679 679 716 660 660 696 679 679 716 661 661 697 661 661 697 679 679 716 680 680 717 661 661 697 680 680 717 662 662 698 662 662 698 680 680 717 681 681 718 662 662 698 681 681 718 663 663 699 663 663 699 681 681 718 682 682 719 663 663 699 682 682 719 664 664 700 664 664 700 682 682 719 683 683 720 664 664 700 683 683 720 665 665 701 665 665 701 683 683 720 666 666 721 665 665 701 666 666 721 648 648 702 666 666 703 684 684 722 685 685 723 666 666 703 685 685 723 667 667 704 667 667 704 685 685 723 686 686 724 667 667 704 686 686 724 668 668 705 668 668 705 686 686 724 687 687 725 668 668 705 687 687 725 669 669 706 669 669 706 687 687 725 688 688 726 669 669 706 688 688 726 670 670 707 670 670 707 688 688 726 689 689 727 670 670 707 689 689 727 671 671 708 671 671 708 689 689 727 690 690 728 671 671 708 690 690 728 672 672 709 672 672 709 690 690 728 691 691 729 672 672 709 691 691 729 673 673 710 673 673 710 691 691 729 692 692 730 673 673 710 692 692 730 674 674 711 674 674 711 692 692 730 693 693 731 674 674 711 693 693 731 675 675 712 675 675 712 693 693 731 694 694 732 675 675 712 694 694 732 676 676 713 676 676 713 694 694 732 695 695 733 676 676 713 695 695 733 677 677 714 677 677 714 695 695 733 696 696 734 677 677 714 696 696 734 678 678 715 678 678 715 696 696 734 697 697 735 678 678 715 697 697 735 679 679 716 679 679 716 697 697 735 698 698 736 679 679 716 698 698 736 680 680 717 680 680 717 698 698 736 699 699 737 680 680 717 699 699 737 681 681 718 681 681 718 699 699 737 700 700 738 681 681 718 700 700 738 682 682 719 682 682 719 700 700 738 701 701 739 682 682 719 701 701 739 683 683 720 683 683 720 701 701 739 684 684 740 683 683 720 684 684 740 666 666 721 684 684 722 702 702 741 703 703 742 684 684 722 703 703 742 685 685 723 685 685 723 703 703 742 704 704 743 685 685 723 704 704 743 686 686 724 686 686 724 704 704 743 705 705 744 686 686 724 705 705 744 687 687 725 687 687 725 705 705 744 706 706 745 687 687 725 706 706 745 688 688 726 688 688 726 706 706 745 707 707 746 688 688 726 707 707 746 689 689 727 689 689 727 707 707 746 708 708 747 689 689 727 708 708 747 690 690 728 690 690 728 708 708 747 709 709 748 690 690 728 709 709 748 691 691 729 691 691 729 709 709 748 710 710 749 691 691 729 710 710 749 692 692 730 692 692 730 710 710 749 711 711 750 692 692 730 711 711 750 693 693 731 693 693 731 711 711 750 712 712 751 693 693 731 712 712 751 694 694 732 694 694 732 712 712 751 713 713 752 694 694 732 713 713 752 695 695 733 695 695 733 713 713 752 714 714 753 695 695 733 714 714 753 696 696 734 696 696 734 714 714 753 715 715 754 696 696 734 715 715 754 697 697 735 697 697 735 715 715 754 716 716 755 697 697 735 716 716 755 698 698 736 698 698 736 716 716 755 717 717 756 698 698 736 717 717 756 699 699 737 699 699 737 717 717 756 718 718 757 699 699 737 718 718 757 700 700 738 700 700 738 718 718 757 719 719 758 700 700 738 719 719 758 701 701 739 701 701 739 719 719 758 702 702 759 701 701 739 702 702 759 684 684 740 702 702 741 720 720 760 721 721 761 702 702 741 721 721 761 703 703 742 703 703 742 721 721 761 722 722 762 703 703 742 722 722 762 704 704 743 704 704 743 722 722 762 723 723 763 704 704 743 723 723 763 705 705 744 705 705 744 723 723 763 724 724 764 705 705 744 724 724 764 706 706 745 706 706 745 724 724 764 725 725 765 706 706 745 725 725 765 707 707 746 707 707 746 725 725 765 726 726 766 707 707 746 726 726 766 708 708 747 708 708 747 726 726 766 727 727 767 708 708 747 727 727 767 709 709 748 709 709 748 727 727 767 728 728 768 709 709 748 728 728 768 710 710 749 710 710 749 728 728 768 729 729 769 710 710 749 729 729 769 711 711 750 711 711 750 729 729 769 730 730 770 711 711 750 730 730 770 712 712 751 712 712 751 730 730 770 731 731 771 712 712 751 731 731 771 713 713 752 713 713 752 731 731 771 732 732 772 713 713 752 732 732 772 714 714 753 714 714 753 732 732 772 733 733 773 714 714 753 733 733 773 715 715 754 715 715 754 733 733 773 734 734 774 715 715 754 734 734 774 716 716 755 716 716 755 734 734 774 735 735 775 716 716 755 735 735 775 717 717 756 717 717 756 735 735 775 736 736 776 717 717 756 736 736 776 718 718 757 718 718 757 736 736 776 737 737 777 718 718 757 737 737 777 719 719 758 719 719 758 737 737 777 720 720 778 719 719 758 720 720 778 702 702 759 720 720 760 738 738 779 739 739 780 720 720 760 739 739 780 721 721 761 721 721 761 739 739 780 740 740 781 721 721 761 740 740 781 722 722 762 722 722 762 740 740 781 741 741 782 722 722 762 741 741 782 723 723 763 723 723 763 741 741 782 742 742 783 723 723 763 742 742 783 724 724 764 724 724 764 742 742 783 743 743 784 724 724 764 743 743 784 725 725 765 725 725 765 743 743 784 744 744 785 725 725 765 744 744 785 726 726 766 726 726 766 744 744 785 745 745 786 726 726 766 745 745 786 727 727 767 727 727 767 745 745 786 746 746 787 727 727 767 746 746 787 728 728 768 728 728 768 746 746 787 747 747 788 728 728 768 747 747 788 729 729 769 729 729 769 747 747 788 748 748 789 729 729 769 748 748 789 730 730 770 730 730 770 748 748 789 749 749 790 730 730 770 749 749 790 731 731 771 731 731 771 749 749 790 750 750 791 731 731 771 750 750 791 732 732 772 732 732 772 750 750 791 751 751 792 732 732 772 751 751 792 733 733 773 733 733 773 751 751 792 752 752 793 733 733 773 752 752 793 734 734 774 734 734 774 752 752 793 753 753 794 734 734 774 753 753 794 735 735 775 735 735 775 753 753 794 754 754 795 735 735 775 754 754 795 736 736 776 736 736 776 754 754 795 755 755 796 736 736 776 755 755 796 737 737 777 737 737 777 755 755 796 738 738 797 737 737 777 738 738 797 720 720 778 738 738 779 756 756 798 757 757 799 738 738 779 757 757 799 739 739 780 739 739 780 757 757 799 758 758 800 739 739 780 758 758 800 740 740 781 740 740 781 758 758 800 759 759 801 740 740 781 759 759 801 741 741 782 741 741 782 759 759 801 760 760 802 741 741 782 760 760 802 742 742 783 742 742 783 760 760 802 761 761 803 742 742 783 761 761 803 743 743 784 743 743 784 761 761 803 762 762 804 743 743 784 762 762 804 744 744 785 744 744 785 762 762 804 763 763 805 744 744 785 763 763 805 745 745 786 745 745 786 763 763 805 764 764 806 745 745 786 764 764 806 746 746 787 746 746 787 764 764 806 765 765 807 746 746 787 765 765 807 747 747 788 747 747 788 765 765 807 766 766 808 747 747 788 766 766 808 748 748 789 748 748 789 766 766 808 767 767 809 748 748 789 767 767 809 749 749 790 749 749 790 767 767 809 768 768 810 749 749 790 768 768 810 750 750 791 750 750 791 768 768 810 769 769 811 750 750 791 769 769 811 751 751 792 751 751 792 769 769 811 770 770 812 751 751 792 770 770 812 752 752 793 752 752 793 770 770 812 771 771 813 752 752 793 771 771 813 753 753 794 753 753 794 771 771 813 772 772 814 753 753 794 772 772 814 754 754 795 754 754 795 772 772 814 773 773 815 754 754 795 773 773 815 755 755 796 755 755 796 773 773 815 756 756 816 755 755 796 756 756 816 738 738 797 756 756 798 774 774 817 775 775 818 756 756 798 775 775 818 757 757 799 757 757 799 775 775 818 776 776 819 757 757 799 776 776 819 758 758 800 758 758 800 776 776 819 777 777 820 758 758 800 777 777 820 759 759 801 759 759 801 777 777 820 778 778 821 759 759 801 778 778 821 760 760 802 760 760 802 778 778 821 779 779 822 760 760 802 779 779 822 761 761 803 761 761 803 779 779 822 780 780 823 761 761 803 780 780 823 762 762 804 762 762 804 780 780 823 781 781 824 762 762 804 781 781 824 763 763 805 763 763 805 781 781 824 782 782 825 763 763 805 782 782 825 764 764 806 764 764 806 782 782 825 783 783 826 764 764 806 783 783 826 765 765 807 765 765 807 783 783 826 784 784 827 765 765 807 784 784 827 766 766 808 766 766 808 784 784 827 785 785 828 766 766 808 785 785 828 767 767 809 767 767 809 785 785 828 786 786 829 767 767 809 786 786 829 768 768 810 768 768 810 786 786 829 787 787 830 768 768 810 787 787 830 769 769 811 769 769 811 787 787 830 788 788 831 769 769 811 788 788 831 770 770 812 770 770 812 788 788 831 789 789 832 770 770 812 789 789 832 771 771 813 771 771 813 789 789 832 790 790 833 771 771 813 790 790 833 772 772 814 772 772 814 790 790 833 791 791 834 772 772 814 791 791 834 773 773 815 773 773 815 791 791 834 774 774 835 773 773 815 774 774 835 756 756 816 774 774 817 792 792 836 793 793 837 774 774 817 793 793 837 775 775 818 775 775 818 793 793 837 794 794 838 775 775 818 794 794 838 776 776 819 776 776 819 794 794 838 795 795 839 776 776 819 795 795 839 777 777 820 777 777 820 795 795 839 796 796 840 777 777 820 796 796 840 778 778 821 778 778 821 796 796 840 797 797 841 778 778 821 797 797 841 779 779 822 779 779 822 797 797 841 798 798 842 779 779 822 798 798 842 780 780 823 780 780 823 798 798 842 799 799 843 780 780 823 799 799 843 781 781 824 781 781 824 799 799 843 800 800 844 781 781 824 800 800 844 782 782 825 782 782 825 800 800 844 801 801 845 782 782 825 801 801 845 783 783 826 783 783 826 801 801 845 802 802 846 783 783 826 802 802 846 784 784 827 784 784 827 802 802 846 803 803 847 784 784 827 803 803 847 785 785 828 785 785 828 803 803 847 804 804 848 785 785 828 804 804 848 786 786 829 786 786 829 804 804 848 805 805 849 786 786 829 805 805 849 787 787 830 787 787 830 805 805 849 806 806 850 787 787 830 806 806 850 788 788 831 788 788 831 806 806 850 807 807 851 788 788 831 807 807 851 789 789 832 789 789 832 807 807 851 808 808 852 789 789 832 808 808 852 790 790 833 790 790 833 808 808 852 809 809 853 790 790 833 809 809 853 791 791 834 791 791 834 809 809 853 792 792 854 791 791 834 792 792 854 774 774 835 792 792 836 810 810 855 811 811 856 792 792 836 811 811 856 793 793 837 793 793 837 811 811 856 812 812 857 793 793 837 812 812 857 794 794 838 794 794 838 812 812 857 813 813 858 794 794 838 813 813 858 795 795 839 795 795 839 813 813 858 814 814 859 795 795 839 814 814 859 796 796 840 796 796 840 814 814 859 815 815 860 796 796 840 815 815 860 797 797 841 797 797 841 815 815 860 816 816 861 797 797 841 816 816 861 798 798 842 798 798 842 816 816 861 817 817 862 798 798 842 817 817 862 799 799 843 799 799 843 817 817 862 818 818 863 799 799 843 818 818 863 800 800 844 800 800 844 818 818 863 819 819 864 800 800 844 819 819 864 801 801 845 801 801 845 819 819 864 820 820 865 801 801 845 820 820 865 802 802 846 802 802 846 820 820 865 821 821 866 802 802 846 821 821 866 803 803 847 803 803 847 821 821 866 822 822 867 803 803 847 822 822 867 804 804 848 804 804 848 822 822 867 823 823 868 804 804 848 823 823 868 805 805 849 805 805 849 823 823 868 824 824 869 805 805 849 824 824 869 806 806 850 806 806 850 824 824 869 825 825 870 806 806 850 825 825 870 807 807 851 807 807 851 825 825 870 826 826 871 807 807 851 826 826 871 808 808 852 808 808 852 826 826 871 827 827 872 808 808 852 827 827 872 809 809 853 809 809 853 827 827 872 810 810 873 809 809 853 810 810 873 792 792 854 810 810 855 828 828 874 829 829 875 810 810 855 829 829 875 811 811 856 811 811 856 829 829 875 830 830 876 811 811 856 830 830 876 812 812 857 812 812 857 830 830 876 831 831 877 812 812 857 831 831 877 813 813 858 813 813 858 831 831 877 832 832 878 813 813 858 832 832 878 814 814 859 814 814 859 832 832 878 833 833 879 814 814 859 833 833 879 815 815 860 815 815 860 833 833 879 834 834 880 815 815 860 834 834 880 816 816 861 816 816 861 834 834 880 835 835 881 816 816 861 835 835 881 817 817 862 817 817 862 835 835 881 836 836 882 817 817 862 836 836 882 818 818 863 818 818 863 836 836 882 837 837 883 818 818 863 837 837 883 819 819 864 819 819 864 837 837 883 838 838 884 819 819 864 838 838 884 820 820 865 820 820 865 838 838 884 839 839 885 820 820 865 839 839 885 821 821 866 821 821 866 839 839 885 840 840 886 821 821 866 840 840 886 822 822 867 822 822 867 840 840 886 841 841 887 822 822 867 841 841 887 823 823 868 823 823 868 841 841 887 842 842 888 823 823 868 842 842 888 824 824 869 824 824 869 842 842 888 843 843 889 824 824 869 843 843 889 825 825 870 825 825 870 843 843 889 844 844 890 825 825 870 844 844 890 826 826 871 826 826 871 844 844 890 845 845 891 826 826 871 845 845 891 827 827 872 827 827 872 845 845 891 828 828 892 827 827 872 828 828 892 810 810 873 828 828 874 846 846 893 847 847 894 828 828 874 847 847 894 829 829 875 829 829 875 847 847 894 848 848 895 829 829 875 848 848 895 830 830 876 830 830 876 848 848 895 849 849 896 830 830 876 849 849 896 831 831 877 831 831 877 849 849 896 850 850 897 831 831 877 850 850 897 832 832 878 832 832 878 850 850 897 851 851 898 832 832 878 851 851 898 833 833 879 833 833 879 851 851 898 852 852 899 833 833 879 852 852 899 834 834 880 834 834 880 852 852 899 853 853 900 834 834 880 853 853 900 835 835 881 835 835 881 853 853 900 854 854 901 835 835 881 854 854 901 836 836 882 836 836 882 854 854 901 855 855 902 836 836 882 855 855 902 837 837 883 837 837 883 855 855 902 856 856 903 837 837 883 856 856 903 838 838 884 838 838 884 856 856 903 857 857 904 838 838 884 857 857 904 839 839 885 839 839 885 857 857 904 858 858 905 839 839 885 858 858 905 840 840 886 840 840 886 858 858 905 859 859 906 840 840 886 859 859 906 841 841 887 841 841 887 859 859 906 860 860 907 841 841 887 860 860 907 842 842 888 842 842 888 860 860 907 861 861 908 842 842 888 861 861 908 843 843 889 843 843 889 861 861 908 862 862 909 843 843 889 862 862 909 844 844 890 844 844 890 862 862 909 863 863 910 844 844 890 863 863 910 845 845 891 845 845 891 863 863 910 846 846 911 845 845 891 846 846 911 828 828 892 846 846 893 864 864 912 865 865 913 846 846 893 865 865 913 847 847 894 847 847 894 865 865 913 866 866 914 847 847 894 866 866 914 848 848 895 848 848 895 866 866 914 867 867 915 848 848 895 867 867 915 849 849 896 849 849 896 867 867 915 868 868 916 849 849 896 868 868 916 850 850 897 850 850 897 868 868 916 869 869 917 850 850 897 869 869 917 851 851 898 851 851 898 869 869 917 870 870 918 851 851 898 870 870 918 852 852 899 852 852 899 870 870 918 871 871 919 852 852 899 871 871 919 853 853 900 853 853 900 871 871 919 872 872 920 853 853 900 872 872 920 854 854 901 854 854 901 872 872 920 873 873 921 854 854 901 873 873 921 855 855 902 855 855 902 873 873 921 874 874 922 855 855 902 874 874 922 856 856 903 856 856 903 874 874 922 875 875 923 856 856 903 875 875 923 857 857 904 857 857 904 875 875 923 876 876 924 857 857 904 876 876 924 858 858 905 858 858 905 876 876 924 877 877 925 858 858 905 877 877 925 859 859 906 859 859 906 877 877 925 878 878 926 859 859 906 878 878 926 860 860 907 860 860 907 878 878 926 879 879 927 860 860 907 879 879 927 861 861 908 861 861 908 879 879 927 880 880 928 861 861 908 880 880 928 862 862 909 862 862 909 880 880 928 881 881 929 862 862 909 881 881 929 863 863 910 863 863 910 881 881 929 864 864 930 863 863 910 864 864 930 846 846 911 864 864 912 882 882 931 883 883 932 864 864 912 883 883 932 865 865 913 865 865 913 883 883 932 884 884 933 865 865 913 884 884 933 866 866 914 866 866 914 884 884 933 885 885 934 866 866 914 885 885 934 867 867 915 867 867 915 885 885 934 886 886 935 867 867 915 886 886 935 868 868 916 868 868 916 886 886 935 887 887 936 868 868 916 887 887 936 869 869 917 869 869 917 887 887 936 888 888 937 869 869 917 888 888 937 870 870 918 870 870 918 888 888 937 889 889 938 870 870 918 889 889 938 871 871 919 871 871 919 889 889 938 890 890 939 871 871 919 890 890 939 872 872 920 872 872 920 890 890 939 891 891 940 872 872 920 891 891 940 873 873 921 873 873 921 891 891 940 892 892 941 873 873 921 892 892 941 874 874 922 874 874 922 892 892 941 893 893 942 874 874 922 893 893 942 875 875 923 875 875 923 893 893 942 894 894 943 875 875 923 894 894 943 876 876 924 876 876 924 894 894 943 895 895 944 876 876 924 895 895 944 877 877 925 877 877 925 895 895 944 896 896 945 877 877 925 896 896 945 878 878 926 878 878 926 896 896 945 897 897 946 878 878 926 897 897 946 879 879 927 879 879 927 897 897 946 898 898 947 879 879 927 898 898 947 880 880 928 880 880 928 898 898 947 899 899 948 880 880 928 899 899 948 881 881 929 881 881 929 899 899 948 882 882 949 881 881 929 882 882 949 864 864 930 882 882 931 900 900 950 901 901 951 882 882 931 901 901 951 883 883 932 883 883 932 901 901 951 902 902 952 883 883 932 902 902 952 884 884 933 884 884 933 902 902 952 903 903 953 884 884 933 903 903 953 885 885 934 885 885 934 903 903 953 904 904 954 885 885 934 904 904 954 886 886 935 886 886 935 904 904 954 905 905 955 886 886 935 905 905 955 887 887 936 887 887 936 905 905 955 906 906 956 887 887 936 906 906 956 888 888 937 888 888 937 906 906 956 907 907 957 888 888 937 907 907 957 889 889 938 889 889 938 907 907 957 908 908 958 889 889 938 908 908 958 890 890 939 890 890 939 908 908 958 909 909 959 890 890 939 909 909 959 891 891 940 891 891 940 909 909 959 910 910 960 891 891 940 910 910 960 892 892 941 892 892 941 910 910 960 911 911 961 892 892 941 911 911 961 893 893 942 893 893 942 911 911 961 912 912 962 893 893 942 912 912 962 894 894 943 894 894 943 912 912 962 913 913 963 894 894 943 913 913 963 895 895 944 895 895 944 913 913 963 914 914 964 895 895 944 914 914 964 896 896 945 896 896 945 914 914 964 915 915 965 896 896 945 915 915 965 897 897 946 897 897 946 915 915 965 916 916 966 897 897 946 916 916 966 898 898 947 898 898 947 916 916 966 917 917 967 898 898 947 917 917 967 899 899 948 899 899 948 917 917 967 900 900 968 899 899 948 900 900 968 882 882 949 900 900 950 918 918 969 919 919 970 900 900 950 919 919 970 901 901 951 901 901 951 919 919 970 920 920 971 901 901 951 920 920 971 902 902 952 902 902 952 920 920 971 921 921 972 902 902 952 921 921 972 903 903 953 903 903 953 921 921 972 922 922 973 903 903 953 922 922 973 904 904 954 904 904 954 922 922 973 923 923 974 904 904 954 923 923 974 905 905 955 905 905 955 923 923 974 924 924 975 905 905 955 924 924 975 906 906 956 906 906 956 924 924 975 925 925 976 906 906 956 925 925 976 907 907 957 907 907 957 925 925 976 926 926 977 907 907 957 926 926 977 908 908 958 908 908 958 926 926 977 927 927 978 908 908 958 927 927 978 909 909 959 909 909 959 927 927 978 928 928 979 909 909 959 928 928 979 910 910 960 910 910 960 928 928 979 929 929 980 910 910 960 929 929 980 911 911 961 911 911 961 929 929 980 930 930 981 911 911 961 930 930 981 912 912 962 912 912 962 930 930 981 931 931 982 912 912 962 931 931 982 913 913 963 913 913 963 931 931 982 932 932 983 913 913 963 932 932 983 914 914 964 914 914 964 932 932 983 933 933 984 914 914 964 933 933 984 915 915 965 915 915 965 933 933 984 934 934 985 915 915 965 934 934 985 916 916 966 916 916 966 934 934 985 935 935 986 916 916 966 935 935 986 917 917 967 917 917 967 935 935 986 918 918 987 917 917 967 918 918 987 900 900 968 918 918 969 936 936 988 937 937 989 918 918 969 937 937 989 919 919 970 919 919 970 937 937 989 938 938 990 919 919 970 938 938 990 920 920 971 920 920 971 938 938 990 939 939 991 920 920 971 939 939 991 921 921 972 921 921 972 939 939 991 940 940 992 921 921 972 940 940 992 922 922 973 922 922 973 940 940 992 941 941 993 922 922 973 941 941 993 923 923 974 923 923 974 941 941 993 942 942 994 923 923 974 942 942 994 924 924 975 924 924 975 942 942 994 943 943 995 924 924 975 943 943 995 925 925 976 925 925 976 943 943 995 944 944 996 925 925 976 944 944 996 926 926 977 926 926 977 944 944 996 945 945 997 926 926 977 945 945 997 927 927 978 927 927 978 945 945 997 946 946 998 927 927 978 946 946 998 928 928 979 928 928 979 946 946 998 947 947 999 928 928 979 947 947 999 929 929 980 929 929 980 947 947 999 948 948 1000 929 929 980 948 948 1000 930 930 981 930 930 981 948 948 1000 949 949 1001 930 930 981 949 949 1001 931 931 982 931 931 982 949 949 1001 950 950 1002 931 931 982 950 950 1002 932 932 983 932 932 983 950 950 1002 951 951 1003 932 932 983 951 951 1003 933 933 984 933 933 984 951 951 1003 952 952 1004 933 933 984 952 952 1004 934 934 985 934 934 985 952 952 1004 953 953 1005 934 934 985 953 953 1005 935 935 986 935 935 986 953 953 1005 936 936 1006 935 935 986 936 936 1006 918 918 987 936 936 988 954 954 1007 955 955 1008 936 936 988 955 955 1008 937 937 989 937 937 989 955 955 1008 956 956 1009 937 937 989 956 956 1009 938 938 990 938 938 990 956 956 1009 957 957 1010 938 938 990 957 957 1010 939 939 991 939 939 991 957 957 1010 958 958 1011 939 939 991 958 958 1011 940 940 992 940 940 992 958 958 1011 959 959 1012 940 940 992 959 959 1012 941 941 993 941 941 993 959 959 1012 960 960 1013 941 941 993 960 960 1013 942 942 994 942 942 994 960 960 1013 961 961 1014 942 942 994 961 961 1014 943 943 995 943 943 995 961 961 1014 962 962 1015 943 943 995 962 962 1015 944 944 996 944 944 996 962 962 1015 963 963 1016 944 944 996 963 963 1016 945 945 997 945 945 997 963 963 1016 964 964 1017 945 945 997 964 964 1017 946 946 998 946 946 998 964 964 1017 965 965 1018 946 946 998 965 965 1018 947 947 999 947 947 999 965 965 1018 966 966 1019 947 947 999 966 966 1019 948 948 1000 948 948 1000 966 966 1019 967 967 1020 948 948 1000 967 967 1020 949 949 1001 949 949 1001 967 967 1020 968 968 1021 949 949 1001 968 968 1021 950 950 1002 950 950 1002 968 968 1021 969 969 1022 950 950 1002 969 969 1022 951 951 1003 951 951 1003 969 969 1022 970 970 1023 951 951 1003 970 970 1023 952 952 1004 952 952 1004 970 970 1023 971 971 1024 952 952 1004 971 971 1024 953 953 1005 953 953 1005 971 971 1024 954 954 1025 953 953 1005 954 954 1025 936 936 1006 954 954 1007 972 972 1026 973 973 1027 954 954 1007 973 973 1027 955 955 1008 955 955 1008 973 973 1027 974 974 1028 955 955 1008 974 974 1028 956 956 1009 956 956 1009 974 974 1028 975 975 1029 956 956 1009 975 975 1029 957 957 1010 957 957 1010 975 975 1029 976 976 1030 957 957 1010 976 976 1030 958 958 1011 958 958 1011 976 976 1030 977 977 1031 958 958 1011 977 977 1031 959 959 1012 959 959 1012 977 977 1031 978 978 1032 959 959 1012 978 978 1032 960 960 1013 960 960 1013 978 978 1032 979 979 1033 960 960 1013 979 979 1033 961 961 1014 961 961 1014 979 979 1033 980 980 1034 961 961 1014 980 980 1034 962 962 1015 962 962 1015 980 980 1034 981 981 1035 962 962 1015 981 981 1035 963 963 1016 963 963 1016 981 981 1035 982 982 1036 963 963 1016 982 982 1036 964 964 1017 964 964 1017 982 982 1036 983 983 1037 964 964 1017 983 983 1037 965 965 1018 965 965 1018 983 983 1037 984 984 1038 965 965 1018 984 984 1038 966 966 1019 966 966 1019 984 984 1038 985 985 1039 966 966 1019 985 985 1039 967 967 1020 967 967 1020 985 985 1039 986 986 1040 967 967 1020 986 986 1040 968 968 1021 968 968 1021 986 986 1040 987 987 1041 968 968 1021 987 987 1041 969 969 1022 969 969 1022 987 987 1041 988 988 1042 969 969 1022 988 988 1042 970 970 1023 970 970 1023 988 988 1042 989 989 1043 970 970 1023 989 989 1043 971 971 1024 971 971 1024 989 989 1043 972 972 1044 971 971 1024 972 972 1044 954 954 1025 972 972 1026 990 990 1045 991 991 1046 972 972 1026 991 991 1046 973 973 1027 973 973 1027 991 991 1046 992 992 1047 973 973 1027 992 992 1047 974 974 1028 974 974 1028 992 992 1047 993 993 1048 974 974 1028 993 993 1048 975 975 1029 975 975 1029 993 993 1048 994 994 1049 975 975 1029 994 994 1049 976 976 1030 976 976 1030 994 994 1049 995 995 1050 976 976 1030 995 995 1050 977 977 1031 977 977 1031 995 995 1050 996 996 1051 977 977 1031 996 996 1051 978 978 1032 978 978 1032 996 996 1051 997 997 1052 978 978 1032 997 997 1052 979 979 1033 979 979 1033 997 997 1052 998 998 1053 979 979 1033 998 998 1053 980 980 1034 980 980 1034 998 998 1053 999 999 1054 980 980 1034 999 999 1054 981 981 1035 981 981 1035 999 999 1054 1000 1000 1055 981 981 1035 1000 1000 1055 982 982 1036 982 982 1036 1000 1000 1055 1001 1001 1056 982 982 1036 1001 1001 1056 983 983 1037 983 983 1037 1001 1001 1056 1002 1002 1057 983 983 1037 1002 1002 1057 984 984 1038 984 984 1038 1002 1002 1057 1003 1003 1058 984 984 1038 1003 1003 1058 985 985 1039 985 985 1039 1003 1003 1058 1004 1004 1059 985 985 1039 1004 1004 1059 986 986 1040 986 986 1040 1004 1004 1059 1005 1005 1060 986 986 1040 1005 1005 1060 987 987 1041 987 987 1041 1005 1005 1060 1006 1006 1061 987 987 1041 1006 1006 1061 988 988 1042 988 988 1042 1006 1006 1061 1007 1007 1062 988 988 1042 1007 1007 1062 989 989 1043 989 989 1043 1007 1007 1062 990 990 1063 989 989 1043 990 990 1063 972 972 1044 990 990 1045 1008 1008 1064 1009 1009 1065 990 990 1045 1009 1009 1065 991 991 1046 991 991 1046 1009 1009 1065 1010 1010 1066 991 991 1046 1010 1010 1066 992 992 1047 992 992 1047 1010 1010 1066 1011 1011 1067 992 992 1047 1011 1011 1067 993 993 1048 993 993 1048 1011 1011 1067 1012 1012 1068 993 993 1048 1012 1012 1068 994 994 1049 994 994 1049 1012 1012 1068 1013 1013 1069 994 994 1049 1013 1013 1069 995 995 1050 995 995 1050 1013 1013 1069 1014 1014 1070 995 995 1050 1014 1014 1070 996 996 1051 996 996 1051 1014 1014 1070 1015 1015 1071 996 996 1051 1015 1015 1071 997 997 1052 997 997 1052 1015 1015 1071 1016 1016 1072 997 997 1052 1016 1016 1072 998 998 1053 998 998 1053 1016 1016 1072 1017 1017 1073 998 998 1053 1017 1017 1073 999 999 1054 999 999 1054 1017 1017 1073 1018 1018 1074 999 999 1054 1018 1018 1074 1000 1000 1055 1000 1000 1055 1018 1018 1074 1019 1019 1075 1000 1000 1055 1019 1019 1075 1001 1001 1056 1001 1001 1056 1019 1019 1075 1020 1020 1076 1001 1001 1056 1020 1020 1076 1002 1002 1057 1002 1002 1057 1020 1020 1076 1021 1021 1077 1002 1002 1057 1021 1021 1077 1003 1003 1058 1003 1003 1058 1021 1021 1077 1022 1022 1078 1003 1003 1058 1022 1022 1078 1004 1004 1059 1004 1004 1059 1022 1022 1078 1023 1023 1079 1004 1004 1059 1023 1023 1079 1005 1005 1060 1005 1005 1060 1023 1023 1079 1024 1024 1080 1005 1005 1060 1024 1024 1080 1006 1006 1061 1006 1006 1061 1024 1024 1080 1025 1025 1081 1006 1006 1061 1025 1025 1081 1007 1007 1062 1007 1007 1062 1025 1025 1081 1008 1008 1082 1007 1007 1062 1008 1008 1082 990 990 1063 1008 1008 1064 1026 1026 1083 1027 1027 1084 1008 1008 1064 1027 1027 1084 1009 1009 1065 1009 1009 1065 1027 1027 1084 1028 1028 1085 1009 1009 1065 1028 1028 1085 1010 1010 1066 1010 1010 1066 1028 1028 1085 1029 1029 1086 1010 1010 1066 1029 1029 1086 1011 1011 1067 1011 1011 1067 1029 1029 1086 1030 1030 1087 1011 1011 1067 1030 1030 1087 1012 1012 1068 1012 1012 1068 1030 1030 1087 1031 1031 1088 1012 1012 1068 1031 1031 1088 1013 1013 1069 1013 1013 1069 1031 1031 1088 1032 1032 1089 1013 1013 1069 1032 1032 1089 1014 1014 1070 1014 1014 1070 1032 1032 1089 1033 1033 1090 1014 1014 1070 1033 1033 1090 1015 1015 1071 1015 1015 1071 1033 1033 1090 1034 1034 1091 1015 1015 1071 1034 1034 1091 1016 1016 1072 1016 1016 1072 1034 1034 1091 1035 1035 1092 1016 1016 1072 1035 1035 1092 1017 1017 1073 1017 1017 1073 1035 1035 1092 1036 1036 1093 1017 1017 1073 1036 1036 1093 1018 1018 1074 1018 1018 1074 1036 1036 1093 1037 1037 1094 1018 1018 1074 1037 1037 1094 1019 1019 1075 1019 1019 1075 1037 1037 1094 1038 1038 1095 1019 1019 1075 1038 1038 1095 1020 1020 1076 1020 1020 1076 1038 1038 1095 1039 1039 1096 1020 1020 1076 1039 1039 1096 1021 1021 1077 1021 1021 1077 1039 1039 1096 1040 1040 1097 1021 1021 1077 1040 1040 1097 1022 1022 1078 1022 1022 1078 1040 1040 1097 1041 1041 1098 1022 1022 1078 1041 1041 1098 1023 1023 1079 1023 1023 1079 1041 1041 1098 1042 1042 1099 1023 1023 1079 1042 1042 1099 1024 1024 1080 1024 1024 1080 1042 1042 1099 1043 1043 1100 1024 1024 1080 1043 1043 1100 1025 1025 1081 1025 1025 1081 1043 1043 1100 1026 1026 1101 1025 1025 1081 1026 1026 1101 1008 1008 1082 1026 1026 1083 1044 1044 1102 1045 1045 1103 1026 1026 1083 1045 1045 1103 1027 1027 1084 1027 1027 1084 1045 1045 1103 1046 1046 1104 1027 1027 1084 1046 1046 1104 1028 1028 1085 1028 1028 1085 1046 1046 1104 1047 1047 1105 1028 1028 1085 1047 1047 1105 1029 1029 1086 1029 1029 1086 1047 1047 1105 1048 1048 1106 1029 1029 1086 1048 1048 1106 1030 1030 1087 1030 1030 1087 1048 1048 1106 1049 1049 1107 1030 1030 1087 1049 1049 1107 1031 1031 1088 1031 1031 1088 1049 1049 1107 1050 1050 1108 1031 1031 1088 1050 1050 1108 1032 1032 1089 1032 1032 1089 1050 1050 1108 1051 1051 1109 1032 1032 1089 1051 1051 1109 1033 1033 1090 1033 1033 1090 1051 1051 1109 1052 1052 1110 1033 1033 1090 1052 1052 1110 1034 1034 1091 1034 1034 1091 1052 1052 1110 1053 1053 1111 1034 1034 1091 1053 1053 1111 1035 1035 1092 1035 1035 1092 1053 1053 1111 1054 1054 1112 1035 1035 1092 1054 1054 1112 1036 1036 1093 1036 1036 1093 1054 1054 1112 1055 1055 1113 1036 1036 1093 1055 1055 1113 1037 1037 1094 1037 1037 1094 1055 1055 1113 1056 1056 1114 1037 1037 1094 1056 1056 1114 1038 1038 1095 1038 1038 1095 1056 1056 1114 1057 1057 1115 1038 1038 1095 1057 1057 1115 1039 1039 1096 1039 1039 1096 1057 1057 1115 1058 1058 1116 1039 1039 1096 1058 1058 1116 1040 1040 1097 1040 1040 1097 1058 1058 1116 1059 1059 1117 1040 1040 1097 1059 1059 1117 1041 1041 1098 1041 1041 1098 1059 1059 1117 1060 1060 1118 1041 1041 1098 1060 1060 1118 1042 1042 1099 1042 1042 1099 1060 1060 1118 1061 1061 1119 1042 1042 1099 1061 1061 1119 1043 1043 1100 1043 1043 1100 1061 1061 1119 1044 1044 1120 1043 1043 1100 1044 1044 1120 1026 1026 1101 1044 1044 1102 1062 1062 1121 1063 1063 1122 1044 1044 1102 1063 1063 1122 1045 1045 1103 1045 1045 1103 1063 1063 1122 1064 1064 1123 1045 1045 1103 1064 1064 1123 1046 1046 1104 1046 1046 1104 1064 1064 1123 1065 1065 1124 1046 1046 1104 1065 1065 1124 1047 1047 1105 1047 1047 1105 1065 1065 1124 1066 1066 1125 1047 1047 1105 1066 1066 1125 1048 1048 1106 1048 1048 1106 1066 1066 1125 1067 1067 1126 1048 1048 1106 1067 1067 1126 1049 1049 1107 1049 1049 1107 1067 1067 1126 1068 1068 1127 1049 1049 1107 1068 1068 1127 1050 1050 1108 1050 1050 1108 1068 1068 1127 1069 1069 1128 1050 1050 1108 1069 1069 1128 1051 1051 1109 1051 1051 1109 1069 1069 1128 1070 1070 1129 1051 1051 1109 1070 1070 1129 1052 1052 1110 1052 1052 1110 1070 1070 1129 1071 1071 1130 1052 1052 1110 1071 1071 1130 1053 1053 1111 1053 1053 1111 1071 1071 1130 1072 1072 1131 1053 1053 1111 1072 1072 1131 1054 1054 1112 1054 1054 1112 1072 1072 1131 1073 1073 1132 1054 1054 1112 1073 1073 1132 1055 1055 1113 1055 1055 1113 1073 1073 1132 1074 1074 1133 1055 1055 1113 1074 1074 1133 1056 1056 1114 1056 1056 1114 1074 1074 1133 1075 1075 1134 1056 1056 1114 1075 1075 1134 1057 1057 1115 1057 1057 1115 1075 1075 1134 1076 1076 1135 1057 1057 1115 1076 1076 1135 1058 1058 1116 1058 1058 1116 1076 1076 1135 1077 1077 1136 1058 1058 1116 1077 1077 1136 1059 1059 1117 1059 1059 1117 1077 1077 1136 1078 1078 1137 1059 1059 1117 1078 1078 1137 1060 1060 1118 1060 1060 1118 1078 1078 1137 1079 1079 1138 1060 1060 1118 1079 1079 1138 1061 1061 1119 1061 1061 1119 1079 1079 1138 1062 1062 1139 1061 1061 1119 1062 1062 1139 1044 1044 1120 1062 1062 1121 1080 1080 1140 1081 1081 1141 1062 1062 1121 1081 1081 1141 1063 1063 1122 1063 1063 1122 1081 1081 1141 1082 1082 1142 1063 1063 1122 1082 1082 1142 1064 1064 1123 1064 1064 1123 1082 1082 1142 1083 1083 1143 1064 1064 1123 1083 1083 1143 1065 1065 1124 1065 1065 1124 1083 1083 1143 1084 1084 1144 1065 1065 1124 1084 1084 1144 1066 1066 1125 1066 1066 1125 1084 1084 1144 1085 1085 1145 1066 1066 1125 1085 1085 1145 1067 1067 1126 1067 1067 1126 1085 1085 1145 1086 1086 1146 1067 1067 1126 1086 1086 1146 1068 1068 1127 1068 1068 1127 1086 1086 1146 1087 1087 1147 1068 1068 1127 1087 1087 1147 1069 1069 1128 1069 1069 1128 1087 1087 1147 1088 1088 1148 1069 1069 1128 1088 1088 1148 1070 1070 1129 1070 1070 1129 1088 1088 1148 1089 1089 1149 1070 1070 1129 1089 1089 1149 1071 1071 1130 1071 1071 1130 1089 1089 1149 1090 1090 1150 1071 1071 1130 1090 1090 1150 1072 1072 1131 1072 1072 1131 1090 1090 1150 1091 1091 1151 1072 1072 1131 1091 1091 1151 1073 1073 1132 1073 1073 1132 1091 1091 1151 1092 1092 1152 1073 1073 1132 1092 1092 1152 1074 1074 1133 1074 1074 1133 1092 1092 1152 1093 1093 1153 1074 1074 1133 1093 1093 1153 1075 1075 1134 1075 1075 1134 1093 1093 1153 1094 1094 1154 1075 1075 1134 1094 1094 1154 1076 1076 1135 1076 1076 1135 1094 1094 1154 1095 1095 1155 1076 1076 1135 1095 1095 1155 1077 1077 1136 1077 1077 1136 1095 1095 1155 1096 1096 1156 1077 1077 1136 1096 1096 1156 1078 1078 1137 1078 1078 1137 1096 1096 1156 1097 1097 1157 1078 1078 1137 1097 1097 1157 1079 1079 1138 1079 1079 1138 1097 1097 1157 1080 1080 1158 1079 1079 1138 1080 1080 1158 1062 1062 1139 1080 1080 1140 1098 1098 1159 1099 1099 1160 1080 1080 1140 1099 1099 1160 1081 1081 1141 1081 1081 1141 1099 1099 1160 1100 1100 1161 1081 1081 1141 1100 1100 1161 1082 1082 1142 1082 1082 1142 1100 1100 1161 1101 1101 1162 1082 1082 1142 1101 1101 1162 1083 1083 1143 1083 1083 1143 1101 1101 1162 1102 1102 1163 1083 1083 1143 1102 1102 1163 1084 1084 1144 1084 1084 1144 1102 1102 1163 1103 1103 1164 1084 1084 1144 1103 1103 1164 1085 1085 1145 1085 1085 1145 1103 1103 1164 1104 1104 1165 1085 1085 1145 1104 1104 1165 1086 1086 1146 1086 1086 1146 1104 1104 1165 1105 1105 1166 1086 1086 1146 1105 1105 1166 1087 1087 1147 1087 1087 1147 1105 1105 1166 1106 1106 1167 1087 1087 1147 1106 1106 1167 1088 1088 1148 1088 1088 1148 1106 1106 1167 1107 1107 1168 1088 1088 1148 1107 1107 1168 1089 1089 1149 1089 1089 1149 1107 1107 1168 1108 1108 1169 1089 1089 1149 1108 1108 1169 1090 1090 1150 1090 1090 1150 1108 1108 1169 1109 1109 1170 1090 1090 1150 1109 1109 1170 1091 1091 1151 1091 1091 1151 1109 1109 1170 1110 1110 1171 1091 1091 1151 1110 1110 1171 1092 1092 1152 1092 1092 1152 1110 1110 1171 1111 1111 1172 1092 1092 1152 1111 1111 1172 1093 1093 1153 1093 1093 1153 1111 1111 1172 1112 1112 1173 1093 1093 1153 1112 1112 1173 1094 1094 1154 1094 1094 1154 1112 1112 1173 1113 1113 1174 1094 1094 1154 1113 1113 1174 1095 1095 1155 1095 1095 1155 1113 1113 1174 1114 1114 1175 1095 1095 1155 1114 1114 1175 1096 1096 1156 1096 1096 1156 1114 1114 1175 1115 1115 1176 1096 1096 1156 1115 1115 1176 1097 1097 1157 1097 1097 1157 1115 1115 1176 1098 1098 1177 1097 1097 1157 1098 1098 1177 1080 1080 1158 1098 1098 1159 1116 1116 1178 1117 1117 1179 1098 1098 1159 1117 1117 1179 1099 1099 1160 1099 1099 1160 1117 1117 1179 1118 1118 1180 1099 1099 1160 1118 1118 1180 1100 1100 1161 1100 1100 1161 1118 1118 1180 1119 1119 1181 1100 1100 1161 1119 1119 1181 1101 1101 1162 1101 1101 1162 1119 1119 1181 1120 1120 1182 1101 1101 1162 1120 1120 1182 1102 1102 1163 1102 1102 1163 1120 1120 1182 1121 1121 1183 1102 1102 1163 1121 1121 1183 1103 1103 1164 1103 1103 1164 1121 1121 1183 1122 1122 1184 1103 1103 1164 1122 1122 1184 1104 1104 1165 1104 1104 1165 1122 1122 1184 1123 1123 1185 1104 1104 1165 1123 1123 1185 1105 1105 1166 1105 1105 1166 1123 1123 1185 1124 1124 1186 1105 1105 1166 1124 1124 1186 1106 1106 1167 1106 1106 1167 1124 1124 1186 1125 1125 1187 1106 1106 1167 1125 1125 1187 1107 1107 1168 1107 1107 1168 1125 1125 1187 1126 1126 1188 1107 1107 1168 1126 1126 1188 1108 1108 1169 1108 1108 1169 1126 1126 1188 1127 1127 1189 1108 1108 1169 1127 1127 1189 1109 1109 1170 1109 1109 1170 1127 1127 1189 1128 1128 1190 1109 1109 1170 1128 1128 1190 1110 1110 1171 1110 1110 1171 1128 1128 1190 1129 1129 1191 1110 1110 1171 1129 1129 1191 1111 1111 1172 1111 1111 1172 1129 1129 1191 1130 1130 1192 1111 1111 1172 1130 1130 1192 1112 1112 1173 1112 1112 1173 1130 1130 1192 1131 1131 1193 1112 1112 1173 1131 1131 1193 1113 1113 1174 1113 1113 1174 1131 1131 1193 1132 1132 1194 1113 1113 1174 1132 1132 1194 1114 1114 1175 1114 1114 1175 1132 1132 1194 1133 1133 1195 1114 1114 1175 1133 1133 1195 1115 1115 1176 1115 1115 1176 1133 1133 1195 1116 1116 1196 1115 1115 1176 1116 1116 1196 1098 1098 1177 1116 1116 1178 1134 1134 1197 1135 1135 1198 1116 1116 1178 1135 1135 1198 1117 1117 1179 1117 1117 1179 1135 1135 1198 1136 1136 1199 1117 1117 1179 1136 1136 1199 1118 1118 1180 1118 1118 1180 1136 1136 1199 1137 1137 1200 1118 1118 1180 1137 1137 1200 1119 1119 1181 1119 1119 1181 1137 1137 1200 1138 1138 1201 1119 1119 1181 1138 1138 1201 1120 1120 1182 1120 1120 1182 1138 1138 1201 1139 1139 1202 1120 1120 1182 1139 1139 1202 1121 1121 1183 1121 1121 1183 1139 1139 1202 1140 1140 1203 1121 1121 1183 1140 1140 1203 1122 1122 1184 1122 1122 1184 1140 1140 1203 1141 1141 1204 1122 1122 1184 1141 1141 1204 1123 1123 1185 1123 1123 1185 1141 1141 1204 1142 1142 1205 1123 1123 1185 1142 1142 1205 1124 1124 1186 1124 1124 1186 1142 1142 1205 1143 1143 1206 1124 1124 1186 1143 1143 1206 1125 1125 1187 1125 1125 1187 1143 1143 1206 1144 1144 1207 1125 1125 1187 1144 1144 1207 1126 1126 1188 1126 1126 1188 1144 1144 1207 1145 1145 1208 1126 1126 1188 1145 1145 1208 1127 1127 1189 1127 1127 1189 1145 1145 1208 1146 1146 1209 1127 1127 1189 1146 1146 1209 1128 1128 1190 1128 1128 1190 1146 1146 1209 1147 1147 1210 1128 1128 1190 1147 1147 1210 1129 1129 1191 1129 1129 1191 1147 1147 1210 1148 1148 1211 1129 1129 1191 1148 1148 1211 1130 1130 1192 1130 1130 1192 1148 1148 1211 1149 1149 1212 1130 1130 1192 1149 1149 1212 1131 1131 1193 1131 1131 1193 1149 1149 1212 1150 1150 1213 1131 1131 1193 1150 1150 1213 1132 1132 1194 1132 1132 1194 1150 1150 1213 1151 1151 1214 1132 1132 1194 1151 1151 1214 1133 1133 1195 1133 1133 1195 1151 1151 1214 1134 1134 1215 1133 1133 1195 1134 1134 1215 1116 1116 1196 1134 1134 1197 1152 1152 1216 1153 1153 1217 1134 1134 1197 1153 1153 1217 1135 1135 1198 1135 1135 1198 1153 1153 1217 1154 1154 1218 1135 1135 1198 1154 1154 1218 1136 1136 1199 1136 1136 1199 1154 1154 1218 1155 1155 1219 1136 1136 1199 1155 1155 1219 1137 1137 1200 1137 1137 1200 1155 1155 1219 1156 1156 1220 1137 1137 1200 1156 1156 1220 1138 1138 1201 1138 1138 1201 1156 1156 1220 1157 1157 1221 1138 1138 1201 1157 1157 1221 1139 1139 1202 1139 1139 1202 1157 1157 1221 1158 1158 1222 1139 1139 1202 1158 1158 1222 1140 1140 1203 1140 1140 1203 1158 1158 1222 1159 1159 1223 1140 1140 1203 1159 1159 1223 1141 1141 1204 1141 1141 1204 1159 1159 1223 1160 1160 1224 1141 1141 1204 1160 1160 1224 1142 1142 1205 1142 1142 1205 1160 1160 1224 1161 1161 1225 1142 1142 1205 1161 1161 1225 1143 1143 1206 1143 1143 1206 1161 1161 1225 1162 1162 1226 1143 1143 1206 1162 1162 1226 1144 1144 1207 1144 1144 1207 1162 1162 1226 1163 1163 1227 1144 1144 1207 1163 1163 1227 1145 1145 1208 1145 1145 1208 1163 1163 1227 1164 1164 1228 1145 1145 1208 1164 1164 1228 1146 1146 1209 1146 1146 1209 1164 1164 1228 1165 1165 1229 1146 1146 1209 1165 1165 1229 1147 1147 1210 1147 1147 1210 1165 1165 1229 1166 1166 1230 1147 1147 1210 1166 1166 1230 1148 1148 1211 1148 1148 1211 1166 1166 1230 1167 1167 1231 1148 1148 1211 1167 1167 1231 1149 1149 1212 1149 1149 1212 1167 1167 1231 1168 1168 1232 1149 1149 1212 1168 1168 1232 1150 1150 1213 1150 1150 1213 1168 1168 1232 1169 1169 1233 1150 1150 1213 1169 1169 1233 1151 1151 1214 1151 1151 1214 1169 1169 1233 1152 1152 1234 1151 1151 1214 1152 1152 1234 1134 1134 1215 1152 1152 1216 1170 1170 1235 1171 1171 1236 1152 1152 1216 1171 1171 1236 1153 1153 1217 1153 1153 1217 1171 1171 1236 1172 1172 1237 1153 1153 1217 1172 1172 1237 1154 1154 1218 1154 1154 1218 1172 1172 1237 1173 1173 1238 1154 1154 1218 1173 1173 1238 1155 1155 1219 1155 1155 1219 1173 1173 1238 1174 1174 1239 1155 1155 1219 1174 1174 1239 1156 1156 1220 1156 1156 1220 1174 1174 1239 1175 1175 1240 1156 1156 1220 1175 1175 1240 1157 1157 1221 1157 1157 1221 1175 1175 1240 1176 1176 1241 1157 1157 1221 1176 1176 1241 1158 1158 1222 1158 1158 1222 1176 1176 1241 1177 1177 1242 1158 1158 1222 1177 1177 1242 1159 1159 1223 1159 1159 1223 1177 1177 1242 1178 1178 1243 1159 1159 1223 1178 1178 1243 1160 1160 1224 1160 1160 1224 1178 1178 1243 1179 1179 1244 1160 1160 1224 1179 1179 1244 1161 1161 1225 1161 1161 1225 1179 1179 1244 1180 1180 1245 1161 1161 1225 1180 1180 1245 1162 1162 1226 1162 1162 1226 1180 1180 1245 1181 1181 1246 1162 1162 1226 1181 1181 1246 1163 1163 1227 1163 1163 1227 1181 1181 1246 1182 1182 1247 1163 1163 1227 1182 1182 1247 1164 1164 1228 1164 1164 1228 1182 1182 1247 1183 1183 1248 1164 1164 1228 1183 1183 1248 1165 1165 1229 1165 1165 1229 1183 1183 1248 1184 1184 1249 1165 1165 1229 1184 1184 1249 1166 1166 1230 1166 1166 1230 1184 1184 1249 1185 1185 1250 1166 1166 1230 1185 1185 1250 1167 1167 1231 1167 1167 1231 1185 1185 1250 1186 1186 1251 1167 1167 1231 1186 1186 1251 1168 1168 1232 1168 1168 1232 1186 1186 1251 1187 1187 1252 1168 1168 1232 1187 1187 1252 1169 1169 1233 1169 1169 1233 1187 1187 1252 1170 1170 1253 1169 1169 1233 1170 1170 1253 1152 1152 1234 1170 1170 1235 1188 1188 1254 1189 1189 1255 1170 1170 1235 1189 1189 1255 1171 1171 1236 1171 1171 1236 1189 1189 1255 1190 1190 1256 1171 1171 1236 1190 1190 1256 1172 1172 1237 1172 1172 1237 1190 1190 1256 1191 1191 1257 1172 1172 1237 1191 1191 1257 1173 1173 1238 1173 1173 1238 1191 1191 1257 1192 1192 1258 1173 1173 1238 1192 1192 1258 1174 1174 1239 1174 1174 1239 1192 1192 1258 1193 1193 1259 1174 1174 1239 1193 1193 1259 1175 1175 1240 1175 1175 1240 1193 1193 1259 1194 1194 1260 1175 1175 1240 1194 1194 1260 1176 1176 1241 1176 1176 1241 1194 1194 1260 1195 1195 1261 1176 1176 1241 1195 1195 1261 1177 1177 1242 1177 1177 1242 1195 1195 1261 1196 1196 1262 1177 1177 1242 1196 1196 1262 1178 1178 1243 1178 1178 1243 1196 1196 1262 1197 1197 1263 1178 1178 1243 1197 1197 1263 1179 1179 1244 1179 1179 1244 1197 1197 1263 1198 1198 1264 1179 1179 1244 1198 1198 1264 1180 1180 1245 1180 1180 1245 1198 1198 1264 1199 1199 1265 1180 1180 1245 1199 1199 1265 1181 1181 1246 1181 1181 1246 1199 1199 1265 1200 1200 1266 1181 1181 1246 1200 1200 1266 1182 1182 1247 1182 1182 1247 1200 1200 1266 1201 1201 1267 1182 1182 1247 1201 1201 1267 1183 1183 1248 1183 1183 1248 1201 1201 1267 1202 1202 1268 1183 1183 1248 1202 1202 1268 1184 1184 1249 1184 1184 1249 1202 1202 1268 1203 1203 1269 1184 1184 1249 1203 1203 1269 1185 1185 1250 1185 1185 1250 1203 1203 1269 1204 1204 1270 1185 1185 1250 1204 1204 1270 1186 1186 1251 1186 1186 1251 1204 1204 1270 1205 1205 1271 1186 1186 1251 1205 1205 1271 1187 1187 1252 1187 1187 1252 1205 1205 1271 1188 1188 1272 1187 1187 1252 1188 1188 1272 1170 1170 1253 1188 1188 1254 1206 1206 1273 1207 1207 1274 1188 1188 1254 1207 1207 1274 1189 1189 1255 1189 1189 1255 1207 1207 1274 1208 1208 1275 1189 1189 1255 1208 1208 1275 1190 1190 1256 1190 1190 1256 1208 1208 1275 1209 1209 1276 1190 1190 1256 1209 1209 1276 1191 1191 1257 1191 1191 1257 1209 1209 1276 1210 1210 1277 1191 1191 1257 1210 1210 1277 1192 1192 1258 1192 1192 1258 1210 1210 1277 1211 1211 1278 1192 1192 1258 1211 1211 1278 1193 1193 1259 1193 1193 1259 1211 1211 1278 1212 1212 1279 1193 1193 1259 1212 1212 1279 1194 1194 1260 1194 1194 1260 1212 1212 1279 1213 1213 1280 1194 1194 1260 1213 1213 1280 1195 1195 1261 1195 1195 1261 1213 1213 1280 1214 1214 1281 1195 1195 1261 1214 1214 1281 1196 1196 1262 1196 1196 1262 1214 1214 1281 1215 1215 1282 1196 1196 1262 1215 1215 1282 1197 1197 1263 1197 1197 1263 1215 1215 1282 1216 1216 1283 1197 1197 1263 1216 1216 1283 1198 1198 1264 1198 1198 1264 1216 1216 1283 1217 1217 1284 1198 1198 1264 1217 1217 1284 1199 1199 1265 1199 1199 1265 1217 1217 1284 1218 1218 1285 1199 1199 1265 1218 1218 1285 1200 1200 1266 1200 1200 1266 1218 1218 1285 1219 1219 1286 1200 1200 1266 1219 1219 1286 1201 1201 1267 1201 1201 1267 1219 1219 1286 1220 1220 1287 1201 1201 1267 1220 1220 1287 1202 1202 1268 1202 1202 1268 1220 1220 1287 1221 1221 1288 1202 1202 1268 1221 1221 1288 1203 1203 1269 1203 1203 1269 1221 1221 1288 1222 1222 1289 1203 1203 1269 1222 1222 1289 1204 1204 1270 1204 1204 1270 1222 1222 1289 1223 1223 1290 1204 1204 1270 1223 1223 1290 1205 1205 1271 1205 1205 1271 1223 1223 1290 1206 1206 1291 1205 1205 1271 1206 1206 1291 1188 1188 1272 1206 1206 1273 1224 1224 1292 1225 1225 1293 1206 1206 1273 1225 1225 1293 1207 1207 1274 1207 1207 1274 1225 1225 1293 1226 1226 1294 1207 1207 1274 1226 1226 1294 1208 1208 1275 1208 1208 1275 1226 1226 1294 1227 1227 1295 1208 1208 1275 1227 1227 1295 1209 1209 1276 1209 1209 1276 1227 1227 1295 1228 1228 1296 1209 1209 1276 1228 1228 1296 1210 1210 1277 1210 1210 1277 1228 1228 1296 1229 1229 1297 1210 1210 1277 1229 1229 1297 1211 1211 1278 1211 1211 1278 1229 1229 1297 1230 1230 1298 1211 1211 1278 1230 1230 1298 1212 1212 1279 1212 1212 1279 1230 1230 1298 1231 1231 1299 1212 1212 1279 1231 1231 1299 1213 1213 1280 1213 1213 1280 1231 1231 1299 1232 1232 1300 1213 1213 1280 1232 1232 1300 1214 1214 1281 1214 1214 1281 1232 1232 1300 1233 1233 1301 1214 1214 1281 1233 1233 1301 1215 1215 1282 1215 1215 1282 1233 1233 1301 1234 1234 1302 1215 1215 1282 1234 1234 1302 1216 1216 1283 1216 1216 1283 1234 1234 1302 1235 1235 1303 1216 1216 1283 1235 1235 1303 1217 1217 1284 1217 1217 1284 1235 1235 1303 1236 1236 1304 1217 1217 1284 1236 1236 1304 1218 1218 1285 1218 1218 1285 1236 1236 1304 1237 1237 1305 1218 1218 1285 1237 1237 1305 1219 1219 1286 1219 1219 1286 1237 1237 1305 1238 1238 1306 1219 1219 1286 1238 1238 1306 1220 1220 1287 1220 1220 1287 1238 1238 1306 1239 1239 1307 1220 1220 1287 1239 1239 1307 1221 1221 1288 1221 1221 1288 1239 1239 1307 1240 1240 1308 1221 1221 1288 1240 1240 1308 1222 1222 1289 1222 1222 1289 1240 1240 1308 1241 1241 1309 1222 1222 1289 1241 1241 1309 1223 1223 1290 1223 1223 1290 1241 1241 1309 1224 1224 1310 1223 1223 1290 1224 1224 1310 1206 1206 1291 1224 1224 1292 1242 1242 1311 1243 1243 1312 1224 1224 1292 1243 1243 1312 1225 1225 1293 1225 1225 1293 1243 1243 1312 1244 1244 1313 1225 1225 1293 1244 1244 1313 1226 1226 1294 1226 1226 1294 1244 1244 1313 1245 1245 1314 1226 1226 1294 1245 1245 1314 1227 1227 1295 1227 1227 1295 1245 1245 1314 1246 1246 1315 1227 1227 1295 1246 1246 1315 1228 1228 1296 1228 1228 1296 1246 1246 1315 1247 1247 1316 1228 1228 1296 1247 1247 1316 1229 1229 1297 1229 1229 1297 1247 1247 1316 1248 1248 1317 1229 1229 1297 1248 1248 1317 1230 1230 1298 1230 1230 1298 1248 1248 1317 1249 1249 1318 1230 1230 1298 1249 1249 1318 1231 1231 1299 1231 1231 1299 1249 1249 1318 1250 1250 1319 1231 1231 1299 1250 1250 1319 1232 1232 1300 1232 1232 1300 1250 1250 1319 1251 1251 1320 1232 1232 1300 1251 1251 1320 1233 1233 1301 1233 1233 1301 1251 1251 1320 1252 1252 1321 1233 1233 1301 1252 1252 1321 1234 1234 1302 1234 1234 1302 1252 1252 1321 1253 1253 1322 1234 1234 1302 1253 1253 1322 1235 1235 1303 1235 1235 1303 1253 1253 1322 1254 1254 1323 1235 1235 1303 1254 1254 1323 1236 1236 1304 1236 1236 1304 1254 1254 1323 1255 1255 1324 1236 1236 1304 1255 1255 1324 1237 1237 1305 1237 1237 1305 1255 1255 1324 1256 1256 1325 1237 1237 1305 1256 1256 1325 1238 1238 1306 1238 1238 1306 1256 1256 1325 1257 1257 1326 1238 1238 1306 1257 1257 1326 1239 1239 1307 1239 1239 1307 1257 1257 1326 1258 1258 1327 1239 1239 1307 1258 1258 1327 1240 1240 1308 1240 1240 1308 1258 1258 1327 1259 1259 1328 1240 1240 1308 1259 1259 1328 1241 1241 1309 1241 1241 1309 1259 1259 1328 1242 1242 1329 1241 1241 1309 1242 1242 1329 1224 1224 1310 1242 1242 1311 1260 1260 1330 1261 1261 1331 1242 1242 1311 1261 1261 1331 1243 1243 1312 1243 1243 1312 1261 1261 1331 1262 1262 1332 1243 1243 1312 1262 1262 1332 1244 1244 1313 1244 1244 1313 1262 1262 1332 1263 1263 1333 1244 1244 1313 1263 1263 1333 1245 1245 1314 1245 1245 1314 1263 1263 1333 1264 1264 1334 1245 1245 1314 1264 1264 1334 1246 1246 1315 1246 1246 1315 1264 1264 1334 1265 1265 1335 1246 1246 1315 1265 1265 1335 1247 1247 1316 1247 1247 1316 1265 1265 1335 1266 1266 1336 1247 1247 1316 1266 1266 1336 1248 1248 1317 1248 1248 1317 1266 1266 1336 1267 1267 1337 1248 1248 1317 1267 1267 1337 1249 1249 1318 1249 1249 1318 1267 1267 1337 1268 1268 1338 1249 1249 1318 1268 1268 1338 1250 1250 1319 1250 1250 1319 1268 1268 1338 1269 1269 1339 1250 1250 1319 1269 1269 1339 1251 1251 1320 1251 1251 1320 1269 1269 1339 1270 1270 1340 1251 1251 1320 1270 1270 1340 1252 1252 1321 1252 1252 1321 1270 1270 1340 1271 1271 1341 1252 1252 1321 1271 1271 1341 1253 1253 1322 1253 1253 1322 1271 1271 1341 1272 1272 1342 1253 1253 1322 1272 1272 1342 1254 1254 1323 1254 1254 1323 1272 1272 1342 1273 1273 1343 1254 1254 1323 1273 1273 1343 1255 1255 1324 1255 1255 1324 1273 1273 1343 1274 1274 1344 1255 1255 1324 1274 1274 1344 1256 1256 1325 1256 1256 1325 1274 1274 1344 1275 1275 1345 1256 1256 1325 1275 1275 1345 1257 1257 1326 1257 1257 1326 1275 1275 1345 1276 1276 1346 1257 1257 1326 1276 1276 1346 1258 1258 1327 1258 1258 1327 1276 1276 1346 1277 1277 1347 1258 1258 1327 1277 1277 1347 1259 1259 1328 1259 1259 1328 1277 1277 1347 1260 1260 1348 1259 1259 1328 1260 1260 1348 1242 1242 1329 1260 1260 1330 1278 1278 1349 1279 1279 1350 1260 1260 1330 1279 1279 1350 1261 1261 1331 1261 1261 1331 1279 1279 1350 1280 1280 1351 1261 1261 1331 1280 1280 1351 1262 1262 1332 1262 1262 1332 1280 1280 1351 1281 1281 1352 1262 1262 1332 1281 1281 1352 1263 1263 1333 1263 1263 1333 1281 1281 1352 1282 1282 1353 1263 1263 1333 1282 1282 1353 1264 1264 1334 1264 1264 1334 1282 1282 1353 1283 1283 1354 1264 1264 1334 1283 1283 1354 1265 1265 1335 1265 1265 1335 1283 1283 1354 1284 1284 1355 1265 1265 1335 1284 1284 1355 1266 1266 1336 1266 1266 1336 1284 1284 1355 1285 1285 1356 1266 1266 1336 1285 1285 1356 1267 1267 1337 1267 1267 1337 1285 1285 1356 1286 1286 1357 1267 1267 1337 1286 1286 1357 1268 1268 1338 1268 1268 1338 1286 1286 1357 1287 1287 1358 1268 1268 1338 1287 1287 1358 1269 1269 1339 1269 1269 1339 1287 1287 1358 1288 1288 1359 1269 1269 1339 1288 1288 1359 1270 1270 1340 1270 1270 1340 1288 1288 1359 1289 1289 1360 1270 1270 1340 1289 1289 1360 1271 1271 1341 1271 1271 1341 1289 1289 1360 1290 1290 1361 1271 1271 1341 1290 1290 1361 1272 1272 1342 1272 1272 1342 1290 1290 1361 1291 1291 1362 1272 1272 1342 1291 1291 1362 1273 1273 1343 1273 1273 1343 1291 1291 1362 1292 1292 1363 1273 1273 1343 1292 1292 1363 1274 1274 1344 1274 1274 1344 1292 1292 1363 1293 1293 1364 1274 1274 1344 1293 1293 1364 1275 1275 1345 1275 1275 1345 1293 1293 1364 1294 1294 1365 1275 1275 1345 1294 1294 1365 1276 1276 1346 1276 1276 1346 1294 1294 1365 1295 1295 1366 1276 1276 1346 1295 1295 1366 1277 1277 1347 1277 1277 1347 1295 1295 1366 1278 1278 1367 1277 1277 1347 1278 1278 1367 1260 1260 1348 1278 1278 1349 1296 1296 1368 1297 1297 1369 1278 1278 1349 1297 1297 1369 1279 1279 1350 1279 1279 1350 1297 1297 1369 1298 1298 1370 1279 1279 1350 1298 1298 1370 1280 1280 1351 1280 1280 1351 1298 1298 1370 1299 1299 1371 1280 1280 1351 1299 1299 1371 1281 1281 1352 1281 1281 1352 1299 1299 1371 1300 1300 1372 1281 1281 1352 1300 1300 1372 1282 1282 1353 1282 1282 1353 1300 1300 1372 1301 1301 1373 1282 1282 1353 1301 1301 1373 1283 1283 1354 1283 1283 1354 1301 1301 1373 1302 1302 1374 1283 1283 1354 1302 1302 1374 1284 1284 1355 1284 1284 1355 1302 1302 1374 1303 1303 1375 1284 1284 1355 1303 1303 1375 1285 1285 1356 1285 1285 1356 1303 1303 1375 1304 1304 1376 1285 1285 1356 1304 1304 1376 1286 1286 1357 1286 1286 1357 1304 1304 1376 1305 1305 1377 1286 1286 1357 1305 1305 1377 1287 1287 1358 1287 1287 1358 1305 1305 1377 1306 1306 1378 1287 1287 1358 1306 1306 1378 1288 1288 1359 1288 1288 1359 1306 1306 1378 1307 1307 1379 1288 1288 1359 1307 1307 1379 1289 1289 1360 1289 1289 1360 1307 1307 1379 1308 1308 1380 1289 1289 1360 1308 1308 1380 1290 1290 1361 1290 1290 1361 1308 1308 1380 1309 1309 1381 1290 1290 1361 1309 1309 1381 1291 1291 1362 1291 1291 1362 1309 1309 1381 1310 1310 1382 1291 1291 1362 1310 1310 1382 1292 1292 1363 1292 1292 1363 1310 1310 1382 1311 1311 1383 1292 1292 1363 1311 1311 1383 1293 1293 1364 1293 1293 1364 1311 1311 1383 1312 1312 1384 1293 1293 1364 1312 1312 1384 1294 1294 1365 1294 1294 1365 1312 1312 1384 1313 1313 1385 1294 1294 1365 1313 1313 1385 1295 1295 1366 1295 1295 1366 1313 1313 1385 1296 1296 1386 1295 1295 1366 1296 1296 1386 1278 1278 1367 1296 1296 1368 1314 1314 1387 1315 1315 1388 1296 1296 1368 1315 1315 1388 1297 1297 1369 1297 1297 1369 1315 1315 1388 1316 1316 1389 1297 1297 1369 1316 1316 1389 1298 1298 1370 1298 1298 1370 1316 1316 1389 1317 1317 1390 1298 1298 1370 1317 1317 1390 1299 1299 1371 1299 1299 1371 1317 1317 1390 1318 1318 1391 1299 1299 1371 1318 1318 1391 1300 1300 1372 1300 1300 1372 1318 1318 1391 1319 1319 1392 1300 1300 1372 1319 1319 1392 1301 1301 1373 1301 1301 1373 1319 1319 1392 1320 1320 1393 1301 1301 1373 1320 1320 1393 1302 1302 1374 1302 1302 1374 1320 1320 1393 1321 1321 1394 1302 1302 1374 1321 1321 1394 1303 1303 1375 1303 1303 1375 1321 1321 1394 1322 1322 1395 1303 1303 1375 1322 1322 1395 1304 1304 1376 1304 1304 1376 1322 1322 1395 1323 1323 1396 1304 1304 1376 1323 1323 1396 1305 1305 1377 1305 1305 1377 1323 1323 1396 1324 1324 1397 1305 1305 1377 1324 1324 1397 1306 1306 1378 1306 1306 1378 1324 1324 1397 1325 1325 1398 1306 1306 1378 1325 1325 1398 1307 1307 1379 1307 1307 1379 1325 1325 1398 1326 1326 1399 1307 1307 1379 1326 1326 1399 1308 1308 1380 1308 1308 1380 1326 1326 1399 1327 1327 1400 1308 1308 1380 1327 1327 1400 1309 1309 1381 1309 1309 1381 1327 1327 1400 1328 1328 1401 1309 1309 1381 1328 1328 1401 1310 1310 1382 1310 1310 1382 1328 1328 1401 1329 1329 1402 1310 1310 1382 1329 1329 1402 1311 1311 1383 1311 1311 1383 1329 1329 1402 1330 1330 1403 1311 1311 1383 1330 1330 1403 1312 1312 1384 1312 1312 1384 1330 1330 1403 1331 1331 1404 1312 1312 1384 1331 1331 1404 1313 1313 1385 1313 1313 1385 1331 1331 1404 1314 1314 1405 1313 1313 1385 1314 1314 1405 1296 1296 1386 1314 1314 1387 1332 1332 1406 1333 1333 1407 1314 1314 1387 1333 1333 1407 1315 1315 1388 1315 1315 1388 1333 1333 1407 1334 1334 1408 1315 1315 1388 1334 1334 1408 1316 1316 1389 1316 1316 1389 1334 1334 1408 1335 1335 1409 1316 1316 1389 1335 1335 1409 1317 1317 1390 1317 1317 1390 1335 1335 1409 1336 1336 1410 1317 1317 1390 1336 1336 1410 1318 1318 1391 1318 1318 1391 1336 1336 1410 1337 1337 1411 1318 1318 1391 1337 1337 1411 1319 1319 1392 1319 1319 1392 1337 1337 1411 1338 1338 1412 1319 1319 1392 1338 1338 1412 1320 1320 1393 1320 1320 1393 1338 1338 1412 1339 1339 1413 1320 1320 1393 1339 1339 1413 1321 1321 1394 1321 1321 1394 1339 1339 1413 1340 1340 1414 1321 1321 1394 1340 1340 1414 1322 1322 1395 1322 1322 1395 1340 1340 1414 1341 1341 1415 1322 1322 1395 1341 1341 1415 1323 1323 1396 1323 1323 1396 1341 1341 1415 1342 1342 1416 1323 1323 1396 1342 1342 1416 1324 1324 1397 1324 1324 1397 1342 1342 1416 1343 1343 1417 1324 1324 1397 1343 1343 1417 1325 1325 1398 1325 1325 1398 1343 1343 1417 1344 1344 1418 1325 1325 1398 1344 1344 1418 1326 1326 1399 1326 1326 1399 1344 1344 1418 1345 1345 1419 1326 1326 1399 1345 1345 1419 1327 1327 1400 1327 1327 1400 1345 1345 1419 1346 1346 1420 1327 1327 1400 1346 1346 1420 1328 1328 1401 1328 1328 1401 1346 1346 1420 1347 1347 1421 1328 1328 1401 1347 1347 1421 1329 1329 1402 1329 1329 1402 1347 1347 1421 1348 1348 1422 1329 1329 1402 1348 1348 1422 1330 1330 1403 1330 1330 1403 1348 1348 1422 1349 1349 1423 1330 1330 1403 1349 1349 1423 1331 1331 1404 1331 1331 1404 1349 1349 1423 1332 1332 1424 1331 1331 1404 1332 1332 1424 1314 1314 1405 1332 1332 1406 1350 1350 1425 1351 1351 1426 1332 1332 1406 1351 1351 1426 1333 1333 1407 1333 1333 1407 1351 1351 1426 1352 1352 1427 1333 1333 1407 1352 1352 1427 1334 1334 1408 1334 1334 1408 1352 1352 1427 1353 1353 1428 1334 1334 1408 1353 1353 1428 1335 1335 1409 1335 1335 1409 1353 1353 1428 1354 1354 1429 1335 1335 1409 1354 1354 1429 1336 1336 1410 1336 1336 1410 1354 1354 1429 1355 1355 1430 1336 1336 1410 1355 1355 1430 1337 1337 1411 1337 1337 1411 1355 1355 1430 1356 1356 1431 1337 1337 1411 1356 1356 1431 1338 1338 1412 1338 1338 1412 1356 1356 1431 1357 1357 1432 1338 1338 1412 1357 1357 1432 1339 1339 1413 1339 1339 1413 1357 1357 1432 1358 1358 1433 1339 1339 1413 1358 1358 1433 1340 1340 1414 1340 1340 1414 1358 1358 1433 1359 1359 1434 1340 1340 1414 1359 1359 1434 1341 1341 1415 1341 1341 1415 1359 1359 1434 1360 1360 1435 1341 1341 1415 1360 1360 1435 1342 1342 1416 1342 1342 1416 1360 1360 1435 1361 1361 1436 1342 1342 1416 1361 1361 1436 1343 1343 1417 1343 1343 1417 1361 1361 1436 1362 1362 1437 1343 1343 1417 1362 1362 1437 1344 1344 1418 1344 1344 1418 1362 1362 1437 1363 1363 1438 1344 1344 1418 1363 1363 1438 1345 1345 1419 1345 1345 1419 1363 1363 1438 1364 1364 1439 1345 1345 1419 1364 1364 1439 1346 1346 1420 1346 1346 1420 1364 1364 1439 1365 1365 1440 1346 1346 1420 1365 1365 1440 1347 1347 1421 1347 1347 1421 1365 1365 1440 1366 1366 1441 1347 1347 1421 1366 1366 1441 1348 1348 1422 1348 1348 1422 1366 1366 1441 1367 1367 1442 1348 1348 1422 1367 1367 1442 1349 1349 1423 1349 1349 1423 1367 1367 1442 1350 1350 1443 1349 1349 1423 1350 1350 1443 1332 1332 1424 1350 1350 1425 1368 1368 1444 1369 1369 1445 1350 1350 1425 1369 1369 1445 1351 1351 1426 1351 1351 1426 1369 1369 1445 1370 1370 1446 1351 1351 1426 1370 1370 1446 1352 1352 1427 1352 1352 1427 1370 1370 1446 1371 1371 1447 1352 1352 1427 1371 1371 1447 1353 1353 1428 1353 1353 1428 1371 1371 1447 1372 1372 1448 1353 1353 1428 1372 1372 1448 1354 1354 1429 1354 1354 1429 1372 1372 1448 1373 1373 1449 1354 1354 1429 1373 1373 1449 1355 1355 1430 1355 1355 1430 1373 1373 1449 1374 1374 1450 1355 1355 1430 1374 1374 1450 1356 1356 1431 1356 1356 1431 1374 1374 1450 1375 1375 1451 1356 1356 1431 1375 1375 1451 1357 1357 1432 1357 1357 1432 1375 1375 1451 1376 1376 1452 1357 1357 1432 1376 1376 1452 1358 1358 1433 1358 1358 1433 1376 1376 1452 1377 1377 1453 1358 1358 1433 1377 1377 1453 1359 1359 1434 1359 1359 1434 1377 1377 1453 1378 1378 1454 1359 1359 1434 1378 1378 1454 1360 1360 1435 1360 1360 1435 1378 1378 1454 1379 1379 1455 1360 1360 1435 1379 1379 1455 1361 1361 1436 1361 1361 1436 1379 1379 1455 1380 1380 1456 1361 1361 1436 1380 1380 1456 1362 1362 1437 1362 1362 1437 1380 1380 1456 1381 1381 1457 1362 1362 1437 1381 1381 1457 1363 1363 1438 1363 1363 1438 1381 1381 1457 1382 1382 1458 1363 1363 1438 1382 1382 1458 1364 1364 1439 1364 1364 1439 1382 1382 1458 1383 1383 1459 1364 1364 1439 1383 1383 1459 1365 1365 1440 1365 1365 1440 1383 1383 1459 1384 1384 1460 1365 1365 1440 1384 1384 1460 1366 1366 1441 1366 1366 1441 1384 1384 1460 1385 1385 1461 1366 1366 1441 1385 1385 1461 1367 1367 1442 1367 1367 1442 1385 1385 1461 1368 1368 1462 1367 1367 1442 1368 1368 1462 1350 1350 1443 1368 1368 1444 1386 1386 1463 1387 1387 1464 1368 1368 1444 1387 1387 1464 1369 1369 1445 1369 1369 1445 1387 1387 1464 1388 1388 1465 1369 1369 1445 1388 1388 1465 1370 1370 1446 1370 1370 1446 1388 1388 1465 1389 1389 1466 1370 1370 1446 1389 1389 1466 1371 1371 1447 1371 1371 1447 1389 1389 1466 1390 1390 1467 1371 1371 1447 1390 1390 1467 1372 1372 1448 1372 1372 1448 1390 1390 1467 1391 1391 1468 1372 1372 1448 1391 1391 1468 1373 1373 1449 1373 1373 1449 1391 1391 1468 1392 1392 1469 1373 1373 1449 1392 1392 1469 1374 1374 1450 1374 1374 1450 1392 1392 1469 1393 1393 1470 1374 1374 1450 1393 1393 1470 1375 1375 1451 1375 1375 1451 1393 1393 1470 1394 1394 1471 1375 1375 1451 1394 1394 1471 1376 1376 1452 1376 1376 1452 1394 1394 1471 1395 1395 1472 1376 1376 1452 1395 1395 1472 1377 1377 1453 1377 1377 1453 1395 1395 1472 1396 1396 1473 1377 1377 1453 1396 1396 1473 1378 1378 1454 1378 1378 1454 1396 1396 1473 1397 1397 1474 1378 1378 1454 1397 1397 1474 1379 1379 1455 1379 1379 1455 1397 1397 1474 1398 1398 1475 1379 1379 1455 1398 1398 1475 1380 1380 1456 1380 1380 1456 1398 1398 1475 1399 1399 1476 1380 1380 1456 1399 1399 1476 1381 1381 1457 1381 1381 1457 1399 1399 1476 1400 1400 1477 1381 1381 1457 1400 1400 1477 1382 1382 1458 1382 1382 1458 1400 1400 1477 1401 1401 1478 1382 1382 1458 1401 1401 1478 1383 1383 1459 1383 1383 1459 1401 1401 1478 1402 1402 1479 1383 1383 1459 1402 1402 1479 1384 1384 1460 1384 1384 1460 1402 1402 1479 1403 1403 1480 1384 1384 1460 1403 1403 1480 1385 1385 1461 1385 1385 1461 1403 1403 1480 1386 1386 1481 1385 1385 1461 1386 1386 1481 1368 1368 1462 1386 1386 1463 1404 1404 1482 1405 1405 1483 1386 1386 1463 1405 1405 1483 1387 1387 1464 1387 1387 1464 1405 1405 1483 1406 1406 1484 1387 1387 1464 1406 1406 1484 1388 1388 1465 1388 1388 1465 1406 1406 1484 1407 1407 1485 1388 1388 1465 1407 1407 1485 1389 1389 1466 1389 1389 1466 1407 1407 1485 1408 1408 1486 1389 1389 1466 1408 1408 1486 1390 1390 1467 1390 1390 1467 1408 1408 1486 1409 1409 1487 1390 1390 1467 1409 1409 1487 1391 1391 1468 1391 1391 1468 1409 1409 1487 1410 1410 1488 1391 1391 1468 1410 1410 1488 1392 1392 1469 1392 1392 1469 1410 1410 1488 1411 1411 1489 1392 1392 1469 1411 1411 1489 1393 1393 1470 1393 1393 1470 1411 1411 1489 1412 1412 1490 1393 1393 1470 1412 1412 1490 1394 1394 1471 1394 1394 1471 1412 1412 1490 1413 1413 1491 1394 1394 1471 1413 1413 1491 1395 1395 1472 1395 1395 1472 1413 1413 1491 1414 1414 1492 1395 1395 1472 1414 1414 1492 1396 1396 1473 1396 1396 1473 1414 1414 1492 1415 1415 1493 1396 1396 1473 1415 1415 1493 1397 1397 1474 1397 1397 1474 1415 1415 1493 1416 1416 1494 1397 1397 1474 1416 1416 1494 1398 1398 1475 1398 1398 1475 1416 1416 1494 1417 1417 1495 1398 1398 1475 1417 1417 1495 1399 1399 1476 1399 1399 1476 1417 1417 1495 1418 1418 1496 1399 1399 1476 1418 1418 1496 1400 1400 1477 1400 1400 1477 1418 1418 1496 1419 1419 1497 1400 1400 1477 1419 1419 1497 1401 1401 1478 1401 1401 1478 1419 1419 1497 1420 1420 1498 1401 1401 1478 1420 1420 1498 1402 1402 1479 1402 1402 1479 1420 1420 1498 1421 1421 1499 1402 1402 1479 1421 1421 1499 1403 1403 1480 1403 1403 1480 1421 1421 1499 1404 1404 1500 1403 1403 1480 1404 1404 1500 1386 1386 1481 1404 1404 1482 1422 1422 1501 1423 1423 1502 1404 1404 1482 1423 1423 1502 1405 1405 1483 1405 1405 1483 1423 1423 1502 1424 1424 1503 1405 1405 1483 1424 1424 1503 1406 1406 1484 1406 1406 1484 1424 1424 1503 1425 1425 1504 1406 1406 1484 1425 1425 1504 1407 1407 1485 1407 1407 1485 1425 1425 1504 1426 1426 1505 1407 1407 1485 1426 1426 1505 1408 1408 1486 1408 1408 1486 1426 1426 1505 1427 1427 1506 1408 1408 1486 1427 1427 1506 1409 1409 1487 1409 1409 1487 1427 1427 1506 1428 1428 1507 1409 1409 1487 1428 1428 1507 1410 1410 1488 1410 1410 1488 1428 1428 1507 1429 1429 1508 1410 1410 1488 1429 1429 1508 1411 1411 1489 1411 1411 1489 1429 1429 1508 1430 1430 1509 1411 1411 1489 1430 1430 1509 1412 1412 1490 1412 1412 1490 1430 1430 1509 1431 1431 1510 1412 1412 1490 1431 1431 1510 1413 1413 1491 1413 1413 1491 1431 1431 1510 1432 1432 1511 1413 1413 1491 1432 1432 1511 1414 1414 1492 1414 1414 1492 1432 1432 1511 1433 1433 1512 1414 1414 1492 1433 1433 1512 1415 1415 1493 1415 1415 1493 1433 1433 1512 1434 1434 1513 1415 1415 1493 1434 1434 1513 1416 1416 1494 1416 1416 1494 1434 1434 1513 1435 1435 1514 1416 1416 1494 1435 1435 1514 1417 1417 1495 1417 1417 1495 1435 1435 1514 1436 1436 1515 1417 1417 1495 1436 1436 1515 1418 1418 1496 1418 1418 1496 1436 1436 1515 1437 1437 1516 1418 1418 1496 1437 1437 1516 1419 1419 1497 1419 1419 1497 1437 1437 1516 1438 1438 1517 1419 1419 1497 1438 1438 1517 1420 1420 1498 1420 1420 1498 1438 1438 1517 1439 1439 1518 1420 1420 1498 1439 1439 1518 1421 1421 1499 1421 1421 1499 1439 1439 1518 1422 1422 1519 1421 1421 1499 1422 1422 1519 1404 1404 1500 1422 1422 1501 1440 1440 1520 1441 1441 1521 1422 1422 1501 1441 1441 1521 1423 1423 1502 1423 1423 1502 1441 1441 1521 1442 1442 1522 1423 1423 1502 1442 1442 1522 1424 1424 1503 1424 1424 1503 1442 1442 1522 1443 1443 1523 1424 1424 1503 1443 1443 1523 1425 1425 1504 1425 1425 1504 1443 1443 1523 1444 1444 1524 1425 1425 1504 1444 1444 1524 1426 1426 1505 1426 1426 1505 1444 1444 1524 1445 1445 1525 1426 1426 1505 1445 1445 1525 1427 1427 1506 1427 1427 1506 1445 1445 1525 1446 1446 1526 1427 1427 1506 1446 1446 1526 1428 1428 1507 1428 1428 1507 1446 1446 1526 1447 1447 1527 1428 1428 1507 1447 1447 1527 1429 1429 1508 1429 1429 1508 1447 1447 1527 1448 1448 1528 1429 1429 1508 1448 1448 1528 1430 1430 1509 1430 1430 1509 1448 1448 1528 1449 1449 1529 1430 1430 1509 1449 1449 1529 1431 1431 1510 1431 1431 1510 1449 1449 1529 1450 1450 1530 1431 1431 1510 1450 1450 1530 1432 1432 1511 1432 1432 1511 1450 1450 1530 1451 1451 1531 1432 1432 1511 1451 1451 1531 1433 1433 1512 1433 1433 1512 1451 1451 1531 1452 1452 1532 1433 1433 1512 1452 1452 1532 1434 1434 1513 1434 1434 1513 1452 1452 1532 1453 1453 1533 1434 1434 1513 1453 1453 1533 1435 1435 1514 1435 1435 1514 1453 1453 1533 1454 1454 1534 1435 1435 1514 1454 1454 1534 1436 1436 1515 1436 1436 1515 1454 1454 1534 1455 1455 1535 1436 1436 1515 1455 1455 1535 1437 1437 1516 1437 1437 1516 1455 1455 1535 1456 1456 1536 1437 1437 1516 1456 1456 1536 1438 1438 1517 1438 1438 1517 1456 1456 1536 1457 1457 1537 1438 1438 1517 1457 1457 1537 1439 1439 1518 1439 1439 1518 1457 1457 1537 1440 1440 1538 1439 1439 1518 1440 1440 1538 1422 1422 1519 1440 1440 1520 1458 1458 1539 1459 1459 1540 1440 1440 1520 1459 1459 1540 1441 1441 1521 1441 1441 1521 1459 1459 1540 1460 1460 1541 1441 1441 1521 1460 1460 1541 1442 1442 1522 1442 1442 1522 1460 1460 1541 1461 1461 1542 1442 1442 1522 1461 1461 1542 1443 1443 1523 1443 1443 1523 1461 1461 1542 1462 1462 1543 1443 1443 1523 1462 1462 1543 1444 1444 1524 1444 1444 1524 1462 1462 1543 1463 1463 1544 1444 1444 1524 1463 1463 1544 1445 1445 1525 1445 1445 1525 1463 1463 1544 1464 1464 1545 1445 1445 1525 1464 1464 1545 1446 1446 1526 1446 1446 1526 1464 1464 1545 1465 1465 1546 1446 1446 1526 1465 1465 1546 1447 1447 1527 1447 1447 1527 1465 1465 1546 1466 1466 1547 1447 1447 1527 1466 1466 1547 1448 1448 1528 1448 1448 1528 1466 1466 1547 1467 1467 1548 1448 1448 1528 1467 1467 1548 1449 1449 1529 1449 1449 1529 1467 1467 1548 1468 1468 1549 1449 1449 1529 1468 1468 1549 1450 1450 1530 1450 1450 1530 1468 1468 1549 1469 1469 1550 1450 1450 1530 1469 1469 1550 1451 1451 1531 1451 1451 1531 1469 1469 1550 1470 1470 1551 1451 1451 1531 1470 1470 1551 1452 1452 1532 1452 1452 1532 1470 1470 1551 1471 1471 1552 1452 1452 1532 1471 1471 1552 1453 1453 1533 1453 1453 1533 1471 1471 1552 1472 1472 1553 1453 1453 1533 1472 1472 1553 1454 1454 1534 1454 1454 1534 1472 1472 1553 1473 1473 1554 1454 1454 1534 1473 1473 1554 1455 1455 1535 1455 1455 1535 1473 1473 1554 1474 1474 1555 1455 1455 1535 1474 1474 1555 1456 1456 1536 1456 1456 1536 1474 1474 1555 1475 1475 1556 1456 1456 1536 1475 1475 1556 1457 1457 1537 1457 1457 1537 1475 1475 1556 1458 1458 1557 1457 1457 1537 1458 1458 1557 1440 1440 1538 1458 1458 1539 1476 1476 1558 1477 1477 1559 1458 1458 1539 1477 1477 1559 1459 1459 1540 1459 1459 1540 1477 1477 1559 1478 1478 1560 1459 1459 1540 1478 1478 1560 1460 1460 1541 1460 1460 1541 1478 1478 1560 1479 1479 1561 1460 1460 1541 1479 1479 1561 1461 1461 1542 1461 1461 1542 1479 1479 1561 1480 1480 1562 1461 1461 1542 1480 1480 1562 1462 1462 1543 1462 1462 1543 1480 1480 1562 1481 1481 1563 1462 1462 1543 1481 1481 1563 1463 1463 1544 1463 1463 1544 1481 1481 1563 1482 1482 1564 1463 1463 1544 1482 1482 1564 1464 1464 1545 1464 1464 1545 1482 1482 1564 1483 1483 1565 1464 1464 1545 1483 1483 1565 1465 1465 1546 1465 1465 1546 1483 1483 1565 1484 1484 1566 1465 1465 1546 1484 1484 1566 1466 1466 1547 1466 1466 1547 1484 1484 1566 1485 1485 1567 1466 1466 1547 1485 1485 1567 1467 1467 1548 1467 1467 1548 1485 1485 1567 1486 1486 1568 1467 1467 1548 1486 1486 1568 1468 1468 1549 1468 1468 1549 1486 1486 1568 1487 1487 1569 1468 1468 1549 1487 1487 1569 1469 1469 1550 1469 1469 1550 1487 1487 1569 1488 1488 1570 1469 1469 1550 1488 1488 1570 1470 1470 1551 1470 1470 1551 1488 1488 1570 1489 1489 1571 1470 1470 1551 1489 1489 1571 1471 1471 1552 1471 1471 1552 1489 1489 1571 1490 1490 1572 1471 1471 1552 1490 1490 1572 1472 1472 1553 1472 1472 1553 1490 1490 1572 1491 1491 1573 1472 1472 1553 1491 1491 1573 1473 1473 1554 1473 1473 1554 1491 1491 1573 1492 1492 1574 1473 1473 1554 1492 1492 1574 1474 1474 1555 1474 1474 1555 1492 1492 1574 1493 1493 1575 1474 1474 1555 1493 1493 1575 1475 1475 1556 1475 1475 1556 1493 1493 1575 1476 1476 1576 1475 1475 1556 1476 1476 1576 1458 1458 1557 1476 1476 1558 1494 1494 1577 1495 1495 1578 1476 1476 1558 1495 1495 1578 1477 1477 1559 1477 1477 1559 1495 1495 1578 1496 1496 1579 1477 1477 1559 1496 1496 1579 1478 1478 1560 1478 1478 1560 1496 1496 1579 1497 1497 1580 1478 1478 1560 1497 1497 1580 1479 1479 1561 1479 1479 1561 1497 1497 1580 1498 1498 1581 1479 1479 1561 1498 1498 1581 1480 1480 1562 1480 1480 1562 1498 1498 1581 1499 1499 1582 1480 1480 1562 1499 1499 1582 1481 1481 1563 1481 1481 1563 1499 1499 1582 1500 1500 1583 1481 1481 1563 1500 1500 1583 1482 1482 1564 1482 1482 1564 1500 1500 1583 1501 1501 1584 1482 1482 1564 1501 1501 1584 1483 1483 1565 1483 1483 1565 1501 1501 1584 1502 1502 1585 1483 1483 1565 1502 1502 1585 1484 1484 1566 1484 1484 1566 1502 1502 1585 1503 1503 1586 1484 1484 1566 1503 1503 1586 1485 1485 1567 1485 1485 1567 1503 1503 1586 1504 1504 1587 1485 1485 1567 1504 1504 1587 1486 1486 1568 1486 1486 1568 1504 1504 1587 1505 1505 1588 1486 1486 1568 1505 1505 1588 1487 1487 1569 1487 1487 1569 1505 1505 1588 1506 1506 1589 1487 1487 1569 1506 1506 1589 1488 1488 1570 1488 1488 1570 1506 1506 1589 1507 1507 1590 1488 1488 1570 1507 1507 1590 1489 1489 1571 1489 1489 1571 1507 1507 1590 1508 1508 1591 1489 1489 1571 1508 1508 1591 1490 1490 1572 1490 1490 1572 1508 1508 1591 1509 1509 1592 1490 1490 1572 1509 1509 1592 1491 1491 1573 1491 1491 1573 1509 1509 1592 1510 1510 1593 1491 1491 1573 1510 1510 1593 1492 1492 1574 1492 1492 1574 1510 1510 1593 1511 1511 1594 1492 1492 1574 1511 1511 1594 1493 1493 1575 1493 1493 1575 1511 1511 1594 1494 1494 1595 1493 1493 1575 1494 1494 1595 1476 1476 1576 1494 1494 1577 1512 1512 1596 1513 1513 1597 1494 1494 1577 1513 1513 1597 1495 1495 1578 1495 1495 1578 1513 1513 1597 1514 1514 1598 1495 1495 1578 1514 1514 1598 1496 1496 1579 1496 1496 1579 1514 1514 1598 1515 1515 1599 1496 1496 1579 1515 1515 1599 1497 1497 1580 1497 1497 1580 1515 1515 1599 1516 1516 1600 1497 1497 1580 1516 1516 1600 1498 1498 1581 1498 1498 1581 1516 1516 1600 1517 1517 1601 1498 1498 1581 1517 1517 1601 1499 1499 1582 1499 1499 1582 1517 1517 1601 1518 1518 1602 1499 1499 1582 1518 1518 1602 1500 1500 1583 1500 1500 1583 1518 1518 1602 1519 1519 1603 1500 1500 1583 1519 1519 1603 1501 1501 1584 1501 1501 1584 1519 1519 1603 1520 1520 1604 1501 1501 1584 1520 1520 1604 1502 1502 1585 1502 1502 1585 1520 1520 1604 1521 1521 1605 1502 1502 1585 1521 1521 1605 1503 1503 1586 1503 1503 1586 1521 1521 1605 1522 1522 1606 1503 1503 1586 1522 1522 1606 1504 1504 1587 1504 1504 1587 1522 1522 1606 1523 1523 1607 1504 1504 1587 1523 1523 1607 1505 1505 1588 1505 1505 1588 1523 1523 1607 1524 1524 1608 1505 1505 1588 1524 1524 1608 1506 1506 1589 1506 1506 1589 1524 1524 1608 1525 1525 1609 1506 1506 1589 1525 1525 1609 1507 1507 1590 1507 1507 1590 1525 1525 1609 1526 1526 1610 1507 1507 1590 1526 1526 1610 1508 1508 1591 1508 1508 1591 1526 1526 1610 1527 1527 1611 1508 1508 1591 1527 1527 1611 1509 1509 1592 1509 1509 1592 1527 1527 1611 1528 1528 1612 1509 1509 1592 1528 1528 1612 1510 1510 1593 1510 1510 1593 1528 1528 1612 1529 1529 1613 1510 1510 1593 1529 1529 1613 1511 1511 1594 1511 1511 1594 1529 1529 1613 1512 1512 1614 1511 1511 1594 1512 1512 1614 1494 1494 1595 1512 1512 1596 1530 1530 1615 1531 1531 1616 1512 1512 1596 1531 1531 1616 1513 1513 1597 1513 1513 1597 1531 1531 1616 1532 1532 1617 1513 1513 1597 1532 1532 1617 1514 1514 1598 1514 1514 1598 1532 1532 1617 1533 1533 1618 1514 1514 1598 1533 1533 1618 1515 1515 1599 1515 1515 1599 1533 1533 1618 1534 1534 1619 1515 1515 1599 1534 1534 1619 1516 1516 1600 1516 1516 1600 1534 1534 1619 1535 1535 1620 1516 1516 1600 1535 1535 1620 1517 1517 1601 1517 1517 1601 1535 1535 1620 1536 1536 1621 1517 1517 1601 1536 1536 1621 1518 1518 1602 1518 1518 1602 1536 1536 1621 1537 1537 1622 1518 1518 1602 1537 1537 1622 1519 1519 1603 1519 1519 1603 1537 1537 1622 1538 1538 1623 1519 1519 1603 1538 1538 1623 1520 1520 1604 1520 1520 1604 1538 1538 1623 1539 1539 1624 1520 1520 1604 1539 1539 1624 1521 1521 1605 1521 1521 1605 1539 1539 1624 1540 1540 1625 1521 1521 1605 1540 1540 1625 1522 1522 1606 1522 1522 1606 1540 1540 1625 1541 1541 1626 1522 1522 1606 1541 1541 1626 1523 1523 1607 1523 1523 1607 1541 1541 1626 1542 1542 1627 1523 1523 1607 1542 1542 1627 1524 1524 1608 1524 1524 1608 1542 1542 1627 1543 1543 1628 1524 1524 1608 1543 1543 1628 1525 1525 1609 1525 1525 1609 1543 1543 1628 1544 1544 1629 1525 1525 1609 1544 1544 1629 1526 1526 1610 1526 1526 1610 1544 1544 1629 1545 1545 1630 1526 1526 1610 1545 1545 1630 1527 1527 1611 1527 1527 1611 1545 1545 1630 1546 1546 1631 1527 1527 1611 1546 1546 1631 1528 1528 1612 1528 1528 1612 1546 1546 1631 1547 1547 1632 1528 1528 1612 1547 1547 1632 1529 1529 1613 1529 1529 1613 1547 1547 1632 1530 1530 1633 1529 1529 1613 1530 1530 1633 1512 1512 1614 1530 1530 1615 1548 1548 1634 1549 1549 1635 1530 1530 1615 1549 1549 1635 1531 1531 1616 1531 1531 1616 1549 1549 1635 1550 1550 1636 1531 1531 1616 1550 1550 1636 1532 1532 1617 1532 1532 1617 1550 1550 1636 1551 1551 1637 1532 1532 1617 1551 1551 1637 1533 1533 1618 1533 1533 1618 1551 1551 1637 1552 1552 1638 1533 1533 1618 1552 1552 1638 1534 1534 1619 1534 1534 1619 1552 1552 1638 1553 1553 1639 1534 1534 1619 1553 1553 1639 1535 1535 1620 1535 1535 1620 1553 1553 1639 1554 1554 1640 1535 1535 1620 1554 1554 1640 1536 1536 1621 1536 1536 1621 1554 1554 1640 1555 1555 1641 1536 1536 1621 1555 1555 1641 1537 1537 1622 1537 1537 1622 1555 1555 1641 1556 1556 1642 1537 1537 1622 1556 1556 1642 1538 1538 1623 1538 1538 1623 1556 1556 1642 1557 1557 1643 1538 1538 1623 1557 1557 1643 1539 1539 1624 1539 1539 1624 1557 1557 1643 1558 1558 1644 1539 1539 1624 1558 1558 1644 1540 1540 1625 1540 1540 1625 1558 1558 1644 1559 1559 1645 1540 1540 1625 1559 1559 1645 1541 1541 1626 1541 1541 1626 1559 1559 1645 1560 1560 1646 1541 1541 1626 1560 1560 1646 1542 1542 1627 1542 1542 1627 1560 1560 1646 1561 1561 1647 1542 1542 1627 1561 1561 1647 1543 1543 1628 1543 1543 1628 1561 1561 1647 1562 1562 1648 1543 1543 1628 1562 1562 1648 1544 1544 1629 1544 1544 1629 1562 1562 1648 1563 1563 1649 1544 1544 1629 1563 1563 1649 1545 1545 1630 1545 1545 1630 1563 1563 1649 1564 1564 1650 1545 1545 1630 1564 1564 1650 1546 1546 1631 1546 1546 1631 1564 1564 1650 1565 1565 1651 1546 1546 1631 1565 1565 1651 1547 1547 1632 1547 1547 1632 1565 1565 1651 1548 1548 1652 1547 1547 1632 1548 1548 1652 1530 1530 1633 1548 1548 1634 1566 1566 1653 1567 1567 1654 1548 1548 1634 1567 1567 1654 1549 1549 1635 1549 1549 1635 1567 1567 1654 1568 1568 1655 1549 1549 1635 1568 1568 1655 1550 1550 1636 1550 1550 1636 1568 1568 1655 1569 1569 1656 1550 1550 1636 1569 1569 1656 1551 1551 1637 1551 1551 1637 1569 1569 1656 1570 1570 1657 1551 1551 1637 1570 1570 1657 1552 1552 1638 1552 1552 1638 1570 1570 1657 1571 1571 1658 1552 1552 1638 1571 1571 1658 1553 1553 1639 1553 1553 1639 1571 1571 1658 1572 1572 1659 1553 1553 1639 1572 1572 1659 1554 1554 1640 1554 1554 1640 1572 1572 1659 1573 1573 1660 1554 1554 1640 1573 1573 1660 1555 1555 1641 1555 1555 1641 1573 1573 1660 1574 1574 1661 1555 1555 1641 1574 1574 1661 1556 1556 1642 1556 1556 1642 1574 1574 1661 1575 1575 1662 1556 1556 1642 1575 1575 1662 1557 1557 1643 1557 1557 1643 1575 1575 1662 1576 1576 1663 1557 1557 1643 1576 1576 1663 1558 1558 1644 1558 1558 1644 1576 1576 1663 1577 1577 1664 1558 1558 1644 1577 1577 1664 1559 1559 1645 1559 1559 1645 1577 1577 1664 1578 1578 1665 1559 1559 1645 1578 1578 1665 1560 1560 1646 1560 1560 1646 1578 1578 1665 1579 1579 1666 1560 1560 1646 1579 1579 1666 1561 1561 1647 1561 1561 1647 1579 1579 1666 1580 1580 1667 1561 1561 1647 1580 1580 1667 1562 1562 1648 1562 1562 1648 1580 1580 1667 1581 1581 1668 1562 1562 1648 1581 1581 1668 1563 1563 1649 1563 1563 1649 1581 1581 1668 1582 1582 1669 1563 1563 1649 1582 1582 1669 1564 1564 1650 1564 1564 1650 1582 1582 1669 1583 1583 1670 1564 1564 1650 1583 1583 1670 1565 1565 1651 1565 1565 1651 1583 1583 1670 1566 1566 1671 1565 1565 1651 1566 1566 1671 1548 1548 1652 1566 1566 1653 1584 1584 1672 1585 1585 1673 1566 1566 1653 1585 1585 1673 1567 1567 1654 1567 1567 1654 1585 1585 1673 1586 1586 1674 1567 1567 1654 1586 1586 1674 1568 1568 1655 1568 1568 1655 1586 1586 1674 1587 1587 1675 1568 1568 1655 1587 1587 1675 1569 1569 1656 1569 1569 1656 1587 1587 1675 1588 1588 1676 1569 1569 1656 1588 1588 1676 1570 1570 1657 1570 1570 1657 1588 1588 1676 1589 1589 1677 1570 1570 1657 1589 1589 1677 1571 1571 1658 1571 1571 1658 1589 1589 1677 1590 1590 1678 1571 1571 1658 1590 1590 1678 1572 1572 1659 1572 1572 1659 1590 1590 1678 1591 1591 1679 1572 1572 1659 1591 1591 1679 1573 1573 1660 1573 1573 1660 1591 1591 1679 1592 1592 1680 1573 1573 1660 1592 1592 1680 1574 1574 1661 1574 1574 1661 1592 1592 1680 1593 1593 1681 1574 1574 1661 1593 1593 1681 1575 1575 1662 1575 1575 1662 1593 1593 1681 1594 1594 1682 1575 1575 1662 1594 1594 1682 1576 1576 1663 1576 1576 1663 1594 1594 1682 1595 1595 1683 1576 1576 1663 1595 1595 1683 1577 1577 1664 1577 1577 1664 1595 1595 1683 1596 1596 1684 1577 1577 1664 1596 1596 1684 1578 1578 1665 1578 1578 1665 1596 1596 1684 1597 1597 1685 1578 1578 1665 1597 1597 1685 1579 1579 1666 1579 1579 1666 1597 1597 1685 1598 1598 1686 1579 1579 1666 1598 1598 1686 1580 1580 1667 1580 1580 1667 1598 1598 1686 1599 1599 1687 1580 1580 1667 1599 1599 1687 1581 1581 1668 1581 1581 1668 1599 1599 1687 1600 1600 1688 1581 1581 1668 1600 1600 1688 1582 1582 1669 1582 1582 1669 1600 1600 1688 1601 1601 1689 1582 1582 1669 1601 1601 1689 1583 1583 1670 1583 1583 1670 1601 1601 1689 1584 1584 1690 1583 1583 1670 1584 1584 1690 1566 1566 1671 1584 1584 1672 1602 1602 1691 1603 1603 1692 1584 1584 1672 1603 1603 1692 1585 1585 1673 1585 1585 1673 1603 1603 1692 1604 1604 1693 1585 1585 1673 1604 1604 1693 1586 1586 1674 1586 1586 1674 1604 1604 1693 1605 1605 1694 1586 1586 1674 1605 1605 1694 1587 1587 1675 1587 1587 1675 1605 1605 1694 1606 1606 1695 1587 1587 1675 1606 1606 1695 1588 1588 1676 1588 1588 1676 1606 1606 1695 1607 1607 1696 1588 1588 1676 1607 1607 1696 1589 1589 1677 1589 1589 1677 1607 1607 1696 1608 1608 1697 1589 1589 1677 1608 1608 1697 1590 1590 1678 1590 1590 1678 1608 1608 1697 1609 1609 1698 1590 1590 1678 1609 1609 1698 1591 1591 1679 1591 1591 1679 1609 1609 1698 1610 1610 1699 1591 1591 1679 1610 1610 1699 1592 1592 1680 1592 1592 1680 1610 1610 1699 1611 1611 1700 1592 1592 1680 1611 1611 1700 1593 1593 1681 1593 1593 1681 1611 1611 1700 1612 1612 1701 1593 1593 1681 1612 1612 1701 1594 1594 1682 1594 1594 1682 1612 1612 1701 1613 1613 1702 1594 1594 1682 1613 1613 1702 1595 1595 1683 1595 1595 1683 1613 1613 1702 1614 1614 1703 1595 1595 1683 1614 1614 1703 1596 1596 1684 1596 1596 1684 1614 1614 1703 1615 1615 1704 1596 1596 1684 1615 1615 1704 1597 1597 1685 1597 1597 1685 1615 1615 1704 1616 1616 1705 1597 1597 1685 1616 1616 1705 1598 1598 1686 1598 1598 1686 1616 1616 1705 1617 1617 1706 1598 1598 1686 1617 1617 1706 1599 1599 1687 1599 1599 1687 1617 1617 1706 1618 1618 1707 1599 1599 1687 1618 1618 1707 1600 1600 1688 1600 1600 1688 1618 1618 1707 1619 1619 1708 1600 1600 1688 1619 1619 1708 1601 1601 1689 1601 1601 1689 1619 1619 1708 1602 1602 1709 1601 1601 1689 1602 1602 1709 1584 1584 1690 1602 1602 1691 1620 1620 1710 1621 1621 1711 1602 1602 1691 1621 1621 1711 1603 1603 1692 1603 1603 1692 1621 1621 1711 1622 1622 1712 1603 1603 1692 1622 1622 1712 1604 1604 1693 1604 1604 1693 1622 1622 1712 1623 1623 1713 1604 1604 1693 1623 1623 1713 1605 1605 1694 1605 1605 1694 1623 1623 1713 1624 1624 1714 1605 1605 1694 1624 1624 1714 1606 1606 1695 1606 1606 1695 1624 1624 1714 1625 1625 1715 1606 1606 1695 1625 1625 1715 1607 1607 1696 1607 1607 1696 1625 1625 1715 1626 1626 1716 1607 1607 1696 1626 1626 1716 1608 1608 1697 1608 1608 1697 1626 1626 1716 1627 1627 1717 1608 1608 1697 1627 1627 1717 1609 1609 1698 1609 1609 1698 1627 1627 1717 1628 1628 1718 1609 1609 1698 1628 1628 1718 1610 1610 1699 1610 1610 1699 1628 1628 1718 1629 1629 1719 1610 1610 1699 1629 1629 1719 1611 1611 1700 1611 1611 1700 1629 1629 1719 1630 1630 1720 1611 1611 1700 1630 1630 1720 1612 1612 1701 1612 1612 1701 1630 1630 1720 1631 1631 1721 1612 1612 1701 1631 1631 1721 1613 1613 1702 1613 1613 1702 1631 1631 1721 1632 1632 1722 1613 1613 1702 1632 1632 1722 1614 1614 1703 1614 1614 1703 1632 1632 1722 1633 1633 1723 1614 1614 1703 1633 1633 1723 1615 1615 1704 1615 1615 1704 1633 1633 1723 1634 1634 1724 1615 1615 1704 1634 1634 1724 1616 1616 1705 1616 1616 1705 1634 1634 1724 1635 1635 1725 1616 1616 1705 1635 1635 1725 1617 1617 1706 1617 1617 1706 1635 1635 1725 1636 1636 1726 1617 1617 1706 1636 1636 1726 1618 1618 1707 1618 1618 1707 1636 1636 1726 1637 1637 1727 1618 1618 1707 1637 1637 1727 1619 1619 1708 1619 1619 1708 1637 1637 1727 1620 1620 1728 1619 1619 1708 1620 1620 1728 1602 1602 1709 1620 1620 1710 1638 1638 1729 1639 1639 1730 1620 1620 1710 1639 1639 1730 1621 1621 1711 1621 1621 1711 1639 1639 1730 1640 1640 1731 1621 1621 1711 1640 1640 1731 1622 1622 1712 1622 1622 1712 1640 1640 1731 1641 1641 1732 1622 1622 1712 1641 1641 1732 1623 1623 1713 1623 1623 1713 1641 1641 1732 1642 1642 1733 1623 1623 1713 1642 1642 1733 1624 1624 1714 1624 1624 1714 1642 1642 1733 1643 1643 1734 1624 1624 1714 1643 1643 1734 1625 1625 1715 1625 1625 1715 1643 1643 1734 1644 1644 1735 1625 1625 1715 1644 1644 1735 1626 1626 1716 1626 1626 1716 1644 1644 1735 1645 1645 1736 1626 1626 1716 1645 1645 1736 1627 1627 1717 1627 1627 1717 1645 1645 1736 1646 1646 1737 1627 1627 1717 1646 1646 1737 1628 1628 1718 1628 1628 1718 1646 1646 1737 1647 1647 1738 1628 1628 1718 1647 1647 1738 1629 1629 1719 1629 1629 1719 1647 1647 1738 1648 1648 1739 1629 1629 1719 1648 1648 1739 1630 1630 1720 1630 1630 1720 1648 1648 1739 1649 1649 1740 1630 1630 1720 1649 1649 1740 1631 1631 1721 1631 1631 1721 1649 1649 1740 1650 1650 1741 1631 1631 1721 1650 1650 1741 1632 1632 1722 1632 1632 1722 1650 1650 1741 1651 1651 1742 1632 1632 1722 1651 1651 1742 1633 1633 1723 1633 1633 1723 1651 1651 1742 1652 1652 1743 1633 1633 1723 1652 1652 1743 1634 1634 1724 1634 1634 1724 1652 1652 1743 1653 1653 1744 1634 1634 1724 1653 1653 1744 1635 1635 1725 1635 1635 1725 1653 1653 1744 1654 1654 1745 1635 1635 1725 1654 1654 1745 1636 1636 1726 1636 1636 1726 1654 1654 1745 1655 1655 1746 1636 1636 1726 1655 1655 1746 1637 1637 1727 1637 1637 1727 1655 1655 1746 1638 1638 1747 1637 1637 1727 1638 1638 1747 1620 1620 1728 1638 1638 1729 1656 1656 1748 1657 1657 1749 1638 1638 1729 1657 1657 1749 1639 1639 1730 1639 1639 1730 1657 1657 1749 1658 1658 1750 1639 1639 1730 1658 1658 1750 1640 1640 1731 1640 1640 1731 1658 1658 1750 1659 1659 1751 1640 1640 1731 1659 1659 1751 1641 1641 1732 1641 1641 1732 1659 1659 1751 1660 1660 1752 1641 1641 1732 1660 1660 1752 1642 1642 1733 1642 1642 1733 1660 1660 1752 1661 1661 1753 1642 1642 1733 1661 1661 1753 1643 1643 1734 1643 1643 1734 1661 1661 1753 1662 1662 1754 1643 1643 1734 1662 1662 1754 1644 1644 1735 1644 1644 1735 1662 1662 1754 1663 1663 1755 1644 1644 1735 1663 1663 1755 1645 1645 1736 1645 1645 1736 1663 1663 1755 1664 1664 1756 1645 1645 1736 1664 1664 1756 1646 1646 1737 1646 1646 1737 1664 1664 1756 1665 1665 1757 1646 1646 1737 1665 1665 1757 1647 1647 1738 1647 1647 1738 1665 1665 1757 1666 1666 1758 1647 1647 1738 1666 1666 1758 1648 1648 1739 1648 1648 1739 1666 1666 1758 1667 1667 1759 1648 1648 1739 1667 1667 1759 1649 1649 1740 1649 1649 1740 1667 1667 1759 1668 1668 1760 1649 1649 1740 1668 1668 1760 1650 1650 1741 1650 1650 1741 1668 1668 1760 1669 1669 1761 1650 1650 1741 1669 1669 1761 1651 1651 1742 1651 1651 1742 1669 1669 1761 1670 1670 1762 1651 1651 1742 1670 1670 1762 1652 1652 1743 1652 1652 1743 1670 1670 1762 1671 1671 1763 1652 1652 1743 1671 1671 1763 1653 1653 1744 1653 1653 1744 1671 1671 1763 1672 1672 1764 1653 1653 1744 1672 1672 1764 1654 1654 1745 1654 1654 1745 1672 1672 1764 1673 1673 1765 1654 1654 1745 1673 1673 1765 1655 1655 1746 1655 1655 1746 1673 1673 1765 1656 1656 1766 1655 1655 1746 1656 1656 1766 1638 1638 1747 1656 1656 1748 1674 1674 1767 1675 1675 1768 1656 1656 1748 1675 1675 1768 1657 1657 1749 1657 1657 1749 1675 1675 1768 1676 1676 1769 1657 1657 1749 1676 1676 1769 1658 1658 1750 1658 1658 1750 1676 1676 1769 1677 1677 1770 1658 1658 1750 1677 1677 1770 1659 1659 1751 1659 1659 1751 1677 1677 1770 1678 1678 1771 1659 1659 1751 1678 1678 1771 1660 1660 1752 1660 1660 1752 1678 1678 1771 1679 1679 1772 1660 1660 1752 1679 1679 1772 1661 1661 1753 1661 1661 1753 1679 1679 1772 1680 1680 1773 1661 1661 1753 1680 1680 1773 1662 1662 1754 1662 1662 1754 1680 1680 1773 1681 1681 1774 1662 1662 1754 1681 1681 1774 1663 1663 1755 1663 1663 1755 1681 1681 1774 1682 1682 1775 1663 1663 1755 1682 1682 1775 1664 1664 1756 1664 1664 1756 1682 1682 1775 1683 1683 1776 1664 1664 1756 1683 1683 1776 1665 1665 1757 1665 1665 1757 1683 1683 1776 1684 1684 1777 1665 1665 1757 1684 1684 1777 1666 1666 1758 1666 1666 1758 1684 1684 1777 1685 1685 1778 1666 1666 1758 1685 1685 1778 1667 1667 1759 1667 1667 1759 1685 1685 1778 1686 1686 1779 1667 1667 1759 1686 1686 1779 1668 1668 1760 1668 1668 1760 1686 1686 1779 1687 1687 1780 1668 1668 1760 1687 1687 1780 1669 1669 1761 1669 1669 1761 1687 1687 1780 1688 1688 1781 1669 1669 1761 1688 1688 1781 1670 1670 1762 1670 1670 1762 1688 1688 1781 1689 1689 1782 1670 1670 1762 1689 1689 1782 1671 1671 1763 1671 1671 1763 1689 1689 1782 1690 1690 1783 1671 1671 1763 1690 1690 1783 1672 1672 1764 1672 1672 1764 1690 1690 1783 1691 1691 1784 1672 1672 1764 1691 1691 1784 1673 1673 1765 1673 1673 1765 1691 1691 1784 1674 1674 1785 1673 1673 1765 1674 1674 1785 1656 1656 1766 1674 1674 1767 1692 1692 1786 1693 1693 1787 1674 1674 1767 1693 1693 1787 1675 1675 1768 1675 1675 1768 1693 1693 1787 1694 1694 1788 1675 1675 1768 1694 1694 1788 1676 1676 1769 1676 1676 1769 1694 1694 1788 1695 1695 1789 1676 1676 1769 1695 1695 1789 1677 1677 1770 1677 1677 1770 1695 1695 1789 1696 1696 1790 1677 1677 1770 1696 1696 1790 1678 1678 1771 1678 1678 1771 1696 1696 1790 1697 1697 1791 1678 1678 1771 1697 1697 1791 1679 1679 1772 1679 1679 1772 1697 1697 1791 1698 1698 1792 1679 1679 1772 1698 1698 1792 1680 1680 1773 1680 1680 1773 1698 1698 1792 1699 1699 1793 1680 1680 1773 1699 1699 1793 1681 1681 1774 1681 1681 1774 1699 1699 1793 1700 1700 1794 1681 1681 1774 1700 1700 1794 1682 1682 1775 1682 1682 1775 1700 1700 1794 1701 1701 1795 1682 1682 1775 1701 1701 1795 1683 1683 1776 1683 1683 1776 1701 1701 1795 1702 1702 1796 1683 1683 1776 1702 1702 1796 1684 1684 1777 1684 1684 1777 1702 1702 1796 1703 1703 1797 1684 1684 1777 1703 1703 1797 1685 1685 1778 1685 1685 1778 1703 1703 1797 1704 1704 1798 1685 1685 1778 1704 1704 1798 1686 1686 1779 1686 1686 1779 1704 1704 1798 1705 1705 1799 1686 1686 1779 1705 1705 1799 1687 1687 1780 1687 1687 1780 1705 1705 1799 1706 1706 1800 1687 1687 1780 1706 1706 1800 1688 1688 1781 1688 1688 1781 1706 1706 1800 1707 1707 1801 1688 1688 1781 1707 1707 1801 1689 1689 1782 1689 1689 1782 1707 1707 1801 1708 1708 1802 1689 1689 1782 1708 1708 1802 1690 1690 1783 1690 1690 1783 1708 1708 1802 1709 1709 1803 1690 1690 1783 1709 1709 1803 1691 1691 1784 1691 1691 1784 1709 1709 1803 1692 1692 1804 1691 1691 1784 1692 1692 1804 1674 1674 1785 1692 1692 1786 1710 1710 1805 1711 1711 1806 1692 1692 1786 1711 1711 1806 1693 1693 1787 1693 1693 1787 1711 1711 1806 1712 1712 1807 1693 1693 1787 1712 1712 1807 1694 1694 1788 1694 1694 1788 1712 1712 1807 1713 1713 1808 1694 1694 1788 1713 1713 1808 1695 1695 1789 1695 1695 1789 1713 1713 1808 1714 1714 1809 1695 1695 1789 1714 1714 1809 1696 1696 1790 1696 1696 1790 1714 1714 1809 1715 1715 1810 1696 1696 1790 1715 1715 1810 1697 1697 1791 1697 1697 1791 1715 1715 1810 1716 1716 1811 1697 1697 1791 1716 1716 1811 1698 1698 1792 1698 1698 1792 1716 1716 1811 1717 1717 1812 1698 1698 1792 1717 1717 1812 1699 1699 1793 1699 1699 1793 1717 1717 1812 1718 1718 1813 1699 1699 1793 1718 1718 1813 1700 1700 1794 1700 1700 1794 1718 1718 1813 1719 1719 1814 1700 1700 1794 1719 1719 1814 1701 1701 1795 1701 1701 1795 1719 1719 1814 1720 1720 1815 1701 1701 1795 1720 1720 1815 1702 1702 1796 1702 1702 1796 1720 1720 1815 1721 1721 1816 1702 1702 1796 1721 1721 1816 1703 1703 1797 1703 1703 1797 1721 1721 1816 1722 1722 1817 1703 1703 1797 1722 1722 1817 1704 1704 1798 1704 1704 1798 1722 1722 1817 1723 1723 1818 1704 1704 1798 1723 1723 1818 1705 1705 1799 1705 1705 1799 1723 1723 1818 1724 1724 1819 1705 1705 1799 1724 1724 1819 1706 1706 1800 1706 1706 1800 1724 1724 1819 1725 1725 1820 1706 1706 1800 1725 1725 1820 1707 1707 1801 1707 1707 1801 1725 1725 1820 1726 1726 1821 1707 1707 1801 1726 1726 1821 1708 1708 1802 1708 1708 1802 1726 1726 1821 1727 1727 1822 1708 1708 1802 1727 1727 1822 1709 1709 1803 1709 1709 1803 1727 1727 1822 1710 1710 1823 1709 1709 1803 1710 1710 1823 1692 1692 1804 1710 1710 1805 1728 1728 1824 1729 1729 1825 1710 1710 1805 1729 1729 1825 1711 1711 1806 1711 1711 1806 1729 1729 1825 1730 1730 1826 1711 1711 1806 1730 1730 1826 1712 1712 1807 1712 1712 1807 1730 1730 1826 1731 1731 1827 1712 1712 1807 1731 1731 1827 1713 1713 1808 1713 1713 1808 1731 1731 1827 1732 1732 1828 1713 1713 1808 1732 1732 1828 1714 1714 1809 1714 1714 1809 1732 1732 1828 1733 1733 1829 1714 1714 1809 1733 1733 1829 1715 1715 1810 1715 1715 1810 1733 1733 1829 1734 1734 1830 1715 1715 1810 1734 1734 1830 1716 1716 1811 1716 1716 1811 1734 1734 1830 1735 1735 1831 1716 1716 1811 1735 1735 1831 1717 1717 1812 1717 1717 1812 1735 1735 1831 1736 1736 1832 1717 1717 1812 1736 1736 1832 1718 1718 1813 1718 1718 1813 1736 1736 1832 1737 1737 1833 1718 1718 1813 1737 1737 1833 1719 1719 1814 1719 1719 1814 1737 1737 1833 1738 1738 1834 1719 1719 1814 1738 1738 1834 1720 1720 1815 1720 1720 1815 1738 1738 1834 1739 1739 1835 1720 1720 1815 1739 1739 1835 1721 1721 1816 1721 1721 1816 1739 1739 1835 1740 1740 1836 1721 1721 1816 1740 1740 1836 1722 1722 1817 1722 1722 1817 1740 1740 1836 1741 1741 1837 1722 1722 1817 1741 1741 1837 1723 1723 1818 1723 1723 1818 1741 1741 1837 1742 1742 1838 1723 1723 1818 1742 1742 1838 1724 1724 1819 1724 1724 1819 1742 1742 1838 1743 1743 1839 1724 1724 1819 1743 1743 1839 1725 1725 1820 1725 1725 1820 1743 1743 1839 1744 1744 1840 1725 1725 1820 1744 1744 1840 1726 1726 1821 1726 1726 1821 1744 1744 1840 1745 1745 1841 1726 1726 1821 1745 1745 1841 1727 1727 1822 1727 1727 1822 1745 1745 1841 1728 1728 1842 1727 1727 1822 1728 1728 1842 1710 1710 1823 1728 1728 1824 1746 1746 1843 1747 1747 1844 1728 1728 1824 1747 1747 1844 1729 1729 1825 1729 1729 1825 1747 1747 1844 1748 1748 1845 1729 1729 1825 1748 1748 1845 1730 1730 1826 1730 1730 1826 1748 1748 1845 1749 1749 1846 1730 1730 1826 1749 1749 1846 1731 1731 1827 1731 1731 1827 1749 1749 1846 1750 1750 1847 1731 1731 1827 1750 1750 1847 1732 1732 1828 1732 1732 1828 1750 1750 1847 1751 1751 1848 1732 1732 1828 1751 1751 1848 1733 1733 1829 1733 1733 1829 1751 1751 1848 1752 1752 1849 1733 1733 1829 1752 1752 1849 1734 1734 1830 1734 1734 1830 1752 1752 1849 1753 1753 1850 1734 1734 1830 1753 1753 1850 1735 1735 1831 1735 1735 1831 1753 1753 1850 1754 1754 1851 1735 1735 1831 1754 1754 1851 1736 1736 1832 1736 1736 1832 1754 1754 1851 1755 1755 1852 1736 1736 1832 1755 1755 1852 1737 1737 1833 1737 1737 1833 1755 1755 1852 1756 1756 1853 1737 1737 1833 1756 1756 1853 1738 1738 1834 1738 1738 1834 1756 1756 1853 1757 1757 1854 1738 1738 1834 1757 1757 1854 1739 1739 1835 1739 1739 1835 1757 1757 1854 1758 1758 1855 1739 1739 1835 1758 1758 1855 1740 1740 1836 1740 1740 1836 1758 1758 1855 1759 1759 1856 1740 1740 1836 1759 1759 1856 1741 1741 1837 1741 1741 1837 1759 1759 1856 1760 1760 1857 1741 1741 1837 1760 1760 1857 1742 1742 1838 1742 1742 1838 1760 1760 1857 1761 1761 1858 1742 1742 1838 1761 1761 1858 1743 1743 1839 1743 1743 1839 1761 1761 1858 1762 1762 1859 1743 1743 1839 1762 1762 1859 1744 1744 1840 1744 1744 1840 1762 1762 1859 1763 1763 1860 1744 1744 1840 1763 1763 1860 1745 1745 1841 1745 1745 1841 1763 1763 1860 1746 1746 1861 1745 1745 1841 1746 1746 1861 1728 1728 1842 1746 1746 1843 1764 1764 1862 1765 1765 1863 1746 1746 1843 1765 1765 1863 1747 1747 1844 1747 1747 1844 1765 1765 1863 1766 1766 1864 1747 1747 1844 1766 1766 1864 1748 1748 1845 1748 1748 1845 1766 1766 1864 1767 1767 1865 1748 1748 1845 1767 1767 1865 1749 1749 1846 1749 1749 1846 1767 1767 1865 1768 1768 1866 1749 1749 1846 1768 1768 1866 1750 1750 1847 1750 1750 1847 1768 1768 1866 1769 1769 1867 1750 1750 1847 1769 1769 1867 1751 1751 1848 1751 1751 1848 1769 1769 1867 1770 1770 1868 1751 1751 1848 1770 1770 1868 1752 1752 1849 1752 1752 1849 1770 1770 1868 1771 1771 1869 1752 1752 1849 1771 1771 1869 1753 1753 1850 1753 1753 1850 1771 1771 1869 1772 1772 1870 1753 1753 1850 1772 1772 1870 1754 1754 1851 1754 1754 1851 1772 1772 1870 1773 1773 1871 1754 1754 1851 1773 1773 1871 1755 1755 1852 1755 1755 1852 1773 1773 1871 1774 1774 1872 1755 1755 1852 1774 1774 1872 1756 1756 1853 1756 1756 1853 1774 1774 1872 1775 1775 1873 1756 1756 1853 1775 1775 1873 1757 1757 1854 1757 1757 1854 1775 1775 1873 1776 1776 1874 1757 1757 1854 1776 1776 1874 1758 1758 1855 1758 1758 1855 1776 1776 1874 1777 1777 1875 1758 1758 1855 1777 1777 1875 1759 1759 1856 1759 1759 1856 1777 1777 1875 1778 1778 1876 1759 1759 1856 1778 1778 1876 1760 1760 1857 1760 1760 1857 1778 1778 1876 1779 1779 1877 1760 1760 1857 1779 1779 1877 1761 1761 1858 1761 1761 1858 1779 1779 1877 1780 1780 1878 1761 1761 1858 1780 1780 1878 1762 1762 1859 1762 1762 1859 1780 1780 1878 1781 1781 1879 1762 1762 1859 1781 1781 1879 1763 1763 1860 1763 1763 1860 1781 1781 1879 1764 1764 1880 1763 1763 1860 1764 1764 1880 1746 1746 1861 1764 1764 1862 1782 1782 1881 1783 1783 1882 1764 1764 1862 1783 1783 1882 1765 1765 1863 1765 1765 1863 1783 1783 1882 1784 1784 1883 1765 1765 1863 1784 1784 1883 1766 1766 1864 1766 1766 1864 1784 1784 1883 1785 1785 1884 1766 1766 1864 1785 1785 1884 1767 1767 1865 1767 1767 1865 1785 1785 1884 1786 1786 1885 1767 1767 1865 1786 1786 1885 1768 1768 1866 1768 1768 1866 1786 1786 1885 1787 1787 1886 1768 1768 1866 1787 1787 1886 1769 1769 1867 1769 1769 1867 1787 1787 1886 1788 1788 1887 1769 1769 1867 1788 1788 1887 1770 1770 1868 1770 1770 1868 1788 1788 1887 1789 1789 1888 1770 1770 1868 1789 1789 1888 1771 1771 1869 1771 1771 1869 1789 1789 1888 1790 1790 1889 1771 1771 1869 1790 1790 1889 1772 1772 1870 1772 1772 1870 1790 1790 1889 1791 1791 1890 1772 1772 1870 1791 1791 1890 1773 1773 1871 1773 1773 1871 1791 1791 1890 1792 1792 1891 1773 1773 1871 1792 1792 1891 1774 1774 1872 1774 1774 1872 1792 1792 1891 1793 1793 1892 1774 1774 1872 1793 1793 1892 1775 1775 1873 1775 1775 1873 1793 1793 1892 1794 1794 1893 1775 1775 1873 1794 1794 1893 1776 1776 1874 1776 1776 1874 1794 1794 1893 1795 1795 1894 1776 1776 1874 1795 1795 1894 1777 1777 1875 1777 1777 1875 1795 1795 1894 1796 1796 1895 1777 1777 1875 1796 1796 1895 1778 1778 1876 1778 1778 1876 1796 1796 1895 1797 1797 1896 1778 1778 1876 1797 1797 1896 1779 1779 1877 1779 1779 1877 1797 1797 1896 1798 1798 1897 1779 1779 1877 1798 1798 1897 1780 1780 1878 1780 1780 1878 1798 1798 1897 1799 1799 1898 1780 1780 1878 1799 1799 1898 1781 1781 1879 1781 1781 1879 1799 1799 1898 1782 1782 1899 1781 1781 1879 1782 1782 1899 1764 1764 1880 1782 1782 1881 1800 1800 1900 1801 1801 1901 1782 1782 1881 1801 1801 1901 1783 1783 1882 1783 1783 1882 1801 1801 1901 1802 1802 1902 1783 1783 1882 1802 1802 1902 1784 1784 1883 1784 1784 1883 1802 1802 1902 1803 1803 1903 1784 1784 1883 1803 1803 1903 1785 1785 1884 1785 1785 1884 1803 1803 1903 1804 1804 1904 1785 1785 1884 1804 1804 1904 1786 1786 1885 1786 1786 1885 1804 1804 1904 1805 1805 1905 1786 1786 1885 1805 1805 1905 1787 1787 1886 1787 1787 1886 1805 1805 1905 1806 1806 1906 1787 1787 1886 1806 1806 1906 1788 1788 1887 1788 1788 1887 1806 1806 1906 1807 1807 1907 1788 1788 1887 1807 1807 1907 1789 1789 1888 1789 1789 1888 1807 1807 1907 1808 1808 1908 1789 1789 1888 1808 1808 1908 1790 1790 1889 1790 1790 1889 1808 1808 1908 1809 1809 1909 1790 1790 1889 1809 1809 1909 1791 1791 1890 1791 1791 1890 1809 1809 1909 1810 1810 1910 1791 1791 1890 1810 1810 1910 1792 1792 1891 1792 1792 1891 1810 1810 1910 1811 1811 1911 1792 1792 1891 1811 1811 1911 1793 1793 1892 1793 1793 1892 1811 1811 1911 1812 1812 1912 1793 1793 1892 1812 1812 1912 1794 1794 1893 1794 1794 1893 1812 1812 1912 1813 1813 1913 1794 1794 1893 1813 1813 1913 1795 1795 1894 1795 1795 1894 1813 1813 1913 1814 1814 1914 1795 1795 1894 1814 1814 1914 1796 1796 1895 1796 1796 1895 1814 1814 1914 1815 1815 1915 1796 1796 1895 1815 1815 1915 1797 1797 1896 1797 1797 1896 1815 1815 1915 1816 1816 1916 1797 1797 1896 1816 1816 1916 1798 1798 1897 1798 1798 1897 1816 1816 1916 1817 1817 1917 1798 1798 1897 1817 1817 1917 1799 1799 1898 1799 1799 1898 1817 1817 1917 1800 1800 1918 1799 1799 1898 1800 1800 1918 1782 1782 1899 1800 1800 1900 1818 1818 1919 1819 1819 1920 1800 1800 1900 1819 1819 1920 1801 1801 1901 1801 1801 1901 1819 1819 1920 1820 1820 1921 1801 1801 1901 1820 1820 1921 1802 1802 1902 1802 1802 1902 1820 1820 1921 1821 1821 1922 1802 1802 1902 1821 1821 1922 1803 1803 1903 1803 1803 1903 1821 1821 1922 1822 1822 1923 1803 1803 1903 1822 1822 1923 1804 1804 1904 1804 1804 1904 1822 1822 1923 1823 1823 1924 1804 1804 1904 1823 1823 1924 1805 1805 1905 1805 1805 1905 1823 1823 1924 1824 1824 1925 1805 1805 1905 1824 1824 1925 1806 1806 1906 1806 1806 1906 1824 1824 1925 1825 1825 1926 1806 1806 1906 1825 1825 1926 1807 1807 1907 1807 1807 1907 1825 1825 1926 1826 1826 1927 1807 1807 1907 1826 1826 1927 1808 1808 1908 1808 1808 1908 1826 1826 1927 1827 1827 1928 1808 1808 1908 1827 1827 1928 1809 1809 1909 1809 1809 1909 1827 1827 1928 1828 1828 1929 1809 1809 1909 1828 1828 1929 1810 1810 1910 1810 1810 1910 1828 1828 1929 1829 1829 1930 1810 1810 1910 1829 1829 1930 1811 1811 1911 1811 1811 1911 1829 1829 1930 1830 1830 1931 1811 1811 1911 1830 1830 1931 1812 1812 1912 1812 1812 1912 1830 1830 1931 1831 1831 1932 1812 1812 1912 1831 1831 1932 1813 1813 1913 1813 1813 1913 1831 1831 1932 1832 1832 1933 1813 1813 1913 1832 1832 1933 1814 1814 1914 1814 1814 1914 1832 1832 1933 1833 1833 1934 1814 1814 1914 1833 1833 1934 1815 1815 1915 1815 1815 1915 1833 1833 1934 1834 1834 1935 1815 1815 1915 1834 1834 1935 1816 1816 1916 1816 1816 1916 1834 1834 1935 1835 1835 1936 1816 1816 1916 1835 1835 1936 1817 1817 1917 1817 1817 1917 1835 1835 1936 1818 1818 1937 1817 1817 1917 1818 1818 1937 1800 1800 1918 1818 1818 1919 1836 1836 1938 1837 1837 1939 1818 1818 1919 1837 1837 1939 1819 1819 1920 1819 1819 1920 1837 1837 1939 1838 1838 1940 1819 1819 1920 1838 1838 1940 1820 1820 1921 1820 1820 1921 1838 1838 1940 1839 1839 1941 1820 1820 1921 1839 1839 1941 1821 1821 1922 1821 1821 1922 1839 1839 1941 1840 1840 1942 1821 1821 1922 1840 1840 1942 1822 1822 1923 1822 1822 1923 1840 1840 1942 1841 1841 1943 1822 1822 1923 1841 1841 1943 1823 1823 1924 1823 1823 1924 1841 1841 1943 1842 1842 1944 1823 1823 1924 1842 1842 1944 1824 1824 1925 1824 1824 1925 1842 1842 1944 1843 1843 1945 1824 1824 1925 1843 1843 1945 1825 1825 1926 1825 1825 1926 1843 1843 1945 1844 1844 1946 1825 1825 1926 1844 1844 1946 1826 1826 1927 1826 1826 1927 1844 1844 1946 1845 1845 1947 1826 1826 1927 1845 1845 1947 1827 1827 1928 1827 1827 1928 1845 1845 1947 1846 1846 1948 1827 1827 1928 1846 1846 1948 1828 1828 1929 1828 1828 1929 1846 1846 1948 1847 1847 1949 1828 1828 1929 1847 1847 1949 1829 1829 1930 1829 1829 1930 1847 1847 1949 1848 1848 1950 1829 1829 1930 1848 1848 1950 1830 1830 1931 1830 1830 1931 1848 1848 1950 1849 1849 1951 1830 1830 1931 1849 1849 1951 1831 1831 1932 1831 1831 1932 1849 1849 1951 1850 1850 1952 1831 1831 1932 1850 1850 1952 1832 1832 1933 1832 1832 1933 1850 1850 1952 1851 1851 1953 1832 1832 1933 1851 1851 1953 1833 1833 1934 1833 1833 1934 1851 1851 1953 1852 1852 1954 1833 1833 1934 1852 1852 1954 1834 1834 1935 1834 1834 1935 1852 1852 1954 1853 1853 1955 1834 1834 1935 1853 1853 1955 1835 1835 1936 1835 1835 1936 1853 1853 1955 1836 1836 1956 1835 1835 1936 1836 1836 1956 1818 1818 1937 1836 1836 1938 1854 1854 1957 1855 1855 1958 1836 1836 1938 1855 1855 1958 1837 1837 1939 1837 1837 1939 1855 1855 1958 1856 1856 1959 1837 1837 1939 1856 1856 1959 1838 1838 1940 1838 1838 1940 1856 1856 1959 1857 1857 1960 1838 1838 1940 1857 1857 1960 1839 1839 1941 1839 1839 1941 1857 1857 1960 1858 1858 1961 1839 1839 1941 1858 1858 1961 1840 1840 1942 1840 1840 1942 1858 1858 1961 1859 1859 1962 1840 1840 1942 1859 1859 1962 1841 1841 1943 1841 1841 1943 1859 1859 1962 1860 1860 1963 1841 1841 1943 1860 1860 1963 1842 1842 1944 1842 1842 1944 1860 1860 1963 1861 1861 1964 1842 1842 1944 1861 1861 1964 1843 1843 1945 1843 1843 1945 1861 1861 1964 1862 1862 1965 1843 1843 1945 1862 1862 1965 1844 1844 1946 1844 1844 1946 1862 1862 1965 1863 1863 1966 1844 1844 1946 1863 1863 1966 1845 1845 1947 1845 1845 1947 1863 1863 1966 1864 1864 1967 1845 1845 1947 1864 1864 1967 1846 1846 1948 1846 1846 1948 1864 1864 1967 1865 1865 1968 1846 1846 1948 1865 1865 1968 1847 1847 1949 1847 1847 1949 1865 1865 1968 1866 1866 1969 1847 1847 1949 1866 1866 1969 1848 1848 1950 1848 1848 1950 1866 1866 1969 1867 1867 1970 1848 1848 1950 1867 1867 1970 1849 1849 1951 1849 1849 1951 1867 1867 1970 1868 1868 1971 1849 1849 1951 1868 1868 1971 1850 1850 1952 1850 1850 1952 1868 1868 1971 1869 1869 1972 1850 1850 1952 1869 1869 1972 1851 1851 1953 1851 1851 1953 1869 1869 1972 1870 1870 1973 1851 1851 1953 1870 1870 1973 1852 1852 1954 1852 1852 1954 1870 1870 1973 1871 1871 1974 1852 1852 1954 1871 1871 1974 1853 1853 1955 1853 1853 1955 1871 1871 1974 1854 1854 1975 1853 1853 1955 1854 1854 1975 1836 1836 1956 1854 1854 1957 1872 1872 1976 1873 1873 1977 1854 1854 1957 1873 1873 1977 1855 1855 1958 1855 1855 1958 1873 1873 1977 1874 1874 1978 1855 1855 1958 1874 1874 1978 1856 1856 1959 1856 1856 1959 1874 1874 1978 1875 1875 1979 1856 1856 1959 1875 1875 1979 1857 1857 1960 1857 1857 1960 1875 1875 1979 1876 1876 1980 1857 1857 1960 1876 1876 1980 1858 1858 1961 1858 1858 1961 1876 1876 1980 1877 1877 1981 1858 1858 1961 1877 1877 1981 1859 1859 1962 1859 1859 1962 1877 1877 1981 1878 1878 1982 1859 1859 1962 1878 1878 1982 1860 1860 1963 1860 1860 1963 1878 1878 1982 1879 1879 1983 1860 1860 1963 1879 1879 1983 1861 1861 1964 1861 1861 1964 1879 1879 1983 1880 1880 1984 1861 1861 1964 1880 1880 1984 1862 1862 1965 1862 1862 1965 1880 1880 1984 1881 1881 1985 1862 1862 1965 1881 1881 1985 1863 1863 1966 1863 1863 1966 1881 1881 1985 1882 1882 1986 1863 1863 1966 1882 1882 1986 1864 1864 1967 1864 1864 1967 1882 1882 1986 1883 1883 1987 1864 1864 1967 1883 1883 1987 1865 1865 1968 1865 1865 1968 1883 1883 1987 1884 1884 1988 1865 1865 1968 1884 1884 1988 1866 1866 1969 1866 1866 1969 1884 1884 1988 1885 1885 1989 1866 1866 1969 1885 1885 1989 1867 1867 1970 1867 1867 1970 1885 1885 1989 1886 1886 1990 1867 1867 1970 1886 1886 1990 1868 1868 1971 1868 1868 1971 1886 1886 1990 1887 1887 1991 1868 1868 1971 1887 1887 1991 1869 1869 1972 1869 1869 1972 1887 1887 1991 1888 1888 1992 1869 1869 1972 1888 1888 1992 1870 1870 1973 1870 1870 1973 1888 1888 1992 1889 1889 1993 1870 1870 1973 1889 1889 1993 1871 1871 1974 1871 1871 1974 1889 1889 1993 1872 1872 1994 1871 1871 1974 1872 1872 1994 1854 1854 1975 1872 1872 1976 1890 1890 1995 1891 1891 1996 1872 1872 1976 1891 1891 1996 1873 1873 1977 1873 1873 1977 1891 1891 1996 1892 1892 1997 1873 1873 1977 1892 1892 1997 1874 1874 1978 1874 1874 1978 1892 1892 1997 1893 1893 1998 1874 1874 1978 1893 1893 1998 1875 1875 1979 1875 1875 1979 1893 1893 1998 1894 1894 1999 1875 1875 1979 1894 1894 1999 1876 1876 1980 1876 1876 1980 1894 1894 1999 1895 1895 2000 1876 1876 1980 1895 1895 2000 1877 1877 1981 1877 1877 1981 1895 1895 2000 1896 1896 2001 1877 1877 1981 1896 1896 2001 1878 1878 1982 1878 1878 1982 1896 1896 2001 1897 1897 2002 1878 1878 1982 1897 1897 2002 1879 1879 1983 1879 1879 1983 1897 1897 2002 1898 1898 2003 1879 1879 1983 1898 1898 2003 1880 1880 1984 1880 1880 1984 1898 1898 2003 1899 1899 2004 1880 1880 1984 1899 1899 2004 1881 1881 1985 1881 1881 1985 1899 1899 2004 1900 1900 2005 1881 1881 1985 1900 1900 2005 1882 1882 1986 1882 1882 1986 1900 1900 2005 1901 1901 2006 1882 1882 1986 1901 1901 2006 1883 1883 1987 1883 1883 1987 1901 1901 2006 1902 1902 2007 1883 1883 1987 1902 1902 2007 1884 1884 1988 1884 1884 1988 1902 1902 2007 1903 1903 2008 1884 1884 1988 1903 1903 2008 1885 1885 1989 1885 1885 1989 1903 1903 2008 1904 1904 2009 1885 1885 1989 1904 1904 2009 1886 1886 1990 1886 1886 1990 1904 1904 2009 1905 1905 2010 1886 1886 1990 1905 1905 2010 1887 1887 1991 1887 1887 1991 1905 1905 2010 1906 1906 2011 1887 1887 1991 1906 1906 2011 1888 1888 1992 1888 1888 1992 1906 1906 2011 1907 1907 2012 1888 1888 1992 1907 1907 2012 1889 1889 1993 1889 1889 1993 1907 1907 2012 1890 1890 2013 1889 1889 1993 1890 1890 2013 1872 1872 1994 1890 1890 1995 1908 1908 2014 1909 1909 2015 1890 1890 1995 1909 1909 2015 1891 1891 1996 1891 1891 1996 1909 1909 2015 1910 1910 2016 1891 1891 1996 1910 1910 2016 1892 1892 1997 1892 1892 1997 1910 1910 2016 1911 1911 2017 1892 1892 1997 1911 1911 2017 1893 1893 1998 1893 1893 1998 1911 1911 2017 1912 1912 2018 1893 1893 1998 1912 1912 2018 1894 1894 1999 1894 1894 1999 1912 1912 2018 1913 1913 2019 1894 1894 1999 1913 1913 2019 1895 1895 2000 1895 1895 2000 1913 1913 2019 1914 1914 2020 1895 1895 2000 1914 1914 2020 1896 1896 2001 1896 1896 2001 1914 1914 2020 1915 1915 2021 1896 1896 2001 1915 1915 2021 1897 1897 2002 1897 1897 2002 1915 1915 2021 1916 1916 2022 1897 1897 2002 1916 1916 2022 1898 1898 2003 1898 1898 2003 1916 1916 2022 1917 1917 2023 1898 1898 2003 1917 1917 2023 1899 1899 2004 1899 1899 2004 1917 1917 2023 1918 1918 2024 1899 1899 2004 1918 1918 2024 1900 1900 2005 1900 1900 2005 1918 1918 2024 1919 1919 2025 1900 1900 2005 1919 1919 2025 1901 1901 2006 1901 1901 2006 1919 1919 2025 1920 1920 2026 1901 1901 2006 1920 1920 2026 1902 1902 2007 1902 1902 2007 1920 1920 2026 1921 1921 2027 1902 1902 2007 1921 1921 2027 1903 1903 2008 1903 1903 2008 1921 1921 2027 1922 1922 2028 1903 1903 2008 1922 1922 2028 1904 1904 2009 1904 1904 2009 1922 1922 2028 1923 1923 2029 1904 1904 2009 1923 1923 2029 1905 1905 2010 1905 1905 2010 1923 1923 2029 1924 1924 2030 1905 1905 2010 1924 1924 2030 1906 1906 2011 1906 1906 2011 1924 1924 2030 1925 1925 2031 1906 1906 2011 1925 1925 2031 1907 1907 2012 1907 1907 2012 1925 1925 2031 1908 1908 2032 1907 1907 2012 1908 1908 2032 1890 1890 2013 1908 1908 2014 1926 1926 2033 1927 1927 2034 1908 1908 2014 1927 1927 2034 1909 1909 2015 1909 1909 2015 1927 1927 2034 1928 1928 2035 1909 1909 2015 1928 1928 2035 1910 1910 2016 1910 1910 2016 1928 1928 2035 1929 1929 2036 1910 1910 2016 1929 1929 2036 1911 1911 2017 1911 1911 2017 1929 1929 2036 1930 1930 2037 1911 1911 2017 1930 1930 2037 1912 1912 2018 1912 1912 2018 1930 1930 2037 1931 1931 2038 1912 1912 2018 1931 1931 2038 1913 1913 2019 1913 1913 2019 1931 1931 2038 1932 1932 2039 1913 1913 2019 1932 1932 2039 1914 1914 2020 1914 1914 2020 1932 1932 2039 1933 1933 2040 1914 1914 2020 1933 1933 2040 1915 1915 2021 1915 1915 2021 1933 1933 2040 1934 1934 2041 1915 1915 2021 1934 1934 2041 1916 1916 2022 1916 1916 2022 1934 1934 2041 1935 1935 2042 1916 1916 2022 1935 1935 2042 1917 1917 2023 1917 1917 2023 1935 1935 2042 1936 1936 2043 1917 1917 2023 1936 1936 2043 1918 1918 2024 1918 1918 2024 1936 1936 2043 1937 1937 2044 1918 1918 2024 1937 1937 2044 1919 1919 2025 1919 1919 2025 1937 1937 2044 1938 1938 2045 1919 1919 2025 1938 1938 2045 1920 1920 2026 1920 1920 2026 1938 1938 2045 1939 1939 2046 1920 1920 2026 1939 1939 2046 1921 1921 2027 1921 1921 2027 1939 1939 2046 1940 1940 2047 1921 1921 2027 1940 1940 2047 1922 1922 2028 1922 1922 2028 1940 1940 2047 1941 1941 2048 1922 1922 2028 1941 1941 2048 1923 1923 2029 1923 1923 2029 1941 1941 2048 1942 1942 2049 1923 1923 2029 1942 1942 2049 1924 1924 2030 1924 1924 2030 1942 1942 2049 1943 1943 2050 1924 1924 2030 1943 1943 2050 1925 1925 2031 1925 1925 2031 1943 1943 2050 1926 1926 2051 1925 1925 2031 1926 1926 2051 1908 1908 2032 1926 1926 2033 1944 1944 2052 1945 1945 2053 1926 1926 2033 1945 1945 2053 1927 1927 2034 1927 1927 2034 1945 1945 2053 1946 1946 2054 1927 1927 2034 1946 1946 2054 1928 1928 2035 1928 1928 2035 1946 1946 2054 1947 1947 2055 1928 1928 2035 1947 1947 2055 1929 1929 2036 1929 1929 2036 1947 1947 2055 1948 1948 2056 1929 1929 2036 1948 1948 2056 1930 1930 2037 1930 1930 2037 1948 1948 2056 1949 1949 2057 1930 1930 2037 1949 1949 2057 1931 1931 2038 1931 1931 2038 1949 1949 2057 1950 1950 2058 1931 1931 2038 1950 1950 2058 1932 1932 2039 1932 1932 2039 1950 1950 2058 1951 1951 2059 1932 1932 2039 1951 1951 2059 1933 1933 2040 1933 1933 2040 1951 1951 2059 1952 1952 2060 1933 1933 2040 1952 1952 2060 1934 1934 2041 1934 1934 2041 1952 1952 2060 1953 1953 2061 1934 1934 2041 1953 1953 2061 1935 1935 2042 1935 1935 2042 1953 1953 2061 1954 1954 2062 1935 1935 2042 1954 1954 2062 1936 1936 2043 1936 1936 2043 1954 1954 2062 1955 1955 2063 1936 1936 2043 1955 1955 2063 1937 1937 2044 1937 1937 2044 1955 1955 2063 1956 1956 2064 1937 1937 2044 1956 1956 2064 1938 1938 2045 1938 1938 2045 1956 1956 2064 1957 1957 2065 1938 1938 2045 1957 1957 2065 1939 1939 2046 1939 1939 2046 1957 1957 2065 1958 1958 2066 1939 1939 2046 1958 1958 2066 1940 1940 2047 1940 1940 2047 1958 1958 2066 1959 1959 2067 1940 1940 2047 1959 1959 2067 1941 1941 2048 1941 1941 2048 1959 1959 2067 1960 1960 2068 1941 1941 2048 1960 1960 2068 1942 1942 2049 1942 1942 2049 1960 1960 2068 1961 1961 2069 1942 1942 2049 1961 1961 2069 1943 1943 2050 1943 1943 2050 1961 1961 2069 1944 1944 2070 1943 1943 2050 1944 1944 2070 1926 1926 2051 1944 1944 2052 1962 1962 2071 1963 1963 2072 1944 1944 2052 1963 1963 2072 1945 1945 2053 1945 1945 2053 1963 1963 2072 1964 1964 2073 1945 1945 2053 1964 1964 2073 1946 1946 2054 1946 1946 2054 1964 1964 2073 1965 1965 2074 1946 1946 2054 1965 1965 2074 1947 1947 2055 1947 1947 2055 1965 1965 2074 1966 1966 2075 1947 1947 2055 1966 1966 2075 1948 1948 2056 1948 1948 2056 1966 1966 2075 1967 1967 2076 1948 1948 2056 1967 1967 2076 1949 1949 2057 1949 1949 2057 1967 1967 2076 1968 1968 2077 1949 1949 2057 1968 1968 2077 1950 1950 2058 1950 1950 2058 1968 1968 2077 1969 1969 2078 1950 1950 2058 1969 1969 2078 1951 1951 2059 1951 1951 2059 1969 1969 2078 1970 1970 2079 1951 1951 2059 1970 1970 2079 1952 1952 2060 1952 1952 2060 1970 1970 2079 1971 1971 2080 1952 1952 2060 1971 1971 2080 1953 1953 2061 1953 1953 2061 1971 1971 2080 1972 1972 2081 1953 1953 2061 1972 1972 2081 1954 1954 2062 1954 1954 2062 1972 1972 2081 1973 1973 2082 1954 1954 2062 1973 1973 2082 1955 1955 2063 1955 1955 2063 1973 1973 2082 1974 1974 2083 1955 1955 2063 1974 1974 2083 1956 1956 2064 1956 1956 2064 1974 1974 2083 1975 1975 2084 1956 1956 2064 1975 1975 2084 1957 1957 2065 1957 1957 2065 1975 1975 2084 1976 1976 2085 1957 1957 2065 1976 1976 2085 1958 1958 2066 1958 1958 2066 1976 1976 2085 1977 1977 2086 1958 1958 2066 1977 1977 2086 1959 1959 2067 1959 1959 2067 1977 1977 2086 1978 1978 2087 1959 1959 2067 1978 1978 2087 1960 1960 2068 1960 1960 2068 1978 1978 2087 1979 1979 2088 1960 1960 2068 1979 1979 2088 1961 1961 2069 1961 1961 2069 1979 1979 2088 1962 1962 2089 1961 1961 2069 1962 1962 2089 1944 1944 2070 1962 1962 2071 1980 1980 2090 1981 1981 2091 1962 1962 2071 1981 1981 2091 1963 1963 2072 1963 1963 2072 1981 1981 2091 1982 1982 2092 1963 1963 2072 1982 1982 2092 1964 1964 2073 1964 1964 2073 1982 1982 2092 1983 1983 2093 1964 1964 2073 1983 1983 2093 1965 1965 2074 1965 1965 2074 1983 1983 2093 1984 1984 2094 1965 1965 2074 1984 1984 2094 1966 1966 2075 1966 1966 2075 1984 1984 2094 1985 1985 2095 1966 1966 2075 1985 1985 2095 1967 1967 2076 1967 1967 2076 1985 1985 2095 1986 1986 2096 1967 1967 2076 1986 1986 2096 1968 1968 2077 1968 1968 2077 1986 1986 2096 1987 1987 2097 1968 1968 2077 1987 1987 2097 1969 1969 2078 1969 1969 2078 1987 1987 2097 1988 1988 2098 1969 1969 2078 1988 1988 2098 1970 1970 2079 1970 1970 2079 1988 1988 2098 1989 1989 2099 1970 1970 2079 1989 1989 2099 1971 1971 2080 1971 1971 2080 1989 1989 2099 1990 1990 2100 1971 1971 2080 1990 1990 2100 1972 1972 2081 1972 1972 2081 1990 1990 2100 1991 1991 2101 1972 1972 2081 1991 1991 2101 1973 1973 2082 1973 1973 2082 1991 1991 2101 1992 1992 2102 1973 1973 2082 1992 1992 2102 1974 1974 2083 1974 1974 2083 1992 1992 2102 1993 1993 2103 1974 1974 2083 1993 1993 2103 1975 1975 2084 1975 1975 2084 1993 1993 2103 1994 1994 2104 1975 1975 2084 1994 1994 2104 1976 1976 2085 1976 1976 2085 1994 1994 2104 1995 1995 2105 1976 1976 2085 1995 1995 2105 1977 1977 2086 1977 1977 2086 1995 1995 2105 1996 1996 2106 1977 1977 2086 1996 1996 2106 1978 1978 2087 1978 1978 2087 1996 1996 2106 1997 1997 2107 1978 1978 2087 1997 1997 2107 1979 1979 2088 1979 1979 2088 1997 1997 2107 1980 1980 2108 1979 1979 2088 1980 1980 2108 1962 1962 2089 1980 1980 2090 1998 1998 2109 1999 1999 2110 1980 1980 2090 1999 1999 2110 1981 1981 2091 1981 1981 2091 1999 1999 2110 2000 2000 2111 1981 1981 2091 2000 2000 2111 1982 1982 2092 1982 1982 2092 2000 2000 2111 2001 2001 2112 1982 1982 2092 2001 2001 2112 1983 1983 2093 1983 1983 2093 2001 2001 2112 2002 2002 2113 1983 1983 2093 2002 2002 2113 1984 1984 2094 1984 1984 2094 2002 2002 2113 2003 2003 2114 1984 1984 2094 2003 2003 2114 1985 1985 2095 1985 1985 2095 2003 2003 2114 2004 2004 2115 1985 1985 2095 2004 2004 2115 1986 1986 2096 1986 1986 2096 2004 2004 2115 2005 2005 2116 1986 1986 2096 2005 2005 2116 1987 1987 2097 1987 1987 2097 2005 2005 2116 2006 2006 2117 1987 1987 2097 2006 2006 2117 1988 1988 2098 1988 1988 2098 2006 2006 2117 2007 2007 2118 1988 1988 2098 2007 2007 2118 1989 1989 2099 1989 1989 2099 2007 2007 2118 2008 2008 2119 1989 1989 2099 2008 2008 2119 1990 1990 2100 1990 1990 2100 2008 2008 2119 2009 2009 2120 1990 1990 2100 2009 2009 2120 1991 1991 2101 1991 1991 2101 2009 2009 2120 2010 2010 2121 1991 1991 2101 2010 2010 2121 1992 1992 2102 1992 1992 2102 2010 2010 2121 2011 2011 2122 1992 1992 2102 2011 2011 2122 1993 1993 2103 1993 1993 2103 2011 2011 2122 2012 2012 2123 1993 1993 2103 2012 2012 2123 1994 1994 2104 1994 1994 2104 2012 2012 2123 2013 2013 2124 1994 1994 2104 2013 2013 2124 1995 1995 2105 1995 1995 2105 2013 2013 2124 2014 2014 2125 1995 1995 2105 2014 2014 2125 1996 1996 2106 1996 1996 2106 2014 2014 2125 2015 2015 2126 1996 1996 2106 2015 2015 2126 1997 1997 2107 1997 1997 2107 2015 2015 2126 1998 1998 2127 1997 1997 2107 1998 1998 2127 1980 1980 2108 1998 1998 2109 2016 2016 2128 2017 2017 2129 1998 1998 2109 2017 2017 2129 1999 1999 2110 1999 1999 2110 2017 2017 2129 2018 2018 2130 1999 1999 2110 2018 2018 2130 2000 2000 2111 2000 2000 2111 2018 2018 2130 2019 2019 2131 2000 2000 2111 2019 2019 2131 2001 2001 2112 2001 2001 2112 2019 2019 2131 2020 2020 2132 2001 2001 2112 2020 2020 2132 2002 2002 2113 2002 2002 2113 2020 2020 2132 2021 2021 2133 2002 2002 2113 2021 2021 2133 2003 2003 2114 2003 2003 2114 2021 2021 2133 2022 2022 2134 2003 2003 2114 2022 2022 2134 2004 2004 2115 2004 2004 2115 2022 2022 2134 2023 2023 2135 2004 2004 2115 2023 2023 2135 2005 2005 2116 2005 2005 2116 2023 2023 2135 2024 2024 2136 2005 2005 2116 2024 2024 2136 2006 2006 2117 2006 2006 2117 2024 2024 2136 2025 2025 2137 2006 2006 2117 2025 2025 2137 2007 2007 2118 2007 2007 2118 2025 2025 2137 2026 2026 2138 2007 2007 2118 2026 2026 2138 2008 2008 2119 2008 2008 2119 2026 2026 2138 2027 2027 2139 2008 2008 2119 2027 2027 2139 2009 2009 2120 2009 2009 2120 2027 2027 2139 2028 2028 2140 2009 2009 2120 2028 2028 2140 2010 2010 2121 2010 2010 2121 2028 2028 2140 2029 2029 2141 2010 2010 2121 2029 2029 2141 2011 2011 2122 2011 2011 2122 2029 2029 2141 2030 2030 2142 2011 2011 2122 2030 2030 2142 2012 2012 2123 2012 2012 2123 2030 2030 2142 2031 2031 2143 2012 2012 2123 2031 2031 2143 2013 2013 2124 2013 2013 2124 2031 2031 2143 2032 2032 2144 2013 2013 2124 2032 2032 2144 2014 2014 2125 2014 2014 2125 2032 2032 2144 2033 2033 2145 2014 2014 2125 2033 2033 2145 2015 2015 2126 2015 2015 2126 2033 2033 2145 2016 2016 2146 2015 2015 2126 2016 2016 2146 1998 1998 2127 2016 2016 2128 2034 2034 2147 2035 2035 2148 2016 2016 2128 2035 2035 2148 2017 2017 2129 2017 2017 2129 2035 2035 2148 2036 2036 2149 2017 2017 2129 2036 2036 2149 2018 2018 2130 2018 2018 2130 2036 2036 2149 2037 2037 2150 2018 2018 2130 2037 2037 2150 2019 2019 2131 2019 2019 2131 2037 2037 2150 2038 2038 2151 2019 2019 2131 2038 2038 2151 2020 2020 2132 2020 2020 2132 2038 2038 2151 2039 2039 2152 2020 2020 2132 2039 2039 2152 2021 2021 2133 2021 2021 2133 2039 2039 2152 2040 2040 2153 2021 2021 2133 2040 2040 2153 2022 2022 2134 2022 2022 2134 2040 2040 2153 2041 2041 2154 2022 2022 2134 2041 2041 2154 2023 2023 2135 2023 2023 2135 2041 2041 2154 2042 2042 2155 2023 2023 2135 2042 2042 2155 2024 2024 2136 2024 2024 2136 2042 2042 2155 2043 2043 2156 2024 2024 2136 2043 2043 2156 2025 2025 2137 2025 2025 2137 2043 2043 2156 2044 2044 2157 2025 2025 2137 2044 2044 2157 2026 2026 2138 2026 2026 2138 2044 2044 2157 2045 2045 2158 2026 2026 2138 2045 2045 2158 2027 2027 2139 2027 2027 2139 2045 2045 2158 2046 2046 2159 2027 2027 2139 2046 2046 2159 2028 2028 2140 2028 2028 2140 2046 2046 2159 2047 2047 2160 2028 2028 2140 2047 2047 2160 2029 2029 2141 2029 2029 2141 2047 2047 2160 2048 2048 2161 2029 2029 2141 2048 2048 2161 2030 2030 2142 2030 2030 2142 2048 2048 2161 2049 2049 2162 2030 2030 2142 2049 2049 2162 2031 2031 2143 2031 2031 2143 2049 2049 2162 2050 2050 2163 2031 2031 2143 2050 2050 2163 2032 2032 2144 2032 2032 2144 2050 2050 2163 2051 2051 2164 2032 2032 2144 2051 2051 2164 2033 2033 2145 2033 2033 2145 2051 2051 2164 2034 2034 2165 2033 2033 2145 2034 2034 2165 2016 2016 2146 2034 2034 2147 2052 2052 2166 2053 2053 2167 2034 2034 2147 2053 2053 2167 2035 2035 2148 2035 2035 2148 2053 2053 2167 2054 2054 2168 2035 2035 2148 2054 2054 2168 2036 2036 2149 2036 2036 2149 2054 2054 2168 2055 2055 2169 2036 2036 2149 2055 2055 2169 2037 2037 2150 2037 2037 2150 2055 2055 2169 2056 2056 2170 2037 2037 2150 2056 2056 2170 2038 2038 2151 2038 2038 2151 2056 2056 2170 2057 2057 2171 2038 2038 2151 2057 2057 2171 2039 2039 2152 2039 2039 2152 2057 2057 2171 2058 2058 2172 2039 2039 2152 2058 2058 2172 2040 2040 2153 2040 2040 2153 2058 2058 2172 2059 2059 2173 2040 2040 2153 2059 2059 2173 2041 2041 2154 2041 2041 2154 2059 2059 2173 2060 2060 2174 2041 2041 2154 2060 2060 2174 2042 2042 2155 2042 2042 2155 2060 2060 2174 2061 2061 2175 2042 2042 2155 2061 2061 2175 2043 2043 2156 2043 2043 2156 2061 2061 2175 2062 2062 2176 2043 2043 2156 2062 2062 2176 2044 2044 2157 2044 2044 2157 2062 2062 2176 2063 2063 2177 2044 2044 2157 2063 2063 2177 2045 2045 2158 2045 2045 2158 2063 2063 2177 2064 2064 2178 2045 2045 2158 2064 2064 2178 2046 2046 2159 2046 2046 2159 2064 2064 2178 2065 2065 2179 2046 2046 2159 2065 2065 2179 2047 2047 2160 2047 2047 2160 2065 2065 2179 2066 2066 2180 2047 2047 2160 2066 2066 2180 2048 2048 2161 2048 2048 2161 2066 2066 2180 2067 2067 2181 2048 2048 2161 2067 2067 2181 2049 2049 2162 2049 2049 2162 2067 2067 2181 2068 2068 2182 2049 2049 2162 2068 2068 2182 2050 2050 2163 2050 2050 2163 2068 2068 2182 2069 2069 2183 2050 2050 2163 2069 2069 2183 2051 2051 2164 2051 2051 2164 2069 2069 2183 2052 2052 2184 2051 2051 2164 2052 2052 2184 2034 2034 2165 2052 2052 2166 2070 2070 2185 2071 2071 2186 2052 2052 2166 2071 2071 2186 2053 2053 2167 2053 2053 2167 2071 2071 2186 2072 2072 2187 2053 2053 2167 2072 2072 2187 2054 2054 2168 2054 2054 2168 2072 2072 2187 2073 2073 2188 2054 2054 2168 2073 2073 2188 2055 2055 2169 2055 2055 2169 2073 2073 2188 2074 2074 2189 2055 2055 2169 2074 2074 2189 2056 2056 2170 2056 2056 2170 2074 2074 2189 2075 2075 2190 2056 2056 2170 2075 2075 2190 2057 2057 2171 2057 2057 2171 2075 2075 2190 2076 2076 2191 2057 2057 2171 2076 2076 2191 2058 2058 2172 2058 2058 2172 2076 2076 2191 2077 2077 2192 2058 2058 2172 2077 2077 2192 2059 2059 2173 2059 2059 2173 2077 2077 2192 2078 2078 2193 2059 2059 2173 2078 2078 2193 2060 2060 2174 2060 2060 2174 2078 2078 2193 2079 2079 2194 2060 2060 2174 2079 2079 2194 2061 2061 2175 2061 2061 2175 2079 2079 2194 2080 2080 2195 2061 2061 2175 2080 2080 2195 2062 2062 2176 2062 2062 2176 2080 2080 2195 2081 2081 2196 2062 2062 2176 2081 2081 2196 2063 2063 2177 2063 2063 2177 2081 2081 2196 2082 2082 2197 2063 2063 2177 2082 2082 2197 2064 2064 2178 2064 2064 2178 2082 2082 2197 2083 2083 2198 2064 2064 2178 2083 2083 2198 2065 2065 2179 2065 2065 2179 2083 2083 2198 2084 2084 2199 2065 2065 2179 2084 2084 2199 2066 2066 2180 2066 2066 2180 2084 2084 2199 2085 2085 2200 2066 2066 2180 2085 2085 2200 2067 2067 2181 2067 2067 2181 2085 2085 2200 2086 2086 2201 2067 2067 2181 2086 2086 2201 2068 2068 2182 2068 2068 2182 2086 2086 2201 2087 2087 2202 2068 2068 2182 2087 2087 2202 2069 2069 2183 2069 2069 2183 2087 2087 2202 2070 2070 2203 2069 2069 2183 2070 2070 2203 2052 2052 2184 2070 2070 2185 2088 2088 2204 2089 2089 2205 2070 2070 2185 2089 2089 2205 2071 2071 2186 2071 2071 2186 2089 2089 2205 2090 2090 2206 2071 2071 2186 2090 2090 2206 2072 2072 2187 2072 2072 2187 2090 2090 2206 2091 2091 2207 2072 2072 2187 2091 2091 2207 2073 2073 2188 2073 2073 2188 2091 2091 2207 2092 2092 2208 2073 2073 2188 2092 2092 2208 2074 2074 2189 2074 2074 2189 2092 2092 2208 2093 2093 2209 2074 2074 2189 2093 2093 2209 2075 2075 2190 2075 2075 2190 2093 2093 2209 2094 2094 2210 2075 2075 2190 2094 2094 2210 2076 2076 2191 2076 2076 2191 2094 2094 2210 2095 2095 2211 2076 2076 2191 2095 2095 2211 2077 2077 2192 2077 2077 2192 2095 2095 2211 2096 2096 2212 2077 2077 2192 2096 2096 2212 2078 2078 2193 2078 2078 2193 2096 2096 2212 2097 2097 2213 2078 2078 2193 2097 2097 2213 2079 2079 2194 2079 2079 2194 2097 2097 2213 2098 2098 2214 2079 2079 2194 2098 2098 2214 2080 2080 2195 2080 2080 2195 2098 2098 2214 2099 2099 2215 2080 2080 2195 2099 2099 2215 2081 2081 2196 2081 2081 2196 2099 2099 2215 2100 2100 2216 2081 2081 2196 2100 2100 2216 2082 2082 2197 2082 2082 2197 2100 2100 2216 2101 2101 2217 2082 2082 2197 2101 2101 2217 2083 2083 2198 2083 2083 2198 2101 2101 2217 2102 2102 2218 2083 2083 2198 2102 2102 2218 2084 2084 2199 2084 2084 2199 2102 2102 2218 2103 2103 2219 2084 2084 2199 2103 2103 2219 2085 2085 2200 2085 2085 2200 2103 2103 2219 2104 2104 2220 2085 2085 2200 2104 2104 2220 2086 2086 2201 2086 2086 2201 2104 2104 2220 2105 2105 2221 2086 2086 2201 2105 2105 2221 2087 2087 2202 2087 2087 2202 2105 2105 2221 2088 2088 2222 2087 2087 2202 2088 2088 2222 2070 2070 2203 2088 2088 2204 2106 2106 2223 2107 2107 2224 2088 2088 2204 2107 2107 2224 2089 2089 2205 2089 2089 2205 2107 2107 2224 2108 2108 2225 2089 2089 2205 2108 2108 2225 2090 2090 2206 2090 2090 2206 2108 2108 2225 2109 2109 2226 2090 2090 2206 2109 2109 2226 2091 2091 2207 2091 2091 2207 2109 2109 2226 2110 2110 2227 2091 2091 2207 2110 2110 2227 2092 2092 2208 2092 2092 2208 2110 2110 2227 2111 2111 2228 2092 2092 2208 2111 2111 2228 2093 2093 2209 2093 2093 2209 2111 2111 2228 2112 2112 2229 2093 2093 2209 2112 2112 2229 2094 2094 2210 2094 2094 2210 2112 2112 2229 2113 2113 2230 2094 2094 2210 2113 2113 2230 2095 2095 2211 2095 2095 2211 2113 2113 2230 2114 2114 2231 2095 2095 2211 2114 2114 2231 2096 2096 2212 2096 2096 2212 2114 2114 2231 2115 2115 2232 2096 2096 2212 2115 2115 2232 2097 2097 2213 2097 2097 2213 2115 2115 2232 2116 2116 2233 2097 2097 2213 2116 2116 2233 2098 2098 2214 2098 2098 2214 2116 2116 2233 2117 2117 2234 2098 2098 2214 2117 2117 2234 2099 2099 2215 2099 2099 2215 2117 2117 2234 2118 2118 2235 2099 2099 2215 2118 2118 2235 2100 2100 2216 2100 2100 2216 2118 2118 2235 2119 2119 2236 2100 2100 2216 2119 2119 2236 2101 2101 2217 2101 2101 2217 2119 2119 2236 2120 2120 2237 2101 2101 2217 2120 2120 2237 2102 2102 2218 2102 2102 2218 2120 2120 2237 2121 2121 2238 2102 2102 2218 2121 2121 2238 2103 2103 2219 2103 2103 2219 2121 2121 2238 2122 2122 2239 2103 2103 2219 2122 2122 2239 2104 2104 2220 2104 2104 2220 2122 2122 2239 2123 2123 2240 2104 2104 2220 2123 2123 2240 2105 2105 2221 2105 2105 2221 2123 2123 2240 2106 2106 2241 2105 2105 2221 2106 2106 2241 2088 2088 2222 2106 2106 2223 2124 2124 2242 2125 2125 2243 2106 2106 2223 2125 2125 2243 2107 2107 2224 2107 2107 2224 2125 2125 2243 2126 2126 2244 2107 2107 2224 2126 2126 2244 2108 2108 2225 2108 2108 2225 2126 2126 2244 2127 2127 2245 2108 2108 2225 2127 2127 2245 2109 2109 2226 2109 2109 2226 2127 2127 2245 2128 2128 2246 2109 2109 2226 2128 2128 2246 2110 2110 2227 2110 2110 2227 2128 2128 2246 2129 2129 2247 2110 2110 2227 2129 2129 2247 2111 2111 2228 2111 2111 2228 2129 2129 2247 2130 2130 2248 2111 2111 2228 2130 2130 2248 2112 2112 2229 2112 2112 2229 2130 2130 2248 2131 2131 2249 2112 2112 2229 2131 2131 2249 2113 2113 2230 2113 2113 2230 2131 2131 2249 2132 2132 2250 2113 2113 2230 2132 2132 2250 2114 2114 2231 2114 2114 2231 2132 2132 2250 2133 2133 2251 2114 2114 2231 2133 2133 2251 2115 2115 2232 2115 2115 2232 2133 2133 2251 2134 2134 2252 2115 2115 2232 2134 2134 2252 2116 2116 2233 2116 2116 2233 2134 2134 2252 2135 2135 2253 2116 2116 2233 2135 2135 2253 2117 2117 2234 2117 2117 2234 2135 2135 2253 2136 2136 2254 2117 2117 2234 2136 2136 2254 2118 2118 2235 2118 2118 2235 2136 2136 2254 2137 2137 2255 2118 2118 2235 2137 2137 2255 2119 2119 2236 2119 2119 2236 2137 2137 2255 2138 2138 2256 2119 2119 2236 2138 2138 2256 2120 2120 2237 2120 2120 2237 2138 2138 2256 2139 2139 2257 2120 2120 2237 2139 2139 2257 2121 2121 2238 2121 2121 2238 2139 2139 2257 2140 2140 2258 2121 2121 2238 2140 2140 2258 2122 2122 2239 2122 2122 2239 2140 2140 2258 2141 2141 2259 2122 2122 2239 2141 2141 2259 2123 2123 2240 2123 2123 2240 2141 2141 2259 2124 2124 2260 2123 2123 2240 2124 2124 2260 2106 2106 2241 2124 2124 2242 2142 2142 2261 2143 2143 2262 2124 2124 2242 2143 2143 2262 2125 2125 2243 2125 2125 2243 2143 2143 2262 2144 2144 2263 2125 2125 2243 2144 2144 2263 2126 2126 2244 2126 2126 2244 2144 2144 2263 2145 2145 2264 2126 2126 2244 2145 2145 2264 2127 2127 2245 2127 2127 2245 2145 2145 2264 2146 2146 2265 2127 2127 2245 2146 2146 2265 2128 2128 2246 2128 2128 2246 2146 2146 2265 2147 2147 2266 2128 2128 2246 2147 2147 2266 2129 2129 2247 2129 2129 2247 2147 2147 2266 2148 2148 2267 2129 2129 2247 2148 2148 2267 2130 2130 2248 2130 2130 2248 2148 2148 2267 2149 2149 2268 2130 2130 2248 2149 2149 2268 2131 2131 2249 2131 2131 2249 2149 2149 2268 2150 2150 2269 2131 2131 2249 2150 2150 2269 2132 2132 2250 2132 2132 2250 2150 2150 2269 2151 2151 2270 2132 2132 2250 2151 2151 2270 2133 2133 2251 2133 2133 2251 2151 2151 2270 2152 2152 2271 2133 2133 2251 2152 2152 2271 2134 2134 2252 2134 2134 2252 2152 2152 2271 2153 2153 2272 2134 2134 2252 2153 2153 2272 2135 2135 2253 2135 2135 2253 2153 2153 2272 2154 2154 2273 2135 2135 2253 2154 2154 2273 2136 2136 2254 2136 2136 2254 2154 2154 2273 2155 2155 2274 2136 2136 2254 2155 2155 2274 2137 2137 2255 2137 2137 2255 2155 2155 2274 2156 2156 2275 2137 2137 2255 2156 2156 2275 2138 2138 2256 2138 2138 2256 2156 2156 2275 2157 2157 2276 2138 2138 2256 2157 2157 2276 2139 2139 2257 2139 2139 2257 2157 2157 2276 2158 2158 2277 2139 2139 2257 2158 2158 2277 2140 2140 2258 2140 2140 2258 2158 2158 2277 2159 2159 2278 2140 2140 2258 2159 2159 2278 2141 2141 2259 2141 2141 2259 2159 2159 2278 2142 2142 2279 2141 2141 2259 2142 2142 2279 2124 2124 2260 2142 2142 2261 0 0 2280 1 3 2281 2142 2142 2261 1 3 2281 2143 2143 2262 2143 2143 2262 1 3 2281 2 5 2282 2143 2143 2262 2 5 2282 2144 2144 2263 2144 2144 2263 2 5 2282 3 7 2283 2144 2144 2263 3 7 2283 2145 2145 2264 2145 2145 2264 3 7 2283 4 9 2284 2145 2145 2264 4 9 2284 2146 2146 2265 2146 2146 2265 4 9 2284 5 11 2285 2146 2146 2265 5 11 2285 2147 2147 2266 2147 2147 2266 5 11 2285 6 13 2286 2147 2147 2266 6 13 2286 2148 2148 2267 2148 2148 2267 6 13 2286 7 15 2287 2148 2148 2267 7 15 2287 2149 2149 2268 2149 2149 2268 7 15 2287 8 17 2288 2149 2149 2268 8 17 2288 2150 2150 2269 2150 2150 2269 8 17 2288 9 19 2289 2150 2150 2269 9 19 2289 2151 2151 2270 2151 2151 2270 9 19 2289 10 21 2290 2151 2151 2270 10 21 2290 2152 2152 2271 2152 2152 2271 10 21 2290 11 23 2291 2152 2152 2271 11 23 2291 2153 2153 2272 2153 2153 2272 11 23 2291 12 25 2292 2153 2153 2272 12 25 2292 2154 2154 2273 2154 2154 2273 12 25 2292 13 27 2293 2154 2154 2273 13 27 2293 2155 2155 2274 2155 2155 2274 13 27 2293 14 29 2294 2155 2155 2274 14 29 2294 2156 2156 2275 2156 2156 2275 14 29 2294 15 31 2295 2156 2156 2275 15 31 2295 2157 2157 2276 2157 2157 2276 15 31 2295 16 33 2296 2157 2157 2276 16 33 2296 2158 2158 2277 2158 2158 2277 16 33 2296 17 35 2297 2158 2158 2277 17 35 2297 2159 2159 2278 2159 2159 2278 17 35 2297 0 0 2298 2159 2159 2278 0 0 2298 2142 2142 2279</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-3_max" name="Torus_Knot-3_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-3_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-4.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-4.DAE
new file mode 100644
index 00000000..d8c93239
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-4.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-4.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:20:22Z</created>
+ <modified>2008-10-31T16:20:23Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="6480">36.869415 -0.010380 8.585130 36.443169 -0.590930 9.865063 34.362587 -1.100204 12.696369 30.878613 -1.476778 16.737549 26.411465 -1.675231 21.501183 21.499950 -1.671626 26.412697 16.736469 -1.466398 30.879692 12.695569 -1.084301 34.363388 9.864638 -0.571422 36.443596 8.585131 0.010380 36.869415 9.011374 0.590929 35.589485 11.091956 1.100204 32.758179 14.575928 1.476778 28.716999 19.043072 1.675231 23.953369 23.954586 1.671626 19.041855 28.718067 1.466399 14.574858 32.758968 1.084302 11.091161 35.589901 0.571423 9.010949 38.463608 0.720380 10.131867 38.058578 0.343384 11.492300 35.998039 0.233443 14.381344 32.530525 0.403818 18.450539 28.074268 0.833959 23.209082 23.166761 1.471985 28.083017 18.399921 2.240940 32.484482 14.348699 3.048077 35.882591 11.501730 3.796043 37.867485 10.202403 4.394623 38.199753 10.607434 4.771620 36.839321 12.667971 4.881561 33.950279 16.135483 4.711186 29.881084 20.591736 4.281046 25.122547 25.499243 3.643020 20.248608 30.266083 2.874066 15.847145 34.317307 2.066929 12.449034 37.164276 1.318962 10.464139 39.967487 1.975798 11.411241 39.599033 1.832959 12.825733 37.573872 2.132110 15.726371 34.136257 2.837172 19.763292 29.700823 3.863102 24.449587 24.802547 5.086159 29.220016 20.032238 6.358824 33.499199 15.965258 7.527594 36.770996 13.092149 8.451498 38.640789 11.759449 9.019101 38.883049 12.127901 9.161942 37.468555 14.153064 8.862790 34.567921 17.590675 8.157729 30.531000 22.026106 7.131799 25.844707 26.924379 5.908743 21.074280 31.694691 4.636078 16.795097 35.761673 3.467308 13.523296 38.634785 2.543403 11.653501 41.315632 3.884909 12.207775 40.992466 3.999348 13.635859 39.009968 4.698754 16.496801 35.607246 5.898769 20.445536 31.194729 7.454656 25.005783 26.304626 9.178749 29.627512 21.526760 10.863096 33.753273 17.437407 12.304543 36.885437 14.529808 13.329229 38.646217 13.154658 13.813562 38.823246 13.477822 13.699123 37.395164 15.460322 12.999718 34.534222 18.863039 11.799704 30.585489 23.275555 10.243817 26.025244 28.165657 8.519726 21.403517 32.943523 6.835378 17.277756 37.032879 5.393930 14.145589 39.940479 4.369244 12.384804 42.409981 6.498417 12.268070 42.127308 6.876197 13.658872 40.180717 7.946067 16.428465 36.805000 9.578985 20.242796 32.407310 11.577999 24.641800 27.518078 13.701996 29.094893 22.727020 15.694790 33.064964 18.612005 17.316021 36.073166 15.669364 18.370148 37.756664 14.254025 18.730024 37.912403 14.536695 18.352245 36.521603 16.483284 17.282375 33.752010 19.859001 15.649458 29.937681 24.256689 13.650446 25.538679 29.145918 11.526449 21.085588 33.936977 9.533655 17.115515 38.051994 7.912422 14.107312 40.994637 6.858294 12.423811 43.111057 9.766623 11.341201 42.850121 10.389200 12.645524 40.919250 11.778502 15.281062 37.551334 13.766958 18.929930 33.152599 16.114733 23.152020 28.253593 18.538649 27.438084 23.445213 20.746344 31.271160 19.307415 22.471540 34.188923 16.339281 23.506155 35.839451 14.898812 23.725393 36.023659 15.159749 23.102816 34.719337 17.090616 21.713516 32.083801 20.458529 19.725060 28.434937 24.857262 17.377285 24.212849 29.756266 14.953371 19.926785 34.564648 12.745676 16.093708 38.702446 11.020477 13.175941 41.670582 9.985863 11.525412 43.244488 13.545299 9.216830 42.980289 14.372921 10.400972 41.039604 16.015354 12.879004 37.656506 18.274496 16.352034 33.239044 20.877867 20.401165 28.320034 23.511456 24.538015 23.492781 25.857611 28.263615 19.339520 27.633358 31.128603 16.361195 28.624512 32.787422 14.917038 28.711525 33.039989 15.181234 27.883904 31.855850 17.121918 26.241472 29.377819 20.505014 23.982330 25.904791 24.922472 21.378962 21.855661 29.841482 18.745375 17.718813 34.668736 16.399216 13.993214 38.821999 14.623469 11.128222 41.800327 13.632314 9.469400 42.627083 17.585602 5.781768 42.336926 18.570782 6.831616 40.364098 20.398840 9.149078 36.946545 22.849285 12.454632 32.496475 25.626560 16.349577 27.550638 28.395681 20.364128 22.705574 30.822655 24.014071 18.545664 32.614754 26.859165 15.572659 33.555817 28.556255 14.145144 33.532345 28.900642 14.435300 32.547165 27.850796 16.408129 30.719110 25.533337 19.825680 28.268665 22.227783 24.275745 25.491392 18.332840 29.221581 22.722269 14.318290 34.066647 20.295296 10.668347 38.226559 18.503197 7.823250 41.199566 17.562132 6.126157 41.109146 21.555719 1.068933 40.776257 22.654591 1.984696 38.756165 24.609385 4.153217 35.292519 27.184326 7.312940 30.803083 30.068840 11.082758 25.829353 32.915009 15.007972 20.971235 35.379547 18.615143 16.814690 37.165188 21.469194 13.861053 38.056564 23.225887 12.466581 37.946159 23.673336 12.799466 36.847290 22.757572 14.819557 34.892494 20.589052 18.283203 32.317551 17.429331 22.772635 29.433041 13.659515 27.746363 26.586872 9.734303 32.604481 24.122334 6.127132 36.761028 22.336691 3.273078 39.714668 21.445314 1.516383 38.627655 25.070396 -4.694134 38.240345 26.247536 -3.905918 36.164669 28.283352 -1.868396 32.650982 30.932297 1.172676 28.123085 33.874866 4.850502 23.127115 36.756145 8.721481 18.265657 39.228607 12.318714 14.125073 40.994038 15.208323 11.204780 41.839500 17.041779 9.857007 41.663017 17.597940 10.244315 40.485878 16.809725 12.319991 38.450066 14.772205 15.833675 35.801117 11.731134 20.361568 32.858547 8.053309 25.357538 29.977270 4.182333 30.218996 27.504808 0.585098 34.359581 25.739374 -2.304513 37.279877 24.893915 -4.137970 35.244701 27.763985 -11.094314 34.794155 28.991686 -10.425950 32.659729 31.074875 -8.500063 29.098866 33.762283 -5.548943 24.541056 36.729771 -1.928538 19.536037 39.619419 1.924477 14.687496 42.082687 5.545370 10.580232 43.822479 8.497410 7.709643 44.628941 10.424537 6.421964 44.404800 11.094310 6.872507 43.177101 10.425947 9.006931 41.093914 8.500061 12.567794 38.406506 5.548943 17.125603 35.439018 1.928540 22.130617 32.549370 -1.924474 26.979160 30.086102 -5.545367 31.086426 28.346310 -8.497409 33.957016 27.539848 -10.424538 31.151981 29.368080 -17.599018 30.630020 30.623739 -17.044197 28.436966 32.730225 -15.211792 24.837339 35.433468 -12.322813 20.265303 38.407410 -8.725716 15.272316 41.293358 -4.854364 10.460606 43.743217 -1.175702 6.410535 45.461502 1.866574 3.610600 46.240963 3.905519 2.398518 45.987579 4.695204 2.920479 44.731922 4.140385 5.113530 42.625435 2.307979 8.713156 39.922195 -0.580997 13.285189 36.948254 -4.178092 18.278173 34.062305 -8.049443 23.089886 31.612444 -11.728107 27.139957 29.894157 -14.770384 29.939896 29.114700 -16.809330 26.627132 29.769325 -23.675652 26.024481 31.032137 -23.229477 23.775036 33.144352 -21.473625 20.150110 35.851212 -18.619877 15.586926 38.826225 -15.012441 10.635869 41.710560 -11.086423 5.894112 44.156326 -7.315362 1.933579 45.868526 -4.154101 -0.768031 46.640648 -1.983937 -1.884864 46.379555 -1.066623 -1.282215 45.116745 -1.512798 0.967230 43.004528 -3.268649 4.592152 40.297672 -6.122394 9.155334 37.322662 -9.729830 14.106390 34.438324 -13.655846 18.848148 31.992558 -17.426907 22.808683 30.280357 -20.588169 25.510296 29.508236 -22.758335 21.962570 29.014990 -28.905474 21.268017 30.262678 -28.562216 18.966108 32.366718 -26.865538 15.334488 35.073330 -24.020086 10.811184 38.056065 -20.369061 5.941772 40.955154 -16.352833 1.313579 43.420925 -12.455818 -2.515171 45.155972 -9.148054 -5.082673 45.951023 -6.828505 -6.079247 45.710175 -5.776941 -5.384696 44.462494 -6.120198 -3.082789 42.358452 -7.816875 0.548829 39.651840 -10.662327 5.072131 36.669106 -14.313348 9.941541 33.770020 -18.329575 14.569736 31.304245 -22.226589 18.398487 29.569197 -25.534357 20.965992 28.774147 -27.853909 17.401157 27.272192 -33.044487 16.602388 28.478689 -32.792923 14.254320 30.562078 -31.134449 10.640162 33.271076 -28.269102 6.195835 36.278934 -24.542479 1.457392 39.222858 -20.404068 -3.003639 41.747768 -16.353025 -6.649195 43.549126 -12.877963 -9.039568 44.409664 -10.398027 -9.886442 44.225578 -9.212335 -9.087674 43.019085 -9.463895 -6.739606 40.935696 -11.122368 -3.125450 38.226700 -13.987717 1.318874 35.218842 -17.714336 6.057315 32.274918 -21.852745 10.518347 29.750008 -25.903790 14.163905 27.948643 -29.378853 16.554281 27.088108 -31.858788 13.089686 24.761597 -36.029102 12.178218 25.898464 -35.845505 9.797875 27.951227 -34.194862 6.235765 30.672287 -31.276264 1.921528 33.733452 -27.441736 -2.624473 36.765495 -23.153782 -6.853923 39.402702 -18.929590 -10.256690 41.327000 -15.278660 -12.422349 42.306278 -12.641349 -13.089690 42.222427 -11.335754 -12.178222 41.085560 -11.519350 -9.797881 39.032803 -13.169991 -6.235773 36.311737 -16.088587 -1.921538 33.250576 -19.923115 2.624463 30.218536 -24.211067 6.853914 27.581324 -28.435261 10.256682 25.657026 -32.086189 12.422343 24.677746 -34.723503 9.082949 21.703339 -37.918415 8.062400 22.747938 -37.762718 5.678401 24.768965 -36.078529 2.218498 27.522650 -33.068989 -1.899994 30.676859 -29.097094 -6.180323 33.851147 -24.641912 -10.106217 36.662651 -20.240807 -13.204160 38.772263 -16.424616 -15.100490 39.925526 -13.653624 -15.566483 39.983345 -12.262057 -14.545935 38.938747 -12.417756 -12.161938 36.917725 -14.101943 -8.702037 34.164040 -17.111481 -4.583547 31.009830 -21.083372 -0.303219 27.835541 -25.538551 3.622678 25.024036 -29.939657 6.720621 22.914425 -33.755852 8.616953 21.761160 -36.526844 5.371840 18.290901 -38.828987 4.264019 19.238607 -38.651398 1.923765 21.244389 -36.889427 -1.366653 24.066313 -33.755592 -5.210363 27.364021 -29.627884 -9.143756 30.739756 -25.004162 -12.692406 33.786354 -20.442118 -15.428293 36.136356 -16.492001 -17.021433 37.506310 -13.630250 -17.279665 37.730988 -12.202039 -16.171844 36.783283 -12.379627 -13.831592 34.777504 -14.141598 -10.541175 31.955578 -17.275427 -6.697466 28.657873 -21.403133 -2.764074 25.282139 -26.026854 0.784576 22.235538 -30.588900 3.520467 19.885536 -34.539017 5.113606 18.515577 -37.400772 1.914354 14.683488 -38.887669 0.756090 15.553085 -38.644409 -1.478889 17.579868 -36.773178 -4.521012 20.519377 -33.499676 -8.003355 24.017063 -29.218737 -11.505894 27.651052 -24.446703 -14.606171 30.983034 -19.759153 -16.930248 33.611122 -15.721477 -18.197807 35.218327 -12.820673 -18.255962 35.610802 -11.406624 -17.097700 34.741203 -11.649883 -14.862721 32.714424 -13.521112 -11.820600 29.774914 -16.794611 -8.338259 26.277231 -21.075548 -4.835720 22.643242 -25.847580 -1.735442 19.311260 -30.535130 0.588637 16.683170 -34.572811 1.856199 15.075964 -37.473618 -1.313918 11.021830 -38.202301 -2.481848 11.847498 -37.868881 -4.550744 13.940134 -35.882675 -7.271069 17.047337 -32.483242 -10.314712 20.794329 -28.080601 -13.314562 24.729170 -23.205778 -15.908794 28.377258 -18.446751 -17.784506 31.298582 -14.377527 -18.715460 33.140785 -11.488914 -18.589369 33.681671 -10.129320 -17.421440 32.856007 -10.462734 -15.352544 30.763371 -12.448939 -12.632220 27.656170 -15.848373 -9.588579 23.909180 -20.251013 -6.588729 19.974340 -25.125834 -3.994496 16.326250 -29.884859 -2.118782 13.404925 -33.954086 -1.187827 11.562718 -36.842705 -4.302186 7.429386 -36.869415 -5.445383 8.246586 -36.442520 -7.302408 10.443111 -34.361362 -9.649278 13.754031 -30.876965 -12.202925 17.780001 -26.409590 -14.655341 22.035427 -21.498075 -16.710730 26.007040 -16.734821 -18.121180 29.215809 -12.694345 -18.716570 31.274708 -9.863988 -18.425089 31.935402 -8.585131 -17.281893 31.118202 -9.012026 -15.424868 28.921679 -11.093180 -13.077999 25.610760 -14.577576 -10.524353 21.584793 -19.044947 -8.071937 17.329369 -23.956459 -6.016548 13.357755 -28.719715 -4.606097 10.148984 -32.760193 -4.010705 8.090082 -35.590553 -6.998141 4.009809 -34.991135 -8.093750 4.845504 -34.482994 -9.717430 7.167247 -32.343449 -11.673343 10.695004 -28.830563 -13.725575 15.003274 -24.368040 -15.626598 19.572416 -19.494127 -17.147120 23.851322 -14.796692 -18.103745 27.323895 -10.842312 -18.381086 29.571293 -8.107944 -17.945698 30.322445 -6.923393 -16.850090 29.486750 -7.431535 -15.226410 27.165009 -9.571076 -13.270498 23.637253 -13.083961 -11.218266 19.328985 -17.546480 -9.317243 14.759845 -22.420391 -7.796720 10.480937 -27.117828 -6.840095 7.008362 -31.072212 -6.562751 4.760962 -33.806580 -9.332147 0.834331 -32.688732 -10.370099 1.703290 -32.119068 -11.765604 4.153050 -29.961357 -13.350343 7.888134 -26.475847 -14.933172 12.458036 -22.082943 -16.323181 17.311558 -17.312494 -17.352711 21.863289 -12.739889 -17.897589 25.564232 -8.916649 -17.892092 27.967991 -6.303912 -17.336885 28.784641 -5.216816 -16.298933 27.915684 -5.786478 -14.903429 25.465923 -7.944188 -13.318690 21.730843 -11.429697 -11.735861 17.160942 -15.822598 -10.345853 12.307423 -20.593046 -9.316321 7.755689 -25.165653 -8.771442 4.054746 -28.988895 -8.776938 1.650984 -31.601633 -11.258440 -2.069497 -30.094347 -12.239215 -1.162840 -29.483604 -13.432428 1.404556 -27.341364 -14.694162 5.323029 -23.926012 -15.872232 10.119952 -19.649488 -16.824545 15.216743 -15.027607 -17.436237 19.998655 -10.617838 -17.633533 23.888920 -6.952059 -17.392632 26.418314 -4.472419 -16.742592 27.281754 -3.477999 -15.761818 26.375099 -4.088739 -14.568604 23.807705 -6.230979 -13.306871 19.889233 -9.646330 -12.128801 15.092313 -13.922852 -11.176488 9.995522 -18.544731 -10.564795 5.213610 -22.954502 -10.367498 1.323343 -26.620281 -10.608398 -1.206054 -29.099924 -12.768213 -4.708061 -27.331791 -13.699398 -3.766325 -26.696983 -14.728356 -1.098774 -24.592251 -15.730981 2.972846 -21.271454 -16.586342 7.957438 -17.135132 -17.191267 13.253786 -12.682184 -17.472797 18.223070 -8.449704 -17.396973 22.265924 -4.948190 -16.972940 24.894720 -2.599976 -16.251844 25.792385 -1.688291 -15.320661 24.850651 -2.323096 -14.291702 22.183102 -4.427828 -13.289078 18.111483 -7.748622 -12.433718 13.126893 -11.884943 -11.828791 7.830547 -16.337889 -11.547261 2.861262 -20.570370 -11.623085 -1.181595 -24.071884 -12.047116 -3.810393 -26.420101 -13.885397 -7.105777 -24.503567 -14.778214 -6.135464 -23.856789 -15.685112 -3.387879 -21.799412 -16.496708 0.805573 -18.579582 -17.115110 5.939105 -14.585664 -17.465731 11.393534 -10.299379 -17.506279 16.510975 -6.237720 -17.231865 20.674191 -2.890580 -16.675587 23.381037 -0.661674 -15.904539 24.305027 0.180159 -15.011724 23.334713 -0.466618 -14.104825 20.587132 -2.523994 -13.293229 16.393681 -5.743821 -12.674828 11.260153 -9.737738 -12.324206 5.805725 -14.024021 -12.283658 0.688282 -18.085682 -12.558071 -3.474936 -21.432823 -13.114348 -6.181785 -23.661732 -14.666747 -9.300088 -21.677334 -15.532693 -8.308895 -21.025703 -16.356113 -5.500333 -19.016115 -17.037695 -1.213158 -15.890957 -17.495226 4.035534 -12.027169 -17.673521 9.612673 -7.890781 -17.551077 14.845572 -3.980704 -17.142662 19.103069 -0.768549 -16.497538 21.871645 1.358250 -15.693513 22.817371 2.143170 -14.827568 21.826178 1.491540 -14.004147 19.017620 -0.518047 -13.322566 14.730446 -3.643203 -12.865035 9.481756 -7.506989 -12.686739 3.904619 -11.643375 -12.809182 -1.328281 -15.553453 -13.217596 -5.585780 -18.765610 -13.862721 -8.354359 -20.892410 -15.168360 -11.320513 -18.903961 -16.017952 -10.316467 -18.250481 -16.791113 -7.465193 -16.281487 -17.394583 -3.110595 -13.234468 -17.755579 2.222102 -9.476942 -17.830557 7.889691 -5.462122 -17.610476 13.208577 -1.674255 -17.121878 17.537228 1.429787 -16.423697 20.353542 3.475612 -15.600143 21.317831 4.216462 -14.750551 20.313787 3.562981 -13.977391 17.462515 1.593987 -13.373920 13.107918 -1.453028 -13.012924 7.775225 -5.210552 -12.937945 2.107637 -9.225370 -13.158028 -3.211250 -13.013239 -13.646625 -7.539903 -16.117283 -14.344805 -10.356220 -18.163109 -15.457341 -13.200760 -16.206116 -16.298586 -12.190961 -15.550703 -17.046036 -9.312833 -13.611071 -17.609537 -4.913520 -10.621163 -17.921124 0.476357 -6.941609 -17.943213 6.206696 -3.016219 -17.673141 11.586334 0.681549 -17.143484 15.966409 3.705689 -16.418123 18.818619 5.691446 -15.584551 19.798946 6.399308 -14.743306 18.789148 5.743897 -13.995856 15.911022 3.804265 -13.432355 11.511711 0.814360 -13.120769 6.121838 -2.865192 -13.098679 0.391500 -6.790582 -13.368750 -4.988140 -10.488350 -13.898407 -9.368217 -13.512491 -14.623766 -12.220431 -15.498251 -15.591489 -14.966376 -13.600168 -16.429790 -13.957111 -12.940178 -17.167938 -11.066657 -11.015369 -17.716898 -6.643641 -8.057903 -18.010460 -1.221546 -4.424493 -18.013214 4.545643 -0.553383 -17.724831 9.962317 3.088513 -17.180090 14.375146 6.061932 -16.444698 17.251879 8.008232 -15.607352 18.245537 8.692663 -14.769052 17.236275 8.032675 -14.030904 14.345821 6.107867 -13.481943 9.922809 3.150403 -13.188381 4.500716 -0.483006 -13.185627 -1.266472 -4.354115 -13.474010 -6.683146 -7.996012 -14.018750 -11.095978 -10.969431 -14.754142 -13.972713 -12.915735 -15.624997 -16.641966 -11.092587 -16.462946 -15.638383 -10.423549 -17.199827 -12.748577 -8.497280 -17.746759 -8.321101 -5.546118 -18.037777 -2.889976 -1.926015 -18.037777 2.889725 1.926390 -17.746761 8.320883 5.546440 -17.199831 12.748423 8.497503 -16.462952 15.638316 10.423640 -15.625003 16.642000 11.092527 -14.787054 15.638419 10.423491 -14.050174 12.748614 8.497223 -13.503241 8.321141 5.546062 -13.212223 2.890019 1.925961 -13.212222 -2.889681 -1.926443 -13.503237 -8.320840 -5.546493 -14.050168 -12.748382 -8.497559 -14.787047 -15.638279 -10.423697 -15.607663 -18.244593 -8.694071 -16.444986 -17.251093 -8.009382 -17.180323 -14.374608 -6.062693 -17.724977 -9.962088 -3.088800 -18.013260 -4.545744 0.553601 -18.010397 1.221129 4.425182 -17.716736 6.642961 8.058972 -17.167696 11.065801 11.016684 -16.429499 13.956189 12.941574 -15.591182 14.965501 13.601471 -14.753860 13.972001 12.916784 -14.018523 11.095518 10.970097 -13.473867 6.683001 7.996204 -13.185585 1.266660 4.353806 -13.188447 -4.500211 0.482226 -13.482108 -9.922045 -3.151565 -14.031148 -14.344886 -6.109279 -14.769345 -17.235277 -8.034171 -15.585720 -19.797182 -6.401866 -16.419214 -18.817038 -5.693662 -17.144365 -15.965196 -3.707301 -17.673708 -11.585629 -0.682367 -17.943398 -6.206579 3.016288 -17.920902 -0.476839 6.942553 -17.608938 4.912498 10.622858 -17.045130 9.311400 13.613309 -16.297485 12.189297 15.553211 -15.456178 13.199067 16.208584 -14.622683 12.218925 15.500381 -13.897532 9.367083 13.514023 -13.368189 4.987519 10.489090 -13.098500 -0.391528 6.790436 -13.120995 -6.121266 2.864173 -13.432959 -11.510604 -0.816134 -13.996765 -15.909510 -3.806586 -14.744411 -18.787409 -5.746491 -15.602850 -21.315063 -4.220317 -16.426226 -20.350996 -3.478981 -17.123924 -17.535206 -1.432270 -17.611794 -13.207319 1.672952 -17.830988 -7.889341 5.462151 -17.755072 -2.222701 9.478292 -17.393198 3.109121 13.236969 -16.789019 7.463031 16.284830 -16.015402 10.313881 18.254259 -15.165661 11.317818 18.907715 -14.342285 10.353751 18.166380 -13.644587 7.537964 16.119671 -13.156718 3.210078 13.014449 -12.937523 -2.107896 9.225252 -13.013440 -7.774535 5.209112 -13.375312 -13.106359 1.450435 -13.979492 -17.460270 -1.597429 -14.753107 -20.311123 -3.566860 -15.698283 -22.813595 -2.148056 -16.501993 -21.868122 -1.362509 -17.146265 -19.100220 0.765425 -17.553394 -14.843735 3.979085 -17.674273 -9.612062 7.890856 -17.494322 -4.036221 12.028921 -17.035246 1.211259 15.894167 -16.352415 5.497458 19.020390 -15.528190 8.305393 21.030519 -14.661984 9.296391 21.682106 -13.858275 8.350920 20.896561 -13.214003 5.583018 18.768627 -12.806873 1.326535 15.554970 -12.685994 -3.905135 11.643200 -12.865946 -9.480974 7.505136 -13.325022 -14.728456 3.639890 -14.007852 -19.014656 0.513665 -14.832076 -21.822596 -1.496468 -15.912259 -24.299894 -0.186053 -16.682795 -23.376165 0.656531 -17.237694 -20.670162 2.886805 -17.510027 -16.508268 6.235761 -17.466946 -11.392470 10.299469 -17.113646 -5.939809 14.587783 -16.492743 -0.807958 18.583469 -15.679126 3.384109 21.804590 -14.770928 6.130766 23.862633 -13.877693 7.100725 24.509361 -13.107157 6.176997 23.666779 -12.552258 3.470996 21.436508 -12.279924 -0.690896 18.087553 -12.323006 -5.806691 14.023847 -12.676305 -11.259350 9.735534 -13.297207 -16.391203 5.739846 -14.110825 -20.583271 2.518723 -15.019022 -23.329933 0.460680 -16.263086 -25.785679 1.681853 -16.983402 -24.888405 2.594539 -17.405392 -22.260756 4.944404 -17.478161 -18.219666 8.448021 -17.192930 -13.252550 12.682801 -16.584103 -7.958517 17.137968 -15.725114 -2.976107 21.276161 -14.719567 1.093733 24.598255 -13.688749 3.760117 26.703556 -12.756991 4.701439 27.338131 -12.036675 3.804166 26.425447 -11.614684 1.176518 24.075584 -11.541915 -2.864568 20.571968 -11.827146 -7.831682 16.337191 -12.435972 -13.125713 11.882025 -13.294962 -18.108126 7.743832 -14.300508 -22.177967 4.421736 -15.331326 -24.844353 2.316433 -16.756092 -27.274136 3.472388 -17.405151 -26.411160 4.467852 -17.643564 -23.883091 6.949082 -17.442572 -19.994846 10.616806 -16.826418 -15.215407 15.028639 -15.869419 -10.121246 19.652452 -14.687006 -5.326795 23.930544 -13.421794 -1.410332 27.346912 -12.226385 1.155759 29.489494 -11.244965 2.061967 30.099861 -10.595905 1.198994 29.104401 -10.357493 -1.329074 26.623171 -10.558485 -5.217316 22.955450 -11.174639 -9.996753 18.543619 -12.131636 -15.090913 13.919806 -13.314049 -19.885365 9.641714 -14.579261 -23.801830 6.225344 -15.774670 -26.367924 4.082758 -17.351767 -28.776361 5.212740 -17.905813 -27.960318 6.300884 -17.908495 -25.558083 8.915026 -17.359489 -21.859402 12.739865 -16.325014 -17.310392 17.314066 -14.929841 -12.459729 22.085915 -13.342252 -7.892477 26.479855 -11.753731 -4.159513 29.965910 -10.355878 -1.711084 32.123615 -9.317295 -0.842512 32.692719 -8.763248 -1.658555 31.604574 -8.760567 -4.060787 28.990433 -9.309572 -7.759466 25.165596 -10.344047 -12.308475 20.591396 -11.739218 -17.159136 15.819550 -13.326807 -21.726389 11.425610 -14.915328 -25.459354 7.939552 -16.313181 -27.907787 5.781844 -17.965210 -30.311451 6.920716 -18.398952 -29.561226 8.106459 -18.117809 -27.315966 10.842194 -17.155691 -23.846478 14.797949 -15.628644 -19.571234 19.496607 -13.720851 -15.005893 24.371435 -11.662422 -10.701101 28.834457 -9.701632 -7.176081 32.347370 -8.074983 -4.856002 34.486465 -6.978672 -4.020700 34.993732 -6.544928 -4.770922 33.807991 -6.826070 -7.016182 31.072258 -7.788187 -10.485666 27.116505 -9.315233 -14.760908 22.417849 -11.223025 -19.326248 17.543022 -13.281454 -23.631041 13.079998 -15.242245 -27.156063 9.567082 -16.868895 -29.476145 7.427987 -18.444687 -31.924046 8.585096 -18.734264 -31.264654 9.865056 -18.134838 -29.208263 12.696385 -16.718708 -26.002903 16.737583 -14.656679 -22.035191 21.501225 -12.197465 -17.783689 26.412739 -9.637683 -13.761195 30.879726 -7.286079 -10.452878 34.363403 -5.426292 -8.257769 36.443588 -4.282640 -7.440631 36.869377 -3.993063 -8.100022 35.589420 -4.592489 -10.156412 32.758095 -6.008618 -13.361770 28.716896 -8.070644 -17.329481 23.953259 -10.529858 -21.580980 19.041746 -13.089641 -25.603476 14.574757 -15.441244 -28.911795 11.091076 -17.301033 -31.106907 9.010889 -18.607834 -33.670673 10.131820 -18.731821 -33.131397 11.492248 -17.796793 -31.291931 14.381289 -15.915527 -28.374136 18.450485 -13.314934 -24.729948 23.209030 -10.308681 -20.798906 28.082975 -7.259370 -17.055153 32.484444 -4.534791 -13.950242 35.882565 -2.463568 -11.858669 37.867466 -1.295521 -11.032708 38.199741 -1.171534 -11.571982 36.839317 -2.106561 -13.411448 33.950279 -3.987824 -16.329241 29.881083 -6.588417 -19.973427 25.122538 -9.594667 -23.904467 20.248596 -12.643979 -27.648220 15.847122 -15.368559 -30.753134 12.449001 -17.439783 -32.844711 10.464098 -18.273399 -35.600266 11.411421 -18.212826 -35.209770 12.825915 -16.941042 -33.605568 15.726530 -14.611442 -30.981140 19.763409 -11.505012 -27.653042 24.449644 -7.996431 -24.022684 29.220007 -4.508891 -20.527946 33.499115 -1.463035 -17.590345 36.770859 0.773759 -15.564197 38.640602 1.931700 -14.693884 38.882835 1.871128 -15.084379 37.468346 0.599343 -16.688583 34.567730 -1.730255 -19.313007 30.530855 -4.836684 -22.641106 25.844622 -8.345262 -26.271460 21.074261 -11.832804 -29.766199 16.795147 -14.878660 -32.703800 13.523406 -17.115456 -34.729954 11.653655 -17.291914 -37.723682 12.207134 -17.031359 -37.500969 13.635231 -15.434706 -36.133614 16.496265 -12.694537 -33.786533 20.445154 -9.141356 -30.742825 25.005604 -5.203729 -27.369600 29.627556 -1.356595 -24.073725 33.753532 1.936029 -21.252728 36.885883 4.277003 -19.246862 38.646797 5.383970 -18.298065 38.823887 5.123416 -18.520775 37.395790 3.526765 -19.888132 34.534760 0.786597 -22.235210 30.585873 -2.766582 -25.278919 26.025425 -6.704207 -28.652142 21.403475 -10.551343 -31.948017 17.277496 -13.843968 -34.769016 14.145144 -16.184944 -36.774883 12.384224 -15.575989 -39.977974 12.267365 -15.107668 -39.921947 13.658223 -13.208153 -38.770897 16.427952 -10.106554 -36.663654 20.242485 -6.176969 -33.854389 24.641729 -1.893364 -30.681940 29.095074 2.227592 -27.528950 33.065372 5.688855 -24.775715 36.073761 8.072943 -22.754318 37.757374 9.092301 -21.708567 37.913143 8.623981 -21.764595 36.522285 6.724468 -22.915646 33.752556 3.622870 -25.022882 29.938028 -0.306713 -27.832146 25.538784 -4.590316 -31.004595 21.085442 -8.711273 -34.157585 17.115139 -12.172537 -36.910824 14.106750 -14.556628 -38.932220 12.423138 -13.098382 -42.218063 11.341891 -12.428619 -42.303440 12.646147 -10.259791 -41.326027 15.281545 -6.853494 -39.403706 18.930222 -2.620574 -36.768337 23.152092 1.928414 -33.737789 27.437935 6.244793 -30.677586 31.270813 9.807948 -27.956841 34.188431 12.188108 -25.903706 35.838875 13.098191 -24.765825 36.023075 12.428429 -24.680445 34.718826 10.259604 -25.657856 32.083424 6.853307 -27.580179 28.434750 2.620389 -30.215546 24.212883 -1.928597 -33.246094 19.927040 -6.244978 -36.306297 16.094160 -9.808134 -39.027042 13.176542 -12.188296 -41.080177 11.526096 -9.892659 -44.223072 9.217680 -9.043694 -44.408134 10.401724 -6.650745 -43.548756 12.879577 -3.002439 -41.748596 16.352371 1.461185 -39.224773 20.401241 6.201748 -36.281700 24.537828 10.647467 -33.274361 28.263203 14.262124 -30.565470 31.128025 16.609737 -28.481773 32.786758 17.407152 -27.274593 33.039337 16.558187 -27.089531 31.855297 14.165240 -27.948906 29.377445 10.516936 -29.749069 25.904652 6.053314 -32.272888 21.855783 1.312752 -35.215958 17.719196 -3.132967 -38.223301 13.993823 -6.747626 -40.932190 11.128998 -9.095243 -43.015884 9.470259 -6.082735 -45.709259 5.780507 -5.084556 -45.950542 6.830448 -2.515239 -45.155987 9.148154 1.315320 -43.421429 12.454082 5.945098 -40.956078 16.349483 10.815677 -38.057297 20.364519 15.339590 -35.074718 24.014912 18.971188 -32.368084 26.860371 21.272448 -30.263857 28.557697 21.965803 -29.015839 28.902164 20.967627 -28.774553 27.852224 18.398312 -29.569109 25.534519 14.567754 -31.303665 22.228592 9.937978 -33.769016 18.333191 5.067401 -36.667797 14.318159 0.543487 -39.650375 10.667765 -3.088115 -42.357010 7.822302 -5.389378 -44.461239 6.124975 -1.886203 -46.379463 1.068234 -0.768166 -46.640606 1.984067 1.934647 -45.868542 4.152754 5.896240 -44.156395 7.312716 10.638784 -41.710674 11.082819 15.590260 -38.826366 15.008331 20.153442 -35.851364 18.615776 23.777948 -33.144497 21.470045 26.026609 -31.032255 23.226871 26.628202 -29.769403 23.674355 25.510166 -29.508259 22.758522 22.807354 -30.280323 20.589836 18.845764 -31.992468 17.429876 14.103222 -34.438187 13.659775 9.151748 -37.322495 9.734263 4.588563 -40.297497 6.126818 0.964055 -43.004360 3.272547 -1.284608 -45.116604 1.515719 2.396898 -45.987907 -4.692870 3.610030 -46.241051 -3.904719 6.411066 -45.461342 -1.867383 10.462158 -43.742836 1.173408 15.274688 -41.292801 4.850887 20.268190 -38.406754 8.721498 24.840376 -35.432785 12.318384 28.439772 -32.729614 15.207712 30.632236 -30.623270 17.040985 31.153330 -29.367813 17.597082 29.940201 -29.114670 16.808933 27.139166 -29.894375 14.771597 23.088074 -31.612885 11.730808 18.275547 -34.062916 8.053330 13.282046 -36.948963 4.182722 8.709860 -39.922928 0.585834 5.110462 -42.626106 -2.303495 2.917993 -44.732449 -4.136771 6.420932 -44.405396 -11.092510 7.709474 -44.629036 -10.424231 10.580931 -43.822075 -8.498607 14.688965 -42.081841 -5.547898 19.538086 -39.618237 -1.928004 24.543419 -36.728405 1.924463 29.101242 -33.760906 5.544837 32.661823 -31.073662 8.496449 34.795696 -28.990793 10.423292 35.245487 -27.763527 11.092958 33.956947 -27.539886 10.424680 31.085493 -28.346848 8.499057 26.977461 -30.087078 5.548351 22.128342 -32.550682 1.928458 17.123011 -35.440514 -1.924007 12.565185 -38.408012 -5.544382 9.004602 -41.095257 -8.495997 6.870726 -43.178123 -10.422841 9.857864 -41.662041 -17.599777 11.206259 -41.837860 -17.044916 14.126985 -40.991943 -15.212357 18.267759 -39.226330 -12.323133 23.129143 -36.753967 -8.725725 28.124783 -33.873066 -4.854037 32.652126 -30.931108 -1.175051 36.165115 -28.282928 1.867494 38.240028 -26.247942 3.906623 38.626598 -25.071596 4.696385 37.278206 -24.895775 4.141527 34.357483 -25.741690 2.308969 30.216709 -27.507303 -0.580255 25.355328 -29.979662 -4.177660 20.359690 -32.860561 -8.049347 15.832343 -35.802521 -11.728334 12.319353 -38.450699 -14.770882 10.244438 -40.485691 -16.810013 12.467755 -37.943748 -23.676573 13.862687 -38.053284 -23.230347 16.816578 -37.161449 -21.474316 20.973145 -35.375813 -18.620285 25.831043 -32.911751 -15.012493 30.804340 -30.066465 -11.086090 35.293182 -27.183138 -7.314664 38.756149 -24.609543 -4.153099 40.775555 -22.656094 -1.982728 41.107830 -21.558401 -1.065331 39.712898 -21.448866 -1.511557 36.759010 -22.340702 -3.267585 32.602444 -24.126335 -6.121614 27.744549 -26.590397 -9.729405 22.771252 -29.435682 -13.655805 18.282410 -32.319008 -17.427235 14.819441 -34.892605 -20.588799 12.800033 -36.846058 -22.759172 14.145473 -33.531174 -28.901836 15.573307 -33.553413 -28.558689 18.546549 -32.611420 -26.862530 22.706585 -30.818817 -24.017935 27.551651 -28.391821 -20.368008 32.497360 -25.623158 -16.352980 36.947186 -22.846773 -12.457128 40.364418 -20.397541 -9.150346 42.336884 -18.570871 -6.831481 42.626678 -17.587088 -5.780224 41.198845 -17.564850 -6.123369 38.225605 -18.506842 -7.819529 34.065575 -20.299442 -10.664122 29.220509 -22.726439 -14.314048 24.274799 -25.495100 -18.329073 19.824972 -28.271482 -22.224926 16.407738 -30.720720 -25.531708 14.435268 -32.547390 -27.850574 14.917938 -28.705292 -33.045021 16.362177 -28.616806 -32.793434 19.340466 -27.625130 -31.134865 23.493576 -25.849873 -28.269350 28.320583 -23.505157 -24.542519 33.239277 -20.873793 -20.403879 37.656391 -18.273157 -16.352617 41.039158 -16.016930 -12.877370 42.979565 -14.377239 -10.397304 43.243568 -13.551861 -9.211554 41.799332 -13.640346 -9.463137 38.821045 -14.632021 -11.121709 34.667934 -16.407276 -13.987219 29.840931 -18.751991 -17.714048 24.922237 -21.383356 -21.852686 20.505123 -23.983992 -25.903950 17.122353 -26.240221 -29.379198 15.181944 -27.879913 -31.859264 14.899465 -23.714947 -36.030308 16.339754 -23.494074 -35.846653 19.307655 -22.459305 -34.195805 23.445192 -20.735445 -31.276878 28.253319 -18.530420 -27.441940 33.152103 -16.110188 -23.153542 37.550678 -13.766667 -18.928928 40.918514 -11.782516 -15.277645 42.849396 -10.397057 -12.640096 43.110435 -9.777392 -11.334405 41.670147 -9.998266 -11.518059 38.702248 -11.033035 -13.168905 34.564713 -12.756892 -16.087830 29.756588 -14.961917 -19.922764 24.857803 -17.382147 -24.211163 20.459229 -19.725670 -28.435778 17.091391 -21.709820 -32.087063 15.160504 -23.095282 -34.724613 14.254209 -18.717684 -37.918488 15.669124 -18.356123 -37.762787 18.611372 -17.302025 -36.078590 22.726078 -15.682524 -33.069031 27.516947 -13.692960 -29.097107 32.406124 -11.573303 -24.641891 36.803909 -9.579216 -20.240751 40.179859 -7.951213 -16.424526 42.126789 -6.885656 -13.653509 42.409870 -6.511068 -12.261927 40.994957 -6.872628 -12.417622 38.052708 -7.926727 -14.101819 33.938004 -9.546227 -17.111376 29.147139 -11.535789 -21.083298 24.257961 -13.655445 -25.538513 19.860176 -15.649533 -29.939655 16.484222 -17.277536 -33.755882 14.537290 -18.343094 -36.526901 13.154503 -13.796513 -38.829433 14.529137 -13.310940 -38.651802 17.436310 -12.287237 -36.889740 21.525373 -10.848880 -33.755779 26.303127 -9.169352 -29.627918 31.193300 -7.451230 -25.004042 35.606068 -5.901748 -20.441860 39.009186 -4.707792 -16.491634 40.992191 -4.013374 -13.629823 41.315895 -3.902249 -12.201602 39.941261 -4.387821 -12.379234 37.034092 -5.411522 -14.141294 32.945030 -6.849880 -17.275253 28.167278 -8.529408 -21.403112 23.277105 -10.247528 -26.026985 18.864336 -11.797010 -30.589169 15.461215 -12.990967 -34.539394 13.478210 -13.685387 -37.401207 11.759220 -9.003184 -38.886883 13.091471 -8.434890 -38.643768 15.964219 -7.512313 -36.772766 20.030970 -6.346729 -33.499550 24.801216 -5.078725 -29.218906 29.699591 -3.861242 -24.447153 34.135281 -2.841125 -19.759836 37.573273 -2.141416 -15.722307 39.598900 -1.846510 -12.821558 39.967838 -1.991977 -11.407459 38.635590 -2.560270 -11.650571 35.762844 -3.482847 -13.521572 31.696093 -4.648430 -16.794788 26.925850 -5.916434 -21.075430 22.027475 -7.133917 -25.847181 17.591785 -8.154034 -30.534500 14.153789 -8.853745 -34.572029 12.128160 -9.148651 -37.472778 10.202206 -4.372631 -38.202415 11.501224 -3.774027 -37.868980 14.347952 -3.028707 -35.882748 18.399035 -2.226567 -32.483288 23.165850 -1.464356 -28.080622 28.073450 -0.834009 -23.205778 32.529903 -0.411555 -18.446735 35.997700 -0.247948 -14.377505 38.058571 -0.362921 -11.488895 38.463943 -0.742608 -10.129313 37.164928 -1.341211 -10.462746 34.318199 -2.086531 -12.448975 30.267120 -2.888671 -15.848434 25.500307 -3.650882 -20.251097 20.592709 -4.281229 -25.125938 16.136251 -4.703683 -29.884981 12.668454 -4.867290 -33.954216 10.607581 -4.752318 -36.842827 8.585201 0.011240 -36.869484 9.864545 0.592627 -36.442608 12.695332 1.102521 -34.361473 16.736128 1.479423 -30.877087 21.499552 1.677871 -26.409719 26.411068 1.673931 -21.498205 30.878269 1.468078 -16.734943 34.362350 1.085140 -12.694455 36.443077 0.571306 -9.864078 36.869484 -0.011449 -8.585201 35.590141 -0.592835 -9.012075 32.759357 -1.102730 -11.093212 28.718563 -1.479631 -14.577595 23.955139 -1.678080 -19.044958 19.043627 -1.674140 -23.956470 14.576424 -1.468287 -28.719734 11.092340 -1.085350 -32.760223 9.011611 -0.571516 -35.590603 6.971740 4.055659 -34.991211 8.243273 4.586638 -34.483063 11.065798 4.831906 -32.343510 15.098879 4.761879 -28.830624 19.856066 4.385005 -24.368097 24.763569 3.746738 -19.494188 29.229473 2.924064 -14.796761 32.715126 2.016210 -10.842387 34.800102 1.132676 -8.108030 35.232925 0.380029 -6.923489 33.961395 -0.150950 -7.431637 31.138870 -0.396218 -9.571187 27.105793 -0.326191 -13.084072 22.348608 0.050683 -17.546595 17.441105 0.688950 -22.420502 12.975201 1.511623 -27.117931 9.489547 2.419477 -31.072304 7.404566 3.303011 -33.806667 5.388670 7.663244 -32.689156 6.660145 8.127762 -32.119488 9.479419 8.111685 -29.961731 13.506445 7.616950 -26.476141 18.255505 6.703230 -22.083134 23.153791 5.480734 -17.312571 27.610497 4.096913 -12.739854 31.088079 2.718675 -8.916516 33.167091 1.512258 -6.303712 33.596771 0.623171 -5.216582 32.325294 0.158652 -5.786251 29.506023 0.174729 -7.944007 25.478998 0.669463 -11.429593 20.729942 1.583182 -15.822598 15.831657 2.805677 -20.593161 11.374950 4.189499 -25.165878 7.897366 5.567737 -28.989216 5.818352 6.774155 -31.602024 3.837049 10.784647 -30.094490 5.112621 11.180704 -29.483749 7.932657 10.930382 -27.341503 11.957019 10.063874 -23.926138 16.700310 8.685694 -19.649601 21.590420 6.962069 -15.027704 26.037525 5.100896 -10.617918 29.505243 3.326659 -6.952127 31.575315 1.853356 -4.472478 31.998060 0.858691 -3.478053 30.722490 0.462634 -4.088796 27.902456 0.712955 -6.231040 23.878096 1.579462 -9.646402 19.134808 2.957641 -13.922937 14.244699 4.681265 -18.544832 9.797592 6.542439 -22.954620 6.329872 8.316675 -26.620411 4.259797 9.789979 -29.100063 2.306895 13.409804 -27.332752 3.588035 13.745470 -26.697962 6.412662 13.303102 -24.593140 10.440084 12.136058 -21.272158 15.184533 10.385100 -17.135578 20.073759 8.261418 -12.682329 24.518049 6.021164 -8.449544 27.981358 3.934542 -4.947755 30.045958 2.253229 -2.599331 30.462828 1.180018 -1.687526 29.181688 0.844352 -2.322315 26.357063 1.286719 -4.427136 22.329643 2.453762 -7.748116 17.585196 4.204720 -11.884695 12.695971 6.328399 -16.337942 8.251679 8.568654 -20.570728 4.788369 10.655277 -24.072517 2.723767 12.336590 -26.420946 0.789012 15.577466 -24.503971 2.075707 15.865559 -23.857157 4.908604 15.277264 -21.799709 8.946012 13.883539 -18.579788 13.700964 11.852487 -14.585765 18.599937 9.429083 -10.299374 23.052044 6.905625 -6.237622 26.520298 4.586483 -2.890412 28.586374 2.751373 -0.661470 29.001076 1.621642 0.180363 27.714380 1.333549 -0.466451 24.881485 1.921844 -2.523896 20.844078 3.315568 -5.743815 16.089130 5.346619 -9.737839 11.190158 7.770022 -14.024227 6.738049 10.293478 -18.085979 3.269794 12.612623 -21.433191 1.203714 14.447732 -23.662136 -0.720886 17.353256 -21.676247 0.570526 17.607487 -21.024654 3.414583 16.916040 -19.015245 7.468250 15.362314 -15.890385 12.242595 13.133711 -12.026976 17.161760 10.499035 -7.891004 21.632420 7.776066 -3.981328 25.115351 5.293234 -0.769512 27.190458 3.350006 1.357052 27.607452 2.180761 2.141868 26.316042 1.926530 1.490277 23.471987 2.617977 -0.519130 19.418322 4.171701 -3.643989 14.643979 6.400302 -7.507396 9.724814 9.034978 -11.643368 5.254153 11.757947 -15.553043 1.771220 14.240780 -18.764862 -0.303890 16.184010 -20.891426 -2.219485 18.795944 -18.904533 -0.925158 19.029709 -18.251064 1.930687 18.273718 -16.282028 6.003591 16.619154 -13.234914 10.802302 14.265581 -9.477251 15.748024 11.496877 -5.462270 20.244230 8.646987 -1.674238 23.748611 6.059651 1.429955 25.838490 4.046938 3.475898 26.261793 2.851613 4.216818 24.967466 2.617847 3.563351 22.111624 3.373837 1.594314 18.038721 5.028401 -1.452798 13.240012 7.381971 -5.210459 8.294291 10.150675 -9.225438 3.798084 13.000565 -13.013472 0.293700 15.587902 -16.117668 -1.796181 17.600615 -18.163612 -3.703264 19.986389 -16.206762 -2.408167 20.210070 -15.551290 0.458032 19.418400 -13.611538 4.549631 17.706867 -10.621469 9.373121 15.281907 -6.941731 14.346718 12.436007 -3.016153 18.870529 9.512423 0.681780 22.398922 6.863784 3.706045 24.506317 4.809554 5.691871 24.938532 3.597503 6.399737 23.643436 3.373822 5.744266 20.777239 4.165491 3.804515 16.685642 5.877022 0.814448 11.862154 8.301980 -2.865288 6.888559 11.147880 -6.790865 2.364745 14.071463 -10.488798 -1.163649 16.720104 -13.513065 -3.271047 18.774334 -15.498893 -5.166954 20.987476 -13.597084 -3.873645 21.208721 -12.937270 -1.001086 20.402441 -11.013004 3.104250 18.665888 -8.056379 7.947199 16.208513 -4.424009 12.943629 13.326714 -0.554010 17.490896 10.368078 3.086836 21.040535 7.689458 6.059393 23.164404 5.613938 8.005124 23.606337 4.391856 8.689346 22.313028 4.170611 8.029534 19.440472 4.976889 6.105269 15.335138 6.713442 3.148647 10.492191 9.170815 -0.483722 5.495762 12.052612 -4.353720 0.948494 15.011250 -7.994567 -2.601146 17.689869 -10.967125 -4.725020 19.765388 -12.912859 -6.598434 21.851801 -11.095069 -5.310406 22.075737 -10.425900 -2.439552 21.269125 -8.499231 1.667860 19.529253 -5.547445 6.516417 17.065975 -1.926571 11.521310 14.176401 1.926658 16.078873 11.209055 5.547486 19.639399 8.521841 8.499189 21.773438 6.438879 10.425749 22.223589 5.211403 11.094792 20.935562 4.987467 10.425624 18.064711 5.794077 8.498956 13.957300 7.533948 5.547171 9.108746 9.997224 1.926300 4.103855 12.886798 -1.926929 -0.453710 15.854144 -5.547758 -4.014240 18.541359 -8.499462 -6.148280 20.624323 -10.426023 -7.996110 22.638840 -8.694574 -6.717063 22.867233 -8.009865 -3.858331 22.065819 -6.063108 0.235282 20.331257 -3.089112 5.070026 17.872761 0.553417 10.062758 14.986864 4.425135 14.611280 12.021648 8.059054 18.166975 9.334762 11.016872 20.300974 7.250282 12.941833 20.755884 6.019628 13.601757 19.476839 5.791235 12.917048 16.618109 6.592650 10.970294 12.524497 8.327210 7.996299 7.689755 10.785705 4.353771 2.697024 13.671598 0.482054 -1.851499 16.636814 -3.151866 -5.407197 19.323702 -6.109686 -7.541198 21.408184 -8.034649 -9.351471 23.396221 -6.402538 -8.085900 23.627964 -5.694316 -5.253621 22.830027 -3.707870 -1.196244 21.098652 -0.682796 3.596848 18.642670 3.016038 8.547539 15.758307 6.942498 13.058701 12.793461 10.622993 16.586222 10.105738 13.613604 18.704630 8.019313 15.553617 19.158417 6.785842 16.209040 17.892849 6.554099 15.500818 15.060571 7.352036 13.514374 11.003196 9.083407 10.489302 6.210106 11.539389 6.790469 1.259416 14.423750 2.864010 -3.251746 17.388596 -0.816486 -6.779269 20.076321 -3.807099 -8.897682 22.162746 -5.747114 -10.657550 24.170057 -4.220764 -9.410973 24.401081 -3.479397 -6.623633 23.597391 -1.432618 -2.631727 21.855928 1.672703 2.083265 19.386736 5.462018 6.952642 16.487637 9.478279 11.389087 13.508307 13.237065 14.857499 10.808092 16.285011 16.939537 8.712682 18.254494 17.384077 7.474813 18.907959 16.137501 7.243790 18.166594 13.350163 8.047478 16.119816 9.358258 9.788940 13.014496 4.643270 12.258131 9.225183 -0.226107 15.157228 5.208922 -4.662553 18.136560 1.450136 -8.130968 20.836775 -1.597813 -10.213009 22.932186 -3.567297 -11.909538 25.001236 -2.146790 -10.688810 25.224588 -1.361367 -7.969344 24.398722 0.766291 -4.079147 22.623245 3.979558 0.512567 20.112310 7.890866 5.251967 17.168770 12.028454 9.567411 14.147663 15.893265 12.938396 11.413374 19.019150 14.958330 9.295702 21.029079 15.383578 8.050069 21.680624 14.162852 7.826715 20.895203 11.443387 8.652581 18.767546 7.553192 10.428055 15.554281 2.961480 12.938990 11.642975 -1.777919 15.882527 7.505388 -6.093365 18.903637 3.640576 -9.464352 21.637924 0.514689 -11.484287 23.755598 -1.495241 -13.087865 25.930462 -0.186337 -11.902627 26.135887 0.656256 -9.281743 25.263416 2.886558 -5.541331 23.418280 6.235559 -1.132539 20.823029 10.299324 3.412867 17.790689 14.587700 7.546643 14.687006 18.583445 10.770196 11.886330 21.804615 12.694718 9.726463 23.862690 13.088082 8.467917 24.509434 11.902846 8.262492 23.666843 9.281964 9.134962 21.436543 5.541554 10.980099 18.087542 1.132764 13.575348 14.023779 -3.412641 16.607685 9.735404 -7.546418 19.711369 5.739658 -10.769974 22.512045 2.518486 -12.694498 24.671913 0.460410 -14.198614 26.977512 1.681296 -13.061417 27.152643 2.594018 -10.574928 26.204182 4.943970 -7.039056 24.246525 8.447714 -2.880278 21.515797 12.682647 1.399795 18.341362 17.137970 5.284921 15.106106 21.276310 8.306499 12.200250 24.598518 10.100084 9.974279 26.703888 10.449339 8.696678 27.338486 9.312142 8.521548 26.425766 6.825655 9.470008 24.075813 3.289785 11.427663 20.572071 -0.868992 14.158390 16.337141 -5.149063 17.332823 11.881817 -9.034191 20.568077 7.743479 -12.055772 23.473936 4.421268 -13.849358 25.699909 2.315893 -15.245874 28.145916 3.473923 -14.173788 28.276730 4.469146 -11.864560 27.219620 6.949966 -8.596720 25.102091 10.617161 -4.764414 22.179546 15.028412 -0.829878 18.804491 19.651657 2.732325 15.384004 23.929260 5.492543 12.330647 27.345287 7.117852 10.012701 29.487709 7.412215 8.709743 30.098122 6.340130 8.578929 29.102900 4.030904 9.636038 26.622080 0.763064 11.753565 22.954887 -3.069239 14.676107 18.543640 -7.003775 18.051163 13.920397 -10.565979 21.471651 9.642790 -13.326199 24.525007 6.226763 -14.951509 26.842957 4.084337 -16.243759 29.416031 5.212296 -15.260136 29.487764 6.300545 -13.178658 28.288820 8.914824 -10.250382 25.963806 12.739815 -6.828504 22.793156 17.314165 -3.325752 19.159292 22.086140 -0.164611 15.500519 26.480167 2.273641 12.258135 29.966267 3.694914 9.823217 32.123962 3.927781 8.489457 32.693001 2.944158 8.417722 31.604752 0.862680 9.616667 28.990475 -2.065593 11.941677 25.165485 -5.487470 15.112328 20.591139 -8.990221 18.746187 15.819164 -12.151362 22.404961 11.425135 -14.589617 25.647348 7.939034 -16.010891 28.082266 5.781337 -17.267721 30.714081 6.920640 -16.401142 30.714598 8.106387 -14.597273 29.348484 10.842125 -12.073685 26.780508 14.797884 -9.134762 23.320410 19.496546 -6.134980 19.385529 24.371378 -3.436159 15.450468 28.834402 -1.363815 11.989854 32.347317 -0.167904 9.421087 34.486408 0.007330 8.054001 34.993675 -0.859248 8.053483 33.807930 -2.663117 9.419597 31.072193 -5.186703 11.987570 27.116434 -8.125626 15.447666 22.417776 -11.125406 19.382547 17.542946 -13.824227 23.317608 13.079920 -15.896573 26.778223 9.567002 -17.092485 29.346991 7.427907 -18.425446 31.935099 8.585044 -17.709539 31.856228 9.864971 -16.228207 30.309011 12.696270 -14.160117 27.480068 16.737446 -11.754711 23.710606 21.501076 -9.302118 19.455282 26.412588 -7.098157 15.227352 30.879589 -5.408658 11.536764 34.363289 -4.437397 8.828656 36.443504 -4.301526 7.429670 36.869328 -5.017430 7.508541 35.589405 -6.498762 9.055755 32.758106 -8.566852 11.884697 28.716930 -10.972256 15.654158 23.953306 -13.424848 19.909479 19.041790 -15.628810 24.137409 14.574791 -17.318312 27.828001 11.091088 -18.289572 30.536110 9.010871 -19.854231 32.950993 10.131983 -19.325340 32.788654 11.492450 -18.200113 31.058996 14.381504 -16.614269 27.970646 18.450684 -14.759086 23.896099 23.209185 -12.858325 19.326809 28.083061 -11.141247 14.813904 32.484451 -9.814956 10.901697 35.882484 -9.039422 8.062066 37.867306 -8.908187 6.637508 38.199516 -9.437078 6.799847 36.839050 -10.562305 8.529502 33.950001 -12.148148 11.617851 29.880821 -14.003330 15.692395 25.122324 -15.904091 20.261683 20.248447 -17.621170 24.774591 15.847056 -18.947460 28.686798 12.449022 -19.722996 31.526430 10.464197 -21.695261 33.624649 11.411049 -21.387285 33.377014 12.825539 -20.633663 31.473660 15.726190 -19.525293 28.144165 19.763145 -18.195864 23.790112 24.449486 -16.805721 18.936663 29.219971 -15.522538 14.169223 33.499207 -14.501086 10.062808 36.771061 -13.864566 7.112714 38.640892 -13.689752 5.674768 38.883175 -13.997728 5.922405 37.468689 -14.751350 7.825756 34.568039 -15.859718 11.155250 30.531084 -17.189148 15.509302 25.844746 -18.579290 20.362745 21.074261 -19.862473 25.130188 16.795023 -20.883926 29.236605 13.523170 -21.520447 32.186699 11.653335 -24.026447 33.835518 12.205972 -23.963617 33.498672 13.634096 -23.577234 31.432579 16.495293 -22.913900 27.886442 20.444462 -22.053625 23.287975 25.005274 -21.100168 18.191826 29.627626 -20.168533 13.212664 33.753994 -19.371088 8.951046 36.886681 -18.804016 5.920990 38.647835 -18.535715 4.487964 38.825039 -18.598543 4.824809 37.396915 -18.984926 6.890901 34.535721 -19.648260 10.437036 30.586552 -20.508535 15.035500 26.025743 -21.461990 20.131647 21.403393 -22.393625 25.110811 17.277021 -23.191071 29.372429 14.144332 -23.758144 32.402489 12.383176 -26.832588 33.478985 12.268130 -27.018400 33.045296 13.658937 -26.971630 30.824566 16.428532 -26.697916 27.084644 20.242859 -26.230274 22.276623 24.641857 -25.625111 16.980415 29.094940 -24.955414 11.834829 33.064999 -24.301962 7.460494 36.073189 -23.743568 4.385019 37.756680 -23.347584 2.979355 37.912411 -23.161772 3.413041 36.521606 -23.208542 5.633770 33.752014 -23.482256 9.373690 29.937691 -23.949896 14.181709 25.538692 -24.555061 19.477915 21.085609 -25.224756 24.623503 17.115549 -25.878210 28.997837 14.107357 -26.436604 32.073315 12.423864 -30.010406 32.454086 11.343650 -30.419472 31.916586 12.647762 -30.657906 29.549295 15.282829 -30.696951 25.637747 18.931019 -30.531897 20.653732 23.152311 -30.182652 15.198393 27.437553 -29.691338 9.929729 31.269878 -29.117220 5.483217 34.187057 -28.529539 2.395170 35.837231 -27.999184 1.038053 36.021366 -27.590118 1.575553 34.717255 -27.351685 3.942840 32.082191 -27.312639 7.854385 28.434002 -27.477694 12.838398 24.212711 -27.826939 18.293734 19.927471 -28.318251 23.562399 16.095142 -28.892370 28.008915 13.177964 -29.480049 31.096966 11.527786 -33.352669 30.678276 9.216960 -33.937302 30.035671 10.401112 -34.389343 27.533775 12.879146 -34.654270 23.474354 16.352175 -34.700127 18.347031 20.401302 -34.521389 12.770241 24.538141 -34.139606 7.416628 28.263727 -33.600834 2.931913 31.128700 -32.970051 -0.142979 32.787506 -32.323341 -1.437171 33.040062 -31.738710 -0.794567 31.855911 -31.286669 1.707328 29.377880 -31.021742 5.766747 25.904852 -30.975882 10.894067 21.855726 -31.154623 16.470856 17.718889 -31.536404 21.824471 13.993301 -32.075176 26.309187 11.128325 -32.705959 29.384081 9.469519 -36.545738 28.120682 5.778054 -37.253601 27.377062 6.828250 -37.849785 24.755064 9.146475 -38.262383 20.570940 12.453121 -38.441624 15.329357 16.349354 -38.365894 9.662528 20.365232 -38.044327 4.253957 24.016380 -37.515709 -0.244003 26.862417 -36.843796 -3.288834 28.560070 -36.109634 -4.513282 28.904575 -35.401772 -3.769663 27.854380 -34.805588 -1.147667 25.536156 -34.392990 3.036455 22.229511 -34.213749 8.278036 18.333281 -34.289478 13.944863 14.317403 -34.611042 19.353436 10.666254 -35.139664 23.851398 7.820213 -35.811573 26.896233 6.122561 -39.222378 24.823700 1.068924 -40.007587 23.985973 1.984686 -40.690434 21.259136 4.153223 -41.188560 16.972080 7.312979 -41.441887 11.641890 11.082840 -41.419853 5.911463 15.008104 -41.125122 0.471978 18.615328 -40.593239 -4.020487 21.469425 -39.888359 -7.024075 23.226152 -39.095501 -8.176507 23.673620 -38.310291 -7.338783 22.757858 -37.627445 -4.611948 20.589323 -37.129318 -0.324894 17.429569 -36.875992 5.005294 13.659710 -36.898026 10.735719 9.734447 -37.192757 16.175205 6.127223 -37.724640 20.667673 3.273123 -38.429520 23.671263 1.516395 -41.024509 20.920063 -4.690040 -41.850349 19.995888 -3.902109 -42.575745 17.179909 -1.865312 -43.113197 12.811773 1.174684 -43.397884 7.418344 4.851209 -43.395470 1.650150 8.720821 -43.106243 -3.797080 12.316786 -42.565090 -8.266330 15.205379 -41.837280 -11.218544 17.038193 -41.010601 -12.297641 17.594162 -40.184761 -11.373466 16.806232 -39.459366 -8.557488 14.769436 -38.921913 -4.189356 11.729443 -38.637226 1.204070 8.052918 -38.639641 6.972263 4.183308 -38.928867 12.419495 0.587342 -39.470020 16.888748 -2.301252 -40.197826 19.840965 -4.134069 -41.666664 16.641092 -11.093895 -42.504612 15.637047 -10.425549 -43.241493 12.746952 -8.499712 -43.788425 8.319397 -5.548672 -44.079441 2.888407 -1.928364 -44.079441 -2.890957 1.924546 -43.788425 -8.321618 5.545341 -43.241493 -12.748560 8.497301 -42.504612 -15.637829 10.424376 -41.666664 -16.640936 11.094130 -40.828716 -15.636891 10.425785 -40.091835 -12.746799 8.499950 -39.544903 -8.319245 5.548911 -39.253887 -2.888258 1.928605 -39.253887 2.891104 -1.924304 -39.544903 8.321766 -5.545100 -40.091835 12.748712 -8.497062 -40.828712 15.637983 -10.424138 -41.008617 12.291817 -17.602840 -41.835110 11.212072 -17.047848 -42.563000 8.260010 -15.214821 -43.104492 3.791691 -12.324849 -43.394272 -1.653940 -8.726503 -43.397392 -7.420060 -4.853800 -43.113476 -12.811186 -1.173844 -42.576763 -17.177073 1.869508 -41.851994 -19.991129 3.909184 -41.026585 -20.913937 4.699168 -40.200092 -19.834194 4.144178 -39.472202 -16.882135 2.311153 -38.930710 -12.413818 -0.578818 -38.640930 -6.968189 -4.177162 -38.637810 -1.202071 -8.049865 -38.921726 4.189056 -11.729820 -39.458439 8.554945 -14.773175 -40.183208 11.369003 -16.812855 -39.094440 8.174933 -23.675909 -39.886745 7.021627 -23.229719 -40.591282 4.017478 -21.473816 -41.123062 -0.475172 -18.619987 -41.417953 -5.914441 -15.012447 -41.440388 -11.644274 -11.086319 -41.187653 -16.973568 -7.315153 -40.690235 -21.259529 -4.153804 -40.008133 -23.985210 -1.983580 -39.223618 -24.821854 -1.066240 -38.431309 -23.668550 -1.512430 -37.726776 -20.664402 -3.268332 -37.194992 -16.171755 -6.122159 -36.900101 -10.732488 -9.729696 -36.877666 -5.002656 -13.655824 -37.130402 0.326637 -17.426991 -37.627819 4.612602 -20.588341 -38.309921 7.338286 -22.758568 -36.111965 4.515631 -28.901302 -36.845135 3.290203 -28.558167 -37.515903 0.244243 -26.862093 -38.043373 -4.254866 -24.017653 -38.363918 -9.664461 -20.367928 -38.438881 -15.332067 -16.353130 -38.259212 -20.574085 -12.457505 -37.846592 -24.758251 -9.150919 -37.250782 -27.379894 -6.832195 -36.543644 -28.122805 -5.781009 -35.810478 -26.897379 -6.124145 -35.139706 -23.851419 -7.820217 -34.612236 -19.352314 -10.664656 -34.291691 -13.942720 -14.314378 -34.216728 -8.275117 -18.329174 -34.396397 -3.033098 -22.224800 -34.809017 1.151071 -25.531387 -35.404827 3.772717 -27.850113 -32.318867 1.433651 -33.044613 -32.964359 0.138659 -32.793037 -33.594624 -2.936500 -31.134533 -34.133644 -7.420919 -28.269140 -34.516411 -12.773711 -24.542469 -34.696751 -18.349247 -20.404011 -34.652916 -23.475037 -16.352926 -34.390190 -27.532833 -12.877834 -33.940266 -30.033211 -10.397881 -33.357410 -30.674580 -9.212185 -32.711922 -29.379591 -9.463761 -32.081654 -26.304432 -11.122264 -31.542633 -21.820015 -13.987654 -31.159866 -16.467226 -17.714321 -30.979527 -10.891691 -21.852779 -31.023361 -5.765901 -25.903864 -31.286085 -1.708100 -29.378960 -31.736010 0.792278 -31.858915 -27.984854 -1.047542 -36.032265 -28.513762 -2.405278 -35.848530 -29.101915 -5.492719 -34.197388 -29.678370 -9.937469 -31.277985 -30.173599 -15.203433 -27.442448 -30.527870 -20.655453 -23.153399 -30.698452 -25.635933 -18.928160 -30.664772 -29.544159 -15.276357 -30.430891 -31.908737 -12.638451 -30.025019 -32.444466 -11.332613 -29.496111 -31.086731 -11.516345 -28.907959 -27.999294 -13.167487 -28.331503 -23.554543 -16.086885 -27.836275 -18.288582 -19.922422 -27.482002 -12.836564 -24.211470 -27.311420 -7.856082 -28.436710 -27.345100 -3.947855 -32.088512 -27.578979 -1.583273 -34.726421 -23.337664 -2.985279 -37.918102 -23.731993 -4.391418 -37.762428 -24.290144 -7.466586 -36.078304 -24.944796 -11.839878 -33.068855 -25.616989 -16.983809 -29.097067 -26.225649 -22.277941 -24.641993 -26.697357 -27.083725 -20.240990 -26.975224 -30.821514 -16.424873 -27.025730 -33.040478 -13.653930 -26.842787 -33.472973 -12.262372 -26.448460 -32.066837 -12.418042 -25.890308 -28.991669 -14.102167 -25.235655 -24.618382 -17.111616 -24.563461 -19.474451 -21.083403 -23.954803 -14.180321 -25.538471 -23.483093 -9.374535 -29.939478 -23.205227 -5.636743 -33.755592 -23.154720 -3.417776 -36.526543 -18.529282 -4.491625 -38.827747 -18.796032 -5.924908 -38.650280 -19.362534 -8.954745 -36.888565 -20.160454 -13.215695 -33.755089 -21.093555 -18.193823 -29.627798 -22.049292 -23.288692 -25.004505 -22.912386 -27.885788 -20.442848 -23.578737 -31.430630 -16.493027 -23.967972 -33.495663 -13.631452 -24.033146 -33.831810 -12.203267 -23.766396 -32.398525 -12.380734 -23.199896 -29.368690 -14.142449 -22.401974 -25.107742 -17.275921 -21.468874 -20.129618 -21.403210 -20.513138 -15.034748 -26.026501 -19.650043 -10.437653 -30.588158 -18.983692 -6.892808 -34.537979 -18.594456 -4.827773 -37.399559 -13.674234 -5.683416 -38.887440 -13.848251 -7.121304 -38.644230 -14.485957 -10.070299 -36.773071 -15.510435 -14.174713 -33.499653 -16.798119 -18.939491 -29.218798 -18.193693 -23.789930 -24.446840 -19.528831 -28.140995 -19.759350 -20.642496 -31.467886 -15.721706 -21.400366 -33.369328 -12.820909 -21.711027 -33.615982 -11.406835 -21.537010 -32.178093 -11.650043 -20.899305 -29.229099 -13.521200 -19.874828 -25.124687 -16.794617 -18.587145 -20.359913 -21.075468 -17.191572 -15.509474 -25.847424 -15.856433 -11.158408 -30.534914 -14.742766 -7.831516 -34.572563 -13.984897 -5.930069 -37.473358 -8.886005 -6.650025 -38.202579 -9.017183 -8.074286 -37.869076 -9.795357 -10.912148 -35.882759 -11.126665 -14.821323 -32.483200 -12.850534 -19.330307 -28.080437 -14.759039 -23.895248 -23.205513 -16.621984 -27.965549 -18.446415 -18.214674 -31.050270 -14.377157 -19.345005 -32.777351 -11.488555 -19.876642 -32.938477 -10.129014 -19.745464 -31.514217 -10.462514 -18.967291 -28.676355 -12.448833 -17.635984 -24.767183 -15.848391 -15.912116 -20.258202 -20.251148 -14.003613 -15.693258 -25.126070 -12.140666 -11.622958 -29.885170 -10.547976 -8.538235 -33.954430 -9.417645 -6.811152 -36.843037 -4.283631 -7.440068 -36.869385 -4.419693 -8.838716 -36.442509 -5.393292 -11.545271 -34.361366 -7.086998 -15.233282 -30.876980 -9.296523 -19.457922 -26.409613 -11.755367 -23.709637 -21.498098 -14.166956 -27.475605 -16.734837 -16.240417 -30.301600 -12.694350 -17.725662 -31.846760 -9.863976 -18.443546 -31.924717 -8.585104 -18.307484 -30.526070 -9.011982 -17.333885 -27.819519 -11.093121 -15.640182 -24.131508 -14.577507 -13.430657 -19.906868 -19.044870 -10.971814 -15.655154 -23.956383 -8.560225 -11.889183 -28.719645 -6.486763 -9.063189 -32.760136 -5.001517 -7.518025 -35.590508 0.027319 -8.065935 -34.990990 -0.148672 -9.432594 -34.482834 -1.347672 -11.999549 -32.343296 -3.425063 -15.457182 -28.830425 -6.130281 -19.388454 -24.367931 -9.137037 -23.319197 -19.494057 -12.082671 -26.775301 -14.796663 -14.611897 -29.339912 -10.842324 -16.419653 -30.703701 -8.107989 -17.287897 -30.702173 -6.923464 -17.111906 -29.335514 -7.431616 -15.912908 -26.768564 -9.571154 -13.835518 -23.310930 -13.084021 -11.130301 -19.379660 -17.546513 -8.123546 -15.448918 -22.420385 -5.177912 -11.992813 -27.117781 -2.648685 -9.428199 -31.072123 -0.840927 -8.064408 -33.806458 3.946368 -8.500702 -32.687912 3.712630 -9.834018 -32.118183 2.288339 -12.267187 -29.960510 -0.154713 -15.506737 -26.475134 -3.321861 -19.161928 -22.082443 -6.831097 -22.791889 -17.312263 -10.259155 -25.958794 -12.739950 -13.192563 -28.280668 -8.916988 -15.277509 -29.477459 -6.304484 -16.262514 -29.404816 -5.217546 -16.028778 -28.071503 -5.787271 -14.604487 -25.638332 -7.944943 -12.161436 -22.398785 -11.430319 -8.994291 -18.743595 -15.823006 -5.485056 -15.113634 -20.593184 -2.056997 -11.946729 -25.165501 0.876412 -9.624851 -28.988462 2.961359 -8.428060 -31.600967 7.418983 -8.713822 -30.095341 7.124358 -10.016581 -29.484627 5.497993 -12.333862 -27.342285 2.736053 -15.386168 -23.926712 -0.828333 -18.805346 -19.649876 -4.765247 -22.178993 -15.027624 -8.599836 -25.100195 -10.617474 -11.869596 -27.216614 -6.951350 -14.180145 -28.272978 -4.471443 -15.252795 -28.141876 -3.476865 -14.958171 -26.839119 -4.087576 -13.331808 -24.521839 -6.229917 -10.569869 -21.469534 -9.645489 -7.005485 -18.050356 -13.922323 -3.068573 -14.676711 -18.544573 0.766017 -11.755508 -22.954723 4.035779 -9.639088 -26.620850 6.346329 -8.582720 -29.100760 10.464165 -8.705061 -27.330196 10.114002 -9.982301 -26.695377 8.317824 -12.206946 -24.590816 5.292278 -15.110674 -21.270355 1.402288 -18.343252 -17.134491 -2.882956 -21.514782 -12.682068 -7.046587 -24.242727 -8.450118 -10.586413 -26.198063 -4.949074 -13.075478 -27.144947 -2.601213 -14.213563 -26.969168 -1.689723 -13.863402 -25.691929 -2.324542 -12.067225 -23.467285 -4.429101 -9.041680 -20.563557 -7.749560 -5.151692 -17.330982 -11.885424 -0.866450 -14.159452 -16.337845 3.297182 -11.431505 -20.569796 6.837009 -9.476166 -24.070843 9.326077 -8.529282 -26.418705 13.100987 -8.474408 -24.500341 12.706738 -9.732691 -23.853622 10.779876 -11.891544 -21.796673 7.552810 -14.690580 -18.577595 3.414769 -17.792194 -14.584654 -1.135136 -20.822287 -10.299460 -5.548117 -23.415380 -6.238872 -9.291907 -25.258713 -2.892653 -11.914949 -26.129950 -0.664407 -13.100865 -25.924007 0.177105 -12.706617 -24.665726 -0.469614 -10.779757 -22.506872 -2.526561 -7.552692 -19.707838 -5.745637 -3.414654 -16.606224 -9.738576 1.135249 -13.576134 -14.023768 5.548232 -10.983039 -18.084358 9.292023 -9.139706 -21.430580 11.915068 -8.268467 -23.658827 15.382504 -8.049675 -21.681564 14.957470 -9.295266 -21.029799 12.937848 -11.412952 -19.019569 9.567238 -14.147306 -15.893339 5.252182 -17.168528 -12.028175 0.513141 -20.112209 -7.890277 -4.078285 -22.623301 -3.978737 -7.968304 -24.398930 -0.765340 -10.687723 -25.224926 1.362328 -11.908539 -25.001663 2.147639 -11.483505 -23.756073 1.495875 -9.463885 -21.638390 -0.514354 -6.093277 -18.904036 -3.640582 -1.778223 -15.882816 -7.505743 2.960816 -12.939134 -11.643640 7.552243 -10.428041 -15.555182 11.442265 -8.652412 -18.768578 14.161685 -7.826413 -20.896248 17.385042 -7.475095 -18.906979 16.940550 -8.712900 -18.253363 14.858434 -10.808224 -16.283871 11.389826 -13.508336 -13.236055 6.953092 -16.487564 -9.477525 2.083369 -19.386570 -5.461615 -2.631981 -21.855690 -1.672704 -6.624221 -23.597111 1.432210 -9.411827 -24.400793 3.478629 -10.658571 -24.169800 4.219724 -10.214080 -22.931995 3.566109 -8.131966 -20.836674 1.596620 -4.663360 -18.136562 -1.451195 -0.226629 -15.157335 -5.209723 4.643093 -12.258329 -9.225633 9.358444 -9.789209 -13.014544 13.350685 -8.047786 -16.119459 16.138294 -7.244102 -18.165880 19.158150 -6.785837 -16.209370 18.704475 -8.019260 -15.553780 16.586195 -10.105645 -13.613583 13.058803 -12.793343 -10.622793 8.547754 -15.758177 -6.942145 3.597149 -18.642542 -3.015581 -1.195894 -21.098545 0.683299 -5.253267 -22.829956 3.708355 -8.085590 -23.627937 5.694721 -9.351242 -23.396244 6.402812 -8.897570 -22.162821 5.747222 -6.779291 -20.076439 3.807026 -3.251901 -17.388742 0.816238 1.259145 -14.423910 -2.864408 6.209748 -11.539543 -6.790971 11.002793 -9.083540 -10.489851 15.060167 -7.352129 -13.514909 17.892492 -6.554144 -15.501278 20.760061 -6.018798 -13.595757 20.304962 -7.249469 -12.935997 18.170294 -9.334066 -11.011907 14.613524 -12.021154 -8.055561 10.063656 -14.986633 -4.423537 5.069468 -17.872820 -0.553913 0.233337 -20.331598 3.086577 -3.861432 -22.066404 6.058839 -6.720948 -22.867994 8.004372 -8.000312 -22.639687 8.688518 -7.545214 -21.409016 8.028757 -5.410546 -19.324419 6.104668 -1.853780 -16.637333 3.148324 2.696087 -13.671855 -0.483698 7.690272 -10.785668 -4.353321 12.526404 -8.326888 -7.993812 16.621176 -6.592081 -10.966076 19.480694 -5.790488 -12.911611 22.226334 -5.209805 -11.090048 21.776091 -6.437333 -10.421163 19.641642 -8.520535 -8.495318 16.080431 -11.208147 -5.544800 11.521996 -14.176003 -1.925483 6.516148 -17.066135 1.926089 1.666670 -19.529947 5.545358 -2.441523 -21.270275 8.495790 -5.312920 -22.077204 10.421515 -6.601189 -21.853407 11.090267 -6.150947 -20.625879 10.421383 -4.016499 -18.542679 8.495541 -0.455292 -15.855067 5.545024 4.103142 -12.887213 1.925708 9.108988 -9.997082 -1.925862 13.958467 -7.533267 -5.545132 18.066660 -5.792938 -8.495564 20.938061 -4.986008 -10.421294 23.602608 -4.396105 -8.697319 23.160948 -5.617902 -8.012411 21.037764 -7.692657 -6.065115 17.489147 -10.370127 -3.090303 12.943110 -13.327366 0.553219 7.947975 -16.207689 4.425987 3.106229 -18.663687 8.060886 -0.998144 -20.399130 11.019499 -3.870095 -21.204697 12.944969 -5.163224 -20.983227 13.605059 -4.721563 -19.761433 12.920151 -2.598382 -17.686676 10.972857 0.950234 -15.009209 7.998046 5.496267 -12.051970 4.354526 10.491401 -9.171647 0.481759 15.333148 -6.715649 -3.153142 19.437521 -4.980204 -6.111755 22.309475 -4.174634 -8.037229 24.939240 -3.596072 -6.397799 24.507111 -4.808125 -5.689882 22.399710 -6.862528 -3.704243 18.871216 -9.511492 -0.680380 14.347218 -12.435513 3.016986 9.373377 -15.281908 6.941896 4.549615 -17.707361 10.620949 0.457746 -19.419329 13.610395 -2.408690 -20.211319 15.549665 -3.703959 -19.987808 16.204857 -3.271833 -18.775757 15.496939 -1.164433 -16.721355 13.511301 2.364059 -14.072392 10.487440 6.888055 -11.148374 6.790076 11.861893 -8.301978 2.865167 16.685656 -5.876524 -0.813886 20.777527 -4.164556 -3.803335 23.643967 -3.372562 -5.742608 26.261982 -2.850945 -4.216131 25.838774 -4.046238 -3.475104 23.748959 -6.059001 -1.429149 20.244596 -8.646465 1.674964 15.748368 -11.496546 5.462831 10.802584 -14.265477 9.477579 6.003780 -16.619289 13.234970 1.930763 -18.274075 16.281807 -0.925205 -19.030245 18.250601 -2.219647 -18.796593 18.903879 -1.796440 -17.601301 18.162853 0.293375 -15.588539 16.116899 3.797734 -13.001075 13.012790 8.293961 -10.150997 9.224924 13.239743 -7.382064 5.210177 18.038548 -5.028252 1.452785 22.111567 -3.373464 -1.594055 24.967537 -2.617293 -3.562850 27.605679 -2.193420 -2.152020 27.188690 -3.361916 -1.366087 25.113804 -5.302958 0.762688 21.631283 -7.782429 3.977545 17.161171 -10.501268 7.890723 12.242628 -13.131542 12.030237 7.468906 -15.356001 15.896797 3.415785 -16.906343 19.024042 0.572130 -17.595575 21.034781 -0.719071 -17.340565 21.686485 -0.302083 -16.172070 20.900555 1.772802 -14.231030 18.771782 5.255321 -11.751559 15.556925 9.725431 -9.032722 11.643748 14.643971 -6.402448 7.504236 19.417694 -4.177988 3.637674 23.470818 -2.627643 0.510427 26.314474 -1.938409 -1.500313 29.000404 -1.633278 -0.187688 28.585657 -2.762295 0.655080 26.519623 -4.595368 2.885736 23.051495 -6.911403 6.235228 18.599581 -9.431051 10.299561 13.700848 -11.850405 14.588514 8.946158 -13.877656 18.584776 4.908994 -15.268287 21.806339 2.076298 -15.854568 23.864635 0.789735 -15.565784 24.511406 1.204482 -14.436769 23.668640 3.270515 -12.603696 21.437986 6.738642 -10.287663 18.088495 11.190553 -7.768015 14.024164 16.089283 -5.348661 9.735212 20.843975 -3.321410 5.738950 24.881140 -1.930777 2.517384 27.713839 -1.344495 0.459084 30.462685 -1.195012 1.680232 30.045706 -2.267265 2.593114 27.981033 -3.945923 4.943372 24.517694 -6.028515 8.447531 20.073420 -8.263847 12.682938 15.184255 -10.382310 17.138737 10.439906 -12.128382 21.277496 6.412611 -13.291462 24.600018 3.588120 -13.731266 26.705561 2.307110 -13.394747 27.340160 2.724087 -12.322495 26.427280 4.788759 -10.643837 24.077023 8.252095 -8.561246 20.572868 12.696368 -6.325912 16.337463 17.585531 -4.207451 11.881663 22.329880 -2.461379 7.742904 26.357178 -1.298297 4.420379 29.181671 -0.858492 2.314836 31.998245 -0.870819 3.473730 31.575459 -1.864607 4.469012 29.505331 -3.335670 6.949944 26.037552 -5.106576 10.617290 21.590384 -6.963727 15.028714 16.700226 -8.683125 19.652132 11.956902 -10.057382 23.929890 7.932524 -10.920744 27.346031 5.112494 -11.169079 29.488514 3.836948 -10.772430 30.098928 4.259735 -9.778643 29.103647 6.329860 -8.307581 26.622717 9.797638 -6.536675 22.955372 14.244802 -4.679524 18.543951 19.134960 -2.960128 13.920534 23.878284 -1.585870 9.642776 27.902664 -0.722506 6.226633 30.722696 -0.474171 4.084146 33.597076 -0.637621 5.213198 33.167408 -1.525524 6.301297 31.088375 -2.729152 8.915372 27.610741 -4.103328 12.740124 23.153957 -5.482308 17.314234 18.255583 -6.699765 22.085993 13.506431 -7.608857 26.479855 9.479321 -8.099933 29.965862 6.659979 -8.113762 32.123547 5.388460 -7.648678 32.692657 5.818129 -6.760775 31.604561 7.897161 -5.557147 28.990488 11.374793 -4.182971 25.165737 15.831573 -2.803992 20.591631 20.729948 -1.586535 15.819873 25.479099 -0.677442 11.426009 29.506212 -0.186366 7.940001 32.325558 -0.172535 5.782312 35.233276 -0.404113 6.920709 34.800407 -1.154746 8.106510 32.715355 -2.033595 10.842320 29.229607 -2.934659 14.798162 24.763596 -3.749254 19.496901 19.855991 -4.379130 24.371799 15.098722 -4.748313 28.834873 11.065583 -4.812276 32.347809 8.243032 -4.563303 34.486897 6.971508 -4.031423 34.994129 7.404377 -3.280790 33.808327 9.489429 -2.401941 31.072519 12.975174 -1.500878 27.116680 17.441181 -0.686283 22.417942 22.348785 -0.056407 17.543045 27.106056 0.312777 13.079971 31.139196 0.376740 9.567034 33.961750 0.127767 7.427943</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="2160" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="6480">0.702468 -0.051924 -0.709819 0.702703 -0.174813 -0.689673 0.528767 -0.838433 0.132044 0.457857 -0.888266 -0.036750 0.465074 -0.806655 0.364711 0.402213 -0.893235 0.200886 0.494332 -0.719774 0.487403 0.447862 -0.823879 0.347336 0.526211 -0.624117 0.577563 0.495111 -0.734847 0.463535 0.542598 -0.536859 0.646042 0.522605 -0.648555 0.553408 0.537460 -0.464725 0.703681 0.524503 -0.576743 0.626309 0.495642 -0.405822 0.767885 0.487047 -0.521240 0.700781 0.296662 -0.329655 0.896281 0.291429 -0.458824 0.839374 -0.685334 0.082828 0.723503 -0.687524 -0.008769 0.726108 -0.853297 0.387592 -0.348792 -0.844983 0.447790 -0.292385 -0.718085 0.413283 -0.559957 -0.707776 0.504482 -0.494521 -0.648732 0.456739 -0.608717 -0.634762 0.559463 -0.532990 -0.579513 0.529628 -0.619402 -0.558681 0.640132 -0.527357 -0.489018 0.629787 -0.603514 -0.457023 0.743785 -0.487765 -0.368355 0.738376 -0.564903 -0.322026 0.848224 -0.420494 -0.223134 0.817961 -0.530236 -0.164841 0.918149 -0.360319 0.007024 0.797103 -0.603803 0.063904 0.902507 -0.425907 0.719288 -0.267931 -0.640966 0.646973 -0.699042 0.304576 0.565325 -0.637502 0.523449 0.567381 -0.548489 0.614198 0.576587 -0.461000 0.674556 0.577208 -0.384133 0.720606 0.561973 -0.319772 0.762844 0.513709 -0.263310 0.816560 0.309801 -0.179607 0.933684 -0.680412 0.168376 0.713224 -0.868654 0.303995 -0.391186 -0.736533 0.296524 -0.607942 -0.672427 0.323794 -0.665582 -0.613654 0.379825 -0.692215 -0.541562 0.461701 -0.702526 -0.447227 0.555539 -0.700974 -0.327140 0.628446 -0.705716 -0.097436 0.597342 -0.796045 0.743876 -0.310727 -0.591690 0.775189 -0.469050 0.423172 0.674194 -0.390544 0.626848 0.649194 -0.316541 0.691627 0.636591 -0.249446 0.729746 0.621782 -0.190952 0.759556 0.596187 -0.140013 0.790543 0.540944 -0.090734 0.836150 0.331457 -0.006845 0.943445 -0.674076 0.244225 0.697120 -0.890942 0.191609 -0.411714 -0.762607 0.150353 -0.629146 -0.704233 0.158768 -0.691989 -0.656689 0.191653 -0.729403 -0.604170 0.243447 -0.758757 -0.538144 0.303704 -0.786235 -0.446485 0.347880 -0.824397 -0.219080 0.300351 -0.928328 0.756679 -0.323331 -0.568238 0.871435 -0.197997 0.448775 0.758549 -0.108543 0.642513 0.716307 -0.054698 0.695638 0.689394 -0.009995 0.724318 0.663898 0.029360 0.747247 0.630643 0.065987 0.773263 0.569912 0.106255 0.814807 0.355710 0.184280 0.916249 -0.668420 0.308914 0.676599 -0.914893 0.051485 -0.400399 -0.789978 -0.022179 -0.612733 -0.736157 -0.032069 -0.676050 -0.697093 -0.022619 -0.716624 -0.658512 -0.002350 -0.752566 -0.611658 0.020445 -0.790858 -0.538892 0.029591 -0.841855 -0.313476 -0.030890 -0.949094 0.756039 -0.335533 -0.561981 0.918824 0.051341 0.391313 0.801471 0.154732 0.577670 0.752326 0.195815 0.629017 0.719301 0.225438 0.657103 0.688885 0.251381 0.679886 0.651834 0.277453 0.705784 0.588189 0.310319 0.746817 0.371261 0.379698 0.847345 -0.666315 0.361664 0.652091 -0.930756 -0.104765 -0.350312 -0.807609 -0.207036 -0.552181 -0.756042 -0.231367 -0.612266 -0.720997 -0.239436 -0.650257 -0.688534 -0.241654 -0.683757 -0.649407 -0.244550 -0.720046 -0.583732 -0.258590 -0.769668 -0.358914 -0.322207 -0.875993 0.751201 -0.351270 -0.558843 0.925136 0.249068 0.286512 0.805544 0.369010 0.463605 0.754637 0.406302 0.515211 0.720109 0.429560 0.544905 0.688429 0.449222 0.569443 0.650339 0.469983 0.596804 0.585848 0.498664 0.638840 0.368316 0.559587 0.742432 -0.669227 0.401309 0.625369 -0.929514 -0.257607 -0.263898 -0.805801 -0.382666 -0.451942 -0.754479 -0.416125 -0.507545 -0.720173 -0.433801 -0.541449 -0.688880 -0.447223 -0.570471 -0.651157 -0.461945 -0.602164 -0.586676 -0.485817 -0.647914 -0.362292 -0.545919 -0.755459 0.747396 -0.365165 -0.555026 0.903671 0.395821 0.163416 0.781048 0.530727 0.329079 0.729564 0.568796 0.379746 0.694851 0.590823 0.410013 0.663105 0.608816 0.435472 0.624994 0.627955 0.463740 0.560556 0.654988 0.506722 0.344039 0.708865 0.615750 -0.676275 0.427571 0.599862 -0.907992 -0.390106 -0.152865 -0.781638 -0.531634 -0.326202 -0.729639 -0.569886 -0.377964 -0.694898 -0.591498 -0.408958 -0.663248 -0.608904 -0.435131 -0.625230 -0.627440 -0.464119 -0.560576 -0.654046 -0.507915 -0.337463 -0.708443 -0.619860 0.745236 -0.374184 -0.551914 0.863711 0.502691 0.036129 0.736827 0.648872 0.189869 0.684650 0.688692 0.238657 0.649748 0.711178 0.268427 0.617973 0.729236 0.293810 0.579922 0.748245 0.322211 0.515736 0.774726 0.365809 0.301470 0.822894 0.481624 -0.684844 0.442568 0.578897 -0.868394 -0.494944 -0.030360 -0.737988 -0.647567 -0.189816 -0.685150 -0.688139 -0.238817 -0.649937 -0.711046 -0.268321 -0.617925 -0.729461 -0.293351 -0.579636 -0.748792 -0.321454 -0.514940 -0.775614 -0.365048 -0.294213 -0.824338 -0.483638 0.743683 -0.377993 -0.551413 0.809724 0.579699 -0.091085 0.677763 0.733478 0.051445 0.624716 0.774643 0.098274 0.589491 0.797687 0.127265 0.557577 0.816042 0.152262 0.519528 0.835154 0.180576 0.455692 0.861277 0.224828 0.244883 0.904772 0.348453 -0.692487 0.449871 0.563983 -0.814126 -0.572777 0.095526 -0.678809 -0.732504 -0.051540 -0.625185 -0.774228 -0.098561 -0.589675 -0.797537 -0.127355 -0.557524 -0.816112 -0.152079 -0.519214 -0.835438 -0.180165 -0.454803 -0.861838 -0.224478 -0.237600 -0.905642 -0.351225 0.741172 -0.377615 -0.555042 0.742673 0.632949 -0.218659 0.605235 0.791368 -0.086181 0.551347 0.833272 -0.040906 0.515848 0.856590 -0.012451 0.483859 0.875059 0.012367 0.445921 0.894140 0.040831 0.382697 0.919851 0.086122 0.176792 0.959661 0.218622 -0.697588 0.453033 0.555097 -0.746826 -0.626732 0.222391 -0.606076 -0.790725 0.086171 -0.551712 -0.833043 0.040667 -0.515994 -0.856504 0.012293 -0.483813 -0.875084 -0.012383 -0.445629 -0.894290 -0.040746 -0.381788 -0.920219 -0.086230 -0.169378 -0.960122 -0.222432 0.735885 -0.374769 -0.563934 0.661071 0.664470 -0.348519 0.517989 0.825289 -0.224911 0.463441 0.867514 -0.180670 0.427864 0.890909 -0.152357 0.396018 0.909369 -0.127350 0.358463 0.928350 -0.098339 0.296307 0.953704 -0.051485 0.097164 0.991093 0.091072 -0.699164 0.455026 0.551472 -0.665559 -0.658576 0.351153 -0.519036 -0.824773 0.224390 -0.463977 -0.867353 0.180065 -0.428086 -0.890868 0.151979 -0.395916 -0.909425 0.127266 -0.357959 -0.928528 0.098495 -0.294993 -0.954111 0.051502 -0.088988 -0.991440 -0.095541 0.725740 -0.371787 -0.578857 0.561831 0.672520 -0.481729 0.412974 0.833995 -0.365930 0.357945 0.876342 -0.322336 0.322464 0.899791 -0.293925 0.290956 0.918281 -0.268521 0.254059 0.937266 -0.238718 0.193518 0.962545 -0.189891 0.003503 0.999342 -0.036112 -0.696636 0.458277 0.551979 -0.566891 -0.666966 0.483519 -0.414347 -0.833758 0.364916 -0.358775 -0.876376 0.321318 -0.322879 -0.899870 0.293227 -0.290903 -0.918385 0.268226 -0.253426 -0.937427 0.238760 -0.191836 -0.962899 0.189801 0.005571 -0.999523 0.030373 0.708463 -0.371853 -0.599838 0.441736 0.652342 -0.615889 0.286807 0.812909 -0.506873 0.231176 0.855197 -0.463892 0.195561 0.878636 -0.435609 0.164135 0.897141 -0.410120 0.127746 0.916202 -0.379809 0.069089 0.941768 -0.329089 -0.109014 0.980523 -0.163374 -0.689895 0.464662 0.555098 -0.444967 -0.646522 0.619688 -0.286320 -0.812548 0.507726 -0.230950 -0.855237 0.463931 -0.195866 -0.878886 0.434966 -0.164925 -0.897581 0.408837 -0.128784 -0.916847 0.377897 -0.069600 -0.942738 0.326191 0.116184 -0.981390 0.152889 0.682183 -0.378867 -0.625369 0.300267 0.598703 -0.742559 0.138720 0.756612 -0.638979 0.081627 0.798116 -0.596949 0.044611 0.820726 -0.569577 0.011772 0.838344 -0.545014 -0.025586 0.856640 -0.515280 -0.083273 0.882112 -0.463620 -0.246884 0.925734 -0.286469 -0.679765 0.474906 0.558914 -0.291848 -0.586840 0.755277 -0.127631 -0.751128 0.647701 -0.074725 -0.795038 0.601939 -0.043090 -0.820331 0.570264 -0.015766 -0.840691 0.541285 0.016764 -0.861525 0.507438 0.071474 -0.889203 0.451895 0.241686 -0.933782 0.263891 0.646349 -0.396137 -0.652157 0.142944 0.511317 -0.847421 -0.025622 0.664453 -0.746891 -0.085928 0.703116 -0.705864 -0.127039 0.722159 -0.679962 -0.164704 0.735535 -0.657162 -0.206840 0.749346 -0.629045 -0.266942 0.771402 -0.577651 -0.415101 0.821362 -0.391223 -0.668568 0.486905 0.562086 -0.099784 -0.472153 0.875851 0.067693 -0.635087 0.769469 0.112653 -0.684966 0.719813 0.134732 -0.717386 0.683524 0.152933 -0.744340 0.650053 0.177519 -0.770590 0.612110 0.224453 -0.803013 0.552079 0.374648 -0.858467 0.350248 0.601618 -0.424326 -0.676759 -0.018609 0.400185 -0.916245 -0.193274 0.546620 -0.814771 -0.258534 0.579043 -0.773220 -0.306901 0.589506 -0.747191 -0.353745 0.591899 -0.724237 -0.405919 0.592859 -0.695520 -0.473661 0.602534 -0.642338 -0.607527 0.655565 -0.448493 -0.658315 0.493436 0.568456 0.129886 -0.287218 0.949018 0.294960 -0.452288 0.841685 0.323346 -0.519942 0.790638 0.327007 -0.571900 0.752328 0.328777 -0.615370 0.716398 0.340192 -0.653825 0.675856 0.375739 -0.695390 0.612579 0.502020 -0.766653 0.400274 0.548271 -0.461602 -0.697368 -0.172104 0.283698 -0.943343 -0.349439 0.423117 -0.835981 -0.419745 0.446280 -0.790347 -0.476681 0.442948 -0.759324 -0.534775 0.426499 -0.729461 -0.599222 0.403836 -0.691267 -0.675840 0.388448 -0.626377 -0.794271 0.436587 -0.422522 -0.640915 0.488482 0.592126 0.369780 -0.039818 0.928266 0.524649 -0.213155 0.824202 0.532093 -0.314757 0.786006 0.512842 -0.402067 0.758509 0.494242 -0.473350 0.729153 0.489574 -0.530840 0.691756 0.511515 -0.585483 0.628937 0.611395 -0.675902 0.411525 0.485576 -0.505056 -0.713536 -0.311007 0.178629 -0.933470 -0.485324 0.313332 -0.816262 -0.558333 0.326883 -0.762503 -0.621696 0.307889 -0.720208 -0.687980 0.268905 -0.674072 -0.759178 0.217159 -0.613588 -0.835252 0.170826 -0.522659 -0.929239 0.210682 -0.303527 -0.591164 0.488598 0.641714 0.566330 0.213962 0.795921 0.708137 0.030396 0.705421 0.704914 -0.110201 0.700680 0.670717 -0.238792 0.702223 0.635831 -0.342031 0.691906 0.616707 -0.420799 0.665282 0.625152 -0.489831 0.607660 0.697608 -0.600435 0.390923 0.413799 -0.552146 -0.723813 -0.434481 0.092215 -0.895948 -0.599758 0.226452 -0.767469 -0.671621 0.233246 -0.703223 -0.736629 0.201679 -0.645526 -0.803986 0.143921 -0.576969 -0.870876 0.068551 -0.486699 -0.931456 -0.000168 -0.363853 -0.990619 0.039113 -0.130938 -0.501804 0.521028 0.690451 0.687159 0.404005 0.603815 0.820310 0.214942 0.529992 0.823893 0.049349 0.564593 0.790109 -0.109300 0.603143 0.748608 -0.237540 0.618999 0.720113 -0.333752 0.608315 0.717151 -0.415421 0.559571 0.762393 -0.545306 0.348422 0.335555 -0.599960 -0.726258 -0.543665 0.023164 -0.838982 -0.695342 0.161401 -0.700321 -0.762078 0.166132 -0.625809 -0.823296 0.128635 -0.552844 -0.884276 0.061723 -0.462867 -0.937747 -0.023699 -0.346509 -0.974919 -0.097924 -0.199860 -0.998159 -0.047302 0.037967 -0.395553 0.581823 0.710647 0.750094 0.506165 0.425623 0.877990 0.315655 0.359854 0.895928 0.144469 0.420049 0.872878 -0.024583 0.487318 0.833897 -0.164279 0.526905 0.802065 -0.270345 0.532547 0.790932 -0.360960 0.494099 0.810302 -0.508080 0.292002 0.256002 -0.645766 -0.719339 -0.639093 -0.033763 -0.768388 -0.774848 0.111891 -0.622166 -0.833226 0.119423 -0.539882 -0.886119 0.083635 -0.455850 -0.935796 0.018941 -0.352034 -0.973129 -0.061619 -0.221861 -0.989805 -0.125967 -0.066471 -0.984339 -0.055211 0.167419 -0.293106 0.647913 0.703063 0.788702 0.537328 0.298711 0.909950 0.345110 0.229977 0.937725 0.181402 0.296252 0.926619 0.019214 0.375509 0.895413 -0.118168 0.429268 0.865469 -0.225776 0.447201 0.849820 -0.321024 0.418031 0.845808 -0.482816 0.226929 0.181675 -0.687559 -0.703034 -0.720004 -0.083281 -0.688955 -0.839658 0.071733 -0.538358 -0.887764 0.085897 -0.452213 -0.929723 0.058102 -0.363648 -0.966556 0.004789 -0.256411 -0.990165 -0.059888 -0.126435 -0.994225 -0.104583 0.024048 -0.968663 -0.009083 0.248212 -0.203481 0.702891 0.681572 0.821788 0.523442 0.225108 0.933258 0.328009 0.146421 0.962605 0.178297 0.203965 0.959544 0.033525 0.279555 0.937402 -0.091707 0.335958 0.912674 -0.194123 0.359642 0.895766 -0.290079 0.336834 0.871858 -0.463804 0.157322 0.117842 -0.723954 -0.679709 -0.785506 -0.128071 -0.605457 -0.890451 0.036891 -0.453582 -0.927916 0.060027 -0.367926 -0.958522 0.044057 -0.281593 -0.983569 0.007285 -0.180385 -0.997460 -0.035935 -0.061494 -0.995590 -0.056513 0.074876 -0.956160 0.064885 0.285567 -0.129724 0.743202 0.656371 0.852753 0.485438 0.192774 0.952623 0.286747 0.101414 0.977843 0.153892 0.141918 0.978589 0.030881 0.203496 0.964365 -0.077326 0.253024 0.946024 -0.170388 0.275694 0.930063 -0.264085 0.255427 0.890266 -0.447070 0.086917 0.067498 -0.754457 -0.652869 -0.835601 -0.169481 -0.522539 -0.928229 0.005001 -0.371976 -0.956057 0.038060 -0.290701 -0.976613 0.035405 -0.212069 -0.992209 0.016713 -0.123455 -0.999748 -0.003965 -0.022107 -0.995468 -0.000022 0.095099 -0.945951 0.145476 0.289851 -0.073835 0.771197 0.632300 0.878823 0.438462 0.188205 0.967666 0.237775 0.084175 0.987000 0.122351 0.104214 0.988966 0.021259 0.146611 0.980666 -0.068888 0.183163 0.968246 -0.150795 0.199403 0.954242 -0.240318 0.177961 0.902563 -0.430138 0.019033 0.031864 -0.779357 -0.625770 -0.871151 -0.207467 -0.445032 -0.954390 -0.024573 -0.297550 -0.974588 0.018125 -0.223269 -0.987436 0.028292 -0.155465 -0.996257 0.026383 -0.082315 -0.999664 0.025906 -0.000390 -0.993992 0.051315 0.096677 -0.936808 0.216427 0.274864 -0.037127 0.790563 0.611254 0.897351 0.394618 0.197579 0.977676 0.193083 0.082877 0.992165 0.093295 0.083094 0.994340 0.011349 0.105639 0.989952 -0.062421 0.126883 0.982024 -0.133326 0.133612 0.969962 -0.217816 0.108307 0.910019 -0.412351 -0.042814 0.008587 -0.798732 -0.601626 -0.894445 -0.241603 -0.376293 -0.971133 -0.051845 -0.232837 -0.985999 -0.000582 -0.166750 -0.993632 0.020795 -0.110737 -0.998044 0.033001 -0.053098 -0.998749 0.048873 0.010614 -0.991814 0.091134 0.089445 -0.928903 0.270747 0.252657 -0.014119 0.805487 0.592446 0.908693 0.360244 0.210952 0.983370 0.158646 0.088407 0.994863 0.071400 0.071761 0.997060 0.004651 0.076486 0.995015 -0.055628 0.082773 0.990004 -0.116813 0.079038 0.979358 -0.196243 0.048432 0.914046 -0.393901 -0.096758 -0.003527 -0.813327 -0.581797 -0.908078 -0.271628 -0.318766 -0.980799 -0.076648 -0.179326 -0.992459 -0.018384 -0.121191 -0.997030 0.011993 -0.076079 -0.998872 0.035110 -0.031974 -0.997868 0.063115 0.016636 -0.989791 0.117414 0.080789 -0.923110 0.306833 0.231779 -0.003531 0.816743 0.576991 0.914529 0.337743 0.222636 0.986133 0.136189 0.094835 0.996181 0.058025 0.065246 0.998451 0.002407 0.055590 0.997664 -0.047585 0.049013 0.994261 -0.100897 0.035556 0.984425 -0.175805 -0.000554 0.916034 -0.375340 -0.141426 -0.008185 -0.823381 -0.567429 -0.914907 -0.296555 -0.273862 -0.985606 -0.098080 -0.137703 -0.995682 -0.034701 -0.086094 -0.998768 0.002138 -0.049586 -0.999339 0.032800 -0.015662 -0.997383 0.068843 0.022094 -0.988489 0.130806 0.076020 -0.919680 0.326395 0.218298 0.000075 0.824973 0.565172 0.917033 0.326891 0.228457 0.987305 0.125375 0.097522 0.996834 0.052983 0.059282 0.999208 0.004631 0.039517 0.998991 -0.038345 0.023386 0.996294 -0.085986 0.002268 0.986787 -0.157385 -0.038491 0.916907 -0.358021 -0.176362 -0.007643 -0.829337 -0.558697 -0.917505 -0.315910 -0.241630 -0.987480 -0.115569 -0.107361 -0.996989 -0.049039 -0.060064 -0.999542 -0.008264 -0.029111 -0.999638 0.026845 -0.001525 -0.997280 0.067450 0.029720 -0.987985 0.133622 0.077657 -0.918305 0.332730 0.214494 -0.001148 0.829930 0.557866 0.917756 0.325481 0.227566 0.987757 0.123979 0.094685 0.997173 0.054715 0.051506 0.999614 0.010438 0.025754 0.999589 -0.028434 0.003710 0.997111 -0.072594 -0.022364 0.987690 -0.141703 -0.066253 0.917381 -0.342897 -0.202075 -0.004478 -0.831450 -0.555581 -0.918042 -0.328476 -0.222039 -0.987902 -0.127892 -0.087707 -0.997301 -0.060353 -0.041806 -0.999752 -0.018280 -0.012726 -0.999752 0.018281 0.012735 -0.997301 0.060354 0.041814 -0.987902 0.127893 0.087712 -0.918043 0.328473 0.222040 -0.004530 0.831447 0.555586 0.917701 0.331506 0.218927 0.987888 0.130067 0.084614 0.997299 0.061758 0.039748 0.999752 0.018764 0.012012 0.999752 -0.018773 -0.012008 0.997299 -0.061766 -0.039743 0.987888 -0.130075 -0.084608 0.917702 -0.331508 -0.218918 -0.001112 -0.829937 -0.557856 -0.918312 -0.332626 -0.214622 -0.987989 -0.133528 -0.077763 -0.997282 -0.067384 -0.029783 -0.999639 -0.026815 0.001514 -0.999541 0.008258 0.029152 -0.996986 0.049001 0.060152 -0.987475 0.115506 0.107484 -0.917497 0.315834 0.241762 -0.007668 0.829332 0.558704 0.917382 0.342968 0.201949 0.987689 0.141760 0.066138 0.997110 0.072625 0.022284 0.999589 0.028432 -0.003740 0.999614 -0.010476 -0.025730 0.997173 -0.054790 -0.051429 0.987756 -0.124081 -0.094562 0.917754 -0.325588 -0.227420 0.000088 -0.824993 -0.565143 -0.919707 -0.326145 -0.218557 -0.988502 -0.130581 -0.076234 -0.997391 -0.068685 -0.022215 -0.999342 -0.032719 0.015649 -0.998763 -0.002132 0.049676 -0.995669 0.034644 0.086274 -0.985582 0.097974 0.137947 -0.914871 0.296424 0.274125 -0.008176 0.823368 0.567450 0.916909 0.358141 0.176106 0.986780 0.157484 0.038252 0.996289 0.086037 -0.002440 0.998990 0.038329 -0.023465 0.999209 -0.004724 -0.039486 0.996834 -0.053155 -0.059138 0.987299 -0.125611 -0.097279 0.917018 -0.327141 -0.228161 -0.003605 -0.816786 -0.576930 -0.923164 -0.306389 -0.232150 -0.989813 -0.117020 -0.081093 -0.997883 -0.062834 -0.016796 -0.998877 -0.034954 0.031976 -0.997018 -0.011953 0.076232 -0.992426 0.018329 0.121468 -0.980743 0.076522 0.179690 -0.907990 0.271467 0.319155 -0.003439 0.813303 0.581830 0.916035 0.375482 0.141044 0.984404 0.175922 0.000191 0.994246 0.100946 -0.035830 0.997659 0.047535 -0.049157 0.998451 -0.002578 -0.055572 0.996176 -0.058324 -0.065054 0.986111 -0.136595 -0.094484 0.914478 -0.338174 -0.222191 -0.014262 -0.805580 -0.592316 -0.928976 -0.270039 -0.253145 -0.991835 -0.090510 -0.089839 -0.998768 -0.048429 -0.010802 -0.998050 -0.032746 0.053134 -0.993608 -0.020708 0.110972 -0.985933 0.000536 0.167141 -0.971022 0.051704 0.233330 -0.894278 0.241412 0.376811 0.008750 0.798689 0.601680 0.914033 0.394056 0.096249 0.979309 0.196370 -0.048925 0.989969 0.116849 -0.079425 0.995002 0.055526 -0.082996 0.997058 -0.004929 -0.076494 0.994846 -0.071872 -0.071522 0.983309 -0.159282 -0.087931 0.908575 -0.360914 -0.210315 -0.037476 -0.790706 -0.611049 -0.936886 -0.215385 -0.275416 -0.993995 -0.050414 -0.097119 -0.999681 -0.025265 0.000208 -0.996259 -0.026004 0.082412 -0.987388 -0.028138 0.155799 -0.974471 -0.018144 0.223778 -0.954201 0.024434 0.298168 -0.870872 0.207263 0.445672 0.032165 0.779297 0.625829 0.909980 0.412502 0.042169 0.969863 0.217941 -0.108940 0.981952 0.133340 -0.134131 0.989920 0.062254 -0.127211 0.994329 -0.011763 -0.105699 0.992122 -0.093986 -0.082828 0.977543 -0.194005 -0.082286 0.897112 -0.395574 -0.196751 -0.074606 -0.771278 -0.632111 -0.946045 -0.144319 -0.290121 -0.995446 0.001024 -0.095323 -0.999745 0.004706 0.022089 -0.992191 -0.016235 0.123667 -0.976534 -0.035152 0.212473 -0.955895 -0.037977 0.291242 -0.927978 -0.005035 0.372600 -0.835221 0.169384 0.523178 0.068003 0.754407 0.652875 0.902525 0.430187 -0.019679 0.954113 0.240349 -0.178606 0.968142 0.150720 -0.199964 0.980608 0.068631 -0.183572 0.988928 -0.021770 -0.146789 0.986914 -0.123140 -0.104102 0.967454 -0.238782 -0.083765 0.878456 -0.439480 -0.187541 -0.130583 -0.743285 -0.656106 -0.956275 -0.063904 -0.285401 -0.995550 0.057402 -0.074734 -0.997421 0.036636 0.061723 -0.983509 -0.006785 0.180729 -0.958406 -0.043737 0.282037 -0.927724 -0.059847 0.368438 -0.890173 -0.036809 0.454134 -0.785080 0.128095 0.606004 0.118402 0.723880 0.679690 0.890246 0.447004 -0.087461 0.929935 0.263997 -0.255983 0.945906 0.170207 -0.276210 0.964279 0.076987 -0.253454 0.978511 -0.031435 -0.203785 0.977706 -0.154665 -0.142022 0.952358 -0.287656 -0.101327 0.852333 -0.486298 -0.192464 -0.203972 -0.703403 -0.680896 -0.968654 0.010488 -0.248193 -0.994099 0.105785 -0.024002 -0.990083 0.060763 0.126663 -0.966448 -0.004240 0.256828 -0.929527 -0.057818 0.364194 -0.887461 -0.085800 0.452826 -0.839247 -0.071758 0.538994 -0.719439 0.083180 0.689557 0.182178 0.687378 0.703081 0.871727 0.463841 -0.157936 0.895522 0.290089 -0.337475 0.912460 0.194007 -0.360247 0.937257 0.091357 -0.336456 0.959439 -0.034228 -0.279829 0.962417 -0.179386 -0.203897 0.932863 -0.329327 -0.145982 0.821254 -0.524632 -0.224286 -0.294640 -0.647549 -0.702757 -0.984329 0.056663 -0.166989 -0.989626 0.127203 0.066783 -0.972977 0.062540 0.222270 -0.935608 -0.018332 0.352563 -0.885840 -0.083282 0.456456 -0.832837 -0.119252 0.540519 -0.774340 -0.111835 0.622808 -0.638375 0.033760 0.768985 0.256796 0.645712 0.719104 0.845647 0.482791 -0.227585 0.849506 0.320986 -0.418697 0.865173 0.225617 -0.447853 0.895187 0.117771 -0.429850 0.926440 -0.019973 -0.375912 0.937470 -0.182550 -0.296354 0.909494 -0.346470 -0.229737 0.788092 -0.538589 -0.298049 -0.396638 -0.581936 -0.709950 -0.998173 0.047873 -0.036855 -0.974677 0.098487 0.200762 -0.937455 0.024202 0.347264 -0.883966 -0.061300 0.463515 -0.822961 -0.128302 0.553420 -0.761700 -0.165877 0.626337 -0.694891 -0.161203 0.700814 -0.543013 -0.022997 0.839409 0.336244 0.599863 0.726020 0.810247 0.507913 -0.292445 0.790734 0.360751 -0.494569 0.801850 0.270026 -0.533032 0.833688 0.163786 -0.527388 0.872647 0.023880 -0.487767 0.895608 -0.145317 -0.420440 0.877556 -0.316475 -0.360193 0.749612 -0.506803 -0.425714 -0.502506 -0.521384 -0.689671 -0.990482 -0.038773 0.132070 -0.931106 0.000519 0.364748 -0.870493 -0.068239 0.487427 -0.803598 -0.143661 0.577574 -0.736230 -0.201473 0.646045 -0.671195 -0.233087 0.703681 -0.599278 -0.226322 0.767883 -0.433830 -0.092088 0.896276 0.414376 0.552064 0.723545 0.762324 0.545173 -0.348781 0.716967 0.415226 -0.559952 0.719924 0.333433 -0.608713 0.748435 0.237043 -0.619400 0.789920 0.108596 -0.603517 0.823622 -0.050184 -0.564914 0.819932 -0.215724 -0.530259 0.686796 -0.404590 -0.603836 -0.591993 -0.488803 -0.640793 -0.928830 -0.210880 0.304638 -0.834722 -0.170905 0.523479 -0.758678 -0.217147 0.614210 -0.687532 -0.268830 0.674560 -0.621287 -0.307779 0.720607 -0.557943 -0.326752 0.762845 -0.484917 -0.313177 0.816563 -0.310465 -0.178431 0.933688 0.486060 0.505129 0.713155 0.697626 0.600232 -0.391202 0.625093 0.489550 -0.607947 0.616646 0.420409 -0.665585 0.635768 0.341516 -0.692218 0.670602 0.238186 -0.702538 0.704674 0.109629 -0.701011 0.707746 -0.030767 -0.705797 0.565918 -0.214163 -0.796160 -0.640808 -0.488915 -0.591885 -0.793658 -0.437095 0.423148 -0.675206 -0.388802 0.626841 -0.598675 -0.404059 0.691610 -0.534319 -0.426621 0.729725 -0.476297 -0.442996 0.759536 -0.419414 -0.446271 0.790528 -0.349134 -0.423054 0.836140 -0.171752 -0.283577 0.943443 0.548497 0.461618 0.697180 0.611496 0.675713 -0.411685 0.511603 0.585199 -0.629130 0.489690 0.530452 -0.691971 0.494367 0.472867 -0.729382 0.512909 0.401550 -0.758737 0.532009 0.314343 -0.786229 0.524367 0.212993 -0.824423 0.369469 0.039892 -0.928386 -0.658323 -0.493583 -0.568320 -0.607271 -0.655619 0.448760 -0.473344 -0.602604 0.642506 -0.405571 -0.592968 0.695630 -0.353380 -0.592032 0.724307 -0.306534 -0.589643 0.747233 -0.258175 -0.579168 0.773246 -0.192930 -0.546715 0.814789 -0.018262 -0.400227 0.916234 0.601721 0.424378 0.676635 0.502012 0.766608 -0.400371 0.375763 0.695261 -0.612711 0.340295 0.653591 -0.676031 0.328961 0.615024 -0.716610 0.327246 0.571460 -0.752558 0.323589 0.519460 -0.790855 0.295155 0.451845 -0.841855 0.130084 0.286871 -0.949096 -0.668632 -0.487013 -0.561916 -0.415030 -0.821326 0.391374 -0.266798 -0.771405 0.577713 -0.206620 -0.749407 0.629045 -0.164427 -0.735637 0.657116 -0.126731 -0.722283 0.679887 -0.085610 -0.703242 0.705777 -0.025314 -0.664564 0.746802 0.143241 -0.511388 0.847328 0.646372 0.396238 0.652073 0.374604 0.858465 -0.350299 0.224464 0.802950 -0.552166 0.177621 0.770450 -0.612257 0.153130 0.744120 -0.650258 0.135007 0.717096 -0.683774 0.112971 0.684633 -0.720080 0.068007 0.634751 -0.769718 -0.099485 0.471846 -0.876050 -0.679810 -0.474945 -0.558825 -0.246866 -0.925723 0.286519 -0.083199 -0.882126 0.463608 -0.025449 -0.856684 0.515213 0.011957 -0.838411 0.544907 0.044824 -0.820807 0.569445 0.081848 -0.798199 0.596807 0.138932 -0.756688 0.638844 0.300460 -0.598761 0.742435 0.682156 0.378928 0.625362 0.241666 0.933783 -0.263908 0.071509 0.889172 -0.451951 0.016873 0.861455 -0.507554 -0.015587 0.840583 -0.541459 -0.042857 0.820192 -0.570480 -0.074469 0.794885 -0.602173 -0.127385 0.750978 -0.647923 -0.291627 0.586704 -0.755468 -0.689939 -0.464681 -0.555028 -0.109026 -0.980518 0.163395 0.069114 -0.941776 0.329062 0.127817 -0.916223 0.379735 0.164242 -0.897171 0.410011 0.195690 -0.878672 0.435477 0.231314 -0.855235 0.463753 0.286939 -0.812945 0.506741 0.441852 -0.652373 0.615772 0.708421 0.371887 0.599866 0.116178 0.981391 -0.152886 -0.069566 0.942730 -0.326223 -0.128699 0.916825 -0.377979 -0.164794 0.897546 -0.408966 -0.195701 0.878842 -0.435130 -0.230771 0.855188 -0.464110 -0.286149 0.812502 -0.507897 -0.444819 0.646480 -0.619839 -0.696674 -0.458294 -0.551917 0.003496 -0.999341 0.036118 0.193535 -0.962547 0.189862 0.254105 -0.937270 0.238654 0.291025 -0.918287 0.268429 0.322547 -0.899797 0.293818 0.358031 -0.876348 0.322223 0.413053 -0.834001 0.365826 0.561899 -0.672526 0.481642 0.725697 0.371802 0.578902 0.005577 0.999523 -0.030377 -0.191804 0.962899 -0.189834 -0.253361 0.937426 -0.238831 -0.290810 0.918383 -0.268330 -0.322770 0.899868 -0.293354 -0.358660 0.876375 -0.321451 -0.414240 0.833757 -0.365040 -0.566802 0.666964 -0.483627 -0.699199 -0.455041 -0.551416 0.097161 -0.991093 -0.091071 0.296321 -0.953701 0.051459 0.358496 -0.928343 0.098284 0.396068 -0.909358 0.127270 0.427924 -0.890897 0.152264 0.463503 -0.867501 0.180573 0.518046 -0.825278 0.224822 0.661119 -0.664461 0.348445 0.735849 0.374765 0.563984 -0.088980 0.991441 0.095535 -0.294967 0.954117 -0.051535 -0.357910 0.928540 -0.098560 -0.395848 0.909442 -0.127359 -0.428006 0.890887 -0.152088 -0.463895 0.867373 -0.180179 -0.518960 0.824793 -0.224494 -0.665496 0.658593 -0.351241 -0.697606 -0.453074 -0.555040 0.176802 -0.959655 -0.218639 0.382716 -0.919839 -0.086163 0.445952 -0.894122 -0.040893 0.483899 -0.875036 -0.012444 0.515891 -0.856565 0.012369 0.551389 -0.833249 0.040828 0.605270 -0.791349 0.086115 0.742700 -0.632933 0.218612 0.741129 0.377620 0.555095 -0.169361 0.960132 0.222402 -0.381755 0.920237 0.086180 -0.445582 0.894317 0.040673 -0.483756 0.875116 0.012294 -0.515933 0.856539 -0.012389 -0.551655 0.833076 -0.040758 -0.606028 0.790754 -0.086247 -0.746790 0.626753 -0.222452 -0.692497 -0.449918 -0.563934 0.244914 -0.904737 -0.348524 0.455727 -0.861235 -0.224915 0.519567 -0.835110 -0.180671 0.557614 -0.815999 -0.152355 0.589522 -0.797651 -0.127344 0.624736 -0.774620 -0.098330 0.677770 -0.733470 -0.051472 0.809722 -0.579701 0.091087 0.743641 0.377987 0.551475 -0.237555 0.905687 0.351138 -0.454748 0.861893 0.224377 -0.519154 0.835499 0.180056 -0.557466 0.816171 0.151973 -0.589624 0.797588 0.127265 -0.625148 0.774266 0.098498 -0.678788 0.732525 0.051508 -0.814121 0.572783 -0.095536 -0.684861 -0.442602 -0.578851 0.301499 -0.822825 -0.481723 0.515772 -0.774648 -0.365922 0.579961 -0.748164 -0.322329 0.618010 -0.729160 -0.293920 0.649778 -0.711117 -0.268518 0.684668 -0.688653 -0.238717 0.736831 -0.648861 -0.189892 0.863704 -0.502704 -0.036116 0.745211 0.374146 0.551973 -0.294163 0.824424 0.483522 -0.514884 0.775713 0.364916 -0.579577 0.748897 0.321315 -0.617871 0.729559 0.293221 -0.649892 0.711126 0.268217 -0.685120 0.688193 0.238750 -0.737974 0.647592 0.189790 -0.868394 0.494945 0.030365 -0.676275 -0.427619 -0.599829 0.344063 -0.708771 -0.615844 0.560585 -0.654876 -0.506835 0.625025 -0.627831 -0.463865 0.663136 -0.608693 -0.435596 0.694878 -0.590715 -0.410122 0.729584 -0.568717 -0.379827 0.781057 -0.530687 -0.329121 0.903672 -0.395818 -0.163417 0.747370 0.365131 0.555083 -0.337430 0.708568 0.619736 -0.560537 0.654196 0.507766 -0.625187 0.627603 0.463957 -0.663205 0.609062 0.434974 -0.694862 0.591632 0.408827 -0.729613 0.569981 0.377871 -0.781624 0.531684 0.326155 -0.907988 0.390120 0.152852 -0.669180 -0.401371 -0.625379 0.368361 -0.559419 -0.742537 0.585885 -0.498469 -0.638958 0.650375 -0.469771 -0.596932 0.688464 -0.449011 -0.569567 0.720141 -0.429371 -0.545011 0.754666 -0.406154 -0.515284 0.805570 -0.368922 -0.463631 0.925155 -0.249032 -0.286481 0.751142 0.351260 0.558929 -0.362301 0.546142 0.755292 -0.586684 0.486072 0.647716 -0.651162 0.462220 0.601947 -0.688882 0.447483 0.570263 -0.720176 0.434012 0.541276 -0.754483 0.416267 0.507422 -0.805808 0.382731 0.451874 -0.929522 0.257612 0.263866 -0.666207 -0.361688 -0.652189 0.371356 -0.379405 -0.847435 0.588255 -0.309996 -0.746899 0.651891 -0.277113 -0.705865 0.688940 -0.251048 -0.679953 0.719358 -0.225141 -0.657142 0.752390 -0.195583 -0.629013 0.801546 -0.154590 -0.577604 0.918894 -0.051274 -0.391159 0.755901 0.335552 0.562156 -0.359043 0.322604 0.875794 -0.583875 0.259013 0.769417 -0.649545 0.244983 0.719774 -0.688656 0.242037 0.683499 -0.721096 0.239722 0.650042 -0.756119 0.231532 0.612108 -0.807665 0.207083 0.552082 -0.930784 0.104733 0.350247 -0.668312 -0.308837 -0.676741 0.355874 -0.183949 -0.916251 0.570024 -0.105903 -0.814774 0.630735 -0.065602 -0.773220 0.663983 -0.028953 -0.747187 0.689480 0.010410 -0.724230 0.716401 0.055106 -0.695509 0.758654 0.108928 -0.642323 0.871507 0.198341 -0.448483 0.756533 0.323443 0.568368 -0.313691 0.031179 0.949013 -0.539199 -0.029247 0.841671 -0.611980 -0.020008 0.790620 -0.658802 0.002789 0.752311 -0.697327 0.022976 0.716385 -0.736332 0.032302 0.675849 -0.790097 0.022289 0.612576 -0.914948 -0.051447 0.400278 -0.673804 -0.244025 -0.697453 0.331739 0.007307 -0.943343 0.541135 0.091161 -0.835980 0.596353 0.140435 -0.790343 0.621947 0.191358 -0.759318 0.636776 0.249813 -0.729459 0.649421 0.316841 -0.691277 0.674485 0.390745 -0.626409 0.775491 0.469128 -0.422532 0.743424 0.310365 0.592448 -0.219646 -0.299813 0.928368 -0.447120 -0.347363 0.824271 -0.538732 -0.303197 0.786028 -0.604645 -0.243046 0.758507 -0.657043 -0.191410 0.729148 -0.704486 -0.158680 0.691752 -0.762777 -0.150381 0.628933 -0.891026 -0.191665 0.411506 -0.680361 -0.168030 -0.713355 0.310121 0.179981 -0.933505 0.513964 0.263613 -0.816302 0.562209 0.320075 -0.762544 0.577439 0.384457 -0.720247 0.576813 0.461372 -0.674109 0.567583 0.548931 -0.613616 0.565468 0.638004 -0.522682 0.646941 0.699489 -0.303616 0.718742 0.268624 0.641288 -0.097705 -0.597450 0.795932 -0.327684 -0.628453 0.705457 -0.447860 -0.555349 0.700721 -0.542132 -0.461426 0.702267 -0.614096 -0.379592 0.691951 -0.672747 -0.323650 0.665329 -0.736751 -0.296456 0.607711 -0.868767 -0.303920 0.390994 -0.684979 -0.082292 -0.723900 0.297180 0.330027 -0.895972 0.496057 0.406042 -0.767501 0.537860 0.464907 -0.703255 0.543005 0.537038 -0.645551 0.526620 0.624325 -0.576966 0.494708 0.720035 -0.486635 0.465356 0.806951 -0.363693 0.528830 0.838604 -0.130698 0.702189 0.173511 0.690525 0.006598 -0.797452 0.603347 -0.223674 -0.818192 0.529652 -0.369012 -0.738406 0.564435 -0.489649 -0.629686 0.603108 -0.580034 -0.529509 0.619017 -0.649138 -0.456656 0.608347 -0.718394 -0.413222 0.559604 -0.853499 -0.387457 0.348448 -0.687359 0.009388 -0.726257 0.291886 0.459263 -0.838975 0.487445 0.521499 -0.700312 0.524914 0.576923 -0.625800 0.523055 0.648678 -0.552838 0.495606 0.734934 -0.462868 0.448379 0.823940 -0.346524 0.402702 0.893238 -0.199890 0.458173 0.888054 0.037930 0.701637 0.051662 0.710659 0.063244 -0.902660 0.425682 -0.165686 -0.918163 0.359897 -0.322886 -0.848108 0.420068 -0.457744 -0.743633 0.487320 -0.559223 -0.640039 0.526897 -0.635158 -0.559447 0.532535 -0.708065 -0.504503 0.494085 -0.845160 -0.447716 0.291985 -0.687220 0.101188 -0.719368 0.290281 0.570410 -0.768355 0.484295 0.615149 -0.622133 0.520012 0.661924 -0.539856 0.515478 0.725596 -0.455843 0.484322 0.800925 -0.352067 0.433282 0.873500 -0.221958 0.385973 0.920100 -0.066633 0.444588 0.879982 0.167251 0.707728 -0.070305 0.702978 0.070826 -0.951635 0.298955 -0.156237 -0.960531 0.230151 -0.311833 -0.902741 0.296342 -0.446683 -0.812065 0.375533 -0.550028 -0.716387 0.429255 -0.628238 -0.636675 0.447171 -0.702899 -0.575513 0.417992 -0.841013 -0.491142 0.226885 -0.686365 0.186377 -0.702970 0.287844 0.665172 -0.688979 0.481924 0.691301 -0.538379 0.518242 0.725887 -0.452232 0.515148 0.776125 -0.363664 0.487394 0.834681 -0.256427 0.443189 0.887464 -0.126456 0.406520 0.913326 0.024013 0.476460 0.843451 0.248146 0.710411 -0.174821 0.681728 0.042455 -0.973390 0.225190 -0.182564 -0.972219 0.146496 -0.326890 -0.922777 0.204022 -0.450727 -0.847745 0.279596 -0.548105 -0.765957 0.335992 -0.624434 -0.693338 0.359674 -0.699080 -0.630721 0.336866 -0.837575 -0.523168 0.157361 -0.685808 0.259955 -0.679773 0.281837 0.744308 -0.605453 0.477164 0.752712 -0.453585 0.515932 0.773587 -0.367937 0.517407 0.808074 -0.281615 0.498089 0.848148 -0.180421 0.467616 0.881786 -0.061547 0.448877 0.890457 0.074809 0.534324 0.795599 0.285516 0.708534 -0.259600 0.656192 -0.006006 -0.981216 0.192820 -0.227981 -0.968365 0.101460 -0.355632 -0.923784 0.141946 -0.462529 -0.862932 0.203508 -0.549126 -0.796517 0.253023 -0.620551 -0.734107 0.275686 -0.693719 -0.673437 0.255414 -0.832299 -0.547474 0.086896 -0.687234 0.318662 -0.652812 0.270972 0.808390 -0.522571 0.468403 0.801383 -0.372000 0.510948 0.808959 -0.290720 0.518927 0.828090 -0.212087 0.510540 0.850942 -0.123479 0.496409 0.867806 -0.022145 0.497698 0.862128 0.095038 0.598958 0.746520 0.289753 0.704858 -0.321266 0.632426 -0.059662 -0.980294 0.188318 -0.277912 -0.956903 0.084270 -0.387531 -0.915939 0.104285 -0.476050 -0.867102 0.146661 -0.549966 -0.814846 0.183203 -0.614688 -0.763140 0.199438 -0.685216 -0.706255 0.177997 -0.823766 -0.566609 0.019073 -0.690893 0.362048 -0.625770 0.255993 0.858057 -0.445204 0.455996 0.838710 -0.297713 0.503049 0.834888 -0.223392 0.518238 0.840978 -0.155518 0.520933 0.849624 -0.082268 0.522134 0.852863 -0.000218 0.541199 0.835284 0.096973 0.655525 0.703238 0.275215 0.703248 -0.363064 0.611250 -0.106650 -0.974551 0.197172 -0.321386 -0.943343 0.082553 -0.415146 -0.905969 0.082910 -0.487295 -0.866830 0.105593 -0.549056 -0.826088 0.126946 -0.606538 -0.783724 0.133749 -0.673695 -0.731003 0.108487 -0.812196 -0.581826 -0.042622 -0.695882 0.392087 -0.601677 0.238033 0.895414 -0.376262 0.440696 0.866938 -0.232820 0.492525 0.854176 -0.166743 0.514855 0.850095 -0.110735 0.527632 0.847812 -0.053098 0.541727 0.840488 0.010619 0.574854 0.813351 0.089464 0.698949 0.669036 0.252708 0.704490 -0.390886 0.592370 -0.142403 -0.967085 0.210875 -0.354299 -0.930949 0.088352 -0.435604 -0.897277 0.071718 -0.494512 -0.865802 0.076452 -0.545694 -0.833890 0.082741 -0.596176 -0.798957 0.079002 -0.659642 -0.750020 0.048392 -0.798167 -0.594607 -0.096809 -0.702665 0.409638 -0.581772 0.218721 0.922287 -0.318664 0.423955 0.887773 -0.179224 0.480261 0.868724 -0.121116 0.508879 0.857472 -0.076046 0.529854 0.847485 -0.031998 0.553645 0.832588 0.016546 0.596672 0.798424 0.080635 0.727390 0.645967 0.231583 0.709154 -0.405146 0.577024 -0.164874 -0.960807 0.222861 -0.375228 -0.922049 0.095018 -0.447906 -0.891689 0.065360 -0.497165 -0.865871 0.055633 -0.540029 -0.840219 0.048995 -0.584471 -0.810638 0.035492 -0.644407 -0.764682 -0.000648 -0.783007 -0.605699 -0.141524 -0.709013 0.418725 -0.567424 0.200672 0.940573 -0.273960 0.407904 0.902568 -0.137788 0.467816 0.879617 -0.086152 0.501242 0.863884 -0.049605 0.528057 0.849065 -0.015638 0.558266 0.829366 0.022163 0.607457 0.790697 0.076128 0.742422 0.633326 0.218419 0.714450 -0.412471 0.565180 -0.175338 -0.957662 0.228341 -0.385009 -0.917757 0.097421 -0.452491 -0.889800 0.059221 -0.495580 -0.867663 0.039502 -0.532716 -0.845970 0.023416 -0.572646 -0.819799 0.002337 -0.629740 -0.775857 -0.038394 -0.768557 -0.615025 -0.176253 -0.714325 0.421411 -0.558707 0.185208 0.952530 -0.241629 0.393684 0.912954 -0.107369 0.456051 0.887924 -0.060072 0.492636 0.869748 -0.029114 0.523084 0.852280 -0.001519 0.557063 0.829937 0.029737 0.609717 0.788803 0.077687 0.747307 0.628892 0.214540 0.719231 -0.414127 0.557859 -0.177015 -0.957553 0.227504 -0.386507 -0.917418 0.094635 -0.451202 -0.890936 0.051469 -0.490774 -0.870907 0.025729 -0.524430 -0.851446 0.003694 -0.561438 -0.827216 -0.022374 -0.616580 -0.784499 -0.066261 -0.755669 -0.622997 -0.202088 -0.717854 0.419552 -0.555574 0.174512 0.959308 -0.221975 0.383163 0.919513 -0.087645 0.446364 0.893876 -0.041762 0.484040 0.874954 -0.012705 0.515718 0.856664 0.012730 0.550943 0.833496 0.041783 0.604745 0.791580 0.087660 0.743524 0.630792 0.221974 0.722350 -0.411739 0.555591 -0.171797 -0.960481 0.219002 -0.381345 -0.920547 0.084678 -0.445197 -0.894548 0.039789 -0.483641 -0.875184 0.012027 -0.516134 -0.856423 -0.012020 -0.552126 -0.832811 -0.039779 -0.606566 -0.790513 -0.084663 -0.745911 -0.629020 -0.218975 -0.718193 0.415931 -0.557854 0.171117 0.961583 -0.214654 0.378378 0.922377 -0.077790 0.440300 0.897356 -0.029800 0.476605 0.879116 0.001510 0.506921 0.861499 0.029161 0.540921 0.838918 0.060173 0.593754 0.797431 0.107513 0.732251 0.636666 0.241795 0.722055 -0.408026 0.558706 -0.161657 -0.965969 0.201916 -0.371064 -0.926251 0.066108 -0.435652 -0.899840 0.022264 -0.475171 -0.879885 -0.003749 -0.508888 -0.860448 -0.025725 -0.546051 -0.836173 -0.051410 -0.601357 -0.793368 -0.094533 -0.740867 -0.631990 -0.227386 -0.714496 0.412446 -0.565141 0.177427 0.959556 -0.218570 0.381185 0.921349 -0.076247 0.439229 0.898100 -0.022222 0.471347 0.881809 0.015649 0.497541 0.866016 0.049684 0.527838 0.844951 0.086289 0.577636 0.804551 0.137967 0.714139 0.644087 0.274148 0.717134 -0.404623 0.567449 -0.148294 -0.973142 0.176081 -0.357002 -0.933321 0.038229 -0.423634 -0.905830 -0.002458 -0.466305 -0.884312 -0.023476 -0.503705 -0.862973 -0.039489 -0.544465 -0.836697 -0.059133 -0.602449 -0.792208 -0.097268 -0.741839 -0.630574 -0.228147 -0.705445 0.411654 -0.576964 0.196120 0.952756 -0.231934 0.393457 0.915775 -0.080923 0.444461 0.895643 -0.016698 0.469151 0.882538 0.032000 0.488184 0.869408 0.076191 0.512148 0.850277 0.121379 0.556729 0.811054 0.179569 0.689191 0.650564 0.319034 0.706027 -0.403770 0.581803 -0.132933 -0.981021 0.141161 -0.339927 -0.940452 0.000303 -0.409753 -0.911496 -0.035752 -0.457679 -0.887759 -0.049131 -0.501428 -0.863410 -0.055616 -0.548519 -0.833594 -0.065178 -0.611230 -0.785769 -0.094686 -0.749978 -0.622939 -0.222440 -0.690785 0.414817 -0.592236 0.230563 0.939540 -0.253191 0.417494 0.904226 -0.089853 0.457405 0.889193 -0.010806 0.470629 0.880730 0.053131 0.478838 0.870863 0.110964 0.493404 0.853594 0.167122 0.530268 0.815099 0.233301 0.656192 0.653804 0.376766 0.687387 -0.406717 0.601731 -0.115721 -0.988601 0.096312 -0.319582 -0.946297 -0.048872 -0.393780 -0.915771 -0.079379 -0.449402 -0.889470 -0.082956 -0.502786 -0.861023 -0.076455 -0.559657 -0.825636 -0.071477 -0.629590 -0.771942 -0.087875 -0.766831 -0.606440 -0.210241 -0.665947 0.427906 -0.611073 0.282147 0.918901 -0.275704 0.453514 0.885914 -0.097371 0.478069 0.878322 0.000056 0.475648 0.875771 0.082362 0.469303 0.869178 0.155832 0.471452 0.853004 0.223867 0.498158 0.814163 0.298291 0.614820 0.650581 0.445804 0.658789 -0.417559 0.625813 -0.097652 -0.994333 0.042017 -0.296084 -0.948913 -0.109079 -0.375422 -0.917082 -0.134235 -0.441015 -0.888432 -0.127257 -0.507384 -0.855218 -0.105658 -0.577558 -0.812152 -0.082679 -0.656946 -0.749462 -0.082025 -0.791319 -0.578991 -0.196427 -0.630028 0.450634 -0.632450 0.347640 0.891803 -0.289541 0.498283 0.861807 -0.094884 0.503759 0.863556 0.022322 0.481992 0.867398 0.123711 0.457905 0.863259 0.212383 0.445225 0.846788 0.291074 0.459849 0.806137 0.372399 0.564541 0.638572 0.522990 0.619314 -0.436330 0.652738 -0.078932 -0.996689 -0.019493 -0.269105 -0.946441 -0.178414 -0.353682 -0.913773 -0.199819 -0.430908 -0.883537 -0.183522 -0.513216 -0.845594 -0.146901 -0.599844 -0.793271 -0.104443 -0.690155 -0.718728 -0.084354 -0.819476 -0.541294 -0.188309 -0.579790 0.483975 -0.655448 0.422666 0.860105 -0.285608 0.547406 0.833516 -0.074813 0.530347 0.845533 0.061689 0.485779 0.855198 0.180709 0.441230 0.851931 0.282008 0.411952 0.833416 0.368393 0.413144 0.789388 0.454070 0.503423 0.615980 0.605916 0.567772 -0.464011 0.679947 -0.057913 -0.994494 -0.087332 -0.236293 -0.937385 -0.255882 -0.325516 -0.904324 -0.276113 -0.415447 -0.873623 -0.253351 -0.516485 -0.831726 -0.203654 -0.622833 -0.769390 -0.141837 -0.725336 -0.680932 -0.101088 -0.847307 -0.495110 -0.192190 -0.506179 0.528701 -0.681365 0.493960 0.833175 -0.248642 0.589066 0.807714 -0.024460 0.547928 0.826923 0.126384 0.479660 0.839055 0.256735 0.414666 0.833899 0.364231 0.369309 0.811456 0.452934 0.357310 0.762667 0.539138 0.431576 0.581414 0.689711 0.504201 -0.501695 0.702911 -0.033994 -0.986831 -0.158145 -0.196339 -0.920563 -0.337661 -0.288049 -0.887208 -0.360401 -0.389427 -0.857370 -0.336544 -0.509414 -0.813766 -0.279788 -0.636774 -0.743670 -0.203651 -0.751964 -0.642947 -0.145497 -0.865340 -0.448528 -0.223626 -0.413543 0.578936 -0.702720 0.540973 0.824346 -0.166740 0.604774 0.793574 0.066999 0.540531 0.811400 0.222388 0.451894 0.819431 0.352597 0.370829 0.808795 0.456439 0.313219 0.780882 0.540479 0.290417 0.726518 0.622760 0.348528 0.535970 0.768937 0.430805 -0.545242 0.719109 -0.004819 -0.973762 -0.227518 -0.146883 -0.896199 -0.418633 -0.237290 -0.862073 -0.447799 -0.345646 -0.834135 -0.429823 -0.480476 -0.792341 -0.375950 -0.626682 -0.720661 -0.296510 -0.754589 -0.614557 -0.230032 -0.860264 -0.413377 -0.298439 -0.306197 0.634309 -0.709856 0.540683 0.840412 -0.037013 0.572732 0.794804 0.200661 0.489736 0.799750 0.347216 0.388896 0.796194 0.463502 0.300334 0.776866 0.553424 0.237143 0.742600 0.626346 0.207776 0.682405 0.700823 0.251526 0.481787 0.839414 0.351353 -0.591037 0.726104 0.034808 -0.955649 -0.292445 -0.082889 -0.865173 -0.494575 -0.167033 -0.829441 -0.533037 -0.274991 -0.803896 -0.527381 -0.415692 -0.767674 -0.487727 -0.573774 -0.702926 -0.420331 -0.713018 -0.601672 -0.359994 -0.813861 -0.395741 -0.425463 -0.199495 0.696161 -0.689609 0.461691 0.877145 0.132131 0.466032 0.806082 0.364754 0.376185 0.787972 0.487427 0.277420 0.767751 0.577579 0.193666 0.738314 0.646054 0.133770 0.697797 0.703693 0.103668 0.632128 0.767898 0.137192 0.421707 0.896293 0.270955 -0.635017 0.723420 0.090947 -0.932767 -0.348819 0.001098 -0.828509 -0.559975 -0.071206 -0.790172 -0.608734 -0.168926 -0.766669 -0.619421 -0.300892 -0.738378 -0.603541 -0.455235 -0.688180 -0.564951 -0.596744 -0.602213 -0.530317 -0.693768 -0.392425 -0.603895 -0.127606 0.756992 -0.640843 0.281128 0.909981 0.304798 0.268869 0.808421 0.523608 0.191021 0.765638 0.614255 0.110873 0.729855 0.674550 0.044148 0.691971 0.720574 -0.003876 0.646614 0.762808 -0.028587 0.576596 0.816529 0.000894 0.358150 0.933664 0.194442 -0.673460 0.713193 0.170815 -0.904339 -0.391145 0.111220 -0.786186 -0.607900 0.055600 -0.744290 -0.665539 -0.022196 -0.721385 -0.692179 -0.128927 -0.699875 -0.702533 -0.257034 -0.665122 -0.701104 -0.379893 -0.597636 -0.706054 -0.467681 -0.383108 -0.796557 -0.103175 0.799106 -0.592270 0.018369 0.905919 0.423053 0.000939 0.779189 0.626788 -0.050574 0.720539 0.691568 -0.102317 0.676083 0.729687 -0.145529 0.634019 0.759501 -0.176820 0.586392 0.790493 -0.191860 0.513921 0.836107 -0.159759 0.290587 0.943417 0.125475 -0.705705 0.697306 0.279488 -0.867441 -0.411621 0.251040 -0.735683 -0.629087 0.214567 -0.689338 -0.691935 0.162333 -0.664604 -0.729349 0.091258 -0.645013 -0.758703 0.006133 -0.617959 -0.786186 -0.077860 -0.560681 -0.824363 -0.150299 -0.340043 -0.928321 -0.098211 0.817068 -0.568115 -0.263717 0.853798 0.448869 -0.284879 0.711297 0.642574 -0.310567 0.647754 0.695674 -0.335972 0.602055 0.724329 -0.357414 0.560263 0.747235 -0.372581 0.513124 0.773232 -0.377135 0.440378 0.814762 -0.337615 0.215856 0.916200 0.066683 -0.733336 0.676588 0.413052 -0.817990 -0.400351 0.414384 -0.672982 -0.612684 0.395995 -0.621445 -0.676013 0.368191 -0.592372 -0.716610 0.331200 -0.569143 -0.752584 0.287825 -0.540021 -0.790907 0.243305 -0.481631 -0.841923 0.182877 -0.256199 -0.949167 -0.087507 0.822617 -0.561821 -0.503749 0.770083 0.391420 -0.534634 0.616748 0.577745 -0.545682 0.553629 0.629068 -0.554862 0.510200 0.657133 -0.562152 0.470873 0.679899 -0.566228 0.425739 0.705785 -0.562883 0.354177 0.746807 -0.514507 0.131609 0.847326 0.020000 -0.757932 0.652027 0.556165 -0.753629 -0.350318 0.583155 -0.595845 -0.552177 0.578426 -0.539030 -0.612267 0.567862 -0.504658 -0.650271 0.553509 -0.475455 -0.683791 0.536402 -0.440142 -0.720103 0.515671 -0.376262 -0.769747 0.458318 -0.149753 -0.876082 -0.071409 0.826190 -0.558848 -0.678321 0.676622 0.286467 -0.722387 0.513090 0.463568 -0.729210 0.450369 0.515190 -0.732069 0.408851 0.544900 -0.733240 0.371596 0.569452 -0.732160 0.328237 0.596826 -0.724743 0.258052 0.638871 -0.668735 0.039203 0.742466 -0.012920 -0.780227 0.625363 0.687808 -0.676209 -0.263935 0.734258 -0.506541 -0.451976 0.737583 -0.445359 -0.507569 0.735754 -0.406800 -0.541461 0.731752 -0.372973 -0.570464 0.725664 -0.332928 -0.602138 0.714118 -0.265135 -0.647873 0.653982 -0.040756 -0.755412 -0.057446 0.829838 -0.555039 -0.794662 0.584659 0.163362 -0.850176 0.411017 0.329036 -0.857390 0.347410 0.379722 -0.859094 0.306348 0.410010 -0.858789 0.269872 0.435488 -0.856296 0.227310 0.463774 -0.847480 0.157999 0.506769 -0.785874 -0.056443 0.615805 -0.032153 -0.799448 0.599874 0.791801 -0.591329 -0.152910 0.851194 -0.411137 -0.326245 0.858333 -0.346967 -0.377992 0.859694 -0.306059 -0.408967 0.858960 -0.269930 -0.435116 0.856020 -0.227722 -0.464083 0.846749 -0.158413 -0.507860 0.782309 0.062013 -0.619797 -0.048535 0.832480 -0.551925 -0.867202 0.496645 0.036119 -0.930357 0.313667 0.189864 -0.938752 0.248572 0.238655 -0.940773 0.207105 0.268430 -0.940522 0.170561 0.293816 -0.937957 0.128105 0.322221 -0.928795 0.059281 0.365821 -0.863377 -0.150358 0.481636 -0.040878 -0.814367 0.578908 0.862825 -0.504590 -0.030372 0.929798 -0.315340 -0.189832 0.938516 -0.249293 -0.238832 0.940748 -0.207341 -0.268333 0.940692 -0.170407 -0.293358 0.938291 -0.127580 -0.321456 0.929173 -0.058138 -0.365046 0.861008 0.157377 -0.483630 -0.044480 0.833047 -0.551411 -0.906886 0.411421 -0.091047 -0.974085 0.220246 0.051477 -0.983214 0.153716 0.098294 -0.985561 0.111678 0.127271 -0.985503 0.074853 0.152254 -0.983033 0.032337 0.180554 -0.973740 -0.036016 0.224795 -0.906007 -0.240332 0.348414 -0.043368 -0.824649 0.563980 0.903108 -0.418645 0.095563 0.973777 -0.221596 -0.051509 0.983097 -0.154302 -0.098542 0.985525 -0.111906 -0.127351 0.985533 -0.074787 -0.152092 0.983112 -0.031956 -0.180193 0.973767 0.037017 -0.224516 0.903102 0.247019 -0.351268 -0.043595 0.830682 -0.555038 -0.919487 0.326704 -0.218651 -0.987962 0.128474 -0.086175 -0.997308 0.060854 -0.040902 -0.999752 0.018451 -0.012448 -0.999753 -0.018487 0.012369 -0.997309 -0.060884 0.040832 -0.987963 -0.128496 0.086124 -0.919487 -0.326723 0.218624 -0.043513 -0.830647 0.555097 0.916180 -0.333403 0.222391 0.987826 -0.129517 0.086174 0.997292 -0.061278 0.040672 0.999751 -0.018616 0.012297 0.999751 0.018542 -0.012380 0.997293 0.061214 -0.040744 0.987827 0.129467 -0.086231 0.916179 0.333374 -0.222437 -0.043376 0.824678 -0.563937 -0.905973 0.240248 -0.348560 -0.973709 0.035929 -0.224946 -0.983005 -0.032416 -0.180693 -0.985481 -0.074915 -0.152367 -0.985547 -0.111714 -0.127345 -0.983211 -0.153720 -0.098321 -0.974093 -0.220217 -0.051454 -0.906904 -0.411370 0.091109 -0.044491 -0.833004 0.551476 0.903130 -0.247138 0.351111 0.973800 -0.037143 0.224353 0.983144 0.031838 0.180040 0.985559 0.074688 0.151968 0.985543 0.111838 0.127272 0.983105 0.154271 0.098516 0.973775 0.221601 0.051534 0.903100 0.418675 -0.095504 -0.040867 0.814409 -0.578850 -0.863338 0.150304 -0.481723 -0.928751 -0.059351 -0.365923 -0.937909 -0.128183 -0.322330 -0.940475 -0.170637 -0.293923 -0.940732 -0.207171 -0.268521 -0.938723 -0.248619 -0.238721 -0.930343 -0.313690 -0.189896 -0.867204 -0.496642 -0.036122 -0.048595 -0.832447 0.551970 0.861050 -0.157455 0.483529 0.929227 0.058051 0.364920 0.938351 0.127486 0.321318 0.940751 0.170317 0.293223 0.940798 0.207264 0.268218 0.938552 0.249238 0.238749 0.929817 0.315311 0.189789 0.862831 0.504579 0.030365 -0.032193 0.799482 -0.599827 -0.785853 0.056426 -0.615833 -0.847438 -0.158037 -0.506826 -0.856235 -0.227368 -0.463860 -0.858713 -0.269944 -0.435594 -0.859011 -0.306426 -0.410126 -0.857309 -0.347486 -0.379836 -0.850107 -0.411081 -0.329135 -0.794613 -0.584705 -0.163433 -0.057471 -0.829807 0.555083 0.782337 -0.062045 0.619757 0.846804 0.158355 0.507786 0.856102 0.227637 0.463972 0.859058 0.269829 0.434984 0.859796 0.305954 0.408831 0.858426 0.346871 0.377870 0.851268 0.411059 0.326149 0.791854 0.591275 0.152845 -0.012992 0.780216 -0.625375 -0.668666 -0.039285 -0.742524 -0.724643 -0.258146 -0.638946 -0.732029 -0.328349 -0.596926 -0.733086 -0.371721 -0.569569 -0.731905 -0.408982 -0.545022 -0.729048 -0.450498 -0.515306 -0.722243 -0.513206 -0.463664 -0.678201 -0.676718 -0.286523 -0.071378 -0.826157 0.558901 0.654077 0.040717 0.755331 0.714253 0.265072 0.647750 0.725849 0.332829 0.601969 0.731962 0.372854 0.570273 0.735956 0.406681 0.541275 0.737752 0.445258 0.507413 0.734378 0.506470 0.451860 0.687881 0.676167 0.263852 0.019821 0.757745 -0.652250 -0.514206 -0.131957 -0.847455 -0.562549 -0.354489 -0.746912 -0.565901 -0.426032 -0.705870 -0.561871 -0.471139 -0.679948 -0.554669 -0.510423 -0.657123 -0.545620 -0.553794 -0.628977 -0.534733 -0.616846 -0.577548 -0.503953 -0.770124 -0.391075 -0.087296 -0.822308 0.562306 0.459034 0.149625 0.875728 0.516344 0.376124 0.769363 0.536984 0.440027 0.719740 0.553944 0.475388 0.683486 0.568126 0.504655 0.650043 0.578525 0.539092 0.612119 0.583114 0.595961 0.552095 0.556032 0.753761 0.350248 0.066708 0.733204 -0.676729 -0.337096 -0.216256 -0.916297 -0.376590 -0.440737 -0.814819 -0.372080 -0.513453 -0.773255 -0.357022 -0.560550 -0.747207 -0.335767 -0.602286 -0.724233 -0.310634 -0.647917 -0.695493 -0.285286 -0.711390 -0.642290 -0.264390 -0.853820 -0.448430 -0.098268 -0.816849 0.568420 0.184295 0.255934 0.948964 0.244646 0.481466 0.841629 0.288867 0.539922 0.790595 0.331857 0.569120 0.752312 0.368487 0.592429 0.716411 0.396002 0.621572 0.675892 0.414183 0.673155 0.612629 0.412753 0.818150 0.400332 0.125652 0.705726 -0.697254 -0.159674 -0.290814 -0.943362 -0.191742 -0.514121 -0.836011 -0.176637 -0.586597 -0.790382 -0.145262 -0.634244 -0.759364 -0.101938 -0.676336 -0.729505 -0.050041 -0.720821 -0.691312 0.001650 -0.779481 -0.626424 0.019215 -0.906109 -0.422607 -0.102392 -0.799568 0.591783 -0.150615 0.340061 0.928264 -0.077867 0.560884 0.824224 0.006464 0.618140 0.786041 0.091753 0.645124 0.758549 0.162818 0.664656 0.729193 0.214957 0.689357 0.691795 0.251316 0.735680 0.628979 0.279679 0.867397 0.411585 0.194590 0.673076 -0.713515 0.000592 -0.358595 -0.933493 -0.028896 -0.576916 -0.816292 -0.004078 -0.646933 -0.762536 0.044143 -0.692326 -0.720234 0.111192 -0.730250 -0.674070 0.191819 -0.766027 -0.613521 0.270245 -0.808685 -0.522491 0.282939 -0.909914 -0.303318 -0.127263 -0.756313 0.641713 -0.469357 0.383412 0.795424 -0.381148 0.597979 0.705087 -0.257465 0.665544 0.700545 -0.128692 0.700243 0.702209 -0.021634 0.721635 0.691936 0.056249 0.744436 0.665321 0.111853 0.786250 0.607700 0.171406 0.904304 0.390965 0.271240 0.634274 -0.723965 0.137383 -0.422446 -0.895916 0.103763 -0.632674 -0.767435 0.133800 -0.698299 -0.703190 0.193626 -0.738810 -0.645499 0.277298 -0.768264 -0.576954 0.375985 -0.788515 -0.486703 0.465766 -0.806637 -0.363866 0.461317 -0.877527 -0.130890 -0.201264 -0.694737 0.690531 -0.693409 0.393212 0.603794 -0.596301 0.602980 0.529944 -0.454701 0.688864 0.564547 -0.300420 0.738931 0.603099 -0.168608 0.767115 0.618956 -0.071034 0.790544 0.608271 0.001181 0.828813 0.559524 0.091059 0.932929 0.348356 0.351844 0.590694 -0.726145 0.251850 -0.482388 -0.838972 0.207968 -0.682880 -0.700303 0.237228 -0.743042 -0.625789 0.300288 -0.777309 -0.552827 0.388692 -0.796667 -0.462861 0.489356 -0.800278 -0.346534 0.572165 -0.795394 -0.199937 0.539907 -0.840875 0.037822 -0.305344 -0.633667 0.710796 -0.813244 0.396560 0.425881 -0.712181 0.602626 0.360055 -0.572941 0.703710 0.420156 -0.415090 0.768237 0.487352 -0.274684 0.804314 0.526904 -0.166950 0.829779 0.532535 -0.082928 0.865448 0.494087 0.034788 0.955785 0.292002 0.431266 0.544576 -0.719338 0.348625 -0.536607 -0.768449 0.290363 -0.726995 -0.622228 0.313061 -0.781325 -0.539929 0.370568 -0.809243 -0.455857 0.451542 -0.819901 -0.351954 0.540115 -0.811882 -0.221638 0.604309 -0.794005 -0.066086 0.540399 -0.824495 0.167858 -0.414475 -0.577759 0.703139 -0.860026 0.414140 0.298067 -0.754169 0.615276 0.229486 -0.626178 0.721315 0.295984 -0.480005 0.792875 0.375425 -0.345295 0.834556 0.429287 -0.237059 0.862414 0.447263 -0.146720 0.896470 0.418108 -0.004600 0.973881 0.227012 0.504638 0.500811 -0.703228 0.432283 -0.581990 -0.688780 0.357843 -0.763083 -0.538194 0.369573 -0.811812 -0.452080 0.414535 -0.834248 -0.363580 0.478999 -0.839518 -0.256455 0.546678 -0.827712 -0.126635 0.587294 -0.809026 0.023706 0.491677 -0.834745 0.247902 -0.508131 -0.527200 0.681075 -0.863874 0.450362 0.225601 -0.750396 0.644489 0.146763 -0.635514 0.744621 0.204112 -0.508743 0.814273 0.279535 -0.389336 0.857691 0.335832 -0.288350 0.887492 0.359460 -0.196823 0.920839 0.336625 -0.034384 0.986986 0.157086 0.568007 0.464476 -0.679434 0.503707 -0.616143 -0.605514 0.413321 -0.789559 -0.453611 0.412029 -0.833581 -0.367932 0.441172 -0.852104 -0.281577 0.485545 -0.855406 -0.180350 0.529916 -0.845821 -0.061452 0.546800 -0.833907 0.074897 0.422012 -0.860473 0.285469 -0.577352 -0.484666 0.657087 -0.846796 0.495693 0.192940 -0.724598 0.681649 0.101550 -0.622141 0.769915 0.142025 -0.516000 0.832046 0.203575 -0.415197 0.873817 0.253091 -0.325445 0.904456 0.275762 -0.236335 0.937478 0.255502 -0.058012 0.994516 0.087024 0.619688 0.435453 -0.652968 0.564206 -0.639035 -0.522787 0.459423 -0.806458 -0.372231 0.444782 -0.847083 -0.290893 0.457488 -0.863543 -0.212128 0.481659 -0.867643 -0.123289 0.503557 -0.863691 -0.021628 0.498218 -0.861731 0.095913 0.347600 -0.891391 0.290854 -0.631446 -0.449185 0.632067 -0.819661 0.541474 0.186982 -0.690247 0.718774 0.083204 -0.599774 0.793430 0.103635 -0.512970 0.845832 0.146394 -0.430539 0.883783 0.183204 -0.353252 0.913989 0.199595 -0.268642 0.946607 0.178230 -0.078390 0.996736 0.019313 0.659210 0.416690 -0.625948 0.615578 -0.650759 -0.444495 0.498763 -0.814240 -0.297069 0.471762 -0.853081 -0.222919 0.469212 -0.869320 -0.155318 0.475065 -0.876080 -0.082444 0.476953 -0.878928 -0.000843 0.451892 -0.886900 0.095927 0.280073 -0.920025 0.274068 -0.667018 -0.426439 0.610931 -0.789784 0.580397 0.198443 -0.655506 0.750551 0.083575 -0.576517 0.812812 0.083458 -0.506858 0.855528 0.105668 -0.440984 0.888536 0.126634 -0.375772 0.917095 0.133165 -0.296655 0.948888 0.107735 -0.098157 0.994222 -0.043446 0.687196 0.407471 -0.601439 0.656867 -0.653574 -0.375988 0.530856 -0.814943 -0.232507 0.493817 -0.853477 -0.166499 0.479000 -0.870815 -0.110639 0.470471 -0.880808 -0.053233 0.456886 -0.889467 0.010179 0.416634 -0.904738 0.088691 0.229589 -0.940190 0.251659 -0.689630 -0.416019 0.592739 -0.765855 0.607014 0.212132 -0.628630 0.772554 0.089354 -0.558995 0.826008 0.072359 -0.502495 0.861167 0.076749 -0.449455 0.889460 0.082772 -0.394100 0.915678 0.078859 -0.320083 0.946165 0.048152 -0.116333 0.988459 -0.097036 0.706089 0.403609 -0.581841 0.689134 -0.650609 -0.319065 0.556679 -0.811079 -0.179610 0.512109 -0.850296 -0.121411 0.488160 -0.869421 -0.076205 0.469145 -0.882542 -0.031987 0.444476 -0.895634 0.016746 0.393489 -0.915753 0.081009 0.196140 -0.952722 0.232056 -0.705613 -0.411423 0.576925 -0.750032 0.622926 0.222296 -0.611284 0.785741 0.094573 -0.548551 0.833578 0.065106 -0.501436 0.863407 0.055583 -0.457666 0.887766 0.049129 -0.409725 0.911508 0.035770 -0.339888 0.940466 -0.000274 -0.132878 0.981032 -0.141134 0.717073 0.404764 -0.567427 0.714116 -0.644092 -0.274196 0.577608 -0.804565 -0.138000 0.527819 -0.844961 -0.086302 0.497535 -0.866021 -0.049674 0.471355 -0.881805 -0.015613 0.439252 -0.898088 0.022283 0.381221 -0.921328 0.076327 0.177486 -0.959527 0.218645 -0.714366 -0.412627 0.565173 -0.741878 0.630544 0.228105 -0.602468 0.792200 0.097223 -0.544468 0.836697 0.059106 -0.503693 0.862980 0.039486 -0.466279 0.884325 0.023497 -0.423598 0.905847 0.002501 -0.356961 0.933339 -0.038170 -0.148269 0.973158 -0.176008 0.722176 0.407788 -0.558723 0.732231 -0.636710 -0.241741 0.593732 -0.797452 -0.107480 0.540893 -0.838938 -0.060153 0.506888 -0.861519 -0.029151 0.476567 -0.879137 -0.001504 0.440262 -0.897374 0.029809 0.378339 -0.922391 0.077809 0.171057 -0.961585 0.214696 -0.718355 -0.415662 0.557844 -0.740846 0.632036 0.227325 -0.601341 0.793386 0.094486 -0.546033 0.836187 0.051372 -0.508868 0.860461 0.025691 -0.475153 0.879895 0.003712 -0.435637 0.899846 -0.022310 -0.371049 0.926253 -0.066165 -0.161619 0.965961 -0.201988 0.722233 0.411978 -0.555566 0.743510 -0.630796 -0.222012 0.604720 -0.791598 -0.087671 0.550923 -0.833510 -0.041774 0.515707 -0.856671 -0.012701 0.484037 -0.874955 0.012749 0.446368 -0.893872 0.041815 0.383173 -0.919504 0.087701 0.174546 -0.959294 0.222012 -0.717710 -0.419766 0.555598 -0.745922 0.629008 0.218971 -0.606557 0.790521 0.084646 -0.552108 0.832824 0.039767 -0.516107 0.856440 0.012019 -0.483604 0.875204 -0.012012 -0.445151 0.894573 -0.039755 -0.381293 0.920573 -0.084624 -0.171769 0.960503 -0.218927 0.719453 0.413712 -0.557880 0.747317 -0.628929 -0.214394 0.609723 -0.788808 -0.077586 0.557049 -0.829949 -0.029678 0.523048 -0.852301 0.001539 0.492581 -0.869780 0.029103 0.455981 -0.887962 0.060040 0.393600 -0.912995 0.107330 0.185090 -0.952558 0.241611 -0.714540 -0.421085 0.558677 -0.755605 0.623077 0.202078 -0.616528 0.784540 0.066263 -0.561396 0.827245 0.022364 -0.524401 0.851463 -0.003727 -0.490764 0.870911 -0.025796 -0.451213 0.890925 -0.051578 -0.386531 0.917393 -0.094785 -0.177003 0.957511 -0.227688 0.714307 0.412755 -0.565153 0.742615 -0.633188 -0.218164 0.607618 -0.790596 -0.075889 0.558375 -0.829297 -0.022004 0.528108 -0.849032 0.015699 0.501238 -0.863888 0.049569 0.467766 -0.879655 0.086030 0.407822 -0.902633 0.137602 0.200594 -0.940653 0.273740 -0.708882 -0.418915 0.567447 -0.768456 0.615078 0.176509 -0.629639 0.775927 0.038620 -0.572575 0.819850 -0.002175 -0.532689 0.845989 -0.023339 -0.495609 0.867646 -0.039523 -0.452580 0.889747 -0.059341 -0.385152 0.917675 -0.097625 -0.175533 0.957572 -0.228571 0.708773 0.406160 -0.576780 0.726495 -0.646461 -0.233009 0.595906 -0.798881 -0.081760 0.553188 -0.832879 -0.017186 0.529709 -0.847581 0.031862 0.508997 -0.857375 0.076348 0.480577 -0.868460 0.121751 0.424409 -0.887385 0.180071 0.219275 -0.921857 0.319527 -0.702262 -0.410084 0.581945 -0.783480 0.605280 0.140698 -0.644813 0.764340 -0.000145 -0.584738 0.810421 -0.036052 -0.540084 0.840172 -0.049195 -0.496934 0.866021 -0.055358 -0.447342 0.892031 -0.064541 -0.374368 0.922536 -0.093678 -0.164003 0.961339 -0.221202 0.705218 0.389379 -0.592496 0.697727 -0.669931 -0.253712 0.573792 -0.813999 -0.090382 0.540984 -0.840959 -0.011135 0.527205 -0.848081 0.053044 0.514690 -0.850147 0.111104 0.492551 -0.854023 0.167450 0.440839 -0.866612 0.233764 0.238149 -0.894944 0.377307 -0.696439 -0.391281 0.601558 -0.798427 0.594440 0.095681 -0.659863 0.749758 -0.049437 -0.596277 0.798801 -0.079820 -0.545594 0.833907 -0.083219 -0.494134 0.866014 -0.076497 -0.434890 0.897658 -0.071279 -0.353256 0.931430 -0.087460 -0.141112 0.967519 -0.209748 0.703532 0.363084 -0.610911 0.655048 -0.703695 -0.275185 0.540660 -0.835642 -0.096897 0.521678 -0.853142 0.000375 0.520579 -0.849816 0.082527 0.517977 -0.841072 0.155876 0.502859 -0.834885 0.223830 0.455849 -0.838615 0.298207 0.255857 -0.857839 0.445702 -0.690924 -0.361771 0.625895 -0.812166 0.581901 0.042167 -0.673588 0.731031 -0.108957 -0.606358 0.783793 -0.134160 -0.548776 0.826226 -0.127262 -0.486885 0.867036 -0.105786 -0.414593 0.906217 -0.082964 -0.320711 0.943580 -0.082474 -0.105960 0.974671 -0.196946 0.705355 0.320019 -0.632505 0.598584 -0.746993 -0.289308 0.497226 -0.862438 -0.094696 0.495954 -0.868059 0.022450 0.510133 -0.851141 0.123788 0.518578 -0.828221 0.212429 0.510648 -0.809010 0.291104 0.468129 -0.801346 0.372424 0.270658 -0.808206 0.523018 -0.687611 -0.318054 0.652712 -0.823636 0.566783 -0.019516 -0.685023 0.706330 -0.178439 -0.614440 0.763231 -0.199853 -0.549646 0.814978 -0.183576 -0.475648 0.867267 -0.146995 -0.387053 0.916106 -0.104597 -0.277376 0.957032 -0.084574 -0.059043 0.980284 -0.188564 0.708995 0.259755 -0.655632 0.534171 -0.795903 -0.284957 0.448575 -0.890654 -0.074276 0.467280 -0.881933 0.061999 0.497761 -0.848259 0.180808 0.517106 -0.808144 0.281964 0.515662 -0.773608 0.368271 0.476911 -0.752673 0.453915 0.281577 -0.744151 0.605767 -0.685822 -0.259628 0.679884 -0.832179 0.547614 -0.087157 -0.693524 0.673525 -0.255711 -0.620296 0.734211 -0.275985 -0.548795 0.796653 -0.253316 -0.462113 0.863088 -0.203792 -0.355151 0.923925 -0.142235 -0.227494 0.968447 -0.101771 -0.005598 0.981170 -0.193063 0.711150 0.175181 -0.680865 0.474642 -0.844300 -0.248742 0.405039 -0.913972 -0.024469 0.442242 -0.887945 0.126395 0.486877 -0.834886 0.256742 0.514902 -0.776025 0.364225 0.518141 -0.725533 0.452915 0.481890 -0.690759 0.539106 0.287816 -0.664473 0.689665 -0.686339 -0.185947 0.703109 -0.837657 0.522823 -0.158070 -0.699092 0.630311 -0.337606 -0.624348 0.693064 -0.360350 -0.547812 0.765946 -0.336493 -0.450043 0.848065 -0.279728 -0.325640 0.923319 -0.203567 -0.180820 0.972710 -0.145393 0.044148 0.973698 -0.223524 0.707902 0.067796 -0.703049 0.443020 -0.880829 -0.166950 0.384588 -0.920670 0.066770 0.432276 -0.873922 0.222257 0.483643 -0.801117 0.352563 0.515015 -0.725531 0.456470 0.519668 -0.661633 0.540543 0.483997 -0.614670 0.622839 0.289910 -0.569702 0.769020 -0.687746 -0.100389 0.718976 -0.840916 0.490956 -0.227646 -0.702723 0.575182 -0.418744 -0.627969 0.636430 -0.447897 -0.549582 0.716346 -0.429893 -0.445924 0.812287 -0.375955 -0.310644 0.903132 -0.296399 -0.154681 0.960871 -0.229783 0.072466 0.951786 -0.298081</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="2160" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="6897">0 0 0 0 0.055556 0 0 0.111111 0 0 0.166667 0 0 0.222222 0 0 0.277778 0 0 0.333333 0 0 0.388889 0 0 0.444444 0 0 0.500000 0 0 0.555556 0 0 0.611111 0 0 0.666667 0 0 0.722222 0 0 0.777778 0 0 0.833333 0 0 0.888889 0 0 0.944444 0 0 1.000000 0 0.008333 0 0 0.008333 0.055556 0 0.008333 0.111111 0 0.008333 0.166667 0 0.008333 0.222222 0 0.008333 0.277778 0 0.008333 0.333333 0 0.008333 0.388889 0 0.008333 0.444444 0 0.008333 0.500000 0 0.008333 0.555556 0 0.008333 0.611111 0 0.008333 0.666667 0 0.008333 0.722222 0 0.008333 0.777778 0 0.008333 0.833333 0 0.008333 0.888889 0 0.008333 0.944444 0 0.008333 1.000000 0 0.016667 0 0 0.016667 0.055556 0 0.016667 0.111111 0 0.016667 0.166667 0 0.016667 0.222222 0 0.016667 0.277778 0 0.016667 0.333333 0 0.016667 0.388889 0 0.016667 0.444444 0 0.016667 0.500000 0 0.016667 0.555556 0 0.016667 0.611111 0 0.016667 0.666667 0 0.016667 0.722222 0 0.016667 0.777778 0 0.016667 0.833333 0 0.016667 0.888889 0 0.016667 0.944444 0 0.016667 1.000000 0 0.025000 0 0 0.025000 0.055556 0 0.025000 0.111111 0 0.025000 0.166667 0 0.025000 0.222222 0 0.025000 0.277778 0 0.025000 0.333333 0 0.025000 0.388889 0 0.025000 0.444444 0 0.025000 0.500000 0 0.025000 0.555556 0 0.025000 0.611111 0 0.025000 0.666667 0 0.025000 0.722222 0 0.025000 0.777778 0 0.025000 0.833333 0 0.025000 0.888889 0 0.025000 0.944444 0 0.025000 1.000000 0 0.033333 0 0 0.033333 0.055556 0 0.033333 0.111111 0 0.033333 0.166667 0 0.033333 0.222222 0 0.033333 0.277778 0 0.033333 0.333333 0 0.033333 0.388889 0 0.033333 0.444444 0 0.033333 0.500000 0 0.033333 0.555556 0 0.033333 0.611111 0 0.033333 0.666667 0 0.033333 0.722222 0 0.033333 0.777778 0 0.033333 0.833333 0 0.033333 0.888889 0 0.033333 0.944444 0 0.033333 1.000000 0 0.041667 0 0 0.041667 0.055556 0 0.041667 0.111111 0 0.041667 0.166667 0 0.041667 0.222222 0 0.041667 0.277778 0 0.041667 0.333333 0 0.041667 0.388889 0 0.041667 0.444444 0 0.041667 0.500000 0 0.041667 0.555556 0 0.041667 0.611111 0 0.041667 0.666667 0 0.041667 0.722222 0 0.041667 0.777778 0 0.041667 0.833333 0 0.041667 0.888889 0 0.041667 0.944444 0 0.041667 1.000000 0 0.050000 0 0 0.050000 0.055556 0 0.050000 0.111111 0 0.050000 0.166667 0 0.050000 0.222222 0 0.050000 0.277778 0 0.050000 0.333333 0 0.050000 0.388889 0 0.050000 0.444444 0 0.050000 0.500000 0 0.050000 0.555556 0 0.050000 0.611111 0 0.050000 0.666667 0 0.050000 0.722222 0 0.050000 0.777778 0 0.050000 0.833333 0 0.050000 0.888889 0 0.050000 0.944444 0 0.050000 1.000000 0 0.058333 0 0 0.058333 0.055556 0 0.058333 0.111111 0 0.058333 0.166667 0 0.058333 0.222222 0 0.058333 0.277778 0 0.058333 0.333333 0 0.058333 0.388889 0 0.058333 0.444444 0 0.058333 0.500000 0 0.058333 0.555556 0 0.058333 0.611111 0 0.058333 0.666667 0 0.058333 0.722222 0 0.058333 0.777778 0 0.058333 0.833333 0 0.058333 0.888889 0 0.058333 0.944444 0 0.058333 1.000000 0 0.066667 0 0 0.066667 0.055556 0 0.066667 0.111111 0 0.066667 0.166667 0 0.066667 0.222222 0 0.066667 0.277778 0 0.066667 0.333333 0 0.066667 0.388889 0 0.066667 0.444444 0 0.066667 0.500000 0 0.066667 0.555556 0 0.066667 0.611111 0 0.066667 0.666667 0 0.066667 0.722222 0 0.066667 0.777778 0 0.066667 0.833333 0 0.066667 0.888889 0 0.066667 0.944444 0 0.066667 1.000000 0 0.075000 0 0 0.075000 0.055556 0 0.075000 0.111111 0 0.075000 0.166667 0 0.075000 0.222222 0 0.075000 0.277778 0 0.075000 0.333333 0 0.075000 0.388889 0 0.075000 0.444444 0 0.075000 0.500000 0 0.075000 0.555556 0 0.075000 0.611111 0 0.075000 0.666667 0 0.075000 0.722222 0 0.075000 0.777778 0 0.075000 0.833333 0 0.075000 0.888889 0 0.075000 0.944444 0 0.075000 1.000000 0 0.083333 0 0 0.083333 0.055556 0 0.083333 0.111111 0 0.083333 0.166667 0 0.083333 0.222222 0 0.083333 0.277778 0 0.083333 0.333333 0 0.083333 0.388889 0 0.083333 0.444444 0 0.083333 0.500000 0 0.083333 0.555556 0 0.083333 0.611111 0 0.083333 0.666667 0 0.083333 0.722222 0 0.083333 0.777778 0 0.083333 0.833333 0 0.083333 0.888889 0 0.083333 0.944444 0 0.083333 1.000000 0 0.091667 0 0 0.091667 0.055556 0 0.091667 0.111111 0 0.091667 0.166667 0 0.091667 0.222222 0 0.091667 0.277778 0 0.091667 0.333333 0 0.091667 0.388889 0 0.091667 0.444444 0 0.091667 0.500000 0 0.091667 0.555556 0 0.091667 0.611111 0 0.091667 0.666667 0 0.091667 0.722222 0 0.091667 0.777778 0 0.091667 0.833333 0 0.091667 0.888889 0 0.091667 0.944444 0 0.091667 1.000000 0 0.100000 0 0 0.100000 0.055556 0 0.100000 0.111111 0 0.100000 0.166667 0 0.100000 0.222222 0 0.100000 0.277778 0 0.100000 0.333333 0 0.100000 0.388889 0 0.100000 0.444444 0 0.100000 0.500000 0 0.100000 0.555556 0 0.100000 0.611111 0 0.100000 0.666667 0 0.100000 0.722222 0 0.100000 0.777778 0 0.100000 0.833333 0 0.100000 0.888889 0 0.100000 0.944444 0 0.100000 1.000000 0 0.108333 0 0 0.108333 0.055556 0 0.108333 0.111111 0 0.108333 0.166667 0 0.108333 0.222222 0 0.108333 0.277778 0 0.108333 0.333333 0 0.108333 0.388889 0 0.108333 0.444444 0 0.108333 0.500000 0 0.108333 0.555556 0 0.108333 0.611111 0 0.108333 0.666667 0 0.108333 0.722222 0 0.108333 0.777778 0 0.108333 0.833333 0 0.108333 0.888889 0 0.108333 0.944444 0 0.108333 1.000000 0 0.116667 0 0 0.116667 0.055556 0 0.116667 0.111111 0 0.116667 0.166667 0 0.116667 0.222222 0 0.116667 0.277778 0 0.116667 0.333333 0 0.116667 0.388889 0 0.116667 0.444444 0 0.116667 0.500000 0 0.116667 0.555556 0 0.116667 0.611111 0 0.116667 0.666667 0 0.116667 0.722222 0 0.116667 0.777778 0 0.116667 0.833333 0 0.116667 0.888889 0 0.116667 0.944444 0 0.116667 1.000000 0 0.125000 0 0 0.125000 0.055556 0 0.125000 0.111111 0 0.125000 0.166667 0 0.125000 0.222222 0 0.125000 0.277778 0 0.125000 0.333333 0 0.125000 0.388889 0 0.125000 0.444444 0 0.125000 0.500000 0 0.125000 0.555556 0 0.125000 0.611111 0 0.125000 0.666667 0 0.125000 0.722222 0 0.125000 0.777778 0 0.125000 0.833333 0 0.125000 0.888889 0 0.125000 0.944444 0 0.125000 1.000000 0 0.133333 0 0 0.133333 0.055556 0 0.133333 0.111111 0 0.133333 0.166667 0 0.133333 0.222222 0 0.133333 0.277778 0 0.133333 0.333333 0 0.133333 0.388889 0 0.133333 0.444444 0 0.133333 0.500000 0 0.133333 0.555556 0 0.133333 0.611111 0 0.133333 0.666667 0 0.133333 0.722222 0 0.133333 0.777778 0 0.133333 0.833333 0 0.133333 0.888889 0 0.133333 0.944444 0 0.133333 1.000000 0 0.141667 0 0 0.141667 0.055556 0 0.141667 0.111111 0 0.141667 0.166667 0 0.141667 0.222222 0 0.141667 0.277778 0 0.141667 0.333333 0 0.141667 0.388889 0 0.141667 0.444444 0 0.141667 0.500000 0 0.141667 0.555556 0 0.141667 0.611111 0 0.141667 0.666667 0 0.141667 0.722222 0 0.141667 0.777778 0 0.141667 0.833333 0 0.141667 0.888889 0 0.141667 0.944444 0 0.141667 1.000000 0 0.150000 0 0 0.150000 0.055556 0 0.150000 0.111111 0 0.150000 0.166667 0 0.150000 0.222222 0 0.150000 0.277778 0 0.150000 0.333333 0 0.150000 0.388889 0 0.150000 0.444444 0 0.150000 0.500000 0 0.150000 0.555556 0 0.150000 0.611111 0 0.150000 0.666667 0 0.150000 0.722222 0 0.150000 0.777778 0 0.150000 0.833333 0 0.150000 0.888889 0 0.150000 0.944444 0 0.150000 1.000000 0 0.158333 0 0 0.158333 0.055556 0 0.158333 0.111111 0 0.158333 0.166667 0 0.158333 0.222222 0 0.158333 0.277778 0 0.158333 0.333333 0 0.158333 0.388889 0 0.158333 0.444444 0 0.158333 0.500000 0 0.158333 0.555556 0 0.158333 0.611111 0 0.158333 0.666667 0 0.158333 0.722222 0 0.158333 0.777778 0 0.158333 0.833333 0 0.158333 0.888889 0 0.158333 0.944444 0 0.158333 1.000000 0 0.166667 0 0 0.166667 0.055556 0 0.166667 0.111111 0 0.166667 0.166667 0 0.166667 0.222222 0 0.166667 0.277778 0 0.166667 0.333333 0 0.166667 0.388889 0 0.166667 0.444444 0 0.166667 0.500000 0 0.166667 0.555556 0 0.166667 0.611111 0 0.166667 0.666667 0 0.166667 0.722222 0 0.166667 0.777778 0 0.166667 0.833333 0 0.166667 0.888889 0 0.166667 0.944444 0 0.166667 1.000000 0 0.175000 0 0 0.175000 0.055556 0 0.175000 0.111111 0 0.175000 0.166667 0 0.175000 0.222222 0 0.175000 0.277778 0 0.175000 0.333333 0 0.175000 0.388889 0 0.175000 0.444444 0 0.175000 0.500000 0 0.175000 0.555556 0 0.175000 0.611111 0 0.175000 0.666667 0 0.175000 0.722222 0 0.175000 0.777778 0 0.175000 0.833333 0 0.175000 0.888889 0 0.175000 0.944444 0 0.175000 1.000000 0 0.183333 0 0 0.183333 0.055556 0 0.183333 0.111111 0 0.183333 0.166667 0 0.183333 0.222222 0 0.183333 0.277778 0 0.183333 0.333333 0 0.183333 0.388889 0 0.183333 0.444444 0 0.183333 0.500000 0 0.183333 0.555556 0 0.183333 0.611111 0 0.183333 0.666667 0 0.183333 0.722222 0 0.183333 0.777778 0 0.183333 0.833333 0 0.183333 0.888889 0 0.183333 0.944444 0 0.183333 1.000000 0 0.191667 0 0 0.191667 0.055556 0 0.191667 0.111111 0 0.191667 0.166667 0 0.191667 0.222222 0 0.191667 0.277778 0 0.191667 0.333333 0 0.191667 0.388889 0 0.191667 0.444444 0 0.191667 0.500000 0 0.191667 0.555556 0 0.191667 0.611111 0 0.191667 0.666667 0 0.191667 0.722222 0 0.191667 0.777778 0 0.191667 0.833333 0 0.191667 0.888889 0 0.191667 0.944444 0 0.191667 1.000000 0 0.200000 0 0 0.200000 0.055556 0 0.200000 0.111111 0 0.200000 0.166667 0 0.200000 0.222222 0 0.200000 0.277778 0 0.200000 0.333333 0 0.200000 0.388889 0 0.200000 0.444444 0 0.200000 0.500000 0 0.200000 0.555556 0 0.200000 0.611111 0 0.200000 0.666667 0 0.200000 0.722222 0 0.200000 0.777778 0 0.200000 0.833333 0 0.200000 0.888889 0 0.200000 0.944444 0 0.200000 1.000000 0 0.208333 0 0 0.208333 0.055556 0 0.208333 0.111111 0 0.208333 0.166667 0 0.208333 0.222222 0 0.208333 0.277778 0 0.208333 0.333333 0 0.208333 0.388889 0 0.208333 0.444444 0 0.208333 0.500000 0 0.208333 0.555556 0 0.208333 0.611111 0 0.208333 0.666667 0 0.208333 0.722222 0 0.208333 0.777778 0 0.208333 0.833333 0 0.208333 0.888889 0 0.208333 0.944444 0 0.208333 1.000000 0 0.216667 0 0 0.216667 0.055556 0 0.216667 0.111111 0 0.216667 0.166667 0 0.216667 0.222222 0 0.216667 0.277778 0 0.216667 0.333333 0 0.216667 0.388889 0 0.216667 0.444444 0 0.216667 0.500000 0 0.216667 0.555556 0 0.216667 0.611111 0 0.216667 0.666667 0 0.216667 0.722222 0 0.216667 0.777778 0 0.216667 0.833333 0 0.216667 0.888889 0 0.216667 0.944444 0 0.216667 1.000000 0 0.225000 0 0 0.225000 0.055556 0 0.225000 0.111111 0 0.225000 0.166667 0 0.225000 0.222222 0 0.225000 0.277778 0 0.225000 0.333333 0 0.225000 0.388889 0 0.225000 0.444444 0 0.225000 0.500000 0 0.225000 0.555556 0 0.225000 0.611111 0 0.225000 0.666667 0 0.225000 0.722222 0 0.225000 0.777778 0 0.225000 0.833333 0 0.225000 0.888889 0 0.225000 0.944444 0 0.225000 1.000000 0 0.233333 0 0 0.233333 0.055556 0 0.233333 0.111111 0 0.233333 0.166667 0 0.233333 0.222222 0 0.233333 0.277778 0 0.233333 0.333333 0 0.233333 0.388889 0 0.233333 0.444444 0 0.233333 0.500000 0 0.233333 0.555556 0 0.233333 0.611111 0 0.233333 0.666667 0 0.233333 0.722222 0 0.233333 0.777778 0 0.233333 0.833333 0 0.233333 0.888889 0 0.233333 0.944444 0 0.233333 1.000000 0 0.241667 0 0 0.241667 0.055556 0 0.241667 0.111111 0 0.241667 0.166667 0 0.241667 0.222222 0 0.241667 0.277778 0 0.241667 0.333333 0 0.241667 0.388889 0 0.241667 0.444444 0 0.241667 0.500000 0 0.241667 0.555556 0 0.241667 0.611111 0 0.241667 0.666667 0 0.241667 0.722222 0 0.241667 0.777778 0 0.241667 0.833333 0 0.241667 0.888889 0 0.241667 0.944444 0 0.241667 1.000000 0 0.250000 0 0 0.250000 0.055556 0 0.250000 0.111111 0 0.250000 0.166667 0 0.250000 0.222222 0 0.250000 0.277778 0 0.250000 0.333333 0 0.250000 0.388889 0 0.250000 0.444444 0 0.250000 0.500000 0 0.250000 0.555556 0 0.250000 0.611111 0 0.250000 0.666667 0 0.250000 0.722222 0 0.250000 0.777778 0 0.250000 0.833333 0 0.250000 0.888889 0 0.250000 0.944444 0 0.250000 1.000000 0 0.258333 0 0 0.258333 0.055556 0 0.258333 0.111111 0 0.258333 0.166667 0 0.258333 0.222222 0 0.258333 0.277778 0 0.258333 0.333333 0 0.258333 0.388889 0 0.258333 0.444444 0 0.258333 0.500000 0 0.258333 0.555556 0 0.258333 0.611111 0 0.258333 0.666667 0 0.258333 0.722222 0 0.258333 0.777778 0 0.258333 0.833333 0 0.258333 0.888889 0 0.258333 0.944444 0 0.258333 1.000000 0 0.266667 0 0 0.266667 0.055556 0 0.266667 0.111111 0 0.266667 0.166667 0 0.266667 0.222222 0 0.266667 0.277778 0 0.266667 0.333333 0 0.266667 0.388889 0 0.266667 0.444444 0 0.266667 0.500000 0 0.266667 0.555556 0 0.266667 0.611111 0 0.266667 0.666667 0 0.266667 0.722222 0 0.266667 0.777778 0 0.266667 0.833333 0 0.266667 0.888889 0 0.266667 0.944444 0 0.266667 1.000000 0 0.275000 0 0 0.275000 0.055556 0 0.275000 0.111111 0 0.275000 0.166667 0 0.275000 0.222222 0 0.275000 0.277778 0 0.275000 0.333333 0 0.275000 0.388889 0 0.275000 0.444444 0 0.275000 0.500000 0 0.275000 0.555556 0 0.275000 0.611111 0 0.275000 0.666667 0 0.275000 0.722222 0 0.275000 0.777778 0 0.275000 0.833333 0 0.275000 0.888889 0 0.275000 0.944444 0 0.275000 1.000000 0 0.283333 0 0 0.283333 0.055556 0 0.283333 0.111111 0 0.283333 0.166667 0 0.283333 0.222222 0 0.283333 0.277778 0 0.283333 0.333333 0 0.283333 0.388889 0 0.283333 0.444444 0 0.283333 0.500000 0 0.283333 0.555556 0 0.283333 0.611111 0 0.283333 0.666667 0 0.283333 0.722222 0 0.283333 0.777778 0 0.283333 0.833333 0 0.283333 0.888889 0 0.283333 0.944444 0 0.283333 1.000000 0 0.291667 0 0 0.291667 0.055556 0 0.291667 0.111111 0 0.291667 0.166667 0 0.291667 0.222222 0 0.291667 0.277778 0 0.291667 0.333333 0 0.291667 0.388889 0 0.291667 0.444444 0 0.291667 0.500000 0 0.291667 0.555556 0 0.291667 0.611111 0 0.291667 0.666667 0 0.291667 0.722222 0 0.291667 0.777778 0 0.291667 0.833333 0 0.291667 0.888889 0 0.291667 0.944444 0 0.291667 1.000000 0 0.300000 0 0 0.300000 0.055556 0 0.300000 0.111111 0 0.300000 0.166667 0 0.300000 0.222222 0 0.300000 0.277778 0 0.300000 0.333333 0 0.300000 0.388889 0 0.300000 0.444444 0 0.300000 0.500000 0 0.300000 0.555556 0 0.300000 0.611111 0 0.300000 0.666667 0 0.300000 0.722222 0 0.300000 0.777778 0 0.300000 0.833333 0 0.300000 0.888889 0 0.300000 0.944444 0 0.300000 1.000000 0 0.308333 0 0 0.308333 0.055556 0 0.308333 0.111111 0 0.308333 0.166667 0 0.308333 0.222222 0 0.308333 0.277778 0 0.308333 0.333333 0 0.308333 0.388889 0 0.308333 0.444444 0 0.308333 0.500000 0 0.308333 0.555556 0 0.308333 0.611111 0 0.308333 0.666667 0 0.308333 0.722222 0 0.308333 0.777778 0 0.308333 0.833333 0 0.308333 0.888889 0 0.308333 0.944444 0 0.308333 1.000000 0 0.316666 0 0 0.316666 0.055556 0 0.316666 0.111111 0 0.316666 0.166667 0 0.316666 0.222222 0 0.316666 0.277778 0 0.316666 0.333333 0 0.316666 0.388889 0 0.316666 0.444444 0 0.316666 0.500000 0 0.316666 0.555556 0 0.316666 0.611111 0 0.316666 0.666667 0 0.316666 0.722222 0 0.316666 0.777778 0 0.316666 0.833333 0 0.316666 0.888889 0 0.316666 0.944444 0 0.316666 1.000000 0 0.325000 0 0 0.325000 0.055556 0 0.325000 0.111111 0 0.325000 0.166667 0 0.325000 0.222222 0 0.325000 0.277778 0 0.325000 0.333333 0 0.325000 0.388889 0 0.325000 0.444444 0 0.325000 0.500000 0 0.325000 0.555556 0 0.325000 0.611111 0 0.325000 0.666667 0 0.325000 0.722222 0 0.325000 0.777778 0 0.325000 0.833333 0 0.325000 0.888889 0 0.325000 0.944444 0 0.325000 1.000000 0 0.333333 0 0 0.333333 0.055556 0 0.333333 0.111111 0 0.333333 0.166667 0 0.333333 0.222222 0 0.333333 0.277778 0 0.333333 0.333333 0 0.333333 0.388889 0 0.333333 0.444444 0 0.333333 0.500000 0 0.333333 0.555556 0 0.333333 0.611111 0 0.333333 0.666667 0 0.333333 0.722222 0 0.333333 0.777778 0 0.333333 0.833333 0 0.333333 0.888889 0 0.333333 0.944444 0 0.333333 1.000000 0 0.341666 0 0 0.341666 0.055556 0 0.341666 0.111111 0 0.341666 0.166667 0 0.341666 0.222222 0 0.341666 0.277778 0 0.341666 0.333333 0 0.341666 0.388889 0 0.341666 0.444444 0 0.341666 0.500000 0 0.341666 0.555556 0 0.341666 0.611111 0 0.341666 0.666667 0 0.341666 0.722222 0 0.341666 0.777778 0 0.341666 0.833333 0 0.341666 0.888889 0 0.341666 0.944444 0 0.341666 1.000000 0 0.350000 0 0 0.350000 0.055556 0 0.350000 0.111111 0 0.350000 0.166667 0 0.350000 0.222222 0 0.350000 0.277778 0 0.350000 0.333333 0 0.350000 0.388889 0 0.350000 0.444444 0 0.350000 0.500000 0 0.350000 0.555556 0 0.350000 0.611111 0 0.350000 0.666667 0 0.350000 0.722222 0 0.350000 0.777778 0 0.350000 0.833333 0 0.350000 0.888889 0 0.350000 0.944444 0 0.350000 1.000000 0 0.358333 0 0 0.358333 0.055556 0 0.358333 0.111111 0 0.358333 0.166667 0 0.358333 0.222222 0 0.358333 0.277778 0 0.358333 0.333333 0 0.358333 0.388889 0 0.358333 0.444444 0 0.358333 0.500000 0 0.358333 0.555556 0 0.358333 0.611111 0 0.358333 0.666667 0 0.358333 0.722222 0 0.358333 0.777778 0 0.358333 0.833333 0 0.358333 0.888889 0 0.358333 0.944444 0 0.358333 1.000000 0 0.366666 0 0 0.366666 0.055556 0 0.366666 0.111111 0 0.366666 0.166667 0 0.366666 0.222222 0 0.366666 0.277778 0 0.366666 0.333333 0 0.366666 0.388889 0 0.366666 0.444444 0 0.366666 0.500000 0 0.366666 0.555556 0 0.366666 0.611111 0 0.366666 0.666667 0 0.366666 0.722222 0 0.366666 0.777778 0 0.366666 0.833333 0 0.366666 0.888889 0 0.366666 0.944444 0 0.366666 1.000000 0 0.375000 0 0 0.375000 0.055556 0 0.375000 0.111111 0 0.375000 0.166667 0 0.375000 0.222222 0 0.375000 0.277778 0 0.375000 0.333333 0 0.375000 0.388889 0 0.375000 0.444444 0 0.375000 0.500000 0 0.375000 0.555556 0 0.375000 0.611111 0 0.375000 0.666667 0 0.375000 0.722222 0 0.375000 0.777778 0 0.375000 0.833333 0 0.375000 0.888889 0 0.375000 0.944444 0 0.375000 1.000000 0 0.383333 0 0 0.383333 0.055556 0 0.383333 0.111111 0 0.383333 0.166667 0 0.383333 0.222222 0 0.383333 0.277778 0 0.383333 0.333333 0 0.383333 0.388889 0 0.383333 0.444444 0 0.383333 0.500000 0 0.383333 0.555556 0 0.383333 0.611111 0 0.383333 0.666667 0 0.383333 0.722222 0 0.383333 0.777778 0 0.383333 0.833333 0 0.383333 0.888889 0 0.383333 0.944444 0 0.383333 1.000000 0 0.391666 0 0 0.391666 0.055556 0 0.391666 0.111111 0 0.391666 0.166667 0 0.391666 0.222222 0 0.391666 0.277778 0 0.391666 0.333333 0 0.391666 0.388889 0 0.391666 0.444444 0 0.391666 0.500000 0 0.391666 0.555556 0 0.391666 0.611111 0 0.391666 0.666667 0 0.391666 0.722222 0 0.391666 0.777778 0 0.391666 0.833333 0 0.391666 0.888889 0 0.391666 0.944444 0 0.391666 1.000000 0 0.400000 0 0 0.400000 0.055556 0 0.400000 0.111111 0 0.400000 0.166667 0 0.400000 0.222222 0 0.400000 0.277778 0 0.400000 0.333333 0 0.400000 0.388889 0 0.400000 0.444444 0 0.400000 0.500000 0 0.400000 0.555556 0 0.400000 0.611111 0 0.400000 0.666667 0 0.400000 0.722222 0 0.400000 0.777778 0 0.400000 0.833333 0 0.400000 0.888889 0 0.400000 0.944444 0 0.400000 1.000000 0 0.408333 0 0 0.408333 0.055556 0 0.408333 0.111111 0 0.408333 0.166667 0 0.408333 0.222222 0 0.408333 0.277778 0 0.408333 0.333333 0 0.408333 0.388889 0 0.408333 0.444444 0 0.408333 0.500000 0 0.408333 0.555556 0 0.408333 0.611111 0 0.408333 0.666667 0 0.408333 0.722222 0 0.408333 0.777778 0 0.408333 0.833333 0 0.408333 0.888889 0 0.408333 0.944444 0 0.408333 1.000000 0 0.416666 0 0 0.416666 0.055556 0 0.416666 0.111111 0 0.416666 0.166667 0 0.416666 0.222222 0 0.416666 0.277778 0 0.416666 0.333333 0 0.416666 0.388889 0 0.416666 0.444444 0 0.416666 0.500000 0 0.416666 0.555556 0 0.416666 0.611111 0 0.416666 0.666667 0 0.416666 0.722222 0 0.416666 0.777778 0 0.416666 0.833333 0 0.416666 0.888889 0 0.416666 0.944444 0 0.416666 1.000000 0 0.425000 0 0 0.425000 0.055556 0 0.425000 0.111111 0 0.425000 0.166667 0 0.425000 0.222222 0 0.425000 0.277778 0 0.425000 0.333333 0 0.425000 0.388889 0 0.425000 0.444444 0 0.425000 0.500000 0 0.425000 0.555556 0 0.425000 0.611111 0 0.425000 0.666667 0 0.425000 0.722222 0 0.425000 0.777778 0 0.425000 0.833333 0 0.425000 0.888889 0 0.425000 0.944444 0 0.425000 1.000000 0 0.433333 0 0 0.433333 0.055556 0 0.433333 0.111111 0 0.433333 0.166667 0 0.433333 0.222222 0 0.433333 0.277778 0 0.433333 0.333333 0 0.433333 0.388889 0 0.433333 0.444444 0 0.433333 0.500000 0 0.433333 0.555556 0 0.433333 0.611111 0 0.433333 0.666667 0 0.433333 0.722222 0 0.433333 0.777778 0 0.433333 0.833333 0 0.433333 0.888889 0 0.433333 0.944444 0 0.433333 1.000000 0 0.441666 0 0 0.441666 0.055556 0 0.441666 0.111111 0 0.441666 0.166667 0 0.441666 0.222222 0 0.441666 0.277778 0 0.441666 0.333333 0 0.441666 0.388889 0 0.441666 0.444444 0 0.441666 0.500000 0 0.441666 0.555556 0 0.441666 0.611111 0 0.441666 0.666667 0 0.441666 0.722222 0 0.441666 0.777778 0 0.441666 0.833333 0 0.441666 0.888889 0 0.441666 0.944444 0 0.441666 1.000000 0 0.450000 0 0 0.450000 0.055556 0 0.450000 0.111111 0 0.450000 0.166667 0 0.450000 0.222222 0 0.450000 0.277778 0 0.450000 0.333333 0 0.450000 0.388889 0 0.450000 0.444444 0 0.450000 0.500000 0 0.450000 0.555556 0 0.450000 0.611111 0 0.450000 0.666667 0 0.450000 0.722222 0 0.450000 0.777778 0 0.450000 0.833333 0 0.450000 0.888889 0 0.450000 0.944444 0 0.450000 1.000000 0 0.458333 0 0 0.458333 0.055556 0 0.458333 0.111111 0 0.458333 0.166667 0 0.458333 0.222222 0 0.458333 0.277778 0 0.458333 0.333333 0 0.458333 0.388889 0 0.458333 0.444444 0 0.458333 0.500000 0 0.458333 0.555556 0 0.458333 0.611111 0 0.458333 0.666667 0 0.458333 0.722222 0 0.458333 0.777778 0 0.458333 0.833333 0 0.458333 0.888889 0 0.458333 0.944444 0 0.458333 1.000000 0 0.466666 0 0 0.466666 0.055556 0 0.466666 0.111111 0 0.466666 0.166667 0 0.466666 0.222222 0 0.466666 0.277778 0 0.466666 0.333333 0 0.466666 0.388889 0 0.466666 0.444444 0 0.466666 0.500000 0 0.466666 0.555556 0 0.466666 0.611111 0 0.466666 0.666667 0 0.466666 0.722222 0 0.466666 0.777778 0 0.466666 0.833333 0 0.466666 0.888889 0 0.466666 0.944444 0 0.466666 1.000000 0 0.475000 0 0 0.475000 0.055556 0 0.475000 0.111111 0 0.475000 0.166667 0 0.475000 0.222222 0 0.475000 0.277778 0 0.475000 0.333333 0 0.475000 0.388889 0 0.475000 0.444444 0 0.475000 0.500000 0 0.475000 0.555556 0 0.475000 0.611111 0 0.475000 0.666667 0 0.475000 0.722222 0 0.475000 0.777778 0 0.475000 0.833333 0 0.475000 0.888889 0 0.475000 0.944444 0 0.475000 1.000000 0 0.483333 0 0 0.483333 0.055556 0 0.483333 0.111111 0 0.483333 0.166667 0 0.483333 0.222222 0 0.483333 0.277778 0 0.483333 0.333333 0 0.483333 0.388889 0 0.483333 0.444444 0 0.483333 0.500000 0 0.483333 0.555556 0 0.483333 0.611111 0 0.483333 0.666667 0 0.483333 0.722222 0 0.483333 0.777778 0 0.483333 0.833333 0 0.483333 0.888889 0 0.483333 0.944444 0 0.483333 1.000000 0 0.491666 0 0 0.491666 0.055556 0 0.491666 0.111111 0 0.491666 0.166667 0 0.491666 0.222222 0 0.491666 0.277778 0 0.491666 0.333333 0 0.491666 0.388889 0 0.491666 0.444444 0 0.491666 0.500000 0 0.491666 0.555556 0 0.491666 0.611111 0 0.491666 0.666667 0 0.491666 0.722222 0 0.491666 0.777778 0 0.491666 0.833333 0 0.491666 0.888889 0 0.491666 0.944444 0 0.491666 1.000000 0 0.500000 0 0 0.500000 0.055556 0 0.500000 0.111111 0 0.500000 0.166667 0 0.500000 0.222222 0 0.500000 0.277778 0 0.500000 0.333333 0 0.500000 0.388889 0 0.500000 0.444444 0 0.500000 0.500000 0 0.500000 0.555556 0 0.500000 0.611111 0 0.500000 0.666667 0 0.500000 0.722222 0 0.500000 0.777778 0 0.500000 0.833333 0 0.500000 0.888889 0 0.500000 0.944444 0 0.500000 1.000000 0 0.508333 0 0 0.508333 0.055556 0 0.508333 0.111111 0 0.508333 0.166667 0 0.508333 0.222222 0 0.508333 0.277778 0 0.508333 0.333333 0 0.508333 0.388889 0 0.508333 0.444444 0 0.508333 0.500000 0 0.508333 0.555556 0 0.508333 0.611111 0 0.508333 0.666667 0 0.508333 0.722222 0 0.508333 0.777778 0 0.508333 0.833333 0 0.508333 0.888889 0 0.508333 0.944444 0 0.508333 1.000000 0 0.516666 0 0 0.516666 0.055556 0 0.516666 0.111111 0 0.516666 0.166667 0 0.516666 0.222222 0 0.516666 0.277778 0 0.516666 0.333333 0 0.516666 0.388889 0 0.516666 0.444444 0 0.516666 0.500000 0 0.516666 0.555556 0 0.516666 0.611111 0 0.516666 0.666667 0 0.516666 0.722222 0 0.516666 0.777778 0 0.516666 0.833333 0 0.516666 0.888889 0 0.516666 0.944444 0 0.516666 1.000000 0 0.525000 0 0 0.525000 0.055556 0 0.525000 0.111111 0 0.525000 0.166667 0 0.525000 0.222222 0 0.525000 0.277778 0 0.525000 0.333333 0 0.525000 0.388889 0 0.525000 0.444444 0 0.525000 0.500000 0 0.525000 0.555556 0 0.525000 0.611111 0 0.525000 0.666667 0 0.525000 0.722222 0 0.525000 0.777778 0 0.525000 0.833333 0 0.525000 0.888889 0 0.525000 0.944444 0 0.525000 1.000000 0 0.533333 0 0 0.533333 0.055556 0 0.533333 0.111111 0 0.533333 0.166667 0 0.533333 0.222222 0 0.533333 0.277778 0 0.533333 0.333333 0 0.533333 0.388889 0 0.533333 0.444444 0 0.533333 0.500000 0 0.533333 0.555556 0 0.533333 0.611111 0 0.533333 0.666667 0 0.533333 0.722222 0 0.533333 0.777778 0 0.533333 0.833333 0 0.533333 0.888889 0 0.533333 0.944444 0 0.533333 1.000000 0 0.541666 0 0 0.541666 0.055556 0 0.541666 0.111111 0 0.541666 0.166667 0 0.541666 0.222222 0 0.541666 0.277778 0 0.541666 0.333333 0 0.541666 0.388889 0 0.541666 0.444444 0 0.541666 0.500000 0 0.541666 0.555556 0 0.541666 0.611111 0 0.541666 0.666667 0 0.541666 0.722222 0 0.541666 0.777778 0 0.541666 0.833333 0 0.541666 0.888889 0 0.541666 0.944444 0 0.541666 1.000000 0 0.550000 0 0 0.550000 0.055556 0 0.550000 0.111111 0 0.550000 0.166667 0 0.550000 0.222222 0 0.550000 0.277778 0 0.550000 0.333333 0 0.550000 0.388889 0 0.550000 0.444444 0 0.550000 0.500000 0 0.550000 0.555556 0 0.550000 0.611111 0 0.550000 0.666667 0 0.550000 0.722222 0 0.550000 0.777778 0 0.550000 0.833333 0 0.550000 0.888889 0 0.550000 0.944444 0 0.550000 1.000000 0 0.558333 0 0 0.558333 0.055556 0 0.558333 0.111111 0 0.558333 0.166667 0 0.558333 0.222222 0 0.558333 0.277778 0 0.558333 0.333333 0 0.558333 0.388889 0 0.558333 0.444444 0 0.558333 0.500000 0 0.558333 0.555556 0 0.558333 0.611111 0 0.558333 0.666667 0 0.558333 0.722222 0 0.558333 0.777778 0 0.558333 0.833333 0 0.558333 0.888889 0 0.558333 0.944444 0 0.558333 1.000000 0 0.566666 0 0 0.566666 0.055556 0 0.566666 0.111111 0 0.566666 0.166667 0 0.566666 0.222222 0 0.566666 0.277778 0 0.566666 0.333333 0 0.566666 0.388889 0 0.566666 0.444444 0 0.566666 0.500000 0 0.566666 0.555556 0 0.566666 0.611111 0 0.566666 0.666667 0 0.566666 0.722222 0 0.566666 0.777778 0 0.566666 0.833333 0 0.566666 0.888889 0 0.566666 0.944444 0 0.566666 1.000000 0 0.575000 0 0 0.575000 0.055556 0 0.575000 0.111111 0 0.575000 0.166667 0 0.575000 0.222222 0 0.575000 0.277778 0 0.575000 0.333333 0 0.575000 0.388889 0 0.575000 0.444444 0 0.575000 0.500000 0 0.575000 0.555556 0 0.575000 0.611111 0 0.575000 0.666667 0 0.575000 0.722222 0 0.575000 0.777778 0 0.575000 0.833333 0 0.575000 0.888889 0 0.575000 0.944444 0 0.575000 1.000000 0 0.583333 0 0 0.583333 0.055556 0 0.583333 0.111111 0 0.583333 0.166667 0 0.583333 0.222222 0 0.583333 0.277778 0 0.583333 0.333333 0 0.583333 0.388889 0 0.583333 0.444444 0 0.583333 0.500000 0 0.583333 0.555556 0 0.583333 0.611111 0 0.583333 0.666667 0 0.583333 0.722222 0 0.583333 0.777778 0 0.583333 0.833333 0 0.583333 0.888889 0 0.583333 0.944444 0 0.583333 1.000000 0 0.591666 0 0 0.591666 0.055556 0 0.591666 0.111111 0 0.591666 0.166667 0 0.591666 0.222222 0 0.591666 0.277778 0 0.591666 0.333333 0 0.591666 0.388889 0 0.591666 0.444444 0 0.591666 0.500000 0 0.591666 0.555556 0 0.591666 0.611111 0 0.591666 0.666667 0 0.591666 0.722222 0 0.591666 0.777778 0 0.591666 0.833333 0 0.591666 0.888889 0 0.591666 0.944444 0 0.591666 1.000000 0 0.599999 0 0 0.599999 0.055556 0 0.599999 0.111111 0 0.599999 0.166667 0 0.599999 0.222222 0 0.599999 0.277778 0 0.599999 0.333333 0 0.599999 0.388889 0 0.599999 0.444444 0 0.599999 0.500000 0 0.599999 0.555556 0 0.599999 0.611111 0 0.599999 0.666667 0 0.599999 0.722222 0 0.599999 0.777778 0 0.599999 0.833333 0 0.599999 0.888889 0 0.599999 0.944444 0 0.599999 1.000000 0 0.608333 0 0 0.608333 0.055556 0 0.608333 0.111111 0 0.608333 0.166667 0 0.608333 0.222222 0 0.608333 0.277778 0 0.608333 0.333333 0 0.608333 0.388889 0 0.608333 0.444444 0 0.608333 0.500000 0 0.608333 0.555556 0 0.608333 0.611111 0 0.608333 0.666667 0 0.608333 0.722222 0 0.608333 0.777778 0 0.608333 0.833333 0 0.608333 0.888889 0 0.608333 0.944444 0 0.608333 1.000000 0 0.616666 0 0 0.616666 0.055556 0 0.616666 0.111111 0 0.616666 0.166667 0 0.616666 0.222222 0 0.616666 0.277778 0 0.616666 0.333333 0 0.616666 0.388889 0 0.616666 0.444444 0 0.616666 0.500000 0 0.616666 0.555556 0 0.616666 0.611111 0 0.616666 0.666667 0 0.616666 0.722222 0 0.616666 0.777778 0 0.616666 0.833333 0 0.616666 0.888889 0 0.616666 0.944444 0 0.616666 1.000000 0 0.624999 0 0 0.624999 0.055556 0 0.624999 0.111111 0 0.624999 0.166667 0 0.624999 0.222222 0 0.624999 0.277778 0 0.624999 0.333333 0 0.624999 0.388889 0 0.624999 0.444444 0 0.624999 0.500000 0 0.624999 0.555556 0 0.624999 0.611111 0 0.624999 0.666667 0 0.624999 0.722222 0 0.624999 0.777778 0 0.624999 0.833333 0 0.624999 0.888889 0 0.624999 0.944444 0 0.624999 1.000000 0 0.633333 0 0 0.633333 0.055556 0 0.633333 0.111111 0 0.633333 0.166667 0 0.633333 0.222222 0 0.633333 0.277778 0 0.633333 0.333333 0 0.633333 0.388889 0 0.633333 0.444444 0 0.633333 0.500000 0 0.633333 0.555556 0 0.633333 0.611111 0 0.633333 0.666667 0 0.633333 0.722222 0 0.633333 0.777778 0 0.633333 0.833333 0 0.633333 0.888889 0 0.633333 0.944444 0 0.633333 1.000000 0 0.641666 0 0 0.641666 0.055556 0 0.641666 0.111111 0 0.641666 0.166667 0 0.641666 0.222222 0 0.641666 0.277778 0 0.641666 0.333333 0 0.641666 0.388889 0 0.641666 0.444444 0 0.641666 0.500000 0 0.641666 0.555556 0 0.641666 0.611111 0 0.641666 0.666667 0 0.641666 0.722222 0 0.641666 0.777778 0 0.641666 0.833333 0 0.641666 0.888889 0 0.641666 0.944444 0 0.641666 1.000000 0 0.649999 0 0 0.649999 0.055556 0 0.649999 0.111111 0 0.649999 0.166667 0 0.649999 0.222222 0 0.649999 0.277778 0 0.649999 0.333333 0 0.649999 0.388889 0 0.649999 0.444444 0 0.649999 0.500000 0 0.649999 0.555556 0 0.649999 0.611111 0 0.649999 0.666667 0 0.649999 0.722222 0 0.649999 0.777778 0 0.649999 0.833333 0 0.649999 0.888889 0 0.649999 0.944444 0 0.649999 1.000000 0 0.658333 0 0 0.658333 0.055556 0 0.658333 0.111111 0 0.658333 0.166667 0 0.658333 0.222222 0 0.658333 0.277778 0 0.658333 0.333333 0 0.658333 0.388889 0 0.658333 0.444444 0 0.658333 0.500000 0 0.658333 0.555556 0 0.658333 0.611111 0 0.658333 0.666667 0 0.658333 0.722222 0 0.658333 0.777778 0 0.658333 0.833333 0 0.658333 0.888889 0 0.658333 0.944444 0 0.658333 1.000000 0 0.666666 0 0 0.666666 0.055556 0 0.666666 0.111111 0 0.666666 0.166667 0 0.666666 0.222222 0 0.666666 0.277778 0 0.666666 0.333333 0 0.666666 0.388889 0 0.666666 0.444444 0 0.666666 0.500000 0 0.666666 0.555556 0 0.666666 0.611111 0 0.666666 0.666667 0 0.666666 0.722222 0 0.666666 0.777778 0 0.666666 0.833333 0 0.666666 0.888889 0 0.666666 0.944444 0 0.666666 1.000000 0 0.675000 0 0 0.675000 0.055556 0 0.675000 0.111111 0 0.675000 0.166667 0 0.675000 0.222222 0 0.675000 0.277778 0 0.675000 0.333333 0 0.675000 0.388889 0 0.675000 0.444444 0 0.675000 0.500000 0 0.675000 0.555556 0 0.675000 0.611111 0 0.675000 0.666667 0 0.675000 0.722222 0 0.675000 0.777778 0 0.675000 0.833333 0 0.675000 0.888889 0 0.675000 0.944444 0 0.675000 1.000000 0 0.683333 0 0 0.683333 0.055556 0 0.683333 0.111111 0 0.683333 0.166667 0 0.683333 0.222222 0 0.683333 0.277778 0 0.683333 0.333333 0 0.683333 0.388889 0 0.683333 0.444444 0 0.683333 0.500000 0 0.683333 0.555556 0 0.683333 0.611111 0 0.683333 0.666667 0 0.683333 0.722222 0 0.683333 0.777778 0 0.683333 0.833333 0 0.683333 0.888889 0 0.683333 0.944444 0 0.683333 1.000000 0 0.691666 0 0 0.691666 0.055556 0 0.691666 0.111111 0 0.691666 0.166667 0 0.691666 0.222222 0 0.691666 0.277778 0 0.691666 0.333333 0 0.691666 0.388889 0 0.691666 0.444444 0 0.691666 0.500000 0 0.691666 0.555556 0 0.691666 0.611111 0 0.691666 0.666667 0 0.691666 0.722222 0 0.691666 0.777778 0 0.691666 0.833333 0 0.691666 0.888889 0 0.691666 0.944444 0 0.691666 1.000000 0 0.700000 0 0 0.700000 0.055556 0 0.700000 0.111111 0 0.700000 0.166667 0 0.700000 0.222222 0 0.700000 0.277778 0 0.700000 0.333333 0 0.700000 0.388889 0 0.700000 0.444444 0 0.700000 0.500000 0 0.700000 0.555556 0 0.700000 0.611111 0 0.700000 0.666667 0 0.700000 0.722222 0 0.700000 0.777778 0 0.700000 0.833333 0 0.700000 0.888889 0 0.700000 0.944444 0 0.700000 1.000000 0 0.708333 0 0 0.708333 0.055556 0 0.708333 0.111111 0 0.708333 0.166667 0 0.708333 0.222222 0 0.708333 0.277778 0 0.708333 0.333333 0 0.708333 0.388889 0 0.708333 0.444444 0 0.708333 0.500000 0 0.708333 0.555556 0 0.708333 0.611111 0 0.708333 0.666667 0 0.708333 0.722222 0 0.708333 0.777778 0 0.708333 0.833333 0 0.708333 0.888889 0 0.708333 0.944444 0 0.708333 1.000000 0 0.716666 0 0 0.716666 0.055556 0 0.716666 0.111111 0 0.716666 0.166667 0 0.716666 0.222222 0 0.716666 0.277778 0 0.716666 0.333333 0 0.716666 0.388889 0 0.716666 0.444444 0 0.716666 0.500000 0 0.716666 0.555556 0 0.716666 0.611111 0 0.716666 0.666667 0 0.716666 0.722222 0 0.716666 0.777778 0 0.716666 0.833333 0 0.716666 0.888889 0 0.716666 0.944444 0 0.716666 1.000000 0 0.725000 0 0 0.725000 0.055556 0 0.725000 0.111111 0 0.725000 0.166667 0 0.725000 0.222222 0 0.725000 0.277778 0 0.725000 0.333333 0 0.725000 0.388889 0 0.725000 0.444444 0 0.725000 0.500000 0 0.725000 0.555556 0 0.725000 0.611111 0 0.725000 0.666667 0 0.725000 0.722222 0 0.725000 0.777778 0 0.725000 0.833333 0 0.725000 0.888889 0 0.725000 0.944444 0 0.725000 1.000000 0 0.733333 0 0 0.733333 0.055556 0 0.733333 0.111111 0 0.733333 0.166667 0 0.733333 0.222222 0 0.733333 0.277778 0 0.733333 0.333333 0 0.733333 0.388889 0 0.733333 0.444444 0 0.733333 0.500000 0 0.733333 0.555556 0 0.733333 0.611111 0 0.733333 0.666667 0 0.733333 0.722222 0 0.733333 0.777778 0 0.733333 0.833333 0 0.733333 0.888889 0 0.733333 0.944444 0 0.733333 1.000000 0 0.741666 0 0 0.741666 0.055556 0 0.741666 0.111111 0 0.741666 0.166667 0 0.741666 0.222222 0 0.741666 0.277778 0 0.741666 0.333333 0 0.741666 0.388889 0 0.741666 0.444444 0 0.741666 0.500000 0 0.741666 0.555556 0 0.741666 0.611111 0 0.741666 0.666667 0 0.741666 0.722222 0 0.741666 0.777778 0 0.741666 0.833333 0 0.741666 0.888889 0 0.741666 0.944444 0 0.741666 1.000000 0 0.750000 0 0 0.750000 0.055556 0 0.750000 0.111111 0 0.750000 0.166667 0 0.750000 0.222222 0 0.750000 0.277778 0 0.750000 0.333333 0 0.750000 0.388889 0 0.750000 0.444444 0 0.750000 0.500000 0 0.750000 0.555556 0 0.750000 0.611111 0 0.750000 0.666667 0 0.750000 0.722222 0 0.750000 0.777778 0 0.750000 0.833333 0 0.750000 0.888889 0 0.750000 0.944444 0 0.750000 1.000000 0 0.758333 0 0 0.758333 0.055556 0 0.758333 0.111111 0 0.758333 0.166667 0 0.758333 0.222222 0 0.758333 0.277778 0 0.758333 0.333333 0 0.758333 0.388889 0 0.758333 0.444444 0 0.758333 0.500000 0 0.758333 0.555556 0 0.758333 0.611111 0 0.758333 0.666667 0 0.758333 0.722222 0 0.758333 0.777778 0 0.758333 0.833333 0 0.758333 0.888889 0 0.758333 0.944444 0 0.758333 1.000000 0 0.766667 0 0 0.766667 0.055556 0 0.766667 0.111111 0 0.766667 0.166667 0 0.766667 0.222222 0 0.766667 0.277778 0 0.766667 0.333333 0 0.766667 0.388889 0 0.766667 0.444444 0 0.766667 0.500000 0 0.766667 0.555556 0 0.766667 0.611111 0 0.766667 0.666667 0 0.766667 0.722222 0 0.766667 0.777778 0 0.766667 0.833333 0 0.766667 0.888889 0 0.766667 0.944444 0 0.766667 1.000000 0 0.775000 0 0 0.775000 0.055556 0 0.775000 0.111111 0 0.775000 0.166667 0 0.775000 0.222222 0 0.775000 0.277778 0 0.775000 0.333333 0 0.775000 0.388889 0 0.775000 0.444444 0 0.775000 0.500000 0 0.775000 0.555556 0 0.775000 0.611111 0 0.775000 0.666667 0 0.775000 0.722222 0 0.775000 0.777778 0 0.775000 0.833333 0 0.775000 0.888889 0 0.775000 0.944444 0 0.775000 1.000000 0 0.783333 0 0 0.783333 0.055556 0 0.783333 0.111111 0 0.783333 0.166667 0 0.783333 0.222222 0 0.783333 0.277778 0 0.783333 0.333333 0 0.783333 0.388889 0 0.783333 0.444444 0 0.783333 0.500000 0 0.783333 0.555556 0 0.783333 0.611111 0 0.783333 0.666667 0 0.783333 0.722222 0 0.783333 0.777778 0 0.783333 0.833333 0 0.783333 0.888889 0 0.783333 0.944444 0 0.783333 1.000000 0 0.791667 0 0 0.791667 0.055556 0 0.791667 0.111111 0 0.791667 0.166667 0 0.791667 0.222222 0 0.791667 0.277778 0 0.791667 0.333333 0 0.791667 0.388889 0 0.791667 0.444444 0 0.791667 0.500000 0 0.791667 0.555556 0 0.791667 0.611111 0 0.791667 0.666667 0 0.791667 0.722222 0 0.791667 0.777778 0 0.791667 0.833333 0 0.791667 0.888889 0 0.791667 0.944444 0 0.791667 1.000000 0 0.800000 0 0 0.800000 0.055556 0 0.800000 0.111111 0 0.800000 0.166667 0 0.800000 0.222222 0 0.800000 0.277778 0 0.800000 0.333333 0 0.800000 0.388889 0 0.800000 0.444444 0 0.800000 0.500000 0 0.800000 0.555556 0 0.800000 0.611111 0 0.800000 0.666667 0 0.800000 0.722222 0 0.800000 0.777778 0 0.800000 0.833333 0 0.800000 0.888889 0 0.800000 0.944444 0 0.800000 1.000000 0 0.808333 0 0 0.808333 0.055556 0 0.808333 0.111111 0 0.808333 0.166667 0 0.808333 0.222222 0 0.808333 0.277778 0 0.808333 0.333333 0 0.808333 0.388889 0 0.808333 0.444444 0 0.808333 0.500000 0 0.808333 0.555556 0 0.808333 0.611111 0 0.808333 0.666667 0 0.808333 0.722222 0 0.808333 0.777778 0 0.808333 0.833333 0 0.808333 0.888889 0 0.808333 0.944444 0 0.808333 1.000000 0 0.816667 0 0 0.816667 0.055556 0 0.816667 0.111111 0 0.816667 0.166667 0 0.816667 0.222222 0 0.816667 0.277778 0 0.816667 0.333333 0 0.816667 0.388889 0 0.816667 0.444444 0 0.816667 0.500000 0 0.816667 0.555556 0 0.816667 0.611111 0 0.816667 0.666667 0 0.816667 0.722222 0 0.816667 0.777778 0 0.816667 0.833333 0 0.816667 0.888889 0 0.816667 0.944444 0 0.816667 1.000000 0 0.825000 0 0 0.825000 0.055556 0 0.825000 0.111111 0 0.825000 0.166667 0 0.825000 0.222222 0 0.825000 0.277778 0 0.825000 0.333333 0 0.825000 0.388889 0 0.825000 0.444444 0 0.825000 0.500000 0 0.825000 0.555556 0 0.825000 0.611111 0 0.825000 0.666667 0 0.825000 0.722222 0 0.825000 0.777778 0 0.825000 0.833333 0 0.825000 0.888889 0 0.825000 0.944444 0 0.825000 1.000000 0 0.833333 0 0 0.833333 0.055556 0 0.833333 0.111111 0 0.833333 0.166667 0 0.833333 0.222222 0 0.833333 0.277778 0 0.833333 0.333333 0 0.833333 0.388889 0 0.833333 0.444444 0 0.833333 0.500000 0 0.833333 0.555556 0 0.833333 0.611111 0 0.833333 0.666667 0 0.833333 0.722222 0 0.833333 0.777778 0 0.833333 0.833333 0 0.833333 0.888889 0 0.833333 0.944444 0 0.833333 1.000000 0 0.841667 0 0 0.841667 0.055556 0 0.841667 0.111111 0 0.841667 0.166667 0 0.841667 0.222222 0 0.841667 0.277778 0 0.841667 0.333333 0 0.841667 0.388889 0 0.841667 0.444444 0 0.841667 0.500000 0 0.841667 0.555556 0 0.841667 0.611111 0 0.841667 0.666667 0 0.841667 0.722222 0 0.841667 0.777778 0 0.841667 0.833333 0 0.841667 0.888889 0 0.841667 0.944444 0 0.841667 1.000000 0 0.850000 0 0 0.850000 0.055556 0 0.850000 0.111111 0 0.850000 0.166667 0 0.850000 0.222222 0 0.850000 0.277778 0 0.850000 0.333333 0 0.850000 0.388889 0 0.850000 0.444444 0 0.850000 0.500000 0 0.850000 0.555556 0 0.850000 0.611111 0 0.850000 0.666667 0 0.850000 0.722222 0 0.850000 0.777778 0 0.850000 0.833333 0 0.850000 0.888889 0 0.850000 0.944444 0 0.850000 1.000000 0 0.858334 0 0 0.858334 0.055556 0 0.858334 0.111111 0 0.858334 0.166667 0 0.858334 0.222222 0 0.858334 0.277778 0 0.858334 0.333333 0 0.858334 0.388889 0 0.858334 0.444444 0 0.858334 0.500000 0 0.858334 0.555556 0 0.858334 0.611111 0 0.858334 0.666667 0 0.858334 0.722222 0 0.858334 0.777778 0 0.858334 0.833333 0 0.858334 0.888889 0 0.858334 0.944444 0 0.858334 1.000000 0 0.866667 0 0 0.866667 0.055556 0 0.866667 0.111111 0 0.866667 0.166667 0 0.866667 0.222222 0 0.866667 0.277778 0 0.866667 0.333333 0 0.866667 0.388889 0 0.866667 0.444444 0 0.866667 0.500000 0 0.866667 0.555556 0 0.866667 0.611111 0 0.866667 0.666667 0 0.866667 0.722222 0 0.866667 0.777778 0 0.866667 0.833333 0 0.866667 0.888889 0 0.866667 0.944444 0 0.866667 1.000000 0 0.875000 0 0 0.875000 0.055556 0 0.875000 0.111111 0 0.875000 0.166667 0 0.875000 0.222222 0 0.875000 0.277778 0 0.875000 0.333333 0 0.875000 0.388889 0 0.875000 0.444444 0 0.875000 0.500000 0 0.875000 0.555556 0 0.875000 0.611111 0 0.875000 0.666667 0 0.875000 0.722222 0 0.875000 0.777778 0 0.875000 0.833333 0 0.875000 0.888889 0 0.875000 0.944444 0 0.875000 1.000000 0 0.883334 0 0 0.883334 0.055556 0 0.883334 0.111111 0 0.883334 0.166667 0 0.883334 0.222222 0 0.883334 0.277778 0 0.883334 0.333333 0 0.883334 0.388889 0 0.883334 0.444444 0 0.883334 0.500000 0 0.883334 0.555556 0 0.883334 0.611111 0 0.883334 0.666667 0 0.883334 0.722222 0 0.883334 0.777778 0 0.883334 0.833333 0 0.883334 0.888889 0 0.883334 0.944444 0 0.883334 1.000000 0 0.891667 0 0 0.891667 0.055556 0 0.891667 0.111111 0 0.891667 0.166667 0 0.891667 0.222222 0 0.891667 0.277778 0 0.891667 0.333333 0 0.891667 0.388889 0 0.891667 0.444444 0 0.891667 0.500000 0 0.891667 0.555556 0 0.891667 0.611111 0 0.891667 0.666667 0 0.891667 0.722222 0 0.891667 0.777778 0 0.891667 0.833333 0 0.891667 0.888889 0 0.891667 0.944444 0 0.891667 1.000000 0 0.900000 0 0 0.900000 0.055556 0 0.900000 0.111111 0 0.900000 0.166667 0 0.900000 0.222222 0 0.900000 0.277778 0 0.900000 0.333333 0 0.900000 0.388889 0 0.900000 0.444444 0 0.900000 0.500000 0 0.900000 0.555556 0 0.900000 0.611111 0 0.900000 0.666667 0 0.900000 0.722222 0 0.900000 0.777778 0 0.900000 0.833333 0 0.900000 0.888889 0 0.900000 0.944444 0 0.900000 1.000000 0 0.908334 0 0 0.908334 0.055556 0 0.908334 0.111111 0 0.908334 0.166667 0 0.908334 0.222222 0 0.908334 0.277778 0 0.908334 0.333333 0 0.908334 0.388889 0 0.908334 0.444444 0 0.908334 0.500000 0 0.908334 0.555556 0 0.908334 0.611111 0 0.908334 0.666667 0 0.908334 0.722222 0 0.908334 0.777778 0 0.908334 0.833333 0 0.908334 0.888889 0 0.908334 0.944444 0 0.908334 1.000000 0 0.916667 0 0 0.916667 0.055556 0 0.916667 0.111111 0 0.916667 0.166667 0 0.916667 0.222222 0 0.916667 0.277778 0 0.916667 0.333333 0 0.916667 0.388889 0 0.916667 0.444444 0 0.916667 0.500000 0 0.916667 0.555556 0 0.916667 0.611111 0 0.916667 0.666667 0 0.916667 0.722222 0 0.916667 0.777778 0 0.916667 0.833333 0 0.916667 0.888889 0 0.916667 0.944444 0 0.916667 1.000000 0 0.925000 0 0 0.925000 0.055556 0 0.925000 0.111111 0 0.925000 0.166667 0 0.925000 0.222222 0 0.925000 0.277778 0 0.925000 0.333333 0 0.925000 0.388889 0 0.925000 0.444444 0 0.925000 0.500000 0 0.925000 0.555556 0 0.925000 0.611111 0 0.925000 0.666667 0 0.925000 0.722222 0 0.925000 0.777778 0 0.925000 0.833333 0 0.925000 0.888889 0 0.925000 0.944444 0 0.925000 1.000000 0 0.933334 0 0 0.933334 0.055556 0 0.933334 0.111111 0 0.933334 0.166667 0 0.933334 0.222222 0 0.933334 0.277778 0 0.933334 0.333333 0 0.933334 0.388889 0 0.933334 0.444444 0 0.933334 0.500000 0 0.933334 0.555556 0 0.933334 0.611111 0 0.933334 0.666667 0 0.933334 0.722222 0 0.933334 0.777778 0 0.933334 0.833333 0 0.933334 0.888889 0 0.933334 0.944444 0 0.933334 1.000000 0 0.941667 0 0 0.941667 0.055556 0 0.941667 0.111111 0 0.941667 0.166667 0 0.941667 0.222222 0 0.941667 0.277778 0 0.941667 0.333333 0 0.941667 0.388889 0 0.941667 0.444444 0 0.941667 0.500000 0 0.941667 0.555556 0 0.941667 0.611111 0 0.941667 0.666667 0 0.941667 0.722222 0 0.941667 0.777778 0 0.941667 0.833333 0 0.941667 0.888889 0 0.941667 0.944444 0 0.941667 1.000000 0 0.950001 0 0 0.950001 0.055556 0 0.950001 0.111111 0 0.950001 0.166667 0 0.950001 0.222222 0 0.950001 0.277778 0 0.950001 0.333333 0 0.950001 0.388889 0 0.950001 0.444444 0 0.950001 0.500000 0 0.950001 0.555556 0 0.950001 0.611111 0 0.950001 0.666667 0 0.950001 0.722222 0 0.950001 0.777778 0 0.950001 0.833333 0 0.950001 0.888889 0 0.950001 0.944444 0 0.950001 1.000000 0 0.958334 0 0 0.958334 0.055556 0 0.958334 0.111111 0 0.958334 0.166667 0 0.958334 0.222222 0 0.958334 0.277778 0 0.958334 0.333333 0 0.958334 0.388889 0 0.958334 0.444444 0 0.958334 0.500000 0 0.958334 0.555556 0 0.958334 0.611111 0 0.958334 0.666667 0 0.958334 0.722222 0 0.958334 0.777778 0 0.958334 0.833333 0 0.958334 0.888889 0 0.958334 0.944444 0 0.958334 1.000000 0 0.966667 0 0 0.966667 0.055556 0 0.966667 0.111111 0 0.966667 0.166667 0 0.966667 0.222222 0 0.966667 0.277778 0 0.966667 0.333333 0 0.966667 0.388889 0 0.966667 0.444444 0 0.966667 0.500000 0 0.966667 0.555556 0 0.966667 0.611111 0 0.966667 0.666667 0 0.966667 0.722222 0 0.966667 0.777778 0 0.966667 0.833333 0 0.966667 0.888889 0 0.966667 0.944444 0 0.966667 1.000000 0 0.975001 0 0 0.975001 0.055556 0 0.975001 0.111111 0 0.975001 0.166667 0 0.975001 0.222222 0 0.975001 0.277778 0 0.975001 0.333333 0 0.975001 0.388889 0 0.975001 0.444444 0 0.975001 0.500000 0 0.975001 0.555556 0 0.975001 0.611111 0 0.975001 0.666667 0 0.975001 0.722222 0 0.975001 0.777778 0 0.975001 0.833333 0 0.975001 0.888889 0 0.975001 0.944444 0 0.975001 1.000000 0 0.983334 0 0 0.983334 0.055556 0 0.983334 0.111111 0 0.983334 0.166667 0 0.983334 0.222222 0 0.983334 0.277778 0 0.983334 0.333333 0 0.983334 0.388889 0 0.983334 0.444444 0 0.983334 0.500000 0 0.983334 0.555556 0 0.983334 0.611111 0 0.983334 0.666667 0 0.983334 0.722222 0 0.983334 0.777778 0 0.983334 0.833333 0 0.983334 0.888889 0 0.983334 0.944444 0 0.983334 1.000000 0 0.991667 0 0 0.991667 0.055556 0 0.991667 0.111111 0 0.991667 0.166667 0 0.991667 0.222222 0 0.991667 0.277778 0 0.991667 0.333333 0 0.991667 0.388889 0 0.991667 0.444444 0 0.991667 0.500000 0 0.991667 0.555556 0 0.991667 0.611111 0 0.991667 0.666667 0 0.991667 0.722222 0 0.991667 0.777778 0 0.991667 0.833333 0 0.991667 0.888889 0 0.991667 0.944444 0 0.991667 1.000000 0 1.000001 0 0 1.000001 0.055556 0 1.000001 0.111111 0 1.000001 0.166667 0 1.000001 0.222222 0 1.000001 0.277778 0 1.000001 0.333333 0 1.000001 0.388889 0 1.000001 0.444444 0 1.000001 0.500000 0 1.000001 0.555556 0 1.000001 0.611111 0 1.000001 0.666667 0 1.000001 0.722222 0 1.000001 0.777778 0 1.000001 0.833333 0 1.000001 0.888889 0 1.000001 0.944444 0 1.000001 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="2299" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="4320">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 18 1 19 19 2 20 0 0 0 19 2 20 1 3 1 1 3 1 19 2 20 20 4 21 1 3 1 20 4 21 2 5 2 2 5 2 20 4 21 21 6 22 2 5 2 21 6 22 3 7 3 3 7 3 21 6 22 22 8 23 3 7 3 22 8 23 4 9 4 4 9 4 22 8 23 23 10 24 4 9 4 23 10 24 5 11 5 5 11 5 23 10 24 24 12 25 5 11 5 24 12 25 6 13 6 6 13 6 24 12 25 25 14 26 6 13 6 25 14 26 7 15 7 7 15 7 25 14 26 26 16 27 7 15 7 26 16 27 8 17 8 8 17 8 26 16 27 27 18 28 8 17 8 27 18 28 9 19 9 9 19 9 27 18 28 28 20 29 9 19 9 28 20 29 10 21 10 10 21 10 28 20 29 29 22 30 10 21 10 29 22 30 11 23 11 11 23 11 29 22 30 30 24 31 11 23 11 30 24 31 12 25 12 12 25 12 30 24 31 31 26 32 12 25 12 31 26 32 13 27 13 13 27 13 31 26 32 32 28 33 13 27 13 32 28 33 14 29 14 14 29 14 32 28 33 33 30 34 14 29 14 33 30 34 15 31 15 15 31 15 33 30 34 34 32 35 15 31 15 34 32 35 16 33 16 16 33 16 34 32 35 35 34 36 16 33 16 35 34 36 17 35 17 17 35 17 35 34 36 18 1 37 17 35 17 18 1 37 0 0 18 18 1 19 36 36 38 37 37 39 18 1 19 37 37 39 19 2 20 19 2 20 37 37 39 38 38 40 19 2 20 38 38 40 20 4 21 20 4 21 38 38 40 39 39 41 20 4 21 39 39 41 21 6 22 21 6 22 39 39 41 40 40 42 21 6 22 40 40 42 22 8 23 22 8 23 40 40 42 41 41 43 22 8 23 41 41 43 23 10 24 23 10 24 41 41 43 42 42 44 23 10 24 42 42 44 24 12 25 24 12 25 42 42 44 43 43 45 24 12 25 43 43 45 25 14 26 25 14 26 43 43 45 44 44 46 25 14 26 44 44 46 26 16 27 26 16 27 44 44 46 45 45 47 26 16 27 45 45 47 27 18 28 27 18 28 45 45 47 46 46 48 27 18 28 46 46 48 28 20 29 28 20 29 46 46 48 47 47 49 28 20 29 47 47 49 29 22 30 29 22 30 47 47 49 48 48 50 29 22 30 48 48 50 30 24 31 30 24 31 48 48 50 49 49 51 30 24 31 49 49 51 31 26 32 31 26 32 49 49 51 50 50 52 31 26 32 50 50 52 32 28 33 32 28 33 50 50 52 51 51 53 32 28 33 51 51 53 33 30 34 33 30 34 51 51 53 52 52 54 33 30 34 52 52 54 34 32 35 34 32 35 52 52 54 53 53 55 34 32 35 53 53 55 35 34 36 35 34 36 53 53 55 36 36 56 35 34 36 36 36 56 18 1 37 36 36 38 54 54 57 55 55 58 36 36 38 55 55 58 37 37 39 37 37 39 55 55 58 56 56 59 37 37 39 56 56 59 38 38 40 38 38 40 56 56 59 57 57 60 38 38 40 57 57 60 39 39 41 39 39 41 57 57 60 58 58 61 39 39 41 58 58 61 40 40 42 40 40 42 58 58 61 59 59 62 40 40 42 59 59 62 41 41 43 41 41 43 59 59 62 60 60 63 41 41 43 60 60 63 42 42 44 42 42 44 60 60 63 61 61 64 42 42 44 61 61 64 43 43 45 43 43 45 61 61 64 62 62 65 43 43 45 62 62 65 44 44 46 44 44 46 62 62 65 63 63 66 44 44 46 63 63 66 45 45 47 45 45 47 63 63 66 64 64 67 45 45 47 64 64 67 46 46 48 46 46 48 64 64 67 65 65 68 46 46 48 65 65 68 47 47 49 47 47 49 65 65 68 66 66 69 47 47 49 66 66 69 48 48 50 48 48 50 66 66 69 67 67 70 48 48 50 67 67 70 49 49 51 49 49 51 67 67 70 68 68 71 49 49 51 68 68 71 50 50 52 50 50 52 68 68 71 69 69 72 50 50 52 69 69 72 51 51 53 51 51 53 69 69 72 70 70 73 51 51 53 70 70 73 52 52 54 52 52 54 70 70 73 71 71 74 52 52 54 71 71 74 53 53 55 53 53 55 71 71 74 54 54 75 53 53 55 54 54 75 36 36 56 54 54 57 72 72 76 73 73 77 54 54 57 73 73 77 55 55 58 55 55 58 73 73 77 74 74 78 55 55 58 74 74 78 56 56 59 56 56 59 74 74 78 75 75 79 56 56 59 75 75 79 57 57 60 57 57 60 75 75 79 76 76 80 57 57 60 76 76 80 58 58 61 58 58 61 76 76 80 77 77 81 58 58 61 77 77 81 59 59 62 59 59 62 77 77 81 78 78 82 59 59 62 78 78 82 60 60 63 60 60 63 78 78 82 79 79 83 60 60 63 79 79 83 61 61 64 61 61 64 79 79 83 80 80 84 61 61 64 80 80 84 62 62 65 62 62 65 80 80 84 81 81 85 62 62 65 81 81 85 63 63 66 63 63 66 81 81 85 82 82 86 63 63 66 82 82 86 64 64 67 64 64 67 82 82 86 83 83 87 64 64 67 83 83 87 65 65 68 65 65 68 83 83 87 84 84 88 65 65 68 84 84 88 66 66 69 66 66 69 84 84 88 85 85 89 66 66 69 85 85 89 67 67 70 67 67 70 85 85 89 86 86 90 67 67 70 86 86 90 68 68 71 68 68 71 86 86 90 87 87 91 68 68 71 87 87 91 69 69 72 69 69 72 87 87 91 88 88 92 69 69 72 88 88 92 70 70 73 70 70 73 88 88 92 89 89 93 70 70 73 89 89 93 71 71 74 71 71 74 89 89 93 72 72 94 71 71 74 72 72 94 54 54 75 72 72 76 90 90 95 91 91 96 72 72 76 91 91 96 73 73 77 73 73 77 91 91 96 92 92 97 73 73 77 92 92 97 74 74 78 74 74 78 92 92 97 93 93 98 74 74 78 93 93 98 75 75 79 75 75 79 93 93 98 94 94 99 75 75 79 94 94 99 76 76 80 76 76 80 94 94 99 95 95 100 76 76 80 95 95 100 77 77 81 77 77 81 95 95 100 96 96 101 77 77 81 96 96 101 78 78 82 78 78 82 96 96 101 97 97 102 78 78 82 97 97 102 79 79 83 79 79 83 97 97 102 98 98 103 79 79 83 98 98 103 80 80 84 80 80 84 98 98 103 99 99 104 80 80 84 99 99 104 81 81 85 81 81 85 99 99 104 100 100 105 81 81 85 100 100 105 82 82 86 82 82 86 100 100 105 101 101 106 82 82 86 101 101 106 83 83 87 83 83 87 101 101 106 102 102 107 83 83 87 102 102 107 84 84 88 84 84 88 102 102 107 103 103 108 84 84 88 103 103 108 85 85 89 85 85 89 103 103 108 104 104 109 85 85 89 104 104 109 86 86 90 86 86 90 104 104 109 105 105 110 86 86 90 105 105 110 87 87 91 87 87 91 105 105 110 106 106 111 87 87 91 106 106 111 88 88 92 88 88 92 106 106 111 107 107 112 88 88 92 107 107 112 89 89 93 89 89 93 107 107 112 90 90 113 89 89 93 90 90 113 72 72 94 90 90 95 108 108 114 109 109 115 90 90 95 109 109 115 91 91 96 91 91 96 109 109 115 110 110 116 91 91 96 110 110 116 92 92 97 92 92 97 110 110 116 111 111 117 92 92 97 111 111 117 93 93 98 93 93 98 111 111 117 112 112 118 93 93 98 112 112 118 94 94 99 94 94 99 112 112 118 113 113 119 94 94 99 113 113 119 95 95 100 95 95 100 113 113 119 114 114 120 95 95 100 114 114 120 96 96 101 96 96 101 114 114 120 115 115 121 96 96 101 115 115 121 97 97 102 97 97 102 115 115 121 116 116 122 97 97 102 116 116 122 98 98 103 98 98 103 116 116 122 117 117 123 98 98 103 117 117 123 99 99 104 99 99 104 117 117 123 118 118 124 99 99 104 118 118 124 100 100 105 100 100 105 118 118 124 119 119 125 100 100 105 119 119 125 101 101 106 101 101 106 119 119 125 120 120 126 101 101 106 120 120 126 102 102 107 102 102 107 120 120 126 121 121 127 102 102 107 121 121 127 103 103 108 103 103 108 121 121 127 122 122 128 103 103 108 122 122 128 104 104 109 104 104 109 122 122 128 123 123 129 104 104 109 123 123 129 105 105 110 105 105 110 123 123 129 124 124 130 105 105 110 124 124 130 106 106 111 106 106 111 124 124 130 125 125 131 106 106 111 125 125 131 107 107 112 107 107 112 125 125 131 108 108 132 107 107 112 108 108 132 90 90 113 108 108 114 126 126 133 127 127 134 108 108 114 127 127 134 109 109 115 109 109 115 127 127 134 128 128 135 109 109 115 128 128 135 110 110 116 110 110 116 128 128 135 129 129 136 110 110 116 129 129 136 111 111 117 111 111 117 129 129 136 130 130 137 111 111 117 130 130 137 112 112 118 112 112 118 130 130 137 131 131 138 112 112 118 131 131 138 113 113 119 113 113 119 131 131 138 132 132 139 113 113 119 132 132 139 114 114 120 114 114 120 132 132 139 133 133 140 114 114 120 133 133 140 115 115 121 115 115 121 133 133 140 134 134 141 115 115 121 134 134 141 116 116 122 116 116 122 134 134 141 135 135 142 116 116 122 135 135 142 117 117 123 117 117 123 135 135 142 136 136 143 117 117 123 136 136 143 118 118 124 118 118 124 136 136 143 137 137 144 118 118 124 137 137 144 119 119 125 119 119 125 137 137 144 138 138 145 119 119 125 138 138 145 120 120 126 120 120 126 138 138 145 139 139 146 120 120 126 139 139 146 121 121 127 121 121 127 139 139 146 140 140 147 121 121 127 140 140 147 122 122 128 122 122 128 140 140 147 141 141 148 122 122 128 141 141 148 123 123 129 123 123 129 141 141 148 142 142 149 123 123 129 142 142 149 124 124 130 124 124 130 142 142 149 143 143 150 124 124 130 143 143 150 125 125 131 125 125 131 143 143 150 126 126 151 125 125 131 126 126 151 108 108 132 126 126 133 144 144 152 145 145 153 126 126 133 145 145 153 127 127 134 127 127 134 145 145 153 146 146 154 127 127 134 146 146 154 128 128 135 128 128 135 146 146 154 147 147 155 128 128 135 147 147 155 129 129 136 129 129 136 147 147 155 148 148 156 129 129 136 148 148 156 130 130 137 130 130 137 148 148 156 149 149 157 130 130 137 149 149 157 131 131 138 131 131 138 149 149 157 150 150 158 131 131 138 150 150 158 132 132 139 132 132 139 150 150 158 151 151 159 132 132 139 151 151 159 133 133 140 133 133 140 151 151 159 152 152 160 133 133 140 152 152 160 134 134 141 134 134 141 152 152 160 153 153 161 134 134 141 153 153 161 135 135 142 135 135 142 153 153 161 154 154 162 135 135 142 154 154 162 136 136 143 136 136 143 154 154 162 155 155 163 136 136 143 155 155 163 137 137 144 137 137 144 155 155 163 156 156 164 137 137 144 156 156 164 138 138 145 138 138 145 156 156 164 157 157 165 138 138 145 157 157 165 139 139 146 139 139 146 157 157 165 158 158 166 139 139 146 158 158 166 140 140 147 140 140 147 158 158 166 159 159 167 140 140 147 159 159 167 141 141 148 141 141 148 159 159 167 160 160 168 141 141 148 160 160 168 142 142 149 142 142 149 160 160 168 161 161 169 142 142 149 161 161 169 143 143 150 143 143 150 161 161 169 144 144 170 143 143 150 144 144 170 126 126 151 144 144 152 162 162 171 163 163 172 144 144 152 163 163 172 145 145 153 145 145 153 163 163 172 164 164 173 145 145 153 164 164 173 146 146 154 146 146 154 164 164 173 165 165 174 146 146 154 165 165 174 147 147 155 147 147 155 165 165 174 166 166 175 147 147 155 166 166 175 148 148 156 148 148 156 166 166 175 167 167 176 148 148 156 167 167 176 149 149 157 149 149 157 167 167 176 168 168 177 149 149 157 168 168 177 150 150 158 150 150 158 168 168 177 169 169 178 150 150 158 169 169 178 151 151 159 151 151 159 169 169 178 170 170 179 151 151 159 170 170 179 152 152 160 152 152 160 170 170 179 171 171 180 152 152 160 171 171 180 153 153 161 153 153 161 171 171 180 172 172 181 153 153 161 172 172 181 154 154 162 154 154 162 172 172 181 173 173 182 154 154 162 173 173 182 155 155 163 155 155 163 173 173 182 174 174 183 155 155 163 174 174 183 156 156 164 156 156 164 174 174 183 175 175 184 156 156 164 175 175 184 157 157 165 157 157 165 175 175 184 176 176 185 157 157 165 176 176 185 158 158 166 158 158 166 176 176 185 177 177 186 158 158 166 177 177 186 159 159 167 159 159 167 177 177 186 178 178 187 159 159 167 178 178 187 160 160 168 160 160 168 178 178 187 179 179 188 160 160 168 179 179 188 161 161 169 161 161 169 179 179 188 162 162 189 161 161 169 162 162 189 144 144 170 162 162 171 180 180 190 181 181 191 162 162 171 181 181 191 163 163 172 163 163 172 181 181 191 182 182 192 163 163 172 182 182 192 164 164 173 164 164 173 182 182 192 183 183 193 164 164 173 183 183 193 165 165 174 165 165 174 183 183 193 184 184 194 165 165 174 184 184 194 166 166 175 166 166 175 184 184 194 185 185 195 166 166 175 185 185 195 167 167 176 167 167 176 185 185 195 186 186 196 167 167 176 186 186 196 168 168 177 168 168 177 186 186 196 187 187 197 168 168 177 187 187 197 169 169 178 169 169 178 187 187 197 188 188 198 169 169 178 188 188 198 170 170 179 170 170 179 188 188 198 189 189 199 170 170 179 189 189 199 171 171 180 171 171 180 189 189 199 190 190 200 171 171 180 190 190 200 172 172 181 172 172 181 190 190 200 191 191 201 172 172 181 191 191 201 173 173 182 173 173 182 191 191 201 192 192 202 173 173 182 192 192 202 174 174 183 174 174 183 192 192 202 193 193 203 174 174 183 193 193 203 175 175 184 175 175 184 193 193 203 194 194 204 175 175 184 194 194 204 176 176 185 176 176 185 194 194 204 195 195 205 176 176 185 195 195 205 177 177 186 177 177 186 195 195 205 196 196 206 177 177 186 196 196 206 178 178 187 178 178 187 196 196 206 197 197 207 178 178 187 197 197 207 179 179 188 179 179 188 197 197 207 180 180 208 179 179 188 180 180 208 162 162 189 180 180 190 198 198 209 199 199 210 180 180 190 199 199 210 181 181 191 181 181 191 199 199 210 200 200 211 181 181 191 200 200 211 182 182 192 182 182 192 200 200 211 201 201 212 182 182 192 201 201 212 183 183 193 183 183 193 201 201 212 202 202 213 183 183 193 202 202 213 184 184 194 184 184 194 202 202 213 203 203 214 184 184 194 203 203 214 185 185 195 185 185 195 203 203 214 204 204 215 185 185 195 204 204 215 186 186 196 186 186 196 204 204 215 205 205 216 186 186 196 205 205 216 187 187 197 187 187 197 205 205 216 206 206 217 187 187 197 206 206 217 188 188 198 188 188 198 206 206 217 207 207 218 188 188 198 207 207 218 189 189 199 189 189 199 207 207 218 208 208 219 189 189 199 208 208 219 190 190 200 190 190 200 208 208 219 209 209 220 190 190 200 209 209 220 191 191 201 191 191 201 209 209 220 210 210 221 191 191 201 210 210 221 192 192 202 192 192 202 210 210 221 211 211 222 192 192 202 211 211 222 193 193 203 193 193 203 211 211 222 212 212 223 193 193 203 212 212 223 194 194 204 194 194 204 212 212 223 213 213 224 194 194 204 213 213 224 195 195 205 195 195 205 213 213 224 214 214 225 195 195 205 214 214 225 196 196 206 196 196 206 214 214 225 215 215 226 196 196 206 215 215 226 197 197 207 197 197 207 215 215 226 198 198 227 197 197 207 198 198 227 180 180 208 198 198 209 216 216 228 217 217 229 198 198 209 217 217 229 199 199 210 199 199 210 217 217 229 218 218 230 199 199 210 218 218 230 200 200 211 200 200 211 218 218 230 219 219 231 200 200 211 219 219 231 201 201 212 201 201 212 219 219 231 220 220 232 201 201 212 220 220 232 202 202 213 202 202 213 220 220 232 221 221 233 202 202 213 221 221 233 203 203 214 203 203 214 221 221 233 222 222 234 203 203 214 222 222 234 204 204 215 204 204 215 222 222 234 223 223 235 204 204 215 223 223 235 205 205 216 205 205 216 223 223 235 224 224 236 205 205 216 224 224 236 206 206 217 206 206 217 224 224 236 225 225 237 206 206 217 225 225 237 207 207 218 207 207 218 225 225 237 226 226 238 207 207 218 226 226 238 208 208 219 208 208 219 226 226 238 227 227 239 208 208 219 227 227 239 209 209 220 209 209 220 227 227 239 228 228 240 209 209 220 228 228 240 210 210 221 210 210 221 228 228 240 229 229 241 210 210 221 229 229 241 211 211 222 211 211 222 229 229 241 230 230 242 211 211 222 230 230 242 212 212 223 212 212 223 230 230 242 231 231 243 212 212 223 231 231 243 213 213 224 213 213 224 231 231 243 232 232 244 213 213 224 232 232 244 214 214 225 214 214 225 232 232 244 233 233 245 214 214 225 233 233 245 215 215 226 215 215 226 233 233 245 216 216 246 215 215 226 216 216 246 198 198 227 216 216 228 234 234 247 235 235 248 216 216 228 235 235 248 217 217 229 217 217 229 235 235 248 236 236 249 217 217 229 236 236 249 218 218 230 218 218 230 236 236 249 237 237 250 218 218 230 237 237 250 219 219 231 219 219 231 237 237 250 238 238 251 219 219 231 238 238 251 220 220 232 220 220 232 238 238 251 239 239 252 220 220 232 239 239 252 221 221 233 221 221 233 239 239 252 240 240 253 221 221 233 240 240 253 222 222 234 222 222 234 240 240 253 241 241 254 222 222 234 241 241 254 223 223 235 223 223 235 241 241 254 242 242 255 223 223 235 242 242 255 224 224 236 224 224 236 242 242 255 243 243 256 224 224 236 243 243 256 225 225 237 225 225 237 243 243 256 244 244 257 225 225 237 244 244 257 226 226 238 226 226 238 244 244 257 245 245 258 226 226 238 245 245 258 227 227 239 227 227 239 245 245 258 246 246 259 227 227 239 246 246 259 228 228 240 228 228 240 246 246 259 247 247 260 228 228 240 247 247 260 229 229 241 229 229 241 247 247 260 248 248 261 229 229 241 248 248 261 230 230 242 230 230 242 248 248 261 249 249 262 230 230 242 249 249 262 231 231 243 231 231 243 249 249 262 250 250 263 231 231 243 250 250 263 232 232 244 232 232 244 250 250 263 251 251 264 232 232 244 251 251 264 233 233 245 233 233 245 251 251 264 234 234 265 233 233 245 234 234 265 216 216 246 234 234 247 252 252 266 253 253 267 234 234 247 253 253 267 235 235 248 235 235 248 253 253 267 254 254 268 235 235 248 254 254 268 236 236 249 236 236 249 254 254 268 255 255 269 236 236 249 255 255 269 237 237 250 237 237 250 255 255 269 256 256 270 237 237 250 256 256 270 238 238 251 238 238 251 256 256 270 257 257 271 238 238 251 257 257 271 239 239 252 239 239 252 257 257 271 258 258 272 239 239 252 258 258 272 240 240 253 240 240 253 258 258 272 259 259 273 240 240 253 259 259 273 241 241 254 241 241 254 259 259 273 260 260 274 241 241 254 260 260 274 242 242 255 242 242 255 260 260 274 261 261 275 242 242 255 261 261 275 243 243 256 243 243 256 261 261 275 262 262 276 243 243 256 262 262 276 244 244 257 244 244 257 262 262 276 263 263 277 244 244 257 263 263 277 245 245 258 245 245 258 263 263 277 264 264 278 245 245 258 264 264 278 246 246 259 246 246 259 264 264 278 265 265 279 246 246 259 265 265 279 247 247 260 247 247 260 265 265 279 266 266 280 247 247 260 266 266 280 248 248 261 248 248 261 266 266 280 267 267 281 248 248 261 267 267 281 249 249 262 249 249 262 267 267 281 268 268 282 249 249 262 268 268 282 250 250 263 250 250 263 268 268 282 269 269 283 250 250 263 269 269 283 251 251 264 251 251 264 269 269 283 252 252 284 251 251 264 252 252 284 234 234 265 252 252 266 270 270 285 271 271 286 252 252 266 271 271 286 253 253 267 253 253 267 271 271 286 272 272 287 253 253 267 272 272 287 254 254 268 254 254 268 272 272 287 273 273 288 254 254 268 273 273 288 255 255 269 255 255 269 273 273 288 274 274 289 255 255 269 274 274 289 256 256 270 256 256 270 274 274 289 275 275 290 256 256 270 275 275 290 257 257 271 257 257 271 275 275 290 276 276 291 257 257 271 276 276 291 258 258 272 258 258 272 276 276 291 277 277 292 258 258 272 277 277 292 259 259 273 259 259 273 277 277 292 278 278 293 259 259 273 278 278 293 260 260 274 260 260 274 278 278 293 279 279 294 260 260 274 279 279 294 261 261 275 261 261 275 279 279 294 280 280 295 261 261 275 280 280 295 262 262 276 262 262 276 280 280 295 281 281 296 262 262 276 281 281 296 263 263 277 263 263 277 281 281 296 282 282 297 263 263 277 282 282 297 264 264 278 264 264 278 282 282 297 283 283 298 264 264 278 283 283 298 265 265 279 265 265 279 283 283 298 284 284 299 265 265 279 284 284 299 266 266 280 266 266 280 284 284 299 285 285 300 266 266 280 285 285 300 267 267 281 267 267 281 285 285 300 286 286 301 267 267 281 286 286 301 268 268 282 268 268 282 286 286 301 287 287 302 268 268 282 287 287 302 269 269 283 269 269 283 287 287 302 270 270 303 269 269 283 270 270 303 252 252 284 270 270 285 288 288 304 289 289 305 270 270 285 289 289 305 271 271 286 271 271 286 289 289 305 290 290 306 271 271 286 290 290 306 272 272 287 272 272 287 290 290 306 291 291 307 272 272 287 291 291 307 273 273 288 273 273 288 291 291 307 292 292 308 273 273 288 292 292 308 274 274 289 274 274 289 292 292 308 293 293 309 274 274 289 293 293 309 275 275 290 275 275 290 293 293 309 294 294 310 275 275 290 294 294 310 276 276 291 276 276 291 294 294 310 295 295 311 276 276 291 295 295 311 277 277 292 277 277 292 295 295 311 296 296 312 277 277 292 296 296 312 278 278 293 278 278 293 296 296 312 297 297 313 278 278 293 297 297 313 279 279 294 279 279 294 297 297 313 298 298 314 279 279 294 298 298 314 280 280 295 280 280 295 298 298 314 299 299 315 280 280 295 299 299 315 281 281 296 281 281 296 299 299 315 300 300 316 281 281 296 300 300 316 282 282 297 282 282 297 300 300 316 301 301 317 282 282 297 301 301 317 283 283 298 283 283 298 301 301 317 302 302 318 283 283 298 302 302 318 284 284 299 284 284 299 302 302 318 303 303 319 284 284 299 303 303 319 285 285 300 285 285 300 303 303 319 304 304 320 285 285 300 304 304 320 286 286 301 286 286 301 304 304 320 305 305 321 286 286 301 305 305 321 287 287 302 287 287 302 305 305 321 288 288 322 287 287 302 288 288 322 270 270 303 288 288 304 306 306 323 307 307 324 288 288 304 307 307 324 289 289 305 289 289 305 307 307 324 308 308 325 289 289 305 308 308 325 290 290 306 290 290 306 308 308 325 309 309 326 290 290 306 309 309 326 291 291 307 291 291 307 309 309 326 310 310 327 291 291 307 310 310 327 292 292 308 292 292 308 310 310 327 311 311 328 292 292 308 311 311 328 293 293 309 293 293 309 311 311 328 312 312 329 293 293 309 312 312 329 294 294 310 294 294 310 312 312 329 313 313 330 294 294 310 313 313 330 295 295 311 295 295 311 313 313 330 314 314 331 295 295 311 314 314 331 296 296 312 296 296 312 314 314 331 315 315 332 296 296 312 315 315 332 297 297 313 297 297 313 315 315 332 316 316 333 297 297 313 316 316 333 298 298 314 298 298 314 316 316 333 317 317 334 298 298 314 317 317 334 299 299 315 299 299 315 317 317 334 318 318 335 299 299 315 318 318 335 300 300 316 300 300 316 318 318 335 319 319 336 300 300 316 319 319 336 301 301 317 301 301 317 319 319 336 320 320 337 301 301 317 320 320 337 302 302 318 302 302 318 320 320 337 321 321 338 302 302 318 321 321 338 303 303 319 303 303 319 321 321 338 322 322 339 303 303 319 322 322 339 304 304 320 304 304 320 322 322 339 323 323 340 304 304 320 323 323 340 305 305 321 305 305 321 323 323 340 306 306 341 305 305 321 306 306 341 288 288 322 306 306 323 324 324 342 325 325 343 306 306 323 325 325 343 307 307 324 307 307 324 325 325 343 326 326 344 307 307 324 326 326 344 308 308 325 308 308 325 326 326 344 327 327 345 308 308 325 327 327 345 309 309 326 309 309 326 327 327 345 328 328 346 309 309 326 328 328 346 310 310 327 310 310 327 328 328 346 329 329 347 310 310 327 329 329 347 311 311 328 311 311 328 329 329 347 330 330 348 311 311 328 330 330 348 312 312 329 312 312 329 330 330 348 331 331 349 312 312 329 331 331 349 313 313 330 313 313 330 331 331 349 332 332 350 313 313 330 332 332 350 314 314 331 314 314 331 332 332 350 333 333 351 314 314 331 333 333 351 315 315 332 315 315 332 333 333 351 334 334 352 315 315 332 334 334 352 316 316 333 316 316 333 334 334 352 335 335 353 316 316 333 335 335 353 317 317 334 317 317 334 335 335 353 336 336 354 317 317 334 336 336 354 318 318 335 318 318 335 336 336 354 337 337 355 318 318 335 337 337 355 319 319 336 319 319 336 337 337 355 338 338 356 319 319 336 338 338 356 320 320 337 320 320 337 338 338 356 339 339 357 320 320 337 339 339 357 321 321 338 321 321 338 339 339 357 340 340 358 321 321 338 340 340 358 322 322 339 322 322 339 340 340 358 341 341 359 322 322 339 341 341 359 323 323 340 323 323 340 341 341 359 324 324 360 323 323 340 324 324 360 306 306 341 324 324 342 342 342 361 343 343 362 324 324 342 343 343 362 325 325 343 325 325 343 343 343 362 344 344 363 325 325 343 344 344 363 326 326 344 326 326 344 344 344 363 345 345 364 326 326 344 345 345 364 327 327 345 327 327 345 345 345 364 346 346 365 327 327 345 346 346 365 328 328 346 328 328 346 346 346 365 347 347 366 328 328 346 347 347 366 329 329 347 329 329 347 347 347 366 348 348 367 329 329 347 348 348 367 330 330 348 330 330 348 348 348 367 349 349 368 330 330 348 349 349 368 331 331 349 331 331 349 349 349 368 350 350 369 331 331 349 350 350 369 332 332 350 332 332 350 350 350 369 351 351 370 332 332 350 351 351 370 333 333 351 333 333 351 351 351 370 352 352 371 333 333 351 352 352 371 334 334 352 334 334 352 352 352 371 353 353 372 334 334 352 353 353 372 335 335 353 335 335 353 353 353 372 354 354 373 335 335 353 354 354 373 336 336 354 336 336 354 354 354 373 355 355 374 336 336 354 355 355 374 337 337 355 337 337 355 355 355 374 356 356 375 337 337 355 356 356 375 338 338 356 338 338 356 356 356 375 357 357 376 338 338 356 357 357 376 339 339 357 339 339 357 357 357 376 358 358 377 339 339 357 358 358 377 340 340 358 340 340 358 358 358 377 359 359 378 340 340 358 359 359 378 341 341 359 341 341 359 359 359 378 342 342 379 341 341 359 342 342 379 324 324 360 342 342 361 360 360 380 361 361 381 342 342 361 361 361 381 343 343 362 343 343 362 361 361 381 362 362 382 343 343 362 362 362 382 344 344 363 344 344 363 362 362 382 363 363 383 344 344 363 363 363 383 345 345 364 345 345 364 363 363 383 364 364 384 345 345 364 364 364 384 346 346 365 346 346 365 364 364 384 365 365 385 346 346 365 365 365 385 347 347 366 347 347 366 365 365 385 366 366 386 347 347 366 366 366 386 348 348 367 348 348 367 366 366 386 367 367 387 348 348 367 367 367 387 349 349 368 349 349 368 367 367 387 368 368 388 349 349 368 368 368 388 350 350 369 350 350 369 368 368 388 369 369 389 350 350 369 369 369 389 351 351 370 351 351 370 369 369 389 370 370 390 351 351 370 370 370 390 352 352 371 352 352 371 370 370 390 371 371 391 352 352 371 371 371 391 353 353 372 353 353 372 371 371 391 372 372 392 353 353 372 372 372 392 354 354 373 354 354 373 372 372 392 373 373 393 354 354 373 373 373 393 355 355 374 355 355 374 373 373 393 374 374 394 355 355 374 374 374 394 356 356 375 356 356 375 374 374 394 375 375 395 356 356 375 375 375 395 357 357 376 357 357 376 375 375 395 376 376 396 357 357 376 376 376 396 358 358 377 358 358 377 376 376 396 377 377 397 358 358 377 377 377 397 359 359 378 359 359 378 377 377 397 360 360 398 359 359 378 360 360 398 342 342 379 360 360 380 378 378 399 379 379 400 360 360 380 379 379 400 361 361 381 361 361 381 379 379 400 380 380 401 361 361 381 380 380 401 362 362 382 362 362 382 380 380 401 381 381 402 362 362 382 381 381 402 363 363 383 363 363 383 381 381 402 382 382 403 363 363 383 382 382 403 364 364 384 364 364 384 382 382 403 383 383 404 364 364 384 383 383 404 365 365 385 365 365 385 383 383 404 384 384 405 365 365 385 384 384 405 366 366 386 366 366 386 384 384 405 385 385 406 366 366 386 385 385 406 367 367 387 367 367 387 385 385 406 386 386 407 367 367 387 386 386 407 368 368 388 368 368 388 386 386 407 387 387 408 368 368 388 387 387 408 369 369 389 369 369 389 387 387 408 388 388 409 369 369 389 388 388 409 370 370 390 370 370 390 388 388 409 389 389 410 370 370 390 389 389 410 371 371 391 371 371 391 389 389 410 390 390 411 371 371 391 390 390 411 372 372 392 372 372 392 390 390 411 391 391 412 372 372 392 391 391 412 373 373 393 373 373 393 391 391 412 392 392 413 373 373 393 392 392 413 374 374 394 374 374 394 392 392 413 393 393 414 374 374 394 393 393 414 375 375 395 375 375 395 393 393 414 394 394 415 375 375 395 394 394 415 376 376 396 376 376 396 394 394 415 395 395 416 376 376 396 395 395 416 377 377 397 377 377 397 395 395 416 378 378 417 377 377 397 378 378 417 360 360 398 378 378 399 396 396 418 397 397 419 378 378 399 397 397 419 379 379 400 379 379 400 397 397 419 398 398 420 379 379 400 398 398 420 380 380 401 380 380 401 398 398 420 399 399 421 380 380 401 399 399 421 381 381 402 381 381 402 399 399 421 400 400 422 381 381 402 400 400 422 382 382 403 382 382 403 400 400 422 401 401 423 382 382 403 401 401 423 383 383 404 383 383 404 401 401 423 402 402 424 383 383 404 402 402 424 384 384 405 384 384 405 402 402 424 403 403 425 384 384 405 403 403 425 385 385 406 385 385 406 403 403 425 404 404 426 385 385 406 404 404 426 386 386 407 386 386 407 404 404 426 405 405 427 386 386 407 405 405 427 387 387 408 387 387 408 405 405 427 406 406 428 387 387 408 406 406 428 388 388 409 388 388 409 406 406 428 407 407 429 388 388 409 407 407 429 389 389 410 389 389 410 407 407 429 408 408 430 389 389 410 408 408 430 390 390 411 390 390 411 408 408 430 409 409 431 390 390 411 409 409 431 391 391 412 391 391 412 409 409 431 410 410 432 391 391 412 410 410 432 392 392 413 392 392 413 410 410 432 411 411 433 392 392 413 411 411 433 393 393 414 393 393 414 411 411 433 412 412 434 393 393 414 412 412 434 394 394 415 394 394 415 412 412 434 413 413 435 394 394 415 413 413 435 395 395 416 395 395 416 413 413 435 396 396 436 395 395 416 396 396 436 378 378 417 396 396 418 414 414 437 415 415 438 396 396 418 415 415 438 397 397 419 397 397 419 415 415 438 416 416 439 397 397 419 416 416 439 398 398 420 398 398 420 416 416 439 417 417 440 398 398 420 417 417 440 399 399 421 399 399 421 417 417 440 418 418 441 399 399 421 418 418 441 400 400 422 400 400 422 418 418 441 419 419 442 400 400 422 419 419 442 401 401 423 401 401 423 419 419 442 420 420 443 401 401 423 420 420 443 402 402 424 402 402 424 420 420 443 421 421 444 402 402 424 421 421 444 403 403 425 403 403 425 421 421 444 422 422 445 403 403 425 422 422 445 404 404 426 404 404 426 422 422 445 423 423 446 404 404 426 423 423 446 405 405 427 405 405 427 423 423 446 424 424 447 405 405 427 424 424 447 406 406 428 406 406 428 424 424 447 425 425 448 406 406 428 425 425 448 407 407 429 407 407 429 425 425 448 426 426 449 407 407 429 426 426 449 408 408 430 408 408 430 426 426 449 427 427 450 408 408 430 427 427 450 409 409 431 409 409 431 427 427 450 428 428 451 409 409 431 428 428 451 410 410 432 410 410 432 428 428 451 429 429 452 410 410 432 429 429 452 411 411 433 411 411 433 429 429 452 430 430 453 411 411 433 430 430 453 412 412 434 412 412 434 430 430 453 431 431 454 412 412 434 431 431 454 413 413 435 413 413 435 431 431 454 414 414 455 413 413 435 414 414 455 396 396 436 414 414 437 432 432 456 433 433 457 414 414 437 433 433 457 415 415 438 415 415 438 433 433 457 434 434 458 415 415 438 434 434 458 416 416 439 416 416 439 434 434 458 435 435 459 416 416 439 435 435 459 417 417 440 417 417 440 435 435 459 436 436 460 417 417 440 436 436 460 418 418 441 418 418 441 436 436 460 437 437 461 418 418 441 437 437 461 419 419 442 419 419 442 437 437 461 438 438 462 419 419 442 438 438 462 420 420 443 420 420 443 438 438 462 439 439 463 420 420 443 439 439 463 421 421 444 421 421 444 439 439 463 440 440 464 421 421 444 440 440 464 422 422 445 422 422 445 440 440 464 441 441 465 422 422 445 441 441 465 423 423 446 423 423 446 441 441 465 442 442 466 423 423 446 442 442 466 424 424 447 424 424 447 442 442 466 443 443 467 424 424 447 443 443 467 425 425 448 425 425 448 443 443 467 444 444 468 425 425 448 444 444 468 426 426 449 426 426 449 444 444 468 445 445 469 426 426 449 445 445 469 427 427 450 427 427 450 445 445 469 446 446 470 427 427 450 446 446 470 428 428 451 428 428 451 446 446 470 447 447 471 428 428 451 447 447 471 429 429 452 429 429 452 447 447 471 448 448 472 429 429 452 448 448 472 430 430 453 430 430 453 448 448 472 449 449 473 430 430 453 449 449 473 431 431 454 431 431 454 449 449 473 432 432 474 431 431 454 432 432 474 414 414 455 432 432 456 450 450 475 451 451 476 432 432 456 451 451 476 433 433 457 433 433 457 451 451 476 452 452 477 433 433 457 452 452 477 434 434 458 434 434 458 452 452 477 453 453 478 434 434 458 453 453 478 435 435 459 435 435 459 453 453 478 454 454 479 435 435 459 454 454 479 436 436 460 436 436 460 454 454 479 455 455 480 436 436 460 455 455 480 437 437 461 437 437 461 455 455 480 456 456 481 437 437 461 456 456 481 438 438 462 438 438 462 456 456 481 457 457 482 438 438 462 457 457 482 439 439 463 439 439 463 457 457 482 458 458 483 439 439 463 458 458 483 440 440 464 440 440 464 458 458 483 459 459 484 440 440 464 459 459 484 441 441 465 441 441 465 459 459 484 460 460 485 441 441 465 460 460 485 442 442 466 442 442 466 460 460 485 461 461 486 442 442 466 461 461 486 443 443 467 443 443 467 461 461 486 462 462 487 443 443 467 462 462 487 444 444 468 444 444 468 462 462 487 463 463 488 444 444 468 463 463 488 445 445 469 445 445 469 463 463 488 464 464 489 445 445 469 464 464 489 446 446 470 446 446 470 464 464 489 465 465 490 446 446 470 465 465 490 447 447 471 447 447 471 465 465 490 466 466 491 447 447 471 466 466 491 448 448 472 448 448 472 466 466 491 467 467 492 448 448 472 467 467 492 449 449 473 449 449 473 467 467 492 450 450 493 449 449 473 450 450 493 432 432 474 450 450 475 468 468 494 469 469 495 450 450 475 469 469 495 451 451 476 451 451 476 469 469 495 470 470 496 451 451 476 470 470 496 452 452 477 452 452 477 470 470 496 471 471 497 452 452 477 471 471 497 453 453 478 453 453 478 471 471 497 472 472 498 453 453 478 472 472 498 454 454 479 454 454 479 472 472 498 473 473 499 454 454 479 473 473 499 455 455 480 455 455 480 473 473 499 474 474 500 455 455 480 474 474 500 456 456 481 456 456 481 474 474 500 475 475 501 456 456 481 475 475 501 457 457 482 457 457 482 475 475 501 476 476 502 457 457 482 476 476 502 458 458 483 458 458 483 476 476 502 477 477 503 458 458 483 477 477 503 459 459 484 459 459 484 477 477 503 478 478 504 459 459 484 478 478 504 460 460 485 460 460 485 478 478 504 479 479 505 460 460 485 479 479 505 461 461 486 461 461 486 479 479 505 480 480 506 461 461 486 480 480 506 462 462 487 462 462 487 480 480 506 481 481 507 462 462 487 481 481 507 463 463 488 463 463 488 481 481 507 482 482 508 463 463 488 482 482 508 464 464 489 464 464 489 482 482 508 483 483 509 464 464 489 483 483 509 465 465 490 465 465 490 483 483 509 484 484 510 465 465 490 484 484 510 466 466 491 466 466 491 484 484 510 485 485 511 466 466 491 485 485 511 467 467 492 467 467 492 485 485 511 468 468 512 467 467 492 468 468 512 450 450 493 468 468 494 486 486 513 487 487 514 468 468 494 487 487 514 469 469 495 469 469 495 487 487 514 488 488 515 469 469 495 488 488 515 470 470 496 470 470 496 488 488 515 489 489 516 470 470 496 489 489 516 471 471 497 471 471 497 489 489 516 490 490 517 471 471 497 490 490 517 472 472 498 472 472 498 490 490 517 491 491 518 472 472 498 491 491 518 473 473 499 473 473 499 491 491 518 492 492 519 473 473 499 492 492 519 474 474 500 474 474 500 492 492 519 493 493 520 474 474 500 493 493 520 475 475 501 475 475 501 493 493 520 494 494 521 475 475 501 494 494 521 476 476 502 476 476 502 494 494 521 495 495 522 476 476 502 495 495 522 477 477 503 477 477 503 495 495 522 496 496 523 477 477 503 496 496 523 478 478 504 478 478 504 496 496 523 497 497 524 478 478 504 497 497 524 479 479 505 479 479 505 497 497 524 498 498 525 479 479 505 498 498 525 480 480 506 480 480 506 498 498 525 499 499 526 480 480 506 499 499 526 481 481 507 481 481 507 499 499 526 500 500 527 481 481 507 500 500 527 482 482 508 482 482 508 500 500 527 501 501 528 482 482 508 501 501 528 483 483 509 483 483 509 501 501 528 502 502 529 483 483 509 502 502 529 484 484 510 484 484 510 502 502 529 503 503 530 484 484 510 503 503 530 485 485 511 485 485 511 503 503 530 486 486 531 485 485 511 486 486 531 468 468 512 486 486 513 504 504 532 505 505 533 486 486 513 505 505 533 487 487 514 487 487 514 505 505 533 506 506 534 487 487 514 506 506 534 488 488 515 488 488 515 506 506 534 507 507 535 488 488 515 507 507 535 489 489 516 489 489 516 507 507 535 508 508 536 489 489 516 508 508 536 490 490 517 490 490 517 508 508 536 509 509 537 490 490 517 509 509 537 491 491 518 491 491 518 509 509 537 510 510 538 491 491 518 510 510 538 492 492 519 492 492 519 510 510 538 511 511 539 492 492 519 511 511 539 493 493 520 493 493 520 511 511 539 512 512 540 493 493 520 512 512 540 494 494 521 494 494 521 512 512 540 513 513 541 494 494 521 513 513 541 495 495 522 495 495 522 513 513 541 514 514 542 495 495 522 514 514 542 496 496 523 496 496 523 514 514 542 515 515 543 496 496 523 515 515 543 497 497 524 497 497 524 515 515 543 516 516 544 497 497 524 516 516 544 498 498 525 498 498 525 516 516 544 517 517 545 498 498 525 517 517 545 499 499 526 499 499 526 517 517 545 518 518 546 499 499 526 518 518 546 500 500 527 500 500 527 518 518 546 519 519 547 500 500 527 519 519 547 501 501 528 501 501 528 519 519 547 520 520 548 501 501 528 520 520 548 502 502 529 502 502 529 520 520 548 521 521 549 502 502 529 521 521 549 503 503 530 503 503 530 521 521 549 504 504 550 503 503 530 504 504 550 486 486 531 504 504 532 522 522 551 523 523 552 504 504 532 523 523 552 505 505 533 505 505 533 523 523 552 524 524 553 505 505 533 524 524 553 506 506 534 506 506 534 524 524 553 525 525 554 506 506 534 525 525 554 507 507 535 507 507 535 525 525 554 526 526 555 507 507 535 526 526 555 508 508 536 508 508 536 526 526 555 527 527 556 508 508 536 527 527 556 509 509 537 509 509 537 527 527 556 528 528 557 509 509 537 528 528 557 510 510 538 510 510 538 528 528 557 529 529 558 510 510 538 529 529 558 511 511 539 511 511 539 529 529 558 530 530 559 511 511 539 530 530 559 512 512 540 512 512 540 530 530 559 531 531 560 512 512 540 531 531 560 513 513 541 513 513 541 531 531 560 532 532 561 513 513 541 532 532 561 514 514 542 514 514 542 532 532 561 533 533 562 514 514 542 533 533 562 515 515 543 515 515 543 533 533 562 534 534 563 515 515 543 534 534 563 516 516 544 516 516 544 534 534 563 535 535 564 516 516 544 535 535 564 517 517 545 517 517 545 535 535 564 536 536 565 517 517 545 536 536 565 518 518 546 518 518 546 536 536 565 537 537 566 518 518 546 537 537 566 519 519 547 519 519 547 537 537 566 538 538 567 519 519 547 538 538 567 520 520 548 520 520 548 538 538 567 539 539 568 520 520 548 539 539 568 521 521 549 521 521 549 539 539 568 522 522 569 521 521 549 522 522 569 504 504 550 522 522 551 540 540 570 541 541 571 522 522 551 541 541 571 523 523 552 523 523 552 541 541 571 542 542 572 523 523 552 542 542 572 524 524 553 524 524 553 542 542 572 543 543 573 524 524 553 543 543 573 525 525 554 525 525 554 543 543 573 544 544 574 525 525 554 544 544 574 526 526 555 526 526 555 544 544 574 545 545 575 526 526 555 545 545 575 527 527 556 527 527 556 545 545 575 546 546 576 527 527 556 546 546 576 528 528 557 528 528 557 546 546 576 547 547 577 528 528 557 547 547 577 529 529 558 529 529 558 547 547 577 548 548 578 529 529 558 548 548 578 530 530 559 530 530 559 548 548 578 549 549 579 530 530 559 549 549 579 531 531 560 531 531 560 549 549 579 550 550 580 531 531 560 550 550 580 532 532 561 532 532 561 550 550 580 551 551 581 532 532 561 551 551 581 533 533 562 533 533 562 551 551 581 552 552 582 533 533 562 552 552 582 534 534 563 534 534 563 552 552 582 553 553 583 534 534 563 553 553 583 535 535 564 535 535 564 553 553 583 554 554 584 535 535 564 554 554 584 536 536 565 536 536 565 554 554 584 555 555 585 536 536 565 555 555 585 537 537 566 537 537 566 555 555 585 556 556 586 537 537 566 556 556 586 538 538 567 538 538 567 556 556 586 557 557 587 538 538 567 557 557 587 539 539 568 539 539 568 557 557 587 540 540 588 539 539 568 540 540 588 522 522 569 540 540 570 558 558 589 559 559 590 540 540 570 559 559 590 541 541 571 541 541 571 559 559 590 560 560 591 541 541 571 560 560 591 542 542 572 542 542 572 560 560 591 561 561 592 542 542 572 561 561 592 543 543 573 543 543 573 561 561 592 562 562 593 543 543 573 562 562 593 544 544 574 544 544 574 562 562 593 563 563 594 544 544 574 563 563 594 545 545 575 545 545 575 563 563 594 564 564 595 545 545 575 564 564 595 546 546 576 546 546 576 564 564 595 565 565 596 546 546 576 565 565 596 547 547 577 547 547 577 565 565 596 566 566 597 547 547 577 566 566 597 548 548 578 548 548 578 566 566 597 567 567 598 548 548 578 567 567 598 549 549 579 549 549 579 567 567 598 568 568 599 549 549 579 568 568 599 550 550 580 550 550 580 568 568 599 569 569 600 550 550 580 569 569 600 551 551 581 551 551 581 569 569 600 570 570 601 551 551 581 570 570 601 552 552 582 552 552 582 570 570 601 571 571 602 552 552 582 571 571 602 553 553 583 553 553 583 571 571 602 572 572 603 553 553 583 572 572 603 554 554 584 554 554 584 572 572 603 573 573 604 554 554 584 573 573 604 555 555 585 555 555 585 573 573 604 574 574 605 555 555 585 574 574 605 556 556 586 556 556 586 574 574 605 575 575 606 556 556 586 575 575 606 557 557 587 557 557 587 575 575 606 558 558 607 557 557 587 558 558 607 540 540 588 558 558 589 576 576 608 577 577 609 558 558 589 577 577 609 559 559 590 559 559 590 577 577 609 578 578 610 559 559 590 578 578 610 560 560 591 560 560 591 578 578 610 579 579 611 560 560 591 579 579 611 561 561 592 561 561 592 579 579 611 580 580 612 561 561 592 580 580 612 562 562 593 562 562 593 580 580 612 581 581 613 562 562 593 581 581 613 563 563 594 563 563 594 581 581 613 582 582 614 563 563 594 582 582 614 564 564 595 564 564 595 582 582 614 583 583 615 564 564 595 583 583 615 565 565 596 565 565 596 583 583 615 584 584 616 565 565 596 584 584 616 566 566 597 566 566 597 584 584 616 585 585 617 566 566 597 585 585 617 567 567 598 567 567 598 585 585 617 586 586 618 567 567 598 586 586 618 568 568 599 568 568 599 586 586 618 587 587 619 568 568 599 587 587 619 569 569 600 569 569 600 587 587 619 588 588 620 569 569 600 588 588 620 570 570 601 570 570 601 588 588 620 589 589 621 570 570 601 589 589 621 571 571 602 571 571 602 589 589 621 590 590 622 571 571 602 590 590 622 572 572 603 572 572 603 590 590 622 591 591 623 572 572 603 591 591 623 573 573 604 573 573 604 591 591 623 592 592 624 573 573 604 592 592 624 574 574 605 574 574 605 592 592 624 593 593 625 574 574 605 593 593 625 575 575 606 575 575 606 593 593 625 576 576 626 575 575 606 576 576 626 558 558 607 576 576 608 594 594 627 595 595 628 576 576 608 595 595 628 577 577 609 577 577 609 595 595 628 596 596 629 577 577 609 596 596 629 578 578 610 578 578 610 596 596 629 597 597 630 578 578 610 597 597 630 579 579 611 579 579 611 597 597 630 598 598 631 579 579 611 598 598 631 580 580 612 580 580 612 598 598 631 599 599 632 580 580 612 599 599 632 581 581 613 581 581 613 599 599 632 600 600 633 581 581 613 600 600 633 582 582 614 582 582 614 600 600 633 601 601 634 582 582 614 601 601 634 583 583 615 583 583 615 601 601 634 602 602 635 583 583 615 602 602 635 584 584 616 584 584 616 602 602 635 603 603 636 584 584 616 603 603 636 585 585 617 585 585 617 603 603 636 604 604 637 585 585 617 604 604 637 586 586 618 586 586 618 604 604 637 605 605 638 586 586 618 605 605 638 587 587 619 587 587 619 605 605 638 606 606 639 587 587 619 606 606 639 588 588 620 588 588 620 606 606 639 607 607 640 588 588 620 607 607 640 589 589 621 589 589 621 607 607 640 608 608 641 589 589 621 608 608 641 590 590 622 590 590 622 608 608 641 609 609 642 590 590 622 609 609 642 591 591 623 591 591 623 609 609 642 610 610 643 591 591 623 610 610 643 592 592 624 592 592 624 610 610 643 611 611 644 592 592 624 611 611 644 593 593 625 593 593 625 611 611 644 594 594 645 593 593 625 594 594 645 576 576 626 594 594 627 612 612 646 613 613 647 594 594 627 613 613 647 595 595 628 595 595 628 613 613 647 614 614 648 595 595 628 614 614 648 596 596 629 596 596 629 614 614 648 615 615 649 596 596 629 615 615 649 597 597 630 597 597 630 615 615 649 616 616 650 597 597 630 616 616 650 598 598 631 598 598 631 616 616 650 617 617 651 598 598 631 617 617 651 599 599 632 599 599 632 617 617 651 618 618 652 599 599 632 618 618 652 600 600 633 600 600 633 618 618 652 619 619 653 600 600 633 619 619 653 601 601 634 601 601 634 619 619 653 620 620 654 601 601 634 620 620 654 602 602 635 602 602 635 620 620 654 621 621 655 602 602 635 621 621 655 603 603 636 603 603 636 621 621 655 622 622 656 603 603 636 622 622 656 604 604 637 604 604 637 622 622 656 623 623 657 604 604 637 623 623 657 605 605 638 605 605 638 623 623 657 624 624 658 605 605 638 624 624 658 606 606 639 606 606 639 624 624 658 625 625 659 606 606 639 625 625 659 607 607 640 607 607 640 625 625 659 626 626 660 607 607 640 626 626 660 608 608 641 608 608 641 626 626 660 627 627 661 608 608 641 627 627 661 609 609 642 609 609 642 627 627 661 628 628 662 609 609 642 628 628 662 610 610 643 610 610 643 628 628 662 629 629 663 610 610 643 629 629 663 611 611 644 611 611 644 629 629 663 612 612 664 611 611 644 612 612 664 594 594 645 612 612 646 630 630 665 631 631 666 612 612 646 631 631 666 613 613 647 613 613 647 631 631 666 632 632 667 613 613 647 632 632 667 614 614 648 614 614 648 632 632 667 633 633 668 614 614 648 633 633 668 615 615 649 615 615 649 633 633 668 634 634 669 615 615 649 634 634 669 616 616 650 616 616 650 634 634 669 635 635 670 616 616 650 635 635 670 617 617 651 617 617 651 635 635 670 636 636 671 617 617 651 636 636 671 618 618 652 618 618 652 636 636 671 637 637 672 618 618 652 637 637 672 619 619 653 619 619 653 637 637 672 638 638 673 619 619 653 638 638 673 620 620 654 620 620 654 638 638 673 639 639 674 620 620 654 639 639 674 621 621 655 621 621 655 639 639 674 640 640 675 621 621 655 640 640 675 622 622 656 622 622 656 640 640 675 641 641 676 622 622 656 641 641 676 623 623 657 623 623 657 641 641 676 642 642 677 623 623 657 642 642 677 624 624 658 624 624 658 642 642 677 643 643 678 624 624 658 643 643 678 625 625 659 625 625 659 643 643 678 644 644 679 625 625 659 644 644 679 626 626 660 626 626 660 644 644 679 645 645 680 626 626 660 645 645 680 627 627 661 627 627 661 645 645 680 646 646 681 627 627 661 646 646 681 628 628 662 628 628 662 646 646 681 647 647 682 628 628 662 647 647 682 629 629 663 629 629 663 647 647 682 630 630 683 629 629 663 630 630 683 612 612 664 630 630 665 648 648 684 649 649 685 630 630 665 649 649 685 631 631 666 631 631 666 649 649 685 650 650 686 631 631 666 650 650 686 632 632 667 632 632 667 650 650 686 651 651 687 632 632 667 651 651 687 633 633 668 633 633 668 651 651 687 652 652 688 633 633 668 652 652 688 634 634 669 634 634 669 652 652 688 653 653 689 634 634 669 653 653 689 635 635 670 635 635 670 653 653 689 654 654 690 635 635 670 654 654 690 636 636 671 636 636 671 654 654 690 655 655 691 636 636 671 655 655 691 637 637 672 637 637 672 655 655 691 656 656 692 637 637 672 656 656 692 638 638 673 638 638 673 656 656 692 657 657 693 638 638 673 657 657 693 639 639 674 639 639 674 657 657 693 658 658 694 639 639 674 658 658 694 640 640 675 640 640 675 658 658 694 659 659 695 640 640 675 659 659 695 641 641 676 641 641 676 659 659 695 660 660 696 641 641 676 660 660 696 642 642 677 642 642 677 660 660 696 661 661 697 642 642 677 661 661 697 643 643 678 643 643 678 661 661 697 662 662 698 643 643 678 662 662 698 644 644 679 644 644 679 662 662 698 663 663 699 644 644 679 663 663 699 645 645 680 645 645 680 663 663 699 664 664 700 645 645 680 664 664 700 646 646 681 646 646 681 664 664 700 665 665 701 646 646 681 665 665 701 647 647 682 647 647 682 665 665 701 648 648 702 647 647 682 648 648 702 630 630 683 648 648 684 666 666 703 667 667 704 648 648 684 667 667 704 649 649 685 649 649 685 667 667 704 668 668 705 649 649 685 668 668 705 650 650 686 650 650 686 668 668 705 669 669 706 650 650 686 669 669 706 651 651 687 651 651 687 669 669 706 670 670 707 651 651 687 670 670 707 652 652 688 652 652 688 670 670 707 671 671 708 652 652 688 671 671 708 653 653 689 653 653 689 671 671 708 672 672 709 653 653 689 672 672 709 654 654 690 654 654 690 672 672 709 673 673 710 654 654 690 673 673 710 655 655 691 655 655 691 673 673 710 674 674 711 655 655 691 674 674 711 656 656 692 656 656 692 674 674 711 675 675 712 656 656 692 675 675 712 657 657 693 657 657 693 675 675 712 676 676 713 657 657 693 676 676 713 658 658 694 658 658 694 676 676 713 677 677 714 658 658 694 677 677 714 659 659 695 659 659 695 677 677 714 678 678 715 659 659 695 678 678 715 660 660 696 660 660 696 678 678 715 679 679 716 660 660 696 679 679 716 661 661 697 661 661 697 679 679 716 680 680 717 661 661 697 680 680 717 662 662 698 662 662 698 680 680 717 681 681 718 662 662 698 681 681 718 663 663 699 663 663 699 681 681 718 682 682 719 663 663 699 682 682 719 664 664 700 664 664 700 682 682 719 683 683 720 664 664 700 683 683 720 665 665 701 665 665 701 683 683 720 666 666 721 665 665 701 666 666 721 648 648 702 666 666 703 684 684 722 685 685 723 666 666 703 685 685 723 667 667 704 667 667 704 685 685 723 686 686 724 667 667 704 686 686 724 668 668 705 668 668 705 686 686 724 687 687 725 668 668 705 687 687 725 669 669 706 669 669 706 687 687 725 688 688 726 669 669 706 688 688 726 670 670 707 670 670 707 688 688 726 689 689 727 670 670 707 689 689 727 671 671 708 671 671 708 689 689 727 690 690 728 671 671 708 690 690 728 672 672 709 672 672 709 690 690 728 691 691 729 672 672 709 691 691 729 673 673 710 673 673 710 691 691 729 692 692 730 673 673 710 692 692 730 674 674 711 674 674 711 692 692 730 693 693 731 674 674 711 693 693 731 675 675 712 675 675 712 693 693 731 694 694 732 675 675 712 694 694 732 676 676 713 676 676 713 694 694 732 695 695 733 676 676 713 695 695 733 677 677 714 677 677 714 695 695 733 696 696 734 677 677 714 696 696 734 678 678 715 678 678 715 696 696 734 697 697 735 678 678 715 697 697 735 679 679 716 679 679 716 697 697 735 698 698 736 679 679 716 698 698 736 680 680 717 680 680 717 698 698 736 699 699 737 680 680 717 699 699 737 681 681 718 681 681 718 699 699 737 700 700 738 681 681 718 700 700 738 682 682 719 682 682 719 700 700 738 701 701 739 682 682 719 701 701 739 683 683 720 683 683 720 701 701 739 684 684 740 683 683 720 684 684 740 666 666 721 684 684 722 702 702 741 703 703 742 684 684 722 703 703 742 685 685 723 685 685 723 703 703 742 704 704 743 685 685 723 704 704 743 686 686 724 686 686 724 704 704 743 705 705 744 686 686 724 705 705 744 687 687 725 687 687 725 705 705 744 706 706 745 687 687 725 706 706 745 688 688 726 688 688 726 706 706 745 707 707 746 688 688 726 707 707 746 689 689 727 689 689 727 707 707 746 708 708 747 689 689 727 708 708 747 690 690 728 690 690 728 708 708 747 709 709 748 690 690 728 709 709 748 691 691 729 691 691 729 709 709 748 710 710 749 691 691 729 710 710 749 692 692 730 692 692 730 710 710 749 711 711 750 692 692 730 711 711 750 693 693 731 693 693 731 711 711 750 712 712 751 693 693 731 712 712 751 694 694 732 694 694 732 712 712 751 713 713 752 694 694 732 713 713 752 695 695 733 695 695 733 713 713 752 714 714 753 695 695 733 714 714 753 696 696 734 696 696 734 714 714 753 715 715 754 696 696 734 715 715 754 697 697 735 697 697 735 715 715 754 716 716 755 697 697 735 716 716 755 698 698 736 698 698 736 716 716 755 717 717 756 698 698 736 717 717 756 699 699 737 699 699 737 717 717 756 718 718 757 699 699 737 718 718 757 700 700 738 700 700 738 718 718 757 719 719 758 700 700 738 719 719 758 701 701 739 701 701 739 719 719 758 702 702 759 701 701 739 702 702 759 684 684 740 702 702 741 720 720 760 721 721 761 702 702 741 721 721 761 703 703 742 703 703 742 721 721 761 722 722 762 703 703 742 722 722 762 704 704 743 704 704 743 722 722 762 723 723 763 704 704 743 723 723 763 705 705 744 705 705 744 723 723 763 724 724 764 705 705 744 724 724 764 706 706 745 706 706 745 724 724 764 725 725 765 706 706 745 725 725 765 707 707 746 707 707 746 725 725 765 726 726 766 707 707 746 726 726 766 708 708 747 708 708 747 726 726 766 727 727 767 708 708 747 727 727 767 709 709 748 709 709 748 727 727 767 728 728 768 709 709 748 728 728 768 710 710 749 710 710 749 728 728 768 729 729 769 710 710 749 729 729 769 711 711 750 711 711 750 729 729 769 730 730 770 711 711 750 730 730 770 712 712 751 712 712 751 730 730 770 731 731 771 712 712 751 731 731 771 713 713 752 713 713 752 731 731 771 732 732 772 713 713 752 732 732 772 714 714 753 714 714 753 732 732 772 733 733 773 714 714 753 733 733 773 715 715 754 715 715 754 733 733 773 734 734 774 715 715 754 734 734 774 716 716 755 716 716 755 734 734 774 735 735 775 716 716 755 735 735 775 717 717 756 717 717 756 735 735 775 736 736 776 717 717 756 736 736 776 718 718 757 718 718 757 736 736 776 737 737 777 718 718 757 737 737 777 719 719 758 719 719 758 737 737 777 720 720 778 719 719 758 720 720 778 702 702 759 720 720 760 738 738 779 739 739 780 720 720 760 739 739 780 721 721 761 721 721 761 739 739 780 740 740 781 721 721 761 740 740 781 722 722 762 722 722 762 740 740 781 741 741 782 722 722 762 741 741 782 723 723 763 723 723 763 741 741 782 742 742 783 723 723 763 742 742 783 724 724 764 724 724 764 742 742 783 743 743 784 724 724 764 743 743 784 725 725 765 725 725 765 743 743 784 744 744 785 725 725 765 744 744 785 726 726 766 726 726 766 744 744 785 745 745 786 726 726 766 745 745 786 727 727 767 727 727 767 745 745 786 746 746 787 727 727 767 746 746 787 728 728 768 728 728 768 746 746 787 747 747 788 728 728 768 747 747 788 729 729 769 729 729 769 747 747 788 748 748 789 729 729 769 748 748 789 730 730 770 730 730 770 748 748 789 749 749 790 730 730 770 749 749 790 731 731 771 731 731 771 749 749 790 750 750 791 731 731 771 750 750 791 732 732 772 732 732 772 750 750 791 751 751 792 732 732 772 751 751 792 733 733 773 733 733 773 751 751 792 752 752 793 733 733 773 752 752 793 734 734 774 734 734 774 752 752 793 753 753 794 734 734 774 753 753 794 735 735 775 735 735 775 753 753 794 754 754 795 735 735 775 754 754 795 736 736 776 736 736 776 754 754 795 755 755 796 736 736 776 755 755 796 737 737 777 737 737 777 755 755 796 738 738 797 737 737 777 738 738 797 720 720 778 738 738 779 756 756 798 757 757 799 738 738 779 757 757 799 739 739 780 739 739 780 757 757 799 758 758 800 739 739 780 758 758 800 740 740 781 740 740 781 758 758 800 759 759 801 740 740 781 759 759 801 741 741 782 741 741 782 759 759 801 760 760 802 741 741 782 760 760 802 742 742 783 742 742 783 760 760 802 761 761 803 742 742 783 761 761 803 743 743 784 743 743 784 761 761 803 762 762 804 743 743 784 762 762 804 744 744 785 744 744 785 762 762 804 763 763 805 744 744 785 763 763 805 745 745 786 745 745 786 763 763 805 764 764 806 745 745 786 764 764 806 746 746 787 746 746 787 764 764 806 765 765 807 746 746 787 765 765 807 747 747 788 747 747 788 765 765 807 766 766 808 747 747 788 766 766 808 748 748 789 748 748 789 766 766 808 767 767 809 748 748 789 767 767 809 749 749 790 749 749 790 767 767 809 768 768 810 749 749 790 768 768 810 750 750 791 750 750 791 768 768 810 769 769 811 750 750 791 769 769 811 751 751 792 751 751 792 769 769 811 770 770 812 751 751 792 770 770 812 752 752 793 752 752 793 770 770 812 771 771 813 752 752 793 771 771 813 753 753 794 753 753 794 771 771 813 772 772 814 753 753 794 772 772 814 754 754 795 754 754 795 772 772 814 773 773 815 754 754 795 773 773 815 755 755 796 755 755 796 773 773 815 756 756 816 755 755 796 756 756 816 738 738 797 756 756 798 774 774 817 775 775 818 756 756 798 775 775 818 757 757 799 757 757 799 775 775 818 776 776 819 757 757 799 776 776 819 758 758 800 758 758 800 776 776 819 777 777 820 758 758 800 777 777 820 759 759 801 759 759 801 777 777 820 778 778 821 759 759 801 778 778 821 760 760 802 760 760 802 778 778 821 779 779 822 760 760 802 779 779 822 761 761 803 761 761 803 779 779 822 780 780 823 761 761 803 780 780 823 762 762 804 762 762 804 780 780 823 781 781 824 762 762 804 781 781 824 763 763 805 763 763 805 781 781 824 782 782 825 763 763 805 782 782 825 764 764 806 764 764 806 782 782 825 783 783 826 764 764 806 783 783 826 765 765 807 765 765 807 783 783 826 784 784 827 765 765 807 784 784 827 766 766 808 766 766 808 784 784 827 785 785 828 766 766 808 785 785 828 767 767 809 767 767 809 785 785 828 786 786 829 767 767 809 786 786 829 768 768 810 768 768 810 786 786 829 787 787 830 768 768 810 787 787 830 769 769 811 769 769 811 787 787 830 788 788 831 769 769 811 788 788 831 770 770 812 770 770 812 788 788 831 789 789 832 770 770 812 789 789 832 771 771 813 771 771 813 789 789 832 790 790 833 771 771 813 790 790 833 772 772 814 772 772 814 790 790 833 791 791 834 772 772 814 791 791 834 773 773 815 773 773 815 791 791 834 774 774 835 773 773 815 774 774 835 756 756 816 774 774 817 792 792 836 793 793 837 774 774 817 793 793 837 775 775 818 775 775 818 793 793 837 794 794 838 775 775 818 794 794 838 776 776 819 776 776 819 794 794 838 795 795 839 776 776 819 795 795 839 777 777 820 777 777 820 795 795 839 796 796 840 777 777 820 796 796 840 778 778 821 778 778 821 796 796 840 797 797 841 778 778 821 797 797 841 779 779 822 779 779 822 797 797 841 798 798 842 779 779 822 798 798 842 780 780 823 780 780 823 798 798 842 799 799 843 780 780 823 799 799 843 781 781 824 781 781 824 799 799 843 800 800 844 781 781 824 800 800 844 782 782 825 782 782 825 800 800 844 801 801 845 782 782 825 801 801 845 783 783 826 783 783 826 801 801 845 802 802 846 783 783 826 802 802 846 784 784 827 784 784 827 802 802 846 803 803 847 784 784 827 803 803 847 785 785 828 785 785 828 803 803 847 804 804 848 785 785 828 804 804 848 786 786 829 786 786 829 804 804 848 805 805 849 786 786 829 805 805 849 787 787 830 787 787 830 805 805 849 806 806 850 787 787 830 806 806 850 788 788 831 788 788 831 806 806 850 807 807 851 788 788 831 807 807 851 789 789 832 789 789 832 807 807 851 808 808 852 789 789 832 808 808 852 790 790 833 790 790 833 808 808 852 809 809 853 790 790 833 809 809 853 791 791 834 791 791 834 809 809 853 792 792 854 791 791 834 792 792 854 774 774 835 792 792 836 810 810 855 811 811 856 792 792 836 811 811 856 793 793 837 793 793 837 811 811 856 812 812 857 793 793 837 812 812 857 794 794 838 794 794 838 812 812 857 813 813 858 794 794 838 813 813 858 795 795 839 795 795 839 813 813 858 814 814 859 795 795 839 814 814 859 796 796 840 796 796 840 814 814 859 815 815 860 796 796 840 815 815 860 797 797 841 797 797 841 815 815 860 816 816 861 797 797 841 816 816 861 798 798 842 798 798 842 816 816 861 817 817 862 798 798 842 817 817 862 799 799 843 799 799 843 817 817 862 818 818 863 799 799 843 818 818 863 800 800 844 800 800 844 818 818 863 819 819 864 800 800 844 819 819 864 801 801 845 801 801 845 819 819 864 820 820 865 801 801 845 820 820 865 802 802 846 802 802 846 820 820 865 821 821 866 802 802 846 821 821 866 803 803 847 803 803 847 821 821 866 822 822 867 803 803 847 822 822 867 804 804 848 804 804 848 822 822 867 823 823 868 804 804 848 823 823 868 805 805 849 805 805 849 823 823 868 824 824 869 805 805 849 824 824 869 806 806 850 806 806 850 824 824 869 825 825 870 806 806 850 825 825 870 807 807 851 807 807 851 825 825 870 826 826 871 807 807 851 826 826 871 808 808 852 808 808 852 826 826 871 827 827 872 808 808 852 827 827 872 809 809 853 809 809 853 827 827 872 810 810 873 809 809 853 810 810 873 792 792 854 810 810 855 828 828 874 829 829 875 810 810 855 829 829 875 811 811 856 811 811 856 829 829 875 830 830 876 811 811 856 830 830 876 812 812 857 812 812 857 830 830 876 831 831 877 812 812 857 831 831 877 813 813 858 813 813 858 831 831 877 832 832 878 813 813 858 832 832 878 814 814 859 814 814 859 832 832 878 833 833 879 814 814 859 833 833 879 815 815 860 815 815 860 833 833 879 834 834 880 815 815 860 834 834 880 816 816 861 816 816 861 834 834 880 835 835 881 816 816 861 835 835 881 817 817 862 817 817 862 835 835 881 836 836 882 817 817 862 836 836 882 818 818 863 818 818 863 836 836 882 837 837 883 818 818 863 837 837 883 819 819 864 819 819 864 837 837 883 838 838 884 819 819 864 838 838 884 820 820 865 820 820 865 838 838 884 839 839 885 820 820 865 839 839 885 821 821 866 821 821 866 839 839 885 840 840 886 821 821 866 840 840 886 822 822 867 822 822 867 840 840 886 841 841 887 822 822 867 841 841 887 823 823 868 823 823 868 841 841 887 842 842 888 823 823 868 842 842 888 824 824 869 824 824 869 842 842 888 843 843 889 824 824 869 843 843 889 825 825 870 825 825 870 843 843 889 844 844 890 825 825 870 844 844 890 826 826 871 826 826 871 844 844 890 845 845 891 826 826 871 845 845 891 827 827 872 827 827 872 845 845 891 828 828 892 827 827 872 828 828 892 810 810 873 828 828 874 846 846 893 847 847 894 828 828 874 847 847 894 829 829 875 829 829 875 847 847 894 848 848 895 829 829 875 848 848 895 830 830 876 830 830 876 848 848 895 849 849 896 830 830 876 849 849 896 831 831 877 831 831 877 849 849 896 850 850 897 831 831 877 850 850 897 832 832 878 832 832 878 850 850 897 851 851 898 832 832 878 851 851 898 833 833 879 833 833 879 851 851 898 852 852 899 833 833 879 852 852 899 834 834 880 834 834 880 852 852 899 853 853 900 834 834 880 853 853 900 835 835 881 835 835 881 853 853 900 854 854 901 835 835 881 854 854 901 836 836 882 836 836 882 854 854 901 855 855 902 836 836 882 855 855 902 837 837 883 837 837 883 855 855 902 856 856 903 837 837 883 856 856 903 838 838 884 838 838 884 856 856 903 857 857 904 838 838 884 857 857 904 839 839 885 839 839 885 857 857 904 858 858 905 839 839 885 858 858 905 840 840 886 840 840 886 858 858 905 859 859 906 840 840 886 859 859 906 841 841 887 841 841 887 859 859 906 860 860 907 841 841 887 860 860 907 842 842 888 842 842 888 860 860 907 861 861 908 842 842 888 861 861 908 843 843 889 843 843 889 861 861 908 862 862 909 843 843 889 862 862 909 844 844 890 844 844 890 862 862 909 863 863 910 844 844 890 863 863 910 845 845 891 845 845 891 863 863 910 846 846 911 845 845 891 846 846 911 828 828 892 846 846 893 864 864 912 865 865 913 846 846 893 865 865 913 847 847 894 847 847 894 865 865 913 866 866 914 847 847 894 866 866 914 848 848 895 848 848 895 866 866 914 867 867 915 848 848 895 867 867 915 849 849 896 849 849 896 867 867 915 868 868 916 849 849 896 868 868 916 850 850 897 850 850 897 868 868 916 869 869 917 850 850 897 869 869 917 851 851 898 851 851 898 869 869 917 870 870 918 851 851 898 870 870 918 852 852 899 852 852 899 870 870 918 871 871 919 852 852 899 871 871 919 853 853 900 853 853 900 871 871 919 872 872 920 853 853 900 872 872 920 854 854 901 854 854 901 872 872 920 873 873 921 854 854 901 873 873 921 855 855 902 855 855 902 873 873 921 874 874 922 855 855 902 874 874 922 856 856 903 856 856 903 874 874 922 875 875 923 856 856 903 875 875 923 857 857 904 857 857 904 875 875 923 876 876 924 857 857 904 876 876 924 858 858 905 858 858 905 876 876 924 877 877 925 858 858 905 877 877 925 859 859 906 859 859 906 877 877 925 878 878 926 859 859 906 878 878 926 860 860 907 860 860 907 878 878 926 879 879 927 860 860 907 879 879 927 861 861 908 861 861 908 879 879 927 880 880 928 861 861 908 880 880 928 862 862 909 862 862 909 880 880 928 881 881 929 862 862 909 881 881 929 863 863 910 863 863 910 881 881 929 864 864 930 863 863 910 864 864 930 846 846 911 864 864 912 882 882 931 883 883 932 864 864 912 883 883 932 865 865 913 865 865 913 883 883 932 884 884 933 865 865 913 884 884 933 866 866 914 866 866 914 884 884 933 885 885 934 866 866 914 885 885 934 867 867 915 867 867 915 885 885 934 886 886 935 867 867 915 886 886 935 868 868 916 868 868 916 886 886 935 887 887 936 868 868 916 887 887 936 869 869 917 869 869 917 887 887 936 888 888 937 869 869 917 888 888 937 870 870 918 870 870 918 888 888 937 889 889 938 870 870 918 889 889 938 871 871 919 871 871 919 889 889 938 890 890 939 871 871 919 890 890 939 872 872 920 872 872 920 890 890 939 891 891 940 872 872 920 891 891 940 873 873 921 873 873 921 891 891 940 892 892 941 873 873 921 892 892 941 874 874 922 874 874 922 892 892 941 893 893 942 874 874 922 893 893 942 875 875 923 875 875 923 893 893 942 894 894 943 875 875 923 894 894 943 876 876 924 876 876 924 894 894 943 895 895 944 876 876 924 895 895 944 877 877 925 877 877 925 895 895 944 896 896 945 877 877 925 896 896 945 878 878 926 878 878 926 896 896 945 897 897 946 878 878 926 897 897 946 879 879 927 879 879 927 897 897 946 898 898 947 879 879 927 898 898 947 880 880 928 880 880 928 898 898 947 899 899 948 880 880 928 899 899 948 881 881 929 881 881 929 899 899 948 882 882 949 881 881 929 882 882 949 864 864 930 882 882 931 900 900 950 901 901 951 882 882 931 901 901 951 883 883 932 883 883 932 901 901 951 902 902 952 883 883 932 902 902 952 884 884 933 884 884 933 902 902 952 903 903 953 884 884 933 903 903 953 885 885 934 885 885 934 903 903 953 904 904 954 885 885 934 904 904 954 886 886 935 886 886 935 904 904 954 905 905 955 886 886 935 905 905 955 887 887 936 887 887 936 905 905 955 906 906 956 887 887 936 906 906 956 888 888 937 888 888 937 906 906 956 907 907 957 888 888 937 907 907 957 889 889 938 889 889 938 907 907 957 908 908 958 889 889 938 908 908 958 890 890 939 890 890 939 908 908 958 909 909 959 890 890 939 909 909 959 891 891 940 891 891 940 909 909 959 910 910 960 891 891 940 910 910 960 892 892 941 892 892 941 910 910 960 911 911 961 892 892 941 911 911 961 893 893 942 893 893 942 911 911 961 912 912 962 893 893 942 912 912 962 894 894 943 894 894 943 912 912 962 913 913 963 894 894 943 913 913 963 895 895 944 895 895 944 913 913 963 914 914 964 895 895 944 914 914 964 896 896 945 896 896 945 914 914 964 915 915 965 896 896 945 915 915 965 897 897 946 897 897 946 915 915 965 916 916 966 897 897 946 916 916 966 898 898 947 898 898 947 916 916 966 917 917 967 898 898 947 917 917 967 899 899 948 899 899 948 917 917 967 900 900 968 899 899 948 900 900 968 882 882 949 900 900 950 918 918 969 919 919 970 900 900 950 919 919 970 901 901 951 901 901 951 919 919 970 920 920 971 901 901 951 920 920 971 902 902 952 902 902 952 920 920 971 921 921 972 902 902 952 921 921 972 903 903 953 903 903 953 921 921 972 922 922 973 903 903 953 922 922 973 904 904 954 904 904 954 922 922 973 923 923 974 904 904 954 923 923 974 905 905 955 905 905 955 923 923 974 924 924 975 905 905 955 924 924 975 906 906 956 906 906 956 924 924 975 925 925 976 906 906 956 925 925 976 907 907 957 907 907 957 925 925 976 926 926 977 907 907 957 926 926 977 908 908 958 908 908 958 926 926 977 927 927 978 908 908 958 927 927 978 909 909 959 909 909 959 927 927 978 928 928 979 909 909 959 928 928 979 910 910 960 910 910 960 928 928 979 929 929 980 910 910 960 929 929 980 911 911 961 911 911 961 929 929 980 930 930 981 911 911 961 930 930 981 912 912 962 912 912 962 930 930 981 931 931 982 912 912 962 931 931 982 913 913 963 913 913 963 931 931 982 932 932 983 913 913 963 932 932 983 914 914 964 914 914 964 932 932 983 933 933 984 914 914 964 933 933 984 915 915 965 915 915 965 933 933 984 934 934 985 915 915 965 934 934 985 916 916 966 916 916 966 934 934 985 935 935 986 916 916 966 935 935 986 917 917 967 917 917 967 935 935 986 918 918 987 917 917 967 918 918 987 900 900 968 918 918 969 936 936 988 937 937 989 918 918 969 937 937 989 919 919 970 919 919 970 937 937 989 938 938 990 919 919 970 938 938 990 920 920 971 920 920 971 938 938 990 939 939 991 920 920 971 939 939 991 921 921 972 921 921 972 939 939 991 940 940 992 921 921 972 940 940 992 922 922 973 922 922 973 940 940 992 941 941 993 922 922 973 941 941 993 923 923 974 923 923 974 941 941 993 942 942 994 923 923 974 942 942 994 924 924 975 924 924 975 942 942 994 943 943 995 924 924 975 943 943 995 925 925 976 925 925 976 943 943 995 944 944 996 925 925 976 944 944 996 926 926 977 926 926 977 944 944 996 945 945 997 926 926 977 945 945 997 927 927 978 927 927 978 945 945 997 946 946 998 927 927 978 946 946 998 928 928 979 928 928 979 946 946 998 947 947 999 928 928 979 947 947 999 929 929 980 929 929 980 947 947 999 948 948 1000 929 929 980 948 948 1000 930 930 981 930 930 981 948 948 1000 949 949 1001 930 930 981 949 949 1001 931 931 982 931 931 982 949 949 1001 950 950 1002 931 931 982 950 950 1002 932 932 983 932 932 983 950 950 1002 951 951 1003 932 932 983 951 951 1003 933 933 984 933 933 984 951 951 1003 952 952 1004 933 933 984 952 952 1004 934 934 985 934 934 985 952 952 1004 953 953 1005 934 934 985 953 953 1005 935 935 986 935 935 986 953 953 1005 936 936 1006 935 935 986 936 936 1006 918 918 987 936 936 988 954 954 1007 955 955 1008 936 936 988 955 955 1008 937 937 989 937 937 989 955 955 1008 956 956 1009 937 937 989 956 956 1009 938 938 990 938 938 990 956 956 1009 957 957 1010 938 938 990 957 957 1010 939 939 991 939 939 991 957 957 1010 958 958 1011 939 939 991 958 958 1011 940 940 992 940 940 992 958 958 1011 959 959 1012 940 940 992 959 959 1012 941 941 993 941 941 993 959 959 1012 960 960 1013 941 941 993 960 960 1013 942 942 994 942 942 994 960 960 1013 961 961 1014 942 942 994 961 961 1014 943 943 995 943 943 995 961 961 1014 962 962 1015 943 943 995 962 962 1015 944 944 996 944 944 996 962 962 1015 963 963 1016 944 944 996 963 963 1016 945 945 997 945 945 997 963 963 1016 964 964 1017 945 945 997 964 964 1017 946 946 998 946 946 998 964 964 1017 965 965 1018 946 946 998 965 965 1018 947 947 999 947 947 999 965 965 1018 966 966 1019 947 947 999 966 966 1019 948 948 1000 948 948 1000 966 966 1019 967 967 1020 948 948 1000 967 967 1020 949 949 1001 949 949 1001 967 967 1020 968 968 1021 949 949 1001 968 968 1021 950 950 1002 950 950 1002 968 968 1021 969 969 1022 950 950 1002 969 969 1022 951 951 1003 951 951 1003 969 969 1022 970 970 1023 951 951 1003 970 970 1023 952 952 1004 952 952 1004 970 970 1023 971 971 1024 952 952 1004 971 971 1024 953 953 1005 953 953 1005 971 971 1024 954 954 1025 953 953 1005 954 954 1025 936 936 1006 954 954 1007 972 972 1026 973 973 1027 954 954 1007 973 973 1027 955 955 1008 955 955 1008 973 973 1027 974 974 1028 955 955 1008 974 974 1028 956 956 1009 956 956 1009 974 974 1028 975 975 1029 956 956 1009 975 975 1029 957 957 1010 957 957 1010 975 975 1029 976 976 1030 957 957 1010 976 976 1030 958 958 1011 958 958 1011 976 976 1030 977 977 1031 958 958 1011 977 977 1031 959 959 1012 959 959 1012 977 977 1031 978 978 1032 959 959 1012 978 978 1032 960 960 1013 960 960 1013 978 978 1032 979 979 1033 960 960 1013 979 979 1033 961 961 1014 961 961 1014 979 979 1033 980 980 1034 961 961 1014 980 980 1034 962 962 1015 962 962 1015 980 980 1034 981 981 1035 962 962 1015 981 981 1035 963 963 1016 963 963 1016 981 981 1035 982 982 1036 963 963 1016 982 982 1036 964 964 1017 964 964 1017 982 982 1036 983 983 1037 964 964 1017 983 983 1037 965 965 1018 965 965 1018 983 983 1037 984 984 1038 965 965 1018 984 984 1038 966 966 1019 966 966 1019 984 984 1038 985 985 1039 966 966 1019 985 985 1039 967 967 1020 967 967 1020 985 985 1039 986 986 1040 967 967 1020 986 986 1040 968 968 1021 968 968 1021 986 986 1040 987 987 1041 968 968 1021 987 987 1041 969 969 1022 969 969 1022 987 987 1041 988 988 1042 969 969 1022 988 988 1042 970 970 1023 970 970 1023 988 988 1042 989 989 1043 970 970 1023 989 989 1043 971 971 1024 971 971 1024 989 989 1043 972 972 1044 971 971 1024 972 972 1044 954 954 1025 972 972 1026 990 990 1045 991 991 1046 972 972 1026 991 991 1046 973 973 1027 973 973 1027 991 991 1046 992 992 1047 973 973 1027 992 992 1047 974 974 1028 974 974 1028 992 992 1047 993 993 1048 974 974 1028 993 993 1048 975 975 1029 975 975 1029 993 993 1048 994 994 1049 975 975 1029 994 994 1049 976 976 1030 976 976 1030 994 994 1049 995 995 1050 976 976 1030 995 995 1050 977 977 1031 977 977 1031 995 995 1050 996 996 1051 977 977 1031 996 996 1051 978 978 1032 978 978 1032 996 996 1051 997 997 1052 978 978 1032 997 997 1052 979 979 1033 979 979 1033 997 997 1052 998 998 1053 979 979 1033 998 998 1053 980 980 1034 980 980 1034 998 998 1053 999 999 1054 980 980 1034 999 999 1054 981 981 1035 981 981 1035 999 999 1054 1000 1000 1055 981 981 1035 1000 1000 1055 982 982 1036 982 982 1036 1000 1000 1055 1001 1001 1056 982 982 1036 1001 1001 1056 983 983 1037 983 983 1037 1001 1001 1056 1002 1002 1057 983 983 1037 1002 1002 1057 984 984 1038 984 984 1038 1002 1002 1057 1003 1003 1058 984 984 1038 1003 1003 1058 985 985 1039 985 985 1039 1003 1003 1058 1004 1004 1059 985 985 1039 1004 1004 1059 986 986 1040 986 986 1040 1004 1004 1059 1005 1005 1060 986 986 1040 1005 1005 1060 987 987 1041 987 987 1041 1005 1005 1060 1006 1006 1061 987 987 1041 1006 1006 1061 988 988 1042 988 988 1042 1006 1006 1061 1007 1007 1062 988 988 1042 1007 1007 1062 989 989 1043 989 989 1043 1007 1007 1062 990 990 1063 989 989 1043 990 990 1063 972 972 1044 990 990 1045 1008 1008 1064 1009 1009 1065 990 990 1045 1009 1009 1065 991 991 1046 991 991 1046 1009 1009 1065 1010 1010 1066 991 991 1046 1010 1010 1066 992 992 1047 992 992 1047 1010 1010 1066 1011 1011 1067 992 992 1047 1011 1011 1067 993 993 1048 993 993 1048 1011 1011 1067 1012 1012 1068 993 993 1048 1012 1012 1068 994 994 1049 994 994 1049 1012 1012 1068 1013 1013 1069 994 994 1049 1013 1013 1069 995 995 1050 995 995 1050 1013 1013 1069 1014 1014 1070 995 995 1050 1014 1014 1070 996 996 1051 996 996 1051 1014 1014 1070 1015 1015 1071 996 996 1051 1015 1015 1071 997 997 1052 997 997 1052 1015 1015 1071 1016 1016 1072 997 997 1052 1016 1016 1072 998 998 1053 998 998 1053 1016 1016 1072 1017 1017 1073 998 998 1053 1017 1017 1073 999 999 1054 999 999 1054 1017 1017 1073 1018 1018 1074 999 999 1054 1018 1018 1074 1000 1000 1055 1000 1000 1055 1018 1018 1074 1019 1019 1075 1000 1000 1055 1019 1019 1075 1001 1001 1056 1001 1001 1056 1019 1019 1075 1020 1020 1076 1001 1001 1056 1020 1020 1076 1002 1002 1057 1002 1002 1057 1020 1020 1076 1021 1021 1077 1002 1002 1057 1021 1021 1077 1003 1003 1058 1003 1003 1058 1021 1021 1077 1022 1022 1078 1003 1003 1058 1022 1022 1078 1004 1004 1059 1004 1004 1059 1022 1022 1078 1023 1023 1079 1004 1004 1059 1023 1023 1079 1005 1005 1060 1005 1005 1060 1023 1023 1079 1024 1024 1080 1005 1005 1060 1024 1024 1080 1006 1006 1061 1006 1006 1061 1024 1024 1080 1025 1025 1081 1006 1006 1061 1025 1025 1081 1007 1007 1062 1007 1007 1062 1025 1025 1081 1008 1008 1082 1007 1007 1062 1008 1008 1082 990 990 1063 1008 1008 1064 1026 1026 1083 1027 1027 1084 1008 1008 1064 1027 1027 1084 1009 1009 1065 1009 1009 1065 1027 1027 1084 1028 1028 1085 1009 1009 1065 1028 1028 1085 1010 1010 1066 1010 1010 1066 1028 1028 1085 1029 1029 1086 1010 1010 1066 1029 1029 1086 1011 1011 1067 1011 1011 1067 1029 1029 1086 1030 1030 1087 1011 1011 1067 1030 1030 1087 1012 1012 1068 1012 1012 1068 1030 1030 1087 1031 1031 1088 1012 1012 1068 1031 1031 1088 1013 1013 1069 1013 1013 1069 1031 1031 1088 1032 1032 1089 1013 1013 1069 1032 1032 1089 1014 1014 1070 1014 1014 1070 1032 1032 1089 1033 1033 1090 1014 1014 1070 1033 1033 1090 1015 1015 1071 1015 1015 1071 1033 1033 1090 1034 1034 1091 1015 1015 1071 1034 1034 1091 1016 1016 1072 1016 1016 1072 1034 1034 1091 1035 1035 1092 1016 1016 1072 1035 1035 1092 1017 1017 1073 1017 1017 1073 1035 1035 1092 1036 1036 1093 1017 1017 1073 1036 1036 1093 1018 1018 1074 1018 1018 1074 1036 1036 1093 1037 1037 1094 1018 1018 1074 1037 1037 1094 1019 1019 1075 1019 1019 1075 1037 1037 1094 1038 1038 1095 1019 1019 1075 1038 1038 1095 1020 1020 1076 1020 1020 1076 1038 1038 1095 1039 1039 1096 1020 1020 1076 1039 1039 1096 1021 1021 1077 1021 1021 1077 1039 1039 1096 1040 1040 1097 1021 1021 1077 1040 1040 1097 1022 1022 1078 1022 1022 1078 1040 1040 1097 1041 1041 1098 1022 1022 1078 1041 1041 1098 1023 1023 1079 1023 1023 1079 1041 1041 1098 1042 1042 1099 1023 1023 1079 1042 1042 1099 1024 1024 1080 1024 1024 1080 1042 1042 1099 1043 1043 1100 1024 1024 1080 1043 1043 1100 1025 1025 1081 1025 1025 1081 1043 1043 1100 1026 1026 1101 1025 1025 1081 1026 1026 1101 1008 1008 1082 1026 1026 1083 1044 1044 1102 1045 1045 1103 1026 1026 1083 1045 1045 1103 1027 1027 1084 1027 1027 1084 1045 1045 1103 1046 1046 1104 1027 1027 1084 1046 1046 1104 1028 1028 1085 1028 1028 1085 1046 1046 1104 1047 1047 1105 1028 1028 1085 1047 1047 1105 1029 1029 1086 1029 1029 1086 1047 1047 1105 1048 1048 1106 1029 1029 1086 1048 1048 1106 1030 1030 1087 1030 1030 1087 1048 1048 1106 1049 1049 1107 1030 1030 1087 1049 1049 1107 1031 1031 1088 1031 1031 1088 1049 1049 1107 1050 1050 1108 1031 1031 1088 1050 1050 1108 1032 1032 1089 1032 1032 1089 1050 1050 1108 1051 1051 1109 1032 1032 1089 1051 1051 1109 1033 1033 1090 1033 1033 1090 1051 1051 1109 1052 1052 1110 1033 1033 1090 1052 1052 1110 1034 1034 1091 1034 1034 1091 1052 1052 1110 1053 1053 1111 1034 1034 1091 1053 1053 1111 1035 1035 1092 1035 1035 1092 1053 1053 1111 1054 1054 1112 1035 1035 1092 1054 1054 1112 1036 1036 1093 1036 1036 1093 1054 1054 1112 1055 1055 1113 1036 1036 1093 1055 1055 1113 1037 1037 1094 1037 1037 1094 1055 1055 1113 1056 1056 1114 1037 1037 1094 1056 1056 1114 1038 1038 1095 1038 1038 1095 1056 1056 1114 1057 1057 1115 1038 1038 1095 1057 1057 1115 1039 1039 1096 1039 1039 1096 1057 1057 1115 1058 1058 1116 1039 1039 1096 1058 1058 1116 1040 1040 1097 1040 1040 1097 1058 1058 1116 1059 1059 1117 1040 1040 1097 1059 1059 1117 1041 1041 1098 1041 1041 1098 1059 1059 1117 1060 1060 1118 1041 1041 1098 1060 1060 1118 1042 1042 1099 1042 1042 1099 1060 1060 1118 1061 1061 1119 1042 1042 1099 1061 1061 1119 1043 1043 1100 1043 1043 1100 1061 1061 1119 1044 1044 1120 1043 1043 1100 1044 1044 1120 1026 1026 1101 1044 1044 1102 1062 1062 1121 1063 1063 1122 1044 1044 1102 1063 1063 1122 1045 1045 1103 1045 1045 1103 1063 1063 1122 1064 1064 1123 1045 1045 1103 1064 1064 1123 1046 1046 1104 1046 1046 1104 1064 1064 1123 1065 1065 1124 1046 1046 1104 1065 1065 1124 1047 1047 1105 1047 1047 1105 1065 1065 1124 1066 1066 1125 1047 1047 1105 1066 1066 1125 1048 1048 1106 1048 1048 1106 1066 1066 1125 1067 1067 1126 1048 1048 1106 1067 1067 1126 1049 1049 1107 1049 1049 1107 1067 1067 1126 1068 1068 1127 1049 1049 1107 1068 1068 1127 1050 1050 1108 1050 1050 1108 1068 1068 1127 1069 1069 1128 1050 1050 1108 1069 1069 1128 1051 1051 1109 1051 1051 1109 1069 1069 1128 1070 1070 1129 1051 1051 1109 1070 1070 1129 1052 1052 1110 1052 1052 1110 1070 1070 1129 1071 1071 1130 1052 1052 1110 1071 1071 1130 1053 1053 1111 1053 1053 1111 1071 1071 1130 1072 1072 1131 1053 1053 1111 1072 1072 1131 1054 1054 1112 1054 1054 1112 1072 1072 1131 1073 1073 1132 1054 1054 1112 1073 1073 1132 1055 1055 1113 1055 1055 1113 1073 1073 1132 1074 1074 1133 1055 1055 1113 1074 1074 1133 1056 1056 1114 1056 1056 1114 1074 1074 1133 1075 1075 1134 1056 1056 1114 1075 1075 1134 1057 1057 1115 1057 1057 1115 1075 1075 1134 1076 1076 1135 1057 1057 1115 1076 1076 1135 1058 1058 1116 1058 1058 1116 1076 1076 1135 1077 1077 1136 1058 1058 1116 1077 1077 1136 1059 1059 1117 1059 1059 1117 1077 1077 1136 1078 1078 1137 1059 1059 1117 1078 1078 1137 1060 1060 1118 1060 1060 1118 1078 1078 1137 1079 1079 1138 1060 1060 1118 1079 1079 1138 1061 1061 1119 1061 1061 1119 1079 1079 1138 1062 1062 1139 1061 1061 1119 1062 1062 1139 1044 1044 1120 1062 1062 1121 1080 1080 1140 1081 1081 1141 1062 1062 1121 1081 1081 1141 1063 1063 1122 1063 1063 1122 1081 1081 1141 1082 1082 1142 1063 1063 1122 1082 1082 1142 1064 1064 1123 1064 1064 1123 1082 1082 1142 1083 1083 1143 1064 1064 1123 1083 1083 1143 1065 1065 1124 1065 1065 1124 1083 1083 1143 1084 1084 1144 1065 1065 1124 1084 1084 1144 1066 1066 1125 1066 1066 1125 1084 1084 1144 1085 1085 1145 1066 1066 1125 1085 1085 1145 1067 1067 1126 1067 1067 1126 1085 1085 1145 1086 1086 1146 1067 1067 1126 1086 1086 1146 1068 1068 1127 1068 1068 1127 1086 1086 1146 1087 1087 1147 1068 1068 1127 1087 1087 1147 1069 1069 1128 1069 1069 1128 1087 1087 1147 1088 1088 1148 1069 1069 1128 1088 1088 1148 1070 1070 1129 1070 1070 1129 1088 1088 1148 1089 1089 1149 1070 1070 1129 1089 1089 1149 1071 1071 1130 1071 1071 1130 1089 1089 1149 1090 1090 1150 1071 1071 1130 1090 1090 1150 1072 1072 1131 1072 1072 1131 1090 1090 1150 1091 1091 1151 1072 1072 1131 1091 1091 1151 1073 1073 1132 1073 1073 1132 1091 1091 1151 1092 1092 1152 1073 1073 1132 1092 1092 1152 1074 1074 1133 1074 1074 1133 1092 1092 1152 1093 1093 1153 1074 1074 1133 1093 1093 1153 1075 1075 1134 1075 1075 1134 1093 1093 1153 1094 1094 1154 1075 1075 1134 1094 1094 1154 1076 1076 1135 1076 1076 1135 1094 1094 1154 1095 1095 1155 1076 1076 1135 1095 1095 1155 1077 1077 1136 1077 1077 1136 1095 1095 1155 1096 1096 1156 1077 1077 1136 1096 1096 1156 1078 1078 1137 1078 1078 1137 1096 1096 1156 1097 1097 1157 1078 1078 1137 1097 1097 1157 1079 1079 1138 1079 1079 1138 1097 1097 1157 1080 1080 1158 1079 1079 1138 1080 1080 1158 1062 1062 1139 1080 1080 1140 1098 1098 1159 1099 1099 1160 1080 1080 1140 1099 1099 1160 1081 1081 1141 1081 1081 1141 1099 1099 1160 1100 1100 1161 1081 1081 1141 1100 1100 1161 1082 1082 1142 1082 1082 1142 1100 1100 1161 1101 1101 1162 1082 1082 1142 1101 1101 1162 1083 1083 1143 1083 1083 1143 1101 1101 1162 1102 1102 1163 1083 1083 1143 1102 1102 1163 1084 1084 1144 1084 1084 1144 1102 1102 1163 1103 1103 1164 1084 1084 1144 1103 1103 1164 1085 1085 1145 1085 1085 1145 1103 1103 1164 1104 1104 1165 1085 1085 1145 1104 1104 1165 1086 1086 1146 1086 1086 1146 1104 1104 1165 1105 1105 1166 1086 1086 1146 1105 1105 1166 1087 1087 1147 1087 1087 1147 1105 1105 1166 1106 1106 1167 1087 1087 1147 1106 1106 1167 1088 1088 1148 1088 1088 1148 1106 1106 1167 1107 1107 1168 1088 1088 1148 1107 1107 1168 1089 1089 1149 1089 1089 1149 1107 1107 1168 1108 1108 1169 1089 1089 1149 1108 1108 1169 1090 1090 1150 1090 1090 1150 1108 1108 1169 1109 1109 1170 1090 1090 1150 1109 1109 1170 1091 1091 1151 1091 1091 1151 1109 1109 1170 1110 1110 1171 1091 1091 1151 1110 1110 1171 1092 1092 1152 1092 1092 1152 1110 1110 1171 1111 1111 1172 1092 1092 1152 1111 1111 1172 1093 1093 1153 1093 1093 1153 1111 1111 1172 1112 1112 1173 1093 1093 1153 1112 1112 1173 1094 1094 1154 1094 1094 1154 1112 1112 1173 1113 1113 1174 1094 1094 1154 1113 1113 1174 1095 1095 1155 1095 1095 1155 1113 1113 1174 1114 1114 1175 1095 1095 1155 1114 1114 1175 1096 1096 1156 1096 1096 1156 1114 1114 1175 1115 1115 1176 1096 1096 1156 1115 1115 1176 1097 1097 1157 1097 1097 1157 1115 1115 1176 1098 1098 1177 1097 1097 1157 1098 1098 1177 1080 1080 1158 1098 1098 1159 1116 1116 1178 1117 1117 1179 1098 1098 1159 1117 1117 1179 1099 1099 1160 1099 1099 1160 1117 1117 1179 1118 1118 1180 1099 1099 1160 1118 1118 1180 1100 1100 1161 1100 1100 1161 1118 1118 1180 1119 1119 1181 1100 1100 1161 1119 1119 1181 1101 1101 1162 1101 1101 1162 1119 1119 1181 1120 1120 1182 1101 1101 1162 1120 1120 1182 1102 1102 1163 1102 1102 1163 1120 1120 1182 1121 1121 1183 1102 1102 1163 1121 1121 1183 1103 1103 1164 1103 1103 1164 1121 1121 1183 1122 1122 1184 1103 1103 1164 1122 1122 1184 1104 1104 1165 1104 1104 1165 1122 1122 1184 1123 1123 1185 1104 1104 1165 1123 1123 1185 1105 1105 1166 1105 1105 1166 1123 1123 1185 1124 1124 1186 1105 1105 1166 1124 1124 1186 1106 1106 1167 1106 1106 1167 1124 1124 1186 1125 1125 1187 1106 1106 1167 1125 1125 1187 1107 1107 1168 1107 1107 1168 1125 1125 1187 1126 1126 1188 1107 1107 1168 1126 1126 1188 1108 1108 1169 1108 1108 1169 1126 1126 1188 1127 1127 1189 1108 1108 1169 1127 1127 1189 1109 1109 1170 1109 1109 1170 1127 1127 1189 1128 1128 1190 1109 1109 1170 1128 1128 1190 1110 1110 1171 1110 1110 1171 1128 1128 1190 1129 1129 1191 1110 1110 1171 1129 1129 1191 1111 1111 1172 1111 1111 1172 1129 1129 1191 1130 1130 1192 1111 1111 1172 1130 1130 1192 1112 1112 1173 1112 1112 1173 1130 1130 1192 1131 1131 1193 1112 1112 1173 1131 1131 1193 1113 1113 1174 1113 1113 1174 1131 1131 1193 1132 1132 1194 1113 1113 1174 1132 1132 1194 1114 1114 1175 1114 1114 1175 1132 1132 1194 1133 1133 1195 1114 1114 1175 1133 1133 1195 1115 1115 1176 1115 1115 1176 1133 1133 1195 1116 1116 1196 1115 1115 1176 1116 1116 1196 1098 1098 1177 1116 1116 1178 1134 1134 1197 1135 1135 1198 1116 1116 1178 1135 1135 1198 1117 1117 1179 1117 1117 1179 1135 1135 1198 1136 1136 1199 1117 1117 1179 1136 1136 1199 1118 1118 1180 1118 1118 1180 1136 1136 1199 1137 1137 1200 1118 1118 1180 1137 1137 1200 1119 1119 1181 1119 1119 1181 1137 1137 1200 1138 1138 1201 1119 1119 1181 1138 1138 1201 1120 1120 1182 1120 1120 1182 1138 1138 1201 1139 1139 1202 1120 1120 1182 1139 1139 1202 1121 1121 1183 1121 1121 1183 1139 1139 1202 1140 1140 1203 1121 1121 1183 1140 1140 1203 1122 1122 1184 1122 1122 1184 1140 1140 1203 1141 1141 1204 1122 1122 1184 1141 1141 1204 1123 1123 1185 1123 1123 1185 1141 1141 1204 1142 1142 1205 1123 1123 1185 1142 1142 1205 1124 1124 1186 1124 1124 1186 1142 1142 1205 1143 1143 1206 1124 1124 1186 1143 1143 1206 1125 1125 1187 1125 1125 1187 1143 1143 1206 1144 1144 1207 1125 1125 1187 1144 1144 1207 1126 1126 1188 1126 1126 1188 1144 1144 1207 1145 1145 1208 1126 1126 1188 1145 1145 1208 1127 1127 1189 1127 1127 1189 1145 1145 1208 1146 1146 1209 1127 1127 1189 1146 1146 1209 1128 1128 1190 1128 1128 1190 1146 1146 1209 1147 1147 1210 1128 1128 1190 1147 1147 1210 1129 1129 1191 1129 1129 1191 1147 1147 1210 1148 1148 1211 1129 1129 1191 1148 1148 1211 1130 1130 1192 1130 1130 1192 1148 1148 1211 1149 1149 1212 1130 1130 1192 1149 1149 1212 1131 1131 1193 1131 1131 1193 1149 1149 1212 1150 1150 1213 1131 1131 1193 1150 1150 1213 1132 1132 1194 1132 1132 1194 1150 1150 1213 1151 1151 1214 1132 1132 1194 1151 1151 1214 1133 1133 1195 1133 1133 1195 1151 1151 1214 1134 1134 1215 1133 1133 1195 1134 1134 1215 1116 1116 1196 1134 1134 1197 1152 1152 1216 1153 1153 1217 1134 1134 1197 1153 1153 1217 1135 1135 1198 1135 1135 1198 1153 1153 1217 1154 1154 1218 1135 1135 1198 1154 1154 1218 1136 1136 1199 1136 1136 1199 1154 1154 1218 1155 1155 1219 1136 1136 1199 1155 1155 1219 1137 1137 1200 1137 1137 1200 1155 1155 1219 1156 1156 1220 1137 1137 1200 1156 1156 1220 1138 1138 1201 1138 1138 1201 1156 1156 1220 1157 1157 1221 1138 1138 1201 1157 1157 1221 1139 1139 1202 1139 1139 1202 1157 1157 1221 1158 1158 1222 1139 1139 1202 1158 1158 1222 1140 1140 1203 1140 1140 1203 1158 1158 1222 1159 1159 1223 1140 1140 1203 1159 1159 1223 1141 1141 1204 1141 1141 1204 1159 1159 1223 1160 1160 1224 1141 1141 1204 1160 1160 1224 1142 1142 1205 1142 1142 1205 1160 1160 1224 1161 1161 1225 1142 1142 1205 1161 1161 1225 1143 1143 1206 1143 1143 1206 1161 1161 1225 1162 1162 1226 1143 1143 1206 1162 1162 1226 1144 1144 1207 1144 1144 1207 1162 1162 1226 1163 1163 1227 1144 1144 1207 1163 1163 1227 1145 1145 1208 1145 1145 1208 1163 1163 1227 1164 1164 1228 1145 1145 1208 1164 1164 1228 1146 1146 1209 1146 1146 1209 1164 1164 1228 1165 1165 1229 1146 1146 1209 1165 1165 1229 1147 1147 1210 1147 1147 1210 1165 1165 1229 1166 1166 1230 1147 1147 1210 1166 1166 1230 1148 1148 1211 1148 1148 1211 1166 1166 1230 1167 1167 1231 1148 1148 1211 1167 1167 1231 1149 1149 1212 1149 1149 1212 1167 1167 1231 1168 1168 1232 1149 1149 1212 1168 1168 1232 1150 1150 1213 1150 1150 1213 1168 1168 1232 1169 1169 1233 1150 1150 1213 1169 1169 1233 1151 1151 1214 1151 1151 1214 1169 1169 1233 1152 1152 1234 1151 1151 1214 1152 1152 1234 1134 1134 1215 1152 1152 1216 1170 1170 1235 1171 1171 1236 1152 1152 1216 1171 1171 1236 1153 1153 1217 1153 1153 1217 1171 1171 1236 1172 1172 1237 1153 1153 1217 1172 1172 1237 1154 1154 1218 1154 1154 1218 1172 1172 1237 1173 1173 1238 1154 1154 1218 1173 1173 1238 1155 1155 1219 1155 1155 1219 1173 1173 1238 1174 1174 1239 1155 1155 1219 1174 1174 1239 1156 1156 1220 1156 1156 1220 1174 1174 1239 1175 1175 1240 1156 1156 1220 1175 1175 1240 1157 1157 1221 1157 1157 1221 1175 1175 1240 1176 1176 1241 1157 1157 1221 1176 1176 1241 1158 1158 1222 1158 1158 1222 1176 1176 1241 1177 1177 1242 1158 1158 1222 1177 1177 1242 1159 1159 1223 1159 1159 1223 1177 1177 1242 1178 1178 1243 1159 1159 1223 1178 1178 1243 1160 1160 1224 1160 1160 1224 1178 1178 1243 1179 1179 1244 1160 1160 1224 1179 1179 1244 1161 1161 1225 1161 1161 1225 1179 1179 1244 1180 1180 1245 1161 1161 1225 1180 1180 1245 1162 1162 1226 1162 1162 1226 1180 1180 1245 1181 1181 1246 1162 1162 1226 1181 1181 1246 1163 1163 1227 1163 1163 1227 1181 1181 1246 1182 1182 1247 1163 1163 1227 1182 1182 1247 1164 1164 1228 1164 1164 1228 1182 1182 1247 1183 1183 1248 1164 1164 1228 1183 1183 1248 1165 1165 1229 1165 1165 1229 1183 1183 1248 1184 1184 1249 1165 1165 1229 1184 1184 1249 1166 1166 1230 1166 1166 1230 1184 1184 1249 1185 1185 1250 1166 1166 1230 1185 1185 1250 1167 1167 1231 1167 1167 1231 1185 1185 1250 1186 1186 1251 1167 1167 1231 1186 1186 1251 1168 1168 1232 1168 1168 1232 1186 1186 1251 1187 1187 1252 1168 1168 1232 1187 1187 1252 1169 1169 1233 1169 1169 1233 1187 1187 1252 1170 1170 1253 1169 1169 1233 1170 1170 1253 1152 1152 1234 1170 1170 1235 1188 1188 1254 1189 1189 1255 1170 1170 1235 1189 1189 1255 1171 1171 1236 1171 1171 1236 1189 1189 1255 1190 1190 1256 1171 1171 1236 1190 1190 1256 1172 1172 1237 1172 1172 1237 1190 1190 1256 1191 1191 1257 1172 1172 1237 1191 1191 1257 1173 1173 1238 1173 1173 1238 1191 1191 1257 1192 1192 1258 1173 1173 1238 1192 1192 1258 1174 1174 1239 1174 1174 1239 1192 1192 1258 1193 1193 1259 1174 1174 1239 1193 1193 1259 1175 1175 1240 1175 1175 1240 1193 1193 1259 1194 1194 1260 1175 1175 1240 1194 1194 1260 1176 1176 1241 1176 1176 1241 1194 1194 1260 1195 1195 1261 1176 1176 1241 1195 1195 1261 1177 1177 1242 1177 1177 1242 1195 1195 1261 1196 1196 1262 1177 1177 1242 1196 1196 1262 1178 1178 1243 1178 1178 1243 1196 1196 1262 1197 1197 1263 1178 1178 1243 1197 1197 1263 1179 1179 1244 1179 1179 1244 1197 1197 1263 1198 1198 1264 1179 1179 1244 1198 1198 1264 1180 1180 1245 1180 1180 1245 1198 1198 1264 1199 1199 1265 1180 1180 1245 1199 1199 1265 1181 1181 1246 1181 1181 1246 1199 1199 1265 1200 1200 1266 1181 1181 1246 1200 1200 1266 1182 1182 1247 1182 1182 1247 1200 1200 1266 1201 1201 1267 1182 1182 1247 1201 1201 1267 1183 1183 1248 1183 1183 1248 1201 1201 1267 1202 1202 1268 1183 1183 1248 1202 1202 1268 1184 1184 1249 1184 1184 1249 1202 1202 1268 1203 1203 1269 1184 1184 1249 1203 1203 1269 1185 1185 1250 1185 1185 1250 1203 1203 1269 1204 1204 1270 1185 1185 1250 1204 1204 1270 1186 1186 1251 1186 1186 1251 1204 1204 1270 1205 1205 1271 1186 1186 1251 1205 1205 1271 1187 1187 1252 1187 1187 1252 1205 1205 1271 1188 1188 1272 1187 1187 1252 1188 1188 1272 1170 1170 1253 1188 1188 1254 1206 1206 1273 1207 1207 1274 1188 1188 1254 1207 1207 1274 1189 1189 1255 1189 1189 1255 1207 1207 1274 1208 1208 1275 1189 1189 1255 1208 1208 1275 1190 1190 1256 1190 1190 1256 1208 1208 1275 1209 1209 1276 1190 1190 1256 1209 1209 1276 1191 1191 1257 1191 1191 1257 1209 1209 1276 1210 1210 1277 1191 1191 1257 1210 1210 1277 1192 1192 1258 1192 1192 1258 1210 1210 1277 1211 1211 1278 1192 1192 1258 1211 1211 1278 1193 1193 1259 1193 1193 1259 1211 1211 1278 1212 1212 1279 1193 1193 1259 1212 1212 1279 1194 1194 1260 1194 1194 1260 1212 1212 1279 1213 1213 1280 1194 1194 1260 1213 1213 1280 1195 1195 1261 1195 1195 1261 1213 1213 1280 1214 1214 1281 1195 1195 1261 1214 1214 1281 1196 1196 1262 1196 1196 1262 1214 1214 1281 1215 1215 1282 1196 1196 1262 1215 1215 1282 1197 1197 1263 1197 1197 1263 1215 1215 1282 1216 1216 1283 1197 1197 1263 1216 1216 1283 1198 1198 1264 1198 1198 1264 1216 1216 1283 1217 1217 1284 1198 1198 1264 1217 1217 1284 1199 1199 1265 1199 1199 1265 1217 1217 1284 1218 1218 1285 1199 1199 1265 1218 1218 1285 1200 1200 1266 1200 1200 1266 1218 1218 1285 1219 1219 1286 1200 1200 1266 1219 1219 1286 1201 1201 1267 1201 1201 1267 1219 1219 1286 1220 1220 1287 1201 1201 1267 1220 1220 1287 1202 1202 1268 1202 1202 1268 1220 1220 1287 1221 1221 1288 1202 1202 1268 1221 1221 1288 1203 1203 1269 1203 1203 1269 1221 1221 1288 1222 1222 1289 1203 1203 1269 1222 1222 1289 1204 1204 1270 1204 1204 1270 1222 1222 1289 1223 1223 1290 1204 1204 1270 1223 1223 1290 1205 1205 1271 1205 1205 1271 1223 1223 1290 1206 1206 1291 1205 1205 1271 1206 1206 1291 1188 1188 1272 1206 1206 1273 1224 1224 1292 1225 1225 1293 1206 1206 1273 1225 1225 1293 1207 1207 1274 1207 1207 1274 1225 1225 1293 1226 1226 1294 1207 1207 1274 1226 1226 1294 1208 1208 1275 1208 1208 1275 1226 1226 1294 1227 1227 1295 1208 1208 1275 1227 1227 1295 1209 1209 1276 1209 1209 1276 1227 1227 1295 1228 1228 1296 1209 1209 1276 1228 1228 1296 1210 1210 1277 1210 1210 1277 1228 1228 1296 1229 1229 1297 1210 1210 1277 1229 1229 1297 1211 1211 1278 1211 1211 1278 1229 1229 1297 1230 1230 1298 1211 1211 1278 1230 1230 1298 1212 1212 1279 1212 1212 1279 1230 1230 1298 1231 1231 1299 1212 1212 1279 1231 1231 1299 1213 1213 1280 1213 1213 1280 1231 1231 1299 1232 1232 1300 1213 1213 1280 1232 1232 1300 1214 1214 1281 1214 1214 1281 1232 1232 1300 1233 1233 1301 1214 1214 1281 1233 1233 1301 1215 1215 1282 1215 1215 1282 1233 1233 1301 1234 1234 1302 1215 1215 1282 1234 1234 1302 1216 1216 1283 1216 1216 1283 1234 1234 1302 1235 1235 1303 1216 1216 1283 1235 1235 1303 1217 1217 1284 1217 1217 1284 1235 1235 1303 1236 1236 1304 1217 1217 1284 1236 1236 1304 1218 1218 1285 1218 1218 1285 1236 1236 1304 1237 1237 1305 1218 1218 1285 1237 1237 1305 1219 1219 1286 1219 1219 1286 1237 1237 1305 1238 1238 1306 1219 1219 1286 1238 1238 1306 1220 1220 1287 1220 1220 1287 1238 1238 1306 1239 1239 1307 1220 1220 1287 1239 1239 1307 1221 1221 1288 1221 1221 1288 1239 1239 1307 1240 1240 1308 1221 1221 1288 1240 1240 1308 1222 1222 1289 1222 1222 1289 1240 1240 1308 1241 1241 1309 1222 1222 1289 1241 1241 1309 1223 1223 1290 1223 1223 1290 1241 1241 1309 1224 1224 1310 1223 1223 1290 1224 1224 1310 1206 1206 1291 1224 1224 1292 1242 1242 1311 1243 1243 1312 1224 1224 1292 1243 1243 1312 1225 1225 1293 1225 1225 1293 1243 1243 1312 1244 1244 1313 1225 1225 1293 1244 1244 1313 1226 1226 1294 1226 1226 1294 1244 1244 1313 1245 1245 1314 1226 1226 1294 1245 1245 1314 1227 1227 1295 1227 1227 1295 1245 1245 1314 1246 1246 1315 1227 1227 1295 1246 1246 1315 1228 1228 1296 1228 1228 1296 1246 1246 1315 1247 1247 1316 1228 1228 1296 1247 1247 1316 1229 1229 1297 1229 1229 1297 1247 1247 1316 1248 1248 1317 1229 1229 1297 1248 1248 1317 1230 1230 1298 1230 1230 1298 1248 1248 1317 1249 1249 1318 1230 1230 1298 1249 1249 1318 1231 1231 1299 1231 1231 1299 1249 1249 1318 1250 1250 1319 1231 1231 1299 1250 1250 1319 1232 1232 1300 1232 1232 1300 1250 1250 1319 1251 1251 1320 1232 1232 1300 1251 1251 1320 1233 1233 1301 1233 1233 1301 1251 1251 1320 1252 1252 1321 1233 1233 1301 1252 1252 1321 1234 1234 1302 1234 1234 1302 1252 1252 1321 1253 1253 1322 1234 1234 1302 1253 1253 1322 1235 1235 1303 1235 1235 1303 1253 1253 1322 1254 1254 1323 1235 1235 1303 1254 1254 1323 1236 1236 1304 1236 1236 1304 1254 1254 1323 1255 1255 1324 1236 1236 1304 1255 1255 1324 1237 1237 1305 1237 1237 1305 1255 1255 1324 1256 1256 1325 1237 1237 1305 1256 1256 1325 1238 1238 1306 1238 1238 1306 1256 1256 1325 1257 1257 1326 1238 1238 1306 1257 1257 1326 1239 1239 1307 1239 1239 1307 1257 1257 1326 1258 1258 1327 1239 1239 1307 1258 1258 1327 1240 1240 1308 1240 1240 1308 1258 1258 1327 1259 1259 1328 1240 1240 1308 1259 1259 1328 1241 1241 1309 1241 1241 1309 1259 1259 1328 1242 1242 1329 1241 1241 1309 1242 1242 1329 1224 1224 1310 1242 1242 1311 1260 1260 1330 1261 1261 1331 1242 1242 1311 1261 1261 1331 1243 1243 1312 1243 1243 1312 1261 1261 1331 1262 1262 1332 1243 1243 1312 1262 1262 1332 1244 1244 1313 1244 1244 1313 1262 1262 1332 1263 1263 1333 1244 1244 1313 1263 1263 1333 1245 1245 1314 1245 1245 1314 1263 1263 1333 1264 1264 1334 1245 1245 1314 1264 1264 1334 1246 1246 1315 1246 1246 1315 1264 1264 1334 1265 1265 1335 1246 1246 1315 1265 1265 1335 1247 1247 1316 1247 1247 1316 1265 1265 1335 1266 1266 1336 1247 1247 1316 1266 1266 1336 1248 1248 1317 1248 1248 1317 1266 1266 1336 1267 1267 1337 1248 1248 1317 1267 1267 1337 1249 1249 1318 1249 1249 1318 1267 1267 1337 1268 1268 1338 1249 1249 1318 1268 1268 1338 1250 1250 1319 1250 1250 1319 1268 1268 1338 1269 1269 1339 1250 1250 1319 1269 1269 1339 1251 1251 1320 1251 1251 1320 1269 1269 1339 1270 1270 1340 1251 1251 1320 1270 1270 1340 1252 1252 1321 1252 1252 1321 1270 1270 1340 1271 1271 1341 1252 1252 1321 1271 1271 1341 1253 1253 1322 1253 1253 1322 1271 1271 1341 1272 1272 1342 1253 1253 1322 1272 1272 1342 1254 1254 1323 1254 1254 1323 1272 1272 1342 1273 1273 1343 1254 1254 1323 1273 1273 1343 1255 1255 1324 1255 1255 1324 1273 1273 1343 1274 1274 1344 1255 1255 1324 1274 1274 1344 1256 1256 1325 1256 1256 1325 1274 1274 1344 1275 1275 1345 1256 1256 1325 1275 1275 1345 1257 1257 1326 1257 1257 1326 1275 1275 1345 1276 1276 1346 1257 1257 1326 1276 1276 1346 1258 1258 1327 1258 1258 1327 1276 1276 1346 1277 1277 1347 1258 1258 1327 1277 1277 1347 1259 1259 1328 1259 1259 1328 1277 1277 1347 1260 1260 1348 1259 1259 1328 1260 1260 1348 1242 1242 1329 1260 1260 1330 1278 1278 1349 1279 1279 1350 1260 1260 1330 1279 1279 1350 1261 1261 1331 1261 1261 1331 1279 1279 1350 1280 1280 1351 1261 1261 1331 1280 1280 1351 1262 1262 1332 1262 1262 1332 1280 1280 1351 1281 1281 1352 1262 1262 1332 1281 1281 1352 1263 1263 1333 1263 1263 1333 1281 1281 1352 1282 1282 1353 1263 1263 1333 1282 1282 1353 1264 1264 1334 1264 1264 1334 1282 1282 1353 1283 1283 1354 1264 1264 1334 1283 1283 1354 1265 1265 1335 1265 1265 1335 1283 1283 1354 1284 1284 1355 1265 1265 1335 1284 1284 1355 1266 1266 1336 1266 1266 1336 1284 1284 1355 1285 1285 1356 1266 1266 1336 1285 1285 1356 1267 1267 1337 1267 1267 1337 1285 1285 1356 1286 1286 1357 1267 1267 1337 1286 1286 1357 1268 1268 1338 1268 1268 1338 1286 1286 1357 1287 1287 1358 1268 1268 1338 1287 1287 1358 1269 1269 1339 1269 1269 1339 1287 1287 1358 1288 1288 1359 1269 1269 1339 1288 1288 1359 1270 1270 1340 1270 1270 1340 1288 1288 1359 1289 1289 1360 1270 1270 1340 1289 1289 1360 1271 1271 1341 1271 1271 1341 1289 1289 1360 1290 1290 1361 1271 1271 1341 1290 1290 1361 1272 1272 1342 1272 1272 1342 1290 1290 1361 1291 1291 1362 1272 1272 1342 1291 1291 1362 1273 1273 1343 1273 1273 1343 1291 1291 1362 1292 1292 1363 1273 1273 1343 1292 1292 1363 1274 1274 1344 1274 1274 1344 1292 1292 1363 1293 1293 1364 1274 1274 1344 1293 1293 1364 1275 1275 1345 1275 1275 1345 1293 1293 1364 1294 1294 1365 1275 1275 1345 1294 1294 1365 1276 1276 1346 1276 1276 1346 1294 1294 1365 1295 1295 1366 1276 1276 1346 1295 1295 1366 1277 1277 1347 1277 1277 1347 1295 1295 1366 1278 1278 1367 1277 1277 1347 1278 1278 1367 1260 1260 1348 1278 1278 1349 1296 1296 1368 1297 1297 1369 1278 1278 1349 1297 1297 1369 1279 1279 1350 1279 1279 1350 1297 1297 1369 1298 1298 1370 1279 1279 1350 1298 1298 1370 1280 1280 1351 1280 1280 1351 1298 1298 1370 1299 1299 1371 1280 1280 1351 1299 1299 1371 1281 1281 1352 1281 1281 1352 1299 1299 1371 1300 1300 1372 1281 1281 1352 1300 1300 1372 1282 1282 1353 1282 1282 1353 1300 1300 1372 1301 1301 1373 1282 1282 1353 1301 1301 1373 1283 1283 1354 1283 1283 1354 1301 1301 1373 1302 1302 1374 1283 1283 1354 1302 1302 1374 1284 1284 1355 1284 1284 1355 1302 1302 1374 1303 1303 1375 1284 1284 1355 1303 1303 1375 1285 1285 1356 1285 1285 1356 1303 1303 1375 1304 1304 1376 1285 1285 1356 1304 1304 1376 1286 1286 1357 1286 1286 1357 1304 1304 1376 1305 1305 1377 1286 1286 1357 1305 1305 1377 1287 1287 1358 1287 1287 1358 1305 1305 1377 1306 1306 1378 1287 1287 1358 1306 1306 1378 1288 1288 1359 1288 1288 1359 1306 1306 1378 1307 1307 1379 1288 1288 1359 1307 1307 1379 1289 1289 1360 1289 1289 1360 1307 1307 1379 1308 1308 1380 1289 1289 1360 1308 1308 1380 1290 1290 1361 1290 1290 1361 1308 1308 1380 1309 1309 1381 1290 1290 1361 1309 1309 1381 1291 1291 1362 1291 1291 1362 1309 1309 1381 1310 1310 1382 1291 1291 1362 1310 1310 1382 1292 1292 1363 1292 1292 1363 1310 1310 1382 1311 1311 1383 1292 1292 1363 1311 1311 1383 1293 1293 1364 1293 1293 1364 1311 1311 1383 1312 1312 1384 1293 1293 1364 1312 1312 1384 1294 1294 1365 1294 1294 1365 1312 1312 1384 1313 1313 1385 1294 1294 1365 1313 1313 1385 1295 1295 1366 1295 1295 1366 1313 1313 1385 1296 1296 1386 1295 1295 1366 1296 1296 1386 1278 1278 1367 1296 1296 1368 1314 1314 1387 1315 1315 1388 1296 1296 1368 1315 1315 1388 1297 1297 1369 1297 1297 1369 1315 1315 1388 1316 1316 1389 1297 1297 1369 1316 1316 1389 1298 1298 1370 1298 1298 1370 1316 1316 1389 1317 1317 1390 1298 1298 1370 1317 1317 1390 1299 1299 1371 1299 1299 1371 1317 1317 1390 1318 1318 1391 1299 1299 1371 1318 1318 1391 1300 1300 1372 1300 1300 1372 1318 1318 1391 1319 1319 1392 1300 1300 1372 1319 1319 1392 1301 1301 1373 1301 1301 1373 1319 1319 1392 1320 1320 1393 1301 1301 1373 1320 1320 1393 1302 1302 1374 1302 1302 1374 1320 1320 1393 1321 1321 1394 1302 1302 1374 1321 1321 1394 1303 1303 1375 1303 1303 1375 1321 1321 1394 1322 1322 1395 1303 1303 1375 1322 1322 1395 1304 1304 1376 1304 1304 1376 1322 1322 1395 1323 1323 1396 1304 1304 1376 1323 1323 1396 1305 1305 1377 1305 1305 1377 1323 1323 1396 1324 1324 1397 1305 1305 1377 1324 1324 1397 1306 1306 1378 1306 1306 1378 1324 1324 1397 1325 1325 1398 1306 1306 1378 1325 1325 1398 1307 1307 1379 1307 1307 1379 1325 1325 1398 1326 1326 1399 1307 1307 1379 1326 1326 1399 1308 1308 1380 1308 1308 1380 1326 1326 1399 1327 1327 1400 1308 1308 1380 1327 1327 1400 1309 1309 1381 1309 1309 1381 1327 1327 1400 1328 1328 1401 1309 1309 1381 1328 1328 1401 1310 1310 1382 1310 1310 1382 1328 1328 1401 1329 1329 1402 1310 1310 1382 1329 1329 1402 1311 1311 1383 1311 1311 1383 1329 1329 1402 1330 1330 1403 1311 1311 1383 1330 1330 1403 1312 1312 1384 1312 1312 1384 1330 1330 1403 1331 1331 1404 1312 1312 1384 1331 1331 1404 1313 1313 1385 1313 1313 1385 1331 1331 1404 1314 1314 1405 1313 1313 1385 1314 1314 1405 1296 1296 1386 1314 1314 1387 1332 1332 1406 1333 1333 1407 1314 1314 1387 1333 1333 1407 1315 1315 1388 1315 1315 1388 1333 1333 1407 1334 1334 1408 1315 1315 1388 1334 1334 1408 1316 1316 1389 1316 1316 1389 1334 1334 1408 1335 1335 1409 1316 1316 1389 1335 1335 1409 1317 1317 1390 1317 1317 1390 1335 1335 1409 1336 1336 1410 1317 1317 1390 1336 1336 1410 1318 1318 1391 1318 1318 1391 1336 1336 1410 1337 1337 1411 1318 1318 1391 1337 1337 1411 1319 1319 1392 1319 1319 1392 1337 1337 1411 1338 1338 1412 1319 1319 1392 1338 1338 1412 1320 1320 1393 1320 1320 1393 1338 1338 1412 1339 1339 1413 1320 1320 1393 1339 1339 1413 1321 1321 1394 1321 1321 1394 1339 1339 1413 1340 1340 1414 1321 1321 1394 1340 1340 1414 1322 1322 1395 1322 1322 1395 1340 1340 1414 1341 1341 1415 1322 1322 1395 1341 1341 1415 1323 1323 1396 1323 1323 1396 1341 1341 1415 1342 1342 1416 1323 1323 1396 1342 1342 1416 1324 1324 1397 1324 1324 1397 1342 1342 1416 1343 1343 1417 1324 1324 1397 1343 1343 1417 1325 1325 1398 1325 1325 1398 1343 1343 1417 1344 1344 1418 1325 1325 1398 1344 1344 1418 1326 1326 1399 1326 1326 1399 1344 1344 1418 1345 1345 1419 1326 1326 1399 1345 1345 1419 1327 1327 1400 1327 1327 1400 1345 1345 1419 1346 1346 1420 1327 1327 1400 1346 1346 1420 1328 1328 1401 1328 1328 1401 1346 1346 1420 1347 1347 1421 1328 1328 1401 1347 1347 1421 1329 1329 1402 1329 1329 1402 1347 1347 1421 1348 1348 1422 1329 1329 1402 1348 1348 1422 1330 1330 1403 1330 1330 1403 1348 1348 1422 1349 1349 1423 1330 1330 1403 1349 1349 1423 1331 1331 1404 1331 1331 1404 1349 1349 1423 1332 1332 1424 1331 1331 1404 1332 1332 1424 1314 1314 1405 1332 1332 1406 1350 1350 1425 1351 1351 1426 1332 1332 1406 1351 1351 1426 1333 1333 1407 1333 1333 1407 1351 1351 1426 1352 1352 1427 1333 1333 1407 1352 1352 1427 1334 1334 1408 1334 1334 1408 1352 1352 1427 1353 1353 1428 1334 1334 1408 1353 1353 1428 1335 1335 1409 1335 1335 1409 1353 1353 1428 1354 1354 1429 1335 1335 1409 1354 1354 1429 1336 1336 1410 1336 1336 1410 1354 1354 1429 1355 1355 1430 1336 1336 1410 1355 1355 1430 1337 1337 1411 1337 1337 1411 1355 1355 1430 1356 1356 1431 1337 1337 1411 1356 1356 1431 1338 1338 1412 1338 1338 1412 1356 1356 1431 1357 1357 1432 1338 1338 1412 1357 1357 1432 1339 1339 1413 1339 1339 1413 1357 1357 1432 1358 1358 1433 1339 1339 1413 1358 1358 1433 1340 1340 1414 1340 1340 1414 1358 1358 1433 1359 1359 1434 1340 1340 1414 1359 1359 1434 1341 1341 1415 1341 1341 1415 1359 1359 1434 1360 1360 1435 1341 1341 1415 1360 1360 1435 1342 1342 1416 1342 1342 1416 1360 1360 1435 1361 1361 1436 1342 1342 1416 1361 1361 1436 1343 1343 1417 1343 1343 1417 1361 1361 1436 1362 1362 1437 1343 1343 1417 1362 1362 1437 1344 1344 1418 1344 1344 1418 1362 1362 1437 1363 1363 1438 1344 1344 1418 1363 1363 1438 1345 1345 1419 1345 1345 1419 1363 1363 1438 1364 1364 1439 1345 1345 1419 1364 1364 1439 1346 1346 1420 1346 1346 1420 1364 1364 1439 1365 1365 1440 1346 1346 1420 1365 1365 1440 1347 1347 1421 1347 1347 1421 1365 1365 1440 1366 1366 1441 1347 1347 1421 1366 1366 1441 1348 1348 1422 1348 1348 1422 1366 1366 1441 1367 1367 1442 1348 1348 1422 1367 1367 1442 1349 1349 1423 1349 1349 1423 1367 1367 1442 1350 1350 1443 1349 1349 1423 1350 1350 1443 1332 1332 1424 1350 1350 1425 1368 1368 1444 1369 1369 1445 1350 1350 1425 1369 1369 1445 1351 1351 1426 1351 1351 1426 1369 1369 1445 1370 1370 1446 1351 1351 1426 1370 1370 1446 1352 1352 1427 1352 1352 1427 1370 1370 1446 1371 1371 1447 1352 1352 1427 1371 1371 1447 1353 1353 1428 1353 1353 1428 1371 1371 1447 1372 1372 1448 1353 1353 1428 1372 1372 1448 1354 1354 1429 1354 1354 1429 1372 1372 1448 1373 1373 1449 1354 1354 1429 1373 1373 1449 1355 1355 1430 1355 1355 1430 1373 1373 1449 1374 1374 1450 1355 1355 1430 1374 1374 1450 1356 1356 1431 1356 1356 1431 1374 1374 1450 1375 1375 1451 1356 1356 1431 1375 1375 1451 1357 1357 1432 1357 1357 1432 1375 1375 1451 1376 1376 1452 1357 1357 1432 1376 1376 1452 1358 1358 1433 1358 1358 1433 1376 1376 1452 1377 1377 1453 1358 1358 1433 1377 1377 1453 1359 1359 1434 1359 1359 1434 1377 1377 1453 1378 1378 1454 1359 1359 1434 1378 1378 1454 1360 1360 1435 1360 1360 1435 1378 1378 1454 1379 1379 1455 1360 1360 1435 1379 1379 1455 1361 1361 1436 1361 1361 1436 1379 1379 1455 1380 1380 1456 1361 1361 1436 1380 1380 1456 1362 1362 1437 1362 1362 1437 1380 1380 1456 1381 1381 1457 1362 1362 1437 1381 1381 1457 1363 1363 1438 1363 1363 1438 1381 1381 1457 1382 1382 1458 1363 1363 1438 1382 1382 1458 1364 1364 1439 1364 1364 1439 1382 1382 1458 1383 1383 1459 1364 1364 1439 1383 1383 1459 1365 1365 1440 1365 1365 1440 1383 1383 1459 1384 1384 1460 1365 1365 1440 1384 1384 1460 1366 1366 1441 1366 1366 1441 1384 1384 1460 1385 1385 1461 1366 1366 1441 1385 1385 1461 1367 1367 1442 1367 1367 1442 1385 1385 1461 1368 1368 1462 1367 1367 1442 1368 1368 1462 1350 1350 1443 1368 1368 1444 1386 1386 1463 1387 1387 1464 1368 1368 1444 1387 1387 1464 1369 1369 1445 1369 1369 1445 1387 1387 1464 1388 1388 1465 1369 1369 1445 1388 1388 1465 1370 1370 1446 1370 1370 1446 1388 1388 1465 1389 1389 1466 1370 1370 1446 1389 1389 1466 1371 1371 1447 1371 1371 1447 1389 1389 1466 1390 1390 1467 1371 1371 1447 1390 1390 1467 1372 1372 1448 1372 1372 1448 1390 1390 1467 1391 1391 1468 1372 1372 1448 1391 1391 1468 1373 1373 1449 1373 1373 1449 1391 1391 1468 1392 1392 1469 1373 1373 1449 1392 1392 1469 1374 1374 1450 1374 1374 1450 1392 1392 1469 1393 1393 1470 1374 1374 1450 1393 1393 1470 1375 1375 1451 1375 1375 1451 1393 1393 1470 1394 1394 1471 1375 1375 1451 1394 1394 1471 1376 1376 1452 1376 1376 1452 1394 1394 1471 1395 1395 1472 1376 1376 1452 1395 1395 1472 1377 1377 1453 1377 1377 1453 1395 1395 1472 1396 1396 1473 1377 1377 1453 1396 1396 1473 1378 1378 1454 1378 1378 1454 1396 1396 1473 1397 1397 1474 1378 1378 1454 1397 1397 1474 1379 1379 1455 1379 1379 1455 1397 1397 1474 1398 1398 1475 1379 1379 1455 1398 1398 1475 1380 1380 1456 1380 1380 1456 1398 1398 1475 1399 1399 1476 1380 1380 1456 1399 1399 1476 1381 1381 1457 1381 1381 1457 1399 1399 1476 1400 1400 1477 1381 1381 1457 1400 1400 1477 1382 1382 1458 1382 1382 1458 1400 1400 1477 1401 1401 1478 1382 1382 1458 1401 1401 1478 1383 1383 1459 1383 1383 1459 1401 1401 1478 1402 1402 1479 1383 1383 1459 1402 1402 1479 1384 1384 1460 1384 1384 1460 1402 1402 1479 1403 1403 1480 1384 1384 1460 1403 1403 1480 1385 1385 1461 1385 1385 1461 1403 1403 1480 1386 1386 1481 1385 1385 1461 1386 1386 1481 1368 1368 1462 1386 1386 1463 1404 1404 1482 1405 1405 1483 1386 1386 1463 1405 1405 1483 1387 1387 1464 1387 1387 1464 1405 1405 1483 1406 1406 1484 1387 1387 1464 1406 1406 1484 1388 1388 1465 1388 1388 1465 1406 1406 1484 1407 1407 1485 1388 1388 1465 1407 1407 1485 1389 1389 1466 1389 1389 1466 1407 1407 1485 1408 1408 1486 1389 1389 1466 1408 1408 1486 1390 1390 1467 1390 1390 1467 1408 1408 1486 1409 1409 1487 1390 1390 1467 1409 1409 1487 1391 1391 1468 1391 1391 1468 1409 1409 1487 1410 1410 1488 1391 1391 1468 1410 1410 1488 1392 1392 1469 1392 1392 1469 1410 1410 1488 1411 1411 1489 1392 1392 1469 1411 1411 1489 1393 1393 1470 1393 1393 1470 1411 1411 1489 1412 1412 1490 1393 1393 1470 1412 1412 1490 1394 1394 1471 1394 1394 1471 1412 1412 1490 1413 1413 1491 1394 1394 1471 1413 1413 1491 1395 1395 1472 1395 1395 1472 1413 1413 1491 1414 1414 1492 1395 1395 1472 1414 1414 1492 1396 1396 1473 1396 1396 1473 1414 1414 1492 1415 1415 1493 1396 1396 1473 1415 1415 1493 1397 1397 1474 1397 1397 1474 1415 1415 1493 1416 1416 1494 1397 1397 1474 1416 1416 1494 1398 1398 1475 1398 1398 1475 1416 1416 1494 1417 1417 1495 1398 1398 1475 1417 1417 1495 1399 1399 1476 1399 1399 1476 1417 1417 1495 1418 1418 1496 1399 1399 1476 1418 1418 1496 1400 1400 1477 1400 1400 1477 1418 1418 1496 1419 1419 1497 1400 1400 1477 1419 1419 1497 1401 1401 1478 1401 1401 1478 1419 1419 1497 1420 1420 1498 1401 1401 1478 1420 1420 1498 1402 1402 1479 1402 1402 1479 1420 1420 1498 1421 1421 1499 1402 1402 1479 1421 1421 1499 1403 1403 1480 1403 1403 1480 1421 1421 1499 1404 1404 1500 1403 1403 1480 1404 1404 1500 1386 1386 1481 1404 1404 1482 1422 1422 1501 1423 1423 1502 1404 1404 1482 1423 1423 1502 1405 1405 1483 1405 1405 1483 1423 1423 1502 1424 1424 1503 1405 1405 1483 1424 1424 1503 1406 1406 1484 1406 1406 1484 1424 1424 1503 1425 1425 1504 1406 1406 1484 1425 1425 1504 1407 1407 1485 1407 1407 1485 1425 1425 1504 1426 1426 1505 1407 1407 1485 1426 1426 1505 1408 1408 1486 1408 1408 1486 1426 1426 1505 1427 1427 1506 1408 1408 1486 1427 1427 1506 1409 1409 1487 1409 1409 1487 1427 1427 1506 1428 1428 1507 1409 1409 1487 1428 1428 1507 1410 1410 1488 1410 1410 1488 1428 1428 1507 1429 1429 1508 1410 1410 1488 1429 1429 1508 1411 1411 1489 1411 1411 1489 1429 1429 1508 1430 1430 1509 1411 1411 1489 1430 1430 1509 1412 1412 1490 1412 1412 1490 1430 1430 1509 1431 1431 1510 1412 1412 1490 1431 1431 1510 1413 1413 1491 1413 1413 1491 1431 1431 1510 1432 1432 1511 1413 1413 1491 1432 1432 1511 1414 1414 1492 1414 1414 1492 1432 1432 1511 1433 1433 1512 1414 1414 1492 1433 1433 1512 1415 1415 1493 1415 1415 1493 1433 1433 1512 1434 1434 1513 1415 1415 1493 1434 1434 1513 1416 1416 1494 1416 1416 1494 1434 1434 1513 1435 1435 1514 1416 1416 1494 1435 1435 1514 1417 1417 1495 1417 1417 1495 1435 1435 1514 1436 1436 1515 1417 1417 1495 1436 1436 1515 1418 1418 1496 1418 1418 1496 1436 1436 1515 1437 1437 1516 1418 1418 1496 1437 1437 1516 1419 1419 1497 1419 1419 1497 1437 1437 1516 1438 1438 1517 1419 1419 1497 1438 1438 1517 1420 1420 1498 1420 1420 1498 1438 1438 1517 1439 1439 1518 1420 1420 1498 1439 1439 1518 1421 1421 1499 1421 1421 1499 1439 1439 1518 1422 1422 1519 1421 1421 1499 1422 1422 1519 1404 1404 1500 1422 1422 1501 1440 1440 1520 1441 1441 1521 1422 1422 1501 1441 1441 1521 1423 1423 1502 1423 1423 1502 1441 1441 1521 1442 1442 1522 1423 1423 1502 1442 1442 1522 1424 1424 1503 1424 1424 1503 1442 1442 1522 1443 1443 1523 1424 1424 1503 1443 1443 1523 1425 1425 1504 1425 1425 1504 1443 1443 1523 1444 1444 1524 1425 1425 1504 1444 1444 1524 1426 1426 1505 1426 1426 1505 1444 1444 1524 1445 1445 1525 1426 1426 1505 1445 1445 1525 1427 1427 1506 1427 1427 1506 1445 1445 1525 1446 1446 1526 1427 1427 1506 1446 1446 1526 1428 1428 1507 1428 1428 1507 1446 1446 1526 1447 1447 1527 1428 1428 1507 1447 1447 1527 1429 1429 1508 1429 1429 1508 1447 1447 1527 1448 1448 1528 1429 1429 1508 1448 1448 1528 1430 1430 1509 1430 1430 1509 1448 1448 1528 1449 1449 1529 1430 1430 1509 1449 1449 1529 1431 1431 1510 1431 1431 1510 1449 1449 1529 1450 1450 1530 1431 1431 1510 1450 1450 1530 1432 1432 1511 1432 1432 1511 1450 1450 1530 1451 1451 1531 1432 1432 1511 1451 1451 1531 1433 1433 1512 1433 1433 1512 1451 1451 1531 1452 1452 1532 1433 1433 1512 1452 1452 1532 1434 1434 1513 1434 1434 1513 1452 1452 1532 1453 1453 1533 1434 1434 1513 1453 1453 1533 1435 1435 1514 1435 1435 1514 1453 1453 1533 1454 1454 1534 1435 1435 1514 1454 1454 1534 1436 1436 1515 1436 1436 1515 1454 1454 1534 1455 1455 1535 1436 1436 1515 1455 1455 1535 1437 1437 1516 1437 1437 1516 1455 1455 1535 1456 1456 1536 1437 1437 1516 1456 1456 1536 1438 1438 1517 1438 1438 1517 1456 1456 1536 1457 1457 1537 1438 1438 1517 1457 1457 1537 1439 1439 1518 1439 1439 1518 1457 1457 1537 1440 1440 1538 1439 1439 1518 1440 1440 1538 1422 1422 1519 1440 1440 1520 1458 1458 1539 1459 1459 1540 1440 1440 1520 1459 1459 1540 1441 1441 1521 1441 1441 1521 1459 1459 1540 1460 1460 1541 1441 1441 1521 1460 1460 1541 1442 1442 1522 1442 1442 1522 1460 1460 1541 1461 1461 1542 1442 1442 1522 1461 1461 1542 1443 1443 1523 1443 1443 1523 1461 1461 1542 1462 1462 1543 1443 1443 1523 1462 1462 1543 1444 1444 1524 1444 1444 1524 1462 1462 1543 1463 1463 1544 1444 1444 1524 1463 1463 1544 1445 1445 1525 1445 1445 1525 1463 1463 1544 1464 1464 1545 1445 1445 1525 1464 1464 1545 1446 1446 1526 1446 1446 1526 1464 1464 1545 1465 1465 1546 1446 1446 1526 1465 1465 1546 1447 1447 1527 1447 1447 1527 1465 1465 1546 1466 1466 1547 1447 1447 1527 1466 1466 1547 1448 1448 1528 1448 1448 1528 1466 1466 1547 1467 1467 1548 1448 1448 1528 1467 1467 1548 1449 1449 1529 1449 1449 1529 1467 1467 1548 1468 1468 1549 1449 1449 1529 1468 1468 1549 1450 1450 1530 1450 1450 1530 1468 1468 1549 1469 1469 1550 1450 1450 1530 1469 1469 1550 1451 1451 1531 1451 1451 1531 1469 1469 1550 1470 1470 1551 1451 1451 1531 1470 1470 1551 1452 1452 1532 1452 1452 1532 1470 1470 1551 1471 1471 1552 1452 1452 1532 1471 1471 1552 1453 1453 1533 1453 1453 1533 1471 1471 1552 1472 1472 1553 1453 1453 1533 1472 1472 1553 1454 1454 1534 1454 1454 1534 1472 1472 1553 1473 1473 1554 1454 1454 1534 1473 1473 1554 1455 1455 1535 1455 1455 1535 1473 1473 1554 1474 1474 1555 1455 1455 1535 1474 1474 1555 1456 1456 1536 1456 1456 1536 1474 1474 1555 1475 1475 1556 1456 1456 1536 1475 1475 1556 1457 1457 1537 1457 1457 1537 1475 1475 1556 1458 1458 1557 1457 1457 1537 1458 1458 1557 1440 1440 1538 1458 1458 1539 1476 1476 1558 1477 1477 1559 1458 1458 1539 1477 1477 1559 1459 1459 1540 1459 1459 1540 1477 1477 1559 1478 1478 1560 1459 1459 1540 1478 1478 1560 1460 1460 1541 1460 1460 1541 1478 1478 1560 1479 1479 1561 1460 1460 1541 1479 1479 1561 1461 1461 1542 1461 1461 1542 1479 1479 1561 1480 1480 1562 1461 1461 1542 1480 1480 1562 1462 1462 1543 1462 1462 1543 1480 1480 1562 1481 1481 1563 1462 1462 1543 1481 1481 1563 1463 1463 1544 1463 1463 1544 1481 1481 1563 1482 1482 1564 1463 1463 1544 1482 1482 1564 1464 1464 1545 1464 1464 1545 1482 1482 1564 1483 1483 1565 1464 1464 1545 1483 1483 1565 1465 1465 1546 1465 1465 1546 1483 1483 1565 1484 1484 1566 1465 1465 1546 1484 1484 1566 1466 1466 1547 1466 1466 1547 1484 1484 1566 1485 1485 1567 1466 1466 1547 1485 1485 1567 1467 1467 1548 1467 1467 1548 1485 1485 1567 1486 1486 1568 1467 1467 1548 1486 1486 1568 1468 1468 1549 1468 1468 1549 1486 1486 1568 1487 1487 1569 1468 1468 1549 1487 1487 1569 1469 1469 1550 1469 1469 1550 1487 1487 1569 1488 1488 1570 1469 1469 1550 1488 1488 1570 1470 1470 1551 1470 1470 1551 1488 1488 1570 1489 1489 1571 1470 1470 1551 1489 1489 1571 1471 1471 1552 1471 1471 1552 1489 1489 1571 1490 1490 1572 1471 1471 1552 1490 1490 1572 1472 1472 1553 1472 1472 1553 1490 1490 1572 1491 1491 1573 1472 1472 1553 1491 1491 1573 1473 1473 1554 1473 1473 1554 1491 1491 1573 1492 1492 1574 1473 1473 1554 1492 1492 1574 1474 1474 1555 1474 1474 1555 1492 1492 1574 1493 1493 1575 1474 1474 1555 1493 1493 1575 1475 1475 1556 1475 1475 1556 1493 1493 1575 1476 1476 1576 1475 1475 1556 1476 1476 1576 1458 1458 1557 1476 1476 1558 1494 1494 1577 1495 1495 1578 1476 1476 1558 1495 1495 1578 1477 1477 1559 1477 1477 1559 1495 1495 1578 1496 1496 1579 1477 1477 1559 1496 1496 1579 1478 1478 1560 1478 1478 1560 1496 1496 1579 1497 1497 1580 1478 1478 1560 1497 1497 1580 1479 1479 1561 1479 1479 1561 1497 1497 1580 1498 1498 1581 1479 1479 1561 1498 1498 1581 1480 1480 1562 1480 1480 1562 1498 1498 1581 1499 1499 1582 1480 1480 1562 1499 1499 1582 1481 1481 1563 1481 1481 1563 1499 1499 1582 1500 1500 1583 1481 1481 1563 1500 1500 1583 1482 1482 1564 1482 1482 1564 1500 1500 1583 1501 1501 1584 1482 1482 1564 1501 1501 1584 1483 1483 1565 1483 1483 1565 1501 1501 1584 1502 1502 1585 1483 1483 1565 1502 1502 1585 1484 1484 1566 1484 1484 1566 1502 1502 1585 1503 1503 1586 1484 1484 1566 1503 1503 1586 1485 1485 1567 1485 1485 1567 1503 1503 1586 1504 1504 1587 1485 1485 1567 1504 1504 1587 1486 1486 1568 1486 1486 1568 1504 1504 1587 1505 1505 1588 1486 1486 1568 1505 1505 1588 1487 1487 1569 1487 1487 1569 1505 1505 1588 1506 1506 1589 1487 1487 1569 1506 1506 1589 1488 1488 1570 1488 1488 1570 1506 1506 1589 1507 1507 1590 1488 1488 1570 1507 1507 1590 1489 1489 1571 1489 1489 1571 1507 1507 1590 1508 1508 1591 1489 1489 1571 1508 1508 1591 1490 1490 1572 1490 1490 1572 1508 1508 1591 1509 1509 1592 1490 1490 1572 1509 1509 1592 1491 1491 1573 1491 1491 1573 1509 1509 1592 1510 1510 1593 1491 1491 1573 1510 1510 1593 1492 1492 1574 1492 1492 1574 1510 1510 1593 1511 1511 1594 1492 1492 1574 1511 1511 1594 1493 1493 1575 1493 1493 1575 1511 1511 1594 1494 1494 1595 1493 1493 1575 1494 1494 1595 1476 1476 1576 1494 1494 1577 1512 1512 1596 1513 1513 1597 1494 1494 1577 1513 1513 1597 1495 1495 1578 1495 1495 1578 1513 1513 1597 1514 1514 1598 1495 1495 1578 1514 1514 1598 1496 1496 1579 1496 1496 1579 1514 1514 1598 1515 1515 1599 1496 1496 1579 1515 1515 1599 1497 1497 1580 1497 1497 1580 1515 1515 1599 1516 1516 1600 1497 1497 1580 1516 1516 1600 1498 1498 1581 1498 1498 1581 1516 1516 1600 1517 1517 1601 1498 1498 1581 1517 1517 1601 1499 1499 1582 1499 1499 1582 1517 1517 1601 1518 1518 1602 1499 1499 1582 1518 1518 1602 1500 1500 1583 1500 1500 1583 1518 1518 1602 1519 1519 1603 1500 1500 1583 1519 1519 1603 1501 1501 1584 1501 1501 1584 1519 1519 1603 1520 1520 1604 1501 1501 1584 1520 1520 1604 1502 1502 1585 1502 1502 1585 1520 1520 1604 1521 1521 1605 1502 1502 1585 1521 1521 1605 1503 1503 1586 1503 1503 1586 1521 1521 1605 1522 1522 1606 1503 1503 1586 1522 1522 1606 1504 1504 1587 1504 1504 1587 1522 1522 1606 1523 1523 1607 1504 1504 1587 1523 1523 1607 1505 1505 1588 1505 1505 1588 1523 1523 1607 1524 1524 1608 1505 1505 1588 1524 1524 1608 1506 1506 1589 1506 1506 1589 1524 1524 1608 1525 1525 1609 1506 1506 1589 1525 1525 1609 1507 1507 1590 1507 1507 1590 1525 1525 1609 1526 1526 1610 1507 1507 1590 1526 1526 1610 1508 1508 1591 1508 1508 1591 1526 1526 1610 1527 1527 1611 1508 1508 1591 1527 1527 1611 1509 1509 1592 1509 1509 1592 1527 1527 1611 1528 1528 1612 1509 1509 1592 1528 1528 1612 1510 1510 1593 1510 1510 1593 1528 1528 1612 1529 1529 1613 1510 1510 1593 1529 1529 1613 1511 1511 1594 1511 1511 1594 1529 1529 1613 1512 1512 1614 1511 1511 1594 1512 1512 1614 1494 1494 1595 1512 1512 1596 1530 1530 1615 1531 1531 1616 1512 1512 1596 1531 1531 1616 1513 1513 1597 1513 1513 1597 1531 1531 1616 1532 1532 1617 1513 1513 1597 1532 1532 1617 1514 1514 1598 1514 1514 1598 1532 1532 1617 1533 1533 1618 1514 1514 1598 1533 1533 1618 1515 1515 1599 1515 1515 1599 1533 1533 1618 1534 1534 1619 1515 1515 1599 1534 1534 1619 1516 1516 1600 1516 1516 1600 1534 1534 1619 1535 1535 1620 1516 1516 1600 1535 1535 1620 1517 1517 1601 1517 1517 1601 1535 1535 1620 1536 1536 1621 1517 1517 1601 1536 1536 1621 1518 1518 1602 1518 1518 1602 1536 1536 1621 1537 1537 1622 1518 1518 1602 1537 1537 1622 1519 1519 1603 1519 1519 1603 1537 1537 1622 1538 1538 1623 1519 1519 1603 1538 1538 1623 1520 1520 1604 1520 1520 1604 1538 1538 1623 1539 1539 1624 1520 1520 1604 1539 1539 1624 1521 1521 1605 1521 1521 1605 1539 1539 1624 1540 1540 1625 1521 1521 1605 1540 1540 1625 1522 1522 1606 1522 1522 1606 1540 1540 1625 1541 1541 1626 1522 1522 1606 1541 1541 1626 1523 1523 1607 1523 1523 1607 1541 1541 1626 1542 1542 1627 1523 1523 1607 1542 1542 1627 1524 1524 1608 1524 1524 1608 1542 1542 1627 1543 1543 1628 1524 1524 1608 1543 1543 1628 1525 1525 1609 1525 1525 1609 1543 1543 1628 1544 1544 1629 1525 1525 1609 1544 1544 1629 1526 1526 1610 1526 1526 1610 1544 1544 1629 1545 1545 1630 1526 1526 1610 1545 1545 1630 1527 1527 1611 1527 1527 1611 1545 1545 1630 1546 1546 1631 1527 1527 1611 1546 1546 1631 1528 1528 1612 1528 1528 1612 1546 1546 1631 1547 1547 1632 1528 1528 1612 1547 1547 1632 1529 1529 1613 1529 1529 1613 1547 1547 1632 1530 1530 1633 1529 1529 1613 1530 1530 1633 1512 1512 1614 1530 1530 1615 1548 1548 1634 1549 1549 1635 1530 1530 1615 1549 1549 1635 1531 1531 1616 1531 1531 1616 1549 1549 1635 1550 1550 1636 1531 1531 1616 1550 1550 1636 1532 1532 1617 1532 1532 1617 1550 1550 1636 1551 1551 1637 1532 1532 1617 1551 1551 1637 1533 1533 1618 1533 1533 1618 1551 1551 1637 1552 1552 1638 1533 1533 1618 1552 1552 1638 1534 1534 1619 1534 1534 1619 1552 1552 1638 1553 1553 1639 1534 1534 1619 1553 1553 1639 1535 1535 1620 1535 1535 1620 1553 1553 1639 1554 1554 1640 1535 1535 1620 1554 1554 1640 1536 1536 1621 1536 1536 1621 1554 1554 1640 1555 1555 1641 1536 1536 1621 1555 1555 1641 1537 1537 1622 1537 1537 1622 1555 1555 1641 1556 1556 1642 1537 1537 1622 1556 1556 1642 1538 1538 1623 1538 1538 1623 1556 1556 1642 1557 1557 1643 1538 1538 1623 1557 1557 1643 1539 1539 1624 1539 1539 1624 1557 1557 1643 1558 1558 1644 1539 1539 1624 1558 1558 1644 1540 1540 1625 1540 1540 1625 1558 1558 1644 1559 1559 1645 1540 1540 1625 1559 1559 1645 1541 1541 1626 1541 1541 1626 1559 1559 1645 1560 1560 1646 1541 1541 1626 1560 1560 1646 1542 1542 1627 1542 1542 1627 1560 1560 1646 1561 1561 1647 1542 1542 1627 1561 1561 1647 1543 1543 1628 1543 1543 1628 1561 1561 1647 1562 1562 1648 1543 1543 1628 1562 1562 1648 1544 1544 1629 1544 1544 1629 1562 1562 1648 1563 1563 1649 1544 1544 1629 1563 1563 1649 1545 1545 1630 1545 1545 1630 1563 1563 1649 1564 1564 1650 1545 1545 1630 1564 1564 1650 1546 1546 1631 1546 1546 1631 1564 1564 1650 1565 1565 1651 1546 1546 1631 1565 1565 1651 1547 1547 1632 1547 1547 1632 1565 1565 1651 1548 1548 1652 1547 1547 1632 1548 1548 1652 1530 1530 1633 1548 1548 1634 1566 1566 1653 1567 1567 1654 1548 1548 1634 1567 1567 1654 1549 1549 1635 1549 1549 1635 1567 1567 1654 1568 1568 1655 1549 1549 1635 1568 1568 1655 1550 1550 1636 1550 1550 1636 1568 1568 1655 1569 1569 1656 1550 1550 1636 1569 1569 1656 1551 1551 1637 1551 1551 1637 1569 1569 1656 1570 1570 1657 1551 1551 1637 1570 1570 1657 1552 1552 1638 1552 1552 1638 1570 1570 1657 1571 1571 1658 1552 1552 1638 1571 1571 1658 1553 1553 1639 1553 1553 1639 1571 1571 1658 1572 1572 1659 1553 1553 1639 1572 1572 1659 1554 1554 1640 1554 1554 1640 1572 1572 1659 1573 1573 1660 1554 1554 1640 1573 1573 1660 1555 1555 1641 1555 1555 1641 1573 1573 1660 1574 1574 1661 1555 1555 1641 1574 1574 1661 1556 1556 1642 1556 1556 1642 1574 1574 1661 1575 1575 1662 1556 1556 1642 1575 1575 1662 1557 1557 1643 1557 1557 1643 1575 1575 1662 1576 1576 1663 1557 1557 1643 1576 1576 1663 1558 1558 1644 1558 1558 1644 1576 1576 1663 1577 1577 1664 1558 1558 1644 1577 1577 1664 1559 1559 1645 1559 1559 1645 1577 1577 1664 1578 1578 1665 1559 1559 1645 1578 1578 1665 1560 1560 1646 1560 1560 1646 1578 1578 1665 1579 1579 1666 1560 1560 1646 1579 1579 1666 1561 1561 1647 1561 1561 1647 1579 1579 1666 1580 1580 1667 1561 1561 1647 1580 1580 1667 1562 1562 1648 1562 1562 1648 1580 1580 1667 1581 1581 1668 1562 1562 1648 1581 1581 1668 1563 1563 1649 1563 1563 1649 1581 1581 1668 1582 1582 1669 1563 1563 1649 1582 1582 1669 1564 1564 1650 1564 1564 1650 1582 1582 1669 1583 1583 1670 1564 1564 1650 1583 1583 1670 1565 1565 1651 1565 1565 1651 1583 1583 1670 1566 1566 1671 1565 1565 1651 1566 1566 1671 1548 1548 1652 1566 1566 1653 1584 1584 1672 1585 1585 1673 1566 1566 1653 1585 1585 1673 1567 1567 1654 1567 1567 1654 1585 1585 1673 1586 1586 1674 1567 1567 1654 1586 1586 1674 1568 1568 1655 1568 1568 1655 1586 1586 1674 1587 1587 1675 1568 1568 1655 1587 1587 1675 1569 1569 1656 1569 1569 1656 1587 1587 1675 1588 1588 1676 1569 1569 1656 1588 1588 1676 1570 1570 1657 1570 1570 1657 1588 1588 1676 1589 1589 1677 1570 1570 1657 1589 1589 1677 1571 1571 1658 1571 1571 1658 1589 1589 1677 1590 1590 1678 1571 1571 1658 1590 1590 1678 1572 1572 1659 1572 1572 1659 1590 1590 1678 1591 1591 1679 1572 1572 1659 1591 1591 1679 1573 1573 1660 1573 1573 1660 1591 1591 1679 1592 1592 1680 1573 1573 1660 1592 1592 1680 1574 1574 1661 1574 1574 1661 1592 1592 1680 1593 1593 1681 1574 1574 1661 1593 1593 1681 1575 1575 1662 1575 1575 1662 1593 1593 1681 1594 1594 1682 1575 1575 1662 1594 1594 1682 1576 1576 1663 1576 1576 1663 1594 1594 1682 1595 1595 1683 1576 1576 1663 1595 1595 1683 1577 1577 1664 1577 1577 1664 1595 1595 1683 1596 1596 1684 1577 1577 1664 1596 1596 1684 1578 1578 1665 1578 1578 1665 1596 1596 1684 1597 1597 1685 1578 1578 1665 1597 1597 1685 1579 1579 1666 1579 1579 1666 1597 1597 1685 1598 1598 1686 1579 1579 1666 1598 1598 1686 1580 1580 1667 1580 1580 1667 1598 1598 1686 1599 1599 1687 1580 1580 1667 1599 1599 1687 1581 1581 1668 1581 1581 1668 1599 1599 1687 1600 1600 1688 1581 1581 1668 1600 1600 1688 1582 1582 1669 1582 1582 1669 1600 1600 1688 1601 1601 1689 1582 1582 1669 1601 1601 1689 1583 1583 1670 1583 1583 1670 1601 1601 1689 1584 1584 1690 1583 1583 1670 1584 1584 1690 1566 1566 1671 1584 1584 1672 1602 1602 1691 1603 1603 1692 1584 1584 1672 1603 1603 1692 1585 1585 1673 1585 1585 1673 1603 1603 1692 1604 1604 1693 1585 1585 1673 1604 1604 1693 1586 1586 1674 1586 1586 1674 1604 1604 1693 1605 1605 1694 1586 1586 1674 1605 1605 1694 1587 1587 1675 1587 1587 1675 1605 1605 1694 1606 1606 1695 1587 1587 1675 1606 1606 1695 1588 1588 1676 1588 1588 1676 1606 1606 1695 1607 1607 1696 1588 1588 1676 1607 1607 1696 1589 1589 1677 1589 1589 1677 1607 1607 1696 1608 1608 1697 1589 1589 1677 1608 1608 1697 1590 1590 1678 1590 1590 1678 1608 1608 1697 1609 1609 1698 1590 1590 1678 1609 1609 1698 1591 1591 1679 1591 1591 1679 1609 1609 1698 1610 1610 1699 1591 1591 1679 1610 1610 1699 1592 1592 1680 1592 1592 1680 1610 1610 1699 1611 1611 1700 1592 1592 1680 1611 1611 1700 1593 1593 1681 1593 1593 1681 1611 1611 1700 1612 1612 1701 1593 1593 1681 1612 1612 1701 1594 1594 1682 1594 1594 1682 1612 1612 1701 1613 1613 1702 1594 1594 1682 1613 1613 1702 1595 1595 1683 1595 1595 1683 1613 1613 1702 1614 1614 1703 1595 1595 1683 1614 1614 1703 1596 1596 1684 1596 1596 1684 1614 1614 1703 1615 1615 1704 1596 1596 1684 1615 1615 1704 1597 1597 1685 1597 1597 1685 1615 1615 1704 1616 1616 1705 1597 1597 1685 1616 1616 1705 1598 1598 1686 1598 1598 1686 1616 1616 1705 1617 1617 1706 1598 1598 1686 1617 1617 1706 1599 1599 1687 1599 1599 1687 1617 1617 1706 1618 1618 1707 1599 1599 1687 1618 1618 1707 1600 1600 1688 1600 1600 1688 1618 1618 1707 1619 1619 1708 1600 1600 1688 1619 1619 1708 1601 1601 1689 1601 1601 1689 1619 1619 1708 1602 1602 1709 1601 1601 1689 1602 1602 1709 1584 1584 1690 1602 1602 1691 1620 1620 1710 1621 1621 1711 1602 1602 1691 1621 1621 1711 1603 1603 1692 1603 1603 1692 1621 1621 1711 1622 1622 1712 1603 1603 1692 1622 1622 1712 1604 1604 1693 1604 1604 1693 1622 1622 1712 1623 1623 1713 1604 1604 1693 1623 1623 1713 1605 1605 1694 1605 1605 1694 1623 1623 1713 1624 1624 1714 1605 1605 1694 1624 1624 1714 1606 1606 1695 1606 1606 1695 1624 1624 1714 1625 1625 1715 1606 1606 1695 1625 1625 1715 1607 1607 1696 1607 1607 1696 1625 1625 1715 1626 1626 1716 1607 1607 1696 1626 1626 1716 1608 1608 1697 1608 1608 1697 1626 1626 1716 1627 1627 1717 1608 1608 1697 1627 1627 1717 1609 1609 1698 1609 1609 1698 1627 1627 1717 1628 1628 1718 1609 1609 1698 1628 1628 1718 1610 1610 1699 1610 1610 1699 1628 1628 1718 1629 1629 1719 1610 1610 1699 1629 1629 1719 1611 1611 1700 1611 1611 1700 1629 1629 1719 1630 1630 1720 1611 1611 1700 1630 1630 1720 1612 1612 1701 1612 1612 1701 1630 1630 1720 1631 1631 1721 1612 1612 1701 1631 1631 1721 1613 1613 1702 1613 1613 1702 1631 1631 1721 1632 1632 1722 1613 1613 1702 1632 1632 1722 1614 1614 1703 1614 1614 1703 1632 1632 1722 1633 1633 1723 1614 1614 1703 1633 1633 1723 1615 1615 1704 1615 1615 1704 1633 1633 1723 1634 1634 1724 1615 1615 1704 1634 1634 1724 1616 1616 1705 1616 1616 1705 1634 1634 1724 1635 1635 1725 1616 1616 1705 1635 1635 1725 1617 1617 1706 1617 1617 1706 1635 1635 1725 1636 1636 1726 1617 1617 1706 1636 1636 1726 1618 1618 1707 1618 1618 1707 1636 1636 1726 1637 1637 1727 1618 1618 1707 1637 1637 1727 1619 1619 1708 1619 1619 1708 1637 1637 1727 1620 1620 1728 1619 1619 1708 1620 1620 1728 1602 1602 1709 1620 1620 1710 1638 1638 1729 1639 1639 1730 1620 1620 1710 1639 1639 1730 1621 1621 1711 1621 1621 1711 1639 1639 1730 1640 1640 1731 1621 1621 1711 1640 1640 1731 1622 1622 1712 1622 1622 1712 1640 1640 1731 1641 1641 1732 1622 1622 1712 1641 1641 1732 1623 1623 1713 1623 1623 1713 1641 1641 1732 1642 1642 1733 1623 1623 1713 1642 1642 1733 1624 1624 1714 1624 1624 1714 1642 1642 1733 1643 1643 1734 1624 1624 1714 1643 1643 1734 1625 1625 1715 1625 1625 1715 1643 1643 1734 1644 1644 1735 1625 1625 1715 1644 1644 1735 1626 1626 1716 1626 1626 1716 1644 1644 1735 1645 1645 1736 1626 1626 1716 1645 1645 1736 1627 1627 1717 1627 1627 1717 1645 1645 1736 1646 1646 1737 1627 1627 1717 1646 1646 1737 1628 1628 1718 1628 1628 1718 1646 1646 1737 1647 1647 1738 1628 1628 1718 1647 1647 1738 1629 1629 1719 1629 1629 1719 1647 1647 1738 1648 1648 1739 1629 1629 1719 1648 1648 1739 1630 1630 1720 1630 1630 1720 1648 1648 1739 1649 1649 1740 1630 1630 1720 1649 1649 1740 1631 1631 1721 1631 1631 1721 1649 1649 1740 1650 1650 1741 1631 1631 1721 1650 1650 1741 1632 1632 1722 1632 1632 1722 1650 1650 1741 1651 1651 1742 1632 1632 1722 1651 1651 1742 1633 1633 1723 1633 1633 1723 1651 1651 1742 1652 1652 1743 1633 1633 1723 1652 1652 1743 1634 1634 1724 1634 1634 1724 1652 1652 1743 1653 1653 1744 1634 1634 1724 1653 1653 1744 1635 1635 1725 1635 1635 1725 1653 1653 1744 1654 1654 1745 1635 1635 1725 1654 1654 1745 1636 1636 1726 1636 1636 1726 1654 1654 1745 1655 1655 1746 1636 1636 1726 1655 1655 1746 1637 1637 1727 1637 1637 1727 1655 1655 1746 1638 1638 1747 1637 1637 1727 1638 1638 1747 1620 1620 1728 1638 1638 1729 1656 1656 1748 1657 1657 1749 1638 1638 1729 1657 1657 1749 1639 1639 1730 1639 1639 1730 1657 1657 1749 1658 1658 1750 1639 1639 1730 1658 1658 1750 1640 1640 1731 1640 1640 1731 1658 1658 1750 1659 1659 1751 1640 1640 1731 1659 1659 1751 1641 1641 1732 1641 1641 1732 1659 1659 1751 1660 1660 1752 1641 1641 1732 1660 1660 1752 1642 1642 1733 1642 1642 1733 1660 1660 1752 1661 1661 1753 1642 1642 1733 1661 1661 1753 1643 1643 1734 1643 1643 1734 1661 1661 1753 1662 1662 1754 1643 1643 1734 1662 1662 1754 1644 1644 1735 1644 1644 1735 1662 1662 1754 1663 1663 1755 1644 1644 1735 1663 1663 1755 1645 1645 1736 1645 1645 1736 1663 1663 1755 1664 1664 1756 1645 1645 1736 1664 1664 1756 1646 1646 1737 1646 1646 1737 1664 1664 1756 1665 1665 1757 1646 1646 1737 1665 1665 1757 1647 1647 1738 1647 1647 1738 1665 1665 1757 1666 1666 1758 1647 1647 1738 1666 1666 1758 1648 1648 1739 1648 1648 1739 1666 1666 1758 1667 1667 1759 1648 1648 1739 1667 1667 1759 1649 1649 1740 1649 1649 1740 1667 1667 1759 1668 1668 1760 1649 1649 1740 1668 1668 1760 1650 1650 1741 1650 1650 1741 1668 1668 1760 1669 1669 1761 1650 1650 1741 1669 1669 1761 1651 1651 1742 1651 1651 1742 1669 1669 1761 1670 1670 1762 1651 1651 1742 1670 1670 1762 1652 1652 1743 1652 1652 1743 1670 1670 1762 1671 1671 1763 1652 1652 1743 1671 1671 1763 1653 1653 1744 1653 1653 1744 1671 1671 1763 1672 1672 1764 1653 1653 1744 1672 1672 1764 1654 1654 1745 1654 1654 1745 1672 1672 1764 1673 1673 1765 1654 1654 1745 1673 1673 1765 1655 1655 1746 1655 1655 1746 1673 1673 1765 1656 1656 1766 1655 1655 1746 1656 1656 1766 1638 1638 1747 1656 1656 1748 1674 1674 1767 1675 1675 1768 1656 1656 1748 1675 1675 1768 1657 1657 1749 1657 1657 1749 1675 1675 1768 1676 1676 1769 1657 1657 1749 1676 1676 1769 1658 1658 1750 1658 1658 1750 1676 1676 1769 1677 1677 1770 1658 1658 1750 1677 1677 1770 1659 1659 1751 1659 1659 1751 1677 1677 1770 1678 1678 1771 1659 1659 1751 1678 1678 1771 1660 1660 1752 1660 1660 1752 1678 1678 1771 1679 1679 1772 1660 1660 1752 1679 1679 1772 1661 1661 1753 1661 1661 1753 1679 1679 1772 1680 1680 1773 1661 1661 1753 1680 1680 1773 1662 1662 1754 1662 1662 1754 1680 1680 1773 1681 1681 1774 1662 1662 1754 1681 1681 1774 1663 1663 1755 1663 1663 1755 1681 1681 1774 1682 1682 1775 1663 1663 1755 1682 1682 1775 1664 1664 1756 1664 1664 1756 1682 1682 1775 1683 1683 1776 1664 1664 1756 1683 1683 1776 1665 1665 1757 1665 1665 1757 1683 1683 1776 1684 1684 1777 1665 1665 1757 1684 1684 1777 1666 1666 1758 1666 1666 1758 1684 1684 1777 1685 1685 1778 1666 1666 1758 1685 1685 1778 1667 1667 1759 1667 1667 1759 1685 1685 1778 1686 1686 1779 1667 1667 1759 1686 1686 1779 1668 1668 1760 1668 1668 1760 1686 1686 1779 1687 1687 1780 1668 1668 1760 1687 1687 1780 1669 1669 1761 1669 1669 1761 1687 1687 1780 1688 1688 1781 1669 1669 1761 1688 1688 1781 1670 1670 1762 1670 1670 1762 1688 1688 1781 1689 1689 1782 1670 1670 1762 1689 1689 1782 1671 1671 1763 1671 1671 1763 1689 1689 1782 1690 1690 1783 1671 1671 1763 1690 1690 1783 1672 1672 1764 1672 1672 1764 1690 1690 1783 1691 1691 1784 1672 1672 1764 1691 1691 1784 1673 1673 1765 1673 1673 1765 1691 1691 1784 1674 1674 1785 1673 1673 1765 1674 1674 1785 1656 1656 1766 1674 1674 1767 1692 1692 1786 1693 1693 1787 1674 1674 1767 1693 1693 1787 1675 1675 1768 1675 1675 1768 1693 1693 1787 1694 1694 1788 1675 1675 1768 1694 1694 1788 1676 1676 1769 1676 1676 1769 1694 1694 1788 1695 1695 1789 1676 1676 1769 1695 1695 1789 1677 1677 1770 1677 1677 1770 1695 1695 1789 1696 1696 1790 1677 1677 1770 1696 1696 1790 1678 1678 1771 1678 1678 1771 1696 1696 1790 1697 1697 1791 1678 1678 1771 1697 1697 1791 1679 1679 1772 1679 1679 1772 1697 1697 1791 1698 1698 1792 1679 1679 1772 1698 1698 1792 1680 1680 1773 1680 1680 1773 1698 1698 1792 1699 1699 1793 1680 1680 1773 1699 1699 1793 1681 1681 1774 1681 1681 1774 1699 1699 1793 1700 1700 1794 1681 1681 1774 1700 1700 1794 1682 1682 1775 1682 1682 1775 1700 1700 1794 1701 1701 1795 1682 1682 1775 1701 1701 1795 1683 1683 1776 1683 1683 1776 1701 1701 1795 1702 1702 1796 1683 1683 1776 1702 1702 1796 1684 1684 1777 1684 1684 1777 1702 1702 1796 1703 1703 1797 1684 1684 1777 1703 1703 1797 1685 1685 1778 1685 1685 1778 1703 1703 1797 1704 1704 1798 1685 1685 1778 1704 1704 1798 1686 1686 1779 1686 1686 1779 1704 1704 1798 1705 1705 1799 1686 1686 1779 1705 1705 1799 1687 1687 1780 1687 1687 1780 1705 1705 1799 1706 1706 1800 1687 1687 1780 1706 1706 1800 1688 1688 1781 1688 1688 1781 1706 1706 1800 1707 1707 1801 1688 1688 1781 1707 1707 1801 1689 1689 1782 1689 1689 1782 1707 1707 1801 1708 1708 1802 1689 1689 1782 1708 1708 1802 1690 1690 1783 1690 1690 1783 1708 1708 1802 1709 1709 1803 1690 1690 1783 1709 1709 1803 1691 1691 1784 1691 1691 1784 1709 1709 1803 1692 1692 1804 1691 1691 1784 1692 1692 1804 1674 1674 1785 1692 1692 1786 1710 1710 1805 1711 1711 1806 1692 1692 1786 1711 1711 1806 1693 1693 1787 1693 1693 1787 1711 1711 1806 1712 1712 1807 1693 1693 1787 1712 1712 1807 1694 1694 1788 1694 1694 1788 1712 1712 1807 1713 1713 1808 1694 1694 1788 1713 1713 1808 1695 1695 1789 1695 1695 1789 1713 1713 1808 1714 1714 1809 1695 1695 1789 1714 1714 1809 1696 1696 1790 1696 1696 1790 1714 1714 1809 1715 1715 1810 1696 1696 1790 1715 1715 1810 1697 1697 1791 1697 1697 1791 1715 1715 1810 1716 1716 1811 1697 1697 1791 1716 1716 1811 1698 1698 1792 1698 1698 1792 1716 1716 1811 1717 1717 1812 1698 1698 1792 1717 1717 1812 1699 1699 1793 1699 1699 1793 1717 1717 1812 1718 1718 1813 1699 1699 1793 1718 1718 1813 1700 1700 1794 1700 1700 1794 1718 1718 1813 1719 1719 1814 1700 1700 1794 1719 1719 1814 1701 1701 1795 1701 1701 1795 1719 1719 1814 1720 1720 1815 1701 1701 1795 1720 1720 1815 1702 1702 1796 1702 1702 1796 1720 1720 1815 1721 1721 1816 1702 1702 1796 1721 1721 1816 1703 1703 1797 1703 1703 1797 1721 1721 1816 1722 1722 1817 1703 1703 1797 1722 1722 1817 1704 1704 1798 1704 1704 1798 1722 1722 1817 1723 1723 1818 1704 1704 1798 1723 1723 1818 1705 1705 1799 1705 1705 1799 1723 1723 1818 1724 1724 1819 1705 1705 1799 1724 1724 1819 1706 1706 1800 1706 1706 1800 1724 1724 1819 1725 1725 1820 1706 1706 1800 1725 1725 1820 1707 1707 1801 1707 1707 1801 1725 1725 1820 1726 1726 1821 1707 1707 1801 1726 1726 1821 1708 1708 1802 1708 1708 1802 1726 1726 1821 1727 1727 1822 1708 1708 1802 1727 1727 1822 1709 1709 1803 1709 1709 1803 1727 1727 1822 1710 1710 1823 1709 1709 1803 1710 1710 1823 1692 1692 1804 1710 1710 1805 1728 1728 1824 1729 1729 1825 1710 1710 1805 1729 1729 1825 1711 1711 1806 1711 1711 1806 1729 1729 1825 1730 1730 1826 1711 1711 1806 1730 1730 1826 1712 1712 1807 1712 1712 1807 1730 1730 1826 1731 1731 1827 1712 1712 1807 1731 1731 1827 1713 1713 1808 1713 1713 1808 1731 1731 1827 1732 1732 1828 1713 1713 1808 1732 1732 1828 1714 1714 1809 1714 1714 1809 1732 1732 1828 1733 1733 1829 1714 1714 1809 1733 1733 1829 1715 1715 1810 1715 1715 1810 1733 1733 1829 1734 1734 1830 1715 1715 1810 1734 1734 1830 1716 1716 1811 1716 1716 1811 1734 1734 1830 1735 1735 1831 1716 1716 1811 1735 1735 1831 1717 1717 1812 1717 1717 1812 1735 1735 1831 1736 1736 1832 1717 1717 1812 1736 1736 1832 1718 1718 1813 1718 1718 1813 1736 1736 1832 1737 1737 1833 1718 1718 1813 1737 1737 1833 1719 1719 1814 1719 1719 1814 1737 1737 1833 1738 1738 1834 1719 1719 1814 1738 1738 1834 1720 1720 1815 1720 1720 1815 1738 1738 1834 1739 1739 1835 1720 1720 1815 1739 1739 1835 1721 1721 1816 1721 1721 1816 1739 1739 1835 1740 1740 1836 1721 1721 1816 1740 1740 1836 1722 1722 1817 1722 1722 1817 1740 1740 1836 1741 1741 1837 1722 1722 1817 1741 1741 1837 1723 1723 1818 1723 1723 1818 1741 1741 1837 1742 1742 1838 1723 1723 1818 1742 1742 1838 1724 1724 1819 1724 1724 1819 1742 1742 1838 1743 1743 1839 1724 1724 1819 1743 1743 1839 1725 1725 1820 1725 1725 1820 1743 1743 1839 1744 1744 1840 1725 1725 1820 1744 1744 1840 1726 1726 1821 1726 1726 1821 1744 1744 1840 1745 1745 1841 1726 1726 1821 1745 1745 1841 1727 1727 1822 1727 1727 1822 1745 1745 1841 1728 1728 1842 1727 1727 1822 1728 1728 1842 1710 1710 1823 1728 1728 1824 1746 1746 1843 1747 1747 1844 1728 1728 1824 1747 1747 1844 1729 1729 1825 1729 1729 1825 1747 1747 1844 1748 1748 1845 1729 1729 1825 1748 1748 1845 1730 1730 1826 1730 1730 1826 1748 1748 1845 1749 1749 1846 1730 1730 1826 1749 1749 1846 1731 1731 1827 1731 1731 1827 1749 1749 1846 1750 1750 1847 1731 1731 1827 1750 1750 1847 1732 1732 1828 1732 1732 1828 1750 1750 1847 1751 1751 1848 1732 1732 1828 1751 1751 1848 1733 1733 1829 1733 1733 1829 1751 1751 1848 1752 1752 1849 1733 1733 1829 1752 1752 1849 1734 1734 1830 1734 1734 1830 1752 1752 1849 1753 1753 1850 1734 1734 1830 1753 1753 1850 1735 1735 1831 1735 1735 1831 1753 1753 1850 1754 1754 1851 1735 1735 1831 1754 1754 1851 1736 1736 1832 1736 1736 1832 1754 1754 1851 1755 1755 1852 1736 1736 1832 1755 1755 1852 1737 1737 1833 1737 1737 1833 1755 1755 1852 1756 1756 1853 1737 1737 1833 1756 1756 1853 1738 1738 1834 1738 1738 1834 1756 1756 1853 1757 1757 1854 1738 1738 1834 1757 1757 1854 1739 1739 1835 1739 1739 1835 1757 1757 1854 1758 1758 1855 1739 1739 1835 1758 1758 1855 1740 1740 1836 1740 1740 1836 1758 1758 1855 1759 1759 1856 1740 1740 1836 1759 1759 1856 1741 1741 1837 1741 1741 1837 1759 1759 1856 1760 1760 1857 1741 1741 1837 1760 1760 1857 1742 1742 1838 1742 1742 1838 1760 1760 1857 1761 1761 1858 1742 1742 1838 1761 1761 1858 1743 1743 1839 1743 1743 1839 1761 1761 1858 1762 1762 1859 1743 1743 1839 1762 1762 1859 1744 1744 1840 1744 1744 1840 1762 1762 1859 1763 1763 1860 1744 1744 1840 1763 1763 1860 1745 1745 1841 1745 1745 1841 1763 1763 1860 1746 1746 1861 1745 1745 1841 1746 1746 1861 1728 1728 1842 1746 1746 1843 1764 1764 1862 1765 1765 1863 1746 1746 1843 1765 1765 1863 1747 1747 1844 1747 1747 1844 1765 1765 1863 1766 1766 1864 1747 1747 1844 1766 1766 1864 1748 1748 1845 1748 1748 1845 1766 1766 1864 1767 1767 1865 1748 1748 1845 1767 1767 1865 1749 1749 1846 1749 1749 1846 1767 1767 1865 1768 1768 1866 1749 1749 1846 1768 1768 1866 1750 1750 1847 1750 1750 1847 1768 1768 1866 1769 1769 1867 1750 1750 1847 1769 1769 1867 1751 1751 1848 1751 1751 1848 1769 1769 1867 1770 1770 1868 1751 1751 1848 1770 1770 1868 1752 1752 1849 1752 1752 1849 1770 1770 1868 1771 1771 1869 1752 1752 1849 1771 1771 1869 1753 1753 1850 1753 1753 1850 1771 1771 1869 1772 1772 1870 1753 1753 1850 1772 1772 1870 1754 1754 1851 1754 1754 1851 1772 1772 1870 1773 1773 1871 1754 1754 1851 1773 1773 1871 1755 1755 1852 1755 1755 1852 1773 1773 1871 1774 1774 1872 1755 1755 1852 1774 1774 1872 1756 1756 1853 1756 1756 1853 1774 1774 1872 1775 1775 1873 1756 1756 1853 1775 1775 1873 1757 1757 1854 1757 1757 1854 1775 1775 1873 1776 1776 1874 1757 1757 1854 1776 1776 1874 1758 1758 1855 1758 1758 1855 1776 1776 1874 1777 1777 1875 1758 1758 1855 1777 1777 1875 1759 1759 1856 1759 1759 1856 1777 1777 1875 1778 1778 1876 1759 1759 1856 1778 1778 1876 1760 1760 1857 1760 1760 1857 1778 1778 1876 1779 1779 1877 1760 1760 1857 1779 1779 1877 1761 1761 1858 1761 1761 1858 1779 1779 1877 1780 1780 1878 1761 1761 1858 1780 1780 1878 1762 1762 1859 1762 1762 1859 1780 1780 1878 1781 1781 1879 1762 1762 1859 1781 1781 1879 1763 1763 1860 1763 1763 1860 1781 1781 1879 1764 1764 1880 1763 1763 1860 1764 1764 1880 1746 1746 1861 1764 1764 1862 1782 1782 1881 1783 1783 1882 1764 1764 1862 1783 1783 1882 1765 1765 1863 1765 1765 1863 1783 1783 1882 1784 1784 1883 1765 1765 1863 1784 1784 1883 1766 1766 1864 1766 1766 1864 1784 1784 1883 1785 1785 1884 1766 1766 1864 1785 1785 1884 1767 1767 1865 1767 1767 1865 1785 1785 1884 1786 1786 1885 1767 1767 1865 1786 1786 1885 1768 1768 1866 1768 1768 1866 1786 1786 1885 1787 1787 1886 1768 1768 1866 1787 1787 1886 1769 1769 1867 1769 1769 1867 1787 1787 1886 1788 1788 1887 1769 1769 1867 1788 1788 1887 1770 1770 1868 1770 1770 1868 1788 1788 1887 1789 1789 1888 1770 1770 1868 1789 1789 1888 1771 1771 1869 1771 1771 1869 1789 1789 1888 1790 1790 1889 1771 1771 1869 1790 1790 1889 1772 1772 1870 1772 1772 1870 1790 1790 1889 1791 1791 1890 1772 1772 1870 1791 1791 1890 1773 1773 1871 1773 1773 1871 1791 1791 1890 1792 1792 1891 1773 1773 1871 1792 1792 1891 1774 1774 1872 1774 1774 1872 1792 1792 1891 1793 1793 1892 1774 1774 1872 1793 1793 1892 1775 1775 1873 1775 1775 1873 1793 1793 1892 1794 1794 1893 1775 1775 1873 1794 1794 1893 1776 1776 1874 1776 1776 1874 1794 1794 1893 1795 1795 1894 1776 1776 1874 1795 1795 1894 1777 1777 1875 1777 1777 1875 1795 1795 1894 1796 1796 1895 1777 1777 1875 1796 1796 1895 1778 1778 1876 1778 1778 1876 1796 1796 1895 1797 1797 1896 1778 1778 1876 1797 1797 1896 1779 1779 1877 1779 1779 1877 1797 1797 1896 1798 1798 1897 1779 1779 1877 1798 1798 1897 1780 1780 1878 1780 1780 1878 1798 1798 1897 1799 1799 1898 1780 1780 1878 1799 1799 1898 1781 1781 1879 1781 1781 1879 1799 1799 1898 1782 1782 1899 1781 1781 1879 1782 1782 1899 1764 1764 1880 1782 1782 1881 1800 1800 1900 1801 1801 1901 1782 1782 1881 1801 1801 1901 1783 1783 1882 1783 1783 1882 1801 1801 1901 1802 1802 1902 1783 1783 1882 1802 1802 1902 1784 1784 1883 1784 1784 1883 1802 1802 1902 1803 1803 1903 1784 1784 1883 1803 1803 1903 1785 1785 1884 1785 1785 1884 1803 1803 1903 1804 1804 1904 1785 1785 1884 1804 1804 1904 1786 1786 1885 1786 1786 1885 1804 1804 1904 1805 1805 1905 1786 1786 1885 1805 1805 1905 1787 1787 1886 1787 1787 1886 1805 1805 1905 1806 1806 1906 1787 1787 1886 1806 1806 1906 1788 1788 1887 1788 1788 1887 1806 1806 1906 1807 1807 1907 1788 1788 1887 1807 1807 1907 1789 1789 1888 1789 1789 1888 1807 1807 1907 1808 1808 1908 1789 1789 1888 1808 1808 1908 1790 1790 1889 1790 1790 1889 1808 1808 1908 1809 1809 1909 1790 1790 1889 1809 1809 1909 1791 1791 1890 1791 1791 1890 1809 1809 1909 1810 1810 1910 1791 1791 1890 1810 1810 1910 1792 1792 1891 1792 1792 1891 1810 1810 1910 1811 1811 1911 1792 1792 1891 1811 1811 1911 1793 1793 1892 1793 1793 1892 1811 1811 1911 1812 1812 1912 1793 1793 1892 1812 1812 1912 1794 1794 1893 1794 1794 1893 1812 1812 1912 1813 1813 1913 1794 1794 1893 1813 1813 1913 1795 1795 1894 1795 1795 1894 1813 1813 1913 1814 1814 1914 1795 1795 1894 1814 1814 1914 1796 1796 1895 1796 1796 1895 1814 1814 1914 1815 1815 1915 1796 1796 1895 1815 1815 1915 1797 1797 1896 1797 1797 1896 1815 1815 1915 1816 1816 1916 1797 1797 1896 1816 1816 1916 1798 1798 1897 1798 1798 1897 1816 1816 1916 1817 1817 1917 1798 1798 1897 1817 1817 1917 1799 1799 1898 1799 1799 1898 1817 1817 1917 1800 1800 1918 1799 1799 1898 1800 1800 1918 1782 1782 1899 1800 1800 1900 1818 1818 1919 1819 1819 1920 1800 1800 1900 1819 1819 1920 1801 1801 1901 1801 1801 1901 1819 1819 1920 1820 1820 1921 1801 1801 1901 1820 1820 1921 1802 1802 1902 1802 1802 1902 1820 1820 1921 1821 1821 1922 1802 1802 1902 1821 1821 1922 1803 1803 1903 1803 1803 1903 1821 1821 1922 1822 1822 1923 1803 1803 1903 1822 1822 1923 1804 1804 1904 1804 1804 1904 1822 1822 1923 1823 1823 1924 1804 1804 1904 1823 1823 1924 1805 1805 1905 1805 1805 1905 1823 1823 1924 1824 1824 1925 1805 1805 1905 1824 1824 1925 1806 1806 1906 1806 1806 1906 1824 1824 1925 1825 1825 1926 1806 1806 1906 1825 1825 1926 1807 1807 1907 1807 1807 1907 1825 1825 1926 1826 1826 1927 1807 1807 1907 1826 1826 1927 1808 1808 1908 1808 1808 1908 1826 1826 1927 1827 1827 1928 1808 1808 1908 1827 1827 1928 1809 1809 1909 1809 1809 1909 1827 1827 1928 1828 1828 1929 1809 1809 1909 1828 1828 1929 1810 1810 1910 1810 1810 1910 1828 1828 1929 1829 1829 1930 1810 1810 1910 1829 1829 1930 1811 1811 1911 1811 1811 1911 1829 1829 1930 1830 1830 1931 1811 1811 1911 1830 1830 1931 1812 1812 1912 1812 1812 1912 1830 1830 1931 1831 1831 1932 1812 1812 1912 1831 1831 1932 1813 1813 1913 1813 1813 1913 1831 1831 1932 1832 1832 1933 1813 1813 1913 1832 1832 1933 1814 1814 1914 1814 1814 1914 1832 1832 1933 1833 1833 1934 1814 1814 1914 1833 1833 1934 1815 1815 1915 1815 1815 1915 1833 1833 1934 1834 1834 1935 1815 1815 1915 1834 1834 1935 1816 1816 1916 1816 1816 1916 1834 1834 1935 1835 1835 1936 1816 1816 1916 1835 1835 1936 1817 1817 1917 1817 1817 1917 1835 1835 1936 1818 1818 1937 1817 1817 1917 1818 1818 1937 1800 1800 1918 1818 1818 1919 1836 1836 1938 1837 1837 1939 1818 1818 1919 1837 1837 1939 1819 1819 1920 1819 1819 1920 1837 1837 1939 1838 1838 1940 1819 1819 1920 1838 1838 1940 1820 1820 1921 1820 1820 1921 1838 1838 1940 1839 1839 1941 1820 1820 1921 1839 1839 1941 1821 1821 1922 1821 1821 1922 1839 1839 1941 1840 1840 1942 1821 1821 1922 1840 1840 1942 1822 1822 1923 1822 1822 1923 1840 1840 1942 1841 1841 1943 1822 1822 1923 1841 1841 1943 1823 1823 1924 1823 1823 1924 1841 1841 1943 1842 1842 1944 1823 1823 1924 1842 1842 1944 1824 1824 1925 1824 1824 1925 1842 1842 1944 1843 1843 1945 1824 1824 1925 1843 1843 1945 1825 1825 1926 1825 1825 1926 1843 1843 1945 1844 1844 1946 1825 1825 1926 1844 1844 1946 1826 1826 1927 1826 1826 1927 1844 1844 1946 1845 1845 1947 1826 1826 1927 1845 1845 1947 1827 1827 1928 1827 1827 1928 1845 1845 1947 1846 1846 1948 1827 1827 1928 1846 1846 1948 1828 1828 1929 1828 1828 1929 1846 1846 1948 1847 1847 1949 1828 1828 1929 1847 1847 1949 1829 1829 1930 1829 1829 1930 1847 1847 1949 1848 1848 1950 1829 1829 1930 1848 1848 1950 1830 1830 1931 1830 1830 1931 1848 1848 1950 1849 1849 1951 1830 1830 1931 1849 1849 1951 1831 1831 1932 1831 1831 1932 1849 1849 1951 1850 1850 1952 1831 1831 1932 1850 1850 1952 1832 1832 1933 1832 1832 1933 1850 1850 1952 1851 1851 1953 1832 1832 1933 1851 1851 1953 1833 1833 1934 1833 1833 1934 1851 1851 1953 1852 1852 1954 1833 1833 1934 1852 1852 1954 1834 1834 1935 1834 1834 1935 1852 1852 1954 1853 1853 1955 1834 1834 1935 1853 1853 1955 1835 1835 1936 1835 1835 1936 1853 1853 1955 1836 1836 1956 1835 1835 1936 1836 1836 1956 1818 1818 1937 1836 1836 1938 1854 1854 1957 1855 1855 1958 1836 1836 1938 1855 1855 1958 1837 1837 1939 1837 1837 1939 1855 1855 1958 1856 1856 1959 1837 1837 1939 1856 1856 1959 1838 1838 1940 1838 1838 1940 1856 1856 1959 1857 1857 1960 1838 1838 1940 1857 1857 1960 1839 1839 1941 1839 1839 1941 1857 1857 1960 1858 1858 1961 1839 1839 1941 1858 1858 1961 1840 1840 1942 1840 1840 1942 1858 1858 1961 1859 1859 1962 1840 1840 1942 1859 1859 1962 1841 1841 1943 1841 1841 1943 1859 1859 1962 1860 1860 1963 1841 1841 1943 1860 1860 1963 1842 1842 1944 1842 1842 1944 1860 1860 1963 1861 1861 1964 1842 1842 1944 1861 1861 1964 1843 1843 1945 1843 1843 1945 1861 1861 1964 1862 1862 1965 1843 1843 1945 1862 1862 1965 1844 1844 1946 1844 1844 1946 1862 1862 1965 1863 1863 1966 1844 1844 1946 1863 1863 1966 1845 1845 1947 1845 1845 1947 1863 1863 1966 1864 1864 1967 1845 1845 1947 1864 1864 1967 1846 1846 1948 1846 1846 1948 1864 1864 1967 1865 1865 1968 1846 1846 1948 1865 1865 1968 1847 1847 1949 1847 1847 1949 1865 1865 1968 1866 1866 1969 1847 1847 1949 1866 1866 1969 1848 1848 1950 1848 1848 1950 1866 1866 1969 1867 1867 1970 1848 1848 1950 1867 1867 1970 1849 1849 1951 1849 1849 1951 1867 1867 1970 1868 1868 1971 1849 1849 1951 1868 1868 1971 1850 1850 1952 1850 1850 1952 1868 1868 1971 1869 1869 1972 1850 1850 1952 1869 1869 1972 1851 1851 1953 1851 1851 1953 1869 1869 1972 1870 1870 1973 1851 1851 1953 1870 1870 1973 1852 1852 1954 1852 1852 1954 1870 1870 1973 1871 1871 1974 1852 1852 1954 1871 1871 1974 1853 1853 1955 1853 1853 1955 1871 1871 1974 1854 1854 1975 1853 1853 1955 1854 1854 1975 1836 1836 1956 1854 1854 1957 1872 1872 1976 1873 1873 1977 1854 1854 1957 1873 1873 1977 1855 1855 1958 1855 1855 1958 1873 1873 1977 1874 1874 1978 1855 1855 1958 1874 1874 1978 1856 1856 1959 1856 1856 1959 1874 1874 1978 1875 1875 1979 1856 1856 1959 1875 1875 1979 1857 1857 1960 1857 1857 1960 1875 1875 1979 1876 1876 1980 1857 1857 1960 1876 1876 1980 1858 1858 1961 1858 1858 1961 1876 1876 1980 1877 1877 1981 1858 1858 1961 1877 1877 1981 1859 1859 1962 1859 1859 1962 1877 1877 1981 1878 1878 1982 1859 1859 1962 1878 1878 1982 1860 1860 1963 1860 1860 1963 1878 1878 1982 1879 1879 1983 1860 1860 1963 1879 1879 1983 1861 1861 1964 1861 1861 1964 1879 1879 1983 1880 1880 1984 1861 1861 1964 1880 1880 1984 1862 1862 1965 1862 1862 1965 1880 1880 1984 1881 1881 1985 1862 1862 1965 1881 1881 1985 1863 1863 1966 1863 1863 1966 1881 1881 1985 1882 1882 1986 1863 1863 1966 1882 1882 1986 1864 1864 1967 1864 1864 1967 1882 1882 1986 1883 1883 1987 1864 1864 1967 1883 1883 1987 1865 1865 1968 1865 1865 1968 1883 1883 1987 1884 1884 1988 1865 1865 1968 1884 1884 1988 1866 1866 1969 1866 1866 1969 1884 1884 1988 1885 1885 1989 1866 1866 1969 1885 1885 1989 1867 1867 1970 1867 1867 1970 1885 1885 1989 1886 1886 1990 1867 1867 1970 1886 1886 1990 1868 1868 1971 1868 1868 1971 1886 1886 1990 1887 1887 1991 1868 1868 1971 1887 1887 1991 1869 1869 1972 1869 1869 1972 1887 1887 1991 1888 1888 1992 1869 1869 1972 1888 1888 1992 1870 1870 1973 1870 1870 1973 1888 1888 1992 1889 1889 1993 1870 1870 1973 1889 1889 1993 1871 1871 1974 1871 1871 1974 1889 1889 1993 1872 1872 1994 1871 1871 1974 1872 1872 1994 1854 1854 1975 1872 1872 1976 1890 1890 1995 1891 1891 1996 1872 1872 1976 1891 1891 1996 1873 1873 1977 1873 1873 1977 1891 1891 1996 1892 1892 1997 1873 1873 1977 1892 1892 1997 1874 1874 1978 1874 1874 1978 1892 1892 1997 1893 1893 1998 1874 1874 1978 1893 1893 1998 1875 1875 1979 1875 1875 1979 1893 1893 1998 1894 1894 1999 1875 1875 1979 1894 1894 1999 1876 1876 1980 1876 1876 1980 1894 1894 1999 1895 1895 2000 1876 1876 1980 1895 1895 2000 1877 1877 1981 1877 1877 1981 1895 1895 2000 1896 1896 2001 1877 1877 1981 1896 1896 2001 1878 1878 1982 1878 1878 1982 1896 1896 2001 1897 1897 2002 1878 1878 1982 1897 1897 2002 1879 1879 1983 1879 1879 1983 1897 1897 2002 1898 1898 2003 1879 1879 1983 1898 1898 2003 1880 1880 1984 1880 1880 1984 1898 1898 2003 1899 1899 2004 1880 1880 1984 1899 1899 2004 1881 1881 1985 1881 1881 1985 1899 1899 2004 1900 1900 2005 1881 1881 1985 1900 1900 2005 1882 1882 1986 1882 1882 1986 1900 1900 2005 1901 1901 2006 1882 1882 1986 1901 1901 2006 1883 1883 1987 1883 1883 1987 1901 1901 2006 1902 1902 2007 1883 1883 1987 1902 1902 2007 1884 1884 1988 1884 1884 1988 1902 1902 2007 1903 1903 2008 1884 1884 1988 1903 1903 2008 1885 1885 1989 1885 1885 1989 1903 1903 2008 1904 1904 2009 1885 1885 1989 1904 1904 2009 1886 1886 1990 1886 1886 1990 1904 1904 2009 1905 1905 2010 1886 1886 1990 1905 1905 2010 1887 1887 1991 1887 1887 1991 1905 1905 2010 1906 1906 2011 1887 1887 1991 1906 1906 2011 1888 1888 1992 1888 1888 1992 1906 1906 2011 1907 1907 2012 1888 1888 1992 1907 1907 2012 1889 1889 1993 1889 1889 1993 1907 1907 2012 1890 1890 2013 1889 1889 1993 1890 1890 2013 1872 1872 1994 1890 1890 1995 1908 1908 2014 1909 1909 2015 1890 1890 1995 1909 1909 2015 1891 1891 1996 1891 1891 1996 1909 1909 2015 1910 1910 2016 1891 1891 1996 1910 1910 2016 1892 1892 1997 1892 1892 1997 1910 1910 2016 1911 1911 2017 1892 1892 1997 1911 1911 2017 1893 1893 1998 1893 1893 1998 1911 1911 2017 1912 1912 2018 1893 1893 1998 1912 1912 2018 1894 1894 1999 1894 1894 1999 1912 1912 2018 1913 1913 2019 1894 1894 1999 1913 1913 2019 1895 1895 2000 1895 1895 2000 1913 1913 2019 1914 1914 2020 1895 1895 2000 1914 1914 2020 1896 1896 2001 1896 1896 2001 1914 1914 2020 1915 1915 2021 1896 1896 2001 1915 1915 2021 1897 1897 2002 1897 1897 2002 1915 1915 2021 1916 1916 2022 1897 1897 2002 1916 1916 2022 1898 1898 2003 1898 1898 2003 1916 1916 2022 1917 1917 2023 1898 1898 2003 1917 1917 2023 1899 1899 2004 1899 1899 2004 1917 1917 2023 1918 1918 2024 1899 1899 2004 1918 1918 2024 1900 1900 2005 1900 1900 2005 1918 1918 2024 1919 1919 2025 1900 1900 2005 1919 1919 2025 1901 1901 2006 1901 1901 2006 1919 1919 2025 1920 1920 2026 1901 1901 2006 1920 1920 2026 1902 1902 2007 1902 1902 2007 1920 1920 2026 1921 1921 2027 1902 1902 2007 1921 1921 2027 1903 1903 2008 1903 1903 2008 1921 1921 2027 1922 1922 2028 1903 1903 2008 1922 1922 2028 1904 1904 2009 1904 1904 2009 1922 1922 2028 1923 1923 2029 1904 1904 2009 1923 1923 2029 1905 1905 2010 1905 1905 2010 1923 1923 2029 1924 1924 2030 1905 1905 2010 1924 1924 2030 1906 1906 2011 1906 1906 2011 1924 1924 2030 1925 1925 2031 1906 1906 2011 1925 1925 2031 1907 1907 2012 1907 1907 2012 1925 1925 2031 1908 1908 2032 1907 1907 2012 1908 1908 2032 1890 1890 2013 1908 1908 2014 1926 1926 2033 1927 1927 2034 1908 1908 2014 1927 1927 2034 1909 1909 2015 1909 1909 2015 1927 1927 2034 1928 1928 2035 1909 1909 2015 1928 1928 2035 1910 1910 2016 1910 1910 2016 1928 1928 2035 1929 1929 2036 1910 1910 2016 1929 1929 2036 1911 1911 2017 1911 1911 2017 1929 1929 2036 1930 1930 2037 1911 1911 2017 1930 1930 2037 1912 1912 2018 1912 1912 2018 1930 1930 2037 1931 1931 2038 1912 1912 2018 1931 1931 2038 1913 1913 2019 1913 1913 2019 1931 1931 2038 1932 1932 2039 1913 1913 2019 1932 1932 2039 1914 1914 2020 1914 1914 2020 1932 1932 2039 1933 1933 2040 1914 1914 2020 1933 1933 2040 1915 1915 2021 1915 1915 2021 1933 1933 2040 1934 1934 2041 1915 1915 2021 1934 1934 2041 1916 1916 2022 1916 1916 2022 1934 1934 2041 1935 1935 2042 1916 1916 2022 1935 1935 2042 1917 1917 2023 1917 1917 2023 1935 1935 2042 1936 1936 2043 1917 1917 2023 1936 1936 2043 1918 1918 2024 1918 1918 2024 1936 1936 2043 1937 1937 2044 1918 1918 2024 1937 1937 2044 1919 1919 2025 1919 1919 2025 1937 1937 2044 1938 1938 2045 1919 1919 2025 1938 1938 2045 1920 1920 2026 1920 1920 2026 1938 1938 2045 1939 1939 2046 1920 1920 2026 1939 1939 2046 1921 1921 2027 1921 1921 2027 1939 1939 2046 1940 1940 2047 1921 1921 2027 1940 1940 2047 1922 1922 2028 1922 1922 2028 1940 1940 2047 1941 1941 2048 1922 1922 2028 1941 1941 2048 1923 1923 2029 1923 1923 2029 1941 1941 2048 1942 1942 2049 1923 1923 2029 1942 1942 2049 1924 1924 2030 1924 1924 2030 1942 1942 2049 1943 1943 2050 1924 1924 2030 1943 1943 2050 1925 1925 2031 1925 1925 2031 1943 1943 2050 1926 1926 2051 1925 1925 2031 1926 1926 2051 1908 1908 2032 1926 1926 2033 1944 1944 2052 1945 1945 2053 1926 1926 2033 1945 1945 2053 1927 1927 2034 1927 1927 2034 1945 1945 2053 1946 1946 2054 1927 1927 2034 1946 1946 2054 1928 1928 2035 1928 1928 2035 1946 1946 2054 1947 1947 2055 1928 1928 2035 1947 1947 2055 1929 1929 2036 1929 1929 2036 1947 1947 2055 1948 1948 2056 1929 1929 2036 1948 1948 2056 1930 1930 2037 1930 1930 2037 1948 1948 2056 1949 1949 2057 1930 1930 2037 1949 1949 2057 1931 1931 2038 1931 1931 2038 1949 1949 2057 1950 1950 2058 1931 1931 2038 1950 1950 2058 1932 1932 2039 1932 1932 2039 1950 1950 2058 1951 1951 2059 1932 1932 2039 1951 1951 2059 1933 1933 2040 1933 1933 2040 1951 1951 2059 1952 1952 2060 1933 1933 2040 1952 1952 2060 1934 1934 2041 1934 1934 2041 1952 1952 2060 1953 1953 2061 1934 1934 2041 1953 1953 2061 1935 1935 2042 1935 1935 2042 1953 1953 2061 1954 1954 2062 1935 1935 2042 1954 1954 2062 1936 1936 2043 1936 1936 2043 1954 1954 2062 1955 1955 2063 1936 1936 2043 1955 1955 2063 1937 1937 2044 1937 1937 2044 1955 1955 2063 1956 1956 2064 1937 1937 2044 1956 1956 2064 1938 1938 2045 1938 1938 2045 1956 1956 2064 1957 1957 2065 1938 1938 2045 1957 1957 2065 1939 1939 2046 1939 1939 2046 1957 1957 2065 1958 1958 2066 1939 1939 2046 1958 1958 2066 1940 1940 2047 1940 1940 2047 1958 1958 2066 1959 1959 2067 1940 1940 2047 1959 1959 2067 1941 1941 2048 1941 1941 2048 1959 1959 2067 1960 1960 2068 1941 1941 2048 1960 1960 2068 1942 1942 2049 1942 1942 2049 1960 1960 2068 1961 1961 2069 1942 1942 2049 1961 1961 2069 1943 1943 2050 1943 1943 2050 1961 1961 2069 1944 1944 2070 1943 1943 2050 1944 1944 2070 1926 1926 2051 1944 1944 2052 1962 1962 2071 1963 1963 2072 1944 1944 2052 1963 1963 2072 1945 1945 2053 1945 1945 2053 1963 1963 2072 1964 1964 2073 1945 1945 2053 1964 1964 2073 1946 1946 2054 1946 1946 2054 1964 1964 2073 1965 1965 2074 1946 1946 2054 1965 1965 2074 1947 1947 2055 1947 1947 2055 1965 1965 2074 1966 1966 2075 1947 1947 2055 1966 1966 2075 1948 1948 2056 1948 1948 2056 1966 1966 2075 1967 1967 2076 1948 1948 2056 1967 1967 2076 1949 1949 2057 1949 1949 2057 1967 1967 2076 1968 1968 2077 1949 1949 2057 1968 1968 2077 1950 1950 2058 1950 1950 2058 1968 1968 2077 1969 1969 2078 1950 1950 2058 1969 1969 2078 1951 1951 2059 1951 1951 2059 1969 1969 2078 1970 1970 2079 1951 1951 2059 1970 1970 2079 1952 1952 2060 1952 1952 2060 1970 1970 2079 1971 1971 2080 1952 1952 2060 1971 1971 2080 1953 1953 2061 1953 1953 2061 1971 1971 2080 1972 1972 2081 1953 1953 2061 1972 1972 2081 1954 1954 2062 1954 1954 2062 1972 1972 2081 1973 1973 2082 1954 1954 2062 1973 1973 2082 1955 1955 2063 1955 1955 2063 1973 1973 2082 1974 1974 2083 1955 1955 2063 1974 1974 2083 1956 1956 2064 1956 1956 2064 1974 1974 2083 1975 1975 2084 1956 1956 2064 1975 1975 2084 1957 1957 2065 1957 1957 2065 1975 1975 2084 1976 1976 2085 1957 1957 2065 1976 1976 2085 1958 1958 2066 1958 1958 2066 1976 1976 2085 1977 1977 2086 1958 1958 2066 1977 1977 2086 1959 1959 2067 1959 1959 2067 1977 1977 2086 1978 1978 2087 1959 1959 2067 1978 1978 2087 1960 1960 2068 1960 1960 2068 1978 1978 2087 1979 1979 2088 1960 1960 2068 1979 1979 2088 1961 1961 2069 1961 1961 2069 1979 1979 2088 1962 1962 2089 1961 1961 2069 1962 1962 2089 1944 1944 2070 1962 1962 2071 1980 1980 2090 1981 1981 2091 1962 1962 2071 1981 1981 2091 1963 1963 2072 1963 1963 2072 1981 1981 2091 1982 1982 2092 1963 1963 2072 1982 1982 2092 1964 1964 2073 1964 1964 2073 1982 1982 2092 1983 1983 2093 1964 1964 2073 1983 1983 2093 1965 1965 2074 1965 1965 2074 1983 1983 2093 1984 1984 2094 1965 1965 2074 1984 1984 2094 1966 1966 2075 1966 1966 2075 1984 1984 2094 1985 1985 2095 1966 1966 2075 1985 1985 2095 1967 1967 2076 1967 1967 2076 1985 1985 2095 1986 1986 2096 1967 1967 2076 1986 1986 2096 1968 1968 2077 1968 1968 2077 1986 1986 2096 1987 1987 2097 1968 1968 2077 1987 1987 2097 1969 1969 2078 1969 1969 2078 1987 1987 2097 1988 1988 2098 1969 1969 2078 1988 1988 2098 1970 1970 2079 1970 1970 2079 1988 1988 2098 1989 1989 2099 1970 1970 2079 1989 1989 2099 1971 1971 2080 1971 1971 2080 1989 1989 2099 1990 1990 2100 1971 1971 2080 1990 1990 2100 1972 1972 2081 1972 1972 2081 1990 1990 2100 1991 1991 2101 1972 1972 2081 1991 1991 2101 1973 1973 2082 1973 1973 2082 1991 1991 2101 1992 1992 2102 1973 1973 2082 1992 1992 2102 1974 1974 2083 1974 1974 2083 1992 1992 2102 1993 1993 2103 1974 1974 2083 1993 1993 2103 1975 1975 2084 1975 1975 2084 1993 1993 2103 1994 1994 2104 1975 1975 2084 1994 1994 2104 1976 1976 2085 1976 1976 2085 1994 1994 2104 1995 1995 2105 1976 1976 2085 1995 1995 2105 1977 1977 2086 1977 1977 2086 1995 1995 2105 1996 1996 2106 1977 1977 2086 1996 1996 2106 1978 1978 2087 1978 1978 2087 1996 1996 2106 1997 1997 2107 1978 1978 2087 1997 1997 2107 1979 1979 2088 1979 1979 2088 1997 1997 2107 1980 1980 2108 1979 1979 2088 1980 1980 2108 1962 1962 2089 1980 1980 2090 1998 1998 2109 1999 1999 2110 1980 1980 2090 1999 1999 2110 1981 1981 2091 1981 1981 2091 1999 1999 2110 2000 2000 2111 1981 1981 2091 2000 2000 2111 1982 1982 2092 1982 1982 2092 2000 2000 2111 2001 2001 2112 1982 1982 2092 2001 2001 2112 1983 1983 2093 1983 1983 2093 2001 2001 2112 2002 2002 2113 1983 1983 2093 2002 2002 2113 1984 1984 2094 1984 1984 2094 2002 2002 2113 2003 2003 2114 1984 1984 2094 2003 2003 2114 1985 1985 2095 1985 1985 2095 2003 2003 2114 2004 2004 2115 1985 1985 2095 2004 2004 2115 1986 1986 2096 1986 1986 2096 2004 2004 2115 2005 2005 2116 1986 1986 2096 2005 2005 2116 1987 1987 2097 1987 1987 2097 2005 2005 2116 2006 2006 2117 1987 1987 2097 2006 2006 2117 1988 1988 2098 1988 1988 2098 2006 2006 2117 2007 2007 2118 1988 1988 2098 2007 2007 2118 1989 1989 2099 1989 1989 2099 2007 2007 2118 2008 2008 2119 1989 1989 2099 2008 2008 2119 1990 1990 2100 1990 1990 2100 2008 2008 2119 2009 2009 2120 1990 1990 2100 2009 2009 2120 1991 1991 2101 1991 1991 2101 2009 2009 2120 2010 2010 2121 1991 1991 2101 2010 2010 2121 1992 1992 2102 1992 1992 2102 2010 2010 2121 2011 2011 2122 1992 1992 2102 2011 2011 2122 1993 1993 2103 1993 1993 2103 2011 2011 2122 2012 2012 2123 1993 1993 2103 2012 2012 2123 1994 1994 2104 1994 1994 2104 2012 2012 2123 2013 2013 2124 1994 1994 2104 2013 2013 2124 1995 1995 2105 1995 1995 2105 2013 2013 2124 2014 2014 2125 1995 1995 2105 2014 2014 2125 1996 1996 2106 1996 1996 2106 2014 2014 2125 2015 2015 2126 1996 1996 2106 2015 2015 2126 1997 1997 2107 1997 1997 2107 2015 2015 2126 1998 1998 2127 1997 1997 2107 1998 1998 2127 1980 1980 2108 1998 1998 2109 2016 2016 2128 2017 2017 2129 1998 1998 2109 2017 2017 2129 1999 1999 2110 1999 1999 2110 2017 2017 2129 2018 2018 2130 1999 1999 2110 2018 2018 2130 2000 2000 2111 2000 2000 2111 2018 2018 2130 2019 2019 2131 2000 2000 2111 2019 2019 2131 2001 2001 2112 2001 2001 2112 2019 2019 2131 2020 2020 2132 2001 2001 2112 2020 2020 2132 2002 2002 2113 2002 2002 2113 2020 2020 2132 2021 2021 2133 2002 2002 2113 2021 2021 2133 2003 2003 2114 2003 2003 2114 2021 2021 2133 2022 2022 2134 2003 2003 2114 2022 2022 2134 2004 2004 2115 2004 2004 2115 2022 2022 2134 2023 2023 2135 2004 2004 2115 2023 2023 2135 2005 2005 2116 2005 2005 2116 2023 2023 2135 2024 2024 2136 2005 2005 2116 2024 2024 2136 2006 2006 2117 2006 2006 2117 2024 2024 2136 2025 2025 2137 2006 2006 2117 2025 2025 2137 2007 2007 2118 2007 2007 2118 2025 2025 2137 2026 2026 2138 2007 2007 2118 2026 2026 2138 2008 2008 2119 2008 2008 2119 2026 2026 2138 2027 2027 2139 2008 2008 2119 2027 2027 2139 2009 2009 2120 2009 2009 2120 2027 2027 2139 2028 2028 2140 2009 2009 2120 2028 2028 2140 2010 2010 2121 2010 2010 2121 2028 2028 2140 2029 2029 2141 2010 2010 2121 2029 2029 2141 2011 2011 2122 2011 2011 2122 2029 2029 2141 2030 2030 2142 2011 2011 2122 2030 2030 2142 2012 2012 2123 2012 2012 2123 2030 2030 2142 2031 2031 2143 2012 2012 2123 2031 2031 2143 2013 2013 2124 2013 2013 2124 2031 2031 2143 2032 2032 2144 2013 2013 2124 2032 2032 2144 2014 2014 2125 2014 2014 2125 2032 2032 2144 2033 2033 2145 2014 2014 2125 2033 2033 2145 2015 2015 2126 2015 2015 2126 2033 2033 2145 2016 2016 2146 2015 2015 2126 2016 2016 2146 1998 1998 2127 2016 2016 2128 2034 2034 2147 2035 2035 2148 2016 2016 2128 2035 2035 2148 2017 2017 2129 2017 2017 2129 2035 2035 2148 2036 2036 2149 2017 2017 2129 2036 2036 2149 2018 2018 2130 2018 2018 2130 2036 2036 2149 2037 2037 2150 2018 2018 2130 2037 2037 2150 2019 2019 2131 2019 2019 2131 2037 2037 2150 2038 2038 2151 2019 2019 2131 2038 2038 2151 2020 2020 2132 2020 2020 2132 2038 2038 2151 2039 2039 2152 2020 2020 2132 2039 2039 2152 2021 2021 2133 2021 2021 2133 2039 2039 2152 2040 2040 2153 2021 2021 2133 2040 2040 2153 2022 2022 2134 2022 2022 2134 2040 2040 2153 2041 2041 2154 2022 2022 2134 2041 2041 2154 2023 2023 2135 2023 2023 2135 2041 2041 2154 2042 2042 2155 2023 2023 2135 2042 2042 2155 2024 2024 2136 2024 2024 2136 2042 2042 2155 2043 2043 2156 2024 2024 2136 2043 2043 2156 2025 2025 2137 2025 2025 2137 2043 2043 2156 2044 2044 2157 2025 2025 2137 2044 2044 2157 2026 2026 2138 2026 2026 2138 2044 2044 2157 2045 2045 2158 2026 2026 2138 2045 2045 2158 2027 2027 2139 2027 2027 2139 2045 2045 2158 2046 2046 2159 2027 2027 2139 2046 2046 2159 2028 2028 2140 2028 2028 2140 2046 2046 2159 2047 2047 2160 2028 2028 2140 2047 2047 2160 2029 2029 2141 2029 2029 2141 2047 2047 2160 2048 2048 2161 2029 2029 2141 2048 2048 2161 2030 2030 2142 2030 2030 2142 2048 2048 2161 2049 2049 2162 2030 2030 2142 2049 2049 2162 2031 2031 2143 2031 2031 2143 2049 2049 2162 2050 2050 2163 2031 2031 2143 2050 2050 2163 2032 2032 2144 2032 2032 2144 2050 2050 2163 2051 2051 2164 2032 2032 2144 2051 2051 2164 2033 2033 2145 2033 2033 2145 2051 2051 2164 2034 2034 2165 2033 2033 2145 2034 2034 2165 2016 2016 2146 2034 2034 2147 2052 2052 2166 2053 2053 2167 2034 2034 2147 2053 2053 2167 2035 2035 2148 2035 2035 2148 2053 2053 2167 2054 2054 2168 2035 2035 2148 2054 2054 2168 2036 2036 2149 2036 2036 2149 2054 2054 2168 2055 2055 2169 2036 2036 2149 2055 2055 2169 2037 2037 2150 2037 2037 2150 2055 2055 2169 2056 2056 2170 2037 2037 2150 2056 2056 2170 2038 2038 2151 2038 2038 2151 2056 2056 2170 2057 2057 2171 2038 2038 2151 2057 2057 2171 2039 2039 2152 2039 2039 2152 2057 2057 2171 2058 2058 2172 2039 2039 2152 2058 2058 2172 2040 2040 2153 2040 2040 2153 2058 2058 2172 2059 2059 2173 2040 2040 2153 2059 2059 2173 2041 2041 2154 2041 2041 2154 2059 2059 2173 2060 2060 2174 2041 2041 2154 2060 2060 2174 2042 2042 2155 2042 2042 2155 2060 2060 2174 2061 2061 2175 2042 2042 2155 2061 2061 2175 2043 2043 2156 2043 2043 2156 2061 2061 2175 2062 2062 2176 2043 2043 2156 2062 2062 2176 2044 2044 2157 2044 2044 2157 2062 2062 2176 2063 2063 2177 2044 2044 2157 2063 2063 2177 2045 2045 2158 2045 2045 2158 2063 2063 2177 2064 2064 2178 2045 2045 2158 2064 2064 2178 2046 2046 2159 2046 2046 2159 2064 2064 2178 2065 2065 2179 2046 2046 2159 2065 2065 2179 2047 2047 2160 2047 2047 2160 2065 2065 2179 2066 2066 2180 2047 2047 2160 2066 2066 2180 2048 2048 2161 2048 2048 2161 2066 2066 2180 2067 2067 2181 2048 2048 2161 2067 2067 2181 2049 2049 2162 2049 2049 2162 2067 2067 2181 2068 2068 2182 2049 2049 2162 2068 2068 2182 2050 2050 2163 2050 2050 2163 2068 2068 2182 2069 2069 2183 2050 2050 2163 2069 2069 2183 2051 2051 2164 2051 2051 2164 2069 2069 2183 2052 2052 2184 2051 2051 2164 2052 2052 2184 2034 2034 2165 2052 2052 2166 2070 2070 2185 2071 2071 2186 2052 2052 2166 2071 2071 2186 2053 2053 2167 2053 2053 2167 2071 2071 2186 2072 2072 2187 2053 2053 2167 2072 2072 2187 2054 2054 2168 2054 2054 2168 2072 2072 2187 2073 2073 2188 2054 2054 2168 2073 2073 2188 2055 2055 2169 2055 2055 2169 2073 2073 2188 2074 2074 2189 2055 2055 2169 2074 2074 2189 2056 2056 2170 2056 2056 2170 2074 2074 2189 2075 2075 2190 2056 2056 2170 2075 2075 2190 2057 2057 2171 2057 2057 2171 2075 2075 2190 2076 2076 2191 2057 2057 2171 2076 2076 2191 2058 2058 2172 2058 2058 2172 2076 2076 2191 2077 2077 2192 2058 2058 2172 2077 2077 2192 2059 2059 2173 2059 2059 2173 2077 2077 2192 2078 2078 2193 2059 2059 2173 2078 2078 2193 2060 2060 2174 2060 2060 2174 2078 2078 2193 2079 2079 2194 2060 2060 2174 2079 2079 2194 2061 2061 2175 2061 2061 2175 2079 2079 2194 2080 2080 2195 2061 2061 2175 2080 2080 2195 2062 2062 2176 2062 2062 2176 2080 2080 2195 2081 2081 2196 2062 2062 2176 2081 2081 2196 2063 2063 2177 2063 2063 2177 2081 2081 2196 2082 2082 2197 2063 2063 2177 2082 2082 2197 2064 2064 2178 2064 2064 2178 2082 2082 2197 2083 2083 2198 2064 2064 2178 2083 2083 2198 2065 2065 2179 2065 2065 2179 2083 2083 2198 2084 2084 2199 2065 2065 2179 2084 2084 2199 2066 2066 2180 2066 2066 2180 2084 2084 2199 2085 2085 2200 2066 2066 2180 2085 2085 2200 2067 2067 2181 2067 2067 2181 2085 2085 2200 2086 2086 2201 2067 2067 2181 2086 2086 2201 2068 2068 2182 2068 2068 2182 2086 2086 2201 2087 2087 2202 2068 2068 2182 2087 2087 2202 2069 2069 2183 2069 2069 2183 2087 2087 2202 2070 2070 2203 2069 2069 2183 2070 2070 2203 2052 2052 2184 2070 2070 2185 2088 2088 2204 2089 2089 2205 2070 2070 2185 2089 2089 2205 2071 2071 2186 2071 2071 2186 2089 2089 2205 2090 2090 2206 2071 2071 2186 2090 2090 2206 2072 2072 2187 2072 2072 2187 2090 2090 2206 2091 2091 2207 2072 2072 2187 2091 2091 2207 2073 2073 2188 2073 2073 2188 2091 2091 2207 2092 2092 2208 2073 2073 2188 2092 2092 2208 2074 2074 2189 2074 2074 2189 2092 2092 2208 2093 2093 2209 2074 2074 2189 2093 2093 2209 2075 2075 2190 2075 2075 2190 2093 2093 2209 2094 2094 2210 2075 2075 2190 2094 2094 2210 2076 2076 2191 2076 2076 2191 2094 2094 2210 2095 2095 2211 2076 2076 2191 2095 2095 2211 2077 2077 2192 2077 2077 2192 2095 2095 2211 2096 2096 2212 2077 2077 2192 2096 2096 2212 2078 2078 2193 2078 2078 2193 2096 2096 2212 2097 2097 2213 2078 2078 2193 2097 2097 2213 2079 2079 2194 2079 2079 2194 2097 2097 2213 2098 2098 2214 2079 2079 2194 2098 2098 2214 2080 2080 2195 2080 2080 2195 2098 2098 2214 2099 2099 2215 2080 2080 2195 2099 2099 2215 2081 2081 2196 2081 2081 2196 2099 2099 2215 2100 2100 2216 2081 2081 2196 2100 2100 2216 2082 2082 2197 2082 2082 2197 2100 2100 2216 2101 2101 2217 2082 2082 2197 2101 2101 2217 2083 2083 2198 2083 2083 2198 2101 2101 2217 2102 2102 2218 2083 2083 2198 2102 2102 2218 2084 2084 2199 2084 2084 2199 2102 2102 2218 2103 2103 2219 2084 2084 2199 2103 2103 2219 2085 2085 2200 2085 2085 2200 2103 2103 2219 2104 2104 2220 2085 2085 2200 2104 2104 2220 2086 2086 2201 2086 2086 2201 2104 2104 2220 2105 2105 2221 2086 2086 2201 2105 2105 2221 2087 2087 2202 2087 2087 2202 2105 2105 2221 2088 2088 2222 2087 2087 2202 2088 2088 2222 2070 2070 2203 2088 2088 2204 2106 2106 2223 2107 2107 2224 2088 2088 2204 2107 2107 2224 2089 2089 2205 2089 2089 2205 2107 2107 2224 2108 2108 2225 2089 2089 2205 2108 2108 2225 2090 2090 2206 2090 2090 2206 2108 2108 2225 2109 2109 2226 2090 2090 2206 2109 2109 2226 2091 2091 2207 2091 2091 2207 2109 2109 2226 2110 2110 2227 2091 2091 2207 2110 2110 2227 2092 2092 2208 2092 2092 2208 2110 2110 2227 2111 2111 2228 2092 2092 2208 2111 2111 2228 2093 2093 2209 2093 2093 2209 2111 2111 2228 2112 2112 2229 2093 2093 2209 2112 2112 2229 2094 2094 2210 2094 2094 2210 2112 2112 2229 2113 2113 2230 2094 2094 2210 2113 2113 2230 2095 2095 2211 2095 2095 2211 2113 2113 2230 2114 2114 2231 2095 2095 2211 2114 2114 2231 2096 2096 2212 2096 2096 2212 2114 2114 2231 2115 2115 2232 2096 2096 2212 2115 2115 2232 2097 2097 2213 2097 2097 2213 2115 2115 2232 2116 2116 2233 2097 2097 2213 2116 2116 2233 2098 2098 2214 2098 2098 2214 2116 2116 2233 2117 2117 2234 2098 2098 2214 2117 2117 2234 2099 2099 2215 2099 2099 2215 2117 2117 2234 2118 2118 2235 2099 2099 2215 2118 2118 2235 2100 2100 2216 2100 2100 2216 2118 2118 2235 2119 2119 2236 2100 2100 2216 2119 2119 2236 2101 2101 2217 2101 2101 2217 2119 2119 2236 2120 2120 2237 2101 2101 2217 2120 2120 2237 2102 2102 2218 2102 2102 2218 2120 2120 2237 2121 2121 2238 2102 2102 2218 2121 2121 2238 2103 2103 2219 2103 2103 2219 2121 2121 2238 2122 2122 2239 2103 2103 2219 2122 2122 2239 2104 2104 2220 2104 2104 2220 2122 2122 2239 2123 2123 2240 2104 2104 2220 2123 2123 2240 2105 2105 2221 2105 2105 2221 2123 2123 2240 2106 2106 2241 2105 2105 2221 2106 2106 2241 2088 2088 2222 2106 2106 2223 2124 2124 2242 2125 2125 2243 2106 2106 2223 2125 2125 2243 2107 2107 2224 2107 2107 2224 2125 2125 2243 2126 2126 2244 2107 2107 2224 2126 2126 2244 2108 2108 2225 2108 2108 2225 2126 2126 2244 2127 2127 2245 2108 2108 2225 2127 2127 2245 2109 2109 2226 2109 2109 2226 2127 2127 2245 2128 2128 2246 2109 2109 2226 2128 2128 2246 2110 2110 2227 2110 2110 2227 2128 2128 2246 2129 2129 2247 2110 2110 2227 2129 2129 2247 2111 2111 2228 2111 2111 2228 2129 2129 2247 2130 2130 2248 2111 2111 2228 2130 2130 2248 2112 2112 2229 2112 2112 2229 2130 2130 2248 2131 2131 2249 2112 2112 2229 2131 2131 2249 2113 2113 2230 2113 2113 2230 2131 2131 2249 2132 2132 2250 2113 2113 2230 2132 2132 2250 2114 2114 2231 2114 2114 2231 2132 2132 2250 2133 2133 2251 2114 2114 2231 2133 2133 2251 2115 2115 2232 2115 2115 2232 2133 2133 2251 2134 2134 2252 2115 2115 2232 2134 2134 2252 2116 2116 2233 2116 2116 2233 2134 2134 2252 2135 2135 2253 2116 2116 2233 2135 2135 2253 2117 2117 2234 2117 2117 2234 2135 2135 2253 2136 2136 2254 2117 2117 2234 2136 2136 2254 2118 2118 2235 2118 2118 2235 2136 2136 2254 2137 2137 2255 2118 2118 2235 2137 2137 2255 2119 2119 2236 2119 2119 2236 2137 2137 2255 2138 2138 2256 2119 2119 2236 2138 2138 2256 2120 2120 2237 2120 2120 2237 2138 2138 2256 2139 2139 2257 2120 2120 2237 2139 2139 2257 2121 2121 2238 2121 2121 2238 2139 2139 2257 2140 2140 2258 2121 2121 2238 2140 2140 2258 2122 2122 2239 2122 2122 2239 2140 2140 2258 2141 2141 2259 2122 2122 2239 2141 2141 2259 2123 2123 2240 2123 2123 2240 2141 2141 2259 2124 2124 2260 2123 2123 2240 2124 2124 2260 2106 2106 2241 2124 2124 2242 2142 2142 2261 2143 2143 2262 2124 2124 2242 2143 2143 2262 2125 2125 2243 2125 2125 2243 2143 2143 2262 2144 2144 2263 2125 2125 2243 2144 2144 2263 2126 2126 2244 2126 2126 2244 2144 2144 2263 2145 2145 2264 2126 2126 2244 2145 2145 2264 2127 2127 2245 2127 2127 2245 2145 2145 2264 2146 2146 2265 2127 2127 2245 2146 2146 2265 2128 2128 2246 2128 2128 2246 2146 2146 2265 2147 2147 2266 2128 2128 2246 2147 2147 2266 2129 2129 2247 2129 2129 2247 2147 2147 2266 2148 2148 2267 2129 2129 2247 2148 2148 2267 2130 2130 2248 2130 2130 2248 2148 2148 2267 2149 2149 2268 2130 2130 2248 2149 2149 2268 2131 2131 2249 2131 2131 2249 2149 2149 2268 2150 2150 2269 2131 2131 2249 2150 2150 2269 2132 2132 2250 2132 2132 2250 2150 2150 2269 2151 2151 2270 2132 2132 2250 2151 2151 2270 2133 2133 2251 2133 2133 2251 2151 2151 2270 2152 2152 2271 2133 2133 2251 2152 2152 2271 2134 2134 2252 2134 2134 2252 2152 2152 2271 2153 2153 2272 2134 2134 2252 2153 2153 2272 2135 2135 2253 2135 2135 2253 2153 2153 2272 2154 2154 2273 2135 2135 2253 2154 2154 2273 2136 2136 2254 2136 2136 2254 2154 2154 2273 2155 2155 2274 2136 2136 2254 2155 2155 2274 2137 2137 2255 2137 2137 2255 2155 2155 2274 2156 2156 2275 2137 2137 2255 2156 2156 2275 2138 2138 2256 2138 2138 2256 2156 2156 2275 2157 2157 2276 2138 2138 2256 2157 2157 2276 2139 2139 2257 2139 2139 2257 2157 2157 2276 2158 2158 2277 2139 2139 2257 2158 2158 2277 2140 2140 2258 2140 2140 2258 2158 2158 2277 2159 2159 2278 2140 2140 2258 2159 2159 2278 2141 2141 2259 2141 2141 2259 2159 2159 2278 2142 2142 2279 2141 2141 2259 2142 2142 2279 2124 2124 2260 2142 2142 2261 0 0 2280 1 3 2281 2142 2142 2261 1 3 2281 2143 2143 2262 2143 2143 2262 1 3 2281 2 5 2282 2143 2143 2262 2 5 2282 2144 2144 2263 2144 2144 2263 2 5 2282 3 7 2283 2144 2144 2263 3 7 2283 2145 2145 2264 2145 2145 2264 3 7 2283 4 9 2284 2145 2145 2264 4 9 2284 2146 2146 2265 2146 2146 2265 4 9 2284 5 11 2285 2146 2146 2265 5 11 2285 2147 2147 2266 2147 2147 2266 5 11 2285 6 13 2286 2147 2147 2266 6 13 2286 2148 2148 2267 2148 2148 2267 6 13 2286 7 15 2287 2148 2148 2267 7 15 2287 2149 2149 2268 2149 2149 2268 7 15 2287 8 17 2288 2149 2149 2268 8 17 2288 2150 2150 2269 2150 2150 2269 8 17 2288 9 19 2289 2150 2150 2269 9 19 2289 2151 2151 2270 2151 2151 2270 9 19 2289 10 21 2290 2151 2151 2270 10 21 2290 2152 2152 2271 2152 2152 2271 10 21 2290 11 23 2291 2152 2152 2271 11 23 2291 2153 2153 2272 2153 2153 2272 11 23 2291 12 25 2292 2153 2153 2272 12 25 2292 2154 2154 2273 2154 2154 2273 12 25 2292 13 27 2293 2154 2154 2273 13 27 2293 2155 2155 2274 2155 2155 2274 13 27 2293 14 29 2294 2155 2155 2274 14 29 2294 2156 2156 2275 2156 2156 2275 14 29 2294 15 31 2295 2156 2156 2275 15 31 2295 2157 2157 2276 2157 2157 2276 15 31 2295 16 33 2296 2157 2157 2276 16 33 2296 2158 2158 2277 2158 2158 2277 16 33 2296 17 35 2297 2158 2158 2277 17 35 2297 2159 2159 2278 2159 2159 2278 17 35 2297 0 0 2298 2159 2159 2278 0 0 2298 2142 2142 2279</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-4_max" name="Torus_Knot-4_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-4_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-5.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-5.DAE
new file mode 100644
index 00000000..a3556457
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-5.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-5.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:25:38Z</created>
+ <modified>2008-10-31T16:25:39Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="5400">25.402811 -0.001964 20.051733 28.341026 -4.492561 23.710152 29.775038 -7.779380 27.105207 29.320608 -8.981721 29.327200 27.099499 -7.777417 29.780748 23.706856 -4.489160 28.344322 20.051735 0.001962 25.402813 17.113520 4.492559 21.744394 15.679505 7.779379 18.349339 16.133934 8.981721 16.127346 18.355042 7.777419 15.673796 21.747684 4.489165 17.110220 26.109631 2.317777 20.773033 30.274225 -1.654639 23.782789 32.761864 -4.643335 26.826693 32.905983 -5.847491 29.089127 30.667965 -4.944455 29.963879 26.647491 -2.176195 29.216558 21.921839 1.715536 27.047407 17.757244 5.687953 24.037651 15.269605 8.676649 20.993750 15.125484 9.880806 18.731312 17.363497 8.977772 17.856560 21.383970 6.209514 18.603878 26.590143 4.695649 21.299910 31.773573 1.393926 23.400686 35.213028 -1.136284 25.881447 35.986912 -2.217014 28.077467 33.887859 -1.558683 29.400328 29.478313 0.662310 29.495569 23.939808 3.850851 28.337673 18.756378 7.152574 26.236893 15.316922 9.682784 23.756138 14.543036 10.763515 21.560116 16.642086 10.105186 20.237253 21.051628 7.884194 20.142012 26.837536 7.118128 21.629726 32.719040 4.518121 22.541035 36.917255 2.526287 24.212429 38.307274 1.676334 26.196064 36.516644 2.196007 27.960423 32.025162 3.946060 29.032749 26.036318 6.457568 29.125713 20.154816 9.057574 28.214407 15.956600 11.049410 26.543011 14.566577 11.899363 24.559378 16.357204 11.379691 22.795019 20.848682 9.629639 21.722691 26.868868 9.602695 21.766201 33.013447 7.561789 21.254898 37.675564 6.058935 21.881071 39.606007 5.496825 23.476944 38.287514 6.026074 25.614899 34.073376 7.504870 27.722075 28.092770 9.536971 29.233854 21.948191 11.577878 29.745159 17.286074 13.080730 29.118986 15.355631 13.642842 27.523117 16.674120 13.113594 25.385162 20.888254 11.634800 23.277985 26.722904 12.218230 21.688616 32.625465 10.409576 19.670908 37.377594 9.191654 19.105307 39.705967 8.890807 20.143360 38.986694 9.587646 22.506927 35.412506 11.095451 25.562687 29.941103 13.010211 28.491856 24.038544 14.818865 30.509563 19.286413 16.036785 31.075169 16.958038 16.337635 30.037115 17.677309 15.640798 27.673550 21.251493 14.132992 24.617790 26.435047 15.072664 21.311808 31.606880 13.056353 17.939981 36.056721 11.800577 16.205645 38.592239 11.641821 16.573513 38.534042 12.622623 18.945015 35.897728 14.480178 22.684708 31.389692 16.716755 26.790546 26.217859 18.733065 30.162373 21.768019 19.988842 31.896711 19.232500 20.147598 31.528847 19.290691 19.166798 29.157345 21.927006 17.309244 25.417654 26.003407 18.257013 20.476034 30.060545 15.616446 16.145950 33.869301 13.977969 13.463646 36.409122 13.780613 13.147843 36.999470 15.077258 15.283163 35.482155 17.520470 19.297443 32.263744 20.455589 24.115065 28.206608 23.096157 28.445150 24.397852 24.734634 31.127455 21.858028 24.931992 31.443260 21.267681 23.635347 29.307945 22.784994 21.192139 25.293665 25.375786 21.784838 18.986000 28.085573 18.252457 14.257160 31.014721 15.967852 11.003447 33.378368 15.543182 10.096685 34.543175 17.092236 11.779850 34.197033 20.199945 15.601929 32.432693 24.033606 20.538805 29.722908 27.565985 25.267645 26.793760 29.850590 28.521358 24.430115 30.275263 29.428120 23.265305 28.726210 27.744961 23.611444 25.618502 23.922882 24.466114 25.561783 16.678802 25.745634 21.079248 12.156382 27.667189 18.029602 8.780991 29.715900 17.229994 7.457061 31.342819 18.894682 8.539343 32.112015 22.577608 11.737837 31.817379 27.291941 16.195509 30.537861 31.774475 20.717930 28.616306 34.824123 24.093323 26.567595 35.623734 25.417252 24.940674 33.959049 24.334972 24.171480 30.276121 21.136482 23.187120 29.400393 13.479635 23.076649 24.107861 9.716724 23.960594 20.327387 6.665060 25.602104 19.071951 5.142332 27.561338 20.677940 5.556555 29.313320 24.715033 7.796739 30.388609 30.101492 11.262627 30.499081 35.394024 15.025537 29.615135 39.174496 18.077202 27.973627 40.429932 19.599930 26.014393 38.823948 19.185707 24.262411 34.786858 16.945528 21.479961 33.058830 9.426601 20.111931 27.251205 6.860952 20.006815 22.905182 4.518513 21.192778 21.185278 3.026938 23.352043 22.552338 2.785894 25.906036 26.640059 3.859969 28.170418 32.353138 5.961364 29.538448 38.160767 8.527013 29.643564 42.506790 10.869452 28.457602 44.226692 12.361028 26.298338 42.859638 12.602072 23.744345 38.771923 11.528000 19.333717 36.282551 4.669895 16.906075 30.355764 3.591790 15.920904 25.706236 2.251144 16.642185 23.579813 1.007181 18.876648 24.546257 0.193220 22.025572 28.346621 0.027361 25.245205 33.962593 0.554046 27.672848 39.889381 1.632150 28.658018 44.538906 2.972796 27.936739 46.665333 4.216760 25.702276 45.698891 5.030721 22.553354 41.898533 5.196580 16.789354 38.844505 -0.554875 13.542306 33.245373 -0.017335 11.830606 28.615986 -0.175027 12.112906 26.196791 -0.985696 14.313560 26.636009 -2.232126 17.842907 29.815950 -3.580335 21.755260 34.884548 -4.669073 25.002310 40.483685 -5.206614 26.714010 45.113068 -5.048923 26.431713 47.532265 -4.238253 24.231060 47.093052 -2.991824 20.701714 43.913113 -1.643615 13.932156 40.573097 -5.963187 10.124010 35.754292 -3.851384 7.866651 31.497627 -2.769203 7.764933 28.943674 -3.006614 9.846113 28.776764 -4.500003 13.552540 31.041620 -6.849216 17.891081 35.131374 -9.424785 21.699224 39.950184 -11.536588 23.956585 44.206848 -12.618770 24.058304 46.760799 -12.381360 21.977127 46.927711 -10.887973 18.270702 44.662857 -8.538760 10.871604 41.367943 -11.266026 6.752348 37.743828 -7.790380 4.138643 34.208302 -5.542143 3.730829 31.708702 -5.123727 5.638179 30.914799 -6.647246 9.349620 32.039314 -9.704475 13.870674 34.780933 -13.476232 17.989929 38.405048 -16.951876 20.603636 41.940575 -19.200113 21.011452 44.440178 -19.618532 19.104103 45.234085 -18.095015 15.392665 44.109570 -15.037787 7.722597 41.199650 -16.199976 3.500520 39.099487 -11.733885 0.702578 36.593494 -8.528030 0.078476 34.353146 -7.441421 1.795445 32.978745 -8.765211 5.393421 32.838558 -12.144692 9.908330 33.970150 -16.674335 14.130406 36.070313 -21.140429 16.928349 38.576305 -24.346281 17.552452 40.816650 -25.432894 15.835486 42.191055 -24.109104 12.237513 42.331242 -20.729626 4.591222 40.101845 -20.544132 0.396558 39.715946 -15.600605 -2.460694 38.464703 -11.772226 -3.214933 36.683376 -10.084806 -1.664063 34.849277 -10.990488 1.776361 33.453850 -14.246597 6.184481 32.870995 -18.980659 10.379145 33.256893 -23.924183 13.236396 34.508137 -27.752563 13.990639 36.289459 -29.439983 12.439771 38.123562 -28.534304 8.999349 39.518990 -25.278200 1.575475 38.164669 -24.120239 -2.569902 39.487297 -19.298508 -5.438187 39.583069 -15.279833 -6.260827 38.426308 -13.141012 -4.817393 36.326973 -13.455143 -1.494656 33.847580 -16.138054 2.817062 31.652479 -20.470860 6.962438 30.329845 -25.292587 9.830725 30.234081 -29.311264 10.653365 31.390839 -31.450085 9.209934 33.490173 -31.135956 5.887199 35.969566 -28.453051 -1.225904 35.536892 -26.794321 -5.414059 38.324150 -22.686632 -8.336660 39.681118 -18.944571 -9.210603 39.244186 -16.570820 -7.801711 37.130432 -16.201424 -4.487498 33.906239 -17.935360 -0.156005 30.435522 -21.308025 4.032149 27.648260 -25.415712 6.954752 26.291294 -29.157776 7.828695 26.728226 -31.531528 6.419806 28.841976 -31.900927 3.105595 32.066170 -30.166992 -3.711886 32.427948 -28.493917 -8.105902 36.207989 -25.563644 -11.196574 38.550583 -22.506523 -12.155759 38.828026 -20.141705 -10.726444 36.965984 -19.102840 -7.291615 33.463387 -19.668295 -2.771629 29.258755 -21.686552 1.622386 25.478714 -24.616823 4.713058 23.136120 -27.673944 5.672245 22.858673 -30.038765 4.242933 24.720715 -31.077629 0.808106 28.223309 -30.512177 -5.794844 29.090782 -29.234079 -10.547544 33.250481 -27.720360 -13.935078 36.159801 -25.611700 -15.049763 37.039200 -23.473120 -13.592916 35.653034 -21.877649 -9.954902 32.372734 -21.252792 -5.110521 28.077248 -21.765978 -0.357823 23.917551 -23.279699 3.029713 21.008228 -25.388355 4.144399 20.128830 -27.526936 2.687556 21.514992 -29.122406 -0.950457 24.795292 -29.747265 -7.432318 25.771303 -29.124788 -12.605531 29.696995 -29.027802 -16.367849 32.709511 -27.952780 -17.711166 34.001652 -26.187773 -16.275537 33.227192 -24.205713 -12.445641 30.593645 -22.537691 -7.247694 26.806665 -21.630653 -2.074482 22.880976 -21.727642 1.687838 19.868458 -22.802662 3.031156 18.576313 -24.567669 1.595530 19.350773 -26.549728 -2.234364 21.984320 -28.217749 -8.640265 22.653700 -28.336487 -14.175543 25.850018 -29.488377 -18.305746 28.555113 -29.389053 -19.924191 30.044159 -28.065136 -18.597216 29.918163 -25.871359 -14.680384 28.210888 -23.395552 -9.223207 25.379797 -21.301102 -3.687932 22.183479 -20.149212 0.442272 19.478384 -20.248533 2.060719 17.989340 -21.572453 0.733747 18.115334 -23.766226 -3.183082 19.822605 -26.242033 -9.479653 19.839638 -27.046637 -15.217759 21.980869 -29.208086 -19.627808 24.075396 -29.949976 -21.528131 25.561996 -29.073519 -20.409540 26.042330 -26.813560 -16.571758 25.387697 -23.775658 -11.043117 23.773506 -20.773811 -5.305011 21.632277 -18.612362 -0.894962 19.537748 -17.870472 1.005364 18.051149 -18.746927 -0.113225 17.570812 -21.006882 -3.951005 18.225445 -24.044785 -10.027859 17.364170 -25.402821 -15.749867 18.279701 -28.335911 -20.296587 19.571089 -29.766172 -22.449730 20.892300 -29.310368 -21.632360 21.889322 -27.090630 -18.063494 22.295004 -23.701736 -12.699406 22.000641 -20.051739 -6.977398 21.085110 -17.118650 -2.430678 19.793722 -15.688387 -0.277534 18.472511 -16.144190 -1.094900 17.475489 -18.363924 -4.663764 17.069809 -21.752817 -10.360723 15.224617 -23.512394 -15.819410 14.861465 -27.012888 -20.327477 15.247266 -28.991392 -22.676991 16.278648 -28.917768 -22.238400 17.679253 -26.811749 -19.129227 19.073786 -23.237635 -14.182570 20.088589 -19.153109 -8.723886 20.451742 -15.652616 -4.215818 20.065941 -13.674110 -1.866305 19.034559 -13.747730 -2.304892 17.633955 -15.853749 -5.414062 16.239422 -19.427862 -10.548304 13.401569 -21.448816 -15.487481 11.791653 -25.346930 -19.764320 11.237866 -27.752743 -22.232851 11.888598 -28.021618 -22.231627 13.569482 -26.081514 -19.760979 15.830130 -22.452280 -15.482915 18.064800 -18.106361 -10.543739 19.674717 -14.208248 -6.266898 20.228504 -11.802435 -3.798368 19.577774 -11.533556 -3.799590 17.896889 -13.473657 -6.270235 15.636243 -17.102892 -10.654281 11.870151 -19.262699 -14.819475 9.112339 -23.413387 -18.663824 7.640168 -26.140966 -21.157238 7.848103 -26.714577 -21.631609 9.680428 -24.980524 -19.959827 12.646173 -21.403448 -16.589849 15.950668 -16.941820 -12.424656 18.708479 -12.791130 -8.580307 20.180653 -10.063553 -6.086892 19.972717 -9.489939 -5.612521 18.140396 -11.223989 -7.284298 15.174651 -14.801065 -10.739265 10.600572 -16.991253 -13.889677 6.855608 -21.261232 -17.100143 4.538042 -24.212126 -19.510424 4.268860 -25.053242 -20.474684 6.120191 -23.559202 -19.734550 9.595974 -20.130335 -17.488344 13.764873 -15.685405 -14.337933 17.509836 -11.415422 -11.127466 19.827404 -8.464530 -8.717186 20.096588 -7.623414 -7.752925 18.245258 -9.117451 -8.493055 14.769478 -12.546314 -10.860299 9.556005 -14.664935 -12.785354 5.045298 -18.922901 -15.172533 2.007474 -21.998447 -17.382195 1.256515 -23.067482 -18.822262 2.993636 -21.843559 -19.106869 6.753381 -18.654625 -18.159756 11.528328 -14.355155 -16.234703 16.039034 -10.097188 -13.847525 19.076859 -7.021641 -11.637863 19.827820 -5.952606 -10.197796 18.090700 -7.176528 -9.913187 14.330957 -10.365459 -11.067928 8.690038 -12.311372 -11.608091 3.691750 -16.423300 -13.010669 0.110273 -19.520361 -14.899839 -1.094737 -20.772703 -16.769403 0.399597 -19.844759 -18.118410 4.192871 -16.985174 -18.585396 9.268681 -12.960171 -18.045233 14.266968 -8.848244 -16.642656 17.848444 -5.751182 -14.753487 19.053455 -4.498839 -12.883924 17.559124 -5.426780 -11.534915 13.765854 -8.286363 -11.401760 7.945922 -9.955572 -10.468793 2.784595 -13.786090 -10.770514 -1.117487 -16.797520 -12.226078 -2.714766 -18.182949 -14.445468 -1.579249 -17.571156 -16.834000 1.984799 -15.126066 -18.751669 7.022396 -11.502845 -19.684637 12.183722 -7.672328 -19.382915 16.085806 -4.660899 -17.927353 17.683086 -3.275468 -15.707964 16.547571 -3.887261 -13.319432 12.983526 -6.332346 -11.886127 7.259474 -7.621522 -9.480241 2.287420 -11.038095 -8.625885 -1.677503 -13.855087 -9.551985 -3.572897 -15.317690 -12.010392 -2.890892 -15.033997 -15.342379 0.185769 -13.080025 -18.655142 4.832696 -9.979340 -21.061028 9.804750 -6.562767 -21.915384 13.769673 -3.745774 -20.989286 15.665068 -2.283172 -18.530880 14.983065 -2.566863 -15.198895 11.906407 -4.520833 -12.526372 6.561398 -5.331154 -8.748269 2.130716 -8.208234 -6.756948 -1.623702 -10.723184 -7.085982 -3.695863 -12.202126 -9.647206 -3.530531 -12.248777 -13.754342 -1.172009 -10.850641 -18.306887 2.747739 -8.382343 -22.084990 7.178421 -5.505265 -24.076311 10.932838 -2.990315 -23.747278 13.005001 -1.511372 -21.186056 12.839671 -1.464718 -17.078922 10.481152 -2.862854 -13.308053 5.785397 -3.103840 -8.357424 2.220315 -5.331854 -5.326253 -1.055709 -7.445065 -5.026742 -3.164868 -8.877239 -7.539145 -3.542013 -9.244629 -12.190265 -2.086090 -8.448790 -17.733835 0.812788 -6.702968 -22.684465 4.377869 -4.474955 -25.715637 7.653893 -2.361744 -26.015150 9.763052 -0.929569 -23.502750 10.140199 -0.562179 -18.851633 8.684278 -1.358016 -14.197878 4.872149 -0.954799 -8.363507 2.439337 -2.446151 -4.464954 -0.119436 -4.070942 -3.546832 -2.118548 -5.393810 -5.855152 -3.022339 -6.060295 -10.771399 -2.588639 -5.891812 -16.978271 -0.933658 -4.933507 -22.812641 1.499154 -3.442156 -26.711197 4.057927 -1.817365 -27.629320 6.057039 -0.494496 -25.321005 6.960832 0.171989 -20.404758 6.527133 0.003507 -15.146792 3.775322 1.104918 -8.786503 2.657969 0.411492 -4.257493 1.003848 -0.655247 -2.773304 -0.743820 -1.809467 -4.731626 -2.116749 -2.741894 -9.607727 -2.747063 -3.202688 -16.095058 -2.465871 -3.068377 -22.455347 -1.348518 -2.374952 -26.984358 0.305602 -1.308213 -28.468548 2.053270 -0.153994 -26.510229 3.426199 0.778434 -21.634132 4.056515 1.239228 -16.095030 2.465796 3.068498 -9.607704 2.747619 3.201771 -4.731616 2.117795 2.740173 -2.773311 0.745084 1.807390 -4.257514 -1.002696 0.653360 -8.786533 -2.657230 -0.412695 -15.146823 -3.775186 -1.105127 -21.634148 -4.057010 -1.238400 -26.510237 -3.427186 -0.776803 -28.468544 -2.054476 0.155980 -26.984346 -0.306696 1.310009 -22.455330 1.347838 2.376065 -16.978266 0.933514 4.933714 -10.771432 2.589532 5.890478 -5.855214 3.024037 6.057761 -3.546908 2.120605 5.390742 -4.465024 0.121309 4.068148 -8.363552 -2.438142 2.444366 -14.197886 -4.871943 0.954488 -20.404718 -6.527962 -0.002275 -25.320938 -6.962468 -0.169559 -27.629246 -6.059037 0.497459 -26.711132 -4.059742 1.820053 -22.812607 -1.500292 3.443834 -17.733753 -0.813053 6.703437 -12.190145 2.086288 8.448377 -7.539022 3.542628 9.243432 -5.026650 3.165744 8.875568 -5.326217 1.056620 7.443355 -8.357452 -2.219604 5.330552 -13.308140 -5.785069 3.103283 -18.851748 -8.684409 1.358343 -23.502871 -10.140751 0.563287 -26.015244 -9.763867 0.931150 -25.715681 -7.654747 2.363362 -22.684448 -4.378523 4.476164 -18.306555 -2.748142 8.383480 -13.753493 1.171216 10.851444 -9.646070 3.529568 12.249022 -7.084864 3.694996 12.201733 -6.756148 1.623174 10.722247 -8.748003 -2.130756 8.206993 -12.526711 -6.560930 5.329931 -17.079771 -10.480288 2.861966 -21.187195 -12.838642 1.464388 -23.748404 -13.004072 1.511676 -24.077120 -10.932251 2.991160 -22.085268 -7.178324 5.506413 -18.654736 -4.833069 9.980888 -15.340923 -0.186953 13.081670 -12.008278 2.889222 15.035285 -9.549780 3.571198 15.318262 -8.624181 1.676239 13.854782 -9.479495 -2.287901 11.036979 -11.886541 -7.259034 7.619884 -15.200353 -11.905150 4.519102 -18.532997 -14.981326 2.565486 -20.991495 -15.663302 2.282507 -21.917095 -13.768347 3.745986 -21.061783 -9.804209 6.563788 -18.751245 -7.022285 11.504793 -16.831230 -1.986538 15.129347 -14.441096 1.576134 17.574875 -12.221277 2.711117 18.186100 -10.766572 1.114293 16.799246 -10.466767 -2.786469 13.785919 -11.402196 -7.945965 9.953536 -13.322208 -12.981710 6.328983 -15.712342 -16.544384 3.883454 -17.932161 -17.679369 3.272228 -19.386868 -16.082548 4.659080 -19.686674 -12.181787 7.672405 -18.585236 -9.268423 12.962265 -18.115314 -4.194484 16.989286 -16.764204 -0.402639 19.849775 -14.893933 1.091090 20.777266 -13.005638 -0.113541 19.523235 -11.605288 -3.693750 16.423704 -11.068104 -8.690224 12.309187 -11.538023 -13.764162 8.282166 -12.889133 -17.556007 5.421675 -14.759404 -19.049740 4.494184 -16.647699 -17.845112 5.748212 -18.048050 -14.264904 8.847742 -18.159994 -11.527770 14.357186 -19.103519 -6.754763 18.659599 -18.816227 -2.996579 21.850130 -17.375092 -1.260217 23.073879 -15.166269 -2.010937 22.002945 -12.781610 -5.047583 18.924284 -10.860080 -9.556488 14.662820 -9.916553 -14.329494 10.360408 -10.203846 -18.087679 7.169876 -11.644979 -19.824043 5.946124 -13.853801 -19.073324 7.017056 -16.238461 -16.036682 10.095716 -17.489130 -13.764050 15.687484 -19.730864 -9.597326 20.136715 -20.467512 -6.123348 23.568157 -19.501694 -4.272964 25.062363 -17.092196 -4.541981 24.218960 -13.884644 -6.858319 21.263933 -10.738498 -10.601315 16.989086 -8.496764 -14.768037 12.539859 -7.760114 -18.242016 9.108416 -8.725931 -20.092402 7.614209 -11.135427 -19.823387 8.457611 -14.342978 -17.507050 11.412632 -16.591137 -15.949826 16.943634 -19.956408 -12.647753 21.410606 -21.624397 -9.683994 24.991100 -21.148174 -7.852691 26.725723 -18.655338 -7.644536 26.149683 -14.813845 -9.115305 23.417334 -10.653018 -11.870909 19.260801 -7.287748 -15.172981 14.793828 -5.619756 -18.136740 11.213335 -6.095979 -19.968044 9.478711 -8.588812 -20.176201 10.054749 -12.430305 -18.705433 12.787096 -15.484949 -18.063625 18.107731 -19.757801 -15.831770 22.460217 -22.224091 -13.573486 26.093885 -22.222980 -11.893883 28.035101 -19.754765 -11.243008 27.763712 -15.480802 -11.795260 25.352440 -10.546297 -13.402666 21.447382 -6.273445 -15.634521 17.094896 -3.807153 -17.892803 13.461226 -3.808263 -19.572407 11.520012 -6.276475 -20.223284 11.791399 -10.550436 -19.671032 14.202669 -14.185494 -20.086981 19.153881 -19.126413 -19.075798 23.246241 -22.230606 -17.684332 26.825878 -22.666307 -16.285427 28.933628 -20.316772 -15.253921 29.004723 -15.811557 -14.866200 27.020113 -10.357829 -15.226156 23.511572 -5.416911 -16.237339 19.419210 -2.312716 -17.628803 15.839577 -1.877012 -19.027708 13.731824 -4.226544 -20.059216 13.660728 -8.731758 -20.446938 15.645336 -12.703307 -21.998373 20.051727 -18.061245 -22.297537 23.710360 -21.624565 -21.895971 27.105574 -22.438482 -20.901274 29.327621 -20.284904 -19.579971 29.781107 -15.740885 -18.286112 28.344522 -10.023987 -17.366377 25.402796 -4.666050 -17.067213 21.744164 -1.102728 -17.468779 18.348951 -0.288810 -18.463476 16.126902 -2.442384 -19.784775 15.673413 -6.986402 -21.078638 17.109997 -11.047631 -23.770456 20.773027 -16.570154 -25.390785 23.782824 -20.402250 -26.050716 26.826752 -21.517115 -25.573427 29.089195 -19.616018 -24.086805 29.963934 -15.208361 -21.989189 29.216581 -9.475169 -19.842634 27.047394 -3.952647 -18.222309 24.037598 -0.120549 -17.562374 20.993668 0.994317 -18.039661 18.731224 -0.906776 -19.526283 17.856483 -5.314432 -21.623898 18.603836 -9.228685 -25.375456 21.299881 -14.679664 -28.213661 23.400835 -18.590494 -29.927303 25.881729 -19.913271 -30.057209 28.077808 -18.293558 -28.568571 29.400635 -14.165359 -25.860270 29.495758 -8.634819 -22.657991 28.337694 -3.183841 -19.819786 26.236740 0.726989 -18.106146 23.755846 2.049769 -17.976240 21.559767 0.430060 -19.464874 20.236940 -3.698137 -22.173176 20.141813 -7.254162 -26.801058 21.629728 -12.446452 -30.594801 22.540899 -16.270477 -33.234798 24.212194 -17.701593 -34.013668 26.195789 -16.356335 -32.722710 27.960184 -12.595161 -29.707836 29.032608 -7.425878 -25.776880 29.125706 -2.233589 -21.983137 28.214535 1.590437 -19.343140 26.543243 3.021555 -18.564270 24.559647 1.676299 -19.855227 22.795256 -2.084871 -22.870098 21.722832 -5.118119 -28.070484 21.766214 -9.957692 -32.371593 21.254734 -13.590154 -35.657818 21.880781 -15.042190 -37.048618 23.476601 -13.924726 -36.171337 25.614597 -10.537189 -33.261032 27.721895 -5.787266 -29.097523 29.233847 -0.947694 -24.796417 29.745327 2.684768 -21.510193 29.119282 4.136805 -20.119387 27.523464 3.019345 -20.996668 25.385468 -0.368190 -23.906971 23.278168 -2.780457 -29.251665 21.688658 -7.298279 -33.458988 19.671156 -10.729159 -36.965450 19.105692 -12.153799 -38.831501 20.143784 -11.190466 -38.557133 22.507275 -8.097284 -36.215862 25.562870 -3.703070 -32.435032 28.491823 0.814752 -28.227709 30.509327 4.245634 -24.721247 31.074787 5.670275 -22.855194 30.036697 4.706944 -23.129560 27.673208 1.613764 -25.470829 24.617615 -0.164771 -30.429401 21.312035 -4.497156 -33.900047 17.940439 -7.809670 -37.125832 16.206213 -9.214731 -39.242409 16.574036 -8.335852 -39.682640 18.945354 -5.408527 -38.328571 22.684772 -1.217134 -35.543018 26.790316 3.115250 -32.072372 30.161911 6.427765 -28.846592 31.896141 7.832827 -26.730011 31.528316 6.953949 -26.289780 29.157001 4.026628 -27.643848 25.417587 2.809471 -31.648178 20.475967 -1.505638 -33.841583 16.145679 -4.828821 -36.320892 13.463242 -6.269635 -38.421768 13.147408 -5.442012 -39.581287 15.282806 -2.567717 -39.488762 19.297260 1.583087 -38.168976 24.115101 5.898195 -35.975571 28.445387 9.221378 -33.496265 31.127827 10.662193 -31.395386 31.443663 9.834574 -30.235863 29.308264 6.960280 -30.328394 25.293812 6.178480 -32.868546 18.985903 1.765152 -33.449333 14.256441 -1.677471 -34.843906 11.002291 -3.226941 -36.678593 10.095398 -2.468078 -38.461784 11.778766 0.395780 -39.715687 15.601336 4.597265 -40.104309 20.538851 9.010592 -39.523521 25.268312 12.453217 -38.128944 28.522465 14.002687 -36.294262 29.429359 13.243827 -34.511066 27.745995 10.379971 -33.257172 23.923428 9.904259 -33.969204 16.678650 5.382362 -32.835983 12.156388 1.780372 -32.975231 8.781146 0.063437 -34.349636 7.457318 0.691609 -36.590931 8.539623 3.496570 -39.098557 11.738056 7.726731 -41.200600 16.195601 12.248627 -42.333824 20.717863 15.850617 -42.194576 24.093105 17.567554 -40.820171 25.416935 16.939384 -38.578880 24.334633 14.134426 -36.071251 21.136200 13.868072 -34.780842 13.479478 9.339577 -32.038872 9.716912 5.623398 -30.914124 6.665528 3.715282 -31.707979 5.142942 4.126509 -34.207726 5.557129 6.746888 -37.743553 7.797108 10.874292 -41.368042 11.262677 15.402786 -44.110016 15.025244 19.118965 -45.234764 18.076626 21.027082 -44.440910 19.599215 20.615858 -41.941170 19.185028 17.995481 -38.405342 16.945053 17.889669 -35.131638 9.426795 13.544307 -31.043039 6.860909 9.833279 -28.778955 4.518223 7.750950 -28.946053 3.026457 7.855279 -31.499548 2.785328 10.118312 -35.755241 3.859448 13.933669 -40.572823 5.961006 18.279030 -44.661423 8.526892 21.990059 -46.925503 10.869577 24.072390 -46.758408 12.361344 23.968061 -44.204918 12.602474 21.705030 -39.949223 11.528356 21.754723 -34.884800 4.669963 17.835808 -29.818989 3.591876 14.301817 -26.641022 2.251200 12.099681 -26.202427 1.007169 11.819460 -28.620728 0.193121 13.536239 -33.247944 0.027178 16.790009 -38.844212 0.553806 20.708921 -43.910019 1.631893 24.242912 -47.087990 2.972569 26.445049 -47.526585 4.216599 26.725271 -45.108288 5.030648 25.008495 -40.481075 5.196591 25.245764 -33.962196 -0.555068 22.020399 -28.350531 -0.017660 18.867144 -24.553417 -0.175423 16.630911 -23.588291 -0.986083 15.910896 -25.713753 -2.232425 16.900030 -30.360291 -3.580492 19.333271 -36.282864 -4.669072 22.558638 -41.894531 -5.206480 25.711893 -45.691647 -5.048718 27.948126 -46.656773 -4.238059 28.668140 -44.531315 -2.991717 27.679008 -39.884781 -1.643650 28.171301 -32.352131 -5.963292 25.902061 -26.644936 -3.851166 23.344290 -22.561781 -2.768756 21.183336 -21.196737 -3.006091 19.998230 -22.915575 -4.499578 20.106518 -27.257727 -6.849040 21.479185 -33.059719 -9.424937 23.748423 -38.766911 -11.537063 26.306194 -42.850071 -12.619474 28.467148 -44.215111 -12.382140 29.652254 -42.496281 -10.888654 29.543968 -38.154133 -8.539194 30.389921 -30.099024 -11.266131 29.310841 -24.719933 -7.789992 27.555742 -20.688875 -5.541398 25.594902 -19.085968 -5.122857 23.953728 -20.340710 -6.646518 23.071968 -24.116894 -9.704117 23.185892 -29.402695 -13.476373 24.264971 -34.781784 -16.952513 26.020069 -38.812843 -19.201107 27.980909 -40.415752 -19.619652 29.622084 -39.161011 -18.095989 30.503845 -35.384834 -15.038393 31.818678 -27.287685 -16.200123 32.110825 -22.581654 -11.733522 31.339468 -18.905918 -8.527286 29.711292 -17.245386 -7.440518 27.662565 -18.045000 -8.764421 25.742243 -21.090502 -12.144254 24.464872 -25.565849 -16.674393 24.172726 -30.271879 -21.140991 24.944082 -33.947617 -24.347229 26.572256 -35.608147 -25.433998 28.620983 -34.808537 -24.110098 30.541306 -31.763039 -20.730267 32.433605 -24.027002 -20.544174 34.196716 -20.201736 -15.600350 34.541718 -17.101913 -11.771766 33.376163 -15.558125 -10.084290 31.012367 -15.984027 -10.990076 28.083702 -18.265501 -14.246421 25.374905 -21.791227 -18.980789 23.611794 -25.616489 -23.924612 23.266792 -28.716312 -27.753195 24.432344 -30.260105 -29.440674 26.796141 -29.834206 -28.534889 29.724804 -27.552732 -25.278549 32.263760 -20.447496 -24.119892 35.482075 -17.517282 -19.299217 36.999313 -15.079802 -15.281425 36.408932 -13.788176 -13.143078 33.869125 -13.988494 -13.457142 30.060434 -15.627083 -16.139465 26.003391 -18.264883 -20.471323 22.785078 -21.195095 -25.291996 21.267839 -23.632578 -29.309788 21.858217 -24.924204 -31.448139 24.398022 -24.723886 -31.134075 28.206713 -23.085300 -28.451756 31.388742 -16.706089 -26.794590 35.896683 -14.473150 -22.686666 38.533176 -12.621086 -18.944376 38.591782 -11.646156 -16.570461 36.056789 -11.809593 -16.201015 31.607454 -13.067601 -17.935032 26.435970 -15.083100 -21.307875 21.928030 -17.316038 -25.415798 19.291534 -19.168102 -29.158091 19.232927 -20.143032 -31.532001 21.767916 -19.979597 -31.901451 26.217249 -18.721590 -30.167439 29.939316 -12.998945 -28.493992 35.409966 -11.083944 -25.563576 38.984074 -9.578951 -22.506332 39.703964 -8.887223 -20.141453 37.376736 -9.194112 -19.102604 32.625973 -10.417385 -19.668140 26.724638 -12.229267 -21.686531 21.253986 -14.144267 -24.616947 17.679878 -15.649261 -27.674187 16.959990 -16.340988 -30.039066 19.287212 -16.034101 -31.077919 24.037973 -14.810829 -30.512384 28.090731 -9.527630 -29.234091 34.069523 -7.491283 -27.720837 38.282864 -6.011853 -25.612516 39.601799 -5.485751 -23.474058 37.672916 -6.053946 -21.878456 33.013062 -7.564189 -21.253252 26.870834 -9.611813 -21.765968 20.892044 -11.648159 -23.279222 16.678699 -13.127589 -25.387543 15.359763 -13.653691 -27.526001 17.288643 -13.085499 -29.121603 21.948496 -11.575256 -29.746809 26.034605 -6.448629 -29.124739 32.020847 -3.931074 -29.027668 36.510868 -2.178961 -27.952599 38.301575 -1.661767 -26.187588 36.913147 -2.518074 -24.205572 32.717613 -4.518434 -22.537630 26.839161 -7.126853 -21.630688 20.852921 -9.644407 -21.727757 16.362898 -11.396521 -22.802826 14.572188 -11.913717 -24.567837 15.960614 -11.057411 -26.549850 20.156145 -9.057052 -28.217793 23.938696 -3.843793 -28.336401 29.474363 -0.648087 -29.488121 33.882111 1.576286 -29.388689 35.980892 2.233309 -28.064747 35.208340 1.146931 -25.871048 31.771454 -1.391752 -23.395386 26.591150 -4.702503 -21.301119 21.055487 -7.898208 -20.149401 16.647736 -10.122582 -20.248833 14.548953 -10.779605 -21.572769 15.321505 -9.693229 -23.766472 18.758387 -7.154548 -26.242130 21.921354 -1.710054 -27.046553 26.644672 2.188814 -29.207958 30.663553 4.960855 -29.949825 32.901142 5.863304 -29.073372 32.757874 4.654348 -26.813442 30.272142 1.657929 -23.775583 26.109997 -2.323066 -20.773788 21.386679 -6.221934 -18.612381 17.367798 -8.993976 -17.870512 15.130210 -9.896425 -18.746964 15.273474 -8.687472 -21.006891 17.759203 -5.691055 -24.044750 20.051649 0.002206 -25.402727 23.705282 4.499954 -28.335953 27.096842 7.791968 -29.766319 29.317562 8.996155 -29.310564 29.772404 7.789854 -27.090803 28.339491 4.496292 -23.701822 25.402775 -0.002023 -20.051697 21.749142 -4.499771 -17.118469 18.357582 -7.791785 -15.688101 16.136862 -8.995974 -16.143856 15.682018 -7.789675 -18.363615 17.114927 -4.496115 -21.752596 18.365183 1.360642 -23.512337 20.779957 6.269974 -27.012325 23.368055 9.981406 -28.990452 25.436003 11.500464 -28.916685 26.429691 10.420115 -26.810787 26.082865 7.029840 -23.237032 24.488455 2.238061 -19.153006 22.073683 -2.671271 -15.653017 19.485582 -6.382704 -13.674888 17.417637 -7.901762 -13.748654 16.423946 -6.821416 -15.854549 16.770771 -3.431145 -19.428305 16.880165 2.434352 -21.448668 17.955462 7.516688 -25.346897 19.614246 11.497392 -27.752808 21.412048 13.309839 -28.021740 22.867147 12.468384 -26.081631 23.589653 9.198496 -22.452335 23.385969 4.376337 -18.106318 22.310671 -0.705998 -14.208090 20.651888 -4.686703 -11.802177 18.854086 -6.499151 -11.533245 17.398985 -5.657699 -13.473349 16.676479 -2.387813 -17.102644 15.606886 3.291848 -19.262466 15.301125 8.277704 -23.413410 15.948352 12.342949 -26.141207 17.375141 14.398301 -26.714947 19.199188 13.893033 -24.980892 20.931738 10.962529 -21.403687 22.108557 6.392017 -16.941839 22.414318 1.406162 -12.790895 21.767092 -2.659083 -10.063097 20.340302 -4.714437 -9.489359 18.516256 -4.209171 -11.223410 16.783707 -1.278671 -14.800612 14.549733 4.000581 -16.991295 12.881879 8.602078 -21.260612 12.480217 12.541622 -24.210976 13.452372 14.763613 -25.051842 15.537854 14.672670 -23.557898 18.177862 12.293163 -20.129446 20.665007 8.262678 -15.685136 22.332861 3.661181 -11.415819 22.734524 -0.278362 -8.465454 21.762371 -2.500354 -7.624588 19.676889 -2.409413 -9.118530 17.036882 -0.029909 -12.546980 13.705905 4.627270 -14.664737 10.761926 8.549539 -18.922832 9.324570 12.135666 -21.998493 9.778975 14.424753 -23.067593 12.003384 14.803440 -21.843672 15.401766 13.170259 -18.654676 19.063530 9.962818 -14.355097 22.007509 6.040551 -10.097002 23.444866 2.454423 -7.021342 22.990463 0.165335 -5.952239 20.766056 -0.213353 -7.176158 17.367674 1.419826 -10.365150 13.059866 5.240057 -12.310959 9.001230 8.206286 -16.423325 6.600764 11.211199 -19.520782 6.501670 13.449632 -20.773371 8.730501 14.321798 -19.845459 12.690042 13.594003 -16.985683 17.319338 11.461257 -12.960316 21.377974 8.495028 -8.847950 23.778440 5.490116 -5.750492 23.877537 3.251682 -4.497902 21.648708 2.379515 -5.425810 17.689169 3.107308 -8.285585 12.582497 5.901254 -9.955112 7.646270 7.672897 -13.786241 4.417812 9.884488 -16.798201 3.762185 11.943434 -18.183943 5.855063 13.298039 -17.572155 10.135661 13.585340 -15.126768 15.456996 12.728356 -11.503022 20.393221 10.956714 -7.671895 23.621679 8.745123 -4.659934 24.277309 6.686179 -3.274192 22.184435 5.331572 -3.885976 17.903839 5.044269 -6.331361 12.229935 6.664083 -7.621139 6.721097 7.066184 -11.037805 2.860199 8.308464 -13.854929 1.681766 10.058057 -15.317667 3.501559 11.846160 -15.034077 7.831964 13.193652 -13.080149 13.512653 13.739473 -9.979437 19.021492 13.337374 -6.562772 22.882389 12.095094 -3.745648 24.060823 10.345502 -2.282909 22.241034 8.557398 -2.566496 17.910631 7.209907 -4.520422 11.945438 7.567260 -5.331599 6.218821 6.511494 -8.208020 1.971385 6.664842 -10.722330 0.341226 7.986216 -12.200822 1.765147 10.121553 -12.247335 5.861607 12.498692 -10.849406 11.532963 14.480680 -8.381611 17.259581 15.536448 -5.505191 21.507017 15.383101 -2.990880 23.137177 14.061728 -1.512388 21.713259 11.926392 -1.465874 17.616802 9.549253 -2.863800 11.664304 8.632541 -3.103607 6.101654 6.127496 -5.331669 1.749015 5.140264 -7.444936 -0.227325 5.935371 -8.877159 0.702192 8.299772 -9.244575 4.288501 11.599923 -8.448735 9.570655 14.951554 -6.702885 15.133305 17.456598 -4.474823 19.485943 18.443832 -2.361556 21.462286 17.648726 -0.929333 20.532772 15.284327 -0.561916 16.946465 11.984177 -1.357755 11.318236 9.859839 -0.954442 6.294192 6.023428 -2.445586 2.128970 3.926456 -4.070277 -0.061361 4.130805 -5.393178 0.310095 6.581721 -6.059821 3.143807 10.622481 -5.891579 7.680485 15.170367 -4.933531 12.704528 19.006779 -3.442387 16.869751 21.103752 -1.817697 19.060083 20.899405 -0.494795 18.688629 18.448490 0.171848 15.854919 14.407734 0.003607 10.843217 11.229704 1.104430 6.695374 6.280223 0.411157 2.998222 3.185109 -0.655294 0.742409 2.773695 -1.809169 0.532379 5.156219 -2.741288 2.424409 9.694285 -3.201890 5.911531 15.171924 -3.067557 10.059374 20.121403 -2.374284 13.756526 23.216520 -1.307833 16.012339 23.627934 -0.153958 16.222370 21.245413 0.778161 14.330343 16.707350 1.238763 10.182849 12.705957 3.068739 7.183360 6.946803 3.202075 4.199954 3.038834 2.740507 2.032030 2.029188 1.807713 1.260483 4.188401 0.653634 2.092048 8.937910 -0.412494 4.303908 15.005091 -1.105005 7.303396 20.764246 -1.238341 10.286802 24.672216 -0.776774 12.454726 25.681864 0.156020 13.226274 23.522654 1.310098 12.394711 18.773146 2.376227 9.297220 14.237007 4.934320 7.627666 8.033859 5.891466 5.545704 3.559111 6.058918 3.609193 2.011767 5.391807 2.337022 3.806438 4.068887 2.070067 8.462241 2.444632 2.879858 14.731659 0.954260 4.549412 20.934807 -0.002886 6.631374 25.409555 -0.170338 8.567884 26.956900 0.496771 9.840056 25.162233 1.819691 10.107012 20.506433 3.443946 8.162380 15.764504 6.704077 7.901188 9.513987 8.449183 6.836711 4.757858 9.244239 5.254176 2.770519 8.876210 3.577620 4.084476 7.443709 2.256276 8.347655 5.330575 1.644197 14.417739 3.103019 1.905388 20.668255 1.357913 2.969864 25.424385 0.562857 4.552399 27.411726 0.930884 6.228955 26.097773 2.363384 7.550299 21.834597 4.476518 6.773128 17.228138 8.383730 7.890912 11.325433 10.851768 7.879649 6.589134 12.249382 6.742354 4.288327 12.202084 4.783767 5.039515 10.722545 2.528689 8.641417 8.207209 0.581366 14.128901 5.330056 -0.536418 20.031607 2.862019 -0.525155 24.767906 1.464404 0.612138 27.068714 1.511702 2.570724 26.317530 2.991238 4.825802 22.715631 5.506574 5.141623 18.572388 9.980562 7.509622 13.379736 13.080811 8.508274 8.955592 15.034172 7.869991 6.485401 15.317247 5.765802 6.631048 13.854184 2.759522 9.353509 11.037010 -0.343318 13.923300 7.620585 -2.711316 19.115950 4.520338 -3.709969 23.540096 2.566975 -3.071689 26.010286 2.283898 -0.967500 25.864643 3.746960 2.038778 23.142185 6.564132 3.294068 19.750237 11.504864 6.695037 15.569668 15.129619 8.585238 11.718484 17.575331 8.458193 9.228603 18.186670 6.347944 8.767189 16.799829 2.819931 10.457876 13.786413 -1.180519 13.847645 9.953862 -4.581488 18.028210 6.329107 -6.471690 21.879395 3.883396 -6.344646 24.369276 3.272055 -4.234400 24.830692 4.658894 -0.706387 23.140009 7.672307 1.265776 20.729544 12.962517 5.424775 17.785618 16.989750 8.032907 14.719606 19.850380 8.391321 12.353043 20.777905 6.403986 11.320047 19.523792 2.603403 11.897413 16.424082 -1.992063 13.930431 12.309340 -6.151062 16.874357 8.282107 -8.759193 19.940371 5.421477 -9.117611 22.306932 4.493952 -7.130277 23.339928 5.748063 -3.329697 22.762566 8.847770 -0.903977 21.491062 14.357032 3.702236 19.922453 18.658758 6.814059 17.795095 21.848883 7.597682 15.679014 23.072615 5.843132 14.141212 22.002054 2.020541 13.593740 18.924059 -2.845830 14.183295 14.663374 -7.452044 15.751904 10.361649 -10.563868 17.879261 7.171523 -11.347491 19.995342 5.947791 -9.592944 21.533144 7.018349 -5.770356 22.080616 10.096342 -3.175141 22.028080 15.687778 1.553559 21.885550 20.137684 4.929823 20.786114 23.569601 6.048988 19.024357 25.063950 4.611170 17.072346 24.220316 1.001634 15.453119 21.264755 -3.812447 14.600549 16.989206 -8.541146 14.743076 12.539300 -11.917412 15.842514 9.107382 -13.036577 17.604269 7.613035 -11.598763 19.556278 8.456665 -7.989229 21.175505 11.412224 -5.517528 22.343321 16.943861 -0.975492 23.606646 21.411135 2.424972 23.569248 24.991835 3.772715 22.241150 26.726521 2.706608 19.978218 26.150381 -0.487684 17.386803 23.417793 -4.954254 15.161269 19.260954 -9.496288 13.897945 14.793684 -12.896753 13.935342 11.212981 -14.244497 15.263435 9.478295 -13.178394 17.526367 10.054431 -9.984104 20.117783 12.787016 -7.901741 22.442051 18.107796 -3.832359 25.027128 22.459820 -0.643281 26.034344 26.093176 0.810983 25.193813 28.034313 0.140763 22.730762 27.763102 -2.474354 19.305157 25.352215 -6.333650 15.834890 21.447647 -10.403030 13.249812 17.095625 -13.592109 12.242596 13.462268 -15.046374 13.083122 11.521131 -14.376157 15.546173 11.792341 -11.761043 18.971777 14.203224 -10.303327 22.328459 19.153967 -6.957154 26.101942 23.246222 -4.200003 28.094622 26.825794 -2.770651 27.772554 28.933542 -3.052091 25.222042 29.004696 -4.968910 21.126493 27.020193 -8.007500 16.583305 23.511776 -11.353672 12.809821 19.419523 -14.110823 10.817143 15.839951 -15.540176 11.139207 13.732200 -15.258739 13.689715 13.661043 -13.341920 17.785263 15.645544 -12.699782 22.000496 20.051800 -10.279863 26.790319 23.710236 -8.150392 29.675587 27.105316 -6.881956 29.883190 29.327333 -6.814435 27.357502 29.780895 -7.965919 22.775280 28.344475 -10.027868 17.364325 25.402958 -12.447786 12.574500 21.744524 -14.577259 9.689232 18.349443 -15.845695 9.481627 16.127426 -15.913218 12.007313 15.673862 -14.761735 16.589533 17.110279 -15.062130 21.452772 20.773087 -13.704000 27.045567 23.782856 -12.359410 30.694214 26.826773 -11.388644 31.421061 29.089226 -11.051819 29.031349 29.963989 -11.439184 24.165403 29.216669 -12.446947 18.127045 27.047516 -13.805078 12.534251 24.037748 -15.149666 8.885602 20.993830 -16.120432 8.158752 18.731379 -16.457258 10.548460 17.856613 -16.069895 15.414406 18.603930 -17.361389 20.680130 21.299900 -17.093746 26.819849 23.401039 -16.622379 31.063461 25.882078 -16.073589 32.273891 28.078228 -15.594423 30.126804 29.401030 -15.313274 25.197514 29.496038 -15.305477 18.806818 28.337799 -15.573119 12.667097 26.236662 -16.044487 8.423487 23.755623 -16.593277 7.213055 21.559473 -17.072443 9.360137 20.236671 -17.353592 14.289426 20.141661 -19.583210 19.682846 21.629719 -20.272823 26.076334 22.540951 -20.647408 30.707993 24.212299 -20.606594 32.336773 26.195927 -20.161318 30.526245 27.960329 -19.430891 25.761541 29.032724 -18.611031 19.319357 29.125774 -17.921417 12.925870 28.214542 -17.546833 8.294210 26.543196 -17.587646 6.665427 24.559566 -18.032921 8.475950 22.795168 -18.763348 13.240652 21.722771 -21.751682 18.467169 21.766207 -23.056639 24.808901 21.254242 -24.086063 29.597927 21.879929 -24.564123 31.551035 23.475615 -24.362719 30.144888 25.613737 -23.535822 25.756264 27.721388 -22.304995 19.561090 29.233822 -21.000036 13.219358 29.745789 -19.970612 8.430329 29.120104 -19.492554 6.477221 27.524418 -19.693954 7.883365 25.386295 -20.520853 12.271986 23.278648 -23.942917 17.033522 21.688589 -25.327692 23.049650 19.670874 -26.648895 27.774105 19.105259 -27.552513 29.940975 20.143303 -27.796419 28.969646 22.506863 -27.315262 25.120386 25.562620 -26.237965 19.424603 28.491793 -24.853189 13.408474 30.509508 -23.531986 8.684018 31.075123 -22.628368 6.517148 30.037081 -22.384460 7.488473 27.673523 -22.865618 11.337729 24.617764 -26.269732 15.357694 21.312227 -27.108498 20.845367 17.941097 -28.245520 25.327168 16.207140 -29.376133 27.602207 16.574968 -30.197390 27.060886 18.946018 -30.489237 23.848251 22.684975 -30.173471 18.825127 26.789984 -29.334705 13.337456 30.161112 -28.197683 8.855652 31.895069 -27.067070 6.580613 31.527245 -26.245813 7.121931 29.156197 -25.953966 10.334563 25.417242 -28.812887 13.390993 20.475971 -28.554487 18.224890 16.145931 -29.039787 22.342630 13.463642 -30.138752 24.640873 13.147823 -31.556915 24.503803 15.283100 -32.914284 21.968147 19.297321 -33.847145 17.713335 24.114885 -34.105549 12.879438 28.444927 -33.620247 8.761698 31.127214 -32.521282 6.463455 31.443035 -31.103121 6.600522 29.307762 -29.745754 9.136175 25.293541 -31.554537 11.083297 18.985661 -29.851549 15.195050 14.255344 -29.338440 18.873268 11.000591 -30.152700 21.132378 10.093513 -32.076145 21.367046 11.777159 -34.593395 19.514402 15.600396 -37.029949 16.070856 20.538792 -38.732937 11.959105 25.269110 -39.246048 8.280886 28.523863 -38.431789 6.021776 29.430944 -36.508343 5.787104 27.747301 -33.991096 7.639746 23.924065 -34.370293 8.407306 16.678757 -31.127987 11.756630 12.156360 -29.447649 14.945526 8.780951 -29.779524 17.119530 7.456964 -32.034691 17.696121 8.539160 -35.608875 16.520802 11.737568 -39.544376 13.908498 16.195175 -42.786686 10.559175 20.717569 -44.467026 7.370280 24.092979 -44.135151 5.196275 25.416969 -41.879986 4.619682 24.334774 -38.305805 5.794999 21.136370 -37.055367 5.379981 13.479050 -32.416115 7.931258 9.717279 -29.583641 10.587599 6.666554 -29.316898 12.637236 5.144314 -31.687365 13.530973 5.558444 -36.059875 13.029333 7.797975 -41.262814 11.266731 11.262827 -45.902065 8.715455 15.024597 -48.734543 6.059115 18.075321 -49.001286 4.009477 19.597563 -46.630821 3.115738 19.183437 -42.258316 3.617377 16.943909 -39.369827 2.072712 9.426530 -33.656212 3.791776 6.860989 -29.839851 5.873733 4.518589 -28.943336 7.760722 3.026974 -31.206890 8.947126 2.785823 -36.023991 9.115051 3.859750 -42.103901 8.219501 5.960997 -47.817516 6.500437 8.526538 -51.633881 4.418481 10.868937 -52.530396 2.531492 12.360552 -50.266846 1.345086 12.601706 -45.449749 1.177160 11.527780 -41.088467 -1.397480 4.670344 -34.741901 -0.536660 3.592077 -30.222717 0.934674 2.251129 -28.741829 2.622279 1.006806 -30.696039 4.073963 0.192524 -35.561718 4.900748 0.026469 -42.035110 4.881099 0.553134 -48.381676 4.020279 1.631401 -52.900864 2.548946 2.972348 -54.381752 0.861341 4.216671 -52.427547 -0.590343 5.030953 -47.561871 -1.417129 5.197010 -42.035034 -4.882325 -0.555008 -35.562519 -4.894822 -0.017408 -30.697498 -4.062546 -0.175076 -28.743546 -2.608506 -0.985762 -30.224220 -0.922309 -2.232244 -34.742779 0.544228 -3.580529 -41.088478 1.398149 -4.669345 -47.560989 1.410647 -5.206944 -52.426014 0.578372 -5.049278 -54.379967 -0.875669 -4.238592 -52.899296 -2.561865 -2.992110 -48.380741 -4.028402 -1.643825 -42.103199 -8.221562 -5.964082 -36.025780 -9.110512 -3.852841 -31.210667 -8.937273 -2.770873 -28.948063 -7.748266 -3.008090 -29.844234 -5.862083 -4.500931 -33.659050 -3.784127 -6.849389 -39.370335 -2.071183 -9.424196 -45.447750 -1.182233 -11.535438 -50.262867 -1.355471 -12.617407 -52.525471 -2.544477 -12.380190 -51.629303 -4.430659 -10.887351 -47.814487 -6.508615 -8.538894 -41.261421 -11.269022 -11.266258 -36.063351 -13.024221 -7.790352 -31.694742 -13.519893 -5.541901 -29.326157 -12.623220 -5.123374 -29.592258 -10.574469 -6.646916 -32.421745 -7.922598 -9.704297 -37.056454 -5.378175 -13.476290 -42.254524 -3.622975 -16.952196 -46.623135 -3.127303 -19.200649 -48.991722 -4.023974 -19.619177 -48.725620 -6.072725 -18.095634 -45.896141 -8.724595 -15.038258 -39.541214 -13.911893 -16.200069 -35.612370 -16.517246 -11.732531 -32.043858 -17.686625 -8.525625 -29.791851 -17.106693 -7.438643 -29.459778 -14.932844 -8.762836 -31.136618 -11.747561 -12.143393 -34.373058 -8.404334 -16.674490 -38.301903 -5.798981 -21.142029 -41.870419 -4.629601 -24.348934 -44.122425 -5.209532 -25.435919 -44.454498 -7.383379 -24.111729 -42.777660 -10.568663 -20.731174 -37.024815 -16.074808 -20.544165 -34.593380 -19.514519 -15.600574 -32.081192 -21.363342 -11.772160 -30.161394 -21.125889 -10.084745 -29.348392 -18.865788 -10.990471 -29.860029 -15.188625 -14.246647 -31.559214 -11.079697 -18.980783 -33.990650 -7.639987 -23.924374 -36.502834 -5.791162 -27.752789 -38.422634 -6.028611 -29.440207 -39.235638 -8.288713 -28.534485 -38.724003 -11.965874 -25.278309 -33.840015 -17.717430 -24.119846 -32.911255 -21.969866 -19.299393 -31.558737 -24.502720 -15.281763 -30.144869 -24.637318 -13.143484 -29.048492 -22.337593 -13.457504 -28.563385 -18.219757 -16.139681 -28.819527 -13.387178 -20.471327 -29.748287 -9.134744 -25.291780 -31.100803 -6.601889 -29.309408 -32.514671 -6.467289 -31.447689 -33.611050 -8.767012 -31.133671 -34.096157 -12.884846 -28.451498 -30.162867 -18.830116 -26.794340 -30.482727 -23.850763 -22.686617 -30.196655 -27.060276 -18.944534 -29.381300 -27.598665 -16.570780 -28.255136 -25.321671 -16.201399 -27.119923 -20.839417 -17.935368 -26.279833 -15.352914 -21.308067 -25.959972 -10.332268 -25.415791 -26.246044 -7.122755 -29.157871 -27.061399 -6.584364 -31.531628 -28.187561 -8.861353 -31.901011 -29.322777 -13.343607 -30.167046 -26.226128 -19.429253 -28.494135 -27.303505 -25.124130 -25.563225 -27.787827 -28.971497 -22.505583 -27.549320 -29.940460 -20.140501 -26.651892 -27.771381 -19.101704 -25.336006 -23.045467 -19.667532 -23.954256 -17.029022 -21.686377 -22.876877 -11.334146 -24.617287 -22.392555 -7.486778 -27.674927 -22.631062 -6.517815 -30.040009 -23.528490 -8.686890 -31.078808 -24.844374 -13.412800 -30.512980 -22.296049 -19.563877 -29.234070 -23.522427 -25.759605 -27.720289 -24.348400 -30.147900 -25.611589 -24.552649 -31.552925 -23.473000 -24.080444 -29.598202 -21.877548 -23.058315 -24.807499 -21.252741 -21.760138 -18.464479 -21.765991 -20.533760 -12.268752 -23.279774 -19.707787 -7.880455 -25.388470 -19.503538 -6.475429 -27.527060 -19.975742 -8.430149 -29.122511 -20.997869 -13.220850 -29.747320 -18.603174 -19.321678 -29.124855 -19.415815 -25.764730 -29.028597 -20.143003 -30.529457 -27.954088 -20.589886 -32.339153 -26.189243 -20.636721 -30.708908 -24.206949 -20.270960 -26.075550 -22.538359 -19.590609 -19.680584 -21.630573 -18.777967 -13.237531 -21.726830 -18.050779 -8.472803 -22.801338 -17.603897 -6.663106 -24.566183 -17.557062 -8.293346 -26.548477 -17.922821 -12.926700 -28.217066 -15.298413 -18.809626 -28.336472 -15.299029 -25.201494 -29.488256 -15.576756 -30.130894 -29.388861 -16.057177 -32.276997 -28.064917 -16.611561 -31.064751 -25.871176 -17.091364 -26.818985 -23.395449 -17.368023 -20.677343 -21.301102 -17.367405 -14.285478 -20.149317 -17.089680 -9.356077 -20.248711 -16.609261 -7.209974 -21.572655 -16.054874 -8.422215 -23.766394 -15.575071 -12.667976 -26.242123 -12.441563 -18.129559 -27.046598 -11.426649 -24.169601 -29.207718 -11.035439 -29.036106 -29.949375 -11.372755 -31.425102 -29.072845 -12.348216 -30.696453 -26.812994 -13.700445 -27.045406 -23.775345 -15.067116 -21.450254 -20.773838 -16.082029 -15.410213 -18.612719 -16.473240 -10.543708 -17.871058 -16.135923 -8.154712 -18.747587 -15.160464 -8.883356 -21.007439 -13.808235 -12.534399 -24.045086 -10.024055 -17.366362 -25.402815 -7.955879 -22.779398 -28.336117 -6.800810 -27.362597 -29.766533 -6.868348 -29.887890 -29.310787 -8.140396 -29.678633 -27.090994 -10.276110 -26.790890 -23.701944 -12.703226 -21.998432 -20.051735 -14.771402 -16.585396 -17.118431 -15.926472 -12.002197 -15.688013 -15.858934 -9.476902 -16.143759 -14.586888 -9.686158 -18.363550 -12.451175 -12.573897 -21.752600 -8.004319 -16.585083 -23.512442 -4.960207 -21.131081 -27.012424 -3.040150 -25.228205 -28.990543 -2.758629 -27.778631 -28.916763 -4.191075 -28.098980 -26.810854 -6.953666 -26.103411 -23.237091 -10.306168 -22.326635 -19.153063 -13.350280 -17.780640 -15.653083 -15.270337 -13.683518 -13.674963 -15.551860 -11.133090 -13.748741 -14.119415 -10.812740 -15.854649 -11.356826 -12.808307 -19.428408 -6.331878 -15.835921 -21.448856 -2.467955 -19.308512 -25.346779 0.150116 -22.735535 -27.752441 0.820824 -25.198717 -28.021252 -0.635545 -26.038055 -26.081179 -3.828759 -25.028646 -22.452066 -7.903198 -22.440962 -18.106331 -11.767121 -18.968370 -14.208409 -14.385193 -15.541350 -11.802746 -15.055902 -13.078167 -11.533936 -13.599535 -12.238828 -13.474007 -10.406323 -13.248235 -17.103117 -4.952909 -15.161866 -19.262478 -0.482493 -17.389774 -23.413910 2.714293 -19.982759 -26.142094 3.780872 -22.246035 -26.716007 2.431456 -23.573154 -24.981878 -0.972381 -23.608521 -21.404362 -5.518582 -22.342655 -16.942051 -9.988997 -20.114746 -12.790619 -13.185784 -17.521763 -10.062437 -14.252365 -15.258489 -9.488520 -12.902951 -13.931368 -11.222647 -9.499117 -13.896000 -14.800163 -3.811312 -14.600764 -16.990974 1.006397 -15.455797 -21.261944 4.618319 -17.076756 -24.213638 6.056643 -19.029308 -25.055149 4.935970 -20.790270 -23.560997 1.556586 -21.887789 -20.131538 -3.176008 -22.027792 -15.685695 -7.993716 -21.172760 -11.414722 -11.605639 -19.551800 -8.463031 -13.043963 -17.599249 -7.621517 -11.923294 -15.838287 -9.115666 -8.543912 -14.740766 -12.545123 -2.845111 -14.183188 -14.665416 2.024871 -13.595866 -18.922285 5.849942 -14.144990 -21.996902 7.605178 -15.683422 -23.065430 6.820265 -17.798943 -21.841557 3.705520 -19.924696 -18.653217 -0.904464 -21.491093 -14.354727 -5.774445 -22.078417 -10.097859 -9.599516 -21.529293 -7.023241 -11.354753 -19.990864 -5.954710 -10.569843 -17.875343 -7.178583 -7.455101 -15.749587 -10.366919 -1.991471 -13.929920 -12.311728 2.608263 -11.899206 -16.422842 6.411838 -11.323657 -19.519217 8.400088 -12.357489 -20.771187 8.040265 -14.723690 -19.843287 5.428782 -17.788237 -16.984146 1.265385 -20.729986 -12.959869 -3.334348 -22.760700 -8.848757 -7.137923 -23.336252 -5.752381 -9.126174 -22.302422 -4.500409 -8.766354 -19.936222 -5.428308 -6.154873 -16.871675 -8.287447 -1.180817 -13.847584 -9.954947 2.820733 -10.458263 -13.786747 6.349655 -8.767914 -16.799288 8.460378 -9.229462 -18.185364 8.587333 -11.719236 -17.573574 6.696506 -15.570103 -15.127850 3.294540 -19.750227 -11.503521 -0.707009 -23.139547 -7.671721 -4.235931 -24.829899 -4.659179 -6.346654 -24.368353 -3.273102 -6.473612 -21.878580 -3.884889 -4.582787 -18.027716 -6.330611 -0.343823 -13.923123 -7.622125 2.760524 -9.353826 -11.037843 5.768061 -6.631764 -13.854062 7.872922 -6.486316 -15.316177 8.511111 -8.956452 -15.032418 7.511627 -13.380302 -13.078817 5.142279 -18.572498 -9.978839 2.037933 -23.141798 -6.563122 -0.969604 -25.863859 -3.746903 -3.074467 -26.009310 -2.284786 -3.712657 -23.539177 -2.568544 -2.713174 -19.115328 -4.522144 0.580524 -14.128654 -5.332025 2.529731 -8.641498 -8.208531 4.786432 -5.039898 -10.722843 6.745944 -4.288899 -12.201252 7.883219 -6.589733 -12.247620 7.893524 -11.325891 -10.849522 6.774099 -17.228325 -8.381578 4.824893 -22.715481 -5.505073 2.568193 -26.317081 -2.990762 0.608681 -27.068083 -1.512352 -0.528595 -24.767254 -1.465982 -0.538902 -20.031096 -2.864079 1.643999 -14.417905 -3.103316 2.255303 -8.348122 -5.331911 3.576148 -4.085114 -7.445702 5.252614 -2.771149 -8.878300 6.835494 -4.758304 -9.245843 7.900655 -9.514122 -8.449847 8.162689 -15.764283 -6.703599 7.551385 -21.834066 -4.475005 6.230540 -26.097073 -2.361215 4.554074 -27.411041 -0.928616 2.971195 -25.423889 -0.561072 1.906033 -20.668076 -1.357066 2.879879 -14.731735 -0.954226 2.069311 -8.462663 -2.445631 2.335706 -3.807085 -4.070628 3.607682 -2.012460 -5.393799 5.544415 -3.559658 -6.060602 7.626957 -8.034106 -5.892367 9.297295 -14.236881 -4.934174 10.107862 -20.505953 -3.442769 9.841468 -25.161533 -1.817773 8.569493 -26.956158 -0.494601 6.632761 -25.408962 0.172202 4.550219 -20.934519 0.003969 4.304193 -15.005011 1.105474 2.091412 -8.938318 0.411609 1.259107 -4.189182 -0.655612 2.030293 -2.030129 -1.810229 4.198332 -3.039675 -2.742862 7.182299 -6.947312 -3.203614 10.182642 -12.705993 -3.069027 12.395423 -18.772682 -2.375163 13.227729 -23.521820 -1.307942 12.456545 -25.680874 -0.153325 10.288507 -24.671333 0.779308 7.304541 -20.763699 1.240061 5.911581 -15.171939 3.067589 2.423793 -9.694698 3.200873 0.531273 -5.156915 2.739508 0.741117 -2.774481 1.807115 2.997100 -3.185770 0.653528 6.694731 -6.280577 -0.412149 10.843234 -11.229650 -1.104370 14.331021 -16.706888 -1.237656 16.223543 -21.244673 -0.776290 16.013700 -23.627108 0.156102 13.757719 -23.215820 1.309688 10.060090 -20.121019 2.375366 7.680416 -15.170621 4.933131 3.142843 -10.623396 5.890086 0.308502 -6.583048 6.057648 -0.063150 -4.132185 5.390919 2.127473 -3.927515 4.068548 6.293393 -6.023878 2.444865 11.318357 -9.859553 0.954933 15.855928 -14.406778 -0.002022 18.690271 -18.447128 -0.169584 19.061924 -20.897991 0.497144 16.871305 -21.102663 1.819514 12.705386 -19.006302 3.443197 9.571057 -14.950871 6.704327 4.289065 -11.598726 8.449685 0.702772 -8.298378 9.244789 -0.226878 -5.934152 8.876594 1.749215 -5.139542 7.443753 6.101557 -6.127460 5.330199 11.663941 -8.633197 3.102254 16.945932 -11.985340 1.356896 20.532227 -15.285689 0.561791 21.461880 -17.649914 0.929986 19.485788 -18.444529 2.362825 15.133450 -17.456610 4.476379 11.533261 -14.480206 8.382709 5.861832 -12.497835 10.850031 1.765243 -10.120541 12.247319 0.341172 -7.985317 12.200171 1.971197 -6.664296 10.721218 6.218555 -6.511444 8.206747 11.945168 -7.567717 5.330507 17.616596 -9.550088 2.863184 21.713188 -11.927382 1.465895 23.137260 -14.062605 1.513043 21.507238 -15.383627 2.991994 17.259884 -15.536481 5.506464 13.513113 -13.739154 9.980139 7.831993 -13.193710 13.080133 3.501153 -11.846581 15.033345 1.681035 -10.058724 15.316416 2.859342 -8.309200 13.853496 6.720344 -7.066788 11.036573 12.229490 -6.664393 7.620440 17.910608 -7.209836 4.520447 22.241451 -8.556966 2.567234 24.061569 -10.344820 2.284162 22.883266 -12.094345 3.747080 19.022266 -13.336757 6.564001 15.456736 -12.727990 11.505112 10.135856 -13.581934 15.130247 5.855661 -13.292501 17.576090 3.763027 -11.937248 18.187281 4.418673 -9.879314 16.800047 7.646917 -7.670120 13.786100 12.582756 -5.901618 9.953026 17.903635 -5.047676 6.327889 22.183830 -5.337107 3.882047 24.276466 -6.692358 3.270855 23.620823 -8.750292 4.658086 20.392582 -10.959486 7.672030 17.318907 -11.461308 12.962657 12.689813 -13.589964 16.990423 8.730534 -14.314751 19.851330 6.501955 -13.441467 20.778793 6.601224 -11.204104 19.524307 9.001740 -8.202166 16.424007 13.060287 -5.240017 12.308615 17.689381 -3.111362 8.280849 21.648659 -2.386573 5.419943 23.877239 -3.259856 4.492476 23.777971 -5.497217 5.746962 21.377459 -8.499155 8.847260 19.062946 -9.963543 14.357530 15.400995 -13.165812 18.660805 12.002627 -14.795015 21.851851 9.778434 -14.414614 23.075630 9.324385 -12.126529 22.004232 10.762143 -8.543857 18.924738 13.706461 -4.626569 14.662294 17.368412 -1.424300 10.359020 20.766781 0.204906 7.167974 22.990974 -0.175497 5.944193 23.445024 -2.463578 7.015589 22.007269 -6.046249 10.095081 20.664902 -8.263432 15.687098 18.177614 -12.289624 20.135220 15.537526 -14.665791 23.565926 13.452045 -14.755242 25.059961 12.479974 -12.534007 24.217003 12.881780 -8.597267 21.262920 14.549797 -3.999867 16.989256 17.037083 0.026324 12.541137 19.677172 2.402492 9.110430 21.762651 2.491945 7.616392 22.734724 0.270713 8.459349 22.332920 -3.666025 11.413428 22.108582 -6.393137 16.943401 20.931717 -10.959291 21.409697 19.199118 -13.886312 24.989731 17.375034 -14.389907 26.724232 15.948230 -12.335138 26.148443 15.301014 -8.272579 23.416649 15.606807 -3.290790 19.260828 16.783672 1.275364 14.794532 18.516270 4.202387 11.214499 20.340353 4.705984 9.479996 21.767159 2.651217 10.055781 22.414375 -1.411340 12.787576 23.385841 -4.379169 18.107723 23.588964 -9.195002 22.460777 22.866072 -12.459511 26.094837 21.410864 -13.297976 28.036160 19.613260 -11.485728 27.764565 17.954929 -7.508360 25.352833 16.880219 -2.431604 21.447180 16.677095 2.384228 17.094124 17.399986 5.648738 13.460064 18.855194 6.487204 11.518743 20.652798 4.674959 11.790335 22.311129 0.697593 14.202065 24.488552 -2.241341 19.153799 26.083490 -7.026037 23.245918 26.430666 -10.410261 26.825371 25.437054 -11.487216 28.933044 23.368889 -9.968329 29.004189 20.780338 -6.260586 27.019741 18.365000 -1.357475 23.511435 16.770060 3.427221 19.419315 16.422884 6.811446 15.839865 17.416496 7.888401 13.732190 19.484657 6.369517 13.661044 22.073208 2.661777 15.645488</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="1800" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="5400">0.707336 -0.007419 -0.706838 0.553723 0.072058 -0.829577 0.459931 -0.319190 -0.828602 0.569051 -0.376896 -0.730843 0.570182 -0.573700 -0.588014 0.591785 -0.646149 -0.481957 0.685840 -0.598368 0.414221 0.508123 -0.689481 0.516165 0.102232 -0.061688 0.992846 -0.092912 -0.064108 0.993608 -0.247030 0.061428 0.967059 -0.410475 0.106566 0.905623 -0.547172 -0.079764 0.833211 -0.702358 -0.000215 0.711824 -0.806760 -0.331328 0.489245 -0.923865 -0.227582 0.307701 -0.926815 -0.369725 0.065711 -0.959947 -0.249426 -0.127629 -0.689409 0.604593 -0.398976 -0.507284 0.699744 -0.503012 0.411391 0.866156 -0.283779 0.569990 0.795552 -0.205444 0.610102 0.593850 -0.524517 0.771486 0.488975 -0.407078 0.350643 0.103805 -0.930739 0.300301 -0.309857 -0.902113 0.491367 -0.536151 -0.686368 0.829811 -0.486279 0.273764 0.316994 -0.005532 0.948412 -0.044155 0.067295 0.996756 -0.343227 -0.110760 0.932699 -0.631855 -0.387262 0.671407 -0.844756 -0.446818 0.294518 -0.839136 0.479901 -0.256018 0.224329 0.896776 -0.381404 0.407586 0.651360 -0.640002 0.106505 0.080024 -0.991087 0.101424 -0.355539 -0.929142 0.359087 -0.547620 -0.755757 0.923856 -0.371816 0.090794 0.531243 0.098867 0.841431 0.184122 0.126103 0.974781 -0.099551 -0.085518 0.991351 -0.400598 -0.378509 0.834417 -0.700769 -0.457525 0.547351 -0.934949 0.349374 -0.061712 -0.006597 0.870851 -0.491503 0.163640 0.643289 -0.747931 -0.160809 0.003438 -0.986979 -0.115299 -0.447782 -0.886678 0.188187 -0.611120 -0.768842 0.950584 -0.282337 -0.129136 0.717451 0.231035 0.657181 0.415314 0.226842 0.880941 0.165703 -0.007082 0.986150 -0.125166 -0.299205 0.945944 -0.485609 -0.386762 0.783964 -0.950594 0.254414 0.177887 -0.282136 0.771919 -0.569684 -0.117056 0.557168 -0.822108 -0.424330 -0.106640 -0.899206 -0.323210 -0.557889 -0.764392 0.004666 -0.708937 -0.705257 0.897768 -0.249083 -0.363278 0.846829 0.353698 0.397213 0.621484 0.341561 0.705049 0.426069 0.105042 0.898572 0.168437 -0.163888 0.971993 -0.212507 -0.240561 0.947085 -0.876016 0.231696 0.422980 -0.561224 0.614770 -0.554153 -0.410111 0.405222 -0.817071 -0.654366 -0.215829 -0.724722 -0.502772 -0.646596 -0.573702 -0.166200 -0.805673 -0.568567 0.767310 -0.292576 -0.570644 0.901934 0.422728 0.088404 0.778014 0.430814 0.457267 0.653037 0.216584 0.725695 0.446401 -0.007681 0.894800 0.082578 -0.050702 0.995294 -0.726974 0.288740 0.623007 -0.782101 0.456242 -0.424454 -0.671309 0.234524 -0.703095 -0.827815 -0.286366 -0.482407 -0.647071 -0.683053 -0.338729 -0.315207 -0.868107 -0.383451 0.578370 -0.405937 -0.707604 0.885574 0.406775 -0.224258 0.872365 0.459036 0.168121 0.824716 0.289921 0.485582 0.679098 0.126061 0.723142 0.360871 0.137545 0.922417 -0.530608 0.406693 0.743678 -0.908798 0.355612 -0.218235 -0.862313 0.103864 -0.495609 -0.933854 -0.291513 -0.207213 -0.752758 -0.653096 -0.082589 -0.445457 -0.878641 -0.171926 0.357898 -0.556707 -0.749658 0.813901 0.300338 -0.497356 0.904458 0.408375 -0.123231 0.930715 0.297990 0.212064 0.849190 0.201982 0.487933 0.595712 0.283069 0.751665 -0.312529 0.555044 0.770877 -0.940504 0.339757 0.004161 -0.968841 0.051461 -0.242278 -0.972982 -0.222453 0.061816 -0.813412 -0.555352 0.173047 -0.554184 -0.830533 0.055633 0.130125 -0.706044 -0.696110 0.701905 0.121169 -0.701888 0.880473 0.281306 -0.381621 0.971219 0.231391 -0.056491 0.952052 0.202276 0.229523 0.774547 0.359612 0.520343 -0.093018 0.701402 0.706670 -0.894929 0.403144 0.191249 -0.996302 0.085763 0.005118 -0.952809 -0.086329 0.291037 -0.824139 -0.396514 0.404440 -0.629601 -0.721710 0.287641 -0.086439 -0.823931 -0.560059 0.558710 -0.100843 -0.823209 0.808125 0.094548 -0.581373 0.953191 0.096838 -0.286442 0.991848 0.126729 -0.013322 0.894687 0.357392 0.267967 0.112468 0.818074 0.564009 -0.794509 0.521964 0.310335 -0.959153 0.193513 0.206344 -0.884382 0.099532 0.456028 -0.785896 -0.189323 0.588663 -0.660828 -0.555349 0.504871 -0.278178 -0.889804 -0.361754 0.392076 -0.334096 -0.857121 0.696137 -0.128666 -0.706285 0.887119 -0.088442 -0.452987 0.977786 -0.011906 -0.209266 0.959500 0.280115 0.029921 0.292817 0.884800 0.362473 -0.660580 0.666361 0.345829 -0.874275 0.350676 0.335663 -0.780317 0.312748 0.541566 -0.705102 0.049088 0.707405 -0.644001 -0.340686 0.684979 -0.435960 -0.891253 -0.124927 0.211106 -0.550686 -0.807576 0.554565 -0.363578 -0.748511 0.785274 -0.301982 -0.540510 0.921861 -0.193039 -0.336017 0.976139 0.141116 -0.165044 0.440158 0.889209 0.124773 -0.512206 0.806580 0.295083 -0.758557 0.529380 0.379932 -0.654158 0.529085 0.540507 -0.591934 0.298929 0.748502 -0.582479 -0.091872 0.807637 -0.554479 -0.822761 0.124969 0.026397 -0.728185 -0.684872 0.394711 -0.586413 -0.707336 0.661003 -0.519400 -0.541571 0.837885 -0.391884 -0.379968 0.954608 -0.039833 -0.295190 0.549581 0.826022 -0.125095 -0.366281 0.915772 0.164922 -0.628384 0.701592 0.336010 -0.520158 0.724057 0.452965 -0.459191 0.538941 0.706177 -0.485198 0.173186 0.857082 -0.632045 -0.685318 0.361744 -0.151095 -0.849914 -0.504793 0.228557 -0.775484 -0.588546 0.528372 -0.716134 -0.456044 0.741051 -0.581474 -0.335755 0.907441 -0.238427 -0.345981 0.619441 0.696184 -0.362795 -0.237603 0.970897 -0.030065 -0.499523 0.840645 0.209268 -0.392755 0.873914 0.286387 -0.321818 0.747468 0.581140 -0.366327 0.434153 0.822992 -0.670768 -0.486270 0.560011 -0.310730 -0.905915 -0.287687 0.068167 -0.912065 -0.404339 0.401597 -0.868323 -0.291093 0.647460 -0.733587 -0.206510 0.849461 -0.426573 -0.310566 0.651830 0.506608 -0.564328 -0.138288 0.953398 -0.268159 -0.386532 0.922180 0.013313 -0.285302 0.956778 0.056387 -0.196265 0.903393 0.381262 -0.245513 0.669110 0.701438 -0.676828 -0.239783 0.695994 -0.442567 -0.894995 -0.055846 -0.074814 -0.982074 -0.173014 0.293734 -0.953879 -0.061932 0.572781 -0.819691 -0.005379 0.796883 -0.572942 -0.191614 0.653563 0.270274 -0.706971 -0.076313 0.850394 -0.520583 -0.301267 0.925492 -0.229572 -0.207476 0.954944 -0.212215 -0.098363 0.987552 0.122743 -0.146400 0.855540 0.496608 -0.661146 0.032125 0.749569 -0.538331 -0.825070 0.171637 -0.189747 -0.978361 0.082499 0.214256 -0.954592 0.206997 0.529394 -0.813150 0.241930 0.764923 -0.644105 -0.004698 0.636614 0.006979 -0.771151 -0.053196 0.657100 -0.751924 -0.250154 0.836213 -0.488027 -0.161603 0.859034 -0.485742 -0.038715 0.984916 -0.168644 -0.090332 0.970551 0.223317 -0.640636 0.298276 0.707543 -0.593899 -0.707322 0.383379 -0.268262 -0.901879 0.338601 0.165559 -0.860336 0.482092 0.521473 -0.694861 0.495211 0.762913 -0.608811 0.217517 0.617308 -0.256082 -0.743877 -0.061765 0.380742 -0.922616 -0.230909 0.650831 -0.723256 -0.139411 0.673623 -0.725807 -0.016334 0.888941 -0.457731 -0.085079 0.992364 -0.089307 -0.636926 0.518329 0.570666 -0.613953 -0.547272 0.568819 -0.308476 -0.758844 0.573584 0.139811 -0.675076 0.724379 0.538979 -0.464345 0.702770 0.786707 -0.449042 0.423620 0.613555 -0.485092 -0.623085 -0.085428 0.045496 -0.995305 -0.230313 0.382370 -0.894846 -0.122607 0.421282 -0.898604 -0.015675 0.708653 -0.705383 -0.117677 0.909846 -0.397910 -0.664586 0.652846 0.363480 -0.615314 -0.350975 0.705836 -0.321026 -0.559150 0.764391 0.119373 -0.421502 0.898936 0.555988 -0.153034 0.816981 0.813493 -0.178909 0.553373 0.638828 -0.642625 -0.423003 -0.101941 -0.304968 -0.946891 -0.226419 0.063560 -0.971954 -0.089569 0.139809 -0.986119 -0.012128 0.472769 -0.881103 -0.159446 0.736364 -0.657530 -0.719964 0.681803 0.129605 -0.622225 -0.143018 0.769663 -0.329268 -0.324072 0.886882 0.083134 -0.138356 0.986887 0.540756 0.176498 0.822455 0.809906 0.140841 0.569399 0.695954 -0.695712 -0.177859 -0.091534 -0.614379 -0.783683 -0.196559 -0.258242 -0.945873 -0.024884 -0.128984 -0.991334 0.016118 0.222308 -0.974843 -0.180950 0.509088 -0.841479 -0.784216 0.613916 -0.090068 -0.652700 0.036881 0.756719 -0.357552 -0.090219 0.929525 0.016114 0.131523 0.991182 0.474865 0.462770 0.748563 0.757750 0.428960 0.491741 0.770085 -0.634944 0.061773 -0.044891 -0.835863 -0.547099 -0.127316 -0.536266 -0.834392 0.075071 -0.352553 -0.932776 0.079269 -0.004683 -0.996842 -0.164320 0.271479 -0.948313 -0.836438 0.475313 -0.272853 -0.709003 0.157342 0.687429 -0.417367 0.104963 0.902656 -0.085092 0.355011 0.930981 0.359815 0.678246 0.640715 0.664575 0.642151 0.382076 0.835357 -0.486412 0.256090 0.036567 -0.955010 -0.294312 -0.019146 -0.740801 -0.671452 0.203863 -0.513650 -0.833429 0.175595 -0.183231 -0.967260 -0.105622 0.057599 -0.992737 -0.861643 0.294719 -0.413172 -0.781058 0.206927 0.589177 -0.505285 0.238654 0.829296 -0.213918 0.515230 0.829926 0.208771 0.824969 0.525206 0.544355 0.789040 0.284769 0.868330 -0.294520 0.399075 0.144567 -0.987308 -0.065757 0.116841 -0.864171 -0.489445 0.350352 -0.608323 -0.712177 0.296464 -0.302085 -0.906010 -0.010121 -0.112343 -0.993618 -0.851817 0.095394 -0.515080 -0.854767 0.189410 0.483215 -0.609938 0.304344 0.731677 -0.359462 0.608747 0.707258 0.037424 0.912414 0.407553 0.403790 0.891280 0.206334 0.859570 -0.089415 0.503134 0.265167 -0.955735 0.127500 0.265141 -0.913729 -0.307896 0.502899 -0.639983 -0.580960 0.430719 -0.359736 -0.827691 0.112610 -0.229645 -0.966738 -0.803328 -0.106169 -0.585997 -0.916967 0.115550 0.381864 -0.718196 0.305717 0.625085 -0.510484 0.639286 0.575083 -0.140482 0.947688 0.286624 0.246814 0.959489 0.135881 0.807693 0.112977 0.578679 0.382182 -0.877291 0.290339 0.411422 -0.901422 -0.134797 0.650755 -0.614452 -0.446056 0.566925 -0.359341 -0.741263 0.251491 -0.292128 -0.922721 -0.715439 -0.298449 -0.631724 -0.956644 -0.001987 0.291253 -0.817702 0.250747 0.518159 -0.656512 0.612946 0.439647 -0.313973 0.935562 0.161695 0.079160 0.994855 0.063228 0.714689 0.303335 0.630244 0.480789 -0.763891 0.430480 0.543985 -0.838625 0.028083 0.783748 -0.537990 -0.310333 0.694026 -0.306239 -0.651572 0.395235 -0.301045 -0.867849 -0.588600 -0.471936 -0.656374 -0.965145 -0.150569 0.214068 -0.897490 0.148553 0.415264 -0.787638 0.536000 0.303860 -0.474209 0.879772 0.033577 -0.092188 0.995612 -0.016079 0.583178 0.473849 0.659826 0.550603 -0.625169 0.553173 0.653588 -0.734926 0.180850 0.891756 -0.417133 -0.175415 0.801338 -0.207457 -0.561087 0.532328 -0.260207 -0.805555 -0.425280 -0.617493 -0.661694 -0.936245 -0.316988 0.151539 -0.947829 0.009256 0.318645 -0.893914 0.415031 0.169315 -0.613029 0.784196 -0.096077 -0.259522 0.960247 -0.102835 0.416625 0.616103 0.668462 0.585187 -0.469979 0.660815 0.732786 -0.598805 0.323198 0.964736 -0.259683 -0.043009 0.879026 -0.071651 -0.471360 0.651622 -0.175612 -0.737935 -0.230747 -0.725861 -0.647983 -0.866795 -0.487608 0.104425 -0.960638 -0.155913 0.229928 -0.965458 0.257823 0.037660 -0.722305 0.653891 -0.225172 -0.414476 0.888648 -0.196251 0.220643 0.721417 0.656410 0.580613 -0.307310 0.753955 0.775234 -0.438970 0.454222 0.993558 -0.075550 0.084468 0.918865 0.090944 -0.383947 0.743105 -0.055215 -0.666893 -0.013858 -0.788657 -0.614677 -0.757218 -0.649008 0.073548 -0.930178 -0.334625 0.150977 -0.993273 0.074257 -0.088855 -0.794111 0.495948 -0.351317 -0.548077 0.782762 -0.294779 0.003839 0.781717 0.623622 0.535206 -0.146752 0.831876 0.775958 -0.265113 0.572367 0.971239 0.122957 0.203901 0.915080 0.268786 -0.300638 0.798954 0.091315 -0.594420 0.213517 -0.799304 -0.561715 -0.611660 -0.788875 0.059566 -0.853834 -0.513730 0.083963 -0.970471 -0.123471 -0.207223 -0.821679 0.319829 -0.471756 -0.651196 0.647140 -0.396426 -0.222203 0.790689 0.570471 0.449551 0.001409 0.893254 0.731816 -0.088254 0.675763 0.894190 0.321415 0.311635 0.865263 0.449092 -0.222790 0.814846 0.252408 -0.521840 0.437096 -0.753969 -0.490386 -0.437980 -0.896861 0.061758 -0.732901 -0.679646 0.030597 -0.893471 -0.321235 -0.313875 -0.800460 0.137183 -0.583476 -0.715214 0.489335 -0.499019 -0.443495 0.745077 0.498169 0.326892 0.126234 0.936593 0.642282 0.079467 0.762338 0.763228 0.504503 0.403683 0.770132 0.619443 -0.152269 0.789362 0.416772 -0.450786 0.640613 -0.654668 -0.401280 -0.246572 -0.965910 0.078866 -0.572611 -0.819791 -0.007640 -0.762973 -0.503772 -0.405074 -0.729249 -0.038796 -0.683147 -0.733794 0.319725 -0.599435 -0.644767 0.646405 0.407966 0.173990 0.217400 0.960450 0.510235 0.225550 0.829933 0.583931 0.657300 0.476426 0.633400 0.768464 -0.090924 0.723760 0.574272 -0.382600 0.809088 -0.506679 -0.297747 -0.048340 -0.992809 0.109511 -0.381334 -0.923969 -0.029432 -0.584363 -0.656369 -0.477179 -0.610813 -0.194610 -0.767486 -0.703889 0.150649 -0.694150 -0.811259 0.500090 0.302935 0.001013 0.266866 0.963733 0.342262 0.338372 0.876562 0.366396 0.766974 0.526787 0.461638 0.886168 -0.039955 0.621795 0.715906 -0.317568 0.929419 -0.320224 -0.183406 0.146004 -0.977715 0.150848 -0.170063 -0.984818 -0.034813 -0.367471 -0.766225 -0.527128 -0.451959 -0.317603 -0.833583 -0.626219 -0.004294 -0.779635 -0.930176 0.316095 0.186702 -0.179404 0.269170 0.946236 0.148452 0.408241 0.900722 0.124403 0.824130 0.552570 0.263352 0.964699 -0.001082 0.487802 0.834374 -0.256651 0.992051 -0.109649 -0.061735 0.327230 -0.923418 0.200551 0.048972 -0.998505 -0.024290 -0.125874 -0.823845 -0.552662 -0.263370 -0.397879 -0.878822 -0.506274 -0.132576 -0.852121 -0.992135 0.108220 0.062901 -0.353166 0.223309 0.908519 -0.058261 0.428837 0.901501 -0.125875 0.823846 0.552660 0.048860 0.998512 0.024208 0.327069 0.923440 -0.200709 0.992045 0.109654 0.061831 0.487839 -0.834321 0.256750 0.263435 -0.964676 0.001158 0.124391 -0.824132 -0.552570 -0.058377 -0.428890 -0.901469 -0.353313 -0.223411 -0.908437 -0.992142 -0.108161 -0.062897 -0.506221 0.132661 0.852140 -0.263279 0.397937 0.878823 -0.367462 0.766224 0.527136 -0.170184 0.984796 0.034845 0.145849 0.977746 -0.150803 0.929375 0.320515 0.183119 0.621875 -0.715834 0.317575 0.461731 -0.886119 0.039969 0.366391 -0.766979 -0.526783 0.148326 -0.408246 -0.900741 -0.179559 -0.269144 -0.946214 -0.930204 -0.316189 -0.186400 -0.626141 0.004328 0.779698 -0.451866 0.317641 0.833619 -0.584320 0.656382 0.477213 -0.381447 0.923912 0.029741 -0.048476 0.992848 -0.109097 0.809064 0.506757 0.297679 0.724003 -0.574184 0.382272 0.633502 -0.768403 0.090729 0.583911 -0.657322 -0.476421 0.342136 -0.338311 -0.876635 0.000852 -0.266689 -0.963782 -0.811297 -0.500032 -0.302928 -0.703755 -0.150748 0.694265 -0.610735 0.194628 0.767543 -0.762901 0.503839 0.405127 -0.572656 0.819757 0.007996 -0.246664 0.965920 -0.078455 0.640705 0.654536 0.401348 0.789559 -0.416802 0.450414 0.770164 -0.619467 0.152013 0.763162 -0.504572 -0.403720 0.510117 -0.225547 -0.830006 0.173782 -0.217329 -0.960504 -0.644851 -0.646300 -0.407998 -0.733758 -0.319765 0.599457 -0.729241 0.038887 0.683151 -0.893375 0.321370 0.314011 -0.732931 0.679639 -0.030065 -0.438089 0.896851 -0.061129 0.437244 0.754011 0.490189 0.815155 -0.252448 0.521338 0.865327 -0.449180 0.222367 0.894105 -0.321581 -0.311708 0.642189 -0.079500 -0.762412 0.326642 -0.126132 -0.936694 -0.443624 -0.745038 -0.498112 -0.715180 -0.489399 0.499004 -0.800476 -0.137095 0.583476 -0.970398 0.123727 0.207413 -0.853812 0.513860 -0.083381 -0.611637 0.788943 -0.058899 0.214009 0.799011 0.561945 0.799393 -0.091446 0.593809 0.915207 -0.268986 0.300070 0.971171 -0.123198 -0.204083 0.731738 0.088190 -0.675857 0.449301 -0.001368 -0.893380 -0.222419 -0.790525 -0.570614 -0.651158 -0.647190 0.396407 -0.821718 -0.319720 0.471762 -0.993271 -0.073955 0.089125 -0.930178 0.334884 -0.150409 -0.757142 0.649163 -0.072966 -0.013340 0.788609 0.614750 0.743548 0.054925 0.666423 0.919040 -0.091304 0.383444 0.993562 0.075223 -0.084708 0.775915 0.265040 -0.572459 0.535010 0.146756 -0.832002 0.003609 -0.781654 -0.623702 -0.548089 -0.782801 0.294654 -0.794176 -0.495851 0.351306 -0.965561 -0.257487 -0.037318 -0.960772 0.156159 -0.229196 -0.866815 0.487745 -0.103614 -0.230169 0.725915 0.648127 0.652250 0.175496 0.737409 0.879383 0.071358 0.470737 0.964844 0.259330 0.042705 0.775207 0.438916 -0.454321 0.580362 0.307402 -0.754112 0.220420 -0.721415 -0.656487 -0.414431 -0.888685 0.196177 -0.722390 -0.653799 0.225165 -0.894151 -0.414677 -0.168930 -0.948103 -0.008958 -0.317838 -0.936325 0.317198 -0.150600 -0.424523 0.617545 0.662131 0.533122 0.260148 0.805049 0.801874 0.207180 0.560423 0.891989 0.416798 0.175027 0.732720 0.598800 -0.323358 0.584841 0.470138 -0.661008 0.416402 -0.616097 -0.668606 -0.259423 -0.960272 0.102847 -0.613117 -0.784126 0.096094 -0.788001 -0.535712 -0.303425 -0.897924 -0.148284 -0.414420 -0.965335 0.150769 -0.213066 -0.587934 0.472127 0.656833 0.396104 0.301049 0.867451 0.694715 0.306017 0.650941 0.784115 0.537691 0.309921 0.653525 0.734948 -0.180991 0.550184 0.625397 -0.553332 0.583034 -0.473843 -0.659958 -0.092019 -0.995626 0.016157 -0.474251 -0.879751 -0.033523 -0.657012 -0.612741 -0.439186 -0.818330 -0.250603 -0.517238 -0.957001 0.002076 -0.290078 -0.714760 0.298672 0.632387 0.252445 0.292340 0.922393 0.567771 0.359319 0.740625 0.651248 0.614250 0.445616 0.543904 0.838673 -0.028210 0.480167 0.764196 -0.430632 0.714647 -0.303417 -0.630252 0.079366 -0.994857 -0.062940 -0.313973 -0.935582 -0.161578 -0.511104 -0.639217 -0.574607 -0.719026 -0.305679 -0.624149 -0.917502 -0.115543 -0.380579 -0.802647 0.106380 0.586891 0.113632 0.229934 0.966550 0.431707 0.359837 0.827132 0.503511 0.639899 0.580522 0.411257 0.901523 0.134626 0.381238 0.877646 -0.290509 0.807714 -0.113026 -0.578640 0.247033 -0.959523 -0.135241 -0.140372 -0.947790 -0.286339 -0.360126 -0.608864 -0.706820 -0.610965 -0.304326 -0.730826 -0.855501 -0.189367 -0.481931 -0.851147 -0.095291 0.516206 -0.009012 0.112477 0.993613 0.297574 0.302159 0.905621 0.351025 0.608370 0.711806 0.264831 0.913905 0.307640 0.263933 0.956054 -0.127671 0.859600 0.089465 -0.503075 0.403939 -0.891425 -0.205416 0.037701 -0.912629 -0.407047 -0.214472 -0.515581 -0.829565 -0.506407 -0.238722 -0.828592 -0.781937 -0.206942 -0.588005 -0.861143 -0.294744 0.414196 -0.104530 -0.057698 0.992847 0.176734 0.183210 0.967057 0.204530 0.513747 0.833206 0.116437 0.864355 0.489217 0.143162 0.987518 0.065667 0.868333 0.294682 -0.398948 0.544407 -0.789378 -0.283729 0.209240 -0.825312 -0.524480 -0.085437 -0.355568 -0.930737 -0.418519 -0.105137 -0.902102 -0.710029 -0.157466 -0.686341 -0.836003 -0.475522 0.273821 -0.163265 -0.271757 0.948416 0.080377 0.004587 0.996754 0.075693 0.352632 0.932696 -0.019500 0.740876 0.671358 0.035324 0.955020 0.294431 0.835179 0.486750 -0.256030 0.664462 -0.642735 -0.381288 0.360326 -0.678699 -0.639948 0.016066 -0.132244 -0.991087 -0.358624 0.089952 -0.929138 -0.653796 -0.037142 -0.755758 -0.783932 -0.614176 0.090763 -0.179973 -0.509543 0.841413 0.017170 -0.222548 0.974771 -0.024296 0.128959 0.991352 -0.127562 0.536213 0.834388 -0.045928 0.835670 0.547308 0.769980 0.635078 -0.061693 0.757510 -0.429742 -0.491426 0.475332 -0.463372 -0.747895 0.083403 0.137550 -0.986977 -0.330148 0.323763 -0.886668 -0.623348 0.142615 -0.768829 -0.719796 -0.682066 -0.129147 -0.158643 -0.736854 0.657175 -0.011219 -0.473087 0.880944 -0.088985 -0.139975 0.986148 -0.196495 0.257927 0.945972 -0.092068 0.613843 0.784041 0.695526 0.696114 0.177959 0.809573 -0.141512 -0.569707 0.541048 -0.177158 -0.822120 0.119816 0.420785 -0.899213 -0.321571 0.558865 -0.764370 -0.616328 0.350431 -0.705221 -0.664621 -0.652929 -0.363267 -0.117105 -0.910226 0.397209 -0.014953 -0.708986 0.705064 -0.122045 -0.421504 0.898576 -0.226068 -0.063990 0.972008 -0.101966 0.304230 0.947126 0.638774 0.642739 0.422913 0.812943 0.178756 -0.554230 0.555937 0.152584 -0.817100 0.140272 0.674587 -0.724746 -0.308537 0.758684 -0.573763 -0.614593 0.546718 -0.568660 -0.637083 -0.518172 -0.570634 -0.084923 -0.992459 0.088389 -0.015912 -0.889196 0.457250 -0.138941 -0.673844 0.725693 -0.229866 -0.382725 0.894809 -0.085234 -0.046120 0.995293 0.613605 0.485222 0.622935 0.786161 0.449132 -0.424537 0.538754 0.464061 -0.703130 0.165912 0.860092 -0.482406 -0.267939 0.901893 -0.338817 -0.594114 0.707018 -0.383606 -0.640703 -0.297959 -0.707616 -0.090581 -0.970323 -0.224205 -0.038646 -0.985008 0.168123 -0.161282 -0.859188 0.485575 -0.230443 -0.651104 0.723160 -0.061425 -0.381222 0.922441 0.617466 0.256177 0.743713 0.762438 0.609139 -0.218262 0.521152 0.694813 -0.495616 0.214470 0.954500 -0.207203 -0.189266 0.978449 -0.082564 -0.538270 0.825062 -0.171866 -0.660981 -0.031720 -0.749732 -0.146796 -0.855040 -0.497350 -0.098540 -0.987474 -0.123226 -0.207293 -0.955018 0.212062 -0.249688 -0.836418 0.487914 -0.052734 -0.657454 0.751647 0.636871 -0.006910 0.770939 0.764508 0.644600 0.004213 0.529012 0.813303 -0.242249 0.293842 0.953852 0.061827 -0.074276 0.982102 0.173088 -0.442234 0.895166 0.055741 -0.676564 0.240387 -0.696042 -0.245900 -0.668430 -0.701950 -0.196570 -0.903163 -0.381649 -0.285214 -0.956798 -0.056490 -0.300833 -0.925648 0.229509 -0.075800 -0.850602 0.520317 0.653964 -0.270131 0.706655 0.796565 0.573486 0.191308 0.572402 0.819957 0.005157 0.401644 0.868319 0.291040 0.068695 0.911981 0.404441 -0.310177 0.906122 0.287633 -0.670348 0.486868 -0.559995 -0.366719 -0.433435 -0.823196 -0.322201 -0.747129 -0.581365 -0.392735 -0.873905 -0.286444 -0.386171 -0.922331 -0.013319 -0.137827 -0.953516 0.267977 0.652264 -0.506422 0.563993 0.849294 0.427086 0.310319 0.647166 0.733895 0.206335 0.528388 0.716133 0.456025 0.228985 0.775270 0.588661 -0.150538 0.849980 0.504849 -0.631494 0.685790 -0.361811 -0.485417 -0.172502 -0.857096 -0.459521 -0.538539 -0.706269 -0.520157 -0.724043 -0.452989 -0.499210 -0.840830 -0.209273 -0.237180 -0.971005 0.029914 0.619835 -0.696002 0.362473 0.907382 0.238899 0.345812 0.740839 0.581805 0.335649 0.661008 0.519398 0.541566 0.395068 0.586098 0.707397 0.026958 0.728070 0.684972 -0.553869 0.823183 -0.124898 -0.582452 0.092535 -0.807581 -0.592141 -0.298471 -0.748521 -0.654163 -0.529072 -0.540512 -0.628114 -0.701832 -0.336013 -0.365868 -0.915916 -0.165043 0.550003 -0.825790 0.124773 0.954620 0.040295 0.295090 0.837733 0.392236 0.379940 0.785282 0.301968 0.540506 0.554845 0.363153 0.748510 0.211661 0.550361 0.807653 -0.435294 0.891579 0.124922 -0.643814 0.341234 -0.684882 -0.705201 -0.048620 -0.707339 -0.780316 -0.312743 -0.541571 -0.758324 -0.529683 -0.379974 -0.511802 -0.806793 -0.295202 0.440547 -0.888971 -0.125098 0.976221 -0.140690 0.164922 0.921790 0.193392 0.336010 0.887133 0.088433 0.452962 0.696326 0.128172 0.706188 0.392562 0.333556 0.857109 -0.277457 0.890024 0.361767 -0.660452 0.555846 -0.504816 -0.785857 0.189830 -0.588552 -0.884377 -0.099512 -0.456042 -0.874093 -0.351030 -0.335768 -0.660195 -0.666649 -0.346007 0.293205 -0.884534 -0.362809 0.959623 -0.279680 -0.030052 0.977780 0.012276 0.209275 0.953210 -0.096828 0.286381 0.808235 -0.095066 0.581135 0.559153 0.100129 0.822996 -0.085698 0.824032 0.560024 -0.629138 0.722096 -0.287686 -0.823943 0.397032 -0.404330 -0.952790 0.086373 -0.291087 -0.959031 -0.193933 -0.206518 -0.794145 -0.522371 -0.310583 0.112836 -0.817787 -0.564351 0.894817 -0.356921 -0.268160 0.991899 -0.126332 0.013314 0.971244 -0.231314 0.056380 0.880493 -0.281754 0.381245 0.702240 -0.121963 0.701416 0.130801 0.706014 0.696014 -0.553780 0.830790 -0.055816 -0.813085 0.555850 -0.172987 -0.972950 0.222560 -0.061926 -0.996262 -0.086217 -0.005383 -0.894613 -0.403668 -0.191622 -0.092698 -0.701115 -0.706997 0.774628 -0.359073 -0.520594 0.952137 -0.201818 -0.229576 0.930745 -0.297791 -0.212214 0.904454 -0.408539 0.122712 0.814243 -0.300828 0.496500 0.358455 0.556303 0.749691 -0.445467 0.878644 0.171885 -0.752472 0.653422 0.082615 -0.933827 0.291737 0.207020 -0.968885 -0.051968 0.241995 -0.940227 -0.340517 -0.004596 -0.312202 -0.554757 -0.771216 0.595656 -0.282352 -0.751978 0.849252 -0.201404 -0.488065 0.824741 -0.289563 -0.485753 0.872333 -0.458907 -0.168640 0.885692 -0.407010 0.223367 0.578510 0.406062 0.707418 -0.315638 0.867956 0.383437 -0.646923 0.683244 0.338626 -0.827832 0.286791 0.482126 -0.862485 -0.104101 0.495260 -0.908730 -0.356160 0.217623 -0.530609 -0.406732 -0.743655 0.360577 -0.136959 -0.922619 0.679070 -0.125485 -0.723269 0.653065 -0.216091 -0.725817 0.778003 -0.430319 -0.457753 0.901919 -0.422575 -0.089292 0.767393 0.292290 0.570678 -0.166978 0.805490 0.568599 -0.502937 0.646691 0.573450 -0.654552 0.216453 0.724368 -0.671657 -0.234550 0.702754 -0.782337 -0.456681 0.423546 -0.726815 -0.288710 -0.623207 0.082158 0.051043 -0.995311 0.446321 0.008140 -0.894836 0.426142 -0.104461 -0.898605 0.621548 -0.340820 -0.705351 0.846778 -0.353056 -0.397892 0.897673 0.249118 0.363487 0.003704 0.708340 0.705862 -0.323709 0.557548 0.764430 -0.424709 0.107355 0.898942 -0.410513 -0.405035 0.816961 -0.561612 -0.615172 0.553313 -0.875957 -0.231767 -0.423063 -0.213175 0.240950 -0.946837 0.168212 0.164439 -0.971939 0.165832 0.007681 -0.986124 0.415460 -0.225851 -0.881127 0.717408 -0.230055 -0.657572 0.950478 0.282525 0.129506 0.187363 0.610341 0.769661 -0.115962 0.447172 0.886899 -0.161340 -0.002803 0.986895 -0.117438 -0.556605 0.822435 -0.282822 -0.771878 0.569400 -0.950451 -0.255044 -0.177753 -0.486331 0.386530 -0.783631 -0.125399 0.299377 -0.945859 -0.099271 0.086032 -0.991334 0.184430 -0.125017 -0.974862 0.531335 -0.097715 -0.841508 0.923745 0.372281 -0.090018 0.358311 0.546736 0.756765 0.100652 0.354707 0.929544 0.105852 -0.079731 0.991180 0.163366 -0.642642 0.748547 -0.007388 -0.870705 0.491749 -0.934891 -0.349518 0.061770 -0.701450 0.456710 -0.547160 -0.400749 0.378274 -0.834451 -0.342851 0.111275 -0.932776 -0.043669 -0.066302 -0.996844 0.317286 0.006568 -0.948307 0.829849 0.486748 -0.272813 0.490724 0.535341 0.687460 0.299559 0.308954 0.902669 0.349986 -0.103822 0.930984 0.407465 -0.650702 0.640749 0.223797 -0.896599 0.382133 -0.838944 -0.480188 0.256110 -0.845372 0.445786 -0.294316 -0.631992 0.386977 -0.671442 -0.546773 0.080272 -0.833424 -0.246449 -0.060493 -0.967266 0.102723 0.062628 -0.992736 0.686049 0.598860 -0.413163 0.569684 0.572986 0.589192 0.459295 0.318286 0.829302 0.553169 -0.072355 0.829921 0.610076 -0.593281 0.525191 0.411167 -0.865939 0.284765 -0.689236 -0.604698 0.399118 -0.927317 0.368463 -0.065707 -0.806837 0.330930 -0.489387 -0.702017 0.000757 -0.712160 -0.409912 -0.105649 -0.905986 -0.092320 0.065000 -0.993606 0.508496 0.689937 -0.515188 0.591472 0.645531 0.483166 0.568575 0.376033 0.731657 0.706922 0.006953 0.707258 0.771488 -0.488587 0.407541 0.570025 -0.795317 0.206258 -0.507180 -0.699704 0.503173 -0.960268 0.248226 0.127551 -0.923893 0.227220 -0.307885 -0.805677 -0.115541 -0.580977 -0.526876 -0.193120 -0.827712 -0.255140 0.017346 -0.966749 0.309736 0.748926 -0.585810 0.558566 0.736299 0.381926 0.623868 0.469072 0.625107 0.808888 0.122424 0.575076 0.890963 -0.352166 0.286643 0.707533 -0.693476 0.135966 -0.305930 -0.756101 0.578549 -0.950865 0.107610 0.290302 -0.986364 0.094353 -0.134843 -0.857514 -0.256348 -0.446045 -0.594593 -0.311359 -0.741293 -0.378641 -0.071834 -0.922752 0.099238 0.768764 -0.631786 0.476465 0.829526 0.291321 0.625914 0.582832 0.518207 0.859078 0.262092 0.439650 0.967208 -0.195853 0.161711 0.822012 -0.565936 0.063352 -0.094672 -0.770547 0.630313 -0.901963 -0.034579 0.430426 -0.998262 -0.051816 0.028087 -0.857800 -0.409733 -0.310320 -0.612373 -0.447861 -0.651475 -0.458537 -0.191692 -0.867755 -0.114406 0.745561 -0.656544 0.352297 0.911109 0.213932 0.577482 0.702944 0.415192 0.857998 0.414126 0.303874 0.999009 -0.029183 0.033591 0.908310 -0.417986 -0.016164 0.118726 -0.741893 0.659924 -0.816701 -0.164245 0.553194 -0.963256 -0.198597 0.180822 -0.807114 -0.563717 -0.175472 -0.580297 -0.590208 -0.561169 -0.491459 -0.330812 -0.805625 -0.322126 0.677377 -0.661359 0.193708 0.969273 0.151612 0.481999 0.816165 0.318672 0.806419 0.566589 0.169308 0.985654 0.138758 -0.096081 0.961346 -0.255422 -0.102827 0.325281 -0.668972 0.668333 -0.699627 -0.271726 0.660823 -0.884985 -0.335187 0.323188 -0.707254 -0.705651 -0.042985 -0.501356 -0.725489 -0.471495 -0.477585 -0.476615 -0.738073 -0.513247 0.562659 -0.648068 0.010860 0.994447 0.104680 0.345094 0.909926 0.230098 0.705994 0.707216 0.037664 0.927437 0.298568 -0.225206 0.976847 -0.085320 -0.196192 0.514463 -0.551766 0.656417 -0.556407 -0.349262 0.753941 -0.767765 -0.451855 0.454274 -0.562146 -0.822707 0.084525 -0.380503 -0.841301 -0.383967 -0.419158 -0.616043 -0.666931 -0.676114 0.406208 -0.614707 -0.183629 0.980234 0.073637 0.175133 0.972896 0.151003 0.560887 0.823105 -0.088900 0.826542 0.439773 -0.351323 0.951945 0.083343 -0.294712 0.675091 -0.394126 0.623632 -0.394650 -0.390187 0.831869 -0.617545 -0.539453 0.572389 -0.379071 -0.902609 0.203968 -0.224723 -0.926936 -0.300483 -0.320407 -0.737693 -0.594263 -0.798916 0.214465 -0.561906 -0.377448 0.924123 0.059422 -0.018072 0.996315 0.083842 0.378219 0.902215 -0.207266 0.687785 0.551714 -0.471767 0.886026 0.240398 -0.396443 0.795821 -0.202801 0.570562 -0.223531 -0.390003 0.893270 -0.442305 -0.589649 0.675781 -0.168721 -0.935095 0.311658 -0.043860 -0.973944 -0.222509 -0.189168 -0.832026 -0.521486 -0.871435 -0.001658 -0.490507 -0.557636 0.827822 0.061255 -0.222018 0.974573 0.030246 0.168499 0.934389 -0.313888 0.518986 0.624677 -0.583466 0.781361 0.374644 -0.499115 0.866979 0.011594 0.498210 -0.054206 -0.346054 0.936647 -0.252327 -0.595917 0.762374 0.055290 -0.913247 0.403638 0.151338 -0.976671 -0.152348 -0.033832 -0.891936 -0.450894 -0.887570 -0.227103 -0.400805 -0.713158 0.696560 0.078807 -0.423582 0.905825 -0.007684 -0.054763 0.912628 -0.405106 0.331018 0.650958 -0.683140 0.643767 0.475653 -0.599431 0.882276 0.235108 0.407816 0.101236 -0.259390 0.960452 -0.059792 -0.554663 0.829924 0.277274 -0.834340 0.476442 0.348832 -0.932757 -0.090991 0.135541 -0.913871 -0.382712 -0.843178 -0.447494 -0.297995 -0.835618 0.538220 0.109830 -0.609564 0.792200 -0.029169 -0.276257 0.834269 -0.477155 0.136897 0.626215 -0.767538 0.482403 0.534235 -0.694176 0.838675 0.452559 0.303009 0.230699 -0.134348 0.963706 0.121963 -0.465614 0.876544 0.481044 -0.700775 0.526793 0.536643 -0.842862 -0.039977 0.309098 -0.896452 -0.317540 -0.742036 -0.644791 -0.183379 -0.919751 0.362404 0.150738 -0.767846 0.639682 -0.034926 -0.479851 0.701344 -0.527124 -0.049137 0.550238 -0.833561 0.309356 0.544476 -0.779644 0.738840 0.647522 0.186629 0.322764 0.020845 0.946250 0.279287 -0.332622 0.900756 0.651517 -0.519801 0.552570 0.703776 -0.710421 -0.001104 0.478651 -0.839646 -0.256686 -0.590989 -0.804315 -0.061716 -0.963321 0.178276 0.200575 -0.889225 0.456825 -0.024290 -0.650547 0.520903 -0.552674 -0.212927 0.427022 -0.878814 0.138259 0.504738 -0.852129 0.589762 0.805121 0.062933 0.370001 0.194156 0.908517 0.400535 -0.163969 0.901491 0.776410 -0.302901 0.552665 0.840301 -0.541570 0.024403 0.636192 -0.745021 -0.200510 -0.400993 -0.913996 0.061766 -0.966471 -0.005346 0.256720 -0.967151 0.254199 0.001214 -0.775923 0.304334 -0.552561 -0.342147 0.264919 -0.901528 -0.016740 0.417580 -0.908486 0.402393 0.913304 -0.062901 0.367990 0.372084 0.852136 0.476326 0.029033 0.878789 0.847300 -0.064883 0.527137 0.937943 -0.345024 0.034959 0.773836 -0.615199 -0.150692 -0.187242 -0.965065 0.183275 -0.930910 -0.180612 0.317468 -0.998268 0.043221 0.039913 -0.847417 0.066193 -0.526785 -0.427700 0.075648 -0.900750 -0.143286 0.290071 -0.946218 0.191332 0.963636 -0.186541 0.316815 0.540144 0.779662 0.501056 0.232529 0.833591 0.860608 0.177840 0.477208 0.990851 -0.131660 0.029656 0.884051 -0.454447 -0.109230 0.034255 -0.954039 0.297720 -0.859292 -0.339772 0.382325 -0.982217 -0.164359 0.090747 -0.861209 -0.177004 -0.476433 -0.464097 -0.127131 -0.876614 -0.231448 0.132668 -0.963759 -0.027400 0.952628 -0.302902 0.221374 0.684896 0.694198 0.473929 0.431621 0.767525 0.817786 0.408808 0.405096 0.996268 0.085970 0.007647 0.959792 -0.269390 -0.078915 0.246392 -0.882098 0.401490 -0.755743 -0.475134 0.450667 -0.921556 -0.357170 0.152195 -0.818539 -0.408659 -0.403722 -0.450446 -0.328998 -0.829975 -0.275258 -0.041790 -0.960462 -0.237300 0.881594 -0.408021 0.089976 0.795364 0.599416 0.398222 0.612114 0.683180 0.724946 0.613064 0.314015 0.955012 0.295039 -0.030073 0.995752 -0.068871 -0.061105 0.434905 -0.755673 0.489710 -0.626064 -0.579769 0.521452 -0.821594 -0.524879 0.222452 -0.725539 -0.613577 -0.311635 -0.389940 -0.516447 -0.762384 -0.272505 -0.219881 -0.936693 -0.423587 0.756722 -0.497942 -0.066285 0.864061 0.499003 0.281452 0.761800 0.583477 0.592343 0.778537 0.207386 0.871866 0.482627 -0.083195 0.989063 0.135359 -0.058585 0.584771 -0.584801 0.562185 -0.478755 -0.646878 0.593585 -0.690458 -0.658284 0.299884 -0.592237 -0.779492 -0.204080 -0.289459 -0.677812 -0.675858 -0.225720 -0.388437 -0.893402 -0.573343 0.587832 -0.570730 -0.234967 0.887454 0.396505 0.133990 0.871494 0.471747 0.432581 0.897184 0.089074 0.755168 0.637998 -0.150599 0.940805 0.330946 -0.073221 0.689401 -0.382765 0.614993 -0.324351 -0.671196 0.666552 -0.538657 -0.750143 0.383581 -0.431597 -0.898080 -0.084715 -0.158383 -0.804474 -0.572483 -0.140498 -0.536726 -0.831977 -0.678692 0.387679 -0.623765 -0.403857 0.866087 0.294606 -0.032358 0.935703 0.351301 0.259702 0.964968 -0.037296 0.615479 0.754110 -0.229137 0.855677 0.507042 -0.103565 0.744267 -0.163413 0.647583 -0.173940 -0.652614 0.737455 -0.377784 -0.797279 0.470771 -0.257846 -0.965238 0.042793 -0.007524 -0.890858 -0.454219 -0.023892 -0.656352 -0.754076 -0.735122 0.169762 -0.656336 -0.562464 0.803224 0.196124 -0.205056 0.952507 0.225128 0.088021 0.981687 -0.168945 0.466256 0.825646 -0.317668 0.742833 0.652390 -0.150289 0.746709 0.058696 0.662556 -0.041084 -0.592066 0.804842 -0.221370 -0.798226 0.560205 -0.085002 -0.980898 0.174967 0.152203 -0.933956 -0.323359 0.114788 -0.741508 -0.661053 -0.741687 -0.052523 -0.668687 -0.701892 0.704800 0.102979 -0.372446 0.923068 0.096070 -0.069929 0.950285 -0.303427 0.320709 0.851656 -0.414521 0.613416 0.760434 -0.213217 0.702796 0.273066 0.656896 0.062362 -0.493418 0.867554 -0.082564 -0.754527 0.651055 0.073588 -0.947914 0.309910 0.309840 -0.933380 -0.181110 0.266550 -0.789148 -0.553350 -0.701817 -0.268011 -0.660017 -0.816231 0.577501 0.016117 -0.524808 0.850562 -0.033484 -0.202208 0.875334 -0.439207 0.192106 0.833955 -0.517314 0.480268 0.827719 -0.290213 0.616151 0.469814 0.632165 0.126898 -0.364664 0.922452 0.027258 -0.671277 0.740706 0.206336 -0.871091 0.445675 0.454372 -0.890367 -0.028154 0.421720 -0.797977 -0.430563 -0.620050 -0.467273 -0.630234 -0.901276 0.428637 -0.063028 -0.653298 0.739654 -0.161600 -0.298033 0.762208 -0.574643 0.094730 0.775532 -0.624160 0.358622 0.852382 -0.380571 0.493395 0.641922 0.586939 0.142405 -0.213382 0.966534 0.095872 -0.553788 0.827120 0.302449 -0.755975 0.580540 0.575080 -0.806931 0.134705 0.569407 -0.769032 -0.290459 -0.501775 -0.642996 -0.578600 -0.954481 0.265821 -0.135295 -0.750606 0.595454 -0.286401 -0.347238 0.616292 -0.706831 0.041903 0.681258 -0.730843 0.263725 0.835563 -0.481958 0.343059 0.784789 0.516155 0.101932 -0.048402 0.993613 0.112908 -0.408762 0.905630 0.351348 -0.608164 0.711822 0.659019 -0.686311 0.307687 0.695973 -0.706635 -0.127622 -0.352280 -0.789178 -0.503088 -0.973958 0.095881 -0.205459 -0.809200 0.423659 -0.407074 -0.339267 0.443530 -0.829565 0.046425 0.557929 -0.828589 0.211701 0.780667 -0.587997 0.175322 0.893144 0.414193 0.002360 0.119379 0.992846 0.070352 -0.244664 0.967052 0.342645 -0.434004 0.833208 0.690270 -0.533042 0.489279 0.783596 -0.617784 0.065723 -0.179015 -0.899335 -0.398937 -0.955813 -0.076764 -0.283775 -0.819337 0.231468 -0.524509 -0.265204 0.251796 -0.930734 0.118200 0.415043 -0.902091 0.218617 0.693673 -0.686312 0.006178 0.961749 0.273862 -0.153687 0.277259 0.948424 -0.036200 -0.071921 0.996753 0.267535 -0.241885 0.932693 0.651380 -0.353554 0.671344 0.809469 -0.508042 0.294368 0.003773 -0.966667 -0.256009 -0.888914 -0.254005 -0.381200 -0.767976 0.027319 -0.639895 -0.122537 0.052213 -0.991090 0.257263 0.265611 -0.929121 0.294807 0.584789 -0.755718 -0.140017 0.985976 0.090813 -0.351398 0.410603 0.841382 -0.201421 0.096395 0.974750 0.123827 -0.043425 0.991353 0.528280 -0.157594 0.834317 0.746784 -0.377987 0.547210 0.165174 -0.984331 -0.061725 -0.750987 -0.441119 -0.491359 -0.638966 -0.179968 -0.747886 0.077463 -0.141054 -0.986967 0.445496 0.123980 -0.886658 0.435248 0.468434 -0.768849 -0.230707 0.964400 -0.129258 -0.558875 0.505812 0.657125 -0.404162 0.246278 0.880908 -0.076750 0.147088 0.986141 0.321657 0.041249 0.945957 0.577662 -0.227164 0.784030 0.255173 -0.950363 0.178037 -0.527261 -0.630454 -0.569669 -0.423864 -0.380047 -0.822134 0.304533 -0.314183 -0.899194 0.644872 -0.000946 -0.764290 0.611741 0.358526 -0.705147 -0.233183 0.902029 -0.363277 -0.729704 0.556551 0.397220 -0.606462 0.367491 0.705091 -0.304022 0.316460 0.898567 0.057433 0.227750 0.972024 0.314217 -0.063870 0.947200 0.237271 -0.874510 0.423007 -0.251493 -0.793471 -0.554215 -0.145761 -0.557767 -0.817098 0.514068 -0.458761 -0.724757 0.811322 -0.112148 -0.573742 0.780781 0.258902 -0.568640 -0.130061 0.810843 -0.570629 -0.817029 0.569791 0.088335 -0.762103 0.458402 0.457238 -0.514105 0.457241 0.725690 -0.216601 0.390387 0.894809 0.002546 0.096808 0.995300 0.113296 -0.774147 0.622784 -0.003962 -0.905361 -0.424624 0.132592 -0.698552 -0.703167 0.661903 -0.573729 -0.482411 0.914959 -0.219013 -0.338944 0.909272 0.160854 -0.383862 0.062404 0.703858 -0.707594 -0.794954 0.563740 -0.224155 -0.833703 0.526002 0.168111 -0.663443 0.569277 0.485558 -0.448569 0.525148 0.723191 -0.299291 0.243846 0.922477 -0.086873 -0.662877 0.743672 0.146182 -0.964857 -0.218360 0.341092 -0.798737 -0.495657 0.719384 -0.662994 -0.207184 0.941999 -0.325302 -0.082561 0.983652 0.053645 -0.171902 0.302765 0.588248 -0.749866 -0.667083 0.554715 -0.497284 -0.805901 0.579090 -0.123203 -0.723424 0.657035 0.212044 -0.599496 0.634479 0.487894 -0.542963 0.374463 0.751644 -0.324429 -0.547951 0.771035 0.175872 -0.984404 0.004222 0.439763 -0.864827 -0.242245 0.679135 -0.731404 0.061840 0.887682 -0.426660 0.173153 0.996355 -0.064437 0.055899 0.546490 0.465736 -0.696017 -0.455966 0.547003 -0.702056 -0.683901 0.621757 -0.381703 -0.686005 0.725399 -0.056501 -0.651241 0.723346 0.229467 -0.698802 0.490934 0.520250 -0.560931 -0.431273 0.706654 0.098424 -0.976566 0.191395 0.423929 -0.905681 0.005214 0.551154 -0.781995 0.291055 0.755423 -0.515506 0.404463 0.939790 -0.184475 0.287688 0.756906 0.337076 -0.559887 -0.191996 0.534242 -0.823240 -0.485922 0.652574 -0.581401 -0.560455 0.777069 -0.286451 -0.605690 0.795589 -0.013316 -0.756880 0.596089 0.267973 -0.764708 -0.311719 0.563962 -0.054761 -0.949046 0.310342 0.312008 -0.927397 0.206361 0.355988 -0.815666 0.456028 0.556891 -0.585958 0.588664 0.811361 -0.294690 0.504828 0.909669 0.203979 -0.361793 0.093350 0.506713 -0.857046 -0.236600 0.667270 -0.706238 -0.366950 0.812495 -0.452990 -0.478576 0.852742 -0.209275 -0.722325 0.690906 0.029926 -0.912678 -0.188803 0.362452 -0.246806 -0.905279 0.345770 0.133434 -0.932499 0.335622 0.119308 -0.832151 0.541563 0.310046 -0.635182 0.707401 0.617068 -0.387369 0.684962 0.989825 0.068073 -0.124947 0.371396 0.458166 -0.807557 0.037609 0.662061 -0.748506 -0.131097 0.831061 -0.540511 -0.293736 0.894879 -0.336023 -0.610254 0.774819 -0.165061 -0.990158 -0.063403 0.124765 -0.442406 -0.846879 0.295081 -0.079179 -0.921621 0.379929 -0.131126 -0.831060 0.540504 0.037092 -0.662139 0.748462 0.370811 -0.458573 0.807595 0.989765 -0.068817 0.125019 0.617438 0.386957 -0.684861 0.310499 0.635017 -0.707350 0.119324 0.832144 -0.541570 -0.079550 0.921585 -0.379938 -0.442798 0.846647 -0.295160 -0.990147 0.062938 -0.125093 -0.609946 -0.775092 0.164920 -0.293414 -0.894985 0.336021 -0.366985 -0.812495 0.452961 -0.237155 -0.667124 0.706189 0.092587 -0.506750 0.857107 0.909580 -0.204693 0.361615 0.811557 0.294138 -0.504835 0.557290 0.585687 -0.588557 0.356002 0.815648 -0.456050 0.133057 0.932500 -0.335767 -0.247233 0.905078 -0.345992 -0.912625 0.188420 -0.362785 -0.722050 -0.691186 -0.030089 -0.478281 -0.852913 0.209253 -0.560469 -0.777086 0.286377 -0.486473 -0.652345 0.581197 -0.192908 -0.534118 0.823107 0.756523 -0.337795 0.559971 0.939904 0.183679 -0.287825 0.755810 0.515005 -0.404376 0.551193 0.781953 -0.291094 0.311595 0.927489 -0.206573 -0.055273 0.948910 -0.310669 -0.764640 0.311197 -0.564343 -0.756557 -0.596436 -0.268115 -0.605377 -0.795827 0.013326 -0.685945 -0.725466 0.056380 -0.684256 -0.621662 0.381221 -0.456759 -0.547214 0.701376 0.545797 -0.466267 0.696204 0.996380 0.064129 -0.055801 0.887937 0.426197 -0.172988 0.679218 0.731320 -0.061923 0.423426 0.905915 -0.005376 0.097663 0.976597 -0.191624 -0.560848 0.430718 -0.707058 -0.698261 -0.491352 -0.520581 -0.650837 -0.723680 -0.229561 -0.723261 -0.657160 -0.212212 -0.806016 -0.579039 0.122690 -0.667607 -0.554838 0.496443 0.302658 -0.588612 0.749623 0.983641 -0.053418 0.172036 0.942092 0.325000 0.082685 0.719566 0.662847 0.207026 0.439409 0.865069 0.242024 0.175171 0.984528 -0.004534 -0.324322 0.547810 -0.771180 -0.542282 -0.374695 -0.752020 -0.599007 -0.634790 -0.488091 -0.663147 -0.569456 -0.485753 -0.833596 -0.526008 -0.168619 -0.795315 -0.563535 0.223390 0.062410 -0.704024 0.707429 0.909485 -0.160601 0.383464 0.915151 0.218669 0.338647 0.662277 0.573531 0.482132 0.341112 0.798966 0.495273 0.145940 0.965055 0.217649 -0.086933 0.662901 -0.743643 -0.298900 -0.243773 -0.922623 -0.448209 -0.525333 -0.723279 -0.513669 -0.457535 -0.725814 -0.761642 -0.458639 -0.457768 -0.816926 -0.569792 -0.089266 -0.130492 -0.810744 0.570672 0.781105 -0.258177 0.568524 0.811567 0.112174 0.573390 0.514738 0.458624 0.724368 0.132769 0.698931 0.702757 -0.004170 0.905855 0.423568 0.113280 0.773878 -0.623122 0.002961 -0.096628 -0.995316 -0.216217 -0.390574 -0.894820 -0.303537 -0.316851 -0.898594 -0.605892 -0.367895 -0.705371 -0.729145 -0.556790 -0.397910 -0.233098 -0.901951 0.363524 0.611694 -0.357321 0.705799 0.644797 0.001574 0.764353 0.305383 0.314181 0.898906 -0.145417 0.558107 0.816927 -0.251781 0.794076 0.553218 0.237295 0.874413 -0.423194 0.315096 0.064163 -0.946888 0.058187 -0.227914 -0.971941 -0.076291 -0.147484 -0.986118 -0.403512 -0.246846 -0.881048 -0.558098 -0.506216 -0.657474 -0.230527 -0.964396 0.129603 0.434977 -0.467370 0.769650 0.445261 -0.123135 0.886893 0.078238 0.141157 0.986891 -0.423363 0.380072 0.822380 -0.527225 0.630897 0.569212 0.254772 0.950504 -0.177858 0.578180 0.227763 -0.783475 0.322215 -0.041176 -0.945771 0.124180 0.042994 -0.991328 -0.200533 -0.097135 -0.974860 -0.350359 -0.411201 -0.841524 -0.139630 -0.986085 -0.090225 0.294355 -0.583808 0.756653 0.256881 -0.264622 0.929509 -0.121952 -0.051872 0.991180 -0.638222 0.179786 0.748565 -0.750401 0.441627 0.491796 0.164251 0.984480 0.061814 0.746375 0.379046 -0.547036 0.528098 0.157907 -0.834373 0.267761 0.241300 -0.932780 -0.035444 0.070984 -0.996848 -0.152788 -0.278077 -0.948330 0.006635 -0.962044 -0.272814 0.218116 -0.692702 0.687451 0.117687 -0.413934 0.902667 -0.264932 -0.251199 0.930973 -0.767289 -0.027527 0.640711 -0.888409 0.254464 0.382069 0.003871 0.966620 0.256186 0.808650 0.509282 -0.294479 0.650949 0.353880 -0.671591 0.342895 0.433362 -0.833439 0.070827 0.243648 -0.967274 0.002871 -0.120314 -0.992732 0.175649 -0.893608 -0.413052 0.211344 -0.779834 0.589231 0.045975 -0.556882 0.829318 -0.339256 -0.442858 0.829929 -0.818856 -0.231665 0.525173 -0.955513 0.076926 0.284741 -0.179243 0.899271 0.398977 0.782804 0.618791 -0.065690 0.690026 0.533251 -0.489395 0.351673 0.607576 -0.712164 0.113432 0.407809 -0.905994 0.102401 0.047450 -0.993611 0.343210 -0.785325 -0.515240 0.263357 -0.834977 0.483174 0.041405 -0.680401 0.731669 -0.347435 -0.615677 0.707270 -0.808865 -0.423825 0.407566 -0.973767 -0.095990 0.206309 -0.352267 0.789088 0.503238 0.695079 0.707533 0.127522 0.658738 0.686493 -0.307883 0.302789 0.755495 -0.580987 0.096248 0.552855 -0.827700 0.142666 0.212297 -0.966735 0.493694 -0.642705 -0.585830 0.358308 -0.851919 0.381902 0.094247 -0.774835 0.625099 -0.298427 -0.761719 0.575088 -0.750482 -0.595498 0.286633 -0.954355 -0.265978 0.135877 -0.501790 0.643009 0.578573 0.568673 0.769624 0.290325 0.574907 0.807029 -0.134853 0.206744 0.870794 -0.446067 0.027574 0.670549 -0.741352 0.127013 0.363735 -0.922803 0.616248 -0.470409 -0.631627 0.480187 -0.827345 0.291411 0.191816 -0.833439 0.518253 -0.202585 -0.875025 0.439649 -0.653241 -0.739680 0.161710 -0.901121 -0.428903 0.063422 -0.620105 0.467273 0.630180 0.421058 0.798409 0.430410 0.454286 0.890413 0.028094 0.073982 0.947763 -0.310278 -0.082055 0.754093 -0.651622 0.062766 0.492733 -0.867914 0.702945 -0.273662 -0.656488 0.613188 -0.760354 0.214154 0.320306 -0.851425 0.415305 -0.070319 -0.950131 0.303819 -0.524807 -0.850560 0.033546 -0.816107 -0.577679 -0.015983 -0.701809 0.268115 0.659983 0.266037 0.789463 0.553147 0.309702 0.933461 0.180930 -0.084611 0.980868 -0.175325 -0.220812 0.797987 -0.560767 -0.040546 0.591552 -0.805247 0.746961 -0.059315 -0.662216 0.742572 -0.652507 0.151070 0.465829 -0.825619 0.318366 0.087629 -0.981659 0.169312 -0.372522 -0.923039 -0.096057 -0.701831 -0.704850 -0.103048 -0.741751 0.052699 0.668602 0.114530 0.741677 0.660907 0.152168 0.934010 0.323220 -0.257443 0.965331 -0.043121 -0.377141 0.797306 -0.471242 -0.173224 0.652403 -0.737810 0.744470 0.162845 -0.647492 0.855432 -0.507344 0.104110 0.615049 -0.754285 0.229716 0.259344 -0.965051 0.037661 -0.205149 -0.952487 -0.225128 -0.562446 -0.803183 -0.196345 -0.735245 -0.169566 0.656249 -0.023982 0.656470 0.753971 -0.007501 0.890916 0.454107 -0.431355 0.898227 0.084387 -0.538365 0.749897 -0.384472 -0.324010 0.670468 -0.667450 0.690450 0.382219 -0.614156 0.940702 -0.330997 0.074308 0.754974 -0.638021 0.151467 0.432242 -0.897371 -0.088838 -0.032572 -0.935683 -0.351335 -0.403809 -0.866127 -0.294556 -0.679097 -0.387530 0.623417 -0.140706 0.536954 0.831795 -0.158359 0.804569 0.572357 -0.592051 0.779647 0.204023 -0.690359 0.658136 -0.300436 -0.478708 0.646388 -0.594156 0.584308 0.584602 -0.562872 0.989051 -0.135035 0.059536 0.871893 -0.482442 0.083983 0.592255 -0.778668 -0.207145 0.133910 -0.871486 -0.471783 -0.234842 -0.887468 -0.396547 -0.573319 -0.587723 0.570864 -0.226049 0.388542 0.893273 -0.289445 0.677845 0.675831 -0.725453 0.613720 0.311555 -0.821428 0.525100 -0.222544 -0.625751 0.580035 -0.521531 0.435089 0.755533 -0.489763 0.995771 0.068730 0.060966 0.954945 -0.295259 0.030046 0.724881 -0.613190 -0.313918 0.281494 -0.761830 -0.583418 -0.066259 -0.864005 -0.499104 -0.423684 -0.756648 0.497972 -0.272455 0.220078 0.936661 -0.389885 0.516544 0.762346 -0.818521 0.408787 0.403629 -0.921485 0.357165 -0.152637 -0.755499 0.474926 -0.451295 0.247045 0.882171 -0.400927 0.959743 0.269405 0.079457 0.996272 -0.085963 -0.007194 0.817733 -0.408944 -0.405064 0.398147 -0.612179 -0.683166 0.090103 -0.795390 -0.599364 -0.237561 -0.881602 0.407851 -0.275496 0.041993 0.960385 -0.450549 0.329127 0.829868 -0.861188 0.177032 0.476460 -0.982220 0.164229 -0.090953 -0.859258 0.339446 -0.382691 0.033825 0.953898 -0.298219 0.883890 0.454582 0.109966 0.990842 0.131863 -0.029051 0.860638 -0.177885 -0.477137 0.473815 -0.431694 -0.767554 0.221420 -0.684928 -0.694152 -0.027379 -0.952572 0.303079 -0.231729 -0.132654 0.963693 -0.464246 0.127183 0.876527 -0.847414 -0.066213 0.526788 -0.998264 -0.043349 -0.039873 -0.930935 0.180462 -0.317481 -0.187312 0.965064 -0.183208 0.773746 0.615306 0.150716 0.937897 0.345153 -0.034922 0.847299 0.064903 -0.527136 0.501068 -0.232614 -0.833559 0.316866 -0.540225 -0.779585 0.191296 -0.963641 0.186551 -0.143355 -0.289996 0.946230 -0.427774 -0.075576 0.900721 -0.775913 -0.304358 0.552563 -0.967115 -0.254338 -0.001210 -0.966478 0.005173 -0.256697 -0.401178 0.913907 -0.061896 0.636102 0.745106 0.200477 0.840231 0.541676 -0.024445 0.776407 0.302909 -0.552664 0.476381 -0.029122 -0.878756 0.368033 -0.372202 -0.852067 0.402444 -0.913268 0.063099 -0.016768 -0.417497 0.908524 -0.342174 -0.264827 0.901545 -0.650537 -0.520923 0.552667 -0.889169 -0.456943 0.024128 -0.963270 -0.178416 -0.200697 -0.591020 0.804287 0.061787 0.478527 0.839735 0.256626 0.703672 0.710524 0.001010 0.651498 0.519815 -0.552579 0.400640 0.163922 -0.901453 0.370081 -0.194228 -0.908469 0.589774 -0.805119 -0.062855 0.138266 -0.504577 0.852223 -0.212882 -0.426867 0.878900 -0.479850 -0.701310 0.527170 -0.767747 -0.639781 0.035278 -0.919772 -0.362521 -0.150324 -0.742362 0.644530 0.182974 0.308876 0.896580 0.317395 0.536529 0.842936 0.039930 0.481038 0.700802 -0.526763 0.279256 0.332512 -0.900806 0.322667 -0.020957 -0.946280 0.738883 -0.647513 -0.186492 0.309302 -0.544415 0.779708 -0.049242 -0.550240 0.833553 -0.276314 -0.834256 0.477145 -0.609506 -0.792233 0.029482 -0.835612 -0.538298 -0.109490 -0.842882 0.447758 0.298433 0.135509 0.914030 0.382344 0.348825 0.932779 0.090800 0.277325 0.834298 -0.476484 0.121979 0.465451 -0.876628 0.230719 0.134111 -0.963734 0.838568 -0.452691 -0.303107 0.482414 -0.534168 0.694220 0.136785 -0.626249 0.767529 -0.054815 -0.912615 0.405128 -0.423674 -0.905784 0.007445 -0.713144 -0.696532 -0.079181 -0.887522 0.227218 0.400845 -0.033536 0.891889 0.451009 0.151471 0.976638 0.152432 0.055356 0.913229 -0.403670 -0.059666 0.554651 -0.829941 0.101470 0.259362 -0.960435 0.882279 -0.235178 -0.407770 0.643789 -0.475682 0.599386 0.331012 -0.650894 0.683204 0.168441 -0.934350 0.314033 -0.221794 -0.974642 -0.029681 -0.557380 -0.828047 -0.060548 -0.871894 0.001147 0.489693 -0.189493 0.832178 0.521125 -0.043973 0.974007 0.222207 -0.168603 0.935127 -0.311626 -0.252303 0.595863 -0.762424 -0.054284 0.345766 -0.936749 0.867117 -0.011554 -0.497971 0.781406 -0.374545 0.499119 0.518954 -0.624709 0.583460 0.377964 -0.902284 0.207429 -0.017958 -0.996394 -0.082927 -0.377307 -0.924256 -0.058232 -0.798764 -0.213730 0.562402 -0.321027 0.738207 0.593288 -0.224917 0.927168 0.299618 -0.378867 0.902652 -0.204153 -0.442228 0.589580 -0.675892 -0.223516 0.389603 -0.893448 0.795723 0.202489 -0.570809 0.886016 -0.240236 0.396563 0.687682 -0.551862 0.471743 0.560577 -0.823282 0.089219 0.174951 -0.973048 -0.150230 -0.183747 -0.980275 -0.072786 -0.676359 -0.405650 0.614806 -0.419302 0.616643 0.666287 -0.380351 0.841682 0.383281 -0.561822 0.822900 -0.084806 -0.617449 0.539469 -0.572477 -0.394570 0.389951 -0.832018 0.675154 0.393854 -0.623736 0.951979 -0.083326 0.294607 0.826473 -0.439922 0.351298 0.705699 -0.707528 -0.037324 0.344699 -0.910234 -0.229469 0.010424 -0.994521 -0.104016 -0.513552 -0.561769 0.648598 -0.477538 0.477418 0.737583 -0.501088 0.726056 0.470908 -0.706993 0.705936 0.042601 -0.767687 0.451808 -0.454451 -0.556307 0.349078 -0.754100 0.514548 0.551449 -0.656615 0.976870 0.085312 0.196078 0.927391 -0.298697 0.225225 0.806265 -0.566917 -0.168945 0.481679 -0.816565 -0.318132 0.193309 -0.969434 -0.151091 -0.322544 -0.676995 0.661546 -0.491335 0.331609 0.805373 -0.580015 0.590860 0.560774 -0.806932 0.564081 0.175140 -0.884958 0.335093 -0.323360 -0.699601 0.271490 -0.660947 0.325365 0.668826 -0.668438 0.961341 0.255507 0.102667 0.985648 -0.138778 0.096122 0.857962 -0.414510 -0.303453 0.577671 -0.703307 -0.414313 0.352518 -0.911266 -0.212898 -0.114839 -0.745388 0.656664 -0.459141 0.192177 0.867328 -0.612677 0.448393 0.650824 -0.857712 0.410171 0.309983 -0.963250 0.198642 -0.180809 -0.816719 0.163774 -0.553307 0.118824 0.741906 -0.659891 0.908220 0.418178 0.016239 0.999011 0.029137 -0.033586 0.859128 -0.262684 -0.439200 0.626206 -0.583434 -0.517176 0.476717 -0.829870 -0.289927 0.098661 -0.768042 0.632753 -0.379576 0.072464 0.922318 -0.595190 0.312025 0.740533 -0.857616 0.256849 0.445558 -0.998263 0.051680 -0.028276 -0.901856 0.033695 -0.430721 -0.094466 0.770603 -0.630276 0.821927 0.566117 -0.062824 0.967237 0.195824 -0.161570 0.809141 -0.122996 -0.574598 0.624157 -0.469891 -0.624204 0.558695 -0.736841 -0.380691 0.309220 -0.748413 0.586737 -0.255774 -0.016457 0.966596 -0.527339 0.194045 0.827200 -0.805908 0.116121 0.580541 -0.986374 -0.094685 0.134540 -0.950667 -0.108713 -0.290540 -0.306061 0.755932 -0.578700 0.707422 0.693734 -0.135228 0.890990 0.352390 -0.286283</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="1800" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="5889">0 0 0 0 0.083333 0 0 0.166667 0 0 0.250000 0 0 0.333333 0 0 0.416667 0 0 0.500000 0 0 0.583333 0 0 0.666667 0 0 0.750000 0 0 0.833333 0 0 0.916667 0 0 1.000000 0 0.006667 0 0 0.006667 0.083333 0 0.006667 0.166667 0 0.006667 0.250000 0 0.006667 0.333333 0 0.006667 0.416667 0 0.006667 0.500000 0 0.006667 0.583333 0 0.006667 0.666667 0 0.006667 0.750000 0 0.006667 0.833333 0 0.006667 0.916667 0 0.006667 1.000000 0 0.013333 0 0 0.013333 0.083333 0 0.013333 0.166667 0 0.013333 0.250000 0 0.013333 0.333333 0 0.013333 0.416667 0 0.013333 0.500000 0 0.013333 0.583333 0 0.013333 0.666667 0 0.013333 0.750000 0 0.013333 0.833333 0 0.013333 0.916667 0 0.013333 1.000000 0 0.020000 0 0 0.020000 0.083333 0 0.020000 0.166667 0 0.020000 0.250000 0 0.020000 0.333333 0 0.020000 0.416667 0 0.020000 0.500000 0 0.020000 0.583333 0 0.020000 0.666667 0 0.020000 0.750000 0 0.020000 0.833333 0 0.020000 0.916667 0 0.020000 1.000000 0 0.026667 0 0 0.026667 0.083333 0 0.026667 0.166667 0 0.026667 0.250000 0 0.026667 0.333333 0 0.026667 0.416667 0 0.026667 0.500000 0 0.026667 0.583333 0 0.026667 0.666667 0 0.026667 0.750000 0 0.026667 0.833333 0 0.026667 0.916667 0 0.026667 1.000000 0 0.033333 0 0 0.033333 0.083333 0 0.033333 0.166667 0 0.033333 0.250000 0 0.033333 0.333333 0 0.033333 0.416667 0 0.033333 0.500000 0 0.033333 0.583333 0 0.033333 0.666667 0 0.033333 0.750000 0 0.033333 0.833333 0 0.033333 0.916667 0 0.033333 1.000000 0 0.040000 0 0 0.040000 0.083333 0 0.040000 0.166667 0 0.040000 0.250000 0 0.040000 0.333333 0 0.040000 0.416667 0 0.040000 0.500000 0 0.040000 0.583333 0 0.040000 0.666667 0 0.040000 0.750000 0 0.040000 0.833333 0 0.040000 0.916667 0 0.040000 1.000000 0 0.046667 0 0 0.046667 0.083333 0 0.046667 0.166667 0 0.046667 0.250000 0 0.046667 0.333333 0 0.046667 0.416667 0 0.046667 0.500000 0 0.046667 0.583333 0 0.046667 0.666667 0 0.046667 0.750000 0 0.046667 0.833333 0 0.046667 0.916667 0 0.046667 1.000000 0 0.053333 0 0 0.053333 0.083333 0 0.053333 0.166667 0 0.053333 0.250000 0 0.053333 0.333333 0 0.053333 0.416667 0 0.053333 0.500000 0 0.053333 0.583333 0 0.053333 0.666667 0 0.053333 0.750000 0 0.053333 0.833333 0 0.053333 0.916667 0 0.053333 1.000000 0 0.060000 0 0 0.060000 0.083333 0 0.060000 0.166667 0 0.060000 0.250000 0 0.060000 0.333333 0 0.060000 0.416667 0 0.060000 0.500000 0 0.060000 0.583333 0 0.060000 0.666667 0 0.060000 0.750000 0 0.060000 0.833333 0 0.060000 0.916667 0 0.060000 1.000000 0 0.066667 0 0 0.066667 0.083333 0 0.066667 0.166667 0 0.066667 0.250000 0 0.066667 0.333333 0 0.066667 0.416667 0 0.066667 0.500000 0 0.066667 0.583333 0 0.066667 0.666667 0 0.066667 0.750000 0 0.066667 0.833333 0 0.066667 0.916667 0 0.066667 1.000000 0 0.073333 0 0 0.073333 0.083333 0 0.073333 0.166667 0 0.073333 0.250000 0 0.073333 0.333333 0 0.073333 0.416667 0 0.073333 0.500000 0 0.073333 0.583333 0 0.073333 0.666667 0 0.073333 0.750000 0 0.073333 0.833333 0 0.073333 0.916667 0 0.073333 1.000000 0 0.080000 0 0 0.080000 0.083333 0 0.080000 0.166667 0 0.080000 0.250000 0 0.080000 0.333333 0 0.080000 0.416667 0 0.080000 0.500000 0 0.080000 0.583333 0 0.080000 0.666667 0 0.080000 0.750000 0 0.080000 0.833333 0 0.080000 0.916667 0 0.080000 1.000000 0 0.086667 0 0 0.086667 0.083333 0 0.086667 0.166667 0 0.086667 0.250000 0 0.086667 0.333333 0 0.086667 0.416667 0 0.086667 0.500000 0 0.086667 0.583333 0 0.086667 0.666667 0 0.086667 0.750000 0 0.086667 0.833333 0 0.086667 0.916667 0 0.086667 1.000000 0 0.093333 0 0 0.093333 0.083333 0 0.093333 0.166667 0 0.093333 0.250000 0 0.093333 0.333333 0 0.093333 0.416667 0 0.093333 0.500000 0 0.093333 0.583333 0 0.093333 0.666667 0 0.093333 0.750000 0 0.093333 0.833333 0 0.093333 0.916667 0 0.093333 1.000000 0 0.100000 0 0 0.100000 0.083333 0 0.100000 0.166667 0 0.100000 0.250000 0 0.100000 0.333333 0 0.100000 0.416667 0 0.100000 0.500000 0 0.100000 0.583333 0 0.100000 0.666667 0 0.100000 0.750000 0 0.100000 0.833333 0 0.100000 0.916667 0 0.100000 1.000000 0 0.106667 0 0 0.106667 0.083333 0 0.106667 0.166667 0 0.106667 0.250000 0 0.106667 0.333333 0 0.106667 0.416667 0 0.106667 0.500000 0 0.106667 0.583333 0 0.106667 0.666667 0 0.106667 0.750000 0 0.106667 0.833333 0 0.106667 0.916667 0 0.106667 1.000000 0 0.113333 0 0 0.113333 0.083333 0 0.113333 0.166667 0 0.113333 0.250000 0 0.113333 0.333333 0 0.113333 0.416667 0 0.113333 0.500000 0 0.113333 0.583333 0 0.113333 0.666667 0 0.113333 0.750000 0 0.113333 0.833333 0 0.113333 0.916667 0 0.113333 1.000000 0 0.120000 0 0 0.120000 0.083333 0 0.120000 0.166667 0 0.120000 0.250000 0 0.120000 0.333333 0 0.120000 0.416667 0 0.120000 0.500000 0 0.120000 0.583333 0 0.120000 0.666667 0 0.120000 0.750000 0 0.120000 0.833333 0 0.120000 0.916667 0 0.120000 1.000000 0 0.126667 0 0 0.126667 0.083333 0 0.126667 0.166667 0 0.126667 0.250000 0 0.126667 0.333333 0 0.126667 0.416667 0 0.126667 0.500000 0 0.126667 0.583333 0 0.126667 0.666667 0 0.126667 0.750000 0 0.126667 0.833333 0 0.126667 0.916667 0 0.126667 1.000000 0 0.133333 0 0 0.133333 0.083333 0 0.133333 0.166667 0 0.133333 0.250000 0 0.133333 0.333333 0 0.133333 0.416667 0 0.133333 0.500000 0 0.133333 0.583333 0 0.133333 0.666667 0 0.133333 0.750000 0 0.133333 0.833333 0 0.133333 0.916667 0 0.133333 1.000000 0 0.140000 0 0 0.140000 0.083333 0 0.140000 0.166667 0 0.140000 0.250000 0 0.140000 0.333333 0 0.140000 0.416667 0 0.140000 0.500000 0 0.140000 0.583333 0 0.140000 0.666667 0 0.140000 0.750000 0 0.140000 0.833333 0 0.140000 0.916667 0 0.140000 1.000000 0 0.146667 0 0 0.146667 0.083333 0 0.146667 0.166667 0 0.146667 0.250000 0 0.146667 0.333333 0 0.146667 0.416667 0 0.146667 0.500000 0 0.146667 0.583333 0 0.146667 0.666667 0 0.146667 0.750000 0 0.146667 0.833333 0 0.146667 0.916667 0 0.146667 1.000000 0 0.153333 0 0 0.153333 0.083333 0 0.153333 0.166667 0 0.153333 0.250000 0 0.153333 0.333333 0 0.153333 0.416667 0 0.153333 0.500000 0 0.153333 0.583333 0 0.153333 0.666667 0 0.153333 0.750000 0 0.153333 0.833333 0 0.153333 0.916667 0 0.153333 1.000000 0 0.160000 0 0 0.160000 0.083333 0 0.160000 0.166667 0 0.160000 0.250000 0 0.160000 0.333333 0 0.160000 0.416667 0 0.160000 0.500000 0 0.160000 0.583333 0 0.160000 0.666667 0 0.160000 0.750000 0 0.160000 0.833333 0 0.160000 0.916667 0 0.160000 1.000000 0 0.166667 0 0 0.166667 0.083333 0 0.166667 0.166667 0 0.166667 0.250000 0 0.166667 0.333333 0 0.166667 0.416667 0 0.166667 0.500000 0 0.166667 0.583333 0 0.166667 0.666667 0 0.166667 0.750000 0 0.166667 0.833333 0 0.166667 0.916667 0 0.166667 1.000000 0 0.173333 0 0 0.173333 0.083333 0 0.173333 0.166667 0 0.173333 0.250000 0 0.173333 0.333333 0 0.173333 0.416667 0 0.173333 0.500000 0 0.173333 0.583333 0 0.173333 0.666667 0 0.173333 0.750000 0 0.173333 0.833333 0 0.173333 0.916667 0 0.173333 1.000000 0 0.180000 0 0 0.180000 0.083333 0 0.180000 0.166667 0 0.180000 0.250000 0 0.180000 0.333333 0 0.180000 0.416667 0 0.180000 0.500000 0 0.180000 0.583333 0 0.180000 0.666667 0 0.180000 0.750000 0 0.180000 0.833333 0 0.180000 0.916667 0 0.180000 1.000000 0 0.186667 0 0 0.186667 0.083333 0 0.186667 0.166667 0 0.186667 0.250000 0 0.186667 0.333333 0 0.186667 0.416667 0 0.186667 0.500000 0 0.186667 0.583333 0 0.186667 0.666667 0 0.186667 0.750000 0 0.186667 0.833333 0 0.186667 0.916667 0 0.186667 1.000000 0 0.193333 0 0 0.193333 0.083333 0 0.193333 0.166667 0 0.193333 0.250000 0 0.193333 0.333333 0 0.193333 0.416667 0 0.193333 0.500000 0 0.193333 0.583333 0 0.193333 0.666667 0 0.193333 0.750000 0 0.193333 0.833333 0 0.193333 0.916667 0 0.193333 1.000000 0 0.200000 0 0 0.200000 0.083333 0 0.200000 0.166667 0 0.200000 0.250000 0 0.200000 0.333333 0 0.200000 0.416667 0 0.200000 0.500000 0 0.200000 0.583333 0 0.200000 0.666667 0 0.200000 0.750000 0 0.200000 0.833333 0 0.200000 0.916667 0 0.200000 1.000000 0 0.206667 0 0 0.206667 0.083333 0 0.206667 0.166667 0 0.206667 0.250000 0 0.206667 0.333333 0 0.206667 0.416667 0 0.206667 0.500000 0 0.206667 0.583333 0 0.206667 0.666667 0 0.206667 0.750000 0 0.206667 0.833333 0 0.206667 0.916667 0 0.206667 1.000000 0 0.213333 0 0 0.213333 0.083333 0 0.213333 0.166667 0 0.213333 0.250000 0 0.213333 0.333333 0 0.213333 0.416667 0 0.213333 0.500000 0 0.213333 0.583333 0 0.213333 0.666667 0 0.213333 0.750000 0 0.213333 0.833333 0 0.213333 0.916667 0 0.213333 1.000000 0 0.220000 0 0 0.220000 0.083333 0 0.220000 0.166667 0 0.220000 0.250000 0 0.220000 0.333333 0 0.220000 0.416667 0 0.220000 0.500000 0 0.220000 0.583333 0 0.220000 0.666667 0 0.220000 0.750000 0 0.220000 0.833333 0 0.220000 0.916667 0 0.220000 1.000000 0 0.226667 0 0 0.226667 0.083333 0 0.226667 0.166667 0 0.226667 0.250000 0 0.226667 0.333333 0 0.226667 0.416667 0 0.226667 0.500000 0 0.226667 0.583333 0 0.226667 0.666667 0 0.226667 0.750000 0 0.226667 0.833333 0 0.226667 0.916667 0 0.226667 1.000000 0 0.233333 0 0 0.233333 0.083333 0 0.233333 0.166667 0 0.233333 0.250000 0 0.233333 0.333333 0 0.233333 0.416667 0 0.233333 0.500000 0 0.233333 0.583333 0 0.233333 0.666667 0 0.233333 0.750000 0 0.233333 0.833333 0 0.233333 0.916667 0 0.233333 1.000000 0 0.240000 0 0 0.240000 0.083333 0 0.240000 0.166667 0 0.240000 0.250000 0 0.240000 0.333333 0 0.240000 0.416667 0 0.240000 0.500000 0 0.240000 0.583333 0 0.240000 0.666667 0 0.240000 0.750000 0 0.240000 0.833333 0 0.240000 0.916667 0 0.240000 1.000000 0 0.246667 0 0 0.246667 0.083333 0 0.246667 0.166667 0 0.246667 0.250000 0 0.246667 0.333333 0 0.246667 0.416667 0 0.246667 0.500000 0 0.246667 0.583333 0 0.246667 0.666667 0 0.246667 0.750000 0 0.246667 0.833333 0 0.246667 0.916667 0 0.246667 1.000000 0 0.253333 0 0 0.253333 0.083333 0 0.253333 0.166667 0 0.253333 0.250000 0 0.253333 0.333333 0 0.253333 0.416667 0 0.253333 0.500000 0 0.253333 0.583333 0 0.253333 0.666667 0 0.253333 0.750000 0 0.253333 0.833333 0 0.253333 0.916667 0 0.253333 1.000000 0 0.260000 0 0 0.260000 0.083333 0 0.260000 0.166667 0 0.260000 0.250000 0 0.260000 0.333333 0 0.260000 0.416667 0 0.260000 0.500000 0 0.260000 0.583333 0 0.260000 0.666667 0 0.260000 0.750000 0 0.260000 0.833333 0 0.260000 0.916667 0 0.260000 1.000000 0 0.266667 0 0 0.266667 0.083333 0 0.266667 0.166667 0 0.266667 0.250000 0 0.266667 0.333333 0 0.266667 0.416667 0 0.266667 0.500000 0 0.266667 0.583333 0 0.266667 0.666667 0 0.266667 0.750000 0 0.266667 0.833333 0 0.266667 0.916667 0 0.266667 1.000000 0 0.273333 0 0 0.273333 0.083333 0 0.273333 0.166667 0 0.273333 0.250000 0 0.273333 0.333333 0 0.273333 0.416667 0 0.273333 0.500000 0 0.273333 0.583333 0 0.273333 0.666667 0 0.273333 0.750000 0 0.273333 0.833333 0 0.273333 0.916667 0 0.273333 1.000000 0 0.280000 0 0 0.280000 0.083333 0 0.280000 0.166667 0 0.280000 0.250000 0 0.280000 0.333333 0 0.280000 0.416667 0 0.280000 0.500000 0 0.280000 0.583333 0 0.280000 0.666667 0 0.280000 0.750000 0 0.280000 0.833333 0 0.280000 0.916667 0 0.280000 1.000000 0 0.286667 0 0 0.286667 0.083333 0 0.286667 0.166667 0 0.286667 0.250000 0 0.286667 0.333333 0 0.286667 0.416667 0 0.286667 0.500000 0 0.286667 0.583333 0 0.286667 0.666667 0 0.286667 0.750000 0 0.286667 0.833333 0 0.286667 0.916667 0 0.286667 1.000000 0 0.293333 0 0 0.293333 0.083333 0 0.293333 0.166667 0 0.293333 0.250000 0 0.293333 0.333333 0 0.293333 0.416667 0 0.293333 0.500000 0 0.293333 0.583333 0 0.293333 0.666667 0 0.293333 0.750000 0 0.293333 0.833333 0 0.293333 0.916667 0 0.293333 1.000000 0 0.300000 0 0 0.300000 0.083333 0 0.300000 0.166667 0 0.300000 0.250000 0 0.300000 0.333333 0 0.300000 0.416667 0 0.300000 0.500000 0 0.300000 0.583333 0 0.300000 0.666667 0 0.300000 0.750000 0 0.300000 0.833333 0 0.300000 0.916667 0 0.300000 1.000000 0 0.306667 0 0 0.306667 0.083333 0 0.306667 0.166667 0 0.306667 0.250000 0 0.306667 0.333333 0 0.306667 0.416667 0 0.306667 0.500000 0 0.306667 0.583333 0 0.306667 0.666667 0 0.306667 0.750000 0 0.306667 0.833333 0 0.306667 0.916667 0 0.306667 1.000000 0 0.313333 0 0 0.313333 0.083333 0 0.313333 0.166667 0 0.313333 0.250000 0 0.313333 0.333333 0 0.313333 0.416667 0 0.313333 0.500000 0 0.313333 0.583333 0 0.313333 0.666667 0 0.313333 0.750000 0 0.313333 0.833333 0 0.313333 0.916667 0 0.313333 1.000000 0 0.320000 0 0 0.320000 0.083333 0 0.320000 0.166667 0 0.320000 0.250000 0 0.320000 0.333333 0 0.320000 0.416667 0 0.320000 0.500000 0 0.320000 0.583333 0 0.320000 0.666667 0 0.320000 0.750000 0 0.320000 0.833333 0 0.320000 0.916667 0 0.320000 1.000000 0 0.326667 0 0 0.326667 0.083333 0 0.326667 0.166667 0 0.326667 0.250000 0 0.326667 0.333333 0 0.326667 0.416667 0 0.326667 0.500000 0 0.326667 0.583333 0 0.326667 0.666667 0 0.326667 0.750000 0 0.326667 0.833333 0 0.326667 0.916667 0 0.326667 1.000000 0 0.333333 0 0 0.333333 0.083333 0 0.333333 0.166667 0 0.333333 0.250000 0 0.333333 0.333333 0 0.333333 0.416667 0 0.333333 0.500000 0 0.333333 0.583333 0 0.333333 0.666667 0 0.333333 0.750000 0 0.333333 0.833333 0 0.333333 0.916667 0 0.333333 1.000000 0 0.340000 0 0 0.340000 0.083333 0 0.340000 0.166667 0 0.340000 0.250000 0 0.340000 0.333333 0 0.340000 0.416667 0 0.340000 0.500000 0 0.340000 0.583333 0 0.340000 0.666667 0 0.340000 0.750000 0 0.340000 0.833333 0 0.340000 0.916667 0 0.340000 1.000000 0 0.346667 0 0 0.346667 0.083333 0 0.346667 0.166667 0 0.346667 0.250000 0 0.346667 0.333333 0 0.346667 0.416667 0 0.346667 0.500000 0 0.346667 0.583333 0 0.346667 0.666667 0 0.346667 0.750000 0 0.346667 0.833333 0 0.346667 0.916667 0 0.346667 1.000000 0 0.353333 0 0 0.353333 0.083333 0 0.353333 0.166667 0 0.353333 0.250000 0 0.353333 0.333333 0 0.353333 0.416667 0 0.353333 0.500000 0 0.353333 0.583333 0 0.353333 0.666667 0 0.353333 0.750000 0 0.353333 0.833333 0 0.353333 0.916667 0 0.353333 1.000000 0 0.360000 0 0 0.360000 0.083333 0 0.360000 0.166667 0 0.360000 0.250000 0 0.360000 0.333333 0 0.360000 0.416667 0 0.360000 0.500000 0 0.360000 0.583333 0 0.360000 0.666667 0 0.360000 0.750000 0 0.360000 0.833333 0 0.360000 0.916667 0 0.360000 1.000000 0 0.366667 0 0 0.366667 0.083333 0 0.366667 0.166667 0 0.366667 0.250000 0 0.366667 0.333333 0 0.366667 0.416667 0 0.366667 0.500000 0 0.366667 0.583333 0 0.366667 0.666667 0 0.366667 0.750000 0 0.366667 0.833333 0 0.366667 0.916667 0 0.366667 1.000000 0 0.373333 0 0 0.373333 0.083333 0 0.373333 0.166667 0 0.373333 0.250000 0 0.373333 0.333333 0 0.373333 0.416667 0 0.373333 0.500000 0 0.373333 0.583333 0 0.373333 0.666667 0 0.373333 0.750000 0 0.373333 0.833333 0 0.373333 0.916667 0 0.373333 1.000000 0 0.380000 0 0 0.380000 0.083333 0 0.380000 0.166667 0 0.380000 0.250000 0 0.380000 0.333333 0 0.380000 0.416667 0 0.380000 0.500000 0 0.380000 0.583333 0 0.380000 0.666667 0 0.380000 0.750000 0 0.380000 0.833333 0 0.380000 0.916667 0 0.380000 1.000000 0 0.386667 0 0 0.386667 0.083333 0 0.386667 0.166667 0 0.386667 0.250000 0 0.386667 0.333333 0 0.386667 0.416667 0 0.386667 0.500000 0 0.386667 0.583333 0 0.386667 0.666667 0 0.386667 0.750000 0 0.386667 0.833333 0 0.386667 0.916667 0 0.386667 1.000000 0 0.393333 0 0 0.393333 0.083333 0 0.393333 0.166667 0 0.393333 0.250000 0 0.393333 0.333333 0 0.393333 0.416667 0 0.393333 0.500000 0 0.393333 0.583333 0 0.393333 0.666667 0 0.393333 0.750000 0 0.393333 0.833333 0 0.393333 0.916667 0 0.393333 1.000000 0 0.400000 0 0 0.400000 0.083333 0 0.400000 0.166667 0 0.400000 0.250000 0 0.400000 0.333333 0 0.400000 0.416667 0 0.400000 0.500000 0 0.400000 0.583333 0 0.400000 0.666667 0 0.400000 0.750000 0 0.400000 0.833333 0 0.400000 0.916667 0 0.400000 1.000000 0 0.406667 0 0 0.406667 0.083333 0 0.406667 0.166667 0 0.406667 0.250000 0 0.406667 0.333333 0 0.406667 0.416667 0 0.406667 0.500000 0 0.406667 0.583333 0 0.406667 0.666667 0 0.406667 0.750000 0 0.406667 0.833333 0 0.406667 0.916667 0 0.406667 1.000000 0 0.413333 0 0 0.413333 0.083333 0 0.413333 0.166667 0 0.413333 0.250000 0 0.413333 0.333333 0 0.413333 0.416667 0 0.413333 0.500000 0 0.413333 0.583333 0 0.413333 0.666667 0 0.413333 0.750000 0 0.413333 0.833333 0 0.413333 0.916667 0 0.413333 1.000000 0 0.420000 0 0 0.420000 0.083333 0 0.420000 0.166667 0 0.420000 0.250000 0 0.420000 0.333333 0 0.420000 0.416667 0 0.420000 0.500000 0 0.420000 0.583333 0 0.420000 0.666667 0 0.420000 0.750000 0 0.420000 0.833333 0 0.420000 0.916667 0 0.420000 1.000000 0 0.426667 0 0 0.426667 0.083333 0 0.426667 0.166667 0 0.426667 0.250000 0 0.426667 0.333333 0 0.426667 0.416667 0 0.426667 0.500000 0 0.426667 0.583333 0 0.426667 0.666667 0 0.426667 0.750000 0 0.426667 0.833333 0 0.426667 0.916667 0 0.426667 1.000000 0 0.433333 0 0 0.433333 0.083333 0 0.433333 0.166667 0 0.433333 0.250000 0 0.433333 0.333333 0 0.433333 0.416667 0 0.433333 0.500000 0 0.433333 0.583333 0 0.433333 0.666667 0 0.433333 0.750000 0 0.433333 0.833333 0 0.433333 0.916667 0 0.433333 1.000000 0 0.440000 0 0 0.440000 0.083333 0 0.440000 0.166667 0 0.440000 0.250000 0 0.440000 0.333333 0 0.440000 0.416667 0 0.440000 0.500000 0 0.440000 0.583333 0 0.440000 0.666667 0 0.440000 0.750000 0 0.440000 0.833333 0 0.440000 0.916667 0 0.440000 1.000000 0 0.446667 0 0 0.446667 0.083333 0 0.446667 0.166667 0 0.446667 0.250000 0 0.446667 0.333333 0 0.446667 0.416667 0 0.446667 0.500000 0 0.446667 0.583333 0 0.446667 0.666667 0 0.446667 0.750000 0 0.446667 0.833333 0 0.446667 0.916667 0 0.446667 1.000000 0 0.453334 0 0 0.453334 0.083333 0 0.453334 0.166667 0 0.453334 0.250000 0 0.453334 0.333333 0 0.453334 0.416667 0 0.453334 0.500000 0 0.453334 0.583333 0 0.453334 0.666667 0 0.453334 0.750000 0 0.453334 0.833333 0 0.453334 0.916667 0 0.453334 1.000000 0 0.460000 0 0 0.460000 0.083333 0 0.460000 0.166667 0 0.460000 0.250000 0 0.460000 0.333333 0 0.460000 0.416667 0 0.460000 0.500000 0 0.460000 0.583333 0 0.460000 0.666667 0 0.460000 0.750000 0 0.460000 0.833333 0 0.460000 0.916667 0 0.460000 1.000000 0 0.466667 0 0 0.466667 0.083333 0 0.466667 0.166667 0 0.466667 0.250000 0 0.466667 0.333333 0 0.466667 0.416667 0 0.466667 0.500000 0 0.466667 0.583333 0 0.466667 0.666667 0 0.466667 0.750000 0 0.466667 0.833333 0 0.466667 0.916667 0 0.466667 1.000000 0 0.473334 0 0 0.473334 0.083333 0 0.473334 0.166667 0 0.473334 0.250000 0 0.473334 0.333333 0 0.473334 0.416667 0 0.473334 0.500000 0 0.473334 0.583333 0 0.473334 0.666667 0 0.473334 0.750000 0 0.473334 0.833333 0 0.473334 0.916667 0 0.473334 1.000000 0 0.480000 0 0 0.480000 0.083333 0 0.480000 0.166667 0 0.480000 0.250000 0 0.480000 0.333333 0 0.480000 0.416667 0 0.480000 0.500000 0 0.480000 0.583333 0 0.480000 0.666667 0 0.480000 0.750000 0 0.480000 0.833333 0 0.480000 0.916667 0 0.480000 1.000000 0 0.486667 0 0 0.486667 0.083333 0 0.486667 0.166667 0 0.486667 0.250000 0 0.486667 0.333333 0 0.486667 0.416667 0 0.486667 0.500000 0 0.486667 0.583333 0 0.486667 0.666667 0 0.486667 0.750000 0 0.486667 0.833333 0 0.486667 0.916667 0 0.486667 1.000000 0 0.493334 0 0 0.493334 0.083333 0 0.493334 0.166667 0 0.493334 0.250000 0 0.493334 0.333333 0 0.493334 0.416667 0 0.493334 0.500000 0 0.493334 0.583333 0 0.493334 0.666667 0 0.493334 0.750000 0 0.493334 0.833333 0 0.493334 0.916667 0 0.493334 1.000000 0 0.500000 0 0 0.500000 0.083333 0 0.500000 0.166667 0 0.500000 0.250000 0 0.500000 0.333333 0 0.500000 0.416667 0 0.500000 0.500000 0 0.500000 0.583333 0 0.500000 0.666667 0 0.500000 0.750000 0 0.500000 0.833333 0 0.500000 0.916667 0 0.500000 1.000000 0 0.506667 0 0 0.506667 0.083333 0 0.506667 0.166667 0 0.506667 0.250000 0 0.506667 0.333333 0 0.506667 0.416667 0 0.506667 0.500000 0 0.506667 0.583333 0 0.506667 0.666667 0 0.506667 0.750000 0 0.506667 0.833333 0 0.506667 0.916667 0 0.506667 1.000000 0 0.513334 0 0 0.513334 0.083333 0 0.513334 0.166667 0 0.513334 0.250000 0 0.513334 0.333333 0 0.513334 0.416667 0 0.513334 0.500000 0 0.513334 0.583333 0 0.513334 0.666667 0 0.513334 0.750000 0 0.513334 0.833333 0 0.513334 0.916667 0 0.513334 1.000000 0 0.520000 0 0 0.520000 0.083333 0 0.520000 0.166667 0 0.520000 0.250000 0 0.520000 0.333333 0 0.520000 0.416667 0 0.520000 0.500000 0 0.520000 0.583333 0 0.520000 0.666667 0 0.520000 0.750000 0 0.520000 0.833333 0 0.520000 0.916667 0 0.520000 1.000000 0 0.526667 0 0 0.526667 0.083333 0 0.526667 0.166667 0 0.526667 0.250000 0 0.526667 0.333333 0 0.526667 0.416667 0 0.526667 0.500000 0 0.526667 0.583333 0 0.526667 0.666667 0 0.526667 0.750000 0 0.526667 0.833333 0 0.526667 0.916667 0 0.526667 1.000000 0 0.533334 0 0 0.533334 0.083333 0 0.533334 0.166667 0 0.533334 0.250000 0 0.533334 0.333333 0 0.533334 0.416667 0 0.533334 0.500000 0 0.533334 0.583333 0 0.533334 0.666667 0 0.533334 0.750000 0 0.533334 0.833333 0 0.533334 0.916667 0 0.533334 1.000000 0 0.540000 0 0 0.540000 0.083333 0 0.540000 0.166667 0 0.540000 0.250000 0 0.540000 0.333333 0 0.540000 0.416667 0 0.540000 0.500000 0 0.540000 0.583333 0 0.540000 0.666667 0 0.540000 0.750000 0 0.540000 0.833333 0 0.540000 0.916667 0 0.540000 1.000000 0 0.546667 0 0 0.546667 0.083333 0 0.546667 0.166667 0 0.546667 0.250000 0 0.546667 0.333333 0 0.546667 0.416667 0 0.546667 0.500000 0 0.546667 0.583333 0 0.546667 0.666667 0 0.546667 0.750000 0 0.546667 0.833333 0 0.546667 0.916667 0 0.546667 1.000000 0 0.553334 0 0 0.553334 0.083333 0 0.553334 0.166667 0 0.553334 0.250000 0 0.553334 0.333333 0 0.553334 0.416667 0 0.553334 0.500000 0 0.553334 0.583333 0 0.553334 0.666667 0 0.553334 0.750000 0 0.553334 0.833333 0 0.553334 0.916667 0 0.553334 1.000000 0 0.560000 0 0 0.560000 0.083333 0 0.560000 0.166667 0 0.560000 0.250000 0 0.560000 0.333333 0 0.560000 0.416667 0 0.560000 0.500000 0 0.560000 0.583333 0 0.560000 0.666667 0 0.560000 0.750000 0 0.560000 0.833333 0 0.560000 0.916667 0 0.560000 1.000000 0 0.566667 0 0 0.566667 0.083333 0 0.566667 0.166667 0 0.566667 0.250000 0 0.566667 0.333333 0 0.566667 0.416667 0 0.566667 0.500000 0 0.566667 0.583333 0 0.566667 0.666667 0 0.566667 0.750000 0 0.566667 0.833333 0 0.566667 0.916667 0 0.566667 1.000000 0 0.573334 0 0 0.573334 0.083333 0 0.573334 0.166667 0 0.573334 0.250000 0 0.573334 0.333333 0 0.573334 0.416667 0 0.573334 0.500000 0 0.573334 0.583333 0 0.573334 0.666667 0 0.573334 0.750000 0 0.573334 0.833333 0 0.573334 0.916667 0 0.573334 1.000000 0 0.580000 0 0 0.580000 0.083333 0 0.580000 0.166667 0 0.580000 0.250000 0 0.580000 0.333333 0 0.580000 0.416667 0 0.580000 0.500000 0 0.580000 0.583333 0 0.580000 0.666667 0 0.580000 0.750000 0 0.580000 0.833333 0 0.580000 0.916667 0 0.580000 1.000000 0 0.586667 0 0 0.586667 0.083333 0 0.586667 0.166667 0 0.586667 0.250000 0 0.586667 0.333333 0 0.586667 0.416667 0 0.586667 0.500000 0 0.586667 0.583333 0 0.586667 0.666667 0 0.586667 0.750000 0 0.586667 0.833333 0 0.586667 0.916667 0 0.586667 1.000000 0 0.593334 0 0 0.593334 0.083333 0 0.593334 0.166667 0 0.593334 0.250000 0 0.593334 0.333333 0 0.593334 0.416667 0 0.593334 0.500000 0 0.593334 0.583333 0 0.593334 0.666667 0 0.593334 0.750000 0 0.593334 0.833333 0 0.593334 0.916667 0 0.593334 1.000000 0 0.600001 0 0 0.600001 0.083333 0 0.600001 0.166667 0 0.600001 0.250000 0 0.600001 0.333333 0 0.600001 0.416667 0 0.600001 0.500000 0 0.600001 0.583333 0 0.600001 0.666667 0 0.600001 0.750000 0 0.600001 0.833333 0 0.600001 0.916667 0 0.600001 1.000000 0 0.606667 0 0 0.606667 0.083333 0 0.606667 0.166667 0 0.606667 0.250000 0 0.606667 0.333333 0 0.606667 0.416667 0 0.606667 0.500000 0 0.606667 0.583333 0 0.606667 0.666667 0 0.606667 0.750000 0 0.606667 0.833333 0 0.606667 0.916667 0 0.606667 1.000000 0 0.613334 0 0 0.613334 0.083333 0 0.613334 0.166667 0 0.613334 0.250000 0 0.613334 0.333333 0 0.613334 0.416667 0 0.613334 0.500000 0 0.613334 0.583333 0 0.613334 0.666667 0 0.613334 0.750000 0 0.613334 0.833333 0 0.613334 0.916667 0 0.613334 1.000000 0 0.620001 0 0 0.620001 0.083333 0 0.620001 0.166667 0 0.620001 0.250000 0 0.620001 0.333333 0 0.620001 0.416667 0 0.620001 0.500000 0 0.620001 0.583333 0 0.620001 0.666667 0 0.620001 0.750000 0 0.620001 0.833333 0 0.620001 0.916667 0 0.620001 1.000000 0 0.626667 0 0 0.626667 0.083333 0 0.626667 0.166667 0 0.626667 0.250000 0 0.626667 0.333333 0 0.626667 0.416667 0 0.626667 0.500000 0 0.626667 0.583333 0 0.626667 0.666667 0 0.626667 0.750000 0 0.626667 0.833333 0 0.626667 0.916667 0 0.626667 1.000000 0 0.633334 0 0 0.633334 0.083333 0 0.633334 0.166667 0 0.633334 0.250000 0 0.633334 0.333333 0 0.633334 0.416667 0 0.633334 0.500000 0 0.633334 0.583333 0 0.633334 0.666667 0 0.633334 0.750000 0 0.633334 0.833333 0 0.633334 0.916667 0 0.633334 1.000000 0 0.640001 0 0 0.640001 0.083333 0 0.640001 0.166667 0 0.640001 0.250000 0 0.640001 0.333333 0 0.640001 0.416667 0 0.640001 0.500000 0 0.640001 0.583333 0 0.640001 0.666667 0 0.640001 0.750000 0 0.640001 0.833333 0 0.640001 0.916667 0 0.640001 1.000000 0 0.646667 0 0 0.646667 0.083333 0 0.646667 0.166667 0 0.646667 0.250000 0 0.646667 0.333333 0 0.646667 0.416667 0 0.646667 0.500000 0 0.646667 0.583333 0 0.646667 0.666667 0 0.646667 0.750000 0 0.646667 0.833333 0 0.646667 0.916667 0 0.646667 1.000000 0 0.653334 0 0 0.653334 0.083333 0 0.653334 0.166667 0 0.653334 0.250000 0 0.653334 0.333333 0 0.653334 0.416667 0 0.653334 0.500000 0 0.653334 0.583333 0 0.653334 0.666667 0 0.653334 0.750000 0 0.653334 0.833333 0 0.653334 0.916667 0 0.653334 1.000000 0 0.660001 0 0 0.660001 0.083333 0 0.660001 0.166667 0 0.660001 0.250000 0 0.660001 0.333333 0 0.660001 0.416667 0 0.660001 0.500000 0 0.660001 0.583333 0 0.660001 0.666667 0 0.660001 0.750000 0 0.660001 0.833333 0 0.660001 0.916667 0 0.660001 1.000000 0 0.666667 0 0 0.666667 0.083333 0 0.666667 0.166667 0 0.666667 0.250000 0 0.666667 0.333333 0 0.666667 0.416667 0 0.666667 0.500000 0 0.666667 0.583333 0 0.666667 0.666667 0 0.666667 0.750000 0 0.666667 0.833333 0 0.666667 0.916667 0 0.666667 1.000000 0 0.673334 0 0 0.673334 0.083333 0 0.673334 0.166667 0 0.673334 0.250000 0 0.673334 0.333333 0 0.673334 0.416667 0 0.673334 0.500000 0 0.673334 0.583333 0 0.673334 0.666667 0 0.673334 0.750000 0 0.673334 0.833333 0 0.673334 0.916667 0 0.673334 1.000000 0 0.680000 0 0 0.680000 0.083333 0 0.680000 0.166667 0 0.680000 0.250000 0 0.680000 0.333333 0 0.680000 0.416667 0 0.680000 0.500000 0 0.680000 0.583333 0 0.680000 0.666667 0 0.680000 0.750000 0 0.680000 0.833333 0 0.680000 0.916667 0 0.680000 1.000000 0 0.686667 0 0 0.686667 0.083333 0 0.686667 0.166667 0 0.686667 0.250000 0 0.686667 0.333333 0 0.686667 0.416667 0 0.686667 0.500000 0 0.686667 0.583333 0 0.686667 0.666667 0 0.686667 0.750000 0 0.686667 0.833333 0 0.686667 0.916667 0 0.686667 1.000000 0 0.693334 0 0 0.693334 0.083333 0 0.693334 0.166667 0 0.693334 0.250000 0 0.693334 0.333333 0 0.693334 0.416667 0 0.693334 0.500000 0 0.693334 0.583333 0 0.693334 0.666667 0 0.693334 0.750000 0 0.693334 0.833333 0 0.693334 0.916667 0 0.693334 1.000000 0 0.700000 0 0 0.700000 0.083333 0 0.700000 0.166667 0 0.700000 0.250000 0 0.700000 0.333333 0 0.700000 0.416667 0 0.700000 0.500000 0 0.700000 0.583333 0 0.700000 0.666667 0 0.700000 0.750000 0 0.700000 0.833333 0 0.700000 0.916667 0 0.700000 1.000000 0 0.706667 0 0 0.706667 0.083333 0 0.706667 0.166667 0 0.706667 0.250000 0 0.706667 0.333333 0 0.706667 0.416667 0 0.706667 0.500000 0 0.706667 0.583333 0 0.706667 0.666667 0 0.706667 0.750000 0 0.706667 0.833333 0 0.706667 0.916667 0 0.706667 1.000000 0 0.713334 0 0 0.713334 0.083333 0 0.713334 0.166667 0 0.713334 0.250000 0 0.713334 0.333333 0 0.713334 0.416667 0 0.713334 0.500000 0 0.713334 0.583333 0 0.713334 0.666667 0 0.713334 0.750000 0 0.713334 0.833333 0 0.713334 0.916667 0 0.713334 1.000000 0 0.720000 0 0 0.720000 0.083333 0 0.720000 0.166667 0 0.720000 0.250000 0 0.720000 0.333333 0 0.720000 0.416667 0 0.720000 0.500000 0 0.720000 0.583333 0 0.720000 0.666667 0 0.720000 0.750000 0 0.720000 0.833333 0 0.720000 0.916667 0 0.720000 1.000000 0 0.726667 0 0 0.726667 0.083333 0 0.726667 0.166667 0 0.726667 0.250000 0 0.726667 0.333333 0 0.726667 0.416667 0 0.726667 0.500000 0 0.726667 0.583333 0 0.726667 0.666667 0 0.726667 0.750000 0 0.726667 0.833333 0 0.726667 0.916667 0 0.726667 1.000000 0 0.733334 0 0 0.733334 0.083333 0 0.733334 0.166667 0 0.733334 0.250000 0 0.733334 0.333333 0 0.733334 0.416667 0 0.733334 0.500000 0 0.733334 0.583333 0 0.733334 0.666667 0 0.733334 0.750000 0 0.733334 0.833333 0 0.733334 0.916667 0 0.733334 1.000000 0 0.740000 0 0 0.740000 0.083333 0 0.740000 0.166667 0 0.740000 0.250000 0 0.740000 0.333333 0 0.740000 0.416667 0 0.740000 0.500000 0 0.740000 0.583333 0 0.740000 0.666667 0 0.740000 0.750000 0 0.740000 0.833333 0 0.740000 0.916667 0 0.740000 1.000000 0 0.746667 0 0 0.746667 0.083333 0 0.746667 0.166667 0 0.746667 0.250000 0 0.746667 0.333333 0 0.746667 0.416667 0 0.746667 0.500000 0 0.746667 0.583333 0 0.746667 0.666667 0 0.746667 0.750000 0 0.746667 0.833333 0 0.746667 0.916667 0 0.746667 1.000000 0 0.753334 0 0 0.753334 0.083333 0 0.753334 0.166667 0 0.753334 0.250000 0 0.753334 0.333333 0 0.753334 0.416667 0 0.753334 0.500000 0 0.753334 0.583333 0 0.753334 0.666667 0 0.753334 0.750000 0 0.753334 0.833333 0 0.753334 0.916667 0 0.753334 1.000000 0 0.760000 0 0 0.760000 0.083333 0 0.760000 0.166667 0 0.760000 0.250000 0 0.760000 0.333333 0 0.760000 0.416667 0 0.760000 0.500000 0 0.760000 0.583333 0 0.760000 0.666667 0 0.760000 0.750000 0 0.760000 0.833333 0 0.760000 0.916667 0 0.760000 1.000000 0 0.766667 0 0 0.766667 0.083333 0 0.766667 0.166667 0 0.766667 0.250000 0 0.766667 0.333333 0 0.766667 0.416667 0 0.766667 0.500000 0 0.766667 0.583333 0 0.766667 0.666667 0 0.766667 0.750000 0 0.766667 0.833333 0 0.766667 0.916667 0 0.766667 1.000000 0 0.773333 0 0 0.773333 0.083333 0 0.773333 0.166667 0 0.773333 0.250000 0 0.773333 0.333333 0 0.773333 0.416667 0 0.773333 0.500000 0 0.773333 0.583333 0 0.773333 0.666667 0 0.773333 0.750000 0 0.773333 0.833333 0 0.773333 0.916667 0 0.773333 1.000000 0 0.780000 0 0 0.780000 0.083333 0 0.780000 0.166667 0 0.780000 0.250000 0 0.780000 0.333333 0 0.780000 0.416667 0 0.780000 0.500000 0 0.780000 0.583333 0 0.780000 0.666667 0 0.780000 0.750000 0 0.780000 0.833333 0 0.780000 0.916667 0 0.780000 1.000000 0 0.786667 0 0 0.786667 0.083333 0 0.786667 0.166667 0 0.786667 0.250000 0 0.786667 0.333333 0 0.786667 0.416667 0 0.786667 0.500000 0 0.786667 0.583333 0 0.786667 0.666667 0 0.786667 0.750000 0 0.786667 0.833333 0 0.786667 0.916667 0 0.786667 1.000000 0 0.793333 0 0 0.793333 0.083333 0 0.793333 0.166667 0 0.793333 0.250000 0 0.793333 0.333333 0 0.793333 0.416667 0 0.793333 0.500000 0 0.793333 0.583333 0 0.793333 0.666667 0 0.793333 0.750000 0 0.793333 0.833333 0 0.793333 0.916667 0 0.793333 1.000000 0 0.800000 0 0 0.800000 0.083333 0 0.800000 0.166667 0 0.800000 0.250000 0 0.800000 0.333333 0 0.800000 0.416667 0 0.800000 0.500000 0 0.800000 0.583333 0 0.800000 0.666667 0 0.800000 0.750000 0 0.800000 0.833333 0 0.800000 0.916667 0 0.800000 1.000000 0 0.806667 0 0 0.806667 0.083333 0 0.806667 0.166667 0 0.806667 0.250000 0 0.806667 0.333333 0 0.806667 0.416667 0 0.806667 0.500000 0 0.806667 0.583333 0 0.806667 0.666667 0 0.806667 0.750000 0 0.806667 0.833333 0 0.806667 0.916667 0 0.806667 1.000000 0 0.813333 0 0 0.813333 0.083333 0 0.813333 0.166667 0 0.813333 0.250000 0 0.813333 0.333333 0 0.813333 0.416667 0 0.813333 0.500000 0 0.813333 0.583333 0 0.813333 0.666667 0 0.813333 0.750000 0 0.813333 0.833333 0 0.813333 0.916667 0 0.813333 1.000000 0 0.820000 0 0 0.820000 0.083333 0 0.820000 0.166667 0 0.820000 0.250000 0 0.820000 0.333333 0 0.820000 0.416667 0 0.820000 0.500000 0 0.820000 0.583333 0 0.820000 0.666667 0 0.820000 0.750000 0 0.820000 0.833333 0 0.820000 0.916667 0 0.820000 1.000000 0 0.826667 0 0 0.826667 0.083333 0 0.826667 0.166667 0 0.826667 0.250000 0 0.826667 0.333333 0 0.826667 0.416667 0 0.826667 0.500000 0 0.826667 0.583333 0 0.826667 0.666667 0 0.826667 0.750000 0 0.826667 0.833333 0 0.826667 0.916667 0 0.826667 1.000000 0 0.833333 0 0 0.833333 0.083333 0 0.833333 0.166667 0 0.833333 0.250000 0 0.833333 0.333333 0 0.833333 0.416667 0 0.833333 0.500000 0 0.833333 0.583333 0 0.833333 0.666667 0 0.833333 0.750000 0 0.833333 0.833333 0 0.833333 0.916667 0 0.833333 1.000000 0 0.840000 0 0 0.840000 0.083333 0 0.840000 0.166667 0 0.840000 0.250000 0 0.840000 0.333333 0 0.840000 0.416667 0 0.840000 0.500000 0 0.840000 0.583333 0 0.840000 0.666667 0 0.840000 0.750000 0 0.840000 0.833333 0 0.840000 0.916667 0 0.840000 1.000000 0 0.846667 0 0 0.846667 0.083333 0 0.846667 0.166667 0 0.846667 0.250000 0 0.846667 0.333333 0 0.846667 0.416667 0 0.846667 0.500000 0 0.846667 0.583333 0 0.846667 0.666667 0 0.846667 0.750000 0 0.846667 0.833333 0 0.846667 0.916667 0 0.846667 1.000000 0 0.853333 0 0 0.853333 0.083333 0 0.853333 0.166667 0 0.853333 0.250000 0 0.853333 0.333333 0 0.853333 0.416667 0 0.853333 0.500000 0 0.853333 0.583333 0 0.853333 0.666667 0 0.853333 0.750000 0 0.853333 0.833333 0 0.853333 0.916667 0 0.853333 1.000000 0 0.860000 0 0 0.860000 0.083333 0 0.860000 0.166667 0 0.860000 0.250000 0 0.860000 0.333333 0 0.860000 0.416667 0 0.860000 0.500000 0 0.860000 0.583333 0 0.860000 0.666667 0 0.860000 0.750000 0 0.860000 0.833333 0 0.860000 0.916667 0 0.860000 1.000000 0 0.866666 0 0 0.866666 0.083333 0 0.866666 0.166667 0 0.866666 0.250000 0 0.866666 0.333333 0 0.866666 0.416667 0 0.866666 0.500000 0 0.866666 0.583333 0 0.866666 0.666667 0 0.866666 0.750000 0 0.866666 0.833333 0 0.866666 0.916667 0 0.866666 1.000000 0 0.873333 0 0 0.873333 0.083333 0 0.873333 0.166667 0 0.873333 0.250000 0 0.873333 0.333333 0 0.873333 0.416667 0 0.873333 0.500000 0 0.873333 0.583333 0 0.873333 0.666667 0 0.873333 0.750000 0 0.873333 0.833333 0 0.873333 0.916667 0 0.873333 1.000000 0 0.880000 0 0 0.880000 0.083333 0 0.880000 0.166667 0 0.880000 0.250000 0 0.880000 0.333333 0 0.880000 0.416667 0 0.880000 0.500000 0 0.880000 0.583333 0 0.880000 0.666667 0 0.880000 0.750000 0 0.880000 0.833333 0 0.880000 0.916667 0 0.880000 1.000000 0 0.886666 0 0 0.886666 0.083333 0 0.886666 0.166667 0 0.886666 0.250000 0 0.886666 0.333333 0 0.886666 0.416667 0 0.886666 0.500000 0 0.886666 0.583333 0 0.886666 0.666667 0 0.886666 0.750000 0 0.886666 0.833333 0 0.886666 0.916667 0 0.886666 1.000000 0 0.893333 0 0 0.893333 0.083333 0 0.893333 0.166667 0 0.893333 0.250000 0 0.893333 0.333333 0 0.893333 0.416667 0 0.893333 0.500000 0 0.893333 0.583333 0 0.893333 0.666667 0 0.893333 0.750000 0 0.893333 0.833333 0 0.893333 0.916667 0 0.893333 1.000000 0 0.900000 0 0 0.900000 0.083333 0 0.900000 0.166667 0 0.900000 0.250000 0 0.900000 0.333333 0 0.900000 0.416667 0 0.900000 0.500000 0 0.900000 0.583333 0 0.900000 0.666667 0 0.900000 0.750000 0 0.900000 0.833333 0 0.900000 0.916667 0 0.900000 1.000000 0 0.906666 0 0 0.906666 0.083333 0 0.906666 0.166667 0 0.906666 0.250000 0 0.906666 0.333333 0 0.906666 0.416667 0 0.906666 0.500000 0 0.906666 0.583333 0 0.906666 0.666667 0 0.906666 0.750000 0 0.906666 0.833333 0 0.906666 0.916667 0 0.906666 1.000000 0 0.913333 0 0 0.913333 0.083333 0 0.913333 0.166667 0 0.913333 0.250000 0 0.913333 0.333333 0 0.913333 0.416667 0 0.913333 0.500000 0 0.913333 0.583333 0 0.913333 0.666667 0 0.913333 0.750000 0 0.913333 0.833333 0 0.913333 0.916667 0 0.913333 1.000000 0 0.920000 0 0 0.920000 0.083333 0 0.920000 0.166667 0 0.920000 0.250000 0 0.920000 0.333333 0 0.920000 0.416667 0 0.920000 0.500000 0 0.920000 0.583333 0 0.920000 0.666667 0 0.920000 0.750000 0 0.920000 0.833333 0 0.920000 0.916667 0 0.920000 1.000000 0 0.926666 0 0 0.926666 0.083333 0 0.926666 0.166667 0 0.926666 0.250000 0 0.926666 0.333333 0 0.926666 0.416667 0 0.926666 0.500000 0 0.926666 0.583333 0 0.926666 0.666667 0 0.926666 0.750000 0 0.926666 0.833333 0 0.926666 0.916667 0 0.926666 1.000000 0 0.933333 0 0 0.933333 0.083333 0 0.933333 0.166667 0 0.933333 0.250000 0 0.933333 0.333333 0 0.933333 0.416667 0 0.933333 0.500000 0 0.933333 0.583333 0 0.933333 0.666667 0 0.933333 0.750000 0 0.933333 0.833333 0 0.933333 0.916667 0 0.933333 1.000000 0 0.940000 0 0 0.940000 0.083333 0 0.940000 0.166667 0 0.940000 0.250000 0 0.940000 0.333333 0 0.940000 0.416667 0 0.940000 0.500000 0 0.940000 0.583333 0 0.940000 0.666667 0 0.940000 0.750000 0 0.940000 0.833333 0 0.940000 0.916667 0 0.940000 1.000000 0 0.946666 0 0 0.946666 0.083333 0 0.946666 0.166667 0 0.946666 0.250000 0 0.946666 0.333333 0 0.946666 0.416667 0 0.946666 0.500000 0 0.946666 0.583333 0 0.946666 0.666667 0 0.946666 0.750000 0 0.946666 0.833333 0 0.946666 0.916667 0 0.946666 1.000000 0 0.953333 0 0 0.953333 0.083333 0 0.953333 0.166667 0 0.953333 0.250000 0 0.953333 0.333333 0 0.953333 0.416667 0 0.953333 0.500000 0 0.953333 0.583333 0 0.953333 0.666667 0 0.953333 0.750000 0 0.953333 0.833333 0 0.953333 0.916667 0 0.953333 1.000000 0 0.960000 0 0 0.960000 0.083333 0 0.960000 0.166667 0 0.960000 0.250000 0 0.960000 0.333333 0 0.960000 0.416667 0 0.960000 0.500000 0 0.960000 0.583333 0 0.960000 0.666667 0 0.960000 0.750000 0 0.960000 0.833333 0 0.960000 0.916667 0 0.960000 1.000000 0 0.966666 0 0 0.966666 0.083333 0 0.966666 0.166667 0 0.966666 0.250000 0 0.966666 0.333333 0 0.966666 0.416667 0 0.966666 0.500000 0 0.966666 0.583333 0 0.966666 0.666667 0 0.966666 0.750000 0 0.966666 0.833333 0 0.966666 0.916667 0 0.966666 1.000000 0 0.973333 0 0 0.973333 0.083333 0 0.973333 0.166667 0 0.973333 0.250000 0 0.973333 0.333333 0 0.973333 0.416667 0 0.973333 0.500000 0 0.973333 0.583333 0 0.973333 0.666667 0 0.973333 0.750000 0 0.973333 0.833333 0 0.973333 0.916667 0 0.973333 1.000000 0 0.979999 0 0 0.979999 0.083333 0 0.979999 0.166667 0 0.979999 0.250000 0 0.979999 0.333333 0 0.979999 0.416667 0 0.979999 0.500000 0 0.979999 0.583333 0 0.979999 0.666667 0 0.979999 0.750000 0 0.979999 0.833333 0 0.979999 0.916667 0 0.979999 1.000000 0 0.986666 0 0 0.986666 0.083333 0 0.986666 0.166667 0 0.986666 0.250000 0 0.986666 0.333333 0 0.986666 0.416667 0 0.986666 0.500000 0 0.986666 0.583333 0 0.986666 0.666667 0 0.986666 0.750000 0 0.986666 0.833333 0 0.986666 0.916667 0 0.986666 1.000000 0 0.993333 0 0 0.993333 0.083333 0 0.993333 0.166667 0 0.993333 0.250000 0 0.993333 0.333333 0 0.993333 0.416667 0 0.993333 0.500000 0 0.993333 0.583333 0 0.993333 0.666667 0 0.993333 0.750000 0 0.993333 0.833333 0 0.993333 0.916667 0 0.993333 1.000000 0 0.999999 0 0 0.999999 0.083333 0 0.999999 0.166667 0 0.999999 0.250000 0 0.999999 0.333333 0 0.999999 0.416667 0 0.999999 0.500000 0 0.999999 0.583333 0 0.999999 0.666667 0 0.999999 0.750000 0 0.999999 0.833333 0 0.999999 0.916667 0 0.999999 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="1963" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="3600">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 12 1 13 13 2 14 0 0 0 13 2 14 1 3 1 1 3 1 13 2 14 14 4 15 1 3 1 14 4 15 2 5 2 2 5 2 14 4 15 15 6 16 2 5 2 15 6 16 3 7 3 3 7 3 15 6 16 16 8 17 3 7 3 16 8 17 4 9 4 4 9 4 16 8 17 17 10 18 4 9 4 17 10 18 5 11 5 5 11 5 17 10 18 18 12 19 5 11 5 18 12 19 6 13 6 6 13 6 18 12 19 19 14 20 6 13 6 19 14 20 7 15 7 7 15 7 19 14 20 20 16 21 7 15 7 20 16 21 8 17 8 8 17 8 20 16 21 21 18 22 8 17 8 21 18 22 9 19 9 9 19 9 21 18 22 22 20 23 9 19 9 22 20 23 10 21 10 10 21 10 22 20 23 23 22 24 10 21 10 23 22 24 11 23 11 11 23 11 23 22 24 12 1 25 11 23 11 12 1 25 0 0 12 12 1 13 24 24 26 25 25 27 12 1 13 25 25 27 13 2 14 13 2 14 25 25 27 26 26 28 13 2 14 26 26 28 14 4 15 14 4 15 26 26 28 27 27 29 14 4 15 27 27 29 15 6 16 15 6 16 27 27 29 28 28 30 15 6 16 28 28 30 16 8 17 16 8 17 28 28 30 29 29 31 16 8 17 29 29 31 17 10 18 17 10 18 29 29 31 30 30 32 17 10 18 30 30 32 18 12 19 18 12 19 30 30 32 31 31 33 18 12 19 31 31 33 19 14 20 19 14 20 31 31 33 32 32 34 19 14 20 32 32 34 20 16 21 20 16 21 32 32 34 33 33 35 20 16 21 33 33 35 21 18 22 21 18 22 33 33 35 34 34 36 21 18 22 34 34 36 22 20 23 22 20 23 34 34 36 35 35 37 22 20 23 35 35 37 23 22 24 23 22 24 35 35 37 24 24 38 23 22 24 24 24 38 12 1 25 24 24 26 36 36 39 37 37 40 24 24 26 37 37 40 25 25 27 25 25 27 37 37 40 38 38 41 25 25 27 38 38 41 26 26 28 26 26 28 38 38 41 39 39 42 26 26 28 39 39 42 27 27 29 27 27 29 39 39 42 40 40 43 27 27 29 40 40 43 28 28 30 28 28 30 40 40 43 41 41 44 28 28 30 41 41 44 29 29 31 29 29 31 41 41 44 42 42 45 29 29 31 42 42 45 30 30 32 30 30 32 42 42 45 43 43 46 30 30 32 43 43 46 31 31 33 31 31 33 43 43 46 44 44 47 31 31 33 44 44 47 32 32 34 32 32 34 44 44 47 45 45 48 32 32 34 45 45 48 33 33 35 33 33 35 45 45 48 46 46 49 33 33 35 46 46 49 34 34 36 34 34 36 46 46 49 47 47 50 34 34 36 47 47 50 35 35 37 35 35 37 47 47 50 36 36 51 35 35 37 36 36 51 24 24 38 36 36 39 48 48 52 49 49 53 36 36 39 49 49 53 37 37 40 37 37 40 49 49 53 50 50 54 37 37 40 50 50 54 38 38 41 38 38 41 50 50 54 51 51 55 38 38 41 51 51 55 39 39 42 39 39 42 51 51 55 52 52 56 39 39 42 52 52 56 40 40 43 40 40 43 52 52 56 53 53 57 40 40 43 53 53 57 41 41 44 41 41 44 53 53 57 54 54 58 41 41 44 54 54 58 42 42 45 42 42 45 54 54 58 55 55 59 42 42 45 55 55 59 43 43 46 43 43 46 55 55 59 56 56 60 43 43 46 56 56 60 44 44 47 44 44 47 56 56 60 57 57 61 44 44 47 57 57 61 45 45 48 45 45 48 57 57 61 58 58 62 45 45 48 58 58 62 46 46 49 46 46 49 58 58 62 59 59 63 46 46 49 59 59 63 47 47 50 47 47 50 59 59 63 48 48 64 47 47 50 48 48 64 36 36 51 48 48 52 60 60 65 61 61 66 48 48 52 61 61 66 49 49 53 49 49 53 61 61 66 62 62 67 49 49 53 62 62 67 50 50 54 50 50 54 62 62 67 63 63 68 50 50 54 63 63 68 51 51 55 51 51 55 63 63 68 64 64 69 51 51 55 64 64 69 52 52 56 52 52 56 64 64 69 65 65 70 52 52 56 65 65 70 53 53 57 53 53 57 65 65 70 66 66 71 53 53 57 66 66 71 54 54 58 54 54 58 66 66 71 67 67 72 54 54 58 67 67 72 55 55 59 55 55 59 67 67 72 68 68 73 55 55 59 68 68 73 56 56 60 56 56 60 68 68 73 69 69 74 56 56 60 69 69 74 57 57 61 57 57 61 69 69 74 70 70 75 57 57 61 70 70 75 58 58 62 58 58 62 70 70 75 71 71 76 58 58 62 71 71 76 59 59 63 59 59 63 71 71 76 60 60 77 59 59 63 60 60 77 48 48 64 60 60 65 72 72 78 73 73 79 60 60 65 73 73 79 61 61 66 61 61 66 73 73 79 74 74 80 61 61 66 74 74 80 62 62 67 62 62 67 74 74 80 75 75 81 62 62 67 75 75 81 63 63 68 63 63 68 75 75 81 76 76 82 63 63 68 76 76 82 64 64 69 64 64 69 76 76 82 77 77 83 64 64 69 77 77 83 65 65 70 65 65 70 77 77 83 78 78 84 65 65 70 78 78 84 66 66 71 66 66 71 78 78 84 79 79 85 66 66 71 79 79 85 67 67 72 67 67 72 79 79 85 80 80 86 67 67 72 80 80 86 68 68 73 68 68 73 80 80 86 81 81 87 68 68 73 81 81 87 69 69 74 69 69 74 81 81 87 82 82 88 69 69 74 82 82 88 70 70 75 70 70 75 82 82 88 83 83 89 70 70 75 83 83 89 71 71 76 71 71 76 83 83 89 72 72 90 71 71 76 72 72 90 60 60 77 72 72 78 84 84 91 85 85 92 72 72 78 85 85 92 73 73 79 73 73 79 85 85 92 86 86 93 73 73 79 86 86 93 74 74 80 74 74 80 86 86 93 87 87 94 74 74 80 87 87 94 75 75 81 75 75 81 87 87 94 88 88 95 75 75 81 88 88 95 76 76 82 76 76 82 88 88 95 89 89 96 76 76 82 89 89 96 77 77 83 77 77 83 89 89 96 90 90 97 77 77 83 90 90 97 78 78 84 78 78 84 90 90 97 91 91 98 78 78 84 91 91 98 79 79 85 79 79 85 91 91 98 92 92 99 79 79 85 92 92 99 80 80 86 80 80 86 92 92 99 93 93 100 80 80 86 93 93 100 81 81 87 81 81 87 93 93 100 94 94 101 81 81 87 94 94 101 82 82 88 82 82 88 94 94 101 95 95 102 82 82 88 95 95 102 83 83 89 83 83 89 95 95 102 84 84 103 83 83 89 84 84 103 72 72 90 84 84 91 96 96 104 97 97 105 84 84 91 97 97 105 85 85 92 85 85 92 97 97 105 98 98 106 85 85 92 98 98 106 86 86 93 86 86 93 98 98 106 99 99 107 86 86 93 99 99 107 87 87 94 87 87 94 99 99 107 100 100 108 87 87 94 100 100 108 88 88 95 88 88 95 100 100 108 101 101 109 88 88 95 101 101 109 89 89 96 89 89 96 101 101 109 102 102 110 89 89 96 102 102 110 90 90 97 90 90 97 102 102 110 103 103 111 90 90 97 103 103 111 91 91 98 91 91 98 103 103 111 104 104 112 91 91 98 104 104 112 92 92 99 92 92 99 104 104 112 105 105 113 92 92 99 105 105 113 93 93 100 93 93 100 105 105 113 106 106 114 93 93 100 106 106 114 94 94 101 94 94 101 106 106 114 107 107 115 94 94 101 107 107 115 95 95 102 95 95 102 107 107 115 96 96 116 95 95 102 96 96 116 84 84 103 96 96 104 108 108 117 109 109 118 96 96 104 109 109 118 97 97 105 97 97 105 109 109 118 110 110 119 97 97 105 110 110 119 98 98 106 98 98 106 110 110 119 111 111 120 98 98 106 111 111 120 99 99 107 99 99 107 111 111 120 112 112 121 99 99 107 112 112 121 100 100 108 100 100 108 112 112 121 113 113 122 100 100 108 113 113 122 101 101 109 101 101 109 113 113 122 114 114 123 101 101 109 114 114 123 102 102 110 102 102 110 114 114 123 115 115 124 102 102 110 115 115 124 103 103 111 103 103 111 115 115 124 116 116 125 103 103 111 116 116 125 104 104 112 104 104 112 116 116 125 117 117 126 104 104 112 117 117 126 105 105 113 105 105 113 117 117 126 118 118 127 105 105 113 118 118 127 106 106 114 106 106 114 118 118 127 119 119 128 106 106 114 119 119 128 107 107 115 107 107 115 119 119 128 108 108 129 107 107 115 108 108 129 96 96 116 108 108 117 120 120 130 121 121 131 108 108 117 121 121 131 109 109 118 109 109 118 121 121 131 122 122 132 109 109 118 122 122 132 110 110 119 110 110 119 122 122 132 123 123 133 110 110 119 123 123 133 111 111 120 111 111 120 123 123 133 124 124 134 111 111 120 124 124 134 112 112 121 112 112 121 124 124 134 125 125 135 112 112 121 125 125 135 113 113 122 113 113 122 125 125 135 126 126 136 113 113 122 126 126 136 114 114 123 114 114 123 126 126 136 127 127 137 114 114 123 127 127 137 115 115 124 115 115 124 127 127 137 128 128 138 115 115 124 128 128 138 116 116 125 116 116 125 128 128 138 129 129 139 116 116 125 129 129 139 117 117 126 117 117 126 129 129 139 130 130 140 117 117 126 130 130 140 118 118 127 118 118 127 130 130 140 131 131 141 118 118 127 131 131 141 119 119 128 119 119 128 131 131 141 120 120 142 119 119 128 120 120 142 108 108 129 120 120 130 132 132 143 133 133 144 120 120 130 133 133 144 121 121 131 121 121 131 133 133 144 134 134 145 121 121 131 134 134 145 122 122 132 122 122 132 134 134 145 135 135 146 122 122 132 135 135 146 123 123 133 123 123 133 135 135 146 136 136 147 123 123 133 136 136 147 124 124 134 124 124 134 136 136 147 137 137 148 124 124 134 137 137 148 125 125 135 125 125 135 137 137 148 138 138 149 125 125 135 138 138 149 126 126 136 126 126 136 138 138 149 139 139 150 126 126 136 139 139 150 127 127 137 127 127 137 139 139 150 140 140 151 127 127 137 140 140 151 128 128 138 128 128 138 140 140 151 141 141 152 128 128 138 141 141 152 129 129 139 129 129 139 141 141 152 142 142 153 129 129 139 142 142 153 130 130 140 130 130 140 142 142 153 143 143 154 130 130 140 143 143 154 131 131 141 131 131 141 143 143 154 132 132 155 131 131 141 132 132 155 120 120 142 132 132 143 144 144 156 145 145 157 132 132 143 145 145 157 133 133 144 133 133 144 145 145 157 146 146 158 133 133 144 146 146 158 134 134 145 134 134 145 146 146 158 147 147 159 134 134 145 147 147 159 135 135 146 135 135 146 147 147 159 148 148 160 135 135 146 148 148 160 136 136 147 136 136 147 148 148 160 149 149 161 136 136 147 149 149 161 137 137 148 137 137 148 149 149 161 150 150 162 137 137 148 150 150 162 138 138 149 138 138 149 150 150 162 151 151 163 138 138 149 151 151 163 139 139 150 139 139 150 151 151 163 152 152 164 139 139 150 152 152 164 140 140 151 140 140 151 152 152 164 153 153 165 140 140 151 153 153 165 141 141 152 141 141 152 153 153 165 154 154 166 141 141 152 154 154 166 142 142 153 142 142 153 154 154 166 155 155 167 142 142 153 155 155 167 143 143 154 143 143 154 155 155 167 144 144 168 143 143 154 144 144 168 132 132 155 144 144 156 156 156 169 157 157 170 144 144 156 157 157 170 145 145 157 145 145 157 157 157 170 158 158 171 145 145 157 158 158 171 146 146 158 146 146 158 158 158 171 159 159 172 146 146 158 159 159 172 147 147 159 147 147 159 159 159 172 160 160 173 147 147 159 160 160 173 148 148 160 148 148 160 160 160 173 161 161 174 148 148 160 161 161 174 149 149 161 149 149 161 161 161 174 162 162 175 149 149 161 162 162 175 150 150 162 150 150 162 162 162 175 163 163 176 150 150 162 163 163 176 151 151 163 151 151 163 163 163 176 164 164 177 151 151 163 164 164 177 152 152 164 152 152 164 164 164 177 165 165 178 152 152 164 165 165 178 153 153 165 153 153 165 165 165 178 166 166 179 153 153 165 166 166 179 154 154 166 154 154 166 166 166 179 167 167 180 154 154 166 167 167 180 155 155 167 155 155 167 167 167 180 156 156 181 155 155 167 156 156 181 144 144 168 156 156 169 168 168 182 169 169 183 156 156 169 169 169 183 157 157 170 157 157 170 169 169 183 170 170 184 157 157 170 170 170 184 158 158 171 158 158 171 170 170 184 171 171 185 158 158 171 171 171 185 159 159 172 159 159 172 171 171 185 172 172 186 159 159 172 172 172 186 160 160 173 160 160 173 172 172 186 173 173 187 160 160 173 173 173 187 161 161 174 161 161 174 173 173 187 174 174 188 161 161 174 174 174 188 162 162 175 162 162 175 174 174 188 175 175 189 162 162 175 175 175 189 163 163 176 163 163 176 175 175 189 176 176 190 163 163 176 176 176 190 164 164 177 164 164 177 176 176 190 177 177 191 164 164 177 177 177 191 165 165 178 165 165 178 177 177 191 178 178 192 165 165 178 178 178 192 166 166 179 166 166 179 178 178 192 179 179 193 166 166 179 179 179 193 167 167 180 167 167 180 179 179 193 168 168 194 167 167 180 168 168 194 156 156 181 168 168 182 180 180 195 181 181 196 168 168 182 181 181 196 169 169 183 169 169 183 181 181 196 182 182 197 169 169 183 182 182 197 170 170 184 170 170 184 182 182 197 183 183 198 170 170 184 183 183 198 171 171 185 171 171 185 183 183 198 184 184 199 171 171 185 184 184 199 172 172 186 172 172 186 184 184 199 185 185 200 172 172 186 185 185 200 173 173 187 173 173 187 185 185 200 186 186 201 173 173 187 186 186 201 174 174 188 174 174 188 186 186 201 187 187 202 174 174 188 187 187 202 175 175 189 175 175 189 187 187 202 188 188 203 175 175 189 188 188 203 176 176 190 176 176 190 188 188 203 189 189 204 176 176 190 189 189 204 177 177 191 177 177 191 189 189 204 190 190 205 177 177 191 190 190 205 178 178 192 178 178 192 190 190 205 191 191 206 178 178 192 191 191 206 179 179 193 179 179 193 191 191 206 180 180 207 179 179 193 180 180 207 168 168 194 180 180 195 192 192 208 193 193 209 180 180 195 193 193 209 181 181 196 181 181 196 193 193 209 194 194 210 181 181 196 194 194 210 182 182 197 182 182 197 194 194 210 195 195 211 182 182 197 195 195 211 183 183 198 183 183 198 195 195 211 196 196 212 183 183 198 196 196 212 184 184 199 184 184 199 196 196 212 197 197 213 184 184 199 197 197 213 185 185 200 185 185 200 197 197 213 198 198 214 185 185 200 198 198 214 186 186 201 186 186 201 198 198 214 199 199 215 186 186 201 199 199 215 187 187 202 187 187 202 199 199 215 200 200 216 187 187 202 200 200 216 188 188 203 188 188 203 200 200 216 201 201 217 188 188 203 201 201 217 189 189 204 189 189 204 201 201 217 202 202 218 189 189 204 202 202 218 190 190 205 190 190 205 202 202 218 203 203 219 190 190 205 203 203 219 191 191 206 191 191 206 203 203 219 192 192 220 191 191 206 192 192 220 180 180 207 192 192 208 204 204 221 205 205 222 192 192 208 205 205 222 193 193 209 193 193 209 205 205 222 206 206 223 193 193 209 206 206 223 194 194 210 194 194 210 206 206 223 207 207 224 194 194 210 207 207 224 195 195 211 195 195 211 207 207 224 208 208 225 195 195 211 208 208 225 196 196 212 196 196 212 208 208 225 209 209 226 196 196 212 209 209 226 197 197 213 197 197 213 209 209 226 210 210 227 197 197 213 210 210 227 198 198 214 198 198 214 210 210 227 211 211 228 198 198 214 211 211 228 199 199 215 199 199 215 211 211 228 212 212 229 199 199 215 212 212 229 200 200 216 200 200 216 212 212 229 213 213 230 200 200 216 213 213 230 201 201 217 201 201 217 213 213 230 214 214 231 201 201 217 214 214 231 202 202 218 202 202 218 214 214 231 215 215 232 202 202 218 215 215 232 203 203 219 203 203 219 215 215 232 204 204 233 203 203 219 204 204 233 192 192 220 204 204 221 216 216 234 217 217 235 204 204 221 217 217 235 205 205 222 205 205 222 217 217 235 218 218 236 205 205 222 218 218 236 206 206 223 206 206 223 218 218 236 219 219 237 206 206 223 219 219 237 207 207 224 207 207 224 219 219 237 220 220 238 207 207 224 220 220 238 208 208 225 208 208 225 220 220 238 221 221 239 208 208 225 221 221 239 209 209 226 209 209 226 221 221 239 222 222 240 209 209 226 222 222 240 210 210 227 210 210 227 222 222 240 223 223 241 210 210 227 223 223 241 211 211 228 211 211 228 223 223 241 224 224 242 211 211 228 224 224 242 212 212 229 212 212 229 224 224 242 225 225 243 212 212 229 225 225 243 213 213 230 213 213 230 225 225 243 226 226 244 213 213 230 226 226 244 214 214 231 214 214 231 226 226 244 227 227 245 214 214 231 227 227 245 215 215 232 215 215 232 227 227 245 216 216 246 215 215 232 216 216 246 204 204 233 216 216 234 228 228 247 229 229 248 216 216 234 229 229 248 217 217 235 217 217 235 229 229 248 230 230 249 217 217 235 230 230 249 218 218 236 218 218 236 230 230 249 231 231 250 218 218 236 231 231 250 219 219 237 219 219 237 231 231 250 232 232 251 219 219 237 232 232 251 220 220 238 220 220 238 232 232 251 233 233 252 220 220 238 233 233 252 221 221 239 221 221 239 233 233 252 234 234 253 221 221 239 234 234 253 222 222 240 222 222 240 234 234 253 235 235 254 222 222 240 235 235 254 223 223 241 223 223 241 235 235 254 236 236 255 223 223 241 236 236 255 224 224 242 224 224 242 236 236 255 237 237 256 224 224 242 237 237 256 225 225 243 225 225 243 237 237 256 238 238 257 225 225 243 238 238 257 226 226 244 226 226 244 238 238 257 239 239 258 226 226 244 239 239 258 227 227 245 227 227 245 239 239 258 228 228 259 227 227 245 228 228 259 216 216 246 228 228 247 240 240 260 241 241 261 228 228 247 241 241 261 229 229 248 229 229 248 241 241 261 242 242 262 229 229 248 242 242 262 230 230 249 230 230 249 242 242 262 243 243 263 230 230 249 243 243 263 231 231 250 231 231 250 243 243 263 244 244 264 231 231 250 244 244 264 232 232 251 232 232 251 244 244 264 245 245 265 232 232 251 245 245 265 233 233 252 233 233 252 245 245 265 246 246 266 233 233 252 246 246 266 234 234 253 234 234 253 246 246 266 247 247 267 234 234 253 247 247 267 235 235 254 235 235 254 247 247 267 248 248 268 235 235 254 248 248 268 236 236 255 236 236 255 248 248 268 249 249 269 236 236 255 249 249 269 237 237 256 237 237 256 249 249 269 250 250 270 237 237 256 250 250 270 238 238 257 238 238 257 250 250 270 251 251 271 238 238 257 251 251 271 239 239 258 239 239 258 251 251 271 240 240 272 239 239 258 240 240 272 228 228 259 240 240 260 252 252 273 253 253 274 240 240 260 253 253 274 241 241 261 241 241 261 253 253 274 254 254 275 241 241 261 254 254 275 242 242 262 242 242 262 254 254 275 255 255 276 242 242 262 255 255 276 243 243 263 243 243 263 255 255 276 256 256 277 243 243 263 256 256 277 244 244 264 244 244 264 256 256 277 257 257 278 244 244 264 257 257 278 245 245 265 245 245 265 257 257 278 258 258 279 245 245 265 258 258 279 246 246 266 246 246 266 258 258 279 259 259 280 246 246 266 259 259 280 247 247 267 247 247 267 259 259 280 260 260 281 247 247 267 260 260 281 248 248 268 248 248 268 260 260 281 261 261 282 248 248 268 261 261 282 249 249 269 249 249 269 261 261 282 262 262 283 249 249 269 262 262 283 250 250 270 250 250 270 262 262 283 263 263 284 250 250 270 263 263 284 251 251 271 251 251 271 263 263 284 252 252 285 251 251 271 252 252 285 240 240 272 252 252 273 264 264 286 265 265 287 252 252 273 265 265 287 253 253 274 253 253 274 265 265 287 266 266 288 253 253 274 266 266 288 254 254 275 254 254 275 266 266 288 267 267 289 254 254 275 267 267 289 255 255 276 255 255 276 267 267 289 268 268 290 255 255 276 268 268 290 256 256 277 256 256 277 268 268 290 269 269 291 256 256 277 269 269 291 257 257 278 257 257 278 269 269 291 270 270 292 257 257 278 270 270 292 258 258 279 258 258 279 270 270 292 271 271 293 258 258 279 271 271 293 259 259 280 259 259 280 271 271 293 272 272 294 259 259 280 272 272 294 260 260 281 260 260 281 272 272 294 273 273 295 260 260 281 273 273 295 261 261 282 261 261 282 273 273 295 274 274 296 261 261 282 274 274 296 262 262 283 262 262 283 274 274 296 275 275 297 262 262 283 275 275 297 263 263 284 263 263 284 275 275 297 264 264 298 263 263 284 264 264 298 252 252 285 264 264 286 276 276 299 277 277 300 264 264 286 277 277 300 265 265 287 265 265 287 277 277 300 278 278 301 265 265 287 278 278 301 266 266 288 266 266 288 278 278 301 279 279 302 266 266 288 279 279 302 267 267 289 267 267 289 279 279 302 280 280 303 267 267 289 280 280 303 268 268 290 268 268 290 280 280 303 281 281 304 268 268 290 281 281 304 269 269 291 269 269 291 281 281 304 282 282 305 269 269 291 282 282 305 270 270 292 270 270 292 282 282 305 283 283 306 270 270 292 283 283 306 271 271 293 271 271 293 283 283 306 284 284 307 271 271 293 284 284 307 272 272 294 272 272 294 284 284 307 285 285 308 272 272 294 285 285 308 273 273 295 273 273 295 285 285 308 286 286 309 273 273 295 286 286 309 274 274 296 274 274 296 286 286 309 287 287 310 274 274 296 287 287 310 275 275 297 275 275 297 287 287 310 276 276 311 275 275 297 276 276 311 264 264 298 276 276 299 288 288 312 289 289 313 276 276 299 289 289 313 277 277 300 277 277 300 289 289 313 290 290 314 277 277 300 290 290 314 278 278 301 278 278 301 290 290 314 291 291 315 278 278 301 291 291 315 279 279 302 279 279 302 291 291 315 292 292 316 279 279 302 292 292 316 280 280 303 280 280 303 292 292 316 293 293 317 280 280 303 293 293 317 281 281 304 281 281 304 293 293 317 294 294 318 281 281 304 294 294 318 282 282 305 282 282 305 294 294 318 295 295 319 282 282 305 295 295 319 283 283 306 283 283 306 295 295 319 296 296 320 283 283 306 296 296 320 284 284 307 284 284 307 296 296 320 297 297 321 284 284 307 297 297 321 285 285 308 285 285 308 297 297 321 298 298 322 285 285 308 298 298 322 286 286 309 286 286 309 298 298 322 299 299 323 286 286 309 299 299 323 287 287 310 287 287 310 299 299 323 288 288 324 287 287 310 288 288 324 276 276 311 288 288 312 300 300 325 301 301 326 288 288 312 301 301 326 289 289 313 289 289 313 301 301 326 302 302 327 289 289 313 302 302 327 290 290 314 290 290 314 302 302 327 303 303 328 290 290 314 303 303 328 291 291 315 291 291 315 303 303 328 304 304 329 291 291 315 304 304 329 292 292 316 292 292 316 304 304 329 305 305 330 292 292 316 305 305 330 293 293 317 293 293 317 305 305 330 306 306 331 293 293 317 306 306 331 294 294 318 294 294 318 306 306 331 307 307 332 294 294 318 307 307 332 295 295 319 295 295 319 307 307 332 308 308 333 295 295 319 308 308 333 296 296 320 296 296 320 308 308 333 309 309 334 296 296 320 309 309 334 297 297 321 297 297 321 309 309 334 310 310 335 297 297 321 310 310 335 298 298 322 298 298 322 310 310 335 311 311 336 298 298 322 311 311 336 299 299 323 299 299 323 311 311 336 300 300 337 299 299 323 300 300 337 288 288 324 300 300 325 312 312 338 313 313 339 300 300 325 313 313 339 301 301 326 301 301 326 313 313 339 314 314 340 301 301 326 314 314 340 302 302 327 302 302 327 314 314 340 315 315 341 302 302 327 315 315 341 303 303 328 303 303 328 315 315 341 316 316 342 303 303 328 316 316 342 304 304 329 304 304 329 316 316 342 317 317 343 304 304 329 317 317 343 305 305 330 305 305 330 317 317 343 318 318 344 305 305 330 318 318 344 306 306 331 306 306 331 318 318 344 319 319 345 306 306 331 319 319 345 307 307 332 307 307 332 319 319 345 320 320 346 307 307 332 320 320 346 308 308 333 308 308 333 320 320 346 321 321 347 308 308 333 321 321 347 309 309 334 309 309 334 321 321 347 322 322 348 309 309 334 322 322 348 310 310 335 310 310 335 322 322 348 323 323 349 310 310 335 323 323 349 311 311 336 311 311 336 323 323 349 312 312 350 311 311 336 312 312 350 300 300 337 312 312 338 324 324 351 325 325 352 312 312 338 325 325 352 313 313 339 313 313 339 325 325 352 326 326 353 313 313 339 326 326 353 314 314 340 314 314 340 326 326 353 327 327 354 314 314 340 327 327 354 315 315 341 315 315 341 327 327 354 328 328 355 315 315 341 328 328 355 316 316 342 316 316 342 328 328 355 329 329 356 316 316 342 329 329 356 317 317 343 317 317 343 329 329 356 330 330 357 317 317 343 330 330 357 318 318 344 318 318 344 330 330 357 331 331 358 318 318 344 331 331 358 319 319 345 319 319 345 331 331 358 332 332 359 319 319 345 332 332 359 320 320 346 320 320 346 332 332 359 333 333 360 320 320 346 333 333 360 321 321 347 321 321 347 333 333 360 334 334 361 321 321 347 334 334 361 322 322 348 322 322 348 334 334 361 335 335 362 322 322 348 335 335 362 323 323 349 323 323 349 335 335 362 324 324 363 323 323 349 324 324 363 312 312 350 324 324 351 336 336 364 337 337 365 324 324 351 337 337 365 325 325 352 325 325 352 337 337 365 338 338 366 325 325 352 338 338 366 326 326 353 326 326 353 338 338 366 339 339 367 326 326 353 339 339 367 327 327 354 327 327 354 339 339 367 340 340 368 327 327 354 340 340 368 328 328 355 328 328 355 340 340 368 341 341 369 328 328 355 341 341 369 329 329 356 329 329 356 341 341 369 342 342 370 329 329 356 342 342 370 330 330 357 330 330 357 342 342 370 343 343 371 330 330 357 343 343 371 331 331 358 331 331 358 343 343 371 344 344 372 331 331 358 344 344 372 332 332 359 332 332 359 344 344 372 345 345 373 332 332 359 345 345 373 333 333 360 333 333 360 345 345 373 346 346 374 333 333 360 346 346 374 334 334 361 334 334 361 346 346 374 347 347 375 334 334 361 347 347 375 335 335 362 335 335 362 347 347 375 336 336 376 335 335 362 336 336 376 324 324 363 336 336 364 348 348 377 349 349 378 336 336 364 349 349 378 337 337 365 337 337 365 349 349 378 350 350 379 337 337 365 350 350 379 338 338 366 338 338 366 350 350 379 351 351 380 338 338 366 351 351 380 339 339 367 339 339 367 351 351 380 352 352 381 339 339 367 352 352 381 340 340 368 340 340 368 352 352 381 353 353 382 340 340 368 353 353 382 341 341 369 341 341 369 353 353 382 354 354 383 341 341 369 354 354 383 342 342 370 342 342 370 354 354 383 355 355 384 342 342 370 355 355 384 343 343 371 343 343 371 355 355 384 356 356 385 343 343 371 356 356 385 344 344 372 344 344 372 356 356 385 357 357 386 344 344 372 357 357 386 345 345 373 345 345 373 357 357 386 358 358 387 345 345 373 358 358 387 346 346 374 346 346 374 358 358 387 359 359 388 346 346 374 359 359 388 347 347 375 347 347 375 359 359 388 348 348 389 347 347 375 348 348 389 336 336 376 348 348 377 360 360 390 361 361 391 348 348 377 361 361 391 349 349 378 349 349 378 361 361 391 362 362 392 349 349 378 362 362 392 350 350 379 350 350 379 362 362 392 363 363 393 350 350 379 363 363 393 351 351 380 351 351 380 363 363 393 364 364 394 351 351 380 364 364 394 352 352 381 352 352 381 364 364 394 365 365 395 352 352 381 365 365 395 353 353 382 353 353 382 365 365 395 366 366 396 353 353 382 366 366 396 354 354 383 354 354 383 366 366 396 367 367 397 354 354 383 367 367 397 355 355 384 355 355 384 367 367 397 368 368 398 355 355 384 368 368 398 356 356 385 356 356 385 368 368 398 369 369 399 356 356 385 369 369 399 357 357 386 357 357 386 369 369 399 370 370 400 357 357 386 370 370 400 358 358 387 358 358 387 370 370 400 371 371 401 358 358 387 371 371 401 359 359 388 359 359 388 371 371 401 360 360 402 359 359 388 360 360 402 348 348 389 360 360 390 372 372 403 373 373 404 360 360 390 373 373 404 361 361 391 361 361 391 373 373 404 374 374 405 361 361 391 374 374 405 362 362 392 362 362 392 374 374 405 375 375 406 362 362 392 375 375 406 363 363 393 363 363 393 375 375 406 376 376 407 363 363 393 376 376 407 364 364 394 364 364 394 376 376 407 377 377 408 364 364 394 377 377 408 365 365 395 365 365 395 377 377 408 378 378 409 365 365 395 378 378 409 366 366 396 366 366 396 378 378 409 379 379 410 366 366 396 379 379 410 367 367 397 367 367 397 379 379 410 380 380 411 367 367 397 380 380 411 368 368 398 368 368 398 380 380 411 381 381 412 368 368 398 381 381 412 369 369 399 369 369 399 381 381 412 382 382 413 369 369 399 382 382 413 370 370 400 370 370 400 382 382 413 383 383 414 370 370 400 383 383 414 371 371 401 371 371 401 383 383 414 372 372 415 371 371 401 372 372 415 360 360 402 372 372 403 384 384 416 385 385 417 372 372 403 385 385 417 373 373 404 373 373 404 385 385 417 386 386 418 373 373 404 386 386 418 374 374 405 374 374 405 386 386 418 387 387 419 374 374 405 387 387 419 375 375 406 375 375 406 387 387 419 388 388 420 375 375 406 388 388 420 376 376 407 376 376 407 388 388 420 389 389 421 376 376 407 389 389 421 377 377 408 377 377 408 389 389 421 390 390 422 377 377 408 390 390 422 378 378 409 378 378 409 390 390 422 391 391 423 378 378 409 391 391 423 379 379 410 379 379 410 391 391 423 392 392 424 379 379 410 392 392 424 380 380 411 380 380 411 392 392 424 393 393 425 380 380 411 393 393 425 381 381 412 381 381 412 393 393 425 394 394 426 381 381 412 394 394 426 382 382 413 382 382 413 394 394 426 395 395 427 382 382 413 395 395 427 383 383 414 383 383 414 395 395 427 384 384 428 383 383 414 384 384 428 372 372 415 384 384 416 396 396 429 397 397 430 384 384 416 397 397 430 385 385 417 385 385 417 397 397 430 398 398 431 385 385 417 398 398 431 386 386 418 386 386 418 398 398 431 399 399 432 386 386 418 399 399 432 387 387 419 387 387 419 399 399 432 400 400 433 387 387 419 400 400 433 388 388 420 388 388 420 400 400 433 401 401 434 388 388 420 401 401 434 389 389 421 389 389 421 401 401 434 402 402 435 389 389 421 402 402 435 390 390 422 390 390 422 402 402 435 403 403 436 390 390 422 403 403 436 391 391 423 391 391 423 403 403 436 404 404 437 391 391 423 404 404 437 392 392 424 392 392 424 404 404 437 405 405 438 392 392 424 405 405 438 393 393 425 393 393 425 405 405 438 406 406 439 393 393 425 406 406 439 394 394 426 394 394 426 406 406 439 407 407 440 394 394 426 407 407 440 395 395 427 395 395 427 407 407 440 396 396 441 395 395 427 396 396 441 384 384 428 396 396 429 408 408 442 409 409 443 396 396 429 409 409 443 397 397 430 397 397 430 409 409 443 410 410 444 397 397 430 410 410 444 398 398 431 398 398 431 410 410 444 411 411 445 398 398 431 411 411 445 399 399 432 399 399 432 411 411 445 412 412 446 399 399 432 412 412 446 400 400 433 400 400 433 412 412 446 413 413 447 400 400 433 413 413 447 401 401 434 401 401 434 413 413 447 414 414 448 401 401 434 414 414 448 402 402 435 402 402 435 414 414 448 415 415 449 402 402 435 415 415 449 403 403 436 403 403 436 415 415 449 416 416 450 403 403 436 416 416 450 404 404 437 404 404 437 416 416 450 417 417 451 404 404 437 417 417 451 405 405 438 405 405 438 417 417 451 418 418 452 405 405 438 418 418 452 406 406 439 406 406 439 418 418 452 419 419 453 406 406 439 419 419 453 407 407 440 407 407 440 419 419 453 408 408 454 407 407 440 408 408 454 396 396 441 408 408 442 420 420 455 421 421 456 408 408 442 421 421 456 409 409 443 409 409 443 421 421 456 422 422 457 409 409 443 422 422 457 410 410 444 410 410 444 422 422 457 423 423 458 410 410 444 423 423 458 411 411 445 411 411 445 423 423 458 424 424 459 411 411 445 424 424 459 412 412 446 412 412 446 424 424 459 425 425 460 412 412 446 425 425 460 413 413 447 413 413 447 425 425 460 426 426 461 413 413 447 426 426 461 414 414 448 414 414 448 426 426 461 427 427 462 414 414 448 427 427 462 415 415 449 415 415 449 427 427 462 428 428 463 415 415 449 428 428 463 416 416 450 416 416 450 428 428 463 429 429 464 416 416 450 429 429 464 417 417 451 417 417 451 429 429 464 430 430 465 417 417 451 430 430 465 418 418 452 418 418 452 430 430 465 431 431 466 418 418 452 431 431 466 419 419 453 419 419 453 431 431 466 420 420 467 419 419 453 420 420 467 408 408 454 420 420 455 432 432 468 433 433 469 420 420 455 433 433 469 421 421 456 421 421 456 433 433 469 434 434 470 421 421 456 434 434 470 422 422 457 422 422 457 434 434 470 435 435 471 422 422 457 435 435 471 423 423 458 423 423 458 435 435 471 436 436 472 423 423 458 436 436 472 424 424 459 424 424 459 436 436 472 437 437 473 424 424 459 437 437 473 425 425 460 425 425 460 437 437 473 438 438 474 425 425 460 438 438 474 426 426 461 426 426 461 438 438 474 439 439 475 426 426 461 439 439 475 427 427 462 427 427 462 439 439 475 440 440 476 427 427 462 440 440 476 428 428 463 428 428 463 440 440 476 441 441 477 428 428 463 441 441 477 429 429 464 429 429 464 441 441 477 442 442 478 429 429 464 442 442 478 430 430 465 430 430 465 442 442 478 443 443 479 430 430 465 443 443 479 431 431 466 431 431 466 443 443 479 432 432 480 431 431 466 432 432 480 420 420 467 432 432 468 444 444 481 445 445 482 432 432 468 445 445 482 433 433 469 433 433 469 445 445 482 446 446 483 433 433 469 446 446 483 434 434 470 434 434 470 446 446 483 447 447 484 434 434 470 447 447 484 435 435 471 435 435 471 447 447 484 448 448 485 435 435 471 448 448 485 436 436 472 436 436 472 448 448 485 449 449 486 436 436 472 449 449 486 437 437 473 437 437 473 449 449 486 450 450 487 437 437 473 450 450 487 438 438 474 438 438 474 450 450 487 451 451 488 438 438 474 451 451 488 439 439 475 439 439 475 451 451 488 452 452 489 439 439 475 452 452 489 440 440 476 440 440 476 452 452 489 453 453 490 440 440 476 453 453 490 441 441 477 441 441 477 453 453 490 454 454 491 441 441 477 454 454 491 442 442 478 442 442 478 454 454 491 455 455 492 442 442 478 455 455 492 443 443 479 443 443 479 455 455 492 444 444 493 443 443 479 444 444 493 432 432 480 444 444 481 456 456 494 457 457 495 444 444 481 457 457 495 445 445 482 445 445 482 457 457 495 458 458 496 445 445 482 458 458 496 446 446 483 446 446 483 458 458 496 459 459 497 446 446 483 459 459 497 447 447 484 447 447 484 459 459 497 460 460 498 447 447 484 460 460 498 448 448 485 448 448 485 460 460 498 461 461 499 448 448 485 461 461 499 449 449 486 449 449 486 461 461 499 462 462 500 449 449 486 462 462 500 450 450 487 450 450 487 462 462 500 463 463 501 450 450 487 463 463 501 451 451 488 451 451 488 463 463 501 464 464 502 451 451 488 464 464 502 452 452 489 452 452 489 464 464 502 465 465 503 452 452 489 465 465 503 453 453 490 453 453 490 465 465 503 466 466 504 453 453 490 466 466 504 454 454 491 454 454 491 466 466 504 467 467 505 454 454 491 467 467 505 455 455 492 455 455 492 467 467 505 456 456 506 455 455 492 456 456 506 444 444 493 456 456 494 468 468 507 469 469 508 456 456 494 469 469 508 457 457 495 457 457 495 469 469 508 470 470 509 457 457 495 470 470 509 458 458 496 458 458 496 470 470 509 471 471 510 458 458 496 471 471 510 459 459 497 459 459 497 471 471 510 472 472 511 459 459 497 472 472 511 460 460 498 460 460 498 472 472 511 473 473 512 460 460 498 473 473 512 461 461 499 461 461 499 473 473 512 474 474 513 461 461 499 474 474 513 462 462 500 462 462 500 474 474 513 475 475 514 462 462 500 475 475 514 463 463 501 463 463 501 475 475 514 476 476 515 463 463 501 476 476 515 464 464 502 464 464 502 476 476 515 477 477 516 464 464 502 477 477 516 465 465 503 465 465 503 477 477 516 478 478 517 465 465 503 478 478 517 466 466 504 466 466 504 478 478 517 479 479 518 466 466 504 479 479 518 467 467 505 467 467 505 479 479 518 468 468 519 467 467 505 468 468 519 456 456 506 468 468 507 480 480 520 481 481 521 468 468 507 481 481 521 469 469 508 469 469 508 481 481 521 482 482 522 469 469 508 482 482 522 470 470 509 470 470 509 482 482 522 483 483 523 470 470 509 483 483 523 471 471 510 471 471 510 483 483 523 484 484 524 471 471 510 484 484 524 472 472 511 472 472 511 484 484 524 485 485 525 472 472 511 485 485 525 473 473 512 473 473 512 485 485 525 486 486 526 473 473 512 486 486 526 474 474 513 474 474 513 486 486 526 487 487 527 474 474 513 487 487 527 475 475 514 475 475 514 487 487 527 488 488 528 475 475 514 488 488 528 476 476 515 476 476 515 488 488 528 489 489 529 476 476 515 489 489 529 477 477 516 477 477 516 489 489 529 490 490 530 477 477 516 490 490 530 478 478 517 478 478 517 490 490 530 491 491 531 478 478 517 491 491 531 479 479 518 479 479 518 491 491 531 480 480 532 479 479 518 480 480 532 468 468 519 480 480 520 492 492 533 493 493 534 480 480 520 493 493 534 481 481 521 481 481 521 493 493 534 494 494 535 481 481 521 494 494 535 482 482 522 482 482 522 494 494 535 495 495 536 482 482 522 495 495 536 483 483 523 483 483 523 495 495 536 496 496 537 483 483 523 496 496 537 484 484 524 484 484 524 496 496 537 497 497 538 484 484 524 497 497 538 485 485 525 485 485 525 497 497 538 498 498 539 485 485 525 498 498 539 486 486 526 486 486 526 498 498 539 499 499 540 486 486 526 499 499 540 487 487 527 487 487 527 499 499 540 500 500 541 487 487 527 500 500 541 488 488 528 488 488 528 500 500 541 501 501 542 488 488 528 501 501 542 489 489 529 489 489 529 501 501 542 502 502 543 489 489 529 502 502 543 490 490 530 490 490 530 502 502 543 503 503 544 490 490 530 503 503 544 491 491 531 491 491 531 503 503 544 492 492 545 491 491 531 492 492 545 480 480 532 492 492 533 504 504 546 505 505 547 492 492 533 505 505 547 493 493 534 493 493 534 505 505 547 506 506 548 493 493 534 506 506 548 494 494 535 494 494 535 506 506 548 507 507 549 494 494 535 507 507 549 495 495 536 495 495 536 507 507 549 508 508 550 495 495 536 508 508 550 496 496 537 496 496 537 508 508 550 509 509 551 496 496 537 509 509 551 497 497 538 497 497 538 509 509 551 510 510 552 497 497 538 510 510 552 498 498 539 498 498 539 510 510 552 511 511 553 498 498 539 511 511 553 499 499 540 499 499 540 511 511 553 512 512 554 499 499 540 512 512 554 500 500 541 500 500 541 512 512 554 513 513 555 500 500 541 513 513 555 501 501 542 501 501 542 513 513 555 514 514 556 501 501 542 514 514 556 502 502 543 502 502 543 514 514 556 515 515 557 502 502 543 515 515 557 503 503 544 503 503 544 515 515 557 504 504 558 503 503 544 504 504 558 492 492 545 504 504 546 516 516 559 517 517 560 504 504 546 517 517 560 505 505 547 505 505 547 517 517 560 518 518 561 505 505 547 518 518 561 506 506 548 506 506 548 518 518 561 519 519 562 506 506 548 519 519 562 507 507 549 507 507 549 519 519 562 520 520 563 507 507 549 520 520 563 508 508 550 508 508 550 520 520 563 521 521 564 508 508 550 521 521 564 509 509 551 509 509 551 521 521 564 522 522 565 509 509 551 522 522 565 510 510 552 510 510 552 522 522 565 523 523 566 510 510 552 523 523 566 511 511 553 511 511 553 523 523 566 524 524 567 511 511 553 524 524 567 512 512 554 512 512 554 524 524 567 525 525 568 512 512 554 525 525 568 513 513 555 513 513 555 525 525 568 526 526 569 513 513 555 526 526 569 514 514 556 514 514 556 526 526 569 527 527 570 514 514 556 527 527 570 515 515 557 515 515 557 527 527 570 516 516 571 515 515 557 516 516 571 504 504 558 516 516 559 528 528 572 529 529 573 516 516 559 529 529 573 517 517 560 517 517 560 529 529 573 530 530 574 517 517 560 530 530 574 518 518 561 518 518 561 530 530 574 531 531 575 518 518 561 531 531 575 519 519 562 519 519 562 531 531 575 532 532 576 519 519 562 532 532 576 520 520 563 520 520 563 532 532 576 533 533 577 520 520 563 533 533 577 521 521 564 521 521 564 533 533 577 534 534 578 521 521 564 534 534 578 522 522 565 522 522 565 534 534 578 535 535 579 522 522 565 535 535 579 523 523 566 523 523 566 535 535 579 536 536 580 523 523 566 536 536 580 524 524 567 524 524 567 536 536 580 537 537 581 524 524 567 537 537 581 525 525 568 525 525 568 537 537 581 538 538 582 525 525 568 538 538 582 526 526 569 526 526 569 538 538 582 539 539 583 526 526 569 539 539 583 527 527 570 527 527 570 539 539 583 528 528 584 527 527 570 528 528 584 516 516 571 528 528 572 540 540 585 541 541 586 528 528 572 541 541 586 529 529 573 529 529 573 541 541 586 542 542 587 529 529 573 542 542 587 530 530 574 530 530 574 542 542 587 543 543 588 530 530 574 543 543 588 531 531 575 531 531 575 543 543 588 544 544 589 531 531 575 544 544 589 532 532 576 532 532 576 544 544 589 545 545 590 532 532 576 545 545 590 533 533 577 533 533 577 545 545 590 546 546 591 533 533 577 546 546 591 534 534 578 534 534 578 546 546 591 547 547 592 534 534 578 547 547 592 535 535 579 535 535 579 547 547 592 548 548 593 535 535 579 548 548 593 536 536 580 536 536 580 548 548 593 549 549 594 536 536 580 549 549 594 537 537 581 537 537 581 549 549 594 550 550 595 537 537 581 550 550 595 538 538 582 538 538 582 550 550 595 551 551 596 538 538 582 551 551 596 539 539 583 539 539 583 551 551 596 540 540 597 539 539 583 540 540 597 528 528 584 540 540 585 552 552 598 553 553 599 540 540 585 553 553 599 541 541 586 541 541 586 553 553 599 554 554 600 541 541 586 554 554 600 542 542 587 542 542 587 554 554 600 555 555 601 542 542 587 555 555 601 543 543 588 543 543 588 555 555 601 556 556 602 543 543 588 556 556 602 544 544 589 544 544 589 556 556 602 557 557 603 544 544 589 557 557 603 545 545 590 545 545 590 557 557 603 558 558 604 545 545 590 558 558 604 546 546 591 546 546 591 558 558 604 559 559 605 546 546 591 559 559 605 547 547 592 547 547 592 559 559 605 560 560 606 547 547 592 560 560 606 548 548 593 548 548 593 560 560 606 561 561 607 548 548 593 561 561 607 549 549 594 549 549 594 561 561 607 562 562 608 549 549 594 562 562 608 550 550 595 550 550 595 562 562 608 563 563 609 550 550 595 563 563 609 551 551 596 551 551 596 563 563 609 552 552 610 551 551 596 552 552 610 540 540 597 552 552 598 564 564 611 565 565 612 552 552 598 565 565 612 553 553 599 553 553 599 565 565 612 566 566 613 553 553 599 566 566 613 554 554 600 554 554 600 566 566 613 567 567 614 554 554 600 567 567 614 555 555 601 555 555 601 567 567 614 568 568 615 555 555 601 568 568 615 556 556 602 556 556 602 568 568 615 569 569 616 556 556 602 569 569 616 557 557 603 557 557 603 569 569 616 570 570 617 557 557 603 570 570 617 558 558 604 558 558 604 570 570 617 571 571 618 558 558 604 571 571 618 559 559 605 559 559 605 571 571 618 572 572 619 559 559 605 572 572 619 560 560 606 560 560 606 572 572 619 573 573 620 560 560 606 573 573 620 561 561 607 561 561 607 573 573 620 574 574 621 561 561 607 574 574 621 562 562 608 562 562 608 574 574 621 575 575 622 562 562 608 575 575 622 563 563 609 563 563 609 575 575 622 564 564 623 563 563 609 564 564 623 552 552 610 564 564 611 576 576 624 577 577 625 564 564 611 577 577 625 565 565 612 565 565 612 577 577 625 578 578 626 565 565 612 578 578 626 566 566 613 566 566 613 578 578 626 579 579 627 566 566 613 579 579 627 567 567 614 567 567 614 579 579 627 580 580 628 567 567 614 580 580 628 568 568 615 568 568 615 580 580 628 581 581 629 568 568 615 581 581 629 569 569 616 569 569 616 581 581 629 582 582 630 569 569 616 582 582 630 570 570 617 570 570 617 582 582 630 583 583 631 570 570 617 583 583 631 571 571 618 571 571 618 583 583 631 584 584 632 571 571 618 584 584 632 572 572 619 572 572 619 584 584 632 585 585 633 572 572 619 585 585 633 573 573 620 573 573 620 585 585 633 586 586 634 573 573 620 586 586 634 574 574 621 574 574 621 586 586 634 587 587 635 574 574 621 587 587 635 575 575 622 575 575 622 587 587 635 576 576 636 575 575 622 576 576 636 564 564 623 576 576 624 588 588 637 589 589 638 576 576 624 589 589 638 577 577 625 577 577 625 589 589 638 590 590 639 577 577 625 590 590 639 578 578 626 578 578 626 590 590 639 591 591 640 578 578 626 591 591 640 579 579 627 579 579 627 591 591 640 592 592 641 579 579 627 592 592 641 580 580 628 580 580 628 592 592 641 593 593 642 580 580 628 593 593 642 581 581 629 581 581 629 593 593 642 594 594 643 581 581 629 594 594 643 582 582 630 582 582 630 594 594 643 595 595 644 582 582 630 595 595 644 583 583 631 583 583 631 595 595 644 596 596 645 583 583 631 596 596 645 584 584 632 584 584 632 596 596 645 597 597 646 584 584 632 597 597 646 585 585 633 585 585 633 597 597 646 598 598 647 585 585 633 598 598 647 586 586 634 586 586 634 598 598 647 599 599 648 586 586 634 599 599 648 587 587 635 587 587 635 599 599 648 588 588 649 587 587 635 588 588 649 576 576 636 588 588 637 600 600 650 601 601 651 588 588 637 601 601 651 589 589 638 589 589 638 601 601 651 602 602 652 589 589 638 602 602 652 590 590 639 590 590 639 602 602 652 603 603 653 590 590 639 603 603 653 591 591 640 591 591 640 603 603 653 604 604 654 591 591 640 604 604 654 592 592 641 592 592 641 604 604 654 605 605 655 592 592 641 605 605 655 593 593 642 593 593 642 605 605 655 606 606 656 593 593 642 606 606 656 594 594 643 594 594 643 606 606 656 607 607 657 594 594 643 607 607 657 595 595 644 595 595 644 607 607 657 608 608 658 595 595 644 608 608 658 596 596 645 596 596 645 608 608 658 609 609 659 596 596 645 609 609 659 597 597 646 597 597 646 609 609 659 610 610 660 597 597 646 610 610 660 598 598 647 598 598 647 610 610 660 611 611 661 598 598 647 611 611 661 599 599 648 599 599 648 611 611 661 600 600 662 599 599 648 600 600 662 588 588 649 600 600 650 612 612 663 613 613 664 600 600 650 613 613 664 601 601 651 601 601 651 613 613 664 614 614 665 601 601 651 614 614 665 602 602 652 602 602 652 614 614 665 615 615 666 602 602 652 615 615 666 603 603 653 603 603 653 615 615 666 616 616 667 603 603 653 616 616 667 604 604 654 604 604 654 616 616 667 617 617 668 604 604 654 617 617 668 605 605 655 605 605 655 617 617 668 618 618 669 605 605 655 618 618 669 606 606 656 606 606 656 618 618 669 619 619 670 606 606 656 619 619 670 607 607 657 607 607 657 619 619 670 620 620 671 607 607 657 620 620 671 608 608 658 608 608 658 620 620 671 621 621 672 608 608 658 621 621 672 609 609 659 609 609 659 621 621 672 622 622 673 609 609 659 622 622 673 610 610 660 610 610 660 622 622 673 623 623 674 610 610 660 623 623 674 611 611 661 611 611 661 623 623 674 612 612 675 611 611 661 612 612 675 600 600 662 612 612 663 624 624 676 625 625 677 612 612 663 625 625 677 613 613 664 613 613 664 625 625 677 626 626 678 613 613 664 626 626 678 614 614 665 614 614 665 626 626 678 627 627 679 614 614 665 627 627 679 615 615 666 615 615 666 627 627 679 628 628 680 615 615 666 628 628 680 616 616 667 616 616 667 628 628 680 629 629 681 616 616 667 629 629 681 617 617 668 617 617 668 629 629 681 630 630 682 617 617 668 630 630 682 618 618 669 618 618 669 630 630 682 631 631 683 618 618 669 631 631 683 619 619 670 619 619 670 631 631 683 632 632 684 619 619 670 632 632 684 620 620 671 620 620 671 632 632 684 633 633 685 620 620 671 633 633 685 621 621 672 621 621 672 633 633 685 634 634 686 621 621 672 634 634 686 622 622 673 622 622 673 634 634 686 635 635 687 622 622 673 635 635 687 623 623 674 623 623 674 635 635 687 624 624 688 623 623 674 624 624 688 612 612 675 624 624 676 636 636 689 637 637 690 624 624 676 637 637 690 625 625 677 625 625 677 637 637 690 638 638 691 625 625 677 638 638 691 626 626 678 626 626 678 638 638 691 639 639 692 626 626 678 639 639 692 627 627 679 627 627 679 639 639 692 640 640 693 627 627 679 640 640 693 628 628 680 628 628 680 640 640 693 641 641 694 628 628 680 641 641 694 629 629 681 629 629 681 641 641 694 642 642 695 629 629 681 642 642 695 630 630 682 630 630 682 642 642 695 643 643 696 630 630 682 643 643 696 631 631 683 631 631 683 643 643 696 644 644 697 631 631 683 644 644 697 632 632 684 632 632 684 644 644 697 645 645 698 632 632 684 645 645 698 633 633 685 633 633 685 645 645 698 646 646 699 633 633 685 646 646 699 634 634 686 634 634 686 646 646 699 647 647 700 634 634 686 647 647 700 635 635 687 635 635 687 647 647 700 636 636 701 635 635 687 636 636 701 624 624 688 636 636 689 648 648 702 649 649 703 636 636 689 649 649 703 637 637 690 637 637 690 649 649 703 650 650 704 637 637 690 650 650 704 638 638 691 638 638 691 650 650 704 651 651 705 638 638 691 651 651 705 639 639 692 639 639 692 651 651 705 652 652 706 639 639 692 652 652 706 640 640 693 640 640 693 652 652 706 653 653 707 640 640 693 653 653 707 641 641 694 641 641 694 653 653 707 654 654 708 641 641 694 654 654 708 642 642 695 642 642 695 654 654 708 655 655 709 642 642 695 655 655 709 643 643 696 643 643 696 655 655 709 656 656 710 643 643 696 656 656 710 644 644 697 644 644 697 656 656 710 657 657 711 644 644 697 657 657 711 645 645 698 645 645 698 657 657 711 658 658 712 645 645 698 658 658 712 646 646 699 646 646 699 658 658 712 659 659 713 646 646 699 659 659 713 647 647 700 647 647 700 659 659 713 648 648 714 647 647 700 648 648 714 636 636 701 648 648 702 660 660 715 661 661 716 648 648 702 661 661 716 649 649 703 649 649 703 661 661 716 662 662 717 649 649 703 662 662 717 650 650 704 650 650 704 662 662 717 663 663 718 650 650 704 663 663 718 651 651 705 651 651 705 663 663 718 664 664 719 651 651 705 664 664 719 652 652 706 652 652 706 664 664 719 665 665 720 652 652 706 665 665 720 653 653 707 653 653 707 665 665 720 666 666 721 653 653 707 666 666 721 654 654 708 654 654 708 666 666 721 667 667 722 654 654 708 667 667 722 655 655 709 655 655 709 667 667 722 668 668 723 655 655 709 668 668 723 656 656 710 656 656 710 668 668 723 669 669 724 656 656 710 669 669 724 657 657 711 657 657 711 669 669 724 670 670 725 657 657 711 670 670 725 658 658 712 658 658 712 670 670 725 671 671 726 658 658 712 671 671 726 659 659 713 659 659 713 671 671 726 660 660 727 659 659 713 660 660 727 648 648 714 660 660 715 672 672 728 673 673 729 660 660 715 673 673 729 661 661 716 661 661 716 673 673 729 674 674 730 661 661 716 674 674 730 662 662 717 662 662 717 674 674 730 675 675 731 662 662 717 675 675 731 663 663 718 663 663 718 675 675 731 676 676 732 663 663 718 676 676 732 664 664 719 664 664 719 676 676 732 677 677 733 664 664 719 677 677 733 665 665 720 665 665 720 677 677 733 678 678 734 665 665 720 678 678 734 666 666 721 666 666 721 678 678 734 679 679 735 666 666 721 679 679 735 667 667 722 667 667 722 679 679 735 680 680 736 667 667 722 680 680 736 668 668 723 668 668 723 680 680 736 681 681 737 668 668 723 681 681 737 669 669 724 669 669 724 681 681 737 682 682 738 669 669 724 682 682 738 670 670 725 670 670 725 682 682 738 683 683 739 670 670 725 683 683 739 671 671 726 671 671 726 683 683 739 672 672 740 671 671 726 672 672 740 660 660 727 672 672 728 684 684 741 685 685 742 672 672 728 685 685 742 673 673 729 673 673 729 685 685 742 686 686 743 673 673 729 686 686 743 674 674 730 674 674 730 686 686 743 687 687 744 674 674 730 687 687 744 675 675 731 675 675 731 687 687 744 688 688 745 675 675 731 688 688 745 676 676 732 676 676 732 688 688 745 689 689 746 676 676 732 689 689 746 677 677 733 677 677 733 689 689 746 690 690 747 677 677 733 690 690 747 678 678 734 678 678 734 690 690 747 691 691 748 678 678 734 691 691 748 679 679 735 679 679 735 691 691 748 692 692 749 679 679 735 692 692 749 680 680 736 680 680 736 692 692 749 693 693 750 680 680 736 693 693 750 681 681 737 681 681 737 693 693 750 694 694 751 681 681 737 694 694 751 682 682 738 682 682 738 694 694 751 695 695 752 682 682 738 695 695 752 683 683 739 683 683 739 695 695 752 684 684 753 683 683 739 684 684 753 672 672 740 684 684 741 696 696 754 697 697 755 684 684 741 697 697 755 685 685 742 685 685 742 697 697 755 698 698 756 685 685 742 698 698 756 686 686 743 686 686 743 698 698 756 699 699 757 686 686 743 699 699 757 687 687 744 687 687 744 699 699 757 700 700 758 687 687 744 700 700 758 688 688 745 688 688 745 700 700 758 701 701 759 688 688 745 701 701 759 689 689 746 689 689 746 701 701 759 702 702 760 689 689 746 702 702 760 690 690 747 690 690 747 702 702 760 703 703 761 690 690 747 703 703 761 691 691 748 691 691 748 703 703 761 704 704 762 691 691 748 704 704 762 692 692 749 692 692 749 704 704 762 705 705 763 692 692 749 705 705 763 693 693 750 693 693 750 705 705 763 706 706 764 693 693 750 706 706 764 694 694 751 694 694 751 706 706 764 707 707 765 694 694 751 707 707 765 695 695 752 695 695 752 707 707 765 696 696 766 695 695 752 696 696 766 684 684 753 696 696 754 708 708 767 709 709 768 696 696 754 709 709 768 697 697 755 697 697 755 709 709 768 710 710 769 697 697 755 710 710 769 698 698 756 698 698 756 710 710 769 711 711 770 698 698 756 711 711 770 699 699 757 699 699 757 711 711 770 712 712 771 699 699 757 712 712 771 700 700 758 700 700 758 712 712 771 713 713 772 700 700 758 713 713 772 701 701 759 701 701 759 713 713 772 714 714 773 701 701 759 714 714 773 702 702 760 702 702 760 714 714 773 715 715 774 702 702 760 715 715 774 703 703 761 703 703 761 715 715 774 716 716 775 703 703 761 716 716 775 704 704 762 704 704 762 716 716 775 717 717 776 704 704 762 717 717 776 705 705 763 705 705 763 717 717 776 718 718 777 705 705 763 718 718 777 706 706 764 706 706 764 718 718 777 719 719 778 706 706 764 719 719 778 707 707 765 707 707 765 719 719 778 708 708 779 707 707 765 708 708 779 696 696 766 708 708 767 720 720 780 721 721 781 708 708 767 721 721 781 709 709 768 709 709 768 721 721 781 722 722 782 709 709 768 722 722 782 710 710 769 710 710 769 722 722 782 723 723 783 710 710 769 723 723 783 711 711 770 711 711 770 723 723 783 724 724 784 711 711 770 724 724 784 712 712 771 712 712 771 724 724 784 725 725 785 712 712 771 725 725 785 713 713 772 713 713 772 725 725 785 726 726 786 713 713 772 726 726 786 714 714 773 714 714 773 726 726 786 727 727 787 714 714 773 727 727 787 715 715 774 715 715 774 727 727 787 728 728 788 715 715 774 728 728 788 716 716 775 716 716 775 728 728 788 729 729 789 716 716 775 729 729 789 717 717 776 717 717 776 729 729 789 730 730 790 717 717 776 730 730 790 718 718 777 718 718 777 730 730 790 731 731 791 718 718 777 731 731 791 719 719 778 719 719 778 731 731 791 720 720 792 719 719 778 720 720 792 708 708 779 720 720 780 732 732 793 733 733 794 720 720 780 733 733 794 721 721 781 721 721 781 733 733 794 734 734 795 721 721 781 734 734 795 722 722 782 722 722 782 734 734 795 735 735 796 722 722 782 735 735 796 723 723 783 723 723 783 735 735 796 736 736 797 723 723 783 736 736 797 724 724 784 724 724 784 736 736 797 737 737 798 724 724 784 737 737 798 725 725 785 725 725 785 737 737 798 738 738 799 725 725 785 738 738 799 726 726 786 726 726 786 738 738 799 739 739 800 726 726 786 739 739 800 727 727 787 727 727 787 739 739 800 740 740 801 727 727 787 740 740 801 728 728 788 728 728 788 740 740 801 741 741 802 728 728 788 741 741 802 729 729 789 729 729 789 741 741 802 742 742 803 729 729 789 742 742 803 730 730 790 730 730 790 742 742 803 743 743 804 730 730 790 743 743 804 731 731 791 731 731 791 743 743 804 732 732 805 731 731 791 732 732 805 720 720 792 732 732 793 744 744 806 745 745 807 732 732 793 745 745 807 733 733 794 733 733 794 745 745 807 746 746 808 733 733 794 746 746 808 734 734 795 734 734 795 746 746 808 747 747 809 734 734 795 747 747 809 735 735 796 735 735 796 747 747 809 748 748 810 735 735 796 748 748 810 736 736 797 736 736 797 748 748 810 749 749 811 736 736 797 749 749 811 737 737 798 737 737 798 749 749 811 750 750 812 737 737 798 750 750 812 738 738 799 738 738 799 750 750 812 751 751 813 738 738 799 751 751 813 739 739 800 739 739 800 751 751 813 752 752 814 739 739 800 752 752 814 740 740 801 740 740 801 752 752 814 753 753 815 740 740 801 753 753 815 741 741 802 741 741 802 753 753 815 754 754 816 741 741 802 754 754 816 742 742 803 742 742 803 754 754 816 755 755 817 742 742 803 755 755 817 743 743 804 743 743 804 755 755 817 744 744 818 743 743 804 744 744 818 732 732 805 744 744 806 756 756 819 757 757 820 744 744 806 757 757 820 745 745 807 745 745 807 757 757 820 758 758 821 745 745 807 758 758 821 746 746 808 746 746 808 758 758 821 759 759 822 746 746 808 759 759 822 747 747 809 747 747 809 759 759 822 760 760 823 747 747 809 760 760 823 748 748 810 748 748 810 760 760 823 761 761 824 748 748 810 761 761 824 749 749 811 749 749 811 761 761 824 762 762 825 749 749 811 762 762 825 750 750 812 750 750 812 762 762 825 763 763 826 750 750 812 763 763 826 751 751 813 751 751 813 763 763 826 764 764 827 751 751 813 764 764 827 752 752 814 752 752 814 764 764 827 765 765 828 752 752 814 765 765 828 753 753 815 753 753 815 765 765 828 766 766 829 753 753 815 766 766 829 754 754 816 754 754 816 766 766 829 767 767 830 754 754 816 767 767 830 755 755 817 755 755 817 767 767 830 756 756 831 755 755 817 756 756 831 744 744 818 756 756 819 768 768 832 769 769 833 756 756 819 769 769 833 757 757 820 757 757 820 769 769 833 770 770 834 757 757 820 770 770 834 758 758 821 758 758 821 770 770 834 771 771 835 758 758 821 771 771 835 759 759 822 759 759 822 771 771 835 772 772 836 759 759 822 772 772 836 760 760 823 760 760 823 772 772 836 773 773 837 760 760 823 773 773 837 761 761 824 761 761 824 773 773 837 774 774 838 761 761 824 774 774 838 762 762 825 762 762 825 774 774 838 775 775 839 762 762 825 775 775 839 763 763 826 763 763 826 775 775 839 776 776 840 763 763 826 776 776 840 764 764 827 764 764 827 776 776 840 777 777 841 764 764 827 777 777 841 765 765 828 765 765 828 777 777 841 778 778 842 765 765 828 778 778 842 766 766 829 766 766 829 778 778 842 779 779 843 766 766 829 779 779 843 767 767 830 767 767 830 779 779 843 768 768 844 767 767 830 768 768 844 756 756 831 768 768 832 780 780 845 781 781 846 768 768 832 781 781 846 769 769 833 769 769 833 781 781 846 782 782 847 769 769 833 782 782 847 770 770 834 770 770 834 782 782 847 783 783 848 770 770 834 783 783 848 771 771 835 771 771 835 783 783 848 784 784 849 771 771 835 784 784 849 772 772 836 772 772 836 784 784 849 785 785 850 772 772 836 785 785 850 773 773 837 773 773 837 785 785 850 786 786 851 773 773 837 786 786 851 774 774 838 774 774 838 786 786 851 787 787 852 774 774 838 787 787 852 775 775 839 775 775 839 787 787 852 788 788 853 775 775 839 788 788 853 776 776 840 776 776 840 788 788 853 789 789 854 776 776 840 789 789 854 777 777 841 777 777 841 789 789 854 790 790 855 777 777 841 790 790 855 778 778 842 778 778 842 790 790 855 791 791 856 778 778 842 791 791 856 779 779 843 779 779 843 791 791 856 780 780 857 779 779 843 780 780 857 768 768 844 780 780 845 792 792 858 793 793 859 780 780 845 793 793 859 781 781 846 781 781 846 793 793 859 794 794 860 781 781 846 794 794 860 782 782 847 782 782 847 794 794 860 795 795 861 782 782 847 795 795 861 783 783 848 783 783 848 795 795 861 796 796 862 783 783 848 796 796 862 784 784 849 784 784 849 796 796 862 797 797 863 784 784 849 797 797 863 785 785 850 785 785 850 797 797 863 798 798 864 785 785 850 798 798 864 786 786 851 786 786 851 798 798 864 799 799 865 786 786 851 799 799 865 787 787 852 787 787 852 799 799 865 800 800 866 787 787 852 800 800 866 788 788 853 788 788 853 800 800 866 801 801 867 788 788 853 801 801 867 789 789 854 789 789 854 801 801 867 802 802 868 789 789 854 802 802 868 790 790 855 790 790 855 802 802 868 803 803 869 790 790 855 803 803 869 791 791 856 791 791 856 803 803 869 792 792 870 791 791 856 792 792 870 780 780 857 792 792 858 804 804 871 805 805 872 792 792 858 805 805 872 793 793 859 793 793 859 805 805 872 806 806 873 793 793 859 806 806 873 794 794 860 794 794 860 806 806 873 807 807 874 794 794 860 807 807 874 795 795 861 795 795 861 807 807 874 808 808 875 795 795 861 808 808 875 796 796 862 796 796 862 808 808 875 809 809 876 796 796 862 809 809 876 797 797 863 797 797 863 809 809 876 810 810 877 797 797 863 810 810 877 798 798 864 798 798 864 810 810 877 811 811 878 798 798 864 811 811 878 799 799 865 799 799 865 811 811 878 812 812 879 799 799 865 812 812 879 800 800 866 800 800 866 812 812 879 813 813 880 800 800 866 813 813 880 801 801 867 801 801 867 813 813 880 814 814 881 801 801 867 814 814 881 802 802 868 802 802 868 814 814 881 815 815 882 802 802 868 815 815 882 803 803 869 803 803 869 815 815 882 804 804 883 803 803 869 804 804 883 792 792 870 804 804 871 816 816 884 817 817 885 804 804 871 817 817 885 805 805 872 805 805 872 817 817 885 818 818 886 805 805 872 818 818 886 806 806 873 806 806 873 818 818 886 819 819 887 806 806 873 819 819 887 807 807 874 807 807 874 819 819 887 820 820 888 807 807 874 820 820 888 808 808 875 808 808 875 820 820 888 821 821 889 808 808 875 821 821 889 809 809 876 809 809 876 821 821 889 822 822 890 809 809 876 822 822 890 810 810 877 810 810 877 822 822 890 823 823 891 810 810 877 823 823 891 811 811 878 811 811 878 823 823 891 824 824 892 811 811 878 824 824 892 812 812 879 812 812 879 824 824 892 825 825 893 812 812 879 825 825 893 813 813 880 813 813 880 825 825 893 826 826 894 813 813 880 826 826 894 814 814 881 814 814 881 826 826 894 827 827 895 814 814 881 827 827 895 815 815 882 815 815 882 827 827 895 816 816 896 815 815 882 816 816 896 804 804 883 816 816 884 828 828 897 829 829 898 816 816 884 829 829 898 817 817 885 817 817 885 829 829 898 830 830 899 817 817 885 830 830 899 818 818 886 818 818 886 830 830 899 831 831 900 818 818 886 831 831 900 819 819 887 819 819 887 831 831 900 832 832 901 819 819 887 832 832 901 820 820 888 820 820 888 832 832 901 833 833 902 820 820 888 833 833 902 821 821 889 821 821 889 833 833 902 834 834 903 821 821 889 834 834 903 822 822 890 822 822 890 834 834 903 835 835 904 822 822 890 835 835 904 823 823 891 823 823 891 835 835 904 836 836 905 823 823 891 836 836 905 824 824 892 824 824 892 836 836 905 837 837 906 824 824 892 837 837 906 825 825 893 825 825 893 837 837 906 838 838 907 825 825 893 838 838 907 826 826 894 826 826 894 838 838 907 839 839 908 826 826 894 839 839 908 827 827 895 827 827 895 839 839 908 828 828 909 827 827 895 828 828 909 816 816 896 828 828 897 840 840 910 841 841 911 828 828 897 841 841 911 829 829 898 829 829 898 841 841 911 842 842 912 829 829 898 842 842 912 830 830 899 830 830 899 842 842 912 843 843 913 830 830 899 843 843 913 831 831 900 831 831 900 843 843 913 844 844 914 831 831 900 844 844 914 832 832 901 832 832 901 844 844 914 845 845 915 832 832 901 845 845 915 833 833 902 833 833 902 845 845 915 846 846 916 833 833 902 846 846 916 834 834 903 834 834 903 846 846 916 847 847 917 834 834 903 847 847 917 835 835 904 835 835 904 847 847 917 848 848 918 835 835 904 848 848 918 836 836 905 836 836 905 848 848 918 849 849 919 836 836 905 849 849 919 837 837 906 837 837 906 849 849 919 850 850 920 837 837 906 850 850 920 838 838 907 838 838 907 850 850 920 851 851 921 838 838 907 851 851 921 839 839 908 839 839 908 851 851 921 840 840 922 839 839 908 840 840 922 828 828 909 840 840 910 852 852 923 853 853 924 840 840 910 853 853 924 841 841 911 841 841 911 853 853 924 854 854 925 841 841 911 854 854 925 842 842 912 842 842 912 854 854 925 855 855 926 842 842 912 855 855 926 843 843 913 843 843 913 855 855 926 856 856 927 843 843 913 856 856 927 844 844 914 844 844 914 856 856 927 857 857 928 844 844 914 857 857 928 845 845 915 845 845 915 857 857 928 858 858 929 845 845 915 858 858 929 846 846 916 846 846 916 858 858 929 859 859 930 846 846 916 859 859 930 847 847 917 847 847 917 859 859 930 860 860 931 847 847 917 860 860 931 848 848 918 848 848 918 860 860 931 861 861 932 848 848 918 861 861 932 849 849 919 849 849 919 861 861 932 862 862 933 849 849 919 862 862 933 850 850 920 850 850 920 862 862 933 863 863 934 850 850 920 863 863 934 851 851 921 851 851 921 863 863 934 852 852 935 851 851 921 852 852 935 840 840 922 852 852 923 864 864 936 865 865 937 852 852 923 865 865 937 853 853 924 853 853 924 865 865 937 866 866 938 853 853 924 866 866 938 854 854 925 854 854 925 866 866 938 867 867 939 854 854 925 867 867 939 855 855 926 855 855 926 867 867 939 868 868 940 855 855 926 868 868 940 856 856 927 856 856 927 868 868 940 869 869 941 856 856 927 869 869 941 857 857 928 857 857 928 869 869 941 870 870 942 857 857 928 870 870 942 858 858 929 858 858 929 870 870 942 871 871 943 858 858 929 871 871 943 859 859 930 859 859 930 871 871 943 872 872 944 859 859 930 872 872 944 860 860 931 860 860 931 872 872 944 873 873 945 860 860 931 873 873 945 861 861 932 861 861 932 873 873 945 874 874 946 861 861 932 874 874 946 862 862 933 862 862 933 874 874 946 875 875 947 862 862 933 875 875 947 863 863 934 863 863 934 875 875 947 864 864 948 863 863 934 864 864 948 852 852 935 864 864 936 876 876 949 877 877 950 864 864 936 877 877 950 865 865 937 865 865 937 877 877 950 878 878 951 865 865 937 878 878 951 866 866 938 866 866 938 878 878 951 879 879 952 866 866 938 879 879 952 867 867 939 867 867 939 879 879 952 880 880 953 867 867 939 880 880 953 868 868 940 868 868 940 880 880 953 881 881 954 868 868 940 881 881 954 869 869 941 869 869 941 881 881 954 882 882 955 869 869 941 882 882 955 870 870 942 870 870 942 882 882 955 883 883 956 870 870 942 883 883 956 871 871 943 871 871 943 883 883 956 884 884 957 871 871 943 884 884 957 872 872 944 872 872 944 884 884 957 885 885 958 872 872 944 885 885 958 873 873 945 873 873 945 885 885 958 886 886 959 873 873 945 886 886 959 874 874 946 874 874 946 886 886 959 887 887 960 874 874 946 887 887 960 875 875 947 875 875 947 887 887 960 876 876 961 875 875 947 876 876 961 864 864 948 876 876 949 888 888 962 889 889 963 876 876 949 889 889 963 877 877 950 877 877 950 889 889 963 890 890 964 877 877 950 890 890 964 878 878 951 878 878 951 890 890 964 891 891 965 878 878 951 891 891 965 879 879 952 879 879 952 891 891 965 892 892 966 879 879 952 892 892 966 880 880 953 880 880 953 892 892 966 893 893 967 880 880 953 893 893 967 881 881 954 881 881 954 893 893 967 894 894 968 881 881 954 894 894 968 882 882 955 882 882 955 894 894 968 895 895 969 882 882 955 895 895 969 883 883 956 883 883 956 895 895 969 896 896 970 883 883 956 896 896 970 884 884 957 884 884 957 896 896 970 897 897 971 884 884 957 897 897 971 885 885 958 885 885 958 897 897 971 898 898 972 885 885 958 898 898 972 886 886 959 886 886 959 898 898 972 899 899 973 886 886 959 899 899 973 887 887 960 887 887 960 899 899 973 888 888 974 887 887 960 888 888 974 876 876 961 888 888 962 900 900 975 901 901 976 888 888 962 901 901 976 889 889 963 889 889 963 901 901 976 902 902 977 889 889 963 902 902 977 890 890 964 890 890 964 902 902 977 903 903 978 890 890 964 903 903 978 891 891 965 891 891 965 903 903 978 904 904 979 891 891 965 904 904 979 892 892 966 892 892 966 904 904 979 905 905 980 892 892 966 905 905 980 893 893 967 893 893 967 905 905 980 906 906 981 893 893 967 906 906 981 894 894 968 894 894 968 906 906 981 907 907 982 894 894 968 907 907 982 895 895 969 895 895 969 907 907 982 908 908 983 895 895 969 908 908 983 896 896 970 896 896 970 908 908 983 909 909 984 896 896 970 909 909 984 897 897 971 897 897 971 909 909 984 910 910 985 897 897 971 910 910 985 898 898 972 898 898 972 910 910 985 911 911 986 898 898 972 911 911 986 899 899 973 899 899 973 911 911 986 900 900 987 899 899 973 900 900 987 888 888 974 900 900 975 912 912 988 913 913 989 900 900 975 913 913 989 901 901 976 901 901 976 913 913 989 914 914 990 901 901 976 914 914 990 902 902 977 902 902 977 914 914 990 915 915 991 902 902 977 915 915 991 903 903 978 903 903 978 915 915 991 916 916 992 903 903 978 916 916 992 904 904 979 904 904 979 916 916 992 917 917 993 904 904 979 917 917 993 905 905 980 905 905 980 917 917 993 918 918 994 905 905 980 918 918 994 906 906 981 906 906 981 918 918 994 919 919 995 906 906 981 919 919 995 907 907 982 907 907 982 919 919 995 920 920 996 907 907 982 920 920 996 908 908 983 908 908 983 920 920 996 921 921 997 908 908 983 921 921 997 909 909 984 909 909 984 921 921 997 922 922 998 909 909 984 922 922 998 910 910 985 910 910 985 922 922 998 923 923 999 910 910 985 923 923 999 911 911 986 911 911 986 923 923 999 912 912 1000 911 911 986 912 912 1000 900 900 987 912 912 988 924 924 1001 925 925 1002 912 912 988 925 925 1002 913 913 989 913 913 989 925 925 1002 926 926 1003 913 913 989 926 926 1003 914 914 990 914 914 990 926 926 1003 927 927 1004 914 914 990 927 927 1004 915 915 991 915 915 991 927 927 1004 928 928 1005 915 915 991 928 928 1005 916 916 992 916 916 992 928 928 1005 929 929 1006 916 916 992 929 929 1006 917 917 993 917 917 993 929 929 1006 930 930 1007 917 917 993 930 930 1007 918 918 994 918 918 994 930 930 1007 931 931 1008 918 918 994 931 931 1008 919 919 995 919 919 995 931 931 1008 932 932 1009 919 919 995 932 932 1009 920 920 996 920 920 996 932 932 1009 933 933 1010 920 920 996 933 933 1010 921 921 997 921 921 997 933 933 1010 934 934 1011 921 921 997 934 934 1011 922 922 998 922 922 998 934 934 1011 935 935 1012 922 922 998 935 935 1012 923 923 999 923 923 999 935 935 1012 924 924 1013 923 923 999 924 924 1013 912 912 1000 924 924 1001 936 936 1014 937 937 1015 924 924 1001 937 937 1015 925 925 1002 925 925 1002 937 937 1015 938 938 1016 925 925 1002 938 938 1016 926 926 1003 926 926 1003 938 938 1016 939 939 1017 926 926 1003 939 939 1017 927 927 1004 927 927 1004 939 939 1017 940 940 1018 927 927 1004 940 940 1018 928 928 1005 928 928 1005 940 940 1018 941 941 1019 928 928 1005 941 941 1019 929 929 1006 929 929 1006 941 941 1019 942 942 1020 929 929 1006 942 942 1020 930 930 1007 930 930 1007 942 942 1020 943 943 1021 930 930 1007 943 943 1021 931 931 1008 931 931 1008 943 943 1021 944 944 1022 931 931 1008 944 944 1022 932 932 1009 932 932 1009 944 944 1022 945 945 1023 932 932 1009 945 945 1023 933 933 1010 933 933 1010 945 945 1023 946 946 1024 933 933 1010 946 946 1024 934 934 1011 934 934 1011 946 946 1024 947 947 1025 934 934 1011 947 947 1025 935 935 1012 935 935 1012 947 947 1025 936 936 1026 935 935 1012 936 936 1026 924 924 1013 936 936 1014 948 948 1027 949 949 1028 936 936 1014 949 949 1028 937 937 1015 937 937 1015 949 949 1028 950 950 1029 937 937 1015 950 950 1029 938 938 1016 938 938 1016 950 950 1029 951 951 1030 938 938 1016 951 951 1030 939 939 1017 939 939 1017 951 951 1030 952 952 1031 939 939 1017 952 952 1031 940 940 1018 940 940 1018 952 952 1031 953 953 1032 940 940 1018 953 953 1032 941 941 1019 941 941 1019 953 953 1032 954 954 1033 941 941 1019 954 954 1033 942 942 1020 942 942 1020 954 954 1033 955 955 1034 942 942 1020 955 955 1034 943 943 1021 943 943 1021 955 955 1034 956 956 1035 943 943 1021 956 956 1035 944 944 1022 944 944 1022 956 956 1035 957 957 1036 944 944 1022 957 957 1036 945 945 1023 945 945 1023 957 957 1036 958 958 1037 945 945 1023 958 958 1037 946 946 1024 946 946 1024 958 958 1037 959 959 1038 946 946 1024 959 959 1038 947 947 1025 947 947 1025 959 959 1038 948 948 1039 947 947 1025 948 948 1039 936 936 1026 948 948 1027 960 960 1040 961 961 1041 948 948 1027 961 961 1041 949 949 1028 949 949 1028 961 961 1041 962 962 1042 949 949 1028 962 962 1042 950 950 1029 950 950 1029 962 962 1042 963 963 1043 950 950 1029 963 963 1043 951 951 1030 951 951 1030 963 963 1043 964 964 1044 951 951 1030 964 964 1044 952 952 1031 952 952 1031 964 964 1044 965 965 1045 952 952 1031 965 965 1045 953 953 1032 953 953 1032 965 965 1045 966 966 1046 953 953 1032 966 966 1046 954 954 1033 954 954 1033 966 966 1046 967 967 1047 954 954 1033 967 967 1047 955 955 1034 955 955 1034 967 967 1047 968 968 1048 955 955 1034 968 968 1048 956 956 1035 956 956 1035 968 968 1048 969 969 1049 956 956 1035 969 969 1049 957 957 1036 957 957 1036 969 969 1049 970 970 1050 957 957 1036 970 970 1050 958 958 1037 958 958 1037 970 970 1050 971 971 1051 958 958 1037 971 971 1051 959 959 1038 959 959 1038 971 971 1051 960 960 1052 959 959 1038 960 960 1052 948 948 1039 960 960 1040 972 972 1053 973 973 1054 960 960 1040 973 973 1054 961 961 1041 961 961 1041 973 973 1054 974 974 1055 961 961 1041 974 974 1055 962 962 1042 962 962 1042 974 974 1055 975 975 1056 962 962 1042 975 975 1056 963 963 1043 963 963 1043 975 975 1056 976 976 1057 963 963 1043 976 976 1057 964 964 1044 964 964 1044 976 976 1057 977 977 1058 964 964 1044 977 977 1058 965 965 1045 965 965 1045 977 977 1058 978 978 1059 965 965 1045 978 978 1059 966 966 1046 966 966 1046 978 978 1059 979 979 1060 966 966 1046 979 979 1060 967 967 1047 967 967 1047 979 979 1060 980 980 1061 967 967 1047 980 980 1061 968 968 1048 968 968 1048 980 980 1061 981 981 1062 968 968 1048 981 981 1062 969 969 1049 969 969 1049 981 981 1062 982 982 1063 969 969 1049 982 982 1063 970 970 1050 970 970 1050 982 982 1063 983 983 1064 970 970 1050 983 983 1064 971 971 1051 971 971 1051 983 983 1064 972 972 1065 971 971 1051 972 972 1065 960 960 1052 972 972 1053 984 984 1066 985 985 1067 972 972 1053 985 985 1067 973 973 1054 973 973 1054 985 985 1067 986 986 1068 973 973 1054 986 986 1068 974 974 1055 974 974 1055 986 986 1068 987 987 1069 974 974 1055 987 987 1069 975 975 1056 975 975 1056 987 987 1069 988 988 1070 975 975 1056 988 988 1070 976 976 1057 976 976 1057 988 988 1070 989 989 1071 976 976 1057 989 989 1071 977 977 1058 977 977 1058 989 989 1071 990 990 1072 977 977 1058 990 990 1072 978 978 1059 978 978 1059 990 990 1072 991 991 1073 978 978 1059 991 991 1073 979 979 1060 979 979 1060 991 991 1073 992 992 1074 979 979 1060 992 992 1074 980 980 1061 980 980 1061 992 992 1074 993 993 1075 980 980 1061 993 993 1075 981 981 1062 981 981 1062 993 993 1075 994 994 1076 981 981 1062 994 994 1076 982 982 1063 982 982 1063 994 994 1076 995 995 1077 982 982 1063 995 995 1077 983 983 1064 983 983 1064 995 995 1077 984 984 1078 983 983 1064 984 984 1078 972 972 1065 984 984 1066 996 996 1079 997 997 1080 984 984 1066 997 997 1080 985 985 1067 985 985 1067 997 997 1080 998 998 1081 985 985 1067 998 998 1081 986 986 1068 986 986 1068 998 998 1081 999 999 1082 986 986 1068 999 999 1082 987 987 1069 987 987 1069 999 999 1082 1000 1000 1083 987 987 1069 1000 1000 1083 988 988 1070 988 988 1070 1000 1000 1083 1001 1001 1084 988 988 1070 1001 1001 1084 989 989 1071 989 989 1071 1001 1001 1084 1002 1002 1085 989 989 1071 1002 1002 1085 990 990 1072 990 990 1072 1002 1002 1085 1003 1003 1086 990 990 1072 1003 1003 1086 991 991 1073 991 991 1073 1003 1003 1086 1004 1004 1087 991 991 1073 1004 1004 1087 992 992 1074 992 992 1074 1004 1004 1087 1005 1005 1088 992 992 1074 1005 1005 1088 993 993 1075 993 993 1075 1005 1005 1088 1006 1006 1089 993 993 1075 1006 1006 1089 994 994 1076 994 994 1076 1006 1006 1089 1007 1007 1090 994 994 1076 1007 1007 1090 995 995 1077 995 995 1077 1007 1007 1090 996 996 1091 995 995 1077 996 996 1091 984 984 1078 996 996 1079 1008 1008 1092 1009 1009 1093 996 996 1079 1009 1009 1093 997 997 1080 997 997 1080 1009 1009 1093 1010 1010 1094 997 997 1080 1010 1010 1094 998 998 1081 998 998 1081 1010 1010 1094 1011 1011 1095 998 998 1081 1011 1011 1095 999 999 1082 999 999 1082 1011 1011 1095 1012 1012 1096 999 999 1082 1012 1012 1096 1000 1000 1083 1000 1000 1083 1012 1012 1096 1013 1013 1097 1000 1000 1083 1013 1013 1097 1001 1001 1084 1001 1001 1084 1013 1013 1097 1014 1014 1098 1001 1001 1084 1014 1014 1098 1002 1002 1085 1002 1002 1085 1014 1014 1098 1015 1015 1099 1002 1002 1085 1015 1015 1099 1003 1003 1086 1003 1003 1086 1015 1015 1099 1016 1016 1100 1003 1003 1086 1016 1016 1100 1004 1004 1087 1004 1004 1087 1016 1016 1100 1017 1017 1101 1004 1004 1087 1017 1017 1101 1005 1005 1088 1005 1005 1088 1017 1017 1101 1018 1018 1102 1005 1005 1088 1018 1018 1102 1006 1006 1089 1006 1006 1089 1018 1018 1102 1019 1019 1103 1006 1006 1089 1019 1019 1103 1007 1007 1090 1007 1007 1090 1019 1019 1103 1008 1008 1104 1007 1007 1090 1008 1008 1104 996 996 1091 1008 1008 1092 1020 1020 1105 1021 1021 1106 1008 1008 1092 1021 1021 1106 1009 1009 1093 1009 1009 1093 1021 1021 1106 1022 1022 1107 1009 1009 1093 1022 1022 1107 1010 1010 1094 1010 1010 1094 1022 1022 1107 1023 1023 1108 1010 1010 1094 1023 1023 1108 1011 1011 1095 1011 1011 1095 1023 1023 1108 1024 1024 1109 1011 1011 1095 1024 1024 1109 1012 1012 1096 1012 1012 1096 1024 1024 1109 1025 1025 1110 1012 1012 1096 1025 1025 1110 1013 1013 1097 1013 1013 1097 1025 1025 1110 1026 1026 1111 1013 1013 1097 1026 1026 1111 1014 1014 1098 1014 1014 1098 1026 1026 1111 1027 1027 1112 1014 1014 1098 1027 1027 1112 1015 1015 1099 1015 1015 1099 1027 1027 1112 1028 1028 1113 1015 1015 1099 1028 1028 1113 1016 1016 1100 1016 1016 1100 1028 1028 1113 1029 1029 1114 1016 1016 1100 1029 1029 1114 1017 1017 1101 1017 1017 1101 1029 1029 1114 1030 1030 1115 1017 1017 1101 1030 1030 1115 1018 1018 1102 1018 1018 1102 1030 1030 1115 1031 1031 1116 1018 1018 1102 1031 1031 1116 1019 1019 1103 1019 1019 1103 1031 1031 1116 1020 1020 1117 1019 1019 1103 1020 1020 1117 1008 1008 1104 1020 1020 1105 1032 1032 1118 1033 1033 1119 1020 1020 1105 1033 1033 1119 1021 1021 1106 1021 1021 1106 1033 1033 1119 1034 1034 1120 1021 1021 1106 1034 1034 1120 1022 1022 1107 1022 1022 1107 1034 1034 1120 1035 1035 1121 1022 1022 1107 1035 1035 1121 1023 1023 1108 1023 1023 1108 1035 1035 1121 1036 1036 1122 1023 1023 1108 1036 1036 1122 1024 1024 1109 1024 1024 1109 1036 1036 1122 1037 1037 1123 1024 1024 1109 1037 1037 1123 1025 1025 1110 1025 1025 1110 1037 1037 1123 1038 1038 1124 1025 1025 1110 1038 1038 1124 1026 1026 1111 1026 1026 1111 1038 1038 1124 1039 1039 1125 1026 1026 1111 1039 1039 1125 1027 1027 1112 1027 1027 1112 1039 1039 1125 1040 1040 1126 1027 1027 1112 1040 1040 1126 1028 1028 1113 1028 1028 1113 1040 1040 1126 1041 1041 1127 1028 1028 1113 1041 1041 1127 1029 1029 1114 1029 1029 1114 1041 1041 1127 1042 1042 1128 1029 1029 1114 1042 1042 1128 1030 1030 1115 1030 1030 1115 1042 1042 1128 1043 1043 1129 1030 1030 1115 1043 1043 1129 1031 1031 1116 1031 1031 1116 1043 1043 1129 1032 1032 1130 1031 1031 1116 1032 1032 1130 1020 1020 1117 1032 1032 1118 1044 1044 1131 1045 1045 1132 1032 1032 1118 1045 1045 1132 1033 1033 1119 1033 1033 1119 1045 1045 1132 1046 1046 1133 1033 1033 1119 1046 1046 1133 1034 1034 1120 1034 1034 1120 1046 1046 1133 1047 1047 1134 1034 1034 1120 1047 1047 1134 1035 1035 1121 1035 1035 1121 1047 1047 1134 1048 1048 1135 1035 1035 1121 1048 1048 1135 1036 1036 1122 1036 1036 1122 1048 1048 1135 1049 1049 1136 1036 1036 1122 1049 1049 1136 1037 1037 1123 1037 1037 1123 1049 1049 1136 1050 1050 1137 1037 1037 1123 1050 1050 1137 1038 1038 1124 1038 1038 1124 1050 1050 1137 1051 1051 1138 1038 1038 1124 1051 1051 1138 1039 1039 1125 1039 1039 1125 1051 1051 1138 1052 1052 1139 1039 1039 1125 1052 1052 1139 1040 1040 1126 1040 1040 1126 1052 1052 1139 1053 1053 1140 1040 1040 1126 1053 1053 1140 1041 1041 1127 1041 1041 1127 1053 1053 1140 1054 1054 1141 1041 1041 1127 1054 1054 1141 1042 1042 1128 1042 1042 1128 1054 1054 1141 1055 1055 1142 1042 1042 1128 1055 1055 1142 1043 1043 1129 1043 1043 1129 1055 1055 1142 1044 1044 1143 1043 1043 1129 1044 1044 1143 1032 1032 1130 1044 1044 1131 1056 1056 1144 1057 1057 1145 1044 1044 1131 1057 1057 1145 1045 1045 1132 1045 1045 1132 1057 1057 1145 1058 1058 1146 1045 1045 1132 1058 1058 1146 1046 1046 1133 1046 1046 1133 1058 1058 1146 1059 1059 1147 1046 1046 1133 1059 1059 1147 1047 1047 1134 1047 1047 1134 1059 1059 1147 1060 1060 1148 1047 1047 1134 1060 1060 1148 1048 1048 1135 1048 1048 1135 1060 1060 1148 1061 1061 1149 1048 1048 1135 1061 1061 1149 1049 1049 1136 1049 1049 1136 1061 1061 1149 1062 1062 1150 1049 1049 1136 1062 1062 1150 1050 1050 1137 1050 1050 1137 1062 1062 1150 1063 1063 1151 1050 1050 1137 1063 1063 1151 1051 1051 1138 1051 1051 1138 1063 1063 1151 1064 1064 1152 1051 1051 1138 1064 1064 1152 1052 1052 1139 1052 1052 1139 1064 1064 1152 1065 1065 1153 1052 1052 1139 1065 1065 1153 1053 1053 1140 1053 1053 1140 1065 1065 1153 1066 1066 1154 1053 1053 1140 1066 1066 1154 1054 1054 1141 1054 1054 1141 1066 1066 1154 1067 1067 1155 1054 1054 1141 1067 1067 1155 1055 1055 1142 1055 1055 1142 1067 1067 1155 1056 1056 1156 1055 1055 1142 1056 1056 1156 1044 1044 1143 1056 1056 1144 1068 1068 1157 1069 1069 1158 1056 1056 1144 1069 1069 1158 1057 1057 1145 1057 1057 1145 1069 1069 1158 1070 1070 1159 1057 1057 1145 1070 1070 1159 1058 1058 1146 1058 1058 1146 1070 1070 1159 1071 1071 1160 1058 1058 1146 1071 1071 1160 1059 1059 1147 1059 1059 1147 1071 1071 1160 1072 1072 1161 1059 1059 1147 1072 1072 1161 1060 1060 1148 1060 1060 1148 1072 1072 1161 1073 1073 1162 1060 1060 1148 1073 1073 1162 1061 1061 1149 1061 1061 1149 1073 1073 1162 1074 1074 1163 1061 1061 1149 1074 1074 1163 1062 1062 1150 1062 1062 1150 1074 1074 1163 1075 1075 1164 1062 1062 1150 1075 1075 1164 1063 1063 1151 1063 1063 1151 1075 1075 1164 1076 1076 1165 1063 1063 1151 1076 1076 1165 1064 1064 1152 1064 1064 1152 1076 1076 1165 1077 1077 1166 1064 1064 1152 1077 1077 1166 1065 1065 1153 1065 1065 1153 1077 1077 1166 1078 1078 1167 1065 1065 1153 1078 1078 1167 1066 1066 1154 1066 1066 1154 1078 1078 1167 1079 1079 1168 1066 1066 1154 1079 1079 1168 1067 1067 1155 1067 1067 1155 1079 1079 1168 1068 1068 1169 1067 1067 1155 1068 1068 1169 1056 1056 1156 1068 1068 1157 1080 1080 1170 1081 1081 1171 1068 1068 1157 1081 1081 1171 1069 1069 1158 1069 1069 1158 1081 1081 1171 1082 1082 1172 1069 1069 1158 1082 1082 1172 1070 1070 1159 1070 1070 1159 1082 1082 1172 1083 1083 1173 1070 1070 1159 1083 1083 1173 1071 1071 1160 1071 1071 1160 1083 1083 1173 1084 1084 1174 1071 1071 1160 1084 1084 1174 1072 1072 1161 1072 1072 1161 1084 1084 1174 1085 1085 1175 1072 1072 1161 1085 1085 1175 1073 1073 1162 1073 1073 1162 1085 1085 1175 1086 1086 1176 1073 1073 1162 1086 1086 1176 1074 1074 1163 1074 1074 1163 1086 1086 1176 1087 1087 1177 1074 1074 1163 1087 1087 1177 1075 1075 1164 1075 1075 1164 1087 1087 1177 1088 1088 1178 1075 1075 1164 1088 1088 1178 1076 1076 1165 1076 1076 1165 1088 1088 1178 1089 1089 1179 1076 1076 1165 1089 1089 1179 1077 1077 1166 1077 1077 1166 1089 1089 1179 1090 1090 1180 1077 1077 1166 1090 1090 1180 1078 1078 1167 1078 1078 1167 1090 1090 1180 1091 1091 1181 1078 1078 1167 1091 1091 1181 1079 1079 1168 1079 1079 1168 1091 1091 1181 1080 1080 1182 1079 1079 1168 1080 1080 1182 1068 1068 1169 1080 1080 1170 1092 1092 1183 1093 1093 1184 1080 1080 1170 1093 1093 1184 1081 1081 1171 1081 1081 1171 1093 1093 1184 1094 1094 1185 1081 1081 1171 1094 1094 1185 1082 1082 1172 1082 1082 1172 1094 1094 1185 1095 1095 1186 1082 1082 1172 1095 1095 1186 1083 1083 1173 1083 1083 1173 1095 1095 1186 1096 1096 1187 1083 1083 1173 1096 1096 1187 1084 1084 1174 1084 1084 1174 1096 1096 1187 1097 1097 1188 1084 1084 1174 1097 1097 1188 1085 1085 1175 1085 1085 1175 1097 1097 1188 1098 1098 1189 1085 1085 1175 1098 1098 1189 1086 1086 1176 1086 1086 1176 1098 1098 1189 1099 1099 1190 1086 1086 1176 1099 1099 1190 1087 1087 1177 1087 1087 1177 1099 1099 1190 1100 1100 1191 1087 1087 1177 1100 1100 1191 1088 1088 1178 1088 1088 1178 1100 1100 1191 1101 1101 1192 1088 1088 1178 1101 1101 1192 1089 1089 1179 1089 1089 1179 1101 1101 1192 1102 1102 1193 1089 1089 1179 1102 1102 1193 1090 1090 1180 1090 1090 1180 1102 1102 1193 1103 1103 1194 1090 1090 1180 1103 1103 1194 1091 1091 1181 1091 1091 1181 1103 1103 1194 1092 1092 1195 1091 1091 1181 1092 1092 1195 1080 1080 1182 1092 1092 1183 1104 1104 1196 1105 1105 1197 1092 1092 1183 1105 1105 1197 1093 1093 1184 1093 1093 1184 1105 1105 1197 1106 1106 1198 1093 1093 1184 1106 1106 1198 1094 1094 1185 1094 1094 1185 1106 1106 1198 1107 1107 1199 1094 1094 1185 1107 1107 1199 1095 1095 1186 1095 1095 1186 1107 1107 1199 1108 1108 1200 1095 1095 1186 1108 1108 1200 1096 1096 1187 1096 1096 1187 1108 1108 1200 1109 1109 1201 1096 1096 1187 1109 1109 1201 1097 1097 1188 1097 1097 1188 1109 1109 1201 1110 1110 1202 1097 1097 1188 1110 1110 1202 1098 1098 1189 1098 1098 1189 1110 1110 1202 1111 1111 1203 1098 1098 1189 1111 1111 1203 1099 1099 1190 1099 1099 1190 1111 1111 1203 1112 1112 1204 1099 1099 1190 1112 1112 1204 1100 1100 1191 1100 1100 1191 1112 1112 1204 1113 1113 1205 1100 1100 1191 1113 1113 1205 1101 1101 1192 1101 1101 1192 1113 1113 1205 1114 1114 1206 1101 1101 1192 1114 1114 1206 1102 1102 1193 1102 1102 1193 1114 1114 1206 1115 1115 1207 1102 1102 1193 1115 1115 1207 1103 1103 1194 1103 1103 1194 1115 1115 1207 1104 1104 1208 1103 1103 1194 1104 1104 1208 1092 1092 1195 1104 1104 1196 1116 1116 1209 1117 1117 1210 1104 1104 1196 1117 1117 1210 1105 1105 1197 1105 1105 1197 1117 1117 1210 1118 1118 1211 1105 1105 1197 1118 1118 1211 1106 1106 1198 1106 1106 1198 1118 1118 1211 1119 1119 1212 1106 1106 1198 1119 1119 1212 1107 1107 1199 1107 1107 1199 1119 1119 1212 1120 1120 1213 1107 1107 1199 1120 1120 1213 1108 1108 1200 1108 1108 1200 1120 1120 1213 1121 1121 1214 1108 1108 1200 1121 1121 1214 1109 1109 1201 1109 1109 1201 1121 1121 1214 1122 1122 1215 1109 1109 1201 1122 1122 1215 1110 1110 1202 1110 1110 1202 1122 1122 1215 1123 1123 1216 1110 1110 1202 1123 1123 1216 1111 1111 1203 1111 1111 1203 1123 1123 1216 1124 1124 1217 1111 1111 1203 1124 1124 1217 1112 1112 1204 1112 1112 1204 1124 1124 1217 1125 1125 1218 1112 1112 1204 1125 1125 1218 1113 1113 1205 1113 1113 1205 1125 1125 1218 1126 1126 1219 1113 1113 1205 1126 1126 1219 1114 1114 1206 1114 1114 1206 1126 1126 1219 1127 1127 1220 1114 1114 1206 1127 1127 1220 1115 1115 1207 1115 1115 1207 1127 1127 1220 1116 1116 1221 1115 1115 1207 1116 1116 1221 1104 1104 1208 1116 1116 1209 1128 1128 1222 1129 1129 1223 1116 1116 1209 1129 1129 1223 1117 1117 1210 1117 1117 1210 1129 1129 1223 1130 1130 1224 1117 1117 1210 1130 1130 1224 1118 1118 1211 1118 1118 1211 1130 1130 1224 1131 1131 1225 1118 1118 1211 1131 1131 1225 1119 1119 1212 1119 1119 1212 1131 1131 1225 1132 1132 1226 1119 1119 1212 1132 1132 1226 1120 1120 1213 1120 1120 1213 1132 1132 1226 1133 1133 1227 1120 1120 1213 1133 1133 1227 1121 1121 1214 1121 1121 1214 1133 1133 1227 1134 1134 1228 1121 1121 1214 1134 1134 1228 1122 1122 1215 1122 1122 1215 1134 1134 1228 1135 1135 1229 1122 1122 1215 1135 1135 1229 1123 1123 1216 1123 1123 1216 1135 1135 1229 1136 1136 1230 1123 1123 1216 1136 1136 1230 1124 1124 1217 1124 1124 1217 1136 1136 1230 1137 1137 1231 1124 1124 1217 1137 1137 1231 1125 1125 1218 1125 1125 1218 1137 1137 1231 1138 1138 1232 1125 1125 1218 1138 1138 1232 1126 1126 1219 1126 1126 1219 1138 1138 1232 1139 1139 1233 1126 1126 1219 1139 1139 1233 1127 1127 1220 1127 1127 1220 1139 1139 1233 1128 1128 1234 1127 1127 1220 1128 1128 1234 1116 1116 1221 1128 1128 1222 1140 1140 1235 1141 1141 1236 1128 1128 1222 1141 1141 1236 1129 1129 1223 1129 1129 1223 1141 1141 1236 1142 1142 1237 1129 1129 1223 1142 1142 1237 1130 1130 1224 1130 1130 1224 1142 1142 1237 1143 1143 1238 1130 1130 1224 1143 1143 1238 1131 1131 1225 1131 1131 1225 1143 1143 1238 1144 1144 1239 1131 1131 1225 1144 1144 1239 1132 1132 1226 1132 1132 1226 1144 1144 1239 1145 1145 1240 1132 1132 1226 1145 1145 1240 1133 1133 1227 1133 1133 1227 1145 1145 1240 1146 1146 1241 1133 1133 1227 1146 1146 1241 1134 1134 1228 1134 1134 1228 1146 1146 1241 1147 1147 1242 1134 1134 1228 1147 1147 1242 1135 1135 1229 1135 1135 1229 1147 1147 1242 1148 1148 1243 1135 1135 1229 1148 1148 1243 1136 1136 1230 1136 1136 1230 1148 1148 1243 1149 1149 1244 1136 1136 1230 1149 1149 1244 1137 1137 1231 1137 1137 1231 1149 1149 1244 1150 1150 1245 1137 1137 1231 1150 1150 1245 1138 1138 1232 1138 1138 1232 1150 1150 1245 1151 1151 1246 1138 1138 1232 1151 1151 1246 1139 1139 1233 1139 1139 1233 1151 1151 1246 1140 1140 1247 1139 1139 1233 1140 1140 1247 1128 1128 1234 1140 1140 1235 1152 1152 1248 1153 1153 1249 1140 1140 1235 1153 1153 1249 1141 1141 1236 1141 1141 1236 1153 1153 1249 1154 1154 1250 1141 1141 1236 1154 1154 1250 1142 1142 1237 1142 1142 1237 1154 1154 1250 1155 1155 1251 1142 1142 1237 1155 1155 1251 1143 1143 1238 1143 1143 1238 1155 1155 1251 1156 1156 1252 1143 1143 1238 1156 1156 1252 1144 1144 1239 1144 1144 1239 1156 1156 1252 1157 1157 1253 1144 1144 1239 1157 1157 1253 1145 1145 1240 1145 1145 1240 1157 1157 1253 1158 1158 1254 1145 1145 1240 1158 1158 1254 1146 1146 1241 1146 1146 1241 1158 1158 1254 1159 1159 1255 1146 1146 1241 1159 1159 1255 1147 1147 1242 1147 1147 1242 1159 1159 1255 1160 1160 1256 1147 1147 1242 1160 1160 1256 1148 1148 1243 1148 1148 1243 1160 1160 1256 1161 1161 1257 1148 1148 1243 1161 1161 1257 1149 1149 1244 1149 1149 1244 1161 1161 1257 1162 1162 1258 1149 1149 1244 1162 1162 1258 1150 1150 1245 1150 1150 1245 1162 1162 1258 1163 1163 1259 1150 1150 1245 1163 1163 1259 1151 1151 1246 1151 1151 1246 1163 1163 1259 1152 1152 1260 1151 1151 1246 1152 1152 1260 1140 1140 1247 1152 1152 1248 1164 1164 1261 1165 1165 1262 1152 1152 1248 1165 1165 1262 1153 1153 1249 1153 1153 1249 1165 1165 1262 1166 1166 1263 1153 1153 1249 1166 1166 1263 1154 1154 1250 1154 1154 1250 1166 1166 1263 1167 1167 1264 1154 1154 1250 1167 1167 1264 1155 1155 1251 1155 1155 1251 1167 1167 1264 1168 1168 1265 1155 1155 1251 1168 1168 1265 1156 1156 1252 1156 1156 1252 1168 1168 1265 1169 1169 1266 1156 1156 1252 1169 1169 1266 1157 1157 1253 1157 1157 1253 1169 1169 1266 1170 1170 1267 1157 1157 1253 1170 1170 1267 1158 1158 1254 1158 1158 1254 1170 1170 1267 1171 1171 1268 1158 1158 1254 1171 1171 1268 1159 1159 1255 1159 1159 1255 1171 1171 1268 1172 1172 1269 1159 1159 1255 1172 1172 1269 1160 1160 1256 1160 1160 1256 1172 1172 1269 1173 1173 1270 1160 1160 1256 1173 1173 1270 1161 1161 1257 1161 1161 1257 1173 1173 1270 1174 1174 1271 1161 1161 1257 1174 1174 1271 1162 1162 1258 1162 1162 1258 1174 1174 1271 1175 1175 1272 1162 1162 1258 1175 1175 1272 1163 1163 1259 1163 1163 1259 1175 1175 1272 1164 1164 1273 1163 1163 1259 1164 1164 1273 1152 1152 1260 1164 1164 1261 1176 1176 1274 1177 1177 1275 1164 1164 1261 1177 1177 1275 1165 1165 1262 1165 1165 1262 1177 1177 1275 1178 1178 1276 1165 1165 1262 1178 1178 1276 1166 1166 1263 1166 1166 1263 1178 1178 1276 1179 1179 1277 1166 1166 1263 1179 1179 1277 1167 1167 1264 1167 1167 1264 1179 1179 1277 1180 1180 1278 1167 1167 1264 1180 1180 1278 1168 1168 1265 1168 1168 1265 1180 1180 1278 1181 1181 1279 1168 1168 1265 1181 1181 1279 1169 1169 1266 1169 1169 1266 1181 1181 1279 1182 1182 1280 1169 1169 1266 1182 1182 1280 1170 1170 1267 1170 1170 1267 1182 1182 1280 1183 1183 1281 1170 1170 1267 1183 1183 1281 1171 1171 1268 1171 1171 1268 1183 1183 1281 1184 1184 1282 1171 1171 1268 1184 1184 1282 1172 1172 1269 1172 1172 1269 1184 1184 1282 1185 1185 1283 1172 1172 1269 1185 1185 1283 1173 1173 1270 1173 1173 1270 1185 1185 1283 1186 1186 1284 1173 1173 1270 1186 1186 1284 1174 1174 1271 1174 1174 1271 1186 1186 1284 1187 1187 1285 1174 1174 1271 1187 1187 1285 1175 1175 1272 1175 1175 1272 1187 1187 1285 1176 1176 1286 1175 1175 1272 1176 1176 1286 1164 1164 1273 1176 1176 1274 1188 1188 1287 1189 1189 1288 1176 1176 1274 1189 1189 1288 1177 1177 1275 1177 1177 1275 1189 1189 1288 1190 1190 1289 1177 1177 1275 1190 1190 1289 1178 1178 1276 1178 1178 1276 1190 1190 1289 1191 1191 1290 1178 1178 1276 1191 1191 1290 1179 1179 1277 1179 1179 1277 1191 1191 1290 1192 1192 1291 1179 1179 1277 1192 1192 1291 1180 1180 1278 1180 1180 1278 1192 1192 1291 1193 1193 1292 1180 1180 1278 1193 1193 1292 1181 1181 1279 1181 1181 1279 1193 1193 1292 1194 1194 1293 1181 1181 1279 1194 1194 1293 1182 1182 1280 1182 1182 1280 1194 1194 1293 1195 1195 1294 1182 1182 1280 1195 1195 1294 1183 1183 1281 1183 1183 1281 1195 1195 1294 1196 1196 1295 1183 1183 1281 1196 1196 1295 1184 1184 1282 1184 1184 1282 1196 1196 1295 1197 1197 1296 1184 1184 1282 1197 1197 1296 1185 1185 1283 1185 1185 1283 1197 1197 1296 1198 1198 1297 1185 1185 1283 1198 1198 1297 1186 1186 1284 1186 1186 1284 1198 1198 1297 1199 1199 1298 1186 1186 1284 1199 1199 1298 1187 1187 1285 1187 1187 1285 1199 1199 1298 1188 1188 1299 1187 1187 1285 1188 1188 1299 1176 1176 1286 1188 1188 1287 1200 1200 1300 1201 1201 1301 1188 1188 1287 1201 1201 1301 1189 1189 1288 1189 1189 1288 1201 1201 1301 1202 1202 1302 1189 1189 1288 1202 1202 1302 1190 1190 1289 1190 1190 1289 1202 1202 1302 1203 1203 1303 1190 1190 1289 1203 1203 1303 1191 1191 1290 1191 1191 1290 1203 1203 1303 1204 1204 1304 1191 1191 1290 1204 1204 1304 1192 1192 1291 1192 1192 1291 1204 1204 1304 1205 1205 1305 1192 1192 1291 1205 1205 1305 1193 1193 1292 1193 1193 1292 1205 1205 1305 1206 1206 1306 1193 1193 1292 1206 1206 1306 1194 1194 1293 1194 1194 1293 1206 1206 1306 1207 1207 1307 1194 1194 1293 1207 1207 1307 1195 1195 1294 1195 1195 1294 1207 1207 1307 1208 1208 1308 1195 1195 1294 1208 1208 1308 1196 1196 1295 1196 1196 1295 1208 1208 1308 1209 1209 1309 1196 1196 1295 1209 1209 1309 1197 1197 1296 1197 1197 1296 1209 1209 1309 1210 1210 1310 1197 1197 1296 1210 1210 1310 1198 1198 1297 1198 1198 1297 1210 1210 1310 1211 1211 1311 1198 1198 1297 1211 1211 1311 1199 1199 1298 1199 1199 1298 1211 1211 1311 1200 1200 1312 1199 1199 1298 1200 1200 1312 1188 1188 1299 1200 1200 1300 1212 1212 1313 1213 1213 1314 1200 1200 1300 1213 1213 1314 1201 1201 1301 1201 1201 1301 1213 1213 1314 1214 1214 1315 1201 1201 1301 1214 1214 1315 1202 1202 1302 1202 1202 1302 1214 1214 1315 1215 1215 1316 1202 1202 1302 1215 1215 1316 1203 1203 1303 1203 1203 1303 1215 1215 1316 1216 1216 1317 1203 1203 1303 1216 1216 1317 1204 1204 1304 1204 1204 1304 1216 1216 1317 1217 1217 1318 1204 1204 1304 1217 1217 1318 1205 1205 1305 1205 1205 1305 1217 1217 1318 1218 1218 1319 1205 1205 1305 1218 1218 1319 1206 1206 1306 1206 1206 1306 1218 1218 1319 1219 1219 1320 1206 1206 1306 1219 1219 1320 1207 1207 1307 1207 1207 1307 1219 1219 1320 1220 1220 1321 1207 1207 1307 1220 1220 1321 1208 1208 1308 1208 1208 1308 1220 1220 1321 1221 1221 1322 1208 1208 1308 1221 1221 1322 1209 1209 1309 1209 1209 1309 1221 1221 1322 1222 1222 1323 1209 1209 1309 1222 1222 1323 1210 1210 1310 1210 1210 1310 1222 1222 1323 1223 1223 1324 1210 1210 1310 1223 1223 1324 1211 1211 1311 1211 1211 1311 1223 1223 1324 1212 1212 1325 1211 1211 1311 1212 1212 1325 1200 1200 1312 1212 1212 1313 1224 1224 1326 1225 1225 1327 1212 1212 1313 1225 1225 1327 1213 1213 1314 1213 1213 1314 1225 1225 1327 1226 1226 1328 1213 1213 1314 1226 1226 1328 1214 1214 1315 1214 1214 1315 1226 1226 1328 1227 1227 1329 1214 1214 1315 1227 1227 1329 1215 1215 1316 1215 1215 1316 1227 1227 1329 1228 1228 1330 1215 1215 1316 1228 1228 1330 1216 1216 1317 1216 1216 1317 1228 1228 1330 1229 1229 1331 1216 1216 1317 1229 1229 1331 1217 1217 1318 1217 1217 1318 1229 1229 1331 1230 1230 1332 1217 1217 1318 1230 1230 1332 1218 1218 1319 1218 1218 1319 1230 1230 1332 1231 1231 1333 1218 1218 1319 1231 1231 1333 1219 1219 1320 1219 1219 1320 1231 1231 1333 1232 1232 1334 1219 1219 1320 1232 1232 1334 1220 1220 1321 1220 1220 1321 1232 1232 1334 1233 1233 1335 1220 1220 1321 1233 1233 1335 1221 1221 1322 1221 1221 1322 1233 1233 1335 1234 1234 1336 1221 1221 1322 1234 1234 1336 1222 1222 1323 1222 1222 1323 1234 1234 1336 1235 1235 1337 1222 1222 1323 1235 1235 1337 1223 1223 1324 1223 1223 1324 1235 1235 1337 1224 1224 1338 1223 1223 1324 1224 1224 1338 1212 1212 1325 1224 1224 1326 1236 1236 1339 1237 1237 1340 1224 1224 1326 1237 1237 1340 1225 1225 1327 1225 1225 1327 1237 1237 1340 1238 1238 1341 1225 1225 1327 1238 1238 1341 1226 1226 1328 1226 1226 1328 1238 1238 1341 1239 1239 1342 1226 1226 1328 1239 1239 1342 1227 1227 1329 1227 1227 1329 1239 1239 1342 1240 1240 1343 1227 1227 1329 1240 1240 1343 1228 1228 1330 1228 1228 1330 1240 1240 1343 1241 1241 1344 1228 1228 1330 1241 1241 1344 1229 1229 1331 1229 1229 1331 1241 1241 1344 1242 1242 1345 1229 1229 1331 1242 1242 1345 1230 1230 1332 1230 1230 1332 1242 1242 1345 1243 1243 1346 1230 1230 1332 1243 1243 1346 1231 1231 1333 1231 1231 1333 1243 1243 1346 1244 1244 1347 1231 1231 1333 1244 1244 1347 1232 1232 1334 1232 1232 1334 1244 1244 1347 1245 1245 1348 1232 1232 1334 1245 1245 1348 1233 1233 1335 1233 1233 1335 1245 1245 1348 1246 1246 1349 1233 1233 1335 1246 1246 1349 1234 1234 1336 1234 1234 1336 1246 1246 1349 1247 1247 1350 1234 1234 1336 1247 1247 1350 1235 1235 1337 1235 1235 1337 1247 1247 1350 1236 1236 1351 1235 1235 1337 1236 1236 1351 1224 1224 1338 1236 1236 1339 1248 1248 1352 1249 1249 1353 1236 1236 1339 1249 1249 1353 1237 1237 1340 1237 1237 1340 1249 1249 1353 1250 1250 1354 1237 1237 1340 1250 1250 1354 1238 1238 1341 1238 1238 1341 1250 1250 1354 1251 1251 1355 1238 1238 1341 1251 1251 1355 1239 1239 1342 1239 1239 1342 1251 1251 1355 1252 1252 1356 1239 1239 1342 1252 1252 1356 1240 1240 1343 1240 1240 1343 1252 1252 1356 1253 1253 1357 1240 1240 1343 1253 1253 1357 1241 1241 1344 1241 1241 1344 1253 1253 1357 1254 1254 1358 1241 1241 1344 1254 1254 1358 1242 1242 1345 1242 1242 1345 1254 1254 1358 1255 1255 1359 1242 1242 1345 1255 1255 1359 1243 1243 1346 1243 1243 1346 1255 1255 1359 1256 1256 1360 1243 1243 1346 1256 1256 1360 1244 1244 1347 1244 1244 1347 1256 1256 1360 1257 1257 1361 1244 1244 1347 1257 1257 1361 1245 1245 1348 1245 1245 1348 1257 1257 1361 1258 1258 1362 1245 1245 1348 1258 1258 1362 1246 1246 1349 1246 1246 1349 1258 1258 1362 1259 1259 1363 1246 1246 1349 1259 1259 1363 1247 1247 1350 1247 1247 1350 1259 1259 1363 1248 1248 1364 1247 1247 1350 1248 1248 1364 1236 1236 1351 1248 1248 1352 1260 1260 1365 1261 1261 1366 1248 1248 1352 1261 1261 1366 1249 1249 1353 1249 1249 1353 1261 1261 1366 1262 1262 1367 1249 1249 1353 1262 1262 1367 1250 1250 1354 1250 1250 1354 1262 1262 1367 1263 1263 1368 1250 1250 1354 1263 1263 1368 1251 1251 1355 1251 1251 1355 1263 1263 1368 1264 1264 1369 1251 1251 1355 1264 1264 1369 1252 1252 1356 1252 1252 1356 1264 1264 1369 1265 1265 1370 1252 1252 1356 1265 1265 1370 1253 1253 1357 1253 1253 1357 1265 1265 1370 1266 1266 1371 1253 1253 1357 1266 1266 1371 1254 1254 1358 1254 1254 1358 1266 1266 1371 1267 1267 1372 1254 1254 1358 1267 1267 1372 1255 1255 1359 1255 1255 1359 1267 1267 1372 1268 1268 1373 1255 1255 1359 1268 1268 1373 1256 1256 1360 1256 1256 1360 1268 1268 1373 1269 1269 1374 1256 1256 1360 1269 1269 1374 1257 1257 1361 1257 1257 1361 1269 1269 1374 1270 1270 1375 1257 1257 1361 1270 1270 1375 1258 1258 1362 1258 1258 1362 1270 1270 1375 1271 1271 1376 1258 1258 1362 1271 1271 1376 1259 1259 1363 1259 1259 1363 1271 1271 1376 1260 1260 1377 1259 1259 1363 1260 1260 1377 1248 1248 1364 1260 1260 1365 1272 1272 1378 1273 1273 1379 1260 1260 1365 1273 1273 1379 1261 1261 1366 1261 1261 1366 1273 1273 1379 1274 1274 1380 1261 1261 1366 1274 1274 1380 1262 1262 1367 1262 1262 1367 1274 1274 1380 1275 1275 1381 1262 1262 1367 1275 1275 1381 1263 1263 1368 1263 1263 1368 1275 1275 1381 1276 1276 1382 1263 1263 1368 1276 1276 1382 1264 1264 1369 1264 1264 1369 1276 1276 1382 1277 1277 1383 1264 1264 1369 1277 1277 1383 1265 1265 1370 1265 1265 1370 1277 1277 1383 1278 1278 1384 1265 1265 1370 1278 1278 1384 1266 1266 1371 1266 1266 1371 1278 1278 1384 1279 1279 1385 1266 1266 1371 1279 1279 1385 1267 1267 1372 1267 1267 1372 1279 1279 1385 1280 1280 1386 1267 1267 1372 1280 1280 1386 1268 1268 1373 1268 1268 1373 1280 1280 1386 1281 1281 1387 1268 1268 1373 1281 1281 1387 1269 1269 1374 1269 1269 1374 1281 1281 1387 1282 1282 1388 1269 1269 1374 1282 1282 1388 1270 1270 1375 1270 1270 1375 1282 1282 1388 1283 1283 1389 1270 1270 1375 1283 1283 1389 1271 1271 1376 1271 1271 1376 1283 1283 1389 1272 1272 1390 1271 1271 1376 1272 1272 1390 1260 1260 1377 1272 1272 1378 1284 1284 1391 1285 1285 1392 1272 1272 1378 1285 1285 1392 1273 1273 1379 1273 1273 1379 1285 1285 1392 1286 1286 1393 1273 1273 1379 1286 1286 1393 1274 1274 1380 1274 1274 1380 1286 1286 1393 1287 1287 1394 1274 1274 1380 1287 1287 1394 1275 1275 1381 1275 1275 1381 1287 1287 1394 1288 1288 1395 1275 1275 1381 1288 1288 1395 1276 1276 1382 1276 1276 1382 1288 1288 1395 1289 1289 1396 1276 1276 1382 1289 1289 1396 1277 1277 1383 1277 1277 1383 1289 1289 1396 1290 1290 1397 1277 1277 1383 1290 1290 1397 1278 1278 1384 1278 1278 1384 1290 1290 1397 1291 1291 1398 1278 1278 1384 1291 1291 1398 1279 1279 1385 1279 1279 1385 1291 1291 1398 1292 1292 1399 1279 1279 1385 1292 1292 1399 1280 1280 1386 1280 1280 1386 1292 1292 1399 1293 1293 1400 1280 1280 1386 1293 1293 1400 1281 1281 1387 1281 1281 1387 1293 1293 1400 1294 1294 1401 1281 1281 1387 1294 1294 1401 1282 1282 1388 1282 1282 1388 1294 1294 1401 1295 1295 1402 1282 1282 1388 1295 1295 1402 1283 1283 1389 1283 1283 1389 1295 1295 1402 1284 1284 1403 1283 1283 1389 1284 1284 1403 1272 1272 1390 1284 1284 1391 1296 1296 1404 1297 1297 1405 1284 1284 1391 1297 1297 1405 1285 1285 1392 1285 1285 1392 1297 1297 1405 1298 1298 1406 1285 1285 1392 1298 1298 1406 1286 1286 1393 1286 1286 1393 1298 1298 1406 1299 1299 1407 1286 1286 1393 1299 1299 1407 1287 1287 1394 1287 1287 1394 1299 1299 1407 1300 1300 1408 1287 1287 1394 1300 1300 1408 1288 1288 1395 1288 1288 1395 1300 1300 1408 1301 1301 1409 1288 1288 1395 1301 1301 1409 1289 1289 1396 1289 1289 1396 1301 1301 1409 1302 1302 1410 1289 1289 1396 1302 1302 1410 1290 1290 1397 1290 1290 1397 1302 1302 1410 1303 1303 1411 1290 1290 1397 1303 1303 1411 1291 1291 1398 1291 1291 1398 1303 1303 1411 1304 1304 1412 1291 1291 1398 1304 1304 1412 1292 1292 1399 1292 1292 1399 1304 1304 1412 1305 1305 1413 1292 1292 1399 1305 1305 1413 1293 1293 1400 1293 1293 1400 1305 1305 1413 1306 1306 1414 1293 1293 1400 1306 1306 1414 1294 1294 1401 1294 1294 1401 1306 1306 1414 1307 1307 1415 1294 1294 1401 1307 1307 1415 1295 1295 1402 1295 1295 1402 1307 1307 1415 1296 1296 1416 1295 1295 1402 1296 1296 1416 1284 1284 1403 1296 1296 1404 1308 1308 1417 1309 1309 1418 1296 1296 1404 1309 1309 1418 1297 1297 1405 1297 1297 1405 1309 1309 1418 1310 1310 1419 1297 1297 1405 1310 1310 1419 1298 1298 1406 1298 1298 1406 1310 1310 1419 1311 1311 1420 1298 1298 1406 1311 1311 1420 1299 1299 1407 1299 1299 1407 1311 1311 1420 1312 1312 1421 1299 1299 1407 1312 1312 1421 1300 1300 1408 1300 1300 1408 1312 1312 1421 1313 1313 1422 1300 1300 1408 1313 1313 1422 1301 1301 1409 1301 1301 1409 1313 1313 1422 1314 1314 1423 1301 1301 1409 1314 1314 1423 1302 1302 1410 1302 1302 1410 1314 1314 1423 1315 1315 1424 1302 1302 1410 1315 1315 1424 1303 1303 1411 1303 1303 1411 1315 1315 1424 1316 1316 1425 1303 1303 1411 1316 1316 1425 1304 1304 1412 1304 1304 1412 1316 1316 1425 1317 1317 1426 1304 1304 1412 1317 1317 1426 1305 1305 1413 1305 1305 1413 1317 1317 1426 1318 1318 1427 1305 1305 1413 1318 1318 1427 1306 1306 1414 1306 1306 1414 1318 1318 1427 1319 1319 1428 1306 1306 1414 1319 1319 1428 1307 1307 1415 1307 1307 1415 1319 1319 1428 1308 1308 1429 1307 1307 1415 1308 1308 1429 1296 1296 1416 1308 1308 1417 1320 1320 1430 1321 1321 1431 1308 1308 1417 1321 1321 1431 1309 1309 1418 1309 1309 1418 1321 1321 1431 1322 1322 1432 1309 1309 1418 1322 1322 1432 1310 1310 1419 1310 1310 1419 1322 1322 1432 1323 1323 1433 1310 1310 1419 1323 1323 1433 1311 1311 1420 1311 1311 1420 1323 1323 1433 1324 1324 1434 1311 1311 1420 1324 1324 1434 1312 1312 1421 1312 1312 1421 1324 1324 1434 1325 1325 1435 1312 1312 1421 1325 1325 1435 1313 1313 1422 1313 1313 1422 1325 1325 1435 1326 1326 1436 1313 1313 1422 1326 1326 1436 1314 1314 1423 1314 1314 1423 1326 1326 1436 1327 1327 1437 1314 1314 1423 1327 1327 1437 1315 1315 1424 1315 1315 1424 1327 1327 1437 1328 1328 1438 1315 1315 1424 1328 1328 1438 1316 1316 1425 1316 1316 1425 1328 1328 1438 1329 1329 1439 1316 1316 1425 1329 1329 1439 1317 1317 1426 1317 1317 1426 1329 1329 1439 1330 1330 1440 1317 1317 1426 1330 1330 1440 1318 1318 1427 1318 1318 1427 1330 1330 1440 1331 1331 1441 1318 1318 1427 1331 1331 1441 1319 1319 1428 1319 1319 1428 1331 1331 1441 1320 1320 1442 1319 1319 1428 1320 1320 1442 1308 1308 1429 1320 1320 1430 1332 1332 1443 1333 1333 1444 1320 1320 1430 1333 1333 1444 1321 1321 1431 1321 1321 1431 1333 1333 1444 1334 1334 1445 1321 1321 1431 1334 1334 1445 1322 1322 1432 1322 1322 1432 1334 1334 1445 1335 1335 1446 1322 1322 1432 1335 1335 1446 1323 1323 1433 1323 1323 1433 1335 1335 1446 1336 1336 1447 1323 1323 1433 1336 1336 1447 1324 1324 1434 1324 1324 1434 1336 1336 1447 1337 1337 1448 1324 1324 1434 1337 1337 1448 1325 1325 1435 1325 1325 1435 1337 1337 1448 1338 1338 1449 1325 1325 1435 1338 1338 1449 1326 1326 1436 1326 1326 1436 1338 1338 1449 1339 1339 1450 1326 1326 1436 1339 1339 1450 1327 1327 1437 1327 1327 1437 1339 1339 1450 1340 1340 1451 1327 1327 1437 1340 1340 1451 1328 1328 1438 1328 1328 1438 1340 1340 1451 1341 1341 1452 1328 1328 1438 1341 1341 1452 1329 1329 1439 1329 1329 1439 1341 1341 1452 1342 1342 1453 1329 1329 1439 1342 1342 1453 1330 1330 1440 1330 1330 1440 1342 1342 1453 1343 1343 1454 1330 1330 1440 1343 1343 1454 1331 1331 1441 1331 1331 1441 1343 1343 1454 1332 1332 1455 1331 1331 1441 1332 1332 1455 1320 1320 1442 1332 1332 1443 1344 1344 1456 1345 1345 1457 1332 1332 1443 1345 1345 1457 1333 1333 1444 1333 1333 1444 1345 1345 1457 1346 1346 1458 1333 1333 1444 1346 1346 1458 1334 1334 1445 1334 1334 1445 1346 1346 1458 1347 1347 1459 1334 1334 1445 1347 1347 1459 1335 1335 1446 1335 1335 1446 1347 1347 1459 1348 1348 1460 1335 1335 1446 1348 1348 1460 1336 1336 1447 1336 1336 1447 1348 1348 1460 1349 1349 1461 1336 1336 1447 1349 1349 1461 1337 1337 1448 1337 1337 1448 1349 1349 1461 1350 1350 1462 1337 1337 1448 1350 1350 1462 1338 1338 1449 1338 1338 1449 1350 1350 1462 1351 1351 1463 1338 1338 1449 1351 1351 1463 1339 1339 1450 1339 1339 1450 1351 1351 1463 1352 1352 1464 1339 1339 1450 1352 1352 1464 1340 1340 1451 1340 1340 1451 1352 1352 1464 1353 1353 1465 1340 1340 1451 1353 1353 1465 1341 1341 1452 1341 1341 1452 1353 1353 1465 1354 1354 1466 1341 1341 1452 1354 1354 1466 1342 1342 1453 1342 1342 1453 1354 1354 1466 1355 1355 1467 1342 1342 1453 1355 1355 1467 1343 1343 1454 1343 1343 1454 1355 1355 1467 1344 1344 1468 1343 1343 1454 1344 1344 1468 1332 1332 1455 1344 1344 1456 1356 1356 1469 1357 1357 1470 1344 1344 1456 1357 1357 1470 1345 1345 1457 1345 1345 1457 1357 1357 1470 1358 1358 1471 1345 1345 1457 1358 1358 1471 1346 1346 1458 1346 1346 1458 1358 1358 1471 1359 1359 1472 1346 1346 1458 1359 1359 1472 1347 1347 1459 1347 1347 1459 1359 1359 1472 1360 1360 1473 1347 1347 1459 1360 1360 1473 1348 1348 1460 1348 1348 1460 1360 1360 1473 1361 1361 1474 1348 1348 1460 1361 1361 1474 1349 1349 1461 1349 1349 1461 1361 1361 1474 1362 1362 1475 1349 1349 1461 1362 1362 1475 1350 1350 1462 1350 1350 1462 1362 1362 1475 1363 1363 1476 1350 1350 1462 1363 1363 1476 1351 1351 1463 1351 1351 1463 1363 1363 1476 1364 1364 1477 1351 1351 1463 1364 1364 1477 1352 1352 1464 1352 1352 1464 1364 1364 1477 1365 1365 1478 1352 1352 1464 1365 1365 1478 1353 1353 1465 1353 1353 1465 1365 1365 1478 1366 1366 1479 1353 1353 1465 1366 1366 1479 1354 1354 1466 1354 1354 1466 1366 1366 1479 1367 1367 1480 1354 1354 1466 1367 1367 1480 1355 1355 1467 1355 1355 1467 1367 1367 1480 1356 1356 1481 1355 1355 1467 1356 1356 1481 1344 1344 1468 1356 1356 1469 1368 1368 1482 1369 1369 1483 1356 1356 1469 1369 1369 1483 1357 1357 1470 1357 1357 1470 1369 1369 1483 1370 1370 1484 1357 1357 1470 1370 1370 1484 1358 1358 1471 1358 1358 1471 1370 1370 1484 1371 1371 1485 1358 1358 1471 1371 1371 1485 1359 1359 1472 1359 1359 1472 1371 1371 1485 1372 1372 1486 1359 1359 1472 1372 1372 1486 1360 1360 1473 1360 1360 1473 1372 1372 1486 1373 1373 1487 1360 1360 1473 1373 1373 1487 1361 1361 1474 1361 1361 1474 1373 1373 1487 1374 1374 1488 1361 1361 1474 1374 1374 1488 1362 1362 1475 1362 1362 1475 1374 1374 1488 1375 1375 1489 1362 1362 1475 1375 1375 1489 1363 1363 1476 1363 1363 1476 1375 1375 1489 1376 1376 1490 1363 1363 1476 1376 1376 1490 1364 1364 1477 1364 1364 1477 1376 1376 1490 1377 1377 1491 1364 1364 1477 1377 1377 1491 1365 1365 1478 1365 1365 1478 1377 1377 1491 1378 1378 1492 1365 1365 1478 1378 1378 1492 1366 1366 1479 1366 1366 1479 1378 1378 1492 1379 1379 1493 1366 1366 1479 1379 1379 1493 1367 1367 1480 1367 1367 1480 1379 1379 1493 1368 1368 1494 1367 1367 1480 1368 1368 1494 1356 1356 1481 1368 1368 1482 1380 1380 1495 1381 1381 1496 1368 1368 1482 1381 1381 1496 1369 1369 1483 1369 1369 1483 1381 1381 1496 1382 1382 1497 1369 1369 1483 1382 1382 1497 1370 1370 1484 1370 1370 1484 1382 1382 1497 1383 1383 1498 1370 1370 1484 1383 1383 1498 1371 1371 1485 1371 1371 1485 1383 1383 1498 1384 1384 1499 1371 1371 1485 1384 1384 1499 1372 1372 1486 1372 1372 1486 1384 1384 1499 1385 1385 1500 1372 1372 1486 1385 1385 1500 1373 1373 1487 1373 1373 1487 1385 1385 1500 1386 1386 1501 1373 1373 1487 1386 1386 1501 1374 1374 1488 1374 1374 1488 1386 1386 1501 1387 1387 1502 1374 1374 1488 1387 1387 1502 1375 1375 1489 1375 1375 1489 1387 1387 1502 1388 1388 1503 1375 1375 1489 1388 1388 1503 1376 1376 1490 1376 1376 1490 1388 1388 1503 1389 1389 1504 1376 1376 1490 1389 1389 1504 1377 1377 1491 1377 1377 1491 1389 1389 1504 1390 1390 1505 1377 1377 1491 1390 1390 1505 1378 1378 1492 1378 1378 1492 1390 1390 1505 1391 1391 1506 1378 1378 1492 1391 1391 1506 1379 1379 1493 1379 1379 1493 1391 1391 1506 1380 1380 1507 1379 1379 1493 1380 1380 1507 1368 1368 1494 1380 1380 1495 1392 1392 1508 1393 1393 1509 1380 1380 1495 1393 1393 1509 1381 1381 1496 1381 1381 1496 1393 1393 1509 1394 1394 1510 1381 1381 1496 1394 1394 1510 1382 1382 1497 1382 1382 1497 1394 1394 1510 1395 1395 1511 1382 1382 1497 1395 1395 1511 1383 1383 1498 1383 1383 1498 1395 1395 1511 1396 1396 1512 1383 1383 1498 1396 1396 1512 1384 1384 1499 1384 1384 1499 1396 1396 1512 1397 1397 1513 1384 1384 1499 1397 1397 1513 1385 1385 1500 1385 1385 1500 1397 1397 1513 1398 1398 1514 1385 1385 1500 1398 1398 1514 1386 1386 1501 1386 1386 1501 1398 1398 1514 1399 1399 1515 1386 1386 1501 1399 1399 1515 1387 1387 1502 1387 1387 1502 1399 1399 1515 1400 1400 1516 1387 1387 1502 1400 1400 1516 1388 1388 1503 1388 1388 1503 1400 1400 1516 1401 1401 1517 1388 1388 1503 1401 1401 1517 1389 1389 1504 1389 1389 1504 1401 1401 1517 1402 1402 1518 1389 1389 1504 1402 1402 1518 1390 1390 1505 1390 1390 1505 1402 1402 1518 1403 1403 1519 1390 1390 1505 1403 1403 1519 1391 1391 1506 1391 1391 1506 1403 1403 1519 1392 1392 1520 1391 1391 1506 1392 1392 1520 1380 1380 1507 1392 1392 1508 1404 1404 1521 1405 1405 1522 1392 1392 1508 1405 1405 1522 1393 1393 1509 1393 1393 1509 1405 1405 1522 1406 1406 1523 1393 1393 1509 1406 1406 1523 1394 1394 1510 1394 1394 1510 1406 1406 1523 1407 1407 1524 1394 1394 1510 1407 1407 1524 1395 1395 1511 1395 1395 1511 1407 1407 1524 1408 1408 1525 1395 1395 1511 1408 1408 1525 1396 1396 1512 1396 1396 1512 1408 1408 1525 1409 1409 1526 1396 1396 1512 1409 1409 1526 1397 1397 1513 1397 1397 1513 1409 1409 1526 1410 1410 1527 1397 1397 1513 1410 1410 1527 1398 1398 1514 1398 1398 1514 1410 1410 1527 1411 1411 1528 1398 1398 1514 1411 1411 1528 1399 1399 1515 1399 1399 1515 1411 1411 1528 1412 1412 1529 1399 1399 1515 1412 1412 1529 1400 1400 1516 1400 1400 1516 1412 1412 1529 1413 1413 1530 1400 1400 1516 1413 1413 1530 1401 1401 1517 1401 1401 1517 1413 1413 1530 1414 1414 1531 1401 1401 1517 1414 1414 1531 1402 1402 1518 1402 1402 1518 1414 1414 1531 1415 1415 1532 1402 1402 1518 1415 1415 1532 1403 1403 1519 1403 1403 1519 1415 1415 1532 1404 1404 1533 1403 1403 1519 1404 1404 1533 1392 1392 1520 1404 1404 1521 1416 1416 1534 1417 1417 1535 1404 1404 1521 1417 1417 1535 1405 1405 1522 1405 1405 1522 1417 1417 1535 1418 1418 1536 1405 1405 1522 1418 1418 1536 1406 1406 1523 1406 1406 1523 1418 1418 1536 1419 1419 1537 1406 1406 1523 1419 1419 1537 1407 1407 1524 1407 1407 1524 1419 1419 1537 1420 1420 1538 1407 1407 1524 1420 1420 1538 1408 1408 1525 1408 1408 1525 1420 1420 1538 1421 1421 1539 1408 1408 1525 1421 1421 1539 1409 1409 1526 1409 1409 1526 1421 1421 1539 1422 1422 1540 1409 1409 1526 1422 1422 1540 1410 1410 1527 1410 1410 1527 1422 1422 1540 1423 1423 1541 1410 1410 1527 1423 1423 1541 1411 1411 1528 1411 1411 1528 1423 1423 1541 1424 1424 1542 1411 1411 1528 1424 1424 1542 1412 1412 1529 1412 1412 1529 1424 1424 1542 1425 1425 1543 1412 1412 1529 1425 1425 1543 1413 1413 1530 1413 1413 1530 1425 1425 1543 1426 1426 1544 1413 1413 1530 1426 1426 1544 1414 1414 1531 1414 1414 1531 1426 1426 1544 1427 1427 1545 1414 1414 1531 1427 1427 1545 1415 1415 1532 1415 1415 1532 1427 1427 1545 1416 1416 1546 1415 1415 1532 1416 1416 1546 1404 1404 1533 1416 1416 1534 1428 1428 1547 1429 1429 1548 1416 1416 1534 1429 1429 1548 1417 1417 1535 1417 1417 1535 1429 1429 1548 1430 1430 1549 1417 1417 1535 1430 1430 1549 1418 1418 1536 1418 1418 1536 1430 1430 1549 1431 1431 1550 1418 1418 1536 1431 1431 1550 1419 1419 1537 1419 1419 1537 1431 1431 1550 1432 1432 1551 1419 1419 1537 1432 1432 1551 1420 1420 1538 1420 1420 1538 1432 1432 1551 1433 1433 1552 1420 1420 1538 1433 1433 1552 1421 1421 1539 1421 1421 1539 1433 1433 1552 1434 1434 1553 1421 1421 1539 1434 1434 1553 1422 1422 1540 1422 1422 1540 1434 1434 1553 1435 1435 1554 1422 1422 1540 1435 1435 1554 1423 1423 1541 1423 1423 1541 1435 1435 1554 1436 1436 1555 1423 1423 1541 1436 1436 1555 1424 1424 1542 1424 1424 1542 1436 1436 1555 1437 1437 1556 1424 1424 1542 1437 1437 1556 1425 1425 1543 1425 1425 1543 1437 1437 1556 1438 1438 1557 1425 1425 1543 1438 1438 1557 1426 1426 1544 1426 1426 1544 1438 1438 1557 1439 1439 1558 1426 1426 1544 1439 1439 1558 1427 1427 1545 1427 1427 1545 1439 1439 1558 1428 1428 1559 1427 1427 1545 1428 1428 1559 1416 1416 1546 1428 1428 1547 1440 1440 1560 1441 1441 1561 1428 1428 1547 1441 1441 1561 1429 1429 1548 1429 1429 1548 1441 1441 1561 1442 1442 1562 1429 1429 1548 1442 1442 1562 1430 1430 1549 1430 1430 1549 1442 1442 1562 1443 1443 1563 1430 1430 1549 1443 1443 1563 1431 1431 1550 1431 1431 1550 1443 1443 1563 1444 1444 1564 1431 1431 1550 1444 1444 1564 1432 1432 1551 1432 1432 1551 1444 1444 1564 1445 1445 1565 1432 1432 1551 1445 1445 1565 1433 1433 1552 1433 1433 1552 1445 1445 1565 1446 1446 1566 1433 1433 1552 1446 1446 1566 1434 1434 1553 1434 1434 1553 1446 1446 1566 1447 1447 1567 1434 1434 1553 1447 1447 1567 1435 1435 1554 1435 1435 1554 1447 1447 1567 1448 1448 1568 1435 1435 1554 1448 1448 1568 1436 1436 1555 1436 1436 1555 1448 1448 1568 1449 1449 1569 1436 1436 1555 1449 1449 1569 1437 1437 1556 1437 1437 1556 1449 1449 1569 1450 1450 1570 1437 1437 1556 1450 1450 1570 1438 1438 1557 1438 1438 1557 1450 1450 1570 1451 1451 1571 1438 1438 1557 1451 1451 1571 1439 1439 1558 1439 1439 1558 1451 1451 1571 1440 1440 1572 1439 1439 1558 1440 1440 1572 1428 1428 1559 1440 1440 1560 1452 1452 1573 1453 1453 1574 1440 1440 1560 1453 1453 1574 1441 1441 1561 1441 1441 1561 1453 1453 1574 1454 1454 1575 1441 1441 1561 1454 1454 1575 1442 1442 1562 1442 1442 1562 1454 1454 1575 1455 1455 1576 1442 1442 1562 1455 1455 1576 1443 1443 1563 1443 1443 1563 1455 1455 1576 1456 1456 1577 1443 1443 1563 1456 1456 1577 1444 1444 1564 1444 1444 1564 1456 1456 1577 1457 1457 1578 1444 1444 1564 1457 1457 1578 1445 1445 1565 1445 1445 1565 1457 1457 1578 1458 1458 1579 1445 1445 1565 1458 1458 1579 1446 1446 1566 1446 1446 1566 1458 1458 1579 1459 1459 1580 1446 1446 1566 1459 1459 1580 1447 1447 1567 1447 1447 1567 1459 1459 1580 1460 1460 1581 1447 1447 1567 1460 1460 1581 1448 1448 1568 1448 1448 1568 1460 1460 1581 1461 1461 1582 1448 1448 1568 1461 1461 1582 1449 1449 1569 1449 1449 1569 1461 1461 1582 1462 1462 1583 1449 1449 1569 1462 1462 1583 1450 1450 1570 1450 1450 1570 1462 1462 1583 1463 1463 1584 1450 1450 1570 1463 1463 1584 1451 1451 1571 1451 1451 1571 1463 1463 1584 1452 1452 1585 1451 1451 1571 1452 1452 1585 1440 1440 1572 1452 1452 1573 1464 1464 1586 1465 1465 1587 1452 1452 1573 1465 1465 1587 1453 1453 1574 1453 1453 1574 1465 1465 1587 1466 1466 1588 1453 1453 1574 1466 1466 1588 1454 1454 1575 1454 1454 1575 1466 1466 1588 1467 1467 1589 1454 1454 1575 1467 1467 1589 1455 1455 1576 1455 1455 1576 1467 1467 1589 1468 1468 1590 1455 1455 1576 1468 1468 1590 1456 1456 1577 1456 1456 1577 1468 1468 1590 1469 1469 1591 1456 1456 1577 1469 1469 1591 1457 1457 1578 1457 1457 1578 1469 1469 1591 1470 1470 1592 1457 1457 1578 1470 1470 1592 1458 1458 1579 1458 1458 1579 1470 1470 1592 1471 1471 1593 1458 1458 1579 1471 1471 1593 1459 1459 1580 1459 1459 1580 1471 1471 1593 1472 1472 1594 1459 1459 1580 1472 1472 1594 1460 1460 1581 1460 1460 1581 1472 1472 1594 1473 1473 1595 1460 1460 1581 1473 1473 1595 1461 1461 1582 1461 1461 1582 1473 1473 1595 1474 1474 1596 1461 1461 1582 1474 1474 1596 1462 1462 1583 1462 1462 1583 1474 1474 1596 1475 1475 1597 1462 1462 1583 1475 1475 1597 1463 1463 1584 1463 1463 1584 1475 1475 1597 1464 1464 1598 1463 1463 1584 1464 1464 1598 1452 1452 1585 1464 1464 1586 1476 1476 1599 1477 1477 1600 1464 1464 1586 1477 1477 1600 1465 1465 1587 1465 1465 1587 1477 1477 1600 1478 1478 1601 1465 1465 1587 1478 1478 1601 1466 1466 1588 1466 1466 1588 1478 1478 1601 1479 1479 1602 1466 1466 1588 1479 1479 1602 1467 1467 1589 1467 1467 1589 1479 1479 1602 1480 1480 1603 1467 1467 1589 1480 1480 1603 1468 1468 1590 1468 1468 1590 1480 1480 1603 1481 1481 1604 1468 1468 1590 1481 1481 1604 1469 1469 1591 1469 1469 1591 1481 1481 1604 1482 1482 1605 1469 1469 1591 1482 1482 1605 1470 1470 1592 1470 1470 1592 1482 1482 1605 1483 1483 1606 1470 1470 1592 1483 1483 1606 1471 1471 1593 1471 1471 1593 1483 1483 1606 1484 1484 1607 1471 1471 1593 1484 1484 1607 1472 1472 1594 1472 1472 1594 1484 1484 1607 1485 1485 1608 1472 1472 1594 1485 1485 1608 1473 1473 1595 1473 1473 1595 1485 1485 1608 1486 1486 1609 1473 1473 1595 1486 1486 1609 1474 1474 1596 1474 1474 1596 1486 1486 1609 1487 1487 1610 1474 1474 1596 1487 1487 1610 1475 1475 1597 1475 1475 1597 1487 1487 1610 1476 1476 1611 1475 1475 1597 1476 1476 1611 1464 1464 1598 1476 1476 1599 1488 1488 1612 1489 1489 1613 1476 1476 1599 1489 1489 1613 1477 1477 1600 1477 1477 1600 1489 1489 1613 1490 1490 1614 1477 1477 1600 1490 1490 1614 1478 1478 1601 1478 1478 1601 1490 1490 1614 1491 1491 1615 1478 1478 1601 1491 1491 1615 1479 1479 1602 1479 1479 1602 1491 1491 1615 1492 1492 1616 1479 1479 1602 1492 1492 1616 1480 1480 1603 1480 1480 1603 1492 1492 1616 1493 1493 1617 1480 1480 1603 1493 1493 1617 1481 1481 1604 1481 1481 1604 1493 1493 1617 1494 1494 1618 1481 1481 1604 1494 1494 1618 1482 1482 1605 1482 1482 1605 1494 1494 1618 1495 1495 1619 1482 1482 1605 1495 1495 1619 1483 1483 1606 1483 1483 1606 1495 1495 1619 1496 1496 1620 1483 1483 1606 1496 1496 1620 1484 1484 1607 1484 1484 1607 1496 1496 1620 1497 1497 1621 1484 1484 1607 1497 1497 1621 1485 1485 1608 1485 1485 1608 1497 1497 1621 1498 1498 1622 1485 1485 1608 1498 1498 1622 1486 1486 1609 1486 1486 1609 1498 1498 1622 1499 1499 1623 1486 1486 1609 1499 1499 1623 1487 1487 1610 1487 1487 1610 1499 1499 1623 1488 1488 1624 1487 1487 1610 1488 1488 1624 1476 1476 1611 1488 1488 1612 1500 1500 1625 1501 1501 1626 1488 1488 1612 1501 1501 1626 1489 1489 1613 1489 1489 1613 1501 1501 1626 1502 1502 1627 1489 1489 1613 1502 1502 1627 1490 1490 1614 1490 1490 1614 1502 1502 1627 1503 1503 1628 1490 1490 1614 1503 1503 1628 1491 1491 1615 1491 1491 1615 1503 1503 1628 1504 1504 1629 1491 1491 1615 1504 1504 1629 1492 1492 1616 1492 1492 1616 1504 1504 1629 1505 1505 1630 1492 1492 1616 1505 1505 1630 1493 1493 1617 1493 1493 1617 1505 1505 1630 1506 1506 1631 1493 1493 1617 1506 1506 1631 1494 1494 1618 1494 1494 1618 1506 1506 1631 1507 1507 1632 1494 1494 1618 1507 1507 1632 1495 1495 1619 1495 1495 1619 1507 1507 1632 1508 1508 1633 1495 1495 1619 1508 1508 1633 1496 1496 1620 1496 1496 1620 1508 1508 1633 1509 1509 1634 1496 1496 1620 1509 1509 1634 1497 1497 1621 1497 1497 1621 1509 1509 1634 1510 1510 1635 1497 1497 1621 1510 1510 1635 1498 1498 1622 1498 1498 1622 1510 1510 1635 1511 1511 1636 1498 1498 1622 1511 1511 1636 1499 1499 1623 1499 1499 1623 1511 1511 1636 1500 1500 1637 1499 1499 1623 1500 1500 1637 1488 1488 1624 1500 1500 1625 1512 1512 1638 1513 1513 1639 1500 1500 1625 1513 1513 1639 1501 1501 1626 1501 1501 1626 1513 1513 1639 1514 1514 1640 1501 1501 1626 1514 1514 1640 1502 1502 1627 1502 1502 1627 1514 1514 1640 1515 1515 1641 1502 1502 1627 1515 1515 1641 1503 1503 1628 1503 1503 1628 1515 1515 1641 1516 1516 1642 1503 1503 1628 1516 1516 1642 1504 1504 1629 1504 1504 1629 1516 1516 1642 1517 1517 1643 1504 1504 1629 1517 1517 1643 1505 1505 1630 1505 1505 1630 1517 1517 1643 1518 1518 1644 1505 1505 1630 1518 1518 1644 1506 1506 1631 1506 1506 1631 1518 1518 1644 1519 1519 1645 1506 1506 1631 1519 1519 1645 1507 1507 1632 1507 1507 1632 1519 1519 1645 1520 1520 1646 1507 1507 1632 1520 1520 1646 1508 1508 1633 1508 1508 1633 1520 1520 1646 1521 1521 1647 1508 1508 1633 1521 1521 1647 1509 1509 1634 1509 1509 1634 1521 1521 1647 1522 1522 1648 1509 1509 1634 1522 1522 1648 1510 1510 1635 1510 1510 1635 1522 1522 1648 1523 1523 1649 1510 1510 1635 1523 1523 1649 1511 1511 1636 1511 1511 1636 1523 1523 1649 1512 1512 1650 1511 1511 1636 1512 1512 1650 1500 1500 1637 1512 1512 1638 1524 1524 1651 1525 1525 1652 1512 1512 1638 1525 1525 1652 1513 1513 1639 1513 1513 1639 1525 1525 1652 1526 1526 1653 1513 1513 1639 1526 1526 1653 1514 1514 1640 1514 1514 1640 1526 1526 1653 1527 1527 1654 1514 1514 1640 1527 1527 1654 1515 1515 1641 1515 1515 1641 1527 1527 1654 1528 1528 1655 1515 1515 1641 1528 1528 1655 1516 1516 1642 1516 1516 1642 1528 1528 1655 1529 1529 1656 1516 1516 1642 1529 1529 1656 1517 1517 1643 1517 1517 1643 1529 1529 1656 1530 1530 1657 1517 1517 1643 1530 1530 1657 1518 1518 1644 1518 1518 1644 1530 1530 1657 1531 1531 1658 1518 1518 1644 1531 1531 1658 1519 1519 1645 1519 1519 1645 1531 1531 1658 1532 1532 1659 1519 1519 1645 1532 1532 1659 1520 1520 1646 1520 1520 1646 1532 1532 1659 1533 1533 1660 1520 1520 1646 1533 1533 1660 1521 1521 1647 1521 1521 1647 1533 1533 1660 1534 1534 1661 1521 1521 1647 1534 1534 1661 1522 1522 1648 1522 1522 1648 1534 1534 1661 1535 1535 1662 1522 1522 1648 1535 1535 1662 1523 1523 1649 1523 1523 1649 1535 1535 1662 1524 1524 1663 1523 1523 1649 1524 1524 1663 1512 1512 1650 1524 1524 1651 1536 1536 1664 1537 1537 1665 1524 1524 1651 1537 1537 1665 1525 1525 1652 1525 1525 1652 1537 1537 1665 1538 1538 1666 1525 1525 1652 1538 1538 1666 1526 1526 1653 1526 1526 1653 1538 1538 1666 1539 1539 1667 1526 1526 1653 1539 1539 1667 1527 1527 1654 1527 1527 1654 1539 1539 1667 1540 1540 1668 1527 1527 1654 1540 1540 1668 1528 1528 1655 1528 1528 1655 1540 1540 1668 1541 1541 1669 1528 1528 1655 1541 1541 1669 1529 1529 1656 1529 1529 1656 1541 1541 1669 1542 1542 1670 1529 1529 1656 1542 1542 1670 1530 1530 1657 1530 1530 1657 1542 1542 1670 1543 1543 1671 1530 1530 1657 1543 1543 1671 1531 1531 1658 1531 1531 1658 1543 1543 1671 1544 1544 1672 1531 1531 1658 1544 1544 1672 1532 1532 1659 1532 1532 1659 1544 1544 1672 1545 1545 1673 1532 1532 1659 1545 1545 1673 1533 1533 1660 1533 1533 1660 1545 1545 1673 1546 1546 1674 1533 1533 1660 1546 1546 1674 1534 1534 1661 1534 1534 1661 1546 1546 1674 1547 1547 1675 1534 1534 1661 1547 1547 1675 1535 1535 1662 1535 1535 1662 1547 1547 1675 1536 1536 1676 1535 1535 1662 1536 1536 1676 1524 1524 1663 1536 1536 1664 1548 1548 1677 1549 1549 1678 1536 1536 1664 1549 1549 1678 1537 1537 1665 1537 1537 1665 1549 1549 1678 1550 1550 1679 1537 1537 1665 1550 1550 1679 1538 1538 1666 1538 1538 1666 1550 1550 1679 1551 1551 1680 1538 1538 1666 1551 1551 1680 1539 1539 1667 1539 1539 1667 1551 1551 1680 1552 1552 1681 1539 1539 1667 1552 1552 1681 1540 1540 1668 1540 1540 1668 1552 1552 1681 1553 1553 1682 1540 1540 1668 1553 1553 1682 1541 1541 1669 1541 1541 1669 1553 1553 1682 1554 1554 1683 1541 1541 1669 1554 1554 1683 1542 1542 1670 1542 1542 1670 1554 1554 1683 1555 1555 1684 1542 1542 1670 1555 1555 1684 1543 1543 1671 1543 1543 1671 1555 1555 1684 1556 1556 1685 1543 1543 1671 1556 1556 1685 1544 1544 1672 1544 1544 1672 1556 1556 1685 1557 1557 1686 1544 1544 1672 1557 1557 1686 1545 1545 1673 1545 1545 1673 1557 1557 1686 1558 1558 1687 1545 1545 1673 1558 1558 1687 1546 1546 1674 1546 1546 1674 1558 1558 1687 1559 1559 1688 1546 1546 1674 1559 1559 1688 1547 1547 1675 1547 1547 1675 1559 1559 1688 1548 1548 1689 1547 1547 1675 1548 1548 1689 1536 1536 1676 1548 1548 1677 1560 1560 1690 1561 1561 1691 1548 1548 1677 1561 1561 1691 1549 1549 1678 1549 1549 1678 1561 1561 1691 1562 1562 1692 1549 1549 1678 1562 1562 1692 1550 1550 1679 1550 1550 1679 1562 1562 1692 1563 1563 1693 1550 1550 1679 1563 1563 1693 1551 1551 1680 1551 1551 1680 1563 1563 1693 1564 1564 1694 1551 1551 1680 1564 1564 1694 1552 1552 1681 1552 1552 1681 1564 1564 1694 1565 1565 1695 1552 1552 1681 1565 1565 1695 1553 1553 1682 1553 1553 1682 1565 1565 1695 1566 1566 1696 1553 1553 1682 1566 1566 1696 1554 1554 1683 1554 1554 1683 1566 1566 1696 1567 1567 1697 1554 1554 1683 1567 1567 1697 1555 1555 1684 1555 1555 1684 1567 1567 1697 1568 1568 1698 1555 1555 1684 1568 1568 1698 1556 1556 1685 1556 1556 1685 1568 1568 1698 1569 1569 1699 1556 1556 1685 1569 1569 1699 1557 1557 1686 1557 1557 1686 1569 1569 1699 1570 1570 1700 1557 1557 1686 1570 1570 1700 1558 1558 1687 1558 1558 1687 1570 1570 1700 1571 1571 1701 1558 1558 1687 1571 1571 1701 1559 1559 1688 1559 1559 1688 1571 1571 1701 1560 1560 1702 1559 1559 1688 1560 1560 1702 1548 1548 1689 1560 1560 1690 1572 1572 1703 1573 1573 1704 1560 1560 1690 1573 1573 1704 1561 1561 1691 1561 1561 1691 1573 1573 1704 1574 1574 1705 1561 1561 1691 1574 1574 1705 1562 1562 1692 1562 1562 1692 1574 1574 1705 1575 1575 1706 1562 1562 1692 1575 1575 1706 1563 1563 1693 1563 1563 1693 1575 1575 1706 1576 1576 1707 1563 1563 1693 1576 1576 1707 1564 1564 1694 1564 1564 1694 1576 1576 1707 1577 1577 1708 1564 1564 1694 1577 1577 1708 1565 1565 1695 1565 1565 1695 1577 1577 1708 1578 1578 1709 1565 1565 1695 1578 1578 1709 1566 1566 1696 1566 1566 1696 1578 1578 1709 1579 1579 1710 1566 1566 1696 1579 1579 1710 1567 1567 1697 1567 1567 1697 1579 1579 1710 1580 1580 1711 1567 1567 1697 1580 1580 1711 1568 1568 1698 1568 1568 1698 1580 1580 1711 1581 1581 1712 1568 1568 1698 1581 1581 1712 1569 1569 1699 1569 1569 1699 1581 1581 1712 1582 1582 1713 1569 1569 1699 1582 1582 1713 1570 1570 1700 1570 1570 1700 1582 1582 1713 1583 1583 1714 1570 1570 1700 1583 1583 1714 1571 1571 1701 1571 1571 1701 1583 1583 1714 1572 1572 1715 1571 1571 1701 1572 1572 1715 1560 1560 1702 1572 1572 1703 1584 1584 1716 1585 1585 1717 1572 1572 1703 1585 1585 1717 1573 1573 1704 1573 1573 1704 1585 1585 1717 1586 1586 1718 1573 1573 1704 1586 1586 1718 1574 1574 1705 1574 1574 1705 1586 1586 1718 1587 1587 1719 1574 1574 1705 1587 1587 1719 1575 1575 1706 1575 1575 1706 1587 1587 1719 1588 1588 1720 1575 1575 1706 1588 1588 1720 1576 1576 1707 1576 1576 1707 1588 1588 1720 1589 1589 1721 1576 1576 1707 1589 1589 1721 1577 1577 1708 1577 1577 1708 1589 1589 1721 1590 1590 1722 1577 1577 1708 1590 1590 1722 1578 1578 1709 1578 1578 1709 1590 1590 1722 1591 1591 1723 1578 1578 1709 1591 1591 1723 1579 1579 1710 1579 1579 1710 1591 1591 1723 1592 1592 1724 1579 1579 1710 1592 1592 1724 1580 1580 1711 1580 1580 1711 1592 1592 1724 1593 1593 1725 1580 1580 1711 1593 1593 1725 1581 1581 1712 1581 1581 1712 1593 1593 1725 1594 1594 1726 1581 1581 1712 1594 1594 1726 1582 1582 1713 1582 1582 1713 1594 1594 1726 1595 1595 1727 1582 1582 1713 1595 1595 1727 1583 1583 1714 1583 1583 1714 1595 1595 1727 1584 1584 1728 1583 1583 1714 1584 1584 1728 1572 1572 1715 1584 1584 1716 1596 1596 1729 1597 1597 1730 1584 1584 1716 1597 1597 1730 1585 1585 1717 1585 1585 1717 1597 1597 1730 1598 1598 1731 1585 1585 1717 1598 1598 1731 1586 1586 1718 1586 1586 1718 1598 1598 1731 1599 1599 1732 1586 1586 1718 1599 1599 1732 1587 1587 1719 1587 1587 1719 1599 1599 1732 1600 1600 1733 1587 1587 1719 1600 1600 1733 1588 1588 1720 1588 1588 1720 1600 1600 1733 1601 1601 1734 1588 1588 1720 1601 1601 1734 1589 1589 1721 1589 1589 1721 1601 1601 1734 1602 1602 1735 1589 1589 1721 1602 1602 1735 1590 1590 1722 1590 1590 1722 1602 1602 1735 1603 1603 1736 1590 1590 1722 1603 1603 1736 1591 1591 1723 1591 1591 1723 1603 1603 1736 1604 1604 1737 1591 1591 1723 1604 1604 1737 1592 1592 1724 1592 1592 1724 1604 1604 1737 1605 1605 1738 1592 1592 1724 1605 1605 1738 1593 1593 1725 1593 1593 1725 1605 1605 1738 1606 1606 1739 1593 1593 1725 1606 1606 1739 1594 1594 1726 1594 1594 1726 1606 1606 1739 1607 1607 1740 1594 1594 1726 1607 1607 1740 1595 1595 1727 1595 1595 1727 1607 1607 1740 1596 1596 1741 1595 1595 1727 1596 1596 1741 1584 1584 1728 1596 1596 1729 1608 1608 1742 1609 1609 1743 1596 1596 1729 1609 1609 1743 1597 1597 1730 1597 1597 1730 1609 1609 1743 1610 1610 1744 1597 1597 1730 1610 1610 1744 1598 1598 1731 1598 1598 1731 1610 1610 1744 1611 1611 1745 1598 1598 1731 1611 1611 1745 1599 1599 1732 1599 1599 1732 1611 1611 1745 1612 1612 1746 1599 1599 1732 1612 1612 1746 1600 1600 1733 1600 1600 1733 1612 1612 1746 1613 1613 1747 1600 1600 1733 1613 1613 1747 1601 1601 1734 1601 1601 1734 1613 1613 1747 1614 1614 1748 1601 1601 1734 1614 1614 1748 1602 1602 1735 1602 1602 1735 1614 1614 1748 1615 1615 1749 1602 1602 1735 1615 1615 1749 1603 1603 1736 1603 1603 1736 1615 1615 1749 1616 1616 1750 1603 1603 1736 1616 1616 1750 1604 1604 1737 1604 1604 1737 1616 1616 1750 1617 1617 1751 1604 1604 1737 1617 1617 1751 1605 1605 1738 1605 1605 1738 1617 1617 1751 1618 1618 1752 1605 1605 1738 1618 1618 1752 1606 1606 1739 1606 1606 1739 1618 1618 1752 1619 1619 1753 1606 1606 1739 1619 1619 1753 1607 1607 1740 1607 1607 1740 1619 1619 1753 1608 1608 1754 1607 1607 1740 1608 1608 1754 1596 1596 1741 1608 1608 1742 1620 1620 1755 1621 1621 1756 1608 1608 1742 1621 1621 1756 1609 1609 1743 1609 1609 1743 1621 1621 1756 1622 1622 1757 1609 1609 1743 1622 1622 1757 1610 1610 1744 1610 1610 1744 1622 1622 1757 1623 1623 1758 1610 1610 1744 1623 1623 1758 1611 1611 1745 1611 1611 1745 1623 1623 1758 1624 1624 1759 1611 1611 1745 1624 1624 1759 1612 1612 1746 1612 1612 1746 1624 1624 1759 1625 1625 1760 1612 1612 1746 1625 1625 1760 1613 1613 1747 1613 1613 1747 1625 1625 1760 1626 1626 1761 1613 1613 1747 1626 1626 1761 1614 1614 1748 1614 1614 1748 1626 1626 1761 1627 1627 1762 1614 1614 1748 1627 1627 1762 1615 1615 1749 1615 1615 1749 1627 1627 1762 1628 1628 1763 1615 1615 1749 1628 1628 1763 1616 1616 1750 1616 1616 1750 1628 1628 1763 1629 1629 1764 1616 1616 1750 1629 1629 1764 1617 1617 1751 1617 1617 1751 1629 1629 1764 1630 1630 1765 1617 1617 1751 1630 1630 1765 1618 1618 1752 1618 1618 1752 1630 1630 1765 1631 1631 1766 1618 1618 1752 1631 1631 1766 1619 1619 1753 1619 1619 1753 1631 1631 1766 1620 1620 1767 1619 1619 1753 1620 1620 1767 1608 1608 1754 1620 1620 1755 1632 1632 1768 1633 1633 1769 1620 1620 1755 1633 1633 1769 1621 1621 1756 1621 1621 1756 1633 1633 1769 1634 1634 1770 1621 1621 1756 1634 1634 1770 1622 1622 1757 1622 1622 1757 1634 1634 1770 1635 1635 1771 1622 1622 1757 1635 1635 1771 1623 1623 1758 1623 1623 1758 1635 1635 1771 1636 1636 1772 1623 1623 1758 1636 1636 1772 1624 1624 1759 1624 1624 1759 1636 1636 1772 1637 1637 1773 1624 1624 1759 1637 1637 1773 1625 1625 1760 1625 1625 1760 1637 1637 1773 1638 1638 1774 1625 1625 1760 1638 1638 1774 1626 1626 1761 1626 1626 1761 1638 1638 1774 1639 1639 1775 1626 1626 1761 1639 1639 1775 1627 1627 1762 1627 1627 1762 1639 1639 1775 1640 1640 1776 1627 1627 1762 1640 1640 1776 1628 1628 1763 1628 1628 1763 1640 1640 1776 1641 1641 1777 1628 1628 1763 1641 1641 1777 1629 1629 1764 1629 1629 1764 1641 1641 1777 1642 1642 1778 1629 1629 1764 1642 1642 1778 1630 1630 1765 1630 1630 1765 1642 1642 1778 1643 1643 1779 1630 1630 1765 1643 1643 1779 1631 1631 1766 1631 1631 1766 1643 1643 1779 1632 1632 1780 1631 1631 1766 1632 1632 1780 1620 1620 1767 1632 1632 1768 1644 1644 1781 1645 1645 1782 1632 1632 1768 1645 1645 1782 1633 1633 1769 1633 1633 1769 1645 1645 1782 1646 1646 1783 1633 1633 1769 1646 1646 1783 1634 1634 1770 1634 1634 1770 1646 1646 1783 1647 1647 1784 1634 1634 1770 1647 1647 1784 1635 1635 1771 1635 1635 1771 1647 1647 1784 1648 1648 1785 1635 1635 1771 1648 1648 1785 1636 1636 1772 1636 1636 1772 1648 1648 1785 1649 1649 1786 1636 1636 1772 1649 1649 1786 1637 1637 1773 1637 1637 1773 1649 1649 1786 1650 1650 1787 1637 1637 1773 1650 1650 1787 1638 1638 1774 1638 1638 1774 1650 1650 1787 1651 1651 1788 1638 1638 1774 1651 1651 1788 1639 1639 1775 1639 1639 1775 1651 1651 1788 1652 1652 1789 1639 1639 1775 1652 1652 1789 1640 1640 1776 1640 1640 1776 1652 1652 1789 1653 1653 1790 1640 1640 1776 1653 1653 1790 1641 1641 1777 1641 1641 1777 1653 1653 1790 1654 1654 1791 1641 1641 1777 1654 1654 1791 1642 1642 1778 1642 1642 1778 1654 1654 1791 1655 1655 1792 1642 1642 1778 1655 1655 1792 1643 1643 1779 1643 1643 1779 1655 1655 1792 1644 1644 1793 1643 1643 1779 1644 1644 1793 1632 1632 1780 1644 1644 1781 1656 1656 1794 1657 1657 1795 1644 1644 1781 1657 1657 1795 1645 1645 1782 1645 1645 1782 1657 1657 1795 1658 1658 1796 1645 1645 1782 1658 1658 1796 1646 1646 1783 1646 1646 1783 1658 1658 1796 1659 1659 1797 1646 1646 1783 1659 1659 1797 1647 1647 1784 1647 1647 1784 1659 1659 1797 1660 1660 1798 1647 1647 1784 1660 1660 1798 1648 1648 1785 1648 1648 1785 1660 1660 1798 1661 1661 1799 1648 1648 1785 1661 1661 1799 1649 1649 1786 1649 1649 1786 1661 1661 1799 1662 1662 1800 1649 1649 1786 1662 1662 1800 1650 1650 1787 1650 1650 1787 1662 1662 1800 1663 1663 1801 1650 1650 1787 1663 1663 1801 1651 1651 1788 1651 1651 1788 1663 1663 1801 1664 1664 1802 1651 1651 1788 1664 1664 1802 1652 1652 1789 1652 1652 1789 1664 1664 1802 1665 1665 1803 1652 1652 1789 1665 1665 1803 1653 1653 1790 1653 1653 1790 1665 1665 1803 1666 1666 1804 1653 1653 1790 1666 1666 1804 1654 1654 1791 1654 1654 1791 1666 1666 1804 1667 1667 1805 1654 1654 1791 1667 1667 1805 1655 1655 1792 1655 1655 1792 1667 1667 1805 1656 1656 1806 1655 1655 1792 1656 1656 1806 1644 1644 1793 1656 1656 1794 1668 1668 1807 1669 1669 1808 1656 1656 1794 1669 1669 1808 1657 1657 1795 1657 1657 1795 1669 1669 1808 1670 1670 1809 1657 1657 1795 1670 1670 1809 1658 1658 1796 1658 1658 1796 1670 1670 1809 1671 1671 1810 1658 1658 1796 1671 1671 1810 1659 1659 1797 1659 1659 1797 1671 1671 1810 1672 1672 1811 1659 1659 1797 1672 1672 1811 1660 1660 1798 1660 1660 1798 1672 1672 1811 1673 1673 1812 1660 1660 1798 1673 1673 1812 1661 1661 1799 1661 1661 1799 1673 1673 1812 1674 1674 1813 1661 1661 1799 1674 1674 1813 1662 1662 1800 1662 1662 1800 1674 1674 1813 1675 1675 1814 1662 1662 1800 1675 1675 1814 1663 1663 1801 1663 1663 1801 1675 1675 1814 1676 1676 1815 1663 1663 1801 1676 1676 1815 1664 1664 1802 1664 1664 1802 1676 1676 1815 1677 1677 1816 1664 1664 1802 1677 1677 1816 1665 1665 1803 1665 1665 1803 1677 1677 1816 1678 1678 1817 1665 1665 1803 1678 1678 1817 1666 1666 1804 1666 1666 1804 1678 1678 1817 1679 1679 1818 1666 1666 1804 1679 1679 1818 1667 1667 1805 1667 1667 1805 1679 1679 1818 1668 1668 1819 1667 1667 1805 1668 1668 1819 1656 1656 1806 1668 1668 1807 1680 1680 1820 1681 1681 1821 1668 1668 1807 1681 1681 1821 1669 1669 1808 1669 1669 1808 1681 1681 1821 1682 1682 1822 1669 1669 1808 1682 1682 1822 1670 1670 1809 1670 1670 1809 1682 1682 1822 1683 1683 1823 1670 1670 1809 1683 1683 1823 1671 1671 1810 1671 1671 1810 1683 1683 1823 1684 1684 1824 1671 1671 1810 1684 1684 1824 1672 1672 1811 1672 1672 1811 1684 1684 1824 1685 1685 1825 1672 1672 1811 1685 1685 1825 1673 1673 1812 1673 1673 1812 1685 1685 1825 1686 1686 1826 1673 1673 1812 1686 1686 1826 1674 1674 1813 1674 1674 1813 1686 1686 1826 1687 1687 1827 1674 1674 1813 1687 1687 1827 1675 1675 1814 1675 1675 1814 1687 1687 1827 1688 1688 1828 1675 1675 1814 1688 1688 1828 1676 1676 1815 1676 1676 1815 1688 1688 1828 1689 1689 1829 1676 1676 1815 1689 1689 1829 1677 1677 1816 1677 1677 1816 1689 1689 1829 1690 1690 1830 1677 1677 1816 1690 1690 1830 1678 1678 1817 1678 1678 1817 1690 1690 1830 1691 1691 1831 1678 1678 1817 1691 1691 1831 1679 1679 1818 1679 1679 1818 1691 1691 1831 1680 1680 1832 1679 1679 1818 1680 1680 1832 1668 1668 1819 1680 1680 1820 1692 1692 1833 1693 1693 1834 1680 1680 1820 1693 1693 1834 1681 1681 1821 1681 1681 1821 1693 1693 1834 1694 1694 1835 1681 1681 1821 1694 1694 1835 1682 1682 1822 1682 1682 1822 1694 1694 1835 1695 1695 1836 1682 1682 1822 1695 1695 1836 1683 1683 1823 1683 1683 1823 1695 1695 1836 1696 1696 1837 1683 1683 1823 1696 1696 1837 1684 1684 1824 1684 1684 1824 1696 1696 1837 1697 1697 1838 1684 1684 1824 1697 1697 1838 1685 1685 1825 1685 1685 1825 1697 1697 1838 1698 1698 1839 1685 1685 1825 1698 1698 1839 1686 1686 1826 1686 1686 1826 1698 1698 1839 1699 1699 1840 1686 1686 1826 1699 1699 1840 1687 1687 1827 1687 1687 1827 1699 1699 1840 1700 1700 1841 1687 1687 1827 1700 1700 1841 1688 1688 1828 1688 1688 1828 1700 1700 1841 1701 1701 1842 1688 1688 1828 1701 1701 1842 1689 1689 1829 1689 1689 1829 1701 1701 1842 1702 1702 1843 1689 1689 1829 1702 1702 1843 1690 1690 1830 1690 1690 1830 1702 1702 1843 1703 1703 1844 1690 1690 1830 1703 1703 1844 1691 1691 1831 1691 1691 1831 1703 1703 1844 1692 1692 1845 1691 1691 1831 1692 1692 1845 1680 1680 1832 1692 1692 1833 1704 1704 1846 1705 1705 1847 1692 1692 1833 1705 1705 1847 1693 1693 1834 1693 1693 1834 1705 1705 1847 1706 1706 1848 1693 1693 1834 1706 1706 1848 1694 1694 1835 1694 1694 1835 1706 1706 1848 1707 1707 1849 1694 1694 1835 1707 1707 1849 1695 1695 1836 1695 1695 1836 1707 1707 1849 1708 1708 1850 1695 1695 1836 1708 1708 1850 1696 1696 1837 1696 1696 1837 1708 1708 1850 1709 1709 1851 1696 1696 1837 1709 1709 1851 1697 1697 1838 1697 1697 1838 1709 1709 1851 1710 1710 1852 1697 1697 1838 1710 1710 1852 1698 1698 1839 1698 1698 1839 1710 1710 1852 1711 1711 1853 1698 1698 1839 1711 1711 1853 1699 1699 1840 1699 1699 1840 1711 1711 1853 1712 1712 1854 1699 1699 1840 1712 1712 1854 1700 1700 1841 1700 1700 1841 1712 1712 1854 1713 1713 1855 1700 1700 1841 1713 1713 1855 1701 1701 1842 1701 1701 1842 1713 1713 1855 1714 1714 1856 1701 1701 1842 1714 1714 1856 1702 1702 1843 1702 1702 1843 1714 1714 1856 1715 1715 1857 1702 1702 1843 1715 1715 1857 1703 1703 1844 1703 1703 1844 1715 1715 1857 1704 1704 1858 1703 1703 1844 1704 1704 1858 1692 1692 1845 1704 1704 1846 1716 1716 1859 1717 1717 1860 1704 1704 1846 1717 1717 1860 1705 1705 1847 1705 1705 1847 1717 1717 1860 1718 1718 1861 1705 1705 1847 1718 1718 1861 1706 1706 1848 1706 1706 1848 1718 1718 1861 1719 1719 1862 1706 1706 1848 1719 1719 1862 1707 1707 1849 1707 1707 1849 1719 1719 1862 1720 1720 1863 1707 1707 1849 1720 1720 1863 1708 1708 1850 1708 1708 1850 1720 1720 1863 1721 1721 1864 1708 1708 1850 1721 1721 1864 1709 1709 1851 1709 1709 1851 1721 1721 1864 1722 1722 1865 1709 1709 1851 1722 1722 1865 1710 1710 1852 1710 1710 1852 1722 1722 1865 1723 1723 1866 1710 1710 1852 1723 1723 1866 1711 1711 1853 1711 1711 1853 1723 1723 1866 1724 1724 1867 1711 1711 1853 1724 1724 1867 1712 1712 1854 1712 1712 1854 1724 1724 1867 1725 1725 1868 1712 1712 1854 1725 1725 1868 1713 1713 1855 1713 1713 1855 1725 1725 1868 1726 1726 1869 1713 1713 1855 1726 1726 1869 1714 1714 1856 1714 1714 1856 1726 1726 1869 1727 1727 1870 1714 1714 1856 1727 1727 1870 1715 1715 1857 1715 1715 1857 1727 1727 1870 1716 1716 1871 1715 1715 1857 1716 1716 1871 1704 1704 1858 1716 1716 1859 1728 1728 1872 1729 1729 1873 1716 1716 1859 1729 1729 1873 1717 1717 1860 1717 1717 1860 1729 1729 1873 1730 1730 1874 1717 1717 1860 1730 1730 1874 1718 1718 1861 1718 1718 1861 1730 1730 1874 1731 1731 1875 1718 1718 1861 1731 1731 1875 1719 1719 1862 1719 1719 1862 1731 1731 1875 1732 1732 1876 1719 1719 1862 1732 1732 1876 1720 1720 1863 1720 1720 1863 1732 1732 1876 1733 1733 1877 1720 1720 1863 1733 1733 1877 1721 1721 1864 1721 1721 1864 1733 1733 1877 1734 1734 1878 1721 1721 1864 1734 1734 1878 1722 1722 1865 1722 1722 1865 1734 1734 1878 1735 1735 1879 1722 1722 1865 1735 1735 1879 1723 1723 1866 1723 1723 1866 1735 1735 1879 1736 1736 1880 1723 1723 1866 1736 1736 1880 1724 1724 1867 1724 1724 1867 1736 1736 1880 1737 1737 1881 1724 1724 1867 1737 1737 1881 1725 1725 1868 1725 1725 1868 1737 1737 1881 1738 1738 1882 1725 1725 1868 1738 1738 1882 1726 1726 1869 1726 1726 1869 1738 1738 1882 1739 1739 1883 1726 1726 1869 1739 1739 1883 1727 1727 1870 1727 1727 1870 1739 1739 1883 1728 1728 1884 1727 1727 1870 1728 1728 1884 1716 1716 1871 1728 1728 1872 1740 1740 1885 1741 1741 1886 1728 1728 1872 1741 1741 1886 1729 1729 1873 1729 1729 1873 1741 1741 1886 1742 1742 1887 1729 1729 1873 1742 1742 1887 1730 1730 1874 1730 1730 1874 1742 1742 1887 1743 1743 1888 1730 1730 1874 1743 1743 1888 1731 1731 1875 1731 1731 1875 1743 1743 1888 1744 1744 1889 1731 1731 1875 1744 1744 1889 1732 1732 1876 1732 1732 1876 1744 1744 1889 1745 1745 1890 1732 1732 1876 1745 1745 1890 1733 1733 1877 1733 1733 1877 1745 1745 1890 1746 1746 1891 1733 1733 1877 1746 1746 1891 1734 1734 1878 1734 1734 1878 1746 1746 1891 1747 1747 1892 1734 1734 1878 1747 1747 1892 1735 1735 1879 1735 1735 1879 1747 1747 1892 1748 1748 1893 1735 1735 1879 1748 1748 1893 1736 1736 1880 1736 1736 1880 1748 1748 1893 1749 1749 1894 1736 1736 1880 1749 1749 1894 1737 1737 1881 1737 1737 1881 1749 1749 1894 1750 1750 1895 1737 1737 1881 1750 1750 1895 1738 1738 1882 1738 1738 1882 1750 1750 1895 1751 1751 1896 1738 1738 1882 1751 1751 1896 1739 1739 1883 1739 1739 1883 1751 1751 1896 1740 1740 1897 1739 1739 1883 1740 1740 1897 1728 1728 1884 1740 1740 1885 1752 1752 1898 1753 1753 1899 1740 1740 1885 1753 1753 1899 1741 1741 1886 1741 1741 1886 1753 1753 1899 1754 1754 1900 1741 1741 1886 1754 1754 1900 1742 1742 1887 1742 1742 1887 1754 1754 1900 1755 1755 1901 1742 1742 1887 1755 1755 1901 1743 1743 1888 1743 1743 1888 1755 1755 1901 1756 1756 1902 1743 1743 1888 1756 1756 1902 1744 1744 1889 1744 1744 1889 1756 1756 1902 1757 1757 1903 1744 1744 1889 1757 1757 1903 1745 1745 1890 1745 1745 1890 1757 1757 1903 1758 1758 1904 1745 1745 1890 1758 1758 1904 1746 1746 1891 1746 1746 1891 1758 1758 1904 1759 1759 1905 1746 1746 1891 1759 1759 1905 1747 1747 1892 1747 1747 1892 1759 1759 1905 1760 1760 1906 1747 1747 1892 1760 1760 1906 1748 1748 1893 1748 1748 1893 1760 1760 1906 1761 1761 1907 1748 1748 1893 1761 1761 1907 1749 1749 1894 1749 1749 1894 1761 1761 1907 1762 1762 1908 1749 1749 1894 1762 1762 1908 1750 1750 1895 1750 1750 1895 1762 1762 1908 1763 1763 1909 1750 1750 1895 1763 1763 1909 1751 1751 1896 1751 1751 1896 1763 1763 1909 1752 1752 1910 1751 1751 1896 1752 1752 1910 1740 1740 1897 1752 1752 1898 1764 1764 1911 1765 1765 1912 1752 1752 1898 1765 1765 1912 1753 1753 1899 1753 1753 1899 1765 1765 1912 1766 1766 1913 1753 1753 1899 1766 1766 1913 1754 1754 1900 1754 1754 1900 1766 1766 1913 1767 1767 1914 1754 1754 1900 1767 1767 1914 1755 1755 1901 1755 1755 1901 1767 1767 1914 1768 1768 1915 1755 1755 1901 1768 1768 1915 1756 1756 1902 1756 1756 1902 1768 1768 1915 1769 1769 1916 1756 1756 1902 1769 1769 1916 1757 1757 1903 1757 1757 1903 1769 1769 1916 1770 1770 1917 1757 1757 1903 1770 1770 1917 1758 1758 1904 1758 1758 1904 1770 1770 1917 1771 1771 1918 1758 1758 1904 1771 1771 1918 1759 1759 1905 1759 1759 1905 1771 1771 1918 1772 1772 1919 1759 1759 1905 1772 1772 1919 1760 1760 1906 1760 1760 1906 1772 1772 1919 1773 1773 1920 1760 1760 1906 1773 1773 1920 1761 1761 1907 1761 1761 1907 1773 1773 1920 1774 1774 1921 1761 1761 1907 1774 1774 1921 1762 1762 1908 1762 1762 1908 1774 1774 1921 1775 1775 1922 1762 1762 1908 1775 1775 1922 1763 1763 1909 1763 1763 1909 1775 1775 1922 1764 1764 1923 1763 1763 1909 1764 1764 1923 1752 1752 1910 1764 1764 1911 1776 1776 1924 1777 1777 1925 1764 1764 1911 1777 1777 1925 1765 1765 1912 1765 1765 1912 1777 1777 1925 1778 1778 1926 1765 1765 1912 1778 1778 1926 1766 1766 1913 1766 1766 1913 1778 1778 1926 1779 1779 1927 1766 1766 1913 1779 1779 1927 1767 1767 1914 1767 1767 1914 1779 1779 1927 1780 1780 1928 1767 1767 1914 1780 1780 1928 1768 1768 1915 1768 1768 1915 1780 1780 1928 1781 1781 1929 1768 1768 1915 1781 1781 1929 1769 1769 1916 1769 1769 1916 1781 1781 1929 1782 1782 1930 1769 1769 1916 1782 1782 1930 1770 1770 1917 1770 1770 1917 1782 1782 1930 1783 1783 1931 1770 1770 1917 1783 1783 1931 1771 1771 1918 1771 1771 1918 1783 1783 1931 1784 1784 1932 1771 1771 1918 1784 1784 1932 1772 1772 1919 1772 1772 1919 1784 1784 1932 1785 1785 1933 1772 1772 1919 1785 1785 1933 1773 1773 1920 1773 1773 1920 1785 1785 1933 1786 1786 1934 1773 1773 1920 1786 1786 1934 1774 1774 1921 1774 1774 1921 1786 1786 1934 1787 1787 1935 1774 1774 1921 1787 1787 1935 1775 1775 1922 1775 1775 1922 1787 1787 1935 1776 1776 1936 1775 1775 1922 1776 1776 1936 1764 1764 1923 1776 1776 1924 1788 1788 1937 1789 1789 1938 1776 1776 1924 1789 1789 1938 1777 1777 1925 1777 1777 1925 1789 1789 1938 1790 1790 1939 1777 1777 1925 1790 1790 1939 1778 1778 1926 1778 1778 1926 1790 1790 1939 1791 1791 1940 1778 1778 1926 1791 1791 1940 1779 1779 1927 1779 1779 1927 1791 1791 1940 1792 1792 1941 1779 1779 1927 1792 1792 1941 1780 1780 1928 1780 1780 1928 1792 1792 1941 1793 1793 1942 1780 1780 1928 1793 1793 1942 1781 1781 1929 1781 1781 1929 1793 1793 1942 1794 1794 1943 1781 1781 1929 1794 1794 1943 1782 1782 1930 1782 1782 1930 1794 1794 1943 1795 1795 1944 1782 1782 1930 1795 1795 1944 1783 1783 1931 1783 1783 1931 1795 1795 1944 1796 1796 1945 1783 1783 1931 1796 1796 1945 1784 1784 1932 1784 1784 1932 1796 1796 1945 1797 1797 1946 1784 1784 1932 1797 1797 1946 1785 1785 1933 1785 1785 1933 1797 1797 1946 1798 1798 1947 1785 1785 1933 1798 1798 1947 1786 1786 1934 1786 1786 1934 1798 1798 1947 1799 1799 1948 1786 1786 1934 1799 1799 1948 1787 1787 1935 1787 1787 1935 1799 1799 1948 1788 1788 1949 1787 1787 1935 1788 1788 1949 1776 1776 1936 1788 1788 1937 0 0 1950 1 3 1951 1788 1788 1937 1 3 1951 1789 1789 1938 1789 1789 1938 1 3 1951 2 5 1952 1789 1789 1938 2 5 1952 1790 1790 1939 1790 1790 1939 2 5 1952 3 7 1953 1790 1790 1939 3 7 1953 1791 1791 1940 1791 1791 1940 3 7 1953 4 9 1954 1791 1791 1940 4 9 1954 1792 1792 1941 1792 1792 1941 4 9 1954 5 11 1955 1792 1792 1941 5 11 1955 1793 1793 1942 1793 1793 1942 5 11 1955 6 13 1956 1793 1793 1942 6 13 1956 1794 1794 1943 1794 1794 1943 6 13 1956 7 15 1957 1794 1794 1943 7 15 1957 1795 1795 1944 1795 1795 1944 7 15 1957 8 17 1958 1795 1795 1944 8 17 1958 1796 1796 1945 1796 1796 1945 8 17 1958 9 19 1959 1796 1796 1945 9 19 1959 1797 1797 1946 1797 1797 1946 9 19 1959 10 21 1960 1797 1797 1946 10 21 1960 1798 1798 1947 1798 1798 1947 10 21 1960 11 23 1961 1798 1798 1947 11 23 1961 1799 1799 1948 1799 1799 1948 11 23 1961 0 0 1962 1799 1799 1948 0 0 1962 1788 1788 1949</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-5_max" name="Torus_Knot-5_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-5_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-6.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-6.DAE
new file mode 100644
index 00000000..872afd78
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-6.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-6.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:29:48Z</created>
+ <modified>2008-10-31T16:29:50Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="5400">23.434380 -0.000519 22.020164 23.594213 -0.347234 22.369724 23.521751 -0.600908 22.815086 23.236410 -0.693569 23.236919 22.814646 -0.600389 23.522194 22.369469 -0.346335 23.594467 22.020166 0.000519 23.434380 21.860331 0.347234 23.084822 21.932793 0.600908 22.639458 22.218134 0.693569 22.217625 22.639898 0.600389 21.932350 23.085075 0.346336 21.860077 24.603891 2.101239 23.029009 24.889914 1.767194 23.359591 24.941700 1.499992 23.837711 24.745375 1.371230 24.335262 24.353542 1.415410 24.718922 23.871195 1.620693 24.885891 23.427576 1.932075 24.791430 23.141554 2.266120 24.460848 23.089766 2.533323 23.982727 23.286093 2.662085 23.485176 23.677925 2.617905 23.101517 24.160273 2.412621 22.934546 25.701838 4.412501 23.658733 26.159697 4.081263 23.971094 26.377813 3.801468 24.510597 26.297747 3.648087 25.132677 25.940950 3.662218 25.670652 25.403027 3.840074 25.980373 24.828112 4.134000 25.978848 24.370255 4.465238 25.666487 24.152136 4.745033 25.126987 24.232203 4.898414 24.504904 24.588999 4.884284 23.966928 25.126923 4.706427 23.657207 26.600193 6.922452 23.850243 27.285069 6.600083 24.103609 27.742685 6.328027 24.698374 27.850426 6.179178 25.475168 27.579420 6.193423 26.225849 27.002283 6.366943 26.749277 26.273659 6.653245 26.905197 25.588783 6.975613 26.651829 25.131166 7.247670 26.057066 25.023426 7.396519 25.280275 25.294432 7.382274 24.529591 25.871569 7.208754 24.006163 27.168947 9.586581 23.597143 28.113493 9.281087 23.701454 28.888514 9.052963 24.287693 29.286345 8.963334 25.198776 29.200384 9.036216 26.190580 28.653669 9.252080 26.997351 27.792688 9.553086 27.402914 26.848143 9.858580 27.298603 26.073122 10.086704 26.712364 25.675291 10.176333 25.801281 25.761251 10.103452 24.809479 26.307966 9.887588 24.002708 27.319044 12.364937 22.948851 28.500793 12.055901 22.780788 29.637316 11.896465 23.231541 30.424080 11.929353 24.180330 30.650274 12.145749 25.372927 30.255289 12.487673 26.489779 29.344961 12.863504 27.231623 28.163212 13.172541 27.399685 27.026691 13.331976 26.948933 26.239925 13.299089 26.000145 26.013731 13.082693 24.807547 26.408714 12.740769 23.690697 27.030428 15.270228 21.970167 28.356846 14.881901 21.419088 29.832117 14.764955 21.573275 31.060942 14.950727 22.391413 31.714058 15.389438 23.654284 31.616465 15.963535 25.023502 30.794312 16.519192 26.132189 29.467892 16.907518 26.683268 27.992622 17.024464 26.529081 26.763798 16.838694 25.710943 26.110680 16.399982 24.448072 26.208273 15.825885 23.078854 26.341774 18.375845 20.672722 27.663807 17.780689 19.698196 29.379662 17.607721 19.419630 31.029579 17.903280 19.911663 32.171463 18.588177 21.042458 32.499348 19.478893 22.509018 31.925377 20.336760 23.918381 30.603346 20.931913 24.892906 28.887489 21.104883 25.171473 27.237574 20.809324 24.679440 26.095688 20.124430 23.548647 25.767803 19.233715 22.082087 25.312586 21.764696 18.972094 26.459118 20.822639 17.640598 28.260820 20.439678 16.877638 30.234924 20.718430 16.887650 31.852474 21.584204 17.667948 32.680046 22.805014 19.009455 32.495895 24.053745 20.552713 31.349361 24.995804 21.884209 29.547661 25.378765 22.647169 27.573557 25.100012 22.637159 25.956007 24.234241 21.856861 25.128433 23.013432 20.515354 23.989086 25.449511 16.710165 24.805256 24.062490 15.191405 26.515434 23.309000 14.006443 28.661381 23.390938 13.472790 30.668093 24.286352 13.733436 31.997873 25.755312 14.718542 32.294407 27.404215 16.164148 31.478239 28.791235 17.682907 29.768061 29.544725 18.867868 27.622114 29.462788 19.401524 25.615402 28.567375 19.140879 24.285622 27.098417 18.155773 22.393229 29.323101 13.724038 22.770573 27.476330 12.253870 24.224350 26.239040 10.815122 26.365017 25.942760 9.793304 28.618986 26.666880 9.462214 30.382307 28.217371 9.910566 31.182501 30.178783 11.018224 30.805157 32.025555 12.488392 29.351381 33.262848 13.927139 27.210714 33.559124 14.948956 24.956745 32.835007 15.280047 23.193422 31.284515 14.831697 20.528877 33.159149 9.919203 20.422934 30.936834 8.745414 21.496571 29.188562 7.289894 23.462109 28.382782 5.942650 25.792883 28.735397 5.064674 27.864365 30.151932 4.891220 29.121502 32.252823 5.468763 29.227446 34.475136 6.642552 28.153809 36.223408 8.098070 26.188272 37.029190 9.445315 23.857498 36.676575 10.323291 21.786016 35.260044 10.496746 18.395977 36.650570 5.322793 17.830835 34.224552 4.650784 18.460379 32.039158 3.432476 20.115923 30.679964 1.994315 22.353865 30.511164 0.721654 24.574547 31.577988 -0.044498 26.182945 33.594578 -0.098852 26.748087 36.020596 0.573157 26.118544 38.205986 1.791464 24.463001 39.565182 3.229625 22.225061 39.733982 4.502286 20.004377 38.667164 5.268439 16.001612 39.472675 0.097761 15.062037 37.070335 0.047688 15.250602 34.612850 -0.715039 16.516779 32.758701 -1.986048 18.521297 32.004704 -3.424774 20.727049 32.552895 -4.645710 22.543005 34.256382 -5.321709 23.482580 36.658722 -5.271637 23.294016 39.116203 -4.508911 22.027840 40.970356 -3.237902 20.023321 41.724350 -1.799176 17.817570 41.176163 -0.578239 13.369374 41.346668 -5.471104 12.181427 39.207012 -4.889432 11.992982 36.704342 -5.059240 12.854533 34.509251 -5.935026 14.535227 33.209915 -7.282124 16.584723 33.154480 -8.739579 18.453861 34.357807 -9.916869 19.641809 36.497463 -10.498540 19.830254 39.000130 -10.328733 18.968704 41.195217 -9.452949 17.288012 42.494560 -8.105851 15.238516 42.549995 -6.648396 10.540985 42.094097 -11.022372 9.245590 40.420536 -9.910842 8.787684 38.118340 -9.458543 9.289961 35.804382 -9.786670 10.617838 34.098690 -10.807300 12.415510 33.458290 -12.246956 14.201293 34.054783 -13.719885 15.496688 35.728340 -14.831416 15.954596 38.030533 -15.283715 15.452319 40.344490 -14.955589 14.124443 42.050190 -13.934960 12.326772 42.690590 -12.495303 7.580763 41.668774 -16.169195 6.304124 40.588234 -14.720330 5.700396 38.702946 -13.731487 5.931348 36.518082 -13.467627 6.935096 34.619072 -13.999449 8.442688 33.514751 -15.184453 10.050164 33.501026 -16.705118 11.326803 34.581566 -18.153982 11.930532 36.466850 -19.142826 11.699580 38.651711 -19.406687 10.695833 40.550724 -18.874865 9.188242 41.655048 -17.689861 4.576953 40.166603 -20.558134 3.406282 39.702843 -19.012383 2.766572 38.377243 -17.667595 2.829231 36.544998 -16.884109 3.577471 34.697056 -16.871857 4.810801 33.328575 -17.634121 6.198751 32.806236 -18.966656 7.369421 33.269997 -20.512407 8.009132 34.595596 -21.857197 7.946474 36.427841 -22.640682 7.198235 38.275776 -22.652937 5.964905 39.644260 -21.890671 1.642582 37.812687 -23.922993 0.614804 37.881973 -22.512121 0.010779 37.154533 -21.043222 -0.007646 35.825291 -19.909882 0.564466 34.250420 -19.415777 1.573818 32.851894 -19.693308 2.749956 32.004459 -20.668106 3.777734 31.935175 -22.078976 4.381759 32.662613 -23.547876 4.400185 33.991852 -24.681217 3.828073 35.566727 -25.175320 2.818721 36.965248 -24.897793 -1.097338 34.923878 -26.135057 -1.988417 35.358803 -25.025688 -2.531841 35.157986 -23.655199 -2.582001 34.375248 -22.390812 -2.125456 33.220314 -21.571318 -1.284538 32.002651 -21.416298 -0.284569 31.048532 -21.967291 0.606509 30.613611 -23.076660 1.149933 30.814425 -24.447147 1.200094 31.597164 -25.711536 0.743549 32.752098 -26.531031 -0.097369 33.969761 -26.686050 -3.537713 31.840887 -27.232920 -4.317864 32.441574 -26.490749 -4.809674 32.614025 -25.373310 -4.881361 32.312019 -24.180023 -4.513718 31.616488 -23.230625 -3.805254 30.713795 -22.779509 -2.945802 29.845816 -22.947550 -2.165650 29.245127 -23.689720 -1.673841 29.072680 -24.807156 -1.602153 29.374683 -26.000446 -1.969796 30.070215 -26.949844 -2.678259 30.972906 -27.400961 -5.627059 28.842281 -27.403032 -6.318235 29.437201 -26.997166 -6.777486 29.803507 -26.190144 -6.881757 29.843052 -25.198208 -6.603108 29.545240 -24.287144 -6.016204 28.989868 -23.701069 -5.278305 28.325748 -23.597025 -4.587130 27.730829 -24.002892 -4.127879 27.364523 -24.809912 -4.023607 27.324978 -25.801849 -4.302255 27.622787 -26.712914 -4.889159 28.178160 -27.298986 -7.377626 26.078005 -26.904821 -7.990077 26.565477 -26.748459 -8.428341 26.978863 -26.224810 -8.574986 27.207396 -25.474180 -8.390718 27.189840 -24.697708 -7.924914 26.930904 -24.103443 -7.302383 26.499964 -23.850622 -6.689934 26.012493 -24.006985 -6.251669 25.599106 -24.530634 -6.105024 25.370573 -25.281261 -6.289291 25.388128 -26.057734 -6.755095 25.647064 -26.651999 -8.835648 23.567396 -25.978462 -9.377936 23.917889 -25.979445 -9.800666 24.294870 -25.669432 -9.990566 24.597328 -25.131493 -9.896754 24.744223 -24.509766 -9.544366 24.696188 -23.970842 -9.027824 24.466101 -23.659128 -8.485536 24.115608 -23.658144 -8.062806 23.738626 -23.968157 -7.872905 23.436169 -24.506094 -7.966717 23.289276 -25.127821 -8.319105 23.337309 -25.666744 -10.041802 21.254076 -24.791218 -10.533564 21.482204 -24.885067 -10.952394 21.797245 -24.717709 -11.186070 22.114786 -24.333986 -11.171977 22.349743 -23.836716 -10.913891 22.439156 -23.359142 -10.480966 22.359068 -23.029228 -9.989204 22.130939 -22.935379 -9.570374 21.815899 -23.102737 -9.336698 21.498358 -23.486460 -9.350791 21.263403 -23.983728 -9.608877 21.173988 -24.461304 -11.010606 19.069729 -23.434387 -11.485937 19.198528 -23.593826 -11.928496 19.456978 -23.521074 -12.219701 19.775833 -23.235628 -12.281522 20.069654 -22.813967 -12.097395 20.259712 -22.369080 -11.716657 20.295082 -22.020172 -11.241325 20.166286 -21.860735 -10.798766 19.907833 -21.933485 -10.507562 19.588978 -22.218931 -10.445741 19.295156 -22.640593 -10.629867 19.105099 -23.085480 -11.734884 16.973478 -21.944992 -12.233791 17.008453 -22.174229 -12.742841 17.217100 -22.177988 -13.125634 17.543510 -21.955267 -13.279603 17.900225 -21.565744 -13.163490 18.191660 -21.113791 -12.808409 18.339727 -20.720509 -12.309503 18.304752 -20.491272 -11.800452 18.096106 -20.487511 -11.417659 17.769695 -20.710232 -11.263690 17.412983 -21.099756 -11.379803 17.121546 -21.551708 -12.202222 14.964531 -20.328535 -12.755113 14.882349 -20.651768 -13.377803 15.028149 -20.740765 -13.903443 15.362862 -20.571680 -14.191189 15.796803 -20.189817 -14.163939 16.213697 -19.697498 -13.828996 16.501839 -19.226641 -13.276106 16.584021 -18.903408 -12.653416 16.438221 -18.814411 -12.127775 16.103508 -18.983496 -11.840029 15.669567 -19.365358 -11.867278 15.252672 -19.857676 -12.412560 13.078914 -18.575190 -13.023240 12.829369 -19.024597 -13.794374 12.869489 -19.226866 -14.519339 13.188522 -19.127798 -15.003879 13.700985 -18.753935 -15.118163 14.269563 -18.205458 -14.831569 14.741906 -17.629328 -14.220889 14.991450 -17.179920 -13.449756 14.951331 -16.977650 -12.724792 14.632298 -17.076719 -12.240251 14.119835 -17.450581 -12.125966 13.551258 -17.999058 -12.394026 11.376407 -16.671080 -13.026229 10.895218 -17.275354 -13.949847 10.759015 -17.628553 -14.917397 11.004294 -17.636038 -15.669625 11.565332 -17.295801 -16.004972 12.291800 -16.699011 -15.833582 12.989039 -16.005575 -15.201379 13.470228 -15.401300 -14.277761 13.606431 -15.048102 -13.310211 13.361152 -15.040617 -12.557982 12.800114 -15.380853 -12.222635 12.073647 -15.977643 -12.212457 9.921359 -14.607551 -12.784419 9.150552 -15.381495 -13.818757 8.752626 -15.921934 -15.038321 8.834207 -16.084061 -16.116329 9.373434 -15.824429 -16.763929 10.225821 -15.212609 -16.807600 11.162974 -14.412538 -16.235638 11.933782 -13.638594 -15.201300 12.331707 -13.098154 -13.981736 12.250127 -12.936029 -12.903728 11.710900 -13.195660 -12.256126 10.858513 -13.807478 -11.971277 8.759571 -12.389336 -12.361948 7.670980 -13.325399 -13.413036 6.932970 -14.076677 -14.842905 6.743287 -14.441865 -16.268421 7.152759 -14.323112 -17.307619 8.051666 -13.752236 -17.682047 9.199148 -12.882207 -17.291376 10.287738 -11.946143 -16.240290 11.025749 -11.194865 -14.810421 11.215432 -10.829677 -13.384905 10.805962 -10.948429 -12.345706 9.907055 -11.519304 -11.799022 7.896006 -10.039203 -11.866713 6.511913 -11.102864 -12.794521 5.388333 -12.066406 -14.333841 4.826329 -12.671646 -16.072214 4.976488 -12.756412 -17.543842 5.798575 -12.297990 -18.354406 7.072314 -11.419214 -18.286716 8.456406 -10.355552 -17.358910 9.579986 -9.392011 -15.819590 10.141991 -8.786770 -14.081218 9.991833 -8.702003 -12.609588 9.169745 -9.160425 -11.825509 7.281207 -7.600407 -11.436655 5.685306 -8.730352 -12.075113 4.186075 -9.879075 -13.569809 3.185233 -10.738776 -15.520240 2.950954 -11.079100 -17.403788 3.546014 -10.808854 -18.715759 4.810965 -10.000454 -19.104614 6.406865 -8.870509 -18.466156 7.906096 -7.721786 -16.971462 8.906938 -6.862085 -15.021032 9.141217 -6.521762 -13.137484 8.546159 -6.792006 -12.151274 6.808867 -5.133163 -11.213759 5.141991 -6.246344 -11.402401 3.344510 -7.523083 -12.666651 1.898059 -8.621278 -14.667756 1.190213 -9.246669 -16.869522 1.410638 -9.231683 -18.681986 2.500272 -8.580335 -19.619499 4.167147 -7.467154 -19.430861 5.964627 -6.190415 -18.166611 7.411077 -5.092220 -16.165506 8.118925 -4.466829 -13.963741 7.898500 -4.481814 -12.820156 6.333575 -2.707074 -11.310852 4.774492 -3.709871 -10.929639 2.820077 -5.032474 -11.778663 0.994013 -6.320493 -13.630428 -0.214406 -7.228804 -15.988756 -0.481385 -7.514026 -18.221735 0.264610 -7.099734 -19.731037 1.823693 -6.096938 -20.112253 3.778107 -4.774335 -19.263229 5.604171 -3.486316 -17.411465 6.812590 -2.578005 -15.053138 7.079571 -2.292781 -13.802631 5.697474 -0.389207 -11.782567 4.431003 -1.191128 -10.782187 2.504907 -2.462770 -11.069539 0.435281 -3.863399 -12.567630 -1.223320 -5.017716 -14.875047 -2.026475 -5.616425 -17.373520 -1.758981 -5.499099 -19.393583 -0.492511 -4.697179 -20.393965 1.433584 -3.425536 -20.106613 3.503210 -2.024908 -18.608522 5.161811 -0.870590 -16.301107 5.964968 -0.271882 -14.996368 4.765364 1.766928 -12.607630 3.945505 1.239387 -11.026302 2.243884 0.116700 -10.676100 0.116450 -1.300311 -11.650860 -1.866754 -2.631958 -13.689396 -3.174329 -3.521428 -16.245483 -3.455912 -3.730387 -18.634220 -2.636054 -3.202847 -20.215549 -0.934434 -2.080160 -20.565752 1.193000 -0.663150 -19.590994 3.176203 0.668497 -17.552460 4.483779 1.557967 -16.245445 3.455805 3.730561 -13.689363 3.174477 3.521181 -11.650842 1.867127 2.631346 -10.676103 -0.115944 1.299485 -11.026325 -2.243373 -0.117530 -12.607668 -3.945117 -1.240011 -14.996410 -4.765195 -1.767190 -17.552492 -4.483868 -1.557811 -19.591013 -3.176518 -0.667976 -20.565754 -1.193448 0.663885 -20.215532 0.933981 2.080900 -18.634192 2.635725 3.203381 -17.373512 1.758791 5.499383 -14.875053 2.026696 5.616098 -12.567648 1.223900 5.016853 -11.069564 -0.434489 3.862216 -10.782212 -2.504106 2.461571 -11.782588 -4.430399 1.190220 -13.802640 -5.697221 0.388819 -16.301100 -5.965127 0.272104 -18.608503 -5.162332 0.871348 -20.106588 -3.503944 2.025985 -20.393942 -1.434327 3.426630 -19.393568 0.491967 4.697981 -18.221636 -0.264935 7.100320 -15.988650 0.481261 7.514238 -13.630345 0.214523 7.228574 -11.778625 -0.993677 6.319870 -10.929658 -2.819603 5.031613 -11.310922 -4.774000 3.708991 -12.820259 -6.333187 2.706399 -15.053243 -7.079383 2.292480 -17.411549 -6.812646 2.578145 -19.263268 -5.604446 3.486848 -20.112238 -3.778521 4.775104 -19.730974 -1.824126 6.097726 -18.681616 -2.500726 8.581628 -16.869013 -1.411172 9.232741 -14.667247 -1.190675 9.247197 -12.666278 -1.898318 8.621122 -11.402265 -3.344487 7.522274 -11.213899 -5.141682 6.245086 -12.151651 -6.808348 5.131782 -13.964253 -7.897901 4.480669 -16.166019 -8.118399 4.466212 -18.166986 -7.410757 5.092286 -19.431002 -5.964589 6.191134 -19.619370 -4.167394 7.468322 -18.715357 -4.811340 10.002035 -17.403107 -3.546588 10.810312 -15.519465 -2.951565 11.080031 -13.569151 -3.185707 10.738921 -12.074748 -4.186277 9.878381 -11.436682 -5.685172 8.728994 -11.825921 -7.280764 7.598737 -13.138168 -8.545517 6.790459 -15.021810 -9.140540 6.520740 -16.972124 -8.906399 6.861849 -18.466528 -7.905829 7.722389 -19.104595 -6.406935 8.871775 -18.354040 -7.072208 11.420950 -17.542898 -5.798954 12.299908 -16.070946 -4.977241 12.757985 -14.332592 -4.827245 12.672442 -12.793626 -5.389158 12.066198 -11.866413 -6.512416 11.101700 -11.799399 -7.896042 10.037379 -12.610541 -9.169296 9.158422 -14.082493 -9.991010 8.700343 -15.820848 -10.141006 8.785886 -17.359814 -9.579094 9.392128 -18.287027 -8.455837 10.356627 -17.681938 -9.198944 12.883787 -17.306870 -8.051888 13.754115 -16.267235 -7.153338 14.324772 -14.841599 -6.744061 14.442849 -13.411964 -6.933719 14.076710 -12.361399 -7.671496 13.324459 -11.971400 -8.759705 12.387663 -12.346469 -9.906759 11.517335 -13.386105 -10.805310 10.946679 -14.811738 -11.214588 10.828600 -16.241373 -11.024931 11.194739 -17.291939 -10.287154 11.946990 -16.807762 -11.162612 14.413801 -16.763420 -10.225842 15.214293 -16.115284 -9.373823 15.826071 -15.037024 -8.834849 16.085209 -13.817558 -8.753341 15.922273 -12.783641 -9.151136 15.380919 -12.212311 -9.921647 14.606203 -12.256653 -10.858416 13.805712 -12.904788 -11.710435 13.193933 -13.983047 -12.249409 12.934795 -15.202514 -12.330918 13.097732 -16.236431 -11.933124 13.639085 -15.833997 -12.988605 16.006613 -16.004684 -12.291722 16.700590 -15.668715 -11.565623 17.297487 -14.916110 -11.004866 17.637367 -13.948531 -10.759702 17.629158 -13.025239 -10.895825 17.275063 -12.393630 -11.376761 16.669956 -12.222942 -12.073643 15.975981 -12.558912 -12.799742 15.379084 -13.311516 -13.360500 15.039204 -14.279095 -13.605664 15.047413 -15.202387 -13.469541 15.401509 -14.832108 -14.741543 17.630039 -15.118093 -14.269516 18.206738 -15.003222 -13.701257 18.755430 -14.518274 -13.189028 19.129091 -13.793192 -12.870082 19.227606 -13.022259 -12.829880 19.024570 -12.412046 -13.079193 18.574394 -12.126061 -13.551220 17.997696 -12.240932 -14.119479 17.449005 -12.725879 -14.631707 17.075340 -13.450961 -14.950654 16.976828 -14.221894 -14.990857 17.179861 -13.829679 -16.501429 19.227068 -14.164059 -16.213593 19.698517 -14.190716 -15.797021 20.191147 -13.902508 -15.363334 20.572952 -13.376659 -15.028738 20.741632 -12.754071 -14.882887 20.651989 -12.201566 -14.964862 20.328043 -11.867186 -15.252699 19.856594 -11.840528 -15.669270 19.363964 -12.128736 -16.102957 18.982159 -12.654584 -16.437553 18.813478 -13.277172 -16.583405 18.903120 -12.809241 -18.339252 20.720705 -13.163775 -18.191523 21.114611 -13.279267 -17.900454 21.566961 -13.124773 -17.544037 21.956547 -12.741687 -17.217772 22.178982 -12.232658 -17.009081 22.174662 -11.734080 -16.973885 21.944746 -11.379546 -17.121614 21.550840 -11.264053 -17.412683 21.098490 -11.418549 -17.769100 20.708904 -11.801634 -18.095366 20.486469 -12.310662 -18.304054 20.490789 -11.717700 -20.294460 22.020155 -12.097865 -20.259518 22.369730 -12.281298 -20.069931 22.815104 -12.218846 -19.776499 23.236940 -11.927245 -19.457846 23.522211 -11.484628 -19.199354 23.594473 -11.009593 -19.070290 23.434366 -10.629428 -19.105232 23.084791 -10.445995 -19.294819 22.639418 -10.508447 -19.588251 22.217581 -10.800048 -19.906904 21.932312 -11.242665 -20.165394 21.860048 -10.482245 -22.358191 23.029001 -10.914547 -22.438862 23.359587 -11.171839 -22.350105 23.837709 -11.185179 -22.115702 24.335258 -10.950993 -21.798460 24.718918 -10.532031 -21.483383 24.885883 -10.040553 -21.254900 24.791418 -9.608252 -21.174227 24.460833 -9.350960 -21.262985 23.982710 -9.337620 -21.497389 23.485161 -9.571805 -21.814631 23.101501 -9.990767 -22.129707 22.934538 -9.029640 -24.464651 23.658722 -9.545413 -24.695560 23.971102 -9.896756 -24.744576 24.510616 -9.989527 -24.598562 25.132706 -9.798867 -24.296646 25.670681 -9.375864 -23.919727 25.980391 -8.833862 -23.568796 25.978851 -8.318089 -23.337887 25.666471 -7.966747 -23.288872 25.126957 -7.873976 -23.434885 24.504868 -8.064635 -23.736801 23.966892 -8.487638 -24.113720 23.657183 -7.305028 -26.497669 23.850245 -7.926635 -26.929628 24.103596 -8.391058 -27.189926 24.698345 -8.573856 -27.208811 25.475132 -8.426049 -26.981226 26.225817 -7.987241 -26.568151 26.749256 -7.375010 -26.080269 26.905191 -6.753404 -25.648310 26.651840 -6.288980 -25.388014 26.057093 -6.106182 -25.369125 25.280304 -6.253989 -25.596710 24.529619 -6.692797 -26.009785 24.006182 -5.282182 -28.322296 23.597149 -6.018998 -28.987581 23.701435 -6.604073 -29.544724 24.287655 -6.880636 -29.844444 25.198727 -6.774582 -29.806431 26.190536 -6.314330 -29.440868 26.997322 -5.623202 -28.845711 27.402912 -4.886386 -28.180428 27.298626 -4.301311 -27.623283 26.712408 -4.024748 -27.323563 25.801334 -4.130801 -27.361576 24.809528 -4.591054 -27.727139 24.002739 -2.951361 -29.841352 22.948875 -3.809889 -30.710247 22.780849 -4.516187 -31.614805 23.231625 -4.881004 -32.312653 24.180410 -4.806588 -32.616802 25.372986 -4.312878 -32.445755 26.489799 -3.532164 -31.845345 27.231606 -2.673637 -30.976448 27.399632 -1.967338 -30.071890 26.948858 -1.602521 -29.374041 26.000072 -1.676937 -29.069895 24.807495 -2.170646 -29.240940 23.690681 -0.291229 -31.043884 21.970337 -1.290764 -31.998430 21.419292 -2.129579 -33.217648 21.573460 -2.582916 -34.374855 22.391527 -2.529302 -35.159973 23.654299 -1.983104 -35.362637 25.023411 -1.090675 -34.928535 26.132015 -0.091141 -33.973991 26.683060 0.747675 -32.754772 26.528894 1.201012 -31.597567 25.710825 1.147399 -30.812447 24.448057 0.601201 -30.609785 23.078943 2.743186 -32.000622 20.672657 1.566807 -32.847980 19.698082 0.559095 -34.247475 19.419493 -0.009935 -35.824116 19.911535 0.012188 -37.155434 21.042370 0.619537 -37.884712 22.508987 1.649373 -37.816532 23.918411 2.825751 -36.969173 24.892984 3.833464 -35.569679 25.171576 4.402494 -33.993042 24.679535 4.380371 -32.661724 23.548702 3.773023 -31.932444 22.082085 6.192642 -32.803741 18.971996 4.803723 -33.325703 17.640320 3.571326 -34.694580 16.877249 2.825672 -36.543579 16.887245 2.766558 -38.377266 17.667631 3.409822 -39.704304 19.009302 4.583104 -40.169113 20.552761 5.972023 -39.647152 21.884438 7.204419 -38.278275 22.647509 7.950074 -36.429276 22.637514 8.009189 -34.595589 21.857126 7.365925 -33.268555 20.515455 10.045561 -33.499950 16.709995 8.436216 -33.513241 15.191299 6.928499 -34.617535 14.006423 5.926402 -36.516930 13.472852 5.698435 -38.702488 13.733554 6.305681 -40.588589 14.718678 7.585430 -41.669857 16.164255 9.194775 -41.656567 17.682951 10.702491 -40.552273 18.867828 11.704589 -38.652882 19.401402 11.932556 -36.467323 19.140697 11.325311 -34.581223 18.155577 14.198108 -34.054665 13.723860 12.409976 -33.458057 12.253825 10.611450 -34.098404 10.815208 9.284443 -35.804127 9.793487 8.784525 -38.118183 9.462428 9.245649 -40.420517 9.910740 10.544257 -42.094223 11.018297 12.332388 -42.690826 12.488331 14.130914 -42.050484 13.926948 15.457921 -40.344761 14.948669 15.957840 -38.030708 15.279729 15.496716 -35.728374 14.831418 18.452036 -34.358143 9.919477 16.580515 -33.155216 8.745564 14.529777 -33.210854 7.289859 12.849316 -34.510139 5.942418 11.989410 -36.704937 5.064284 12.180471 -39.207153 4.890755 13.371304 -41.346317 5.468326 15.242825 -42.549244 6.642238 17.293562 -42.493610 8.097941 18.974022 -41.194321 9.445383 19.833929 -38.999527 10.323517 19.642868 -36.497311 10.497047 22.542276 -34.256714 5.322910 20.723871 -32.554268 4.650888 18.516535 -32.006744 3.432517 16.511723 -32.760857 1.994257 15.246623 -34.614536 0.721490 15.060218 -37.071091 -0.044747 16.002455 -39.472298 -0.099141 17.820860 -41.174740 0.572880 20.028194 -41.722267 1.791251 22.033007 -40.968159 3.229511 23.298107 -39.114475 4.502277 23.484514 -36.657921 5.268515 26.183662 -33.594070 0.097537 24.572996 -31.579182 0.047426 22.350473 -30.513729 -0.715296 20.111618 -30.683205 -1.986256 18.456329 -32.042191 -3.424903 17.828140 -34.226555 -4.645752 18.395372 -36.650993 -5.321677 20.006039 -38.665882 -5.271566 22.228561 -39.731335 -4.508846 24.467417 -39.561859 -3.237886 26.122705 -38.202873 -1.799240 26.750896 -36.018513 -0.578390 29.122616 -32.251545 -5.471204 27.863556 -30.152979 -4.889416 25.790382 -28.738476 -5.059144 23.458601 -28.387049 -5.934912 21.493010 -29.192860 -7.282056 20.420288 -30.939993 -8.739612 20.527870 -33.160309 -9.917027 21.786930 -35.258869 -10.498815 23.860102 -36.673370 -10.329086 26.191883 -37.024803 -9.453321 28.157475 -36.218994 -8.106176 29.230198 -34.471859 -6.648621 31.184088 -30.175787 -11.022477 30.382397 -28.217285 -9.910773 28.617563 -26.669701 -9.458353 26.362476 -25.947712 -9.786443 24.221382 -26.244774 -10.807129 22.767986 -27.481289 -12.246922 22.391726 -29.325932 -13.720029 23.193417 -31.284435 -14.831732 24.958248 -32.832020 -15.284152 27.213335 -33.554008 -14.956064 29.354429 -33.256947 -13.935377 30.807825 -32.020432 -12.495585 32.295860 -27.399412 -16.169346 31.998369 -25.753700 -14.720313 30.667507 -24.288338 -13.731333 28.659878 -23.395964 -13.467404 26.513422 -23.315691 -13.999245 24.803284 -24.069029 -15.184348 23.987690 -25.454123 -16.705168 24.285181 -27.099834 -18.154202 25.616041 -28.565197 -19.143181 27.623671 -29.457571 -19.407112 29.770124 -29.537844 -18.875273 31.480265 -28.784506 -17.690170 32.496811 -24.047020 -20.558172 32.680508 -22.801416 -19.012342 31.852364 -21.584669 -17.667509 30.234276 -20.722809 -16.884026 28.259809 -20.446764 -16.871820 26.458021 -20.830507 -17.634167 25.311701 -21.771208 -18.966791 25.128000 -23.016813 -20.512621 25.956146 -24.233559 -21.857452 27.574232 -25.095421 -22.640938 29.548698 -25.371466 -22.653143 31.350487 -24.987724 -21.890799 31.925381 -20.329523 -23.922682 32.499321 -19.473614 -22.512127 32.171413 -18.586241 -21.043558 31.029520 -17.905174 -19.910475 29.379610 -17.612907 -19.416485 27.663774 -17.787752 -19.693954 26.341772 -18.382856 -20.668535 25.767830 -19.238766 -22.079088 26.095736 -20.126137 -23.547657 27.237629 -20.807203 -24.680742 28.887539 -21.099472 -25.174732 30.603374 -20.924629 -24.897263 30.793575 -16.511057 -26.135262 31.615770 -15.956972 -25.025833 31.713587 -15.386172 -23.655262 31.060816 -14.951605 -22.390789 29.832367 -14.769711 -21.571234 28.357401 -14.889229 -21.416189 27.031136 -15.278133 -21.967205 26.208941 -15.832217 -23.076633 26.111124 -16.403017 -24.447205 26.763893 -16.837585 -25.711676 27.992342 -17.019480 -26.531233 29.467308 -16.899963 -26.686275 29.343821 -12.856367 -27.232960 30.254108 -12.481160 -26.490767 30.649363 -12.141576 -25.373306 30.423674 -11.928604 -24.180006 29.637518 -11.899314 -23.230608 28.501541 -12.061551 -22.779501 27.320131 -12.371844 -22.947563 26.409843 -12.747052 -23.689756 26.014589 -13.086637 -24.807217 26.240276 -13.299608 -26.000515 27.026434 -13.328898 -26.949915 28.162409 -13.166661 -27.401020 27.791630 -9.548270 -27.403019 28.652430 -9.247080 -26.997229 29.199287 -9.032342 -26.190264 29.285671 -8.961595 -25.198351 28.888437 -9.053794 -24.287273 28.114025 -9.284235 -23.701153 27.169933 -9.591172 -23.597042 26.309134 -9.892363 -24.002832 25.762278 -10.107100 -24.809795 25.675892 -10.177848 -25.801710 26.073124 -10.085649 -26.712786 26.847538 -9.855207 -27.298908 26.272938 -6.649539 -26.904779 27.001308 -6.362862 -26.748411 27.578442 -6.190031 -26.224764 27.849695 -6.177355 -25.474150 27.742388 -6.328233 -24.697695 27.285269 -6.602235 -24.103453 26.600826 -6.925944 -23.850645 25.872456 -7.212622 -24.007013 25.295322 -7.385453 -24.530659 25.024069 -7.398128 -25.281273 25.131376 -7.247251 -26.057730 25.588493 -6.973248 -26.651972 24.827715 -4.131605 -25.978399 25.402384 -3.837209 -25.979366 25.940220 -3.659623 -25.669352 26.297112 -3.646430 -25.131422 26.377430 -3.801166 -24.509714 26.159651 -4.082369 -23.970814 25.702131 -4.414691 -23.659121 25.127462 -4.709087 -23.658154 24.589626 -4.886673 -23.968168 24.232735 -4.899866 -24.506098 24.152416 -4.745131 -25.127806 24.370193 -4.463928 -25.666706 23.427401 -1.930466 -24.791149 23.870836 -1.618644 -24.884996 24.353083 -1.413443 -24.717640 24.744919 -1.369847 -24.333923 24.941357 -1.499538 -23.836660 24.889757 -1.767764 -23.359097 24.603949 -2.102655 -23.029190 24.160513 -2.414478 -22.935343 23.678267 -2.619678 -23.102699 23.286430 -2.663275 -23.486416 23.089993 -2.533584 -23.983679 23.141592 -2.265358 -24.461243 22.020098 0.000650 -23.434313 22.369287 0.347913 -23.593761 22.814381 0.601978 -23.521021 23.236118 0.694768 -23.235577 23.521494 0.601419 -22.813919 23.594042 0.346945 -22.369028 23.434324 -0.000468 -22.020109 23.085135 -0.347732 -21.860661 22.640041 -0.601797 -21.933401 22.218304 -0.694586 -22.218843 21.932928 -0.601238 -22.640503 21.860380 -0.346764 -23.085394 20.566826 1.676120 -21.944925 20.846565 2.090728 -22.174118 21.281782 2.427261 -22.177845 21.755863 2.595546 -21.955111 22.141775 2.550491 -21.565592 22.336117 2.304169 -21.113663 22.286812 1.922581 -20.720417 22.007072 1.507974 -20.491222 21.571856 1.171440 -20.487495 21.097775 1.003155 -20.710232 20.711863 1.048210 -21.099749 20.517521 1.294532 -21.551676 19.060682 3.085237 -20.328428 19.265953 3.605145 -20.651678 19.703566 4.071517 -20.740688 20.256264 4.359387 -20.571613 20.775949 4.391623 -20.189753 21.123377 4.159586 -19.697430 21.205450 3.725451 -19.226557 21.000179 3.205543 -18.903309 20.562567 2.739172 -18.814295 20.009871 2.451301 -18.983372 19.490183 2.419065 -19.365231 19.142757 2.651101 -19.857555 17.532843 4.210195 -18.575039 17.622070 4.863816 -19.024488 18.042389 5.511574 -19.226799 18.681177 5.979901 -19.127762 19.367268 6.143311 -18.753912 19.916826 5.958017 -18.205425 20.182600 5.473669 -17.629265 20.093372 4.820047 -17.179815 19.673054 4.172290 -16.977507 19.034267 3.703963 -17.076544 18.348175 3.540553 -17.450390 17.798616 3.725847 -17.998878 16.049074 5.045560 -16.671051 15.948488 5.833755 -17.275227 16.292398 6.701766 -17.628332 16.988653 7.417008 -17.635752 17.850695 7.787835 -17.295496 18.647535 7.714882 -16.698738 19.165667 7.217698 -16.005379 19.266253 6.429503 -15.401203 18.922342 5.561493 -15.048097 18.226088 4.846250 -15.040679 17.364048 4.475423 -15.380933 16.567205 4.548376 -15.977691 14.698333 5.615608 -14.607380 14.316743 6.496321 -15.381363 14.489264 7.591052 -15.921842 15.169672 8.606467 -16.083996 16.175650 9.270487 -15.824379 17.237648 9.405189 -15.212551 18.071102 8.974480 -14.412454 18.452694 8.093766 -13.638471 18.280170 6.999036 -13.097992 17.599764 5.983621 -12.935836 16.593788 5.319600 -13.195455 15.531790 5.184898 -13.807281 13.571693 5.987609 -12.388987 12.824242 6.870095 -13.325178 12.710588 8.149297 -14.076609 13.261184 9.482451 -14.441931 14.328498 10.512343 -14.323258 15.626544 10.963013 -13.752389 16.807512 10.713704 -12.882287 17.554964 9.831218 -11.946095 17.668617 8.552017 -11.194664 17.118023 7.218862 -10.829342 16.050709 6.188970 -10.948014 14.752663 5.738300 -11.518883 12.737849 6.270226 -10.038770 11.573021 7.020635 -11.102630 11.063790 8.385765 -12.066393 11.346606 9.999830 -12.671822 12.345689 11.430345 -12.756691 13.793332 12.294001 -12.298260 15.301644 12.359385 -11.419364 16.466473 11.608976 -10.355505 16.975702 10.243847 -9.391741 16.692888 8.629782 -8.786312 15.693807 7.199267 -8.701443 14.246163 6.335609 -9.159874 12.218442 6.600688 -7.600008 10.641912 7.061770 -8.730015 9.662745 8.364215 -9.878851 9.543305 10.159033 -10.738687 10.315598 11.965304 -11.079129 11.772687 13.299041 -10.808959 13.524147 13.802869 -10.000566 15.100677 13.341787 -8.870560 16.079845 12.039344 -7.721725 16.199286 10.244526 -6.861889 15.426993 8.438254 -6.521445 13.969905 7.104517 -6.791615 11.972205 7.118620 -5.133672 10.059718 7.140447 -6.246581 8.597246 8.202861 -7.522945 7.976659 10.021189 -8.620764 8.364243 12.108212 -9.245878 9.656143 13.904713 -9.230787 11.506197 14.929321 -8.579537 13.418684 14.907495 -7.466629 14.881156 13.845081 -6.190265 15.501743 12.026754 -5.092446 15.114161 9.939733 -4.467332 13.822262 8.143231 -4.482421 11.895114 7.935914 -2.706812 9.790278 7.408273 -3.709640 7.907092 8.055262 -5.032294 6.750151 9.703519 -6.320369 6.629458 11.911395 -7.228727 7.577353 14.087292 -7.513974 9.339847 15.648180 -7.099679 11.444681 16.175821 -6.096851 13.327868 15.528834 -4.774198 14.484809 13.880579 -3.486123 14.605503 11.672703 -2.577764 13.657610 9.496805 -2.292517 11.835367 9.104911 -0.388787 9.728541 7.988660 -1.190656 7.560307 8.085267 -2.462328 5.911641 9.368845 -3.863061 5.224301 11.495460 -5.017528 5.682460 13.895288 -5.616391 7.163354 15.925297 -5.499186 9.270180 17.041548 -4.697317 11.438414 16.944942 -3.425645 13.087080 15.661366 -2.024913 13.774421 13.534752 -0.870446 13.316263 11.134923 -0.271582 11.625535 10.604346 1.766236 9.721079 8.945597 1.238835 7.456579 8.427029 0.116480 5.438806 9.187593 -1.300095 4.208420 11.023498 -2.631319 4.095101 13.442811 -3.520493 5.129214 15.797281 -3.729362 7.033669 17.456032 -3.201962 9.298168 17.974602 -2.079607 11.315942 17.214037 -0.663033 12.546329 15.378134 0.668191 12.659649 12.958821 1.557366 11.115422 12.341248 3.730819 9.593789 10.268249 3.521456 7.442365 9.156458 2.631612 5.237623 9.303778 1.299720 3.570321 10.670735 -0.117340 2.887213 12.891054 -1.239868 3.371335 15.369802 -1.767085 4.892967 17.442801 -1.557722 7.044391 18.554592 -0.667879 9.249133 18.407274 0.664012 10.916434 17.040318 2.081072 11.599545 14.819999 3.203601 10.209469 14.166692 5.500098 9.192177 11.869057 5.616906 7.343267 10.272183 5.017587 5.158155 9.803954 3.862730 3.222338 10.589828 2.461778 2.054518 12.419230 1.190115 1.967610 14.801976 0.388481 2.984902 17.099611 0.271674 4.833810 18.696484 0.870991 7.018922 19.164715 2.025848 8.954739 18.378841 3.426800 10.122561 16.549440 4.698463 8.880924 15.912967 7.101046 8.410585 13.606078 7.514969 7.000470 11.697105 7.229164 5.028416 10.697557 6.320211 3.022834 10.875261 5.031665 1.521119 12.182601 3.708790 0.925653 14.269277 2.706050 1.395991 16.576166 2.292126 2.806106 18.485140 2.577931 4.778159 19.484688 3.486883 6.783741 19.306984 4.775428 8.285457 17.999647 6.098304 7.174888 17.429235 8.581871 7.212191 15.314725 9.232996 6.302309 13.297691 9.247446 4.689044 11.918600 8.621348 2.804668 11.546976 7.522467 1.154099 12.282396 6.245245 0.179606 13.927805 5.131915 0.142302 16.042316 4.480789 1.052184 18.059349 4.466339 2.665448 19.438442 5.092436 4.549823 19.810066 6.191317 6.200392 19.074646 7.468538 5.190718 18.614000 10.001685 5.630272 16.845249 10.809844 5.204051 14.916422 11.079620 4.026260 13.344351 10.738728 2.412486 12.550267 9.878509 0.795140 12.746946 8.729457 -0.392413 13.881688 7.599462 -0.831968 15.650440 6.791303 -0.405748 17.579266 6.521527 0.772043 19.151337 6.862419 2.385816 19.945421 7.722637 4.003163 19.748745 8.871688 3.052193 19.431171 11.421024 3.749248 18.092117 12.300032 3.724857 16.406561 12.758180 2.985555 14.826140 12.672707 1.729437 13.774330 12.066518 0.293081 13.532963 11.102039 -0.938645 14.166711 10.037702 -1.635700 15.505763 9.158694 -1.611309 17.191320 8.700546 -0.872008 18.771740 8.786017 0.384109 19.823551 9.392206 1.820466 20.064919 10.356685 0.874274 19.912481 12.884024 1.680059 19.014153 13.754379 1.938370 17.664555 14.325047 1.579991 16.225307 14.443116 0.700951 15.082062 14.076951 -0.463212 14.541144 13.324666 -1.600563 14.747497 12.387834 -2.406348 15.645824 11.517478 -2.664658 16.995422 10.946811 -2.306281 18.434668 10.828740 -1.427241 19.577913 11.194905 -0.263078 20.118832 11.947189 -1.263699 20.137325 14.413780 -0.474428 19.630688 15.214150 -0.060414 18.643478 15.825897 -0.132591 17.440224 16.085106 -0.671620 16.343332 15.922319 -1.533068 15.646715 15.381158 -2.486110 15.537031 14.606625 -3.275381 16.043671 13.806255 -3.689395 17.030878 13.194508 -3.617218 18.234133 12.935300 -3.078190 19.331026 13.098085 -2.216743 20.027641 13.639247 -3.331402 20.206938 16.006872 -2.642679 20.006237 16.700928 -2.182013 19.352188 17.297871 -2.072837 18.420042 17.637747 -2.344406 17.459566 17.629488 -2.923953 16.728119 17.275311 -3.656188 16.421690 16.670111 -4.344911 16.622391 15.976054 -4.805577 17.276438 15.379113 -4.914753 18.208586 15.039236 -4.643184 19.169060 15.047495 -4.063638 19.900509 15.401672 -5.350668 20.215771 17.630259 -4.798938 20.227421 18.206976 -4.364289 19.843813 18.755674 -4.163185 19.167732 19.129332 -4.249512 18.380337 19.227823 -4.600138 17.692608 19.024761 -5.121114 17.288818 18.574556 -5.672844 17.277168 17.997841 -6.107494 17.660776 17.449141 -6.308598 18.336857 17.075485 -6.222271 19.124250 16.976992 -5.871645 19.811981 17.180052 -7.376164 20.227531 19.227213 -6.959685 20.373253 19.698610 -6.585544 20.188120 20.191206 -6.353992 19.721731 20.573011 -6.327075 19.099058 20.741714 -6.512003 18.486946 20.652119 -6.859227 18.049408 20.328230 -7.275707 17.903687 19.856833 -7.649848 18.088820 19.364237 -7.881399 18.555208 18.982433 -7.908317 19.177881 18.813728 -7.723388 19.789993 18.903322 -9.477850 20.262756 20.720840 -9.172648 20.495935 21.114737 -8.862829 20.450434 21.567080 -8.631408 20.138441 21.956667 -8.540394 19.643559 22.179110 -8.614173 19.098387 22.174801 -8.832977 18.649006 21.944901 -9.138179 18.415827 21.551004 -9.447998 18.461329 21.098661 -9.679420 18.773321 20.709074 -9.770433 19.268204 20.486631 -9.696654 19.813375 20.490938 -11.716900 20.295046 22.020260 -11.496552 20.606819 22.369822 -11.240640 20.670900 22.815189 -11.017735 20.470116 23.237028 -10.887566 20.058262 23.522306 -10.885010 19.545702 23.594585 -11.010752 19.069773 23.434498 -11.231099 18.757999 23.084936 -11.487012 18.693918 22.639570 -11.709916 18.894703 22.217730 -11.840086 19.306553 21.932451 -11.842643 19.819115 21.860172 -14.121834 20.256996 23.029076 -13.975537 20.671721 23.359663 -13.770025 20.850161 23.837791 -13.560363 20.744511 24.335352 -13.402730 20.383074 24.719017 -13.339364 19.862698 24.885990 -13.387243 19.322819 24.791527 -13.533540 18.908094 24.460939 -13.739052 18.729654 23.982811 -13.948714 18.835304 23.485252 -14.106347 19.196741 23.101585 -14.169713 19.717117 22.934612 -16.672321 20.052261 23.658754 -16.614403 20.614388 23.971155 -16.481201 20.943151 24.510696 -16.308403 20.950460 25.132809 -16.142313 20.634363 25.670795 -16.027433 20.079550 25.980501 -15.994546 19.434685 25.978947 -16.052462 18.872559 25.666544 -16.185665 18.543795 25.127003 -16.358463 18.536484 24.504892 -16.524553 18.852583 23.966906 -16.639433 19.407396 23.657198 -19.295227 19.575171 23.850233 -19.358561 20.329485 24.103596 -19.351841 20.861832 24.698366 -19.276869 21.029575 25.475176 -19.153734 20.787762 26.225880 -19.015429 20.201191 26.749327 -18.899014 19.427031 26.905260 -18.835680 18.672716 26.651897 -18.842400 18.140369 26.057129 -18.917372 17.972628 25.280317 -19.040506 18.214439 24.529613 -19.178812 18.801010 24.006166 -21.887342 18.735374 23.597109 -22.095034 19.706152 23.701324 -22.284853 20.491501 24.287498 -22.405939 20.880991 25.198565 -22.425848 20.770256 26.190403 -22.339245 20.188967 26.997253 -22.169333 19.292881 27.402922 -21.961643 18.322105 27.298706 -21.771822 17.536755 26.712534 -21.650736 17.147266 25.801470 -21.630827 17.257999 24.809629 -21.717430 17.839287 24.002779 -24.368042 17.476435 22.948788 -24.691259 18.654402 22.780720 -25.121437 19.718399 23.231474 -25.543310 20.383327 24.180269 -25.843836 20.471024 25.372879 -25.942490 19.957987 26.489740 -25.812840 18.981688 27.231594 -25.489622 17.803720 27.399662 -25.059444 16.739723 26.948908 -24.637573 16.074795 26.000113 -24.337046 15.987098 24.807507 -24.238392 16.500135 23.690643 -26.738813 15.774347 21.970446 -27.065601 17.117317 21.419479 -27.702141 18.453344 21.573654 -28.477867 19.424442 22.391661 -29.184929 19.770407 23.654316 -29.633867 19.398535 25.023287 -29.704391 18.408474 26.131765 -29.377602 17.065504 26.682732 -28.741064 15.729476 26.528557 -27.965336 14.758377 25.710550 -27.258274 14.412414 24.447897 -26.809336 14.784283 23.078924 -29.084967 13.624596 20.672640 -29.230524 15.067107 19.698111 -29.938639 16.639589 19.419531 -31.019571 17.920696 19.911547 -32.183689 18.567156 21.042324 -33.119064 18.405752 22.508865 -33.575066 17.479731 23.918219 -33.429512 16.037220 24.892748 -32.721397 14.464739 25.171328 -31.640465 13.183631 24.679312 -30.476347 12.537169 23.548538 -29.540970 12.698573 22.081993 -31.505482 11.038612 18.971748 -31.263247 12.502250 17.639818 -31.832628 14.253885 16.876589 -33.061062 15.824171 16.886562 -34.619389 16.792349 17.667068 -36.090061 16.898996 19.008972 -37.079006 16.115540 20.552708 -37.321239 14.651903 21.884636 -36.751862 12.900268 22.647867 -35.523426 11.329983 22.637896 -33.965099 10.361804 21.857389 -32.494431 10.255155 20.515488 -34.034531 8.050316 16.710136 -33.241394 9.450638 15.191364 -33.443943 11.308418 14.006349 -34.587898 13.125870 13.472616 -36.366745 14.416004 13.733178 -38.303841 14.833134 14.718218 -39.880142 14.265487 16.163794 -40.673279 12.865167 17.682568 -40.470730 11.007386 18.867584 -39.326775 9.189936 19.401316 -37.547928 7.899800 19.140755 -35.610832 7.482670 18.155716 -36.591530 4.731014 13.723372 -35.180626 5.981474 12.253651 -34.835747 7.859440 10.815357 -35.649307 9.861712 9.793880 -37.403309 11.451782 9.462926 -39.627773 12.203592 9.911170 -41.726654 11.915697 11.018507 -43.137558 10.665237 12.488228 -43.482437 8.787272 13.926520 -42.668880 6.785001 14.947996 -40.914879 5.194931 15.278953 -38.690414 4.443119 14.830709 -38.981163 1.198907 9.919177 -37.003586 2.218306 8.745408 -36.026340 4.022207 7.289852 -36.311275 6.127256 5.942524 -37.782043 7.969406 5.064439 -40.044556 9.055056 4.890880 -42.492569 9.093306 5.468350 -44.470142 8.073906 6.642118 -45.447392 6.270007 8.097674 -45.162457 4.164958 9.445003 -43.691689 2.322808 10.323088 -41.429180 1.237158 10.496648 -40.938301 -2.393454 5.323459 -38.554741 -1.669995 4.651302 -36.976917 -0.032346 3.432646 -36.627605 2.080687 1.994028 -37.600407 4.102918 0.720926 -39.634655 5.492492 -0.045535 -42.185280 5.877073 -0.099981 -44.568840 5.153614 0.572176 -46.146664 3.515966 1.790831 -46.495975 1.402933 3.229449 -45.523174 -0.619297 4.502552 -43.488930 -2.008872 5.269012 -42.185184 -5.878596 0.097649 -39.634911 -5.491143 0.047591 -37.600929 -4.099134 -0.715150 -36.628250 -2.075557 -1.986198 -36.977501 0.037374 -3.424976 -38.555099 1.673499 -4.645965 -40.938328 2.394420 -5.322002 -43.488602 2.006968 -5.271944 -45.522579 0.614960 -4.509203 -46.495262 -1.408617 -3.238156 -46.146011 -3.521547 -1.799379 -44.568417 -5.157673 -0.578389 -42.491688 -9.095865 -5.472212 -40.044689 -9.054919 -4.890663 -37.783134 -7.966681 -5.060304 -36.313000 -6.122745 -5.935678 -36.028214 -4.017190 -7.282231 -37.005081 -2.214198 -8.739155 -38.981846 -1.196880 -9.916067 -41.428844 -1.237825 -10.497616 -43.690399 -2.326061 -10.327977 -45.160530 -4.169998 -9.452602 -45.445320 -6.275553 -8.106050 -44.468456 -8.078545 -6.649127 -41.724976 -11.918423 -11.022626 -39.627983 -12.203440 -9.910995 -37.405315 -11.448855 -9.458593 -35.652527 -9.856862 -9.786642 -34.839279 -7.854031 -10.807241 -35.183483 -5.977021 -12.246922 -36.592903 -4.728773 -13.719923 -38.689892 -4.443757 -14.831554 -40.912563 -5.198339 -15.283957 -42.665352 -6.790332 -14.955909 -43.478600 -8.793162 -13.935310 -43.134399 -10.670173 -12.495629 -39.876572 -14.269274 -16.169285 -38.302799 -14.834280 -14.719949 -36.368458 -14.414261 -13.730772 -34.591854 -13.121759 -13.466801 -33.449024 -11.303101 -13.998767 -33.246193 -9.445593 -15.184131 -34.037704 -8.046953 -16.705276 -35.611477 -7.481947 -18.154612 -37.545818 -7.901965 -19.143789 -39.322422 -9.194467 -19.407761 -40.465252 -11.013124 -18.875793 -40.668083 -12.870632 -17.690432 -37.073757 -16.119535 -20.558165 -36.086815 -16.901480 -19.012402 -34.618961 -16.792702 -17.667622 -33.063499 -15.822344 -16.884155 -31.837217 -14.250416 -16.871933 -31.268698 -12.498116 -17.634228 -31.510273 -11.034967 -18.966787 -32.497211 -10.253023 -20.512548 -33.965069 -10.361802 -21.857330 -35.520531 -11.332158 -22.640795 -36.746811 -12.904085 -22.653019 -37.315331 -14.656385 -21.890724 -33.568653 -17.483377 -23.922644 -33.114307 -18.408434 -22.512144 -32.181797 -18.568193 -21.043621 -31.020987 -17.919846 -19.910561 -29.942915 -16.637119 -19.416567 -29.236448 -15.063717 -19.694004 -29.090887 -13.621231 -20.668531 -29.545233 -12.696174 -22.079029 -30.477743 -12.536415 -23.547552 -31.638554 -13.184761 -24.680611 -32.716625 -14.467487 -25.174606 -33.423092 -16.040890 -24.897173 -29.696253 -18.412271 -26.135071 -29.627386 -19.401419 -25.025700 -29.181772 -19.771629 -23.655214 -28.478815 -19.423706 -22.390833 -27.706869 -18.450872 -21.571348 -27.072779 -17.113802 -21.416338 -26.746447 -15.770759 -21.967339 -26.815313 -14.781611 -23.076710 -27.260927 -14.411401 -24.447195 -27.963884 -14.759324 -25.711575 -28.735828 -15.732155 -26.531059 -29.369921 -17.069227 -26.686071 -25.805283 -18.984632 -27.233057 -25.935638 -19.960476 -26.490761 -25.839457 -20.472410 -25.373199 -25.542511 -20.383261 -24.179823 -25.124365 -19.716915 -23.230396 -24.697063 -18.651922 -22.779318 -24.375099 -17.473644 -22.947454 -24.244743 -16.497799 -23.689751 -24.340923 -15.985865 -24.807312 -24.637871 -16.075014 -26.000689 -25.056015 -16.741358 -26.950113 -25.483318 -17.806353 -27.401194 -22.164652 -19.294321 -27.403021 -22.334318 -20.190342 -26.997149 -22.421932 -20.771210 -26.190125 -22.404016 -20.881281 -25.198191 -22.285374 -20.491064 -24.287136 -22.097792 -19.705116 -23.701073 -21.891535 -18.734034 -23.597040 -21.721869 -17.838013 -24.002913 -21.634254 -17.257147 -24.809935 -21.652170 -17.147074 -25.801867 -21.770813 -17.537291 -26.712925 -21.958395 -18.323238 -27.298988 -18.895679 -19.427996 -26.904840 -19.011528 -20.202156 -26.748562 -19.150249 -20.788477 -26.224966 -19.274673 -21.029856 -25.474350 -19.351461 -20.861610 -24.697840 -19.360037 -20.328829 -24.103502 -19.298103 -19.574263 -23.850588 -19.182255 -18.800102 -24.006866 -19.043533 -18.213781 -24.530462 -18.919109 -17.972404 -25.281078 -18.842321 -18.140646 -26.057589 -18.833746 -18.673429 -26.651926 -15.992078 -19.435623 -25.978449 -16.024487 -20.080503 -25.979424 -16.139620 -20.635078 -25.669405 -16.306629 -20.950754 -25.131466 -16.480761 -20.942940 -24.509743 -16.615358 -20.613733 -23.970829 -16.674358 -20.051346 -23.659124 -16.641949 -19.406467 -23.658152 -16.526815 -18.851891 -23.968168 -16.359806 -18.536217 -24.506107 -16.185675 -18.544027 -25.127831 -16.051077 -18.873236 -25.666744 -13.385592 -19.323528 -24.791201 -13.337263 -19.863474 -24.885025 -13.400690 -20.383707 -24.717649 -13.558878 -20.744831 -24.333925 -13.769439 -20.850084 -23.836666 -13.975954 -20.671263 -23.359116 -14.123087 -20.256283 -23.029234 -14.171415 -19.716337 -22.935410 -14.107988 -19.196104 -23.102783 -13.949801 -18.834980 -23.486509 -13.739240 -18.729727 -23.983767 -13.532725 -18.908548 -24.461317 -11.009607 -19.070301 -23.434381 -10.883475 -19.546341 -23.593836 -10.886003 -20.058836 -23.521097 -11.016514 -20.470465 -23.235653 -11.240037 -20.670931 -22.813990 -11.496679 -20.606520 -22.369091 -11.717674 -20.294491 -22.020166 -11.843806 -19.818451 -21.860712 -11.841278 -19.305956 -21.933451 -11.710768 -18.894327 -22.218895 -11.487246 -18.693861 -22.640558 -11.230602 -18.758270 -23.085455 -8.831959 -18.649485 -21.945007 -8.612780 -19.099052 -22.174200 -8.538953 -19.644224 -22.177925 -8.630260 -20.138927 -21.955187 -8.862237 -20.450602 -21.565668 -9.172725 -20.495737 -21.113739 -9.478529 -20.262236 -20.720497 -9.697708 -19.812670 -20.491304 -9.771535 -19.267496 -20.487579 -9.680227 -18.772793 -20.710318 -9.448251 -18.461119 -21.099836 -9.137763 -18.415983 -21.551764 -6.858533 -18.049713 -20.328552 -6.510910 -18.487448 -20.651764 -6.325831 -19.099615 -20.740744 -6.352891 -19.722185 -20.571648 -6.584837 -20.188345 -20.189787 -6.959520 -20.373180 -19.697477 -7.376544 -20.227169 -19.226635 -7.724168 -19.789434 -18.903423 -7.909246 -19.177267 -18.814444 -7.882187 -18.554697 -18.983540 -7.650241 -18.088539 -19.365400 -7.275558 -17.903702 -19.857710 -5.120478 -17.289017 -18.575104 -4.599081 -17.693069 -19.024609 -4.248278 -18.380932 -19.226973 -4.162066 -19.168291 -19.127972 -4.363546 -19.844177 -18.754133 -4.798732 -20.227482 -18.205627 -5.351015 -20.215504 -17.629425 -5.872411 -19.811449 -17.179920 -6.223215 -19.123589 -16.977558 -6.309426 -18.336229 -17.076557 -6.107946 -17.660347 -17.450394 -5.672761 -17.277039 -17.998899 -3.655546 -16.421751 -16.670940 -2.922806 -16.728537 -17.275373 -2.343026 -17.460222 -17.628731 -2.071558 -18.420750 -17.636324 -2.181140 -19.352749 -17.296124 -2.642412 -20.006491 -16.699284 -3.331775 -20.206806 -16.005728 -4.064515 -19.900019 -15.401292 -4.644295 -19.168333 -15.047936 -4.915763 -18.207806 -15.040342 -4.806181 -17.275806 -15.380542 -4.344910 -16.622065 -15.977383 -2.485623 -15.536916 -14.607863 -1.531938 -15.647016 -15.381577 -0.670120 -16.343958 -15.921771 -0.131091 -17.440996 -16.083700 -0.059285 -18.644182 -15.823977 -0.473941 -19.631123 -15.212194 -1.263953 -20.137367 -14.412278 -2.217638 -20.027266 -13.638566 -3.079456 -19.330324 -13.098372 -3.618484 -18.233288 -12.936441 -3.690291 -17.030102 -13.196164 -3.275636 -16.043159 -13.807946 -1.600102 -14.747068 -12.389615 -0.461826 -14.541261 -13.325471 0.702918 -15.082682 -14.076530 1.582039 -16.226255 -14.441546 1.939977 -17.665565 -14.322714 1.680822 -19.014950 -13.751874 0.874015 -19.912842 -12.881983 -0.264260 -20.118649 -11.946127 -1.429004 -19.577229 -11.195067 -2.308125 -18.433653 -10.830050 -2.666064 -16.994343 -10.948883 -2.406910 -15.644960 -11.519722 -0.938920 -14.166628 -10.038648 0.293137 -13.532994 -11.102696 1.729833 -13.774457 -12.066677 2.986206 -14.826321 -12.672290 3.725613 -16.406736 -12.757261 3.749930 -18.092234 -12.298825 3.052642 -19.431185 -11.419818 1.820586 -20.064819 -10.355769 0.383890 -19.823357 -9.391789 -0.872483 -18.771494 -8.786177 -1.611891 -17.191078 -8.701204 -1.636209 -15.505581 -9.159639 -0.392946 -13.881494 -7.601024 0.795118 -12.746904 -8.730658 2.413002 -12.550381 -9.879003 4.027195 -13.344581 -10.738358 5.205176 -14.916700 -11.078462 5.631305 -16.845490 -10.808182 5.191401 -18.614130 -9.999941 4.003337 -19.748720 -8.870306 2.385454 -19.945244 -7.721962 0.771261 -19.151045 -6.862606 -0.406721 -17.578928 -6.522502 -0.832850 -15.650138 -6.792781 0.178630 -13.927521 -5.134143 1.153847 -12.282236 -6.247045 2.805225 -11.546975 -7.523332 4.690277 -11.918750 -8.621021 6.303905 -13.297945 -9.245990 7.213741 -15.315004 -9.230778 7.175992 -17.429461 -8.579460 6.200776 -19.074745 -7.466558 4.549399 -19.810005 -6.190272 2.664348 -19.438232 -5.092582 1.050718 -18.059038 -4.467613 0.140883 -16.041979 -4.482825 0.925387 -14.269482 -2.706426 1.520608 -12.182885 -3.709496 3.022230 -10.875540 -5.032486 5.027895 -10.697751 -6.320903 7.000187 -11.697154 -7.229517 8.410631 -13.605961 -7.514866 8.881301 -15.912708 -7.100490 8.286080 -17.999304 -6.097420 6.784459 -19.306648 -4.774430 4.778794 -19.484440 -3.486013 2.806503 -18.485037 -2.577399 1.396057 -16.576233 -2.292050 1.967616 -14.802081 -0.388459 2.054236 -12.419448 -1.190475 3.221857 -10.590095 -2.462400 5.157616 -9.804191 -3.863423 7.342828 -10.272323 -5.018140 9.191967 -11.869052 -5.617146 10.209558 -14.166536 -5.499940 10.122938 -16.549170 -4.697925 8.955317 -18.378523 -3.426000 7.019559 -19.164427 -2.024978 4.834348 -18.696297 -0.870260 2.985209 -17.099569 -0.271253 3.371696 -15.369703 1.767674 2.887188 -12.891149 1.239889 3.569929 -10.670993 0.116811 5.236978 -9.304124 -1.300633 7.441651 -9.156793 -2.632640 9.593208 -10.268476 -3.522299 11.115141 -12.341301 -3.731227 11.599648 -14.819853 -3.203442 10.916908 -17.040010 -2.080365 9.249860 -18.406881 -0.662921 7.045187 -18.554211 0.669086 4.893631 -17.442530 1.558745 5.129269 -15.797307 3.729389 4.094898 -13.442986 3.520118 4.208023 -11.023768 2.630655 5.438331 -9.187884 1.299332 7.456162 -8.427258 -0.117125 9.720840 -8.945695 -1.239177 11.625546 -10.604282 -1.766171 12.659917 -12.958604 -1.556900 12.546794 -15.377820 -0.667438 11.316487 -17.213705 0.663885 9.298656 -17.974333 2.080341 7.033979 -17.455896 3.202393 7.163260 -15.925622 5.498657 5.682042 -13.895830 5.615507 5.223680 -11.496070 5.016537 5.910989 -9.369355 3.862240 7.559807 -8.085535 2.461911 9.728333 -7.988612 1.190766 11.835514 -9.104553 0.389407 13.316730 -11.134345 0.272557 13.775094 -13.534104 0.871527 13.087785 -15.660819 2.025822 11.438969 -16.944639 3.426151 9.270443 -17.041565 4.697297 9.340333 -15.647345 7.101427 7.577855 -14.086352 7.515385 6.629847 -11.910600 7.229434 6.750328 -9.703077 6.320195 7.907014 -8.055289 5.031297 9.789973 -7.408759 3.708100 11.894668 -7.936723 2.705153 13.657146 -9.497715 2.291195 14.605153 -11.673468 2.577146 14.484674 -13.880989 3.486385 13.327988 -15.528778 4.775282 11.445029 -16.175310 6.098479 11.506532 -14.928782 8.580776 9.656425 -13.904098 9.231752 8.364401 -12.107684 9.246310 7.976655 -10.020887 8.620549 8.597085 -8.202865 7.522141 10.059445 -7.140752 6.245404 11.971900 -7.119143 5.132439 13.822006 -8.143826 4.481462 15.114031 -9.940239 4.466905 15.501777 -12.027035 5.092665 14.881348 -13.845057 6.191072 13.418988 -14.907170 7.467809 13.524614 -13.802540 10.001280 11.772984 -13.298856 10.809390 10.315646 -11.965311 11.079164 9.543096 -10.159228 10.738314 9.662335 -8.364546 9.878173 10.641415 -7.062146 8.729213 12.217991 -6.601007 7.599298 13.969621 -7.104691 6.791188 15.426958 -8.438234 6.521415 16.199509 -10.244317 6.862263 16.080271 -12.039001 7.722404 15.101192 -13.341400 8.871364 15.301411 -12.359058 11.421229 13.793241 -12.292912 12.300309 12.345761 -11.428785 12.758376 11.346827 -9.998218 12.672691 11.064097 -8.384531 12.066215 11.573333 -7.020110 11.101451 12.738082 -6.270550 10.036907 14.246252 -6.336696 9.157827 15.693731 -7.200822 8.699759 16.692667 -8.631389 8.785443 16.975395 -10.245076 9.391919 16.466162 -11.609498 10.356684 16.807184 -10.713747 12.884066 15.626290 -10.962145 13.754533 14.328384 -10.510799 14.325191 13.261241 -9.480645 14.443135 12.710798 -8.147714 14.076760 12.824548 -6.869162 13.324239 13.572010 -5.987577 12.387205 14.752904 -5.739179 11.516739 16.050808 -6.190525 10.946079 17.117952 -7.220678 10.828135 17.668396 -8.553610 11.194509 17.554647 -9.832161 11.947031 18.070734 -8.974944 14.413983 17.237276 -9.404660 15.214616 16.175373 -9.269111 15.826425 15.169559 -8.604614 16.085474 14.489343 -7.589222 15.922353 14.316987 -6.495009 15.380770 14.698675 -5.615167 14.605840 15.532133 -5.185451 13.805206 16.594036 -5.321000 13.193398 17.599850 -5.985496 12.934348 18.280066 -7.000887 13.097470 18.452421 -8.095100 13.639053 19.165607 -7.218096 16.006359 18.647459 -7.714607 16.700191 17.850613 -7.786966 17.297026 16.988585 -7.415784 17.636932 16.292355 -6.700519 17.628841 15.948476 -5.832826 17.274918 16.049091 -5.045202 16.669994 16.567240 -4.548691 15.976162 17.364084 -4.476332 15.379330 18.226112 -4.847514 15.039419 18.922344 -5.562778 15.047512 19.266222 -6.430471 15.401436 20.182600 -5.474146 17.629879 19.916819 -5.957935 18.206509 19.367247 -6.142701 18.755165 18.681139 -5.978934 19.128838 18.042339 -5.510517 19.227400 17.622015 -4.862961 19.024445 17.532789 -4.209778 18.574348 17.798571 -3.725989 17.997719 18.348143 -3.541224 17.449062 19.034250 -3.704990 17.075390 19.673048 -4.173408 16.976828 20.093374 -4.820963 17.179783 21.205389 -3.726415 19.226990 21.123264 -4.159856 19.698496 20.775806 -4.391138 20.191160 20.256117 -4.358288 20.572969 19.703447 -4.070109 20.741621 19.265882 -3.603818 20.651924 19.060671 -3.084358 20.327911 19.142796 -2.650917 19.856405 19.490253 -2.419635 19.363741 20.009943 -2.452484 18.981932 20.562613 -2.740663 18.813280 21.000175 -3.206954 18.902977 22.286812 -1.923544 20.720598 22.336155 -2.304466 21.114489 22.141832 -2.550058 21.566824 21.755911 -2.594514 21.956406 21.281796 -2.425922 22.178843 20.846529 -2.089455 22.174536 20.566738 -1.675271 21.944635 20.517395 -1.294349 21.550745 20.711718 -1.048757 21.098410 21.097639 -1.004301 20.708828 21.571753 -1.172893 20.486391 22.007019 -1.509359 20.490698</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="1800" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="5400">0.711155 -0.006805 -0.703003 0.535280 0.034518 -0.843969 0.802919 -0.278013 -0.527286 0.868149 -0.352365 -0.349507 0.848125 -0.524356 -0.075728 0.792584 -0.602185 0.095834 0.662339 -0.640293 0.389014 0.507386 -0.691498 0.514189 0.296988 -0.597095 0.745168 0.089106 -0.598365 0.796253 -0.151821 -0.406959 0.900741 -0.352654 -0.347642 0.868781 -0.567288 -0.119181 0.814850 -0.702204 -0.004438 0.711962 -0.839871 0.191471 0.507894 -0.866148 0.341340 0.365068 -0.894845 0.442517 0.058576 -0.798075 0.597035 -0.081399 -0.713882 0.565035 -0.413651 -0.513421 0.692002 -0.507476 -0.343589 0.523718 -0.779529 -0.088194 0.598651 -0.796140 0.114989 0.328879 -0.937345 0.361058 0.342055 -0.867546 0.314279 0.025041 -0.949000 0.681460 -0.237159 -0.692364 0.852903 -0.454480 -0.256913 0.786390 -0.569889 0.238366 0.503000 -0.554712 0.662786 0.078347 -0.414108 0.906850 -0.377287 -0.184690 0.907493 -0.745141 0.074251 0.662761 -0.926546 0.294560 0.233980 -0.869324 0.416217 -0.266531 -0.585263 0.404301 -0.702856 -0.150645 0.260707 -0.953592 0.061034 -0.037504 -0.997431 0.506688 -0.241341 -0.827661 0.800552 -0.408531 -0.438426 0.866667 -0.495017 0.062023 0.691717 -0.479435 0.540065 0.324287 -0.367031 0.871852 -0.139705 -0.187271 0.972323 -0.580241 0.013403 0.814334 -0.881223 0.182377 0.436101 -0.959576 0.273814 -0.065119 -0.789755 0.261398 -0.554940 -0.415204 0.147206 -0.897739 -0.203734 -0.142310 -0.968628 0.288418 -0.294596 -0.911059 0.688364 -0.401969 -0.603801 0.889665 -0.436475 -0.134109 0.842839 -0.390293 0.370532 0.564112 -0.276443 0.778047 0.127553 -0.124683 0.983964 -0.354106 0.025735 0.934851 -0.755586 0.135229 0.640940 -0.968911 0.173740 0.176143 -0.932581 0.129440 -0.336954 -0.652324 0.013453 -0.757821 -0.454029 -0.262117 -0.851559 0.044541 -0.386869 -0.921058 0.521015 -0.442780 -0.729719 0.845941 -0.416280 -0.333309 0.935407 -0.316080 0.158449 0.770279 -0.169351 0.614809 0.396505 -0.014169 0.917923 -0.088772 0.109527 0.990012 -0.560291 0.169079 0.810855 -0.893579 0.147301 0.424050 -0.996359 0.048194 -0.070326 -0.836161 -0.102200 -0.538878 -0.665620 -0.359960 -0.653742 -0.201983 -0.493131 -0.846182 0.312186 -0.524753 -0.791944 0.735397 -0.448163 -0.508272 0.955180 -0.286265 -0.075387 0.917328 -0.083119 0.389358 0.635643 0.108411 0.764333 0.184635 0.239319 0.953224 -0.319427 0.275418 0.906704 -0.745189 0.205576 0.634374 -0.977673 0.045978 0.205038 -0.949901 -0.161652 -0.267500 -0.822421 -0.403563 -0.400950 -0.428971 -0.581519 -0.691245 0.082001 -0.627213 -0.774519 0.569019 -0.529718 -0.628980 0.900253 -0.318219 -0.297122 0.990306 -0.051128 0.129148 0.819692 0.201175 0.536316 0.435368 0.373971 0.818902 -0.063006 0.422800 0.904030 -0.546503 0.333598 0.768145 -0.886904 0.127284 0.444071 -0.989604 -0.142940 0.015857 -0.917735 -0.375896 -0.128315 -0.619353 -0.624592 -0.475696 -0.147992 -0.722208 -0.675658 0.365624 -0.642605 -0.673334 0.780834 -0.410110 -0.471283 0.987817 -0.089928 -0.127008 0.935600 0.232194 0.265968 0.641165 0.472788 0.604466 0.181976 0.570231 0.801075 -0.323343 0.498550 0.804299 -0.742469 0.274177 0.611200 -0.961696 -0.045824 0.270261 -0.952421 -0.276141 0.128998 -0.762416 -0.605782 -0.227484 -0.358917 -0.783416 -0.507384 0.146525 -0.759893 -0.633320 0.614506 -0.543612 -0.571724 0.919096 -0.196099 -0.341772 0.982123 0.188089 -0.007516 0.790616 0.508049 0.341780 0.396406 0.681476 0.615185 -0.098210 0.663410 0.741783 -0.564642 0.456814 0.687387 -0.878553 0.113525 0.463957 -0.932766 -0.115363 0.341524 -0.853761 -0.520158 0.022958 -0.536829 -0.791728 -0.291516 -0.068750 -0.854402 -0.515044 0.420993 -0.692005 -0.586425 0.799007 -0.351526 -0.487870 0.965896 0.073023 -0.248419 0.880928 0.468548 0.066539 0.568969 0.732407 0.373972 0.111821 0.796622 0.594045 -0.371937 0.643485 0.669021 -0.754920 0.310735 0.577529 -0.868511 0.088188 0.487762 -0.894442 -0.372644 0.247205 -0.673409 -0.737245 -0.054687 -0.264738 -0.904233 -0.335078 0.218675 -0.827786 -0.516674 0.644075 -0.531011 -0.550631 0.897676 -0.097045 -0.429837 0.914880 0.356875 -0.188769 0.694181 0.711675 0.107849 0.294556 0.875766 0.382453 -0.180130 0.806219 0.563528 -0.605849 0.519254 0.602762 -0.771487 0.312557 0.554180 -0.889780 -0.175578 0.421264 -0.765538 -0.618954 0.175634 -0.430588 -0.895039 -0.116181 0.023119 -0.927237 -0.373762 0.470396 -0.708096 -0.526620 0.790050 -0.300082 -0.534576 0.898672 0.184990 -0.397702 0.770650 0.618353 -0.154068 0.441581 0.887488 0.131797 -0.002462 0.922739 0.385418 -0.445949 0.713611 0.540268 -0.654911 0.534146 0.534584 -0.848447 0.053316 0.526588 -0.814649 -0.443571 0.373620 -0.559962 -0.820362 0.115967 -0.153379 -0.972403 -0.175806 0.292779 -0.858350 -0.421326 0.656417 -0.511867 -0.554173 0.840963 -0.029410 -0.540292 0.800282 0.459254 -0.385531 0.547695 0.826205 -0.131965 0.150093 0.976615 0.153930 -0.289174 0.870777 0.397651 -0.532921 0.728856 0.429842 -0.781926 0.292226 0.550632 -0.826278 -0.224546 0.516569 -0.650847 -0.681368 0.334868 -0.301932 -0.951771 0.054484 0.124377 -0.960924 -0.247296 0.510579 -0.708100 -0.487754 0.752596 -0.265112 -0.602756 0.788224 0.247078 -0.563609 0.611055 0.692976 -0.382617 0.269115 0.957032 -0.108013 -0.148470 0.970749 0.188688 -0.419799 0.872960 0.248416 -0.703969 0.516108 0.487913 -0.809827 0.018485 0.586377 -0.705667 -0.486795 0.514843 -0.417434 -0.860763 0.291264 -0.023791 -0.999450 -0.023104 0.366356 -0.865532 -0.341524 0.646530 -0.498510 -0.577483 0.743214 -0.000459 -0.669054 0.633891 0.495095 -0.594191 0.349647 0.858925 -0.374159 -0.034837 0.997168 -0.066658 -0.328335 0.944532 0.007490 -0.629451 0.697802 0.341853 -0.778064 0.260205 0.571760 -0.731427 -0.253207 0.633168 -0.499198 -0.702608 0.507092 -0.143688 -0.963175 0.227260 0.236852 -0.962940 -0.129025 0.537512 -0.704208 -0.463866 0.677917 -0.260736 -0.687347 0.623564 0.246528 -0.741884 0.391806 0.683955 -0.615381 0.044467 0.938669 -0.341941 -0.266972 0.926261 -0.266020 -0.571939 0.810385 0.127129 -0.745621 0.470952 0.471438 -0.739351 -0.004936 0.673302 -0.551610 -0.489481 0.675377 -0.231550 -0.848762 0.475382 0.133012 -0.982786 0.128220 0.441002 -0.855887 -0.270139 0.608661 -0.506094 -0.611065 0.593396 -0.030940 -0.804316 0.402685 0.442553 -0.801244 0.088597 0.791547 -0.604652 -0.235978 0.810314 -0.536382 -0.539686 0.831924 -0.129003 -0.725788 0.620310 0.297401 -0.743225 0.227584 0.629144 -0.584223 -0.242957 0.774374 -0.289373 -0.662499 0.690911 0.061350 -0.914126 0.400762 0.370769 -0.928592 -0.015756 0.553644 -0.704607 -0.443855 0.562170 -0.306705 -0.768047 0.397537 0.156612 -0.904122 0.105889 0.563834 -0.819072 -0.224334 0.604492 -0.764372 -0.530993 0.752712 -0.389193 -0.725643 0.683889 0.075753 -0.755753 0.412470 0.508632 -0.610444 0.007538 0.792023 -0.326166 -0.421896 0.845943 0.020768 -0.756657 0.653482 0.334666 -0.903570 0.267505 0.528576 -0.823805 -0.204823 0.550678 -0.542727 -0.634193 0.398184 -0.139136 -0.906692 0.114675 0.279331 -0.953323 -0.210925 0.336113 -0.917899 -0.532218 0.582260 -0.614587 -0.741656 0.651909 -0.157989 -0.783411 0.524219 0.333857 -0.643732 0.229385 0.730063 -0.357177 -0.155391 0.921020 -0.000117 -0.524668 0.851307 0.329317 -0.775431 0.538756 0.539796 -0.838844 0.070440 0.574405 -0.700279 -0.423872 0.426588 -0.400814 -0.810784 0.139039 -0.022297 -0.990036 -0.172136 0.048019 -0.983902 -0.521915 0.350231 -0.777781 -0.759714 0.534718 -0.370016 -0.822803 0.552116 0.134771 -0.691989 0.394847 0.604356 -0.398987 0.101976 0.911268 -0.021237 -0.248110 0.968499 0.337731 -0.558533 0.757614 0.578290 -0.743029 0.336882 0.634928 -0.752231 -0.176110 0.494918 -0.586750 -0.640921 0.199178 -0.293865 -0.934864 -0.092738 -0.214570 -0.972296 -0.480488 0.097387 -0.871577 -0.761412 0.359411 -0.539515 -0.862059 0.503088 -0.061289 -0.753751 0.488903 0.439128 -0.461849 0.317757 0.828086 -0.062585 0.033575 0.997475 0.335260 -0.286442 0.897525 0.621265 -0.553503 0.554676 0.716892 -0.694157 0.064898 0.598488 -0.671916 -0.436282 0.301511 -0.495733 -0.814457 0.028250 -0.418945 -0.907572 -0.398313 -0.139027 -0.906652 -0.732289 0.158463 -0.662300 -0.886832 0.396282 -0.237675 -0.819776 0.511460 0.257636 -0.545583 0.471404 0.692905 -0.134887 0.284276 0.949206 0.301496 -0.000619 0.953467 0.642932 -0.305110 0.702529 0.795110 -0.544951 0.266137 0.718232 -0.655150 -0.234353 0.436585 -0.608095 -0.663034 0.179862 -0.550714 -0.815085 -0.277141 -0.334696 -0.900650 -0.666079 -0.041020 -0.744752 -0.885869 0.253789 -0.388364 -0.877980 0.472553 0.076452 -0.641712 0.556355 0.527897 -0.237085 0.480558 0.844307 0.227912 0.263545 0.937337 0.625712 -0.036218 0.779213 0.846370 -0.336120 0.413136 0.830487 -0.553889 -0.059144 0.585358 -0.631603 -0.508364 0.346588 -0.610270 -0.712353 -0.125471 -0.478961 -0.868823 -0.563349 -0.221625 -0.795940 -0.852846 0.094090 -0.513615 -0.917716 0.385673 -0.095151 -0.738792 0.575842 0.350131 -0.360807 0.612388 0.703420 0.116396 0.483349 0.867655 0.563083 0.222409 0.795909 0.856247 -0.099179 0.506957 0.915974 -0.393033 0.080728 0.728241 -0.579599 -0.365693 0.513773 -0.605376 -0.607912 0.046217 -0.569929 -0.820393 -0.428300 -0.373884 -0.822660 -0.785301 -0.069460 -0.615205 -0.931060 0.263527 -0.252349 -0.825825 0.537348 0.171084 -0.495112 0.678387 0.542822 -0.025496 0.647068 0.762006 0.456488 0.450221 0.767411 0.818894 0.140866 0.556390 0.962590 -0.196249 0.186831 0.849890 -0.469267 -0.239740 0.669187 -0.545789 -0.504285 0.227595 -0.609489 -0.759424 -0.266735 -0.492605 -0.828368 -0.683263 -0.226956 -0.694005 -0.912470 0.117363 -0.391949 -0.893176 0.449706 -0.001381 -0.628672 0.681580 0.374460 -0.187665 0.749780 0.634517 0.311947 0.634360 0.707302 0.734340 0.365677 0.571861 0.964132 0.016857 0.264887 0.939557 -0.316949 -0.129521 0.803004 -0.441039 -0.400836 0.409190 -0.600698 -0.686822 -0.085025 -0.574454 -0.814109 -0.548262 -0.370304 -0.749856 -0.858245 -0.042599 -0.511470 -0.932759 0.322172 -0.161761 -0.750837 0.627263 0.206846 -0.359347 0.790599 0.495805 0.137698 0.767072 0.626609 0.606087 0.561963 0.562900 0.918392 0.230581 0.321541 0.990077 -0.136908 -0.031684 0.906779 -0.300206 -0.296021 0.581689 -0.546885 -0.602126 0.109575 -0.616656 -0.779570 -0.383328 -0.491863 -0.781749 -0.766276 -0.206174 -0.608533 -0.937732 0.164663 -0.305850 -0.851499 0.522322 0.046145 -0.529346 0.771210 0.353593 -0.056510 0.843834 0.533621 0.440051 0.719684 0.537038 0.825936 0.431787 0.362478 0.996670 0.058097 0.057212 0.973090 -0.132512 -0.188512 0.735577 -0.451965 -0.504632 0.308558 -0.616988 -0.723960 -0.193310 -0.584162 -0.788281 -0.636278 -0.362812 -0.680822 -0.902622 -0.011972 -0.430268 -0.921202 0.375156 -0.103176 -0.686289 0.695360 0.213264 -0.259870 0.862555 0.434127 0.243995 0.831147 0.499661 0.689559 0.609046 0.391881 0.956505 0.256037 0.139795 0.995616 0.052037 -0.077722 0.861154 -0.321157 -0.394044 0.501950 -0.574388 -0.646625 0.014690 -0.640236 -0.768038 -0.470295 -0.501614 -0.726090 -0.823745 -0.195767 -0.532090 -0.951388 0.195823 -0.237727 -0.818740 0.568776 0.078474 -0.460651 0.823226 0.331814 0.027311 0.890530 0.454104 0.514107 0.752146 0.412274 0.868669 0.445084 0.217518 0.969487 0.242485 0.035994 0.949025 -0.161426 -0.270727 0.678685 -0.489677 -0.547361 0.231323 -0.654429 -0.719870 -0.273113 -0.611955 -0.742240 -0.699849 -0.373923 -0.608599 -0.934996 -0.003953 -0.354636 -0.915572 0.399261 -0.048154 -0.646353 0.727922 0.228816 -0.199070 0.893782 0.401901 0.306406 0.852003 0.424507 0.734258 0.613561 0.290530 0.891691 0.426726 0.150973 0.990536 0.018090 -0.136059 0.826910 -0.366254 -0.426706 0.444983 -0.623231 -0.643097 -0.052672 -0.684217 -0.727374 -0.532840 -0.533207 -0.657093 -0.867249 -0.210736 -0.451076 -0.966515 0.197067 -0.164358 -0.803850 0.581253 0.126374 -0.422461 0.838906 0.343166 0.075619 0.900725 0.427757 0.556746 0.749871 0.357389 0.762075 0.591387 0.263634 0.978591 0.205701 0.006778 0.934551 -0.210743 -0.286710 0.641979 -0.546151 -0.538128 0.179581 -0.710713 -0.680175 -0.328670 -0.660633 -0.674937 -0.746856 -0.409557 -0.523899 -0.963258 -0.024663 -0.267445 -0.919928 0.391231 0.025879 -0.628184 0.726882 0.277539 -0.165898 0.892237 0.419990 0.343066 0.842706 0.414913 0.584338 0.722882 0.368768 0.909031 0.387732 0.152727 0.990795 -0.033036 -0.131275 0.807799 -0.426394 -0.407000 0.409393 -0.686839 -0.600541 -0.097415 -0.744779 -0.660162 -0.576907 -0.584996 -0.570050 -0.900952 -0.250402 -0.354379 -0.982973 0.169565 -0.070793 -0.800883 0.562679 0.204885 -0.403127 0.823681 0.398795 0.103939 0.882422 0.458833 0.367180 0.808573 0.459769 0.782126 0.549071 0.294618 0.987566 0.153644 0.033282 0.928308 -0.271487 -0.254047 0.620428 -0.612155 -0.490240 0.146778 -0.777093 -0.612032 -0.365571 -0.722381 -0.586962 -0.779544 -0.462941 -0.421896 -0.984585 -0.068268 -0.161035 -0.925900 0.356170 0.125905 -0.618994 0.696901 0.362182 -0.145743 0.862594 0.484450 0.124491 0.838936 0.529801 0.603978 0.674962 0.423835 0.921588 0.333721 0.198259 0.991887 -0.093237 -0.086409 0.795993 -0.491211 -0.353704 0.386676 -0.753376 -0.531890 -0.126054 -0.809594 -0.573295 -0.604757 -0.645108 -0.467016 -0.921455 -0.304182 -0.241649 -0.991626 0.121949 0.042497 -0.796516 0.519410 0.309478 -0.388111 0.781889 0.487873 -0.126041 0.809594 0.573299 0.386687 0.753367 0.531893 0.796000 0.491197 0.353709 0.991888 0.093223 0.086415 0.921585 -0.333731 -0.198254 0.603975 -0.674965 -0.423835 0.124488 -0.838933 -0.529806 -0.388113 -0.781884 -0.487879 -0.796518 -0.519404 -0.309481 -0.991627 -0.121943 -0.042495 -0.921452 0.304188 0.241653 -0.604749 0.645112 0.467021 -0.365553 0.722388 0.586964 0.146798 0.777095 0.612025 0.620441 0.612152 0.490228 0.928311 0.271483 0.254040 0.987566 -0.153642 -0.033280 0.782133 -0.549065 -0.294611 0.367197 -0.808569 -0.459763 -0.145724 -0.862598 -0.484447 -0.618982 -0.696913 -0.362181 -0.925896 -0.356181 -0.125899 -0.984583 0.068265 0.161045 -0.779536 0.462946 0.421906 -0.576876 0.585024 0.570053 -0.097369 0.744801 0.660145 0.409437 0.686843 0.600506 0.807825 0.426380 0.406963 0.990799 0.033012 0.131255 0.909023 -0.387753 -0.152723 0.584335 -0.722897 -0.368745 0.103946 -0.882436 -0.458805 -0.403119 -0.823697 -0.398771 -0.800881 -0.562690 -0.204865 -0.982972 -0.169563 0.070812 -0.900941 0.250422 0.354394 -0.746787 0.409635 0.523935 -0.328547 0.660687 0.674944 0.179729 0.710711 0.680138 0.642101 0.546082 0.538053 0.934602 0.210627 0.286626 0.978565 -0.205823 -0.006834 0.762002 -0.591476 -0.263646 0.342987 -0.842749 -0.414891 -0.165960 -0.892242 -0.419955 -0.628228 -0.726858 -0.277502 -0.919951 -0.391182 -0.025840 -0.963243 0.024735 0.267489 -0.867180 0.210848 0.451155 -0.532681 0.533302 0.657145 -0.052448 0.684247 0.727362 0.445206 0.623163 0.643008 0.827051 0.366096 0.426568 0.990550 -0.018287 0.135928 0.891598 -0.426894 -0.151047 0.556611 -0.749969 -0.357396 0.075497 -0.900752 -0.427721 -0.422550 -0.838883 -0.343114 -0.803904 -0.581191 -0.126312 -0.966521 -0.196973 0.164433 -0.934934 0.004156 0.354797 -0.699633 0.374109 0.608734 -0.272761 0.612056 0.742286 0.231726 0.654381 0.719783 0.679009 0.489463 0.547149 0.949156 0.161098 0.270462 0.969395 -0.242820 -0.036214 0.734014 -0.613800 -0.290642 0.306122 -0.852104 -0.424510 -0.199313 -0.893760 -0.401831 -0.646519 -0.727811 -0.228703 -0.915639 -0.399089 0.048299 -0.951387 -0.195596 0.237918 -0.823566 0.195996 0.532282 -0.469937 0.501775 0.726211 0.015157 0.640251 0.768017 0.502389 0.574214 0.646440 0.861415 0.320821 0.393748 0.995618 -0.052433 0.077425 0.868451 -0.445412 -0.217719 0.513786 -0.752326 -0.412345 0.027001 -0.890556 -0.454073 -0.460889 -0.823132 -0.331715 -0.818877 -0.568600 -0.078323 -0.921277 -0.374908 0.103410 -0.902499 0.012253 0.430518 -0.635937 0.363052 0.681012 -0.192803 0.584274 0.788322 0.309100 0.616902 0.723802 0.735982 0.451670 0.504307 0.973221 0.132085 0.188132 0.956348 -0.256458 -0.140097 0.689216 -0.609340 -0.392029 0.243606 -0.831263 -0.499658 -0.260204 -0.862509 -0.434019 -0.686515 -0.695193 -0.213083 -0.851685 -0.522044 -0.045848 -0.937685 -0.164315 0.306182 -0.765959 0.206514 0.608818 -0.382771 0.492093 0.781876 0.110242 0.616679 0.779457 0.582268 0.546653 0.601776 0.907081 0.299763 0.295543 0.996614 -0.058617 -0.057653 0.825588 -0.432223 -0.362749 0.439570 -0.719930 -0.537103 -0.056978 -0.843866 -0.533520 -0.529705 -0.771062 -0.353377 -0.751120 -0.627029 -0.206525 -0.932810 -0.321832 0.162141 -0.858014 0.042970 0.511827 -0.547758 0.370609 0.750073 -0.084352 0.574590 0.814083 0.409849 0.600593 0.686522 0.803441 0.440689 0.400344 0.990163 0.136406 0.031169 0.918136 -0.231079 -0.321913 0.605620 -0.562317 -0.563048 0.137183 -0.767213 -0.626550 -0.359789 -0.790532 -0.495592 -0.629094 -0.681400 -0.374079 -0.893347 -0.449364 0.001850 -0.912325 -0.116946 0.392411 -0.682800 0.227347 0.694332 -0.266045 0.492862 0.828436 0.228336 0.609522 0.759174 0.669763 0.545555 0.503772 0.939796 0.316492 0.128908 0.963981 -0.017411 -0.265401 0.733885 -0.366161 -0.572136 0.311352 -0.634649 -0.707306 -0.188238 -0.749824 -0.634296 -0.495686 -0.678311 -0.542393 -0.826141 -0.537045 -0.170512 -0.931023 -0.263095 0.252938 -0.784900 0.069911 0.615666 -0.427619 0.374245 0.822850 0.047004 0.570102 0.820228 0.514452 0.605293 0.607420 0.850272 0.468919 0.239065 0.962575 0.195712 -0.187475 0.818506 -0.141442 -0.556814 0.455859 -0.450668 -0.767523 -0.026183 -0.647268 -0.761813 -0.361506 -0.612479 -0.702981 -0.739254 -0.575647 -0.349476 -0.917804 -0.385285 0.095868 -0.852534 -0.093636 0.514216 -0.562724 0.222035 0.796268 -0.124701 0.479243 0.868778 0.347297 0.610349 0.711940 0.728707 0.579427 0.365034 0.916090 0.392617 -0.081435 0.855987 0.098610 -0.507506 0.562514 -0.222970 -0.796155 0.115662 -0.483729 -0.867542 -0.237755 -0.480830 -0.843964 -0.642233 -0.556342 -0.527275 -0.878171 -0.472316 -0.075715 -0.885676 -0.253450 0.389025 -0.665585 0.041355 0.745176 -0.276513 0.334967 0.900743 0.180444 0.550879 0.814845 0.585764 0.631613 0.507883 0.830657 0.553696 0.058563 0.846274 0.335716 -0.413660 0.625339 0.035688 -0.779537 0.227312 -0.264032 -0.937345 -0.135471 -0.284708 -0.948994 -0.546131 -0.471588 -0.692347 -0.820051 -0.511394 -0.256891 -0.886731 -0.396080 0.238389 -0.731883 -0.158241 0.662803 -0.397785 0.139216 0.906855 0.028712 0.419095 0.907488 0.436886 0.608192 0.662747 0.718375 0.655132 0.233963 0.795116 0.544741 -0.266549 0.642759 0.304688 -0.702870 0.301088 0.000093 -0.953596 -0.062979 -0.034094 -0.997432 -0.462334 -0.318125 -0.827674 -0.754063 -0.489030 -0.438450 -0.862029 -0.503053 0.061996 -0.761072 -0.359341 0.540040 -0.480023 -0.097342 0.871838 -0.092354 0.214609 0.972324 0.301706 0.495792 0.814349 0.598543 0.671969 0.436124 0.716918 0.694112 -0.065096 0.621265 0.553254 -0.554923 0.335103 0.285984 -0.897730 -0.021367 0.247609 -0.968624 -0.399328 -0.102461 -0.911065 -0.692290 -0.395142 -0.603819 -0.822829 -0.552231 -0.134136 -0.759429 -0.534782 0.370506 -0.521477 -0.350333 0.778029 -0.171774 -0.048145 0.983959 0.199325 0.293776 0.934861 0.494897 0.586727 0.640959 0.634920 0.752225 0.176166 0.578397 0.742920 -0.336936 0.337822 0.558212 -0.757809 0.000002 0.524248 -0.851566 -0.357328 0.154843 -0.921054 -0.643983 -0.229840 -0.729698 -0.783486 -0.524478 -0.333276 -0.741425 -0.652052 0.158485 -0.531774 -0.582406 0.614833 -0.210489 -0.336297 0.917932 0.139269 0.022119 0.990008 0.426588 0.400690 0.810845 0.574359 0.700215 0.424040 0.539913 0.838777 -0.070335 0.329566 0.775233 -0.538887 0.021091 0.756409 -0.653759 -0.326068 0.421457 -0.846200 -0.610546 -0.008021 -0.791940 -0.755822 -0.412820 -0.508245 -0.725495 -0.684091 -0.075351 -0.530628 -0.752870 0.389385 -0.223911 -0.604684 0.764344 0.114955 -0.279553 0.953224 0.398235 0.138927 0.906702 0.550624 0.542566 0.634378 0.528654 0.823700 0.205045 0.334967 0.903460 -0.267502 0.061725 0.914016 -0.400955 -0.289112 0.662257 -0.691253 -0.584171 0.242590 -0.774528 -0.743250 -0.227924 -0.628991 -0.725710 -0.620528 -0.297136 -0.539438 -0.832064 0.129135 -0.235637 -0.810461 0.536310 0.106168 -0.564026 0.818904 0.397644 -0.156835 0.904037 0.562146 0.306490 0.768151 0.553680 0.704441 0.444073 0.371017 0.928491 0.015856 0.133325 0.982731 -0.128316 -0.231249 0.848673 -0.475687 -0.551464 0.489277 -0.675644 -0.739329 0.004678 -0.673328 -0.745587 -0.471152 -0.471291 -0.571797 -0.810502 -0.127024 -0.266728 -0.926350 0.265955 0.088848 -0.791664 0.604462 0.402835 -0.442718 0.801078 0.593425 0.030744 0.804302 0.608682 0.505910 0.611197 0.441164 0.855767 0.270255 0.237065 0.962890 0.129003 -0.143417 0.963165 -0.227474 -0.499004 0.702543 -0.507374 -0.731352 0.253060 -0.633312 -0.778039 -0.260366 -0.571721 -0.629378 -0.697908 -0.341770 -0.328173 -0.944588 -0.007515 0.044677 -0.938717 0.341781 0.391976 -0.684035 0.615184 0.623639 -0.246654 0.741779 0.677938 0.260586 0.687383 0.537596 0.704085 0.463957 0.366477 0.865477 0.341532 -0.023585 0.999458 0.022966 -0.417236 0.860776 -0.291512 -0.705555 0.486746 -0.515044 -0.809788 -0.018584 -0.586428 -0.703934 -0.516195 -0.487873 -0.419708 -0.873002 -0.248420 -0.034689 -0.997181 0.066536 0.349798 -0.858947 0.373968 0.633985 -0.495155 0.594041 0.743244 0.000361 0.669020 0.646565 0.498407 0.577532 0.510629 0.708058 0.487761 0.124502 0.960932 0.247203 -0.301769 0.951811 -0.054687 -0.650721 0.681385 -0.335077 -0.826223 0.224514 -0.516672 -0.781907 -0.292279 -0.550631 -0.532880 -0.728886 -0.429841 -0.148377 -0.970746 -0.188776 0.269237 -0.957017 0.107844 0.611155 -0.692979 0.382452 0.788270 -0.247116 0.563529 0.752611 0.265052 0.602763 0.656428 0.511846 0.554180 0.292839 0.858360 0.421265 -0.153258 0.972453 0.175636 -0.559832 0.820421 -0.116177 -0.814571 0.443599 -0.373757 -0.848428 -0.053323 -0.526617 -0.654905 -0.534159 -0.534577 -0.289132 -0.870765 -0.397707 0.150183 -0.976579 -0.154074 0.547795 -0.826166 0.131794 0.800345 -0.459240 0.385418 0.840979 0.029394 0.540268 0.790042 0.300093 0.534582 0.470400 0.708116 0.526589 0.023185 0.927291 0.373623 -0.430471 0.895123 0.115971 -0.765435 0.619034 -0.175802 -0.889743 0.175625 -0.421324 -0.771501 -0.312537 -0.554173 -0.445955 -0.713588 -0.540294 -0.002419 -0.922690 -0.385534 0.441665 -0.887421 -0.131970 0.770726 -0.618295 0.153925 0.898703 -0.184959 0.397647 0.897670 0.097092 0.429839 0.644042 0.531052 0.550630 0.218683 0.827851 0.516567 -0.264650 0.904337 0.334867 -0.673286 0.737372 0.054486 -0.894372 0.372755 -0.247291 -0.868525 -0.088118 -0.487749 -0.605897 -0.519207 -0.602755 -0.180141 -0.806157 -0.563613 0.294604 -0.875675 -0.382625 0.694255 -0.711577 -0.108021 0.914928 -0.356799 0.188682 0.965905 -0.072925 0.248413 0.798950 0.351598 0.487912 0.420929 0.692087 0.586374 -0.068733 0.854527 0.514840 -0.536715 0.791898 0.291266 -0.853649 0.520337 -0.023097 -0.932752 0.115501 -0.341515 -0.754993 -0.310647 -0.577480 -0.372010 -0.643404 -0.669059 0.111817 -0.796505 -0.594202 0.569027 -0.732260 -0.374171 0.880991 -0.468412 -0.066666 0.982156 -0.187917 0.007487 0.919039 0.196220 0.341854 0.614379 0.543720 0.571759 0.146437 0.760039 0.633164 -0.358866 0.783627 0.507093 -0.762281 0.606033 0.227270 -0.952356 0.276358 -0.129011 -0.878624 -0.113388 -0.463857 -0.564770 -0.456715 -0.687347 -0.098287 -0.663275 -0.741894 0.396419 -0.681280 -0.615393 0.790678 -0.507836 -0.341950 0.935653 -0.231920 -0.266020 0.987783 0.090120 0.127131 0.780670 0.410239 0.471442 0.365409 0.642746 0.673316 -0.148091 0.722426 0.675404 -0.619273 0.624889 0.475410 -0.917625 0.376190 0.128239 -0.961722 0.046026 -0.270133 -0.742623 -0.274058 -0.611068 -0.323495 -0.498411 -0.804324 0.181920 -0.569999 -0.801253 0.641204 -0.472491 -0.604657 0.819711 -0.200827 -0.536416 0.990305 0.051387 -0.129057 0.900126 0.318368 0.297346 0.568754 0.529840 0.629117 0.081746 0.627416 0.774381 -0.429035 0.581842 0.690934 -0.822329 0.403924 0.400776 -0.989568 0.143200 -0.015757 -0.887029 -0.127161 -0.443857 -0.546708 -0.333498 -0.768043 -0.063163 -0.422595 -0.904115 0.435314 -0.373645 -0.819079 0.635682 -0.107971 -0.764363 0.917371 0.083500 -0.389176 0.955082 0.286490 0.075772 0.735067 0.448283 0.508644 0.311727 0.524913 0.792018 -0.202303 0.493442 0.845925 -0.665668 0.360367 0.653469 -0.949845 0.161969 0.267507 -0.977726 -0.045859 -0.204813 -0.745358 -0.205552 -0.634185 -0.319586 -0.275285 -0.906688 0.184578 -0.238988 -0.953318 0.396552 0.014642 -0.917895 0.770368 0.169811 -0.614571 0.935397 0.316352 -0.157966 0.845685 0.416342 0.333879 0.520510 0.442781 0.730079 0.044009 0.386996 0.921030 -0.454320 0.262410 0.851313 -0.836202 0.102497 0.538759 -0.996357 -0.048066 0.070440 -0.893662 -0.147307 -0.423874 -0.560408 -0.169013 -0.810788 -0.088824 -0.109235 -0.990039 0.127586 0.125044 -0.983914 0.564204 0.276856 -0.777833 0.842903 0.390564 -0.370099 0.889560 0.436514 0.134679 0.687998 0.401868 0.604286 0.287885 0.294553 0.911241 -0.204180 0.142446 0.968514 -0.652523 -0.013221 0.757654 -0.932610 -0.129300 0.336928 -0.968924 -0.173747 -0.176063 -0.755634 -0.135239 -0.640881 -0.354139 -0.025573 -0.934843 -0.139449 0.187594 -0.972298 0.324590 0.367421 -0.871575 0.691971 0.479696 -0.539507 0.866719 0.495019 -0.061278 0.800272 0.408311 0.439143 0.506095 0.241090 0.828096 0.060356 0.037414 0.997476 -0.415704 -0.147119 0.897522 -0.789982 -0.261276 0.554674 -0.959603 -0.273770 0.064902 -0.881139 -0.182354 -0.436282 -0.580068 -0.013256 -0.814460 -0.376932 0.185023 -0.907573 0.078765 0.414480 -0.906644 0.503386 0.554962 -0.662283 0.786611 0.569880 -0.237653 0.852823 0.454208 0.257659 0.681029 0.236772 0.692920 0.313618 -0.025339 0.949211 -0.151298 -0.260807 0.953461 -0.585706 -0.404249 0.702518 -0.869498 -0.416115 0.266125 -0.926490 -0.294433 -0.234363 -0.744912 -0.074037 -0.663042 -0.566870 0.119590 -0.815081 -0.151294 0.407361 -0.900648 0.297509 0.597356 -0.744751 0.662718 0.640295 -0.388364 0.848233 0.524077 0.076450 0.802676 0.277559 0.527893 0.534725 -0.034961 0.844303 0.114289 -0.329154 0.937334 -0.344214 -0.523779 0.779212 -0.714268 -0.564924 0.413137 -0.894923 -0.442283 -0.059142 -0.839665 -0.191136 -0.508360 -0.701827 0.004953 -0.712331 -0.352093 0.348121 -0.868817 0.089704 0.598677 -0.795951 0.507877 0.691545 -0.513641 0.792844 0.601945 -0.095187 0.868094 0.351916 0.350097 0.710771 0.006300 0.703396 0.360430 -0.342457 0.867648 -0.088891 -0.598839 0.795921 -0.513984 -0.691945 0.506984 -0.798347 -0.596757 0.080763 -0.866071 -0.340902 -0.365659 -0.781140 -0.142219 -0.607942 -0.516649 0.244972 -0.820404 -0.109608 0.557881 -0.822651 0.332529 0.714826 -0.615181 0.693775 0.674546 -0.252318 0.878277 0.446487 0.171112 0.835046 0.089553 0.542842 0.573099 -0.301488 0.762012 0.161624 -0.620464 0.767399 -0.287487 -0.779624 0.556361 -0.651274 -0.735494 0.186790 -0.831345 -0.501369 -0.239780 -0.807262 -0.306656 -0.504272 -0.641640 0.107625 -0.759417 -0.293256 0.477291 -0.828368 0.145064 0.705197 -0.694013 0.557861 0.731544 -0.391962 0.836038 0.548669 -0.001396 0.904604 0.203667 0.374447 0.743172 -0.212355 0.634508 0.393416 -0.587326 0.707300 -0.050466 -0.818793 0.571866 -0.467451 -0.843397 0.264898 -0.744256 -0.655218 -0.129507 -0.783451 -0.474925 -0.400812 -0.724832 -0.054043 -0.686803 -0.455007 0.360845 -0.814101 -0.046594 0.659955 -0.749859 0.392204 0.764566 -0.511482 0.745373 0.646720 -0.161780 0.918642 0.336629 0.206827 0.864363 -0.084082 0.495789 0.595475 -0.502776 0.626599 0.183658 -0.805863 0.562898 -0.259480 -0.910646 0.321550 -0.613586 -0.788993 -0.031665 -0.713405 -0.635119 -0.296104 -0.764441 -0.230226 -0.602184 -0.588770 0.213512 -0.779591 -0.234227 0.577953 -0.781734 0.204660 0.766714 -0.608493 0.611524 0.729744 -0.305797 0.878120 0.476205 0.046198 0.932550 0.072749 0.353635 0.758987 -0.373055 0.533637 0.403158 -0.740996 0.537017 -0.039120 -0.931194 0.362420 -0.448093 -0.892160 0.057130 -0.601281 -0.776489 -0.188484 -0.759193 -0.411084 -0.504615 -0.688612 0.041235 -0.723956 -0.409262 0.459459 -0.788291 0.003910 0.732420 -0.680842 0.440919 0.787680 -0.430292 0.785477 0.610226 -0.103197 0.945338 0.246697 0.213252 0.876939 -0.206184 0.434128 0.597820 -0.626846 0.499676 0.182701 -0.901681 0.391907 -0.256487 -0.956380 0.139825 -0.452668 -0.888291 -0.077658 -0.708669 -0.585287 -0.393989 -0.748415 -0.147604 -0.646597 -0.561847 0.307313 -0.768041 -0.199324 0.658044 -0.726118 0.242271 0.811259 -0.532131 0.645232 0.726045 -0.237769 0.901920 0.424721 0.078441 0.943267 -0.012602 0.331796 0.757611 -0.468842 0.454107 0.394400 -0.821251 0.412304 -0.048792 -0.974824 0.217571 -0.274633 -0.960872 0.036075 -0.614244 -0.741255 -0.270639 -0.763410 -0.343036 -0.547295 -0.682462 0.126774 -0.719843 -0.393492 0.542426 -0.742252 0.026010 0.793021 -0.608639 0.464000 0.811726 -0.354690 0.803509 0.593337 -0.048211 0.953569 0.195886 0.228766 0.873618 -0.274391 0.401872 0.584747 -0.691273 0.424515 0.164352 -0.942630 0.290580 -0.076238 -0.985593 0.150975 -0.479571 -0.866895 -0.136029 -0.730643 -0.533030 -0.426661 -0.762261 -0.073783 -0.643051 -0.566270 0.387704 -0.727340 -0.195412 0.728054 -0.657078 0.251072 0.856439 -0.451081 0.653893 0.738513 -0.164383 0.905300 0.405551 0.126333 0.937764 -0.053568 0.343116 0.742282 -0.515830 0.427711 0.371089 -0.857080 0.357361 0.131043 -0.955693 0.263589 -0.311225 -0.950313 0.006718 -0.649829 -0.703908 -0.286766 -0.793977 -0.282810 -0.538163 -0.705259 0.199913 -0.680180 -0.407746 0.615005 -0.674916 0.018787 0.851595 -0.523864 0.460309 0.846528 -0.267406 0.798805 0.601032 0.025913 0.943594 0.180528 0.277562 0.855624 -0.302511 0.419995 0.558216 -0.718511 0.414893 0.333874 -0.867474 0.368806 -0.118717 -0.981107 0.152759 -0.523993 -0.841548 -0.131255 -0.773155 -0.486402 -0.406994 -0.799511 -0.011157 -0.600548 -0.596294 0.456723 -0.660180 -0.218181 0.792095 -0.570073 0.233603 0.905445 -0.354400 0.638316 0.766511 -0.070806 0.887723 0.412274 0.204886 0.914887 -0.062687 0.398813 0.712233 -0.531194 0.458866 0.516675 -0.722258 0.459772 0.084469 -0.951871 0.294630 -0.360704 -0.932086 0.033301 -0.699259 -0.668212 -0.254025 -0.840361 -0.231253 -0.490220 -0.746390 0.261409 -0.612019 -0.442844 0.677768 -0.586959 -0.011178 0.906572 -0.421903 0.433145 0.886819 -0.161049 0.771389 0.623788 0.125888 0.913031 0.187638 0.362168 0.819912 -0.305057 0.484443 0.664306 -0.527277 0.529789 0.282557 -0.860542 0.423826 -0.171774 -0.964981 0.198255 -0.576687 -0.812383 -0.086406 -0.823402 -0.443746 -0.353693 -0.845791 0.041817 -0.531873 -0.638119 0.513964 -0.573276 -0.256321 0.846292 -0.467001 0.197281 0.950100 -0.241641 0.601413 0.797807 0.042495 0.848078 0.430107 0.309470 0.871198 -0.054824 0.487861 0.764158 -0.295624 0.573297 0.459108 -0.711552 0.531896 0.027409 -0.934951 0.353716 -0.415195 -0.905618 0.086427 -0.749804 -0.631265 -0.198240 -0.886527 -0.185593 -0.423821 -0.788795 0.311641 -0.529795 -0.483095 0.727048 -0.487873 -0.051580 0.949506 -0.309480 0.390190 0.919753 -0.042498 0.724149 0.645921 0.241648 0.861057 0.201190 0.467016 0.808380 -0.044618 0.586967 0.599578 -0.515683 0.612026 0.219906 -0.843398 0.490227 -0.229061 -0.939679 0.254037 -0.626857 -0.778423 -0.033282 -0.866580 -0.402797 -0.294607 -0.883843 0.086298 -0.459755 -0.674169 0.557507 -0.484440 -0.294052 0.884512 -0.362177 0.154486 0.979941 -0.125898 0.551410 0.818542 0.161045 0.790690 0.443625 0.421907 0.795072 0.207067 0.570074 0.693676 -0.288091 0.660164 0.390068 -0.698017 0.600515 -0.034698 -0.912787 0.406958 -0.466844 -0.874548 0.131238 -0.790332 -0.593334 -0.152743 -0.918212 -0.144573 -0.368762 -0.816170 0.351216 -0.458818 -0.511765 0.760967 -0.398780 -0.086850 0.974929 -0.204868 0.344647 0.936058 0.070816 0.667339 0.655021 0.354408 0.728122 0.441939 0.523955 0.736419 -0.045790 0.674974 0.525608 -0.510982 0.680171 0.151859 -0.829100 0.538081 -0.284891 -0.914699 0.286641 -0.667519 -0.744561 -0.006837 -0.893218 -0.364197 -0.263670 -0.901321 0.124314 -0.414929 -0.689716 0.589827 -0.419995 -0.315365 0.907480 -0.277533 0.121191 0.992293 -0.025855 0.503022 0.821838 0.267492 0.616136 0.645662 0.451107 0.728188 0.194782 0.657116 0.618851 -0.296581 0.727367 0.317176 -0.697052 0.643054 -0.096347 -0.899272 0.426646 -0.510995 -0.848754 0.136016 -0.815432 -0.558818 -0.150976 -0.927795 -0.107196 -0.357360 -0.817878 0.384872 -0.427725 -0.515310 0.785306 -0.343147 -0.101476 0.986780 -0.126362 0.312589 0.935557 0.164378 0.471065 0.807603 0.354788 0.673816 0.418852 0.608715 0.666461 -0.069804 0.742265 0.450878 -0.527871 0.719765 0.084410 -0.832776 0.547137 -0.335047 -0.902550 0.270459 -0.694982 -0.718114 -0.036207 -0.898580 -0.328773 -0.290622 -0.891017 0.160946 -0.424482 -0.674378 0.619491 -0.401802 -0.307059 0.923807 -0.228682 0.112187 0.992512 0.048305 0.306307 0.921722 0.237916 0.581519 0.615229 0.532287 0.669510 0.156086 0.726219 0.546881 -0.333257 0.768024 0.246072 -0.722191 0.646443 -0.152884 -0.906416 0.393745 -0.543227 -0.836009 0.077415 -0.819964 -0.529388 -0.217735 -0.908419 -0.068781 -0.412364 -0.784731 0.421900 -0.454090 -0.482395 0.810710 -0.331728 -0.082973 0.993469 -0.078331 0.135857 0.985325 0.103328 0.461786 0.775546 0.430444 0.632354 0.369342 0.680966 0.602430 -0.125018 0.788320 0.379792 -0.576016 0.723853 0.023293 -0.863154 0.504402 -0.372096 -0.908905 0.188245 -0.700186 -0.700100 -0.139998 -0.872286 -0.292359 -0.391973 -0.841736 0.204513 -0.499655 -0.616937 0.656490 -0.434062 -0.258903 0.942090 -0.213155 -0.026190 0.998608 -0.045785 0.326603 0.894175 0.306239 0.561864 0.560003 0.608856 0.617556 0.085341 0.781883 0.478906 -0.403913 0.779425 0.182217 -0.777655 0.601705 -0.194019 -0.935451 0.295447 -0.549142 -0.833731 -0.057747 -0.787148 -0.498765 -0.362811 -0.843256 -0.020594 -0.537118 -0.702277 0.471374 -0.533491 -0.402842 0.844323 -0.353322 -0.167448 0.964006 -0.206526 0.187699 0.968751 0.162147 0.466220 0.721569 0.511837 0.594828 0.289053 0.750085 0.539769 -0.214263 0.814089 0.315183 -0.655251 0.686517 -0.020093 -0.916151 0.400329 -0.376963 -0.925704 0.031147 -0.659191 -0.679576 -0.321936 -0.789782 -0.243308 -0.563068 -0.733001 0.264815 -0.626564 -0.504709 0.706859 -0.495600 -0.275623 0.885463 -0.374150 0.057445 0.998347 0.001770 0.354827 0.848626 0.392341 0.538260 0.477739 0.694292 0.559860 -0.015925 0.828434 0.413735 -0.502413 0.759213 0.137650 -0.852757 0.503844 -0.195732 -0.972137 0.128994 -0.497004 -0.826190 -0.265325 -0.684013 -0.452585 -0.572095 -0.705301 0.047572 -0.707310 -0.555286 0.537837 -0.634341 -0.339596 0.768419 -0.542409 -0.052035 0.983977 -0.170532 0.237653 0.937844 0.252921 0.452986 0.644804 0.615655 0.537913 0.183227 0.822847 0.470228 -0.325737 0.820232 0.266989 -0.748161 0.607431 -0.019019 -0.970814 0.239078 -0.311773 -0.931480 -0.187464 -0.531726 -0.638145 -0.556811 -0.618206 -0.169476 -0.767528 -0.547455 0.346288 -0.761825 -0.349673 0.619287 -0.703002 -0.128911 0.928024 -0.349504 0.125218 0.987489 0.095839 0.345161 0.785152 0.514198 0.473641 0.376342 0.796260 0.477387 -0.131593 0.868783 0.354939 -0.605916 0.711957 0.137464 -0.920780 0.365058 -0.118003 -0.989671 -0.081409 -0.342570 -0.790633 -0.507490 -0.474336 -0.375698 -0.796151 -0.476745 0.141664 -0.867552 -0.297523 0.446320 -0.843966 -0.160683 0.834364 -0.527274 0.030049 0.996677 -0.075711 0.223341 0.893741 0.389031 0.368602 0.555731 0.745182 0.428339 0.071979 0.900747 0.386848 -0.431712 0.814845 0.254111 -0.823096 0.507878 0.064193 -0.996218 0.058557 -0.132385 -0.900752 -0.413667 -0.281748 -0.559402 -0.779543 -0.342301 -0.064840 -0.937350 -0.178818 0.259707 -0.948987 -0.135331 0.708782 -0.692324 -0.032844 0.965892 -0.256853 0.100355 0.965962 0.238427 0.228898 0.712923 0.662832 0.319448 0.274848 0.906869 0.348581 -0.234445 0.907484 0.308261 -0.682472 0.662727 0.208174 -0.949705 0.233933 0.074209 -0.960953 -0.266577 -0.057502 -0.708969 -0.702891 -0.150454 -0.260765 -0.953606 0.001965 0.071596 -0.997432 -0.044336 0.559465 -0.827667 -0.046480 0.897558 -0.438440 -0.004640 0.998065 0.062006 0.069338 0.838773 0.540048 0.155711 0.464379 0.871841 0.232035 -0.027324 0.972324 0.278519 -0.509178 0.814349 0.282676 -0.854335 0.436125 0.242666 -0.967924 -0.065093 0.168506 -0.814658 -0.554921 0.080121 -0.433196 -0.897732 0.225161 -0.105366 -0.968608 0.110965 0.396981 -0.911094 0.003960 0.797053 -0.603896 -0.066831 0.988693 -0.134236 -0.083427 0.925111 0.370417 -0.042667 0.626846 0.777974 0.044183 0.172905 0.983947 0.154744 -0.319452 0.934882 0.260661 -0.721925 0.640999 0.333983 -0.925961 0.176213 0.354204 -0.872380 -0.336887 0.314547 -0.571708 -0.757767 0.454058 -0.262137 -0.851537 0.312812 0.232009 -0.921043 0.122982 0.672602 -0.729713 -0.062452 0.940747 -0.333310 -0.193986 0.968124 0.158447 -0.238512 0.751749 0.614805 -0.186028 0.350460 0.917917 -0.050513 -0.131648 0.990009 0.133685 -0.569769 0.810858 0.319210 -0.847513 0.424059 0.456453 -0.886965 -0.070311 0.506619 -0.673028 -0.538860 0.644522 -0.396468 -0.653761 0.528017 0.071669 -0.846204 0.298310 0.532787 -0.791928 0.020379 0.860993 -0.508208 -0.229713 0.970341 -0.075302 -0.386712 0.835945 0.389423 -0.411739 0.496214 0.764357 -0.299599 0.040187 0.953218 -0.078819 -0.414363 0.906692 0.194558 -0.748139 0.634378 0.449018 -0.869675 0.205055 0.614938 -0.741821 -0.267494 0.760689 -0.510481 -0.400951 0.718073 -0.080771 -0.691265 0.502158 0.384600 -0.774545 0.174222 0.757632 -0.629000 -0.174548 0.938745 -0.297138 -0.450874 0.883197 0.129134 -0.584065 0.609298 0.536306 -0.541548 0.190069 0.818901 -0.334645 -0.265949 0.904038 -0.015644 -0.640070 0.768157 0.333223 -0.831714 0.444087 0.618583 -0.785559 0.015871 0.784412 -0.606823 -0.128309 0.850607 -0.224065 -0.475671 0.699474 0.232939 -0.675629 0.373736 0.637926 -0.673329 -0.035216 0.881263 -0.471313 -0.416004 0.900443 -0.127058 -0.668874 0.694184 0.265924 -0.730028 0.318913 0.604444 -0.584830 -0.127483 0.801075 -0.270095 -0.529282 0.804307 0.133785 -0.780086 0.611202 0.520535 -0.809941 0.270258 0.715350 -0.686754 0.129007 0.905837 -0.357378 -0.227465 0.857931 0.080883 -0.507358 0.584845 0.506844 -0.633297 0.163550 0.803986 -0.571714 -0.289708 0.894013 -0.341774 -0.653948 0.756502 -0.007527 -0.835295 0.430671 0.341766 -0.788390 0.002563 0.615170 -0.525444 -0.416754 0.741771 -0.113314 -0.717403 0.687381 0.340944 -0.817618 0.463959 0.566272 -0.750122 0.341545 0.877341 -0.479317 0.022981 0.954073 -0.069069 -0.291504 0.774320 0.367639 -0.515045 0.388811 0.710580 -0.586431 -0.095062 0.867722 -0.487875 -0.546182 0.799982 -0.248423 -0.846239 0.528633 0.066530 -0.918774 0.126537 0.373956 -0.745819 -0.301472 0.594028 -0.371323 -0.643848 0.669013 0.108335 -0.809145 0.577537 0.357874 -0.796246 0.487768 0.769934 -0.588292 0.247212 0.975175 -0.214576 -0.054680 0.915461 0.222838 -0.335074 0.607552 0.603265 -0.516674 0.137838 0.823287 -0.550635 -0.364788 0.825931 -0.429846 -0.766498 0.613874 -0.188783 -0.963420 0.245346 0.107833 -0.905720 -0.182784 0.382442 -0.608150 -0.559102 0.563523 -0.146772 -0.784305 0.602764 0.115053 -0.824408 0.554179 0.596938 -0.682791 0.421262 0.918796 -0.353505 0.175635 0.990422 0.074617 -0.116172 0.791456 0.483642 -0.373749 0.378038 0.761424 -0.526612 -0.135138 0.834244 -0.534579 -0.609535 0.685776 -0.397715 -0.920832 0.358227 -0.154084 -0.989380 -0.061318 0.131787 -0.797890 -0.463495 0.385415 -0.395039 -0.743004 0.540268 -0.135140 -0.834240 0.534584 0.378039 -0.761436 0.526594 0.791461 -0.483725 0.373630 0.990434 -0.074763 0.115977 0.918818 0.353367 -0.175799 0.596972 0.682723 -0.421323 0.115093 0.824405 -0.554175 -0.395001 0.743002 -0.540299 -0.797860 0.463441 -0.385540 -0.989361 0.061219 -0.131974 -0.920823 -0.358319 0.153922 -0.609535 -0.685817 0.397646 -0.364751 -0.825954 0.429834 0.137884 -0.823279 0.550636 0.607599 -0.603298 0.516580 0.915504 -0.222958 0.334876 0.975223 0.214409 0.054482 0.769996 0.588173 -0.247303 0.357945 0.796220 -0.487759 -0.146701 0.784324 -0.602755 -0.608084 0.559090 -0.563607 -0.905660 0.182708 -0.382620 -0.963371 -0.245453 -0.108023 -0.766461 -0.613954 0.188674 -0.546106 -0.800040 0.248403 -0.094977 -0.867716 0.487902 0.388907 -0.710583 0.586365 0.774412 -0.367743 0.514832 0.954163 0.068857 0.291260 0.877449 0.479113 -0.023098 0.566399 0.750041 -0.341512 0.108462 0.809174 -0.577472 -0.371205 0.643880 -0.669048 -0.745705 0.301426 -0.594194 -0.918670 -0.126654 -0.374170 -0.846154 -0.528752 -0.066672 -0.653814 -0.756618 0.007496 -0.289583 -0.894021 0.341861 0.163691 -0.803927 0.571757 0.584997 -0.506844 0.633157 0.858076 -0.081039 0.507088 0.905984 0.357127 0.227274 0.715517 0.686581 -0.129000 0.341122 0.817607 -0.463849 -0.113138 0.717464 -0.687346 -0.525267 0.416752 -0.741898 -0.788213 -0.002679 -0.615396 -0.835135 -0.430839 -0.341946 -0.668675 -0.694338 -0.266024 -0.415850 -0.900504 0.127130 -0.035066 -0.881197 0.471446 0.373920 -0.637822 0.673325 0.699677 -0.232956 0.675413 0.850802 0.223868 0.475415 0.784601 0.606594 0.128237 0.520723 0.809860 -0.270137 0.133977 0.780153 -0.611073 -0.269881 0.529356 -0.804330 -0.584587 0.127450 -0.801258 -0.729786 -0.319054 -0.604662 -0.583781 -0.609469 -0.536421 -0.450653 -0.883320 -0.129068 -0.174352 -0.938718 0.297338 0.174469 -0.757478 0.629117 0.502473 -0.384500 0.774391 0.718394 0.080643 0.690946 0.760963 0.510206 0.400781 0.618794 0.785395 -0.015759 0.333389 0.831770 -0.443860 -0.015465 0.640214 -0.768041 -0.334397 0.266007 -0.904112 -0.541247 -0.190159 -0.819080 -0.411362 -0.496514 -0.764366 -0.386385 -0.836203 -0.389193 -0.229442 -0.970371 0.075746 0.020689 -0.860743 0.508619 0.298730 -0.532441 0.792001 0.528495 -0.071541 0.845917 0.644931 0.396291 0.653466 0.615197 0.741603 0.267502 0.449143 0.869666 -0.204821 0.194654 0.748274 -0.634189 -0.078627 0.414416 -0.906685 -0.299275 -0.040343 -0.953314 -0.185610 -0.350808 -0.917869 -0.238129 -0.752114 -0.614507 -0.193724 -0.968270 -0.157876 -0.062251 -0.940527 0.333965 0.123259 -0.672105 0.730124 0.313211 -0.231556 0.921021 0.454471 0.262274 0.851274 0.506898 0.672927 0.538724 0.456555 0.886904 0.070416 0.319242 0.847582 -0.423897 0.133810 0.569810 -0.810809 -0.050208 0.131492 -0.990045 0.044511 -0.173102 -0.983898 -0.042329 -0.627119 -0.777772 -0.083210 -0.925295 -0.370007 -0.066747 -0.988625 0.134777 0.004029 -0.796701 0.604360 0.111150 -0.396518 0.911274 0.225454 0.105672 0.968506 0.314811 0.571762 0.757616 0.354322 0.872336 0.336876 0.333989 0.925977 -0.176118 0.260699 0.721975 -0.640928 0.154933 0.319407 -0.934866 0.232201 0.027093 -0.972291 0.155920 -0.464693 -0.871636 0.069469 -0.839032 -0.539629 -0.004637 -0.998101 -0.061429 -0.046519 -0.897279 0.439006 -0.044274 -0.558958 0.828013 0.002188 -0.071101 0.997467 0.080406 0.433476 0.897571 0.168695 0.814732 0.554755 0.242705 0.967920 0.064996 0.282654 0.854309 -0.436190 0.278567 0.509075 -0.814397 0.348683 0.233916 -0.907581 0.319546 -0.275457 -0.906650 0.228901 -0.713428 -0.662288 0.100217 -0.966166 -0.237655 -0.033054 -0.965670 0.257660 -0.135456 -0.708176 0.692921 -0.178743 -0.258933 0.949213 -0.150207 0.261432 0.953463 -0.057229 0.709363 0.702516 0.074388 0.961066 0.266118 0.208260 0.949576 -0.234376 0.308329 0.682123 -0.663055 0.387008 0.431093 -0.815098 0.428427 -0.072697 -0.900647 0.368558 -0.556362 -0.744732 0.223134 -0.894097 -0.388332 0.029729 -0.996627 0.076488 -0.160978 -0.833894 0.527928 -0.297641 -0.445566 0.844323 -0.342191 0.065640 0.937335 -0.281481 0.560020 0.779195 -0.132083 0.901053 0.413107 0.064452 0.996165 -0.059176 0.254316 0.822716 -0.508390 0.355205 0.605320 -0.712332 0.477527 0.130858 -0.868818 0.473616 -0.377028 -0.795951 0.344955 -0.785609 -0.513639 0.124876 -0.987596 -0.095183 -0.129279 -0.927748 0.350102 -0.349926 -0.618692 0.703400 -0.476786 -0.140910 0.867652 -0.474157 0.376406 0.795923 -0.342243 0.791098 0.506984 -0.117628 0.989768 0.080764 0.137810 0.920489 -0.365660 0.267413 0.747587 -0.607950 0.470480 0.324934 -0.820406 0.537942 -0.184031 -0.822649 0.452788 -0.645403 -0.615174 0.237280 -0.938104 -0.252307 -0.052478 -0.983850 0.171126 -0.339972 -0.767937 0.542855 -0.547644 -0.345561 0.762019 -0.618143 0.170276 0.767401 -0.531421 0.638795 0.556357 -0.311308 0.931772 0.186782 -0.018513 0.970648 -0.239791 0.138087 0.852415 -0.504303 0.414041 0.501826 -0.759434 0.559974 0.015279 -0.828369 0.538173 -0.478263 -0.693999 0.354582 -0.848915 -0.391938 0.057115 -0.998367 -0.001365 -0.275943 -0.885226 0.374474 -0.555503 -0.537394 0.634526 -0.705345 -0.047003 0.707304 -0.683847 0.453140 0.571855 -0.496651 0.826547 0.264873 -0.195276 0.972156 -0.129540 -0.019621 0.915967 -0.400774 0.315566 0.654783 -0.686787 0.539972 0.213674 -0.814109 0.594822 -0.289582 -0.749886 0.466040 -0.721913 -0.511515 0.187412 -0.968863 -0.161808 -0.167759 -0.963892 0.206808 -0.504965 -0.706548 0.495783 -0.733130 -0.264353 0.626608 -0.789723 0.243830 0.562926 -0.658922 0.680000 0.321594 -0.376535 0.925863 -0.031616 -0.193527 0.935411 -0.295893 0.182670 0.777301 -0.602026 0.479201 0.403373 -0.779523 0.617638 -0.085887 -0.781759 0.561749 -0.560408 -0.608589 0.326355 -0.894370 -0.305933 -0.026492 -0.998588 0.046054 -0.403125 -0.844108 0.353514 -0.702472 -0.470990 0.533575 -0.843289 0.021089 0.537046 -0.786967 0.499241 0.362549 -0.548757 0.834014 0.057330 -0.371631 0.909011 -0.188652 0.023789 0.862945 -0.504738 0.380176 0.575573 -0.724005 0.602614 0.124504 -0.788261 0.632331 -0.369771 -0.680755 0.461607 -0.775799 -0.430179 0.135594 -0.985387 -0.103089 -0.259181 -0.941974 0.213330 -0.617168 -0.656213 0.434153 -0.841849 -0.204099 0.499633 -0.872210 0.292827 0.391794 -0.699887 0.700466 0.139663 -0.542765 0.836271 -0.077823 -0.152339 0.906328 -0.394159 0.246531 0.721788 -0.646718 0.547133 0.332698 -0.768087 0.669525 -0.156615 -0.726091 0.581343 -0.615598 -0.532051 0.306023 -0.921884 -0.237657 -0.083288 -0.993424 0.078564 -0.482675 -0.810471 0.331906 -0.784908 -0.421482 0.454173 -0.908412 0.069314 0.412290 -0.819715 0.529882 0.217468 -0.694872 0.718225 0.036130 -0.334889 0.902573 -0.270576 0.084565 0.832692 -0.547241 0.450984 0.527716 -0.719812 0.666497 0.069642 -0.742247 0.673796 -0.418968 -0.608658 0.471019 -0.807658 -0.354725 0.112144 -0.992520 -0.048253 -0.307090 -0.923786 0.228727 -0.674398 -0.619439 0.401848 -0.891018 -0.160848 0.424517 -0.898536 0.328905 0.290611 -0.815350 0.558971 0.150852 -0.510816 0.848838 -0.136166 -0.096118 0.899237 -0.426771 0.317384 0.696909 -0.643106 0.618984 0.296391 -0.727331 0.728231 -0.194949 -0.657019 0.616107 -0.645766 -0.450998 0.312520 -0.935595 -0.164298 -0.101562 -0.986767 0.126400 -0.515399 -0.785248 0.343147 -0.817947 -0.384764 0.427690 -0.927806 0.107348 0.357284 -0.893150 0.364407 0.263611 -0.667351 0.744713 0.006705 -0.284660 0.914719 -0.286805 0.152080 0.828974 -0.538214 0.525751 0.510762 -0.680227 0.736458 0.045559 -0.674948 0.728074 -0.442112 -0.523875 0.502927 -0.821927 -0.267396 0.121083 -0.992303 0.025945 -0.315464 -0.907422 0.277610 -0.689790 -0.589701 0.420051 -0.901342 -0.124125 0.414941 -0.918184 0.144558 0.368837 -0.790322 0.593334 0.152796 -0.466844 0.874550 -0.131224 -0.034706 0.912777 -0.406980 0.390050 0.697993 -0.600555 0.693650 0.288065 -0.660204 0.795047 -0.207082 -0.570103 0.667331 -0.655020 -0.354426 0.344667 -0.936050 -0.070821 -0.086803 -0.974930 0.204881 -0.511706 -0.760986 0.398820 -0.816121 -0.351243 0.458885 -0.883832 -0.086333 0.459770 -0.866584 0.402770 0.294632 -0.626870 0.778412 0.033307 -0.229074 0.939680 -0.254020 0.219897 0.843403 -0.490222 0.599573 0.515688 -0.612028 0.808378 0.044622 -0.586970 0.790693 -0.443618 -0.421909 0.551422 -0.818533 -0.161048 0.154509 -0.979938 0.125893 -0.294023 -0.884524 0.362171 -0.674144 -0.557536 0.484442 -0.788780 -0.311659 0.529806 -0.886523 0.185573 0.423838 -0.749811 0.631250 0.198259 -0.415209 0.905613 -0.086413 0.027392 0.934953 -0.353711 0.459093 0.711559 -0.531900 0.764149 0.295633 -0.573305 0.861056 -0.201179 -0.467023 0.724159 -0.645909 -0.241651 0.390208 -0.919745 0.042499 -0.051556 -0.949506 0.309484 -0.483072 -0.727059 0.487880 -0.638110 -0.513965 0.573286 -0.845784 -0.041818 0.531884 -0.823398 0.443743 0.353705 -0.576689 0.812380 0.086417 -0.171784 0.964981 -0.198249 0.282542 0.860546 -0.423828 0.664292 0.527287 -0.529797 0.871191 0.054837 -0.487872 0.848082 -0.430094 -0.309478 0.601425 -0.797798 -0.042497 0.197295 -0.950096 0.241645 -0.256308 -0.846292 0.467008 -0.442843 -0.677802 0.586919 -0.746401 -0.261455 0.611986 -0.840382 0.231206 0.490207 -0.699288 0.668176 0.254042 -0.360738 0.932074 -0.033255 0.084437 0.951893 -0.294567 0.516654 0.722311 -0.459713 0.819910 0.305124 -0.484403 0.913050 -0.187578 -0.362153 0.771418 -0.623751 -0.125893 0.433171 -0.886811 0.161027 -0.011164 -0.906588 0.421869 -0.218281 -0.792049 0.570098 -0.596381 -0.456626 0.660169 -0.799547 0.011284 0.600497 -0.773122 0.486518 0.406920 -0.523902 0.841616 0.131187 -0.118606 0.981115 -0.152797 0.333967 0.867437 -0.368807 0.712290 0.531138 -0.458841 0.914907 0.062629 -0.398776 0.887709 -0.412326 -0.204843 0.638267 -0.766547 0.070853 0.233521 -0.905449 0.354444 0.018736 -0.851555 0.523930 -0.407795 -0.614912 0.674971 -0.705278 -0.199781 0.680199 -0.793947 0.282941 0.538138 -0.649757 0.703997 0.286713 -0.311143 0.950339 -0.006777 0.131102 0.955670 -0.263643 0.558239 0.718467 -0.414940 0.855621 0.302463 -0.420033 0.943580 -0.180570 -0.277582 0.798782 -0.601063 -0.025901 0.460272 -0.846533 0.267454 0.251066 -0.856440 0.451083 -0.195441 -0.728048 0.657076 -0.566307 -0.387681 0.727324 -0.762283 0.073814 0.643021 -0.730641 0.533054 0.426635 -0.479555 0.866904 0.136033 -0.076231 0.985600 -0.150936 0.371077 0.857108 -0.357305 0.742266 0.515887 -0.427669 0.937765 0.053632 -0.343103 0.905318 -0.405508 -0.126338 0.653910 -0.738500 0.164378 0.463775 -0.811788 0.354842 0.025709 -0.792948 0.608747 -0.393796 -0.542193 0.742261 -0.682661 -0.126417 0.719717 -0.763412 0.343416 0.547054 -0.614032 0.741531 0.270364 -0.274286 0.960964 -0.036280 0.164702 0.942547 -0.290651 0.584999 0.691091 -0.424464 0.873738 0.274184 -0.401752 0.953566 -0.196076 -0.228619 0.803391 -0.593484 0.048369 0.645001 -0.726178 0.237991 0.241934 -0.811218 0.532347 -0.199697 -0.657787 0.726249 -0.562139 -0.306862 0.768007 -0.748502 0.148139 0.646375 -0.708487 0.585741 0.393641 -0.452269 0.888525 0.077310 -0.048325 0.974796 -0.217803 0.394783 0.821030 -0.412378 0.757828 0.468539 -0.454056 0.943317 0.012302 -0.331666 0.901821 -0.424964 -0.078257 0.785244 -0.610475 0.103496 0.440529 -0.787725 0.430608 0.003435 -0.732200 0.681081 -0.409698 -0.458976 0.788346 -0.688853 -0.040589 0.723763 -0.759123 0.411710 0.504209 -0.600899 0.776901 0.188001 -0.255928 0.956472 -0.140223 0.183243 0.901480 -0.392116 0.598199 0.626472 -0.499692 0.877101 0.205763 -0.433999 0.945292 -0.247071 -0.213022 0.878001 -0.476447 -0.045960 0.611261 -0.729846 0.306079 0.204289 -0.766611 0.608748 -0.234619 -0.577623 0.781861 -0.589058 -0.213012 0.779511 -0.764505 0.230766 0.601896 -0.713200 0.635535 0.295703 -0.447691 0.892338 -0.057502 -0.038669 0.931122 -0.362653 0.403520 0.740751 -0.537085 0.759190 0.372735 -0.533572 0.932587 -0.073063 -0.353474 0.918598 -0.336905 -0.206573 0.745166 -0.646883 0.162082 0.391860 -0.764550 0.511770 -0.047006 -0.659724 0.750036 -0.455374 -0.360429 0.814079 -0.725025 0.054545 0.686560 -0.783384 0.475369 0.400416 -0.613272 0.789253 0.031256 -0.259033 0.910671 -0.321838 0.184087 0.805691 -0.563004 0.595774 0.502491 -0.626543 0.864492 0.083766 -0.495617 0.904668 -0.204197 -0.374005 0.835794 -0.549040 0.001934 0.557360 -0.731646 0.392484 0.144410 -0.704974 0.694375 -0.293906 -0.476772 0.828437 -0.642098 -0.106928 0.759129 -0.807364 0.307345 0.503689 -0.743947 0.655707 0.128810 -0.466822 0.843560 -0.265488 -0.049725 0.818615 -0.572186 0.394048 0.586893 -0.707307 0.743549 0.211803 -0.634251 0.835265 -0.090086 -0.542418 0.878172 -0.446909 -0.170547 0.693385 -0.674728 0.252902 0.331943 -0.714703 0.615641 -0.110256 -0.557471 0.822842 -0.517191 -0.244374 0.820241 -0.781408 0.142852 0.607450 -0.831234 0.501875 0.239108 -0.650802 0.735750 -0.187428 -0.286797 0.779579 -0.556780 0.162320 0.620147 -0.767509 0.573611 0.300996 -0.761822</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="1800" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="5889">0 0 0 0 0.083333 0 0 0.166667 0 0 0.250000 0 0 0.333333 0 0 0.416667 0 0 0.500000 0 0 0.583333 0 0 0.666667 0 0 0.750000 0 0 0.833333 0 0 0.916667 0 0 1.000000 0 0.006667 0 0 0.006667 0.083333 0 0.006667 0.166667 0 0.006667 0.250000 0 0.006667 0.333333 0 0.006667 0.416667 0 0.006667 0.500000 0 0.006667 0.583333 0 0.006667 0.666667 0 0.006667 0.750000 0 0.006667 0.833333 0 0.006667 0.916667 0 0.006667 1.000000 0 0.013333 0 0 0.013333 0.083333 0 0.013333 0.166667 0 0.013333 0.250000 0 0.013333 0.333333 0 0.013333 0.416667 0 0.013333 0.500000 0 0.013333 0.583333 0 0.013333 0.666667 0 0.013333 0.750000 0 0.013333 0.833333 0 0.013333 0.916667 0 0.013333 1.000000 0 0.020000 0 0 0.020000 0.083333 0 0.020000 0.166667 0 0.020000 0.250000 0 0.020000 0.333333 0 0.020000 0.416667 0 0.020000 0.500000 0 0.020000 0.583333 0 0.020000 0.666667 0 0.020000 0.750000 0 0.020000 0.833333 0 0.020000 0.916667 0 0.020000 1.000000 0 0.026667 0 0 0.026667 0.083333 0 0.026667 0.166667 0 0.026667 0.250000 0 0.026667 0.333333 0 0.026667 0.416667 0 0.026667 0.500000 0 0.026667 0.583333 0 0.026667 0.666667 0 0.026667 0.750000 0 0.026667 0.833333 0 0.026667 0.916667 0 0.026667 1.000000 0 0.033333 0 0 0.033333 0.083333 0 0.033333 0.166667 0 0.033333 0.250000 0 0.033333 0.333333 0 0.033333 0.416667 0 0.033333 0.500000 0 0.033333 0.583333 0 0.033333 0.666667 0 0.033333 0.750000 0 0.033333 0.833333 0 0.033333 0.916667 0 0.033333 1.000000 0 0.040000 0 0 0.040000 0.083333 0 0.040000 0.166667 0 0.040000 0.250000 0 0.040000 0.333333 0 0.040000 0.416667 0 0.040000 0.500000 0 0.040000 0.583333 0 0.040000 0.666667 0 0.040000 0.750000 0 0.040000 0.833333 0 0.040000 0.916667 0 0.040000 1.000000 0 0.046667 0 0 0.046667 0.083333 0 0.046667 0.166667 0 0.046667 0.250000 0 0.046667 0.333333 0 0.046667 0.416667 0 0.046667 0.500000 0 0.046667 0.583333 0 0.046667 0.666667 0 0.046667 0.750000 0 0.046667 0.833333 0 0.046667 0.916667 0 0.046667 1.000000 0 0.053333 0 0 0.053333 0.083333 0 0.053333 0.166667 0 0.053333 0.250000 0 0.053333 0.333333 0 0.053333 0.416667 0 0.053333 0.500000 0 0.053333 0.583333 0 0.053333 0.666667 0 0.053333 0.750000 0 0.053333 0.833333 0 0.053333 0.916667 0 0.053333 1.000000 0 0.060000 0 0 0.060000 0.083333 0 0.060000 0.166667 0 0.060000 0.250000 0 0.060000 0.333333 0 0.060000 0.416667 0 0.060000 0.500000 0 0.060000 0.583333 0 0.060000 0.666667 0 0.060000 0.750000 0 0.060000 0.833333 0 0.060000 0.916667 0 0.060000 1.000000 0 0.066667 0 0 0.066667 0.083333 0 0.066667 0.166667 0 0.066667 0.250000 0 0.066667 0.333333 0 0.066667 0.416667 0 0.066667 0.500000 0 0.066667 0.583333 0 0.066667 0.666667 0 0.066667 0.750000 0 0.066667 0.833333 0 0.066667 0.916667 0 0.066667 1.000000 0 0.073333 0 0 0.073333 0.083333 0 0.073333 0.166667 0 0.073333 0.250000 0 0.073333 0.333333 0 0.073333 0.416667 0 0.073333 0.500000 0 0.073333 0.583333 0 0.073333 0.666667 0 0.073333 0.750000 0 0.073333 0.833333 0 0.073333 0.916667 0 0.073333 1.000000 0 0.080000 0 0 0.080000 0.083333 0 0.080000 0.166667 0 0.080000 0.250000 0 0.080000 0.333333 0 0.080000 0.416667 0 0.080000 0.500000 0 0.080000 0.583333 0 0.080000 0.666667 0 0.080000 0.750000 0 0.080000 0.833333 0 0.080000 0.916667 0 0.080000 1.000000 0 0.086667 0 0 0.086667 0.083333 0 0.086667 0.166667 0 0.086667 0.250000 0 0.086667 0.333333 0 0.086667 0.416667 0 0.086667 0.500000 0 0.086667 0.583333 0 0.086667 0.666667 0 0.086667 0.750000 0 0.086667 0.833333 0 0.086667 0.916667 0 0.086667 1.000000 0 0.093333 0 0 0.093333 0.083333 0 0.093333 0.166667 0 0.093333 0.250000 0 0.093333 0.333333 0 0.093333 0.416667 0 0.093333 0.500000 0 0.093333 0.583333 0 0.093333 0.666667 0 0.093333 0.750000 0 0.093333 0.833333 0 0.093333 0.916667 0 0.093333 1.000000 0 0.100000 0 0 0.100000 0.083333 0 0.100000 0.166667 0 0.100000 0.250000 0 0.100000 0.333333 0 0.100000 0.416667 0 0.100000 0.500000 0 0.100000 0.583333 0 0.100000 0.666667 0 0.100000 0.750000 0 0.100000 0.833333 0 0.100000 0.916667 0 0.100000 1.000000 0 0.106667 0 0 0.106667 0.083333 0 0.106667 0.166667 0 0.106667 0.250000 0 0.106667 0.333333 0 0.106667 0.416667 0 0.106667 0.500000 0 0.106667 0.583333 0 0.106667 0.666667 0 0.106667 0.750000 0 0.106667 0.833333 0 0.106667 0.916667 0 0.106667 1.000000 0 0.113333 0 0 0.113333 0.083333 0 0.113333 0.166667 0 0.113333 0.250000 0 0.113333 0.333333 0 0.113333 0.416667 0 0.113333 0.500000 0 0.113333 0.583333 0 0.113333 0.666667 0 0.113333 0.750000 0 0.113333 0.833333 0 0.113333 0.916667 0 0.113333 1.000000 0 0.120000 0 0 0.120000 0.083333 0 0.120000 0.166667 0 0.120000 0.250000 0 0.120000 0.333333 0 0.120000 0.416667 0 0.120000 0.500000 0 0.120000 0.583333 0 0.120000 0.666667 0 0.120000 0.750000 0 0.120000 0.833333 0 0.120000 0.916667 0 0.120000 1.000000 0 0.126667 0 0 0.126667 0.083333 0 0.126667 0.166667 0 0.126667 0.250000 0 0.126667 0.333333 0 0.126667 0.416667 0 0.126667 0.500000 0 0.126667 0.583333 0 0.126667 0.666667 0 0.126667 0.750000 0 0.126667 0.833333 0 0.126667 0.916667 0 0.126667 1.000000 0 0.133333 0 0 0.133333 0.083333 0 0.133333 0.166667 0 0.133333 0.250000 0 0.133333 0.333333 0 0.133333 0.416667 0 0.133333 0.500000 0 0.133333 0.583333 0 0.133333 0.666667 0 0.133333 0.750000 0 0.133333 0.833333 0 0.133333 0.916667 0 0.133333 1.000000 0 0.140000 0 0 0.140000 0.083333 0 0.140000 0.166667 0 0.140000 0.250000 0 0.140000 0.333333 0 0.140000 0.416667 0 0.140000 0.500000 0 0.140000 0.583333 0 0.140000 0.666667 0 0.140000 0.750000 0 0.140000 0.833333 0 0.140000 0.916667 0 0.140000 1.000000 0 0.146667 0 0 0.146667 0.083333 0 0.146667 0.166667 0 0.146667 0.250000 0 0.146667 0.333333 0 0.146667 0.416667 0 0.146667 0.500000 0 0.146667 0.583333 0 0.146667 0.666667 0 0.146667 0.750000 0 0.146667 0.833333 0 0.146667 0.916667 0 0.146667 1.000000 0 0.153333 0 0 0.153333 0.083333 0 0.153333 0.166667 0 0.153333 0.250000 0 0.153333 0.333333 0 0.153333 0.416667 0 0.153333 0.500000 0 0.153333 0.583333 0 0.153333 0.666667 0 0.153333 0.750000 0 0.153333 0.833333 0 0.153333 0.916667 0 0.153333 1.000000 0 0.160000 0 0 0.160000 0.083333 0 0.160000 0.166667 0 0.160000 0.250000 0 0.160000 0.333333 0 0.160000 0.416667 0 0.160000 0.500000 0 0.160000 0.583333 0 0.160000 0.666667 0 0.160000 0.750000 0 0.160000 0.833333 0 0.160000 0.916667 0 0.160000 1.000000 0 0.166667 0 0 0.166667 0.083333 0 0.166667 0.166667 0 0.166667 0.250000 0 0.166667 0.333333 0 0.166667 0.416667 0 0.166667 0.500000 0 0.166667 0.583333 0 0.166667 0.666667 0 0.166667 0.750000 0 0.166667 0.833333 0 0.166667 0.916667 0 0.166667 1.000000 0 0.173333 0 0 0.173333 0.083333 0 0.173333 0.166667 0 0.173333 0.250000 0 0.173333 0.333333 0 0.173333 0.416667 0 0.173333 0.500000 0 0.173333 0.583333 0 0.173333 0.666667 0 0.173333 0.750000 0 0.173333 0.833333 0 0.173333 0.916667 0 0.173333 1.000000 0 0.180000 0 0 0.180000 0.083333 0 0.180000 0.166667 0 0.180000 0.250000 0 0.180000 0.333333 0 0.180000 0.416667 0 0.180000 0.500000 0 0.180000 0.583333 0 0.180000 0.666667 0 0.180000 0.750000 0 0.180000 0.833333 0 0.180000 0.916667 0 0.180000 1.000000 0 0.186667 0 0 0.186667 0.083333 0 0.186667 0.166667 0 0.186667 0.250000 0 0.186667 0.333333 0 0.186667 0.416667 0 0.186667 0.500000 0 0.186667 0.583333 0 0.186667 0.666667 0 0.186667 0.750000 0 0.186667 0.833333 0 0.186667 0.916667 0 0.186667 1.000000 0 0.193333 0 0 0.193333 0.083333 0 0.193333 0.166667 0 0.193333 0.250000 0 0.193333 0.333333 0 0.193333 0.416667 0 0.193333 0.500000 0 0.193333 0.583333 0 0.193333 0.666667 0 0.193333 0.750000 0 0.193333 0.833333 0 0.193333 0.916667 0 0.193333 1.000000 0 0.200000 0 0 0.200000 0.083333 0 0.200000 0.166667 0 0.200000 0.250000 0 0.200000 0.333333 0 0.200000 0.416667 0 0.200000 0.500000 0 0.200000 0.583333 0 0.200000 0.666667 0 0.200000 0.750000 0 0.200000 0.833333 0 0.200000 0.916667 0 0.200000 1.000000 0 0.206667 0 0 0.206667 0.083333 0 0.206667 0.166667 0 0.206667 0.250000 0 0.206667 0.333333 0 0.206667 0.416667 0 0.206667 0.500000 0 0.206667 0.583333 0 0.206667 0.666667 0 0.206667 0.750000 0 0.206667 0.833333 0 0.206667 0.916667 0 0.206667 1.000000 0 0.213333 0 0 0.213333 0.083333 0 0.213333 0.166667 0 0.213333 0.250000 0 0.213333 0.333333 0 0.213333 0.416667 0 0.213333 0.500000 0 0.213333 0.583333 0 0.213333 0.666667 0 0.213333 0.750000 0 0.213333 0.833333 0 0.213333 0.916667 0 0.213333 1.000000 0 0.220000 0 0 0.220000 0.083333 0 0.220000 0.166667 0 0.220000 0.250000 0 0.220000 0.333333 0 0.220000 0.416667 0 0.220000 0.500000 0 0.220000 0.583333 0 0.220000 0.666667 0 0.220000 0.750000 0 0.220000 0.833333 0 0.220000 0.916667 0 0.220000 1.000000 0 0.226667 0 0 0.226667 0.083333 0 0.226667 0.166667 0 0.226667 0.250000 0 0.226667 0.333333 0 0.226667 0.416667 0 0.226667 0.500000 0 0.226667 0.583333 0 0.226667 0.666667 0 0.226667 0.750000 0 0.226667 0.833333 0 0.226667 0.916667 0 0.226667 1.000000 0 0.233333 0 0 0.233333 0.083333 0 0.233333 0.166667 0 0.233333 0.250000 0 0.233333 0.333333 0 0.233333 0.416667 0 0.233333 0.500000 0 0.233333 0.583333 0 0.233333 0.666667 0 0.233333 0.750000 0 0.233333 0.833333 0 0.233333 0.916667 0 0.233333 1.000000 0 0.240000 0 0 0.240000 0.083333 0 0.240000 0.166667 0 0.240000 0.250000 0 0.240000 0.333333 0 0.240000 0.416667 0 0.240000 0.500000 0 0.240000 0.583333 0 0.240000 0.666667 0 0.240000 0.750000 0 0.240000 0.833333 0 0.240000 0.916667 0 0.240000 1.000000 0 0.246667 0 0 0.246667 0.083333 0 0.246667 0.166667 0 0.246667 0.250000 0 0.246667 0.333333 0 0.246667 0.416667 0 0.246667 0.500000 0 0.246667 0.583333 0 0.246667 0.666667 0 0.246667 0.750000 0 0.246667 0.833333 0 0.246667 0.916667 0 0.246667 1.000000 0 0.253333 0 0 0.253333 0.083333 0 0.253333 0.166667 0 0.253333 0.250000 0 0.253333 0.333333 0 0.253333 0.416667 0 0.253333 0.500000 0 0.253333 0.583333 0 0.253333 0.666667 0 0.253333 0.750000 0 0.253333 0.833333 0 0.253333 0.916667 0 0.253333 1.000000 0 0.260000 0 0 0.260000 0.083333 0 0.260000 0.166667 0 0.260000 0.250000 0 0.260000 0.333333 0 0.260000 0.416667 0 0.260000 0.500000 0 0.260000 0.583333 0 0.260000 0.666667 0 0.260000 0.750000 0 0.260000 0.833333 0 0.260000 0.916667 0 0.260000 1.000000 0 0.266667 0 0 0.266667 0.083333 0 0.266667 0.166667 0 0.266667 0.250000 0 0.266667 0.333333 0 0.266667 0.416667 0 0.266667 0.500000 0 0.266667 0.583333 0 0.266667 0.666667 0 0.266667 0.750000 0 0.266667 0.833333 0 0.266667 0.916667 0 0.266667 1.000000 0 0.273333 0 0 0.273333 0.083333 0 0.273333 0.166667 0 0.273333 0.250000 0 0.273333 0.333333 0 0.273333 0.416667 0 0.273333 0.500000 0 0.273333 0.583333 0 0.273333 0.666667 0 0.273333 0.750000 0 0.273333 0.833333 0 0.273333 0.916667 0 0.273333 1.000000 0 0.280000 0 0 0.280000 0.083333 0 0.280000 0.166667 0 0.280000 0.250000 0 0.280000 0.333333 0 0.280000 0.416667 0 0.280000 0.500000 0 0.280000 0.583333 0 0.280000 0.666667 0 0.280000 0.750000 0 0.280000 0.833333 0 0.280000 0.916667 0 0.280000 1.000000 0 0.286667 0 0 0.286667 0.083333 0 0.286667 0.166667 0 0.286667 0.250000 0 0.286667 0.333333 0 0.286667 0.416667 0 0.286667 0.500000 0 0.286667 0.583333 0 0.286667 0.666667 0 0.286667 0.750000 0 0.286667 0.833333 0 0.286667 0.916667 0 0.286667 1.000000 0 0.293333 0 0 0.293333 0.083333 0 0.293333 0.166667 0 0.293333 0.250000 0 0.293333 0.333333 0 0.293333 0.416667 0 0.293333 0.500000 0 0.293333 0.583333 0 0.293333 0.666667 0 0.293333 0.750000 0 0.293333 0.833333 0 0.293333 0.916667 0 0.293333 1.000000 0 0.300000 0 0 0.300000 0.083333 0 0.300000 0.166667 0 0.300000 0.250000 0 0.300000 0.333333 0 0.300000 0.416667 0 0.300000 0.500000 0 0.300000 0.583333 0 0.300000 0.666667 0 0.300000 0.750000 0 0.300000 0.833333 0 0.300000 0.916667 0 0.300000 1.000000 0 0.306667 0 0 0.306667 0.083333 0 0.306667 0.166667 0 0.306667 0.250000 0 0.306667 0.333333 0 0.306667 0.416667 0 0.306667 0.500000 0 0.306667 0.583333 0 0.306667 0.666667 0 0.306667 0.750000 0 0.306667 0.833333 0 0.306667 0.916667 0 0.306667 1.000000 0 0.313333 0 0 0.313333 0.083333 0 0.313333 0.166667 0 0.313333 0.250000 0 0.313333 0.333333 0 0.313333 0.416667 0 0.313333 0.500000 0 0.313333 0.583333 0 0.313333 0.666667 0 0.313333 0.750000 0 0.313333 0.833333 0 0.313333 0.916667 0 0.313333 1.000000 0 0.320000 0 0 0.320000 0.083333 0 0.320000 0.166667 0 0.320000 0.250000 0 0.320000 0.333333 0 0.320000 0.416667 0 0.320000 0.500000 0 0.320000 0.583333 0 0.320000 0.666667 0 0.320000 0.750000 0 0.320000 0.833333 0 0.320000 0.916667 0 0.320000 1.000000 0 0.326667 0 0 0.326667 0.083333 0 0.326667 0.166667 0 0.326667 0.250000 0 0.326667 0.333333 0 0.326667 0.416667 0 0.326667 0.500000 0 0.326667 0.583333 0 0.326667 0.666667 0 0.326667 0.750000 0 0.326667 0.833333 0 0.326667 0.916667 0 0.326667 1.000000 0 0.333333 0 0 0.333333 0.083333 0 0.333333 0.166667 0 0.333333 0.250000 0 0.333333 0.333333 0 0.333333 0.416667 0 0.333333 0.500000 0 0.333333 0.583333 0 0.333333 0.666667 0 0.333333 0.750000 0 0.333333 0.833333 0 0.333333 0.916667 0 0.333333 1.000000 0 0.340000 0 0 0.340000 0.083333 0 0.340000 0.166667 0 0.340000 0.250000 0 0.340000 0.333333 0 0.340000 0.416667 0 0.340000 0.500000 0 0.340000 0.583333 0 0.340000 0.666667 0 0.340000 0.750000 0 0.340000 0.833333 0 0.340000 0.916667 0 0.340000 1.000000 0 0.346667 0 0 0.346667 0.083333 0 0.346667 0.166667 0 0.346667 0.250000 0 0.346667 0.333333 0 0.346667 0.416667 0 0.346667 0.500000 0 0.346667 0.583333 0 0.346667 0.666667 0 0.346667 0.750000 0 0.346667 0.833333 0 0.346667 0.916667 0 0.346667 1.000000 0 0.353333 0 0 0.353333 0.083333 0 0.353333 0.166667 0 0.353333 0.250000 0 0.353333 0.333333 0 0.353333 0.416667 0 0.353333 0.500000 0 0.353333 0.583333 0 0.353333 0.666667 0 0.353333 0.750000 0 0.353333 0.833333 0 0.353333 0.916667 0 0.353333 1.000000 0 0.360000 0 0 0.360000 0.083333 0 0.360000 0.166667 0 0.360000 0.250000 0 0.360000 0.333333 0 0.360000 0.416667 0 0.360000 0.500000 0 0.360000 0.583333 0 0.360000 0.666667 0 0.360000 0.750000 0 0.360000 0.833333 0 0.360000 0.916667 0 0.360000 1.000000 0 0.366667 0 0 0.366667 0.083333 0 0.366667 0.166667 0 0.366667 0.250000 0 0.366667 0.333333 0 0.366667 0.416667 0 0.366667 0.500000 0 0.366667 0.583333 0 0.366667 0.666667 0 0.366667 0.750000 0 0.366667 0.833333 0 0.366667 0.916667 0 0.366667 1.000000 0 0.373333 0 0 0.373333 0.083333 0 0.373333 0.166667 0 0.373333 0.250000 0 0.373333 0.333333 0 0.373333 0.416667 0 0.373333 0.500000 0 0.373333 0.583333 0 0.373333 0.666667 0 0.373333 0.750000 0 0.373333 0.833333 0 0.373333 0.916667 0 0.373333 1.000000 0 0.380000 0 0 0.380000 0.083333 0 0.380000 0.166667 0 0.380000 0.250000 0 0.380000 0.333333 0 0.380000 0.416667 0 0.380000 0.500000 0 0.380000 0.583333 0 0.380000 0.666667 0 0.380000 0.750000 0 0.380000 0.833333 0 0.380000 0.916667 0 0.380000 1.000000 0 0.386667 0 0 0.386667 0.083333 0 0.386667 0.166667 0 0.386667 0.250000 0 0.386667 0.333333 0 0.386667 0.416667 0 0.386667 0.500000 0 0.386667 0.583333 0 0.386667 0.666667 0 0.386667 0.750000 0 0.386667 0.833333 0 0.386667 0.916667 0 0.386667 1.000000 0 0.393333 0 0 0.393333 0.083333 0 0.393333 0.166667 0 0.393333 0.250000 0 0.393333 0.333333 0 0.393333 0.416667 0 0.393333 0.500000 0 0.393333 0.583333 0 0.393333 0.666667 0 0.393333 0.750000 0 0.393333 0.833333 0 0.393333 0.916667 0 0.393333 1.000000 0 0.400000 0 0 0.400000 0.083333 0 0.400000 0.166667 0 0.400000 0.250000 0 0.400000 0.333333 0 0.400000 0.416667 0 0.400000 0.500000 0 0.400000 0.583333 0 0.400000 0.666667 0 0.400000 0.750000 0 0.400000 0.833333 0 0.400000 0.916667 0 0.400000 1.000000 0 0.406667 0 0 0.406667 0.083333 0 0.406667 0.166667 0 0.406667 0.250000 0 0.406667 0.333333 0 0.406667 0.416667 0 0.406667 0.500000 0 0.406667 0.583333 0 0.406667 0.666667 0 0.406667 0.750000 0 0.406667 0.833333 0 0.406667 0.916667 0 0.406667 1.000000 0 0.413333 0 0 0.413333 0.083333 0 0.413333 0.166667 0 0.413333 0.250000 0 0.413333 0.333333 0 0.413333 0.416667 0 0.413333 0.500000 0 0.413333 0.583333 0 0.413333 0.666667 0 0.413333 0.750000 0 0.413333 0.833333 0 0.413333 0.916667 0 0.413333 1.000000 0 0.420000 0 0 0.420000 0.083333 0 0.420000 0.166667 0 0.420000 0.250000 0 0.420000 0.333333 0 0.420000 0.416667 0 0.420000 0.500000 0 0.420000 0.583333 0 0.420000 0.666667 0 0.420000 0.750000 0 0.420000 0.833333 0 0.420000 0.916667 0 0.420000 1.000000 0 0.426667 0 0 0.426667 0.083333 0 0.426667 0.166667 0 0.426667 0.250000 0 0.426667 0.333333 0 0.426667 0.416667 0 0.426667 0.500000 0 0.426667 0.583333 0 0.426667 0.666667 0 0.426667 0.750000 0 0.426667 0.833333 0 0.426667 0.916667 0 0.426667 1.000000 0 0.433333 0 0 0.433333 0.083333 0 0.433333 0.166667 0 0.433333 0.250000 0 0.433333 0.333333 0 0.433333 0.416667 0 0.433333 0.500000 0 0.433333 0.583333 0 0.433333 0.666667 0 0.433333 0.750000 0 0.433333 0.833333 0 0.433333 0.916667 0 0.433333 1.000000 0 0.440000 0 0 0.440000 0.083333 0 0.440000 0.166667 0 0.440000 0.250000 0 0.440000 0.333333 0 0.440000 0.416667 0 0.440000 0.500000 0 0.440000 0.583333 0 0.440000 0.666667 0 0.440000 0.750000 0 0.440000 0.833333 0 0.440000 0.916667 0 0.440000 1.000000 0 0.446667 0 0 0.446667 0.083333 0 0.446667 0.166667 0 0.446667 0.250000 0 0.446667 0.333333 0 0.446667 0.416667 0 0.446667 0.500000 0 0.446667 0.583333 0 0.446667 0.666667 0 0.446667 0.750000 0 0.446667 0.833333 0 0.446667 0.916667 0 0.446667 1.000000 0 0.453334 0 0 0.453334 0.083333 0 0.453334 0.166667 0 0.453334 0.250000 0 0.453334 0.333333 0 0.453334 0.416667 0 0.453334 0.500000 0 0.453334 0.583333 0 0.453334 0.666667 0 0.453334 0.750000 0 0.453334 0.833333 0 0.453334 0.916667 0 0.453334 1.000000 0 0.460000 0 0 0.460000 0.083333 0 0.460000 0.166667 0 0.460000 0.250000 0 0.460000 0.333333 0 0.460000 0.416667 0 0.460000 0.500000 0 0.460000 0.583333 0 0.460000 0.666667 0 0.460000 0.750000 0 0.460000 0.833333 0 0.460000 0.916667 0 0.460000 1.000000 0 0.466667 0 0 0.466667 0.083333 0 0.466667 0.166667 0 0.466667 0.250000 0 0.466667 0.333333 0 0.466667 0.416667 0 0.466667 0.500000 0 0.466667 0.583333 0 0.466667 0.666667 0 0.466667 0.750000 0 0.466667 0.833333 0 0.466667 0.916667 0 0.466667 1.000000 0 0.473334 0 0 0.473334 0.083333 0 0.473334 0.166667 0 0.473334 0.250000 0 0.473334 0.333333 0 0.473334 0.416667 0 0.473334 0.500000 0 0.473334 0.583333 0 0.473334 0.666667 0 0.473334 0.750000 0 0.473334 0.833333 0 0.473334 0.916667 0 0.473334 1.000000 0 0.480000 0 0 0.480000 0.083333 0 0.480000 0.166667 0 0.480000 0.250000 0 0.480000 0.333333 0 0.480000 0.416667 0 0.480000 0.500000 0 0.480000 0.583333 0 0.480000 0.666667 0 0.480000 0.750000 0 0.480000 0.833333 0 0.480000 0.916667 0 0.480000 1.000000 0 0.486667 0 0 0.486667 0.083333 0 0.486667 0.166667 0 0.486667 0.250000 0 0.486667 0.333333 0 0.486667 0.416667 0 0.486667 0.500000 0 0.486667 0.583333 0 0.486667 0.666667 0 0.486667 0.750000 0 0.486667 0.833333 0 0.486667 0.916667 0 0.486667 1.000000 0 0.493334 0 0 0.493334 0.083333 0 0.493334 0.166667 0 0.493334 0.250000 0 0.493334 0.333333 0 0.493334 0.416667 0 0.493334 0.500000 0 0.493334 0.583333 0 0.493334 0.666667 0 0.493334 0.750000 0 0.493334 0.833333 0 0.493334 0.916667 0 0.493334 1.000000 0 0.500000 0 0 0.500000 0.083333 0 0.500000 0.166667 0 0.500000 0.250000 0 0.500000 0.333333 0 0.500000 0.416667 0 0.500000 0.500000 0 0.500000 0.583333 0 0.500000 0.666667 0 0.500000 0.750000 0 0.500000 0.833333 0 0.500000 0.916667 0 0.500000 1.000000 0 0.506667 0 0 0.506667 0.083333 0 0.506667 0.166667 0 0.506667 0.250000 0 0.506667 0.333333 0 0.506667 0.416667 0 0.506667 0.500000 0 0.506667 0.583333 0 0.506667 0.666667 0 0.506667 0.750000 0 0.506667 0.833333 0 0.506667 0.916667 0 0.506667 1.000000 0 0.513334 0 0 0.513334 0.083333 0 0.513334 0.166667 0 0.513334 0.250000 0 0.513334 0.333333 0 0.513334 0.416667 0 0.513334 0.500000 0 0.513334 0.583333 0 0.513334 0.666667 0 0.513334 0.750000 0 0.513334 0.833333 0 0.513334 0.916667 0 0.513334 1.000000 0 0.520000 0 0 0.520000 0.083333 0 0.520000 0.166667 0 0.520000 0.250000 0 0.520000 0.333333 0 0.520000 0.416667 0 0.520000 0.500000 0 0.520000 0.583333 0 0.520000 0.666667 0 0.520000 0.750000 0 0.520000 0.833333 0 0.520000 0.916667 0 0.520000 1.000000 0 0.526667 0 0 0.526667 0.083333 0 0.526667 0.166667 0 0.526667 0.250000 0 0.526667 0.333333 0 0.526667 0.416667 0 0.526667 0.500000 0 0.526667 0.583333 0 0.526667 0.666667 0 0.526667 0.750000 0 0.526667 0.833333 0 0.526667 0.916667 0 0.526667 1.000000 0 0.533334 0 0 0.533334 0.083333 0 0.533334 0.166667 0 0.533334 0.250000 0 0.533334 0.333333 0 0.533334 0.416667 0 0.533334 0.500000 0 0.533334 0.583333 0 0.533334 0.666667 0 0.533334 0.750000 0 0.533334 0.833333 0 0.533334 0.916667 0 0.533334 1.000000 0 0.540000 0 0 0.540000 0.083333 0 0.540000 0.166667 0 0.540000 0.250000 0 0.540000 0.333333 0 0.540000 0.416667 0 0.540000 0.500000 0 0.540000 0.583333 0 0.540000 0.666667 0 0.540000 0.750000 0 0.540000 0.833333 0 0.540000 0.916667 0 0.540000 1.000000 0 0.546667 0 0 0.546667 0.083333 0 0.546667 0.166667 0 0.546667 0.250000 0 0.546667 0.333333 0 0.546667 0.416667 0 0.546667 0.500000 0 0.546667 0.583333 0 0.546667 0.666667 0 0.546667 0.750000 0 0.546667 0.833333 0 0.546667 0.916667 0 0.546667 1.000000 0 0.553334 0 0 0.553334 0.083333 0 0.553334 0.166667 0 0.553334 0.250000 0 0.553334 0.333333 0 0.553334 0.416667 0 0.553334 0.500000 0 0.553334 0.583333 0 0.553334 0.666667 0 0.553334 0.750000 0 0.553334 0.833333 0 0.553334 0.916667 0 0.553334 1.000000 0 0.560000 0 0 0.560000 0.083333 0 0.560000 0.166667 0 0.560000 0.250000 0 0.560000 0.333333 0 0.560000 0.416667 0 0.560000 0.500000 0 0.560000 0.583333 0 0.560000 0.666667 0 0.560000 0.750000 0 0.560000 0.833333 0 0.560000 0.916667 0 0.560000 1.000000 0 0.566667 0 0 0.566667 0.083333 0 0.566667 0.166667 0 0.566667 0.250000 0 0.566667 0.333333 0 0.566667 0.416667 0 0.566667 0.500000 0 0.566667 0.583333 0 0.566667 0.666667 0 0.566667 0.750000 0 0.566667 0.833333 0 0.566667 0.916667 0 0.566667 1.000000 0 0.573334 0 0 0.573334 0.083333 0 0.573334 0.166667 0 0.573334 0.250000 0 0.573334 0.333333 0 0.573334 0.416667 0 0.573334 0.500000 0 0.573334 0.583333 0 0.573334 0.666667 0 0.573334 0.750000 0 0.573334 0.833333 0 0.573334 0.916667 0 0.573334 1.000000 0 0.580000 0 0 0.580000 0.083333 0 0.580000 0.166667 0 0.580000 0.250000 0 0.580000 0.333333 0 0.580000 0.416667 0 0.580000 0.500000 0 0.580000 0.583333 0 0.580000 0.666667 0 0.580000 0.750000 0 0.580000 0.833333 0 0.580000 0.916667 0 0.580000 1.000000 0 0.586667 0 0 0.586667 0.083333 0 0.586667 0.166667 0 0.586667 0.250000 0 0.586667 0.333333 0 0.586667 0.416667 0 0.586667 0.500000 0 0.586667 0.583333 0 0.586667 0.666667 0 0.586667 0.750000 0 0.586667 0.833333 0 0.586667 0.916667 0 0.586667 1.000000 0 0.593334 0 0 0.593334 0.083333 0 0.593334 0.166667 0 0.593334 0.250000 0 0.593334 0.333333 0 0.593334 0.416667 0 0.593334 0.500000 0 0.593334 0.583333 0 0.593334 0.666667 0 0.593334 0.750000 0 0.593334 0.833333 0 0.593334 0.916667 0 0.593334 1.000000 0 0.600001 0 0 0.600001 0.083333 0 0.600001 0.166667 0 0.600001 0.250000 0 0.600001 0.333333 0 0.600001 0.416667 0 0.600001 0.500000 0 0.600001 0.583333 0 0.600001 0.666667 0 0.600001 0.750000 0 0.600001 0.833333 0 0.600001 0.916667 0 0.600001 1.000000 0 0.606667 0 0 0.606667 0.083333 0 0.606667 0.166667 0 0.606667 0.250000 0 0.606667 0.333333 0 0.606667 0.416667 0 0.606667 0.500000 0 0.606667 0.583333 0 0.606667 0.666667 0 0.606667 0.750000 0 0.606667 0.833333 0 0.606667 0.916667 0 0.606667 1.000000 0 0.613334 0 0 0.613334 0.083333 0 0.613334 0.166667 0 0.613334 0.250000 0 0.613334 0.333333 0 0.613334 0.416667 0 0.613334 0.500000 0 0.613334 0.583333 0 0.613334 0.666667 0 0.613334 0.750000 0 0.613334 0.833333 0 0.613334 0.916667 0 0.613334 1.000000 0 0.620001 0 0 0.620001 0.083333 0 0.620001 0.166667 0 0.620001 0.250000 0 0.620001 0.333333 0 0.620001 0.416667 0 0.620001 0.500000 0 0.620001 0.583333 0 0.620001 0.666667 0 0.620001 0.750000 0 0.620001 0.833333 0 0.620001 0.916667 0 0.620001 1.000000 0 0.626667 0 0 0.626667 0.083333 0 0.626667 0.166667 0 0.626667 0.250000 0 0.626667 0.333333 0 0.626667 0.416667 0 0.626667 0.500000 0 0.626667 0.583333 0 0.626667 0.666667 0 0.626667 0.750000 0 0.626667 0.833333 0 0.626667 0.916667 0 0.626667 1.000000 0 0.633334 0 0 0.633334 0.083333 0 0.633334 0.166667 0 0.633334 0.250000 0 0.633334 0.333333 0 0.633334 0.416667 0 0.633334 0.500000 0 0.633334 0.583333 0 0.633334 0.666667 0 0.633334 0.750000 0 0.633334 0.833333 0 0.633334 0.916667 0 0.633334 1.000000 0 0.640001 0 0 0.640001 0.083333 0 0.640001 0.166667 0 0.640001 0.250000 0 0.640001 0.333333 0 0.640001 0.416667 0 0.640001 0.500000 0 0.640001 0.583333 0 0.640001 0.666667 0 0.640001 0.750000 0 0.640001 0.833333 0 0.640001 0.916667 0 0.640001 1.000000 0 0.646667 0 0 0.646667 0.083333 0 0.646667 0.166667 0 0.646667 0.250000 0 0.646667 0.333333 0 0.646667 0.416667 0 0.646667 0.500000 0 0.646667 0.583333 0 0.646667 0.666667 0 0.646667 0.750000 0 0.646667 0.833333 0 0.646667 0.916667 0 0.646667 1.000000 0 0.653334 0 0 0.653334 0.083333 0 0.653334 0.166667 0 0.653334 0.250000 0 0.653334 0.333333 0 0.653334 0.416667 0 0.653334 0.500000 0 0.653334 0.583333 0 0.653334 0.666667 0 0.653334 0.750000 0 0.653334 0.833333 0 0.653334 0.916667 0 0.653334 1.000000 0 0.660001 0 0 0.660001 0.083333 0 0.660001 0.166667 0 0.660001 0.250000 0 0.660001 0.333333 0 0.660001 0.416667 0 0.660001 0.500000 0 0.660001 0.583333 0 0.660001 0.666667 0 0.660001 0.750000 0 0.660001 0.833333 0 0.660001 0.916667 0 0.660001 1.000000 0 0.666667 0 0 0.666667 0.083333 0 0.666667 0.166667 0 0.666667 0.250000 0 0.666667 0.333333 0 0.666667 0.416667 0 0.666667 0.500000 0 0.666667 0.583333 0 0.666667 0.666667 0 0.666667 0.750000 0 0.666667 0.833333 0 0.666667 0.916667 0 0.666667 1.000000 0 0.673334 0 0 0.673334 0.083333 0 0.673334 0.166667 0 0.673334 0.250000 0 0.673334 0.333333 0 0.673334 0.416667 0 0.673334 0.500000 0 0.673334 0.583333 0 0.673334 0.666667 0 0.673334 0.750000 0 0.673334 0.833333 0 0.673334 0.916667 0 0.673334 1.000000 0 0.680000 0 0 0.680000 0.083333 0 0.680000 0.166667 0 0.680000 0.250000 0 0.680000 0.333333 0 0.680000 0.416667 0 0.680000 0.500000 0 0.680000 0.583333 0 0.680000 0.666667 0 0.680000 0.750000 0 0.680000 0.833333 0 0.680000 0.916667 0 0.680000 1.000000 0 0.686667 0 0 0.686667 0.083333 0 0.686667 0.166667 0 0.686667 0.250000 0 0.686667 0.333333 0 0.686667 0.416667 0 0.686667 0.500000 0 0.686667 0.583333 0 0.686667 0.666667 0 0.686667 0.750000 0 0.686667 0.833333 0 0.686667 0.916667 0 0.686667 1.000000 0 0.693334 0 0 0.693334 0.083333 0 0.693334 0.166667 0 0.693334 0.250000 0 0.693334 0.333333 0 0.693334 0.416667 0 0.693334 0.500000 0 0.693334 0.583333 0 0.693334 0.666667 0 0.693334 0.750000 0 0.693334 0.833333 0 0.693334 0.916667 0 0.693334 1.000000 0 0.700000 0 0 0.700000 0.083333 0 0.700000 0.166667 0 0.700000 0.250000 0 0.700000 0.333333 0 0.700000 0.416667 0 0.700000 0.500000 0 0.700000 0.583333 0 0.700000 0.666667 0 0.700000 0.750000 0 0.700000 0.833333 0 0.700000 0.916667 0 0.700000 1.000000 0 0.706667 0 0 0.706667 0.083333 0 0.706667 0.166667 0 0.706667 0.250000 0 0.706667 0.333333 0 0.706667 0.416667 0 0.706667 0.500000 0 0.706667 0.583333 0 0.706667 0.666667 0 0.706667 0.750000 0 0.706667 0.833333 0 0.706667 0.916667 0 0.706667 1.000000 0 0.713334 0 0 0.713334 0.083333 0 0.713334 0.166667 0 0.713334 0.250000 0 0.713334 0.333333 0 0.713334 0.416667 0 0.713334 0.500000 0 0.713334 0.583333 0 0.713334 0.666667 0 0.713334 0.750000 0 0.713334 0.833333 0 0.713334 0.916667 0 0.713334 1.000000 0 0.720000 0 0 0.720000 0.083333 0 0.720000 0.166667 0 0.720000 0.250000 0 0.720000 0.333333 0 0.720000 0.416667 0 0.720000 0.500000 0 0.720000 0.583333 0 0.720000 0.666667 0 0.720000 0.750000 0 0.720000 0.833333 0 0.720000 0.916667 0 0.720000 1.000000 0 0.726667 0 0 0.726667 0.083333 0 0.726667 0.166667 0 0.726667 0.250000 0 0.726667 0.333333 0 0.726667 0.416667 0 0.726667 0.500000 0 0.726667 0.583333 0 0.726667 0.666667 0 0.726667 0.750000 0 0.726667 0.833333 0 0.726667 0.916667 0 0.726667 1.000000 0 0.733334 0 0 0.733334 0.083333 0 0.733334 0.166667 0 0.733334 0.250000 0 0.733334 0.333333 0 0.733334 0.416667 0 0.733334 0.500000 0 0.733334 0.583333 0 0.733334 0.666667 0 0.733334 0.750000 0 0.733334 0.833333 0 0.733334 0.916667 0 0.733334 1.000000 0 0.740000 0 0 0.740000 0.083333 0 0.740000 0.166667 0 0.740000 0.250000 0 0.740000 0.333333 0 0.740000 0.416667 0 0.740000 0.500000 0 0.740000 0.583333 0 0.740000 0.666667 0 0.740000 0.750000 0 0.740000 0.833333 0 0.740000 0.916667 0 0.740000 1.000000 0 0.746667 0 0 0.746667 0.083333 0 0.746667 0.166667 0 0.746667 0.250000 0 0.746667 0.333333 0 0.746667 0.416667 0 0.746667 0.500000 0 0.746667 0.583333 0 0.746667 0.666667 0 0.746667 0.750000 0 0.746667 0.833333 0 0.746667 0.916667 0 0.746667 1.000000 0 0.753334 0 0 0.753334 0.083333 0 0.753334 0.166667 0 0.753334 0.250000 0 0.753334 0.333333 0 0.753334 0.416667 0 0.753334 0.500000 0 0.753334 0.583333 0 0.753334 0.666667 0 0.753334 0.750000 0 0.753334 0.833333 0 0.753334 0.916667 0 0.753334 1.000000 0 0.760000 0 0 0.760000 0.083333 0 0.760000 0.166667 0 0.760000 0.250000 0 0.760000 0.333333 0 0.760000 0.416667 0 0.760000 0.500000 0 0.760000 0.583333 0 0.760000 0.666667 0 0.760000 0.750000 0 0.760000 0.833333 0 0.760000 0.916667 0 0.760000 1.000000 0 0.766667 0 0 0.766667 0.083333 0 0.766667 0.166667 0 0.766667 0.250000 0 0.766667 0.333333 0 0.766667 0.416667 0 0.766667 0.500000 0 0.766667 0.583333 0 0.766667 0.666667 0 0.766667 0.750000 0 0.766667 0.833333 0 0.766667 0.916667 0 0.766667 1.000000 0 0.773333 0 0 0.773333 0.083333 0 0.773333 0.166667 0 0.773333 0.250000 0 0.773333 0.333333 0 0.773333 0.416667 0 0.773333 0.500000 0 0.773333 0.583333 0 0.773333 0.666667 0 0.773333 0.750000 0 0.773333 0.833333 0 0.773333 0.916667 0 0.773333 1.000000 0 0.780000 0 0 0.780000 0.083333 0 0.780000 0.166667 0 0.780000 0.250000 0 0.780000 0.333333 0 0.780000 0.416667 0 0.780000 0.500000 0 0.780000 0.583333 0 0.780000 0.666667 0 0.780000 0.750000 0 0.780000 0.833333 0 0.780000 0.916667 0 0.780000 1.000000 0 0.786667 0 0 0.786667 0.083333 0 0.786667 0.166667 0 0.786667 0.250000 0 0.786667 0.333333 0 0.786667 0.416667 0 0.786667 0.500000 0 0.786667 0.583333 0 0.786667 0.666667 0 0.786667 0.750000 0 0.786667 0.833333 0 0.786667 0.916667 0 0.786667 1.000000 0 0.793333 0 0 0.793333 0.083333 0 0.793333 0.166667 0 0.793333 0.250000 0 0.793333 0.333333 0 0.793333 0.416667 0 0.793333 0.500000 0 0.793333 0.583333 0 0.793333 0.666667 0 0.793333 0.750000 0 0.793333 0.833333 0 0.793333 0.916667 0 0.793333 1.000000 0 0.800000 0 0 0.800000 0.083333 0 0.800000 0.166667 0 0.800000 0.250000 0 0.800000 0.333333 0 0.800000 0.416667 0 0.800000 0.500000 0 0.800000 0.583333 0 0.800000 0.666667 0 0.800000 0.750000 0 0.800000 0.833333 0 0.800000 0.916667 0 0.800000 1.000000 0 0.806667 0 0 0.806667 0.083333 0 0.806667 0.166667 0 0.806667 0.250000 0 0.806667 0.333333 0 0.806667 0.416667 0 0.806667 0.500000 0 0.806667 0.583333 0 0.806667 0.666667 0 0.806667 0.750000 0 0.806667 0.833333 0 0.806667 0.916667 0 0.806667 1.000000 0 0.813333 0 0 0.813333 0.083333 0 0.813333 0.166667 0 0.813333 0.250000 0 0.813333 0.333333 0 0.813333 0.416667 0 0.813333 0.500000 0 0.813333 0.583333 0 0.813333 0.666667 0 0.813333 0.750000 0 0.813333 0.833333 0 0.813333 0.916667 0 0.813333 1.000000 0 0.820000 0 0 0.820000 0.083333 0 0.820000 0.166667 0 0.820000 0.250000 0 0.820000 0.333333 0 0.820000 0.416667 0 0.820000 0.500000 0 0.820000 0.583333 0 0.820000 0.666667 0 0.820000 0.750000 0 0.820000 0.833333 0 0.820000 0.916667 0 0.820000 1.000000 0 0.826667 0 0 0.826667 0.083333 0 0.826667 0.166667 0 0.826667 0.250000 0 0.826667 0.333333 0 0.826667 0.416667 0 0.826667 0.500000 0 0.826667 0.583333 0 0.826667 0.666667 0 0.826667 0.750000 0 0.826667 0.833333 0 0.826667 0.916667 0 0.826667 1.000000 0 0.833333 0 0 0.833333 0.083333 0 0.833333 0.166667 0 0.833333 0.250000 0 0.833333 0.333333 0 0.833333 0.416667 0 0.833333 0.500000 0 0.833333 0.583333 0 0.833333 0.666667 0 0.833333 0.750000 0 0.833333 0.833333 0 0.833333 0.916667 0 0.833333 1.000000 0 0.840000 0 0 0.840000 0.083333 0 0.840000 0.166667 0 0.840000 0.250000 0 0.840000 0.333333 0 0.840000 0.416667 0 0.840000 0.500000 0 0.840000 0.583333 0 0.840000 0.666667 0 0.840000 0.750000 0 0.840000 0.833333 0 0.840000 0.916667 0 0.840000 1.000000 0 0.846667 0 0 0.846667 0.083333 0 0.846667 0.166667 0 0.846667 0.250000 0 0.846667 0.333333 0 0.846667 0.416667 0 0.846667 0.500000 0 0.846667 0.583333 0 0.846667 0.666667 0 0.846667 0.750000 0 0.846667 0.833333 0 0.846667 0.916667 0 0.846667 1.000000 0 0.853333 0 0 0.853333 0.083333 0 0.853333 0.166667 0 0.853333 0.250000 0 0.853333 0.333333 0 0.853333 0.416667 0 0.853333 0.500000 0 0.853333 0.583333 0 0.853333 0.666667 0 0.853333 0.750000 0 0.853333 0.833333 0 0.853333 0.916667 0 0.853333 1.000000 0 0.860000 0 0 0.860000 0.083333 0 0.860000 0.166667 0 0.860000 0.250000 0 0.860000 0.333333 0 0.860000 0.416667 0 0.860000 0.500000 0 0.860000 0.583333 0 0.860000 0.666667 0 0.860000 0.750000 0 0.860000 0.833333 0 0.860000 0.916667 0 0.860000 1.000000 0 0.866666 0 0 0.866666 0.083333 0 0.866666 0.166667 0 0.866666 0.250000 0 0.866666 0.333333 0 0.866666 0.416667 0 0.866666 0.500000 0 0.866666 0.583333 0 0.866666 0.666667 0 0.866666 0.750000 0 0.866666 0.833333 0 0.866666 0.916667 0 0.866666 1.000000 0 0.873333 0 0 0.873333 0.083333 0 0.873333 0.166667 0 0.873333 0.250000 0 0.873333 0.333333 0 0.873333 0.416667 0 0.873333 0.500000 0 0.873333 0.583333 0 0.873333 0.666667 0 0.873333 0.750000 0 0.873333 0.833333 0 0.873333 0.916667 0 0.873333 1.000000 0 0.880000 0 0 0.880000 0.083333 0 0.880000 0.166667 0 0.880000 0.250000 0 0.880000 0.333333 0 0.880000 0.416667 0 0.880000 0.500000 0 0.880000 0.583333 0 0.880000 0.666667 0 0.880000 0.750000 0 0.880000 0.833333 0 0.880000 0.916667 0 0.880000 1.000000 0 0.886666 0 0 0.886666 0.083333 0 0.886666 0.166667 0 0.886666 0.250000 0 0.886666 0.333333 0 0.886666 0.416667 0 0.886666 0.500000 0 0.886666 0.583333 0 0.886666 0.666667 0 0.886666 0.750000 0 0.886666 0.833333 0 0.886666 0.916667 0 0.886666 1.000000 0 0.893333 0 0 0.893333 0.083333 0 0.893333 0.166667 0 0.893333 0.250000 0 0.893333 0.333333 0 0.893333 0.416667 0 0.893333 0.500000 0 0.893333 0.583333 0 0.893333 0.666667 0 0.893333 0.750000 0 0.893333 0.833333 0 0.893333 0.916667 0 0.893333 1.000000 0 0.900000 0 0 0.900000 0.083333 0 0.900000 0.166667 0 0.900000 0.250000 0 0.900000 0.333333 0 0.900000 0.416667 0 0.900000 0.500000 0 0.900000 0.583333 0 0.900000 0.666667 0 0.900000 0.750000 0 0.900000 0.833333 0 0.900000 0.916667 0 0.900000 1.000000 0 0.906666 0 0 0.906666 0.083333 0 0.906666 0.166667 0 0.906666 0.250000 0 0.906666 0.333333 0 0.906666 0.416667 0 0.906666 0.500000 0 0.906666 0.583333 0 0.906666 0.666667 0 0.906666 0.750000 0 0.906666 0.833333 0 0.906666 0.916667 0 0.906666 1.000000 0 0.913333 0 0 0.913333 0.083333 0 0.913333 0.166667 0 0.913333 0.250000 0 0.913333 0.333333 0 0.913333 0.416667 0 0.913333 0.500000 0 0.913333 0.583333 0 0.913333 0.666667 0 0.913333 0.750000 0 0.913333 0.833333 0 0.913333 0.916667 0 0.913333 1.000000 0 0.920000 0 0 0.920000 0.083333 0 0.920000 0.166667 0 0.920000 0.250000 0 0.920000 0.333333 0 0.920000 0.416667 0 0.920000 0.500000 0 0.920000 0.583333 0 0.920000 0.666667 0 0.920000 0.750000 0 0.920000 0.833333 0 0.920000 0.916667 0 0.920000 1.000000 0 0.926666 0 0 0.926666 0.083333 0 0.926666 0.166667 0 0.926666 0.250000 0 0.926666 0.333333 0 0.926666 0.416667 0 0.926666 0.500000 0 0.926666 0.583333 0 0.926666 0.666667 0 0.926666 0.750000 0 0.926666 0.833333 0 0.926666 0.916667 0 0.926666 1.000000 0 0.933333 0 0 0.933333 0.083333 0 0.933333 0.166667 0 0.933333 0.250000 0 0.933333 0.333333 0 0.933333 0.416667 0 0.933333 0.500000 0 0.933333 0.583333 0 0.933333 0.666667 0 0.933333 0.750000 0 0.933333 0.833333 0 0.933333 0.916667 0 0.933333 1.000000 0 0.940000 0 0 0.940000 0.083333 0 0.940000 0.166667 0 0.940000 0.250000 0 0.940000 0.333333 0 0.940000 0.416667 0 0.940000 0.500000 0 0.940000 0.583333 0 0.940000 0.666667 0 0.940000 0.750000 0 0.940000 0.833333 0 0.940000 0.916667 0 0.940000 1.000000 0 0.946666 0 0 0.946666 0.083333 0 0.946666 0.166667 0 0.946666 0.250000 0 0.946666 0.333333 0 0.946666 0.416667 0 0.946666 0.500000 0 0.946666 0.583333 0 0.946666 0.666667 0 0.946666 0.750000 0 0.946666 0.833333 0 0.946666 0.916667 0 0.946666 1.000000 0 0.953333 0 0 0.953333 0.083333 0 0.953333 0.166667 0 0.953333 0.250000 0 0.953333 0.333333 0 0.953333 0.416667 0 0.953333 0.500000 0 0.953333 0.583333 0 0.953333 0.666667 0 0.953333 0.750000 0 0.953333 0.833333 0 0.953333 0.916667 0 0.953333 1.000000 0 0.960000 0 0 0.960000 0.083333 0 0.960000 0.166667 0 0.960000 0.250000 0 0.960000 0.333333 0 0.960000 0.416667 0 0.960000 0.500000 0 0.960000 0.583333 0 0.960000 0.666667 0 0.960000 0.750000 0 0.960000 0.833333 0 0.960000 0.916667 0 0.960000 1.000000 0 0.966666 0 0 0.966666 0.083333 0 0.966666 0.166667 0 0.966666 0.250000 0 0.966666 0.333333 0 0.966666 0.416667 0 0.966666 0.500000 0 0.966666 0.583333 0 0.966666 0.666667 0 0.966666 0.750000 0 0.966666 0.833333 0 0.966666 0.916667 0 0.966666 1.000000 0 0.973333 0 0 0.973333 0.083333 0 0.973333 0.166667 0 0.973333 0.250000 0 0.973333 0.333333 0 0.973333 0.416667 0 0.973333 0.500000 0 0.973333 0.583333 0 0.973333 0.666667 0 0.973333 0.750000 0 0.973333 0.833333 0 0.973333 0.916667 0 0.973333 1.000000 0 0.979999 0 0 0.979999 0.083333 0 0.979999 0.166667 0 0.979999 0.250000 0 0.979999 0.333333 0 0.979999 0.416667 0 0.979999 0.500000 0 0.979999 0.583333 0 0.979999 0.666667 0 0.979999 0.750000 0 0.979999 0.833333 0 0.979999 0.916667 0 0.979999 1.000000 0 0.986666 0 0 0.986666 0.083333 0 0.986666 0.166667 0 0.986666 0.250000 0 0.986666 0.333333 0 0.986666 0.416667 0 0.986666 0.500000 0 0.986666 0.583333 0 0.986666 0.666667 0 0.986666 0.750000 0 0.986666 0.833333 0 0.986666 0.916667 0 0.986666 1.000000 0 0.993333 0 0 0.993333 0.083333 0 0.993333 0.166667 0 0.993333 0.250000 0 0.993333 0.333333 0 0.993333 0.416667 0 0.993333 0.500000 0 0.993333 0.583333 0 0.993333 0.666667 0 0.993333 0.750000 0 0.993333 0.833333 0 0.993333 0.916667 0 0.993333 1.000000 0 0.999999 0 0 0.999999 0.083333 0 0.999999 0.166667 0 0.999999 0.250000 0 0.999999 0.333333 0 0.999999 0.416667 0 0.999999 0.500000 0 0.999999 0.583333 0 0.999999 0.666667 0 0.999999 0.750000 0 0.999999 0.833333 0 0.999999 0.916667 0 0.999999 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="1963" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="3600">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 12 1 13 13 2 14 0 0 0 13 2 14 1 3 1 1 3 1 13 2 14 14 4 15 1 3 1 14 4 15 2 5 2 2 5 2 14 4 15 15 6 16 2 5 2 15 6 16 3 7 3 3 7 3 15 6 16 16 8 17 3 7 3 16 8 17 4 9 4 4 9 4 16 8 17 17 10 18 4 9 4 17 10 18 5 11 5 5 11 5 17 10 18 18 12 19 5 11 5 18 12 19 6 13 6 6 13 6 18 12 19 19 14 20 6 13 6 19 14 20 7 15 7 7 15 7 19 14 20 20 16 21 7 15 7 20 16 21 8 17 8 8 17 8 20 16 21 21 18 22 8 17 8 21 18 22 9 19 9 9 19 9 21 18 22 22 20 23 9 19 9 22 20 23 10 21 10 10 21 10 22 20 23 23 22 24 10 21 10 23 22 24 11 23 11 11 23 11 23 22 24 12 1 25 11 23 11 12 1 25 0 0 12 12 1 13 24 24 26 25 25 27 12 1 13 25 25 27 13 2 14 13 2 14 25 25 27 26 26 28 13 2 14 26 26 28 14 4 15 14 4 15 26 26 28 27 27 29 14 4 15 27 27 29 15 6 16 15 6 16 27 27 29 28 28 30 15 6 16 28 28 30 16 8 17 16 8 17 28 28 30 29 29 31 16 8 17 29 29 31 17 10 18 17 10 18 29 29 31 30 30 32 17 10 18 30 30 32 18 12 19 18 12 19 30 30 32 31 31 33 18 12 19 31 31 33 19 14 20 19 14 20 31 31 33 32 32 34 19 14 20 32 32 34 20 16 21 20 16 21 32 32 34 33 33 35 20 16 21 33 33 35 21 18 22 21 18 22 33 33 35 34 34 36 21 18 22 34 34 36 22 20 23 22 20 23 34 34 36 35 35 37 22 20 23 35 35 37 23 22 24 23 22 24 35 35 37 24 24 38 23 22 24 24 24 38 12 1 25 24 24 26 36 36 39 37 37 40 24 24 26 37 37 40 25 25 27 25 25 27 37 37 40 38 38 41 25 25 27 38 38 41 26 26 28 26 26 28 38 38 41 39 39 42 26 26 28 39 39 42 27 27 29 27 27 29 39 39 42 40 40 43 27 27 29 40 40 43 28 28 30 28 28 30 40 40 43 41 41 44 28 28 30 41 41 44 29 29 31 29 29 31 41 41 44 42 42 45 29 29 31 42 42 45 30 30 32 30 30 32 42 42 45 43 43 46 30 30 32 43 43 46 31 31 33 31 31 33 43 43 46 44 44 47 31 31 33 44 44 47 32 32 34 32 32 34 44 44 47 45 45 48 32 32 34 45 45 48 33 33 35 33 33 35 45 45 48 46 46 49 33 33 35 46 46 49 34 34 36 34 34 36 46 46 49 47 47 50 34 34 36 47 47 50 35 35 37 35 35 37 47 47 50 36 36 51 35 35 37 36 36 51 24 24 38 36 36 39 48 48 52 49 49 53 36 36 39 49 49 53 37 37 40 37 37 40 49 49 53 50 50 54 37 37 40 50 50 54 38 38 41 38 38 41 50 50 54 51 51 55 38 38 41 51 51 55 39 39 42 39 39 42 51 51 55 52 52 56 39 39 42 52 52 56 40 40 43 40 40 43 52 52 56 53 53 57 40 40 43 53 53 57 41 41 44 41 41 44 53 53 57 54 54 58 41 41 44 54 54 58 42 42 45 42 42 45 54 54 58 55 55 59 42 42 45 55 55 59 43 43 46 43 43 46 55 55 59 56 56 60 43 43 46 56 56 60 44 44 47 44 44 47 56 56 60 57 57 61 44 44 47 57 57 61 45 45 48 45 45 48 57 57 61 58 58 62 45 45 48 58 58 62 46 46 49 46 46 49 58 58 62 59 59 63 46 46 49 59 59 63 47 47 50 47 47 50 59 59 63 48 48 64 47 47 50 48 48 64 36 36 51 48 48 52 60 60 65 61 61 66 48 48 52 61 61 66 49 49 53 49 49 53 61 61 66 62 62 67 49 49 53 62 62 67 50 50 54 50 50 54 62 62 67 63 63 68 50 50 54 63 63 68 51 51 55 51 51 55 63 63 68 64 64 69 51 51 55 64 64 69 52 52 56 52 52 56 64 64 69 65 65 70 52 52 56 65 65 70 53 53 57 53 53 57 65 65 70 66 66 71 53 53 57 66 66 71 54 54 58 54 54 58 66 66 71 67 67 72 54 54 58 67 67 72 55 55 59 55 55 59 67 67 72 68 68 73 55 55 59 68 68 73 56 56 60 56 56 60 68 68 73 69 69 74 56 56 60 69 69 74 57 57 61 57 57 61 69 69 74 70 70 75 57 57 61 70 70 75 58 58 62 58 58 62 70 70 75 71 71 76 58 58 62 71 71 76 59 59 63 59 59 63 71 71 76 60 60 77 59 59 63 60 60 77 48 48 64 60 60 65 72 72 78 73 73 79 60 60 65 73 73 79 61 61 66 61 61 66 73 73 79 74 74 80 61 61 66 74 74 80 62 62 67 62 62 67 74 74 80 75 75 81 62 62 67 75 75 81 63 63 68 63 63 68 75 75 81 76 76 82 63 63 68 76 76 82 64 64 69 64 64 69 76 76 82 77 77 83 64 64 69 77 77 83 65 65 70 65 65 70 77 77 83 78 78 84 65 65 70 78 78 84 66 66 71 66 66 71 78 78 84 79 79 85 66 66 71 79 79 85 67 67 72 67 67 72 79 79 85 80 80 86 67 67 72 80 80 86 68 68 73 68 68 73 80 80 86 81 81 87 68 68 73 81 81 87 69 69 74 69 69 74 81 81 87 82 82 88 69 69 74 82 82 88 70 70 75 70 70 75 82 82 88 83 83 89 70 70 75 83 83 89 71 71 76 71 71 76 83 83 89 72 72 90 71 71 76 72 72 90 60 60 77 72 72 78 84 84 91 85 85 92 72 72 78 85 85 92 73 73 79 73 73 79 85 85 92 86 86 93 73 73 79 86 86 93 74 74 80 74 74 80 86 86 93 87 87 94 74 74 80 87 87 94 75 75 81 75 75 81 87 87 94 88 88 95 75 75 81 88 88 95 76 76 82 76 76 82 88 88 95 89 89 96 76 76 82 89 89 96 77 77 83 77 77 83 89 89 96 90 90 97 77 77 83 90 90 97 78 78 84 78 78 84 90 90 97 91 91 98 78 78 84 91 91 98 79 79 85 79 79 85 91 91 98 92 92 99 79 79 85 92 92 99 80 80 86 80 80 86 92 92 99 93 93 100 80 80 86 93 93 100 81 81 87 81 81 87 93 93 100 94 94 101 81 81 87 94 94 101 82 82 88 82 82 88 94 94 101 95 95 102 82 82 88 95 95 102 83 83 89 83 83 89 95 95 102 84 84 103 83 83 89 84 84 103 72 72 90 84 84 91 96 96 104 97 97 105 84 84 91 97 97 105 85 85 92 85 85 92 97 97 105 98 98 106 85 85 92 98 98 106 86 86 93 86 86 93 98 98 106 99 99 107 86 86 93 99 99 107 87 87 94 87 87 94 99 99 107 100 100 108 87 87 94 100 100 108 88 88 95 88 88 95 100 100 108 101 101 109 88 88 95 101 101 109 89 89 96 89 89 96 101 101 109 102 102 110 89 89 96 102 102 110 90 90 97 90 90 97 102 102 110 103 103 111 90 90 97 103 103 111 91 91 98 91 91 98 103 103 111 104 104 112 91 91 98 104 104 112 92 92 99 92 92 99 104 104 112 105 105 113 92 92 99 105 105 113 93 93 100 93 93 100 105 105 113 106 106 114 93 93 100 106 106 114 94 94 101 94 94 101 106 106 114 107 107 115 94 94 101 107 107 115 95 95 102 95 95 102 107 107 115 96 96 116 95 95 102 96 96 116 84 84 103 96 96 104 108 108 117 109 109 118 96 96 104 109 109 118 97 97 105 97 97 105 109 109 118 110 110 119 97 97 105 110 110 119 98 98 106 98 98 106 110 110 119 111 111 120 98 98 106 111 111 120 99 99 107 99 99 107 111 111 120 112 112 121 99 99 107 112 112 121 100 100 108 100 100 108 112 112 121 113 113 122 100 100 108 113 113 122 101 101 109 101 101 109 113 113 122 114 114 123 101 101 109 114 114 123 102 102 110 102 102 110 114 114 123 115 115 124 102 102 110 115 115 124 103 103 111 103 103 111 115 115 124 116 116 125 103 103 111 116 116 125 104 104 112 104 104 112 116 116 125 117 117 126 104 104 112 117 117 126 105 105 113 105 105 113 117 117 126 118 118 127 105 105 113 118 118 127 106 106 114 106 106 114 118 118 127 119 119 128 106 106 114 119 119 128 107 107 115 107 107 115 119 119 128 108 108 129 107 107 115 108 108 129 96 96 116 108 108 117 120 120 130 121 121 131 108 108 117 121 121 131 109 109 118 109 109 118 121 121 131 122 122 132 109 109 118 122 122 132 110 110 119 110 110 119 122 122 132 123 123 133 110 110 119 123 123 133 111 111 120 111 111 120 123 123 133 124 124 134 111 111 120 124 124 134 112 112 121 112 112 121 124 124 134 125 125 135 112 112 121 125 125 135 113 113 122 113 113 122 125 125 135 126 126 136 113 113 122 126 126 136 114 114 123 114 114 123 126 126 136 127 127 137 114 114 123 127 127 137 115 115 124 115 115 124 127 127 137 128 128 138 115 115 124 128 128 138 116 116 125 116 116 125 128 128 138 129 129 139 116 116 125 129 129 139 117 117 126 117 117 126 129 129 139 130 130 140 117 117 126 130 130 140 118 118 127 118 118 127 130 130 140 131 131 141 118 118 127 131 131 141 119 119 128 119 119 128 131 131 141 120 120 142 119 119 128 120 120 142 108 108 129 120 120 130 132 132 143 133 133 144 120 120 130 133 133 144 121 121 131 121 121 131 133 133 144 134 134 145 121 121 131 134 134 145 122 122 132 122 122 132 134 134 145 135 135 146 122 122 132 135 135 146 123 123 133 123 123 133 135 135 146 136 136 147 123 123 133 136 136 147 124 124 134 124 124 134 136 136 147 137 137 148 124 124 134 137 137 148 125 125 135 125 125 135 137 137 148 138 138 149 125 125 135 138 138 149 126 126 136 126 126 136 138 138 149 139 139 150 126 126 136 139 139 150 127 127 137 127 127 137 139 139 150 140 140 151 127 127 137 140 140 151 128 128 138 128 128 138 140 140 151 141 141 152 128 128 138 141 141 152 129 129 139 129 129 139 141 141 152 142 142 153 129 129 139 142 142 153 130 130 140 130 130 140 142 142 153 143 143 154 130 130 140 143 143 154 131 131 141 131 131 141 143 143 154 132 132 155 131 131 141 132 132 155 120 120 142 132 132 143 144 144 156 145 145 157 132 132 143 145 145 157 133 133 144 133 133 144 145 145 157 146 146 158 133 133 144 146 146 158 134 134 145 134 134 145 146 146 158 147 147 159 134 134 145 147 147 159 135 135 146 135 135 146 147 147 159 148 148 160 135 135 146 148 148 160 136 136 147 136 136 147 148 148 160 149 149 161 136 136 147 149 149 161 137 137 148 137 137 148 149 149 161 150 150 162 137 137 148 150 150 162 138 138 149 138 138 149 150 150 162 151 151 163 138 138 149 151 151 163 139 139 150 139 139 150 151 151 163 152 152 164 139 139 150 152 152 164 140 140 151 140 140 151 152 152 164 153 153 165 140 140 151 153 153 165 141 141 152 141 141 152 153 153 165 154 154 166 141 141 152 154 154 166 142 142 153 142 142 153 154 154 166 155 155 167 142 142 153 155 155 167 143 143 154 143 143 154 155 155 167 144 144 168 143 143 154 144 144 168 132 132 155 144 144 156 156 156 169 157 157 170 144 144 156 157 157 170 145 145 157 145 145 157 157 157 170 158 158 171 145 145 157 158 158 171 146 146 158 146 146 158 158 158 171 159 159 172 146 146 158 159 159 172 147 147 159 147 147 159 159 159 172 160 160 173 147 147 159 160 160 173 148 148 160 148 148 160 160 160 173 161 161 174 148 148 160 161 161 174 149 149 161 149 149 161 161 161 174 162 162 175 149 149 161 162 162 175 150 150 162 150 150 162 162 162 175 163 163 176 150 150 162 163 163 176 151 151 163 151 151 163 163 163 176 164 164 177 151 151 163 164 164 177 152 152 164 152 152 164 164 164 177 165 165 178 152 152 164 165 165 178 153 153 165 153 153 165 165 165 178 166 166 179 153 153 165 166 166 179 154 154 166 154 154 166 166 166 179 167 167 180 154 154 166 167 167 180 155 155 167 155 155 167 167 167 180 156 156 181 155 155 167 156 156 181 144 144 168 156 156 169 168 168 182 169 169 183 156 156 169 169 169 183 157 157 170 157 157 170 169 169 183 170 170 184 157 157 170 170 170 184 158 158 171 158 158 171 170 170 184 171 171 185 158 158 171 171 171 185 159 159 172 159 159 172 171 171 185 172 172 186 159 159 172 172 172 186 160 160 173 160 160 173 172 172 186 173 173 187 160 160 173 173 173 187 161 161 174 161 161 174 173 173 187 174 174 188 161 161 174 174 174 188 162 162 175 162 162 175 174 174 188 175 175 189 162 162 175 175 175 189 163 163 176 163 163 176 175 175 189 176 176 190 163 163 176 176 176 190 164 164 177 164 164 177 176 176 190 177 177 191 164 164 177 177 177 191 165 165 178 165 165 178 177 177 191 178 178 192 165 165 178 178 178 192 166 166 179 166 166 179 178 178 192 179 179 193 166 166 179 179 179 193 167 167 180 167 167 180 179 179 193 168 168 194 167 167 180 168 168 194 156 156 181 168 168 182 180 180 195 181 181 196 168 168 182 181 181 196 169 169 183 169 169 183 181 181 196 182 182 197 169 169 183 182 182 197 170 170 184 170 170 184 182 182 197 183 183 198 170 170 184 183 183 198 171 171 185 171 171 185 183 183 198 184 184 199 171 171 185 184 184 199 172 172 186 172 172 186 184 184 199 185 185 200 172 172 186 185 185 200 173 173 187 173 173 187 185 185 200 186 186 201 173 173 187 186 186 201 174 174 188 174 174 188 186 186 201 187 187 202 174 174 188 187 187 202 175 175 189 175 175 189 187 187 202 188 188 203 175 175 189 188 188 203 176 176 190 176 176 190 188 188 203 189 189 204 176 176 190 189 189 204 177 177 191 177 177 191 189 189 204 190 190 205 177 177 191 190 190 205 178 178 192 178 178 192 190 190 205 191 191 206 178 178 192 191 191 206 179 179 193 179 179 193 191 191 206 180 180 207 179 179 193 180 180 207 168 168 194 180 180 195 192 192 208 193 193 209 180 180 195 193 193 209 181 181 196 181 181 196 193 193 209 194 194 210 181 181 196 194 194 210 182 182 197 182 182 197 194 194 210 195 195 211 182 182 197 195 195 211 183 183 198 183 183 198 195 195 211 196 196 212 183 183 198 196 196 212 184 184 199 184 184 199 196 196 212 197 197 213 184 184 199 197 197 213 185 185 200 185 185 200 197 197 213 198 198 214 185 185 200 198 198 214 186 186 201 186 186 201 198 198 214 199 199 215 186 186 201 199 199 215 187 187 202 187 187 202 199 199 215 200 200 216 187 187 202 200 200 216 188 188 203 188 188 203 200 200 216 201 201 217 188 188 203 201 201 217 189 189 204 189 189 204 201 201 217 202 202 218 189 189 204 202 202 218 190 190 205 190 190 205 202 202 218 203 203 219 190 190 205 203 203 219 191 191 206 191 191 206 203 203 219 192 192 220 191 191 206 192 192 220 180 180 207 192 192 208 204 204 221 205 205 222 192 192 208 205 205 222 193 193 209 193 193 209 205 205 222 206 206 223 193 193 209 206 206 223 194 194 210 194 194 210 206 206 223 207 207 224 194 194 210 207 207 224 195 195 211 195 195 211 207 207 224 208 208 225 195 195 211 208 208 225 196 196 212 196 196 212 208 208 225 209 209 226 196 196 212 209 209 226 197 197 213 197 197 213 209 209 226 210 210 227 197 197 213 210 210 227 198 198 214 198 198 214 210 210 227 211 211 228 198 198 214 211 211 228 199 199 215 199 199 215 211 211 228 212 212 229 199 199 215 212 212 229 200 200 216 200 200 216 212 212 229 213 213 230 200 200 216 213 213 230 201 201 217 201 201 217 213 213 230 214 214 231 201 201 217 214 214 231 202 202 218 202 202 218 214 214 231 215 215 232 202 202 218 215 215 232 203 203 219 203 203 219 215 215 232 204 204 233 203 203 219 204 204 233 192 192 220 204 204 221 216 216 234 217 217 235 204 204 221 217 217 235 205 205 222 205 205 222 217 217 235 218 218 236 205 205 222 218 218 236 206 206 223 206 206 223 218 218 236 219 219 237 206 206 223 219 219 237 207 207 224 207 207 224 219 219 237 220 220 238 207 207 224 220 220 238 208 208 225 208 208 225 220 220 238 221 221 239 208 208 225 221 221 239 209 209 226 209 209 226 221 221 239 222 222 240 209 209 226 222 222 240 210 210 227 210 210 227 222 222 240 223 223 241 210 210 227 223 223 241 211 211 228 211 211 228 223 223 241 224 224 242 211 211 228 224 224 242 212 212 229 212 212 229 224 224 242 225 225 243 212 212 229 225 225 243 213 213 230 213 213 230 225 225 243 226 226 244 213 213 230 226 226 244 214 214 231 214 214 231 226 226 244 227 227 245 214 214 231 227 227 245 215 215 232 215 215 232 227 227 245 216 216 246 215 215 232 216 216 246 204 204 233 216 216 234 228 228 247 229 229 248 216 216 234 229 229 248 217 217 235 217 217 235 229 229 248 230 230 249 217 217 235 230 230 249 218 218 236 218 218 236 230 230 249 231 231 250 218 218 236 231 231 250 219 219 237 219 219 237 231 231 250 232 232 251 219 219 237 232 232 251 220 220 238 220 220 238 232 232 251 233 233 252 220 220 238 233 233 252 221 221 239 221 221 239 233 233 252 234 234 253 221 221 239 234 234 253 222 222 240 222 222 240 234 234 253 235 235 254 222 222 240 235 235 254 223 223 241 223 223 241 235 235 254 236 236 255 223 223 241 236 236 255 224 224 242 224 224 242 236 236 255 237 237 256 224 224 242 237 237 256 225 225 243 225 225 243 237 237 256 238 238 257 225 225 243 238 238 257 226 226 244 226 226 244 238 238 257 239 239 258 226 226 244 239 239 258 227 227 245 227 227 245 239 239 258 228 228 259 227 227 245 228 228 259 216 216 246 228 228 247 240 240 260 241 241 261 228 228 247 241 241 261 229 229 248 229 229 248 241 241 261 242 242 262 229 229 248 242 242 262 230 230 249 230 230 249 242 242 262 243 243 263 230 230 249 243 243 263 231 231 250 231 231 250 243 243 263 244 244 264 231 231 250 244 244 264 232 232 251 232 232 251 244 244 264 245 245 265 232 232 251 245 245 265 233 233 252 233 233 252 245 245 265 246 246 266 233 233 252 246 246 266 234 234 253 234 234 253 246 246 266 247 247 267 234 234 253 247 247 267 235 235 254 235 235 254 247 247 267 248 248 268 235 235 254 248 248 268 236 236 255 236 236 255 248 248 268 249 249 269 236 236 255 249 249 269 237 237 256 237 237 256 249 249 269 250 250 270 237 237 256 250 250 270 238 238 257 238 238 257 250 250 270 251 251 271 238 238 257 251 251 271 239 239 258 239 239 258 251 251 271 240 240 272 239 239 258 240 240 272 228 228 259 240 240 260 252 252 273 253 253 274 240 240 260 253 253 274 241 241 261 241 241 261 253 253 274 254 254 275 241 241 261 254 254 275 242 242 262 242 242 262 254 254 275 255 255 276 242 242 262 255 255 276 243 243 263 243 243 263 255 255 276 256 256 277 243 243 263 256 256 277 244 244 264 244 244 264 256 256 277 257 257 278 244 244 264 257 257 278 245 245 265 245 245 265 257 257 278 258 258 279 245 245 265 258 258 279 246 246 266 246 246 266 258 258 279 259 259 280 246 246 266 259 259 280 247 247 267 247 247 267 259 259 280 260 260 281 247 247 267 260 260 281 248 248 268 248 248 268 260 260 281 261 261 282 248 248 268 261 261 282 249 249 269 249 249 269 261 261 282 262 262 283 249 249 269 262 262 283 250 250 270 250 250 270 262 262 283 263 263 284 250 250 270 263 263 284 251 251 271 251 251 271 263 263 284 252 252 285 251 251 271 252 252 285 240 240 272 252 252 273 264 264 286 265 265 287 252 252 273 265 265 287 253 253 274 253 253 274 265 265 287 266 266 288 253 253 274 266 266 288 254 254 275 254 254 275 266 266 288 267 267 289 254 254 275 267 267 289 255 255 276 255 255 276 267 267 289 268 268 290 255 255 276 268 268 290 256 256 277 256 256 277 268 268 290 269 269 291 256 256 277 269 269 291 257 257 278 257 257 278 269 269 291 270 270 292 257 257 278 270 270 292 258 258 279 258 258 279 270 270 292 271 271 293 258 258 279 271 271 293 259 259 280 259 259 280 271 271 293 272 272 294 259 259 280 272 272 294 260 260 281 260 260 281 272 272 294 273 273 295 260 260 281 273 273 295 261 261 282 261 261 282 273 273 295 274 274 296 261 261 282 274 274 296 262 262 283 262 262 283 274 274 296 275 275 297 262 262 283 275 275 297 263 263 284 263 263 284 275 275 297 264 264 298 263 263 284 264 264 298 252 252 285 264 264 286 276 276 299 277 277 300 264 264 286 277 277 300 265 265 287 265 265 287 277 277 300 278 278 301 265 265 287 278 278 301 266 266 288 266 266 288 278 278 301 279 279 302 266 266 288 279 279 302 267 267 289 267 267 289 279 279 302 280 280 303 267 267 289 280 280 303 268 268 290 268 268 290 280 280 303 281 281 304 268 268 290 281 281 304 269 269 291 269 269 291 281 281 304 282 282 305 269 269 291 282 282 305 270 270 292 270 270 292 282 282 305 283 283 306 270 270 292 283 283 306 271 271 293 271 271 293 283 283 306 284 284 307 271 271 293 284 284 307 272 272 294 272 272 294 284 284 307 285 285 308 272 272 294 285 285 308 273 273 295 273 273 295 285 285 308 286 286 309 273 273 295 286 286 309 274 274 296 274 274 296 286 286 309 287 287 310 274 274 296 287 287 310 275 275 297 275 275 297 287 287 310 276 276 311 275 275 297 276 276 311 264 264 298 276 276 299 288 288 312 289 289 313 276 276 299 289 289 313 277 277 300 277 277 300 289 289 313 290 290 314 277 277 300 290 290 314 278 278 301 278 278 301 290 290 314 291 291 315 278 278 301 291 291 315 279 279 302 279 279 302 291 291 315 292 292 316 279 279 302 292 292 316 280 280 303 280 280 303 292 292 316 293 293 317 280 280 303 293 293 317 281 281 304 281 281 304 293 293 317 294 294 318 281 281 304 294 294 318 282 282 305 282 282 305 294 294 318 295 295 319 282 282 305 295 295 319 283 283 306 283 283 306 295 295 319 296 296 320 283 283 306 296 296 320 284 284 307 284 284 307 296 296 320 297 297 321 284 284 307 297 297 321 285 285 308 285 285 308 297 297 321 298 298 322 285 285 308 298 298 322 286 286 309 286 286 309 298 298 322 299 299 323 286 286 309 299 299 323 287 287 310 287 287 310 299 299 323 288 288 324 287 287 310 288 288 324 276 276 311 288 288 312 300 300 325 301 301 326 288 288 312 301 301 326 289 289 313 289 289 313 301 301 326 302 302 327 289 289 313 302 302 327 290 290 314 290 290 314 302 302 327 303 303 328 290 290 314 303 303 328 291 291 315 291 291 315 303 303 328 304 304 329 291 291 315 304 304 329 292 292 316 292 292 316 304 304 329 305 305 330 292 292 316 305 305 330 293 293 317 293 293 317 305 305 330 306 306 331 293 293 317 306 306 331 294 294 318 294 294 318 306 306 331 307 307 332 294 294 318 307 307 332 295 295 319 295 295 319 307 307 332 308 308 333 295 295 319 308 308 333 296 296 320 296 296 320 308 308 333 309 309 334 296 296 320 309 309 334 297 297 321 297 297 321 309 309 334 310 310 335 297 297 321 310 310 335 298 298 322 298 298 322 310 310 335 311 311 336 298 298 322 311 311 336 299 299 323 299 299 323 311 311 336 300 300 337 299 299 323 300 300 337 288 288 324 300 300 325 312 312 338 313 313 339 300 300 325 313 313 339 301 301 326 301 301 326 313 313 339 314 314 340 301 301 326 314 314 340 302 302 327 302 302 327 314 314 340 315 315 341 302 302 327 315 315 341 303 303 328 303 303 328 315 315 341 316 316 342 303 303 328 316 316 342 304 304 329 304 304 329 316 316 342 317 317 343 304 304 329 317 317 343 305 305 330 305 305 330 317 317 343 318 318 344 305 305 330 318 318 344 306 306 331 306 306 331 318 318 344 319 319 345 306 306 331 319 319 345 307 307 332 307 307 332 319 319 345 320 320 346 307 307 332 320 320 346 308 308 333 308 308 333 320 320 346 321 321 347 308 308 333 321 321 347 309 309 334 309 309 334 321 321 347 322 322 348 309 309 334 322 322 348 310 310 335 310 310 335 322 322 348 323 323 349 310 310 335 323 323 349 311 311 336 311 311 336 323 323 349 312 312 350 311 311 336 312 312 350 300 300 337 312 312 338 324 324 351 325 325 352 312 312 338 325 325 352 313 313 339 313 313 339 325 325 352 326 326 353 313 313 339 326 326 353 314 314 340 314 314 340 326 326 353 327 327 354 314 314 340 327 327 354 315 315 341 315 315 341 327 327 354 328 328 355 315 315 341 328 328 355 316 316 342 316 316 342 328 328 355 329 329 356 316 316 342 329 329 356 317 317 343 317 317 343 329 329 356 330 330 357 317 317 343 330 330 357 318 318 344 318 318 344 330 330 357 331 331 358 318 318 344 331 331 358 319 319 345 319 319 345 331 331 358 332 332 359 319 319 345 332 332 359 320 320 346 320 320 346 332 332 359 333 333 360 320 320 346 333 333 360 321 321 347 321 321 347 333 333 360 334 334 361 321 321 347 334 334 361 322 322 348 322 322 348 334 334 361 335 335 362 322 322 348 335 335 362 323 323 349 323 323 349 335 335 362 324 324 363 323 323 349 324 324 363 312 312 350 324 324 351 336 336 364 337 337 365 324 324 351 337 337 365 325 325 352 325 325 352 337 337 365 338 338 366 325 325 352 338 338 366 326 326 353 326 326 353 338 338 366 339 339 367 326 326 353 339 339 367 327 327 354 327 327 354 339 339 367 340 340 368 327 327 354 340 340 368 328 328 355 328 328 355 340 340 368 341 341 369 328 328 355 341 341 369 329 329 356 329 329 356 341 341 369 342 342 370 329 329 356 342 342 370 330 330 357 330 330 357 342 342 370 343 343 371 330 330 357 343 343 371 331 331 358 331 331 358 343 343 371 344 344 372 331 331 358 344 344 372 332 332 359 332 332 359 344 344 372 345 345 373 332 332 359 345 345 373 333 333 360 333 333 360 345 345 373 346 346 374 333 333 360 346 346 374 334 334 361 334 334 361 346 346 374 347 347 375 334 334 361 347 347 375 335 335 362 335 335 362 347 347 375 336 336 376 335 335 362 336 336 376 324 324 363 336 336 364 348 348 377 349 349 378 336 336 364 349 349 378 337 337 365 337 337 365 349 349 378 350 350 379 337 337 365 350 350 379 338 338 366 338 338 366 350 350 379 351 351 380 338 338 366 351 351 380 339 339 367 339 339 367 351 351 380 352 352 381 339 339 367 352 352 381 340 340 368 340 340 368 352 352 381 353 353 382 340 340 368 353 353 382 341 341 369 341 341 369 353 353 382 354 354 383 341 341 369 354 354 383 342 342 370 342 342 370 354 354 383 355 355 384 342 342 370 355 355 384 343 343 371 343 343 371 355 355 384 356 356 385 343 343 371 356 356 385 344 344 372 344 344 372 356 356 385 357 357 386 344 344 372 357 357 386 345 345 373 345 345 373 357 357 386 358 358 387 345 345 373 358 358 387 346 346 374 346 346 374 358 358 387 359 359 388 346 346 374 359 359 388 347 347 375 347 347 375 359 359 388 348 348 389 347 347 375 348 348 389 336 336 376 348 348 377 360 360 390 361 361 391 348 348 377 361 361 391 349 349 378 349 349 378 361 361 391 362 362 392 349 349 378 362 362 392 350 350 379 350 350 379 362 362 392 363 363 393 350 350 379 363 363 393 351 351 380 351 351 380 363 363 393 364 364 394 351 351 380 364 364 394 352 352 381 352 352 381 364 364 394 365 365 395 352 352 381 365 365 395 353 353 382 353 353 382 365 365 395 366 366 396 353 353 382 366 366 396 354 354 383 354 354 383 366 366 396 367 367 397 354 354 383 367 367 397 355 355 384 355 355 384 367 367 397 368 368 398 355 355 384 368 368 398 356 356 385 356 356 385 368 368 398 369 369 399 356 356 385 369 369 399 357 357 386 357 357 386 369 369 399 370 370 400 357 357 386 370 370 400 358 358 387 358 358 387 370 370 400 371 371 401 358 358 387 371 371 401 359 359 388 359 359 388 371 371 401 360 360 402 359 359 388 360 360 402 348 348 389 360 360 390 372 372 403 373 373 404 360 360 390 373 373 404 361 361 391 361 361 391 373 373 404 374 374 405 361 361 391 374 374 405 362 362 392 362 362 392 374 374 405 375 375 406 362 362 392 375 375 406 363 363 393 363 363 393 375 375 406 376 376 407 363 363 393 376 376 407 364 364 394 364 364 394 376 376 407 377 377 408 364 364 394 377 377 408 365 365 395 365 365 395 377 377 408 378 378 409 365 365 395 378 378 409 366 366 396 366 366 396 378 378 409 379 379 410 366 366 396 379 379 410 367 367 397 367 367 397 379 379 410 380 380 411 367 367 397 380 380 411 368 368 398 368 368 398 380 380 411 381 381 412 368 368 398 381 381 412 369 369 399 369 369 399 381 381 412 382 382 413 369 369 399 382 382 413 370 370 400 370 370 400 382 382 413 383 383 414 370 370 400 383 383 414 371 371 401 371 371 401 383 383 414 372 372 415 371 371 401 372 372 415 360 360 402 372 372 403 384 384 416 385 385 417 372 372 403 385 385 417 373 373 404 373 373 404 385 385 417 386 386 418 373 373 404 386 386 418 374 374 405 374 374 405 386 386 418 387 387 419 374 374 405 387 387 419 375 375 406 375 375 406 387 387 419 388 388 420 375 375 406 388 388 420 376 376 407 376 376 407 388 388 420 389 389 421 376 376 407 389 389 421 377 377 408 377 377 408 389 389 421 390 390 422 377 377 408 390 390 422 378 378 409 378 378 409 390 390 422 391 391 423 378 378 409 391 391 423 379 379 410 379 379 410 391 391 423 392 392 424 379 379 410 392 392 424 380 380 411 380 380 411 392 392 424 393 393 425 380 380 411 393 393 425 381 381 412 381 381 412 393 393 425 394 394 426 381 381 412 394 394 426 382 382 413 382 382 413 394 394 426 395 395 427 382 382 413 395 395 427 383 383 414 383 383 414 395 395 427 384 384 428 383 383 414 384 384 428 372 372 415 384 384 416 396 396 429 397 397 430 384 384 416 397 397 430 385 385 417 385 385 417 397 397 430 398 398 431 385 385 417 398 398 431 386 386 418 386 386 418 398 398 431 399 399 432 386 386 418 399 399 432 387 387 419 387 387 419 399 399 432 400 400 433 387 387 419 400 400 433 388 388 420 388 388 420 400 400 433 401 401 434 388 388 420 401 401 434 389 389 421 389 389 421 401 401 434 402 402 435 389 389 421 402 402 435 390 390 422 390 390 422 402 402 435 403 403 436 390 390 422 403 403 436 391 391 423 391 391 423 403 403 436 404 404 437 391 391 423 404 404 437 392 392 424 392 392 424 404 404 437 405 405 438 392 392 424 405 405 438 393 393 425 393 393 425 405 405 438 406 406 439 393 393 425 406 406 439 394 394 426 394 394 426 406 406 439 407 407 440 394 394 426 407 407 440 395 395 427 395 395 427 407 407 440 396 396 441 395 395 427 396 396 441 384 384 428 396 396 429 408 408 442 409 409 443 396 396 429 409 409 443 397 397 430 397 397 430 409 409 443 410 410 444 397 397 430 410 410 444 398 398 431 398 398 431 410 410 444 411 411 445 398 398 431 411 411 445 399 399 432 399 399 432 411 411 445 412 412 446 399 399 432 412 412 446 400 400 433 400 400 433 412 412 446 413 413 447 400 400 433 413 413 447 401 401 434 401 401 434 413 413 447 414 414 448 401 401 434 414 414 448 402 402 435 402 402 435 414 414 448 415 415 449 402 402 435 415 415 449 403 403 436 403 403 436 415 415 449 416 416 450 403 403 436 416 416 450 404 404 437 404 404 437 416 416 450 417 417 451 404 404 437 417 417 451 405 405 438 405 405 438 417 417 451 418 418 452 405 405 438 418 418 452 406 406 439 406 406 439 418 418 452 419 419 453 406 406 439 419 419 453 407 407 440 407 407 440 419 419 453 408 408 454 407 407 440 408 408 454 396 396 441 408 408 442 420 420 455 421 421 456 408 408 442 421 421 456 409 409 443 409 409 443 421 421 456 422 422 457 409 409 443 422 422 457 410 410 444 410 410 444 422 422 457 423 423 458 410 410 444 423 423 458 411 411 445 411 411 445 423 423 458 424 424 459 411 411 445 424 424 459 412 412 446 412 412 446 424 424 459 425 425 460 412 412 446 425 425 460 413 413 447 413 413 447 425 425 460 426 426 461 413 413 447 426 426 461 414 414 448 414 414 448 426 426 461 427 427 462 414 414 448 427 427 462 415 415 449 415 415 449 427 427 462 428 428 463 415 415 449 428 428 463 416 416 450 416 416 450 428 428 463 429 429 464 416 416 450 429 429 464 417 417 451 417 417 451 429 429 464 430 430 465 417 417 451 430 430 465 418 418 452 418 418 452 430 430 465 431 431 466 418 418 452 431 431 466 419 419 453 419 419 453 431 431 466 420 420 467 419 419 453 420 420 467 408 408 454 420 420 455 432 432 468 433 433 469 420 420 455 433 433 469 421 421 456 421 421 456 433 433 469 434 434 470 421 421 456 434 434 470 422 422 457 422 422 457 434 434 470 435 435 471 422 422 457 435 435 471 423 423 458 423 423 458 435 435 471 436 436 472 423 423 458 436 436 472 424 424 459 424 424 459 436 436 472 437 437 473 424 424 459 437 437 473 425 425 460 425 425 460 437 437 473 438 438 474 425 425 460 438 438 474 426 426 461 426 426 461 438 438 474 439 439 475 426 426 461 439 439 475 427 427 462 427 427 462 439 439 475 440 440 476 427 427 462 440 440 476 428 428 463 428 428 463 440 440 476 441 441 477 428 428 463 441 441 477 429 429 464 429 429 464 441 441 477 442 442 478 429 429 464 442 442 478 430 430 465 430 430 465 442 442 478 443 443 479 430 430 465 443 443 479 431 431 466 431 431 466 443 443 479 432 432 480 431 431 466 432 432 480 420 420 467 432 432 468 444 444 481 445 445 482 432 432 468 445 445 482 433 433 469 433 433 469 445 445 482 446 446 483 433 433 469 446 446 483 434 434 470 434 434 470 446 446 483 447 447 484 434 434 470 447 447 484 435 435 471 435 435 471 447 447 484 448 448 485 435 435 471 448 448 485 436 436 472 436 436 472 448 448 485 449 449 486 436 436 472 449 449 486 437 437 473 437 437 473 449 449 486 450 450 487 437 437 473 450 450 487 438 438 474 438 438 474 450 450 487 451 451 488 438 438 474 451 451 488 439 439 475 439 439 475 451 451 488 452 452 489 439 439 475 452 452 489 440 440 476 440 440 476 452 452 489 453 453 490 440 440 476 453 453 490 441 441 477 441 441 477 453 453 490 454 454 491 441 441 477 454 454 491 442 442 478 442 442 478 454 454 491 455 455 492 442 442 478 455 455 492 443 443 479 443 443 479 455 455 492 444 444 493 443 443 479 444 444 493 432 432 480 444 444 481 456 456 494 457 457 495 444 444 481 457 457 495 445 445 482 445 445 482 457 457 495 458 458 496 445 445 482 458 458 496 446 446 483 446 446 483 458 458 496 459 459 497 446 446 483 459 459 497 447 447 484 447 447 484 459 459 497 460 460 498 447 447 484 460 460 498 448 448 485 448 448 485 460 460 498 461 461 499 448 448 485 461 461 499 449 449 486 449 449 486 461 461 499 462 462 500 449 449 486 462 462 500 450 450 487 450 450 487 462 462 500 463 463 501 450 450 487 463 463 501 451 451 488 451 451 488 463 463 501 464 464 502 451 451 488 464 464 502 452 452 489 452 452 489 464 464 502 465 465 503 452 452 489 465 465 503 453 453 490 453 453 490 465 465 503 466 466 504 453 453 490 466 466 504 454 454 491 454 454 491 466 466 504 467 467 505 454 454 491 467 467 505 455 455 492 455 455 492 467 467 505 456 456 506 455 455 492 456 456 506 444 444 493 456 456 494 468 468 507 469 469 508 456 456 494 469 469 508 457 457 495 457 457 495 469 469 508 470 470 509 457 457 495 470 470 509 458 458 496 458 458 496 470 470 509 471 471 510 458 458 496 471 471 510 459 459 497 459 459 497 471 471 510 472 472 511 459 459 497 472 472 511 460 460 498 460 460 498 472 472 511 473 473 512 460 460 498 473 473 512 461 461 499 461 461 499 473 473 512 474 474 513 461 461 499 474 474 513 462 462 500 462 462 500 474 474 513 475 475 514 462 462 500 475 475 514 463 463 501 463 463 501 475 475 514 476 476 515 463 463 501 476 476 515 464 464 502 464 464 502 476 476 515 477 477 516 464 464 502 477 477 516 465 465 503 465 465 503 477 477 516 478 478 517 465 465 503 478 478 517 466 466 504 466 466 504 478 478 517 479 479 518 466 466 504 479 479 518 467 467 505 467 467 505 479 479 518 468 468 519 467 467 505 468 468 519 456 456 506 468 468 507 480 480 520 481 481 521 468 468 507 481 481 521 469 469 508 469 469 508 481 481 521 482 482 522 469 469 508 482 482 522 470 470 509 470 470 509 482 482 522 483 483 523 470 470 509 483 483 523 471 471 510 471 471 510 483 483 523 484 484 524 471 471 510 484 484 524 472 472 511 472 472 511 484 484 524 485 485 525 472 472 511 485 485 525 473 473 512 473 473 512 485 485 525 486 486 526 473 473 512 486 486 526 474 474 513 474 474 513 486 486 526 487 487 527 474 474 513 487 487 527 475 475 514 475 475 514 487 487 527 488 488 528 475 475 514 488 488 528 476 476 515 476 476 515 488 488 528 489 489 529 476 476 515 489 489 529 477 477 516 477 477 516 489 489 529 490 490 530 477 477 516 490 490 530 478 478 517 478 478 517 490 490 530 491 491 531 478 478 517 491 491 531 479 479 518 479 479 518 491 491 531 480 480 532 479 479 518 480 480 532 468 468 519 480 480 520 492 492 533 493 493 534 480 480 520 493 493 534 481 481 521 481 481 521 493 493 534 494 494 535 481 481 521 494 494 535 482 482 522 482 482 522 494 494 535 495 495 536 482 482 522 495 495 536 483 483 523 483 483 523 495 495 536 496 496 537 483 483 523 496 496 537 484 484 524 484 484 524 496 496 537 497 497 538 484 484 524 497 497 538 485 485 525 485 485 525 497 497 538 498 498 539 485 485 525 498 498 539 486 486 526 486 486 526 498 498 539 499 499 540 486 486 526 499 499 540 487 487 527 487 487 527 499 499 540 500 500 541 487 487 527 500 500 541 488 488 528 488 488 528 500 500 541 501 501 542 488 488 528 501 501 542 489 489 529 489 489 529 501 501 542 502 502 543 489 489 529 502 502 543 490 490 530 490 490 530 502 502 543 503 503 544 490 490 530 503 503 544 491 491 531 491 491 531 503 503 544 492 492 545 491 491 531 492 492 545 480 480 532 492 492 533 504 504 546 505 505 547 492 492 533 505 505 547 493 493 534 493 493 534 505 505 547 506 506 548 493 493 534 506 506 548 494 494 535 494 494 535 506 506 548 507 507 549 494 494 535 507 507 549 495 495 536 495 495 536 507 507 549 508 508 550 495 495 536 508 508 550 496 496 537 496 496 537 508 508 550 509 509 551 496 496 537 509 509 551 497 497 538 497 497 538 509 509 551 510 510 552 497 497 538 510 510 552 498 498 539 498 498 539 510 510 552 511 511 553 498 498 539 511 511 553 499 499 540 499 499 540 511 511 553 512 512 554 499 499 540 512 512 554 500 500 541 500 500 541 512 512 554 513 513 555 500 500 541 513 513 555 501 501 542 501 501 542 513 513 555 514 514 556 501 501 542 514 514 556 502 502 543 502 502 543 514 514 556 515 515 557 502 502 543 515 515 557 503 503 544 503 503 544 515 515 557 504 504 558 503 503 544 504 504 558 492 492 545 504 504 546 516 516 559 517 517 560 504 504 546 517 517 560 505 505 547 505 505 547 517 517 560 518 518 561 505 505 547 518 518 561 506 506 548 506 506 548 518 518 561 519 519 562 506 506 548 519 519 562 507 507 549 507 507 549 519 519 562 520 520 563 507 507 549 520 520 563 508 508 550 508 508 550 520 520 563 521 521 564 508 508 550 521 521 564 509 509 551 509 509 551 521 521 564 522 522 565 509 509 551 522 522 565 510 510 552 510 510 552 522 522 565 523 523 566 510 510 552 523 523 566 511 511 553 511 511 553 523 523 566 524 524 567 511 511 553 524 524 567 512 512 554 512 512 554 524 524 567 525 525 568 512 512 554 525 525 568 513 513 555 513 513 555 525 525 568 526 526 569 513 513 555 526 526 569 514 514 556 514 514 556 526 526 569 527 527 570 514 514 556 527 527 570 515 515 557 515 515 557 527 527 570 516 516 571 515 515 557 516 516 571 504 504 558 516 516 559 528 528 572 529 529 573 516 516 559 529 529 573 517 517 560 517 517 560 529 529 573 530 530 574 517 517 560 530 530 574 518 518 561 518 518 561 530 530 574 531 531 575 518 518 561 531 531 575 519 519 562 519 519 562 531 531 575 532 532 576 519 519 562 532 532 576 520 520 563 520 520 563 532 532 576 533 533 577 520 520 563 533 533 577 521 521 564 521 521 564 533 533 577 534 534 578 521 521 564 534 534 578 522 522 565 522 522 565 534 534 578 535 535 579 522 522 565 535 535 579 523 523 566 523 523 566 535 535 579 536 536 580 523 523 566 536 536 580 524 524 567 524 524 567 536 536 580 537 537 581 524 524 567 537 537 581 525 525 568 525 525 568 537 537 581 538 538 582 525 525 568 538 538 582 526 526 569 526 526 569 538 538 582 539 539 583 526 526 569 539 539 583 527 527 570 527 527 570 539 539 583 528 528 584 527 527 570 528 528 584 516 516 571 528 528 572 540 540 585 541 541 586 528 528 572 541 541 586 529 529 573 529 529 573 541 541 586 542 542 587 529 529 573 542 542 587 530 530 574 530 530 574 542 542 587 543 543 588 530 530 574 543 543 588 531 531 575 531 531 575 543 543 588 544 544 589 531 531 575 544 544 589 532 532 576 532 532 576 544 544 589 545 545 590 532 532 576 545 545 590 533 533 577 533 533 577 545 545 590 546 546 591 533 533 577 546 546 591 534 534 578 534 534 578 546 546 591 547 547 592 534 534 578 547 547 592 535 535 579 535 535 579 547 547 592 548 548 593 535 535 579 548 548 593 536 536 580 536 536 580 548 548 593 549 549 594 536 536 580 549 549 594 537 537 581 537 537 581 549 549 594 550 550 595 537 537 581 550 550 595 538 538 582 538 538 582 550 550 595 551 551 596 538 538 582 551 551 596 539 539 583 539 539 583 551 551 596 540 540 597 539 539 583 540 540 597 528 528 584 540 540 585 552 552 598 553 553 599 540 540 585 553 553 599 541 541 586 541 541 586 553 553 599 554 554 600 541 541 586 554 554 600 542 542 587 542 542 587 554 554 600 555 555 601 542 542 587 555 555 601 543 543 588 543 543 588 555 555 601 556 556 602 543 543 588 556 556 602 544 544 589 544 544 589 556 556 602 557 557 603 544 544 589 557 557 603 545 545 590 545 545 590 557 557 603 558 558 604 545 545 590 558 558 604 546 546 591 546 546 591 558 558 604 559 559 605 546 546 591 559 559 605 547 547 592 547 547 592 559 559 605 560 560 606 547 547 592 560 560 606 548 548 593 548 548 593 560 560 606 561 561 607 548 548 593 561 561 607 549 549 594 549 549 594 561 561 607 562 562 608 549 549 594 562 562 608 550 550 595 550 550 595 562 562 608 563 563 609 550 550 595 563 563 609 551 551 596 551 551 596 563 563 609 552 552 610 551 551 596 552 552 610 540 540 597 552 552 598 564 564 611 565 565 612 552 552 598 565 565 612 553 553 599 553 553 599 565 565 612 566 566 613 553 553 599 566 566 613 554 554 600 554 554 600 566 566 613 567 567 614 554 554 600 567 567 614 555 555 601 555 555 601 567 567 614 568 568 615 555 555 601 568 568 615 556 556 602 556 556 602 568 568 615 569 569 616 556 556 602 569 569 616 557 557 603 557 557 603 569 569 616 570 570 617 557 557 603 570 570 617 558 558 604 558 558 604 570 570 617 571 571 618 558 558 604 571 571 618 559 559 605 559 559 605 571 571 618 572 572 619 559 559 605 572 572 619 560 560 606 560 560 606 572 572 619 573 573 620 560 560 606 573 573 620 561 561 607 561 561 607 573 573 620 574 574 621 561 561 607 574 574 621 562 562 608 562 562 608 574 574 621 575 575 622 562 562 608 575 575 622 563 563 609 563 563 609 575 575 622 564 564 623 563 563 609 564 564 623 552 552 610 564 564 611 576 576 624 577 577 625 564 564 611 577 577 625 565 565 612 565 565 612 577 577 625 578 578 626 565 565 612 578 578 626 566 566 613 566 566 613 578 578 626 579 579 627 566 566 613 579 579 627 567 567 614 567 567 614 579 579 627 580 580 628 567 567 614 580 580 628 568 568 615 568 568 615 580 580 628 581 581 629 568 568 615 581 581 629 569 569 616 569 569 616 581 581 629 582 582 630 569 569 616 582 582 630 570 570 617 570 570 617 582 582 630 583 583 631 570 570 617 583 583 631 571 571 618 571 571 618 583 583 631 584 584 632 571 571 618 584 584 632 572 572 619 572 572 619 584 584 632 585 585 633 572 572 619 585 585 633 573 573 620 573 573 620 585 585 633 586 586 634 573 573 620 586 586 634 574 574 621 574 574 621 586 586 634 587 587 635 574 574 621 587 587 635 575 575 622 575 575 622 587 587 635 576 576 636 575 575 622 576 576 636 564 564 623 576 576 624 588 588 637 589 589 638 576 576 624 589 589 638 577 577 625 577 577 625 589 589 638 590 590 639 577 577 625 590 590 639 578 578 626 578 578 626 590 590 639 591 591 640 578 578 626 591 591 640 579 579 627 579 579 627 591 591 640 592 592 641 579 579 627 592 592 641 580 580 628 580 580 628 592 592 641 593 593 642 580 580 628 593 593 642 581 581 629 581 581 629 593 593 642 594 594 643 581 581 629 594 594 643 582 582 630 582 582 630 594 594 643 595 595 644 582 582 630 595 595 644 583 583 631 583 583 631 595 595 644 596 596 645 583 583 631 596 596 645 584 584 632 584 584 632 596 596 645 597 597 646 584 584 632 597 597 646 585 585 633 585 585 633 597 597 646 598 598 647 585 585 633 598 598 647 586 586 634 586 586 634 598 598 647 599 599 648 586 586 634 599 599 648 587 587 635 587 587 635 599 599 648 588 588 649 587 587 635 588 588 649 576 576 636 588 588 637 600 600 650 601 601 651 588 588 637 601 601 651 589 589 638 589 589 638 601 601 651 602 602 652 589 589 638 602 602 652 590 590 639 590 590 639 602 602 652 603 603 653 590 590 639 603 603 653 591 591 640 591 591 640 603 603 653 604 604 654 591 591 640 604 604 654 592 592 641 592 592 641 604 604 654 605 605 655 592 592 641 605 605 655 593 593 642 593 593 642 605 605 655 606 606 656 593 593 642 606 606 656 594 594 643 594 594 643 606 606 656 607 607 657 594 594 643 607 607 657 595 595 644 595 595 644 607 607 657 608 608 658 595 595 644 608 608 658 596 596 645 596 596 645 608 608 658 609 609 659 596 596 645 609 609 659 597 597 646 597 597 646 609 609 659 610 610 660 597 597 646 610 610 660 598 598 647 598 598 647 610 610 660 611 611 661 598 598 647 611 611 661 599 599 648 599 599 648 611 611 661 600 600 662 599 599 648 600 600 662 588 588 649 600 600 650 612 612 663 613 613 664 600 600 650 613 613 664 601 601 651 601 601 651 613 613 664 614 614 665 601 601 651 614 614 665 602 602 652 602 602 652 614 614 665 615 615 666 602 602 652 615 615 666 603 603 653 603 603 653 615 615 666 616 616 667 603 603 653 616 616 667 604 604 654 604 604 654 616 616 667 617 617 668 604 604 654 617 617 668 605 605 655 605 605 655 617 617 668 618 618 669 605 605 655 618 618 669 606 606 656 606 606 656 618 618 669 619 619 670 606 606 656 619 619 670 607 607 657 607 607 657 619 619 670 620 620 671 607 607 657 620 620 671 608 608 658 608 608 658 620 620 671 621 621 672 608 608 658 621 621 672 609 609 659 609 609 659 621 621 672 622 622 673 609 609 659 622 622 673 610 610 660 610 610 660 622 622 673 623 623 674 610 610 660 623 623 674 611 611 661 611 611 661 623 623 674 612 612 675 611 611 661 612 612 675 600 600 662 612 612 663 624 624 676 625 625 677 612 612 663 625 625 677 613 613 664 613 613 664 625 625 677 626 626 678 613 613 664 626 626 678 614 614 665 614 614 665 626 626 678 627 627 679 614 614 665 627 627 679 615 615 666 615 615 666 627 627 679 628 628 680 615 615 666 628 628 680 616 616 667 616 616 667 628 628 680 629 629 681 616 616 667 629 629 681 617 617 668 617 617 668 629 629 681 630 630 682 617 617 668 630 630 682 618 618 669 618 618 669 630 630 682 631 631 683 618 618 669 631 631 683 619 619 670 619 619 670 631 631 683 632 632 684 619 619 670 632 632 684 620 620 671 620 620 671 632 632 684 633 633 685 620 620 671 633 633 685 621 621 672 621 621 672 633 633 685 634 634 686 621 621 672 634 634 686 622 622 673 622 622 673 634 634 686 635 635 687 622 622 673 635 635 687 623 623 674 623 623 674 635 635 687 624 624 688 623 623 674 624 624 688 612 612 675 624 624 676 636 636 689 637 637 690 624 624 676 637 637 690 625 625 677 625 625 677 637 637 690 638 638 691 625 625 677 638 638 691 626 626 678 626 626 678 638 638 691 639 639 692 626 626 678 639 639 692 627 627 679 627 627 679 639 639 692 640 640 693 627 627 679 640 640 693 628 628 680 628 628 680 640 640 693 641 641 694 628 628 680 641 641 694 629 629 681 629 629 681 641 641 694 642 642 695 629 629 681 642 642 695 630 630 682 630 630 682 642 642 695 643 643 696 630 630 682 643 643 696 631 631 683 631 631 683 643 643 696 644 644 697 631 631 683 644 644 697 632 632 684 632 632 684 644 644 697 645 645 698 632 632 684 645 645 698 633 633 685 633 633 685 645 645 698 646 646 699 633 633 685 646 646 699 634 634 686 634 634 686 646 646 699 647 647 700 634 634 686 647 647 700 635 635 687 635 635 687 647 647 700 636 636 701 635 635 687 636 636 701 624 624 688 636 636 689 648 648 702 649 649 703 636 636 689 649 649 703 637 637 690 637 637 690 649 649 703 650 650 704 637 637 690 650 650 704 638 638 691 638 638 691 650 650 704 651 651 705 638 638 691 651 651 705 639 639 692 639 639 692 651 651 705 652 652 706 639 639 692 652 652 706 640 640 693 640 640 693 652 652 706 653 653 707 640 640 693 653 653 707 641 641 694 641 641 694 653 653 707 654 654 708 641 641 694 654 654 708 642 642 695 642 642 695 654 654 708 655 655 709 642 642 695 655 655 709 643 643 696 643 643 696 655 655 709 656 656 710 643 643 696 656 656 710 644 644 697 644 644 697 656 656 710 657 657 711 644 644 697 657 657 711 645 645 698 645 645 698 657 657 711 658 658 712 645 645 698 658 658 712 646 646 699 646 646 699 658 658 712 659 659 713 646 646 699 659 659 713 647 647 700 647 647 700 659 659 713 648 648 714 647 647 700 648 648 714 636 636 701 648 648 702 660 660 715 661 661 716 648 648 702 661 661 716 649 649 703 649 649 703 661 661 716 662 662 717 649 649 703 662 662 717 650 650 704 650 650 704 662 662 717 663 663 718 650 650 704 663 663 718 651 651 705 651 651 705 663 663 718 664 664 719 651 651 705 664 664 719 652 652 706 652 652 706 664 664 719 665 665 720 652 652 706 665 665 720 653 653 707 653 653 707 665 665 720 666 666 721 653 653 707 666 666 721 654 654 708 654 654 708 666 666 721 667 667 722 654 654 708 667 667 722 655 655 709 655 655 709 667 667 722 668 668 723 655 655 709 668 668 723 656 656 710 656 656 710 668 668 723 669 669 724 656 656 710 669 669 724 657 657 711 657 657 711 669 669 724 670 670 725 657 657 711 670 670 725 658 658 712 658 658 712 670 670 725 671 671 726 658 658 712 671 671 726 659 659 713 659 659 713 671 671 726 660 660 727 659 659 713 660 660 727 648 648 714 660 660 715 672 672 728 673 673 729 660 660 715 673 673 729 661 661 716 661 661 716 673 673 729 674 674 730 661 661 716 674 674 730 662 662 717 662 662 717 674 674 730 675 675 731 662 662 717 675 675 731 663 663 718 663 663 718 675 675 731 676 676 732 663 663 718 676 676 732 664 664 719 664 664 719 676 676 732 677 677 733 664 664 719 677 677 733 665 665 720 665 665 720 677 677 733 678 678 734 665 665 720 678 678 734 666 666 721 666 666 721 678 678 734 679 679 735 666 666 721 679 679 735 667 667 722 667 667 722 679 679 735 680 680 736 667 667 722 680 680 736 668 668 723 668 668 723 680 680 736 681 681 737 668 668 723 681 681 737 669 669 724 669 669 724 681 681 737 682 682 738 669 669 724 682 682 738 670 670 725 670 670 725 682 682 738 683 683 739 670 670 725 683 683 739 671 671 726 671 671 726 683 683 739 672 672 740 671 671 726 672 672 740 660 660 727 672 672 728 684 684 741 685 685 742 672 672 728 685 685 742 673 673 729 673 673 729 685 685 742 686 686 743 673 673 729 686 686 743 674 674 730 674 674 730 686 686 743 687 687 744 674 674 730 687 687 744 675 675 731 675 675 731 687 687 744 688 688 745 675 675 731 688 688 745 676 676 732 676 676 732 688 688 745 689 689 746 676 676 732 689 689 746 677 677 733 677 677 733 689 689 746 690 690 747 677 677 733 690 690 747 678 678 734 678 678 734 690 690 747 691 691 748 678 678 734 691 691 748 679 679 735 679 679 735 691 691 748 692 692 749 679 679 735 692 692 749 680 680 736 680 680 736 692 692 749 693 693 750 680 680 736 693 693 750 681 681 737 681 681 737 693 693 750 694 694 751 681 681 737 694 694 751 682 682 738 682 682 738 694 694 751 695 695 752 682 682 738 695 695 752 683 683 739 683 683 739 695 695 752 684 684 753 683 683 739 684 684 753 672 672 740 684 684 741 696 696 754 697 697 755 684 684 741 697 697 755 685 685 742 685 685 742 697 697 755 698 698 756 685 685 742 698 698 756 686 686 743 686 686 743 698 698 756 699 699 757 686 686 743 699 699 757 687 687 744 687 687 744 699 699 757 700 700 758 687 687 744 700 700 758 688 688 745 688 688 745 700 700 758 701 701 759 688 688 745 701 701 759 689 689 746 689 689 746 701 701 759 702 702 760 689 689 746 702 702 760 690 690 747 690 690 747 702 702 760 703 703 761 690 690 747 703 703 761 691 691 748 691 691 748 703 703 761 704 704 762 691 691 748 704 704 762 692 692 749 692 692 749 704 704 762 705 705 763 692 692 749 705 705 763 693 693 750 693 693 750 705 705 763 706 706 764 693 693 750 706 706 764 694 694 751 694 694 751 706 706 764 707 707 765 694 694 751 707 707 765 695 695 752 695 695 752 707 707 765 696 696 766 695 695 752 696 696 766 684 684 753 696 696 754 708 708 767 709 709 768 696 696 754 709 709 768 697 697 755 697 697 755 709 709 768 710 710 769 697 697 755 710 710 769 698 698 756 698 698 756 710 710 769 711 711 770 698 698 756 711 711 770 699 699 757 699 699 757 711 711 770 712 712 771 699 699 757 712 712 771 700 700 758 700 700 758 712 712 771 713 713 772 700 700 758 713 713 772 701 701 759 701 701 759 713 713 772 714 714 773 701 701 759 714 714 773 702 702 760 702 702 760 714 714 773 715 715 774 702 702 760 715 715 774 703 703 761 703 703 761 715 715 774 716 716 775 703 703 761 716 716 775 704 704 762 704 704 762 716 716 775 717 717 776 704 704 762 717 717 776 705 705 763 705 705 763 717 717 776 718 718 777 705 705 763 718 718 777 706 706 764 706 706 764 718 718 777 719 719 778 706 706 764 719 719 778 707 707 765 707 707 765 719 719 778 708 708 779 707 707 765 708 708 779 696 696 766 708 708 767 720 720 780 721 721 781 708 708 767 721 721 781 709 709 768 709 709 768 721 721 781 722 722 782 709 709 768 722 722 782 710 710 769 710 710 769 722 722 782 723 723 783 710 710 769 723 723 783 711 711 770 711 711 770 723 723 783 724 724 784 711 711 770 724 724 784 712 712 771 712 712 771 724 724 784 725 725 785 712 712 771 725 725 785 713 713 772 713 713 772 725 725 785 726 726 786 713 713 772 726 726 786 714 714 773 714 714 773 726 726 786 727 727 787 714 714 773 727 727 787 715 715 774 715 715 774 727 727 787 728 728 788 715 715 774 728 728 788 716 716 775 716 716 775 728 728 788 729 729 789 716 716 775 729 729 789 717 717 776 717 717 776 729 729 789 730 730 790 717 717 776 730 730 790 718 718 777 718 718 777 730 730 790 731 731 791 718 718 777 731 731 791 719 719 778 719 719 778 731 731 791 720 720 792 719 719 778 720 720 792 708 708 779 720 720 780 732 732 793 733 733 794 720 720 780 733 733 794 721 721 781 721 721 781 733 733 794 734 734 795 721 721 781 734 734 795 722 722 782 722 722 782 734 734 795 735 735 796 722 722 782 735 735 796 723 723 783 723 723 783 735 735 796 736 736 797 723 723 783 736 736 797 724 724 784 724 724 784 736 736 797 737 737 798 724 724 784 737 737 798 725 725 785 725 725 785 737 737 798 738 738 799 725 725 785 738 738 799 726 726 786 726 726 786 738 738 799 739 739 800 726 726 786 739 739 800 727 727 787 727 727 787 739 739 800 740 740 801 727 727 787 740 740 801 728 728 788 728 728 788 740 740 801 741 741 802 728 728 788 741 741 802 729 729 789 729 729 789 741 741 802 742 742 803 729 729 789 742 742 803 730 730 790 730 730 790 742 742 803 743 743 804 730 730 790 743 743 804 731 731 791 731 731 791 743 743 804 732 732 805 731 731 791 732 732 805 720 720 792 732 732 793 744 744 806 745 745 807 732 732 793 745 745 807 733 733 794 733 733 794 745 745 807 746 746 808 733 733 794 746 746 808 734 734 795 734 734 795 746 746 808 747 747 809 734 734 795 747 747 809 735 735 796 735 735 796 747 747 809 748 748 810 735 735 796 748 748 810 736 736 797 736 736 797 748 748 810 749 749 811 736 736 797 749 749 811 737 737 798 737 737 798 749 749 811 750 750 812 737 737 798 750 750 812 738 738 799 738 738 799 750 750 812 751 751 813 738 738 799 751 751 813 739 739 800 739 739 800 751 751 813 752 752 814 739 739 800 752 752 814 740 740 801 740 740 801 752 752 814 753 753 815 740 740 801 753 753 815 741 741 802 741 741 802 753 753 815 754 754 816 741 741 802 754 754 816 742 742 803 742 742 803 754 754 816 755 755 817 742 742 803 755 755 817 743 743 804 743 743 804 755 755 817 744 744 818 743 743 804 744 744 818 732 732 805 744 744 806 756 756 819 757 757 820 744 744 806 757 757 820 745 745 807 745 745 807 757 757 820 758 758 821 745 745 807 758 758 821 746 746 808 746 746 808 758 758 821 759 759 822 746 746 808 759 759 822 747 747 809 747 747 809 759 759 822 760 760 823 747 747 809 760 760 823 748 748 810 748 748 810 760 760 823 761 761 824 748 748 810 761 761 824 749 749 811 749 749 811 761 761 824 762 762 825 749 749 811 762 762 825 750 750 812 750 750 812 762 762 825 763 763 826 750 750 812 763 763 826 751 751 813 751 751 813 763 763 826 764 764 827 751 751 813 764 764 827 752 752 814 752 752 814 764 764 827 765 765 828 752 752 814 765 765 828 753 753 815 753 753 815 765 765 828 766 766 829 753 753 815 766 766 829 754 754 816 754 754 816 766 766 829 767 767 830 754 754 816 767 767 830 755 755 817 755 755 817 767 767 830 756 756 831 755 755 817 756 756 831 744 744 818 756 756 819 768 768 832 769 769 833 756 756 819 769 769 833 757 757 820 757 757 820 769 769 833 770 770 834 757 757 820 770 770 834 758 758 821 758 758 821 770 770 834 771 771 835 758 758 821 771 771 835 759 759 822 759 759 822 771 771 835 772 772 836 759 759 822 772 772 836 760 760 823 760 760 823 772 772 836 773 773 837 760 760 823 773 773 837 761 761 824 761 761 824 773 773 837 774 774 838 761 761 824 774 774 838 762 762 825 762 762 825 774 774 838 775 775 839 762 762 825 775 775 839 763 763 826 763 763 826 775 775 839 776 776 840 763 763 826 776 776 840 764 764 827 764 764 827 776 776 840 777 777 841 764 764 827 777 777 841 765 765 828 765 765 828 777 777 841 778 778 842 765 765 828 778 778 842 766 766 829 766 766 829 778 778 842 779 779 843 766 766 829 779 779 843 767 767 830 767 767 830 779 779 843 768 768 844 767 767 830 768 768 844 756 756 831 768 768 832 780 780 845 781 781 846 768 768 832 781 781 846 769 769 833 769 769 833 781 781 846 782 782 847 769 769 833 782 782 847 770 770 834 770 770 834 782 782 847 783 783 848 770 770 834 783 783 848 771 771 835 771 771 835 783 783 848 784 784 849 771 771 835 784 784 849 772 772 836 772 772 836 784 784 849 785 785 850 772 772 836 785 785 850 773 773 837 773 773 837 785 785 850 786 786 851 773 773 837 786 786 851 774 774 838 774 774 838 786 786 851 787 787 852 774 774 838 787 787 852 775 775 839 775 775 839 787 787 852 788 788 853 775 775 839 788 788 853 776 776 840 776 776 840 788 788 853 789 789 854 776 776 840 789 789 854 777 777 841 777 777 841 789 789 854 790 790 855 777 777 841 790 790 855 778 778 842 778 778 842 790 790 855 791 791 856 778 778 842 791 791 856 779 779 843 779 779 843 791 791 856 780 780 857 779 779 843 780 780 857 768 768 844 780 780 845 792 792 858 793 793 859 780 780 845 793 793 859 781 781 846 781 781 846 793 793 859 794 794 860 781 781 846 794 794 860 782 782 847 782 782 847 794 794 860 795 795 861 782 782 847 795 795 861 783 783 848 783 783 848 795 795 861 796 796 862 783 783 848 796 796 862 784 784 849 784 784 849 796 796 862 797 797 863 784 784 849 797 797 863 785 785 850 785 785 850 797 797 863 798 798 864 785 785 850 798 798 864 786 786 851 786 786 851 798 798 864 799 799 865 786 786 851 799 799 865 787 787 852 787 787 852 799 799 865 800 800 866 787 787 852 800 800 866 788 788 853 788 788 853 800 800 866 801 801 867 788 788 853 801 801 867 789 789 854 789 789 854 801 801 867 802 802 868 789 789 854 802 802 868 790 790 855 790 790 855 802 802 868 803 803 869 790 790 855 803 803 869 791 791 856 791 791 856 803 803 869 792 792 870 791 791 856 792 792 870 780 780 857 792 792 858 804 804 871 805 805 872 792 792 858 805 805 872 793 793 859 793 793 859 805 805 872 806 806 873 793 793 859 806 806 873 794 794 860 794 794 860 806 806 873 807 807 874 794 794 860 807 807 874 795 795 861 795 795 861 807 807 874 808 808 875 795 795 861 808 808 875 796 796 862 796 796 862 808 808 875 809 809 876 796 796 862 809 809 876 797 797 863 797 797 863 809 809 876 810 810 877 797 797 863 810 810 877 798 798 864 798 798 864 810 810 877 811 811 878 798 798 864 811 811 878 799 799 865 799 799 865 811 811 878 812 812 879 799 799 865 812 812 879 800 800 866 800 800 866 812 812 879 813 813 880 800 800 866 813 813 880 801 801 867 801 801 867 813 813 880 814 814 881 801 801 867 814 814 881 802 802 868 802 802 868 814 814 881 815 815 882 802 802 868 815 815 882 803 803 869 803 803 869 815 815 882 804 804 883 803 803 869 804 804 883 792 792 870 804 804 871 816 816 884 817 817 885 804 804 871 817 817 885 805 805 872 805 805 872 817 817 885 818 818 886 805 805 872 818 818 886 806 806 873 806 806 873 818 818 886 819 819 887 806 806 873 819 819 887 807 807 874 807 807 874 819 819 887 820 820 888 807 807 874 820 820 888 808 808 875 808 808 875 820 820 888 821 821 889 808 808 875 821 821 889 809 809 876 809 809 876 821 821 889 822 822 890 809 809 876 822 822 890 810 810 877 810 810 877 822 822 890 823 823 891 810 810 877 823 823 891 811 811 878 811 811 878 823 823 891 824 824 892 811 811 878 824 824 892 812 812 879 812 812 879 824 824 892 825 825 893 812 812 879 825 825 893 813 813 880 813 813 880 825 825 893 826 826 894 813 813 880 826 826 894 814 814 881 814 814 881 826 826 894 827 827 895 814 814 881 827 827 895 815 815 882 815 815 882 827 827 895 816 816 896 815 815 882 816 816 896 804 804 883 816 816 884 828 828 897 829 829 898 816 816 884 829 829 898 817 817 885 817 817 885 829 829 898 830 830 899 817 817 885 830 830 899 818 818 886 818 818 886 830 830 899 831 831 900 818 818 886 831 831 900 819 819 887 819 819 887 831 831 900 832 832 901 819 819 887 832 832 901 820 820 888 820 820 888 832 832 901 833 833 902 820 820 888 833 833 902 821 821 889 821 821 889 833 833 902 834 834 903 821 821 889 834 834 903 822 822 890 822 822 890 834 834 903 835 835 904 822 822 890 835 835 904 823 823 891 823 823 891 835 835 904 836 836 905 823 823 891 836 836 905 824 824 892 824 824 892 836 836 905 837 837 906 824 824 892 837 837 906 825 825 893 825 825 893 837 837 906 838 838 907 825 825 893 838 838 907 826 826 894 826 826 894 838 838 907 839 839 908 826 826 894 839 839 908 827 827 895 827 827 895 839 839 908 828 828 909 827 827 895 828 828 909 816 816 896 828 828 897 840 840 910 841 841 911 828 828 897 841 841 911 829 829 898 829 829 898 841 841 911 842 842 912 829 829 898 842 842 912 830 830 899 830 830 899 842 842 912 843 843 913 830 830 899 843 843 913 831 831 900 831 831 900 843 843 913 844 844 914 831 831 900 844 844 914 832 832 901 832 832 901 844 844 914 845 845 915 832 832 901 845 845 915 833 833 902 833 833 902 845 845 915 846 846 916 833 833 902 846 846 916 834 834 903 834 834 903 846 846 916 847 847 917 834 834 903 847 847 917 835 835 904 835 835 904 847 847 917 848 848 918 835 835 904 848 848 918 836 836 905 836 836 905 848 848 918 849 849 919 836 836 905 849 849 919 837 837 906 837 837 906 849 849 919 850 850 920 837 837 906 850 850 920 838 838 907 838 838 907 850 850 920 851 851 921 838 838 907 851 851 921 839 839 908 839 839 908 851 851 921 840 840 922 839 839 908 840 840 922 828 828 909 840 840 910 852 852 923 853 853 924 840 840 910 853 853 924 841 841 911 841 841 911 853 853 924 854 854 925 841 841 911 854 854 925 842 842 912 842 842 912 854 854 925 855 855 926 842 842 912 855 855 926 843 843 913 843 843 913 855 855 926 856 856 927 843 843 913 856 856 927 844 844 914 844 844 914 856 856 927 857 857 928 844 844 914 857 857 928 845 845 915 845 845 915 857 857 928 858 858 929 845 845 915 858 858 929 846 846 916 846 846 916 858 858 929 859 859 930 846 846 916 859 859 930 847 847 917 847 847 917 859 859 930 860 860 931 847 847 917 860 860 931 848 848 918 848 848 918 860 860 931 861 861 932 848 848 918 861 861 932 849 849 919 849 849 919 861 861 932 862 862 933 849 849 919 862 862 933 850 850 920 850 850 920 862 862 933 863 863 934 850 850 920 863 863 934 851 851 921 851 851 921 863 863 934 852 852 935 851 851 921 852 852 935 840 840 922 852 852 923 864 864 936 865 865 937 852 852 923 865 865 937 853 853 924 853 853 924 865 865 937 866 866 938 853 853 924 866 866 938 854 854 925 854 854 925 866 866 938 867 867 939 854 854 925 867 867 939 855 855 926 855 855 926 867 867 939 868 868 940 855 855 926 868 868 940 856 856 927 856 856 927 868 868 940 869 869 941 856 856 927 869 869 941 857 857 928 857 857 928 869 869 941 870 870 942 857 857 928 870 870 942 858 858 929 858 858 929 870 870 942 871 871 943 858 858 929 871 871 943 859 859 930 859 859 930 871 871 943 872 872 944 859 859 930 872 872 944 860 860 931 860 860 931 872 872 944 873 873 945 860 860 931 873 873 945 861 861 932 861 861 932 873 873 945 874 874 946 861 861 932 874 874 946 862 862 933 862 862 933 874 874 946 875 875 947 862 862 933 875 875 947 863 863 934 863 863 934 875 875 947 864 864 948 863 863 934 864 864 948 852 852 935 864 864 936 876 876 949 877 877 950 864 864 936 877 877 950 865 865 937 865 865 937 877 877 950 878 878 951 865 865 937 878 878 951 866 866 938 866 866 938 878 878 951 879 879 952 866 866 938 879 879 952 867 867 939 867 867 939 879 879 952 880 880 953 867 867 939 880 880 953 868 868 940 868 868 940 880 880 953 881 881 954 868 868 940 881 881 954 869 869 941 869 869 941 881 881 954 882 882 955 869 869 941 882 882 955 870 870 942 870 870 942 882 882 955 883 883 956 870 870 942 883 883 956 871 871 943 871 871 943 883 883 956 884 884 957 871 871 943 884 884 957 872 872 944 872 872 944 884 884 957 885 885 958 872 872 944 885 885 958 873 873 945 873 873 945 885 885 958 886 886 959 873 873 945 886 886 959 874 874 946 874 874 946 886 886 959 887 887 960 874 874 946 887 887 960 875 875 947 875 875 947 887 887 960 876 876 961 875 875 947 876 876 961 864 864 948 876 876 949 888 888 962 889 889 963 876 876 949 889 889 963 877 877 950 877 877 950 889 889 963 890 890 964 877 877 950 890 890 964 878 878 951 878 878 951 890 890 964 891 891 965 878 878 951 891 891 965 879 879 952 879 879 952 891 891 965 892 892 966 879 879 952 892 892 966 880 880 953 880 880 953 892 892 966 893 893 967 880 880 953 893 893 967 881 881 954 881 881 954 893 893 967 894 894 968 881 881 954 894 894 968 882 882 955 882 882 955 894 894 968 895 895 969 882 882 955 895 895 969 883 883 956 883 883 956 895 895 969 896 896 970 883 883 956 896 896 970 884 884 957 884 884 957 896 896 970 897 897 971 884 884 957 897 897 971 885 885 958 885 885 958 897 897 971 898 898 972 885 885 958 898 898 972 886 886 959 886 886 959 898 898 972 899 899 973 886 886 959 899 899 973 887 887 960 887 887 960 899 899 973 888 888 974 887 887 960 888 888 974 876 876 961 888 888 962 900 900 975 901 901 976 888 888 962 901 901 976 889 889 963 889 889 963 901 901 976 902 902 977 889 889 963 902 902 977 890 890 964 890 890 964 902 902 977 903 903 978 890 890 964 903 903 978 891 891 965 891 891 965 903 903 978 904 904 979 891 891 965 904 904 979 892 892 966 892 892 966 904 904 979 905 905 980 892 892 966 905 905 980 893 893 967 893 893 967 905 905 980 906 906 981 893 893 967 906 906 981 894 894 968 894 894 968 906 906 981 907 907 982 894 894 968 907 907 982 895 895 969 895 895 969 907 907 982 908 908 983 895 895 969 908 908 983 896 896 970 896 896 970 908 908 983 909 909 984 896 896 970 909 909 984 897 897 971 897 897 971 909 909 984 910 910 985 897 897 971 910 910 985 898 898 972 898 898 972 910 910 985 911 911 986 898 898 972 911 911 986 899 899 973 899 899 973 911 911 986 900 900 987 899 899 973 900 900 987 888 888 974 900 900 975 912 912 988 913 913 989 900 900 975 913 913 989 901 901 976 901 901 976 913 913 989 914 914 990 901 901 976 914 914 990 902 902 977 902 902 977 914 914 990 915 915 991 902 902 977 915 915 991 903 903 978 903 903 978 915 915 991 916 916 992 903 903 978 916 916 992 904 904 979 904 904 979 916 916 992 917 917 993 904 904 979 917 917 993 905 905 980 905 905 980 917 917 993 918 918 994 905 905 980 918 918 994 906 906 981 906 906 981 918 918 994 919 919 995 906 906 981 919 919 995 907 907 982 907 907 982 919 919 995 920 920 996 907 907 982 920 920 996 908 908 983 908 908 983 920 920 996 921 921 997 908 908 983 921 921 997 909 909 984 909 909 984 921 921 997 922 922 998 909 909 984 922 922 998 910 910 985 910 910 985 922 922 998 923 923 999 910 910 985 923 923 999 911 911 986 911 911 986 923 923 999 912 912 1000 911 911 986 912 912 1000 900 900 987 912 912 988 924 924 1001 925 925 1002 912 912 988 925 925 1002 913 913 989 913 913 989 925 925 1002 926 926 1003 913 913 989 926 926 1003 914 914 990 914 914 990 926 926 1003 927 927 1004 914 914 990 927 927 1004 915 915 991 915 915 991 927 927 1004 928 928 1005 915 915 991 928 928 1005 916 916 992 916 916 992 928 928 1005 929 929 1006 916 916 992 929 929 1006 917 917 993 917 917 993 929 929 1006 930 930 1007 917 917 993 930 930 1007 918 918 994 918 918 994 930 930 1007 931 931 1008 918 918 994 931 931 1008 919 919 995 919 919 995 931 931 1008 932 932 1009 919 919 995 932 932 1009 920 920 996 920 920 996 932 932 1009 933 933 1010 920 920 996 933 933 1010 921 921 997 921 921 997 933 933 1010 934 934 1011 921 921 997 934 934 1011 922 922 998 922 922 998 934 934 1011 935 935 1012 922 922 998 935 935 1012 923 923 999 923 923 999 935 935 1012 924 924 1013 923 923 999 924 924 1013 912 912 1000 924 924 1001 936 936 1014 937 937 1015 924 924 1001 937 937 1015 925 925 1002 925 925 1002 937 937 1015 938 938 1016 925 925 1002 938 938 1016 926 926 1003 926 926 1003 938 938 1016 939 939 1017 926 926 1003 939 939 1017 927 927 1004 927 927 1004 939 939 1017 940 940 1018 927 927 1004 940 940 1018 928 928 1005 928 928 1005 940 940 1018 941 941 1019 928 928 1005 941 941 1019 929 929 1006 929 929 1006 941 941 1019 942 942 1020 929 929 1006 942 942 1020 930 930 1007 930 930 1007 942 942 1020 943 943 1021 930 930 1007 943 943 1021 931 931 1008 931 931 1008 943 943 1021 944 944 1022 931 931 1008 944 944 1022 932 932 1009 932 932 1009 944 944 1022 945 945 1023 932 932 1009 945 945 1023 933 933 1010 933 933 1010 945 945 1023 946 946 1024 933 933 1010 946 946 1024 934 934 1011 934 934 1011 946 946 1024 947 947 1025 934 934 1011 947 947 1025 935 935 1012 935 935 1012 947 947 1025 936 936 1026 935 935 1012 936 936 1026 924 924 1013 936 936 1014 948 948 1027 949 949 1028 936 936 1014 949 949 1028 937 937 1015 937 937 1015 949 949 1028 950 950 1029 937 937 1015 950 950 1029 938 938 1016 938 938 1016 950 950 1029 951 951 1030 938 938 1016 951 951 1030 939 939 1017 939 939 1017 951 951 1030 952 952 1031 939 939 1017 952 952 1031 940 940 1018 940 940 1018 952 952 1031 953 953 1032 940 940 1018 953 953 1032 941 941 1019 941 941 1019 953 953 1032 954 954 1033 941 941 1019 954 954 1033 942 942 1020 942 942 1020 954 954 1033 955 955 1034 942 942 1020 955 955 1034 943 943 1021 943 943 1021 955 955 1034 956 956 1035 943 943 1021 956 956 1035 944 944 1022 944 944 1022 956 956 1035 957 957 1036 944 944 1022 957 957 1036 945 945 1023 945 945 1023 957 957 1036 958 958 1037 945 945 1023 958 958 1037 946 946 1024 946 946 1024 958 958 1037 959 959 1038 946 946 1024 959 959 1038 947 947 1025 947 947 1025 959 959 1038 948 948 1039 947 947 1025 948 948 1039 936 936 1026 948 948 1027 960 960 1040 961 961 1041 948 948 1027 961 961 1041 949 949 1028 949 949 1028 961 961 1041 962 962 1042 949 949 1028 962 962 1042 950 950 1029 950 950 1029 962 962 1042 963 963 1043 950 950 1029 963 963 1043 951 951 1030 951 951 1030 963 963 1043 964 964 1044 951 951 1030 964 964 1044 952 952 1031 952 952 1031 964 964 1044 965 965 1045 952 952 1031 965 965 1045 953 953 1032 953 953 1032 965 965 1045 966 966 1046 953 953 1032 966 966 1046 954 954 1033 954 954 1033 966 966 1046 967 967 1047 954 954 1033 967 967 1047 955 955 1034 955 955 1034 967 967 1047 968 968 1048 955 955 1034 968 968 1048 956 956 1035 956 956 1035 968 968 1048 969 969 1049 956 956 1035 969 969 1049 957 957 1036 957 957 1036 969 969 1049 970 970 1050 957 957 1036 970 970 1050 958 958 1037 958 958 1037 970 970 1050 971 971 1051 958 958 1037 971 971 1051 959 959 1038 959 959 1038 971 971 1051 960 960 1052 959 959 1038 960 960 1052 948 948 1039 960 960 1040 972 972 1053 973 973 1054 960 960 1040 973 973 1054 961 961 1041 961 961 1041 973 973 1054 974 974 1055 961 961 1041 974 974 1055 962 962 1042 962 962 1042 974 974 1055 975 975 1056 962 962 1042 975 975 1056 963 963 1043 963 963 1043 975 975 1056 976 976 1057 963 963 1043 976 976 1057 964 964 1044 964 964 1044 976 976 1057 977 977 1058 964 964 1044 977 977 1058 965 965 1045 965 965 1045 977 977 1058 978 978 1059 965 965 1045 978 978 1059 966 966 1046 966 966 1046 978 978 1059 979 979 1060 966 966 1046 979 979 1060 967 967 1047 967 967 1047 979 979 1060 980 980 1061 967 967 1047 980 980 1061 968 968 1048 968 968 1048 980 980 1061 981 981 1062 968 968 1048 981 981 1062 969 969 1049 969 969 1049 981 981 1062 982 982 1063 969 969 1049 982 982 1063 970 970 1050 970 970 1050 982 982 1063 983 983 1064 970 970 1050 983 983 1064 971 971 1051 971 971 1051 983 983 1064 972 972 1065 971 971 1051 972 972 1065 960 960 1052 972 972 1053 984 984 1066 985 985 1067 972 972 1053 985 985 1067 973 973 1054 973 973 1054 985 985 1067 986 986 1068 973 973 1054 986 986 1068 974 974 1055 974 974 1055 986 986 1068 987 987 1069 974 974 1055 987 987 1069 975 975 1056 975 975 1056 987 987 1069 988 988 1070 975 975 1056 988 988 1070 976 976 1057 976 976 1057 988 988 1070 989 989 1071 976 976 1057 989 989 1071 977 977 1058 977 977 1058 989 989 1071 990 990 1072 977 977 1058 990 990 1072 978 978 1059 978 978 1059 990 990 1072 991 991 1073 978 978 1059 991 991 1073 979 979 1060 979 979 1060 991 991 1073 992 992 1074 979 979 1060 992 992 1074 980 980 1061 980 980 1061 992 992 1074 993 993 1075 980 980 1061 993 993 1075 981 981 1062 981 981 1062 993 993 1075 994 994 1076 981 981 1062 994 994 1076 982 982 1063 982 982 1063 994 994 1076 995 995 1077 982 982 1063 995 995 1077 983 983 1064 983 983 1064 995 995 1077 984 984 1078 983 983 1064 984 984 1078 972 972 1065 984 984 1066 996 996 1079 997 997 1080 984 984 1066 997 997 1080 985 985 1067 985 985 1067 997 997 1080 998 998 1081 985 985 1067 998 998 1081 986 986 1068 986 986 1068 998 998 1081 999 999 1082 986 986 1068 999 999 1082 987 987 1069 987 987 1069 999 999 1082 1000 1000 1083 987 987 1069 1000 1000 1083 988 988 1070 988 988 1070 1000 1000 1083 1001 1001 1084 988 988 1070 1001 1001 1084 989 989 1071 989 989 1071 1001 1001 1084 1002 1002 1085 989 989 1071 1002 1002 1085 990 990 1072 990 990 1072 1002 1002 1085 1003 1003 1086 990 990 1072 1003 1003 1086 991 991 1073 991 991 1073 1003 1003 1086 1004 1004 1087 991 991 1073 1004 1004 1087 992 992 1074 992 992 1074 1004 1004 1087 1005 1005 1088 992 992 1074 1005 1005 1088 993 993 1075 993 993 1075 1005 1005 1088 1006 1006 1089 993 993 1075 1006 1006 1089 994 994 1076 994 994 1076 1006 1006 1089 1007 1007 1090 994 994 1076 1007 1007 1090 995 995 1077 995 995 1077 1007 1007 1090 996 996 1091 995 995 1077 996 996 1091 984 984 1078 996 996 1079 1008 1008 1092 1009 1009 1093 996 996 1079 1009 1009 1093 997 997 1080 997 997 1080 1009 1009 1093 1010 1010 1094 997 997 1080 1010 1010 1094 998 998 1081 998 998 1081 1010 1010 1094 1011 1011 1095 998 998 1081 1011 1011 1095 999 999 1082 999 999 1082 1011 1011 1095 1012 1012 1096 999 999 1082 1012 1012 1096 1000 1000 1083 1000 1000 1083 1012 1012 1096 1013 1013 1097 1000 1000 1083 1013 1013 1097 1001 1001 1084 1001 1001 1084 1013 1013 1097 1014 1014 1098 1001 1001 1084 1014 1014 1098 1002 1002 1085 1002 1002 1085 1014 1014 1098 1015 1015 1099 1002 1002 1085 1015 1015 1099 1003 1003 1086 1003 1003 1086 1015 1015 1099 1016 1016 1100 1003 1003 1086 1016 1016 1100 1004 1004 1087 1004 1004 1087 1016 1016 1100 1017 1017 1101 1004 1004 1087 1017 1017 1101 1005 1005 1088 1005 1005 1088 1017 1017 1101 1018 1018 1102 1005 1005 1088 1018 1018 1102 1006 1006 1089 1006 1006 1089 1018 1018 1102 1019 1019 1103 1006 1006 1089 1019 1019 1103 1007 1007 1090 1007 1007 1090 1019 1019 1103 1008 1008 1104 1007 1007 1090 1008 1008 1104 996 996 1091 1008 1008 1092 1020 1020 1105 1021 1021 1106 1008 1008 1092 1021 1021 1106 1009 1009 1093 1009 1009 1093 1021 1021 1106 1022 1022 1107 1009 1009 1093 1022 1022 1107 1010 1010 1094 1010 1010 1094 1022 1022 1107 1023 1023 1108 1010 1010 1094 1023 1023 1108 1011 1011 1095 1011 1011 1095 1023 1023 1108 1024 1024 1109 1011 1011 1095 1024 1024 1109 1012 1012 1096 1012 1012 1096 1024 1024 1109 1025 1025 1110 1012 1012 1096 1025 1025 1110 1013 1013 1097 1013 1013 1097 1025 1025 1110 1026 1026 1111 1013 1013 1097 1026 1026 1111 1014 1014 1098 1014 1014 1098 1026 1026 1111 1027 1027 1112 1014 1014 1098 1027 1027 1112 1015 1015 1099 1015 1015 1099 1027 1027 1112 1028 1028 1113 1015 1015 1099 1028 1028 1113 1016 1016 1100 1016 1016 1100 1028 1028 1113 1029 1029 1114 1016 1016 1100 1029 1029 1114 1017 1017 1101 1017 1017 1101 1029 1029 1114 1030 1030 1115 1017 1017 1101 1030 1030 1115 1018 1018 1102 1018 1018 1102 1030 1030 1115 1031 1031 1116 1018 1018 1102 1031 1031 1116 1019 1019 1103 1019 1019 1103 1031 1031 1116 1020 1020 1117 1019 1019 1103 1020 1020 1117 1008 1008 1104 1020 1020 1105 1032 1032 1118 1033 1033 1119 1020 1020 1105 1033 1033 1119 1021 1021 1106 1021 1021 1106 1033 1033 1119 1034 1034 1120 1021 1021 1106 1034 1034 1120 1022 1022 1107 1022 1022 1107 1034 1034 1120 1035 1035 1121 1022 1022 1107 1035 1035 1121 1023 1023 1108 1023 1023 1108 1035 1035 1121 1036 1036 1122 1023 1023 1108 1036 1036 1122 1024 1024 1109 1024 1024 1109 1036 1036 1122 1037 1037 1123 1024 1024 1109 1037 1037 1123 1025 1025 1110 1025 1025 1110 1037 1037 1123 1038 1038 1124 1025 1025 1110 1038 1038 1124 1026 1026 1111 1026 1026 1111 1038 1038 1124 1039 1039 1125 1026 1026 1111 1039 1039 1125 1027 1027 1112 1027 1027 1112 1039 1039 1125 1040 1040 1126 1027 1027 1112 1040 1040 1126 1028 1028 1113 1028 1028 1113 1040 1040 1126 1041 1041 1127 1028 1028 1113 1041 1041 1127 1029 1029 1114 1029 1029 1114 1041 1041 1127 1042 1042 1128 1029 1029 1114 1042 1042 1128 1030 1030 1115 1030 1030 1115 1042 1042 1128 1043 1043 1129 1030 1030 1115 1043 1043 1129 1031 1031 1116 1031 1031 1116 1043 1043 1129 1032 1032 1130 1031 1031 1116 1032 1032 1130 1020 1020 1117 1032 1032 1118 1044 1044 1131 1045 1045 1132 1032 1032 1118 1045 1045 1132 1033 1033 1119 1033 1033 1119 1045 1045 1132 1046 1046 1133 1033 1033 1119 1046 1046 1133 1034 1034 1120 1034 1034 1120 1046 1046 1133 1047 1047 1134 1034 1034 1120 1047 1047 1134 1035 1035 1121 1035 1035 1121 1047 1047 1134 1048 1048 1135 1035 1035 1121 1048 1048 1135 1036 1036 1122 1036 1036 1122 1048 1048 1135 1049 1049 1136 1036 1036 1122 1049 1049 1136 1037 1037 1123 1037 1037 1123 1049 1049 1136 1050 1050 1137 1037 1037 1123 1050 1050 1137 1038 1038 1124 1038 1038 1124 1050 1050 1137 1051 1051 1138 1038 1038 1124 1051 1051 1138 1039 1039 1125 1039 1039 1125 1051 1051 1138 1052 1052 1139 1039 1039 1125 1052 1052 1139 1040 1040 1126 1040 1040 1126 1052 1052 1139 1053 1053 1140 1040 1040 1126 1053 1053 1140 1041 1041 1127 1041 1041 1127 1053 1053 1140 1054 1054 1141 1041 1041 1127 1054 1054 1141 1042 1042 1128 1042 1042 1128 1054 1054 1141 1055 1055 1142 1042 1042 1128 1055 1055 1142 1043 1043 1129 1043 1043 1129 1055 1055 1142 1044 1044 1143 1043 1043 1129 1044 1044 1143 1032 1032 1130 1044 1044 1131 1056 1056 1144 1057 1057 1145 1044 1044 1131 1057 1057 1145 1045 1045 1132 1045 1045 1132 1057 1057 1145 1058 1058 1146 1045 1045 1132 1058 1058 1146 1046 1046 1133 1046 1046 1133 1058 1058 1146 1059 1059 1147 1046 1046 1133 1059 1059 1147 1047 1047 1134 1047 1047 1134 1059 1059 1147 1060 1060 1148 1047 1047 1134 1060 1060 1148 1048 1048 1135 1048 1048 1135 1060 1060 1148 1061 1061 1149 1048 1048 1135 1061 1061 1149 1049 1049 1136 1049 1049 1136 1061 1061 1149 1062 1062 1150 1049 1049 1136 1062 1062 1150 1050 1050 1137 1050 1050 1137 1062 1062 1150 1063 1063 1151 1050 1050 1137 1063 1063 1151 1051 1051 1138 1051 1051 1138 1063 1063 1151 1064 1064 1152 1051 1051 1138 1064 1064 1152 1052 1052 1139 1052 1052 1139 1064 1064 1152 1065 1065 1153 1052 1052 1139 1065 1065 1153 1053 1053 1140 1053 1053 1140 1065 1065 1153 1066 1066 1154 1053 1053 1140 1066 1066 1154 1054 1054 1141 1054 1054 1141 1066 1066 1154 1067 1067 1155 1054 1054 1141 1067 1067 1155 1055 1055 1142 1055 1055 1142 1067 1067 1155 1056 1056 1156 1055 1055 1142 1056 1056 1156 1044 1044 1143 1056 1056 1144 1068 1068 1157 1069 1069 1158 1056 1056 1144 1069 1069 1158 1057 1057 1145 1057 1057 1145 1069 1069 1158 1070 1070 1159 1057 1057 1145 1070 1070 1159 1058 1058 1146 1058 1058 1146 1070 1070 1159 1071 1071 1160 1058 1058 1146 1071 1071 1160 1059 1059 1147 1059 1059 1147 1071 1071 1160 1072 1072 1161 1059 1059 1147 1072 1072 1161 1060 1060 1148 1060 1060 1148 1072 1072 1161 1073 1073 1162 1060 1060 1148 1073 1073 1162 1061 1061 1149 1061 1061 1149 1073 1073 1162 1074 1074 1163 1061 1061 1149 1074 1074 1163 1062 1062 1150 1062 1062 1150 1074 1074 1163 1075 1075 1164 1062 1062 1150 1075 1075 1164 1063 1063 1151 1063 1063 1151 1075 1075 1164 1076 1076 1165 1063 1063 1151 1076 1076 1165 1064 1064 1152 1064 1064 1152 1076 1076 1165 1077 1077 1166 1064 1064 1152 1077 1077 1166 1065 1065 1153 1065 1065 1153 1077 1077 1166 1078 1078 1167 1065 1065 1153 1078 1078 1167 1066 1066 1154 1066 1066 1154 1078 1078 1167 1079 1079 1168 1066 1066 1154 1079 1079 1168 1067 1067 1155 1067 1067 1155 1079 1079 1168 1068 1068 1169 1067 1067 1155 1068 1068 1169 1056 1056 1156 1068 1068 1157 1080 1080 1170 1081 1081 1171 1068 1068 1157 1081 1081 1171 1069 1069 1158 1069 1069 1158 1081 1081 1171 1082 1082 1172 1069 1069 1158 1082 1082 1172 1070 1070 1159 1070 1070 1159 1082 1082 1172 1083 1083 1173 1070 1070 1159 1083 1083 1173 1071 1071 1160 1071 1071 1160 1083 1083 1173 1084 1084 1174 1071 1071 1160 1084 1084 1174 1072 1072 1161 1072 1072 1161 1084 1084 1174 1085 1085 1175 1072 1072 1161 1085 1085 1175 1073 1073 1162 1073 1073 1162 1085 1085 1175 1086 1086 1176 1073 1073 1162 1086 1086 1176 1074 1074 1163 1074 1074 1163 1086 1086 1176 1087 1087 1177 1074 1074 1163 1087 1087 1177 1075 1075 1164 1075 1075 1164 1087 1087 1177 1088 1088 1178 1075 1075 1164 1088 1088 1178 1076 1076 1165 1076 1076 1165 1088 1088 1178 1089 1089 1179 1076 1076 1165 1089 1089 1179 1077 1077 1166 1077 1077 1166 1089 1089 1179 1090 1090 1180 1077 1077 1166 1090 1090 1180 1078 1078 1167 1078 1078 1167 1090 1090 1180 1091 1091 1181 1078 1078 1167 1091 1091 1181 1079 1079 1168 1079 1079 1168 1091 1091 1181 1080 1080 1182 1079 1079 1168 1080 1080 1182 1068 1068 1169 1080 1080 1170 1092 1092 1183 1093 1093 1184 1080 1080 1170 1093 1093 1184 1081 1081 1171 1081 1081 1171 1093 1093 1184 1094 1094 1185 1081 1081 1171 1094 1094 1185 1082 1082 1172 1082 1082 1172 1094 1094 1185 1095 1095 1186 1082 1082 1172 1095 1095 1186 1083 1083 1173 1083 1083 1173 1095 1095 1186 1096 1096 1187 1083 1083 1173 1096 1096 1187 1084 1084 1174 1084 1084 1174 1096 1096 1187 1097 1097 1188 1084 1084 1174 1097 1097 1188 1085 1085 1175 1085 1085 1175 1097 1097 1188 1098 1098 1189 1085 1085 1175 1098 1098 1189 1086 1086 1176 1086 1086 1176 1098 1098 1189 1099 1099 1190 1086 1086 1176 1099 1099 1190 1087 1087 1177 1087 1087 1177 1099 1099 1190 1100 1100 1191 1087 1087 1177 1100 1100 1191 1088 1088 1178 1088 1088 1178 1100 1100 1191 1101 1101 1192 1088 1088 1178 1101 1101 1192 1089 1089 1179 1089 1089 1179 1101 1101 1192 1102 1102 1193 1089 1089 1179 1102 1102 1193 1090 1090 1180 1090 1090 1180 1102 1102 1193 1103 1103 1194 1090 1090 1180 1103 1103 1194 1091 1091 1181 1091 1091 1181 1103 1103 1194 1092 1092 1195 1091 1091 1181 1092 1092 1195 1080 1080 1182 1092 1092 1183 1104 1104 1196 1105 1105 1197 1092 1092 1183 1105 1105 1197 1093 1093 1184 1093 1093 1184 1105 1105 1197 1106 1106 1198 1093 1093 1184 1106 1106 1198 1094 1094 1185 1094 1094 1185 1106 1106 1198 1107 1107 1199 1094 1094 1185 1107 1107 1199 1095 1095 1186 1095 1095 1186 1107 1107 1199 1108 1108 1200 1095 1095 1186 1108 1108 1200 1096 1096 1187 1096 1096 1187 1108 1108 1200 1109 1109 1201 1096 1096 1187 1109 1109 1201 1097 1097 1188 1097 1097 1188 1109 1109 1201 1110 1110 1202 1097 1097 1188 1110 1110 1202 1098 1098 1189 1098 1098 1189 1110 1110 1202 1111 1111 1203 1098 1098 1189 1111 1111 1203 1099 1099 1190 1099 1099 1190 1111 1111 1203 1112 1112 1204 1099 1099 1190 1112 1112 1204 1100 1100 1191 1100 1100 1191 1112 1112 1204 1113 1113 1205 1100 1100 1191 1113 1113 1205 1101 1101 1192 1101 1101 1192 1113 1113 1205 1114 1114 1206 1101 1101 1192 1114 1114 1206 1102 1102 1193 1102 1102 1193 1114 1114 1206 1115 1115 1207 1102 1102 1193 1115 1115 1207 1103 1103 1194 1103 1103 1194 1115 1115 1207 1104 1104 1208 1103 1103 1194 1104 1104 1208 1092 1092 1195 1104 1104 1196 1116 1116 1209 1117 1117 1210 1104 1104 1196 1117 1117 1210 1105 1105 1197 1105 1105 1197 1117 1117 1210 1118 1118 1211 1105 1105 1197 1118 1118 1211 1106 1106 1198 1106 1106 1198 1118 1118 1211 1119 1119 1212 1106 1106 1198 1119 1119 1212 1107 1107 1199 1107 1107 1199 1119 1119 1212 1120 1120 1213 1107 1107 1199 1120 1120 1213 1108 1108 1200 1108 1108 1200 1120 1120 1213 1121 1121 1214 1108 1108 1200 1121 1121 1214 1109 1109 1201 1109 1109 1201 1121 1121 1214 1122 1122 1215 1109 1109 1201 1122 1122 1215 1110 1110 1202 1110 1110 1202 1122 1122 1215 1123 1123 1216 1110 1110 1202 1123 1123 1216 1111 1111 1203 1111 1111 1203 1123 1123 1216 1124 1124 1217 1111 1111 1203 1124 1124 1217 1112 1112 1204 1112 1112 1204 1124 1124 1217 1125 1125 1218 1112 1112 1204 1125 1125 1218 1113 1113 1205 1113 1113 1205 1125 1125 1218 1126 1126 1219 1113 1113 1205 1126 1126 1219 1114 1114 1206 1114 1114 1206 1126 1126 1219 1127 1127 1220 1114 1114 1206 1127 1127 1220 1115 1115 1207 1115 1115 1207 1127 1127 1220 1116 1116 1221 1115 1115 1207 1116 1116 1221 1104 1104 1208 1116 1116 1209 1128 1128 1222 1129 1129 1223 1116 1116 1209 1129 1129 1223 1117 1117 1210 1117 1117 1210 1129 1129 1223 1130 1130 1224 1117 1117 1210 1130 1130 1224 1118 1118 1211 1118 1118 1211 1130 1130 1224 1131 1131 1225 1118 1118 1211 1131 1131 1225 1119 1119 1212 1119 1119 1212 1131 1131 1225 1132 1132 1226 1119 1119 1212 1132 1132 1226 1120 1120 1213 1120 1120 1213 1132 1132 1226 1133 1133 1227 1120 1120 1213 1133 1133 1227 1121 1121 1214 1121 1121 1214 1133 1133 1227 1134 1134 1228 1121 1121 1214 1134 1134 1228 1122 1122 1215 1122 1122 1215 1134 1134 1228 1135 1135 1229 1122 1122 1215 1135 1135 1229 1123 1123 1216 1123 1123 1216 1135 1135 1229 1136 1136 1230 1123 1123 1216 1136 1136 1230 1124 1124 1217 1124 1124 1217 1136 1136 1230 1137 1137 1231 1124 1124 1217 1137 1137 1231 1125 1125 1218 1125 1125 1218 1137 1137 1231 1138 1138 1232 1125 1125 1218 1138 1138 1232 1126 1126 1219 1126 1126 1219 1138 1138 1232 1139 1139 1233 1126 1126 1219 1139 1139 1233 1127 1127 1220 1127 1127 1220 1139 1139 1233 1128 1128 1234 1127 1127 1220 1128 1128 1234 1116 1116 1221 1128 1128 1222 1140 1140 1235 1141 1141 1236 1128 1128 1222 1141 1141 1236 1129 1129 1223 1129 1129 1223 1141 1141 1236 1142 1142 1237 1129 1129 1223 1142 1142 1237 1130 1130 1224 1130 1130 1224 1142 1142 1237 1143 1143 1238 1130 1130 1224 1143 1143 1238 1131 1131 1225 1131 1131 1225 1143 1143 1238 1144 1144 1239 1131 1131 1225 1144 1144 1239 1132 1132 1226 1132 1132 1226 1144 1144 1239 1145 1145 1240 1132 1132 1226 1145 1145 1240 1133 1133 1227 1133 1133 1227 1145 1145 1240 1146 1146 1241 1133 1133 1227 1146 1146 1241 1134 1134 1228 1134 1134 1228 1146 1146 1241 1147 1147 1242 1134 1134 1228 1147 1147 1242 1135 1135 1229 1135 1135 1229 1147 1147 1242 1148 1148 1243 1135 1135 1229 1148 1148 1243 1136 1136 1230 1136 1136 1230 1148 1148 1243 1149 1149 1244 1136 1136 1230 1149 1149 1244 1137 1137 1231 1137 1137 1231 1149 1149 1244 1150 1150 1245 1137 1137 1231 1150 1150 1245 1138 1138 1232 1138 1138 1232 1150 1150 1245 1151 1151 1246 1138 1138 1232 1151 1151 1246 1139 1139 1233 1139 1139 1233 1151 1151 1246 1140 1140 1247 1139 1139 1233 1140 1140 1247 1128 1128 1234 1140 1140 1235 1152 1152 1248 1153 1153 1249 1140 1140 1235 1153 1153 1249 1141 1141 1236 1141 1141 1236 1153 1153 1249 1154 1154 1250 1141 1141 1236 1154 1154 1250 1142 1142 1237 1142 1142 1237 1154 1154 1250 1155 1155 1251 1142 1142 1237 1155 1155 1251 1143 1143 1238 1143 1143 1238 1155 1155 1251 1156 1156 1252 1143 1143 1238 1156 1156 1252 1144 1144 1239 1144 1144 1239 1156 1156 1252 1157 1157 1253 1144 1144 1239 1157 1157 1253 1145 1145 1240 1145 1145 1240 1157 1157 1253 1158 1158 1254 1145 1145 1240 1158 1158 1254 1146 1146 1241 1146 1146 1241 1158 1158 1254 1159 1159 1255 1146 1146 1241 1159 1159 1255 1147 1147 1242 1147 1147 1242 1159 1159 1255 1160 1160 1256 1147 1147 1242 1160 1160 1256 1148 1148 1243 1148 1148 1243 1160 1160 1256 1161 1161 1257 1148 1148 1243 1161 1161 1257 1149 1149 1244 1149 1149 1244 1161 1161 1257 1162 1162 1258 1149 1149 1244 1162 1162 1258 1150 1150 1245 1150 1150 1245 1162 1162 1258 1163 1163 1259 1150 1150 1245 1163 1163 1259 1151 1151 1246 1151 1151 1246 1163 1163 1259 1152 1152 1260 1151 1151 1246 1152 1152 1260 1140 1140 1247 1152 1152 1248 1164 1164 1261 1165 1165 1262 1152 1152 1248 1165 1165 1262 1153 1153 1249 1153 1153 1249 1165 1165 1262 1166 1166 1263 1153 1153 1249 1166 1166 1263 1154 1154 1250 1154 1154 1250 1166 1166 1263 1167 1167 1264 1154 1154 1250 1167 1167 1264 1155 1155 1251 1155 1155 1251 1167 1167 1264 1168 1168 1265 1155 1155 1251 1168 1168 1265 1156 1156 1252 1156 1156 1252 1168 1168 1265 1169 1169 1266 1156 1156 1252 1169 1169 1266 1157 1157 1253 1157 1157 1253 1169 1169 1266 1170 1170 1267 1157 1157 1253 1170 1170 1267 1158 1158 1254 1158 1158 1254 1170 1170 1267 1171 1171 1268 1158 1158 1254 1171 1171 1268 1159 1159 1255 1159 1159 1255 1171 1171 1268 1172 1172 1269 1159 1159 1255 1172 1172 1269 1160 1160 1256 1160 1160 1256 1172 1172 1269 1173 1173 1270 1160 1160 1256 1173 1173 1270 1161 1161 1257 1161 1161 1257 1173 1173 1270 1174 1174 1271 1161 1161 1257 1174 1174 1271 1162 1162 1258 1162 1162 1258 1174 1174 1271 1175 1175 1272 1162 1162 1258 1175 1175 1272 1163 1163 1259 1163 1163 1259 1175 1175 1272 1164 1164 1273 1163 1163 1259 1164 1164 1273 1152 1152 1260 1164 1164 1261 1176 1176 1274 1177 1177 1275 1164 1164 1261 1177 1177 1275 1165 1165 1262 1165 1165 1262 1177 1177 1275 1178 1178 1276 1165 1165 1262 1178 1178 1276 1166 1166 1263 1166 1166 1263 1178 1178 1276 1179 1179 1277 1166 1166 1263 1179 1179 1277 1167 1167 1264 1167 1167 1264 1179 1179 1277 1180 1180 1278 1167 1167 1264 1180 1180 1278 1168 1168 1265 1168 1168 1265 1180 1180 1278 1181 1181 1279 1168 1168 1265 1181 1181 1279 1169 1169 1266 1169 1169 1266 1181 1181 1279 1182 1182 1280 1169 1169 1266 1182 1182 1280 1170 1170 1267 1170 1170 1267 1182 1182 1280 1183 1183 1281 1170 1170 1267 1183 1183 1281 1171 1171 1268 1171 1171 1268 1183 1183 1281 1184 1184 1282 1171 1171 1268 1184 1184 1282 1172 1172 1269 1172 1172 1269 1184 1184 1282 1185 1185 1283 1172 1172 1269 1185 1185 1283 1173 1173 1270 1173 1173 1270 1185 1185 1283 1186 1186 1284 1173 1173 1270 1186 1186 1284 1174 1174 1271 1174 1174 1271 1186 1186 1284 1187 1187 1285 1174 1174 1271 1187 1187 1285 1175 1175 1272 1175 1175 1272 1187 1187 1285 1176 1176 1286 1175 1175 1272 1176 1176 1286 1164 1164 1273 1176 1176 1274 1188 1188 1287 1189 1189 1288 1176 1176 1274 1189 1189 1288 1177 1177 1275 1177 1177 1275 1189 1189 1288 1190 1190 1289 1177 1177 1275 1190 1190 1289 1178 1178 1276 1178 1178 1276 1190 1190 1289 1191 1191 1290 1178 1178 1276 1191 1191 1290 1179 1179 1277 1179 1179 1277 1191 1191 1290 1192 1192 1291 1179 1179 1277 1192 1192 1291 1180 1180 1278 1180 1180 1278 1192 1192 1291 1193 1193 1292 1180 1180 1278 1193 1193 1292 1181 1181 1279 1181 1181 1279 1193 1193 1292 1194 1194 1293 1181 1181 1279 1194 1194 1293 1182 1182 1280 1182 1182 1280 1194 1194 1293 1195 1195 1294 1182 1182 1280 1195 1195 1294 1183 1183 1281 1183 1183 1281 1195 1195 1294 1196 1196 1295 1183 1183 1281 1196 1196 1295 1184 1184 1282 1184 1184 1282 1196 1196 1295 1197 1197 1296 1184 1184 1282 1197 1197 1296 1185 1185 1283 1185 1185 1283 1197 1197 1296 1198 1198 1297 1185 1185 1283 1198 1198 1297 1186 1186 1284 1186 1186 1284 1198 1198 1297 1199 1199 1298 1186 1186 1284 1199 1199 1298 1187 1187 1285 1187 1187 1285 1199 1199 1298 1188 1188 1299 1187 1187 1285 1188 1188 1299 1176 1176 1286 1188 1188 1287 1200 1200 1300 1201 1201 1301 1188 1188 1287 1201 1201 1301 1189 1189 1288 1189 1189 1288 1201 1201 1301 1202 1202 1302 1189 1189 1288 1202 1202 1302 1190 1190 1289 1190 1190 1289 1202 1202 1302 1203 1203 1303 1190 1190 1289 1203 1203 1303 1191 1191 1290 1191 1191 1290 1203 1203 1303 1204 1204 1304 1191 1191 1290 1204 1204 1304 1192 1192 1291 1192 1192 1291 1204 1204 1304 1205 1205 1305 1192 1192 1291 1205 1205 1305 1193 1193 1292 1193 1193 1292 1205 1205 1305 1206 1206 1306 1193 1193 1292 1206 1206 1306 1194 1194 1293 1194 1194 1293 1206 1206 1306 1207 1207 1307 1194 1194 1293 1207 1207 1307 1195 1195 1294 1195 1195 1294 1207 1207 1307 1208 1208 1308 1195 1195 1294 1208 1208 1308 1196 1196 1295 1196 1196 1295 1208 1208 1308 1209 1209 1309 1196 1196 1295 1209 1209 1309 1197 1197 1296 1197 1197 1296 1209 1209 1309 1210 1210 1310 1197 1197 1296 1210 1210 1310 1198 1198 1297 1198 1198 1297 1210 1210 1310 1211 1211 1311 1198 1198 1297 1211 1211 1311 1199 1199 1298 1199 1199 1298 1211 1211 1311 1200 1200 1312 1199 1199 1298 1200 1200 1312 1188 1188 1299 1200 1200 1300 1212 1212 1313 1213 1213 1314 1200 1200 1300 1213 1213 1314 1201 1201 1301 1201 1201 1301 1213 1213 1314 1214 1214 1315 1201 1201 1301 1214 1214 1315 1202 1202 1302 1202 1202 1302 1214 1214 1315 1215 1215 1316 1202 1202 1302 1215 1215 1316 1203 1203 1303 1203 1203 1303 1215 1215 1316 1216 1216 1317 1203 1203 1303 1216 1216 1317 1204 1204 1304 1204 1204 1304 1216 1216 1317 1217 1217 1318 1204 1204 1304 1217 1217 1318 1205 1205 1305 1205 1205 1305 1217 1217 1318 1218 1218 1319 1205 1205 1305 1218 1218 1319 1206 1206 1306 1206 1206 1306 1218 1218 1319 1219 1219 1320 1206 1206 1306 1219 1219 1320 1207 1207 1307 1207 1207 1307 1219 1219 1320 1220 1220 1321 1207 1207 1307 1220 1220 1321 1208 1208 1308 1208 1208 1308 1220 1220 1321 1221 1221 1322 1208 1208 1308 1221 1221 1322 1209 1209 1309 1209 1209 1309 1221 1221 1322 1222 1222 1323 1209 1209 1309 1222 1222 1323 1210 1210 1310 1210 1210 1310 1222 1222 1323 1223 1223 1324 1210 1210 1310 1223 1223 1324 1211 1211 1311 1211 1211 1311 1223 1223 1324 1212 1212 1325 1211 1211 1311 1212 1212 1325 1200 1200 1312 1212 1212 1313 1224 1224 1326 1225 1225 1327 1212 1212 1313 1225 1225 1327 1213 1213 1314 1213 1213 1314 1225 1225 1327 1226 1226 1328 1213 1213 1314 1226 1226 1328 1214 1214 1315 1214 1214 1315 1226 1226 1328 1227 1227 1329 1214 1214 1315 1227 1227 1329 1215 1215 1316 1215 1215 1316 1227 1227 1329 1228 1228 1330 1215 1215 1316 1228 1228 1330 1216 1216 1317 1216 1216 1317 1228 1228 1330 1229 1229 1331 1216 1216 1317 1229 1229 1331 1217 1217 1318 1217 1217 1318 1229 1229 1331 1230 1230 1332 1217 1217 1318 1230 1230 1332 1218 1218 1319 1218 1218 1319 1230 1230 1332 1231 1231 1333 1218 1218 1319 1231 1231 1333 1219 1219 1320 1219 1219 1320 1231 1231 1333 1232 1232 1334 1219 1219 1320 1232 1232 1334 1220 1220 1321 1220 1220 1321 1232 1232 1334 1233 1233 1335 1220 1220 1321 1233 1233 1335 1221 1221 1322 1221 1221 1322 1233 1233 1335 1234 1234 1336 1221 1221 1322 1234 1234 1336 1222 1222 1323 1222 1222 1323 1234 1234 1336 1235 1235 1337 1222 1222 1323 1235 1235 1337 1223 1223 1324 1223 1223 1324 1235 1235 1337 1224 1224 1338 1223 1223 1324 1224 1224 1338 1212 1212 1325 1224 1224 1326 1236 1236 1339 1237 1237 1340 1224 1224 1326 1237 1237 1340 1225 1225 1327 1225 1225 1327 1237 1237 1340 1238 1238 1341 1225 1225 1327 1238 1238 1341 1226 1226 1328 1226 1226 1328 1238 1238 1341 1239 1239 1342 1226 1226 1328 1239 1239 1342 1227 1227 1329 1227 1227 1329 1239 1239 1342 1240 1240 1343 1227 1227 1329 1240 1240 1343 1228 1228 1330 1228 1228 1330 1240 1240 1343 1241 1241 1344 1228 1228 1330 1241 1241 1344 1229 1229 1331 1229 1229 1331 1241 1241 1344 1242 1242 1345 1229 1229 1331 1242 1242 1345 1230 1230 1332 1230 1230 1332 1242 1242 1345 1243 1243 1346 1230 1230 1332 1243 1243 1346 1231 1231 1333 1231 1231 1333 1243 1243 1346 1244 1244 1347 1231 1231 1333 1244 1244 1347 1232 1232 1334 1232 1232 1334 1244 1244 1347 1245 1245 1348 1232 1232 1334 1245 1245 1348 1233 1233 1335 1233 1233 1335 1245 1245 1348 1246 1246 1349 1233 1233 1335 1246 1246 1349 1234 1234 1336 1234 1234 1336 1246 1246 1349 1247 1247 1350 1234 1234 1336 1247 1247 1350 1235 1235 1337 1235 1235 1337 1247 1247 1350 1236 1236 1351 1235 1235 1337 1236 1236 1351 1224 1224 1338 1236 1236 1339 1248 1248 1352 1249 1249 1353 1236 1236 1339 1249 1249 1353 1237 1237 1340 1237 1237 1340 1249 1249 1353 1250 1250 1354 1237 1237 1340 1250 1250 1354 1238 1238 1341 1238 1238 1341 1250 1250 1354 1251 1251 1355 1238 1238 1341 1251 1251 1355 1239 1239 1342 1239 1239 1342 1251 1251 1355 1252 1252 1356 1239 1239 1342 1252 1252 1356 1240 1240 1343 1240 1240 1343 1252 1252 1356 1253 1253 1357 1240 1240 1343 1253 1253 1357 1241 1241 1344 1241 1241 1344 1253 1253 1357 1254 1254 1358 1241 1241 1344 1254 1254 1358 1242 1242 1345 1242 1242 1345 1254 1254 1358 1255 1255 1359 1242 1242 1345 1255 1255 1359 1243 1243 1346 1243 1243 1346 1255 1255 1359 1256 1256 1360 1243 1243 1346 1256 1256 1360 1244 1244 1347 1244 1244 1347 1256 1256 1360 1257 1257 1361 1244 1244 1347 1257 1257 1361 1245 1245 1348 1245 1245 1348 1257 1257 1361 1258 1258 1362 1245 1245 1348 1258 1258 1362 1246 1246 1349 1246 1246 1349 1258 1258 1362 1259 1259 1363 1246 1246 1349 1259 1259 1363 1247 1247 1350 1247 1247 1350 1259 1259 1363 1248 1248 1364 1247 1247 1350 1248 1248 1364 1236 1236 1351 1248 1248 1352 1260 1260 1365 1261 1261 1366 1248 1248 1352 1261 1261 1366 1249 1249 1353 1249 1249 1353 1261 1261 1366 1262 1262 1367 1249 1249 1353 1262 1262 1367 1250 1250 1354 1250 1250 1354 1262 1262 1367 1263 1263 1368 1250 1250 1354 1263 1263 1368 1251 1251 1355 1251 1251 1355 1263 1263 1368 1264 1264 1369 1251 1251 1355 1264 1264 1369 1252 1252 1356 1252 1252 1356 1264 1264 1369 1265 1265 1370 1252 1252 1356 1265 1265 1370 1253 1253 1357 1253 1253 1357 1265 1265 1370 1266 1266 1371 1253 1253 1357 1266 1266 1371 1254 1254 1358 1254 1254 1358 1266 1266 1371 1267 1267 1372 1254 1254 1358 1267 1267 1372 1255 1255 1359 1255 1255 1359 1267 1267 1372 1268 1268 1373 1255 1255 1359 1268 1268 1373 1256 1256 1360 1256 1256 1360 1268 1268 1373 1269 1269 1374 1256 1256 1360 1269 1269 1374 1257 1257 1361 1257 1257 1361 1269 1269 1374 1270 1270 1375 1257 1257 1361 1270 1270 1375 1258 1258 1362 1258 1258 1362 1270 1270 1375 1271 1271 1376 1258 1258 1362 1271 1271 1376 1259 1259 1363 1259 1259 1363 1271 1271 1376 1260 1260 1377 1259 1259 1363 1260 1260 1377 1248 1248 1364 1260 1260 1365 1272 1272 1378 1273 1273 1379 1260 1260 1365 1273 1273 1379 1261 1261 1366 1261 1261 1366 1273 1273 1379 1274 1274 1380 1261 1261 1366 1274 1274 1380 1262 1262 1367 1262 1262 1367 1274 1274 1380 1275 1275 1381 1262 1262 1367 1275 1275 1381 1263 1263 1368 1263 1263 1368 1275 1275 1381 1276 1276 1382 1263 1263 1368 1276 1276 1382 1264 1264 1369 1264 1264 1369 1276 1276 1382 1277 1277 1383 1264 1264 1369 1277 1277 1383 1265 1265 1370 1265 1265 1370 1277 1277 1383 1278 1278 1384 1265 1265 1370 1278 1278 1384 1266 1266 1371 1266 1266 1371 1278 1278 1384 1279 1279 1385 1266 1266 1371 1279 1279 1385 1267 1267 1372 1267 1267 1372 1279 1279 1385 1280 1280 1386 1267 1267 1372 1280 1280 1386 1268 1268 1373 1268 1268 1373 1280 1280 1386 1281 1281 1387 1268 1268 1373 1281 1281 1387 1269 1269 1374 1269 1269 1374 1281 1281 1387 1282 1282 1388 1269 1269 1374 1282 1282 1388 1270 1270 1375 1270 1270 1375 1282 1282 1388 1283 1283 1389 1270 1270 1375 1283 1283 1389 1271 1271 1376 1271 1271 1376 1283 1283 1389 1272 1272 1390 1271 1271 1376 1272 1272 1390 1260 1260 1377 1272 1272 1378 1284 1284 1391 1285 1285 1392 1272 1272 1378 1285 1285 1392 1273 1273 1379 1273 1273 1379 1285 1285 1392 1286 1286 1393 1273 1273 1379 1286 1286 1393 1274 1274 1380 1274 1274 1380 1286 1286 1393 1287 1287 1394 1274 1274 1380 1287 1287 1394 1275 1275 1381 1275 1275 1381 1287 1287 1394 1288 1288 1395 1275 1275 1381 1288 1288 1395 1276 1276 1382 1276 1276 1382 1288 1288 1395 1289 1289 1396 1276 1276 1382 1289 1289 1396 1277 1277 1383 1277 1277 1383 1289 1289 1396 1290 1290 1397 1277 1277 1383 1290 1290 1397 1278 1278 1384 1278 1278 1384 1290 1290 1397 1291 1291 1398 1278 1278 1384 1291 1291 1398 1279 1279 1385 1279 1279 1385 1291 1291 1398 1292 1292 1399 1279 1279 1385 1292 1292 1399 1280 1280 1386 1280 1280 1386 1292 1292 1399 1293 1293 1400 1280 1280 1386 1293 1293 1400 1281 1281 1387 1281 1281 1387 1293 1293 1400 1294 1294 1401 1281 1281 1387 1294 1294 1401 1282 1282 1388 1282 1282 1388 1294 1294 1401 1295 1295 1402 1282 1282 1388 1295 1295 1402 1283 1283 1389 1283 1283 1389 1295 1295 1402 1284 1284 1403 1283 1283 1389 1284 1284 1403 1272 1272 1390 1284 1284 1391 1296 1296 1404 1297 1297 1405 1284 1284 1391 1297 1297 1405 1285 1285 1392 1285 1285 1392 1297 1297 1405 1298 1298 1406 1285 1285 1392 1298 1298 1406 1286 1286 1393 1286 1286 1393 1298 1298 1406 1299 1299 1407 1286 1286 1393 1299 1299 1407 1287 1287 1394 1287 1287 1394 1299 1299 1407 1300 1300 1408 1287 1287 1394 1300 1300 1408 1288 1288 1395 1288 1288 1395 1300 1300 1408 1301 1301 1409 1288 1288 1395 1301 1301 1409 1289 1289 1396 1289 1289 1396 1301 1301 1409 1302 1302 1410 1289 1289 1396 1302 1302 1410 1290 1290 1397 1290 1290 1397 1302 1302 1410 1303 1303 1411 1290 1290 1397 1303 1303 1411 1291 1291 1398 1291 1291 1398 1303 1303 1411 1304 1304 1412 1291 1291 1398 1304 1304 1412 1292 1292 1399 1292 1292 1399 1304 1304 1412 1305 1305 1413 1292 1292 1399 1305 1305 1413 1293 1293 1400 1293 1293 1400 1305 1305 1413 1306 1306 1414 1293 1293 1400 1306 1306 1414 1294 1294 1401 1294 1294 1401 1306 1306 1414 1307 1307 1415 1294 1294 1401 1307 1307 1415 1295 1295 1402 1295 1295 1402 1307 1307 1415 1296 1296 1416 1295 1295 1402 1296 1296 1416 1284 1284 1403 1296 1296 1404 1308 1308 1417 1309 1309 1418 1296 1296 1404 1309 1309 1418 1297 1297 1405 1297 1297 1405 1309 1309 1418 1310 1310 1419 1297 1297 1405 1310 1310 1419 1298 1298 1406 1298 1298 1406 1310 1310 1419 1311 1311 1420 1298 1298 1406 1311 1311 1420 1299 1299 1407 1299 1299 1407 1311 1311 1420 1312 1312 1421 1299 1299 1407 1312 1312 1421 1300 1300 1408 1300 1300 1408 1312 1312 1421 1313 1313 1422 1300 1300 1408 1313 1313 1422 1301 1301 1409 1301 1301 1409 1313 1313 1422 1314 1314 1423 1301 1301 1409 1314 1314 1423 1302 1302 1410 1302 1302 1410 1314 1314 1423 1315 1315 1424 1302 1302 1410 1315 1315 1424 1303 1303 1411 1303 1303 1411 1315 1315 1424 1316 1316 1425 1303 1303 1411 1316 1316 1425 1304 1304 1412 1304 1304 1412 1316 1316 1425 1317 1317 1426 1304 1304 1412 1317 1317 1426 1305 1305 1413 1305 1305 1413 1317 1317 1426 1318 1318 1427 1305 1305 1413 1318 1318 1427 1306 1306 1414 1306 1306 1414 1318 1318 1427 1319 1319 1428 1306 1306 1414 1319 1319 1428 1307 1307 1415 1307 1307 1415 1319 1319 1428 1308 1308 1429 1307 1307 1415 1308 1308 1429 1296 1296 1416 1308 1308 1417 1320 1320 1430 1321 1321 1431 1308 1308 1417 1321 1321 1431 1309 1309 1418 1309 1309 1418 1321 1321 1431 1322 1322 1432 1309 1309 1418 1322 1322 1432 1310 1310 1419 1310 1310 1419 1322 1322 1432 1323 1323 1433 1310 1310 1419 1323 1323 1433 1311 1311 1420 1311 1311 1420 1323 1323 1433 1324 1324 1434 1311 1311 1420 1324 1324 1434 1312 1312 1421 1312 1312 1421 1324 1324 1434 1325 1325 1435 1312 1312 1421 1325 1325 1435 1313 1313 1422 1313 1313 1422 1325 1325 1435 1326 1326 1436 1313 1313 1422 1326 1326 1436 1314 1314 1423 1314 1314 1423 1326 1326 1436 1327 1327 1437 1314 1314 1423 1327 1327 1437 1315 1315 1424 1315 1315 1424 1327 1327 1437 1328 1328 1438 1315 1315 1424 1328 1328 1438 1316 1316 1425 1316 1316 1425 1328 1328 1438 1329 1329 1439 1316 1316 1425 1329 1329 1439 1317 1317 1426 1317 1317 1426 1329 1329 1439 1330 1330 1440 1317 1317 1426 1330 1330 1440 1318 1318 1427 1318 1318 1427 1330 1330 1440 1331 1331 1441 1318 1318 1427 1331 1331 1441 1319 1319 1428 1319 1319 1428 1331 1331 1441 1320 1320 1442 1319 1319 1428 1320 1320 1442 1308 1308 1429 1320 1320 1430 1332 1332 1443 1333 1333 1444 1320 1320 1430 1333 1333 1444 1321 1321 1431 1321 1321 1431 1333 1333 1444 1334 1334 1445 1321 1321 1431 1334 1334 1445 1322 1322 1432 1322 1322 1432 1334 1334 1445 1335 1335 1446 1322 1322 1432 1335 1335 1446 1323 1323 1433 1323 1323 1433 1335 1335 1446 1336 1336 1447 1323 1323 1433 1336 1336 1447 1324 1324 1434 1324 1324 1434 1336 1336 1447 1337 1337 1448 1324 1324 1434 1337 1337 1448 1325 1325 1435 1325 1325 1435 1337 1337 1448 1338 1338 1449 1325 1325 1435 1338 1338 1449 1326 1326 1436 1326 1326 1436 1338 1338 1449 1339 1339 1450 1326 1326 1436 1339 1339 1450 1327 1327 1437 1327 1327 1437 1339 1339 1450 1340 1340 1451 1327 1327 1437 1340 1340 1451 1328 1328 1438 1328 1328 1438 1340 1340 1451 1341 1341 1452 1328 1328 1438 1341 1341 1452 1329 1329 1439 1329 1329 1439 1341 1341 1452 1342 1342 1453 1329 1329 1439 1342 1342 1453 1330 1330 1440 1330 1330 1440 1342 1342 1453 1343 1343 1454 1330 1330 1440 1343 1343 1454 1331 1331 1441 1331 1331 1441 1343 1343 1454 1332 1332 1455 1331 1331 1441 1332 1332 1455 1320 1320 1442 1332 1332 1443 1344 1344 1456 1345 1345 1457 1332 1332 1443 1345 1345 1457 1333 1333 1444 1333 1333 1444 1345 1345 1457 1346 1346 1458 1333 1333 1444 1346 1346 1458 1334 1334 1445 1334 1334 1445 1346 1346 1458 1347 1347 1459 1334 1334 1445 1347 1347 1459 1335 1335 1446 1335 1335 1446 1347 1347 1459 1348 1348 1460 1335 1335 1446 1348 1348 1460 1336 1336 1447 1336 1336 1447 1348 1348 1460 1349 1349 1461 1336 1336 1447 1349 1349 1461 1337 1337 1448 1337 1337 1448 1349 1349 1461 1350 1350 1462 1337 1337 1448 1350 1350 1462 1338 1338 1449 1338 1338 1449 1350 1350 1462 1351 1351 1463 1338 1338 1449 1351 1351 1463 1339 1339 1450 1339 1339 1450 1351 1351 1463 1352 1352 1464 1339 1339 1450 1352 1352 1464 1340 1340 1451 1340 1340 1451 1352 1352 1464 1353 1353 1465 1340 1340 1451 1353 1353 1465 1341 1341 1452 1341 1341 1452 1353 1353 1465 1354 1354 1466 1341 1341 1452 1354 1354 1466 1342 1342 1453 1342 1342 1453 1354 1354 1466 1355 1355 1467 1342 1342 1453 1355 1355 1467 1343 1343 1454 1343 1343 1454 1355 1355 1467 1344 1344 1468 1343 1343 1454 1344 1344 1468 1332 1332 1455 1344 1344 1456 1356 1356 1469 1357 1357 1470 1344 1344 1456 1357 1357 1470 1345 1345 1457 1345 1345 1457 1357 1357 1470 1358 1358 1471 1345 1345 1457 1358 1358 1471 1346 1346 1458 1346 1346 1458 1358 1358 1471 1359 1359 1472 1346 1346 1458 1359 1359 1472 1347 1347 1459 1347 1347 1459 1359 1359 1472 1360 1360 1473 1347 1347 1459 1360 1360 1473 1348 1348 1460 1348 1348 1460 1360 1360 1473 1361 1361 1474 1348 1348 1460 1361 1361 1474 1349 1349 1461 1349 1349 1461 1361 1361 1474 1362 1362 1475 1349 1349 1461 1362 1362 1475 1350 1350 1462 1350 1350 1462 1362 1362 1475 1363 1363 1476 1350 1350 1462 1363 1363 1476 1351 1351 1463 1351 1351 1463 1363 1363 1476 1364 1364 1477 1351 1351 1463 1364 1364 1477 1352 1352 1464 1352 1352 1464 1364 1364 1477 1365 1365 1478 1352 1352 1464 1365 1365 1478 1353 1353 1465 1353 1353 1465 1365 1365 1478 1366 1366 1479 1353 1353 1465 1366 1366 1479 1354 1354 1466 1354 1354 1466 1366 1366 1479 1367 1367 1480 1354 1354 1466 1367 1367 1480 1355 1355 1467 1355 1355 1467 1367 1367 1480 1356 1356 1481 1355 1355 1467 1356 1356 1481 1344 1344 1468 1356 1356 1469 1368 1368 1482 1369 1369 1483 1356 1356 1469 1369 1369 1483 1357 1357 1470 1357 1357 1470 1369 1369 1483 1370 1370 1484 1357 1357 1470 1370 1370 1484 1358 1358 1471 1358 1358 1471 1370 1370 1484 1371 1371 1485 1358 1358 1471 1371 1371 1485 1359 1359 1472 1359 1359 1472 1371 1371 1485 1372 1372 1486 1359 1359 1472 1372 1372 1486 1360 1360 1473 1360 1360 1473 1372 1372 1486 1373 1373 1487 1360 1360 1473 1373 1373 1487 1361 1361 1474 1361 1361 1474 1373 1373 1487 1374 1374 1488 1361 1361 1474 1374 1374 1488 1362 1362 1475 1362 1362 1475 1374 1374 1488 1375 1375 1489 1362 1362 1475 1375 1375 1489 1363 1363 1476 1363 1363 1476 1375 1375 1489 1376 1376 1490 1363 1363 1476 1376 1376 1490 1364 1364 1477 1364 1364 1477 1376 1376 1490 1377 1377 1491 1364 1364 1477 1377 1377 1491 1365 1365 1478 1365 1365 1478 1377 1377 1491 1378 1378 1492 1365 1365 1478 1378 1378 1492 1366 1366 1479 1366 1366 1479 1378 1378 1492 1379 1379 1493 1366 1366 1479 1379 1379 1493 1367 1367 1480 1367 1367 1480 1379 1379 1493 1368 1368 1494 1367 1367 1480 1368 1368 1494 1356 1356 1481 1368 1368 1482 1380 1380 1495 1381 1381 1496 1368 1368 1482 1381 1381 1496 1369 1369 1483 1369 1369 1483 1381 1381 1496 1382 1382 1497 1369 1369 1483 1382 1382 1497 1370 1370 1484 1370 1370 1484 1382 1382 1497 1383 1383 1498 1370 1370 1484 1383 1383 1498 1371 1371 1485 1371 1371 1485 1383 1383 1498 1384 1384 1499 1371 1371 1485 1384 1384 1499 1372 1372 1486 1372 1372 1486 1384 1384 1499 1385 1385 1500 1372 1372 1486 1385 1385 1500 1373 1373 1487 1373 1373 1487 1385 1385 1500 1386 1386 1501 1373 1373 1487 1386 1386 1501 1374 1374 1488 1374 1374 1488 1386 1386 1501 1387 1387 1502 1374 1374 1488 1387 1387 1502 1375 1375 1489 1375 1375 1489 1387 1387 1502 1388 1388 1503 1375 1375 1489 1388 1388 1503 1376 1376 1490 1376 1376 1490 1388 1388 1503 1389 1389 1504 1376 1376 1490 1389 1389 1504 1377 1377 1491 1377 1377 1491 1389 1389 1504 1390 1390 1505 1377 1377 1491 1390 1390 1505 1378 1378 1492 1378 1378 1492 1390 1390 1505 1391 1391 1506 1378 1378 1492 1391 1391 1506 1379 1379 1493 1379 1379 1493 1391 1391 1506 1380 1380 1507 1379 1379 1493 1380 1380 1507 1368 1368 1494 1380 1380 1495 1392 1392 1508 1393 1393 1509 1380 1380 1495 1393 1393 1509 1381 1381 1496 1381 1381 1496 1393 1393 1509 1394 1394 1510 1381 1381 1496 1394 1394 1510 1382 1382 1497 1382 1382 1497 1394 1394 1510 1395 1395 1511 1382 1382 1497 1395 1395 1511 1383 1383 1498 1383 1383 1498 1395 1395 1511 1396 1396 1512 1383 1383 1498 1396 1396 1512 1384 1384 1499 1384 1384 1499 1396 1396 1512 1397 1397 1513 1384 1384 1499 1397 1397 1513 1385 1385 1500 1385 1385 1500 1397 1397 1513 1398 1398 1514 1385 1385 1500 1398 1398 1514 1386 1386 1501 1386 1386 1501 1398 1398 1514 1399 1399 1515 1386 1386 1501 1399 1399 1515 1387 1387 1502 1387 1387 1502 1399 1399 1515 1400 1400 1516 1387 1387 1502 1400 1400 1516 1388 1388 1503 1388 1388 1503 1400 1400 1516 1401 1401 1517 1388 1388 1503 1401 1401 1517 1389 1389 1504 1389 1389 1504 1401 1401 1517 1402 1402 1518 1389 1389 1504 1402 1402 1518 1390 1390 1505 1390 1390 1505 1402 1402 1518 1403 1403 1519 1390 1390 1505 1403 1403 1519 1391 1391 1506 1391 1391 1506 1403 1403 1519 1392 1392 1520 1391 1391 1506 1392 1392 1520 1380 1380 1507 1392 1392 1508 1404 1404 1521 1405 1405 1522 1392 1392 1508 1405 1405 1522 1393 1393 1509 1393 1393 1509 1405 1405 1522 1406 1406 1523 1393 1393 1509 1406 1406 1523 1394 1394 1510 1394 1394 1510 1406 1406 1523 1407 1407 1524 1394 1394 1510 1407 1407 1524 1395 1395 1511 1395 1395 1511 1407 1407 1524 1408 1408 1525 1395 1395 1511 1408 1408 1525 1396 1396 1512 1396 1396 1512 1408 1408 1525 1409 1409 1526 1396 1396 1512 1409 1409 1526 1397 1397 1513 1397 1397 1513 1409 1409 1526 1410 1410 1527 1397 1397 1513 1410 1410 1527 1398 1398 1514 1398 1398 1514 1410 1410 1527 1411 1411 1528 1398 1398 1514 1411 1411 1528 1399 1399 1515 1399 1399 1515 1411 1411 1528 1412 1412 1529 1399 1399 1515 1412 1412 1529 1400 1400 1516 1400 1400 1516 1412 1412 1529 1413 1413 1530 1400 1400 1516 1413 1413 1530 1401 1401 1517 1401 1401 1517 1413 1413 1530 1414 1414 1531 1401 1401 1517 1414 1414 1531 1402 1402 1518 1402 1402 1518 1414 1414 1531 1415 1415 1532 1402 1402 1518 1415 1415 1532 1403 1403 1519 1403 1403 1519 1415 1415 1532 1404 1404 1533 1403 1403 1519 1404 1404 1533 1392 1392 1520 1404 1404 1521 1416 1416 1534 1417 1417 1535 1404 1404 1521 1417 1417 1535 1405 1405 1522 1405 1405 1522 1417 1417 1535 1418 1418 1536 1405 1405 1522 1418 1418 1536 1406 1406 1523 1406 1406 1523 1418 1418 1536 1419 1419 1537 1406 1406 1523 1419 1419 1537 1407 1407 1524 1407 1407 1524 1419 1419 1537 1420 1420 1538 1407 1407 1524 1420 1420 1538 1408 1408 1525 1408 1408 1525 1420 1420 1538 1421 1421 1539 1408 1408 1525 1421 1421 1539 1409 1409 1526 1409 1409 1526 1421 1421 1539 1422 1422 1540 1409 1409 1526 1422 1422 1540 1410 1410 1527 1410 1410 1527 1422 1422 1540 1423 1423 1541 1410 1410 1527 1423 1423 1541 1411 1411 1528 1411 1411 1528 1423 1423 1541 1424 1424 1542 1411 1411 1528 1424 1424 1542 1412 1412 1529 1412 1412 1529 1424 1424 1542 1425 1425 1543 1412 1412 1529 1425 1425 1543 1413 1413 1530 1413 1413 1530 1425 1425 1543 1426 1426 1544 1413 1413 1530 1426 1426 1544 1414 1414 1531 1414 1414 1531 1426 1426 1544 1427 1427 1545 1414 1414 1531 1427 1427 1545 1415 1415 1532 1415 1415 1532 1427 1427 1545 1416 1416 1546 1415 1415 1532 1416 1416 1546 1404 1404 1533 1416 1416 1534 1428 1428 1547 1429 1429 1548 1416 1416 1534 1429 1429 1548 1417 1417 1535 1417 1417 1535 1429 1429 1548 1430 1430 1549 1417 1417 1535 1430 1430 1549 1418 1418 1536 1418 1418 1536 1430 1430 1549 1431 1431 1550 1418 1418 1536 1431 1431 1550 1419 1419 1537 1419 1419 1537 1431 1431 1550 1432 1432 1551 1419 1419 1537 1432 1432 1551 1420 1420 1538 1420 1420 1538 1432 1432 1551 1433 1433 1552 1420 1420 1538 1433 1433 1552 1421 1421 1539 1421 1421 1539 1433 1433 1552 1434 1434 1553 1421 1421 1539 1434 1434 1553 1422 1422 1540 1422 1422 1540 1434 1434 1553 1435 1435 1554 1422 1422 1540 1435 1435 1554 1423 1423 1541 1423 1423 1541 1435 1435 1554 1436 1436 1555 1423 1423 1541 1436 1436 1555 1424 1424 1542 1424 1424 1542 1436 1436 1555 1437 1437 1556 1424 1424 1542 1437 1437 1556 1425 1425 1543 1425 1425 1543 1437 1437 1556 1438 1438 1557 1425 1425 1543 1438 1438 1557 1426 1426 1544 1426 1426 1544 1438 1438 1557 1439 1439 1558 1426 1426 1544 1439 1439 1558 1427 1427 1545 1427 1427 1545 1439 1439 1558 1428 1428 1559 1427 1427 1545 1428 1428 1559 1416 1416 1546 1428 1428 1547 1440 1440 1560 1441 1441 1561 1428 1428 1547 1441 1441 1561 1429 1429 1548 1429 1429 1548 1441 1441 1561 1442 1442 1562 1429 1429 1548 1442 1442 1562 1430 1430 1549 1430 1430 1549 1442 1442 1562 1443 1443 1563 1430 1430 1549 1443 1443 1563 1431 1431 1550 1431 1431 1550 1443 1443 1563 1444 1444 1564 1431 1431 1550 1444 1444 1564 1432 1432 1551 1432 1432 1551 1444 1444 1564 1445 1445 1565 1432 1432 1551 1445 1445 1565 1433 1433 1552 1433 1433 1552 1445 1445 1565 1446 1446 1566 1433 1433 1552 1446 1446 1566 1434 1434 1553 1434 1434 1553 1446 1446 1566 1447 1447 1567 1434 1434 1553 1447 1447 1567 1435 1435 1554 1435 1435 1554 1447 1447 1567 1448 1448 1568 1435 1435 1554 1448 1448 1568 1436 1436 1555 1436 1436 1555 1448 1448 1568 1449 1449 1569 1436 1436 1555 1449 1449 1569 1437 1437 1556 1437 1437 1556 1449 1449 1569 1450 1450 1570 1437 1437 1556 1450 1450 1570 1438 1438 1557 1438 1438 1557 1450 1450 1570 1451 1451 1571 1438 1438 1557 1451 1451 1571 1439 1439 1558 1439 1439 1558 1451 1451 1571 1440 1440 1572 1439 1439 1558 1440 1440 1572 1428 1428 1559 1440 1440 1560 1452 1452 1573 1453 1453 1574 1440 1440 1560 1453 1453 1574 1441 1441 1561 1441 1441 1561 1453 1453 1574 1454 1454 1575 1441 1441 1561 1454 1454 1575 1442 1442 1562 1442 1442 1562 1454 1454 1575 1455 1455 1576 1442 1442 1562 1455 1455 1576 1443 1443 1563 1443 1443 1563 1455 1455 1576 1456 1456 1577 1443 1443 1563 1456 1456 1577 1444 1444 1564 1444 1444 1564 1456 1456 1577 1457 1457 1578 1444 1444 1564 1457 1457 1578 1445 1445 1565 1445 1445 1565 1457 1457 1578 1458 1458 1579 1445 1445 1565 1458 1458 1579 1446 1446 1566 1446 1446 1566 1458 1458 1579 1459 1459 1580 1446 1446 1566 1459 1459 1580 1447 1447 1567 1447 1447 1567 1459 1459 1580 1460 1460 1581 1447 1447 1567 1460 1460 1581 1448 1448 1568 1448 1448 1568 1460 1460 1581 1461 1461 1582 1448 1448 1568 1461 1461 1582 1449 1449 1569 1449 1449 1569 1461 1461 1582 1462 1462 1583 1449 1449 1569 1462 1462 1583 1450 1450 1570 1450 1450 1570 1462 1462 1583 1463 1463 1584 1450 1450 1570 1463 1463 1584 1451 1451 1571 1451 1451 1571 1463 1463 1584 1452 1452 1585 1451 1451 1571 1452 1452 1585 1440 1440 1572 1452 1452 1573 1464 1464 1586 1465 1465 1587 1452 1452 1573 1465 1465 1587 1453 1453 1574 1453 1453 1574 1465 1465 1587 1466 1466 1588 1453 1453 1574 1466 1466 1588 1454 1454 1575 1454 1454 1575 1466 1466 1588 1467 1467 1589 1454 1454 1575 1467 1467 1589 1455 1455 1576 1455 1455 1576 1467 1467 1589 1468 1468 1590 1455 1455 1576 1468 1468 1590 1456 1456 1577 1456 1456 1577 1468 1468 1590 1469 1469 1591 1456 1456 1577 1469 1469 1591 1457 1457 1578 1457 1457 1578 1469 1469 1591 1470 1470 1592 1457 1457 1578 1470 1470 1592 1458 1458 1579 1458 1458 1579 1470 1470 1592 1471 1471 1593 1458 1458 1579 1471 1471 1593 1459 1459 1580 1459 1459 1580 1471 1471 1593 1472 1472 1594 1459 1459 1580 1472 1472 1594 1460 1460 1581 1460 1460 1581 1472 1472 1594 1473 1473 1595 1460 1460 1581 1473 1473 1595 1461 1461 1582 1461 1461 1582 1473 1473 1595 1474 1474 1596 1461 1461 1582 1474 1474 1596 1462 1462 1583 1462 1462 1583 1474 1474 1596 1475 1475 1597 1462 1462 1583 1475 1475 1597 1463 1463 1584 1463 1463 1584 1475 1475 1597 1464 1464 1598 1463 1463 1584 1464 1464 1598 1452 1452 1585 1464 1464 1586 1476 1476 1599 1477 1477 1600 1464 1464 1586 1477 1477 1600 1465 1465 1587 1465 1465 1587 1477 1477 1600 1478 1478 1601 1465 1465 1587 1478 1478 1601 1466 1466 1588 1466 1466 1588 1478 1478 1601 1479 1479 1602 1466 1466 1588 1479 1479 1602 1467 1467 1589 1467 1467 1589 1479 1479 1602 1480 1480 1603 1467 1467 1589 1480 1480 1603 1468 1468 1590 1468 1468 1590 1480 1480 1603 1481 1481 1604 1468 1468 1590 1481 1481 1604 1469 1469 1591 1469 1469 1591 1481 1481 1604 1482 1482 1605 1469 1469 1591 1482 1482 1605 1470 1470 1592 1470 1470 1592 1482 1482 1605 1483 1483 1606 1470 1470 1592 1483 1483 1606 1471 1471 1593 1471 1471 1593 1483 1483 1606 1484 1484 1607 1471 1471 1593 1484 1484 1607 1472 1472 1594 1472 1472 1594 1484 1484 1607 1485 1485 1608 1472 1472 1594 1485 1485 1608 1473 1473 1595 1473 1473 1595 1485 1485 1608 1486 1486 1609 1473 1473 1595 1486 1486 1609 1474 1474 1596 1474 1474 1596 1486 1486 1609 1487 1487 1610 1474 1474 1596 1487 1487 1610 1475 1475 1597 1475 1475 1597 1487 1487 1610 1476 1476 1611 1475 1475 1597 1476 1476 1611 1464 1464 1598 1476 1476 1599 1488 1488 1612 1489 1489 1613 1476 1476 1599 1489 1489 1613 1477 1477 1600 1477 1477 1600 1489 1489 1613 1490 1490 1614 1477 1477 1600 1490 1490 1614 1478 1478 1601 1478 1478 1601 1490 1490 1614 1491 1491 1615 1478 1478 1601 1491 1491 1615 1479 1479 1602 1479 1479 1602 1491 1491 1615 1492 1492 1616 1479 1479 1602 1492 1492 1616 1480 1480 1603 1480 1480 1603 1492 1492 1616 1493 1493 1617 1480 1480 1603 1493 1493 1617 1481 1481 1604 1481 1481 1604 1493 1493 1617 1494 1494 1618 1481 1481 1604 1494 1494 1618 1482 1482 1605 1482 1482 1605 1494 1494 1618 1495 1495 1619 1482 1482 1605 1495 1495 1619 1483 1483 1606 1483 1483 1606 1495 1495 1619 1496 1496 1620 1483 1483 1606 1496 1496 1620 1484 1484 1607 1484 1484 1607 1496 1496 1620 1497 1497 1621 1484 1484 1607 1497 1497 1621 1485 1485 1608 1485 1485 1608 1497 1497 1621 1498 1498 1622 1485 1485 1608 1498 1498 1622 1486 1486 1609 1486 1486 1609 1498 1498 1622 1499 1499 1623 1486 1486 1609 1499 1499 1623 1487 1487 1610 1487 1487 1610 1499 1499 1623 1488 1488 1624 1487 1487 1610 1488 1488 1624 1476 1476 1611 1488 1488 1612 1500 1500 1625 1501 1501 1626 1488 1488 1612 1501 1501 1626 1489 1489 1613 1489 1489 1613 1501 1501 1626 1502 1502 1627 1489 1489 1613 1502 1502 1627 1490 1490 1614 1490 1490 1614 1502 1502 1627 1503 1503 1628 1490 1490 1614 1503 1503 1628 1491 1491 1615 1491 1491 1615 1503 1503 1628 1504 1504 1629 1491 1491 1615 1504 1504 1629 1492 1492 1616 1492 1492 1616 1504 1504 1629 1505 1505 1630 1492 1492 1616 1505 1505 1630 1493 1493 1617 1493 1493 1617 1505 1505 1630 1506 1506 1631 1493 1493 1617 1506 1506 1631 1494 1494 1618 1494 1494 1618 1506 1506 1631 1507 1507 1632 1494 1494 1618 1507 1507 1632 1495 1495 1619 1495 1495 1619 1507 1507 1632 1508 1508 1633 1495 1495 1619 1508 1508 1633 1496 1496 1620 1496 1496 1620 1508 1508 1633 1509 1509 1634 1496 1496 1620 1509 1509 1634 1497 1497 1621 1497 1497 1621 1509 1509 1634 1510 1510 1635 1497 1497 1621 1510 1510 1635 1498 1498 1622 1498 1498 1622 1510 1510 1635 1511 1511 1636 1498 1498 1622 1511 1511 1636 1499 1499 1623 1499 1499 1623 1511 1511 1636 1500 1500 1637 1499 1499 1623 1500 1500 1637 1488 1488 1624 1500 1500 1625 1512 1512 1638 1513 1513 1639 1500 1500 1625 1513 1513 1639 1501 1501 1626 1501 1501 1626 1513 1513 1639 1514 1514 1640 1501 1501 1626 1514 1514 1640 1502 1502 1627 1502 1502 1627 1514 1514 1640 1515 1515 1641 1502 1502 1627 1515 1515 1641 1503 1503 1628 1503 1503 1628 1515 1515 1641 1516 1516 1642 1503 1503 1628 1516 1516 1642 1504 1504 1629 1504 1504 1629 1516 1516 1642 1517 1517 1643 1504 1504 1629 1517 1517 1643 1505 1505 1630 1505 1505 1630 1517 1517 1643 1518 1518 1644 1505 1505 1630 1518 1518 1644 1506 1506 1631 1506 1506 1631 1518 1518 1644 1519 1519 1645 1506 1506 1631 1519 1519 1645 1507 1507 1632 1507 1507 1632 1519 1519 1645 1520 1520 1646 1507 1507 1632 1520 1520 1646 1508 1508 1633 1508 1508 1633 1520 1520 1646 1521 1521 1647 1508 1508 1633 1521 1521 1647 1509 1509 1634 1509 1509 1634 1521 1521 1647 1522 1522 1648 1509 1509 1634 1522 1522 1648 1510 1510 1635 1510 1510 1635 1522 1522 1648 1523 1523 1649 1510 1510 1635 1523 1523 1649 1511 1511 1636 1511 1511 1636 1523 1523 1649 1512 1512 1650 1511 1511 1636 1512 1512 1650 1500 1500 1637 1512 1512 1638 1524 1524 1651 1525 1525 1652 1512 1512 1638 1525 1525 1652 1513 1513 1639 1513 1513 1639 1525 1525 1652 1526 1526 1653 1513 1513 1639 1526 1526 1653 1514 1514 1640 1514 1514 1640 1526 1526 1653 1527 1527 1654 1514 1514 1640 1527 1527 1654 1515 1515 1641 1515 1515 1641 1527 1527 1654 1528 1528 1655 1515 1515 1641 1528 1528 1655 1516 1516 1642 1516 1516 1642 1528 1528 1655 1529 1529 1656 1516 1516 1642 1529 1529 1656 1517 1517 1643 1517 1517 1643 1529 1529 1656 1530 1530 1657 1517 1517 1643 1530 1530 1657 1518 1518 1644 1518 1518 1644 1530 1530 1657 1531 1531 1658 1518 1518 1644 1531 1531 1658 1519 1519 1645 1519 1519 1645 1531 1531 1658 1532 1532 1659 1519 1519 1645 1532 1532 1659 1520 1520 1646 1520 1520 1646 1532 1532 1659 1533 1533 1660 1520 1520 1646 1533 1533 1660 1521 1521 1647 1521 1521 1647 1533 1533 1660 1534 1534 1661 1521 1521 1647 1534 1534 1661 1522 1522 1648 1522 1522 1648 1534 1534 1661 1535 1535 1662 1522 1522 1648 1535 1535 1662 1523 1523 1649 1523 1523 1649 1535 1535 1662 1524 1524 1663 1523 1523 1649 1524 1524 1663 1512 1512 1650 1524 1524 1651 1536 1536 1664 1537 1537 1665 1524 1524 1651 1537 1537 1665 1525 1525 1652 1525 1525 1652 1537 1537 1665 1538 1538 1666 1525 1525 1652 1538 1538 1666 1526 1526 1653 1526 1526 1653 1538 1538 1666 1539 1539 1667 1526 1526 1653 1539 1539 1667 1527 1527 1654 1527 1527 1654 1539 1539 1667 1540 1540 1668 1527 1527 1654 1540 1540 1668 1528 1528 1655 1528 1528 1655 1540 1540 1668 1541 1541 1669 1528 1528 1655 1541 1541 1669 1529 1529 1656 1529 1529 1656 1541 1541 1669 1542 1542 1670 1529 1529 1656 1542 1542 1670 1530 1530 1657 1530 1530 1657 1542 1542 1670 1543 1543 1671 1530 1530 1657 1543 1543 1671 1531 1531 1658 1531 1531 1658 1543 1543 1671 1544 1544 1672 1531 1531 1658 1544 1544 1672 1532 1532 1659 1532 1532 1659 1544 1544 1672 1545 1545 1673 1532 1532 1659 1545 1545 1673 1533 1533 1660 1533 1533 1660 1545 1545 1673 1546 1546 1674 1533 1533 1660 1546 1546 1674 1534 1534 1661 1534 1534 1661 1546 1546 1674 1547 1547 1675 1534 1534 1661 1547 1547 1675 1535 1535 1662 1535 1535 1662 1547 1547 1675 1536 1536 1676 1535 1535 1662 1536 1536 1676 1524 1524 1663 1536 1536 1664 1548 1548 1677 1549 1549 1678 1536 1536 1664 1549 1549 1678 1537 1537 1665 1537 1537 1665 1549 1549 1678 1550 1550 1679 1537 1537 1665 1550 1550 1679 1538 1538 1666 1538 1538 1666 1550 1550 1679 1551 1551 1680 1538 1538 1666 1551 1551 1680 1539 1539 1667 1539 1539 1667 1551 1551 1680 1552 1552 1681 1539 1539 1667 1552 1552 1681 1540 1540 1668 1540 1540 1668 1552 1552 1681 1553 1553 1682 1540 1540 1668 1553 1553 1682 1541 1541 1669 1541 1541 1669 1553 1553 1682 1554 1554 1683 1541 1541 1669 1554 1554 1683 1542 1542 1670 1542 1542 1670 1554 1554 1683 1555 1555 1684 1542 1542 1670 1555 1555 1684 1543 1543 1671 1543 1543 1671 1555 1555 1684 1556 1556 1685 1543 1543 1671 1556 1556 1685 1544 1544 1672 1544 1544 1672 1556 1556 1685 1557 1557 1686 1544 1544 1672 1557 1557 1686 1545 1545 1673 1545 1545 1673 1557 1557 1686 1558 1558 1687 1545 1545 1673 1558 1558 1687 1546 1546 1674 1546 1546 1674 1558 1558 1687 1559 1559 1688 1546 1546 1674 1559 1559 1688 1547 1547 1675 1547 1547 1675 1559 1559 1688 1548 1548 1689 1547 1547 1675 1548 1548 1689 1536 1536 1676 1548 1548 1677 1560 1560 1690 1561 1561 1691 1548 1548 1677 1561 1561 1691 1549 1549 1678 1549 1549 1678 1561 1561 1691 1562 1562 1692 1549 1549 1678 1562 1562 1692 1550 1550 1679 1550 1550 1679 1562 1562 1692 1563 1563 1693 1550 1550 1679 1563 1563 1693 1551 1551 1680 1551 1551 1680 1563 1563 1693 1564 1564 1694 1551 1551 1680 1564 1564 1694 1552 1552 1681 1552 1552 1681 1564 1564 1694 1565 1565 1695 1552 1552 1681 1565 1565 1695 1553 1553 1682 1553 1553 1682 1565 1565 1695 1566 1566 1696 1553 1553 1682 1566 1566 1696 1554 1554 1683 1554 1554 1683 1566 1566 1696 1567 1567 1697 1554 1554 1683 1567 1567 1697 1555 1555 1684 1555 1555 1684 1567 1567 1697 1568 1568 1698 1555 1555 1684 1568 1568 1698 1556 1556 1685 1556 1556 1685 1568 1568 1698 1569 1569 1699 1556 1556 1685 1569 1569 1699 1557 1557 1686 1557 1557 1686 1569 1569 1699 1570 1570 1700 1557 1557 1686 1570 1570 1700 1558 1558 1687 1558 1558 1687 1570 1570 1700 1571 1571 1701 1558 1558 1687 1571 1571 1701 1559 1559 1688 1559 1559 1688 1571 1571 1701 1560 1560 1702 1559 1559 1688 1560 1560 1702 1548 1548 1689 1560 1560 1690 1572 1572 1703 1573 1573 1704 1560 1560 1690 1573 1573 1704 1561 1561 1691 1561 1561 1691 1573 1573 1704 1574 1574 1705 1561 1561 1691 1574 1574 1705 1562 1562 1692 1562 1562 1692 1574 1574 1705 1575 1575 1706 1562 1562 1692 1575 1575 1706 1563 1563 1693 1563 1563 1693 1575 1575 1706 1576 1576 1707 1563 1563 1693 1576 1576 1707 1564 1564 1694 1564 1564 1694 1576 1576 1707 1577 1577 1708 1564 1564 1694 1577 1577 1708 1565 1565 1695 1565 1565 1695 1577 1577 1708 1578 1578 1709 1565 1565 1695 1578 1578 1709 1566 1566 1696 1566 1566 1696 1578 1578 1709 1579 1579 1710 1566 1566 1696 1579 1579 1710 1567 1567 1697 1567 1567 1697 1579 1579 1710 1580 1580 1711 1567 1567 1697 1580 1580 1711 1568 1568 1698 1568 1568 1698 1580 1580 1711 1581 1581 1712 1568 1568 1698 1581 1581 1712 1569 1569 1699 1569 1569 1699 1581 1581 1712 1582 1582 1713 1569 1569 1699 1582 1582 1713 1570 1570 1700 1570 1570 1700 1582 1582 1713 1583 1583 1714 1570 1570 1700 1583 1583 1714 1571 1571 1701 1571 1571 1701 1583 1583 1714 1572 1572 1715 1571 1571 1701 1572 1572 1715 1560 1560 1702 1572 1572 1703 1584 1584 1716 1585 1585 1717 1572 1572 1703 1585 1585 1717 1573 1573 1704 1573 1573 1704 1585 1585 1717 1586 1586 1718 1573 1573 1704 1586 1586 1718 1574 1574 1705 1574 1574 1705 1586 1586 1718 1587 1587 1719 1574 1574 1705 1587 1587 1719 1575 1575 1706 1575 1575 1706 1587 1587 1719 1588 1588 1720 1575 1575 1706 1588 1588 1720 1576 1576 1707 1576 1576 1707 1588 1588 1720 1589 1589 1721 1576 1576 1707 1589 1589 1721 1577 1577 1708 1577 1577 1708 1589 1589 1721 1590 1590 1722 1577 1577 1708 1590 1590 1722 1578 1578 1709 1578 1578 1709 1590 1590 1722 1591 1591 1723 1578 1578 1709 1591 1591 1723 1579 1579 1710 1579 1579 1710 1591 1591 1723 1592 1592 1724 1579 1579 1710 1592 1592 1724 1580 1580 1711 1580 1580 1711 1592 1592 1724 1593 1593 1725 1580 1580 1711 1593 1593 1725 1581 1581 1712 1581 1581 1712 1593 1593 1725 1594 1594 1726 1581 1581 1712 1594 1594 1726 1582 1582 1713 1582 1582 1713 1594 1594 1726 1595 1595 1727 1582 1582 1713 1595 1595 1727 1583 1583 1714 1583 1583 1714 1595 1595 1727 1584 1584 1728 1583 1583 1714 1584 1584 1728 1572 1572 1715 1584 1584 1716 1596 1596 1729 1597 1597 1730 1584 1584 1716 1597 1597 1730 1585 1585 1717 1585 1585 1717 1597 1597 1730 1598 1598 1731 1585 1585 1717 1598 1598 1731 1586 1586 1718 1586 1586 1718 1598 1598 1731 1599 1599 1732 1586 1586 1718 1599 1599 1732 1587 1587 1719 1587 1587 1719 1599 1599 1732 1600 1600 1733 1587 1587 1719 1600 1600 1733 1588 1588 1720 1588 1588 1720 1600 1600 1733 1601 1601 1734 1588 1588 1720 1601 1601 1734 1589 1589 1721 1589 1589 1721 1601 1601 1734 1602 1602 1735 1589 1589 1721 1602 1602 1735 1590 1590 1722 1590 1590 1722 1602 1602 1735 1603 1603 1736 1590 1590 1722 1603 1603 1736 1591 1591 1723 1591 1591 1723 1603 1603 1736 1604 1604 1737 1591 1591 1723 1604 1604 1737 1592 1592 1724 1592 1592 1724 1604 1604 1737 1605 1605 1738 1592 1592 1724 1605 1605 1738 1593 1593 1725 1593 1593 1725 1605 1605 1738 1606 1606 1739 1593 1593 1725 1606 1606 1739 1594 1594 1726 1594 1594 1726 1606 1606 1739 1607 1607 1740 1594 1594 1726 1607 1607 1740 1595 1595 1727 1595 1595 1727 1607 1607 1740 1596 1596 1741 1595 1595 1727 1596 1596 1741 1584 1584 1728 1596 1596 1729 1608 1608 1742 1609 1609 1743 1596 1596 1729 1609 1609 1743 1597 1597 1730 1597 1597 1730 1609 1609 1743 1610 1610 1744 1597 1597 1730 1610 1610 1744 1598 1598 1731 1598 1598 1731 1610 1610 1744 1611 1611 1745 1598 1598 1731 1611 1611 1745 1599 1599 1732 1599 1599 1732 1611 1611 1745 1612 1612 1746 1599 1599 1732 1612 1612 1746 1600 1600 1733 1600 1600 1733 1612 1612 1746 1613 1613 1747 1600 1600 1733 1613 1613 1747 1601 1601 1734 1601 1601 1734 1613 1613 1747 1614 1614 1748 1601 1601 1734 1614 1614 1748 1602 1602 1735 1602 1602 1735 1614 1614 1748 1615 1615 1749 1602 1602 1735 1615 1615 1749 1603 1603 1736 1603 1603 1736 1615 1615 1749 1616 1616 1750 1603 1603 1736 1616 1616 1750 1604 1604 1737 1604 1604 1737 1616 1616 1750 1617 1617 1751 1604 1604 1737 1617 1617 1751 1605 1605 1738 1605 1605 1738 1617 1617 1751 1618 1618 1752 1605 1605 1738 1618 1618 1752 1606 1606 1739 1606 1606 1739 1618 1618 1752 1619 1619 1753 1606 1606 1739 1619 1619 1753 1607 1607 1740 1607 1607 1740 1619 1619 1753 1608 1608 1754 1607 1607 1740 1608 1608 1754 1596 1596 1741 1608 1608 1742 1620 1620 1755 1621 1621 1756 1608 1608 1742 1621 1621 1756 1609 1609 1743 1609 1609 1743 1621 1621 1756 1622 1622 1757 1609 1609 1743 1622 1622 1757 1610 1610 1744 1610 1610 1744 1622 1622 1757 1623 1623 1758 1610 1610 1744 1623 1623 1758 1611 1611 1745 1611 1611 1745 1623 1623 1758 1624 1624 1759 1611 1611 1745 1624 1624 1759 1612 1612 1746 1612 1612 1746 1624 1624 1759 1625 1625 1760 1612 1612 1746 1625 1625 1760 1613 1613 1747 1613 1613 1747 1625 1625 1760 1626 1626 1761 1613 1613 1747 1626 1626 1761 1614 1614 1748 1614 1614 1748 1626 1626 1761 1627 1627 1762 1614 1614 1748 1627 1627 1762 1615 1615 1749 1615 1615 1749 1627 1627 1762 1628 1628 1763 1615 1615 1749 1628 1628 1763 1616 1616 1750 1616 1616 1750 1628 1628 1763 1629 1629 1764 1616 1616 1750 1629 1629 1764 1617 1617 1751 1617 1617 1751 1629 1629 1764 1630 1630 1765 1617 1617 1751 1630 1630 1765 1618 1618 1752 1618 1618 1752 1630 1630 1765 1631 1631 1766 1618 1618 1752 1631 1631 1766 1619 1619 1753 1619 1619 1753 1631 1631 1766 1620 1620 1767 1619 1619 1753 1620 1620 1767 1608 1608 1754 1620 1620 1755 1632 1632 1768 1633 1633 1769 1620 1620 1755 1633 1633 1769 1621 1621 1756 1621 1621 1756 1633 1633 1769 1634 1634 1770 1621 1621 1756 1634 1634 1770 1622 1622 1757 1622 1622 1757 1634 1634 1770 1635 1635 1771 1622 1622 1757 1635 1635 1771 1623 1623 1758 1623 1623 1758 1635 1635 1771 1636 1636 1772 1623 1623 1758 1636 1636 1772 1624 1624 1759 1624 1624 1759 1636 1636 1772 1637 1637 1773 1624 1624 1759 1637 1637 1773 1625 1625 1760 1625 1625 1760 1637 1637 1773 1638 1638 1774 1625 1625 1760 1638 1638 1774 1626 1626 1761 1626 1626 1761 1638 1638 1774 1639 1639 1775 1626 1626 1761 1639 1639 1775 1627 1627 1762 1627 1627 1762 1639 1639 1775 1640 1640 1776 1627 1627 1762 1640 1640 1776 1628 1628 1763 1628 1628 1763 1640 1640 1776 1641 1641 1777 1628 1628 1763 1641 1641 1777 1629 1629 1764 1629 1629 1764 1641 1641 1777 1642 1642 1778 1629 1629 1764 1642 1642 1778 1630 1630 1765 1630 1630 1765 1642 1642 1778 1643 1643 1779 1630 1630 1765 1643 1643 1779 1631 1631 1766 1631 1631 1766 1643 1643 1779 1632 1632 1780 1631 1631 1766 1632 1632 1780 1620 1620 1767 1632 1632 1768 1644 1644 1781 1645 1645 1782 1632 1632 1768 1645 1645 1782 1633 1633 1769 1633 1633 1769 1645 1645 1782 1646 1646 1783 1633 1633 1769 1646 1646 1783 1634 1634 1770 1634 1634 1770 1646 1646 1783 1647 1647 1784 1634 1634 1770 1647 1647 1784 1635 1635 1771 1635 1635 1771 1647 1647 1784 1648 1648 1785 1635 1635 1771 1648 1648 1785 1636 1636 1772 1636 1636 1772 1648 1648 1785 1649 1649 1786 1636 1636 1772 1649 1649 1786 1637 1637 1773 1637 1637 1773 1649 1649 1786 1650 1650 1787 1637 1637 1773 1650 1650 1787 1638 1638 1774 1638 1638 1774 1650 1650 1787 1651 1651 1788 1638 1638 1774 1651 1651 1788 1639 1639 1775 1639 1639 1775 1651 1651 1788 1652 1652 1789 1639 1639 1775 1652 1652 1789 1640 1640 1776 1640 1640 1776 1652 1652 1789 1653 1653 1790 1640 1640 1776 1653 1653 1790 1641 1641 1777 1641 1641 1777 1653 1653 1790 1654 1654 1791 1641 1641 1777 1654 1654 1791 1642 1642 1778 1642 1642 1778 1654 1654 1791 1655 1655 1792 1642 1642 1778 1655 1655 1792 1643 1643 1779 1643 1643 1779 1655 1655 1792 1644 1644 1793 1643 1643 1779 1644 1644 1793 1632 1632 1780 1644 1644 1781 1656 1656 1794 1657 1657 1795 1644 1644 1781 1657 1657 1795 1645 1645 1782 1645 1645 1782 1657 1657 1795 1658 1658 1796 1645 1645 1782 1658 1658 1796 1646 1646 1783 1646 1646 1783 1658 1658 1796 1659 1659 1797 1646 1646 1783 1659 1659 1797 1647 1647 1784 1647 1647 1784 1659 1659 1797 1660 1660 1798 1647 1647 1784 1660 1660 1798 1648 1648 1785 1648 1648 1785 1660 1660 1798 1661 1661 1799 1648 1648 1785 1661 1661 1799 1649 1649 1786 1649 1649 1786 1661 1661 1799 1662 1662 1800 1649 1649 1786 1662 1662 1800 1650 1650 1787 1650 1650 1787 1662 1662 1800 1663 1663 1801 1650 1650 1787 1663 1663 1801 1651 1651 1788 1651 1651 1788 1663 1663 1801 1664 1664 1802 1651 1651 1788 1664 1664 1802 1652 1652 1789 1652 1652 1789 1664 1664 1802 1665 1665 1803 1652 1652 1789 1665 1665 1803 1653 1653 1790 1653 1653 1790 1665 1665 1803 1666 1666 1804 1653 1653 1790 1666 1666 1804 1654 1654 1791 1654 1654 1791 1666 1666 1804 1667 1667 1805 1654 1654 1791 1667 1667 1805 1655 1655 1792 1655 1655 1792 1667 1667 1805 1656 1656 1806 1655 1655 1792 1656 1656 1806 1644 1644 1793 1656 1656 1794 1668 1668 1807 1669 1669 1808 1656 1656 1794 1669 1669 1808 1657 1657 1795 1657 1657 1795 1669 1669 1808 1670 1670 1809 1657 1657 1795 1670 1670 1809 1658 1658 1796 1658 1658 1796 1670 1670 1809 1671 1671 1810 1658 1658 1796 1671 1671 1810 1659 1659 1797 1659 1659 1797 1671 1671 1810 1672 1672 1811 1659 1659 1797 1672 1672 1811 1660 1660 1798 1660 1660 1798 1672 1672 1811 1673 1673 1812 1660 1660 1798 1673 1673 1812 1661 1661 1799 1661 1661 1799 1673 1673 1812 1674 1674 1813 1661 1661 1799 1674 1674 1813 1662 1662 1800 1662 1662 1800 1674 1674 1813 1675 1675 1814 1662 1662 1800 1675 1675 1814 1663 1663 1801 1663 1663 1801 1675 1675 1814 1676 1676 1815 1663 1663 1801 1676 1676 1815 1664 1664 1802 1664 1664 1802 1676 1676 1815 1677 1677 1816 1664 1664 1802 1677 1677 1816 1665 1665 1803 1665 1665 1803 1677 1677 1816 1678 1678 1817 1665 1665 1803 1678 1678 1817 1666 1666 1804 1666 1666 1804 1678 1678 1817 1679 1679 1818 1666 1666 1804 1679 1679 1818 1667 1667 1805 1667 1667 1805 1679 1679 1818 1668 1668 1819 1667 1667 1805 1668 1668 1819 1656 1656 1806 1668 1668 1807 1680 1680 1820 1681 1681 1821 1668 1668 1807 1681 1681 1821 1669 1669 1808 1669 1669 1808 1681 1681 1821 1682 1682 1822 1669 1669 1808 1682 1682 1822 1670 1670 1809 1670 1670 1809 1682 1682 1822 1683 1683 1823 1670 1670 1809 1683 1683 1823 1671 1671 1810 1671 1671 1810 1683 1683 1823 1684 1684 1824 1671 1671 1810 1684 1684 1824 1672 1672 1811 1672 1672 1811 1684 1684 1824 1685 1685 1825 1672 1672 1811 1685 1685 1825 1673 1673 1812 1673 1673 1812 1685 1685 1825 1686 1686 1826 1673 1673 1812 1686 1686 1826 1674 1674 1813 1674 1674 1813 1686 1686 1826 1687 1687 1827 1674 1674 1813 1687 1687 1827 1675 1675 1814 1675 1675 1814 1687 1687 1827 1688 1688 1828 1675 1675 1814 1688 1688 1828 1676 1676 1815 1676 1676 1815 1688 1688 1828 1689 1689 1829 1676 1676 1815 1689 1689 1829 1677 1677 1816 1677 1677 1816 1689 1689 1829 1690 1690 1830 1677 1677 1816 1690 1690 1830 1678 1678 1817 1678 1678 1817 1690 1690 1830 1691 1691 1831 1678 1678 1817 1691 1691 1831 1679 1679 1818 1679 1679 1818 1691 1691 1831 1680 1680 1832 1679 1679 1818 1680 1680 1832 1668 1668 1819 1680 1680 1820 1692 1692 1833 1693 1693 1834 1680 1680 1820 1693 1693 1834 1681 1681 1821 1681 1681 1821 1693 1693 1834 1694 1694 1835 1681 1681 1821 1694 1694 1835 1682 1682 1822 1682 1682 1822 1694 1694 1835 1695 1695 1836 1682 1682 1822 1695 1695 1836 1683 1683 1823 1683 1683 1823 1695 1695 1836 1696 1696 1837 1683 1683 1823 1696 1696 1837 1684 1684 1824 1684 1684 1824 1696 1696 1837 1697 1697 1838 1684 1684 1824 1697 1697 1838 1685 1685 1825 1685 1685 1825 1697 1697 1838 1698 1698 1839 1685 1685 1825 1698 1698 1839 1686 1686 1826 1686 1686 1826 1698 1698 1839 1699 1699 1840 1686 1686 1826 1699 1699 1840 1687 1687 1827 1687 1687 1827 1699 1699 1840 1700 1700 1841 1687 1687 1827 1700 1700 1841 1688 1688 1828 1688 1688 1828 1700 1700 1841 1701 1701 1842 1688 1688 1828 1701 1701 1842 1689 1689 1829 1689 1689 1829 1701 1701 1842 1702 1702 1843 1689 1689 1829 1702 1702 1843 1690 1690 1830 1690 1690 1830 1702 1702 1843 1703 1703 1844 1690 1690 1830 1703 1703 1844 1691 1691 1831 1691 1691 1831 1703 1703 1844 1692 1692 1845 1691 1691 1831 1692 1692 1845 1680 1680 1832 1692 1692 1833 1704 1704 1846 1705 1705 1847 1692 1692 1833 1705 1705 1847 1693 1693 1834 1693 1693 1834 1705 1705 1847 1706 1706 1848 1693 1693 1834 1706 1706 1848 1694 1694 1835 1694 1694 1835 1706 1706 1848 1707 1707 1849 1694 1694 1835 1707 1707 1849 1695 1695 1836 1695 1695 1836 1707 1707 1849 1708 1708 1850 1695 1695 1836 1708 1708 1850 1696 1696 1837 1696 1696 1837 1708 1708 1850 1709 1709 1851 1696 1696 1837 1709 1709 1851 1697 1697 1838 1697 1697 1838 1709 1709 1851 1710 1710 1852 1697 1697 1838 1710 1710 1852 1698 1698 1839 1698 1698 1839 1710 1710 1852 1711 1711 1853 1698 1698 1839 1711 1711 1853 1699 1699 1840 1699 1699 1840 1711 1711 1853 1712 1712 1854 1699 1699 1840 1712 1712 1854 1700 1700 1841 1700 1700 1841 1712 1712 1854 1713 1713 1855 1700 1700 1841 1713 1713 1855 1701 1701 1842 1701 1701 1842 1713 1713 1855 1714 1714 1856 1701 1701 1842 1714 1714 1856 1702 1702 1843 1702 1702 1843 1714 1714 1856 1715 1715 1857 1702 1702 1843 1715 1715 1857 1703 1703 1844 1703 1703 1844 1715 1715 1857 1704 1704 1858 1703 1703 1844 1704 1704 1858 1692 1692 1845 1704 1704 1846 1716 1716 1859 1717 1717 1860 1704 1704 1846 1717 1717 1860 1705 1705 1847 1705 1705 1847 1717 1717 1860 1718 1718 1861 1705 1705 1847 1718 1718 1861 1706 1706 1848 1706 1706 1848 1718 1718 1861 1719 1719 1862 1706 1706 1848 1719 1719 1862 1707 1707 1849 1707 1707 1849 1719 1719 1862 1720 1720 1863 1707 1707 1849 1720 1720 1863 1708 1708 1850 1708 1708 1850 1720 1720 1863 1721 1721 1864 1708 1708 1850 1721 1721 1864 1709 1709 1851 1709 1709 1851 1721 1721 1864 1722 1722 1865 1709 1709 1851 1722 1722 1865 1710 1710 1852 1710 1710 1852 1722 1722 1865 1723 1723 1866 1710 1710 1852 1723 1723 1866 1711 1711 1853 1711 1711 1853 1723 1723 1866 1724 1724 1867 1711 1711 1853 1724 1724 1867 1712 1712 1854 1712 1712 1854 1724 1724 1867 1725 1725 1868 1712 1712 1854 1725 1725 1868 1713 1713 1855 1713 1713 1855 1725 1725 1868 1726 1726 1869 1713 1713 1855 1726 1726 1869 1714 1714 1856 1714 1714 1856 1726 1726 1869 1727 1727 1870 1714 1714 1856 1727 1727 1870 1715 1715 1857 1715 1715 1857 1727 1727 1870 1716 1716 1871 1715 1715 1857 1716 1716 1871 1704 1704 1858 1716 1716 1859 1728 1728 1872 1729 1729 1873 1716 1716 1859 1729 1729 1873 1717 1717 1860 1717 1717 1860 1729 1729 1873 1730 1730 1874 1717 1717 1860 1730 1730 1874 1718 1718 1861 1718 1718 1861 1730 1730 1874 1731 1731 1875 1718 1718 1861 1731 1731 1875 1719 1719 1862 1719 1719 1862 1731 1731 1875 1732 1732 1876 1719 1719 1862 1732 1732 1876 1720 1720 1863 1720 1720 1863 1732 1732 1876 1733 1733 1877 1720 1720 1863 1733 1733 1877 1721 1721 1864 1721 1721 1864 1733 1733 1877 1734 1734 1878 1721 1721 1864 1734 1734 1878 1722 1722 1865 1722 1722 1865 1734 1734 1878 1735 1735 1879 1722 1722 1865 1735 1735 1879 1723 1723 1866 1723 1723 1866 1735 1735 1879 1736 1736 1880 1723 1723 1866 1736 1736 1880 1724 1724 1867 1724 1724 1867 1736 1736 1880 1737 1737 1881 1724 1724 1867 1737 1737 1881 1725 1725 1868 1725 1725 1868 1737 1737 1881 1738 1738 1882 1725 1725 1868 1738 1738 1882 1726 1726 1869 1726 1726 1869 1738 1738 1882 1739 1739 1883 1726 1726 1869 1739 1739 1883 1727 1727 1870 1727 1727 1870 1739 1739 1883 1728 1728 1884 1727 1727 1870 1728 1728 1884 1716 1716 1871 1728 1728 1872 1740 1740 1885 1741 1741 1886 1728 1728 1872 1741 1741 1886 1729 1729 1873 1729 1729 1873 1741 1741 1886 1742 1742 1887 1729 1729 1873 1742 1742 1887 1730 1730 1874 1730 1730 1874 1742 1742 1887 1743 1743 1888 1730 1730 1874 1743 1743 1888 1731 1731 1875 1731 1731 1875 1743 1743 1888 1744 1744 1889 1731 1731 1875 1744 1744 1889 1732 1732 1876 1732 1732 1876 1744 1744 1889 1745 1745 1890 1732 1732 1876 1745 1745 1890 1733 1733 1877 1733 1733 1877 1745 1745 1890 1746 1746 1891 1733 1733 1877 1746 1746 1891 1734 1734 1878 1734 1734 1878 1746 1746 1891 1747 1747 1892 1734 1734 1878 1747 1747 1892 1735 1735 1879 1735 1735 1879 1747 1747 1892 1748 1748 1893 1735 1735 1879 1748 1748 1893 1736 1736 1880 1736 1736 1880 1748 1748 1893 1749 1749 1894 1736 1736 1880 1749 1749 1894 1737 1737 1881 1737 1737 1881 1749 1749 1894 1750 1750 1895 1737 1737 1881 1750 1750 1895 1738 1738 1882 1738 1738 1882 1750 1750 1895 1751 1751 1896 1738 1738 1882 1751 1751 1896 1739 1739 1883 1739 1739 1883 1751 1751 1896 1740 1740 1897 1739 1739 1883 1740 1740 1897 1728 1728 1884 1740 1740 1885 1752 1752 1898 1753 1753 1899 1740 1740 1885 1753 1753 1899 1741 1741 1886 1741 1741 1886 1753 1753 1899 1754 1754 1900 1741 1741 1886 1754 1754 1900 1742 1742 1887 1742 1742 1887 1754 1754 1900 1755 1755 1901 1742 1742 1887 1755 1755 1901 1743 1743 1888 1743 1743 1888 1755 1755 1901 1756 1756 1902 1743 1743 1888 1756 1756 1902 1744 1744 1889 1744 1744 1889 1756 1756 1902 1757 1757 1903 1744 1744 1889 1757 1757 1903 1745 1745 1890 1745 1745 1890 1757 1757 1903 1758 1758 1904 1745 1745 1890 1758 1758 1904 1746 1746 1891 1746 1746 1891 1758 1758 1904 1759 1759 1905 1746 1746 1891 1759 1759 1905 1747 1747 1892 1747 1747 1892 1759 1759 1905 1760 1760 1906 1747 1747 1892 1760 1760 1906 1748 1748 1893 1748 1748 1893 1760 1760 1906 1761 1761 1907 1748 1748 1893 1761 1761 1907 1749 1749 1894 1749 1749 1894 1761 1761 1907 1762 1762 1908 1749 1749 1894 1762 1762 1908 1750 1750 1895 1750 1750 1895 1762 1762 1908 1763 1763 1909 1750 1750 1895 1763 1763 1909 1751 1751 1896 1751 1751 1896 1763 1763 1909 1752 1752 1910 1751 1751 1896 1752 1752 1910 1740 1740 1897 1752 1752 1898 1764 1764 1911 1765 1765 1912 1752 1752 1898 1765 1765 1912 1753 1753 1899 1753 1753 1899 1765 1765 1912 1766 1766 1913 1753 1753 1899 1766 1766 1913 1754 1754 1900 1754 1754 1900 1766 1766 1913 1767 1767 1914 1754 1754 1900 1767 1767 1914 1755 1755 1901 1755 1755 1901 1767 1767 1914 1768 1768 1915 1755 1755 1901 1768 1768 1915 1756 1756 1902 1756 1756 1902 1768 1768 1915 1769 1769 1916 1756 1756 1902 1769 1769 1916 1757 1757 1903 1757 1757 1903 1769 1769 1916 1770 1770 1917 1757 1757 1903 1770 1770 1917 1758 1758 1904 1758 1758 1904 1770 1770 1917 1771 1771 1918 1758 1758 1904 1771 1771 1918 1759 1759 1905 1759 1759 1905 1771 1771 1918 1772 1772 1919 1759 1759 1905 1772 1772 1919 1760 1760 1906 1760 1760 1906 1772 1772 1919 1773 1773 1920 1760 1760 1906 1773 1773 1920 1761 1761 1907 1761 1761 1907 1773 1773 1920 1774 1774 1921 1761 1761 1907 1774 1774 1921 1762 1762 1908 1762 1762 1908 1774 1774 1921 1775 1775 1922 1762 1762 1908 1775 1775 1922 1763 1763 1909 1763 1763 1909 1775 1775 1922 1764 1764 1923 1763 1763 1909 1764 1764 1923 1752 1752 1910 1764 1764 1911 1776 1776 1924 1777 1777 1925 1764 1764 1911 1777 1777 1925 1765 1765 1912 1765 1765 1912 1777 1777 1925 1778 1778 1926 1765 1765 1912 1778 1778 1926 1766 1766 1913 1766 1766 1913 1778 1778 1926 1779 1779 1927 1766 1766 1913 1779 1779 1927 1767 1767 1914 1767 1767 1914 1779 1779 1927 1780 1780 1928 1767 1767 1914 1780 1780 1928 1768 1768 1915 1768 1768 1915 1780 1780 1928 1781 1781 1929 1768 1768 1915 1781 1781 1929 1769 1769 1916 1769 1769 1916 1781 1781 1929 1782 1782 1930 1769 1769 1916 1782 1782 1930 1770 1770 1917 1770 1770 1917 1782 1782 1930 1783 1783 1931 1770 1770 1917 1783 1783 1931 1771 1771 1918 1771 1771 1918 1783 1783 1931 1784 1784 1932 1771 1771 1918 1784 1784 1932 1772 1772 1919 1772 1772 1919 1784 1784 1932 1785 1785 1933 1772 1772 1919 1785 1785 1933 1773 1773 1920 1773 1773 1920 1785 1785 1933 1786 1786 1934 1773 1773 1920 1786 1786 1934 1774 1774 1921 1774 1774 1921 1786 1786 1934 1787 1787 1935 1774 1774 1921 1787 1787 1935 1775 1775 1922 1775 1775 1922 1787 1787 1935 1776 1776 1936 1775 1775 1922 1776 1776 1936 1764 1764 1923 1776 1776 1924 1788 1788 1937 1789 1789 1938 1776 1776 1924 1789 1789 1938 1777 1777 1925 1777 1777 1925 1789 1789 1938 1790 1790 1939 1777 1777 1925 1790 1790 1939 1778 1778 1926 1778 1778 1926 1790 1790 1939 1791 1791 1940 1778 1778 1926 1791 1791 1940 1779 1779 1927 1779 1779 1927 1791 1791 1940 1792 1792 1941 1779 1779 1927 1792 1792 1941 1780 1780 1928 1780 1780 1928 1792 1792 1941 1793 1793 1942 1780 1780 1928 1793 1793 1942 1781 1781 1929 1781 1781 1929 1793 1793 1942 1794 1794 1943 1781 1781 1929 1794 1794 1943 1782 1782 1930 1782 1782 1930 1794 1794 1943 1795 1795 1944 1782 1782 1930 1795 1795 1944 1783 1783 1931 1783 1783 1931 1795 1795 1944 1796 1796 1945 1783 1783 1931 1796 1796 1945 1784 1784 1932 1784 1784 1932 1796 1796 1945 1797 1797 1946 1784 1784 1932 1797 1797 1946 1785 1785 1933 1785 1785 1933 1797 1797 1946 1798 1798 1947 1785 1785 1933 1798 1798 1947 1786 1786 1934 1786 1786 1934 1798 1798 1947 1799 1799 1948 1786 1786 1934 1799 1799 1948 1787 1787 1935 1787 1787 1935 1799 1799 1948 1788 1788 1949 1787 1787 1935 1788 1788 1949 1776 1776 1936 1788 1788 1937 0 0 1950 1 3 1951 1788 1788 1937 1 3 1951 1789 1789 1938 1789 1789 1938 1 3 1951 2 5 1952 1789 1789 1938 2 5 1952 1790 1790 1939 1790 1790 1939 2 5 1952 3 7 1953 1790 1790 1939 3 7 1953 1791 1791 1940 1791 1791 1940 3 7 1953 4 9 1954 1791 1791 1940 4 9 1954 1792 1792 1941 1792 1792 1941 4 9 1954 5 11 1955 1792 1792 1941 5 11 1955 1793 1793 1942 1793 1793 1942 5 11 1955 6 13 1956 1793 1793 1942 6 13 1956 1794 1794 1943 1794 1794 1943 6 13 1956 7 15 1957 1794 1794 1943 7 15 1957 1795 1795 1944 1795 1795 1944 7 15 1957 8 17 1958 1795 1795 1944 8 17 1958 1796 1796 1945 1796 1796 1945 8 17 1958 9 19 1959 1796 1796 1945 9 19 1959 1797 1797 1946 1797 1797 1946 9 19 1959 10 21 1960 1797 1797 1946 10 21 1960 1798 1798 1947 1798 1798 1947 10 21 1960 11 23 1961 1798 1798 1947 11 23 1961 1799 1799 1948 1799 1799 1948 11 23 1961 0 0 1962 1799 1799 1948 0 0 1962 1788 1788 1949</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-6_max" name="Torus_Knot-6_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-6_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-7.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-7.DAE
new file mode 100644
index 00000000..0665b117
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-7.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-7.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:32:06Z</created>
+ <modified>2008-10-31T16:32:07Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="8640">24.084917 -0.000996 21.369627 24.291664 -0.345620 21.669147 24.391800 -0.666689 22.040779 24.378500 -0.942326 22.459192 24.252674 -1.153744 22.895876 24.022892 -1.286536 23.321068 23.704817 -1.331653 23.705795 23.320124 -1.286020 24.023838 22.895029 -1.152747 24.253519 22.458502 -0.940916 24.379190 22.040291 -0.664964 24.392288 21.668896 -0.343695 24.291916 21.369627 0.000996 24.084917 21.162880 0.345619 23.785397 21.062744 0.666689 23.413765 21.076044 0.942325 22.995354 21.201870 1.153743 22.558670 21.431652 1.286536 22.133478 21.749727 1.331653 21.748749 22.134420 1.286020 21.430708 22.559515 1.152748 21.201025 22.996042 0.940917 21.075354 23.414253 0.664964 21.062256 23.785648 0.343696 21.162626 23.208162 3.784582 22.872587 23.631956 3.692655 22.533825 24.103525 3.523370 22.306276 24.590733 3.288263 22.205456 25.060377 3.003356 22.238228 25.480452 2.688064 22.402363 25.822330 2.363875 22.686672 26.062714 2.052881 23.071785 26.185221 1.776276 23.531450 26.181501 1.552911 24.034348 26.051811 1.398006 24.546206 25.804987 1.322120 25.032137 25.457851 1.330422 25.459032 25.034058 1.422348 25.797794 24.562489 1.591633 26.025341 24.075281 1.826740 26.126163 23.605637 2.111648 26.093391 23.185560 2.426939 25.929256 22.843681 2.751129 25.644947 22.603298 3.062123 25.259836 22.480791 3.338727 24.800169 22.484510 3.562093 24.297272 22.614201 3.716997 23.785416 22.861023 3.792884 23.299482 23.992308 5.964663 26.969469 23.660940 6.239866 26.427019 23.479670 6.464475 25.797350 23.460854 6.623182 25.123371 23.605770 6.705173 24.451010 23.904545 6.704859 23.826092 24.336819 6.622262 23.291199 24.873129 6.463012 22.882788 25.476931 6.237960 22.628687 26.107075 5.962443 22.546213 26.720615 5.655238 22.640993 27.275745 5.337280 22.906561 27.734629 5.030238 23.324820 28.065996 4.755034 23.867268 28.247267 4.530426 24.496937 28.266083 4.371718 25.170918 28.121166 4.289727 25.843277 27.822392 4.290040 26.468197 27.390120 4.372637 27.003088 26.853807 4.531888 27.411501 26.250006 4.756939 27.665602 25.619864 5.032455 27.748074 25.006321 5.339661 27.653297 24.451193 5.657619 27.387730 29.433968 8.076095 28.130424 28.720762 8.327477 28.644575 27.906317 8.614415 28.945486 27.046131 8.917356 29.012648 26.198826 9.215655 28.841486 25.422146 9.488983 28.443666 24.769016 9.718713 27.846296 24.283953 9.889191 27.090088 24.000006 9.988795 26.226574 23.936527 10.010742 25.314602 24.097845 9.953534 24.416323 24.472965 9.821070 23.592949 25.036324 9.622376 22.900599 25.749527 9.370996 22.386446 26.563972 9.084057 22.085535 27.424158 8.781116 22.018372 28.271463 8.482817 22.189533 29.048145 8.209489 22.587355 29.701273 7.979758 23.184723 30.186338 7.809282 23.940933 30.470285 7.709676 24.804445 30.533764 7.687729 25.716417 30.372446 7.744936 26.614698 29.997326 7.877401 27.438070 31.551193 11.215729 22.158209 32.241497 11.276027 23.130432 32.665379 11.427520 24.236214 32.793945 11.659884 25.400192 32.618439 11.957287 26.543051 32.150818 12.299458 27.586901 31.422951 12.663078 28.460609 30.484442 13.023370 29.104631 29.399248 13.355779 29.475079 28.241322 13.637651 29.546707 27.089577 13.849779 29.314634 26.022501 13.977706 28.794676 25.112812 14.012712 28.022266 24.422508 13.952415 27.050043 23.998629 13.800921 25.944263 23.870060 13.568557 24.780281 24.045567 13.271154 23.637424 24.513187 12.928985 22.593573 25.241053 12.565364 21.719866 26.179562 12.205071 21.075844 27.264755 11.872663 20.705395 28.422682 11.590790 20.633766 29.574427 11.378662 20.865839 30.641504 11.250735 21.385796 24.950922 15.359750 19.832640 26.140528 14.886744 19.043905 27.525337 14.540442 18.571278 29.010979 14.344448 18.446968 30.496208 14.312115 18.679443 31.879810 14.445648 19.252869 33.067493 14.735946 20.128157 33.978321 15.163226 21.245663 34.550220 15.698372 22.529234 34.744217 16.304911 23.891392 34.547092 16.941511 25.239307 33.972279 17.564787 26.481125 33.058949 18.132263 27.532219 31.869343 18.605270 28.320953 30.484533 18.951572 28.793581 28.998894 19.147568 28.917894 27.513662 19.179903 28.685415 26.130060 19.046370 28.111994 24.942375 18.756069 27.236704 24.031549 18.328789 26.119198 23.459650 17.793644 24.835629 23.265652 17.187107 23.473473 23.462776 16.550507 22.125555 24.037590 15.927231 20.883736 24.161263 23.762262 25.265675 23.063019 22.877989 24.125299 22.374874 21.874481 22.780693 22.143723 20.820129 21.323484 22.385323 19.786789 19.852982 23.083202 18.844875 18.469398 24.189808 18.058582 17.267023 25.629723 17.481493 16.327793 27.304821 17.152935 15.715720 29.100946 17.095301 15.472510 30.895697 17.312515 15.614741 32.566761 17.789776 16.132721 34.000263 18.494560 16.991146 35.098507 19.378836 18.131521 35.786652 20.382343 19.476128 36.017803 21.436693 20.933334 35.776203 22.470036 22.403835 35.078323 23.411947 23.787420 33.971718 24.198240 24.989796 32.531803 24.775330 25.929026 30.856707 25.103888 26.541101 29.060583 25.161524 26.784311 27.265833 24.944311 26.642080 25.594767 24.467049 26.124102 33.826962 30.384117 20.715958 32.164089 31.046932 21.800243 30.243750 31.335752 22.580656 28.196817 31.230894 23.004005 26.162785 30.739502 23.041445 24.280268 29.895069 22.690422 22.677559 28.755136 21.974861 21.463879 27.397390 20.943521 20.721935 25.914360 19.666693 20.502295 24.407112 18.231384 20.819923 22.978357 16.735413 21.653173 21.725471 15.280725 22.945263 20.733829 13.966454 24.608137 20.071014 12.882168 26.528475 19.782192 12.101757 28.575407 19.887053 11.678406 30.609442 20.378443 11.640966 32.491959 21.222878 11.991988 34.094666 22.362808 12.707550 35.308350 23.720554 13.738887 36.050293 25.203583 15.015717 36.269936 26.710835 16.451025 35.952305 28.139585 17.946995 35.119057 29.392473 19.401686 33.136929 26.117743 7.360517 34.374249 27.897432 8.172525 35.094570 29.803440 9.270662 35.248798 31.705868 10.580090 34.826431 33.475071 12.011574 33.856251 34.990479 13.467563 32.404369 36.148823 14.848831 30.569733 36.871159 16.061249 28.477367 37.108269 17.022192 26.269867 36.843983 17.666172 24.097666 36.096325 17.949305 22.108797 34.916233 17.852295 20.438799 33.384136 17.381752 19.201479 31.604446 16.569744 18.481159 29.698441 15.471609 18.326925 27.796015 14.162181 18.749292 26.026808 12.730695 19.719473 24.511398 11.274707 21.171354 23.353058 9.893438 23.005989 22.630718 8.681021 25.098354 22.393610 7.720078 27.305855 22.657892 7.076097 29.478058 23.405554 6.792964 31.466927 24.585642 6.889973 18.848246 25.764589 5.148657 20.784189 25.013126 3.835466 22.955801 24.830946 2.700582 25.215086 25.230461 1.821344 27.408079 26.184452 1.257670 29.385332 27.627899 1.047976 31.012098 29.462437 1.206549 32.177517 31.563046 1.722585 32.802162 33.786568 2.560916 32.843472 35.981480 3.664412 32.298630 37.998196 4.957870 31.204763 39.699287 6.353143 29.636417 40.968822 7.755147 27.700474 41.720287 9.068338 25.528866 41.902470 10.203223 23.269581 41.502953 11.082461 21.076586 40.548962 11.646135 19.099331 39.105515 11.855831 17.472565 37.270981 11.697258 16.307146 35.170372 11.181223 15.682498 32.946846 10.342892 15.641187 30.751938 9.239397 16.186029 28.735218 7.945940 17.279896 27.034126 6.550665 13.915882 40.078190 5.325264 12.910463 37.789627 5.145902 12.444976 35.384857 4.615854 12.551141 33.027756 3.771243 13.221724 30.878965 2.669628 14.411025 29.084911 1.386083 16.037994 27.767862 0.008078 17.991760 27.017572 -1.370478 20.139172 26.885168 -2.655637 22.333891 27.379677 -3.759820 24.426350 28.467396 -4.607778 26.273951 30.074200 -5.141723 27.750780 32.090591 -5.325268 28.756199 34.379154 -5.145906 29.221687 36.783924 -4.615859 29.115524 39.141026 -3.771249 28.444942 41.289818 -2.669634 27.255642 43.083870 -1.386088 25.628672 44.400921 -0.008083 23.674908 45.151211 1.370472 21.527494 45.283615 2.655632 19.332775 44.789108 3.759815 17.240316 43.701393 4.607773 15.392716 42.094585 5.141719 20.651060 46.152798 -7.770945 18.767895 46.876156 -6.368272 16.748936 46.972660 -4.971298 14.731771 46.435741 -3.675226 12.853864 45.301987 -2.568379 11.243195 43.648655 -1.726189 10.009524 41.588425 -1.206049 9.236928 39.261692 -1.043406 8.978055 36.827023 -1.249341 9.250547 34.450333 -1.809824 10.035835 32.293594 -2.686656 11.280404 30.503780 -3.820085 12.899437 29.202866 -5.132867 14.782600 28.479507 -6.535540 16.801558 28.382996 -7.932513 18.818724 28.919914 -9.228586 20.696632 30.053669 -10.335434 22.307302 31.707001 -11.177624 23.540974 33.767231 -11.697765 24.313570 36.093964 -11.860409 24.572445 38.528633 -11.654473 24.299952 40.905323 -11.093991 23.514664 43.062065 -10.217159 22.270098 44.851879 -9.083732 18.691257 34.392521 -17.382778 19.179989 36.604698 -17.857155 19.204710 38.917038 -17.957666 18.763731 41.171951 -17.677467 17.887110 43.215782 -17.035650 16.634583 44.909229 -16.075954 15.091509 46.136902 -14.863781 13.363046 46.815132 -13.481739 11.566987 46.897697 -12.024012 9.825728 46.378971 -10.589939 8.257935 45.294308 -9.277252 6.970449 43.717621 -8.175409 6.051011 41.756363 -7.359498 5.562278 39.544186 -6.885122 5.537558 37.231846 -6.784608 5.978534 34.976929 -7.064807 6.855156 32.933105 -7.706624 8.107683 31.239651 -8.666320 9.650756 30.011978 -9.878492 11.379219 29.333748 -11.260534 13.175279 29.251183 -12.718263 14.916537 29.769905 -14.152334 16.484331 30.854568 -15.465021 17.771818 32.431255 -16.566864 6.496857 30.241814 -13.952846 8.000739 29.618395 -15.268080 9.500596 29.522728 -16.724594 10.894214 29.961336 -18.223129 12.086619 30.904325 -19.661562 12.996553 32.287437 -20.941868 13.562004 34.016411 -21.976793 13.744439 35.973415 -22.695812 13.531424 38.025097 -23.049923 12.937475 40.031624 -23.014996 12.003071 41.856262 -22.593407 10.791888 43.374664 -21.813894 9.386467 44.483349 -20.729570 7.882585 45.106773 -19.414337 6.382729 45.202438 -17.957825 4.989111 44.763832 -16.459290 3.796704 43.820839 -15.020854 2.886770 42.437733 -13.740548 2.321318 40.708763 -12.705624 2.138883 38.751755 -11.986604 2.351897 36.700073 -11.632492 2.945845 34.693546 -11.667419 3.880249 32.868908 -12.089006 5.091432 31.350504 -12.868521 -0.981557 38.693108 -16.989590 -0.871691 37.100960 -16.128469 -0.446363 35.416668 -15.608088 0.265441 33.755016 -15.463907 1.215214 32.229244 -15.705754 2.338229 30.943329 -16.317142 3.557956 29.984905 -17.256414 4.791272 29.419287 -18.459555 5.954128 29.285023 -19.844572 6.967278 29.591257 -21.317083 7.761677 30.317123 -22.776735 8.283189 31.413157 -24.124056 8.496273 32.804661 -25.267229 8.386408 34.396809 -26.128349 7.961080 36.081100 -26.648731 7.249277 37.742752 -26.792913 6.299503 39.268528 -26.551067 5.176488 40.554440 -25.939678 3.956761 41.512867 -25.000408 2.723446 42.078484 -23.797268 1.560589 42.212753 -22.412251 0.547439 41.906517 -20.939739 -0.246961 41.180649 -19.480087 -0.768473 40.084618 -18.132767 -0.839059 37.687576 -27.538698 -1.786172 38.195377 -26.486980 -2.611561 38.382660 -25.244137 -3.258976 38.236649 -23.894867 -3.684298 37.767296 -22.531116 -3.858540 37.006592 -21.245829 -3.769830 36.006374 -20.126591 -3.424212 34.834808 -19.249680 -2.845240 33.571732 -18.674849 -2.072370 32.303223 -18.441278 -1.158271 31.115728 -18.564880 -0.165239 30.090174 -19.037239 0.839055 29.296448 -19.826157 1.786168 28.788645 -20.877874 2.611556 28.601366 -22.120716 3.258972 28.747377 -23.469986 3.684294 29.216730 -24.833736 3.858537 29.977434 -26.119026 3.769827 30.977650 -27.238264 3.424210 32.149216 -28.115179 2.845238 33.412292 -28.690006 2.072368 34.680798 -28.923580 1.158270 35.868294 -28.799974 0.165237 36.893848 -28.327620 -0.423491 28.753309 -28.023636 -0.911200 29.521481 -28.796568 -1.557734 30.379738 -29.316919 -2.319032 31.269587 -29.549231 -3.143212 32.130386 -29.477669 -3.974109 32.903477 -29.107109 -4.755098 33.536175 -28.462807 -5.432956 33.985359 -27.588671 -5.961488 34.220421 -26.544270 -6.304676 34.225338 -25.400778 -6.439131 33.999783 -24.236124 -6.355692 33.559116 -23.129677 -6.060044 32.933376 -22.156839 -5.572335 32.165203 -21.383907 -4.925802 31.306950 -20.863554 -4.164505 30.417099 -20.631243 -3.340323 29.556297 -20.702805 -2.509426 28.783207 -21.073362 -1.728437 28.150509 -21.717665 -1.050579 27.701324 -22.591801 -0.522047 27.466263 -23.636202 -0.178859 27.461346 -24.779694 -0.044403 27.686903 -25.944345 -0.127842 28.127567 -27.050793 -4.178132 26.499691 -22.901503 -3.725233 26.110565 -23.594084 -3.424216 25.850950 -24.417606 -3.295592 25.738533 -25.315950 -3.348129 25.780979 -26.227894 -3.578246 25.975391 -27.091290 -3.970260 26.308525 -27.847300 -4.497457 26.757675 -28.444403 -5.123909 27.292233 -28.841906 -5.806924 27.875771 -29.012720 -6.499956 28.468519 -28.945206 -7.155776 29.030085 -28.643965 -7.729691 29.522198 -28.129522 -8.182590 29.911324 -27.436943 -8.483608 30.170938 -26.613420 -8.612231 30.283354 -25.715075 -8.559694 30.240910 -24.803131 -8.329578 30.046497 -23.939735 -7.937564 29.713364 -23.183727 -7.410367 29.264214 -22.586624 -6.783916 28.729656 -22.189121 -6.100901 28.146118 -22.018305 -5.407868 27.553371 -22.085819 -4.752048 26.991804 -22.387060 -9.508790 26.535343 -23.324211 -9.012400 26.292526 -22.906563 -8.458656 25.971655 -22.641609 -7.885297 25.594595 -22.547403 -7.331394 25.187042 -22.630363 -6.834696 24.776768 -22.884840 -6.429051 24.391737 -23.293488 -6.142104 24.058184 -23.828461 -5.993409 23.798843 -24.453299 -5.993100 23.631386 -25.125422 -6.141198 23.567225 -25.799025 -6.427610 23.610733 -26.428204 -6.832818 23.758945 -26.970081 -7.329207 24.001759 -27.387728 -7.882950 24.322632 -27.652683 -8.456309 24.699694 -27.746891 -9.010213 25.107246 -27.663929 -9.506911 25.517519 -27.409454 -9.912557 25.902552 -27.000805 -10.199504 26.236105 -26.465834 -10.348199 26.495445 -25.840994 -10.348508 26.662905 -25.168873 -10.200411 26.727066 -24.495268 -9.913999 26.683556 -23.866091 -11.579261 22.709946 -25.456537 -11.759428 23.006807 -25.029659 -11.816398 23.259027 -24.543909 -11.746287 23.449421 -24.032394 -11.553875 23.565004 -23.529972 -11.252273 23.597912 -23.070881 -10.862036 23.545893 -22.686407 -10.409756 23.412495 -22.402752 -9.926257 23.206810 -22.239244 -9.444489 22.942854 -22.207031 -8.997281 22.638615 -22.308304 -8.615112 22.314827 -22.536163 -8.324025 21.993557 -22.875082 -8.143858 21.696695 -23.301960 -8.086888 21.444475 -23.787708 -8.156999 21.254084 -24.299221 -8.349411 21.138498 -24.801647 -8.651012 21.105591 -25.260738 -9.041250 21.157610 -25.645212 -9.493529 21.291008 -25.928867 -9.977028 21.496693 -26.092373 -10.458797 21.760647 -26.124588 -10.906004 22.064886 -26.023315 -11.288174 22.388674 -25.795456 -10.685737 18.506105 -24.084917 -11.134242 18.592592 -24.291277 -11.598381 18.753347 -24.391052 -12.046522 18.977415 -24.377447 -12.448125 19.249527 -24.251383 -12.775823 19.551138 -24.021452 -13.007282 19.861692 -23.703327 -13.126730 20.160030 -23.318684 -13.126025 20.425816 -22.893738 -13.005218 20.640938 -22.457447 -12.772539 20.790737 -22.039545 -12.443846 20.865005 -21.668510 -12.041538 20.858683 -21.369629 -11.593033 20.772196 -21.163267 -11.128894 20.611441 -21.063490 -10.680754 20.387373 -21.077099 -10.279149 20.115261 -21.203161 -9.951452 19.813650 -21.433092 -9.719993 19.503096 -21.751217 -9.600544 19.204760 -22.135860 -9.601249 18.938972 -22.560806 -9.722056 18.723850 -22.997097 -9.954735 18.574051 -23.414999 -10.283428 18.499783 -23.786034 -10.546230 17.059784 -20.106480 -10.462528 16.704521 -20.518295 -10.515764 16.380714 -20.960026 -10.702309 16.110432 -21.401569 -11.009448 15.912093 -21.812836 -11.416253 15.799214 -22.165794 -11.895000 15.779489 -22.436394 -12.413063 15.854260 -22.606192 -12.935137 16.018433 -22.663620 -13.425644 16.260820 -22.604763 -13.851155 16.564901 -22.433630 -14.182674 16.909956 -22.161886 -14.397608 17.272467 -21.808050 -14.481310 17.627731 -21.396233 -14.428074 17.951538 -20.954502 -14.241530 18.221821 -20.512959 -13.934390 18.420158 -20.101692 -13.527585 18.533039 -19.748734 -13.048839 18.552763 -19.478134 -12.530776 18.477991 -19.308336 -12.008701 18.313820 -19.250908 -11.518195 18.071434 -19.309765 -11.092684 17.767353 -19.480896 -10.761165 17.422298 -19.752642 -13.865498 16.663549 -17.130442 -13.194565 16.578938 -16.980505 -12.533170 16.373739 -16.964975 -11.926385 16.061941 -17.084911 -11.415561 15.664789 -17.332138 -11.035512 15.209351 -17.689810 -10.812136 14.726662 -18.133549 -10.760655 14.249617 -18.633118 -10.884580 13.810725 -19.154470 -11.175462 13.439898 -19.662079 -11.613481 13.162407 -20.121347 -12.168785 12.997161 -20.500980 -12.803533 12.955421 -20.775106 -13.474465 13.040033 -20.925043 -14.135860 13.245231 -20.940573 -14.742645 13.557029 -20.820639 -15.253469 13.954181 -20.573410 -15.633519 14.409619 -20.215738 -15.856895 14.892308 -19.771999 -15.908376 15.369353 -19.272432 -15.784452 15.808245 -18.751078 -15.493569 16.179071 -18.243469 -15.055551 16.456564 -17.784201 -14.500247 16.621809 -17.404568 -17.409189 12.696468 -17.588112 -17.417339 13.358648 -16.957514 -17.192636 13.969545 -16.315239 -16.750397 14.487529 -15.705059 -16.120758 14.877297 -15.168554 -15.346627 15.112289 -14.742289 -14.480762 15.176491 -14.455309 -13.582169 15.065526 -14.327174 -12.712085 14.786959 -14.366617 -11.929806 14.359770 -14.570949 -11.288642 13.813074 -14.926242 -10.832287 13.184127 -15.408289 -10.591843 12.515790 -15.984235 -10.583694 11.853611 -16.614830 -10.808394 11.242713 -17.257105 -11.250633 10.724730 -17.867285 -11.880273 10.334961 -18.403791 -12.654403 10.099968 -18.830057 -13.520268 10.035767 -19.117037 -14.418861 10.146731 -19.245171 -15.288946 10.425299 -19.205729 -16.071226 10.852486 -19.001398 -16.712389 11.399183 -18.646103 -17.168745 12.028130 -18.164057 -14.111758 7.054919 -17.441975 -15.292324 7.204877 -17.537622 -16.419579 7.582264 -17.426947 -17.416698 8.161365 -17.117489 -18.215734 8.902711 -16.630337 -18.762234 9.755784 -15.998692 -19.018951 10.662448 -15.265596 -18.968393 11.560914 -14.481011 -18.614006 12.389955 -13.698404 -17.979939 13.093070 -12.971109 -17.109404 13.622346 -12.348690 -16.061726 13.941711 -11.873564 -14.908301 14.029405 -11.578107 -13.727736 13.879448 -11.482458 -12.600482 13.502061 -11.593134 -11.603361 12.922961 -11.902591 -10.804323 12.181614 -12.389742 -10.257825 11.328541 -13.021388 -10.001107 10.421877 -13.754482 -10.051663 9.523411 -14.539068 -10.406051 8.694370 -15.321675 -11.040117 7.991255 -16.048969 -11.910652 7.461979 -16.671389 -12.958331 7.142612 -17.146517 -9.176333 8.440373 -11.491337 -9.295950 7.275123 -12.434141 -9.797131 6.200136 -13.358377 -10.645720 5.288669 -14.201063 -11.783888 4.602839 -14.904770 -13.134071 4.189382 -15.421541 -14.604257 4.076477 -15.716160 -16.094254 4.271818 -15.768549 -17.502522 4.762090 -15.575137 -18.733088 5.513884 -15.149105 -19.702093 6.475966 -14.519487 -20.343502 7.582772 -13.729191 -20.613602 8.758874 -12.832072 -20.493986 9.924125 -11.889269 -19.992807 10.999111 -10.965033 -19.144218 11.910579 -10.122347 -18.006050 12.596410 -9.418639 -16.655867 13.009867 -8.901867 -15.185681 13.122772 -8.607248 -13.695685 12.927432 -8.554860 -12.287417 12.437160 -8.748271 -11.056849 11.685368 -9.174302 -10.087844 10.723285 -9.803920 -9.446434 9.616479 -10.594216 -15.358377 12.336329 -5.630280 -13.560745 12.097481 -5.628256 -11.873472 11.494801 -5.908285 -10.411542 10.569358 -6.451286 -9.274583 9.384221 -7.220252 -8.540078 8.020156 -8.162780 -8.258080 6.570121 -9.214639 -8.447810 5.132933 -10.304146 -9.096335 3.806534 -11.357053 -10.159461 2.681316 -12.301606 -11.564737 1.833962 -13.073436 -13.216396 1.322216 -13.619942 -15.001880 1.180954 -13.903883 -16.799511 1.419800 -13.905909 -18.486786 2.022481 -13.625880 -19.948715 2.947922 -13.082880 -21.085676 4.133060 -12.313914 -21.820181 5.497124 -11.371387 -22.102179 6.947160 -10.319527 -21.912451 8.384348 -9.230021 -21.263926 9.710747 -8.177113 -20.200800 10.835964 -7.232560 -18.795525 11.683319 -6.460731 -17.143867 12.195066 -5.914223 -23.388180 5.188914 -7.761646 -23.137827 6.875523 -6.548048 -22.359081 8.434227 -5.388677 -21.105013 9.758803 -4.362539 -19.461084 10.758984 -3.539567 -17.539326 11.366606 -2.975844 -15.470702 11.540265 -2.709786 -13.396189 11.268124 -2.759525 -11.457157 10.568729 -3.121671 -9.785750 9.489743 -3.771545 -8.495873 8.104698 -4.664859 -7.675427 6.507982 -5.740734 -7.380324 4.808407 -6.925852 -7.630675 3.121798 -8.139450 -8.409419 1.563094 -9.298821 -9.663487 0.238518 -10.324959 -11.307417 -0.761663 -11.147932 -13.229175 -1.369287 -11.711655 -15.297797 -1.542947 -11.977715 -17.372313 -1.270806 -11.927975 -19.311344 -0.571413 -11.565829 -20.982750 0.507573 -10.915956 -22.272629 1.892617 -10.022642 -23.093075 3.489334 -8.946768 -15.492864 -4.015797 -9.914247 -17.787191 -3.726165 -9.815310 -19.927078 -2.957773 -9.381636 -21.766695 -1.762987 -8.642776 -23.180674 -0.223228 -7.649086 -24.072653 1.556571 -6.468281 -24.381849 3.455119 -5.180833 -24.087191 5.343035 -3.874479 -23.208755 7.091660 -2.638244 -21.806410 8.581827 -1.556376 -19.975719 9.711986 -0.702602 -17.841444 10.405115 -0.135106 -15.549031 10.613982 0.107439 -13.254704 10.324351 0.008502 -11.114817 9.555961 -0.425171 -9.275200 8.361176 -1.164029 -7.861220 6.821416 -2.157720 -6.969239 5.041617 -3.338524 -6.660041 3.143069 -4.625972 -6.954699 1.255153 -5.932327 -7.833134 -0.493472 -7.168562 -9.235479 -1.983640 -8.250430 -11.066169 -3.113798 -9.104204 -13.200443 -3.806929 -9.671701 -6.188776 1.551826 -2.316568 -6.508505 -0.467804 -3.678886 -7.447766 -2.343818 -4.957713 -8.942550 -3.948371 -6.065900 -10.890986 -5.172113 -6.927924 -13.160295 -5.931650 -7.485041 -15.595826 -6.175220 -7.699284 -18.031603 -5.886226 -7.556053 -20.301630 -5.084359 -7.065109 -22.251209 -3.824267 -6.259908 -23.747480 -2.191824 -5.195324 -24.688475 -0.298277 -3.943907 -25.010065 1.727333 -2.590938 -24.690336 3.746962 -1.228620 -23.751076 5.622976 0.050207 -22.256296 7.227529 1.158394 -20.307858 8.451273 2.020419 -18.038549 9.210811 2.577537 -15.603018 9.454382 2.791780 -13.167242 9.165388 2.648549 -10.897215 8.363523 2.157606 -8.947635 7.103431 1.352405 -7.451363 5.470988 0.287822 -6.510367 3.577441 -0.963595 -15.624843 7.988164 5.324395 -13.140185 7.716090 5.142724 -10.824863 6.918178 4.610583 -8.836663 5.648803 3.764236 -7.311078 3.994474 2.661361 -6.352072 2.067930 1.377117 -6.025001 0.000460 -0.000977 -6.352152 -2.067039 -1.379007 -7.311234 -3.993672 -2.663062 -8.836885 -5.648142 -3.765636 -10.825134 -6.917699 -4.611590 -13.140487 -7.715826 -5.143274 -15.625154 -7.988130 -5.324454 -18.109812 -7.716057 -5.142784 -20.425133 -6.918144 -4.610643 -22.413334 -5.648772 -3.764298 -23.938921 -3.994442 -2.661422 -24.897926 -2.067898 -1.377178 -25.225000 -0.000429 0.000916 -24.897848 2.067071 1.378946 -23.938768 3.993704 2.663001 -22.413116 5.648174 3.765575 -20.424870 6.917732 4.611529 -18.109518 7.715859 5.143214 -25.010035 -1.728200 2.593021 -24.688328 0.297332 3.946082 -23.747227 2.190869 5.197440 -22.250866 3.823370 6.261817 -20.301220 5.083580 7.066677 -18.031157 5.885623 7.557170 -15.595372 6.174837 7.699870 -13.159865 5.931514 7.485053 -10.890610 5.172236 6.927358 -8.942252 3.948746 6.064789 -7.447569 2.344424 4.956132 -6.508420 0.468601 3.676938 -6.188810 -1.550889 2.314383 -6.510516 -3.576420 0.961321 -7.451615 -5.469957 -0.290037 -8.947975 -7.102458 -1.354414 -10.897621 -8.362671 -2.159274 -13.167686 -9.164714 -2.649769 -15.603469 -9.453929 -2.792469 -18.038977 -9.210607 -2.577652 -20.308231 -8.451330 -2.019957 -22.256590 -7.227840 -1.157390 -23.751274 -5.623519 -0.048733 -24.690424 -3.747696 1.230461 -15.549841 -10.613199 -0.108597 -17.842211 -10.404507 0.134549 -19.976391 -9.711589 0.702682 -21.806938 -8.581668 1.557085 -23.209108 -7.091745 2.639531 -24.087341 -5.343359 3.876252 -24.381788 -3.455656 5.182969 -24.072386 -1.557281 6.470631 -23.180216 0.222394 7.651486 -21.766079 1.762089 8.645061 -19.926348 2.956874 9.383644 -17.786396 3.725329 9.816906 -15.492059 4.015084 9.915316 -13.199690 3.806392 9.672171 -11.065510 3.113475 9.104038 -9.234961 1.983555 8.249636 -7.832791 0.493633 7.167190 -6.954557 -1.254754 5.930469 -6.660108 -3.142457 4.623752 -6.969511 -5.040832 3.336090 -7.861680 -6.820508 2.155235 -9.275815 -8.360203 1.161659 -11.115545 -9.554989 0.423074 -13.255497 -10.323443 -0.010186 -7.380451 -4.808040 6.923194 -7.675899 -6.507349 5.737770 -8.496657 -8.103840 4.661788 -9.786795 -9.488716 3.768573 -11.458390 -10.567600 3.118997 -13.397526 -11.266968 2.757328 -15.472054 -11.539158 2.708211 -17.540600 -11.365621 2.974997 -19.462193 -10.758183 3.539501 -21.105883 -9.758243 4.363255 -22.359652 -8.433942 5.390121 -23.138060 -6.875529 6.550120 -23.388060 -5.189208 7.764201 -23.092613 -3.489900 8.949625 -22.271856 -1.893409 10.025608 -20.981720 -0.508533 10.918822 -19.310123 0.570353 11.568399 -17.370989 1.269721 11.930069 -15.296460 1.541912 11.979185 -13.227915 1.368375 11.712401 -11.306321 0.760940 11.147898 -9.662631 -0.239002 10.324143 -8.408861 -1.563302 9.297277 -7.630452 -3.121715 8.137278 -15.000001 -1.182187 13.905500 -13.214636 -1.323394 13.620745 -11.563215 -1.835001 13.073365 -10.158282 -2.682144 12.300663 -9.095579 -3.807091 11.355299 -8.447530 -5.133178 10.301697 -8.258296 -6.570035 9.211657 -8.540773 -8.019743 8.159465 -9.275712 -9.383505 7.216824 -10.413027 -10.568386 6.447977 -11.875213 -11.493636 5.905317 -13.562623 -12.096201 5.625825 -15.360264 -12.335018 5.628549 -17.145630 -12.193811 5.913305 -18.797049 -11.682205 6.460684 -20.201982 -10.835064 7.233384 -21.264687 -9.710116 8.178749 -21.912737 -8.384029 9.232352 -22.101973 -6.947173 10.322392 -21.819496 -5.497465 11.374585 -21.084557 -4.133702 12.317225 -19.947243 -2.948821 13.086073 -18.485058 -2.023570 13.628734 -16.797647 -1.421004 13.908224 -20.613312 -8.758361 12.834889 -20.342598 -7.582646 13.732345 -19.700638 -6.476235 14.522759 -18.731180 -5.514527 15.152269 -17.500292 -4.763061 15.577974 -16.091854 -4.273046 15.770861 -14.601853 -4.077879 15.717787 -13.131827 -4.190857 15.422369 -11.781957 -4.604284 14.904739 -10.644233 -5.289983 14.200171 -9.796190 -6.201227 13.356683 -9.295622 -7.275913 12.431755 -9.176640 -8.440806 11.488420 -9.447352 -9.616521 10.590965 -10.089312 -10.722932 9.800550 -11.058768 -11.684640 9.171041 -12.289658 -12.436108 8.745336 -13.698094 -12.926123 8.552448 -15.188096 -13.121290 8.605522 -16.658123 -13.008311 8.900940 -18.007994 -12.594886 9.418570 -19.145716 -11.909187 10.123136 -19.993759 -10.997944 10.966625 -20.494329 -9.923258 11.891552 -14.911029 -14.027861 11.576609 -16.064219 -13.940174 11.873009 -17.111492 -13.620915 12.349114 -17.981482 -13.091842 12.972481 -18.614897 -12.389009 13.700627 -18.968575 -11.560313 14.483929 -19.018410 -10.662229 15.269008 -18.761007 -9.755960 16.002361 -18.213907 -8.903267 16.634010 -17.414394 -8.162259 17.120914 -16.416956 -7.583434 17.429886 -15.289565 -7.206239 17.539871 -14.109050 -7.056379 17.443378 -12.955861 -7.144066 17.146978 -11.908587 -7.463324 16.670872 -11.038597 -7.992397 16.047504 -10.405180 -8.695230 15.319360 -10.051503 -9.523925 14.536057 -10.001668 -10.422009 13.750978 -10.259069 -11.328278 13.017626 -10.806169 -12.180972 12.385975 -11.605680 -12.921980 11.899073 -12.603118 -13.500805 11.590099 -13.730510 -13.878000 11.480112 -10.592550 -12.515790 15.981140 -10.833612 -13.183786 15.405048 -11.290495 -13.812414 14.923076 -11.932062 -14.358831 14.568065 -12.714591 -14.785802 14.364213 -13.584755 -15.064228 14.325410 -14.483253 -15.175138 14.454300 -15.348853 -15.110970 14.742102 -16.122568 -14.876097 15.169198 -16.751669 -14.486527 15.706486 -17.193285 -13.968808 16.317348 -17.417320 -13.358222 16.960159 -17.408506 -12.696380 17.591110 -17.167444 -12.028382 18.167200 -16.710562 -11.399755 18.649174 -16.068996 -10.853337 19.004185 -15.286467 -10.426367 19.208036 -14.416304 -10.147940 19.246840 -13.517806 -10.037030 19.117950 -12.652205 -10.101198 18.830151 -11.878489 -10.336071 18.403053 -11.249388 -10.725639 17.865765 -10.807772 -11.243359 17.254902 -10.583737 -11.853945 16.612093 -12.801490 -12.956451 20.775579 -12.167031 -12.998080 20.500759 -11.612135 -13.163149 20.120445 -11.174618 -13.440411 19.660553 -10.884295 -13.810968 19.152422 -10.760952 -14.249571 18.630684 -10.812994 -14.726326 18.130892 -11.036875 -15.208746 17.687107 -11.417336 -15.663954 17.329573 -11.928452 -16.060926 17.082651 -12.535389 -16.372614 16.963175 -13.196787 -16.577772 16.979282 -13.867571 -16.662422 17.129877 -14.502029 -16.620794 17.404697 -15.056926 -16.455725 17.785011 -15.494443 -16.178463 18.244904 -15.784766 -15.807906 18.753033 -15.908110 -15.369304 19.274771 -15.856068 -14.892549 19.774565 -15.632188 -14.410129 20.218349 -15.251726 -13.954921 20.575884 -14.740611 -13.557947 20.822803 -14.133674 -13.246260 20.942282 -13.472277 -13.041101 20.926174 -14.396430 -17.273045 21.810659 -14.180988 -16.910807 22.164473 -13.849078 -16.565966 22.436014 -13.423318 -16.262022 22.606777 -12.932723 -16.019688 22.665127 -12.410727 -15.855478 22.607084 -11.892901 -15.780581 22.436609 -11.414537 -15.800106 22.165314 -11.008233 -15.912718 21.811691 -10.701678 -16.110744 21.399836 -10.515763 -16.380690 20.957821 -10.463160 -16.704157 20.515762 -10.547450 -17.059105 20.103788 -10.762891 -17.421341 19.749975 -11.094802 -17.766184 19.478436 -11.520561 -18.070126 19.307673 -12.011157 -18.312462 19.249321 -12.533154 -18.476671 19.307364 -13.050978 -18.551567 19.477839 -13.529343 -18.532043 19.749132 -13.935646 -18.419432 20.102757 -14.242202 -18.221405 20.514608 -14.428116 -17.951460 20.956627 -14.480721 -17.627993 21.398685 -12.043497 -20.857548 21.369625 -12.445304 -20.864267 21.669172 -12.773398 -20.790440 22.040827 -13.005422 -20.641096 22.459257 -13.125562 -20.426416 22.895950 -13.125631 -20.161030 23.321146 -13.005626 -19.863018 23.705866 -12.773724 -19.552696 24.023897 -12.445728 -19.251207 24.253561 -12.043992 -18.979101 24.379208 -11.595892 -18.754917 24.392279 -11.131967 -18.593937 24.291878 -10.683830 -18.507130 24.084850 -10.282024 -18.500410 23.785303 -9.953930 -18.574238 23.413649 -9.721907 -18.723579 22.995220 -9.601766 -18.938259 22.558527 -9.601696 -19.203648 22.133329 -9.721702 -19.501659 21.748610 -9.953604 -19.811981 21.430578 -10.281599 -20.113468 21.200914 -10.683335 -20.385576 21.075266 -11.131434 -20.609760 21.062197 -11.595360 -20.770741 21.162598 -8.326597 -21.991142 22.872526 -8.618114 -22.312197 22.533777 -9.000511 -22.635944 22.306246 -9.447728 -22.940321 22.205439 -9.929289 -23.204580 22.238228 -10.412374 -23.410719 22.402374 -10.864065 -23.544687 22.686695 -11.253578 -23.597353 23.071812 -11.554368 -23.565128 23.531483 -11.745938 -23.450212 24.034378 -11.815231 -23.260431 24.546228 -11.757527 -23.008722 25.032154 -11.576757 -22.712238 25.459034 -11.285241 -22.391184 25.797783 -10.902844 -22.067438 26.025314 -10.455627 -21.763062 26.126123 -9.974067 -21.498800 26.093334 -9.490980 -21.292662 25.929188 -9.039290 -21.158693 25.644867 -8.649777 -21.106028 25.259750 -8.348987 -21.138252 24.800081 -8.157417 -21.253168 24.297184 -8.088123 -21.442949 23.785334 -8.145827 -21.694656 23.299410 -6.830502 -23.760244 26.969347 -6.426513 -23.610897 26.426876 -6.141397 -23.566238 25.797194 -5.994586 -23.629309 25.123211 -5.996084 -23.795815 24.450855 -6.145788 -24.054405 23.825953 -6.433497 -24.387461 23.291084 -6.839603 -24.772282 22.882704 -7.336432 -25.182644 22.628641 -7.890125 -25.590584 22.546206 -8.462949 -25.968300 22.641020 -9.015866 -26.290049 22.906624 -9.511197 -26.533907 23.324911 -9.915187 -26.683254 23.867382 -10.200301 -26.727913 24.497063 -10.347113 -26.664843 25.171047 -10.345615 -26.498335 25.843401 -10.195911 -26.239746 26.468306 -9.908203 -25.906691 27.003172 -9.502097 -25.521870 27.411554 -9.005268 -25.111507 27.665619 -8.451575 -24.703568 27.748053 -7.878752 -24.325853 27.653238 -7.325834 -24.004103 27.387634 -7.723022 -29.528435 28.130398 -7.148769 -29.036423 28.644548 -6.493093 -28.474520 28.945459 -5.800677 -27.881021 29.012625 -5.118708 -27.296373 28.841469 -4.493660 -26.760414 28.443653 -3.968131 -26.309675 27.846289 -3.577933 -25.974867 27.090088 -3.349658 -25.778812 26.226580 -3.298863 -25.734867 25.314615 -3.429009 -25.846029 24.416342 -3.731227 -26.104719 23.592974 -4.184921 -26.493313 22.900625 -4.759173 -26.985325 22.386475 -5.414849 -27.547224 22.085564 -6.107265 -28.140724 22.018396 -6.789235 -28.725374 22.189552 -7.414282 -29.261330 22.587368 -7.939812 -29.712072 23.184731 -8.330010 -30.046879 23.940933 -8.558285 -30.242935 24.804440 -8.609080 -30.286880 25.716404 -8.478935 -30.175720 26.614677 -8.176718 -29.917028 27.438047 -6.062319 -32.932190 22.158218 -6.355375 -33.560017 23.130486 -6.436249 -34.002708 24.236307 -6.299430 -34.230083 25.400324 -5.954241 -34.226658 26.543211 -5.424207 -33.992657 27.587082 -4.745449 -33.544033 28.460794 -3.964222 -32.911354 29.104813 -3.133767 -32.137741 29.475246 -2.310677 -31.275909 29.546848 -1.551044 -30.384598 29.314741 -0.906636 -29.524542 28.794743 -0.421369 -28.754356 28.022289 -0.128313 -28.126524 27.050024 -0.047438 -27.683836 25.944201 -0.184257 -27.456457 24.780186 -0.529446 -27.459885 23.637297 -1.059479 -27.693886 22.593428 -1.738238 -28.142509 21.719715 -2.519464 -28.775188 21.075697 -3.349920 -29.548801 20.705263 -4.173009 -30.410629 20.633659 -4.932642 -31.301945 20.865765 -5.577050 -32.161999 21.385763 0.825707 -29.287771 19.832779 -0.178779 -30.081511 19.044138 -1.171089 -31.107666 18.571590 -2.083597 -32.296307 18.447342 -2.854118 -33.566425 18.679861 -3.430141 -34.831470 19.253300 -3.772413 -36.005230 20.128580 -3.857608 -37.007713 21.246054 -3.679920 -37.770599 22.529564 -3.251458 -38.241901 23.891645 -2.601421 -38.389507 25.239471 -1.774108 -38.203350 26.481192 -0.825899 -37.696114 27.532187 0.178587 -36.902374 28.320827 1.170896 -35.876221 28.793377 2.083404 -34.687580 28.917625 2.853926 -33.417461 28.685108 3.429950 -32.152416 28.111668 3.772222 -30.978659 27.236389 3.857417 -29.976179 26.118916 3.679730 -29.213289 24.835407 3.251268 -28.741985 23.473326 2.601232 -28.594379 22.125498 1.773919 -28.780539 20.883778 8.498251 -32.805225 25.265320 8.281344 -31.411953 24.125032 7.756129 -30.314230 22.780539 6.958396 -29.586868 21.323458 5.942511 -29.279436 19.853094 4.777702 -29.412882 18.469650 3.543352 -29.978111 17.267401 2.323579 -30.936604 16.328278 1.201507 -32.223045 15.716286 0.253605 -33.749760 15.473127 -0.455530 -35.412712 15.615372 -0.877572 -37.098564 16.133327 -0.983758 -38.692440 16.991697 -0.766853 -40.085709 18.131985 -0.241638 -41.183434 19.476480 0.556094 -41.910793 20.933558 1.571980 -42.218231 22.403921 2.736788 -42.084782 23.787369 3.971138 -41.519554 24.989616 5.190912 -40.561062 25.928740 6.312984 -39.274624 26.540731 7.260887 -37.747906 26.783894 7.970022 -36.084957 26.641647 8.392064 -34.399101 26.123692 9.399990 -44.486835 20.716354 10.805273 -43.378040 21.800732 12.015397 -41.859299 22.581205 12.947893 -40.034107 23.004595 13.539214 -38.026855 23.042040 13.749063 -35.974335 22.690992 13.563138 -34.016415 21.975372 12.994111 -32.286533 20.943954 12.080759 -30.902565 19.667021 10.885325 -29.958841 18.231598 9.489279 -29.519665 16.735504 7.987754 -29.614969 15.280696 6.483081 -30.238258 13.966317 5.077798 -31.347054 12.881941 3.867675 -32.865799 12.101465 2.935177 -34.690987 11.678077 2.343855 -36.698238 11.640631 2.134006 -38.750759 11.991679 2.319930 -40.708679 12.707296 2.888957 -42.438568 13.738716 3.802308 -43.822529 15.015648 4.997741 -44.766254 16.451073 6.393788 -45.205433 17.947166 7.895312 -45.110126 19.401974 6.050486 -41.756687 7.360429 6.973110 -43.718018 8.172554 8.263592 -45.294743 9.270818 9.833986 -46.379417 10.580374 11.577273 -46.898125 12.011977 13.374651 -46.815506 13.468067 15.103633 -46.137207 14.849415 16.646389 -44.909435 16.061882 17.897785 -43.215870 17.022842 18.772539 -41.171925 17.666807 19.211040 -38.916897 17.949892 19.183405 -36.604446 17.852804 18.691513 -34.392178 17.382160 17.768890 -32.430851 16.570036 16.478411 -30.854122 15.471773 14.908017 -29.769445 14.162217 13.164728 -29.250740 12.730613 11.367350 -29.333357 11.274523 9.638369 -30.011660 9.893175 8.095612 -31.239428 8.680707 6.844215 -32.932991 7.719747 5.969459 -34.976933 7.075783 5.530958 -37.231968 6.792696 5.558594 -39.544415 6.889784 12.888202 -29.205589 5.148607 11.269417 -30.506554 3.835573 10.025837 -32.296230 2.700851 9.242209 -34.452656 1.821771 8.971936 -36.828876 1.258242 9.233437 -39.262951 1.048665 10.008889 -41.589005 1.207323 11.245450 -43.648521 1.723405 12.858848 -45.301144 2.561739 14.739132 -46.434258 3.665196 16.758165 -46.970638 4.958576 18.778353 -46.873722 6.353737 20.662024 -46.150131 7.755603 22.280807 -44.849171 9.068637 23.524389 -43.059494 10.203359 24.308018 -40.903069 11.082439 24.578293 -38.526848 11.645969 24.316792 -36.092773 11.855547 23.541340 -33.766720 11.696890 22.304779 -31.707203 11.180808 20.691383 -30.054575 10.342474 18.811098 -28.921465 9.239017 16.792067 -28.385086 7.945638 14.771878 -28.481995 6.550477 27.750853 -32.089989 5.324734 26.271530 -30.075054 5.145291 24.421595 -28.469650 4.615219 22.327116 -27.383186 3.770643 20.130831 -26.889698 2.669120 17.982412 -27.022820 1.385716 16.028271 -27.773476 0.007893 14.401578 -29.090509 -1.370453 13.213190 -30.884171 -2.655389 12.544093 -33.032227 -3.759350 12.439886 -35.388283 -4.607102 12.907670 -37.791782 -5.140872 13.915566 -40.078930 -5.324285 15.394887 -42.093864 -5.144843 17.244822 -43.699268 -4.614771 19.339300 -44.785736 -3.770197 21.535585 -45.279221 -2.668673 23.684004 -45.146103 -1.385269 25.638145 -44.395451 -0.007446 27.264839 -43.078415 1.370899 28.453228 -41.284752 2.655836 29.122326 -39.136703 3.759797 29.226534 -36.780647 4.607549 28.758751 -34.377144 5.141320 29.644320 -40.960556 -7.770659 31.212206 -39.691330 -6.367849 32.305099 -37.991104 -4.970755 32.848522 -35.975739 -3.674583 32.805439 -33.782585 -2.567667 32.178787 -31.561092 -1.725442 31.011274 -29.462656 -1.205303 29.382462 -27.630283 -1.042696 27.403351 -26.188848 -1.248704 25.208815 -25.236576 -1.809287 22.948408 -24.838369 -2.686242 20.776173 -25.021360 -3.819807 18.840145 -25.773081 -5.132730 17.272259 -27.042301 -6.535539 16.179365 -28.742527 -7.932633 15.635942 -30.757891 -9.228806 15.679024 -32.951050 -10.335722 16.305674 -35.172539 -11.177948 17.473186 -37.270977 -11.698088 19.101999 -39.103348 -11.860695 21.081110 -40.544785 -11.654687 23.275644 -41.497055 -11.094105 25.536051 -41.895267 -10.217150 27.708286 -41.712276 -9.083586 20.439568 -33.383503 -17.383236 22.111095 -34.912769 -17.857563 24.101334 -36.090275 -17.957989 26.274649 -36.835777 -17.677666 28.482935 -37.098465 -17.035698 30.575699 -36.860439 -16.075836 32.410324 -36.137928 -14.863495 33.861782 -34.980160 -13.481289 34.831158 -33.466038 -12.023417 35.252396 -31.698748 -10.589228 35.096783 -29.798727 -9.276460 34.374928 -27.895462 -8.174577 33.136021 -26.118650 -7.358669 31.464493 -24.589382 -6.884340 29.474255 -23.411879 -6.783916 27.300940 -22.666378 -7.064238 25.092653 -22.403688 -7.706203 22.999887 -22.641710 -8.666064 21.165264 -23.364225 -9.878407 19.713804 -24.521990 -11.260612 18.744427 -26.036112 -12.718485 18.323189 -27.803400 -14.152674 18.478802 -29.703421 -15.465442 19.200657 -31.606688 -16.567326 22.941616 -20.746735 -13.953837 21.649759 -21.737879 -15.268728 20.816973 -22.989431 -16.724844 20.500006 -24.416107 -18.222948 20.720463 -25.920679 -19.660955 21.463320 -27.400610 -20.940861 22.677950 -28.755049 -21.975445 24.281578 -29.891689 -22.694199 26.164923 -30.733074 -23.048147 28.199635 -31.221863 -23.013163 30.247051 -31.324747 -22.591633 32.167648 -31.034714 -21.812283 33.830536 -30.371531 -20.728224 35.122391 -29.380388 -19.413334 35.955177 -28.128834 -17.957220 36.272144 -26.702158 -16.459114 36.051689 -25.197586 -15.021107 35.308834 -23.717655 -13.741202 34.094204 -22.363216 -12.706617 32.490578 -21.226576 -11.987862 30.607233 -20.385189 -11.633915 28.572521 -19.896400 -11.668898 26.525103 -19.793514 -12.090427 24.604507 -20.083548 -12.869776 33.999683 -18.496752 -16.988983 32.565826 -17.795919 -16.127901 30.894466 -17.322203 -15.607584 29.099504 -17.107882 -15.463496 27.303267 -17.167564 -15.705454 25.628160 -17.497185 -16.316967 24.188343 -18.074278 -17.256367 23.081934 -18.859516 -18.459627 22.384336 -19.799389 -19.844757 22.143087 -20.829840 -21.317352 22.374628 -21.880651 -22.777065 23.063181 -22.880211 -24.124416 24.161821 -23.760399 -25.267588 25.595678 -24.461233 -26.128674 27.267036 -24.934952 -26.648987 29.061998 -25.149271 -26.793077 30.858238 -25.089588 -26.551121 32.533344 -24.759970 -25.939606 33.973164 -24.182877 -25.000208 35.079571 -23.397638 -23.796947 35.777168 -22.457767 -22.411819 36.018417 -21.427313 -20.939220 35.786877 -20.376503 -19.479509 35.098328 -19.376944 -18.132158 33.058273 -18.116690 -27.538568 33.971527 -17.550510 -26.486691 34.546314 -16.929520 -25.243700 34.743465 -16.296036 -23.894308 34.549549 -15.693224 -22.530472 33.977779 -15.162171 -21.245132 33.067116 -14.739065 -20.125887 31.879623 -14.452738 -19.249010 30.496227 -14.322707 -18.674259 29.011204 -14.357830 -18.440798 27.525753 -14.555714 -18.564543 26.141108 -14.902874 -19.037058 24.951628 -15.375651 -19.826141 24.038376 -15.941827 -20.878021 23.463587 -16.562819 -22.121008 23.266432 -17.196304 -23.470402 23.460348 -17.799114 -24.834238 24.032120 -18.330168 -26.119577 24.942781 -18.753275 -27.238823 26.130274 -19.039600 -28.115700 27.513670 -19.169634 -28.690454 28.998693 -19.134510 -28.923912 30.484144 -18.936626 -28.800169 31.868790 -18.589466 -28.327656 25.113041 -14.010027 -28.023869 26.022194 -13.971651 -28.796766 27.088758 -13.840777 -29.317070 28.240051 -13.626328 -29.549316 29.397614 -13.342915 -29.477684 30.482557 -13.009854 -29.107050 31.420946 -12.649840 -28.462677 32.148834 -12.287412 -27.588476 32.616611 -11.947265 -26.544020 32.792400 -11.652579 -25.400492 32.664227 -11.423439 -24.235817 32.240822 -11.275459 -23.129366 31.551039 -11.218725 -22.156544 30.641886 -11.257101 -21.383646 29.575321 -11.387974 -20.863344 28.424028 -11.602425 -20.631096 27.266466 -11.885837 -20.702730 26.181522 -12.218898 -21.073360 25.243132 -12.578911 -21.717735 24.515245 -12.941340 -22.591934 24.047468 -13.281487 -23.636389 23.871675 -13.576172 -24.779919 23.999849 -13.805312 -25.944593 24.423256 -13.953292 -27.051044 25.038403 -9.632102 -22.901699 24.474995 -9.829679 -23.594343 24.099691 -9.960450 -24.417913 23.938066 -10.015504 -25.316284 24.001137 -9.991088 -26.228233 24.284601 -9.888866 -27.091610 24.769146 -9.715807 -27.847578 25.421747 -9.483701 -28.444620 26.197931 -9.208367 -28.842051 27.044804 -8.908569 -29.012785 27.904652 -8.604737 -28.945183 28.718878 -8.317578 -28.643856 29.431993 -8.066660 -28.129339 29.995401 -7.869083 -27.436693 30.370707 -7.738311 -26.613123 30.532331 -7.683258 -25.714754 30.469261 -7.707673 -24.802807 30.185797 -7.809894 -23.939430 29.701254 -7.982955 -23.183458 29.048653 -8.215060 -22.586414 28.272467 -8.490394 -22.188986 27.425594 -8.790192 -22.018253 26.565746 -9.094024 -22.085854 25.751520 -9.381183 -22.387178 27.734650 -5.032566 -23.324200 27.276114 -5.340904 -22.906500 26.721313 -5.659920 -22.641495 26.108055 -5.967873 -22.547251 25.478134 -6.243776 -22.630186 24.874475 -6.468827 -22.884647 24.338221 -6.627690 -23.293299 23.905912 -6.709537 -23.828287 23.607014 -6.708791 -24.453156 23.461891 -6.625504 -25.125320 23.480436 -6.465350 -25.798973 23.661386 -6.239244 -26.428207 23.992407 -5.962596 -26.970140 24.450943 -5.654257 -27.387842 25.005745 -5.335242 -27.652845 25.619001 -5.027288 -27.747091 26.248924 -4.751385 -27.664156 26.852581 -4.526334 -27.409695 27.388838 -4.367472 -27.001043 27.821146 -4.285625 -26.466055 28.120045 -4.286370 -25.841187 28.265167 -4.369657 -25.169024 28.246622 -4.529811 -24.495369 28.065672 -4.755916 -23.866137 25.457209 -1.327105 -25.456463 25.804361 -1.319543 -25.029560 26.051247 -1.396355 -24.543800 26.181044 -1.552304 -24.032282 26.184904 -1.776764 -23.529871 26.062565 -2.054438 -23.070797 25.822363 -2.366404 -22.686356 25.480669 -2.691400 -22.402735 25.060770 -3.007279 -22.239271 24.591278 -3.292514 -22.207100 24.104191 -3.527668 -22.308416 23.632700 -3.696715 -22.536314 23.208941 -3.788134 -22.875263 22.861788 -3.795696 -23.302164 22.614902 -3.718884 -23.787926 22.485106 -3.562935 -24.299440 22.481245 -3.338475 -24.801855 22.603584 -3.060801 -25.260927 22.843786 -2.748836 -25.645370 23.185480 -2.423840 -25.928991 23.605379 -2.107960 -26.092455 24.074871 -1.822725 -26.124624 24.561958 -1.587571 -26.023310 25.033447 -1.418524 -25.795414 21.369764 0.001077 -24.085054 21.668959 0.346224 -24.291401 22.040277 0.667770 -24.391159 22.458420 0.943802 -24.377531 22.894890 1.155507 -24.251446 23.319941 1.288460 -24.021494 23.704607 1.333599 -23.703350 24.022675 1.287849 -23.318691 24.252466 1.154327 -22.893734 24.378325 0.942132 -22.457436 24.391670 0.665725 -22.039532 24.291595 0.343943 -21.668503 24.084921 -0.001285 -21.369631 23.785728 -0.346433 -21.163286 23.414408 -0.667979 -21.063526 22.996265 -0.944010 -21.077154 22.559797 -1.155716 -21.203239 22.134747 -1.288669 -21.433191 21.750080 -1.333808 -21.751335 21.432013 -1.288058 -22.135994 21.202219 -1.154536 -22.560951 21.076361 -0.942341 -22.997248 21.063015 -0.665934 -23.415150 21.163088 -0.344153 -23.786182 20.047310 0.603327 -20.106697 19.697815 0.708503 -20.518522 19.444036 0.916538 -20.960251 19.303268 1.213254 -21.401783 19.285105 1.578433 -21.813026 19.390779 1.987185 -22.165958 19.613096 2.411657 -22.436525 19.936901 2.822921 -22.606291 20.340128 3.192950 -22.663681 20.795298 3.496527 -22.604790 21.271391 3.712964 -22.433624 21.735964 3.827511 -22.161858 22.157356 3.832362 -21.808004 22.506849 3.727186 -21.396179 22.760628 3.519151 -20.954449 22.901398 3.222435 -20.512917 22.919561 2.857257 -20.101673 22.813887 2.448504 -19.748741 22.591570 2.024032 -19.478174 22.267765 1.612768 -19.308411 21.864540 1.242739 -19.251019 21.409369 0.939162 -19.309912 20.933275 0.722725 -19.481075 20.468702 0.608178 -19.752842 21.363766 3.676059 -17.130459 20.955032 3.137316 -16.980549 20.446644 2.667123 -16.965050 19.873249 2.297523 -17.085018 19.273920 2.053703 -17.332275 18.689503 1.952279 -17.689976 18.159822 2.000164 -18.133739 17.720978 2.194093 -18.633326 17.402874 2.520850 -19.154686 17.227190 2.958169 -19.662296 17.205898 3.476247 -20.121559 17.340448 4.039776 -20.501179 17.621674 4.610354 -20.775280 18.030407 5.149097 -20.925190 18.538794 5.619290 -20.940689 19.112190 5.988891 -20.820723 19.711517 6.232711 -20.573463 20.295937 6.334135 -20.215763 20.825615 6.286251 -19.771999 21.264460 6.092322 -19.272413 21.582563 5.765564 -18.751053 21.758249 5.328246 -18.243443 21.779541 4.810169 -17.784182 21.644991 4.246639 -17.404564 19.700264 8.728407 -17.588043 20.277758 8.404333 -16.957445 20.694410 7.904255 -16.315178 20.921822 7.262252 -15.705016 20.944500 6.522076 -15.168541 20.760895 5.734168 -14.742310 20.383522 4.952224 -14.455374 19.838099 4.229530 -14.327282 19.161791 3.615338 -14.366769 18.400692 3.151504 -14.571139 17.606668 2.869637 -14.926467 16.833830 2.788946 -15.408537 16.134848 2.914930 -15.984499 15.557352 3.239003 -16.615099 15.140701 3.739081 -17.257364 14.913288 4.381083 -17.867527 14.890610 5.121260 -18.404003 15.074214 5.909168 -18.830233 15.451587 6.691113 -19.117170 15.997011 7.413806 -19.245260 16.673317 8.027998 -19.205776 17.434416 8.491833 -19.001406 18.228439 8.773701 -18.646078 19.001278 8.854392 -18.164007 13.165890 8.693470 -17.442291 13.886059 9.640856 -17.537973 14.776517 10.428371 -17.427315 15.776581 11.002345 -17.117855 16.818098 11.323664 -16.630684 17.830090 11.370429 -15.999001 18.743593 11.139456 -15.265854 19.496353 10.646482 -14.481208 20.037069 9.925105 -13.698532 20.328892 9.024485 -12.971167 20.351938 8.005997 -12.348680 20.104633 6.939050 -11.873493 19.603832 5.896353 -11.577989 18.883665 4.948967 -11.482306 17.993206 4.161452 -11.592965 16.993143 3.587478 -11.902424 15.951626 3.266158 -12.389596 14.939633 3.219392 -13.021277 14.026130 3.450365 -13.754424 13.273371 3.943338 -14.539070 12.732655 4.664715 -15.321745 12.440829 5.565335 -16.049110 12.417784 6.583824 -16.671598 12.665089 7.650771 -17.146786 11.897741 3.726751 -11.491817 10.948483 4.413013 -12.434633 10.268174 5.384580 -13.358857 9.903179 6.575243 -14.201504 9.878372 7.903859 -14.905148 10.195443 9.279885 -15.421837 10.832784 10.609549 -15.716362 11.746960 11.802234 -15.768648 12.875673 12.776662 -15.575134 14.142003 13.466426 -15.149008 15.459651 13.824523 -14.519310 16.738823 13.826545 -13.728951 17.892344 13.472358 -12.831793 18.841604 12.786097 -11.888977 19.521912 11.814530 -10.964753 19.886908 10.623867 -10.122107 19.911715 9.295251 -9.418462 19.594645 7.919224 -8.901772 18.957304 6.589561 -8.607247 18.043129 5.396876 -8.554960 16.914415 4.422448 -8.748473 15.648086 3.732682 -9.174599 14.330438 3.374586 -9.804298 13.051266 3.372562 -10.594657 18.362610 7.131623 -5.630795 17.256811 5.694372 -5.628901 15.891127 4.534665 -5.909024 14.358625 3.731533 -6.452076 12.763745 3.339709 -7.221046 11.215176 3.385895 -8.163532 9.818446 3.866942 -9.215305 8.668744 4.750070 -10.304688 7.844419 5.975093 -11.357441 7.401647 7.458530 -12.301821 7.370602 9.099285 -13.073469 7.753400 10.785544 -13.619801 8.523954 12.402392 -13.903584 9.629752 13.839643 -13.905478 10.995437 14.999351 -13.625355 12.527937 15.802484 -13.082304 14.122818 16.194309 -12.313333 15.671389 16.148125 -11.370847 17.068117 15.667076 -10.319075 18.217821 14.783949 -9.229692 19.042147 13.558926 -8.176939 19.484919 12.075490 -7.232559 19.515965 10.434735 -6.460910 19.133167 8.748476 -5.914578 16.188366 17.659906 -7.761829 17.523726 16.599730 -6.548179 18.484091 15.145932 -5.388754 19.004019 13.397587 -4.362566 19.048077 11.473840 -3.539548 18.613262 9.505793 -2.975788 17.729204 7.627565 -2.709704 16.456154 5.967154 -2.759430 14.880865 4.637713 -3.121577 13.110692 3.729842 -3.771465 11.266269 3.305412 -4.664806 9.473289 3.393345 -5.740720 7.853942 3.987649 -6.925885 6.518584 5.047824 -8.139534 5.558217 6.501622 -9.298960 5.038288 8.249966 -10.325148 4.994229 10.173714 -11.148167 5.429045 12.141760 -11.711927 6.313101 14.019988 -11.978012 7.586151 15.680400 -11.928286 9.161439 17.009842 -11.566139 10.931612 17.917713 -10.916251 12.776035 18.342144 -10.022911 14.569016 18.254213 -8.946998 4.269141 15.425410 -9.914595 5.667158 17.267502 -9.815483 7.402542 18.736443 -9.381628 9.357030 19.732128 -8.642597 11.397425 20.186703 -7.648754 13.384678 20.069189 -6.467827 15.183363 19.387594 -5.180295 16.670900 18.188372 -3.873900 17.745916 16.553240 -2.637672 18.335154 14.593635 -1.555858 18.398455 12.443100 -0.702180 17.931505 10.248190 -0.134816 16.966129 8.158484 0.107570 15.568112 6.316392 0.008459 13.832729 4.847451 -0.425395 11.878242 3.851765 -1.164426 9.837846 3.397188 -2.158269 7.850592 3.514701 -3.339196 6.051908 4.196295 -4.626728 4.564369 5.395518 -5.933123 3.489352 7.030649 -7.169351 2.900114 8.990253 -8.251165 2.836812 11.140787 -9.104844 3.303761 13.335698 -9.672209 4.437686 4.584100 -2.317225 2.848431 5.871147 -3.679135 1.693367 7.622865 -4.957545 1.051209 9.719875 -6.065333 0.965720 12.019274 -6.927007 1.442725 14.364357 -7.483843 2.449717 16.595314 -7.697895 3.918072 18.560106 -7.554574 5.747724 20.124838 -7.063650 7.813984 21.182875 -6.258576 9.976040 21.662115 -5.194219 12.086553 21.529898 -3.943111 14.001694 20.795235 -2.590513 15.590949 19.508188 -1.228604 16.746014 17.756470 0.049806 17.388172 15.659460 1.157595 17.473663 13.360063 2.019269 16.996658 11.014978 2.576106 15.989667 8.784021 2.790158 14.521313 6.819228 2.646838 12.691662 5.254495 2.155914 10.625402 4.196457 1.350842 8.463346 3.717217 0.286484 6.352833 3.849433 -0.964624 14.729445 9.537191 5.325425 13.251380 7.521543 5.143655 11.402670 5.915471 4.611344 9.309301 4.828425 3.764769 7.113933 4.334486 2.661621 4.966177 4.467317 1.377079 3.012398 5.217863 -0.001318 1.385743 6.534975 -1.379635 0.197067 8.328897 -2.663941 -0.472626 10.477373 -3.766714 -0.577696 12.833991 -4.612802 -0.110982 15.238150 -5.144543 0.895709 17.526009 -5.325702 2.373772 19.541658 -5.143933 4.222482 21.147730 -4.611623 6.315850 22.234777 -3.765048 8.511219 22.728718 -2.661901 10.658976 22.595888 -1.377358 12.612755 21.845343 0.001039 14.239410 20.528231 1.379356 15.428087 18.734310 2.663662 16.097780 16.585835 3.766435 16.202852 14.229216 4.612523 15.736139 11.825058 5.144265 11.008952 22.523100 2.593252 12.602128 21.231596 3.946350 13.771269 19.469704 5.197719 14.436699 17.357500 6.262080 14.553072 15.038923 7.066898 14.112454 12.671985 7.557328 13.144876 10.417982 7.699946 11.716275 8.430526 7.485035 9.924007 6.845057 6.927238 7.890215 5.769622 6.064570 5.753496 5.277510 4.955820 3.659465 5.402259 3.676548 1.750825 6.135365 2.313932 0.157648 7.426870 0.960835 -1.011493 9.188759 -0.290534 -1.676925 11.300963 -1.354895 -1.793298 13.619541 -2.159715 -1.352682 15.986482 -2.650145 -0.385104 18.240482 -2.792764 1.043496 20.227940 -2.577852 2.835763 21.813410 -2.020056 4.869556 22.888845 -1.157389 7.006275 23.380957 -0.048639 9.100307 23.256208 1.230633 -1.415829 18.773691 -0.108954 -0.088754 20.654490 0.134251 1.578532 22.156145 0.702455 3.472407 23.176325 1.556937 5.463807 23.645508 2.639464 7.417021 23.531713 3.876264 9.198941 22.842705 5.183052 10.688132 21.625431 6.470771 11.783109 19.962847 7.651668 12.409248 17.968260 8.645264 12.523883 15.777591 9.383846 12.119200 13.540137 9.817086 11.222777 11.408373 9.915456 9.895704 9.527576 9.672253 8.228418 8.025919 9.104048 6.334544 7.005738 8.249567 4.343143 6.536555 7.167040 2.389929 6.650348 5.930240 0.608008 7.339357 4.623452 -0.881183 8.556630 3.335732 -1.976160 10.219212 2.154836 -2.602301 12.213799 1.161240 -2.716937 14.404467 0.422655 -2.312254 16.641922 -0.010584 -0.474039 8.795867 6.922673 -1.797848 9.901520 5.737228 -2.769935 11.410673 4.661256 -3.324056 13.220481 3.768080 -3.422446 15.207607 3.118569 -3.058402 17.236633 2.756988 -2.256732 19.169285 2.707977 -1.072069 20.873852 2.974874 0.414855 22.234177 3.539494 2.102708 23.157551 4.363356 3.876465 23.581047 5.390317 5.615249 23.475809 6.550391 7.200563 22.849005 7.764521 8.524372 21.743355 8.949965 9.496461 20.234201 10.025938 10.050582 18.424393 10.919113 10.148973 16.437265 11.568624 9.784929 14.408239 11.930206 8.983260 12.475590 11.979218 7.798597 10.771021 11.712320 6.311674 9.410697 11.147702 4.623822 8.487322 10.323840 2.850064 8.063825 9.296879 1.111281 8.169062 8.136806 6.476633 13.581222 13.904907 5.461614 12.105663 13.620182 4.192770 10.931320 13.072865 2.756571 10.138221 12.300251 1.250891 9.780415 11.354996 -0.221660 9.882285 10.301517 -1.560729 10.436890 9.211604 -2.675063 11.406434 8.159536 -3.488721 12.724844 7.217009 -3.946253 14.302272 6.448252 -4.016479 16.031221 5.905657 -3.694615 17.793863 5.626201 -3.002594 19.470081 5.628928 -1.987575 20.945639 5.913651 -0.718732 22.119982 6.460968 0.717466 22.913082 7.233580 2.223147 23.270889 8.178836 3.695698 23.169020 9.232317 5.034768 22.614416 10.322228 6.149102 21.644871 11.374297 6.962759 20.326462 12.316825 7.420292 18.749035 13.085581 7.490520 17.020086 13.628177 7.168656 15.257443 13.907633 2.722141 22.230633 12.835022 3.604911 21.408230 13.732478 4.242020 20.298988 14.522878 4.590049 18.978502 15.152358 4.625281 17.536758 15.578018 4.345316 16.072008 15.770852 3.769233 14.684074 15.717718 2.936289 13.467543 15.422237 1.903250 12.505316 14.904547 0.740516 11.862968 14.199924 -0.472677 11.584276 13.356391 -1.653650 11.688229 12.431430 -2.721921 12.167747 11.488077 -3.604692 12.990149 10.590621 -4.241801 14.099388 9.800220 -4.589830 15.419875 9.170741 -4.625064 16.861620 8.745080 -4.345099 18.326370 8.552245 -3.769016 19.714304 8.605379 -2.936073 20.930836 8.900858 -1.903034 21.893063 9.418550 -0.740299 22.535410 10.123172 0.472893 22.814104 10.966705 1.653866 22.710150 11.891665 -4.692580 19.927637 11.576422 -4.039962 20.882423 11.872893 -3.239782 21.629673 12.349072 -2.346569 22.118465 12.972506 -1.421194 22.315491 13.700710 -0.526722 22.207319 14.484059 0.275893 21.801325 15.269169 0.931952 21.125175 16.002535 1.396747 20.224949 16.634178 1.638603 19.161993 17.121056 1.641037 18.008747 17.429989 1.403884 16.843807 17.539919 0.943305 15.746555 17.443359 0.290688 14.791769 17.146889 -0.509492 14.044518 16.670712 -1.402705 13.555725 16.047276 -2.328080 13.358701 15.319072 -3.222553 13.466871 14.535723 -4.025167 13.872865 13.750614 -4.681227 14.549014 13.017248 -5.146022 15.449242 12.385603 -5.387878 16.512196 11.898726 -5.390313 17.665440 11.589794 -5.153160 18.830383 11.479861 -5.542624 15.431126 15.981458 -6.000750 15.973849 15.405434 -6.316860 16.683807 14.923493 -6.469412 17.512619 14.568481 -6.448009 18.403799 14.364594 -6.254111 19.296619 14.325718 -5.900931 20.130230 14.454513 -5.412538 20.847826 14.742192 -4.822215 21.400505 15.169155 -4.170191 21.750597 15.706306 -3.500901 21.874252 16.317039 -2.859957 21.763039 16.959730 -2.291036 21.424534 17.590586 -1.832910 20.881811 18.166611 -1.516800 20.171852 18.648550 -1.364248 19.343042 19.003563 -1.385650 18.451860 19.207453 -1.579548 17.559042 19.246326 -1.932727 16.725431 19.117535 -2.421120 16.007833 18.829853 -3.011443 15.455157 18.402889 -3.663467 15.105062 17.865738 -4.332757 14.981407 17.255007 -4.973702 15.092621 16.612314 -4.820014 17.564363 20.775515 -5.173284 17.035757 20.500595 -5.593660 16.637789 20.120184 -6.052495 16.397581 19.660208 -6.518519 16.331505 19.152012 -6.959974 16.444059 18.630234 -7.346774 16.727579 18.130423 -7.652561 17.162737 17.686647 -7.856495 17.719885 17.329145 -7.944679 18.361048 17.082287 -7.911103 19.042532 16.962887 -7.758056 19.717899 16.979086 -7.495966 20.341122 17.129782 -7.142696 20.869728 17.404701 -6.722319 21.267696 17.785112 -6.263485 21.507904 18.245087 -5.797461 21.573982 18.753283 -5.356006 21.461428 19.275063 -4.969205 21.177910 19.774874 -4.663418 20.742750 20.218649 -4.459484 20.185604 20.576149 -4.371300 19.544443 20.823009 -4.404876 18.862955 20.942410 -4.557923 18.187590 20.926210 -7.760534 21.104124 21.810688 -7.554564 20.736403 22.164488 -7.421895 20.276518 22.436010 -7.371571 19.755814 22.606750 -7.407020 19.209774 22.665075 -7.525826 18.675611 22.607008 -7.719893 18.189726 22.436504 -7.975996 17.785231 22.165186 -8.276681 17.489693 21.811544 -8.601458 17.323250 21.399677 -8.928193 17.297247 20.957653 -9.234620 17.413456 20.515594 -9.499857 17.663958 20.103626 -9.705828 18.031679 19.749826 -9.838496 18.491562 19.478306 -9.888821 19.012266 19.307564 -9.853372 19.558306 19.249239 -9.734566 20.092470 19.307306 -9.540499 20.578356 19.477810 -9.284396 20.982851 19.749125 -8.983711 21.278389 20.102770 -8.658934 21.444832 20.514637 -8.332199 21.470835 20.956661 -8.025771 21.354626 21.398720 -12.041378 20.858768 21.369621 -11.846275 21.210096 21.669165 -11.618271 21.457314 22.040810 -11.372904 21.583570 22.459230 -11.126894 21.580265 22.895910 -10.897008 21.447624 23.321095 -10.698912 21.194683 23.705805 -10.546104 20.838684 24.023821 -10.449001 20.403883 24.253475 -10.414218 19.919912 24.379116 -10.444126 19.419756 24.392179 -10.536687 18.937496 24.291777 -10.685592 18.506001 24.084751 -10.880695 18.154675 23.785208 -11.108699 17.907455 23.413563 -11.354067 17.781199 22.995142 -11.600077 17.784502 22.558462 -11.829963 17.917143 22.133278 -12.028059 18.170084 21.748569 -12.180865 18.526085 21.430552 -12.277969 18.960886 21.200897 -12.312753 19.444857 21.075256 -12.282845 19.945011 21.062193 -12.190285 20.427271 21.162594 -14.881422 18.206755 22.872309 -15.013664 18.619774 22.533588 -15.102805 19.112835 22.306095 -15.142770 19.652332 22.205336 -15.130836 20.201500 22.238173 -15.067817 20.722916 22.402372 -14.958007 21.181044 22.686745 -14.808888 21.544664 23.071907 -14.630624 21.788996 23.531614 -14.435363 21.897390 24.034536 -14.236411 21.862459 24.546400 -14.047327 21.686583 25.032322 -13.880997 21.381746 25.459190 -13.748755 20.968727 25.797915 -13.659615 20.475668 26.025406 -13.619649 19.936171 26.126165 -13.631582 19.387001 26.093328 -13.694601 18.865585 25.929129 -13.804412 18.407457 25.644756 -13.953530 18.043839 25.259594 -14.131794 17.799505 24.799887 -14.327056 17.691111 24.296965 -14.526007 17.726042 23.785101 -14.715091 17.901917 23.299179 -17.161488 17.795561 26.969301 -17.234159 17.371019 26.426842 -17.338064 17.101767 25.797173 -17.466125 17.006151 25.123199 -17.609613 17.090691 24.450857 -17.758751 17.349621 23.825962 -17.903374 17.765301 23.291105 -18.033627 18.309401 22.882729 -18.140633 18.944839 22.628668 -18.217098 19.628313 22.546234 -18.257816 20.313246 22.641045 -18.260008 20.952959 22.906641 -18.223526 21.503857 23.324921 -18.150856 21.928400 23.867380 -18.046949 22.197655 24.497051 -17.918888 22.293268 25.171024 -17.775400 22.208731 25.843367 -17.626263 21.949799 26.468260 -17.481640 21.534119 27.003119 -17.351387 20.990021 27.411495 -17.244381 20.354584 27.665558 -17.167915 19.671108 27.747990 -17.127197 18.986174 27.653179 -17.125006 18.346462 27.387583 -21.710514 21.452742 28.130262 -21.571426 20.709469 28.644449 -21.412550 19.860723 28.945402 -21.244717 18.964344 29.012613 -21.079361 18.081417 28.841501 -20.927752 17.272110 28.443729 -20.800220 16.591579 27.846403 -20.705460 16.086203 27.090233 -20.649925 15.790416 26.226746 -20.637405 15.724380 25.314787 -20.668749 15.892595 24.416510 -20.741823 16.283598 23.593124 -20.851646 16.870741 22.900749 -20.990734 17.614012 22.386562 -21.149609 18.462755 22.085609 -21.317444 19.359137 22.018396 -21.482800 20.242065 22.189507 -21.634409 21.051371 22.587278 -21.761940 21.731903 23.184605 -21.856701 22.237282 23.940775 -21.912235 22.533068 24.804264 -21.924755 22.599100 25.716221 -21.893412 22.430885 26.614500 -21.820337 22.039885 27.437883 -25.488634 21.716450 22.158482 -25.885962 22.284065 23.130743 -26.229053 22.575346 24.236542 -26.494526 22.570442 25.400520 -26.664288 22.269688 26.543358 -26.726768 21.693579 27.587168 -26.677715 20.881376 28.460817 -26.520466 19.888430 29.104773 -26.265739 18.782408 29.475145 -25.930893 17.638683 29.546696 -25.538748 16.535200 29.314548 -25.116028 15.547158 28.794525 -24.691538 14.741890 28.022060 -24.294210 14.174273 27.049801 -23.951120 13.882993 25.944002 -23.685648 13.887897 24.780024 -23.515884 14.188652 23.637186 -23.453403 14.764760 22.593374 -23.502457 15.576962 21.719725 -23.659706 16.569910 21.075771 -23.914433 17.675930 20.705399 -24.249277 18.819654 20.633846 -24.641424 19.923138 20.865993 -25.064144 20.911182 21.386019 -25.776077 13.929348 19.833019 -25.961096 15.196231 19.044512 -26.353539 16.568731 18.572079 -26.926661 17.953318 18.447910 -27.641403 19.255632 18.680473 -28.449059 20.386925 19.253914 -29.294588 21.270098 20.129158 -30.120367 21.844967 21.246555 -30.870121 22.072353 22.529961 -31.492758 21.936762 23.891911 -31.945843 21.447435 25.239590 -32.198502 20.637718 26.481155 -32.233513 19.562792 27.531996 -32.048492 18.295910 28.320503 -31.656052 16.923409 28.792940 -31.082932 15.538824 28.917107 -30.368187 14.236507 28.684546 -29.560532 13.105216 28.111105 -28.715004 12.222042 27.235859 -27.889225 11.647173 26.118464 -27.139469 11.419785 24.835058 -26.516834 11.555374 23.473110 -26.063747 12.044701 22.125431 -25.811089 12.854418 20.883865 -32.658993 9.043101 25.265549 -31.344107 8.534195 24.125113 -30.131029 8.440065 22.780462 -29.102427 8.767125 21.323233 -28.328398 9.493086 19.852736 -27.861691 10.568476 18.469179 -27.734112 11.920007 17.266853 -27.954353 13.455576 16.327692 -28.507408 15.070536 15.715697 -29.355587 16.654831 15.472579 -30.441086 18.100494 15.614902 -31.689930 19.309004 16.132967 -33.017014 20.198004 16.991472 -34.331902 20.706911 18.131908 -35.544979 20.801041 19.476559 -36.573582 20.473982 20.933786 -37.347610 19.748022 22.404285 -37.814320 18.672632 23.787840 -37.941898 17.321100 24.990168 -37.721657 15.785533 25.929331 -37.168602 14.170572 26.541325 -36.320423 12.586277 26.784445 -35.234924 11.140615 26.642120 -33.986080 9.932104 26.124054 -43.225967 14.103564 20.717365 -42.968212 12.332311 21.801962 -42.257915 10.525033 22.582569 -41.143482 8.804894 23.005997 -39.700863 7.289120 23.043385 -38.028366 6.081006 22.692186 -36.239971 5.262885 21.976334 -34.457554 4.890509 20.944613 -32.802586 4.989255 19.667334 -31.387842 5.552395 18.231541 -30.309744 6.541551 16.735079 -29.641758 7.889313 15.279932 -29.429405 9.503834 13.965264 -29.687160 11.275087 12.880669 -30.397455 13.082364 12.100059 -31.511887 14.802503 11.676633 -32.954506 16.318279 11.639244 -34.627003 17.526394 11.990443 -36.415398 18.344515 12.706293 -38.197815 18.716892 13.738014 -39.852787 18.618145 15.015293 -41.267529 18.055008 16.451086 -42.345627 17.065851 17.947548 -43.013615 15.718090 19.402695 -39.187389 15.638653 7.360697 -41.347305 15.820262 8.172726 -43.358086 15.490984 9.270877 -45.082703 14.673261 10.580316 -46.403622 13.422819 12.011806 -47.230831 11.824874 13.467792 -47.507954 9.988322 14.849051 -47.216103 8.038321 16.061455 -46.375172 6.107763 17.022379 -45.042465 4.328209 17.666338 -43.308807 2.820935 17.949446 -41.292343 1.688657 17.852413 -39.130493 1.008539 17.381847 -36.970577 0.826930 16.569820 -34.959797 1.156207 15.471670 -33.235180 1.973928 14.162231 -31.914257 3.224371 12.730742 -31.087049 4.822316 11.274755 -30.809925 6.658867 9.893495 -31.101774 8.608867 8.681090 -31.942705 10.539427 7.720166 -33.275410 12.318979 7.076207 -35.009068 13.826255 6.793098 -37.025532 14.958534 6.890131 -31.736790 3.441424 5.149161 -32.053955 5.494041 3.836451 -32.981972 7.466049 2.701990 -34.457600 9.223061 1.823090 -36.380280 10.645338 1.259647 -38.618980 11.635955 1.050059 -41.021141 12.127403 1.208608 -43.423058 12.086190 1.724490 -45.661041 11.515126 2.562547 -47.582581 10.453127 3.665668 -49.056725 8.972567 4.958677 -49.983013 7.174343 6.353458 -50.298321 5.181002 7.754959 -49.981159 3.128386 9.067670 -49.053143 1.156378 10.202130 -47.577515 -0.600634 11.081030 -45.654835 -2.022913 11.644474 -43.416134 -3.013531 11.854063 -41.013973 -3.504980 11.695515 -38.612057 -3.463767 11.179634 -36.374073 -2.892704 10.341578 -34.452534 -1.830706 9.238456 -32.978390 -0.350146 7.945447 -32.052101 1.448077 6.550666 -41.666393 -7.987603 5.325241 -39.181740 -7.713979 5.145841 -36.866432 -6.914655 4.615768 -34.878250 -5.644102 3.771147 -33.352688 -3.988909 2.669536 -32.393711 -2.061872 1.386009 -32.066669 0.005682 0.008036 -32.393852 2.072855 -1.370477 -33.352959 3.998772 -2.655586 -34.878632 5.652184 -3.759713 -36.866898 6.920415 -4.607615 -39.182262 7.717037 -5.141507 -41.666931 7.987760 -5.325006 -44.151585 7.714137 -5.145606 -46.466892 6.914813 -4.615534 -48.455074 5.644262 -3.770914 -49.980637 3.989068 -2.669302 -50.939617 2.062032 -1.385776 -51.266659 -0.005522 -0.007802 -50.939480 -2.072695 1.370710 -49.980370 -3.998612 2.655820 -48.454697 -5.652025 3.759948 -46.466431 -6.920256 4.607849 -44.151070 -7.716879 5.141742 -50.294907 -5.192605 -7.771467 -49.979828 -7.184809 -6.368291 -49.053989 -8.981172 -4.970807 -47.580486 -10.459272 -3.674254 -45.659729 -11.518385 -2.566988 -43.422623 -12.086329 -1.724469 -41.021618 -12.124401 -1.204111 -38.620338 -11.630009 -1.041377 -36.382427 -10.636840 -1.247357 -34.460396 -9.212582 -1.808013 -32.985229 -7.454292 -2.685138 -32.057453 -5.481797 -3.818957 -31.740297 -3.429518 -5.132202 -32.055374 -1.437315 -6.535378 -32.981209 0.359047 -7.932861 -34.454712 1.837149 -9.229414 -36.375469 2.896262 -10.336681 -38.612576 3.464208 -11.179201 -41.013580 3.502281 -11.699560 -43.414860 3.007888 -11.862294 -45.652771 2.014721 -11.656315 -47.574802 0.590464 -11.095659 -49.049973 -1.167826 -10.218534 -49.977749 -3.140321 -9.084716 -39.130539 -1.009234 -17.382906 -41.290699 -1.692108 -17.857265 -43.305592 -2.826896 -17.957752 -45.037899 -4.336267 -17.677515 -46.369576 -6.117359 -17.035652 -47.209862 -8.048792 -16.075907 -47.501499 -9.998943 -14.863684 -47.224609 -11.834913 -13.481593 -46.398064 -13.431585 -12.023822 -45.078190 -14.680145 -10.589716 -43.354939 -15.495508 -9.277007 -41.345737 -15.822108 -8.175153 -39.187519 -15.637688 -7.359244 -37.027359 -14.954815 -6.884884 -35.012466 -13.820027 -6.784397 -33.280155 -12.310658 -7.064634 -31.948481 -10.529565 -7.706496 -31.108192 -8.598132 -8.666241 -30.816555 -6.647981 -9.878464 -31.093443 -4.812010 -11.260554 -31.919989 -3.215339 -12.718326 -33.239861 -1.966778 -14.152431 -34.963116 -1.151414 -15.465141 -36.972313 -0.824813 -16.566996 -29.437725 -9.495262 -13.954064 -29.650127 -7.880823 -15.268840 -30.317602 -6.533714 -16.724840 -31.394663 -5.545738 -18.222841 -32.807907 -4.984224 -19.660757 -34.461029 -4.887438 -20.940596 -36.241367 -5.261977 -21.975138 -38.027596 -6.082314 -22.693884 -39.697987 -7.292547 -23.047848 -41.138702 -8.810200 -23.012913 -42.251568 -10.531847 -22.591454 -42.960739 -12.340161 -21.812201 -43.217884 -14.111909 -20.728249 -43.005482 -15.726349 -19.413475 -42.338009 -17.073458 -17.957476 -41.260948 -18.061434 -16.459473 -39.847702 -18.622950 -15.021557 -38.194584 -18.719736 -13.741717 -36.414246 -18.345198 -12.707174 -34.628017 -17.524860 -11.988430 -32.957626 -16.314629 -11.634464 -31.516907 -14.796976 -11.669400 -30.404043 -13.075330 -12.090857 -29.694872 -11.267015 -12.870111 -33.018463 -20.196543 -16.989500 -31.694536 -19.305323 -16.128405 -30.448542 -18.094837 -15.608051 -29.365396 -16.647577 -15.463900 -28.518911 -15.062173 -15.705775 -27.966776 -13.446669 -16.317194 -27.746614 -11.911156 -17.256487 -27.873432 -10.560278 -18.459646 -28.338585 -9.486095 -19.844675 -29.110376 -8.761811 -21.317188 -30.136209 -8.436785 -22.776834 -31.346172 -8.533165 -24.124144 -32.657810 -9.044384 -25.267298 -33.981739 -9.935604 -26.128393 -35.227734 -11.146090 -26.648746 -36.310879 -12.593349 -26.792896 -37.157364 -14.178752 -26.551022 -37.709503 -15.794258 -25.939604 -37.929665 -17.329771 -25.000313 -37.802845 -18.680649 -23.797155 -37.337692 -19.754833 -22.412127 -36.565903 -20.479116 -20.939613 -35.540070 -20.804144 -19.479965 -34.330105 -20.707764 -18.132656 -32.217747 -19.571220 -27.539070 -32.184311 -20.645113 -26.487103 -31.934202 -21.453289 -25.244003 -31.484470 -21.940670 -23.894485 -30.865763 -22.074043 -22.530516 -30.120243 -21.844320 -21.245049 -29.298716 -21.267155 -20.125687 -28.457169 -20.381884 -19.248711 -27.652952 -19.248829 -18.673883 -26.940870 -17.945213 -18.440384 -26.369452 -16.559874 -18.564119 -25.977634 -15.187218 -19.036661 -25.792126 -13.920790 -19.825806 -25.825563 -12.846897 -20.877771 -26.075670 -12.038721 -22.120869 -26.525400 -11.551339 -23.470387 -27.144110 -11.417964 -24.834358 -27.889629 -11.647686 -26.119825 -28.711155 -12.224852 -27.239189 -29.552702 -13.110125 -28.116165 -30.356918 -14.243177 -28.690990 -31.069002 -15.546793 -28.924492 -31.640421 -16.932133 -28.800756 -32.032238 -18.304790 -28.328217 -24.689463 -14.743328 -28.023552 -25.110842 -15.549777 -28.796499 -25.530815 -16.538820 -29.316875 -25.920763 -17.643053 -29.549212 -26.254110 -18.787228 -29.477676 -26.508142 -19.893368 -29.107143 -26.665545 -20.886093 -28.462866 -26.715591 -21.697750 -27.588747 -26.654873 -22.273026 -26.544363 -26.487526 -22.572718 -25.400881 -26.224955 -22.576399 -24.236229 -25.885056 -22.283823 -23.129774 -25.490988 -21.714924 -22.156923 -25.069611 -20.908476 -21.383972 -24.649637 -19.919434 -20.863598 -24.259689 -18.815201 -20.631262 -23.926340 -17.671026 -20.702799 -23.672308 -16.564884 -21.073328 -23.514906 -15.572161 -21.717607 -23.464859 -14.760504 -22.591722 -23.525578 -14.185227 -23.636108 -23.692924 -13.885536 -24.779591 -23.955494 -13.881852 -25.944242 -24.295395 -14.174428 -27.050697 -20.859888 -16.868547 -22.901285 -20.749496 -16.281672 -23.593811 -20.675341 -15.891068 -24.417297 -20.642473 -15.723351 -25.315624 -20.653135 -15.789955 -26.227573 -20.706600 -16.086338 -27.090996 -20.799223 -16.592302 -27.847052 -20.924694 -17.273369 -28.444218 -21.074461 -18.083124 -28.841795 -21.238317 -18.966383 -29.012691 -21.405096 -19.862953 -28.945263 -21.563435 -20.711735 -28.644100 -21.702539 -21.454885 -28.129728 -21.812931 -22.041759 -27.437204 -21.887087 -22.432367 -26.613720 -21.919954 -22.600080 -25.715391 -21.909292 -22.533480 -24.803440 -21.855827 -22.237095 -23.940020 -21.763205 -21.731131 -23.183964 -21.637733 -21.050064 -22.586798 -21.487968 -20.240309 -22.189219 -21.324112 -19.357052 -22.018322 -21.157331 -18.460482 -22.085751 -20.998993 -17.611700 -22.386913 -18.225742 -21.502609 -23.324263 -18.263571 -20.951342 -22.906576 -18.262493 -20.311369 -22.641581 -18.222580 -19.626303 -22.547337 -18.146551 -18.942835 -22.630262 -18.039589 -18.307533 -22.884708 -17.908981 -17.763702 -23.293337 -17.763630 -17.348398 -23.828299 -17.613441 -17.089924 -24.453135 -17.468647 -17.005890 -25.125269 -17.339119 -17.102032 -25.798893 -17.233681 -17.371792 -26.428101 -17.159521 -17.796787 -26.970011 -17.121691 -18.348055 -27.387695 -17.122768 -18.988028 -27.652691 -17.162682 -19.673090 -27.746939 -17.238710 -20.356562 -27.664013 -17.345673 -20.991859 -27.409565 -17.476280 -21.535694 -27.000938 -17.621632 -21.950998 -26.465975 -17.771820 -22.209475 -25.841139 -17.916615 -22.293505 -25.169004 -18.046143 -22.197365 -24.495382 -18.151581 -21.927605 -23.866175 -13.877616 -21.382988 -25.456375 -14.044682 -21.687420 -25.029501 -14.234690 -21.862835 -24.543766 -14.434690 -21.897280 -24.032274 -14.631054 -21.788404 -23.529881 -14.810398 -21.543633 -23.070826 -14.960503 -21.179644 -22.686390 -15.071136 -20.721241 -22.402775 -15.134762 -20.199667 -22.239304 -15.147040 -19.650463 -22.207121 -15.107137 -19.111059 -22.308420 -15.017771 -18.618214 -22.536295 -14.885032 -18.205513 -22.875217 -14.717966 -17.901081 -23.302092 -14.527959 -17.725666 -23.787825 -14.327958 -17.691223 -24.299316 -14.131595 -17.800095 -24.801708 -13.952250 -18.044867 -25.260767 -13.802145 -18.408857 -25.645203 -13.691511 -18.867260 -25.928818 -13.627886 -19.388832 -26.092289 -13.615607 -19.938036 -26.124472 -13.655510 -20.477442 -26.023174 -13.744877 -20.970287 -25.795300 -10.683930 -18.507092 -24.084866 -10.534564 -18.938738 -24.291246 -10.441695 -19.421062 -24.391041 -10.411652 -19.921198 -24.377453 -10.446481 -20.405058 -24.251406 -10.543809 -20.839670 -24.021488 -10.697004 -21.195415 -23.703371 -10.895626 -21.448051 -23.318733 -11.126139 -21.580360 -22.893787 -11.372833 -21.583326 -22.457491 -11.618897 -21.456745 -22.039576 -11.847563 -21.209246 -21.668526 -12.043246 -20.857695 -21.369625 -12.192613 -20.426048 -21.163244 -12.285481 -19.943722 -21.063450 -12.315525 -19.443588 -21.077036 -12.280697 -18.959726 -21.203083 -12.183368 -18.525116 -21.433001 -12.030172 -18.169369 -21.751118 -11.831552 -17.916735 -22.135756 -11.601039 -17.784424 -22.560703 -11.354344 -17.781458 -22.997000 -11.108279 -17.908039 -23.414915 -10.879614 -18.155539 -23.785963 -9.501036 -17.663181 -20.106434 -9.235203 -17.413057 -20.518242 -8.928146 -17.297255 -20.959967 -8.600791 -17.323666 -21.401505 -8.275446 -17.490488 -21.812765 -7.974284 -17.786352 -22.165722 -7.717826 -18.191099 -22.436321 -7.523552 -18.677143 -22.606125 -7.404700 -19.211361 -22.663557 -7.369370 -19.757349 -22.604706 -7.419970 -20.277897 -22.433580 -7.553050 -20.737532 -22.161846 -7.759542 -21.104927 -21.808020 -8.025375 -21.355049 -21.396210 -8.332432 -21.470854 -20.954485 -8.659786 -21.444443 -20.512949 -8.985131 -21.277620 -20.101686 -9.286294 -20.981756 -19.748730 -9.542751 -20.577011 -19.478130 -9.737025 -20.090965 -19.308327 -9.855878 -19.556747 -19.250896 -9.891208 -19.010759 -19.309746 -9.840609 -18.490211 -19.480869 -9.707528 -18.030577 -19.752604 -7.498581 -20.339510 -17.130520 -7.760771 -19.716137 -16.980648 -7.913740 -19.040743 -16.965172 -7.947063 -18.359350 -17.085146 -7.858470 -17.718401 -17.332392 -7.653997 -17.161570 -17.690058 -7.347580 -16.726805 -18.133776 -6.960100 -16.443735 -18.633303 -6.517963 -16.331650 -19.154600 -6.051300 -16.398190 -19.662138 -5.591914 -16.638821 -20.121330 -5.171110 -17.037140 -20.500885 -4.817566 -17.566008 -20.774937 -4.555376 -18.189379 -20.924809 -4.402407 -18.864775 -20.940285 -4.369083 -19.546164 -20.820313 -4.457677 -20.187117 -20.573067 -4.662149 -20.743948 -20.215397 -4.968566 -21.178713 -19.771681 -5.356046 -21.461784 -19.272154 -5.798183 -21.573868 -18.750858 -6.264846 -21.507328 -18.243320 -6.724233 -21.266699 -17.784126 -7.145036 -20.868378 -17.404572 -2.290608 -21.424807 -17.588547 -2.859875 -21.763069 -16.957890 -3.501177 -21.874043 -16.315525 -4.170810 -21.750162 -15.705229 -4.823140 -21.399874 -15.168592 -5.413712 -20.847044 -14.742187 -5.902278 -20.129353 -14.455071 -6.255545 -19.295706 -14.326811 -6.449438 -18.402916 -14.366147 -6.470743 -17.511824 -14.570398 -6.318008 -16.683159 -14.925647 -6.001642 -15.973392 -15.407683 -5.543205 -15.430891 -15.983655 -4.973938 -15.092628 -16.614313 -4.332637 -14.981655 -17.256680 -3.663004 -15.105535 -17.866974 -3.010674 -15.455824 -18.403612 -2.420102 -16.008652 -18.830017 -1.931535 -16.726343 -19.117134 -1.578268 -17.559992 -19.245394 -1.384375 -18.452780 -19.206059 -1.363070 -19.343872 -19.001806 -1.515804 -20.172537 -18.646557 -1.832170 -20.882305 -18.164522 0.946731 -15.748695 -17.441532 1.407137 -16.846098 -17.537088 1.643891 -18.011036 -17.426353 1.640859 -19.164122 -17.116869 1.398248 -20.226774 -16.629728 0.932590 -21.126575 -15.998129 0.275621 -21.802204 -15.265114 -0.527889 -22.207619 -14.480637 -1.423182 -22.315193 -13.698157 -2.349245 -22.117590 -12.971001 -3.242968 -21.628284 -12.348722 -4.043447 -20.880613 -11.873728 -4.696128 -19.925533 -11.578388 -5.156535 -18.828133 -11.482830 -5.393289 -17.663195 -11.593567 -5.390258 -16.510109 -11.903050 -5.147646 -15.447455 -12.390191 -4.681989 -14.547655 -13.021791 -4.025020 -13.872025 -13.754806 -3.221511 -13.466610 -14.539283 -2.326218 -13.359036 -15.321762 -1.400155 -13.556637 -16.048920 -0.506431 -14.045945 -16.671198 0.294048 -14.793614 -17.146193 -2.721090 -12.166820 -11.491932 -1.651858 -11.687875 -12.434475 -0.470051 -11.584520 -13.358423 0.743793 -11.863795 -14.200810 1.906954 -12.506670 -14.904231 2.940162 -13.469334 -15.420747 3.773007 -14.686182 -15.715158 4.348733 -16.074287 -15.767402 4.628104 -17.539059 -15.573917 4.592082 -18.980665 -15.147890 4.243120 -20.300871 -14.518353 3.605002 -21.409702 -13.728209 2.721212 -22.231594 -12.831306 1.651981 -22.710539 -11.888763 0.470175 -22.813896 -10.964815 -0.743669 -22.534620 -10.122427 -1.906831 -21.891747 -9.419006 -2.940040 -20.929081 -8.902491 -3.772885 -19.712234 -8.608078 -4.348611 -18.324127 -8.555835 -4.627983 -16.859360 -8.749319 -4.591960 -15.417751 -9.175345 -4.243000 -14.097547 -9.804881 -3.604882 -12.988716 -10.595025 -3.002367 -19.470018 -5.628658 -3.694676 -17.793926 -5.626334 -4.016826 -16.031406 -5.906187 -3.946863 -14.302567 -6.449145 -3.489556 -12.725230 -7.218208 -2.676069 -11.406886 -8.160964 -1.561839 -10.437380 -9.213165 -0.222801 -9.882779 -10.303106 1.249793 -9.780880 -11.356511 2.755589 -10.138628 -12.301590 4.191968 -10.931643 -13.073939 5.461044 -12.105879 -13.620923 6.476332 -13.581318 -13.905266 7.168641 -15.257408 -13.907590 7.490791 -17.019930 -13.627737 7.420829 -18.748768 -13.084779 6.963522 -20.326105 -12.315718 6.150035 -21.644449 -11.372962 5.035807 -22.613956 -10.320761 3.696769 -23.168560 -9.230819 2.224174 -23.270458 -8.177414 0.718379 -22.912712 -7.232335 -0.718000 -22.119698 -6.459986 -1.987077 -20.945461 -5.913002 7.201397 -22.848654 -7.762406 5.615925 -23.475389 -6.548454 3.876937 -23.580591 -5.388691 2.102940 -23.157085 -4.362154 0.414831 -22.233738 -3.538800 -1.072350 -20.873472 -2.974739 -2.257252 -19.168987 -2.708409 -3.059129 -17.236441 -2.757962 -3.423331 -15.207533 -3.120021 -3.325040 -13.220531 -3.769911 -2.770955 -11.410845 -4.663344 -1.798835 -9.901801 -5.739433 -0.474929 -8.796243 -6.924846 1.110542 -8.169505 -8.138798 2.849530 -8.064304 -9.298561 4.623527 -8.487807 -10.325097 6.311638 -9.411156 -11.148453 7.798818 -10.771420 -11.712515 8.983722 -12.475906 -11.978845 9.785598 -14.408452 -11.929292 10.149801 -16.437361 -11.567234 10.051512 -18.424362 -10.917344 9.497427 -20.234049 -10.023911 8.525308 -21.743092 -8.947823 11.222728 -11.408538 -9.915619 12.119385 -13.540181 -9.816808 12.524288 -15.777512 -9.383148 12.409844 -17.968061 -8.644193 11.783853 -19.962547 -7.650301 10.688972 -21.625048 -6.469204 9.199820 -22.842264 -5.181392 7.417876 -23.531250 -3.874627 5.464580 -23.645050 -2.637963 3.473043 -23.175907 -1.555676 1.578987 -22.155796 -0.701523 -0.088513 -20.654232 -0.133713 -1.415819 -18.773546 0.109060 -2.312477 -16.641905 0.010249 -2.717381 -14.404573 -0.423409 -2.602939 -12.214024 -1.162364 -1.976947 -10.219538 -2.156256 -0.882068 -8.557036 -3.337353 0.607085 -7.339818 -4.625165 2.389028 -6.650832 -5.931930 4.342324 -6.537031 -7.168594 6.333861 -7.006173 -8.250881 8.227918 -8.026283 -9.105034 9.895418 -9.527847 -9.672845 1.750183 -6.135693 -2.316284 3.659370 -5.402502 -3.678086 5.753954 -5.277653 -4.956443 7.891194 -5.769655 -6.064236 9.925440 -6.844979 -6.925972 11.718062 -8.430343 -7.482924 13.146894 -10.417707 -7.697138 14.114567 -12.671636 -7.554015 14.555133 -15.038527 -7.063309 14.438568 -17.357080 -6.258460 13.772817 -19.469294 -5.194317 12.603250 -21.231220 -3.943401 11.009569 -22.522789 -2.590958 9.100383 -23.255980 -1.229156 7.005800 -23.380831 0.049200 4.868559 -22.888828 1.156994 2.834312 -21.813505 2.018730 1.041690 -20.228142 2.575684 -0.387144 -18.240780 2.789898 -1.354816 -15.986852 2.646775 -1.795383 -13.619961 2.156070 -1.678819 -11.301405 1.351221 -1.013069 -9.189192 0.287078 0.156498 -7.427265 -0.963838 0.894355 -17.526731 5.323382 -0.112502 -15.238970 5.141908 -0.579279 -12.834852 4.610030 -0.474165 -10.478219 3.763993 0.195677 -8.329668 2.661453 1.384597 -6.535621 1.377548 3.011573 -5.218339 -0.000228 4.965729 -4.467591 -1.377980 7.113893 -4.334542 -2.661818 9.309669 -4.828256 -3.764250 11.403423 -5.915090 -4.610148 13.252465 -7.520975 -5.141864 14.730787 -9.536476 -5.323163 15.737646 -11.824238 -5.141689 16.204422 -14.228354 -4.609811 16.099310 -16.584988 -3.763775 15.429469 -18.733540 -2.661235 14.240549 -20.527588 -1.377330 12.613573 -21.844872 0.000445 10.659418 -22.595621 1.378198 8.511255 -22.728670 2.662036 6.315477 -22.234957 3.764468 4.221724 -21.148125 4.610367 2.372681 -19.542238 5.142083 14.002212 -20.794889 2.592809 12.087508 -21.529051 3.946301 9.977367 -21.660822 5.198085 7.815593 -21.181225 6.262855 5.749505 -20.122940 7.068049 3.919905 -18.558092 7.558795 2.451477 -16.593321 7.701649 1.444292 -14.362521 7.486875 0.966986 -12.017719 6.929110 1.052090 -9.718710 6.066365 1.693801 -7.622166 4.957435 2.848389 -5.870963 3.677891 4.437171 -4.584444 2.314932 6.351873 -3.850282 0.961441 8.462013 -3.718509 -0.290343 10.623787 -4.198105 -1.355114 12.689877 -5.256388 -2.160309 14.519477 -6.821237 -2.651055 15.987906 -8.786008 -2.793909 16.995092 -11.016808 -2.579136 17.472399 -13.361608 -2.021372 17.387295 -15.660619 -1.158628 16.745584 -17.757162 -0.049697 15.590998 -19.508368 1.229846 16.966404 -8.157785 -0.106702 17.932142 -10.247276 0.136101 18.399410 -12.442032 0.703795 18.336361 -14.592487 1.557696 17.747295 -16.552088 2.639609 16.672356 -18.187292 3.875804 15.184795 -19.386663 5.182037 13.385993 -20.068470 6.469290 11.398532 -20.186243 7.649839 9.357853 -19.731958 8.643231 7.403028 -18.736576 9.381769 5.667272 -17.267925 9.815123 4.268877 -15.426099 9.913759 3.303138 -13.336609 9.670957 2.835870 -11.141853 9.103262 2.898917 -8.991400 8.249363 3.487983 -7.031796 7.167449 4.562922 -5.396591 5.931254 6.050481 -4.197218 4.625021 7.849284 -3.515413 3.337768 9.836744 -3.397639 2.157219 11.877422 -3.851922 1.163826 13.832249 -4.847305 0.425288 15.568005 -6.315953 -0.008066 7.852873 -3.988393 6.924562 9.472257 -3.393968 5.739511 11.265345 -3.305872 4.663795 13.109941 -3.730108 3.770723 14.880339 -4.637765 3.121154 16.455889 -5.966989 2.759358 17.729219 -7.627192 2.709988 18.613556 -9.505238 2.976410 19.048632 -11.473139 3.540467 19.004799 -13.396787 4.363720 18.485044 -15.145086 5.390065 17.524786 -16.598898 6.549560 16.189465 -17.659142 7.763186 14.570082 -18.253569 8.948236 12.776994 -18.341665 10.023952 10.932399 -17.917431 10.917025 9.161999 -17.009773 11.566593 7.586449 -15.680552 11.928391 6.313118 -14.020348 11.977761 5.428780 -12.142302 11.711340 4.993703 -10.174401 11.147284 5.037535 -8.250753 10.324030 5.557291 -6.502452 9.297686 6.517549 -5.048641 8.138190 8.524692 -12.398100 13.907171 7.754307 -10.781382 13.622216 7.371618 -9.095535 13.074552 7.402706 -7.455446 12.301497 7.845449 -5.972886 11.355737 8.669678 -4.748888 10.301723 9.819220 -3.866865 9.211285 11.215737 -3.386926 8.158733 12.764060 -3.341778 7.215798 14.358672 -3.734498 6.446740 15.890903 -4.538321 5.903967 17.256334 -5.698470 5.624470 18.361916 -7.135882 5.627295 19.132299 -8.752600 5.912248 19.514990 -10.438448 6.459914 19.483902 -12.078536 7.232967 19.041159 -13.561096 8.178727 18.216932 -14.785096 9.232741 17.067390 -15.667119 10.323179 15.670873 -16.147058 11.375731 14.122550 -16.192207 12.318666 12.527938 -15.799489 13.087726 10.995707 -14.995666 13.630498 9.630275 -13.835517 13.909996 17.891857 -13.472175 12.835108 16.738434 -13.825535 13.732706 15.459387 -13.822750 14.523254 14.141883 -13.464012 15.152877 12.875707 -12.773768 15.578667 11.747148 -11.799057 15.771606 10.833115 -10.606304 15.718549 10.195897 -9.276792 15.423107 9.878920 -7.901126 14.905418 9.903785 -6.573055 14.200760 10.268798 -5.383085 13.357155 10.949082 -4.412311 12.432092 11.898281 -3.726888 11.488612 13.051704 -3.373528 10.591015 14.330751 -3.376312 9.800467 15.648254 -3.735049 9.170844 16.914431 -4.425292 8.745053 18.042992 -5.400003 8.552113 18.957026 -6.592756 8.605170 19.594242 -7.922269 8.900611 19.911221 -9.297934 9.418300 19.886356 -10.626005 10.122957 19.521343 -11.815976 10.966563 18.841059 -12.786751 11.891626 19.603722 -5.899624 11.576354 20.104387 -6.942115 11.872782 20.351574 -8.008647 12.348945 20.328440 -9.026537 12.972394 20.036558 -9.926417 13.700642 19.495823 -10.646961 14.484058 18.743084 -11.139069 15.269258 17.829638 -11.369199 16.002728 16.817734 -11.321672 16.634485 15.776335 -10.999725 17.121473 14.776407 -10.425300 17.430510 13.886096 -9.637542 17.540531 13.166073 -8.690136 17.444040 12.665408 -7.647645 17.147614 12.418220 -6.581113 16.671450 12.441354 -5.563223 16.048000 12.733235 -4.663342 15.319753 13.273970 -3.942797 14.536336 14.026710 -3.450691 13.751137 14.940156 -3.220560 13.017667 15.952058 -3.268086 12.385910 16.993458 -3.590032 11.898920 17.993385 -4.164456 11.589885 18.883698 -4.952214 11.479863 16.134937 -2.915545 15.982181 16.833900 -2.790059 15.406096 17.606716 -2.871169 14.924074 18.400719 -3.153348 14.568962 19.161795 -3.617365 14.364958 19.838083 -4.231599 14.325967 20.383493 -4.954191 14.454645 20.760855 -5.735897 14.742226 20.944454 -6.523445 15.169107 20.921780 -7.263165 15.706200 20.694374 -7.904646 16.316900 20.277735 -8.404173 16.959593 19.700256 -8.727704 17.590479 19.001293 -8.853190 18.166561 18.228479 -8.772080 18.648584 17.434477 -8.489902 19.003696 16.673399 -8.025885 19.207701 15.997111 -7.411651 19.246691 15.451702 -6.689060 19.118013 15.074339 -5.907354 18.830433 14.890739 -5.119806 18.403551 14.913415 -4.380086 17.866459 15.140820 -3.738604 17.255758 15.557458 -3.239077 16.613066 17.621773 -4.608477 20.775824 17.340504 -4.038224 20.501104 17.205908 -3.475122 20.120876 17.227158 -2.957545 19.661058 17.402805 -2.520765 19.152981 17.720881 -2.194548 18.631271 18.159706 -2.001124 18.131481 18.689379 -1.953676 17.687672 19.273800 -2.055437 17.330088 19.873144 -2.299472 17.083097 20.446568 -2.669150 16.963531 20.954990 -3.139279 16.979542 21.363766 -3.677820 17.130033 21.645035 -4.248073 17.404753 21.779631 -4.811175 17.784979 21.758381 -5.328752 18.244799 21.582735 -5.765532 18.752874 21.264660 -6.091750 19.274586 20.825832 -6.285173 19.774376 20.296162 -6.332622 20.218185 19.711739 -6.230861 20.575769 19.112394 -5.986826 20.822760 18.538971 -5.617148 20.942326 18.030550 -5.147019 20.926315 22.157425 -3.830863 21.810719 21.736044 -3.825426 22.164572 21.271479 -3.710429 22.436155 20.795393 -3.493710 22.606968 20.340227 -3.190037 22.665367 19.937002 -2.820106 22.607372 19.613195 -2.409127 22.436935 19.390877 -1.985106 22.165672 19.285192 -1.576942 21.812067 19.303350 -1.212448 21.400221 19.444107 -0.916466 20.958197 19.697876 -0.709165 20.516121 20.047358 -0.604673 20.104118 20.468740 -0.610110 19.750265 20.933304 -0.725107 19.478680 21.409391 -0.941826 19.307869 21.864557 -1.245498 19.249470 22.267782 -1.615429 19.307465 22.591589 -2.026409 19.477901 22.813908 -2.450429 19.749165 22.919592 -2.858593 20.102768 22.901434 -3.223087 20.514616 22.760677 -3.519070 20.956640 22.506908 -3.726371 21.398716</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="2880" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="8640">0.722360 0.013843 -0.691379 -0.554065 0.544435 -0.629764 -0.346012 0.510073 -0.787465 0.830393 -0.163548 -0.532634 -0.114302 0.439245 -0.891066 0.881464 -0.329757 -0.338057 0.124625 0.336678 -0.933336 0.872477 -0.473455 -0.120927 0.353814 0.209386 -0.911577 0.804387 -0.584913 0.104106 0.557203 0.066145 -0.827738 0.682040 -0.656647 0.321926 0.720858 -0.083151 -0.688077 0.513826 -0.683902 0.517940 0.833901 -0.228196 -0.502529 0.311097 -0.664957 0.679007 0.889122 -0.358977 -0.283896 0.087440 -0.601219 0.794286 0.883287 -0.466471 -0.046985 -0.142206 -0.497092 0.855965 0.817225 -0.543284 0.192318 -0.362498 -0.359659 0.859791 0.695683 -0.584192 0.418025 -0.558671 -0.198206 0.805358 0.526983 -0.586498 0.615068 -0.717481 -0.023589 0.696178 0.322462 -0.550212 0.770250 -0.828083 0.152474 0.539472 0.095748 -0.477994 0.873129 -0.882756 0.318150 0.345719 -0.138100 -0.374924 0.916712 -0.877460 0.462257 0.127996 -0.363535 -0.248117 0.897931 -0.812176 0.574972 -0.098883 -0.565506 -0.106205 0.817878 -0.691004 0.648490 -0.319333 -0.730416 0.041258 0.681756 -0.522005 0.677575 -0.518077 -0.847008 0.184420 0.498565 -0.316719 0.660003 -0.681239 -0.907113 0.313757 0.280539 -0.089415 0.596792 -0.797399 -0.906232 0.420654 0.042363 0.143975 0.492209 -0.858488 -0.843910 0.497910 -0.199755 0.367084 0.353478 -0.860408 -0.723898 0.540197 -0.429137 0.564389 0.190246 -0.803288 -0.739546 0.089229 0.667166 -0.866466 0.186844 0.462953 -0.936077 0.269256 0.226409 -0.943143 0.331318 -0.026653 -0.886460 0.369154 -0.279130 -0.769103 0.380323 -0.513648 -0.598508 0.363946 -0.713674 -0.386260 0.320844 -0.864790 -0.147430 0.253587 -0.956012 0.100658 0.166411 -0.980905 0.340022 0.064957 -0.938171 0.553740 -0.044060 -0.831523 0.727275 -0.153265 -0.669015 0.849332 -0.255039 -0.462159 0.912336 -0.342039 -0.225061 0.912680 -0.407822 0.026387 0.850842 -0.447454 0.275414 0.731295 -0.458018 0.505398 0.562194 -0.438873 0.700948 0.354850 -0.391641 0.848940 0.123005 -0.319992 0.939401 -0.118017 -0.229263 0.966183 -0.352267 -0.125989 0.927380 -0.564176 -0.017378 0.825472 0.612945 -0.241999 0.752153 0.402906 -0.190395 0.895219 0.165303 -0.128434 0.977844 -0.084101 -0.061232 0.994574 -0.328763 0.005933 0.944394 -0.552436 0.068128 0.830766 -0.740230 0.121174 0.661345 -0.879562 0.161935 0.447379 -0.960902 0.188400 0.202913 -0.978263 0.199641 -0.056085 -0.929552 0.195620 -0.312514 -0.816906 0.177015 -0.548936 -0.647036 0.145095 -0.748526 -0.431353 0.101670 -0.896436 -0.185459 0.049036 -0.981428 0.072279 -0.010068 -0.997334 0.322819 -0.072499 -0.943680 0.548467 -0.134675 -0.825255 0.734197 -0.192550 -0.651060 0.868231 -0.241723 -0.433295 0.942317 -0.277854 -0.186644 0.952038 -0.297293 0.072394 0.897106 -0.297770 0.326395 0.781447 -0.278846 0.558199 0.730912 -0.223362 -0.644886 0.877229 -0.213400 -0.430035 0.963604 -0.192405 -0.185600 0.984461 -0.160240 0.071835 0.938452 -0.117981 0.324637 0.828750 -0.068141 0.555455 0.662872 -0.014507 0.748592 0.452116 0.038331 0.891135 0.210749 0.085585 0.973786 -0.044955 0.122898 0.991401 -0.297822 0.146896 0.943252 -0.530966 0.155593 0.832986 -0.728966 0.148601 0.668227 -0.878844 0.127083 0.459872 -0.970724 0.093482 0.221259 -0.998161 0.051108 -0.032608 -0.958351 0.003681 -0.285569 -0.852520 -0.045058 -0.520749 -0.686538 -0.091686 -0.721290 -0.471397 -0.133395 -0.871774 -0.222831 -0.168217 -0.960234 0.040323 -0.195066 -0.979961 0.298562 -0.213470 -0.930210 0.533885 -0.223094 -0.815596 -0.703797 -0.316005 -0.636247 -0.492969 -0.360292 -0.791941 -0.246886 -0.382155 -0.890508 0.015968 -0.381430 -0.924260 0.276346 -0.359593 -0.891250 0.516253 -0.319019 -0.794802 0.719993 -0.262381 -0.642469 0.874522 -0.192503 -0.445144 0.969769 -0.112615 -0.216485 0.999259 -0.026714 0.027715 0.960825 0.060252 0.270526 0.857016 0.142513 0.495191 0.694991 0.213941 0.686452 0.485978 0.268694 0.831642 0.244419 0.301896 0.921476 -0.013084 0.310271 0.950558 -0.268978 0.292616 0.917620 -0.506064 0.250012 0.825466 -0.708754 0.185753 0.680561 -0.864038 0.104944 0.492368 -0.962032 0.013905 0.272583 -0.996160 -0.080444 0.034565 -0.963270 -0.171122 -0.206947 -0.864055 -0.251540 -0.436046 -0.688242 0.234815 0.686429 -0.842820 0.103694 0.528112 -0.941086 -0.036974 0.336141 -0.976557 -0.177345 0.122006 -0.946110 -0.307658 -0.101110 -0.850417 -0.418743 -0.318505 -0.694653 -0.502681 -0.514556 -0.488974 -0.553644 -0.674079 -0.248094 -0.568633 -0.784287 0.010269 -0.547695 -0.836615 0.267502 -0.493489 -0.827594 0.505887 -0.410459 -0.758684 0.709642 -0.304135 -0.635539 0.865430 -0.180851 -0.467251 0.962858 -0.047741 -0.265753 0.995165 0.087226 -0.045138 0.959921 0.215445 0.179261 0.859435 0.328160 0.392023 0.700683 0.417173 0.578801 0.494785 0.475595 0.727322 0.256147 0.498571 0.828140 0.001362 0.483848 0.875151 -0.252065 0.432117 0.865874 -0.487062 0.347023 0.801465 0.680216 0.582642 0.444785 0.477596 0.645467 0.596050 0.243686 0.661984 0.708798 -0.005208 0.630682 0.776024 -0.251972 0.553617 0.793737 -0.480005 0.436265 0.761097 -0.674383 0.286992 0.680325 -0.822733 0.116280 0.556407 -0.915684 -0.064143 0.396747 -0.947070 -0.242040 0.210892 -0.914131 -0.405285 0.010387 -0.817951 -0.542493 -0.191462 -0.664010 -0.643859 -0.380180 -0.462441 -0.702175 -0.541386 -0.227489 -0.713696 -0.662486 0.023901 -0.678436 -0.734270 0.273894 -0.599794 -0.751817 0.505324 -0.483747 -0.714588 0.702710 -0.338129 -0.625993 0.852922 -0.172168 -0.492830 0.945799 0.003763 -0.324730 0.974845 0.178454 -0.133534 0.937868 0.340363 0.067503 0.837323 0.478370 0.264674 0.696851 -0.360504 -0.620028 0.836236 -0.162764 -0.523658 0.919423 0.045084 -0.390678 0.940562 0.249433 -0.230492 0.898026 0.436596 -0.054153 0.794675 0.593727 0.126407 0.637716 0.709794 0.299184 0.438180 0.776464 0.452882 0.210056 0.788833 0.577597 -0.030780 0.745864 0.665387 -0.267816 0.650520 0.710703 -0.485122 0.509509 0.710674 -0.668462 0.332682 0.665193 -0.806083 0.132186 0.576852 -0.889178 -0.078424 0.450790 -0.912157 -0.284984 0.294540 -0.872897 -0.473443 0.117911 -0.773145 -0.630652 -0.067265 -0.618909 -0.745373 -0.247731 -0.420488 -0.809408 -0.409937 -0.191816 -0.818512 -0.541521 0.050852 -0.772710 -0.632720 0.290513 -0.675953 -0.677266 0.510780 -0.535368 -0.672670 -0.563794 -0.816937 -0.121454 -0.368499 -0.884706 -0.285487 -0.147013 -0.891666 -0.428158 0.085081 -0.837949 -0.539076 0.311684 -0.727974 -0.610661 0.517389 -0.569717 -0.638538 0.688365 -0.373944 -0.621546 0.813076 -0.153561 -0.561539 0.882947 0.076986 -0.463118 0.893008 0.302431 -0.333275 0.842391 0.507589 -0.180917 0.734513 0.678399 -0.016274 0.576898 0.802967 0.149774 0.380604 0.872509 0.306380 0.159375 0.882051 0.443381 -0.071432 0.830850 0.551893 -0.296020 0.722461 0.624838 -0.499320 0.564431 0.657341 -0.667992 0.367647 0.647011 -0.791158 0.145473 0.594060 -0.860853 -0.087158 0.501333 -0.872315 -0.314602 0.374288 -0.824258 -0.521328 0.220942 -0.719218 -0.692862 0.051651 -0.669127 0.392195 0.631231 -0.774455 0.155083 0.613326 -0.827797 -0.092810 0.553297 -0.825453 -0.334780 0.454478 -0.767119 -0.554217 0.323067 -0.656166 -0.735677 0.168002 -0.499767 -0.866160 0.000452 -0.308605 -0.936394 -0.167119 -0.096047 -0.941768 -0.322256 0.123070 -0.882570 -0.453788 0.333692 -0.763599 -0.552780 0.521597 -0.593414 -0.613023 0.674170 -0.383568 -0.631166 0.781065 -0.147936 -0.606673 0.834844 0.097960 -0.541700 0.831577 0.337760 -0.440905 0.771279 0.555265 -0.311143 0.658031 0.735570 -0.161033 0.499732 0.866180 -0.000423 0.307503 0.937962 0.160217 0.094812 0.945862 0.310413 -0.123578 0.889297 0.440317 -0.332738 0.772191 0.541300 -0.518651 0.602631 0.606496 0.406311 0.901236 -0.150614 0.219666 0.975452 0.015478 0.017903 0.983464 0.180219 -0.184933 0.924713 0.332725 -0.374974 0.803274 0.462759 -0.539521 0.627490 0.561403 -0.667858 0.409291 0.621648 -0.751776 0.163315 0.638875 -0.785870 -0.093996 0.611207 -0.767731 -0.345279 0.539789 -0.698156 -0.573192 0.428986 -0.581368 -0.761576 0.286378 -0.425047 -0.896863 0.122361 -0.239936 -0.969460 -0.050772 -0.038949 -0.974690 -0.220140 0.164000 -0.912972 -0.373613 0.355119 -0.789339 -0.500834 0.521607 -0.612659 -0.593780 0.652302 -0.394875 -0.646974 0.738258 -0.150349 -0.657549 0.773339 0.104805 -0.625270 0.754795 0.353578 -0.552511 0.683636 0.579128 -0.444131 0.564697 0.765991 -0.307205 0.622194 -0.412814 -0.665176 0.683511 -0.165604 -0.710906 0.696832 0.093137 -0.711161 0.660753 0.346140 -0.666027 0.577443 0.576244 -0.578362 0.452609 0.767655 -0.453708 0.295101 0.907144 -0.300009 0.116171 0.985054 -0.127173 -0.071456 0.996008 0.053499 -0.254633 0.939289 0.229998 -0.420825 0.818846 0.390381 -0.559020 0.642926 0.523586 -0.660383 0.423386 0.620193 -0.718620 0.174835 0.673066 -0.730114 -0.086217 0.677865 -0.693993 -0.342175 0.633474 -0.612279 -0.575273 0.542379 -0.490054 -0.768800 0.410844 -0.335424 -0.908663 0.248640 -0.159032 -0.984919 0.068137 0.026878 -0.992754 -0.117119 0.209581 -0.932584 -0.293876 0.376829 -0.809461 -0.450304 0.517522 -0.632233 -0.576587 -0.224762 -0.896763 0.381179 -0.060118 -0.979470 0.192416 0.106642 -0.994252 -0.009521 0.264302 -0.941262 -0.210168 0.402474 -0.825243 -0.396218 0.512042 -0.654630 -0.556123 0.585501 -0.440866 -0.680313 0.617382 -0.197923 -0.761358 0.604807 0.058238 -0.794240 0.548000 0.310497 -0.776716 0.450544 0.541724 -0.709610 0.319229 0.736066 -0.596909 0.163536 0.880157 -0.445623 -0.005207 0.964117 -0.265428 -0.174812 0.982242 -0.068124 -0.333271 0.933390 0.133090 -0.469758 0.820993 0.324495 -0.575405 0.652709 0.492829 -0.643777 0.439746 0.626238 -0.670990 0.196074 0.715072 -0.655624 -0.062336 0.752510 -0.598638 -0.318161 0.735124 -0.503433 -0.553533 0.663443 -0.375989 -0.751297 0.542388 -0.617808 0.462821 0.635696 -0.607759 0.233348 0.759064 -0.560278 -0.014526 0.828177 -0.478470 -0.264365 0.837364 -0.367347 -0.498594 0.785150 -0.233914 -0.699751 0.675006 -0.086991 -0.852457 0.515509 0.063474 -0.945475 0.319450 0.207366 -0.972931 0.102008 0.335250 -0.934300 -0.121210 0.438862 -0.833567 -0.335509 0.511314 -0.678296 -0.527705 0.547331 -0.479001 -0.686285 0.543659 -0.248763 -0.801593 0.499607 -0.002757 -0.866248 0.417477 0.242559 -0.875716 0.302670 0.470567 -0.828829 0.163368 0.665757 -0.728065 0.009836 0.814890 -0.579532 -0.146516 0.907924 -0.392691 -0.294169 0.938684 -0.179825 -0.422559 0.905232 0.044713 -0.522980 0.809940 0.265497 -0.589227 0.659199 0.467192 -0.163392 0.708141 -0.686906 -0.306130 0.812819 -0.495591 -0.429040 0.861720 -0.270855 -0.523276 0.851704 -0.027961 -0.582597 0.783442 0.216334 -0.603832 0.661262 0.445106 -0.586788 0.492735 0.642567 -0.533719 0.288163 0.795051 -0.448709 0.060235 0.891646 -0.337293 -0.176123 0.924778 -0.206414 -0.404121 0.891111 -0.064421 -0.606333 0.792597 0.079304 -0.766823 0.636941 0.215163 -0.873464 0.436767 0.334271 -0.919312 0.207673 0.429064 -0.902639 -0.033883 0.493494 -0.826121 -0.272007 0.523091 -0.695953 -0.491961 0.515155 -0.521264 -0.680367 0.469165 -0.313757 -0.825494 0.387231 -0.087248 -0.917845 0.274321 0.143113 -0.950929 0.138132 0.361888 -0.921931 -0.011491 0.554476 -0.832120 0.493153 -0.557201 -0.668077 0.399894 -0.382433 -0.832965 0.275482 -0.185037 -0.943330 0.128001 0.021830 -0.991534 -0.032353 0.224541 -0.973927 -0.194039 0.409912 -0.891247 -0.345138 0.566033 -0.748657 -0.474379 0.682943 -0.555476 -0.572158 0.753160 -0.324630 -0.631475 0.772063 -0.071821 -0.648598 0.738152 0.185613 -0.623307 0.653099 0.430059 -0.558517 0.521640 0.644942 -0.459552 0.351334 0.815706 -0.333376 0.152480 0.930382 -0.188184 -0.061899 0.980181 -0.033268 -0.276344 0.960483 0.121206 -0.474184 0.872043 0.264877 -0.639649 0.721588 0.388185 -0.760114 0.521094 0.483204 -0.827491 0.285958 0.544037 -0.838412 0.033012 0.566825 -0.793672 -0.220893 0.549743 -0.697532 -0.459599 0.449936 -0.487299 0.748397 0.562456 -0.618415 0.548822 0.634809 -0.706681 0.312443 0.662530 -0.746935 0.056053 0.643959 -0.737658 -0.202925 0.580164 -0.680623 -0.447395 0.474956 -0.580521 -0.661371 0.334855 -0.444584 -0.830793 0.168901 -0.282122 -0.944394 -0.011804 -0.103930 -0.994515 -0.194831 0.078388 -0.977699 -0.367321 0.253148 -0.894981 -0.516962 0.409259 -0.751836 -0.632964 0.536818 -0.557838 -0.706972 0.627611 -0.326031 -0.733787 0.675547 -0.072070 -0.711859 0.676996 0.186902 -0.643319 0.631053 0.433489 -0.533537 0.539698 0.651202 -0.390397 0.407891 0.825358 -0.223595 0.243626 0.943744 -0.044155 0.057907 0.997345 0.135963 -0.135706 0.981376 0.304509 -0.322286 0.896329 -0.495961 0.553220 0.669306 -0.314504 0.457544 0.831710 -0.113143 0.326964 0.938240 0.094452 0.170397 0.980838 0.294003 -0.000833 0.955804 0.471633 -0.173986 0.864460 0.615019 -0.336168 0.713262 0.714410 -0.475648 0.513202 0.763312 -0.582825 0.278694 0.758760 -0.650841 0.026251 0.701328 -0.675809 -0.226763 0.594969 -0.656822 -0.463246 0.446765 -0.595821 -0.667382 0.266545 -0.497357 -0.825584 0.066347 -0.368236 -0.927362 -0.140345 -0.217072 -0.966014 -0.339485 -0.053745 -0.939075 -0.517425 0.111204 -0.848472 -0.661888 0.267168 -0.700375 -0.762840 0.404078 -0.504773 -0.813254 0.512941 -0.274790 -0.809631 0.586371 -0.025817 -0.752290 0.619021 0.225550 -0.645271 0.608006 0.462551 -0.771939 0.163174 -0.614398 -0.854100 0.310440 -0.417301 -0.879239 0.436156 -0.191590 -0.845545 0.531772 0.047666 -0.755190 0.590548 0.284501 -0.614166 0.608082 0.503027 -0.431908 0.582653 0.688456 -0.220697 0.515513 0.827973 0.005099 0.410938 0.911649 0.229940 0.276064 0.933229 0.438188 0.120427 0.890780 0.615298 -0.044796 0.787021 0.748967 -0.207736 0.629202 0.830078 -0.356863 0.428508 0.853317 -0.481878 0.199109 0.817416 -0.574441 -0.042984 0.725122 -0.628636 -0.281097 0.582889 -0.641260 -0.499026 0.400445 -0.611887 -0.682084 0.190140 -0.542820 -0.818042 -0.033849 -0.438878 -0.897909 -0.256431 -0.307054 -0.916494 -0.462594 -0.156063 -0.872726 -0.638404 0.004181 -0.769690 0.337701 -0.633106 -0.696516 0.106970 -0.582848 -0.805510 -0.130987 -0.493651 -0.859739 -0.360143 -0.371554 -0.855713 -0.565077 -0.224707 -0.793848 -0.731975 -0.062859 -0.678425 -0.849574 0.103252 -0.517265 -0.909883 0.262560 -0.321207 -0.908733 0.404369 -0.103396 -0.846061 0.519037 0.121582 -0.725936 0.598622 0.338628 -0.556318 0.637437 0.533090 -0.348567 0.632499 0.691698 -0.116743 0.583812 0.803452 0.123299 0.494477 0.860401 0.354973 0.370563 0.858299 0.562165 0.220697 0.797034 0.730442 0.055449 0.680720 0.848154 -0.113516 0.517444 0.907301 -0.274369 0.318632 0.904046 -0.416010 0.098162 0.838902 -0.528851 -0.128686 0.716582 -0.605444 -0.346335 0.545611 -0.640893 -0.539967 0.914533 -0.056957 0.400481 0.950947 -0.229956 0.206930 0.922554 -0.385864 -0.001454 0.831552 -0.514094 -0.210303 0.684376 -0.606098 -0.405308 0.491201 -0.655871 -0.573196 0.265234 -0.660287 -0.702618 0.021816 -0.619245 -0.784895 -0.222598 -0.535641 -0.814579 -0.451525 -0.415146 -0.789797 -0.649535 -0.265842 -0.712343 -0.803276 -0.097696 -0.587540 -0.902359 0.078069 -0.423855 -0.940043 0.249685 -0.232327 -0.913687 0.405596 -0.025840 -0.824940 0.535208 0.181733 -0.679648 0.629596 0.376414 -0.487498 0.682128 0.545020 -0.261423 0.688943 0.676029 -0.016779 0.649309 0.760339 0.229668 0.565732 0.791960 0.460890 0.443863 0.768483 0.660828 0.292150 0.691342 0.815599 0.121217 0.565778 -0.182250 0.737753 0.650004 0.069488 0.700412 0.710348 0.317239 0.616256 0.720824 0.543901 0.490984 0.680519 0.733768 0.333251 0.592054 0.873692 0.154070 0.461438 0.954064 -0.034050 0.297662 0.969487 -0.218046 0.112034 0.919095 -0.385273 -0.082642 0.806539 -0.524380 -0.272983 0.639665 -0.626061 -0.445956 0.429941 -0.683614 -0.589765 0.191669 -0.693344 -0.694649 -0.058972 -0.654756 -0.753537 -0.305005 -0.570556 -0.762521 -0.529794 -0.446463 -0.721103 -0.718148 -0.290824 -0.632206 -0.857339 -0.114076 -0.501952 -0.937953 0.071934 -0.339219 -0.954509 0.254711 -0.155030 -0.905826 0.421924 0.038193 -0.795099 0.562217 0.227441 -0.629701 0.665962 0.399964 -0.420718 0.725916 0.544098 -0.961981 0.071022 -0.263719 -0.960728 0.263099 -0.088202 -0.893844 0.438920 0.091614 -0.765810 0.586550 0.263617 -0.585219 0.695889 0.416242 -0.364216 0.759357 0.539187 -0.117732 0.772429 0.624094 0.137476 0.733997 0.665092 0.383938 0.646527 0.659238 0.604675 0.515942 0.606771 0.784437 0.351253 0.511156 0.910818 0.163907 0.378874 0.975166 -0.033083 0.218990 0.973176 -0.226105 0.042487 0.905130 -0.401937 -0.138513 0.775815 -0.548653 -0.311594 0.594148 -0.656396 -0.464900 0.372551 -0.718004 -0.587943 0.126123 -0.729435 -0.672323 -0.128377 -0.690025 -0.712309 -0.373657 -0.602512 -0.705237 -0.593067 -0.472844 -0.651682 -0.771722 -0.309785 -0.555409 -0.897529 -0.124332 -0.423063 0.074867 -0.762766 -0.642326 -0.181669 -0.722147 -0.667458 -0.425525 -0.631418 -0.648259 -0.640081 -0.496758 -0.586113 -0.810734 -0.327319 -0.485357 -0.925904 -0.134599 -0.352966 -0.977811 0.068338 -0.198029 -0.962987 0.267748 -0.031111 -0.882476 0.450121 0.136481 -0.741741 0.603082 0.293448 -0.550283 0.716206 0.429229 -0.321022 0.781709 0.534673 -0.069467 0.794994 0.602627 0.187290 0.755003 0.628406 0.431704 0.664345 0.610145 0.647001 0.529173 0.548968 0.818364 0.358777 0.448954 0.934016 0.164923 0.316882 0.986057 -0.039014 0.161768 0.970997 -0.239022 -0.005778 0.889948 -0.421445 -0.174286 0.748510 -0.573902 -0.332218 0.556359 -0.686097 -0.468759 0.326595 -0.750488 -0.574547 0.991997 -0.042510 0.118889 0.967939 -0.247870 -0.040669 0.878031 -0.435526 -0.198442 0.728415 -0.592722 -0.343645 0.529280 -0.708795 -0.466339 0.294178 -0.775873 -0.558105 0.039127 -0.789399 -0.612632 -0.218469 -0.748453 -0.626170 -0.461011 -0.655825 -0.597799 -0.671923 -0.517830 -0.529502 -0.836808 -0.343885 -0.426023 -0.944453 -0.145850 -0.294509 -0.987584 0.062786 -0.143996 -0.963343 0.267839 0.015236 -0.873448 0.455384 0.172378 -0.724043 0.612695 0.316807 -0.525267 0.729077 0.438795 -0.290581 0.796581 0.530114 -0.035884 0.810544 0.584578 0.221521 0.769924 0.598452 0.464089 0.677418 0.570724 0.675233 0.539304 0.503201 0.840487 0.365032 0.400417 0.948533 0.166558 0.269338 -0.014308 0.822229 0.568977 0.243406 0.782230 0.573472 0.484689 0.689351 0.538398 0.693090 0.549896 0.466091 0.854380 0.373369 0.361428 0.957540 0.171823 0.231502 0.995526 -0.040979 0.085144 0.965742 -0.250522 -0.067681 0.870213 -0.442531 -0.216553 0.715428 -0.603941 -0.351310 0.511906 -0.723762 -0.462732 0.273489 -0.793830 -0.543175 0.016424 -0.809345 -0.587103 -0.241740 -0.769227 -0.591482 -0.483347 -0.676193 -0.556003 -0.691863 -0.536589 -0.483113 -0.853031 -0.359960 -0.377845 -0.955868 -0.158381 -0.247452 -0.993411 0.054376 -0.100889 -0.963182 0.263810 0.051824 -0.867321 0.455670 0.200297 -0.712411 0.616928 0.334470 -0.509007 0.736638 0.445281 -0.270922 0.806667 0.525253 -0.996767 0.043479 -0.067562 -0.963292 0.256256 0.080009 -0.864160 0.451766 0.221665 -0.706191 0.616717 0.347785 -0.500177 0.739916 0.449831 -0.260140 0.813008 0.520908 -0.002392 0.831034 0.556216 0.255563 0.792765 0.553364 0.496191 0.700787 0.512535 0.703119 0.561345 0.436480 0.862251 0.383924 0.330341 0.962732 0.180605 0.201317 0.997701 -0.034762 0.058171 0.964757 -0.247505 -0.089361 0.866118 -0.443139 -0.231230 0.708473 -0.608337 -0.357761 0.502524 -0.731840 -0.460304 0.262275 -0.805213 -0.531831 0.004096 -0.823417 -0.567422 -0.254392 -0.785177 -0.564607 -0.495512 -0.693074 -0.523562 -0.702759 -0.553385 -0.447096 -0.861953 -0.375662 -0.340462 -0.962224 -0.172066 -0.210991 -0.000960 -0.833084 -0.553145 -0.259652 -0.797547 -0.544518 -0.500651 -0.707421 -0.498902 -0.707475 -0.568843 -0.419401 -0.865966 -0.391275 -0.311458 -0.965291 -0.186863 -0.182472 -0.998685 0.030413 -0.041282 -0.963915 0.245707 0.102452 -0.863417 0.444329 0.238919 -0.704106 0.612760 0.358830 -0.496882 0.739559 0.454050 -0.255873 0.816128 0.518135 0.002520 0.837286 0.546759 0.260736 0.801610 0.537995 0.501227 0.711527 0.492444 0.707642 0.573161 0.413194 0.865936 0.395918 0.305619 0.965326 0.191855 0.177021 0.999031 -0.025138 0.036135 0.964734 -0.240291 -0.107461 0.864746 -0.438955 -0.243992 0.705845 -0.607598 -0.364153 0.498820 -0.734722 -0.459742 0.257746 -0.811642 -0.524217 0.999765 -0.013135 0.017249 0.965306 -0.229921 -0.123774 0.865129 -0.431004 -0.256492 0.706031 -0.602689 -0.371870 0.498819 -0.733278 -0.462041 0.257583 -0.813861 -0.520847 -0.001263 -0.838921 -0.544252 -0.260078 -0.806715 -0.530633 -0.501202 -0.719405 -0.480888 -0.708155 -0.582923 -0.398394 -0.866780 -0.406571 -0.288778 -0.966222 -0.202394 -0.159534 -0.999687 0.015651 -0.019506 -0.964909 0.232664 0.121726 -0.864303 0.433825 0.254512 -0.704781 0.605421 0.369797 -0.497264 0.735776 0.459741 -0.255922 0.816043 0.518244 0.002799 0.840790 0.541354 0.261294 0.808358 0.527525 0.501989 0.720970 0.477713 0.708518 0.584578 0.395312 0.866838 0.408460 0.285924 0.966176 0.204599 0.156981 0.000768 0.841467 0.540308 0.259504 0.812676 0.521742 0.500529 0.728540 0.467654 0.707448 0.594805 0.381739 0.866193 0.420581 0.269854 0.965972 0.217730 0.139614 1.000000 0.000059 -0.000122 0.965964 -0.217616 -0.139849 0.866177 -0.420478 -0.270065 0.707426 -0.594721 -0.381912 0.500502 -0.728479 -0.467777 0.259475 -0.812643 -0.521809 0.000738 -0.841464 -0.540313 -0.258099 -0.812955 -0.522004 -0.499399 -0.729027 -0.468104 -0.706694 -0.595367 -0.382258 -0.865816 -0.421068 -0.270305 -0.965870 -0.218011 -0.139878 -1.000000 -0.000058 0.000114 -0.965864 0.217899 0.140098 -0.865802 0.420968 0.270503 -0.706675 0.595286 0.382419 -0.499375 0.728971 0.468216 -0.258072 0.812928 0.522060 -0.999680 -0.015769 0.019768 -0.966204 0.202273 0.159801 -0.866750 0.406454 0.289031 -0.708116 0.582818 0.398616 -0.501157 0.719320 0.481063 -0.260030 0.806654 0.530748 -0.001215 0.838890 0.544300 0.257627 0.813862 0.520823 0.498857 0.733311 0.461948 0.706058 0.602753 0.371713 0.865145 0.431095 0.256283 0.965311 0.230033 0.123526 0.999759 0.013261 -0.017518 0.966159 -0.204467 -0.157255 0.866812 -0.408333 -0.286183 0.708485 -0.584464 -0.395540 0.501951 -0.720877 -0.477894 0.261254 -0.808291 -0.527647 0.002758 -0.840754 -0.541410 -0.255960 -0.816041 -0.518230 -0.497296 -0.735807 -0.459657 -0.704805 -0.605481 -0.369651 -0.864318 -0.433912 -0.254312 -0.964914 -0.232770 -0.121487 0.002440 -0.837224 -0.546855 -0.255947 -0.816091 -0.518158 -0.496945 -0.739549 -0.453998 -0.704154 -0.612778 -0.358707 -0.863446 -0.444373 -0.238733 -0.963923 -0.245772 -0.102217 -0.998671 -0.030497 0.041550 -0.965255 0.186768 0.182757 -0.865911 0.391175 0.311739 -0.707402 0.568744 0.419659 -0.500567 0.707330 0.499116 -0.259560 0.797468 0.544677 -0.000870 0.833025 0.553234 0.257830 0.811606 0.524232 0.498891 0.734711 0.459681 0.705899 0.607615 0.364020 0.864780 0.438999 0.243795 0.964745 0.240359 0.107215 0.999018 0.025225 -0.036413 0.965293 -0.191754 -0.177314 0.865884 -0.395810 -0.305907 0.707576 -0.573054 -0.413456 0.501151 -0.711428 -0.492663 0.260656 -0.801526 -0.538158 0.997678 0.034827 -0.058521 0.962671 -0.180519 -0.201687 0.862157 -0.383823 -0.330705 0.702999 -0.561237 -0.436813 0.496052 -0.700679 -0.512817 0.255415 -0.792665 -0.553575 -0.002538 -0.830950 -0.556342 -0.260277 -0.812944 -0.520940 -0.500292 -0.739875 -0.449769 -0.706279 -0.616703 -0.347631 -0.864214 -0.451778 -0.221430 -0.963307 -0.256293 -0.079709 -0.996741 -0.043538 0.067907 -0.962158 0.171988 0.211357 -0.861849 0.375571 0.340826 -0.702624 0.553286 0.447430 -0.495354 0.692973 0.523844 -0.254224 0.785081 0.564817 0.004263 0.823332 0.567543 0.262430 0.805144 0.531858 0.502654 0.731795 0.460233 0.708571 0.608318 0.357598 0.866178 0.443149 0.230987 0.964775 0.247545 0.089053 0.016693 0.809220 0.587269 0.273736 0.793711 0.543223 0.512114 0.723661 0.462659 0.715584 0.603865 0.351122 0.870307 0.442487 0.216264 0.965771 0.250512 0.067309 0.995488 0.041006 -0.085572 0.957440 -0.171765 -0.231958 0.854226 -0.373281 -0.361883 0.692892 -0.549788 -0.466513 0.484460 -0.689229 -0.538759 0.243163 -0.782102 -0.573749 -0.014550 -0.822105 -0.569150 -0.271146 -0.806553 -0.525311 -0.509198 -0.736543 -0.445221 -0.712556 -0.616855 -0.334294 -0.867409 -0.455625 -0.200018 -0.963205 -0.263794 -0.051461 -0.993367 -0.054392 0.101311 -0.955757 0.158337 0.247906 -0.852861 0.359888 0.378298 -0.691643 0.536494 0.483534 -0.483092 0.676080 0.556362 -0.241469 0.769104 0.591753 -0.987522 -0.062700 0.144458 -0.944292 0.145903 0.294999 -0.836556 0.343899 0.426507 -0.671594 0.517802 0.529947 -0.460627 0.655753 0.598173 -0.218057 0.748342 0.626446 0.039538 0.789255 0.612792 0.294558 0.775706 0.558136 0.529604 0.708618 0.466241 0.728661 0.592548 0.343424 0.878184 0.435366 0.198115 0.967990 0.247737 0.040260 0.991946 0.042410 -0.119352 0.948385 -0.166618 -0.269823 0.840254 -0.365051 -0.400889 0.674933 -0.539281 -0.503629 0.463743 -0.677356 -0.571079 0.221152 -0.769830 -0.598710 -0.036249 -0.810423 -0.584723 -0.290917 -0.796443 -0.530138 -0.525553 -0.728931 -0.438696 -0.724259 -0.612551 -0.316591 -0.873580 -0.455252 -0.172057 -0.963381 -0.267726 -0.014833 -0.069962 -0.794901 -0.602692 -0.321472 -0.781588 -0.534580 -0.550658 -0.716067 -0.428980 -0.742015 -0.602936 -0.293057 -0.882628 -0.449977 -0.135970 -0.963004 -0.267616 0.031709 -0.977687 -0.068229 0.198679 -0.925641 0.134676 0.353625 -0.810348 0.327356 0.485978 -0.639593 0.496748 0.586653 -0.424971 0.631361 0.648679 -0.181088 0.722045 0.667727 0.075435 0.762625 0.642428 0.327108 0.750318 0.574477 0.556785 0.685912 0.468525 0.748822 0.573714 0.331839 0.890130 0.421267 0.173791 0.971039 0.238864 0.005204 0.985962 0.038881 -0.162380 0.933792 -0.165022 -0.317491 0.818028 -0.358840 -0.449516 0.646577 -0.529195 -0.549446 0.431223 -0.664326 -0.610507 0.186783 -0.754944 -0.628627 0.975037 0.032843 -0.219602 0.910535 -0.164113 -0.379464 0.784022 -0.351414 -0.511681 0.604159 -0.516041 -0.607201 0.383357 -0.646560 -0.659543 0.136875 -0.733963 -0.665255 -0.118313 -0.772330 -0.624106 -0.364739 -0.759206 -0.539047 -0.585649 -0.695696 -0.415960 -0.766120 -0.586329 -0.263207 -0.894010 -0.438687 -0.091098 -0.960737 -0.262870 0.088792 -0.961825 -0.070811 0.264345 -0.897212 0.124508 0.423685 -0.771261 0.309913 0.555976 -0.592490 0.472912 0.652158 -0.373007 0.602512 0.705581 -0.127700 0.689958 0.712496 0.126780 0.729303 0.672342 0.373143 0.717817 0.587795 0.594635 0.656169 0.464598 0.776167 0.548401 0.311161 0.905329 0.401673 0.137983 0.973210 0.225845 -0.043078 0.192331 0.693317 0.694493 0.430520 0.683527 0.589443 0.640124 0.625922 0.445491 0.806852 0.524197 0.272409 0.919243 0.385058 0.081998 0.969462 0.217809 -0.112703 0.953869 0.033806 -0.298313 0.873340 -0.154303 -0.462026 0.733284 -0.333453 -0.592541 0.543320 -0.491132 -0.680877 0.316601 -0.616343 -0.721030 0.068841 -0.700424 -0.710399 -0.182861 -0.737692 -0.649901 -0.421255 -0.725791 -0.543849 -0.630132 -0.665779 -0.399589 -0.795396 -0.561992 -0.226959 -0.905968 -0.421670 -0.037634 -0.954483 -0.254443 0.155632 -0.937753 -0.071670 0.339828 -0.856974 0.114321 0.502521 -0.717638 0.291034 0.632688 -0.529176 0.446623 0.721457 -0.304323 0.570657 0.762717 -0.058274 0.654792 0.753559 -0.902020 -0.077782 0.424630 -0.802736 0.097963 0.588234 -0.648826 0.266069 0.712904 -0.450698 0.415316 0.790179 -0.221714 0.535742 0.814754 0.022692 0.619272 0.784849 0.266042 0.660238 0.702358 0.491889 0.655749 0.572746 0.684901 0.605907 0.404706 0.831889 0.513840 0.209594 0.922687 0.385550 0.000692 0.950868 0.229598 -0.207691 0.914249 0.056568 -0.401183 0.815127 -0.121610 -0.566373 0.660203 -0.292521 -0.691783 0.460159 -0.444170 -0.768743 0.228885 -0.565955 -0.792027 -0.017560 -0.649438 -0.760212 -0.262146 -0.688970 -0.675721 -0.488116 -0.682058 -0.544555 -0.680120 -0.629446 -0.375812 -0.825235 -0.534991 -0.181029 -0.913781 -0.405334 0.026615 -0.939921 -0.249400 0.233129 -0.349247 -0.632519 -0.691337 -0.556881 -0.637372 -0.532580 -0.726345 -0.598484 -0.337994 -0.846283 -0.518843 -0.120858 -0.908746 -0.404139 0.104174 -0.909676 -0.262314 0.321994 -0.849156 -0.103005 0.518000 -0.731370 0.063088 0.679056 -0.564328 0.224909 0.794323 -0.359319 0.371717 0.855989 -0.130149 0.493771 0.859797 0.107762 0.582925 0.805348 0.338386 0.633138 0.696154 0.546152 0.640881 0.539434 0.716954 0.605382 0.345673 0.839089 0.528735 0.127944 0.904044 0.415831 -0.098937 0.907109 0.274129 -0.319385 0.847780 0.113223 -0.518120 0.729904 -0.055769 -0.681271 0.561497 -0.221012 -0.797417 0.354222 -0.370836 -0.858492 0.122517 -0.494683 -0.860394 -0.117498 -0.583927 -0.803258 0.748508 0.207609 -0.629789 0.614718 0.044609 -0.787485 0.437520 -0.120643 -0.891079 0.229227 -0.276277 -0.933341 0.004392 -0.411110 -0.911575 -0.221351 -0.515624 -0.827730 -0.432470 -0.582700 -0.688063 -0.614601 -0.608071 -0.502509 -0.755466 -0.590496 -0.283875 -0.845635 -0.531691 -0.046962 -0.879121 -0.436066 0.192338 -0.853769 -0.310350 0.418044 -0.771411 -0.163095 0.615081 -0.637722 -0.004116 0.770256 -0.461819 0.156114 0.873128 -0.255630 0.307096 0.916703 -0.033092 0.438922 0.897916 0.190792 0.542872 0.817856 0.400950 0.611952 0.681728 0.583225 0.641336 0.498534 0.725284 0.628713 0.280506 0.817412 0.574497 0.042329 0.853152 0.481889 -0.199789 0.829761 0.356810 -0.429166 0.447113 0.595838 0.667134 0.595106 0.656935 0.462910 0.701273 0.676001 0.226361 0.758540 0.651079 -0.026702 0.762955 0.583059 -0.279178 0.713937 0.475833 -0.513690 0.614444 0.336275 -0.713707 0.470980 0.174012 -0.864811 0.293307 0.000811 -0.956018 0.093760 -0.170437 -0.980898 -0.113789 -0.326998 -0.938150 -0.315063 -0.457558 -0.831490 -0.496403 -0.553226 -0.668973 -0.645565 -0.608031 -0.462108 -0.752404 -0.619080 -0.225008 -0.809532 -0.586481 0.026444 -0.812922 -0.513103 0.275468 -0.762281 -0.404288 0.505449 -0.661137 -0.267414 0.700991 -0.516547 -0.111466 0.848973 -0.338562 0.053489 0.939423 -0.139471 0.216851 0.966190 0.067097 0.368073 0.927373 0.267108 0.497277 0.825451 -0.516079 -0.409797 0.752149 -0.366374 -0.253696 0.895214 -0.193918 -0.078904 0.977839 -0.011020 0.103486 0.994570 0.169481 0.281786 0.944390 0.335186 0.444392 0.830763 0.475032 0.580494 0.661341 0.580005 0.680771 0.447375 0.643608 0.737969 0.202905 0.662032 0.747374 -0.056092 0.634200 0.707193 -0.312521 0.561765 0.618939 -0.548940 0.449186 0.487787 -0.748529 0.303733 0.322718 -0.896437 0.135198 0.136095 -0.981427 -0.044863 -0.057553 -0.997334 -0.224206 -0.243307 -0.943681 -0.390883 -0.407631 -0.825256 -0.533870 -0.539542 -0.651059 -0.643473 -0.631031 -0.433292 -0.711805 -0.677126 -0.186639 -0.733500 -0.675823 0.072396 -0.706450 -0.628009 0.326394 -0.632235 -0.537304 0.558197 -0.558788 -0.521417 -0.644888 -0.623337 -0.653087 -0.430033 -0.648364 -0.738363 -0.185593 -0.630970 -0.772474 0.071846 -0.571398 -0.753728 0.324650 -0.473415 -0.683615 0.555472 -0.344047 -0.566758 0.748610 -0.192926 -0.410641 0.891153 -0.031325 -0.225231 0.973802 0.128841 -0.022439 0.991411 0.276063 0.184548 0.943256 0.400176 0.382101 0.832981 0.493130 0.557059 0.668212 0.549443 0.697604 0.459850 0.566294 0.793959 0.221227 0.543322 0.838890 -0.032642 0.482353 0.828109 -0.285605 0.387241 0.760807 -0.520785 0.263883 0.640358 -0.721323 0.120212 0.474872 -0.871806 -0.034207 0.276997 -0.960262 -0.189015 0.062505 -0.979983 -0.334054 -0.151951 -0.930225 -0.460043 -0.350930 -0.815603 0.078127 0.767537 -0.636226 -0.065628 0.607085 -0.791922 -0.207587 0.404887 -0.890491 -0.338366 0.176870 -0.924243 -0.449623 -0.059552 -0.891231 -0.534417 -0.287612 -0.794782 -0.587216 -0.492381 -0.642447 -0.603944 -0.661149 -0.445122 -0.582362 -0.783580 -0.216463 -0.522697 -0.852067 0.027735 -0.428149 -0.862262 0.270543 -0.304989 -0.813484 0.495203 -0.162111 -0.708871 0.686456 -0.010189 -0.555226 0.831637 0.139335 -0.362618 0.921463 0.275322 -0.143789 0.950538 0.387952 0.086661 0.917596 0.469566 0.313295 0.825442 0.515225 0.520965 0.680543 0.522850 0.695853 0.492358 0.492975 0.826240 0.272586 0.428311 0.902969 0.034579 0.333328 0.919822 -0.206927 0.214076 0.874103 -0.436023 0.547527 0.478642 0.686379 0.511248 0.678067 0.528064 0.438547 0.833497 0.336093 0.334704 0.934398 0.121959 0.206612 0.973180 -0.101153 0.062549 0.945844 -0.318539 -0.088041 0.852913 -0.514575 -0.235032 0.700270 -0.674078 -0.368466 0.499157 -0.784267 -0.479529 0.264947 -0.836573 -0.561211 0.015080 -0.827535 -0.608502 -0.232879 -0.758613 -0.618295 -0.462497 -0.635459 -0.589408 -0.659053 -0.467169 -0.522821 -0.809985 -0.265674 -0.422063 -0.905446 -0.045068 -0.293369 -0.939031 0.179317 -0.145487 -0.908362 0.392061 0.010996 -0.815381 0.578820 0.164553 -0.666276 0.727323 0.303777 -0.471096 0.828123 0.418418 -0.243084 0.875121 0.500325 0.002255 0.865835 0.544121 0.248313 0.801419 0.164474 -0.880380 0.444837 0.320179 -0.736307 0.596102 0.451427 -0.541987 0.708847 0.548756 -0.310786 0.776067 0.605395 -0.058549 0.793769 0.617781 0.197608 0.761116 0.585703 0.440577 0.680327 0.512044 0.654401 0.556390 0.402277 0.825103 0.396709 0.263913 0.941222 0.210836 0.106075 0.994305 0.010316 -0.060836 0.979598 -0.191538 -0.225588 0.896948 -0.380255 -0.376872 0.751529 -0.541453 -0.504320 0.553806 -0.662541 -0.599475 0.318463 -0.734309 -0.656360 0.062639 -0.751843 -0.671570 -0.195806 -0.714600 -0.644149 -0.439551 -0.625993 -0.575526 -0.652611 -0.492817 -0.469602 -0.821000 -0.324706 -0.332844 -0.933484 -0.133501 -0.174146 -0.982401 0.067545 -0.004366 -0.964315 0.264722 -0.660582 -0.423286 -0.620048 -0.559012 -0.642860 -0.523675 -0.420599 -0.818815 -0.390690 -0.254199 -0.939284 -0.230497 -0.070847 -0.996016 -0.054150 0.116899 -0.985065 0.126417 0.295883 -0.907157 0.299199 0.453378 -0.767677 0.452902 0.578137 -0.576293 0.577619 0.661328 -0.346232 0.665408 0.697260 -0.093279 0.710723 0.683782 0.165420 0.710689 0.622302 0.412608 0.665203 0.517465 0.632032 0.576859 0.376611 0.809290 0.450792 0.209209 0.932458 0.294539 0.026368 0.992674 0.117907 -0.159652 0.984879 -0.067269 -0.336113 0.908655 -0.247737 -0.490768 0.768824 -0.409947 -0.612971 0.575331 -0.541536 -0.694620 0.342267 -0.632737 -0.730636 0.086332 -0.677287 -0.718999 -0.174717 -0.672692 -0.425651 0.896701 -0.121440 -0.581988 0.761446 -0.285466 -0.698752 0.573104 -0.428132 -0.768270 0.345241 -0.539046 -0.786319 0.094007 -0.610626 -0.752104 -0.163266 -0.638501 -0.668034 -0.409218 -0.621508 -0.539519 -0.627404 -0.561501 -0.374783 -0.803176 -0.463083 -0.184562 -0.924600 -0.333244 0.018431 -0.983330 -0.180893 0.220302 -0.975296 -0.016258 0.406992 -0.901068 0.149781 0.565364 -0.765830 0.306377 0.684240 -0.579000 0.443368 0.755295 -0.353507 0.551872 0.773711 -0.104810 0.624808 0.738489 0.150267 0.657308 0.652388 0.394728 0.646977 0.521547 0.612469 0.594029 0.354915 0.789129 0.501308 0.163661 0.912762 0.374273 -0.039406 0.974492 0.220937 -0.240485 0.969277 0.051656 0.674217 0.383452 0.631186 0.521532 0.593220 0.613266 0.333517 0.763355 0.553223 0.122790 0.882297 0.454394 -0.096416 0.941482 0.322979 -0.309042 0.936108 0.167912 -0.500240 0.865887 0.000370 -0.656644 0.735436 -0.167189 -0.767575 0.554027 -0.322308 -0.825866 0.334657 -0.453817 -0.828146 0.092760 -0.552784 -0.774715 -0.155067 -0.613001 -0.669272 -0.392122 -0.631122 -0.518657 -0.602510 -0.606611 -0.332591 -0.772027 -0.541625 -0.123280 -0.889087 -0.440824 0.095239 -0.945606 -0.311061 0.308016 -0.937667 -0.160957 0.500281 -0.865863 -0.000357 0.658564 -0.735260 0.160268 0.771752 -0.554998 0.310447 0.831959 -0.337571 0.440331 0.835118 -0.097871 0.541294 0.781226 0.147918 0.606470 0.577365 -0.802484 -0.150561 0.734944 -0.677949 0.015543 0.842746 -0.507222 0.180292 0.893268 -0.302184 0.332801 0.883104 -0.076887 0.462834 0.813135 0.153505 0.561470 0.688331 0.373747 0.621702 0.517267 0.569410 0.638911 0.311479 0.727592 0.611221 0.084797 0.837524 0.539780 -0.147361 0.891226 0.428954 -0.368890 0.884272 0.286326 -0.564199 0.816531 0.122294 -0.719612 0.692512 -0.050848 -0.824621 0.521061 -0.220217 -0.872632 0.314438 -0.373687 -0.861111 0.087106 -0.500900 -0.791336 -0.145418 -0.593835 -0.668071 -0.367495 -0.647015 -0.499277 -0.564195 -0.657576 -0.295845 -0.722149 -0.625281 -0.071132 -0.830469 -0.552505 0.159773 -0.881613 -0.444108 0.381062 -0.872032 -0.307167 -0.668566 -0.332470 -0.665195 -0.485112 -0.509151 -0.710937 -0.267680 -0.650032 -0.711200 -0.030528 -0.745266 -0.666068 0.210404 -0.788151 -0.578401 0.438579 -0.775736 -0.453742 0.638123 -0.709069 -0.300034 0.795046 -0.593065 -0.127189 0.898329 -0.436055 0.053493 0.940780 -0.249066 0.230000 0.919552 -0.044927 0.390391 0.836282 0.162701 0.523604 0.696820 0.360239 0.620217 0.510674 0.534932 0.673097 0.290332 0.675391 0.677904 0.050598 0.772067 0.633523 -0.192132 0.817830 0.542438 -0.420847 0.808728 0.410910 -0.619287 0.744732 0.248711 -0.773518 0.630093 0.068203 -0.873248 0.473006 -0.117063 -0.912472 0.284699 -0.293838 -0.889444 0.078306 -0.450286 -0.806279 -0.132134 -0.576589 -0.664268 0.643081 0.381045 -0.818207 0.541809 0.192302 -0.914380 0.404743 -0.009607 -0.947313 0.241675 -0.210217 -0.915921 0.063973 -0.396228 -0.822951 -0.116253 -0.556091 -0.674557 -0.286776 -0.680244 -0.480106 -0.435874 -0.761257 -0.251977 -0.553069 -0.794118 -0.005109 -0.629994 -0.776583 0.243873 -0.661185 -0.709479 0.477841 -0.644599 -0.596791 0.680482 -0.581764 -0.445528 0.837571 -0.477552 -0.265365 0.938074 -0.339677 -0.068098 0.974997 -0.177966 0.133077 0.945898 -0.003519 0.324446 0.852973 0.172152 0.492748 0.702717 0.337862 0.626130 0.505284 0.483265 0.714943 0.273799 0.599148 0.752367 0.023748 0.677680 0.734974 -0.227695 0.712881 0.663292 -0.462683 0.701353 0.542243 0.709661 0.303518 0.635813 0.505904 0.409570 0.759153 0.267499 0.492416 0.828233 0.010229 0.546526 0.837380 -0.248177 0.567442 0.785123 -0.489090 0.552495 0.674937 -0.694783 0.501630 0.515406 -0.850551 0.417844 0.319327 -0.946253 0.306963 0.101874 -0.976722 0.176894 -0.121338 -0.941277 0.036791 -0.335626 -0.843024 -0.103599 -0.527805 -0.688431 -0.234450 -0.686364 -0.487198 -0.346401 -0.801651 -0.252121 -0.431267 -0.866282 0.001394 -0.482808 -0.875725 0.256255 -0.497399 -0.828811 0.494937 -0.474370 -0.728018 0.700843 -0.415990 -0.579458 0.859572 -0.327122 -0.392590 0.960017 -0.214651 -0.179703 0.995219 -0.086758 0.044849 0.962885 0.047837 0.265637 0.865448 0.180572 0.467326 0.695022 -0.212498 -0.686870 0.857028 -0.141242 -0.495534 0.960815 -0.059270 -0.270781 0.999238 0.027317 -0.027878 0.969763 0.112795 0.216420 0.874553 0.192252 0.445191 0.720069 0.261738 0.642647 0.516358 0.318056 0.795120 0.276453 0.358394 0.891699 0.016052 0.380083 0.924813 -0.246841 0.380745 0.891124 -0.492950 0.358888 0.792590 -0.703790 0.314673 0.636915 -0.864058 0.250351 0.436724 -0.963300 0.170139 0.207619 -0.996238 0.079730 -0.033947 -0.962169 -0.014305 -0.272078 -0.864220 -0.104999 -0.492036 -0.708950 -0.185450 -0.680440 -0.506236 -0.249357 -0.825558 -0.269096 -0.291639 -0.917896 -0.013139 -0.309031 -0.950961 0.244418 -0.300475 -0.921941 0.486008 -0.267198 -0.832107 -0.729089 -0.148496 -0.668116 -0.531097 -0.155106 -0.832993 -0.297932 -0.146047 -0.943349 -0.045035 -0.121748 -0.991539 0.210694 -0.084225 -0.973917 0.452068 -0.036880 -0.891221 0.662812 0.015920 -0.748617 0.828667 0.069390 -0.555425 0.938351 0.118960 -0.324571 0.984363 0.160872 -0.071760 0.963541 0.192649 0.185673 0.877225 0.213257 0.430113 0.730971 0.222863 0.644991 0.533991 0.222295 0.815745 0.298682 0.212436 0.930409 0.040428 0.193870 0.980194 -0.222742 0.166923 0.960480 -0.471306 0.132060 0.872027 -0.686429 0.090369 0.721560 -0.852396 0.043818 0.521058 -0.958243 -0.004776 0.285917 -0.998103 -0.051989 0.032968 -0.970739 -0.094085 -0.220938 -0.878926 -0.127350 -0.459642 -0.647026 -0.146072 0.748345 -0.816819 -0.177965 0.548758 -0.929418 -0.196489 0.312370 -0.978122 -0.200358 0.055976 -0.960786 -0.188892 -0.203002 -0.879480 -0.162133 -0.447468 -0.740172 -0.121038 -0.661434 -0.552387 -0.067643 -0.830838 -0.328711 -0.005129 -0.944417 -0.084040 0.062292 -0.994513 0.165362 0.129653 -0.977673 0.402944 0.191654 -0.894933 0.612947 0.243186 -0.751769 0.781402 0.279858 -0.557755 0.897017 0.298533 -0.325943 0.951921 0.297768 -0.071979 0.942195 0.278035 0.186990 0.868123 0.241629 0.433565 0.734104 0.192213 0.651264 0.548373 0.134141 0.825405 0.322706 0.071807 0.943771 0.072150 0.009254 0.997351 -0.185577 -0.049938 0.981360 -0.431422 -0.102627 0.896294 0.727064 0.152974 0.669311 0.553476 0.043676 0.831719 0.339714 -0.065418 0.938251 0.100328 -0.166927 0.980852 -0.147728 -0.254144 0.955818 -0.386491 -0.321418 0.864474 -0.598636 -0.364520 0.713274 -0.769123 -0.380873 0.513212 -0.886389 -0.369652 0.278698 -0.943012 -0.331723 0.026251 -0.935913 -0.269525 -0.226768 -0.866284 -0.186936 -0.463257 -0.739348 -0.089114 -0.667400 -0.563962 0.017702 -0.825611 -0.352039 0.126497 -0.927398 -0.117780 0.229906 -0.966059 0.123236 0.320700 -0.939129 0.355054 0.392338 -0.848532 0.562353 0.439487 -0.700436 0.731391 0.458493 -0.504829 0.850868 0.447759 -0.274837 0.912638 0.407950 -0.025848 0.912232 0.342006 0.225532 0.849174 0.254864 0.462545 0.527331 0.586961 -0.614328 0.695937 0.584463 -0.417222 0.817367 0.543355 -0.191510 0.883310 0.466352 0.047744 0.889021 0.358697 0.284568 0.833673 0.227793 0.503091 0.720507 0.082664 0.688503 0.556741 -0.066675 0.828006 0.353264 -0.209922 0.911667 0.124027 -0.337186 0.933232 -0.114888 -0.439696 0.890768 -0.346530 -0.510446 0.786995 -0.554470 -0.544716 0.629164 -0.724163 -0.540380 0.428460 -0.844032 -0.497984 0.199055 -0.906224 -0.420603 -0.043039 -0.906991 -0.313565 -0.281150 -0.846786 -0.184073 -0.499071 -0.730108 -0.040759 -0.682115 -0.565127 0.106833 -0.818057 -0.363103 0.248841 -0.897905 -0.137642 0.375679 -0.916471 0.096200 0.478711 -0.872686 0.322878 0.550829 -0.769634 -0.717096 0.024155 -0.696556 -0.558192 0.198833 -0.805536 -0.361954 0.360303 -0.859751 -0.141630 0.497699 -0.855709 0.088011 0.601736 -0.793831 0.311622 0.665338 -0.678393 0.514270 0.684111 -0.517223 0.682377 0.656674 -0.321155 0.804595 0.584763 -0.103338 0.872546 0.473146 0.121643 0.881385 0.329318 0.338689 0.830171 0.163015 0.533144 0.721999 -0.014432 0.691743 0.563908 -0.190850 0.803483 0.366512 -0.354056 0.860415 0.143353 -0.492723 0.858297 -0.090032 -0.597212 0.797015 -0.317274 -0.660306 0.680686 -0.522451 -0.677750 0.517397 -0.691314 -0.648532 0.318576 -0.812334 -0.574882 0.098102 -0.877468 -0.462033 -0.128748 -0.882619 -0.317801 -0.346391 -0.827814 -0.152008 -0.540016 -0.506648 -0.763518 0.400435 -0.674667 -0.708537 0.206881 -0.795478 -0.605980 -0.001503 -0.861015 -0.463041 -0.210350 -0.867088 -0.289572 -0.405347 -0.813591 -0.097387 -0.573224 -0.704418 0.100514 -0.702632 -0.547154 0.290797 -0.784894 -0.352535 0.460659 -0.814563 -0.133715 0.598658 -0.789765 0.094592 0.695474 -0.712298 0.317078 0.744528 -0.587485 0.518831 0.742439 -0.423791 0.686286 0.689251 -0.232258 0.808118 0.588457 -0.025772 0.875977 0.446780 0.181799 0.885060 0.273749 0.376471 0.834464 0.081073 0.545066 0.727316 -0.118124 0.676060 0.570659 -0.310172 0.760356 0.375044 -0.481807 0.791962 0.153885 -0.621106 0.768470 -0.077466 -0.718389 0.691315 -0.302883 -0.766941 0.565742 0.730030 -0.211060 0.650008 0.571821 -0.410401 0.710346 0.375065 -0.582882 0.720816 0.153247 -0.716541 0.680504 -0.078284 -0.802103 0.592032 -0.303417 -0.833690 0.461409 -0.506515 -0.809235 0.297627 -0.673565 -0.730594 0.111993 -0.793186 -0.603340 -0.082686 -0.857372 -0.436312 -0.273030 -0.861986 -0.240957 -0.446004 -0.806962 -0.030553 -0.589813 -0.696250 0.180664 -0.694692 -0.537509 0.378429 -0.753575 -0.341573 0.549402 -0.762552 -0.121712 0.682028 -0.721126 0.107248 0.767330 -0.632221 0.329908 0.799499 -0.501959 0.531299 0.776308 -0.339216 0.697859 0.699258 -0.155020 0.818322 0.573489 0.038202 0.884449 0.407450 0.227452 0.891589 0.212338 0.399976 0.839016 0.001377 0.544105 0.542521 0.797600 -0.263639 0.708227 0.700464 -0.088122 0.827036 0.554620 0.091697 0.890855 0.369917 0.263701 0.895236 0.158846 0.416317 0.839684 -0.064284 0.539257 0.727753 -0.284280 0.624148 0.566857 -0.486078 0.665133 0.367868 -0.655778 0.659263 0.144410 -0.781642 0.606780 -0.088091 -0.854967 0.511148 -0.313524 -0.870731 0.378855 -0.516285 -0.827953 0.218960 -0.682440 -0.729708 0.042450 -0.800679 -0.582853 -0.138552 -0.863066 -0.397498 -0.311630 -0.865528 -0.186290 -0.464928 -0.808070 0.036424 -0.587959 -0.694745 0.255553 -0.672326 -0.533358 0.456249 -0.712296 -0.334924 0.624904 -0.705209 -0.112922 0.750075 -0.651641 0.117616 0.823256 -0.555352 0.341123 0.839470 -0.422996 -0.697979 0.316522 -0.642370 -0.534527 0.518371 -0.667513 -0.334020 0.684186 -0.648321 -0.110120 0.802664 -0.586178 0.121945 0.865733 -0.485423 0.346429 0.869113 -0.353029 0.548128 0.812600 -0.198086 0.713404 0.700060 -0.031159 0.831082 0.539154 0.136444 0.893174 0.340798 0.293422 0.895405 0.118435 0.429212 0.837493 -0.112857 0.534667 0.723212 -0.337346 0.602628 0.560193 -0.539703 0.628414 0.359468 -0.706038 0.610158 0.134754 -0.824899 0.548984 -0.098495 -0.888102 0.448970 -0.324203 -0.891330 0.316897 -0.526834 -0.834430 0.161779 -0.692511 -0.721384 -0.005773 -0.809961 -0.559988 -0.174288 -0.871264 -0.361278 -0.332230 -0.872344 -0.138780 -0.468782 -0.813217 0.092388 -0.574581 -0.532855 -0.837816 0.118871 -0.698662 -0.714294 -0.040692 -0.816209 -0.542599 -0.198469 -0.877523 -0.334426 -0.343676 -0.878462 -0.103933 -0.466372 -0.818986 0.133207 -0.558138 -0.703160 0.360845 -0.612664 -0.538890 0.563450 -0.626196 -0.337391 0.727174 -0.597817 -0.112424 0.840818 -0.529514 0.120661 0.896628 -0.426027 0.345983 0.890821 -0.294506 0.548225 0.823843 -0.143987 0.713674 0.700312 0.015247 0.831131 0.528680 0.172390 0.892648 0.320632 0.316820 0.894034 0.090297 0.438806 0.835136 -0.146695 0.530122 0.719865 -0.374242 0.584583 0.555974 -0.576841 0.598453 0.354568 -0.740647 0.570722 0.129381 -0.854432 0.503196 -0.104168 -0.910397 0.400407 -0.330072 -0.904719 0.269325 0.719173 -0.398820 0.568975 0.555660 -0.601996 0.573449 0.354571 -0.764495 0.538355 0.129591 -0.875225 0.466033 -0.103935 -0.926616 0.361359 -0.330056 -0.915152 0.231428 -0.533334 -0.841616 0.085072 -0.699900 -0.711021 -0.067745 -0.818404 -0.532259 -0.216602 -0.880775 -0.317486 -0.351338 -0.882760 -0.081306 -0.462735 -0.824209 0.160207 -0.543151 -0.709093 0.390585 -0.587052 -0.545251 0.594089 -0.591405 -0.343865 0.756787 -0.555905 -0.118700 0.867537 -0.483000 0.114851 0.918768 -0.377723 0.340837 0.907006 -0.247328 0.543852 0.833109 -0.100771 0.710098 0.702185 0.051929 0.828307 0.523214 0.200386 0.890486 0.308413 0.334539 0.892436 0.072395 0.445327 0.834020 -0.168810 0.525275 0.536087 0.841455 -0.067559 0.703611 0.706066 0.080015 0.823349 0.522452 0.221674 0.887203 0.303165 0.347795 0.890874 0.063150 0.449840 0.834139 -0.181274 0.520914 0.720861 -0.413500 0.556218 0.558728 -0.617751 0.553359 0.358748 -0.780141 0.512523 0.134519 -0.889611 0.436460 -0.098700 -0.938696 0.330316 -0.325016 -0.924039 0.201288 -0.529004 -0.846625 0.058139 -0.696761 -0.711711 -0.089393 -0.816850 -0.528464 -0.231261 -0.881078 -0.309336 -0.357790 -0.885045 -0.069227 -0.460330 -0.828448 0.175515 -0.531854 -0.715111 0.408199 -0.567441 -0.552741 0.612926 -0.564623 -0.352410 0.775678 -0.523575 -0.127808 0.885303 -0.447105 0.105701 0.934296 -0.340468 0.332154 0.919324 -0.210992 -0.720942 0.417402 -0.553189 -0.560802 0.623657 -0.544566 -0.362237 0.787297 -0.498947 -0.138804 0.897108 -0.419441 0.094223 0.945567 -0.311490 0.320908 0.929362 -0.182493 0.525761 0.849629 -0.041292 0.694809 0.711859 0.102453 0.816552 0.525506 0.238928 0.882738 0.303321 0.358846 0.888911 0.060463 0.454072 0.834694 -0.186533 0.518161 0.723801 -0.420875 0.546787 0.563781 -0.626642 0.538025 0.365512 -0.789855 0.492473 0.142472 -0.899416 0.413223 -0.090169 -0.947866 0.305645 -0.316580 -0.931898 0.177043 -0.521342 -0.852582 0.036149 -0.690507 -0.715299 -0.107455 -0.812545 -0.529373 -0.243997 -0.879125 -0.307440 -0.364170 -0.885685 -0.064592 -0.459771 -0.831745 0.182641 -0.524255 -0.511311 -0.859224 0.017150 -0.681837 -0.720947 -0.123828 -0.805897 -0.533610 -0.256497 -0.875030 -0.309952 -0.371822 -0.884511 -0.065185 -0.461942 -0.833668 0.184033 -0.520701 -0.725934 0.420725 -0.544069 -0.568620 0.628747 -0.530423 -0.372431 0.793884 -0.480669 -0.150745 0.904836 -0.398181 0.081304 0.953995 -0.288587 0.307858 0.937988 -0.159378 0.513433 0.857911 -0.019395 0.683991 0.719253 0.121786 0.807905 0.531518 0.254516 0.876755 0.307549 0.369749 0.885890 0.062642 0.459646 0.834732 -0.186507 0.518110 0.726797 -0.422939 0.541192 0.569453 -0.630580 0.527345 0.373411 -0.795319 0.477528 0.152008 -0.905960 0.395133 -0.079696 -0.954981 0.285762 -0.305936 -0.939043 0.156847 0.728220 -0.421428 0.540458 0.573914 -0.631102 0.521856 0.380545 -0.797761 0.467722 0.161284 -0.910082 0.381757 -0.068946 -0.960438 0.269823 -0.294477 -0.945417 0.139536 -0.499964 -0.866046 -0.000240 -0.671422 -0.727731 -0.140000 -0.797180 -0.539884 -0.270239 -0.868675 -0.315284 -0.382098 -0.881033 -0.069207 -0.467965 -0.833395 0.181606 -0.521988 -0.728983 0.420087 -0.540472 -0.574879 0.629992 -0.522134 -0.381556 0.796999 -0.468195 -0.162173 0.909694 -0.382305 0.068314 0.960348 -0.270303 0.294169 0.945470 -0.139827 0.499959 0.866049 0.000211 0.671619 0.727504 0.140234 0.797424 0.539309 0.270668 0.868797 0.314336 0.382602 0.880898 0.067961 0.468402 0.832936 -0.182996 0.522236 0.486268 0.873586 0.019765 0.658345 0.735559 0.159800 0.785425 0.547329 0.289031 0.858822 0.321761 0.398617 0.873533 0.074279 0.481064 0.828580 -0.178205 0.530752 0.727069 -0.418452 0.544306 0.575955 -0.630088 0.520831 0.385567 -0.798707 0.461958 0.168890 -0.912851 0.371724 -0.059319 -0.964777 0.256294 -0.283525 -0.950975 0.123536 -0.488472 -0.872404 -0.017510 -0.660219 -0.734427 -0.157250 -0.787081 -0.546447 -0.286181 -0.860430 -0.321258 -0.395541 -0.875277 -0.074186 -0.477898 -0.830608 0.177968 -0.527654 -0.729450 0.418054 -0.541418 -0.578668 0.629740 -0.518237 -0.388499 0.798609 -0.459665 -0.171868 0.913135 -0.369657 0.056476 0.965470 -0.254317 0.280966 0.951997 -0.121491 -0.726226 0.416562 -0.546875 -0.578713 0.629753 -0.518173 -0.391915 0.800175 -0.454007 -0.178517 0.916220 -0.358710 0.046974 0.969949 -0.238729 0.269200 0.957646 -0.102207 0.472997 0.880083 0.041567 0.644431 0.742496 0.182779 0.771760 0.554246 0.311765 0.846262 0.328182 0.419688 0.862840 0.079763 0.499145 0.820374 -0.174022 0.544703 0.721801 -0.415825 0.553257 0.573883 -0.629144 0.524249 0.386746 -0.799444 0.459691 0.173166 -0.915151 0.364023 -0.052301 -0.968417 0.243790 -0.274305 -0.955649 0.107203 -0.477741 -0.877745 -0.036431 -0.648771 -0.740032 -0.177336 -0.775764 -0.551903 -0.305932 -0.850083 -0.326176 -0.413482 -0.866683 -0.078218 -0.492689 -0.824439 0.175101 -0.538182 -0.468759 -0.881385 -0.058521 -0.637736 -0.743381 -0.201688 -0.763527 -0.554670 -0.330707 -0.837572 -0.328122 -0.436816 -0.854837 -0.079178 -0.512820 -0.814158 0.175209 -0.553578 -0.718316 0.417739 -0.556342 -0.573834 0.631931 -0.520939 -0.390533 0.803242 -0.449762 -0.180859 0.920027 -0.347620 0.040941 0.974320 -0.221413 0.259780 0.962374 -0.079687 0.460739 0.884932 0.067934 0.630084 0.747202 0.211387 0.756217 0.558527 0.340857 0.830487 0.331769 0.447461 0.847799 0.082423 0.523873 0.806978 -0.172453 0.564842 0.710839 -0.415424 0.567565 0.565988 -0.629895 0.531875 0.382340 -0.801243 0.460246 0.172440 -0.917814 0.357606 -0.049406 -0.971701 0.230992 -0.268098 -0.959267 0.089056 0.692524 -0.419098 0.587169 0.550562 -0.633946 0.543133 0.370696 -0.805358 0.462584 0.165200 -0.921663 0.351064 -0.051934 -0.974961 0.216225 -0.265937 -0.961639 0.067290 -0.462248 -0.882612 -0.085573 -0.627499 -0.743268 -0.231942 -0.750418 -0.553115 -0.361853 -0.822611 -0.325137 -0.466473 -0.839154 -0.074906 -0.538712 -0.798930 0.180501 -0.573698 -0.704709 0.423685 -0.569102 -0.562932 0.638121 -0.525271 -0.383263 0.809267 -0.445192 -0.177919 0.925527 -0.334282 0.039150 0.979008 -0.200025 0.253190 0.966045 -0.051488 0.449630 0.887456 0.101263 0.615063 0.748514 0.247838 0.738170 0.558623 0.378213 0.810511 0.330699 0.483436 0.827122 0.080294 0.556258 0.786869 -0.175468 0.591648 0.439473 0.886548 0.144556 0.598501 0.744793 0.295095 0.716088 0.552480 0.426595 0.784198 0.322657 0.530025 0.798173 0.070973 0.598233 0.757062 -0.185394 0.626487 0.663688 -0.428931 0.612811 0.524439 -0.643002 0.558132 0.348816 -0.813002 0.466214 0.148771 -0.927340 0.343378 -0.062108 -0.978222 0.198053 -0.269492 -0.962164 0.040188 -0.459277 -0.880228 -0.119428 -0.618506 -0.737974 -0.269897 -0.736275 -0.545100 -0.400955 -0.804490 -0.314803 -0.503681 -0.818461 -0.062865 -0.571113 -0.777241 0.193462 -0.598723 -0.683688 0.436672 -0.584712 -0.544243 0.650222 -0.530105 -0.368457 0.819655 -0.438641 -0.168319 0.933533 -0.316520 0.042561 0.984182 -0.171972 0.249856 0.968171 -0.014739 -0.653376 0.458124 -0.602679 -0.516071 0.669266 -0.534559 -0.344720 0.834967 -0.428951 -0.151060 0.944098 -0.293019 0.051712 0.989369 -0.135922 0.249818 0.967771 0.031770 0.429816 0.880771 0.198748 0.579490 0.734227 0.353699 0.688679 0.538025 0.486056 0.749969 0.305443 0.586728 0.759202 0.052266 0.648754 0.715764 -0.204280 0.667796 0.622621 -0.446713 0.642488 0.486105 -0.658498 0.574528 0.315473 -0.825180 0.468567 0.122283 -0.935365 0.331872 -0.080393 -0.981491 0.173815 -0.278802 -0.960334 0.005221 -0.459436 -0.873244 -0.162368 -0.609913 -0.726093 -0.317483 -0.719852 -0.528918 -0.449510 -0.781627 -0.295253 -0.549441 -0.790944 -0.041186 -0.610500 -0.747172 0.215808 -0.628618 -0.458993 -0.860879 -0.219576 -0.597342 -0.706553 -0.379427 -0.696319 -0.503351 -0.511642 -0.748984 -0.265275 -0.607167 -0.751634 -0.008798 -0.659521 -0.704097 0.248365 -0.665254 -0.609735 0.488557 -0.624127 -0.475152 0.695413 -0.539103 -0.309684 0.854986 -0.416045 -0.124717 0.956611 -0.263326 0.067114 0.993564 -0.091249 0.252771 0.963460 0.088612 0.419675 0.868390 0.264142 0.556553 0.714790 0.423467 0.654177 0.513023 0.555752 0.705980 0.276711 0.651938 0.708499 0.021835 0.705374 0.661587 -0.234334 0.712313 0.568424 -0.474401 0.672189 0.435292 -0.682026 0.587675 0.271141 -0.843036 0.464514 0.087022 -0.946380 0.311113 -0.104656 -0.984892 0.137965 -0.290901 -0.955783 -0.043071 0.504137 -0.513308 0.694522 0.376568 -0.714674 0.589438 0.221888 -0.867372 0.445457 0.050441 -0.960875 0.272351 -0.126241 -0.988611 0.081927 -0.296179 -0.948451 -0.112779 -0.447720 -0.842920 -0.298383 -0.570351 -0.679103 -0.462082 -0.655461 -0.468216 -0.592574 -0.697027 -0.224849 -0.680879 -0.692093 0.034101 -0.721002 -0.641024 0.290708 -0.710336 -0.547445 0.527314 -0.649803 -0.417940 0.727800 -0.543722 -0.261535 0.878665 -0.399434 -0.089028 0.969868 -0.226784 0.087770 0.995437 -0.037444 0.256836 0.953810 0.155827 0.406742 0.847908 0.340020 0.527409 0.684932 0.502701 0.610763 0.475889 0.632849 0.651262 0.234871 0.721590 0.646242 -0.021878 0.762819 0.596076 -0.277026 0.753625 0.383691 0.820029 0.424657 0.486239 0.646162 0.588257 0.554858 0.428811 0.712920 0.585034 0.182601 0.790185 0.574822 -0.075917 0.814749 0.524944 -0.329344 0.784835 0.438734 -0.560568 0.702336 0.321916 -0.753900 0.572716 0.182239 -0.896120 0.404671 0.029009 -0.977366 0.209556 -0.127492 -0.991839 0.000651 -0.276639 -0.938253 -0.207731 -0.408169 -0.820013 -0.401220 -0.512904 -0.645070 -0.566405 -0.583439 -0.425441 -0.691808 -0.614737 -0.176368 -0.768760 -0.604555 0.084813 -0.792035 -0.553618 0.339978 -0.760212 -0.465551 0.571556 -0.675711 -0.346571 0.763784 -0.544539 -0.205001 0.903747 -0.375788 -0.050642 0.982178 -0.181000 0.105915 0.994018 0.026646 0.254024 0.938674 0.233158 -0.373140 0.618730 -0.691331 -0.273523 0.800968 -0.532574 -0.155109 0.928280 -0.337990 -0.026165 0.992326 -0.120852 0.104409 0.989064 0.104173 0.227704 0.918953 0.321987 0.335410 0.786882 0.517992 0.420363 0.601828 0.679042 0.476983 0.376255 0.794304 0.501617 0.125304 0.855967 0.492731 -0.134192 0.859772 0.450984 -0.384802 0.805321 0.379155 -0.609634 0.696123 0.281974 -0.793432 0.539403 0.165827 -0.923598 0.345642 0.038374 -0.991043 0.127912 -0.091882 -0.990840 -0.098965 -0.216134 -0.922639 -0.319411 -0.325821 -0.790802 -0.518144 -0.413237 -0.604218 -0.681290 -0.472140 -0.375750 -0.797431 -0.498254 -0.121329 -0.858500 -0.489656 0.141254 -0.860398 -0.446935 0.393734 -0.803258 -0.194524 -0.751974 -0.629838 -0.268786 -0.554590 -0.787517 -0.323289 -0.318494 -0.891092 -0.353910 -0.060290 -0.933334 -0.358250 0.201837 -0.911547 -0.335880 0.449588 -0.827681 -0.288400 0.665946 -0.687998 -0.219301 0.836344 -0.502430 -0.133647 0.949529 -0.283783 -0.037639 0.998192 -0.046866 0.061910 0.979354 0.192438 0.158098 0.894518 0.418141 0.244436 0.749548 0.615166 0.315257 0.554262 0.770329 0.366058 0.321795 0.873184 0.393709 0.067739 0.916736 0.396598 -0.190894 0.897925 0.374673 -0.436753 0.817843 0.329413 -0.653283 0.681695 0.263723 -0.825810 0.498485 0.181765 -0.942503 0.280446 0.088747 -0.995157 0.042263 -0.009319 -0.979781 -0.199854 -0.105945 -0.896961 -0.429227 0.292464 -0.685124 0.667136 0.271366 -0.843842 0.462916 0.234783 -0.945322 0.226369 0.184552 -0.982460 -0.026694 0.123431 -0.952276 -0.279168 0.055072 -0.856212 -0.513681 -0.016042 -0.700269 -0.713698 -0.084827 -0.494896 -0.864802 -0.145981 -0.254425 -0.956011 -0.194498 0.004011 -0.980895 -0.226296 0.262033 -0.938152 -0.238718 0.501626 -0.831496 -0.230890 0.706507 -0.668983 -0.203767 0.863089 -0.462121 -0.159915 0.961142 -0.225019 -0.103115 0.994318 0.026429 -0.037876 0.960568 0.275455 0.031044 0.862306 0.505436 0.099009 0.706278 0.700977 0.161771 0.503090 0.848959 0.215635 0.266473 0.939412 0.257562 0.012374 0.966183 0.285239 -0.242129 0.927369 0.297118 -0.479951 0.825450 -0.096808 0.651887 0.752111 -0.036447 0.444202 0.895185 0.028723 0.207467 0.977820 0.095241 -0.042118 0.994563 0.159411 -0.287586 0.944395 0.217380 -0.512399 0.830779 0.265323 -0.701569 0.661366 0.299672 -0.842630 0.447406 0.317398 -0.926323 0.202941 0.316317 -0.946996 -0.056058 0.295424 -0.902816 -0.312487 0.255194 -0.795974 -0.548910 0.197885 -0.632916 -0.748504 0.127634 -0.424430 -0.896420 0.050250 -0.185173 -0.981420 -0.027457 0.067580 -0.997336 -0.098683 0.315769 -0.943690 -0.157679 0.542277 -0.825271 -0.200432 0.732065 -0.651082 -0.224857 0.872738 -0.433322 -0.230594 0.954976 -0.186673 -0.218587 0.973131 0.072357 -0.190670 0.925818 0.326352 -0.149188 0.816215 0.558154 -0.172194 0.744645 -0.644867 -0.253976 0.866364 -0.430011 -0.315331 0.930661 -0.185572 -0.353588 0.932636 0.071867 -0.367151 0.871659 0.324670 -0.355431 0.751733 0.555488 -0.318916 0.581258 0.748620 -0.259273 0.372317 0.891155 -0.179493 0.139661 0.973795 -0.083937 -0.100438 0.991396 0.021733 -0.331415 0.943235 0.130791 -0.537659 0.832957 0.235866 -0.705614 0.668189 0.329458 -0.824629 0.459831 0.404511 -0.887374 0.221217 0.454936 -0.889926 -0.032642 0.476105 -0.831721 -0.285593 0.465384 -0.715694 -0.520769 0.422747 -0.548637 -0.721306 0.351255 -0.341472 -0.871790 0.257075 -0.108809 -0.960246 0.148695 0.132496 -0.979967 0.035461 0.365319 -0.930207 -0.073895 0.573902 -0.815583 0.625670 -0.451395 -0.636223 0.558630 -0.246649 -0.791895 0.454542 -0.022588 -0.890439 0.322501 0.204698 -0.924171 0.173412 0.419275 -0.891144 0.018316 0.606746 -0.794685 -0.132626 0.754852 -0.642346 -0.270442 0.853707 -0.445022 -0.387296 0.896206 -0.216372 -0.476487 0.878741 0.027811 -0.532635 0.801920 0.270598 -0.552016 0.670836 0.495234 -0.532897 0.494762 0.686463 -0.475827 0.286348 0.831621 -0.383807 0.060535 0.921427 -0.262302 -0.166656 0.950486 -0.119045 -0.379419 0.917535 0.036421 -0.563410 0.825374 0.193447 -0.706776 0.680475 0.341106 -0.800807 0.492295 0.468978 -0.840112 0.272528 0.567781 -0.822455 0.034531 0.629892 -0.748600 -0.206962 0.649952 -0.622440 -0.436041 0.140730 -0.713530 0.686345 0.331547 -0.781856 0.527994 0.502477 -0.796635 0.335990 0.641758 -0.757169 0.121830 0.739374 -0.665631 -0.101298 0.787721 -0.527194 -0.318688 0.782535 -0.350300 -0.514712 0.723849 -0.146664 -0.674190 0.616419 0.069470 -0.784348 0.469146 0.282780 -0.836622 0.293630 0.478475 -0.827553 0.102566 0.643430 -0.758602 -0.091360 0.766740 -0.635424 -0.276005 0.840016 -0.467113 -0.439986 0.857828 -0.265602 -0.573020 0.818306 -0.044986 -0.666436 0.723655 0.179404 -0.713813 0.580251 0.392148 -0.711530 0.398243 0.578903 -0.659185 0.190702 0.727398 -0.559780 -0.027469 0.828186 -0.419657 -0.240773 0.875166 -0.248169 -0.434399 0.865858 -0.057005 -0.595385 0.801415 -0.844623 0.297806 0.444886 -0.797684 0.090950 0.596178 -0.695007 -0.119856 0.708943 -0.543437 -0.319738 0.776173 -0.353310 -0.494907 0.793876 -0.137668 -0.633718 0.761215 0.088780 -0.727435 0.680409 0.310774 -0.770573 0.556449 0.513472 -0.760882 0.396743 0.683196 -0.699134 0.210844 0.808063 -0.589006 0.010295 0.878758 -0.437126 -0.191587 0.889531 -0.253145 -0.380331 0.839210 -0.049442 -0.541555 0.731675 0.159772 -0.662664 0.575418 0.359833 -0.734448 0.382297 0.536994 -0.751989 0.166078 0.679381 -0.714744 -0.058714 0.777509 -0.626125 -0.277519 0.824623 -0.492930 -0.476281 0.817108 -0.324793 -0.642043 0.754946 -0.133555 -0.763722 0.642004 0.067527 -0.832919 0.485963 0.264738 -0.036283 0.783702 -0.620077 -0.277234 0.805514 -0.523726 -0.498830 0.773613 -0.390758 -0.686368 0.689734 -0.230577 -0.827182 0.559311 -0.054237 -0.911577 0.391239 0.126328 -0.933601 0.197280 0.299114 -0.891556 -0.008850 0.452824 -0.788188 -0.212579 0.577555 -0.630538 -0.399645 0.665362 -0.429430 -0.557223 0.710698 -0.198640 -0.674876 0.710693 0.046182 -0.745204 0.665236 0.288635 -0.764100 0.576923 0.512580 -0.730727 0.450888 0.702955 -0.647325 0.294661 0.846532 -0.519084 0.118047 0.932798 -0.354093 -0.067124 0.955024 -0.163171 -0.247599 0.911255 0.040667 -0.409830 0.804783 0.243229 -0.541446 0.643759 0.430454 -0.632679 0.440109 0.589594 -0.677261 0.208204 0.710023 -0.672695 0.989393 -0.079745 -0.121422 0.950437 0.123291 -0.285427 0.845724 0.318602 -0.428071 0.683160 0.492756 -0.538965 0.474620 0.634024 -0.610532 0.234715 0.733046 -0.638398 -0.020319 0.783228 -0.621403 -0.273534 0.781029 -0.561403 -0.508134 0.726246 -0.462998 -0.708412 0.622209 -0.333180 -0.860781 0.475760 -0.180853 -0.954772 0.296895 -0.016246 -0.983845 0.098075 0.149765 -0.945922 -0.106723 0.306335 -0.843568 -0.303109 0.443303 -0.683820 -0.477407 0.551790 -0.477654 -0.617717 0.624718 -0.239142 -0.714759 0.657215 0.015616 -0.762425 0.646888 0.269607 -0.757981 0.593951 0.505918 -0.701998 0.501245 0.708619 -0.598174 0.374227 0.863620 -0.453166 0.220911 0.959652 -0.276407 0.051652 -0.005059 -0.775585 0.631223 0.252951 -0.748264 0.613284 0.494305 -0.670531 0.553219 0.702682 -0.547530 0.454366 0.863548 -0.387303 0.322925 0.965212 -0.200491 0.167839 1.000000 0.000194 0.000283 0.965231 0.200865 -0.167280 0.863595 0.387640 -0.322395 0.702765 0.547813 -0.453897 0.494421 0.670748 -0.552852 0.253085 0.748405 -0.613056 -0.004931 0.775634 -0.631163 -0.262441 0.750410 -0.606638 -0.502283 0.674048 -0.541638 -0.708319 0.551327 -0.440821 -0.866529 0.390358 -0.311044 -0.966047 0.202130 -0.160927 -1.000000 -0.000267 -0.000314 -0.966042 -0.202635 0.160320 -0.866529 -0.390785 0.310506 -0.708342 -0.551640 0.440392 -0.502342 -0.674233 0.541353 -0.262541 -0.750470 0.606521 -0.983642 -0.098786 -0.150633 -0.954597 -0.297497 0.015496 -0.860660 -0.476199 0.180274 -0.708370 -0.622453 0.332812 -0.508189 -0.726287 0.462872 -0.273690 -0.780880 0.561534 -0.020559 -0.782915 0.621789 0.234421 -0.732603 0.639014 0.474308 -0.633483 0.611336 0.682862 -0.492146 0.539900 0.845459 -0.317952 0.429074 0.950217 -0.122637 0.286440 0.989223 0.080364 0.122395 0.959542 0.276952 -0.050767 0.863580 0.453605 -0.220164 0.708657 0.598481 -0.373666 0.506029 0.702154 -0.500914 0.269776 0.757975 -0.593881 0.015822 0.762249 -0.647090 -0.238920 0.714412 -0.657672 -0.477430 0.617211 -0.625389 -0.683598 0.476769 -0.552617 -0.843349 0.302383 -0.444214 -0.945707 0.105971 -0.307259 0.046370 0.745281 -0.665136 -0.198364 0.674744 -0.710895 -0.429084 0.556879 -0.711177 -0.630134 0.399110 -0.666065 -0.787740 0.211892 -0.578418 -0.891078 0.008068 -0.453779 -0.933116 -0.198090 -0.300091 -0.911118 -0.392006 -0.127263 -0.826787 -0.559973 0.053406 -0.686078 -0.690246 0.229906 -0.498677 -0.773944 0.390297 -0.277233 -0.805651 0.523516 -0.036432 -0.783642 0.620144 0.207923 -0.709774 0.673044 0.439728 -0.589172 0.677876 0.643313 -0.429881 0.633523 0.804304 -0.242538 0.542466 0.910777 -0.039901 0.410966 0.954579 0.163964 0.248788 0.932420 0.354864 0.068294 0.846251 0.519787 -0.116967 0.702792 0.647918 -0.293744 0.512543 0.731177 -0.450200 0.288719 0.764376 -0.576516 0.889071 0.253684 0.381048 0.878340 0.437646 0.192314 0.807726 0.589480 -0.009587 0.682973 0.699548 -0.210192 0.513382 0.761227 -0.396196 0.310817 0.770840 -0.556057 0.088941 0.727603 -0.680208 -0.137411 0.633763 -0.761224 -0.352973 0.494806 -0.794089 -0.543031 0.319480 -0.776563 -0.694541 0.119454 -0.709467 -0.797167 -0.091464 -0.596790 -0.844076 -0.298381 -0.445538 -0.832375 -0.486541 -0.265386 -0.763225 -0.642531 -0.068128 -0.641642 -0.755378 0.133040 -0.476015 -0.817418 0.324402 -0.277415 -0.824795 0.492701 -0.058773 -0.777538 0.626083 0.165871 -0.679269 0.714899 0.381974 -0.536747 0.752329 0.575015 -0.359466 0.734943 0.731225 -0.159310 0.663272 0.838741 0.049963 0.542234 -0.092021 -0.766354 0.635794 0.101714 -0.642939 0.759133 0.292684 -0.477915 0.828211 0.468196 -0.282182 0.837356 0.615535 -0.068866 0.785095 0.723067 0.147235 0.674905 0.781878 0.350798 0.515372 0.787212 0.527588 0.319292 0.739043 0.665915 0.101847 0.641635 0.757349 -0.121355 0.502575 0.796726 -0.335628 0.331857 0.781860 -0.527794 0.141226 0.713434 -0.686344 -0.056362 0.595165 -0.801624 -0.247418 0.434038 -0.866254 -0.418832 0.240274 -0.875698 -0.558916 0.026863 -0.828789 -0.658328 -0.191354 -0.728002 -0.710732 -0.398871 -0.579450 -0.713142 -0.580777 -0.392590 -0.665965 -0.724013 -0.179709 -0.572808 -0.818462 0.044839 -0.440074 -0.857776 0.265623 -0.276397 -0.839778 0.467309 -0.531442 -0.495690 -0.686921 -0.550783 -0.671597 -0.495576 -0.531735 -0.802446 -0.270811 -0.476011 -0.878997 -0.027893 -0.387297 -0.896194 0.216421 -0.270920 -0.853460 0.445207 -0.133529 -0.754414 0.642674 0.017085 -0.606159 0.795160 0.171974 -0.418575 0.891751 0.320977 -0.203916 0.924874 0.453018 0.023413 0.891194 0.557174 0.247471 0.792663 0.624334 0.452164 0.636989 0.648795 0.623117 0.436795 0.628984 0.749165 0.207681 0.567191 0.822889 -0.033901 0.468753 0.840392 -0.272050 0.341268 0.800902 -0.492029 0.193990 0.706647 -0.680454 0.037311 0.563035 -0.825590 -0.117861 0.378801 -0.917943 -0.260899 0.165833 -0.951016 -0.382276 -0.061492 -0.922000 -0.474276 -0.287341 -0.832165 0.235886 0.705739 -0.668050 0.131189 0.537580 -0.832945 0.022474 0.331126 -0.943319 -0.082911 0.099959 -0.991531 -0.178260 -0.140277 -0.973933 -0.257928 -0.372997 -0.891261 -0.317555 -0.581926 -0.748680 -0.354156 -0.752320 -0.555507 -0.366050 -0.872122 -0.324671 -0.352742 -0.932957 -0.071866 -0.314796 -0.930843 0.185568 -0.253789 -0.866416 0.430016 -0.172352 -0.744573 0.644908 -0.074382 -0.573701 0.815681 0.034695 -0.364982 0.930368 0.147693 -0.132033 0.980181 0.255889 0.109369 0.960500 0.349934 0.342086 0.872080 0.421361 0.549261 0.721642 0.464015 0.716297 0.521160 0.474854 0.832287 0.286027 0.453907 0.890435 0.033075 0.403786 0.887798 -0.220841 0.329093 0.824926 -0.459559 0.197045 0.633247 0.748446 0.254314 0.796275 0.548881 0.294559 0.903091 0.312508 0.315540 0.947251 0.056121 0.316774 0.926554 -0.202860 0.299259 0.842814 -0.447335 0.265159 0.701672 -0.661322 0.217476 0.512390 -0.830759 0.159752 0.287451 -0.944379 0.095790 0.041866 -0.994521 0.029423 -0.207804 -0.977728 -0.035662 -0.444578 -0.895030 -0.096012 -0.652247 -0.751902 -0.148448 -0.816513 -0.557915 -0.190041 -0.926032 -0.326113 -0.218114 -0.973253 -0.072151 -0.230301 -0.955017 0.186829 -0.224759 -0.872711 0.433426 -0.200527 -0.731979 0.651149 -0.157946 -0.542125 0.825320 -0.099103 -0.315545 0.943721 -0.028005 -0.067288 0.997340 0.049587 0.185511 0.981390 0.126873 0.424779 0.896362 -0.231130 -0.706150 0.669277 -0.238985 -0.501174 0.831692 -0.226562 -0.261506 0.938235 -0.194751 -0.003441 0.980847 -0.146221 0.254988 0.955824 -0.085072 0.495399 0.864490 -0.016298 0.700672 0.713297 0.054800 0.856493 0.513242 0.123162 0.952437 0.278737 0.184333 0.982512 0.026291 0.234655 0.945268 -0.226727 0.271372 0.843676 -0.463215 0.292625 0.684837 -0.667359 0.297440 0.479543 -0.825571 0.285699 0.241617 -0.927361 0.258120 -0.012960 -0.966026 0.216233 -0.267083 -0.939100 0.162349 -0.503661 -0.848510 0.099508 -0.706757 -0.700423 0.031421 -0.862650 -0.504825 -0.037647 -0.960751 -0.274846 -0.103041 -0.994341 -0.025866 -0.159977 -0.961018 0.225504 -0.203937 -0.862840 0.462511 0.244706 -0.750147 -0.614327 0.158235 -0.894920 -0.417229 0.061914 -0.979534 -0.191522 -0.037750 -0.998147 0.047730 -0.133844 -0.949271 0.284554 -0.219545 -0.835893 0.503073 -0.288654 -0.665329 0.688489 -0.336111 -0.448836 0.827995 -0.358437 -0.201000 0.911659 -0.354039 0.061159 0.933229 -0.323364 0.319322 0.890769 -0.268820 0.555306 0.787001 -0.194530 0.752526 0.629176 -0.105928 0.897321 0.428479 -0.009268 0.979940 0.199078 0.088851 0.995116 -0.043012 0.181942 0.942268 -0.281118 0.263995 0.825389 -0.499039 0.329785 0.652688 -0.682085 0.375124 0.436017 -0.818029 0.397099 0.190061 -0.897880 0.394219 -0.068615 -0.916451 0.366530 -0.322648 -0.872671 0.315645 -0.555018 -0.769625 0.379367 0.609052 -0.696517 0.451215 0.384112 -0.805520 0.492957 0.133437 -0.859760 0.501805 -0.126066 -0.855745 0.477109 -0.376968 -0.793891 0.420404 -0.602440 -0.678474 0.335356 -0.787347 -0.517320 0.227554 -0.919242 -0.321268 0.104174 -0.989164 -0.103458 -0.026466 -0.992236 0.121523 -0.155449 -0.928010 0.338575 -0.273876 -0.800536 0.533042 -0.373480 -0.618159 0.691659 -0.447236 -0.393056 0.803422 -0.489903 -0.140514 0.860378 -0.498438 0.122077 0.858287 -0.472257 0.376450 0.797031 -0.413297 0.604811 0.680727 -0.325834 0.791246 0.517457 -0.216112 0.922907 0.318650 -0.091827 0.990923 0.098184 0.038470 0.990941 -0.128668 0.165963 0.923319 -0.346321 0.282154 0.792990 -0.539959 -0.407932 0.820490 0.400484 -0.276314 0.938524 0.206937 -0.127096 0.991889 -0.001448 0.029456 0.977193 -0.210299 0.182719 0.895736 -0.405304 0.322407 0.753328 -0.573194 0.439210 0.559842 -0.702618 0.525370 0.328515 -0.784898 0.575171 0.075042 -0.814584 0.585278 -0.183462 -0.789804 0.554977 -0.429594 -0.712355 0.486224 -0.646811 -0.587556 0.383545 -0.820503 -0.423872 0.253761 -0.938945 -0.232350 0.105559 -0.994077 -0.025863 -0.051063 -0.982025 0.181711 -0.205451 -0.903393 0.376391 -0.347017 -0.763253 0.545000 -0.465955 -0.570875 0.676009 -0.553947 -0.339184 0.760327 -0.604784 -0.083965 0.791950 -0.614848 0.177213 0.768478 -0.583425 0.426220 0.691340 -0.512770 0.645724 0.565781 -0.547771 -0.526643 0.650072 -0.641302 -0.289954 0.710393 -0.692295 -0.033314 0.720846 -0.697130 0.225617 0.680520 -0.655457 0.468901 0.592037 -0.570231 0.679659 0.461410 -0.447487 0.843311 0.297628 -0.295838 0.948649 0.112003 -0.125803 0.988605 -0.082664 0.050966 0.960666 -0.272989 0.222475 0.866973 -0.445940 0.377192 0.714110 -0.589723 0.504763 0.512615 -0.694580 0.596667 0.276252 -0.753441 0.646763 0.021077 -0.762400 0.651680 -0.235639 -0.720963 0.611057 -0.476571 -0.632052 0.527568 -0.685477 -0.501790 0.406768 -0.848281 -0.339057 0.256740 -0.953992 -0.154870 0.087571 -0.995420 0.038342 -0.089305 -0.969657 0.227572 -0.261860 -0.878275 0.400079 -0.418283 -0.727253 0.544189 0.419430 -0.868564 -0.263960 0.252488 -0.963550 -0.088437 0.066804 -0.993571 0.091397 -0.125046 -0.956540 0.263428 -0.310024 -0.854845 0.416084 -0.475489 -0.695210 0.539067 -0.610059 -0.488305 0.624008 -0.704394 -0.248084 0.665044 -0.751892 0.009089 0.659224 -0.749194 0.265552 0.606787 -0.696476 0.503589 0.511194 -0.597448 0.706732 0.378928 -0.459051 0.860982 0.219049 -0.290922 0.955801 0.042539 -0.104650 0.984821 -0.138478 0.087047 0.946223 -0.311585 0.271174 0.842798 -0.464926 0.435320 0.681721 -0.588008 0.568436 0.474044 -0.672430 0.661569 0.233949 -0.712457 0.708440 -0.022223 -0.705421 0.705875 -0.277076 -0.651897 0.654022 -0.513340 -0.555641 0.556350 -0.715041 -0.423309 0.623252 0.446185 -0.642242 0.716322 0.203699 -0.667376 0.759649 -0.052856 -0.648182 0.750279 -0.305999 -0.586043 0.688836 -0.538505 -0.485302 0.579490 -0.734598 -0.352927 0.429668 -0.881009 -0.198011 0.249541 -0.967864 -0.031115 0.051330 -0.989315 0.136456 -0.151514 -0.943905 0.293406 -0.345211 -0.834650 0.429172 -0.516562 -0.668845 0.534612 -0.653830 -0.457626 0.602565 -0.747553 -0.215265 0.628351 -0.791222 0.041740 0.610103 -0.781778 0.295782 0.548941 -0.719861 0.529386 0.448944 -0.609775 0.726468 0.316890 -0.459154 0.873499 0.161792 -0.278390 0.960451 -0.005737 -0.079868 0.981461 -0.174231 0.122889 0.935186 -0.332153 0.316130 0.824861 -0.468685 0.486768 0.658061 -0.574467 -0.459209 0.880363 0.118696 -0.269283 0.962196 -0.040819 -0.061761 0.978147 -0.198531 0.149238 0.927161 -0.343658 0.349377 0.812731 -0.466266 0.525059 0.642659 -0.557945 0.664327 0.428542 -0.612391 0.757682 0.184989 -0.625857 0.798737 -0.071363 -0.597434 0.784677 -0.323003 -0.529104 0.716459 -0.552757 -0.425613 0.598749 -0.744984 -0.294108 0.439592 -0.886640 -0.143624 0.249849 -0.968160 0.015562 0.042436 -0.984070 0.172644 -0.168546 -0.933327 0.317007 -0.368765 -0.819368 0.438918 -0.544606 -0.649874 0.530159 -0.684076 -0.436283 0.584548 -0.777624 -0.193059 0.598355 -0.818808 0.063257 0.570571 -0.804771 0.315161 0.503009 -0.736460 0.545402 0.400204 -0.618574 0.738199 0.269124 -0.704696 -0.423656 0.569139 -0.798974 -0.180492 0.573641 -0.839255 0.074890 0.538556 -0.822769 0.325094 0.466225 -0.750627 0.553045 0.361525 -0.627752 0.743176 0.231553 -0.462535 0.882503 0.085143 -0.266242 0.961523 -0.067738 -0.052243 0.974846 -0.216669 0.164906 0.921557 -0.351482 0.370431 0.805266 -0.462956 0.550341 0.633873 -0.543442 0.692357 0.419046 -0.587403 0.786763 0.175439 -0.591799 0.827079 -0.080301 -0.556320 0.810531 -0.330685 -0.483413 0.738246 -0.558592 -0.378111 0.615185 -0.748470 -0.247668 0.449784 -0.887403 -0.101045 0.253359 -0.965988 0.051736 0.039315 -0.978950 0.200279 -0.177773 -0.925471 0.334516 -0.383152 -0.809215 0.445382 -0.562866 -0.638079 0.525393 0.460835 -0.884901 -0.067679 0.259862 -0.962333 0.079921 0.041004 -0.974272 0.221613 -0.180819 -0.919977 0.347774 -0.390516 -0.803195 0.449861 -0.573843 -0.631891 0.520978 -0.718349 -0.417709 0.556322 -0.814215 -0.175191 0.553500 -0.854913 0.079183 0.512693 -0.837662 0.328116 0.436649 -0.763624 0.554653 0.330512 -0.637832 0.743356 0.201477 -0.468847 0.881353 0.058311 -0.268168 0.959229 -0.089250 -0.049453 0.971659 -0.231156 0.172422 0.917770 -0.357728 0.382351 0.801199 -0.460314 0.566027 0.629852 -0.531883 0.710906 0.415386 -0.567510 0.807066 0.172421 -0.564726 0.847902 -0.082444 -0.523703 0.830598 -0.331779 -0.447247 0.756330 -0.558523 -0.340613 0.630191 -0.747184 -0.211129 0.721746 0.415797 -0.553349 0.820326 0.173991 -0.544787 0.862797 -0.079795 -0.499214 0.846226 -0.328214 -0.419735 0.771730 -0.554274 -0.311790 0.644406 -0.742517 -0.182781 0.472980 -0.880093 -0.041547 0.269190 -0.957644 0.102246 0.046971 -0.969936 0.238783 -0.178512 -0.916196 0.358774 -0.391904 -0.800143 0.454074 -0.578696 -0.629714 0.518238 -0.726205 -0.416523 0.546933 -0.824417 -0.175065 0.538228 -0.866662 0.078249 0.492722 -0.850067 0.326198 0.413499 -0.775756 0.551914 0.305931 -0.648775 0.740033 0.177318 -0.477759 0.877737 0.036396 -0.274337 0.955634 -0.107254 -0.052346 0.968398 -0.243857 0.173113 0.915129 -0.364102 0.386689 0.799421 -0.459780 0.573826 0.629118 -0.524342 -0.488470 0.872407 0.017422 -0.283466 0.950991 -0.123548 -0.059205 0.964802 -0.256228 0.169052 0.912879 -0.371581 0.385767 0.798734 -0.461745 0.576177 0.630110 -0.520559 0.727296 0.418468 -0.543990 0.828797 0.178213 -0.530411 0.873722 -0.074276 -0.480720 0.858972 -0.321763 -0.398291 0.785527 -0.547332 -0.288747 0.658394 -0.735563 -0.159576 0.486263 -0.873592 -0.019619 0.280912 -0.952005 0.121551 0.056380 -0.965484 0.254288 -0.172000 -0.913156 0.369544 -0.388656 -0.798641 0.459478 -0.578842 -0.629782 0.517993 -0.729630 -0.418104 0.541137 -0.830784 -0.178021 0.527358 -0.875439 0.074135 0.477610 -0.860566 0.321216 0.395280 -0.787180 0.546417 0.285965 -0.660271 0.734414 0.157093 -0.729139 -0.420205 0.540170 -0.833619 -0.181754 0.521579 -0.881307 0.069040 0.467473 -0.868979 0.315109 0.381551 -0.797489 0.539712 0.269670 -0.671712 0.727570 0.139445 -0.500213 0.865902 -0.000264 -0.294668 0.945295 -0.139956 -0.069066 0.960344 -0.270130 0.161240 0.910018 -0.381929 0.380576 0.797731 -0.467746 0.574015 0.631112 -0.521733 0.728382 0.421480 -0.540199 0.833150 0.183089 -0.521862 0.881150 -0.067830 -0.467947 0.869076 -0.314177 -0.382099 0.797714 -0.539136 -0.270156 0.671904 -0.727334 -0.139751 0.500221 -0.865898 0.000209 0.294389 -0.945353 0.140155 0.068474 -0.960276 0.270519 -0.162085 -0.909673 0.382393 -0.381550 -0.797030 0.468149 -0.574956 -0.630069 0.521956 0.513548 -0.857834 0.019731 0.308016 -0.937859 0.159831 0.081494 -0.953815 0.289128 -0.150535 -0.904611 0.398772 -0.372213 -0.793624 0.481268 -0.568403 -0.628466 0.530988 -0.725729 -0.420444 0.544559 -0.833485 -0.183772 0.521085 -0.884362 0.065404 0.462197 -0.874925 0.310112 0.371936 -0.805847 0.533699 0.256468 -0.681851 0.720962 0.123665 -0.511394 0.859170 -0.017433 -0.306084 0.938931 -0.157227 -0.079902 0.954828 -0.286214 0.151762 0.905785 -0.395628 0.373147 0.795138 -0.478035 0.569194 0.630406 -0.527832 0.726566 0.422783 -0.541624 0.834546 0.186376 -0.518457 0.885762 -0.062742 -0.459879 0.876691 -0.307612 -0.369849 0.807906 -0.531539 -0.254468 0.684052 -0.719228 -0.121589 0.723859 0.420944 -0.546657 0.834752 0.186596 -0.518045 0.888963 -0.060410 -0.453977 0.882778 -0.303281 -0.358781 0.816576 -0.525482 -0.238898 0.694816 -0.711851 -0.102463 0.525751 -0.849638 0.041238 0.320882 -0.929390 0.182396 0.094184 -0.945615 0.311356 -0.138852 -0.897177 0.419277 -0.362292 -0.787387 0.498764 -0.560862 -0.623768 0.544378 -0.721006 -0.417528 0.553011 -0.831813 -0.182774 0.524100 -0.885758 0.064461 0.459650 -0.879198 0.307324 0.364091 -0.812616 0.529281 0.243961 -0.690569 0.715238 0.107462 -0.521389 0.852555 -0.036104 -0.316607 0.931903 -0.176965 -0.090174 0.947899 -0.305542 0.142490 0.899469 -0.413100 0.365549 0.789921 -0.492341 0.563832 0.626713 -0.537889 -0.529279 0.846421 -0.058606 -0.325264 0.923859 -0.201713 -0.098907 0.938548 -0.330674 0.134364 0.889503 -0.436728 0.358653 0.780078 -0.512685 0.558694 0.617738 -0.553409 0.720886 0.413537 -0.556156 0.834221 0.181361 -0.520753 0.891005 -0.063019 -0.449598 0.887376 -0.303001 -0.347496 0.823553 -0.522271 -0.221345 0.703831 -0.705884 -0.079684 0.536308 -0.841290 0.067866 0.332357 -0.919191 0.211250 0.105870 -0.934207 0.340659 -0.127690 -0.885266 0.447213 -0.352353 -0.775695 0.523588 -0.552752 -0.612995 0.564537 -0.715192 -0.408316 0.567255 -0.828594 -0.175673 0.531575 -0.885247 0.069038 0.459969 -0.881324 0.309124 0.357365 -0.817124 0.528243 0.230797 -0.697046 0.711493 0.088913 -0.709005 -0.389952 0.587579 -0.824123 -0.159618 0.543454 -0.882679 0.081811 0.462801 -0.880702 0.317873 0.351169 -0.818344 0.532504 0.216221 -0.699858 0.711115 0.067186 -0.533314 0.841559 -0.085760 -0.330056 0.914959 -0.232192 -0.103951 0.926309 -0.362141 0.129566 0.874834 -0.466775 0.354544 0.764051 -0.539003 0.555640 0.601532 -0.573954 0.719166 0.398370 -0.569299 0.834029 0.168405 -0.525391 0.892464 -0.072727 -0.445218 0.890530 -0.308646 -0.334206 0.828366 -0.523328 -0.199844 0.710170 -0.702165 -0.051206 0.543934 -0.832950 0.101636 0.340924 -0.906712 0.248284 0.114942 -0.918350 0.378710 -0.118608 -0.867016 0.483957 -0.343774 -0.756191 0.556771 -0.545161 -0.593454 0.592125 0.548044 -0.823895 0.144379 0.345787 -0.890752 0.294943 0.120462 -0.896441 0.426477 -0.112612 -0.840524 0.529941 -0.337554 -0.726792 0.598189 -0.539016 -0.563009 0.626484 -0.703241 -0.360378 0.612846 -0.819017 -0.132747 0.558203 -0.878443 0.104352 0.466313 -0.877459 0.334776 0.343497 -0.816108 0.542856 0.198181 -0.698533 0.714442 0.040312 -0.532707 0.837846 -0.119319 -0.329918 0.904630 -0.269813 -0.104020 0.910195 -0.400906 0.129515 0.854131 -0.503673 0.354675 0.740266 -0.571149 0.556046 0.576409 -0.598803 0.719899 0.373785 -0.584833 0.835127 0.146245 -0.530260 0.893983 -0.090712 -0.438823 0.892557 -0.320986 -0.316716 0.831005 -0.528950 -0.172172 0.713516 -0.700480 -0.014931 0.723341 0.336837 -0.602759 0.837568 0.112363 -0.534654 0.895423 -0.118877 -0.429052 0.893137 -0.341158 -0.293118 0.830990 -0.539404 -0.136013 0.713264 -0.700179 0.031694 0.547948 -0.812572 0.198693 0.346221 -0.868935 0.353670 0.121726 -0.865410 0.486055 -0.110334 -0.802212 0.586756 -0.334209 -0.683634 0.648805 -0.534674 -0.517756 0.667871 -0.698072 -0.315887 0.642581 -0.813248 -0.091775 0.574635 -0.872311 0.139330 0.468680 -0.871170 0.361731 0.331984 -0.809812 0.560318 0.173920 -0.692316 0.721575 0.005313 -0.526605 0.834474 -0.162296 -0.323954 0.891229 -0.317435 -0.098243 0.887867 -0.449489 0.134996 0.824550 -0.549448 0.359685 0.705602 -0.610535 0.560371 0.539212 -0.628677 -0.516135 0.827923 -0.219429 -0.313339 0.870601 -0.379307 -0.087889 0.854743 -0.511556 0.144612 0.781340 -0.607120 0.368051 0.655417 -0.659521 0.567006 0.485683 -0.665294 0.727858 0.283876 -0.624210 0.839741 0.063897 -0.539215 0.895237 -0.159192 -0.416183 0.890802 -0.370203 -0.263479 0.826928 -0.554829 -0.091403 0.708067 -0.700582 0.088467 0.542315 -0.797616 0.264013 0.340879 -0.839383 0.423364 0.117349 -0.823070 0.555685 -0.113198 -0.749803 0.651906 -0.335188 -0.624567 0.705383 -0.533593 -0.455873 0.712361 -0.694937 -0.255167 0.672274 -0.808207 -0.036059 0.587793 -0.865604 0.186608 0.464658 -0.863080 0.397745 0.311274 -0.800632 0.583017 0.138132 -0.682338 0.729777 -0.042909 -0.696502 -0.180262 0.694544 -0.807162 0.030905 0.589521 -0.862124 0.241232 0.445590 -0.857439 0.436496 0.272522 -0.793180 0.603425 0.082118 -0.673487 0.730575 -0.112584 -0.506369 0.809114 -0.298202 -0.303214 0.833475 -0.461932 -0.078043 0.801805 -0.592468 0.153502 0.716177 -0.680829 0.375314 0.582477 -0.721013 0.572043 0.409981 -0.710410 0.730206 0.210655 -0.649941 0.839139 -0.001744 -0.543915 0.891652 -0.212645 -0.399674 0.884445 -0.407676 -0.227060 0.818250 -0.573622 -0.037745 0.697720 -0.699284 0.155523 0.531097 -0.776225 0.339723 0.329653 -0.799308 0.502430 0.106954 -0.767042 0.632619 -0.122026 -0.681668 0.721415 -0.341885 -0.548993 0.762706 -0.537800 -0.378007 0.753579 0.518467 -0.742237 0.424590 0.316638 -0.744140 0.588214 0.094105 -0.694920 0.712902 -0.134208 -0.597976 0.790198 -0.352998 -0.459897 0.814793 -0.547553 -0.290009 0.784908 -0.704724 -0.099752 0.702434 -0.813781 0.098077 0.572836 -0.867149 0.290151 0.404803 -0.860934 0.463487 0.209696 -0.795258 0.606270 0.000791 -0.674311 0.708666 -0.207598 -0.506175 0.763482 -0.401101 -0.302319 0.766747 -0.566306 -0.076853 0.718050 -0.691735 0.154505 0.620650 -0.768715 0.375615 0.481267 -0.792020 0.571146 0.309592 -0.760227 0.727696 0.117547 -0.675752 0.834715 -0.081602 -0.544603 0.885179 -0.274191 -0.375869 0.875962 -0.447098 -0.181088 0.807975 -0.588618 0.026557 0.686023 -0.689237 0.233078</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="2880" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="9075">0 0 0 0 0.041667 0 0 0.083333 0 0 0.125000 0 0 0.166667 0 0 0.208333 0 0 0.250000 0 0 0.291667 0 0 0.333333 0 0 0.375000 0 0 0.416667 0 0 0.458333 0 0 0.500000 0 0 0.541667 0 0 0.583333 0 0 0.625000 0 0 0.666667 0 0 0.708333 0 0 0.750000 0 0 0.791667 0 0 0.833333 0 0 0.875000 0 0 0.916667 0 0 0.958333 0 0 1.000000 0 0.008333 0 0 0.008333 0.041667 0 0.008333 0.083333 0 0.008333 0.125000 0 0.008333 0.166667 0 0.008333 0.208333 0 0.008333 0.250000 0 0.008333 0.291667 0 0.008333 0.333333 0 0.008333 0.375000 0 0.008333 0.416667 0 0.008333 0.458333 0 0.008333 0.500000 0 0.008333 0.541667 0 0.008333 0.583333 0 0.008333 0.625000 0 0.008333 0.666667 0 0.008333 0.708333 0 0.008333 0.750000 0 0.008333 0.791667 0 0.008333 0.833333 0 0.008333 0.875000 0 0.008333 0.916667 0 0.008333 0.958333 0 0.008333 1.000000 0 0.016667 0 0 0.016667 0.041667 0 0.016667 0.083333 0 0.016667 0.125000 0 0.016667 0.166667 0 0.016667 0.208333 0 0.016667 0.250000 0 0.016667 0.291667 0 0.016667 0.333333 0 0.016667 0.375000 0 0.016667 0.416667 0 0.016667 0.458333 0 0.016667 0.500000 0 0.016667 0.541667 0 0.016667 0.583333 0 0.016667 0.625000 0 0.016667 0.666667 0 0.016667 0.708333 0 0.016667 0.750000 0 0.016667 0.791667 0 0.016667 0.833333 0 0.016667 0.875000 0 0.016667 0.916667 0 0.016667 0.958333 0 0.016667 1.000000 0 0.025000 0 0 0.025000 0.041667 0 0.025000 0.083333 0 0.025000 0.125000 0 0.025000 0.166667 0 0.025000 0.208333 0 0.025000 0.250000 0 0.025000 0.291667 0 0.025000 0.333333 0 0.025000 0.375000 0 0.025000 0.416667 0 0.025000 0.458333 0 0.025000 0.500000 0 0.025000 0.541667 0 0.025000 0.583333 0 0.025000 0.625000 0 0.025000 0.666667 0 0.025000 0.708333 0 0.025000 0.750000 0 0.025000 0.791667 0 0.025000 0.833333 0 0.025000 0.875000 0 0.025000 0.916667 0 0.025000 0.958333 0 0.025000 1.000000 0 0.033333 0 0 0.033333 0.041667 0 0.033333 0.083333 0 0.033333 0.125000 0 0.033333 0.166667 0 0.033333 0.208333 0 0.033333 0.250000 0 0.033333 0.291667 0 0.033333 0.333333 0 0.033333 0.375000 0 0.033333 0.416667 0 0.033333 0.458333 0 0.033333 0.500000 0 0.033333 0.541667 0 0.033333 0.583333 0 0.033333 0.625000 0 0.033333 0.666667 0 0.033333 0.708333 0 0.033333 0.750000 0 0.033333 0.791667 0 0.033333 0.833333 0 0.033333 0.875000 0 0.033333 0.916667 0 0.033333 0.958333 0 0.033333 1.000000 0 0.041667 0 0 0.041667 0.041667 0 0.041667 0.083333 0 0.041667 0.125000 0 0.041667 0.166667 0 0.041667 0.208333 0 0.041667 0.250000 0 0.041667 0.291667 0 0.041667 0.333333 0 0.041667 0.375000 0 0.041667 0.416667 0 0.041667 0.458333 0 0.041667 0.500000 0 0.041667 0.541667 0 0.041667 0.583333 0 0.041667 0.625000 0 0.041667 0.666667 0 0.041667 0.708333 0 0.041667 0.750000 0 0.041667 0.791667 0 0.041667 0.833333 0 0.041667 0.875000 0 0.041667 0.916667 0 0.041667 0.958333 0 0.041667 1.000000 0 0.050000 0 0 0.050000 0.041667 0 0.050000 0.083333 0 0.050000 0.125000 0 0.050000 0.166667 0 0.050000 0.208333 0 0.050000 0.250000 0 0.050000 0.291667 0 0.050000 0.333333 0 0.050000 0.375000 0 0.050000 0.416667 0 0.050000 0.458333 0 0.050000 0.500000 0 0.050000 0.541667 0 0.050000 0.583333 0 0.050000 0.625000 0 0.050000 0.666667 0 0.050000 0.708333 0 0.050000 0.750000 0 0.050000 0.791667 0 0.050000 0.833333 0 0.050000 0.875000 0 0.050000 0.916667 0 0.050000 0.958333 0 0.050000 1.000000 0 0.058333 0 0 0.058333 0.041667 0 0.058333 0.083333 0 0.058333 0.125000 0 0.058333 0.166667 0 0.058333 0.208333 0 0.058333 0.250000 0 0.058333 0.291667 0 0.058333 0.333333 0 0.058333 0.375000 0 0.058333 0.416667 0 0.058333 0.458333 0 0.058333 0.500000 0 0.058333 0.541667 0 0.058333 0.583333 0 0.058333 0.625000 0 0.058333 0.666667 0 0.058333 0.708333 0 0.058333 0.750000 0 0.058333 0.791667 0 0.058333 0.833333 0 0.058333 0.875000 0 0.058333 0.916667 0 0.058333 0.958333 0 0.058333 1.000000 0 0.066667 0 0 0.066667 0.041667 0 0.066667 0.083333 0 0.066667 0.125000 0 0.066667 0.166667 0 0.066667 0.208333 0 0.066667 0.250000 0 0.066667 0.291667 0 0.066667 0.333333 0 0.066667 0.375000 0 0.066667 0.416667 0 0.066667 0.458333 0 0.066667 0.500000 0 0.066667 0.541667 0 0.066667 0.583333 0 0.066667 0.625000 0 0.066667 0.666667 0 0.066667 0.708333 0 0.066667 0.750000 0 0.066667 0.791667 0 0.066667 0.833333 0 0.066667 0.875000 0 0.066667 0.916667 0 0.066667 0.958333 0 0.066667 1.000000 0 0.075000 0 0 0.075000 0.041667 0 0.075000 0.083333 0 0.075000 0.125000 0 0.075000 0.166667 0 0.075000 0.208333 0 0.075000 0.250000 0 0.075000 0.291667 0 0.075000 0.333333 0 0.075000 0.375000 0 0.075000 0.416667 0 0.075000 0.458333 0 0.075000 0.500000 0 0.075000 0.541667 0 0.075000 0.583333 0 0.075000 0.625000 0 0.075000 0.666667 0 0.075000 0.708333 0 0.075000 0.750000 0 0.075000 0.791667 0 0.075000 0.833333 0 0.075000 0.875000 0 0.075000 0.916667 0 0.075000 0.958333 0 0.075000 1.000000 0 0.083333 0 0 0.083333 0.041667 0 0.083333 0.083333 0 0.083333 0.125000 0 0.083333 0.166667 0 0.083333 0.208333 0 0.083333 0.250000 0 0.083333 0.291667 0 0.083333 0.333333 0 0.083333 0.375000 0 0.083333 0.416667 0 0.083333 0.458333 0 0.083333 0.500000 0 0.083333 0.541667 0 0.083333 0.583333 0 0.083333 0.625000 0 0.083333 0.666667 0 0.083333 0.708333 0 0.083333 0.750000 0 0.083333 0.791667 0 0.083333 0.833333 0 0.083333 0.875000 0 0.083333 0.916667 0 0.083333 0.958333 0 0.083333 1.000000 0 0.091667 0 0 0.091667 0.041667 0 0.091667 0.083333 0 0.091667 0.125000 0 0.091667 0.166667 0 0.091667 0.208333 0 0.091667 0.250000 0 0.091667 0.291667 0 0.091667 0.333333 0 0.091667 0.375000 0 0.091667 0.416667 0 0.091667 0.458333 0 0.091667 0.500000 0 0.091667 0.541667 0 0.091667 0.583333 0 0.091667 0.625000 0 0.091667 0.666667 0 0.091667 0.708333 0 0.091667 0.750000 0 0.091667 0.791667 0 0.091667 0.833333 0 0.091667 0.875000 0 0.091667 0.916667 0 0.091667 0.958333 0 0.091667 1.000000 0 0.100000 0 0 0.100000 0.041667 0 0.100000 0.083333 0 0.100000 0.125000 0 0.100000 0.166667 0 0.100000 0.208333 0 0.100000 0.250000 0 0.100000 0.291667 0 0.100000 0.333333 0 0.100000 0.375000 0 0.100000 0.416667 0 0.100000 0.458333 0 0.100000 0.500000 0 0.100000 0.541667 0 0.100000 0.583333 0 0.100000 0.625000 0 0.100000 0.666667 0 0.100000 0.708333 0 0.100000 0.750000 0 0.100000 0.791667 0 0.100000 0.833333 0 0.100000 0.875000 0 0.100000 0.916667 0 0.100000 0.958333 0 0.100000 1.000000 0 0.108333 0 0 0.108333 0.041667 0 0.108333 0.083333 0 0.108333 0.125000 0 0.108333 0.166667 0 0.108333 0.208333 0 0.108333 0.250000 0 0.108333 0.291667 0 0.108333 0.333333 0 0.108333 0.375000 0 0.108333 0.416667 0 0.108333 0.458333 0 0.108333 0.500000 0 0.108333 0.541667 0 0.108333 0.583333 0 0.108333 0.625000 0 0.108333 0.666667 0 0.108333 0.708333 0 0.108333 0.750000 0 0.108333 0.791667 0 0.108333 0.833333 0 0.108333 0.875000 0 0.108333 0.916667 0 0.108333 0.958333 0 0.108333 1.000000 0 0.116667 0 0 0.116667 0.041667 0 0.116667 0.083333 0 0.116667 0.125000 0 0.116667 0.166667 0 0.116667 0.208333 0 0.116667 0.250000 0 0.116667 0.291667 0 0.116667 0.333333 0 0.116667 0.375000 0 0.116667 0.416667 0 0.116667 0.458333 0 0.116667 0.500000 0 0.116667 0.541667 0 0.116667 0.583333 0 0.116667 0.625000 0 0.116667 0.666667 0 0.116667 0.708333 0 0.116667 0.750000 0 0.116667 0.791667 0 0.116667 0.833333 0 0.116667 0.875000 0 0.116667 0.916667 0 0.116667 0.958333 0 0.116667 1.000000 0 0.125000 0 0 0.125000 0.041667 0 0.125000 0.083333 0 0.125000 0.125000 0 0.125000 0.166667 0 0.125000 0.208333 0 0.125000 0.250000 0 0.125000 0.291667 0 0.125000 0.333333 0 0.125000 0.375000 0 0.125000 0.416667 0 0.125000 0.458333 0 0.125000 0.500000 0 0.125000 0.541667 0 0.125000 0.583333 0 0.125000 0.625000 0 0.125000 0.666667 0 0.125000 0.708333 0 0.125000 0.750000 0 0.125000 0.791667 0 0.125000 0.833333 0 0.125000 0.875000 0 0.125000 0.916667 0 0.125000 0.958333 0 0.125000 1.000000 0 0.133333 0 0 0.133333 0.041667 0 0.133333 0.083333 0 0.133333 0.125000 0 0.133333 0.166667 0 0.133333 0.208333 0 0.133333 0.250000 0 0.133333 0.291667 0 0.133333 0.333333 0 0.133333 0.375000 0 0.133333 0.416667 0 0.133333 0.458333 0 0.133333 0.500000 0 0.133333 0.541667 0 0.133333 0.583333 0 0.133333 0.625000 0 0.133333 0.666667 0 0.133333 0.708333 0 0.133333 0.750000 0 0.133333 0.791667 0 0.133333 0.833333 0 0.133333 0.875000 0 0.133333 0.916667 0 0.133333 0.958333 0 0.133333 1.000000 0 0.141667 0 0 0.141667 0.041667 0 0.141667 0.083333 0 0.141667 0.125000 0 0.141667 0.166667 0 0.141667 0.208333 0 0.141667 0.250000 0 0.141667 0.291667 0 0.141667 0.333333 0 0.141667 0.375000 0 0.141667 0.416667 0 0.141667 0.458333 0 0.141667 0.500000 0 0.141667 0.541667 0 0.141667 0.583333 0 0.141667 0.625000 0 0.141667 0.666667 0 0.141667 0.708333 0 0.141667 0.750000 0 0.141667 0.791667 0 0.141667 0.833333 0 0.141667 0.875000 0 0.141667 0.916667 0 0.141667 0.958333 0 0.141667 1.000000 0 0.150000 0 0 0.150000 0.041667 0 0.150000 0.083333 0 0.150000 0.125000 0 0.150000 0.166667 0 0.150000 0.208333 0 0.150000 0.250000 0 0.150000 0.291667 0 0.150000 0.333333 0 0.150000 0.375000 0 0.150000 0.416667 0 0.150000 0.458333 0 0.150000 0.500000 0 0.150000 0.541667 0 0.150000 0.583333 0 0.150000 0.625000 0 0.150000 0.666667 0 0.150000 0.708333 0 0.150000 0.750000 0 0.150000 0.791667 0 0.150000 0.833333 0 0.150000 0.875000 0 0.150000 0.916667 0 0.150000 0.958333 0 0.150000 1.000000 0 0.158333 0 0 0.158333 0.041667 0 0.158333 0.083333 0 0.158333 0.125000 0 0.158333 0.166667 0 0.158333 0.208333 0 0.158333 0.250000 0 0.158333 0.291667 0 0.158333 0.333333 0 0.158333 0.375000 0 0.158333 0.416667 0 0.158333 0.458333 0 0.158333 0.500000 0 0.158333 0.541667 0 0.158333 0.583333 0 0.158333 0.625000 0 0.158333 0.666667 0 0.158333 0.708333 0 0.158333 0.750000 0 0.158333 0.791667 0 0.158333 0.833333 0 0.158333 0.875000 0 0.158333 0.916667 0 0.158333 0.958333 0 0.158333 1.000000 0 0.166667 0 0 0.166667 0.041667 0 0.166667 0.083333 0 0.166667 0.125000 0 0.166667 0.166667 0 0.166667 0.208333 0 0.166667 0.250000 0 0.166667 0.291667 0 0.166667 0.333333 0 0.166667 0.375000 0 0.166667 0.416667 0 0.166667 0.458333 0 0.166667 0.500000 0 0.166667 0.541667 0 0.166667 0.583333 0 0.166667 0.625000 0 0.166667 0.666667 0 0.166667 0.708333 0 0.166667 0.750000 0 0.166667 0.791667 0 0.166667 0.833333 0 0.166667 0.875000 0 0.166667 0.916667 0 0.166667 0.958333 0 0.166667 1.000000 0 0.175000 0 0 0.175000 0.041667 0 0.175000 0.083333 0 0.175000 0.125000 0 0.175000 0.166667 0 0.175000 0.208333 0 0.175000 0.250000 0 0.175000 0.291667 0 0.175000 0.333333 0 0.175000 0.375000 0 0.175000 0.416667 0 0.175000 0.458333 0 0.175000 0.500000 0 0.175000 0.541667 0 0.175000 0.583333 0 0.175000 0.625000 0 0.175000 0.666667 0 0.175000 0.708333 0 0.175000 0.750000 0 0.175000 0.791667 0 0.175000 0.833333 0 0.175000 0.875000 0 0.175000 0.916667 0 0.175000 0.958333 0 0.175000 1.000000 0 0.183333 0 0 0.183333 0.041667 0 0.183333 0.083333 0 0.183333 0.125000 0 0.183333 0.166667 0 0.183333 0.208333 0 0.183333 0.250000 0 0.183333 0.291667 0 0.183333 0.333333 0 0.183333 0.375000 0 0.183333 0.416667 0 0.183333 0.458333 0 0.183333 0.500000 0 0.183333 0.541667 0 0.183333 0.583333 0 0.183333 0.625000 0 0.183333 0.666667 0 0.183333 0.708333 0 0.183333 0.750000 0 0.183333 0.791667 0 0.183333 0.833333 0 0.183333 0.875000 0 0.183333 0.916667 0 0.183333 0.958333 0 0.183333 1.000000 0 0.191667 0 0 0.191667 0.041667 0 0.191667 0.083333 0 0.191667 0.125000 0 0.191667 0.166667 0 0.191667 0.208333 0 0.191667 0.250000 0 0.191667 0.291667 0 0.191667 0.333333 0 0.191667 0.375000 0 0.191667 0.416667 0 0.191667 0.458333 0 0.191667 0.500000 0 0.191667 0.541667 0 0.191667 0.583333 0 0.191667 0.625000 0 0.191667 0.666667 0 0.191667 0.708333 0 0.191667 0.750000 0 0.191667 0.791667 0 0.191667 0.833333 0 0.191667 0.875000 0 0.191667 0.916667 0 0.191667 0.958333 0 0.191667 1.000000 0 0.200000 0 0 0.200000 0.041667 0 0.200000 0.083333 0 0.200000 0.125000 0 0.200000 0.166667 0 0.200000 0.208333 0 0.200000 0.250000 0 0.200000 0.291667 0 0.200000 0.333333 0 0.200000 0.375000 0 0.200000 0.416667 0 0.200000 0.458333 0 0.200000 0.500000 0 0.200000 0.541667 0 0.200000 0.583333 0 0.200000 0.625000 0 0.200000 0.666667 0 0.200000 0.708333 0 0.200000 0.750000 0 0.200000 0.791667 0 0.200000 0.833333 0 0.200000 0.875000 0 0.200000 0.916667 0 0.200000 0.958333 0 0.200000 1.000000 0 0.208333 0 0 0.208333 0.041667 0 0.208333 0.083333 0 0.208333 0.125000 0 0.208333 0.166667 0 0.208333 0.208333 0 0.208333 0.250000 0 0.208333 0.291667 0 0.208333 0.333333 0 0.208333 0.375000 0 0.208333 0.416667 0 0.208333 0.458333 0 0.208333 0.500000 0 0.208333 0.541667 0 0.208333 0.583333 0 0.208333 0.625000 0 0.208333 0.666667 0 0.208333 0.708333 0 0.208333 0.750000 0 0.208333 0.791667 0 0.208333 0.833333 0 0.208333 0.875000 0 0.208333 0.916667 0 0.208333 0.958333 0 0.208333 1.000000 0 0.216667 0 0 0.216667 0.041667 0 0.216667 0.083333 0 0.216667 0.125000 0 0.216667 0.166667 0 0.216667 0.208333 0 0.216667 0.250000 0 0.216667 0.291667 0 0.216667 0.333333 0 0.216667 0.375000 0 0.216667 0.416667 0 0.216667 0.458333 0 0.216667 0.500000 0 0.216667 0.541667 0 0.216667 0.583333 0 0.216667 0.625000 0 0.216667 0.666667 0 0.216667 0.708333 0 0.216667 0.750000 0 0.216667 0.791667 0 0.216667 0.833333 0 0.216667 0.875000 0 0.216667 0.916667 0 0.216667 0.958333 0 0.216667 1.000000 0 0.225000 0 0 0.225000 0.041667 0 0.225000 0.083333 0 0.225000 0.125000 0 0.225000 0.166667 0 0.225000 0.208333 0 0.225000 0.250000 0 0.225000 0.291667 0 0.225000 0.333333 0 0.225000 0.375000 0 0.225000 0.416667 0 0.225000 0.458333 0 0.225000 0.500000 0 0.225000 0.541667 0 0.225000 0.583333 0 0.225000 0.625000 0 0.225000 0.666667 0 0.225000 0.708333 0 0.225000 0.750000 0 0.225000 0.791667 0 0.225000 0.833333 0 0.225000 0.875000 0 0.225000 0.916667 0 0.225000 0.958333 0 0.225000 1.000000 0 0.233333 0 0 0.233333 0.041667 0 0.233333 0.083333 0 0.233333 0.125000 0 0.233333 0.166667 0 0.233333 0.208333 0 0.233333 0.250000 0 0.233333 0.291667 0 0.233333 0.333333 0 0.233333 0.375000 0 0.233333 0.416667 0 0.233333 0.458333 0 0.233333 0.500000 0 0.233333 0.541667 0 0.233333 0.583333 0 0.233333 0.625000 0 0.233333 0.666667 0 0.233333 0.708333 0 0.233333 0.750000 0 0.233333 0.791667 0 0.233333 0.833333 0 0.233333 0.875000 0 0.233333 0.916667 0 0.233333 0.958333 0 0.233333 1.000000 0 0.241667 0 0 0.241667 0.041667 0 0.241667 0.083333 0 0.241667 0.125000 0 0.241667 0.166667 0 0.241667 0.208333 0 0.241667 0.250000 0 0.241667 0.291667 0 0.241667 0.333333 0 0.241667 0.375000 0 0.241667 0.416667 0 0.241667 0.458333 0 0.241667 0.500000 0 0.241667 0.541667 0 0.241667 0.583333 0 0.241667 0.625000 0 0.241667 0.666667 0 0.241667 0.708333 0 0.241667 0.750000 0 0.241667 0.791667 0 0.241667 0.833333 0 0.241667 0.875000 0 0.241667 0.916667 0 0.241667 0.958333 0 0.241667 1.000000 0 0.250000 0 0 0.250000 0.041667 0 0.250000 0.083333 0 0.250000 0.125000 0 0.250000 0.166667 0 0.250000 0.208333 0 0.250000 0.250000 0 0.250000 0.291667 0 0.250000 0.333333 0 0.250000 0.375000 0 0.250000 0.416667 0 0.250000 0.458333 0 0.250000 0.500000 0 0.250000 0.541667 0 0.250000 0.583333 0 0.250000 0.625000 0 0.250000 0.666667 0 0.250000 0.708333 0 0.250000 0.750000 0 0.250000 0.791667 0 0.250000 0.833333 0 0.250000 0.875000 0 0.250000 0.916667 0 0.250000 0.958333 0 0.250000 1.000000 0 0.258333 0 0 0.258333 0.041667 0 0.258333 0.083333 0 0.258333 0.125000 0 0.258333 0.166667 0 0.258333 0.208333 0 0.258333 0.250000 0 0.258333 0.291667 0 0.258333 0.333333 0 0.258333 0.375000 0 0.258333 0.416667 0 0.258333 0.458333 0 0.258333 0.500000 0 0.258333 0.541667 0 0.258333 0.583333 0 0.258333 0.625000 0 0.258333 0.666667 0 0.258333 0.708333 0 0.258333 0.750000 0 0.258333 0.791667 0 0.258333 0.833333 0 0.258333 0.875000 0 0.258333 0.916667 0 0.258333 0.958333 0 0.258333 1.000000 0 0.266667 0 0 0.266667 0.041667 0 0.266667 0.083333 0 0.266667 0.125000 0 0.266667 0.166667 0 0.266667 0.208333 0 0.266667 0.250000 0 0.266667 0.291667 0 0.266667 0.333333 0 0.266667 0.375000 0 0.266667 0.416667 0 0.266667 0.458333 0 0.266667 0.500000 0 0.266667 0.541667 0 0.266667 0.583333 0 0.266667 0.625000 0 0.266667 0.666667 0 0.266667 0.708333 0 0.266667 0.750000 0 0.266667 0.791667 0 0.266667 0.833333 0 0.266667 0.875000 0 0.266667 0.916667 0 0.266667 0.958333 0 0.266667 1.000000 0 0.275000 0 0 0.275000 0.041667 0 0.275000 0.083333 0 0.275000 0.125000 0 0.275000 0.166667 0 0.275000 0.208333 0 0.275000 0.250000 0 0.275000 0.291667 0 0.275000 0.333333 0 0.275000 0.375000 0 0.275000 0.416667 0 0.275000 0.458333 0 0.275000 0.500000 0 0.275000 0.541667 0 0.275000 0.583333 0 0.275000 0.625000 0 0.275000 0.666667 0 0.275000 0.708333 0 0.275000 0.750000 0 0.275000 0.791667 0 0.275000 0.833333 0 0.275000 0.875000 0 0.275000 0.916667 0 0.275000 0.958333 0 0.275000 1.000000 0 0.283333 0 0 0.283333 0.041667 0 0.283333 0.083333 0 0.283333 0.125000 0 0.283333 0.166667 0 0.283333 0.208333 0 0.283333 0.250000 0 0.283333 0.291667 0 0.283333 0.333333 0 0.283333 0.375000 0 0.283333 0.416667 0 0.283333 0.458333 0 0.283333 0.500000 0 0.283333 0.541667 0 0.283333 0.583333 0 0.283333 0.625000 0 0.283333 0.666667 0 0.283333 0.708333 0 0.283333 0.750000 0 0.283333 0.791667 0 0.283333 0.833333 0 0.283333 0.875000 0 0.283333 0.916667 0 0.283333 0.958333 0 0.283333 1.000000 0 0.291667 0 0 0.291667 0.041667 0 0.291667 0.083333 0 0.291667 0.125000 0 0.291667 0.166667 0 0.291667 0.208333 0 0.291667 0.250000 0 0.291667 0.291667 0 0.291667 0.333333 0 0.291667 0.375000 0 0.291667 0.416667 0 0.291667 0.458333 0 0.291667 0.500000 0 0.291667 0.541667 0 0.291667 0.583333 0 0.291667 0.625000 0 0.291667 0.666667 0 0.291667 0.708333 0 0.291667 0.750000 0 0.291667 0.791667 0 0.291667 0.833333 0 0.291667 0.875000 0 0.291667 0.916667 0 0.291667 0.958333 0 0.291667 1.000000 0 0.300000 0 0 0.300000 0.041667 0 0.300000 0.083333 0 0.300000 0.125000 0 0.300000 0.166667 0 0.300000 0.208333 0 0.300000 0.250000 0 0.300000 0.291667 0 0.300000 0.333333 0 0.300000 0.375000 0 0.300000 0.416667 0 0.300000 0.458333 0 0.300000 0.500000 0 0.300000 0.541667 0 0.300000 0.583333 0 0.300000 0.625000 0 0.300000 0.666667 0 0.300000 0.708333 0 0.300000 0.750000 0 0.300000 0.791667 0 0.300000 0.833333 0 0.300000 0.875000 0 0.300000 0.916667 0 0.300000 0.958333 0 0.300000 1.000000 0 0.308333 0 0 0.308333 0.041667 0 0.308333 0.083333 0 0.308333 0.125000 0 0.308333 0.166667 0 0.308333 0.208333 0 0.308333 0.250000 0 0.308333 0.291667 0 0.308333 0.333333 0 0.308333 0.375000 0 0.308333 0.416667 0 0.308333 0.458333 0 0.308333 0.500000 0 0.308333 0.541667 0 0.308333 0.583333 0 0.308333 0.625000 0 0.308333 0.666667 0 0.308333 0.708333 0 0.308333 0.750000 0 0.308333 0.791667 0 0.308333 0.833333 0 0.308333 0.875000 0 0.308333 0.916667 0 0.308333 0.958333 0 0.308333 1.000000 0 0.316666 0 0 0.316666 0.041667 0 0.316666 0.083333 0 0.316666 0.125000 0 0.316666 0.166667 0 0.316666 0.208333 0 0.316666 0.250000 0 0.316666 0.291667 0 0.316666 0.333333 0 0.316666 0.375000 0 0.316666 0.416667 0 0.316666 0.458333 0 0.316666 0.500000 0 0.316666 0.541667 0 0.316666 0.583333 0 0.316666 0.625000 0 0.316666 0.666667 0 0.316666 0.708333 0 0.316666 0.750000 0 0.316666 0.791667 0 0.316666 0.833333 0 0.316666 0.875000 0 0.316666 0.916667 0 0.316666 0.958333 0 0.316666 1.000000 0 0.325000 0 0 0.325000 0.041667 0 0.325000 0.083333 0 0.325000 0.125000 0 0.325000 0.166667 0 0.325000 0.208333 0 0.325000 0.250000 0 0.325000 0.291667 0 0.325000 0.333333 0 0.325000 0.375000 0 0.325000 0.416667 0 0.325000 0.458333 0 0.325000 0.500000 0 0.325000 0.541667 0 0.325000 0.583333 0 0.325000 0.625000 0 0.325000 0.666667 0 0.325000 0.708333 0 0.325000 0.750000 0 0.325000 0.791667 0 0.325000 0.833333 0 0.325000 0.875000 0 0.325000 0.916667 0 0.325000 0.958333 0 0.325000 1.000000 0 0.333333 0 0 0.333333 0.041667 0 0.333333 0.083333 0 0.333333 0.125000 0 0.333333 0.166667 0 0.333333 0.208333 0 0.333333 0.250000 0 0.333333 0.291667 0 0.333333 0.333333 0 0.333333 0.375000 0 0.333333 0.416667 0 0.333333 0.458333 0 0.333333 0.500000 0 0.333333 0.541667 0 0.333333 0.583333 0 0.333333 0.625000 0 0.333333 0.666667 0 0.333333 0.708333 0 0.333333 0.750000 0 0.333333 0.791667 0 0.333333 0.833333 0 0.333333 0.875000 0 0.333333 0.916667 0 0.333333 0.958333 0 0.333333 1.000000 0 0.341666 0 0 0.341666 0.041667 0 0.341666 0.083333 0 0.341666 0.125000 0 0.341666 0.166667 0 0.341666 0.208333 0 0.341666 0.250000 0 0.341666 0.291667 0 0.341666 0.333333 0 0.341666 0.375000 0 0.341666 0.416667 0 0.341666 0.458333 0 0.341666 0.500000 0 0.341666 0.541667 0 0.341666 0.583333 0 0.341666 0.625000 0 0.341666 0.666667 0 0.341666 0.708333 0 0.341666 0.750000 0 0.341666 0.791667 0 0.341666 0.833333 0 0.341666 0.875000 0 0.341666 0.916667 0 0.341666 0.958333 0 0.341666 1.000000 0 0.350000 0 0 0.350000 0.041667 0 0.350000 0.083333 0 0.350000 0.125000 0 0.350000 0.166667 0 0.350000 0.208333 0 0.350000 0.250000 0 0.350000 0.291667 0 0.350000 0.333333 0 0.350000 0.375000 0 0.350000 0.416667 0 0.350000 0.458333 0 0.350000 0.500000 0 0.350000 0.541667 0 0.350000 0.583333 0 0.350000 0.625000 0 0.350000 0.666667 0 0.350000 0.708333 0 0.350000 0.750000 0 0.350000 0.791667 0 0.350000 0.833333 0 0.350000 0.875000 0 0.350000 0.916667 0 0.350000 0.958333 0 0.350000 1.000000 0 0.358333 0 0 0.358333 0.041667 0 0.358333 0.083333 0 0.358333 0.125000 0 0.358333 0.166667 0 0.358333 0.208333 0 0.358333 0.250000 0 0.358333 0.291667 0 0.358333 0.333333 0 0.358333 0.375000 0 0.358333 0.416667 0 0.358333 0.458333 0 0.358333 0.500000 0 0.358333 0.541667 0 0.358333 0.583333 0 0.358333 0.625000 0 0.358333 0.666667 0 0.358333 0.708333 0 0.358333 0.750000 0 0.358333 0.791667 0 0.358333 0.833333 0 0.358333 0.875000 0 0.358333 0.916667 0 0.358333 0.958333 0 0.358333 1.000000 0 0.366666 0 0 0.366666 0.041667 0 0.366666 0.083333 0 0.366666 0.125000 0 0.366666 0.166667 0 0.366666 0.208333 0 0.366666 0.250000 0 0.366666 0.291667 0 0.366666 0.333333 0 0.366666 0.375000 0 0.366666 0.416667 0 0.366666 0.458333 0 0.366666 0.500000 0 0.366666 0.541667 0 0.366666 0.583333 0 0.366666 0.625000 0 0.366666 0.666667 0 0.366666 0.708333 0 0.366666 0.750000 0 0.366666 0.791667 0 0.366666 0.833333 0 0.366666 0.875000 0 0.366666 0.916667 0 0.366666 0.958333 0 0.366666 1.000000 0 0.375000 0 0 0.375000 0.041667 0 0.375000 0.083333 0 0.375000 0.125000 0 0.375000 0.166667 0 0.375000 0.208333 0 0.375000 0.250000 0 0.375000 0.291667 0 0.375000 0.333333 0 0.375000 0.375000 0 0.375000 0.416667 0 0.375000 0.458333 0 0.375000 0.500000 0 0.375000 0.541667 0 0.375000 0.583333 0 0.375000 0.625000 0 0.375000 0.666667 0 0.375000 0.708333 0 0.375000 0.750000 0 0.375000 0.791667 0 0.375000 0.833333 0 0.375000 0.875000 0 0.375000 0.916667 0 0.375000 0.958333 0 0.375000 1.000000 0 0.383333 0 0 0.383333 0.041667 0 0.383333 0.083333 0 0.383333 0.125000 0 0.383333 0.166667 0 0.383333 0.208333 0 0.383333 0.250000 0 0.383333 0.291667 0 0.383333 0.333333 0 0.383333 0.375000 0 0.383333 0.416667 0 0.383333 0.458333 0 0.383333 0.500000 0 0.383333 0.541667 0 0.383333 0.583333 0 0.383333 0.625000 0 0.383333 0.666667 0 0.383333 0.708333 0 0.383333 0.750000 0 0.383333 0.791667 0 0.383333 0.833333 0 0.383333 0.875000 0 0.383333 0.916667 0 0.383333 0.958333 0 0.383333 1.000000 0 0.391666 0 0 0.391666 0.041667 0 0.391666 0.083333 0 0.391666 0.125000 0 0.391666 0.166667 0 0.391666 0.208333 0 0.391666 0.250000 0 0.391666 0.291667 0 0.391666 0.333333 0 0.391666 0.375000 0 0.391666 0.416667 0 0.391666 0.458333 0 0.391666 0.500000 0 0.391666 0.541667 0 0.391666 0.583333 0 0.391666 0.625000 0 0.391666 0.666667 0 0.391666 0.708333 0 0.391666 0.750000 0 0.391666 0.791667 0 0.391666 0.833333 0 0.391666 0.875000 0 0.391666 0.916667 0 0.391666 0.958333 0 0.391666 1.000000 0 0.400000 0 0 0.400000 0.041667 0 0.400000 0.083333 0 0.400000 0.125000 0 0.400000 0.166667 0 0.400000 0.208333 0 0.400000 0.250000 0 0.400000 0.291667 0 0.400000 0.333333 0 0.400000 0.375000 0 0.400000 0.416667 0 0.400000 0.458333 0 0.400000 0.500000 0 0.400000 0.541667 0 0.400000 0.583333 0 0.400000 0.625000 0 0.400000 0.666667 0 0.400000 0.708333 0 0.400000 0.750000 0 0.400000 0.791667 0 0.400000 0.833333 0 0.400000 0.875000 0 0.400000 0.916667 0 0.400000 0.958333 0 0.400000 1.000000 0 0.408333 0 0 0.408333 0.041667 0 0.408333 0.083333 0 0.408333 0.125000 0 0.408333 0.166667 0 0.408333 0.208333 0 0.408333 0.250000 0 0.408333 0.291667 0 0.408333 0.333333 0 0.408333 0.375000 0 0.408333 0.416667 0 0.408333 0.458333 0 0.408333 0.500000 0 0.408333 0.541667 0 0.408333 0.583333 0 0.408333 0.625000 0 0.408333 0.666667 0 0.408333 0.708333 0 0.408333 0.750000 0 0.408333 0.791667 0 0.408333 0.833333 0 0.408333 0.875000 0 0.408333 0.916667 0 0.408333 0.958333 0 0.408333 1.000000 0 0.416666 0 0 0.416666 0.041667 0 0.416666 0.083333 0 0.416666 0.125000 0 0.416666 0.166667 0 0.416666 0.208333 0 0.416666 0.250000 0 0.416666 0.291667 0 0.416666 0.333333 0 0.416666 0.375000 0 0.416666 0.416667 0 0.416666 0.458333 0 0.416666 0.500000 0 0.416666 0.541667 0 0.416666 0.583333 0 0.416666 0.625000 0 0.416666 0.666667 0 0.416666 0.708333 0 0.416666 0.750000 0 0.416666 0.791667 0 0.416666 0.833333 0 0.416666 0.875000 0 0.416666 0.916667 0 0.416666 0.958333 0 0.416666 1.000000 0 0.425000 0 0 0.425000 0.041667 0 0.425000 0.083333 0 0.425000 0.125000 0 0.425000 0.166667 0 0.425000 0.208333 0 0.425000 0.250000 0 0.425000 0.291667 0 0.425000 0.333333 0 0.425000 0.375000 0 0.425000 0.416667 0 0.425000 0.458333 0 0.425000 0.500000 0 0.425000 0.541667 0 0.425000 0.583333 0 0.425000 0.625000 0 0.425000 0.666667 0 0.425000 0.708333 0 0.425000 0.750000 0 0.425000 0.791667 0 0.425000 0.833333 0 0.425000 0.875000 0 0.425000 0.916667 0 0.425000 0.958333 0 0.425000 1.000000 0 0.433333 0 0 0.433333 0.041667 0 0.433333 0.083333 0 0.433333 0.125000 0 0.433333 0.166667 0 0.433333 0.208333 0 0.433333 0.250000 0 0.433333 0.291667 0 0.433333 0.333333 0 0.433333 0.375000 0 0.433333 0.416667 0 0.433333 0.458333 0 0.433333 0.500000 0 0.433333 0.541667 0 0.433333 0.583333 0 0.433333 0.625000 0 0.433333 0.666667 0 0.433333 0.708333 0 0.433333 0.750000 0 0.433333 0.791667 0 0.433333 0.833333 0 0.433333 0.875000 0 0.433333 0.916667 0 0.433333 0.958333 0 0.433333 1.000000 0 0.441666 0 0 0.441666 0.041667 0 0.441666 0.083333 0 0.441666 0.125000 0 0.441666 0.166667 0 0.441666 0.208333 0 0.441666 0.250000 0 0.441666 0.291667 0 0.441666 0.333333 0 0.441666 0.375000 0 0.441666 0.416667 0 0.441666 0.458333 0 0.441666 0.500000 0 0.441666 0.541667 0 0.441666 0.583333 0 0.441666 0.625000 0 0.441666 0.666667 0 0.441666 0.708333 0 0.441666 0.750000 0 0.441666 0.791667 0 0.441666 0.833333 0 0.441666 0.875000 0 0.441666 0.916667 0 0.441666 0.958333 0 0.441666 1.000000 0 0.450000 0 0 0.450000 0.041667 0 0.450000 0.083333 0 0.450000 0.125000 0 0.450000 0.166667 0 0.450000 0.208333 0 0.450000 0.250000 0 0.450000 0.291667 0 0.450000 0.333333 0 0.450000 0.375000 0 0.450000 0.416667 0 0.450000 0.458333 0 0.450000 0.500000 0 0.450000 0.541667 0 0.450000 0.583333 0 0.450000 0.625000 0 0.450000 0.666667 0 0.450000 0.708333 0 0.450000 0.750000 0 0.450000 0.791667 0 0.450000 0.833333 0 0.450000 0.875000 0 0.450000 0.916667 0 0.450000 0.958333 0 0.450000 1.000000 0 0.458333 0 0 0.458333 0.041667 0 0.458333 0.083333 0 0.458333 0.125000 0 0.458333 0.166667 0 0.458333 0.208333 0 0.458333 0.250000 0 0.458333 0.291667 0 0.458333 0.333333 0 0.458333 0.375000 0 0.458333 0.416667 0 0.458333 0.458333 0 0.458333 0.500000 0 0.458333 0.541667 0 0.458333 0.583333 0 0.458333 0.625000 0 0.458333 0.666667 0 0.458333 0.708333 0 0.458333 0.750000 0 0.458333 0.791667 0 0.458333 0.833333 0 0.458333 0.875000 0 0.458333 0.916667 0 0.458333 0.958333 0 0.458333 1.000000 0 0.466666 0 0 0.466666 0.041667 0 0.466666 0.083333 0 0.466666 0.125000 0 0.466666 0.166667 0 0.466666 0.208333 0 0.466666 0.250000 0 0.466666 0.291667 0 0.466666 0.333333 0 0.466666 0.375000 0 0.466666 0.416667 0 0.466666 0.458333 0 0.466666 0.500000 0 0.466666 0.541667 0 0.466666 0.583333 0 0.466666 0.625000 0 0.466666 0.666667 0 0.466666 0.708333 0 0.466666 0.750000 0 0.466666 0.791667 0 0.466666 0.833333 0 0.466666 0.875000 0 0.466666 0.916667 0 0.466666 0.958333 0 0.466666 1.000000 0 0.475000 0 0 0.475000 0.041667 0 0.475000 0.083333 0 0.475000 0.125000 0 0.475000 0.166667 0 0.475000 0.208333 0 0.475000 0.250000 0 0.475000 0.291667 0 0.475000 0.333333 0 0.475000 0.375000 0 0.475000 0.416667 0 0.475000 0.458333 0 0.475000 0.500000 0 0.475000 0.541667 0 0.475000 0.583333 0 0.475000 0.625000 0 0.475000 0.666667 0 0.475000 0.708333 0 0.475000 0.750000 0 0.475000 0.791667 0 0.475000 0.833333 0 0.475000 0.875000 0 0.475000 0.916667 0 0.475000 0.958333 0 0.475000 1.000000 0 0.483333 0 0 0.483333 0.041667 0 0.483333 0.083333 0 0.483333 0.125000 0 0.483333 0.166667 0 0.483333 0.208333 0 0.483333 0.250000 0 0.483333 0.291667 0 0.483333 0.333333 0 0.483333 0.375000 0 0.483333 0.416667 0 0.483333 0.458333 0 0.483333 0.500000 0 0.483333 0.541667 0 0.483333 0.583333 0 0.483333 0.625000 0 0.483333 0.666667 0 0.483333 0.708333 0 0.483333 0.750000 0 0.483333 0.791667 0 0.483333 0.833333 0 0.483333 0.875000 0 0.483333 0.916667 0 0.483333 0.958333 0 0.483333 1.000000 0 0.491666 0 0 0.491666 0.041667 0 0.491666 0.083333 0 0.491666 0.125000 0 0.491666 0.166667 0 0.491666 0.208333 0 0.491666 0.250000 0 0.491666 0.291667 0 0.491666 0.333333 0 0.491666 0.375000 0 0.491666 0.416667 0 0.491666 0.458333 0 0.491666 0.500000 0 0.491666 0.541667 0 0.491666 0.583333 0 0.491666 0.625000 0 0.491666 0.666667 0 0.491666 0.708333 0 0.491666 0.750000 0 0.491666 0.791667 0 0.491666 0.833333 0 0.491666 0.875000 0 0.491666 0.916667 0 0.491666 0.958333 0 0.491666 1.000000 0 0.500000 0 0 0.500000 0.041667 0 0.500000 0.083333 0 0.500000 0.125000 0 0.500000 0.166667 0 0.500000 0.208333 0 0.500000 0.250000 0 0.500000 0.291667 0 0.500000 0.333333 0 0.500000 0.375000 0 0.500000 0.416667 0 0.500000 0.458333 0 0.500000 0.500000 0 0.500000 0.541667 0 0.500000 0.583333 0 0.500000 0.625000 0 0.500000 0.666667 0 0.500000 0.708333 0 0.500000 0.750000 0 0.500000 0.791667 0 0.500000 0.833333 0 0.500000 0.875000 0 0.500000 0.916667 0 0.500000 0.958333 0 0.500000 1.000000 0 0.508333 0 0 0.508333 0.041667 0 0.508333 0.083333 0 0.508333 0.125000 0 0.508333 0.166667 0 0.508333 0.208333 0 0.508333 0.250000 0 0.508333 0.291667 0 0.508333 0.333333 0 0.508333 0.375000 0 0.508333 0.416667 0 0.508333 0.458333 0 0.508333 0.500000 0 0.508333 0.541667 0 0.508333 0.583333 0 0.508333 0.625000 0 0.508333 0.666667 0 0.508333 0.708333 0 0.508333 0.750000 0 0.508333 0.791667 0 0.508333 0.833333 0 0.508333 0.875000 0 0.508333 0.916667 0 0.508333 0.958333 0 0.508333 1.000000 0 0.516666 0 0 0.516666 0.041667 0 0.516666 0.083333 0 0.516666 0.125000 0 0.516666 0.166667 0 0.516666 0.208333 0 0.516666 0.250000 0 0.516666 0.291667 0 0.516666 0.333333 0 0.516666 0.375000 0 0.516666 0.416667 0 0.516666 0.458333 0 0.516666 0.500000 0 0.516666 0.541667 0 0.516666 0.583333 0 0.516666 0.625000 0 0.516666 0.666667 0 0.516666 0.708333 0 0.516666 0.750000 0 0.516666 0.791667 0 0.516666 0.833333 0 0.516666 0.875000 0 0.516666 0.916667 0 0.516666 0.958333 0 0.516666 1.000000 0 0.525000 0 0 0.525000 0.041667 0 0.525000 0.083333 0 0.525000 0.125000 0 0.525000 0.166667 0 0.525000 0.208333 0 0.525000 0.250000 0 0.525000 0.291667 0 0.525000 0.333333 0 0.525000 0.375000 0 0.525000 0.416667 0 0.525000 0.458333 0 0.525000 0.500000 0 0.525000 0.541667 0 0.525000 0.583333 0 0.525000 0.625000 0 0.525000 0.666667 0 0.525000 0.708333 0 0.525000 0.750000 0 0.525000 0.791667 0 0.525000 0.833333 0 0.525000 0.875000 0 0.525000 0.916667 0 0.525000 0.958333 0 0.525000 1.000000 0 0.533333 0 0 0.533333 0.041667 0 0.533333 0.083333 0 0.533333 0.125000 0 0.533333 0.166667 0 0.533333 0.208333 0 0.533333 0.250000 0 0.533333 0.291667 0 0.533333 0.333333 0 0.533333 0.375000 0 0.533333 0.416667 0 0.533333 0.458333 0 0.533333 0.500000 0 0.533333 0.541667 0 0.533333 0.583333 0 0.533333 0.625000 0 0.533333 0.666667 0 0.533333 0.708333 0 0.533333 0.750000 0 0.533333 0.791667 0 0.533333 0.833333 0 0.533333 0.875000 0 0.533333 0.916667 0 0.533333 0.958333 0 0.533333 1.000000 0 0.541666 0 0 0.541666 0.041667 0 0.541666 0.083333 0 0.541666 0.125000 0 0.541666 0.166667 0 0.541666 0.208333 0 0.541666 0.250000 0 0.541666 0.291667 0 0.541666 0.333333 0 0.541666 0.375000 0 0.541666 0.416667 0 0.541666 0.458333 0 0.541666 0.500000 0 0.541666 0.541667 0 0.541666 0.583333 0 0.541666 0.625000 0 0.541666 0.666667 0 0.541666 0.708333 0 0.541666 0.750000 0 0.541666 0.791667 0 0.541666 0.833333 0 0.541666 0.875000 0 0.541666 0.916667 0 0.541666 0.958333 0 0.541666 1.000000 0 0.550000 0 0 0.550000 0.041667 0 0.550000 0.083333 0 0.550000 0.125000 0 0.550000 0.166667 0 0.550000 0.208333 0 0.550000 0.250000 0 0.550000 0.291667 0 0.550000 0.333333 0 0.550000 0.375000 0 0.550000 0.416667 0 0.550000 0.458333 0 0.550000 0.500000 0 0.550000 0.541667 0 0.550000 0.583333 0 0.550000 0.625000 0 0.550000 0.666667 0 0.550000 0.708333 0 0.550000 0.750000 0 0.550000 0.791667 0 0.550000 0.833333 0 0.550000 0.875000 0 0.550000 0.916667 0 0.550000 0.958333 0 0.550000 1.000000 0 0.558333 0 0 0.558333 0.041667 0 0.558333 0.083333 0 0.558333 0.125000 0 0.558333 0.166667 0 0.558333 0.208333 0 0.558333 0.250000 0 0.558333 0.291667 0 0.558333 0.333333 0 0.558333 0.375000 0 0.558333 0.416667 0 0.558333 0.458333 0 0.558333 0.500000 0 0.558333 0.541667 0 0.558333 0.583333 0 0.558333 0.625000 0 0.558333 0.666667 0 0.558333 0.708333 0 0.558333 0.750000 0 0.558333 0.791667 0 0.558333 0.833333 0 0.558333 0.875000 0 0.558333 0.916667 0 0.558333 0.958333 0 0.558333 1.000000 0 0.566666 0 0 0.566666 0.041667 0 0.566666 0.083333 0 0.566666 0.125000 0 0.566666 0.166667 0 0.566666 0.208333 0 0.566666 0.250000 0 0.566666 0.291667 0 0.566666 0.333333 0 0.566666 0.375000 0 0.566666 0.416667 0 0.566666 0.458333 0 0.566666 0.500000 0 0.566666 0.541667 0 0.566666 0.583333 0 0.566666 0.625000 0 0.566666 0.666667 0 0.566666 0.708333 0 0.566666 0.750000 0 0.566666 0.791667 0 0.566666 0.833333 0 0.566666 0.875000 0 0.566666 0.916667 0 0.566666 0.958333 0 0.566666 1.000000 0 0.575000 0 0 0.575000 0.041667 0 0.575000 0.083333 0 0.575000 0.125000 0 0.575000 0.166667 0 0.575000 0.208333 0 0.575000 0.250000 0 0.575000 0.291667 0 0.575000 0.333333 0 0.575000 0.375000 0 0.575000 0.416667 0 0.575000 0.458333 0 0.575000 0.500000 0 0.575000 0.541667 0 0.575000 0.583333 0 0.575000 0.625000 0 0.575000 0.666667 0 0.575000 0.708333 0 0.575000 0.750000 0 0.575000 0.791667 0 0.575000 0.833333 0 0.575000 0.875000 0 0.575000 0.916667 0 0.575000 0.958333 0 0.575000 1.000000 0 0.583333 0 0 0.583333 0.041667 0 0.583333 0.083333 0 0.583333 0.125000 0 0.583333 0.166667 0 0.583333 0.208333 0 0.583333 0.250000 0 0.583333 0.291667 0 0.583333 0.333333 0 0.583333 0.375000 0 0.583333 0.416667 0 0.583333 0.458333 0 0.583333 0.500000 0 0.583333 0.541667 0 0.583333 0.583333 0 0.583333 0.625000 0 0.583333 0.666667 0 0.583333 0.708333 0 0.583333 0.750000 0 0.583333 0.791667 0 0.583333 0.833333 0 0.583333 0.875000 0 0.583333 0.916667 0 0.583333 0.958333 0 0.583333 1.000000 0 0.591666 0 0 0.591666 0.041667 0 0.591666 0.083333 0 0.591666 0.125000 0 0.591666 0.166667 0 0.591666 0.208333 0 0.591666 0.250000 0 0.591666 0.291667 0 0.591666 0.333333 0 0.591666 0.375000 0 0.591666 0.416667 0 0.591666 0.458333 0 0.591666 0.500000 0 0.591666 0.541667 0 0.591666 0.583333 0 0.591666 0.625000 0 0.591666 0.666667 0 0.591666 0.708333 0 0.591666 0.750000 0 0.591666 0.791667 0 0.591666 0.833333 0 0.591666 0.875000 0 0.591666 0.916667 0 0.591666 0.958333 0 0.591666 1.000000 0 0.599999 0 0 0.599999 0.041667 0 0.599999 0.083333 0 0.599999 0.125000 0 0.599999 0.166667 0 0.599999 0.208333 0 0.599999 0.250000 0 0.599999 0.291667 0 0.599999 0.333333 0 0.599999 0.375000 0 0.599999 0.416667 0 0.599999 0.458333 0 0.599999 0.500000 0 0.599999 0.541667 0 0.599999 0.583333 0 0.599999 0.625000 0 0.599999 0.666667 0 0.599999 0.708333 0 0.599999 0.750000 0 0.599999 0.791667 0 0.599999 0.833333 0 0.599999 0.875000 0 0.599999 0.916667 0 0.599999 0.958333 0 0.599999 1.000000 0 0.608333 0 0 0.608333 0.041667 0 0.608333 0.083333 0 0.608333 0.125000 0 0.608333 0.166667 0 0.608333 0.208333 0 0.608333 0.250000 0 0.608333 0.291667 0 0.608333 0.333333 0 0.608333 0.375000 0 0.608333 0.416667 0 0.608333 0.458333 0 0.608333 0.500000 0 0.608333 0.541667 0 0.608333 0.583333 0 0.608333 0.625000 0 0.608333 0.666667 0 0.608333 0.708333 0 0.608333 0.750000 0 0.608333 0.791667 0 0.608333 0.833333 0 0.608333 0.875000 0 0.608333 0.916667 0 0.608333 0.958333 0 0.608333 1.000000 0 0.616666 0 0 0.616666 0.041667 0 0.616666 0.083333 0 0.616666 0.125000 0 0.616666 0.166667 0 0.616666 0.208333 0 0.616666 0.250000 0 0.616666 0.291667 0 0.616666 0.333333 0 0.616666 0.375000 0 0.616666 0.416667 0 0.616666 0.458333 0 0.616666 0.500000 0 0.616666 0.541667 0 0.616666 0.583333 0 0.616666 0.625000 0 0.616666 0.666667 0 0.616666 0.708333 0 0.616666 0.750000 0 0.616666 0.791667 0 0.616666 0.833333 0 0.616666 0.875000 0 0.616666 0.916667 0 0.616666 0.958333 0 0.616666 1.000000 0 0.624999 0 0 0.624999 0.041667 0 0.624999 0.083333 0 0.624999 0.125000 0 0.624999 0.166667 0 0.624999 0.208333 0 0.624999 0.250000 0 0.624999 0.291667 0 0.624999 0.333333 0 0.624999 0.375000 0 0.624999 0.416667 0 0.624999 0.458333 0 0.624999 0.500000 0 0.624999 0.541667 0 0.624999 0.583333 0 0.624999 0.625000 0 0.624999 0.666667 0 0.624999 0.708333 0 0.624999 0.750000 0 0.624999 0.791667 0 0.624999 0.833333 0 0.624999 0.875000 0 0.624999 0.916667 0 0.624999 0.958333 0 0.624999 1.000000 0 0.633333 0 0 0.633333 0.041667 0 0.633333 0.083333 0 0.633333 0.125000 0 0.633333 0.166667 0 0.633333 0.208333 0 0.633333 0.250000 0 0.633333 0.291667 0 0.633333 0.333333 0 0.633333 0.375000 0 0.633333 0.416667 0 0.633333 0.458333 0 0.633333 0.500000 0 0.633333 0.541667 0 0.633333 0.583333 0 0.633333 0.625000 0 0.633333 0.666667 0 0.633333 0.708333 0 0.633333 0.750000 0 0.633333 0.791667 0 0.633333 0.833333 0 0.633333 0.875000 0 0.633333 0.916667 0 0.633333 0.958333 0 0.633333 1.000000 0 0.641666 0 0 0.641666 0.041667 0 0.641666 0.083333 0 0.641666 0.125000 0 0.641666 0.166667 0 0.641666 0.208333 0 0.641666 0.250000 0 0.641666 0.291667 0 0.641666 0.333333 0 0.641666 0.375000 0 0.641666 0.416667 0 0.641666 0.458333 0 0.641666 0.500000 0 0.641666 0.541667 0 0.641666 0.583333 0 0.641666 0.625000 0 0.641666 0.666667 0 0.641666 0.708333 0 0.641666 0.750000 0 0.641666 0.791667 0 0.641666 0.833333 0 0.641666 0.875000 0 0.641666 0.916667 0 0.641666 0.958333 0 0.641666 1.000000 0 0.649999 0 0 0.649999 0.041667 0 0.649999 0.083333 0 0.649999 0.125000 0 0.649999 0.166667 0 0.649999 0.208333 0 0.649999 0.250000 0 0.649999 0.291667 0 0.649999 0.333333 0 0.649999 0.375000 0 0.649999 0.416667 0 0.649999 0.458333 0 0.649999 0.500000 0 0.649999 0.541667 0 0.649999 0.583333 0 0.649999 0.625000 0 0.649999 0.666667 0 0.649999 0.708333 0 0.649999 0.750000 0 0.649999 0.791667 0 0.649999 0.833333 0 0.649999 0.875000 0 0.649999 0.916667 0 0.649999 0.958333 0 0.649999 1.000000 0 0.658333 0 0 0.658333 0.041667 0 0.658333 0.083333 0 0.658333 0.125000 0 0.658333 0.166667 0 0.658333 0.208333 0 0.658333 0.250000 0 0.658333 0.291667 0 0.658333 0.333333 0 0.658333 0.375000 0 0.658333 0.416667 0 0.658333 0.458333 0 0.658333 0.500000 0 0.658333 0.541667 0 0.658333 0.583333 0 0.658333 0.625000 0 0.658333 0.666667 0 0.658333 0.708333 0 0.658333 0.750000 0 0.658333 0.791667 0 0.658333 0.833333 0 0.658333 0.875000 0 0.658333 0.916667 0 0.658333 0.958333 0 0.658333 1.000000 0 0.666666 0 0 0.666666 0.041667 0 0.666666 0.083333 0 0.666666 0.125000 0 0.666666 0.166667 0 0.666666 0.208333 0 0.666666 0.250000 0 0.666666 0.291667 0 0.666666 0.333333 0 0.666666 0.375000 0 0.666666 0.416667 0 0.666666 0.458333 0 0.666666 0.500000 0 0.666666 0.541667 0 0.666666 0.583333 0 0.666666 0.625000 0 0.666666 0.666667 0 0.666666 0.708333 0 0.666666 0.750000 0 0.666666 0.791667 0 0.666666 0.833333 0 0.666666 0.875000 0 0.666666 0.916667 0 0.666666 0.958333 0 0.666666 1.000000 0 0.675000 0 0 0.675000 0.041667 0 0.675000 0.083333 0 0.675000 0.125000 0 0.675000 0.166667 0 0.675000 0.208333 0 0.675000 0.250000 0 0.675000 0.291667 0 0.675000 0.333333 0 0.675000 0.375000 0 0.675000 0.416667 0 0.675000 0.458333 0 0.675000 0.500000 0 0.675000 0.541667 0 0.675000 0.583333 0 0.675000 0.625000 0 0.675000 0.666667 0 0.675000 0.708333 0 0.675000 0.750000 0 0.675000 0.791667 0 0.675000 0.833333 0 0.675000 0.875000 0 0.675000 0.916667 0 0.675000 0.958333 0 0.675000 1.000000 0 0.683333 0 0 0.683333 0.041667 0 0.683333 0.083333 0 0.683333 0.125000 0 0.683333 0.166667 0 0.683333 0.208333 0 0.683333 0.250000 0 0.683333 0.291667 0 0.683333 0.333333 0 0.683333 0.375000 0 0.683333 0.416667 0 0.683333 0.458333 0 0.683333 0.500000 0 0.683333 0.541667 0 0.683333 0.583333 0 0.683333 0.625000 0 0.683333 0.666667 0 0.683333 0.708333 0 0.683333 0.750000 0 0.683333 0.791667 0 0.683333 0.833333 0 0.683333 0.875000 0 0.683333 0.916667 0 0.683333 0.958333 0 0.683333 1.000000 0 0.691666 0 0 0.691666 0.041667 0 0.691666 0.083333 0 0.691666 0.125000 0 0.691666 0.166667 0 0.691666 0.208333 0 0.691666 0.250000 0 0.691666 0.291667 0 0.691666 0.333333 0 0.691666 0.375000 0 0.691666 0.416667 0 0.691666 0.458333 0 0.691666 0.500000 0 0.691666 0.541667 0 0.691666 0.583333 0 0.691666 0.625000 0 0.691666 0.666667 0 0.691666 0.708333 0 0.691666 0.750000 0 0.691666 0.791667 0 0.691666 0.833333 0 0.691666 0.875000 0 0.691666 0.916667 0 0.691666 0.958333 0 0.691666 1.000000 0 0.700000 0 0 0.700000 0.041667 0 0.700000 0.083333 0 0.700000 0.125000 0 0.700000 0.166667 0 0.700000 0.208333 0 0.700000 0.250000 0 0.700000 0.291667 0 0.700000 0.333333 0 0.700000 0.375000 0 0.700000 0.416667 0 0.700000 0.458333 0 0.700000 0.500000 0 0.700000 0.541667 0 0.700000 0.583333 0 0.700000 0.625000 0 0.700000 0.666667 0 0.700000 0.708333 0 0.700000 0.750000 0 0.700000 0.791667 0 0.700000 0.833333 0 0.700000 0.875000 0 0.700000 0.916667 0 0.700000 0.958333 0 0.700000 1.000000 0 0.708333 0 0 0.708333 0.041667 0 0.708333 0.083333 0 0.708333 0.125000 0 0.708333 0.166667 0 0.708333 0.208333 0 0.708333 0.250000 0 0.708333 0.291667 0 0.708333 0.333333 0 0.708333 0.375000 0 0.708333 0.416667 0 0.708333 0.458333 0 0.708333 0.500000 0 0.708333 0.541667 0 0.708333 0.583333 0 0.708333 0.625000 0 0.708333 0.666667 0 0.708333 0.708333 0 0.708333 0.750000 0 0.708333 0.791667 0 0.708333 0.833333 0 0.708333 0.875000 0 0.708333 0.916667 0 0.708333 0.958333 0 0.708333 1.000000 0 0.716666 0 0 0.716666 0.041667 0 0.716666 0.083333 0 0.716666 0.125000 0 0.716666 0.166667 0 0.716666 0.208333 0 0.716666 0.250000 0 0.716666 0.291667 0 0.716666 0.333333 0 0.716666 0.375000 0 0.716666 0.416667 0 0.716666 0.458333 0 0.716666 0.500000 0 0.716666 0.541667 0 0.716666 0.583333 0 0.716666 0.625000 0 0.716666 0.666667 0 0.716666 0.708333 0 0.716666 0.750000 0 0.716666 0.791667 0 0.716666 0.833333 0 0.716666 0.875000 0 0.716666 0.916667 0 0.716666 0.958333 0 0.716666 1.000000 0 0.725000 0 0 0.725000 0.041667 0 0.725000 0.083333 0 0.725000 0.125000 0 0.725000 0.166667 0 0.725000 0.208333 0 0.725000 0.250000 0 0.725000 0.291667 0 0.725000 0.333333 0 0.725000 0.375000 0 0.725000 0.416667 0 0.725000 0.458333 0 0.725000 0.500000 0 0.725000 0.541667 0 0.725000 0.583333 0 0.725000 0.625000 0 0.725000 0.666667 0 0.725000 0.708333 0 0.725000 0.750000 0 0.725000 0.791667 0 0.725000 0.833333 0 0.725000 0.875000 0 0.725000 0.916667 0 0.725000 0.958333 0 0.725000 1.000000 0 0.733333 0 0 0.733333 0.041667 0 0.733333 0.083333 0 0.733333 0.125000 0 0.733333 0.166667 0 0.733333 0.208333 0 0.733333 0.250000 0 0.733333 0.291667 0 0.733333 0.333333 0 0.733333 0.375000 0 0.733333 0.416667 0 0.733333 0.458333 0 0.733333 0.500000 0 0.733333 0.541667 0 0.733333 0.583333 0 0.733333 0.625000 0 0.733333 0.666667 0 0.733333 0.708333 0 0.733333 0.750000 0 0.733333 0.791667 0 0.733333 0.833333 0 0.733333 0.875000 0 0.733333 0.916667 0 0.733333 0.958333 0 0.733333 1.000000 0 0.741666 0 0 0.741666 0.041667 0 0.741666 0.083333 0 0.741666 0.125000 0 0.741666 0.166667 0 0.741666 0.208333 0 0.741666 0.250000 0 0.741666 0.291667 0 0.741666 0.333333 0 0.741666 0.375000 0 0.741666 0.416667 0 0.741666 0.458333 0 0.741666 0.500000 0 0.741666 0.541667 0 0.741666 0.583333 0 0.741666 0.625000 0 0.741666 0.666667 0 0.741666 0.708333 0 0.741666 0.750000 0 0.741666 0.791667 0 0.741666 0.833333 0 0.741666 0.875000 0 0.741666 0.916667 0 0.741666 0.958333 0 0.741666 1.000000 0 0.750000 0 0 0.750000 0.041667 0 0.750000 0.083333 0 0.750000 0.125000 0 0.750000 0.166667 0 0.750000 0.208333 0 0.750000 0.250000 0 0.750000 0.291667 0 0.750000 0.333333 0 0.750000 0.375000 0 0.750000 0.416667 0 0.750000 0.458333 0 0.750000 0.500000 0 0.750000 0.541667 0 0.750000 0.583333 0 0.750000 0.625000 0 0.750000 0.666667 0 0.750000 0.708333 0 0.750000 0.750000 0 0.750000 0.791667 0 0.750000 0.833333 0 0.750000 0.875000 0 0.750000 0.916667 0 0.750000 0.958333 0 0.750000 1.000000 0 0.758333 0 0 0.758333 0.041667 0 0.758333 0.083333 0 0.758333 0.125000 0 0.758333 0.166667 0 0.758333 0.208333 0 0.758333 0.250000 0 0.758333 0.291667 0 0.758333 0.333333 0 0.758333 0.375000 0 0.758333 0.416667 0 0.758333 0.458333 0 0.758333 0.500000 0 0.758333 0.541667 0 0.758333 0.583333 0 0.758333 0.625000 0 0.758333 0.666667 0 0.758333 0.708333 0 0.758333 0.750000 0 0.758333 0.791667 0 0.758333 0.833333 0 0.758333 0.875000 0 0.758333 0.916667 0 0.758333 0.958333 0 0.758333 1.000000 0 0.766667 0 0 0.766667 0.041667 0 0.766667 0.083333 0 0.766667 0.125000 0 0.766667 0.166667 0 0.766667 0.208333 0 0.766667 0.250000 0 0.766667 0.291667 0 0.766667 0.333333 0 0.766667 0.375000 0 0.766667 0.416667 0 0.766667 0.458333 0 0.766667 0.500000 0 0.766667 0.541667 0 0.766667 0.583333 0 0.766667 0.625000 0 0.766667 0.666667 0 0.766667 0.708333 0 0.766667 0.750000 0 0.766667 0.791667 0 0.766667 0.833333 0 0.766667 0.875000 0 0.766667 0.916667 0 0.766667 0.958333 0 0.766667 1.000000 0 0.775000 0 0 0.775000 0.041667 0 0.775000 0.083333 0 0.775000 0.125000 0 0.775000 0.166667 0 0.775000 0.208333 0 0.775000 0.250000 0 0.775000 0.291667 0 0.775000 0.333333 0 0.775000 0.375000 0 0.775000 0.416667 0 0.775000 0.458333 0 0.775000 0.500000 0 0.775000 0.541667 0 0.775000 0.583333 0 0.775000 0.625000 0 0.775000 0.666667 0 0.775000 0.708333 0 0.775000 0.750000 0 0.775000 0.791667 0 0.775000 0.833333 0 0.775000 0.875000 0 0.775000 0.916667 0 0.775000 0.958333 0 0.775000 1.000000 0 0.783333 0 0 0.783333 0.041667 0 0.783333 0.083333 0 0.783333 0.125000 0 0.783333 0.166667 0 0.783333 0.208333 0 0.783333 0.250000 0 0.783333 0.291667 0 0.783333 0.333333 0 0.783333 0.375000 0 0.783333 0.416667 0 0.783333 0.458333 0 0.783333 0.500000 0 0.783333 0.541667 0 0.783333 0.583333 0 0.783333 0.625000 0 0.783333 0.666667 0 0.783333 0.708333 0 0.783333 0.750000 0 0.783333 0.791667 0 0.783333 0.833333 0 0.783333 0.875000 0 0.783333 0.916667 0 0.783333 0.958333 0 0.783333 1.000000 0 0.791667 0 0 0.791667 0.041667 0 0.791667 0.083333 0 0.791667 0.125000 0 0.791667 0.166667 0 0.791667 0.208333 0 0.791667 0.250000 0 0.791667 0.291667 0 0.791667 0.333333 0 0.791667 0.375000 0 0.791667 0.416667 0 0.791667 0.458333 0 0.791667 0.500000 0 0.791667 0.541667 0 0.791667 0.583333 0 0.791667 0.625000 0 0.791667 0.666667 0 0.791667 0.708333 0 0.791667 0.750000 0 0.791667 0.791667 0 0.791667 0.833333 0 0.791667 0.875000 0 0.791667 0.916667 0 0.791667 0.958333 0 0.791667 1.000000 0 0.800000 0 0 0.800000 0.041667 0 0.800000 0.083333 0 0.800000 0.125000 0 0.800000 0.166667 0 0.800000 0.208333 0 0.800000 0.250000 0 0.800000 0.291667 0 0.800000 0.333333 0 0.800000 0.375000 0 0.800000 0.416667 0 0.800000 0.458333 0 0.800000 0.500000 0 0.800000 0.541667 0 0.800000 0.583333 0 0.800000 0.625000 0 0.800000 0.666667 0 0.800000 0.708333 0 0.800000 0.750000 0 0.800000 0.791667 0 0.800000 0.833333 0 0.800000 0.875000 0 0.800000 0.916667 0 0.800000 0.958333 0 0.800000 1.000000 0 0.808333 0 0 0.808333 0.041667 0 0.808333 0.083333 0 0.808333 0.125000 0 0.808333 0.166667 0 0.808333 0.208333 0 0.808333 0.250000 0 0.808333 0.291667 0 0.808333 0.333333 0 0.808333 0.375000 0 0.808333 0.416667 0 0.808333 0.458333 0 0.808333 0.500000 0 0.808333 0.541667 0 0.808333 0.583333 0 0.808333 0.625000 0 0.808333 0.666667 0 0.808333 0.708333 0 0.808333 0.750000 0 0.808333 0.791667 0 0.808333 0.833333 0 0.808333 0.875000 0 0.808333 0.916667 0 0.808333 0.958333 0 0.808333 1.000000 0 0.816667 0 0 0.816667 0.041667 0 0.816667 0.083333 0 0.816667 0.125000 0 0.816667 0.166667 0 0.816667 0.208333 0 0.816667 0.250000 0 0.816667 0.291667 0 0.816667 0.333333 0 0.816667 0.375000 0 0.816667 0.416667 0 0.816667 0.458333 0 0.816667 0.500000 0 0.816667 0.541667 0 0.816667 0.583333 0 0.816667 0.625000 0 0.816667 0.666667 0 0.816667 0.708333 0 0.816667 0.750000 0 0.816667 0.791667 0 0.816667 0.833333 0 0.816667 0.875000 0 0.816667 0.916667 0 0.816667 0.958333 0 0.816667 1.000000 0 0.825000 0 0 0.825000 0.041667 0 0.825000 0.083333 0 0.825000 0.125000 0 0.825000 0.166667 0 0.825000 0.208333 0 0.825000 0.250000 0 0.825000 0.291667 0 0.825000 0.333333 0 0.825000 0.375000 0 0.825000 0.416667 0 0.825000 0.458333 0 0.825000 0.500000 0 0.825000 0.541667 0 0.825000 0.583333 0 0.825000 0.625000 0 0.825000 0.666667 0 0.825000 0.708333 0 0.825000 0.750000 0 0.825000 0.791667 0 0.825000 0.833333 0 0.825000 0.875000 0 0.825000 0.916667 0 0.825000 0.958333 0 0.825000 1.000000 0 0.833333 0 0 0.833333 0.041667 0 0.833333 0.083333 0 0.833333 0.125000 0 0.833333 0.166667 0 0.833333 0.208333 0 0.833333 0.250000 0 0.833333 0.291667 0 0.833333 0.333333 0 0.833333 0.375000 0 0.833333 0.416667 0 0.833333 0.458333 0 0.833333 0.500000 0 0.833333 0.541667 0 0.833333 0.583333 0 0.833333 0.625000 0 0.833333 0.666667 0 0.833333 0.708333 0 0.833333 0.750000 0 0.833333 0.791667 0 0.833333 0.833333 0 0.833333 0.875000 0 0.833333 0.916667 0 0.833333 0.958333 0 0.833333 1.000000 0 0.841667 0 0 0.841667 0.041667 0 0.841667 0.083333 0 0.841667 0.125000 0 0.841667 0.166667 0 0.841667 0.208333 0 0.841667 0.250000 0 0.841667 0.291667 0 0.841667 0.333333 0 0.841667 0.375000 0 0.841667 0.416667 0 0.841667 0.458333 0 0.841667 0.500000 0 0.841667 0.541667 0 0.841667 0.583333 0 0.841667 0.625000 0 0.841667 0.666667 0 0.841667 0.708333 0 0.841667 0.750000 0 0.841667 0.791667 0 0.841667 0.833333 0 0.841667 0.875000 0 0.841667 0.916667 0 0.841667 0.958333 0 0.841667 1.000000 0 0.850000 0 0 0.850000 0.041667 0 0.850000 0.083333 0 0.850000 0.125000 0 0.850000 0.166667 0 0.850000 0.208333 0 0.850000 0.250000 0 0.850000 0.291667 0 0.850000 0.333333 0 0.850000 0.375000 0 0.850000 0.416667 0 0.850000 0.458333 0 0.850000 0.500000 0 0.850000 0.541667 0 0.850000 0.583333 0 0.850000 0.625000 0 0.850000 0.666667 0 0.850000 0.708333 0 0.850000 0.750000 0 0.850000 0.791667 0 0.850000 0.833333 0 0.850000 0.875000 0 0.850000 0.916667 0 0.850000 0.958333 0 0.850000 1.000000 0 0.858334 0 0 0.858334 0.041667 0 0.858334 0.083333 0 0.858334 0.125000 0 0.858334 0.166667 0 0.858334 0.208333 0 0.858334 0.250000 0 0.858334 0.291667 0 0.858334 0.333333 0 0.858334 0.375000 0 0.858334 0.416667 0 0.858334 0.458333 0 0.858334 0.500000 0 0.858334 0.541667 0 0.858334 0.583333 0 0.858334 0.625000 0 0.858334 0.666667 0 0.858334 0.708333 0 0.858334 0.750000 0 0.858334 0.791667 0 0.858334 0.833333 0 0.858334 0.875000 0 0.858334 0.916667 0 0.858334 0.958333 0 0.858334 1.000000 0 0.866667 0 0 0.866667 0.041667 0 0.866667 0.083333 0 0.866667 0.125000 0 0.866667 0.166667 0 0.866667 0.208333 0 0.866667 0.250000 0 0.866667 0.291667 0 0.866667 0.333333 0 0.866667 0.375000 0 0.866667 0.416667 0 0.866667 0.458333 0 0.866667 0.500000 0 0.866667 0.541667 0 0.866667 0.583333 0 0.866667 0.625000 0 0.866667 0.666667 0 0.866667 0.708333 0 0.866667 0.750000 0 0.866667 0.791667 0 0.866667 0.833333 0 0.866667 0.875000 0 0.866667 0.916667 0 0.866667 0.958333 0 0.866667 1.000000 0 0.875000 0 0 0.875000 0.041667 0 0.875000 0.083333 0 0.875000 0.125000 0 0.875000 0.166667 0 0.875000 0.208333 0 0.875000 0.250000 0 0.875000 0.291667 0 0.875000 0.333333 0 0.875000 0.375000 0 0.875000 0.416667 0 0.875000 0.458333 0 0.875000 0.500000 0 0.875000 0.541667 0 0.875000 0.583333 0 0.875000 0.625000 0 0.875000 0.666667 0 0.875000 0.708333 0 0.875000 0.750000 0 0.875000 0.791667 0 0.875000 0.833333 0 0.875000 0.875000 0 0.875000 0.916667 0 0.875000 0.958333 0 0.875000 1.000000 0 0.883334 0 0 0.883334 0.041667 0 0.883334 0.083333 0 0.883334 0.125000 0 0.883334 0.166667 0 0.883334 0.208333 0 0.883334 0.250000 0 0.883334 0.291667 0 0.883334 0.333333 0 0.883334 0.375000 0 0.883334 0.416667 0 0.883334 0.458333 0 0.883334 0.500000 0 0.883334 0.541667 0 0.883334 0.583333 0 0.883334 0.625000 0 0.883334 0.666667 0 0.883334 0.708333 0 0.883334 0.750000 0 0.883334 0.791667 0 0.883334 0.833333 0 0.883334 0.875000 0 0.883334 0.916667 0 0.883334 0.958333 0 0.883334 1.000000 0 0.891667 0 0 0.891667 0.041667 0 0.891667 0.083333 0 0.891667 0.125000 0 0.891667 0.166667 0 0.891667 0.208333 0 0.891667 0.250000 0 0.891667 0.291667 0 0.891667 0.333333 0 0.891667 0.375000 0 0.891667 0.416667 0 0.891667 0.458333 0 0.891667 0.500000 0 0.891667 0.541667 0 0.891667 0.583333 0 0.891667 0.625000 0 0.891667 0.666667 0 0.891667 0.708333 0 0.891667 0.750000 0 0.891667 0.791667 0 0.891667 0.833333 0 0.891667 0.875000 0 0.891667 0.916667 0 0.891667 0.958333 0 0.891667 1.000000 0 0.900000 0 0 0.900000 0.041667 0 0.900000 0.083333 0 0.900000 0.125000 0 0.900000 0.166667 0 0.900000 0.208333 0 0.900000 0.250000 0 0.900000 0.291667 0 0.900000 0.333333 0 0.900000 0.375000 0 0.900000 0.416667 0 0.900000 0.458333 0 0.900000 0.500000 0 0.900000 0.541667 0 0.900000 0.583333 0 0.900000 0.625000 0 0.900000 0.666667 0 0.900000 0.708333 0 0.900000 0.750000 0 0.900000 0.791667 0 0.900000 0.833333 0 0.900000 0.875000 0 0.900000 0.916667 0 0.900000 0.958333 0 0.900000 1.000000 0 0.908334 0 0 0.908334 0.041667 0 0.908334 0.083333 0 0.908334 0.125000 0 0.908334 0.166667 0 0.908334 0.208333 0 0.908334 0.250000 0 0.908334 0.291667 0 0.908334 0.333333 0 0.908334 0.375000 0 0.908334 0.416667 0 0.908334 0.458333 0 0.908334 0.500000 0 0.908334 0.541667 0 0.908334 0.583333 0 0.908334 0.625000 0 0.908334 0.666667 0 0.908334 0.708333 0 0.908334 0.750000 0 0.908334 0.791667 0 0.908334 0.833333 0 0.908334 0.875000 0 0.908334 0.916667 0 0.908334 0.958333 0 0.908334 1.000000 0 0.916667 0 0 0.916667 0.041667 0 0.916667 0.083333 0 0.916667 0.125000 0 0.916667 0.166667 0 0.916667 0.208333 0 0.916667 0.250000 0 0.916667 0.291667 0 0.916667 0.333333 0 0.916667 0.375000 0 0.916667 0.416667 0 0.916667 0.458333 0 0.916667 0.500000 0 0.916667 0.541667 0 0.916667 0.583333 0 0.916667 0.625000 0 0.916667 0.666667 0 0.916667 0.708333 0 0.916667 0.750000 0 0.916667 0.791667 0 0.916667 0.833333 0 0.916667 0.875000 0 0.916667 0.916667 0 0.916667 0.958333 0 0.916667 1.000000 0 0.925000 0 0 0.925000 0.041667 0 0.925000 0.083333 0 0.925000 0.125000 0 0.925000 0.166667 0 0.925000 0.208333 0 0.925000 0.250000 0 0.925000 0.291667 0 0.925000 0.333333 0 0.925000 0.375000 0 0.925000 0.416667 0 0.925000 0.458333 0 0.925000 0.500000 0 0.925000 0.541667 0 0.925000 0.583333 0 0.925000 0.625000 0 0.925000 0.666667 0 0.925000 0.708333 0 0.925000 0.750000 0 0.925000 0.791667 0 0.925000 0.833333 0 0.925000 0.875000 0 0.925000 0.916667 0 0.925000 0.958333 0 0.925000 1.000000 0 0.933334 0 0 0.933334 0.041667 0 0.933334 0.083333 0 0.933334 0.125000 0 0.933334 0.166667 0 0.933334 0.208333 0 0.933334 0.250000 0 0.933334 0.291667 0 0.933334 0.333333 0 0.933334 0.375000 0 0.933334 0.416667 0 0.933334 0.458333 0 0.933334 0.500000 0 0.933334 0.541667 0 0.933334 0.583333 0 0.933334 0.625000 0 0.933334 0.666667 0 0.933334 0.708333 0 0.933334 0.750000 0 0.933334 0.791667 0 0.933334 0.833333 0 0.933334 0.875000 0 0.933334 0.916667 0 0.933334 0.958333 0 0.933334 1.000000 0 0.941667 0 0 0.941667 0.041667 0 0.941667 0.083333 0 0.941667 0.125000 0 0.941667 0.166667 0 0.941667 0.208333 0 0.941667 0.250000 0 0.941667 0.291667 0 0.941667 0.333333 0 0.941667 0.375000 0 0.941667 0.416667 0 0.941667 0.458333 0 0.941667 0.500000 0 0.941667 0.541667 0 0.941667 0.583333 0 0.941667 0.625000 0 0.941667 0.666667 0 0.941667 0.708333 0 0.941667 0.750000 0 0.941667 0.791667 0 0.941667 0.833333 0 0.941667 0.875000 0 0.941667 0.916667 0 0.941667 0.958333 0 0.941667 1.000000 0 0.950001 0 0 0.950001 0.041667 0 0.950001 0.083333 0 0.950001 0.125000 0 0.950001 0.166667 0 0.950001 0.208333 0 0.950001 0.250000 0 0.950001 0.291667 0 0.950001 0.333333 0 0.950001 0.375000 0 0.950001 0.416667 0 0.950001 0.458333 0 0.950001 0.500000 0 0.950001 0.541667 0 0.950001 0.583333 0 0.950001 0.625000 0 0.950001 0.666667 0 0.950001 0.708333 0 0.950001 0.750000 0 0.950001 0.791667 0 0.950001 0.833333 0 0.950001 0.875000 0 0.950001 0.916667 0 0.950001 0.958333 0 0.950001 1.000000 0 0.958334 0 0 0.958334 0.041667 0 0.958334 0.083333 0 0.958334 0.125000 0 0.958334 0.166667 0 0.958334 0.208333 0 0.958334 0.250000 0 0.958334 0.291667 0 0.958334 0.333333 0 0.958334 0.375000 0 0.958334 0.416667 0 0.958334 0.458333 0 0.958334 0.500000 0 0.958334 0.541667 0 0.958334 0.583333 0 0.958334 0.625000 0 0.958334 0.666667 0 0.958334 0.708333 0 0.958334 0.750000 0 0.958334 0.791667 0 0.958334 0.833333 0 0.958334 0.875000 0 0.958334 0.916667 0 0.958334 0.958333 0 0.958334 1.000000 0 0.966667 0 0 0.966667 0.041667 0 0.966667 0.083333 0 0.966667 0.125000 0 0.966667 0.166667 0 0.966667 0.208333 0 0.966667 0.250000 0 0.966667 0.291667 0 0.966667 0.333333 0 0.966667 0.375000 0 0.966667 0.416667 0 0.966667 0.458333 0 0.966667 0.500000 0 0.966667 0.541667 0 0.966667 0.583333 0 0.966667 0.625000 0 0.966667 0.666667 0 0.966667 0.708333 0 0.966667 0.750000 0 0.966667 0.791667 0 0.966667 0.833333 0 0.966667 0.875000 0 0.966667 0.916667 0 0.966667 0.958333 0 0.966667 1.000000 0 0.975001 0 0 0.975001 0.041667 0 0.975001 0.083333 0 0.975001 0.125000 0 0.975001 0.166667 0 0.975001 0.208333 0 0.975001 0.250000 0 0.975001 0.291667 0 0.975001 0.333333 0 0.975001 0.375000 0 0.975001 0.416667 0 0.975001 0.458333 0 0.975001 0.500000 0 0.975001 0.541667 0 0.975001 0.583333 0 0.975001 0.625000 0 0.975001 0.666667 0 0.975001 0.708333 0 0.975001 0.750000 0 0.975001 0.791667 0 0.975001 0.833333 0 0.975001 0.875000 0 0.975001 0.916667 0 0.975001 0.958333 0 0.975001 1.000000 0 0.983334 0 0 0.983334 0.041667 0 0.983334 0.083333 0 0.983334 0.125000 0 0.983334 0.166667 0 0.983334 0.208333 0 0.983334 0.250000 0 0.983334 0.291667 0 0.983334 0.333333 0 0.983334 0.375000 0 0.983334 0.416667 0 0.983334 0.458333 0 0.983334 0.500000 0 0.983334 0.541667 0 0.983334 0.583333 0 0.983334 0.625000 0 0.983334 0.666667 0 0.983334 0.708333 0 0.983334 0.750000 0 0.983334 0.791667 0 0.983334 0.833333 0 0.983334 0.875000 0 0.983334 0.916667 0 0.983334 0.958333 0 0.983334 1.000000 0 0.991667 0 0 0.991667 0.041667 0 0.991667 0.083333 0 0.991667 0.125000 0 0.991667 0.166667 0 0.991667 0.208333 0 0.991667 0.250000 0 0.991667 0.291667 0 0.991667 0.333333 0 0.991667 0.375000 0 0.991667 0.416667 0 0.991667 0.458333 0 0.991667 0.500000 0 0.991667 0.541667 0 0.991667 0.583333 0 0.991667 0.625000 0 0.991667 0.666667 0 0.991667 0.708333 0 0.991667 0.750000 0 0.991667 0.791667 0 0.991667 0.833333 0 0.991667 0.875000 0 0.991667 0.916667 0 0.991667 0.958333 0 0.991667 1.000000 0 1.000001 0 0 1.000001 0.041667 0 1.000001 0.083333 0 1.000001 0.125000 0 1.000001 0.166667 0 1.000001 0.208333 0 1.000001 0.250000 0 1.000001 0.291667 0 1.000001 0.333333 0 1.000001 0.375000 0 1.000001 0.416667 0 1.000001 0.458333 0 1.000001 0.500000 0 1.000001 0.541667 0 1.000001 0.583333 0 1.000001 0.625000 0 1.000001 0.666667 0 1.000001 0.708333 0 1.000001 0.750000 0 1.000001 0.791667 0 1.000001 0.833333 0 1.000001 0.875000 0 1.000001 0.916667 0 1.000001 0.958333 0 1.000001 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="3025" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="5760">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 24 1 25 25 2 26 0 0 0 25 2 26 1 3 1 1 3 1 25 2 26 26 4 27 1 3 1 26 4 27 2 5 2 2 5 2 26 4 27 27 6 28 2 5 2 27 6 28 3 7 3 3 7 3 27 6 28 28 8 29 3 7 3 28 8 29 4 9 4 4 9 4 28 8 29 29 10 30 4 9 4 29 10 30 5 11 5 5 11 5 29 10 30 30 12 31 5 11 5 30 12 31 6 13 6 6 13 6 30 12 31 31 14 32 6 13 6 31 14 32 7 15 7 7 15 7 31 14 32 32 16 33 7 15 7 32 16 33 8 17 8 8 17 8 32 16 33 33 18 34 8 17 8 33 18 34 9 19 9 9 19 9 33 18 34 34 20 35 9 19 9 34 20 35 10 21 10 10 21 10 34 20 35 35 22 36 10 21 10 35 22 36 11 23 11 11 23 11 35 22 36 36 24 37 11 23 11 36 24 37 12 25 12 12 25 12 36 24 37 37 26 38 12 25 12 37 26 38 13 27 13 13 27 13 37 26 38 38 28 39 13 27 13 38 28 39 14 29 14 14 29 14 38 28 39 39 30 40 14 29 14 39 30 40 15 31 15 15 31 15 39 30 40 40 32 41 15 31 15 40 32 41 16 33 16 16 33 16 40 32 41 41 34 42 16 33 16 41 34 42 17 35 17 17 35 17 41 34 42 42 36 43 17 35 17 42 36 43 18 37 18 18 37 18 42 36 43 43 38 44 18 37 18 43 38 44 19 39 19 19 39 19 43 38 44 44 40 45 19 39 19 44 40 45 20 41 20 20 41 20 44 40 45 45 42 46 20 41 20 45 42 46 21 43 21 21 43 21 45 42 46 46 44 47 21 43 21 46 44 47 22 45 22 22 45 22 46 44 47 47 46 48 22 45 22 47 46 48 23 47 23 23 47 23 47 46 48 24 1 49 23 47 23 24 1 49 0 0 24 24 1 25 48 48 50 49 49 51 24 1 25 49 49 51 25 2 26 25 2 26 49 49 51 50 50 52 25 2 26 50 50 52 26 4 27 26 4 27 50 50 52 51 51 53 26 4 27 51 51 53 27 6 28 27 6 28 51 51 53 52 52 54 27 6 28 52 52 54 28 8 29 28 8 29 52 52 54 53 53 55 28 8 29 53 53 55 29 10 30 29 10 30 53 53 55 54 54 56 29 10 30 54 54 56 30 12 31 30 12 31 54 54 56 55 55 57 30 12 31 55 55 57 31 14 32 31 14 32 55 55 57 56 56 58 31 14 32 56 56 58 32 16 33 32 16 33 56 56 58 57 57 59 32 16 33 57 57 59 33 18 34 33 18 34 57 57 59 58 58 60 33 18 34 58 58 60 34 20 35 34 20 35 58 58 60 59 59 61 34 20 35 59 59 61 35 22 36 35 22 36 59 59 61 60 60 62 35 22 36 60 60 62 36 24 37 36 24 37 60 60 62 61 61 63 36 24 37 61 61 63 37 26 38 37 26 38 61 61 63 62 62 64 37 26 38 62 62 64 38 28 39 38 28 39 62 62 64 63 63 65 38 28 39 63 63 65 39 30 40 39 30 40 63 63 65 64 64 66 39 30 40 64 64 66 40 32 41 40 32 41 64 64 66 65 65 67 40 32 41 65 65 67 41 34 42 41 34 42 65 65 67 66 66 68 41 34 42 66 66 68 42 36 43 42 36 43 66 66 68 67 67 69 42 36 43 67 67 69 43 38 44 43 38 44 67 67 69 68 68 70 43 38 44 68 68 70 44 40 45 44 40 45 68 68 70 69 69 71 44 40 45 69 69 71 45 42 46 45 42 46 69 69 71 70 70 72 45 42 46 70 70 72 46 44 47 46 44 47 70 70 72 71 71 73 46 44 47 71 71 73 47 46 48 47 46 48 71 71 73 48 48 74 47 46 48 48 48 74 24 1 49 48 48 50 72 72 75 73 73 76 48 48 50 73 73 76 49 49 51 49 49 51 73 73 76 74 74 77 49 49 51 74 74 77 50 50 52 50 50 52 74 74 77 75 75 78 50 50 52 75 75 78 51 51 53 51 51 53 75 75 78 76 76 79 51 51 53 76 76 79 52 52 54 52 52 54 76 76 79 77 77 80 52 52 54 77 77 80 53 53 55 53 53 55 77 77 80 78 78 81 53 53 55 78 78 81 54 54 56 54 54 56 78 78 81 79 79 82 54 54 56 79 79 82 55 55 57 55 55 57 79 79 82 80 80 83 55 55 57 80 80 83 56 56 58 56 56 58 80 80 83 81 81 84 56 56 58 81 81 84 57 57 59 57 57 59 81 81 84 82 82 85 57 57 59 82 82 85 58 58 60 58 58 60 82 82 85 83 83 86 58 58 60 83 83 86 59 59 61 59 59 61 83 83 86 84 84 87 59 59 61 84 84 87 60 60 62 60 60 62 84 84 87 85 85 88 60 60 62 85 85 88 61 61 63 61 61 63 85 85 88 86 86 89 61 61 63 86 86 89 62 62 64 62 62 64 86 86 89 87 87 90 62 62 64 87 87 90 63 63 65 63 63 65 87 87 90 88 88 91 63 63 65 88 88 91 64 64 66 64 64 66 88 88 91 89 89 92 64 64 66 89 89 92 65 65 67 65 65 67 89 89 92 90 90 93 65 65 67 90 90 93 66 66 68 66 66 68 90 90 93 91 91 94 66 66 68 91 91 94 67 67 69 67 67 69 91 91 94 92 92 95 67 67 69 92 92 95 68 68 70 68 68 70 92 92 95 93 93 96 68 68 70 93 93 96 69 69 71 69 69 71 93 93 96 94 94 97 69 69 71 94 94 97 70 70 72 70 70 72 94 94 97 95 95 98 70 70 72 95 95 98 71 71 73 71 71 73 95 95 98 72 72 99 71 71 73 72 72 99 48 48 74 72 72 75 96 96 100 97 97 101 72 72 75 97 97 101 73 73 76 73 73 76 97 97 101 98 98 102 73 73 76 98 98 102 74 74 77 74 74 77 98 98 102 99 99 103 74 74 77 99 99 103 75 75 78 75 75 78 99 99 103 100 100 104 75 75 78 100 100 104 76 76 79 76 76 79 100 100 104 101 101 105 76 76 79 101 101 105 77 77 80 77 77 80 101 101 105 102 102 106 77 77 80 102 102 106 78 78 81 78 78 81 102 102 106 103 103 107 78 78 81 103 103 107 79 79 82 79 79 82 103 103 107 104 104 108 79 79 82 104 104 108 80 80 83 80 80 83 104 104 108 105 105 109 80 80 83 105 105 109 81 81 84 81 81 84 105 105 109 106 106 110 81 81 84 106 106 110 82 82 85 82 82 85 106 106 110 107 107 111 82 82 85 107 107 111 83 83 86 83 83 86 107 107 111 108 108 112 83 83 86 108 108 112 84 84 87 84 84 87 108 108 112 109 109 113 84 84 87 109 109 113 85 85 88 85 85 88 109 109 113 110 110 114 85 85 88 110 110 114 86 86 89 86 86 89 110 110 114 111 111 115 86 86 89 111 111 115 87 87 90 87 87 90 111 111 115 112 112 116 87 87 90 112 112 116 88 88 91 88 88 91 112 112 116 113 113 117 88 88 91 113 113 117 89 89 92 89 89 92 113 113 117 114 114 118 89 89 92 114 114 118 90 90 93 90 90 93 114 114 118 115 115 119 90 90 93 115 115 119 91 91 94 91 91 94 115 115 119 116 116 120 91 91 94 116 116 120 92 92 95 92 92 95 116 116 120 117 117 121 92 92 95 117 117 121 93 93 96 93 93 96 117 117 121 118 118 122 93 93 96 118 118 122 94 94 97 94 94 97 118 118 122 119 119 123 94 94 97 119 119 123 95 95 98 95 95 98 119 119 123 96 96 124 95 95 98 96 96 124 72 72 99 96 96 100 120 120 125 121 121 126 96 96 100 121 121 126 97 97 101 97 97 101 121 121 126 122 122 127 97 97 101 122 122 127 98 98 102 98 98 102 122 122 127 123 123 128 98 98 102 123 123 128 99 99 103 99 99 103 123 123 128 124 124 129 99 99 103 124 124 129 100 100 104 100 100 104 124 124 129 125 125 130 100 100 104 125 125 130 101 101 105 101 101 105 125 125 130 126 126 131 101 101 105 126 126 131 102 102 106 102 102 106 126 126 131 127 127 132 102 102 106 127 127 132 103 103 107 103 103 107 127 127 132 128 128 133 103 103 107 128 128 133 104 104 108 104 104 108 128 128 133 129 129 134 104 104 108 129 129 134 105 105 109 105 105 109 129 129 134 130 130 135 105 105 109 130 130 135 106 106 110 106 106 110 130 130 135 131 131 136 106 106 110 131 131 136 107 107 111 107 107 111 131 131 136 132 132 137 107 107 111 132 132 137 108 108 112 108 108 112 132 132 137 133 133 138 108 108 112 133 133 138 109 109 113 109 109 113 133 133 138 134 134 139 109 109 113 134 134 139 110 110 114 110 110 114 134 134 139 135 135 140 110 110 114 135 135 140 111 111 115 111 111 115 135 135 140 136 136 141 111 111 115 136 136 141 112 112 116 112 112 116 136 136 141 137 137 142 112 112 116 137 137 142 113 113 117 113 113 117 137 137 142 138 138 143 113 113 117 138 138 143 114 114 118 114 114 118 138 138 143 139 139 144 114 114 118 139 139 144 115 115 119 115 115 119 139 139 144 140 140 145 115 115 119 140 140 145 116 116 120 116 116 120 140 140 145 141 141 146 116 116 120 141 141 146 117 117 121 117 117 121 141 141 146 142 142 147 117 117 121 142 142 147 118 118 122 118 118 122 142 142 147 143 143 148 118 118 122 143 143 148 119 119 123 119 119 123 143 143 148 120 120 149 119 119 123 120 120 149 96 96 124 120 120 125 144 144 150 145 145 151 120 120 125 145 145 151 121 121 126 121 121 126 145 145 151 146 146 152 121 121 126 146 146 152 122 122 127 122 122 127 146 146 152 147 147 153 122 122 127 147 147 153 123 123 128 123 123 128 147 147 153 148 148 154 123 123 128 148 148 154 124 124 129 124 124 129 148 148 154 149 149 155 124 124 129 149 149 155 125 125 130 125 125 130 149 149 155 150 150 156 125 125 130 150 150 156 126 126 131 126 126 131 150 150 156 151 151 157 126 126 131 151 151 157 127 127 132 127 127 132 151 151 157 152 152 158 127 127 132 152 152 158 128 128 133 128 128 133 152 152 158 153 153 159 128 128 133 153 153 159 129 129 134 129 129 134 153 153 159 154 154 160 129 129 134 154 154 160 130 130 135 130 130 135 154 154 160 155 155 161 130 130 135 155 155 161 131 131 136 131 131 136 155 155 161 156 156 162 131 131 136 156 156 162 132 132 137 132 132 137 156 156 162 157 157 163 132 132 137 157 157 163 133 133 138 133 133 138 157 157 163 158 158 164 133 133 138 158 158 164 134 134 139 134 134 139 158 158 164 159 159 165 134 134 139 159 159 165 135 135 140 135 135 140 159 159 165 160 160 166 135 135 140 160 160 166 136 136 141 136 136 141 160 160 166 161 161 167 136 136 141 161 161 167 137 137 142 137 137 142 161 161 167 162 162 168 137 137 142 162 162 168 138 138 143 138 138 143 162 162 168 163 163 169 138 138 143 163 163 169 139 139 144 139 139 144 163 163 169 164 164 170 139 139 144 164 164 170 140 140 145 140 140 145 164 164 170 165 165 171 140 140 145 165 165 171 141 141 146 141 141 146 165 165 171 166 166 172 141 141 146 166 166 172 142 142 147 142 142 147 166 166 172 167 167 173 142 142 147 167 167 173 143 143 148 143 143 148 167 167 173 144 144 174 143 143 148 144 144 174 120 120 149 144 144 150 168 168 175 169 169 176 144 144 150 169 169 176 145 145 151 145 145 151 169 169 176 170 170 177 145 145 151 170 170 177 146 146 152 146 146 152 170 170 177 171 171 178 146 146 152 171 171 178 147 147 153 147 147 153 171 171 178 172 172 179 147 147 153 172 172 179 148 148 154 148 148 154 172 172 179 173 173 180 148 148 154 173 173 180 149 149 155 149 149 155 173 173 180 174 174 181 149 149 155 174 174 181 150 150 156 150 150 156 174 174 181 175 175 182 150 150 156 175 175 182 151 151 157 151 151 157 175 175 182 176 176 183 151 151 157 176 176 183 152 152 158 152 152 158 176 176 183 177 177 184 152 152 158 177 177 184 153 153 159 153 153 159 177 177 184 178 178 185 153 153 159 178 178 185 154 154 160 154 154 160 178 178 185 179 179 186 154 154 160 179 179 186 155 155 161 155 155 161 179 179 186 180 180 187 155 155 161 180 180 187 156 156 162 156 156 162 180 180 187 181 181 188 156 156 162 181 181 188 157 157 163 157 157 163 181 181 188 182 182 189 157 157 163 182 182 189 158 158 164 158 158 164 182 182 189 183 183 190 158 158 164 183 183 190 159 159 165 159 159 165 183 183 190 184 184 191 159 159 165 184 184 191 160 160 166 160 160 166 184 184 191 185 185 192 160 160 166 185 185 192 161 161 167 161 161 167 185 185 192 186 186 193 161 161 167 186 186 193 162 162 168 162 162 168 186 186 193 187 187 194 162 162 168 187 187 194 163 163 169 163 163 169 187 187 194 188 188 195 163 163 169 188 188 195 164 164 170 164 164 170 188 188 195 189 189 196 164 164 170 189 189 196 165 165 171 165 165 171 189 189 196 190 190 197 165 165 171 190 190 197 166 166 172 166 166 172 190 190 197 191 191 198 166 166 172 191 191 198 167 167 173 167 167 173 191 191 198 168 168 199 167 167 173 168 168 199 144 144 174 168 168 175 192 192 200 193 193 201 168 168 175 193 193 201 169 169 176 169 169 176 193 193 201 194 194 202 169 169 176 194 194 202 170 170 177 170 170 177 194 194 202 195 195 203 170 170 177 195 195 203 171 171 178 171 171 178 195 195 203 196 196 204 171 171 178 196 196 204 172 172 179 172 172 179 196 196 204 197 197 205 172 172 179 197 197 205 173 173 180 173 173 180 197 197 205 198 198 206 173 173 180 198 198 206 174 174 181 174 174 181 198 198 206 199 199 207 174 174 181 199 199 207 175 175 182 175 175 182 199 199 207 200 200 208 175 175 182 200 200 208 176 176 183 176 176 183 200 200 208 201 201 209 176 176 183 201 201 209 177 177 184 177 177 184 201 201 209 202 202 210 177 177 184 202 202 210 178 178 185 178 178 185 202 202 210 203 203 211 178 178 185 203 203 211 179 179 186 179 179 186 203 203 211 204 204 212 179 179 186 204 204 212 180 180 187 180 180 187 204 204 212 205 205 213 180 180 187 205 205 213 181 181 188 181 181 188 205 205 213 206 206 214 181 181 188 206 206 214 182 182 189 182 182 189 206 206 214 207 207 215 182 182 189 207 207 215 183 183 190 183 183 190 207 207 215 208 208 216 183 183 190 208 208 216 184 184 191 184 184 191 208 208 216 209 209 217 184 184 191 209 209 217 185 185 192 185 185 192 209 209 217 210 210 218 185 185 192 210 210 218 186 186 193 186 186 193 210 210 218 211 211 219 186 186 193 211 211 219 187 187 194 187 187 194 211 211 219 212 212 220 187 187 194 212 212 220 188 188 195 188 188 195 212 212 220 213 213 221 188 188 195 213 213 221 189 189 196 189 189 196 213 213 221 214 214 222 189 189 196 214 214 222 190 190 197 190 190 197 214 214 222 215 215 223 190 190 197 215 215 223 191 191 198 191 191 198 215 215 223 192 192 224 191 191 198 192 192 224 168 168 199 192 192 200 216 216 225 217 217 226 192 192 200 217 217 226 193 193 201 193 193 201 217 217 226 218 218 227 193 193 201 218 218 227 194 194 202 194 194 202 218 218 227 219 219 228 194 194 202 219 219 228 195 195 203 195 195 203 219 219 228 220 220 229 195 195 203 220 220 229 196 196 204 196 196 204 220 220 229 221 221 230 196 196 204 221 221 230 197 197 205 197 197 205 221 221 230 222 222 231 197 197 205 222 222 231 198 198 206 198 198 206 222 222 231 223 223 232 198 198 206 223 223 232 199 199 207 199 199 207 223 223 232 224 224 233 199 199 207 224 224 233 200 200 208 200 200 208 224 224 233 225 225 234 200 200 208 225 225 234 201 201 209 201 201 209 225 225 234 226 226 235 201 201 209 226 226 235 202 202 210 202 202 210 226 226 235 227 227 236 202 202 210 227 227 236 203 203 211 203 203 211 227 227 236 228 228 237 203 203 211 228 228 237 204 204 212 204 204 212 228 228 237 229 229 238 204 204 212 229 229 238 205 205 213 205 205 213 229 229 238 230 230 239 205 205 213 230 230 239 206 206 214 206 206 214 230 230 239 231 231 240 206 206 214 231 231 240 207 207 215 207 207 215 231 231 240 232 232 241 207 207 215 232 232 241 208 208 216 208 208 216 232 232 241 233 233 242 208 208 216 233 233 242 209 209 217 209 209 217 233 233 242 234 234 243 209 209 217 234 234 243 210 210 218 210 210 218 234 234 243 235 235 244 210 210 218 235 235 244 211 211 219 211 211 219 235 235 244 236 236 245 211 211 219 236 236 245 212 212 220 212 212 220 236 236 245 237 237 246 212 212 220 237 237 246 213 213 221 213 213 221 237 237 246 238 238 247 213 213 221 238 238 247 214 214 222 214 214 222 238 238 247 239 239 248 214 214 222 239 239 248 215 215 223 215 215 223 239 239 248 216 216 249 215 215 223 216 216 249 192 192 224 216 216 225 240 240 250 241 241 251 216 216 225 241 241 251 217 217 226 217 217 226 241 241 251 242 242 252 217 217 226 242 242 252 218 218 227 218 218 227 242 242 252 243 243 253 218 218 227 243 243 253 219 219 228 219 219 228 243 243 253 244 244 254 219 219 228 244 244 254 220 220 229 220 220 229 244 244 254 245 245 255 220 220 229 245 245 255 221 221 230 221 221 230 245 245 255 246 246 256 221 221 230 246 246 256 222 222 231 222 222 231 246 246 256 247 247 257 222 222 231 247 247 257 223 223 232 223 223 232 247 247 257 248 248 258 223 223 232 248 248 258 224 224 233 224 224 233 248 248 258 249 249 259 224 224 233 249 249 259 225 225 234 225 225 234 249 249 259 250 250 260 225 225 234 250 250 260 226 226 235 226 226 235 250 250 260 251 251 261 226 226 235 251 251 261 227 227 236 227 227 236 251 251 261 252 252 262 227 227 236 252 252 262 228 228 237 228 228 237 252 252 262 253 253 263 228 228 237 253 253 263 229 229 238 229 229 238 253 253 263 254 254 264 229 229 238 254 254 264 230 230 239 230 230 239 254 254 264 255 255 265 230 230 239 255 255 265 231 231 240 231 231 240 255 255 265 256 256 266 231 231 240 256 256 266 232 232 241 232 232 241 256 256 266 257 257 267 232 232 241 257 257 267 233 233 242 233 233 242 257 257 267 258 258 268 233 233 242 258 258 268 234 234 243 234 234 243 258 258 268 259 259 269 234 234 243 259 259 269 235 235 244 235 235 244 259 259 269 260 260 270 235 235 244 260 260 270 236 236 245 236 236 245 260 260 270 261 261 271 236 236 245 261 261 271 237 237 246 237 237 246 261 261 271 262 262 272 237 237 246 262 262 272 238 238 247 238 238 247 262 262 272 263 263 273 238 238 247 263 263 273 239 239 248 239 239 248 263 263 273 240 240 274 239 239 248 240 240 274 216 216 249 240 240 250 264 264 275 265 265 276 240 240 250 265 265 276 241 241 251 241 241 251 265 265 276 266 266 277 241 241 251 266 266 277 242 242 252 242 242 252 266 266 277 267 267 278 242 242 252 267 267 278 243 243 253 243 243 253 267 267 278 268 268 279 243 243 253 268 268 279 244 244 254 244 244 254 268 268 279 269 269 280 244 244 254 269 269 280 245 245 255 245 245 255 269 269 280 270 270 281 245 245 255 270 270 281 246 246 256 246 246 256 270 270 281 271 271 282 246 246 256 271 271 282 247 247 257 247 247 257 271 271 282 272 272 283 247 247 257 272 272 283 248 248 258 248 248 258 272 272 283 273 273 284 248 248 258 273 273 284 249 249 259 249 249 259 273 273 284 274 274 285 249 249 259 274 274 285 250 250 260 250 250 260 274 274 285 275 275 286 250 250 260 275 275 286 251 251 261 251 251 261 275 275 286 276 276 287 251 251 261 276 276 287 252 252 262 252 252 262 276 276 287 277 277 288 252 252 262 277 277 288 253 253 263 253 253 263 277 277 288 278 278 289 253 253 263 278 278 289 254 254 264 254 254 264 278 278 289 279 279 290 254 254 264 279 279 290 255 255 265 255 255 265 279 279 290 280 280 291 255 255 265 280 280 291 256 256 266 256 256 266 280 280 291 281 281 292 256 256 266 281 281 292 257 257 267 257 257 267 281 281 292 282 282 293 257 257 267 282 282 293 258 258 268 258 258 268 282 282 293 283 283 294 258 258 268 283 283 294 259 259 269 259 259 269 283 283 294 284 284 295 259 259 269 284 284 295 260 260 270 260 260 270 284 284 295 285 285 296 260 260 270 285 285 296 261 261 271 261 261 271 285 285 296 286 286 297 261 261 271 286 286 297 262 262 272 262 262 272 286 286 297 287 287 298 262 262 272 287 287 298 263 263 273 263 263 273 287 287 298 264 264 299 263 263 273 264 264 299 240 240 274 264 264 275 288 288 300 289 289 301 264 264 275 289 289 301 265 265 276 265 265 276 289 289 301 290 290 302 265 265 276 290 290 302 266 266 277 266 266 277 290 290 302 291 291 303 266 266 277 291 291 303 267 267 278 267 267 278 291 291 303 292 292 304 267 267 278 292 292 304 268 268 279 268 268 279 292 292 304 293 293 305 268 268 279 293 293 305 269 269 280 269 269 280 293 293 305 294 294 306 269 269 280 294 294 306 270 270 281 270 270 281 294 294 306 295 295 307 270 270 281 295 295 307 271 271 282 271 271 282 295 295 307 296 296 308 271 271 282 296 296 308 272 272 283 272 272 283 296 296 308 297 297 309 272 272 283 297 297 309 273 273 284 273 273 284 297 297 309 298 298 310 273 273 284 298 298 310 274 274 285 274 274 285 298 298 310 299 299 311 274 274 285 299 299 311 275 275 286 275 275 286 299 299 311 300 300 312 275 275 286 300 300 312 276 276 287 276 276 287 300 300 312 301 301 313 276 276 287 301 301 313 277 277 288 277 277 288 301 301 313 302 302 314 277 277 288 302 302 314 278 278 289 278 278 289 302 302 314 303 303 315 278 278 289 303 303 315 279 279 290 279 279 290 303 303 315 304 304 316 279 279 290 304 304 316 280 280 291 280 280 291 304 304 316 305 305 317 280 280 291 305 305 317 281 281 292 281 281 292 305 305 317 306 306 318 281 281 292 306 306 318 282 282 293 282 282 293 306 306 318 307 307 319 282 282 293 307 307 319 283 283 294 283 283 294 307 307 319 308 308 320 283 283 294 308 308 320 284 284 295 284 284 295 308 308 320 309 309 321 284 284 295 309 309 321 285 285 296 285 285 296 309 309 321 310 310 322 285 285 296 310 310 322 286 286 297 286 286 297 310 310 322 311 311 323 286 286 297 311 311 323 287 287 298 287 287 298 311 311 323 288 288 324 287 287 298 288 288 324 264 264 299 288 288 300 312 312 325 313 313 326 288 288 300 313 313 326 289 289 301 289 289 301 313 313 326 314 314 327 289 289 301 314 314 327 290 290 302 290 290 302 314 314 327 315 315 328 290 290 302 315 315 328 291 291 303 291 291 303 315 315 328 316 316 329 291 291 303 316 316 329 292 292 304 292 292 304 316 316 329 317 317 330 292 292 304 317 317 330 293 293 305 293 293 305 317 317 330 318 318 331 293 293 305 318 318 331 294 294 306 294 294 306 318 318 331 319 319 332 294 294 306 319 319 332 295 295 307 295 295 307 319 319 332 320 320 333 295 295 307 320 320 333 296 296 308 296 296 308 320 320 333 321 321 334 296 296 308 321 321 334 297 297 309 297 297 309 321 321 334 322 322 335 297 297 309 322 322 335 298 298 310 298 298 310 322 322 335 323 323 336 298 298 310 323 323 336 299 299 311 299 299 311 323 323 336 324 324 337 299 299 311 324 324 337 300 300 312 300 300 312 324 324 337 325 325 338 300 300 312 325 325 338 301 301 313 301 301 313 325 325 338 326 326 339 301 301 313 326 326 339 302 302 314 302 302 314 326 326 339 327 327 340 302 302 314 327 327 340 303 303 315 303 303 315 327 327 340 328 328 341 303 303 315 328 328 341 304 304 316 304 304 316 328 328 341 329 329 342 304 304 316 329 329 342 305 305 317 305 305 317 329 329 342 330 330 343 305 305 317 330 330 343 306 306 318 306 306 318 330 330 343 331 331 344 306 306 318 331 331 344 307 307 319 307 307 319 331 331 344 332 332 345 307 307 319 332 332 345 308 308 320 308 308 320 332 332 345 333 333 346 308 308 320 333 333 346 309 309 321 309 309 321 333 333 346 334 334 347 309 309 321 334 334 347 310 310 322 310 310 322 334 334 347 335 335 348 310 310 322 335 335 348 311 311 323 311 311 323 335 335 348 312 312 349 311 311 323 312 312 349 288 288 324 312 312 325 336 336 350 337 337 351 312 312 325 337 337 351 313 313 326 313 313 326 337 337 351 338 338 352 313 313 326 338 338 352 314 314 327 314 314 327 338 338 352 339 339 353 314 314 327 339 339 353 315 315 328 315 315 328 339 339 353 340 340 354 315 315 328 340 340 354 316 316 329 316 316 329 340 340 354 341 341 355 316 316 329 341 341 355 317 317 330 317 317 330 341 341 355 342 342 356 317 317 330 342 342 356 318 318 331 318 318 331 342 342 356 343 343 357 318 318 331 343 343 357 319 319 332 319 319 332 343 343 357 344 344 358 319 319 332 344 344 358 320 320 333 320 320 333 344 344 358 345 345 359 320 320 333 345 345 359 321 321 334 321 321 334 345 345 359 346 346 360 321 321 334 346 346 360 322 322 335 322 322 335 346 346 360 347 347 361 322 322 335 347 347 361 323 323 336 323 323 336 347 347 361 348 348 362 323 323 336 348 348 362 324 324 337 324 324 337 348 348 362 349 349 363 324 324 337 349 349 363 325 325 338 325 325 338 349 349 363 350 350 364 325 325 338 350 350 364 326 326 339 326 326 339 350 350 364 351 351 365 326 326 339 351 351 365 327 327 340 327 327 340 351 351 365 352 352 366 327 327 340 352 352 366 328 328 341 328 328 341 352 352 366 353 353 367 328 328 341 353 353 367 329 329 342 329 329 342 353 353 367 354 354 368 329 329 342 354 354 368 330 330 343 330 330 343 354 354 368 355 355 369 330 330 343 355 355 369 331 331 344 331 331 344 355 355 369 356 356 370 331 331 344 356 356 370 332 332 345 332 332 345 356 356 370 357 357 371 332 332 345 357 357 371 333 333 346 333 333 346 357 357 371 358 358 372 333 333 346 358 358 372 334 334 347 334 334 347 358 358 372 359 359 373 334 334 347 359 359 373 335 335 348 335 335 348 359 359 373 336 336 374 335 335 348 336 336 374 312 312 349 336 336 350 360 360 375 361 361 376 336 336 350 361 361 376 337 337 351 337 337 351 361 361 376 362 362 377 337 337 351 362 362 377 338 338 352 338 338 352 362 362 377 363 363 378 338 338 352 363 363 378 339 339 353 339 339 353 363 363 378 364 364 379 339 339 353 364 364 379 340 340 354 340 340 354 364 364 379 365 365 380 340 340 354 365 365 380 341 341 355 341 341 355 365 365 380 366 366 381 341 341 355 366 366 381 342 342 356 342 342 356 366 366 381 367 367 382 342 342 356 367 367 382 343 343 357 343 343 357 367 367 382 368 368 383 343 343 357 368 368 383 344 344 358 344 344 358 368 368 383 369 369 384 344 344 358 369 369 384 345 345 359 345 345 359 369 369 384 370 370 385 345 345 359 370 370 385 346 346 360 346 346 360 370 370 385 371 371 386 346 346 360 371 371 386 347 347 361 347 347 361 371 371 386 372 372 387 347 347 361 372 372 387 348 348 362 348 348 362 372 372 387 373 373 388 348 348 362 373 373 388 349 349 363 349 349 363 373 373 388 374 374 389 349 349 363 374 374 389 350 350 364 350 350 364 374 374 389 375 375 390 350 350 364 375 375 390 351 351 365 351 351 365 375 375 390 376 376 391 351 351 365 376 376 391 352 352 366 352 352 366 376 376 391 377 377 392 352 352 366 377 377 392 353 353 367 353 353 367 377 377 392 378 378 393 353 353 367 378 378 393 354 354 368 354 354 368 378 378 393 379 379 394 354 354 368 379 379 394 355 355 369 355 355 369 379 379 394 380 380 395 355 355 369 380 380 395 356 356 370 356 356 370 380 380 395 381 381 396 356 356 370 381 381 396 357 357 371 357 357 371 381 381 396 382 382 397 357 357 371 382 382 397 358 358 372 358 358 372 382 382 397 383 383 398 358 358 372 383 383 398 359 359 373 359 359 373 383 383 398 360 360 399 359 359 373 360 360 399 336 336 374 360 360 375 384 384 400 385 385 401 360 360 375 385 385 401 361 361 376 361 361 376 385 385 401 386 386 402 361 361 376 386 386 402 362 362 377 362 362 377 386 386 402 387 387 403 362 362 377 387 387 403 363 363 378 363 363 378 387 387 403 388 388 404 363 363 378 388 388 404 364 364 379 364 364 379 388 388 404 389 389 405 364 364 379 389 389 405 365 365 380 365 365 380 389 389 405 390 390 406 365 365 380 390 390 406 366 366 381 366 366 381 390 390 406 391 391 407 366 366 381 391 391 407 367 367 382 367 367 382 391 391 407 392 392 408 367 367 382 392 392 408 368 368 383 368 368 383 392 392 408 393 393 409 368 368 383 393 393 409 369 369 384 369 369 384 393 393 409 394 394 410 369 369 384 394 394 410 370 370 385 370 370 385 394 394 410 395 395 411 370 370 385 395 395 411 371 371 386 371 371 386 395 395 411 396 396 412 371 371 386 396 396 412 372 372 387 372 372 387 396 396 412 397 397 413 372 372 387 397 397 413 373 373 388 373 373 388 397 397 413 398 398 414 373 373 388 398 398 414 374 374 389 374 374 389 398 398 414 399 399 415 374 374 389 399 399 415 375 375 390 375 375 390 399 399 415 400 400 416 375 375 390 400 400 416 376 376 391 376 376 391 400 400 416 401 401 417 376 376 391 401 401 417 377 377 392 377 377 392 401 401 417 402 402 418 377 377 392 402 402 418 378 378 393 378 378 393 402 402 418 403 403 419 378 378 393 403 403 419 379 379 394 379 379 394 403 403 419 404 404 420 379 379 394 404 404 420 380 380 395 380 380 395 404 404 420 405 405 421 380 380 395 405 405 421 381 381 396 381 381 396 405 405 421 406 406 422 381 381 396 406 406 422 382 382 397 382 382 397 406 406 422 407 407 423 382 382 397 407 407 423 383 383 398 383 383 398 407 407 423 384 384 424 383 383 398 384 384 424 360 360 399 384 384 400 408 408 425 409 409 426 384 384 400 409 409 426 385 385 401 385 385 401 409 409 426 410 410 427 385 385 401 410 410 427 386 386 402 386 386 402 410 410 427 411 411 428 386 386 402 411 411 428 387 387 403 387 387 403 411 411 428 412 412 429 387 387 403 412 412 429 388 388 404 388 388 404 412 412 429 413 413 430 388 388 404 413 413 430 389 389 405 389 389 405 413 413 430 414 414 431 389 389 405 414 414 431 390 390 406 390 390 406 414 414 431 415 415 432 390 390 406 415 415 432 391 391 407 391 391 407 415 415 432 416 416 433 391 391 407 416 416 433 392 392 408 392 392 408 416 416 433 417 417 434 392 392 408 417 417 434 393 393 409 393 393 409 417 417 434 418 418 435 393 393 409 418 418 435 394 394 410 394 394 410 418 418 435 419 419 436 394 394 410 419 419 436 395 395 411 395 395 411 419 419 436 420 420 437 395 395 411 420 420 437 396 396 412 396 396 412 420 420 437 421 421 438 396 396 412 421 421 438 397 397 413 397 397 413 421 421 438 422 422 439 397 397 413 422 422 439 398 398 414 398 398 414 422 422 439 423 423 440 398 398 414 423 423 440 399 399 415 399 399 415 423 423 440 424 424 441 399 399 415 424 424 441 400 400 416 400 400 416 424 424 441 425 425 442 400 400 416 425 425 442 401 401 417 401 401 417 425 425 442 426 426 443 401 401 417 426 426 443 402 402 418 402 402 418 426 426 443 427 427 444 402 402 418 427 427 444 403 403 419 403 403 419 427 427 444 428 428 445 403 403 419 428 428 445 404 404 420 404 404 420 428 428 445 429 429 446 404 404 420 429 429 446 405 405 421 405 405 421 429 429 446 430 430 447 405 405 421 430 430 447 406 406 422 406 406 422 430 430 447 431 431 448 406 406 422 431 431 448 407 407 423 407 407 423 431 431 448 408 408 449 407 407 423 408 408 449 384 384 424 408 408 425 432 432 450 433 433 451 408 408 425 433 433 451 409 409 426 409 409 426 433 433 451 434 434 452 409 409 426 434 434 452 410 410 427 410 410 427 434 434 452 435 435 453 410 410 427 435 435 453 411 411 428 411 411 428 435 435 453 436 436 454 411 411 428 436 436 454 412 412 429 412 412 429 436 436 454 437 437 455 412 412 429 437 437 455 413 413 430 413 413 430 437 437 455 438 438 456 413 413 430 438 438 456 414 414 431 414 414 431 438 438 456 439 439 457 414 414 431 439 439 457 415 415 432 415 415 432 439 439 457 440 440 458 415 415 432 440 440 458 416 416 433 416 416 433 440 440 458 441 441 459 416 416 433 441 441 459 417 417 434 417 417 434 441 441 459 442 442 460 417 417 434 442 442 460 418 418 435 418 418 435 442 442 460 443 443 461 418 418 435 443 443 461 419 419 436 419 419 436 443 443 461 444 444 462 419 419 436 444 444 462 420 420 437 420 420 437 444 444 462 445 445 463 420 420 437 445 445 463 421 421 438 421 421 438 445 445 463 446 446 464 421 421 438 446 446 464 422 422 439 422 422 439 446 446 464 447 447 465 422 422 439 447 447 465 423 423 440 423 423 440 447 447 465 448 448 466 423 423 440 448 448 466 424 424 441 424 424 441 448 448 466 449 449 467 424 424 441 449 449 467 425 425 442 425 425 442 449 449 467 450 450 468 425 425 442 450 450 468 426 426 443 426 426 443 450 450 468 451 451 469 426 426 443 451 451 469 427 427 444 427 427 444 451 451 469 452 452 470 427 427 444 452 452 470 428 428 445 428 428 445 452 452 470 453 453 471 428 428 445 453 453 471 429 429 446 429 429 446 453 453 471 454 454 472 429 429 446 454 454 472 430 430 447 430 430 447 454 454 472 455 455 473 430 430 447 455 455 473 431 431 448 431 431 448 455 455 473 432 432 474 431 431 448 432 432 474 408 408 449 432 432 450 456 456 475 457 457 476 432 432 450 457 457 476 433 433 451 433 433 451 457 457 476 458 458 477 433 433 451 458 458 477 434 434 452 434 434 452 458 458 477 459 459 478 434 434 452 459 459 478 435 435 453 435 435 453 459 459 478 460 460 479 435 435 453 460 460 479 436 436 454 436 436 454 460 460 479 461 461 480 436 436 454 461 461 480 437 437 455 437 437 455 461 461 480 462 462 481 437 437 455 462 462 481 438 438 456 438 438 456 462 462 481 463 463 482 438 438 456 463 463 482 439 439 457 439 439 457 463 463 482 464 464 483 439 439 457 464 464 483 440 440 458 440 440 458 464 464 483 465 465 484 440 440 458 465 465 484 441 441 459 441 441 459 465 465 484 466 466 485 441 441 459 466 466 485 442 442 460 442 442 460 466 466 485 467 467 486 442 442 460 467 467 486 443 443 461 443 443 461 467 467 486 468 468 487 443 443 461 468 468 487 444 444 462 444 444 462 468 468 487 469 469 488 444 444 462 469 469 488 445 445 463 445 445 463 469 469 488 470 470 489 445 445 463 470 470 489 446 446 464 446 446 464 470 470 489 471 471 490 446 446 464 471 471 490 447 447 465 447 447 465 471 471 490 472 472 491 447 447 465 472 472 491 448 448 466 448 448 466 472 472 491 473 473 492 448 448 466 473 473 492 449 449 467 449 449 467 473 473 492 474 474 493 449 449 467 474 474 493 450 450 468 450 450 468 474 474 493 475 475 494 450 450 468 475 475 494 451 451 469 451 451 469 475 475 494 476 476 495 451 451 469 476 476 495 452 452 470 452 452 470 476 476 495 477 477 496 452 452 470 477 477 496 453 453 471 453 453 471 477 477 496 478 478 497 453 453 471 478 478 497 454 454 472 454 454 472 478 478 497 479 479 498 454 454 472 479 479 498 455 455 473 455 455 473 479 479 498 456 456 499 455 455 473 456 456 499 432 432 474 456 456 475 480 480 500 481 481 501 456 456 475 481 481 501 457 457 476 457 457 476 481 481 501 482 482 502 457 457 476 482 482 502 458 458 477 458 458 477 482 482 502 483 483 503 458 458 477 483 483 503 459 459 478 459 459 478 483 483 503 484 484 504 459 459 478 484 484 504 460 460 479 460 460 479 484 484 504 485 485 505 460 460 479 485 485 505 461 461 480 461 461 480 485 485 505 486 486 506 461 461 480 486 486 506 462 462 481 462 462 481 486 486 506 487 487 507 462 462 481 487 487 507 463 463 482 463 463 482 487 487 507 488 488 508 463 463 482 488 488 508 464 464 483 464 464 483 488 488 508 489 489 509 464 464 483 489 489 509 465 465 484 465 465 484 489 489 509 490 490 510 465 465 484 490 490 510 466 466 485 466 466 485 490 490 510 491 491 511 466 466 485 491 491 511 467 467 486 467 467 486 491 491 511 492 492 512 467 467 486 492 492 512 468 468 487 468 468 487 492 492 512 493 493 513 468 468 487 493 493 513 469 469 488 469 469 488 493 493 513 494 494 514 469 469 488 494 494 514 470 470 489 470 470 489 494 494 514 495 495 515 470 470 489 495 495 515 471 471 490 471 471 490 495 495 515 496 496 516 471 471 490 496 496 516 472 472 491 472 472 491 496 496 516 497 497 517 472 472 491 497 497 517 473 473 492 473 473 492 497 497 517 498 498 518 473 473 492 498 498 518 474 474 493 474 474 493 498 498 518 499 499 519 474 474 493 499 499 519 475 475 494 475 475 494 499 499 519 500 500 520 475 475 494 500 500 520 476 476 495 476 476 495 500 500 520 501 501 521 476 476 495 501 501 521 477 477 496 477 477 496 501 501 521 502 502 522 477 477 496 502 502 522 478 478 497 478 478 497 502 502 522 503 503 523 478 478 497 503 503 523 479 479 498 479 479 498 503 503 523 480 480 524 479 479 498 480 480 524 456 456 499 480 480 500 504 504 525 505 505 526 480 480 500 505 505 526 481 481 501 481 481 501 505 505 526 506 506 527 481 481 501 506 506 527 482 482 502 482 482 502 506 506 527 507 507 528 482 482 502 507 507 528 483 483 503 483 483 503 507 507 528 508 508 529 483 483 503 508 508 529 484 484 504 484 484 504 508 508 529 509 509 530 484 484 504 509 509 530 485 485 505 485 485 505 509 509 530 510 510 531 485 485 505 510 510 531 486 486 506 486 486 506 510 510 531 511 511 532 486 486 506 511 511 532 487 487 507 487 487 507 511 511 532 512 512 533 487 487 507 512 512 533 488 488 508 488 488 508 512 512 533 513 513 534 488 488 508 513 513 534 489 489 509 489 489 509 513 513 534 514 514 535 489 489 509 514 514 535 490 490 510 490 490 510 514 514 535 515 515 536 490 490 510 515 515 536 491 491 511 491 491 511 515 515 536 516 516 537 491 491 511 516 516 537 492 492 512 492 492 512 516 516 537 517 517 538 492 492 512 517 517 538 493 493 513 493 493 513 517 517 538 518 518 539 493 493 513 518 518 539 494 494 514 494 494 514 518 518 539 519 519 540 494 494 514 519 519 540 495 495 515 495 495 515 519 519 540 520 520 541 495 495 515 520 520 541 496 496 516 496 496 516 520 520 541 521 521 542 496 496 516 521 521 542 497 497 517 497 497 517 521 521 542 522 522 543 497 497 517 522 522 543 498 498 518 498 498 518 522 522 543 523 523 544 498 498 518 523 523 544 499 499 519 499 499 519 523 523 544 524 524 545 499 499 519 524 524 545 500 500 520 500 500 520 524 524 545 525 525 546 500 500 520 525 525 546 501 501 521 501 501 521 525 525 546 526 526 547 501 501 521 526 526 547 502 502 522 502 502 522 526 526 547 527 527 548 502 502 522 527 527 548 503 503 523 503 503 523 527 527 548 504 504 549 503 503 523 504 504 549 480 480 524 504 504 525 528 528 550 529 529 551 504 504 525 529 529 551 505 505 526 505 505 526 529 529 551 530 530 552 505 505 526 530 530 552 506 506 527 506 506 527 530 530 552 531 531 553 506 506 527 531 531 553 507 507 528 507 507 528 531 531 553 532 532 554 507 507 528 532 532 554 508 508 529 508 508 529 532 532 554 533 533 555 508 508 529 533 533 555 509 509 530 509 509 530 533 533 555 534 534 556 509 509 530 534 534 556 510 510 531 510 510 531 534 534 556 535 535 557 510 510 531 535 535 557 511 511 532 511 511 532 535 535 557 536 536 558 511 511 532 536 536 558 512 512 533 512 512 533 536 536 558 537 537 559 512 512 533 537 537 559 513 513 534 513 513 534 537 537 559 538 538 560 513 513 534 538 538 560 514 514 535 514 514 535 538 538 560 539 539 561 514 514 535 539 539 561 515 515 536 515 515 536 539 539 561 540 540 562 515 515 536 540 540 562 516 516 537 516 516 537 540 540 562 541 541 563 516 516 537 541 541 563 517 517 538 517 517 538 541 541 563 542 542 564 517 517 538 542 542 564 518 518 539 518 518 539 542 542 564 543 543 565 518 518 539 543 543 565 519 519 540 519 519 540 543 543 565 544 544 566 519 519 540 544 544 566 520 520 541 520 520 541 544 544 566 545 545 567 520 520 541 545 545 567 521 521 542 521 521 542 545 545 567 546 546 568 521 521 542 546 546 568 522 522 543 522 522 543 546 546 568 547 547 569 522 522 543 547 547 569 523 523 544 523 523 544 547 547 569 548 548 570 523 523 544 548 548 570 524 524 545 524 524 545 548 548 570 549 549 571 524 524 545 549 549 571 525 525 546 525 525 546 549 549 571 550 550 572 525 525 546 550 550 572 526 526 547 526 526 547 550 550 572 551 551 573 526 526 547 551 551 573 527 527 548 527 527 548 551 551 573 528 528 574 527 527 548 528 528 574 504 504 549 528 528 550 552 552 575 553 553 576 528 528 550 553 553 576 529 529 551 529 529 551 553 553 576 554 554 577 529 529 551 554 554 577 530 530 552 530 530 552 554 554 577 555 555 578 530 530 552 555 555 578 531 531 553 531 531 553 555 555 578 556 556 579 531 531 553 556 556 579 532 532 554 532 532 554 556 556 579 557 557 580 532 532 554 557 557 580 533 533 555 533 533 555 557 557 580 558 558 581 533 533 555 558 558 581 534 534 556 534 534 556 558 558 581 559 559 582 534 534 556 559 559 582 535 535 557 535 535 557 559 559 582 560 560 583 535 535 557 560 560 583 536 536 558 536 536 558 560 560 583 561 561 584 536 536 558 561 561 584 537 537 559 537 537 559 561 561 584 562 562 585 537 537 559 562 562 585 538 538 560 538 538 560 562 562 585 563 563 586 538 538 560 563 563 586 539 539 561 539 539 561 563 563 586 564 564 587 539 539 561 564 564 587 540 540 562 540 540 562 564 564 587 565 565 588 540 540 562 565 565 588 541 541 563 541 541 563 565 565 588 566 566 589 541 541 563 566 566 589 542 542 564 542 542 564 566 566 589 567 567 590 542 542 564 567 567 590 543 543 565 543 543 565 567 567 590 568 568 591 543 543 565 568 568 591 544 544 566 544 544 566 568 568 591 569 569 592 544 544 566 569 569 592 545 545 567 545 545 567 569 569 592 570 570 593 545 545 567 570 570 593 546 546 568 546 546 568 570 570 593 571 571 594 546 546 568 571 571 594 547 547 569 547 547 569 571 571 594 572 572 595 547 547 569 572 572 595 548 548 570 548 548 570 572 572 595 573 573 596 548 548 570 573 573 596 549 549 571 549 549 571 573 573 596 574 574 597 549 549 571 574 574 597 550 550 572 550 550 572 574 574 597 575 575 598 550 550 572 575 575 598 551 551 573 551 551 573 575 575 598 552 552 599 551 551 573 552 552 599 528 528 574 552 552 575 576 576 600 577 577 601 552 552 575 577 577 601 553 553 576 553 553 576 577 577 601 578 578 602 553 553 576 578 578 602 554 554 577 554 554 577 578 578 602 579 579 603 554 554 577 579 579 603 555 555 578 555 555 578 579 579 603 580 580 604 555 555 578 580 580 604 556 556 579 556 556 579 580 580 604 581 581 605 556 556 579 581 581 605 557 557 580 557 557 580 581 581 605 582 582 606 557 557 580 582 582 606 558 558 581 558 558 581 582 582 606 583 583 607 558 558 581 583 583 607 559 559 582 559 559 582 583 583 607 584 584 608 559 559 582 584 584 608 560 560 583 560 560 583 584 584 608 585 585 609 560 560 583 585 585 609 561 561 584 561 561 584 585 585 609 586 586 610 561 561 584 586 586 610 562 562 585 562 562 585 586 586 610 587 587 611 562 562 585 587 587 611 563 563 586 563 563 586 587 587 611 588 588 612 563 563 586 588 588 612 564 564 587 564 564 587 588 588 612 589 589 613 564 564 587 589 589 613 565 565 588 565 565 588 589 589 613 590 590 614 565 565 588 590 590 614 566 566 589 566 566 589 590 590 614 591 591 615 566 566 589 591 591 615 567 567 590 567 567 590 591 591 615 592 592 616 567 567 590 592 592 616 568 568 591 568 568 591 592 592 616 593 593 617 568 568 591 593 593 617 569 569 592 569 569 592 593 593 617 594 594 618 569 569 592 594 594 618 570 570 593 570 570 593 594 594 618 595 595 619 570 570 593 595 595 619 571 571 594 571 571 594 595 595 619 596 596 620 571 571 594 596 596 620 572 572 595 572 572 595 596 596 620 597 597 621 572 572 595 597 597 621 573 573 596 573 573 596 597 597 621 598 598 622 573 573 596 598 598 622 574 574 597 574 574 597 598 598 622 599 599 623 574 574 597 599 599 623 575 575 598 575 575 598 599 599 623 576 576 624 575 575 598 576 576 624 552 552 599 576 576 600 600 600 625 601 601 626 576 576 600 601 601 626 577 577 601 577 577 601 601 601 626 602 602 627 577 577 601 602 602 627 578 578 602 578 578 602 602 602 627 603 603 628 578 578 602 603 603 628 579 579 603 579 579 603 603 603 628 604 604 629 579 579 603 604 604 629 580 580 604 580 580 604 604 604 629 605 605 630 580 580 604 605 605 630 581 581 605 581 581 605 605 605 630 606 606 631 581 581 605 606 606 631 582 582 606 582 582 606 606 606 631 607 607 632 582 582 606 607 607 632 583 583 607 583 583 607 607 607 632 608 608 633 583 583 607 608 608 633 584 584 608 584 584 608 608 608 633 609 609 634 584 584 608 609 609 634 585 585 609 585 585 609 609 609 634 610 610 635 585 585 609 610 610 635 586 586 610 586 586 610 610 610 635 611 611 636 586 586 610 611 611 636 587 587 611 587 587 611 611 611 636 612 612 637 587 587 611 612 612 637 588 588 612 588 588 612 612 612 637 613 613 638 588 588 612 613 613 638 589 589 613 589 589 613 613 613 638 614 614 639 589 589 613 614 614 639 590 590 614 590 590 614 614 614 639 615 615 640 590 590 614 615 615 640 591 591 615 591 591 615 615 615 640 616 616 641 591 591 615 616 616 641 592 592 616 592 592 616 616 616 641 617 617 642 592 592 616 617 617 642 593 593 617 593 593 617 617 617 642 618 618 643 593 593 617 618 618 643 594 594 618 594 594 618 618 618 643 619 619 644 594 594 618 619 619 644 595 595 619 595 595 619 619 619 644 620 620 645 595 595 619 620 620 645 596 596 620 596 596 620 620 620 645 621 621 646 596 596 620 621 621 646 597 597 621 597 597 621 621 621 646 622 622 647 597 597 621 622 622 647 598 598 622 598 598 622 622 622 647 623 623 648 598 598 622 623 623 648 599 599 623 599 599 623 623 623 648 600 600 649 599 599 623 600 600 649 576 576 624 600 600 625 624 624 650 625 625 651 600 600 625 625 625 651 601 601 626 601 601 626 625 625 651 626 626 652 601 601 626 626 626 652 602 602 627 602 602 627 626 626 652 627 627 653 602 602 627 627 627 653 603 603 628 603 603 628 627 627 653 628 628 654 603 603 628 628 628 654 604 604 629 604 604 629 628 628 654 629 629 655 604 604 629 629 629 655 605 605 630 605 605 630 629 629 655 630 630 656 605 605 630 630 630 656 606 606 631 606 606 631 630 630 656 631 631 657 606 606 631 631 631 657 607 607 632 607 607 632 631 631 657 632 632 658 607 607 632 632 632 658 608 608 633 608 608 633 632 632 658 633 633 659 608 608 633 633 633 659 609 609 634 609 609 634 633 633 659 634 634 660 609 609 634 634 634 660 610 610 635 610 610 635 634 634 660 635 635 661 610 610 635 635 635 661 611 611 636 611 611 636 635 635 661 636 636 662 611 611 636 636 636 662 612 612 637 612 612 637 636 636 662 637 637 663 612 612 637 637 637 663 613 613 638 613 613 638 637 637 663 638 638 664 613 613 638 638 638 664 614 614 639 614 614 639 638 638 664 639 639 665 614 614 639 639 639 665 615 615 640 615 615 640 639 639 665 640 640 666 615 615 640 640 640 666 616 616 641 616 616 641 640 640 666 641 641 667 616 616 641 641 641 667 617 617 642 617 617 642 641 641 667 642 642 668 617 617 642 642 642 668 618 618 643 618 618 643 642 642 668 643 643 669 618 618 643 643 643 669 619 619 644 619 619 644 643 643 669 644 644 670 619 619 644 644 644 670 620 620 645 620 620 645 644 644 670 645 645 671 620 620 645 645 645 671 621 621 646 621 621 646 645 645 671 646 646 672 621 621 646 646 646 672 622 622 647 622 622 647 646 646 672 647 647 673 622 622 647 647 647 673 623 623 648 623 623 648 647 647 673 624 624 674 623 623 648 624 624 674 600 600 649 624 624 650 648 648 675 649 649 676 624 624 650 649 649 676 625 625 651 625 625 651 649 649 676 650 650 677 625 625 651 650 650 677 626 626 652 626 626 652 650 650 677 651 651 678 626 626 652 651 651 678 627 627 653 627 627 653 651 651 678 652 652 679 627 627 653 652 652 679 628 628 654 628 628 654 652 652 679 653 653 680 628 628 654 653 653 680 629 629 655 629 629 655 653 653 680 654 654 681 629 629 655 654 654 681 630 630 656 630 630 656 654 654 681 655 655 682 630 630 656 655 655 682 631 631 657 631 631 657 655 655 682 656 656 683 631 631 657 656 656 683 632 632 658 632 632 658 656 656 683 657 657 684 632 632 658 657 657 684 633 633 659 633 633 659 657 657 684 658 658 685 633 633 659 658 658 685 634 634 660 634 634 660 658 658 685 659 659 686 634 634 660 659 659 686 635 635 661 635 635 661 659 659 686 660 660 687 635 635 661 660 660 687 636 636 662 636 636 662 660 660 687 661 661 688 636 636 662 661 661 688 637 637 663 637 637 663 661 661 688 662 662 689 637 637 663 662 662 689 638 638 664 638 638 664 662 662 689 663 663 690 638 638 664 663 663 690 639 639 665 639 639 665 663 663 690 664 664 691 639 639 665 664 664 691 640 640 666 640 640 666 664 664 691 665 665 692 640 640 666 665 665 692 641 641 667 641 641 667 665 665 692 666 666 693 641 641 667 666 666 693 642 642 668 642 642 668 666 666 693 667 667 694 642 642 668 667 667 694 643 643 669 643 643 669 667 667 694 668 668 695 643 643 669 668 668 695 644 644 670 644 644 670 668 668 695 669 669 696 644 644 670 669 669 696 645 645 671 645 645 671 669 669 696 670 670 697 645 645 671 670 670 697 646 646 672 646 646 672 670 670 697 671 671 698 646 646 672 671 671 698 647 647 673 647 647 673 671 671 698 648 648 699 647 647 673 648 648 699 624 624 674 648 648 675 672 672 700 673 673 701 648 648 675 673 673 701 649 649 676 649 649 676 673 673 701 674 674 702 649 649 676 674 674 702 650 650 677 650 650 677 674 674 702 675 675 703 650 650 677 675 675 703 651 651 678 651 651 678 675 675 703 676 676 704 651 651 678 676 676 704 652 652 679 652 652 679 676 676 704 677 677 705 652 652 679 677 677 705 653 653 680 653 653 680 677 677 705 678 678 706 653 653 680 678 678 706 654 654 681 654 654 681 678 678 706 679 679 707 654 654 681 679 679 707 655 655 682 655 655 682 679 679 707 680 680 708 655 655 682 680 680 708 656 656 683 656 656 683 680 680 708 681 681 709 656 656 683 681 681 709 657 657 684 657 657 684 681 681 709 682 682 710 657 657 684 682 682 710 658 658 685 658 658 685 682 682 710 683 683 711 658 658 685 683 683 711 659 659 686 659 659 686 683 683 711 684 684 712 659 659 686 684 684 712 660 660 687 660 660 687 684 684 712 685 685 713 660 660 687 685 685 713 661 661 688 661 661 688 685 685 713 686 686 714 661 661 688 686 686 714 662 662 689 662 662 689 686 686 714 687 687 715 662 662 689 687 687 715 663 663 690 663 663 690 687 687 715 688 688 716 663 663 690 688 688 716 664 664 691 664 664 691 688 688 716 689 689 717 664 664 691 689 689 717 665 665 692 665 665 692 689 689 717 690 690 718 665 665 692 690 690 718 666 666 693 666 666 693 690 690 718 691 691 719 666 666 693 691 691 719 667 667 694 667 667 694 691 691 719 692 692 720 667 667 694 692 692 720 668 668 695 668 668 695 692 692 720 693 693 721 668 668 695 693 693 721 669 669 696 669 669 696 693 693 721 694 694 722 669 669 696 694 694 722 670 670 697 670 670 697 694 694 722 695 695 723 670 670 697 695 695 723 671 671 698 671 671 698 695 695 723 672 672 724 671 671 698 672 672 724 648 648 699 672 672 700 696 696 725 697 697 726 672 672 700 697 697 726 673 673 701 673 673 701 697 697 726 698 698 727 673 673 701 698 698 727 674 674 702 674 674 702 698 698 727 699 699 728 674 674 702 699 699 728 675 675 703 675 675 703 699 699 728 700 700 729 675 675 703 700 700 729 676 676 704 676 676 704 700 700 729 701 701 730 676 676 704 701 701 730 677 677 705 677 677 705 701 701 730 702 702 731 677 677 705 702 702 731 678 678 706 678 678 706 702 702 731 703 703 732 678 678 706 703 703 732 679 679 707 679 679 707 703 703 732 704 704 733 679 679 707 704 704 733 680 680 708 680 680 708 704 704 733 705 705 734 680 680 708 705 705 734 681 681 709 681 681 709 705 705 734 706 706 735 681 681 709 706 706 735 682 682 710 682 682 710 706 706 735 707 707 736 682 682 710 707 707 736 683 683 711 683 683 711 707 707 736 708 708 737 683 683 711 708 708 737 684 684 712 684 684 712 708 708 737 709 709 738 684 684 712 709 709 738 685 685 713 685 685 713 709 709 738 710 710 739 685 685 713 710 710 739 686 686 714 686 686 714 710 710 739 711 711 740 686 686 714 711 711 740 687 687 715 687 687 715 711 711 740 712 712 741 687 687 715 712 712 741 688 688 716 688 688 716 712 712 741 713 713 742 688 688 716 713 713 742 689 689 717 689 689 717 713 713 742 714 714 743 689 689 717 714 714 743 690 690 718 690 690 718 714 714 743 715 715 744 690 690 718 715 715 744 691 691 719 691 691 719 715 715 744 716 716 745 691 691 719 716 716 745 692 692 720 692 692 720 716 716 745 717 717 746 692 692 720 717 717 746 693 693 721 693 693 721 717 717 746 718 718 747 693 693 721 718 718 747 694 694 722 694 694 722 718 718 747 719 719 748 694 694 722 719 719 748 695 695 723 695 695 723 719 719 748 696 696 749 695 695 723 696 696 749 672 672 724 696 696 725 720 720 750 721 721 751 696 696 725 721 721 751 697 697 726 697 697 726 721 721 751 722 722 752 697 697 726 722 722 752 698 698 727 698 698 727 722 722 752 723 723 753 698 698 727 723 723 753 699 699 728 699 699 728 723 723 753 724 724 754 699 699 728 724 724 754 700 700 729 700 700 729 724 724 754 725 725 755 700 700 729 725 725 755 701 701 730 701 701 730 725 725 755 726 726 756 701 701 730 726 726 756 702 702 731 702 702 731 726 726 756 727 727 757 702 702 731 727 727 757 703 703 732 703 703 732 727 727 757 728 728 758 703 703 732 728 728 758 704 704 733 704 704 733 728 728 758 729 729 759 704 704 733 729 729 759 705 705 734 705 705 734 729 729 759 730 730 760 705 705 734 730 730 760 706 706 735 706 706 735 730 730 760 731 731 761 706 706 735 731 731 761 707 707 736 707 707 736 731 731 761 732 732 762 707 707 736 732 732 762 708 708 737 708 708 737 732 732 762 733 733 763 708 708 737 733 733 763 709 709 738 709 709 738 733 733 763 734 734 764 709 709 738 734 734 764 710 710 739 710 710 739 734 734 764 735 735 765 710 710 739 735 735 765 711 711 740 711 711 740 735 735 765 736 736 766 711 711 740 736 736 766 712 712 741 712 712 741 736 736 766 737 737 767 712 712 741 737 737 767 713 713 742 713 713 742 737 737 767 738 738 768 713 713 742 738 738 768 714 714 743 714 714 743 738 738 768 739 739 769 714 714 743 739 739 769 715 715 744 715 715 744 739 739 769 740 740 770 715 715 744 740 740 770 716 716 745 716 716 745 740 740 770 741 741 771 716 716 745 741 741 771 717 717 746 717 717 746 741 741 771 742 742 772 717 717 746 742 742 772 718 718 747 718 718 747 742 742 772 743 743 773 718 718 747 743 743 773 719 719 748 719 719 748 743 743 773 720 720 774 719 719 748 720 720 774 696 696 749 720 720 750 744 744 775 745 745 776 720 720 750 745 745 776 721 721 751 721 721 751 745 745 776 746 746 777 721 721 751 746 746 777 722 722 752 722 722 752 746 746 777 747 747 778 722 722 752 747 747 778 723 723 753 723 723 753 747 747 778 748 748 779 723 723 753 748 748 779 724 724 754 724 724 754 748 748 779 749 749 780 724 724 754 749 749 780 725 725 755 725 725 755 749 749 780 750 750 781 725 725 755 750 750 781 726 726 756 726 726 756 750 750 781 751 751 782 726 726 756 751 751 782 727 727 757 727 727 757 751 751 782 752 752 783 727 727 757 752 752 783 728 728 758 728 728 758 752 752 783 753 753 784 728 728 758 753 753 784 729 729 759 729 729 759 753 753 784 754 754 785 729 729 759 754 754 785 730 730 760 730 730 760 754 754 785 755 755 786 730 730 760 755 755 786 731 731 761 731 731 761 755 755 786 756 756 787 731 731 761 756 756 787 732 732 762 732 732 762 756 756 787 757 757 788 732 732 762 757 757 788 733 733 763 733 733 763 757 757 788 758 758 789 733 733 763 758 758 789 734 734 764 734 734 764 758 758 789 759 759 790 734 734 764 759 759 790 735 735 765 735 735 765 759 759 790 760 760 791 735 735 765 760 760 791 736 736 766 736 736 766 760 760 791 761 761 792 736 736 766 761 761 792 737 737 767 737 737 767 761 761 792 762 762 793 737 737 767 762 762 793 738 738 768 738 738 768 762 762 793 763 763 794 738 738 768 763 763 794 739 739 769 739 739 769 763 763 794 764 764 795 739 739 769 764 764 795 740 740 770 740 740 770 764 764 795 765 765 796 740 740 770 765 765 796 741 741 771 741 741 771 765 765 796 766 766 797 741 741 771 766 766 797 742 742 772 742 742 772 766 766 797 767 767 798 742 742 772 767 767 798 743 743 773 743 743 773 767 767 798 744 744 799 743 743 773 744 744 799 720 720 774 744 744 775 768 768 800 769 769 801 744 744 775 769 769 801 745 745 776 745 745 776 769 769 801 770 770 802 745 745 776 770 770 802 746 746 777 746 746 777 770 770 802 771 771 803 746 746 777 771 771 803 747 747 778 747 747 778 771 771 803 772 772 804 747 747 778 772 772 804 748 748 779 748 748 779 772 772 804 773 773 805 748 748 779 773 773 805 749 749 780 749 749 780 773 773 805 774 774 806 749 749 780 774 774 806 750 750 781 750 750 781 774 774 806 775 775 807 750 750 781 775 775 807 751 751 782 751 751 782 775 775 807 776 776 808 751 751 782 776 776 808 752 752 783 752 752 783 776 776 808 777 777 809 752 752 783 777 777 809 753 753 784 753 753 784 777 777 809 778 778 810 753 753 784 778 778 810 754 754 785 754 754 785 778 778 810 779 779 811 754 754 785 779 779 811 755 755 786 755 755 786 779 779 811 780 780 812 755 755 786 780 780 812 756 756 787 756 756 787 780 780 812 781 781 813 756 756 787 781 781 813 757 757 788 757 757 788 781 781 813 782 782 814 757 757 788 782 782 814 758 758 789 758 758 789 782 782 814 783 783 815 758 758 789 783 783 815 759 759 790 759 759 790 783 783 815 784 784 816 759 759 790 784 784 816 760 760 791 760 760 791 784 784 816 785 785 817 760 760 791 785 785 817 761 761 792 761 761 792 785 785 817 786 786 818 761 761 792 786 786 818 762 762 793 762 762 793 786 786 818 787 787 819 762 762 793 787 787 819 763 763 794 763 763 794 787 787 819 788 788 820 763 763 794 788 788 820 764 764 795 764 764 795 788 788 820 789 789 821 764 764 795 789 789 821 765 765 796 765 765 796 789 789 821 790 790 822 765 765 796 790 790 822 766 766 797 766 766 797 790 790 822 791 791 823 766 766 797 791 791 823 767 767 798 767 767 798 791 791 823 768 768 824 767 767 798 768 768 824 744 744 799 768 768 800 792 792 825 793 793 826 768 768 800 793 793 826 769 769 801 769 769 801 793 793 826 794 794 827 769 769 801 794 794 827 770 770 802 770 770 802 794 794 827 795 795 828 770 770 802 795 795 828 771 771 803 771 771 803 795 795 828 796 796 829 771 771 803 796 796 829 772 772 804 772 772 804 796 796 829 797 797 830 772 772 804 797 797 830 773 773 805 773 773 805 797 797 830 798 798 831 773 773 805 798 798 831 774 774 806 774 774 806 798 798 831 799 799 832 774 774 806 799 799 832 775 775 807 775 775 807 799 799 832 800 800 833 775 775 807 800 800 833 776 776 808 776 776 808 800 800 833 801 801 834 776 776 808 801 801 834 777 777 809 777 777 809 801 801 834 802 802 835 777 777 809 802 802 835 778 778 810 778 778 810 802 802 835 803 803 836 778 778 810 803 803 836 779 779 811 779 779 811 803 803 836 804 804 837 779 779 811 804 804 837 780 780 812 780 780 812 804 804 837 805 805 838 780 780 812 805 805 838 781 781 813 781 781 813 805 805 838 806 806 839 781 781 813 806 806 839 782 782 814 782 782 814 806 806 839 807 807 840 782 782 814 807 807 840 783 783 815 783 783 815 807 807 840 808 808 841 783 783 815 808 808 841 784 784 816 784 784 816 808 808 841 809 809 842 784 784 816 809 809 842 785 785 817 785 785 817 809 809 842 810 810 843 785 785 817 810 810 843 786 786 818 786 786 818 810 810 843 811 811 844 786 786 818 811 811 844 787 787 819 787 787 819 811 811 844 812 812 845 787 787 819 812 812 845 788 788 820 788 788 820 812 812 845 813 813 846 788 788 820 813 813 846 789 789 821 789 789 821 813 813 846 814 814 847 789 789 821 814 814 847 790 790 822 790 790 822 814 814 847 815 815 848 790 790 822 815 815 848 791 791 823 791 791 823 815 815 848 792 792 849 791 791 823 792 792 849 768 768 824 792 792 825 816 816 850 817 817 851 792 792 825 817 817 851 793 793 826 793 793 826 817 817 851 818 818 852 793 793 826 818 818 852 794 794 827 794 794 827 818 818 852 819 819 853 794 794 827 819 819 853 795 795 828 795 795 828 819 819 853 820 820 854 795 795 828 820 820 854 796 796 829 796 796 829 820 820 854 821 821 855 796 796 829 821 821 855 797 797 830 797 797 830 821 821 855 822 822 856 797 797 830 822 822 856 798 798 831 798 798 831 822 822 856 823 823 857 798 798 831 823 823 857 799 799 832 799 799 832 823 823 857 824 824 858 799 799 832 824 824 858 800 800 833 800 800 833 824 824 858 825 825 859 800 800 833 825 825 859 801 801 834 801 801 834 825 825 859 826 826 860 801 801 834 826 826 860 802 802 835 802 802 835 826 826 860 827 827 861 802 802 835 827 827 861 803 803 836 803 803 836 827 827 861 828 828 862 803 803 836 828 828 862 804 804 837 804 804 837 828 828 862 829 829 863 804 804 837 829 829 863 805 805 838 805 805 838 829 829 863 830 830 864 805 805 838 830 830 864 806 806 839 806 806 839 830 830 864 831 831 865 806 806 839 831 831 865 807 807 840 807 807 840 831 831 865 832 832 866 807 807 840 832 832 866 808 808 841 808 808 841 832 832 866 833 833 867 808 808 841 833 833 867 809 809 842 809 809 842 833 833 867 834 834 868 809 809 842 834 834 868 810 810 843 810 810 843 834 834 868 835 835 869 810 810 843 835 835 869 811 811 844 811 811 844 835 835 869 836 836 870 811 811 844 836 836 870 812 812 845 812 812 845 836 836 870 837 837 871 812 812 845 837 837 871 813 813 846 813 813 846 837 837 871 838 838 872 813 813 846 838 838 872 814 814 847 814 814 847 838 838 872 839 839 873 814 814 847 839 839 873 815 815 848 815 815 848 839 839 873 816 816 874 815 815 848 816 816 874 792 792 849 816 816 850 840 840 875 841 841 876 816 816 850 841 841 876 817 817 851 817 817 851 841 841 876 842 842 877 817 817 851 842 842 877 818 818 852 818 818 852 842 842 877 843 843 878 818 818 852 843 843 878 819 819 853 819 819 853 843 843 878 844 844 879 819 819 853 844 844 879 820 820 854 820 820 854 844 844 879 845 845 880 820 820 854 845 845 880 821 821 855 821 821 855 845 845 880 846 846 881 821 821 855 846 846 881 822 822 856 822 822 856 846 846 881 847 847 882 822 822 856 847 847 882 823 823 857 823 823 857 847 847 882 848 848 883 823 823 857 848 848 883 824 824 858 824 824 858 848 848 883 849 849 884 824 824 858 849 849 884 825 825 859 825 825 859 849 849 884 850 850 885 825 825 859 850 850 885 826 826 860 826 826 860 850 850 885 851 851 886 826 826 860 851 851 886 827 827 861 827 827 861 851 851 886 852 852 887 827 827 861 852 852 887 828 828 862 828 828 862 852 852 887 853 853 888 828 828 862 853 853 888 829 829 863 829 829 863 853 853 888 854 854 889 829 829 863 854 854 889 830 830 864 830 830 864 854 854 889 855 855 890 830 830 864 855 855 890 831 831 865 831 831 865 855 855 890 856 856 891 831 831 865 856 856 891 832 832 866 832 832 866 856 856 891 857 857 892 832 832 866 857 857 892 833 833 867 833 833 867 857 857 892 858 858 893 833 833 867 858 858 893 834 834 868 834 834 868 858 858 893 859 859 894 834 834 868 859 859 894 835 835 869 835 835 869 859 859 894 860 860 895 835 835 869 860 860 895 836 836 870 836 836 870 860 860 895 861 861 896 836 836 870 861 861 896 837 837 871 837 837 871 861 861 896 862 862 897 837 837 871 862 862 897 838 838 872 838 838 872 862 862 897 863 863 898 838 838 872 863 863 898 839 839 873 839 839 873 863 863 898 840 840 899 839 839 873 840 840 899 816 816 874 840 840 875 864 864 900 865 865 901 840 840 875 865 865 901 841 841 876 841 841 876 865 865 901 866 866 902 841 841 876 866 866 902 842 842 877 842 842 877 866 866 902 867 867 903 842 842 877 867 867 903 843 843 878 843 843 878 867 867 903 868 868 904 843 843 878 868 868 904 844 844 879 844 844 879 868 868 904 869 869 905 844 844 879 869 869 905 845 845 880 845 845 880 869 869 905 870 870 906 845 845 880 870 870 906 846 846 881 846 846 881 870 870 906 871 871 907 846 846 881 871 871 907 847 847 882 847 847 882 871 871 907 872 872 908 847 847 882 872 872 908 848 848 883 848 848 883 872 872 908 873 873 909 848 848 883 873 873 909 849 849 884 849 849 884 873 873 909 874 874 910 849 849 884 874 874 910 850 850 885 850 850 885 874 874 910 875 875 911 850 850 885 875 875 911 851 851 886 851 851 886 875 875 911 876 876 912 851 851 886 876 876 912 852 852 887 852 852 887 876 876 912 877 877 913 852 852 887 877 877 913 853 853 888 853 853 888 877 877 913 878 878 914 853 853 888 878 878 914 854 854 889 854 854 889 878 878 914 879 879 915 854 854 889 879 879 915 855 855 890 855 855 890 879 879 915 880 880 916 855 855 890 880 880 916 856 856 891 856 856 891 880 880 916 881 881 917 856 856 891 881 881 917 857 857 892 857 857 892 881 881 917 882 882 918 857 857 892 882 882 918 858 858 893 858 858 893 882 882 918 883 883 919 858 858 893 883 883 919 859 859 894 859 859 894 883 883 919 884 884 920 859 859 894 884 884 920 860 860 895 860 860 895 884 884 920 885 885 921 860 860 895 885 885 921 861 861 896 861 861 896 885 885 921 886 886 922 861 861 896 886 886 922 862 862 897 862 862 897 886 886 922 887 887 923 862 862 897 887 887 923 863 863 898 863 863 898 887 887 923 864 864 924 863 863 898 864 864 924 840 840 899 864 864 900 888 888 925 889 889 926 864 864 900 889 889 926 865 865 901 865 865 901 889 889 926 890 890 927 865 865 901 890 890 927 866 866 902 866 866 902 890 890 927 891 891 928 866 866 902 891 891 928 867 867 903 867 867 903 891 891 928 892 892 929 867 867 903 892 892 929 868 868 904 868 868 904 892 892 929 893 893 930 868 868 904 893 893 930 869 869 905 869 869 905 893 893 930 894 894 931 869 869 905 894 894 931 870 870 906 870 870 906 894 894 931 895 895 932 870 870 906 895 895 932 871 871 907 871 871 907 895 895 932 896 896 933 871 871 907 896 896 933 872 872 908 872 872 908 896 896 933 897 897 934 872 872 908 897 897 934 873 873 909 873 873 909 897 897 934 898 898 935 873 873 909 898 898 935 874 874 910 874 874 910 898 898 935 899 899 936 874 874 910 899 899 936 875 875 911 875 875 911 899 899 936 900 900 937 875 875 911 900 900 937 876 876 912 876 876 912 900 900 937 901 901 938 876 876 912 901 901 938 877 877 913 877 877 913 901 901 938 902 902 939 877 877 913 902 902 939 878 878 914 878 878 914 902 902 939 903 903 940 878 878 914 903 903 940 879 879 915 879 879 915 903 903 940 904 904 941 879 879 915 904 904 941 880 880 916 880 880 916 904 904 941 905 905 942 880 880 916 905 905 942 881 881 917 881 881 917 905 905 942 906 906 943 881 881 917 906 906 943 882 882 918 882 882 918 906 906 943 907 907 944 882 882 918 907 907 944 883 883 919 883 883 919 907 907 944 908 908 945 883 883 919 908 908 945 884 884 920 884 884 920 908 908 945 909 909 946 884 884 920 909 909 946 885 885 921 885 885 921 909 909 946 910 910 947 885 885 921 910 910 947 886 886 922 886 886 922 910 910 947 911 911 948 886 886 922 911 911 948 887 887 923 887 887 923 911 911 948 888 888 949 887 887 923 888 888 949 864 864 924 888 888 925 912 912 950 913 913 951 888 888 925 913 913 951 889 889 926 889 889 926 913 913 951 914 914 952 889 889 926 914 914 952 890 890 927 890 890 927 914 914 952 915 915 953 890 890 927 915 915 953 891 891 928 891 891 928 915 915 953 916 916 954 891 891 928 916 916 954 892 892 929 892 892 929 916 916 954 917 917 955 892 892 929 917 917 955 893 893 930 893 893 930 917 917 955 918 918 956 893 893 930 918 918 956 894 894 931 894 894 931 918 918 956 919 919 957 894 894 931 919 919 957 895 895 932 895 895 932 919 919 957 920 920 958 895 895 932 920 920 958 896 896 933 896 896 933 920 920 958 921 921 959 896 896 933 921 921 959 897 897 934 897 897 934 921 921 959 922 922 960 897 897 934 922 922 960 898 898 935 898 898 935 922 922 960 923 923 961 898 898 935 923 923 961 899 899 936 899 899 936 923 923 961 924 924 962 899 899 936 924 924 962 900 900 937 900 900 937 924 924 962 925 925 963 900 900 937 925 925 963 901 901 938 901 901 938 925 925 963 926 926 964 901 901 938 926 926 964 902 902 939 902 902 939 926 926 964 927 927 965 902 902 939 927 927 965 903 903 940 903 903 940 927 927 965 928 928 966 903 903 940 928 928 966 904 904 941 904 904 941 928 928 966 929 929 967 904 904 941 929 929 967 905 905 942 905 905 942 929 929 967 930 930 968 905 905 942 930 930 968 906 906 943 906 906 943 930 930 968 931 931 969 906 906 943 931 931 969 907 907 944 907 907 944 931 931 969 932 932 970 907 907 944 932 932 970 908 908 945 908 908 945 932 932 970 933 933 971 908 908 945 933 933 971 909 909 946 909 909 946 933 933 971 934 934 972 909 909 946 934 934 972 910 910 947 910 910 947 934 934 972 935 935 973 910 910 947 935 935 973 911 911 948 911 911 948 935 935 973 912 912 974 911 911 948 912 912 974 888 888 949 912 912 950 936 936 975 937 937 976 912 912 950 937 937 976 913 913 951 913 913 951 937 937 976 938 938 977 913 913 951 938 938 977 914 914 952 914 914 952 938 938 977 939 939 978 914 914 952 939 939 978 915 915 953 915 915 953 939 939 978 940 940 979 915 915 953 940 940 979 916 916 954 916 916 954 940 940 979 941 941 980 916 916 954 941 941 980 917 917 955 917 917 955 941 941 980 942 942 981 917 917 955 942 942 981 918 918 956 918 918 956 942 942 981 943 943 982 918 918 956 943 943 982 919 919 957 919 919 957 943 943 982 944 944 983 919 919 957 944 944 983 920 920 958 920 920 958 944 944 983 945 945 984 920 920 958 945 945 984 921 921 959 921 921 959 945 945 984 946 946 985 921 921 959 946 946 985 922 922 960 922 922 960 946 946 985 947 947 986 922 922 960 947 947 986 923 923 961 923 923 961 947 947 986 948 948 987 923 923 961 948 948 987 924 924 962 924 924 962 948 948 987 949 949 988 924 924 962 949 949 988 925 925 963 925 925 963 949 949 988 950 950 989 925 925 963 950 950 989 926 926 964 926 926 964 950 950 989 951 951 990 926 926 964 951 951 990 927 927 965 927 927 965 951 951 990 952 952 991 927 927 965 952 952 991 928 928 966 928 928 966 952 952 991 953 953 992 928 928 966 953 953 992 929 929 967 929 929 967 953 953 992 954 954 993 929 929 967 954 954 993 930 930 968 930 930 968 954 954 993 955 955 994 930 930 968 955 955 994 931 931 969 931 931 969 955 955 994 956 956 995 931 931 969 956 956 995 932 932 970 932 932 970 956 956 995 957 957 996 932 932 970 957 957 996 933 933 971 933 933 971 957 957 996 958 958 997 933 933 971 958 958 997 934 934 972 934 934 972 958 958 997 959 959 998 934 934 972 959 959 998 935 935 973 935 935 973 959 959 998 936 936 999 935 935 973 936 936 999 912 912 974 936 936 975 960 960 1000 961 961 1001 936 936 975 961 961 1001 937 937 976 937 937 976 961 961 1001 962 962 1002 937 937 976 962 962 1002 938 938 977 938 938 977 962 962 1002 963 963 1003 938 938 977 963 963 1003 939 939 978 939 939 978 963 963 1003 964 964 1004 939 939 978 964 964 1004 940 940 979 940 940 979 964 964 1004 965 965 1005 940 940 979 965 965 1005 941 941 980 941 941 980 965 965 1005 966 966 1006 941 941 980 966 966 1006 942 942 981 942 942 981 966 966 1006 967 967 1007 942 942 981 967 967 1007 943 943 982 943 943 982 967 967 1007 968 968 1008 943 943 982 968 968 1008 944 944 983 944 944 983 968 968 1008 969 969 1009 944 944 983 969 969 1009 945 945 984 945 945 984 969 969 1009 970 970 1010 945 945 984 970 970 1010 946 946 985 946 946 985 970 970 1010 971 971 1011 946 946 985 971 971 1011 947 947 986 947 947 986 971 971 1011 972 972 1012 947 947 986 972 972 1012 948 948 987 948 948 987 972 972 1012 973 973 1013 948 948 987 973 973 1013 949 949 988 949 949 988 973 973 1013 974 974 1014 949 949 988 974 974 1014 950 950 989 950 950 989 974 974 1014 975 975 1015 950 950 989 975 975 1015 951 951 990 951 951 990 975 975 1015 976 976 1016 951 951 990 976 976 1016 952 952 991 952 952 991 976 976 1016 977 977 1017 952 952 991 977 977 1017 953 953 992 953 953 992 977 977 1017 978 978 1018 953 953 992 978 978 1018 954 954 993 954 954 993 978 978 1018 979 979 1019 954 954 993 979 979 1019 955 955 994 955 955 994 979 979 1019 980 980 1020 955 955 994 980 980 1020 956 956 995 956 956 995 980 980 1020 981 981 1021 956 956 995 981 981 1021 957 957 996 957 957 996 981 981 1021 982 982 1022 957 957 996 982 982 1022 958 958 997 958 958 997 982 982 1022 983 983 1023 958 958 997 983 983 1023 959 959 998 959 959 998 983 983 1023 960 960 1024 959 959 998 960 960 1024 936 936 999 960 960 1000 984 984 1025 985 985 1026 960 960 1000 985 985 1026 961 961 1001 961 961 1001 985 985 1026 986 986 1027 961 961 1001 986 986 1027 962 962 1002 962 962 1002 986 986 1027 987 987 1028 962 962 1002 987 987 1028 963 963 1003 963 963 1003 987 987 1028 988 988 1029 963 963 1003 988 988 1029 964 964 1004 964 964 1004 988 988 1029 989 989 1030 964 964 1004 989 989 1030 965 965 1005 965 965 1005 989 989 1030 990 990 1031 965 965 1005 990 990 1031 966 966 1006 966 966 1006 990 990 1031 991 991 1032 966 966 1006 991 991 1032 967 967 1007 967 967 1007 991 991 1032 992 992 1033 967 967 1007 992 992 1033 968 968 1008 968 968 1008 992 992 1033 993 993 1034 968 968 1008 993 993 1034 969 969 1009 969 969 1009 993 993 1034 994 994 1035 969 969 1009 994 994 1035 970 970 1010 970 970 1010 994 994 1035 995 995 1036 970 970 1010 995 995 1036 971 971 1011 971 971 1011 995 995 1036 996 996 1037 971 971 1011 996 996 1037 972 972 1012 972 972 1012 996 996 1037 997 997 1038 972 972 1012 997 997 1038 973 973 1013 973 973 1013 997 997 1038 998 998 1039 973 973 1013 998 998 1039 974 974 1014 974 974 1014 998 998 1039 999 999 1040 974 974 1014 999 999 1040 975 975 1015 975 975 1015 999 999 1040 1000 1000 1041 975 975 1015 1000 1000 1041 976 976 1016 976 976 1016 1000 1000 1041 1001 1001 1042 976 976 1016 1001 1001 1042 977 977 1017 977 977 1017 1001 1001 1042 1002 1002 1043 977 977 1017 1002 1002 1043 978 978 1018 978 978 1018 1002 1002 1043 1003 1003 1044 978 978 1018 1003 1003 1044 979 979 1019 979 979 1019 1003 1003 1044 1004 1004 1045 979 979 1019 1004 1004 1045 980 980 1020 980 980 1020 1004 1004 1045 1005 1005 1046 980 980 1020 1005 1005 1046 981 981 1021 981 981 1021 1005 1005 1046 1006 1006 1047 981 981 1021 1006 1006 1047 982 982 1022 982 982 1022 1006 1006 1047 1007 1007 1048 982 982 1022 1007 1007 1048 983 983 1023 983 983 1023 1007 1007 1048 984 984 1049 983 983 1023 984 984 1049 960 960 1024 984 984 1025 1008 1008 1050 1009 1009 1051 984 984 1025 1009 1009 1051 985 985 1026 985 985 1026 1009 1009 1051 1010 1010 1052 985 985 1026 1010 1010 1052 986 986 1027 986 986 1027 1010 1010 1052 1011 1011 1053 986 986 1027 1011 1011 1053 987 987 1028 987 987 1028 1011 1011 1053 1012 1012 1054 987 987 1028 1012 1012 1054 988 988 1029 988 988 1029 1012 1012 1054 1013 1013 1055 988 988 1029 1013 1013 1055 989 989 1030 989 989 1030 1013 1013 1055 1014 1014 1056 989 989 1030 1014 1014 1056 990 990 1031 990 990 1031 1014 1014 1056 1015 1015 1057 990 990 1031 1015 1015 1057 991 991 1032 991 991 1032 1015 1015 1057 1016 1016 1058 991 991 1032 1016 1016 1058 992 992 1033 992 992 1033 1016 1016 1058 1017 1017 1059 992 992 1033 1017 1017 1059 993 993 1034 993 993 1034 1017 1017 1059 1018 1018 1060 993 993 1034 1018 1018 1060 994 994 1035 994 994 1035 1018 1018 1060 1019 1019 1061 994 994 1035 1019 1019 1061 995 995 1036 995 995 1036 1019 1019 1061 1020 1020 1062 995 995 1036 1020 1020 1062 996 996 1037 996 996 1037 1020 1020 1062 1021 1021 1063 996 996 1037 1021 1021 1063 997 997 1038 997 997 1038 1021 1021 1063 1022 1022 1064 997 997 1038 1022 1022 1064 998 998 1039 998 998 1039 1022 1022 1064 1023 1023 1065 998 998 1039 1023 1023 1065 999 999 1040 999 999 1040 1023 1023 1065 1024 1024 1066 999 999 1040 1024 1024 1066 1000 1000 1041 1000 1000 1041 1024 1024 1066 1025 1025 1067 1000 1000 1041 1025 1025 1067 1001 1001 1042 1001 1001 1042 1025 1025 1067 1026 1026 1068 1001 1001 1042 1026 1026 1068 1002 1002 1043 1002 1002 1043 1026 1026 1068 1027 1027 1069 1002 1002 1043 1027 1027 1069 1003 1003 1044 1003 1003 1044 1027 1027 1069 1028 1028 1070 1003 1003 1044 1028 1028 1070 1004 1004 1045 1004 1004 1045 1028 1028 1070 1029 1029 1071 1004 1004 1045 1029 1029 1071 1005 1005 1046 1005 1005 1046 1029 1029 1071 1030 1030 1072 1005 1005 1046 1030 1030 1072 1006 1006 1047 1006 1006 1047 1030 1030 1072 1031 1031 1073 1006 1006 1047 1031 1031 1073 1007 1007 1048 1007 1007 1048 1031 1031 1073 1008 1008 1074 1007 1007 1048 1008 1008 1074 984 984 1049 1008 1008 1050 1032 1032 1075 1033 1033 1076 1008 1008 1050 1033 1033 1076 1009 1009 1051 1009 1009 1051 1033 1033 1076 1034 1034 1077 1009 1009 1051 1034 1034 1077 1010 1010 1052 1010 1010 1052 1034 1034 1077 1035 1035 1078 1010 1010 1052 1035 1035 1078 1011 1011 1053 1011 1011 1053 1035 1035 1078 1036 1036 1079 1011 1011 1053 1036 1036 1079 1012 1012 1054 1012 1012 1054 1036 1036 1079 1037 1037 1080 1012 1012 1054 1037 1037 1080 1013 1013 1055 1013 1013 1055 1037 1037 1080 1038 1038 1081 1013 1013 1055 1038 1038 1081 1014 1014 1056 1014 1014 1056 1038 1038 1081 1039 1039 1082 1014 1014 1056 1039 1039 1082 1015 1015 1057 1015 1015 1057 1039 1039 1082 1040 1040 1083 1015 1015 1057 1040 1040 1083 1016 1016 1058 1016 1016 1058 1040 1040 1083 1041 1041 1084 1016 1016 1058 1041 1041 1084 1017 1017 1059 1017 1017 1059 1041 1041 1084 1042 1042 1085 1017 1017 1059 1042 1042 1085 1018 1018 1060 1018 1018 1060 1042 1042 1085 1043 1043 1086 1018 1018 1060 1043 1043 1086 1019 1019 1061 1019 1019 1061 1043 1043 1086 1044 1044 1087 1019 1019 1061 1044 1044 1087 1020 1020 1062 1020 1020 1062 1044 1044 1087 1045 1045 1088 1020 1020 1062 1045 1045 1088 1021 1021 1063 1021 1021 1063 1045 1045 1088 1046 1046 1089 1021 1021 1063 1046 1046 1089 1022 1022 1064 1022 1022 1064 1046 1046 1089 1047 1047 1090 1022 1022 1064 1047 1047 1090 1023 1023 1065 1023 1023 1065 1047 1047 1090 1048 1048 1091 1023 1023 1065 1048 1048 1091 1024 1024 1066 1024 1024 1066 1048 1048 1091 1049 1049 1092 1024 1024 1066 1049 1049 1092 1025 1025 1067 1025 1025 1067 1049 1049 1092 1050 1050 1093 1025 1025 1067 1050 1050 1093 1026 1026 1068 1026 1026 1068 1050 1050 1093 1051 1051 1094 1026 1026 1068 1051 1051 1094 1027 1027 1069 1027 1027 1069 1051 1051 1094 1052 1052 1095 1027 1027 1069 1052 1052 1095 1028 1028 1070 1028 1028 1070 1052 1052 1095 1053 1053 1096 1028 1028 1070 1053 1053 1096 1029 1029 1071 1029 1029 1071 1053 1053 1096 1054 1054 1097 1029 1029 1071 1054 1054 1097 1030 1030 1072 1030 1030 1072 1054 1054 1097 1055 1055 1098 1030 1030 1072 1055 1055 1098 1031 1031 1073 1031 1031 1073 1055 1055 1098 1032 1032 1099 1031 1031 1073 1032 1032 1099 1008 1008 1074 1032 1032 1075 1056 1056 1100 1057 1057 1101 1032 1032 1075 1057 1057 1101 1033 1033 1076 1033 1033 1076 1057 1057 1101 1058 1058 1102 1033 1033 1076 1058 1058 1102 1034 1034 1077 1034 1034 1077 1058 1058 1102 1059 1059 1103 1034 1034 1077 1059 1059 1103 1035 1035 1078 1035 1035 1078 1059 1059 1103 1060 1060 1104 1035 1035 1078 1060 1060 1104 1036 1036 1079 1036 1036 1079 1060 1060 1104 1061 1061 1105 1036 1036 1079 1061 1061 1105 1037 1037 1080 1037 1037 1080 1061 1061 1105 1062 1062 1106 1037 1037 1080 1062 1062 1106 1038 1038 1081 1038 1038 1081 1062 1062 1106 1063 1063 1107 1038 1038 1081 1063 1063 1107 1039 1039 1082 1039 1039 1082 1063 1063 1107 1064 1064 1108 1039 1039 1082 1064 1064 1108 1040 1040 1083 1040 1040 1083 1064 1064 1108 1065 1065 1109 1040 1040 1083 1065 1065 1109 1041 1041 1084 1041 1041 1084 1065 1065 1109 1066 1066 1110 1041 1041 1084 1066 1066 1110 1042 1042 1085 1042 1042 1085 1066 1066 1110 1067 1067 1111 1042 1042 1085 1067 1067 1111 1043 1043 1086 1043 1043 1086 1067 1067 1111 1068 1068 1112 1043 1043 1086 1068 1068 1112 1044 1044 1087 1044 1044 1087 1068 1068 1112 1069 1069 1113 1044 1044 1087 1069 1069 1113 1045 1045 1088 1045 1045 1088 1069 1069 1113 1070 1070 1114 1045 1045 1088 1070 1070 1114 1046 1046 1089 1046 1046 1089 1070 1070 1114 1071 1071 1115 1046 1046 1089 1071 1071 1115 1047 1047 1090 1047 1047 1090 1071 1071 1115 1072 1072 1116 1047 1047 1090 1072 1072 1116 1048 1048 1091 1048 1048 1091 1072 1072 1116 1073 1073 1117 1048 1048 1091 1073 1073 1117 1049 1049 1092 1049 1049 1092 1073 1073 1117 1074 1074 1118 1049 1049 1092 1074 1074 1118 1050 1050 1093 1050 1050 1093 1074 1074 1118 1075 1075 1119 1050 1050 1093 1075 1075 1119 1051 1051 1094 1051 1051 1094 1075 1075 1119 1076 1076 1120 1051 1051 1094 1076 1076 1120 1052 1052 1095 1052 1052 1095 1076 1076 1120 1077 1077 1121 1052 1052 1095 1077 1077 1121 1053 1053 1096 1053 1053 1096 1077 1077 1121 1078 1078 1122 1053 1053 1096 1078 1078 1122 1054 1054 1097 1054 1054 1097 1078 1078 1122 1079 1079 1123 1054 1054 1097 1079 1079 1123 1055 1055 1098 1055 1055 1098 1079 1079 1123 1056 1056 1124 1055 1055 1098 1056 1056 1124 1032 1032 1099 1056 1056 1100 1080 1080 1125 1081 1081 1126 1056 1056 1100 1081 1081 1126 1057 1057 1101 1057 1057 1101 1081 1081 1126 1082 1082 1127 1057 1057 1101 1082 1082 1127 1058 1058 1102 1058 1058 1102 1082 1082 1127 1083 1083 1128 1058 1058 1102 1083 1083 1128 1059 1059 1103 1059 1059 1103 1083 1083 1128 1084 1084 1129 1059 1059 1103 1084 1084 1129 1060 1060 1104 1060 1060 1104 1084 1084 1129 1085 1085 1130 1060 1060 1104 1085 1085 1130 1061 1061 1105 1061 1061 1105 1085 1085 1130 1086 1086 1131 1061 1061 1105 1086 1086 1131 1062 1062 1106 1062 1062 1106 1086 1086 1131 1087 1087 1132 1062 1062 1106 1087 1087 1132 1063 1063 1107 1063 1063 1107 1087 1087 1132 1088 1088 1133 1063 1063 1107 1088 1088 1133 1064 1064 1108 1064 1064 1108 1088 1088 1133 1089 1089 1134 1064 1064 1108 1089 1089 1134 1065 1065 1109 1065 1065 1109 1089 1089 1134 1090 1090 1135 1065 1065 1109 1090 1090 1135 1066 1066 1110 1066 1066 1110 1090 1090 1135 1091 1091 1136 1066 1066 1110 1091 1091 1136 1067 1067 1111 1067 1067 1111 1091 1091 1136 1092 1092 1137 1067 1067 1111 1092 1092 1137 1068 1068 1112 1068 1068 1112 1092 1092 1137 1093 1093 1138 1068 1068 1112 1093 1093 1138 1069 1069 1113 1069 1069 1113 1093 1093 1138 1094 1094 1139 1069 1069 1113 1094 1094 1139 1070 1070 1114 1070 1070 1114 1094 1094 1139 1095 1095 1140 1070 1070 1114 1095 1095 1140 1071 1071 1115 1071 1071 1115 1095 1095 1140 1096 1096 1141 1071 1071 1115 1096 1096 1141 1072 1072 1116 1072 1072 1116 1096 1096 1141 1097 1097 1142 1072 1072 1116 1097 1097 1142 1073 1073 1117 1073 1073 1117 1097 1097 1142 1098 1098 1143 1073 1073 1117 1098 1098 1143 1074 1074 1118 1074 1074 1118 1098 1098 1143 1099 1099 1144 1074 1074 1118 1099 1099 1144 1075 1075 1119 1075 1075 1119 1099 1099 1144 1100 1100 1145 1075 1075 1119 1100 1100 1145 1076 1076 1120 1076 1076 1120 1100 1100 1145 1101 1101 1146 1076 1076 1120 1101 1101 1146 1077 1077 1121 1077 1077 1121 1101 1101 1146 1102 1102 1147 1077 1077 1121 1102 1102 1147 1078 1078 1122 1078 1078 1122 1102 1102 1147 1103 1103 1148 1078 1078 1122 1103 1103 1148 1079 1079 1123 1079 1079 1123 1103 1103 1148 1080 1080 1149 1079 1079 1123 1080 1080 1149 1056 1056 1124 1080 1080 1125 1104 1104 1150 1105 1105 1151 1080 1080 1125 1105 1105 1151 1081 1081 1126 1081 1081 1126 1105 1105 1151 1106 1106 1152 1081 1081 1126 1106 1106 1152 1082 1082 1127 1082 1082 1127 1106 1106 1152 1107 1107 1153 1082 1082 1127 1107 1107 1153 1083 1083 1128 1083 1083 1128 1107 1107 1153 1108 1108 1154 1083 1083 1128 1108 1108 1154 1084 1084 1129 1084 1084 1129 1108 1108 1154 1109 1109 1155 1084 1084 1129 1109 1109 1155 1085 1085 1130 1085 1085 1130 1109 1109 1155 1110 1110 1156 1085 1085 1130 1110 1110 1156 1086 1086 1131 1086 1086 1131 1110 1110 1156 1111 1111 1157 1086 1086 1131 1111 1111 1157 1087 1087 1132 1087 1087 1132 1111 1111 1157 1112 1112 1158 1087 1087 1132 1112 1112 1158 1088 1088 1133 1088 1088 1133 1112 1112 1158 1113 1113 1159 1088 1088 1133 1113 1113 1159 1089 1089 1134 1089 1089 1134 1113 1113 1159 1114 1114 1160 1089 1089 1134 1114 1114 1160 1090 1090 1135 1090 1090 1135 1114 1114 1160 1115 1115 1161 1090 1090 1135 1115 1115 1161 1091 1091 1136 1091 1091 1136 1115 1115 1161 1116 1116 1162 1091 1091 1136 1116 1116 1162 1092 1092 1137 1092 1092 1137 1116 1116 1162 1117 1117 1163 1092 1092 1137 1117 1117 1163 1093 1093 1138 1093 1093 1138 1117 1117 1163 1118 1118 1164 1093 1093 1138 1118 1118 1164 1094 1094 1139 1094 1094 1139 1118 1118 1164 1119 1119 1165 1094 1094 1139 1119 1119 1165 1095 1095 1140 1095 1095 1140 1119 1119 1165 1120 1120 1166 1095 1095 1140 1120 1120 1166 1096 1096 1141 1096 1096 1141 1120 1120 1166 1121 1121 1167 1096 1096 1141 1121 1121 1167 1097 1097 1142 1097 1097 1142 1121 1121 1167 1122 1122 1168 1097 1097 1142 1122 1122 1168 1098 1098 1143 1098 1098 1143 1122 1122 1168 1123 1123 1169 1098 1098 1143 1123 1123 1169 1099 1099 1144 1099 1099 1144 1123 1123 1169 1124 1124 1170 1099 1099 1144 1124 1124 1170 1100 1100 1145 1100 1100 1145 1124 1124 1170 1125 1125 1171 1100 1100 1145 1125 1125 1171 1101 1101 1146 1101 1101 1146 1125 1125 1171 1126 1126 1172 1101 1101 1146 1126 1126 1172 1102 1102 1147 1102 1102 1147 1126 1126 1172 1127 1127 1173 1102 1102 1147 1127 1127 1173 1103 1103 1148 1103 1103 1148 1127 1127 1173 1104 1104 1174 1103 1103 1148 1104 1104 1174 1080 1080 1149 1104 1104 1150 1128 1128 1175 1129 1129 1176 1104 1104 1150 1129 1129 1176 1105 1105 1151 1105 1105 1151 1129 1129 1176 1130 1130 1177 1105 1105 1151 1130 1130 1177 1106 1106 1152 1106 1106 1152 1130 1130 1177 1131 1131 1178 1106 1106 1152 1131 1131 1178 1107 1107 1153 1107 1107 1153 1131 1131 1178 1132 1132 1179 1107 1107 1153 1132 1132 1179 1108 1108 1154 1108 1108 1154 1132 1132 1179 1133 1133 1180 1108 1108 1154 1133 1133 1180 1109 1109 1155 1109 1109 1155 1133 1133 1180 1134 1134 1181 1109 1109 1155 1134 1134 1181 1110 1110 1156 1110 1110 1156 1134 1134 1181 1135 1135 1182 1110 1110 1156 1135 1135 1182 1111 1111 1157 1111 1111 1157 1135 1135 1182 1136 1136 1183 1111 1111 1157 1136 1136 1183 1112 1112 1158 1112 1112 1158 1136 1136 1183 1137 1137 1184 1112 1112 1158 1137 1137 1184 1113 1113 1159 1113 1113 1159 1137 1137 1184 1138 1138 1185 1113 1113 1159 1138 1138 1185 1114 1114 1160 1114 1114 1160 1138 1138 1185 1139 1139 1186 1114 1114 1160 1139 1139 1186 1115 1115 1161 1115 1115 1161 1139 1139 1186 1140 1140 1187 1115 1115 1161 1140 1140 1187 1116 1116 1162 1116 1116 1162 1140 1140 1187 1141 1141 1188 1116 1116 1162 1141 1141 1188 1117 1117 1163 1117 1117 1163 1141 1141 1188 1142 1142 1189 1117 1117 1163 1142 1142 1189 1118 1118 1164 1118 1118 1164 1142 1142 1189 1143 1143 1190 1118 1118 1164 1143 1143 1190 1119 1119 1165 1119 1119 1165 1143 1143 1190 1144 1144 1191 1119 1119 1165 1144 1144 1191 1120 1120 1166 1120 1120 1166 1144 1144 1191 1145 1145 1192 1120 1120 1166 1145 1145 1192 1121 1121 1167 1121 1121 1167 1145 1145 1192 1146 1146 1193 1121 1121 1167 1146 1146 1193 1122 1122 1168 1122 1122 1168 1146 1146 1193 1147 1147 1194 1122 1122 1168 1147 1147 1194 1123 1123 1169 1123 1123 1169 1147 1147 1194 1148 1148 1195 1123 1123 1169 1148 1148 1195 1124 1124 1170 1124 1124 1170 1148 1148 1195 1149 1149 1196 1124 1124 1170 1149 1149 1196 1125 1125 1171 1125 1125 1171 1149 1149 1196 1150 1150 1197 1125 1125 1171 1150 1150 1197 1126 1126 1172 1126 1126 1172 1150 1150 1197 1151 1151 1198 1126 1126 1172 1151 1151 1198 1127 1127 1173 1127 1127 1173 1151 1151 1198 1128 1128 1199 1127 1127 1173 1128 1128 1199 1104 1104 1174 1128 1128 1175 1152 1152 1200 1153 1153 1201 1128 1128 1175 1153 1153 1201 1129 1129 1176 1129 1129 1176 1153 1153 1201 1154 1154 1202 1129 1129 1176 1154 1154 1202 1130 1130 1177 1130 1130 1177 1154 1154 1202 1155 1155 1203 1130 1130 1177 1155 1155 1203 1131 1131 1178 1131 1131 1178 1155 1155 1203 1156 1156 1204 1131 1131 1178 1156 1156 1204 1132 1132 1179 1132 1132 1179 1156 1156 1204 1157 1157 1205 1132 1132 1179 1157 1157 1205 1133 1133 1180 1133 1133 1180 1157 1157 1205 1158 1158 1206 1133 1133 1180 1158 1158 1206 1134 1134 1181 1134 1134 1181 1158 1158 1206 1159 1159 1207 1134 1134 1181 1159 1159 1207 1135 1135 1182 1135 1135 1182 1159 1159 1207 1160 1160 1208 1135 1135 1182 1160 1160 1208 1136 1136 1183 1136 1136 1183 1160 1160 1208 1161 1161 1209 1136 1136 1183 1161 1161 1209 1137 1137 1184 1137 1137 1184 1161 1161 1209 1162 1162 1210 1137 1137 1184 1162 1162 1210 1138 1138 1185 1138 1138 1185 1162 1162 1210 1163 1163 1211 1138 1138 1185 1163 1163 1211 1139 1139 1186 1139 1139 1186 1163 1163 1211 1164 1164 1212 1139 1139 1186 1164 1164 1212 1140 1140 1187 1140 1140 1187 1164 1164 1212 1165 1165 1213 1140 1140 1187 1165 1165 1213 1141 1141 1188 1141 1141 1188 1165 1165 1213 1166 1166 1214 1141 1141 1188 1166 1166 1214 1142 1142 1189 1142 1142 1189 1166 1166 1214 1167 1167 1215 1142 1142 1189 1167 1167 1215 1143 1143 1190 1143 1143 1190 1167 1167 1215 1168 1168 1216 1143 1143 1190 1168 1168 1216 1144 1144 1191 1144 1144 1191 1168 1168 1216 1169 1169 1217 1144 1144 1191 1169 1169 1217 1145 1145 1192 1145 1145 1192 1169 1169 1217 1170 1170 1218 1145 1145 1192 1170 1170 1218 1146 1146 1193 1146 1146 1193 1170 1170 1218 1171 1171 1219 1146 1146 1193 1171 1171 1219 1147 1147 1194 1147 1147 1194 1171 1171 1219 1172 1172 1220 1147 1147 1194 1172 1172 1220 1148 1148 1195 1148 1148 1195 1172 1172 1220 1173 1173 1221 1148 1148 1195 1173 1173 1221 1149 1149 1196 1149 1149 1196 1173 1173 1221 1174 1174 1222 1149 1149 1196 1174 1174 1222 1150 1150 1197 1150 1150 1197 1174 1174 1222 1175 1175 1223 1150 1150 1197 1175 1175 1223 1151 1151 1198 1151 1151 1198 1175 1175 1223 1152 1152 1224 1151 1151 1198 1152 1152 1224 1128 1128 1199 1152 1152 1200 1176 1176 1225 1177 1177 1226 1152 1152 1200 1177 1177 1226 1153 1153 1201 1153 1153 1201 1177 1177 1226 1178 1178 1227 1153 1153 1201 1178 1178 1227 1154 1154 1202 1154 1154 1202 1178 1178 1227 1179 1179 1228 1154 1154 1202 1179 1179 1228 1155 1155 1203 1155 1155 1203 1179 1179 1228 1180 1180 1229 1155 1155 1203 1180 1180 1229 1156 1156 1204 1156 1156 1204 1180 1180 1229 1181 1181 1230 1156 1156 1204 1181 1181 1230 1157 1157 1205 1157 1157 1205 1181 1181 1230 1182 1182 1231 1157 1157 1205 1182 1182 1231 1158 1158 1206 1158 1158 1206 1182 1182 1231 1183 1183 1232 1158 1158 1206 1183 1183 1232 1159 1159 1207 1159 1159 1207 1183 1183 1232 1184 1184 1233 1159 1159 1207 1184 1184 1233 1160 1160 1208 1160 1160 1208 1184 1184 1233 1185 1185 1234 1160 1160 1208 1185 1185 1234 1161 1161 1209 1161 1161 1209 1185 1185 1234 1186 1186 1235 1161 1161 1209 1186 1186 1235 1162 1162 1210 1162 1162 1210 1186 1186 1235 1187 1187 1236 1162 1162 1210 1187 1187 1236 1163 1163 1211 1163 1163 1211 1187 1187 1236 1188 1188 1237 1163 1163 1211 1188 1188 1237 1164 1164 1212 1164 1164 1212 1188 1188 1237 1189 1189 1238 1164 1164 1212 1189 1189 1238 1165 1165 1213 1165 1165 1213 1189 1189 1238 1190 1190 1239 1165 1165 1213 1190 1190 1239 1166 1166 1214 1166 1166 1214 1190 1190 1239 1191 1191 1240 1166 1166 1214 1191 1191 1240 1167 1167 1215 1167 1167 1215 1191 1191 1240 1192 1192 1241 1167 1167 1215 1192 1192 1241 1168 1168 1216 1168 1168 1216 1192 1192 1241 1193 1193 1242 1168 1168 1216 1193 1193 1242 1169 1169 1217 1169 1169 1217 1193 1193 1242 1194 1194 1243 1169 1169 1217 1194 1194 1243 1170 1170 1218 1170 1170 1218 1194 1194 1243 1195 1195 1244 1170 1170 1218 1195 1195 1244 1171 1171 1219 1171 1171 1219 1195 1195 1244 1196 1196 1245 1171 1171 1219 1196 1196 1245 1172 1172 1220 1172 1172 1220 1196 1196 1245 1197 1197 1246 1172 1172 1220 1197 1197 1246 1173 1173 1221 1173 1173 1221 1197 1197 1246 1198 1198 1247 1173 1173 1221 1198 1198 1247 1174 1174 1222 1174 1174 1222 1198 1198 1247 1199 1199 1248 1174 1174 1222 1199 1199 1248 1175 1175 1223 1175 1175 1223 1199 1199 1248 1176 1176 1249 1175 1175 1223 1176 1176 1249 1152 1152 1224 1176 1176 1225 1200 1200 1250 1201 1201 1251 1176 1176 1225 1201 1201 1251 1177 1177 1226 1177 1177 1226 1201 1201 1251 1202 1202 1252 1177 1177 1226 1202 1202 1252 1178 1178 1227 1178 1178 1227 1202 1202 1252 1203 1203 1253 1178 1178 1227 1203 1203 1253 1179 1179 1228 1179 1179 1228 1203 1203 1253 1204 1204 1254 1179 1179 1228 1204 1204 1254 1180 1180 1229 1180 1180 1229 1204 1204 1254 1205 1205 1255 1180 1180 1229 1205 1205 1255 1181 1181 1230 1181 1181 1230 1205 1205 1255 1206 1206 1256 1181 1181 1230 1206 1206 1256 1182 1182 1231 1182 1182 1231 1206 1206 1256 1207 1207 1257 1182 1182 1231 1207 1207 1257 1183 1183 1232 1183 1183 1232 1207 1207 1257 1208 1208 1258 1183 1183 1232 1208 1208 1258 1184 1184 1233 1184 1184 1233 1208 1208 1258 1209 1209 1259 1184 1184 1233 1209 1209 1259 1185 1185 1234 1185 1185 1234 1209 1209 1259 1210 1210 1260 1185 1185 1234 1210 1210 1260 1186 1186 1235 1186 1186 1235 1210 1210 1260 1211 1211 1261 1186 1186 1235 1211 1211 1261 1187 1187 1236 1187 1187 1236 1211 1211 1261 1212 1212 1262 1187 1187 1236 1212 1212 1262 1188 1188 1237 1188 1188 1237 1212 1212 1262 1213 1213 1263 1188 1188 1237 1213 1213 1263 1189 1189 1238 1189 1189 1238 1213 1213 1263 1214 1214 1264 1189 1189 1238 1214 1214 1264 1190 1190 1239 1190 1190 1239 1214 1214 1264 1215 1215 1265 1190 1190 1239 1215 1215 1265 1191 1191 1240 1191 1191 1240 1215 1215 1265 1216 1216 1266 1191 1191 1240 1216 1216 1266 1192 1192 1241 1192 1192 1241 1216 1216 1266 1217 1217 1267 1192 1192 1241 1217 1217 1267 1193 1193 1242 1193 1193 1242 1217 1217 1267 1218 1218 1268 1193 1193 1242 1218 1218 1268 1194 1194 1243 1194 1194 1243 1218 1218 1268 1219 1219 1269 1194 1194 1243 1219 1219 1269 1195 1195 1244 1195 1195 1244 1219 1219 1269 1220 1220 1270 1195 1195 1244 1220 1220 1270 1196 1196 1245 1196 1196 1245 1220 1220 1270 1221 1221 1271 1196 1196 1245 1221 1221 1271 1197 1197 1246 1197 1197 1246 1221 1221 1271 1222 1222 1272 1197 1197 1246 1222 1222 1272 1198 1198 1247 1198 1198 1247 1222 1222 1272 1223 1223 1273 1198 1198 1247 1223 1223 1273 1199 1199 1248 1199 1199 1248 1223 1223 1273 1200 1200 1274 1199 1199 1248 1200 1200 1274 1176 1176 1249 1200 1200 1250 1224 1224 1275 1225 1225 1276 1200 1200 1250 1225 1225 1276 1201 1201 1251 1201 1201 1251 1225 1225 1276 1226 1226 1277 1201 1201 1251 1226 1226 1277 1202 1202 1252 1202 1202 1252 1226 1226 1277 1227 1227 1278 1202 1202 1252 1227 1227 1278 1203 1203 1253 1203 1203 1253 1227 1227 1278 1228 1228 1279 1203 1203 1253 1228 1228 1279 1204 1204 1254 1204 1204 1254 1228 1228 1279 1229 1229 1280 1204 1204 1254 1229 1229 1280 1205 1205 1255 1205 1205 1255 1229 1229 1280 1230 1230 1281 1205 1205 1255 1230 1230 1281 1206 1206 1256 1206 1206 1256 1230 1230 1281 1231 1231 1282 1206 1206 1256 1231 1231 1282 1207 1207 1257 1207 1207 1257 1231 1231 1282 1232 1232 1283 1207 1207 1257 1232 1232 1283 1208 1208 1258 1208 1208 1258 1232 1232 1283 1233 1233 1284 1208 1208 1258 1233 1233 1284 1209 1209 1259 1209 1209 1259 1233 1233 1284 1234 1234 1285 1209 1209 1259 1234 1234 1285 1210 1210 1260 1210 1210 1260 1234 1234 1285 1235 1235 1286 1210 1210 1260 1235 1235 1286 1211 1211 1261 1211 1211 1261 1235 1235 1286 1236 1236 1287 1211 1211 1261 1236 1236 1287 1212 1212 1262 1212 1212 1262 1236 1236 1287 1237 1237 1288 1212 1212 1262 1237 1237 1288 1213 1213 1263 1213 1213 1263 1237 1237 1288 1238 1238 1289 1213 1213 1263 1238 1238 1289 1214 1214 1264 1214 1214 1264 1238 1238 1289 1239 1239 1290 1214 1214 1264 1239 1239 1290 1215 1215 1265 1215 1215 1265 1239 1239 1290 1240 1240 1291 1215 1215 1265 1240 1240 1291 1216 1216 1266 1216 1216 1266 1240 1240 1291 1241 1241 1292 1216 1216 1266 1241 1241 1292 1217 1217 1267 1217 1217 1267 1241 1241 1292 1242 1242 1293 1217 1217 1267 1242 1242 1293 1218 1218 1268 1218 1218 1268 1242 1242 1293 1243 1243 1294 1218 1218 1268 1243 1243 1294 1219 1219 1269 1219 1219 1269 1243 1243 1294 1244 1244 1295 1219 1219 1269 1244 1244 1295 1220 1220 1270 1220 1220 1270 1244 1244 1295 1245 1245 1296 1220 1220 1270 1245 1245 1296 1221 1221 1271 1221 1221 1271 1245 1245 1296 1246 1246 1297 1221 1221 1271 1246 1246 1297 1222 1222 1272 1222 1222 1272 1246 1246 1297 1247 1247 1298 1222 1222 1272 1247 1247 1298 1223 1223 1273 1223 1223 1273 1247 1247 1298 1224 1224 1299 1223 1223 1273 1224 1224 1299 1200 1200 1274 1224 1224 1275 1248 1248 1300 1249 1249 1301 1224 1224 1275 1249 1249 1301 1225 1225 1276 1225 1225 1276 1249 1249 1301 1250 1250 1302 1225 1225 1276 1250 1250 1302 1226 1226 1277 1226 1226 1277 1250 1250 1302 1251 1251 1303 1226 1226 1277 1251 1251 1303 1227 1227 1278 1227 1227 1278 1251 1251 1303 1252 1252 1304 1227 1227 1278 1252 1252 1304 1228 1228 1279 1228 1228 1279 1252 1252 1304 1253 1253 1305 1228 1228 1279 1253 1253 1305 1229 1229 1280 1229 1229 1280 1253 1253 1305 1254 1254 1306 1229 1229 1280 1254 1254 1306 1230 1230 1281 1230 1230 1281 1254 1254 1306 1255 1255 1307 1230 1230 1281 1255 1255 1307 1231 1231 1282 1231 1231 1282 1255 1255 1307 1256 1256 1308 1231 1231 1282 1256 1256 1308 1232 1232 1283 1232 1232 1283 1256 1256 1308 1257 1257 1309 1232 1232 1283 1257 1257 1309 1233 1233 1284 1233 1233 1284 1257 1257 1309 1258 1258 1310 1233 1233 1284 1258 1258 1310 1234 1234 1285 1234 1234 1285 1258 1258 1310 1259 1259 1311 1234 1234 1285 1259 1259 1311 1235 1235 1286 1235 1235 1286 1259 1259 1311 1260 1260 1312 1235 1235 1286 1260 1260 1312 1236 1236 1287 1236 1236 1287 1260 1260 1312 1261 1261 1313 1236 1236 1287 1261 1261 1313 1237 1237 1288 1237 1237 1288 1261 1261 1313 1262 1262 1314 1237 1237 1288 1262 1262 1314 1238 1238 1289 1238 1238 1289 1262 1262 1314 1263 1263 1315 1238 1238 1289 1263 1263 1315 1239 1239 1290 1239 1239 1290 1263 1263 1315 1264 1264 1316 1239 1239 1290 1264 1264 1316 1240 1240 1291 1240 1240 1291 1264 1264 1316 1265 1265 1317 1240 1240 1291 1265 1265 1317 1241 1241 1292 1241 1241 1292 1265 1265 1317 1266 1266 1318 1241 1241 1292 1266 1266 1318 1242 1242 1293 1242 1242 1293 1266 1266 1318 1267 1267 1319 1242 1242 1293 1267 1267 1319 1243 1243 1294 1243 1243 1294 1267 1267 1319 1268 1268 1320 1243 1243 1294 1268 1268 1320 1244 1244 1295 1244 1244 1295 1268 1268 1320 1269 1269 1321 1244 1244 1295 1269 1269 1321 1245 1245 1296 1245 1245 1296 1269 1269 1321 1270 1270 1322 1245 1245 1296 1270 1270 1322 1246 1246 1297 1246 1246 1297 1270 1270 1322 1271 1271 1323 1246 1246 1297 1271 1271 1323 1247 1247 1298 1247 1247 1298 1271 1271 1323 1248 1248 1324 1247 1247 1298 1248 1248 1324 1224 1224 1299 1248 1248 1300 1272 1272 1325 1273 1273 1326 1248 1248 1300 1273 1273 1326 1249 1249 1301 1249 1249 1301 1273 1273 1326 1274 1274 1327 1249 1249 1301 1274 1274 1327 1250 1250 1302 1250 1250 1302 1274 1274 1327 1275 1275 1328 1250 1250 1302 1275 1275 1328 1251 1251 1303 1251 1251 1303 1275 1275 1328 1276 1276 1329 1251 1251 1303 1276 1276 1329 1252 1252 1304 1252 1252 1304 1276 1276 1329 1277 1277 1330 1252 1252 1304 1277 1277 1330 1253 1253 1305 1253 1253 1305 1277 1277 1330 1278 1278 1331 1253 1253 1305 1278 1278 1331 1254 1254 1306 1254 1254 1306 1278 1278 1331 1279 1279 1332 1254 1254 1306 1279 1279 1332 1255 1255 1307 1255 1255 1307 1279 1279 1332 1280 1280 1333 1255 1255 1307 1280 1280 1333 1256 1256 1308 1256 1256 1308 1280 1280 1333 1281 1281 1334 1256 1256 1308 1281 1281 1334 1257 1257 1309 1257 1257 1309 1281 1281 1334 1282 1282 1335 1257 1257 1309 1282 1282 1335 1258 1258 1310 1258 1258 1310 1282 1282 1335 1283 1283 1336 1258 1258 1310 1283 1283 1336 1259 1259 1311 1259 1259 1311 1283 1283 1336 1284 1284 1337 1259 1259 1311 1284 1284 1337 1260 1260 1312 1260 1260 1312 1284 1284 1337 1285 1285 1338 1260 1260 1312 1285 1285 1338 1261 1261 1313 1261 1261 1313 1285 1285 1338 1286 1286 1339 1261 1261 1313 1286 1286 1339 1262 1262 1314 1262 1262 1314 1286 1286 1339 1287 1287 1340 1262 1262 1314 1287 1287 1340 1263 1263 1315 1263 1263 1315 1287 1287 1340 1288 1288 1341 1263 1263 1315 1288 1288 1341 1264 1264 1316 1264 1264 1316 1288 1288 1341 1289 1289 1342 1264 1264 1316 1289 1289 1342 1265 1265 1317 1265 1265 1317 1289 1289 1342 1290 1290 1343 1265 1265 1317 1290 1290 1343 1266 1266 1318 1266 1266 1318 1290 1290 1343 1291 1291 1344 1266 1266 1318 1291 1291 1344 1267 1267 1319 1267 1267 1319 1291 1291 1344 1292 1292 1345 1267 1267 1319 1292 1292 1345 1268 1268 1320 1268 1268 1320 1292 1292 1345 1293 1293 1346 1268 1268 1320 1293 1293 1346 1269 1269 1321 1269 1269 1321 1293 1293 1346 1294 1294 1347 1269 1269 1321 1294 1294 1347 1270 1270 1322 1270 1270 1322 1294 1294 1347 1295 1295 1348 1270 1270 1322 1295 1295 1348 1271 1271 1323 1271 1271 1323 1295 1295 1348 1272 1272 1349 1271 1271 1323 1272 1272 1349 1248 1248 1324 1272 1272 1325 1296 1296 1350 1297 1297 1351 1272 1272 1325 1297 1297 1351 1273 1273 1326 1273 1273 1326 1297 1297 1351 1298 1298 1352 1273 1273 1326 1298 1298 1352 1274 1274 1327 1274 1274 1327 1298 1298 1352 1299 1299 1353 1274 1274 1327 1299 1299 1353 1275 1275 1328 1275 1275 1328 1299 1299 1353 1300 1300 1354 1275 1275 1328 1300 1300 1354 1276 1276 1329 1276 1276 1329 1300 1300 1354 1301 1301 1355 1276 1276 1329 1301 1301 1355 1277 1277 1330 1277 1277 1330 1301 1301 1355 1302 1302 1356 1277 1277 1330 1302 1302 1356 1278 1278 1331 1278 1278 1331 1302 1302 1356 1303 1303 1357 1278 1278 1331 1303 1303 1357 1279 1279 1332 1279 1279 1332 1303 1303 1357 1304 1304 1358 1279 1279 1332 1304 1304 1358 1280 1280 1333 1280 1280 1333 1304 1304 1358 1305 1305 1359 1280 1280 1333 1305 1305 1359 1281 1281 1334 1281 1281 1334 1305 1305 1359 1306 1306 1360 1281 1281 1334 1306 1306 1360 1282 1282 1335 1282 1282 1335 1306 1306 1360 1307 1307 1361 1282 1282 1335 1307 1307 1361 1283 1283 1336 1283 1283 1336 1307 1307 1361 1308 1308 1362 1283 1283 1336 1308 1308 1362 1284 1284 1337 1284 1284 1337 1308 1308 1362 1309 1309 1363 1284 1284 1337 1309 1309 1363 1285 1285 1338 1285 1285 1338 1309 1309 1363 1310 1310 1364 1285 1285 1338 1310 1310 1364 1286 1286 1339 1286 1286 1339 1310 1310 1364 1311 1311 1365 1286 1286 1339 1311 1311 1365 1287 1287 1340 1287 1287 1340 1311 1311 1365 1312 1312 1366 1287 1287 1340 1312 1312 1366 1288 1288 1341 1288 1288 1341 1312 1312 1366 1313 1313 1367 1288 1288 1341 1313 1313 1367 1289 1289 1342 1289 1289 1342 1313 1313 1367 1314 1314 1368 1289 1289 1342 1314 1314 1368 1290 1290 1343 1290 1290 1343 1314 1314 1368 1315 1315 1369 1290 1290 1343 1315 1315 1369 1291 1291 1344 1291 1291 1344 1315 1315 1369 1316 1316 1370 1291 1291 1344 1316 1316 1370 1292 1292 1345 1292 1292 1345 1316 1316 1370 1317 1317 1371 1292 1292 1345 1317 1317 1371 1293 1293 1346 1293 1293 1346 1317 1317 1371 1318 1318 1372 1293 1293 1346 1318 1318 1372 1294 1294 1347 1294 1294 1347 1318 1318 1372 1319 1319 1373 1294 1294 1347 1319 1319 1373 1295 1295 1348 1295 1295 1348 1319 1319 1373 1296 1296 1374 1295 1295 1348 1296 1296 1374 1272 1272 1349 1296 1296 1350 1320 1320 1375 1321 1321 1376 1296 1296 1350 1321 1321 1376 1297 1297 1351 1297 1297 1351 1321 1321 1376 1322 1322 1377 1297 1297 1351 1322 1322 1377 1298 1298 1352 1298 1298 1352 1322 1322 1377 1323 1323 1378 1298 1298 1352 1323 1323 1378 1299 1299 1353 1299 1299 1353 1323 1323 1378 1324 1324 1379 1299 1299 1353 1324 1324 1379 1300 1300 1354 1300 1300 1354 1324 1324 1379 1325 1325 1380 1300 1300 1354 1325 1325 1380 1301 1301 1355 1301 1301 1355 1325 1325 1380 1326 1326 1381 1301 1301 1355 1326 1326 1381 1302 1302 1356 1302 1302 1356 1326 1326 1381 1327 1327 1382 1302 1302 1356 1327 1327 1382 1303 1303 1357 1303 1303 1357 1327 1327 1382 1328 1328 1383 1303 1303 1357 1328 1328 1383 1304 1304 1358 1304 1304 1358 1328 1328 1383 1329 1329 1384 1304 1304 1358 1329 1329 1384 1305 1305 1359 1305 1305 1359 1329 1329 1384 1330 1330 1385 1305 1305 1359 1330 1330 1385 1306 1306 1360 1306 1306 1360 1330 1330 1385 1331 1331 1386 1306 1306 1360 1331 1331 1386 1307 1307 1361 1307 1307 1361 1331 1331 1386 1332 1332 1387 1307 1307 1361 1332 1332 1387 1308 1308 1362 1308 1308 1362 1332 1332 1387 1333 1333 1388 1308 1308 1362 1333 1333 1388 1309 1309 1363 1309 1309 1363 1333 1333 1388 1334 1334 1389 1309 1309 1363 1334 1334 1389 1310 1310 1364 1310 1310 1364 1334 1334 1389 1335 1335 1390 1310 1310 1364 1335 1335 1390 1311 1311 1365 1311 1311 1365 1335 1335 1390 1336 1336 1391 1311 1311 1365 1336 1336 1391 1312 1312 1366 1312 1312 1366 1336 1336 1391 1337 1337 1392 1312 1312 1366 1337 1337 1392 1313 1313 1367 1313 1313 1367 1337 1337 1392 1338 1338 1393 1313 1313 1367 1338 1338 1393 1314 1314 1368 1314 1314 1368 1338 1338 1393 1339 1339 1394 1314 1314 1368 1339 1339 1394 1315 1315 1369 1315 1315 1369 1339 1339 1394 1340 1340 1395 1315 1315 1369 1340 1340 1395 1316 1316 1370 1316 1316 1370 1340 1340 1395 1341 1341 1396 1316 1316 1370 1341 1341 1396 1317 1317 1371 1317 1317 1371 1341 1341 1396 1342 1342 1397 1317 1317 1371 1342 1342 1397 1318 1318 1372 1318 1318 1372 1342 1342 1397 1343 1343 1398 1318 1318 1372 1343 1343 1398 1319 1319 1373 1319 1319 1373 1343 1343 1398 1320 1320 1399 1319 1319 1373 1320 1320 1399 1296 1296 1374 1320 1320 1375 1344 1344 1400 1345 1345 1401 1320 1320 1375 1345 1345 1401 1321 1321 1376 1321 1321 1376 1345 1345 1401 1346 1346 1402 1321 1321 1376 1346 1346 1402 1322 1322 1377 1322 1322 1377 1346 1346 1402 1347 1347 1403 1322 1322 1377 1347 1347 1403 1323 1323 1378 1323 1323 1378 1347 1347 1403 1348 1348 1404 1323 1323 1378 1348 1348 1404 1324 1324 1379 1324 1324 1379 1348 1348 1404 1349 1349 1405 1324 1324 1379 1349 1349 1405 1325 1325 1380 1325 1325 1380 1349 1349 1405 1350 1350 1406 1325 1325 1380 1350 1350 1406 1326 1326 1381 1326 1326 1381 1350 1350 1406 1351 1351 1407 1326 1326 1381 1351 1351 1407 1327 1327 1382 1327 1327 1382 1351 1351 1407 1352 1352 1408 1327 1327 1382 1352 1352 1408 1328 1328 1383 1328 1328 1383 1352 1352 1408 1353 1353 1409 1328 1328 1383 1353 1353 1409 1329 1329 1384 1329 1329 1384 1353 1353 1409 1354 1354 1410 1329 1329 1384 1354 1354 1410 1330 1330 1385 1330 1330 1385 1354 1354 1410 1355 1355 1411 1330 1330 1385 1355 1355 1411 1331 1331 1386 1331 1331 1386 1355 1355 1411 1356 1356 1412 1331 1331 1386 1356 1356 1412 1332 1332 1387 1332 1332 1387 1356 1356 1412 1357 1357 1413 1332 1332 1387 1357 1357 1413 1333 1333 1388 1333 1333 1388 1357 1357 1413 1358 1358 1414 1333 1333 1388 1358 1358 1414 1334 1334 1389 1334 1334 1389 1358 1358 1414 1359 1359 1415 1334 1334 1389 1359 1359 1415 1335 1335 1390 1335 1335 1390 1359 1359 1415 1360 1360 1416 1335 1335 1390 1360 1360 1416 1336 1336 1391 1336 1336 1391 1360 1360 1416 1361 1361 1417 1336 1336 1391 1361 1361 1417 1337 1337 1392 1337 1337 1392 1361 1361 1417 1362 1362 1418 1337 1337 1392 1362 1362 1418 1338 1338 1393 1338 1338 1393 1362 1362 1418 1363 1363 1419 1338 1338 1393 1363 1363 1419 1339 1339 1394 1339 1339 1394 1363 1363 1419 1364 1364 1420 1339 1339 1394 1364 1364 1420 1340 1340 1395 1340 1340 1395 1364 1364 1420 1365 1365 1421 1340 1340 1395 1365 1365 1421 1341 1341 1396 1341 1341 1396 1365 1365 1421 1366 1366 1422 1341 1341 1396 1366 1366 1422 1342 1342 1397 1342 1342 1397 1366 1366 1422 1367 1367 1423 1342 1342 1397 1367 1367 1423 1343 1343 1398 1343 1343 1398 1367 1367 1423 1344 1344 1424 1343 1343 1398 1344 1344 1424 1320 1320 1399 1344 1344 1400 1368 1368 1425 1369 1369 1426 1344 1344 1400 1369 1369 1426 1345 1345 1401 1345 1345 1401 1369 1369 1426 1370 1370 1427 1345 1345 1401 1370 1370 1427 1346 1346 1402 1346 1346 1402 1370 1370 1427 1371 1371 1428 1346 1346 1402 1371 1371 1428 1347 1347 1403 1347 1347 1403 1371 1371 1428 1372 1372 1429 1347 1347 1403 1372 1372 1429 1348 1348 1404 1348 1348 1404 1372 1372 1429 1373 1373 1430 1348 1348 1404 1373 1373 1430 1349 1349 1405 1349 1349 1405 1373 1373 1430 1374 1374 1431 1349 1349 1405 1374 1374 1431 1350 1350 1406 1350 1350 1406 1374 1374 1431 1375 1375 1432 1350 1350 1406 1375 1375 1432 1351 1351 1407 1351 1351 1407 1375 1375 1432 1376 1376 1433 1351 1351 1407 1376 1376 1433 1352 1352 1408 1352 1352 1408 1376 1376 1433 1377 1377 1434 1352 1352 1408 1377 1377 1434 1353 1353 1409 1353 1353 1409 1377 1377 1434 1378 1378 1435 1353 1353 1409 1378 1378 1435 1354 1354 1410 1354 1354 1410 1378 1378 1435 1379 1379 1436 1354 1354 1410 1379 1379 1436 1355 1355 1411 1355 1355 1411 1379 1379 1436 1380 1380 1437 1355 1355 1411 1380 1380 1437 1356 1356 1412 1356 1356 1412 1380 1380 1437 1381 1381 1438 1356 1356 1412 1381 1381 1438 1357 1357 1413 1357 1357 1413 1381 1381 1438 1382 1382 1439 1357 1357 1413 1382 1382 1439 1358 1358 1414 1358 1358 1414 1382 1382 1439 1383 1383 1440 1358 1358 1414 1383 1383 1440 1359 1359 1415 1359 1359 1415 1383 1383 1440 1384 1384 1441 1359 1359 1415 1384 1384 1441 1360 1360 1416 1360 1360 1416 1384 1384 1441 1385 1385 1442 1360 1360 1416 1385 1385 1442 1361 1361 1417 1361 1361 1417 1385 1385 1442 1386 1386 1443 1361 1361 1417 1386 1386 1443 1362 1362 1418 1362 1362 1418 1386 1386 1443 1387 1387 1444 1362 1362 1418 1387 1387 1444 1363 1363 1419 1363 1363 1419 1387 1387 1444 1388 1388 1445 1363 1363 1419 1388 1388 1445 1364 1364 1420 1364 1364 1420 1388 1388 1445 1389 1389 1446 1364 1364 1420 1389 1389 1446 1365 1365 1421 1365 1365 1421 1389 1389 1446 1390 1390 1447 1365 1365 1421 1390 1390 1447 1366 1366 1422 1366 1366 1422 1390 1390 1447 1391 1391 1448 1366 1366 1422 1391 1391 1448 1367 1367 1423 1367 1367 1423 1391 1391 1448 1368 1368 1449 1367 1367 1423 1368 1368 1449 1344 1344 1424 1368 1368 1425 1392 1392 1450 1393 1393 1451 1368 1368 1425 1393 1393 1451 1369 1369 1426 1369 1369 1426 1393 1393 1451 1394 1394 1452 1369 1369 1426 1394 1394 1452 1370 1370 1427 1370 1370 1427 1394 1394 1452 1395 1395 1453 1370 1370 1427 1395 1395 1453 1371 1371 1428 1371 1371 1428 1395 1395 1453 1396 1396 1454 1371 1371 1428 1396 1396 1454 1372 1372 1429 1372 1372 1429 1396 1396 1454 1397 1397 1455 1372 1372 1429 1397 1397 1455 1373 1373 1430 1373 1373 1430 1397 1397 1455 1398 1398 1456 1373 1373 1430 1398 1398 1456 1374 1374 1431 1374 1374 1431 1398 1398 1456 1399 1399 1457 1374 1374 1431 1399 1399 1457 1375 1375 1432 1375 1375 1432 1399 1399 1457 1400 1400 1458 1375 1375 1432 1400 1400 1458 1376 1376 1433 1376 1376 1433 1400 1400 1458 1401 1401 1459 1376 1376 1433 1401 1401 1459 1377 1377 1434 1377 1377 1434 1401 1401 1459 1402 1402 1460 1377 1377 1434 1402 1402 1460 1378 1378 1435 1378 1378 1435 1402 1402 1460 1403 1403 1461 1378 1378 1435 1403 1403 1461 1379 1379 1436 1379 1379 1436 1403 1403 1461 1404 1404 1462 1379 1379 1436 1404 1404 1462 1380 1380 1437 1380 1380 1437 1404 1404 1462 1405 1405 1463 1380 1380 1437 1405 1405 1463 1381 1381 1438 1381 1381 1438 1405 1405 1463 1406 1406 1464 1381 1381 1438 1406 1406 1464 1382 1382 1439 1382 1382 1439 1406 1406 1464 1407 1407 1465 1382 1382 1439 1407 1407 1465 1383 1383 1440 1383 1383 1440 1407 1407 1465 1408 1408 1466 1383 1383 1440 1408 1408 1466 1384 1384 1441 1384 1384 1441 1408 1408 1466 1409 1409 1467 1384 1384 1441 1409 1409 1467 1385 1385 1442 1385 1385 1442 1409 1409 1467 1410 1410 1468 1385 1385 1442 1410 1410 1468 1386 1386 1443 1386 1386 1443 1410 1410 1468 1411 1411 1469 1386 1386 1443 1411 1411 1469 1387 1387 1444 1387 1387 1444 1411 1411 1469 1412 1412 1470 1387 1387 1444 1412 1412 1470 1388 1388 1445 1388 1388 1445 1412 1412 1470 1413 1413 1471 1388 1388 1445 1413 1413 1471 1389 1389 1446 1389 1389 1446 1413 1413 1471 1414 1414 1472 1389 1389 1446 1414 1414 1472 1390 1390 1447 1390 1390 1447 1414 1414 1472 1415 1415 1473 1390 1390 1447 1415 1415 1473 1391 1391 1448 1391 1391 1448 1415 1415 1473 1392 1392 1474 1391 1391 1448 1392 1392 1474 1368 1368 1449 1392 1392 1450 1416 1416 1475 1417 1417 1476 1392 1392 1450 1417 1417 1476 1393 1393 1451 1393 1393 1451 1417 1417 1476 1418 1418 1477 1393 1393 1451 1418 1418 1477 1394 1394 1452 1394 1394 1452 1418 1418 1477 1419 1419 1478 1394 1394 1452 1419 1419 1478 1395 1395 1453 1395 1395 1453 1419 1419 1478 1420 1420 1479 1395 1395 1453 1420 1420 1479 1396 1396 1454 1396 1396 1454 1420 1420 1479 1421 1421 1480 1396 1396 1454 1421 1421 1480 1397 1397 1455 1397 1397 1455 1421 1421 1480 1422 1422 1481 1397 1397 1455 1422 1422 1481 1398 1398 1456 1398 1398 1456 1422 1422 1481 1423 1423 1482 1398 1398 1456 1423 1423 1482 1399 1399 1457 1399 1399 1457 1423 1423 1482 1424 1424 1483 1399 1399 1457 1424 1424 1483 1400 1400 1458 1400 1400 1458 1424 1424 1483 1425 1425 1484 1400 1400 1458 1425 1425 1484 1401 1401 1459 1401 1401 1459 1425 1425 1484 1426 1426 1485 1401 1401 1459 1426 1426 1485 1402 1402 1460 1402 1402 1460 1426 1426 1485 1427 1427 1486 1402 1402 1460 1427 1427 1486 1403 1403 1461 1403 1403 1461 1427 1427 1486 1428 1428 1487 1403 1403 1461 1428 1428 1487 1404 1404 1462 1404 1404 1462 1428 1428 1487 1429 1429 1488 1404 1404 1462 1429 1429 1488 1405 1405 1463 1405 1405 1463 1429 1429 1488 1430 1430 1489 1405 1405 1463 1430 1430 1489 1406 1406 1464 1406 1406 1464 1430 1430 1489 1431 1431 1490 1406 1406 1464 1431 1431 1490 1407 1407 1465 1407 1407 1465 1431 1431 1490 1432 1432 1491 1407 1407 1465 1432 1432 1491 1408 1408 1466 1408 1408 1466 1432 1432 1491 1433 1433 1492 1408 1408 1466 1433 1433 1492 1409 1409 1467 1409 1409 1467 1433 1433 1492 1434 1434 1493 1409 1409 1467 1434 1434 1493 1410 1410 1468 1410 1410 1468 1434 1434 1493 1435 1435 1494 1410 1410 1468 1435 1435 1494 1411 1411 1469 1411 1411 1469 1435 1435 1494 1436 1436 1495 1411 1411 1469 1436 1436 1495 1412 1412 1470 1412 1412 1470 1436 1436 1495 1437 1437 1496 1412 1412 1470 1437 1437 1496 1413 1413 1471 1413 1413 1471 1437 1437 1496 1438 1438 1497 1413 1413 1471 1438 1438 1497 1414 1414 1472 1414 1414 1472 1438 1438 1497 1439 1439 1498 1414 1414 1472 1439 1439 1498 1415 1415 1473 1415 1415 1473 1439 1439 1498 1416 1416 1499 1415 1415 1473 1416 1416 1499 1392 1392 1474 1416 1416 1475 1440 1440 1500 1441 1441 1501 1416 1416 1475 1441 1441 1501 1417 1417 1476 1417 1417 1476 1441 1441 1501 1442 1442 1502 1417 1417 1476 1442 1442 1502 1418 1418 1477 1418 1418 1477 1442 1442 1502 1443 1443 1503 1418 1418 1477 1443 1443 1503 1419 1419 1478 1419 1419 1478 1443 1443 1503 1444 1444 1504 1419 1419 1478 1444 1444 1504 1420 1420 1479 1420 1420 1479 1444 1444 1504 1445 1445 1505 1420 1420 1479 1445 1445 1505 1421 1421 1480 1421 1421 1480 1445 1445 1505 1446 1446 1506 1421 1421 1480 1446 1446 1506 1422 1422 1481 1422 1422 1481 1446 1446 1506 1447 1447 1507 1422 1422 1481 1447 1447 1507 1423 1423 1482 1423 1423 1482 1447 1447 1507 1448 1448 1508 1423 1423 1482 1448 1448 1508 1424 1424 1483 1424 1424 1483 1448 1448 1508 1449 1449 1509 1424 1424 1483 1449 1449 1509 1425 1425 1484 1425 1425 1484 1449 1449 1509 1450 1450 1510 1425 1425 1484 1450 1450 1510 1426 1426 1485 1426 1426 1485 1450 1450 1510 1451 1451 1511 1426 1426 1485 1451 1451 1511 1427 1427 1486 1427 1427 1486 1451 1451 1511 1452 1452 1512 1427 1427 1486 1452 1452 1512 1428 1428 1487 1428 1428 1487 1452 1452 1512 1453 1453 1513 1428 1428 1487 1453 1453 1513 1429 1429 1488 1429 1429 1488 1453 1453 1513 1454 1454 1514 1429 1429 1488 1454 1454 1514 1430 1430 1489 1430 1430 1489 1454 1454 1514 1455 1455 1515 1430 1430 1489 1455 1455 1515 1431 1431 1490 1431 1431 1490 1455 1455 1515 1456 1456 1516 1431 1431 1490 1456 1456 1516 1432 1432 1491 1432 1432 1491 1456 1456 1516 1457 1457 1517 1432 1432 1491 1457 1457 1517 1433 1433 1492 1433 1433 1492 1457 1457 1517 1458 1458 1518 1433 1433 1492 1458 1458 1518 1434 1434 1493 1434 1434 1493 1458 1458 1518 1459 1459 1519 1434 1434 1493 1459 1459 1519 1435 1435 1494 1435 1435 1494 1459 1459 1519 1460 1460 1520 1435 1435 1494 1460 1460 1520 1436 1436 1495 1436 1436 1495 1460 1460 1520 1461 1461 1521 1436 1436 1495 1461 1461 1521 1437 1437 1496 1437 1437 1496 1461 1461 1521 1462 1462 1522 1437 1437 1496 1462 1462 1522 1438 1438 1497 1438 1438 1497 1462 1462 1522 1463 1463 1523 1438 1438 1497 1463 1463 1523 1439 1439 1498 1439 1439 1498 1463 1463 1523 1440 1440 1524 1439 1439 1498 1440 1440 1524 1416 1416 1499 1440 1440 1500 1464 1464 1525 1465 1465 1526 1440 1440 1500 1465 1465 1526 1441 1441 1501 1441 1441 1501 1465 1465 1526 1466 1466 1527 1441 1441 1501 1466 1466 1527 1442 1442 1502 1442 1442 1502 1466 1466 1527 1467 1467 1528 1442 1442 1502 1467 1467 1528 1443 1443 1503 1443 1443 1503 1467 1467 1528 1468 1468 1529 1443 1443 1503 1468 1468 1529 1444 1444 1504 1444 1444 1504 1468 1468 1529 1469 1469 1530 1444 1444 1504 1469 1469 1530 1445 1445 1505 1445 1445 1505 1469 1469 1530 1470 1470 1531 1445 1445 1505 1470 1470 1531 1446 1446 1506 1446 1446 1506 1470 1470 1531 1471 1471 1532 1446 1446 1506 1471 1471 1532 1447 1447 1507 1447 1447 1507 1471 1471 1532 1472 1472 1533 1447 1447 1507 1472 1472 1533 1448 1448 1508 1448 1448 1508 1472 1472 1533 1473 1473 1534 1448 1448 1508 1473 1473 1534 1449 1449 1509 1449 1449 1509 1473 1473 1534 1474 1474 1535 1449 1449 1509 1474 1474 1535 1450 1450 1510 1450 1450 1510 1474 1474 1535 1475 1475 1536 1450 1450 1510 1475 1475 1536 1451 1451 1511 1451 1451 1511 1475 1475 1536 1476 1476 1537 1451 1451 1511 1476 1476 1537 1452 1452 1512 1452 1452 1512 1476 1476 1537 1477 1477 1538 1452 1452 1512 1477 1477 1538 1453 1453 1513 1453 1453 1513 1477 1477 1538 1478 1478 1539 1453 1453 1513 1478 1478 1539 1454 1454 1514 1454 1454 1514 1478 1478 1539 1479 1479 1540 1454 1454 1514 1479 1479 1540 1455 1455 1515 1455 1455 1515 1479 1479 1540 1480 1480 1541 1455 1455 1515 1480 1480 1541 1456 1456 1516 1456 1456 1516 1480 1480 1541 1481 1481 1542 1456 1456 1516 1481 1481 1542 1457 1457 1517 1457 1457 1517 1481 1481 1542 1482 1482 1543 1457 1457 1517 1482 1482 1543 1458 1458 1518 1458 1458 1518 1482 1482 1543 1483 1483 1544 1458 1458 1518 1483 1483 1544 1459 1459 1519 1459 1459 1519 1483 1483 1544 1484 1484 1545 1459 1459 1519 1484 1484 1545 1460 1460 1520 1460 1460 1520 1484 1484 1545 1485 1485 1546 1460 1460 1520 1485 1485 1546 1461 1461 1521 1461 1461 1521 1485 1485 1546 1486 1486 1547 1461 1461 1521 1486 1486 1547 1462 1462 1522 1462 1462 1522 1486 1486 1547 1487 1487 1548 1462 1462 1522 1487 1487 1548 1463 1463 1523 1463 1463 1523 1487 1487 1548 1464 1464 1549 1463 1463 1523 1464 1464 1549 1440 1440 1524 1464 1464 1525 1488 1488 1550 1489 1489 1551 1464 1464 1525 1489 1489 1551 1465 1465 1526 1465 1465 1526 1489 1489 1551 1490 1490 1552 1465 1465 1526 1490 1490 1552 1466 1466 1527 1466 1466 1527 1490 1490 1552 1491 1491 1553 1466 1466 1527 1491 1491 1553 1467 1467 1528 1467 1467 1528 1491 1491 1553 1492 1492 1554 1467 1467 1528 1492 1492 1554 1468 1468 1529 1468 1468 1529 1492 1492 1554 1493 1493 1555 1468 1468 1529 1493 1493 1555 1469 1469 1530 1469 1469 1530 1493 1493 1555 1494 1494 1556 1469 1469 1530 1494 1494 1556 1470 1470 1531 1470 1470 1531 1494 1494 1556 1495 1495 1557 1470 1470 1531 1495 1495 1557 1471 1471 1532 1471 1471 1532 1495 1495 1557 1496 1496 1558 1471 1471 1532 1496 1496 1558 1472 1472 1533 1472 1472 1533 1496 1496 1558 1497 1497 1559 1472 1472 1533 1497 1497 1559 1473 1473 1534 1473 1473 1534 1497 1497 1559 1498 1498 1560 1473 1473 1534 1498 1498 1560 1474 1474 1535 1474 1474 1535 1498 1498 1560 1499 1499 1561 1474 1474 1535 1499 1499 1561 1475 1475 1536 1475 1475 1536 1499 1499 1561 1500 1500 1562 1475 1475 1536 1500 1500 1562 1476 1476 1537 1476 1476 1537 1500 1500 1562 1501 1501 1563 1476 1476 1537 1501 1501 1563 1477 1477 1538 1477 1477 1538 1501 1501 1563 1502 1502 1564 1477 1477 1538 1502 1502 1564 1478 1478 1539 1478 1478 1539 1502 1502 1564 1503 1503 1565 1478 1478 1539 1503 1503 1565 1479 1479 1540 1479 1479 1540 1503 1503 1565 1504 1504 1566 1479 1479 1540 1504 1504 1566 1480 1480 1541 1480 1480 1541 1504 1504 1566 1505 1505 1567 1480 1480 1541 1505 1505 1567 1481 1481 1542 1481 1481 1542 1505 1505 1567 1506 1506 1568 1481 1481 1542 1506 1506 1568 1482 1482 1543 1482 1482 1543 1506 1506 1568 1507 1507 1569 1482 1482 1543 1507 1507 1569 1483 1483 1544 1483 1483 1544 1507 1507 1569 1508 1508 1570 1483 1483 1544 1508 1508 1570 1484 1484 1545 1484 1484 1545 1508 1508 1570 1509 1509 1571 1484 1484 1545 1509 1509 1571 1485 1485 1546 1485 1485 1546 1509 1509 1571 1510 1510 1572 1485 1485 1546 1510 1510 1572 1486 1486 1547 1486 1486 1547 1510 1510 1572 1511 1511 1573 1486 1486 1547 1511 1511 1573 1487 1487 1548 1487 1487 1548 1511 1511 1573 1488 1488 1574 1487 1487 1548 1488 1488 1574 1464 1464 1549 1488 1488 1550 1512 1512 1575 1513 1513 1576 1488 1488 1550 1513 1513 1576 1489 1489 1551 1489 1489 1551 1513 1513 1576 1514 1514 1577 1489 1489 1551 1514 1514 1577 1490 1490 1552 1490 1490 1552 1514 1514 1577 1515 1515 1578 1490 1490 1552 1515 1515 1578 1491 1491 1553 1491 1491 1553 1515 1515 1578 1516 1516 1579 1491 1491 1553 1516 1516 1579 1492 1492 1554 1492 1492 1554 1516 1516 1579 1517 1517 1580 1492 1492 1554 1517 1517 1580 1493 1493 1555 1493 1493 1555 1517 1517 1580 1518 1518 1581 1493 1493 1555 1518 1518 1581 1494 1494 1556 1494 1494 1556 1518 1518 1581 1519 1519 1582 1494 1494 1556 1519 1519 1582 1495 1495 1557 1495 1495 1557 1519 1519 1582 1520 1520 1583 1495 1495 1557 1520 1520 1583 1496 1496 1558 1496 1496 1558 1520 1520 1583 1521 1521 1584 1496 1496 1558 1521 1521 1584 1497 1497 1559 1497 1497 1559 1521 1521 1584 1522 1522 1585 1497 1497 1559 1522 1522 1585 1498 1498 1560 1498 1498 1560 1522 1522 1585 1523 1523 1586 1498 1498 1560 1523 1523 1586 1499 1499 1561 1499 1499 1561 1523 1523 1586 1524 1524 1587 1499 1499 1561 1524 1524 1587 1500 1500 1562 1500 1500 1562 1524 1524 1587 1525 1525 1588 1500 1500 1562 1525 1525 1588 1501 1501 1563 1501 1501 1563 1525 1525 1588 1526 1526 1589 1501 1501 1563 1526 1526 1589 1502 1502 1564 1502 1502 1564 1526 1526 1589 1527 1527 1590 1502 1502 1564 1527 1527 1590 1503 1503 1565 1503 1503 1565 1527 1527 1590 1528 1528 1591 1503 1503 1565 1528 1528 1591 1504 1504 1566 1504 1504 1566 1528 1528 1591 1529 1529 1592 1504 1504 1566 1529 1529 1592 1505 1505 1567 1505 1505 1567 1529 1529 1592 1530 1530 1593 1505 1505 1567 1530 1530 1593 1506 1506 1568 1506 1506 1568 1530 1530 1593 1531 1531 1594 1506 1506 1568 1531 1531 1594 1507 1507 1569 1507 1507 1569 1531 1531 1594 1532 1532 1595 1507 1507 1569 1532 1532 1595 1508 1508 1570 1508 1508 1570 1532 1532 1595 1533 1533 1596 1508 1508 1570 1533 1533 1596 1509 1509 1571 1509 1509 1571 1533 1533 1596 1534 1534 1597 1509 1509 1571 1534 1534 1597 1510 1510 1572 1510 1510 1572 1534 1534 1597 1535 1535 1598 1510 1510 1572 1535 1535 1598 1511 1511 1573 1511 1511 1573 1535 1535 1598 1512 1512 1599 1511 1511 1573 1512 1512 1599 1488 1488 1574 1512 1512 1575 1536 1536 1600 1537 1537 1601 1512 1512 1575 1537 1537 1601 1513 1513 1576 1513 1513 1576 1537 1537 1601 1538 1538 1602 1513 1513 1576 1538 1538 1602 1514 1514 1577 1514 1514 1577 1538 1538 1602 1539 1539 1603 1514 1514 1577 1539 1539 1603 1515 1515 1578 1515 1515 1578 1539 1539 1603 1540 1540 1604 1515 1515 1578 1540 1540 1604 1516 1516 1579 1516 1516 1579 1540 1540 1604 1541 1541 1605 1516 1516 1579 1541 1541 1605 1517 1517 1580 1517 1517 1580 1541 1541 1605 1542 1542 1606 1517 1517 1580 1542 1542 1606 1518 1518 1581 1518 1518 1581 1542 1542 1606 1543 1543 1607 1518 1518 1581 1543 1543 1607 1519 1519 1582 1519 1519 1582 1543 1543 1607 1544 1544 1608 1519 1519 1582 1544 1544 1608 1520 1520 1583 1520 1520 1583 1544 1544 1608 1545 1545 1609 1520 1520 1583 1545 1545 1609 1521 1521 1584 1521 1521 1584 1545 1545 1609 1546 1546 1610 1521 1521 1584 1546 1546 1610 1522 1522 1585 1522 1522 1585 1546 1546 1610 1547 1547 1611 1522 1522 1585 1547 1547 1611 1523 1523 1586 1523 1523 1586 1547 1547 1611 1548 1548 1612 1523 1523 1586 1548 1548 1612 1524 1524 1587 1524 1524 1587 1548 1548 1612 1549 1549 1613 1524 1524 1587 1549 1549 1613 1525 1525 1588 1525 1525 1588 1549 1549 1613 1550 1550 1614 1525 1525 1588 1550 1550 1614 1526 1526 1589 1526 1526 1589 1550 1550 1614 1551 1551 1615 1526 1526 1589 1551 1551 1615 1527 1527 1590 1527 1527 1590 1551 1551 1615 1552 1552 1616 1527 1527 1590 1552 1552 1616 1528 1528 1591 1528 1528 1591 1552 1552 1616 1553 1553 1617 1528 1528 1591 1553 1553 1617 1529 1529 1592 1529 1529 1592 1553 1553 1617 1554 1554 1618 1529 1529 1592 1554 1554 1618 1530 1530 1593 1530 1530 1593 1554 1554 1618 1555 1555 1619 1530 1530 1593 1555 1555 1619 1531 1531 1594 1531 1531 1594 1555 1555 1619 1556 1556 1620 1531 1531 1594 1556 1556 1620 1532 1532 1595 1532 1532 1595 1556 1556 1620 1557 1557 1621 1532 1532 1595 1557 1557 1621 1533 1533 1596 1533 1533 1596 1557 1557 1621 1558 1558 1622 1533 1533 1596 1558 1558 1622 1534 1534 1597 1534 1534 1597 1558 1558 1622 1559 1559 1623 1534 1534 1597 1559 1559 1623 1535 1535 1598 1535 1535 1598 1559 1559 1623 1536 1536 1624 1535 1535 1598 1536 1536 1624 1512 1512 1599 1536 1536 1600 1560 1560 1625 1561 1561 1626 1536 1536 1600 1561 1561 1626 1537 1537 1601 1537 1537 1601 1561 1561 1626 1562 1562 1627 1537 1537 1601 1562 1562 1627 1538 1538 1602 1538 1538 1602 1562 1562 1627 1563 1563 1628 1538 1538 1602 1563 1563 1628 1539 1539 1603 1539 1539 1603 1563 1563 1628 1564 1564 1629 1539 1539 1603 1564 1564 1629 1540 1540 1604 1540 1540 1604 1564 1564 1629 1565 1565 1630 1540 1540 1604 1565 1565 1630 1541 1541 1605 1541 1541 1605 1565 1565 1630 1566 1566 1631 1541 1541 1605 1566 1566 1631 1542 1542 1606 1542 1542 1606 1566 1566 1631 1567 1567 1632 1542 1542 1606 1567 1567 1632 1543 1543 1607 1543 1543 1607 1567 1567 1632 1568 1568 1633 1543 1543 1607 1568 1568 1633 1544 1544 1608 1544 1544 1608 1568 1568 1633 1569 1569 1634 1544 1544 1608 1569 1569 1634 1545 1545 1609 1545 1545 1609 1569 1569 1634 1570 1570 1635 1545 1545 1609 1570 1570 1635 1546 1546 1610 1546 1546 1610 1570 1570 1635 1571 1571 1636 1546 1546 1610 1571 1571 1636 1547 1547 1611 1547 1547 1611 1571 1571 1636 1572 1572 1637 1547 1547 1611 1572 1572 1637 1548 1548 1612 1548 1548 1612 1572 1572 1637 1573 1573 1638 1548 1548 1612 1573 1573 1638 1549 1549 1613 1549 1549 1613 1573 1573 1638 1574 1574 1639 1549 1549 1613 1574 1574 1639 1550 1550 1614 1550 1550 1614 1574 1574 1639 1575 1575 1640 1550 1550 1614 1575 1575 1640 1551 1551 1615 1551 1551 1615 1575 1575 1640 1576 1576 1641 1551 1551 1615 1576 1576 1641 1552 1552 1616 1552 1552 1616 1576 1576 1641 1577 1577 1642 1552 1552 1616 1577 1577 1642 1553 1553 1617 1553 1553 1617 1577 1577 1642 1578 1578 1643 1553 1553 1617 1578 1578 1643 1554 1554 1618 1554 1554 1618 1578 1578 1643 1579 1579 1644 1554 1554 1618 1579 1579 1644 1555 1555 1619 1555 1555 1619 1579 1579 1644 1580 1580 1645 1555 1555 1619 1580 1580 1645 1556 1556 1620 1556 1556 1620 1580 1580 1645 1581 1581 1646 1556 1556 1620 1581 1581 1646 1557 1557 1621 1557 1557 1621 1581 1581 1646 1582 1582 1647 1557 1557 1621 1582 1582 1647 1558 1558 1622 1558 1558 1622 1582 1582 1647 1583 1583 1648 1558 1558 1622 1583 1583 1648 1559 1559 1623 1559 1559 1623 1583 1583 1648 1560 1560 1649 1559 1559 1623 1560 1560 1649 1536 1536 1624 1560 1560 1625 1584 1584 1650 1585 1585 1651 1560 1560 1625 1585 1585 1651 1561 1561 1626 1561 1561 1626 1585 1585 1651 1586 1586 1652 1561 1561 1626 1586 1586 1652 1562 1562 1627 1562 1562 1627 1586 1586 1652 1587 1587 1653 1562 1562 1627 1587 1587 1653 1563 1563 1628 1563 1563 1628 1587 1587 1653 1588 1588 1654 1563 1563 1628 1588 1588 1654 1564 1564 1629 1564 1564 1629 1588 1588 1654 1589 1589 1655 1564 1564 1629 1589 1589 1655 1565 1565 1630 1565 1565 1630 1589 1589 1655 1590 1590 1656 1565 1565 1630 1590 1590 1656 1566 1566 1631 1566 1566 1631 1590 1590 1656 1591 1591 1657 1566 1566 1631 1591 1591 1657 1567 1567 1632 1567 1567 1632 1591 1591 1657 1592 1592 1658 1567 1567 1632 1592 1592 1658 1568 1568 1633 1568 1568 1633 1592 1592 1658 1593 1593 1659 1568 1568 1633 1593 1593 1659 1569 1569 1634 1569 1569 1634 1593 1593 1659 1594 1594 1660 1569 1569 1634 1594 1594 1660 1570 1570 1635 1570 1570 1635 1594 1594 1660 1595 1595 1661 1570 1570 1635 1595 1595 1661 1571 1571 1636 1571 1571 1636 1595 1595 1661 1596 1596 1662 1571 1571 1636 1596 1596 1662 1572 1572 1637 1572 1572 1637 1596 1596 1662 1597 1597 1663 1572 1572 1637 1597 1597 1663 1573 1573 1638 1573 1573 1638 1597 1597 1663 1598 1598 1664 1573 1573 1638 1598 1598 1664 1574 1574 1639 1574 1574 1639 1598 1598 1664 1599 1599 1665 1574 1574 1639 1599 1599 1665 1575 1575 1640 1575 1575 1640 1599 1599 1665 1600 1600 1666 1575 1575 1640 1600 1600 1666 1576 1576 1641 1576 1576 1641 1600 1600 1666 1601 1601 1667 1576 1576 1641 1601 1601 1667 1577 1577 1642 1577 1577 1642 1601 1601 1667 1602 1602 1668 1577 1577 1642 1602 1602 1668 1578 1578 1643 1578 1578 1643 1602 1602 1668 1603 1603 1669 1578 1578 1643 1603 1603 1669 1579 1579 1644 1579 1579 1644 1603 1603 1669 1604 1604 1670 1579 1579 1644 1604 1604 1670 1580 1580 1645 1580 1580 1645 1604 1604 1670 1605 1605 1671 1580 1580 1645 1605 1605 1671 1581 1581 1646 1581 1581 1646 1605 1605 1671 1606 1606 1672 1581 1581 1646 1606 1606 1672 1582 1582 1647 1582 1582 1647 1606 1606 1672 1607 1607 1673 1582 1582 1647 1607 1607 1673 1583 1583 1648 1583 1583 1648 1607 1607 1673 1584 1584 1674 1583 1583 1648 1584 1584 1674 1560 1560 1649 1584 1584 1650 1608 1608 1675 1609 1609 1676 1584 1584 1650 1609 1609 1676 1585 1585 1651 1585 1585 1651 1609 1609 1676 1610 1610 1677 1585 1585 1651 1610 1610 1677 1586 1586 1652 1586 1586 1652 1610 1610 1677 1611 1611 1678 1586 1586 1652 1611 1611 1678 1587 1587 1653 1587 1587 1653 1611 1611 1678 1612 1612 1679 1587 1587 1653 1612 1612 1679 1588 1588 1654 1588 1588 1654 1612 1612 1679 1613 1613 1680 1588 1588 1654 1613 1613 1680 1589 1589 1655 1589 1589 1655 1613 1613 1680 1614 1614 1681 1589 1589 1655 1614 1614 1681 1590 1590 1656 1590 1590 1656 1614 1614 1681 1615 1615 1682 1590 1590 1656 1615 1615 1682 1591 1591 1657 1591 1591 1657 1615 1615 1682 1616 1616 1683 1591 1591 1657 1616 1616 1683 1592 1592 1658 1592 1592 1658 1616 1616 1683 1617 1617 1684 1592 1592 1658 1617 1617 1684 1593 1593 1659 1593 1593 1659 1617 1617 1684 1618 1618 1685 1593 1593 1659 1618 1618 1685 1594 1594 1660 1594 1594 1660 1618 1618 1685 1619 1619 1686 1594 1594 1660 1619 1619 1686 1595 1595 1661 1595 1595 1661 1619 1619 1686 1620 1620 1687 1595 1595 1661 1620 1620 1687 1596 1596 1662 1596 1596 1662 1620 1620 1687 1621 1621 1688 1596 1596 1662 1621 1621 1688 1597 1597 1663 1597 1597 1663 1621 1621 1688 1622 1622 1689 1597 1597 1663 1622 1622 1689 1598 1598 1664 1598 1598 1664 1622 1622 1689 1623 1623 1690 1598 1598 1664 1623 1623 1690 1599 1599 1665 1599 1599 1665 1623 1623 1690 1624 1624 1691 1599 1599 1665 1624 1624 1691 1600 1600 1666 1600 1600 1666 1624 1624 1691 1625 1625 1692 1600 1600 1666 1625 1625 1692 1601 1601 1667 1601 1601 1667 1625 1625 1692 1626 1626 1693 1601 1601 1667 1626 1626 1693 1602 1602 1668 1602 1602 1668 1626 1626 1693 1627 1627 1694 1602 1602 1668 1627 1627 1694 1603 1603 1669 1603 1603 1669 1627 1627 1694 1628 1628 1695 1603 1603 1669 1628 1628 1695 1604 1604 1670 1604 1604 1670 1628 1628 1695 1629 1629 1696 1604 1604 1670 1629 1629 1696 1605 1605 1671 1605 1605 1671 1629 1629 1696 1630 1630 1697 1605 1605 1671 1630 1630 1697 1606 1606 1672 1606 1606 1672 1630 1630 1697 1631 1631 1698 1606 1606 1672 1631 1631 1698 1607 1607 1673 1607 1607 1673 1631 1631 1698 1608 1608 1699 1607 1607 1673 1608 1608 1699 1584 1584 1674 1608 1608 1675 1632 1632 1700 1633 1633 1701 1608 1608 1675 1633 1633 1701 1609 1609 1676 1609 1609 1676 1633 1633 1701 1634 1634 1702 1609 1609 1676 1634 1634 1702 1610 1610 1677 1610 1610 1677 1634 1634 1702 1635 1635 1703 1610 1610 1677 1635 1635 1703 1611 1611 1678 1611 1611 1678 1635 1635 1703 1636 1636 1704 1611 1611 1678 1636 1636 1704 1612 1612 1679 1612 1612 1679 1636 1636 1704 1637 1637 1705 1612 1612 1679 1637 1637 1705 1613 1613 1680 1613 1613 1680 1637 1637 1705 1638 1638 1706 1613 1613 1680 1638 1638 1706 1614 1614 1681 1614 1614 1681 1638 1638 1706 1639 1639 1707 1614 1614 1681 1639 1639 1707 1615 1615 1682 1615 1615 1682 1639 1639 1707 1640 1640 1708 1615 1615 1682 1640 1640 1708 1616 1616 1683 1616 1616 1683 1640 1640 1708 1641 1641 1709 1616 1616 1683 1641 1641 1709 1617 1617 1684 1617 1617 1684 1641 1641 1709 1642 1642 1710 1617 1617 1684 1642 1642 1710 1618 1618 1685 1618 1618 1685 1642 1642 1710 1643 1643 1711 1618 1618 1685 1643 1643 1711 1619 1619 1686 1619 1619 1686 1643 1643 1711 1644 1644 1712 1619 1619 1686 1644 1644 1712 1620 1620 1687 1620 1620 1687 1644 1644 1712 1645 1645 1713 1620 1620 1687 1645 1645 1713 1621 1621 1688 1621 1621 1688 1645 1645 1713 1646 1646 1714 1621 1621 1688 1646 1646 1714 1622 1622 1689 1622 1622 1689 1646 1646 1714 1647 1647 1715 1622 1622 1689 1647 1647 1715 1623 1623 1690 1623 1623 1690 1647 1647 1715 1648 1648 1716 1623 1623 1690 1648 1648 1716 1624 1624 1691 1624 1624 1691 1648 1648 1716 1649 1649 1717 1624 1624 1691 1649 1649 1717 1625 1625 1692 1625 1625 1692 1649 1649 1717 1650 1650 1718 1625 1625 1692 1650 1650 1718 1626 1626 1693 1626 1626 1693 1650 1650 1718 1651 1651 1719 1626 1626 1693 1651 1651 1719 1627 1627 1694 1627 1627 1694 1651 1651 1719 1652 1652 1720 1627 1627 1694 1652 1652 1720 1628 1628 1695 1628 1628 1695 1652 1652 1720 1653 1653 1721 1628 1628 1695 1653 1653 1721 1629 1629 1696 1629 1629 1696 1653 1653 1721 1654 1654 1722 1629 1629 1696 1654 1654 1722 1630 1630 1697 1630 1630 1697 1654 1654 1722 1655 1655 1723 1630 1630 1697 1655 1655 1723 1631 1631 1698 1631 1631 1698 1655 1655 1723 1632 1632 1724 1631 1631 1698 1632 1632 1724 1608 1608 1699 1632 1632 1700 1656 1656 1725 1657 1657 1726 1632 1632 1700 1657 1657 1726 1633 1633 1701 1633 1633 1701 1657 1657 1726 1658 1658 1727 1633 1633 1701 1658 1658 1727 1634 1634 1702 1634 1634 1702 1658 1658 1727 1659 1659 1728 1634 1634 1702 1659 1659 1728 1635 1635 1703 1635 1635 1703 1659 1659 1728 1660 1660 1729 1635 1635 1703 1660 1660 1729 1636 1636 1704 1636 1636 1704 1660 1660 1729 1661 1661 1730 1636 1636 1704 1661 1661 1730 1637 1637 1705 1637 1637 1705 1661 1661 1730 1662 1662 1731 1637 1637 1705 1662 1662 1731 1638 1638 1706 1638 1638 1706 1662 1662 1731 1663 1663 1732 1638 1638 1706 1663 1663 1732 1639 1639 1707 1639 1639 1707 1663 1663 1732 1664 1664 1733 1639 1639 1707 1664 1664 1733 1640 1640 1708 1640 1640 1708 1664 1664 1733 1665 1665 1734 1640 1640 1708 1665 1665 1734 1641 1641 1709 1641 1641 1709 1665 1665 1734 1666 1666 1735 1641 1641 1709 1666 1666 1735 1642 1642 1710 1642 1642 1710 1666 1666 1735 1667 1667 1736 1642 1642 1710 1667 1667 1736 1643 1643 1711 1643 1643 1711 1667 1667 1736 1668 1668 1737 1643 1643 1711 1668 1668 1737 1644 1644 1712 1644 1644 1712 1668 1668 1737 1669 1669 1738 1644 1644 1712 1669 1669 1738 1645 1645 1713 1645 1645 1713 1669 1669 1738 1670 1670 1739 1645 1645 1713 1670 1670 1739 1646 1646 1714 1646 1646 1714 1670 1670 1739 1671 1671 1740 1646 1646 1714 1671 1671 1740 1647 1647 1715 1647 1647 1715 1671 1671 1740 1672 1672 1741 1647 1647 1715 1672 1672 1741 1648 1648 1716 1648 1648 1716 1672 1672 1741 1673 1673 1742 1648 1648 1716 1673 1673 1742 1649 1649 1717 1649 1649 1717 1673 1673 1742 1674 1674 1743 1649 1649 1717 1674 1674 1743 1650 1650 1718 1650 1650 1718 1674 1674 1743 1675 1675 1744 1650 1650 1718 1675 1675 1744 1651 1651 1719 1651 1651 1719 1675 1675 1744 1676 1676 1745 1651 1651 1719 1676 1676 1745 1652 1652 1720 1652 1652 1720 1676 1676 1745 1677 1677 1746 1652 1652 1720 1677 1677 1746 1653 1653 1721 1653 1653 1721 1677 1677 1746 1678 1678 1747 1653 1653 1721 1678 1678 1747 1654 1654 1722 1654 1654 1722 1678 1678 1747 1679 1679 1748 1654 1654 1722 1679 1679 1748 1655 1655 1723 1655 1655 1723 1679 1679 1748 1656 1656 1749 1655 1655 1723 1656 1656 1749 1632 1632 1724 1656 1656 1725 1680 1680 1750 1681 1681 1751 1656 1656 1725 1681 1681 1751 1657 1657 1726 1657 1657 1726 1681 1681 1751 1682 1682 1752 1657 1657 1726 1682 1682 1752 1658 1658 1727 1658 1658 1727 1682 1682 1752 1683 1683 1753 1658 1658 1727 1683 1683 1753 1659 1659 1728 1659 1659 1728 1683 1683 1753 1684 1684 1754 1659 1659 1728 1684 1684 1754 1660 1660 1729 1660 1660 1729 1684 1684 1754 1685 1685 1755 1660 1660 1729 1685 1685 1755 1661 1661 1730 1661 1661 1730 1685 1685 1755 1686 1686 1756 1661 1661 1730 1686 1686 1756 1662 1662 1731 1662 1662 1731 1686 1686 1756 1687 1687 1757 1662 1662 1731 1687 1687 1757 1663 1663 1732 1663 1663 1732 1687 1687 1757 1688 1688 1758 1663 1663 1732 1688 1688 1758 1664 1664 1733 1664 1664 1733 1688 1688 1758 1689 1689 1759 1664 1664 1733 1689 1689 1759 1665 1665 1734 1665 1665 1734 1689 1689 1759 1690 1690 1760 1665 1665 1734 1690 1690 1760 1666 1666 1735 1666 1666 1735 1690 1690 1760 1691 1691 1761 1666 1666 1735 1691 1691 1761 1667 1667 1736 1667 1667 1736 1691 1691 1761 1692 1692 1762 1667 1667 1736 1692 1692 1762 1668 1668 1737 1668 1668 1737 1692 1692 1762 1693 1693 1763 1668 1668 1737 1693 1693 1763 1669 1669 1738 1669 1669 1738 1693 1693 1763 1694 1694 1764 1669 1669 1738 1694 1694 1764 1670 1670 1739 1670 1670 1739 1694 1694 1764 1695 1695 1765 1670 1670 1739 1695 1695 1765 1671 1671 1740 1671 1671 1740 1695 1695 1765 1696 1696 1766 1671 1671 1740 1696 1696 1766 1672 1672 1741 1672 1672 1741 1696 1696 1766 1697 1697 1767 1672 1672 1741 1697 1697 1767 1673 1673 1742 1673 1673 1742 1697 1697 1767 1698 1698 1768 1673 1673 1742 1698 1698 1768 1674 1674 1743 1674 1674 1743 1698 1698 1768 1699 1699 1769 1674 1674 1743 1699 1699 1769 1675 1675 1744 1675 1675 1744 1699 1699 1769 1700 1700 1770 1675 1675 1744 1700 1700 1770 1676 1676 1745 1676 1676 1745 1700 1700 1770 1701 1701 1771 1676 1676 1745 1701 1701 1771 1677 1677 1746 1677 1677 1746 1701 1701 1771 1702 1702 1772 1677 1677 1746 1702 1702 1772 1678 1678 1747 1678 1678 1747 1702 1702 1772 1703 1703 1773 1678 1678 1747 1703 1703 1773 1679 1679 1748 1679 1679 1748 1703 1703 1773 1680 1680 1774 1679 1679 1748 1680 1680 1774 1656 1656 1749 1680 1680 1750 1704 1704 1775 1705 1705 1776 1680 1680 1750 1705 1705 1776 1681 1681 1751 1681 1681 1751 1705 1705 1776 1706 1706 1777 1681 1681 1751 1706 1706 1777 1682 1682 1752 1682 1682 1752 1706 1706 1777 1707 1707 1778 1682 1682 1752 1707 1707 1778 1683 1683 1753 1683 1683 1753 1707 1707 1778 1708 1708 1779 1683 1683 1753 1708 1708 1779 1684 1684 1754 1684 1684 1754 1708 1708 1779 1709 1709 1780 1684 1684 1754 1709 1709 1780 1685 1685 1755 1685 1685 1755 1709 1709 1780 1710 1710 1781 1685 1685 1755 1710 1710 1781 1686 1686 1756 1686 1686 1756 1710 1710 1781 1711 1711 1782 1686 1686 1756 1711 1711 1782 1687 1687 1757 1687 1687 1757 1711 1711 1782 1712 1712 1783 1687 1687 1757 1712 1712 1783 1688 1688 1758 1688 1688 1758 1712 1712 1783 1713 1713 1784 1688 1688 1758 1713 1713 1784 1689 1689 1759 1689 1689 1759 1713 1713 1784 1714 1714 1785 1689 1689 1759 1714 1714 1785 1690 1690 1760 1690 1690 1760 1714 1714 1785 1715 1715 1786 1690 1690 1760 1715 1715 1786 1691 1691 1761 1691 1691 1761 1715 1715 1786 1716 1716 1787 1691 1691 1761 1716 1716 1787 1692 1692 1762 1692 1692 1762 1716 1716 1787 1717 1717 1788 1692 1692 1762 1717 1717 1788 1693 1693 1763 1693 1693 1763 1717 1717 1788 1718 1718 1789 1693 1693 1763 1718 1718 1789 1694 1694 1764 1694 1694 1764 1718 1718 1789 1719 1719 1790 1694 1694 1764 1719 1719 1790 1695 1695 1765 1695 1695 1765 1719 1719 1790 1720 1720 1791 1695 1695 1765 1720 1720 1791 1696 1696 1766 1696 1696 1766 1720 1720 1791 1721 1721 1792 1696 1696 1766 1721 1721 1792 1697 1697 1767 1697 1697 1767 1721 1721 1792 1722 1722 1793 1697 1697 1767 1722 1722 1793 1698 1698 1768 1698 1698 1768 1722 1722 1793 1723 1723 1794 1698 1698 1768 1723 1723 1794 1699 1699 1769 1699 1699 1769 1723 1723 1794 1724 1724 1795 1699 1699 1769 1724 1724 1795 1700 1700 1770 1700 1700 1770 1724 1724 1795 1725 1725 1796 1700 1700 1770 1725 1725 1796 1701 1701 1771 1701 1701 1771 1725 1725 1796 1726 1726 1797 1701 1701 1771 1726 1726 1797 1702 1702 1772 1702 1702 1772 1726 1726 1797 1727 1727 1798 1702 1702 1772 1727 1727 1798 1703 1703 1773 1703 1703 1773 1727 1727 1798 1704 1704 1799 1703 1703 1773 1704 1704 1799 1680 1680 1774 1704 1704 1775 1728 1728 1800 1729 1729 1801 1704 1704 1775 1729 1729 1801 1705 1705 1776 1705 1705 1776 1729 1729 1801 1730 1730 1802 1705 1705 1776 1730 1730 1802 1706 1706 1777 1706 1706 1777 1730 1730 1802 1731 1731 1803 1706 1706 1777 1731 1731 1803 1707 1707 1778 1707 1707 1778 1731 1731 1803 1732 1732 1804 1707 1707 1778 1732 1732 1804 1708 1708 1779 1708 1708 1779 1732 1732 1804 1733 1733 1805 1708 1708 1779 1733 1733 1805 1709 1709 1780 1709 1709 1780 1733 1733 1805 1734 1734 1806 1709 1709 1780 1734 1734 1806 1710 1710 1781 1710 1710 1781 1734 1734 1806 1735 1735 1807 1710 1710 1781 1735 1735 1807 1711 1711 1782 1711 1711 1782 1735 1735 1807 1736 1736 1808 1711 1711 1782 1736 1736 1808 1712 1712 1783 1712 1712 1783 1736 1736 1808 1737 1737 1809 1712 1712 1783 1737 1737 1809 1713 1713 1784 1713 1713 1784 1737 1737 1809 1738 1738 1810 1713 1713 1784 1738 1738 1810 1714 1714 1785 1714 1714 1785 1738 1738 1810 1739 1739 1811 1714 1714 1785 1739 1739 1811 1715 1715 1786 1715 1715 1786 1739 1739 1811 1740 1740 1812 1715 1715 1786 1740 1740 1812 1716 1716 1787 1716 1716 1787 1740 1740 1812 1741 1741 1813 1716 1716 1787 1741 1741 1813 1717 1717 1788 1717 1717 1788 1741 1741 1813 1742 1742 1814 1717 1717 1788 1742 1742 1814 1718 1718 1789 1718 1718 1789 1742 1742 1814 1743 1743 1815 1718 1718 1789 1743 1743 1815 1719 1719 1790 1719 1719 1790 1743 1743 1815 1744 1744 1816 1719 1719 1790 1744 1744 1816 1720 1720 1791 1720 1720 1791 1744 1744 1816 1745 1745 1817 1720 1720 1791 1745 1745 1817 1721 1721 1792 1721 1721 1792 1745 1745 1817 1746 1746 1818 1721 1721 1792 1746 1746 1818 1722 1722 1793 1722 1722 1793 1746 1746 1818 1747 1747 1819 1722 1722 1793 1747 1747 1819 1723 1723 1794 1723 1723 1794 1747 1747 1819 1748 1748 1820 1723 1723 1794 1748 1748 1820 1724 1724 1795 1724 1724 1795 1748 1748 1820 1749 1749 1821 1724 1724 1795 1749 1749 1821 1725 1725 1796 1725 1725 1796 1749 1749 1821 1750 1750 1822 1725 1725 1796 1750 1750 1822 1726 1726 1797 1726 1726 1797 1750 1750 1822 1751 1751 1823 1726 1726 1797 1751 1751 1823 1727 1727 1798 1727 1727 1798 1751 1751 1823 1728 1728 1824 1727 1727 1798 1728 1728 1824 1704 1704 1799 1728 1728 1800 1752 1752 1825 1753 1753 1826 1728 1728 1800 1753 1753 1826 1729 1729 1801 1729 1729 1801 1753 1753 1826 1754 1754 1827 1729 1729 1801 1754 1754 1827 1730 1730 1802 1730 1730 1802 1754 1754 1827 1755 1755 1828 1730 1730 1802 1755 1755 1828 1731 1731 1803 1731 1731 1803 1755 1755 1828 1756 1756 1829 1731 1731 1803 1756 1756 1829 1732 1732 1804 1732 1732 1804 1756 1756 1829 1757 1757 1830 1732 1732 1804 1757 1757 1830 1733 1733 1805 1733 1733 1805 1757 1757 1830 1758 1758 1831 1733 1733 1805 1758 1758 1831 1734 1734 1806 1734 1734 1806 1758 1758 1831 1759 1759 1832 1734 1734 1806 1759 1759 1832 1735 1735 1807 1735 1735 1807 1759 1759 1832 1760 1760 1833 1735 1735 1807 1760 1760 1833 1736 1736 1808 1736 1736 1808 1760 1760 1833 1761 1761 1834 1736 1736 1808 1761 1761 1834 1737 1737 1809 1737 1737 1809 1761 1761 1834 1762 1762 1835 1737 1737 1809 1762 1762 1835 1738 1738 1810 1738 1738 1810 1762 1762 1835 1763 1763 1836 1738 1738 1810 1763 1763 1836 1739 1739 1811 1739 1739 1811 1763 1763 1836 1764 1764 1837 1739 1739 1811 1764 1764 1837 1740 1740 1812 1740 1740 1812 1764 1764 1837 1765 1765 1838 1740 1740 1812 1765 1765 1838 1741 1741 1813 1741 1741 1813 1765 1765 1838 1766 1766 1839 1741 1741 1813 1766 1766 1839 1742 1742 1814 1742 1742 1814 1766 1766 1839 1767 1767 1840 1742 1742 1814 1767 1767 1840 1743 1743 1815 1743 1743 1815 1767 1767 1840 1768 1768 1841 1743 1743 1815 1768 1768 1841 1744 1744 1816 1744 1744 1816 1768 1768 1841 1769 1769 1842 1744 1744 1816 1769 1769 1842 1745 1745 1817 1745 1745 1817 1769 1769 1842 1770 1770 1843 1745 1745 1817 1770 1770 1843 1746 1746 1818 1746 1746 1818 1770 1770 1843 1771 1771 1844 1746 1746 1818 1771 1771 1844 1747 1747 1819 1747 1747 1819 1771 1771 1844 1772 1772 1845 1747 1747 1819 1772 1772 1845 1748 1748 1820 1748 1748 1820 1772 1772 1845 1773 1773 1846 1748 1748 1820 1773 1773 1846 1749 1749 1821 1749 1749 1821 1773 1773 1846 1774 1774 1847 1749 1749 1821 1774 1774 1847 1750 1750 1822 1750 1750 1822 1774 1774 1847 1775 1775 1848 1750 1750 1822 1775 1775 1848 1751 1751 1823 1751 1751 1823 1775 1775 1848 1752 1752 1849 1751 1751 1823 1752 1752 1849 1728 1728 1824 1752 1752 1825 1776 1776 1850 1777 1777 1851 1752 1752 1825 1777 1777 1851 1753 1753 1826 1753 1753 1826 1777 1777 1851 1778 1778 1852 1753 1753 1826 1778 1778 1852 1754 1754 1827 1754 1754 1827 1778 1778 1852 1779 1779 1853 1754 1754 1827 1779 1779 1853 1755 1755 1828 1755 1755 1828 1779 1779 1853 1780 1780 1854 1755 1755 1828 1780 1780 1854 1756 1756 1829 1756 1756 1829 1780 1780 1854 1781 1781 1855 1756 1756 1829 1781 1781 1855 1757 1757 1830 1757 1757 1830 1781 1781 1855 1782 1782 1856 1757 1757 1830 1782 1782 1856 1758 1758 1831 1758 1758 1831 1782 1782 1856 1783 1783 1857 1758 1758 1831 1783 1783 1857 1759 1759 1832 1759 1759 1832 1783 1783 1857 1784 1784 1858 1759 1759 1832 1784 1784 1858 1760 1760 1833 1760 1760 1833 1784 1784 1858 1785 1785 1859 1760 1760 1833 1785 1785 1859 1761 1761 1834 1761 1761 1834 1785 1785 1859 1786 1786 1860 1761 1761 1834 1786 1786 1860 1762 1762 1835 1762 1762 1835 1786 1786 1860 1787 1787 1861 1762 1762 1835 1787 1787 1861 1763 1763 1836 1763 1763 1836 1787 1787 1861 1788 1788 1862 1763 1763 1836 1788 1788 1862 1764 1764 1837 1764 1764 1837 1788 1788 1862 1789 1789 1863 1764 1764 1837 1789 1789 1863 1765 1765 1838 1765 1765 1838 1789 1789 1863 1790 1790 1864 1765 1765 1838 1790 1790 1864 1766 1766 1839 1766 1766 1839 1790 1790 1864 1791 1791 1865 1766 1766 1839 1791 1791 1865 1767 1767 1840 1767 1767 1840 1791 1791 1865 1792 1792 1866 1767 1767 1840 1792 1792 1866 1768 1768 1841 1768 1768 1841 1792 1792 1866 1793 1793 1867 1768 1768 1841 1793 1793 1867 1769 1769 1842 1769 1769 1842 1793 1793 1867 1794 1794 1868 1769 1769 1842 1794 1794 1868 1770 1770 1843 1770 1770 1843 1794 1794 1868 1795 1795 1869 1770 1770 1843 1795 1795 1869 1771 1771 1844 1771 1771 1844 1795 1795 1869 1796 1796 1870 1771 1771 1844 1796 1796 1870 1772 1772 1845 1772 1772 1845 1796 1796 1870 1797 1797 1871 1772 1772 1845 1797 1797 1871 1773 1773 1846 1773 1773 1846 1797 1797 1871 1798 1798 1872 1773 1773 1846 1798 1798 1872 1774 1774 1847 1774 1774 1847 1798 1798 1872 1799 1799 1873 1774 1774 1847 1799 1799 1873 1775 1775 1848 1775 1775 1848 1799 1799 1873 1776 1776 1874 1775 1775 1848 1776 1776 1874 1752 1752 1849 1776 1776 1850 1800 1800 1875 1801 1801 1876 1776 1776 1850 1801 1801 1876 1777 1777 1851 1777 1777 1851 1801 1801 1876 1802 1802 1877 1777 1777 1851 1802 1802 1877 1778 1778 1852 1778 1778 1852 1802 1802 1877 1803 1803 1878 1778 1778 1852 1803 1803 1878 1779 1779 1853 1779 1779 1853 1803 1803 1878 1804 1804 1879 1779 1779 1853 1804 1804 1879 1780 1780 1854 1780 1780 1854 1804 1804 1879 1805 1805 1880 1780 1780 1854 1805 1805 1880 1781 1781 1855 1781 1781 1855 1805 1805 1880 1806 1806 1881 1781 1781 1855 1806 1806 1881 1782 1782 1856 1782 1782 1856 1806 1806 1881 1807 1807 1882 1782 1782 1856 1807 1807 1882 1783 1783 1857 1783 1783 1857 1807 1807 1882 1808 1808 1883 1783 1783 1857 1808 1808 1883 1784 1784 1858 1784 1784 1858 1808 1808 1883 1809 1809 1884 1784 1784 1858 1809 1809 1884 1785 1785 1859 1785 1785 1859 1809 1809 1884 1810 1810 1885 1785 1785 1859 1810 1810 1885 1786 1786 1860 1786 1786 1860 1810 1810 1885 1811 1811 1886 1786 1786 1860 1811 1811 1886 1787 1787 1861 1787 1787 1861 1811 1811 1886 1812 1812 1887 1787 1787 1861 1812 1812 1887 1788 1788 1862 1788 1788 1862 1812 1812 1887 1813 1813 1888 1788 1788 1862 1813 1813 1888 1789 1789 1863 1789 1789 1863 1813 1813 1888 1814 1814 1889 1789 1789 1863 1814 1814 1889 1790 1790 1864 1790 1790 1864 1814 1814 1889 1815 1815 1890 1790 1790 1864 1815 1815 1890 1791 1791 1865 1791 1791 1865 1815 1815 1890 1816 1816 1891 1791 1791 1865 1816 1816 1891 1792 1792 1866 1792 1792 1866 1816 1816 1891 1817 1817 1892 1792 1792 1866 1817 1817 1892 1793 1793 1867 1793 1793 1867 1817 1817 1892 1818 1818 1893 1793 1793 1867 1818 1818 1893 1794 1794 1868 1794 1794 1868 1818 1818 1893 1819 1819 1894 1794 1794 1868 1819 1819 1894 1795 1795 1869 1795 1795 1869 1819 1819 1894 1820 1820 1895 1795 1795 1869 1820 1820 1895 1796 1796 1870 1796 1796 1870 1820 1820 1895 1821 1821 1896 1796 1796 1870 1821 1821 1896 1797 1797 1871 1797 1797 1871 1821 1821 1896 1822 1822 1897 1797 1797 1871 1822 1822 1897 1798 1798 1872 1798 1798 1872 1822 1822 1897 1823 1823 1898 1798 1798 1872 1823 1823 1898 1799 1799 1873 1799 1799 1873 1823 1823 1898 1800 1800 1899 1799 1799 1873 1800 1800 1899 1776 1776 1874 1800 1800 1875 1824 1824 1900 1825 1825 1901 1800 1800 1875 1825 1825 1901 1801 1801 1876 1801 1801 1876 1825 1825 1901 1826 1826 1902 1801 1801 1876 1826 1826 1902 1802 1802 1877 1802 1802 1877 1826 1826 1902 1827 1827 1903 1802 1802 1877 1827 1827 1903 1803 1803 1878 1803 1803 1878 1827 1827 1903 1828 1828 1904 1803 1803 1878 1828 1828 1904 1804 1804 1879 1804 1804 1879 1828 1828 1904 1829 1829 1905 1804 1804 1879 1829 1829 1905 1805 1805 1880 1805 1805 1880 1829 1829 1905 1830 1830 1906 1805 1805 1880 1830 1830 1906 1806 1806 1881 1806 1806 1881 1830 1830 1906 1831 1831 1907 1806 1806 1881 1831 1831 1907 1807 1807 1882 1807 1807 1882 1831 1831 1907 1832 1832 1908 1807 1807 1882 1832 1832 1908 1808 1808 1883 1808 1808 1883 1832 1832 1908 1833 1833 1909 1808 1808 1883 1833 1833 1909 1809 1809 1884 1809 1809 1884 1833 1833 1909 1834 1834 1910 1809 1809 1884 1834 1834 1910 1810 1810 1885 1810 1810 1885 1834 1834 1910 1835 1835 1911 1810 1810 1885 1835 1835 1911 1811 1811 1886 1811 1811 1886 1835 1835 1911 1836 1836 1912 1811 1811 1886 1836 1836 1912 1812 1812 1887 1812 1812 1887 1836 1836 1912 1837 1837 1913 1812 1812 1887 1837 1837 1913 1813 1813 1888 1813 1813 1888 1837 1837 1913 1838 1838 1914 1813 1813 1888 1838 1838 1914 1814 1814 1889 1814 1814 1889 1838 1838 1914 1839 1839 1915 1814 1814 1889 1839 1839 1915 1815 1815 1890 1815 1815 1890 1839 1839 1915 1840 1840 1916 1815 1815 1890 1840 1840 1916 1816 1816 1891 1816 1816 1891 1840 1840 1916 1841 1841 1917 1816 1816 1891 1841 1841 1917 1817 1817 1892 1817 1817 1892 1841 1841 1917 1842 1842 1918 1817 1817 1892 1842 1842 1918 1818 1818 1893 1818 1818 1893 1842 1842 1918 1843 1843 1919 1818 1818 1893 1843 1843 1919 1819 1819 1894 1819 1819 1894 1843 1843 1919 1844 1844 1920 1819 1819 1894 1844 1844 1920 1820 1820 1895 1820 1820 1895 1844 1844 1920 1845 1845 1921 1820 1820 1895 1845 1845 1921 1821 1821 1896 1821 1821 1896 1845 1845 1921 1846 1846 1922 1821 1821 1896 1846 1846 1922 1822 1822 1897 1822 1822 1897 1846 1846 1922 1847 1847 1923 1822 1822 1897 1847 1847 1923 1823 1823 1898 1823 1823 1898 1847 1847 1923 1824 1824 1924 1823 1823 1898 1824 1824 1924 1800 1800 1899 1824 1824 1900 1848 1848 1925 1849 1849 1926 1824 1824 1900 1849 1849 1926 1825 1825 1901 1825 1825 1901 1849 1849 1926 1850 1850 1927 1825 1825 1901 1850 1850 1927 1826 1826 1902 1826 1826 1902 1850 1850 1927 1851 1851 1928 1826 1826 1902 1851 1851 1928 1827 1827 1903 1827 1827 1903 1851 1851 1928 1852 1852 1929 1827 1827 1903 1852 1852 1929 1828 1828 1904 1828 1828 1904 1852 1852 1929 1853 1853 1930 1828 1828 1904 1853 1853 1930 1829 1829 1905 1829 1829 1905 1853 1853 1930 1854 1854 1931 1829 1829 1905 1854 1854 1931 1830 1830 1906 1830 1830 1906 1854 1854 1931 1855 1855 1932 1830 1830 1906 1855 1855 1932 1831 1831 1907 1831 1831 1907 1855 1855 1932 1856 1856 1933 1831 1831 1907 1856 1856 1933 1832 1832 1908 1832 1832 1908 1856 1856 1933 1857 1857 1934 1832 1832 1908 1857 1857 1934 1833 1833 1909 1833 1833 1909 1857 1857 1934 1858 1858 1935 1833 1833 1909 1858 1858 1935 1834 1834 1910 1834 1834 1910 1858 1858 1935 1859 1859 1936 1834 1834 1910 1859 1859 1936 1835 1835 1911 1835 1835 1911 1859 1859 1936 1860 1860 1937 1835 1835 1911 1860 1860 1937 1836 1836 1912 1836 1836 1912 1860 1860 1937 1861 1861 1938 1836 1836 1912 1861 1861 1938 1837 1837 1913 1837 1837 1913 1861 1861 1938 1862 1862 1939 1837 1837 1913 1862 1862 1939 1838 1838 1914 1838 1838 1914 1862 1862 1939 1863 1863 1940 1838 1838 1914 1863 1863 1940 1839 1839 1915 1839 1839 1915 1863 1863 1940 1864 1864 1941 1839 1839 1915 1864 1864 1941 1840 1840 1916 1840 1840 1916 1864 1864 1941 1865 1865 1942 1840 1840 1916 1865 1865 1942 1841 1841 1917 1841 1841 1917 1865 1865 1942 1866 1866 1943 1841 1841 1917 1866 1866 1943 1842 1842 1918 1842 1842 1918 1866 1866 1943 1867 1867 1944 1842 1842 1918 1867 1867 1944 1843 1843 1919 1843 1843 1919 1867 1867 1944 1868 1868 1945 1843 1843 1919 1868 1868 1945 1844 1844 1920 1844 1844 1920 1868 1868 1945 1869 1869 1946 1844 1844 1920 1869 1869 1946 1845 1845 1921 1845 1845 1921 1869 1869 1946 1870 1870 1947 1845 1845 1921 1870 1870 1947 1846 1846 1922 1846 1846 1922 1870 1870 1947 1871 1871 1948 1846 1846 1922 1871 1871 1948 1847 1847 1923 1847 1847 1923 1871 1871 1948 1848 1848 1949 1847 1847 1923 1848 1848 1949 1824 1824 1924 1848 1848 1925 1872 1872 1950 1873 1873 1951 1848 1848 1925 1873 1873 1951 1849 1849 1926 1849 1849 1926 1873 1873 1951 1874 1874 1952 1849 1849 1926 1874 1874 1952 1850 1850 1927 1850 1850 1927 1874 1874 1952 1875 1875 1953 1850 1850 1927 1875 1875 1953 1851 1851 1928 1851 1851 1928 1875 1875 1953 1876 1876 1954 1851 1851 1928 1876 1876 1954 1852 1852 1929 1852 1852 1929 1876 1876 1954 1877 1877 1955 1852 1852 1929 1877 1877 1955 1853 1853 1930 1853 1853 1930 1877 1877 1955 1878 1878 1956 1853 1853 1930 1878 1878 1956 1854 1854 1931 1854 1854 1931 1878 1878 1956 1879 1879 1957 1854 1854 1931 1879 1879 1957 1855 1855 1932 1855 1855 1932 1879 1879 1957 1880 1880 1958 1855 1855 1932 1880 1880 1958 1856 1856 1933 1856 1856 1933 1880 1880 1958 1881 1881 1959 1856 1856 1933 1881 1881 1959 1857 1857 1934 1857 1857 1934 1881 1881 1959 1882 1882 1960 1857 1857 1934 1882 1882 1960 1858 1858 1935 1858 1858 1935 1882 1882 1960 1883 1883 1961 1858 1858 1935 1883 1883 1961 1859 1859 1936 1859 1859 1936 1883 1883 1961 1884 1884 1962 1859 1859 1936 1884 1884 1962 1860 1860 1937 1860 1860 1937 1884 1884 1962 1885 1885 1963 1860 1860 1937 1885 1885 1963 1861 1861 1938 1861 1861 1938 1885 1885 1963 1886 1886 1964 1861 1861 1938 1886 1886 1964 1862 1862 1939 1862 1862 1939 1886 1886 1964 1887 1887 1965 1862 1862 1939 1887 1887 1965 1863 1863 1940 1863 1863 1940 1887 1887 1965 1888 1888 1966 1863 1863 1940 1888 1888 1966 1864 1864 1941 1864 1864 1941 1888 1888 1966 1889 1889 1967 1864 1864 1941 1889 1889 1967 1865 1865 1942 1865 1865 1942 1889 1889 1967 1890 1890 1968 1865 1865 1942 1890 1890 1968 1866 1866 1943 1866 1866 1943 1890 1890 1968 1891 1891 1969 1866 1866 1943 1891 1891 1969 1867 1867 1944 1867 1867 1944 1891 1891 1969 1892 1892 1970 1867 1867 1944 1892 1892 1970 1868 1868 1945 1868 1868 1945 1892 1892 1970 1893 1893 1971 1868 1868 1945 1893 1893 1971 1869 1869 1946 1869 1869 1946 1893 1893 1971 1894 1894 1972 1869 1869 1946 1894 1894 1972 1870 1870 1947 1870 1870 1947 1894 1894 1972 1895 1895 1973 1870 1870 1947 1895 1895 1973 1871 1871 1948 1871 1871 1948 1895 1895 1973 1872 1872 1974 1871 1871 1948 1872 1872 1974 1848 1848 1949 1872 1872 1950 1896 1896 1975 1897 1897 1976 1872 1872 1950 1897 1897 1976 1873 1873 1951 1873 1873 1951 1897 1897 1976 1898 1898 1977 1873 1873 1951 1898 1898 1977 1874 1874 1952 1874 1874 1952 1898 1898 1977 1899 1899 1978 1874 1874 1952 1899 1899 1978 1875 1875 1953 1875 1875 1953 1899 1899 1978 1900 1900 1979 1875 1875 1953 1900 1900 1979 1876 1876 1954 1876 1876 1954 1900 1900 1979 1901 1901 1980 1876 1876 1954 1901 1901 1980 1877 1877 1955 1877 1877 1955 1901 1901 1980 1902 1902 1981 1877 1877 1955 1902 1902 1981 1878 1878 1956 1878 1878 1956 1902 1902 1981 1903 1903 1982 1878 1878 1956 1903 1903 1982 1879 1879 1957 1879 1879 1957 1903 1903 1982 1904 1904 1983 1879 1879 1957 1904 1904 1983 1880 1880 1958 1880 1880 1958 1904 1904 1983 1905 1905 1984 1880 1880 1958 1905 1905 1984 1881 1881 1959 1881 1881 1959 1905 1905 1984 1906 1906 1985 1881 1881 1959 1906 1906 1985 1882 1882 1960 1882 1882 1960 1906 1906 1985 1907 1907 1986 1882 1882 1960 1907 1907 1986 1883 1883 1961 1883 1883 1961 1907 1907 1986 1908 1908 1987 1883 1883 1961 1908 1908 1987 1884 1884 1962 1884 1884 1962 1908 1908 1987 1909 1909 1988 1884 1884 1962 1909 1909 1988 1885 1885 1963 1885 1885 1963 1909 1909 1988 1910 1910 1989 1885 1885 1963 1910 1910 1989 1886 1886 1964 1886 1886 1964 1910 1910 1989 1911 1911 1990 1886 1886 1964 1911 1911 1990 1887 1887 1965 1887 1887 1965 1911 1911 1990 1912 1912 1991 1887 1887 1965 1912 1912 1991 1888 1888 1966 1888 1888 1966 1912 1912 1991 1913 1913 1992 1888 1888 1966 1913 1913 1992 1889 1889 1967 1889 1889 1967 1913 1913 1992 1914 1914 1993 1889 1889 1967 1914 1914 1993 1890 1890 1968 1890 1890 1968 1914 1914 1993 1915 1915 1994 1890 1890 1968 1915 1915 1994 1891 1891 1969 1891 1891 1969 1915 1915 1994 1916 1916 1995 1891 1891 1969 1916 1916 1995 1892 1892 1970 1892 1892 1970 1916 1916 1995 1917 1917 1996 1892 1892 1970 1917 1917 1996 1893 1893 1971 1893 1893 1971 1917 1917 1996 1918 1918 1997 1893 1893 1971 1918 1918 1997 1894 1894 1972 1894 1894 1972 1918 1918 1997 1919 1919 1998 1894 1894 1972 1919 1919 1998 1895 1895 1973 1895 1895 1973 1919 1919 1998 1896 1896 1999 1895 1895 1973 1896 1896 1999 1872 1872 1974 1896 1896 1975 1920 1920 2000 1921 1921 2001 1896 1896 1975 1921 1921 2001 1897 1897 1976 1897 1897 1976 1921 1921 2001 1922 1922 2002 1897 1897 1976 1922 1922 2002 1898 1898 1977 1898 1898 1977 1922 1922 2002 1923 1923 2003 1898 1898 1977 1923 1923 2003 1899 1899 1978 1899 1899 1978 1923 1923 2003 1924 1924 2004 1899 1899 1978 1924 1924 2004 1900 1900 1979 1900 1900 1979 1924 1924 2004 1925 1925 2005 1900 1900 1979 1925 1925 2005 1901 1901 1980 1901 1901 1980 1925 1925 2005 1926 1926 2006 1901 1901 1980 1926 1926 2006 1902 1902 1981 1902 1902 1981 1926 1926 2006 1927 1927 2007 1902 1902 1981 1927 1927 2007 1903 1903 1982 1903 1903 1982 1927 1927 2007 1928 1928 2008 1903 1903 1982 1928 1928 2008 1904 1904 1983 1904 1904 1983 1928 1928 2008 1929 1929 2009 1904 1904 1983 1929 1929 2009 1905 1905 1984 1905 1905 1984 1929 1929 2009 1930 1930 2010 1905 1905 1984 1930 1930 2010 1906 1906 1985 1906 1906 1985 1930 1930 2010 1931 1931 2011 1906 1906 1985 1931 1931 2011 1907 1907 1986 1907 1907 1986 1931 1931 2011 1932 1932 2012 1907 1907 1986 1932 1932 2012 1908 1908 1987 1908 1908 1987 1932 1932 2012 1933 1933 2013 1908 1908 1987 1933 1933 2013 1909 1909 1988 1909 1909 1988 1933 1933 2013 1934 1934 2014 1909 1909 1988 1934 1934 2014 1910 1910 1989 1910 1910 1989 1934 1934 2014 1935 1935 2015 1910 1910 1989 1935 1935 2015 1911 1911 1990 1911 1911 1990 1935 1935 2015 1936 1936 2016 1911 1911 1990 1936 1936 2016 1912 1912 1991 1912 1912 1991 1936 1936 2016 1937 1937 2017 1912 1912 1991 1937 1937 2017 1913 1913 1992 1913 1913 1992 1937 1937 2017 1938 1938 2018 1913 1913 1992 1938 1938 2018 1914 1914 1993 1914 1914 1993 1938 1938 2018 1939 1939 2019 1914 1914 1993 1939 1939 2019 1915 1915 1994 1915 1915 1994 1939 1939 2019 1940 1940 2020 1915 1915 1994 1940 1940 2020 1916 1916 1995 1916 1916 1995 1940 1940 2020 1941 1941 2021 1916 1916 1995 1941 1941 2021 1917 1917 1996 1917 1917 1996 1941 1941 2021 1942 1942 2022 1917 1917 1996 1942 1942 2022 1918 1918 1997 1918 1918 1997 1942 1942 2022 1943 1943 2023 1918 1918 1997 1943 1943 2023 1919 1919 1998 1919 1919 1998 1943 1943 2023 1920 1920 2024 1919 1919 1998 1920 1920 2024 1896 1896 1999 1920 1920 2000 1944 1944 2025 1945 1945 2026 1920 1920 2000 1945 1945 2026 1921 1921 2001 1921 1921 2001 1945 1945 2026 1946 1946 2027 1921 1921 2001 1946 1946 2027 1922 1922 2002 1922 1922 2002 1946 1946 2027 1947 1947 2028 1922 1922 2002 1947 1947 2028 1923 1923 2003 1923 1923 2003 1947 1947 2028 1948 1948 2029 1923 1923 2003 1948 1948 2029 1924 1924 2004 1924 1924 2004 1948 1948 2029 1949 1949 2030 1924 1924 2004 1949 1949 2030 1925 1925 2005 1925 1925 2005 1949 1949 2030 1950 1950 2031 1925 1925 2005 1950 1950 2031 1926 1926 2006 1926 1926 2006 1950 1950 2031 1951 1951 2032 1926 1926 2006 1951 1951 2032 1927 1927 2007 1927 1927 2007 1951 1951 2032 1952 1952 2033 1927 1927 2007 1952 1952 2033 1928 1928 2008 1928 1928 2008 1952 1952 2033 1953 1953 2034 1928 1928 2008 1953 1953 2034 1929 1929 2009 1929 1929 2009 1953 1953 2034 1954 1954 2035 1929 1929 2009 1954 1954 2035 1930 1930 2010 1930 1930 2010 1954 1954 2035 1955 1955 2036 1930 1930 2010 1955 1955 2036 1931 1931 2011 1931 1931 2011 1955 1955 2036 1956 1956 2037 1931 1931 2011 1956 1956 2037 1932 1932 2012 1932 1932 2012 1956 1956 2037 1957 1957 2038 1932 1932 2012 1957 1957 2038 1933 1933 2013 1933 1933 2013 1957 1957 2038 1958 1958 2039 1933 1933 2013 1958 1958 2039 1934 1934 2014 1934 1934 2014 1958 1958 2039 1959 1959 2040 1934 1934 2014 1959 1959 2040 1935 1935 2015 1935 1935 2015 1959 1959 2040 1960 1960 2041 1935 1935 2015 1960 1960 2041 1936 1936 2016 1936 1936 2016 1960 1960 2041 1961 1961 2042 1936 1936 2016 1961 1961 2042 1937 1937 2017 1937 1937 2017 1961 1961 2042 1962 1962 2043 1937 1937 2017 1962 1962 2043 1938 1938 2018 1938 1938 2018 1962 1962 2043 1963 1963 2044 1938 1938 2018 1963 1963 2044 1939 1939 2019 1939 1939 2019 1963 1963 2044 1964 1964 2045 1939 1939 2019 1964 1964 2045 1940 1940 2020 1940 1940 2020 1964 1964 2045 1965 1965 2046 1940 1940 2020 1965 1965 2046 1941 1941 2021 1941 1941 2021 1965 1965 2046 1966 1966 2047 1941 1941 2021 1966 1966 2047 1942 1942 2022 1942 1942 2022 1966 1966 2047 1967 1967 2048 1942 1942 2022 1967 1967 2048 1943 1943 2023 1943 1943 2023 1967 1967 2048 1944 1944 2049 1943 1943 2023 1944 1944 2049 1920 1920 2024 1944 1944 2025 1968 1968 2050 1969 1969 2051 1944 1944 2025 1969 1969 2051 1945 1945 2026 1945 1945 2026 1969 1969 2051 1970 1970 2052 1945 1945 2026 1970 1970 2052 1946 1946 2027 1946 1946 2027 1970 1970 2052 1971 1971 2053 1946 1946 2027 1971 1971 2053 1947 1947 2028 1947 1947 2028 1971 1971 2053 1972 1972 2054 1947 1947 2028 1972 1972 2054 1948 1948 2029 1948 1948 2029 1972 1972 2054 1973 1973 2055 1948 1948 2029 1973 1973 2055 1949 1949 2030 1949 1949 2030 1973 1973 2055 1974 1974 2056 1949 1949 2030 1974 1974 2056 1950 1950 2031 1950 1950 2031 1974 1974 2056 1975 1975 2057 1950 1950 2031 1975 1975 2057 1951 1951 2032 1951 1951 2032 1975 1975 2057 1976 1976 2058 1951 1951 2032 1976 1976 2058 1952 1952 2033 1952 1952 2033 1976 1976 2058 1977 1977 2059 1952 1952 2033 1977 1977 2059 1953 1953 2034 1953 1953 2034 1977 1977 2059 1978 1978 2060 1953 1953 2034 1978 1978 2060 1954 1954 2035 1954 1954 2035 1978 1978 2060 1979 1979 2061 1954 1954 2035 1979 1979 2061 1955 1955 2036 1955 1955 2036 1979 1979 2061 1980 1980 2062 1955 1955 2036 1980 1980 2062 1956 1956 2037 1956 1956 2037 1980 1980 2062 1981 1981 2063 1956 1956 2037 1981 1981 2063 1957 1957 2038 1957 1957 2038 1981 1981 2063 1982 1982 2064 1957 1957 2038 1982 1982 2064 1958 1958 2039 1958 1958 2039 1982 1982 2064 1983 1983 2065 1958 1958 2039 1983 1983 2065 1959 1959 2040 1959 1959 2040 1983 1983 2065 1984 1984 2066 1959 1959 2040 1984 1984 2066 1960 1960 2041 1960 1960 2041 1984 1984 2066 1985 1985 2067 1960 1960 2041 1985 1985 2067 1961 1961 2042 1961 1961 2042 1985 1985 2067 1986 1986 2068 1961 1961 2042 1986 1986 2068 1962 1962 2043 1962 1962 2043 1986 1986 2068 1987 1987 2069 1962 1962 2043 1987 1987 2069 1963 1963 2044 1963 1963 2044 1987 1987 2069 1988 1988 2070 1963 1963 2044 1988 1988 2070 1964 1964 2045 1964 1964 2045 1988 1988 2070 1989 1989 2071 1964 1964 2045 1989 1989 2071 1965 1965 2046 1965 1965 2046 1989 1989 2071 1990 1990 2072 1965 1965 2046 1990 1990 2072 1966 1966 2047 1966 1966 2047 1990 1990 2072 1991 1991 2073 1966 1966 2047 1991 1991 2073 1967 1967 2048 1967 1967 2048 1991 1991 2073 1968 1968 2074 1967 1967 2048 1968 1968 2074 1944 1944 2049 1968 1968 2050 1992 1992 2075 1993 1993 2076 1968 1968 2050 1993 1993 2076 1969 1969 2051 1969 1969 2051 1993 1993 2076 1994 1994 2077 1969 1969 2051 1994 1994 2077 1970 1970 2052 1970 1970 2052 1994 1994 2077 1995 1995 2078 1970 1970 2052 1995 1995 2078 1971 1971 2053 1971 1971 2053 1995 1995 2078 1996 1996 2079 1971 1971 2053 1996 1996 2079 1972 1972 2054 1972 1972 2054 1996 1996 2079 1997 1997 2080 1972 1972 2054 1997 1997 2080 1973 1973 2055 1973 1973 2055 1997 1997 2080 1998 1998 2081 1973 1973 2055 1998 1998 2081 1974 1974 2056 1974 1974 2056 1998 1998 2081 1999 1999 2082 1974 1974 2056 1999 1999 2082 1975 1975 2057 1975 1975 2057 1999 1999 2082 2000 2000 2083 1975 1975 2057 2000 2000 2083 1976 1976 2058 1976 1976 2058 2000 2000 2083 2001 2001 2084 1976 1976 2058 2001 2001 2084 1977 1977 2059 1977 1977 2059 2001 2001 2084 2002 2002 2085 1977 1977 2059 2002 2002 2085 1978 1978 2060 1978 1978 2060 2002 2002 2085 2003 2003 2086 1978 1978 2060 2003 2003 2086 1979 1979 2061 1979 1979 2061 2003 2003 2086 2004 2004 2087 1979 1979 2061 2004 2004 2087 1980 1980 2062 1980 1980 2062 2004 2004 2087 2005 2005 2088 1980 1980 2062 2005 2005 2088 1981 1981 2063 1981 1981 2063 2005 2005 2088 2006 2006 2089 1981 1981 2063 2006 2006 2089 1982 1982 2064 1982 1982 2064 2006 2006 2089 2007 2007 2090 1982 1982 2064 2007 2007 2090 1983 1983 2065 1983 1983 2065 2007 2007 2090 2008 2008 2091 1983 1983 2065 2008 2008 2091 1984 1984 2066 1984 1984 2066 2008 2008 2091 2009 2009 2092 1984 1984 2066 2009 2009 2092 1985 1985 2067 1985 1985 2067 2009 2009 2092 2010 2010 2093 1985 1985 2067 2010 2010 2093 1986 1986 2068 1986 1986 2068 2010 2010 2093 2011 2011 2094 1986 1986 2068 2011 2011 2094 1987 1987 2069 1987 1987 2069 2011 2011 2094 2012 2012 2095 1987 1987 2069 2012 2012 2095 1988 1988 2070 1988 1988 2070 2012 2012 2095 2013 2013 2096 1988 1988 2070 2013 2013 2096 1989 1989 2071 1989 1989 2071 2013 2013 2096 2014 2014 2097 1989 1989 2071 2014 2014 2097 1990 1990 2072 1990 1990 2072 2014 2014 2097 2015 2015 2098 1990 1990 2072 2015 2015 2098 1991 1991 2073 1991 1991 2073 2015 2015 2098 1992 1992 2099 1991 1991 2073 1992 1992 2099 1968 1968 2074 1992 1992 2075 2016 2016 2100 2017 2017 2101 1992 1992 2075 2017 2017 2101 1993 1993 2076 1993 1993 2076 2017 2017 2101 2018 2018 2102 1993 1993 2076 2018 2018 2102 1994 1994 2077 1994 1994 2077 2018 2018 2102 2019 2019 2103 1994 1994 2077 2019 2019 2103 1995 1995 2078 1995 1995 2078 2019 2019 2103 2020 2020 2104 1995 1995 2078 2020 2020 2104 1996 1996 2079 1996 1996 2079 2020 2020 2104 2021 2021 2105 1996 1996 2079 2021 2021 2105 1997 1997 2080 1997 1997 2080 2021 2021 2105 2022 2022 2106 1997 1997 2080 2022 2022 2106 1998 1998 2081 1998 1998 2081 2022 2022 2106 2023 2023 2107 1998 1998 2081 2023 2023 2107 1999 1999 2082 1999 1999 2082 2023 2023 2107 2024 2024 2108 1999 1999 2082 2024 2024 2108 2000 2000 2083 2000 2000 2083 2024 2024 2108 2025 2025 2109 2000 2000 2083 2025 2025 2109 2001 2001 2084 2001 2001 2084 2025 2025 2109 2026 2026 2110 2001 2001 2084 2026 2026 2110 2002 2002 2085 2002 2002 2085 2026 2026 2110 2027 2027 2111 2002 2002 2085 2027 2027 2111 2003 2003 2086 2003 2003 2086 2027 2027 2111 2028 2028 2112 2003 2003 2086 2028 2028 2112 2004 2004 2087 2004 2004 2087 2028 2028 2112 2029 2029 2113 2004 2004 2087 2029 2029 2113 2005 2005 2088 2005 2005 2088 2029 2029 2113 2030 2030 2114 2005 2005 2088 2030 2030 2114 2006 2006 2089 2006 2006 2089 2030 2030 2114 2031 2031 2115 2006 2006 2089 2031 2031 2115 2007 2007 2090 2007 2007 2090 2031 2031 2115 2032 2032 2116 2007 2007 2090 2032 2032 2116 2008 2008 2091 2008 2008 2091 2032 2032 2116 2033 2033 2117 2008 2008 2091 2033 2033 2117 2009 2009 2092 2009 2009 2092 2033 2033 2117 2034 2034 2118 2009 2009 2092 2034 2034 2118 2010 2010 2093 2010 2010 2093 2034 2034 2118 2035 2035 2119 2010 2010 2093 2035 2035 2119 2011 2011 2094 2011 2011 2094 2035 2035 2119 2036 2036 2120 2011 2011 2094 2036 2036 2120 2012 2012 2095 2012 2012 2095 2036 2036 2120 2037 2037 2121 2012 2012 2095 2037 2037 2121 2013 2013 2096 2013 2013 2096 2037 2037 2121 2038 2038 2122 2013 2013 2096 2038 2038 2122 2014 2014 2097 2014 2014 2097 2038 2038 2122 2039 2039 2123 2014 2014 2097 2039 2039 2123 2015 2015 2098 2015 2015 2098 2039 2039 2123 2016 2016 2124 2015 2015 2098 2016 2016 2124 1992 1992 2099 2016 2016 2100 2040 2040 2125 2041 2041 2126 2016 2016 2100 2041 2041 2126 2017 2017 2101 2017 2017 2101 2041 2041 2126 2042 2042 2127 2017 2017 2101 2042 2042 2127 2018 2018 2102 2018 2018 2102 2042 2042 2127 2043 2043 2128 2018 2018 2102 2043 2043 2128 2019 2019 2103 2019 2019 2103 2043 2043 2128 2044 2044 2129 2019 2019 2103 2044 2044 2129 2020 2020 2104 2020 2020 2104 2044 2044 2129 2045 2045 2130 2020 2020 2104 2045 2045 2130 2021 2021 2105 2021 2021 2105 2045 2045 2130 2046 2046 2131 2021 2021 2105 2046 2046 2131 2022 2022 2106 2022 2022 2106 2046 2046 2131 2047 2047 2132 2022 2022 2106 2047 2047 2132 2023 2023 2107 2023 2023 2107 2047 2047 2132 2048 2048 2133 2023 2023 2107 2048 2048 2133 2024 2024 2108 2024 2024 2108 2048 2048 2133 2049 2049 2134 2024 2024 2108 2049 2049 2134 2025 2025 2109 2025 2025 2109 2049 2049 2134 2050 2050 2135 2025 2025 2109 2050 2050 2135 2026 2026 2110 2026 2026 2110 2050 2050 2135 2051 2051 2136 2026 2026 2110 2051 2051 2136 2027 2027 2111 2027 2027 2111 2051 2051 2136 2052 2052 2137 2027 2027 2111 2052 2052 2137 2028 2028 2112 2028 2028 2112 2052 2052 2137 2053 2053 2138 2028 2028 2112 2053 2053 2138 2029 2029 2113 2029 2029 2113 2053 2053 2138 2054 2054 2139 2029 2029 2113 2054 2054 2139 2030 2030 2114 2030 2030 2114 2054 2054 2139 2055 2055 2140 2030 2030 2114 2055 2055 2140 2031 2031 2115 2031 2031 2115 2055 2055 2140 2056 2056 2141 2031 2031 2115 2056 2056 2141 2032 2032 2116 2032 2032 2116 2056 2056 2141 2057 2057 2142 2032 2032 2116 2057 2057 2142 2033 2033 2117 2033 2033 2117 2057 2057 2142 2058 2058 2143 2033 2033 2117 2058 2058 2143 2034 2034 2118 2034 2034 2118 2058 2058 2143 2059 2059 2144 2034 2034 2118 2059 2059 2144 2035 2035 2119 2035 2035 2119 2059 2059 2144 2060 2060 2145 2035 2035 2119 2060 2060 2145 2036 2036 2120 2036 2036 2120 2060 2060 2145 2061 2061 2146 2036 2036 2120 2061 2061 2146 2037 2037 2121 2037 2037 2121 2061 2061 2146 2062 2062 2147 2037 2037 2121 2062 2062 2147 2038 2038 2122 2038 2038 2122 2062 2062 2147 2063 2063 2148 2038 2038 2122 2063 2063 2148 2039 2039 2123 2039 2039 2123 2063 2063 2148 2040 2040 2149 2039 2039 2123 2040 2040 2149 2016 2016 2124 2040 2040 2125 2064 2064 2150 2065 2065 2151 2040 2040 2125 2065 2065 2151 2041 2041 2126 2041 2041 2126 2065 2065 2151 2066 2066 2152 2041 2041 2126 2066 2066 2152 2042 2042 2127 2042 2042 2127 2066 2066 2152 2067 2067 2153 2042 2042 2127 2067 2067 2153 2043 2043 2128 2043 2043 2128 2067 2067 2153 2068 2068 2154 2043 2043 2128 2068 2068 2154 2044 2044 2129 2044 2044 2129 2068 2068 2154 2069 2069 2155 2044 2044 2129 2069 2069 2155 2045 2045 2130 2045 2045 2130 2069 2069 2155 2070 2070 2156 2045 2045 2130 2070 2070 2156 2046 2046 2131 2046 2046 2131 2070 2070 2156 2071 2071 2157 2046 2046 2131 2071 2071 2157 2047 2047 2132 2047 2047 2132 2071 2071 2157 2072 2072 2158 2047 2047 2132 2072 2072 2158 2048 2048 2133 2048 2048 2133 2072 2072 2158 2073 2073 2159 2048 2048 2133 2073 2073 2159 2049 2049 2134 2049 2049 2134 2073 2073 2159 2074 2074 2160 2049 2049 2134 2074 2074 2160 2050 2050 2135 2050 2050 2135 2074 2074 2160 2075 2075 2161 2050 2050 2135 2075 2075 2161 2051 2051 2136 2051 2051 2136 2075 2075 2161 2076 2076 2162 2051 2051 2136 2076 2076 2162 2052 2052 2137 2052 2052 2137 2076 2076 2162 2077 2077 2163 2052 2052 2137 2077 2077 2163 2053 2053 2138 2053 2053 2138 2077 2077 2163 2078 2078 2164 2053 2053 2138 2078 2078 2164 2054 2054 2139 2054 2054 2139 2078 2078 2164 2079 2079 2165 2054 2054 2139 2079 2079 2165 2055 2055 2140 2055 2055 2140 2079 2079 2165 2080 2080 2166 2055 2055 2140 2080 2080 2166 2056 2056 2141 2056 2056 2141 2080 2080 2166 2081 2081 2167 2056 2056 2141 2081 2081 2167 2057 2057 2142 2057 2057 2142 2081 2081 2167 2082 2082 2168 2057 2057 2142 2082 2082 2168 2058 2058 2143 2058 2058 2143 2082 2082 2168 2083 2083 2169 2058 2058 2143 2083 2083 2169 2059 2059 2144 2059 2059 2144 2083 2083 2169 2084 2084 2170 2059 2059 2144 2084 2084 2170 2060 2060 2145 2060 2060 2145 2084 2084 2170 2085 2085 2171 2060 2060 2145 2085 2085 2171 2061 2061 2146 2061 2061 2146 2085 2085 2171 2086 2086 2172 2061 2061 2146 2086 2086 2172 2062 2062 2147 2062 2062 2147 2086 2086 2172 2087 2087 2173 2062 2062 2147 2087 2087 2173 2063 2063 2148 2063 2063 2148 2087 2087 2173 2064 2064 2174 2063 2063 2148 2064 2064 2174 2040 2040 2149 2064 2064 2150 2088 2088 2175 2089 2089 2176 2064 2064 2150 2089 2089 2176 2065 2065 2151 2065 2065 2151 2089 2089 2176 2090 2090 2177 2065 2065 2151 2090 2090 2177 2066 2066 2152 2066 2066 2152 2090 2090 2177 2091 2091 2178 2066 2066 2152 2091 2091 2178 2067 2067 2153 2067 2067 2153 2091 2091 2178 2092 2092 2179 2067 2067 2153 2092 2092 2179 2068 2068 2154 2068 2068 2154 2092 2092 2179 2093 2093 2180 2068 2068 2154 2093 2093 2180 2069 2069 2155 2069 2069 2155 2093 2093 2180 2094 2094 2181 2069 2069 2155 2094 2094 2181 2070 2070 2156 2070 2070 2156 2094 2094 2181 2095 2095 2182 2070 2070 2156 2095 2095 2182 2071 2071 2157 2071 2071 2157 2095 2095 2182 2096 2096 2183 2071 2071 2157 2096 2096 2183 2072 2072 2158 2072 2072 2158 2096 2096 2183 2097 2097 2184 2072 2072 2158 2097 2097 2184 2073 2073 2159 2073 2073 2159 2097 2097 2184 2098 2098 2185 2073 2073 2159 2098 2098 2185 2074 2074 2160 2074 2074 2160 2098 2098 2185 2099 2099 2186 2074 2074 2160 2099 2099 2186 2075 2075 2161 2075 2075 2161 2099 2099 2186 2100 2100 2187 2075 2075 2161 2100 2100 2187 2076 2076 2162 2076 2076 2162 2100 2100 2187 2101 2101 2188 2076 2076 2162 2101 2101 2188 2077 2077 2163 2077 2077 2163 2101 2101 2188 2102 2102 2189 2077 2077 2163 2102 2102 2189 2078 2078 2164 2078 2078 2164 2102 2102 2189 2103 2103 2190 2078 2078 2164 2103 2103 2190 2079 2079 2165 2079 2079 2165 2103 2103 2190 2104 2104 2191 2079 2079 2165 2104 2104 2191 2080 2080 2166 2080 2080 2166 2104 2104 2191 2105 2105 2192 2080 2080 2166 2105 2105 2192 2081 2081 2167 2081 2081 2167 2105 2105 2192 2106 2106 2193 2081 2081 2167 2106 2106 2193 2082 2082 2168 2082 2082 2168 2106 2106 2193 2107 2107 2194 2082 2082 2168 2107 2107 2194 2083 2083 2169 2083 2083 2169 2107 2107 2194 2108 2108 2195 2083 2083 2169 2108 2108 2195 2084 2084 2170 2084 2084 2170 2108 2108 2195 2109 2109 2196 2084 2084 2170 2109 2109 2196 2085 2085 2171 2085 2085 2171 2109 2109 2196 2110 2110 2197 2085 2085 2171 2110 2110 2197 2086 2086 2172 2086 2086 2172 2110 2110 2197 2111 2111 2198 2086 2086 2172 2111 2111 2198 2087 2087 2173 2087 2087 2173 2111 2111 2198 2088 2088 2199 2087 2087 2173 2088 2088 2199 2064 2064 2174 2088 2088 2175 2112 2112 2200 2113 2113 2201 2088 2088 2175 2113 2113 2201 2089 2089 2176 2089 2089 2176 2113 2113 2201 2114 2114 2202 2089 2089 2176 2114 2114 2202 2090 2090 2177 2090 2090 2177 2114 2114 2202 2115 2115 2203 2090 2090 2177 2115 2115 2203 2091 2091 2178 2091 2091 2178 2115 2115 2203 2116 2116 2204 2091 2091 2178 2116 2116 2204 2092 2092 2179 2092 2092 2179 2116 2116 2204 2117 2117 2205 2092 2092 2179 2117 2117 2205 2093 2093 2180 2093 2093 2180 2117 2117 2205 2118 2118 2206 2093 2093 2180 2118 2118 2206 2094 2094 2181 2094 2094 2181 2118 2118 2206 2119 2119 2207 2094 2094 2181 2119 2119 2207 2095 2095 2182 2095 2095 2182 2119 2119 2207 2120 2120 2208 2095 2095 2182 2120 2120 2208 2096 2096 2183 2096 2096 2183 2120 2120 2208 2121 2121 2209 2096 2096 2183 2121 2121 2209 2097 2097 2184 2097 2097 2184 2121 2121 2209 2122 2122 2210 2097 2097 2184 2122 2122 2210 2098 2098 2185 2098 2098 2185 2122 2122 2210 2123 2123 2211 2098 2098 2185 2123 2123 2211 2099 2099 2186 2099 2099 2186 2123 2123 2211 2124 2124 2212 2099 2099 2186 2124 2124 2212 2100 2100 2187 2100 2100 2187 2124 2124 2212 2125 2125 2213 2100 2100 2187 2125 2125 2213 2101 2101 2188 2101 2101 2188 2125 2125 2213 2126 2126 2214 2101 2101 2188 2126 2126 2214 2102 2102 2189 2102 2102 2189 2126 2126 2214 2127 2127 2215 2102 2102 2189 2127 2127 2215 2103 2103 2190 2103 2103 2190 2127 2127 2215 2128 2128 2216 2103 2103 2190 2128 2128 2216 2104 2104 2191 2104 2104 2191 2128 2128 2216 2129 2129 2217 2104 2104 2191 2129 2129 2217 2105 2105 2192 2105 2105 2192 2129 2129 2217 2130 2130 2218 2105 2105 2192 2130 2130 2218 2106 2106 2193 2106 2106 2193 2130 2130 2218 2131 2131 2219 2106 2106 2193 2131 2131 2219 2107 2107 2194 2107 2107 2194 2131 2131 2219 2132 2132 2220 2107 2107 2194 2132 2132 2220 2108 2108 2195 2108 2108 2195 2132 2132 2220 2133 2133 2221 2108 2108 2195 2133 2133 2221 2109 2109 2196 2109 2109 2196 2133 2133 2221 2134 2134 2222 2109 2109 2196 2134 2134 2222 2110 2110 2197 2110 2110 2197 2134 2134 2222 2135 2135 2223 2110 2110 2197 2135 2135 2223 2111 2111 2198 2111 2111 2198 2135 2135 2223 2112 2112 2224 2111 2111 2198 2112 2112 2224 2088 2088 2199 2112 2112 2200 2136 2136 2225 2137 2137 2226 2112 2112 2200 2137 2137 2226 2113 2113 2201 2113 2113 2201 2137 2137 2226 2138 2138 2227 2113 2113 2201 2138 2138 2227 2114 2114 2202 2114 2114 2202 2138 2138 2227 2139 2139 2228 2114 2114 2202 2139 2139 2228 2115 2115 2203 2115 2115 2203 2139 2139 2228 2140 2140 2229 2115 2115 2203 2140 2140 2229 2116 2116 2204 2116 2116 2204 2140 2140 2229 2141 2141 2230 2116 2116 2204 2141 2141 2230 2117 2117 2205 2117 2117 2205 2141 2141 2230 2142 2142 2231 2117 2117 2205 2142 2142 2231 2118 2118 2206 2118 2118 2206 2142 2142 2231 2143 2143 2232 2118 2118 2206 2143 2143 2232 2119 2119 2207 2119 2119 2207 2143 2143 2232 2144 2144 2233 2119 2119 2207 2144 2144 2233 2120 2120 2208 2120 2120 2208 2144 2144 2233 2145 2145 2234 2120 2120 2208 2145 2145 2234 2121 2121 2209 2121 2121 2209 2145 2145 2234 2146 2146 2235 2121 2121 2209 2146 2146 2235 2122 2122 2210 2122 2122 2210 2146 2146 2235 2147 2147 2236 2122 2122 2210 2147 2147 2236 2123 2123 2211 2123 2123 2211 2147 2147 2236 2148 2148 2237 2123 2123 2211 2148 2148 2237 2124 2124 2212 2124 2124 2212 2148 2148 2237 2149 2149 2238 2124 2124 2212 2149 2149 2238 2125 2125 2213 2125 2125 2213 2149 2149 2238 2150 2150 2239 2125 2125 2213 2150 2150 2239 2126 2126 2214 2126 2126 2214 2150 2150 2239 2151 2151 2240 2126 2126 2214 2151 2151 2240 2127 2127 2215 2127 2127 2215 2151 2151 2240 2152 2152 2241 2127 2127 2215 2152 2152 2241 2128 2128 2216 2128 2128 2216 2152 2152 2241 2153 2153 2242 2128 2128 2216 2153 2153 2242 2129 2129 2217 2129 2129 2217 2153 2153 2242 2154 2154 2243 2129 2129 2217 2154 2154 2243 2130 2130 2218 2130 2130 2218 2154 2154 2243 2155 2155 2244 2130 2130 2218 2155 2155 2244 2131 2131 2219 2131 2131 2219 2155 2155 2244 2156 2156 2245 2131 2131 2219 2156 2156 2245 2132 2132 2220 2132 2132 2220 2156 2156 2245 2157 2157 2246 2132 2132 2220 2157 2157 2246 2133 2133 2221 2133 2133 2221 2157 2157 2246 2158 2158 2247 2133 2133 2221 2158 2158 2247 2134 2134 2222 2134 2134 2222 2158 2158 2247 2159 2159 2248 2134 2134 2222 2159 2159 2248 2135 2135 2223 2135 2135 2223 2159 2159 2248 2136 2136 2249 2135 2135 2223 2136 2136 2249 2112 2112 2224 2136 2136 2225 2160 2160 2250 2161 2161 2251 2136 2136 2225 2161 2161 2251 2137 2137 2226 2137 2137 2226 2161 2161 2251 2162 2162 2252 2137 2137 2226 2162 2162 2252 2138 2138 2227 2138 2138 2227 2162 2162 2252 2163 2163 2253 2138 2138 2227 2163 2163 2253 2139 2139 2228 2139 2139 2228 2163 2163 2253 2164 2164 2254 2139 2139 2228 2164 2164 2254 2140 2140 2229 2140 2140 2229 2164 2164 2254 2165 2165 2255 2140 2140 2229 2165 2165 2255 2141 2141 2230 2141 2141 2230 2165 2165 2255 2166 2166 2256 2141 2141 2230 2166 2166 2256 2142 2142 2231 2142 2142 2231 2166 2166 2256 2167 2167 2257 2142 2142 2231 2167 2167 2257 2143 2143 2232 2143 2143 2232 2167 2167 2257 2168 2168 2258 2143 2143 2232 2168 2168 2258 2144 2144 2233 2144 2144 2233 2168 2168 2258 2169 2169 2259 2144 2144 2233 2169 2169 2259 2145 2145 2234 2145 2145 2234 2169 2169 2259 2170 2170 2260 2145 2145 2234 2170 2170 2260 2146 2146 2235 2146 2146 2235 2170 2170 2260 2171 2171 2261 2146 2146 2235 2171 2171 2261 2147 2147 2236 2147 2147 2236 2171 2171 2261 2172 2172 2262 2147 2147 2236 2172 2172 2262 2148 2148 2237 2148 2148 2237 2172 2172 2262 2173 2173 2263 2148 2148 2237 2173 2173 2263 2149 2149 2238 2149 2149 2238 2173 2173 2263 2174 2174 2264 2149 2149 2238 2174 2174 2264 2150 2150 2239 2150 2150 2239 2174 2174 2264 2175 2175 2265 2150 2150 2239 2175 2175 2265 2151 2151 2240 2151 2151 2240 2175 2175 2265 2176 2176 2266 2151 2151 2240 2176 2176 2266 2152 2152 2241 2152 2152 2241 2176 2176 2266 2177 2177 2267 2152 2152 2241 2177 2177 2267 2153 2153 2242 2153 2153 2242 2177 2177 2267 2178 2178 2268 2153 2153 2242 2178 2178 2268 2154 2154 2243 2154 2154 2243 2178 2178 2268 2179 2179 2269 2154 2154 2243 2179 2179 2269 2155 2155 2244 2155 2155 2244 2179 2179 2269 2180 2180 2270 2155 2155 2244 2180 2180 2270 2156 2156 2245 2156 2156 2245 2180 2180 2270 2181 2181 2271 2156 2156 2245 2181 2181 2271 2157 2157 2246 2157 2157 2246 2181 2181 2271 2182 2182 2272 2157 2157 2246 2182 2182 2272 2158 2158 2247 2158 2158 2247 2182 2182 2272 2183 2183 2273 2158 2158 2247 2183 2183 2273 2159 2159 2248 2159 2159 2248 2183 2183 2273 2160 2160 2274 2159 2159 2248 2160 2160 2274 2136 2136 2249 2160 2160 2250 2184 2184 2275 2185 2185 2276 2160 2160 2250 2185 2185 2276 2161 2161 2251 2161 2161 2251 2185 2185 2276 2186 2186 2277 2161 2161 2251 2186 2186 2277 2162 2162 2252 2162 2162 2252 2186 2186 2277 2187 2187 2278 2162 2162 2252 2187 2187 2278 2163 2163 2253 2163 2163 2253 2187 2187 2278 2188 2188 2279 2163 2163 2253 2188 2188 2279 2164 2164 2254 2164 2164 2254 2188 2188 2279 2189 2189 2280 2164 2164 2254 2189 2189 2280 2165 2165 2255 2165 2165 2255 2189 2189 2280 2190 2190 2281 2165 2165 2255 2190 2190 2281 2166 2166 2256 2166 2166 2256 2190 2190 2281 2191 2191 2282 2166 2166 2256 2191 2191 2282 2167 2167 2257 2167 2167 2257 2191 2191 2282 2192 2192 2283 2167 2167 2257 2192 2192 2283 2168 2168 2258 2168 2168 2258 2192 2192 2283 2193 2193 2284 2168 2168 2258 2193 2193 2284 2169 2169 2259 2169 2169 2259 2193 2193 2284 2194 2194 2285 2169 2169 2259 2194 2194 2285 2170 2170 2260 2170 2170 2260 2194 2194 2285 2195 2195 2286 2170 2170 2260 2195 2195 2286 2171 2171 2261 2171 2171 2261 2195 2195 2286 2196 2196 2287 2171 2171 2261 2196 2196 2287 2172 2172 2262 2172 2172 2262 2196 2196 2287 2197 2197 2288 2172 2172 2262 2197 2197 2288 2173 2173 2263 2173 2173 2263 2197 2197 2288 2198 2198 2289 2173 2173 2263 2198 2198 2289 2174 2174 2264 2174 2174 2264 2198 2198 2289 2199 2199 2290 2174 2174 2264 2199 2199 2290 2175 2175 2265 2175 2175 2265 2199 2199 2290 2200 2200 2291 2175 2175 2265 2200 2200 2291 2176 2176 2266 2176 2176 2266 2200 2200 2291 2201 2201 2292 2176 2176 2266 2201 2201 2292 2177 2177 2267 2177 2177 2267 2201 2201 2292 2202 2202 2293 2177 2177 2267 2202 2202 2293 2178 2178 2268 2178 2178 2268 2202 2202 2293 2203 2203 2294 2178 2178 2268 2203 2203 2294 2179 2179 2269 2179 2179 2269 2203 2203 2294 2204 2204 2295 2179 2179 2269 2204 2204 2295 2180 2180 2270 2180 2180 2270 2204 2204 2295 2205 2205 2296 2180 2180 2270 2205 2205 2296 2181 2181 2271 2181 2181 2271 2205 2205 2296 2206 2206 2297 2181 2181 2271 2206 2206 2297 2182 2182 2272 2182 2182 2272 2206 2206 2297 2207 2207 2298 2182 2182 2272 2207 2207 2298 2183 2183 2273 2183 2183 2273 2207 2207 2298 2184 2184 2299 2183 2183 2273 2184 2184 2299 2160 2160 2274 2184 2184 2275 2208 2208 2300 2209 2209 2301 2184 2184 2275 2209 2209 2301 2185 2185 2276 2185 2185 2276 2209 2209 2301 2210 2210 2302 2185 2185 2276 2210 2210 2302 2186 2186 2277 2186 2186 2277 2210 2210 2302 2211 2211 2303 2186 2186 2277 2211 2211 2303 2187 2187 2278 2187 2187 2278 2211 2211 2303 2212 2212 2304 2187 2187 2278 2212 2212 2304 2188 2188 2279 2188 2188 2279 2212 2212 2304 2213 2213 2305 2188 2188 2279 2213 2213 2305 2189 2189 2280 2189 2189 2280 2213 2213 2305 2214 2214 2306 2189 2189 2280 2214 2214 2306 2190 2190 2281 2190 2190 2281 2214 2214 2306 2215 2215 2307 2190 2190 2281 2215 2215 2307 2191 2191 2282 2191 2191 2282 2215 2215 2307 2216 2216 2308 2191 2191 2282 2216 2216 2308 2192 2192 2283 2192 2192 2283 2216 2216 2308 2217 2217 2309 2192 2192 2283 2217 2217 2309 2193 2193 2284 2193 2193 2284 2217 2217 2309 2218 2218 2310 2193 2193 2284 2218 2218 2310 2194 2194 2285 2194 2194 2285 2218 2218 2310 2219 2219 2311 2194 2194 2285 2219 2219 2311 2195 2195 2286 2195 2195 2286 2219 2219 2311 2220 2220 2312 2195 2195 2286 2220 2220 2312 2196 2196 2287 2196 2196 2287 2220 2220 2312 2221 2221 2313 2196 2196 2287 2221 2221 2313 2197 2197 2288 2197 2197 2288 2221 2221 2313 2222 2222 2314 2197 2197 2288 2222 2222 2314 2198 2198 2289 2198 2198 2289 2222 2222 2314 2223 2223 2315 2198 2198 2289 2223 2223 2315 2199 2199 2290 2199 2199 2290 2223 2223 2315 2224 2224 2316 2199 2199 2290 2224 2224 2316 2200 2200 2291 2200 2200 2291 2224 2224 2316 2225 2225 2317 2200 2200 2291 2225 2225 2317 2201 2201 2292 2201 2201 2292 2225 2225 2317 2226 2226 2318 2201 2201 2292 2226 2226 2318 2202 2202 2293 2202 2202 2293 2226 2226 2318 2227 2227 2319 2202 2202 2293 2227 2227 2319 2203 2203 2294 2203 2203 2294 2227 2227 2319 2228 2228 2320 2203 2203 2294 2228 2228 2320 2204 2204 2295 2204 2204 2295 2228 2228 2320 2229 2229 2321 2204 2204 2295 2229 2229 2321 2205 2205 2296 2205 2205 2296 2229 2229 2321 2230 2230 2322 2205 2205 2296 2230 2230 2322 2206 2206 2297 2206 2206 2297 2230 2230 2322 2231 2231 2323 2206 2206 2297 2231 2231 2323 2207 2207 2298 2207 2207 2298 2231 2231 2323 2208 2208 2324 2207 2207 2298 2208 2208 2324 2184 2184 2299 2208 2208 2300 2232 2232 2325 2233 2233 2326 2208 2208 2300 2233 2233 2326 2209 2209 2301 2209 2209 2301 2233 2233 2326 2234 2234 2327 2209 2209 2301 2234 2234 2327 2210 2210 2302 2210 2210 2302 2234 2234 2327 2235 2235 2328 2210 2210 2302 2235 2235 2328 2211 2211 2303 2211 2211 2303 2235 2235 2328 2236 2236 2329 2211 2211 2303 2236 2236 2329 2212 2212 2304 2212 2212 2304 2236 2236 2329 2237 2237 2330 2212 2212 2304 2237 2237 2330 2213 2213 2305 2213 2213 2305 2237 2237 2330 2238 2238 2331 2213 2213 2305 2238 2238 2331 2214 2214 2306 2214 2214 2306 2238 2238 2331 2239 2239 2332 2214 2214 2306 2239 2239 2332 2215 2215 2307 2215 2215 2307 2239 2239 2332 2240 2240 2333 2215 2215 2307 2240 2240 2333 2216 2216 2308 2216 2216 2308 2240 2240 2333 2241 2241 2334 2216 2216 2308 2241 2241 2334 2217 2217 2309 2217 2217 2309 2241 2241 2334 2242 2242 2335 2217 2217 2309 2242 2242 2335 2218 2218 2310 2218 2218 2310 2242 2242 2335 2243 2243 2336 2218 2218 2310 2243 2243 2336 2219 2219 2311 2219 2219 2311 2243 2243 2336 2244 2244 2337 2219 2219 2311 2244 2244 2337 2220 2220 2312 2220 2220 2312 2244 2244 2337 2245 2245 2338 2220 2220 2312 2245 2245 2338 2221 2221 2313 2221 2221 2313 2245 2245 2338 2246 2246 2339 2221 2221 2313 2246 2246 2339 2222 2222 2314 2222 2222 2314 2246 2246 2339 2247 2247 2340 2222 2222 2314 2247 2247 2340 2223 2223 2315 2223 2223 2315 2247 2247 2340 2248 2248 2341 2223 2223 2315 2248 2248 2341 2224 2224 2316 2224 2224 2316 2248 2248 2341 2249 2249 2342 2224 2224 2316 2249 2249 2342 2225 2225 2317 2225 2225 2317 2249 2249 2342 2250 2250 2343 2225 2225 2317 2250 2250 2343 2226 2226 2318 2226 2226 2318 2250 2250 2343 2251 2251 2344 2226 2226 2318 2251 2251 2344 2227 2227 2319 2227 2227 2319 2251 2251 2344 2252 2252 2345 2227 2227 2319 2252 2252 2345 2228 2228 2320 2228 2228 2320 2252 2252 2345 2253 2253 2346 2228 2228 2320 2253 2253 2346 2229 2229 2321 2229 2229 2321 2253 2253 2346 2254 2254 2347 2229 2229 2321 2254 2254 2347 2230 2230 2322 2230 2230 2322 2254 2254 2347 2255 2255 2348 2230 2230 2322 2255 2255 2348 2231 2231 2323 2231 2231 2323 2255 2255 2348 2232 2232 2349 2231 2231 2323 2232 2232 2349 2208 2208 2324 2232 2232 2325 2256 2256 2350 2257 2257 2351 2232 2232 2325 2257 2257 2351 2233 2233 2326 2233 2233 2326 2257 2257 2351 2258 2258 2352 2233 2233 2326 2258 2258 2352 2234 2234 2327 2234 2234 2327 2258 2258 2352 2259 2259 2353 2234 2234 2327 2259 2259 2353 2235 2235 2328 2235 2235 2328 2259 2259 2353 2260 2260 2354 2235 2235 2328 2260 2260 2354 2236 2236 2329 2236 2236 2329 2260 2260 2354 2261 2261 2355 2236 2236 2329 2261 2261 2355 2237 2237 2330 2237 2237 2330 2261 2261 2355 2262 2262 2356 2237 2237 2330 2262 2262 2356 2238 2238 2331 2238 2238 2331 2262 2262 2356 2263 2263 2357 2238 2238 2331 2263 2263 2357 2239 2239 2332 2239 2239 2332 2263 2263 2357 2264 2264 2358 2239 2239 2332 2264 2264 2358 2240 2240 2333 2240 2240 2333 2264 2264 2358 2265 2265 2359 2240 2240 2333 2265 2265 2359 2241 2241 2334 2241 2241 2334 2265 2265 2359 2266 2266 2360 2241 2241 2334 2266 2266 2360 2242 2242 2335 2242 2242 2335 2266 2266 2360 2267 2267 2361 2242 2242 2335 2267 2267 2361 2243 2243 2336 2243 2243 2336 2267 2267 2361 2268 2268 2362 2243 2243 2336 2268 2268 2362 2244 2244 2337 2244 2244 2337 2268 2268 2362 2269 2269 2363 2244 2244 2337 2269 2269 2363 2245 2245 2338 2245 2245 2338 2269 2269 2363 2270 2270 2364 2245 2245 2338 2270 2270 2364 2246 2246 2339 2246 2246 2339 2270 2270 2364 2271 2271 2365 2246 2246 2339 2271 2271 2365 2247 2247 2340 2247 2247 2340 2271 2271 2365 2272 2272 2366 2247 2247 2340 2272 2272 2366 2248 2248 2341 2248 2248 2341 2272 2272 2366 2273 2273 2367 2248 2248 2341 2273 2273 2367 2249 2249 2342 2249 2249 2342 2273 2273 2367 2274 2274 2368 2249 2249 2342 2274 2274 2368 2250 2250 2343 2250 2250 2343 2274 2274 2368 2275 2275 2369 2250 2250 2343 2275 2275 2369 2251 2251 2344 2251 2251 2344 2275 2275 2369 2276 2276 2370 2251 2251 2344 2276 2276 2370 2252 2252 2345 2252 2252 2345 2276 2276 2370 2277 2277 2371 2252 2252 2345 2277 2277 2371 2253 2253 2346 2253 2253 2346 2277 2277 2371 2278 2278 2372 2253 2253 2346 2278 2278 2372 2254 2254 2347 2254 2254 2347 2278 2278 2372 2279 2279 2373 2254 2254 2347 2279 2279 2373 2255 2255 2348 2255 2255 2348 2279 2279 2373 2256 2256 2374 2255 2255 2348 2256 2256 2374 2232 2232 2349 2256 2256 2350 2280 2280 2375 2281 2281 2376 2256 2256 2350 2281 2281 2376 2257 2257 2351 2257 2257 2351 2281 2281 2376 2282 2282 2377 2257 2257 2351 2282 2282 2377 2258 2258 2352 2258 2258 2352 2282 2282 2377 2283 2283 2378 2258 2258 2352 2283 2283 2378 2259 2259 2353 2259 2259 2353 2283 2283 2378 2284 2284 2379 2259 2259 2353 2284 2284 2379 2260 2260 2354 2260 2260 2354 2284 2284 2379 2285 2285 2380 2260 2260 2354 2285 2285 2380 2261 2261 2355 2261 2261 2355 2285 2285 2380 2286 2286 2381 2261 2261 2355 2286 2286 2381 2262 2262 2356 2262 2262 2356 2286 2286 2381 2287 2287 2382 2262 2262 2356 2287 2287 2382 2263 2263 2357 2263 2263 2357 2287 2287 2382 2288 2288 2383 2263 2263 2357 2288 2288 2383 2264 2264 2358 2264 2264 2358 2288 2288 2383 2289 2289 2384 2264 2264 2358 2289 2289 2384 2265 2265 2359 2265 2265 2359 2289 2289 2384 2290 2290 2385 2265 2265 2359 2290 2290 2385 2266 2266 2360 2266 2266 2360 2290 2290 2385 2291 2291 2386 2266 2266 2360 2291 2291 2386 2267 2267 2361 2267 2267 2361 2291 2291 2386 2292 2292 2387 2267 2267 2361 2292 2292 2387 2268 2268 2362 2268 2268 2362 2292 2292 2387 2293 2293 2388 2268 2268 2362 2293 2293 2388 2269 2269 2363 2269 2269 2363 2293 2293 2388 2294 2294 2389 2269 2269 2363 2294 2294 2389 2270 2270 2364 2270 2270 2364 2294 2294 2389 2295 2295 2390 2270 2270 2364 2295 2295 2390 2271 2271 2365 2271 2271 2365 2295 2295 2390 2296 2296 2391 2271 2271 2365 2296 2296 2391 2272 2272 2366 2272 2272 2366 2296 2296 2391 2297 2297 2392 2272 2272 2366 2297 2297 2392 2273 2273 2367 2273 2273 2367 2297 2297 2392 2298 2298 2393 2273 2273 2367 2298 2298 2393 2274 2274 2368 2274 2274 2368 2298 2298 2393 2299 2299 2394 2274 2274 2368 2299 2299 2394 2275 2275 2369 2275 2275 2369 2299 2299 2394 2300 2300 2395 2275 2275 2369 2300 2300 2395 2276 2276 2370 2276 2276 2370 2300 2300 2395 2301 2301 2396 2276 2276 2370 2301 2301 2396 2277 2277 2371 2277 2277 2371 2301 2301 2396 2302 2302 2397 2277 2277 2371 2302 2302 2397 2278 2278 2372 2278 2278 2372 2302 2302 2397 2303 2303 2398 2278 2278 2372 2303 2303 2398 2279 2279 2373 2279 2279 2373 2303 2303 2398 2280 2280 2399 2279 2279 2373 2280 2280 2399 2256 2256 2374 2280 2280 2375 2304 2304 2400 2305 2305 2401 2280 2280 2375 2305 2305 2401 2281 2281 2376 2281 2281 2376 2305 2305 2401 2306 2306 2402 2281 2281 2376 2306 2306 2402 2282 2282 2377 2282 2282 2377 2306 2306 2402 2307 2307 2403 2282 2282 2377 2307 2307 2403 2283 2283 2378 2283 2283 2378 2307 2307 2403 2308 2308 2404 2283 2283 2378 2308 2308 2404 2284 2284 2379 2284 2284 2379 2308 2308 2404 2309 2309 2405 2284 2284 2379 2309 2309 2405 2285 2285 2380 2285 2285 2380 2309 2309 2405 2310 2310 2406 2285 2285 2380 2310 2310 2406 2286 2286 2381 2286 2286 2381 2310 2310 2406 2311 2311 2407 2286 2286 2381 2311 2311 2407 2287 2287 2382 2287 2287 2382 2311 2311 2407 2312 2312 2408 2287 2287 2382 2312 2312 2408 2288 2288 2383 2288 2288 2383 2312 2312 2408 2313 2313 2409 2288 2288 2383 2313 2313 2409 2289 2289 2384 2289 2289 2384 2313 2313 2409 2314 2314 2410 2289 2289 2384 2314 2314 2410 2290 2290 2385 2290 2290 2385 2314 2314 2410 2315 2315 2411 2290 2290 2385 2315 2315 2411 2291 2291 2386 2291 2291 2386 2315 2315 2411 2316 2316 2412 2291 2291 2386 2316 2316 2412 2292 2292 2387 2292 2292 2387 2316 2316 2412 2317 2317 2413 2292 2292 2387 2317 2317 2413 2293 2293 2388 2293 2293 2388 2317 2317 2413 2318 2318 2414 2293 2293 2388 2318 2318 2414 2294 2294 2389 2294 2294 2389 2318 2318 2414 2319 2319 2415 2294 2294 2389 2319 2319 2415 2295 2295 2390 2295 2295 2390 2319 2319 2415 2320 2320 2416 2295 2295 2390 2320 2320 2416 2296 2296 2391 2296 2296 2391 2320 2320 2416 2321 2321 2417 2296 2296 2391 2321 2321 2417 2297 2297 2392 2297 2297 2392 2321 2321 2417 2322 2322 2418 2297 2297 2392 2322 2322 2418 2298 2298 2393 2298 2298 2393 2322 2322 2418 2323 2323 2419 2298 2298 2393 2323 2323 2419 2299 2299 2394 2299 2299 2394 2323 2323 2419 2324 2324 2420 2299 2299 2394 2324 2324 2420 2300 2300 2395 2300 2300 2395 2324 2324 2420 2325 2325 2421 2300 2300 2395 2325 2325 2421 2301 2301 2396 2301 2301 2396 2325 2325 2421 2326 2326 2422 2301 2301 2396 2326 2326 2422 2302 2302 2397 2302 2302 2397 2326 2326 2422 2327 2327 2423 2302 2302 2397 2327 2327 2423 2303 2303 2398 2303 2303 2398 2327 2327 2423 2304 2304 2424 2303 2303 2398 2304 2304 2424 2280 2280 2399 2304 2304 2400 2328 2328 2425 2329 2329 2426 2304 2304 2400 2329 2329 2426 2305 2305 2401 2305 2305 2401 2329 2329 2426 2330 2330 2427 2305 2305 2401 2330 2330 2427 2306 2306 2402 2306 2306 2402 2330 2330 2427 2331 2331 2428 2306 2306 2402 2331 2331 2428 2307 2307 2403 2307 2307 2403 2331 2331 2428 2332 2332 2429 2307 2307 2403 2332 2332 2429 2308 2308 2404 2308 2308 2404 2332 2332 2429 2333 2333 2430 2308 2308 2404 2333 2333 2430 2309 2309 2405 2309 2309 2405 2333 2333 2430 2334 2334 2431 2309 2309 2405 2334 2334 2431 2310 2310 2406 2310 2310 2406 2334 2334 2431 2335 2335 2432 2310 2310 2406 2335 2335 2432 2311 2311 2407 2311 2311 2407 2335 2335 2432 2336 2336 2433 2311 2311 2407 2336 2336 2433 2312 2312 2408 2312 2312 2408 2336 2336 2433 2337 2337 2434 2312 2312 2408 2337 2337 2434 2313 2313 2409 2313 2313 2409 2337 2337 2434 2338 2338 2435 2313 2313 2409 2338 2338 2435 2314 2314 2410 2314 2314 2410 2338 2338 2435 2339 2339 2436 2314 2314 2410 2339 2339 2436 2315 2315 2411 2315 2315 2411 2339 2339 2436 2340 2340 2437 2315 2315 2411 2340 2340 2437 2316 2316 2412 2316 2316 2412 2340 2340 2437 2341 2341 2438 2316 2316 2412 2341 2341 2438 2317 2317 2413 2317 2317 2413 2341 2341 2438 2342 2342 2439 2317 2317 2413 2342 2342 2439 2318 2318 2414 2318 2318 2414 2342 2342 2439 2343 2343 2440 2318 2318 2414 2343 2343 2440 2319 2319 2415 2319 2319 2415 2343 2343 2440 2344 2344 2441 2319 2319 2415 2344 2344 2441 2320 2320 2416 2320 2320 2416 2344 2344 2441 2345 2345 2442 2320 2320 2416 2345 2345 2442 2321 2321 2417 2321 2321 2417 2345 2345 2442 2346 2346 2443 2321 2321 2417 2346 2346 2443 2322 2322 2418 2322 2322 2418 2346 2346 2443 2347 2347 2444 2322 2322 2418 2347 2347 2444 2323 2323 2419 2323 2323 2419 2347 2347 2444 2348 2348 2445 2323 2323 2419 2348 2348 2445 2324 2324 2420 2324 2324 2420 2348 2348 2445 2349 2349 2446 2324 2324 2420 2349 2349 2446 2325 2325 2421 2325 2325 2421 2349 2349 2446 2350 2350 2447 2325 2325 2421 2350 2350 2447 2326 2326 2422 2326 2326 2422 2350 2350 2447 2351 2351 2448 2326 2326 2422 2351 2351 2448 2327 2327 2423 2327 2327 2423 2351 2351 2448 2328 2328 2449 2327 2327 2423 2328 2328 2449 2304 2304 2424 2328 2328 2425 2352 2352 2450 2353 2353 2451 2328 2328 2425 2353 2353 2451 2329 2329 2426 2329 2329 2426 2353 2353 2451 2354 2354 2452 2329 2329 2426 2354 2354 2452 2330 2330 2427 2330 2330 2427 2354 2354 2452 2355 2355 2453 2330 2330 2427 2355 2355 2453 2331 2331 2428 2331 2331 2428 2355 2355 2453 2356 2356 2454 2331 2331 2428 2356 2356 2454 2332 2332 2429 2332 2332 2429 2356 2356 2454 2357 2357 2455 2332 2332 2429 2357 2357 2455 2333 2333 2430 2333 2333 2430 2357 2357 2455 2358 2358 2456 2333 2333 2430 2358 2358 2456 2334 2334 2431 2334 2334 2431 2358 2358 2456 2359 2359 2457 2334 2334 2431 2359 2359 2457 2335 2335 2432 2335 2335 2432 2359 2359 2457 2360 2360 2458 2335 2335 2432 2360 2360 2458 2336 2336 2433 2336 2336 2433 2360 2360 2458 2361 2361 2459 2336 2336 2433 2361 2361 2459 2337 2337 2434 2337 2337 2434 2361 2361 2459 2362 2362 2460 2337 2337 2434 2362 2362 2460 2338 2338 2435 2338 2338 2435 2362 2362 2460 2363 2363 2461 2338 2338 2435 2363 2363 2461 2339 2339 2436 2339 2339 2436 2363 2363 2461 2364 2364 2462 2339 2339 2436 2364 2364 2462 2340 2340 2437 2340 2340 2437 2364 2364 2462 2365 2365 2463 2340 2340 2437 2365 2365 2463 2341 2341 2438 2341 2341 2438 2365 2365 2463 2366 2366 2464 2341 2341 2438 2366 2366 2464 2342 2342 2439 2342 2342 2439 2366 2366 2464 2367 2367 2465 2342 2342 2439 2367 2367 2465 2343 2343 2440 2343 2343 2440 2367 2367 2465 2368 2368 2466 2343 2343 2440 2368 2368 2466 2344 2344 2441 2344 2344 2441 2368 2368 2466 2369 2369 2467 2344 2344 2441 2369 2369 2467 2345 2345 2442 2345 2345 2442 2369 2369 2467 2370 2370 2468 2345 2345 2442 2370 2370 2468 2346 2346 2443 2346 2346 2443 2370 2370 2468 2371 2371 2469 2346 2346 2443 2371 2371 2469 2347 2347 2444 2347 2347 2444 2371 2371 2469 2372 2372 2470 2347 2347 2444 2372 2372 2470 2348 2348 2445 2348 2348 2445 2372 2372 2470 2373 2373 2471 2348 2348 2445 2373 2373 2471 2349 2349 2446 2349 2349 2446 2373 2373 2471 2374 2374 2472 2349 2349 2446 2374 2374 2472 2350 2350 2447 2350 2350 2447 2374 2374 2472 2375 2375 2473 2350 2350 2447 2375 2375 2473 2351 2351 2448 2351 2351 2448 2375 2375 2473 2352 2352 2474 2351 2351 2448 2352 2352 2474 2328 2328 2449 2352 2352 2450 2376 2376 2475 2377 2377 2476 2352 2352 2450 2377 2377 2476 2353 2353 2451 2353 2353 2451 2377 2377 2476 2378 2378 2477 2353 2353 2451 2378 2378 2477 2354 2354 2452 2354 2354 2452 2378 2378 2477 2379 2379 2478 2354 2354 2452 2379 2379 2478 2355 2355 2453 2355 2355 2453 2379 2379 2478 2380 2380 2479 2355 2355 2453 2380 2380 2479 2356 2356 2454 2356 2356 2454 2380 2380 2479 2381 2381 2480 2356 2356 2454 2381 2381 2480 2357 2357 2455 2357 2357 2455 2381 2381 2480 2382 2382 2481 2357 2357 2455 2382 2382 2481 2358 2358 2456 2358 2358 2456 2382 2382 2481 2383 2383 2482 2358 2358 2456 2383 2383 2482 2359 2359 2457 2359 2359 2457 2383 2383 2482 2384 2384 2483 2359 2359 2457 2384 2384 2483 2360 2360 2458 2360 2360 2458 2384 2384 2483 2385 2385 2484 2360 2360 2458 2385 2385 2484 2361 2361 2459 2361 2361 2459 2385 2385 2484 2386 2386 2485 2361 2361 2459 2386 2386 2485 2362 2362 2460 2362 2362 2460 2386 2386 2485 2387 2387 2486 2362 2362 2460 2387 2387 2486 2363 2363 2461 2363 2363 2461 2387 2387 2486 2388 2388 2487 2363 2363 2461 2388 2388 2487 2364 2364 2462 2364 2364 2462 2388 2388 2487 2389 2389 2488 2364 2364 2462 2389 2389 2488 2365 2365 2463 2365 2365 2463 2389 2389 2488 2390 2390 2489 2365 2365 2463 2390 2390 2489 2366 2366 2464 2366 2366 2464 2390 2390 2489 2391 2391 2490 2366 2366 2464 2391 2391 2490 2367 2367 2465 2367 2367 2465 2391 2391 2490 2392 2392 2491 2367 2367 2465 2392 2392 2491 2368 2368 2466 2368 2368 2466 2392 2392 2491 2393 2393 2492 2368 2368 2466 2393 2393 2492 2369 2369 2467 2369 2369 2467 2393 2393 2492 2394 2394 2493 2369 2369 2467 2394 2394 2493 2370 2370 2468 2370 2370 2468 2394 2394 2493 2395 2395 2494 2370 2370 2468 2395 2395 2494 2371 2371 2469 2371 2371 2469 2395 2395 2494 2396 2396 2495 2371 2371 2469 2396 2396 2495 2372 2372 2470 2372 2372 2470 2396 2396 2495 2397 2397 2496 2372 2372 2470 2397 2397 2496 2373 2373 2471 2373 2373 2471 2397 2397 2496 2398 2398 2497 2373 2373 2471 2398 2398 2497 2374 2374 2472 2374 2374 2472 2398 2398 2497 2399 2399 2498 2374 2374 2472 2399 2399 2498 2375 2375 2473 2375 2375 2473 2399 2399 2498 2376 2376 2499 2375 2375 2473 2376 2376 2499 2352 2352 2474 2376 2376 2475 2400 2400 2500 2401 2401 2501 2376 2376 2475 2401 2401 2501 2377 2377 2476 2377 2377 2476 2401 2401 2501 2402 2402 2502 2377 2377 2476 2402 2402 2502 2378 2378 2477 2378 2378 2477 2402 2402 2502 2403 2403 2503 2378 2378 2477 2403 2403 2503 2379 2379 2478 2379 2379 2478 2403 2403 2503 2404 2404 2504 2379 2379 2478 2404 2404 2504 2380 2380 2479 2380 2380 2479 2404 2404 2504 2405 2405 2505 2380 2380 2479 2405 2405 2505 2381 2381 2480 2381 2381 2480 2405 2405 2505 2406 2406 2506 2381 2381 2480 2406 2406 2506 2382 2382 2481 2382 2382 2481 2406 2406 2506 2407 2407 2507 2382 2382 2481 2407 2407 2507 2383 2383 2482 2383 2383 2482 2407 2407 2507 2408 2408 2508 2383 2383 2482 2408 2408 2508 2384 2384 2483 2384 2384 2483 2408 2408 2508 2409 2409 2509 2384 2384 2483 2409 2409 2509 2385 2385 2484 2385 2385 2484 2409 2409 2509 2410 2410 2510 2385 2385 2484 2410 2410 2510 2386 2386 2485 2386 2386 2485 2410 2410 2510 2411 2411 2511 2386 2386 2485 2411 2411 2511 2387 2387 2486 2387 2387 2486 2411 2411 2511 2412 2412 2512 2387 2387 2486 2412 2412 2512 2388 2388 2487 2388 2388 2487 2412 2412 2512 2413 2413 2513 2388 2388 2487 2413 2413 2513 2389 2389 2488 2389 2389 2488 2413 2413 2513 2414 2414 2514 2389 2389 2488 2414 2414 2514 2390 2390 2489 2390 2390 2489 2414 2414 2514 2415 2415 2515 2390 2390 2489 2415 2415 2515 2391 2391 2490 2391 2391 2490 2415 2415 2515 2416 2416 2516 2391 2391 2490 2416 2416 2516 2392 2392 2491 2392 2392 2491 2416 2416 2516 2417 2417 2517 2392 2392 2491 2417 2417 2517 2393 2393 2492 2393 2393 2492 2417 2417 2517 2418 2418 2518 2393 2393 2492 2418 2418 2518 2394 2394 2493 2394 2394 2493 2418 2418 2518 2419 2419 2519 2394 2394 2493 2419 2419 2519 2395 2395 2494 2395 2395 2494 2419 2419 2519 2420 2420 2520 2395 2395 2494 2420 2420 2520 2396 2396 2495 2396 2396 2495 2420 2420 2520 2421 2421 2521 2396 2396 2495 2421 2421 2521 2397 2397 2496 2397 2397 2496 2421 2421 2521 2422 2422 2522 2397 2397 2496 2422 2422 2522 2398 2398 2497 2398 2398 2497 2422 2422 2522 2423 2423 2523 2398 2398 2497 2423 2423 2523 2399 2399 2498 2399 2399 2498 2423 2423 2523 2400 2400 2524 2399 2399 2498 2400 2400 2524 2376 2376 2499 2400 2400 2500 2424 2424 2525 2425 2425 2526 2400 2400 2500 2425 2425 2526 2401 2401 2501 2401 2401 2501 2425 2425 2526 2426 2426 2527 2401 2401 2501 2426 2426 2527 2402 2402 2502 2402 2402 2502 2426 2426 2527 2427 2427 2528 2402 2402 2502 2427 2427 2528 2403 2403 2503 2403 2403 2503 2427 2427 2528 2428 2428 2529 2403 2403 2503 2428 2428 2529 2404 2404 2504 2404 2404 2504 2428 2428 2529 2429 2429 2530 2404 2404 2504 2429 2429 2530 2405 2405 2505 2405 2405 2505 2429 2429 2530 2430 2430 2531 2405 2405 2505 2430 2430 2531 2406 2406 2506 2406 2406 2506 2430 2430 2531 2431 2431 2532 2406 2406 2506 2431 2431 2532 2407 2407 2507 2407 2407 2507 2431 2431 2532 2432 2432 2533 2407 2407 2507 2432 2432 2533 2408 2408 2508 2408 2408 2508 2432 2432 2533 2433 2433 2534 2408 2408 2508 2433 2433 2534 2409 2409 2509 2409 2409 2509 2433 2433 2534 2434 2434 2535 2409 2409 2509 2434 2434 2535 2410 2410 2510 2410 2410 2510 2434 2434 2535 2435 2435 2536 2410 2410 2510 2435 2435 2536 2411 2411 2511 2411 2411 2511 2435 2435 2536 2436 2436 2537 2411 2411 2511 2436 2436 2537 2412 2412 2512 2412 2412 2512 2436 2436 2537 2437 2437 2538 2412 2412 2512 2437 2437 2538 2413 2413 2513 2413 2413 2513 2437 2437 2538 2438 2438 2539 2413 2413 2513 2438 2438 2539 2414 2414 2514 2414 2414 2514 2438 2438 2539 2439 2439 2540 2414 2414 2514 2439 2439 2540 2415 2415 2515 2415 2415 2515 2439 2439 2540 2440 2440 2541 2415 2415 2515 2440 2440 2541 2416 2416 2516 2416 2416 2516 2440 2440 2541 2441 2441 2542 2416 2416 2516 2441 2441 2542 2417 2417 2517 2417 2417 2517 2441 2441 2542 2442 2442 2543 2417 2417 2517 2442 2442 2543 2418 2418 2518 2418 2418 2518 2442 2442 2543 2443 2443 2544 2418 2418 2518 2443 2443 2544 2419 2419 2519 2419 2419 2519 2443 2443 2544 2444 2444 2545 2419 2419 2519 2444 2444 2545 2420 2420 2520 2420 2420 2520 2444 2444 2545 2445 2445 2546 2420 2420 2520 2445 2445 2546 2421 2421 2521 2421 2421 2521 2445 2445 2546 2446 2446 2547 2421 2421 2521 2446 2446 2547 2422 2422 2522 2422 2422 2522 2446 2446 2547 2447 2447 2548 2422 2422 2522 2447 2447 2548 2423 2423 2523 2423 2423 2523 2447 2447 2548 2424 2424 2549 2423 2423 2523 2424 2424 2549 2400 2400 2524 2424 2424 2525 2448 2448 2550 2449 2449 2551 2424 2424 2525 2449 2449 2551 2425 2425 2526 2425 2425 2526 2449 2449 2551 2450 2450 2552 2425 2425 2526 2450 2450 2552 2426 2426 2527 2426 2426 2527 2450 2450 2552 2451 2451 2553 2426 2426 2527 2451 2451 2553 2427 2427 2528 2427 2427 2528 2451 2451 2553 2452 2452 2554 2427 2427 2528 2452 2452 2554 2428 2428 2529 2428 2428 2529 2452 2452 2554 2453 2453 2555 2428 2428 2529 2453 2453 2555 2429 2429 2530 2429 2429 2530 2453 2453 2555 2454 2454 2556 2429 2429 2530 2454 2454 2556 2430 2430 2531 2430 2430 2531 2454 2454 2556 2455 2455 2557 2430 2430 2531 2455 2455 2557 2431 2431 2532 2431 2431 2532 2455 2455 2557 2456 2456 2558 2431 2431 2532 2456 2456 2558 2432 2432 2533 2432 2432 2533 2456 2456 2558 2457 2457 2559 2432 2432 2533 2457 2457 2559 2433 2433 2534 2433 2433 2534 2457 2457 2559 2458 2458 2560 2433 2433 2534 2458 2458 2560 2434 2434 2535 2434 2434 2535 2458 2458 2560 2459 2459 2561 2434 2434 2535 2459 2459 2561 2435 2435 2536 2435 2435 2536 2459 2459 2561 2460 2460 2562 2435 2435 2536 2460 2460 2562 2436 2436 2537 2436 2436 2537 2460 2460 2562 2461 2461 2563 2436 2436 2537 2461 2461 2563 2437 2437 2538 2437 2437 2538 2461 2461 2563 2462 2462 2564 2437 2437 2538 2462 2462 2564 2438 2438 2539 2438 2438 2539 2462 2462 2564 2463 2463 2565 2438 2438 2539 2463 2463 2565 2439 2439 2540 2439 2439 2540 2463 2463 2565 2464 2464 2566 2439 2439 2540 2464 2464 2566 2440 2440 2541 2440 2440 2541 2464 2464 2566 2465 2465 2567 2440 2440 2541 2465 2465 2567 2441 2441 2542 2441 2441 2542 2465 2465 2567 2466 2466 2568 2441 2441 2542 2466 2466 2568 2442 2442 2543 2442 2442 2543 2466 2466 2568 2467 2467 2569 2442 2442 2543 2467 2467 2569 2443 2443 2544 2443 2443 2544 2467 2467 2569 2468 2468 2570 2443 2443 2544 2468 2468 2570 2444 2444 2545 2444 2444 2545 2468 2468 2570 2469 2469 2571 2444 2444 2545 2469 2469 2571 2445 2445 2546 2445 2445 2546 2469 2469 2571 2470 2470 2572 2445 2445 2546 2470 2470 2572 2446 2446 2547 2446 2446 2547 2470 2470 2572 2471 2471 2573 2446 2446 2547 2471 2471 2573 2447 2447 2548 2447 2447 2548 2471 2471 2573 2448 2448 2574 2447 2447 2548 2448 2448 2574 2424 2424 2549 2448 2448 2550 2472 2472 2575 2473 2473 2576 2448 2448 2550 2473 2473 2576 2449 2449 2551 2449 2449 2551 2473 2473 2576 2474 2474 2577 2449 2449 2551 2474 2474 2577 2450 2450 2552 2450 2450 2552 2474 2474 2577 2475 2475 2578 2450 2450 2552 2475 2475 2578 2451 2451 2553 2451 2451 2553 2475 2475 2578 2476 2476 2579 2451 2451 2553 2476 2476 2579 2452 2452 2554 2452 2452 2554 2476 2476 2579 2477 2477 2580 2452 2452 2554 2477 2477 2580 2453 2453 2555 2453 2453 2555 2477 2477 2580 2478 2478 2581 2453 2453 2555 2478 2478 2581 2454 2454 2556 2454 2454 2556 2478 2478 2581 2479 2479 2582 2454 2454 2556 2479 2479 2582 2455 2455 2557 2455 2455 2557 2479 2479 2582 2480 2480 2583 2455 2455 2557 2480 2480 2583 2456 2456 2558 2456 2456 2558 2480 2480 2583 2481 2481 2584 2456 2456 2558 2481 2481 2584 2457 2457 2559 2457 2457 2559 2481 2481 2584 2482 2482 2585 2457 2457 2559 2482 2482 2585 2458 2458 2560 2458 2458 2560 2482 2482 2585 2483 2483 2586 2458 2458 2560 2483 2483 2586 2459 2459 2561 2459 2459 2561 2483 2483 2586 2484 2484 2587 2459 2459 2561 2484 2484 2587 2460 2460 2562 2460 2460 2562 2484 2484 2587 2485 2485 2588 2460 2460 2562 2485 2485 2588 2461 2461 2563 2461 2461 2563 2485 2485 2588 2486 2486 2589 2461 2461 2563 2486 2486 2589 2462 2462 2564 2462 2462 2564 2486 2486 2589 2487 2487 2590 2462 2462 2564 2487 2487 2590 2463 2463 2565 2463 2463 2565 2487 2487 2590 2488 2488 2591 2463 2463 2565 2488 2488 2591 2464 2464 2566 2464 2464 2566 2488 2488 2591 2489 2489 2592 2464 2464 2566 2489 2489 2592 2465 2465 2567 2465 2465 2567 2489 2489 2592 2490 2490 2593 2465 2465 2567 2490 2490 2593 2466 2466 2568 2466 2466 2568 2490 2490 2593 2491 2491 2594 2466 2466 2568 2491 2491 2594 2467 2467 2569 2467 2467 2569 2491 2491 2594 2492 2492 2595 2467 2467 2569 2492 2492 2595 2468 2468 2570 2468 2468 2570 2492 2492 2595 2493 2493 2596 2468 2468 2570 2493 2493 2596 2469 2469 2571 2469 2469 2571 2493 2493 2596 2494 2494 2597 2469 2469 2571 2494 2494 2597 2470 2470 2572 2470 2470 2572 2494 2494 2597 2495 2495 2598 2470 2470 2572 2495 2495 2598 2471 2471 2573 2471 2471 2573 2495 2495 2598 2472 2472 2599 2471 2471 2573 2472 2472 2599 2448 2448 2574 2472 2472 2575 2496 2496 2600 2497 2497 2601 2472 2472 2575 2497 2497 2601 2473 2473 2576 2473 2473 2576 2497 2497 2601 2498 2498 2602 2473 2473 2576 2498 2498 2602 2474 2474 2577 2474 2474 2577 2498 2498 2602 2499 2499 2603 2474 2474 2577 2499 2499 2603 2475 2475 2578 2475 2475 2578 2499 2499 2603 2500 2500 2604 2475 2475 2578 2500 2500 2604 2476 2476 2579 2476 2476 2579 2500 2500 2604 2501 2501 2605 2476 2476 2579 2501 2501 2605 2477 2477 2580 2477 2477 2580 2501 2501 2605 2502 2502 2606 2477 2477 2580 2502 2502 2606 2478 2478 2581 2478 2478 2581 2502 2502 2606 2503 2503 2607 2478 2478 2581 2503 2503 2607 2479 2479 2582 2479 2479 2582 2503 2503 2607 2504 2504 2608 2479 2479 2582 2504 2504 2608 2480 2480 2583 2480 2480 2583 2504 2504 2608 2505 2505 2609 2480 2480 2583 2505 2505 2609 2481 2481 2584 2481 2481 2584 2505 2505 2609 2506 2506 2610 2481 2481 2584 2506 2506 2610 2482 2482 2585 2482 2482 2585 2506 2506 2610 2507 2507 2611 2482 2482 2585 2507 2507 2611 2483 2483 2586 2483 2483 2586 2507 2507 2611 2508 2508 2612 2483 2483 2586 2508 2508 2612 2484 2484 2587 2484 2484 2587 2508 2508 2612 2509 2509 2613 2484 2484 2587 2509 2509 2613 2485 2485 2588 2485 2485 2588 2509 2509 2613 2510 2510 2614 2485 2485 2588 2510 2510 2614 2486 2486 2589 2486 2486 2589 2510 2510 2614 2511 2511 2615 2486 2486 2589 2511 2511 2615 2487 2487 2590 2487 2487 2590 2511 2511 2615 2512 2512 2616 2487 2487 2590 2512 2512 2616 2488 2488 2591 2488 2488 2591 2512 2512 2616 2513 2513 2617 2488 2488 2591 2513 2513 2617 2489 2489 2592 2489 2489 2592 2513 2513 2617 2514 2514 2618 2489 2489 2592 2514 2514 2618 2490 2490 2593 2490 2490 2593 2514 2514 2618 2515 2515 2619 2490 2490 2593 2515 2515 2619 2491 2491 2594 2491 2491 2594 2515 2515 2619 2516 2516 2620 2491 2491 2594 2516 2516 2620 2492 2492 2595 2492 2492 2595 2516 2516 2620 2517 2517 2621 2492 2492 2595 2517 2517 2621 2493 2493 2596 2493 2493 2596 2517 2517 2621 2518 2518 2622 2493 2493 2596 2518 2518 2622 2494 2494 2597 2494 2494 2597 2518 2518 2622 2519 2519 2623 2494 2494 2597 2519 2519 2623 2495 2495 2598 2495 2495 2598 2519 2519 2623 2496 2496 2624 2495 2495 2598 2496 2496 2624 2472 2472 2599 2496 2496 2600 2520 2520 2625 2521 2521 2626 2496 2496 2600 2521 2521 2626 2497 2497 2601 2497 2497 2601 2521 2521 2626 2522 2522 2627 2497 2497 2601 2522 2522 2627 2498 2498 2602 2498 2498 2602 2522 2522 2627 2523 2523 2628 2498 2498 2602 2523 2523 2628 2499 2499 2603 2499 2499 2603 2523 2523 2628 2524 2524 2629 2499 2499 2603 2524 2524 2629 2500 2500 2604 2500 2500 2604 2524 2524 2629 2525 2525 2630 2500 2500 2604 2525 2525 2630 2501 2501 2605 2501 2501 2605 2525 2525 2630 2526 2526 2631 2501 2501 2605 2526 2526 2631 2502 2502 2606 2502 2502 2606 2526 2526 2631 2527 2527 2632 2502 2502 2606 2527 2527 2632 2503 2503 2607 2503 2503 2607 2527 2527 2632 2528 2528 2633 2503 2503 2607 2528 2528 2633 2504 2504 2608 2504 2504 2608 2528 2528 2633 2529 2529 2634 2504 2504 2608 2529 2529 2634 2505 2505 2609 2505 2505 2609 2529 2529 2634 2530 2530 2635 2505 2505 2609 2530 2530 2635 2506 2506 2610 2506 2506 2610 2530 2530 2635 2531 2531 2636 2506 2506 2610 2531 2531 2636 2507 2507 2611 2507 2507 2611 2531 2531 2636 2532 2532 2637 2507 2507 2611 2532 2532 2637 2508 2508 2612 2508 2508 2612 2532 2532 2637 2533 2533 2638 2508 2508 2612 2533 2533 2638 2509 2509 2613 2509 2509 2613 2533 2533 2638 2534 2534 2639 2509 2509 2613 2534 2534 2639 2510 2510 2614 2510 2510 2614 2534 2534 2639 2535 2535 2640 2510 2510 2614 2535 2535 2640 2511 2511 2615 2511 2511 2615 2535 2535 2640 2536 2536 2641 2511 2511 2615 2536 2536 2641 2512 2512 2616 2512 2512 2616 2536 2536 2641 2537 2537 2642 2512 2512 2616 2537 2537 2642 2513 2513 2617 2513 2513 2617 2537 2537 2642 2538 2538 2643 2513 2513 2617 2538 2538 2643 2514 2514 2618 2514 2514 2618 2538 2538 2643 2539 2539 2644 2514 2514 2618 2539 2539 2644 2515 2515 2619 2515 2515 2619 2539 2539 2644 2540 2540 2645 2515 2515 2619 2540 2540 2645 2516 2516 2620 2516 2516 2620 2540 2540 2645 2541 2541 2646 2516 2516 2620 2541 2541 2646 2517 2517 2621 2517 2517 2621 2541 2541 2646 2542 2542 2647 2517 2517 2621 2542 2542 2647 2518 2518 2622 2518 2518 2622 2542 2542 2647 2543 2543 2648 2518 2518 2622 2543 2543 2648 2519 2519 2623 2519 2519 2623 2543 2543 2648 2520 2520 2649 2519 2519 2623 2520 2520 2649 2496 2496 2624 2520 2520 2625 2544 2544 2650 2545 2545 2651 2520 2520 2625 2545 2545 2651 2521 2521 2626 2521 2521 2626 2545 2545 2651 2546 2546 2652 2521 2521 2626 2546 2546 2652 2522 2522 2627 2522 2522 2627 2546 2546 2652 2547 2547 2653 2522 2522 2627 2547 2547 2653 2523 2523 2628 2523 2523 2628 2547 2547 2653 2548 2548 2654 2523 2523 2628 2548 2548 2654 2524 2524 2629 2524 2524 2629 2548 2548 2654 2549 2549 2655 2524 2524 2629 2549 2549 2655 2525 2525 2630 2525 2525 2630 2549 2549 2655 2550 2550 2656 2525 2525 2630 2550 2550 2656 2526 2526 2631 2526 2526 2631 2550 2550 2656 2551 2551 2657 2526 2526 2631 2551 2551 2657 2527 2527 2632 2527 2527 2632 2551 2551 2657 2552 2552 2658 2527 2527 2632 2552 2552 2658 2528 2528 2633 2528 2528 2633 2552 2552 2658 2553 2553 2659 2528 2528 2633 2553 2553 2659 2529 2529 2634 2529 2529 2634 2553 2553 2659 2554 2554 2660 2529 2529 2634 2554 2554 2660 2530 2530 2635 2530 2530 2635 2554 2554 2660 2555 2555 2661 2530 2530 2635 2555 2555 2661 2531 2531 2636 2531 2531 2636 2555 2555 2661 2556 2556 2662 2531 2531 2636 2556 2556 2662 2532 2532 2637 2532 2532 2637 2556 2556 2662 2557 2557 2663 2532 2532 2637 2557 2557 2663 2533 2533 2638 2533 2533 2638 2557 2557 2663 2558 2558 2664 2533 2533 2638 2558 2558 2664 2534 2534 2639 2534 2534 2639 2558 2558 2664 2559 2559 2665 2534 2534 2639 2559 2559 2665 2535 2535 2640 2535 2535 2640 2559 2559 2665 2560 2560 2666 2535 2535 2640 2560 2560 2666 2536 2536 2641 2536 2536 2641 2560 2560 2666 2561 2561 2667 2536 2536 2641 2561 2561 2667 2537 2537 2642 2537 2537 2642 2561 2561 2667 2562 2562 2668 2537 2537 2642 2562 2562 2668 2538 2538 2643 2538 2538 2643 2562 2562 2668 2563 2563 2669 2538 2538 2643 2563 2563 2669 2539 2539 2644 2539 2539 2644 2563 2563 2669 2564 2564 2670 2539 2539 2644 2564 2564 2670 2540 2540 2645 2540 2540 2645 2564 2564 2670 2565 2565 2671 2540 2540 2645 2565 2565 2671 2541 2541 2646 2541 2541 2646 2565 2565 2671 2566 2566 2672 2541 2541 2646 2566 2566 2672 2542 2542 2647 2542 2542 2647 2566 2566 2672 2567 2567 2673 2542 2542 2647 2567 2567 2673 2543 2543 2648 2543 2543 2648 2567 2567 2673 2544 2544 2674 2543 2543 2648 2544 2544 2674 2520 2520 2649 2544 2544 2650 2568 2568 2675 2569 2569 2676 2544 2544 2650 2569 2569 2676 2545 2545 2651 2545 2545 2651 2569 2569 2676 2570 2570 2677 2545 2545 2651 2570 2570 2677 2546 2546 2652 2546 2546 2652 2570 2570 2677 2571 2571 2678 2546 2546 2652 2571 2571 2678 2547 2547 2653 2547 2547 2653 2571 2571 2678 2572 2572 2679 2547 2547 2653 2572 2572 2679 2548 2548 2654 2548 2548 2654 2572 2572 2679 2573 2573 2680 2548 2548 2654 2573 2573 2680 2549 2549 2655 2549 2549 2655 2573 2573 2680 2574 2574 2681 2549 2549 2655 2574 2574 2681 2550 2550 2656 2550 2550 2656 2574 2574 2681 2575 2575 2682 2550 2550 2656 2575 2575 2682 2551 2551 2657 2551 2551 2657 2575 2575 2682 2576 2576 2683 2551 2551 2657 2576 2576 2683 2552 2552 2658 2552 2552 2658 2576 2576 2683 2577 2577 2684 2552 2552 2658 2577 2577 2684 2553 2553 2659 2553 2553 2659 2577 2577 2684 2578 2578 2685 2553 2553 2659 2578 2578 2685 2554 2554 2660 2554 2554 2660 2578 2578 2685 2579 2579 2686 2554 2554 2660 2579 2579 2686 2555 2555 2661 2555 2555 2661 2579 2579 2686 2580 2580 2687 2555 2555 2661 2580 2580 2687 2556 2556 2662 2556 2556 2662 2580 2580 2687 2581 2581 2688 2556 2556 2662 2581 2581 2688 2557 2557 2663 2557 2557 2663 2581 2581 2688 2582 2582 2689 2557 2557 2663 2582 2582 2689 2558 2558 2664 2558 2558 2664 2582 2582 2689 2583 2583 2690 2558 2558 2664 2583 2583 2690 2559 2559 2665 2559 2559 2665 2583 2583 2690 2584 2584 2691 2559 2559 2665 2584 2584 2691 2560 2560 2666 2560 2560 2666 2584 2584 2691 2585 2585 2692 2560 2560 2666 2585 2585 2692 2561 2561 2667 2561 2561 2667 2585 2585 2692 2586 2586 2693 2561 2561 2667 2586 2586 2693 2562 2562 2668 2562 2562 2668 2586 2586 2693 2587 2587 2694 2562 2562 2668 2587 2587 2694 2563 2563 2669 2563 2563 2669 2587 2587 2694 2588 2588 2695 2563 2563 2669 2588 2588 2695 2564 2564 2670 2564 2564 2670 2588 2588 2695 2589 2589 2696 2564 2564 2670 2589 2589 2696 2565 2565 2671 2565 2565 2671 2589 2589 2696 2590 2590 2697 2565 2565 2671 2590 2590 2697 2566 2566 2672 2566 2566 2672 2590 2590 2697 2591 2591 2698 2566 2566 2672 2591 2591 2698 2567 2567 2673 2567 2567 2673 2591 2591 2698 2568 2568 2699 2567 2567 2673 2568 2568 2699 2544 2544 2674 2568 2568 2675 2592 2592 2700 2593 2593 2701 2568 2568 2675 2593 2593 2701 2569 2569 2676 2569 2569 2676 2593 2593 2701 2594 2594 2702 2569 2569 2676 2594 2594 2702 2570 2570 2677 2570 2570 2677 2594 2594 2702 2595 2595 2703 2570 2570 2677 2595 2595 2703 2571 2571 2678 2571 2571 2678 2595 2595 2703 2596 2596 2704 2571 2571 2678 2596 2596 2704 2572 2572 2679 2572 2572 2679 2596 2596 2704 2597 2597 2705 2572 2572 2679 2597 2597 2705 2573 2573 2680 2573 2573 2680 2597 2597 2705 2598 2598 2706 2573 2573 2680 2598 2598 2706 2574 2574 2681 2574 2574 2681 2598 2598 2706 2599 2599 2707 2574 2574 2681 2599 2599 2707 2575 2575 2682 2575 2575 2682 2599 2599 2707 2600 2600 2708 2575 2575 2682 2600 2600 2708 2576 2576 2683 2576 2576 2683 2600 2600 2708 2601 2601 2709 2576 2576 2683 2601 2601 2709 2577 2577 2684 2577 2577 2684 2601 2601 2709 2602 2602 2710 2577 2577 2684 2602 2602 2710 2578 2578 2685 2578 2578 2685 2602 2602 2710 2603 2603 2711 2578 2578 2685 2603 2603 2711 2579 2579 2686 2579 2579 2686 2603 2603 2711 2604 2604 2712 2579 2579 2686 2604 2604 2712 2580 2580 2687 2580 2580 2687 2604 2604 2712 2605 2605 2713 2580 2580 2687 2605 2605 2713 2581 2581 2688 2581 2581 2688 2605 2605 2713 2606 2606 2714 2581 2581 2688 2606 2606 2714 2582 2582 2689 2582 2582 2689 2606 2606 2714 2607 2607 2715 2582 2582 2689 2607 2607 2715 2583 2583 2690 2583 2583 2690 2607 2607 2715 2608 2608 2716 2583 2583 2690 2608 2608 2716 2584 2584 2691 2584 2584 2691 2608 2608 2716 2609 2609 2717 2584 2584 2691 2609 2609 2717 2585 2585 2692 2585 2585 2692 2609 2609 2717 2610 2610 2718 2585 2585 2692 2610 2610 2718 2586 2586 2693 2586 2586 2693 2610 2610 2718 2611 2611 2719 2586 2586 2693 2611 2611 2719 2587 2587 2694 2587 2587 2694 2611 2611 2719 2612 2612 2720 2587 2587 2694 2612 2612 2720 2588 2588 2695 2588 2588 2695 2612 2612 2720 2613 2613 2721 2588 2588 2695 2613 2613 2721 2589 2589 2696 2589 2589 2696 2613 2613 2721 2614 2614 2722 2589 2589 2696 2614 2614 2722 2590 2590 2697 2590 2590 2697 2614 2614 2722 2615 2615 2723 2590 2590 2697 2615 2615 2723 2591 2591 2698 2591 2591 2698 2615 2615 2723 2592 2592 2724 2591 2591 2698 2592 2592 2724 2568 2568 2699 2592 2592 2700 2616 2616 2725 2617 2617 2726 2592 2592 2700 2617 2617 2726 2593 2593 2701 2593 2593 2701 2617 2617 2726 2618 2618 2727 2593 2593 2701 2618 2618 2727 2594 2594 2702 2594 2594 2702 2618 2618 2727 2619 2619 2728 2594 2594 2702 2619 2619 2728 2595 2595 2703 2595 2595 2703 2619 2619 2728 2620 2620 2729 2595 2595 2703 2620 2620 2729 2596 2596 2704 2596 2596 2704 2620 2620 2729 2621 2621 2730 2596 2596 2704 2621 2621 2730 2597 2597 2705 2597 2597 2705 2621 2621 2730 2622 2622 2731 2597 2597 2705 2622 2622 2731 2598 2598 2706 2598 2598 2706 2622 2622 2731 2623 2623 2732 2598 2598 2706 2623 2623 2732 2599 2599 2707 2599 2599 2707 2623 2623 2732 2624 2624 2733 2599 2599 2707 2624 2624 2733 2600 2600 2708 2600 2600 2708 2624 2624 2733 2625 2625 2734 2600 2600 2708 2625 2625 2734 2601 2601 2709 2601 2601 2709 2625 2625 2734 2626 2626 2735 2601 2601 2709 2626 2626 2735 2602 2602 2710 2602 2602 2710 2626 2626 2735 2627 2627 2736 2602 2602 2710 2627 2627 2736 2603 2603 2711 2603 2603 2711 2627 2627 2736 2628 2628 2737 2603 2603 2711 2628 2628 2737 2604 2604 2712 2604 2604 2712 2628 2628 2737 2629 2629 2738 2604 2604 2712 2629 2629 2738 2605 2605 2713 2605 2605 2713 2629 2629 2738 2630 2630 2739 2605 2605 2713 2630 2630 2739 2606 2606 2714 2606 2606 2714 2630 2630 2739 2631 2631 2740 2606 2606 2714 2631 2631 2740 2607 2607 2715 2607 2607 2715 2631 2631 2740 2632 2632 2741 2607 2607 2715 2632 2632 2741 2608 2608 2716 2608 2608 2716 2632 2632 2741 2633 2633 2742 2608 2608 2716 2633 2633 2742 2609 2609 2717 2609 2609 2717 2633 2633 2742 2634 2634 2743 2609 2609 2717 2634 2634 2743 2610 2610 2718 2610 2610 2718 2634 2634 2743 2635 2635 2744 2610 2610 2718 2635 2635 2744 2611 2611 2719 2611 2611 2719 2635 2635 2744 2636 2636 2745 2611 2611 2719 2636 2636 2745 2612 2612 2720 2612 2612 2720 2636 2636 2745 2637 2637 2746 2612 2612 2720 2637 2637 2746 2613 2613 2721 2613 2613 2721 2637 2637 2746 2638 2638 2747 2613 2613 2721 2638 2638 2747 2614 2614 2722 2614 2614 2722 2638 2638 2747 2639 2639 2748 2614 2614 2722 2639 2639 2748 2615 2615 2723 2615 2615 2723 2639 2639 2748 2616 2616 2749 2615 2615 2723 2616 2616 2749 2592 2592 2724 2616 2616 2725 2640 2640 2750 2641 2641 2751 2616 2616 2725 2641 2641 2751 2617 2617 2726 2617 2617 2726 2641 2641 2751 2642 2642 2752 2617 2617 2726 2642 2642 2752 2618 2618 2727 2618 2618 2727 2642 2642 2752 2643 2643 2753 2618 2618 2727 2643 2643 2753 2619 2619 2728 2619 2619 2728 2643 2643 2753 2644 2644 2754 2619 2619 2728 2644 2644 2754 2620 2620 2729 2620 2620 2729 2644 2644 2754 2645 2645 2755 2620 2620 2729 2645 2645 2755 2621 2621 2730 2621 2621 2730 2645 2645 2755 2646 2646 2756 2621 2621 2730 2646 2646 2756 2622 2622 2731 2622 2622 2731 2646 2646 2756 2647 2647 2757 2622 2622 2731 2647 2647 2757 2623 2623 2732 2623 2623 2732 2647 2647 2757 2648 2648 2758 2623 2623 2732 2648 2648 2758 2624 2624 2733 2624 2624 2733 2648 2648 2758 2649 2649 2759 2624 2624 2733 2649 2649 2759 2625 2625 2734 2625 2625 2734 2649 2649 2759 2650 2650 2760 2625 2625 2734 2650 2650 2760 2626 2626 2735 2626 2626 2735 2650 2650 2760 2651 2651 2761 2626 2626 2735 2651 2651 2761 2627 2627 2736 2627 2627 2736 2651 2651 2761 2652 2652 2762 2627 2627 2736 2652 2652 2762 2628 2628 2737 2628 2628 2737 2652 2652 2762 2653 2653 2763 2628 2628 2737 2653 2653 2763 2629 2629 2738 2629 2629 2738 2653 2653 2763 2654 2654 2764 2629 2629 2738 2654 2654 2764 2630 2630 2739 2630 2630 2739 2654 2654 2764 2655 2655 2765 2630 2630 2739 2655 2655 2765 2631 2631 2740 2631 2631 2740 2655 2655 2765 2656 2656 2766 2631 2631 2740 2656 2656 2766 2632 2632 2741 2632 2632 2741 2656 2656 2766 2657 2657 2767 2632 2632 2741 2657 2657 2767 2633 2633 2742 2633 2633 2742 2657 2657 2767 2658 2658 2768 2633 2633 2742 2658 2658 2768 2634 2634 2743 2634 2634 2743 2658 2658 2768 2659 2659 2769 2634 2634 2743 2659 2659 2769 2635 2635 2744 2635 2635 2744 2659 2659 2769 2660 2660 2770 2635 2635 2744 2660 2660 2770 2636 2636 2745 2636 2636 2745 2660 2660 2770 2661 2661 2771 2636 2636 2745 2661 2661 2771 2637 2637 2746 2637 2637 2746 2661 2661 2771 2662 2662 2772 2637 2637 2746 2662 2662 2772 2638 2638 2747 2638 2638 2747 2662 2662 2772 2663 2663 2773 2638 2638 2747 2663 2663 2773 2639 2639 2748 2639 2639 2748 2663 2663 2773 2640 2640 2774 2639 2639 2748 2640 2640 2774 2616 2616 2749 2640 2640 2750 2664 2664 2775 2665 2665 2776 2640 2640 2750 2665 2665 2776 2641 2641 2751 2641 2641 2751 2665 2665 2776 2666 2666 2777 2641 2641 2751 2666 2666 2777 2642 2642 2752 2642 2642 2752 2666 2666 2777 2667 2667 2778 2642 2642 2752 2667 2667 2778 2643 2643 2753 2643 2643 2753 2667 2667 2778 2668 2668 2779 2643 2643 2753 2668 2668 2779 2644 2644 2754 2644 2644 2754 2668 2668 2779 2669 2669 2780 2644 2644 2754 2669 2669 2780 2645 2645 2755 2645 2645 2755 2669 2669 2780 2670 2670 2781 2645 2645 2755 2670 2670 2781 2646 2646 2756 2646 2646 2756 2670 2670 2781 2671 2671 2782 2646 2646 2756 2671 2671 2782 2647 2647 2757 2647 2647 2757 2671 2671 2782 2672 2672 2783 2647 2647 2757 2672 2672 2783 2648 2648 2758 2648 2648 2758 2672 2672 2783 2673 2673 2784 2648 2648 2758 2673 2673 2784 2649 2649 2759 2649 2649 2759 2673 2673 2784 2674 2674 2785 2649 2649 2759 2674 2674 2785 2650 2650 2760 2650 2650 2760 2674 2674 2785 2675 2675 2786 2650 2650 2760 2675 2675 2786 2651 2651 2761 2651 2651 2761 2675 2675 2786 2676 2676 2787 2651 2651 2761 2676 2676 2787 2652 2652 2762 2652 2652 2762 2676 2676 2787 2677 2677 2788 2652 2652 2762 2677 2677 2788 2653 2653 2763 2653 2653 2763 2677 2677 2788 2678 2678 2789 2653 2653 2763 2678 2678 2789 2654 2654 2764 2654 2654 2764 2678 2678 2789 2679 2679 2790 2654 2654 2764 2679 2679 2790 2655 2655 2765 2655 2655 2765 2679 2679 2790 2680 2680 2791 2655 2655 2765 2680 2680 2791 2656 2656 2766 2656 2656 2766 2680 2680 2791 2681 2681 2792 2656 2656 2766 2681 2681 2792 2657 2657 2767 2657 2657 2767 2681 2681 2792 2682 2682 2793 2657 2657 2767 2682 2682 2793 2658 2658 2768 2658 2658 2768 2682 2682 2793 2683 2683 2794 2658 2658 2768 2683 2683 2794 2659 2659 2769 2659 2659 2769 2683 2683 2794 2684 2684 2795 2659 2659 2769 2684 2684 2795 2660 2660 2770 2660 2660 2770 2684 2684 2795 2685 2685 2796 2660 2660 2770 2685 2685 2796 2661 2661 2771 2661 2661 2771 2685 2685 2796 2686 2686 2797 2661 2661 2771 2686 2686 2797 2662 2662 2772 2662 2662 2772 2686 2686 2797 2687 2687 2798 2662 2662 2772 2687 2687 2798 2663 2663 2773 2663 2663 2773 2687 2687 2798 2664 2664 2799 2663 2663 2773 2664 2664 2799 2640 2640 2774 2664 2664 2775 2688 2688 2800 2689 2689 2801 2664 2664 2775 2689 2689 2801 2665 2665 2776 2665 2665 2776 2689 2689 2801 2690 2690 2802 2665 2665 2776 2690 2690 2802 2666 2666 2777 2666 2666 2777 2690 2690 2802 2691 2691 2803 2666 2666 2777 2691 2691 2803 2667 2667 2778 2667 2667 2778 2691 2691 2803 2692 2692 2804 2667 2667 2778 2692 2692 2804 2668 2668 2779 2668 2668 2779 2692 2692 2804 2693 2693 2805 2668 2668 2779 2693 2693 2805 2669 2669 2780 2669 2669 2780 2693 2693 2805 2694 2694 2806 2669 2669 2780 2694 2694 2806 2670 2670 2781 2670 2670 2781 2694 2694 2806 2695 2695 2807 2670 2670 2781 2695 2695 2807 2671 2671 2782 2671 2671 2782 2695 2695 2807 2696 2696 2808 2671 2671 2782 2696 2696 2808 2672 2672 2783 2672 2672 2783 2696 2696 2808 2697 2697 2809 2672 2672 2783 2697 2697 2809 2673 2673 2784 2673 2673 2784 2697 2697 2809 2698 2698 2810 2673 2673 2784 2698 2698 2810 2674 2674 2785 2674 2674 2785 2698 2698 2810 2699 2699 2811 2674 2674 2785 2699 2699 2811 2675 2675 2786 2675 2675 2786 2699 2699 2811 2700 2700 2812 2675 2675 2786 2700 2700 2812 2676 2676 2787 2676 2676 2787 2700 2700 2812 2701 2701 2813 2676 2676 2787 2701 2701 2813 2677 2677 2788 2677 2677 2788 2701 2701 2813 2702 2702 2814 2677 2677 2788 2702 2702 2814 2678 2678 2789 2678 2678 2789 2702 2702 2814 2703 2703 2815 2678 2678 2789 2703 2703 2815 2679 2679 2790 2679 2679 2790 2703 2703 2815 2704 2704 2816 2679 2679 2790 2704 2704 2816 2680 2680 2791 2680 2680 2791 2704 2704 2816 2705 2705 2817 2680 2680 2791 2705 2705 2817 2681 2681 2792 2681 2681 2792 2705 2705 2817 2706 2706 2818 2681 2681 2792 2706 2706 2818 2682 2682 2793 2682 2682 2793 2706 2706 2818 2707 2707 2819 2682 2682 2793 2707 2707 2819 2683 2683 2794 2683 2683 2794 2707 2707 2819 2708 2708 2820 2683 2683 2794 2708 2708 2820 2684 2684 2795 2684 2684 2795 2708 2708 2820 2709 2709 2821 2684 2684 2795 2709 2709 2821 2685 2685 2796 2685 2685 2796 2709 2709 2821 2710 2710 2822 2685 2685 2796 2710 2710 2822 2686 2686 2797 2686 2686 2797 2710 2710 2822 2711 2711 2823 2686 2686 2797 2711 2711 2823 2687 2687 2798 2687 2687 2798 2711 2711 2823 2688 2688 2824 2687 2687 2798 2688 2688 2824 2664 2664 2799 2688 2688 2800 2712 2712 2825 2713 2713 2826 2688 2688 2800 2713 2713 2826 2689 2689 2801 2689 2689 2801 2713 2713 2826 2714 2714 2827 2689 2689 2801 2714 2714 2827 2690 2690 2802 2690 2690 2802 2714 2714 2827 2715 2715 2828 2690 2690 2802 2715 2715 2828 2691 2691 2803 2691 2691 2803 2715 2715 2828 2716 2716 2829 2691 2691 2803 2716 2716 2829 2692 2692 2804 2692 2692 2804 2716 2716 2829 2717 2717 2830 2692 2692 2804 2717 2717 2830 2693 2693 2805 2693 2693 2805 2717 2717 2830 2718 2718 2831 2693 2693 2805 2718 2718 2831 2694 2694 2806 2694 2694 2806 2718 2718 2831 2719 2719 2832 2694 2694 2806 2719 2719 2832 2695 2695 2807 2695 2695 2807 2719 2719 2832 2720 2720 2833 2695 2695 2807 2720 2720 2833 2696 2696 2808 2696 2696 2808 2720 2720 2833 2721 2721 2834 2696 2696 2808 2721 2721 2834 2697 2697 2809 2697 2697 2809 2721 2721 2834 2722 2722 2835 2697 2697 2809 2722 2722 2835 2698 2698 2810 2698 2698 2810 2722 2722 2835 2723 2723 2836 2698 2698 2810 2723 2723 2836 2699 2699 2811 2699 2699 2811 2723 2723 2836 2724 2724 2837 2699 2699 2811 2724 2724 2837 2700 2700 2812 2700 2700 2812 2724 2724 2837 2725 2725 2838 2700 2700 2812 2725 2725 2838 2701 2701 2813 2701 2701 2813 2725 2725 2838 2726 2726 2839 2701 2701 2813 2726 2726 2839 2702 2702 2814 2702 2702 2814 2726 2726 2839 2727 2727 2840 2702 2702 2814 2727 2727 2840 2703 2703 2815 2703 2703 2815 2727 2727 2840 2728 2728 2841 2703 2703 2815 2728 2728 2841 2704 2704 2816 2704 2704 2816 2728 2728 2841 2729 2729 2842 2704 2704 2816 2729 2729 2842 2705 2705 2817 2705 2705 2817 2729 2729 2842 2730 2730 2843 2705 2705 2817 2730 2730 2843 2706 2706 2818 2706 2706 2818 2730 2730 2843 2731 2731 2844 2706 2706 2818 2731 2731 2844 2707 2707 2819 2707 2707 2819 2731 2731 2844 2732 2732 2845 2707 2707 2819 2732 2732 2845 2708 2708 2820 2708 2708 2820 2732 2732 2845 2733 2733 2846 2708 2708 2820 2733 2733 2846 2709 2709 2821 2709 2709 2821 2733 2733 2846 2734 2734 2847 2709 2709 2821 2734 2734 2847 2710 2710 2822 2710 2710 2822 2734 2734 2847 2735 2735 2848 2710 2710 2822 2735 2735 2848 2711 2711 2823 2711 2711 2823 2735 2735 2848 2712 2712 2849 2711 2711 2823 2712 2712 2849 2688 2688 2824 2712 2712 2825 2736 2736 2850 2737 2737 2851 2712 2712 2825 2737 2737 2851 2713 2713 2826 2713 2713 2826 2737 2737 2851 2738 2738 2852 2713 2713 2826 2738 2738 2852 2714 2714 2827 2714 2714 2827 2738 2738 2852 2739 2739 2853 2714 2714 2827 2739 2739 2853 2715 2715 2828 2715 2715 2828 2739 2739 2853 2740 2740 2854 2715 2715 2828 2740 2740 2854 2716 2716 2829 2716 2716 2829 2740 2740 2854 2741 2741 2855 2716 2716 2829 2741 2741 2855 2717 2717 2830 2717 2717 2830 2741 2741 2855 2742 2742 2856 2717 2717 2830 2742 2742 2856 2718 2718 2831 2718 2718 2831 2742 2742 2856 2743 2743 2857 2718 2718 2831 2743 2743 2857 2719 2719 2832 2719 2719 2832 2743 2743 2857 2744 2744 2858 2719 2719 2832 2744 2744 2858 2720 2720 2833 2720 2720 2833 2744 2744 2858 2745 2745 2859 2720 2720 2833 2745 2745 2859 2721 2721 2834 2721 2721 2834 2745 2745 2859 2746 2746 2860 2721 2721 2834 2746 2746 2860 2722 2722 2835 2722 2722 2835 2746 2746 2860 2747 2747 2861 2722 2722 2835 2747 2747 2861 2723 2723 2836 2723 2723 2836 2747 2747 2861 2748 2748 2862 2723 2723 2836 2748 2748 2862 2724 2724 2837 2724 2724 2837 2748 2748 2862 2749 2749 2863 2724 2724 2837 2749 2749 2863 2725 2725 2838 2725 2725 2838 2749 2749 2863 2750 2750 2864 2725 2725 2838 2750 2750 2864 2726 2726 2839 2726 2726 2839 2750 2750 2864 2751 2751 2865 2726 2726 2839 2751 2751 2865 2727 2727 2840 2727 2727 2840 2751 2751 2865 2752 2752 2866 2727 2727 2840 2752 2752 2866 2728 2728 2841 2728 2728 2841 2752 2752 2866 2753 2753 2867 2728 2728 2841 2753 2753 2867 2729 2729 2842 2729 2729 2842 2753 2753 2867 2754 2754 2868 2729 2729 2842 2754 2754 2868 2730 2730 2843 2730 2730 2843 2754 2754 2868 2755 2755 2869 2730 2730 2843 2755 2755 2869 2731 2731 2844 2731 2731 2844 2755 2755 2869 2756 2756 2870 2731 2731 2844 2756 2756 2870 2732 2732 2845 2732 2732 2845 2756 2756 2870 2757 2757 2871 2732 2732 2845 2757 2757 2871 2733 2733 2846 2733 2733 2846 2757 2757 2871 2758 2758 2872 2733 2733 2846 2758 2758 2872 2734 2734 2847 2734 2734 2847 2758 2758 2872 2759 2759 2873 2734 2734 2847 2759 2759 2873 2735 2735 2848 2735 2735 2848 2759 2759 2873 2736 2736 2874 2735 2735 2848 2736 2736 2874 2712 2712 2849 2736 2736 2850 2760 2760 2875 2761 2761 2876 2736 2736 2850 2761 2761 2876 2737 2737 2851 2737 2737 2851 2761 2761 2876 2762 2762 2877 2737 2737 2851 2762 2762 2877 2738 2738 2852 2738 2738 2852 2762 2762 2877 2763 2763 2878 2738 2738 2852 2763 2763 2878 2739 2739 2853 2739 2739 2853 2763 2763 2878 2764 2764 2879 2739 2739 2853 2764 2764 2879 2740 2740 2854 2740 2740 2854 2764 2764 2879 2765 2765 2880 2740 2740 2854 2765 2765 2880 2741 2741 2855 2741 2741 2855 2765 2765 2880 2766 2766 2881 2741 2741 2855 2766 2766 2881 2742 2742 2856 2742 2742 2856 2766 2766 2881 2767 2767 2882 2742 2742 2856 2767 2767 2882 2743 2743 2857 2743 2743 2857 2767 2767 2882 2768 2768 2883 2743 2743 2857 2768 2768 2883 2744 2744 2858 2744 2744 2858 2768 2768 2883 2769 2769 2884 2744 2744 2858 2769 2769 2884 2745 2745 2859 2745 2745 2859 2769 2769 2884 2770 2770 2885 2745 2745 2859 2770 2770 2885 2746 2746 2860 2746 2746 2860 2770 2770 2885 2771 2771 2886 2746 2746 2860 2771 2771 2886 2747 2747 2861 2747 2747 2861 2771 2771 2886 2772 2772 2887 2747 2747 2861 2772 2772 2887 2748 2748 2862 2748 2748 2862 2772 2772 2887 2773 2773 2888 2748 2748 2862 2773 2773 2888 2749 2749 2863 2749 2749 2863 2773 2773 2888 2774 2774 2889 2749 2749 2863 2774 2774 2889 2750 2750 2864 2750 2750 2864 2774 2774 2889 2775 2775 2890 2750 2750 2864 2775 2775 2890 2751 2751 2865 2751 2751 2865 2775 2775 2890 2776 2776 2891 2751 2751 2865 2776 2776 2891 2752 2752 2866 2752 2752 2866 2776 2776 2891 2777 2777 2892 2752 2752 2866 2777 2777 2892 2753 2753 2867 2753 2753 2867 2777 2777 2892 2778 2778 2893 2753 2753 2867 2778 2778 2893 2754 2754 2868 2754 2754 2868 2778 2778 2893 2779 2779 2894 2754 2754 2868 2779 2779 2894 2755 2755 2869 2755 2755 2869 2779 2779 2894 2780 2780 2895 2755 2755 2869 2780 2780 2895 2756 2756 2870 2756 2756 2870 2780 2780 2895 2781 2781 2896 2756 2756 2870 2781 2781 2896 2757 2757 2871 2757 2757 2871 2781 2781 2896 2782 2782 2897 2757 2757 2871 2782 2782 2897 2758 2758 2872 2758 2758 2872 2782 2782 2897 2783 2783 2898 2758 2758 2872 2783 2783 2898 2759 2759 2873 2759 2759 2873 2783 2783 2898 2760 2760 2899 2759 2759 2873 2760 2760 2899 2736 2736 2874 2760 2760 2875 2784 2784 2900 2785 2785 2901 2760 2760 2875 2785 2785 2901 2761 2761 2876 2761 2761 2876 2785 2785 2901 2786 2786 2902 2761 2761 2876 2786 2786 2902 2762 2762 2877 2762 2762 2877 2786 2786 2902 2787 2787 2903 2762 2762 2877 2787 2787 2903 2763 2763 2878 2763 2763 2878 2787 2787 2903 2788 2788 2904 2763 2763 2878 2788 2788 2904 2764 2764 2879 2764 2764 2879 2788 2788 2904 2789 2789 2905 2764 2764 2879 2789 2789 2905 2765 2765 2880 2765 2765 2880 2789 2789 2905 2790 2790 2906 2765 2765 2880 2790 2790 2906 2766 2766 2881 2766 2766 2881 2790 2790 2906 2791 2791 2907 2766 2766 2881 2791 2791 2907 2767 2767 2882 2767 2767 2882 2791 2791 2907 2792 2792 2908 2767 2767 2882 2792 2792 2908 2768 2768 2883 2768 2768 2883 2792 2792 2908 2793 2793 2909 2768 2768 2883 2793 2793 2909 2769 2769 2884 2769 2769 2884 2793 2793 2909 2794 2794 2910 2769 2769 2884 2794 2794 2910 2770 2770 2885 2770 2770 2885 2794 2794 2910 2795 2795 2911 2770 2770 2885 2795 2795 2911 2771 2771 2886 2771 2771 2886 2795 2795 2911 2796 2796 2912 2771 2771 2886 2796 2796 2912 2772 2772 2887 2772 2772 2887 2796 2796 2912 2797 2797 2913 2772 2772 2887 2797 2797 2913 2773 2773 2888 2773 2773 2888 2797 2797 2913 2798 2798 2914 2773 2773 2888 2798 2798 2914 2774 2774 2889 2774 2774 2889 2798 2798 2914 2799 2799 2915 2774 2774 2889 2799 2799 2915 2775 2775 2890 2775 2775 2890 2799 2799 2915 2800 2800 2916 2775 2775 2890 2800 2800 2916 2776 2776 2891 2776 2776 2891 2800 2800 2916 2801 2801 2917 2776 2776 2891 2801 2801 2917 2777 2777 2892 2777 2777 2892 2801 2801 2917 2802 2802 2918 2777 2777 2892 2802 2802 2918 2778 2778 2893 2778 2778 2893 2802 2802 2918 2803 2803 2919 2778 2778 2893 2803 2803 2919 2779 2779 2894 2779 2779 2894 2803 2803 2919 2804 2804 2920 2779 2779 2894 2804 2804 2920 2780 2780 2895 2780 2780 2895 2804 2804 2920 2805 2805 2921 2780 2780 2895 2805 2805 2921 2781 2781 2896 2781 2781 2896 2805 2805 2921 2806 2806 2922 2781 2781 2896 2806 2806 2922 2782 2782 2897 2782 2782 2897 2806 2806 2922 2807 2807 2923 2782 2782 2897 2807 2807 2923 2783 2783 2898 2783 2783 2898 2807 2807 2923 2784 2784 2924 2783 2783 2898 2784 2784 2924 2760 2760 2899 2784 2784 2900 2808 2808 2925 2809 2809 2926 2784 2784 2900 2809 2809 2926 2785 2785 2901 2785 2785 2901 2809 2809 2926 2810 2810 2927 2785 2785 2901 2810 2810 2927 2786 2786 2902 2786 2786 2902 2810 2810 2927 2811 2811 2928 2786 2786 2902 2811 2811 2928 2787 2787 2903 2787 2787 2903 2811 2811 2928 2812 2812 2929 2787 2787 2903 2812 2812 2929 2788 2788 2904 2788 2788 2904 2812 2812 2929 2813 2813 2930 2788 2788 2904 2813 2813 2930 2789 2789 2905 2789 2789 2905 2813 2813 2930 2814 2814 2931 2789 2789 2905 2814 2814 2931 2790 2790 2906 2790 2790 2906 2814 2814 2931 2815 2815 2932 2790 2790 2906 2815 2815 2932 2791 2791 2907 2791 2791 2907 2815 2815 2932 2816 2816 2933 2791 2791 2907 2816 2816 2933 2792 2792 2908 2792 2792 2908 2816 2816 2933 2817 2817 2934 2792 2792 2908 2817 2817 2934 2793 2793 2909 2793 2793 2909 2817 2817 2934 2818 2818 2935 2793 2793 2909 2818 2818 2935 2794 2794 2910 2794 2794 2910 2818 2818 2935 2819 2819 2936 2794 2794 2910 2819 2819 2936 2795 2795 2911 2795 2795 2911 2819 2819 2936 2820 2820 2937 2795 2795 2911 2820 2820 2937 2796 2796 2912 2796 2796 2912 2820 2820 2937 2821 2821 2938 2796 2796 2912 2821 2821 2938 2797 2797 2913 2797 2797 2913 2821 2821 2938 2822 2822 2939 2797 2797 2913 2822 2822 2939 2798 2798 2914 2798 2798 2914 2822 2822 2939 2823 2823 2940 2798 2798 2914 2823 2823 2940 2799 2799 2915 2799 2799 2915 2823 2823 2940 2824 2824 2941 2799 2799 2915 2824 2824 2941 2800 2800 2916 2800 2800 2916 2824 2824 2941 2825 2825 2942 2800 2800 2916 2825 2825 2942 2801 2801 2917 2801 2801 2917 2825 2825 2942 2826 2826 2943 2801 2801 2917 2826 2826 2943 2802 2802 2918 2802 2802 2918 2826 2826 2943 2827 2827 2944 2802 2802 2918 2827 2827 2944 2803 2803 2919 2803 2803 2919 2827 2827 2944 2828 2828 2945 2803 2803 2919 2828 2828 2945 2804 2804 2920 2804 2804 2920 2828 2828 2945 2829 2829 2946 2804 2804 2920 2829 2829 2946 2805 2805 2921 2805 2805 2921 2829 2829 2946 2830 2830 2947 2805 2805 2921 2830 2830 2947 2806 2806 2922 2806 2806 2922 2830 2830 2947 2831 2831 2948 2806 2806 2922 2831 2831 2948 2807 2807 2923 2807 2807 2923 2831 2831 2948 2808 2808 2949 2807 2807 2923 2808 2808 2949 2784 2784 2924 2808 2808 2925 2832 2832 2950 2833 2833 2951 2808 2808 2925 2833 2833 2951 2809 2809 2926 2809 2809 2926 2833 2833 2951 2834 2834 2952 2809 2809 2926 2834 2834 2952 2810 2810 2927 2810 2810 2927 2834 2834 2952 2835 2835 2953 2810 2810 2927 2835 2835 2953 2811 2811 2928 2811 2811 2928 2835 2835 2953 2836 2836 2954 2811 2811 2928 2836 2836 2954 2812 2812 2929 2812 2812 2929 2836 2836 2954 2837 2837 2955 2812 2812 2929 2837 2837 2955 2813 2813 2930 2813 2813 2930 2837 2837 2955 2838 2838 2956 2813 2813 2930 2838 2838 2956 2814 2814 2931 2814 2814 2931 2838 2838 2956 2839 2839 2957 2814 2814 2931 2839 2839 2957 2815 2815 2932 2815 2815 2932 2839 2839 2957 2840 2840 2958 2815 2815 2932 2840 2840 2958 2816 2816 2933 2816 2816 2933 2840 2840 2958 2841 2841 2959 2816 2816 2933 2841 2841 2959 2817 2817 2934 2817 2817 2934 2841 2841 2959 2842 2842 2960 2817 2817 2934 2842 2842 2960 2818 2818 2935 2818 2818 2935 2842 2842 2960 2843 2843 2961 2818 2818 2935 2843 2843 2961 2819 2819 2936 2819 2819 2936 2843 2843 2961 2844 2844 2962 2819 2819 2936 2844 2844 2962 2820 2820 2937 2820 2820 2937 2844 2844 2962 2845 2845 2963 2820 2820 2937 2845 2845 2963 2821 2821 2938 2821 2821 2938 2845 2845 2963 2846 2846 2964 2821 2821 2938 2846 2846 2964 2822 2822 2939 2822 2822 2939 2846 2846 2964 2847 2847 2965 2822 2822 2939 2847 2847 2965 2823 2823 2940 2823 2823 2940 2847 2847 2965 2848 2848 2966 2823 2823 2940 2848 2848 2966 2824 2824 2941 2824 2824 2941 2848 2848 2966 2849 2849 2967 2824 2824 2941 2849 2849 2967 2825 2825 2942 2825 2825 2942 2849 2849 2967 2850 2850 2968 2825 2825 2942 2850 2850 2968 2826 2826 2943 2826 2826 2943 2850 2850 2968 2851 2851 2969 2826 2826 2943 2851 2851 2969 2827 2827 2944 2827 2827 2944 2851 2851 2969 2852 2852 2970 2827 2827 2944 2852 2852 2970 2828 2828 2945 2828 2828 2945 2852 2852 2970 2853 2853 2971 2828 2828 2945 2853 2853 2971 2829 2829 2946 2829 2829 2946 2853 2853 2971 2854 2854 2972 2829 2829 2946 2854 2854 2972 2830 2830 2947 2830 2830 2947 2854 2854 2972 2855 2855 2973 2830 2830 2947 2855 2855 2973 2831 2831 2948 2831 2831 2948 2855 2855 2973 2832 2832 2974 2831 2831 2948 2832 2832 2974 2808 2808 2949 2832 2832 2950 2856 2856 2975 2857 2857 2976 2832 2832 2950 2857 2857 2976 2833 2833 2951 2833 2833 2951 2857 2857 2976 2858 2858 2977 2833 2833 2951 2858 2858 2977 2834 2834 2952 2834 2834 2952 2858 2858 2977 2859 2859 2978 2834 2834 2952 2859 2859 2978 2835 2835 2953 2835 2835 2953 2859 2859 2978 2860 2860 2979 2835 2835 2953 2860 2860 2979 2836 2836 2954 2836 2836 2954 2860 2860 2979 2861 2861 2980 2836 2836 2954 2861 2861 2980 2837 2837 2955 2837 2837 2955 2861 2861 2980 2862 2862 2981 2837 2837 2955 2862 2862 2981 2838 2838 2956 2838 2838 2956 2862 2862 2981 2863 2863 2982 2838 2838 2956 2863 2863 2982 2839 2839 2957 2839 2839 2957 2863 2863 2982 2864 2864 2983 2839 2839 2957 2864 2864 2983 2840 2840 2958 2840 2840 2958 2864 2864 2983 2865 2865 2984 2840 2840 2958 2865 2865 2984 2841 2841 2959 2841 2841 2959 2865 2865 2984 2866 2866 2985 2841 2841 2959 2866 2866 2985 2842 2842 2960 2842 2842 2960 2866 2866 2985 2867 2867 2986 2842 2842 2960 2867 2867 2986 2843 2843 2961 2843 2843 2961 2867 2867 2986 2868 2868 2987 2843 2843 2961 2868 2868 2987 2844 2844 2962 2844 2844 2962 2868 2868 2987 2869 2869 2988 2844 2844 2962 2869 2869 2988 2845 2845 2963 2845 2845 2963 2869 2869 2988 2870 2870 2989 2845 2845 2963 2870 2870 2989 2846 2846 2964 2846 2846 2964 2870 2870 2989 2871 2871 2990 2846 2846 2964 2871 2871 2990 2847 2847 2965 2847 2847 2965 2871 2871 2990 2872 2872 2991 2847 2847 2965 2872 2872 2991 2848 2848 2966 2848 2848 2966 2872 2872 2991 2873 2873 2992 2848 2848 2966 2873 2873 2992 2849 2849 2967 2849 2849 2967 2873 2873 2992 2874 2874 2993 2849 2849 2967 2874 2874 2993 2850 2850 2968 2850 2850 2968 2874 2874 2993 2875 2875 2994 2850 2850 2968 2875 2875 2994 2851 2851 2969 2851 2851 2969 2875 2875 2994 2876 2876 2995 2851 2851 2969 2876 2876 2995 2852 2852 2970 2852 2852 2970 2876 2876 2995 2877 2877 2996 2852 2852 2970 2877 2877 2996 2853 2853 2971 2853 2853 2971 2877 2877 2996 2878 2878 2997 2853 2853 2971 2878 2878 2997 2854 2854 2972 2854 2854 2972 2878 2878 2997 2879 2879 2998 2854 2854 2972 2879 2879 2998 2855 2855 2973 2855 2855 2973 2879 2879 2998 2856 2856 2999 2855 2855 2973 2856 2856 2999 2832 2832 2974 2856 2856 2975 0 0 3000 1 3 3001 2856 2856 2975 1 3 3001 2857 2857 2976 2857 2857 2976 1 3 3001 2 5 3002 2857 2857 2976 2 5 3002 2858 2858 2977 2858 2858 2977 2 5 3002 3 7 3003 2858 2858 2977 3 7 3003 2859 2859 2978 2859 2859 2978 3 7 3003 4 9 3004 2859 2859 2978 4 9 3004 2860 2860 2979 2860 2860 2979 4 9 3004 5 11 3005 2860 2860 2979 5 11 3005 2861 2861 2980 2861 2861 2980 5 11 3005 6 13 3006 2861 2861 2980 6 13 3006 2862 2862 2981 2862 2862 2981 6 13 3006 7 15 3007 2862 2862 2981 7 15 3007 2863 2863 2982 2863 2863 2982 7 15 3007 8 17 3008 2863 2863 2982 8 17 3008 2864 2864 2983 2864 2864 2983 8 17 3008 9 19 3009 2864 2864 2983 9 19 3009 2865 2865 2984 2865 2865 2984 9 19 3009 10 21 3010 2865 2865 2984 10 21 3010 2866 2866 2985 2866 2866 2985 10 21 3010 11 23 3011 2866 2866 2985 11 23 3011 2867 2867 2986 2867 2867 2986 11 23 3011 12 25 3012 2867 2867 2986 12 25 3012 2868 2868 2987 2868 2868 2987 12 25 3012 13 27 3013 2868 2868 2987 13 27 3013 2869 2869 2988 2869 2869 2988 13 27 3013 14 29 3014 2869 2869 2988 14 29 3014 2870 2870 2989 2870 2870 2989 14 29 3014 15 31 3015 2870 2870 2989 15 31 3015 2871 2871 2990 2871 2871 2990 15 31 3015 16 33 3016 2871 2871 2990 16 33 3016 2872 2872 2991 2872 2872 2991 16 33 3016 17 35 3017 2872 2872 2991 17 35 3017 2873 2873 2992 2873 2873 2992 17 35 3017 18 37 3018 2873 2873 2992 18 37 3018 2874 2874 2993 2874 2874 2993 18 37 3018 19 39 3019 2874 2874 2993 19 39 3019 2875 2875 2994 2875 2875 2994 19 39 3019 20 41 3020 2875 2875 2994 20 41 3020 2876 2876 2995 2876 2876 2995 20 41 3020 21 43 3021 2876 2876 2995 21 43 3021 2877 2877 2996 2877 2877 2996 21 43 3021 22 45 3022 2877 2877 2996 22 45 3022 2878 2878 2997 2878 2878 2997 22 45 3022 23 47 3023 2878 2878 2997 23 47 3023 2879 2879 2998 2879 2879 2998 23 47 3023 0 0 3024 2879 2879 2998 0 0 3024 2856 2856 2999</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-7_max" name="Torus_Knot-7_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-7_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-8.DAE b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-8.DAE
new file mode 100644
index 00000000..4ec6fc56
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus Knots/TorusKnot-8.DAE
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Feeling ColladaMax v3.00 with FCollada v3.00.</authoring_tool>
+ <comments>ColladaMax Export Options: ExportNormals=1;ExportEPolyAsTriangles=1;ExportXRefs=1;ExportSelected=1;ExportTangents=0;ExportAnimations=1;SampleAnim=0;ExportAnimClip=0;BakeMatrices=0;ExportRelativePaths=1;AnimStart=0;AnimEnd=100;</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/Torus%20Knots/Torus%20Knot-8.max</source_data>
+ </contributor>
+ <created>2008-10-31T16:32:56Z</created>
+ <modified>2008-10-31T16:32:58Z</modified>
+ <unit meter="0.025400" name="inch"/>
+ <up_axis>Z_UP</up_axis>
+ </asset>
+ <library_materials>
+ <material id="Torus-Knot" name="Torus-Knot">
+ <instance_effect url="#Torus-Knot-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Torus-Knot-fx" name="Torus-Knot">
+ <profile_COMMON>
+ <technique sid="common">
+ <blinn>
+ <ambient>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </ambient>
+ <diffuse>
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </diffuse>
+ <specular>
+ <color>0.900000 0.900000 0.900000 1.000000</color>
+ </specular>
+ <shininess>
+ <float>9.999999</float>
+ </shininess>
+ <reflective>
+ <color>0 0 0 1.000000</color>
+ </reflective>
+ <reflectivity>
+ <float>1.000000</float>
+ </reflectivity>
+ <transparent opaque="RGB_ZERO">
+ <color>1.000000 1.000000 1.000000 1.000000</color>
+ </transparent>
+ <transparency>
+ <float>0</float>
+ </transparency>
+ <index_of_refraction>
+ <float>0</float>
+ </index_of_refraction>
+ </blinn>
+ <extra>
+ <technique profile="FCOLLADA">
+ <spec_level>
+ <float>0</float>
+ </spec_level>
+ <emission_level>
+ <float>0</float>
+ </emission_level>
+ </technique>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ <extra>
+ <technique profile="MAX3D">
+ <faceted>0</faceted>
+ <double_sided>0</double_sided>
+ <wireframe>0</wireframe>
+ <face_map>0</face_map>
+ </technique>
+ </extra>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus_Knot01-mesh" name="Torus_Knot01">
+ <mesh>
+ <source id="Torus_Knot01-mesh-positions">
+ <float_array id="Torus_Knot01-mesh-positions-array" count="8640">23.481520 -0.000554 21.973024 23.911232 -0.620918 22.454594 24.260260 -1.198967 22.954746 24.504816 -1.695309 23.439394 24.628237 -2.076118 23.875515 24.622110 -2.315444 24.233383 24.486853 -2.396976 24.488613 24.231684 -2.315157 24.623810 23.873991 -2.075565 24.629761 23.438150 -1.694527 24.506062 22.953865 -1.198009 24.261139 22.454140 -0.619849 23.911688 21.973026 0.000553 23.481520 21.543312 0.620917 22.999950 21.194284 1.198966 22.499802 20.949728 1.695308 22.015150 20.826307 2.076118 21.579029 20.832434 2.315444 21.221161 20.967691 2.396976 20.965931 21.222860 2.315157 20.830734 21.580553 2.075565 20.824783 22.016392 1.694527 20.948483 22.500677 1.198010 21.193405 23.000404 0.619850 21.542856 23.728848 3.216572 23.471214 24.420227 3.106905 22.828674 25.105663 2.959797 22.277262 25.738445 2.785273 21.854548 26.275448 2.595227 21.589344 26.680077 2.402610 21.499722 26.924755 2.220549 21.591789 26.992811 2.061450 21.859272 26.879606 1.936157 22.283939 26.592855 1.853207 22.836855 26.152098 1.818254 23.480335 25.587374 1.833679 24.170532 24.937166 1.898432 24.860403 24.245785 2.008099 25.502943 23.560349 2.155207 26.054358 22.927568 2.329731 26.477070 22.390564 2.519777 26.742275 21.985937 2.712394 26.831898 21.741257 2.894455 26.739830 21.673201 3.053554 26.472349 21.786406 3.178847 26.047680 22.073156 3.261797 25.494764 22.513912 3.296750 24.851284 23.078638 3.281325 24.161091 24.930962 5.730289 26.055313 24.324734 6.192425 25.248751 23.823368 6.607200 24.435263 23.461033 6.946347 23.670290 23.262421 7.186754 23.005962 23.241064 7.312038 22.487553 23.398420 7.313661 22.150389 23.723764 7.191512 22.017450 24.194927 6.953915 22.097794 24.779797 6.617063 22.385946 25.438519 6.203911 22.862268 26.126198 5.742616 23.494303 26.795975 5.264612 24.238974 27.402201 4.802476 25.045536 27.903566 4.387701 25.859024 28.265902 4.048553 26.623995 28.464516 3.808146 27.288326 28.485872 3.682862 27.806736 28.328516 3.681239 28.143900 28.003172 3.803388 28.276838 27.532011 4.040984 28.196497 26.947140 4.377836 27.908344 26.288420 4.790988 27.432020 25.600739 5.252284 26.799988 28.251091 8.492013 26.723707 27.260960 8.841068 27.585613 26.269068 9.190681 28.306446 25.343014 9.517024 28.837082 24.545904 9.797858 29.141357 23.932064 10.014047 29.198536 23.543322 10.150854 29.004725 23.406172 10.198958 28.573128 23.529959 10.155081 27.933161 23.906250 10.022213 27.128433 24.509398 9.809408 26.213789 25.298302 9.531171 25.251558 26.219198 9.206459 24.307316 27.209330 8.857404 23.445410 28.201221 8.507792 22.724577 29.127275 8.181448 22.193941 29.924385 7.900613 21.889664 30.538227 7.684424 21.832483 30.926970 7.547617 22.026295 31.064119 7.499513 22.457893 30.940332 7.543390 23.097858 30.564043 7.676258 23.902586 29.960894 7.889062 24.817230 29.171989 8.167301 25.779461 29.733931 12.005190 23.813366 30.814947 12.043784 25.087704 31.726757 12.121253 26.362215 32.407219 12.232318 27.550041 32.809959 12.369407 28.570240 32.907539 12.523181 29.353279 32.693298 12.683159 29.845800 32.181847 12.838438 30.014235 31.408033 12.978437 29.847111 30.424593 13.093616 29.355812 29.298548 13.176126 28.573822 28.106632 13.220341 27.554430 26.930077 13.223251 26.367109 25.849058 13.184657 25.092772 24.937250 13.107188 23.818260 24.256788 12.996123 22.630434 23.854044 12.859035 21.610237 23.756468 12.705260 20.827196 23.970705 12.545283 20.334675 24.482157 12.390003 20.166239 25.255970 12.250004 20.333364 26.239410 12.134825 20.824659 27.365456 12.052316 21.606649 28.557371 12.008101 22.626041 27.312010 16.167116 22.074787 28.792330 15.482954 20.884924 30.287140 14.884866 19.885704 31.694569 14.413612 19.145227 32.918705 14.101308 18.713951 33.876122 13.969234 18.621271 34.501579 14.026394 18.873499 34.752445 14.268890 19.453449 34.611629 14.680199 20.321596 34.088726 15.232288 21.418776 33.219372 15.887533 22.670223 32.062813 16.601286 23.990650 30.697861 17.324898 25.290071 29.217541 18.009060 26.479937 27.722733 18.607149 27.479155 26.315302 19.078402 28.219633 25.091166 19.390707 28.650909 24.133747 19.522781 28.743589 23.508291 19.465622 28.491362 23.257423 19.223125 27.911415 23.398237 18.811819 27.043268 23.921139 18.259729 25.946085 24.790493 17.604483 24.694639 25.947054 16.890732 23.374212 27.084385 22.197252 22.807348 25.488012 21.116167 21.436108 24.136482 20.035917 20.043896 23.121895 19.030117 18.725592 22.513395 18.167315 17.571037 22.352451 17.506304 16.658913 22.650030 17.092134 16.051374 23.385853 16.953030 15.789829 24.509773 17.098471 15.892099 25.945200 17.518547 16.351215 27.594309 18.184629 17.135887 29.344717 19.051323 18.192646 31.077139 20.059570 19.449471 32.673512 21.140656 20.820711 34.025040 22.220905 22.212923 35.039627 23.226706 23.531225 35.648129 24.089510 24.685781 35.809074 24.750521 25.597908 35.511497 25.164690 26.205446 34.775673 25.303793 26.466991 33.651756 25.158354 26.364723 32.216328 24.738277 25.905607 30.567219 24.072197 25.120935 28.816811 23.205502 24.064177 30.552507 27.480211 18.684938 28.572622 28.481934 20.186312 26.580029 29.284462 21.493797 24.710514 29.833103 22.518290 23.091488 30.090471 23.189972 21.833282 30.039024 23.463070 21.021639 29.682270 23.318975 20.711874 29.044518 22.767506 20.925095 28.169235 21.846241 21.646772 27.116064 20.617966 22.827724 25.956783 19.166386 24.387470 24.770390 17.590424 26.219719 23.637737 15.997476 28.199602 22.636015 14.496101 30.192196 21.833487 13.188617 32.061710 21.284843 12.164124 33.680737 21.027475 11.492440 34.938946 21.078922 11.219339 35.750587 21.435677 11.363436 36.060356 22.073425 11.914906 35.847134 22.948709 12.836167 35.125458 24.001881 14.064443 33.944508 25.161163 15.516024 32.384762 26.347555 17.091986 29.285734 28.321554 10.399840 31.053587 30.481014 11.284438 32.530739 32.590717 12.243093 33.616524 34.506901 13.210474 34.236946 36.098965 14.120655 34.349724 37.258430 14.911610 33.947178 37.906269 15.529435 33.056732 37.998333 15.932027 31.739077 37.528355 16.091949 30.084002 36.528358 15.998305 28.204302 35.066486 15.657475 26.228073 33.242374 15.092687 24.289995 31.180326 14.342429 22.522141 29.020866 13.457830 21.044989 26.911161 12.499175 19.959204 24.994982 11.531795 19.338781 23.402910 10.621614 19.226000 22.243448 9.830659 19.628548 21.595610 9.212833 20.518991 21.503544 8.810242 21.836647 21.973522 8.650318 23.491720 22.973520 8.743962 25.371422 24.435387 9.084791 27.347649 26.259499 9.649580 22.134180 30.395597 5.942560 24.424715 29.217262 4.240820 26.702822 28.321707 2.689762 28.813250 27.769958 1.395087 30.612177 27.599621 0.445026 31.977011 27.822300 -0.095677 32.814735 28.422819 -0.190171 33.068268 29.360256 0.167979 32.720329 30.570726 0.954369 31.794626 31.971739 2.115406 30.354248 33.467819 3.571968 28.497353 34.957001 5.224793 26.350485 36.337814 6.961244 24.059950 37.516148 8.662984 21.781845 38.411705 10.214043 19.671415 38.963455 11.508717 17.872486 39.133793 12.458779 16.507652 38.911118 12.999483 15.669926 38.310596 13.093979 15.416392 37.373158 12.735828 15.764332 36.162689 11.949440 16.690033 34.761677 10.788403 18.130411 33.265598 9.331841 19.987305 31.776411 7.679016 18.135527 37.641972 2.076852 16.659166 34.869030 2.008728 15.467270 32.178913 1.803711 14.641061 29.754946 1.475775 14.236846 27.762323 1.047266 14.282170 26.336834 0.547389 14.773945 25.575624 0.010207 15.678657 25.530571 -0.527670 16.934650 26.204741 -1.029587 18.456333 27.552195 -1.461340 20.140005 29.481102 -1.793505 21.870926 31.860012 -2.003446 23.531136 34.526810 -2.076856 25.007494 37.299751 -2.008731 26.199392 39.989868 -1.803715 27.025600 42.413834 -1.475779 27.429817 44.406456 -1.047271 27.384495 45.831951 -0.547393 26.892721 46.593159 -0.010212 25.988008 46.638214 0.527665 24.732016 45.964043 1.029583 23.210333 44.616592 1.461336 21.526661 42.687683 1.793501 19.795742 40.308777 2.003442 18.290018 40.990070 -6.967422 16.021027 42.158855 -5.230596 13.803434 43.022263 -3.576999 11.788366 43.521461 -2.119323 10.113146 43.622417 -0.956906 8.891936 43.318268 -0.168964 8.207963 42.629726 0.190806 8.107835 41.603725 0.097886 8.598376 40.310181 -0.441391 9.646158 38.837242 -1.390274 11.179776 37.285297 -2.684100 13.094715 35.760098 -4.234695 15.260477 34.365593 -5.936390 17.529469 33.196804 -7.673216 19.747061 32.333397 -9.326812 21.762129 31.834202 -10.784489 23.437351 31.733238 -11.946907 24.658560 32.037392 -12.734850 25.342535 32.725929 -13.094621 25.442663 33.751934 -13.001701 24.952124 35.045479 -12.462425 23.904343 36.518414 -11.513541 22.370726 38.070362 -10.219717 20.455788 39.595562 -8.669122 14.857618 36.625889 -14.342834 15.670384 39.335171 -15.098009 16.258312 41.958534 -15.667353 16.581335 44.317207 -16.012064 16.617439 46.250443 -16.108654 16.364166 47.626495 -15.950536 15.838773 48.351597 -15.548490 15.077066 48.376320 -14.929911 14.130956 47.698997 -14.136957 13.064916 46.365768 -13.223665 11.951595 44.467506 -12.252275 10.866866 42.133560 -11.288985 9.884651 39.522995 -10.399443 9.071884 36.813713 -9.644267 8.483956 34.190350 -9.074924 8.160933 31.831680 -8.730211 8.124828 29.898441 -8.633622 8.378101 28.522385 -8.791739 8.903494 27.797285 -9.193786 9.665200 27.772556 -9.812364 10.611311 28.449883 -10.605317 11.677350 29.783108 -11.518608 12.790670 31.681372 -12.489999 13.875400 34.015316 -13.453288 7.366381 34.527290 -15.992057 9.262596 33.506626 -17.585835 11.068791 32.748737 -19.162941 12.661879 32.305275 -20.615898 13.933290 32.206463 -21.845692 14.796382 32.459023 -22.768513 15.192336 33.045761 -23.321470 15.094169 33.926682 -23.466883 14.508571 35.041748 -23.194841 13.475449 36.314980 -22.523886 12.065207 37.659603 -21.499739 10.373954 38.983986 -20.192194 8.516944 40.197872 -18.690361 6.620729 41.218536 -17.096584 4.814534 41.976425 -15.519478 3.221447 42.419888 -14.066519 1.950034 42.518707 -12.836725 1.086940 42.266140 -11.913903 0.690986 41.679409 -11.360947 0.789153 40.798485 -11.215532 1.374750 39.683418 -11.487572 2.407872 38.410187 -12.158527 3.818112 37.065567 -13.182674 5.509365 35.741184 -14.490219 1.834263 36.943676 -19.448839 1.831934 34.941479 -18.188425 1.960820 32.994305 -17.128366 2.212137 31.234848 -16.340904 2.568758 29.783016 -15.879703 3.006381 28.737749 -15.776193 3.495181 28.170279 -16.037426 4.001848 28.119280 -16.645603 4.491853 28.588224 -17.559273 4.931804 29.545155 -18.716175 5.291718 30.924862 -20.037468 5.547069 32.633316 -21.433105 5.680453 34.554092 -22.807980 5.682782 36.556290 -24.068394 5.553896 38.503464 -25.128450 5.302579 40.262920 -25.915915 4.945958 41.714756 -26.377117 4.508336 42.760021 -26.480629 4.019536 43.327492 -26.219395 3.512869 43.378490 -25.611219 3.022863 42.909550 -24.697548 2.582912 41.952618 -23.540648 2.222998 40.572914 -22.219355 1.967648 38.864460 -20.823717 -0.350386 35.244049 -25.292780 -1.658573 36.064835 -23.992716 -2.853732 36.710285 -22.671507 -3.854414 37.136417 -21.419193 -4.592423 37.314190 -20.321114 -5.017467 37.231483 -19.452103 -5.100579 36.893944 -18.871380 -4.836095 36.324562 -18.618523 -4.242040 35.562153 -18.710762 -3.358896 34.658661 -19.141815 -2.246850 33.675671 -19.882299 -0.981684 32.680161 -20.881758 0.350381 31.739977 -22.072077 1.658568 30.919191 -23.372139 2.853727 30.273739 -24.693346 3.854409 29.847609 -25.945662 4.592419 29.669836 -27.043741 5.017464 29.752541 -27.912754 5.100576 30.090082 -28.493477 4.836093 30.659460 -28.746332 4.242038 31.421871 -28.654093 3.358895 32.325356 -28.223043 2.246849 33.308353 -27.482557 0.981684 34.303864 -26.483099 -2.014434 29.933153 -26.367704 -2.608909 30.947565 -27.555809 -3.246513 31.954874 -28.575890 -3.883793 32.886433 -29.358425 -4.477321 33.678761 -29.850094 -4.986647 34.277859 -30.017385 -5.377062 34.642902 -29.848900 -5.621962 34.749012 -29.356119 -5.704654 34.588955 -28.572626 -5.619505 34.173641 -27.551815 -5.372317 33.531372 -26.363249 -4.979936 32.705917 -25.087931 -4.469101 31.753532 -23.812771 -3.874626 30.739122 -22.624666 -3.237023 29.731812 -21.604586 -2.599742 28.800249 -20.822046 -2.006215 28.007923 -20.330379 -1.496888 27.408823 -20.163088 -1.106472 27.043781 -20.331573 -0.861573 26.937672 -20.824352 -0.778881 27.097729 -21.607845 -0.864029 27.513044 -22.628658 -1.111217 28.155312 -23.817223 -1.503598 28.980764 -25.092541 -5.133429 27.312683 -24.307734 -4.392810 26.676865 -25.252350 -3.758578 26.131962 -26.214901 -3.273954 25.715107 -27.129791 -2.971964 25.454712 -27.934671 -2.873190 25.368519 -28.574688 -2.984362 25.462402 -29.006226 -3.297903 25.729965 -29.199881 -3.792447 26.152973 -29.142450 -4.434291 26.702597 -28.837851 -5.179695 27.341385 -28.306839 -5.977860 28.025801 -27.585602 -6.774394 28.709204 -26.723293 -7.515012 29.345022 -25.778677 -8.149245 29.889927 -24.816124 -8.633869 30.306780 -23.901236 -8.935859 30.567177 -23.096355 -9.034634 30.653370 -22.456337 -8.923462 30.559486 -22.024799 -8.609921 30.291924 -21.831144 -8.115377 29.868917 -21.888577 -7.473534 29.319292 -22.193172 -6.728130 28.680504 -22.724186 -5.929965 27.996088 -23.445421 -8.837599 25.838964 -24.238672 -8.086984 25.499699 -23.494967 -7.342080 25.136408 -22.863855 -6.653653 24.773848 -22.388346 -6.068617 24.436728 -22.100842 -5.626842 24.148022 -22.020941 -5.358433 23.927402 -22.154085 -5.281682 23.789907 -22.491201 -5.401822 23.744907 -23.009315 -5.710661 23.795465 -23.673119 -6.187156 23.938139 -24.437376 -6.798833 24.163206 -25.250002 -7.504008 24.455324 -26.055618 -8.254623 24.794590 -26.799324 -8.999527 25.157881 -27.430437 -9.687954 25.520441 -27.905949 -10.272990 25.857561 -28.193451 -10.714766 26.146267 -28.273352 -10.983175 26.366886 -28.140207 -11.059925 26.504381 -27.803091 -10.939787 26.549381 -27.284977 -10.630947 26.498823 -26.621176 -10.154452 26.356150 -25.856918 -9.542776 26.131084 -25.044292 -10.825844 22.544140 -24.859064 -11.206099 23.075428 -24.169117 -11.500864 23.557398 -23.478945 -11.690053 23.957205 -22.835577 -11.760772 24.247604 -22.282866 -11.708201 24.408804 -21.858475 -11.535925 24.429817 -21.591324 -11.255682 24.309216 -21.499619 -10.886571 24.055216 -21.589611 -10.453746 23.685127 -21.855167 -9.986704 23.224171 -22.278189 -9.517273 22.703762 -22.829849 -9.077443 22.159365 -23.472553 -8.697188 21.628075 -24.162500 -8.402422 21.146105 -24.852674 -8.213234 20.746298 -25.496038 -8.142514 20.455898 -26.048752 -8.195085 20.294699 -26.473145 -8.367361 20.273685 -26.740295 -8.647604 20.394287 -26.832001 -9.016714 20.648287 -26.742008 -9.449539 21.018375 -26.476454 -9.916581 21.479332 -26.053432 -10.386013 21.999739 -25.501770 -10.987025 19.028900 -23.481520 -11.765591 19.134697 -23.910538 -12.516763 19.277821 -24.258919 -13.189351 19.448513 -24.502920 -13.737520 19.635147 -24.625914 -14.123913 19.824999 -24.619518 -14.322198 20.005133 -24.484171 -14.318862 20.163271 -24.229092 -14.114132 20.288639 -23.871668 -13.721960 20.372694 -23.436255 -13.169073 20.409704 -22.952524 -12.493149 20.397150 -22.453445 -11.740250 20.335888 -21.973026 -10.961685 20.230091 -21.544006 -10.210513 20.086967 -21.195627 -9.537924 19.916275 -20.951626 -8.989755 19.729641 -20.828630 -8.603361 19.539789 -20.835026 -8.405076 19.359655 -20.970373 -8.408412 19.201517 -21.225452 -8.613142 19.076149 -21.582876 -9.005313 18.992094 -22.018290 -9.558200 18.955084 -22.502018 -10.234124 18.967636 -23.001099 -11.437623 17.109011 -20.500303 -11.213020 16.486412 -21.182076 -11.074210 15.910136 -21.848530 -11.030651 15.419454 -22.454243 -11.085312 15.047804 -22.957941 -11.234468 14.820515 -23.325296 -11.467955 14.753074 -23.531273 -11.769859 14.850079 -23.561836 -12.119608 15.104920 -23.414902 -12.493367 15.500227 -23.100485 -12.865664 16.009064 -22.640009 -13.211127 16.596752 -22.064857 -13.506215 17.223242 -21.414225 -13.730818 17.845840 -20.732452 -13.869628 18.422115 -20.066002 -13.913187 18.912798 -19.460287 -13.858526 19.284447 -18.956587 -13.709370 19.511738 -18.589233 -13.475883 19.579178 -18.383255 -13.173979 19.482174 -18.352692 -12.824230 19.227333 -18.499626 -12.450472 18.832026 -18.814043 -12.078176 18.323191 -19.274519 -11.732712 17.735500 -19.849670 -13.599134 15.733473 -18.044600 -12.535991 15.667376 -17.733183 -11.527266 15.542814 -17.504879 -10.641702 15.368279 -17.375248 -9.939649 15.155662 -17.353123 -9.468949 14.919454 -17.440010 -9.261683 14.675752 -17.629990 -9.331972 14.441163 -17.910114 -9.675029 14.231675 -18.261295 -10.267473 14.061563 -18.659599 -11.068932 13.942422 -19.077883 -12.024785 13.882370 -19.487640 -13.069895 13.885498 -19.860947 -14.133039 13.951595 -20.172365 -15.141764 14.076156 -20.400667 -16.027328 14.250692 -20.530300 -16.729382 14.463309 -20.552427 -17.200081 14.699516 -20.465538 -17.407349 14.943219 -20.275558 -17.337059 15.177808 -19.995434 -16.994003 15.387296 -19.644255 -16.401560 15.557406 -19.245951 -15.600101 15.676548 -18.827667 -14.644247 15.736601 -18.417908 -15.575462 12.647869 -17.156702 -15.707871 13.642347 -16.240971 -15.723927 14.566209 -15.362394 -15.622535 15.356494 -14.580846 -15.410604 15.959347 -13.949588 -15.102579 16.333683 -13.511637 -14.719450 16.453991 -13.296841 -14.287327 16.312077 -13.319839 -13.835658 15.917606 -13.579060 -13.395225 15.297465 -14.056839 -12.996039 14.493913 -14.720621 -12.665309 13.561712 -15.525164 -12.425570 12.564389 -16.415644 -12.293160 11.569912 -17.331373 -12.277105 10.646050 -18.209949 -12.378497 9.855765 -18.991499 -12.590427 9.252912 -19.622757 -12.898452 8.878575 -20.060709 -13.281581 8.758265 -20.275505 -13.713704 8.900181 -20.252508 -14.165373 9.294650 -19.993288 -14.605807 9.914791 -19.515509 -15.004992 10.718343 -18.851727 -15.335723 11.650544 -18.047184 -14.336586 9.023499 -15.786871 -15.989115 9.119175 -16.019285 -17.540846 9.311823 -16.148849 -18.886032 9.588318 -16.166729 -19.933001 9.929815 -16.071709 -20.610403 10.313043 -15.870265 -20.872074 10.711884 -15.576123 -20.700184 11.099160 -15.209329 -20.106445 11.448478 -14.794880 -19.131319 11.736031 -14.361019 -17.841259 11.942224 -13.937315 -16.324183 12.053005 -13.552640 -14.683475 12.060825 -13.233210 -13.030946 11.965149 -13.000795 -11.479215 11.772501 -12.871231 -10.134028 11.496007 -12.853351 -9.087058 11.154510 -12.948371 -8.409655 10.771281 -13.149816 -8.147983 10.372439 -13.443957 -8.319873 9.985164 -13.810751 -8.913612 9.635847 -14.225201 -9.888738 9.348293 -14.659060 -11.178796 9.142100 -15.082766 -12.695872 9.031319 -15.467441 -12.506908 8.533122 -11.881763 -12.486478 6.951463 -13.136010 -12.630181 5.482122 -14.323858 -12.928227 4.225235 -15.364361 -13.360303 3.266455 -16.186605 -13.896963 2.671122 -16.734562 -14.501636 2.479806 -16.970882 -15.133113 2.705545 -16.879469 -15.748362 3.332957 -16.466545 -16.305452 4.319283 -15.760256 -16.766422 5.597307 -14.808730 -17.099854 7.079933 -13.676814 -17.283028 8.666124 -12.441647 -17.303459 10.247784 -11.187400 -17.159756 11.717124 -9.999552 -16.861710 12.974011 -8.959051 -16.429634 13.932793 -8.136804 -15.892974 14.528127 -7.588847 -15.288301 14.719443 -7.352525 -14.656824 14.493704 -7.443938 -14.041575 13.866294 -7.856861 -13.484484 12.879969 -8.563151 -13.023515 11.601945 -9.514676 -12.690083 10.119318 -10.646592 -15.252464 9.022119 -8.088330 -12.894420 8.880838 -7.957536 -10.692142 8.594934 -7.950058 -8.795714 8.183889 -8.066408 -7.334374 7.675717 -8.298656 -6.407709 7.105047 -8.630975 -6.078869 6.510770 -9.040718 -6.370265 5.933385 -9.499961 -7.262038 5.412240 -9.977408 -8.693418 4.982850 -10.440521 -10.566854 4.674477 -10.857741 -12.754678 4.508137 -11.200635 -15.107792 4.495164 -11.445834 -17.465836 4.636443 -11.576630 -19.668114 4.922347 -11.584106 -21.564541 5.333392 -11.467756 -23.025885 5.841565 -11.235509 -23.952551 6.412235 -10.903190 -24.281391 7.006511 -10.493447 -23.989996 7.583897 -10.034204 -23.098223 8.105042 -9.556757 -21.666845 8.534432 -9.093643 -19.793409 8.842805 -8.676423 -17.605585 9.009146 -8.333530 -18.571192 5.074413 -7.510144 -18.491465 7.256051 -5.957210 -18.199986 9.283852 -4.498767 -17.716619 11.019623 -3.234204 -17.074306 12.345077 -2.249700 -16.316820 13.169883 -1.612347 -15.495780 13.437834 -1.365580 -14.667139 13.130670 -1.526215 -13.887368 12.269322 -2.083305 -13.209607 10.912492 -2.998886 -12.680045 9.152643 -4.210562 -12.334770 7.109708 -5.635759 -12.197312 4.922908 -7.177353 -12.277039 2.741271 -8.730288 -12.568517 0.713470 -10.188731 -13.051882 -1.022302 -11.453294 -13.694195 -2.347756 -12.437799 -14.451682 -3.172564 -13.075152 -15.272722 -3.440516 -13.321920 -16.101362 -3.133352 -13.161285 -16.881134 -2.272007 -12.604197 -17.558895 -0.915176 -11.688616 -18.088457 0.844672 -10.476940 -18.433733 2.887607 -9.051743 -15.509897 0.421244 -6.874786 -18.433615 0.570780 -6.899141 -21.158838 0.906246 -6.787489 -23.499849 1.404780 -6.547441 -25.297110 2.032409 -6.195353 -26.428143 2.746360 -5.755222 -26.815866 3.497979 -5.257041 -26.433863 4.236044 -4.734759 -25.308159 4.910257 -4.223971 -23.515474 5.474672 -3.759485 -21.177977 5.890826 -3.372955 -18.454962 6.130357 -3.090723 -15.531998 6.176941 -2.932021 -12.608281 6.027406 -2.907666 -9.883058 5.691940 -3.019318 -7.542046 5.193406 -3.259366 -5.744783 4.565777 -3.611454 -4.613750 3.851826 -4.051585 -4.226024 3.100208 -4.549766 -4.608028 2.362143 -5.072047 -5.733729 1.687929 -5.582836 -7.526413 1.123514 -6.047322 -9.863911 0.707361 -6.433852 -12.586926 0.467829 -6.716084 -11.921492 1.605284 -2.400137 -12.045636 -0.954746 -4.121118 -12.411965 -3.337976 -5.728470 -12.995515 -5.381994 -7.112656 -13.756516 -6.947504 -8.179346 -14.643107 -7.927818 -8.855845 -15.594871 -8.256128 -9.096053 -16.546944 -7.910065 -8.883598 -17.434444 -6.913208 -8.232962 -18.196892 -5.333493 -7.188480 -18.782326 -3.278574 -5.821336 -19.150850 -0.888492 -4.224696 -19.277349 1.673874 -2.507370 -19.153206 4.233903 -0.786389 -18.786877 6.617133 0.820963 -18.203327 8.661151 2.205149 -17.442327 10.226664 3.271840 -16.555735 11.206978 3.948340 -15.603972 11.535290 4.188549 -14.651899 11.189227 3.976095 -13.764399 10.192370 3.325458 -13.001951 8.612658 2.280979 -12.416516 6.557739 0.913834 -12.047992 4.167657 -0.682805 -15.624938 3.115395 2.076496 -12.485321 3.009386 2.005430 -9.559667 2.698292 1.797695 -7.047355 2.203317 1.467448 -5.119596 1.558190 1.037195 -3.907764 0.806876 0.536257 -3.494441 0.000576 -0.001228 -3.907795 -0.805761 -0.538631 -5.119657 -1.557187 -1.039330 -7.047441 -2.202492 -1.469202 -9.559771 -2.697699 -1.798952 -12.485435 -3.009061 -2.006109 -15.625057 -3.115360 -2.076555 -18.764673 -3.009351 -2.005490 -21.690329 -2.698259 -1.797755 -24.202639 -2.203284 -1.467509 -26.130402 -1.558157 -1.037255 -27.342236 -0.806843 -0.536317 -27.755560 -0.000543 0.001168 -27.342207 0.805795 0.538571 -26.130344 1.557220 1.039270 -24.202562 2.202525 1.469142 -21.690233 2.697733 1.798893 -18.764568 3.009096 2.006050 -19.277338 -1.674195 2.508151 -19.150690 0.888047 4.225658 -18.782026 3.278037 5.822410 -18.196476 5.332902 7.189589 -17.433939 6.912606 8.234025 -16.546383 7.909495 8.884542 -15.594294 8.255631 9.096807 -14.642553 7.927431 8.856358 -13.756022 6.947255 8.179576 -12.995117 5.381904 7.112586 -12.411690 3.338052 5.728101 -12.045501 0.954986 4.120471 -11.921506 -1.604894 2.399253 -12.048155 -4.167135 0.681746 -12.416818 -6.557125 -0.915005 -13.002368 -8.611990 -2.282185 -13.764905 -10.191696 -3.326623 -14.652461 -11.188585 -3.977140 -15.604550 -11.534724 -4.189407 -16.556290 -11.206524 -3.948957 -17.442822 -10.226350 -3.272177 -18.203728 -8.660998 -2.205187 -18.787155 -6.617148 -0.820702 -19.153343 -4.234082 0.786928 -15.532315 -6.176611 2.931539 -18.455248 -6.130225 3.090974 -21.178211 -5.890899 3.373921 -23.515642 -5.474943 3.761096 -25.308249 -4.910705 4.226115 -26.433865 -4.236635 4.737286 -26.815786 -3.498672 5.259775 -26.427982 -2.747104 5.757976 -25.296883 -2.033152 6.197935 -23.499569 -1.405469 6.549671 -21.158525 -0.906831 6.789214 -18.433292 -0.571218 6.900239 -15.509585 -0.421504 6.875180 -12.586655 -0.467890 6.715745 -9.863690 -0.707216 6.432798 -7.526258 -1.123171 6.045624 -5.733651 -1.687410 5.580605 -4.608033 -2.361479 5.069434 -4.226110 -3.099443 4.546944 -4.613914 -3.851010 4.048744 -5.745013 -4.564963 3.608785 -7.542325 -5.192646 3.257048 -9.883368 -5.691284 3.017505 -12.608602 -6.026896 2.906480 -12.197367 -4.922738 7.176266 -12.335273 -7.109185 5.634198 -12.680963 -9.151800 4.208631 -13.210877 -10.911383 2.996713 -13.888904 -12.268021 2.081035 -14.668837 -13.129261 1.523999 -15.497523 -13.436413 1.363566 -16.318491 -13.168543 1.610669 -17.075792 -12.343906 2.248467 -17.717819 -11.018702 3.233498 -18.200815 -9.283238 4.498631 -18.491869 -7.255785 5.957652 -18.571144 -5.074511 7.511129 -18.433239 -2.888065 9.053196 -18.087549 -0.845450 10.478764 -17.557634 0.914133 11.690681 -16.879608 2.270773 12.606361 -16.099676 3.132015 13.163398 -15.270989 3.439167 13.323832 -14.450021 3.171298 13.076729 -13.692719 2.346663 12.438931 -13.050694 1.021458 11.453901 -12.567696 -0.714005 10.188767 -12.276642 -2.741457 8.729747 -15.107035 -4.495643 11.446455 -12.754019 -4.508581 11.200237 -10.566338 -4.674856 10.856349 -8.693081 -4.983134 10.438224 -7.261905 -5.412407 9.974360 -6.370344 -5.933421 9.496365 -6.079154 -6.510670 9.036815 -6.408183 -7.104815 8.627028 -7.335004 -7.675366 8.294929 -8.796457 -8.183442 8.063151 -10.692948 -8.594417 7.947490 -12.895233 -8.880284 7.955827 -15.253230 -9.021563 8.087594 -17.606245 -9.008624 8.333812 -19.793926 -8.842350 8.677700 -21.667183 -8.534073 9.095824 -23.098362 -8.104799 9.559690 -23.989923 -7.583785 10.037685 -24.281113 -7.006536 10.497235 -23.952085 -6.412391 10.907022 -23.025265 -5.841839 11.239120 -21.563812 -5.333764 11.470899 -19.667322 -4.922789 11.586559 -17.465038 -4.636922 11.578222 -17.282909 -8.665888 12.442792 -17.098896 -7.080209 13.678506 -16.764688 -5.598073 14.810849 -16.303064 -4.320486 15.762653 -15.745481 -3.334510 16.469057 -15.129937 -2.707343 16.881916 -14.498381 -2.481720 16.973099 -13.893852 -2.673020 16.736389 -13.357548 -3.268206 16.187920 -12.926017 -4.226716 15.365067 -12.628668 -5.483231 14.323906 -12.485763 -6.952118 13.135391 -12.507042 -8.533279 11.880519 -12.691055 -10.118958 10.644805 -13.025262 -11.601094 9.512462 -13.486886 -12.878681 8.560657 -14.044470 -13.864658 7.854253 -14.660013 -14.491826 7.441392 -15.291570 -14.717449 7.350210 -15.896099 -14.526150 7.586918 -16.432404 -13.930964 8.135388 -16.863934 -12.972455 8.958241 -17.161283 -11.715940 9.999401 -17.304188 -10.247053 11.187916 -14.684666 -12.060126 13.232532 -16.325130 -12.052265 13.553246 -17.841902 -11.941489 13.939160 -19.131609 -11.735349 14.363976 -20.106365 -11.447891 14.798742 -20.699741 -11.098707 15.213832 -20.871300 -10.711594 15.580955 -20.609348 -10.312929 15.875094 -19.931740 -9.929884 16.076204 -18.884649 -9.588562 16.170578 -17.539438 -9.312223 16.151787 -15.987779 -9.119700 16.021111 -14.335413 -9.024114 15.787454 -12.694948 -9.031975 15.466741 -11.178179 -9.142751 15.080826 -9.888470 -9.348891 14.656010 -8.913713 -9.636348 14.221243 -8.320336 -9.985532 13.806155 -8.148777 -10.372646 13.439031 -8.410728 -10.771311 13.144892 -9.088336 -11.154355 12.943782 -10.135425 -11.495677 12.849407 -11.480637 -11.772016 12.868198 -13.032295 -11.964540 12.998875 -12.425905 -12.564364 16.414190 -12.666594 -13.561178 15.523387 -12.998187 -14.492904 14.718637 -13.398088 -15.296045 14.054784 -13.839045 -15.915871 13.577065 -14.291006 -16.310139 13.318041 -14.723171 -16.451982 13.295359 -15.106091 -16.331736 13.510568 -15.413667 -15.957590 13.949000 -15.624941 -15.355045 14.580778 -15.725513 -14.565165 15.362846 -15.708531 -13.641775 16.241909 -15.575151 -12.647805 17.158060 -15.334464 -11.650991 18.048862 -15.002871 -10.719266 18.853613 -14.602970 -9.916124 19.517466 -14.162013 -9.296297 19.995184 -13.710052 -8.902029 20.254210 -13.277885 -8.760185 20.276892 -12.894967 -8.880432 20.061684 -12.587390 -9.254578 19.623251 -12.376117 -9.857121 18.991472 -12.275543 -10.647002 18.209404 -12.292525 -11.570392 17.330341 -13.068886 -13.885989 19.861156 -12.024165 -13.882722 19.486752 -11.068744 -13.942610 19.075953 -10.267732 -14.061570 18.656754 -9.675717 -14.231496 18.257729 -9.333044 -14.440807 17.906063 -9.263066 -14.675241 17.625729 -9.470552 -14.918819 17.435827 -9.941361 -15.154943 17.349298 -10.643410 -15.367522 17.372040 -11.528852 -15.542068 17.502504 -12.537350 -15.666686 17.731800 -13.600174 -15.732884 18.044298 -14.644895 -15.736152 18.418705 -15.600316 -15.676264 18.829504 -16.401329 -15.557304 19.248701 -16.993343 -15.387378 19.647728 -17.336018 -15.178066 19.999393 -17.405996 -14.943634 20.279728 -17.198509 -14.700055 20.469629 -16.727701 -14.463931 20.556158 -16.025654 -14.251352 20.533417 -15.140210 -14.076806 20.402952 -14.131713 -13.952188 20.173656 -13.505591 -17.223528 21.415606 -13.209571 -16.597542 22.066305 -12.863281 -16.010303 22.641420 -12.490324 -15.501825 23.101761 -12.116113 -15.106766 23.415955 -11.766150 -14.852041 23.562590 -11.464288 -14.755018 23.531673 -11.231093 -14.822301 23.325314 -11.082462 -15.049312 22.957573 -11.028521 -15.420573 22.453508 -11.072946 -15.910789 21.847479 -11.212710 -16.486549 21.180777 -11.438289 -17.108620 20.498842 -11.734309 -17.734606 19.848143 -12.080598 -18.321846 19.273029 -12.453556 -18.830324 18.812689 -12.827767 -19.225384 18.498493 -13.177729 -19.480108 18.351858 -13.479592 -19.577131 18.382774 -13.712786 -19.509848 18.589134 -13.861418 -19.282839 18.956875 -13.915359 -18.911577 19.460939 -13.870934 -18.421360 20.066969 -13.731171 -17.845600 20.733671 -11.741349 -20.335234 21.973009 -12.493428 -20.397160 22.454628 -13.168515 -20.410374 22.954823 -13.720604 -20.373972 23.439510 -14.112072 -20.290438 23.875654 -14.316240 -20.165462 24.233540 -14.319196 -20.007563 24.488771 -14.120736 -19.827499 24.623957 -13.734387 -19.637545 24.629885 -13.186477 -19.450642 24.506149 -12.514345 -19.279528 24.261185 -11.763797 -19.135866 23.911686 -10.985979 -19.029444 23.481468 -10.233901 -18.967518 22.999849 -9.558814 -18.954304 22.499655 -9.006724 -18.990705 22.014969 -8.615255 -19.074240 21.578821 -8.411087 -19.199215 21.220938 -8.408132 -19.357115 20.965706 -8.606590 -19.537178 20.830519 -8.992940 -19.727133 20.824591 -9.540850 -19.914036 20.948326 -10.212981 -20.085150 21.193289 -10.963530 -20.228811 21.542789 -9.078838 -22.158037 23.471167 -9.519522 -22.701963 22.828651 -9.989655 -23.222019 22.277260 -10.457201 -23.682766 21.854567 -10.890296 -24.052799 21.589378 -11.259425 -24.306904 21.499767 -11.539434 -24.427767 21.591843 -11.711240 -24.407146 21.859327 -11.763135 -24.246452 22.283993 -11.691582 -23.956631 22.836899 -11.501457 -23.557436 23.480364 -11.205717 -23.076073 24.170542 -10.824517 -22.545343 24.860394 -10.383834 -22.001417 25.502909 -9.913700 -21.481361 26.054302 -9.446155 -21.020615 26.476994 -9.013060 -20.650583 26.742184 -8.643929 -20.396477 26.831793 -8.363921 -20.275614 26.739719 -8.192115 -20.296234 26.472235 -8.140220 -20.456928 26.047569 -8.211773 -20.746750 25.494663 -8.401897 -21.145945 24.851198 -8.697637 -21.627306 24.161022 -7.502876 -24.455938 26.055246 -6.799579 -24.162037 25.248642 -6.189732 -23.935265 24.435122 -5.714894 -23.791075 23.670122 -5.407427 -23.739296 23.005779 -5.288281 -23.783455 22.487364 -5.365579 -23.920540 22.150209 -5.634050 -24.141212 22.017288 -6.075400 -24.430433 22.097662 -6.659552 -24.768494 22.385851 -7.346696 -25.132351 22.862217 -8.090005 -25.497213 23.494295 -8.838822 -25.838213 24.239012 -9.542120 -26.132114 25.045614 -10.151967 -26.358887 25.859135 -10.626804 -26.503077 26.624134 -10.934273 -26.554855 27.288477 -11.053418 -26.510696 27.806892 -10.976121 -26.373611 28.144049 -10.707650 -26.152939 28.276970 -10.266300 -25.863718 28.196596 -9.682149 -25.525660 27.908409 -8.995005 -25.161800 27.432043 -8.251697 -24.796938 26.799965 -6.771347 -28.712049 26.723698 -5.974069 -28.029020 27.585604 -5.175422 -27.344749 28.306437 -4.429832 -26.705877 28.837072 -3.788110 -26.155939 29.141348 -3.293988 -25.732410 29.198528 -2.981139 -25.464153 29.004721 -2.870883 -25.369453 28.573126 -2.970736 -25.454762 27.933161 -3.273890 -25.714264 27.128439 -3.759688 -26.130278 26.213797 -4.395022 -26.674448 25.251568 -5.136596 -27.309698 24.307325 -5.933873 -27.992727 23.445419 -6.732520 -28.676994 22.724586 -7.478109 -29.315868 22.193951 -8.119833 -29.865808 21.889673 -8.613955 -30.289337 21.832491 -8.926805 -30.557594 22.026300 -9.037060 -30.652294 22.457895 -8.937208 -30.566986 23.097858 -8.634054 -30.307484 23.902582 -8.148257 -29.891472 24.817223 -7.512923 -29.347300 25.779453 -4.470136 -31.752975 23.813379 -4.977387 -32.708275 25.087780 -5.366364 -33.536476 26.362350 -5.610557 -34.181137 27.550228 -5.693327 -34.598331 28.570465 -5.609033 -34.759624 29.353531 -5.363418 -34.654022 29.846060 -4.973222 -34.288723 30.014490 -4.465035 -33.688625 29.847342 -3.873490 -32.894619 29.356005 -3.238899 -31.960819 28.573965 -2.604509 -30.950859 27.554516 -2.013552 -29.933567 26.367130 -1.506301 -28.978270 25.092730 -1.117325 -28.150070 23.818159 -0.873131 -27.505407 22.630281 -0.790360 -27.088213 21.610043 -0.874655 -26.926918 20.826979 -1.120269 -27.032520 20.334448 -1.510465 -27.397818 20.166018 -2.018651 -27.997915 20.333166 -2.610196 -28.791922 20.824501 -3.244787 -29.725721 21.606541 -3.879178 -30.735682 22.625990 0.344754 -31.736311 22.074875 -0.987996 -32.676243 20.885139 -2.253423 -33.671761 19.886036 -3.365289 -34.655025 19.145655 -4.247822 -35.559029 18.714453 -4.840880 -36.322163 18.621811 -5.104046 -36.892422 18.874048 -5.019388 -37.230942 19.453972 -4.592672 -37.314659 20.322060 -3.852980 -37.137863 21.419157 -2.850720 -36.712608 22.670494 -1.654196 -36.067863 23.990799 -0.344947 -35.247578 25.290091 0.987803 -34.307648 26.479826 2.253229 -33.312130 27.478931 3.365095 -32.328861 28.219311 4.247630 -31.424860 28.650517 4.840689 -30.661728 28.743156 5.103856 -30.091463 28.490921 5.019197 -29.752943 27.910999 4.592482 -29.669226 27.042910 3.852791 -29.846020 25.945812 2.850531 -30.271280 24.694475 1.654007 -30.916021 23.374170 5.681190 -34.554291 22.807264 5.542845 -32.631210 21.436125 5.282815 -30.920589 20.044018 4.918818 -29.539007 18.725819 4.475664 -28.580614 17.571358 3.983550 -28.110725 16.659313 3.476013 -28.161358 16.051836 2.987643 -28.729065 15.790325 2.551719 -29.775158 15.892603 2.197951 -31.228348 16.351698 1.950445 -32.989597 17.136326 1.826071 -34.938889 18.193014 1.833302 -36.943375 19.449753 1.971647 -38.866455 20.820892 2.231678 -40.577072 22.212999 2.595673 -41.958656 23.531197 3.038828 -42.917049 24.685658 3.530942 -43.386944 25.597706 4.038478 -43.336308 26.205181 4.526849 -42.768600 26.466694 4.962772 -41.722507 26.364418 5.316541 -40.269321 25.905323 5.564047 -38.508072 25.120695 5.688422 -36.558781 24.064007 8.522251 -40.199242 18.685175 10.379498 -38.985321 20.186674 12.070601 -37.660812 21.494267 13.480317 -36.315975 22.518847 14.512572 -35.042461 23.190584 15.097023 -33.927055 23.463709 15.193839 -33.045776 23.319603 14.796423 -32.458679 22.768089 13.931857 -32.205769 21.846748 12.659061 -32.304287 20.618372 11.064774 -32.747513 19.166672 9.257643 -33.505249 17.590578 7.360821 -34.525856 15.997499 5.503574 -35.739773 14.495999 3.812470 -37.064285 13.188406 2.402755 -38.409122 12.163826 1.370498 -39.682632 11.492085 0.786046 -40.798042 11.218962 0.689230 -41.679321 11.363068 1.086645 -42.266418 11.914581 1.951210 -42.519329 12.835920 3.224006 -42.420815 14.064297 4.818293 -41.977585 15.515995 6.625424 -41.219849 17.092089 9.884361 -39.523117 10.399902 10.870627 -42.133781 11.284644 11.959141 -44.467804 12.243439 13.075722 -46.366135 13.210948 14.144278 -47.699394 14.121235 15.091987 -48.376732 14.912267 15.854265 -48.351982 15.530135 16.379166 -47.626835 15.932734 16.630915 -46.250710 16.092627 16.592360 -44.317387 15.998917 16.266125 -41.958614 15.657990 15.674444 -39.335136 15.093081 14.857639 -36.625751 14.342688 13.871373 -34.015091 13.457946 12.782860 -31.681063 12.499151 11.666279 -29.782736 11.531643 10.597722 -28.449471 10.621355 9.650013 -27.772135 9.830323 8.887734 -27.796883 9.212454 8.362834 -28.522024 8.809855 8.111083 -29.898151 8.649961 8.149639 -31.831476 8.743670 8.475873 -34.190247 9.084597 9.067554 -36.813725 9.649506 15.256005 -34.366673 5.942664 13.090227 -35.761322 4.241115 11.175568 -37.286587 2.690240 9.642508 -38.838509 1.395730 8.595524 -40.311340 0.445805 8.105965 -41.604706 -0.094801 8.207194 -42.630459 -0.189247 8.892313 -43.318699 0.168905 10.114632 -43.622528 0.955246 11.790851 -43.521236 2.116189 13.806739 -43.021732 3.572618 16.024916 -42.158051 5.225278 18.294220 -40.989052 6.961545 20.459997 -39.594398 8.663095 22.374657 -38.069138 10.213969 23.907717 -36.517212 11.508478 24.954704 -35.044380 12.458406 25.444263 -33.751019 12.999013 25.343035 -32.725266 13.093458 24.657917 -32.037022 12.735308 23.435598 -31.733191 11.948967 21.759380 -31.834480 10.788025 19.743492 -32.333988 9.331597 17.525314 -33.197666 7.678936 23.531090 -34.526615 2.076783 21.867737 -31.861643 2.008534 20.133883 -29.484446 1.803422 18.447685 -27.557030 1.475425 16.924059 -26.210747 1.046895 15.666834 -25.537338 0.547037 14.761689 -25.582699 0.009914 14.270308 -26.343739 -0.527869 14.226178 -27.768589 -1.029663 14.632306 -29.760155 -1.461273 15.461016 -32.182709 -1.793283 16.655830 -34.871166 -2.003070 18.135326 -37.642303 -2.076335 19.798679 -40.307278 -2.008085 21.532534 -42.684471 -1.802974 23.218731 -44.611889 -1.474977 24.742359 -45.958176 -1.046447 25.999584 -46.631584 -0.546589 26.904730 -46.586224 -0.009466 27.396111 -45.825184 0.528317 27.440243 -44.400333 1.030111 27.034115 -42.408772 1.461721 26.205406 -39.986217 1.793732 25.010592 -37.297760 2.003518 26.353510 -36.334652 -6.967181 28.500034 -34.953987 -5.230181 30.356396 -33.465160 -3.576424 31.796087 -31.969631 -2.118613 32.720997 -30.569317 -0.956094 33.068089 -29.359652 -0.168092 32.813717 -28.423065 0.191694 31.975212 -27.823389 0.098743 30.609716 -27.601486 -0.440608 28.810289 -27.772482 -1.389605 26.699556 -28.324722 -2.683575 24.421360 -29.220573 -4.234337 22.130955 -30.398983 -5.936207 19.984432 -31.779646 -7.673207 18.128071 -33.268471 -9.326963 16.688379 -34.764000 -10.784775 15.763468 -36.164314 -11.947296 15.416373 -37.373985 -12.735298 15.670745 -38.310570 -13.095085 16.509249 -38.910248 -13.002135 17.874743 -39.132149 -12.462784 19.674171 -38.961151 -11.513787 21.784904 -38.408916 -10.219818 24.063101 -37.513065 -8.669057 24.290253 -31.180157 -14.342901 26.230309 -33.238575 -15.098034 28.208355 -35.059326 -15.667321 30.089594 -36.518330 -16.011965 31.745819 -37.516155 -16.108480 33.064163 -37.984802 -15.950291 33.954784 -37.892338 -15.548174 34.356987 -37.245056 -14.929535 34.243359 -36.087074 -14.136534 33.621647 -34.497307 -13.223209 32.534222 -32.584087 -12.251806 31.055185 -30.477804 -11.288523 29.285334 -28.321997 -10.399004 27.345280 -26.263578 -9.643871 25.367233 -24.442827 -9.074584 23.485994 -22.983824 -8.729939 21.829767 -21.985996 -8.633422 20.511423 -21.517347 -8.791612 19.620802 -21.609814 -9.193728 19.218599 -22.257093 -9.812367 19.332224 -23.415073 -10.605370 19.953934 -25.004845 -11.518692 21.041361 -26.918060 -12.490095 22.520395 -29.024343 -13.453380 26.218246 -23.642973 -15.992347 24.386190 -24.775368 -17.585716 22.826721 -25.961178 -19.162409 21.646112 -27.119585 -20.614979 20.924822 -28.171654 -21.844437 20.712002 -29.045681 -22.766991 21.022158 -29.682106 -23.319778 21.834152 -30.037560 -23.465122 23.092649 -30.087812 -23.193119 24.711885 -29.829445 -22.522308 26.581511 -29.280064 -21.498400 28.574114 -28.477106 -20.191174 30.553904 -27.475292 -18.689716 32.385960 -26.342897 -17.096348 33.945427 -25.157089 -15.519653 35.126038 -23.998680 -14.067085 35.847328 -22.946611 -12.837627 36.060150 -22.072584 -11.915071 35.749996 -21.436157 -11.362283 34.938000 -21.080706 -11.216938 33.679504 -21.030449 -11.488940 32.060268 -21.288816 -12.159751 30.190643 -21.838198 -13.183659 28.198042 -22.641157 -14.490885 31.076899 -20.060558 -19.448521 29.343992 -19.057571 -18.188141 27.593145 -18.195719 -17.128126 25.943676 -17.533735 -16.340717 24.507994 -17.116737 -15.879572 23.383938 -16.973137 -15.776118 22.648111 -17.112722 -16.037407 22.350658 -17.525982 -16.645628 22.511848 -18.184753 -17.559338 23.120699 -19.044138 -18.716263 24.135719 -20.045578 -20.037565 25.487732 -21.120819 -21.433197 27.084606 -22.196592 -22.808050 28.817513 -23.199579 -24.068430 30.568359 -24.061432 -25.128445 32.217827 -24.723415 -25.915855 33.653511 -25.140417 -26.376999 34.777565 -25.284016 -26.480455 35.513393 -25.144430 -26.219168 35.810848 -24.731171 -25.610945 35.649658 -24.072401 -24.697239 35.040810 -23.213015 -23.540312 34.025791 -22.211575 -22.219011 32.673775 -21.136333 -20.823378 30.697586 -17.318489 -25.292679 32.062405 -16.596134 -23.992399 33.218868 -15.884006 -22.670990 34.088158 -15.230633 -21.418503 34.611031 -14.680541 -20.320295 34.751865 -14.271218 -19.451204 34.501053 -14.030561 -18.870461 33.875690 -13.974966 -18.617640 32.918396 -14.108225 -18.709969 31.694408 -14.421254 -19.141161 30.287136 -14.892723 -19.881826 28.792488 -15.490500 -20.881491 27.312317 -16.173851 -22.072031 25.947495 -16.896204 -23.372311 24.791035 -17.608332 -24.693720 23.921745 -18.261705 -25.946205 23.398867 -18.811798 -27.044416 23.258036 -19.221121 -27.913507 23.508846 -19.461779 -28.494249 24.134207 -19.517374 -28.747072 25.091499 -19.384115 -28.654741 26.315489 -19.071087 -28.223553 27.722759 -18.599617 -27.482887 29.217409 -18.001841 -26.483223 26.930197 -13.222168 -26.367786 28.106003 -13.214410 -27.555849 29.297215 -13.165759 -28.575880 30.422649 -13.079534 -29.358370 31.405611 -12.961609 -29.849991 32.179115 -12.820020 -30.017239 32.690449 -12.664416 -29.848721 32.904762 -12.505404 -29.355915 32.807453 -12.353817 -28.572409 32.405151 -12.219987 -27.551598 31.725275 -12.113033 -26.363047 30.814154 -12.040246 -25.087755 29.733881 -12.006584 -23.812626 28.558077 -12.014342 -22.624565 27.366867 -12.062993 -21.604534 26.241432 -12.149218 -20.822044 25.258467 -12.267143 -20.330421 24.484962 -12.408732 -20.163174 23.973629 -12.564336 -20.331692 23.759315 -12.723348 -20.824495 23.856625 -12.874935 -21.608000 24.258924 -13.008765 -22.628811 24.938801 -13.115719 -23.817364 25.849922 -13.188506 -25.092657 26.220192 -9.211029 -24.307831 25.299295 -9.534406 -25.252548 24.510326 -9.811100 -26.215185 23.907053 -10.022255 -27.130144 23.530588 -10.153481 -27.935066 23.406586 -10.195833 -28.575102 23.543497 -10.146427 -29.006632 23.931992 -10.008630 -29.200249 24.545595 -9.791832 -29.142754 25.342489 -9.510807 -28.838072 26.268368 -9.184708 -28.306963 27.260136 -8.835756 -27.585623 28.250204 -8.487733 -26.723207 29.171101 -8.164355 -25.778490 29.960070 -7.887661 -24.815853 30.563343 -7.676507 -23.900896 30.939808 -7.545281 -23.095970 31.063812 -7.502928 -22.455935 30.926901 -7.552334 -22.024406 30.538406 -7.690131 -21.830790 29.924805 -7.906929 -21.888281 29.127911 -8.187953 -22.192963 28.202030 -8.514052 -22.724072 27.210264 -8.863004 -23.445412 26.796013 -5.265838 -24.238682 26.126801 -5.746016 -23.494890 25.439648 -6.209263 -22.863699 24.781380 -6.624011 -22.388121 24.196859 -6.961994 -22.100571 23.725920 -7.200181 -22.020638 23.400656 -7.322337 -22.153774 23.243231 -7.320140 -22.490906 23.264376 -7.193738 -23.009056 23.462648 -6.951746 -23.672918 23.824537 -6.610654 -24.437246 24.325380 -6.193709 -25.249954 24.931044 -5.729324 -26.055658 25.600256 -5.249146 -26.799450 26.287411 -4.785898 -27.430641 26.945677 -4.371150 -27.906219 27.530199 -4.033167 -28.193773 28.001139 -3.794981 -28.273705 28.326403 -3.672824 -28.140568 28.483828 -3.675021 -27.803438 28.462683 -3.801423 -27.285286 28.264410 -4.043416 -26.621426 27.902523 -4.384506 -25.857098 27.401680 -4.801451 -25.044390 24.936852 -1.896706 -24.859047 25.587053 -1.833102 -24.169058 26.151800 -1.818874 -23.478848 26.592604 -1.854989 -22.835459 26.879423 -1.938987 -22.282732 26.992714 -2.065145 -21.858339 26.924755 -2.224863 -21.591200 26.680176 -2.407258 -21.499519 26.275648 -2.599900 -21.589546 25.738735 -2.789661 -21.855146 25.106030 -2.963609 -22.278215 24.420649 -3.109889 -22.829926 23.729300 -3.218532 -23.472677 23.079096 -3.282136 -24.162668 22.514351 -3.296365 -24.852879 22.073547 -3.260250 -25.496267 21.786726 -3.176251 -26.048992 21.673435 -3.050094 -26.473387 21.741394 -2.890376 -26.740526 21.985971 -2.707981 -26.832207 22.390501 -2.515338 -26.742180 22.927412 -2.325578 -26.476580 23.560118 -2.151630 -26.053511 24.245499 -2.005350 -25.501801 21.973133 0.000552 -23.481628 22.454115 0.621868 -23.910622 22.953714 1.200797 -24.258978 23.437889 1.697887 -24.502956 23.873642 2.079262 -24.625929 24.231274 2.318931 -24.619516 24.486418 2.400562 -24.484156 24.621681 2.318592 -24.229071 24.627851 2.078606 -23.871643 24.504503 1.696960 -23.436235 24.260046 1.199661 -22.952518 23.911137 0.620601 -22.453457 23.481552 -0.000760 -21.973059 23.000572 -0.622075 -21.544064 22.500971 -1.201005 -21.195709 22.016796 -1.698095 -20.951729 21.581045 -2.079470 -20.828756 21.223412 -2.319140 -20.835169 20.968267 -2.400771 -20.970530 20.833004 -2.318801 -21.225615 20.826834 -2.078816 -21.583040 20.950182 -1.697169 -22.018446 21.194639 -1.199871 -22.502165 21.543549 -0.620811 -23.001228 20.535673 1.350677 -20.500458 19.884226 1.467519 -21.182253 19.315788 1.635494 -21.848719 18.869102 1.843156 -22.454441 18.574608 2.076352 -22.958139 18.452372 2.319190 -23.325485 18.510727 2.555122 -23.531448 18.745697 2.768069 -23.561989 19.141266 2.943519 -23.415028 19.670481 3.069515 -23.100584 20.297272 3.137472 -22.640079 20.978926 3.142757 -22.064899 21.668991 3.085011 -21.414242 22.320440 2.968169 -20.732449 22.888876 2.800195 -20.065981 23.335562 2.592533 -19.460260 23.630058 2.359337 -18.956562 23.752295 2.116499 -18.589214 23.693939 1.880567 -18.383251 23.458969 1.667620 -18.352711 23.063400 1.492170 -18.499670 22.534187 1.366173 -18.814116 21.907396 1.298217 -19.274620 21.225740 1.292931 -19.849800 20.425173 3.910400 -18.044655 19.836369 3.022731 -17.733276 19.224144 2.211420 -17.505013 18.630224 1.531758 -17.375418 18.095079 1.030062 -17.353325 17.655184 0.740521 -17.440237 17.340513 0.682868 -17.630234 17.172510 0.861031 -17.910364 17.162626 1.262869 -18.261539 17.311535 1.860997 -18.659830 17.609087 2.614654 -19.078089 18.035006 3.472479 -19.487816 18.560266 4.376013 -19.861084 19.149071 5.263682 -20.172462 19.761293 6.074992 -20.400724 20.355215 6.754654 -20.530321 20.890358 7.256351 -20.552414 21.330256 7.545893 -20.465502 21.644926 7.603546 -20.275507 21.812929 7.425383 -19.995375 21.822813 7.023546 -19.644199 21.673904 6.425418 -19.245911 21.376352 5.671761 -18.827650 20.950434 4.813936 -18.417925 18.741241 7.164705 -17.156725 19.668631 6.782069 -16.240980 20.476686 6.333984 -15.362396 21.110340 5.850986 -14.580848 21.526413 5.365990 -13.949593 21.696547 4.912047 -13.511657 21.609150 4.520094 -13.296877 21.270176 4.216841 -13.319895 20.702726 4.022954 -13.579142 19.945473 3.951647 -14.056947 19.050020 4.007778 -14.720753 18.077391 4.187523 -15.525320 17.093870 4.478632 -16.415817 16.166481 4.861267 -17.331562 15.358425 5.309352 -18.210146 14.724770 5.792350 -18.991695 14.308697 6.277347 -19.622948 14.138562 6.731289 -20.060886 14.225960 7.123242 -20.275667 14.564933 7.426496 -20.252649 15.132382 7.620383 -19.993402 15.889636 7.691691 -19.515598 16.785089 7.635560 -18.851791 17.757717 7.455815 -18.047226 14.983026 7.903972 -15.787067 15.892182 9.287216 -16.019537 16.834913 10.534687 -16.149145 17.746975 11.561373 -16.167057 18.566212 12.297307 -16.072054 19.236792 12.692335 -15.870608 19.713017 12.719539 -15.576447 19.962435 12.377063 -15.209621 19.968046 11.688247 -14.795126 19.729471 10.700032 -14.361209 19.262964 9.479764 -13.937443 18.600321 8.110602 -13.552703 17.786697 6.685852 -13.233212 16.877541 5.302608 -13.000741 15.934810 4.055137 -12.871134 15.022748 3.028450 -12.853221 14.203512 2.292516 -12.948225 13.532931 1.897487 -13.149672 13.056705 1.870283 -13.443831 12.807287 2.212758 -13.810658 12.801675 2.901574 -14.225152 13.040251 3.889788 -14.659068 13.506756 5.110056 -15.082836 14.169399 6.479218 -15.467575 13.643391 6.564704 -11.882022 12.263506 7.337905 -13.136300 11.062957 8.197086 -14.324167 10.123557 9.083694 -15.364675 9.509327 9.937309 -16.186909 9.262125 10.699759 -16.734842 9.398796 11.319081 -16.971128 9.910028 11.753075 -16.879667 10.760980 11.972159 -16.466694 11.893661 11.961408 -15.760346 13.230882 11.721550 -14.808765 14.681512 11.268935 -13.676799 16.146694 10.634405 -12.441588 17.526579 9.861204 -11.187310 18.727129 9.002024 -9.999443 19.666529 8.115416 -8.958937 20.280758 7.261801 -8.136700 20.527962 6.499351 -7.588768 20.391291 5.880027 -7.352480 19.880060 5.446034 -7.443940 19.029108 5.226949 -7.856915 17.896427 5.237701 -8.563261 16.559208 5.477557 -9.514841 15.108577 5.930173 -10.646808 15.439593 8.697544 -8.088600 14.138034 6.726185 -7.957990 12.789128 4.962053 -7.950674 11.484803 3.525371 -8.067150 10.313944 2.514046 -8.299480 9.356345 1.996999 -8.631834 8.677263 2.009465 -9.041559 8.322979 2.550595 -9.500735 8.317634 3.583511 -9.978069 8.661593 5.037822 -10.441032 9.331417 6.814418 -10.858074 10.281457 8.792230 -11.200774 11.446971 10.836471 -11.445777 12.748529 12.807829 -11.576387 14.097435 14.571961 -11.583704 15.401761 16.008644 -11.467229 16.572620 17.019970 -11.234897 17.530220 17.537018 -10.902544 18.209303 17.524553 -10.492819 18.563587 16.983423 -10.033644 18.568933 15.950509 -9.556309 18.224974 14.496198 -9.093346 17.555151 12.719603 -8.676304 16.605110 10.741791 -8.333604 13.680422 13.545734 -7.510282 15.529783 12.385780 -5.957283 17.140038 11.119379 -4.498776 18.401447 9.832832 -3.234157 19.228052 8.613818 -2.249607 19.563517 7.545409 -1.612223 19.384983 6.700415 -1.365438 18.704617 6.136420 -1.526074 17.568783 5.891863 -2.083182 16.054890 5.983406 -2.998796 14.266102 6.404812 -4.210519 12.324326 7.127365 -5.635773 10.361888 8.101821 -7.177431 8.512527 9.261774 -8.730431 6.902273 10.528174 -10.188937 5.640862 11.814720 -11.453556 4.814256 13.033737 -12.438107 4.478790 14.102146 -13.075493 4.657323 14.947141 -13.322277 5.337688 15.511135 -13.161642 6.473521 15.755693 -12.604534 7.987415 15.664150 -11.688921 9.776202 15.242744 -10.477199 11.717978 14.520193 -9.051945 8.119987 13.221437 -6.874990 9.711393 15.678643 -6.899128 11.364558 17.870979 -6.787269 12.966822 19.649038 -6.547034 14.408992 20.891649 -6.194796 15.592787 21.514130 -5.754559 16.437534 21.474062 -5.256324 16.885664 20.774174 -4.734047 16.906637 19.462158 -4.223318 16.499027 17.627434 -3.758943 15.690610 15.395030 -3.372569 14.536478 12.917083 -3.090526 13.115283 10.362458 -2.932034 11.523877 7.905252 -2.907897 9.870712 5.712917 -3.019756 8.268450 3.934857 -3.259990 6.826278 2.692244 -3.612229 5.642483 2.069762 -4.052465 4.797735 2.109830 -4.550700 4.349604 2.809717 -5.072978 4.328629 4.121730 -5.583706 4.736239 5.956454 -6.048081 5.544656 8.188857 -6.434456 6.698788 10.666805 -6.716499 7.350757 9.521795 -2.400465 5.195669 10.909763 -4.120945 3.314812 12.419028 -5.727817 1.836363 13.946737 -7.111574 0.861075 15.388779 -8.177917 0.455414 16.646877 -8.854176 0.647023 17.635302 -9.094263 1.422845 18.286688 -8.881819 2.730009 18.556648 -8.231322 4.479434 18.426781 -7.187099 6.551899 17.905941 -5.820316 8.806170 17.029619 -4.224115 11.088622 15.857538 -2.507275 13.243710 14.469571 -0.786795 15.124567 12.960306 0.820077 16.603018 11.432598 2.203835 17.578306 9.990557 3.270179 17.983969 8.732455 3.946437 17.792360 7.744031 4.186526 17.016539 7.092644 3.974083 15.709376 6.822684 3.323586 13.959951 6.952549 2.279365 11.887486 7.473390 0.912582 9.633215 8.349710 -0.683619 10.510156 11.973782 2.076831 8.848370 9.307906 2.005674 7.115994 6.929869 1.797824 5.431091 5.001729 1.467446 3.908483 3.654886 1.037055 2.651932 2.981125 0.535981 1.747070 3.026361 -0.001630 1.255562 3.787511 -0.539138 1.210904 5.212705 -1.039914 1.616140 7.204819 -1.469832 2.443651 9.628090 -1.799592 3.637047 12.317381 -2.006723 5.114997 15.089417 -2.077108 6.776783 17.755293 -2.005952 8.509157 20.133331 -1.798102 10.194060 22.061470 -1.467724 11.716670 23.408314 -1.037333 12.973223 24.082079 -0.536259 13.878084 24.036842 0.001351 14.369593 23.275694 0.538860 14.414251 21.850502 1.039636 14.009017 19.858389 1.469554 13.181506 17.435118 1.799315 11.988111 14.745828 2.006446 8.189048 17.531612 2.508175 10.344537 16.140633 4.225738 12.229842 14.626211 5.822532 13.716483 13.091549 7.189739 14.703147 11.641233 8.234185 15.122593 10.374100 8.884693 14.946239 9.376503 9.096932 14.186103 8.716427 8.856440 12.893987 8.438854 8.179603 11.157946 8.562700 7.112548 9.096287 9.079526 5.727993 6.849510 9.954110 4.120293 4.570730 11.126853 2.399011 2.415240 12.517832 0.681448 0.529935 14.032254 -0.915346 -0.956706 15.566916 -2.282554 -1.943371 17.017233 -3.327001 -2.362818 18.284367 -3.977510 -2.186466 19.281963 -4.189750 -1.426331 19.942039 -3.949257 -0.134215 20.219614 -3.272421 1.601826 20.095768 -2.205367 3.663485 19.578943 -0.820812 5.910261 18.704359 0.786887 2.417314 16.539875 2.931334 3.919164 19.047894 3.090835 5.488093 21.286261 3.373850 7.017182 23.102432 3.761091 8.402224 24.372639 4.226169 9.548832 25.010319 4.737388 10.378867 24.972017 5.259911 10.835764 24.260344 5.758127 10.888384 22.923796 6.198085 10.533143 21.053457 6.549803 9.794249 18.776791 6.789311 8.722057 16.248945 6.900287 7.389635 13.642191 6.875168 5.887785 11.134171 6.715667 4.318857 8.895806 6.432652 2.789768 7.079634 6.045411 1.404724 5.809425 5.580334 0.258116 5.171743 5.069114 -0.571920 5.210043 4.546591 -1.028816 5.921718 4.048375 -1.081437 7.258264 3.608416 -0.726197 9.128601 3.256699 0.012697 11.405268 3.017190 1.084888 13.933113 2.906214 1.835359 13.024656 7.175997 0.010926 14.237488 5.633892 -1.585050 15.558331 4.208301 -2.843807 16.897175 2.996374 -3.679562 18.162773 2.080704 -4.035360 19.268883 1.523692 -3.886956 20.140125 1.363295 -3.244460 20.717123 1.610446 -2.151659 20.960554 2.248303 -0.683026 20.853832 3.233396 1.061356 20.404228 4.498590 2.962608 19.642384 5.957669 4.891165 18.620216 7.511196 6.715598 17.407385 9.053300 8.311574 16.086542 10.478891 9.570332 14.747700 11.690819 10.406089 13.482100 12.606489 10.761888 12.375988 13.163503 10.613483 11.504747 13.323900 9.970988 10.927750 13.076749 8.878188 10.684317 12.438892 7.409554 10.791039 11.453800 5.665174 11.240642 10.188606 3.763921 12.002485 8.729528 3.660395 15.330776 11.446149 2.472632 13.299482 11.199958 1.234739 11.488048 10.856106 0.031074 10.019916 10.438028 -1.056332 8.995140 9.974216 -1.953376 8.483557 9.496277 -2.598926 8.520028 9.036781 -2.948989 9.102068 8.627043 -2.979707 10.190015 8.294985 -2.688989 11.709723 8.063237 -2.096646 13.557630 7.947592 -1.243045 15.607802 7.955931 -0.186357 17.720524 8.087686 1.001405 19.751818 8.333877 2.239299 21.563253 8.677727 3.442963 23.031385 9.095804 4.530371 24.056162 9.559618 5.427415 24.567745 10.037557 6.072966 24.531277 10.497053 6.423029 23.949236 10.906791 6.453748 22.861290 11.238849 6.163030 21.341583 11.470597 5.570687 19.493677 11.586243 4.717086 17.443504 11.577904 1.136807 19.300280 12.442785 2.417952 18.347939 13.678507 3.534325 17.317314 14.810850 4.409847 16.278641 15.762648 4.984852 15.302698 16.469036 5.220156 14.456001 16.881878 5.099722 13.796247 16.973036 4.631758 13.368397 16.736300 3.848155 13.201610 16.187801 2.802314 13.307251 15.364921 1.565507 13.678122 14.323736 0.222022 14.288947 13.135201 -1.136587 15.098100 11.880314 -2.417732 16.050440 10.644592 -3.534105 17.081064 9.512248 -4.409627 18.119740 8.560451 -4.984634 19.095680 7.854061 -5.219938 19.942379 7.441220 -5.099504 20.602133 7.350061 -4.631541 21.029984 7.586797 -3.847938 21.196770 8.135294 -2.802098 21.091129 8.958176 -1.565291 20.720259 9.999360 -0.221806 20.109436 11.187894 -3.101822 18.747505 13.232396 -2.274654 20.164179 13.553206 -1.420226 21.422270 13.939213 -0.596766 22.436033 14.364111 0.139610 23.136389 14.798944 0.738718 23.475605 15.214077 1.159730 23.430565 15.581222 1.373955 23.004343 15.875357 1.366794 22.225979 16.076437 1.138735 21.148521 16.170761 0.705320 19.845396 16.151899 0.096084 18.405407 16.021137 -0.647453 16.926689 15.787386 -1.474620 15.510014 15.466576 -2.329048 14.251925 15.080569 -3.152508 13.238159 14.655671 -3.888885 12.537804 14.220839 -4.487993 12.198586 13.805704 -4.909006 12.243624 13.438560 -5.123231 12.669847 13.144424 -5.116070 13.448210 12.943344 -4.888011 14.525667 12.849020 -4.454596 15.828794 12.867883 -3.845361 17.268782 12.998644 -4.668010 17.043236 16.414282 -5.411161 17.750015 15.523597 -6.052476 18.502987 14.718944 -6.548251 19.250839 14.055158 -6.864698 19.942602 13.577477 -6.980253 20.531136 13.318453 -6.887041 20.976334 13.295736 -6.591413 21.247854 13.510879 -6.113518 21.327196 13.949215 -5.485922 21.208950 14.580877 -4.751395 20.901175 15.362815 -3.959993 20.424847 16.241741 -3.165650 19.812426 17.157761 -2.422499 19.105644 18.048447 -1.781184 18.352673 18.853100 -1.285409 17.604822 19.516886 -0.968962 16.913059 19.994568 -0.853406 16.324524 20.253592 -0.946618 15.879328 20.276308 -1.242245 15.607804 20.061165 -1.720140 15.528463 19.622829 -2.347736 15.646708 18.991167 -3.082263 15.954484 18.209230 -3.873665 16.430811 17.330303 -5.491202 18.260838 19.861084 -6.010725 17.354500 19.486515 -6.540283 16.557081 19.075563 -7.043788 15.922922 18.656237 -7.486928 15.495241 18.257111 -7.839503 15.303183 17.905382 -8.077485 15.359836 17.625025 -8.184657 15.661340 17.435143 -8.153715 16.187147 17.348677 -7.986768 16.901424 17.371515 -7.695193 17.755495 17.502110 -7.298859 18.691158 17.731554 -6.824778 19.644648 18.044212 -6.305255 20.550985 18.418781 -5.775697 21.348404 18.829731 -5.272192 21.982563 19.249058 -4.829051 22.410246 19.648186 -4.476477 22.602304 19.999914 -4.238494 22.545652 20.280272 -4.131322 22.244148 20.470154 -4.162263 21.718340 20.556622 -4.329211 21.004063 20.533779 -4.620786 20.149992 20.403189 -5.017119 19.214331 20.173744 -8.163098 20.307901 21.415592 -7.769013 19.738503 22.066267 -7.433617 19.144947 22.641361 -7.179766 18.567684 23.101681 -7.024758 18.046055 23.415852 -6.979159 17.615610 23.562468 -7.046075 17.305677 23.531536 -7.220947 17.137383 23.325165 -7.491856 17.122194 22.957420 -7.840341 17.261147 22.453358 -8.242654 17.544771 21.847332 -8.671376 17.953739 21.180643 -9.097293 18.460178 20.498724 -9.491377 19.029577 19.848047 -9.826774 19.623135 19.272955 -10.080626 20.200396 18.812635 -10.235633 20.722025 18.498463 -10.281232 21.152472 18.351847 -10.214316 21.462402 18.382778 -10.039445 21.630697 18.589149 -9.768536 21.645885 18.956894 -9.420051 21.506935 19.460955 -9.017738 21.223310 20.066982 -8.589016 20.814344 20.733669 -11.740092 20.335932 21.972982 -11.417652 21.018204 22.454596 -11.091520 21.609444 22.954782 -10.783923 22.069355 23.439461 -10.515821 22.366600 23.875599 -10.305487 22.480919 24.233473 -10.167253 22.404524 24.488697 -10.110540 22.142620 24.623877 -10.139214 21.713055 24.629801 -10.251319 21.145102 24.506065 -10.439218 20.477467 24.261101 -10.690103 19.755650 23.911604 -10.986877 19.028837 23.481390 -11.309318 18.346565 22.999779 -11.635449 17.755327 22.499590 -11.943048 17.295414 22.014914 -12.211149 16.998169 21.578773 -12.421484 16.883850 21.220900 -12.559718 16.960245 20.965675 -12.616430 17.222149 20.830494 -12.587757 17.651714 20.824572 -12.475652 18.219667 20.948307 -12.287754 18.887300 21.193272 -12.036868 19.609119 21.542768 -14.649877 18.941597 23.471035 -14.900514 19.595266 22.828560 -15.115760 20.262495 22.277208 -15.280949 20.897814 21.854561 -15.384821 21.457928 21.589415 -15.420300 21.904663 21.499844 -15.384966 22.207579 21.591949 -15.281227 22.346031 21.859455 -15.116154 22.310583 22.284130 -14.900996 22.103649 22.837036 -14.650415 21.739334 23.480490 -14.381488 21.242468 24.170643 -14.112542 20.646904 24.860466 -13.861906 19.993237 25.502941 -13.646659 19.326006 26.054291 -13.481470 18.690687 26.476940 -13.377598 18.130573 26.742085 -13.342119 17.683838 26.831657 -13.377453 17.380922 26.739552 -13.481192 17.242470 26.472048 -13.646264 17.277920 26.047371 -13.861423 17.484852 25.494467 -14.112003 17.849165 24.851011 -14.380930 18.346033 24.160858 -17.427868 18.725677 26.055216 -17.525009 17.969646 25.248629 -17.633566 17.328112 24.435120 -17.746138 16.844790 23.670134 -17.855055 16.552616 23.005802 -17.952894 16.471506 22.487394 -18.032990 16.606985 22.150246 -18.089882 16.949821 22.017324 -18.119694 17.476648 22.097696 -18.120392 18.151567 22.385880 -18.091932 18.928581 22.862236 -18.036251 19.754742 23.494303 -17.957146 20.573742 24.239006 -17.860004 21.329771 25.045593 -17.751448 21.971306 25.859102 -17.638876 22.454628 26.624088 -17.529959 22.746803 27.288422 -17.432119 22.827913 27.806826 -17.352024 22.692434 28.143978 -17.295132 22.349600 28.276897 -17.265320 21.822771 28.196527 -17.264622 21.147852 27.908344 -17.293081 20.370838 27.431988 -17.348763 19.544680 26.799923 -21.479496 20.220280 26.723633 -21.286423 19.188385 27.585588 -21.092987 18.154675 28.306473 -20.912367 17.189594 28.837154 -20.756876 16.358913 29.141472 -20.637108 15.719239 29.198689 -20.561224 15.314166 29.004900 -20.534399 15.171299 28.573315 -20.558458 15.300374 27.933346 -20.631763 15.692595 27.128605 -20.749319 16.321232 26.213934 -20.903112 17.143444 25.251667 -21.082663 18.103201 24.307377 -21.275736 19.135096 23.445423 -21.469173 20.168806 22.724539 -21.649794 21.133884 22.193855 -21.805285 21.964569 21.889536 -21.925053 22.604242 21.832321 -22.000937 23.009315 22.026108 -22.027761 23.152182 22.457693 -22.003702 23.023109 23.097662 -21.930397 22.630888 23.902405 -21.812841 22.002253 24.817074 -21.659048 21.180038 25.779343 -25.263651 19.747852 23.813503 -25.837524 20.664667 25.087902 -26.360464 21.415508 26.362465 -26.796827 21.949205 27.550331 -27.116880 22.229387 28.570547 -27.298809 22.236963 29.353588 -27.330219 21.971411 29.846090 -27.208967 21.450836 30.014490 -26.943316 20.710709 29.847317 -26.551371 19.801466 29.355957 -26.059841 18.785074 28.573896 -25.502226 17.730801 27.554434 -24.916523 16.710489 26.367041 -24.342648 15.793673 25.092642 -23.819710 15.042832 23.818079 -23.383345 14.509135 22.630215 -23.063292 14.228951 21.609997 -22.881363 14.221377 20.826956 -22.849953 14.486926 20.334454 -22.971205 15.007504 20.166050 -23.236856 15.747631 20.333227 -23.628801 16.656874 20.824587 -24.120329 17.673264 21.606644 -24.677946 18.727537 22.626106 -27.656504 15.569826 22.074987 -27.803926 17.194141 20.885443 -28.033186 18.787922 19.886509 -28.328659 20.242554 19.146271 -28.670210 21.458904 18.715168 -29.034561 22.354084 18.622581 -29.396885 22.867086 18.874821 -29.732489 22.962952 19.454695 -30.018499 22.635147 20.322687 -30.235430 21.906013 21.419645 -30.368494 20.825235 22.670818 -30.408625 19.466469 23.990931 -30.353086 17.922314 25.290028 -30.205664 16.297998 26.479572 -29.976404 14.704220 27.478504 -29.680931 13.249589 28.218744 -29.339382 12.033236 28.649849 -28.975029 11.138056 28.742435 -28.612705 10.625051 28.490196 -28.277103 10.529184 27.910324 -27.991091 10.856989 27.042330 -27.774160 11.586124 25.945372 -27.641096 12.666901 24.694202 -27.600965 14.025665 23.374088 -32.765362 12.357170 22.807360 -31.030975 11.515294 21.436028 -29.419735 10.885037 20.043739 -28.041445 10.509348 18.725376 -26.990032 10.413832 17.570780 -26.337151 10.604997 16.658642 -26.127289 11.069814 16.051117 -26.374754 11.776608 15.789605 -27.062677 12.677214 15.891932 -28.144180 13.710254 16.351124 -29.545557 14.805329 17.135887 -31.171312 15.887814 18.192739 -32.910648 16.883934 19.449661 -34.645031 17.725811 20.820993 -36.256271 18.356068 22.213282 -37.634563 18.731758 23.531645 -38.685978 18.827274 24.686239 -39.338860 18.636110 25.598381 -39.548721 18.171293 26.205906 -39.301258 17.464499 26.467417 -38.613335 16.563894 26.365089 -37.531834 15.530854 25.905899 -36.130455 14.435779 25.121138 -34.504700 13.353295 24.064285 -39.074390 12.719442 18.685564 -38.951511 10.504282 20.187376 -38.649822 8.377676 21.495235 -38.189884 6.484548 22.520010 -37.603039 4.953911 23.191866 -36.929283 3.890076 23.465019 -36.214527 3.365542 23.320847 -35.507484 3.416054 22.769182 -34.856339 4.038169 21.847618 -34.305458 5.189493 20.618956 -33.892395 6.791564 19.166929 -33.645287 8.735203 17.590488 -33.580982 10.887956 15.997066 -33.703861 13.103115 14.495255 -34.005550 15.229721 13.187396 -34.465488 17.122849 12.162621 -35.052330 18.653488 11.490763 -35.726089 19.717323 11.217611 -36.440842 20.241859 11.361780 -37.147884 20.191347 11.913446 -37.799034 19.569233 12.835009 -38.349911 18.417910 14.063669 -38.762978 16.815840 15.515697 -39.010086 14.872201 17.092138 -39.170132 11.201511 10.399995 -41.924213 11.652666 11.284619 -44.489841 11.876949 12.243299 -46.692181 11.859078 13.210699 -48.381142 11.600269 14.120893 -49.441624 11.118162 14.911854 -49.801357 10.445608 15.529677 -49.435829 9.628444 15.932261 -48.369949 8.722356 16.092171 -46.676353 7.789092 15.998507 -44.470459 6.892256 15.657652 -41.902592 6.092962 15.092836 -39.147751 5.445682 14.342550 -36.393673 4.994527 13.457926 -33.828041 4.770242 12.499247 -31.625702 4.788114 11.531848 -29.936739 5.046922 10.621653 -28.876255 5.529030 9.830691 -28.516520 6.201582 9.212867 -28.882046 7.018747 8.810283 -29.947926 7.924835 8.650373 -31.641521 8.858098 8.744038 -33.847416 9.754935 9.084891 -36.415283 10.554230 9.649707 -37.390385 3.971276 5.942853 -37.515156 6.544513 4.241731 -37.878605 8.965553 2.691240 -38.455971 11.069408 1.397041 -39.207901 12.712704 0.447335 -40.083160 13.783451 -0.093159 -41.022095 14.208682 -0.187608 -41.960720 13.959414 0.170426 -42.835072 13.052641 0.956542 -43.585560 11.550152 2.117170 -44.161045 9.554342 3.573212 -44.522305 7.201221 5.225443 -44.644726 4.651151 6.961267 -44.519955 2.077915 8.662388 -44.156506 -0.343126 10.212879 -43.579144 -2.446982 11.507078 -42.827209 -4.090279 12.456786 -41.951954 -5.161027 12.997281 -41.013016 -5.586258 13.091730 -40.074390 -5.336992 12.733697 -39.200043 -4.430218 11.947580 -38.449551 -2.927732 10.786955 -37.874065 -0.931921 9.330913 -37.512806 1.421198 7.678682 -41.666557 -3.115118 2.076916 -38.526943 -3.007137 2.008740 -35.601295 -2.694219 1.803680 -33.088993 -2.197690 1.475710 -31.161243 -1.551386 1.047181 -29.949421 -0.799353 0.547297 -29.536112 0.007160 0.010123 -29.949476 0.813191 -0.527733 -31.161348 1.563809 -1.029616 -33.089142 2.207862 -1.461325 -35.601475 2.701458 -1.793439 -38.527145 3.010959 -2.003325 -41.666763 3.115274 -2.076680 -44.806381 3.007294 -2.008505 -47.732029 2.694377 -1.803445 -50.244331 2.197848 -1.475476 -52.172081 1.551544 -1.046946 -53.383907 0.799511 -0.547062 -53.797218 -0.007002 -0.009888 -53.383854 -0.813032 0.527968 -52.171982 -1.563651 1.029851 -50.244190 -2.207704 1.461560 -47.731857 -2.701300 1.793674 -44.806190 -3.010802 2.003561 -44.643417 -4.655591 -6.967583 -44.521187 -7.204571 -5.230136 -44.160191 -9.556362 -3.575947 -43.585033 -11.550695 -2.117745 -42.834911 -13.051659 -0.954905 -41.960941 -13.956964 -0.166670 -41.022686 -14.204919 0.193240 -40.084084 -13.778623 0.100300 -39.209099 -12.707129 -0.439157 -38.457359 -11.063457 -1.388368 -37.880096 -8.959620 -2.682646 -37.516647 -6.538991 -4.233788 -37.391785 -3.966533 -5.936086 -37.514015 -1.417554 -7.673532 -37.875008 0.934238 -9.327721 -38.450165 2.928571 -10.785923 -39.200287 4.429536 -11.948765 -40.074257 5.334843 -12.737000 -41.012516 5.582798 -13.096911 -41.951118 5.156503 -13.003971 -42.826103 4.085010 -12.464516 -43.577843 2.441338 -11.515305 -44.155106 0.337502 -10.221027 -44.518555 -2.083126 -8.669886 -39.147820 -5.445873 -14.342846 -41.900501 -6.096691 -15.098006 -44.466358 -6.899259 -15.667333 -46.670532 -7.798884 -16.012024 -48.362804 -8.734259 -16.108589 -49.427856 -9.641638 -15.950449 -49.793106 -10.459185 -15.548381 -49.433659 -11.131186 -14.929785 -48.374012 -11.611846 -14.136818 -46.686382 -11.868406 -13.223517 -44.485775 -11.883387 -12.252126 -41.922157 -11.655763 -11.288838 -39.170238 -11.201049 -10.399304 -36.417557 -10.550232 -9.644143 -33.851700 -9.747663 -9.074819 -31.647528 -8.848039 -8.730127 -29.955252 -7.912663 -8.633560 -28.890198 -7.005284 -8.791699 -28.524950 -6.187737 -9.193768 -28.884394 -5.515736 -9.812363 -29.944038 -5.035076 -10.605330 -31.631668 -4.778514 -11.518630 -33.832275 -4.763534 -12.490023 -36.395893 -4.991158 -13.453310 -33.584370 -10.884477 -15.992512 -33.648987 -8.731575 -17.585735 -33.896164 -6.788025 -19.162292 -34.309052 -5.186277 -20.614742 -34.859516 -4.035489 -21.844101 -35.510040 -3.414083 -22.766590 -36.216293 -3.364408 -23.319349 -36.930145 -3.889848 -23.464703 -37.602951 -4.954597 -23.192745 -38.188854 -6.486094 -22.522013 -38.647934 -8.379969 -21.498213 -38.948898 -10.507155 -20.191118 -39.071239 -12.722693 -18.689804 -39.006622 -14.875596 -17.096579 -38.759445 -16.819145 -15.520022 -38.346558 -18.420893 -14.067575 -37.796093 -19.571684 -12.838213 -37.145569 -20.193090 -11.915722 -36.439316 -20.242767 -11.362965 -35.725464 -19.717327 -11.217609 -35.052658 -18.652578 -11.489567 -34.466755 -17.121082 -12.160297 -34.007675 -15.227209 -13.184096 -33.706711 -13.100021 -14.491192 -32.911316 -16.883287 -19.448797 -31.176172 -15.884205 -18.188412 -29.554289 -14.798999 -17.128384 -28.156195 -13.701626 -16.340950 -27.077168 -12.666871 -15.879772 -26.390739 -11.765250 -15.776280 -26.143692 -11.058207 -16.037527 -26.352861 -10.593926 -16.645708 -27.003988 -10.404047 -17.559374 -28.052706 -10.501509 -18.716269 -29.427540 -10.879672 -20.037540 -31.034801 -11.512763 -21.433155 -32.764957 -12.357639 -22.807999 -34.500103 -13.356723 -24.068382 -36.121986 -14.441928 -25.128410 -37.520081 -15.539300 -25.915846 -38.599110 -16.574057 -26.377024 -39.285538 -17.475677 -26.480518 -39.532585 -18.182720 -26.219273 -39.323418 -18.647001 -25.611092 -38.672291 -18.836882 -24.697424 -37.623573 -18.739418 -23.540533 -36.248737 -18.361256 -22.219259 -34.641476 -17.728167 -20.823645 -30.346582 -17.925793 -25.292938 -30.403744 -19.468821 -23.992550 -30.365578 -20.826290 -22.671030 -30.234688 -21.905697 -21.418434 -30.019991 -22.633478 -20.320126 -29.736120 -22.960039 -19.450954 -29.402420 -22.863123 -18.870152 -29.041634 -22.349335 -18.617298 -28.678345 -21.453690 -18.709625 -28.337313 -20.237225 -19.140841 -28.041779 -18.782837 -19.881559 -27.811882 -17.189644 -20.881300 -27.663290 -15.566217 -22.071936 -27.606129 -14.023191 -23.372322 -27.644295 -12.665720 -24.693844 -27.775185 -11.586313 -25.946440 -27.989882 -10.858531 -27.044748 -28.273752 -10.531970 -27.913919 -28.607450 -10.628885 -28.494724 -28.968239 -11.142673 -28.747578 -29.331528 -12.038317 -28.655251 -29.672558 -13.254782 -28.224035 -29.968094 -14.709167 -27.483318 -30.197990 -16.302362 -26.483578 -24.915697 -16.711092 -26.367668 -25.496937 -17.733118 -27.555794 -26.050459 -18.788948 -28.575899 -26.538544 -19.806625 -29.358459 -26.927929 -20.716801 -29.850147 -27.192076 -21.457443 -30.017456 -27.312986 -21.978081 -29.848982 -27.282419 -22.243233 -29.356209 -27.102457 -22.234833 -28.572716 -26.785364 -21.953449 -27.551899 -26.352753 -21.418259 -26.363323 -25.834101 -20.665735 -25.087988 -25.264755 -19.747160 -23.812807 -24.683516 -18.725134 -22.624680 -24.129992 -17.669306 -21.604578 -23.641907 -16.651628 -20.822016 -23.252523 -15.741454 -20.330326 -22.988375 -15.000811 -20.163017 -22.867464 -14.480171 -20.331491 -22.898031 -14.215018 -20.824265 -23.077993 -14.223419 -21.607754 -23.395084 -14.504803 -22.628572 -23.827698 -15.039991 -23.817150 -24.346350 -15.792515 -25.092484 -21.086544 -18.102179 -24.307631 -20.906427 -17.142748 -25.252157 -20.751852 -16.320908 -26.214630 -20.633352 -15.692662 -27.129459 -20.559002 -15.300829 -27.934303 -20.533869 -15.172109 -28.574306 -20.559668 -15.315273 -29.005859 -20.634638 -15.720567 -29.199549 -20.753672 -16.360369 -29.142179 -20.908655 -17.191076 -28.837658 -21.089029 -18.156080 -28.306736 -21.282499 -19.189617 -27.585598 -21.475883 -20.221252 -26.723385 -21.656000 -21.180683 -25.778858 -21.810575 -22.002525 -24.816385 -21.929075 -22.630770 -23.901556 -22.003426 -23.022604 -23.096712 -22.028559 -23.151323 -22.456709 -22.002760 -23.008162 -22.025154 -21.927790 -22.602869 -21.831463 -21.808756 -21.963068 -21.888834 -21.653772 -21.132359 -22.193356 -21.473398 -20.167355 -22.724277 -21.279928 -19.133818 -23.445415 -17.958311 -20.573111 -24.238691 -18.039673 -19.753471 -23.494926 -18.097385 -18.926758 -22.863754 -18.127514 -18.149313 -22.388193 -18.128006 -17.474115 -22.100647 -18.098827 -16.947182 -22.020716 -18.041967 -16.604420 -22.153845 -17.961302 -16.469189 -22.490959 -17.862326 -16.550703 -23.009092 -17.751785 -16.843409 -23.672926 -17.637215 -17.327360 -24.437225 -17.526419 -17.969572 -25.249905 -17.426950 -18.726284 -26.055580 -17.345589 -19.545925 -26.799345 -17.287876 -20.372637 -27.430517 -17.257748 -21.150084 -27.906080 -17.257256 -21.825279 -28.193624 -17.286434 -22.352215 -28.273558 -17.343294 -22.694977 -28.140429 -17.423960 -22.830208 -27.803314 -17.522936 -22.748695 -27.285183 -17.633476 -22.455988 -26.621349 -17.748047 -21.972038 -25.857048 -17.858843 -21.329826 -25.044371 -14.110780 -20.647570 -24.858973 -14.380862 -21.242477 -24.169024 -14.650975 -21.738691 -23.478859 -14.902713 -22.102394 -22.835505 -15.118917 -22.308800 -22.282806 -15.284858 -22.343843 -21.858435 -15.389222 -22.205139 -21.591305 -15.424901 -21.902134 -21.499620 -15.389462 -21.455481 -21.589632 -15.285319 -20.895617 -21.855206 -15.119572 -20.260698 -22.278242 -14.903513 -19.593992 -22.829912 -14.651868 -18.940931 -23.472620 -14.381786 -18.346025 -24.162567 -14.111672 -17.849812 -24.852734 -13.859936 -17.486109 -25.496086 -13.643730 -17.279701 -26.048782 -13.477791 -17.244656 -26.473158 -13.373425 -17.383362 -26.740288 -13.337747 -17.686367 -26.831970 -13.373186 -18.133020 -26.741961 -13.477328 -18.692883 -26.476387 -13.643076 -19.327801 -26.053352 -13.859135 -19.994509 -25.501682 -10.986000 -19.029448 -23.481480 -10.688322 -19.756575 -23.910532 -10.436662 -20.478647 -24.258945 -10.248170 -21.146454 -24.502977 -10.135693 -21.714489 -24.625994 -10.106894 -22.144041 -24.619616 -10.163737 -22.405834 -24.484274 -10.302348 -22.482031 -24.229195 -10.513280 -22.367435 -23.871759 -10.782160 -22.069859 -23.436329 -11.090663 -21.609581 -22.952576 -11.417766 -21.017967 -22.453465 -11.741176 -20.335339 -21.973013 -12.038855 -19.608212 -21.543961 -12.290514 -18.886139 -21.195547 -12.479006 -18.218330 -20.951515 -12.591484 -17.650295 -20.828497 -12.620283 -17.220745 -20.834877 -12.563440 -16.958950 -20.970217 -12.424829 -16.882753 -21.225296 -12.213897 -16.997349 -21.582729 -11.945017 -17.294926 -22.018162 -11.636514 -17.755203 -22.501915 -11.309412 -18.346815 -23.001026 -9.097970 -18.459764 -20.500263 -8.671061 -17.953953 -21.182018 -8.241371 -17.545597 -21.848457 -7.838187 -17.262531 -22.454159 -7.488983 -17.124043 -22.957848 -7.217557 -17.139568 -23.325197 -7.042407 -17.308056 -23.531174 -6.975468 -17.618015 -23.561739 -7.021302 -18.048328 -23.414812 -7.176786 -18.569672 -23.100405 -7.431324 -19.146511 -22.639942 -7.767569 -19.739540 -22.064806 -8.162607 -20.308342 -21.414190 -8.589518 -20.814156 -20.732433 -9.019206 -21.222511 -20.065996 -9.422390 -21.505577 -19.460293 -9.771595 -21.644068 -18.956604 -10.043020 -21.628538 -18.589254 -10.218171 -21.460052 -18.383278 -10.285110 -21.150093 -18.352713 -10.239276 -20.719780 -18.499640 -10.083793 -20.198437 -18.814049 -9.829255 -19.621597 -19.274509 -9.493010 -19.028568 -19.849646 -6.826124 -19.643854 -18.044619 -7.300466 -18.690062 -17.733315 -7.696956 -17.754168 -17.505110 -7.988573 -16.899958 -17.375561 -8.155445 -16.185642 -17.353491 -8.186199 -15.659903 -17.440409 -8.078740 -15.358564 -17.630386 -7.840391 -15.302165 -17.910480 -7.487394 -15.494546 -18.261602 -7.043807 -15.922600 -18.659822 -6.539858 -16.557154 -19.078003 -6.009892 -17.354963 -19.487648 -5.490024 -18.261662 -19.860838 -5.015682 -19.215456 -20.172142 -4.619192 -20.151348 -20.400347 -4.327574 -21.005558 -20.529896 -4.160702 -21.719875 -20.551966 -4.129948 -22.245615 -20.465050 -4.237406 -22.546953 -20.275070 -4.475756 -22.603354 -19.994976 -4.828752 -22.410973 -19.643856 -5.272339 -21.982920 -19.245634 -5.776288 -21.348366 -18.827454 -6.306254 -20.550556 -18.417810 -3.165492 -19.812563 -17.156864 -3.960337 -20.424635 -16.241062 -4.752223 -20.900631 -15.362404 -5.487183 -21.208107 -14.580769 -6.115131 -21.326117 -13.949421 -6.593274 -21.246613 -13.511391 -6.889027 -20.975016 -13.296525 -6.982234 -20.529831 -13.319470 -6.866546 -19.941402 -13.578660 -6.549844 -19.249826 -14.056431 -6.053711 -18.502235 -14.720224 -5.411959 -17.749573 -15.524803 -4.668322 -17.043137 -16.415340 -3.873477 -16.431063 -17.331141 -3.081592 -15.955069 -18.209799 -2.346632 -15.647591 -18.991436 -1.718682 -15.529581 -19.622784 -1.240540 -15.609085 -20.060814 -0.944786 -15.880683 -20.275677 -0.851578 -16.325865 -20.252735 -0.967267 -16.914293 -19.993546 -1.283968 -17.605869 -19.515776 -1.780101 -18.353460 -18.851980 -2.421852 -19.106123 -18.047403 -0.645994 -16.927629 -15.786632 0.097415 -18.406633 -16.018904 0.706429 -19.846825 -16.148346 1.139542 -21.150057 -16.166134 1.367240 -22.227520 -16.071056 1.374005 -23.005783 -15.869594 1.159377 -23.431810 -15.575473 0.737981 -23.476566 -15.208739 0.138535 -23.137005 -14.794386 -0.598109 -22.436266 -14.360649 -1.421750 -21.422100 -13.937088 -2.276259 -20.163626 -13.552567 -3.103403 -18.746601 -13.233290 -3.846812 -17.267599 -13.001017 -4.455826 -15.827407 -12.871574 -4.888940 -14.524174 -12.853786 -5.116638 -13.446712 -12.948864 -5.123404 -12.668447 -13.150327 -4.908775 -12.242419 -13.444448 -4.487380 -12.197662 -13.811180 -3.887934 -12.537223 -14.225533 -3.151291 -13.237963 -14.659271 -2.327649 -14.252127 -15.082832 -1.473140 -15.510601 -15.467354 -1.136270 -15.097721 -11.881963 0.223666 -14.289313 -13.135876 1.568365 -13.679209 -14.323397 2.806186 -13.308987 -15.363595 3.852774 -13.203876 -16.185583 4.636806 -13.371042 -16.733345 5.104852 -13.799089 -16.969551 5.225015 -14.458851 -16.878105 4.989105 -15.305362 -16.465239 4.413201 -16.280935 -15.759088 3.536549 -17.319086 -14.807775 2.418891 -18.349070 -13.676131 1.136394 -19.300692 -12.441276 -0.223543 -20.109100 -11.187363 -1.568241 -20.719204 -9.999842 -2.806062 -21.089428 -8.959644 -3.852652 -21.194538 -8.137655 -4.636684 -21.027374 -7.589891 -5.104731 -20.599325 -7.353684 -5.224894 -19.939566 -7.445131 -4.988985 -19.093056 -7.857997 -4.413082 -18.117481 -8.564148 -3.536429 -17.079329 -9.515460 -2.418772 -16.049345 -10.647103 -0.186287 -17.720510 -8.087603 -1.243345 -15.607950 -7.956367 -2.097297 -13.557928 -7.948522 -2.689950 -11.710155 -8.064600 -2.980915 -10.190549 -8.296692 -2.950363 -9.102674 -8.628979 -2.600376 -8.520661 -9.038818 -1.954805 -8.484177 -9.498280 -1.057645 -8.995708 -9.976051 0.029963 -10.020391 -10.439574 1.233903 -11.488400 -10.857258 2.472126 -13.299689 -11.200642 3.660251 -15.330824 -11.446321 4.717309 -17.443384 -11.577557 5.571261 -19.493406 -11.585402 6.163915 -21.341179 -11.469324 6.454880 -22.860786 -11.237233 6.424328 -23.948664 -10.904945 6.074342 -24.530676 -10.495106 5.428772 -24.567162 -10.035645 4.531612 -24.055632 -9.557873 3.444004 -23.030949 -9.094352 2.240064 -21.562943 -8.676666 1.001841 -19.751654 -8.333283 4.891482 -18.620085 -7.510373 2.962749 -19.642153 -5.957009 1.061307 -20.403917 -4.498141 -0.683261 -20.853460 -3.233189 -2.152067 -20.960146 -2.248356 -3.245015 -20.716711 -1.610757 -3.887621 -20.139738 -1.363844 -4.036094 -19.268547 -1.524443 -3.680315 -18.162512 -2.081609 -2.844529 -16.897007 -2.997374 -1.585695 -15.558270 -4.209328 0.010400 -14.237537 -5.634879 1.834985 -13.024814 -7.176879 3.763718 -12.002744 -8.730242 5.665160 -11.240980 -10.189110 7.409728 -10.791437 -11.454062 8.878536 -10.684748 -12.438896 9.971484 -10.928185 -13.076496 10.614091 -11.505157 -13.323410 10.762565 -12.376347 -13.162811 10.406787 -13.482382 -12.605646 9.571001 -14.747888 -11.689882 8.312168 -16.086624 -10.477928 6.716073 -17.407356 -9.052377 7.389603 -13.642259 -6.875250 8.722322 -16.248865 -6.899809 9.794791 -18.776567 -6.788310 10.533924 -21.053106 -6.548347 10.889350 -22.923342 -6.196276 10.836847 -24.259819 -5.756090 10.379993 -24.971458 -5.257786 9.549922 -25.009764 -4.735323 8.403201 -24.372124 -4.224306 7.017980 -23.101995 -3.759560 5.488657 -21.285934 -3.372757 3.919452 -19.047699 -3.090255 2.417306 -16.539825 -2.931309 1.084587 -13.933221 -2.906749 0.012117 -11.405518 -3.018249 -0.727017 -9.128979 -3.258211 -1.082443 -7.258741 -3.610281 -1.029941 -5.922264 -4.050467 -0.573087 -5.210623 -4.548771 0.256984 -5.172318 -5.071235 1.403703 -5.809955 -5.582252 2.788925 -7.080084 -6.046998 4.318248 -8.896145 -6.433801 5.887452 -11.134378 -6.716302 4.570469 -11.126987 -2.399946 6.849924 -9.954147 -4.120268 9.097346 -9.079464 -5.727011 11.159577 -8.562544 -7.110678 12.896079 -8.438614 -8.176974 14.188513 -8.716122 -8.853233 14.948800 -9.376154 -9.093369 15.125130 -10.373732 -8.881017 14.705485 -11.640869 -8.230650 13.718465 -13.091215 -7.186586 12.231331 -14.625931 -5.819980 10.345430 -16.140429 -4.223961 8.189284 -17.531494 -2.507297 5.909829 -18.704334 -0.786975 3.662407 -19.579020 0.819768 1.600176 -20.095938 2.203435 -0.136328 -20.219870 3.269732 -1.428762 -19.942364 3.945992 -2.189050 -19.282330 4.186129 -2.365381 -18.284754 3.973778 -1.945737 -17.017616 3.323411 -0.958717 -15.567270 2.279348 0.528416 -14.032555 0.912742 2.414316 -12.518058 -0.683276 5.114467 -15.089705 2.076186 3.636266 -12.317812 2.005335 2.442674 -9.628637 1.797831 1.615031 -7.205442 1.467816 1.209740 -5.213366 1.037778 1.254422 -3.788164 0.537026 1.746030 -3.026961 -0.000317 2.651063 -2.981632 -0.537630 3.907844 -3.655266 -1.038298 5.430727 -5.001956 -1.468199 7.115927 -6.929927 -1.798038 8.848602 -9.307792 -2.005336 10.510674 -11.973502 -2.075966 11.988875 -14.745395 -2.005116 13.182468 -17.434570 -1.797612 14.010111 -19.857763 -1.467596 14.415403 -21.849842 -1.037559 14.370723 -23.275045 -0.536806 13.879114 -24.036249 0.000536 12.974082 -24.081581 0.537849 11.717301 -23.407946 1.038517 10.194421 -22.061256 1.468419 8.509220 -20.133286 1.798257 6.776544 -17.755424 2.005556 11.088828 -15.857403 2.508171 8.806945 -17.028835 4.226211 6.553190 -17.904562 5.823469 4.481153 -18.424902 7.191094 2.732040 -18.554394 8.235886 1.425049 -18.284216 8.886642 0.649251 -17.632776 9.099016 0.457513 -16.644474 8.858534 0.862904 -15.386658 8.181585 1.837795 -13.945047 7.114302 3.315751 -12.417883 5.729418 5.196050 -10.909241 4.121311 7.350554 -9.521931 2.399571 9.632436 -8.350498 0.681531 11.886190 -7.474771 -0.915727 13.958227 -6.954431 -2.283353 15.707342 -6.824937 -3.328146 17.014334 -7.095116 -3.978903 17.790133 -7.746553 -4.191278 17.981871 -8.734856 -3.950796 17.576483 -9.992671 -3.273848 16.601591 -11.434282 -2.206566 15.123636 -12.961447 -0.821681 13.243338 -14.470089 0.786426 13.115394 -10.362179 2.932385 14.537056 -12.916508 3.091435 15.691617 -15.394199 3.373975 16.500395 -17.626402 3.760752 16.908272 -19.460997 4.225408 16.887453 -20.772957 4.736276 16.439358 -21.472878 5.258542 15.594522 -21.513058 5.756614 14.410520 -20.890759 6.196550 12.968039 -19.648392 6.548369 11.365382 -17.870623 6.788095 9.711768 -15.678598 6.899390 8.119888 -13.221706 6.874671 6.698225 -10.667378 6.715622 5.543664 -8.189688 6.433082 4.734886 -5.957483 6.046305 4.327007 -4.122887 5.581649 4.347825 -2.810925 5.070782 4.795920 -2.111005 4.548515 5.640756 -2.070823 4.050443 6.824758 -2.693120 3.610507 8.267238 -3.935486 3.258688 9.869895 -5.713257 3.018962 11.523508 -7.905279 2.907666 10.361468 -8.102112 7.176916 12.323922 -7.127523 5.635365 14.265742 -6.404829 4.210246 16.054600 -5.983277 2.998679 17.568584 -5.891597 2.083230 18.704523 -6.136036 1.526285 19.385000 -6.699937 1.365800 19.563646 -7.544868 1.612710 19.228283 -8.613254 2.250188 18.401770 -9.832280 3.234794 17.140427 -11.118876 4.499426 15.530216 -12.385359 5.957902 13.680870 -13.545424 7.510831 11.718417 -14.520012 9.052382 9.776596 -15.242707 10.477500 7.987740 -15.664260 11.689068 6.473752 -15.755940 12.604518 5.337814 -15.511501 13.161463 4.657336 -14.947601 13.321949 4.478690 -14.102670 13.075040 4.814050 -13.034286 12.437562 5.640565 -11.815258 11.452957 6.901906 -10.528665 10.188325 8.512116 -9.262180 8.729849 11.447283 -10.834722 11.447261 10.282015 -8.790518 11.200825 9.332184 -6.812860 10.856692 8.662519 -5.036520 10.438315 8.318656 -3.582555 9.974204 8.324029 -2.550049 9.495990 8.678273 -2.009366 9.036260 9.357245 -1.997351 8.626343 10.314676 -2.514825 8.294177 11.485317 -3.526522 8.062398 12.789392 -4.963496 7.946799 14.138030 -6.727821 7.955260 15.439323 -8.699261 8.087205 16.604591 -10.743464 8.333641 17.554422 -12.721121 8.677773 18.224089 -14.497461 9.096149 18.567953 -15.951428 9.560261 18.562578 -16.983936 10.038476 18.208336 -17.524620 10.498206 17.529364 -17.536634 10.908122 16.571934 -17.019159 11.240288 15.401293 -16.007465 11.472069 14.097219 -14.570492 11.587667 12.748581 -12.806167 11.579206 16.146509 -10.634315 12.443004 14.681439 -11.267720 13.678916 13.230928 -11.719292 14.811442 11.893826 -11.958256 15.763406 10.761253 -11.968328 16.469929 9.910394 -11.748824 16.882864 9.399231 -11.314701 16.974070 9.262601 -10.695542 16.737333 9.509814 -9.933544 16.188786 10.124023 -9.080636 15.365808 11.063372 -8.194942 14.324489 12.263844 -7.336819 13.135789 13.643629 -6.564748 11.880717 15.108698 -5.931344 10.644806 16.559208 -5.479773 9.512278 17.896311 -5.240807 8.560315 19.028885 -5.230734 7.853792 19.879745 -5.450238 7.440856 20.390909 -5.884361 7.349649 20.527538 -6.503519 7.586385 20.280327 -7.265516 8.134933 19.666119 -8.118424 8.957909 18.726770 -9.004120 9.999229 17.526299 -9.862243 11.187928 17.786671 -6.687256 13.232531 18.600098 -8.111830 13.553269 19.262564 -9.480728 13.939221 19.728920 -10.700665 14.364084 19.967388 -11.688503 14.798904 19.961714 -12.376924 15.214049 19.712286 -12.719011 15.581228 19.236103 -12.691453 15.875418 18.565615 -12.296127 16.076571 17.746513 -11.559975 16.170977 16.834621 -10.533163 16.152205 15.892080 -9.285667 16.021530 14.983125 -7.902504 15.787863 14.169697 -6.477931 15.467125 13.507232 -5.109032 15.081173 13.040874 -3.889095 14.656310 12.802406 -2.901256 14.221489 12.808080 -2.212835 13.806344 13.057508 -1.870747 13.439165 13.533690 -1.898306 13.144976 14.204179 -2.293630 12.943823 15.023279 -3.029782 12.849417 15.935172 -4.056593 12.868190 16.877712 -5.304088 12.998862 17.093931 -4.478890 16.414778 18.077427 -4.188550 15.524011 19.050030 -4.009501 14.719268 19.945459 -3.953944 14.055393 20.702692 -4.025667 13.577626 21.270126 -4.219782 13.318528 21.609091 -4.523059 13.295754 21.696487 -4.914832 13.510857 21.526358 -5.368401 13.949178 21.110298 -5.852857 14.580846 20.476660 -6.335183 15.362814 19.668627 -6.782513 16.241791 18.741264 -7.164359 17.157881 17.757769 -7.454700 18.048647 16.785166 -7.633749 18.853390 15.889737 -7.689305 19.517263 15.132503 -7.617582 19.995031 14.565068 -7.423468 20.254129 14.226103 -7.120191 20.276903 14.138706 -6.728418 20.061802 14.308835 -6.274849 19.623482 14.724895 -5.790393 18.991814 15.358533 -5.308066 18.209846 16.166565 -4.860738 17.330868 18.560339 -4.375050 19.861387 18.035007 -3.471970 19.487141 17.609020 -2.614630 19.076487 17.311407 -1.861456 18.657413 17.162451 -1.263775 18.258476 17.172300 -0.862319 17.906868 17.340288 -0.684447 17.626547 17.654963 -0.742279 17.436615 18.094881 -1.031874 17.350019 18.630062 -1.533498 17.372656 19.224037 -2.212965 17.502989 19.836325 -3.023970 17.732132 20.425200 -3.911246 18.044468 20.950531 -4.814326 18.418716 21.376518 -5.671666 18.829370 21.674131 -6.424840 19.248444 21.823088 -7.022522 19.647379 21.813238 -7.423978 19.998989 21.645250 -7.601851 20.279310 21.330576 -7.544019 20.469240 20.890659 -7.254425 20.555840 20.355476 -6.752801 20.533201 19.761503 -6.073335 20.402870 19.149216 -5.262329 20.173727 21.669058 -3.084173 21.415731 20.979010 -3.140840 22.066498 20.297369 -3.134601 22.641678 19.670589 -3.065881 23.102079 19.141384 -2.939363 23.416328 18.745819 -2.763671 23.563004 18.510851 -2.550776 23.532114 18.452492 -2.315187 23.325764 18.574718 -2.072958 22.958014 18.869202 -1.840599 22.453926 19.315874 -1.633943 21.847857 19.884295 -1.467074 21.181101 20.535725 -1.351363 20.499105 21.225775 -1.294696 19.848341 21.907413 -1.300935 19.273161 22.534193 -1.369655 18.812759 23.063398 -1.496172 18.498510 23.458963 -1.671865 18.351833 23.693933 -1.884760 18.382723 23.752293 -2.120349 18.589073 23.630066 -2.362577 18.956821 23.335583 -2.594937 19.460911 22.888910 -2.801593 20.066980 22.320492 -2.968462 20.733734</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-positions-array" count="2880" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-normals">
+ <float_array id="Torus_Knot01-mesh-normals-array" count="8640">0.704886 -0.007624 -0.709279 -0.552938 0.557017 -0.619671 -0.590652 0.293027 -0.751841 0.591047 -0.261263 -0.763155 -0.568967 0.072133 -0.819191 0.484794 -0.450902 -0.749441 -0.497136 -0.067077 -0.865076 0.438288 -0.583459 -0.683724 -0.328414 -0.105248 -0.938652 0.500772 -0.686193 -0.527605 0.192150 0.038515 -0.980610 0.673907 -0.734891 -0.076053 0.748946 -0.022929 -0.662235 0.523221 -0.672393 0.523572 0.986999 -0.116886 -0.110323 0.170952 -0.356421 0.918553 0.948569 -0.050524 0.312512 -0.034391 0.042307 0.998513 0.871825 -0.067155 0.485192 -0.164381 0.184185 0.969048 0.800840 -0.182613 0.570358 -0.314586 0.192939 0.929414 0.695816 -0.378362 0.610477 -0.502995 0.124427 0.855286 0.524877 -0.602533 0.601214 -0.702944 0.004762 0.711229 0.317888 -0.772791 0.549310 -0.851886 -0.119892 0.509819 0.131229 -0.858275 0.496128 -0.928467 -0.197612 0.314480 -0.023550 -0.873057 0.487049 -0.967402 -0.198502 0.157261 -0.180125 -0.802186 0.569256 -0.997141 -0.072964 0.019665 -0.431783 -0.493589 0.754939 -0.930276 0.314549 -0.188800 -0.746566 0.032318 0.664526 -0.528675 0.662144 -0.531101 -0.786200 0.534650 0.309901 0.093423 0.748686 -0.656309 -0.509741 0.859047 0.046922 0.539919 0.693736 -0.476674 -0.389427 0.914747 -0.107633 0.689366 0.584873 -0.427432 -0.396882 0.880786 -0.258266 0.752970 0.447268 -0.482687 -0.468656 0.768620 -0.435414 0.763512 0.250603 -0.595187 -0.714402 0.133156 0.686949 -0.845957 -0.089426 0.525699 -0.900741 -0.244986 0.358674 -0.928054 -0.307061 0.210783 -0.969021 -0.242469 0.046985 -0.955601 0.103995 -0.275702 -0.576550 0.384482 -0.720947 0.009253 0.453635 -0.891140 0.460728 0.518945 -0.720017 0.625893 0.468151 -0.623773 0.702675 0.332745 -0.628911 0.727408 0.095564 -0.679518 0.673728 -0.230237 -0.702198 0.556235 -0.519385 -0.648723 0.450990 -0.698498 -0.555616 0.409889 -0.795532 -0.446228 0.491286 -0.826205 -0.275723 0.735300 -0.654914 0.174417 0.577495 -0.392935 0.715612 0.185942 -0.039082 0.981783 -0.058534 0.340458 0.938436 -0.191250 0.472651 0.860247 -0.335755 0.458099 0.823051 -0.519859 0.339549 0.783870 0.612432 -0.281107 0.738855 0.404746 -0.517469 0.753927 0.221436 -0.646634 0.729953 0.075033 -0.681093 0.728342 -0.077008 -0.601480 0.795167 -0.362920 -0.262750 0.894009 -0.758897 0.132758 0.637535 -0.902564 0.405804 0.143880 -0.661118 0.712321 -0.235628 -0.505733 0.765383 -0.398023 -0.507214 0.686205 -0.521398 -0.584101 0.490287 -0.646873 -0.660408 0.150076 -0.735757 -0.651566 -0.213400 -0.727958 -0.582152 -0.454956 -0.673880 -0.489437 -0.584360 -0.647282 -0.333813 -0.609652 -0.718953 0.216046 -0.245059 -0.945130 0.741833 -0.119087 -0.659926 0.990201 -0.002139 -0.139633 0.947089 0.224429 0.229462 0.872803 0.286204 0.395350 0.828489 0.206802 0.520422 0.763255 0.002123 0.646094 0.680004 -0.387243 -0.622606 0.594015 -0.689367 -0.414632 0.506397 -0.829140 -0.236831 0.484077 -0.869035 -0.102211 0.598664 -0.800144 0.037033 0.867869 -0.364740 0.337295 0.667391 0.031563 0.744038 0.223149 0.357953 0.906683 -0.091046 0.674050 0.733053 -0.236006 0.767279 0.596308 -0.369970 0.722514 0.584034 -0.537741 0.555024 0.634652 -0.706779 0.239930 0.665505 -0.783411 -0.111974 0.611334 -0.783345 -0.346554 0.516015 -0.788043 -0.458941 0.410318 -0.855046 -0.454043 0.250483 -0.959942 -0.200086 -0.196156 -0.665124 -0.060893 -0.744246 -0.135159 0.012510 -0.990745 0.307631 0.283164 -0.908395 0.480517 0.347663 -0.805130 0.584729 0.248351 -0.772278 0.667366 -0.004022 -0.744719 -0.715285 -0.310028 -0.626299 -0.602962 -0.661473 -0.445971 -0.465752 -0.833593 -0.296981 -0.346266 -0.907630 -0.237291 -0.203778 -0.917176 -0.342436 0.220977 -0.520084 -0.825035 0.703431 -0.230652 -0.672297 0.951001 0.127994 -0.281450 0.867413 0.496431 -0.033929 0.779549 0.619395 0.093024 0.764902 0.598113 0.239136 0.770044 0.451130 0.451125 0.701164 0.176606 0.690781 0.544331 -0.108139 0.831871 0.389868 -0.285886 0.875370 0.260391 -0.345361 0.901622 0.107092 -0.264086 0.958535 -0.245479 0.045862 0.968316 -0.738861 0.196650 0.644526 -0.974712 0.175592 0.138219 -0.823165 0.416235 -0.386197 -0.654227 0.479481 -0.584881 -0.651344 0.362332 -0.666682 -0.707726 0.100151 -0.699353 -0.695522 0.334571 0.635855 -0.674328 -0.041542 0.737262 -0.612828 -0.291153 0.734624 -0.598204 -0.426873 0.678182 -0.690346 -0.485453 0.536431 -0.899408 -0.435622 0.036030 -0.685012 -0.482893 -0.545502 -0.214867 -0.413539 -0.884770 0.146401 -0.018494 -0.989053 0.299051 0.126203 -0.945855 0.427313 0.071554 -0.901268 0.579968 -0.129695 -0.804249 0.710367 -0.432655 -0.555147 0.722698 -0.651112 -0.231862 0.685243 -0.728314 -0.000043 0.686185 -0.714085 0.138681 0.797638 -0.563965 0.213816 0.956193 -0.011668 0.292506 0.693559 0.446015 0.565726 0.198024 0.710793 0.674952 -0.202068 0.883701 0.422186 -0.370767 0.889681 0.266458 -0.488215 0.821332 0.295058 -0.609233 0.657536 0.443263 0.688540 0.567946 0.450944 0.625232 0.324144 0.709940 0.525543 0.142011 0.838831 0.417823 0.071620 0.905701 0.253042 0.142676 0.956877 -0.167045 0.363346 0.916556 -0.704456 0.279507 0.652394 -0.974151 0.036231 0.222972 -0.915767 0.112472 -0.385643 -0.788050 0.120462 -0.603711 -0.768745 -0.018961 -0.639274 -0.765985 -0.282755 -0.577336 -0.672407 -0.634047 -0.381908 -0.470583 -0.873371 -0.125601 -0.287596 -0.956872 0.041035 -0.150393 -0.984473 0.090520 -0.017656 -0.998376 -0.054159 0.268387 -0.742093 -0.614220 0.684298 -0.330901 -0.649800 0.867853 0.194061 -0.457352 0.706504 0.616506 -0.347522 0.598330 0.758282 -0.258863 0.601627 0.790410 -0.115315 0.661229 0.739591 0.125624 0.727109 -0.426944 -0.537616 0.830582 -0.523348 -0.190368 0.845426 -0.531294 0.054610 0.862483 -0.472052 0.182458 0.939843 -0.280932 0.194351 0.958515 0.259950 0.116938 0.629190 0.721159 0.289912 0.092438 0.918255 0.385048 -0.364011 0.920874 0.139595 -0.539234 0.841668 0.028653 -0.635002 0.766011 0.099999 -0.703510 0.642065 0.304675 -0.702502 0.397864 0.590081 -0.597284 0.094343 0.796461 -0.487589 -0.126449 0.863868 -0.452819 -0.269967 0.849749 -0.549828 -0.387790 0.739803 -0.790629 -0.541852 0.285134 -0.617604 -0.739621 -0.267445 -0.208630 -0.689238 -0.693848 0.044481 -0.289815 -0.956048 0.168905 -0.127688 -0.977326 0.311964 -0.142557 -0.939338 0.511762 -0.262416 -0.818069 -0.568021 -0.813465 -0.125006 -0.310942 -0.940598 0.136348 -0.101951 -0.952570 0.286732 0.043672 -0.947954 0.315398 0.164018 -0.975631 0.145749 0.353208 -0.830974 -0.429798 0.673172 -0.383268 -0.632413 0.752776 0.206042 -0.625200 0.506978 0.608457 -0.610535 0.384342 0.746344 -0.543370 0.396133 0.819040 -0.415032 0.485347 0.853983 -0.187488 0.579994 0.800482 0.151117 0.601884 0.646588 0.468679 0.560634 0.500325 0.659821 0.477195 0.436332 0.762823 0.301509 0.489697 0.818101 -0.158659 0.601059 0.783298 -0.684573 0.349663 0.639606 -0.949543 -0.043413 0.310618 -0.945645 -0.141863 -0.292626 -0.849797 -0.197350 -0.488772 -0.805189 -0.338127 -0.487176 -0.740825 -0.561595 -0.368496 -0.719558 0.420141 0.552918 -0.545591 0.210215 0.811259 -0.391801 0.036387 0.919330 -0.333543 -0.100304 0.937384 -0.423025 -0.260657 0.867818 -0.659100 -0.563545 0.498001 -0.499695 -0.866201 0.000728 -0.158368 -0.853120 -0.497098 -0.014781 -0.497465 -0.867358 0.079235 -0.339994 -0.937083 0.226811 -0.321997 -0.919171 0.454463 -0.367937 -0.811225 0.723637 -0.413111 -0.552891 0.888617 -0.399004 -0.226178 0.939853 -0.341521 0.006352 0.962658 -0.246787 0.111292 0.997063 -0.042849 0.063471 0.889852 0.441439 -0.115302 0.499556 0.866282 -0.000573 -0.063372 0.991386 0.114621 -0.536449 0.841538 -0.063523 -0.695890 0.709471 -0.111302 -0.766361 0.642379 -0.006311 -0.790211 0.569538 0.226260 0.403171 0.902528 -0.151317 0.496828 0.847449 0.187060 0.511214 0.752996 0.414316 0.454240 0.706634 0.542525 0.273574 0.743931 0.609692 -0.198021 0.755433 0.624586 -0.668337 0.391448 0.632530 -0.895869 -0.109887 0.430516 -0.926680 -0.346528 -0.145543 -0.842552 -0.436907 -0.314990 -0.773738 -0.565091 -0.286359 -0.658940 -0.739755 -0.136236 -0.420440 -0.898686 0.124873 -0.115691 -0.922390 0.368528 0.110364 -0.866196 0.487364 0.254768 -0.834293 0.488926 0.350693 -0.889609 0.292592 0.437626 -0.844007 -0.310058 0.645030 -0.418185 -0.639576 0.599267 0.162710 -0.783839 0.272765 0.505258 -0.818727 0.138695 0.630805 -0.763445 0.152507 0.735281 -0.660381 0.258789 0.844405 -0.469050 0.695801 -0.409544 -0.590029 0.907954 -0.287623 -0.304783 0.981028 -0.165902 -0.100304 0.998564 -0.045016 -0.029053 0.979324 0.146075 -0.139954 0.748330 0.539525 -0.385895 0.308754 0.905524 -0.291029 -0.254970 0.959797 -0.117391 -0.713995 0.672735 -0.194009 -0.840782 0.509859 -0.182017 -0.883372 0.465532 -0.054168 -0.868791 0.456984 0.190702 -0.733282 0.416184 0.537669 -0.482953 0.312635 0.817934 -0.279089 0.199963 0.939215 -0.194616 0.083655 0.977306 -0.272888 -0.105374 0.956258 -0.491878 -0.524842 0.694691 -0.330845 -0.904558 0.268918 -0.073689 -0.955948 -0.284135 -0.061388 -0.670892 -0.739009 -0.007943 -0.528229 -0.849065 0.133775 -0.486507 -0.863374 0.380004 -0.470786 -0.796215 -0.212899 -0.899418 0.381734 0.138424 -0.804773 0.577217 0.368660 -0.674961 0.639154 0.499222 -0.621806 0.603436 0.555994 -0.736538 0.385204 0.518929 -0.825346 -0.222522 0.594030 -0.470573 -0.652449 0.397315 0.036198 -0.916968 -0.003698 0.289384 -0.957206 -0.147653 0.396664 -0.906011 -0.140463 0.525423 -0.839167 -0.032305 0.703223 -0.710235 0.147435 0.880180 -0.451160 0.309743 0.942412 -0.126171 0.383531 0.916422 0.114342 0.357417 0.897694 0.257678 0.180609 0.920554 0.346353 -0.265985 0.848951 0.456657 -0.628274 0.427399 0.650078 -0.776047 -0.138558 0.615267 -0.855336 -0.515191 0.054576 -0.776955 -0.623122 -0.089771 -0.684497 -0.727897 -0.040382 -0.520850 -0.844323 0.125830 -0.729829 0.398764 0.555281 -0.402248 0.438121 0.803895 -0.151516 0.407088 0.900735 -0.039988 0.323544 0.945368 -0.088932 0.118796 0.988928 -0.249593 -0.391843 0.885529 -0.074250 -0.833844 0.546983 0.073031 -0.996722 -0.034808 -0.075434 -0.841450 -0.535044 -0.070828 -0.732708 -0.676848 0.054025 -0.677478 -0.733556 0.301029 -0.605603 -0.736632 0.637543 -0.435179 -0.635734 0.874035 -0.198179 -0.443607 0.955193 -0.011084 -0.295777 0.955490 0.124865 -0.267296 0.865778 0.267612 -0.422863 0.515350 0.526780 -0.675956 0.037763 0.823039 -0.566729 -0.489219 0.821598 -0.292645 -0.887912 0.407820 -0.212826 -0.961999 0.235900 -0.137510 -0.973642 0.228080 0.001126 -0.925300 0.299516 0.232617 -0.197921 0.695350 -0.690881 0.005354 0.892197 -0.451615 0.135051 0.961294 -0.240157 0.146125 0.984757 -0.094348 -0.004259 0.999460 0.032590 -0.365069 0.887664 0.280673 -0.550942 0.494300 0.672407 -0.559798 -0.068109 0.825825 -0.691588 -0.635707 0.342902 -0.612048 -0.754081 0.238241 -0.488333 -0.820297 0.297733 -0.271030 -0.852922 0.446170 0.089156 -0.774660 0.626062 0.440956 -0.562924 0.699053 0.640169 -0.382622 0.666171 0.743154 -0.326405 0.584108 0.772689 -0.504392 0.385409 0.640161 -0.755761 -0.137909 0.539540 -0.541816 -0.644462 0.161623 -0.190826 -0.968227 -0.282917 -0.040735 -0.958279 -0.430019 0.051504 -0.901350 -0.443241 0.193686 -0.875227 -0.366359 0.416827 -0.831888 0.561208 -0.492100 -0.665494 0.749176 -0.187614 -0.635245 0.809957 0.041617 -0.585011 0.781524 0.179993 -0.597346 0.628225 0.258593 -0.733800 0.196863 0.371639 -0.907265 -0.308251 0.592602 -0.744180 -0.750650 0.568490 -0.336665 -0.992445 0.117514 -0.035271 -0.994430 -0.016384 0.104118 -0.970867 0.023009 0.238513 -0.893615 0.169057 0.415779 -0.675213 0.395060 0.622909 -0.337321 0.576366 0.744323 -0.077484 0.631501 0.771494 0.060671 0.591144 0.804281 0.091477 0.409103 0.907891 0.079562 -0.109411 0.990807 0.281438 -0.604912 0.744899 0.307429 -0.930941 0.197068 0.034668 -0.967928 -0.248825 -0.003057 -0.912690 -0.408642 0.091853 -0.852457 -0.514665 0.294927 -0.734992 -0.610578 0.460351 -0.497211 0.735431 0.717095 -0.260925 0.646291 0.848471 -0.096081 0.520447 0.916263 -0.055077 0.396773 0.947854 -0.216013 0.234331 0.803192 -0.577944 -0.144441 0.494138 -0.590949 -0.637657 -0.046700 -0.446547 -0.893541 -0.482893 -0.368472 -0.794382 -0.627938 -0.276500 -0.727490 -0.671356 -0.132220 -0.729246 -0.651094 0.091504 -0.753462 -0.550038 0.389781 -0.738599 -0.380134 0.661802 -0.646155 -0.235699 0.820425 -0.520911 -0.189217 0.898481 -0.396143 -0.279874 0.932003 -0.230307 -0.497469 0.856230 0.139262 -0.473620 0.583285 0.659896 -0.319449 0.064792 0.945386 -0.359987 -0.594138 0.719312 -0.260267 -0.715894 0.647886 -0.102109 -0.731426 0.674233 0.141357 -0.670950 0.727904 -0.535828 0.468123 0.702673 -0.280925 0.677732 0.679530 -0.063328 0.775192 0.628544 0.092325 0.776573 0.623225 0.219135 0.658965 0.719545 0.389021 0.235644 0.890581 0.622340 -0.305877 0.720508 0.568380 -0.775144 0.275855 0.275003 -0.960339 -0.046072 0.198582 -0.957359 -0.209830 0.238530 -0.902743 -0.357993 0.345593 -0.777448 -0.525491 0.472210 -0.551990 -0.687258 0.553239 -0.280131 -0.784509 0.563497 -0.061418 -0.823832 0.503665 0.070935 -0.860982 0.322832 0.119628 -0.938866 -0.128226 0.140991 -0.981672 -0.630388 0.302840 -0.714772 -0.935118 0.309118 -0.173207 -0.960639 0.012227 0.277532 -0.893002 -0.043015 0.447992 -0.829436 0.041090 0.557088 -0.727087 0.221775 0.649739 -0.784601 0.153560 -0.600684 -0.675866 0.413455 -0.610131 -0.558949 0.602005 -0.570233 -0.494548 0.721070 -0.485263 -0.518520 0.795862 -0.312635 -0.594944 0.796134 0.110508 -0.393808 0.637344 0.662350 -0.061817 0.185569 0.980685 0.073984 -0.337129 0.938547 0.191283 -0.463945 0.864966 0.347536 -0.456628 0.818968 0.549447 -0.365221 0.751479 0.759158 -0.200804 0.619158 0.900346 -0.022006 0.434618 0.961560 0.096358 0.257132 0.987088 0.119867 0.106249 0.998755 -0.012085 -0.048399 0.855861 -0.413273 -0.310980 0.400620 -0.630484 -0.664826 -0.212213 -0.621056 -0.754490 -0.605131 -0.557379 -0.568458 -0.744809 -0.457100 -0.486128 -0.809429 -0.315488 -0.495270 -0.828691 -0.110888 -0.548613 0.354960 -0.606332 -0.711593 0.358297 -0.373306 -0.855726 0.323215 -0.175939 -0.929827 0.240450 -0.050289 -0.969358 0.052661 -0.008649 -0.998575 -0.395169 -0.030292 -0.918109 -0.844610 0.116772 -0.522492 -0.973238 0.216457 0.077167 -0.843846 0.090962 0.528818 -0.723377 0.088118 0.684807 -0.631806 0.194565 0.750310 -0.520841 0.381258 0.763785 -0.358397 0.606558 0.709675 -0.164380 0.786477 0.595342 0.011028 0.875783 0.482579 0.161955 0.889566 0.427134 0.331099 0.814551 0.476319 0.602256 0.455392 0.655672 0.838363 -0.126329 0.530273 0.737760 -0.648224 0.188455 0.435566 -0.899946 -0.019480 0.311937 -0.937040 -0.157008 0.293071 -0.902929 -0.314369 0.321819 -0.797731 -0.509959 0.920386 -0.024069 0.390268 0.981756 0.131850 0.137004 0.971982 0.223829 -0.071777 0.945785 0.231702 -0.227606 0.927485 0.096637 -0.361155 0.772441 -0.383623 -0.506131 0.247836 -0.699100 -0.670698 -0.353681 -0.713288 -0.605087 -0.693041 -0.640595 -0.330653 -0.813728 -0.538962 -0.217641 -0.885970 -0.402661 -0.230045 -0.927028 -0.201057 -0.316537 -0.901659 0.067992 -0.427070 -0.799666 0.331973 -0.500328 -0.679454 0.524193 -0.513385 -0.597645 0.653172 -0.464959 -0.583254 0.751513 -0.308290 -0.585031 0.796405 0.153222 -0.249463 0.689386 0.680085 0.195239 0.331610 0.922993 0.379507 -0.125491 0.916639 0.475869 -0.275150 0.835369 0.605685 -0.275700 0.746415 0.771341 -0.183293 0.609456 -0.199198 0.738028 0.644698 -0.017774 0.911982 0.409845 0.127839 0.967268 0.219203 0.251089 0.960467 0.120241 0.415649 0.897173 0.149384 0.740358 0.526596 0.417812 0.940416 -0.073482 0.331990 0.799371 -0.596391 0.072960 0.451087 -0.892473 -0.003564 0.281272 -0.956834 -0.073170 0.228463 -0.949041 -0.217083 0.226847 -0.863293 -0.450850 0.224706 -0.651710 -0.724418 0.192295 -0.376547 -0.906220 0.139180 -0.158834 -0.977446 0.055182 -0.032524 -0.997946 -0.126496 -0.009346 -0.991923 -0.592970 -0.105340 -0.798305 -0.949130 0.059828 -0.309149 -0.934536 0.250164 0.253103 -0.709791 0.165909 0.684595 -0.554080 0.149472 0.818934 -0.458223 0.258767 0.850336 -0.355795 0.474213 0.805315 -0.951937 0.072575 -0.297571 -0.796912 0.385974 -0.464711 -0.631313 0.568828 -0.527141 -0.531446 0.677292 -0.508765 -0.518972 0.772872 -0.365153 -0.527794 0.826178 0.197136 -0.109572 0.747523 0.655136 0.367922 0.455804 0.810479 0.526262 -0.043864 0.849190 0.565168 -0.247263 0.787049 0.670791 -0.266087 0.692269 0.842923 -0.164481 0.512276 0.984039 0.042950 0.172692 0.955924 0.230284 -0.182148 0.858687 0.318764 -0.401305 0.786560 0.317870 -0.529417 0.767322 0.169206 -0.618536 0.646645 -0.456339 -0.611232 0.117164 -0.763439 -0.635164 -0.444753 -0.752523 -0.485699 -0.727318 -0.679174 -0.098647 -0.805873 -0.587726 0.071740 -0.881940 -0.467153 0.062856 -0.962515 -0.260607 -0.075164 0.110934 -0.690362 -0.714908 0.063257 -0.306740 -0.949689 0.019510 -0.054132 -0.998343 -0.047028 0.062738 -0.996921 -0.219919 0.045086 -0.974476 -0.731816 -0.167668 -0.660555 -0.985297 0.055124 -0.161711 -0.890051 0.317281 0.327324 -0.597771 0.197235 0.777025 -0.409485 0.109964 0.905666 -0.321380 0.206333 0.924198 -0.239942 0.466958 0.851104 -0.084047 0.826208 0.557060 0.084548 0.984812 0.151647 0.182735 0.978288 -0.097776 0.264759 0.942841 -0.202370 0.417313 0.896029 -0.151600 0.814646 0.505373 0.284517 0.980137 -0.057455 0.189819 0.823233 -0.567313 -0.021041 0.428439 -0.901820 0.056217 0.219067 -0.971669 0.088706 0.149181 -0.988509 -0.024407 0.134121 -0.943662 -0.302513 0.998432 0.046479 0.031184 0.858620 0.282339 -0.427851 0.691272 0.368445 -0.621604 0.605615 0.360384 -0.709474 0.618471 0.193365 -0.761646 0.557884 -0.560495 -0.612055 0.041920 -0.803823 -0.593389 -0.491133 -0.763429 -0.419482 -0.713286 -0.695699 0.085005 -0.721160 -0.612729 0.323251 -0.793706 -0.513893 0.325490 -0.933784 -0.321626 0.156857 -0.974239 0.088611 -0.207378 -0.742501 0.450705 -0.495537 -0.539200 0.598823 -0.592178 -0.443466 0.677084 -0.587278 -0.463836 0.769728 -0.438606 -0.496676 0.828322 0.259222 -0.026677 0.792887 0.608784 0.461904 0.547813 0.697528 0.585422 -0.018964 0.810507 0.547540 -0.282224 0.787750 0.633544 -0.315281 0.706555 0.832131 -0.215805 0.510869 -0.022775 0.862788 0.505052 0.115746 0.991711 -0.055779 0.170326 0.933099 -0.316727 0.227132 0.886727 -0.402649 0.387596 0.866492 -0.314582 0.847408 0.478436 0.230215 0.994188 -0.043080 0.098666 0.835264 -0.542291 -0.090856 0.411843 -0.901222 0.134845 0.178773 -0.947036 0.266764 0.108330 -0.977211 0.182546 0.085259 -0.989900 -0.113267 0.035991 -0.736761 -0.675194 -0.017473 -0.239163 -0.970822 -0.044437 0.029010 -0.998591 -0.096842 0.126541 -0.987223 -0.274824 0.059396 -0.959658 -0.812814 -0.242276 -0.529751 -0.995777 0.049895 -0.077056 -0.863766 0.362695 0.349802 -0.515853 0.187004 0.836018 -0.297226 0.019106 0.954616 -0.222668 0.102425 0.969499 -0.166134 0.395092 0.903494 -0.989178 0.073002 -0.127270 -0.707288 0.470357 -0.527738 -0.490033 0.590901 -0.640862 -0.407432 0.652999 -0.638429 -0.466897 0.751278 -0.466464 -0.489031 0.815468 0.309614 0.006737 0.821870 0.569635 0.501228 0.606084 0.617602 0.590836 -0.028883 0.806275 0.489037 -0.321876 0.810702 0.565100 -0.355038 0.744721 0.787280 -0.263972 0.557234 0.999442 0.027039 -0.019625 0.770901 0.301930 -0.560847 0.568444 0.383443 -0.727903 0.487829 0.368975 -0.791126 0.542863 0.173210 -0.821765 0.518771 -0.625743 -0.582514 0.010674 -0.827404 -0.561505 -0.507882 -0.771833 -0.382530 -0.666226 -0.709413 0.229948 -0.599550 -0.621405 0.504376 -0.667758 -0.541782 0.510462 -0.859075 -0.379694 0.343254 0.003717 -0.789035 -0.614337 -0.061806 -0.216081 -0.974417 -0.081520 0.060053 -0.994861 -0.129371 0.143263 -0.981192 -0.325224 0.024440 -0.945321 -0.845400 -0.304600 -0.438767 -0.999095 0.030078 -0.030086 -0.854804 0.370791 0.363076 -0.448189 0.129350 0.884531 -0.217259 -0.069112 0.973664 -0.157100 0.008308 0.987548 -0.121500 0.307974 0.943605 -0.003381 0.861142 0.508353 0.107123 0.982448 -0.152712 0.139623 0.899345 -0.414347 0.189024 0.853524 -0.485559 0.374681 0.856642 -0.354652 0.855945 0.478173 0.196745 0.998863 -0.023607 0.041423 0.844328 -0.518170 -0.136417 0.398264 -0.889191 0.225221 0.162523 -0.898340 0.408131 0.101225 -0.935446 0.338666 0.076616 -0.995857 0.048980 0.999889 0.008077 -0.012489 0.733214 0.303503 -0.608509 0.512726 0.383333 -0.768223 0.437815 0.362856 -0.822589 0.533887 0.126328 -0.836066 0.509827 -0.647469 -0.566445 0.006371 -0.838110 -0.545464 -0.505382 -0.784926 -0.358441 -0.594303 -0.723725 0.350751 -0.491160 -0.623695 0.608085 -0.559447 -0.557976 0.612930 -0.776163 -0.425885 0.464966 -0.998671 0.027833 -0.043381 -0.719261 0.457288 -0.523021 -0.497977 0.573148 -0.650785 -0.425070 0.632373 -0.647626 -0.518021 0.736169 -0.435557 -0.495202 0.800292 0.338095 0.011161 0.836456 0.547920 0.510323 0.638689 0.575888 0.562872 -0.070340 0.823545 0.442678 -0.348260 0.826288 0.515873 -0.375251 0.770105 0.744921 -0.291833 0.599939 -0.002174 0.833921 0.551879 0.088797 0.985471 -0.144783 0.114144 0.901456 -0.417549 0.166587 0.859416 -0.483378 0.382967 0.869829 -0.311020 0.852441 0.495123 0.167922 1.000000 0.000046 -0.000129 0.852454 -0.495019 -0.168158 0.383082 -0.869785 0.311001 0.166739 -0.859373 0.483401 0.114296 -0.901424 0.417579 0.088908 -0.985456 0.144816 -0.002204 -0.833914 -0.551890 -0.091263 -0.241692 -0.966052 -0.114253 0.046821 -0.992348 -0.164952 0.123878 -0.978491 -0.383482 -0.046261 -0.922389 -0.853285 -0.348801 -0.387611 -1.000000 -0.000071 0.000109 -0.853241 0.348679 0.387818 -0.383350 0.046318 0.922441 -0.164776 -0.123814 0.978529 -0.114071 -0.046760 0.992372 -0.091106 0.241754 0.966051 -0.998670 -0.027816 0.043424 -0.776212 0.425904 -0.464866 -0.559556 0.557990 -0.612817 -0.491278 0.623701 -0.607983 -0.594359 0.723709 -0.350690 -0.505358 0.784871 0.358595 0.006429 0.838074 0.545518 0.509896 0.647482 0.566368 0.534024 -0.126422 0.835964 0.437971 -0.362922 0.822477 0.512864 -0.383386 0.768106 0.733289 -0.303549 0.608395 0.999890 -0.008098 0.012425 0.744842 0.291887 -0.600011 0.515728 0.375327 -0.770165 0.442513 0.348335 -0.826344 0.562731 0.070398 -0.823637 0.510261 -0.638594 -0.576047 0.011124 -0.836416 -0.547983 -0.495200 -0.800321 -0.338029 -0.517896 -0.736253 0.435564 -0.424923 -0.632466 0.647632 -0.497845 -0.573236 0.650808 -0.719190 -0.457356 0.523060 -0.003458 -0.861142 -0.508352 -0.121717 -0.307851 -0.943617 -0.157337 -0.008130 -0.987511 -0.217485 0.069310 -0.973600 -0.448372 -0.129169 -0.884465 -0.854870 -0.370821 -0.362889 -0.999083 -0.030184 0.030350 -0.845303 0.304444 0.439063 -0.325041 -0.024506 0.945382 -0.129151 -0.143337 0.981211 -0.081294 -0.060117 0.994875 -0.061604 0.216064 0.974434 0.003807 0.789040 0.614330 0.076535 0.995867 -0.048909 0.101083 0.935499 -0.338561 0.162367 0.898411 -0.408037 0.398123 0.889247 -0.225249 0.844325 0.518231 0.136209 0.998849 0.023679 -0.041720 0.855926 -0.478075 -0.197065 0.374738 -0.856642 0.354594 0.189160 -0.853541 0.485475 0.139756 -0.899359 0.414273 0.107201 -0.982444 0.152685 0.999440 -0.027181 0.019504 0.787190 0.264029 -0.557333 0.564918 0.355182 -0.744791 0.488819 0.322040 -0.810769 0.590641 0.028998 -0.806413 0.501070 -0.605957 -0.617855 0.006610 -0.821762 -0.569793 -0.489082 -0.815457 -0.309562 -0.466721 -0.751400 0.466444 -0.407246 -0.653159 0.638384 -0.489868 -0.591053 0.640848 -0.707197 -0.470456 0.527773 -0.989172 -0.072922 0.127365 -0.859094 0.379837 -0.343048 -0.667838 0.541917 -0.510214 -0.599626 0.621525 -0.504139 -0.666194 0.709491 -0.229798 -0.507749 0.771793 0.382787 0.010870 0.827303 0.561651 0.518955 0.625654 0.582446 0.543060 -0.173483 0.821577 0.488026 -0.369198 0.790900 0.568609 -0.383650 0.727665 0.770985 -0.302132 0.560624 0.036250 0.736758 0.675184 0.085290 0.989890 0.113333 0.108240 0.977245 -0.182417 0.178637 0.947095 -0.266647 0.411736 0.901266 -0.134881 0.835298 0.542285 0.090578 0.994140 0.043109 -0.099128 0.847305 -0.478384 -0.230699 0.387594 -0.866553 0.314414 0.227243 -0.886801 0.402423 0.170415 -0.933152 0.316521 0.115731 -0.991719 0.055671 -0.023003 -0.862796 -0.505029 -0.166535 -0.394965 -0.903476 -0.223093 -0.102185 -0.969427 -0.297636 -0.018810 -0.954494 -0.516203 -0.186701 -0.835869 -0.863921 -0.362591 -0.349525 -0.995742 -0.049931 0.077493 -0.812570 0.242107 0.530203 -0.274484 -0.059559 0.959745 -0.096464 -0.126731 0.987235 -0.044046 -0.029185 0.998603 -0.017100 0.239074 0.970851 -0.974213 -0.088391 0.207596 -0.933737 0.321942 -0.156486 -0.793705 0.514186 -0.325031 -0.721139 0.612995 -0.322794 -0.713119 0.695911 -0.084674 -0.490795 0.763453 0.419833 0.042375 0.803643 0.593601 0.558287 0.560212 0.611946 0.618817 -0.193783 0.761258 0.605914 -0.360765 0.709026 0.691495 -0.368822 0.621132 0.858709 -0.282732 0.427412 0.998408 -0.046828 -0.031449 0.832034 0.215726 -0.511059 0.633321 0.315395 -0.706704 0.547249 0.282399 -0.787889 0.585126 0.019047 -0.810719 0.461540 -0.547705 -0.697854 -0.027012 -0.792700 -0.609013 -0.496843 -0.828243 -0.259153 -0.463621 -0.769848 0.438622 -0.443225 -0.677264 0.587252 -0.538998 -0.598984 0.592199 -0.742400 -0.450751 0.495648 -0.084537 -0.826236 -0.556945 -0.240648 -0.466875 -0.850950 -0.322143 -0.206109 -0.923982 -0.410235 -0.109650 -0.905364 -0.598411 -0.196847 -0.776631 -0.890344 -0.316993 -0.326808 -0.985178 -0.055060 0.162457 -0.731301 0.167525 0.661161 -0.219305 -0.045273 0.974605 -0.046345 -0.062977 0.996938 0.020219 0.053923 0.998340 0.063949 0.306636 0.949676 0.111483 0.690333 0.714851 0.134387 0.943615 0.302540 0.149245 0.988496 0.024526 0.219037 0.971687 -0.088587 0.428441 0.901819 -0.056230 0.823314 0.567210 0.020662 0.980001 0.057441 -0.190522 0.814379 -0.505443 -0.285155 0.417178 -0.896142 0.151302 0.264745 -0.942919 0.202024 0.182670 -0.978328 0.097501 0.084319 -0.984818 -0.151736 0.983938 -0.043459 -0.173138 0.842777 0.164190 -0.512610 0.670532 0.266016 -0.692547 0.564815 0.247271 -0.787300 0.525806 0.043810 -0.849476 0.367277 -0.455674 -0.810845 -0.110149 -0.747278 -0.655318 -0.528004 -0.826091 -0.196942 -0.518792 -0.772982 0.365176 -0.531216 -0.677445 0.508801 -0.631123 -0.568912 0.527278 -0.796802 -0.385872 0.464984 -0.951839 -0.072209 0.297973 -0.962353 0.261046 0.075706 -0.881781 0.467539 -0.062205 -0.805693 0.588053 -0.071083 -0.727020 0.679410 0.099218 -0.444189 0.752525 0.486212 0.117892 0.763203 0.635313 0.647268 0.456030 0.610803 0.767783 -0.169771 0.617808 0.786867 -0.318413 0.528634 0.858848 -0.319294 0.400538 0.955918 -0.230827 0.181491 0.225352 0.651725 0.724204 0.227235 0.863244 0.450748 0.228643 0.948989 0.217122 0.281323 0.956813 0.073250 0.451099 0.892467 0.003521 0.799356 0.596355 -0.073425 0.940123 0.073551 -0.332806 0.739928 -0.526692 -0.418452 0.415384 -0.897230 -0.149784 0.250908 -0.960470 -0.120593 0.127600 -0.967254 -0.219403 -0.018163 -0.911984 -0.409823 -0.199814 -0.738034 -0.644500 -0.356615 -0.474102 -0.805018 -0.459122 -0.258505 -0.849931 -0.554958 -0.149098 -0.818408 -0.710515 -0.165444 -0.683957 -0.934835 -0.249784 -0.252371 -0.948846 -0.059723 0.310038 -0.592295 0.105323 0.798808 -0.125679 0.009268 0.992028 0.056083 0.032402 0.997900 0.140087 0.158762 0.977328 0.193132 0.376557 0.906038 -0.901407 -0.067533 0.427674 -0.926666 0.201546 0.317285 -0.885567 0.403053 0.230910 -0.813302 0.539248 0.218518 -0.692528 0.640769 0.331392 -0.352906 0.713269 0.605561 0.248769 0.698898 0.670564 0.773136 0.383397 0.505240 0.927886 -0.097275 0.359951 0.945915 -0.232343 0.226410 0.971912 -0.224471 0.070708 0.981548 -0.132517 -0.137848 0.920146 0.023446 -0.390872 0.771067 0.182876 -0.609928 0.605286 0.275515 -0.746807 0.475331 0.275072 -0.835701 0.378823 0.125325 -0.916944 0.194342 -0.331651 -0.923168 -0.250158 -0.689204 -0.680014 -0.585124 -0.796414 -0.152822 -0.583006 -0.751648 0.308430 -0.597367 -0.653309 0.465123 -0.679221 -0.524202 0.513684 -0.799474 -0.331743 0.500787 -0.359104 -0.606652 -0.709238 -0.521836 -0.381251 -0.763108 -0.632941 -0.194423 -0.749390 -0.724483 -0.087868 -0.683669 -0.844689 -0.090608 -0.527532 -0.973396 -0.216165 -0.075976 -0.843883 -0.116906 0.523637 -0.394081 0.030181 0.918580 0.053882 0.008667 0.998510 0.241751 0.050300 0.969034 0.324437 0.175998 0.929390 0.359313 0.373409 0.855254 0.355659 0.606389 0.711195 0.322174 0.797697 0.509787 0.293147 0.902877 0.314449 0.311834 0.937037 0.157229 0.435416 0.900015 0.019631 0.737571 0.648326 -0.188843 0.837749 0.126730 -0.531145 0.601615 -0.455282 -0.656337 0.330772 -0.814481 -0.476667 0.161775 -0.889464 -0.427414 0.010802 -0.875739 -0.482664 -0.164788 -0.786534 -0.595155 0.758843 0.200337 -0.619695 0.549077 0.364991 -0.751862 0.346934 0.456658 -0.819207 0.190457 0.464061 -0.865086 0.073034 0.337038 -0.938654 -0.062753 -0.185660 -0.980608 -0.394362 -0.637142 -0.662215 -0.594750 -0.796308 -0.110301 -0.518053 -0.796205 0.312535 -0.494073 -0.721426 0.485218 -0.558566 -0.602221 0.570381 -0.675575 -0.413389 0.610498 -0.784241 -0.153262 0.601230 -0.828191 0.111126 0.549319 -0.808890 0.315517 0.496131 -0.744300 0.456950 0.487046 -0.604635 0.557111 0.569249 -0.211556 0.620759 0.754918 0.401286 0.630407 0.664497 0.856128 0.413554 0.309867 0.998828 0.011936 0.046895 0.986905 -0.120117 -0.107659 0.961217 -0.096684 -0.258292 0.899960 0.021553 -0.435440 0.472567 0.552119 0.686910 0.345572 0.777344 0.525657 0.238233 0.902568 0.358631 0.198121 0.957255 0.210741 0.274549 0.960427 0.046944 0.567919 0.775521 -0.275747 0.621253 0.306999 -0.720969 0.388208 -0.234890 -0.891135 0.219029 -0.658531 -0.719975 0.092460 -0.776154 -0.623727 -0.063198 -0.774943 -0.628864 -0.280974 -0.677768 -0.679473 -0.536286 -0.468383 -0.702151 -0.727943 -0.222066 -0.648680 -0.830436 -0.041374 -0.555576 -0.893919 0.042733 -0.446187 -0.961174 -0.012425 -0.275665 -0.934818 -0.309314 0.174469 -0.629017 -0.303621 0.715648 -0.126769 -0.141461 0.981793 0.324157 -0.119516 0.938423 0.504990 -0.070678 0.860226 0.564647 0.061736 0.823021 0.554038 0.280443 0.783833 -0.549679 -0.389813 0.738849 -0.650553 -0.091765 0.753897 -0.670769 0.131577 0.729902 -0.627415 0.275598 0.728283 -0.482449 0.367461 0.795120 -0.046125 0.445699 0.893994 0.494389 0.590871 0.637536 0.802711 0.578748 0.143894 0.947456 0.216394 -0.235585 0.915728 0.055301 -0.397974 0.847901 0.096174 -0.521358 0.716666 0.260720 -0.646850 0.460173 0.496897 -0.735754 0.140972 0.670950 -0.727979 -0.102918 0.731594 -0.673927 -0.261338 0.715994 -0.647345 -0.361058 0.593869 -0.718997 -0.320296 -0.064532 -0.945117 -0.474058 -0.582922 -0.659903 -0.496980 -0.856459 -0.139605 -0.279216 -0.932396 0.229513 -0.188561 -0.898944 0.395404 -0.235158 -0.820864 0.520464 -0.379794 -0.662038 0.646114 -0.675369 -0.395275 -0.622603 -0.894020 -0.169681 -0.414653 -0.971246 -0.023883 -0.236875 -0.994637 0.015409 -0.102275 -0.992291 -0.118290 0.036964 -0.749825 -0.569214 0.337280 -0.306431 -0.593702 0.744055 0.198353 -0.372177 0.906720 0.629229 -0.258171 0.733088 0.782444 -0.179258 0.596362 0.810661 -0.040853 0.584089 0.749511 0.188195 0.634677 0.561185 0.492141 0.665484 0.294774 0.734473 0.611275 0.091600 0.851720 0.515928 -0.003383 0.911985 0.410210 0.034329 0.967541 0.250371 0.306656 0.931377 -0.196210 0.279860 0.606386 -0.744295 0.078448 0.110708 -0.990752 0.091403 -0.408064 -0.908366 0.060821 -0.590049 -0.805073 -0.077281 -0.630640 -0.772218 -0.337156 -0.575999 -0.744682 0.089117 0.774444 -0.626334 -0.271393 0.852906 -0.445980 -0.489052 0.820141 -0.296978 -0.612914 0.753678 -0.237291 -0.692428 0.635031 -0.342462 -0.560909 0.068631 -0.825028 -0.551460 -0.493893 -0.672281 -0.364583 -0.887617 -0.281453 -0.003755 -0.999417 -0.033948 0.146635 -0.984808 0.093017 0.135533 -0.961479 0.239141 0.005687 -0.892433 0.451144 -0.197590 -0.695514 0.690809 -0.365750 -0.417324 0.831906 -0.442452 -0.194680 0.875406 -0.429233 -0.052807 0.901649 -0.282215 0.039319 0.958545 0.162488 0.189691 0.968305 0.539719 0.541609 0.644487 0.639307 0.756429 0.138209 0.772000 0.504789 -0.386270 0.742324 0.326762 -0.584963 0.639428 0.382851 -0.666751 0.440559 0.562792 -0.699409 0.637506 0.435087 0.635834 0.301173 0.604753 0.737271 0.054243 0.676271 0.734653 -0.070610 0.731454 0.678226 -0.075257 0.840555 0.536474 0.072467 0.996721 0.035994 -0.075733 0.834688 -0.545491 -0.250745 0.392846 -0.884759 -0.089218 -0.117540 -0.989052 -0.040236 -0.322066 -0.945862 -0.151701 -0.405823 -0.901274 -0.402321 -0.437424 -0.804238 -0.729876 -0.398913 -0.555112 -0.925210 -0.300406 -0.231823 -0.973333 -0.229396 -0.000004 -0.961471 -0.237339 0.138725 -0.887170 -0.408884 0.213877 -0.488174 -0.822242 0.292582 0.039564 -0.823631 0.565744 0.516618 -0.526849 0.674934 0.866373 -0.266784 0.422166 0.955892 -0.123664 0.266417 0.955417 0.012221 0.295006 0.874067 0.198908 0.443218 0.147608 -0.880247 0.450974 -0.031911 -0.703526 0.709953 -0.139814 -0.526138 0.838827 -0.146915 -0.397663 0.905693 -0.002980 -0.290482 0.956876 0.398167 -0.036983 0.916567 0.594248 0.470351 0.652411 0.518450 0.825535 0.222938 0.555287 0.736844 -0.385638 0.498341 0.622283 -0.603672 0.367941 0.675265 -0.639247 0.138105 0.804740 -0.577339 -0.212922 0.899321 -0.381949 -0.521116 0.844184 -0.125663 -0.684935 0.727451 0.040973 -0.777438 0.622420 0.090469 -0.855832 0.514408 -0.054190 -0.776865 0.138551 -0.614235 -0.628671 -0.427232 -0.649805 -0.265820 -0.848646 -0.457319 0.180724 -0.920109 -0.347475 0.357610 -0.897288 -0.258822 0.383780 -0.916201 -0.115279 0.309949 -0.942412 0.125660 -0.733282 -0.416266 -0.537606 -0.868513 -0.457658 -0.190354 -0.882821 -0.466523 0.054626 -0.840046 -0.510907 0.182473 -0.713209 -0.673467 0.194358 -0.254074 -0.960092 0.116922 0.309985 -0.905458 0.289923 0.749031 -0.539143 0.385067 0.979511 -0.145149 0.139604 0.998521 0.046191 0.028664 0.980879 0.166955 0.100008 0.907787 0.288263 0.304675 0.695795 0.409500 0.590067 0.380323 0.470144 0.796441 0.134258 0.485539 0.863844 -0.007423 0.527183 0.849719 -0.060972 0.670094 0.739768 -0.074028 0.955624 0.285135 -0.331787 0.904644 -0.267462 -0.492614 0.525259 -0.693855 -0.273238 0.106349 -0.956050 -0.195024 -0.082475 -0.977325 -0.279421 -0.198938 -0.939333 -0.483118 -0.312042 -0.818063 -0.420508 0.898632 -0.125030 -0.659128 0.739569 0.136341 -0.773976 0.564573 0.286737 -0.842785 0.436157 0.315405 -0.926932 0.345763 0.145755 -0.896268 0.109557 -0.429768 -0.668520 -0.391398 -0.632367 -0.197942 -0.754976 -0.625164 0.273451 -0.743301 -0.610514 0.454178 -0.706038 -0.543354 0.511245 -0.752590 -0.415014 0.496912 -0.847311 -0.187464 0.403272 -0.902511 0.151148 0.259063 -0.844507 0.468716 0.153023 -0.735642 0.659860 0.139317 -0.631377 0.762859 0.273369 -0.505903 0.818127 0.599886 -0.163063 0.783292 0.645109 0.418086 0.639561 0.437146 0.844066 0.310575 0.349917 0.889886 -0.292678 0.253942 0.834599 -0.488833 0.109723 0.866352 -0.487232 -0.115988 0.922348 -0.368539 0.723609 0.413130 0.552914 0.454824 0.367430 0.811252 0.227391 0.321150 0.919323 0.079886 0.339031 0.937377 -0.014233 0.496704 0.867803 -0.158484 0.852626 0.497907 -0.500307 0.865848 0.000653 -0.659648 0.563664 -0.497140 -0.423404 0.261464 -0.867391 -0.334035 0.101316 -0.937100 -0.392238 -0.035480 -0.919179 -0.545852 -0.209659 -0.811227 -0.719559 -0.420180 -0.552887 -0.789828 -0.570103 -0.226172 -0.765663 -0.643210 0.006356 -0.695017 -0.710327 0.111297 -0.535595 -0.842084 0.063505 -0.062626 -0.991367 -0.115191 0.500462 -0.865759 -0.000499 0.890266 -0.440777 0.114641 0.997019 0.043818 -0.063512 0.962362 0.247936 -0.111295 0.939488 0.342524 -0.006308 0.888323 0.399612 0.226259 0.580063 -0.800400 -0.151283 0.485513 -0.853976 0.187089 0.396502 -0.819214 0.414337 0.384827 -0.746698 0.542541 0.507461 -0.608881 0.609710 0.753204 -0.206210 0.624628 0.673114 0.383083 0.632586 0.352708 0.830791 0.430562 0.163216 0.975796 -0.145543 0.042892 0.948126 -0.314988 -0.102530 0.952621 -0.286359 -0.311199 0.940527 -0.136253 -0.568097 0.813438 0.124833 -0.741010 0.561366 0.368473 -0.805378 0.337493 0.487304 -0.849948 0.196475 0.488862 -0.945798 0.141050 0.292526 -0.949728 0.042969 -0.310113 -0.684615 -0.349540 -0.639629 -0.158653 -0.600335 -0.783854 0.301245 -0.488843 -0.818708 0.477007 -0.435499 -0.763417 0.560577 -0.499693 -0.660349 0.601934 -0.646297 -0.469017 -0.702540 -0.397849 -0.590046 -0.703028 -0.642539 -0.304787 -0.634150 -0.766680 -0.100280 -0.538228 -0.842300 -0.029011 -0.363116 -0.921173 -0.139951 0.093170 -0.917787 -0.385987 0.629884 -0.720086 -0.291070 0.958711 -0.259023 -0.117389 0.939574 0.282061 -0.194016 0.861900 0.473280 -0.182031 0.844811 0.532315 -0.054181 0.830126 0.523949 0.190704 0.727034 0.426986 0.537684 0.512193 0.261965 0.817944 0.312696 0.141754 0.939216 0.169735 0.126757 0.977304 0.045137 0.289013 0.956260 -0.208682 0.688281 0.694782 -0.618036 0.738709 0.268963 -0.791082 0.541726 -0.284117 -0.550375 0.388570 -0.738986 -0.453536 0.270948 -0.849054 -0.488238 0.127348 -0.863369 -0.597701 -0.093750 -0.796219 -0.672512 0.634070 0.381684 -0.766143 0.282483 0.577260 -0.768774 0.018178 0.639262 -0.787993 -0.121461 0.603584 -0.915816 -0.113220 0.385307 -0.974234 -0.036767 -0.222520 -0.704578 -0.279319 -0.652342 -0.167338 -0.362356 -0.916895 0.252427 -0.141565 -0.957204 0.417289 -0.070538 -0.906032 0.525213 -0.141152 -0.839183 0.625144 -0.323698 -0.710221 0.688571 -0.567774 -0.451113 0.661366 -0.739386 -0.126108 0.602007 -0.790250 0.114419 0.598853 -0.758240 0.257774 0.706997 -0.616542 0.346457 0.868220 -0.193992 0.456684 0.684285 0.330615 0.649960 0.267996 0.741547 0.615050 -0.018613 0.998339 0.054530 -0.151294 0.984395 -0.089872 -0.288246 0.956699 -0.040510 -0.470867 0.873202 0.125710 0.710207 0.432693 0.555323 0.580509 0.129290 0.803924 0.428282 -0.072320 0.900747 0.300171 -0.127115 0.945378 0.147313 0.017675 0.988932 -0.214589 0.412144 0.885488 -0.685015 0.481295 0.546909 -0.899654 0.435203 -0.034941 -0.691014 0.486029 -0.535048 -0.599164 0.427646 -0.676847 -0.613744 0.291901 -0.733561 -0.674972 0.042059 -0.736643 -0.695608 -0.334568 -0.635762 -0.608589 -0.657870 -0.443651 -0.487132 -0.821704 -0.295811 -0.369543 -0.889935 -0.267309 -0.201064 -0.883620 -0.422835 0.198601 -0.709727 -0.675903 0.693952 -0.444246 -0.566636 0.956173 0.012805 -0.292521 0.797080 0.565135 -0.212804 0.685197 0.715257 -0.137522 0.684257 0.729241 0.001114 0.721974 0.651643 0.232628 0.701211 -0.176231 -0.690830 0.770016 -0.450717 -0.451586 0.764984 -0.597600 -0.240153 0.779758 -0.618930 -0.094356 0.867681 -0.496052 0.032589 0.951256 -0.127692 0.280725 0.703495 0.229893 0.672491 0.220857 0.518758 0.825901 -0.204769 0.916779 0.342908 -0.347035 0.907080 0.238271 -0.466240 0.833044 0.297756 -0.603164 0.661164 0.446157 -0.715510 0.310104 0.626004 -0.708068 -0.100439 0.698965 -0.651537 -0.363124 0.666064 -0.654339 -0.480422 0.583983 -0.823210 -0.417001 0.385274 -0.974575 -0.176515 -0.138009 -0.738938 -0.196276 -0.644551 -0.245994 -0.044464 -0.968251 0.106264 0.265456 -0.958249 0.259697 0.346732 -0.901296 0.389440 0.287092 -0.875165 0.544240 0.108926 -0.831828 -0.706733 -0.239980 -0.665535 -0.537005 -0.555004 -0.635292 -0.368875 -0.722242 -0.585062 -0.234822 -0.766795 -0.597397 -0.090097 -0.673328 -0.733833 0.223479 -0.356269 -0.907265 0.667378 -0.029278 -0.744143 0.867663 0.365882 -0.336587 0.598019 0.800710 -0.035171 0.483034 0.869377 0.104225 0.505347 0.829269 0.238614 0.593182 0.689344 0.415861 0.679694 0.387213 0.622963 0.667772 0.003934 0.744356 0.585610 -0.248682 0.771504 0.481586 -0.348164 0.804274 0.308523 -0.283822 0.907887 -0.134582 -0.014257 0.990800 -0.664620 0.058636 0.744877 -0.959951 0.199166 0.197047 -0.855577 0.453952 -0.248830 -0.788869 0.459020 -0.408639 -0.784160 0.346709 -0.514671 -0.783963 0.112093 -0.610603 -0.660845 -0.150073 0.735365 -0.584608 -0.490552 0.646214 -0.507557 -0.686734 0.520368 -0.505950 -0.765935 0.396684 -0.661058 -0.712843 0.234215 -0.902057 -0.406695 -0.144540 -0.758781 -0.132452 -0.637737 -0.363300 0.263766 -0.893555 -0.077592 0.602470 -0.794361 0.074582 0.682102 -0.727444 0.221237 0.647576 -0.729177 0.404849 0.518175 -0.753387 0.612634 0.281507 -0.738535 0.763248 -0.001674 -0.646104 0.828385 -0.206089 -0.520870 0.872730 -0.285372 -0.396112 0.947091 -0.223587 -0.230278 0.990242 0.002795 0.139333 0.741898 0.118534 0.659952 0.215761 0.244242 0.945406 -0.334623 0.608862 0.719245 -0.489894 0.583366 0.647834 -0.582418 0.454153 0.674192 -0.651789 0.213057 0.727858 0.673370 0.229963 0.702631 0.727385 -0.095589 0.679539 0.702954 -0.332771 0.628585 0.626309 -0.468269 0.623266 0.461073 -0.519275 0.719559 0.009503 -0.454635 0.890627 -0.576132 -0.385907 0.720519 -0.955498 -0.104670 0.275805 -0.969157 0.242078 -0.046189 -0.928337 0.306787 -0.209932 -0.901019 0.244860 -0.358063 -0.846063 0.089447 -0.525525 -0.714140 -0.132993 -0.687253 -0.519234 -0.339145 -0.784459 -0.334971 -0.457411 -0.823753 -0.190444 -0.471780 -0.860903 -0.057840 -0.339540 -0.938812 0.186245 0.040329 -0.981675 0.577511 0.394314 -0.714840 0.735311 0.655194 -0.173317 0.491069 0.825792 0.277343 0.409430 0.794868 0.447830 0.450465 0.697764 0.556962 0.555722 0.518773 0.649652 0.525341 0.602723 -0.600619 0.696050 0.378593 -0.610067 0.800873 0.183029 -0.570177 0.871773 0.067694 -0.485212 0.948517 0.051046 -0.312586 0.986948 0.117091 0.110561 0.748840 0.022276 0.662377 0.191567 -0.039300 0.980692 -0.329046 0.104568 0.938506 -0.497502 0.066390 0.864919 -0.569288 -0.072609 0.818926 -0.591084 -0.293199 0.751435 -0.553552 -0.557031 0.619110 -0.469313 -0.768691 0.434578 -0.397431 -0.880878 0.257106 -0.389846 -0.914733 0.106224 -0.509942 -0.858844 -0.048437 -0.785869 -0.534484 -0.311026 -0.746314 -0.031593 -0.664844 -0.431687 0.494405 -0.754460 -0.180058 0.802774 -0.568447 -0.023370 0.873584 -0.486112 0.131572 0.858737 -0.495237 0.318377 0.773123 -0.548558 -0.702538 -0.004184 -0.711634 -0.502402 -0.123604 -0.855754 -0.313941 -0.191919 -0.929843 -0.163744 -0.183077 -0.969366 -0.033782 -0.041269 -0.998577 0.171415 0.357376 -0.918095 0.523505 0.673034 -0.522463 0.674117 0.734579 0.077209 0.500712 0.685280 0.528846 0.438002 0.582374 0.684832 0.484391 0.449842 0.750338 0.590574 0.260389 0.763820 0.704450 0.007051 0.709719 0.763244 -0.250938 0.595389 0.752873 -0.447500 0.482623 0.689338 -0.585097 0.427170 0.539792 -0.694064 0.476339 0.093160 -0.749283 0.655665 -0.528668 -0.662845 0.530233 -0.930290 -0.314751 0.188394 -0.997153 0.072825 -0.019542 -0.967445 0.198448 -0.157065 -0.928462 0.197729 -0.314421 -0.851726 0.120228 -0.510007 -0.481099 -0.785028 0.390224 -0.376750 -0.916134 0.136963 -0.292203 -0.953656 -0.071815 -0.272284 -0.934901 -0.227644 -0.380102 -0.851506 -0.361193 -0.718477 -0.477068 -0.506159 -0.729335 0.134988 -0.670708 -0.440838 0.662994 -0.605063 -0.208202 0.920511 -0.330622 -0.059841 0.974201 -0.217606 0.094318 0.968609 -0.230003 0.289442 0.903360 -0.316487 0.509760 0.746862 -0.427016 0.687375 0.526538 -0.500274 0.793729 0.326317 -0.513334 0.864514 0.190976 -0.464914 0.942475 0.129336 -0.308242 0.982219 0.108411 0.153277 0.721725 -0.128715 0.680107 0.189512 -0.334941 0.922984 -0.298486 -0.265937 0.916615 -0.476274 -0.274542 0.835338 -0.541660 -0.386685 0.746378 -0.544466 -0.576345 0.609412 0.738750 -0.196523 0.644692 0.798688 -0.440606 0.409833 0.773765 -0.594344 0.219186 0.706256 -0.697675 0.120218 0.569171 -0.808541 0.149351 0.085871 -0.904477 0.417789 -0.533842 -0.777703 0.331951 -0.916169 -0.394106 0.072911 -0.998448 0.055572 -0.003600 -0.969279 0.234820 -0.073198 -0.936122 0.276657 -0.217110 -0.861044 0.235187 -0.450877 -0.676729 0.131258 -0.724437 -0.422221 0.021753 -0.906232 -0.207116 -0.041097 -0.977453 -0.055724 -0.031503 -0.997949 0.055196 0.114234 -0.991919 0.205304 0.566174 -0.798309 0.526399 0.792050 -0.309129 0.683918 0.684240 0.253125 0.498590 0.531724 0.684600 0.406494 0.405088 0.818942 0.453213 0.267423 0.850343 0.588578 0.070994 0.805317 0.538859 0.788110 -0.297513 0.732758 0.497142 -0.464666 0.808308 0.262296 -0.527104 0.852299 0.121575 -0.508729 0.928834 0.062989 -0.365103 0.979372 0.043985 0.197222 0.702115 -0.278883 0.655179 0.210700 -0.546530 0.810500 -0.301185 -0.433802 0.849178 -0.496770 -0.365802 0.787025 -0.565882 -0.447863 0.692240 -0.563960 -0.647731 0.512243 -0.454889 -0.873648 0.172672 -0.278604 -0.942974 -0.182152 -0.153358 -0.903014 -0.401306 -0.118065 -0.840104 -0.529420 -0.237200 -0.749094 -0.618541 -0.718528 -0.331789 -0.611255 -0.719704 0.280296 -0.635185 -0.429277 0.761463 -0.485691 -0.224480 0.969476 -0.098612 -0.106014 0.991770 0.071780 0.036436 0.997354 0.062906 0.255597 0.963862 -0.075102 -0.653318 0.249089 -0.714934 -0.297251 0.098546 -0.949700 -0.056616 0.010123 -0.998345 0.077861 0.009315 -0.996921 0.149028 0.167874 -0.974479 0.220760 0.717531 -0.660616 0.540426 0.825698 -0.161750 0.719810 0.612162 0.327310 0.469734 0.419088 0.776991 0.300032 0.299666 0.905638 0.339432 0.175170 0.924176 0.524407 -0.025685 0.851080 0.757549 -0.340329 0.557042 0.810586 -0.565643 0.151653 0.755839 -0.647418 -0.097762 0.684131 -0.700724 -0.202364 0.567326 -0.809414 -0.151624 0.030315 -0.958183 0.284546 -0.539854 -0.820073 0.189838 -0.902925 -0.429282 -0.021073 -0.995219 0.079895 0.056169 -0.951014 0.296156 0.088677 -0.930651 0.365090 -0.024431 -0.884282 0.355690 -0.302539 -0.458988 -0.887897 0.031140 -0.184800 -0.884740 -0.427883 -0.026556 -0.782867 -0.621622 0.009290 -0.704655 -0.709490 -0.141762 -0.632266 -0.761672 -0.764292 -0.202873 -0.612128 -0.717058 0.365644 -0.593408 -0.415559 0.807084 -0.419435 -0.245834 0.965575 0.085029 -0.170035 0.930916 0.323239 -0.048158 0.944321 0.325481 0.188400 0.969485 0.156858 0.563902 0.799386 -0.207354 0.761606 0.417648 -0.495507 0.788219 0.167519 -0.592156 0.808114 0.045473 -0.587268 0.898511 0.016769 -0.438630 0.965684 0.015916 0.259233 0.699961 -0.373393 0.608795 0.243435 -0.673971 0.697497 -0.309202 -0.497493 0.810490 -0.518242 -0.333025 0.787731 -0.589865 -0.390984 0.706535 -0.603005 -0.612719 0.510843 0.758498 -0.411760 0.505108 0.800920 -0.596173 -0.055725 0.722886 -0.614127 -0.316676 0.654319 -0.640147 -0.402589 0.556515 -0.769018 -0.314489 -0.009435 -0.973121 0.230103 -0.534484 -0.839408 0.098590 -0.887332 -0.452092 -0.090857 -0.986393 0.094030 0.134857 -0.909533 0.318747 0.266739 -0.900429 0.394855 0.182530 -0.899862 0.421214 -0.113253 -0.656015 0.337348 -0.675160 -0.198349 0.134813 -0.970816 0.047386 0.024031 -0.998587 0.158054 0.020621 -0.987215 0.188894 0.208334 -0.959644 0.196625 0.825139 -0.529608 0.541159 0.837390 -0.076968 0.746039 0.566600 0.349844 0.419810 0.353143 0.836092 0.165052 0.247780 0.954654 0.199938 0.141558 0.969529 0.425132 -0.053746 0.903534 0.557860 0.820119 -0.127265 0.761024 0.377346 -0.527685 0.756803 0.128941 -0.640799 0.769290 0.026355 -0.638357 0.884121 0.028689 -0.466376 0.950744 0.015697 0.309578 0.708350 -0.416827 0.569645 0.274195 -0.737138 0.617612 -0.320444 -0.497310 0.806225 -0.523302 -0.262632 0.810666 -0.590061 -0.311897 0.744680 -0.622289 -0.549820 0.557185 -0.476326 -0.879048 -0.019679 -0.123936 -0.818557 -0.560896 0.047912 -0.683976 -0.727929 0.075709 -0.606932 -0.791140 -0.121329 -0.556725 -0.821789 -0.801326 -0.136336 -0.582486 -0.721857 0.404492 -0.561523 -0.414416 0.825766 -0.382583 -0.281200 0.931700 0.229916 -0.238353 0.829935 0.504377 -0.135290 0.849195 0.510456 0.100762 0.933828 0.343237 -0.685138 0.391328 -0.614368 -0.156271 0.161684 -0.974391 0.092695 0.040732 -0.994861 0.188688 0.040596 -0.981198 0.183769 0.269581 -0.945281 0.159063 0.884364 -0.438861 0.525697 0.850141 -0.030048 0.748557 0.554806 0.363115 0.336150 0.323401 0.884542 0.048783 0.222641 0.973679 0.085726 0.131829 0.987559 0.327414 -0.048832 0.943618 0.747437 -0.427701 0.508340 0.797241 -0.583987 -0.152857 0.709005 -0.570516 -0.414517 0.644629 -0.590344 -0.485744 0.554551 -0.752694 -0.354860 -0.013963 -0.980332 0.196861 -0.519891 -0.853227 0.041448 -0.870925 -0.472102 -0.136418 -0.969184 0.099723 0.225251 -0.859239 0.308421 0.408147 -0.860734 0.380055 0.338666 -0.900745 0.431581 0.048941 -0.493047 -0.869913 -0.012520 -0.104034 -0.786690 -0.608520 0.075355 -0.635656 -0.768286 0.095102 -0.560512 -0.822667 -0.157723 -0.525392 -0.836114 -0.815710 -0.117633 -0.566374 -0.729036 0.413694 -0.545311 -0.427033 0.830225 -0.358285 -0.329500 0.876508 0.350946 -0.294452 0.737071 0.608297 -0.203421 0.763327 0.613149 0.019295 0.884994 0.465203 0.523495 0.850928 -0.043291 0.755617 0.394185 -0.523126 0.745248 0.144648 -0.650909 0.760086 0.051932 -0.647744 0.896518 0.080550 -0.435623 0.940706 0.028613 0.338013 0.718856 -0.428004 0.547776 0.297957 -0.761375 0.575786 -0.342303 -0.452326 0.823547 -0.522845 -0.209384 0.826312 -0.582835 -0.259295 0.770110 -0.625151 -0.499325 0.599885 0.723225 -0.415143 0.551907 0.809002 -0.569692 -0.144799 0.723572 -0.549585 -0.417612 0.660953 -0.573938 -0.483464 0.561809 -0.766536 -0.311117 0.002446 -0.985795 0.167935 -0.500024 -0.866011 -0.000251 -0.854859 -0.490756 -0.168450 -0.944760 0.103263 0.311072 -0.827478 0.285379 0.483569 -0.837711 0.351786 0.417717 -0.897848 0.415786 0.144884 -0.721028 0.418889 -0.551952 -0.163659 0.199905 -0.966051 0.097655 0.075599 -0.992345 0.189735 0.081017 -0.978487 0.151697 0.355341 -0.922345 0.124645 0.913340 -0.387652 0.499926 0.866068 0.000165 0.728451 0.564607 0.388045 0.231994 0.308825 0.922391 -0.024582 0.204573 0.978543 0.016727 0.122098 0.992377 0.255008 -0.042065 0.966023 0.475302 0.878749 0.043456 0.756998 0.459193 -0.464862 0.763035 0.205522 -0.612811 0.785794 0.113539 -0.607978 0.923945 0.152803 -0.350680 0.932386 0.045149 0.358633 0.722532 -0.424664 0.545535 0.305718 -0.765357 0.566361 -0.376554 -0.399257 0.835943 -0.533329 -0.197821 0.822452 -0.588500 -0.252455 0.768072 -0.629579 -0.483269 0.608343 -0.507016 -0.861848 0.012388 -0.119697 -0.790987 -0.600010 0.067135 -0.634304 -0.770163 0.080375 -0.557399 -0.826345 -0.220415 -0.522511 -0.823650 -0.808151 -0.122540 -0.576087 -0.729871 0.408636 -0.548001 -0.445432 0.829054 -0.338023 -0.378630 0.816651 0.435569 -0.335253 0.684230 0.647638 -0.247502 0.717755 0.650823 -0.036471 0.851494 0.523094 -0.744003 0.433641 -0.508346 -0.205704 0.259367 -0.943618 0.071667 0.140330 -0.987508 0.168804 0.153695 -0.973593 0.112378 0.452900 -0.884451 0.106387 0.925741 -0.362885 0.473476 0.880283 0.030370 0.686338 0.579773 0.439095 0.141297 0.293730 0.945388 -0.059560 0.183514 0.981211 -0.011421 0.100450 0.994877 0.217905 -0.054717 0.974435 0.681384 -0.397886 0.614331 0.824133 -0.564283 -0.048897 0.759587 -0.555348 -0.338550 0.696826 -0.589868 -0.408031 0.570994 -0.789446 -0.225255 0.026545 -0.990324 0.136209 -0.478993 -0.876826 -0.041739 -0.842023 -0.502145 -0.197099 -0.929237 0.103874 0.354584 -0.833750 0.263024 0.485468 -0.848720 0.328716 0.414270 -0.904387 0.398459 0.152691 -0.523337 -0.851903 0.019485 -0.164995 -0.813718 -0.557351 0.025096 -0.666813 -0.744802 0.034437 -0.584342 -0.810776 -0.270295 -0.525974 -0.806407 -0.775305 -0.130895 -0.617874 -0.714934 0.405215 -0.569798 -0.461612 0.831328 -0.309529 -0.417329 0.779921 0.466434 -0.361996 0.679293 0.638374 -0.266892 0.719782 0.640845 -0.053778 0.847672 0.527788 0.431481 0.893077 0.127429 0.758543 0.554057 -0.342977 0.803276 0.307383 -0.510160 0.838106 0.208500 -0.504089 0.947563 0.222161 -0.229714 0.922247 0.053760 0.382845 0.710979 -0.423131 0.561666 0.282293 -0.762301 0.582415 -0.421844 -0.383521 0.821559 -0.563800 -0.237985 0.790881 -0.616605 -0.300541 0.727649 -0.647210 -0.516561 0.560611 0.619971 -0.399790 0.675132 0.814627 -0.568815 0.113283 0.792184 -0.582376 -0.182437 0.730864 -0.628275 -0.266661 0.574636 -0.807207 -0.134946 0.052009 -0.994537 0.090509 -0.459756 -0.882496 -0.099121 -0.837983 -0.494561 -0.230637 -0.944297 0.097557 0.314302 -0.881645 0.246592 0.402361 -0.893356 0.318999 0.316472 -0.916717 0.395645 0.055623 -0.735675 0.451315 -0.505071 -0.258742 0.341676 -0.903499 0.023095 0.244241 -0.969440 0.132571 0.267086 -0.954510 0.096440 0.540335 -0.835905 0.117947 0.929483 -0.349499 0.454673 0.887283 0.077476 0.616075 0.582619 0.530101 0.085670 0.267463 0.959752 -0.061535 0.146895 0.987236 -0.003249 0.052735 0.998603 0.215624 -0.104735 0.970843 0.410598 0.887855 0.207662 0.745720 0.647638 -0.156420 0.842189 0.430236 -0.324984 0.891470 0.317977 -0.322757 0.959257 0.269554 -0.084650 0.906560 0.043236 0.419856 0.674742 -0.438582 0.593606 0.205932 -0.763618 0.611948 -0.477299 -0.438962 0.761248 -0.615434 -0.344303 0.709011 -0.665204 -0.414386 0.621119 -0.674268 -0.602239 0.427400 -0.539825 -0.841188 -0.031479 -0.229226 -0.828389 -0.511104 -0.043537 -0.706136 -0.706737 -0.029068 -0.615097 -0.787915 -0.276066 -0.516210 -0.810749 -0.705088 -0.125781 -0.697875 -0.672957 0.419805 -0.609010 -0.468821 0.844439 -0.259094 -0.434868 0.786420 0.438673 -0.364883 0.722473 0.587276 -0.249198 0.766271 0.592225 -0.019117 0.868292 0.495686 -0.673247 0.486431 -0.556888 -0.284001 0.441950 -0.850896 -0.017450 0.382149 -0.923936 0.110125 0.410221 -0.905313 0.128731 0.616764 -0.776550 0.170743 0.929552 -0.326772 0.444990 0.880669 0.162500 0.510757 0.549484 0.661207 0.070448 0.212509 0.974616 -0.031377 0.071577 0.996941 0.036549 -0.044526 0.998339 0.233502 -0.208762 0.949682 0.542013 -0.441792 0.714872 0.749928 -0.588278 0.302551 0.781380 -0.623574 0.024517 0.731924 -0.675603 -0.088592 0.566666 -0.822030 -0.056177 0.079383 -0.996629 0.020733 -0.440361 -0.877377 -0.190503 -0.844970 -0.452458 -0.285144 -0.984652 0.086888 0.151365 -0.948931 0.242263 0.202085 -0.938559 0.331044 0.097559 -0.895006 0.419472 -0.151681 -0.529472 -0.830473 -0.173131 -0.279115 -0.811990 -0.512608 -0.104848 -0.713703 -0.692557 -0.068220 -0.612766 -0.787314 -0.224904 -0.477285 -0.849480 -0.578339 -0.090278 -0.810786 -0.592183 0.469004 -0.655251 -0.451400 0.870299 -0.197020 -0.409979 0.835799 0.365181 -0.321042 0.798758 0.508839 -0.177109 0.831021 0.527291 0.064243 0.883010 0.464938 0.413397 0.860459 0.297846 0.707235 0.702933 0.075518 0.845748 0.529920 -0.062405 0.912074 0.403783 -0.071279 0.951900 0.289974 0.099000 0.873934 0.008477 0.485970 0.602200 -0.483670 0.635152 0.071554 -0.788603 0.610725 -0.530673 -0.580204 0.617858 -0.669001 -0.522409 0.528703 -0.705775 -0.584301 0.400592 -0.677705 -0.712578 0.181518 0.451631 -0.521118 0.724200 0.633901 -0.628493 0.450739 0.707493 -0.672553 0.217087 0.687947 -0.722060 0.073201 0.547331 -0.836909 0.003463 0.116748 -0.990437 -0.073519 -0.406347 -0.850905 -0.332930 -0.826117 -0.377371 -0.418476 -0.984729 0.088963 -0.149649 -0.957246 0.262986 -0.120489 -0.901467 0.373172 -0.219316 -0.780714 0.471798 -0.409747 -0.539237 0.542168 -0.644420 -0.232274 0.546020 -0.804929 0.005685 0.527017 -0.849836 0.148356 0.555315 -0.818300 0.211984 0.698182 -0.683816 0.251085 0.934532 -0.252202 0.422612 0.851562 0.310227 0.387178 0.460172 0.798959 0.070783 0.104081 0.992047 -0.000041 -0.064900 0.997892 0.067377 -0.200825 0.977307 0.229447 -0.355647 0.906018 0.392247 0.814373 0.427713 0.637903 0.701705 0.317315 0.791856 0.565359 0.230939 0.873665 0.434679 0.218550 0.901187 0.279320 0.331425 0.794139 -0.051061 0.605587 0.480838 -0.564933 0.670556 -0.054581 -0.861274 0.505200 -0.548197 -0.754952 0.359899 -0.674187 -0.703017 0.226359 -0.680371 -0.729453 0.070659 -0.605558 -0.783764 -0.137892 -0.439793 -0.808560 -0.390913 -0.227182 -0.759163 -0.609967 -0.064053 -0.661912 -0.746840 0.000547 -0.549142 -0.835729 -0.080880 -0.390683 -0.916965 -0.384360 -0.002426 -0.923180 -0.471733 0.561293 -0.680013 -0.397090 0.904968 -0.152818 -0.359412 0.880724 0.308461 -0.267079 0.843976 0.465159 -0.114345 0.850302 0.513724 0.112462 0.858208 0.500830 -0.345807 0.614328 -0.709238 -0.069233 0.642545 -0.763113 0.148121 0.645339 -0.749399 0.286174 0.671331 -0.683681 0.343908 0.776799 -0.527551 0.299527 0.951057 -0.075988 0.320741 0.789265 0.523627 0.223224 0.326184 0.918573 -0.019408 -0.051003 0.998510 -0.077291 -0.234516 0.969035 -0.009778 -0.368977 0.929387 0.143746 -0.497889 0.855245 0.347332 -0.611217 0.711178 0.529739 -0.677875 0.509767 0.635332 -0.705328 0.314428 0.655568 -0.738592 0.157206 0.561719 -0.827096 0.019597 0.192701 -0.962907 -0.188882 -0.309123 -0.788861 -0.531170 -0.695084 -0.293355 -0.656355 -0.870733 0.120803 -0.476688 -0.851171 0.304655 -0.427425 -0.763799 0.428539 -0.482665 -0.598749 0.535995 -0.595154 -0.205982 -0.757284 -0.619752 0.041508 -0.657962 -0.751907 0.221969 -0.528745 -0.819243 0.306614 -0.396934 -0.865119 0.255297 -0.231711 -0.938687 -0.129432 0.147258 -0.980593 -0.354567 0.660152 -0.662179 -0.392240 0.913234 -0.110238 -0.430497 0.846740 0.312576 -0.377723 0.788577 0.485253 -0.242243 0.784813 0.570428 -0.020211 0.791712 0.610560 0.259391 0.755742 0.601307 0.510331 0.661602 0.549405 0.677689 0.542687 0.496214 0.767874 0.416031 0.487122 0.784771 0.244994 0.569309 0.643303 -0.127261 0.754960 0.345218 -0.662798 0.664473 -0.069991 -0.948225 0.309792 -0.489178 -0.870927 0.046806 -0.597562 -0.794552 -0.107735 -0.564415 -0.784019 -0.258359 -0.431383 -0.790093 -0.435502 0.241878 -0.685306 0.686914 0.500430 -0.687938 0.525653 0.662544 -0.657594 0.358617 0.729954 -0.650202 0.210724 0.694469 -0.717991 0.046926 0.387602 -0.879616 -0.275755 -0.044827 -0.691537 -0.720949 -0.397577 -0.218771 -0.891107 -0.679826 0.139561 -0.719972 -0.718402 0.307991 -0.623731 -0.639521 0.442191 -0.628872 -0.446471 0.582207 -0.679484 -0.137484 0.698621 -0.702158 0.171645 0.741445 -0.648689 0.379364 0.739864 -0.555594 0.483941 0.752790 -0.446215 0.469800 0.838618 -0.275696 0.199545 0.964236 0.174445 0.051626 0.696564 0.715635 -0.059033 0.180531 0.981796 -0.265523 -0.220969 0.938440 -0.313674 -0.401997 0.860236 -0.228839 -0.519863 0.823028 -0.034136 -0.620025 0.783839 -0.062720 0.670990 0.738809 0.245826 0.609349 0.753833 0.449341 0.515204 0.729834 0.552388 0.405655 0.728225 0.559484 0.234179 0.795071 0.409174 -0.182799 0.893958 0.264675 -0.723507 0.637561 0.099952 -0.984523 0.143955 -0.286226 -0.928775 -0.235482 -0.409871 -0.820789 -0.397883 -0.340573 -0.782477 -0.521286 -0.132480 -0.751069 -0.646796 0.200268 -0.646995 -0.735724 0.510587 -0.457550 -0.727976 0.685051 -0.276627 -0.673931 0.750759 -0.131617 -0.647331 0.694890 0.015787 -0.718942 0.104103 0.309600 -0.945151 -0.267960 0.701927 -0.659921 -0.493300 0.858582 -0.139612 -0.667905 0.707964 0.229541 -0.684253 0.612724 0.395433 -0.593321 0.614063 0.520477 -0.383431 0.659947 0.646104 -0.004672 0.782551 -0.622569 0.300020 0.859131 -0.414587 0.464893 0.853117 -0.236782 0.510610 0.853721 -0.102163 0.393647 0.918514 0.037078 -0.118144 0.933942 0.337333 -0.361102 0.562141 0.744045 -0.421645 0.014199 0.906650 -0.538247 -0.415919 0.733009 -0.546465 -0.588055 0.596295 -0.440702 -0.681688 0.584023 -0.211767 -0.743242 0.634623 0.145611 -0.732101 0.665451 0.488675 -0.622527 0.611276 0.691800 -0.505171 0.515961 0.791485 -0.453028 0.410264 0.820759 -0.513458 0.250431 0.653363 -0.731187 -0.196172 0.385387 -0.545462 -0.744277 0.056822 -0.123208 -0.990753 -0.399065 0.124897 -0.908377 -0.541397 0.242347 -0.805082 -0.507504 0.382244 -0.772224 -0.330269 0.579992 -0.744669 0.626116 -0.464378 -0.626364 0.874333 -0.191436 -0.445976 0.954793 0.013415 -0.296969 0.959165 0.153907 -0.237309 0.896147 0.282120 -0.342534 0.340151 0.451600 -0.824836 -0.151827 0.724670 -0.672162 -0.586328 0.759623 -0.281413 -0.863597 0.503036 -0.033975 -0.926159 0.365490 0.092986 -0.900418 0.363410 0.239124 -0.775717 0.441288 0.451142 -0.503556 0.518828 0.690832 -0.178557 0.525334 0.831951 0.052615 0.480423 0.875457 0.168872 0.398037 0.901692 0.175124 0.224659 0.958572 0.082894 -0.235703 0.968283 0.199049 -0.738331 0.644396 0.335373 -0.931904 0.138131 0.051108 -0.920909 -0.386413 -0.088241 -0.806150 -0.585094 0.011788 -0.745097 -0.666852 0.267073 -0.662874 -0.699479 0.058049 -0.769641 0.635832 0.373174 -0.563225 0.737238 0.558597 -0.385154 0.734593 0.668822 -0.304623 0.678146 0.765614 -0.355155 0.536377 0.826890 -0.561219 0.035861 0.760582 -0.351875 -0.545618 0.465408 0.020631 -0.884856 -0.057264 0.136031 -0.989048 -0.258859 0.195905 -0.945840 -0.275651 0.334314 -0.901250 -0.177680 0.567153 -0.804218 0.019479 0.831551 -0.555107 0.202484 0.951444 -0.231852 0.288064 0.957611 -0.000060 0.275264 0.951317 0.138656 0.089550 0.972760 0.213820 -0.467874 0.833943 0.292630 -0.732935 0.377638 0.565858 -0.714467 -0.183890 0.675071 -0.664220 -0.616864 0.422245 -0.585071 -0.765956 0.266464 -0.467155 -0.833495 0.295046 -0.264791 -0.856401 0.443241 -0.836109 0.312306 0.450984 -0.593290 0.379456 0.709943 -0.385707 0.384231 0.838807 -0.270893 0.326144 0.905675 -0.250024 0.147894 0.956878 -0.230996 -0.326205 0.916641 0.110298 -0.749700 0.652522 0.455727 -0.861736 0.222988 0.360479 -0.849374 -0.385511 0.289763 -0.742813 -0.603545 0.400848 -0.656356 -0.639153 0.627891 -0.522013 -0.577283 0.885297 -0.265264 -0.381947 0.991636 0.029235 -0.125714 0.972451 0.229491 0.040902 0.927737 0.362118 0.090412 0.873395 0.483985 -0.054221 0.508284 0.603377 -0.614479 -0.055769 0.757930 -0.649947 -0.602104 0.654459 -0.457334 -0.887255 0.303456 -0.347409 -0.955913 0.138848 -0.258749 -0.985359 0.125663 -0.115222 -0.971130 0.202750 0.125695 0.006152 0.843169 -0.537613 0.037910 0.980982 -0.190358 0.037373 0.997807 0.054630 -0.022460 0.982952 0.182483 -0.226671 0.954383 0.194353 -0.704477 0.700042 0.116846 -0.939184 0.184227 0.289817 -0.841458 -0.379162 0.384948 -0.615461 -0.775711 0.139572 -0.459254 -0.887842 0.028665 -0.345849 -0.932945 0.100009 -0.204253 -0.930297 0.304676 0.006733 -0.807322 0.590073 0.216982 -0.564428 0.796454 0.353332 -0.359022 0.863863 0.460228 -0.257147 0.849745 0.610765 -0.282215 0.739811 0.864610 -0.413626 0.285242 0.949386 -0.164892 -0.267352 0.701284 0.164087 -0.693741 0.228767 0.183492 -0.956032 0.026115 0.210142 -0.977322 -0.032551 0.341460 -0.939332 -0.028663 0.574412 -0.818064 0.988492 -0.085164 -0.125020 0.970050 0.200989 0.136404 0.875923 0.387928 0.286827 0.799125 0.511721 0.315501 0.762934 0.629814 0.145829 0.543059 0.721459 -0.429632 -0.004638 0.774752 -0.632248 -0.554805 0.548999 -0.625133 -0.780396 0.134941 -0.610551 -0.838509 -0.040194 -0.543403 -0.907373 -0.066353 -0.415055 -0.982244 -0.006617 -0.187492 -0.983235 0.102021 0.151133 -0.860909 0.197853 0.468710 -0.713617 0.235220 0.659865 -0.616467 0.194944 0.762867 -0.574825 0.016127 0.818117 -0.441195 -0.438077 0.783221 0.039489 -0.767818 0.639450 0.512399 -0.800645 0.310508 0.595727 -0.747933 -0.292755 0.595818 -0.637149 -0.488920 0.695415 -0.528140 -0.487304 0.856763 -0.360703 -0.368580 -0.004045 -0.833227 0.552916 0.090762 -0.577609 0.811252 0.164406 -0.357516 0.919322 0.253658 -0.238719 0.937375 0.437285 -0.236065 0.867787 0.817644 -0.289133 0.497856 1.000000 0.000256 0.000599 0.817961 0.289316 -0.497229 0.438164 0.235900 -0.867389 0.254801 0.238612 -0.937092 0.165431 0.357418 -0.919176 0.091392 0.577544 -0.811227 -0.004082 0.833244 -0.552890 -0.098796 0.969062 -0.226181 -0.174192 0.984691 0.006343 -0.267636 0.957072 0.111282 -0.461439 0.884896 0.063500 -0.827217 0.549953 -0.115168 -1.000000 -0.000487 -0.000444 -0.826885 -0.550541 0.114741 -0.460562 -0.885354 -0.063493 -0.266452 -0.957400 -0.111308 -0.173108 -0.984883 -0.006316 -0.098095 -0.969115 0.226258 -0.983197 -0.102126 -0.151310 -0.982329 0.006598 0.187047 -0.907727 0.066337 0.414285 -0.839104 0.040204 0.542484 -0.781093 -0.134928 0.609663 -0.555247 -0.549115 0.624639 -0.004874 -0.774390 0.632690 0.543073 -0.720816 0.430693 0.763420 -0.629310 -0.145463 0.799638 -0.511296 -0.314889 0.876254 -0.387600 -0.286260 0.970119 -0.200815 -0.136174 0.988505 0.085246 0.124864 0.856667 0.361067 0.368446 0.694980 0.528778 0.487235 0.595137 0.637899 0.488771 0.595038 0.748597 0.292459 0.512093 0.800980 -0.310150 0.039633 0.767579 -0.639727 -0.440540 0.437487 -0.783920 -0.573963 -0.016529 -0.818714 -0.615646 -0.195428 -0.763406 -0.713019 -0.235696 -0.660342 -0.860664 -0.198174 -0.469026 0.006754 0.807349 -0.590036 -0.204902 0.930121 -0.304778 -0.346850 0.932544 -0.100286 -0.460308 0.887284 -0.029033 -0.616177 0.775068 -0.139985 -0.841385 0.378229 -0.386024 -0.938537 -0.185438 -0.291137 -0.703649 -0.700768 -0.117484 -0.225571 -0.954712 -0.194017 -0.021147 -0.983071 -0.181999 0.038534 -0.997789 -0.054155 0.038643 -0.980886 0.190709 0.006230 -0.843133 0.537668 -0.029249 -0.574568 0.817934 -0.033608 -0.341678 0.939216 0.024875 -0.210363 0.977307 0.227678 -0.183587 0.956273 0.700378 -0.163414 0.694814 0.948738 0.165903 0.269023 0.864694 0.414294 -0.284016 0.611706 0.282340 -0.738985 0.461425 0.257263 -0.849060 0.354424 0.359126 -0.863372 0.217685 0.564492 -0.796217 0.885374 0.265343 0.381715 0.627714 0.522211 0.577297 0.400146 0.656637 0.639305 0.288831 0.743103 0.603635 0.359888 0.849692 0.385362 0.455304 0.862091 -0.222479 0.110407 0.749880 -0.652296 -0.230142 0.326155 -0.916874 -0.248817 -0.147775 -0.957211 -0.269737 -0.326063 -0.906049 -0.384851 -0.384219 -0.839205 -0.592902 -0.379494 -0.710247 -0.835992 -0.312396 -0.451139 -0.971013 -0.203043 -0.126121 -0.985382 -0.126217 0.114417 -0.956081 -0.139499 0.257776 -0.887439 -0.304010 0.346452 -0.602122 -0.654916 0.456655 -0.055830 -0.757960 0.649908 0.508196 -0.602922 0.614998 0.873880 -0.483074 0.054532 0.928152 -0.361188 -0.089875 0.972645 -0.228736 -0.040508 0.991646 -0.028839 0.125728 0.019572 -0.831421 0.555298 -0.178318 -0.567396 0.803906 -0.276795 -0.334749 0.900737 -0.260193 -0.196400 0.945371 -0.058351 -0.136449 0.988927 0.464303 -0.020337 0.885443 0.759387 0.352491 0.546884 0.826769 0.561455 -0.034951 0.766432 0.355368 -0.535065 0.669946 0.305022 -0.676856 0.559690 0.385535 -0.733560 0.373945 0.563511 -0.736627 0.058097 0.769723 -0.635729 -0.265393 0.856021 -0.443616 -0.467997 0.832759 -0.295789 -0.585883 0.765044 -0.267297 -0.664676 0.615992 -0.422800 -0.713979 0.182971 -0.675837 -0.731765 -0.378775 -0.566612 -0.467065 -0.834429 -0.292539 0.090788 -0.972861 -0.212837 0.276743 -0.951049 -0.137547 0.289331 -0.957228 0.001094 0.203284 -0.951089 0.232606 -0.503187 -0.519152 -0.690857 -0.775333 -0.441450 -0.451642 -0.900046 -0.363608 -0.240223 -0.925920 -0.365722 -0.094445 -0.863477 -0.503341 0.032489 -0.586275 -0.759935 0.280679 -0.152816 -0.724121 0.672530 0.338599 -0.450592 0.826025 0.896332 -0.281129 0.342863 0.959050 -0.153096 0.238295 0.954537 -0.012836 0.297815 0.874148 0.191711 0.446220 0.626308 0.464572 0.626028 0.267096 0.663437 0.698936 0.011385 0.745867 0.665998 -0.088777 0.806966 0.583888 0.050518 0.921453 0.385192 0.334436 0.932260 -0.137998 0.199619 0.738008 -0.644590 0.084630 0.235194 -0.968257 0.176805 -0.224798 -0.958231 0.170462 -0.398329 -0.901264 0.053950 -0.480868 -0.875132 -0.177736 -0.525826 -0.831816 0.145573 0.732076 -0.665487 -0.212114 0.742622 -0.635232 -0.441013 0.680643 -0.585006 -0.546619 0.586828 -0.597362 -0.538008 0.414758 -0.733841 -0.420183 -0.015345 -0.907310 -0.358966 -0.563268 -0.744226 -0.116879 -0.934334 -0.336689 0.394347 -0.918285 -0.035256 0.511306 -0.853064 0.104158 0.465423 -0.852335 0.238552 0.300335 -0.858437 0.415795 -0.004538 -0.782291 0.622897 -0.330474 -0.580328 0.744316 -0.508161 -0.382861 0.771486 -0.542307 -0.243032 0.804263 -0.400089 -0.125326 0.907867 0.054844 0.123644 0.990810 0.382991 0.546262 0.744926 0.652339 0.731837 0.197150 0.820911 0.514006 -0.248805 0.791961 0.453681 -0.408622 0.692349 0.505759 -0.514647 0.489081 0.622902 -0.610567 0.200384 0.647223 0.735492 -0.132632 0.751396 0.646385 -0.341087 0.782731 0.520569 -0.410500 0.820941 0.396920 -0.286935 0.928807 0.234489 0.098827 0.984581 -0.144336 0.264551 0.723512 -0.637607 0.409937 0.182956 -0.893576 0.560494 -0.233846 -0.794457 0.553386 -0.405444 -0.727584 0.450152 -0.515188 -0.729345 0.246278 -0.609514 -0.753551 -0.062562 -0.671163 -0.738665 -0.383088 -0.660065 -0.646187 -0.592669 -0.614327 -0.520909 -0.683501 -0.613121 -0.396118 -0.667190 -0.708397 -0.230286 -0.492727 -0.858973 0.139230 -0.268167 -0.701909 0.659856 0.103764 -0.309139 0.945339 0.694501 -0.014709 0.719341 0.750123 0.132555 0.647878 0.684492 0.277283 0.674230 0.510368 0.457870 0.727929 -0.137495 -0.698134 0.702641 -0.446468 -0.582166 0.679521 -0.639658 -0.442437 0.628560 -0.718675 -0.308320 0.623253 -0.680219 -0.139705 0.719573 -0.398479 0.219053 0.890635 -0.046112 0.691858 0.720560 0.387219 0.879751 0.275863 0.694213 0.718291 -0.046106 0.729822 0.650626 -0.209870 0.662535 0.657928 -0.358019 0.500485 0.688022 -0.525491 0.241924 0.684968 -0.687234 -0.034031 0.619235 -0.784468 -0.228582 0.518778 -0.823784 -0.313302 0.400793 -0.860933 -0.265086 0.219845 -0.938828 -0.058120 -0.181467 -0.981678 0.052790 -0.697300 -0.714832 0.199803 -0.964390 -0.173294 0.469745 -0.838078 0.277425 0.483771 -0.751904 0.447891 0.379145 -0.738916 0.557003 0.171486 -0.740613 0.649680 0.259330 -0.756304 -0.600626 -0.020117 -0.792073 -0.610095 -0.241878 -0.785076 -0.570219 -0.377200 -0.788823 -0.485262 -0.429986 -0.846978 -0.312635 -0.392026 -0.913291 0.110523 -0.355136 -0.659684 0.662340 -0.129840 -0.146282 0.980685 0.255032 0.232648 0.938527 0.306193 0.397625 0.864951 0.221723 0.529294 0.818955 0.041602 0.658467 0.751459 -0.205632 0.757892 0.619125 -0.431051 0.790783 0.434578 -0.564147 0.784630 0.257088 -0.597252 0.794992 0.106197 -0.488792 0.871054 -0.048456 -0.069907 0.947832 -0.311010 0.345844 0.662136 -0.664807 0.644055 0.126669 -0.754419 0.785289 -0.245437 -0.568403 0.768266 -0.416543 -0.486065 0.677935 -0.543304 -0.495201 0.510384 -0.662274 -0.548544 0.347580 0.610611 -0.711578 0.144105 0.496986 -0.855709 -0.009269 0.367922 -0.929811 -0.076693 0.233420 -0.969347 -0.018860 0.049971 -0.998573 0.223794 -0.327038 -0.918130 0.321176 -0.789816 -0.522530 0.299153 -0.951085 0.077103 0.343119 -0.776328 0.528757 0.285349 -0.670578 0.684763 0.147384 -0.644495 0.750270 -0.069771 -0.641739 0.763742 -0.346099 -0.613706 0.709634 -0.598922 -0.535639 0.595300 -0.763971 -0.428382 0.482532 -0.851375 -0.304569 0.427081 -0.870992 -0.120587 0.476268 -0.695548 0.293821 0.655654 -0.309842 0.789179 0.530278 0.192413 0.963046 0.188468 0.561555 0.827211 -0.019459 0.655507 0.738693 -0.156982 0.635398 0.705306 -0.314345 0.529912 0.677609 -0.509941 -0.439354 0.809112 0.390264 -0.605070 0.784299 0.136988 -0.679837 0.729840 -0.071802 -0.673556 0.703210 -0.227636 -0.547448 0.754883 -0.361182 -0.053982 0.860762 -0.506137 0.481550 0.564179 -0.670680 0.794587 0.050343 -0.605060 0.901299 -0.279899 -0.330631 0.873618 -0.435237 -0.217625 0.791695 -0.565951 -0.230039 0.637626 -0.702308 -0.316538 0.391942 -0.814857 -0.427071 0.112343 -0.858514 -0.500332 -0.114223 -0.850519 -0.513392 -0.266827 -0.844157 -0.464975 -0.359203 -0.880863 -0.308309 -0.397227 -0.904846 0.153180 -0.472334 -0.560736 0.680055 -0.384818 0.003276 0.922987 -0.081090 0.391401 0.916641 0.000335 0.549682 0.835374 -0.064094 0.662382 0.746419 -0.226941 0.759645 0.609457 -0.539548 -0.541447 0.644766 -0.780910 -0.471330 0.409912 -0.901596 -0.372884 0.219277 -0.957333 -0.262744 0.120332 -0.984787 -0.088542 0.149514 -0.826202 0.377932 0.417801 -0.406588 0.851189 0.331910 0.116838 0.990470 0.072928 0.547367 0.836885 -0.003572 0.688017 0.721996 -0.073175 0.707693 0.672345 -0.217078 0.634275 0.628051 -0.450830 0.452138 0.520396 -0.724403 0.230041 0.354738 -0.906224 0.068040 0.199874 -0.977456 0.000642 0.063978 -0.997951 0.071439 -0.104938 -0.991910 0.387923 -0.460919 -0.798166 0.422854 -0.851889 -0.308996 0.250634 -0.934376 0.253226 0.211212 -0.697540 0.684710 0.147598 -0.554453 0.819022 0.005023 -0.526093 0.850412 -0.232773 -0.545132 0.805387 0.413138 -0.860621 -0.297737 0.064232 -0.883082 -0.464802 -0.176919 -0.831134 -0.527178 -0.320797 -0.798895 -0.508779 -0.409828 -0.835863 -0.365203 -0.451595 -0.870212 0.196961 -0.592528 -0.468744 0.655126 -0.578688 0.090619 0.810499 -0.225263 0.477617 0.849199 -0.068550 0.613048 0.787066 -0.105051 0.713926 0.692296 -0.279138 0.812166 0.512316 -0.529387 0.830612 0.172723 -0.677579 0.712542 -0.182129 -0.705579 0.584070 -0.401273 -0.668755 0.522047 -0.529371 -0.530448 0.579727 -0.618500 0.071642 0.788181 -0.611259 0.602410 0.483276 -0.635253 0.873973 -0.008784 -0.485895 0.951851 -0.290189 -0.098845 0.911974 -0.403959 0.071553 0.845593 -0.530139 0.062652 0.706984 -0.703201 -0.075379 0.542464 0.441207 -0.714891 0.234130 0.208110 -0.949670 0.037254 0.043928 -0.998340 -0.030699 -0.072125 -0.996923 0.070984 -0.213024 -0.974465 0.511064 -0.549983 -0.660555 0.444836 -0.880899 -0.161672 0.170137 -0.929468 0.327326 0.128016 -0.616220 0.777100 0.109477 -0.409491 0.905722 -0.018032 -0.381385 0.924240 -0.284453 -0.441181 0.851144 -0.673519 -0.485833 0.557080 -0.895166 -0.419160 0.151600 -0.938587 -0.330873 -0.097862 -0.948886 -0.242114 -0.202473 -0.984625 -0.086584 -0.151710 -0.844960 0.452873 0.284515 -0.440263 0.877566 0.189860 0.079829 0.996590 -0.020899 0.566837 0.821899 0.056370 0.731963 0.675534 0.088793 0.781495 0.623437 -0.024345 0.750204 0.587963 -0.302479 -0.539261 0.841559 0.031236 -0.673591 0.602700 -0.427818 -0.664498 0.414729 -0.621645 -0.614666 0.344574 -0.709545 -0.476335 0.439286 -0.761665 0.206734 0.763430 -0.611911 0.675356 0.438172 -0.593211 0.906814 -0.043704 -0.419259 0.959089 -0.269970 0.085229 0.891105 -0.318239 0.323505 0.841777 -0.430441 0.325779 0.745372 -0.647856 0.157171 0.410405 -0.888056 -0.207183 -0.019051 -0.868381 -0.495531 -0.248952 -0.766334 -0.592245 -0.364561 -0.722571 -0.587356 -0.434574 -0.786648 -0.438556 -0.468949 -0.844275 0.259397 -0.673418 -0.419534 0.608686 -0.705464 0.126152 0.697428 -0.276297 0.516474 0.810503 -0.029427 0.615269 0.787768 -0.043803 0.706294 0.706563 -0.229160 0.828563 0.510851 -0.735738 -0.451375 0.504926 -0.916646 -0.395785 -0.055808 -0.893199 -0.319185 -0.316727 -0.881446 -0.246825 -0.402654 -0.944153 -0.097846 -0.314646 -0.838104 0.494494 0.230344 -0.459959 0.882441 0.098667 0.051595 0.994501 -0.091139 0.574379 0.807455 0.134556 0.730721 0.628410 0.266736 0.792053 0.582530 0.182515 0.814511 0.568962 -0.113376 0.619793 0.399741 -0.675325 0.215598 0.104596 -0.970864 -0.003079 -0.052878 -0.998596 -0.061275 -0.147058 -0.987228 0.085905 -0.267625 -0.959686 0.616196 -0.582600 -0.529980 0.454896 -0.887192 -0.077198 0.118141 -0.929329 0.349844 0.096059 -0.540565 0.835800 0.132002 -0.267385 0.954505 0.022574 -0.244407 0.969410 -0.259103 -0.341743 0.903370 0.431483 -0.893087 -0.127347 -0.053703 -0.847704 -0.527744 -0.266765 -0.719853 -0.640819 -0.361848 -0.679379 -0.638365 -0.417185 -0.780003 -0.466425 -0.461549 -0.831315 0.309656 -0.714969 -0.405198 0.569766 -0.775402 0.130919 0.617748 -0.270293 0.526075 0.806341 0.034345 0.584450 0.810702 0.024994 0.666907 0.744722 -0.165030 0.813764 0.557274 -0.523255 0.851953 -0.019491 -0.647123 0.516589 -0.560686 -0.616496 0.300498 -0.727759 -0.563664 0.237920 -0.790997 -0.421668 0.383491 -0.821664 0.282302 0.762214 -0.582525 0.711037 0.423090 -0.561625 0.922322 -0.053745 -0.382667 0.947551 -0.222053 0.229867 0.838052 -0.208358 0.504237 0.803225 -0.307249 0.510322 0.758526 -0.553981 0.343137 0.681332 0.397860 -0.614406 0.218071 0.054638 -0.974402 -0.011105 -0.100535 -0.994872 -0.059171 -0.183625 -0.981214 0.141590 -0.293855 -0.945305 0.686215 -0.579849 -0.439186 0.473441 -0.880306 -0.030236 0.106356 -0.925695 0.363010 0.112188 -0.452926 0.884462 0.168565 -0.153682 0.973636 0.071431 -0.140276 0.987532 -0.205873 -0.259282 0.943604 -0.744016 -0.433629 0.508337 -0.904307 -0.398569 -0.152876 -0.848532 -0.328859 -0.414542 -0.833502 -0.263211 -0.485792 -0.929071 -0.104123 -0.354945 -0.841987 0.502159 0.197216 -0.479097 0.876771 0.041697 0.026428 0.990316 -0.136290 0.570896 0.789501 0.225311 0.696692 0.589940 0.408156 0.759460 0.555452 0.338664 0.824049 0.564401 0.048929 -0.506892 0.861921 -0.012368 -0.629315 0.483449 -0.608473 -0.588183 0.252583 -0.768272 -0.532973 0.197924 -0.822658 -0.376161 0.399355 -0.836073 0.305904 0.765349 -0.566271 0.722746 0.424680 -0.545238 0.932540 -0.045120 -0.358236 0.923833 -0.152801 0.350975 0.785555 -0.113498 0.608295 0.762788 -0.205459 0.613140 0.756832 -0.459154 0.465170 0.475293 -0.878758 -0.043370 -0.036302 -0.851435 -0.523202 -0.247242 -0.717703 -0.650979 -0.334963 -0.684203 -0.647816 -0.378380 -0.816699 -0.435696 -0.445477 -0.829072 0.337921 -0.730054 -0.408693 0.547715 -0.808377 0.122485 0.575781 -0.220532 0.522479 0.823639 0.080067 0.557389 0.826382 0.066815 0.634306 0.770189 -0.119897 0.790965 0.600000 -0.721091 -0.418955 0.551819 -0.897828 -0.415886 -0.144720 -0.837801 -0.351898 -0.417441 -0.827655 -0.285424 -0.483240 -0.944797 -0.103243 -0.310965 -0.855156 0.490525 0.167613 -0.500093 0.865971 -0.000279 0.002377 0.985740 -0.168256 0.561619 0.766722 0.311000 0.660798 0.574100 0.483483 0.723448 0.549712 0.417659 0.808933 0.569768 0.144882 0.723242 0.415128 -0.551896 0.254805 0.041849 -0.966087 0.016407 -0.122325 -0.992354 -0.025020 -0.204737 -0.978497 0.231669 -0.308866 -0.922459 0.728970 -0.564371 -0.387412 0.500281 -0.865863 0.000113 0.124827 -0.913243 0.387821 0.151529 -0.355233 0.922415 0.189538 -0.080905 0.978535 0.097459 -0.075527 0.992370 -0.163870 -0.199920 0.966012 0.523501 -0.850917 0.043444 0.019362 -0.885284 -0.464648 -0.203440 -0.763748 -0.612619 -0.294531 -0.737454 -0.607794 -0.329557 -0.876676 -0.350472 -0.426899 -0.830082 0.358777 -0.728860 -0.413469 0.545717 -0.815568 0.117841 0.566535 -0.157345 0.525729 0.835973 0.095551 0.560765 0.822443 0.075849 0.635819 0.768103 -0.103514 0.786782 0.608489 -0.492922 0.869983 0.012539 -0.625348 0.498965 -0.599978 -0.583068 0.258813 -0.770096 -0.523097 0.208966 -0.826259 -0.342455 0.452230 -0.823537 0.297753 0.761193 -0.576132 0.718653 0.427855 -0.548159 0.940640 -0.028653 -0.338195 0.896640 -0.080289 0.435421 0.760356 -0.051733 0.647444 0.745533 -0.144548 0.650605 0.755801 -0.394197 0.522852 0.747401 0.427732 -0.508366 0.327445 0.048688 -0.943615 0.085705 -0.132030 -0.987534 0.048718 -0.222825 -0.973640 0.336061 -0.323503 -0.884539 0.748606 -0.554825 -0.362987 0.525646 -0.850169 0.030152 0.158865 -0.884528 0.438602 0.183820 -0.269191 0.945382 0.188836 -0.040087 0.981190 0.092840 -0.040334 0.994864 -0.156197 -0.161469 0.974439 -0.685170 -0.391429 0.614268 -0.900645 -0.431789 -0.048952 -0.860673 -0.380276 -0.338573 -0.859227 -0.308619 -0.408024 -0.969196 -0.099858 -0.225139 -0.871025 0.471929 0.136375 -0.520063 0.853124 -0.041398 -0.013935 0.980393 -0.196557 0.554314 0.753115 0.354336 0.644556 0.590798 0.485289 0.708953 0.570865 0.414124 0.797148 0.584193 0.152555 -0.476489 0.878964 0.019507 -0.622330 0.549621 -0.557334 -0.590038 0.311622 -0.744814 -0.523274 0.262253 -0.810807 -0.320571 0.496817 -0.806478 0.274158 0.737085 -0.617692 0.708363 0.416873 -0.569596 0.950784 -0.015577 -0.309463 0.884065 -0.028470 0.466496 0.769197 -0.026104 0.638478 0.756739 -0.128694 0.640925 0.761044 -0.377184 0.527773 0.557863 -0.820137 0.127141 0.100739 -0.933775 -0.343390 -0.135228 -0.849157 -0.510535 -0.238257 -0.829912 -0.504460 -0.281186 -0.931624 -0.230239 -0.414459 -0.825817 0.382428 -0.721933 -0.404522 0.561404 -0.801449 0.136283 0.582329 -0.121572 0.556824 0.821686 0.075409 0.607095 0.791043 0.047598 0.684136 0.727800 -0.124227 0.818640 0.560710 -0.656110 -0.336824 0.675329 -0.899928 -0.421017 0.113461 -0.900437 -0.394899 -0.182394 -0.909503 -0.318904 -0.266654 -0.986388 -0.094103 -0.134849 -0.887250 0.452311 0.090566 -0.534410 0.839367 -0.099348 -0.009510 0.972885 -0.231093 0.556787 0.768656 0.314891 0.654357 0.640032 0.402710 0.722897 0.614075 0.316753 0.800998 0.596053 0.055888 0.758800 0.411472 -0.504890 0.425452 0.053236 -0.903414 0.200217 -0.142159 -0.969383 0.165318 -0.248439 -0.954436 0.419953 -0.353791 -0.835746 0.745999 -0.566873 -0.349486 0.541275 -0.837251 0.077667 0.196928 -0.824368 0.530694 0.188842 -0.207936 0.959740 0.157905 -0.020250 0.987247 0.047218 -0.023556 0.998607 -0.198513 -0.134258 0.970859 0.563674 -0.799497 0.207548 0.188014 -0.969617 -0.156505 -0.048497 -0.944468 -0.325005 -0.170343 -0.931030 -0.322749 -0.246135 -0.965533 -0.084634 -0.415727 -0.806747 0.419916 -0.717102 -0.365087 0.593698 -0.764265 0.203414 0.611982 -0.141631 0.632875 0.761190 0.009468 0.705202 0.708943 -0.026352 0.783338 0.621037 -0.184535 0.885071 0.427312 -0.458688 0.888040 -0.031484 -0.602901 0.612680 -0.511013 -0.589882 0.390746 -0.706652 -0.518278 0.332696 -0.787846 -0.309148 0.497167 -0.810711 0.243463 0.673504 -0.697938 0.699925 0.372909 -0.609133 0.965660 -0.016183 -0.259305 0.898574 -0.016538 0.438510 0.808205 -0.045140 0.587168 0.788303 -0.167220 0.592128 0.761628 -0.417507 0.495592 0.757835 0.339917 -0.556905 0.524712 0.025044 -0.850911 0.339656 -0.175922 -0.923951 0.300191 -0.300454 -0.905325 0.469764 -0.419831 -0.776572 0.719648 -0.612593 -0.326858 0.540267 -0.825665 0.162447 0.220616 -0.717048 0.661189 0.148923 -0.167271 0.974598 0.077770 -0.008617 0.996934 -0.056750 -0.009403 0.998344 -0.297469 -0.097877 0.949701 -0.653543 -0.248576 0.714907 -0.884369 -0.355403 0.302623 -0.930685 -0.364992 0.024614 -0.951034 -0.296150 -0.088482 -0.995233 -0.079811 -0.056045 -0.902820 0.429512 0.020863 -0.539736 0.820013 -0.190432 0.030548 0.958001 -0.285132 0.567533 0.809326 0.151318 0.684239 0.700719 0.202015 0.755929 0.647354 0.097489 0.810719 0.565431 -0.151731 -0.454590 0.873734 -0.173023 -0.563767 0.647707 -0.512486 -0.565782 0.447671 -0.692446 -0.496682 0.365508 -0.787217 -0.301016 0.433484 -0.849401 0.210824 0.546062 -0.810783 0.702138 0.278437 -0.655344 0.979372 -0.044139 -0.197187 0.928869 -0.062787 0.365048 0.852344 -0.121299 0.508720 0.808331 -0.262080 0.527176 0.732695 -0.497086 0.464827 0.538604 -0.788196 0.297748 0.255259 -0.963925 0.075443 0.036157 -0.997393 -0.062452 -0.106245 -0.991780 -0.071300 -0.224693 -0.969386 0.099019 -0.429457 -0.761136 0.486044 -0.719836 -0.279783 0.635262 -0.718677 0.332231 0.610841 -0.237170 0.749619 0.617917 -0.117958 0.840537 0.528757 -0.153189 0.903332 0.400654 -0.278347 0.943157 0.181598 -0.676991 -0.130855 0.724265 -0.861132 -0.234977 0.450818 -0.936115 -0.276623 0.217183 -0.969249 -0.234909 0.073307 -0.998440 -0.055726 0.003576 -0.916214 0.393918 -0.073352 -0.533913 0.777326 -0.332719 0.085984 0.904187 -0.418393 0.569212 0.808440 -0.149742 0.706235 0.697632 -0.120586 0.773768 0.594252 -0.219423 0.798783 0.440400 -0.409871 0.738964 0.196129 -0.644565 0.588814 -0.071621 -0.805089 0.453383 -0.268201 -0.850007 0.406572 -0.405910 -0.818496 0.498538 -0.532456 -0.684069 0.683829 -0.684563 -0.252489 0.526310 -0.791796 0.309931 0.205114 -0.565607 0.798759 0.054922 -0.113568 0.992011 -0.056023 0.032245 0.997909 -0.207457 0.041795 0.977351 -0.422584 -0.021176 0.906076 0.509271 -0.746853 0.427613 0.288868 -0.903278 0.317245 0.093796 -0.968449 0.230888 -0.060291 -0.973972 0.218504 -0.208590 -0.920147 0.331392 -0.441164 -0.662283 0.605604 -0.729561 -0.134034 0.670653 -0.718535 0.477848 0.505341 -0.379667 0.852199 0.360014 -0.271729 0.935348 0.226467 -0.291565 0.953929 0.070772 -0.376047 0.916301 -0.137775 -0.480443 0.785144 -0.390798 -0.543994 0.576319 -0.609858 -0.541339 0.386428 -0.746743 -0.475982 0.274110 -0.835647 -0.298046 0.265423 -0.916907 0.189942 0.334176 -0.923173 0.721884 0.128038 -0.680066 0.982279 -0.108425 -0.152876 0.942485 -0.128998 0.308353 0.864523 -0.190629 0.465039 0.793652 -0.326082 0.513602 0.687113 -0.526463 0.500712</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-normals-array" count="2880" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus_Knot01-mesh-map-channel1">
+ <float_array id="Torus_Knot01-mesh-map-channel1-array" count="9075">0 0 0 0 0.041667 0 0 0.083333 0 0 0.125000 0 0 0.166667 0 0 0.208333 0 0 0.250000 0 0 0.291667 0 0 0.333333 0 0 0.375000 0 0 0.416667 0 0 0.458333 0 0 0.500000 0 0 0.541667 0 0 0.583333 0 0 0.625000 0 0 0.666667 0 0 0.708333 0 0 0.750000 0 0 0.791667 0 0 0.833333 0 0 0.875000 0 0 0.916667 0 0 0.958333 0 0 1.000000 0 0.008333 0 0 0.008333 0.041667 0 0.008333 0.083333 0 0.008333 0.125000 0 0.008333 0.166667 0 0.008333 0.208333 0 0.008333 0.250000 0 0.008333 0.291667 0 0.008333 0.333333 0 0.008333 0.375000 0 0.008333 0.416667 0 0.008333 0.458333 0 0.008333 0.500000 0 0.008333 0.541667 0 0.008333 0.583333 0 0.008333 0.625000 0 0.008333 0.666667 0 0.008333 0.708333 0 0.008333 0.750000 0 0.008333 0.791667 0 0.008333 0.833333 0 0.008333 0.875000 0 0.008333 0.916667 0 0.008333 0.958333 0 0.008333 1.000000 0 0.016667 0 0 0.016667 0.041667 0 0.016667 0.083333 0 0.016667 0.125000 0 0.016667 0.166667 0 0.016667 0.208333 0 0.016667 0.250000 0 0.016667 0.291667 0 0.016667 0.333333 0 0.016667 0.375000 0 0.016667 0.416667 0 0.016667 0.458333 0 0.016667 0.500000 0 0.016667 0.541667 0 0.016667 0.583333 0 0.016667 0.625000 0 0.016667 0.666667 0 0.016667 0.708333 0 0.016667 0.750000 0 0.016667 0.791667 0 0.016667 0.833333 0 0.016667 0.875000 0 0.016667 0.916667 0 0.016667 0.958333 0 0.016667 1.000000 0 0.025000 0 0 0.025000 0.041667 0 0.025000 0.083333 0 0.025000 0.125000 0 0.025000 0.166667 0 0.025000 0.208333 0 0.025000 0.250000 0 0.025000 0.291667 0 0.025000 0.333333 0 0.025000 0.375000 0 0.025000 0.416667 0 0.025000 0.458333 0 0.025000 0.500000 0 0.025000 0.541667 0 0.025000 0.583333 0 0.025000 0.625000 0 0.025000 0.666667 0 0.025000 0.708333 0 0.025000 0.750000 0 0.025000 0.791667 0 0.025000 0.833333 0 0.025000 0.875000 0 0.025000 0.916667 0 0.025000 0.958333 0 0.025000 1.000000 0 0.033333 0 0 0.033333 0.041667 0 0.033333 0.083333 0 0.033333 0.125000 0 0.033333 0.166667 0 0.033333 0.208333 0 0.033333 0.250000 0 0.033333 0.291667 0 0.033333 0.333333 0 0.033333 0.375000 0 0.033333 0.416667 0 0.033333 0.458333 0 0.033333 0.500000 0 0.033333 0.541667 0 0.033333 0.583333 0 0.033333 0.625000 0 0.033333 0.666667 0 0.033333 0.708333 0 0.033333 0.750000 0 0.033333 0.791667 0 0.033333 0.833333 0 0.033333 0.875000 0 0.033333 0.916667 0 0.033333 0.958333 0 0.033333 1.000000 0 0.041667 0 0 0.041667 0.041667 0 0.041667 0.083333 0 0.041667 0.125000 0 0.041667 0.166667 0 0.041667 0.208333 0 0.041667 0.250000 0 0.041667 0.291667 0 0.041667 0.333333 0 0.041667 0.375000 0 0.041667 0.416667 0 0.041667 0.458333 0 0.041667 0.500000 0 0.041667 0.541667 0 0.041667 0.583333 0 0.041667 0.625000 0 0.041667 0.666667 0 0.041667 0.708333 0 0.041667 0.750000 0 0.041667 0.791667 0 0.041667 0.833333 0 0.041667 0.875000 0 0.041667 0.916667 0 0.041667 0.958333 0 0.041667 1.000000 0 0.050000 0 0 0.050000 0.041667 0 0.050000 0.083333 0 0.050000 0.125000 0 0.050000 0.166667 0 0.050000 0.208333 0 0.050000 0.250000 0 0.050000 0.291667 0 0.050000 0.333333 0 0.050000 0.375000 0 0.050000 0.416667 0 0.050000 0.458333 0 0.050000 0.500000 0 0.050000 0.541667 0 0.050000 0.583333 0 0.050000 0.625000 0 0.050000 0.666667 0 0.050000 0.708333 0 0.050000 0.750000 0 0.050000 0.791667 0 0.050000 0.833333 0 0.050000 0.875000 0 0.050000 0.916667 0 0.050000 0.958333 0 0.050000 1.000000 0 0.058333 0 0 0.058333 0.041667 0 0.058333 0.083333 0 0.058333 0.125000 0 0.058333 0.166667 0 0.058333 0.208333 0 0.058333 0.250000 0 0.058333 0.291667 0 0.058333 0.333333 0 0.058333 0.375000 0 0.058333 0.416667 0 0.058333 0.458333 0 0.058333 0.500000 0 0.058333 0.541667 0 0.058333 0.583333 0 0.058333 0.625000 0 0.058333 0.666667 0 0.058333 0.708333 0 0.058333 0.750000 0 0.058333 0.791667 0 0.058333 0.833333 0 0.058333 0.875000 0 0.058333 0.916667 0 0.058333 0.958333 0 0.058333 1.000000 0 0.066667 0 0 0.066667 0.041667 0 0.066667 0.083333 0 0.066667 0.125000 0 0.066667 0.166667 0 0.066667 0.208333 0 0.066667 0.250000 0 0.066667 0.291667 0 0.066667 0.333333 0 0.066667 0.375000 0 0.066667 0.416667 0 0.066667 0.458333 0 0.066667 0.500000 0 0.066667 0.541667 0 0.066667 0.583333 0 0.066667 0.625000 0 0.066667 0.666667 0 0.066667 0.708333 0 0.066667 0.750000 0 0.066667 0.791667 0 0.066667 0.833333 0 0.066667 0.875000 0 0.066667 0.916667 0 0.066667 0.958333 0 0.066667 1.000000 0 0.075000 0 0 0.075000 0.041667 0 0.075000 0.083333 0 0.075000 0.125000 0 0.075000 0.166667 0 0.075000 0.208333 0 0.075000 0.250000 0 0.075000 0.291667 0 0.075000 0.333333 0 0.075000 0.375000 0 0.075000 0.416667 0 0.075000 0.458333 0 0.075000 0.500000 0 0.075000 0.541667 0 0.075000 0.583333 0 0.075000 0.625000 0 0.075000 0.666667 0 0.075000 0.708333 0 0.075000 0.750000 0 0.075000 0.791667 0 0.075000 0.833333 0 0.075000 0.875000 0 0.075000 0.916667 0 0.075000 0.958333 0 0.075000 1.000000 0 0.083333 0 0 0.083333 0.041667 0 0.083333 0.083333 0 0.083333 0.125000 0 0.083333 0.166667 0 0.083333 0.208333 0 0.083333 0.250000 0 0.083333 0.291667 0 0.083333 0.333333 0 0.083333 0.375000 0 0.083333 0.416667 0 0.083333 0.458333 0 0.083333 0.500000 0 0.083333 0.541667 0 0.083333 0.583333 0 0.083333 0.625000 0 0.083333 0.666667 0 0.083333 0.708333 0 0.083333 0.750000 0 0.083333 0.791667 0 0.083333 0.833333 0 0.083333 0.875000 0 0.083333 0.916667 0 0.083333 0.958333 0 0.083333 1.000000 0 0.091667 0 0 0.091667 0.041667 0 0.091667 0.083333 0 0.091667 0.125000 0 0.091667 0.166667 0 0.091667 0.208333 0 0.091667 0.250000 0 0.091667 0.291667 0 0.091667 0.333333 0 0.091667 0.375000 0 0.091667 0.416667 0 0.091667 0.458333 0 0.091667 0.500000 0 0.091667 0.541667 0 0.091667 0.583333 0 0.091667 0.625000 0 0.091667 0.666667 0 0.091667 0.708333 0 0.091667 0.750000 0 0.091667 0.791667 0 0.091667 0.833333 0 0.091667 0.875000 0 0.091667 0.916667 0 0.091667 0.958333 0 0.091667 1.000000 0 0.100000 0 0 0.100000 0.041667 0 0.100000 0.083333 0 0.100000 0.125000 0 0.100000 0.166667 0 0.100000 0.208333 0 0.100000 0.250000 0 0.100000 0.291667 0 0.100000 0.333333 0 0.100000 0.375000 0 0.100000 0.416667 0 0.100000 0.458333 0 0.100000 0.500000 0 0.100000 0.541667 0 0.100000 0.583333 0 0.100000 0.625000 0 0.100000 0.666667 0 0.100000 0.708333 0 0.100000 0.750000 0 0.100000 0.791667 0 0.100000 0.833333 0 0.100000 0.875000 0 0.100000 0.916667 0 0.100000 0.958333 0 0.100000 1.000000 0 0.108333 0 0 0.108333 0.041667 0 0.108333 0.083333 0 0.108333 0.125000 0 0.108333 0.166667 0 0.108333 0.208333 0 0.108333 0.250000 0 0.108333 0.291667 0 0.108333 0.333333 0 0.108333 0.375000 0 0.108333 0.416667 0 0.108333 0.458333 0 0.108333 0.500000 0 0.108333 0.541667 0 0.108333 0.583333 0 0.108333 0.625000 0 0.108333 0.666667 0 0.108333 0.708333 0 0.108333 0.750000 0 0.108333 0.791667 0 0.108333 0.833333 0 0.108333 0.875000 0 0.108333 0.916667 0 0.108333 0.958333 0 0.108333 1.000000 0 0.116667 0 0 0.116667 0.041667 0 0.116667 0.083333 0 0.116667 0.125000 0 0.116667 0.166667 0 0.116667 0.208333 0 0.116667 0.250000 0 0.116667 0.291667 0 0.116667 0.333333 0 0.116667 0.375000 0 0.116667 0.416667 0 0.116667 0.458333 0 0.116667 0.500000 0 0.116667 0.541667 0 0.116667 0.583333 0 0.116667 0.625000 0 0.116667 0.666667 0 0.116667 0.708333 0 0.116667 0.750000 0 0.116667 0.791667 0 0.116667 0.833333 0 0.116667 0.875000 0 0.116667 0.916667 0 0.116667 0.958333 0 0.116667 1.000000 0 0.125000 0 0 0.125000 0.041667 0 0.125000 0.083333 0 0.125000 0.125000 0 0.125000 0.166667 0 0.125000 0.208333 0 0.125000 0.250000 0 0.125000 0.291667 0 0.125000 0.333333 0 0.125000 0.375000 0 0.125000 0.416667 0 0.125000 0.458333 0 0.125000 0.500000 0 0.125000 0.541667 0 0.125000 0.583333 0 0.125000 0.625000 0 0.125000 0.666667 0 0.125000 0.708333 0 0.125000 0.750000 0 0.125000 0.791667 0 0.125000 0.833333 0 0.125000 0.875000 0 0.125000 0.916667 0 0.125000 0.958333 0 0.125000 1.000000 0 0.133333 0 0 0.133333 0.041667 0 0.133333 0.083333 0 0.133333 0.125000 0 0.133333 0.166667 0 0.133333 0.208333 0 0.133333 0.250000 0 0.133333 0.291667 0 0.133333 0.333333 0 0.133333 0.375000 0 0.133333 0.416667 0 0.133333 0.458333 0 0.133333 0.500000 0 0.133333 0.541667 0 0.133333 0.583333 0 0.133333 0.625000 0 0.133333 0.666667 0 0.133333 0.708333 0 0.133333 0.750000 0 0.133333 0.791667 0 0.133333 0.833333 0 0.133333 0.875000 0 0.133333 0.916667 0 0.133333 0.958333 0 0.133333 1.000000 0 0.141667 0 0 0.141667 0.041667 0 0.141667 0.083333 0 0.141667 0.125000 0 0.141667 0.166667 0 0.141667 0.208333 0 0.141667 0.250000 0 0.141667 0.291667 0 0.141667 0.333333 0 0.141667 0.375000 0 0.141667 0.416667 0 0.141667 0.458333 0 0.141667 0.500000 0 0.141667 0.541667 0 0.141667 0.583333 0 0.141667 0.625000 0 0.141667 0.666667 0 0.141667 0.708333 0 0.141667 0.750000 0 0.141667 0.791667 0 0.141667 0.833333 0 0.141667 0.875000 0 0.141667 0.916667 0 0.141667 0.958333 0 0.141667 1.000000 0 0.150000 0 0 0.150000 0.041667 0 0.150000 0.083333 0 0.150000 0.125000 0 0.150000 0.166667 0 0.150000 0.208333 0 0.150000 0.250000 0 0.150000 0.291667 0 0.150000 0.333333 0 0.150000 0.375000 0 0.150000 0.416667 0 0.150000 0.458333 0 0.150000 0.500000 0 0.150000 0.541667 0 0.150000 0.583333 0 0.150000 0.625000 0 0.150000 0.666667 0 0.150000 0.708333 0 0.150000 0.750000 0 0.150000 0.791667 0 0.150000 0.833333 0 0.150000 0.875000 0 0.150000 0.916667 0 0.150000 0.958333 0 0.150000 1.000000 0 0.158333 0 0 0.158333 0.041667 0 0.158333 0.083333 0 0.158333 0.125000 0 0.158333 0.166667 0 0.158333 0.208333 0 0.158333 0.250000 0 0.158333 0.291667 0 0.158333 0.333333 0 0.158333 0.375000 0 0.158333 0.416667 0 0.158333 0.458333 0 0.158333 0.500000 0 0.158333 0.541667 0 0.158333 0.583333 0 0.158333 0.625000 0 0.158333 0.666667 0 0.158333 0.708333 0 0.158333 0.750000 0 0.158333 0.791667 0 0.158333 0.833333 0 0.158333 0.875000 0 0.158333 0.916667 0 0.158333 0.958333 0 0.158333 1.000000 0 0.166667 0 0 0.166667 0.041667 0 0.166667 0.083333 0 0.166667 0.125000 0 0.166667 0.166667 0 0.166667 0.208333 0 0.166667 0.250000 0 0.166667 0.291667 0 0.166667 0.333333 0 0.166667 0.375000 0 0.166667 0.416667 0 0.166667 0.458333 0 0.166667 0.500000 0 0.166667 0.541667 0 0.166667 0.583333 0 0.166667 0.625000 0 0.166667 0.666667 0 0.166667 0.708333 0 0.166667 0.750000 0 0.166667 0.791667 0 0.166667 0.833333 0 0.166667 0.875000 0 0.166667 0.916667 0 0.166667 0.958333 0 0.166667 1.000000 0 0.175000 0 0 0.175000 0.041667 0 0.175000 0.083333 0 0.175000 0.125000 0 0.175000 0.166667 0 0.175000 0.208333 0 0.175000 0.250000 0 0.175000 0.291667 0 0.175000 0.333333 0 0.175000 0.375000 0 0.175000 0.416667 0 0.175000 0.458333 0 0.175000 0.500000 0 0.175000 0.541667 0 0.175000 0.583333 0 0.175000 0.625000 0 0.175000 0.666667 0 0.175000 0.708333 0 0.175000 0.750000 0 0.175000 0.791667 0 0.175000 0.833333 0 0.175000 0.875000 0 0.175000 0.916667 0 0.175000 0.958333 0 0.175000 1.000000 0 0.183333 0 0 0.183333 0.041667 0 0.183333 0.083333 0 0.183333 0.125000 0 0.183333 0.166667 0 0.183333 0.208333 0 0.183333 0.250000 0 0.183333 0.291667 0 0.183333 0.333333 0 0.183333 0.375000 0 0.183333 0.416667 0 0.183333 0.458333 0 0.183333 0.500000 0 0.183333 0.541667 0 0.183333 0.583333 0 0.183333 0.625000 0 0.183333 0.666667 0 0.183333 0.708333 0 0.183333 0.750000 0 0.183333 0.791667 0 0.183333 0.833333 0 0.183333 0.875000 0 0.183333 0.916667 0 0.183333 0.958333 0 0.183333 1.000000 0 0.191667 0 0 0.191667 0.041667 0 0.191667 0.083333 0 0.191667 0.125000 0 0.191667 0.166667 0 0.191667 0.208333 0 0.191667 0.250000 0 0.191667 0.291667 0 0.191667 0.333333 0 0.191667 0.375000 0 0.191667 0.416667 0 0.191667 0.458333 0 0.191667 0.500000 0 0.191667 0.541667 0 0.191667 0.583333 0 0.191667 0.625000 0 0.191667 0.666667 0 0.191667 0.708333 0 0.191667 0.750000 0 0.191667 0.791667 0 0.191667 0.833333 0 0.191667 0.875000 0 0.191667 0.916667 0 0.191667 0.958333 0 0.191667 1.000000 0 0.200000 0 0 0.200000 0.041667 0 0.200000 0.083333 0 0.200000 0.125000 0 0.200000 0.166667 0 0.200000 0.208333 0 0.200000 0.250000 0 0.200000 0.291667 0 0.200000 0.333333 0 0.200000 0.375000 0 0.200000 0.416667 0 0.200000 0.458333 0 0.200000 0.500000 0 0.200000 0.541667 0 0.200000 0.583333 0 0.200000 0.625000 0 0.200000 0.666667 0 0.200000 0.708333 0 0.200000 0.750000 0 0.200000 0.791667 0 0.200000 0.833333 0 0.200000 0.875000 0 0.200000 0.916667 0 0.200000 0.958333 0 0.200000 1.000000 0 0.208333 0 0 0.208333 0.041667 0 0.208333 0.083333 0 0.208333 0.125000 0 0.208333 0.166667 0 0.208333 0.208333 0 0.208333 0.250000 0 0.208333 0.291667 0 0.208333 0.333333 0 0.208333 0.375000 0 0.208333 0.416667 0 0.208333 0.458333 0 0.208333 0.500000 0 0.208333 0.541667 0 0.208333 0.583333 0 0.208333 0.625000 0 0.208333 0.666667 0 0.208333 0.708333 0 0.208333 0.750000 0 0.208333 0.791667 0 0.208333 0.833333 0 0.208333 0.875000 0 0.208333 0.916667 0 0.208333 0.958333 0 0.208333 1.000000 0 0.216667 0 0 0.216667 0.041667 0 0.216667 0.083333 0 0.216667 0.125000 0 0.216667 0.166667 0 0.216667 0.208333 0 0.216667 0.250000 0 0.216667 0.291667 0 0.216667 0.333333 0 0.216667 0.375000 0 0.216667 0.416667 0 0.216667 0.458333 0 0.216667 0.500000 0 0.216667 0.541667 0 0.216667 0.583333 0 0.216667 0.625000 0 0.216667 0.666667 0 0.216667 0.708333 0 0.216667 0.750000 0 0.216667 0.791667 0 0.216667 0.833333 0 0.216667 0.875000 0 0.216667 0.916667 0 0.216667 0.958333 0 0.216667 1.000000 0 0.225000 0 0 0.225000 0.041667 0 0.225000 0.083333 0 0.225000 0.125000 0 0.225000 0.166667 0 0.225000 0.208333 0 0.225000 0.250000 0 0.225000 0.291667 0 0.225000 0.333333 0 0.225000 0.375000 0 0.225000 0.416667 0 0.225000 0.458333 0 0.225000 0.500000 0 0.225000 0.541667 0 0.225000 0.583333 0 0.225000 0.625000 0 0.225000 0.666667 0 0.225000 0.708333 0 0.225000 0.750000 0 0.225000 0.791667 0 0.225000 0.833333 0 0.225000 0.875000 0 0.225000 0.916667 0 0.225000 0.958333 0 0.225000 1.000000 0 0.233333 0 0 0.233333 0.041667 0 0.233333 0.083333 0 0.233333 0.125000 0 0.233333 0.166667 0 0.233333 0.208333 0 0.233333 0.250000 0 0.233333 0.291667 0 0.233333 0.333333 0 0.233333 0.375000 0 0.233333 0.416667 0 0.233333 0.458333 0 0.233333 0.500000 0 0.233333 0.541667 0 0.233333 0.583333 0 0.233333 0.625000 0 0.233333 0.666667 0 0.233333 0.708333 0 0.233333 0.750000 0 0.233333 0.791667 0 0.233333 0.833333 0 0.233333 0.875000 0 0.233333 0.916667 0 0.233333 0.958333 0 0.233333 1.000000 0 0.241667 0 0 0.241667 0.041667 0 0.241667 0.083333 0 0.241667 0.125000 0 0.241667 0.166667 0 0.241667 0.208333 0 0.241667 0.250000 0 0.241667 0.291667 0 0.241667 0.333333 0 0.241667 0.375000 0 0.241667 0.416667 0 0.241667 0.458333 0 0.241667 0.500000 0 0.241667 0.541667 0 0.241667 0.583333 0 0.241667 0.625000 0 0.241667 0.666667 0 0.241667 0.708333 0 0.241667 0.750000 0 0.241667 0.791667 0 0.241667 0.833333 0 0.241667 0.875000 0 0.241667 0.916667 0 0.241667 0.958333 0 0.241667 1.000000 0 0.250000 0 0 0.250000 0.041667 0 0.250000 0.083333 0 0.250000 0.125000 0 0.250000 0.166667 0 0.250000 0.208333 0 0.250000 0.250000 0 0.250000 0.291667 0 0.250000 0.333333 0 0.250000 0.375000 0 0.250000 0.416667 0 0.250000 0.458333 0 0.250000 0.500000 0 0.250000 0.541667 0 0.250000 0.583333 0 0.250000 0.625000 0 0.250000 0.666667 0 0.250000 0.708333 0 0.250000 0.750000 0 0.250000 0.791667 0 0.250000 0.833333 0 0.250000 0.875000 0 0.250000 0.916667 0 0.250000 0.958333 0 0.250000 1.000000 0 0.258333 0 0 0.258333 0.041667 0 0.258333 0.083333 0 0.258333 0.125000 0 0.258333 0.166667 0 0.258333 0.208333 0 0.258333 0.250000 0 0.258333 0.291667 0 0.258333 0.333333 0 0.258333 0.375000 0 0.258333 0.416667 0 0.258333 0.458333 0 0.258333 0.500000 0 0.258333 0.541667 0 0.258333 0.583333 0 0.258333 0.625000 0 0.258333 0.666667 0 0.258333 0.708333 0 0.258333 0.750000 0 0.258333 0.791667 0 0.258333 0.833333 0 0.258333 0.875000 0 0.258333 0.916667 0 0.258333 0.958333 0 0.258333 1.000000 0 0.266667 0 0 0.266667 0.041667 0 0.266667 0.083333 0 0.266667 0.125000 0 0.266667 0.166667 0 0.266667 0.208333 0 0.266667 0.250000 0 0.266667 0.291667 0 0.266667 0.333333 0 0.266667 0.375000 0 0.266667 0.416667 0 0.266667 0.458333 0 0.266667 0.500000 0 0.266667 0.541667 0 0.266667 0.583333 0 0.266667 0.625000 0 0.266667 0.666667 0 0.266667 0.708333 0 0.266667 0.750000 0 0.266667 0.791667 0 0.266667 0.833333 0 0.266667 0.875000 0 0.266667 0.916667 0 0.266667 0.958333 0 0.266667 1.000000 0 0.275000 0 0 0.275000 0.041667 0 0.275000 0.083333 0 0.275000 0.125000 0 0.275000 0.166667 0 0.275000 0.208333 0 0.275000 0.250000 0 0.275000 0.291667 0 0.275000 0.333333 0 0.275000 0.375000 0 0.275000 0.416667 0 0.275000 0.458333 0 0.275000 0.500000 0 0.275000 0.541667 0 0.275000 0.583333 0 0.275000 0.625000 0 0.275000 0.666667 0 0.275000 0.708333 0 0.275000 0.750000 0 0.275000 0.791667 0 0.275000 0.833333 0 0.275000 0.875000 0 0.275000 0.916667 0 0.275000 0.958333 0 0.275000 1.000000 0 0.283333 0 0 0.283333 0.041667 0 0.283333 0.083333 0 0.283333 0.125000 0 0.283333 0.166667 0 0.283333 0.208333 0 0.283333 0.250000 0 0.283333 0.291667 0 0.283333 0.333333 0 0.283333 0.375000 0 0.283333 0.416667 0 0.283333 0.458333 0 0.283333 0.500000 0 0.283333 0.541667 0 0.283333 0.583333 0 0.283333 0.625000 0 0.283333 0.666667 0 0.283333 0.708333 0 0.283333 0.750000 0 0.283333 0.791667 0 0.283333 0.833333 0 0.283333 0.875000 0 0.283333 0.916667 0 0.283333 0.958333 0 0.283333 1.000000 0 0.291667 0 0 0.291667 0.041667 0 0.291667 0.083333 0 0.291667 0.125000 0 0.291667 0.166667 0 0.291667 0.208333 0 0.291667 0.250000 0 0.291667 0.291667 0 0.291667 0.333333 0 0.291667 0.375000 0 0.291667 0.416667 0 0.291667 0.458333 0 0.291667 0.500000 0 0.291667 0.541667 0 0.291667 0.583333 0 0.291667 0.625000 0 0.291667 0.666667 0 0.291667 0.708333 0 0.291667 0.750000 0 0.291667 0.791667 0 0.291667 0.833333 0 0.291667 0.875000 0 0.291667 0.916667 0 0.291667 0.958333 0 0.291667 1.000000 0 0.300000 0 0 0.300000 0.041667 0 0.300000 0.083333 0 0.300000 0.125000 0 0.300000 0.166667 0 0.300000 0.208333 0 0.300000 0.250000 0 0.300000 0.291667 0 0.300000 0.333333 0 0.300000 0.375000 0 0.300000 0.416667 0 0.300000 0.458333 0 0.300000 0.500000 0 0.300000 0.541667 0 0.300000 0.583333 0 0.300000 0.625000 0 0.300000 0.666667 0 0.300000 0.708333 0 0.300000 0.750000 0 0.300000 0.791667 0 0.300000 0.833333 0 0.300000 0.875000 0 0.300000 0.916667 0 0.300000 0.958333 0 0.300000 1.000000 0 0.308333 0 0 0.308333 0.041667 0 0.308333 0.083333 0 0.308333 0.125000 0 0.308333 0.166667 0 0.308333 0.208333 0 0.308333 0.250000 0 0.308333 0.291667 0 0.308333 0.333333 0 0.308333 0.375000 0 0.308333 0.416667 0 0.308333 0.458333 0 0.308333 0.500000 0 0.308333 0.541667 0 0.308333 0.583333 0 0.308333 0.625000 0 0.308333 0.666667 0 0.308333 0.708333 0 0.308333 0.750000 0 0.308333 0.791667 0 0.308333 0.833333 0 0.308333 0.875000 0 0.308333 0.916667 0 0.308333 0.958333 0 0.308333 1.000000 0 0.316666 0 0 0.316666 0.041667 0 0.316666 0.083333 0 0.316666 0.125000 0 0.316666 0.166667 0 0.316666 0.208333 0 0.316666 0.250000 0 0.316666 0.291667 0 0.316666 0.333333 0 0.316666 0.375000 0 0.316666 0.416667 0 0.316666 0.458333 0 0.316666 0.500000 0 0.316666 0.541667 0 0.316666 0.583333 0 0.316666 0.625000 0 0.316666 0.666667 0 0.316666 0.708333 0 0.316666 0.750000 0 0.316666 0.791667 0 0.316666 0.833333 0 0.316666 0.875000 0 0.316666 0.916667 0 0.316666 0.958333 0 0.316666 1.000000 0 0.325000 0 0 0.325000 0.041667 0 0.325000 0.083333 0 0.325000 0.125000 0 0.325000 0.166667 0 0.325000 0.208333 0 0.325000 0.250000 0 0.325000 0.291667 0 0.325000 0.333333 0 0.325000 0.375000 0 0.325000 0.416667 0 0.325000 0.458333 0 0.325000 0.500000 0 0.325000 0.541667 0 0.325000 0.583333 0 0.325000 0.625000 0 0.325000 0.666667 0 0.325000 0.708333 0 0.325000 0.750000 0 0.325000 0.791667 0 0.325000 0.833333 0 0.325000 0.875000 0 0.325000 0.916667 0 0.325000 0.958333 0 0.325000 1.000000 0 0.333333 0 0 0.333333 0.041667 0 0.333333 0.083333 0 0.333333 0.125000 0 0.333333 0.166667 0 0.333333 0.208333 0 0.333333 0.250000 0 0.333333 0.291667 0 0.333333 0.333333 0 0.333333 0.375000 0 0.333333 0.416667 0 0.333333 0.458333 0 0.333333 0.500000 0 0.333333 0.541667 0 0.333333 0.583333 0 0.333333 0.625000 0 0.333333 0.666667 0 0.333333 0.708333 0 0.333333 0.750000 0 0.333333 0.791667 0 0.333333 0.833333 0 0.333333 0.875000 0 0.333333 0.916667 0 0.333333 0.958333 0 0.333333 1.000000 0 0.341666 0 0 0.341666 0.041667 0 0.341666 0.083333 0 0.341666 0.125000 0 0.341666 0.166667 0 0.341666 0.208333 0 0.341666 0.250000 0 0.341666 0.291667 0 0.341666 0.333333 0 0.341666 0.375000 0 0.341666 0.416667 0 0.341666 0.458333 0 0.341666 0.500000 0 0.341666 0.541667 0 0.341666 0.583333 0 0.341666 0.625000 0 0.341666 0.666667 0 0.341666 0.708333 0 0.341666 0.750000 0 0.341666 0.791667 0 0.341666 0.833333 0 0.341666 0.875000 0 0.341666 0.916667 0 0.341666 0.958333 0 0.341666 1.000000 0 0.350000 0 0 0.350000 0.041667 0 0.350000 0.083333 0 0.350000 0.125000 0 0.350000 0.166667 0 0.350000 0.208333 0 0.350000 0.250000 0 0.350000 0.291667 0 0.350000 0.333333 0 0.350000 0.375000 0 0.350000 0.416667 0 0.350000 0.458333 0 0.350000 0.500000 0 0.350000 0.541667 0 0.350000 0.583333 0 0.350000 0.625000 0 0.350000 0.666667 0 0.350000 0.708333 0 0.350000 0.750000 0 0.350000 0.791667 0 0.350000 0.833333 0 0.350000 0.875000 0 0.350000 0.916667 0 0.350000 0.958333 0 0.350000 1.000000 0 0.358333 0 0 0.358333 0.041667 0 0.358333 0.083333 0 0.358333 0.125000 0 0.358333 0.166667 0 0.358333 0.208333 0 0.358333 0.250000 0 0.358333 0.291667 0 0.358333 0.333333 0 0.358333 0.375000 0 0.358333 0.416667 0 0.358333 0.458333 0 0.358333 0.500000 0 0.358333 0.541667 0 0.358333 0.583333 0 0.358333 0.625000 0 0.358333 0.666667 0 0.358333 0.708333 0 0.358333 0.750000 0 0.358333 0.791667 0 0.358333 0.833333 0 0.358333 0.875000 0 0.358333 0.916667 0 0.358333 0.958333 0 0.358333 1.000000 0 0.366666 0 0 0.366666 0.041667 0 0.366666 0.083333 0 0.366666 0.125000 0 0.366666 0.166667 0 0.366666 0.208333 0 0.366666 0.250000 0 0.366666 0.291667 0 0.366666 0.333333 0 0.366666 0.375000 0 0.366666 0.416667 0 0.366666 0.458333 0 0.366666 0.500000 0 0.366666 0.541667 0 0.366666 0.583333 0 0.366666 0.625000 0 0.366666 0.666667 0 0.366666 0.708333 0 0.366666 0.750000 0 0.366666 0.791667 0 0.366666 0.833333 0 0.366666 0.875000 0 0.366666 0.916667 0 0.366666 0.958333 0 0.366666 1.000000 0 0.375000 0 0 0.375000 0.041667 0 0.375000 0.083333 0 0.375000 0.125000 0 0.375000 0.166667 0 0.375000 0.208333 0 0.375000 0.250000 0 0.375000 0.291667 0 0.375000 0.333333 0 0.375000 0.375000 0 0.375000 0.416667 0 0.375000 0.458333 0 0.375000 0.500000 0 0.375000 0.541667 0 0.375000 0.583333 0 0.375000 0.625000 0 0.375000 0.666667 0 0.375000 0.708333 0 0.375000 0.750000 0 0.375000 0.791667 0 0.375000 0.833333 0 0.375000 0.875000 0 0.375000 0.916667 0 0.375000 0.958333 0 0.375000 1.000000 0 0.383333 0 0 0.383333 0.041667 0 0.383333 0.083333 0 0.383333 0.125000 0 0.383333 0.166667 0 0.383333 0.208333 0 0.383333 0.250000 0 0.383333 0.291667 0 0.383333 0.333333 0 0.383333 0.375000 0 0.383333 0.416667 0 0.383333 0.458333 0 0.383333 0.500000 0 0.383333 0.541667 0 0.383333 0.583333 0 0.383333 0.625000 0 0.383333 0.666667 0 0.383333 0.708333 0 0.383333 0.750000 0 0.383333 0.791667 0 0.383333 0.833333 0 0.383333 0.875000 0 0.383333 0.916667 0 0.383333 0.958333 0 0.383333 1.000000 0 0.391666 0 0 0.391666 0.041667 0 0.391666 0.083333 0 0.391666 0.125000 0 0.391666 0.166667 0 0.391666 0.208333 0 0.391666 0.250000 0 0.391666 0.291667 0 0.391666 0.333333 0 0.391666 0.375000 0 0.391666 0.416667 0 0.391666 0.458333 0 0.391666 0.500000 0 0.391666 0.541667 0 0.391666 0.583333 0 0.391666 0.625000 0 0.391666 0.666667 0 0.391666 0.708333 0 0.391666 0.750000 0 0.391666 0.791667 0 0.391666 0.833333 0 0.391666 0.875000 0 0.391666 0.916667 0 0.391666 0.958333 0 0.391666 1.000000 0 0.400000 0 0 0.400000 0.041667 0 0.400000 0.083333 0 0.400000 0.125000 0 0.400000 0.166667 0 0.400000 0.208333 0 0.400000 0.250000 0 0.400000 0.291667 0 0.400000 0.333333 0 0.400000 0.375000 0 0.400000 0.416667 0 0.400000 0.458333 0 0.400000 0.500000 0 0.400000 0.541667 0 0.400000 0.583333 0 0.400000 0.625000 0 0.400000 0.666667 0 0.400000 0.708333 0 0.400000 0.750000 0 0.400000 0.791667 0 0.400000 0.833333 0 0.400000 0.875000 0 0.400000 0.916667 0 0.400000 0.958333 0 0.400000 1.000000 0 0.408333 0 0 0.408333 0.041667 0 0.408333 0.083333 0 0.408333 0.125000 0 0.408333 0.166667 0 0.408333 0.208333 0 0.408333 0.250000 0 0.408333 0.291667 0 0.408333 0.333333 0 0.408333 0.375000 0 0.408333 0.416667 0 0.408333 0.458333 0 0.408333 0.500000 0 0.408333 0.541667 0 0.408333 0.583333 0 0.408333 0.625000 0 0.408333 0.666667 0 0.408333 0.708333 0 0.408333 0.750000 0 0.408333 0.791667 0 0.408333 0.833333 0 0.408333 0.875000 0 0.408333 0.916667 0 0.408333 0.958333 0 0.408333 1.000000 0 0.416666 0 0 0.416666 0.041667 0 0.416666 0.083333 0 0.416666 0.125000 0 0.416666 0.166667 0 0.416666 0.208333 0 0.416666 0.250000 0 0.416666 0.291667 0 0.416666 0.333333 0 0.416666 0.375000 0 0.416666 0.416667 0 0.416666 0.458333 0 0.416666 0.500000 0 0.416666 0.541667 0 0.416666 0.583333 0 0.416666 0.625000 0 0.416666 0.666667 0 0.416666 0.708333 0 0.416666 0.750000 0 0.416666 0.791667 0 0.416666 0.833333 0 0.416666 0.875000 0 0.416666 0.916667 0 0.416666 0.958333 0 0.416666 1.000000 0 0.425000 0 0 0.425000 0.041667 0 0.425000 0.083333 0 0.425000 0.125000 0 0.425000 0.166667 0 0.425000 0.208333 0 0.425000 0.250000 0 0.425000 0.291667 0 0.425000 0.333333 0 0.425000 0.375000 0 0.425000 0.416667 0 0.425000 0.458333 0 0.425000 0.500000 0 0.425000 0.541667 0 0.425000 0.583333 0 0.425000 0.625000 0 0.425000 0.666667 0 0.425000 0.708333 0 0.425000 0.750000 0 0.425000 0.791667 0 0.425000 0.833333 0 0.425000 0.875000 0 0.425000 0.916667 0 0.425000 0.958333 0 0.425000 1.000000 0 0.433333 0 0 0.433333 0.041667 0 0.433333 0.083333 0 0.433333 0.125000 0 0.433333 0.166667 0 0.433333 0.208333 0 0.433333 0.250000 0 0.433333 0.291667 0 0.433333 0.333333 0 0.433333 0.375000 0 0.433333 0.416667 0 0.433333 0.458333 0 0.433333 0.500000 0 0.433333 0.541667 0 0.433333 0.583333 0 0.433333 0.625000 0 0.433333 0.666667 0 0.433333 0.708333 0 0.433333 0.750000 0 0.433333 0.791667 0 0.433333 0.833333 0 0.433333 0.875000 0 0.433333 0.916667 0 0.433333 0.958333 0 0.433333 1.000000 0 0.441666 0 0 0.441666 0.041667 0 0.441666 0.083333 0 0.441666 0.125000 0 0.441666 0.166667 0 0.441666 0.208333 0 0.441666 0.250000 0 0.441666 0.291667 0 0.441666 0.333333 0 0.441666 0.375000 0 0.441666 0.416667 0 0.441666 0.458333 0 0.441666 0.500000 0 0.441666 0.541667 0 0.441666 0.583333 0 0.441666 0.625000 0 0.441666 0.666667 0 0.441666 0.708333 0 0.441666 0.750000 0 0.441666 0.791667 0 0.441666 0.833333 0 0.441666 0.875000 0 0.441666 0.916667 0 0.441666 0.958333 0 0.441666 1.000000 0 0.450000 0 0 0.450000 0.041667 0 0.450000 0.083333 0 0.450000 0.125000 0 0.450000 0.166667 0 0.450000 0.208333 0 0.450000 0.250000 0 0.450000 0.291667 0 0.450000 0.333333 0 0.450000 0.375000 0 0.450000 0.416667 0 0.450000 0.458333 0 0.450000 0.500000 0 0.450000 0.541667 0 0.450000 0.583333 0 0.450000 0.625000 0 0.450000 0.666667 0 0.450000 0.708333 0 0.450000 0.750000 0 0.450000 0.791667 0 0.450000 0.833333 0 0.450000 0.875000 0 0.450000 0.916667 0 0.450000 0.958333 0 0.450000 1.000000 0 0.458333 0 0 0.458333 0.041667 0 0.458333 0.083333 0 0.458333 0.125000 0 0.458333 0.166667 0 0.458333 0.208333 0 0.458333 0.250000 0 0.458333 0.291667 0 0.458333 0.333333 0 0.458333 0.375000 0 0.458333 0.416667 0 0.458333 0.458333 0 0.458333 0.500000 0 0.458333 0.541667 0 0.458333 0.583333 0 0.458333 0.625000 0 0.458333 0.666667 0 0.458333 0.708333 0 0.458333 0.750000 0 0.458333 0.791667 0 0.458333 0.833333 0 0.458333 0.875000 0 0.458333 0.916667 0 0.458333 0.958333 0 0.458333 1.000000 0 0.466666 0 0 0.466666 0.041667 0 0.466666 0.083333 0 0.466666 0.125000 0 0.466666 0.166667 0 0.466666 0.208333 0 0.466666 0.250000 0 0.466666 0.291667 0 0.466666 0.333333 0 0.466666 0.375000 0 0.466666 0.416667 0 0.466666 0.458333 0 0.466666 0.500000 0 0.466666 0.541667 0 0.466666 0.583333 0 0.466666 0.625000 0 0.466666 0.666667 0 0.466666 0.708333 0 0.466666 0.750000 0 0.466666 0.791667 0 0.466666 0.833333 0 0.466666 0.875000 0 0.466666 0.916667 0 0.466666 0.958333 0 0.466666 1.000000 0 0.475000 0 0 0.475000 0.041667 0 0.475000 0.083333 0 0.475000 0.125000 0 0.475000 0.166667 0 0.475000 0.208333 0 0.475000 0.250000 0 0.475000 0.291667 0 0.475000 0.333333 0 0.475000 0.375000 0 0.475000 0.416667 0 0.475000 0.458333 0 0.475000 0.500000 0 0.475000 0.541667 0 0.475000 0.583333 0 0.475000 0.625000 0 0.475000 0.666667 0 0.475000 0.708333 0 0.475000 0.750000 0 0.475000 0.791667 0 0.475000 0.833333 0 0.475000 0.875000 0 0.475000 0.916667 0 0.475000 0.958333 0 0.475000 1.000000 0 0.483333 0 0 0.483333 0.041667 0 0.483333 0.083333 0 0.483333 0.125000 0 0.483333 0.166667 0 0.483333 0.208333 0 0.483333 0.250000 0 0.483333 0.291667 0 0.483333 0.333333 0 0.483333 0.375000 0 0.483333 0.416667 0 0.483333 0.458333 0 0.483333 0.500000 0 0.483333 0.541667 0 0.483333 0.583333 0 0.483333 0.625000 0 0.483333 0.666667 0 0.483333 0.708333 0 0.483333 0.750000 0 0.483333 0.791667 0 0.483333 0.833333 0 0.483333 0.875000 0 0.483333 0.916667 0 0.483333 0.958333 0 0.483333 1.000000 0 0.491666 0 0 0.491666 0.041667 0 0.491666 0.083333 0 0.491666 0.125000 0 0.491666 0.166667 0 0.491666 0.208333 0 0.491666 0.250000 0 0.491666 0.291667 0 0.491666 0.333333 0 0.491666 0.375000 0 0.491666 0.416667 0 0.491666 0.458333 0 0.491666 0.500000 0 0.491666 0.541667 0 0.491666 0.583333 0 0.491666 0.625000 0 0.491666 0.666667 0 0.491666 0.708333 0 0.491666 0.750000 0 0.491666 0.791667 0 0.491666 0.833333 0 0.491666 0.875000 0 0.491666 0.916667 0 0.491666 0.958333 0 0.491666 1.000000 0 0.500000 0 0 0.500000 0.041667 0 0.500000 0.083333 0 0.500000 0.125000 0 0.500000 0.166667 0 0.500000 0.208333 0 0.500000 0.250000 0 0.500000 0.291667 0 0.500000 0.333333 0 0.500000 0.375000 0 0.500000 0.416667 0 0.500000 0.458333 0 0.500000 0.500000 0 0.500000 0.541667 0 0.500000 0.583333 0 0.500000 0.625000 0 0.500000 0.666667 0 0.500000 0.708333 0 0.500000 0.750000 0 0.500000 0.791667 0 0.500000 0.833333 0 0.500000 0.875000 0 0.500000 0.916667 0 0.500000 0.958333 0 0.500000 1.000000 0 0.508333 0 0 0.508333 0.041667 0 0.508333 0.083333 0 0.508333 0.125000 0 0.508333 0.166667 0 0.508333 0.208333 0 0.508333 0.250000 0 0.508333 0.291667 0 0.508333 0.333333 0 0.508333 0.375000 0 0.508333 0.416667 0 0.508333 0.458333 0 0.508333 0.500000 0 0.508333 0.541667 0 0.508333 0.583333 0 0.508333 0.625000 0 0.508333 0.666667 0 0.508333 0.708333 0 0.508333 0.750000 0 0.508333 0.791667 0 0.508333 0.833333 0 0.508333 0.875000 0 0.508333 0.916667 0 0.508333 0.958333 0 0.508333 1.000000 0 0.516666 0 0 0.516666 0.041667 0 0.516666 0.083333 0 0.516666 0.125000 0 0.516666 0.166667 0 0.516666 0.208333 0 0.516666 0.250000 0 0.516666 0.291667 0 0.516666 0.333333 0 0.516666 0.375000 0 0.516666 0.416667 0 0.516666 0.458333 0 0.516666 0.500000 0 0.516666 0.541667 0 0.516666 0.583333 0 0.516666 0.625000 0 0.516666 0.666667 0 0.516666 0.708333 0 0.516666 0.750000 0 0.516666 0.791667 0 0.516666 0.833333 0 0.516666 0.875000 0 0.516666 0.916667 0 0.516666 0.958333 0 0.516666 1.000000 0 0.525000 0 0 0.525000 0.041667 0 0.525000 0.083333 0 0.525000 0.125000 0 0.525000 0.166667 0 0.525000 0.208333 0 0.525000 0.250000 0 0.525000 0.291667 0 0.525000 0.333333 0 0.525000 0.375000 0 0.525000 0.416667 0 0.525000 0.458333 0 0.525000 0.500000 0 0.525000 0.541667 0 0.525000 0.583333 0 0.525000 0.625000 0 0.525000 0.666667 0 0.525000 0.708333 0 0.525000 0.750000 0 0.525000 0.791667 0 0.525000 0.833333 0 0.525000 0.875000 0 0.525000 0.916667 0 0.525000 0.958333 0 0.525000 1.000000 0 0.533333 0 0 0.533333 0.041667 0 0.533333 0.083333 0 0.533333 0.125000 0 0.533333 0.166667 0 0.533333 0.208333 0 0.533333 0.250000 0 0.533333 0.291667 0 0.533333 0.333333 0 0.533333 0.375000 0 0.533333 0.416667 0 0.533333 0.458333 0 0.533333 0.500000 0 0.533333 0.541667 0 0.533333 0.583333 0 0.533333 0.625000 0 0.533333 0.666667 0 0.533333 0.708333 0 0.533333 0.750000 0 0.533333 0.791667 0 0.533333 0.833333 0 0.533333 0.875000 0 0.533333 0.916667 0 0.533333 0.958333 0 0.533333 1.000000 0 0.541666 0 0 0.541666 0.041667 0 0.541666 0.083333 0 0.541666 0.125000 0 0.541666 0.166667 0 0.541666 0.208333 0 0.541666 0.250000 0 0.541666 0.291667 0 0.541666 0.333333 0 0.541666 0.375000 0 0.541666 0.416667 0 0.541666 0.458333 0 0.541666 0.500000 0 0.541666 0.541667 0 0.541666 0.583333 0 0.541666 0.625000 0 0.541666 0.666667 0 0.541666 0.708333 0 0.541666 0.750000 0 0.541666 0.791667 0 0.541666 0.833333 0 0.541666 0.875000 0 0.541666 0.916667 0 0.541666 0.958333 0 0.541666 1.000000 0 0.550000 0 0 0.550000 0.041667 0 0.550000 0.083333 0 0.550000 0.125000 0 0.550000 0.166667 0 0.550000 0.208333 0 0.550000 0.250000 0 0.550000 0.291667 0 0.550000 0.333333 0 0.550000 0.375000 0 0.550000 0.416667 0 0.550000 0.458333 0 0.550000 0.500000 0 0.550000 0.541667 0 0.550000 0.583333 0 0.550000 0.625000 0 0.550000 0.666667 0 0.550000 0.708333 0 0.550000 0.750000 0 0.550000 0.791667 0 0.550000 0.833333 0 0.550000 0.875000 0 0.550000 0.916667 0 0.550000 0.958333 0 0.550000 1.000000 0 0.558333 0 0 0.558333 0.041667 0 0.558333 0.083333 0 0.558333 0.125000 0 0.558333 0.166667 0 0.558333 0.208333 0 0.558333 0.250000 0 0.558333 0.291667 0 0.558333 0.333333 0 0.558333 0.375000 0 0.558333 0.416667 0 0.558333 0.458333 0 0.558333 0.500000 0 0.558333 0.541667 0 0.558333 0.583333 0 0.558333 0.625000 0 0.558333 0.666667 0 0.558333 0.708333 0 0.558333 0.750000 0 0.558333 0.791667 0 0.558333 0.833333 0 0.558333 0.875000 0 0.558333 0.916667 0 0.558333 0.958333 0 0.558333 1.000000 0 0.566666 0 0 0.566666 0.041667 0 0.566666 0.083333 0 0.566666 0.125000 0 0.566666 0.166667 0 0.566666 0.208333 0 0.566666 0.250000 0 0.566666 0.291667 0 0.566666 0.333333 0 0.566666 0.375000 0 0.566666 0.416667 0 0.566666 0.458333 0 0.566666 0.500000 0 0.566666 0.541667 0 0.566666 0.583333 0 0.566666 0.625000 0 0.566666 0.666667 0 0.566666 0.708333 0 0.566666 0.750000 0 0.566666 0.791667 0 0.566666 0.833333 0 0.566666 0.875000 0 0.566666 0.916667 0 0.566666 0.958333 0 0.566666 1.000000 0 0.575000 0 0 0.575000 0.041667 0 0.575000 0.083333 0 0.575000 0.125000 0 0.575000 0.166667 0 0.575000 0.208333 0 0.575000 0.250000 0 0.575000 0.291667 0 0.575000 0.333333 0 0.575000 0.375000 0 0.575000 0.416667 0 0.575000 0.458333 0 0.575000 0.500000 0 0.575000 0.541667 0 0.575000 0.583333 0 0.575000 0.625000 0 0.575000 0.666667 0 0.575000 0.708333 0 0.575000 0.750000 0 0.575000 0.791667 0 0.575000 0.833333 0 0.575000 0.875000 0 0.575000 0.916667 0 0.575000 0.958333 0 0.575000 1.000000 0 0.583333 0 0 0.583333 0.041667 0 0.583333 0.083333 0 0.583333 0.125000 0 0.583333 0.166667 0 0.583333 0.208333 0 0.583333 0.250000 0 0.583333 0.291667 0 0.583333 0.333333 0 0.583333 0.375000 0 0.583333 0.416667 0 0.583333 0.458333 0 0.583333 0.500000 0 0.583333 0.541667 0 0.583333 0.583333 0 0.583333 0.625000 0 0.583333 0.666667 0 0.583333 0.708333 0 0.583333 0.750000 0 0.583333 0.791667 0 0.583333 0.833333 0 0.583333 0.875000 0 0.583333 0.916667 0 0.583333 0.958333 0 0.583333 1.000000 0 0.591666 0 0 0.591666 0.041667 0 0.591666 0.083333 0 0.591666 0.125000 0 0.591666 0.166667 0 0.591666 0.208333 0 0.591666 0.250000 0 0.591666 0.291667 0 0.591666 0.333333 0 0.591666 0.375000 0 0.591666 0.416667 0 0.591666 0.458333 0 0.591666 0.500000 0 0.591666 0.541667 0 0.591666 0.583333 0 0.591666 0.625000 0 0.591666 0.666667 0 0.591666 0.708333 0 0.591666 0.750000 0 0.591666 0.791667 0 0.591666 0.833333 0 0.591666 0.875000 0 0.591666 0.916667 0 0.591666 0.958333 0 0.591666 1.000000 0 0.599999 0 0 0.599999 0.041667 0 0.599999 0.083333 0 0.599999 0.125000 0 0.599999 0.166667 0 0.599999 0.208333 0 0.599999 0.250000 0 0.599999 0.291667 0 0.599999 0.333333 0 0.599999 0.375000 0 0.599999 0.416667 0 0.599999 0.458333 0 0.599999 0.500000 0 0.599999 0.541667 0 0.599999 0.583333 0 0.599999 0.625000 0 0.599999 0.666667 0 0.599999 0.708333 0 0.599999 0.750000 0 0.599999 0.791667 0 0.599999 0.833333 0 0.599999 0.875000 0 0.599999 0.916667 0 0.599999 0.958333 0 0.599999 1.000000 0 0.608333 0 0 0.608333 0.041667 0 0.608333 0.083333 0 0.608333 0.125000 0 0.608333 0.166667 0 0.608333 0.208333 0 0.608333 0.250000 0 0.608333 0.291667 0 0.608333 0.333333 0 0.608333 0.375000 0 0.608333 0.416667 0 0.608333 0.458333 0 0.608333 0.500000 0 0.608333 0.541667 0 0.608333 0.583333 0 0.608333 0.625000 0 0.608333 0.666667 0 0.608333 0.708333 0 0.608333 0.750000 0 0.608333 0.791667 0 0.608333 0.833333 0 0.608333 0.875000 0 0.608333 0.916667 0 0.608333 0.958333 0 0.608333 1.000000 0 0.616666 0 0 0.616666 0.041667 0 0.616666 0.083333 0 0.616666 0.125000 0 0.616666 0.166667 0 0.616666 0.208333 0 0.616666 0.250000 0 0.616666 0.291667 0 0.616666 0.333333 0 0.616666 0.375000 0 0.616666 0.416667 0 0.616666 0.458333 0 0.616666 0.500000 0 0.616666 0.541667 0 0.616666 0.583333 0 0.616666 0.625000 0 0.616666 0.666667 0 0.616666 0.708333 0 0.616666 0.750000 0 0.616666 0.791667 0 0.616666 0.833333 0 0.616666 0.875000 0 0.616666 0.916667 0 0.616666 0.958333 0 0.616666 1.000000 0 0.624999 0 0 0.624999 0.041667 0 0.624999 0.083333 0 0.624999 0.125000 0 0.624999 0.166667 0 0.624999 0.208333 0 0.624999 0.250000 0 0.624999 0.291667 0 0.624999 0.333333 0 0.624999 0.375000 0 0.624999 0.416667 0 0.624999 0.458333 0 0.624999 0.500000 0 0.624999 0.541667 0 0.624999 0.583333 0 0.624999 0.625000 0 0.624999 0.666667 0 0.624999 0.708333 0 0.624999 0.750000 0 0.624999 0.791667 0 0.624999 0.833333 0 0.624999 0.875000 0 0.624999 0.916667 0 0.624999 0.958333 0 0.624999 1.000000 0 0.633333 0 0 0.633333 0.041667 0 0.633333 0.083333 0 0.633333 0.125000 0 0.633333 0.166667 0 0.633333 0.208333 0 0.633333 0.250000 0 0.633333 0.291667 0 0.633333 0.333333 0 0.633333 0.375000 0 0.633333 0.416667 0 0.633333 0.458333 0 0.633333 0.500000 0 0.633333 0.541667 0 0.633333 0.583333 0 0.633333 0.625000 0 0.633333 0.666667 0 0.633333 0.708333 0 0.633333 0.750000 0 0.633333 0.791667 0 0.633333 0.833333 0 0.633333 0.875000 0 0.633333 0.916667 0 0.633333 0.958333 0 0.633333 1.000000 0 0.641666 0 0 0.641666 0.041667 0 0.641666 0.083333 0 0.641666 0.125000 0 0.641666 0.166667 0 0.641666 0.208333 0 0.641666 0.250000 0 0.641666 0.291667 0 0.641666 0.333333 0 0.641666 0.375000 0 0.641666 0.416667 0 0.641666 0.458333 0 0.641666 0.500000 0 0.641666 0.541667 0 0.641666 0.583333 0 0.641666 0.625000 0 0.641666 0.666667 0 0.641666 0.708333 0 0.641666 0.750000 0 0.641666 0.791667 0 0.641666 0.833333 0 0.641666 0.875000 0 0.641666 0.916667 0 0.641666 0.958333 0 0.641666 1.000000 0 0.649999 0 0 0.649999 0.041667 0 0.649999 0.083333 0 0.649999 0.125000 0 0.649999 0.166667 0 0.649999 0.208333 0 0.649999 0.250000 0 0.649999 0.291667 0 0.649999 0.333333 0 0.649999 0.375000 0 0.649999 0.416667 0 0.649999 0.458333 0 0.649999 0.500000 0 0.649999 0.541667 0 0.649999 0.583333 0 0.649999 0.625000 0 0.649999 0.666667 0 0.649999 0.708333 0 0.649999 0.750000 0 0.649999 0.791667 0 0.649999 0.833333 0 0.649999 0.875000 0 0.649999 0.916667 0 0.649999 0.958333 0 0.649999 1.000000 0 0.658333 0 0 0.658333 0.041667 0 0.658333 0.083333 0 0.658333 0.125000 0 0.658333 0.166667 0 0.658333 0.208333 0 0.658333 0.250000 0 0.658333 0.291667 0 0.658333 0.333333 0 0.658333 0.375000 0 0.658333 0.416667 0 0.658333 0.458333 0 0.658333 0.500000 0 0.658333 0.541667 0 0.658333 0.583333 0 0.658333 0.625000 0 0.658333 0.666667 0 0.658333 0.708333 0 0.658333 0.750000 0 0.658333 0.791667 0 0.658333 0.833333 0 0.658333 0.875000 0 0.658333 0.916667 0 0.658333 0.958333 0 0.658333 1.000000 0 0.666666 0 0 0.666666 0.041667 0 0.666666 0.083333 0 0.666666 0.125000 0 0.666666 0.166667 0 0.666666 0.208333 0 0.666666 0.250000 0 0.666666 0.291667 0 0.666666 0.333333 0 0.666666 0.375000 0 0.666666 0.416667 0 0.666666 0.458333 0 0.666666 0.500000 0 0.666666 0.541667 0 0.666666 0.583333 0 0.666666 0.625000 0 0.666666 0.666667 0 0.666666 0.708333 0 0.666666 0.750000 0 0.666666 0.791667 0 0.666666 0.833333 0 0.666666 0.875000 0 0.666666 0.916667 0 0.666666 0.958333 0 0.666666 1.000000 0 0.675000 0 0 0.675000 0.041667 0 0.675000 0.083333 0 0.675000 0.125000 0 0.675000 0.166667 0 0.675000 0.208333 0 0.675000 0.250000 0 0.675000 0.291667 0 0.675000 0.333333 0 0.675000 0.375000 0 0.675000 0.416667 0 0.675000 0.458333 0 0.675000 0.500000 0 0.675000 0.541667 0 0.675000 0.583333 0 0.675000 0.625000 0 0.675000 0.666667 0 0.675000 0.708333 0 0.675000 0.750000 0 0.675000 0.791667 0 0.675000 0.833333 0 0.675000 0.875000 0 0.675000 0.916667 0 0.675000 0.958333 0 0.675000 1.000000 0 0.683333 0 0 0.683333 0.041667 0 0.683333 0.083333 0 0.683333 0.125000 0 0.683333 0.166667 0 0.683333 0.208333 0 0.683333 0.250000 0 0.683333 0.291667 0 0.683333 0.333333 0 0.683333 0.375000 0 0.683333 0.416667 0 0.683333 0.458333 0 0.683333 0.500000 0 0.683333 0.541667 0 0.683333 0.583333 0 0.683333 0.625000 0 0.683333 0.666667 0 0.683333 0.708333 0 0.683333 0.750000 0 0.683333 0.791667 0 0.683333 0.833333 0 0.683333 0.875000 0 0.683333 0.916667 0 0.683333 0.958333 0 0.683333 1.000000 0 0.691666 0 0 0.691666 0.041667 0 0.691666 0.083333 0 0.691666 0.125000 0 0.691666 0.166667 0 0.691666 0.208333 0 0.691666 0.250000 0 0.691666 0.291667 0 0.691666 0.333333 0 0.691666 0.375000 0 0.691666 0.416667 0 0.691666 0.458333 0 0.691666 0.500000 0 0.691666 0.541667 0 0.691666 0.583333 0 0.691666 0.625000 0 0.691666 0.666667 0 0.691666 0.708333 0 0.691666 0.750000 0 0.691666 0.791667 0 0.691666 0.833333 0 0.691666 0.875000 0 0.691666 0.916667 0 0.691666 0.958333 0 0.691666 1.000000 0 0.700000 0 0 0.700000 0.041667 0 0.700000 0.083333 0 0.700000 0.125000 0 0.700000 0.166667 0 0.700000 0.208333 0 0.700000 0.250000 0 0.700000 0.291667 0 0.700000 0.333333 0 0.700000 0.375000 0 0.700000 0.416667 0 0.700000 0.458333 0 0.700000 0.500000 0 0.700000 0.541667 0 0.700000 0.583333 0 0.700000 0.625000 0 0.700000 0.666667 0 0.700000 0.708333 0 0.700000 0.750000 0 0.700000 0.791667 0 0.700000 0.833333 0 0.700000 0.875000 0 0.700000 0.916667 0 0.700000 0.958333 0 0.700000 1.000000 0 0.708333 0 0 0.708333 0.041667 0 0.708333 0.083333 0 0.708333 0.125000 0 0.708333 0.166667 0 0.708333 0.208333 0 0.708333 0.250000 0 0.708333 0.291667 0 0.708333 0.333333 0 0.708333 0.375000 0 0.708333 0.416667 0 0.708333 0.458333 0 0.708333 0.500000 0 0.708333 0.541667 0 0.708333 0.583333 0 0.708333 0.625000 0 0.708333 0.666667 0 0.708333 0.708333 0 0.708333 0.750000 0 0.708333 0.791667 0 0.708333 0.833333 0 0.708333 0.875000 0 0.708333 0.916667 0 0.708333 0.958333 0 0.708333 1.000000 0 0.716666 0 0 0.716666 0.041667 0 0.716666 0.083333 0 0.716666 0.125000 0 0.716666 0.166667 0 0.716666 0.208333 0 0.716666 0.250000 0 0.716666 0.291667 0 0.716666 0.333333 0 0.716666 0.375000 0 0.716666 0.416667 0 0.716666 0.458333 0 0.716666 0.500000 0 0.716666 0.541667 0 0.716666 0.583333 0 0.716666 0.625000 0 0.716666 0.666667 0 0.716666 0.708333 0 0.716666 0.750000 0 0.716666 0.791667 0 0.716666 0.833333 0 0.716666 0.875000 0 0.716666 0.916667 0 0.716666 0.958333 0 0.716666 1.000000 0 0.725000 0 0 0.725000 0.041667 0 0.725000 0.083333 0 0.725000 0.125000 0 0.725000 0.166667 0 0.725000 0.208333 0 0.725000 0.250000 0 0.725000 0.291667 0 0.725000 0.333333 0 0.725000 0.375000 0 0.725000 0.416667 0 0.725000 0.458333 0 0.725000 0.500000 0 0.725000 0.541667 0 0.725000 0.583333 0 0.725000 0.625000 0 0.725000 0.666667 0 0.725000 0.708333 0 0.725000 0.750000 0 0.725000 0.791667 0 0.725000 0.833333 0 0.725000 0.875000 0 0.725000 0.916667 0 0.725000 0.958333 0 0.725000 1.000000 0 0.733333 0 0 0.733333 0.041667 0 0.733333 0.083333 0 0.733333 0.125000 0 0.733333 0.166667 0 0.733333 0.208333 0 0.733333 0.250000 0 0.733333 0.291667 0 0.733333 0.333333 0 0.733333 0.375000 0 0.733333 0.416667 0 0.733333 0.458333 0 0.733333 0.500000 0 0.733333 0.541667 0 0.733333 0.583333 0 0.733333 0.625000 0 0.733333 0.666667 0 0.733333 0.708333 0 0.733333 0.750000 0 0.733333 0.791667 0 0.733333 0.833333 0 0.733333 0.875000 0 0.733333 0.916667 0 0.733333 0.958333 0 0.733333 1.000000 0 0.741666 0 0 0.741666 0.041667 0 0.741666 0.083333 0 0.741666 0.125000 0 0.741666 0.166667 0 0.741666 0.208333 0 0.741666 0.250000 0 0.741666 0.291667 0 0.741666 0.333333 0 0.741666 0.375000 0 0.741666 0.416667 0 0.741666 0.458333 0 0.741666 0.500000 0 0.741666 0.541667 0 0.741666 0.583333 0 0.741666 0.625000 0 0.741666 0.666667 0 0.741666 0.708333 0 0.741666 0.750000 0 0.741666 0.791667 0 0.741666 0.833333 0 0.741666 0.875000 0 0.741666 0.916667 0 0.741666 0.958333 0 0.741666 1.000000 0 0.750000 0 0 0.750000 0.041667 0 0.750000 0.083333 0 0.750000 0.125000 0 0.750000 0.166667 0 0.750000 0.208333 0 0.750000 0.250000 0 0.750000 0.291667 0 0.750000 0.333333 0 0.750000 0.375000 0 0.750000 0.416667 0 0.750000 0.458333 0 0.750000 0.500000 0 0.750000 0.541667 0 0.750000 0.583333 0 0.750000 0.625000 0 0.750000 0.666667 0 0.750000 0.708333 0 0.750000 0.750000 0 0.750000 0.791667 0 0.750000 0.833333 0 0.750000 0.875000 0 0.750000 0.916667 0 0.750000 0.958333 0 0.750000 1.000000 0 0.758333 0 0 0.758333 0.041667 0 0.758333 0.083333 0 0.758333 0.125000 0 0.758333 0.166667 0 0.758333 0.208333 0 0.758333 0.250000 0 0.758333 0.291667 0 0.758333 0.333333 0 0.758333 0.375000 0 0.758333 0.416667 0 0.758333 0.458333 0 0.758333 0.500000 0 0.758333 0.541667 0 0.758333 0.583333 0 0.758333 0.625000 0 0.758333 0.666667 0 0.758333 0.708333 0 0.758333 0.750000 0 0.758333 0.791667 0 0.758333 0.833333 0 0.758333 0.875000 0 0.758333 0.916667 0 0.758333 0.958333 0 0.758333 1.000000 0 0.766667 0 0 0.766667 0.041667 0 0.766667 0.083333 0 0.766667 0.125000 0 0.766667 0.166667 0 0.766667 0.208333 0 0.766667 0.250000 0 0.766667 0.291667 0 0.766667 0.333333 0 0.766667 0.375000 0 0.766667 0.416667 0 0.766667 0.458333 0 0.766667 0.500000 0 0.766667 0.541667 0 0.766667 0.583333 0 0.766667 0.625000 0 0.766667 0.666667 0 0.766667 0.708333 0 0.766667 0.750000 0 0.766667 0.791667 0 0.766667 0.833333 0 0.766667 0.875000 0 0.766667 0.916667 0 0.766667 0.958333 0 0.766667 1.000000 0 0.775000 0 0 0.775000 0.041667 0 0.775000 0.083333 0 0.775000 0.125000 0 0.775000 0.166667 0 0.775000 0.208333 0 0.775000 0.250000 0 0.775000 0.291667 0 0.775000 0.333333 0 0.775000 0.375000 0 0.775000 0.416667 0 0.775000 0.458333 0 0.775000 0.500000 0 0.775000 0.541667 0 0.775000 0.583333 0 0.775000 0.625000 0 0.775000 0.666667 0 0.775000 0.708333 0 0.775000 0.750000 0 0.775000 0.791667 0 0.775000 0.833333 0 0.775000 0.875000 0 0.775000 0.916667 0 0.775000 0.958333 0 0.775000 1.000000 0 0.783333 0 0 0.783333 0.041667 0 0.783333 0.083333 0 0.783333 0.125000 0 0.783333 0.166667 0 0.783333 0.208333 0 0.783333 0.250000 0 0.783333 0.291667 0 0.783333 0.333333 0 0.783333 0.375000 0 0.783333 0.416667 0 0.783333 0.458333 0 0.783333 0.500000 0 0.783333 0.541667 0 0.783333 0.583333 0 0.783333 0.625000 0 0.783333 0.666667 0 0.783333 0.708333 0 0.783333 0.750000 0 0.783333 0.791667 0 0.783333 0.833333 0 0.783333 0.875000 0 0.783333 0.916667 0 0.783333 0.958333 0 0.783333 1.000000 0 0.791667 0 0 0.791667 0.041667 0 0.791667 0.083333 0 0.791667 0.125000 0 0.791667 0.166667 0 0.791667 0.208333 0 0.791667 0.250000 0 0.791667 0.291667 0 0.791667 0.333333 0 0.791667 0.375000 0 0.791667 0.416667 0 0.791667 0.458333 0 0.791667 0.500000 0 0.791667 0.541667 0 0.791667 0.583333 0 0.791667 0.625000 0 0.791667 0.666667 0 0.791667 0.708333 0 0.791667 0.750000 0 0.791667 0.791667 0 0.791667 0.833333 0 0.791667 0.875000 0 0.791667 0.916667 0 0.791667 0.958333 0 0.791667 1.000000 0 0.800000 0 0 0.800000 0.041667 0 0.800000 0.083333 0 0.800000 0.125000 0 0.800000 0.166667 0 0.800000 0.208333 0 0.800000 0.250000 0 0.800000 0.291667 0 0.800000 0.333333 0 0.800000 0.375000 0 0.800000 0.416667 0 0.800000 0.458333 0 0.800000 0.500000 0 0.800000 0.541667 0 0.800000 0.583333 0 0.800000 0.625000 0 0.800000 0.666667 0 0.800000 0.708333 0 0.800000 0.750000 0 0.800000 0.791667 0 0.800000 0.833333 0 0.800000 0.875000 0 0.800000 0.916667 0 0.800000 0.958333 0 0.800000 1.000000 0 0.808333 0 0 0.808333 0.041667 0 0.808333 0.083333 0 0.808333 0.125000 0 0.808333 0.166667 0 0.808333 0.208333 0 0.808333 0.250000 0 0.808333 0.291667 0 0.808333 0.333333 0 0.808333 0.375000 0 0.808333 0.416667 0 0.808333 0.458333 0 0.808333 0.500000 0 0.808333 0.541667 0 0.808333 0.583333 0 0.808333 0.625000 0 0.808333 0.666667 0 0.808333 0.708333 0 0.808333 0.750000 0 0.808333 0.791667 0 0.808333 0.833333 0 0.808333 0.875000 0 0.808333 0.916667 0 0.808333 0.958333 0 0.808333 1.000000 0 0.816667 0 0 0.816667 0.041667 0 0.816667 0.083333 0 0.816667 0.125000 0 0.816667 0.166667 0 0.816667 0.208333 0 0.816667 0.250000 0 0.816667 0.291667 0 0.816667 0.333333 0 0.816667 0.375000 0 0.816667 0.416667 0 0.816667 0.458333 0 0.816667 0.500000 0 0.816667 0.541667 0 0.816667 0.583333 0 0.816667 0.625000 0 0.816667 0.666667 0 0.816667 0.708333 0 0.816667 0.750000 0 0.816667 0.791667 0 0.816667 0.833333 0 0.816667 0.875000 0 0.816667 0.916667 0 0.816667 0.958333 0 0.816667 1.000000 0 0.825000 0 0 0.825000 0.041667 0 0.825000 0.083333 0 0.825000 0.125000 0 0.825000 0.166667 0 0.825000 0.208333 0 0.825000 0.250000 0 0.825000 0.291667 0 0.825000 0.333333 0 0.825000 0.375000 0 0.825000 0.416667 0 0.825000 0.458333 0 0.825000 0.500000 0 0.825000 0.541667 0 0.825000 0.583333 0 0.825000 0.625000 0 0.825000 0.666667 0 0.825000 0.708333 0 0.825000 0.750000 0 0.825000 0.791667 0 0.825000 0.833333 0 0.825000 0.875000 0 0.825000 0.916667 0 0.825000 0.958333 0 0.825000 1.000000 0 0.833333 0 0 0.833333 0.041667 0 0.833333 0.083333 0 0.833333 0.125000 0 0.833333 0.166667 0 0.833333 0.208333 0 0.833333 0.250000 0 0.833333 0.291667 0 0.833333 0.333333 0 0.833333 0.375000 0 0.833333 0.416667 0 0.833333 0.458333 0 0.833333 0.500000 0 0.833333 0.541667 0 0.833333 0.583333 0 0.833333 0.625000 0 0.833333 0.666667 0 0.833333 0.708333 0 0.833333 0.750000 0 0.833333 0.791667 0 0.833333 0.833333 0 0.833333 0.875000 0 0.833333 0.916667 0 0.833333 0.958333 0 0.833333 1.000000 0 0.841667 0 0 0.841667 0.041667 0 0.841667 0.083333 0 0.841667 0.125000 0 0.841667 0.166667 0 0.841667 0.208333 0 0.841667 0.250000 0 0.841667 0.291667 0 0.841667 0.333333 0 0.841667 0.375000 0 0.841667 0.416667 0 0.841667 0.458333 0 0.841667 0.500000 0 0.841667 0.541667 0 0.841667 0.583333 0 0.841667 0.625000 0 0.841667 0.666667 0 0.841667 0.708333 0 0.841667 0.750000 0 0.841667 0.791667 0 0.841667 0.833333 0 0.841667 0.875000 0 0.841667 0.916667 0 0.841667 0.958333 0 0.841667 1.000000 0 0.850000 0 0 0.850000 0.041667 0 0.850000 0.083333 0 0.850000 0.125000 0 0.850000 0.166667 0 0.850000 0.208333 0 0.850000 0.250000 0 0.850000 0.291667 0 0.850000 0.333333 0 0.850000 0.375000 0 0.850000 0.416667 0 0.850000 0.458333 0 0.850000 0.500000 0 0.850000 0.541667 0 0.850000 0.583333 0 0.850000 0.625000 0 0.850000 0.666667 0 0.850000 0.708333 0 0.850000 0.750000 0 0.850000 0.791667 0 0.850000 0.833333 0 0.850000 0.875000 0 0.850000 0.916667 0 0.850000 0.958333 0 0.850000 1.000000 0 0.858334 0 0 0.858334 0.041667 0 0.858334 0.083333 0 0.858334 0.125000 0 0.858334 0.166667 0 0.858334 0.208333 0 0.858334 0.250000 0 0.858334 0.291667 0 0.858334 0.333333 0 0.858334 0.375000 0 0.858334 0.416667 0 0.858334 0.458333 0 0.858334 0.500000 0 0.858334 0.541667 0 0.858334 0.583333 0 0.858334 0.625000 0 0.858334 0.666667 0 0.858334 0.708333 0 0.858334 0.750000 0 0.858334 0.791667 0 0.858334 0.833333 0 0.858334 0.875000 0 0.858334 0.916667 0 0.858334 0.958333 0 0.858334 1.000000 0 0.866667 0 0 0.866667 0.041667 0 0.866667 0.083333 0 0.866667 0.125000 0 0.866667 0.166667 0 0.866667 0.208333 0 0.866667 0.250000 0 0.866667 0.291667 0 0.866667 0.333333 0 0.866667 0.375000 0 0.866667 0.416667 0 0.866667 0.458333 0 0.866667 0.500000 0 0.866667 0.541667 0 0.866667 0.583333 0 0.866667 0.625000 0 0.866667 0.666667 0 0.866667 0.708333 0 0.866667 0.750000 0 0.866667 0.791667 0 0.866667 0.833333 0 0.866667 0.875000 0 0.866667 0.916667 0 0.866667 0.958333 0 0.866667 1.000000 0 0.875000 0 0 0.875000 0.041667 0 0.875000 0.083333 0 0.875000 0.125000 0 0.875000 0.166667 0 0.875000 0.208333 0 0.875000 0.250000 0 0.875000 0.291667 0 0.875000 0.333333 0 0.875000 0.375000 0 0.875000 0.416667 0 0.875000 0.458333 0 0.875000 0.500000 0 0.875000 0.541667 0 0.875000 0.583333 0 0.875000 0.625000 0 0.875000 0.666667 0 0.875000 0.708333 0 0.875000 0.750000 0 0.875000 0.791667 0 0.875000 0.833333 0 0.875000 0.875000 0 0.875000 0.916667 0 0.875000 0.958333 0 0.875000 1.000000 0 0.883334 0 0 0.883334 0.041667 0 0.883334 0.083333 0 0.883334 0.125000 0 0.883334 0.166667 0 0.883334 0.208333 0 0.883334 0.250000 0 0.883334 0.291667 0 0.883334 0.333333 0 0.883334 0.375000 0 0.883334 0.416667 0 0.883334 0.458333 0 0.883334 0.500000 0 0.883334 0.541667 0 0.883334 0.583333 0 0.883334 0.625000 0 0.883334 0.666667 0 0.883334 0.708333 0 0.883334 0.750000 0 0.883334 0.791667 0 0.883334 0.833333 0 0.883334 0.875000 0 0.883334 0.916667 0 0.883334 0.958333 0 0.883334 1.000000 0 0.891667 0 0 0.891667 0.041667 0 0.891667 0.083333 0 0.891667 0.125000 0 0.891667 0.166667 0 0.891667 0.208333 0 0.891667 0.250000 0 0.891667 0.291667 0 0.891667 0.333333 0 0.891667 0.375000 0 0.891667 0.416667 0 0.891667 0.458333 0 0.891667 0.500000 0 0.891667 0.541667 0 0.891667 0.583333 0 0.891667 0.625000 0 0.891667 0.666667 0 0.891667 0.708333 0 0.891667 0.750000 0 0.891667 0.791667 0 0.891667 0.833333 0 0.891667 0.875000 0 0.891667 0.916667 0 0.891667 0.958333 0 0.891667 1.000000 0 0.900000 0 0 0.900000 0.041667 0 0.900000 0.083333 0 0.900000 0.125000 0 0.900000 0.166667 0 0.900000 0.208333 0 0.900000 0.250000 0 0.900000 0.291667 0 0.900000 0.333333 0 0.900000 0.375000 0 0.900000 0.416667 0 0.900000 0.458333 0 0.900000 0.500000 0 0.900000 0.541667 0 0.900000 0.583333 0 0.900000 0.625000 0 0.900000 0.666667 0 0.900000 0.708333 0 0.900000 0.750000 0 0.900000 0.791667 0 0.900000 0.833333 0 0.900000 0.875000 0 0.900000 0.916667 0 0.900000 0.958333 0 0.900000 1.000000 0 0.908334 0 0 0.908334 0.041667 0 0.908334 0.083333 0 0.908334 0.125000 0 0.908334 0.166667 0 0.908334 0.208333 0 0.908334 0.250000 0 0.908334 0.291667 0 0.908334 0.333333 0 0.908334 0.375000 0 0.908334 0.416667 0 0.908334 0.458333 0 0.908334 0.500000 0 0.908334 0.541667 0 0.908334 0.583333 0 0.908334 0.625000 0 0.908334 0.666667 0 0.908334 0.708333 0 0.908334 0.750000 0 0.908334 0.791667 0 0.908334 0.833333 0 0.908334 0.875000 0 0.908334 0.916667 0 0.908334 0.958333 0 0.908334 1.000000 0 0.916667 0 0 0.916667 0.041667 0 0.916667 0.083333 0 0.916667 0.125000 0 0.916667 0.166667 0 0.916667 0.208333 0 0.916667 0.250000 0 0.916667 0.291667 0 0.916667 0.333333 0 0.916667 0.375000 0 0.916667 0.416667 0 0.916667 0.458333 0 0.916667 0.500000 0 0.916667 0.541667 0 0.916667 0.583333 0 0.916667 0.625000 0 0.916667 0.666667 0 0.916667 0.708333 0 0.916667 0.750000 0 0.916667 0.791667 0 0.916667 0.833333 0 0.916667 0.875000 0 0.916667 0.916667 0 0.916667 0.958333 0 0.916667 1.000000 0 0.925000 0 0 0.925000 0.041667 0 0.925000 0.083333 0 0.925000 0.125000 0 0.925000 0.166667 0 0.925000 0.208333 0 0.925000 0.250000 0 0.925000 0.291667 0 0.925000 0.333333 0 0.925000 0.375000 0 0.925000 0.416667 0 0.925000 0.458333 0 0.925000 0.500000 0 0.925000 0.541667 0 0.925000 0.583333 0 0.925000 0.625000 0 0.925000 0.666667 0 0.925000 0.708333 0 0.925000 0.750000 0 0.925000 0.791667 0 0.925000 0.833333 0 0.925000 0.875000 0 0.925000 0.916667 0 0.925000 0.958333 0 0.925000 1.000000 0 0.933334 0 0 0.933334 0.041667 0 0.933334 0.083333 0 0.933334 0.125000 0 0.933334 0.166667 0 0.933334 0.208333 0 0.933334 0.250000 0 0.933334 0.291667 0 0.933334 0.333333 0 0.933334 0.375000 0 0.933334 0.416667 0 0.933334 0.458333 0 0.933334 0.500000 0 0.933334 0.541667 0 0.933334 0.583333 0 0.933334 0.625000 0 0.933334 0.666667 0 0.933334 0.708333 0 0.933334 0.750000 0 0.933334 0.791667 0 0.933334 0.833333 0 0.933334 0.875000 0 0.933334 0.916667 0 0.933334 0.958333 0 0.933334 1.000000 0 0.941667 0 0 0.941667 0.041667 0 0.941667 0.083333 0 0.941667 0.125000 0 0.941667 0.166667 0 0.941667 0.208333 0 0.941667 0.250000 0 0.941667 0.291667 0 0.941667 0.333333 0 0.941667 0.375000 0 0.941667 0.416667 0 0.941667 0.458333 0 0.941667 0.500000 0 0.941667 0.541667 0 0.941667 0.583333 0 0.941667 0.625000 0 0.941667 0.666667 0 0.941667 0.708333 0 0.941667 0.750000 0 0.941667 0.791667 0 0.941667 0.833333 0 0.941667 0.875000 0 0.941667 0.916667 0 0.941667 0.958333 0 0.941667 1.000000 0 0.950001 0 0 0.950001 0.041667 0 0.950001 0.083333 0 0.950001 0.125000 0 0.950001 0.166667 0 0.950001 0.208333 0 0.950001 0.250000 0 0.950001 0.291667 0 0.950001 0.333333 0 0.950001 0.375000 0 0.950001 0.416667 0 0.950001 0.458333 0 0.950001 0.500000 0 0.950001 0.541667 0 0.950001 0.583333 0 0.950001 0.625000 0 0.950001 0.666667 0 0.950001 0.708333 0 0.950001 0.750000 0 0.950001 0.791667 0 0.950001 0.833333 0 0.950001 0.875000 0 0.950001 0.916667 0 0.950001 0.958333 0 0.950001 1.000000 0 0.958334 0 0 0.958334 0.041667 0 0.958334 0.083333 0 0.958334 0.125000 0 0.958334 0.166667 0 0.958334 0.208333 0 0.958334 0.250000 0 0.958334 0.291667 0 0.958334 0.333333 0 0.958334 0.375000 0 0.958334 0.416667 0 0.958334 0.458333 0 0.958334 0.500000 0 0.958334 0.541667 0 0.958334 0.583333 0 0.958334 0.625000 0 0.958334 0.666667 0 0.958334 0.708333 0 0.958334 0.750000 0 0.958334 0.791667 0 0.958334 0.833333 0 0.958334 0.875000 0 0.958334 0.916667 0 0.958334 0.958333 0 0.958334 1.000000 0 0.966667 0 0 0.966667 0.041667 0 0.966667 0.083333 0 0.966667 0.125000 0 0.966667 0.166667 0 0.966667 0.208333 0 0.966667 0.250000 0 0.966667 0.291667 0 0.966667 0.333333 0 0.966667 0.375000 0 0.966667 0.416667 0 0.966667 0.458333 0 0.966667 0.500000 0 0.966667 0.541667 0 0.966667 0.583333 0 0.966667 0.625000 0 0.966667 0.666667 0 0.966667 0.708333 0 0.966667 0.750000 0 0.966667 0.791667 0 0.966667 0.833333 0 0.966667 0.875000 0 0.966667 0.916667 0 0.966667 0.958333 0 0.966667 1.000000 0 0.975001 0 0 0.975001 0.041667 0 0.975001 0.083333 0 0.975001 0.125000 0 0.975001 0.166667 0 0.975001 0.208333 0 0.975001 0.250000 0 0.975001 0.291667 0 0.975001 0.333333 0 0.975001 0.375000 0 0.975001 0.416667 0 0.975001 0.458333 0 0.975001 0.500000 0 0.975001 0.541667 0 0.975001 0.583333 0 0.975001 0.625000 0 0.975001 0.666667 0 0.975001 0.708333 0 0.975001 0.750000 0 0.975001 0.791667 0 0.975001 0.833333 0 0.975001 0.875000 0 0.975001 0.916667 0 0.975001 0.958333 0 0.975001 1.000000 0 0.983334 0 0 0.983334 0.041667 0 0.983334 0.083333 0 0.983334 0.125000 0 0.983334 0.166667 0 0.983334 0.208333 0 0.983334 0.250000 0 0.983334 0.291667 0 0.983334 0.333333 0 0.983334 0.375000 0 0.983334 0.416667 0 0.983334 0.458333 0 0.983334 0.500000 0 0.983334 0.541667 0 0.983334 0.583333 0 0.983334 0.625000 0 0.983334 0.666667 0 0.983334 0.708333 0 0.983334 0.750000 0 0.983334 0.791667 0 0.983334 0.833333 0 0.983334 0.875000 0 0.983334 0.916667 0 0.983334 0.958333 0 0.983334 1.000000 0 0.991667 0 0 0.991667 0.041667 0 0.991667 0.083333 0 0.991667 0.125000 0 0.991667 0.166667 0 0.991667 0.208333 0 0.991667 0.250000 0 0.991667 0.291667 0 0.991667 0.333333 0 0.991667 0.375000 0 0.991667 0.416667 0 0.991667 0.458333 0 0.991667 0.500000 0 0.991667 0.541667 0 0.991667 0.583333 0 0.991667 0.625000 0 0.991667 0.666667 0 0.991667 0.708333 0 0.991667 0.750000 0 0.991667 0.791667 0 0.991667 0.833333 0 0.991667 0.875000 0 0.991667 0.916667 0 0.991667 0.958333 0 0.991667 1.000000 0 1.000001 0 0 1.000001 0.041667 0 1.000001 0.083333 0 1.000001 0.125000 0 1.000001 0.166667 0 1.000001 0.208333 0 1.000001 0.250000 0 1.000001 0.291667 0 1.000001 0.333333 0 1.000001 0.375000 0 1.000001 0.416667 0 1.000001 0.458333 0 1.000001 0.500000 0 1.000001 0.541667 0 1.000001 0.583333 0 1.000001 0.625000 0 1.000001 0.666667 0 1.000001 0.708333 0 1.000001 0.750000 0 1.000001 0.791667 0 1.000001 0.833333 0 1.000001 0.875000 0 1.000001 0.916667 0 1.000001 0.958333 0 1.000001 1.000000 0</float_array>
+ <technique_common>
+ <accessor source="#Torus_Knot01-mesh-map-channel1-array" count="3025" stride="3">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ <param name="P" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus_Knot01-mesh-vertices">
+ <input semantic="POSITION" source="#Torus_Knot01-mesh-positions"/>
+ </vertices>
+ <triangles material="Torus-Knot" count="5760">
+ <input semantic="VERTEX" source="#Torus_Knot01-mesh-vertices" offset="0"/>
+ <input semantic="NORMAL" source="#Torus_Knot01-mesh-normals" offset="1"/>
+ <input semantic="TEXCOORD" source="#Torus_Knot01-mesh-map-channel1" offset="2" set="1"/>
+ <p>0 0 0 24 1 25 25 2 26 0 0 0 25 2 26 1 3 1 1 3 1 25 2 26 26 4 27 1 3 1 26 4 27 2 5 2 2 5 2 26 4 27 27 6 28 2 5 2 27 6 28 3 7 3 3 7 3 27 6 28 28 8 29 3 7 3 28 8 29 4 9 4 4 9 4 28 8 29 29 10 30 4 9 4 29 10 30 5 11 5 5 11 5 29 10 30 30 12 31 5 11 5 30 12 31 6 13 6 6 13 6 30 12 31 31 14 32 6 13 6 31 14 32 7 15 7 7 15 7 31 14 32 32 16 33 7 15 7 32 16 33 8 17 8 8 17 8 32 16 33 33 18 34 8 17 8 33 18 34 9 19 9 9 19 9 33 18 34 34 20 35 9 19 9 34 20 35 10 21 10 10 21 10 34 20 35 35 22 36 10 21 10 35 22 36 11 23 11 11 23 11 35 22 36 36 24 37 11 23 11 36 24 37 12 25 12 12 25 12 36 24 37 37 26 38 12 25 12 37 26 38 13 27 13 13 27 13 37 26 38 38 28 39 13 27 13 38 28 39 14 29 14 14 29 14 38 28 39 39 30 40 14 29 14 39 30 40 15 31 15 15 31 15 39 30 40 40 32 41 15 31 15 40 32 41 16 33 16 16 33 16 40 32 41 41 34 42 16 33 16 41 34 42 17 35 17 17 35 17 41 34 42 42 36 43 17 35 17 42 36 43 18 37 18 18 37 18 42 36 43 43 38 44 18 37 18 43 38 44 19 39 19 19 39 19 43 38 44 44 40 45 19 39 19 44 40 45 20 41 20 20 41 20 44 40 45 45 42 46 20 41 20 45 42 46 21 43 21 21 43 21 45 42 46 46 44 47 21 43 21 46 44 47 22 45 22 22 45 22 46 44 47 47 46 48 22 45 22 47 46 48 23 47 23 23 47 23 47 46 48 24 1 49 23 47 23 24 1 49 0 0 24 24 1 25 48 48 50 49 49 51 24 1 25 49 49 51 25 2 26 25 2 26 49 49 51 50 50 52 25 2 26 50 50 52 26 4 27 26 4 27 50 50 52 51 51 53 26 4 27 51 51 53 27 6 28 27 6 28 51 51 53 52 52 54 27 6 28 52 52 54 28 8 29 28 8 29 52 52 54 53 53 55 28 8 29 53 53 55 29 10 30 29 10 30 53 53 55 54 54 56 29 10 30 54 54 56 30 12 31 30 12 31 54 54 56 55 55 57 30 12 31 55 55 57 31 14 32 31 14 32 55 55 57 56 56 58 31 14 32 56 56 58 32 16 33 32 16 33 56 56 58 57 57 59 32 16 33 57 57 59 33 18 34 33 18 34 57 57 59 58 58 60 33 18 34 58 58 60 34 20 35 34 20 35 58 58 60 59 59 61 34 20 35 59 59 61 35 22 36 35 22 36 59 59 61 60 60 62 35 22 36 60 60 62 36 24 37 36 24 37 60 60 62 61 61 63 36 24 37 61 61 63 37 26 38 37 26 38 61 61 63 62 62 64 37 26 38 62 62 64 38 28 39 38 28 39 62 62 64 63 63 65 38 28 39 63 63 65 39 30 40 39 30 40 63 63 65 64 64 66 39 30 40 64 64 66 40 32 41 40 32 41 64 64 66 65 65 67 40 32 41 65 65 67 41 34 42 41 34 42 65 65 67 66 66 68 41 34 42 66 66 68 42 36 43 42 36 43 66 66 68 67 67 69 42 36 43 67 67 69 43 38 44 43 38 44 67 67 69 68 68 70 43 38 44 68 68 70 44 40 45 44 40 45 68 68 70 69 69 71 44 40 45 69 69 71 45 42 46 45 42 46 69 69 71 70 70 72 45 42 46 70 70 72 46 44 47 46 44 47 70 70 72 71 71 73 46 44 47 71 71 73 47 46 48 47 46 48 71 71 73 48 48 74 47 46 48 48 48 74 24 1 49 48 48 50 72 72 75 73 73 76 48 48 50 73 73 76 49 49 51 49 49 51 73 73 76 74 74 77 49 49 51 74 74 77 50 50 52 50 50 52 74 74 77 75 75 78 50 50 52 75 75 78 51 51 53 51 51 53 75 75 78 76 76 79 51 51 53 76 76 79 52 52 54 52 52 54 76 76 79 77 77 80 52 52 54 77 77 80 53 53 55 53 53 55 77 77 80 78 78 81 53 53 55 78 78 81 54 54 56 54 54 56 78 78 81 79 79 82 54 54 56 79 79 82 55 55 57 55 55 57 79 79 82 80 80 83 55 55 57 80 80 83 56 56 58 56 56 58 80 80 83 81 81 84 56 56 58 81 81 84 57 57 59 57 57 59 81 81 84 82 82 85 57 57 59 82 82 85 58 58 60 58 58 60 82 82 85 83 83 86 58 58 60 83 83 86 59 59 61 59 59 61 83 83 86 84 84 87 59 59 61 84 84 87 60 60 62 60 60 62 84 84 87 85 85 88 60 60 62 85 85 88 61 61 63 61 61 63 85 85 88 86 86 89 61 61 63 86 86 89 62 62 64 62 62 64 86 86 89 87 87 90 62 62 64 87 87 90 63 63 65 63 63 65 87 87 90 88 88 91 63 63 65 88 88 91 64 64 66 64 64 66 88 88 91 89 89 92 64 64 66 89 89 92 65 65 67 65 65 67 89 89 92 90 90 93 65 65 67 90 90 93 66 66 68 66 66 68 90 90 93 91 91 94 66 66 68 91 91 94 67 67 69 67 67 69 91 91 94 92 92 95 67 67 69 92 92 95 68 68 70 68 68 70 92 92 95 93 93 96 68 68 70 93 93 96 69 69 71 69 69 71 93 93 96 94 94 97 69 69 71 94 94 97 70 70 72 70 70 72 94 94 97 95 95 98 70 70 72 95 95 98 71 71 73 71 71 73 95 95 98 72 72 99 71 71 73 72 72 99 48 48 74 72 72 75 96 96 100 97 97 101 72 72 75 97 97 101 73 73 76 73 73 76 97 97 101 98 98 102 73 73 76 98 98 102 74 74 77 74 74 77 98 98 102 99 99 103 74 74 77 99 99 103 75 75 78 75 75 78 99 99 103 100 100 104 75 75 78 100 100 104 76 76 79 76 76 79 100 100 104 101 101 105 76 76 79 101 101 105 77 77 80 77 77 80 101 101 105 102 102 106 77 77 80 102 102 106 78 78 81 78 78 81 102 102 106 103 103 107 78 78 81 103 103 107 79 79 82 79 79 82 103 103 107 104 104 108 79 79 82 104 104 108 80 80 83 80 80 83 104 104 108 105 105 109 80 80 83 105 105 109 81 81 84 81 81 84 105 105 109 106 106 110 81 81 84 106 106 110 82 82 85 82 82 85 106 106 110 107 107 111 82 82 85 107 107 111 83 83 86 83 83 86 107 107 111 108 108 112 83 83 86 108 108 112 84 84 87 84 84 87 108 108 112 109 109 113 84 84 87 109 109 113 85 85 88 85 85 88 109 109 113 110 110 114 85 85 88 110 110 114 86 86 89 86 86 89 110 110 114 111 111 115 86 86 89 111 111 115 87 87 90 87 87 90 111 111 115 112 112 116 87 87 90 112 112 116 88 88 91 88 88 91 112 112 116 113 113 117 88 88 91 113 113 117 89 89 92 89 89 92 113 113 117 114 114 118 89 89 92 114 114 118 90 90 93 90 90 93 114 114 118 115 115 119 90 90 93 115 115 119 91 91 94 91 91 94 115 115 119 116 116 120 91 91 94 116 116 120 92 92 95 92 92 95 116 116 120 117 117 121 92 92 95 117 117 121 93 93 96 93 93 96 117 117 121 118 118 122 93 93 96 118 118 122 94 94 97 94 94 97 118 118 122 119 119 123 94 94 97 119 119 123 95 95 98 95 95 98 119 119 123 96 96 124 95 95 98 96 96 124 72 72 99 96 96 100 120 120 125 121 121 126 96 96 100 121 121 126 97 97 101 97 97 101 121 121 126 122 122 127 97 97 101 122 122 127 98 98 102 98 98 102 122 122 127 123 123 128 98 98 102 123 123 128 99 99 103 99 99 103 123 123 128 124 124 129 99 99 103 124 124 129 100 100 104 100 100 104 124 124 129 125 125 130 100 100 104 125 125 130 101 101 105 101 101 105 125 125 130 126 126 131 101 101 105 126 126 131 102 102 106 102 102 106 126 126 131 127 127 132 102 102 106 127 127 132 103 103 107 103 103 107 127 127 132 128 128 133 103 103 107 128 128 133 104 104 108 104 104 108 128 128 133 129 129 134 104 104 108 129 129 134 105 105 109 105 105 109 129 129 134 130 130 135 105 105 109 130 130 135 106 106 110 106 106 110 130 130 135 131 131 136 106 106 110 131 131 136 107 107 111 107 107 111 131 131 136 132 132 137 107 107 111 132 132 137 108 108 112 108 108 112 132 132 137 133 133 138 108 108 112 133 133 138 109 109 113 109 109 113 133 133 138 134 134 139 109 109 113 134 134 139 110 110 114 110 110 114 134 134 139 135 135 140 110 110 114 135 135 140 111 111 115 111 111 115 135 135 140 136 136 141 111 111 115 136 136 141 112 112 116 112 112 116 136 136 141 137 137 142 112 112 116 137 137 142 113 113 117 113 113 117 137 137 142 138 138 143 113 113 117 138 138 143 114 114 118 114 114 118 138 138 143 139 139 144 114 114 118 139 139 144 115 115 119 115 115 119 139 139 144 140 140 145 115 115 119 140 140 145 116 116 120 116 116 120 140 140 145 141 141 146 116 116 120 141 141 146 117 117 121 117 117 121 141 141 146 142 142 147 117 117 121 142 142 147 118 118 122 118 118 122 142 142 147 143 143 148 118 118 122 143 143 148 119 119 123 119 119 123 143 143 148 120 120 149 119 119 123 120 120 149 96 96 124 120 120 125 144 144 150 145 145 151 120 120 125 145 145 151 121 121 126 121 121 126 145 145 151 146 146 152 121 121 126 146 146 152 122 122 127 122 122 127 146 146 152 147 147 153 122 122 127 147 147 153 123 123 128 123 123 128 147 147 153 148 148 154 123 123 128 148 148 154 124 124 129 124 124 129 148 148 154 149 149 155 124 124 129 149 149 155 125 125 130 125 125 130 149 149 155 150 150 156 125 125 130 150 150 156 126 126 131 126 126 131 150 150 156 151 151 157 126 126 131 151 151 157 127 127 132 127 127 132 151 151 157 152 152 158 127 127 132 152 152 158 128 128 133 128 128 133 152 152 158 153 153 159 128 128 133 153 153 159 129 129 134 129 129 134 153 153 159 154 154 160 129 129 134 154 154 160 130 130 135 130 130 135 154 154 160 155 155 161 130 130 135 155 155 161 131 131 136 131 131 136 155 155 161 156 156 162 131 131 136 156 156 162 132 132 137 132 132 137 156 156 162 157 157 163 132 132 137 157 157 163 133 133 138 133 133 138 157 157 163 158 158 164 133 133 138 158 158 164 134 134 139 134 134 139 158 158 164 159 159 165 134 134 139 159 159 165 135 135 140 135 135 140 159 159 165 160 160 166 135 135 140 160 160 166 136 136 141 136 136 141 160 160 166 161 161 167 136 136 141 161 161 167 137 137 142 137 137 142 161 161 167 162 162 168 137 137 142 162 162 168 138 138 143 138 138 143 162 162 168 163 163 169 138 138 143 163 163 169 139 139 144 139 139 144 163 163 169 164 164 170 139 139 144 164 164 170 140 140 145 140 140 145 164 164 170 165 165 171 140 140 145 165 165 171 141 141 146 141 141 146 165 165 171 166 166 172 141 141 146 166 166 172 142 142 147 142 142 147 166 166 172 167 167 173 142 142 147 167 167 173 143 143 148 143 143 148 167 167 173 144 144 174 143 143 148 144 144 174 120 120 149 144 144 150 168 168 175 169 169 176 144 144 150 169 169 176 145 145 151 145 145 151 169 169 176 170 170 177 145 145 151 170 170 177 146 146 152 146 146 152 170 170 177 171 171 178 146 146 152 171 171 178 147 147 153 147 147 153 171 171 178 172 172 179 147 147 153 172 172 179 148 148 154 148 148 154 172 172 179 173 173 180 148 148 154 173 173 180 149 149 155 149 149 155 173 173 180 174 174 181 149 149 155 174 174 181 150 150 156 150 150 156 174 174 181 175 175 182 150 150 156 175 175 182 151 151 157 151 151 157 175 175 182 176 176 183 151 151 157 176 176 183 152 152 158 152 152 158 176 176 183 177 177 184 152 152 158 177 177 184 153 153 159 153 153 159 177 177 184 178 178 185 153 153 159 178 178 185 154 154 160 154 154 160 178 178 185 179 179 186 154 154 160 179 179 186 155 155 161 155 155 161 179 179 186 180 180 187 155 155 161 180 180 187 156 156 162 156 156 162 180 180 187 181 181 188 156 156 162 181 181 188 157 157 163 157 157 163 181 181 188 182 182 189 157 157 163 182 182 189 158 158 164 158 158 164 182 182 189 183 183 190 158 158 164 183 183 190 159 159 165 159 159 165 183 183 190 184 184 191 159 159 165 184 184 191 160 160 166 160 160 166 184 184 191 185 185 192 160 160 166 185 185 192 161 161 167 161 161 167 185 185 192 186 186 193 161 161 167 186 186 193 162 162 168 162 162 168 186 186 193 187 187 194 162 162 168 187 187 194 163 163 169 163 163 169 187 187 194 188 188 195 163 163 169 188 188 195 164 164 170 164 164 170 188 188 195 189 189 196 164 164 170 189 189 196 165 165 171 165 165 171 189 189 196 190 190 197 165 165 171 190 190 197 166 166 172 166 166 172 190 190 197 191 191 198 166 166 172 191 191 198 167 167 173 167 167 173 191 191 198 168 168 199 167 167 173 168 168 199 144 144 174 168 168 175 192 192 200 193 193 201 168 168 175 193 193 201 169 169 176 169 169 176 193 193 201 194 194 202 169 169 176 194 194 202 170 170 177 170 170 177 194 194 202 195 195 203 170 170 177 195 195 203 171 171 178 171 171 178 195 195 203 196 196 204 171 171 178 196 196 204 172 172 179 172 172 179 196 196 204 197 197 205 172 172 179 197 197 205 173 173 180 173 173 180 197 197 205 198 198 206 173 173 180 198 198 206 174 174 181 174 174 181 198 198 206 199 199 207 174 174 181 199 199 207 175 175 182 175 175 182 199 199 207 200 200 208 175 175 182 200 200 208 176 176 183 176 176 183 200 200 208 201 201 209 176 176 183 201 201 209 177 177 184 177 177 184 201 201 209 202 202 210 177 177 184 202 202 210 178 178 185 178 178 185 202 202 210 203 203 211 178 178 185 203 203 211 179 179 186 179 179 186 203 203 211 204 204 212 179 179 186 204 204 212 180 180 187 180 180 187 204 204 212 205 205 213 180 180 187 205 205 213 181 181 188 181 181 188 205 205 213 206 206 214 181 181 188 206 206 214 182 182 189 182 182 189 206 206 214 207 207 215 182 182 189 207 207 215 183 183 190 183 183 190 207 207 215 208 208 216 183 183 190 208 208 216 184 184 191 184 184 191 208 208 216 209 209 217 184 184 191 209 209 217 185 185 192 185 185 192 209 209 217 210 210 218 185 185 192 210 210 218 186 186 193 186 186 193 210 210 218 211 211 219 186 186 193 211 211 219 187 187 194 187 187 194 211 211 219 212 212 220 187 187 194 212 212 220 188 188 195 188 188 195 212 212 220 213 213 221 188 188 195 213 213 221 189 189 196 189 189 196 213 213 221 214 214 222 189 189 196 214 214 222 190 190 197 190 190 197 214 214 222 215 215 223 190 190 197 215 215 223 191 191 198 191 191 198 215 215 223 192 192 224 191 191 198 192 192 224 168 168 199 192 192 200 216 216 225 217 217 226 192 192 200 217 217 226 193 193 201 193 193 201 217 217 226 218 218 227 193 193 201 218 218 227 194 194 202 194 194 202 218 218 227 219 219 228 194 194 202 219 219 228 195 195 203 195 195 203 219 219 228 220 220 229 195 195 203 220 220 229 196 196 204 196 196 204 220 220 229 221 221 230 196 196 204 221 221 230 197 197 205 197 197 205 221 221 230 222 222 231 197 197 205 222 222 231 198 198 206 198 198 206 222 222 231 223 223 232 198 198 206 223 223 232 199 199 207 199 199 207 223 223 232 224 224 233 199 199 207 224 224 233 200 200 208 200 200 208 224 224 233 225 225 234 200 200 208 225 225 234 201 201 209 201 201 209 225 225 234 226 226 235 201 201 209 226 226 235 202 202 210 202 202 210 226 226 235 227 227 236 202 202 210 227 227 236 203 203 211 203 203 211 227 227 236 228 228 237 203 203 211 228 228 237 204 204 212 204 204 212 228 228 237 229 229 238 204 204 212 229 229 238 205 205 213 205 205 213 229 229 238 230 230 239 205 205 213 230 230 239 206 206 214 206 206 214 230 230 239 231 231 240 206 206 214 231 231 240 207 207 215 207 207 215 231 231 240 232 232 241 207 207 215 232 232 241 208 208 216 208 208 216 232 232 241 233 233 242 208 208 216 233 233 242 209 209 217 209 209 217 233 233 242 234 234 243 209 209 217 234 234 243 210 210 218 210 210 218 234 234 243 235 235 244 210 210 218 235 235 244 211 211 219 211 211 219 235 235 244 236 236 245 211 211 219 236 236 245 212 212 220 212 212 220 236 236 245 237 237 246 212 212 220 237 237 246 213 213 221 213 213 221 237 237 246 238 238 247 213 213 221 238 238 247 214 214 222 214 214 222 238 238 247 239 239 248 214 214 222 239 239 248 215 215 223 215 215 223 239 239 248 216 216 249 215 215 223 216 216 249 192 192 224 216 216 225 240 240 250 241 241 251 216 216 225 241 241 251 217 217 226 217 217 226 241 241 251 242 242 252 217 217 226 242 242 252 218 218 227 218 218 227 242 242 252 243 243 253 218 218 227 243 243 253 219 219 228 219 219 228 243 243 253 244 244 254 219 219 228 244 244 254 220 220 229 220 220 229 244 244 254 245 245 255 220 220 229 245 245 255 221 221 230 221 221 230 245 245 255 246 246 256 221 221 230 246 246 256 222 222 231 222 222 231 246 246 256 247 247 257 222 222 231 247 247 257 223 223 232 223 223 232 247 247 257 248 248 258 223 223 232 248 248 258 224 224 233 224 224 233 248 248 258 249 249 259 224 224 233 249 249 259 225 225 234 225 225 234 249 249 259 250 250 260 225 225 234 250 250 260 226 226 235 226 226 235 250 250 260 251 251 261 226 226 235 251 251 261 227 227 236 227 227 236 251 251 261 252 252 262 227 227 236 252 252 262 228 228 237 228 228 237 252 252 262 253 253 263 228 228 237 253 253 263 229 229 238 229 229 238 253 253 263 254 254 264 229 229 238 254 254 264 230 230 239 230 230 239 254 254 264 255 255 265 230 230 239 255 255 265 231 231 240 231 231 240 255 255 265 256 256 266 231 231 240 256 256 266 232 232 241 232 232 241 256 256 266 257 257 267 232 232 241 257 257 267 233 233 242 233 233 242 257 257 267 258 258 268 233 233 242 258 258 268 234 234 243 234 234 243 258 258 268 259 259 269 234 234 243 259 259 269 235 235 244 235 235 244 259 259 269 260 260 270 235 235 244 260 260 270 236 236 245 236 236 245 260 260 270 261 261 271 236 236 245 261 261 271 237 237 246 237 237 246 261 261 271 262 262 272 237 237 246 262 262 272 238 238 247 238 238 247 262 262 272 263 263 273 238 238 247 263 263 273 239 239 248 239 239 248 263 263 273 240 240 274 239 239 248 240 240 274 216 216 249 240 240 250 264 264 275 265 265 276 240 240 250 265 265 276 241 241 251 241 241 251 265 265 276 266 266 277 241 241 251 266 266 277 242 242 252 242 242 252 266 266 277 267 267 278 242 242 252 267 267 278 243 243 253 243 243 253 267 267 278 268 268 279 243 243 253 268 268 279 244 244 254 244 244 254 268 268 279 269 269 280 244 244 254 269 269 280 245 245 255 245 245 255 269 269 280 270 270 281 245 245 255 270 270 281 246 246 256 246 246 256 270 270 281 271 271 282 246 246 256 271 271 282 247 247 257 247 247 257 271 271 282 272 272 283 247 247 257 272 272 283 248 248 258 248 248 258 272 272 283 273 273 284 248 248 258 273 273 284 249 249 259 249 249 259 273 273 284 274 274 285 249 249 259 274 274 285 250 250 260 250 250 260 274 274 285 275 275 286 250 250 260 275 275 286 251 251 261 251 251 261 275 275 286 276 276 287 251 251 261 276 276 287 252 252 262 252 252 262 276 276 287 277 277 288 252 252 262 277 277 288 253 253 263 253 253 263 277 277 288 278 278 289 253 253 263 278 278 289 254 254 264 254 254 264 278 278 289 279 279 290 254 254 264 279 279 290 255 255 265 255 255 265 279 279 290 280 280 291 255 255 265 280 280 291 256 256 266 256 256 266 280 280 291 281 281 292 256 256 266 281 281 292 257 257 267 257 257 267 281 281 292 282 282 293 257 257 267 282 282 293 258 258 268 258 258 268 282 282 293 283 283 294 258 258 268 283 283 294 259 259 269 259 259 269 283 283 294 284 284 295 259 259 269 284 284 295 260 260 270 260 260 270 284 284 295 285 285 296 260 260 270 285 285 296 261 261 271 261 261 271 285 285 296 286 286 297 261 261 271 286 286 297 262 262 272 262 262 272 286 286 297 287 287 298 262 262 272 287 287 298 263 263 273 263 263 273 287 287 298 264 264 299 263 263 273 264 264 299 240 240 274 264 264 275 288 288 300 289 289 301 264 264 275 289 289 301 265 265 276 265 265 276 289 289 301 290 290 302 265 265 276 290 290 302 266 266 277 266 266 277 290 290 302 291 291 303 266 266 277 291 291 303 267 267 278 267 267 278 291 291 303 292 292 304 267 267 278 292 292 304 268 268 279 268 268 279 292 292 304 293 293 305 268 268 279 293 293 305 269 269 280 269 269 280 293 293 305 294 294 306 269 269 280 294 294 306 270 270 281 270 270 281 294 294 306 295 295 307 270 270 281 295 295 307 271 271 282 271 271 282 295 295 307 296 296 308 271 271 282 296 296 308 272 272 283 272 272 283 296 296 308 297 297 309 272 272 283 297 297 309 273 273 284 273 273 284 297 297 309 298 298 310 273 273 284 298 298 310 274 274 285 274 274 285 298 298 310 299 299 311 274 274 285 299 299 311 275 275 286 275 275 286 299 299 311 300 300 312 275 275 286 300 300 312 276 276 287 276 276 287 300 300 312 301 301 313 276 276 287 301 301 313 277 277 288 277 277 288 301 301 313 302 302 314 277 277 288 302 302 314 278 278 289 278 278 289 302 302 314 303 303 315 278 278 289 303 303 315 279 279 290 279 279 290 303 303 315 304 304 316 279 279 290 304 304 316 280 280 291 280 280 291 304 304 316 305 305 317 280 280 291 305 305 317 281 281 292 281 281 292 305 305 317 306 306 318 281 281 292 306 306 318 282 282 293 282 282 293 306 306 318 307 307 319 282 282 293 307 307 319 283 283 294 283 283 294 307 307 319 308 308 320 283 283 294 308 308 320 284 284 295 284 284 295 308 308 320 309 309 321 284 284 295 309 309 321 285 285 296 285 285 296 309 309 321 310 310 322 285 285 296 310 310 322 286 286 297 286 286 297 310 310 322 311 311 323 286 286 297 311 311 323 287 287 298 287 287 298 311 311 323 288 288 324 287 287 298 288 288 324 264 264 299 288 288 300 312 312 325 313 313 326 288 288 300 313 313 326 289 289 301 289 289 301 313 313 326 314 314 327 289 289 301 314 314 327 290 290 302 290 290 302 314 314 327 315 315 328 290 290 302 315 315 328 291 291 303 291 291 303 315 315 328 316 316 329 291 291 303 316 316 329 292 292 304 292 292 304 316 316 329 317 317 330 292 292 304 317 317 330 293 293 305 293 293 305 317 317 330 318 318 331 293 293 305 318 318 331 294 294 306 294 294 306 318 318 331 319 319 332 294 294 306 319 319 332 295 295 307 295 295 307 319 319 332 320 320 333 295 295 307 320 320 333 296 296 308 296 296 308 320 320 333 321 321 334 296 296 308 321 321 334 297 297 309 297 297 309 321 321 334 322 322 335 297 297 309 322 322 335 298 298 310 298 298 310 322 322 335 323 323 336 298 298 310 323 323 336 299 299 311 299 299 311 323 323 336 324 324 337 299 299 311 324 324 337 300 300 312 300 300 312 324 324 337 325 325 338 300 300 312 325 325 338 301 301 313 301 301 313 325 325 338 326 326 339 301 301 313 326 326 339 302 302 314 302 302 314 326 326 339 327 327 340 302 302 314 327 327 340 303 303 315 303 303 315 327 327 340 328 328 341 303 303 315 328 328 341 304 304 316 304 304 316 328 328 341 329 329 342 304 304 316 329 329 342 305 305 317 305 305 317 329 329 342 330 330 343 305 305 317 330 330 343 306 306 318 306 306 318 330 330 343 331 331 344 306 306 318 331 331 344 307 307 319 307 307 319 331 331 344 332 332 345 307 307 319 332 332 345 308 308 320 308 308 320 332 332 345 333 333 346 308 308 320 333 333 346 309 309 321 309 309 321 333 333 346 334 334 347 309 309 321 334 334 347 310 310 322 310 310 322 334 334 347 335 335 348 310 310 322 335 335 348 311 311 323 311 311 323 335 335 348 312 312 349 311 311 323 312 312 349 288 288 324 312 312 325 336 336 350 337 337 351 312 312 325 337 337 351 313 313 326 313 313 326 337 337 351 338 338 352 313 313 326 338 338 352 314 314 327 314 314 327 338 338 352 339 339 353 314 314 327 339 339 353 315 315 328 315 315 328 339 339 353 340 340 354 315 315 328 340 340 354 316 316 329 316 316 329 340 340 354 341 341 355 316 316 329 341 341 355 317 317 330 317 317 330 341 341 355 342 342 356 317 317 330 342 342 356 318 318 331 318 318 331 342 342 356 343 343 357 318 318 331 343 343 357 319 319 332 319 319 332 343 343 357 344 344 358 319 319 332 344 344 358 320 320 333 320 320 333 344 344 358 345 345 359 320 320 333 345 345 359 321 321 334 321 321 334 345 345 359 346 346 360 321 321 334 346 346 360 322 322 335 322 322 335 346 346 360 347 347 361 322 322 335 347 347 361 323 323 336 323 323 336 347 347 361 348 348 362 323 323 336 348 348 362 324 324 337 324 324 337 348 348 362 349 349 363 324 324 337 349 349 363 325 325 338 325 325 338 349 349 363 350 350 364 325 325 338 350 350 364 326 326 339 326 326 339 350 350 364 351 351 365 326 326 339 351 351 365 327 327 340 327 327 340 351 351 365 352 352 366 327 327 340 352 352 366 328 328 341 328 328 341 352 352 366 353 353 367 328 328 341 353 353 367 329 329 342 329 329 342 353 353 367 354 354 368 329 329 342 354 354 368 330 330 343 330 330 343 354 354 368 355 355 369 330 330 343 355 355 369 331 331 344 331 331 344 355 355 369 356 356 370 331 331 344 356 356 370 332 332 345 332 332 345 356 356 370 357 357 371 332 332 345 357 357 371 333 333 346 333 333 346 357 357 371 358 358 372 333 333 346 358 358 372 334 334 347 334 334 347 358 358 372 359 359 373 334 334 347 359 359 373 335 335 348 335 335 348 359 359 373 336 336 374 335 335 348 336 336 374 312 312 349 336 336 350 360 360 375 361 361 376 336 336 350 361 361 376 337 337 351 337 337 351 361 361 376 362 362 377 337 337 351 362 362 377 338 338 352 338 338 352 362 362 377 363 363 378 338 338 352 363 363 378 339 339 353 339 339 353 363 363 378 364 364 379 339 339 353 364 364 379 340 340 354 340 340 354 364 364 379 365 365 380 340 340 354 365 365 380 341 341 355 341 341 355 365 365 380 366 366 381 341 341 355 366 366 381 342 342 356 342 342 356 366 366 381 367 367 382 342 342 356 367 367 382 343 343 357 343 343 357 367 367 382 368 368 383 343 343 357 368 368 383 344 344 358 344 344 358 368 368 383 369 369 384 344 344 358 369 369 384 345 345 359 345 345 359 369 369 384 370 370 385 345 345 359 370 370 385 346 346 360 346 346 360 370 370 385 371 371 386 346 346 360 371 371 386 347 347 361 347 347 361 371 371 386 372 372 387 347 347 361 372 372 387 348 348 362 348 348 362 372 372 387 373 373 388 348 348 362 373 373 388 349 349 363 349 349 363 373 373 388 374 374 389 349 349 363 374 374 389 350 350 364 350 350 364 374 374 389 375 375 390 350 350 364 375 375 390 351 351 365 351 351 365 375 375 390 376 376 391 351 351 365 376 376 391 352 352 366 352 352 366 376 376 391 377 377 392 352 352 366 377 377 392 353 353 367 353 353 367 377 377 392 378 378 393 353 353 367 378 378 393 354 354 368 354 354 368 378 378 393 379 379 394 354 354 368 379 379 394 355 355 369 355 355 369 379 379 394 380 380 395 355 355 369 380 380 395 356 356 370 356 356 370 380 380 395 381 381 396 356 356 370 381 381 396 357 357 371 357 357 371 381 381 396 382 382 397 357 357 371 382 382 397 358 358 372 358 358 372 382 382 397 383 383 398 358 358 372 383 383 398 359 359 373 359 359 373 383 383 398 360 360 399 359 359 373 360 360 399 336 336 374 360 360 375 384 384 400 385 385 401 360 360 375 385 385 401 361 361 376 361 361 376 385 385 401 386 386 402 361 361 376 386 386 402 362 362 377 362 362 377 386 386 402 387 387 403 362 362 377 387 387 403 363 363 378 363 363 378 387 387 403 388 388 404 363 363 378 388 388 404 364 364 379 364 364 379 388 388 404 389 389 405 364 364 379 389 389 405 365 365 380 365 365 380 389 389 405 390 390 406 365 365 380 390 390 406 366 366 381 366 366 381 390 390 406 391 391 407 366 366 381 391 391 407 367 367 382 367 367 382 391 391 407 392 392 408 367 367 382 392 392 408 368 368 383 368 368 383 392 392 408 393 393 409 368 368 383 393 393 409 369 369 384 369 369 384 393 393 409 394 394 410 369 369 384 394 394 410 370 370 385 370 370 385 394 394 410 395 395 411 370 370 385 395 395 411 371 371 386 371 371 386 395 395 411 396 396 412 371 371 386 396 396 412 372 372 387 372 372 387 396 396 412 397 397 413 372 372 387 397 397 413 373 373 388 373 373 388 397 397 413 398 398 414 373 373 388 398 398 414 374 374 389 374 374 389 398 398 414 399 399 415 374 374 389 399 399 415 375 375 390 375 375 390 399 399 415 400 400 416 375 375 390 400 400 416 376 376 391 376 376 391 400 400 416 401 401 417 376 376 391 401 401 417 377 377 392 377 377 392 401 401 417 402 402 418 377 377 392 402 402 418 378 378 393 378 378 393 402 402 418 403 403 419 378 378 393 403 403 419 379 379 394 379 379 394 403 403 419 404 404 420 379 379 394 404 404 420 380 380 395 380 380 395 404 404 420 405 405 421 380 380 395 405 405 421 381 381 396 381 381 396 405 405 421 406 406 422 381 381 396 406 406 422 382 382 397 382 382 397 406 406 422 407 407 423 382 382 397 407 407 423 383 383 398 383 383 398 407 407 423 384 384 424 383 383 398 384 384 424 360 360 399 384 384 400 408 408 425 409 409 426 384 384 400 409 409 426 385 385 401 385 385 401 409 409 426 410 410 427 385 385 401 410 410 427 386 386 402 386 386 402 410 410 427 411 411 428 386 386 402 411 411 428 387 387 403 387 387 403 411 411 428 412 412 429 387 387 403 412 412 429 388 388 404 388 388 404 412 412 429 413 413 430 388 388 404 413 413 430 389 389 405 389 389 405 413 413 430 414 414 431 389 389 405 414 414 431 390 390 406 390 390 406 414 414 431 415 415 432 390 390 406 415 415 432 391 391 407 391 391 407 415 415 432 416 416 433 391 391 407 416 416 433 392 392 408 392 392 408 416 416 433 417 417 434 392 392 408 417 417 434 393 393 409 393 393 409 417 417 434 418 418 435 393 393 409 418 418 435 394 394 410 394 394 410 418 418 435 419 419 436 394 394 410 419 419 436 395 395 411 395 395 411 419 419 436 420 420 437 395 395 411 420 420 437 396 396 412 396 396 412 420 420 437 421 421 438 396 396 412 421 421 438 397 397 413 397 397 413 421 421 438 422 422 439 397 397 413 422 422 439 398 398 414 398 398 414 422 422 439 423 423 440 398 398 414 423 423 440 399 399 415 399 399 415 423 423 440 424 424 441 399 399 415 424 424 441 400 400 416 400 400 416 424 424 441 425 425 442 400 400 416 425 425 442 401 401 417 401 401 417 425 425 442 426 426 443 401 401 417 426 426 443 402 402 418 402 402 418 426 426 443 427 427 444 402 402 418 427 427 444 403 403 419 403 403 419 427 427 444 428 428 445 403 403 419 428 428 445 404 404 420 404 404 420 428 428 445 429 429 446 404 404 420 429 429 446 405 405 421 405 405 421 429 429 446 430 430 447 405 405 421 430 430 447 406 406 422 406 406 422 430 430 447 431 431 448 406 406 422 431 431 448 407 407 423 407 407 423 431 431 448 408 408 449 407 407 423 408 408 449 384 384 424 408 408 425 432 432 450 433 433 451 408 408 425 433 433 451 409 409 426 409 409 426 433 433 451 434 434 452 409 409 426 434 434 452 410 410 427 410 410 427 434 434 452 435 435 453 410 410 427 435 435 453 411 411 428 411 411 428 435 435 453 436 436 454 411 411 428 436 436 454 412 412 429 412 412 429 436 436 454 437 437 455 412 412 429 437 437 455 413 413 430 413 413 430 437 437 455 438 438 456 413 413 430 438 438 456 414 414 431 414 414 431 438 438 456 439 439 457 414 414 431 439 439 457 415 415 432 415 415 432 439 439 457 440 440 458 415 415 432 440 440 458 416 416 433 416 416 433 440 440 458 441 441 459 416 416 433 441 441 459 417 417 434 417 417 434 441 441 459 442 442 460 417 417 434 442 442 460 418 418 435 418 418 435 442 442 460 443 443 461 418 418 435 443 443 461 419 419 436 419 419 436 443 443 461 444 444 462 419 419 436 444 444 462 420 420 437 420 420 437 444 444 462 445 445 463 420 420 437 445 445 463 421 421 438 421 421 438 445 445 463 446 446 464 421 421 438 446 446 464 422 422 439 422 422 439 446 446 464 447 447 465 422 422 439 447 447 465 423 423 440 423 423 440 447 447 465 448 448 466 423 423 440 448 448 466 424 424 441 424 424 441 448 448 466 449 449 467 424 424 441 449 449 467 425 425 442 425 425 442 449 449 467 450 450 468 425 425 442 450 450 468 426 426 443 426 426 443 450 450 468 451 451 469 426 426 443 451 451 469 427 427 444 427 427 444 451 451 469 452 452 470 427 427 444 452 452 470 428 428 445 428 428 445 452 452 470 453 453 471 428 428 445 453 453 471 429 429 446 429 429 446 453 453 471 454 454 472 429 429 446 454 454 472 430 430 447 430 430 447 454 454 472 455 455 473 430 430 447 455 455 473 431 431 448 431 431 448 455 455 473 432 432 474 431 431 448 432 432 474 408 408 449 432 432 450 456 456 475 457 457 476 432 432 450 457 457 476 433 433 451 433 433 451 457 457 476 458 458 477 433 433 451 458 458 477 434 434 452 434 434 452 458 458 477 459 459 478 434 434 452 459 459 478 435 435 453 435 435 453 459 459 478 460 460 479 435 435 453 460 460 479 436 436 454 436 436 454 460 460 479 461 461 480 436 436 454 461 461 480 437 437 455 437 437 455 461 461 480 462 462 481 437 437 455 462 462 481 438 438 456 438 438 456 462 462 481 463 463 482 438 438 456 463 463 482 439 439 457 439 439 457 463 463 482 464 464 483 439 439 457 464 464 483 440 440 458 440 440 458 464 464 483 465 465 484 440 440 458 465 465 484 441 441 459 441 441 459 465 465 484 466 466 485 441 441 459 466 466 485 442 442 460 442 442 460 466 466 485 467 467 486 442 442 460 467 467 486 443 443 461 443 443 461 467 467 486 468 468 487 443 443 461 468 468 487 444 444 462 444 444 462 468 468 487 469 469 488 444 444 462 469 469 488 445 445 463 445 445 463 469 469 488 470 470 489 445 445 463 470 470 489 446 446 464 446 446 464 470 470 489 471 471 490 446 446 464 471 471 490 447 447 465 447 447 465 471 471 490 472 472 491 447 447 465 472 472 491 448 448 466 448 448 466 472 472 491 473 473 492 448 448 466 473 473 492 449 449 467 449 449 467 473 473 492 474 474 493 449 449 467 474 474 493 450 450 468 450 450 468 474 474 493 475 475 494 450 450 468 475 475 494 451 451 469 451 451 469 475 475 494 476 476 495 451 451 469 476 476 495 452 452 470 452 452 470 476 476 495 477 477 496 452 452 470 477 477 496 453 453 471 453 453 471 477 477 496 478 478 497 453 453 471 478 478 497 454 454 472 454 454 472 478 478 497 479 479 498 454 454 472 479 479 498 455 455 473 455 455 473 479 479 498 456 456 499 455 455 473 456 456 499 432 432 474 456 456 475 480 480 500 481 481 501 456 456 475 481 481 501 457 457 476 457 457 476 481 481 501 482 482 502 457 457 476 482 482 502 458 458 477 458 458 477 482 482 502 483 483 503 458 458 477 483 483 503 459 459 478 459 459 478 483 483 503 484 484 504 459 459 478 484 484 504 460 460 479 460 460 479 484 484 504 485 485 505 460 460 479 485 485 505 461 461 480 461 461 480 485 485 505 486 486 506 461 461 480 486 486 506 462 462 481 462 462 481 486 486 506 487 487 507 462 462 481 487 487 507 463 463 482 463 463 482 487 487 507 488 488 508 463 463 482 488 488 508 464 464 483 464 464 483 488 488 508 489 489 509 464 464 483 489 489 509 465 465 484 465 465 484 489 489 509 490 490 510 465 465 484 490 490 510 466 466 485 466 466 485 490 490 510 491 491 511 466 466 485 491 491 511 467 467 486 467 467 486 491 491 511 492 492 512 467 467 486 492 492 512 468 468 487 468 468 487 492 492 512 493 493 513 468 468 487 493 493 513 469 469 488 469 469 488 493 493 513 494 494 514 469 469 488 494 494 514 470 470 489 470 470 489 494 494 514 495 495 515 470 470 489 495 495 515 471 471 490 471 471 490 495 495 515 496 496 516 471 471 490 496 496 516 472 472 491 472 472 491 496 496 516 497 497 517 472 472 491 497 497 517 473 473 492 473 473 492 497 497 517 498 498 518 473 473 492 498 498 518 474 474 493 474 474 493 498 498 518 499 499 519 474 474 493 499 499 519 475 475 494 475 475 494 499 499 519 500 500 520 475 475 494 500 500 520 476 476 495 476 476 495 500 500 520 501 501 521 476 476 495 501 501 521 477 477 496 477 477 496 501 501 521 502 502 522 477 477 496 502 502 522 478 478 497 478 478 497 502 502 522 503 503 523 478 478 497 503 503 523 479 479 498 479 479 498 503 503 523 480 480 524 479 479 498 480 480 524 456 456 499 480 480 500 504 504 525 505 505 526 480 480 500 505 505 526 481 481 501 481 481 501 505 505 526 506 506 527 481 481 501 506 506 527 482 482 502 482 482 502 506 506 527 507 507 528 482 482 502 507 507 528 483 483 503 483 483 503 507 507 528 508 508 529 483 483 503 508 508 529 484 484 504 484 484 504 508 508 529 509 509 530 484 484 504 509 509 530 485 485 505 485 485 505 509 509 530 510 510 531 485 485 505 510 510 531 486 486 506 486 486 506 510 510 531 511 511 532 486 486 506 511 511 532 487 487 507 487 487 507 511 511 532 512 512 533 487 487 507 512 512 533 488 488 508 488 488 508 512 512 533 513 513 534 488 488 508 513 513 534 489 489 509 489 489 509 513 513 534 514 514 535 489 489 509 514 514 535 490 490 510 490 490 510 514 514 535 515 515 536 490 490 510 515 515 536 491 491 511 491 491 511 515 515 536 516 516 537 491 491 511 516 516 537 492 492 512 492 492 512 516 516 537 517 517 538 492 492 512 517 517 538 493 493 513 493 493 513 517 517 538 518 518 539 493 493 513 518 518 539 494 494 514 494 494 514 518 518 539 519 519 540 494 494 514 519 519 540 495 495 515 495 495 515 519 519 540 520 520 541 495 495 515 520 520 541 496 496 516 496 496 516 520 520 541 521 521 542 496 496 516 521 521 542 497 497 517 497 497 517 521 521 542 522 522 543 497 497 517 522 522 543 498 498 518 498 498 518 522 522 543 523 523 544 498 498 518 523 523 544 499 499 519 499 499 519 523 523 544 524 524 545 499 499 519 524 524 545 500 500 520 500 500 520 524 524 545 525 525 546 500 500 520 525 525 546 501 501 521 501 501 521 525 525 546 526 526 547 501 501 521 526 526 547 502 502 522 502 502 522 526 526 547 527 527 548 502 502 522 527 527 548 503 503 523 503 503 523 527 527 548 504 504 549 503 503 523 504 504 549 480 480 524 504 504 525 528 528 550 529 529 551 504 504 525 529 529 551 505 505 526 505 505 526 529 529 551 530 530 552 505 505 526 530 530 552 506 506 527 506 506 527 530 530 552 531 531 553 506 506 527 531 531 553 507 507 528 507 507 528 531 531 553 532 532 554 507 507 528 532 532 554 508 508 529 508 508 529 532 532 554 533 533 555 508 508 529 533 533 555 509 509 530 509 509 530 533 533 555 534 534 556 509 509 530 534 534 556 510 510 531 510 510 531 534 534 556 535 535 557 510 510 531 535 535 557 511 511 532 511 511 532 535 535 557 536 536 558 511 511 532 536 536 558 512 512 533 512 512 533 536 536 558 537 537 559 512 512 533 537 537 559 513 513 534 513 513 534 537 537 559 538 538 560 513 513 534 538 538 560 514 514 535 514 514 535 538 538 560 539 539 561 514 514 535 539 539 561 515 515 536 515 515 536 539 539 561 540 540 562 515 515 536 540 540 562 516 516 537 516 516 537 540 540 562 541 541 563 516 516 537 541 541 563 517 517 538 517 517 538 541 541 563 542 542 564 517 517 538 542 542 564 518 518 539 518 518 539 542 542 564 543 543 565 518 518 539 543 543 565 519 519 540 519 519 540 543 543 565 544 544 566 519 519 540 544 544 566 520 520 541 520 520 541 544 544 566 545 545 567 520 520 541 545 545 567 521 521 542 521 521 542 545 545 567 546 546 568 521 521 542 546 546 568 522 522 543 522 522 543 546 546 568 547 547 569 522 522 543 547 547 569 523 523 544 523 523 544 547 547 569 548 548 570 523 523 544 548 548 570 524 524 545 524 524 545 548 548 570 549 549 571 524 524 545 549 549 571 525 525 546 525 525 546 549 549 571 550 550 572 525 525 546 550 550 572 526 526 547 526 526 547 550 550 572 551 551 573 526 526 547 551 551 573 527 527 548 527 527 548 551 551 573 528 528 574 527 527 548 528 528 574 504 504 549 528 528 550 552 552 575 553 553 576 528 528 550 553 553 576 529 529 551 529 529 551 553 553 576 554 554 577 529 529 551 554 554 577 530 530 552 530 530 552 554 554 577 555 555 578 530 530 552 555 555 578 531 531 553 531 531 553 555 555 578 556 556 579 531 531 553 556 556 579 532 532 554 532 532 554 556 556 579 557 557 580 532 532 554 557 557 580 533 533 555 533 533 555 557 557 580 558 558 581 533 533 555 558 558 581 534 534 556 534 534 556 558 558 581 559 559 582 534 534 556 559 559 582 535 535 557 535 535 557 559 559 582 560 560 583 535 535 557 560 560 583 536 536 558 536 536 558 560 560 583 561 561 584 536 536 558 561 561 584 537 537 559 537 537 559 561 561 584 562 562 585 537 537 559 562 562 585 538 538 560 538 538 560 562 562 585 563 563 586 538 538 560 563 563 586 539 539 561 539 539 561 563 563 586 564 564 587 539 539 561 564 564 587 540 540 562 540 540 562 564 564 587 565 565 588 540 540 562 565 565 588 541 541 563 541 541 563 565 565 588 566 566 589 541 541 563 566 566 589 542 542 564 542 542 564 566 566 589 567 567 590 542 542 564 567 567 590 543 543 565 543 543 565 567 567 590 568 568 591 543 543 565 568 568 591 544 544 566 544 544 566 568 568 591 569 569 592 544 544 566 569 569 592 545 545 567 545 545 567 569 569 592 570 570 593 545 545 567 570 570 593 546 546 568 546 546 568 570 570 593 571 571 594 546 546 568 571 571 594 547 547 569 547 547 569 571 571 594 572 572 595 547 547 569 572 572 595 548 548 570 548 548 570 572 572 595 573 573 596 548 548 570 573 573 596 549 549 571 549 549 571 573 573 596 574 574 597 549 549 571 574 574 597 550 550 572 550 550 572 574 574 597 575 575 598 550 550 572 575 575 598 551 551 573 551 551 573 575 575 598 552 552 599 551 551 573 552 552 599 528 528 574 552 552 575 576 576 600 577 577 601 552 552 575 577 577 601 553 553 576 553 553 576 577 577 601 578 578 602 553 553 576 578 578 602 554 554 577 554 554 577 578 578 602 579 579 603 554 554 577 579 579 603 555 555 578 555 555 578 579 579 603 580 580 604 555 555 578 580 580 604 556 556 579 556 556 579 580 580 604 581 581 605 556 556 579 581 581 605 557 557 580 557 557 580 581 581 605 582 582 606 557 557 580 582 582 606 558 558 581 558 558 581 582 582 606 583 583 607 558 558 581 583 583 607 559 559 582 559 559 582 583 583 607 584 584 608 559 559 582 584 584 608 560 560 583 560 560 583 584 584 608 585 585 609 560 560 583 585 585 609 561 561 584 561 561 584 585 585 609 586 586 610 561 561 584 586 586 610 562 562 585 562 562 585 586 586 610 587 587 611 562 562 585 587 587 611 563 563 586 563 563 586 587 587 611 588 588 612 563 563 586 588 588 612 564 564 587 564 564 587 588 588 612 589 589 613 564 564 587 589 589 613 565 565 588 565 565 588 589 589 613 590 590 614 565 565 588 590 590 614 566 566 589 566 566 589 590 590 614 591 591 615 566 566 589 591 591 615 567 567 590 567 567 590 591 591 615 592 592 616 567 567 590 592 592 616 568 568 591 568 568 591 592 592 616 593 593 617 568 568 591 593 593 617 569 569 592 569 569 592 593 593 617 594 594 618 569 569 592 594 594 618 570 570 593 570 570 593 594 594 618 595 595 619 570 570 593 595 595 619 571 571 594 571 571 594 595 595 619 596 596 620 571 571 594 596 596 620 572 572 595 572 572 595 596 596 620 597 597 621 572 572 595 597 597 621 573 573 596 573 573 596 597 597 621 598 598 622 573 573 596 598 598 622 574 574 597 574 574 597 598 598 622 599 599 623 574 574 597 599 599 623 575 575 598 575 575 598 599 599 623 576 576 624 575 575 598 576 576 624 552 552 599 576 576 600 600 600 625 601 601 626 576 576 600 601 601 626 577 577 601 577 577 601 601 601 626 602 602 627 577 577 601 602 602 627 578 578 602 578 578 602 602 602 627 603 603 628 578 578 602 603 603 628 579 579 603 579 579 603 603 603 628 604 604 629 579 579 603 604 604 629 580 580 604 580 580 604 604 604 629 605 605 630 580 580 604 605 605 630 581 581 605 581 581 605 605 605 630 606 606 631 581 581 605 606 606 631 582 582 606 582 582 606 606 606 631 607 607 632 582 582 606 607 607 632 583 583 607 583 583 607 607 607 632 608 608 633 583 583 607 608 608 633 584 584 608 584 584 608 608 608 633 609 609 634 584 584 608 609 609 634 585 585 609 585 585 609 609 609 634 610 610 635 585 585 609 610 610 635 586 586 610 586 586 610 610 610 635 611 611 636 586 586 610 611 611 636 587 587 611 587 587 611 611 611 636 612 612 637 587 587 611 612 612 637 588 588 612 588 588 612 612 612 637 613 613 638 588 588 612 613 613 638 589 589 613 589 589 613 613 613 638 614 614 639 589 589 613 614 614 639 590 590 614 590 590 614 614 614 639 615 615 640 590 590 614 615 615 640 591 591 615 591 591 615 615 615 640 616 616 641 591 591 615 616 616 641 592 592 616 592 592 616 616 616 641 617 617 642 592 592 616 617 617 642 593 593 617 593 593 617 617 617 642 618 618 643 593 593 617 618 618 643 594 594 618 594 594 618 618 618 643 619 619 644 594 594 618 619 619 644 595 595 619 595 595 619 619 619 644 620 620 645 595 595 619 620 620 645 596 596 620 596 596 620 620 620 645 621 621 646 596 596 620 621 621 646 597 597 621 597 597 621 621 621 646 622 622 647 597 597 621 622 622 647 598 598 622 598 598 622 622 622 647 623 623 648 598 598 622 623 623 648 599 599 623 599 599 623 623 623 648 600 600 649 599 599 623 600 600 649 576 576 624 600 600 625 624 624 650 625 625 651 600 600 625 625 625 651 601 601 626 601 601 626 625 625 651 626 626 652 601 601 626 626 626 652 602 602 627 602 602 627 626 626 652 627 627 653 602 602 627 627 627 653 603 603 628 603 603 628 627 627 653 628 628 654 603 603 628 628 628 654 604 604 629 604 604 629 628 628 654 629 629 655 604 604 629 629 629 655 605 605 630 605 605 630 629 629 655 630 630 656 605 605 630 630 630 656 606 606 631 606 606 631 630 630 656 631 631 657 606 606 631 631 631 657 607 607 632 607 607 632 631 631 657 632 632 658 607 607 632 632 632 658 608 608 633 608 608 633 632 632 658 633 633 659 608 608 633 633 633 659 609 609 634 609 609 634 633 633 659 634 634 660 609 609 634 634 634 660 610 610 635 610 610 635 634 634 660 635 635 661 610 610 635 635 635 661 611 611 636 611 611 636 635 635 661 636 636 662 611 611 636 636 636 662 612 612 637 612 612 637 636 636 662 637 637 663 612 612 637 637 637 663 613 613 638 613 613 638 637 637 663 638 638 664 613 613 638 638 638 664 614 614 639 614 614 639 638 638 664 639 639 665 614 614 639 639 639 665 615 615 640 615 615 640 639 639 665 640 640 666 615 615 640 640 640 666 616 616 641 616 616 641 640 640 666 641 641 667 616 616 641 641 641 667 617 617 642 617 617 642 641 641 667 642 642 668 617 617 642 642 642 668 618 618 643 618 618 643 642 642 668 643 643 669 618 618 643 643 643 669 619 619 644 619 619 644 643 643 669 644 644 670 619 619 644 644 644 670 620 620 645 620 620 645 644 644 670 645 645 671 620 620 645 645 645 671 621 621 646 621 621 646 645 645 671 646 646 672 621 621 646 646 646 672 622 622 647 622 622 647 646 646 672 647 647 673 622 622 647 647 647 673 623 623 648 623 623 648 647 647 673 624 624 674 623 623 648 624 624 674 600 600 649 624 624 650 648 648 675 649 649 676 624 624 650 649 649 676 625 625 651 625 625 651 649 649 676 650 650 677 625 625 651 650 650 677 626 626 652 626 626 652 650 650 677 651 651 678 626 626 652 651 651 678 627 627 653 627 627 653 651 651 678 652 652 679 627 627 653 652 652 679 628 628 654 628 628 654 652 652 679 653 653 680 628 628 654 653 653 680 629 629 655 629 629 655 653 653 680 654 654 681 629 629 655 654 654 681 630 630 656 630 630 656 654 654 681 655 655 682 630 630 656 655 655 682 631 631 657 631 631 657 655 655 682 656 656 683 631 631 657 656 656 683 632 632 658 632 632 658 656 656 683 657 657 684 632 632 658 657 657 684 633 633 659 633 633 659 657 657 684 658 658 685 633 633 659 658 658 685 634 634 660 634 634 660 658 658 685 659 659 686 634 634 660 659 659 686 635 635 661 635 635 661 659 659 686 660 660 687 635 635 661 660 660 687 636 636 662 636 636 662 660 660 687 661 661 688 636 636 662 661 661 688 637 637 663 637 637 663 661 661 688 662 662 689 637 637 663 662 662 689 638 638 664 638 638 664 662 662 689 663 663 690 638 638 664 663 663 690 639 639 665 639 639 665 663 663 690 664 664 691 639 639 665 664 664 691 640 640 666 640 640 666 664 664 691 665 665 692 640 640 666 665 665 692 641 641 667 641 641 667 665 665 692 666 666 693 641 641 667 666 666 693 642 642 668 642 642 668 666 666 693 667 667 694 642 642 668 667 667 694 643 643 669 643 643 669 667 667 694 668 668 695 643 643 669 668 668 695 644 644 670 644 644 670 668 668 695 669 669 696 644 644 670 669 669 696 645 645 671 645 645 671 669 669 696 670 670 697 645 645 671 670 670 697 646 646 672 646 646 672 670 670 697 671 671 698 646 646 672 671 671 698 647 647 673 647 647 673 671 671 698 648 648 699 647 647 673 648 648 699 624 624 674 648 648 675 672 672 700 673 673 701 648 648 675 673 673 701 649 649 676 649 649 676 673 673 701 674 674 702 649 649 676 674 674 702 650 650 677 650 650 677 674 674 702 675 675 703 650 650 677 675 675 703 651 651 678 651 651 678 675 675 703 676 676 704 651 651 678 676 676 704 652 652 679 652 652 679 676 676 704 677 677 705 652 652 679 677 677 705 653 653 680 653 653 680 677 677 705 678 678 706 653 653 680 678 678 706 654 654 681 654 654 681 678 678 706 679 679 707 654 654 681 679 679 707 655 655 682 655 655 682 679 679 707 680 680 708 655 655 682 680 680 708 656 656 683 656 656 683 680 680 708 681 681 709 656 656 683 681 681 709 657 657 684 657 657 684 681 681 709 682 682 710 657 657 684 682 682 710 658 658 685 658 658 685 682 682 710 683 683 711 658 658 685 683 683 711 659 659 686 659 659 686 683 683 711 684 684 712 659 659 686 684 684 712 660 660 687 660 660 687 684 684 712 685 685 713 660 660 687 685 685 713 661 661 688 661 661 688 685 685 713 686 686 714 661 661 688 686 686 714 662 662 689 662 662 689 686 686 714 687 687 715 662 662 689 687 687 715 663 663 690 663 663 690 687 687 715 688 688 716 663 663 690 688 688 716 664 664 691 664 664 691 688 688 716 689 689 717 664 664 691 689 689 717 665 665 692 665 665 692 689 689 717 690 690 718 665 665 692 690 690 718 666 666 693 666 666 693 690 690 718 691 691 719 666 666 693 691 691 719 667 667 694 667 667 694 691 691 719 692 692 720 667 667 694 692 692 720 668 668 695 668 668 695 692 692 720 693 693 721 668 668 695 693 693 721 669 669 696 669 669 696 693 693 721 694 694 722 669 669 696 694 694 722 670 670 697 670 670 697 694 694 722 695 695 723 670 670 697 695 695 723 671 671 698 671 671 698 695 695 723 672 672 724 671 671 698 672 672 724 648 648 699 672 672 700 696 696 725 697 697 726 672 672 700 697 697 726 673 673 701 673 673 701 697 697 726 698 698 727 673 673 701 698 698 727 674 674 702 674 674 702 698 698 727 699 699 728 674 674 702 699 699 728 675 675 703 675 675 703 699 699 728 700 700 729 675 675 703 700 700 729 676 676 704 676 676 704 700 700 729 701 701 730 676 676 704 701 701 730 677 677 705 677 677 705 701 701 730 702 702 731 677 677 705 702 702 731 678 678 706 678 678 706 702 702 731 703 703 732 678 678 706 703 703 732 679 679 707 679 679 707 703 703 732 704 704 733 679 679 707 704 704 733 680 680 708 680 680 708 704 704 733 705 705 734 680 680 708 705 705 734 681 681 709 681 681 709 705 705 734 706 706 735 681 681 709 706 706 735 682 682 710 682 682 710 706 706 735 707 707 736 682 682 710 707 707 736 683 683 711 683 683 711 707 707 736 708 708 737 683 683 711 708 708 737 684 684 712 684 684 712 708 708 737 709 709 738 684 684 712 709 709 738 685 685 713 685 685 713 709 709 738 710 710 739 685 685 713 710 710 739 686 686 714 686 686 714 710 710 739 711 711 740 686 686 714 711 711 740 687 687 715 687 687 715 711 711 740 712 712 741 687 687 715 712 712 741 688 688 716 688 688 716 712 712 741 713 713 742 688 688 716 713 713 742 689 689 717 689 689 717 713 713 742 714 714 743 689 689 717 714 714 743 690 690 718 690 690 718 714 714 743 715 715 744 690 690 718 715 715 744 691 691 719 691 691 719 715 715 744 716 716 745 691 691 719 716 716 745 692 692 720 692 692 720 716 716 745 717 717 746 692 692 720 717 717 746 693 693 721 693 693 721 717 717 746 718 718 747 693 693 721 718 718 747 694 694 722 694 694 722 718 718 747 719 719 748 694 694 722 719 719 748 695 695 723 695 695 723 719 719 748 696 696 749 695 695 723 696 696 749 672 672 724 696 696 725 720 720 750 721 721 751 696 696 725 721 721 751 697 697 726 697 697 726 721 721 751 722 722 752 697 697 726 722 722 752 698 698 727 698 698 727 722 722 752 723 723 753 698 698 727 723 723 753 699 699 728 699 699 728 723 723 753 724 724 754 699 699 728 724 724 754 700 700 729 700 700 729 724 724 754 725 725 755 700 700 729 725 725 755 701 701 730 701 701 730 725 725 755 726 726 756 701 701 730 726 726 756 702 702 731 702 702 731 726 726 756 727 727 757 702 702 731 727 727 757 703 703 732 703 703 732 727 727 757 728 728 758 703 703 732 728 728 758 704 704 733 704 704 733 728 728 758 729 729 759 704 704 733 729 729 759 705 705 734 705 705 734 729 729 759 730 730 760 705 705 734 730 730 760 706 706 735 706 706 735 730 730 760 731 731 761 706 706 735 731 731 761 707 707 736 707 707 736 731 731 761 732 732 762 707 707 736 732 732 762 708 708 737 708 708 737 732 732 762 733 733 763 708 708 737 733 733 763 709 709 738 709 709 738 733 733 763 734 734 764 709 709 738 734 734 764 710 710 739 710 710 739 734 734 764 735 735 765 710 710 739 735 735 765 711 711 740 711 711 740 735 735 765 736 736 766 711 711 740 736 736 766 712 712 741 712 712 741 736 736 766 737 737 767 712 712 741 737 737 767 713 713 742 713 713 742 737 737 767 738 738 768 713 713 742 738 738 768 714 714 743 714 714 743 738 738 768 739 739 769 714 714 743 739 739 769 715 715 744 715 715 744 739 739 769 740 740 770 715 715 744 740 740 770 716 716 745 716 716 745 740 740 770 741 741 771 716 716 745 741 741 771 717 717 746 717 717 746 741 741 771 742 742 772 717 717 746 742 742 772 718 718 747 718 718 747 742 742 772 743 743 773 718 718 747 743 743 773 719 719 748 719 719 748 743 743 773 720 720 774 719 719 748 720 720 774 696 696 749 720 720 750 744 744 775 745 745 776 720 720 750 745 745 776 721 721 751 721 721 751 745 745 776 746 746 777 721 721 751 746 746 777 722 722 752 722 722 752 746 746 777 747 747 778 722 722 752 747 747 778 723 723 753 723 723 753 747 747 778 748 748 779 723 723 753 748 748 779 724 724 754 724 724 754 748 748 779 749 749 780 724 724 754 749 749 780 725 725 755 725 725 755 749 749 780 750 750 781 725 725 755 750 750 781 726 726 756 726 726 756 750 750 781 751 751 782 726 726 756 751 751 782 727 727 757 727 727 757 751 751 782 752 752 783 727 727 757 752 752 783 728 728 758 728 728 758 752 752 783 753 753 784 728 728 758 753 753 784 729 729 759 729 729 759 753 753 784 754 754 785 729 729 759 754 754 785 730 730 760 730 730 760 754 754 785 755 755 786 730 730 760 755 755 786 731 731 761 731 731 761 755 755 786 756 756 787 731 731 761 756 756 787 732 732 762 732 732 762 756 756 787 757 757 788 732 732 762 757 757 788 733 733 763 733 733 763 757 757 788 758 758 789 733 733 763 758 758 789 734 734 764 734 734 764 758 758 789 759 759 790 734 734 764 759 759 790 735 735 765 735 735 765 759 759 790 760 760 791 735 735 765 760 760 791 736 736 766 736 736 766 760 760 791 761 761 792 736 736 766 761 761 792 737 737 767 737 737 767 761 761 792 762 762 793 737 737 767 762 762 793 738 738 768 738 738 768 762 762 793 763 763 794 738 738 768 763 763 794 739 739 769 739 739 769 763 763 794 764 764 795 739 739 769 764 764 795 740 740 770 740 740 770 764 764 795 765 765 796 740 740 770 765 765 796 741 741 771 741 741 771 765 765 796 766 766 797 741 741 771 766 766 797 742 742 772 742 742 772 766 766 797 767 767 798 742 742 772 767 767 798 743 743 773 743 743 773 767 767 798 744 744 799 743 743 773 744 744 799 720 720 774 744 744 775 768 768 800 769 769 801 744 744 775 769 769 801 745 745 776 745 745 776 769 769 801 770 770 802 745 745 776 770 770 802 746 746 777 746 746 777 770 770 802 771 771 803 746 746 777 771 771 803 747 747 778 747 747 778 771 771 803 772 772 804 747 747 778 772 772 804 748 748 779 748 748 779 772 772 804 773 773 805 748 748 779 773 773 805 749 749 780 749 749 780 773 773 805 774 774 806 749 749 780 774 774 806 750 750 781 750 750 781 774 774 806 775 775 807 750 750 781 775 775 807 751 751 782 751 751 782 775 775 807 776 776 808 751 751 782 776 776 808 752 752 783 752 752 783 776 776 808 777 777 809 752 752 783 777 777 809 753 753 784 753 753 784 777 777 809 778 778 810 753 753 784 778 778 810 754 754 785 754 754 785 778 778 810 779 779 811 754 754 785 779 779 811 755 755 786 755 755 786 779 779 811 780 780 812 755 755 786 780 780 812 756 756 787 756 756 787 780 780 812 781 781 813 756 756 787 781 781 813 757 757 788 757 757 788 781 781 813 782 782 814 757 757 788 782 782 814 758 758 789 758 758 789 782 782 814 783 783 815 758 758 789 783 783 815 759 759 790 759 759 790 783 783 815 784 784 816 759 759 790 784 784 816 760 760 791 760 760 791 784 784 816 785 785 817 760 760 791 785 785 817 761 761 792 761 761 792 785 785 817 786 786 818 761 761 792 786 786 818 762 762 793 762 762 793 786 786 818 787 787 819 762 762 793 787 787 819 763 763 794 763 763 794 787 787 819 788 788 820 763 763 794 788 788 820 764 764 795 764 764 795 788 788 820 789 789 821 764 764 795 789 789 821 765 765 796 765 765 796 789 789 821 790 790 822 765 765 796 790 790 822 766 766 797 766 766 797 790 790 822 791 791 823 766 766 797 791 791 823 767 767 798 767 767 798 791 791 823 768 768 824 767 767 798 768 768 824 744 744 799 768 768 800 792 792 825 793 793 826 768 768 800 793 793 826 769 769 801 769 769 801 793 793 826 794 794 827 769 769 801 794 794 827 770 770 802 770 770 802 794 794 827 795 795 828 770 770 802 795 795 828 771 771 803 771 771 803 795 795 828 796 796 829 771 771 803 796 796 829 772 772 804 772 772 804 796 796 829 797 797 830 772 772 804 797 797 830 773 773 805 773 773 805 797 797 830 798 798 831 773 773 805 798 798 831 774 774 806 774 774 806 798 798 831 799 799 832 774 774 806 799 799 832 775 775 807 775 775 807 799 799 832 800 800 833 775 775 807 800 800 833 776 776 808 776 776 808 800 800 833 801 801 834 776 776 808 801 801 834 777 777 809 777 777 809 801 801 834 802 802 835 777 777 809 802 802 835 778 778 810 778 778 810 802 802 835 803 803 836 778 778 810 803 803 836 779 779 811 779 779 811 803 803 836 804 804 837 779 779 811 804 804 837 780 780 812 780 780 812 804 804 837 805 805 838 780 780 812 805 805 838 781 781 813 781 781 813 805 805 838 806 806 839 781 781 813 806 806 839 782 782 814 782 782 814 806 806 839 807 807 840 782 782 814 807 807 840 783 783 815 783 783 815 807 807 840 808 808 841 783 783 815 808 808 841 784 784 816 784 784 816 808 808 841 809 809 842 784 784 816 809 809 842 785 785 817 785 785 817 809 809 842 810 810 843 785 785 817 810 810 843 786 786 818 786 786 818 810 810 843 811 811 844 786 786 818 811 811 844 787 787 819 787 787 819 811 811 844 812 812 845 787 787 819 812 812 845 788 788 820 788 788 820 812 812 845 813 813 846 788 788 820 813 813 846 789 789 821 789 789 821 813 813 846 814 814 847 789 789 821 814 814 847 790 790 822 790 790 822 814 814 847 815 815 848 790 790 822 815 815 848 791 791 823 791 791 823 815 815 848 792 792 849 791 791 823 792 792 849 768 768 824 792 792 825 816 816 850 817 817 851 792 792 825 817 817 851 793 793 826 793 793 826 817 817 851 818 818 852 793 793 826 818 818 852 794 794 827 794 794 827 818 818 852 819 819 853 794 794 827 819 819 853 795 795 828 795 795 828 819 819 853 820 820 854 795 795 828 820 820 854 796 796 829 796 796 829 820 820 854 821 821 855 796 796 829 821 821 855 797 797 830 797 797 830 821 821 855 822 822 856 797 797 830 822 822 856 798 798 831 798 798 831 822 822 856 823 823 857 798 798 831 823 823 857 799 799 832 799 799 832 823 823 857 824 824 858 799 799 832 824 824 858 800 800 833 800 800 833 824 824 858 825 825 859 800 800 833 825 825 859 801 801 834 801 801 834 825 825 859 826 826 860 801 801 834 826 826 860 802 802 835 802 802 835 826 826 860 827 827 861 802 802 835 827 827 861 803 803 836 803 803 836 827 827 861 828 828 862 803 803 836 828 828 862 804 804 837 804 804 837 828 828 862 829 829 863 804 804 837 829 829 863 805 805 838 805 805 838 829 829 863 830 830 864 805 805 838 830 830 864 806 806 839 806 806 839 830 830 864 831 831 865 806 806 839 831 831 865 807 807 840 807 807 840 831 831 865 832 832 866 807 807 840 832 832 866 808 808 841 808 808 841 832 832 866 833 833 867 808 808 841 833 833 867 809 809 842 809 809 842 833 833 867 834 834 868 809 809 842 834 834 868 810 810 843 810 810 843 834 834 868 835 835 869 810 810 843 835 835 869 811 811 844 811 811 844 835 835 869 836 836 870 811 811 844 836 836 870 812 812 845 812 812 845 836 836 870 837 837 871 812 812 845 837 837 871 813 813 846 813 813 846 837 837 871 838 838 872 813 813 846 838 838 872 814 814 847 814 814 847 838 838 872 839 839 873 814 814 847 839 839 873 815 815 848 815 815 848 839 839 873 816 816 874 815 815 848 816 816 874 792 792 849 816 816 850 840 840 875 841 841 876 816 816 850 841 841 876 817 817 851 817 817 851 841 841 876 842 842 877 817 817 851 842 842 877 818 818 852 818 818 852 842 842 877 843 843 878 818 818 852 843 843 878 819 819 853 819 819 853 843 843 878 844 844 879 819 819 853 844 844 879 820 820 854 820 820 854 844 844 879 845 845 880 820 820 854 845 845 880 821 821 855 821 821 855 845 845 880 846 846 881 821 821 855 846 846 881 822 822 856 822 822 856 846 846 881 847 847 882 822 822 856 847 847 882 823 823 857 823 823 857 847 847 882 848 848 883 823 823 857 848 848 883 824 824 858 824 824 858 848 848 883 849 849 884 824 824 858 849 849 884 825 825 859 825 825 859 849 849 884 850 850 885 825 825 859 850 850 885 826 826 860 826 826 860 850 850 885 851 851 886 826 826 860 851 851 886 827 827 861 827 827 861 851 851 886 852 852 887 827 827 861 852 852 887 828 828 862 828 828 862 852 852 887 853 853 888 828 828 862 853 853 888 829 829 863 829 829 863 853 853 888 854 854 889 829 829 863 854 854 889 830 830 864 830 830 864 854 854 889 855 855 890 830 830 864 855 855 890 831 831 865 831 831 865 855 855 890 856 856 891 831 831 865 856 856 891 832 832 866 832 832 866 856 856 891 857 857 892 832 832 866 857 857 892 833 833 867 833 833 867 857 857 892 858 858 893 833 833 867 858 858 893 834 834 868 834 834 868 858 858 893 859 859 894 834 834 868 859 859 894 835 835 869 835 835 869 859 859 894 860 860 895 835 835 869 860 860 895 836 836 870 836 836 870 860 860 895 861 861 896 836 836 870 861 861 896 837 837 871 837 837 871 861 861 896 862 862 897 837 837 871 862 862 897 838 838 872 838 838 872 862 862 897 863 863 898 838 838 872 863 863 898 839 839 873 839 839 873 863 863 898 840 840 899 839 839 873 840 840 899 816 816 874 840 840 875 864 864 900 865 865 901 840 840 875 865 865 901 841 841 876 841 841 876 865 865 901 866 866 902 841 841 876 866 866 902 842 842 877 842 842 877 866 866 902 867 867 903 842 842 877 867 867 903 843 843 878 843 843 878 867 867 903 868 868 904 843 843 878 868 868 904 844 844 879 844 844 879 868 868 904 869 869 905 844 844 879 869 869 905 845 845 880 845 845 880 869 869 905 870 870 906 845 845 880 870 870 906 846 846 881 846 846 881 870 870 906 871 871 907 846 846 881 871 871 907 847 847 882 847 847 882 871 871 907 872 872 908 847 847 882 872 872 908 848 848 883 848 848 883 872 872 908 873 873 909 848 848 883 873 873 909 849 849 884 849 849 884 873 873 909 874 874 910 849 849 884 874 874 910 850 850 885 850 850 885 874 874 910 875 875 911 850 850 885 875 875 911 851 851 886 851 851 886 875 875 911 876 876 912 851 851 886 876 876 912 852 852 887 852 852 887 876 876 912 877 877 913 852 852 887 877 877 913 853 853 888 853 853 888 877 877 913 878 878 914 853 853 888 878 878 914 854 854 889 854 854 889 878 878 914 879 879 915 854 854 889 879 879 915 855 855 890 855 855 890 879 879 915 880 880 916 855 855 890 880 880 916 856 856 891 856 856 891 880 880 916 881 881 917 856 856 891 881 881 917 857 857 892 857 857 892 881 881 917 882 882 918 857 857 892 882 882 918 858 858 893 858 858 893 882 882 918 883 883 919 858 858 893 883 883 919 859 859 894 859 859 894 883 883 919 884 884 920 859 859 894 884 884 920 860 860 895 860 860 895 884 884 920 885 885 921 860 860 895 885 885 921 861 861 896 861 861 896 885 885 921 886 886 922 861 861 896 886 886 922 862 862 897 862 862 897 886 886 922 887 887 923 862 862 897 887 887 923 863 863 898 863 863 898 887 887 923 864 864 924 863 863 898 864 864 924 840 840 899 864 864 900 888 888 925 889 889 926 864 864 900 889 889 926 865 865 901 865 865 901 889 889 926 890 890 927 865 865 901 890 890 927 866 866 902 866 866 902 890 890 927 891 891 928 866 866 902 891 891 928 867 867 903 867 867 903 891 891 928 892 892 929 867 867 903 892 892 929 868 868 904 868 868 904 892 892 929 893 893 930 868 868 904 893 893 930 869 869 905 869 869 905 893 893 930 894 894 931 869 869 905 894 894 931 870 870 906 870 870 906 894 894 931 895 895 932 870 870 906 895 895 932 871 871 907 871 871 907 895 895 932 896 896 933 871 871 907 896 896 933 872 872 908 872 872 908 896 896 933 897 897 934 872 872 908 897 897 934 873 873 909 873 873 909 897 897 934 898 898 935 873 873 909 898 898 935 874 874 910 874 874 910 898 898 935 899 899 936 874 874 910 899 899 936 875 875 911 875 875 911 899 899 936 900 900 937 875 875 911 900 900 937 876 876 912 876 876 912 900 900 937 901 901 938 876 876 912 901 901 938 877 877 913 877 877 913 901 901 938 902 902 939 877 877 913 902 902 939 878 878 914 878 878 914 902 902 939 903 903 940 878 878 914 903 903 940 879 879 915 879 879 915 903 903 940 904 904 941 879 879 915 904 904 941 880 880 916 880 880 916 904 904 941 905 905 942 880 880 916 905 905 942 881 881 917 881 881 917 905 905 942 906 906 943 881 881 917 906 906 943 882 882 918 882 882 918 906 906 943 907 907 944 882 882 918 907 907 944 883 883 919 883 883 919 907 907 944 908 908 945 883 883 919 908 908 945 884 884 920 884 884 920 908 908 945 909 909 946 884 884 920 909 909 946 885 885 921 885 885 921 909 909 946 910 910 947 885 885 921 910 910 947 886 886 922 886 886 922 910 910 947 911 911 948 886 886 922 911 911 948 887 887 923 887 887 923 911 911 948 888 888 949 887 887 923 888 888 949 864 864 924 888 888 925 912 912 950 913 913 951 888 888 925 913 913 951 889 889 926 889 889 926 913 913 951 914 914 952 889 889 926 914 914 952 890 890 927 890 890 927 914 914 952 915 915 953 890 890 927 915 915 953 891 891 928 891 891 928 915 915 953 916 916 954 891 891 928 916 916 954 892 892 929 892 892 929 916 916 954 917 917 955 892 892 929 917 917 955 893 893 930 893 893 930 917 917 955 918 918 956 893 893 930 918 918 956 894 894 931 894 894 931 918 918 956 919 919 957 894 894 931 919 919 957 895 895 932 895 895 932 919 919 957 920 920 958 895 895 932 920 920 958 896 896 933 896 896 933 920 920 958 921 921 959 896 896 933 921 921 959 897 897 934 897 897 934 921 921 959 922 922 960 897 897 934 922 922 960 898 898 935 898 898 935 922 922 960 923 923 961 898 898 935 923 923 961 899 899 936 899 899 936 923 923 961 924 924 962 899 899 936 924 924 962 900 900 937 900 900 937 924 924 962 925 925 963 900 900 937 925 925 963 901 901 938 901 901 938 925 925 963 926 926 964 901 901 938 926 926 964 902 902 939 902 902 939 926 926 964 927 927 965 902 902 939 927 927 965 903 903 940 903 903 940 927 927 965 928 928 966 903 903 940 928 928 966 904 904 941 904 904 941 928 928 966 929 929 967 904 904 941 929 929 967 905 905 942 905 905 942 929 929 967 930 930 968 905 905 942 930 930 968 906 906 943 906 906 943 930 930 968 931 931 969 906 906 943 931 931 969 907 907 944 907 907 944 931 931 969 932 932 970 907 907 944 932 932 970 908 908 945 908 908 945 932 932 970 933 933 971 908 908 945 933 933 971 909 909 946 909 909 946 933 933 971 934 934 972 909 909 946 934 934 972 910 910 947 910 910 947 934 934 972 935 935 973 910 910 947 935 935 973 911 911 948 911 911 948 935 935 973 912 912 974 911 911 948 912 912 974 888 888 949 912 912 950 936 936 975 937 937 976 912 912 950 937 937 976 913 913 951 913 913 951 937 937 976 938 938 977 913 913 951 938 938 977 914 914 952 914 914 952 938 938 977 939 939 978 914 914 952 939 939 978 915 915 953 915 915 953 939 939 978 940 940 979 915 915 953 940 940 979 916 916 954 916 916 954 940 940 979 941 941 980 916 916 954 941 941 980 917 917 955 917 917 955 941 941 980 942 942 981 917 917 955 942 942 981 918 918 956 918 918 956 942 942 981 943 943 982 918 918 956 943 943 982 919 919 957 919 919 957 943 943 982 944 944 983 919 919 957 944 944 983 920 920 958 920 920 958 944 944 983 945 945 984 920 920 958 945 945 984 921 921 959 921 921 959 945 945 984 946 946 985 921 921 959 946 946 985 922 922 960 922 922 960 946 946 985 947 947 986 922 922 960 947 947 986 923 923 961 923 923 961 947 947 986 948 948 987 923 923 961 948 948 987 924 924 962 924 924 962 948 948 987 949 949 988 924 924 962 949 949 988 925 925 963 925 925 963 949 949 988 950 950 989 925 925 963 950 950 989 926 926 964 926 926 964 950 950 989 951 951 990 926 926 964 951 951 990 927 927 965 927 927 965 951 951 990 952 952 991 927 927 965 952 952 991 928 928 966 928 928 966 952 952 991 953 953 992 928 928 966 953 953 992 929 929 967 929 929 967 953 953 992 954 954 993 929 929 967 954 954 993 930 930 968 930 930 968 954 954 993 955 955 994 930 930 968 955 955 994 931 931 969 931 931 969 955 955 994 956 956 995 931 931 969 956 956 995 932 932 970 932 932 970 956 956 995 957 957 996 932 932 970 957 957 996 933 933 971 933 933 971 957 957 996 958 958 997 933 933 971 958 958 997 934 934 972 934 934 972 958 958 997 959 959 998 934 934 972 959 959 998 935 935 973 935 935 973 959 959 998 936 936 999 935 935 973 936 936 999 912 912 974 936 936 975 960 960 1000 961 961 1001 936 936 975 961 961 1001 937 937 976 937 937 976 961 961 1001 962 962 1002 937 937 976 962 962 1002 938 938 977 938 938 977 962 962 1002 963 963 1003 938 938 977 963 963 1003 939 939 978 939 939 978 963 963 1003 964 964 1004 939 939 978 964 964 1004 940 940 979 940 940 979 964 964 1004 965 965 1005 940 940 979 965 965 1005 941 941 980 941 941 980 965 965 1005 966 966 1006 941 941 980 966 966 1006 942 942 981 942 942 981 966 966 1006 967 967 1007 942 942 981 967 967 1007 943 943 982 943 943 982 967 967 1007 968 968 1008 943 943 982 968 968 1008 944 944 983 944 944 983 968 968 1008 969 969 1009 944 944 983 969 969 1009 945 945 984 945 945 984 969 969 1009 970 970 1010 945 945 984 970 970 1010 946 946 985 946 946 985 970 970 1010 971 971 1011 946 946 985 971 971 1011 947 947 986 947 947 986 971 971 1011 972 972 1012 947 947 986 972 972 1012 948 948 987 948 948 987 972 972 1012 973 973 1013 948 948 987 973 973 1013 949 949 988 949 949 988 973 973 1013 974 974 1014 949 949 988 974 974 1014 950 950 989 950 950 989 974 974 1014 975 975 1015 950 950 989 975 975 1015 951 951 990 951 951 990 975 975 1015 976 976 1016 951 951 990 976 976 1016 952 952 991 952 952 991 976 976 1016 977 977 1017 952 952 991 977 977 1017 953 953 992 953 953 992 977 977 1017 978 978 1018 953 953 992 978 978 1018 954 954 993 954 954 993 978 978 1018 979 979 1019 954 954 993 979 979 1019 955 955 994 955 955 994 979 979 1019 980 980 1020 955 955 994 980 980 1020 956 956 995 956 956 995 980 980 1020 981 981 1021 956 956 995 981 981 1021 957 957 996 957 957 996 981 981 1021 982 982 1022 957 957 996 982 982 1022 958 958 997 958 958 997 982 982 1022 983 983 1023 958 958 997 983 983 1023 959 959 998 959 959 998 983 983 1023 960 960 1024 959 959 998 960 960 1024 936 936 999 960 960 1000 984 984 1025 985 985 1026 960 960 1000 985 985 1026 961 961 1001 961 961 1001 985 985 1026 986 986 1027 961 961 1001 986 986 1027 962 962 1002 962 962 1002 986 986 1027 987 987 1028 962 962 1002 987 987 1028 963 963 1003 963 963 1003 987 987 1028 988 988 1029 963 963 1003 988 988 1029 964 964 1004 964 964 1004 988 988 1029 989 989 1030 964 964 1004 989 989 1030 965 965 1005 965 965 1005 989 989 1030 990 990 1031 965 965 1005 990 990 1031 966 966 1006 966 966 1006 990 990 1031 991 991 1032 966 966 1006 991 991 1032 967 967 1007 967 967 1007 991 991 1032 992 992 1033 967 967 1007 992 992 1033 968 968 1008 968 968 1008 992 992 1033 993 993 1034 968 968 1008 993 993 1034 969 969 1009 969 969 1009 993 993 1034 994 994 1035 969 969 1009 994 994 1035 970 970 1010 970 970 1010 994 994 1035 995 995 1036 970 970 1010 995 995 1036 971 971 1011 971 971 1011 995 995 1036 996 996 1037 971 971 1011 996 996 1037 972 972 1012 972 972 1012 996 996 1037 997 997 1038 972 972 1012 997 997 1038 973 973 1013 973 973 1013 997 997 1038 998 998 1039 973 973 1013 998 998 1039 974 974 1014 974 974 1014 998 998 1039 999 999 1040 974 974 1014 999 999 1040 975 975 1015 975 975 1015 999 999 1040 1000 1000 1041 975 975 1015 1000 1000 1041 976 976 1016 976 976 1016 1000 1000 1041 1001 1001 1042 976 976 1016 1001 1001 1042 977 977 1017 977 977 1017 1001 1001 1042 1002 1002 1043 977 977 1017 1002 1002 1043 978 978 1018 978 978 1018 1002 1002 1043 1003 1003 1044 978 978 1018 1003 1003 1044 979 979 1019 979 979 1019 1003 1003 1044 1004 1004 1045 979 979 1019 1004 1004 1045 980 980 1020 980 980 1020 1004 1004 1045 1005 1005 1046 980 980 1020 1005 1005 1046 981 981 1021 981 981 1021 1005 1005 1046 1006 1006 1047 981 981 1021 1006 1006 1047 982 982 1022 982 982 1022 1006 1006 1047 1007 1007 1048 982 982 1022 1007 1007 1048 983 983 1023 983 983 1023 1007 1007 1048 984 984 1049 983 983 1023 984 984 1049 960 960 1024 984 984 1025 1008 1008 1050 1009 1009 1051 984 984 1025 1009 1009 1051 985 985 1026 985 985 1026 1009 1009 1051 1010 1010 1052 985 985 1026 1010 1010 1052 986 986 1027 986 986 1027 1010 1010 1052 1011 1011 1053 986 986 1027 1011 1011 1053 987 987 1028 987 987 1028 1011 1011 1053 1012 1012 1054 987 987 1028 1012 1012 1054 988 988 1029 988 988 1029 1012 1012 1054 1013 1013 1055 988 988 1029 1013 1013 1055 989 989 1030 989 989 1030 1013 1013 1055 1014 1014 1056 989 989 1030 1014 1014 1056 990 990 1031 990 990 1031 1014 1014 1056 1015 1015 1057 990 990 1031 1015 1015 1057 991 991 1032 991 991 1032 1015 1015 1057 1016 1016 1058 991 991 1032 1016 1016 1058 992 992 1033 992 992 1033 1016 1016 1058 1017 1017 1059 992 992 1033 1017 1017 1059 993 993 1034 993 993 1034 1017 1017 1059 1018 1018 1060 993 993 1034 1018 1018 1060 994 994 1035 994 994 1035 1018 1018 1060 1019 1019 1061 994 994 1035 1019 1019 1061 995 995 1036 995 995 1036 1019 1019 1061 1020 1020 1062 995 995 1036 1020 1020 1062 996 996 1037 996 996 1037 1020 1020 1062 1021 1021 1063 996 996 1037 1021 1021 1063 997 997 1038 997 997 1038 1021 1021 1063 1022 1022 1064 997 997 1038 1022 1022 1064 998 998 1039 998 998 1039 1022 1022 1064 1023 1023 1065 998 998 1039 1023 1023 1065 999 999 1040 999 999 1040 1023 1023 1065 1024 1024 1066 999 999 1040 1024 1024 1066 1000 1000 1041 1000 1000 1041 1024 1024 1066 1025 1025 1067 1000 1000 1041 1025 1025 1067 1001 1001 1042 1001 1001 1042 1025 1025 1067 1026 1026 1068 1001 1001 1042 1026 1026 1068 1002 1002 1043 1002 1002 1043 1026 1026 1068 1027 1027 1069 1002 1002 1043 1027 1027 1069 1003 1003 1044 1003 1003 1044 1027 1027 1069 1028 1028 1070 1003 1003 1044 1028 1028 1070 1004 1004 1045 1004 1004 1045 1028 1028 1070 1029 1029 1071 1004 1004 1045 1029 1029 1071 1005 1005 1046 1005 1005 1046 1029 1029 1071 1030 1030 1072 1005 1005 1046 1030 1030 1072 1006 1006 1047 1006 1006 1047 1030 1030 1072 1031 1031 1073 1006 1006 1047 1031 1031 1073 1007 1007 1048 1007 1007 1048 1031 1031 1073 1008 1008 1074 1007 1007 1048 1008 1008 1074 984 984 1049 1008 1008 1050 1032 1032 1075 1033 1033 1076 1008 1008 1050 1033 1033 1076 1009 1009 1051 1009 1009 1051 1033 1033 1076 1034 1034 1077 1009 1009 1051 1034 1034 1077 1010 1010 1052 1010 1010 1052 1034 1034 1077 1035 1035 1078 1010 1010 1052 1035 1035 1078 1011 1011 1053 1011 1011 1053 1035 1035 1078 1036 1036 1079 1011 1011 1053 1036 1036 1079 1012 1012 1054 1012 1012 1054 1036 1036 1079 1037 1037 1080 1012 1012 1054 1037 1037 1080 1013 1013 1055 1013 1013 1055 1037 1037 1080 1038 1038 1081 1013 1013 1055 1038 1038 1081 1014 1014 1056 1014 1014 1056 1038 1038 1081 1039 1039 1082 1014 1014 1056 1039 1039 1082 1015 1015 1057 1015 1015 1057 1039 1039 1082 1040 1040 1083 1015 1015 1057 1040 1040 1083 1016 1016 1058 1016 1016 1058 1040 1040 1083 1041 1041 1084 1016 1016 1058 1041 1041 1084 1017 1017 1059 1017 1017 1059 1041 1041 1084 1042 1042 1085 1017 1017 1059 1042 1042 1085 1018 1018 1060 1018 1018 1060 1042 1042 1085 1043 1043 1086 1018 1018 1060 1043 1043 1086 1019 1019 1061 1019 1019 1061 1043 1043 1086 1044 1044 1087 1019 1019 1061 1044 1044 1087 1020 1020 1062 1020 1020 1062 1044 1044 1087 1045 1045 1088 1020 1020 1062 1045 1045 1088 1021 1021 1063 1021 1021 1063 1045 1045 1088 1046 1046 1089 1021 1021 1063 1046 1046 1089 1022 1022 1064 1022 1022 1064 1046 1046 1089 1047 1047 1090 1022 1022 1064 1047 1047 1090 1023 1023 1065 1023 1023 1065 1047 1047 1090 1048 1048 1091 1023 1023 1065 1048 1048 1091 1024 1024 1066 1024 1024 1066 1048 1048 1091 1049 1049 1092 1024 1024 1066 1049 1049 1092 1025 1025 1067 1025 1025 1067 1049 1049 1092 1050 1050 1093 1025 1025 1067 1050 1050 1093 1026 1026 1068 1026 1026 1068 1050 1050 1093 1051 1051 1094 1026 1026 1068 1051 1051 1094 1027 1027 1069 1027 1027 1069 1051 1051 1094 1052 1052 1095 1027 1027 1069 1052 1052 1095 1028 1028 1070 1028 1028 1070 1052 1052 1095 1053 1053 1096 1028 1028 1070 1053 1053 1096 1029 1029 1071 1029 1029 1071 1053 1053 1096 1054 1054 1097 1029 1029 1071 1054 1054 1097 1030 1030 1072 1030 1030 1072 1054 1054 1097 1055 1055 1098 1030 1030 1072 1055 1055 1098 1031 1031 1073 1031 1031 1073 1055 1055 1098 1032 1032 1099 1031 1031 1073 1032 1032 1099 1008 1008 1074 1032 1032 1075 1056 1056 1100 1057 1057 1101 1032 1032 1075 1057 1057 1101 1033 1033 1076 1033 1033 1076 1057 1057 1101 1058 1058 1102 1033 1033 1076 1058 1058 1102 1034 1034 1077 1034 1034 1077 1058 1058 1102 1059 1059 1103 1034 1034 1077 1059 1059 1103 1035 1035 1078 1035 1035 1078 1059 1059 1103 1060 1060 1104 1035 1035 1078 1060 1060 1104 1036 1036 1079 1036 1036 1079 1060 1060 1104 1061 1061 1105 1036 1036 1079 1061 1061 1105 1037 1037 1080 1037 1037 1080 1061 1061 1105 1062 1062 1106 1037 1037 1080 1062 1062 1106 1038 1038 1081 1038 1038 1081 1062 1062 1106 1063 1063 1107 1038 1038 1081 1063 1063 1107 1039 1039 1082 1039 1039 1082 1063 1063 1107 1064 1064 1108 1039 1039 1082 1064 1064 1108 1040 1040 1083 1040 1040 1083 1064 1064 1108 1065 1065 1109 1040 1040 1083 1065 1065 1109 1041 1041 1084 1041 1041 1084 1065 1065 1109 1066 1066 1110 1041 1041 1084 1066 1066 1110 1042 1042 1085 1042 1042 1085 1066 1066 1110 1067 1067 1111 1042 1042 1085 1067 1067 1111 1043 1043 1086 1043 1043 1086 1067 1067 1111 1068 1068 1112 1043 1043 1086 1068 1068 1112 1044 1044 1087 1044 1044 1087 1068 1068 1112 1069 1069 1113 1044 1044 1087 1069 1069 1113 1045 1045 1088 1045 1045 1088 1069 1069 1113 1070 1070 1114 1045 1045 1088 1070 1070 1114 1046 1046 1089 1046 1046 1089 1070 1070 1114 1071 1071 1115 1046 1046 1089 1071 1071 1115 1047 1047 1090 1047 1047 1090 1071 1071 1115 1072 1072 1116 1047 1047 1090 1072 1072 1116 1048 1048 1091 1048 1048 1091 1072 1072 1116 1073 1073 1117 1048 1048 1091 1073 1073 1117 1049 1049 1092 1049 1049 1092 1073 1073 1117 1074 1074 1118 1049 1049 1092 1074 1074 1118 1050 1050 1093 1050 1050 1093 1074 1074 1118 1075 1075 1119 1050 1050 1093 1075 1075 1119 1051 1051 1094 1051 1051 1094 1075 1075 1119 1076 1076 1120 1051 1051 1094 1076 1076 1120 1052 1052 1095 1052 1052 1095 1076 1076 1120 1077 1077 1121 1052 1052 1095 1077 1077 1121 1053 1053 1096 1053 1053 1096 1077 1077 1121 1078 1078 1122 1053 1053 1096 1078 1078 1122 1054 1054 1097 1054 1054 1097 1078 1078 1122 1079 1079 1123 1054 1054 1097 1079 1079 1123 1055 1055 1098 1055 1055 1098 1079 1079 1123 1056 1056 1124 1055 1055 1098 1056 1056 1124 1032 1032 1099 1056 1056 1100 1080 1080 1125 1081 1081 1126 1056 1056 1100 1081 1081 1126 1057 1057 1101 1057 1057 1101 1081 1081 1126 1082 1082 1127 1057 1057 1101 1082 1082 1127 1058 1058 1102 1058 1058 1102 1082 1082 1127 1083 1083 1128 1058 1058 1102 1083 1083 1128 1059 1059 1103 1059 1059 1103 1083 1083 1128 1084 1084 1129 1059 1059 1103 1084 1084 1129 1060 1060 1104 1060 1060 1104 1084 1084 1129 1085 1085 1130 1060 1060 1104 1085 1085 1130 1061 1061 1105 1061 1061 1105 1085 1085 1130 1086 1086 1131 1061 1061 1105 1086 1086 1131 1062 1062 1106 1062 1062 1106 1086 1086 1131 1087 1087 1132 1062 1062 1106 1087 1087 1132 1063 1063 1107 1063 1063 1107 1087 1087 1132 1088 1088 1133 1063 1063 1107 1088 1088 1133 1064 1064 1108 1064 1064 1108 1088 1088 1133 1089 1089 1134 1064 1064 1108 1089 1089 1134 1065 1065 1109 1065 1065 1109 1089 1089 1134 1090 1090 1135 1065 1065 1109 1090 1090 1135 1066 1066 1110 1066 1066 1110 1090 1090 1135 1091 1091 1136 1066 1066 1110 1091 1091 1136 1067 1067 1111 1067 1067 1111 1091 1091 1136 1092 1092 1137 1067 1067 1111 1092 1092 1137 1068 1068 1112 1068 1068 1112 1092 1092 1137 1093 1093 1138 1068 1068 1112 1093 1093 1138 1069 1069 1113 1069 1069 1113 1093 1093 1138 1094 1094 1139 1069 1069 1113 1094 1094 1139 1070 1070 1114 1070 1070 1114 1094 1094 1139 1095 1095 1140 1070 1070 1114 1095 1095 1140 1071 1071 1115 1071 1071 1115 1095 1095 1140 1096 1096 1141 1071 1071 1115 1096 1096 1141 1072 1072 1116 1072 1072 1116 1096 1096 1141 1097 1097 1142 1072 1072 1116 1097 1097 1142 1073 1073 1117 1073 1073 1117 1097 1097 1142 1098 1098 1143 1073 1073 1117 1098 1098 1143 1074 1074 1118 1074 1074 1118 1098 1098 1143 1099 1099 1144 1074 1074 1118 1099 1099 1144 1075 1075 1119 1075 1075 1119 1099 1099 1144 1100 1100 1145 1075 1075 1119 1100 1100 1145 1076 1076 1120 1076 1076 1120 1100 1100 1145 1101 1101 1146 1076 1076 1120 1101 1101 1146 1077 1077 1121 1077 1077 1121 1101 1101 1146 1102 1102 1147 1077 1077 1121 1102 1102 1147 1078 1078 1122 1078 1078 1122 1102 1102 1147 1103 1103 1148 1078 1078 1122 1103 1103 1148 1079 1079 1123 1079 1079 1123 1103 1103 1148 1080 1080 1149 1079 1079 1123 1080 1080 1149 1056 1056 1124 1080 1080 1125 1104 1104 1150 1105 1105 1151 1080 1080 1125 1105 1105 1151 1081 1081 1126 1081 1081 1126 1105 1105 1151 1106 1106 1152 1081 1081 1126 1106 1106 1152 1082 1082 1127 1082 1082 1127 1106 1106 1152 1107 1107 1153 1082 1082 1127 1107 1107 1153 1083 1083 1128 1083 1083 1128 1107 1107 1153 1108 1108 1154 1083 1083 1128 1108 1108 1154 1084 1084 1129 1084 1084 1129 1108 1108 1154 1109 1109 1155 1084 1084 1129 1109 1109 1155 1085 1085 1130 1085 1085 1130 1109 1109 1155 1110 1110 1156 1085 1085 1130 1110 1110 1156 1086 1086 1131 1086 1086 1131 1110 1110 1156 1111 1111 1157 1086 1086 1131 1111 1111 1157 1087 1087 1132 1087 1087 1132 1111 1111 1157 1112 1112 1158 1087 1087 1132 1112 1112 1158 1088 1088 1133 1088 1088 1133 1112 1112 1158 1113 1113 1159 1088 1088 1133 1113 1113 1159 1089 1089 1134 1089 1089 1134 1113 1113 1159 1114 1114 1160 1089 1089 1134 1114 1114 1160 1090 1090 1135 1090 1090 1135 1114 1114 1160 1115 1115 1161 1090 1090 1135 1115 1115 1161 1091 1091 1136 1091 1091 1136 1115 1115 1161 1116 1116 1162 1091 1091 1136 1116 1116 1162 1092 1092 1137 1092 1092 1137 1116 1116 1162 1117 1117 1163 1092 1092 1137 1117 1117 1163 1093 1093 1138 1093 1093 1138 1117 1117 1163 1118 1118 1164 1093 1093 1138 1118 1118 1164 1094 1094 1139 1094 1094 1139 1118 1118 1164 1119 1119 1165 1094 1094 1139 1119 1119 1165 1095 1095 1140 1095 1095 1140 1119 1119 1165 1120 1120 1166 1095 1095 1140 1120 1120 1166 1096 1096 1141 1096 1096 1141 1120 1120 1166 1121 1121 1167 1096 1096 1141 1121 1121 1167 1097 1097 1142 1097 1097 1142 1121 1121 1167 1122 1122 1168 1097 1097 1142 1122 1122 1168 1098 1098 1143 1098 1098 1143 1122 1122 1168 1123 1123 1169 1098 1098 1143 1123 1123 1169 1099 1099 1144 1099 1099 1144 1123 1123 1169 1124 1124 1170 1099 1099 1144 1124 1124 1170 1100 1100 1145 1100 1100 1145 1124 1124 1170 1125 1125 1171 1100 1100 1145 1125 1125 1171 1101 1101 1146 1101 1101 1146 1125 1125 1171 1126 1126 1172 1101 1101 1146 1126 1126 1172 1102 1102 1147 1102 1102 1147 1126 1126 1172 1127 1127 1173 1102 1102 1147 1127 1127 1173 1103 1103 1148 1103 1103 1148 1127 1127 1173 1104 1104 1174 1103 1103 1148 1104 1104 1174 1080 1080 1149 1104 1104 1150 1128 1128 1175 1129 1129 1176 1104 1104 1150 1129 1129 1176 1105 1105 1151 1105 1105 1151 1129 1129 1176 1130 1130 1177 1105 1105 1151 1130 1130 1177 1106 1106 1152 1106 1106 1152 1130 1130 1177 1131 1131 1178 1106 1106 1152 1131 1131 1178 1107 1107 1153 1107 1107 1153 1131 1131 1178 1132 1132 1179 1107 1107 1153 1132 1132 1179 1108 1108 1154 1108 1108 1154 1132 1132 1179 1133 1133 1180 1108 1108 1154 1133 1133 1180 1109 1109 1155 1109 1109 1155 1133 1133 1180 1134 1134 1181 1109 1109 1155 1134 1134 1181 1110 1110 1156 1110 1110 1156 1134 1134 1181 1135 1135 1182 1110 1110 1156 1135 1135 1182 1111 1111 1157 1111 1111 1157 1135 1135 1182 1136 1136 1183 1111 1111 1157 1136 1136 1183 1112 1112 1158 1112 1112 1158 1136 1136 1183 1137 1137 1184 1112 1112 1158 1137 1137 1184 1113 1113 1159 1113 1113 1159 1137 1137 1184 1138 1138 1185 1113 1113 1159 1138 1138 1185 1114 1114 1160 1114 1114 1160 1138 1138 1185 1139 1139 1186 1114 1114 1160 1139 1139 1186 1115 1115 1161 1115 1115 1161 1139 1139 1186 1140 1140 1187 1115 1115 1161 1140 1140 1187 1116 1116 1162 1116 1116 1162 1140 1140 1187 1141 1141 1188 1116 1116 1162 1141 1141 1188 1117 1117 1163 1117 1117 1163 1141 1141 1188 1142 1142 1189 1117 1117 1163 1142 1142 1189 1118 1118 1164 1118 1118 1164 1142 1142 1189 1143 1143 1190 1118 1118 1164 1143 1143 1190 1119 1119 1165 1119 1119 1165 1143 1143 1190 1144 1144 1191 1119 1119 1165 1144 1144 1191 1120 1120 1166 1120 1120 1166 1144 1144 1191 1145 1145 1192 1120 1120 1166 1145 1145 1192 1121 1121 1167 1121 1121 1167 1145 1145 1192 1146 1146 1193 1121 1121 1167 1146 1146 1193 1122 1122 1168 1122 1122 1168 1146 1146 1193 1147 1147 1194 1122 1122 1168 1147 1147 1194 1123 1123 1169 1123 1123 1169 1147 1147 1194 1148 1148 1195 1123 1123 1169 1148 1148 1195 1124 1124 1170 1124 1124 1170 1148 1148 1195 1149 1149 1196 1124 1124 1170 1149 1149 1196 1125 1125 1171 1125 1125 1171 1149 1149 1196 1150 1150 1197 1125 1125 1171 1150 1150 1197 1126 1126 1172 1126 1126 1172 1150 1150 1197 1151 1151 1198 1126 1126 1172 1151 1151 1198 1127 1127 1173 1127 1127 1173 1151 1151 1198 1128 1128 1199 1127 1127 1173 1128 1128 1199 1104 1104 1174 1128 1128 1175 1152 1152 1200 1153 1153 1201 1128 1128 1175 1153 1153 1201 1129 1129 1176 1129 1129 1176 1153 1153 1201 1154 1154 1202 1129 1129 1176 1154 1154 1202 1130 1130 1177 1130 1130 1177 1154 1154 1202 1155 1155 1203 1130 1130 1177 1155 1155 1203 1131 1131 1178 1131 1131 1178 1155 1155 1203 1156 1156 1204 1131 1131 1178 1156 1156 1204 1132 1132 1179 1132 1132 1179 1156 1156 1204 1157 1157 1205 1132 1132 1179 1157 1157 1205 1133 1133 1180 1133 1133 1180 1157 1157 1205 1158 1158 1206 1133 1133 1180 1158 1158 1206 1134 1134 1181 1134 1134 1181 1158 1158 1206 1159 1159 1207 1134 1134 1181 1159 1159 1207 1135 1135 1182 1135 1135 1182 1159 1159 1207 1160 1160 1208 1135 1135 1182 1160 1160 1208 1136 1136 1183 1136 1136 1183 1160 1160 1208 1161 1161 1209 1136 1136 1183 1161 1161 1209 1137 1137 1184 1137 1137 1184 1161 1161 1209 1162 1162 1210 1137 1137 1184 1162 1162 1210 1138 1138 1185 1138 1138 1185 1162 1162 1210 1163 1163 1211 1138 1138 1185 1163 1163 1211 1139 1139 1186 1139 1139 1186 1163 1163 1211 1164 1164 1212 1139 1139 1186 1164 1164 1212 1140 1140 1187 1140 1140 1187 1164 1164 1212 1165 1165 1213 1140 1140 1187 1165 1165 1213 1141 1141 1188 1141 1141 1188 1165 1165 1213 1166 1166 1214 1141 1141 1188 1166 1166 1214 1142 1142 1189 1142 1142 1189 1166 1166 1214 1167 1167 1215 1142 1142 1189 1167 1167 1215 1143 1143 1190 1143 1143 1190 1167 1167 1215 1168 1168 1216 1143 1143 1190 1168 1168 1216 1144 1144 1191 1144 1144 1191 1168 1168 1216 1169 1169 1217 1144 1144 1191 1169 1169 1217 1145 1145 1192 1145 1145 1192 1169 1169 1217 1170 1170 1218 1145 1145 1192 1170 1170 1218 1146 1146 1193 1146 1146 1193 1170 1170 1218 1171 1171 1219 1146 1146 1193 1171 1171 1219 1147 1147 1194 1147 1147 1194 1171 1171 1219 1172 1172 1220 1147 1147 1194 1172 1172 1220 1148 1148 1195 1148 1148 1195 1172 1172 1220 1173 1173 1221 1148 1148 1195 1173 1173 1221 1149 1149 1196 1149 1149 1196 1173 1173 1221 1174 1174 1222 1149 1149 1196 1174 1174 1222 1150 1150 1197 1150 1150 1197 1174 1174 1222 1175 1175 1223 1150 1150 1197 1175 1175 1223 1151 1151 1198 1151 1151 1198 1175 1175 1223 1152 1152 1224 1151 1151 1198 1152 1152 1224 1128 1128 1199 1152 1152 1200 1176 1176 1225 1177 1177 1226 1152 1152 1200 1177 1177 1226 1153 1153 1201 1153 1153 1201 1177 1177 1226 1178 1178 1227 1153 1153 1201 1178 1178 1227 1154 1154 1202 1154 1154 1202 1178 1178 1227 1179 1179 1228 1154 1154 1202 1179 1179 1228 1155 1155 1203 1155 1155 1203 1179 1179 1228 1180 1180 1229 1155 1155 1203 1180 1180 1229 1156 1156 1204 1156 1156 1204 1180 1180 1229 1181 1181 1230 1156 1156 1204 1181 1181 1230 1157 1157 1205 1157 1157 1205 1181 1181 1230 1182 1182 1231 1157 1157 1205 1182 1182 1231 1158 1158 1206 1158 1158 1206 1182 1182 1231 1183 1183 1232 1158 1158 1206 1183 1183 1232 1159 1159 1207 1159 1159 1207 1183 1183 1232 1184 1184 1233 1159 1159 1207 1184 1184 1233 1160 1160 1208 1160 1160 1208 1184 1184 1233 1185 1185 1234 1160 1160 1208 1185 1185 1234 1161 1161 1209 1161 1161 1209 1185 1185 1234 1186 1186 1235 1161 1161 1209 1186 1186 1235 1162 1162 1210 1162 1162 1210 1186 1186 1235 1187 1187 1236 1162 1162 1210 1187 1187 1236 1163 1163 1211 1163 1163 1211 1187 1187 1236 1188 1188 1237 1163 1163 1211 1188 1188 1237 1164 1164 1212 1164 1164 1212 1188 1188 1237 1189 1189 1238 1164 1164 1212 1189 1189 1238 1165 1165 1213 1165 1165 1213 1189 1189 1238 1190 1190 1239 1165 1165 1213 1190 1190 1239 1166 1166 1214 1166 1166 1214 1190 1190 1239 1191 1191 1240 1166 1166 1214 1191 1191 1240 1167 1167 1215 1167 1167 1215 1191 1191 1240 1192 1192 1241 1167 1167 1215 1192 1192 1241 1168 1168 1216 1168 1168 1216 1192 1192 1241 1193 1193 1242 1168 1168 1216 1193 1193 1242 1169 1169 1217 1169 1169 1217 1193 1193 1242 1194 1194 1243 1169 1169 1217 1194 1194 1243 1170 1170 1218 1170 1170 1218 1194 1194 1243 1195 1195 1244 1170 1170 1218 1195 1195 1244 1171 1171 1219 1171 1171 1219 1195 1195 1244 1196 1196 1245 1171 1171 1219 1196 1196 1245 1172 1172 1220 1172 1172 1220 1196 1196 1245 1197 1197 1246 1172 1172 1220 1197 1197 1246 1173 1173 1221 1173 1173 1221 1197 1197 1246 1198 1198 1247 1173 1173 1221 1198 1198 1247 1174 1174 1222 1174 1174 1222 1198 1198 1247 1199 1199 1248 1174 1174 1222 1199 1199 1248 1175 1175 1223 1175 1175 1223 1199 1199 1248 1176 1176 1249 1175 1175 1223 1176 1176 1249 1152 1152 1224 1176 1176 1225 1200 1200 1250 1201 1201 1251 1176 1176 1225 1201 1201 1251 1177 1177 1226 1177 1177 1226 1201 1201 1251 1202 1202 1252 1177 1177 1226 1202 1202 1252 1178 1178 1227 1178 1178 1227 1202 1202 1252 1203 1203 1253 1178 1178 1227 1203 1203 1253 1179 1179 1228 1179 1179 1228 1203 1203 1253 1204 1204 1254 1179 1179 1228 1204 1204 1254 1180 1180 1229 1180 1180 1229 1204 1204 1254 1205 1205 1255 1180 1180 1229 1205 1205 1255 1181 1181 1230 1181 1181 1230 1205 1205 1255 1206 1206 1256 1181 1181 1230 1206 1206 1256 1182 1182 1231 1182 1182 1231 1206 1206 1256 1207 1207 1257 1182 1182 1231 1207 1207 1257 1183 1183 1232 1183 1183 1232 1207 1207 1257 1208 1208 1258 1183 1183 1232 1208 1208 1258 1184 1184 1233 1184 1184 1233 1208 1208 1258 1209 1209 1259 1184 1184 1233 1209 1209 1259 1185 1185 1234 1185 1185 1234 1209 1209 1259 1210 1210 1260 1185 1185 1234 1210 1210 1260 1186 1186 1235 1186 1186 1235 1210 1210 1260 1211 1211 1261 1186 1186 1235 1211 1211 1261 1187 1187 1236 1187 1187 1236 1211 1211 1261 1212 1212 1262 1187 1187 1236 1212 1212 1262 1188 1188 1237 1188 1188 1237 1212 1212 1262 1213 1213 1263 1188 1188 1237 1213 1213 1263 1189 1189 1238 1189 1189 1238 1213 1213 1263 1214 1214 1264 1189 1189 1238 1214 1214 1264 1190 1190 1239 1190 1190 1239 1214 1214 1264 1215 1215 1265 1190 1190 1239 1215 1215 1265 1191 1191 1240 1191 1191 1240 1215 1215 1265 1216 1216 1266 1191 1191 1240 1216 1216 1266 1192 1192 1241 1192 1192 1241 1216 1216 1266 1217 1217 1267 1192 1192 1241 1217 1217 1267 1193 1193 1242 1193 1193 1242 1217 1217 1267 1218 1218 1268 1193 1193 1242 1218 1218 1268 1194 1194 1243 1194 1194 1243 1218 1218 1268 1219 1219 1269 1194 1194 1243 1219 1219 1269 1195 1195 1244 1195 1195 1244 1219 1219 1269 1220 1220 1270 1195 1195 1244 1220 1220 1270 1196 1196 1245 1196 1196 1245 1220 1220 1270 1221 1221 1271 1196 1196 1245 1221 1221 1271 1197 1197 1246 1197 1197 1246 1221 1221 1271 1222 1222 1272 1197 1197 1246 1222 1222 1272 1198 1198 1247 1198 1198 1247 1222 1222 1272 1223 1223 1273 1198 1198 1247 1223 1223 1273 1199 1199 1248 1199 1199 1248 1223 1223 1273 1200 1200 1274 1199 1199 1248 1200 1200 1274 1176 1176 1249 1200 1200 1250 1224 1224 1275 1225 1225 1276 1200 1200 1250 1225 1225 1276 1201 1201 1251 1201 1201 1251 1225 1225 1276 1226 1226 1277 1201 1201 1251 1226 1226 1277 1202 1202 1252 1202 1202 1252 1226 1226 1277 1227 1227 1278 1202 1202 1252 1227 1227 1278 1203 1203 1253 1203 1203 1253 1227 1227 1278 1228 1228 1279 1203 1203 1253 1228 1228 1279 1204 1204 1254 1204 1204 1254 1228 1228 1279 1229 1229 1280 1204 1204 1254 1229 1229 1280 1205 1205 1255 1205 1205 1255 1229 1229 1280 1230 1230 1281 1205 1205 1255 1230 1230 1281 1206 1206 1256 1206 1206 1256 1230 1230 1281 1231 1231 1282 1206 1206 1256 1231 1231 1282 1207 1207 1257 1207 1207 1257 1231 1231 1282 1232 1232 1283 1207 1207 1257 1232 1232 1283 1208 1208 1258 1208 1208 1258 1232 1232 1283 1233 1233 1284 1208 1208 1258 1233 1233 1284 1209 1209 1259 1209 1209 1259 1233 1233 1284 1234 1234 1285 1209 1209 1259 1234 1234 1285 1210 1210 1260 1210 1210 1260 1234 1234 1285 1235 1235 1286 1210 1210 1260 1235 1235 1286 1211 1211 1261 1211 1211 1261 1235 1235 1286 1236 1236 1287 1211 1211 1261 1236 1236 1287 1212 1212 1262 1212 1212 1262 1236 1236 1287 1237 1237 1288 1212 1212 1262 1237 1237 1288 1213 1213 1263 1213 1213 1263 1237 1237 1288 1238 1238 1289 1213 1213 1263 1238 1238 1289 1214 1214 1264 1214 1214 1264 1238 1238 1289 1239 1239 1290 1214 1214 1264 1239 1239 1290 1215 1215 1265 1215 1215 1265 1239 1239 1290 1240 1240 1291 1215 1215 1265 1240 1240 1291 1216 1216 1266 1216 1216 1266 1240 1240 1291 1241 1241 1292 1216 1216 1266 1241 1241 1292 1217 1217 1267 1217 1217 1267 1241 1241 1292 1242 1242 1293 1217 1217 1267 1242 1242 1293 1218 1218 1268 1218 1218 1268 1242 1242 1293 1243 1243 1294 1218 1218 1268 1243 1243 1294 1219 1219 1269 1219 1219 1269 1243 1243 1294 1244 1244 1295 1219 1219 1269 1244 1244 1295 1220 1220 1270 1220 1220 1270 1244 1244 1295 1245 1245 1296 1220 1220 1270 1245 1245 1296 1221 1221 1271 1221 1221 1271 1245 1245 1296 1246 1246 1297 1221 1221 1271 1246 1246 1297 1222 1222 1272 1222 1222 1272 1246 1246 1297 1247 1247 1298 1222 1222 1272 1247 1247 1298 1223 1223 1273 1223 1223 1273 1247 1247 1298 1224 1224 1299 1223 1223 1273 1224 1224 1299 1200 1200 1274 1224 1224 1275 1248 1248 1300 1249 1249 1301 1224 1224 1275 1249 1249 1301 1225 1225 1276 1225 1225 1276 1249 1249 1301 1250 1250 1302 1225 1225 1276 1250 1250 1302 1226 1226 1277 1226 1226 1277 1250 1250 1302 1251 1251 1303 1226 1226 1277 1251 1251 1303 1227 1227 1278 1227 1227 1278 1251 1251 1303 1252 1252 1304 1227 1227 1278 1252 1252 1304 1228 1228 1279 1228 1228 1279 1252 1252 1304 1253 1253 1305 1228 1228 1279 1253 1253 1305 1229 1229 1280 1229 1229 1280 1253 1253 1305 1254 1254 1306 1229 1229 1280 1254 1254 1306 1230 1230 1281 1230 1230 1281 1254 1254 1306 1255 1255 1307 1230 1230 1281 1255 1255 1307 1231 1231 1282 1231 1231 1282 1255 1255 1307 1256 1256 1308 1231 1231 1282 1256 1256 1308 1232 1232 1283 1232 1232 1283 1256 1256 1308 1257 1257 1309 1232 1232 1283 1257 1257 1309 1233 1233 1284 1233 1233 1284 1257 1257 1309 1258 1258 1310 1233 1233 1284 1258 1258 1310 1234 1234 1285 1234 1234 1285 1258 1258 1310 1259 1259 1311 1234 1234 1285 1259 1259 1311 1235 1235 1286 1235 1235 1286 1259 1259 1311 1260 1260 1312 1235 1235 1286 1260 1260 1312 1236 1236 1287 1236 1236 1287 1260 1260 1312 1261 1261 1313 1236 1236 1287 1261 1261 1313 1237 1237 1288 1237 1237 1288 1261 1261 1313 1262 1262 1314 1237 1237 1288 1262 1262 1314 1238 1238 1289 1238 1238 1289 1262 1262 1314 1263 1263 1315 1238 1238 1289 1263 1263 1315 1239 1239 1290 1239 1239 1290 1263 1263 1315 1264 1264 1316 1239 1239 1290 1264 1264 1316 1240 1240 1291 1240 1240 1291 1264 1264 1316 1265 1265 1317 1240 1240 1291 1265 1265 1317 1241 1241 1292 1241 1241 1292 1265 1265 1317 1266 1266 1318 1241 1241 1292 1266 1266 1318 1242 1242 1293 1242 1242 1293 1266 1266 1318 1267 1267 1319 1242 1242 1293 1267 1267 1319 1243 1243 1294 1243 1243 1294 1267 1267 1319 1268 1268 1320 1243 1243 1294 1268 1268 1320 1244 1244 1295 1244 1244 1295 1268 1268 1320 1269 1269 1321 1244 1244 1295 1269 1269 1321 1245 1245 1296 1245 1245 1296 1269 1269 1321 1270 1270 1322 1245 1245 1296 1270 1270 1322 1246 1246 1297 1246 1246 1297 1270 1270 1322 1271 1271 1323 1246 1246 1297 1271 1271 1323 1247 1247 1298 1247 1247 1298 1271 1271 1323 1248 1248 1324 1247 1247 1298 1248 1248 1324 1224 1224 1299 1248 1248 1300 1272 1272 1325 1273 1273 1326 1248 1248 1300 1273 1273 1326 1249 1249 1301 1249 1249 1301 1273 1273 1326 1274 1274 1327 1249 1249 1301 1274 1274 1327 1250 1250 1302 1250 1250 1302 1274 1274 1327 1275 1275 1328 1250 1250 1302 1275 1275 1328 1251 1251 1303 1251 1251 1303 1275 1275 1328 1276 1276 1329 1251 1251 1303 1276 1276 1329 1252 1252 1304 1252 1252 1304 1276 1276 1329 1277 1277 1330 1252 1252 1304 1277 1277 1330 1253 1253 1305 1253 1253 1305 1277 1277 1330 1278 1278 1331 1253 1253 1305 1278 1278 1331 1254 1254 1306 1254 1254 1306 1278 1278 1331 1279 1279 1332 1254 1254 1306 1279 1279 1332 1255 1255 1307 1255 1255 1307 1279 1279 1332 1280 1280 1333 1255 1255 1307 1280 1280 1333 1256 1256 1308 1256 1256 1308 1280 1280 1333 1281 1281 1334 1256 1256 1308 1281 1281 1334 1257 1257 1309 1257 1257 1309 1281 1281 1334 1282 1282 1335 1257 1257 1309 1282 1282 1335 1258 1258 1310 1258 1258 1310 1282 1282 1335 1283 1283 1336 1258 1258 1310 1283 1283 1336 1259 1259 1311 1259 1259 1311 1283 1283 1336 1284 1284 1337 1259 1259 1311 1284 1284 1337 1260 1260 1312 1260 1260 1312 1284 1284 1337 1285 1285 1338 1260 1260 1312 1285 1285 1338 1261 1261 1313 1261 1261 1313 1285 1285 1338 1286 1286 1339 1261 1261 1313 1286 1286 1339 1262 1262 1314 1262 1262 1314 1286 1286 1339 1287 1287 1340 1262 1262 1314 1287 1287 1340 1263 1263 1315 1263 1263 1315 1287 1287 1340 1288 1288 1341 1263 1263 1315 1288 1288 1341 1264 1264 1316 1264 1264 1316 1288 1288 1341 1289 1289 1342 1264 1264 1316 1289 1289 1342 1265 1265 1317 1265 1265 1317 1289 1289 1342 1290 1290 1343 1265 1265 1317 1290 1290 1343 1266 1266 1318 1266 1266 1318 1290 1290 1343 1291 1291 1344 1266 1266 1318 1291 1291 1344 1267 1267 1319 1267 1267 1319 1291 1291 1344 1292 1292 1345 1267 1267 1319 1292 1292 1345 1268 1268 1320 1268 1268 1320 1292 1292 1345 1293 1293 1346 1268 1268 1320 1293 1293 1346 1269 1269 1321 1269 1269 1321 1293 1293 1346 1294 1294 1347 1269 1269 1321 1294 1294 1347 1270 1270 1322 1270 1270 1322 1294 1294 1347 1295 1295 1348 1270 1270 1322 1295 1295 1348 1271 1271 1323 1271 1271 1323 1295 1295 1348 1272 1272 1349 1271 1271 1323 1272 1272 1349 1248 1248 1324 1272 1272 1325 1296 1296 1350 1297 1297 1351 1272 1272 1325 1297 1297 1351 1273 1273 1326 1273 1273 1326 1297 1297 1351 1298 1298 1352 1273 1273 1326 1298 1298 1352 1274 1274 1327 1274 1274 1327 1298 1298 1352 1299 1299 1353 1274 1274 1327 1299 1299 1353 1275 1275 1328 1275 1275 1328 1299 1299 1353 1300 1300 1354 1275 1275 1328 1300 1300 1354 1276 1276 1329 1276 1276 1329 1300 1300 1354 1301 1301 1355 1276 1276 1329 1301 1301 1355 1277 1277 1330 1277 1277 1330 1301 1301 1355 1302 1302 1356 1277 1277 1330 1302 1302 1356 1278 1278 1331 1278 1278 1331 1302 1302 1356 1303 1303 1357 1278 1278 1331 1303 1303 1357 1279 1279 1332 1279 1279 1332 1303 1303 1357 1304 1304 1358 1279 1279 1332 1304 1304 1358 1280 1280 1333 1280 1280 1333 1304 1304 1358 1305 1305 1359 1280 1280 1333 1305 1305 1359 1281 1281 1334 1281 1281 1334 1305 1305 1359 1306 1306 1360 1281 1281 1334 1306 1306 1360 1282 1282 1335 1282 1282 1335 1306 1306 1360 1307 1307 1361 1282 1282 1335 1307 1307 1361 1283 1283 1336 1283 1283 1336 1307 1307 1361 1308 1308 1362 1283 1283 1336 1308 1308 1362 1284 1284 1337 1284 1284 1337 1308 1308 1362 1309 1309 1363 1284 1284 1337 1309 1309 1363 1285 1285 1338 1285 1285 1338 1309 1309 1363 1310 1310 1364 1285 1285 1338 1310 1310 1364 1286 1286 1339 1286 1286 1339 1310 1310 1364 1311 1311 1365 1286 1286 1339 1311 1311 1365 1287 1287 1340 1287 1287 1340 1311 1311 1365 1312 1312 1366 1287 1287 1340 1312 1312 1366 1288 1288 1341 1288 1288 1341 1312 1312 1366 1313 1313 1367 1288 1288 1341 1313 1313 1367 1289 1289 1342 1289 1289 1342 1313 1313 1367 1314 1314 1368 1289 1289 1342 1314 1314 1368 1290 1290 1343 1290 1290 1343 1314 1314 1368 1315 1315 1369 1290 1290 1343 1315 1315 1369 1291 1291 1344 1291 1291 1344 1315 1315 1369 1316 1316 1370 1291 1291 1344 1316 1316 1370 1292 1292 1345 1292 1292 1345 1316 1316 1370 1317 1317 1371 1292 1292 1345 1317 1317 1371 1293 1293 1346 1293 1293 1346 1317 1317 1371 1318 1318 1372 1293 1293 1346 1318 1318 1372 1294 1294 1347 1294 1294 1347 1318 1318 1372 1319 1319 1373 1294 1294 1347 1319 1319 1373 1295 1295 1348 1295 1295 1348 1319 1319 1373 1296 1296 1374 1295 1295 1348 1296 1296 1374 1272 1272 1349 1296 1296 1350 1320 1320 1375 1321 1321 1376 1296 1296 1350 1321 1321 1376 1297 1297 1351 1297 1297 1351 1321 1321 1376 1322 1322 1377 1297 1297 1351 1322 1322 1377 1298 1298 1352 1298 1298 1352 1322 1322 1377 1323 1323 1378 1298 1298 1352 1323 1323 1378 1299 1299 1353 1299 1299 1353 1323 1323 1378 1324 1324 1379 1299 1299 1353 1324 1324 1379 1300 1300 1354 1300 1300 1354 1324 1324 1379 1325 1325 1380 1300 1300 1354 1325 1325 1380 1301 1301 1355 1301 1301 1355 1325 1325 1380 1326 1326 1381 1301 1301 1355 1326 1326 1381 1302 1302 1356 1302 1302 1356 1326 1326 1381 1327 1327 1382 1302 1302 1356 1327 1327 1382 1303 1303 1357 1303 1303 1357 1327 1327 1382 1328 1328 1383 1303 1303 1357 1328 1328 1383 1304 1304 1358 1304 1304 1358 1328 1328 1383 1329 1329 1384 1304 1304 1358 1329 1329 1384 1305 1305 1359 1305 1305 1359 1329 1329 1384 1330 1330 1385 1305 1305 1359 1330 1330 1385 1306 1306 1360 1306 1306 1360 1330 1330 1385 1331 1331 1386 1306 1306 1360 1331 1331 1386 1307 1307 1361 1307 1307 1361 1331 1331 1386 1332 1332 1387 1307 1307 1361 1332 1332 1387 1308 1308 1362 1308 1308 1362 1332 1332 1387 1333 1333 1388 1308 1308 1362 1333 1333 1388 1309 1309 1363 1309 1309 1363 1333 1333 1388 1334 1334 1389 1309 1309 1363 1334 1334 1389 1310 1310 1364 1310 1310 1364 1334 1334 1389 1335 1335 1390 1310 1310 1364 1335 1335 1390 1311 1311 1365 1311 1311 1365 1335 1335 1390 1336 1336 1391 1311 1311 1365 1336 1336 1391 1312 1312 1366 1312 1312 1366 1336 1336 1391 1337 1337 1392 1312 1312 1366 1337 1337 1392 1313 1313 1367 1313 1313 1367 1337 1337 1392 1338 1338 1393 1313 1313 1367 1338 1338 1393 1314 1314 1368 1314 1314 1368 1338 1338 1393 1339 1339 1394 1314 1314 1368 1339 1339 1394 1315 1315 1369 1315 1315 1369 1339 1339 1394 1340 1340 1395 1315 1315 1369 1340 1340 1395 1316 1316 1370 1316 1316 1370 1340 1340 1395 1341 1341 1396 1316 1316 1370 1341 1341 1396 1317 1317 1371 1317 1317 1371 1341 1341 1396 1342 1342 1397 1317 1317 1371 1342 1342 1397 1318 1318 1372 1318 1318 1372 1342 1342 1397 1343 1343 1398 1318 1318 1372 1343 1343 1398 1319 1319 1373 1319 1319 1373 1343 1343 1398 1320 1320 1399 1319 1319 1373 1320 1320 1399 1296 1296 1374 1320 1320 1375 1344 1344 1400 1345 1345 1401 1320 1320 1375 1345 1345 1401 1321 1321 1376 1321 1321 1376 1345 1345 1401 1346 1346 1402 1321 1321 1376 1346 1346 1402 1322 1322 1377 1322 1322 1377 1346 1346 1402 1347 1347 1403 1322 1322 1377 1347 1347 1403 1323 1323 1378 1323 1323 1378 1347 1347 1403 1348 1348 1404 1323 1323 1378 1348 1348 1404 1324 1324 1379 1324 1324 1379 1348 1348 1404 1349 1349 1405 1324 1324 1379 1349 1349 1405 1325 1325 1380 1325 1325 1380 1349 1349 1405 1350 1350 1406 1325 1325 1380 1350 1350 1406 1326 1326 1381 1326 1326 1381 1350 1350 1406 1351 1351 1407 1326 1326 1381 1351 1351 1407 1327 1327 1382 1327 1327 1382 1351 1351 1407 1352 1352 1408 1327 1327 1382 1352 1352 1408 1328 1328 1383 1328 1328 1383 1352 1352 1408 1353 1353 1409 1328 1328 1383 1353 1353 1409 1329 1329 1384 1329 1329 1384 1353 1353 1409 1354 1354 1410 1329 1329 1384 1354 1354 1410 1330 1330 1385 1330 1330 1385 1354 1354 1410 1355 1355 1411 1330 1330 1385 1355 1355 1411 1331 1331 1386 1331 1331 1386 1355 1355 1411 1356 1356 1412 1331 1331 1386 1356 1356 1412 1332 1332 1387 1332 1332 1387 1356 1356 1412 1357 1357 1413 1332 1332 1387 1357 1357 1413 1333 1333 1388 1333 1333 1388 1357 1357 1413 1358 1358 1414 1333 1333 1388 1358 1358 1414 1334 1334 1389 1334 1334 1389 1358 1358 1414 1359 1359 1415 1334 1334 1389 1359 1359 1415 1335 1335 1390 1335 1335 1390 1359 1359 1415 1360 1360 1416 1335 1335 1390 1360 1360 1416 1336 1336 1391 1336 1336 1391 1360 1360 1416 1361 1361 1417 1336 1336 1391 1361 1361 1417 1337 1337 1392 1337 1337 1392 1361 1361 1417 1362 1362 1418 1337 1337 1392 1362 1362 1418 1338 1338 1393 1338 1338 1393 1362 1362 1418 1363 1363 1419 1338 1338 1393 1363 1363 1419 1339 1339 1394 1339 1339 1394 1363 1363 1419 1364 1364 1420 1339 1339 1394 1364 1364 1420 1340 1340 1395 1340 1340 1395 1364 1364 1420 1365 1365 1421 1340 1340 1395 1365 1365 1421 1341 1341 1396 1341 1341 1396 1365 1365 1421 1366 1366 1422 1341 1341 1396 1366 1366 1422 1342 1342 1397 1342 1342 1397 1366 1366 1422 1367 1367 1423 1342 1342 1397 1367 1367 1423 1343 1343 1398 1343 1343 1398 1367 1367 1423 1344 1344 1424 1343 1343 1398 1344 1344 1424 1320 1320 1399 1344 1344 1400 1368 1368 1425 1369 1369 1426 1344 1344 1400 1369 1369 1426 1345 1345 1401 1345 1345 1401 1369 1369 1426 1370 1370 1427 1345 1345 1401 1370 1370 1427 1346 1346 1402 1346 1346 1402 1370 1370 1427 1371 1371 1428 1346 1346 1402 1371 1371 1428 1347 1347 1403 1347 1347 1403 1371 1371 1428 1372 1372 1429 1347 1347 1403 1372 1372 1429 1348 1348 1404 1348 1348 1404 1372 1372 1429 1373 1373 1430 1348 1348 1404 1373 1373 1430 1349 1349 1405 1349 1349 1405 1373 1373 1430 1374 1374 1431 1349 1349 1405 1374 1374 1431 1350 1350 1406 1350 1350 1406 1374 1374 1431 1375 1375 1432 1350 1350 1406 1375 1375 1432 1351 1351 1407 1351 1351 1407 1375 1375 1432 1376 1376 1433 1351 1351 1407 1376 1376 1433 1352 1352 1408 1352 1352 1408 1376 1376 1433 1377 1377 1434 1352 1352 1408 1377 1377 1434 1353 1353 1409 1353 1353 1409 1377 1377 1434 1378 1378 1435 1353 1353 1409 1378 1378 1435 1354 1354 1410 1354 1354 1410 1378 1378 1435 1379 1379 1436 1354 1354 1410 1379 1379 1436 1355 1355 1411 1355 1355 1411 1379 1379 1436 1380 1380 1437 1355 1355 1411 1380 1380 1437 1356 1356 1412 1356 1356 1412 1380 1380 1437 1381 1381 1438 1356 1356 1412 1381 1381 1438 1357 1357 1413 1357 1357 1413 1381 1381 1438 1382 1382 1439 1357 1357 1413 1382 1382 1439 1358 1358 1414 1358 1358 1414 1382 1382 1439 1383 1383 1440 1358 1358 1414 1383 1383 1440 1359 1359 1415 1359 1359 1415 1383 1383 1440 1384 1384 1441 1359 1359 1415 1384 1384 1441 1360 1360 1416 1360 1360 1416 1384 1384 1441 1385 1385 1442 1360 1360 1416 1385 1385 1442 1361 1361 1417 1361 1361 1417 1385 1385 1442 1386 1386 1443 1361 1361 1417 1386 1386 1443 1362 1362 1418 1362 1362 1418 1386 1386 1443 1387 1387 1444 1362 1362 1418 1387 1387 1444 1363 1363 1419 1363 1363 1419 1387 1387 1444 1388 1388 1445 1363 1363 1419 1388 1388 1445 1364 1364 1420 1364 1364 1420 1388 1388 1445 1389 1389 1446 1364 1364 1420 1389 1389 1446 1365 1365 1421 1365 1365 1421 1389 1389 1446 1390 1390 1447 1365 1365 1421 1390 1390 1447 1366 1366 1422 1366 1366 1422 1390 1390 1447 1391 1391 1448 1366 1366 1422 1391 1391 1448 1367 1367 1423 1367 1367 1423 1391 1391 1448 1368 1368 1449 1367 1367 1423 1368 1368 1449 1344 1344 1424 1368 1368 1425 1392 1392 1450 1393 1393 1451 1368 1368 1425 1393 1393 1451 1369 1369 1426 1369 1369 1426 1393 1393 1451 1394 1394 1452 1369 1369 1426 1394 1394 1452 1370 1370 1427 1370 1370 1427 1394 1394 1452 1395 1395 1453 1370 1370 1427 1395 1395 1453 1371 1371 1428 1371 1371 1428 1395 1395 1453 1396 1396 1454 1371 1371 1428 1396 1396 1454 1372 1372 1429 1372 1372 1429 1396 1396 1454 1397 1397 1455 1372 1372 1429 1397 1397 1455 1373 1373 1430 1373 1373 1430 1397 1397 1455 1398 1398 1456 1373 1373 1430 1398 1398 1456 1374 1374 1431 1374 1374 1431 1398 1398 1456 1399 1399 1457 1374 1374 1431 1399 1399 1457 1375 1375 1432 1375 1375 1432 1399 1399 1457 1400 1400 1458 1375 1375 1432 1400 1400 1458 1376 1376 1433 1376 1376 1433 1400 1400 1458 1401 1401 1459 1376 1376 1433 1401 1401 1459 1377 1377 1434 1377 1377 1434 1401 1401 1459 1402 1402 1460 1377 1377 1434 1402 1402 1460 1378 1378 1435 1378 1378 1435 1402 1402 1460 1403 1403 1461 1378 1378 1435 1403 1403 1461 1379 1379 1436 1379 1379 1436 1403 1403 1461 1404 1404 1462 1379 1379 1436 1404 1404 1462 1380 1380 1437 1380 1380 1437 1404 1404 1462 1405 1405 1463 1380 1380 1437 1405 1405 1463 1381 1381 1438 1381 1381 1438 1405 1405 1463 1406 1406 1464 1381 1381 1438 1406 1406 1464 1382 1382 1439 1382 1382 1439 1406 1406 1464 1407 1407 1465 1382 1382 1439 1407 1407 1465 1383 1383 1440 1383 1383 1440 1407 1407 1465 1408 1408 1466 1383 1383 1440 1408 1408 1466 1384 1384 1441 1384 1384 1441 1408 1408 1466 1409 1409 1467 1384 1384 1441 1409 1409 1467 1385 1385 1442 1385 1385 1442 1409 1409 1467 1410 1410 1468 1385 1385 1442 1410 1410 1468 1386 1386 1443 1386 1386 1443 1410 1410 1468 1411 1411 1469 1386 1386 1443 1411 1411 1469 1387 1387 1444 1387 1387 1444 1411 1411 1469 1412 1412 1470 1387 1387 1444 1412 1412 1470 1388 1388 1445 1388 1388 1445 1412 1412 1470 1413 1413 1471 1388 1388 1445 1413 1413 1471 1389 1389 1446 1389 1389 1446 1413 1413 1471 1414 1414 1472 1389 1389 1446 1414 1414 1472 1390 1390 1447 1390 1390 1447 1414 1414 1472 1415 1415 1473 1390 1390 1447 1415 1415 1473 1391 1391 1448 1391 1391 1448 1415 1415 1473 1392 1392 1474 1391 1391 1448 1392 1392 1474 1368 1368 1449 1392 1392 1450 1416 1416 1475 1417 1417 1476 1392 1392 1450 1417 1417 1476 1393 1393 1451 1393 1393 1451 1417 1417 1476 1418 1418 1477 1393 1393 1451 1418 1418 1477 1394 1394 1452 1394 1394 1452 1418 1418 1477 1419 1419 1478 1394 1394 1452 1419 1419 1478 1395 1395 1453 1395 1395 1453 1419 1419 1478 1420 1420 1479 1395 1395 1453 1420 1420 1479 1396 1396 1454 1396 1396 1454 1420 1420 1479 1421 1421 1480 1396 1396 1454 1421 1421 1480 1397 1397 1455 1397 1397 1455 1421 1421 1480 1422 1422 1481 1397 1397 1455 1422 1422 1481 1398 1398 1456 1398 1398 1456 1422 1422 1481 1423 1423 1482 1398 1398 1456 1423 1423 1482 1399 1399 1457 1399 1399 1457 1423 1423 1482 1424 1424 1483 1399 1399 1457 1424 1424 1483 1400 1400 1458 1400 1400 1458 1424 1424 1483 1425 1425 1484 1400 1400 1458 1425 1425 1484 1401 1401 1459 1401 1401 1459 1425 1425 1484 1426 1426 1485 1401 1401 1459 1426 1426 1485 1402 1402 1460 1402 1402 1460 1426 1426 1485 1427 1427 1486 1402 1402 1460 1427 1427 1486 1403 1403 1461 1403 1403 1461 1427 1427 1486 1428 1428 1487 1403 1403 1461 1428 1428 1487 1404 1404 1462 1404 1404 1462 1428 1428 1487 1429 1429 1488 1404 1404 1462 1429 1429 1488 1405 1405 1463 1405 1405 1463 1429 1429 1488 1430 1430 1489 1405 1405 1463 1430 1430 1489 1406 1406 1464 1406 1406 1464 1430 1430 1489 1431 1431 1490 1406 1406 1464 1431 1431 1490 1407 1407 1465 1407 1407 1465 1431 1431 1490 1432 1432 1491 1407 1407 1465 1432 1432 1491 1408 1408 1466 1408 1408 1466 1432 1432 1491 1433 1433 1492 1408 1408 1466 1433 1433 1492 1409 1409 1467 1409 1409 1467 1433 1433 1492 1434 1434 1493 1409 1409 1467 1434 1434 1493 1410 1410 1468 1410 1410 1468 1434 1434 1493 1435 1435 1494 1410 1410 1468 1435 1435 1494 1411 1411 1469 1411 1411 1469 1435 1435 1494 1436 1436 1495 1411 1411 1469 1436 1436 1495 1412 1412 1470 1412 1412 1470 1436 1436 1495 1437 1437 1496 1412 1412 1470 1437 1437 1496 1413 1413 1471 1413 1413 1471 1437 1437 1496 1438 1438 1497 1413 1413 1471 1438 1438 1497 1414 1414 1472 1414 1414 1472 1438 1438 1497 1439 1439 1498 1414 1414 1472 1439 1439 1498 1415 1415 1473 1415 1415 1473 1439 1439 1498 1416 1416 1499 1415 1415 1473 1416 1416 1499 1392 1392 1474 1416 1416 1475 1440 1440 1500 1441 1441 1501 1416 1416 1475 1441 1441 1501 1417 1417 1476 1417 1417 1476 1441 1441 1501 1442 1442 1502 1417 1417 1476 1442 1442 1502 1418 1418 1477 1418 1418 1477 1442 1442 1502 1443 1443 1503 1418 1418 1477 1443 1443 1503 1419 1419 1478 1419 1419 1478 1443 1443 1503 1444 1444 1504 1419 1419 1478 1444 1444 1504 1420 1420 1479 1420 1420 1479 1444 1444 1504 1445 1445 1505 1420 1420 1479 1445 1445 1505 1421 1421 1480 1421 1421 1480 1445 1445 1505 1446 1446 1506 1421 1421 1480 1446 1446 1506 1422 1422 1481 1422 1422 1481 1446 1446 1506 1447 1447 1507 1422 1422 1481 1447 1447 1507 1423 1423 1482 1423 1423 1482 1447 1447 1507 1448 1448 1508 1423 1423 1482 1448 1448 1508 1424 1424 1483 1424 1424 1483 1448 1448 1508 1449 1449 1509 1424 1424 1483 1449 1449 1509 1425 1425 1484 1425 1425 1484 1449 1449 1509 1450 1450 1510 1425 1425 1484 1450 1450 1510 1426 1426 1485 1426 1426 1485 1450 1450 1510 1451 1451 1511 1426 1426 1485 1451 1451 1511 1427 1427 1486 1427 1427 1486 1451 1451 1511 1452 1452 1512 1427 1427 1486 1452 1452 1512 1428 1428 1487 1428 1428 1487 1452 1452 1512 1453 1453 1513 1428 1428 1487 1453 1453 1513 1429 1429 1488 1429 1429 1488 1453 1453 1513 1454 1454 1514 1429 1429 1488 1454 1454 1514 1430 1430 1489 1430 1430 1489 1454 1454 1514 1455 1455 1515 1430 1430 1489 1455 1455 1515 1431 1431 1490 1431 1431 1490 1455 1455 1515 1456 1456 1516 1431 1431 1490 1456 1456 1516 1432 1432 1491 1432 1432 1491 1456 1456 1516 1457 1457 1517 1432 1432 1491 1457 1457 1517 1433 1433 1492 1433 1433 1492 1457 1457 1517 1458 1458 1518 1433 1433 1492 1458 1458 1518 1434 1434 1493 1434 1434 1493 1458 1458 1518 1459 1459 1519 1434 1434 1493 1459 1459 1519 1435 1435 1494 1435 1435 1494 1459 1459 1519 1460 1460 1520 1435 1435 1494 1460 1460 1520 1436 1436 1495 1436 1436 1495 1460 1460 1520 1461 1461 1521 1436 1436 1495 1461 1461 1521 1437 1437 1496 1437 1437 1496 1461 1461 1521 1462 1462 1522 1437 1437 1496 1462 1462 1522 1438 1438 1497 1438 1438 1497 1462 1462 1522 1463 1463 1523 1438 1438 1497 1463 1463 1523 1439 1439 1498 1439 1439 1498 1463 1463 1523 1440 1440 1524 1439 1439 1498 1440 1440 1524 1416 1416 1499 1440 1440 1500 1464 1464 1525 1465 1465 1526 1440 1440 1500 1465 1465 1526 1441 1441 1501 1441 1441 1501 1465 1465 1526 1466 1466 1527 1441 1441 1501 1466 1466 1527 1442 1442 1502 1442 1442 1502 1466 1466 1527 1467 1467 1528 1442 1442 1502 1467 1467 1528 1443 1443 1503 1443 1443 1503 1467 1467 1528 1468 1468 1529 1443 1443 1503 1468 1468 1529 1444 1444 1504 1444 1444 1504 1468 1468 1529 1469 1469 1530 1444 1444 1504 1469 1469 1530 1445 1445 1505 1445 1445 1505 1469 1469 1530 1470 1470 1531 1445 1445 1505 1470 1470 1531 1446 1446 1506 1446 1446 1506 1470 1470 1531 1471 1471 1532 1446 1446 1506 1471 1471 1532 1447 1447 1507 1447 1447 1507 1471 1471 1532 1472 1472 1533 1447 1447 1507 1472 1472 1533 1448 1448 1508 1448 1448 1508 1472 1472 1533 1473 1473 1534 1448 1448 1508 1473 1473 1534 1449 1449 1509 1449 1449 1509 1473 1473 1534 1474 1474 1535 1449 1449 1509 1474 1474 1535 1450 1450 1510 1450 1450 1510 1474 1474 1535 1475 1475 1536 1450 1450 1510 1475 1475 1536 1451 1451 1511 1451 1451 1511 1475 1475 1536 1476 1476 1537 1451 1451 1511 1476 1476 1537 1452 1452 1512 1452 1452 1512 1476 1476 1537 1477 1477 1538 1452 1452 1512 1477 1477 1538 1453 1453 1513 1453 1453 1513 1477 1477 1538 1478 1478 1539 1453 1453 1513 1478 1478 1539 1454 1454 1514 1454 1454 1514 1478 1478 1539 1479 1479 1540 1454 1454 1514 1479 1479 1540 1455 1455 1515 1455 1455 1515 1479 1479 1540 1480 1480 1541 1455 1455 1515 1480 1480 1541 1456 1456 1516 1456 1456 1516 1480 1480 1541 1481 1481 1542 1456 1456 1516 1481 1481 1542 1457 1457 1517 1457 1457 1517 1481 1481 1542 1482 1482 1543 1457 1457 1517 1482 1482 1543 1458 1458 1518 1458 1458 1518 1482 1482 1543 1483 1483 1544 1458 1458 1518 1483 1483 1544 1459 1459 1519 1459 1459 1519 1483 1483 1544 1484 1484 1545 1459 1459 1519 1484 1484 1545 1460 1460 1520 1460 1460 1520 1484 1484 1545 1485 1485 1546 1460 1460 1520 1485 1485 1546 1461 1461 1521 1461 1461 1521 1485 1485 1546 1486 1486 1547 1461 1461 1521 1486 1486 1547 1462 1462 1522 1462 1462 1522 1486 1486 1547 1487 1487 1548 1462 1462 1522 1487 1487 1548 1463 1463 1523 1463 1463 1523 1487 1487 1548 1464 1464 1549 1463 1463 1523 1464 1464 1549 1440 1440 1524 1464 1464 1525 1488 1488 1550 1489 1489 1551 1464 1464 1525 1489 1489 1551 1465 1465 1526 1465 1465 1526 1489 1489 1551 1490 1490 1552 1465 1465 1526 1490 1490 1552 1466 1466 1527 1466 1466 1527 1490 1490 1552 1491 1491 1553 1466 1466 1527 1491 1491 1553 1467 1467 1528 1467 1467 1528 1491 1491 1553 1492 1492 1554 1467 1467 1528 1492 1492 1554 1468 1468 1529 1468 1468 1529 1492 1492 1554 1493 1493 1555 1468 1468 1529 1493 1493 1555 1469 1469 1530 1469 1469 1530 1493 1493 1555 1494 1494 1556 1469 1469 1530 1494 1494 1556 1470 1470 1531 1470 1470 1531 1494 1494 1556 1495 1495 1557 1470 1470 1531 1495 1495 1557 1471 1471 1532 1471 1471 1532 1495 1495 1557 1496 1496 1558 1471 1471 1532 1496 1496 1558 1472 1472 1533 1472 1472 1533 1496 1496 1558 1497 1497 1559 1472 1472 1533 1497 1497 1559 1473 1473 1534 1473 1473 1534 1497 1497 1559 1498 1498 1560 1473 1473 1534 1498 1498 1560 1474 1474 1535 1474 1474 1535 1498 1498 1560 1499 1499 1561 1474 1474 1535 1499 1499 1561 1475 1475 1536 1475 1475 1536 1499 1499 1561 1500 1500 1562 1475 1475 1536 1500 1500 1562 1476 1476 1537 1476 1476 1537 1500 1500 1562 1501 1501 1563 1476 1476 1537 1501 1501 1563 1477 1477 1538 1477 1477 1538 1501 1501 1563 1502 1502 1564 1477 1477 1538 1502 1502 1564 1478 1478 1539 1478 1478 1539 1502 1502 1564 1503 1503 1565 1478 1478 1539 1503 1503 1565 1479 1479 1540 1479 1479 1540 1503 1503 1565 1504 1504 1566 1479 1479 1540 1504 1504 1566 1480 1480 1541 1480 1480 1541 1504 1504 1566 1505 1505 1567 1480 1480 1541 1505 1505 1567 1481 1481 1542 1481 1481 1542 1505 1505 1567 1506 1506 1568 1481 1481 1542 1506 1506 1568 1482 1482 1543 1482 1482 1543 1506 1506 1568 1507 1507 1569 1482 1482 1543 1507 1507 1569 1483 1483 1544 1483 1483 1544 1507 1507 1569 1508 1508 1570 1483 1483 1544 1508 1508 1570 1484 1484 1545 1484 1484 1545 1508 1508 1570 1509 1509 1571 1484 1484 1545 1509 1509 1571 1485 1485 1546 1485 1485 1546 1509 1509 1571 1510 1510 1572 1485 1485 1546 1510 1510 1572 1486 1486 1547 1486 1486 1547 1510 1510 1572 1511 1511 1573 1486 1486 1547 1511 1511 1573 1487 1487 1548 1487 1487 1548 1511 1511 1573 1488 1488 1574 1487 1487 1548 1488 1488 1574 1464 1464 1549 1488 1488 1550 1512 1512 1575 1513 1513 1576 1488 1488 1550 1513 1513 1576 1489 1489 1551 1489 1489 1551 1513 1513 1576 1514 1514 1577 1489 1489 1551 1514 1514 1577 1490 1490 1552 1490 1490 1552 1514 1514 1577 1515 1515 1578 1490 1490 1552 1515 1515 1578 1491 1491 1553 1491 1491 1553 1515 1515 1578 1516 1516 1579 1491 1491 1553 1516 1516 1579 1492 1492 1554 1492 1492 1554 1516 1516 1579 1517 1517 1580 1492 1492 1554 1517 1517 1580 1493 1493 1555 1493 1493 1555 1517 1517 1580 1518 1518 1581 1493 1493 1555 1518 1518 1581 1494 1494 1556 1494 1494 1556 1518 1518 1581 1519 1519 1582 1494 1494 1556 1519 1519 1582 1495 1495 1557 1495 1495 1557 1519 1519 1582 1520 1520 1583 1495 1495 1557 1520 1520 1583 1496 1496 1558 1496 1496 1558 1520 1520 1583 1521 1521 1584 1496 1496 1558 1521 1521 1584 1497 1497 1559 1497 1497 1559 1521 1521 1584 1522 1522 1585 1497 1497 1559 1522 1522 1585 1498 1498 1560 1498 1498 1560 1522 1522 1585 1523 1523 1586 1498 1498 1560 1523 1523 1586 1499 1499 1561 1499 1499 1561 1523 1523 1586 1524 1524 1587 1499 1499 1561 1524 1524 1587 1500 1500 1562 1500 1500 1562 1524 1524 1587 1525 1525 1588 1500 1500 1562 1525 1525 1588 1501 1501 1563 1501 1501 1563 1525 1525 1588 1526 1526 1589 1501 1501 1563 1526 1526 1589 1502 1502 1564 1502 1502 1564 1526 1526 1589 1527 1527 1590 1502 1502 1564 1527 1527 1590 1503 1503 1565 1503 1503 1565 1527 1527 1590 1528 1528 1591 1503 1503 1565 1528 1528 1591 1504 1504 1566 1504 1504 1566 1528 1528 1591 1529 1529 1592 1504 1504 1566 1529 1529 1592 1505 1505 1567 1505 1505 1567 1529 1529 1592 1530 1530 1593 1505 1505 1567 1530 1530 1593 1506 1506 1568 1506 1506 1568 1530 1530 1593 1531 1531 1594 1506 1506 1568 1531 1531 1594 1507 1507 1569 1507 1507 1569 1531 1531 1594 1532 1532 1595 1507 1507 1569 1532 1532 1595 1508 1508 1570 1508 1508 1570 1532 1532 1595 1533 1533 1596 1508 1508 1570 1533 1533 1596 1509 1509 1571 1509 1509 1571 1533 1533 1596 1534 1534 1597 1509 1509 1571 1534 1534 1597 1510 1510 1572 1510 1510 1572 1534 1534 1597 1535 1535 1598 1510 1510 1572 1535 1535 1598 1511 1511 1573 1511 1511 1573 1535 1535 1598 1512 1512 1599 1511 1511 1573 1512 1512 1599 1488 1488 1574 1512 1512 1575 1536 1536 1600 1537 1537 1601 1512 1512 1575 1537 1537 1601 1513 1513 1576 1513 1513 1576 1537 1537 1601 1538 1538 1602 1513 1513 1576 1538 1538 1602 1514 1514 1577 1514 1514 1577 1538 1538 1602 1539 1539 1603 1514 1514 1577 1539 1539 1603 1515 1515 1578 1515 1515 1578 1539 1539 1603 1540 1540 1604 1515 1515 1578 1540 1540 1604 1516 1516 1579 1516 1516 1579 1540 1540 1604 1541 1541 1605 1516 1516 1579 1541 1541 1605 1517 1517 1580 1517 1517 1580 1541 1541 1605 1542 1542 1606 1517 1517 1580 1542 1542 1606 1518 1518 1581 1518 1518 1581 1542 1542 1606 1543 1543 1607 1518 1518 1581 1543 1543 1607 1519 1519 1582 1519 1519 1582 1543 1543 1607 1544 1544 1608 1519 1519 1582 1544 1544 1608 1520 1520 1583 1520 1520 1583 1544 1544 1608 1545 1545 1609 1520 1520 1583 1545 1545 1609 1521 1521 1584 1521 1521 1584 1545 1545 1609 1546 1546 1610 1521 1521 1584 1546 1546 1610 1522 1522 1585 1522 1522 1585 1546 1546 1610 1547 1547 1611 1522 1522 1585 1547 1547 1611 1523 1523 1586 1523 1523 1586 1547 1547 1611 1548 1548 1612 1523 1523 1586 1548 1548 1612 1524 1524 1587 1524 1524 1587 1548 1548 1612 1549 1549 1613 1524 1524 1587 1549 1549 1613 1525 1525 1588 1525 1525 1588 1549 1549 1613 1550 1550 1614 1525 1525 1588 1550 1550 1614 1526 1526 1589 1526 1526 1589 1550 1550 1614 1551 1551 1615 1526 1526 1589 1551 1551 1615 1527 1527 1590 1527 1527 1590 1551 1551 1615 1552 1552 1616 1527 1527 1590 1552 1552 1616 1528 1528 1591 1528 1528 1591 1552 1552 1616 1553 1553 1617 1528 1528 1591 1553 1553 1617 1529 1529 1592 1529 1529 1592 1553 1553 1617 1554 1554 1618 1529 1529 1592 1554 1554 1618 1530 1530 1593 1530 1530 1593 1554 1554 1618 1555 1555 1619 1530 1530 1593 1555 1555 1619 1531 1531 1594 1531 1531 1594 1555 1555 1619 1556 1556 1620 1531 1531 1594 1556 1556 1620 1532 1532 1595 1532 1532 1595 1556 1556 1620 1557 1557 1621 1532 1532 1595 1557 1557 1621 1533 1533 1596 1533 1533 1596 1557 1557 1621 1558 1558 1622 1533 1533 1596 1558 1558 1622 1534 1534 1597 1534 1534 1597 1558 1558 1622 1559 1559 1623 1534 1534 1597 1559 1559 1623 1535 1535 1598 1535 1535 1598 1559 1559 1623 1536 1536 1624 1535 1535 1598 1536 1536 1624 1512 1512 1599 1536 1536 1600 1560 1560 1625 1561 1561 1626 1536 1536 1600 1561 1561 1626 1537 1537 1601 1537 1537 1601 1561 1561 1626 1562 1562 1627 1537 1537 1601 1562 1562 1627 1538 1538 1602 1538 1538 1602 1562 1562 1627 1563 1563 1628 1538 1538 1602 1563 1563 1628 1539 1539 1603 1539 1539 1603 1563 1563 1628 1564 1564 1629 1539 1539 1603 1564 1564 1629 1540 1540 1604 1540 1540 1604 1564 1564 1629 1565 1565 1630 1540 1540 1604 1565 1565 1630 1541 1541 1605 1541 1541 1605 1565 1565 1630 1566 1566 1631 1541 1541 1605 1566 1566 1631 1542 1542 1606 1542 1542 1606 1566 1566 1631 1567 1567 1632 1542 1542 1606 1567 1567 1632 1543 1543 1607 1543 1543 1607 1567 1567 1632 1568 1568 1633 1543 1543 1607 1568 1568 1633 1544 1544 1608 1544 1544 1608 1568 1568 1633 1569 1569 1634 1544 1544 1608 1569 1569 1634 1545 1545 1609 1545 1545 1609 1569 1569 1634 1570 1570 1635 1545 1545 1609 1570 1570 1635 1546 1546 1610 1546 1546 1610 1570 1570 1635 1571 1571 1636 1546 1546 1610 1571 1571 1636 1547 1547 1611 1547 1547 1611 1571 1571 1636 1572 1572 1637 1547 1547 1611 1572 1572 1637 1548 1548 1612 1548 1548 1612 1572 1572 1637 1573 1573 1638 1548 1548 1612 1573 1573 1638 1549 1549 1613 1549 1549 1613 1573 1573 1638 1574 1574 1639 1549 1549 1613 1574 1574 1639 1550 1550 1614 1550 1550 1614 1574 1574 1639 1575 1575 1640 1550 1550 1614 1575 1575 1640 1551 1551 1615 1551 1551 1615 1575 1575 1640 1576 1576 1641 1551 1551 1615 1576 1576 1641 1552 1552 1616 1552 1552 1616 1576 1576 1641 1577 1577 1642 1552 1552 1616 1577 1577 1642 1553 1553 1617 1553 1553 1617 1577 1577 1642 1578 1578 1643 1553 1553 1617 1578 1578 1643 1554 1554 1618 1554 1554 1618 1578 1578 1643 1579 1579 1644 1554 1554 1618 1579 1579 1644 1555 1555 1619 1555 1555 1619 1579 1579 1644 1580 1580 1645 1555 1555 1619 1580 1580 1645 1556 1556 1620 1556 1556 1620 1580 1580 1645 1581 1581 1646 1556 1556 1620 1581 1581 1646 1557 1557 1621 1557 1557 1621 1581 1581 1646 1582 1582 1647 1557 1557 1621 1582 1582 1647 1558 1558 1622 1558 1558 1622 1582 1582 1647 1583 1583 1648 1558 1558 1622 1583 1583 1648 1559 1559 1623 1559 1559 1623 1583 1583 1648 1560 1560 1649 1559 1559 1623 1560 1560 1649 1536 1536 1624 1560 1560 1625 1584 1584 1650 1585 1585 1651 1560 1560 1625 1585 1585 1651 1561 1561 1626 1561 1561 1626 1585 1585 1651 1586 1586 1652 1561 1561 1626 1586 1586 1652 1562 1562 1627 1562 1562 1627 1586 1586 1652 1587 1587 1653 1562 1562 1627 1587 1587 1653 1563 1563 1628 1563 1563 1628 1587 1587 1653 1588 1588 1654 1563 1563 1628 1588 1588 1654 1564 1564 1629 1564 1564 1629 1588 1588 1654 1589 1589 1655 1564 1564 1629 1589 1589 1655 1565 1565 1630 1565 1565 1630 1589 1589 1655 1590 1590 1656 1565 1565 1630 1590 1590 1656 1566 1566 1631 1566 1566 1631 1590 1590 1656 1591 1591 1657 1566 1566 1631 1591 1591 1657 1567 1567 1632 1567 1567 1632 1591 1591 1657 1592 1592 1658 1567 1567 1632 1592 1592 1658 1568 1568 1633 1568 1568 1633 1592 1592 1658 1593 1593 1659 1568 1568 1633 1593 1593 1659 1569 1569 1634 1569 1569 1634 1593 1593 1659 1594 1594 1660 1569 1569 1634 1594 1594 1660 1570 1570 1635 1570 1570 1635 1594 1594 1660 1595 1595 1661 1570 1570 1635 1595 1595 1661 1571 1571 1636 1571 1571 1636 1595 1595 1661 1596 1596 1662 1571 1571 1636 1596 1596 1662 1572 1572 1637 1572 1572 1637 1596 1596 1662 1597 1597 1663 1572 1572 1637 1597 1597 1663 1573 1573 1638 1573 1573 1638 1597 1597 1663 1598 1598 1664 1573 1573 1638 1598 1598 1664 1574 1574 1639 1574 1574 1639 1598 1598 1664 1599 1599 1665 1574 1574 1639 1599 1599 1665 1575 1575 1640 1575 1575 1640 1599 1599 1665 1600 1600 1666 1575 1575 1640 1600 1600 1666 1576 1576 1641 1576 1576 1641 1600 1600 1666 1601 1601 1667 1576 1576 1641 1601 1601 1667 1577 1577 1642 1577 1577 1642 1601 1601 1667 1602 1602 1668 1577 1577 1642 1602 1602 1668 1578 1578 1643 1578 1578 1643 1602 1602 1668 1603 1603 1669 1578 1578 1643 1603 1603 1669 1579 1579 1644 1579 1579 1644 1603 1603 1669 1604 1604 1670 1579 1579 1644 1604 1604 1670 1580 1580 1645 1580 1580 1645 1604 1604 1670 1605 1605 1671 1580 1580 1645 1605 1605 1671 1581 1581 1646 1581 1581 1646 1605 1605 1671 1606 1606 1672 1581 1581 1646 1606 1606 1672 1582 1582 1647 1582 1582 1647 1606 1606 1672 1607 1607 1673 1582 1582 1647 1607 1607 1673 1583 1583 1648 1583 1583 1648 1607 1607 1673 1584 1584 1674 1583 1583 1648 1584 1584 1674 1560 1560 1649 1584 1584 1650 1608 1608 1675 1609 1609 1676 1584 1584 1650 1609 1609 1676 1585 1585 1651 1585 1585 1651 1609 1609 1676 1610 1610 1677 1585 1585 1651 1610 1610 1677 1586 1586 1652 1586 1586 1652 1610 1610 1677 1611 1611 1678 1586 1586 1652 1611 1611 1678 1587 1587 1653 1587 1587 1653 1611 1611 1678 1612 1612 1679 1587 1587 1653 1612 1612 1679 1588 1588 1654 1588 1588 1654 1612 1612 1679 1613 1613 1680 1588 1588 1654 1613 1613 1680 1589 1589 1655 1589 1589 1655 1613 1613 1680 1614 1614 1681 1589 1589 1655 1614 1614 1681 1590 1590 1656 1590 1590 1656 1614 1614 1681 1615 1615 1682 1590 1590 1656 1615 1615 1682 1591 1591 1657 1591 1591 1657 1615 1615 1682 1616 1616 1683 1591 1591 1657 1616 1616 1683 1592 1592 1658 1592 1592 1658 1616 1616 1683 1617 1617 1684 1592 1592 1658 1617 1617 1684 1593 1593 1659 1593 1593 1659 1617 1617 1684 1618 1618 1685 1593 1593 1659 1618 1618 1685 1594 1594 1660 1594 1594 1660 1618 1618 1685 1619 1619 1686 1594 1594 1660 1619 1619 1686 1595 1595 1661 1595 1595 1661 1619 1619 1686 1620 1620 1687 1595 1595 1661 1620 1620 1687 1596 1596 1662 1596 1596 1662 1620 1620 1687 1621 1621 1688 1596 1596 1662 1621 1621 1688 1597 1597 1663 1597 1597 1663 1621 1621 1688 1622 1622 1689 1597 1597 1663 1622 1622 1689 1598 1598 1664 1598 1598 1664 1622 1622 1689 1623 1623 1690 1598 1598 1664 1623 1623 1690 1599 1599 1665 1599 1599 1665 1623 1623 1690 1624 1624 1691 1599 1599 1665 1624 1624 1691 1600 1600 1666 1600 1600 1666 1624 1624 1691 1625 1625 1692 1600 1600 1666 1625 1625 1692 1601 1601 1667 1601 1601 1667 1625 1625 1692 1626 1626 1693 1601 1601 1667 1626 1626 1693 1602 1602 1668 1602 1602 1668 1626 1626 1693 1627 1627 1694 1602 1602 1668 1627 1627 1694 1603 1603 1669 1603 1603 1669 1627 1627 1694 1628 1628 1695 1603 1603 1669 1628 1628 1695 1604 1604 1670 1604 1604 1670 1628 1628 1695 1629 1629 1696 1604 1604 1670 1629 1629 1696 1605 1605 1671 1605 1605 1671 1629 1629 1696 1630 1630 1697 1605 1605 1671 1630 1630 1697 1606 1606 1672 1606 1606 1672 1630 1630 1697 1631 1631 1698 1606 1606 1672 1631 1631 1698 1607 1607 1673 1607 1607 1673 1631 1631 1698 1608 1608 1699 1607 1607 1673 1608 1608 1699 1584 1584 1674 1608 1608 1675 1632 1632 1700 1633 1633 1701 1608 1608 1675 1633 1633 1701 1609 1609 1676 1609 1609 1676 1633 1633 1701 1634 1634 1702 1609 1609 1676 1634 1634 1702 1610 1610 1677 1610 1610 1677 1634 1634 1702 1635 1635 1703 1610 1610 1677 1635 1635 1703 1611 1611 1678 1611 1611 1678 1635 1635 1703 1636 1636 1704 1611 1611 1678 1636 1636 1704 1612 1612 1679 1612 1612 1679 1636 1636 1704 1637 1637 1705 1612 1612 1679 1637 1637 1705 1613 1613 1680 1613 1613 1680 1637 1637 1705 1638 1638 1706 1613 1613 1680 1638 1638 1706 1614 1614 1681 1614 1614 1681 1638 1638 1706 1639 1639 1707 1614 1614 1681 1639 1639 1707 1615 1615 1682 1615 1615 1682 1639 1639 1707 1640 1640 1708 1615 1615 1682 1640 1640 1708 1616 1616 1683 1616 1616 1683 1640 1640 1708 1641 1641 1709 1616 1616 1683 1641 1641 1709 1617 1617 1684 1617 1617 1684 1641 1641 1709 1642 1642 1710 1617 1617 1684 1642 1642 1710 1618 1618 1685 1618 1618 1685 1642 1642 1710 1643 1643 1711 1618 1618 1685 1643 1643 1711 1619 1619 1686 1619 1619 1686 1643 1643 1711 1644 1644 1712 1619 1619 1686 1644 1644 1712 1620 1620 1687 1620 1620 1687 1644 1644 1712 1645 1645 1713 1620 1620 1687 1645 1645 1713 1621 1621 1688 1621 1621 1688 1645 1645 1713 1646 1646 1714 1621 1621 1688 1646 1646 1714 1622 1622 1689 1622 1622 1689 1646 1646 1714 1647 1647 1715 1622 1622 1689 1647 1647 1715 1623 1623 1690 1623 1623 1690 1647 1647 1715 1648 1648 1716 1623 1623 1690 1648 1648 1716 1624 1624 1691 1624 1624 1691 1648 1648 1716 1649 1649 1717 1624 1624 1691 1649 1649 1717 1625 1625 1692 1625 1625 1692 1649 1649 1717 1650 1650 1718 1625 1625 1692 1650 1650 1718 1626 1626 1693 1626 1626 1693 1650 1650 1718 1651 1651 1719 1626 1626 1693 1651 1651 1719 1627 1627 1694 1627 1627 1694 1651 1651 1719 1652 1652 1720 1627 1627 1694 1652 1652 1720 1628 1628 1695 1628 1628 1695 1652 1652 1720 1653 1653 1721 1628 1628 1695 1653 1653 1721 1629 1629 1696 1629 1629 1696 1653 1653 1721 1654 1654 1722 1629 1629 1696 1654 1654 1722 1630 1630 1697 1630 1630 1697 1654 1654 1722 1655 1655 1723 1630 1630 1697 1655 1655 1723 1631 1631 1698 1631 1631 1698 1655 1655 1723 1632 1632 1724 1631 1631 1698 1632 1632 1724 1608 1608 1699 1632 1632 1700 1656 1656 1725 1657 1657 1726 1632 1632 1700 1657 1657 1726 1633 1633 1701 1633 1633 1701 1657 1657 1726 1658 1658 1727 1633 1633 1701 1658 1658 1727 1634 1634 1702 1634 1634 1702 1658 1658 1727 1659 1659 1728 1634 1634 1702 1659 1659 1728 1635 1635 1703 1635 1635 1703 1659 1659 1728 1660 1660 1729 1635 1635 1703 1660 1660 1729 1636 1636 1704 1636 1636 1704 1660 1660 1729 1661 1661 1730 1636 1636 1704 1661 1661 1730 1637 1637 1705 1637 1637 1705 1661 1661 1730 1662 1662 1731 1637 1637 1705 1662 1662 1731 1638 1638 1706 1638 1638 1706 1662 1662 1731 1663 1663 1732 1638 1638 1706 1663 1663 1732 1639 1639 1707 1639 1639 1707 1663 1663 1732 1664 1664 1733 1639 1639 1707 1664 1664 1733 1640 1640 1708 1640 1640 1708 1664 1664 1733 1665 1665 1734 1640 1640 1708 1665 1665 1734 1641 1641 1709 1641 1641 1709 1665 1665 1734 1666 1666 1735 1641 1641 1709 1666 1666 1735 1642 1642 1710 1642 1642 1710 1666 1666 1735 1667 1667 1736 1642 1642 1710 1667 1667 1736 1643 1643 1711 1643 1643 1711 1667 1667 1736 1668 1668 1737 1643 1643 1711 1668 1668 1737 1644 1644 1712 1644 1644 1712 1668 1668 1737 1669 1669 1738 1644 1644 1712 1669 1669 1738 1645 1645 1713 1645 1645 1713 1669 1669 1738 1670 1670 1739 1645 1645 1713 1670 1670 1739 1646 1646 1714 1646 1646 1714 1670 1670 1739 1671 1671 1740 1646 1646 1714 1671 1671 1740 1647 1647 1715 1647 1647 1715 1671 1671 1740 1672 1672 1741 1647 1647 1715 1672 1672 1741 1648 1648 1716 1648 1648 1716 1672 1672 1741 1673 1673 1742 1648 1648 1716 1673 1673 1742 1649 1649 1717 1649 1649 1717 1673 1673 1742 1674 1674 1743 1649 1649 1717 1674 1674 1743 1650 1650 1718 1650 1650 1718 1674 1674 1743 1675 1675 1744 1650 1650 1718 1675 1675 1744 1651 1651 1719 1651 1651 1719 1675 1675 1744 1676 1676 1745 1651 1651 1719 1676 1676 1745 1652 1652 1720 1652 1652 1720 1676 1676 1745 1677 1677 1746 1652 1652 1720 1677 1677 1746 1653 1653 1721 1653 1653 1721 1677 1677 1746 1678 1678 1747 1653 1653 1721 1678 1678 1747 1654 1654 1722 1654 1654 1722 1678 1678 1747 1679 1679 1748 1654 1654 1722 1679 1679 1748 1655 1655 1723 1655 1655 1723 1679 1679 1748 1656 1656 1749 1655 1655 1723 1656 1656 1749 1632 1632 1724 1656 1656 1725 1680 1680 1750 1681 1681 1751 1656 1656 1725 1681 1681 1751 1657 1657 1726 1657 1657 1726 1681 1681 1751 1682 1682 1752 1657 1657 1726 1682 1682 1752 1658 1658 1727 1658 1658 1727 1682 1682 1752 1683 1683 1753 1658 1658 1727 1683 1683 1753 1659 1659 1728 1659 1659 1728 1683 1683 1753 1684 1684 1754 1659 1659 1728 1684 1684 1754 1660 1660 1729 1660 1660 1729 1684 1684 1754 1685 1685 1755 1660 1660 1729 1685 1685 1755 1661 1661 1730 1661 1661 1730 1685 1685 1755 1686 1686 1756 1661 1661 1730 1686 1686 1756 1662 1662 1731 1662 1662 1731 1686 1686 1756 1687 1687 1757 1662 1662 1731 1687 1687 1757 1663 1663 1732 1663 1663 1732 1687 1687 1757 1688 1688 1758 1663 1663 1732 1688 1688 1758 1664 1664 1733 1664 1664 1733 1688 1688 1758 1689 1689 1759 1664 1664 1733 1689 1689 1759 1665 1665 1734 1665 1665 1734 1689 1689 1759 1690 1690 1760 1665 1665 1734 1690 1690 1760 1666 1666 1735 1666 1666 1735 1690 1690 1760 1691 1691 1761 1666 1666 1735 1691 1691 1761 1667 1667 1736 1667 1667 1736 1691 1691 1761 1692 1692 1762 1667 1667 1736 1692 1692 1762 1668 1668 1737 1668 1668 1737 1692 1692 1762 1693 1693 1763 1668 1668 1737 1693 1693 1763 1669 1669 1738 1669 1669 1738 1693 1693 1763 1694 1694 1764 1669 1669 1738 1694 1694 1764 1670 1670 1739 1670 1670 1739 1694 1694 1764 1695 1695 1765 1670 1670 1739 1695 1695 1765 1671 1671 1740 1671 1671 1740 1695 1695 1765 1696 1696 1766 1671 1671 1740 1696 1696 1766 1672 1672 1741 1672 1672 1741 1696 1696 1766 1697 1697 1767 1672 1672 1741 1697 1697 1767 1673 1673 1742 1673 1673 1742 1697 1697 1767 1698 1698 1768 1673 1673 1742 1698 1698 1768 1674 1674 1743 1674 1674 1743 1698 1698 1768 1699 1699 1769 1674 1674 1743 1699 1699 1769 1675 1675 1744 1675 1675 1744 1699 1699 1769 1700 1700 1770 1675 1675 1744 1700 1700 1770 1676 1676 1745 1676 1676 1745 1700 1700 1770 1701 1701 1771 1676 1676 1745 1701 1701 1771 1677 1677 1746 1677 1677 1746 1701 1701 1771 1702 1702 1772 1677 1677 1746 1702 1702 1772 1678 1678 1747 1678 1678 1747 1702 1702 1772 1703 1703 1773 1678 1678 1747 1703 1703 1773 1679 1679 1748 1679 1679 1748 1703 1703 1773 1680 1680 1774 1679 1679 1748 1680 1680 1774 1656 1656 1749 1680 1680 1750 1704 1704 1775 1705 1705 1776 1680 1680 1750 1705 1705 1776 1681 1681 1751 1681 1681 1751 1705 1705 1776 1706 1706 1777 1681 1681 1751 1706 1706 1777 1682 1682 1752 1682 1682 1752 1706 1706 1777 1707 1707 1778 1682 1682 1752 1707 1707 1778 1683 1683 1753 1683 1683 1753 1707 1707 1778 1708 1708 1779 1683 1683 1753 1708 1708 1779 1684 1684 1754 1684 1684 1754 1708 1708 1779 1709 1709 1780 1684 1684 1754 1709 1709 1780 1685 1685 1755 1685 1685 1755 1709 1709 1780 1710 1710 1781 1685 1685 1755 1710 1710 1781 1686 1686 1756 1686 1686 1756 1710 1710 1781 1711 1711 1782 1686 1686 1756 1711 1711 1782 1687 1687 1757 1687 1687 1757 1711 1711 1782 1712 1712 1783 1687 1687 1757 1712 1712 1783 1688 1688 1758 1688 1688 1758 1712 1712 1783 1713 1713 1784 1688 1688 1758 1713 1713 1784 1689 1689 1759 1689 1689 1759 1713 1713 1784 1714 1714 1785 1689 1689 1759 1714 1714 1785 1690 1690 1760 1690 1690 1760 1714 1714 1785 1715 1715 1786 1690 1690 1760 1715 1715 1786 1691 1691 1761 1691 1691 1761 1715 1715 1786 1716 1716 1787 1691 1691 1761 1716 1716 1787 1692 1692 1762 1692 1692 1762 1716 1716 1787 1717 1717 1788 1692 1692 1762 1717 1717 1788 1693 1693 1763 1693 1693 1763 1717 1717 1788 1718 1718 1789 1693 1693 1763 1718 1718 1789 1694 1694 1764 1694 1694 1764 1718 1718 1789 1719 1719 1790 1694 1694 1764 1719 1719 1790 1695 1695 1765 1695 1695 1765 1719 1719 1790 1720 1720 1791 1695 1695 1765 1720 1720 1791 1696 1696 1766 1696 1696 1766 1720 1720 1791 1721 1721 1792 1696 1696 1766 1721 1721 1792 1697 1697 1767 1697 1697 1767 1721 1721 1792 1722 1722 1793 1697 1697 1767 1722 1722 1793 1698 1698 1768 1698 1698 1768 1722 1722 1793 1723 1723 1794 1698 1698 1768 1723 1723 1794 1699 1699 1769 1699 1699 1769 1723 1723 1794 1724 1724 1795 1699 1699 1769 1724 1724 1795 1700 1700 1770 1700 1700 1770 1724 1724 1795 1725 1725 1796 1700 1700 1770 1725 1725 1796 1701 1701 1771 1701 1701 1771 1725 1725 1796 1726 1726 1797 1701 1701 1771 1726 1726 1797 1702 1702 1772 1702 1702 1772 1726 1726 1797 1727 1727 1798 1702 1702 1772 1727 1727 1798 1703 1703 1773 1703 1703 1773 1727 1727 1798 1704 1704 1799 1703 1703 1773 1704 1704 1799 1680 1680 1774 1704 1704 1775 1728 1728 1800 1729 1729 1801 1704 1704 1775 1729 1729 1801 1705 1705 1776 1705 1705 1776 1729 1729 1801 1730 1730 1802 1705 1705 1776 1730 1730 1802 1706 1706 1777 1706 1706 1777 1730 1730 1802 1731 1731 1803 1706 1706 1777 1731 1731 1803 1707 1707 1778 1707 1707 1778 1731 1731 1803 1732 1732 1804 1707 1707 1778 1732 1732 1804 1708 1708 1779 1708 1708 1779 1732 1732 1804 1733 1733 1805 1708 1708 1779 1733 1733 1805 1709 1709 1780 1709 1709 1780 1733 1733 1805 1734 1734 1806 1709 1709 1780 1734 1734 1806 1710 1710 1781 1710 1710 1781 1734 1734 1806 1735 1735 1807 1710 1710 1781 1735 1735 1807 1711 1711 1782 1711 1711 1782 1735 1735 1807 1736 1736 1808 1711 1711 1782 1736 1736 1808 1712 1712 1783 1712 1712 1783 1736 1736 1808 1737 1737 1809 1712 1712 1783 1737 1737 1809 1713 1713 1784 1713 1713 1784 1737 1737 1809 1738 1738 1810 1713 1713 1784 1738 1738 1810 1714 1714 1785 1714 1714 1785 1738 1738 1810 1739 1739 1811 1714 1714 1785 1739 1739 1811 1715 1715 1786 1715 1715 1786 1739 1739 1811 1740 1740 1812 1715 1715 1786 1740 1740 1812 1716 1716 1787 1716 1716 1787 1740 1740 1812 1741 1741 1813 1716 1716 1787 1741 1741 1813 1717 1717 1788 1717 1717 1788 1741 1741 1813 1742 1742 1814 1717 1717 1788 1742 1742 1814 1718 1718 1789 1718 1718 1789 1742 1742 1814 1743 1743 1815 1718 1718 1789 1743 1743 1815 1719 1719 1790 1719 1719 1790 1743 1743 1815 1744 1744 1816 1719 1719 1790 1744 1744 1816 1720 1720 1791 1720 1720 1791 1744 1744 1816 1745 1745 1817 1720 1720 1791 1745 1745 1817 1721 1721 1792 1721 1721 1792 1745 1745 1817 1746 1746 1818 1721 1721 1792 1746 1746 1818 1722 1722 1793 1722 1722 1793 1746 1746 1818 1747 1747 1819 1722 1722 1793 1747 1747 1819 1723 1723 1794 1723 1723 1794 1747 1747 1819 1748 1748 1820 1723 1723 1794 1748 1748 1820 1724 1724 1795 1724 1724 1795 1748 1748 1820 1749 1749 1821 1724 1724 1795 1749 1749 1821 1725 1725 1796 1725 1725 1796 1749 1749 1821 1750 1750 1822 1725 1725 1796 1750 1750 1822 1726 1726 1797 1726 1726 1797 1750 1750 1822 1751 1751 1823 1726 1726 1797 1751 1751 1823 1727 1727 1798 1727 1727 1798 1751 1751 1823 1728 1728 1824 1727 1727 1798 1728 1728 1824 1704 1704 1799 1728 1728 1800 1752 1752 1825 1753 1753 1826 1728 1728 1800 1753 1753 1826 1729 1729 1801 1729 1729 1801 1753 1753 1826 1754 1754 1827 1729 1729 1801 1754 1754 1827 1730 1730 1802 1730 1730 1802 1754 1754 1827 1755 1755 1828 1730 1730 1802 1755 1755 1828 1731 1731 1803 1731 1731 1803 1755 1755 1828 1756 1756 1829 1731 1731 1803 1756 1756 1829 1732 1732 1804 1732 1732 1804 1756 1756 1829 1757 1757 1830 1732 1732 1804 1757 1757 1830 1733 1733 1805 1733 1733 1805 1757 1757 1830 1758 1758 1831 1733 1733 1805 1758 1758 1831 1734 1734 1806 1734 1734 1806 1758 1758 1831 1759 1759 1832 1734 1734 1806 1759 1759 1832 1735 1735 1807 1735 1735 1807 1759 1759 1832 1760 1760 1833 1735 1735 1807 1760 1760 1833 1736 1736 1808 1736 1736 1808 1760 1760 1833 1761 1761 1834 1736 1736 1808 1761 1761 1834 1737 1737 1809 1737 1737 1809 1761 1761 1834 1762 1762 1835 1737 1737 1809 1762 1762 1835 1738 1738 1810 1738 1738 1810 1762 1762 1835 1763 1763 1836 1738 1738 1810 1763 1763 1836 1739 1739 1811 1739 1739 1811 1763 1763 1836 1764 1764 1837 1739 1739 1811 1764 1764 1837 1740 1740 1812 1740 1740 1812 1764 1764 1837 1765 1765 1838 1740 1740 1812 1765 1765 1838 1741 1741 1813 1741 1741 1813 1765 1765 1838 1766 1766 1839 1741 1741 1813 1766 1766 1839 1742 1742 1814 1742 1742 1814 1766 1766 1839 1767 1767 1840 1742 1742 1814 1767 1767 1840 1743 1743 1815 1743 1743 1815 1767 1767 1840 1768 1768 1841 1743 1743 1815 1768 1768 1841 1744 1744 1816 1744 1744 1816 1768 1768 1841 1769 1769 1842 1744 1744 1816 1769 1769 1842 1745 1745 1817 1745 1745 1817 1769 1769 1842 1770 1770 1843 1745 1745 1817 1770 1770 1843 1746 1746 1818 1746 1746 1818 1770 1770 1843 1771 1771 1844 1746 1746 1818 1771 1771 1844 1747 1747 1819 1747 1747 1819 1771 1771 1844 1772 1772 1845 1747 1747 1819 1772 1772 1845 1748 1748 1820 1748 1748 1820 1772 1772 1845 1773 1773 1846 1748 1748 1820 1773 1773 1846 1749 1749 1821 1749 1749 1821 1773 1773 1846 1774 1774 1847 1749 1749 1821 1774 1774 1847 1750 1750 1822 1750 1750 1822 1774 1774 1847 1775 1775 1848 1750 1750 1822 1775 1775 1848 1751 1751 1823 1751 1751 1823 1775 1775 1848 1752 1752 1849 1751 1751 1823 1752 1752 1849 1728 1728 1824 1752 1752 1825 1776 1776 1850 1777 1777 1851 1752 1752 1825 1777 1777 1851 1753 1753 1826 1753 1753 1826 1777 1777 1851 1778 1778 1852 1753 1753 1826 1778 1778 1852 1754 1754 1827 1754 1754 1827 1778 1778 1852 1779 1779 1853 1754 1754 1827 1779 1779 1853 1755 1755 1828 1755 1755 1828 1779 1779 1853 1780 1780 1854 1755 1755 1828 1780 1780 1854 1756 1756 1829 1756 1756 1829 1780 1780 1854 1781 1781 1855 1756 1756 1829 1781 1781 1855 1757 1757 1830 1757 1757 1830 1781 1781 1855 1782 1782 1856 1757 1757 1830 1782 1782 1856 1758 1758 1831 1758 1758 1831 1782 1782 1856 1783 1783 1857 1758 1758 1831 1783 1783 1857 1759 1759 1832 1759 1759 1832 1783 1783 1857 1784 1784 1858 1759 1759 1832 1784 1784 1858 1760 1760 1833 1760 1760 1833 1784 1784 1858 1785 1785 1859 1760 1760 1833 1785 1785 1859 1761 1761 1834 1761 1761 1834 1785 1785 1859 1786 1786 1860 1761 1761 1834 1786 1786 1860 1762 1762 1835 1762 1762 1835 1786 1786 1860 1787 1787 1861 1762 1762 1835 1787 1787 1861 1763 1763 1836 1763 1763 1836 1787 1787 1861 1788 1788 1862 1763 1763 1836 1788 1788 1862 1764 1764 1837 1764 1764 1837 1788 1788 1862 1789 1789 1863 1764 1764 1837 1789 1789 1863 1765 1765 1838 1765 1765 1838 1789 1789 1863 1790 1790 1864 1765 1765 1838 1790 1790 1864 1766 1766 1839 1766 1766 1839 1790 1790 1864 1791 1791 1865 1766 1766 1839 1791 1791 1865 1767 1767 1840 1767 1767 1840 1791 1791 1865 1792 1792 1866 1767 1767 1840 1792 1792 1866 1768 1768 1841 1768 1768 1841 1792 1792 1866 1793 1793 1867 1768 1768 1841 1793 1793 1867 1769 1769 1842 1769 1769 1842 1793 1793 1867 1794 1794 1868 1769 1769 1842 1794 1794 1868 1770 1770 1843 1770 1770 1843 1794 1794 1868 1795 1795 1869 1770 1770 1843 1795 1795 1869 1771 1771 1844 1771 1771 1844 1795 1795 1869 1796 1796 1870 1771 1771 1844 1796 1796 1870 1772 1772 1845 1772 1772 1845 1796 1796 1870 1797 1797 1871 1772 1772 1845 1797 1797 1871 1773 1773 1846 1773 1773 1846 1797 1797 1871 1798 1798 1872 1773 1773 1846 1798 1798 1872 1774 1774 1847 1774 1774 1847 1798 1798 1872 1799 1799 1873 1774 1774 1847 1799 1799 1873 1775 1775 1848 1775 1775 1848 1799 1799 1873 1776 1776 1874 1775 1775 1848 1776 1776 1874 1752 1752 1849 1776 1776 1850 1800 1800 1875 1801 1801 1876 1776 1776 1850 1801 1801 1876 1777 1777 1851 1777 1777 1851 1801 1801 1876 1802 1802 1877 1777 1777 1851 1802 1802 1877 1778 1778 1852 1778 1778 1852 1802 1802 1877 1803 1803 1878 1778 1778 1852 1803 1803 1878 1779 1779 1853 1779 1779 1853 1803 1803 1878 1804 1804 1879 1779 1779 1853 1804 1804 1879 1780 1780 1854 1780 1780 1854 1804 1804 1879 1805 1805 1880 1780 1780 1854 1805 1805 1880 1781 1781 1855 1781 1781 1855 1805 1805 1880 1806 1806 1881 1781 1781 1855 1806 1806 1881 1782 1782 1856 1782 1782 1856 1806 1806 1881 1807 1807 1882 1782 1782 1856 1807 1807 1882 1783 1783 1857 1783 1783 1857 1807 1807 1882 1808 1808 1883 1783 1783 1857 1808 1808 1883 1784 1784 1858 1784 1784 1858 1808 1808 1883 1809 1809 1884 1784 1784 1858 1809 1809 1884 1785 1785 1859 1785 1785 1859 1809 1809 1884 1810 1810 1885 1785 1785 1859 1810 1810 1885 1786 1786 1860 1786 1786 1860 1810 1810 1885 1811 1811 1886 1786 1786 1860 1811 1811 1886 1787 1787 1861 1787 1787 1861 1811 1811 1886 1812 1812 1887 1787 1787 1861 1812 1812 1887 1788 1788 1862 1788 1788 1862 1812 1812 1887 1813 1813 1888 1788 1788 1862 1813 1813 1888 1789 1789 1863 1789 1789 1863 1813 1813 1888 1814 1814 1889 1789 1789 1863 1814 1814 1889 1790 1790 1864 1790 1790 1864 1814 1814 1889 1815 1815 1890 1790 1790 1864 1815 1815 1890 1791 1791 1865 1791 1791 1865 1815 1815 1890 1816 1816 1891 1791 1791 1865 1816 1816 1891 1792 1792 1866 1792 1792 1866 1816 1816 1891 1817 1817 1892 1792 1792 1866 1817 1817 1892 1793 1793 1867 1793 1793 1867 1817 1817 1892 1818 1818 1893 1793 1793 1867 1818 1818 1893 1794 1794 1868 1794 1794 1868 1818 1818 1893 1819 1819 1894 1794 1794 1868 1819 1819 1894 1795 1795 1869 1795 1795 1869 1819 1819 1894 1820 1820 1895 1795 1795 1869 1820 1820 1895 1796 1796 1870 1796 1796 1870 1820 1820 1895 1821 1821 1896 1796 1796 1870 1821 1821 1896 1797 1797 1871 1797 1797 1871 1821 1821 1896 1822 1822 1897 1797 1797 1871 1822 1822 1897 1798 1798 1872 1798 1798 1872 1822 1822 1897 1823 1823 1898 1798 1798 1872 1823 1823 1898 1799 1799 1873 1799 1799 1873 1823 1823 1898 1800 1800 1899 1799 1799 1873 1800 1800 1899 1776 1776 1874 1800 1800 1875 1824 1824 1900 1825 1825 1901 1800 1800 1875 1825 1825 1901 1801 1801 1876 1801 1801 1876 1825 1825 1901 1826 1826 1902 1801 1801 1876 1826 1826 1902 1802 1802 1877 1802 1802 1877 1826 1826 1902 1827 1827 1903 1802 1802 1877 1827 1827 1903 1803 1803 1878 1803 1803 1878 1827 1827 1903 1828 1828 1904 1803 1803 1878 1828 1828 1904 1804 1804 1879 1804 1804 1879 1828 1828 1904 1829 1829 1905 1804 1804 1879 1829 1829 1905 1805 1805 1880 1805 1805 1880 1829 1829 1905 1830 1830 1906 1805 1805 1880 1830 1830 1906 1806 1806 1881 1806 1806 1881 1830 1830 1906 1831 1831 1907 1806 1806 1881 1831 1831 1907 1807 1807 1882 1807 1807 1882 1831 1831 1907 1832 1832 1908 1807 1807 1882 1832 1832 1908 1808 1808 1883 1808 1808 1883 1832 1832 1908 1833 1833 1909 1808 1808 1883 1833 1833 1909 1809 1809 1884 1809 1809 1884 1833 1833 1909 1834 1834 1910 1809 1809 1884 1834 1834 1910 1810 1810 1885 1810 1810 1885 1834 1834 1910 1835 1835 1911 1810 1810 1885 1835 1835 1911 1811 1811 1886 1811 1811 1886 1835 1835 1911 1836 1836 1912 1811 1811 1886 1836 1836 1912 1812 1812 1887 1812 1812 1887 1836 1836 1912 1837 1837 1913 1812 1812 1887 1837 1837 1913 1813 1813 1888 1813 1813 1888 1837 1837 1913 1838 1838 1914 1813 1813 1888 1838 1838 1914 1814 1814 1889 1814 1814 1889 1838 1838 1914 1839 1839 1915 1814 1814 1889 1839 1839 1915 1815 1815 1890 1815 1815 1890 1839 1839 1915 1840 1840 1916 1815 1815 1890 1840 1840 1916 1816 1816 1891 1816 1816 1891 1840 1840 1916 1841 1841 1917 1816 1816 1891 1841 1841 1917 1817 1817 1892 1817 1817 1892 1841 1841 1917 1842 1842 1918 1817 1817 1892 1842 1842 1918 1818 1818 1893 1818 1818 1893 1842 1842 1918 1843 1843 1919 1818 1818 1893 1843 1843 1919 1819 1819 1894 1819 1819 1894 1843 1843 1919 1844 1844 1920 1819 1819 1894 1844 1844 1920 1820 1820 1895 1820 1820 1895 1844 1844 1920 1845 1845 1921 1820 1820 1895 1845 1845 1921 1821 1821 1896 1821 1821 1896 1845 1845 1921 1846 1846 1922 1821 1821 1896 1846 1846 1922 1822 1822 1897 1822 1822 1897 1846 1846 1922 1847 1847 1923 1822 1822 1897 1847 1847 1923 1823 1823 1898 1823 1823 1898 1847 1847 1923 1824 1824 1924 1823 1823 1898 1824 1824 1924 1800 1800 1899 1824 1824 1900 1848 1848 1925 1849 1849 1926 1824 1824 1900 1849 1849 1926 1825 1825 1901 1825 1825 1901 1849 1849 1926 1850 1850 1927 1825 1825 1901 1850 1850 1927 1826 1826 1902 1826 1826 1902 1850 1850 1927 1851 1851 1928 1826 1826 1902 1851 1851 1928 1827 1827 1903 1827 1827 1903 1851 1851 1928 1852 1852 1929 1827 1827 1903 1852 1852 1929 1828 1828 1904 1828 1828 1904 1852 1852 1929 1853 1853 1930 1828 1828 1904 1853 1853 1930 1829 1829 1905 1829 1829 1905 1853 1853 1930 1854 1854 1931 1829 1829 1905 1854 1854 1931 1830 1830 1906 1830 1830 1906 1854 1854 1931 1855 1855 1932 1830 1830 1906 1855 1855 1932 1831 1831 1907 1831 1831 1907 1855 1855 1932 1856 1856 1933 1831 1831 1907 1856 1856 1933 1832 1832 1908 1832 1832 1908 1856 1856 1933 1857 1857 1934 1832 1832 1908 1857 1857 1934 1833 1833 1909 1833 1833 1909 1857 1857 1934 1858 1858 1935 1833 1833 1909 1858 1858 1935 1834 1834 1910 1834 1834 1910 1858 1858 1935 1859 1859 1936 1834 1834 1910 1859 1859 1936 1835 1835 1911 1835 1835 1911 1859 1859 1936 1860 1860 1937 1835 1835 1911 1860 1860 1937 1836 1836 1912 1836 1836 1912 1860 1860 1937 1861 1861 1938 1836 1836 1912 1861 1861 1938 1837 1837 1913 1837 1837 1913 1861 1861 1938 1862 1862 1939 1837 1837 1913 1862 1862 1939 1838 1838 1914 1838 1838 1914 1862 1862 1939 1863 1863 1940 1838 1838 1914 1863 1863 1940 1839 1839 1915 1839 1839 1915 1863 1863 1940 1864 1864 1941 1839 1839 1915 1864 1864 1941 1840 1840 1916 1840 1840 1916 1864 1864 1941 1865 1865 1942 1840 1840 1916 1865 1865 1942 1841 1841 1917 1841 1841 1917 1865 1865 1942 1866 1866 1943 1841 1841 1917 1866 1866 1943 1842 1842 1918 1842 1842 1918 1866 1866 1943 1867 1867 1944 1842 1842 1918 1867 1867 1944 1843 1843 1919 1843 1843 1919 1867 1867 1944 1868 1868 1945 1843 1843 1919 1868 1868 1945 1844 1844 1920 1844 1844 1920 1868 1868 1945 1869 1869 1946 1844 1844 1920 1869 1869 1946 1845 1845 1921 1845 1845 1921 1869 1869 1946 1870 1870 1947 1845 1845 1921 1870 1870 1947 1846 1846 1922 1846 1846 1922 1870 1870 1947 1871 1871 1948 1846 1846 1922 1871 1871 1948 1847 1847 1923 1847 1847 1923 1871 1871 1948 1848 1848 1949 1847 1847 1923 1848 1848 1949 1824 1824 1924 1848 1848 1925 1872 1872 1950 1873 1873 1951 1848 1848 1925 1873 1873 1951 1849 1849 1926 1849 1849 1926 1873 1873 1951 1874 1874 1952 1849 1849 1926 1874 1874 1952 1850 1850 1927 1850 1850 1927 1874 1874 1952 1875 1875 1953 1850 1850 1927 1875 1875 1953 1851 1851 1928 1851 1851 1928 1875 1875 1953 1876 1876 1954 1851 1851 1928 1876 1876 1954 1852 1852 1929 1852 1852 1929 1876 1876 1954 1877 1877 1955 1852 1852 1929 1877 1877 1955 1853 1853 1930 1853 1853 1930 1877 1877 1955 1878 1878 1956 1853 1853 1930 1878 1878 1956 1854 1854 1931 1854 1854 1931 1878 1878 1956 1879 1879 1957 1854 1854 1931 1879 1879 1957 1855 1855 1932 1855 1855 1932 1879 1879 1957 1880 1880 1958 1855 1855 1932 1880 1880 1958 1856 1856 1933 1856 1856 1933 1880 1880 1958 1881 1881 1959 1856 1856 1933 1881 1881 1959 1857 1857 1934 1857 1857 1934 1881 1881 1959 1882 1882 1960 1857 1857 1934 1882 1882 1960 1858 1858 1935 1858 1858 1935 1882 1882 1960 1883 1883 1961 1858 1858 1935 1883 1883 1961 1859 1859 1936 1859 1859 1936 1883 1883 1961 1884 1884 1962 1859 1859 1936 1884 1884 1962 1860 1860 1937 1860 1860 1937 1884 1884 1962 1885 1885 1963 1860 1860 1937 1885 1885 1963 1861 1861 1938 1861 1861 1938 1885 1885 1963 1886 1886 1964 1861 1861 1938 1886 1886 1964 1862 1862 1939 1862 1862 1939 1886 1886 1964 1887 1887 1965 1862 1862 1939 1887 1887 1965 1863 1863 1940 1863 1863 1940 1887 1887 1965 1888 1888 1966 1863 1863 1940 1888 1888 1966 1864 1864 1941 1864 1864 1941 1888 1888 1966 1889 1889 1967 1864 1864 1941 1889 1889 1967 1865 1865 1942 1865 1865 1942 1889 1889 1967 1890 1890 1968 1865 1865 1942 1890 1890 1968 1866 1866 1943 1866 1866 1943 1890 1890 1968 1891 1891 1969 1866 1866 1943 1891 1891 1969 1867 1867 1944 1867 1867 1944 1891 1891 1969 1892 1892 1970 1867 1867 1944 1892 1892 1970 1868 1868 1945 1868 1868 1945 1892 1892 1970 1893 1893 1971 1868 1868 1945 1893 1893 1971 1869 1869 1946 1869 1869 1946 1893 1893 1971 1894 1894 1972 1869 1869 1946 1894 1894 1972 1870 1870 1947 1870 1870 1947 1894 1894 1972 1895 1895 1973 1870 1870 1947 1895 1895 1973 1871 1871 1948 1871 1871 1948 1895 1895 1973 1872 1872 1974 1871 1871 1948 1872 1872 1974 1848 1848 1949 1872 1872 1950 1896 1896 1975 1897 1897 1976 1872 1872 1950 1897 1897 1976 1873 1873 1951 1873 1873 1951 1897 1897 1976 1898 1898 1977 1873 1873 1951 1898 1898 1977 1874 1874 1952 1874 1874 1952 1898 1898 1977 1899 1899 1978 1874 1874 1952 1899 1899 1978 1875 1875 1953 1875 1875 1953 1899 1899 1978 1900 1900 1979 1875 1875 1953 1900 1900 1979 1876 1876 1954 1876 1876 1954 1900 1900 1979 1901 1901 1980 1876 1876 1954 1901 1901 1980 1877 1877 1955 1877 1877 1955 1901 1901 1980 1902 1902 1981 1877 1877 1955 1902 1902 1981 1878 1878 1956 1878 1878 1956 1902 1902 1981 1903 1903 1982 1878 1878 1956 1903 1903 1982 1879 1879 1957 1879 1879 1957 1903 1903 1982 1904 1904 1983 1879 1879 1957 1904 1904 1983 1880 1880 1958 1880 1880 1958 1904 1904 1983 1905 1905 1984 1880 1880 1958 1905 1905 1984 1881 1881 1959 1881 1881 1959 1905 1905 1984 1906 1906 1985 1881 1881 1959 1906 1906 1985 1882 1882 1960 1882 1882 1960 1906 1906 1985 1907 1907 1986 1882 1882 1960 1907 1907 1986 1883 1883 1961 1883 1883 1961 1907 1907 1986 1908 1908 1987 1883 1883 1961 1908 1908 1987 1884 1884 1962 1884 1884 1962 1908 1908 1987 1909 1909 1988 1884 1884 1962 1909 1909 1988 1885 1885 1963 1885 1885 1963 1909 1909 1988 1910 1910 1989 1885 1885 1963 1910 1910 1989 1886 1886 1964 1886 1886 1964 1910 1910 1989 1911 1911 1990 1886 1886 1964 1911 1911 1990 1887 1887 1965 1887 1887 1965 1911 1911 1990 1912 1912 1991 1887 1887 1965 1912 1912 1991 1888 1888 1966 1888 1888 1966 1912 1912 1991 1913 1913 1992 1888 1888 1966 1913 1913 1992 1889 1889 1967 1889 1889 1967 1913 1913 1992 1914 1914 1993 1889 1889 1967 1914 1914 1993 1890 1890 1968 1890 1890 1968 1914 1914 1993 1915 1915 1994 1890 1890 1968 1915 1915 1994 1891 1891 1969 1891 1891 1969 1915 1915 1994 1916 1916 1995 1891 1891 1969 1916 1916 1995 1892 1892 1970 1892 1892 1970 1916 1916 1995 1917 1917 1996 1892 1892 1970 1917 1917 1996 1893 1893 1971 1893 1893 1971 1917 1917 1996 1918 1918 1997 1893 1893 1971 1918 1918 1997 1894 1894 1972 1894 1894 1972 1918 1918 1997 1919 1919 1998 1894 1894 1972 1919 1919 1998 1895 1895 1973 1895 1895 1973 1919 1919 1998 1896 1896 1999 1895 1895 1973 1896 1896 1999 1872 1872 1974 1896 1896 1975 1920 1920 2000 1921 1921 2001 1896 1896 1975 1921 1921 2001 1897 1897 1976 1897 1897 1976 1921 1921 2001 1922 1922 2002 1897 1897 1976 1922 1922 2002 1898 1898 1977 1898 1898 1977 1922 1922 2002 1923 1923 2003 1898 1898 1977 1923 1923 2003 1899 1899 1978 1899 1899 1978 1923 1923 2003 1924 1924 2004 1899 1899 1978 1924 1924 2004 1900 1900 1979 1900 1900 1979 1924 1924 2004 1925 1925 2005 1900 1900 1979 1925 1925 2005 1901 1901 1980 1901 1901 1980 1925 1925 2005 1926 1926 2006 1901 1901 1980 1926 1926 2006 1902 1902 1981 1902 1902 1981 1926 1926 2006 1927 1927 2007 1902 1902 1981 1927 1927 2007 1903 1903 1982 1903 1903 1982 1927 1927 2007 1928 1928 2008 1903 1903 1982 1928 1928 2008 1904 1904 1983 1904 1904 1983 1928 1928 2008 1929 1929 2009 1904 1904 1983 1929 1929 2009 1905 1905 1984 1905 1905 1984 1929 1929 2009 1930 1930 2010 1905 1905 1984 1930 1930 2010 1906 1906 1985 1906 1906 1985 1930 1930 2010 1931 1931 2011 1906 1906 1985 1931 1931 2011 1907 1907 1986 1907 1907 1986 1931 1931 2011 1932 1932 2012 1907 1907 1986 1932 1932 2012 1908 1908 1987 1908 1908 1987 1932 1932 2012 1933 1933 2013 1908 1908 1987 1933 1933 2013 1909 1909 1988 1909 1909 1988 1933 1933 2013 1934 1934 2014 1909 1909 1988 1934 1934 2014 1910 1910 1989 1910 1910 1989 1934 1934 2014 1935 1935 2015 1910 1910 1989 1935 1935 2015 1911 1911 1990 1911 1911 1990 1935 1935 2015 1936 1936 2016 1911 1911 1990 1936 1936 2016 1912 1912 1991 1912 1912 1991 1936 1936 2016 1937 1937 2017 1912 1912 1991 1937 1937 2017 1913 1913 1992 1913 1913 1992 1937 1937 2017 1938 1938 2018 1913 1913 1992 1938 1938 2018 1914 1914 1993 1914 1914 1993 1938 1938 2018 1939 1939 2019 1914 1914 1993 1939 1939 2019 1915 1915 1994 1915 1915 1994 1939 1939 2019 1940 1940 2020 1915 1915 1994 1940 1940 2020 1916 1916 1995 1916 1916 1995 1940 1940 2020 1941 1941 2021 1916 1916 1995 1941 1941 2021 1917 1917 1996 1917 1917 1996 1941 1941 2021 1942 1942 2022 1917 1917 1996 1942 1942 2022 1918 1918 1997 1918 1918 1997 1942 1942 2022 1943 1943 2023 1918 1918 1997 1943 1943 2023 1919 1919 1998 1919 1919 1998 1943 1943 2023 1920 1920 2024 1919 1919 1998 1920 1920 2024 1896 1896 1999 1920 1920 2000 1944 1944 2025 1945 1945 2026 1920 1920 2000 1945 1945 2026 1921 1921 2001 1921 1921 2001 1945 1945 2026 1946 1946 2027 1921 1921 2001 1946 1946 2027 1922 1922 2002 1922 1922 2002 1946 1946 2027 1947 1947 2028 1922 1922 2002 1947 1947 2028 1923 1923 2003 1923 1923 2003 1947 1947 2028 1948 1948 2029 1923 1923 2003 1948 1948 2029 1924 1924 2004 1924 1924 2004 1948 1948 2029 1949 1949 2030 1924 1924 2004 1949 1949 2030 1925 1925 2005 1925 1925 2005 1949 1949 2030 1950 1950 2031 1925 1925 2005 1950 1950 2031 1926 1926 2006 1926 1926 2006 1950 1950 2031 1951 1951 2032 1926 1926 2006 1951 1951 2032 1927 1927 2007 1927 1927 2007 1951 1951 2032 1952 1952 2033 1927 1927 2007 1952 1952 2033 1928 1928 2008 1928 1928 2008 1952 1952 2033 1953 1953 2034 1928 1928 2008 1953 1953 2034 1929 1929 2009 1929 1929 2009 1953 1953 2034 1954 1954 2035 1929 1929 2009 1954 1954 2035 1930 1930 2010 1930 1930 2010 1954 1954 2035 1955 1955 2036 1930 1930 2010 1955 1955 2036 1931 1931 2011 1931 1931 2011 1955 1955 2036 1956 1956 2037 1931 1931 2011 1956 1956 2037 1932 1932 2012 1932 1932 2012 1956 1956 2037 1957 1957 2038 1932 1932 2012 1957 1957 2038 1933 1933 2013 1933 1933 2013 1957 1957 2038 1958 1958 2039 1933 1933 2013 1958 1958 2039 1934 1934 2014 1934 1934 2014 1958 1958 2039 1959 1959 2040 1934 1934 2014 1959 1959 2040 1935 1935 2015 1935 1935 2015 1959 1959 2040 1960 1960 2041 1935 1935 2015 1960 1960 2041 1936 1936 2016 1936 1936 2016 1960 1960 2041 1961 1961 2042 1936 1936 2016 1961 1961 2042 1937 1937 2017 1937 1937 2017 1961 1961 2042 1962 1962 2043 1937 1937 2017 1962 1962 2043 1938 1938 2018 1938 1938 2018 1962 1962 2043 1963 1963 2044 1938 1938 2018 1963 1963 2044 1939 1939 2019 1939 1939 2019 1963 1963 2044 1964 1964 2045 1939 1939 2019 1964 1964 2045 1940 1940 2020 1940 1940 2020 1964 1964 2045 1965 1965 2046 1940 1940 2020 1965 1965 2046 1941 1941 2021 1941 1941 2021 1965 1965 2046 1966 1966 2047 1941 1941 2021 1966 1966 2047 1942 1942 2022 1942 1942 2022 1966 1966 2047 1967 1967 2048 1942 1942 2022 1967 1967 2048 1943 1943 2023 1943 1943 2023 1967 1967 2048 1944 1944 2049 1943 1943 2023 1944 1944 2049 1920 1920 2024 1944 1944 2025 1968 1968 2050 1969 1969 2051 1944 1944 2025 1969 1969 2051 1945 1945 2026 1945 1945 2026 1969 1969 2051 1970 1970 2052 1945 1945 2026 1970 1970 2052 1946 1946 2027 1946 1946 2027 1970 1970 2052 1971 1971 2053 1946 1946 2027 1971 1971 2053 1947 1947 2028 1947 1947 2028 1971 1971 2053 1972 1972 2054 1947 1947 2028 1972 1972 2054 1948 1948 2029 1948 1948 2029 1972 1972 2054 1973 1973 2055 1948 1948 2029 1973 1973 2055 1949 1949 2030 1949 1949 2030 1973 1973 2055 1974 1974 2056 1949 1949 2030 1974 1974 2056 1950 1950 2031 1950 1950 2031 1974 1974 2056 1975 1975 2057 1950 1950 2031 1975 1975 2057 1951 1951 2032 1951 1951 2032 1975 1975 2057 1976 1976 2058 1951 1951 2032 1976 1976 2058 1952 1952 2033 1952 1952 2033 1976 1976 2058 1977 1977 2059 1952 1952 2033 1977 1977 2059 1953 1953 2034 1953 1953 2034 1977 1977 2059 1978 1978 2060 1953 1953 2034 1978 1978 2060 1954 1954 2035 1954 1954 2035 1978 1978 2060 1979 1979 2061 1954 1954 2035 1979 1979 2061 1955 1955 2036 1955 1955 2036 1979 1979 2061 1980 1980 2062 1955 1955 2036 1980 1980 2062 1956 1956 2037 1956 1956 2037 1980 1980 2062 1981 1981 2063 1956 1956 2037 1981 1981 2063 1957 1957 2038 1957 1957 2038 1981 1981 2063 1982 1982 2064 1957 1957 2038 1982 1982 2064 1958 1958 2039 1958 1958 2039 1982 1982 2064 1983 1983 2065 1958 1958 2039 1983 1983 2065 1959 1959 2040 1959 1959 2040 1983 1983 2065 1984 1984 2066 1959 1959 2040 1984 1984 2066 1960 1960 2041 1960 1960 2041 1984 1984 2066 1985 1985 2067 1960 1960 2041 1985 1985 2067 1961 1961 2042 1961 1961 2042 1985 1985 2067 1986 1986 2068 1961 1961 2042 1986 1986 2068 1962 1962 2043 1962 1962 2043 1986 1986 2068 1987 1987 2069 1962 1962 2043 1987 1987 2069 1963 1963 2044 1963 1963 2044 1987 1987 2069 1988 1988 2070 1963 1963 2044 1988 1988 2070 1964 1964 2045 1964 1964 2045 1988 1988 2070 1989 1989 2071 1964 1964 2045 1989 1989 2071 1965 1965 2046 1965 1965 2046 1989 1989 2071 1990 1990 2072 1965 1965 2046 1990 1990 2072 1966 1966 2047 1966 1966 2047 1990 1990 2072 1991 1991 2073 1966 1966 2047 1991 1991 2073 1967 1967 2048 1967 1967 2048 1991 1991 2073 1968 1968 2074 1967 1967 2048 1968 1968 2074 1944 1944 2049 1968 1968 2050 1992 1992 2075 1993 1993 2076 1968 1968 2050 1993 1993 2076 1969 1969 2051 1969 1969 2051 1993 1993 2076 1994 1994 2077 1969 1969 2051 1994 1994 2077 1970 1970 2052 1970 1970 2052 1994 1994 2077 1995 1995 2078 1970 1970 2052 1995 1995 2078 1971 1971 2053 1971 1971 2053 1995 1995 2078 1996 1996 2079 1971 1971 2053 1996 1996 2079 1972 1972 2054 1972 1972 2054 1996 1996 2079 1997 1997 2080 1972 1972 2054 1997 1997 2080 1973 1973 2055 1973 1973 2055 1997 1997 2080 1998 1998 2081 1973 1973 2055 1998 1998 2081 1974 1974 2056 1974 1974 2056 1998 1998 2081 1999 1999 2082 1974 1974 2056 1999 1999 2082 1975 1975 2057 1975 1975 2057 1999 1999 2082 2000 2000 2083 1975 1975 2057 2000 2000 2083 1976 1976 2058 1976 1976 2058 2000 2000 2083 2001 2001 2084 1976 1976 2058 2001 2001 2084 1977 1977 2059 1977 1977 2059 2001 2001 2084 2002 2002 2085 1977 1977 2059 2002 2002 2085 1978 1978 2060 1978 1978 2060 2002 2002 2085 2003 2003 2086 1978 1978 2060 2003 2003 2086 1979 1979 2061 1979 1979 2061 2003 2003 2086 2004 2004 2087 1979 1979 2061 2004 2004 2087 1980 1980 2062 1980 1980 2062 2004 2004 2087 2005 2005 2088 1980 1980 2062 2005 2005 2088 1981 1981 2063 1981 1981 2063 2005 2005 2088 2006 2006 2089 1981 1981 2063 2006 2006 2089 1982 1982 2064 1982 1982 2064 2006 2006 2089 2007 2007 2090 1982 1982 2064 2007 2007 2090 1983 1983 2065 1983 1983 2065 2007 2007 2090 2008 2008 2091 1983 1983 2065 2008 2008 2091 1984 1984 2066 1984 1984 2066 2008 2008 2091 2009 2009 2092 1984 1984 2066 2009 2009 2092 1985 1985 2067 1985 1985 2067 2009 2009 2092 2010 2010 2093 1985 1985 2067 2010 2010 2093 1986 1986 2068 1986 1986 2068 2010 2010 2093 2011 2011 2094 1986 1986 2068 2011 2011 2094 1987 1987 2069 1987 1987 2069 2011 2011 2094 2012 2012 2095 1987 1987 2069 2012 2012 2095 1988 1988 2070 1988 1988 2070 2012 2012 2095 2013 2013 2096 1988 1988 2070 2013 2013 2096 1989 1989 2071 1989 1989 2071 2013 2013 2096 2014 2014 2097 1989 1989 2071 2014 2014 2097 1990 1990 2072 1990 1990 2072 2014 2014 2097 2015 2015 2098 1990 1990 2072 2015 2015 2098 1991 1991 2073 1991 1991 2073 2015 2015 2098 1992 1992 2099 1991 1991 2073 1992 1992 2099 1968 1968 2074 1992 1992 2075 2016 2016 2100 2017 2017 2101 1992 1992 2075 2017 2017 2101 1993 1993 2076 1993 1993 2076 2017 2017 2101 2018 2018 2102 1993 1993 2076 2018 2018 2102 1994 1994 2077 1994 1994 2077 2018 2018 2102 2019 2019 2103 1994 1994 2077 2019 2019 2103 1995 1995 2078 1995 1995 2078 2019 2019 2103 2020 2020 2104 1995 1995 2078 2020 2020 2104 1996 1996 2079 1996 1996 2079 2020 2020 2104 2021 2021 2105 1996 1996 2079 2021 2021 2105 1997 1997 2080 1997 1997 2080 2021 2021 2105 2022 2022 2106 1997 1997 2080 2022 2022 2106 1998 1998 2081 1998 1998 2081 2022 2022 2106 2023 2023 2107 1998 1998 2081 2023 2023 2107 1999 1999 2082 1999 1999 2082 2023 2023 2107 2024 2024 2108 1999 1999 2082 2024 2024 2108 2000 2000 2083 2000 2000 2083 2024 2024 2108 2025 2025 2109 2000 2000 2083 2025 2025 2109 2001 2001 2084 2001 2001 2084 2025 2025 2109 2026 2026 2110 2001 2001 2084 2026 2026 2110 2002 2002 2085 2002 2002 2085 2026 2026 2110 2027 2027 2111 2002 2002 2085 2027 2027 2111 2003 2003 2086 2003 2003 2086 2027 2027 2111 2028 2028 2112 2003 2003 2086 2028 2028 2112 2004 2004 2087 2004 2004 2087 2028 2028 2112 2029 2029 2113 2004 2004 2087 2029 2029 2113 2005 2005 2088 2005 2005 2088 2029 2029 2113 2030 2030 2114 2005 2005 2088 2030 2030 2114 2006 2006 2089 2006 2006 2089 2030 2030 2114 2031 2031 2115 2006 2006 2089 2031 2031 2115 2007 2007 2090 2007 2007 2090 2031 2031 2115 2032 2032 2116 2007 2007 2090 2032 2032 2116 2008 2008 2091 2008 2008 2091 2032 2032 2116 2033 2033 2117 2008 2008 2091 2033 2033 2117 2009 2009 2092 2009 2009 2092 2033 2033 2117 2034 2034 2118 2009 2009 2092 2034 2034 2118 2010 2010 2093 2010 2010 2093 2034 2034 2118 2035 2035 2119 2010 2010 2093 2035 2035 2119 2011 2011 2094 2011 2011 2094 2035 2035 2119 2036 2036 2120 2011 2011 2094 2036 2036 2120 2012 2012 2095 2012 2012 2095 2036 2036 2120 2037 2037 2121 2012 2012 2095 2037 2037 2121 2013 2013 2096 2013 2013 2096 2037 2037 2121 2038 2038 2122 2013 2013 2096 2038 2038 2122 2014 2014 2097 2014 2014 2097 2038 2038 2122 2039 2039 2123 2014 2014 2097 2039 2039 2123 2015 2015 2098 2015 2015 2098 2039 2039 2123 2016 2016 2124 2015 2015 2098 2016 2016 2124 1992 1992 2099 2016 2016 2100 2040 2040 2125 2041 2041 2126 2016 2016 2100 2041 2041 2126 2017 2017 2101 2017 2017 2101 2041 2041 2126 2042 2042 2127 2017 2017 2101 2042 2042 2127 2018 2018 2102 2018 2018 2102 2042 2042 2127 2043 2043 2128 2018 2018 2102 2043 2043 2128 2019 2019 2103 2019 2019 2103 2043 2043 2128 2044 2044 2129 2019 2019 2103 2044 2044 2129 2020 2020 2104 2020 2020 2104 2044 2044 2129 2045 2045 2130 2020 2020 2104 2045 2045 2130 2021 2021 2105 2021 2021 2105 2045 2045 2130 2046 2046 2131 2021 2021 2105 2046 2046 2131 2022 2022 2106 2022 2022 2106 2046 2046 2131 2047 2047 2132 2022 2022 2106 2047 2047 2132 2023 2023 2107 2023 2023 2107 2047 2047 2132 2048 2048 2133 2023 2023 2107 2048 2048 2133 2024 2024 2108 2024 2024 2108 2048 2048 2133 2049 2049 2134 2024 2024 2108 2049 2049 2134 2025 2025 2109 2025 2025 2109 2049 2049 2134 2050 2050 2135 2025 2025 2109 2050 2050 2135 2026 2026 2110 2026 2026 2110 2050 2050 2135 2051 2051 2136 2026 2026 2110 2051 2051 2136 2027 2027 2111 2027 2027 2111 2051 2051 2136 2052 2052 2137 2027 2027 2111 2052 2052 2137 2028 2028 2112 2028 2028 2112 2052 2052 2137 2053 2053 2138 2028 2028 2112 2053 2053 2138 2029 2029 2113 2029 2029 2113 2053 2053 2138 2054 2054 2139 2029 2029 2113 2054 2054 2139 2030 2030 2114 2030 2030 2114 2054 2054 2139 2055 2055 2140 2030 2030 2114 2055 2055 2140 2031 2031 2115 2031 2031 2115 2055 2055 2140 2056 2056 2141 2031 2031 2115 2056 2056 2141 2032 2032 2116 2032 2032 2116 2056 2056 2141 2057 2057 2142 2032 2032 2116 2057 2057 2142 2033 2033 2117 2033 2033 2117 2057 2057 2142 2058 2058 2143 2033 2033 2117 2058 2058 2143 2034 2034 2118 2034 2034 2118 2058 2058 2143 2059 2059 2144 2034 2034 2118 2059 2059 2144 2035 2035 2119 2035 2035 2119 2059 2059 2144 2060 2060 2145 2035 2035 2119 2060 2060 2145 2036 2036 2120 2036 2036 2120 2060 2060 2145 2061 2061 2146 2036 2036 2120 2061 2061 2146 2037 2037 2121 2037 2037 2121 2061 2061 2146 2062 2062 2147 2037 2037 2121 2062 2062 2147 2038 2038 2122 2038 2038 2122 2062 2062 2147 2063 2063 2148 2038 2038 2122 2063 2063 2148 2039 2039 2123 2039 2039 2123 2063 2063 2148 2040 2040 2149 2039 2039 2123 2040 2040 2149 2016 2016 2124 2040 2040 2125 2064 2064 2150 2065 2065 2151 2040 2040 2125 2065 2065 2151 2041 2041 2126 2041 2041 2126 2065 2065 2151 2066 2066 2152 2041 2041 2126 2066 2066 2152 2042 2042 2127 2042 2042 2127 2066 2066 2152 2067 2067 2153 2042 2042 2127 2067 2067 2153 2043 2043 2128 2043 2043 2128 2067 2067 2153 2068 2068 2154 2043 2043 2128 2068 2068 2154 2044 2044 2129 2044 2044 2129 2068 2068 2154 2069 2069 2155 2044 2044 2129 2069 2069 2155 2045 2045 2130 2045 2045 2130 2069 2069 2155 2070 2070 2156 2045 2045 2130 2070 2070 2156 2046 2046 2131 2046 2046 2131 2070 2070 2156 2071 2071 2157 2046 2046 2131 2071 2071 2157 2047 2047 2132 2047 2047 2132 2071 2071 2157 2072 2072 2158 2047 2047 2132 2072 2072 2158 2048 2048 2133 2048 2048 2133 2072 2072 2158 2073 2073 2159 2048 2048 2133 2073 2073 2159 2049 2049 2134 2049 2049 2134 2073 2073 2159 2074 2074 2160 2049 2049 2134 2074 2074 2160 2050 2050 2135 2050 2050 2135 2074 2074 2160 2075 2075 2161 2050 2050 2135 2075 2075 2161 2051 2051 2136 2051 2051 2136 2075 2075 2161 2076 2076 2162 2051 2051 2136 2076 2076 2162 2052 2052 2137 2052 2052 2137 2076 2076 2162 2077 2077 2163 2052 2052 2137 2077 2077 2163 2053 2053 2138 2053 2053 2138 2077 2077 2163 2078 2078 2164 2053 2053 2138 2078 2078 2164 2054 2054 2139 2054 2054 2139 2078 2078 2164 2079 2079 2165 2054 2054 2139 2079 2079 2165 2055 2055 2140 2055 2055 2140 2079 2079 2165 2080 2080 2166 2055 2055 2140 2080 2080 2166 2056 2056 2141 2056 2056 2141 2080 2080 2166 2081 2081 2167 2056 2056 2141 2081 2081 2167 2057 2057 2142 2057 2057 2142 2081 2081 2167 2082 2082 2168 2057 2057 2142 2082 2082 2168 2058 2058 2143 2058 2058 2143 2082 2082 2168 2083 2083 2169 2058 2058 2143 2083 2083 2169 2059 2059 2144 2059 2059 2144 2083 2083 2169 2084 2084 2170 2059 2059 2144 2084 2084 2170 2060 2060 2145 2060 2060 2145 2084 2084 2170 2085 2085 2171 2060 2060 2145 2085 2085 2171 2061 2061 2146 2061 2061 2146 2085 2085 2171 2086 2086 2172 2061 2061 2146 2086 2086 2172 2062 2062 2147 2062 2062 2147 2086 2086 2172 2087 2087 2173 2062 2062 2147 2087 2087 2173 2063 2063 2148 2063 2063 2148 2087 2087 2173 2064 2064 2174 2063 2063 2148 2064 2064 2174 2040 2040 2149 2064 2064 2150 2088 2088 2175 2089 2089 2176 2064 2064 2150 2089 2089 2176 2065 2065 2151 2065 2065 2151 2089 2089 2176 2090 2090 2177 2065 2065 2151 2090 2090 2177 2066 2066 2152 2066 2066 2152 2090 2090 2177 2091 2091 2178 2066 2066 2152 2091 2091 2178 2067 2067 2153 2067 2067 2153 2091 2091 2178 2092 2092 2179 2067 2067 2153 2092 2092 2179 2068 2068 2154 2068 2068 2154 2092 2092 2179 2093 2093 2180 2068 2068 2154 2093 2093 2180 2069 2069 2155 2069 2069 2155 2093 2093 2180 2094 2094 2181 2069 2069 2155 2094 2094 2181 2070 2070 2156 2070 2070 2156 2094 2094 2181 2095 2095 2182 2070 2070 2156 2095 2095 2182 2071 2071 2157 2071 2071 2157 2095 2095 2182 2096 2096 2183 2071 2071 2157 2096 2096 2183 2072 2072 2158 2072 2072 2158 2096 2096 2183 2097 2097 2184 2072 2072 2158 2097 2097 2184 2073 2073 2159 2073 2073 2159 2097 2097 2184 2098 2098 2185 2073 2073 2159 2098 2098 2185 2074 2074 2160 2074 2074 2160 2098 2098 2185 2099 2099 2186 2074 2074 2160 2099 2099 2186 2075 2075 2161 2075 2075 2161 2099 2099 2186 2100 2100 2187 2075 2075 2161 2100 2100 2187 2076 2076 2162 2076 2076 2162 2100 2100 2187 2101 2101 2188 2076 2076 2162 2101 2101 2188 2077 2077 2163 2077 2077 2163 2101 2101 2188 2102 2102 2189 2077 2077 2163 2102 2102 2189 2078 2078 2164 2078 2078 2164 2102 2102 2189 2103 2103 2190 2078 2078 2164 2103 2103 2190 2079 2079 2165 2079 2079 2165 2103 2103 2190 2104 2104 2191 2079 2079 2165 2104 2104 2191 2080 2080 2166 2080 2080 2166 2104 2104 2191 2105 2105 2192 2080 2080 2166 2105 2105 2192 2081 2081 2167 2081 2081 2167 2105 2105 2192 2106 2106 2193 2081 2081 2167 2106 2106 2193 2082 2082 2168 2082 2082 2168 2106 2106 2193 2107 2107 2194 2082 2082 2168 2107 2107 2194 2083 2083 2169 2083 2083 2169 2107 2107 2194 2108 2108 2195 2083 2083 2169 2108 2108 2195 2084 2084 2170 2084 2084 2170 2108 2108 2195 2109 2109 2196 2084 2084 2170 2109 2109 2196 2085 2085 2171 2085 2085 2171 2109 2109 2196 2110 2110 2197 2085 2085 2171 2110 2110 2197 2086 2086 2172 2086 2086 2172 2110 2110 2197 2111 2111 2198 2086 2086 2172 2111 2111 2198 2087 2087 2173 2087 2087 2173 2111 2111 2198 2088 2088 2199 2087 2087 2173 2088 2088 2199 2064 2064 2174 2088 2088 2175 2112 2112 2200 2113 2113 2201 2088 2088 2175 2113 2113 2201 2089 2089 2176 2089 2089 2176 2113 2113 2201 2114 2114 2202 2089 2089 2176 2114 2114 2202 2090 2090 2177 2090 2090 2177 2114 2114 2202 2115 2115 2203 2090 2090 2177 2115 2115 2203 2091 2091 2178 2091 2091 2178 2115 2115 2203 2116 2116 2204 2091 2091 2178 2116 2116 2204 2092 2092 2179 2092 2092 2179 2116 2116 2204 2117 2117 2205 2092 2092 2179 2117 2117 2205 2093 2093 2180 2093 2093 2180 2117 2117 2205 2118 2118 2206 2093 2093 2180 2118 2118 2206 2094 2094 2181 2094 2094 2181 2118 2118 2206 2119 2119 2207 2094 2094 2181 2119 2119 2207 2095 2095 2182 2095 2095 2182 2119 2119 2207 2120 2120 2208 2095 2095 2182 2120 2120 2208 2096 2096 2183 2096 2096 2183 2120 2120 2208 2121 2121 2209 2096 2096 2183 2121 2121 2209 2097 2097 2184 2097 2097 2184 2121 2121 2209 2122 2122 2210 2097 2097 2184 2122 2122 2210 2098 2098 2185 2098 2098 2185 2122 2122 2210 2123 2123 2211 2098 2098 2185 2123 2123 2211 2099 2099 2186 2099 2099 2186 2123 2123 2211 2124 2124 2212 2099 2099 2186 2124 2124 2212 2100 2100 2187 2100 2100 2187 2124 2124 2212 2125 2125 2213 2100 2100 2187 2125 2125 2213 2101 2101 2188 2101 2101 2188 2125 2125 2213 2126 2126 2214 2101 2101 2188 2126 2126 2214 2102 2102 2189 2102 2102 2189 2126 2126 2214 2127 2127 2215 2102 2102 2189 2127 2127 2215 2103 2103 2190 2103 2103 2190 2127 2127 2215 2128 2128 2216 2103 2103 2190 2128 2128 2216 2104 2104 2191 2104 2104 2191 2128 2128 2216 2129 2129 2217 2104 2104 2191 2129 2129 2217 2105 2105 2192 2105 2105 2192 2129 2129 2217 2130 2130 2218 2105 2105 2192 2130 2130 2218 2106 2106 2193 2106 2106 2193 2130 2130 2218 2131 2131 2219 2106 2106 2193 2131 2131 2219 2107 2107 2194 2107 2107 2194 2131 2131 2219 2132 2132 2220 2107 2107 2194 2132 2132 2220 2108 2108 2195 2108 2108 2195 2132 2132 2220 2133 2133 2221 2108 2108 2195 2133 2133 2221 2109 2109 2196 2109 2109 2196 2133 2133 2221 2134 2134 2222 2109 2109 2196 2134 2134 2222 2110 2110 2197 2110 2110 2197 2134 2134 2222 2135 2135 2223 2110 2110 2197 2135 2135 2223 2111 2111 2198 2111 2111 2198 2135 2135 2223 2112 2112 2224 2111 2111 2198 2112 2112 2224 2088 2088 2199 2112 2112 2200 2136 2136 2225 2137 2137 2226 2112 2112 2200 2137 2137 2226 2113 2113 2201 2113 2113 2201 2137 2137 2226 2138 2138 2227 2113 2113 2201 2138 2138 2227 2114 2114 2202 2114 2114 2202 2138 2138 2227 2139 2139 2228 2114 2114 2202 2139 2139 2228 2115 2115 2203 2115 2115 2203 2139 2139 2228 2140 2140 2229 2115 2115 2203 2140 2140 2229 2116 2116 2204 2116 2116 2204 2140 2140 2229 2141 2141 2230 2116 2116 2204 2141 2141 2230 2117 2117 2205 2117 2117 2205 2141 2141 2230 2142 2142 2231 2117 2117 2205 2142 2142 2231 2118 2118 2206 2118 2118 2206 2142 2142 2231 2143 2143 2232 2118 2118 2206 2143 2143 2232 2119 2119 2207 2119 2119 2207 2143 2143 2232 2144 2144 2233 2119 2119 2207 2144 2144 2233 2120 2120 2208 2120 2120 2208 2144 2144 2233 2145 2145 2234 2120 2120 2208 2145 2145 2234 2121 2121 2209 2121 2121 2209 2145 2145 2234 2146 2146 2235 2121 2121 2209 2146 2146 2235 2122 2122 2210 2122 2122 2210 2146 2146 2235 2147 2147 2236 2122 2122 2210 2147 2147 2236 2123 2123 2211 2123 2123 2211 2147 2147 2236 2148 2148 2237 2123 2123 2211 2148 2148 2237 2124 2124 2212 2124 2124 2212 2148 2148 2237 2149 2149 2238 2124 2124 2212 2149 2149 2238 2125 2125 2213 2125 2125 2213 2149 2149 2238 2150 2150 2239 2125 2125 2213 2150 2150 2239 2126 2126 2214 2126 2126 2214 2150 2150 2239 2151 2151 2240 2126 2126 2214 2151 2151 2240 2127 2127 2215 2127 2127 2215 2151 2151 2240 2152 2152 2241 2127 2127 2215 2152 2152 2241 2128 2128 2216 2128 2128 2216 2152 2152 2241 2153 2153 2242 2128 2128 2216 2153 2153 2242 2129 2129 2217 2129 2129 2217 2153 2153 2242 2154 2154 2243 2129 2129 2217 2154 2154 2243 2130 2130 2218 2130 2130 2218 2154 2154 2243 2155 2155 2244 2130 2130 2218 2155 2155 2244 2131 2131 2219 2131 2131 2219 2155 2155 2244 2156 2156 2245 2131 2131 2219 2156 2156 2245 2132 2132 2220 2132 2132 2220 2156 2156 2245 2157 2157 2246 2132 2132 2220 2157 2157 2246 2133 2133 2221 2133 2133 2221 2157 2157 2246 2158 2158 2247 2133 2133 2221 2158 2158 2247 2134 2134 2222 2134 2134 2222 2158 2158 2247 2159 2159 2248 2134 2134 2222 2159 2159 2248 2135 2135 2223 2135 2135 2223 2159 2159 2248 2136 2136 2249 2135 2135 2223 2136 2136 2249 2112 2112 2224 2136 2136 2225 2160 2160 2250 2161 2161 2251 2136 2136 2225 2161 2161 2251 2137 2137 2226 2137 2137 2226 2161 2161 2251 2162 2162 2252 2137 2137 2226 2162 2162 2252 2138 2138 2227 2138 2138 2227 2162 2162 2252 2163 2163 2253 2138 2138 2227 2163 2163 2253 2139 2139 2228 2139 2139 2228 2163 2163 2253 2164 2164 2254 2139 2139 2228 2164 2164 2254 2140 2140 2229 2140 2140 2229 2164 2164 2254 2165 2165 2255 2140 2140 2229 2165 2165 2255 2141 2141 2230 2141 2141 2230 2165 2165 2255 2166 2166 2256 2141 2141 2230 2166 2166 2256 2142 2142 2231 2142 2142 2231 2166 2166 2256 2167 2167 2257 2142 2142 2231 2167 2167 2257 2143 2143 2232 2143 2143 2232 2167 2167 2257 2168 2168 2258 2143 2143 2232 2168 2168 2258 2144 2144 2233 2144 2144 2233 2168 2168 2258 2169 2169 2259 2144 2144 2233 2169 2169 2259 2145 2145 2234 2145 2145 2234 2169 2169 2259 2170 2170 2260 2145 2145 2234 2170 2170 2260 2146 2146 2235 2146 2146 2235 2170 2170 2260 2171 2171 2261 2146 2146 2235 2171 2171 2261 2147 2147 2236 2147 2147 2236 2171 2171 2261 2172 2172 2262 2147 2147 2236 2172 2172 2262 2148 2148 2237 2148 2148 2237 2172 2172 2262 2173 2173 2263 2148 2148 2237 2173 2173 2263 2149 2149 2238 2149 2149 2238 2173 2173 2263 2174 2174 2264 2149 2149 2238 2174 2174 2264 2150 2150 2239 2150 2150 2239 2174 2174 2264 2175 2175 2265 2150 2150 2239 2175 2175 2265 2151 2151 2240 2151 2151 2240 2175 2175 2265 2176 2176 2266 2151 2151 2240 2176 2176 2266 2152 2152 2241 2152 2152 2241 2176 2176 2266 2177 2177 2267 2152 2152 2241 2177 2177 2267 2153 2153 2242 2153 2153 2242 2177 2177 2267 2178 2178 2268 2153 2153 2242 2178 2178 2268 2154 2154 2243 2154 2154 2243 2178 2178 2268 2179 2179 2269 2154 2154 2243 2179 2179 2269 2155 2155 2244 2155 2155 2244 2179 2179 2269 2180 2180 2270 2155 2155 2244 2180 2180 2270 2156 2156 2245 2156 2156 2245 2180 2180 2270 2181 2181 2271 2156 2156 2245 2181 2181 2271 2157 2157 2246 2157 2157 2246 2181 2181 2271 2182 2182 2272 2157 2157 2246 2182 2182 2272 2158 2158 2247 2158 2158 2247 2182 2182 2272 2183 2183 2273 2158 2158 2247 2183 2183 2273 2159 2159 2248 2159 2159 2248 2183 2183 2273 2160 2160 2274 2159 2159 2248 2160 2160 2274 2136 2136 2249 2160 2160 2250 2184 2184 2275 2185 2185 2276 2160 2160 2250 2185 2185 2276 2161 2161 2251 2161 2161 2251 2185 2185 2276 2186 2186 2277 2161 2161 2251 2186 2186 2277 2162 2162 2252 2162 2162 2252 2186 2186 2277 2187 2187 2278 2162 2162 2252 2187 2187 2278 2163 2163 2253 2163 2163 2253 2187 2187 2278 2188 2188 2279 2163 2163 2253 2188 2188 2279 2164 2164 2254 2164 2164 2254 2188 2188 2279 2189 2189 2280 2164 2164 2254 2189 2189 2280 2165 2165 2255 2165 2165 2255 2189 2189 2280 2190 2190 2281 2165 2165 2255 2190 2190 2281 2166 2166 2256 2166 2166 2256 2190 2190 2281 2191 2191 2282 2166 2166 2256 2191 2191 2282 2167 2167 2257 2167 2167 2257 2191 2191 2282 2192 2192 2283 2167 2167 2257 2192 2192 2283 2168 2168 2258 2168 2168 2258 2192 2192 2283 2193 2193 2284 2168 2168 2258 2193 2193 2284 2169 2169 2259 2169 2169 2259 2193 2193 2284 2194 2194 2285 2169 2169 2259 2194 2194 2285 2170 2170 2260 2170 2170 2260 2194 2194 2285 2195 2195 2286 2170 2170 2260 2195 2195 2286 2171 2171 2261 2171 2171 2261 2195 2195 2286 2196 2196 2287 2171 2171 2261 2196 2196 2287 2172 2172 2262 2172 2172 2262 2196 2196 2287 2197 2197 2288 2172 2172 2262 2197 2197 2288 2173 2173 2263 2173 2173 2263 2197 2197 2288 2198 2198 2289 2173 2173 2263 2198 2198 2289 2174 2174 2264 2174 2174 2264 2198 2198 2289 2199 2199 2290 2174 2174 2264 2199 2199 2290 2175 2175 2265 2175 2175 2265 2199 2199 2290 2200 2200 2291 2175 2175 2265 2200 2200 2291 2176 2176 2266 2176 2176 2266 2200 2200 2291 2201 2201 2292 2176 2176 2266 2201 2201 2292 2177 2177 2267 2177 2177 2267 2201 2201 2292 2202 2202 2293 2177 2177 2267 2202 2202 2293 2178 2178 2268 2178 2178 2268 2202 2202 2293 2203 2203 2294 2178 2178 2268 2203 2203 2294 2179 2179 2269 2179 2179 2269 2203 2203 2294 2204 2204 2295 2179 2179 2269 2204 2204 2295 2180 2180 2270 2180 2180 2270 2204 2204 2295 2205 2205 2296 2180 2180 2270 2205 2205 2296 2181 2181 2271 2181 2181 2271 2205 2205 2296 2206 2206 2297 2181 2181 2271 2206 2206 2297 2182 2182 2272 2182 2182 2272 2206 2206 2297 2207 2207 2298 2182 2182 2272 2207 2207 2298 2183 2183 2273 2183 2183 2273 2207 2207 2298 2184 2184 2299 2183 2183 2273 2184 2184 2299 2160 2160 2274 2184 2184 2275 2208 2208 2300 2209 2209 2301 2184 2184 2275 2209 2209 2301 2185 2185 2276 2185 2185 2276 2209 2209 2301 2210 2210 2302 2185 2185 2276 2210 2210 2302 2186 2186 2277 2186 2186 2277 2210 2210 2302 2211 2211 2303 2186 2186 2277 2211 2211 2303 2187 2187 2278 2187 2187 2278 2211 2211 2303 2212 2212 2304 2187 2187 2278 2212 2212 2304 2188 2188 2279 2188 2188 2279 2212 2212 2304 2213 2213 2305 2188 2188 2279 2213 2213 2305 2189 2189 2280 2189 2189 2280 2213 2213 2305 2214 2214 2306 2189 2189 2280 2214 2214 2306 2190 2190 2281 2190 2190 2281 2214 2214 2306 2215 2215 2307 2190 2190 2281 2215 2215 2307 2191 2191 2282 2191 2191 2282 2215 2215 2307 2216 2216 2308 2191 2191 2282 2216 2216 2308 2192 2192 2283 2192 2192 2283 2216 2216 2308 2217 2217 2309 2192 2192 2283 2217 2217 2309 2193 2193 2284 2193 2193 2284 2217 2217 2309 2218 2218 2310 2193 2193 2284 2218 2218 2310 2194 2194 2285 2194 2194 2285 2218 2218 2310 2219 2219 2311 2194 2194 2285 2219 2219 2311 2195 2195 2286 2195 2195 2286 2219 2219 2311 2220 2220 2312 2195 2195 2286 2220 2220 2312 2196 2196 2287 2196 2196 2287 2220 2220 2312 2221 2221 2313 2196 2196 2287 2221 2221 2313 2197 2197 2288 2197 2197 2288 2221 2221 2313 2222 2222 2314 2197 2197 2288 2222 2222 2314 2198 2198 2289 2198 2198 2289 2222 2222 2314 2223 2223 2315 2198 2198 2289 2223 2223 2315 2199 2199 2290 2199 2199 2290 2223 2223 2315 2224 2224 2316 2199 2199 2290 2224 2224 2316 2200 2200 2291 2200 2200 2291 2224 2224 2316 2225 2225 2317 2200 2200 2291 2225 2225 2317 2201 2201 2292 2201 2201 2292 2225 2225 2317 2226 2226 2318 2201 2201 2292 2226 2226 2318 2202 2202 2293 2202 2202 2293 2226 2226 2318 2227 2227 2319 2202 2202 2293 2227 2227 2319 2203 2203 2294 2203 2203 2294 2227 2227 2319 2228 2228 2320 2203 2203 2294 2228 2228 2320 2204 2204 2295 2204 2204 2295 2228 2228 2320 2229 2229 2321 2204 2204 2295 2229 2229 2321 2205 2205 2296 2205 2205 2296 2229 2229 2321 2230 2230 2322 2205 2205 2296 2230 2230 2322 2206 2206 2297 2206 2206 2297 2230 2230 2322 2231 2231 2323 2206 2206 2297 2231 2231 2323 2207 2207 2298 2207 2207 2298 2231 2231 2323 2208 2208 2324 2207 2207 2298 2208 2208 2324 2184 2184 2299 2208 2208 2300 2232 2232 2325 2233 2233 2326 2208 2208 2300 2233 2233 2326 2209 2209 2301 2209 2209 2301 2233 2233 2326 2234 2234 2327 2209 2209 2301 2234 2234 2327 2210 2210 2302 2210 2210 2302 2234 2234 2327 2235 2235 2328 2210 2210 2302 2235 2235 2328 2211 2211 2303 2211 2211 2303 2235 2235 2328 2236 2236 2329 2211 2211 2303 2236 2236 2329 2212 2212 2304 2212 2212 2304 2236 2236 2329 2237 2237 2330 2212 2212 2304 2237 2237 2330 2213 2213 2305 2213 2213 2305 2237 2237 2330 2238 2238 2331 2213 2213 2305 2238 2238 2331 2214 2214 2306 2214 2214 2306 2238 2238 2331 2239 2239 2332 2214 2214 2306 2239 2239 2332 2215 2215 2307 2215 2215 2307 2239 2239 2332 2240 2240 2333 2215 2215 2307 2240 2240 2333 2216 2216 2308 2216 2216 2308 2240 2240 2333 2241 2241 2334 2216 2216 2308 2241 2241 2334 2217 2217 2309 2217 2217 2309 2241 2241 2334 2242 2242 2335 2217 2217 2309 2242 2242 2335 2218 2218 2310 2218 2218 2310 2242 2242 2335 2243 2243 2336 2218 2218 2310 2243 2243 2336 2219 2219 2311 2219 2219 2311 2243 2243 2336 2244 2244 2337 2219 2219 2311 2244 2244 2337 2220 2220 2312 2220 2220 2312 2244 2244 2337 2245 2245 2338 2220 2220 2312 2245 2245 2338 2221 2221 2313 2221 2221 2313 2245 2245 2338 2246 2246 2339 2221 2221 2313 2246 2246 2339 2222 2222 2314 2222 2222 2314 2246 2246 2339 2247 2247 2340 2222 2222 2314 2247 2247 2340 2223 2223 2315 2223 2223 2315 2247 2247 2340 2248 2248 2341 2223 2223 2315 2248 2248 2341 2224 2224 2316 2224 2224 2316 2248 2248 2341 2249 2249 2342 2224 2224 2316 2249 2249 2342 2225 2225 2317 2225 2225 2317 2249 2249 2342 2250 2250 2343 2225 2225 2317 2250 2250 2343 2226 2226 2318 2226 2226 2318 2250 2250 2343 2251 2251 2344 2226 2226 2318 2251 2251 2344 2227 2227 2319 2227 2227 2319 2251 2251 2344 2252 2252 2345 2227 2227 2319 2252 2252 2345 2228 2228 2320 2228 2228 2320 2252 2252 2345 2253 2253 2346 2228 2228 2320 2253 2253 2346 2229 2229 2321 2229 2229 2321 2253 2253 2346 2254 2254 2347 2229 2229 2321 2254 2254 2347 2230 2230 2322 2230 2230 2322 2254 2254 2347 2255 2255 2348 2230 2230 2322 2255 2255 2348 2231 2231 2323 2231 2231 2323 2255 2255 2348 2232 2232 2349 2231 2231 2323 2232 2232 2349 2208 2208 2324 2232 2232 2325 2256 2256 2350 2257 2257 2351 2232 2232 2325 2257 2257 2351 2233 2233 2326 2233 2233 2326 2257 2257 2351 2258 2258 2352 2233 2233 2326 2258 2258 2352 2234 2234 2327 2234 2234 2327 2258 2258 2352 2259 2259 2353 2234 2234 2327 2259 2259 2353 2235 2235 2328 2235 2235 2328 2259 2259 2353 2260 2260 2354 2235 2235 2328 2260 2260 2354 2236 2236 2329 2236 2236 2329 2260 2260 2354 2261 2261 2355 2236 2236 2329 2261 2261 2355 2237 2237 2330 2237 2237 2330 2261 2261 2355 2262 2262 2356 2237 2237 2330 2262 2262 2356 2238 2238 2331 2238 2238 2331 2262 2262 2356 2263 2263 2357 2238 2238 2331 2263 2263 2357 2239 2239 2332 2239 2239 2332 2263 2263 2357 2264 2264 2358 2239 2239 2332 2264 2264 2358 2240 2240 2333 2240 2240 2333 2264 2264 2358 2265 2265 2359 2240 2240 2333 2265 2265 2359 2241 2241 2334 2241 2241 2334 2265 2265 2359 2266 2266 2360 2241 2241 2334 2266 2266 2360 2242 2242 2335 2242 2242 2335 2266 2266 2360 2267 2267 2361 2242 2242 2335 2267 2267 2361 2243 2243 2336 2243 2243 2336 2267 2267 2361 2268 2268 2362 2243 2243 2336 2268 2268 2362 2244 2244 2337 2244 2244 2337 2268 2268 2362 2269 2269 2363 2244 2244 2337 2269 2269 2363 2245 2245 2338 2245 2245 2338 2269 2269 2363 2270 2270 2364 2245 2245 2338 2270 2270 2364 2246 2246 2339 2246 2246 2339 2270 2270 2364 2271 2271 2365 2246 2246 2339 2271 2271 2365 2247 2247 2340 2247 2247 2340 2271 2271 2365 2272 2272 2366 2247 2247 2340 2272 2272 2366 2248 2248 2341 2248 2248 2341 2272 2272 2366 2273 2273 2367 2248 2248 2341 2273 2273 2367 2249 2249 2342 2249 2249 2342 2273 2273 2367 2274 2274 2368 2249 2249 2342 2274 2274 2368 2250 2250 2343 2250 2250 2343 2274 2274 2368 2275 2275 2369 2250 2250 2343 2275 2275 2369 2251 2251 2344 2251 2251 2344 2275 2275 2369 2276 2276 2370 2251 2251 2344 2276 2276 2370 2252 2252 2345 2252 2252 2345 2276 2276 2370 2277 2277 2371 2252 2252 2345 2277 2277 2371 2253 2253 2346 2253 2253 2346 2277 2277 2371 2278 2278 2372 2253 2253 2346 2278 2278 2372 2254 2254 2347 2254 2254 2347 2278 2278 2372 2279 2279 2373 2254 2254 2347 2279 2279 2373 2255 2255 2348 2255 2255 2348 2279 2279 2373 2256 2256 2374 2255 2255 2348 2256 2256 2374 2232 2232 2349 2256 2256 2350 2280 2280 2375 2281 2281 2376 2256 2256 2350 2281 2281 2376 2257 2257 2351 2257 2257 2351 2281 2281 2376 2282 2282 2377 2257 2257 2351 2282 2282 2377 2258 2258 2352 2258 2258 2352 2282 2282 2377 2283 2283 2378 2258 2258 2352 2283 2283 2378 2259 2259 2353 2259 2259 2353 2283 2283 2378 2284 2284 2379 2259 2259 2353 2284 2284 2379 2260 2260 2354 2260 2260 2354 2284 2284 2379 2285 2285 2380 2260 2260 2354 2285 2285 2380 2261 2261 2355 2261 2261 2355 2285 2285 2380 2286 2286 2381 2261 2261 2355 2286 2286 2381 2262 2262 2356 2262 2262 2356 2286 2286 2381 2287 2287 2382 2262 2262 2356 2287 2287 2382 2263 2263 2357 2263 2263 2357 2287 2287 2382 2288 2288 2383 2263 2263 2357 2288 2288 2383 2264 2264 2358 2264 2264 2358 2288 2288 2383 2289 2289 2384 2264 2264 2358 2289 2289 2384 2265 2265 2359 2265 2265 2359 2289 2289 2384 2290 2290 2385 2265 2265 2359 2290 2290 2385 2266 2266 2360 2266 2266 2360 2290 2290 2385 2291 2291 2386 2266 2266 2360 2291 2291 2386 2267 2267 2361 2267 2267 2361 2291 2291 2386 2292 2292 2387 2267 2267 2361 2292 2292 2387 2268 2268 2362 2268 2268 2362 2292 2292 2387 2293 2293 2388 2268 2268 2362 2293 2293 2388 2269 2269 2363 2269 2269 2363 2293 2293 2388 2294 2294 2389 2269 2269 2363 2294 2294 2389 2270 2270 2364 2270 2270 2364 2294 2294 2389 2295 2295 2390 2270 2270 2364 2295 2295 2390 2271 2271 2365 2271 2271 2365 2295 2295 2390 2296 2296 2391 2271 2271 2365 2296 2296 2391 2272 2272 2366 2272 2272 2366 2296 2296 2391 2297 2297 2392 2272 2272 2366 2297 2297 2392 2273 2273 2367 2273 2273 2367 2297 2297 2392 2298 2298 2393 2273 2273 2367 2298 2298 2393 2274 2274 2368 2274 2274 2368 2298 2298 2393 2299 2299 2394 2274 2274 2368 2299 2299 2394 2275 2275 2369 2275 2275 2369 2299 2299 2394 2300 2300 2395 2275 2275 2369 2300 2300 2395 2276 2276 2370 2276 2276 2370 2300 2300 2395 2301 2301 2396 2276 2276 2370 2301 2301 2396 2277 2277 2371 2277 2277 2371 2301 2301 2396 2302 2302 2397 2277 2277 2371 2302 2302 2397 2278 2278 2372 2278 2278 2372 2302 2302 2397 2303 2303 2398 2278 2278 2372 2303 2303 2398 2279 2279 2373 2279 2279 2373 2303 2303 2398 2280 2280 2399 2279 2279 2373 2280 2280 2399 2256 2256 2374 2280 2280 2375 2304 2304 2400 2305 2305 2401 2280 2280 2375 2305 2305 2401 2281 2281 2376 2281 2281 2376 2305 2305 2401 2306 2306 2402 2281 2281 2376 2306 2306 2402 2282 2282 2377 2282 2282 2377 2306 2306 2402 2307 2307 2403 2282 2282 2377 2307 2307 2403 2283 2283 2378 2283 2283 2378 2307 2307 2403 2308 2308 2404 2283 2283 2378 2308 2308 2404 2284 2284 2379 2284 2284 2379 2308 2308 2404 2309 2309 2405 2284 2284 2379 2309 2309 2405 2285 2285 2380 2285 2285 2380 2309 2309 2405 2310 2310 2406 2285 2285 2380 2310 2310 2406 2286 2286 2381 2286 2286 2381 2310 2310 2406 2311 2311 2407 2286 2286 2381 2311 2311 2407 2287 2287 2382 2287 2287 2382 2311 2311 2407 2312 2312 2408 2287 2287 2382 2312 2312 2408 2288 2288 2383 2288 2288 2383 2312 2312 2408 2313 2313 2409 2288 2288 2383 2313 2313 2409 2289 2289 2384 2289 2289 2384 2313 2313 2409 2314 2314 2410 2289 2289 2384 2314 2314 2410 2290 2290 2385 2290 2290 2385 2314 2314 2410 2315 2315 2411 2290 2290 2385 2315 2315 2411 2291 2291 2386 2291 2291 2386 2315 2315 2411 2316 2316 2412 2291 2291 2386 2316 2316 2412 2292 2292 2387 2292 2292 2387 2316 2316 2412 2317 2317 2413 2292 2292 2387 2317 2317 2413 2293 2293 2388 2293 2293 2388 2317 2317 2413 2318 2318 2414 2293 2293 2388 2318 2318 2414 2294 2294 2389 2294 2294 2389 2318 2318 2414 2319 2319 2415 2294 2294 2389 2319 2319 2415 2295 2295 2390 2295 2295 2390 2319 2319 2415 2320 2320 2416 2295 2295 2390 2320 2320 2416 2296 2296 2391 2296 2296 2391 2320 2320 2416 2321 2321 2417 2296 2296 2391 2321 2321 2417 2297 2297 2392 2297 2297 2392 2321 2321 2417 2322 2322 2418 2297 2297 2392 2322 2322 2418 2298 2298 2393 2298 2298 2393 2322 2322 2418 2323 2323 2419 2298 2298 2393 2323 2323 2419 2299 2299 2394 2299 2299 2394 2323 2323 2419 2324 2324 2420 2299 2299 2394 2324 2324 2420 2300 2300 2395 2300 2300 2395 2324 2324 2420 2325 2325 2421 2300 2300 2395 2325 2325 2421 2301 2301 2396 2301 2301 2396 2325 2325 2421 2326 2326 2422 2301 2301 2396 2326 2326 2422 2302 2302 2397 2302 2302 2397 2326 2326 2422 2327 2327 2423 2302 2302 2397 2327 2327 2423 2303 2303 2398 2303 2303 2398 2327 2327 2423 2304 2304 2424 2303 2303 2398 2304 2304 2424 2280 2280 2399 2304 2304 2400 2328 2328 2425 2329 2329 2426 2304 2304 2400 2329 2329 2426 2305 2305 2401 2305 2305 2401 2329 2329 2426 2330 2330 2427 2305 2305 2401 2330 2330 2427 2306 2306 2402 2306 2306 2402 2330 2330 2427 2331 2331 2428 2306 2306 2402 2331 2331 2428 2307 2307 2403 2307 2307 2403 2331 2331 2428 2332 2332 2429 2307 2307 2403 2332 2332 2429 2308 2308 2404 2308 2308 2404 2332 2332 2429 2333 2333 2430 2308 2308 2404 2333 2333 2430 2309 2309 2405 2309 2309 2405 2333 2333 2430 2334 2334 2431 2309 2309 2405 2334 2334 2431 2310 2310 2406 2310 2310 2406 2334 2334 2431 2335 2335 2432 2310 2310 2406 2335 2335 2432 2311 2311 2407 2311 2311 2407 2335 2335 2432 2336 2336 2433 2311 2311 2407 2336 2336 2433 2312 2312 2408 2312 2312 2408 2336 2336 2433 2337 2337 2434 2312 2312 2408 2337 2337 2434 2313 2313 2409 2313 2313 2409 2337 2337 2434 2338 2338 2435 2313 2313 2409 2338 2338 2435 2314 2314 2410 2314 2314 2410 2338 2338 2435 2339 2339 2436 2314 2314 2410 2339 2339 2436 2315 2315 2411 2315 2315 2411 2339 2339 2436 2340 2340 2437 2315 2315 2411 2340 2340 2437 2316 2316 2412 2316 2316 2412 2340 2340 2437 2341 2341 2438 2316 2316 2412 2341 2341 2438 2317 2317 2413 2317 2317 2413 2341 2341 2438 2342 2342 2439 2317 2317 2413 2342 2342 2439 2318 2318 2414 2318 2318 2414 2342 2342 2439 2343 2343 2440 2318 2318 2414 2343 2343 2440 2319 2319 2415 2319 2319 2415 2343 2343 2440 2344 2344 2441 2319 2319 2415 2344 2344 2441 2320 2320 2416 2320 2320 2416 2344 2344 2441 2345 2345 2442 2320 2320 2416 2345 2345 2442 2321 2321 2417 2321 2321 2417 2345 2345 2442 2346 2346 2443 2321 2321 2417 2346 2346 2443 2322 2322 2418 2322 2322 2418 2346 2346 2443 2347 2347 2444 2322 2322 2418 2347 2347 2444 2323 2323 2419 2323 2323 2419 2347 2347 2444 2348 2348 2445 2323 2323 2419 2348 2348 2445 2324 2324 2420 2324 2324 2420 2348 2348 2445 2349 2349 2446 2324 2324 2420 2349 2349 2446 2325 2325 2421 2325 2325 2421 2349 2349 2446 2350 2350 2447 2325 2325 2421 2350 2350 2447 2326 2326 2422 2326 2326 2422 2350 2350 2447 2351 2351 2448 2326 2326 2422 2351 2351 2448 2327 2327 2423 2327 2327 2423 2351 2351 2448 2328 2328 2449 2327 2327 2423 2328 2328 2449 2304 2304 2424 2328 2328 2425 2352 2352 2450 2353 2353 2451 2328 2328 2425 2353 2353 2451 2329 2329 2426 2329 2329 2426 2353 2353 2451 2354 2354 2452 2329 2329 2426 2354 2354 2452 2330 2330 2427 2330 2330 2427 2354 2354 2452 2355 2355 2453 2330 2330 2427 2355 2355 2453 2331 2331 2428 2331 2331 2428 2355 2355 2453 2356 2356 2454 2331 2331 2428 2356 2356 2454 2332 2332 2429 2332 2332 2429 2356 2356 2454 2357 2357 2455 2332 2332 2429 2357 2357 2455 2333 2333 2430 2333 2333 2430 2357 2357 2455 2358 2358 2456 2333 2333 2430 2358 2358 2456 2334 2334 2431 2334 2334 2431 2358 2358 2456 2359 2359 2457 2334 2334 2431 2359 2359 2457 2335 2335 2432 2335 2335 2432 2359 2359 2457 2360 2360 2458 2335 2335 2432 2360 2360 2458 2336 2336 2433 2336 2336 2433 2360 2360 2458 2361 2361 2459 2336 2336 2433 2361 2361 2459 2337 2337 2434 2337 2337 2434 2361 2361 2459 2362 2362 2460 2337 2337 2434 2362 2362 2460 2338 2338 2435 2338 2338 2435 2362 2362 2460 2363 2363 2461 2338 2338 2435 2363 2363 2461 2339 2339 2436 2339 2339 2436 2363 2363 2461 2364 2364 2462 2339 2339 2436 2364 2364 2462 2340 2340 2437 2340 2340 2437 2364 2364 2462 2365 2365 2463 2340 2340 2437 2365 2365 2463 2341 2341 2438 2341 2341 2438 2365 2365 2463 2366 2366 2464 2341 2341 2438 2366 2366 2464 2342 2342 2439 2342 2342 2439 2366 2366 2464 2367 2367 2465 2342 2342 2439 2367 2367 2465 2343 2343 2440 2343 2343 2440 2367 2367 2465 2368 2368 2466 2343 2343 2440 2368 2368 2466 2344 2344 2441 2344 2344 2441 2368 2368 2466 2369 2369 2467 2344 2344 2441 2369 2369 2467 2345 2345 2442 2345 2345 2442 2369 2369 2467 2370 2370 2468 2345 2345 2442 2370 2370 2468 2346 2346 2443 2346 2346 2443 2370 2370 2468 2371 2371 2469 2346 2346 2443 2371 2371 2469 2347 2347 2444 2347 2347 2444 2371 2371 2469 2372 2372 2470 2347 2347 2444 2372 2372 2470 2348 2348 2445 2348 2348 2445 2372 2372 2470 2373 2373 2471 2348 2348 2445 2373 2373 2471 2349 2349 2446 2349 2349 2446 2373 2373 2471 2374 2374 2472 2349 2349 2446 2374 2374 2472 2350 2350 2447 2350 2350 2447 2374 2374 2472 2375 2375 2473 2350 2350 2447 2375 2375 2473 2351 2351 2448 2351 2351 2448 2375 2375 2473 2352 2352 2474 2351 2351 2448 2352 2352 2474 2328 2328 2449 2352 2352 2450 2376 2376 2475 2377 2377 2476 2352 2352 2450 2377 2377 2476 2353 2353 2451 2353 2353 2451 2377 2377 2476 2378 2378 2477 2353 2353 2451 2378 2378 2477 2354 2354 2452 2354 2354 2452 2378 2378 2477 2379 2379 2478 2354 2354 2452 2379 2379 2478 2355 2355 2453 2355 2355 2453 2379 2379 2478 2380 2380 2479 2355 2355 2453 2380 2380 2479 2356 2356 2454 2356 2356 2454 2380 2380 2479 2381 2381 2480 2356 2356 2454 2381 2381 2480 2357 2357 2455 2357 2357 2455 2381 2381 2480 2382 2382 2481 2357 2357 2455 2382 2382 2481 2358 2358 2456 2358 2358 2456 2382 2382 2481 2383 2383 2482 2358 2358 2456 2383 2383 2482 2359 2359 2457 2359 2359 2457 2383 2383 2482 2384 2384 2483 2359 2359 2457 2384 2384 2483 2360 2360 2458 2360 2360 2458 2384 2384 2483 2385 2385 2484 2360 2360 2458 2385 2385 2484 2361 2361 2459 2361 2361 2459 2385 2385 2484 2386 2386 2485 2361 2361 2459 2386 2386 2485 2362 2362 2460 2362 2362 2460 2386 2386 2485 2387 2387 2486 2362 2362 2460 2387 2387 2486 2363 2363 2461 2363 2363 2461 2387 2387 2486 2388 2388 2487 2363 2363 2461 2388 2388 2487 2364 2364 2462 2364 2364 2462 2388 2388 2487 2389 2389 2488 2364 2364 2462 2389 2389 2488 2365 2365 2463 2365 2365 2463 2389 2389 2488 2390 2390 2489 2365 2365 2463 2390 2390 2489 2366 2366 2464 2366 2366 2464 2390 2390 2489 2391 2391 2490 2366 2366 2464 2391 2391 2490 2367 2367 2465 2367 2367 2465 2391 2391 2490 2392 2392 2491 2367 2367 2465 2392 2392 2491 2368 2368 2466 2368 2368 2466 2392 2392 2491 2393 2393 2492 2368 2368 2466 2393 2393 2492 2369 2369 2467 2369 2369 2467 2393 2393 2492 2394 2394 2493 2369 2369 2467 2394 2394 2493 2370 2370 2468 2370 2370 2468 2394 2394 2493 2395 2395 2494 2370 2370 2468 2395 2395 2494 2371 2371 2469 2371 2371 2469 2395 2395 2494 2396 2396 2495 2371 2371 2469 2396 2396 2495 2372 2372 2470 2372 2372 2470 2396 2396 2495 2397 2397 2496 2372 2372 2470 2397 2397 2496 2373 2373 2471 2373 2373 2471 2397 2397 2496 2398 2398 2497 2373 2373 2471 2398 2398 2497 2374 2374 2472 2374 2374 2472 2398 2398 2497 2399 2399 2498 2374 2374 2472 2399 2399 2498 2375 2375 2473 2375 2375 2473 2399 2399 2498 2376 2376 2499 2375 2375 2473 2376 2376 2499 2352 2352 2474 2376 2376 2475 2400 2400 2500 2401 2401 2501 2376 2376 2475 2401 2401 2501 2377 2377 2476 2377 2377 2476 2401 2401 2501 2402 2402 2502 2377 2377 2476 2402 2402 2502 2378 2378 2477 2378 2378 2477 2402 2402 2502 2403 2403 2503 2378 2378 2477 2403 2403 2503 2379 2379 2478 2379 2379 2478 2403 2403 2503 2404 2404 2504 2379 2379 2478 2404 2404 2504 2380 2380 2479 2380 2380 2479 2404 2404 2504 2405 2405 2505 2380 2380 2479 2405 2405 2505 2381 2381 2480 2381 2381 2480 2405 2405 2505 2406 2406 2506 2381 2381 2480 2406 2406 2506 2382 2382 2481 2382 2382 2481 2406 2406 2506 2407 2407 2507 2382 2382 2481 2407 2407 2507 2383 2383 2482 2383 2383 2482 2407 2407 2507 2408 2408 2508 2383 2383 2482 2408 2408 2508 2384 2384 2483 2384 2384 2483 2408 2408 2508 2409 2409 2509 2384 2384 2483 2409 2409 2509 2385 2385 2484 2385 2385 2484 2409 2409 2509 2410 2410 2510 2385 2385 2484 2410 2410 2510 2386 2386 2485 2386 2386 2485 2410 2410 2510 2411 2411 2511 2386 2386 2485 2411 2411 2511 2387 2387 2486 2387 2387 2486 2411 2411 2511 2412 2412 2512 2387 2387 2486 2412 2412 2512 2388 2388 2487 2388 2388 2487 2412 2412 2512 2413 2413 2513 2388 2388 2487 2413 2413 2513 2389 2389 2488 2389 2389 2488 2413 2413 2513 2414 2414 2514 2389 2389 2488 2414 2414 2514 2390 2390 2489 2390 2390 2489 2414 2414 2514 2415 2415 2515 2390 2390 2489 2415 2415 2515 2391 2391 2490 2391 2391 2490 2415 2415 2515 2416 2416 2516 2391 2391 2490 2416 2416 2516 2392 2392 2491 2392 2392 2491 2416 2416 2516 2417 2417 2517 2392 2392 2491 2417 2417 2517 2393 2393 2492 2393 2393 2492 2417 2417 2517 2418 2418 2518 2393 2393 2492 2418 2418 2518 2394 2394 2493 2394 2394 2493 2418 2418 2518 2419 2419 2519 2394 2394 2493 2419 2419 2519 2395 2395 2494 2395 2395 2494 2419 2419 2519 2420 2420 2520 2395 2395 2494 2420 2420 2520 2396 2396 2495 2396 2396 2495 2420 2420 2520 2421 2421 2521 2396 2396 2495 2421 2421 2521 2397 2397 2496 2397 2397 2496 2421 2421 2521 2422 2422 2522 2397 2397 2496 2422 2422 2522 2398 2398 2497 2398 2398 2497 2422 2422 2522 2423 2423 2523 2398 2398 2497 2423 2423 2523 2399 2399 2498 2399 2399 2498 2423 2423 2523 2400 2400 2524 2399 2399 2498 2400 2400 2524 2376 2376 2499 2400 2400 2500 2424 2424 2525 2425 2425 2526 2400 2400 2500 2425 2425 2526 2401 2401 2501 2401 2401 2501 2425 2425 2526 2426 2426 2527 2401 2401 2501 2426 2426 2527 2402 2402 2502 2402 2402 2502 2426 2426 2527 2427 2427 2528 2402 2402 2502 2427 2427 2528 2403 2403 2503 2403 2403 2503 2427 2427 2528 2428 2428 2529 2403 2403 2503 2428 2428 2529 2404 2404 2504 2404 2404 2504 2428 2428 2529 2429 2429 2530 2404 2404 2504 2429 2429 2530 2405 2405 2505 2405 2405 2505 2429 2429 2530 2430 2430 2531 2405 2405 2505 2430 2430 2531 2406 2406 2506 2406 2406 2506 2430 2430 2531 2431 2431 2532 2406 2406 2506 2431 2431 2532 2407 2407 2507 2407 2407 2507 2431 2431 2532 2432 2432 2533 2407 2407 2507 2432 2432 2533 2408 2408 2508 2408 2408 2508 2432 2432 2533 2433 2433 2534 2408 2408 2508 2433 2433 2534 2409 2409 2509 2409 2409 2509 2433 2433 2534 2434 2434 2535 2409 2409 2509 2434 2434 2535 2410 2410 2510 2410 2410 2510 2434 2434 2535 2435 2435 2536 2410 2410 2510 2435 2435 2536 2411 2411 2511 2411 2411 2511 2435 2435 2536 2436 2436 2537 2411 2411 2511 2436 2436 2537 2412 2412 2512 2412 2412 2512 2436 2436 2537 2437 2437 2538 2412 2412 2512 2437 2437 2538 2413 2413 2513 2413 2413 2513 2437 2437 2538 2438 2438 2539 2413 2413 2513 2438 2438 2539 2414 2414 2514 2414 2414 2514 2438 2438 2539 2439 2439 2540 2414 2414 2514 2439 2439 2540 2415 2415 2515 2415 2415 2515 2439 2439 2540 2440 2440 2541 2415 2415 2515 2440 2440 2541 2416 2416 2516 2416 2416 2516 2440 2440 2541 2441 2441 2542 2416 2416 2516 2441 2441 2542 2417 2417 2517 2417 2417 2517 2441 2441 2542 2442 2442 2543 2417 2417 2517 2442 2442 2543 2418 2418 2518 2418 2418 2518 2442 2442 2543 2443 2443 2544 2418 2418 2518 2443 2443 2544 2419 2419 2519 2419 2419 2519 2443 2443 2544 2444 2444 2545 2419 2419 2519 2444 2444 2545 2420 2420 2520 2420 2420 2520 2444 2444 2545 2445 2445 2546 2420 2420 2520 2445 2445 2546 2421 2421 2521 2421 2421 2521 2445 2445 2546 2446 2446 2547 2421 2421 2521 2446 2446 2547 2422 2422 2522 2422 2422 2522 2446 2446 2547 2447 2447 2548 2422 2422 2522 2447 2447 2548 2423 2423 2523 2423 2423 2523 2447 2447 2548 2424 2424 2549 2423 2423 2523 2424 2424 2549 2400 2400 2524 2424 2424 2525 2448 2448 2550 2449 2449 2551 2424 2424 2525 2449 2449 2551 2425 2425 2526 2425 2425 2526 2449 2449 2551 2450 2450 2552 2425 2425 2526 2450 2450 2552 2426 2426 2527 2426 2426 2527 2450 2450 2552 2451 2451 2553 2426 2426 2527 2451 2451 2553 2427 2427 2528 2427 2427 2528 2451 2451 2553 2452 2452 2554 2427 2427 2528 2452 2452 2554 2428 2428 2529 2428 2428 2529 2452 2452 2554 2453 2453 2555 2428 2428 2529 2453 2453 2555 2429 2429 2530 2429 2429 2530 2453 2453 2555 2454 2454 2556 2429 2429 2530 2454 2454 2556 2430 2430 2531 2430 2430 2531 2454 2454 2556 2455 2455 2557 2430 2430 2531 2455 2455 2557 2431 2431 2532 2431 2431 2532 2455 2455 2557 2456 2456 2558 2431 2431 2532 2456 2456 2558 2432 2432 2533 2432 2432 2533 2456 2456 2558 2457 2457 2559 2432 2432 2533 2457 2457 2559 2433 2433 2534 2433 2433 2534 2457 2457 2559 2458 2458 2560 2433 2433 2534 2458 2458 2560 2434 2434 2535 2434 2434 2535 2458 2458 2560 2459 2459 2561 2434 2434 2535 2459 2459 2561 2435 2435 2536 2435 2435 2536 2459 2459 2561 2460 2460 2562 2435 2435 2536 2460 2460 2562 2436 2436 2537 2436 2436 2537 2460 2460 2562 2461 2461 2563 2436 2436 2537 2461 2461 2563 2437 2437 2538 2437 2437 2538 2461 2461 2563 2462 2462 2564 2437 2437 2538 2462 2462 2564 2438 2438 2539 2438 2438 2539 2462 2462 2564 2463 2463 2565 2438 2438 2539 2463 2463 2565 2439 2439 2540 2439 2439 2540 2463 2463 2565 2464 2464 2566 2439 2439 2540 2464 2464 2566 2440 2440 2541 2440 2440 2541 2464 2464 2566 2465 2465 2567 2440 2440 2541 2465 2465 2567 2441 2441 2542 2441 2441 2542 2465 2465 2567 2466 2466 2568 2441 2441 2542 2466 2466 2568 2442 2442 2543 2442 2442 2543 2466 2466 2568 2467 2467 2569 2442 2442 2543 2467 2467 2569 2443 2443 2544 2443 2443 2544 2467 2467 2569 2468 2468 2570 2443 2443 2544 2468 2468 2570 2444 2444 2545 2444 2444 2545 2468 2468 2570 2469 2469 2571 2444 2444 2545 2469 2469 2571 2445 2445 2546 2445 2445 2546 2469 2469 2571 2470 2470 2572 2445 2445 2546 2470 2470 2572 2446 2446 2547 2446 2446 2547 2470 2470 2572 2471 2471 2573 2446 2446 2547 2471 2471 2573 2447 2447 2548 2447 2447 2548 2471 2471 2573 2448 2448 2574 2447 2447 2548 2448 2448 2574 2424 2424 2549 2448 2448 2550 2472 2472 2575 2473 2473 2576 2448 2448 2550 2473 2473 2576 2449 2449 2551 2449 2449 2551 2473 2473 2576 2474 2474 2577 2449 2449 2551 2474 2474 2577 2450 2450 2552 2450 2450 2552 2474 2474 2577 2475 2475 2578 2450 2450 2552 2475 2475 2578 2451 2451 2553 2451 2451 2553 2475 2475 2578 2476 2476 2579 2451 2451 2553 2476 2476 2579 2452 2452 2554 2452 2452 2554 2476 2476 2579 2477 2477 2580 2452 2452 2554 2477 2477 2580 2453 2453 2555 2453 2453 2555 2477 2477 2580 2478 2478 2581 2453 2453 2555 2478 2478 2581 2454 2454 2556 2454 2454 2556 2478 2478 2581 2479 2479 2582 2454 2454 2556 2479 2479 2582 2455 2455 2557 2455 2455 2557 2479 2479 2582 2480 2480 2583 2455 2455 2557 2480 2480 2583 2456 2456 2558 2456 2456 2558 2480 2480 2583 2481 2481 2584 2456 2456 2558 2481 2481 2584 2457 2457 2559 2457 2457 2559 2481 2481 2584 2482 2482 2585 2457 2457 2559 2482 2482 2585 2458 2458 2560 2458 2458 2560 2482 2482 2585 2483 2483 2586 2458 2458 2560 2483 2483 2586 2459 2459 2561 2459 2459 2561 2483 2483 2586 2484 2484 2587 2459 2459 2561 2484 2484 2587 2460 2460 2562 2460 2460 2562 2484 2484 2587 2485 2485 2588 2460 2460 2562 2485 2485 2588 2461 2461 2563 2461 2461 2563 2485 2485 2588 2486 2486 2589 2461 2461 2563 2486 2486 2589 2462 2462 2564 2462 2462 2564 2486 2486 2589 2487 2487 2590 2462 2462 2564 2487 2487 2590 2463 2463 2565 2463 2463 2565 2487 2487 2590 2488 2488 2591 2463 2463 2565 2488 2488 2591 2464 2464 2566 2464 2464 2566 2488 2488 2591 2489 2489 2592 2464 2464 2566 2489 2489 2592 2465 2465 2567 2465 2465 2567 2489 2489 2592 2490 2490 2593 2465 2465 2567 2490 2490 2593 2466 2466 2568 2466 2466 2568 2490 2490 2593 2491 2491 2594 2466 2466 2568 2491 2491 2594 2467 2467 2569 2467 2467 2569 2491 2491 2594 2492 2492 2595 2467 2467 2569 2492 2492 2595 2468 2468 2570 2468 2468 2570 2492 2492 2595 2493 2493 2596 2468 2468 2570 2493 2493 2596 2469 2469 2571 2469 2469 2571 2493 2493 2596 2494 2494 2597 2469 2469 2571 2494 2494 2597 2470 2470 2572 2470 2470 2572 2494 2494 2597 2495 2495 2598 2470 2470 2572 2495 2495 2598 2471 2471 2573 2471 2471 2573 2495 2495 2598 2472 2472 2599 2471 2471 2573 2472 2472 2599 2448 2448 2574 2472 2472 2575 2496 2496 2600 2497 2497 2601 2472 2472 2575 2497 2497 2601 2473 2473 2576 2473 2473 2576 2497 2497 2601 2498 2498 2602 2473 2473 2576 2498 2498 2602 2474 2474 2577 2474 2474 2577 2498 2498 2602 2499 2499 2603 2474 2474 2577 2499 2499 2603 2475 2475 2578 2475 2475 2578 2499 2499 2603 2500 2500 2604 2475 2475 2578 2500 2500 2604 2476 2476 2579 2476 2476 2579 2500 2500 2604 2501 2501 2605 2476 2476 2579 2501 2501 2605 2477 2477 2580 2477 2477 2580 2501 2501 2605 2502 2502 2606 2477 2477 2580 2502 2502 2606 2478 2478 2581 2478 2478 2581 2502 2502 2606 2503 2503 2607 2478 2478 2581 2503 2503 2607 2479 2479 2582 2479 2479 2582 2503 2503 2607 2504 2504 2608 2479 2479 2582 2504 2504 2608 2480 2480 2583 2480 2480 2583 2504 2504 2608 2505 2505 2609 2480 2480 2583 2505 2505 2609 2481 2481 2584 2481 2481 2584 2505 2505 2609 2506 2506 2610 2481 2481 2584 2506 2506 2610 2482 2482 2585 2482 2482 2585 2506 2506 2610 2507 2507 2611 2482 2482 2585 2507 2507 2611 2483 2483 2586 2483 2483 2586 2507 2507 2611 2508 2508 2612 2483 2483 2586 2508 2508 2612 2484 2484 2587 2484 2484 2587 2508 2508 2612 2509 2509 2613 2484 2484 2587 2509 2509 2613 2485 2485 2588 2485 2485 2588 2509 2509 2613 2510 2510 2614 2485 2485 2588 2510 2510 2614 2486 2486 2589 2486 2486 2589 2510 2510 2614 2511 2511 2615 2486 2486 2589 2511 2511 2615 2487 2487 2590 2487 2487 2590 2511 2511 2615 2512 2512 2616 2487 2487 2590 2512 2512 2616 2488 2488 2591 2488 2488 2591 2512 2512 2616 2513 2513 2617 2488 2488 2591 2513 2513 2617 2489 2489 2592 2489 2489 2592 2513 2513 2617 2514 2514 2618 2489 2489 2592 2514 2514 2618 2490 2490 2593 2490 2490 2593 2514 2514 2618 2515 2515 2619 2490 2490 2593 2515 2515 2619 2491 2491 2594 2491 2491 2594 2515 2515 2619 2516 2516 2620 2491 2491 2594 2516 2516 2620 2492 2492 2595 2492 2492 2595 2516 2516 2620 2517 2517 2621 2492 2492 2595 2517 2517 2621 2493 2493 2596 2493 2493 2596 2517 2517 2621 2518 2518 2622 2493 2493 2596 2518 2518 2622 2494 2494 2597 2494 2494 2597 2518 2518 2622 2519 2519 2623 2494 2494 2597 2519 2519 2623 2495 2495 2598 2495 2495 2598 2519 2519 2623 2496 2496 2624 2495 2495 2598 2496 2496 2624 2472 2472 2599 2496 2496 2600 2520 2520 2625 2521 2521 2626 2496 2496 2600 2521 2521 2626 2497 2497 2601 2497 2497 2601 2521 2521 2626 2522 2522 2627 2497 2497 2601 2522 2522 2627 2498 2498 2602 2498 2498 2602 2522 2522 2627 2523 2523 2628 2498 2498 2602 2523 2523 2628 2499 2499 2603 2499 2499 2603 2523 2523 2628 2524 2524 2629 2499 2499 2603 2524 2524 2629 2500 2500 2604 2500 2500 2604 2524 2524 2629 2525 2525 2630 2500 2500 2604 2525 2525 2630 2501 2501 2605 2501 2501 2605 2525 2525 2630 2526 2526 2631 2501 2501 2605 2526 2526 2631 2502 2502 2606 2502 2502 2606 2526 2526 2631 2527 2527 2632 2502 2502 2606 2527 2527 2632 2503 2503 2607 2503 2503 2607 2527 2527 2632 2528 2528 2633 2503 2503 2607 2528 2528 2633 2504 2504 2608 2504 2504 2608 2528 2528 2633 2529 2529 2634 2504 2504 2608 2529 2529 2634 2505 2505 2609 2505 2505 2609 2529 2529 2634 2530 2530 2635 2505 2505 2609 2530 2530 2635 2506 2506 2610 2506 2506 2610 2530 2530 2635 2531 2531 2636 2506 2506 2610 2531 2531 2636 2507 2507 2611 2507 2507 2611 2531 2531 2636 2532 2532 2637 2507 2507 2611 2532 2532 2637 2508 2508 2612 2508 2508 2612 2532 2532 2637 2533 2533 2638 2508 2508 2612 2533 2533 2638 2509 2509 2613 2509 2509 2613 2533 2533 2638 2534 2534 2639 2509 2509 2613 2534 2534 2639 2510 2510 2614 2510 2510 2614 2534 2534 2639 2535 2535 2640 2510 2510 2614 2535 2535 2640 2511 2511 2615 2511 2511 2615 2535 2535 2640 2536 2536 2641 2511 2511 2615 2536 2536 2641 2512 2512 2616 2512 2512 2616 2536 2536 2641 2537 2537 2642 2512 2512 2616 2537 2537 2642 2513 2513 2617 2513 2513 2617 2537 2537 2642 2538 2538 2643 2513 2513 2617 2538 2538 2643 2514 2514 2618 2514 2514 2618 2538 2538 2643 2539 2539 2644 2514 2514 2618 2539 2539 2644 2515 2515 2619 2515 2515 2619 2539 2539 2644 2540 2540 2645 2515 2515 2619 2540 2540 2645 2516 2516 2620 2516 2516 2620 2540 2540 2645 2541 2541 2646 2516 2516 2620 2541 2541 2646 2517 2517 2621 2517 2517 2621 2541 2541 2646 2542 2542 2647 2517 2517 2621 2542 2542 2647 2518 2518 2622 2518 2518 2622 2542 2542 2647 2543 2543 2648 2518 2518 2622 2543 2543 2648 2519 2519 2623 2519 2519 2623 2543 2543 2648 2520 2520 2649 2519 2519 2623 2520 2520 2649 2496 2496 2624 2520 2520 2625 2544 2544 2650 2545 2545 2651 2520 2520 2625 2545 2545 2651 2521 2521 2626 2521 2521 2626 2545 2545 2651 2546 2546 2652 2521 2521 2626 2546 2546 2652 2522 2522 2627 2522 2522 2627 2546 2546 2652 2547 2547 2653 2522 2522 2627 2547 2547 2653 2523 2523 2628 2523 2523 2628 2547 2547 2653 2548 2548 2654 2523 2523 2628 2548 2548 2654 2524 2524 2629 2524 2524 2629 2548 2548 2654 2549 2549 2655 2524 2524 2629 2549 2549 2655 2525 2525 2630 2525 2525 2630 2549 2549 2655 2550 2550 2656 2525 2525 2630 2550 2550 2656 2526 2526 2631 2526 2526 2631 2550 2550 2656 2551 2551 2657 2526 2526 2631 2551 2551 2657 2527 2527 2632 2527 2527 2632 2551 2551 2657 2552 2552 2658 2527 2527 2632 2552 2552 2658 2528 2528 2633 2528 2528 2633 2552 2552 2658 2553 2553 2659 2528 2528 2633 2553 2553 2659 2529 2529 2634 2529 2529 2634 2553 2553 2659 2554 2554 2660 2529 2529 2634 2554 2554 2660 2530 2530 2635 2530 2530 2635 2554 2554 2660 2555 2555 2661 2530 2530 2635 2555 2555 2661 2531 2531 2636 2531 2531 2636 2555 2555 2661 2556 2556 2662 2531 2531 2636 2556 2556 2662 2532 2532 2637 2532 2532 2637 2556 2556 2662 2557 2557 2663 2532 2532 2637 2557 2557 2663 2533 2533 2638 2533 2533 2638 2557 2557 2663 2558 2558 2664 2533 2533 2638 2558 2558 2664 2534 2534 2639 2534 2534 2639 2558 2558 2664 2559 2559 2665 2534 2534 2639 2559 2559 2665 2535 2535 2640 2535 2535 2640 2559 2559 2665 2560 2560 2666 2535 2535 2640 2560 2560 2666 2536 2536 2641 2536 2536 2641 2560 2560 2666 2561 2561 2667 2536 2536 2641 2561 2561 2667 2537 2537 2642 2537 2537 2642 2561 2561 2667 2562 2562 2668 2537 2537 2642 2562 2562 2668 2538 2538 2643 2538 2538 2643 2562 2562 2668 2563 2563 2669 2538 2538 2643 2563 2563 2669 2539 2539 2644 2539 2539 2644 2563 2563 2669 2564 2564 2670 2539 2539 2644 2564 2564 2670 2540 2540 2645 2540 2540 2645 2564 2564 2670 2565 2565 2671 2540 2540 2645 2565 2565 2671 2541 2541 2646 2541 2541 2646 2565 2565 2671 2566 2566 2672 2541 2541 2646 2566 2566 2672 2542 2542 2647 2542 2542 2647 2566 2566 2672 2567 2567 2673 2542 2542 2647 2567 2567 2673 2543 2543 2648 2543 2543 2648 2567 2567 2673 2544 2544 2674 2543 2543 2648 2544 2544 2674 2520 2520 2649 2544 2544 2650 2568 2568 2675 2569 2569 2676 2544 2544 2650 2569 2569 2676 2545 2545 2651 2545 2545 2651 2569 2569 2676 2570 2570 2677 2545 2545 2651 2570 2570 2677 2546 2546 2652 2546 2546 2652 2570 2570 2677 2571 2571 2678 2546 2546 2652 2571 2571 2678 2547 2547 2653 2547 2547 2653 2571 2571 2678 2572 2572 2679 2547 2547 2653 2572 2572 2679 2548 2548 2654 2548 2548 2654 2572 2572 2679 2573 2573 2680 2548 2548 2654 2573 2573 2680 2549 2549 2655 2549 2549 2655 2573 2573 2680 2574 2574 2681 2549 2549 2655 2574 2574 2681 2550 2550 2656 2550 2550 2656 2574 2574 2681 2575 2575 2682 2550 2550 2656 2575 2575 2682 2551 2551 2657 2551 2551 2657 2575 2575 2682 2576 2576 2683 2551 2551 2657 2576 2576 2683 2552 2552 2658 2552 2552 2658 2576 2576 2683 2577 2577 2684 2552 2552 2658 2577 2577 2684 2553 2553 2659 2553 2553 2659 2577 2577 2684 2578 2578 2685 2553 2553 2659 2578 2578 2685 2554 2554 2660 2554 2554 2660 2578 2578 2685 2579 2579 2686 2554 2554 2660 2579 2579 2686 2555 2555 2661 2555 2555 2661 2579 2579 2686 2580 2580 2687 2555 2555 2661 2580 2580 2687 2556 2556 2662 2556 2556 2662 2580 2580 2687 2581 2581 2688 2556 2556 2662 2581 2581 2688 2557 2557 2663 2557 2557 2663 2581 2581 2688 2582 2582 2689 2557 2557 2663 2582 2582 2689 2558 2558 2664 2558 2558 2664 2582 2582 2689 2583 2583 2690 2558 2558 2664 2583 2583 2690 2559 2559 2665 2559 2559 2665 2583 2583 2690 2584 2584 2691 2559 2559 2665 2584 2584 2691 2560 2560 2666 2560 2560 2666 2584 2584 2691 2585 2585 2692 2560 2560 2666 2585 2585 2692 2561 2561 2667 2561 2561 2667 2585 2585 2692 2586 2586 2693 2561 2561 2667 2586 2586 2693 2562 2562 2668 2562 2562 2668 2586 2586 2693 2587 2587 2694 2562 2562 2668 2587 2587 2694 2563 2563 2669 2563 2563 2669 2587 2587 2694 2588 2588 2695 2563 2563 2669 2588 2588 2695 2564 2564 2670 2564 2564 2670 2588 2588 2695 2589 2589 2696 2564 2564 2670 2589 2589 2696 2565 2565 2671 2565 2565 2671 2589 2589 2696 2590 2590 2697 2565 2565 2671 2590 2590 2697 2566 2566 2672 2566 2566 2672 2590 2590 2697 2591 2591 2698 2566 2566 2672 2591 2591 2698 2567 2567 2673 2567 2567 2673 2591 2591 2698 2568 2568 2699 2567 2567 2673 2568 2568 2699 2544 2544 2674 2568 2568 2675 2592 2592 2700 2593 2593 2701 2568 2568 2675 2593 2593 2701 2569 2569 2676 2569 2569 2676 2593 2593 2701 2594 2594 2702 2569 2569 2676 2594 2594 2702 2570 2570 2677 2570 2570 2677 2594 2594 2702 2595 2595 2703 2570 2570 2677 2595 2595 2703 2571 2571 2678 2571 2571 2678 2595 2595 2703 2596 2596 2704 2571 2571 2678 2596 2596 2704 2572 2572 2679 2572 2572 2679 2596 2596 2704 2597 2597 2705 2572 2572 2679 2597 2597 2705 2573 2573 2680 2573 2573 2680 2597 2597 2705 2598 2598 2706 2573 2573 2680 2598 2598 2706 2574 2574 2681 2574 2574 2681 2598 2598 2706 2599 2599 2707 2574 2574 2681 2599 2599 2707 2575 2575 2682 2575 2575 2682 2599 2599 2707 2600 2600 2708 2575 2575 2682 2600 2600 2708 2576 2576 2683 2576 2576 2683 2600 2600 2708 2601 2601 2709 2576 2576 2683 2601 2601 2709 2577 2577 2684 2577 2577 2684 2601 2601 2709 2602 2602 2710 2577 2577 2684 2602 2602 2710 2578 2578 2685 2578 2578 2685 2602 2602 2710 2603 2603 2711 2578 2578 2685 2603 2603 2711 2579 2579 2686 2579 2579 2686 2603 2603 2711 2604 2604 2712 2579 2579 2686 2604 2604 2712 2580 2580 2687 2580 2580 2687 2604 2604 2712 2605 2605 2713 2580 2580 2687 2605 2605 2713 2581 2581 2688 2581 2581 2688 2605 2605 2713 2606 2606 2714 2581 2581 2688 2606 2606 2714 2582 2582 2689 2582 2582 2689 2606 2606 2714 2607 2607 2715 2582 2582 2689 2607 2607 2715 2583 2583 2690 2583 2583 2690 2607 2607 2715 2608 2608 2716 2583 2583 2690 2608 2608 2716 2584 2584 2691 2584 2584 2691 2608 2608 2716 2609 2609 2717 2584 2584 2691 2609 2609 2717 2585 2585 2692 2585 2585 2692 2609 2609 2717 2610 2610 2718 2585 2585 2692 2610 2610 2718 2586 2586 2693 2586 2586 2693 2610 2610 2718 2611 2611 2719 2586 2586 2693 2611 2611 2719 2587 2587 2694 2587 2587 2694 2611 2611 2719 2612 2612 2720 2587 2587 2694 2612 2612 2720 2588 2588 2695 2588 2588 2695 2612 2612 2720 2613 2613 2721 2588 2588 2695 2613 2613 2721 2589 2589 2696 2589 2589 2696 2613 2613 2721 2614 2614 2722 2589 2589 2696 2614 2614 2722 2590 2590 2697 2590 2590 2697 2614 2614 2722 2615 2615 2723 2590 2590 2697 2615 2615 2723 2591 2591 2698 2591 2591 2698 2615 2615 2723 2592 2592 2724 2591 2591 2698 2592 2592 2724 2568 2568 2699 2592 2592 2700 2616 2616 2725 2617 2617 2726 2592 2592 2700 2617 2617 2726 2593 2593 2701 2593 2593 2701 2617 2617 2726 2618 2618 2727 2593 2593 2701 2618 2618 2727 2594 2594 2702 2594 2594 2702 2618 2618 2727 2619 2619 2728 2594 2594 2702 2619 2619 2728 2595 2595 2703 2595 2595 2703 2619 2619 2728 2620 2620 2729 2595 2595 2703 2620 2620 2729 2596 2596 2704 2596 2596 2704 2620 2620 2729 2621 2621 2730 2596 2596 2704 2621 2621 2730 2597 2597 2705 2597 2597 2705 2621 2621 2730 2622 2622 2731 2597 2597 2705 2622 2622 2731 2598 2598 2706 2598 2598 2706 2622 2622 2731 2623 2623 2732 2598 2598 2706 2623 2623 2732 2599 2599 2707 2599 2599 2707 2623 2623 2732 2624 2624 2733 2599 2599 2707 2624 2624 2733 2600 2600 2708 2600 2600 2708 2624 2624 2733 2625 2625 2734 2600 2600 2708 2625 2625 2734 2601 2601 2709 2601 2601 2709 2625 2625 2734 2626 2626 2735 2601 2601 2709 2626 2626 2735 2602 2602 2710 2602 2602 2710 2626 2626 2735 2627 2627 2736 2602 2602 2710 2627 2627 2736 2603 2603 2711 2603 2603 2711 2627 2627 2736 2628 2628 2737 2603 2603 2711 2628 2628 2737 2604 2604 2712 2604 2604 2712 2628 2628 2737 2629 2629 2738 2604 2604 2712 2629 2629 2738 2605 2605 2713 2605 2605 2713 2629 2629 2738 2630 2630 2739 2605 2605 2713 2630 2630 2739 2606 2606 2714 2606 2606 2714 2630 2630 2739 2631 2631 2740 2606 2606 2714 2631 2631 2740 2607 2607 2715 2607 2607 2715 2631 2631 2740 2632 2632 2741 2607 2607 2715 2632 2632 2741 2608 2608 2716 2608 2608 2716 2632 2632 2741 2633 2633 2742 2608 2608 2716 2633 2633 2742 2609 2609 2717 2609 2609 2717 2633 2633 2742 2634 2634 2743 2609 2609 2717 2634 2634 2743 2610 2610 2718 2610 2610 2718 2634 2634 2743 2635 2635 2744 2610 2610 2718 2635 2635 2744 2611 2611 2719 2611 2611 2719 2635 2635 2744 2636 2636 2745 2611 2611 2719 2636 2636 2745 2612 2612 2720 2612 2612 2720 2636 2636 2745 2637 2637 2746 2612 2612 2720 2637 2637 2746 2613 2613 2721 2613 2613 2721 2637 2637 2746 2638 2638 2747 2613 2613 2721 2638 2638 2747 2614 2614 2722 2614 2614 2722 2638 2638 2747 2639 2639 2748 2614 2614 2722 2639 2639 2748 2615 2615 2723 2615 2615 2723 2639 2639 2748 2616 2616 2749 2615 2615 2723 2616 2616 2749 2592 2592 2724 2616 2616 2725 2640 2640 2750 2641 2641 2751 2616 2616 2725 2641 2641 2751 2617 2617 2726 2617 2617 2726 2641 2641 2751 2642 2642 2752 2617 2617 2726 2642 2642 2752 2618 2618 2727 2618 2618 2727 2642 2642 2752 2643 2643 2753 2618 2618 2727 2643 2643 2753 2619 2619 2728 2619 2619 2728 2643 2643 2753 2644 2644 2754 2619 2619 2728 2644 2644 2754 2620 2620 2729 2620 2620 2729 2644 2644 2754 2645 2645 2755 2620 2620 2729 2645 2645 2755 2621 2621 2730 2621 2621 2730 2645 2645 2755 2646 2646 2756 2621 2621 2730 2646 2646 2756 2622 2622 2731 2622 2622 2731 2646 2646 2756 2647 2647 2757 2622 2622 2731 2647 2647 2757 2623 2623 2732 2623 2623 2732 2647 2647 2757 2648 2648 2758 2623 2623 2732 2648 2648 2758 2624 2624 2733 2624 2624 2733 2648 2648 2758 2649 2649 2759 2624 2624 2733 2649 2649 2759 2625 2625 2734 2625 2625 2734 2649 2649 2759 2650 2650 2760 2625 2625 2734 2650 2650 2760 2626 2626 2735 2626 2626 2735 2650 2650 2760 2651 2651 2761 2626 2626 2735 2651 2651 2761 2627 2627 2736 2627 2627 2736 2651 2651 2761 2652 2652 2762 2627 2627 2736 2652 2652 2762 2628 2628 2737 2628 2628 2737 2652 2652 2762 2653 2653 2763 2628 2628 2737 2653 2653 2763 2629 2629 2738 2629 2629 2738 2653 2653 2763 2654 2654 2764 2629 2629 2738 2654 2654 2764 2630 2630 2739 2630 2630 2739 2654 2654 2764 2655 2655 2765 2630 2630 2739 2655 2655 2765 2631 2631 2740 2631 2631 2740 2655 2655 2765 2656 2656 2766 2631 2631 2740 2656 2656 2766 2632 2632 2741 2632 2632 2741 2656 2656 2766 2657 2657 2767 2632 2632 2741 2657 2657 2767 2633 2633 2742 2633 2633 2742 2657 2657 2767 2658 2658 2768 2633 2633 2742 2658 2658 2768 2634 2634 2743 2634 2634 2743 2658 2658 2768 2659 2659 2769 2634 2634 2743 2659 2659 2769 2635 2635 2744 2635 2635 2744 2659 2659 2769 2660 2660 2770 2635 2635 2744 2660 2660 2770 2636 2636 2745 2636 2636 2745 2660 2660 2770 2661 2661 2771 2636 2636 2745 2661 2661 2771 2637 2637 2746 2637 2637 2746 2661 2661 2771 2662 2662 2772 2637 2637 2746 2662 2662 2772 2638 2638 2747 2638 2638 2747 2662 2662 2772 2663 2663 2773 2638 2638 2747 2663 2663 2773 2639 2639 2748 2639 2639 2748 2663 2663 2773 2640 2640 2774 2639 2639 2748 2640 2640 2774 2616 2616 2749 2640 2640 2750 2664 2664 2775 2665 2665 2776 2640 2640 2750 2665 2665 2776 2641 2641 2751 2641 2641 2751 2665 2665 2776 2666 2666 2777 2641 2641 2751 2666 2666 2777 2642 2642 2752 2642 2642 2752 2666 2666 2777 2667 2667 2778 2642 2642 2752 2667 2667 2778 2643 2643 2753 2643 2643 2753 2667 2667 2778 2668 2668 2779 2643 2643 2753 2668 2668 2779 2644 2644 2754 2644 2644 2754 2668 2668 2779 2669 2669 2780 2644 2644 2754 2669 2669 2780 2645 2645 2755 2645 2645 2755 2669 2669 2780 2670 2670 2781 2645 2645 2755 2670 2670 2781 2646 2646 2756 2646 2646 2756 2670 2670 2781 2671 2671 2782 2646 2646 2756 2671 2671 2782 2647 2647 2757 2647 2647 2757 2671 2671 2782 2672 2672 2783 2647 2647 2757 2672 2672 2783 2648 2648 2758 2648 2648 2758 2672 2672 2783 2673 2673 2784 2648 2648 2758 2673 2673 2784 2649 2649 2759 2649 2649 2759 2673 2673 2784 2674 2674 2785 2649 2649 2759 2674 2674 2785 2650 2650 2760 2650 2650 2760 2674 2674 2785 2675 2675 2786 2650 2650 2760 2675 2675 2786 2651 2651 2761 2651 2651 2761 2675 2675 2786 2676 2676 2787 2651 2651 2761 2676 2676 2787 2652 2652 2762 2652 2652 2762 2676 2676 2787 2677 2677 2788 2652 2652 2762 2677 2677 2788 2653 2653 2763 2653 2653 2763 2677 2677 2788 2678 2678 2789 2653 2653 2763 2678 2678 2789 2654 2654 2764 2654 2654 2764 2678 2678 2789 2679 2679 2790 2654 2654 2764 2679 2679 2790 2655 2655 2765 2655 2655 2765 2679 2679 2790 2680 2680 2791 2655 2655 2765 2680 2680 2791 2656 2656 2766 2656 2656 2766 2680 2680 2791 2681 2681 2792 2656 2656 2766 2681 2681 2792 2657 2657 2767 2657 2657 2767 2681 2681 2792 2682 2682 2793 2657 2657 2767 2682 2682 2793 2658 2658 2768 2658 2658 2768 2682 2682 2793 2683 2683 2794 2658 2658 2768 2683 2683 2794 2659 2659 2769 2659 2659 2769 2683 2683 2794 2684 2684 2795 2659 2659 2769 2684 2684 2795 2660 2660 2770 2660 2660 2770 2684 2684 2795 2685 2685 2796 2660 2660 2770 2685 2685 2796 2661 2661 2771 2661 2661 2771 2685 2685 2796 2686 2686 2797 2661 2661 2771 2686 2686 2797 2662 2662 2772 2662 2662 2772 2686 2686 2797 2687 2687 2798 2662 2662 2772 2687 2687 2798 2663 2663 2773 2663 2663 2773 2687 2687 2798 2664 2664 2799 2663 2663 2773 2664 2664 2799 2640 2640 2774 2664 2664 2775 2688 2688 2800 2689 2689 2801 2664 2664 2775 2689 2689 2801 2665 2665 2776 2665 2665 2776 2689 2689 2801 2690 2690 2802 2665 2665 2776 2690 2690 2802 2666 2666 2777 2666 2666 2777 2690 2690 2802 2691 2691 2803 2666 2666 2777 2691 2691 2803 2667 2667 2778 2667 2667 2778 2691 2691 2803 2692 2692 2804 2667 2667 2778 2692 2692 2804 2668 2668 2779 2668 2668 2779 2692 2692 2804 2693 2693 2805 2668 2668 2779 2693 2693 2805 2669 2669 2780 2669 2669 2780 2693 2693 2805 2694 2694 2806 2669 2669 2780 2694 2694 2806 2670 2670 2781 2670 2670 2781 2694 2694 2806 2695 2695 2807 2670 2670 2781 2695 2695 2807 2671 2671 2782 2671 2671 2782 2695 2695 2807 2696 2696 2808 2671 2671 2782 2696 2696 2808 2672 2672 2783 2672 2672 2783 2696 2696 2808 2697 2697 2809 2672 2672 2783 2697 2697 2809 2673 2673 2784 2673 2673 2784 2697 2697 2809 2698 2698 2810 2673 2673 2784 2698 2698 2810 2674 2674 2785 2674 2674 2785 2698 2698 2810 2699 2699 2811 2674 2674 2785 2699 2699 2811 2675 2675 2786 2675 2675 2786 2699 2699 2811 2700 2700 2812 2675 2675 2786 2700 2700 2812 2676 2676 2787 2676 2676 2787 2700 2700 2812 2701 2701 2813 2676 2676 2787 2701 2701 2813 2677 2677 2788 2677 2677 2788 2701 2701 2813 2702 2702 2814 2677 2677 2788 2702 2702 2814 2678 2678 2789 2678 2678 2789 2702 2702 2814 2703 2703 2815 2678 2678 2789 2703 2703 2815 2679 2679 2790 2679 2679 2790 2703 2703 2815 2704 2704 2816 2679 2679 2790 2704 2704 2816 2680 2680 2791 2680 2680 2791 2704 2704 2816 2705 2705 2817 2680 2680 2791 2705 2705 2817 2681 2681 2792 2681 2681 2792 2705 2705 2817 2706 2706 2818 2681 2681 2792 2706 2706 2818 2682 2682 2793 2682 2682 2793 2706 2706 2818 2707 2707 2819 2682 2682 2793 2707 2707 2819 2683 2683 2794 2683 2683 2794 2707 2707 2819 2708 2708 2820 2683 2683 2794 2708 2708 2820 2684 2684 2795 2684 2684 2795 2708 2708 2820 2709 2709 2821 2684 2684 2795 2709 2709 2821 2685 2685 2796 2685 2685 2796 2709 2709 2821 2710 2710 2822 2685 2685 2796 2710 2710 2822 2686 2686 2797 2686 2686 2797 2710 2710 2822 2711 2711 2823 2686 2686 2797 2711 2711 2823 2687 2687 2798 2687 2687 2798 2711 2711 2823 2688 2688 2824 2687 2687 2798 2688 2688 2824 2664 2664 2799 2688 2688 2800 2712 2712 2825 2713 2713 2826 2688 2688 2800 2713 2713 2826 2689 2689 2801 2689 2689 2801 2713 2713 2826 2714 2714 2827 2689 2689 2801 2714 2714 2827 2690 2690 2802 2690 2690 2802 2714 2714 2827 2715 2715 2828 2690 2690 2802 2715 2715 2828 2691 2691 2803 2691 2691 2803 2715 2715 2828 2716 2716 2829 2691 2691 2803 2716 2716 2829 2692 2692 2804 2692 2692 2804 2716 2716 2829 2717 2717 2830 2692 2692 2804 2717 2717 2830 2693 2693 2805 2693 2693 2805 2717 2717 2830 2718 2718 2831 2693 2693 2805 2718 2718 2831 2694 2694 2806 2694 2694 2806 2718 2718 2831 2719 2719 2832 2694 2694 2806 2719 2719 2832 2695 2695 2807 2695 2695 2807 2719 2719 2832 2720 2720 2833 2695 2695 2807 2720 2720 2833 2696 2696 2808 2696 2696 2808 2720 2720 2833 2721 2721 2834 2696 2696 2808 2721 2721 2834 2697 2697 2809 2697 2697 2809 2721 2721 2834 2722 2722 2835 2697 2697 2809 2722 2722 2835 2698 2698 2810 2698 2698 2810 2722 2722 2835 2723 2723 2836 2698 2698 2810 2723 2723 2836 2699 2699 2811 2699 2699 2811 2723 2723 2836 2724 2724 2837 2699 2699 2811 2724 2724 2837 2700 2700 2812 2700 2700 2812 2724 2724 2837 2725 2725 2838 2700 2700 2812 2725 2725 2838 2701 2701 2813 2701 2701 2813 2725 2725 2838 2726 2726 2839 2701 2701 2813 2726 2726 2839 2702 2702 2814 2702 2702 2814 2726 2726 2839 2727 2727 2840 2702 2702 2814 2727 2727 2840 2703 2703 2815 2703 2703 2815 2727 2727 2840 2728 2728 2841 2703 2703 2815 2728 2728 2841 2704 2704 2816 2704 2704 2816 2728 2728 2841 2729 2729 2842 2704 2704 2816 2729 2729 2842 2705 2705 2817 2705 2705 2817 2729 2729 2842 2730 2730 2843 2705 2705 2817 2730 2730 2843 2706 2706 2818 2706 2706 2818 2730 2730 2843 2731 2731 2844 2706 2706 2818 2731 2731 2844 2707 2707 2819 2707 2707 2819 2731 2731 2844 2732 2732 2845 2707 2707 2819 2732 2732 2845 2708 2708 2820 2708 2708 2820 2732 2732 2845 2733 2733 2846 2708 2708 2820 2733 2733 2846 2709 2709 2821 2709 2709 2821 2733 2733 2846 2734 2734 2847 2709 2709 2821 2734 2734 2847 2710 2710 2822 2710 2710 2822 2734 2734 2847 2735 2735 2848 2710 2710 2822 2735 2735 2848 2711 2711 2823 2711 2711 2823 2735 2735 2848 2712 2712 2849 2711 2711 2823 2712 2712 2849 2688 2688 2824 2712 2712 2825 2736 2736 2850 2737 2737 2851 2712 2712 2825 2737 2737 2851 2713 2713 2826 2713 2713 2826 2737 2737 2851 2738 2738 2852 2713 2713 2826 2738 2738 2852 2714 2714 2827 2714 2714 2827 2738 2738 2852 2739 2739 2853 2714 2714 2827 2739 2739 2853 2715 2715 2828 2715 2715 2828 2739 2739 2853 2740 2740 2854 2715 2715 2828 2740 2740 2854 2716 2716 2829 2716 2716 2829 2740 2740 2854 2741 2741 2855 2716 2716 2829 2741 2741 2855 2717 2717 2830 2717 2717 2830 2741 2741 2855 2742 2742 2856 2717 2717 2830 2742 2742 2856 2718 2718 2831 2718 2718 2831 2742 2742 2856 2743 2743 2857 2718 2718 2831 2743 2743 2857 2719 2719 2832 2719 2719 2832 2743 2743 2857 2744 2744 2858 2719 2719 2832 2744 2744 2858 2720 2720 2833 2720 2720 2833 2744 2744 2858 2745 2745 2859 2720 2720 2833 2745 2745 2859 2721 2721 2834 2721 2721 2834 2745 2745 2859 2746 2746 2860 2721 2721 2834 2746 2746 2860 2722 2722 2835 2722 2722 2835 2746 2746 2860 2747 2747 2861 2722 2722 2835 2747 2747 2861 2723 2723 2836 2723 2723 2836 2747 2747 2861 2748 2748 2862 2723 2723 2836 2748 2748 2862 2724 2724 2837 2724 2724 2837 2748 2748 2862 2749 2749 2863 2724 2724 2837 2749 2749 2863 2725 2725 2838 2725 2725 2838 2749 2749 2863 2750 2750 2864 2725 2725 2838 2750 2750 2864 2726 2726 2839 2726 2726 2839 2750 2750 2864 2751 2751 2865 2726 2726 2839 2751 2751 2865 2727 2727 2840 2727 2727 2840 2751 2751 2865 2752 2752 2866 2727 2727 2840 2752 2752 2866 2728 2728 2841 2728 2728 2841 2752 2752 2866 2753 2753 2867 2728 2728 2841 2753 2753 2867 2729 2729 2842 2729 2729 2842 2753 2753 2867 2754 2754 2868 2729 2729 2842 2754 2754 2868 2730 2730 2843 2730 2730 2843 2754 2754 2868 2755 2755 2869 2730 2730 2843 2755 2755 2869 2731 2731 2844 2731 2731 2844 2755 2755 2869 2756 2756 2870 2731 2731 2844 2756 2756 2870 2732 2732 2845 2732 2732 2845 2756 2756 2870 2757 2757 2871 2732 2732 2845 2757 2757 2871 2733 2733 2846 2733 2733 2846 2757 2757 2871 2758 2758 2872 2733 2733 2846 2758 2758 2872 2734 2734 2847 2734 2734 2847 2758 2758 2872 2759 2759 2873 2734 2734 2847 2759 2759 2873 2735 2735 2848 2735 2735 2848 2759 2759 2873 2736 2736 2874 2735 2735 2848 2736 2736 2874 2712 2712 2849 2736 2736 2850 2760 2760 2875 2761 2761 2876 2736 2736 2850 2761 2761 2876 2737 2737 2851 2737 2737 2851 2761 2761 2876 2762 2762 2877 2737 2737 2851 2762 2762 2877 2738 2738 2852 2738 2738 2852 2762 2762 2877 2763 2763 2878 2738 2738 2852 2763 2763 2878 2739 2739 2853 2739 2739 2853 2763 2763 2878 2764 2764 2879 2739 2739 2853 2764 2764 2879 2740 2740 2854 2740 2740 2854 2764 2764 2879 2765 2765 2880 2740 2740 2854 2765 2765 2880 2741 2741 2855 2741 2741 2855 2765 2765 2880 2766 2766 2881 2741 2741 2855 2766 2766 2881 2742 2742 2856 2742 2742 2856 2766 2766 2881 2767 2767 2882 2742 2742 2856 2767 2767 2882 2743 2743 2857 2743 2743 2857 2767 2767 2882 2768 2768 2883 2743 2743 2857 2768 2768 2883 2744 2744 2858 2744 2744 2858 2768 2768 2883 2769 2769 2884 2744 2744 2858 2769 2769 2884 2745 2745 2859 2745 2745 2859 2769 2769 2884 2770 2770 2885 2745 2745 2859 2770 2770 2885 2746 2746 2860 2746 2746 2860 2770 2770 2885 2771 2771 2886 2746 2746 2860 2771 2771 2886 2747 2747 2861 2747 2747 2861 2771 2771 2886 2772 2772 2887 2747 2747 2861 2772 2772 2887 2748 2748 2862 2748 2748 2862 2772 2772 2887 2773 2773 2888 2748 2748 2862 2773 2773 2888 2749 2749 2863 2749 2749 2863 2773 2773 2888 2774 2774 2889 2749 2749 2863 2774 2774 2889 2750 2750 2864 2750 2750 2864 2774 2774 2889 2775 2775 2890 2750 2750 2864 2775 2775 2890 2751 2751 2865 2751 2751 2865 2775 2775 2890 2776 2776 2891 2751 2751 2865 2776 2776 2891 2752 2752 2866 2752 2752 2866 2776 2776 2891 2777 2777 2892 2752 2752 2866 2777 2777 2892 2753 2753 2867 2753 2753 2867 2777 2777 2892 2778 2778 2893 2753 2753 2867 2778 2778 2893 2754 2754 2868 2754 2754 2868 2778 2778 2893 2779 2779 2894 2754 2754 2868 2779 2779 2894 2755 2755 2869 2755 2755 2869 2779 2779 2894 2780 2780 2895 2755 2755 2869 2780 2780 2895 2756 2756 2870 2756 2756 2870 2780 2780 2895 2781 2781 2896 2756 2756 2870 2781 2781 2896 2757 2757 2871 2757 2757 2871 2781 2781 2896 2782 2782 2897 2757 2757 2871 2782 2782 2897 2758 2758 2872 2758 2758 2872 2782 2782 2897 2783 2783 2898 2758 2758 2872 2783 2783 2898 2759 2759 2873 2759 2759 2873 2783 2783 2898 2760 2760 2899 2759 2759 2873 2760 2760 2899 2736 2736 2874 2760 2760 2875 2784 2784 2900 2785 2785 2901 2760 2760 2875 2785 2785 2901 2761 2761 2876 2761 2761 2876 2785 2785 2901 2786 2786 2902 2761 2761 2876 2786 2786 2902 2762 2762 2877 2762 2762 2877 2786 2786 2902 2787 2787 2903 2762 2762 2877 2787 2787 2903 2763 2763 2878 2763 2763 2878 2787 2787 2903 2788 2788 2904 2763 2763 2878 2788 2788 2904 2764 2764 2879 2764 2764 2879 2788 2788 2904 2789 2789 2905 2764 2764 2879 2789 2789 2905 2765 2765 2880 2765 2765 2880 2789 2789 2905 2790 2790 2906 2765 2765 2880 2790 2790 2906 2766 2766 2881 2766 2766 2881 2790 2790 2906 2791 2791 2907 2766 2766 2881 2791 2791 2907 2767 2767 2882 2767 2767 2882 2791 2791 2907 2792 2792 2908 2767 2767 2882 2792 2792 2908 2768 2768 2883 2768 2768 2883 2792 2792 2908 2793 2793 2909 2768 2768 2883 2793 2793 2909 2769 2769 2884 2769 2769 2884 2793 2793 2909 2794 2794 2910 2769 2769 2884 2794 2794 2910 2770 2770 2885 2770 2770 2885 2794 2794 2910 2795 2795 2911 2770 2770 2885 2795 2795 2911 2771 2771 2886 2771 2771 2886 2795 2795 2911 2796 2796 2912 2771 2771 2886 2796 2796 2912 2772 2772 2887 2772 2772 2887 2796 2796 2912 2797 2797 2913 2772 2772 2887 2797 2797 2913 2773 2773 2888 2773 2773 2888 2797 2797 2913 2798 2798 2914 2773 2773 2888 2798 2798 2914 2774 2774 2889 2774 2774 2889 2798 2798 2914 2799 2799 2915 2774 2774 2889 2799 2799 2915 2775 2775 2890 2775 2775 2890 2799 2799 2915 2800 2800 2916 2775 2775 2890 2800 2800 2916 2776 2776 2891 2776 2776 2891 2800 2800 2916 2801 2801 2917 2776 2776 2891 2801 2801 2917 2777 2777 2892 2777 2777 2892 2801 2801 2917 2802 2802 2918 2777 2777 2892 2802 2802 2918 2778 2778 2893 2778 2778 2893 2802 2802 2918 2803 2803 2919 2778 2778 2893 2803 2803 2919 2779 2779 2894 2779 2779 2894 2803 2803 2919 2804 2804 2920 2779 2779 2894 2804 2804 2920 2780 2780 2895 2780 2780 2895 2804 2804 2920 2805 2805 2921 2780 2780 2895 2805 2805 2921 2781 2781 2896 2781 2781 2896 2805 2805 2921 2806 2806 2922 2781 2781 2896 2806 2806 2922 2782 2782 2897 2782 2782 2897 2806 2806 2922 2807 2807 2923 2782 2782 2897 2807 2807 2923 2783 2783 2898 2783 2783 2898 2807 2807 2923 2784 2784 2924 2783 2783 2898 2784 2784 2924 2760 2760 2899 2784 2784 2900 2808 2808 2925 2809 2809 2926 2784 2784 2900 2809 2809 2926 2785 2785 2901 2785 2785 2901 2809 2809 2926 2810 2810 2927 2785 2785 2901 2810 2810 2927 2786 2786 2902 2786 2786 2902 2810 2810 2927 2811 2811 2928 2786 2786 2902 2811 2811 2928 2787 2787 2903 2787 2787 2903 2811 2811 2928 2812 2812 2929 2787 2787 2903 2812 2812 2929 2788 2788 2904 2788 2788 2904 2812 2812 2929 2813 2813 2930 2788 2788 2904 2813 2813 2930 2789 2789 2905 2789 2789 2905 2813 2813 2930 2814 2814 2931 2789 2789 2905 2814 2814 2931 2790 2790 2906 2790 2790 2906 2814 2814 2931 2815 2815 2932 2790 2790 2906 2815 2815 2932 2791 2791 2907 2791 2791 2907 2815 2815 2932 2816 2816 2933 2791 2791 2907 2816 2816 2933 2792 2792 2908 2792 2792 2908 2816 2816 2933 2817 2817 2934 2792 2792 2908 2817 2817 2934 2793 2793 2909 2793 2793 2909 2817 2817 2934 2818 2818 2935 2793 2793 2909 2818 2818 2935 2794 2794 2910 2794 2794 2910 2818 2818 2935 2819 2819 2936 2794 2794 2910 2819 2819 2936 2795 2795 2911 2795 2795 2911 2819 2819 2936 2820 2820 2937 2795 2795 2911 2820 2820 2937 2796 2796 2912 2796 2796 2912 2820 2820 2937 2821 2821 2938 2796 2796 2912 2821 2821 2938 2797 2797 2913 2797 2797 2913 2821 2821 2938 2822 2822 2939 2797 2797 2913 2822 2822 2939 2798 2798 2914 2798 2798 2914 2822 2822 2939 2823 2823 2940 2798 2798 2914 2823 2823 2940 2799 2799 2915 2799 2799 2915 2823 2823 2940 2824 2824 2941 2799 2799 2915 2824 2824 2941 2800 2800 2916 2800 2800 2916 2824 2824 2941 2825 2825 2942 2800 2800 2916 2825 2825 2942 2801 2801 2917 2801 2801 2917 2825 2825 2942 2826 2826 2943 2801 2801 2917 2826 2826 2943 2802 2802 2918 2802 2802 2918 2826 2826 2943 2827 2827 2944 2802 2802 2918 2827 2827 2944 2803 2803 2919 2803 2803 2919 2827 2827 2944 2828 2828 2945 2803 2803 2919 2828 2828 2945 2804 2804 2920 2804 2804 2920 2828 2828 2945 2829 2829 2946 2804 2804 2920 2829 2829 2946 2805 2805 2921 2805 2805 2921 2829 2829 2946 2830 2830 2947 2805 2805 2921 2830 2830 2947 2806 2806 2922 2806 2806 2922 2830 2830 2947 2831 2831 2948 2806 2806 2922 2831 2831 2948 2807 2807 2923 2807 2807 2923 2831 2831 2948 2808 2808 2949 2807 2807 2923 2808 2808 2949 2784 2784 2924 2808 2808 2925 2832 2832 2950 2833 2833 2951 2808 2808 2925 2833 2833 2951 2809 2809 2926 2809 2809 2926 2833 2833 2951 2834 2834 2952 2809 2809 2926 2834 2834 2952 2810 2810 2927 2810 2810 2927 2834 2834 2952 2835 2835 2953 2810 2810 2927 2835 2835 2953 2811 2811 2928 2811 2811 2928 2835 2835 2953 2836 2836 2954 2811 2811 2928 2836 2836 2954 2812 2812 2929 2812 2812 2929 2836 2836 2954 2837 2837 2955 2812 2812 2929 2837 2837 2955 2813 2813 2930 2813 2813 2930 2837 2837 2955 2838 2838 2956 2813 2813 2930 2838 2838 2956 2814 2814 2931 2814 2814 2931 2838 2838 2956 2839 2839 2957 2814 2814 2931 2839 2839 2957 2815 2815 2932 2815 2815 2932 2839 2839 2957 2840 2840 2958 2815 2815 2932 2840 2840 2958 2816 2816 2933 2816 2816 2933 2840 2840 2958 2841 2841 2959 2816 2816 2933 2841 2841 2959 2817 2817 2934 2817 2817 2934 2841 2841 2959 2842 2842 2960 2817 2817 2934 2842 2842 2960 2818 2818 2935 2818 2818 2935 2842 2842 2960 2843 2843 2961 2818 2818 2935 2843 2843 2961 2819 2819 2936 2819 2819 2936 2843 2843 2961 2844 2844 2962 2819 2819 2936 2844 2844 2962 2820 2820 2937 2820 2820 2937 2844 2844 2962 2845 2845 2963 2820 2820 2937 2845 2845 2963 2821 2821 2938 2821 2821 2938 2845 2845 2963 2846 2846 2964 2821 2821 2938 2846 2846 2964 2822 2822 2939 2822 2822 2939 2846 2846 2964 2847 2847 2965 2822 2822 2939 2847 2847 2965 2823 2823 2940 2823 2823 2940 2847 2847 2965 2848 2848 2966 2823 2823 2940 2848 2848 2966 2824 2824 2941 2824 2824 2941 2848 2848 2966 2849 2849 2967 2824 2824 2941 2849 2849 2967 2825 2825 2942 2825 2825 2942 2849 2849 2967 2850 2850 2968 2825 2825 2942 2850 2850 2968 2826 2826 2943 2826 2826 2943 2850 2850 2968 2851 2851 2969 2826 2826 2943 2851 2851 2969 2827 2827 2944 2827 2827 2944 2851 2851 2969 2852 2852 2970 2827 2827 2944 2852 2852 2970 2828 2828 2945 2828 2828 2945 2852 2852 2970 2853 2853 2971 2828 2828 2945 2853 2853 2971 2829 2829 2946 2829 2829 2946 2853 2853 2971 2854 2854 2972 2829 2829 2946 2854 2854 2972 2830 2830 2947 2830 2830 2947 2854 2854 2972 2855 2855 2973 2830 2830 2947 2855 2855 2973 2831 2831 2948 2831 2831 2948 2855 2855 2973 2832 2832 2974 2831 2831 2948 2832 2832 2974 2808 2808 2949 2832 2832 2950 2856 2856 2975 2857 2857 2976 2832 2832 2950 2857 2857 2976 2833 2833 2951 2833 2833 2951 2857 2857 2976 2858 2858 2977 2833 2833 2951 2858 2858 2977 2834 2834 2952 2834 2834 2952 2858 2858 2977 2859 2859 2978 2834 2834 2952 2859 2859 2978 2835 2835 2953 2835 2835 2953 2859 2859 2978 2860 2860 2979 2835 2835 2953 2860 2860 2979 2836 2836 2954 2836 2836 2954 2860 2860 2979 2861 2861 2980 2836 2836 2954 2861 2861 2980 2837 2837 2955 2837 2837 2955 2861 2861 2980 2862 2862 2981 2837 2837 2955 2862 2862 2981 2838 2838 2956 2838 2838 2956 2862 2862 2981 2863 2863 2982 2838 2838 2956 2863 2863 2982 2839 2839 2957 2839 2839 2957 2863 2863 2982 2864 2864 2983 2839 2839 2957 2864 2864 2983 2840 2840 2958 2840 2840 2958 2864 2864 2983 2865 2865 2984 2840 2840 2958 2865 2865 2984 2841 2841 2959 2841 2841 2959 2865 2865 2984 2866 2866 2985 2841 2841 2959 2866 2866 2985 2842 2842 2960 2842 2842 2960 2866 2866 2985 2867 2867 2986 2842 2842 2960 2867 2867 2986 2843 2843 2961 2843 2843 2961 2867 2867 2986 2868 2868 2987 2843 2843 2961 2868 2868 2987 2844 2844 2962 2844 2844 2962 2868 2868 2987 2869 2869 2988 2844 2844 2962 2869 2869 2988 2845 2845 2963 2845 2845 2963 2869 2869 2988 2870 2870 2989 2845 2845 2963 2870 2870 2989 2846 2846 2964 2846 2846 2964 2870 2870 2989 2871 2871 2990 2846 2846 2964 2871 2871 2990 2847 2847 2965 2847 2847 2965 2871 2871 2990 2872 2872 2991 2847 2847 2965 2872 2872 2991 2848 2848 2966 2848 2848 2966 2872 2872 2991 2873 2873 2992 2848 2848 2966 2873 2873 2992 2849 2849 2967 2849 2849 2967 2873 2873 2992 2874 2874 2993 2849 2849 2967 2874 2874 2993 2850 2850 2968 2850 2850 2968 2874 2874 2993 2875 2875 2994 2850 2850 2968 2875 2875 2994 2851 2851 2969 2851 2851 2969 2875 2875 2994 2876 2876 2995 2851 2851 2969 2876 2876 2995 2852 2852 2970 2852 2852 2970 2876 2876 2995 2877 2877 2996 2852 2852 2970 2877 2877 2996 2853 2853 2971 2853 2853 2971 2877 2877 2996 2878 2878 2997 2853 2853 2971 2878 2878 2997 2854 2854 2972 2854 2854 2972 2878 2878 2997 2879 2879 2998 2854 2854 2972 2879 2879 2998 2855 2855 2973 2855 2855 2973 2879 2879 2998 2856 2856 2999 2855 2855 2973 2856 2856 2999 2832 2832 2974 2856 2856 2975 0 0 3000 1 3 3001 2856 2856 2975 1 3 3001 2857 2857 2976 2857 2857 2976 1 3 3001 2 5 3002 2857 2857 2976 2 5 3002 2858 2858 2977 2858 2858 2977 2 5 3002 3 7 3003 2858 2858 2977 3 7 3003 2859 2859 2978 2859 2859 2978 3 7 3003 4 9 3004 2859 2859 2978 4 9 3004 2860 2860 2979 2860 2860 2979 4 9 3004 5 11 3005 2860 2860 2979 5 11 3005 2861 2861 2980 2861 2861 2980 5 11 3005 6 13 3006 2861 2861 2980 6 13 3006 2862 2862 2981 2862 2862 2981 6 13 3006 7 15 3007 2862 2862 2981 7 15 3007 2863 2863 2982 2863 2863 2982 7 15 3007 8 17 3008 2863 2863 2982 8 17 3008 2864 2864 2983 2864 2864 2983 8 17 3008 9 19 3009 2864 2864 2983 9 19 3009 2865 2865 2984 2865 2865 2984 9 19 3009 10 21 3010 2865 2865 2984 10 21 3010 2866 2866 2985 2866 2866 2985 10 21 3010 11 23 3011 2866 2866 2985 11 23 3011 2867 2867 2986 2867 2867 2986 11 23 3011 12 25 3012 2867 2867 2986 12 25 3012 2868 2868 2987 2868 2868 2987 12 25 3012 13 27 3013 2868 2868 2987 13 27 3013 2869 2869 2988 2869 2869 2988 13 27 3013 14 29 3014 2869 2869 2988 14 29 3014 2870 2870 2989 2870 2870 2989 14 29 3014 15 31 3015 2870 2870 2989 15 31 3015 2871 2871 2990 2871 2871 2990 15 31 3015 16 33 3016 2871 2871 2990 16 33 3016 2872 2872 2991 2872 2872 2991 16 33 3016 17 35 3017 2872 2872 2991 17 35 3017 2873 2873 2992 2873 2873 2992 17 35 3017 18 37 3018 2873 2873 2992 18 37 3018 2874 2874 2993 2874 2874 2993 18 37 3018 19 39 3019 2874 2874 2993 19 39 3019 2875 2875 2994 2875 2875 2994 19 39 3019 20 41 3020 2875 2875 2994 20 41 3020 2876 2876 2995 2876 2876 2995 20 41 3020 21 43 3021 2876 2876 2995 21 43 3021 2877 2877 2996 2877 2877 2996 21 43 3021 22 45 3022 2877 2877 2996 22 45 3022 2878 2878 2997 2878 2878 2997 22 45 3022 23 47 3023 2878 2878 2997 23 47 3023 2879 2879 2998 2879 2879 2998 23 47 3023 0 0 3024 2879 2879 2998 0 0 3024 2856 2856 2999</p>
+ </triangles>
+ </mesh>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="Torus_Knot-8_max" name="Torus_Knot-8_max">
+ <node id="Torus_Knot01-node" name="Torus_Knot01" type="NODE">
+ <translate>0 0 0</translate>
+ <rotate>-1.000000 0 0 -90.000000</rotate>
+ <instance_geometry url="#Torus_Knot01-mesh">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="Torus-Knot" target="#Torus-Knot"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="MAX3D">
+ <frame_rate>30</frame_rate>
+ </technique>
+ <technique profile="FCOLLADA">
+ <start_time>0</start_time>
+ <end_time>3.333333</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#Torus_Knot-8_max"/>
+ </scene>
+</COLLADA>
diff --git a/Studio/Content/Models Library/Primitives/Torus/Torus.dae b/Studio/Content/Models Library/Primitives/Torus/Torus.dae
new file mode 100644
index 00000000..880f8b1f
--- /dev/null
+++ b/Studio/Content/Models Library/Primitives/Torus/Torus.dae
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>jgiles</author>
+ <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ <comments>SSKK Patch3
+ColladaMaya export options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=1;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+ <source_data>file:///C:/Jason/RESOURCES/UI%20Composer%20RAW%20sample%20assets/models/primitives/torus/Torus.mb</source_data>
+ </contributor>
+ <created>2008-09-19T19:11:39Z</created>
+ <modified>2008-09-19T19:11:39Z</modified>
+ <unit meter="0.01" name="centimeter"/>
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_physics_scenes>
+ <physics_scene id="MayaNativePhysicsScene">
+ <technique_common>
+ <gravity>0 -980 0</gravity>
+ <time_step>0.083</time_step>
+ </technique_common>
+ </physics_scene>
+ </library_physics_scenes>
+ <library_materials>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx"/>
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <color>1 1 1 1</color>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ <extra>
+ <technique profile="FCOLLADA"/>
+ </extra>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_geometries>
+ <geometry id="Torus" name="Torus">
+ <mesh>
+ <source id="Torus-positions" name="position">
+ <float_array id="Torus-positions-array" count="3456">-25 0 0 -24.1481 -6.47048 0 -21.6506 -12.5 0 -17.6777 -17.6777 0 -12.5 -21.6506 0 -6.47048 -24.1481 0 0 -25 0 6.47047 -24.1481 0 12.5 -21.6506 0 17.6777 -17.6777 0 21.6506 -12.5 0 24.1481 -6.47047 0 25 0 0 24.1481 6.47048 0 21.6506 12.5 0 17.6777 17.6777 0 12.5 21.6506 0 6.47048 24.1481 0 0 25 0 -6.47048 24.1481 0 -12.5 21.6506 0 -17.6777 17.6777 0 -21.6506 12.5 0 -24.1481 6.47048 0 -28.3494 0 -12.5 -27.3834 -7.33736 -12.5 -24.5513 -14.1747 -12.5 -20.046 -20.046 -12.5 -14.1747 -24.5513 -12.5 -7.33736 -27.3834 -12.5 0 -28.3494 -12.5 7.33735 -27.3834 -12.5 14.1747 -24.5513 -12.5 20.046 -20.046 -12.5 24.5513 -14.1747 -12.5 27.3834 -7.33735 -12.5 28.3494 0 -12.5 27.3834 7.33736 -12.5 24.5513 14.1747 -12.5 20.046 20.046 -12.5 14.1747 24.5513 -12.5 7.33736 27.3834 -12.5 0 28.3494 -12.5 -7.33736 27.3834 -12.5 -14.1747 24.5513 -12.5 -20.046 20.046 -12.5 -24.5513 14.1747 -12.5 -27.3834 7.33736 -12.5 -37.5 0 -21.6506 -36.2222 -9.70572 -21.6506 -32.476 -18.75 -21.6506 -26.5165 -26.5165 -21.6506 -18.75 -32.476 -21.6506 -9.70572 -36.2222 -21.6506 0 -37.5 -21.6506 9.70571 -36.2222 -21.6506 18.75 -32.476 -21.6506 26.5165 -26.5165 -21.6506 32.476 -18.75 -21.6506 36.2222 -9.70571 -21.6506 37.5 0 -21.6506 36.2222 9.70572 -21.6506 32.476 18.75 -21.6506 26.5165 26.5165 -21.6506 18.75 32.476 -21.6506 9.70572 36.2222 -21.6506 0 37.5 -21.6506 -9.70572 36.2222 -21.6506 -18.75 32.476 -21.6506 -26.5165 26.5165 -21.6506 -32.476 18.75 -21.6506 -36.2222 9.70572 -21.6506 -50 0 -25 -48.2963 -12.941 -25 -43.3013 -25 -25 -35.3553 -35.3553 -25 -25 -43.3013 -25 -12.941 -48.2963 -25 0 -50 -25 12.9409 -48.2963 -25 25 -43.3013 -25 35.3553 -35.3553 -25 43.3013 -25 -25 48.2963 -12.9409 -25 50 0 -25 48.2963 12.941 -25 43.3013 25 -25 35.3553 35.3553 -25 25 43.3013 -25 12.941 48.2963 -25 0 50 -25 -12.941 48.2963 -25 -25 43.3013 -25 -35.3553 35.3553 -25 -43.3013 25 -25 -48.2963 12.941 -25 -62.5 0 -21.6506 -60.3704 -16.1762 -21.6506 -54.1266 -31.25 -21.6506 -44.1942 -44.1942 -21.6506 -31.25 -54.1266 -21.6506 -16.1762 -60.3704 -21.6506 0 -62.5 -21.6506 16.1762 -60.3704 -21.6506 31.25 -54.1266 -21.6506 44.1942 -44.1942 -21.6506 54.1266 -31.25 -21.6506 60.3704 -16.1762 -21.6506 62.5 0 -21.6506 60.3704 16.1762 -21.6506 54.1266 31.25 -21.6506 44.1942 44.1942 -21.6506 31.25 54.1266 -21.6506 16.1762 60.3704 -21.6506 0 62.5 -21.6506 -16.1762 60.3704 -21.6506 -31.25 54.1266 -21.6506 -44.1942 44.1942 -21.6506 -54.1266 31.25 -21.6506 -60.3704 16.1762 -21.6506 -71.6506 0 -12.5 -69.2092 -18.5445 -12.5 -62.0513 -35.8253 -12.5 -50.6646 -50.6646 -12.5 -35.8253 -62.0513 -12.5 -18.5445 -69.2092 -12.5 0 -71.6506 -12.5 18.5445 -69.2092 -12.5 35.8253 -62.0513 -12.5 50.6646 -50.6646 -12.5 62.0513 -35.8253 -12.5 69.2092 -18.5445 -12.5 71.6506 0 -12.5 69.2092 18.5446 -12.5 62.0513 35.8253 -12.5 50.6646 50.6646 -12.5 35.8253 62.0513 -12.5 18.5446 69.2092 -12.5 0 71.6506 -12.5 -18.5446 69.2092 -12.5 -35.8253 62.0513 -12.5 -50.6646 50.6646 -12.5 -62.0513 35.8253 -12.5 -69.2092 18.5446 -12.5 -75 0 0 -72.4444 -19.4114 0 -64.9519 -37.5 0 -53.033 -53.033 0 -37.5 -64.9519 0 -19.4114 -72.4444 0 0 -75 0 19.4114 -72.4444 0 37.5 -64.9519 0 53.033 -53.033 0 64.9519 -37.5 0 72.4444 -19.4114 0 75 0 0 72.4444 19.4114 0 64.9519 37.5 0 53.033 53.033 0 37.5 64.9519 0 19.4114 72.4444 0 0 75 0 -19.4114 72.4444 0 -37.5 64.9519 0 -53.033 53.033 0 -64.9519 37.5 0 -72.4444 19.4114 0 -71.6506 0 12.5 -69.2092 -18.5445 12.5 -62.0513 -35.8253 12.5 -50.6646 -50.6646 12.5 -35.8253 -62.0513 12.5 -18.5446 -69.2092 12.5 0 -71.6506 12.5 18.5445 -69.2092 12.5 35.8253 -62.0513 12.5 50.6646 -50.6646 12.5 62.0513 -35.8253 12.5 69.2092 -18.5445 12.5 71.6506 0 12.5 69.2092 18.5446 12.5 62.0513 35.8253 12.5 50.6646 50.6646 12.5 35.8253 62.0513 12.5 18.5446 69.2092 12.5 0 71.6506 12.5 -18.5446 69.2092 12.5 -35.8253 62.0513 12.5 -50.6646 50.6646 12.5 -62.0513 35.8253 12.5 -69.2092 18.5446 12.5 -62.5 0 21.6506 -60.3704 -16.1762 21.6506 -54.1266 -31.25 21.6506 -44.1942 -44.1942 21.6506 -31.25 -54.1266 21.6506 -16.1762 -60.3704 21.6506 0 -62.5 21.6506 16.1762 -60.3704 21.6506 31.25 -54.1266 21.6506 44.1942 -44.1942 21.6506 54.1266 -31.25 21.6506 60.3704 -16.1762 21.6506 62.5 0 21.6506 60.3704 16.1762 21.6506 54.1266 31.25 21.6506 44.1942 44.1942 21.6506 31.25 54.1266 21.6506 16.1762 60.3704 21.6506 0 62.5 21.6506 -16.1762 60.3704 21.6506 -31.25 54.1266 21.6506 -44.1942 44.1942 21.6506 -54.1266 31.25 21.6506 -60.3704 16.1762 21.6506 -50 0 25 -48.2963 -12.941 25 -43.3013 -25 25 -35.3553 -35.3553 25 -25 -43.3013 25 -12.941 -48.2963 25 0 -50 25 12.9409 -48.2963 25 25 -43.3013 25 35.3553 -35.3553 25 43.3013 -25 25 48.2963 -12.9409 25 50 0 25 48.2963 12.941 25 43.3013 25 25 35.3553 35.3553 25 25 43.3013 25 12.941 48.2963 25 0 50 25 -12.941 48.2963 25 -25 43.3013 25 -35.3553 35.3553 25 -43.3013 25 25 -48.2963 12.941 25 -37.5 0 21.6506 -36.2222 -9.70572 21.6506 -32.476 -18.75 21.6506 -26.5165 -26.5165 21.6506 -18.75 -32.476 21.6506 -9.70572 -36.2222 21.6506 0 -37.5 21.6506 9.70571 -36.2222 21.6506 18.75 -32.476 21.6506 26.5165 -26.5165 21.6506 32.476 -18.75 21.6506 36.2222 -9.70571 21.6506 37.5 0 21.6506 36.2222 9.70572 21.6506 32.476 18.75 21.6506 26.5165 26.5165 21.6506 18.75 32.476 21.6506 9.70572 36.2222 21.6506 0 37.5 21.6506 -9.70572 36.2222 21.6506 -18.75 32.476 21.6506 -26.5165 26.5165 21.6506 -32.476 18.75 21.6506 -36.2222 9.70572 21.6506 -28.3494 0 12.5 -27.3834 -7.33736 12.5 -24.5513 -14.1747 12.5 -20.046 -20.046 12.5 -14.1747 -24.5513 12.5 -7.33736 -27.3834 12.5 0 -28.3494 12.5 7.33735 -27.3834 12.5 14.1747 -24.5513 12.5 20.046 -20.046 12.5 24.5513 -14.1747 12.5 27.3834 -7.33735 12.5 28.3494 0 12.5 27.3834 7.33736 12.5 24.5513 14.1747 12.5 20.046 20.046 12.5 14.1747 24.5513 12.5 7.33736 27.3834 12.5 0 28.3494 12.5 -7.33736 27.3834 12.5 -14.1747 24.5513 12.5 -20.046 20.046 12.5 -24.5513 14.1747 12.5 -27.3834 7.33736 12.5 -24.7852 -3.26304 0 -24.9838 -6.6944 -6.46712 -28.0455 -3.69225 -12.3947 -25.8652 0 -6.46712 -25.6392 -3.37547 -6.41199 -23.0961 -9.56674 0 -22.3999 -12.9326 -6.46712 -26.1342 -10.8251 -12.3947 -23.892 -9.89638 -6.41199 -19.8331 -15.2185 0 -18.2894 -18.2894 -6.46712 -22.4419 -17.2203 -12.3947 -20.5165 -15.7429 -6.41199 -15.2185 -19.8331 0 -12.9326 -22.3999 -6.46712 -17.2203 -22.4419 -12.3947 -15.7429 -20.5165 -6.41199 -9.56674 -23.0961 0 -6.6944 -24.9838 -6.46712 -10.8251 -26.1342 -12.3947 -9.89638 -23.892 -6.41199 -3.26304 -24.7852 0 0 -25.8652 -6.46712 -3.69225 -28.0455 -12.3947 -3.37547 -25.6392 -6.41199 3.26303 -24.7852 0 6.6944 -24.9838 -6.46712 3.69225 -28.0455 -12.3947 3.37547 -25.6392 -6.41199 9.56674 -23.0961 0 12.9326 -22.3999 -6.46712 10.8251 -26.1342 -12.3947 9.89638 -23.892 -6.41199 15.2185 -19.8331 0 18.2894 -18.2894 -6.46712 17.2203 -22.4419 -12.3947 15.7429 -20.5165 -6.41199 19.8331 -15.2185 0 22.3999 -12.9326 -6.46712 22.4419 -17.2203 -12.3947 20.5165 -15.7429 -6.41199 23.0961 -9.56674 0 24.9838 -6.6944 -6.46712 26.1342 -10.8251 -12.3947 23.892 -9.89638 -6.41199 24.7852 -3.26303 0 25.8652 0 -6.46712 28.0455 -3.69225 -12.3947 25.6392 -3.37547 -6.41199 24.7852 3.26304 0 24.9838 6.6944 -6.46712 28.0455 3.69226 -12.3947 25.6392 3.37547 -6.41199 23.0961 9.56674 0 22.3999 12.9326 -6.46712 26.1342 10.8251 -12.3947 23.892 9.89638 -6.41199 19.8331 15.2185 0 18.2894 18.2894 -6.46712 22.4419 17.2203 -12.3947 20.5165 15.7429 -6.41199 15.2185 19.8331 0 12.9326 22.3999 -6.46712 17.2203 22.4419 -12.3947 15.7429 20.5165 -6.41199 9.56674 23.0961 0 6.6944 24.9838 -6.46712 10.8251 26.1342 -12.3947 9.89638 23.892 -6.41199 3.26304 24.7852 0 0 25.8652 -6.46712 3.69226 28.0455 -12.3947 3.37547 25.6392 -6.41199 -3.26304 24.7852 0 -6.6944 24.9838 -6.46712 -3.69226 28.0455 -12.3947 -3.37547 25.6392 -6.41199 -9.56674 23.0961 0 -12.9326 22.3999 -6.46712 -10.8251 26.1342 -12.3947 -9.89638 23.892 -6.41199 -15.2185 19.8331 0 -18.2894 18.2894 -6.46712 -17.2203 22.4419 -12.3947 -15.7429 20.5165 -6.41199 -19.8331 15.2185 0 -22.3999 12.9326 -6.46712 -22.4419 17.2203 -12.3947 -20.5165 15.7429 -6.41199 -23.0961 9.56674 0 -24.9838 6.6944 -6.46712 -26.1342 10.8251 -12.3947 -23.892 9.89638 -6.41199 -24.7852 3.26304 0 -28.0455 3.69226 -12.3947 -25.6392 3.37547 -6.41199 -31.2312 -8.36837 -17.6677 -36.9396 -4.8632 -21.5121 -32.3329 0 -17.6677 -31.9359 -4.20443 -17.5252 -28.0011 -16.1664 -17.6677 -34.4223 -14.2582 -21.5121 -29.7595 -12.3268 -17.5252 -22.8628 -22.8628 -17.6677 -29.5591 -22.6815 -21.5121 -25.555 -19.6091 -17.5252 -16.1664 -28.0011 -17.6677 -22.6815 -29.5591 -21.5121 -19.6091 -25.555 -17.5252 -8.36837 -31.2312 -17.6677 -14.2582 -34.4223 -21.5121 -12.3268 -29.7595 -17.5252 0 -32.3329 -17.6677 -4.8632 -36.9396 -21.5121 -4.20444 -31.9359 -17.5252 8.36836 -31.2312 -17.6677 4.86319 -36.9396 -21.5121 4.20443 -31.9359 -17.5252 16.1664 -28.0011 -17.6677 14.2582 -34.4223 -21.5121 12.3268 -29.7595 -17.5252 22.8628 -22.8628 -17.6677 22.6815 -29.5591 -21.5121 19.6091 -25.555 -17.5252 28.0011 -16.1664 -17.6677 29.5591 -22.6815 -21.5121 25.555 -19.6091 -17.5252 31.2312 -8.36836 -17.6677 34.4223 -14.2582 -21.5121 29.7595 -12.3268 -17.5252 32.3329 0 -17.6677 36.9396 -4.86319 -21.5121 31.9359 -4.20443 -17.5252 31.2312 8.36837 -17.6677 36.9396 4.8632 -21.5121 31.9359 4.20444 -17.5252 28.0011 16.1664 -17.6677 34.4223 14.2582 -21.5121 29.7595 12.3268 -17.5252 22.8628 22.8628 -17.6677 29.5591 22.6815 -21.5121 25.555 19.6091 -17.5252 16.1664 28.0011 -17.6677 22.6815 29.5591 -21.5121 19.6091 25.555 -17.5252 8.36837 31.2312 -17.6677 14.2582 34.4223 -21.5121 12.3268 29.7595 -17.5252 0 32.3329 -17.6677 4.8632 36.9396 -21.5121 4.20444 31.9359 -17.5252 -8.36837 31.2312 -17.6677 -4.8632 36.9396 -21.5121 -4.20444 31.9359 -17.5252 -16.1664 28.0011 -17.6677 -14.2582 34.4223 -21.5121 -12.3268 29.7595 -17.5252 -22.8628 22.8628 -17.6677 -22.6815 29.5591 -21.5121 -19.6091 25.555 -17.5252 -28.0011 16.1664 -17.6677 -29.5591 22.6815 -21.5121 -25.555 19.6091 -17.5252 -31.2312 8.36837 -17.6677 -34.4223 14.2582 -21.5121 -29.7595 12.3268 -17.5252 -36.9396 4.8632 -21.5121 -31.9359 4.20444 -17.5252 -42.0503 -11.2673 -24.1334 -49.1481 -6.47048 -25 -43.5337 0 -24.1334 -42.8364 -5.63952 -24.0212 -37.7013 -21.7668 -24.1334 -45.7988 -18.9705 -25 -39.9172 -16.5342 -24.0212 -30.783 -30.783 -24.1334 -39.3283 -30.1777 -25 -34.2777 -26.3022 -24.0212 -21.7668 -37.7013 -24.1334 -30.1777 -39.3283 -25 -26.3022 -34.2777 -24.0212 -11.2673 -42.0503 -24.1334 -18.9705 -45.7988 -25 -16.5342 -39.9172 -24.0212 0 -43.5337 -24.1334 -6.47048 -49.1481 -25 -5.63952 -42.8364 -24.0212 11.2673 -42.0503 -24.1334 6.47047 -49.1481 -25 5.63952 -42.8364 -24.0212 21.7668 -37.7013 -24.1334 18.9705 -45.7988 -25 16.5342 -39.9172 -24.0212 30.783 -30.783 -24.1334 30.1777 -39.3283 -25 26.3022 -34.2777 -24.0212 37.7013 -21.7668 -24.1334 39.3283 -30.1777 -25 34.2777 -26.3022 -24.0212 42.0503 -11.2673 -24.1334 45.7988 -18.9705 -25 39.9172 -16.5342 -24.0212 43.5337 0 -24.1334 49.1481 -6.47047 -25 42.8364 -5.63952 -24.0212 42.0503 11.2674 -24.1334 49.1481 6.47048 -25 42.8364 5.63952 -24.0212 37.7013 21.7668 -24.1334 45.7988 18.9705 -25 39.9172 16.5342 -24.0212 30.783 30.783 -24.1334 39.3283 30.1777 -25 34.2777 26.3022 -24.0212 21.7668 37.7013 -24.1334 30.1777 39.3283 -25 26.3022 34.2777 -24.0212 11.2674 42.0503 -24.1334 18.9705 45.7988 -25 16.5342 39.9172 -24.0212 0 43.5337 -24.1334 6.47048 49.1481 -25 5.63952 42.8364 -24.0212 -11.2674 42.0503 -24.1334 -6.47048 49.1481 -25 -5.63952 42.8364 -24.0212 -21.7668 37.7013 -24.1334 -18.9705 45.7988 -25 -16.5342 39.9172 -24.0212 -30.783 30.783 -24.1334 -30.1777 39.3283 -25 -26.3022 34.2777 -24.0212 -37.7013 21.7668 -24.1334 -39.3283 30.1777 -25 -34.2777 26.3022 -24.0212 -42.0503 11.2674 -24.1334 -45.7988 18.9705 -25 -39.9172 16.5342 -24.0212 -49.1481 6.47048 -25 -42.8364 5.63952 -24.0212 -54.5423 -14.6146 -24.1334 -61.5661 -8.10533 -21.8815 -56.4663 0 -24.1334 -55.5416 -7.3122 -24.2191 -48.9013 -28.2332 -24.1334 -57.3704 -23.7636 -21.8815 -51.7566 -21.4383 -24.2191 -39.9277 -39.9277 -24.1334 -49.2651 -37.8025 -21.8815 -44.4444 -34.1034 -24.2191 -28.2332 -48.9013 -24.1334 -37.8025 -49.2651 -21.8815 -34.1034 -44.4444 -24.2191 -14.6146 -54.5423 -24.1334 -23.7636 -57.3704 -21.8815 -21.4383 -51.7566 -24.2191 0 -56.4663 -24.1334 -8.10533 -61.5661 -21.8815 -7.3122 -55.5416 -24.2191 14.6146 -54.5423 -24.1334 8.10532 -61.5661 -21.8815 7.31219 -55.5416 -24.2191 28.2332 -48.9013 -24.1334 23.7636 -57.3704 -21.8815 21.4383 -51.7566 -24.2191 39.9277 -39.9277 -24.1334 37.8025 -49.2651 -21.8815 34.1034 -44.4444 -24.2191 48.9013 -28.2332 -24.1334 49.2651 -37.8025 -21.8815 44.4444 -34.1034 -24.2191 54.5423 -14.6146 -24.1334 57.3704 -23.7636 -21.8815 51.7566 -21.4383 -24.2191 56.4663 0 -24.1334 61.5661 -8.10532 -21.8815 55.5416 -7.31219 -24.2191 54.5423 14.6146 -24.1334 61.5661 8.10533 -21.8815 55.5416 7.3122 -24.2191 48.9013 28.2332 -24.1334 57.3704 23.7636 -21.8815 51.7566 21.4383 -24.2191 39.9277 39.9277 -24.1334 49.2651 37.8024 -21.8815 44.4444 34.1034 -24.2191 28.2332 48.9013 -24.1334 37.8024 49.2651 -21.8815 34.1034 44.4444 -24.2191 14.6146 54.5423 -24.1334 23.7636 57.3704 -21.8815 21.4383 51.7566 -24.2191 0 56.4663 -24.1334 8.10533 61.5661 -21.8815 7.3122 55.5416 -24.2191 -14.6146 54.5423 -24.1334 -8.10533 61.5661 -21.8815 -7.3122 55.5416 -24.2191 -28.2332 48.9013 -24.1334 -23.7636 57.3704 -21.8815 -21.4383 51.7566 -24.2191 -39.9277 39.9277 -24.1334 -37.8024 49.2651 -21.8815 -34.1034 44.4444 -24.2191 -48.9013 28.2332 -24.1334 -49.2651 37.8024 -21.8815 -44.4444 34.1034 -24.2191 -54.5423 14.6146 -24.1334 -57.3704 23.7636 -21.8815 -51.7566 21.4383 -24.2191 -61.5661 8.10533 -21.8815 -55.5416 7.3122 -24.2191 -65.3614 -17.5135 -17.6677 -70.8825 -9.33186 -12.7662 -67.6671 0 -17.6677 -66.7803 -8.7918 -17.924 -58.6014 -33.8336 -17.6677 -66.052 -27.3596 -12.7662 -62.2294 -25.7762 -17.924 -47.8479 -47.8479 -17.6677 -56.7201 -43.5229 -12.7662 -53.4376 -41.0041 -17.924 -33.8336 -58.6014 -17.6677 -43.5229 -56.7201 -12.7662 -41.0041 -53.4376 -17.924 -17.5135 -65.3614 -17.6677 -27.3596 -66.052 -12.7662 -25.7762 -62.2294 -17.924 0 -67.6671 -17.6677 -9.33186 -70.8825 -12.7662 -8.7918 -66.7803 -17.924 17.5135 -65.3614 -17.6677 9.33186 -70.8825 -12.7662 8.7918 -66.7803 -17.924 33.8336 -58.6014 -17.6677 27.3596 -66.052 -12.7662 25.7762 -62.2294 -17.924 47.8479 -47.8479 -17.6677 43.5229 -56.7201 -12.7662 41.0041 -53.4376 -17.924 58.6014 -33.8336 -17.6677 56.7201 -43.5229 -12.7662 53.4376 -41.0041 -17.924 65.3614 -17.5135 -17.6677 66.052 -27.3596 -12.7662 62.2294 -25.7762 -17.924 67.6671 0 -17.6677 70.8825 -9.33186 -12.7662 66.7803 -8.7918 -17.924 65.3614 17.5135 -17.6677 70.8825 9.33187 -12.7662 66.7803 8.7918 -17.924 58.6014 33.8335 -17.6677 66.052 27.3596 -12.7662 62.2294 25.7762 -17.924 47.8479 47.8479 -17.6677 56.7201 43.5229 -12.7662 53.4376 41.0041 -17.924 33.8335 58.6014 -17.6677 43.5229 56.7201 -12.7662 41.0041 53.4376 -17.924 17.5135 65.3614 -17.6677 27.3596 66.052 -12.7662 25.7762 62.2294 -17.924 0 67.6671 -17.6677 9.33187 70.8825 -12.7662 8.7918 66.7803 -17.924 -17.5135 65.3614 -17.6677 -9.33187 70.8825 -12.7662 -8.7918 66.7803 -17.924 -33.8335 58.6014 -17.6677 -27.3596 66.052 -12.7662 -25.7762 62.2294 -17.924 -47.8479 47.8479 -17.6677 -43.5229 56.7201 -12.7662 -41.0041 53.4376 -17.924 -58.6014 33.8335 -17.6677 -56.7201 43.5229 -12.7662 -53.4376 41.0041 -17.924 -65.3614 17.5135 -17.6677 -66.052 27.3596 -12.7662 -62.2294 25.7762 -17.924 -70.8825 9.33187 -12.7662 -66.7803 8.7918 -17.924 -71.6087 -19.1875 -6.46712 -74.3556 -9.78911 0 -74.1348 0 -6.46712 -73.4203 -9.66597 -6.61295 -64.2026 -37.0674 -6.46712 -69.2884 -28.7002 0 -68.4168 -28.3392 -6.61295 -52.4212 -52.4212 -6.46712 -59.4993 -45.6554 0 -58.7509 -45.0811 -6.61295 -37.0674 -64.2026 -6.46712 -45.6554 -59.4993 0 -45.0811 -58.7509 -6.61295 -19.1875 -71.6087 -6.46712 -28.7002 -69.2884 0 -28.3392 -68.4168 -6.61295 0 -74.1348 -6.46712 -9.78911 -74.3556 0 -9.66597 -73.4203 -6.61295 19.1875 -71.6087 -6.46712 9.7891 -74.3556 0 9.66596 -73.4203 -6.61295 37.0674 -64.2026 -6.46712 28.7002 -69.2884 0 28.3392 -68.4168 -6.61295 52.4212 -52.4212 -6.46712 45.6554 -59.4993 0 45.0811 -58.7509 -6.61295 64.2026 -37.0674 -6.46712 59.4993 -45.6554 0 58.7509 -45.0811 -6.61295 71.6087 -19.1875 -6.46712 69.2884 -28.7002 0 68.4168 -28.3392 -6.61295 74.1348 0 -6.46712 74.3556 -9.7891 0 73.4203 -9.66596 -6.61295 71.6087 19.1875 -6.46712 74.3556 9.78911 0 73.4203 9.66597 -6.61295 64.2026 37.0674 -6.46712 69.2884 28.7002 0 68.4168 28.3392 -6.61295 52.4212 52.4212 -6.46712 59.4993 45.6554 0 58.7509 45.0811 -6.61295 37.0674 64.2026 -6.46712 45.6554 59.4993 0 45.0811 58.7509 -6.61295 19.1875 71.6087 -6.46712 28.7002 69.2884 0 28.3392 68.4168 -6.61295 0 74.1348 -6.46712 9.78911 74.3556 0 9.66597 73.4203 -6.61295 -19.1875 71.6087 -6.46712 -9.78911 74.3556 0 -9.66597 73.4203 -6.61295 -37.0674 64.2026 -6.46712 -28.7002 69.2884 0 -28.3392 68.4168 -6.61295 -52.4212 52.4212 -6.46712 -45.6554 59.4993 0 -45.0811 58.7509 -6.61295 -64.2026 37.0674 -6.46712 -59.4993 45.6554 0 -58.7509 45.0811 -6.61295 -71.6087 19.1875 -6.46712 -69.2884 28.7002 0 -68.4168 28.3392 -6.61295 -74.3556 9.78911 0 -73.4203 9.66597 -6.61295 -71.6087 -19.1875 6.46712 -70.8825 -9.33186 12.7661 -74.1348 0 6.46712 -73.4203 -9.66597 6.61295 -64.2026 -37.0674 6.46712 -66.052 -27.3596 12.7661 -68.4168 -28.3392 6.61295 -52.4212 -52.4212 6.46712 -56.7201 -43.5229 12.7661 -58.7509 -45.0811 6.61295 -37.0674 -64.2026 6.46712 -43.5229 -56.7201 12.7661 -45.0811 -58.7509 6.61295 -19.1875 -71.6087 6.46712 -27.3596 -66.052 12.7661 -28.3392 -68.4168 6.61295 0 -74.1348 6.46712 -9.33186 -70.8825 12.7661 -9.66597 -73.4203 6.61295 19.1875 -71.6087 6.46712 9.33186 -70.8825 12.7661 9.66596 -73.4203 6.61295 37.0674 -64.2026 6.46712 27.3596 -66.052 12.7661 28.3392 -68.4168 6.61295 52.4212 -52.4212 6.46712 43.5229 -56.7201 12.7661 45.0811 -58.7509 6.61295 64.2026 -37.0674 6.46712 56.7201 -43.5229 12.7661 58.7509 -45.0811 6.61295 71.6087 -19.1875 6.46712 66.052 -27.3596 12.7661 68.4168 -28.3392 6.61295 74.1348 0 6.46712 70.8825 -9.33186 12.7661 73.4203 -9.66596 6.61295 71.6087 19.1875 6.46712 70.8825 9.33187 12.7661 73.4203 9.66597 6.61295 64.2026 37.0674 6.46712 66.052 27.3596 12.7661 68.4168 28.3392 6.61295 52.4212 52.4212 6.46712 56.7201 43.5229 12.7661 58.7509 45.0811 6.61295 37.0674 64.2026 6.46712 43.5229 56.7201 12.7661 45.0811 58.7509 6.61295 19.1875 71.6087 6.46712 27.3596 66.052 12.7661 28.3392 68.4168 6.61295 0 74.1348 6.46712 9.33187 70.8825 12.7661 9.66597 73.4203 6.61295 -19.1875 71.6087 6.46712 -9.33187 70.8825 12.7661 -9.66597 73.4203 6.61295 -37.0674 64.2026 6.46712 -27.3596 66.052 12.7661 -28.3392 68.4168 6.61295 -52.4212 52.4212 6.46712 -43.5229 56.7201 12.7661 -45.0811 58.7509 6.61295 -64.2026 37.0674 6.46712 -56.7201 43.5229 12.7661 -58.7509 45.0811 6.61295 -71.6087 19.1875 6.46712 -66.052 27.3596 12.7661 -68.4168 28.3392 6.61295 -70.8825 9.33187 12.7661 -73.4203 9.66597 6.61295 -65.3614 -17.5135 17.6677 -61.5661 -8.10533 21.8815 -67.6671 0 17.6677 -66.7803 -8.7918 17.924 -58.6014 -33.8336 17.6677 -57.3704 -23.7636 21.8815 -62.2294 -25.7762 17.924 -47.8479 -47.8479 17.6677 -49.2651 -37.8025 21.8815 -53.4376 -41.0041 17.924 -33.8336 -58.6014 17.6677 -37.8024 -49.2651 21.8815 -41.0041 -53.4376 17.924 -17.5135 -65.3614 17.6677 -23.7636 -57.3704 21.8815 -25.7762 -62.2294 17.924 0 -67.6671 17.6677 -8.10533 -61.5661 21.8815 -8.7918 -66.7803 17.924 17.5135 -65.3614 17.6677 8.10532 -61.5661 21.8815 8.7918 -66.7803 17.924 33.8336 -58.6014 17.6677 23.7636 -57.3704 21.8815 25.7762 -62.2294 17.924 47.8479 -47.8479 17.6677 37.8025 -49.2651 21.8815 41.0041 -53.4376 17.924 58.6014 -33.8336 17.6677 49.2651 -37.8025 21.8815 53.4376 -41.0041 17.924 65.3614 -17.5135 17.6677 57.3704 -23.7636 21.8815 62.2294 -25.7762 17.924 67.6671 0 17.6677 61.5661 -8.10532 21.8815 66.7803 -8.7918 17.924 65.3614 17.5135 17.6677 61.5661 8.10533 21.8815 66.7803 8.7918 17.924 58.6014 33.8335 17.6677 57.3704 23.7636 21.8815 62.2294 25.7762 17.924 47.8479 47.8479 17.6677 49.2651 37.8024 21.8815 53.4376 41.0041 17.924 33.8335 58.6014 17.6677 37.8024 49.2651 21.8815 41.0041 53.4376 17.924 17.5135 65.3614 17.6677 23.7636 57.3704 21.8815 25.7762 62.2294 17.924 0 67.6671 17.6677 8.10533 61.5661 21.8815 8.7918 66.7803 17.924 -17.5135 65.3614 17.6677 -8.10533 61.5661 21.8815 -8.7918 66.7803 17.924 -33.8335 58.6014 17.6677 -23.7636 57.3704 21.8815 -25.7762 62.2294 17.924 -47.8479 47.8479 17.6677 -37.8024 49.2651 21.8815 -41.0041 53.4376 17.924 -58.6014 33.8335 17.6677 -49.2651 37.8024 21.8815 -53.4376 41.0041 17.924 -65.3614 17.5135 17.6677 -57.3704 23.7636 21.8815 -62.2294 25.7762 17.924 -61.5661 8.10533 21.8815 -66.7803 8.7918 17.924 -54.5423 -14.6146 24.1334 -49.1481 -6.47048 25 -56.4663 0 24.1334 -55.5416 -7.3122 24.2191 -48.9013 -28.2332 24.1334 -45.7988 -18.9705 25 -51.7566 -21.4383 24.2191 -39.9277 -39.9277 24.1334 -39.3283 -30.1777 25 -44.4444 -34.1034 24.2191 -28.2332 -48.9013 24.1334 -30.1777 -39.3283 25 -34.1034 -44.4444 24.2191 -14.6146 -54.5423 24.1334 -18.9705 -45.7988 25 -21.4383 -51.7566 24.2191 0 -56.4663 24.1334 -6.47048 -49.1481 25 -7.3122 -55.5416 24.2191 14.6146 -54.5423 24.1334 6.47047 -49.1481 25 7.31219 -55.5416 24.2191 28.2332 -48.9013 24.1334 18.9705 -45.7988 25 21.4383 -51.7566 24.2191 39.9277 -39.9277 24.1334 30.1777 -39.3283 25 34.1034 -44.4444 24.2191 48.9013 -28.2332 24.1334 39.3283 -30.1777 25 44.4444 -34.1034 24.2191 54.5423 -14.6146 24.1334 45.7988 -18.9705 25 51.7566 -21.4383 24.2191 56.4663 0 24.1334 49.1481 -6.47047 25 55.5416 -7.31219 24.2191 54.5423 14.6146 24.1334 49.1481 6.47048 25 55.5416 7.3122 24.2191 48.9013 28.2332 24.1334 45.7988 18.9705 25 51.7566 21.4383 24.2191 39.9277 39.9277 24.1334 39.3283 30.1777 25 44.4444 34.1034 24.2191 28.2332 48.9013 24.1334 30.1777 39.3283 25 34.1034 44.4444 24.2191 14.6146 54.5423 24.1334 18.9705 45.7988 25 21.4383 51.7566 24.2191 0 56.4663 24.1334 6.47048 49.1481 25 7.3122 55.5416 24.2191 -14.6146 54.5423 24.1334 -6.47048 49.1481 25 -7.3122 55.5416 24.2191 -28.2332 48.9013 24.1334 -18.9705 45.7988 25 -21.4383 51.7566 24.2191 -39.9277 39.9277 24.1334 -30.1777 39.3283 25 -34.1034 44.4444 24.2191 -48.9013 28.2332 24.1334 -39.3283 30.1777 25 -44.4444 34.1034 24.2191 -54.5423 14.6146 24.1334 -45.7988 18.9705 25 -51.7566 21.4383 24.2191 -49.1481 6.47048 25 -55.5416 7.3122 24.2191 -42.0503 -11.2673 24.1334 -36.9396 -4.8632 21.5121 -43.5337 0 24.1334 -42.8364 -5.63952 24.0212 -37.7013 -21.7668 24.1334 -34.4223 -14.2582 21.5121 -39.9172 -16.5342 24.0212 -30.783 -30.783 24.1334 -29.5591 -22.6815 21.5121 -34.2777 -26.3022 24.0212 -21.7668 -37.7013 24.1334 -22.6815 -29.5591 21.5121 -26.3022 -34.2777 24.0212 -11.2673 -42.0503 24.1334 -14.2582 -34.4223 21.5121 -16.5342 -39.9172 24.0212 0 -43.5337 24.1334 -4.8632 -36.9396 21.5121 -5.63952 -42.8364 24.0212 11.2673 -42.0503 24.1334 4.86319 -36.9396 21.5121 5.63952 -42.8364 24.0212 21.7668 -37.7013 24.1334 14.2582 -34.4223 21.5121 16.5342 -39.9172 24.0212 30.783 -30.783 24.1334 22.6815 -29.5591 21.5121 26.3022 -34.2777 24.0212 37.7013 -21.7668 24.1334 29.5591 -22.6815 21.5121 34.2777 -26.3022 24.0212 42.0503 -11.2673 24.1334 34.4223 -14.2582 21.5121 39.9172 -16.5342 24.0212 43.5337 0 24.1334 36.9396 -4.86319 21.5121 42.8364 -5.63952 24.0212 42.0503 11.2674 24.1334 36.9396 4.8632 21.5121 42.8364 5.63952 24.0212 37.7013 21.7668 24.1334 34.4223 14.2582 21.5121 39.9172 16.5342 24.0212 30.783 30.783 24.1334 29.5591 22.6815 21.5121 34.2777 26.3022 24.0212 21.7668 37.7013 24.1334 22.6815 29.5591 21.5121 26.3022 34.2777 24.0212 11.2674 42.0503 24.1334 14.2582 34.4223 21.5121 16.5342 39.9172 24.0212 0 43.5337 24.1334 4.8632 36.9396 21.5121 5.63952 42.8364 24.0212 -11.2674 42.0503 24.1334 -4.8632 36.9396 21.5121 -5.63952 42.8364 24.0212 -21.7668 37.7013 24.1334 -14.2582 34.4223 21.5121 -16.5342 39.9172 24.0212 -30.783 30.783 24.1334 -22.6815 29.5591 21.5121 -26.3022 34.2777 24.0212 -37.7013 21.7668 24.1334 -29.5591 22.6815 21.5121 -34.2777 26.3022 24.0212 -42.0503 11.2674 24.1334 -34.4223 14.2582 21.5121 -39.9172 16.5342 24.0212 -36.9396 4.8632 21.5121 -42.8364 5.63952 24.0212 -31.2312 -8.36837 17.6677 -28.0455 -3.69225 12.3947 -32.3329 0 17.6677 -31.9359 -4.20443 17.5252 -28.0011 -16.1664 17.6677 -26.1342 -10.8251 12.3947 -29.7595 -12.3268 17.5252 -22.8628 -22.8628 17.6677 -22.4419 -17.2203 12.3947 -25.555 -19.6091 17.5252 -16.1664 -28.0011 17.6677 -17.2203 -22.4419 12.3947 -19.6091 -25.555 17.5252 -8.36837 -31.2312 17.6677 -10.8251 -26.1342 12.3947 -12.3268 -29.7595 17.5252 0 -32.3329 17.6677 -3.69225 -28.0455 12.3947 -4.20444 -31.9359 17.5252 8.36836 -31.2312 17.6677 3.69225 -28.0455 12.3947 4.20443 -31.9359 17.5252 16.1664 -28.0011 17.6677 10.8251 -26.1342 12.3947 12.3268 -29.7595 17.5252 22.8628 -22.8628 17.6677 17.2203 -22.4419 12.3947 19.6091 -25.555 17.5252 28.0011 -16.1664 17.6677 22.4419 -17.2203 12.3947 25.555 -19.6091 17.5252 31.2312 -8.36836 17.6677 26.1342 -10.8251 12.3947 29.7595 -12.3268 17.5252 32.3329 0 17.6677 28.0455 -3.69225 12.3947 31.9359 -4.20443 17.5252 31.2312 8.36837 17.6677 28.0455 3.69226 12.3947 31.9359 4.20444 17.5252 28.0011 16.1664 17.6677 26.1342 10.8251 12.3947 29.7595 12.3268 17.5252 22.8628 22.8628 17.6677 22.4419 17.2203 12.3947 25.555 19.6091 17.5252 16.1664 28.0011 17.6677 17.2203 22.4419 12.3947 19.6091 25.555 17.5252 8.36837 31.2312 17.6677 10.8251 26.1342 12.3947 12.3268 29.7595 17.5252 0 32.3329 17.6677 3.69226 28.0455 12.3947 4.20444 31.9359 17.5252 -8.36837 31.2312 17.6677 -3.69226 28.0455 12.3947 -4.20444 31.9359 17.5252 -16.1664 28.0011 17.6677 -10.8251 26.1342 12.3947 -12.3268 29.7595 17.5252 -22.8628 22.8628 17.6677 -17.2203 22.4419 12.3947 -19.6091 25.555 17.5252 -28.0011 16.1664 17.6677 -22.4419 17.2203 12.3947 -25.555 19.6091 17.5252 -31.2312 8.36837 17.6677 -26.1342 10.8251 12.3947 -29.7595 12.3268 17.5252 -28.0455 3.69226 12.3947 -31.9359 4.20444 17.5252 -24.9838 -6.6944 6.46712 -25.8652 0 6.46712 -25.6392 -3.37547 6.41199 -22.3999 -12.9326 6.46712 -23.892 -9.89638 6.41199 -18.2894 -18.2894 6.46712 -20.5165 -15.7429 6.41199 -12.9326 -22.3999 6.46712 -15.7429 -20.5165 6.41199 -6.6944 -24.9838 6.46712 -9.89638 -23.892 6.41199 0 -25.8652 6.46712 -3.37547 -25.6392 6.41199 6.6944 -24.9838 6.46712 3.37547 -25.6392 6.41199 12.9326 -22.3999 6.46712 9.89638 -23.892 6.41199 18.2894 -18.2894 6.46712 15.7429 -20.5165 6.41199 22.3999 -12.9326 6.46712 20.5165 -15.7429 6.41199 24.9838 -6.6944 6.46712 23.892 -9.89638 6.41199 25.8652 0 6.46712 25.6392 -3.37547 6.41199 24.9838 6.6944 6.46712 25.6392 3.37547 6.41199 22.3999 12.9326 6.46712 23.892 9.89638 6.41199 18.2894 18.2894 6.46712 20.5165 15.7429 6.41199 12.9326 22.3999 6.46712 15.7429 20.5165 6.41199 6.6944 24.9838 6.46712 9.89638 23.892 6.41199 0 25.8652 6.46712 3.37547 25.6392 6.41199 -6.6944 24.9838 6.46712 -3.37547 25.6392 6.41199 -12.9326 22.3999 6.46712 -9.89638 23.892 6.41199 -18.2894 18.2894 6.46712 -15.7429 20.5165 6.41199 -22.3999 12.9326 6.46712 -20.5165 15.7429 6.41199 -24.9838 6.6944 6.46712 -23.892 9.89638 6.41199 -25.6392 3.37547 6.41199</float_array>
+ <technique_common>
+ <accessor source="#Torus-positions-array" count="1152" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus-normals" name="normal">
+ <float_array id="Torus-normals-array" count="3456">1 0 0 0.965926 0.25882 0 0.866025 0.5 0 0.707107 0.707107 0 0.5 0.866025 0 0.258819 0.965926 0 0 1 0 -0.258819 0.965926 0 -0.5 0.866025 0 -0.707107 0.707107 0 -0.866025 0.5 0 -0.965926 0.25882 0 -1 0 0 -0.965926 -0.25882 0 -0.866025 -0.5 0 -0.707107 -0.707107 0 -0.5 -0.866025 0 -0.258819 -0.965926 0 0 -1 0 0.258819 -0.965926 0 0.5 -0.866025 0.000000 0.707107 -0.707107 0 0.866025 -0.5 0 0.965926 -0.25882 0 0.867101 0 -0.498132 0.837556 0.224422 -0.498132 0.750932 0.433551 -0.498132 0.613133 0.613133 -0.498132 0.433551 0.750932 -0.498132 0.224422 0.837556 -0.498132 0 0.867101 -0.498132 -0.224422 0.837556 -0.498132 -0.433551 0.750932 -0.498132 -0.613133 0.613133 -0.498132 -0.750932 0.433551 -0.498132 -0.837556 0.224422 -0.498132 -0.867101 0.000000 -0.498132 -0.837556 -0.224422 -0.498132 -0.750932 -0.433551 -0.498132 -0.613133 -0.613133 -0.498132 -0.433551 -0.750932 -0.498132 -0.224422 -0.837556 -0.498132 0 -0.867101 -0.498132 0.224422 -0.837556 -0.498132 0.433551 -0.750932 -0.498132 0.613133 -0.613133 -0.498132 0.750932 -0.433551 -0.498132 0.837556 -0.224422 -0.498132 0.504391 0 -0.863475 0.487205 0.130546 -0.863475 0.436815 0.252196 -0.863475 0.356659 0.356658 -0.863475 0.252196 0.436816 -0.863475 0.130546 0.487205 -0.863475 0 0.504391 -0.863475 -0.130546 0.487204 -0.863475 -0.252196 0.436815 -0.863475 -0.356658 0.356658 -0.863475 -0.436816 0.252196 -0.863475 -0.487204 0.130546 -0.863475 -0.504391 0 -0.863475 -0.487205 -0.130546 -0.863475 -0.436816 -0.252196 -0.863475 -0.356658 -0.356658 -0.863475 -0.252196 -0.436816 -0.863475 -0.130546 -0.487205 -0.863475 0 -0.504391 -0.863475 0.130546 -0.487204 -0.863475 0.252196 -0.436816 -0.863475 0.356658 -0.356658 -0.863475 0.436816 -0.252196 -0.863475 0.487205 -0.130546 -0.863475 0.008042 0 -0.999968 0.007768 0.002081 -0.999968 0.006965 0.004021 -0.999968 0.005687 0.005686 -0.999968 0.004021 0.006965 -0.999968 0.002081 0.007768 -0.999968 0 0.008042 -0.999968 -0.002081 0.007768 -0.999968 -0.004021 0.006965 -0.999968 -0.005686 0.005686 -0.999968 -0.006964 0.004021 -0.999968 -0.007768 0.002081 -0.999968 -0.008042 0 -0.999968 -0.007768 -0.002081 -0.999968 -0.006965 -0.004021 -0.999968 -0.005686 -0.005686 -0.999968 -0.004021 -0.006965 -0.999968 -0.002081 -0.007768 -0.999968 0 -0.008042 -0.999968 0.002081 -0.007768 -0.999968 0.004021 -0.006965 -0.999968 0.005686 -0.005686 -0.999968 0.006965 -0.004021 -0.999968 0.007768 -0.002081 -0.999968 -0.49227 0 -0.870443 -0.475496 -0.127409 -0.870443 -0.426318 -0.246135 -0.870443 -0.348087 -0.348088 -0.870443 -0.246135 -0.426318 -0.870443 -0.127409 -0.475496 -0.870443 0 -0.49227 -0.870443 0.127409 -0.475496 -0.870442 0.246135 -0.426318 -0.870443 0.348087 -0.348087 -0.870443 0.426318 -0.246135 -0.870442 0.475496 -0.127409 -0.870443 0.49227 0.000000 -0.870443 0.475496 0.127409 -0.870443 0.426318 0.246135 -0.870443 0.348088 0.348088 -0.870443 0.246135 0.426318 -0.870443 0.127409 0.475497 -0.870442 0 0.49227 -0.870443 -0.127409 0.475497 -0.870442 -0.246135 0.426319 -0.870443 -0.348088 0.348088 -0.870443 -0.426318 0.246135 -0.870442 -0.475496 0.127409 -0.870442 -0.863021 0.000000 -0.505168 -0.833614 -0.223366 -0.505168 -0.747398 -0.43151 -0.505168 -0.610248 -0.610248 -0.505168 -0.43151 -0.747398 -0.505168 -0.223366 -0.833614 -0.505168 0 -0.863021 -0.505168 0.223366 -0.833614 -0.505169 0.43151 -0.747398 -0.505168 0.610248 -0.610248 -0.505168 0.747398 -0.43151 -0.505168 0.833614 -0.223366 -0.505168 0.863021 0 -0.505168 0.833614 0.223366 -0.505168 0.747398 0.43151 -0.505168 0.610248 0.610248 -0.505168 0.43151 0.747398 -0.505168 0.223366 0.833614 -0.505168 0 0.863021 -0.505168 -0.223366 0.833614 -0.505168 -0.43151 0.747398 -0.505169 -0.610248 0.610248 -0.505168 -0.747398 0.43151 -0.505168 -0.833614 0.223367 -0.505168 -1 0 0 -0.965926 -0.258819 0 -0.866025 -0.5 0 -0.707107 -0.707107 0 -0.5 -0.866025 0 -0.258819 -0.965926 0.000000 0 -1 -0.000000 0.258819 -0.965926 0 0.5 -0.866025 0 0.707107 -0.707107 0 0.866025 -0.5 0 0.965926 -0.258819 0 1 0 0 0.965926 0.258819 -0.000000 0.866025 0.5 0 0.707107 0.707107 -0.000000 0.5 0.866025 0 0.258819 0.965926 -0.000000 0 1 0 -0.258819 0.965926 -0.000000 -0.5 0.866026 -0.000000 -0.707107 0.707107 -0.000000 -0.866025 0.5 -0.000000 -0.965926 0.258819 -0.000000 -0.863021 -0.000000 0.505168 -0.833614 -0.223366 0.505168 -0.747398 -0.43151 0.505168 -0.610248 -0.610248 0.505168 -0.43151 -0.747398 0.505169 -0.223366 -0.833614 0.505169 0 -0.863021 0.505168 0.223366 -0.833614 0.505168 0.43151 -0.747398 0.505168 0.610248 -0.610248 0.505168 0.747398 -0.431511 0.505168 0.833614 -0.223366 0.505168 0.863021 0 0.505168 0.833614 0.223366 0.505168 0.747398 0.43151 0.505168 0.610248 0.610248 0.505168 0.43151 0.747398 0.505168 0.223366 0.833614 0.505168 0 0.863021 0.505168 -0.223366 0.833614 0.505168 -0.43151 0.747398 0.505168 -0.610248 0.610248 0.505168 -0.747398 0.43151 0.505168 -0.833614 0.223366 0.505168 -0.49227 0 0.870443 -0.475496 -0.127409 0.870443 -0.426318 -0.246135 0.870443 -0.348087 -0.348087 0.870443 -0.246135 -0.426318 0.870443 -0.127409 -0.475496 0.870443 0 -0.49227 0.870443 0.127409 -0.475496 0.870442 0.246135 -0.426318 0.870443 0.348087 -0.348087 0.870443 0.426318 -0.246135 0.870442 0.475496 -0.127409 0.870443 0.49227 0 0.870443 0.475496 0.127409 0.870443 0.426318 0.246135 0.870443 0.348087 0.348087 0.870443 0.246135 0.426318 0.870443 0.127409 0.475496 0.870443 0 0.49227 0.870442 -0.127409 0.475496 0.870443 -0.246135 0.426318 0.870443 -0.348087 0.348087 0.870443 -0.426318 0.246135 0.870443 -0.475496 0.127409 0.870443 0.008042 0 0.999968 0.007768 0.002081 0.999968 0.006964 0.004021 0.999968 0.005686 0.005686 0.999968 0.004021 0.006965 0.999968 0.002081 0.007768 0.999968 0 0.008042 0.999968 -0.002081 0.007768 0.999968 -0.004021 0.006965 0.999968 -0.005686 0.005686 0.999968 -0.006964 0.004021 0.999968 -0.007768 0.002081 0.999968 -0.008042 0 0.999968 -0.007768 -0.002081 0.999968 -0.006965 -0.004021 0.999968 -0.005686 -0.005686 0.999968 -0.004021 -0.006965 0.999968 -0.002081 -0.007768 0.999968 0 -0.008042 0.999968 0.002081 -0.007768 0.999968 0.004021 -0.006965 0.999968 0.005686 -0.005686 0.999968 0.006965 -0.004021 0.999968 0.007768 -0.002081 0.999968 0.504391 -0.000000 0.863475 0.487204 0.130546 0.863475 0.436816 0.252196 0.863475 0.356658 0.356658 0.863475 0.252196 0.436815 0.863475 0.130546 0.487204 0.863475 0.000000 0.504391 0.863475 -0.130546 0.487205 0.863475 -0.252196 0.436816 0.863475 -0.356658 0.356658 0.863475 -0.436816 0.252196 0.863475 -0.487205 0.130546 0.863475 -0.504391 -0.000000 0.863475 -0.487204 -0.130546 0.863475 -0.436816 -0.252196 0.863475 -0.356658 -0.356658 0.863475 -0.252196 -0.436816 0.863475 -0.130546 -0.487204 0.863475 0 -0.504391 0.863475 0.130546 -0.487205 0.863475 0.252196 -0.436816 0.863475 0.356658 -0.356658 0.863475 0.436816 -0.252196 0.863475 0.487204 -0.130546 0.863475 0.867101 0.000000 0.498132 0.837556 0.224422 0.498132 0.750932 0.433551 0.498132 0.613133 0.613133 0.498132 0.433551 0.750932 0.498132 0.224422 0.837556 0.498132 0.000000 0.867101 0.498132 -0.224422 0.837556 0.498132 -0.433551 0.750932 0.498132 -0.613133 0.613133 0.498132 -0.750932 0.433551 0.498132 -0.837556 0.224422 0.498132 -0.867101 0 0.498132 -0.837556 -0.224422 0.498132 -0.750932 -0.433551 0.498132 -0.613133 -0.613133 0.498132 -0.433551 -0.750932 0.498132 -0.224422 -0.837556 0.498132 0 -0.867101 0.498132 0.224423 -0.837556 0.498132 0.433551 -0.750932 0.498132 0.613133 -0.613133 0.498132 0.750932 -0.433551 0.498132 0.837556 -0.224422 0.498132 0.991445 0.130526 0 0.933298 0.250077 -0.257713 0.859674 0.113178 -0.498148 0.966221 0 -0.257713 0.957955 0.126117 -0.257715 0.923879 0.382683 0 0.836772 0.483111 -0.257713 0.801089 0.331822 -0.498148 0.892672 0.369757 -0.257716 0.793353 0.608761 0 0.683222 0.683222 -0.257713 0.687911 0.527852 -0.498148 0.766554 0.588198 -0.257715 0.608762 0.793353 0 0.483111 0.836772 -0.257713 0.527852 0.687911 -0.498148 0.588198 0.766554 -0.257715 0.382683 0.92388 -0.000000 0.250076 0.933298 -0.257713 0.331822 0.801089 -0.498148 0.369757 0.892672 -0.257716 0.130526 0.991445 0 0 0.966222 -0.257713 0.113178 0.859674 -0.498148 0.126117 0.957955 -0.257715 -0.130526 0.991445 0 -0.250076 0.933298 -0.257713 -0.113178 0.859674 -0.498148 -0.126117 0.957955 -0.257715 -0.382683 0.92388 0 -0.483111 0.836772 -0.257713 -0.331822 0.801089 -0.498148 -0.369757 0.892672 -0.257715 -0.608761 0.793353 0 -0.683222 0.683222 -0.257713 -0.527852 0.687911 -0.498148 -0.588198 0.766554 -0.257715 -0.793353 0.608762 0 -0.836772 0.483111 -0.257713 -0.68791 0.527852 -0.498148 -0.766554 0.588198 -0.257715 -0.92388 0.382683 0 -0.933298 0.250077 -0.257713 -0.801089 0.331822 -0.498148 -0.892672 0.369756 -0.257716 -0.991445 0.130526 0 -0.966221 0 -0.257713 -0.859674 0.113178 -0.498148 -0.957955 0.126117 -0.257715 -0.991445 -0.130526 0 -0.933298 -0.250077 -0.257713 -0.859674 -0.113178 -0.498147 -0.957955 -0.126117 -0.257715 -0.923879 -0.382684 0 -0.836772 -0.483111 -0.257713 -0.801089 -0.331822 -0.498148 -0.892672 -0.369757 -0.257716 -0.793353 -0.608761 0 -0.683222 -0.683222 -0.257713 -0.687911 -0.527852 -0.498148 -0.766555 -0.588198 -0.257715 -0.608762 -0.793353 0 -0.483111 -0.836772 -0.257713 -0.527852 -0.687911 -0.498148 -0.588198 -0.766555 -0.257715 -0.382683 -0.923879 0 -0.250077 -0.933298 -0.257714 -0.331822 -0.801089 -0.498148 -0.369757 -0.892672 -0.257716 -0.130526 -0.991445 0 0 -0.966221 -0.257713 -0.113178 -0.859674 -0.498148 -0.126117 -0.957955 -0.257715 0.130526 -0.991445 0 0.250077 -0.933298 -0.257713 0.113178 -0.859674 -0.498148 0.126117 -0.957955 -0.257715 0.382684 -0.92388 0 0.483111 -0.836772 -0.257713 0.331822 -0.801089 -0.498148 0.369757 -0.892672 -0.257716 0.608762 -0.793353 0.000000 0.683222 -0.683222 -0.257713 0.527852 -0.687911 -0.498148 0.588198 -0.766555 -0.257715 0.793353 -0.608761 0 0.836772 -0.483111 -0.257713 0.687911 -0.527852 -0.498148 0.766555 -0.588198 -0.257715 0.923879 -0.382684 0 0.933298 -0.250077 -0.257713 0.801089 -0.331822 -0.498148 0.892672 -0.369757 -0.257716 0.991445 -0.130526 0 0.859674 -0.113178 -0.498147 0.957955 -0.126117 -0.257715 0.685646 0.183718 -0.70437 0.500028 0.065829 -0.863504 0.709833 0 -0.70437 0.703744 0.092649 -0.704386 0.614733 0.354916 -0.70437 0.465952 0.193004 -0.863504 0.655785 0.271635 -0.704387 0.501927 0.501927 -0.70437 0.400122 0.307024 -0.863504 0.563135 0.432109 -0.704387 0.354916 0.614733 -0.70437 0.307024 0.400122 -0.863504 0.432109 0.563135 -0.704387 0.183718 0.685646 -0.70437 0.193003 0.465952 -0.863504 0.271635 0.655785 -0.704386 0 0.709833 -0.70437 0.065829 0.500028 -0.863504 0.092649 0.703744 -0.704386 -0.183718 0.685646 -0.70437 -0.065829 0.500028 -0.863504 -0.092649 0.703744 -0.704386 -0.354916 0.614733 -0.70437 -0.193003 0.465952 -0.863504 -0.271635 0.655785 -0.704387 -0.501927 0.501927 -0.70437 -0.307024 0.400122 -0.863504 -0.432109 0.563135 -0.704387 -0.614733 0.354916 -0.70437 -0.400122 0.307024 -0.863504 -0.563135 0.432109 -0.704387 -0.685646 0.183718 -0.70437 -0.465952 0.193004 -0.863504 -0.655785 0.271635 -0.704387 -0.709833 0 -0.70437 -0.500028 0.065829 -0.863504 -0.703744 0.092649 -0.704386 -0.685646 -0.183718 -0.70437 -0.500028 -0.06583 -0.863504 -0.703744 -0.092649 -0.704386 -0.614733 -0.354916 -0.70437 -0.465952 -0.193003 -0.863504 -0.655785 -0.271635 -0.704386 -0.501927 -0.501927 -0.70437 -0.400122 -0.307024 -0.863504 -0.563136 -0.432109 -0.704386 -0.354917 -0.614733 -0.70437 -0.307024 -0.400122 -0.863504 -0.432109 -0.563135 -0.704386 -0.183718 -0.685646 -0.70437 -0.193004 -0.465952 -0.863504 -0.271635 -0.655785 -0.704386 0 -0.709833 -0.70437 -0.06583 -0.500028 -0.863504 -0.092649 -0.703744 -0.704386 0.183718 -0.685646 -0.70437 0.065829 -0.500028 -0.863504 0.092649 -0.703744 -0.704386 0.354916 -0.614733 -0.70437 0.193004 -0.465952 -0.863504 0.271635 -0.655785 -0.704386 0.501927 -0.501927 -0.70437 0.307024 -0.400122 -0.863504 0.432109 -0.563135 -0.704387 0.614733 -0.354916 -0.70437 0.400122 -0.307024 -0.863504 0.563135 -0.432109 -0.704386 0.685646 -0.183718 -0.70437 0.465952 -0.193003 -0.863504 0.655785 -0.271635 -0.704386 0.500028 -0.06583 -0.863504 0.703744 -0.092649 -0.704386 0.25655 0.068742 -0.964083 0.007834 0.001031 -0.999969 0.2656 0 -0.964083 0.263237 0.034655 -0.964109 0.230016 0.1328 -0.964083 0.0073 0.003023 -0.999969 0.245298 0.101606 -0.964108 0.187808 0.187807 -0.964083 0.006268 0.00481 -0.999969 0.210642 0.161632 -0.964108 0.1328 0.230016 -0.964083 0.00481 0.006268 -0.999969 0.161632 0.210642 -0.964108 0.068742 0.25655 -0.964083 0.003023 0.0073 -0.999969 0.101606 0.245298 -0.964108 0 0.2656 -0.964083 0.001031 0.007834 -0.999969 0.034655 0.263238 -0.964109 -0.068742 0.25655 -0.964083 -0.001031 0.007834 -0.999969 -0.034655 0.263237 -0.964108 -0.1328 0.230016 -0.964083 -0.003024 0.0073 -0.999969 -0.101606 0.245298 -0.964108 -0.187808 0.187807 -0.964083 -0.00481 0.006268 -0.999969 -0.161632 0.210642 -0.964108 -0.230016 0.1328 -0.964083 -0.006268 0.00481 -0.999969 -0.210643 0.161632 -0.964108 -0.25655 0.068742 -0.964083 -0.0073 0.003023 -0.999969 -0.245298 0.101606 -0.964109 -0.2656 0 -0.964083 -0.007834 0.001031 -0.999969 -0.263237 0.034655 -0.964108 -0.25655 -0.068742 -0.964083 -0.007833 -0.001031 -0.999969 -0.263237 -0.034656 -0.964108 -0.230016 -0.1328 -0.964083 -0.0073 -0.003023 -0.999969 -0.245298 -0.101606 -0.964108 -0.187807 -0.187807 -0.964083 -0.006268 -0.00481 -0.999969 -0.210642 -0.161632 -0.964108 -0.1328 -0.230016 -0.964083 -0.00481 -0.006268 -0.999969 -0.161631 -0.210642 -0.964109 -0.068742 -0.25655 -0.964083 -0.003023 -0.0073 -0.999969 -0.101606 -0.245298 -0.964108 0 -0.2656 -0.964083 -0.001031 -0.007834 -0.999969 -0.034655 -0.263237 -0.964108 0.068742 -0.25655 -0.964083 0.001031 -0.007834 -0.999969 0.034655 -0.263237 -0.964109 0.1328 -0.230016 -0.964083 0.003023 -0.0073 -0.999969 0.101606 -0.245298 -0.964109 0.187807 -0.187807 -0.964083 0.00481 -0.006268 -0.999969 0.161631 -0.210642 -0.964109 0.230016 -0.1328 -0.964083 0.006268 -0.00481 -0.999969 0.210642 -0.161632 -0.964109 0.256549 -0.068742 -0.964084 0.0073 -0.003023 -0.999969 0.245298 -0.101606 -0.964109 0.007834 -0.001031 -0.999969 0.263237 -0.034656 -0.964109 -0.241531 -0.064717 -0.968233 -0.488251 -0.064279 -0.870333 -0.250051 0 -0.968233 -0.248102 -0.032663 -0.968183 -0.216551 -0.125026 -0.968233 -0.454977 -0.188458 -0.870333 -0.231194 -0.095763 -0.968183 -0.176813 -0.176813 -0.968233 -0.390698 -0.299793 -0.870333 -0.198531 -0.152338 -0.968183 -0.125026 -0.216551 -0.968233 -0.299793 -0.390698 -0.870333 -0.152338 -0.198531 -0.968183 -0.064718 -0.241531 -0.968233 -0.188458 -0.454977 -0.870333 -0.095764 -0.231194 -0.968183 0 -0.250052 -0.968233 -0.064279 -0.488251 -0.870333 -0.032663 -0.248102 -0.968183 0.064718 -0.241531 -0.968233 0.064279 -0.488251 -0.870333 0.032663 -0.248102 -0.968183 0.125026 -0.216551 -0.968233 0.188458 -0.454978 -0.870333 0.095763 -0.231194 -0.968183 0.176813 -0.176813 -0.968233 0.299793 -0.390698 -0.870333 0.152338 -0.198531 -0.968183 0.216551 -0.125026 -0.968233 0.390698 -0.299793 -0.870333 0.198531 -0.152338 -0.968183 0.241531 -0.064718 -0.968233 0.454978 -0.188458 -0.870333 0.231195 -0.095763 -0.968183 0.250052 0 -0.968233 0.488251 -0.064279 -0.870333 0.248102 -0.032663 -0.968183 0.241531 0.064718 -0.968233 0.488251 0.064279 -0.870333 0.248103 0.032663 -0.968183 0.216551 0.125026 -0.968233 0.454978 0.188458 -0.870333 0.231195 0.095764 -0.968183 0.176813 0.176813 -0.968233 0.390698 0.299793 -0.870333 0.198531 0.152338 -0.968183 0.125026 0.216551 -0.968233 0.299793 0.390698 -0.870333 0.152338 0.198531 -0.968183 0.064718 0.241531 -0.968233 0.188458 0.454978 -0.870333 0.095764 0.231195 -0.968183 0 0.250051 -0.968233 0.064279 0.488251 -0.870333 0.032663 0.248102 -0.968183 -0.064718 0.241531 -0.968233 -0.064279 0.488251 -0.870333 -0.032663 0.248102 -0.968183 -0.125026 0.216551 -0.968233 -0.188458 0.454978 -0.870333 -0.095764 0.231195 -0.968183 -0.176813 0.176813 -0.968233 -0.299793 0.390698 -0.870333 -0.152338 0.198531 -0.968183 -0.216551 0.125026 -0.968233 -0.390698 0.299793 -0.870333 -0.198531 0.152338 -0.968183 -0.241531 0.064718 -0.968233 -0.454978 0.188458 -0.870333 -0.231195 0.095764 -0.968183 -0.488251 0.064279 -0.870333 -0.248102 0.032663 -0.968183 -0.677561 -0.181552 -0.712706 -0.855732 -0.112659 -0.505005 -0.701463 0.000000 -0.712706 -0.695629 -0.091581 -0.712539 -0.607485 -0.350732 -0.712706 -0.797416 -0.3303 -0.505005 -0.648224 -0.268503 -0.712539 -0.496009 -0.496009 -0.712706 -0.684756 -0.525432 -0.505005 -0.556642 -0.427126 -0.712539 -0.350732 -0.607485 -0.712706 -0.525432 -0.684756 -0.505005 -0.427126 -0.556642 -0.71254 -0.181552 -0.677562 -0.712706 -0.3303 -0.797415 -0.505005 -0.268503 -0.648224 -0.712539 0 -0.701463 -0.712706 -0.112659 -0.855732 -0.505005 -0.091581 -0.695629 -0.712539 0.181552 -0.677561 -0.712706 0.112659 -0.855732 -0.505005 0.091581 -0.695629 -0.71254 0.350731 -0.607485 -0.712706 0.3303 -0.797415 -0.505005 0.268503 -0.648223 -0.71254 0.496009 -0.496009 -0.712706 0.525432 -0.684756 -0.505005 0.427126 -0.556642 -0.71254 0.607485 -0.350731 -0.712706 0.684756 -0.525432 -0.505005 0.556642 -0.427126 -0.71254 0.677561 -0.181552 -0.712706 0.797416 -0.3303 -0.505005 0.648223 -0.268503 -0.712539 0.701463 0.000000 -0.712706 0.855732 -0.112659 -0.505005 0.695629 -0.091581 -0.712539 0.677561 0.181552 -0.712706 0.855732 0.112659 -0.505005 0.695629 0.091581 -0.71254 0.607485 0.350731 -0.712706 0.797415 0.3303 -0.505005 0.648223 0.268503 -0.71254 0.496009 0.496009 -0.712706 0.684756 0.525432 -0.505005 0.556642 0.427126 -0.71254 0.350731 0.607485 -0.712706 0.525432 0.684756 -0.505005 0.427126 0.556642 -0.71254 0.181552 0.677561 -0.712706 0.3303 0.797416 -0.505005 0.268503 0.648223 -0.71254 0 0.701463 -0.712706 0.112659 0.855732 -0.505005 0.091581 0.695629 -0.71254 -0.181552 0.677561 -0.712706 -0.112659 0.855732 -0.505005 -0.091581 0.695629 -0.71254 -0.350731 0.607485 -0.712706 -0.3303 0.797415 -0.505005 -0.268503 0.648223 -0.71254 -0.496009 0.496009 -0.712706 -0.525432 0.684756 -0.505005 -0.427126 0.556642 -0.712539 -0.607485 0.350731 -0.712706 -0.684756 0.525432 -0.505005 -0.556642 0.427126 -0.71254 -0.677561 0.181552 -0.712706 -0.797415 0.3303 -0.505005 -0.648223 0.268503 -0.71254 -0.855732 0.112659 -0.505005 -0.695629 0.091581 -0.71254 -0.93221 -0.249785 -0.261901 -0.991445 -0.130526 0 -0.965095 0 -0.261901 -0.956867 -0.125974 -0.261793 -0.835797 -0.482547 -0.261901 -0.923879 -0.382684 0 -0.891658 -0.369337 -0.261793 -0.682425 -0.682425 -0.261901 -0.793353 -0.608761 0 -0.765684 -0.58753 -0.261793 -0.482547 -0.835797 -0.261901 -0.608762 -0.793353 -0.000000 -0.58753 -0.765684 -0.261793 -0.249785 -0.93221 -0.261901 -0.382684 -0.923879 0.000000 -0.369337 -0.891658 -0.261793 0 -0.965095 -0.261901 -0.130526 -0.991445 0 -0.125974 -0.956867 -0.261793 0.249785 -0.93221 -0.261901 0.130526 -0.991445 0 0.125974 -0.956867 -0.261793 0.482547 -0.835797 -0.261901 0.382684 -0.92388 0 0.369337 -0.891658 -0.261793 0.682425 -0.682425 -0.2619 0.608761 -0.793353 0 0.58753 -0.765684 -0.261793 0.835797 -0.482547 -0.261901 0.793353 -0.608761 0 0.765684 -0.58753 -0.261793 0.93221 -0.249785 -0.261901 0.923879 -0.382684 0 0.891658 -0.369337 -0.261793 0.965095 0 -0.261901 0.991445 -0.130526 0 0.956867 -0.125974 -0.261793 0.93221 0.249785 -0.261901 0.991445 0.130526 0 0.956867 0.125974 -0.261793 0.835797 0.482547 -0.261901 0.92388 0.382683 -0.000000 0.891658 0.369337 -0.261793 0.682425 0.682425 -0.261901 0.793353 0.608761 -0.000000 0.765684 0.58753 -0.261793 0.482547 0.835797 -0.261901 0.608762 0.793353 -0.000000 0.58753 0.765684 -0.261793 0.249785 0.93221 -0.261901 0.382683 0.92388 -0.000000 0.369337 0.891658 -0.261793 0 0.965095 -0.261901 0.130526 0.991445 -0.000000 0.125974 0.956867 -0.261793 -0.249785 0.93221 -0.261901 -0.130526 0.991445 -0.000000 -0.125974 0.956867 -0.261793 -0.482547 0.835797 -0.261901 -0.382683 0.92388 -0.000000 -0.369337 0.891658 -0.261793 -0.682425 0.682425 -0.261901 -0.608762 0.793353 -0.000000 -0.58753 0.765684 -0.261793 -0.835797 0.482547 -0.261901 -0.793353 0.608762 -0.000000 -0.765684 0.58753 -0.261793 -0.93221 0.249785 -0.261901 -0.92388 0.382683 0 -0.891658 0.369337 -0.261793 -0.991445 0.130526 0 -0.956867 0.125974 -0.261793 -0.93221 -0.249785 0.261901 -0.855732 -0.11266 0.505005 -0.965095 0 0.261901 -0.956867 -0.125974 0.261793 -0.835797 -0.482547 0.261901 -0.797416 -0.3303 0.505005 -0.891658 -0.369337 0.261793 -0.682425 -0.682425 0.261901 -0.684756 -0.525432 0.505005 -0.765684 -0.58753 0.261793 -0.482547 -0.835797 0.261901 -0.525432 -0.684756 0.505005 -0.58753 -0.765684 0.261793 -0.249785 -0.93221 0.261901 -0.3303 -0.797415 0.505006 -0.369337 -0.891658 0.261794 0 -0.965095 0.261901 -0.112659 -0.855732 0.505005 -0.125974 -0.956867 0.261793 0.249785 -0.93221 0.261901 0.112659 -0.855732 0.505005 0.125974 -0.956867 0.261793 0.482547 -0.835797 0.261901 0.3303 -0.797415 0.505005 0.369337 -0.891658 0.261793 0.682425 -0.682425 0.261901 0.525432 -0.684756 0.505005 0.58753 -0.765684 0.261793 0.835797 -0.482547 0.261901 0.684756 -0.525432 0.505005 0.765684 -0.58753 0.261793 0.93221 -0.249785 0.261901 0.797416 -0.3303 0.505005 0.891658 -0.369337 0.261793 0.965095 0 0.261901 0.855732 -0.112659 0.505005 0.956867 -0.125974 0.261793 0.93221 0.249785 0.261901 0.855732 0.11266 0.505005 0.956867 0.125974 0.261793 0.835797 0.482547 0.261901 0.797416 0.3303 0.505005 0.891658 0.369337 0.261793 0.682425 0.682425 0.261901 0.684756 0.525432 0.505005 0.765684 0.58753 0.261793 0.482547 0.835797 0.261901 0.525432 0.684756 0.505005 0.58753 0.765684 0.261793 0.249785 0.93221 0.261901 0.3303 0.797415 0.505005 0.369337 0.891658 0.261793 0 0.965095 0.261901 0.112659 0.855732 0.505005 0.125974 0.956867 0.261793 -0.249785 0.93221 0.261901 -0.112659 0.855732 0.505005 -0.125974 0.956867 0.261793 -0.482547 0.835797 0.261901 -0.3303 0.797415 0.505005 -0.369337 0.891658 0.261793 -0.682425 0.682425 0.261901 -0.525432 0.684756 0.505005 -0.58753 0.765684 0.261793 -0.835797 0.482547 0.261901 -0.684756 0.525432 0.505005 -0.765684 0.58753 0.261793 -0.93221 0.249785 0.261901 -0.797416 0.3303 0.505005 -0.891658 0.369337 0.261793 -0.855732 0.112659 0.505005 -0.956867 0.125974 0.261793 -0.677562 -0.181552 0.712705 -0.488251 -0.064279 0.870333 -0.701463 -0.000000 0.712706 -0.69563 -0.091581 0.712539 -0.607485 -0.350732 0.712706 -0.454977 -0.188458 0.870333 -0.648224 -0.268503 0.712539 -0.496009 -0.496009 0.712706 -0.390698 -0.299793 0.870333 -0.556642 -0.427126 0.712539 -0.350731 -0.607485 0.712706 -0.299793 -0.390698 0.870333 -0.427126 -0.556642 0.712539 -0.181552 -0.677561 0.712706 -0.188458 -0.454978 0.870333 -0.268503 -0.648223 0.712539 0 -0.701463 0.712706 -0.064279 -0.488251 0.870333 -0.091581 -0.69563 0.712539 0.181552 -0.677561 0.712706 0.064279 -0.488251 0.870333 0.091581 -0.695629 0.712539 0.350732 -0.607485 0.712706 0.188458 -0.454978 0.870333 0.268503 -0.648223 0.712539 0.496009 -0.496009 0.712706 0.299793 -0.390698 0.870333 0.427127 -0.556642 0.712539 0.607485 -0.350732 0.712705 0.390698 -0.299793 0.870333 0.556642 -0.427127 0.712539 0.677561 -0.181552 0.712705 0.454978 -0.188458 0.870333 0.648224 -0.268503 0.712539 0.701463 -0.000000 0.712706 0.488251 -0.064279 0.870333 0.69563 -0.091581 0.712539 0.677562 0.181552 0.712705 0.488251 0.064279 0.870333 0.69563 0.091581 0.712539 0.607485 0.350731 0.712706 0.454977 0.188458 0.870333 0.648223 0.268503 0.712539 0.496009 0.496009 0.712706 0.390698 0.299793 0.870333 0.556642 0.427126 0.71254 0.350732 0.607485 0.712706 0.299793 0.390698 0.870333 0.427126 0.556642 0.712539 0.181552 0.677561 0.712706 0.188458 0.454978 0.870333 0.268503 0.648223 0.712539 0 0.701463 0.712705 0.064279 0.488251 0.870333 0.091581 0.695629 0.712539 -0.181552 0.677561 0.712706 -0.064279 0.488251 0.870333 -0.091581 0.695629 0.712539 -0.350732 0.607485 0.712706 -0.188458 0.454978 0.870333 -0.268503 0.648224 0.712539 -0.496009 0.496009 0.712706 -0.299793 0.390698 0.870333 -0.427126 0.556642 0.712539 -0.607485 0.350731 0.712706 -0.390698 0.299793 0.870333 -0.556642 0.427126 0.712539 -0.677562 0.181552 0.712706 -0.454977 0.188458 0.870333 -0.648223 0.268503 0.712539 -0.488251 0.064279 0.870333 -0.69563 0.091581 0.712539 -0.241531 -0.064718 0.968233 0.007834 0.001031 0.999969 -0.250051 0 0.968233 -0.248102 -0.032663 0.968183 -0.216551 -0.125026 0.968233 0.0073 0.003023 0.999969 -0.231194 -0.095763 0.968183 -0.176813 -0.176813 0.968233 0.006268 0.00481 0.999969 -0.198531 -0.152338 0.968183 -0.125026 -0.216551 0.968233 0.00481 0.006268 0.999969 -0.152338 -0.198531 0.968183 -0.064718 -0.241531 0.968233 0.003023 0.0073 0.999969 -0.095763 -0.231194 0.968183 0 -0.250051 0.968233 0.001031 0.007834 0.999969 -0.032663 -0.248102 0.968183 0.064718 -0.241531 0.968233 -0.001031 0.007834 0.999969 0.032663 -0.248102 0.968183 0.125026 -0.216551 0.968233 -0.003023 0.0073 0.999969 0.095763 -0.231194 0.968183 0.176813 -0.176813 0.968233 -0.00481 0.006268 0.999969 0.152338 -0.198531 0.968183 0.216551 -0.125026 0.968233 -0.006268 0.00481 0.999969 0.198531 -0.152338 0.968183 0.241531 -0.064718 0.968233 -0.0073 0.003023 0.999969 0.231195 -0.095763 0.968183 0.250051 0 0.968233 -0.007834 0.001031 0.999969 0.248102 -0.032663 0.968183 0.241531 0.064718 0.968233 -0.007834 -0.001031 0.999969 0.248102 0.032663 0.968183 0.216551 0.125026 0.968233 -0.0073 -0.003023 0.999969 0.231194 0.095763 0.968183 0.176813 0.176813 0.968233 -0.006268 -0.00481 0.999969 0.198531 0.152338 0.968183 0.125026 0.216551 0.968233 -0.00481 -0.006268 0.999969 0.152338 0.198531 0.968183 0.064718 0.241531 0.968233 -0.003023 -0.0073 0.999969 0.095764 0.231194 0.968183 0 0.250051 0.968233 -0.001031 -0.007834 0.999969 0.032663 0.248102 0.968183 -0.064718 0.241531 0.968233 0.001031 -0.007834 0.999969 -0.032663 0.248102 0.968183 -0.125026 0.216551 0.968233 0.003023 -0.0073 0.999969 -0.095764 0.231194 0.968183 -0.176813 0.176813 0.968233 0.00481 -0.006268 0.999969 -0.152338 0.198531 0.968183 -0.216551 0.125026 0.968233 0.006268 -0.00481 0.999969 -0.198531 0.152338 0.968183 -0.241531 0.064718 0.968233 0.0073 -0.003023 0.999969 -0.231194 0.095764 0.968183 0.007834 -0.001031 0.999969 -0.248102 0.032663 0.968183 0.25655 0.068742 0.964083 0.500028 0.06583 0.863504 0.2656 0 0.964083 0.263237 0.034655 0.964108 0.230016 0.1328 0.964083 0.465952 0.193004 0.863504 0.245298 0.101606 0.964108 0.187807 0.187807 0.964083 0.400122 0.307024 0.863504 0.210642 0.161632 0.964108 0.1328 0.230016 0.964083 0.307024 0.400122 0.863504 0.161632 0.210642 0.964109 0.068742 0.25655 0.964083 0.193003 0.465952 0.863504 0.101606 0.245298 0.964108 0 0.2656 0.964083 0.06583 0.500028 0.863504 0.034655 0.263238 0.964108 -0.068742 0.25655 0.964083 -0.06583 0.500028 0.863504 -0.034655 0.263238 0.964108 -0.1328 0.230016 0.964083 -0.193003 0.465952 0.863504 -0.101606 0.245298 0.964108 -0.187808 0.187807 0.964083 -0.307024 0.400122 0.863504 -0.161632 0.210642 0.964109 -0.230016 0.1328 0.964083 -0.400122 0.307024 0.863504 -0.210643 0.161632 0.964108 -0.25655 0.068742 0.964083 -0.465952 0.193004 0.863504 -0.245298 0.101606 0.964108 -0.2656 0 0.964083 -0.500028 0.06583 0.863504 -0.263238 0.034655 0.964108 -0.256549 -0.068742 0.964083 -0.500028 -0.06583 0.863504 -0.263237 -0.034655 0.964108 -0.230016 -0.1328 0.964083 -0.465951 -0.193004 0.863504 -0.245298 -0.101606 0.964108 -0.187807 -0.187807 0.964083 -0.400122 -0.307024 0.863504 -0.210642 -0.161632 0.964109 -0.1328 -0.230016 0.964083 -0.307024 -0.400122 0.863504 -0.161631 -0.210642 0.964108 -0.068742 -0.25655 0.964083 -0.193004 -0.465952 0.863504 -0.101606 -0.245298 0.964108 0 -0.2656 0.964083 -0.06583 -0.500028 0.863504 -0.034655 -0.263238 0.964108 0.068742 -0.25655 0.964083 0.065829 -0.500028 0.863504 0.034655 -0.263238 0.964108 0.1328 -0.230016 0.964083 0.193004 -0.465952 0.863504 0.101606 -0.245298 0.964108 0.187807 -0.187807 0.964083 0.307024 -0.400122 0.863504 0.161631 -0.210642 0.964109 0.230016 -0.1328 0.964083 0.400122 -0.307024 0.863504 0.210642 -0.161632 0.964109 0.25655 -0.068742 0.964083 0.465951 -0.193004 0.863504 0.245298 -0.101606 0.964109 0.500028 -0.06583 0.863504 0.263237 -0.034655 0.964108 0.685646 0.183718 0.70437 0.859674 0.113178 0.498148 0.709833 0 0.70437 0.703744 0.092649 0.704387 0.614733 0.354916 0.70437 0.801089 0.331822 0.498148 0.655785 0.271635 0.704386 0.501927 0.501927 0.70437 0.687911 0.527852 0.498148 0.563135 0.432109 0.704386 0.354916 0.614733 0.70437 0.527852 0.687911 0.498147 0.432109 0.563135 0.704387 0.183718 0.685646 0.70437 0.331822 0.801089 0.498148 0.271635 0.655785 0.704387 0.000000 0.709833 0.70437 0.113178 0.859674 0.498147 0.092649 0.703744 0.704387 -0.183718 0.685646 0.70437 -0.113178 0.859674 0.498148 -0.092649 0.703744 0.704387 -0.354917 0.614733 0.70437 -0.331822 0.801089 0.498147 -0.271635 0.655785 0.704386 -0.501927 0.501927 0.70437 -0.527852 0.687911 0.498147 -0.432109 0.563135 0.704387 -0.614733 0.354916 0.70437 -0.68791 0.527852 0.498148 -0.563135 0.432109 0.704387 -0.685646 0.183718 0.70437 -0.801089 0.331822 0.498148 -0.655785 0.271635 0.704387 -0.709833 -0.000000 0.70437 -0.859674 0.113178 0.498148 -0.703744 0.092649 0.704386 -0.685646 -0.183718 0.70437 -0.859674 -0.113178 0.498147 -0.703744 -0.092649 0.704386 -0.614733 -0.354916 0.70437 -0.801089 -0.331822 0.498148 -0.655785 -0.271635 0.704387 -0.501928 -0.501927 0.70437 -0.687911 -0.527852 0.498147 -0.563135 -0.432109 0.704386 -0.354916 -0.614733 0.70437 -0.527852 -0.687911 0.498147 -0.432109 -0.563135 0.704386 -0.183718 -0.685646 0.70437 -0.331822 -0.801089 0.498147 -0.271635 -0.655785 0.704386 0 -0.709833 0.70437 -0.113178 -0.859674 0.498148 -0.092649 -0.703744 0.704387 0.183718 -0.685646 0.70437 0.113178 -0.859674 0.498147 0.092649 -0.703744 0.704386 0.354916 -0.614733 0.70437 0.331822 -0.801089 0.498148 0.271635 -0.655785 0.704386 0.501928 -0.501927 0.70437 0.527852 -0.687911 0.498148 0.432109 -0.563135 0.704387 0.614733 -0.354916 0.70437 0.687911 -0.527852 0.498147 0.563136 -0.432109 0.704386 0.685646 -0.183718 0.70437 0.801089 -0.331822 0.498148 0.655785 -0.271635 0.704387 0.859674 -0.113178 0.498148 0.703744 -0.092649 0.704387 0.933298 0.250077 0.257713 0.966221 0 0.257713 0.957955 0.126117 0.257715 0.836772 0.483111 0.257713 0.892672 0.369757 0.257715 0.683222 0.683222 0.257713 0.766555 0.588198 0.257715 0.483111 0.836772 0.257713 0.588198 0.766554 0.257715 0.250077 0.933298 0.257713 0.369757 0.892672 0.257715 0 0.966222 0.257713 0.126117 0.957955 0.257715 -0.250076 0.933298 0.257713 -0.126117 0.957955 0.257715 -0.483111 0.836772 0.257713 -0.369757 0.892672 0.257715 -0.683222 0.683222 0.257713 -0.588198 0.766555 0.257715 -0.836772 0.483111 0.257713 -0.766555 0.588198 0.257715 -0.933298 0.250077 0.257713 -0.892672 0.369757 0.257715 -0.966221 0 0.257713 -0.957955 0.126117 0.257715 -0.933298 -0.250077 0.257713 -0.957955 -0.126117 0.257715 -0.836772 -0.483111 0.257713 -0.892672 -0.369757 0.257715 -0.683222 -0.683222 0.257713 -0.766555 -0.588198 0.257715 -0.483111 -0.836772 0.257713 -0.588198 -0.766555 0.257715 -0.250077 -0.933298 0.257713 -0.369757 -0.892672 0.257715 0 -0.966221 0.257713 -0.126117 -0.957955 0.257715 0.250077 -0.933298 0.257713 0.126117 -0.957955 0.257715 0.483111 -0.836772 0.257713 0.369757 -0.892672 0.257715 0.683222 -0.683222 0.257713 0.588198 -0.766555 0.257715 0.836772 -0.483111 0.257713 0.766555 -0.588198 0.257715 0.933298 -0.250077 0.257713 0.892672 -0.369757 0.257715 0.957955 -0.126117 0.257715</float_array>
+ <technique_common>
+ <accessor source="#Torus-normals-array" count="1152" stride="3">
+ <param name="X" type="float"/>
+ <param name="Y" type="float"/>
+ <param name="Z" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <source id="Torus-Texture" name="Texture">
+ <float_array id="Torus-Texture-array" count="2798">0 0 0.020833 0 0.020833 0.041666 0 0.041666 0.041666 0 0.041666 0.041666 0.041666 0.083333 0.020833 0.083333 0 0.083333 0.0625 0 0.0625 0.041666 0.083333 0 0.083333 0.041666 0.083333 0.083333 0.0625 0.083333 0.104167 0 0.104167 0.041666 0.125 0 0.125 0.041666 0.125 0.083333 0.104167 0.083333 0.145833 0 0.145833 0.041666 0.166667 0 0.166667 0.041666 0.166667 0.083333 0.145833 0.083333 0.1875 0 0.1875 0.041666 0.208333 0 0.208333 0.041666 0.208333 0.083333 0.1875 0.083333 0.229167 0 0.229167 0.041666 0.25 0 0.25 0.041666 0.25 0.083333 0.229167 0.083333 0.270833 0 0.270833 0.041666 0.291667 0 0.291667 0.041666 0.291667 0.083333 0.270833 0.083333 0.3125 0 0.3125 0.041666 0.333333 0 0.333333 0.041666 0.333333 0.083333 0.3125 0.083333 0.354167 0 0.354167 0.041666 0.375 0 0.375 0.041666 0.375 0.083333 0.354167 0.083333 0.395833 0 0.395833 0.041666 0.416667 0 0.416667 0.041666 0.416667 0.083333 0.395833 0.083333 0.4375 0 0.4375 0.041666 0.458333 0 0.458333 0.041666 0.458333 0.083333 0.4375 0.083333 0.479167 0 0.479167 0.041666 0.5 0 0.5 0.041666 0.5 0.083333 0.479167 0.083333 0.520833 0 0.520833 0.041666 0.541667 0 0.541667 0.041666 0.541667 0.083333 0.520833 0.083333 0.5625 0 0.5625 0.041666 0.583333 0 0.583333 0.041666 0.583333 0.083333 0.5625 0.083333 0.604167 0 0.604167 0.041666 0.625 0 0.625 0.041666 0.625 0.083333 0.604167 0.083333 0.645833 0 0.645833 0.041666 0.666667 0 0.666667 0.041666 0.666667 0.083333 0.645833 0.083333 0.6875 0 0.6875 0.041666 0.708333 0 0.708333 0.041666 0.708333 0.083333 0.6875 0.083333 0.729167 0 0.729167 0.041666 0.75 0 0.75 0.041666 0.75 0.083333 0.729167 0.083333 0.770833 0 0.770833 0.041666 0.791667 0 0.791667 0.041666 0.791667 0.083333 0.770833 0.083333 0.8125 0 0.8125 0.041666 0.833333 0 0.833333 0.041666 0.833333 0.083333 0.8125 0.083333 0.854167 0 0.854167 0.041666 0.875 0 0.875 0.041666 0.875 0.083333 0.854167 0.083333 0.895833 0 0.895833 0.041666 0.916667 0 0.916667 0.041666 0.916667 0.083333 0.895833 0.083333 0.9375 0 0.9375 0.041666 0.958333 0 0.958333 0.041666 0.958333 0.083333 0.9375 0.083333 0.979167 0 0.979167 0.041666 1 0 1 0.041666 0.979167 0 1 0.083333 0.979167 0.083333 1 0.041666 0.979167 0.083333 0.020833 0.125 0 0.125 0.041666 0.125 0.041666 0.166667 0.020833 0.166667 0 0.166667 0.0625 0.125 0.083333 0.125 0.083333 0.166667 0.0625 0.166667 0.104167 0.125 0.125 0.125 0.125 0.166667 0.104167 0.166667 0.145833 0.125 0.166667 0.125 0.166667 0.166667 0.145833 0.166667 0.1875 0.125 0.208333 0.125 0.208333 0.166667 0.1875 0.166667 0.229167 0.125 0.25 0.125 0.25 0.166667 0.229167 0.166667 0.270833 0.125 0.291667 0.125 0.291667 0.166667 0.270833 0.166667 0.3125 0.125 0.333333 0.125 0.333333 0.166667 0.3125 0.166667 0.354167 0.125 0.375 0.125 0.375 0.166667 0.354167 0.166667 0.395833 0.125 0.416667 0.125 0.416667 0.166667 0.395833 0.166667 0.4375 0.125 0.458333 0.125 0.458333 0.166667 0.4375 0.166667 0.479167 0.125 0.5 0.125 0.5 0.166667 0.479167 0.166667 0.520833 0.125 0.541667 0.125 0.541667 0.166667 0.520833 0.166667 0.5625 0.125 0.583333 0.125 0.583333 0.166667 0.5625 0.166667 0.604167 0.125 0.625 0.125 0.625 0.166667 0.604167 0.166667 0.645833 0.125 0.666667 0.125 0.666667 0.166667 0.645833 0.166667 0.6875 0.125 0.708333 0.125 0.708333 0.166667 0.6875 0.166667 0.729167 0.125 0.75 0.125 0.75 0.166667 0.729167 0.166667 0.770833 0.125 0.791667 0.125 0.791667 0.166667 0.770833 0.166667 0.8125 0.125 0.833333 0.125 0.833333 0.166667 0.8125 0.166667 0.854167 0.125 0.875 0.125 0.875 0.166667 0.854167 0.166667 0.895833 0.125 0.916667 0.125 0.916667 0.166667 0.895833 0.166667 0.9375 0.125 0.958333 0.125 0.958333 0.166667 0.9375 0.166667 0.979167 0.083333 0.979167 0.125 1 0.083333 1 0.125 0.979167 0.083333 1 0.166667 0.979167 0.166667 1 0.125 0.979167 0.166667 0.020833 0.208333 0 0.208333 0.041666 0.208333 0.041666 0.25 0.020833 0.25 0 0.25 0.0625 0.208333 0.083333 0.208333 0.083333 0.25 0.0625 0.25 0.104167 0.208333 0.125 0.208333 0.125 0.25 0.104167 0.25 0.145833 0.208333 0.166667 0.208333 0.166667 0.25 0.145833 0.25 0.1875 0.208333 0.208333 0.208333 0.208333 0.25 0.1875 0.25 0.229167 0.208333 0.25 0.208333 0.25 0.25 0.229167 0.25 0.270833 0.208333 0.291667 0.208333 0.291667 0.25 0.270833 0.25 0.3125 0.208333 0.333333 0.208333 0.333333 0.25 0.3125 0.25 0.354167 0.208333 0.375 0.208333 0.375 0.25 0.354167 0.25 0.395833 0.208333 0.416667 0.208333 0.416667 0.25 0.395833 0.25 0.4375 0.208333 0.458333 0.208333 0.458333 0.25 0.4375 0.25 0.479167 0.208333 0.5 0.208333 0.5 0.25 0.479167 0.25 0.520833 0.208333 0.541667 0.208333 0.541667 0.25 0.520833 0.25 0.5625 0.208333 0.583333 0.208333 0.583333 0.25 0.5625 0.25 0.604167 0.208333 0.625 0.208333 0.625 0.25 0.604167 0.25 0.645833 0.208333 0.666667 0.208333 0.666667 0.25 0.645833 0.25 0.6875 0.208333 0.708333 0.208333 0.708333 0.25 0.6875 0.25 0.729167 0.208333 0.75 0.208333 0.75 0.25 0.729167 0.25 0.770833 0.208333 0.791667 0.208333 0.791667 0.25 0.770833 0.25 0.8125 0.208333 0.833333 0.208333 0.833333 0.25 0.8125 0.25 0.854167 0.208333 0.875 0.208333 0.875 0.25 0.854167 0.25 0.895833 0.208333 0.916667 0.208333 0.916667 0.25 0.895833 0.25 0.9375 0.208333 0.958333 0.208333 0.958333 0.25 0.9375 0.25 0.979167 0.166667 0.979167 0.208333 1 0.166667 1 0.208333 0.979167 0.166667 1 0.25 0.979167 0.25 1 0.208333 0.979167 0.25 0.020833 0.291667 0 0.291667 0.041666 0.291667 0.041666 0.333333 0.020833 0.333333 0 0.333333 0.0625 0.291667 0.083333 0.291667 0.083333 0.333333 0.0625 0.333333 0.104167 0.291667 0.125 0.291667 0.125 0.333333 0.104167 0.333333 0.145833 0.291667 0.166667 0.291667 0.166667 0.333333 0.145833 0.333333 0.1875 0.291667 0.208333 0.291667 0.208333 0.333333 0.1875 0.333333 0.229167 0.291667 0.25 0.291667 0.25 0.333333 0.229167 0.333333 0.270833 0.291667 0.291667 0.291667 0.291667 0.333333 0.270833 0.333333 0.3125 0.291667 0.333333 0.291667 0.333333 0.333333 0.3125 0.333333 0.354167 0.291667 0.375 0.291667 0.375 0.333333 0.354167 0.333333 0.395833 0.291667 0.416667 0.291667 0.416667 0.333333 0.395833 0.333333 0.4375 0.291667 0.458333 0.291667 0.458333 0.333333 0.4375 0.333333 0.479167 0.291667 0.5 0.291667 0.5 0.333333 0.479167 0.333333 0.520833 0.291667 0.541667 0.291667 0.541667 0.333333 0.520833 0.333333 0.5625 0.291667 0.583333 0.291667 0.583333 0.333333 0.5625 0.333333 0.604167 0.291667 0.625 0.291667 0.625 0.333333 0.604167 0.333333 0.645833 0.291667 0.666667 0.291667 0.666667 0.333333 0.645833 0.333333 0.6875 0.291667 0.708333 0.291667 0.708333 0.333333 0.6875 0.333333 0.729167 0.291667 0.75 0.291667 0.75 0.333333 0.729167 0.333333 0.770833 0.291667 0.791667 0.291667 0.791667 0.333333 0.770833 0.333333 0.8125 0.291667 0.833333 0.291667 0.833333 0.333333 0.8125 0.333333 0.854167 0.291667 0.875 0.291667 0.875 0.333333 0.854167 0.333333 0.895833 0.291667 0.916667 0.291667 0.916667 0.333333 0.895833 0.333333 0.9375 0.291667 0.958333 0.291667 0.958333 0.333333 0.9375 0.333333 0.979167 0.25 0.979167 0.291667 1 0.25 1 0.291667 0.979167 0.25 1 0.333333 0.979167 0.333333 1 0.291667 0.979167 0.333333 0.020833 0.375 0 0.375 0.041666 0.375 0.041666 0.416667 0.020833 0.416667 0 0.416667 0.0625 0.375 0.083333 0.375 0.083333 0.416667 0.0625 0.416667 0.104167 0.375 0.125 0.375 0.125 0.416667 0.104167 0.416667 0.145833 0.375 0.166667 0.375 0.166667 0.416667 0.145833 0.416667 0.1875 0.375 0.208333 0.375 0.208333 0.416667 0.1875 0.416667 0.229167 0.375 0.25 0.375 0.25 0.416667 0.229167 0.416667 0.270833 0.375 0.291667 0.375 0.291667 0.416667 0.270833 0.416667 0.3125 0.375 0.333333 0.375 0.333333 0.416667 0.3125 0.416667 0.354167 0.375 0.375 0.375 0.375 0.416667 0.354167 0.416667 0.395833 0.375 0.416667 0.375 0.416667 0.416667 0.395833 0.416667 0.4375 0.375 0.458333 0.375 0.458333 0.416667 0.4375 0.416667 0.479167 0.375 0.5 0.375 0.5 0.416667 0.479167 0.416667 0.520833 0.375 0.541667 0.375 0.541667 0.416667 0.520833 0.416667 0.5625 0.375 0.583333 0.375 0.583333 0.416667 0.5625 0.416667 0.604167 0.375 0.625 0.375 0.625 0.416667 0.604167 0.416667 0.645833 0.375 0.666667 0.375 0.666667 0.416667 0.645833 0.416667 0.6875 0.375 0.708333 0.375 0.708333 0.416667 0.6875 0.416667 0.729167 0.375 0.75 0.375 0.75 0.416667 0.729167 0.416667 0.770833 0.375 0.791667 0.375 0.791667 0.416667 0.770833 0.416667 0.8125 0.375 0.833333 0.375 0.833333 0.416667 0.8125 0.416667 0.854167 0.375 0.875 0.375 0.875 0.416667 0.854167 0.416667 0.895833 0.375 0.916667 0.375 0.916667 0.416667 0.895833 0.416667 0.9375 0.375 0.958333 0.375 0.958333 0.416667 0.9375 0.416667 0.979167 0.333333 0.979167 0.375 1 0.333333 1 0.375 0.979167 0.333333 1 0.416667 0.979167 0.416667 1 0.375 0.979167 0.416667 0.020833 0.458333 0 0.458333 0.041666 0.458333 0.041666 0.5 0.020833 0.5 0 0.5 0.0625 0.458333 0.083333 0.458333 0.083333 0.5 0.0625 0.5 0.104167 0.458333 0.125 0.458333 0.125 0.5 0.104167 0.5 0.145833 0.458333 0.166667 0.458333 0.166667 0.5 0.145833 0.5 0.1875 0.458333 0.208333 0.458333 0.208333 0.5 0.1875 0.5 0.229167 0.458333 0.25 0.458333 0.25 0.5 0.229167 0.5 0.270833 0.458333 0.291667 0.458333 0.291667 0.5 0.270833 0.5 0.3125 0.458333 0.333333 0.458333 0.333333 0.5 0.3125 0.5 0.354167 0.458333 0.375 0.458333 0.375 0.5 0.354167 0.5 0.395833 0.458333 0.416667 0.458333 0.416667 0.5 0.395833 0.5 0.4375 0.458333 0.458333 0.458333 0.458333 0.5 0.4375 0.5 0.479167 0.458333 0.5 0.458333 0.5 0.5 0.479167 0.5 0.520833 0.458333 0.541667 0.458333 0.541667 0.5 0.520833 0.5 0.5625 0.458333 0.583333 0.458333 0.583333 0.5 0.5625 0.5 0.604167 0.458333 0.625 0.458333 0.625 0.5 0.604167 0.5 0.645833 0.458333 0.666667 0.458333 0.666667 0.5 0.645833 0.5 0.6875 0.458333 0.708333 0.458333 0.708333 0.5 0.6875 0.5 0.729167 0.458333 0.75 0.458333 0.75 0.5 0.729167 0.5 0.770833 0.458333 0.791667 0.458333 0.791667 0.5 0.770833 0.5 0.8125 0.458333 0.833333 0.458333 0.833333 0.5 0.8125 0.5 0.854167 0.458333 0.875 0.458333 0.875 0.5 0.854167 0.5 0.895833 0.458333 0.916667 0.458333 0.916667 0.5 0.895833 0.5 0.9375 0.458333 0.958333 0.458333 0.958333 0.5 0.9375 0.5 0.979167 0.416667 0.979167 0.458333 1 0.416667 1 0.458333 0.979167 0.416667 1 0.5 0.979167 0.5 1 0.458333 0.979167 0.5 0.020833 0.541667 0 0.541667 0.041666 0.541667 0.041666 0.583333 0.020833 0.583333 0 0.583333 0.0625 0.541667 0.083333 0.541667 0.083333 0.583333 0.0625 0.583333 0.104167 0.541667 0.125 0.541667 0.125 0.583333 0.104167 0.583333 0.145833 0.541667 0.166667 0.541667 0.166667 0.583333 0.145833 0.583333 0.1875 0.541667 0.208333 0.541667 0.208333 0.583333 0.1875 0.583333 0.229167 0.541667 0.25 0.541667 0.25 0.583333 0.229167 0.583333 0.270833 0.541667 0.291667 0.541667 0.291667 0.583333 0.270833 0.583333 0.3125 0.541667 0.333333 0.541667 0.333333 0.583333 0.3125 0.583333 0.354167 0.541667 0.375 0.541667 0.375 0.583333 0.354167 0.583333 0.395833 0.541667 0.416667 0.541667 0.416667 0.583333 0.395833 0.583333 0.4375 0.541667 0.458333 0.541667 0.458333 0.583333 0.4375 0.583333 0.479167 0.541667 0.5 0.541667 0.5 0.583333 0.479167 0.583333 0.520833 0.541667 0.541667 0.541667 0.541667 0.583333 0.520833 0.583333 0.5625 0.541667 0.583333 0.541667 0.583333 0.583333 0.5625 0.583333 0.604167 0.541667 0.625 0.541667 0.625 0.583333 0.604167 0.583333 0.645833 0.541667 0.666667 0.541667 0.666667 0.583333 0.645833 0.583333 0.6875 0.541667 0.708333 0.541667 0.708333 0.583333 0.6875 0.583333 0.729167 0.541667 0.75 0.541667 0.75 0.583333 0.729167 0.583333 0.770833 0.541667 0.791667 0.541667 0.791667 0.583333 0.770833 0.583333 0.8125 0.541667 0.833333 0.541667 0.833333 0.583333 0.8125 0.583333 0.854167 0.541667 0.875 0.541667 0.875 0.583333 0.854167 0.583333 0.895833 0.541667 0.916667 0.541667 0.916667 0.583333 0.895833 0.583333 0.9375 0.541667 0.958333 0.541667 0.958333 0.583333 0.9375 0.583333 0.979167 0.5 0.979167 0.541667 1 0.5 1 0.541667 0.979167 0.5 1 0.583333 0.979167 0.583333 1 0.541667 0.979167 0.583333 0.020833 0.625 0 0.625 0.041666 0.625 0.041666 0.666667 0.020833 0.666667 0 0.666667 0.0625 0.625 0.083333 0.625 0.083333 0.666667 0.0625 0.666667 0.104167 0.625 0.125 0.625 0.125 0.666667 0.104167 0.666667 0.145833 0.625 0.166667 0.625 0.166667 0.666667 0.145833 0.666667 0.1875 0.625 0.208333 0.625 0.208333 0.666667 0.1875 0.666667 0.229167 0.625 0.25 0.625 0.25 0.666667 0.229167 0.666667 0.270833 0.625 0.291667 0.625 0.291667 0.666667 0.270833 0.666667 0.3125 0.625 0.333333 0.625 0.333333 0.666667 0.3125 0.666667 0.354167 0.625 0.375 0.625 0.375 0.666667 0.354167 0.666667 0.395833 0.625 0.416667 0.625 0.416667 0.666667 0.395833 0.666667 0.4375 0.625 0.458333 0.625 0.458333 0.666667 0.4375 0.666667 0.479167 0.625 0.5 0.625 0.5 0.666667 0.479167 0.666667 0.520833 0.625 0.541667 0.625 0.541667 0.666667 0.520833 0.666667 0.5625 0.625 0.583333 0.625 0.583333 0.666667 0.5625 0.666667 0.604167 0.625 0.625 0.625 0.625 0.666667 0.604167 0.666667 0.645833 0.625 0.666667 0.625 0.666667 0.666667 0.645833 0.666667 0.6875 0.625 0.708333 0.625 0.708333 0.666667 0.6875 0.666667 0.729167 0.625 0.75 0.625 0.75 0.666667 0.729167 0.666667 0.770833 0.625 0.791667 0.625 0.791667 0.666667 0.770833 0.666667 0.8125 0.625 0.833333 0.625 0.833333 0.666667 0.8125 0.666667 0.854167 0.625 0.875 0.625 0.875 0.666667 0.854167 0.666667 0.895833 0.625 0.916667 0.625 0.916667 0.666667 0.895833 0.666667 0.9375 0.625 0.958333 0.625 0.958333 0.666667 0.9375 0.666667 0.979167 0.583333 0.979167 0.625 1 0.583333 1 0.625 0.979167 0.583333 1 0.666667 0.979167 0.666667 1 0.625 0.979167 0.666667 0.020833 0.708333 0 0.708333 0.041666 0.708333 0.041666 0.75 0.020833 0.75 0 0.75 0.0625 0.708333 0.083333 0.708333 0.083333 0.75 0.0625 0.75 0.104167 0.708333 0.125 0.708333 0.125 0.75 0.104167 0.75 0.145833 0.708333 0.166667 0.708333 0.166667 0.75 0.145833 0.75 0.1875 0.708333 0.208333 0.708333 0.208333 0.75 0.1875 0.75 0.229167 0.708333 0.25 0.708333 0.25 0.75 0.229167 0.75 0.270833 0.708333 0.291667 0.708333 0.291667 0.75 0.270833 0.75 0.3125 0.708333 0.333333 0.708333 0.333333 0.75 0.3125 0.75 0.354167 0.708333 0.375 0.708333 0.375 0.75 0.354167 0.75 0.395833 0.708333 0.416667 0.708333 0.416667 0.75 0.395833 0.75 0.4375 0.708333 0.458333 0.708333 0.458333 0.75 0.4375 0.75 0.479167 0.708333 0.5 0.708333 0.5 0.75 0.479167 0.75 0.520833 0.708333 0.541667 0.708333 0.541667 0.75 0.520833 0.75 0.5625 0.708333 0.583333 0.708333 0.583333 0.75 0.5625 0.75 0.604167 0.708333 0.625 0.708333 0.625 0.75 0.604167 0.75 0.645833 0.708333 0.666667 0.708333 0.666667 0.75 0.645833 0.75 0.6875 0.708333 0.708333 0.708333 0.708333 0.75 0.6875 0.75 0.729167 0.708333 0.75 0.708333 0.75 0.75 0.729167 0.75 0.770833 0.708333 0.791667 0.708333 0.791667 0.75 0.770833 0.75 0.8125 0.708333 0.833333 0.708333 0.833333 0.75 0.8125 0.75 0.854167 0.708333 0.875 0.708333 0.875 0.75 0.854167 0.75 0.895833 0.708333 0.916667 0.708333 0.916667 0.75 0.895833 0.75 0.9375 0.708333 0.958333 0.708333 0.958333 0.75 0.9375 0.75 0.979167 0.666667 0.979167 0.708333 1 0.666667 1 0.708333 0.979167 0.666667 1 0.75 0.979167 0.75 1 0.708333 0.979167 0.75 0.020833 0.791667 0 0.791667 0.041666 0.791667 0.041666 0.833333 0.020833 0.833333 0 0.833333 0.0625 0.791667 0.083333 0.791667 0.083333 0.833333 0.0625 0.833333 0.104167 0.791667 0.125 0.791667 0.125 0.833333 0.104167 0.833333 0.145833 0.791667 0.166667 0.791667 0.166667 0.833333 0.145833 0.833333 0.1875 0.791667 0.208333 0.791667 0.208333 0.833333 0.1875 0.833333 0.229167 0.791667 0.25 0.791667 0.25 0.833333 0.229167 0.833333 0.270833 0.791667 0.291667 0.791667 0.291667 0.833333 0.270833 0.833333 0.3125 0.791667 0.333333 0.791667 0.333333 0.833333 0.3125 0.833333 0.354167 0.791667 0.375 0.791667 0.375 0.833333 0.354167 0.833333 0.395833 0.791667 0.416667 0.791667 0.416667 0.833333 0.395833 0.833333 0.4375 0.791667 0.458333 0.791667 0.458333 0.833333 0.4375 0.833333 0.479167 0.791667 0.5 0.791667 0.5 0.833333 0.479167 0.833333 0.520833 0.791667 0.541667 0.791667 0.541667 0.833333 0.520833 0.833333 0.5625 0.791667 0.583333 0.791667 0.583333 0.833333 0.5625 0.833333 0.604167 0.791667 0.625 0.791667 0.625 0.833333 0.604167 0.833333 0.645833 0.791667 0.666667 0.791667 0.666667 0.833333 0.645833 0.833333 0.6875 0.791667 0.708333 0.791667 0.708333 0.833333 0.6875 0.833333 0.729167 0.791667 0.75 0.791667 0.75 0.833333 0.729167 0.833333 0.770833 0.791667 0.791667 0.791667 0.791667 0.833333 0.770833 0.833333 0.8125 0.791667 0.833333 0.791667 0.833333 0.833333 0.8125 0.833333 0.854167 0.791667 0.875 0.791667 0.875 0.833333 0.854167 0.833333 0.895833 0.791667 0.916667 0.791667 0.916667 0.833333 0.895833 0.833333 0.9375 0.791667 0.958333 0.791667 0.958333 0.833333 0.9375 0.833333 0.979167 0.75 0.979167 0.791667 1 0.75 1 0.791667 0.979167 0.75 1 0.833333 0.979167 0.833333 1 0.791667 0.979167 0.833333 0.020833 0.875 0 0.875 0.041666 0.875 0.041666 0.916667 0.020833 0.916667 0 0.916667 0.0625 0.875 0.083333 0.875 0.083333 0.916667 0.0625 0.916667 0.104167 0.875 0.125 0.875 0.125 0.916667 0.104167 0.916667 0.145833 0.875 0.166667 0.875 0.166667 0.916667 0.145833 0.916667 0.1875 0.875 0.208333 0.875 0.208333 0.916667 0.1875 0.916667 0.229167 0.875 0.25 0.875 0.25 0.916667 0.229167 0.916667 0.270833 0.875 0.291667 0.875 0.291667 0.916667 0.270833 0.916667 0.3125 0.875 0.333333 0.875 0.333333 0.916667 0.3125 0.916667 0.354167 0.875 0.375 0.875 0.375 0.916667 0.354167 0.916667 0.395833 0.875 0.416667 0.875 0.416667 0.916667 0.395833 0.916667 0.4375 0.875 0.458333 0.875 0.458333 0.916667 0.4375 0.916667 0.479167 0.875 0.5 0.875 0.5 0.916667 0.479167 0.916667 0.520833 0.875 0.541667 0.875 0.541667 0.916667 0.520833 0.916667 0.5625 0.875 0.583333 0.875 0.583333 0.916667 0.5625 0.916667 0.604167 0.875 0.625 0.875 0.625 0.916667 0.604167 0.916667 0.645833 0.875 0.666667 0.875 0.666667 0.916667 0.645833 0.916667 0.6875 0.875 0.708333 0.875 0.708333 0.916667 0.6875 0.916667 0.729167 0.875 0.75 0.875 0.75 0.916667 0.729167 0.916667 0.770833 0.875 0.791667 0.875 0.791667 0.916667 0.770833 0.916667 0.8125 0.875 0.833333 0.875 0.833333 0.916667 0.8125 0.916667 0.854167 0.875 0.875 0.875 0.875 0.916667 0.854167 0.916667 0.895833 0.875 0.916667 0.875 0.916667 0.916667 0.895833 0.916667 0.9375 0.875 0.958333 0.875 0.958333 0.916667 0.9375 0.916667 0.979167 0.833333 0.979167 0.875 1 0.833333 1 0.875 0.979167 0.833333 1 0.916667 0.979167 0.916667 1 0.875 0.979167 0.916667 0.020833 0.958333 0 0.958333 0.041666 0.958333 0.041666 1 0.020833 1 0.041666 0.958333 0 1 0 0.958333 0.020833 1 0.0625 0.958333 0.041666 0.958333 0.083333 0.958333 0.083333 1 0.0625 1 0.083333 0.958333 0.041666 1 0.041666 0.958333 0.0625 1 0.104167 0.958333 0.083333 0.958333 0.125 0.958333 0.125 1 0.104167 1 0.125 0.958333 0.083333 1 0.083333 0.958333 0.104167 1 0.145833 0.958333 0.125 0.958333 0.166667 0.958333 0.166667 1 0.145833 1 0.166667 0.958333 0.125 1 0.125 0.958333 0.145833 1 0.1875 0.958333 0.166667 0.958333 0.208333 0.958333 0.208333 1 0.1875 1 0.208333 0.958333 0.166667 1 0.166667 0.958333 0.1875 1 0.229167 0.958333 0.208333 0.958333 0.25 0.958333 0.25 1 0.229167 1 0.25 0.958333 0.208333 1 0.208333 0.958333 0.229167 1 0.270833 0.958333 0.25 0.958333 0.291667 0.958333 0.291667 1 0.270833 1 0.291667 0.958333 0.25 1 0.25 0.958333 0.270833 1 0.3125 0.958333 0.291667 0.958333 0.333333 0.958333 0.333333 1 0.3125 1 0.333333 0.958333 0.291667 1 0.291667 0.958333 0.3125 1 0.354167 0.958333 0.333333 0.958333 0.375 0.958333 0.375 1 0.354167 1 0.375 0.958333 0.333333 1 0.333333 0.958333 0.354167 1 0.395833 0.958333 0.375 0.958333 0.416667 0.958333 0.416667 1 0.395833 1 0.416667 0.958333 0.375 1 0.375 0.958333 0.395833 1 0.4375 0.958333 0.416667 0.958333 0.458333 0.958333 0.458333 1 0.4375 1 0.458333 0.958333 0.416667 1 0.416667 0.958333 0.4375 1 0.479167 0.958333 0.458333 0.958333 0.5 0.958333 0.5 1 0.479167 1 0.5 0.958333 0.458333 1 0.458333 0.958333 0.479167 1 0.520833 0.958333 0.5 0.958333 0.541667 0.958333 0.541667 1 0.520833 1 0.541667 0.958333 0.5 1 0.5 0.958333 0.520833 1 0.5625 0.958333 0.541667 0.958333 0.583333 0.958333 0.583333 1 0.5625 1 0.583333 0.958333 0.541667 1 0.541667 0.958333 0.5625 1 0.604167 0.958333 0.583333 0.958333 0.625 0.958333 0.625 1 0.604167 1 0.625 0.958333 0.583333 1 0.583333 0.958333 0.604167 1 0.645833 0.958333 0.625 0.958333 0.666667 0.958333 0.666667 1 0.645833 1 0.666667 0.958333 0.625 1 0.625 0.958333 0.645833 1 0.6875 0.958333 0.666667 0.958333 0.708333 0.958333 0.708333 1 0.6875 1 0.708333 0.958333 0.666667 1 0.666667 0.958333 0.6875 1 0.729167 0.958333 0.708333 0.958333 0.75 0.958333 0.75 1 0.729167 1 0.75 0.958333 0.708333 1 0.708333 0.958333 0.729167 1 0.770833 0.958333 0.75 0.958333 0.791667 0.958333 0.791667 1 0.770833 1 0.791667 0.958333 0.75 1 0.75 0.958333 0.770833 1 0.8125 0.958333 0.791667 0.958333 0.833333 0.958333 0.833333 1 0.8125 1 0.833333 0.958333 0.791667 1 0.791667 0.958333 0.8125 1 0.854167 0.958333 0.833333 0.958333 0.875 0.958333 0.875 1 0.854167 1 0.875 0.958333 0.833333 1 0.833333 0.958333 0.854167 1 0.895833 0.958333 0.875 0.958333 0.916667 0.958333 0.916667 1 0.895833 1 0.916667 0.958333 0.875 1 0.875 0.958333 0.895833 1 0.9375 0.958333 0.916667 0.958333 0.958333 0.958333 0.958333 1 0.9375 1 0.958333 0.958333 0.916667 1 0.916667 0.958333 0.9375 1 0.979167 0.916667 0.979167 0.958333 0.958333 0.958333 1 0.916667 1 0.958333 0.979167 0.916667 1 1 0.979167 1 1 0.958333 0.958333 1 0.958333 0.958333 0.979167 1</float_array>
+ <technique_common>
+ <accessor source="#Torus-Texture-array" count="1399" stride="2">
+ <param name="S" type="float"/>
+ <param name="T" type="float"/>
+ </accessor>
+ </technique_common>
+ </source>
+ <vertices id="Torus-vertices">
+ <input semantic="POSITION" source="#Torus-positions"/>
+ <input semantic="NORMAL" source="#Torus-normals"/>
+ </vertices>
+ <triangles material="lambert2SG" count="2304">
+ <input semantic="VERTEX" source="#Torus-vertices" offset="0"/>
+ <input semantic="TEXCOORD" source="#Torus-Texture" offset="1" set="1"/>
+ <p>288 1 292 2 0 0 0 0 292 2 291 3 289 5 292 2 1 4 1 4 292 2 288 1 25 6 290 7 289 5 289 5 290 7 292 2 24 8 291 3 290 7 290 7 291 3 292 2 293 9 296 10 1 4 1 4 296 10 289 5 294 12 296 10 2 11 2 11 296 10 293 9 26 13 295 14 294 12 294 12 295 14 296 10 25 6 289 5 295 14 295 14 289 5 296 10 297 15 300 16 2 11 2 11 300 16 294 12 298 18 300 16 3 17 3 17 300 16 297 15 27 19 299 20 298 18 298 18 299 20 300 16 26 13 294 12 299 20 299 20 294 12 300 16 301 21 304 22 3 17 3 17 304 22 298 18 302 24 304 22 4 23 4 23 304 22 301 21 28 25 303 26 302 24 302 24 303 26 304 22 27 19 298 18 303 26 303 26 298 18 304 22 305 27 308 28 4 23 4 23 308 28 302 24 306 30 308 28 5 29 5 29 308 28 305 27 29 31 307 32 306 30 306 30 307 32 308 28 28 25 302 24 307 32 307 32 302 24 308 28 309 33 312 34 5 29 5 29 312 34 306 30 310 36 312 34 6 35 6 35 312 34 309 33 30 37 311 38 310 36 310 36 311 38 312 34 29 31 306 30 311 38 311 38 306 30 312 34 313 39 316 40 6 35 6 35 316 40 310 36 314 42 316 40 7 41 7 41 316 40 313 39 31 43 315 44 314 42 314 42 315 44 316 40 30 37 310 36 315 44 315 44 310 36 316 40 317 45 320 46 7 41 7 41 320 46 314 42 318 48 320 46 8 47 8 47 320 46 317 45 32 49 319 50 318 48 318 48 319 50 320 46 31 43 314 42 319 50 319 50 314 42 320 46 321 51 324 52 8 47 8 47 324 52 318 48 322 54 324 52 9 53 9 53 324 52 321 51 33 55 323 56 322 54 322 54 323 56 324 52 32 49 318 48 323 56 323 56 318 48 324 52 325 57 328 58 9 53 9 53 328 58 322 54 326 60 328 58 10 59 10 59 328 58 325 57 34 61 327 62 326 60 326 60 327 62 328 58 33 55 322 54 327 62 327 62 322 54 328 58 329 63 332 64 10 59 10 59 332 64 326 60 330 66 332 64 11 65 11 65 332 64 329 63 35 67 331 68 330 66 330 66 331 68 332 64 34 61 326 60 331 68 331 68 326 60 332 64 333 69 336 70 11 65 11 65 336 70 330 66 334 72 336 70 12 71 12 71 336 70 333 69 36 73 335 74 334 72 334 72 335 74 336 70 35 67 330 66 335 74 335 74 330 66 336 70 337 75 340 76 12 71 12 71 340 76 334 72 338 78 340 76 13 77 13 77 340 76 337 75 37 79 339 80 338 78 338 78 339 80 340 76 36 73 334 72 339 80 339 80 334 72 340 76 341 81 344 82 13 77 13 77 344 82 338 78 342 84 344 82 14 83 14 83 344 82 341 81 38 85 343 86 342 84 342 84 343 86 344 82 37 79 338 78 343 86 343 86 338 78 344 82 345 87 348 88 14 83 14 83 348 88 342 84 346 90 348 88 15 89 15 89 348 88 345 87 39 91 347 92 346 90 346 90 347 92 348 88 38 85 342 84 347 92 347 92 342 84 348 88 349 93 352 94 15 89 15 89 352 94 346 90 350 96 352 94 16 95 16 95 352 94 349 93 40 97 351 98 350 96 350 96 351 98 352 94 39 91 346 90 351 98 351 98 346 90 352 94 353 99 356 100 16 95 16 95 356 100 350 96 354 102 356 100 17 101 17 101 356 100 353 99 41 103 355 104 354 102 354 102 355 104 356 100 40 97 350 96 355 104 355 104 350 96 356 100 357 105 360 106 17 101 17 101 360 106 354 102 358 108 360 106 18 107 18 107 360 106 357 105 42 109 359 110 358 108 358 108 359 110 360 106 41 103 354 102 359 110 359 110 354 102 360 106 361 111 364 112 18 107 18 107 364 112 358 108 362 114 364 112 19 113 19 113 364 112 361 111 43 115 363 116 362 114 362 114 363 116 364 112 42 109 358 108 363 116 363 116 358 108 364 112 365 117 368 118 19 113 19 113 368 118 362 114 366 120 368 118 20 119 20 119 368 118 365 117 44 121 367 122 366 120 366 120 367 122 368 118 43 115 362 114 367 122 367 122 362 114 368 118 369 123 372 124 20 119 20 119 372 124 366 120 370 126 372 124 21 125 21 125 372 124 369 123 45 127 371 128 370 126 370 126 371 128 372 124 44 121 366 120 371 128 371 128 366 120 372 124 373 129 376 130 21 125 21 125 376 130 370 126 374 132 376 130 22 131 22 131 376 130 373 129 46 133 375 134 374 132 374 132 375 134 376 130 45 127 370 126 375 134 375 134 370 126 376 130 377 135 380 136 22 131 22 131 380 136 374 132 378 138 380 136 23 137 23 137 380 136 377 135 47 139 379 140 378 138 378 138 379 140 380 136 46 133 374 132 379 140 379 140 374 132 380 136 381 141 383 142 23 137 23 137 383 142 378 138 291 144 383 142 0 143 0 143 383 142 381 145 24 146 382 147 291 148 291 148 382 147 383 142 47 139 378 138 382 149 382 149 378 138 383 142 290 7 387 150 24 8 24 8 387 150 386 151 384 152 387 150 25 6 25 6 387 150 290 7 49 153 385 154 384 152 384 152 385 154 387 150 48 155 386 151 385 154 385 154 386 151 387 150 295 14 390 156 25 6 25 6 390 156 384 152 388 157 390 156 26 13 26 13 390 156 295 14 50 158 389 159 388 157 388 157 389 159 390 156 49 153 384 152 389 159 389 159 384 152 390 156 299 20 393 160 26 13 26 13 393 160 388 157 391 161 393 160 27 19 27 19 393 160 299 20 51 162 392 163 391 161 391 161 392 163 393 160 50 158 388 157 392 163 392 163 388 157 393 160 303 26 396 164 27 19 27 19 396 164 391 161 394 165 396 164 28 25 28 25 396 164 303 26 52 166 395 167 394 165 394 165 395 167 396 164 51 162 391 161 395 167 395 167 391 161 396 164 307 32 399 168 28 25 28 25 399 168 394 165 397 169 399 168 29 31 29 31 399 168 307 32 53 170 398 171 397 169 397 169 398 171 399 168 52 166 394 165 398 171 398 171 394 165 399 168 311 38 402 172 29 31 29 31 402 172 397 169 400 173 402 172 30 37 30 37 402 172 311 38 54 174 401 175 400 173 400 173 401 175 402 172 53 170 397 169 401 175 401 175 397 169 402 172 315 44 405 176 30 37 30 37 405 176 400 173 403 177 405 176 31 43 31 43 405 176 315 44 55 178 404 179 403 177 403 177 404 179 405 176 54 174 400 173 404 179 404 179 400 173 405 176 319 50 408 180 31 43 31 43 408 180 403 177 406 181 408 180 32 49 32 49 408 180 319 50 56 182 407 183 406 181 406 181 407 183 408 180 55 178 403 177 407 183 407 183 403 177 408 180 323 56 411 184 32 49 32 49 411 184 406 181 409 185 411 184 33 55 33 55 411 184 323 56 57 186 410 187 409 185 409 185 410 187 411 184 56 182 406 181 410 187 410 187 406 181 411 184 327 62 414 188 33 55 33 55 414 188 409 185 412 189 414 188 34 61 34 61 414 188 327 62 58 190 413 191 412 189 412 189 413 191 414 188 57 186 409 185 413 191 413 191 409 185 414 188 331 68 417 192 34 61 34 61 417 192 412 189 415 193 417 192 35 67 35 67 417 192 331 68 59 194 416 195 415 193 415 193 416 195 417 192 58 190 412 189 416 195 416 195 412 189 417 192 335 74 420 196 35 67 35 67 420 196 415 193 418 197 420 196 36 73 36 73 420 196 335 74 60 198 419 199 418 197 418 197 419 199 420 196 59 194 415 193 419 199 419 199 415 193 420 196 339 80 423 200 36 73 36 73 423 200 418 197 421 201 423 200 37 79 37 79 423 200 339 80 61 202 422 203 421 201 421 201 422 203 423 200 60 198 418 197 422 203 422 203 418 197 423 200 343 86 426 204 37 79 37 79 426 204 421 201 424 205 426 204 38 85 38 85 426 204 343 86 62 206 425 207 424 205 424 205 425 207 426 204 61 202 421 201 425 207 425 207 421 201 426 204 347 92 429 208 38 85 38 85 429 208 424 205 427 209 429 208 39 91 39 91 429 208 347 92 63 210 428 211 427 209 427 209 428 211 429 208 62 206 424 205 428 211 428 211 424 205 429 208 351 98 432 212 39 91 39 91 432 212 427 209 430 213 432 212 40 97 40 97 432 212 351 98 64 214 431 215 430 213 430 213 431 215 432 212 63 210 427 209 431 215 431 215 427 209 432 212 355 104 435 216 40 97 40 97 435 216 430 213 433 217 435 216 41 103 41 103 435 216 355 104 65 218 434 219 433 217 433 217 434 219 435 216 64 214 430 213 434 219 434 219 430 213 435 216 359 110 438 220 41 103 41 103 438 220 433 217 436 221 438 220 42 109 42 109 438 220 359 110 66 222 437 223 436 221 436 221 437 223 438 220 65 218 433 217 437 223 437 223 433 217 438 220 363 116 441 224 42 109 42 109 441 224 436 221 439 225 441 224 43 115 43 115 441 224 363 116 67 226 440 227 439 225 439 225 440 227 441 224 66 222 436 221 440 227 440 227 436 221 441 224 367 122 444 228 43 115 43 115 444 228 439 225 442 229 444 228 44 121 44 121 444 228 367 122 68 230 443 231 442 229 442 229 443 231 444 228 67 226 439 225 443 231 443 231 439 225 444 228 371 128 447 232 44 121 44 121 447 232 442 229 445 233 447 232 45 127 45 127 447 232 371 128 69 234 446 235 445 233 445 233 446 235 447 232 68 230 442 229 446 235 446 235 442 229 447 232 375 134 450 236 45 127 45 127 450 236 445 233 448 237 450 236 46 133 46 133 450 236 375 134 70 238 449 239 448 237 448 237 449 239 450 236 69 234 445 233 449 239 449 239 445 233 450 236 379 140 453 240 46 133 46 133 453 240 448 237 451 241 453 240 47 139 47 139 453 240 379 140 71 242 452 243 451 241 451 241 452 243 453 240 70 238 448 237 452 243 452 243 448 237 453 240 382 244 455 245 47 139 47 139 455 245 451 241 386 247 455 245 24 246 24 246 455 245 382 248 48 249 454 250 386 251 386 251 454 250 455 245 71 242 451 241 454 252 454 252 451 241 455 245 385 154 459 253 48 155 48 155 459 253 458 254 456 255 459 253 49 153 49 153 459 253 385 154 73 256 457 257 456 255 456 255 457 257 459 253 72 258 458 254 457 257 457 257 458 254 459 253 389 159 462 259 49 153 49 153 462 259 456 255 460 260 462 259 50 158 50 158 462 259 389 159 74 261 461 262 460 260 460 260 461 262 462 259 73 256 456 255 461 262 461 262 456 255 462 259 392 163 465 263 50 158 50 158 465 263 460 260 463 264 465 263 51 162 51 162 465 263 392 163 75 265 464 266 463 264 463 264 464 266 465 263 74 261 460 260 464 266 464 266 460 260 465 263 395 167 468 267 51 162 51 162 468 267 463 264 466 268 468 267 52 166 52 166 468 267 395 167 76 269 467 270 466 268 466 268 467 270 468 267 75 265 463 264 467 270 467 270 463 264 468 267 398 171 471 271 52 166 52 166 471 271 466 268 469 272 471 271 53 170 53 170 471 271 398 171 77 273 470 274 469 272 469 272 470 274 471 271 76 269 466 268 470 274 470 274 466 268 471 271 401 175 474 275 53 170 53 170 474 275 469 272 472 276 474 275 54 174 54 174 474 275 401 175 78 277 473 278 472 276 472 276 473 278 474 275 77 273 469 272 473 278 473 278 469 272 474 275 404 179 477 279 54 174 54 174 477 279 472 276 475 280 477 279 55 178 55 178 477 279 404 179 79 281 476 282 475 280 475 280 476 282 477 279 78 277 472 276 476 282 476 282 472 276 477 279 407 183 480 283 55 178 55 178 480 283 475 280 478 284 480 283 56 182 56 182 480 283 407 183 80 285 479 286 478 284 478 284 479 286 480 283 79 281 475 280 479 286 479 286 475 280 480 283 410 187 483 287 56 182 56 182 483 287 478 284 481 288 483 287 57 186 57 186 483 287 410 187 81 289 482 290 481 288 481 288 482 290 483 287 80 285 478 284 482 290 482 290 478 284 483 287 413 191 486 291 57 186 57 186 486 291 481 288 484 292 486 291 58 190 58 190 486 291 413 191 82 293 485 294 484 292 484 292 485 294 486 291 81 289 481 288 485 294 485 294 481 288 486 291 416 195 489 295 58 190 58 190 489 295 484 292 487 296 489 295 59 194 59 194 489 295 416 195 83 297 488 298 487 296 487 296 488 298 489 295 82 293 484 292 488 298 488 298 484 292 489 295 419 199 492 299 59 194 59 194 492 299 487 296 490 300 492 299 60 198 60 198 492 299 419 199 84 301 491 302 490 300 490 300 491 302 492 299 83 297 487 296 491 302 491 302 487 296 492 299 422 203 495 303 60 198 60 198 495 303 490 300 493 304 495 303 61 202 61 202 495 303 422 203 85 305 494 306 493 304 493 304 494 306 495 303 84 301 490 300 494 306 494 306 490 300 495 303 425 207 498 307 61 202 61 202 498 307 493 304 496 308 498 307 62 206 62 206 498 307 425 207 86 309 497 310 496 308 496 308 497 310 498 307 85 305 493 304 497 310 497 310 493 304 498 307 428 211 501 311 62 206 62 206 501 311 496 308 499 312 501 311 63 210 63 210 501 311 428 211 87 313 500 314 499 312 499 312 500 314 501 311 86 309 496 308 500 314 500 314 496 308 501 311 431 215 504 315 63 210 63 210 504 315 499 312 502 316 504 315 64 214 64 214 504 315 431 215 88 317 503 318 502 316 502 316 503 318 504 315 87 313 499 312 503 318 503 318 499 312 504 315 434 219 507 319 64 214 64 214 507 319 502 316 505 320 507 319 65 218 65 218 507 319 434 219 89 321 506 322 505 320 505 320 506 322 507 319 88 317 502 316 506 322 506 322 502 316 507 319 437 223 510 323 65 218 65 218 510 323 505 320 508 324 510 323 66 222 66 222 510 323 437 223 90 325 509 326 508 324 508 324 509 326 510 323 89 321 505 320 509 326 509 326 505 320 510 323 440 227 513 327 66 222 66 222 513 327 508 324 511 328 513 327 67 226 67 226 513 327 440 227 91 329 512 330 511 328 511 328 512 330 513 327 90 325 508 324 512 330 512 330 508 324 513 327 443 231 516 331 67 226 67 226 516 331 511 328 514 332 516 331 68 230 68 230 516 331 443 231 92 333 515 334 514 332 514 332 515 334 516 331 91 329 511 328 515 334 515 334 511 328 516 331 446 235 519 335 68 230 68 230 519 335 514 332 517 336 519 335 69 234 69 234 519 335 446 235 93 337 518 338 517 336 517 336 518 338 519 335 92 333 514 332 518 338 518 338 514 332 519 335 449 239 522 339 69 234 69 234 522 339 517 336 520 340 522 339 70 238 70 238 522 339 449 239 94 341 521 342 520 340 520 340 521 342 522 339 93 337 517 336 521 342 521 342 517 336 522 339 452 243 525 343 70 238 70 238 525 343 520 340 523 344 525 343 71 242 71 242 525 343 452 243 95 345 524 346 523 344 523 344 524 346 525 343 94 341 520 340 524 346 524 346 520 340 525 343 454 347 527 348 71 242 71 242 527 348 523 344 458 350 527 348 48 349 48 349 527 348 454 351 72 352 526 353 458 354 458 354 526 353 527 348 95 345 523 344 526 355 526 355 523 344 527 348 457 257 531 356 72 258 72 258 531 356 530 357 528 358 531 356 73 256 73 256 531 356 457 257 97 359 529 360 528 358 528 358 529 360 531 356 96 361 530 357 529 360 529 360 530 357 531 356 461 262 534 362 73 256 73 256 534 362 528 358 532 363 534 362 74 261 74 261 534 362 461 262 98 364 533 365 532 363 532 363 533 365 534 362 97 359 528 358 533 365 533 365 528 358 534 362 464 266 537 366 74 261 74 261 537 366 532 363 535 367 537 366 75 265 75 265 537 366 464 266 99 368 536 369 535 367 535 367 536 369 537 366 98 364 532 363 536 369 536 369 532 363 537 366 467 270 540 370 75 265 75 265 540 370 535 367 538 371 540 370 76 269 76 269 540 370 467 270 100 372 539 373 538 371 538 371 539 373 540 370 99 368 535 367 539 373 539 373 535 367 540 370 470 274 543 374 76 269 76 269 543 374 538 371 541 375 543 374 77 273 77 273 543 374 470 274 101 376 542 377 541 375 541 375 542 377 543 374 100 372 538 371 542 377 542 377 538 371 543 374 473 278 546 378 77 273 77 273 546 378 541 375 544 379 546 378 78 277 78 277 546 378 473 278 102 380 545 381 544 379 544 379 545 381 546 378 101 376 541 375 545 381 545 381 541 375 546 378 476 282 549 382 78 277 78 277 549 382 544 379 547 383 549 382 79 281 79 281 549 382 476 282 103 384 548 385 547 383 547 383 548 385 549 382 102 380 544 379 548 385 548 385 544 379 549 382 479 286 552 386 79 281 79 281 552 386 547 383 550 387 552 386 80 285 80 285 552 386 479 286 104 388 551 389 550 387 550 387 551 389 552 386 103 384 547 383 551 389 551 389 547 383 552 386 482 290 555 390 80 285 80 285 555 390 550 387 553 391 555 390 81 289 81 289 555 390 482 290 105 392 554 393 553 391 553 391 554 393 555 390 104 388 550 387 554 393 554 393 550 387 555 390 485 294 558 394 81 289 81 289 558 394 553 391 556 395 558 394 82 293 82 293 558 394 485 294 106 396 557 397 556 395 556 395 557 397 558 394 105 392 553 391 557 397 557 397 553 391 558 394 488 298 561 398 82 293 82 293 561 398 556 395 559 399 561 398 83 297 83 297 561 398 488 298 107 400 560 401 559 399 559 399 560 401 561 398 106 396 556 395 560 401 560 401 556 395 561 398 491 302 564 402 83 297 83 297 564 402 559 399 562 403 564 402 84 301 84 301 564 402 491 302 108 404 563 405 562 403 562 403 563 405 564 402 107 400 559 399 563 405 563 405 559 399 564 402 494 306 567 406 84 301 84 301 567 406 562 403 565 407 567 406 85 305 85 305 567 406 494 306 109 408 566 409 565 407 565 407 566 409 567 406 108 404 562 403 566 409 566 409 562 403 567 406 497 310 570 410 85 305 85 305 570 410 565 407 568 411 570 410 86 309 86 309 570 410 497 310 110 412 569 413 568 411 568 411 569 413 570 410 109 408 565 407 569 413 569 413 565 407 570 410 500 314 573 414 86 309 86 309 573 414 568 411 571 415 573 414 87 313 87 313 573 414 500 314 111 416 572 417 571 415 571 415 572 417 573 414 110 412 568 411 572 417 572 417 568 411 573 414 503 318 576 418 87 313 87 313 576 418 571 415 574 419 576 418 88 317 88 317 576 418 503 318 112 420 575 421 574 419 574 419 575 421 576 418 111 416 571 415 575 421 575 421 571 415 576 418 506 322 579 422 88 317 88 317 579 422 574 419 577 423 579 422 89 321 89 321 579 422 506 322 113 424 578 425 577 423 577 423 578 425 579 422 112 420 574 419 578 425 578 425 574 419 579 422 509 326 582 426 89 321 89 321 582 426 577 423 580 427 582 426 90 325 90 325 582 426 509 326 114 428 581 429 580 427 580 427 581 429 582 426 113 424 577 423 581 429 581 429 577 423 582 426 512 330 585 430 90 325 90 325 585 430 580 427 583 431 585 430 91 329 91 329 585 430 512 330 115 432 584 433 583 431 583 431 584 433 585 430 114 428 580 427 584 433 584 433 580 427 585 430 515 334 588 434 91 329 91 329 588 434 583 431 586 435 588 434 92 333 92 333 588 434 515 334 116 436 587 437 586 435 586 435 587 437 588 434 115 432 583 431 587 437 587 437 583 431 588 434 518 338 591 438 92 333 92 333 591 438 586 435 589 439 591 438 93 337 93 337 591 438 518 338 117 440 590 441 589 439 589 439 590 441 591 438 116 436 586 435 590 441 590 441 586 435 591 438 521 342 594 442 93 337 93 337 594 442 589 439 592 443 594 442 94 341 94 341 594 442 521 342 118 444 593 445 592 443 592 443 593 445 594 442 117 440 589 439 593 445 593 445 589 439 594 442 524 346 597 446 94 341 94 341 597 446 592 443 595 447 597 446 95 345 95 345 597 446 524 346 119 448 596 449 595 447 595 447 596 449 597 446 118 444 592 443 596 449 596 449 592 443 597 446 526 450 599 451 95 345 95 345 599 451 595 447 530 453 599 451 72 452 72 452 599 451 526 454 96 455 598 456 530 457 530 457 598 456 599 451 119 448 595 447 598 458 598 458 595 447 599 451 529 360 603 459 96 361 96 361 603 459 602 460 600 461 603 459 97 359 97 359 603 459 529 360 121 462 601 463 600 461 600 461 601 463 603 459 120 464 602 460 601 463 601 463 602 460 603 459 533 365 606 465 97 359 97 359 606 465 600 461 604 466 606 465 98 364 98 364 606 465 533 365 122 467 605 468 604 466 604 466 605 468 606 465 121 462 600 461 605 468 605 468 600 461 606 465 536 369 609 469 98 364 98 364 609 469 604 466 607 470 609 469 99 368 99 368 609 469 536 369 123 471 608 472 607 470 607 470 608 472 609 469 122 467 604 466 608 472 608 472 604 466 609 469 539 373 612 473 99 368 99 368 612 473 607 470 610 474 612 473 100 372 100 372 612 473 539 373 124 475 611 476 610 474 610 474 611 476 612 473 123 471 607 470 611 476 611 476 607 470 612 473 542 377 615 477 100 372 100 372 615 477 610 474 613 478 615 477 101 376 101 376 615 477 542 377 125 479 614 480 613 478 613 478 614 480 615 477 124 475 610 474 614 480 614 480 610 474 615 477 545 381 618 481 101 376 101 376 618 481 613 478 616 482 618 481 102 380 102 380 618 481 545 381 126 483 617 484 616 482 616 482 617 484 618 481 125 479 613 478 617 484 617 484 613 478 618 481 548 385 621 485 102 380 102 380 621 485 616 482 619 486 621 485 103 384 103 384 621 485 548 385 127 487 620 488 619 486 619 486 620 488 621 485 126 483 616 482 620 488 620 488 616 482 621 485 551 389 624 489 103 384 103 384 624 489 619 486 622 490 624 489 104 388 104 388 624 489 551 389 128 491 623 492 622 490 622 490 623 492 624 489 127 487 619 486 623 492 623 492 619 486 624 489 554 393 627 493 104 388 104 388 627 493 622 490 625 494 627 493 105 392 105 392 627 493 554 393 129 495 626 496 625 494 625 494 626 496 627 493 128 491 622 490 626 496 626 496 622 490 627 493 557 397 630 497 105 392 105 392 630 497 625 494 628 498 630 497 106 396 106 396 630 497 557 397 130 499 629 500 628 498 628 498 629 500 630 497 129 495 625 494 629 500 629 500 625 494 630 497 560 401 633 501 106 396 106 396 633 501 628 498 631 502 633 501 107 400 107 400 633 501 560 401 131 503 632 504 631 502 631 502 632 504 633 501 130 499 628 498 632 504 632 504 628 498 633 501 563 405 636 505 107 400 107 400 636 505 631 502 634 506 636 505 108 404 108 404 636 505 563 405 132 507 635 508 634 506 634 506 635 508 636 505 131 503 631 502 635 508 635 508 631 502 636 505 566 409 639 509 108 404 108 404 639 509 634 506 637 510 639 509 109 408 109 408 639 509 566 409 133 511 638 512 637 510 637 510 638 512 639 509 132 507 634 506 638 512 638 512 634 506 639 509 569 413 642 513 109 408 109 408 642 513 637 510 640 514 642 513 110 412 110 412 642 513 569 413 134 515 641 516 640 514 640 514 641 516 642 513 133 511 637 510 641 516 641 516 637 510 642 513 572 417 645 517 110 412 110 412 645 517 640 514 643 518 645 517 111 416 111 416 645 517 572 417 135 519 644 520 643 518 643 518 644 520 645 517 134 515 640 514 644 520 644 520 640 514 645 517 575 421 648 521 111 416 111 416 648 521 643 518 646 522 648 521 112 420 112 420 648 521 575 421 136 523 647 524 646 522 646 522 647 524 648 521 135 519 643 518 647 524 647 524 643 518 648 521 578 425 651 525 112 420 112 420 651 525 646 522 649 526 651 525 113 424 113 424 651 525 578 425 137 527 650 528 649 526 649 526 650 528 651 525 136 523 646 522 650 528 650 528 646 522 651 525 581 429 654 529 113 424 113 424 654 529 649 526 652 530 654 529 114 428 114 428 654 529 581 429 138 531 653 532 652 530 652 530 653 532 654 529 137 527 649 526 653 532 653 532 649 526 654 529 584 433 657 533 114 428 114 428 657 533 652 530 655 534 657 533 115 432 115 432 657 533 584 433 139 535 656 536 655 534 655 534 656 536 657 533 138 531 652 530 656 536 656 536 652 530 657 533 587 437 660 537 115 432 115 432 660 537 655 534 658 538 660 537 116 436 116 436 660 537 587 437 140 539 659 540 658 538 658 538 659 540 660 537 139 535 655 534 659 540 659 540 655 534 660 537 590 441 663 541 116 436 116 436 663 541 658 538 661 542 663 541 117 440 117 440 663 541 590 441 141 543 662 544 661 542 661 542 662 544 663 541 140 539 658 538 662 544 662 544 658 538 663 541 593 445 666 545 117 440 117 440 666 545 661 542 664 546 666 545 118 444 118 444 666 545 593 445 142 547 665 548 664 546 664 546 665 548 666 545 141 543 661 542 665 548 665 548 661 542 666 545 596 449 669 549 118 444 118 444 669 549 664 546 667 550 669 549 119 448 119 448 669 549 596 449 143 551 668 552 667 550 667 550 668 552 669 549 142 547 664 546 668 552 668 552 664 546 669 549 598 553 671 554 119 448 119 448 671 554 667 550 602 556 671 554 96 555 96 555 671 554 598 557 120 558 670 559 602 560 602 560 670 559 671 554 143 551 667 550 670 561 670 561 667 550 671 554 601 463 675 562 120 464 120 464 675 562 674 563 672 564 675 562 121 462 121 462 675 562 601 463 145 565 673 566 672 564 672 564 673 566 675 562 144 567 674 563 673 566 673 566 674 563 675 562 605 468 678 568 121 462 121 462 678 568 672 564 676 569 678 568 122 467 122 467 678 568 605 468 146 570 677 571 676 569 676 569 677 571 678 568 145 565 672 564 677 571 677 571 672 564 678 568 608 472 681 572 122 467 122 467 681 572 676 569 679 573 681 572 123 471 123 471 681 572 608 472 147 574 680 575 679 573 679 573 680 575 681 572 146 570 676 569 680 575 680 575 676 569 681 572 611 476 684 576 123 471 123 471 684 576 679 573 682 577 684 576 124 475 124 475 684 576 611 476 148 578 683 579 682 577 682 577 683 579 684 576 147 574 679 573 683 579 683 579 679 573 684 576 614 480 687 580 124 475 124 475 687 580 682 577 685 581 687 580 125 479 125 479 687 580 614 480 149 582 686 583 685 581 685 581 686 583 687 580 148 578 682 577 686 583 686 583 682 577 687 580 617 484 690 584 125 479 125 479 690 584 685 581 688 585 690 584 126 483 126 483 690 584 617 484 150 586 689 587 688 585 688 585 689 587 690 584 149 582 685 581 689 587 689 587 685 581 690 584 620 488 693 588 126 483 126 483 693 588 688 585 691 589 693 588 127 487 127 487 693 588 620 488 151 590 692 591 691 589 691 589 692 591 693 588 150 586 688 585 692 591 692 591 688 585 693 588 623 492 696 592 127 487 127 487 696 592 691 589 694 593 696 592 128 491 128 491 696 592 623 492 152 594 695 595 694 593 694 593 695 595 696 592 151 590 691 589 695 595 695 595 691 589 696 592 626 496 699 596 128 491 128 491 699 596 694 593 697 597 699 596 129 495 129 495 699 596 626 496 153 598 698 599 697 597 697 597 698 599 699 596 152 594 694 593 698 599 698 599 694 593 699 596 629 500 702 600 129 495 129 495 702 600 697 597 700 601 702 600 130 499 130 499 702 600 629 500 154 602 701 603 700 601 700 601 701 603 702 600 153 598 697 597 701 603 701 603 697 597 702 600 632 504 705 604 130 499 130 499 705 604 700 601 703 605 705 604 131 503 131 503 705 604 632 504 155 606 704 607 703 605 703 605 704 607 705 604 154 602 700 601 704 607 704 607 700 601 705 604 635 508 708 608 131 503 131 503 708 608 703 605 706 609 708 608 132 507 132 507 708 608 635 508 156 610 707 611 706 609 706 609 707 611 708 608 155 606 703 605 707 611 707 611 703 605 708 608 638 512 711 612 132 507 132 507 711 612 706 609 709 613 711 612 133 511 133 511 711 612 638 512 157 614 710 615 709 613 709 613 710 615 711 612 156 610 706 609 710 615 710 615 706 609 711 612 641 516 714 616 133 511 133 511 714 616 709 613 712 617 714 616 134 515 134 515 714 616 641 516 158 618 713 619 712 617 712 617 713 619 714 616 157 614 709 613 713 619 713 619 709 613 714 616 644 520 717 620 134 515 134 515 717 620 712 617 715 621 717 620 135 519 135 519 717 620 644 520 159 622 716 623 715 621 715 621 716 623 717 620 158 618 712 617 716 623 716 623 712 617 717 620 647 524 720 624 135 519 135 519 720 624 715 621 718 625 720 624 136 523 136 523 720 624 647 524 160 626 719 627 718 625 718 625 719 627 720 624 159 622 715 621 719 627 719 627 715 621 720 624 650 528 723 628 136 523 136 523 723 628 718 625 721 629 723 628 137 527 137 527 723 628 650 528 161 630 722 631 721 629 721 629 722 631 723 628 160 626 718 625 722 631 722 631 718 625 723 628 653 532 726 632 137 527 137 527 726 632 721 629 724 633 726 632 138 531 138 531 726 632 653 532 162 634 725 635 724 633 724 633 725 635 726 632 161 630 721 629 725 635 725 635 721 629 726 632 656 536 729 636 138 531 138 531 729 636 724 633 727 637 729 636 139 535 139 535 729 636 656 536 163 638 728 639 727 637 727 637 728 639 729 636 162 634 724 633 728 639 728 639 724 633 729 636 659 540 732 640 139 535 139 535 732 640 727 637 730 641 732 640 140 539 140 539 732 640 659 540 164 642 731 643 730 641 730 641 731 643 732 640 163 638 727 637 731 643 731 643 727 637 732 640 662 544 735 644 140 539 140 539 735 644 730 641 733 645 735 644 141 543 141 543 735 644 662 544 165 646 734 647 733 645 733 645 734 647 735 644 164 642 730 641 734 647 734 647 730 641 735 644 665 548 738 648 141 543 141 543 738 648 733 645 736 649 738 648 142 547 142 547 738 648 665 548 166 650 737 651 736 649 736 649 737 651 738 648 165 646 733 645 737 651 737 651 733 645 738 648 668 552 741 652 142 547 142 547 741 652 736 649 739 653 741 652 143 551 143 551 741 652 668 552 167 654 740 655 739 653 739 653 740 655 741 652 166 650 736 649 740 655 740 655 736 649 741 652 670 656 743 657 143 551 143 551 743 657 739 653 674 659 743 657 120 658 120 658 743 657 670 660 144 661 742 662 674 663 674 663 742 662 743 657 167 654 739 653 742 664 742 664 739 653 743 657 144 567 673 566 746 666 746 666 673 566 747 665 145 565 744 667 673 566 673 566 744 667 747 665 745 669 747 665 169 668 169 668 747 665 744 667 746 666 747 665 168 670 168 670 747 665 745 669 145 565 677 571 744 667 744 667 677 571 750 671 146 570 748 672 677 571 677 571 748 672 750 671 749 674 750 671 170 673 170 673 750 671 748 672 744 667 750 671 169 668 169 668 750 671 749 674 146 570 680 575 748 672 748 672 680 575 753 675 147 574 751 676 680 575 680 575 751 676 753 675 752 678 753 675 171 677 171 677 753 675 751 676 748 672 753 675 170 673 170 673 753 675 752 678 147 574 683 579 751 676 751 676 683 579 756 679 148 578 754 680 683 579 683 579 754 680 756 679 755 682 756 679 172 681 172 681 756 679 754 680 751 676 756 679 171 677 171 677 756 679 755 682 148 578 686 583 754 680 754 680 686 583 759 683 149 582 757 684 686 583 686 583 757 684 759 683 758 686 759 683 173 685 173 685 759 683 757 684 754 680 759 683 172 681 172 681 759 683 758 686 149 582 689 587 757 684 757 684 689 587 762 687 150 586 760 688 689 587 689 587 760 688 762 687 761 690 762 687 174 689 174 689 762 687 760 688 757 684 762 687 173 685 173 685 762 687 761 690 150 586 692 591 760 688 760 688 692 591 765 691 151 590 763 692 692 591 692 591 763 692 765 691 764 694 765 691 175 693 175 693 765 691 763 692 760 688 765 691 174 689 174 689 765 691 764 694 151 590 695 595 763 692 763 692 695 595 768 695 152 594 766 696 695 595 695 595 766 696 768 695 767 698 768 695 176 697 176 697 768 695 766 696 763 692 768 695 175 693 175 693 768 695 767 698 152 594 698 599 766 696 766 696 698 599 771 699 153 598 769 700 698 599 698 599 769 700 771 699 770 702 771 699 177 701 177 701 771 699 769 700 766 696 771 699 176 697 176 697 771 699 770 702 153 598 701 603 769 700 769 700 701 603 774 703 154 602 772 704 701 603 701 603 772 704 774 703 773 706 774 703 178 705 178 705 774 703 772 704 769 700 774 703 177 701 177 701 774 703 773 706 154 602 704 607 772 704 772 704 704 607 777 707 155 606 775 708 704 607 704 607 775 708 777 707 776 710 777 707 179 709 179 709 777 707 775 708 772 704 777 707 178 705 178 705 777 707 776 710 155 606 707 611 775 708 775 708 707 611 780 711 156 610 778 712 707 611 707 611 778 712 780 711 779 714 780 711 180 713 180 713 780 711 778 712 775 708 780 711 179 709 179 709 780 711 779 714 156 610 710 615 778 712 778 712 710 615 783 715 157 614 781 716 710 615 710 615 781 716 783 715 782 718 783 715 181 717 181 717 783 715 781 716 778 712 783 715 180 713 180 713 783 715 782 718 157 614 713 619 781 716 781 716 713 619 786 719 158 618 784 720 713 619 713 619 784 720 786 719 785 722 786 719 182 721 182 721 786 719 784 720 781 716 786 719 181 717 181 717 786 719 785 722 158 618 716 623 784 720 784 720 716 623 789 723 159 622 787 724 716 623 716 623 787 724 789 723 788 726 789 723 183 725 183 725 789 723 787 724 784 720 789 723 182 721 182 721 789 723 788 726 159 622 719 627 787 724 787 724 719 627 792 727 160 626 790 728 719 627 719 627 790 728 792 727 791 730 792 727 184 729 184 729 792 727 790 728 787 724 792 727 183 725 183 725 792 727 791 730 160 626 722 631 790 728 790 728 722 631 795 731 161 630 793 732 722 631 722 631 793 732 795 731 794 734 795 731 185 733 185 733 795 731 793 732 790 728 795 731 184 729 184 729 795 731 794 734 161 630 725 635 793 732 793 732 725 635 798 735 162 634 796 736 725 635 725 635 796 736 798 735 797 738 798 735 186 737 186 737 798 735 796 736 793 732 798 735 185 733 185 733 798 735 797 738 162 634 728 639 796 736 796 736 728 639 801 739 163 638 799 740 728 639 728 639 799 740 801 739 800 742 801 739 187 741 187 741 801 739 799 740 796 736 801 739 186 737 186 737 801 739 800 742 163 638 731 643 799 740 799 740 731 643 804 743 164 642 802 744 731 643 731 643 802 744 804 743 803 746 804 743 188 745 188 745 804 743 802 744 799 740 804 743 187 741 187 741 804 743 803 746 164 642 734 647 802 744 802 744 734 647 807 747 165 646 805 748 734 647 734 647 805 748 807 747 806 750 807 747 189 749 189 749 807 747 805 748 802 744 807 747 188 745 188 745 807 747 806 750 165 646 737 651 805 748 805 748 737 651 810 751 166 650 808 752 737 651 737 651 808 752 810 751 809 754 810 751 190 753 190 753 810 751 808 752 805 748 810 751 189 749 189 749 810 751 809 754 166 650 740 655 808 752 808 752 740 655 813 755 167 654 811 756 740 655 740 655 811 756 813 755 812 758 813 755 191 757 191 757 813 755 811 756 808 752 813 755 190 753 190 753 813 755 812 758 167 654 742 759 811 756 811 756 742 759 815 760 144 761 746 762 742 763 742 763 746 762 815 760 814 765 815 760 168 764 168 764 815 760 746 766 811 756 815 760 191 757 191 757 815 760 814 767 168 670 745 669 818 769 818 769 745 669 819 768 169 668 816 770 745 669 745 669 816 770 819 768 817 772 819 768 193 771 193 771 819 768 816 770 818 769 819 768 192 773 192 773 819 768 817 772 169 668 749 674 816 770 816 770 749 674 822 774 170 673 820 775 749 674 749 674 820 775 822 774 821 777 822 774 194 776 194 776 822 774 820 775 816 770 822 774 193 771 193 771 822 774 821 777 170 673 752 678 820 775 820 775 752 678 825 778 171 677 823 779 752 678 752 678 823 779 825 778 824 781 825 778 195 780 195 780 825 778 823 779 820 775 825 778 194 776 194 776 825 778 824 781 171 677 755 682 823 779 823 779 755 682 828 782 172 681 826 783 755 682 755 682 826 783 828 782 827 785 828 782 196 784 196 784 828 782 826 783 823 779 828 782 195 780 195 780 828 782 827 785 172 681 758 686 826 783 826 783 758 686 831 786 173 685 829 787 758 686 758 686 829 787 831 786 830 789 831 786 197 788 197 788 831 786 829 787 826 783 831 786 196 784 196 784 831 786 830 789 173 685 761 690 829 787 829 787 761 690 834 790 174 689 832 791 761 690 761 690 832 791 834 790 833 793 834 790 198 792 198 792 834 790 832 791 829 787 834 790 197 788 197 788 834 790 833 793 174 689 764 694 832 791 832 791 764 694 837 794 175 693 835 795 764 694 764 694 835 795 837 794 836 797 837 794 199 796 199 796 837 794 835 795 832 791 837 794 198 792 198 792 837 794 836 797 175 693 767 698 835 795 835 795 767 698 840 798 176 697 838 799 767 698 767 698 838 799 840 798 839 801 840 798 200 800 200 800 840 798 838 799 835 795 840 798 199 796 199 796 840 798 839 801 176 697 770 702 838 799 838 799 770 702 843 802 177 701 841 803 770 702 770 702 841 803 843 802 842 805 843 802 201 804 201 804 843 802 841 803 838 799 843 802 200 800 200 800 843 802 842 805 177 701 773 706 841 803 841 803 773 706 846 806 178 705 844 807 773 706 773 706 844 807 846 806 845 809 846 806 202 808 202 808 846 806 844 807 841 803 846 806 201 804 201 804 846 806 845 809 178 705 776 710 844 807 844 807 776 710 849 810 179 709 847 811 776 710 776 710 847 811 849 810 848 813 849 810 203 812 203 812 849 810 847 811 844 807 849 810 202 808 202 808 849 810 848 813 179 709 779 714 847 811 847 811 779 714 852 814 180 713 850 815 779 714 779 714 850 815 852 814 851 817 852 814 204 816 204 816 852 814 850 815 847 811 852 814 203 812 203 812 852 814 851 817 180 713 782 718 850 815 850 815 782 718 855 818 181 717 853 819 782 718 782 718 853 819 855 818 854 821 855 818 205 820 205 820 855 818 853 819 850 815 855 818 204 816 204 816 855 818 854 821 181 717 785 722 853 819 853 819 785 722 858 822 182 721 856 823 785 722 785 722 856 823 858 822 857 825 858 822 206 824 206 824 858 822 856 823 853 819 858 822 205 820 205 820 858 822 857 825 182 721 788 726 856 823 856 823 788 726 861 826 183 725 859 827 788 726 788 726 859 827 861 826 860 829 861 826 207 828 207 828 861 826 859 827 856 823 861 826 206 824 206 824 861 826 860 829 183 725 791 730 859 827 859 827 791 730 864 830 184 729 862 831 791 730 791 730 862 831 864 830 863 833 864 830 208 832 208 832 864 830 862 831 859 827 864 830 207 828 207 828 864 830 863 833 184 729 794 734 862 831 862 831 794 734 867 834 185 733 865 835 794 734 794 734 865 835 867 834 866 837 867 834 209 836 209 836 867 834 865 835 862 831 867 834 208 832 208 832 867 834 866 837 185 733 797 738 865 835 865 835 797 738 870 838 186 737 868 839 797 738 797 738 868 839 870 838 869 841 870 838 210 840 210 840 870 838 868 839 865 835 870 838 209 836 209 836 870 838 869 841 186 737 800 742 868 839 868 839 800 742 873 842 187 741 871 843 800 742 800 742 871 843 873 842 872 845 873 842 211 844 211 844 873 842 871 843 868 839 873 842 210 840 210 840 873 842 872 845 187 741 803 746 871 843 871 843 803 746 876 846 188 745 874 847 803 746 803 746 874 847 876 846 875 849 876 846 212 848 212 848 876 846 874 847 871 843 876 846 211 844 211 844 876 846 875 849 188 745 806 750 874 847 874 847 806 750 879 850 189 749 877 851 806 750 806 750 877 851 879 850 878 853 879 850 213 852 213 852 879 850 877 851 874 847 879 850 212 848 212 848 879 850 878 853 189 749 809 754 877 851 877 851 809 754 882 854 190 753 880 855 809 754 809 754 880 855 882 854 881 857 882 854 214 856 214 856 882 854 880 855 877 851 882 854 213 852 213 852 882 854 881 857 190 753 812 758 880 855 880 855 812 758 885 858 191 757 883 859 812 758 812 758 883 859 885 858 884 861 885 858 215 860 215 860 885 858 883 859 880 855 885 858 214 856 214 856 885 858 884 861 191 757 814 862 883 859 883 859 814 862 887 863 168 864 818 865 814 866 814 866 818 865 887 863 886 868 887 863 192 867 192 867 887 863 818 869 883 859 887 863 215 860 215 860 887 863 886 870 192 773 817 772 890 872 890 872 817 772 891 871 193 771 888 873 817 772 817 772 888 873 891 871 889 875 891 871 217 874 217 874 891 871 888 873 890 872 891 871 216 876 216 876 891 871 889 875 193 771 821 777 888 873 888 873 821 777 894 877 194 776 892 878 821 777 821 777 892 878 894 877 893 880 894 877 218 879 218 879 894 877 892 878 888 873 894 877 217 874 217 874 894 877 893 880 194 776 824 781 892 878 892 878 824 781 897 881 195 780 895 882 824 781 824 781 895 882 897 881 896 884 897 881 219 883 219 883 897 881 895 882 892 878 897 881 218 879 218 879 897 881 896 884 195 780 827 785 895 882 895 882 827 785 900 885 196 784 898 886 827 785 827 785 898 886 900 885 899 888 900 885 220 887 220 887 900 885 898 886 895 882 900 885 219 883 219 883 900 885 899 888 196 784 830 789 898 886 898 886 830 789 903 889 197 788 901 890 830 789 830 789 901 890 903 889 902 892 903 889 221 891 221 891 903 889 901 890 898 886 903 889 220 887 220 887 903 889 902 892 197 788 833 793 901 890 901 890 833 793 906 893 198 792 904 894 833 793 833 793 904 894 906 893 905 896 906 893 222 895 222 895 906 893 904 894 901 890 906 893 221 891 221 891 906 893 905 896 198 792 836 797 904 894 904 894 836 797 909 897 199 796 907 898 836 797 836 797 907 898 909 897 908 900 909 897 223 899 223 899 909 897 907 898 904 894 909 897 222 895 222 895 909 897 908 900 199 796 839 801 907 898 907 898 839 801 912 901 200 800 910 902 839 801 839 801 910 902 912 901 911 904 912 901 224 903 224 903 912 901 910 902 907 898 912 901 223 899 223 899 912 901 911 904 200 800 842 805 910 902 910 902 842 805 915 905 201 804 913 906 842 805 842 805 913 906 915 905 914 908 915 905 225 907 225 907 915 905 913 906 910 902 915 905 224 903 224 903 915 905 914 908 201 804 845 809 913 906 913 906 845 809 918 909 202 808 916 910 845 809 845 809 916 910 918 909 917 912 918 909 226 911 226 911 918 909 916 910 913 906 918 909 225 907 225 907 918 909 917 912 202 808 848 813 916 910 916 910 848 813 921 913 203 812 919 914 848 813 848 813 919 914 921 913 920 916 921 913 227 915 227 915 921 913 919 914 916 910 921 913 226 911 226 911 921 913 920 916 203 812 851 817 919 914 919 914 851 817 924 917 204 816 922 918 851 817 851 817 922 918 924 917 923 920 924 917 228 919 228 919 924 917 922 918 919 914 924 917 227 915 227 915 924 917 923 920 204 816 854 821 922 918 922 918 854 821 927 921 205 820 925 922 854 821 854 821 925 922 927 921 926 924 927 921 229 923 229 923 927 921 925 922 922 918 927 921 228 919 228 919 927 921 926 924 205 820 857 825 925 922 925 922 857 825 930 925 206 824 928 926 857 825 857 825 928 926 930 925 929 928 930 925 230 927 230 927 930 925 928 926 925 922 930 925 229 923 229 923 930 925 929 928 206 824 860 829 928 926 928 926 860 829 933 929 207 828 931 930 860 829 860 829 931 930 933 929 932 932 933 929 231 931 231 931 933 929 931 930 928 926 933 929 230 927 230 927 933 929 932 932 207 828 863 833 931 930 931 930 863 833 936 933 208 832 934 934 863 833 863 833 934 934 936 933 935 936 936 933 232 935 232 935 936 933 934 934 931 930 936 933 231 931 231 931 936 933 935 936 208 832 866 837 934 934 934 934 866 837 939 937 209 836 937 938 866 837 866 837 937 938 939 937 938 940 939 937 233 939 233 939 939 937 937 938 934 934 939 937 232 935 232 935 939 937 938 940 209 836 869 841 937 938 937 938 869 841 942 941 210 840 940 942 869 841 869 841 940 942 942 941 941 944 942 941 234 943 234 943 942 941 940 942 937 938 942 941 233 939 233 939 942 941 941 944 210 840 872 845 940 942 940 942 872 845 945 945 211 844 943 946 872 845 872 845 943 946 945 945 944 948 945 945 235 947 235 947 945 945 943 946 940 942 945 945 234 943 234 943 945 945 944 948 211 844 875 849 943 946 943 946 875 849 948 949 212 848 946 950 875 849 875 849 946 950 948 949 947 952 948 949 236 951 236 951 948 949 946 950 943 946 948 949 235 947 235 947 948 949 947 952 212 848 878 853 946 950 946 950 878 853 951 953 213 852 949 954 878 853 878 853 949 954 951 953 950 956 951 953 237 955 237 955 951 953 949 954 946 950 951 953 236 951 236 951 951 953 950 956 213 852 881 857 949 954 949 954 881 857 954 957 214 856 952 958 881 857 881 857 952 958 954 957 953 960 954 957 238 959 238 959 954 957 952 958 949 954 954 957 237 955 237 955 954 957 953 960 214 856 884 861 952 958 952 958 884 861 957 961 215 860 955 962 884 861 884 861 955 962 957 961 956 964 957 961 239 963 239 963 957 961 955 962 952 958 957 961 238 959 238 959 957 961 956 964 215 860 886 965 955 962 955 962 886 965 959 966 192 967 890 968 886 969 886 969 890 968 959 966 958 971 959 966 216 970 216 970 959 966 890 972 955 962 959 966 239 963 239 963 959 966 958 973 216 876 889 875 962 975 962 975 889 875 963 974 217 874 960 976 889 875 889 875 960 976 963 974 961 978 963 974 241 977 241 977 963 974 960 976 962 975 963 974 240 979 240 979 963 974 961 978 217 874 893 880 960 976 960 976 893 880 966 980 218 879 964 981 893 880 893 880 964 981 966 980 965 983 966 980 242 982 242 982 966 980 964 981 960 976 966 980 241 977 241 977 966 980 965 983 218 879 896 884 964 981 964 981 896 884 969 984 219 883 967 985 896 884 896 884 967 985 969 984 968 987 969 984 243 986 243 986 969 984 967 985 964 981 969 984 242 982 242 982 969 984 968 987 219 883 899 888 967 985 967 985 899 888 972 988 220 887 970 989 899 888 899 888 970 989 972 988 971 991 972 988 244 990 244 990 972 988 970 989 967 985 972 988 243 986 243 986 972 988 971 991 220 887 902 892 970 989 970 989 902 892 975 992 221 891 973 993 902 892 902 892 973 993 975 992 974 995 975 992 245 994 245 994 975 992 973 993 970 989 975 992 244 990 244 990 975 992 974 995 221 891 905 896 973 993 973 993 905 896 978 996 222 895 976 997 905 896 905 896 976 997 978 996 977 999 978 996 246 998 246 998 978 996 976 997 973 993 978 996 245 994 245 994 978 996 977 999 222 895 908 900 976 997 976 997 908 900 981 1000 223 899 979 1001 908 900 908 900 979 1001 981 1000 980 1003 981 1000 247 1002 247 1002 981 1000 979 1001 976 997 981 1000 246 998 246 998 981 1000 980 1003 223 899 911 904 979 1001 979 1001 911 904 984 1004 224 903 982 1005 911 904 911 904 982 1005 984 1004 983 1007 984 1004 248 1006 248 1006 984 1004 982 1005 979 1001 984 1004 247 1002 247 1002 984 1004 983 1007 224 903 914 908 982 1005 982 1005 914 908 987 1008 225 907 985 1009 914 908 914 908 985 1009 987 1008 986 1011 987 1008 249 1010 249 1010 987 1008 985 1009 982 1005 987 1008 248 1006 248 1006 987 1008 986 1011 225 907 917 912 985 1009 985 1009 917 912 990 1012 226 911 988 1013 917 912 917 912 988 1013 990 1012 989 1015 990 1012 250 1014 250 1014 990 1012 988 1013 985 1009 990 1012 249 1010 249 1010 990 1012 989 1015 226 911 920 916 988 1013 988 1013 920 916 993 1016 227 915 991 1017 920 916 920 916 991 1017 993 1016 992 1019 993 1016 251 1018 251 1018 993 1016 991 1017 988 1013 993 1016 250 1014 250 1014 993 1016 992 1019 227 915 923 920 991 1017 991 1017 923 920 996 1020 228 919 994 1021 923 920 923 920 994 1021 996 1020 995 1023 996 1020 252 1022 252 1022 996 1020 994 1021 991 1017 996 1020 251 1018 251 1018 996 1020 995 1023 228 919 926 924 994 1021 994 1021 926 924 999 1024 229 923 997 1025 926 924 926 924 997 1025 999 1024 998 1027 999 1024 253 1026 253 1026 999 1024 997 1025 994 1021 999 1024 252 1022 252 1022 999 1024 998 1027 229 923 929 928 997 1025 997 1025 929 928 1002 1028 230 927 1000 1029 929 928 929 928 1000 1029 1002 1028 1001 1031 1002 1028 254 1030 254 1030 1002 1028 1000 1029 997 1025 1002 1028 253 1026 253 1026 1002 1028 1001 1031 230 927 932 932 1000 1029 1000 1029 932 932 1005 1032 231 931 1003 1033 932 932 932 932 1003 1033 1005 1032 1004 1035 1005 1032 255 1034 255 1034 1005 1032 1003 1033 1000 1029 1005 1032 254 1030 254 1030 1005 1032 1004 1035 231 931 935 936 1003 1033 1003 1033 935 936 1008 1036 232 935 1006 1037 935 936 935 936 1006 1037 1008 1036 1007 1039 1008 1036 256 1038 256 1038 1008 1036 1006 1037 1003 1033 1008 1036 255 1034 255 1034 1008 1036 1007 1039 232 935 938 940 1006 1037 1006 1037 938 940 1011 1040 233 939 1009 1041 938 940 938 940 1009 1041 1011 1040 1010 1043 1011 1040 257 1042 257 1042 1011 1040 1009 1041 1006 1037 1011 1040 256 1038 256 1038 1011 1040 1010 1043 233 939 941 944 1009 1041 1009 1041 941 944 1014 1044 234 943 1012 1045 941 944 941 944 1012 1045 1014 1044 1013 1047 1014 1044 258 1046 258 1046 1014 1044 1012 1045 1009 1041 1014 1044 257 1042 257 1042 1014 1044 1013 1047 234 943 944 948 1012 1045 1012 1045 944 948 1017 1048 235 947 1015 1049 944 948 944 948 1015 1049 1017 1048 1016 1051 1017 1048 259 1050 259 1050 1017 1048 1015 1049 1012 1045 1017 1048 258 1046 258 1046 1017 1048 1016 1051 235 947 947 952 1015 1049 1015 1049 947 952 1020 1052 236 951 1018 1053 947 952 947 952 1018 1053 1020 1052 1019 1055 1020 1052 260 1054 260 1054 1020 1052 1018 1053 1015 1049 1020 1052 259 1050 259 1050 1020 1052 1019 1055 236 951 950 956 1018 1053 1018 1053 950 956 1023 1056 237 955 1021 1057 950 956 950 956 1021 1057 1023 1056 1022 1059 1023 1056 261 1058 261 1058 1023 1056 1021 1057 1018 1053 1023 1056 260 1054 260 1054 1023 1056 1022 1059 237 955 953 960 1021 1057 1021 1057 953 960 1026 1060 238 959 1024 1061 953 960 953 960 1024 1061 1026 1060 1025 1063 1026 1060 262 1062 262 1062 1026 1060 1024 1061 1021 1057 1026 1060 261 1058 261 1058 1026 1060 1025 1063 238 959 956 964 1024 1061 1024 1061 956 964 1029 1064 239 963 1027 1065 956 964 956 964 1027 1065 1029 1064 1028 1067 1029 1064 263 1066 263 1066 1029 1064 1027 1065 1024 1061 1029 1064 262 1062 262 1062 1029 1064 1028 1067 239 963 958 1068 1027 1065 1027 1065 958 1068 1031 1069 216 1070 962 1071 958 1072 958 1072 962 1071 1031 1069 1030 1074 1031 1069 240 1073 240 1073 1031 1069 962 1075 1027 1065 1031 1069 263 1066 263 1066 1031 1069 1030 1076 240 979 961 978 1034 1078 1034 1078 961 978 1035 1077 241 977 1032 1079 961 978 961 978 1032 1079 1035 1077 1033 1081 1035 1077 265 1080 265 1080 1035 1077 1032 1079 1034 1078 1035 1077 264 1082 264 1082 1035 1077 1033 1081 241 977 965 983 1032 1079 1032 1079 965 983 1038 1083 242 982 1036 1084 965 983 965 983 1036 1084 1038 1083 1037 1086 1038 1083 266 1085 266 1085 1038 1083 1036 1084 1032 1079 1038 1083 265 1080 265 1080 1038 1083 1037 1086 242 982 968 987 1036 1084 1036 1084 968 987 1041 1087 243 986 1039 1088 968 987 968 987 1039 1088 1041 1087 1040 1090 1041 1087 267 1089 267 1089 1041 1087 1039 1088 1036 1084 1041 1087 266 1085 266 1085 1041 1087 1040 1090 243 986 971 991 1039 1088 1039 1088 971 991 1044 1091 244 990 1042 1092 971 991 971 991 1042 1092 1044 1091 1043 1094 1044 1091 268 1093 268 1093 1044 1091 1042 1092 1039 1088 1044 1091 267 1089 267 1089 1044 1091 1043 1094 244 990 974 995 1042 1092 1042 1092 974 995 1047 1095 245 994 1045 1096 974 995 974 995 1045 1096 1047 1095 1046 1098 1047 1095 269 1097 269 1097 1047 1095 1045 1096 1042 1092 1047 1095 268 1093 268 1093 1047 1095 1046 1098 245 994 977 999 1045 1096 1045 1096 977 999 1050 1099 246 998 1048 1100 977 999 977 999 1048 1100 1050 1099 1049 1102 1050 1099 270 1101 270 1101 1050 1099 1048 1100 1045 1096 1050 1099 269 1097 269 1097 1050 1099 1049 1102 246 998 980 1003 1048 1100 1048 1100 980 1003 1053 1103 247 1002 1051 1104 980 1003 980 1003 1051 1104 1053 1103 1052 1106 1053 1103 271 1105 271 1105 1053 1103 1051 1104 1048 1100 1053 1103 270 1101 270 1101 1053 1103 1052 1106 247 1002 983 1007 1051 1104 1051 1104 983 1007 1056 1107 248 1006 1054 1108 983 1007 983 1007 1054 1108 1056 1107 1055 1110 1056 1107 272 1109 272 1109 1056 1107 1054 1108 1051 1104 1056 1107 271 1105 271 1105 1056 1107 1055 1110 248 1006 986 1011 1054 1108 1054 1108 986 1011 1059 1111 249 1010 1057 1112 986 1011 986 1011 1057 1112 1059 1111 1058 1114 1059 1111 273 1113 273 1113 1059 1111 1057 1112 1054 1108 1059 1111 272 1109 272 1109 1059 1111 1058 1114 249 1010 989 1015 1057 1112 1057 1112 989 1015 1062 1115 250 1014 1060 1116 989 1015 989 1015 1060 1116 1062 1115 1061 1118 1062 1115 274 1117 274 1117 1062 1115 1060 1116 1057 1112 1062 1115 273 1113 273 1113 1062 1115 1061 1118 250 1014 992 1019 1060 1116 1060 1116 992 1019 1065 1119 251 1018 1063 1120 992 1019 992 1019 1063 1120 1065 1119 1064 1122 1065 1119 275 1121 275 1121 1065 1119 1063 1120 1060 1116 1065 1119 274 1117 274 1117 1065 1119 1064 1122 251 1018 995 1023 1063 1120 1063 1120 995 1023 1068 1123 252 1022 1066 1124 995 1023 995 1023 1066 1124 1068 1123 1067 1126 1068 1123 276 1125 276 1125 1068 1123 1066 1124 1063 1120 1068 1123 275 1121 275 1121 1068 1123 1067 1126 252 1022 998 1027 1066 1124 1066 1124 998 1027 1071 1127 253 1026 1069 1128 998 1027 998 1027 1069 1128 1071 1127 1070 1130 1071 1127 277 1129 277 1129 1071 1127 1069 1128 1066 1124 1071 1127 276 1125 276 1125 1071 1127 1070 1130 253 1026 1001 1031 1069 1128 1069 1128 1001 1031 1074 1131 254 1030 1072 1132 1001 1031 1001 1031 1072 1132 1074 1131 1073 1134 1074 1131 278 1133 278 1133 1074 1131 1072 1132 1069 1128 1074 1131 277 1129 277 1129 1074 1131 1073 1134 254 1030 1004 1035 1072 1132 1072 1132 1004 1035 1077 1135 255 1034 1075 1136 1004 1035 1004 1035 1075 1136 1077 1135 1076 1138 1077 1135 279 1137 279 1137 1077 1135 1075 1136 1072 1132 1077 1135 278 1133 278 1133 1077 1135 1076 1138 255 1034 1007 1039 1075 1136 1075 1136 1007 1039 1080 1139 256 1038 1078 1140 1007 1039 1007 1039 1078 1140 1080 1139 1079 1142 1080 1139 280 1141 280 1141 1080 1139 1078 1140 1075 1136 1080 1139 279 1137 279 1137 1080 1139 1079 1142 256 1038 1010 1043 1078 1140 1078 1140 1010 1043 1083 1143 257 1042 1081 1144 1010 1043 1010 1043 1081 1144 1083 1143 1082 1146 1083 1143 281 1145 281 1145 1083 1143 1081 1144 1078 1140 1083 1143 280 1141 280 1141 1083 1143 1082 1146 257 1042 1013 1047 1081 1144 1081 1144 1013 1047 1086 1147 258 1046 1084 1148 1013 1047 1013 1047 1084 1148 1086 1147 1085 1150 1086 1147 282 1149 282 1149 1086 1147 1084 1148 1081 1144 1086 1147 281 1145 281 1145 1086 1147 1085 1150 258 1046 1016 1051 1084 1148 1084 1148 1016 1051 1089 1151 259 1050 1087 1152 1016 1051 1016 1051 1087 1152 1089 1151 1088 1154 1089 1151 283 1153 283 1153 1089 1151 1087 1152 1084 1148 1089 1151 282 1149 282 1149 1089 1151 1088 1154 259 1050 1019 1055 1087 1152 1087 1152 1019 1055 1092 1155 260 1054 1090 1156 1019 1055 1019 1055 1090 1156 1092 1155 1091 1158 1092 1155 284 1157 284 1157 1092 1155 1090 1156 1087 1152 1092 1155 283 1153 283 1153 1092 1155 1091 1158 260 1054 1022 1059 1090 1156 1090 1156 1022 1059 1095 1159 261 1058 1093 1160 1022 1059 1022 1059 1093 1160 1095 1159 1094 1162 1095 1159 285 1161 285 1161 1095 1159 1093 1160 1090 1156 1095 1159 284 1157 284 1157 1095 1159 1094 1162 261 1058 1025 1063 1093 1160 1093 1160 1025 1063 1098 1163 262 1062 1096 1164 1025 1063 1025 1063 1096 1164 1098 1163 1097 1166 1098 1163 286 1165 286 1165 1098 1163 1096 1164 1093 1160 1098 1163 285 1161 285 1161 1098 1163 1097 1166 262 1062 1028 1067 1096 1164 1096 1164 1028 1067 1101 1167 263 1066 1099 1168 1028 1067 1028 1067 1099 1168 1101 1167 1100 1170 1101 1167 287 1169 287 1169 1101 1167 1099 1168 1096 1164 1101 1167 286 1165 286 1165 1101 1167 1100 1170 263 1066 1030 1171 1099 1168 1099 1168 1030 1171 1103 1172 240 1173 1034 1174 1030 1175 1030 1175 1034 1174 1103 1172 1102 1177 1103 1172 264 1176 264 1176 1103 1172 1034 1178 1099 1168 1103 1172 287 1169 287 1169 1103 1172 1102 1179 264 1082 1033 1081 1105 1181 1105 1181 1033 1081 1106 1180 265 1080 1104 1182 1033 1081 1033 1081 1104 1182 1106 1180 288 1184 1106 1180 1 1183 1 1183 1106 1180 1104 1185 1105 1187 1106 1180 0 1186 0 1186 1106 1180 288 1188 265 1080 1037 1086 1104 1190 1104 1190 1037 1086 1108 1189 266 1085 1107 1191 1037 1086 1037 1086 1107 1191 1108 1189 293 1193 1108 1189 2 1192 2 1192 1108 1189 1107 1194 1104 1196 1108 1189 1 1195 1 1195 1108 1189 293 1197 266 1085 1040 1090 1107 1199 1107 1199 1040 1090 1110 1198 267 1089 1109 1200 1040 1090 1040 1090 1109 1200 1110 1198 297 1202 1110 1198 3 1201 3 1201 1110 1198 1109 1203 1107 1205 1110 1198 2 1204 2 1204 1110 1198 297 1206 267 1089 1043 1094 1109 1208 1109 1208 1043 1094 1112 1207 268 1093 1111 1209 1043 1094 1043 1094 1111 1209 1112 1207 301 1211 1112 1207 4 1210 4 1210 1112 1207 1111 1212 1109 1214 1112 1207 3 1213 3 1213 1112 1207 301 1215 268 1093 1046 1098 1111 1217 1111 1217 1046 1098 1114 1216 269 1097 1113 1218 1046 1098 1046 1098 1113 1218 1114 1216 305 1220 1114 1216 5 1219 5 1219 1114 1216 1113 1221 1111 1223 1114 1216 4 1222 4 1222 1114 1216 305 1224 269 1097 1049 1102 1113 1226 1113 1226 1049 1102 1116 1225 270 1101 1115 1227 1049 1102 1049 1102 1115 1227 1116 1225 309 1229 1116 1225 6 1228 6 1228 1116 1225 1115 1230 1113 1232 1116 1225 5 1231 5 1231 1116 1225 309 1233 270 1101 1052 1106 1115 1235 1115 1235 1052 1106 1118 1234 271 1105 1117 1236 1052 1106 1052 1106 1117 1236 1118 1234 313 1238 1118 1234 7 1237 7 1237 1118 1234 1117 1239 1115 1241 1118 1234 6 1240 6 1240 1118 1234 313 1242 271 1105 1055 1110 1117 1244 1117 1244 1055 1110 1120 1243 272 1109 1119 1245 1055 1110 1055 1110 1119 1245 1120 1243 317 1247 1120 1243 8 1246 8 1246 1120 1243 1119 1248 1117 1250 1120 1243 7 1249 7 1249 1120 1243 317 1251 272 1109 1058 1114 1119 1253 1119 1253 1058 1114 1122 1252 273 1113 1121 1254 1058 1114 1058 1114 1121 1254 1122 1252 321 1256 1122 1252 9 1255 9 1255 1122 1252 1121 1257 1119 1259 1122 1252 8 1258 8 1258 1122 1252 321 1260 273 1113 1061 1118 1121 1262 1121 1262 1061 1118 1124 1261 274 1117 1123 1263 1061 1118 1061 1118 1123 1263 1124 1261 325 1265 1124 1261 10 1264 10 1264 1124 1261 1123 1266 1121 1268 1124 1261 9 1267 9 1267 1124 1261 325 1269 274 1117 1064 1122 1123 1271 1123 1271 1064 1122 1126 1270 275 1121 1125 1272 1064 1122 1064 1122 1125 1272 1126 1270 329 1274 1126 1270 11 1273 11 1273 1126 1270 1125 1275 1123 1277 1126 1270 10 1276 10 1276 1126 1270 329 1278 275 1121 1067 1126 1125 1280 1125 1280 1067 1126 1128 1279 276 1125 1127 1281 1067 1126 1067 1126 1127 1281 1128 1279 333 1283 1128 1279 12 1282 12 1282 1128 1279 1127 1284 1125 1286 1128 1279 11 1285 11 1285 1128 1279 333 1287 276 1125 1070 1130 1127 1289 1127 1289 1070 1130 1130 1288 277 1129 1129 1290 1070 1130 1070 1130 1129 1290 1130 1288 337 1292 1130 1288 13 1291 13 1291 1130 1288 1129 1293 1127 1295 1130 1288 12 1294 12 1294 1130 1288 337 1296 277 1129 1073 1134 1129 1298 1129 1298 1073 1134 1132 1297 278 1133 1131 1299 1073 1134 1073 1134 1131 1299 1132 1297 341 1301 1132 1297 14 1300 14 1300 1132 1297 1131 1302 1129 1304 1132 1297 13 1303 13 1303 1132 1297 341 1305 278 1133 1076 1138 1131 1307 1131 1307 1076 1138 1134 1306 279 1137 1133 1308 1076 1138 1076 1138 1133 1308 1134 1306 345 1310 1134 1306 15 1309 15 1309 1134 1306 1133 1311 1131 1313 1134 1306 14 1312 14 1312 1134 1306 345 1314 279 1137 1079 1142 1133 1316 1133 1316 1079 1142 1136 1315 280 1141 1135 1317 1079 1142 1079 1142 1135 1317 1136 1315 349 1319 1136 1315 16 1318 16 1318 1136 1315 1135 1320 1133 1322 1136 1315 15 1321 15 1321 1136 1315 349 1323 280 1141 1082 1146 1135 1325 1135 1325 1082 1146 1138 1324 281 1145 1137 1326 1082 1146 1082 1146 1137 1326 1138 1324 353 1328 1138 1324 17 1327 17 1327 1138 1324 1137 1329 1135 1331 1138 1324 16 1330 16 1330 1138 1324 353 1332 281 1145 1085 1150 1137 1334 1137 1334 1085 1150 1140 1333 282 1149 1139 1335 1085 1150 1085 1150 1139 1335 1140 1333 357 1337 1140 1333 18 1336 18 1336 1140 1333 1139 1338 1137 1340 1140 1333 17 1339 17 1339 1140 1333 357 1341 282 1149 1088 1154 1139 1343 1139 1343 1088 1154 1142 1342 283 1153 1141 1344 1088 1154 1088 1154 1141 1344 1142 1342 361 1346 1142 1342 19 1345 19 1345 1142 1342 1141 1347 1139 1349 1142 1342 18 1348 18 1348 1142 1342 361 1350 283 1153 1091 1158 1141 1352 1141 1352 1091 1158 1144 1351 284 1157 1143 1353 1091 1158 1091 1158 1143 1353 1144 1351 365 1355 1144 1351 20 1354 20 1354 1144 1351 1143 1356 1141 1358 1144 1351 19 1357 19 1357 1144 1351 365 1359 284 1157 1094 1162 1143 1361 1143 1361 1094 1162 1146 1360 285 1161 1145 1362 1094 1162 1094 1162 1145 1362 1146 1360 369 1364 1146 1360 21 1363 21 1363 1146 1360 1145 1365 1143 1367 1146 1360 20 1366 20 1366 1146 1360 369 1368 285 1161 1097 1166 1145 1370 1145 1370 1097 1166 1148 1369 286 1165 1147 1371 1097 1166 1097 1166 1147 1371 1148 1369 373 1373 1148 1369 22 1372 22 1372 1148 1369 1147 1374 1145 1376 1148 1369 21 1375 21 1375 1148 1369 373 1377 286 1165 1100 1170 1147 1379 1147 1379 1100 1170 1150 1378 287 1169 1149 1380 1100 1170 1100 1170 1149 1380 1150 1378 377 1382 1150 1378 23 1381 23 1381 1150 1378 1149 1383 1147 1385 1150 1378 22 1384 22 1384 1150 1378 377 1386 287 1169 1102 1387 1149 1389 1149 1389 1102 1387 1151 1388 264 1390 1105 1391 1102 1392 1102 1392 1105 1391 1151 1388 381 1394 1151 1388 0 1393 0 1393 1151 1388 1105 1395 1149 1397 1151 1388 23 1396 23 1396 1151 1388 381 1398</p>
+ </triangles>
+ </mesh>
+ <extra>
+ <technique profile="MAYA">
+ <double_sided>1</double_sided>
+ </technique>
+ </extra>
+ </geometry>
+ </library_geometries>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="Torus">
+ <node id="_Torus" name="Torus" type="NODE">
+ <rotate sid="rotateY">0 1 0 0</rotate>
+ <rotate sid="rotateX">1 0 0 0</rotate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <instance_geometry url="#Torus">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert2SG" target="#lambert2"/>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ </node>
+ <extra>
+ <technique profile="FCOLLADA">
+ <start_time>0.041666</start_time>
+ <end_time>2</end_time>
+ </technique>
+ </extra>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_physics_scene url="#MayaNativePhysicsScene"/>
+ <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>
diff --git a/build_instructions b/build_instructions
new file mode 100644
index 00000000..f6bf3997
--- /dev/null
+++ b/build_instructions
@@ -0,0 +1,81 @@
+1. Scope
+
+This document contains the instructions to build Qt3D Studio
+
+
+2. What You Need
+
+Clone the 3D Studio repository from
+
+https://codereview.qt-project.org/#/admin/projects/qt3dstudio/qt3dstudio
+
+Additionally Qt 3D Studio Editor requires Boost library and optionally, if FBX assets
+are used, also the FBX SDK.
+
+2.1 List of tested 3rd party libraries and versions
+
+ Boost 1.65.0
+ FBX SDK 2016.1.2
+
+
+3. Environment setup
+
+3.1 Windows 10
+
+You need Windows build tools. Download tools from
+https://go.microsoft.com/fwlink/?LinkId=691126 .
+
+Do a custom installation and select ATL/MFC SDK. For debugging the Qt 3D Studio,
+you need to select also Windows SDK.
+
+Download precompiled boost binaries from www.boost.org and extract them to:
+<path to repo root>/src/3rdparty/boost/1.65.0
+
+Download the Windows version installer of FBX SDK 2016.1.2 from link:
+http://download.autodesk.com/us/fbx_release_older/2016.1.2/fbx20161_2_fbxsdk_vs2015_win.exe
+Install the SDK and set FBXSDK environment variable to point to
+<installation directory>/Autodesk/FBX SDK/2016.1.2.
+Or copy the folder to <path to repo root>/src/3rdparty/FBX
+
+3.2 macOS
+
+Boost can be installed on macOS with HomeBrew package manager.
+To install Homebrew run following command line in terminal:
+/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+And then use the following to install boost:
+brew install boost
+
+Download the macOS version of FBX SDK 2016.1.2 from link:
+http://download.autodesk.com/us/fbx_release_older/2016.1.2/fbx20161_2_fbxsdk_clang_mac.pkg.tgz
+Install the SDK. By default <installation directory> on macOS is /Applications. Set FBXSDK
+environment variable point to <installation directory>/Autodesk/FBX SDK/2016.1.2.
+Or copy the folder to <path to repo root>/src/3rdparty/FBX
+
+3.3 Linux
+
+TBDL
+
+
+4. Setup project in Qt Creator
+
+Open <path to repo root>\qt3dstudio.pro in Qt Creator.
+
+Go to "Projects" view. Select desired Build & Run configuration (either
+Release, or Debug). Tested configurations:
+
+ Windows 10: Qt 5.9.0 MSVC2015_64bit
+ macOS: Qt 5.9.0 clang_64
+ Linux: TBDL
+
+Under "Build steps" click "Add Build Step" and select "Make". To make
+arguments type "install". This will move the qmlviewer plugin to correct
+place under Qt.
+
+
+5. Running Qt3DStudio
+
+Run subproject Q3DStudio under Authoring
+
+Quick Viewer example: Open <path to ndd
+repo>\examples\qmldynamickeyframes\qmldynamickeyframes.pro in Qt Creator and
+build it. Done!
diff --git a/config.tests/fbx/fbx.pro b/config.tests/fbx/fbx.pro
new file mode 100644
index 00000000..fec56e16
--- /dev/null
+++ b/config.tests/fbx/fbx.pro
@@ -0,0 +1,13 @@
+SOURCES += main.cpp
+
+win32-msvc {
+#workaround for debug and release configurations where the test system
+#generates only single Makefile for projects under config.tests and the compiler flags
+#contain -MDd also for release. The dynamic lib version works for both cases.
+LIBS-= -llibfbxsdk-md
+LIBS+= -llibfbxsdk
+}
+
+linux {
+LIBS += -ldl
+}
diff --git a/config.tests/fbx/main.cpp b/config.tests/fbx/main.cpp
new file mode 100644
index 00000000..e976b180
--- /dev/null
+++ b/config.tests/fbx/main.cpp
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <fbxsdk.h>
+
+int main(int, char **)
+{
+ FbxManager *manager = FbxManager::Create();
+ FbxScene::Create(manager, "scene");
+ manager->Destroy();
+
+ return 0;
+}
+
diff --git a/configure.json b/configure.json
new file mode 100644
index 00000000..2f3e2b16
--- /dev/null
+++ b/configure.json
@@ -0,0 +1,5 @@
+{
+ "subconfigs": [
+ "src/Authoring"
+ ]
+}
diff --git a/doc/doc.pro b/doc/doc.pro
new file mode 100644
index 00000000..d98af320
--- /dev/null
+++ b/doc/doc.pro
@@ -0,0 +1,6 @@
+TEMPLATE = aux
+
+build_online_docs: \
+ QMAKE_DOCS = $$PWD/online/qt3dstudio.qdocconf
+else: \
+ QMAKE_DOCS = $$PWD/qt3dstudio.qdocconf
diff --git a/doc/online/qt3dstudio.qdocconf b/doc/online/qt3dstudio.qdocconf
new file mode 100644
index 00000000..90c29719
--- /dev/null
+++ b/doc/online/qt3dstudio.qdocconf
@@ -0,0 +1,2 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults-online-commercial.qdocconf)
+include(../qt3dstudio-project.qdocconf)
diff --git a/doc/qt3dstudio-project.qdocconf b/doc/qt3dstudio-project.qdocconf
new file mode 100644
index 00000000..130eb14c
--- /dev/null
+++ b/doc/qt3dstudio-project.qdocconf
@@ -0,0 +1,54 @@
+project = Qt3DStudio
+description = Qt 3D Studio Reference Manual
+version = $QT_VERSION
+
+sources.fileextensions = "*.qdoc *.html"
+sourcedirs = ./src \
+ ../src/Viewer
+
+headerdirs = ../src/Viewer
+
+# TODO: Move images to doc/images
+imagedirs = ./src/images
+
+depends = qtcore qtgui qtwidgets qtqml qtquick qtmultimedia qtdoc
+
+qhp.projects = Qt3DStudio
+
+qhp.Qt3DStudio.file = qt3dstudio.qhp
+qhp.Qt3DStudio.namespace = io.qt.qt3dstudio.$QT_VERSION_TAG
+qhp.Qt3DStudio.virtualFolder = qt3dstudio
+qhp.Qt3DStudio.indexTitle = Qt 3D Studio
+qhp.Qt3DStudio.indexRoot =
+
+qhp.Qt3DStudio.filterAttributes = qt3dstudio $QT_VERSION
+qhp.Qt3DStudio.customFilters.Qt.name = Qt3DStudio $QT_VERSION
+qhp.Qt3DStudio.customFilters.Qt.filterAttributes = qt3dstudio $QT_VERSION
+
+qhp.Qt3DStudio.subprojects = manual qmltypes classes
+qhp.Qt3DStudio.subprojects.manual.title = Qt 3D Studio
+qhp.Qt3DStudio.subprojects.manual.indexTitle = Qt 3D Studio TOC
+qhp.Qt3DStudio.subprojects.manual.type = manual
+
+qhp.Qt3DStudio.subprojects.qmltypes.title = QML Types
+qhp.Qt3DStudio.subprojects.qmltypes.indexTitle = Qt 3D Studio QML Types
+qhp.Qt3DStudio.subprojects.qmltypes.selectors = qmltype
+qhp.Qt3DStudio.subprojects.qmltypes.sortPages = true
+
+qhp.Qt3DStudio.subprojects.classes.title = C++ Classes
+qhp.Qt3DStudio.subprojects.classes.indexTitle = Qt 3D Studio C++ Classes
+qhp.Qt3DStudio.subprojects.classes.selectors = class fake:headerfile
+qhp.Qt3DStudio.subprojects.classes.sortPages = true
+
+
+# Add an .html file with sidebar content, used in the online style
+#HTML.stylesheets += style/qt5-sidebar.html
+
+# ensure all images are included
+#HTML.extraimages += ./src/static/Runtime-AODistances.jpg
+#qhp.Qt3DStudio.extraimages += ./src/static/Runtime-AODistances.jpg
+
+navigation.homepage = Qt 3D Studio
+navigation.cppclassespage = Qt 3D Studio C++ Classes
+navigation.qmltypespage = Qt 3D Studio QML Types
+buildversion = "Qt 3D Studio $QT_VER Manual"
diff --git a/doc/qt3dstudio.qdocconf b/doc/qt3dstudio.qdocconf
new file mode 100644
index 00000000..ae433164
--- /dev/null
+++ b/doc/qt3dstudio.qdocconf
@@ -0,0 +1,2 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include(qt3dstudio-project.qdocconf)
diff --git a/doc/src/00-concepts.qdoc b/doc/src/00-concepts.qdoc
new file mode 100644
index 00000000..0fbad4d4
--- /dev/null
+++ b/doc/src/00-concepts.qdoc
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\keyword Qt 3D Studio
+\title Qt 3D Studio Index
+\page index.html
+
+\section1 Table of Contents
+
+\list
+ \li \l {Getting started}
+ \li \l {Studio Index}{Studio}
+ \li \l {Viewer Index}{Viewer}
+ \li \l {QML API}{QML API Reference}
+ \li \l {C++ API}{C++ API Reference}
+ \li \l {Runtime}
+ \li \l {File Formats}
+ \omit
+ TODO: Needs to be checked. Maybe a rewrite, or just remove it all.
+ \li \l {Integrating with Qt 3D Studio}
+ \endomit
+ \li \l {Best Practices}
+ \omit
+ \li \l {Copyright Notices}
+ \endomit
+\endlist
+
+\section1 Applications
+
+The Qt 3D Studio suite includes:
+
+\section2 Studio
+
+\image studio_128.png
+
+An authoring tool for creating interactive 3D presentations and applications. Studio is exclusively
+available for Windows PCs.
+
+\section2 Viewer
+
+\image viewer_128.png
+
+A runtime player to test and deploy interfaces created in Studio. The Viewer is currently available
+for PC, with more devices planned.
+
+\section1 Concepts
+
+\section2 Project
+
+A \e{\"project\"} is simply a folder on your computer holding all the art and other assets needed
+for your application. You can create a \e project by creating folders on your favorite OS, or you
+can also have a template project created for you (with suggested folders for organization) from
+\l Studio application.
+
+\section2 Application
+
+Your \e{\"application\"} is the entry point of your project. It is represented by a single \c{.uia}
+file at the root of your project folder. This file references the presentation and
+sub-presentations in your project. The \e application is what is displayed by the \l Viewer.
+
+\omit
+TODO: To be updated for the open source release. Not really needed or even usable now.
+\e{Learn more about the file format for an application in}
+\l{file-formats-uia.html}{The .uia File Format}.
+\endomit
+
+\section2 Presentation
+
+Artists use \l Studio to create \e{presentation} files, represented by \c{.uip} files in your
+project. A presentation has one or more \e{layers} composited to the screen, comprised of 2D and
+3D assets created in other applications.
+
+Each application can only have one main presentation shown on screen (specified by the \c{.uia})
+but this presentation may reference other \e{sub-presentations}, either on flat layers or as images
+and textures drawn in a scene.
+
+\e{Learn more about creating presentations in the reference for}
+\l{Studio Index}{Studio application}.
+
+\section2 QML
+
+Additional functionality can be built on top of the Qt 3D Studio presentations with QML by
+incorporating applications or presentations into QML with the \l Studio3D element.
+
+\e{Learn more in}
+\l{QML API}{QML API Reference}.
+
+\section2 Layer
+
+A single \l Studio presentation combines one or more \e{layers}. The visual result of each \e layer
+comes from rendering a 3D scene, 2D scene (via an orthographic camera), or sub-presentation. Layers
+are then composited with items on upper layers drawing on top of the content on lower layers.
+
+\e{Learn more about the properties of layers in}
+\l{studio-inspector-palette.html#layer-properties}{Layer Properties}.
+
+\section2 Slide
+
+A \l Studio presentation combines 3D assets with animations and \e{slides}. Slides provide visual
+variations within the presentation.
+
+\e{Learn more about slides in}
+\l{studio-slide-palette.html}{Slide Palette}.
+
+*/
diff --git a/doc/src/03-studio/0-menu.qdoc b/doc/src/03-studio/0-menu.qdoc
new file mode 100644
index 00000000..755d90a0
--- /dev/null
+++ b/doc/src/03-studio/0-menu.qdoc
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Menu
+\page studio-menu.html
+\ingroup qt3dstudio-studio
+
+\section1 File
+
+\list
+\li
+ \b{New} - Opens a dialog to create a new presentation. If you
+ enable the \"Create directory for project\" checkbox at the bottom of
+ the dialog a new directory with suggested folder organization is
+ created for you. If a \c{.uia} file exists in the same directory
+ as the \c{.uip} it will be modified to reference the new
+ \c{.uip} as an asset. If no \c{.uia} file exists in the same
+ directory one will be created for you.
+\li
+ \b{Open...} - Opens a \c{.uip} presentation file from
+ disk.
+\li
+ \b{Recent Presentations} - Provides quick access to the last 10
+ presentations opened by Studio.
+\li
+ \b{Save} - Saves changes to the open presentation to disk.
+\li
+ \b{Save As...} - Saves the presentation to a new location.
+ No \c{.uia} file will be created or modified in the new location.
+\li
+ \b{Save a Copy...} - Saves a copy of the presentation to a
+ new location (but keep working on the current presentation). No
+ \c{.uia} file will be created or modified in the new location.
+\li
+ \b{Revert...} - With confirmation, abandons all in-memory
+ changes to the presentation and re-opens it from disk. Note that this
+ resets the state of Studio (resetting all components to the first
+ slide, playheads to time 0, etc.). This command is also a convenient
+ way to re-open a presentation that may have changed on disk, for
+ example via hand editing or source control updating.
+\li
+ \b{Exit} - Quit the Studio application (prompting to save
+ changes).
+\endlist
+
+\section1 Edit
+
+\list
+\li
+ \b{Undo}/\b{Redo} - As expected.
+\li
+ \b{Cut}/\b{Copy}/\b{Paste} - As expected.
+\li
+ Cut/copy/pasting actions can only be done by right-clicking on them in
+ the \l{studio-action-palette.html}{Action palette}.
+\li
+ Duplicating slides can only be done by right-clicking on them in the
+ \l{studio-slide-palette.html}{Slide palette}.
+\li
+ \e{Tip: Holding down the Alt key while pasting an element on the
+ Timelin - trl-Alt- - ill paste it to the master slide, if
+ possible.}
+\li
+ \b{Duplicate Object} - Creates a copy of the currently-selected
+ object in the timeline on the current slide. (If the selected object
+ is on the master slide, but you are on a slide other than the master
+ slide, the copy will be non-master.) Unfortunately, duplicating a
+ master object on the master slide does \e{not} preserve any
+ master-unlinked properties. There is no way within Studio to duplicate
+ a master object while preserving per-slide variations for that object.
+\li
+ \b{Application Preferences...} - Opens the Studio Preferences dialog:
+ \image ApplicationPreferences.png
+
+\li
+ \b{General}
+ \list
+ \li
+ \b{Nudge Increment} - Controls the amount that an object's
+ position values change when using the arrow keys to adjust the
+ position of an object.
+ \li
+ \b{Default Interpolation} - Controls whether new animation
+ keyframes are created with
+ \l{studio-timeline-palette.html#interpolation}{linear or smooth interpolation}.
+ \li
+ \b{Timeline Snapping Grid} - When using snapping in the
+ timeline, controls whether to snap to the largest ticks only (Low
+ Resolution), largest and halfway ticks (Medium Resolution), or every
+ tick mark (High Resolution).
+ \endlist
+\li
+ \b{Editing View}
+ \list
+ \li
+ \b{Background Color} - Sets the color of the background when
+ using an \l{studio-toolbar.html#edit-cameras}{Edit Camera view}. Please note that this does not effect Scene Camera View background color.
+ \li
+ \b{Preferred Startup View} - Sets whether to default to the
+ scene camera(s) or an \l{studio-toolbar.html#edit-cameras}{Edit Camera view}
+ when starting Studio.
+ \endlist
+\li
+ \b{Restore Defaults} - Restores all preferences for Studio to
+ their default state. This includes palette layout and placement.
+\li
+ \target project-settings
+ \b{Project Settings}
+ \list
+ \li
+ \b{Presentation Width/Height} - Sets the render size for the
+ presentation. Note that setting a higher resolution for a
+ sub-presentation than the final display size will result in
+ anti-aliasing for the sub-presentation (albeit at a performance
+ cost).
+ \li
+ \b{Constrain Proportions} - When checked, editing a width or
+ height value will also update the other. (This setting has no effect
+ at runtime.)
+ \li
+ \b{Portrait Format} - When editing a `portrait' style
+ presentation (width is smaller than height) designed to be displayed
+ on a rotated hardware device (e.g.~a tablet), check this setting to
+ have the presentation rotated correctly. This setting has no effect
+ when previewing on Windows.
+ \li
+ \b{Author/Company} - These are informational metadata that are
+ stored in the \c{.uip} file. These settings have no effect at
+ runtime.
+ \endlist
+\endlist
+
+\section1 View
+
+\list
+\li
+ (Palettes) - Selecting a palette ensures that this palette is visible.
+\li
+ \b{Bounding Boxes} - Toggles the display of bounding boxes in the
+ scene for the selected item.
+\li
+ \b{Pivot Point} - Toggles the display of the pivot point for the
+ selected item.
+\li
+ \b{Tooltips} - Toggles the display of tooltips when hovering over
+ rows in the \l{studio-inspector-palette.html}{Inspector palette}.
+\endlist
+
+\section1 Timeline
+
+\list
+\li
+ \b{Set Changed Keyframes} - When \"Autoset Keyframes\" is turned
+ off, invoking this command will create keyframes at the current time
+ for any properties of the object that (a) have their
+ \l{studio-inspector-palette.html#animating-properties}{animation toggle}
+ enabled, and that (b) have values different from the animated
+ value at the current time.
+\li
+ \b{Delete Selected Keyframe(s)} - Behaves as the name implies.
+ This command is also available from the context menu when
+ right-clicking in the animation portion of the Timeline palette; it's
+ usually easier to invoke it from there. Easier still, you can simply
+ press the Delete key after selecting the keyframes.
+\li
+ \b{Set Interpolation...} - Changes the in and out
+ \l{studio-timeline-palette.html#interpolation}{interpolation setting}
+ setting for one or more selected keyframes. This command is
+ also available from the context menu when right-clicking in the
+ animation portion of the Timeline palette; it's usually easier to
+ invoke it from there.
+\li
+ \b{Change Time Bar Color...} - Sets the display color of the
+ time bar in the animation portion of the Timeline palette. This does
+ not affect the rendering of the presentation; it is only there to help
+ you organize and keep track of your work.
+\li
+ \b{Autoset Keyframes} - Toggles the `autoset' animation
+ functionality. When enabled, any change to a property whose
+ \l{studio-inspector-palette.html#animating-properties}{animation toggle}
+ is enabled will result in a keyframe being created or updated
+ at the current time.
+\endlist
+
+\section1 Help
+
+\list
+\li
+ \b{Reference Manual} - Open this help document from within Studio.
+\li
+ \b{Visit Qt Web site...} - Opens Qt homepage in your browser.
+\li
+ \b{About Qt 3D Studio...} - Opens the about dialog.
+\endlist
+
+*/
diff --git a/doc/src/03-studio/1-toolbar.qdoc b/doc/src/03-studio/1-toolbar.qdoc
new file mode 100644
index 00000000..f8a1058b
--- /dev/null
+++ b/doc/src/03-studio/1-toolbar.qdoc
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Toolbar
+\page studio-toolbar.html
+\ingroup qt3dstudio-studio
+
+\section1 Selection Modes
+
+\image Studio-Toolbar-Selection.png
+
+The Selection Mode buttons control what item is selected in the Timeline
+palette when you click on items within the rendered scene.
+
+\list
+\li
+ Clicking on an item using \b{Group Select} mode (dark arrow;
+ keyboard shortcut: \c{A}) will select the highest group or
+ component owning the item you clicked on. This mode is useful when you
+ want to move a group of items at once.
+\li
+ Clicking on an item using \b{Item Select} mode (white arrow;
+ keyboard shortcut: \c{V}) will select the item you clicked on. If
+ the item is not present in the Timeline palette (if it is inside a
+ component) then the component is selected instead.
+\endlist
+
+With either tool, if you \b{double-click} on an item in the
+rendered scene then the item itself will be selected (changing which
+component is displayed in the Timeline palette as necessary).
+
+\section1 Manipulator Modes
+
+\image Studio-Toolbar-Transform.png
+
+The Manipulator Mode buttons control what manipulator is shown in the
+rendered scene when an item is selected, and what happens when you drag
+on the selected item (or on the matte area surrounding the rendered
+scene).
+
+\list
+\li
+ The \b{Position} mode (keyboard shortcut: \c{W}) adjusts the
+ Position of the selected item. Left-dragging on the item/matte will
+ adjust the selected item's position in the plane of the render camera;
+ right-dragging will adjust the selected item's position along the view
+ axis of the camera.
+\li
+ The \b{Scale} mode (keyboard shortcut: \c{E}) adjusts the
+ Scale of the selected item. Left-dragging on the item/matte will
+ uniformly scale the selected item; right-dragging will adjust only the
+ local Z scale of the item.
+\li
+ The \b{Rotation} mode (keyboard shortcut: \c{R}) adjusts the
+ Rotation of the selected item. Left-dragging on the item/matte will
+ tumble the selected item; right-dragging rotate the item around the
+ view axis of the camera.
+\endlist
+By default the manipulators affect the local transformation of the item.
+For example, selecting an unrotated cube inside a rotated group with the
+Position manipulator mode active will show rotated axes. Dragging on the
+red arrow of the manipulator will affect only the X position of the
+item.
+
+The \b{Local/Global Manipulators} mode (last icon above) changes
+this behavior to affect the global transform of the selected item
+instead. In Global mode, the manipulators always transform with respect
+to the global space. In the example above, turning on Global mode will
+show the red arrow for the position manipulator aligned with the screen
+(assuming an unrotated camera). Dragging on the red arrow may affect two
+or three of the position values for the selected item in order to move
+it in global space.
+
+\section1 Keyframing
+
+\image Studio-Toolbar-Animation.png
+
+The \b{Autoset Keyframes} toggle (keyboard shortcut: \c{K})
+controls whether keyframes are automatically created at the current
+playhead time in the timeline whenever a value with animation enabled
+has its value changed.
+
+The following example illustrates the use of this toggle:
+
+\list
+\li
+ Create an object positioned at 0,0,0
+\li
+ Move the playhead to time 0.
+\li
+ Turn on the animation toggle for the Position property in the
+ Inspector palette.
+\endlist
+
+\list
+\li
+ \e{A keyframe is created at time 0 by default.}
+\endlist
+
+\list
+\li
+ Move the playhead to a new time (e.g.~1 second).
+\li
+ Turn off the \c{Autoset Keyframes} toggle.
+\li
+ Adjust the position to 100,200,0.
+\endlist
+
+\list
+\li
+ \e{The object moves in the rendered scene, but no keyframe is
+ created.}
+\endlist
+
+\list
+\li
+ Drag the playhead to a new time (e.g.~2 seconds).
+\endlist
+\list
+\li
+ \e{The object snaps back to position 0,0,0, since no new keyframe
+ was created for the new position.}
+\endlist
+
+\list
+\li
+ Turn on the \c{Autoset Keyframes} toggle.
+\li
+ Adjust the position to 100,200,0.
+\endlist
+
+\list
+\li
+ \e{As soon as you stop editing one of the position values a new
+ keyframe is created. Each time you change a value at this time the
+ keyframe is updated.}
+\endlist
+Without the \c{Autoset Keyframes} mode you must use the Set Changed
+Keyframes command from the Timeline menu to create a new keyframe, such
+as after the second-last example above.
+
+\section1 Edit Cameras
+
+\image Studio-Toolbar-EditCameras.png
+
+By default the rendered scene looks through the camera in each layer and
+shows the composited result. Sometimes you want to instead move around
+the 3D space of your scene without adjusting the final rendered view.
+Studio calls this concept \e {Edit Cameras}, and it is controlled by the
+section of the toolbar displayed above.
+
+Note that when Edit Camera is in use it only makes sense to show the
+contents of one layer at a time. To control which layer's items you are
+viewing, select any item inside the desired layer in the Timeline
+palette.
+
+\list
+\li
+ The \b{Edit Camera Mode} drop-down menu controls the view.
+\li
+ The \b{Perspective View} and \b{Orthographic} view are
+ free-form cameras that you can use to rotate around the scene.
+\li
+ The
+ \b{Top}/\b{Bottom}/\b{Left}/\b{Right}/\b{Front}/\b{Back}
+ axis-aligned presets are orthographic cameras that may be panned and
+ zoomed, but not orbited.
+\li
+ The \b{Scene Camera View} entry at the bottom of the menu
+ switches out of edit camera mode and returns to displaying the final
+ composited result from the cameras in each layer of the presentation.
+\li
+ \target fit-selected
+ The \b{Fit Selected} command (keyboard
+ shortcut: \c{F}) will ensure that whatever is selected fills the
+ view of the active edit camera. If no item is selected, this command
+ ensures that the contents of the active layer are all visible in the
+ edit camera.
+
+ \list
+ \li
+ \b Tip: if you want to drop your selection, but cannot find
+ any empty space in the view to click on, you can click on empty
+ space in the Slides palette to cause no items to be selected.
+ This may seem a little weird, but it is effective.)
+ \li
+ When not using an Edit Camera - when using the default
+ \c{Scene Camera View} mode- this command will instead
+ downscale the appearance of the presentation to fit within the
+ available space in Studio.
+ \endlist
+\li
+ With the \b{Pan} mode active (shortcut: middle-button mouse drag)
+ clicking and dragging anywhere in the rendered view for the edit
+ camera will slide the view around.
+\li
+ With the \b{Zoom} mode active (shortcut: roll the mouse wheel)
+ clicking and dragging anywhere in the rendered view for the edit
+ camera will zoom the view in/out as you drag up/down.
+\li
+ With the \b{Orbit} mode active (shortcut: alt+middle-button mouse
+ drag) clicking and dragging anywhere in the rendered view for the edit
+ camera will rotate the view. (This is not available for the
+ predefined, axis-aligned orthographic views.)
+\li
+ The \b{Shading Mode} toggle (shortcut: \c{F3}) toggles a
+ `headlamp' attached to your edit camera. When enabled (the default)
+ items are lit by the edit camera such that they are always easy to
+ see. When disabled, the lighting from the final rendering is used. If
+ you have a black ambient lighting in your scene (the default) then
+ objects viewed from behind may not be visible without turning on your
+ headlamp.
+\endlist
+
+\section1 Playback Control
+
+\image Studio-Toolbar-Playback.png
+
+These commands control the playhead, making it easier to preview
+animations and slide transitions without leaving Studio.
+
+\list
+\li
+ The \b{Rewind} command sets the playhead to time 0.
+\li
+ The \b{Stop} command stops any playback.
+\li
+ The \b{Play} command starts advancing the playhead in realtime,
+ previewing animations on elements. The \b{Play Mode} for the
+ current slide is honored, possibly looping or ping-ponging playback,
+ or causing Studio to switch to an new slide when the end time for the
+ current slide is reached.
+\li
+ Holding down the space bar temporarily enables playback while held
+ down. Releasing the spacebar returns the playhead to its previous
+ time, allowing you to repeatedly hold down space to preview an
+ animation.
+\li
+ Pressing the Enter key will start playback. Press Enter again to stop
+ playback.
+\endlist
+
+\section1 Preview
+
+\image Studio-Toolbar-Preview.png
+
+Invoking the \b{Preview} command (keyboard shortcut: \c{F12})
+will launch the Qt 3D Studio Viewer application and preview the
+application for the presentation. If there is no \c{.uia} file in
+the folder for this presentation, then the presentation will be
+previewed by itself (no sub-presentations).
+
+*/
diff --git a/doc/src/03-studio/2-scene-view-and-matte.qdoc b/doc/src/03-studio/2-scene-view-and-matte.qdoc
new file mode 100644
index 00000000..8f9435b7
--- /dev/null
+++ b/doc/src/03-studio/2-scene-view-and-matte.qdoc
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Scene View and Matte
+\page studio-scene-view-and-matte.html
+\ingroup qt3dstudio-studio
+
+\image Studio-SceneView.png
+
+The \e {scene view} is the center region of Studio, showing you the
+visual result of rendering and compositing the layers of your
+presentation, and also allowing you to select and transform elements
+graphically.
+
+Surrounding the scene view is the \e matte. The matte may not be
+visible if your presentation is larger than the available space. (This
+would be a shame, since it is rather useful; see below.)
+
+\section1 Scene View
+
+The content of the scene view depends on whether or not you are using an
+\l{studio-toolbar.html#edit-cameras}{edit camera}. Normally (without an
+edit camera) the contents of all layer - s seen through the camera for
+each laye - re composited in the scene view. When an edit camera is
+used, the contents of a single layer are seen as viewed through the edit
+camera.
+
+\section2 Selecting Elements
+
+In addition to displaying content, the scene view allows you to select
+and transform visible elements. Click on an element in the scene to
+select it in the \l{studio-timeline-palette.html}{Timeline palette}
+and show its properties in the
+\l{studio-inspector-palette.html}{Inspector palette}.
+
+Clicking in empty space will drop the current selection. If you don't
+have any empty space to click on, you can alternatively click on empty
+space in the \l{studio-slide-palette.html}{Slide palette} to drop the
+current selection.
+
+\section2 Showing and Hiding Bounding Boxes
+
+When an element is selected its bounding box is drawn in the scene view,
+along with the bounding boxes of immediate children. If this is getting
+in your way, you can turn off bounding boxes in the bottom half of the
+View menu (keyboard shortcut: \c{Ctrl-B}).
+
+\section2 Transforming Elements
+
+When an element is selected, an interactive transform manipulator will
+be displayed in the scene view. Click and drag on portions of the
+manipulator to move/rotate/scale the element. (The manipulator displayed
+is controlled by the current
+\l{studio-toolbar.html#manipulator-modes}{manipulator mode}).
+
+Alternatively, you can click and drag on the element itself to affect
+the transform:
+
+\list
+\li
+ In \b{Position} mode...
+\li
+ left-mouse dragging on the element will adjust the position
+ perpendicular to the camera's view axis. (That's a complicated way of
+ saying that if you drag an item to the left, it will move to the
+ left.)
+\li
+ right-mouse dragging up/down on the element will move it farther
+ from/closer to the camera.
+\li
+ In \b{Rotation} mode...
+\li
+ left-mouse dragging on the element will tumble it.
+\li
+ right-mouse dragging up/down on the element will rotate it counter
+ clockwise/clockwise within the view.
+\li
+ In \b{Scale} mode...
+\li
+ left-mouse dragging up/down on the element will proportionately scale
+ it smaller/larger.
+\li
+ right-mouse dragging up/down on the element will affect the local Z
+ scale.
+\endlist
+
+\section1 Matte
+
+Sometimes you need to select an item via the
+\l{studio-timeline-palette.html}{Timeline palette} because other items
+are in front of it. However, when you attempt to transform it by
+dragging on it (instead of using the manipulators), you end up selecting
+a different item.
+
+Clicking and dragging in the matte area when an element is selected is
+the same as clicking and dragging on the element itself. Using the matte
+for your dragging ensures that you will not accidentally transform the
+wrong element.
+
+*/
diff --git a/doc/src/03-studio/3-project-palette.qdoc b/doc/src/03-studio/3-project-palette.qdoc
new file mode 100644
index 00000000..754c445d
--- /dev/null
+++ b/doc/src/03-studio/3-project-palette.qdoc
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Project Palette
+\page studio-project-palette.html
+\ingroup qt3dstudio-studio
+
+The Project palette displays the files and folders on disk for your project.
+However, only files usable by Studio are displayed in the palette.
+
+\section1 Adding Assets
+
+You can add new assets to your project by dragging the files from the file system to the
+\e{project palette}. This will create a copy of the file in the project folder structure.
+The original file will always remain untouched.
+
+\section2 Adding Assets from a Library
+
+\image Studio-Project-Libraries.png
+
+Qt 3D Studio ships with a variety of sample assets to help you
+experiment and to speed common development needs. These files are hidden
+by the installer deep in the bowels of your computer. To make them easier
+to access, the bottom of the Project palette has five icons that provide
+direct access to a specific library.
+
+Clicking on one of these icons will open the corresponding folder in
+your file system. Once you have found the asset that you want, drag the
+asset from the file system onto the appropriate folder in the Project
+palette. As described above, this will \e{copy} the sample asset into
+your project. Once you have a copy you are free to edit it without fear
+of damaging the pristine original.
+
+\section1 Managing Assets
+
+If you wish to rename or delete items from your project, simply do so
+via the file system. Double-clicking on the folder in the Project
+palette will open the folder in the file system.
+
+Alternatively, you may right-click on a project asset and choose
+\c{Show in Explorer}. This will open the folder containing the item
+and also select it in the file system.
+
+\section1 Using Assets
+
+To use an item from the Project palette in your presentation, drag the
+item into the \l{studio-scene-view-and-matte.html}{scene view}
+or \l{studio-timeline-palette.html}{Timeline palette}. A new element
+will be created in your scene tied to that asset.
+
+For convenience, dragging an image from the Project palette into your
+scene will automatically create a rectangular model scaled to the aspect
+ratio of your image, with the image used as the diffuse map on the
+material. Dragging out a font file will create a text element with the
+font set correctly.
+
+Changes to the asset on disk (for example, editing an image in Photoshop,
+changing a script in Architect) will automatically update inside Studio.
+
+The one caveat to the above are 3D model assets. When you import a 3D
+model (in Collada or FBX format) into your project, it is converted into
+a \c{.import} file that references one or more \c{.mesh}
+assets. Changes to the original 3D model file will \b{not}
+automatically update inside of Studio. To update a changed model,
+right-click on the \c{.import} file in the Project palette and
+choose \c{Refresh Import...}. In the subsequent file dialog,
+select the model file on disk that you wish to re-import. Studio will do
+its best to understand the differences between your original file and
+the new version, and apply them to your presentation. For more details,
+read the section
+\l{best-practices-importing-3d-content.html}{Working with 3D Content}.
+
+\section1 Locating Missing Assets
+
+\image Studio-Project-MissingAsset.png
+
+If you open a presentation that references other files, and one or more
+those files cannot be found, Studio will present you with a dialog
+listing all assets that could not be found. Additionally, each missing
+asset will be shown in the Project palette with a caution icon next to
+the file.
+
+If you click on this icon, a context menu with the option \b {Locate
+File} will be shown. Choosing this option will show a standard file
+open dialog, allowing you to supply a new location for a moved asset.
+\omit
+\b {Warning}: If the missing assets expose custom properties to the
+artist - such as a presentation behavior, layer effect, or custom
+material - any custom values or animations you have specified for these
+assets will be lost if you relocate the file. Until
+\l{known-limitations.html#i9208}{this issue} is resolved,
+the only safe way to move or rename such referenced assets is by
+hand-editing the \c{.uip} presentation file.
+\endomit
+*/
diff --git a/doc/src/03-studio/4-basic-objects-palette.qdoc b/doc/src/03-studio/4-basic-objects-palette.qdoc
new file mode 100644
index 00000000..a5efd71b
--- /dev/null
+++ b/doc/src/03-studio/4-basic-objects-palette.qdoc
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Basic Objects Palette
+\page studio-basic-objects-palette.html
+\ingroup qt3dstudio-studio
+
+The \e {Basic Objects Palette} provides a mechanism for creating objects
+unique to a presentation, not represented by a file on disk in your
+\l{studio-project-palette.html}{Project Palette}.
+
+\target using-the-objects
+\section1 Using the Objects
+
+To use an object in your presentation, drag it from the Basic Objects
+palette into either the
+\l{studio-scene-view-and-matte.html}{scene view} or
+\l{studio-timeline-palette.html}{Timeline palette}. A corresponding
+element will be created.
+
+\b Tip: You often want to create new objects on the
+\l{studio-slide-palette.html#the-master-slide}{Master Slide}. Hold
+down the *\e{Alt} key when dropping the object to have it created on
+the Master Slide for you.
+
+\target model-primitives
+\section1 Model Primitives
+
+\table
+ \row
+ \li \image Studio-Basic-Rectangle.png
+ \li \image Studio-Basic-Sphere.png
+ \li \image Studio-Basic-Cube.png
+ \row
+ \li \image Studio-Basic-Cylinder.png
+ \li \image Studio-Basic-Cone.png
+ \li
+\endtable
+
+The Rectangle, Sphere, Cube, Cylinder, and Cone primitives provide a way
+to quickly add 3D models to your scene without a 3D modeling program.
+Adding one of these files does not add content to your models folder,
+but instead references an internal model.
+
+These primitives are created by the installer in a
+\c{res\textbackslash{}primitives\textbackslash{}*.mesh} subfolder.
+Note that if you modify one of these files, you must also the
+corresponding file installed with the Viewer application on your target
+application. Referencing a primitive does not include the mesh
+definition in your project. Note also that
+\l{studio-project-palette.html#using-assets}{dragging an image into the
+scene from the project palette} uses the Rectangle primitive to
+display the image; change this primitive only with the utmost caution.
+
+\section1 Component
+
+\image Studio-Basic-Component.png
+
+Components are somewhat like mini-scenes. Although they are 3D geometry
+(not a 2D composition of rendered layers), they have their own slides
+and timelines.
+
+You may alternatively create a new component in your scene by
+right-clicking on an element in the Timeline palette and choosing
+\c{Make Component} from the context menu. This will wrap the
+element inside a new component, allowing you to control its visual state
+and animation separate from the rest of its siblings.
+
+\section1 Group
+
+\image Studio-Basic-Group.png
+
+A group is an empty transform element. Attaching models to the group
+(placing them as children of the group in the Timeline palette) allows
+you to move/rotate/scale/hide the group and have this affect all items
+within it. Note that because groups affect the transformation of their
+children they do have an effect on runtime speed. Though the
+performance impact is very slight, you should avoid using groups
+\e{solely} for conceptual organization.
+
+Note that there is no way (currently) to group multiple existing items
+other than to create a new group and a drag the items in one at a time.
+We recognize the surprising nature of this and hope to provide more
+obvious mechanisms (e.g.~multiple select and \c{ctrl-g}) it in the
+future.
+
+\section1 Text
+
+\image Studio-Basic-Text.png
+
+A text element is a flat plane of text placed in 3D space. It is
+basically a transparent image displayed on a rectangle, where the image
+and rectangle size are dynamically updated whenever the text to be
+displayed is changed.
+
+Note that if you drag out a text object with no existing fonts in your
+project, Studio is forced to add a font file ("TitilliumWeb") to your
+project to support the display of text.
+
+\target layers-cameras-lights
+\section1 Layers, Cameras and Lights
+
+\table
+ \row
+ \li \image Studio-Basic-Layer.png
+ \li \image Studio-Basic-Camera.png
+ \li \image Studio-Basic-Light.png
+\endtable
+
+A layer represents a 3D scene that gets rendered into a 2D image and
+placed somewhere on the screen. Just as a Photoshop file may have
+multiple 2D layers drawn on top of one another, a Studio presentation
+may have multiple layers composited together.
+
+Each layer has exactly one active camera that is used to render the
+elements inside the layer. If you place multiple cameras inside a layer,
+the first camera found that is 'active' (eyeballed on and timebar
+present) is used to render the layer. You could thus use different
+non-master cameras on different slides to switch between various views,
+though it is usually easier to just
+\l{studio-inspector-palette.html#unlinking-from-the-master-slide}
+{unlink the properties} of a single camera on the
+\l{studio-slide-palette.html#the-master-slide}{master slide}.
+
+Layers also provide a target where
+\l{best-practices-effects.html}{post-processing effects} may be applied.
+
+In order to keep the runtime from freaking out, you must have at least
+one master layer at all times. Studio will not let you delete the last
+master layer unless you first add a new layer on the master slide to
+replace it.
+
+Each layer may have zero, one, or two lights on it. Lights are used to
+illuminate the models in your scene so that they can be seen. If you
+have zero lights you will need to set the
+\l{studio-inspector-palette.html#material-properties}{Lighting property
+for your materials} to \c{None} in order to see your models.
+
+To make your life simpler, dragging a layer from the Basic objects
+palette into your scene will also add both a camera and a light to that
+new layer.
+
+\section1 Alias
+
+\image Studio-Basic-Alias.png
+
+An alias is an live copy of another node in the scene graph, with its
+own 3D transformation. If you create an alias and set its Reference
+property to a model, any changes to the material of that model will be
+represented in the alias. However, the position, scale, rotation, etc.
+of the alias are its own. If you change the scale the original model,
+the alias will not update.
+
+Aliases are only active during authoring time. At runtime they become a
+full copy of the referenced object and all its descendants. This allows
+you to, for example, create a single template component and with 10
+aliases of it controlled by script. While each alias will look identical
+in Studio during creation, Lua script or state machines can customize
+each instance based on data or application state.
+
+*/
diff --git a/doc/src/03-studio/5-timeline-palette.qdoc b/doc/src/03-studio/5-timeline-palette.qdoc
new file mode 100644
index 00000000..c45d9ab1
--- /dev/null
+++ b/doc/src/03-studio/5-timeline-palette.qdoc
@@ -0,0 +1,379 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Timeline Palette
+\page studio-timeline-palette.html
+\ingroup qt3dstudio-studio
+
+\image Studio-Timeline-Overview.png
+
+The Timeline palette is second-only to the
+\l{studio-inspector-palette.html}{Inspector palette} in frequency of
+use when editing a presentation. The Timeline palette provides direct
+access to all elements in your scene - including those not producing a
+visible result - and also gives you control over the animation and
+timing within a slide.
+
+The palette is comprised of two connected sections: the Scene Graph (on
+the left side) and the Animation portion (on the right).
+
+\section1 Scene Graph
+
+\image Studio-Timeline-SceneGraph.png
+
+The left half of the Timeline palette shows all elements in your
+presentation for the current slide (chosen in the
+\l{studio-slide-palette.html}{Slide palette}). The root of your
+presentation is the Scene, to which are attached one or more layers (and
+possibly additional presentation behaviors).
+
+\section2 Name Color Indicates Slide
+
+The name of an item in the Scene Graph is colored based on its presence
+on the master slide. Elements that are present on the master slide have
+a green name, while elements that are only present on the current slide
+have a light gray name.
+
+The same holds true for animated properties. Properties that are
+animated the same on all slides show with green text, while properties
+that have a custom animation on this slide (such as the \"Position\"
+property shown above) are shown with light gray text.
+
+\section2 Element Hierarchy
+
+Within each layer is a camera, usually a light, and the elements
+rendered for the layer. These elements are arranged hierarchically.
+Placing one element as a child of another causes:
+
+\list
+\li
+ The child element to inherit the transform of the parent. When the
+ parent moves or rotates, so do its children.
+\li
+ The child element to inherit the opacity from the parent. As the
+ parent becomes less opaque, so do its children.
+\li
+ The child element to inherit the `active' state from the parent. If
+ the parent is eyeballed off on this slide, so are all its children.
+\li
+ Events to bubble from the child to the parent. An
+ \c{onPressureDown} event on a child element may also be handled
+ by the parent element.
+\endlist
+
+\section2 Action Indicators
+
+The left-most column of the Timeline palette is used to show which
+elements have actions on them.
+
+\list
+\li
+ A row with \inlineimage Studio-Timeline-ActionBadge.png on it
+ indicates that the element has one or more actions on it.
+\li
+ A row with a down-triangle in this column indicates that one or more
+ descendant elements have actions on them.
+\li
+ A row with a right-triangle in this column indicates that the
+ component on this row has one or more actions inside it.
+\endlist
+
+Elsewhere in the interface, a green item indicates an action on the
+master slide, while a light gray item indicates an action specific to
+this slide.
+
+\section2 Editing Components
+
+Components are somewhat like mini scenes. A component has its own set of
+slides and independent time. Consequently the contents inside a
+component cannot sensibly be shown and edited at the same time as items
+outside a component. To see and edit the contents of a component, either
+\b{double-click} the component or right-click on it and choose
+\"Edit Component\". The Timeline and Slide palettes will both switch to
+show the contents of the component.
+
+When you enter a component, a `breadcrumb' is shown at the top of the
+Timeline palette:
+
+\image Studio-Timeline-Breadcrumb.png
+
+To leave the component and return to the Scene, click on the Scene at
+the front of the breadcrumb.
+
+Alternatively, double-click on an element outside the component in the
+rendered scene view; this will switch the Timeline palette as necessary
+to select and show that item.
+
+\section2 Hiding Irrelevant Elements
+
+As your scene graph grows in elements you may find yourself annoyed by
+the presence of elements that you almost never edit. The first column
+after the name allows you to mark an element as "shy", indicated by
+\inlineimage Studio-Timeline-Shy.png
+Clicking the button at the top of this column will toggle the visibility
+of element rows marked as "shy".
+
+\note This is only an editing convenience within the Timeline
+palette, and has no effect on the visibility of elements rendered in the
+scene at runtime.
+
+\section2 Per-Slide Element Visibility
+
+If you have an element that should only appear on one slide, you should
+to create the element as a non-master element on the correct slide. If
+you have an element that should appear on every slide, you should create
+the element on the master slide. But what if you have an element that
+should appear on a few slides, but not all?
+
+The second column after the name has eyeballs
+\inlineimage Studio-Timeline-Eyeball.png which are used
+to control the `active' state of an element and all its descendants. To
+cause an element to not appear on only certain slides, place your
+element on the master slide and then `eyeball it off' on slides where it
+should not be present.
+
+The active state of an element controls more than just visibility.
+Elements that are not active do not receive update notifications each
+frame. which is particularly important for presentation behaviors.
+
+Similar to the other columns, clicking the eyeball at the top of the
+column will hide the rows for elements that are eyeballed off on the
+current slide.
+
+\note Unlike the "shy" and "lock" columns, the presence or
+absence of the eyeball changes the runtime behavior of your
+presentation. You may wish to use the eyeball to temporarily hide an
+element during editing, but be sure to re-enable the element if it is
+supposed to be present on this slide.
+
+\section2 Locking an Element
+
+Once you have perfected a particular element you may wish to lock it. To
+lock the element, click the lock icon
+\inlineimage Studio-Timeline-Lock.png in the third column. Locking an
+element prevents its properties from being edited, and even prevents it
+from being selected.
+
+Similar to the other columns, clicking the lock at the top of the column
+will hide the rows for elements that are locked. Unlike the other
+column - hich take effect per slid - n element that is locked is
+locked on every slide.
+
+\note This is only an editing convenience, and has no effect
+on interaction with elements at runtime.
+
+\section2 Copying Object Path
+
+The `path' to an element is used both in presentation behaviors as well
+as by an application's
+\l{file-formats-uia.html#visual-actions}{Visual Actions}. While you could
+type out the name of each ancestor of the element, a more convenient
+option is available.
+
+Right-click on the name of any element and choose \"Copy Object Path\"
+from the context menu. This will put a string on your clipboard like
+\c{Scene.Overlays.Dialogs.Content.preloader}, ready for pasting
+elsewhere. \e{(Note that for visual actions you need to prefix this
+path with the \c{id} of the
+\c{<presentation>} asset in order to
+differentiate it from other possible presentations.)}
+
+\section1 Animation Portion
+
+\image Studio-Timeline-Animation.png
+
+To the right of the scene graph in the Timeline palette is the actual
+timeline. The time bars for each element control element lifespan. The
+keyframe markers control the timing of animation. The playhead (in red)
+allows the preview of animation effects. The time measure across the top
+coordinates the timing of it all.
+
+\section2 Zooming In and Out
+
+When working with fast animations you may wish to zoom in to see the
+contents better. The simplest way to do this is with the plus and minus
+keys on the keypad. Pressing and holding these will adjust the time
+scale for the Timeline palette.
+
+Additionally, the bottom of the Timeline palette has a custom scrollbar
+with handles on the edges. Dragging these to make the scroll "thumb"
+smaller will also adjust the time scale.
+
+\section2 Setting Playhead Time
+
+Drag the playhead by the red knob over the time measure to adjust the
+time. (You can actually just click and drag on the time measure and the
+playhead will teleport to your mouse.) This is used to set the time for
+a new keyframe, and the effects of dragging the playhead back and forth
+will also preview the effects in the rendered scene view in real time.
+
+To prevent keyframes from being misaligned (and to cater to your
+excellently obsessive nature, shared by most technical artists) you may
+wish to ensure that the playhead is exactly at a particular time.
+Holding down the \b{shift key} while dragging the playhead will
+cause it to snap to keyframe markers as well as certain notches on the
+time measure.
+
+Use the \c{Timeline Snapping Grid} setting in the
+\l{studio-menu.html#edit}{Application Preferences} to control what level
+of notches it snaps to.
+
+As you adjust the time for the playhead you will see the exact time
+displayed above the name column in the scene graph portion of the
+palette. Clicking on these numbers will open the Go To Time palette,
+where you may type in an exact tim - own to the millisecon - o set
+the playhead to.
+
+\section2 Adjusting Animation
+
+\image Studio-Timeline-Animation-Keyframes.png
+
+Most good visual effects do not "pop" into place, but provide a visual
+transition - even if brief - to help the user understand what happened.
+Animations to the rescue!
+
+\section3 Creating Keyframes
+
+To animate a property of an element, turn on the
+\l{studio-inspector-palette.html#animating-properties}{animation toggle
+in the Inspector palette}. This will add a new keyframe for that
+property at the current playhead time. If the property is not linked to
+the master slide (as with the Opacity shown in the picture above) the
+animation will only be created on the current slide.
+
+To create a new keyframe move the playhead to a new time and then
+either:
+
+\list
+\li
+ ensure that \l{studio-toolbar.html#keyframing}{Autoset Keyframes} is
+ turned on (via the Toolbar, Timeline menu, or by pressing \c{K}),
+ and then change the value of the property (via the Inspector palette
+ or dragging the transform of the element), or
+\li
+ change the value of the property and then invoke the
+ \l{studio-menu.html#timeline}{Set Changed Keyframes} command (from the
+ Timeline menu, or the keyboard shortcut \c{F6}).
+\endlist
+
+This will create a new keyframe at the current time. You can drag the
+keyframe in the Timeline palette to adjust its time, or double-click it
+to show the Set Keyframe Time dialog where you can enter an exact timing
+value.
+
+Keyframes displayed in green are "dynamic keyframes". For more
+information, see the page
+\e{\l{best-practices-dynamic-keyframes.html}{Dynamic Keyframes}}.
+
+\section3 Copying Keyframes
+
+Top copy keyframes from one element to another:
+
+\list 1
+\li
+ Select the keyframe(s) to copy on an element.
+\li
+ Right-click on one of the selected keyframes and choose \"Copy
+ Selected Keyframes\".
+\li
+ Position the playhead at the time where the first keyframe should be
+ placed.
+\li
+ Right click on the time bar for the element and choose \"Paste
+ Keyframes\".
+\endlist
+
+\section3 Interpolation
+
+\image Studio-Timeline-Interpolation.png
+
+As the playhead moves from one keyframe to the next, the Qt 3D Studio
+Runtime can perform \e {linear interpolation}, \e {smooth
+interpolation}, or a custom blending somewhere in-between. With linear
+interpolation the value changes at the same rate from one value to the
+next. With smooth interpolation the value starts off holding the
+previous keyframe value, `accelerates' towards the next keyframe value,
+and then `decelerates' to stop at the new value.
+
+To set the interpolation, first select the keyframe(s) that you want to
+adjust, then right-click on one of the selected keyframes, and from the
+context menu choose \b {Set Interpolation}. The \b {Ease In} setting
+controls how the value behaves as it approaches the keyframe and the
+\b {Ease Out} setting controls how the value behaves when leaving the
+keyframe.
+
+\e{If you find that you are constantly setting your keyframes from
+Smooth to Linear, or vice-versa, you may wish to change the
+\b{Default Interpolation} setting for new keyframes in the
+\l{studio-menu.html#edit}{Application Preferences}.}
+
+\section2 Adjusting Time Bars
+
+The colored bars displayed for each element control the lifespan during
+which the element is active. Whenever the playhead (in Studio, or the
+virtual playhead active at runtime) is outside the time bar for an
+element, that element becomes inactive: it no longer renders, nor does
+it receive update events each frame.
+
+Drag the ends of a time bar to adjust its duration. As with the dragging
+the playhead, holding down the shift key will snap the time to
+appropriate boundaries during dragging.
+
+Alternatively, double-click on a time bar to open the Set Time Bar
+Start/End Time dialog, where you may enter specific values.
+
+To set the start or end time for many time bars at once:
+
+\list 1
+\li
+ Select an element.
+\li
+ Set the playhead to the desired time.
+\li
+ Press the \c{{[}} key to set the start time to the playhead time,
+ or the \c{{]}} key to set the end time to the playhead.
+\endlist
+
+\list
+\li
+ All descendant elements will also have their start or end time set to
+ the same value. It is thus common when entering a new slide for the
+ first time to select the scene or active component, set the playhead
+ to a particular time, and then press \c{{]}} to crop the entire
+ slide to that duration.
+\endlist
+
+\section2 Customizing Time Bars
+
+To help you keep track of your assets, Studio allows you to apply custom
+colors and notes to time bars. Right-click on a time bar and choose
+either \b {Change Time Bar Color} or \b {Change Time Bar Text}.
+
+*/
diff --git a/doc/src/03-studio/6-slide-palette.qdoc b/doc/src/03-studio/6-slide-palette.qdoc
new file mode 100644
index 00000000..d25cde64
--- /dev/null
+++ b/doc/src/03-studio/6-slide-palette.qdoc
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Slide Palette
+\page studio-slide-palette.html
+\ingroup qt3dstudio-studio
+
+ \section1 Using Slides
+
+\image Studio-Slide-Main.png
+
+ Each scene and
+component in a presentation has a set of "slides" associated with it.
+These slides can be used to effect drastic, PowerPoint-like changes
+(\e{each slide has completely different content}) or subtle
+variations on the same content (\e{make the button background pulse
+with a slight orange color on the 'Focused' slide}).
+
+Each slide has its own animation timeline and playback characteristics.
+Your 'Intro' slide may last for 1 second and automatically play through
+to another slide that has no animation at all. A third slide may have 10
+seconds of different animation that play in a looping fashion.
+
+Each scene and component come to life with one slide already created. To
+add additional slides, right-click in the Slide palette and choose \"New
+Slide\" (or duplicate an existing slide).
+
+Click on a slide to select it. This will cause the
+\l{studio-timeline-palette.html}{Timeline palette} to show the
+elements and animations for the selected slide, and the
+\l{studio-scene-view-and-matte.html}{scene view} to update
+accordingly. Adding new elements to your scene (via the
+\l{studio-basic-objects-palette.html}{Basic Objects} or
+\l{studio-project-palette.html}{Project} palettes) will add the
+elements only to this slide. Adding new actions (via the
+\l{studio-action-palette.html}{Actions palette} will create actions
+that only can be triggered on this slide.
+
+You may re-order slides within the palette by dragging them.
+
+\section1 The Master Slide
+
+\image Studio-Slide-Master.png
+
+ To create content
+that subtly changes across multiple slides you need elements that exist
+across all of those slides. Each scene and component have one \"master
+slide\". Elements placed on this slide exist on all slides of that
+scene/component.
+
+Click the \b {Edit Master} button at the top of the Slide palette to
+enter the master slide. As with other slides, the Timeline palette and
+scene view will update accordingly. Now adding new elements and actions
+will create these items on the master slide.
+
+Click the \b {Leave Master} button when you have finished adjusting the
+master slide. Note that you do not need to be on the master slide to
+adjust properties of elements on the master slide. Changes made to a
+property of a master element apply across all slides equally.
+
+To cause certain properties for an element to vary per slide, you must
+\l{studio-inspector-palette.html#unlinking-from-the-master-slide}
+{unlink each property} that you wish to change.
+
+To cause a property to smoothly transition when changing from one slide
+to another, animated the property using
+\l{best-practices-dynamic-keyframes.html}{dynamic keyframes}.
+
+*/
diff --git a/doc/src/03-studio/7-inspector-palette.qdoc b/doc/src/03-studio/7-inspector-palette.qdoc
new file mode 100644
index 00000000..5b9658c2
--- /dev/null
+++ b/doc/src/03-studio/7-inspector-palette.qdoc
@@ -0,0 +1,1092 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Inspector Palette
+\page studio-inspector-palette.html
+\ingroup qt3dstudio-studio
+
+ The Inspector palette is the most-used
+palette in Studio. It is used to control which properties are animated
+or change on a per-slide basis and the values for each of those
+properties.
+
+\section1 Animating Properties
+
+Almost every property of every element may be animated at runtime.
+Non-animatable exceptions are properties with discrete values (booleans,
+text strings, or drop-down lists).
+
+Properties that \e{can} be animated have a small stopwatch icon next
+to them in the Inspector palette. Click on this icon to enable animation
+for an property.
+
+Turning off the toggle for an property with complex animation saves the
+keyframes during the same session; if you accidentally turn off
+animation you can turn it back on and all your keyframes will come back.
+However, if you save your presentation with the animation turned off,
+those keyframes are discarded. Re-enabling animation after re-opening
+the presentation will start with a blank slate.
+
+\section1 Unlinking from the Master Slide
+
+ By default, elements on the
+\l{studio-slide-palette.html#the-master-slide}{master slide} of their
+owning time context have the same property values on all slides. If you
+change the Scale of an that change is applied on all slides. However, it
+is also possible to \"unlink\" any property of a master element. An
+unlinked attriute can have custom values and animations for each slide.
+
+To unlink an property, right-click on the property name in the Inspector
+palette and choose \"Unlink Property from Master Slide\". The name of
+the property will change from green to light grey. This is the same
+color used for the name of elements that are present only on a single
+slide, and the properties of such elements.
+
+Tip: when you first unlink a property the current value for that
+property, including any animation keyframes, is used as the value for
+every slide. If you want a similar-but-slightly-different animation on
+all or most slides, first create the animation on the master slide and
+\b{then} unlink the property and tweak the animation on other
+slides. A little thinking ahead can save you from needing to perform
+redudant work.
+
+\section1 Editing Numeric Values
+
+Studio provides two mechanisms for experimentally changing numeric
+values in the Inspector palette when you are not sure of the exact value
+you want.
+
+\list 1
+\li
+ When a numeric input is \b{not} already focused (ready to be
+ typed into), click and drag the mouse up and down on the number you
+ want to change. The value will increase or decrease as you drag the
+ mouse, and the scene view will update to show the effect of the
+ change.
+\li
+ With a numeric input focused, press the up/down arrow keys to
+ increment/decrement the value by 1 for each key press.
+\endlist
+With both of these techniques, you can hold down the \b{shift} key
+to make the values adjust by 10 instead of 1, or hold down the
+\b{control} key to make the values adjust by 0.1 instead.
+
+\target scenecomponent-properties
+\section1 Scene/Component Properties
+
+Scenes and components are both \"time contexts\". When their contents
+are displayed in the Timeline palette (when you are \"inside\" the scene
+or component) and the element is selected, the following properties are
+shown in the Inspector palette \e{specific to the active slide}:
+
+\list
+\li
+ \b{Play Mode}: Controls what happens when the playhead reaches
+ the end time for the slide:
+\list
+\li
+ \c{Stop at end} - This default value simply holds the playhead at
+ the end time, with any animated properties holding their final value.
+\li
+ \c{Looping} - Upon reaching the final time the playhead starts
+ over at time 0.
+\li
+ \c{PingPong} - Upon reaching the final time the playhead starts
+ playing backwards; upon reaching time 0 the playeah starts playing
+ forwards again.
+\li
+ \c{Ping} - Similar to \e{PingPong}, but when the playhead
+ reaches time 0 it stops playback and holds that time.
+\li
+ \c{Play Through To...} - Upon reaching the final time the
+ scene or component will switch to a new slide. This is useful to have
+ an intro animation that then leads into a looping animation (on a
+ separate slide). You may specify a specific slide to play through to,
+ or simply the next/previous slide in the Slide palette. \^{}
+\endlist
+\li
+ \b{Initial Play State} - When entering this slide, should the
+ playhead immediately start playing, or wait to be started? Using the
+ \b{Pause} setting is particularly useful when QML application is going
+ to control the time for the context and you don't
+ need or want the runtime attempting to do its own work.
+\endlist
+
+\target layer-properties
+\section1 Layer
+Properties
+
+Selecting a layer in the Timeline palette shows the following properties
+in the Inspector palette:
+
+\list
+\li
+ \b{Disable Depth Test} - Controls whether depth-testing is used
+ when rendering objects in the layer. For details see the discussion on
+ the
+ \e{\l{best-practices-disable-depth-test.html}{Disable Depth Test}} page.
+\li
+ \b{Progressive AA} - Controls whether progressive anti-aliasing
+ is used when rendering the layer. For details see the discussion on
+ \e{\l{best-practices-antialiasing.html#progressive-aa}{Progressive Anti-Aliasing}}.
+\li
+ \b{Multisample AA} - Controls whether multisample anti-aliasing
+ is used when rendering the layer. For details see the discussion on
+ \e{\l{best-practices-antialiasing.html#multisample-aa}{Multisample Anti-Aliasing}}.
+\li
+ \b{Temporal AA} - Controls whether temporal anti-aliasing is used
+ when rendering the layer. For details see the discussion on
+ \e{\l{best-practices-antialiasing.html#temporal-aa}{Temporal Anti-Aliasing}}.
+\li
+ \b{Layer Background} - Controls how the layer clears when it
+ starts to render each frame:
+\list
+\li
+ \c{Transparent} - Clear the layer to transparent each frame so
+ that content behind it can be seen.
+\li
+ \c{Unspecified} - Do not clear layer each frame. This provides a
+ slight performance boost if the layer is filled with content, and
+ hence will fully overwrite the previous result.
+\li
+ \c{Solid Color} - Clear this layer to a non-transparent color.
+ This provides a slight performance boost if the layer fills the
+ viewport \b{and} if you turn off \"Enable Background Color\" for
+ the Scene.
+\endlist
+\li
+ \b{Blend Mode} - Controls how colors in the active layer blends with colors in the background
+ layer. For details see the discussion on the
+ \e{\l{best-practices-blend-mode.html}{Blend Mode}} page.
+\list
+\li
+ \c{Normal} - Default blend mode. Opaque objects will occlude objects in layers behind.
+\li
+ \c{Screen} - Colors are blended using an inverted multiply, producing a lighter result.
+\li
+ \c{Multiply} - Colors are blended using a multiply, producing a darker result.
+\li
+ \c{Add} - Colors are blended by addition, producing a lighter result.
+\li
+ \c{Subtract} - Colors are blended by subtraction, producing a darker result.
+\li
+ \c{Overlay} - A mix of \c Multiply and \c Screen modes, producing a result with higher contrast.
+\li
+ \c{Colorburn} - Colors are blended by inverted division where the result also is inverted,
+ producing a darker result. Darker than \c Multiply.
+\li
+ \c{Colordodge} - Colors are blended by inverted division, producing a lighter result. Lighter
+ than \c Screen.
+\endlist
+\li
+ \b{Horizontal Fields} - Choose which two fields of \c{Left},
+ \c{Width}, and \c{Right} are used to control the horizontal
+ placement and sizing of the layer within the presentation.
+\li
+ \b{Left} - The distance between the left edges of the
+ presentation and the layer, either in pixels or as a percentage of the
+ presentation's width.
+\li
+ \b{Width} - The width of the layer, either in pixels or as a
+ percentage of the presentation's width.
+\li
+ \b{Right} - The distance between the right edges of the
+ presentation and the layer, either in pixels or as a percentage of the
+ presentation's width.
+\li
+ \b{Vertical Fields} - Choose which two fields of \c{Top},
+ \c{Height}, and \c{Bottom} are used to control the vertical
+ placement and sizing of the layer within the presentation.
+\li
+ \b{Top} - The distance between the top edges of the presentation
+ and the layer, either in pixels or as a percentage of the
+ presentation's height.
+\li
+ \b{Height} - The height of the layer, either in pixels or as a
+ percentage of the presentation's height.
+\li
+ \b{Bottom} - The distance between the bottom edges of the
+ presentation and the layer, either in pixels or as a percentage of the
+ presentation's height.
+\li
+ \b{Sub-Presentation} - If you specify a value here, it is
+ intepreted to be the \c{id} attribute of another presentation in
+ \omit
+ TODO: Not really usable right now.
+ \l{file-formats-uia.html}{the \c{.uia} application file}.
+ \endomit
+ the \c{.uia} application file.
+ Instead of rendering the contents of this layer,
+ the specified presentation will be rendered and composited in place of
+ this layer. For more information, see the discussion on the
+ \e{\l{best-practices-using-sub-presentations.html}{Using Sub-Presentations}} page.
+\li
+ \b{Ambient Occlusion} - Controls the strength of ambient
+ occlusion (AO). AO is a form of approximated global illumination which
+ causes non-directional self-shadowing where objects are close
+ together. A value of \c{100} causes full darkness shadows; lower
+ values cause the shadowing to appear lighter. A value of \c{0}
+ disables ambient occlusion entirely, improving performance at a cost
+ to the visual realism of 3D objects rendered in the layer. All values
+ other than \c{0} have the same impact to the performance.
+\li
+ \b{AO Distance} - Roughly how far (in world units) ambient
+ occlusion shadows spread away from objects. The following graphic
+ illustrates a variety of distances, starting with 0 (no AO) at left.
+ Greater distances cause increasing impact to performance.
+\raw HTML
+<a href=images/Runtime-AODistances.jpg>
+\endraw
+\image Runtime-AODistances.jpg
+\raw HTML
+</a>
+\endraw
+\li
+ \b{AO Softness} - How smooth the edges of the AO shading are. The
+ following graphic illustrates a variety of softness values, going from
+ \c{0} at left to \c{100} at right.
+ \raw HTML
+<a href=images/Runtime-AOSoftnesses.jpg>
+\endraw
+\image Runtime-AOSoftnesses.jpg
+\raw HTML
+</a>
+\endraw
+\li
+ \b{AO Threshold} - A cutoff distance preventing objects from
+ exhibiting AO at close distances. Higher values increase the distance
+ required between objects before AO is seen.
+ \list
+ \li
+ \note If you see AO shadowing on objects where there should be
+ no shadowing, increase the AO Threshold value slightly to clip away
+ close results.
+ \endlist
+\li
+ \b{AO Sampling Rate} - Larger values result in better AO quality
+ (more shades of gray) at the expense of performance.
+\li
+ \b{AO Detail} - Scatters the edges of the AO shadow bands to
+ improve smoothness (at the risk of sometimes producing obvious
+ patterned artifacts).
+ \list
+ \li
+ \note Very large distances between the clipping planes of your
+ camera may cause problems with AO. If you are seeing odd banding in
+ your AO, try adjusting the Far Clip Plane of your camera to be closer
+ to your content.
+ \endlist
+\li
+ \b{Shadow Strength} - Controls the strength of directional
+ occlusion (DO). DO is a form of approximated directional shadowing. A
+ value of \c{100} causes full darkness shadows; lower values cause
+ the shadowing to appear lighter. A value of \c{0} disables DO
+ entirely, improving performance at a cost to the visual realism of 3D
+ objects rendered in the layer. All values other than \c{0} have
+ the same impact to the performance.
+ \list
+ \li
+ \note Directional occlusion will only render on \e{Standard Materials}
+ that have the \l{standard-materials}{Lighting property} set to \c{Pixel}.
+ \endlist
+\li
+ \b{Shadow Distance} - Roughly how far (in world units) the faked
+ shadows spread away from objects.
+\li
+ \b{Shadow Softness} - Crossfade amount between sharp shadows and
+ smooth gradations.
+\li
+ \b{Shadow Threshold} - A cutoff distance preventing objects from
+ self-shadowing. Higher values increase the distance required between
+ objects before DO is seen.
+ \list
+ \li
+ \note If you see DO shadowing in regions where there should be
+ no shadowing, increase the Shadow Threshold value slightly to clip
+ away close results.
+ \endlist
+\li
+ \b{Light Probe} - Select an image (preferably a high dynamic
+ range image (\c{.hdr})) to use to light the scene, either instead of or
+ in addition to standard lights. If selected, note that this image will
+ be used as the environment for any custom \c{.material}, instead
+ of the environment often associated with them.
+\li
+ \b{IBL Brightness} - The amount of light emitted by the light probe.
+\li
+ \b{IBL Horizon Cutoff} - Increasing the value will add darkness (black)
+ to the bottom half of the environment, forcing the lighting to come
+ predominantly from the top of the image (and removing specific
+ reflections from the lower half).
+\li
+ \b{IBL FOV Angle} - The image source field of view.
+\li
+ \b{Secondary Light Probe} - Select an image to use as secondary IBL light source.
+\li
+ \b{Probe Crossfade} - The blend amount between the primary and secondary light probes.
+\endlist
+
+\target transform-properties
+\section1 Transform
+Properties
+
+Selecting an element in the Timeline palette that has a 3D presence
+shows the following properties in the Inspector palette:
+
+\list
+\li
+ \b{Position} - The local position of the element in the space
+ established by the parent element. Note that Qt 3D Studio uses
+ a Y-up \"left-handed\" coordinate system. Increasing values of X go to
+ the right (as seen from the default camera location), increasing
+ values of Y go up, and increasing values of Z go away from the camera.
+\li
+ \b{Rotation} - The local rotation of the element in the space
+ established by the parent element. Each value is the left-handed
+ rotation about the axis in question, with the direction of the axes as
+ described above. Rotations are applied in the order ZXY.
+\li
+ \b{Scale} - The local scale of the element in the space
+ established by the parent element. Note that an odd-number of negative
+ scale values will cause your element to render 'inside-out', which
+ cannot be seen due to backface-culling.
+\li
+ \b{Pivot} - The local pivot offset for the object. You can think
+ of the pivot as offsetting the geometry for the element away from the
+ origin, allowing an object to rotate and scale around a point other
+ than its local origin. Pivots are applied before scaling and rotation.
+\li
+ \b{Opacity} - Although not technically a transformation, every
+ transformable element has an opacity applied to it. An opacity of 100
+ causes the object to be fully opaque, while an opacity of 0 prevents
+ an object from rendering at all.
+\endlist
+
+Just as modifying the position or rotation of a parent element affects
+all descendant elements, opacity is multiplicatively cumulative through
+the transform hierarchy. A cube that is 50\% opaque inside a group that
+is 80\% opaque will render with an equivalent apperance of 40\% opacity
+(\c{0.8 * 0.5 = 0.4}). Setting the opacity of a group to 0 will
+prevent any descendants within the group from rendering.
+
+For models, having an equivalent opacity of 0 also prevents any touch
+events from being processed for the element. If you can't see the cube,
+you can't click on it. Note, however, that you may alternatively adjust
+the \l{material-properties}{opacity of a material} to 0. In this
+case you cannot see the model but you \b{can} click on it.
+
+\section1 Camera Properties
+
+A camera selected in the Timeline palette shows the following properties
+in the Inspector palette (in addition to the
+\l{transform-properties}{transform properties} described above):
+
+\list
+\li
+ \b{Orthographic} - When enabled, the layer for this camera
+ renders all contents with no perspective. Additionally the default
+ scale of the camera ensures that each world unit renders at exactly
+ one pixel in the final presentation.
+\endlist
+
+Orthographic layers (layers with a camera set to be orthographic) are
+ideal for layering 2D UI elements. Not only are your images guaranteed
+to be the right size on the screen, you can use the Z position of
+objects to bring them closer to/farther from the camera (z-sorting) with
+no foreshortening artifacts.
+
+\list
+\li
+ \b{Field of View} - For perspective cameras (ones without the
+ Orthographic box checked), this is the number of degrees between the
+ top and bottom edges of the camera frustum. The larger the value, the
+ stronger the sense of 3D in your scene. The horizontal field of view
+ is automatically calculated based on the aspect ratio of the
+ presentation as authored in Studio.
+\li
+ \b{Clipping Start/End} - Content closer to the camera than the
+ clipping start or farther than the clipping end will not be rendered.
+ This occurs at the pixel level, not the element level: a model that
+ crosses the clipping plane may be only partially rendered.
+\endlist
+\omit
+TODO: Replace the following paragraph with this once AO is back.
+\e{The default values are intended to cause anything within the view
+of the camera to be rendered. Aside from special clipping effects, you
+may need to adjust these values to more closely contain your content for
+better results with Ambient Occlusion, or with a layer effect that uses
+the depth buffer of the camera, such as the
+\endomit
+\e{The default values are intended to cause anything within the view
+of the camera to be rendered. Aside from special clipping effects, you
+may need to adjust these values to more closely contain your content for
+better results with a layer effect that uses the depth buffer of the camera, such as the
+\l{best-practices-effects.html#using-depth-of-field}{Depth of Field effect}.}
+
+\list
+\li
+ \b{Scale Mode} - When the final size of the layer is different
+ than the presentation size (due to the
+ \l{file-formats-uia.html#application}{application scale mode} and/or
+ the \l{layer-properties}{layer size}), this
+ setting controls how the camera adjusts to fill the space:
+\list
+\li
+ \c{Fit} - render the content seen by the camera (based on the
+ aspect ratio of the presentation) larger or smaller to fit within the
+ layer. When the aspect ratio of the layer is different than the
+ presentation additional content will be shown \e{either}
+ above/below or left/right; the content seen by the camera will never
+ be cropped.
+\li
+ \c{Same Size} - render the content seen by the camera at the same
+ size (same number of pixels) as seen when the layer size is the same
+ as the presentation sized authored in Studio. Layers smaller than the
+ original presentation size will cause content to be cropped, while
+ larger layers will cause additional content (beyond the original
+ bounds of the camera) to be shown.
+\endlist
+\li
+ \b{Scale Anchor} - When changes to the layer size cause the
+ camera to render more or less content this property controls which
+ part of the content stays in the same spot relative to the layer. A
+ value of \c{Center} causes the center of the camera to always
+ remain in the center of the layer, a value of \c{NW} causes the
+ upper left corner of the content seen in Studio to always be at the
+ upper left corner of the layer, a value of \c{N} causes the top
+ middle of the content seen in Studio to always be at the top middle
+ edge of the layer, and so forth.
+\endlist
+
+\section1 Light Properties
+
+A light selected in the Timeline palette shows the following properties
+in the Inspector palette (in addition to the
+\l{transform-properties}{transform properties} described above):
+
+\list
+\li
+ \b{Scope} - Select an element to have this light affect only that
+ element and its descendants.
+\li
+ \b{Light Type}\target light-properties\_light-type
+ - Choose
+ whether the light is a directional or point light:
+\list
+\li
+ \c{Directional} - Lighting is applied uniformly in the direction
+ of the Z axis for this light. The rotation of directional lights
+ affects the result, but not the position or scale.
+\li
+ \c{Point} - Lighting is applied outwards from the center of the
+ light, becoming increasingly dim away from the center. (See the
+ \e{Brightness} and \e{Linear}/\e{Exponential Fade} properties
+ below.) The position of point lights affects the result, but not the
+ rotation or scale.
+\li
+ \c{Area} - Lighting emits from the +Z face of a rectangular
+ light. Use the X/Y scale transforms to control the size of the area
+ light.
+ \list
+ \li
+ \e{Tip: turn on Bounding Boxes (Ctrl-B) to see the size of the
+ area light when selected.}
+ \endlist
+\endlist
+\li
+ \b{Light Color} - The diffuse color (and intensity) applied to
+ models illuminated by this light.
+\li
+ \b{Specular Color} - The specular color (and intensity) applied
+ to models illuminated by this light. Note that a model's material must
+ have a non-zero \e{Specular Amount} for any specular lighting to
+ take effect.
+\li
+ \b{Ambient Color} - The diffuse color (and intensity) applied to
+ materials before being lit by this light.
+\li
+ \b{Brightness} (point light only) - An overall multiplier for the
+ light's effects.
+\li
+ \b{Linear Fade} (point light only) - Turn up this value to
+ increase the rate at which the lighting effect dims the farther
+ surfaces are from the light.
+\li
+ \b{Exponential Fade} (point light only) - Turn up this value to
+ increase the rate at which the lighting effect dims on surfaces that
+ are extra far away from the light.
+\li
+ \b{Cast Shadows?}\target light-properties\_cast-shadows
+ - Simulate
+ shadows using this light?
+\li
+ \b{Shadow Darkness} - How dark should the cast shadows be?
+\li
+ \b{Shadow Softness} - Amount of blur applied to the shadows.
+\li
+ \b{Shadow Resolution} - Size of the shadow map created for the
+ shadows (affects performance and memory usage).
+\li
+ \b{Shadow Depth Bias} - Tweak this value by small amounts if you
+ see objects casting shadows on themselves.
+\li
+ \b{Shadow Far Clip} - Maximum distance for the shadow map;
+ smaller values may improve the precision and effects of the map.
+\endlist
+
+\b Notes:
+
+\list
+\li
+ Each additional light will reduce rendering performance of your
+ presentation. Use them sparingly. Employ a
+ \l{layer-properties}{light probe} on the layer for image-based
+ lighting that can produce soft and subtle lighting.
+\li
+ The \e{Lighting} property for materials (see below) affects the
+ quality/performance of lighting on a per-material basis.
+\li
+ When using only a light probe, or when using an interface layer where
+ the materials are all set to use \c{None} for the lighting, it is
+ valid and beneficial to delete all lights from a layer.
+\li
+ Cast shadows work best with area or point lights.
+\endlist
+
+\target model-properties
+\section1 Model
+Properties
+
+A model selected in the Timeline palette shows the following properties
+in the Inspector palette (in addition to the
+\l{transform-properties}{transform properties} described above):
+
+\list
+\li
+ \b{Mesh} - A \"model\" is just a notional placeholder for
+ displaying geometry, and you may change which geometry is displayed
+ (when authoring in Studio, or during Runtime) by picking a new mesh
+ for the geometry. Clicking the drop-down for this property will open a
+ floating mesh picker. Hover a mesh to see how it appears in the scene
+ for this model, and click on a mesh to pick it as the new mesh.
+\li
+ \b{Tesselation Mode} - Dynamically generate additional geometry
+ for the model. Tessellation is useful if you are using a
+ \l{material-properties_displacement-map}{displacement map} with
+ your geometry, or if you wish to generate a smoother silhouette (Phong
+ and NPatch tessellation modes only) when zooming in.
+\li
+ \e{Tip: turn on tessellation wireframe mode (View menu or toolbar)
+ to display the tessellation result.}
+\endlist
+
+\target material-properties
+\section1 Material
+Properties
+
+A material selected in the Timeline palette shows the different
+properties in the Inspector palette depending on the type of the
+material, chosen in the top-most property:
+
+\list
+\li
+ \b{Material Type} - Controls the type of material to be used. The
+ values are \"Standard Material\" and \"Referenced Material\", followed
+ by a list of any custom \c{.material} files present your
+ application folder.
+\li
+ \e{Tip: Material Type is a special type of property that cannot be
+ unlinked or changed at runtime. If you want to change the type of
+ material used for a model, set the material type to \"Referenced
+ Material\" and then unlink the
+ \l{referenced-materials}{Referenced Material property} to
+ reference different materials during runtime.}
+\endlist
+
+\target standard-materials
+\section2 Standard
+Materials
+
+\list
+\li
+ \b{Lighting} - Choose the type of lighting calculations used for
+ this material:
+\list
+\li
+ \c{Pixel} - Diffuse and specular lighting is calculated for each
+ rendered pixel. This produces better results than Vertex lighting, but
+ is slightly more expensive to compute. Certain effects (such as a
+ Fresnel or bump map) require Pixel lighting to work.
+\li
+ \c{None} - No lighting is calculated. This mode is (predictably)
+ very fast, and is quite effective when image maps are used that you do
+ not need to be shaded by lighting.
+\endlist
+\li
+ \b{Blending Mode} - Choose how the colors of this object blend
+ with those behind it. For details see the discussion on the
+ \e{\l{best-practices-blend-mode.html}{Blend Mode}} page.
+\list
+\li
+ \c{Normal} - Default blend mode. Opaque objects occlude objects behind them.
+\li
+ \c{Screen} - Colors are blended using an
+ inverted multiply, producing a lighter result. This blend mode is
+ order-independent; if you are using semi-opaque objects and
+ experiencing 'popping' as faces or models sort differently, using
+ Screen blending is one way to produce results without popping.
+\li
+ \c{Multiply} - Colors are blended using a multiply, producing a darker result.
+ This blend mode is also order-independent.
+\li
+ \c{Overlay} - A mix of \c Multiply and \c Screen modes, producing a result with higher contrast.
+\li
+ \c{Colorburn} - Colors are blended by inverted division where the result also is inverted,
+ producing a darker result. Darker than \c Multiply.
+\li
+ \c{Colordodge} - Colors are blended by inverted division, producing a lighter result.
+ Lighter than \c Screen.
+\endlist
+\li
+ \b{Diffuse Color} - The base color for the material. Set to black
+ to create a purely-specular material (e.g. metals or mirrors).
+\li
+ \b{Diffuse Map/2/3} - Image maps to apply to the material as a
+ texture. Click to pick an image from the project directory. Using an
+ image format with transparency (e.g. PNG or DDS with DXT5) will also
+ apply the alpha channel as an opacity map.
+\li
+ \b{Specular Reflection} - An image map used for specular
+ highlights on the material. By default the map is applied using
+ environmental mapping (not UV mapping): as you rotate the model the
+ map will appear as though it is reflecting from the environment.
+ Specular Reflection maps are an easy way to add a high-quality look
+ with relatively low cost.
+\list
+\li
+ \e{Tip: Using a Light Probe on your Layer for image-based lighting
+ will automatically use that image as the specular reflection.}
+\li
+ \e{Tip: Studio comes installed with a variety of helpful specular
+ maps for your use. Click the maps button at the bottom of the Project
+ palette to open the library, open the Specular Reflection folder, and
+ drag maps into the Project palette to copy them to your project.}
+\li
+ \e{Tip: Crisp images cause your material to look very glossy; the
+ more you blur your image the softer your material will appear.}
+\endlist
+\li
+ \b{Specular Tint} - A color used to adjust the specular
+ reflections. Use white for no effect
+\li
+ \b{Specular Amount} - Controls the strength of specularity
+ (highlights and reflections). Note that this property does not affect
+ the Specular Reflection map, but does affect the amount of reflections
+ from a layer's \l{layer-properties}{Light Probe}.
+\list
+\li
+ \e{Tip: Unless your mesh is high resolution, you may need to use
+ Pixel lighting (see above) to get good specular highlights from scene
+ lights.}
+\endlist
+\li
+ \b{Specular Map} - A grayscale image map to modulate the amount
+ of specularity across the surface of the material. These values are
+ multiplied by the Specular Amount.
+\li
+ \b{Specular Roughness} - Controls the size of the specular
+ highlight generated from lights, and the clarity of reflections in
+ general. Larger values increase the roughness, softening specular
+ highlights and blurring reflections.
+\li
+ \b{Fresnel Power} - Decreases head-on reflections (looking
+ directly at the surface) while maintaining reflections seen at grazing
+ angles.
+\li
+ \b{Index of Refraction} - Controls what angles of reflections are
+ affected by the Fresnel Power.
+\li
+ \b{Bump Map} - A grayscale image map to \e{simulate} fine
+ geometry displacement across the surface of the material. Brighter
+ pixels indicate raised regions. The amount of the effect is controlled
+ by the Bump Amount property.
+\list
+\li
+ \e{Tip: Bump maps will not affect the silhouette of a model. Use a
+ displacement map if this is required.}
+\endlist
+\li
+ \b{Normal Map} - An RGB image used to \e{simulate} fine
+ geometry displacement across the surface of the material. The RGB
+ channels indicate XYZ normal deviations. The amount of the effect is
+ controlled by the Bump Amount property.
+\list
+\li
+ \e{Tip: Normal maps will not affect the silhouette of a model. Use
+ a displacement map if this is required.}
+\endlist
+\li
+ \b{Bump Amount} - Controls the amount of simulated displacement
+ for a Bump Map or a Normal Map.
+\li
+ \b{Displacement Map}\target material-properties\_displacement-map
+
+ - A grayscale image used to offset the vertices of geometry across the
+ surface of the material. Brighter pixels indicate raised regions. The
+ amount of the effect is controlled by the Displacement Amount
+ property.
+\list
+\li
+ \e{Tip: Displacement maps require vertices to offset. If your model
+ is not high-enough resolution you may need to dynamically generate
+ additional vertices by using the
+ \l{model-properties}{Tessellation properties} on the model.}
+\li
+ \e{Tip: Displacement maps do not affect the normals of your
+ geometry. To look correct with lighting or reflections you will likely
+ want to also add a matching bump map or normal map to your material.}
+\endlist
+\li
+ \b{Emissive Power} - The amount of self-illumination from the
+ material. In a scene with black ambient lighting a material with 0
+ emissive power will appear black wherever the light does not shine on
+ it; turning the emissive power to 100 will cause the material to
+ appear as its diffuse color instead.
+\list
+\li
+ \e{Tip: When you want a material to not be affected by lighting,
+ instead of using 100\% emissive power consider setting the lighting
+ mode to} \c{None} \e{for a performance benefit.}
+\endlist
+\li
+ \b{Emissive Map} - An image map used to set the emissive power
+ for different parts of the material. Using a grayscale image will not
+ affect the color of the result, while using a color image will produce
+ glowing regions with the color affected by the emissive map.
+\li
+ \b{Opacity} - Drop the opacity of just this material, separate
+ from the model.
+\list
+\li
+ Note: Setting the opacity of a \e{model} very low (below 1\% or
+ less) will prevent it from receiving touch events, but setting the
+ opacity of its \e{material} very low still allows touch events to
+ occur.
+\endlist
+\li
+ \b{Opacity Map} - An image map used to control the opacity
+ differently for different parts of the material. Note that you must
+ use an image format with transparency (e.g. a 32-bit PNG, or a DDS
+ with an alpha portion) for the opacity to be applied. You cannot use a
+ grayscale PNG file, for example, to control the opacity.
+\endlist
+Note that the Runtime custom-compiles shaders for each unique
+combination of material properties used. Each additional material
+feature that you use results in a (slight) additional performance hit.
+
+\target referenced-materials
+\section2 Referenced Materials
+
+A \"referenced material\" uses whatever settings are present on another
+material element. This both allows you to have 'master'
+materials - changing the settings on one material affects all the
+others - and also provides a mechanism for quickly switching between
+different material types (in either Studio or at runtime). When you
+select this type of material, the Inspector palette shows only a single
+property:
+
+\list
+\li
+ \b{Referenced Material} - a picker for selecting another material
+ within the presentation.
+\li
+ \e{Tip: the material you reference does \b{not} have to be
+ visible or even active for this to work. It is valid to have a small
+ pile of models with custom materials on them all eyeballed off, and
+ then reference those materials for rendering on other objects.}
+\endlist
+\section1 Image Properties
+
+When image maps are applied to a material (e.g. Diffuse, Specular,
+Opacity, etc.) a new element appears in the Timeline palette as a child
+of the material. This element represents the properties that control
+that image, allowing them to be animated over time. Selecting one of
+these images shows the following properties in the Inspector palette:
+
+\list
+\li
+ \b{U/V Repeat} - Controls how many copies of the image are
+ displayed across the UV coordinates of the material. With UV Tiling
+ set to \"No Repeat\" this will cause the image to only show once on a
+ smaller portion of the material.
+\li
+ \b{Texture Mapping} - Choose how the image is applied to the
+ material:
+\list
+\li
+ \c{UV Mapping} - The default for diffuse and opacity maps, this
+ causes the image to be stuck to the mesh. The same portion of the
+ image will always appear on the same vertex (unless the UV properties
+ are animated).
+\li
+ \c{Environmental Mapping} - The default for specular reflection,
+ this causes the image to be 'projected' onto the material as though it
+ is being reflected. Using Environmental Mapping for diffuse maps
+ provides a mirror effect.
+\endlist
+\li
+ \b{U/V Tiling} - Controls how the image map is applied across the
+ material when the U/V repeat values are greater than 1.
+\li
+ \b{UV Rotation} - Rotates the image map around the pivot point.
+\li
+ \b{U/V Position} - Slides the image map across the UV
+ coordinates.
+\li
+ \b{U/V Pivot} - Sets the pivot location in UV space.
+\li
+ \b{Sub-Presentation} - If you specify a value here, it is
+ intepreted to be the \c{id} attribute of another presentation in
+\omit
+ TODO: Not really usable yet.
+ \l{file-formats-uia.html}{the \c{.uia} application file}.
+\endomit
+ the \c{.uia} application file.
+ Instead of displaying the contents of this image on
+ the material, the specified presentation will be rendered and the
+ resulting image will be used instead. For more information, see the
+ discussion on the
+ \e{\l{best-practices-using-sub-presentations.html}{Using Sub-Presentations}} page.
+\endlist
+
+\section1 Text Properties
+
+A text element selected in the Timeline palette shows the following
+properties in the Inspector palette (in addition to the
+\l{transform-properties}{transform properties} described above):
+
+\list
+\li
+ \b{Text String} - The text to display for the text element.
+\list
+\li
+ \e{Note: Qt 3D Studio does not (currently) support styled
+ text. There is no way to make one word in a paragraph bold, larger, or
+ a different color.}
+\li
+ \e{Note: Qt 3D Studio also does not (currently) support automatically
+ wrapping text; you must manually inject line breaks to wrap your text.}
+\endlist
+\li
+ \b{Text Color} - The color for the text.
+\li
+ \b{Font} - Click to open a font browser. This will only look for
+ font files \e{inside the \c{fonts} directory} for your
+ project.
+\omit
+TODO: Only one font for now. More to be added?
+\list
+\li
+ \e{Tip: Studio comes with a small library of fonts licensed under
+ the Open Font License. Click the second button at the bottom of the
+ Project palette to open the Font Library, find one or more font files
+ that you like and drag them into the \c{fonts} folder of your
+ Project palette to copy the font(s) to your project.}
+\endlist
+\endomit
+\li
+ \b{Font Size} - Changes the size of the font. In addition to
+ clicking the drop-down to pick from predefined font sizes, you can
+ also type a new value for the font.
+\list
+\li
+ \e{Tip: Although the font size is just a number, it is
+ intentionally not animatable. Each time the font size changes a rather
+ expensive rasterization of the text string occurs. You should animate
+ the scale of the text element instead.}
+\endlist
+\li
+ \b{Horizontal/Vertical Alignment} - Controls the placement of the
+ text with respect to the text element's origin. Note that this is for
+ the entire text box, and as such may include padding reserved for
+ characters not present in your text string. \e{(For example, using
+ the Text String \"Text\" with Vertical Alignment of \b{Bottom}
+ will cause the baseline of the letters to appear above the origin for
+ the element. Adding characters with descenders, such as \"y\",
+ illustrates why this occurs.)}
+\li
+ \b{Leading} - Controls the amount of extra (or negative) vertical
+ spacing between lines of text.
+\li
+ \b{Tracking} - Controls the amount of extra (or negative)
+ horizontal spacing between every character pair.
+\endlist
+
+\section1 Alias Properties
+
+An \l{studio-basic-objects-palette.html#alias}{alias} selected in
+the Timeline palette shows the following properties in the Inspector
+palette (in addition to the \l{transform-properties}{transform properties} described above):
+
+\list
+\li
+ \b{Reference} - the node to create an alias of.
+\li
+ \e{Note that you cannot create an alias of a Scene, Layer,
+ Behavior, Material, Effect, or Image element. You can only alias items
+ that have a transform, i.e. groups, components, cameras, lights,
+ models, and text.}
+\endlist
+\section1 Path Properties
+
+A \l{best-practices-paths.html}{path} selected in the
+Timeline palette shows the following properties in the Inspector palette
+(in addition to the \l{transform-properties}{transform properties}
+described above):
+
+\list
+\li
+ \b{Path} - the \c{.path} file on disk to reference for this
+ path, or \c{[None]} if this path has been
+ \l{best-practices-paths.html#internalized-paths}{internalized}.
+\li
+ \b{Stroke Width} - the size of the stroke in local units.
+\li
+ \b{Path Type}
+\list
+\li
+ \c{Painted} - the path is filled and/or stroked with perfect
+ precision and UV coordinates relative to the bounding box.
+\li
+ \c{Geometry} the path is stroked with geometry with customizable
+ tessellation. UV coordinates are relative to the path, i.e. along and
+ across the length.
+\endlist
+\endlist
+
+\section2 For Painted Paths
+
+\list
+\li
+ \b{Paint Style}
+\list
+\li
+ \c{Filled and Stroked} - the path has independent materials for
+ the fill and stroke.
+\li
+ \c{Filled} - the path has only one material, for the fill.
+\li
+ \c{Stroked} - the path has only one material, for the stroke.
+\endlist
+\endlist
+
+\section2 For Geometry Paths
+
+\list
+\li
+ \b{CPU Limit} - amount of tessellation work done on the CPU
+ before GPU tessellation is involved; lower numbers use more CPU
+ values. Edge and Width Detail are applied after the CPU is done.
+\list
+\li
+ \e{Tip: for best performance you usually want to leave this at a
+ high value, leaning mostly on the GPU for tessellation.}
+\endlist
+\li
+ \b{Edge Detail} - amount of GPU tessellation detail used to
+ improve the appearance of the stroke.
+\list
+\li
+ \e{Tip: Turn on Wireframe
+ view (from the View menu or the toolbar) to see the underlying
+ geometry being created for the stroke.}
+\endlist
+\li
+ \b{Width Detail} - amount of GPU tessellation detail used to
+ create geometry across the width of the stroke. Unless you are using a
+ material with a displacement map for the stroke, you likely should
+ leave this set at the lowest setting to improve performance.
+\list
+\li
+ \e{Tip: Turn on Wireframe view (from the View menu or the toolbar)
+ to see the underlying geometry being created for the stroke.}
+\endlist
+\li
+ \b{Begin/End Cap Style} - set this to \"Taper\" to finely taper
+ the end of your stroke over a specified distance. Additional
+ properties will appear allowing you to control the length of the
+ taper, and the size and opacity at the end of the taper.
+\endlist
+
+\section1 SubPath Properties
+
+When you have
+\l{best-practices-paths.html#internalized-paths}{internalized}
+a path you will see a SubPath child element in the Timeline for each set
+of path commands in the path. Selecting this element shows a single
+property allowing you to modify whether the SubPath is \"closed\" or
+not:
+
+\list
+\li
+ \b{Closed Path?} - should the stroke for the path be 'closed',
+ drawing a straight line from the last anchor point to the first?
+\li
+ \e{SubPaths in SVG are always 'closed' with respect to the fill.
+ This property only affects the stroke.}
+\endlist
+
+\section1 Anchor Point Properties
+
+When you have
+\l{best-practices-paths.html#internalized-paths}{internalized}
+a path each SubPath element in the Timeline will have child Anchor Point
+elements for each point along the path. Selecting these elements shows
+the following properties in the Inspector palette:
+
+\list
+\li
+ \b{Position} - the 2D location of the point with respect to the
+ origin of the path. \e{(Though the entire path lives in 3D space
+ within the presentation, the points are all constrained to the same 2D
+ plane, which you may choose to position or rotate in 3D space.)}
+\li
+ \b{Handle Angle} - every anchor is treated as a cubic Bézier with
+ a locked (smooth) tangent. This property controls the angle of that
+ tangent measured counter-clockwise from horizontal going right to
+ left.
+\li
+ \b{Incoming/Outgoing Distance} - the distance of the control
+ point from the anchor. The \"Incoming\" value is meaningless for the
+ first anchor point, as is the \"Outgoing\" value for the last anchor
+ point.
+\endlist
+
+*/
diff --git a/doc/src/03-studio/8-action-palette.qdoc b/doc/src/03-studio/8-action-palette.qdoc
new file mode 100644
index 00000000..0a9e7150
--- /dev/null
+++ b/doc/src/03-studio/8-action-palette.qdoc
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Action Palette
+\page studio-action-palette.html
+\ingroup qt3dstudio-studio
+
+\image Studio-Action.png
+
+\e Actions provide a way for an artist to create interactivity in a
+presentation without scripting. Actions listen for an event to occur on
+an element (or, due to event bubbling, on any descendant of the
+element), and when it occurs they cause an effect in the presentation.
+This effect may be a direct modification of the presentation (tell a
+component to switch slides, change the color of an element).
+
+\section1 Creating Actions
+
+An action is defined by five attributes:
+
+\list
+\li
+ The element that the action is attached to (the \"home element\").
+\li
+ The element that the action is listening to (the \"Trigger Object\").
+\li
+ The event that the action is listening for (the \"Trigger Event\").
+\li
+ The element that the action will control (the \"Target Object\").
+\li
+ The handler to invoke on the target element (with possible additional
+ parameters).
+\endlist
+
+To create an action, first choose the slide and home element that the
+action is attached to. Actions may be non-master, taking effect only on
+a particular slide. For your sanity, we recommend attaching the action
+to either the Trigger or Target object.
+
+Second, click the \b {New Action} button in the Action palette. An action
+will be created and selected, with its properties set to default values.
+Modify these properties in the bottom half of the Action palette as
+appropriate.
+
+\section1 Managing Actions
+
+Actions may be deleted by clicking on the action summary at the top of
+the Actions palette and pressing the \c{Delete} key, by choosing
+\c{Delete Action} after right-clicking on an action sumary, or by
+selecting the action summary and clicking the trash can icon at the
+bottom of the Actions palette.
+
+Tip: it is possible to have an action visually selected at the same time
+as Studio thinks that a different palette (for example, the Timeline palette) is
+actually accepting keyboard input. If you press the \c{Delete} key,
+you might want to double-check and ensure that only the action was
+deleted, and not the element that was selected in the Timeline palette.
+
+\section2 Copying Actions
+
+To save time, you may copy and paste an action to a different element
+instead of creating a new action on that element. You must do this using
+the \c{Copy Action} and \c{Paste Action} context menu entries
+for the action summary. (If you use \c{ctrl-c} and \c{ctrl-v}
+you will end up copying and pasting the entire element that the action
+is on.)
+
+The values of the Trigger Object and Target Object properties for the
+pasted action depends on the \b{Type} chosen when picking the
+objects:
+
+\list
+\li
+ If the type is \c{Absolute Reference} then the same element will
+ be used in the pasted action.
+\li
+ If the type is \c{Path Reference} then the element will be
+ resolved relative to the home element for the new action.
+\endlist
+
+For example, consider an action on element \c{A} that has
+\c{A} as the Trigger Object. You then copy and paste the action to
+element \c{B}. If the Trigger Object was specified with an Absolute
+Reference, the new action on element \c{B} will still be using
+element \c{A} as the Trigger Object. However, if the Trigger Object
+was specified with a Path Reference then the new action will use element
+\c{B} as the Trigger Object.
+
+This seemingly-complex system allows the sophisticated artist to quickly
+copy and paste actions to multiple elements with a minimum of editing on
+each new action.
+
+\omit
+TODO: Not appropriate until we have state machine or somesuch back.
+\section1 When to Use Actions
+
+Generally, actions are appropriate for:
+
+\list
+\li
+ Reporting the intention of touch interactions to the state machine
+ - \e{"when the user taps on this component, it means that you should
+ mute the volume"}.
+\li
+ Communicating events raised by presentation behaviors - \e {"you told
+ the the list manager to show the next item, but it says that there are
+ no more to show"}.
+\li
+ Performing trivial view changes that do not affect the state machine
+ - \e{"when the user presses down on this button, make it glow a
+ little"}
+\endlist
+
+Using actions beyond the above is fine for rough prototyping
+(\e{"when the user taps the `music' button tell the scene to switch
+to to the Music slide"}), but should be evaluated for implementation at
+the application level (\e{"when the user taps the `music' button,
+tell the state machine that they want to see music; separately,
+\b{only if} the state machine tells me that we should be seeing
+music then a visual action will make the scene to go to the Music
+slide"}).
+\endomit
+*/
diff --git a/doc/src/03-studio/9-keyboard-shortcuts.qdoc b/doc/src/03-studio/9-keyboard-shortcuts.qdoc
new file mode 100644
index 00000000..60eeb525
--- /dev/null
+++ b/doc/src/03-studio/9-keyboard-shortcuts.qdoc
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Studio: Keyboard Shortcuts
+\page studio-keyboard-shortcuts.html
+\ingroup qt3dstudio-studio
+
+\section1 File Management
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Preview
+ \li \c{F12}
+ \row
+ \li New
+ \li \c{Ctrl + N}
+ \row
+ \li Open
+ \li \c{Ctrl + O}
+ \row
+ \li Save
+ \li \c{Ctrl + S}
+ \row
+ \li Save As...
+ \li \c{Ctrl + Shift + S}
+ \row
+ \li Save a Copy
+ \li \c{Ctrl + Alt + S}
+\endtable
+
+\section1 Edit Menu
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Undo
+ \li \c{Ctrl + Z}
+ \row
+ \li Redo
+ \li \c{Ctrl + Y} or \c{Ctrl + Shift + Z}
+ \row
+ \li Cut
+ \li \c{Ctrl + X}
+ \row
+ \li Copy
+ \li \c{Ctrl + C}
+ \row
+ \li Paste
+ \li \c{Ctrl + V}
+ \row
+ \li Duplicate Object
+ \li \c{Ctrl + D}
+ \row
+ \li Presentation Settings
+ \li \c{Ctrl + P}
+\endtable
+
+\section1 View Menu
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Show Action Palette
+ \li \c{Ctrl + Shift + A}
+ \row
+ \li Show Basic Objects Palette
+ \li \c{Ctrl + Shift + B}
+ \row
+ \li Show Inspector Palette
+ \li \c{Ctrl + Shift + I}
+ \row
+ \li Show Project Palette
+ \li \c{Ctrl + Shift + P}
+ \row
+ \li Show Slide Palette
+ \li \c{Ctrl + Shift + D}
+ \row
+ \li Show Timeline Palette
+ \li \c{Ctrl + Shift + T}
+ \row
+ \li Show/Hide Bounding Boxes
+ \li \c{Ctrl + B}
+ \row
+ \li Show/Hide Pivot Point
+ \li \c{Ctrl + Alt + P}
+\endtable
+
+\section1 Animation Control
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Set Changed Keyframes
+ \li \c{F6}
+ \row
+ \li Toggle Autoset Keyframes
+ \li \c{K}
+\endtable
+
+\section1 Scene View
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Group Select Mode
+ \li \c{A}
+ \row
+ \li Item Select Mode
+ \li \c{V}
+ \row
+ \li Position Mode
+ \li \c{W}
+ \row
+ \li Scale Mode
+ \li \c{E}
+ \row
+ \li Rotate Mode
+ \li \c{R}
+ \row
+ \li Constrain drag to axis
+ \li \c{Shift} + Mouse Drag
+\endtable
+
+\section2 Nudge Position
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li X+ (Left)
+ \li \c{Left Arrow}
+ \row
+ \li X- (Right)
+ \li \c{Right Arrow}
+ \row
+ \li Y+ (Up)
+ \li \c{Up Arrow}
+ \row
+ \li Y- (Down)
+ \li \c{Down Arrow}
+ \row
+ \li Z- (Forward)
+ \li \c{Shift + Down Arrow}
+ \row
+ \li Z+ (Backward)
+ \li \c{Shift + Up Arrow}
+\endtable
+
+\section2 Nudge Rotation
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li X+
+ \li \c{Ctrl + Up Arrow}
+ \row
+ \li X-
+ \li \c{Ctrl + Down Arrow}
+ \row
+ \li Y+
+ \li \c{Ctrl + Left Arrow}
+ \row
+ \li Y-
+ \li \c{Ctrl + Right Arrow}
+ \row
+ \li Z-
+ \li \c{Ctrl + Shift + Down Arrow}
+ \row
+ \li Z+
+ \li \c{Ctrl + Shift + Up Arrow}
+\endtable
+
+\section2 Nudge Scale
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li X+
+ \li \c{Alt + Right Arrow}
+ \row
+ \li X-
+ \li \c{Alt + Left Arrow}
+ \row
+ \li Y+
+ \li \c{Alt + Up Arrow}
+ \row
+ \li Y-
+ \li \c{Alt + Down Arrow}
+ \row
+ \li Z-
+ \li \c{Alt + Shift + Down Arrow}
+ \row
+ \li Z+
+ \li \c{Alt + Shift + Up Arrow}
+\endtable
+
+\section2 Edit Cameras
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Fit Selected
+ \li \c{F}
+ \row
+ \li Pan
+ \li Middle Mouse Drag
+ \row
+ \li Zoom
+ \li Mouse Wheel
+ \row
+ \li Orbit
+ \li \c{Alt} + Middle Mouse Drag
+ \row
+ \li Toggle Headlight
+ \li \c{F3}
+\endtable
+
+\section1 Timeline
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Quick Play
+ \li Hold down \c{spacebar}
+ \row
+ \li Toggle Play/Pause
+ \li \c{Enter}
+ \row
+ \li Set Time Bar Start Time
+ \li \c{[}
+ \row
+ \li Set Time Bar End Time
+ \li \c{]}
+ \row
+ \li Snap while Dragging
+ \li \c{Shift} + Mouse Drag
+ \row
+ \li Move Playhead to next minor tick mark
+ \li \c{.}
+ \row
+ \li Move Playhead to previous minor tick mark
+ \li \c{,}
+ \row
+ \li Move Playhead to next medium tick mark
+ \li \c{Shift + >}
+ \row
+ \li Move Playhead to previous medium tick mark
+ \li \c{Shift + <}
+\endtable
+
+\section1 Inspector Palette
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Increment value by .1
+ \li \c{Ctrl + Up/Down Arrow}
+ \row
+ \li Increment value by 1
+ \li \c{Up/Down Arrow}
+ \row
+ \li Increment value by 10
+ \li \c{Shift + Up/Down Arrow}
+\endtable
+
+*/
diff --git a/doc/src/03-studio/studio-index.qdoc b/doc/src/03-studio/studio-index.qdoc
new file mode 100644
index 00000000..27de39a6
--- /dev/null
+++ b/doc/src/03-studio/studio-index.qdoc
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\title Studio Index
+\group qt3dstudio-studio
+
+Qt 3D Studio is an artist-centric tool
+designed for designing and building rich interactive interfaces. Though
+there is a strong emphasis on 3D content - all objects are placed in
+three dimensional space - it is not a 3D content creation tool. It is
+also not a drawing program, though it uses 2D images and vectors
+heavily. Studio is a compositing tool.
+
+Create your 2D, 3D, and script assets in other programs and then use
+Studio to place them in your presentation.
+
+\e{For more on importing models into your project see the section}
+\l{best-practices-importing-3d-content.html}{Working with 3D Content}.
+
+\noautolist
+
+\section1 Contents
+
+//! [toc]
+\list
+ \li \l {Studio: Menu}
+ \li \l {Studio: Toolbar}
+ \li \l {Studio: Scene View and Matte}
+ \li \l {Studio: Project Palette}
+ \li \l {Studio: Basic Objects Palette}
+ \li \l {Studio: Timeline Palette}
+ \li \l {Studio: Slide Palette}
+ \li \l {Studio: Inspector Palette}
+ \li \l {Studio: Action Palette}
+ \li \l {Studio: Keyboard Shortcuts}
+\endlist
+//! [toc]
+
+*/
diff --git a/doc/src/04-viewer/0-menu.qdoc b/doc/src/04-viewer/0-menu.qdoc
new file mode 100644
index 00000000..10f82360
--- /dev/null
+++ b/doc/src/04-viewer/0-menu.qdoc
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Viewer: Menu
+\page viewer-menu.html
+\ingroup qt3dstudio-viewer
+
+\section1 File
+
+\list
+\li
+ \b{Open...} - Open a \c{.uip} presentation or
+ \c{.uia} application file to view.
+\li
+ \b{Reload} - Restart the presentation/application from the
+ beginning.
+\li
+ \b{Quit} - Quit the Viewer.
+\endlist
+
+\section1 View
+
+\list
+\li
+ \b{Full Screen} - Remove the window for the viewer and use the
+ full screen for the application. (Whether or not the initial
+ presentation fills the screen or not depends on the
+ \l{studio-menu.html#project-settings}{presentation size}
+ and the scale mode, which is set via the application
+ \l{file-formats-uia.html#application}{scale mode setting}, or
+ Viewer override command (see \e{Scale Mode} below).
+\li
+ \b{Show Matte} - Toggle the display of any letterboxed regions
+ (areas outside the initial presentation) as a darker matte. When
+ disabled, the clear color for the initial presentation is displayed
+ instead.
+\li
+ \b{Scale Mode} - Override the scale mode set by the
+ \l{file-formats-uia.html#application}{application}:
+
+ \image Runtime-ApplicationScaleMode.png
+
+\li
+ \b{VSync Interval} - Clamp render refresh rate to monitor refresh
+ rate to avoid tearing.
+ \list
+ \li
+ \e {Adaptive VSync} - At high frame rates avoid tearing. At low frame
+ rates avoid stuttering.
+ \li
+ \e {VSync Off} - Disable VSync.
+ \li
+ \e {VSync On} - Enable VSync.
+ \endlist
+\li
+ \b{Shade Mode} - Enable overlayed wireframe rendering for
+ tesselated geometry.
+\li
+ \b{Show Render Statistics} - Display debug information on top of
+ the viewer with information for recent average frame rate/frame time.
+\endlist
+
+*/
diff --git a/doc/src/04-viewer/1-keyboard.qdoc b/doc/src/04-viewer/1-keyboard.qdoc
new file mode 100644
index 00000000..5ca037ed
--- /dev/null
+++ b/doc/src/04-viewer/1-keyboard.qdoc
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Viewer: Keyboard Shortcuts
+\page viewer-keyboard.html
+\ingroup qt3dstudio-viewer
+
+\section1 File Menu
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Open
+ \li \c{Ctrl + O}
+ \row
+ \li Reload
+ \li \c{F5}
+ \row
+ \li Quit
+ \li \c{Alt + F4}
+\endtable
+
+\section1 View Menu
+
+\table
+ \header
+ \li Function
+ \li Shortcut
+ \row
+ \li Full Screen
+ \li \c{F11}
+ \row
+ \li Show Matte
+ \li \c{Ctrl + D}
+ \row
+ \li Scale Modes
+ \li \c{Ctrl + Shift + S}
+ \row
+ \li Shade Mode
+ \li \c{Ctrl + Shift + W}
+ \row
+ \li Render Statistics
+ \li \c{F1}
+\endtable
+
+*/
diff --git a/doc/src/04-viewer/viewer-index.qdoc b/doc/src/04-viewer/viewer-index.qdoc
new file mode 100644
index 00000000..ea067783
--- /dev/null
+++ b/doc/src/04-viewer/viewer-index.qdoc
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Viewer Index
+\group qt3dstudio-viewer
+\noautolist
+
+\section1 Contents
+
+//! [toc]
+\list
+ \li \l {Viewer: Menu}
+ \li \l {Viewer: Keyboard Shortcuts}
+\endlist
+//! [toc]
+
+*/
diff --git a/doc/src/05-runtime/0-frame-update-cycle.qdoc b/doc/src/05-runtime/0-frame-update-cycle.qdoc
new file mode 100644
index 00000000..b5b52364
--- /dev/null
+++ b/doc/src/05-runtime/0-frame-update-cycle.qdoc
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Runtime: Frame Update Cycle
+\page runtime-frame-update-cycle.html
+\ingroup qt3dstudio-runtime
+
+Qt 3D Studio presents a
+simple, elegant interface for creating interactive 3D content. Concepts
+like Slides, Components, Actions, Events, Behaviors, Eye-Toggles, and
+the Animation Timeline are highly intuitive and represent a very
+accessible interface for controlling what is a necessarily complex
+real-time runtime system for managing interactive 3D content.
+
+The Qt 3D Studio Runtime operates with a deterministic set of
+rules that bring the content created with Qt 3D Studio to life.
+This document outlines what happens in a
+\b{single frame} in terms of the runtime to make this happen.
+
+The calculations and order of operations involved in each frame are
+fairly complex; in order to explain things more clearly it is helpful to
+think of each frame being made up of several logical stages. Here is the
+full overview of the different conceptual stages.
+
+\section1 Input
+
+A frame is kicked off by calling \c{CRuntime::UpdatePresentations};
+this immediately results in a call to
+\c{CInputEngine::GetInputFrame}. A subclass of
+\c{CInputEngine} will take this opportunity to poll the state of
+the various input devices and fire events indicating user interaction.
+The base class version of \c{CInputEngine} implements
+\c{HandleInputEvent} which can be used to do this simply.
+
+\section1 Stage 0: Time Distribution
+
+This stage is opaque and will be relatively invisible to you. Before any
+real calculations for this frame can begin, various time related
+activities need to be complete. For instance, each presentation itself
+can be playing or paused. This stage manages this and other time related
+things.
+
+\section1 Stage 1: Process Events
+
+The next result of calling \c{CRuntime::UpdatePresentations} is the
+processing of events.
+
+The Runtime maintains a first-in/first-out queue of events that are
+waiting to be processed. When event processing starts this queue will
+contain events that were fired during the input stage as described above
+as well as any events that were fired on the previous frame after event
+processing was completed.
+
+The critical rule of event processing is that all events will be
+processed before this stage ends and the next stage begins. This
+includes events that are fired during event processing. This contract
+allows the Runtime to support chained events, meaning that any event
+fired as a result of processing another event will be handled in the
+same frame. This contract helps to ensure consistent presentation state.
+
+It is interesting to note that because slide changes can only be
+affected as a result of processing events; all slide changes will take
+place during this stage.
+
+\section1 Stage 2: Active Scan
+
+Once all the events for this frame have been processed, and the event
+queue is empty, a full scan of the graph of elements is performed to
+find out which elements will be active this frame. The processing of
+events will result in slide changes and changes to properties which will
+affect the appearance of the presentation. During this stage, a
+definitive list of which elements are active is created and this list
+will be used by subsequent stages to efficiently do their jobs.
+
+It is interesting to note that because this `active list' is created
+here, and is used by all further stages, changes to the active state of
+any elements made after this stage will not take effect until the next
+frame (when the list is calculated again). By clearly drawing this line
+at this stage we can avoid many of the \"doing various things before (or
+after) you exist\" paradoxes inherent in a complex frame rhythm.
+
+\section1 Stage 3: Animation
+
+After the list of active elements for this frame has been decided, the
+Runtime calculates new values for any animated properties on active
+elements, and applies the new values.
+
+\target script-callbacks
+\section1 Stage 4: Script Callbacks
+
+The final act of \c{CRuntime::UpdatePresentations} is to call the
+special active dependent script callbacks. By comparing this frame's
+active list with the active list from the previous frame the Runtime can
+determine which elements are becoming active or inactive. The Runtime
+uses this information to initiate the following script callbacks:
+
+\section2 \c{onDeactivate}
+
+First, any behaviors which were active last frame that are not active
+this frame will have their \c{onDeactivate} handler called. If
+multiple behaviors match this the callbacks for parent elements will
+occur before their children/descendants.
+
+\section2 \c{onInitialize}
+
+On the very first frame a behavior is active it will have its
+\c{onInitialize} handler called. If multiple behaviors match this
+the callbacks for parent elements will occur before their
+children/descendants. Note that each behavior will only have its
+\c{onInitialize} handler called once, even if it is deactivated and
+later reactivated.
+
+\section2 \c{onActivate}
+
+Next, any behaviors which were not active last frame that are active
+this frame will have their \c{onActivate} handlers called. If
+multiple behaviors match this the callbacks for parent elements will
+occur before their children/descendants.
+
+\section2 \c{onUpdate}
+
+Finally, any behaviors that are active this frame will have their
+\c{onUpdate} handler called. If multiple behaviors match this the
+callbacks for parent elements will occur before their
+children/descendants.
+
+\section1 Stage 5: Scene Graph Update
+
+The next call you will make is \c{CRuntime::UpdateScenes}. All the
+activity before this has performed the calculations in the Runtime to
+ensure the presentation is in a newly updated state for this frame.
+Calling \c{UpdateScenes} will first result in any changed
+attributes being communicated through the scene graph to your
+application through calls to \c{CRenderEngine::SetAttributes}.
+Then, a recursive update is done on the assets in the scene graph to
+calculate updated global matrices and hierarchical opacity values.
+
+\section1 Stage 6: Render
+
+Finally you will call \c{CRuntime::Render}. This stage consumes all
+the calculated values produced by the previous stages and translates
+them into calls on your engine specific subclass of
+\c{CRenderEngine}. This includes calls like \c{SetTransform}
+which will communicate the updated global matrices to you and
+\c{DrawItem} which will indicate that you need to draw a specific
+item in the scene.
+*/
diff --git a/doc/src/05-runtime/0b-inputplugins.qdoc b/doc/src/05-runtime/0b-inputplugins.qdoc
new file mode 100644
index 00000000..6f1f4f27
--- /dev/null
+++ b/doc/src/05-runtime/0b-inputplugins.qdoc
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Runtime: Input Plugins
+\page runtime-0b-inputplugins.html
+\ingroup qt3dstudio-runtime
+
+\section1 Overview
+
+TODO
+
+\section1 Lua Bindings
+
+TODO
+
+\section1 Sample Plugin
+
+TODO
+
+*/
diff --git a/doc/src/05-runtime/1-event-processing.qdoc b/doc/src/05-runtime/1-event-processing.qdoc
new file mode 100644
index 00000000..8cbae5ee
--- /dev/null
+++ b/doc/src/05-runtime/1-event-processing.qdoc
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Runtime: Event Processing
+\page runtime-event-processing.html
+\ingroup qt3dstudio-runtime
+
+\omit
+There are three different event systems in
+the Qt 3D Studio Runtime:
+
+\list
+\li
+ \e{External Events} arrive from outside the
+ system (e.g. from the CAN bus, a keyboard, a game controller) via
+ plugins that expose a queue of events each frame to your application.
+ These events must be explicitly received and handled by your
+ application.
+\li
+ \e{State Machine Events} occur within each
+ state machine running in your application, possibly causing the state
+ machine to possibly change states.
+\li
+ \l{presentation-events}{Presentation Events} occur within each
+ presentation (e.g. touch events, slide changes, Lua script), bubbling
+ up the scene graph of elements within the presentation.
+\endlist
+
+\target external-events
+\section1 External Events
+
+\list
+\li
+ \e{TODO: document the handling of events, with an example App.lua
+ with links to the Lua functions and also to the reference for writing
+ plugins.}
+\endlist
+
+\target state-machine-events
+\section1 State Machine Events
+
+\list
+\li
+ \e{TODO: document the firing of events on state machines, with
+ links to the Lua functions.}
+\endlist
+\endomit
+
+\target presentation-events
+\section1 Presentation Events
+
+In the Runtime, processing presentation events is a single stage of the
+overall \l{runtime-frame-update-cycle.html}{Frame Update} cycle
+governing the operation of the runtime. Processing events is a
+sophisticated process with many associated activities and contracts.
+This page describes how event processing works, what sorts of things can
+happen as a result of events being processed, and how your application
+(C++) can interact with the runtime in terms of events.
+
+\section2 How Stuff Works
+
+The stages of the update cycle are clearly defined entities, with nice
+start and end conditions, that occur one right after another and in a
+well-specified order to accomplish the calculations and activities
+required for a given frame. The event processing stage is arguably the
+most important stage, so we'll explore some of the details of its
+operation here.
+
+There exists a list of events that is treated as a first-in/first-out
+queue. The act of 'firing an event' is literally adding the event being
+ 'fired' to the end of this queue. This operation is the same regardless
+of when the event is fired.
+
+On each frame the processing of events is started implicitly by the call
+to \c{CRuntime::UpdatePresentations}. On most frames, when event
+processing begins, the event list (queue) is empty. There are two cases
+in which there will be events in the queue.
+
+\list 1
+\li
+ An input event was fired by the Input Engine in response to user
+ action (e.g. Pressing buttons on the controller)
+\li
+ An event was fired after event processing was complete for last frame
+ (e.g. An event was fired from QML)
+\endlist
+
+Event processing happens in the same way regardless of how the events
+got on the list; Each event in the list is looked at in turn and anyone
+interested in that event is notified. It's important to note that all of
+the events in the queue are processed in turn (including events fired as
+a result of other events being processed) on and on until there are no
+events left to process. Only when the event list is completely empty
+does the event processing stage end for this frame.
+
+There are several possible outcomes of processing an event, we'll
+explore them next.
+
+\section2 Event Processing Results
+
+\section3 Changing Slides
+
+All slide changes are effected as the result of processing events. This
+can be a critical point to understand when trying to deduce the effects
+of complex interactions between actions, slides and script. For example,
+you set up a visual state saying that when the state machine enters a
+particular state tell a component to go to the next slide. For the
+runtime, a piece of logic gets created representing this action. When
+the onSelect event is fired and later processed, the interested logic
+will be notified and the slide change will occur.
+
+\omit
+TODO: Needs to be rewritten?
+Note that behavior event registrations (created with Lua's
+registerForEvent) work similarly to the logic described above. If a
+script registers explicitly for a certain event and in the handler calls
+goToSlide, essentially the same things happen.
+\endomit
+
+\section3 Changing Properties
+
+Attributes can have their values changed in response to events,
+affecting the visual appearance of the presentation. Set Property
+actions created in Studio will be executed when their specified event is
+processed, resulting in properties being changed. Also, changing slides
+will result in changed properties if a master object inside of Studio
+has one or more of its properties unlinked from the master slide and
+that property is changed per-slide.
+
+\omit
+\section3 Executing Script
+
+Processing an event can result in arbitrary script code being executed.
+An event registration can be created by using the registerForEvent
+function to listen for a specific event on a specific element. The
+registration also has a callback function associated with it and when
+that specific event targeting that element is processed, the script
+callback function will be executed.
+
+Of course, script can inspect and change properties on various elements,
+affect slide changes, fire more events, etc. Being able to respond to
+events being processed really empowers scripting.
+\endomit
+
+\omit
+TODO: Needs to be rewritten.
+\section3 Firing More Events (Cascading)
+
+There are two ways a presentation may fire an event in response to
+another event. The first way is through script as described above, and
+the second way is through the action palette.
+
+Behaviors in Studio can have arbitrary Custom Events associated with
+them by adding these custom events in the header section of the
+behavior's .lua file. When a behavior with one or more Custom Events is
+the target of an action in the action palette Studio will offer the Fire
+Event action. By using this action, arbitrary cascading events can be
+set up to fire by pointing and clicking. (as opposed to scripting).
+
+It's worth repeating that these cascading events will all be processed
+in the same frame. The event processor doesn't stop processing events
+until there are none left to process.
+\endomit
+
+\section2 How Your Application (C++) Interacts with Event Processing
+
+There are two basic use cases for your application interacting with
+event processing:
+
+\list 1
+\li
+ Firing arbitrary events into the Runtime system.
+\li
+ Responding (with C++ callbacks) to events being processed.
+\endlist
+
+\section3 Firing Your Own Arbitrary Events into a Presentation
+
+You can fire arbitrary events into a presentation using
+\c{CPresentation::FireEvent}. If some part of your application
+needs to notify a running presentation of something in an event driven
+manner, this is the way to go. This is useful in a lot of circumstances
+such as \e {"A cut-scene video is done playing"} and \e {"Someone from the
+user's online friend list has logged on!"}.
+
+The arguments to \c{CPresentation::FireEvent} allow you to
+parameterize the events you fire into the system. The lifespan of the
+memory associated with these parameters is completely managed by the
+Runtime itself allowing you to 'fire and forget'.
+
+\section3 Responding to Events Being Processed
+
+The method \c{CPresentation::RegisterEventCallback} allows you to
+register a C++ callback for when a specific event is processed on a
+certain element. The TEventCallback typedef is the signature your
+callback function should implement. Also note the last parameter to
+\c{CPresentation::RegisterEventCallback} which allows you to store
+a \c{void*} context data for use in your callback.
+
+*/
diff --git a/doc/src/05-runtime/2-renderplugins.qdoc b/doc/src/05-runtime/2-renderplugins.qdoc
new file mode 100644
index 00000000..cf3e034d
--- /dev/null
+++ b/doc/src/05-runtime/2-renderplugins.qdoc
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Runtime: Render Plugins
+\page runtime-renderplugins.html
+\ingroup qt3dstudio-runtime
+
+\section1 Overview
+
+TODO:
+
+\section1 Lua Bindings
+
+TODO:
+
+\section1 Sample Code
+
+TODO:
+
+*/
diff --git a/doc/src/05-runtime/runtime-index.qdoc b/doc/src/05-runtime/runtime-index.qdoc
new file mode 100644
index 00000000..91387890
--- /dev/null
+++ b/doc/src/05-runtime/runtime-index.qdoc
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Runtime
+\group qt3dstudio-runtime
+\noautolist
+
+\section1 Contents
+
+//! [toc]
+\list
+\li \l {Runtime: Frame Update Cycle}
+\li \l {Runtime: Event Processing}
+//! ---- following pages lack content
+\omit
+\li \l {Runtime: Input Plugins}
+\li \l {Runtime: Render Plugins}
+\endomit
+\endlist
+//! [toc]
+
+*/
diff --git a/doc/src/06-qml-reference/03-attribute-names.html b/doc/src/06-qml-reference/03-attribute-names.html
new file mode 100644
index 00000000..2e725532
--- /dev/null
+++ b/doc/src/06-qml-reference/03-attribute-names.html
@@ -0,0 +1,1243 @@
+\raw HTML
+<table id='scripting-attributes'>
+<tbody></tbody>
+<tr><th colspan="4">Scenes</td></tr>
+<tr>
+<td class='formal'>Name</td>
+<td class='scripting'>name</td>
+<td class='type'>string</td>
+<td class='note'>
+always <code>"Scene"</code>
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>path</td>
+<td class='type'>string</td>
+<td class='note'>
+always <code>"Scene"</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Enable Background Color</td>
+<td class='scripting'>bgcolorenable</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color R</td>
+<td class='scripting'>backgroundcolor.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color G</td>
+<td class='scripting'>backgroundcolor.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color B</td>
+<td class='scripting'>backgroundcolor.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Elements other than Scenes</td></tr>
+<tr>
+<td class='formal'>Element Name</td>
+<td class='scripting'>name</td>
+<td class='type'>string</td>
+<td class='note'>
+always available
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>path</td>
+<td class='type'>string</td>
+<td class='note'>
+full path to the element
+</td>
+</tr>
+<tr>
+<td class='formal'>(Eyeball)</td>
+<td class='scripting'>eyeball</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Timebar Start</td>
+<td class='scripting'>starttime</td>
+<td class='type'>number</td>
+<td class='note'>
+in integer milliseconds; always available
+</td>
+</tr>
+<tr>
+<td class='formal'>Timebar End</td>
+<td class='scripting'>endtime</td>
+<td class='type'>number</td>
+<td class='note'>
+in integer milliseconds; always available
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Layers</td></tr>
+<tr>
+<td class='formal'>Disable Depth Test</td>
+<td class='scripting'>disabledepthtest</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Progressive AA</td>
+<td class='scripting'>progressiveaa</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'2x'</code>, <code>'4x'</code>, <code>'8x'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Multisample AA</td>
+<td class='scripting'>multisampleaa</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'2x'</code>, <code>'4x'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Temporal AA</td>
+<td class='scripting'>temporalaa</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Layer Background</td>
+<td class='scripting'>background</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Transparent'</code>, <code>'Unspecified'</code>, <code>'SolidColor'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color R</td>
+<td class='scripting'>backgroundcolor.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color G</td>
+<td class='scripting'>backgroundcolor.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Background Color B</td>
+<td class='scripting'>backgroundcolor.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Horizontal Fields</td>
+<td class='scripting'>horzfields</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Left/Width'</code>, <code>'Left/Right'</code>, <code>'Width/Right'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Left</td>
+<td class='scripting'>left</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Left Units</td>
+<td class='scripting'>leftunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Width</td>
+<td class='scripting'>width</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Width Units</td>
+<td class='scripting'>widthunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Right</td>
+<td class='scripting'>right</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Right Units</td>
+<td class='scripting'>rightunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Vertical Fields</td>
+<td class='scripting'>vertfields</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Top/Height'</code>, <code>'Top/Bottom'</code>, <code>'Height/Bottom'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Top</td>
+<td class='scripting'>top</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Top Units</td>
+<td class='scripting'>topunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Height</td>
+<td class='scripting'>height</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Height Units</td>
+<td class='scripting'>heightunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Bottom</td>
+<td class='scripting'>bottom</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Bottom Units</td>
+<td class='scripting'>bottomunits</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'pixels'</code>, <code>'percent'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Occlusion</td>
+<td class='scripting'>aostrength</td>
+<td class='type'>number</td>
+<td class='note'>
+values between 0 and 100
+</td>
+</tr>
+<tr>
+<td class='formal'>AO Distance</td>
+<td class='scripting'>aodistance</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>AO Softness</td>
+<td class='scripting'>aosoftness</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>AO Threshold</td>
+<td class='scripting'>aobias</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>AO Sampling Rate</td>
+<td class='scripting'>aosamplerate</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>AO Dithering</td>
+<td class='scripting'>aodither</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Strength</td>
+<td class='scripting'>shadowstrength</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Distance</td>
+<td class='scripting'>shadowdist</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Softness</td>
+<td class='scripting'>shadowsoftness</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Threshold</td>
+<td class='scripting'>shadowbias</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Probe</td>
+<td class='scripting'>lightprobe</td>
+<td class='type'>image element</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>IBL Horizon Cutoff</td>
+<td class='scripting'>probehorizon</td>
+<td class='type'>number</td>
+<td class='note'>
+values from -1 (no horizon) to -0.001 (hard edge)
+</td>
+</tr>
+<tr>
+<td class='formal'>Sub-Presentation</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+<td class='note'>
+id of the sub-presentation to display
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Nodes</td></tr>
+<tr>
+<td class='formal'>Position X</td>
+<td class='scripting'>position.x</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Position Y</td>
+<td class='scripting'>position.y</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Position Z</td>
+<td class='scripting'>position.z</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Rotation X</td>
+<td class='scripting'>rotation.x</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Rotation Y</td>
+<td class='scripting'>rotation.y</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Rotation Z</td>
+<td class='scripting'>rotation.z</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Scale X</td>
+<td class='scripting'>scale.x</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Scale Y</td>
+<td class='scripting'>scale.y</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Scale Z</td>
+<td class='scripting'>scale.z</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Pivot X</td>
+<td class='scripting'>pivot.x</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Pivot Y</td>
+<td class='scripting'>pivot.y</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Pivot Z</td>
+<td class='scripting'>pivot.z</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Opacity</td>
+<td class='scripting'>opacity</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>orientation</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Left Handed'</code>, <code>'Right Handed'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>rotationorder</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'XYZ'</code>, <code>'YZX'</code>, <code>'ZXY'</code>, <code>'XZY'</code>, <code>'YXZ'</code>, <code>'ZYX'</code>, <code>'XYZr'</code>, <code>'YZXr'</code>, <code>'ZXYr'</code>, <code>'XZYr'</code>, <code>'YXZr'</code>, <code>'ZYXr'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'></td>
+<td class='scripting'>ignoresparent</td>
+<td class='type'>boolean</td>
+<td class='note'>
+prevents parent transformation from being applied
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Aliases</td></tr>
+<tr>
+<td class='formal'>Reference</td>
+<td class='scripting'>referencednode</td>
+<td class='type'>string</td>
+<td class='note'>
+relative or absolute element path
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Cameras</td></tr>
+<tr>
+<td class='formal'>Orthographic</td>
+<td class='scripting'>orthographic</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Field of View</td>
+<td class='scripting'>fov</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Clipping Start</td>
+<td class='scripting'>clipnear</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Clipping End</td>
+<td class='scripting'>clipfar</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Runtime Scale Mode</td>
+<td class='scripting'>scalemode</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Fit'</code>, <code>'Same Size'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Runtime Scale Anchor</td>
+<td class='scripting'>scaleanchor</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Center'</code>, <code>'NW'</code>, <code>'N'</code>, <code>'NE'</code>, <code>'E'</code>, <code>'SE'</code>, <code>'S'</code>, <code>'SW'</code>, <code>'W'</code>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Lights</td></tr>
+<tr>
+<td class='formal'>Scope</td>
+<td class='scripting'>scope</td>
+<td class='type'>string</td>
+<td class='note'>
+full path to the element
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Type</td>
+<td class='scripting'>lighttype</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Directional'</code>, <code>'Point'</code>, <code>'Area'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Color R</td>
+<td class='scripting'>lightdiffuse.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Color G</td>
+<td class='scripting'>lightdiffuse.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Light Color B</td>
+<td class='scripting'>lightdiffuse.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Color R</td>
+<td class='scripting'>lightspecular.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Color G</td>
+<td class='scripting'>lightspecular.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Color B</td>
+<td class='scripting'>lightspecular.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Color R</td>
+<td class='scripting'>lightambient.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Color G</td>
+<td class='scripting'>lightambient.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Ambient Color B</td>
+<td class='scripting'>lightambient.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Brightness</td>
+<td class='scripting'>brightness</td>
+<td class='type'>number</td>
+<td class='note'>
+only applies to point lights
+</td>
+</tr>
+<tr>
+<td class='formal'>Linear Fade</td>
+<td class='scripting'>linearfade</td>
+<td class='type'>number</td>
+<td class='note'>
+only applies to point lights
+</td>
+</tr>
+<tr>
+<td class='formal'>Exponential Fade</td>
+<td class='scripting'>expfade</td>
+<td class='type'>number</td>
+<td class='note'>
+only applies to point lights
+</td>
+</tr>
+<tr>
+<td class='formal'>Cast Shadows?</td>
+<td class='scripting'>castshadow</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Darkness</td>
+<td class='scripting'>shdwfactor</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Softness</td>
+<td class='scripting'>shdwfilter</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Resolution</td>
+<td class='scripting'>shdwmapres</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'256'</code>, <code>'512'</code>, <code>'1024'</code>, <code>'2048'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Depth Bias</td>
+<td class='scripting'>shdwbias</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Shadow Far Clip</td>
+<td class='scripting'>shdwmapfar</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Groups</td></tr>
+<tr>
+<td class='formal'>Import</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Text</td></tr>
+<tr>
+<td class='formal'>Text String</td>
+<td class='scripting'>textstring</td>
+<td class='type'>string</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Text Color R</td>
+<td class='scripting'>textcolor.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Text Color G</td>
+<td class='scripting'>textcolor.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Text Color B</td>
+<td class='scripting'>textcolor.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Font</td>
+<td class='scripting'>font</td>
+<td class='type'>string</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Font Size</td>
+<td class='scripting'>size</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Horizontal Alignment</td>
+<td class='scripting'>horzalign</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Left'</code>, <code>'Center'</code>, <code>'Right'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Vertical Alignment</td>
+<td class='scripting'>vertalign</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Top'</code>, <code>'Middle'</code>, <code>'Bottom'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Leading</td>
+<td class='scripting'>leading</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Tracking</td>
+<td class='scripting'>tracking</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Models</td></tr>
+<tr>
+<td class='formal'>Mesh</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Tessellation Mode</td>
+<td class='scripting'>tessellation</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'Linear'</code>, <code>'Phong'</code>, <code>'NPatch'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Edge Tessellation Value</td>
+<td class='scripting'>edgetess</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Inner Tessellation Value</td>
+<td class='scripting'>innertess</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Standard Materials</td></tr>
+<tr>
+<td class='formal'>Lighting</td>
+<td class='scripting'>shaderlighting</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Vertex'</code>, <code>'Pixel'</code>, <code>'None'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Blending Mode</td>
+<td class='scripting'>blendmode</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Normal'</code>, <code>'Screen'</code>, <code>'Multiply'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Color R</td>
+<td class='scripting'>diffuse.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Color G</td>
+<td class='scripting'>diffuse.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Color B</td>
+<td class='scripting'>diffuse.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Map</td>
+<td class='scripting'>diffusemap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Map 2</td>
+<td class='scripting'>diffusemap2</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Diffuse Map 3</td>
+<td class='scripting'>diffusemap3</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Reflection</td>
+<td class='scripting'>specularreflection</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Tint R</td>
+<td class='scripting'>speculartint.r</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Tint G</td>
+<td class='scripting'>speculartint.g</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Tint B</td>
+<td class='scripting'>speculartint.b</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Amount</td>
+<td class='scripting'>specularamount</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Map</td>
+<td class='scripting'>specularmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Model</td>
+<td class='scripting'>specularmodel</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Default'</code>, <code>'KGGX'</code>, <code>'KWard'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Fresnel Power</td>
+<td class='scripting'>fresnelPower</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Index of Refraction</td>
+<td class='scripting'>ior</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Specular Roughness</td>
+<td class='scripting'>specularroughness</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Bump Map</td>
+<td class='scripting'>bumpmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Normal Map</td>
+<td class='scripting'>normalmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Bump Amount</td>
+<td class='scripting'>bumpamount</td>
+<td class='type'>number</td>
+<td class='note'>
+affects both bump and normal maps
+</td>
+</tr>
+<tr>
+<td class='formal'>Displacement Map</td>
+<td class='scripting'>displacementmap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Displacement Amount</td>
+<td class='scripting'>displaceamount</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Opacity</td>
+<td class='scripting'>opacity</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Opacity Map</td>
+<td class='scripting'>opacitymap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tr>
+<td class='formal'>Emissive Power</td>
+<td class='scripting'>emissivepower</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Emissive Map</td>
+<td class='scripting'>emissivemap</td>
+<td class='type'>image element</td>
+<td class='note'>
+to change the image set the <code>sourcepath</code> attribute on the image element
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Material References</td></tr>
+<tr>
+<td class='formal'>Referenced Material</td>
+<td class='scripting'>referencedmaterial</td>
+<td class='type'>string</td>
+<td class='note'>
+relative or absolute element path
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Images</td></tr>
+<tr>
+<td class='formal'>U Repeat</td>
+<td class='scripting'>scaleu</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>V Repeat</td>
+<td class='scripting'>scalev</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Texture Mapping</td>
+<td class='scripting'>mappingmode</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'UV Mapping'</code>, <code>'Environmental Mapping'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>U Tiling</td>
+<td class='scripting'>tilingmodehorz</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Tiled'</code>, <code>'Mirrored'</code>, <code>'No Tiling'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>V Tiling</td>
+<td class='scripting'>tilingmodevert</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Tiled'</code>, <code>'Mirrored'</code>, <code>'No Tiling'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>UV Rotation</td>
+<td class='scripting'>rotationuv</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>U Position</td>
+<td class='scripting'>positionu</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>V Position</td>
+<td class='scripting'>positionv</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>U Pivot</td>
+<td class='scripting'>pivotu</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>V Pivot</td>
+<td class='scripting'>pivotv</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Sub-Presentation</td>
+<td class='scripting'>subpresentation</td>
+<td class='type'>string</td>
+<td class='note'>
+id of the sub-presentation to display
+</td>
+</tr>
+<tr>
+<td class='formal'>Source Path</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>string</td>
+<td class='note'>
+path to the image
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Paths</td></tr>
+<tr>
+<td class='formal'>Path</td>
+<td class='scripting'>sourcepath</td>
+<td class='type'>pathbuffer</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Stroke Width</td>
+<td class='scripting'>width</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Path Type</td>
+<td class='scripting'>pathtype</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Painted'</code>, <code>'Geometry'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Paint Style</td>
+<td class='scripting'>paintstyle</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'Filled and Stroked'</code>, <code>'Filled'</code>, <code>'Stroked'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>GPU Usage</td>
+<td class='scripting'>linearerror</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Edge Detail</td>
+<td class='scripting'>edgetessamount</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Width Detail</td>
+<td class='scripting'>innertessamount</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Begin Cap Style</td>
+<td class='scripting'>begincap</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'Taper'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Taper Length (Begin Cap)</td>
+<td class='scripting'>begincapoffset</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Tip Opacity (Begin Cap)</td>
+<td class='scripting'>begincapopacity</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Tip Width (Begin Cap)</td>
+<td class='scripting'>begincapwidth</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>End Cap Style</td>
+<td class='scripting'>endcap</td>
+<td class='type'>string</td>
+<td class='note'>
+values: <code>'None'</code>, <code>'Taper'</code>
+</td>
+</tr>
+<tr>
+<td class='formal'>Taper Length (End Cap)</td>
+<td class='scripting'>endcapoffset</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Tip Opacity (End Cap)</td>
+<td class='scripting'>endcapopacity</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Tip Width (End Cap)</td>
+<td class='scripting'>endcapwidth</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Path SubPaths</td></tr>
+<tr>
+<td class='formal'>Closed Path?</td>
+<td class='scripting'>closed</td>
+<td class='type'>boolean</td>
+<td class='note'>
+</td>
+</tr>
+<tbody></tbody>
+<tr><th colspan="4">Path Anchor Points</td></tr>
+<tr>
+<td class='formal'>Position</td>
+<td class='scripting'>position</td>
+<td class='type'>float2</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Handle Angle</td>
+<td class='scripting'>incomingangle</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Incoming Distance</td>
+<td class='scripting'>incomingdistance</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+<tr>
+<td class='formal'>Outgoing Distance</td>
+<td class='scripting'>outgoingdistance</td>
+<td class='type'>number</td>
+<td class='note'>
+</td>
+</tr>
+</table>
+\endraw
diff --git a/doc/src/06-qml-reference/03-attribute-names.qdoc b/doc/src/06-qml-reference/03-attribute-names.qdoc
new file mode 100644
index 00000000..35ed1477
--- /dev/null
+++ b/doc/src/06-qml-reference/03-attribute-names.qdoc
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is a wrapper for getting script-generated
+// content in 3_Attribute\ Names.html into qdoc.
+
+/*!
+ \page qml-reference-attribute-names.html
+ \title QML Reference: Attribute Names
+ \ingroup qt3dstudio-qml-api
+ \keyword Attributes
+
+ \include 03-attribute-names.html
+*/
diff --git a/doc/src/06-qml-reference/4-preserving-attributes.qdoc b/doc/src/06-qml-reference/4-preserving-attributes.qdoc
new file mode 100644
index 00000000..22158e58
--- /dev/null
+++ b/doc/src/06-qml-reference/4-preserving-attributes.qdoc
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+TODO: Needs to be rewritten or removed.
+
+\title QML: Preserving Attributes
+\page qml-reference-preserving-attributes.html
+\ingroup qt3dstudio-qml-api
+
+Everyone wants presentations to take
+up as little memory at runtime as possible. The benefits of memory
+efficiency are numerous, especially on embedded hardware where cache
+coherency is king. In order to minimize the amount of memory used by a
+given presentation the Qt 3D Studio Runtime employs several
+sophisticated and aggressive optimizations.
+
+One such optimization is the static analysis of a presentation performed
+by the runtime at startup. The runtime looks at each attribute on each
+element in the presentation and uses a simple heuristic to decide if a
+given attribute is `going to change at runtime'. The idea is that if an
+attribute is not going to change at runtime there is no point in storing
+it at all, anywhere. It will be set in the static scene and never need
+to be updated.
+
+The heuristic that is used to make this determination is twofold. An
+attribute will be preserved (not optimized away) if it is either (1)
+animated, or (2) an attribute on a master element that is unlinked and
+changed per-slide.
+
+A problem occurs when an attribute is optimized away and later a script
+tries to access or modify that attribute at runtime. When this happens
+this error message will be logged:
+\c{setAttribute: Attribute "someAttribute" not found.} The solution
+to this problem is to \"reference\" these attributes with the behavior
+that needs to change them to ensure they are not optimized away.
+
+Note that not every attribute needs to be referenced for scripting.
+Custom attributes on behaviors are never optimized away (otherwise, why
+did you add them?) and some other attributes are also never optimized
+away, such as \c{name} for all elements, or attributes specified to
+Text objects (because the runtime bitmap font engine needs access to the
+values to accurately render the text).
+
+\section1 References
+
+To make the references modular, and to ensure they require no knowledge
+or intervention from an artist wanting to use a behavior, the references
+are stored as part of the behavior. These are placed inside a
+\c{<Reference>} element in the \e{Artist Interface}
+preamble at the top of a behavior. For example:
+
+\badcode
+--[[
+ <Property ... />
+ <Property ... />
+ <Handler ... />
+ <Event ... />
+ <Event ... />
+ <Event ... />
+
+ <Reference>
+ parent.opacity
+ parent.children.position
+ </Reference>
+--]]
+
+-- The rest of the behavior code
+function self:onInitialize()
+ ...
+end
+\endcode
+
+Add reference strings to indicate which attributes this behavior needs
+at runtime to guarantee its proper execution. Each attribute reference
+string is made up of two parts:
+
+\list
+\li
+ the element or elements to preserve the attributes on,
+\li
+ followed by the attribute(s) to preserve.
+\endlist
+The first part can start with a path, either relative or absolute.
+\c{Scene.Layer.Cube} specifies a path to a certain cube absolutely,
+while \c{parent.Cube} specifies a path to a sibling Cube (relative
+to the behavior). Alternatively, the first part can start with a square
+bracketed name, like \c{{[}targetObject{]}} where the name in
+square brackets is the name of a Object Reference type custom property
+on this behavior. Using the square bracket syntax is equivalent to
+typing an absolute path to an object, except the object can be chosen by
+the artist in the inspector palette.
+
+The first part can optionally end with one of the two keywords,
+\c{.children} or \c{.descendants}. Specifying these will cause
+the specified attribute(s) to be preserved on either all of the children
+of the element pointed to by the specified path, or recursively preserve
+that attribute on all descendants. See the examples below for more
+details.
+
+The second part of the attribute reference string is the name of a
+attribute. The \e{\l{QML Reference: Attribute Names}{Attribute Names}}
+page of this manual outlines the names of the different
+attributes. You can also use the suffixe \c{.all} to preserve all
+attributes on a certain object, though this is typically not recommended
+as it undermines the operation of the optimizer.
+
+The second part of the attribute reference string can also use a square
+bracket syntax to reference a String type custom property on this
+behavior to specify (by name, as a string) which attribute to preserve.
+For example, if you had a String type custom property called
+\c{targetProp}, you could have an attribute reference string like
+\c{Scene.Layer.Cube.{[}targetProp{]}} which would preserve whatever
+property that was specified (by name) as the value of targetProp set in
+the inspector palette.
+
+Explaining that all in words is a bit cumbersome, the following examples
+show many different attribute reference strings.
+
+\section2 Reference Examples
+
+\badcode
+# Preserve opacity on a certain cube
+
+Scene.Layer.Cube.opacity
+
+# Preserve opacity on the element the behavior is attached to
+
+parent.opacity
+
+# Preserve position on all the children of a certain group
+
+Scene.Layer.Group.children.position
+
+# Same as above, but specify the group with an object reference custom property
+
+[targetGroup].children.position
+
+# Keep opacity on siblings and their descendants
+
+parent.descendants.opacity
+
+# Preserves the property typed in by the artist in the Inspector palette
+
+parent.[targetProp]
+
+# Circumvent the optimizer (don't do this :)
+
+Scene.descendants.all
+\endcode
+
+*/
diff --git a/doc/src/06-qml-reference/Element.qdoc b/doc/src/06-qml-reference/Element.qdoc
new file mode 100644
index 00000000..2a5a4d2f
--- /dev/null
+++ b/doc/src/06-qml-reference/Element.qdoc
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype Element
+ \inqmlmodule QtStudio3D
+ \brief Control type for elements in a Qt 3D Studio presentation.
+
+ This type is a convenience type for managing a presentation element.
+
+ All methods provided by this type are queued and handled asynchronously before the next
+ frame is displayed.
+
+ \sa Studio3D, Presentation, SceneElement
+*/
+
+/*!
+ \qmlproperty string Element::elementPath
+
+ Holds the element path of the presentation element.
+ This property must be set as part of Element declaration.
+ You can specify an element of a sub-presentation by adding "SubPresentationId:"
+ in front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Element::setAttribute(string attributeName, variant value)
+
+ Sets the \a value of an attribute on an element specified by this instance.
+ The \a attributeName is the \l{QML Reference: Attribute Names}{scripting name} of the attribute.
+
+ The attribute must be preserved for scripting to be set by this function, or else it will fail.
+ An attribute is preserved if it is either \e{animated}, or
+ \e{an attribute on a master element that is unlinked and changed per-slide}.
+*/
+
+/*!
+ \qmlmethod void Element::fireEvent(string eventName)
+
+ Dispatches an event with \a eventName on the element specified by this instance.
+ Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
+ method in attached scripts will be executed in response to the event.
+*/
+
+/*!
+ \qmlsignal Element::elementPathChanged(string elementPath)
+
+ This signal is emitted when the element path property changes.
+ The new value is provided in the \a elementPath parameter.
+
+ The corresponding handler is \c onElementPathChanged.
+*/
diff --git a/doc/src/06-qml-reference/Presentation.qdoc b/doc/src/06-qml-reference/Presentation.qdoc
new file mode 100644
index 00000000..298942c9
--- /dev/null
+++ b/doc/src/06-qml-reference/Presentation.qdoc
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype Presentation
+ \inqmlmodule QtStudio3D
+ \brief Control type for Qt 3D Studio presentations.
+
+ This type provides properties and methods for controlling a presentation.
+
+ All methods provided by this type are queued and handled asynchronously before the next
+ frame is displayed.
+
+ \sa Studio3D
+*/
+
+/*!
+ \qmlproperty url Presentation::source
+
+ Holds the presentation source (\c{*.uia} or \c{*.uip}) file location.
+ May be either a file URL or a qrc URL.
+*/
+
+/*!
+ \qmlproperty SubPresentationSettings Presentation::subPresentationSettings
+
+ Holds the settings for the subpresentations in the Qt 3D Studio presentation.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToSlide(string elementPath, string name)
+
+ Requests a time context (a Scene or a Component element) to change to a specific slide
+ by \a name. If the context is already on that slide playback will start over.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToSlide(string elementPath, int index)
+
+ Requests a time context (a Scene or a Component element) to change to a specific slide by
+ index \a index. If the context is already on that slide playback will start over.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToSlide(string elementPath, bool next, bool wrap)
+
+ Requests a time context (a Scene or a Component element) to change to the next or the
+ previous slide, depending on the value of \a next. If the context is already at the
+ last or first slide, \a wrap defines if change occurs to the opposite end.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::goToTime(string elementPath, real time)
+
+ Sets a time context (a Scene or a Component element) to a specific playback \a time in seconds.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+
+ The behavior when specifying a time before 0 or after the end time for the current slide depends
+ on the play mode of the slide:
+ \list
+ \li \c{Stop at End} - values outside the valid time range instead clamp to the boundaries.
+ For example, going to time -5 is the same as going to time 0.
+ \li \c{Looping} - values outside the valid time range mod into the valid range. For example,
+ going to time -4 on a 10 second slide is the same as going to time 6.
+ \li \c{Ping Pong} - values outside the valid time range ‘bounce’ off the ends. For example,
+ going to time -4 is the same as going to time 4 (assuming the time context is at least 4 seconds
+ long), while going to time 12 on a 10 second slide is the same as going to time 8.
+ \li \c{Ping} - values less than 0 are treated as time 0, while values greater than the endtime
+ bounce off the end (eventually hitting 0.)
+ \endlist
+*/
+
+/*!
+ \qmlmethod void Presentation::setAttribute(string elementPath, string attributeName,
+ variant value)
+
+ Sets the \a value of an attribute on an element found at \a elementPath. The \a attributeName is
+ the \l{QML Reference: Attribute Names}{scripting name} of the attribute.
+
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene.Mesh.Material"}.
+
+ The attribute must be preserved for scripting to be set by this function, or else it will fail.
+ An attribute is preserved if it is either \e{animated}, or
+ \e{an attribute on a master element that is unlinked and changed per-slide}.
+*/
+
+/*!
+ \qmlmethod void Presentation::setPresentationActive(string id, bool active)
+
+ Stops or starts updates to a sub-presentation based on the \a active flag. The presentation is
+ referenced to by the \a id, which is the name of the presentation without the \c{.uip}.
+
+ Making a presentation inactive prevents any elements, behaviors, and animations within it from
+ updating. It also prevents any events within that presentation from being processed. It does
+ not, however, prevent the presentation from rendering. An inactive presentation will continue
+ to render using its last-updated information.
+
+ Explicitly inactivating presentations can provide a significant performance increase, depending
+ on the number and size of the presentations that are inactive. Inactive presentations are not
+ ‘paused’. When the presentation is re-activated, animations will resume at the time they should
+ be had they been running, not where they were when the presentation was made inactive.
+*/
+
+/*!
+ \qmlmethod void Presentation::fireEvent(string elementPath, string eventName)
+
+ Dispatches an event with \a eventName on a specific element found in \a elementPath. Appropriate
+ Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
+ method in attached scripts will be executed in response to the event.
+
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene.Mesh"}.
+*/
+
+/*!
+ \qmlmethod void Presentation::setGlobalAnimationTime(int64 milliseconds)
+
+ Sets the global animation time to \a milliseconds. Setting the global animation time to a
+ non-zero value will disable the automatic animation timer. Setting the value to zero
+ resumes automatic animation timer.
+*/
+
+/*!
+ \qmlsignal Presentation::slideEntered(string elementPath, int index, string name)
+
+ This signal is emitted when a slide is entered in the presentation.
+ The \a elementPath specifies the time context (a Scene or a Component element) owning the
+ entered slide.
+ The \a index and \a name contain the index and the name of the entered slide.
+*/
+
+/*!
+ \qmlsignal Presentation::slideExited(string elementPath, int index, string name)
+
+ This signal is emitted when a slide is exited in the presentation.
+ The \a elementPath specifies the time context (a Scene or a Component element) owning the
+ exited slide.
+ The \a index and \a name contain the index and the name of the exited slide.
+*/
+
+/*!
+ \qmlsignal Presentation::sourceChanged(url source)
+
+ This signal is emitted when the source property has changed.
+ The new value is provided in the \a source parameter.
+
+ The corresponding handler is \c onSourceChanged.
+*/
diff --git a/doc/src/06-qml-reference/Qt3DS_QML_Texture_Streaming.qdoc b/doc/src/06-qml-reference/Qt3DS_QML_Texture_Streaming.qdoc
new file mode 100644
index 00000000..c56769ce
--- /dev/null
+++ b/doc/src/06-qml-reference/Qt3DS_QML_Texture_Streaming.qdoc
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype SubPresentationSettings
+ \inqmlmodule QtStudio3D 1.0
+ \brief Settings for subpresentations.
+
+ This type enables specifying settings for the subpresentations
+ from Qt Quick application.
+
+ \note Currently only 'presentation-qml' settings can be set.
+
+ \section2 Usage
+
+ \qml
+ Studio3D {
+ id: studio3D
+ Presentation {
+ source: "file:///presentation.uia"
+ SubPresentationSettings {
+ qmlStreams: [
+ QmlStream {
+ presentationId: "sub-presentation-id"
+ Item {
+ width: 1024
+ height: 1024
+ }
+ }
+ ]
+ }
+ }
+ }
+ \endqml
+ */
+
+/*!
+ \qmlproperty list<QmlStream> SubPresentationSettings::qmlStreams
+
+ Holds the list of settings for 'presentation-qml' subpresentations.
+ */
+
+/*!
+ \qmltype QmlStream
+ \inqmlmodule QtStudio3D
+ \brief QML stream.
+
+ This type allows attaching qml-subpresentation with a quick item. The item is rendered to a
+ texture and used as a part of a Qt 3D Studio presentation.
+
+ The subpresentation element must be specified in the \e assets element of the presentation
+ .uia file:
+
+ \badcode
+ <assets ...>
+ <presentation-qml id="presentation-id" args="preview-presentation.qml" />
+ </assets>
+ \endcode
+
+ The 'presentation-id' attribute must contain a unique ID of the subpresentation.
+ The 'args' attribute may contain an optional preview version of the item, which is only
+ used in the Viewer application.
+ */
+
+/*!
+ \qmlproperty string QmlStream::presentationId
+
+ Holds the string ID of the subpresentation the item is attached to. The id must be one of
+ the 'presentation-qml' IDs specified in the .uia file.
+ */
+
+/*!
+ \qmlproperty Item QmlStream::item
+
+ Holds the item attached to the subpresentation. The item size is used as the the size of the
+ texture the item is rendered to. Default values \c{(256, 256)} are used if the item doesn't
+ specify a size.
+ */
diff --git a/doc/src/06-qml-reference/SceneElement.qdoc b/doc/src/06-qml-reference/SceneElement.qdoc
new file mode 100644
index 00000000..e99b6d3b
--- /dev/null
+++ b/doc/src/06-qml-reference/SceneElement.qdoc
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype SceneElement
+ \inqmlmodule QtStudio3D
+ \inherits Element
+ \brief Control type for scene and component elements in a Qt 3D Studio presentation.
+
+ This type is a convenience type for managing the slides of a single
+ time context (a Scene or a Component element) of a presentation.
+
+ All methods provided by this type are queued and handled asynchronously before the next
+ frame is displayed.
+
+ \sa Studio3D, Presentation
+*/
+
+/*!
+ \qmlproperty int SceneElement::currentSlideIndex
+
+ Holds the index of the currently active slide of the tracked time context.
+
+ Changing the current slide via this property is asynchronous. The property
+ value will not actually change until the next frame has been processed, and
+ even then only if the new slide was valid.
+
+ \note If this property is set to something else than the default slide for the scene at the
+ initial declaration of SceneElement, you will still get an extra changed signal for the
+ default slide before the slide changes to the desired one. This happens in order to ensure
+ we end up with the index of the slide that is actually shown even if the slide specified in the
+ initial declaration is invalid.
+*/
+
+/*!
+ \qmlproperty int SceneElement::previousSlideIndex
+
+ Holds the index of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlproperty string SceneElement::currentSlideName
+
+ Holds the name of the currently active slide of the tracked time context.
+
+ Changing the current slide via this property is asynchronous. The property
+ value will not actually change until the next frame has been processed, and
+ even then only if the new slide was valid.
+
+ \note If this property is set to something else than the default slide for the scene at the
+ initial declaration of SceneElement, you will still get an extra changed signal for the
+ default slide before the slide changes to the desired one. This happens in order to ensure
+ we end up with the name of the slide that is actually shown even if the slide specified in the
+ initial declaration is invalid.
+*/
+
+/*!
+ \qmlproperty string SceneElement::previousSlideName
+
+ Holds the name of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlsignal SceneElement::currentSlideIndexChanged(int currentSlideIndex)
+
+ This signal is emitted when the current slide changes.
+ The new value is provided in the \a currentSlideIndex parameter.
+
+ This signal is always emitted with currentSlideNameChanged.
+
+ The corresponding handler is \c onCurrentSlideIndexChanged.
+*/
+
+/*!
+ \qmlsignal SceneElement::previousSlideIndexChanged(int previousSlideIndex)
+
+ This signal is emitted when the previous slide changes.
+ The new value is provided in the \a previousSlideIndex parameter.
+
+ This signal is always emitted with previousSlideNameChanged.
+
+ The corresponding handler is \c onPreviousSlideIndexChanged.
+*/
+
+/*!
+ \qmlsignal SceneElement::currentSlideNameChanged(string currentSlideName)
+
+ This signal is emitted when the current slide changes.
+ The new value is provided in the \a currentSlideName parameter.
+
+ This signal is always emitted with currentSlideIndexChanged.
+
+ The corresponding handler is \c onCurrentSlideNameChanged.
+*/
+
+/*!
+ \qmlsignal SceneElement::previousSlideNameChanged(string previousSlideName)
+
+ This signal is emitted when the previous slide changes.
+ The new value is provided in the \a previousSlideName parameter.
+
+ This signal is always emitted with previousSlideIndexChanged.
+
+ The corresponding handler is \c onPreviousSlideNameChanged.
+*/
+
+/*!
+ \qmlmethod void SceneElement::goToSlide(bool next, bool wrap)
+
+ Requests a time context (a Scene or a Component element) to change to the next or the
+ previous slide, depending on the value of \a next. If the context is already at the
+ last or first slide, \a wrap defines if change occurs to the opposite end.
+*/
+
+/*!
+ \qmlmethod void SceneElement::goToTime(string elementPath, real time)
+
+ Sets a time context (a Scene or a Component element) to a specific playback \a time in seconds.
+
+ For behavior details, see Presentation::goToTime() documentation.
+*/
diff --git a/doc/src/06-qml-reference/Studio3D.qdoc b/doc/src/06-qml-reference/Studio3D.qdoc
new file mode 100644
index 00000000..9033df39
--- /dev/null
+++ b/doc/src/06-qml-reference/Studio3D.qdoc
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype Studio3D
+ \inqmlmodule QtStudio3D
+ \brief Qt 3D Studio presentation viewer.
+
+ This type enables developers to embed Qt 3D Studio presentations in Qt Quick.
+
+ \section2 Example usage
+
+ \qml
+ Studio3D {
+ id: studio3D
+ Presentation {
+ source: "qrc:///presentation.uia"
+ SceneElement {
+ id: scene
+ elementPath: "Scene"
+ currentSlideIndex: 2
+ }
+ Element {
+ id: textLabel
+ elementPath: "Scene.Layer.myLabel"
+ }
+ }
+ ViewerSettings {
+ showRenderStats: true
+ }
+ onRunningChanged: {
+ console.log("Presentation ready!");
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Studio3D::running
+
+ The value of this property is \c true when the viewer has been initialized and the presentation
+ is running.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlproperty Presentation Studio3D::presentation
+
+ Accessor for the presentation.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlproperty ViewerSettings Studio3D::viewerSettings
+
+ Accessor for the viewer settings.
+
+ This property is read-only.
+*/
+
+/*!
+ \qmlsignal Studio3D::frameUpdate()
+
+ This signal is emitted each time a frame has been updated regardless of visibility.
+ This allows a hidden Studio3D element to still process information every frame, even though
+ the renderer is not rendering.
+
+ The corresponding handler is \c onFrameUpdate.
+
+ To prevent expensive handlers from being processed when hidden, add an early return to
+ the top like:
+
+ \qml
+ onFrameUpdate: {
+ if (!visible) return;
+ ...
+ }
+ \endqml
+*/
diff --git a/doc/src/06-qml-reference/ViewerSettings.qdoc b/doc/src/06-qml-reference/ViewerSettings.qdoc
new file mode 100644
index 00000000..a11734bf
--- /dev/null
+++ b/doc/src/06-qml-reference/ViewerSettings.qdoc
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype ViewerSettings
+ \inqmlmodule QtStudio3D
+ \brief Qt 3D Studio presentation viewer settings.
+
+ This type provides properties to define presentation independent viewer settings.
+
+ \sa Studio3D
+*/
+
+/*!
+ \qmlproperty color ViewerSettings::matteColor
+
+ Specifies the color of the viewer area not occupied by the presentation.
+ Default value is black.
+*/
+
+/*!
+ \qmlproperty bool ViewerSettings::showRenderStats
+
+ If this property is set to \c{true}, render statistics are displayed on the upper part
+ of the viewer.
+ Default value is \c{false}.
+*/
+
+/*!
+ \qmlproperty enumeration ViewerSettings::shadeMode
+
+ The shading mode used for the viewed presentation.
+ The default value is \c{ShadeModeShaded}.
+
+ \value ViewerSettings.ShadeModeShaded The objects in the presentation are shaded normally.
+ \value ViewerSettings.ShadeModeShadedWireframe The objects in the presentation are shaded
+ with a super-imposed wireframe on top of the normal shading. Only objects that specify
+ a tesselation mode will display this wireframe.
+
+ \sa Q3DSViewerSettings::ShadeMode
+*/
+
+/*!
+ \qmlproperty enumeration ViewerSettings::scaleMode
+
+ The scaling mode used for the viewer presentation.
+
+ \value ViewerSettings::ScaleModeFit Scales the presentation to fit the viewer.
+ \value ViewerSettings::ScaleModeFill Scales the presentation to fill the viewer.
+ \value ViewerSettings::ScaleModeCenter Centers the presentation into the viewer without
+ scaling it.
+ The default value is \c{ScaleModeCenter}.
+
+ \sa Q3DSViewerSettings::ScaleMode
+*/
+
+/*!
+ \qmlsignal ViewerSettings::matteColorChanged(color color)
+
+ This signal is emitted when the matteColor property has changed.
+ The new value is provided in the \a color parameter.
+
+ The corresponding handler is \c onMatteColorChanged.
+*/
+
+/*!
+ \qmlsignal ViewerSettings::showRenderStatsChanged(bool show)
+
+ This signal is emitted when the showRenderStats property has changed.
+ The new value is provided in the \a show parameter.
+
+ The corresponding handler is \c onShowRenderStatsChanged.
+*/
+
+/*!
+ \qmlsignal ViewerSettings::shadeModeChanged(enumeration mode)
+
+ This signal is emitted when the shadeMode property has changed.
+ The new value is provided in the \a mode parameter.
+
+ The corresponding handler is \c onShadeModeChanged.
+*/
+
+/*!
+ \qmlsignal ViewerSettings::scaleModeChanged(enumeration mode)
+
+ This signal is emitted when the scaleMode property has changed.
+ The new value is provided in the \a mode parameter.
+
+ The corresponding handler is \c onScaleModeChanged.
+*/
+
+/*!
+ \qmlmethod void ViewerSettings::save(string group, string organization, string application)
+
+ Persistently saves the viewer \l{QSettings}{settings} using \a group, \a organization and
+ \a application.
+*/
+
+/*!
+ \qmlmethod void ViewerSettings::load(string group, string organization, string application)
+
+ Loads previously saved viewer \l{QSettings}{settings} using \a group, \a organization and
+ \a application.
+*/
diff --git a/doc/src/06-qml-reference/qml-index.qdoc b/doc/src/06-qml-reference/qml-index.qdoc
new file mode 100644
index 00000000..97fabb75
--- /dev/null
+++ b/doc/src/06-qml-reference/qml-index.qdoc
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\qmlmodule QtStudio3D 1.0
+\title Qt 3D Studio QML Types
+\keyword QML API
+\ingroup qmlmodules
+\noautolist
+
+Qt 3D Studio provides a number of QML types to view and control the
+presentation. These types can be imported into your application using the
+following import statement in your .qml file:
+
+\badcode
+import QtStudio3D 1.0
+\endcode
+
+\section1 QML Types
+
+\generatelist {qmltypesbymodule QtStudio3D}
+
+\section1 Additional Information
+
+//! [toc]
+\list
+\omit
+TODO: Needs to be rewritten or removed.
+\li \l {QML: Preserving Attributes}{Preserving Attributes}
+\endomit
+\li \l {QML Reference: Attribute Names}{Attribute Names}
+\endlist
+//! [toc]
+*/
diff --git a/doc/src/07-file-formats/0-uia.qdoc b/doc/src/07-file-formats/0-uia.qdoc
new file mode 100644
index 00000000..5b8c0dd2
--- /dev/null
+++ b/doc/src/07-file-formats/0-uia.qdoc
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+TODO: Rewrite is needed.
+
+\title The .uia File Format
+\page file-formats-uia.html
+\ingroup qt3dstudio-file-formats
+
+Every project has one \c{.uia}
+file (which we like to pronounce as \e{\"OO-yah!\"})
+representing the application. This XML file is created automatically
+when you create a new project with Qt 3D Studio. The file contains an \c{<assets>}
+section followed by zero or more
+\c{<statemachine>} sections:
+
+\badcode
+<?xml version="1.0" encoding="UTF-8"?>
+<application scalemode="center" watermark-location="1.0 1.0" xmlns="http://nvidia.com/uicomposer">
+ <assets initial="#IVI">
+ <behavior id="MainApp" src="scripts/App.lua" />
+ <presentation id="IVI" src="IVI.uip" />
+ <presentation id="music" src="sub_music.uip" />
+ <presentation id="radio" src="sub_radio.uip" active="false" />
+ <statemachine id="logic" src="./charts/app.scxml" datamodel="getIt()" />
+ <renderplugin id="plugin:mapviewer" src="scripts/mylib.so" args="whee" />
+ </assets>
+
+ <statemachine ref="#logic">
+ <visual-states>
+ <state ref="Menu">
+ <enter>
+ <goto-slide element="IVI:Scene.Layer3D.Camera" slide="Animated"/>
+ </enter>
+ <exit>
+ <goto-slide element="IVI:Scene" rel="next" wrap="true"/>
+ </exit>
+ </state>
+ <state ref="Climate"><enter>
+ <call element="IVI:Scene.Menu" handler="focusItem" arguments="'Climate'"/>
+ <set-attribute element="IVI:Scene.Subs" attribute="sourcepath" value="'phone'"/>
+ </enter></state>
+ <transition ref="transition_93">
+ <fire-event element="IVI:Scene" event="onSomethingHappened" />
+ </transition>
+ </visual-states>
+ </statemachine>
+</application>
+\endcode
+
+\section1 Application
+
+The \c{<application>} element encompasses
+the contents of the file and also specifies simple attributes for the
+application's display.
+
+The \c{scalemode="..."} attribute specifies how large the
+\"initial presentation\" \e{(see below)} is rendered when the
+dimensions of the supplied viewport are different than the size entered
+for that presentation. There are three legal values for this attribute:
+
+\list
+\li
+ \c{scalemode="center"} - the presentation is rendered at the size
+ specified in Studio. Additional content is cropped, additional space
+ is letterboxed. This setting is the default behavior if not specified.
+\li
+ \c{scalemode="fit"} - the aspect ratio of the initial
+ presentation is preserved, letterboxing as needed.
+\li
+ \c{scalemode="fill"} - the presentation is always rendered to
+ fill the viewport.
+\endlist
+\e{For more information on the behavior of the \c{scalemode}
+settin - nd its interaction with layer sizing and camera scalin - ee
+\l{best-practices-scalemodes.html}{Using Scale Modes}.}
+
+\section1 Assets
+
+The \c{<assets>} section may contain one or
+more \c{<behavior/>},
+\c{<presentation/>},
+\c{<statemachine/>}, and
+\c{<renderplugin/>} elements, in any order.
+
+Each asset must have a unique \c{id="..."} attribute and a
+\c{src="..."} attribute referencing the location of the file
+(relative to the project folder).
+
+A \c{<statemachine/>} asset may optionally
+have a \c{datamodel="..."} attribute. If present, this attribute
+must provide valid Lua code to run that returns a Lua table. The
+contents of this table will be used for the initial values in the data
+model of the state chart.
+
+A \c{<renderplugin/>} asset may optionally
+have a \c{args="..."} attribute. This provides arguments needed to
+initialize the shared library for the plugin.
+
+An application does not need any
+\c{<presentation/>} elements to run. This
+allows you to create state charts and test them before any visuals have
+been created. Such an application will not display anything on screen,
+however.
+
+If more than one \c{<presentation/>} asset
+is supplied then the first one listed is chosen as the `initial'
+(outermost) presentation that renders for the application; all others
+are treated as `sub-presentations' which may be referenced by the main
+presentation. To select a different presentation as the initial the
+\c{<assets>} element may have an
+\c{initial="\#presentation-id"} attribute referencing the
+presentation to use as the main presentation.
+
+A \c{<presentation/>} element may
+\e{optionally} have an \c{active="..."} attribute with either
+the value \c{true} (the default) or \c{false}. \e{See the
+\l{set-presentation}{\c{<set-presentation> action}}
+below for more information on the effects of making a presentation
+inactive.}
+
+All \c{<behavior/>} assets are initialized
+before any \c{<statemachine/>} assets,
+regardless of element ordering. This allows you to create a global
+function in your application behaviors and use that function to
+initialize the data model for a state chart.
+
+\section1 Visual States
+
+Each \c{<statemachine/>} in the
+\c{<assets>} section (above) may have a
+paired \c{<statemachine>} element following
+the \c{<assets>} section. These provide the
+glue between the logical states of the state chart and the visual impact
+displayed by the presentation(s).
+
+A \c{<statemachine>} section must have a
+\c{ref="\#statemachine-asset-id"} attribute referencing the state
+chart to listen to.
+
+The only allowed child element of a
+\c{<statemachine>} section is
+\c{<visual-states>}. The
+\c{<visual-states>} element may have zero or
+more \c{<state>} and
+\c{<transition>} elements, in any order.
+
+\list
+\li
+ Each \c{<state>} element must have a
+ \c{ref="StateId"} attribute describing a valid state id in the
+ associated state chart. It may have either or both of
+ \c{<enter>} and
+ \c{<exit>} elements, describing what
+ occurs when the state is entered or exited. Each of these elements may
+ have zero or more visual action elements (see below).
+\li
+ Each \c{<transition>} element must have a
+ \c{ref="TransitionId"} attribute describing a valid transition id
+ in the associated state chart. It may have zero or more visual action
+ elements that describe what occurs when the transition is taken.
+\endlist
+
+\target visual-actions
+\section1 Visual Actions
+
+The content elements in each \c{<enter>},
+\c{<exit>}, and
+\c{<transition>} element may be any of the
+following (as many as you like, in any order):
+
+\target goto-slide
+\section2 \c{<goto-slide element="..."/>}
+
+\e{Change scene or component slide, possibly changing how it plays}.
+
+\list
+\li
+ The \b{\c{element}} attribute must reference a full path to
+ a Scene or component element in a presentation, prefixed with that
+ presentation's id and a colon. \e{For example,
+ \c{element="IVI:Scene.Background.Theme"}.}
+\li
+ The action must have \e{either} a \c{slide="..."}** or
+ \c{rel="..."} attribute (but not both):
+\li
+ The \b{\c{slide}} attribute must reference the name of a
+ slide to go to.
+\li
+ The \b{\c{rel}} attribute must be either \c{rel="next"}
+ or \c{rel="prev"}, describing a direction to change slides.
+ \list
+ \li
+ (optional) With \c{rel} you may also supply
+ \c{wrap="true"} to indicate that slide changes past the end of
+ the slide list should wrap to the slide on the other end.
+ \endlist
+\li
+ (optional) Specifying \b{\c{direction="..."}} will
+ force playback on the new slide to go either \c{forward} or
+ \c{reverse}.
+\li
+ If the direction is \c{reverse} and no \c{time="..."}
+ attribute is specified \e{(see below)} then playback will start at
+ the end time of the slide.
+\li
+ (optional) Specifying \b{\c{mode="..."}} will override
+ the play mode for the slide to be one of: \c{stopatend},
+ \c{looping}, \c{ping}, \c{pingpong}, or
+ \c{playthrough}.
+\li
+ If \c{playthrough} is specified you must also add
+ \c{playthroughto="..."} with either the name of a slide to
+ play through to, or the values \c{next} or \c{previous}.
+\li
+ (optional) Specifying \b{\c{state="..."}} with either
+ \c{play} or \c{pause} will override the play state set for
+ the slide.
+\li
+ (optional) Specifying \b{\c{rate="..."}} with a
+ floating point value will cause the playback speed to be multiplied by
+ this value.
+\li
+ \e{For example, a value of \c{2} will cause animations on the
+ slide to play back twice as fast as normal, while a value of
+ \c{0.5} will cause animations to play at half speed.}
+\li
+ \e{The behavior of the runtime for negative rate values is not
+ guaranteed; use \c{direction="reverse"} to play backwards.}
+\li
+ (optional) Specifying \b{\c{time="..."}} with a
+ floating point value will cause playback to start at the specified
+ time.
+\endlist
+
+\section2 \c{<call element="..." handler="..."/>}
+
+\e{Invoke a function on a presentation behavior}.
+
+\list
+\li
+ The \b{\c{element}} attribute must reference a full
+ id-prefixed path to a behavior element in a presentation.
+\li
+ The \b{\c{handler}} attribute must match the name of a
+ function value on the table for the referenced behavior.
+\li
+ (optional) Specifying an \c{arguments="..."} attribute allows you
+ to pass arguments to the function. The contents of this attribute are
+ evaluated in the global Lua context. If the resulting value is a Lua
+ table, it is treated as a list and each integer-keyed value passed to
+ the function through \c{unpack()}. If the result is any other
+ type of value it is passed as a single first parameter to the
+ function.
+\li
+ \e{To pass just one argument, use \c{arguments="42"}}
+\li
+ \e{To pass multiple arguments, use \c{arguments="\{1,2,3\}"}}
+\li
+ \e{To pass a single Lua table to the function wrap it in a list
+ table, e.g. \c{arguments="\{\{hello='World',valid=true\}\}"}}
+\endlist
+
+\section2 \c{<set-attribute element="..." attribute="..." value="..."/>}
+
+\e{Set a value on a presentation element}.
+
+\list
+\li
+ The \b{\c{element}} attribute must reference a full
+ id-prefixed path to any element in a presentation.
+\li
+ The \b{\c{attribute}} attribute must match the
+ \l{QML Reference: Attribute Names}{scripting name} of an attribute on that element.
+\li
+ The \b{\c{value}} attribute must provide a Lua expression to
+ evaluate, the result of which will be set as the value on the element.
+\endlist
+
+\e{For example,
+\c{<set-attribute element="IVI:Scene.Background" attribute="name" value="'new name'"/>};
+note the extra quotes needed in the \c{value} attribute to set a
+string value.}
+
+\target set-presentation
+\section2 \c{<set-presentation ref="..." attribute="active" value="..."/>}
+
+\e{make a presentation active/inactive}.
+
+\list
+\li
+ The \b{\c{ref}} must be the id of a
+ \c{<presentation/>} in the
+ \c{<assets>} section.
+\li
+ The \b{\c{attribute}} attribute must be equal to
+ \c{active}. \e{(Future releases may allow the control of more
+ presentation attributes.)}
+\li
+ The \b{\c{value}} attribute must be either \c{true} or
+ \c{false}. \e{(Arbitrary Lua expressions are not supported at
+ this time.)}
+\endlist
+
+\e{For example,
+\c{<set-presentation ref="music" attribute="active" value="true"/>}.}
+
+\b{Notes}
+
+\list
+\li
+ Making a presentation inactive prevents any elements, behaviors, and
+ animations within it from updating. It also prevents any events within
+ that presentation from being processed. It does not, however, prevent
+ the presentation from rendering. An inactive presentation will
+ continue to render using its last-updated information.
+\li
+ Explicitly inactivating presentations can provide a significant
+ performance increase, depending on the number and size of the
+ presentations that are inactive.
+\li
+ Inactive presentations are not `paused'. When the presentation is
+ re-activated, animations will resume at the time they should be had
+ they been running, not where they were when the presentation was made
+ inactive.
+\endlist
+
+\section2 \c{<fire-event element="..." event="..."/>}
+
+\e{Fire a presentation event on an element in the presentation}.
+
+\list
+\li
+ The \b{\c{element}} attribute must reference a full
+ id-prefixed path to any element in a presentation.
+\li
+ The \b{\c{event}} attribute must be the name of the event to
+ fire.
+\endlist
+
+*/
diff --git a/doc/src/07-file-formats/1-uip.qdoc b/doc/src/07-file-formats/1-uip.qdoc
new file mode 100644
index 00000000..71508d01
--- /dev/null
+++ b/doc/src/07-file-formats/1-uip.qdoc
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\omit
+\title The .uip File Format hide : true
+\page file-formats-uip.html
+
+ \e{Content goes here}
+\endomit
+*/
diff --git a/doc/src/07-file-formats/3-material.qdoc b/doc/src/07-file-formats/3-material.qdoc
new file mode 100644
index 00000000..a7c84d67
--- /dev/null
+++ b/doc/src/07-file-formats/3-material.qdoc
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title The .material Format
+\page file-formats-material.html
+\ingroup qt3dstudio-file-formats
+
+Qt 3D Studio supports custom
+materials used to render elements. Materials are arbitrary single-pass
+GLSL shaders, wrapped in a file format providing an artist-friendly
+interface for tweaking material parameters in Studio.
+
+\section1 Overview
+
+The general structure of a \c{.material} file is shown below. Note
+that some of the attributes and elements shown here are optional (and
+this example does not include all possible attributes):
+
+\badcode
+<Material formalName="..." version="1.0">
+ <MetaData author="...">
+ <Property name="..." />
+ <Property name="..." />
+ </MetaData>
+ <Shaders type="GLSL">
+ <Shader>
+ <VertexShader>
+ <Source>...</Source>
+ </VertexShader>
+ <FragmentShader>
+ <Source>...</Source>
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+</Material>
+\endcode
+
+The actual code for the shader is placed within the
+\c{<Source>} elements.
+
+\section1 Schemata
+
+Legal \c{.material} files are described by the following formal
+schemata. The RelaxNG Compact schema is the reference from which the XML
+Schema Definition schema was derived.
+
+\section2 RelaxNG Compact (\c{.rnc)}
+
+\badcode
+grammar \{
+ start = MaterialElement # Everything is wrapped in a <Material> element
+
+ MaterialElement = element Material \{
+ attribute version \{"1.0"\, }# This file describes version 1.0 only
+ attribute formalName \{text\?, }# The formalName attribute is optional; default: filename (minus extension)
+ attribute description \{text\?, }# Optional long description of the material
+ MetaDataElement?, # <MetaData> is optional,
+ ShadersElement # but <Shaders> is required
+ \}
+
+ MetaDataElement = element MetaData\{
+ attribute author \{text\?, }# Various descriptive attributes (optional)
+ attribute created \{text\?,}
+ attribute modified \{text\?,}
+ PropertyElement* # Zero or more <Property> elements
+ \}
+
+ PropertyElement = element Property \{ # All <Property> attributes are optional except for name
+ attribute name \{xsd:ID\, }# The internal, script name of the property (must be a unique identifier)
+ attribute description \{text\?, }# Tooltip to display in Inspector palette
+ attribute formalName \{text\?, }# The name to display in Inspector palette; default: the property `name`
+ attribute type \{PropertyType\?, }# The type of the property (defined below); default: Float
+ attribute min \{xsd:float\?, }# UI min value for numeric types; default: none
+ attribute max \{xsd:float\?, }# UI max value for numeric types; default: none
+ attribute default \{text\?, }# Default value for the property; default: 0/""
+ attribute usage \{UsageType\?, }# Only for textures; default: diffuse
+ attribute filter \{FilterType\?, }# Only for textures; default: linear
+ attribute clamp \{ClampType\? }# Only for textures; default: wrap
+ \}
+
+ ShadersElement = element Shaders \{
+ attribute type \{"GLSL" | "HLSL"\?, }# Optional shader type; only GLSL supported. default: GLSL
+ attribute version \{text\?, }# Code version
+ element Shared \{text\?, }# Arbitrary definition code to run for all shaders (optional)
+ ShaderElement+ # There must be at least one <Shader> in the .material file
+ \}
+
+ ShaderElement = element Shader \{
+ attribute name \{xsd:NCName\?, }# An identifier-like name
+ ((VSEl | FSEl) | (VSEl & FSEl)) # Either or both of <VertexShader> and <FragmentShader>, in either order
+ \}
+ VSEl = element VertexShader \{ShaderContent\}
+ FSEl = element FragmentShader \{ShaderContent\}
+
+ ShaderContent = element Source \{ text \ }# Shaders currently require a single <Source> element
+
+ UsageType = "diffuse" | "specular" | "bump" | "environment"
+ FilterType = "nearest" | "linear"
+ ClampType = "clamp" | "wrap"
+ PropertyType = "Boolean" | "Color" | "Float" | "Float2" | "Font"
+ | "FontSize" | "Image" | "Import" | "Long" | "Mesh"
+ | "MultiLineString" | "Rotation" | "String" | "Vector"
+ | "Texture" | "Texture3D" | "TextureCube"
+\}
+\endcode
+
+\section2 XML Schema Definition (\c{.xsd)}
+
+\badcode
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <xs:element name="Material">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="MetaData"/>
+ <xs:element ref="Shaders"/>
+ </xs:sequence>
+ <xs:attribute name="version" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="1.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="formalName"/>
+ <xs:attribute name="description"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MetaData">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="Property"/>
+ </xs:sequence>
+ <xs:attribute name="author"/>
+ <xs:attribute name="created"/>
+ <xs:attribute name="modified"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Property">
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:ID"/>
+ <xs:attribute name="description"/>
+ <xs:attribute name="formalName"/>
+ <xs:attribute name="type" type="PropertyType"/>
+ <xs:attribute name="min" type="xs:float"/>
+ <xs:attribute name="max" type="xs:float"/>
+ <xs:attribute name="default"/>
+ <xs:attribute name="usage" type="UsageType"/>
+ <xs:attribute name="filter" type="FilterType"/>
+ <xs:attribute name="clamp" type="ClampType"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Shaders">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="Shared"/>
+ <xs:element maxOccurs="unbounded" ref="Shader"/>
+ </xs:sequence>
+ <xs:attribute name="type">
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="GLSL"/>
+ <xs:enumeration value="HLSL"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="version"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Shared" type="xs:string"/>
+ <xs:element name="Shader">
+ <xs:complexType>
+ <xs:choice>
+ <xs:choice>
+ <xs:element ref="VertexShader"/>
+ <xs:element ref="FragmentShader"/>
+ </xs:choice>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="VertexShader"/>
+ <xs:element ref="FragmentShader"/>
+ </xs:choice>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:NCName"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="VertexShader" type="ShaderContent"/>
+ <xs:element name="FragmentShader" type="ShaderContent"/>
+ <xs:complexType name="ShaderContent">
+ <xs:sequence>
+ <xs:element ref="Source"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="Source" type="xs:string"/>
+ <xs:simpleType name="UsageType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="diffuse"/>
+ <xs:enumeration value="specular"/>
+ <xs:enumeration value="bump"/>
+ <xs:enumeration value="environment"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="FilterType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="nearest"/>
+ <xs:enumeration value="linear"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ClampType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="clamp"/>
+ <xs:enumeration value="wrap"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="PropertyType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="Boolean"/>
+ <xs:enumeration value="Color"/>
+ <xs:enumeration value="Float"/>
+ <xs:enumeration value="Float2"/>
+ <xs:enumeration value="Font"/>
+ <xs:enumeration value="FontSize"/>
+ <xs:enumeration value="Image"/>
+ <xs:enumeration value="Import"/>
+ <xs:enumeration value="Long"/>
+ <xs:enumeration value="Mesh"/>
+ <xs:enumeration value="MultiLineString"/>
+ <xs:enumeration value="Rotation"/>
+ <xs:enumeration value="String"/>
+ <xs:enumeration value="Vector"/>
+ <xs:enumeration value="Texture"/>
+ <xs:enumeration value="Texture3D"/>
+ <xs:enumeration value="TextureCube"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
+\endcode
+
+*/
diff --git a/doc/src/07-file-formats/4-effects.qdoc b/doc/src/07-file-formats/4-effects.qdoc
new file mode 100644
index 00000000..1b886d74
--- /dev/null
+++ b/doc/src/07-file-formats/4-effects.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\omit
+\title Presentation Effects hide : true
+\page file-formats-effects.html
+
+ \e{Content goes here}
+
+In the future we will be publishing the API for ...
+\endomit
+*/
diff --git a/doc/src/07-file-formats/formats-index.qdoc b/doc/src/07-file-formats/formats-index.qdoc
new file mode 100644
index 00000000..d8af41ad
--- /dev/null
+++ b/doc/src/07-file-formats/formats-index.qdoc
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title File Formats
+\group qt3dstudio-file-formats
+\noautolist
+
+\section1 Contents
+//! [toc]
+\list
+\omit
+TODO: The whole qdoc for uia needs to be rewritten.
+ \li \l {The .uia File Format}
+\endomit
+ \li \l {The .material Format}
+\endlist
+//! [toc]
+*/
diff --git a/doc/src/08-integrating/0-lua-modules.qdoc b/doc/src/08-integrating/0-lua-modules.qdoc
new file mode 100644
index 00000000..4a35cc8b
--- /dev/null
+++ b/doc/src/08-integrating/0-lua-modules.qdoc
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Lua Modules
+\page integrating-lua-modules.html
+\ingroup qt3dstudio-integrating
+
+\section1 Extending Qt 3D Studio
+
+The Qt 3D Studio Runtime can easily be integrated with existing
+hardware and software by means of modules. Modules are a standard
+feature of the Lua language that allow new C bindings to be added with a
+DLL or shared library.
+
+\image Workflow-Solid.png
+
+The diagram above shows multiple Lua Modules extending the capabilities
+of the Runtime scripting to allow access to low level calls controlling
+hardware such as music, navigation, and general CAN Bus communication.
+
+\section1 Binding Code to Lua
+
+Lua Bindings are a well-documented topic online. A nice reference for
+implementation can be found
+\l{http://lua-users.org/wiki/BindingCodeToLua}{on the Lua wiki}.
+Additionally, a simple sample of a CAN module that works with
+CarConnection behavior is provided with your installation of Qt 3D Studio
+at \c{INSTALL_DIRECTORY/Runtime/Plugins/Bindings/CAN/...}.
+
+To call functions in your module, place the \c{.dll} (Windows) or
+\c{.so} (Linux/Android) directly next to the Qt 3D Studio
+Viewer executable. At the top of a script where you would like to call
+your custom bindings, use the Lua \c{require} function.
+
+\badcode
+-- Load the CAN module and output any errors in the process
+require("CAN")
+\endcode
+
+The use of \c{require()} will produce helpful error strings if the
+module cannot be found. Once the system is in place, however it is often
+preferable to control the resulting errors. For this, you can use the
+built-in Lua function \c{pcall()}:
+
+\badcode
+-- Instead, one can use pcall to hide errors and control the program flow
+if not pcall( require, "CAN" ) then
+ output( "Could not locate CAN module." )
+end
+
+-- Call a function in our Lua binding
+if CAN then
+ self.catalog = CAN.getCatalog()
+end
+\endcode
+
+*/
diff --git a/doc/src/08-integrating/1-render-plugins.qdoc b/doc/src/08-integrating/1-render-plugins.qdoc
new file mode 100644
index 00000000..05788a7a
--- /dev/null
+++ b/doc/src/08-integrating/1-render-plugins.qdoc
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Render Plugins
+\page integrating-render-plugins.html
+\ingroup qt3dstudio-integrating
+
+Qt 3D Studio provides a mechanism for
+compositing an external OpenGL ES application plugin as a texture at
+runtime. This document describes how this is done.
+
+\section1 Requirements
+
+In general, the initialization and rendering portions of the plugin must
+be modified to be driven by the runtime.
+
+First, the plugin application needs to be converted into a dynamic
+library. The extension of the dynamic library should be \c{.dll}
+for Windows, and \c{.so} for Linux. (See further instructions in
+the \e{Usage} section below.)
+
+Second, the functions in the header file (\c{UICPluginDLL.h}) need
+to be implemented by the plugin.
+
+The following list is a description of these functions and what they
+need to do. The order the functions are listed here also represents the
+expected calling sequence of these functions.
+
+\section2 \c{long GetPluginType( )}
+
+This must return \c{EDLLTYPE\_RENDERABLE\_PLUGIN}.
+
+\section2 \c{void Initialize( const char* inArgs )}
+
+This function should do any initialization (data setup, geometry and
+texture uploads, etc.) required by the plugin. It will be called when
+the dynamic library is loaded during runtime startup.
+
+\section2 \c{void Uninitialize( )}
+
+This function should do any uninitialization (free memory, close files,
+etc) required by the plugin. It will be called when the viewer is
+exited.
+
+\section2 \c{void GetDesiredTextureSize( long* outWidth, out* outHeight, ETEXTUREFORMAT *outTextureFormat )}
+
+The plugin should set \c{outWidth} and \c{outHeight} to its
+desired rendering size, and set the texture format to one of:
+
+\list
+\li
+ \c{ETEXTUREFORMAT\_ANY}
+\li
+ \c{ETEXTUREFORMAT\_RGB565}
+\li
+ \c{ETEXTUREFORMAT\_BGR565}
+\li
+ \c{ETEXTUREFORMAT\_RGB888}
+\li
+ \c{ETEXTUREFORMAT\_BGR888}
+\endlist
+\section2 \c{void SetAllocatedRenderInfo( long inFBO, long inRBO, long inTex, ETEXTUREFORMAT inTextureFormat )}
+
+The runtime uses this function to send the framebuffer, renderbuffer and
+texture handles used for rendering. The plugin should store these and
+activate them when rendering. Note that the data within these handles
+are shared resources, and may be modified between calls to
+\c{Render( )}.
+
+\section2 \c{[Optional] void SetEGLInfo( void* inEGLdisplay, void* inEGLCurrentContext, void* inEGLSurface, void* inEGLConfig )}
+
+The runtime uses this function to send information about the current EGL
+environment. The plugin should store these parameters and use them in
+\c{EGLCreateContext} and \c{EGLMakeCurrent}.
+
+Implementing this function is necessary when using
+\c{EGLMakeCurrent} for state management.
+
+\section2 \c{void Render( long inHostWidth, long inHostHeight, long inDrawTime )}
+
+The runtime calls this whenever it requires a frame from the plugin. The
+plugin should render its results into the texture handle provided by
+\c{SetAllocatedRenderInfo}. The parameters, \c{inHostWidth}
+and \c{inHostHeight} represent the current dimensions of the host
+rectangle, and may be useful for clipping/scaling optimizations. The
+parameter \c{inDrawTime} represents the current frame time in
+milliseconds.
+
+\section1 State Management
+
+The plugin should manage its OpenGLES state properly so that it does not
+affect the runtime. There are two approaches that can be adopted.
+
+\list
+\li
+ In the first approach, the plugin creates its own EGLContext to
+ contain its state. It should switch to this context during
+ \c{Render()} and switch back to the runtime's context before
+ returning from \c{Render()}.
+\endlist
+Switching contexts is slow but might be favorable if the plugin spends a
+lot of time rendering or doing complex state changes.
+
+\list
+\li
+ The second approach is to share the OpenGL state between the runtime
+ and the plugin. The plugin is responsible for restoring state changes
+ it makes during \c{Render( )}. However, the shader program,
+ framebuffer and viewport settings will be restored by the runtime
+ automatically, as these are most likely to have changed. This approach
+ is faster than switching contexts and is probably suitable for simpler
+ applications that do not make many state changes or when maximum speed
+ is desired.
+\endlist
+\section1 Usage
+
+The procedure for using plugins is very similar to that used for Sub
+Presentations.
+
+After converting the plugin into a dynamic library, the
+\l{file-formats-uia.html}{\c{.uia} file} should be
+modified to specify the dynamic library as a
+\c{<renderplugin>} asset. The
+\c{src="..."} attribute should point to the dynamic library.
+For example:
+
+\badcode
+<application xmlns="http://nvidia.com/uicomposer">
+ <assets>
+ ...
+ <renderplugin id="plugin:mapviewer" src="scripts/mylib.so" args="whee" />
+ </assets>
+ ...
+</<application>
+\endcode
+
+Then, in Qt 3D Studio application for the presentation to display this
+plugin, either:
+
+\list
+\li
+ choose a Layer to display the plugin by setting the Sub-Presentation
+ property to the string \c{plugin:mapviewer} (the \c{id}
+ attribute of the asset), or
+\li
+ choose an image to display the composited texture by setting the
+ Sub-Presentation property on the image similarly.
+\endlist
+
+Finally, ensure that the dynamic library and the support files (if any)
+that are required are copied to your project folder.
+*/
diff --git a/doc/src/08-integrating/2-event-providers.qdoc b/doc/src/08-integrating/2-event-providers.qdoc
new file mode 100644
index 00000000..a1054556
--- /dev/null
+++ b/doc/src/08-integrating/2-event-providers.qdoc
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\omit
+\title Event Providers hide : true
+\page integrating-event-providers.html
+
+ \e{Content goes here}
+\endomit
+*/
diff --git a/doc/src/08-integrating/integrating-index.qdoc b/doc/src/08-integrating/integrating-index.qdoc
new file mode 100644
index 00000000..65060756
--- /dev/null
+++ b/doc/src/08-integrating/integrating-index.qdoc
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Integrating with Qt 3D Studio
+\group qt3dstudio-integrating
+
+\noautolist
+
+\section1 Contents
+//! [toc]
+\list
+ \li \l {Lua Modules}
+ \li \l {Render Plugins}
+\endlist
+//! [toc]
+
+*/
diff --git a/doc/src/10-best-practices/0-dynamic-keyframes.qdoc b/doc/src/10-best-practices/0-dynamic-keyframes.qdoc
new file mode 100644
index 00000000..3b3b57f8
--- /dev/null
+++ b/doc/src/10-best-practices/0-dynamic-keyframes.qdoc
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Dynamic Keyframes
+\page best-practices-dynamic-keyframes.html
+\ingroup qt3dstudio-best-practices
+
+Dynamic keyframes are a powerful feature
+that allow you to smoothly interpolate between different animated values
+on different slides. This can be used to simplify the creation of
+interactivity that would otherwise require scripting or heavy coding,
+such as user-interruptible animations.
+
+Dynamic keyframes smoothly animate an unlinked property between slides
+because no matter what the property value is for the object when it
+leaves one slide, a dynamic keyframe at the beginning of the next slide
+ensures that the object's animation will pick up exactly where it left
+off.
+
+To make an animation dynamic in Studio right-click on the animation
+track you want to be dynamic and select \"Make Animations Dynamic\" from
+the context menu. The first keyframe for each dynamic track turns green.
+When the slide is entered at runtime the value of this keyframe is taken
+from the value of the property immediately prior to entering the slide.
+
+*/
diff --git a/doc/src/10-best-practices/05-optimizingimages.qdoc b/doc/src/10-best-practices/05-optimizingimages.qdoc
new file mode 100644
index 00000000..a1e827d7
--- /dev/null
+++ b/doc/src/10-best-practices/05-optimizingimages.qdoc
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Optimizing Images
+\page best-practices-optimizingimages.html
+\ingroup qt3dstudio-best-practices
+
+ Optimizing the images in your presentation
+can substantially improve both the startup and runtime performance of
+your application, as well as the visual quality in certain situations.
+
+\section1 Motivation
+
+Unoptimized images can hurt the performance of your application in
+several ways:
+
+\list
+\li
+ A large image takes more memory bandwidth when being traversed as a
+ texture.
+\li
+ PNG and JPG compressed images must be decompressed before they can be
+ sent to the graphics system.
+\li
+ Poorly-sized images cause a performance hit and quality degradation on
+ startup.
+\li
+ Uncompressed images take longer to send to the graphics system, and
+ take up more graphics memory when there.
+\endlist
+Additionally, choosing an appropriate size for your images and using MIP
+maps \e{(see below)} can prevent aliasing issues if your image is
+going to be shown substantially smaller at some points.
+
+\section1 Reduce Image Dimensions
+
+\e{\b{Make your image small, but with dimensions that are
+multiple of 4.}}
+
+The first thing you need to do is resize your image to be \e{almost}
+as small as possible. The smaller your image, the faster it will upload
+to the graphics system, and less graphics bandwidth and memory it will
+use. Think about the largest size your image will ever be seen, and
+resize your image down to that size. If your carbon fiber will be tiling
+at about 32 pixels per repetition, don't save it at 1024×1024.
+
+However, note that both the horizontal and vertical dimensions of your
+image \b{must be a multiple of 4} to be stored on the graphics
+card. If you save an image at 107×29, the Qt 3D Studio Runtime
+will asymmetrically scale it up to 108×32 before sending it to the
+graphics card. This smears your image slightly, and also wastes
+performance while the image is resized.
+
+\e{If you are using MIP maps, there are further constraints on image
+dimensions; see below.}
+
+\section1 Choose a File Format
+
+\e{\b{Prefer DDS - with the appropriate encoding - in almost all
+cases.}}
+
+Qt 3D Studio supports three main image file formats: JPG, PNG,
+and DDS. You can search the Internet for the pros and cons of JPG versus
+PNG, when to choose which. However, the only advantages that they have
+over DDS is:
+
+\list 1
+\li
+ JPG and PNG are well-supported in most image applications and external
+ systems; DDS is not.
+\li
+ JPG and PNG will usually result in smaller image file sizes \b{on
+ disk} compared with DDS.
+\endlist
+In comparison, DDS offers these benefits:
+
+\list 1
+\li
+ \b{DDS files load faster.} DDS files can be loaded directly into
+ the graphics system without decompressing them first.
+\li
+ \b{Most DDS files render faster.} Almost all DDS encoding schemes
+ use less memory \b{on the graphics card}, making them faster to
+ sample as textures.
+\li
+ \b{DDS files can render even faster, with better visual quality,
+ at small sizes.} DDS files can encode MIP maps (pre-calculated
+ lower-resolution images to use at reduced sizes). These smoothly
+ cross-fade based on image size using trilinear interpolation.
+\endlist
+\section1 Saving as DDS
+
+The easiest way to create a DDS image (for most artists) is to use
+\l{https://developer.nvidia.com/nvidia-texture-tools-adobe-photoshop}{NVIDIA's
+Texture Tools for Photoshop}. Once installed, the standard
+\c{Save As...} dialog has an option to save an image as a
+\c{.dds} file format. You will need to ensure that the dimensions
+of your image are multiples of 4 for the dialog to be used.
+
+After you specify the file name you are presented with a
+somewhat-daunting dialog that provides a large number of options for
+saving the image:
+
+\image DDS-Dialog.png
+
+ The Save As... DDS
+dialog
+
+The most important settings are the drop-down list at the top used to
+select the DDS encoding, and the MIP map section.
+
+\section2 Selecting a DDS Encoding
+
+The encoding drop-down list has 30 entries filled with what looks at
+first like gibberish. Only eight of the encodings are relevant to Qt 3D Studio;
+the irrelevant ones have been grayed out in this picture:
+
+\image DDS-Formats.png
+
+ DDS Encodings Relevant to
+Qt 3D Studio
+
+You should pick the encoding with the least number of bits per pixel
+(bpp) that meets your visual needs:
+
+\list
+\li
+ \b{DXT1} - Applies a lossy compression algorithm, and does not
+ preserve any alpha.
+\li
+ \b{DXT1a} - Similar to DXT1, but also preserves 2 shades of
+ alpha (fully transparent or fully opaque).
+\li
+ \b{DXT3} - Similar to DXT1, but also preserves 16 explicit
+ shades of alpha.
+\li
+ \b{DXT5} - Similar to DXT3, but smoothly transitions the alpha.
+\li
+ \b{alpha} - Lossless 256 shades of alpha with no RGB. Useful
+ for an opacity map.
+\list
+\li
+ \e{If used as a diffuse map, the color channels are all implicitly
+ black.}
+\endlist
+\li
+ \b{luminance} - Lossless 256 shades of grey with no alpha. You
+ may use the Diffuse Color of a Standard Material to tint the result.
+\li
+ \b{alpha/luminance} - Combining the two previous results
+ encodings (at twice the storage space).
+\li
+ \b{8.8.8.8 ARGB} - Lossless RGB and alpha. Try to use DXT5
+ before you resort to this 4-times-larger encoding.
+\list
+\li
+ \e{Though the largest of all DDS encodings, this uses the same
+ amount of graphics memory and bandwidth as a PNG, yet it is still
+ faster to upload to the graphics system because it does not need to be
+ decompressed before uploading.}
+\endlist
+\endlist
+\section2 Using MIP Maps
+
+\e{\b{Use MIP maps when your image may be seen smaller than the
+original size, including portions in perspective.}}
+
+Enabling MIP maps creates many smaller copies of the image at an
+additional 1/3 memory usage. Each mipmap is half the dimensions of the
+one preceding it, downsized in Photoshop with good image resampling. The
+result speeds up renderin - t the appropriate times the graphics card
+will use the smaller image for texture lookup - nd also reduces
+aliasing artifacts such as moiré effects or
+\l{best-practices-antialiasing.html#texture-aliasing}{texture subsampling}.
+
+Select the \"Generate MIP maps\" radio button to cause your DDS to be
+saved with them. Use the \"2D Preview\" button to see them. Use the
+\"Sharpening...\" button to apply simple effects (including
+sharpening or blurring) to separate mipmap levels.
+
+On the other hand, if you do not need MIP maps for your image, select
+the \"No MIP maps\" radio button to save an extra 1/3 memory for your
+image.
+
+Note that MIP maps require specific image dimensions to work correctly
+at all levels, depending on which encoding is used:
+
+\list
+\li
+ \b{DXT*} - all DXT encodings require that the width and height of
+ your image are both some power of 2, e.g. 32, 64, 128, 256, etc. if
+ you wish to use MIP maps.
+\li
+ \b{alpha/luminance} - The alpha, luminance, and alpha/luminance
+ encodings require that the width be a power of 2 for MIP maps to work,
+ but the height may be a multiple of 4.
+\li
+ \b{8.8.8.8 ARGB} - This encoding requires only that your image
+ dimensions be multiples of 4 to work with MIP maps.
+\endlist
+\section3 MIP Maps and Image Dimensions
+
+Just as the original image needs to have dimensions that are
+independently some multiple of 4, so each mipmap level that you want to
+display must also be a multiple of 4. If it is not, you will see
+rendering artifacts as the mipmap level is displayed.
+
+For example, if you save an image that is 132×44, the image will render
+just fine at its normal size. The first mipmap, however, will be created
+at 66×22; as these values are not integer multiples of 4, the image will
+look incorrect at smaller sizes.
+
+So, if you're going to use MIP maps for your image, your image
+dimensions must be a multiple of 4×(2×\c{number\_of\_mip\_levels}).
+If you ensure that your MIP-mapped image dimensions are multiples of 32
+then the first 3 mipmaps will work correctly, allowing your image to
+shrink to 1/8 of its original size efficiently and attractively.
+
+\section2 Saving Alpha Channels
+
+Most of the time when dealing with images with semi-transparent regions
+it is easier to use Photoshop's transparent layers when editing an
+image. If you choose a DDS encoding that supports alpha, the transparent
+regions of your layers will be properly used for the alpha information.
+
+However, in certain cases you need to control the RGB values of fully
+transparent pixels. Specifically, you can see visual artifacts if:
+
+\list
+\li
+ any portion of your image will ever be seen at a size larger than
+ saved, and
+\li
+ you have fully transparent pixels in your image next to rather opaque
+ pixels
+\endlist
+In this case the texture interpolation between a fully-transparent pixel
+and its neighboring somewhat-opaque pixel will blend the RGB values
+between the two. If you use Photoshop's transparent layers, the RGB
+values for certain transparent pixels will be saved as white, and you
+will thus see white fringing at the edges of your transparent regions.
+
+For such cases, instead of creating a semi-transparent layer in
+Photoshop, create a layer will no transparency at all, setting the RGB
+value for every pixel you care about. Then, save the alpha information
+in a fourth Channel (in the Channels palette). When you choose \"Save
+As...\" from Photoshop, check the \"Alpha Channels\" checkbox. The
+information from your fourth channel will be used for the DDS alpha.
+
+\e{Regardless of how you save the alpha information, if you re-open
+an DDS with alpha in Photoshop the alpha information will always be
+displayed in a fourth channel.}
+
+*/
diff --git a/doc/src/10-best-practices/10-antialiasing.qdoc b/doc/src/10-best-practices/10-antialiasing.qdoc
new file mode 100644
index 00000000..fa9251bc
--- /dev/null
+++ b/doc/src/10-best-practices/10-antialiasing.qdoc
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Anti-Aliasing
+\page best-practices-antialiasing.html
+\ingroup qt3dstudio-best-practices
+
+Qt 3D Studio has multiple ways to
+combat aliasing (the \"jaggies\") prevalent in real-time rendering of 3D
+models. Each technique offers its own benefits and limitations. Multiple
+techniques may be combined, albeit incurring the performance cost of
+each.
+
+\section1 Causes of Aliasing
+
+Before covering the details of the different techniques and
+technologies, we illustrate the three main causes of aliasing. Following
+those are the details on each of the possible solutions. Understanding
+which technology best targets your problems will help you to balance
+visual quality with sufficient rendering speed.
+
+\section2 Geometry Aliasing
+
+By default, all geometry is rendered one on-screen pixel at a time. As
+seen below at left, this can leave harsh edges that may be easily
+noticeable in high-contrast cases (most noticeably in this
+black-and-white case).
+
+\raw HTML
+<a href=images/AA-GeometryAliasing.png>
+\endraw
+\image AA-GeometryAliasing.png
+\raw HTML
+</a>
+\endraw Effective techniques for reducing aliasing
+for geometry (click to view full size).
+
+The most correct fix for this is to use
+\l{multisample-aa}{Multisample Anti-Aliasing}, as this gathers more
+geometric detail only as needed. Using \l{temporal-aa}{Temporal AA}
+or \l{progressive-aa}{Progressive AA} can also mitigate the issue
+in a correct manner.
+
+Using the \l{fxaa}{FXAA} or \l{smaa}{SMAA} image effects will
+smooth the edges, but may misinterpret fine details. For example, notice
+how the corners of the lower square are not quite correct, or how the
+sides of the circle are slightly squashed.
+
+Finally, in certain limited cases you may be able to use a
+\l{silhouette-opacity-maps}{silhouette opacity map} to smooth the
+edges of selected geometry.
+
+\section2 Texture Aliasing
+
+When a texture is sub-sample - hen fewer pixels are displayed than are
+present in the origina - ou may see undesirable artifacts based on
+which pixels are chosen. This effect is worsened when the model is
+moving, as very different pixels may be chosen at different times. In
+the image below, notice how the line between E3 and F3 is missing,
+strongly present between G3 and H3, then gone for the next 5 columns,
+and so on.
+
+\raw HTML
+<a href=images/AA-TextureAliasing.png>
+\endraw
+\image AA-TextureAliasing.png
+\raw HTML
+</a>
+\endraw Effective techniques for reducing aliasing
+for textures (click to view full size).
+
+The simplest (and arguably the best) fix for this problem is to use
+\l{mipmaps}{mipmapping in the image texture} itself. Alternative
+fixes include using either \l{temporal-aa}{Temporal AA} or
+\l{progressive-aa}{Progressive AA} to gather more information from
+the texture.
+
+Using \l{multisample-aa}{Multisample Anti-Aliasing} will \e{not}
+fix this problem. Using the \l{fxaa}{FXAA} or \l{smaa}{SMAA}
+image effects will remove some ugly artifacts, but do so in a way that
+is obviously not correct when the texture is predictable by humans.
+
+\raw HTML
+<a href=images/AA-TextureAliasing2.png>
+\endraw
+\image AA-TextureAliasing2.png
+\raw HTML
+</a>
+\endraw Image effects do not work well when
+textures are predictable (click to view full size).
+
+\target reflection-aliasing
+\section2 Reflection
+Aliasing
+
+Similar to Texture Aliasing, a material reflecting the environment will
+sub-sample the image. In some case - s seen in the lines at the bottom
+of the reflection at lef - t becomes obvious when fine details are
+being skipped.
+
+\raw HTML
+<a href=images/AA-ReflectionAliasing.png>
+\endraw
+\image AA-ReflectionAliasing.png
+\raw HTML
+</a>
+\endraw Effective techniques for reducing aliasing
+for reflections (click to view full size).
+
+The most correct solutions in this case are using
+\l{temporal-aa}{Temporal AA} or \l{progressive-aa}{Progressive AA} to find the extra information. Using the \l{fxaa}{FXAA} or
+\l{smaa}{SMAA} image effects can hide obvious glittering problems
+by blurring them out, but this may be noticeably incorrect when the
+environment is predictable.
+
+A simple alternative solution that may be acceptable is to make the
+material less glossy, more rough. In this case lower-resolution mipmaps
+of the environment are automatically used, blending the sharp details
+together.
+
+\section1 Anti-Aliasing Technologies
+
+Aliasing is caused when there is more `information' present in the
+original than we can represent in the pixels on screen. Anti-aliasing
+technologies fall into three categories:
+
+\list
+\li
+ ways to find real additional information for a single pixel and
+ represent them all at the same
+\li
+ image effects that attempt to find where things look bad and sweep the
+ problems under the carpet
+\li
+ cheats employed by artists that attempt to workaround the limitations
+\endlist
+\section2 Technologies that Find Additional Information
+
+\target multisample-aa
+\section3 Multisample AA
+
+Multisample AA (MSAA) operates on an entire layer. The edges of geometry
+are super-sampled, resulting in smoother silhouettes. This technique has
+no effect on the materials inside geometry, however.
+
+\list
+\li
+ \b{To use it}: select a Layer in the Timeline palette, and then
+ select either 2x or 4x for the Multisample AA property in the
+ Inspector palette.
+\li
+ \b{Pros}: good results on geometry silhouettes, where aliasing is
+ often most noticeable; works with fast animation without issue.
+\li
+ \b{Cons}: can be expensive to use; does not help with texture or
+ reflection issues.
+\endlist
+\target temporal-aa
+\section3 Temporal AA
+
+Temporal AA operates on an entire layer. The camera is jiggled
+\e{very slightly} between frames, and the result of each new frame is
+blended with the previous frame.
+
+\list
+\li
+ \b{To use it}: select a Layer in the Timeline palette, and then
+ turn on the Temporal AA checkbox in the Inspector palette.
+\li
+ \b{Pros}: due to the jiggling camera it finds real details that
+ were otherwise lost; low impact on performance.
+\li
+ \b{Cons}: fast-moving objects cause one-frame ghosting.
+\endlist
+\target progressive-aa
+\section3 Progressive AA
+
+Progressive AA (PAA) operates on an entire layer. When all content of
+the layer has stopped moving, the camera is jiggled \e{very slightly}
+between frames, and the result of each new frame is blended with the
+previous frames. The more frames you accumulate, the better looking the
+result.
+
+\list
+\li
+ \b{To use it}: select a Layer in the Timeline palette, and then
+ select 2x, 4x, or 8x for the Progressive AA property in the Inspector
+ palette.
+\li
+ \b{Pros}: provides wonderful detail on static images with no
+ performance cost.
+\li
+ \b{Cons}: does not take effect if any visual changes are
+ occurring; 8x PAA takes one eighth of a secon - o finish rendering
+ (at 60fps), which may be noticeable.
+\endlist
+\target mipmaps
+\section3 Mipmaps
+
+Mipmapping stores along with a texture some pre-calculated lower
+resolution versions of that texture. Whenever the texture is being
+displayed at a smaller size, the rendering system automatically uses
+these low-resolution images (which combine many details into a single
+pixel) blending them into the result as needed.
+
+\list
+\li
+ \b{To use it}: use NVIDIA's free Texture Tools plugin for
+ Photoshop to save your image as a DDS with \"Generate MIP maps\"
+ checked in the interface. You may need to resize your image so that
+ its dimensions are powers of 2, e.g. 32, 64, 128, 256, etc. For more
+ details, see the section
+ \e{\l{best-practices-optimizingimages.html#using-mip-maps}{Optimizing Images/Saving as DDS/Using MIP Maps}}.
+\li
+ \b{Pros}: very low performance impact; greatly improves image
+ quality for textures; encourages you to use DDS, which load and render
+ faster than PNGs.
+\li
+ \b{Cons}: requires using external tools to optimize your images;
+ uses 33\% more graphics memory than the same image without mipmaps.
+\endlist
+\section3 Supersample AA
+
+Supersample AA (SSAA) operates on an entire layer, or even multiple
+layers. It is not mentioned or compared above because the performance
+penalty can be severe, and because it requires additional work from the
+artist. This technique should be used as a last resort.
+
+\list
+\li
+ \b{To use it}: save a layer as its own sub-presentation. Specify
+ the size of this presentation to be larger then the size you want to
+ display it at (roughly 1.4 times larger in each dimension seems to
+ provide good results). Add this presentation to your application (in
+ the \c{.uia} file). Where you wish to display the presentation
+ create a Rectangle with a diffuse map on it. (The source and size of
+ the image you select do not matter.) Select the Diffuse Map image in
+ the image palette, and select your presentation as the
+ Sub-Presentation for that image. The presentation will be rendered at
+ the size you specify, and then used as an image map on your Rectangle.
+ Bilinear interpolation will be used when sampling the texture,
+ providing a form of supersample anti-aliasing in the final result.
+\li
+ \b{Pros}: provides full-scene anti-aliasing with no limitations
+ on animation.
+\li
+ \b{Cons}: can severely degrade performance when your presentation
+ is already limited by the fill-rate of the graphics system (this is
+ often the case).
+\endlist
+\section2 Image Effects
+
+\target fxaa
+\section3 FXAA
+
+Fast Approximate Anti-Alising (FXAA) is an effect that can be applied to
+an entire layer. It looks for pixels at a similar distance from the
+camera that are different, and smoothes the edges.
+
+\list
+\li
+ \b{To use it}: copy the FXAA effect to your project by opening
+ the Effect Library at the bottom of the Project palette and draggin
+ the \c{FXAA.effect} file into your Project palette. Then, drag
+ the FXAA effect from the Project palette onto the Layer in the
+ Timeline that you wish it to apply to. There are no configurable
+ parameters for this effect in the Inspector palette.
+\li
+ \b{Pros}: relatively inexpensive, can clean up a lot of common
+ problems so that they are not distracting.
+\li
+ \b{Cons}: because it is based on the already-aliased image, the
+ fixes that it makes are usually blurring/hiding extra information
+ instead of adding additional information (see the corner between
+ \"G4\" and \"H5\" in the Texture Anti-Aliasing example); it can
+ negatively effect fine text details (see the \"small text\" on the
+ Geometry Anti-Aliasing example).
+\endlist
+\target smaa
+\section3 SMAA
+
+Enhanced Subpixel Morphological Antialiasing (SMAA) is an effect that
+can be applied to an entire layer. It attempts to be smarter than FXAA
+about how it cleans up the image.
+
+\list
+\li
+ \b{To use it}: copy the SMAA effect to your project by opening
+ the Effect Library at the bottom of the Project palette and draggin
+ the \c{SMAA.effect} file into your Project palette. Then, drag
+ the SMAA effect from the Project palette onto the Layer in the
+ Timeline that you wish it to apply to. There are no configurable
+ parameters for this effect in the Inspector palette.
+\li
+ \b{Pros}: can clean up a lot of common problems so that they are
+ not distracting; does not add as many `incorrect' details as FXAA.
+\li
+ \b{Cons}: more expensive than FXAA; as an image-based effect it
+ cannot add missing details reliably.
+\endlist
+\section2 Artist-Employed Cheats
+
+\target silhouette-opacity-maps
+\section3 Silhouette Opacity Maps
+
+When your model has a consistent silhouette you can apply an opacity map
+that makes the outer edge of the geometry transparent. Using a gradient
+for the opacity will let the edge of the object smoothly disappear.
+However, even if your opacity map transitions directly from fully-opaque
+to fully-transparent over the space of one pixel - as is the case shown
+in the geometry example above - the result will provide anti-aliased
+edges. This is because image maps, including opacity maps, use bilinear
+interpolation.
+
+\list
+\li
+ \b{To use it}: construct an opacity map that makes the outer
+ silhouette of your geometry transparent, and apply it to either the
+ Diffuse Map or Opacity Map channel for the material.
+\li
+ \b{Pros}: can show softer transitions than normal AA; can be
+ applied per model instead of per-layer.
+\li
+ \b{Cons}: cannot be used if the silhouette of the object will
+ ever change; multiple overlapping models that employ transparency
+ consume fill rate performance, which is often at a premium.
+\endlist
+\section3 Modifying Materials or Geometry
+
+As demonstrated in the picture for
+\l{reflection-aliasing}{Reflection Aliasing} above, sometimes the
+simplest fix for problems is to change the artwork. If you are getting
+distracting specular glints on the corner of your model, ask yourself:
+Can I make the material softer? Can I modify the geometry to smooth or
+change the reflection angle? Can I edit the environment map to reduce
+sharp transitions?
+
+There is no one-size-fits all solution to certain problems. While it is
+our aim to produce a product that consistently produces pleasing,
+realistic real-time results, being open to occasionally modifying your
+artistic vision is sometimes the most pragmatic way to get the best
+possible renderings.
+
+*/
diff --git a/doc/src/10-best-practices/20-creating-optimized-presentations.qdoc b/doc/src/10-best-practices/20-creating-optimized-presentations.qdoc
new file mode 100644
index 00000000..2349e193
--- /dev/null
+++ b/doc/src/10-best-practices/20-creating-optimized-presentations.qdoc
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Creating Optimized Presentations
+\page best-practices-creating-optimized-presentations.html
+\ingroup qt3dstudio-best-practices
+
+The Qt 3D Studio application authoring environment is very powerful
+and open ended, allowing for basically endless design possibilities.
+Decisions that you make about how you author your content can have
+dramatic effects on the runtime performance of your UI. This document
+presents a few rules of thumb to keep in mind that will help you create
+presentations that perform well.
+
+\section1 Scene Graph
+
+The scene graph is the hierarchy of nodes that describe the scene to be
+rendered.
+
+Inside Studio, the scene graph is represented by the tree-like view in
+the timeline. The scene graph is managed in realtime by the Qt 3D Studio
+Runtime, so by minimizing the size of the scene graph in Studio,
+you can minimize the work done by the Runtime.
+
+In Qt 3D Studio this is the principal performance rule of thumb.
+Likely the single biggest impact you can have in terms of optimization
+when creating presentations with Studio is to keep the scene graph
+small. Although the data exported for runtime is aggressively optimized,
+it is still a good idea to avoid using unnecessary groups or layers as
+organizational tools, and to generally avoid complex hierarchy when
+possible.
+
+If a presentation is becoming too large, consider whether it could be
+split into smaller logical units as separate presentations.
+
+\section1 Components
+
+Components in Studio can be thought of as scenes within the Scene.
+
+Components, like a full presentation scene, have a timeline and their
+own set of slides (including a Master Slide). Each component's timeline
+runs independently of the rest of the scene, allowing for
+time-independent animations. Additionally, a component's separate set of
+slides (states) allow common functionality - for example that of a
+button, to be factored out and reused across presentations.
+
+While these are very powerful concepts, it is important to understand
+the costs associated with using components.
+
+\list
+\li
+ Adding slides to your components (or the Scene for that matter) will
+ increase the file size and runtime memory requirements of your
+ presentation. There is logic information stored to represent the state
+ of each slide of each component, and while there are several
+ optimizations in place to minimize the amount of data that needs to be
+ stored, adding slides is still not \"free\".
+\li
+ For each frame there is a small fixed cost associated with translating
+ \"global\" time, which is generated by the Runtime outside of the
+ presentation, into local time for each component. This translation has
+ to occur, as a component might have a shorter (or longer) overall time
+ bar than the Scene, and may otherwise be looping, ping-ponging or even
+ stopped.
+\li
+ Including components in your presentation also increases the
+ complexity of your scene graph, and complex scene graphs deteriorate
+ performance. Therefore, components should only be used when necessary,
+ such as when you're leveraging their reusability or their time context
+ (slides and independent timeline.)
+\endlist
+
+\omit
+TODO: Rewrite or remove
+\section1 Behaviors
+
+Behaviors are script code that affect the presentation at runtime.
+
+Here are a few key optimization and performance rules of thumb to keep
+in mind while writing scripts.
+
+\list
+\li
+ Less script code is better.
+\li
+ The fastest code is no code at all. Excessively long scripts are
+ typically also more difficult to debug, so there is no shortage of
+ motivation to keep scripts short and sweet.
+\li
+ Caching values can improve performance.
+\li
+ Reading values from a Lua table is going to be faster than getting
+ them by calling \c{getAttribute()} to pull the value from the
+ element.
+\li
+ If you're going to be using a value often (an attribute value, element
+ reference, etc), consider storing it in a Lua table rather than
+ calling a function to look it up over and over again.
+\li
+ Use \c{onUpdate} judiciously.
+\li
+ A behavior's \c{onUpdate} handler, which can be used to execute
+ code every frame, is a very powerful concept that enables a lot of the
+ neat things behaviors can do in the Runtime.
+\li
+ By its very nature, each behavior instance with an \c{onUpdate}
+ handler will cause (at least) one function call every frame, and this
+ can add up. Therefore, it is important to keep the number of
+ \c{onUpdate} handlers to a minimum, and to ensure that each
+ \c{onUpdate} handler is doing as little as possible. Consider an
+ early-outing if that can minimize the code run each frame.
+\li
+ If an \c{onUpdate} handler is being used to poll something,
+ consider whether it would be possible to use an event-driven approach
+ instead, or if there are several instances of the behavior with
+ \c{onUpdate} consider having some kind of \"manager\" behavior
+ that would have a single \c{onUpdate} that would encompass the
+ functionality of each of the behavior instance's \c{onUpdate}.
+\endlist
+\endomit
+
+\section1 Asset Complexity
+
+It is entirely possible for the performance of your UI not to be bound
+by some calculation the Qt 3D Studio Runtime is doing, but
+instead to be bottlenecked at render time. Needless optimization is a
+waste of time, so there is no substitute for profiling to find out what
+the bottleneck is.
+
+With that said, one possible point of optimization can be to simplify
+your assets.
+
+\list
+\li
+ \b{3D models}
+\list
+\li
+ Using the minimum number of triangles or vertices to achieve the
+ desired look is always a good idea.
+\li
+ Hierarchy inside the content creation application is translated into hierarchy
+ inside Studio. This can lead to complex scene graphs and therefore
+ lower performance. It may be worthwhile to see if your 3D assets can
+ be merged into larger meshes, assuming that the hierarchy is not
+ necessary for placement or animation.
+\endlist
+\li
+ \b{Images}
+\list
+\li
+ Plainly, smaller images require less memory and render faster.
+\endlist
+\endlist
+\section1 File Size
+
+Not surprisingly, the sizes of the various files related to Qt 3D Studio
+increase as presentation complexity increases. Titanic .uip files
+can be painful to edit in Studio, are slower to export and load and
+typically use more memory at runtime.
+
+In general it is a good idea to try and keep file sizes down.
+
+We recommend splitting different logical units of your UI (screens,
+sections) into separate presentations (.uip files). Doing this can
+result in smaller files as well as the possibility of distributing the
+work of creating the presentations among multiple artists. File save
+times in Studio are also directly related to presentation complexity, so
+splitting your UI into multiple \c{.uip} files can result in a
+better workflow and faster iterations (change/test cycles) of your UI.
+
+*/
diff --git a/doc/src/10-best-practices/30-using-sub-presentations.qdoc b/doc/src/10-best-practices/30-using-sub-presentations.qdoc
new file mode 100644
index 00000000..5ecc97e5
--- /dev/null
+++ b/doc/src/10-best-practices/30-using-sub-presentations.qdoc
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Using Sub-Presentations
+\page best-practices-using-sub-presentations.html
+\ingroup qt3dstudio-best-practices
+
+\section1 Introduction
+
+Sub-Presentations is a feature which allows one presentation to be
+embedded in another.
+
+The main benefit of doing this is that you can author different parts of
+a large presentation as separate smaller presentations. This can help
+control complexity in single \c{.uip} files, as well as allow
+different parts of a presentation to be authored separately and
+simultaneously.
+
+Sub-presentations execute independently, albeit inside the same Runtime
+process as the initial presentation. The rendered frame from each
+sub-presentation is essentially used as a texture on a rectangle in the
+main presentation. This allows control over where and how each
+sub-presentation is composited into the final frame.
+
+\section1 Using Sub-Presentations
+
+There are two different ways to display a sub-presentation; on a separate layer
+or on an image element on an existing layer.
+
+\target sub-presentation layer
+\section2 Sub-presentation on a Layer
+
+\list 1
+\li
+ From the file menu, select \uicontrol{Edit} > \uicontrol{Sub-presentations}.
+\li
+ Click \uicontrol{Browse}, browse to the project folder of your desired project and select the
+ \c{.uia} file.
+ \image subpresentation-dialog.png
+\li
+ Enter desired name for the sub-presentation in the \uicontrol{Name} field. In case you have
+ several sub-presentations in your project the names need to be unique.
+\li
+ Select the layer you want to use for the sub-presentation in the \e{timeline palette}.
+ Then, in the inspector palette, select the desired sub-presentation in the
+ \uicontrol{Sub-Presentation} field. All sub-presentations added to the project will be listed
+ here.
+ \image layer-sub-presentation.png
+\endlist
+
+\section2 Sub-presentation on an Image Element
+\list 1
+\li
+ Follow step 1 to 3 in the \l {sub-presentation layer}{Sub-presentation on a layer}
+ section above.
+\li
+ Add a basic object to your layer, preferably a rectangle.
+\li
+ Add any image as a diffuse map for the material of the object by first selecting the material
+ of the object in the \e{timeline palette} and then selecting \uicontrol{Diffuse Map} in the
+ \e{inspector palette}.
+ \image add-diffuse-map.png
+\li
+ Select the \e{diffuse map} in the \e{timeline palette} and then select the desired
+ sub-presentation in the \uicontrol{Sub-Presentation} field. All sub-presentations added in
+ the \c{.uia} will be listed here.
+ \image add-diffuse-map-subpresentation.png
+\endlist
+
+*/
diff --git a/doc/src/10-best-practices/35-scalemodes.qdoc b/doc/src/10-best-practices/35-scalemodes.qdoc
new file mode 100644
index 00000000..69f19c6f
--- /dev/null
+++ b/doc/src/10-best-practices/35-scalemodes.qdoc
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Using Scale Modes
+\page best-practices-scalemodes.html
+\ingroup qt3dstudio-best-practices
+
+Qt 3D Studio allows you to use the same application on different
+resolutions and aspect ratios and control how portions of the content
+adjust to the new sizing. There are four related settings that control
+this:
+
+\list
+\li
+ The \e{size set for the presentation} controls how large the application renders.
+ Note that the render size might also be effected by the \e{Application Scale Mode} setting.
+\li
+ The \e{Application Scale Mode} controls how much of your viewport is
+ covered by the application.
+\li
+ \e{Layer positioning and sizing} controls how layers align and the size of them.
+\li
+ \e{Camera scaling and anchoring} controls how the content adjusts
+ (panning and scaling) as the layer size changes.
+\endlist
+
+\target presentation-size
+\section1 Presentation Size
+
+You can set the presentation size by following the steps below:
+
+\list 1
+ \li From the file menu select \uicontrol{Edit} >
+ \uicontrol{Presentation Settings}
+ \li Enter the desired width and height for the presentation. When editing
+ presentation size you can retain proportions by checking the
+ \uicontrol{Constrain Proportions} check box.
+ \image presentation-size.png
+\endlist
+
+The effect of setting the size of a presentation in Studio
+depends on how the presentation is used within the application:
+
+\list
+\li
+ If the presentation is the \e{main presentation} and the
+ \e{\l{Application Scale Mode}} is set to
+ \c{center} (the default value), then the size
+ of the presentation is the size of the application. No matter how big
+ your viewport or the resolution of your screen are, the presentation size
+ you specify will be the final size.
+\li
+ If the presentation is used as a
+ \l{best-practices-using-sub-presentations.html}{sub-presentation}
+ via an image element, the size you specify is the
+ render size for the presentation. The presentation is rendered at this
+ size and then displayed as an image on the material.
+\list
+\li
+ \note If your presentation size is larger than the final display size
+ of your image, you will spend performance rendering results that only
+ lightly affect the end result. You will get a form of AA on the
+ sub-presentation via the linear interpolation of the final image, but
+ at a non-trivial cost to the graphics performance.
+\endlist
+\li
+ If the presentation is used as a
+ \l{best-practices-using-sub-presentations.html}{sub-presentation}
+ via a layer, the presentation is always
+ rendered at the size of the layer. If the layer size differs from the
+ presentation size, the \l{camera-scaling-and-anchoring}{camera scaling and anchoring properties}
+ for the layers within the presentation control how
+ the content for those layers reacts to the size changes.
+\endlist
+
+\target application-scale-mode
+\section1 Application Scale Mode
+
+The \e{Scale Mode} attribute specifies how large the initial presentation is rendered.
+
+\list
+\li
+ \c{Center} - the presentation is rendered at the size
+ specified in Studio. Additional content is cropped, additional space
+ is letterboxed. This setting is the default setting.
+\li
+ \c{Fit} - the aspect ratio of the presentation is
+ preserved, the presentation will scale to fit the viewport, letterboxing as needed.
+\li
+ \c{Fill} - the presentation is always rendered to
+ fill the viewport both horizontally and vertically, adjusting
+ ascpect ratio if needed.
+\endlist
+
+\image Runtime-ApplicationScaleMode.png
+
+\note This setting only describes how much space to fill, but not
+how the content adjusts to fill these dimensions. The results
+depend on how the layers of the presentation adjust with changing
+presentation render size, and how cameras within those layers choose
+which content to display. Read on for these details.
+
+When you view your presentation in the Viewer you
+can change the \e{Scale Mode} either by using shortcut \c{Ctrl + Shift + S} to toggle
+\e{Scale Mode} or by selecting \uicontrol{View} > \uicontrol{Scale Mode} from
+the file menu.
+\image view-scale-mode.png
+
+\target layer-position-and-size
+\section1 Layer Position and Size
+
+A \e{layer} on a presentation is a screen-aligned rectangle into which
+to draw content. By default each layer is set to fill the entire
+presentation. However, you can set layers to fill only a particular
+portion of the presentation. You may wish to do this for the visual
+result (for example if you want a navigation bar that is always 100 pixels high
+regardless of the presentation size, anchored at the bottom of the
+screen.). However, even if you don't need the visual effect of
+cropping, it's a good idea to crop your layers to only minimal content
+needing to be shown, so that no graphics processing power is wasted
+rendering empty space.
+
+Sizing and positioning of layers is done by adjusting the \uicontrol{Horizontal Fields}
+and \uicontrol{Vertical Fields} properties of the layers. You adjust these
+properties in the \e{inspector palette} once you have selected the desired layer in the
+\e{timeline palette}.
+
+\image layer-position-properties.png
+
+\list
+ \li \uicontrol{Horizontal Fields} - Choose which two fields of \uicontrol{Left},
+ \uicontrol{Width}, and \uicontrol{Right} are used to control the horizontal placement
+ and sizing of the layer within the presentation. Each of these values can be set either
+ in pixels or as a percentage of the presentation width.
+ \li \uicontrol{Left} - The distance between the left edge of the presentation
+ and the left edge of the layer.
+ \li \uicontrol{Width} - The width of the layer, either in pixels or as a percentage
+ of the presentation width.
+ \li \uicontrol{Right} - The distance between the right edge of the presentation and
+ the right edge of the layer.
+ \li \uicontrol{Vertical Fields} - Choose which two fields of \uicontrol{Top},
+ \uicontrol{Height}, and \uicontrol{Bottom}
+ are used to control the vertical placement and sizing of the layer within the presentation.
+ Each of these values can be set either in pixels or as a
+ percentage of the presentation width.
+ \li \uicontrol{Top} - The distance between the top edge of the presentation and the top edge
+ of the layer.
+ \li \uicontrol{Height} - The height of the layer, either in pixels or as a percentage
+ of the presentation height.
+ \li \uicontrol{Bottom} - The distance between the bottom edge of the presentation
+ and the bottom edge of the layer.
+\endlist
+
+\image Runtime-LayerSizing.png
+
+\target camera-scaling-and-anchoring
+\section1 Camera Scaling and Anchoring
+
+Whenever a layer is not the same size as the \l{presentation-size} {presentation size},
+and the layer is displaying its own content (rendered from a camera in the layer instead
+of showing a \l{best-practices-using-sub-presentations.html}{sub-presentation}), two
+properties of its camera control how the content adjusts to fill the new size:
+
+\list
+\li
+ \uicontrol{Scale Mode}
+ \list
+ \li \uicontrol{Same Size} - render the content seen by the camera at the same
+ size (same number of pixels) as seen when the layer size is the same
+ as the presentation sized authored in Studio. Layers smaller than the
+ original presentation size will cause content to be cropped, while
+ larger layers will cause additional content (beyond the original
+ bounds of the camera) to be shown.
+ \li \uicontrol{Fit} - render the content seen by the camera (based on the
+ aspect ratio of the presentation) larger or smaller to fit within the
+ layer. When the aspect ratio of the layer is different than the
+ presentation, additional content will be shown either
+ above/below or left/right; the content seen by the camera will never
+ be cropped.
+ \li \uicontrol{Fit Horizontal} - Same as \uicontrol{Fit} but will render the
+ content seen by the camera larger or smaller to fit within the layer horizontally.
+ \li \uicontrol{Fit Vertical} - Same as \uicontrol{Fit} but will render the
+ content seen by the camera larger or smaller to fit within the layer vertically.
+ \endlist
+\li
+ \b{Scale Anchor} - When changes to the layer size cause
+ the camera to render more or less content this property controls which
+ part of the content stays in the same spot relative to the layer. A
+ value of \e{Center} causes the center of the camera to always
+ remain in the center of the layer, a value of \e{NW} causes the
+ upper left corner of the content seen in Studio to always be at the
+ upper left corner of the layer, a value of \e{N} causes the top
+ middle of the content seen in Studio to always be at the top middle
+ edge of the layer, and so forth.
+\endlist
+\raw HTML
+<a href="images/Runtime-CameraModes.png">
+\endraw
+\image Runtime-CameraModes.png
+\raw HTML
+</a>
+\endraw
+You can adjust these properties in the \e{inspector palette} once you have selected the
+desired camera in the \e{timeline palette}.
+
+\image camera-scale-mode.png
+*/
diff --git a/doc/src/10-best-practices/40-disable-depth-test.qdoc b/doc/src/10-best-practices/40-disable-depth-test.qdoc
new file mode 100644
index 00000000..f2b54f3f
--- /dev/null
+++ b/doc/src/10-best-practices/40-disable-depth-test.qdoc
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Disable Depth Test
+\page best-practices-disable-depth-test.html
+\ingroup qt3dstudio-best-practices
+
+ This page describes the
+\c{Disable Depth Test} property of Layers edited in Qt 3D Studio.
+
+\image DisableDepthTest.png
+
+The Disable Depth Test property can be used to simultaneously override
+depth testing and the order objects are rendered. The operation of this
+property is not as obvious as many of the other properties in the system
+so this page offers some insight into when, where, and why this property
+might be used.
+
+\section1 What Does It Do?
+
+By default, the Disable Depth Test property is unchecked
+(\c{false}). This is the normal mode of operation. In this mode
+rendering is done in two passes. First, reading and writing from the
+depth buffer is enabled and all opaque objects are rendered from front
+to back (objects closer to camera are rendered first). In the second
+pass, writing to the depth buffer is disabled and all transparent
+(non-opaque) objects are rendered from back to front.
+
+The first pass allows for optimal z-culling for normal opaque 3D objects
+and the second pass allows for correct blending of transparent objects.
+
+By checking the Disable Depth Test property - setting it to
+\c{true} - a different single pass rendering mode is enabled for
+the Layer. In this mode the depth buffer is not used at all, and all
+objects are rendered in a single back to front pass.
+
+\section1 Why?
+
+Each setting for this property has pros and cons.
+
+\section2 Disable Depth Test: \c{false}
+
+\b{Pros:}
+
+\list
+\li
+ This mode ensures the best visual quality because the two pass
+ rendering technique enables the correct rendering of overlapping and
+ intersecting 3D objects as well as correct blending of transparent
+ objects.
+\li
+ Performance can be higher in this mode if there are opaque objects
+ which occlude other objects. Skipping the rendering of pixels which
+ are hidden behind fully opaque objects is a common and powerful 3D
+ rendering optimization known as z-culling.
+\endlist
+
+\b{Cons:}
+
+\list
+\li
+ The two pass rendering technique can be more expensive in some
+ scenarios.
+\endlist
+
+\section2 Disable Depth Test: \c{true}
+
+\b{Pros:}
+
+\list
+\li
+ This mode can increase performance if there are very few (or no)
+ objects benefiting from z culling. In cases with little overlap it can
+ be faster to render with the one pass technique.
+\endlist
+
+\b{Cons:}
+
+\list
+\li
+ In some scenarios, rendering errors may be introduced and/or
+ performance can suffer in this mode. When objects intersect or overlap
+ each other depth testing and the two pass rendering technique are
+ necessary to achieve the correct results. (For more details, see
+ \l{http://en.wikipedia.org/wiki/Painter\%27s\_algorithm}{\"Painters
+ Algorithm\" on Wikipedia}.
+\endlist
+
+\section1 Conclusion
+
+The Disable Depth Test property on Layers is an advanced property that
+can be used to increase performance under certain specific scenarios. It
+can be activated per-Layer to enable a separate one pass rendering
+technique that can achieve higher performance than the default rendering
+technique by eliminating the overhead of doing expensive depth testing
+in cases where 3D objects do not overlap or intersect.
+
+This property should be enabled with some care. Though it is possible to
+increase performance by enabling this property on some Layers it is also
+possible to introduce undesirable rendering errors and even in some
+cases adversely affect performance. Remember to measure thoroughly when
+optimizing.
+
+*/
diff --git a/doc/src/10-best-practices/45-blend-mode.qdoc b/doc/src/10-best-practices/45-blend-mode.qdoc
new file mode 100644
index 00000000..fa445593
--- /dev/null
+++ b/doc/src/10-best-practices/45-blend-mode.qdoc
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Blend Mode
+\page best-practices-blend-mode.html
+\ingroup qt3dstudio-best-practices
+
+This page describes the
+\c{Blend Mode} property edited in Qt 3D Studio.
+
+\image LayerBlendModes.png "Blend Mode"
+
+The Blend Mode property controls how the colors of the active layer or object are blended with
+the colors of the background layer or object.
+
+In Qt 3D Studio both layers and object materials have the Blend Mode property. Changing Blend
+Mode in a layer will effect all objects in that layer while changing Blend Mode for a single
+object will only effect that object and it will only blend with background objects in the same
+layer, not with objects in other layers.
+
+Different blend modes are using different formulas to calculate the result as described below.
+It is important to know that every color channel of a pixel has a value ranging from 0.0 (black)
+to 1.0 (white). In formulas below \e A is the pixel color value of the active layer or object
+while \e B is the pixel color value of the background layer or object.
+
+\e{Note that modes marked with * are available only with hardware supporting KHR and NV
+extensions.}
+
+\section1 Blend Modes
+
+\section2 Normal
+For both layers and objects the default blend mode is \e Normal. Opaque objects will
+occlude objects in the background.
+
+\image LayerBlendModeNormal.png "Normal"
+
+\section2 Screen
+\e Screen inverts the pixel color values of both active and background layers or objects,
+then multiplies them and finally inverts the product. This will produce a lighter result.
+Black pixels in the active layer will be rendered as 100% transparent.
+
+\b Formula: \c{1-(1-A)*(1-B)}
+
+\image LayerBlendModeScreen.png "Screen"
+
+\section2 Multiply
+\e Multiply multiplies the pixel color values of both active and background layers or objects.
+This will produce a darker result. White pixels in the active layer will be rendered as 100%
+transparent.
+
+\b Formula: \c{A*B}
+
+\image LayerBlendModeMultiply.png "Multiply"
+
+\section2 Add
+\e Add simply adds the pixel color values of both layers. This will produce a lighter result.
+Black pixels in the active layer will be rendered as 100% transparent.
+
+\b Formula: \c{A+B}
+
+\e{Note: Available only in Layers}
+
+\image LayerBlendModeAdd.png "Add"
+
+\section2 Subtract
+\e Subtract simply subtracts the pixel color value of the active layer or object from the pixel
+color value of the background layer or object. This will produce a darker result.
+
+\b Formula: \c{B-A}
+
+\e{Note: Available only in Layers}
+
+\image LayerBlendModeSubtract.png "Subtract"
+
+\section2 Overlay
+\e Overlay uses a combination of \e Multiply and \e Screen modes. Basically it uses \e Screen
+mode on lighter pixels and \e Multiply mode on darker pixels. This will produce a result with
+increased contrast.
+
+\image LayerBlendModeOverlay.png "Overlay"
+
+\section2 ColorBurn
+\e ColorBurn inverts the pixel color value of the background layer or object and then divides it
+with the pixel color value of the active layer or object. Finally the result is inverted. This
+will produce a result darker than with \e Multiply.
+
+\b Formula: \c{1-(1-B)/A}
+
+\image LayerBlendModeColorburn.png "Colorburn"
+
+\section2 ColorDodge
+\e ColorDodge divides the pixel color value of the background layer or object with the inverted
+pixel color value of the active layer or object. This will produce a result lighter than with
+\e Screen.
+
+\b Formula: \c{B/(1-A)}
+
+\image LayerBlendModeColordodge.png "Colordodge"
+
+*/
diff --git a/doc/src/10-best-practices/50-creating-binary-and-optimized-presentations.qdoc b/doc/src/10-best-practices/50-creating-binary-and-optimized-presentations.qdoc
new file mode 100644
index 00000000..471282cd
--- /dev/null
+++ b/doc/src/10-best-practices/50-creating-binary-and-optimized-presentations.qdoc
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\title Creating Binary Presentations
+\page best-practices-creating-binary-and-optimized-presentations.html
+\ingroup qt3dstudio-best-practices
+
+In order to optimize the load
+times and playback experience of a project, Qt 3D Studio allows a
+presentation to be compressed into and viewed in binary format. This is
+a recommended step of deploying a project in a production environment.
+There are two types of compilation, available in different formats:
+
+\list
+\li
+ Compiling the presentation assets for faster loading
+\li
+ Gathering shader information to precompile them at application launch
+\endlist
+Read on for further descriptions of what these mean, how to accomplish
+them, and when and when \e{not} to do them.
+
+\section1 Compiling Assets
+
+\section2 What it Does
+
+Compiles \c{.uia} and \c{.uip} files to a binary representation. This can speed initial loading of
+an application substantially.
+
+\section2 How to Do It
+
+From the command line on Windows, run the \c{Qt3DCompiler.exe} application \e{(in your
+installation directory next to \c{Qt3DStudio.exe})} passing a command line argument of the
+\c{.uia} application file.
+
+\c{Qt3DCompiler.exe \path\to\project\MyAppName.uia}
+
+The files end up in a \c{binary/} directory next to your \c{.uia} application file. You can then
+run your application by passing the \c{.uib} file to the Viewer.
+
+\c{Qt3DViewer.exe \path\to\project\binary\MyAppName.uib}
+
+\section2 When To Do It
+
+Only perform binarization when:
+
+\list
+\li
+ you are about to deploy your content for production or demo, or
+\li
+ you need to test loading speeds of your content.
+\endlist
+Once you perform binarization subsequent changes to your presentations
+will \b{not} be reflected in the runtime until you
+delete the \c{binary} folder, or re-run binarization. Prematurely
+running binarization, and then forgetting that you have done so, is a
+good way to run into head-scratching problems later on.
+
+\section1 Gathering Shaders
+
+\section2 What It Does
+
+In short, it removes performance hiccups due to shader compilation in
+the middle of application execution by precompiling the necessary
+shaders when your application first starts.
+
+\section2 Background
+
+When you are working on a project you will see lines like this in the
+output each time you preview your presentation:
+
+\badcode
+eDEBUG_WARNING Failed to find file: /path/to/project/binary/shadercache.xml
+eDEBUG_WARNING Searched paths:
+eDEBUG_WARNING /path/to/project/binary/shadercache.xml
+\endcode
+Although it may look bad \e{(\"it has three lines, and said
+`failed'!\")} this is not an error. It is only a \e{warning} about
+\e{potential} performance problems. In short, ignore these log lines
+until you are either testing loading speed and performance, or you are
+preparing your content for final production use.
+
+\section3 About Shaders and Shader Compilation
+
+The Qt 3D Studio Runtime uses shaders to render your content at
+high speed. Shaders are mini programs that run on the graphics card. As
+programs, they need to be compiled to run, and they have to compile on
+the graphics card itself. Depending on the Standard Material settings or
+custom materials used in your presentation, you may have several shaders
+that need to compile. Compiling each shader takes a short amount of time
+(depending on the complexity of the shader)...but however slow or
+fast it is, it is not instant.
+
+Because of the dynamic nature of Studio presentations, and the fact that
+different settings for a Standard Material may cause a different shader
+to be generated, the Runtime does not know in advance what shaders may
+be necessary. Only once you go to a particular slide where a combination
+of settings are applied does it \"see\" the material for the first time,
+and need to compile it to render your content. The result when this
+happens is that you may experience a slight lurch when you switch to a
+particular slide for the first time.
+
+\section2 How to Do It
+
+You can remove any performance lurches by pre-compiling the shaders you
+will need when the presentation starts up. This is what the
+\c{shadercache.xml} file is for. This file tells the Runtime all
+the information it needs about all the shaders that will be required.
+When present, the Runtime creates all the shaders at startup, so they
+are ready when needed.
+
+\omit
+
+TODO: Reintroduce support for shader caching (BOUL-728)
+
+\list 1
+\li
+ From the command line, change to the directory for the Viewer
+ application.
+\li
+ \c{Qt3DViewer.exe -D<graphicsdevice> -saveShaders \path\to\project\myapp.uia}
+\endlist
+\list
+\li
+ \b{\c{<graphicsdevice>}} must be one
+ of \c{GL2}, \c{GLES2}, \c{GL3}, or \c{GLES3} (e.g.
+ \c{-DGL3}), specifying the target graphics device to create
+ shaders for.
+\li
+ \e{The Viewer will start, showing your application.}
+\endlist
+\list 2
+\li
+ Run through your application, causing every unique material
+ combination that you want cached to be displayed. If the viewer does
+ not see a particular material during this step, it will not be
+ included in the cache.
+\li
+ Quit the viewer.
+\endlist
+\list
+\li
+ \e{This will create a
+ \c{binary\shadercache.xml} XML file.}
+\endlist
+\list 4
+\li
+ Run your application as you normally would, i.e. either
+ \c{Qt3DViewer.exe \path\to\project\myapp.uia}
+ or
+ \c{Qt3DViewer.exe \path\to\project\binary\myapp.uib}
+\endlist
+
+\endomit
+
+\section2 When to Do It
+
+The presence of a \c{shadercache.xml} file can cause old shader
+information to be cached and used instead of your current information.
+If custom materials are updated - or the implementation is updated in a
+new Qt 3D Studio releases - your old shader cache can override the
+new information, causing rendering problems. You should only generate a
+shader cache when you need to test final performance, or display a demo
+where you cannot pre-navigate the interface once to cause the
+compilation to occur and remove any hiccups.
+
+*/
diff --git a/doc/src/10-best-practices/60-importing-3d-content.qdoc b/doc/src/10-best-practices/60-importing-3d-content.qdoc
new file mode 100644
index 00000000..c96c76f7
--- /dev/null
+++ b/doc/src/10-best-practices/60-importing-3d-content.qdoc
@@ -0,0 +1,779 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Working with 3D Content
+\page best-practices-importing-3d-content.html
+\ingroup qt3dstudio-best-practices
+
+\chapter 3D Content Overview
+
+\list
+\li
+ \b{Use Triangles} - Qt 3D Studio only supports geometry
+ exported as triangles. When exporting you must ensure that this option
+ is selected. Many of the exporters provide an option for this at
+ export time, and Studio will tell you what went wrong if you forget to
+ export with this option.
+\li
+ \b{Time-based Animations} - By default in Max or Maya, when you
+ are creating keyframes you are associating them with certain frame
+ numbers. This is great in the film industry where frame rates are
+ constant, but this technique necessarily has problems in applications
+ where the frame rate may or may not be rock solid. Our solution to
+ this problem is to express the locations of keyframes in time values
+ instead of frame numbers. That way, if you say \"this logo animation
+ will play for 3 seconds\" we can guarantee that it will play for 3
+ seconds. If you express it in frames, \"this logo animation will play
+ for 180 frames\" it may play for 3 seconds if you're getting 60 fps,
+ but if you drop to 30 fps the animation is going to go much slower.
+
+ Luckily, accounting for this is relatively simple. Max and Maya both
+ default to a setting of 24 frames per second, so your keyframes will
+ be translated at that ratio. If you want a keyframe at one second, put
+ it on frame 24. Two seconds? Frame 48, etc. Both Max and Maya offer
+ configurable frame rates, and the frame rate setting should be
+ respected upon import, if changed. It's also worthwhile to note that
+ Maya, by default, starts at frame 1. If you have a keyframe at frame
+ one, the time for that keyframe will be 1/24 or 0.041 seconds. It may
+ be a good idea to go into your Maya animation settings and start your
+ animations at frame 0, or 0/24 = 0 seconds.
+\li
+ \b{Different Animation Systems} - DCC packages offer highly
+ complex and specialized animation systems. We recommend using Studio's
+ animation capabilities whenever practical. This helps keep mesh
+ information on import clean and reduces conflicts between imported
+ mesh animation and Studio's animation upon refreshing.
+
+ The animation system in Studio is a full implementation of bezier
+ keys, and the full complement of bezier animation that you can create
+ with Max or Maya and export with COLLADA will be represented in
+ Studio. The more extreme differences between the various animation
+ systems are mitigated by the limitations imposed by the COLLADA and
+ FBX formats, but there could be some animations that you would be able
+ to create in Max or Maya that would not be represented correctly in
+ Studio. If you believe you've found such an animation, and you'd like
+ to use it in your UI, please bring it up with us. We love finding edge
+ cases we haven't covered yet, and look forward to improving our
+ animation support to meet your needs.
+\li
+ \b{Handling Pivot Points} - DCC packages all handle pivot points
+ differently. In Qt 3D Studio there is only one pivot per object
+ and it is used as the origin for position, scale, and rotation
+ operations. In your DCC package, feel free to adjust the position of a
+ 3D model's pivot as needed. However, extreme edits to pivots in Modo,
+ Max, or Maya can cause problems upon import into Studio, especially if
+ animated. This difference is often manifested as a difference in the
+ position or orientation of an object. As an artist you can prevent
+ these kinds of problems by only making simple edits to your pivot
+ points. Keep your pivot points to the default (world) alignment, don't
+ scale them, and make sure that if you have multiple pivots (Maya) that
+ they are all at the same location in space.
+\endlist
+
+\chapter 3D Content via FBX
+
+\image 3D_Content/FBX-Maya.png
+
+Studio can import 3D geometry and animations exported using FBX. Please
+use the following settings when exporting:
+
+\list
+\li
+ \b{Geometry}
+\li
+ Uncheck all options, except \b{check the following}:
+ \list
+ \li
+ Split per-vertex Normals
+ \li
+ Tangents and Binormals
+ \li
+ Referenced Assets Content
+ \li
+ Triangulate
+ \endlist
+\li
+ \b{Animation} - enable or disable as desired; bake or unbake
+ animations as desired
+\li
+ \b{Cameras} and \b{Lights} - these objects will only come
+ into Studio as empty nodes (groups). This can be useful if you need to
+ animate these objects and use those animations in Studio (by attaching
+ Studio cameras and lights to the animated groups).
+\li
+ \b{Axis Conversion} - Qt 3D Studio uses a Y-up coordinate
+ system, so ensure that \c{Up Axis} is set to \c{Y}.
+\li
+ \b{FBX File Format}
+\li
+ \b{Type} - Studio supports either ASCII or Binary FBX files.
+ ASCII files are preferred for any bug reports.
+\li
+ \b{Version} - Studio supports FBX versions 2013 and 2014 (up to
+ 2014.2). We recommend 2014.
+\endlist
+\chapter 3D Content via COLLADA
+
+\section1 Exporting COLLADA from Various 3D Modeling Applications
+
+Each 3D modeling application uses a specific COLLADA exporter that
+produces a format recognized by Studio. Autodesk's 3D Studio Max 2011
+and Maya 2011 use OpenCOLLADA which can be found by visiting
+www.opencollada.org/download.html
+
+Download the correct version of OpenCOLLADA for 3D Studio Max and Maya.
+Maya and 3D Studio Max need to be installed prior to installing the
+correct OpenCOLLADA version. In addition, be sure that no 3D programs
+are open during the installation of OpenCOLLADA.
+
+\section1 Exporting OpenCOLLADA from Maya
+
+In order for the OpenCOLLADA exporter to become active, some options
+need to be checked and unchecked in the Plug-in Manager. To find the
+Plug-in Manager, go to Window > Settings/Preferences
+> Plug-in Manager.
+
+The \"fbxmaya.mll\" plug-in has to be unchecked. The COLLADAMaya.mll
+needs to be checked as both Loaded and Auto Load.
+
+\image 3D_Content/colladaMaya01.png
+
+Next, go to File > Export Selection and open the dialog
+box.
+
+\image 3D_Content/colladaMaya02.png
+
+Under General Options, be sure that OpenCOLLADA exporter is selected and
+set as the default file extension. Under general export options, check
+that the following options are active.
+
+\image 3D_Content/colladaMaya03.png
+
+The triangulate option must be checked on prior to export.
+
+Finally, choose the location for the COLLADA file to be saved. It is a
+good practice to keep all source art, including COLLADA files, in a
+folder outside of your Studio project folder.
+
+\image 3D_Content/colladaMaya04.png
+
+\section1 Exporting OpenCollada from 3D Studio Max
+
+Select the object to be exported. Next, open the Export dialog box.
+
+\image 3D_Content/colladaMax01.png
+
+Be sure to select OpenCOLLADA and not Autodesk Collada.
+
+Next, you will be prompted with another set of options for the
+OpenCOLLADA exporter.
+
+\image 3D_Content/colladaMax02.png
+
+Again, be sure that triangulate is checked on.
+
+\section1 Exporting COLLADA from Luxology's Modo 601
+
+Modo comes installed with a COLLADA exporter that works with Studio as
+of versions 501 and 601.
+
+With the mesh object selected, triangulate the mesh by pressing Shift+T.
+
+\image 3D_Content/colladaModo01.png
+
+\image 3D_Content/colladaModo02.png
+
+Next, go to System > Preferences to configure the COLLADA
+exporter.
+
+\image 3D_Content/colladaModo03.png
+
+In the Preferences dialog box, locate the Collada I/O section under File
+I/O. Be sure that Save Triangles as Triangles is checked on.
+
+\image 3D_Content/colladaModo04.png
+
+\section1 Description of supported features
+
+The following section describes the features supported by COLLADA import
+into Studio. Where appropriate, caveats, limitations, and differences
+between different DCC applications are discussed.
+
+\section2 Geometry
+
+Generally speaking, the geometry import capabilities are very solid.
+We've stress tested different high poly count scenarios. The one caveat
+here is mentioned above, Studio only supports triangulated geometry, so
+be sure to check that option when exporting COLLADA data for use in
+Studio.
+
+\section2 Transformation
+
+As you would expect with COLLADA you can import full 3D transform
+information including position, rotation, scale, and pivot. Studio can
+import left and right handed coordinate systems, Y-up or Z-up and
+rotations applied in any order. The principal limitation in this area is
+pivot points. As discussed above, only simple edits to pivot points are
+supported.
+
+Most DCC tools allow artists to freeze transformations and we highly
+recommend performing this operation before importing mesh data into
+Studio. This operation ensures that the mesh coming into Studio has
+clean transformation data and no arbitrary transformation values which
+can be confusing or an impediment to your work.
+
+Please note: After freezing transforms, you may have to reposition the
+pivot point in some DCC tools.
+
+\section2 Hierarchy
+
+The plug-in supports translating hierarchical information from COLLADA
+into Scene Graph information inside of Studio. Hierarchies of arbitrary
+depth are supported, including grouped nodes. Hierarchical transforms
+are applied as expected.
+
+\section2 Materials
+
+The plug-in supports translating material settings from the DCC
+application into material settings inside of Studio. Specific mappings
+have been made to ensure consistent control of the look inside of NVIDIA
+from within the DCC application. Material settings for diffuse,
+specular, ambient, and opacity are all imported correctly.
+
+\section2 Textures
+
+Images applied to different material IDs will be imported with the
+COLLADA file and applied inside of Studio. Note that the COLLADA files
+reference the images on disk. (Rather than include them in the COLLADA
+file.) This means that a path to the image is stored in the COLLADA
+file, Studio uses this path to import the image. Studio can import
+transformed UV sets (e.g.~Tiling, Rotation) as well as multi-textured
+setups.
+
+We recommend using .png and .dds image formats. These formats support
+alpha channels and allow for lossless editing. With .dds, you can set
+the compression to DXT5 with alpha blending if your image has
+transparency.
+
+\section2 Using Powers of Two Texture Map Pixel Dimensions
+
+As is the case with most real-time graphics, texture maps run optimally
+when their pixel dimensions are set to powers of two. An example of
+powers of two texture maps include 32X32, 64X64, 128X128, 512X512,
+1024X1024, 2048X2048 and tall or wide images that could be 512X64 or
+128X1024. Dimensions do not have to be square but they should be powers
+of two.
+
+\section2 Materials Inspector palette properties
+
+Materials are found parented to a mesh object in the timeline. The image
+below describes the hierarchy of meshes, materials and texture maps:
+
+\image 3D_Content/timeline_material.png
+
+\list
+\li
+ \b{A}: Mesh object
+\li
+ \b{B}: Material
+\li
+ \b{C}: Texture map
+\endlist
+
+When a material is selected, the Inspector palette lists properties
+relevant to editing the material.
+
+The animation toggle is associated with animatable properties.
+
+\image 3D_Content/Materials_InspectorPalette.png
+
+\list
+\li
+ \b{Lighting}: Vertex, Pixel. Per pixel lighting mode is used
+ primarily for materials that utilize Specular Amount and Specular
+ Roughness. Vertex lighting is the default.
+\li
+ \b{Blending Mode}: Normal, Screen, Multiply, Overlay. Setting the
+ Blend Mode to Screen will result in an additive type effect. Multiply
+ and Overlay are similar to what is found in most photo editing
+ programs. The default is Normal blending which yields no special
+ effect.
+\li
+ \b{Diffuse Color}: Change the diffuse color of your material.
+ There are predefined swatches and a custom color palette where
+ specific RGB values can be input.
+\li
+ \b{Diffuse Map}: This channel UV maps a bitmap image onto a
+ material's surface.
+\endlist
+\section3 Add texture maps to any channel by clicking on the channel
+slot and choosing an image from the pop-up menu. This menu displays all
+supported images in your project directory.
+
+\image 3D_Content/texture_selection.png
+
+\list
+\li
+ \b{Emissive Power}: The default value is zero. Increasing
+ the emissive power causes the material to become luminous. At 100\%
+ emissive, lights will not have an effect on your material.
+\li
+ \b{Emissive Map}: Control the amount and location of the emissive
+ value with a texture map.
+\li
+ \b{Specular Reflection}: When a map is assigned to this channel,
+ it is environmentally mapped to the surface and treated as a
+ reflection.
+\li
+ \b{Specular Amount}: With per pixel lighting turned on, this
+ setting adjusts the specular amount of a material surface.
+\li
+ \b{Specular Roughness}: Controls the spread and falloff of the
+ specular appearance.
+\li
+ \b{Opacity}: Controls the general opacity of the material.
+\li
+ \b{Opacity Map}: Adding a texture map to this channel controls
+ the amount and location of opacity on a material.
+\endlist
+
+\section2 Texture map Inspector palette properties
+
+With a texture map selected in the timeline, the inspector palette will
+display the following properties:
+
+\image 3D_Content/texture_inspectorPalette.png
+
+The animation toggle is associated with animatable properties.
+
+\list
+\li
+ \b{A}: U and V repeat. These properties adjust the texture map's
+ repeat values in U and V space. Default is set to 1.
+\li
+ \b{B}: Sets the texture mapping mode to either UV Mapping or
+ Environmental Mapping.
+\li
+ \b{C}: U and V tiling. Sets the texture map to either tile or not
+ tile (repeat) in either U or V direction. Default is set to No Tiling.
+\li
+ \b{D}: UV Rotation, U and V position, U and V pivot. These
+ properties allow for transforming a texture map in U and V space. To
+ rotate a texture map about its center, set the U and V positions to
+ -.500 and the U and V pivot to .500.
+\endlist
+
+\section2 Adding Fonts and Using Text in Studio
+
+In order to use text in Studio, fonts need to be added to the fonts
+folder within the user's project directory. Before adding fonts to your
+project, be sure that you have the rights to distribute the fonts or use
+open source fonts from www.google.com/webfonts
+
+Studio comes packaged with a default library of open source webfonts.
+These fonts can be found in the project palette font library directory.
+
+\image 3D_Content/text01.png
+
+Drag a font from Windows Explorer to the fonts folder in the project
+directory. A copy of the font will be generated and added to the
+project.
+
+\image 3D_Content/text02.png
+
+Next, drag the font from the fonts folder in the project palette to the
+scene.
+
+\image 3D_Content/text03.png
+
+If there are multiple fonts in the font folder, the user can change the
+font in the scene by first selecting the text, then choosing a different
+font in the font property found in the inspector palette.
+
+Replacing missing fonts is as easy as locating the missing font and
+adding it to the fonts folder.
+
+\note To replace a specific font in your presentation without having
+to tediously locate each font in the presentation, open your
+\c{.uip} file in a text editor and perform a find/replace
+operation. For example, if you wish to replace all 100 instances of
+\"TitilliumWeb\" with \"Michroma\", you simply need to find all
+instances of \"TitilliumWeb\" in a text editor and replace with
+\"Michroma\". Be sure to correctly identify the font names or this
+operation will not work. Save the \c{.uip} file after find/replace
+is complete and reopen the .uip in Studio. Voila! All specified fonts
+will be replaced with the desired font.
+
+\section2 Animation
+
+Animations can be brought into Studio using COLLADA. Animation is
+supported on any imported attribute. Position, rotation, scale, pivot,
+and material attributes can all be animated. An example of our advanced
+support for animations would be a hierarchy of items, rotated
+simultaneously on arbitrary axes in arbitrary axis order. Studio also
+supports importing bezier tangent value tweaked into animations.
+
+\chapter 3D Workflow Case Study
+
+The examples presented below use Luxology's Modo 601 for digital content
+creation, however, these concepts also apply to other DCC tools such as
+Autodesk's 3D Studio Max and Maya.
+
+\section1 Building a simple gauge and importing to Studio.
+
+The following section describes the process of building a simple gauge
+in Modo, Luxology's 3D modeling and animation program. The concepts of
+this example can also be applied to other DCC tools.
+
+Traditionally, artists build their 3D models first and then build
+texture maps based on the mesh's UV coordinate layout. This is
+especially true with complex 3D models such as cars.
+
+Another technique bases the 3D geometry on existing artwork. In many
+cases, source imagery and artwork can be used to build texture maps.
+These resulting texture maps can then be used as a guide to build
+geometry. In the example below, we are going to use a texture map as a
+basis for constructing the 3D gauge model. This technique ensures that
+proper scale and proportions of the 3D models match the original concept
+artwork.
+
+\section1 Elements of a texture map
+
+The texture map shown on the left features alpha transparency and will
+be the final map used in Studio on our mesh material. An alternate copy,
+shown here on the right, replaces the transparent background with black
+for easy reference modeling.
+
+\image 3D_Content/00_transparentmap.png
+
+This texture map has a height and width of 512px and features a circular
+meter, needle, and needle glow graphics. The needle graphic displays all
+four sides of the needle. Remember that once the modeling is finished,
+the UV layout process will assign the appropriate geometry face to the
+correct area of the texture map. Also included on this map is a center
+registration point that makes it easy for alignment.
+
+\image 3D_Content/02_texture_elements.png
+
+\section1 Modeling geometry based on backdrop image
+
+With Modo open, click on the Images tab on the upper right panel and
+choose Add Clip. Then locate and load the reference map or texture map.
+
+With the texture map loaded in Modo, we can now use it as a reference
+image to begin the modeling process. Now click on the Items tab on the
+upper right panel and choose Add Item > Backdrop Item to
+create a new Backdrop Item object in the scene.
+
+With the Backdrop Item selected, now choose the Properties tab and
+assign the texture map to the Image channel.
+
+\image 3D_Content/03_backdropItem.png
+
+Now we can begin modeling the gauge geometry. With the Mesh object
+selected in the Items panel, let's build the circular meter component.
+To do this, choose the front view then under the Basic objects tab
+(upper left panel) click on the cylinder button. Now, while holding the
+Ctrl key, line up the cursor over the center registration mark on the
+Backdrop Item and Cntrl click and drag out to just beyond the circular
+meter graphic. In the cylinder creation parameters on the left, choose
+22 segments. Now press the spacebar to drop the tool and complete the
+modeling operation. Next let's remove excess geometry. Go to the
+perspective view so you can view the 3D cylinder mesh. Press \"3\" on
+the keyboard (not the numeric keypad) and now we are in polygon mode.
+Choose the front-facing polygon and next press the left bracket key to
+inverse select the cylinder's other faces. Now press delete. You will be
+left with a single circular face with 22 sides.
+
+Tip: Use the numerical keypad's numbers to change views or shading
+modes. Pressing \"7\" will switch to wireframe mode while \"4\" switches
+to shaded view mode. Pressing \"2\" and \"3\" will send you into front
+and side views respectively while pressing the . key will bring you back
+to perspective view. Using the numbers along the top of the main
+keyboard will also make you an efficient modeler. Numbers 1,2,3 and 4
+will activate different sub object modes such as vertex, edges, polygon
+and item modes.
+
+For accuracy, we can center the selected circular face to the world's
+origin. To do this, click on the Basic tab on the upper left and with
+the circular polygon still selected choose Center Selected
+> All. This will place the selected poly exactly in the
+middle of your scene.
+
+Currently, your geometry should cover the entire circular meter graphic
+as seen here:
+
+\image 3D_Content/01b_modelingStart.png
+
+It is important to optimize your geometry and only place geometry over
+places on the texture map where a graphical element is present. As an
+example, if we were to leave this polygon as-is and import it into
+Studio with the chosen texture map, there will be an entire region of
+the geometry that will have to be needlessly drawn at runtime. Even
+though this area of the map is transparent, it is still calculated by
+the hardware and as one would imagine could cause performance issues. So
+we need to punch a hole in the geometry so that the mesh is only
+covering the circular meter graphic and nothing else.
+
+In the front view, select the polygon and press the \"b\" key to
+activate the beveling tool. Now bevel the polygon so that the orange
+selected portion of the bevel resides just inside the circular meter
+graphic. Press the spacebar and complete the operation. Now delete the
+center polygon. Next, delete the lower right faces of the circular
+geometry that do not make up the meter. Rename the Mesh item to
+\"indication.\"
+
+The resulting mesh should look similar to this:
+
+\image 3D_Content/01_texture_map.png
+
+\section1 Modeling the needle and needle glow
+
+Create a new Mesh item in the Items tab and draw a cube over top of the
+Backdrop Item, matching the overall dimensions of the needle graphic.
+Remember, the texture is displaying all four sides of the needle so in
+this case we are modeling the center portion of the needle only.
+
+Adjust the cube's shape to taper off at the top and side views. Delete
+the backfacing and bottom polygons of the needle, since we will not see
+them in the final product. Subdivide the geometry across the middle by
+selecting the ring of edges and connecting them (Alt+C).
+
+\image 3D_Content/modeling_needle.png
+
+Model the glow geometry using the same techniques as described earlier.
+Start out with a new Mesh item and draw a cube directly overtop of the
+left side glow gradient. Remove excess polygon faces. With one remaining
+polygon face, taper the points to closely surround the gradient but
+leaving a slight gap between the gradient edges and the geometry.
+
+Now mirror the geometry (select the polygons and select Duplicate
+> Mirror) to the right side to cover the right gradient.
+The mirroring command can be found in the Duplicate tab on the left
+panel.
+
+Now select the four vertical edges of the glow geometry and bisect them
+(Alt+C). Now rename this Mesh item to \"glow.\"
+
+We bisect long strips of polygons to avoid visual artifacts later on.
+
+\image 3D_Content/modeling_glow.png
+
+\section1 Adjusting needle location and pivot
+
+Next, we need to position the needle in such a way that will allow it to
+rotate about its Z axis at the base of the needle. Select all of the
+polygons that make up the needle item and choose Center Selected under
+the Basic tab. Do the same for the glow item. Make sure that both left
+and right glow polygons reside to the left and right of the needle
+respectively. Now select both the needle and glow items and move them up
+in the Y axis so that the bottom of the needle and glow line up just
+around the world origin.
+
+Next, we need to parent the glow item to the needle by selecting the
+glow item in the Items panel and dragging it onto the needle item. It
+will now appear as a child object of the parent needle. This will ensure
+that the glow object travels with the rotation of the needle.
+
+\image 3D_Content/Item_panel_parenting.png
+
+Select the needle item and click and hold on the Items button at the top
+menu. Choose Center. The Center pivot will appear in the modeling space.
+
+\image 3D_Content/center.png
+
+Now position the pivot to the world origin using the move tool.
+
+\image 3D_Content/08_adjustPivots.png
+
+\section1 Creating a material and adding a texture map
+
+The following steps are a simple way to add a material to your polygon
+selections and adding texture maps to them easily.
+
+Continuing with our case study, select all three Items and turn on the
+polygon selection mode. Next, press the \"m\" key to open the material
+assignment pop-up window and type in \"gauge\" for the description. Be
+sure the Diffuse amount is set to 100\%. Press Enter. A new material
+called \"gauge\" has now been created.
+
+\image 3D_Content/selectPolys_MakeMaterial.png
+
+You can view this material by clicking on Texture at the top menu and
+choosing Open Material Editor.
+
+Now with the material editor open, we can drag our image to the gauge
+material to assign a texture map to it.
+
+\image 3D_Content/image_toMaterial.png
+
+\section1 UV layout
+
+This section assumes prior knowledge of UV coordinates and layout. For
+further explanation on advanced techniques, please visit
+www.luxology.com.
+
+With the three items selected (indication, needle, and glow) choose the
+Lists tab. Now expand UV Maps and click on (new map). If there is an
+existing UV map such as Texture or other preexisting UV map, just delete
+it. You should now only have one UV map listed under the UV Maps
+rollout. Rename this map channel to \"gauge.\"
+
+\image 3D_Content/Lists.png
+
+Now click on the UV tab at the top menu.
+
+\image 3D_Content/UVTab.png
+
+Begin unwrapping the UV coordinates by planar mapping the indication
+geometry and glow geometry. Unwrap the needle using the Atlas method so
+that all sides of the needle are broken up into four pieces, one for
+each side.
+
+Position the UVs over the texture map so that it resembles the image
+below.
+
+\image 3D_Content/04_UVSpace.png
+
+The result should look something like this:
+
+\image 3D_Content/05_TexturedModel.png
+
+\section1 Exporting 3D models to Studio via COLLADA.
+
+This section describes the process of preparing a model for export to
+Studio.
+
+As mentioned earlier, it is important to freeze transforms on your mesh
+objects to ensure a clean import to Studio.
+
+Select all three mesh items (indication, needle, glow) and then choose
+Item > Transforms > Freeze All in the top
+menu.
+
+\image 3D_Content/07_freezeTransforms.png
+
+Next, we need to be sure the correct texture map is applied to our
+material prior to export. If you recall, there is a version of the
+texture map that has transparency information. This is the map we will
+use for our exported geometry. Go to the Images tab in the upper right
+panel. Right-click on the image and choose \"Replace as Still\" then
+choose the \"gauge\_elements.png\" map. You will notice the texture map
+updating in the viewport.
+
+Next, with all three models still selected press Shift+T which is the
+shortcut command to triple the polygons. This is a quick method to
+convert quads to triangulated mesh.
+
+\section3 Pro Tips: Save a copy of your project prior to preparing it
+for export. This way, you have non-triangulated version of your project
+for future editing.
+
+\image 3D_Content/export_triangulateMesh.png
+
+Before we export our 3D models, we must first check our export
+preferences. In Modo, this is located under System >
+Preferences.
+
+Next, click on Scene I/O under the File I/O rollout list. Now, be sure
+that \"Save Triangles as Triangles\" is checked on. Here is a common
+configuration for successful export from Modo via COLLADA.
+
+\image 3D_Content/export_exportSettings.png
+
+Export the 3D models by choosing File > Export As.
+
+Choose COLLADA as the Save as type. Save the COLLADA file as
+\"Gauge.dae\"
+
+\section1 Import 3D gauge into Studio
+
+The following steps will guide you through the process of importing a
+COLLADA 3D model into Studio.
+
+Launch Studio 5.0.
+
+Create a new project and with \"Create directory for project\" checked
+on, save the project as Gauge.uip.
+
+You now have created a new UIP project called Gauge. Now, locate your
+exported Gauge.dae file in Windows Explorer.
+
+Drag and drop the Gauge.dae file onto the models folder in Studio's
+Project palette. A series of mesh files are created in addition to a
+.import file.
+
+\image 3D_Content/export_DragDAE.png
+
+\section3 Converted DAE to .mesh objects:
+
+\image 3D_Content/export_project.png
+
+If you want this gauge to appear in additional slides, turn on the Edit
+Master slide view button at the upper left of Studio's user interface.
+
+Now drag the Gauge.import to either the timeline or the scene project
+window.
+
+\image 3D_Content/export_dragToScene.png
+
+The gauge will appear very small in the project window. Select the
+camera under the Layer and adjust its Z position under the Inspector
+palette.
+
+Expand the Gauge, needle, and glow mesh objects in the timeline. Notice
+the gauge materials under each mesh object. These are the materials we
+assigned in Modo.
+
+Select the gauge material for the needle and change its color to red
+using the Diffuse color property under the Inspector palette.
+
+Repeat the previous steps to change the glow's material to red as well.
+With the glow material still selected, increase its emmisive value to
+100\%.
+
+\image 3D_Content/export_diffuseColor.png
+
+You may notice that the indication texture is visible in front of the
+needle. If this is the case, try moving the indication mesh object back
+and away from the needle and also scale it up until it looks correct.
+Some values to consider:
+
+\list
+\li
+ Position Z = 2.4
+\li
+ Scale XYZ = 1.120
+\endlist
+
+Now with the needle selected in the timeline, rotate it about its Z axis
+and notice how it rotates correctly.
+
+*/
diff --git a/doc/src/10-best-practices/70-using-skinned-animation.qdoc b/doc/src/10-best-practices/70-using-skinned-animation.qdoc
new file mode 100644
index 00000000..15cbf344
--- /dev/null
+++ b/doc/src/10-best-practices/70-using-skinned-animation.qdoc
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\omit
+\title Using Skinned Animation hide : true
+\page best-practices-using-skinned-animation.html
+
+ \e{Content goes here}
+\endomit
+*/
diff --git a/doc/src/10-best-practices/80-effects.qdoc b/doc/src/10-best-practices/80-effects.qdoc
new file mode 100644
index 00000000..9ec6964a
--- /dev/null
+++ b/doc/src/10-best-practices/80-effects.qdoc
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Applying Layer Effects
+\page best-practices-effects.html
+\ingroup qt3dstudio-best-practices
+
+\section1 Using Effects
+
+Each layer in a Studio presentation may have one or more post-processing
+effects applied to the visual result. A small library of predefined
+effects is included with the Windows installer. To use one of these
+effects:
+
+\list 1
+\li
+ Click on the
+ \inlineimage{Studio-fx.png}
+ icon at the bottom of the Project palette of Studio.
+\endlist
+\list
+\li
+ \e{This will open the folder for the library in Windows, showing
+ you the available effects.}
+\endlist
+\list 1
+\li
+ Drag one of the \c{.effect} files from the Windows folder into
+ your Project palette.
+\endlist
+\list
+\li
+ \e{This makes a copy of the effect in your project folder.}
+\endlist
+\list 2
+\li
+ Drag the effect from the Project palette onto a Layer in the Timeline
+ palette.
+\endlist
+\list
+\li
+ \e{This applies an instance of the effect to the Layer.}
+\endlist
+\list 3
+\li
+ With the effect selected in the Timeline, use the Inspector palette to
+ adjust or animated the parameters of the effect.
+\endlist
+\list
+\li
+ \e{You will see the effect applied and update immediately within
+ the Studio viewport.}
+\endlist
+You cannot cause an effect to apply to only certain models of a Layer.
+The entire Layer is rendered via its camera, and \e{then} the effect
+is applied. The placement of effects with respect to other (non-effect)
+children of the Layer makes no difference.
+
+You may, however, apply more than one effect to the same Layer. Just as
+layers placed lower in the Timeline render before layers that are on top
+of them, so effects that are lower in the Timeline will be applied
+before the effects that are above them.
+
+\target hdrbloomtonemap
+\section1 Using HDRBloomTonemap
+
+\image Effects-HDRBloomTonemap.png
+
+The \"HDRBloomTonemap\" effect provides two features:
+
+\list 1
+\li
+ Adjust the gamma and exposure of the high-dynamic range rendered
+ content to achieve the image quality you want, and
+\li
+ Apply an adjustable 'bloom' effect to very bright areas (like the sun
+ glinting off a car).
+\endlist
+When you add an HDRBloomTonemap effect to a layer, the following
+properties are available in the Inspector palette:
+
+\list
+\li
+ \b{Gamma} - this affects the non-linear curve of the lighting.
+ Higher values will increase the exposure of mid tones, lightening the
+ image (and decreasing the contrast). A value of \c{1.0} causes no
+ adjustment to the image.
+\li
+ \b{Exposure} - this is a linear multiplier on the lighting,
+ brightening or darkening the image overall. A value of \c{0.0}
+ causes no adjustment to the image.
+\li
+ \b{Bloom Threshold} - lighting greater than this value will
+ bloom. A value of \c{1.0} corresponds to white in the original
+ render result. Lowering this value will cause more areas of the
+ rendered scene to bloom; at a value of \c{0.0} everything in the
+ scene will bloom.
+\list
+\li
+ \e{Tip: to disable bloom and use only the tone mapping, set this to
+ a sufficiently high value, like \c{999}.}
+\endlist
+\li
+ \b{Bloom Falloff} - adjusts the amount of bloom. Lower values
+ result in stronger bloom effect; higher values make the effect more
+ subtle.
+\endlist
+\section1 Using FXAA
+
+\image Effects-FXAA.png
+
+The \"FXAA\" effect applies Fast approXimate Anti-Aliasing to the layer.
+This is a high-speed anti-aliasing technique that removes some of the
+\"jaggies\" from the image without impacting performance as heavily as
+super-sampling would.
+
+\list
+\li
+ Pros: easy fix for many aliasing problems; works with moving images
+ (unlike \l{best-practices-antialiasing.html#progressive-aa}{Progressive Anti-Aliasing}).
+\li
+ Cons: can blur and otherwise 'munge' fine text details present in the
+ layer; as a screen-space heuristic technique it can sometimes leave
+ sharp edges that ideally would be anti-aliased.
+\endlist
+\section1 Using Depth of Field
+
+\image Effects-DOF.png
+
+The \"Depth Of Field HQ Blur\" effect increasingly blurs regions of the
+image based on their deviation from a specified distance from the
+camera. (Notice that the cube and same-distance floor are in focus while
+the closer cone and farther sphere are blurred.)
+
+For this effect to work well, you need to adjust the
+\c{Clipping Start} and \c{Clipping End} properties of the
+camera for the Layer to 'frame' the content. (You ideally want the
+largest possible value for \c{Start} and the smallest possible
+value for \c{End}.) After you do this you can use the properties of
+the effect in the Inspector palette to adjust the effect.
+
+\list
+\li
+ The \c{Focus Distance} property specifies the distance from the
+ camera where the content is in perfect focus.
+\li
+ The \c{Depth of Field} property specifies a the distance around
+ the \c{Focus Distance} where items are fully in focus. The focus
+ then fades away to fully blurred by the same distance on both the near
+ and far sides.
+\endlist
+For example, a \c{Focus Distance} of 100 and a
+\c{Depth of Field} of 20 means that everything that is between 90
+and 110 units away from the camera will be fully in focus, items at a
+distance of 70-90 and 110-130 units will experiencing variable blurring,
+and everything closer than 70 or farther than 130 will be fully blurred.
+
+To make it easier to set up this effect, turn on the
+\c{Debug Focus Rendering} checkbox for the effect:
+\image Effects-DOF-Debug.png
+
+When enabled the scene will switch to a mode showing the amount of blur
+to be applied. Anything completely fogged in white will be fully
+blurred, anything that is fully black will be fully in focus, and shades
+of grey represent varying amounts of blur in between. You will find it
+far easier to turn on this mode and just scrub the values in the
+Inspector palette until the content you want is bracketed, compared to
+performing distance calculations and entering numbers.
+
+\section1 Using Tilt Shift
+
+\image Effects-TiltShift.png
+
+The \"Tilt Shift\" effect simulates depth of field in a much simpler
+(and more performant) manner. Instead of blurring based on the depth
+buffer, it simply blurs everything except for horizontal stripe on the
+layer. The effect is controlled by the properties:
+
+\list
+\li
+ \c{Focus Position} - the vertical placement of the center of
+ effect (the 'focused region') on the screen, from top to bottom.
+\li
+ \c{Focus Width} - the vertical size of the in-focus region.
+\li
+ \c{Blur Amount} - how much the not-in-focus regions are blurred.
+\endlist
+As with the Depth of Field effect, this effect has a
+\c{Debug Rendering} option that you can enable to see where the
+blur will be applied to the Layer. (See above for further description.)
+\image Effects-TiltShift-Debug.png
+
+\section1 Using Gaussian Blur
+
+\image Effects-GaussianBlur.png
+
+The \"Gaussian Blur\" effect is one of the simplest to use and
+understand. Drop it on a Layer and adjust the \c{Blurriness}
+property in the Inspector palette. In order to keep the effect
+performant large blur values will produce a mosaic result instead of
+smooth blurriness. Play with the slider for the value to find the best
+visual result for your needs.
+
+\section1 Using Motion Blur
+
+\image Effects-MotionBlur.png
+
+The \"Motion Blur\" effect takes the image from the previous frame,
+blurs it, fades it by a specified amount, and draws this \e{in the
+transparent areas of the layer}. The end result is that items moving
+over a transparent background will leave a ghost behind them.
+
+The caveats for this effect are implicit in the above description:
+
+\list
+\li
+ The contents are slightly blurred, which (as shown in the image above)
+ can cause static (and even slowly-moving) items to have a halo around
+ them.
+\li
+ Only the transparent regions are drawn to. If a moving object passes
+ in front of another object on the same layer, there will be no motion
+ trail passing over the object.
+\endlist
+In the simple image shown above the blue ring is placed on a second
+Layer underneath the Layer with the motion blur effect applied. This
+both allows the 'needle' to leave a blur trail over top of the ring, and
+also prevents the ring from having a blurry blue halo around it.
+
+*/
diff --git a/doc/src/10-best-practices/practices-index.qdoc b/doc/src/10-best-practices/practices-index.qdoc
new file mode 100644
index 00000000..fe46fcbe
--- /dev/null
+++ b/doc/src/10-best-practices/practices-index.qdoc
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Best Practices
+\group qt3dstudio-best-practices
+\noautolist
+
+\section1 Contents
+//! [toc]
+\list
+\li \l {Dynamic Keyframes}
+\li \l {Optimizing Images}
+\li \l {Anti-Aliasing}
+\li \l {Creating Optimized Presentations}
+\li \l {Using Sub-Presentations}
+\li \l {Using Scale Modes}
+\li \l {Disable Depth Test}
+\li \l {Blend Mode}
+\li \l {Creating Binary Presentations}
+\li \l {Working with 3D Content}
+\li \l {Applying Layer Effects}
+\endlist
+//! [toc]
+
+
+*/
diff --git a/doc/src/11-quick-start-guides/10-getting-started.qdoc b/doc/src/11-quick-start-guides/10-getting-started.qdoc
new file mode 100644
index 00000000..cf454ca6
--- /dev/null
+++ b/doc/src/11-quick-start-guides/10-getting-started.qdoc
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Getting Started
+\page getting-started.html
+\ingroup qt3dstudio-quick-start-guides
+
+\section1 Introduction
+This guide will teach you how to create your first Qt 3D Studio project. Additionally it will
+explain the basics of assets, slides, layers, the timeline, and components.
+
+When you run Qt 3D Studio for the first time you will be greeted by the welcome screen.
+Read through the slides.
+
+\image welcomeScreen.png "Qt 3D Studio Welcome screen"
+
+\section1 Creating a New Project
+
+When you have read through the welcome screen slides, select \e{Create New} on the last slide to
+create a new project.
+
+\image createNewProject.png "Create new project"
+
+You can also create a new project after closing the welcome screen by selecting
+\e{Create New Project}.
+
+\image createNewProject2.png "Create new project"
+
+Then browse to the location in your file system where you want to create your project and
+give your project a name. Your project file (\c{.uip}) and project folder will be
+named accordingly.
+
+It is recommended to check the \e{Create directory for project} check box. This will create a new
+folder with the project name. Inside the folder a pre-defined project folder structure is created.
+
+\image newProjectDialog.png "Create new project dialog window"
+
+\section1 Adding Assets
+Create your 2D, 3D, and other assets in your favorite software and then use Qt 3D Studio
+to add them to your presentation.
+
+You can add new assets to your project by dragging the files from the file system to the
+\e{project palette}. This will create a copy of the file in the project folder structure.
+The original file will \b always remain untouched.
+
+Once added to the project you can start using the assets by dragging them to either a layer in the
+\e{timeline palette} or to the \e{scene view}.
+
+\raw HTML
+<a href="images/addAssets.png">
+\endraw
+\image addAssets.png "Add assets to a project"
+\raw HTML
+</a>
+\endraw
+
+\section2 Sample Assets
+
+You can access sample assets from the bottom of the \e{project palette}.
+
+\image sampleAssets.png "Sample assets"
+
+Clicking any of the icons will open corresponding sample asset library in the file system.
+Add sample assets by dragging them to the \e{project palette}. This will create a copy of
+the file in the project folder structure. The original file will \b always remain untouched.
+
+\section2 Related Content
+
+\table
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{studio-project-palette.html} {Studio: Project Palette}
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{best-practices-importing-3d-content.html} {Best Practices: Working with 3D Content}
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{best-practices-optimizingimages.html} {Best Practices: Optimizing images}
+\endtable
+
+\section1 Working with Objects
+
+Once added to the layer you can start working with your object.
+
+\section2 Basic Properties
+Clicking the object in the \e{timeline palette} will bring up the object basic properties in
+the \e{inspector palette}. The basic properties includes scaling, rotating and positioning
+of the object.
+
+\section2 Material
+By clicking the black arrow on the left side of the object name in the
+\e{timeline palette} you will toggle the visibility of the \e{Material} tab.
+Once visible you can click \e{Material} to show lighting and material properties for
+the object in the \e{inspector palette}. These properties includes object colors,
+textures and maps.
+
+\image objectTimeline.png "Object in timeline"
+
+\section2 Related Content
+
+\table
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{studio-inspector-palette.html#material} {Studie: Inspector Palette: Material}
+\endtable
+
+\section1 Slides
+
+\section2 Master Slide
+Each scene and component has one \e{master slide}. Elements located on the \e{master slide}
+have their name displayed in green both in the \e{timeline palette} and the \e{inspector palette}.
+Elements placed on the \e{master slide} exist on all slides of that scene or component.
+
+\section2 Slides
+In addition to the \e{master slide} each scene and component in a project have one or more
+\e{slide}.
+
+These slides can be thought of as states or transitions between states that show small changes or
+completely different views when moving between them.
+\section2 Editing Slides
+
+The active slide is displayed in a light grey color while inactive slides are displayed in a dark
+grey color. You can make a slide active by clicking on it.
+
+\image slidePalette.png "Slide palette"
+
+You can right-click on a slide to perform the following commands:
+\list
+ \li
+ \c{New slide}
+ \li
+ \c{Duplicate slide}
+ \li
+ \c{Delete slide}
+\endlist
+
+To edit the \e{master slide} click the \e{Edit Master} button.
+
+You can change the \c{play mode} and \c{initial play state} properties for the active slide from
+the \e{inspector palette}.
+
+\section2 Play Modes for Slide Transition
+
+\c{Play mode} controls what happens when the playhead reaches the end time for the slide.
+The following options are available:
+
+\list
+ \li
+ \c{Stop at end} - The playhead will stop at the end time. This is the default value.
+ \li
+ \c{Looping} - When reaching the end time the playhead will jump to start time and start
+ playing again.
+ \li
+ \c{PingPong} - When reaching the end time the playhead will start playing backwards until
+ reaching the start time again where it will start playing forward again.
+ \li
+ \c{Ping} - Similar to \c{PingPong} but when the playhead returns to the start time it will
+ stop.
+ \li
+ \c{Play Through To} - When reaching the end time the scene or component will jump to
+ another slide.
+\endlist
+
+\image slidePlayMode.png "Slide play mode and initial play state"
+
+\section2 Initial Play State
+
+This controls if the playhead should start playing immediately when entering the active slide.
+
+\section2 Related Content
+\table
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{studio-slide-palette.html} {Studio: Slide Palette}
+\endtable
+
+\section1 Layers and the Timeline Palette
+
+The \e{timeline palette} provides direct access to all elements in your
+scene, including those not producing a visible result, and also gives you control over the
+animation and timing within a slide.
+
+The \e{timeline palette} is comprised of two connected sections:
+the \e{scene graph} on the left side and the \e{animation portion} on the right side.
+
+Elements and animated properties that are present on the \e{master slide} have their name
+displayed in green while elements that are only present on the current slide have their
+name displayed in light grey color.
+
+The basic elements of the \e{timeline palette} are:
+\list
+ \li
+ \c{Time bars} - Controls the life span of each element.
+ \li
+ \c{Keyframe markers} - Controls the timing of the animation.
+ \li
+ \c{Eyeball icon} - Controls visibility of elements in both the working area and in runtime.
+ \li
+ \c{Shy icon} - Controls visibility of elements in the \e{timeline palette}. Clicking the button
+at the top of this column will toggle the visibility of element rows marked as \e{Shy}.
+\endlist
+
+\image timeline.png "Timeline palette"
+
+\section2 Add a Layer
+
+You can add a layer to your presentation by dragging it from the \e{basic objects palette} to
+either the \e{timeline palette} or the \e{scene view} as described in the
+\l{adding-assets} {adding assets} section. Dragging the layer object to the \e{scene view} will
+always put the layer behind all current layers.
+
+\section2 Related Content
+
+\table
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{studio-timeline-palette.html} {Studio: Timeline Palette}
+\endtable
+
+\section1 Inspector Palette
+
+The \e{inspector palette} is used to control the
+properties of slides, layers and other elements. You can control which properties should be
+animated or changed.
+
+Properties that can be animated have a small stopwatch icon next to them in the
+\e{inspector palette}. Click on the icon to enable/disable animation for the specific property.
+The icon is yellow \inlineimage{animationIconActive.png}
+when animation is enabled and grey \inlineimage{animationIconInactive.png}
+when disabled.
+
+If you want to animate or change the animation of an element that exists on the \e{master slide},
+right-click the \e{stopwatch icon} and select \e{Unlink Property from Master Slide}. The name of
+the property will change from green to light grey and the change/animation will now only affect
+the active slide.
+
+\section2 Related Content
+
+\table
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l{studio-inspector-palette.html} {Studio: Inspector Palette}
+\endtable
+
+\section1 Components
+
+Components are like small scenes. A component has its own set of slides (including a master slide),
+assets on layers, and an independent timeline.
+
+You can control transitions of components with the \c{play mode} and \c{initial play state}
+properties in the \e{inspector palette}.
+
+\image component_timeline.png "Component timeline"
+
+\section2 Create a Component
+Right-click on an element or a group on the \e{layer palette} and choose \e{Make Component}
+from the \e{context menu}.
+
+\section2 Edit a Component
+
+To display and edit the content of a component, double-click the
+\e{component icon} \inlineimage{component_icon.png}
+in the \e{timeline palette}. The \e{timeline} and \e{slide palette} will switch to show the
+content of the component. To leave the component and return to the scene, click on the
+\e{scene} in the top bar of the \e{layers palette}.
+
+\section2 Related Content
+
+\table
+ \row
+ \li \inlineimage moreinfoicon.png
+ \li \l {studio-timeline-palette.html#editing-components}
+ {Studio: Timeline Palette: Editing Components}
+\endtable
+
+*/
diff --git a/doc/src/12-copyright-notices.qdoc b/doc/src/12-copyright-notices.qdoc
new file mode 100644
index 00000000..69abebe5
--- /dev/null
+++ b/doc/src/12-copyright-notices.qdoc
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\page copyright-notices.html
+\title Copyright Notices
+\section1 Third-party Licenses
+
+The following table lists parts (modules) of Qt3DStudio that incorporate code licensed
+under third-party open-source licenses:
+
+\annotatedlist attributions-qt3dstudio
+*/
+
+/*!
+\page qt3dstudio-attribution-freeimage.html attribution
+\ingroup attributions-qt3dstudio
+\brief FreeImage Public License v1.0
+\title FreeImage
+
+The source code version of FreeImage v.3.0 (\"FreeImage\") is available under
+the terms of the FreeImage Public License v.1.0 (\"FreeImage License\").
+
+The Qt Company has not made any modifications to FreeImage. Any terms of the Qt
+3D Studio End User License Agreement which differ from the FreeImage License are
+offered by The Qt Company alone, not by the Initial Developer or any
+Contributor, as respectively defined in the FreeImage License.
+
+\l {https://spdx.org/licenses/FreeImage.html}
+{FreeImage Public License v1.0}
+*/
diff --git a/doc/src/12-cpp-reference/Q3DSElement.qdoc b/doc/src/12-cpp-reference/Q3DSElement.qdoc
new file mode 100644
index 00000000..05d91424
--- /dev/null
+++ b/doc/src/12-cpp-reference/Q3DSElement.qdoc
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Q3DSElement
+ \inheaderfile q3dselement.h
+ \inmodule QtStudio3D
+ \brief Control class for elements in a Qt 3D Studio presentation.
+
+ This class is a convenience class for managing a presentation element.
+
+ \sa Q3DSPresentation, Q3DSWidget, Q3DSSurfaceViewer, Q3DSSceneElement
+*/
+
+/*!
+ \fn Q3DSElement::Q3DSElement(const QString &elementPath, QObject *parent = nullptr)
+
+ Constructs a Q3DSElement instance and initializes the \a elementPath.
+ An optional \a parent object can be specified.
+*/
+
+/*!
+ \fn Q3DSElement::Q3DSElement(Q3DSPresentation *presentation, const QString &elementPath,
+ QObject *parent = nullptr)
+
+ Constructs a Q3DSElement instance and initializes the \a elementPath.
+ The constructed instance is automatically \l{Q3DSPresentation::registerElement}{registered}
+ for the \a presentation.
+ An optional \a parent object can be specified.
+*/
+
+/*!
+ \fn Q3DSElement::Q3DSElement(Q3DSElementPrivate *d, Q3DSPresentation *presentation,
+ const QString &elementPath, QObject *parent = nullptr)
+ \internal
+*/
+
+/*!
+ \property Q3DSElement::elementPath
+
+ Holds the element path of the presentation element.
+ This property must be set before the element is registered to a presentation.
+ You can specify an element of a sub-presentation by adding "SubPresentationId:"
+ in front of the element path, for example \c{"SubPresentationOne:Scene"}.
+
+ \sa Q3DSPresentation::registerElement()
+*/
+
+/*!
+ \fn void Q3DSElement::setAttribute(const QString &attributeName, const QVariant &value)
+
+ Sets the \a value of an attribute on the element specified by this instance.
+ The \a attributeName is the \l{QML Reference: Attribute Names}{scripting name} of the attribute.
+
+ The attribute must be preserved for scripting to be set by this function, or else it will fail.
+ An attribute is preserved if it is either \e{animated}, or
+ \e{an attribute on a master element that is unlinked and changed per-slide}.
+*/
+
+/*!
+ \fn void Q3DSElement::fireEvent(const QString &eventName)
+
+ Dispatches an event with \a eventName on the element specified by this instance.
+ Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
+ method in attached scripts will be executed in response to the event.
+*/
+
diff --git a/doc/src/12-cpp-reference/Q3DSPresentation.qdoc b/doc/src/12-cpp-reference/Q3DSPresentation.qdoc
new file mode 100644
index 00000000..2d9b4c73
--- /dev/null
+++ b/doc/src/12-cpp-reference/Q3DSPresentation.qdoc
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Q3DSPresentation
+ \inheaderfile q3dspresentation.h
+ \inmodule QtStudio3D
+ \brief Control class for Qt 3D Studio presentations.
+
+ This class provides properties and methods for controlling a presentation.
+
+ All methods provided by this class are queued and handled asynchronously before the next
+ frame is displayed.
+
+ You should never construct this class yourself. You can ask for an instance
+ from \l{Q3DSSurfaceViewer::presentation}{Q3DSSurfaceViewer}
+ or \l{Q3DSWidget::presentation}{Q3DSWidget}.
+*/
+
+/*!
+ \fn Q3DSPresentation::Q3DSPresentation(QObject *parent = nullptr)
+ \internal
+*/
+
+/*!
+ \fn Q3DSPresentation::~Q3DSPresentation()
+ \internal
+*/
+
+/*!
+ \property Q3DSPresentation::source
+
+ Holds the presentation source (\c{*.uia} or \c{*.uip}) file location.
+ May be either a file URL or a qrc URL.
+*/
+
+/*!
+ \fn void Q3DSPresentation::registerElement(Q3DSElement *element)
+
+ Registers an \a element for the presentation. The registered \a element can be used to manage
+ the corresponding element in the presentation.
+*/
+
+/*!
+ \fn void Q3DSPresentation::unregisterElement(Q3DSElement *element)
+
+ Unregisters an \a element from the presentation.
+*/
+
+/*!
+ \fn Q3DSElement *Q3DSPresentation::registeredElement(const QString &elementPath) const
+
+ Returns a pointer to a registered element with \a elementPath. If no element with given path
+ is registered, a null pointer is returned.
+*/
+
+/*!
+ \fn void Q3DSPresentation::goToSlide(const QString &elementPath, unsigned int index)
+
+ Requests a time context (a Scene or a Component element) to change to a specific slide by
+ \a index. If the context is already on that slide playback will start over.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \fn void Q3DSPresentation::goToSlide(const QString &elementPath, const QString &name)
+
+ Requests a time context (a Scene or a Component element) to change to a specific slide
+ by \a name. If the context is already on that slide playback will start over.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \fn void Q3DSPresentation::goToSlide(const QString &elementPath, bool next, bool wrap)
+
+ Requests a time context (a Scene or a Component element) to change to the next or the
+ previous slide, depending on the value of \a next. If the context is already at the
+ last or first slide, \a wrap defines if change occurs to the opposite end.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+*/
+
+/*!
+ \fn void Q3DSPresentation::goToTime(const QString &elementPath, float time)
+
+ Sets a time context (a Scene or a Component element) to a specific playback \a time in seconds.
+
+ If \a elementPath points to a time context, that element is controlled. For
+ all other element types the time context owning that element is controlled instead.
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene"}.
+
+ The behavior when specifying a time before 0 or after the end time for the current slide depends
+ on the play mode of the slide:
+ \list
+ \li \c{Stop at End} - values outside the valid time range instead clamp to the boundaries.
+ For example, going to time -5 is the same as going to time 0.
+ \li \c{Looping} - values outside the valid time range mod into the valid range. For example,
+ going to time -4 on a 10 second slide is the same as going to time 6.
+ \li \c{Ping Pong} - values outside the valid time range ‘bounce’ off the ends. For example,
+ going to time -4 is the same as going to time 4 (assuming the time context is at least 4 seconds
+ long), while going to time 12 on a 10 second slide is the same as going to time 8.
+ \li \c{Ping} - values less than 0 are treated as time 0, while values greater than the endtime
+ bounce off the end (eventually hitting 0.)
+ \endlist
+*/
+
+/*!
+ \fn void Q3DSPresentation::setAttribute(const QString &elementPath,
+ const QString &attributeName,
+ const QVariant &value)
+
+ Sets the \a value of an attribute on an element found at \a elementPath. The \a attributeName is
+ the \l{QML Reference: Attribute Names}{scripting name} of the attribute.
+
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene.Mesh.Material"}.
+
+ The attribute must be preserved for scripting to be set by this function, or else it will fail.
+ An attribute is preserved if it is either \e{animated}, or
+ \e{an attribute on a master element that is unlinked and changed per-slide}.
+*/
+
+/*!
+ \fn void Q3DSPresentation::setPresentationActive(const QString &id, bool active)
+
+ Stops or starts updates to a sub-presentation based on the \a active flag. The presentation is
+ referenced to by the \a id, which is the name of the presentation without the \c{.uip}.
+
+ Making a presentation inactive prevents any elements, behaviors, and animations within it from
+ updating. It also prevents any events within that presentation from being processed. It does
+ not, however, prevent the presentation from rendering. An inactive presentation will continue
+ to render using its last-updated information.
+
+ Explicitly inactivating presentations can provide a significant performance increase, depending
+ on the number and size of the presentations that are inactive. Inactive presentations are not
+ ‘paused’. When the presentation is re-activated, animations will resume at the time they should
+ be had they been running, not where they were when the presentation was made inactive.
+*/
+
+/*!
+ \fn void Q3DSPresentation::fireEvent(const QString &elementPath, const QString &eventName)
+
+ Dispatches an event with \a eventName on a specific element found in \a elementPath.
+ Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
+ method in attached scripts will be executed in response to the event.
+
+ You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
+ front of the element path, for example \c{"SubPresentationOne:Scene.Mesh"}.
+*/
+
+/*!
+ \fn void Q3DSPresentation::setGlobalAnimationTime(qint64 milliseconds)
+
+ Sets the global animation time to \a milliseconds. Setting the global animation time to a
+ non-zero value will disable the automatic animation timer. Setting the value to zero
+ resumes automatic animation timer.
+*/
+
+/*!
+ \fn void Q3DSPresentation::slideEntered(const QString &elementPath, unsigned int index, const QString &name)
+
+ This signal is emitted when a slide is entered in the presentation.
+ The \a elementPath specifies the time context (a Scene or a Component element) owning the
+ entered slide.
+ The \a index and \a name contain the index and the name of the entered slide.
+*/
+
+/*!
+ \fn void Q3DSPresentation::slideExited(const QString &elementPath, unsigned int index, const QString &name)
+
+ This signal is emitted when a slide is exited in the presentation.
+ The \a elementPath specifies the time context (a Scene or a Component element) owning the
+ exited slide.
+ The \a index and \a name contain the index and the name of the exited slide.
+*/
+
+/*!
+ \fn void Q3DSPresentation::mousePressEvent(QMouseEvent *e)
+
+ Passes a mouse press event \a e to the presentation. This will send \c onPressureDown event to
+ the element at the coordinates specified by the event.
+*/
+
+/*!
+ \fn void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e)
+
+ Passes a mouse release event \a e to the presentation. This will send \c onPressureUp and
+ \c onTap events to the element at the coordinates specified by the event.
+*/
+
+/*!
+ \fn void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e)
+
+ Passes a mouse move event \a e to the presentation.
+ Currently it is not possible to react to this event in the presentation.
+*/
+
+/*!
+ \fn void Q3DSPresentation::wheelEvent(QWheelEvent *e)
+
+ Passes a wheel event \a e to the presentation.
+ An attached script can register callbacks for \c onHorizontalScrollWheel and
+ \c onVerticalScrollWheel events to handle wheel events.
+
+ \note registerForEvent() method has not been implemented yet in Qt 3D Studio early access
+ release.
+*/
+
+/*!
+ \fn void Q3DSPresentation::keyPressEvent(QKeyEvent *e)
+
+ Passes a key press event \a e to the presentation.
+ An attached script can register callback for \c onKeyDown event to handle key presses.
+
+ \note registerForEvent() method has not been implemented yet in Qt 3D Studio early access
+ release.
+*/
+
+/*!
+ \fn void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
+
+ Passes a key release event \a e to the presentation.
+ An attached script can register callback for \c onKeyUp event to handle key releases.
+
+ \note registerForEvent() method has not been implemented yet in Qt 3D Studio early access
+ release.
+*/
diff --git a/doc/src/12-cpp-reference/Q3DSSceneElement.qdoc b/doc/src/12-cpp-reference/Q3DSSceneElement.qdoc
new file mode 100644
index 00000000..fc4bb97b
--- /dev/null
+++ b/doc/src/12-cpp-reference/Q3DSSceneElement.qdoc
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Q3DSSceneElement
+ \inheaderfile q3dssceneelement.h
+ \inmodule QtStudio3D
+ \brief Control class for scene and component elements in a Qt 3D Studio presentation.
+
+ This class is a convenience class for managing the slides of a single
+ time context (a Scene or a Component element) of a presentation.
+
+ \sa Q3DSPresentation, Q3DSWidget, Q3DSSurfaceViewer
+*/
+
+/*!
+ \fn Q3DSSceneElement::Q3DSSceneElement(const QString &elementPath,
+ QObject *parent = nullptr)
+
+ Constructs a Q3DSSceneElement instance and initializes the \a elementPath.
+ An optional \a parent object can be specified.
+*/
+
+/*!
+ \fn Q3DSSceneElement::Q3DSSceneElement(Q3DSPresentation *presentation,
+ const QString &elementPath,
+ QObject *parent = nullptr)
+
+ Constructs a Q3DSSceneElement instance and initializes the \a elementPath.
+ The constructed instance is automatically \l{Q3DSPresentation::registerElement}{registered}
+ for the \a presentation.
+ An optional \a parent object can be specified.
+*/
+
+/*!
+ \property Q3DSSceneElement::currentSlideIndex
+
+ Holds the index of the currently active slide of the tracked time context.
+
+ Changing the current slide via this property is asynchronous. The property
+ value will not actually change until the next frame has been processed, and
+ even then only if the new slide was valid.
+
+ \note If this property is set to something else than the default slide for the scene at the
+ initial declaration of SceneElement, you will still get an extra changed signal for the
+ default slide before the slide changes to the desired one. This happens in order to ensure
+ we end up with the index of the slide that is actually shown even if the slide specified in the
+ initial declaration is invalid.
+*/
+
+/*!
+ \property Q3DSSceneElement::previousSlideIndex
+
+ Holds the index of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
+
+/*!
+ \property Q3DSSceneElement::currentSlideName
+
+ Holds the name of the currently active slide of the tracked time context.
+
+ Changing the current slide via this property is asynchronous. The property
+ value will not actually change until the next frame has been processed, and
+ even then only if the new slide was valid.
+
+ \note If this property is set to something else than the default slide for the scene at the
+ initial declaration of SceneElement, you will still get an extra changed signal for the
+ default slide before the slide changes to the desired one. This happens in order to ensure
+ we end up with the name of the slide that is actually shown even if the slide specified in the
+ initial declaration is invalid.
+*/
+
+/*!
+ \property Q3DSSceneElement::previousSlideName
+
+ Holds the name of the previously active slide of the tracked time context.
+
+ This property is read-only.
+*/
+
+/*!
+ \fn void Q3DSSceneElement::goToSlide(bool next, bool wrap)
+
+ Requests the time context specified by this scene to change to the next or the
+ previous slide, depending on the value of \a next. If the context is already at the
+ last or first slide, \a wrap defines if change occurs to the opposite end.
+*/
+
+/*!
+ \fn void Q3DSSceneElement::goToTime(float time)
+
+ Sets the time context specified by this scene to a specific playback \a time in seconds.
+
+ For behavior details, see Q3DSPresentation::goToTime() documentation.
+*/
diff --git a/doc/src/12-cpp-reference/Q3DSSurfaceViewer.qdoc b/doc/src/12-cpp-reference/Q3DSSurfaceViewer.qdoc
new file mode 100644
index 00000000..f80e1dbf
--- /dev/null
+++ b/doc/src/12-cpp-reference/Q3DSSurfaceViewer.qdoc
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Q3DSSurfaceViewer
+ \inheaderfile q3dssurfaceviewer.h
+ \inmodule QtStudio3D
+ \brief Displays a Qt 3D Studio presentation on a surface.
+
+ Q3DSSurfaceViewer is used to specify a render surface for Qt 3D Studio presentation.
+ Supported surface types are QOffscreenSurface and QWindow.
+
+ \section2 Example Usage
+
+ \code
+ // Create a surface
+ QWindow window;
+ window.setSurfaceType(QSurface::OpenGLSurface);
+ window.create();
+
+ // Create an OpenGL context
+ QOpenGLContext context;
+ context.setFormat(window.format());
+ context.create();
+
+ // Create the viewer
+ Q3DSSurfaceViewer viewer;
+ viewer.presentation()->setSource(QUrl(QStringLiteral("qrc:/my_presentation.uip")));
+ viewer.setUpdateInterval(0);
+ viewer.settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ viewer.settings()->setShowRenderStats(true);
+
+ // Register a scene object for slide management (optional)
+ Q3DSSceneElement scene(viewer.presentation(), QStringLiteral("Scene"));
+
+ // Register an element object for attribute setting (optional)
+ Q3DSElement element(viewer.presentation(), QStringLiteral("Scene.Layer.myLabel"));
+
+ viewer.initialize(&window, &context);
+ \endcode
+
+ \sa Q3DSWidget
+*/
+
+/*!
+ \property Q3DSSurfaceViewer::size
+
+ Holds the desired size of the presentation.
+
+ The default value is (-1, -1).
+
+ \sa autoSize
+*/
+
+/*!
+ \property Q3DSSurfaceViewer::autoSize
+
+ Specifies whether the viewer should change the size of the presentation automatically
+ to match the surface size when surface size changes.
+ The \l{Q3DSSurfaceViewer::size}{size} property is updated automatically whenever the viewer
+ is \l{Q3DSSurfaceViewer::update()}{updated} if this property value is \c{true}.
+
+ \note For QOffscreenSurface, the surface size is typically 1x1, so generally you will want
+ to set autoSize to \c false when using offscreen surfaces.
+
+ The default value is \c{true}.
+*/
+
+/*!
+ \property Q3DSSurfaceViewer::updateInterval
+
+ Holds the viewer update interval in milliseconds. If the value is negative, the viewer doesn't
+ update the presentation automatically.
+
+ The default value is -1.
+
+ \sa update()
+*/
+
+/*!
+ \property Q3DSSurfaceViewer::running
+
+ The value of this property is \c true when the viewer has been initialized and the presentation
+ is running.
+
+ This property is read-only.
+*/
+
+/*!
+ \fn bool Q3DSSurfaceViewer::initialize(QSurface *surface, QOpenGLContext *context, GLuint fboId)
+
+ Initializes Q3DSSurfaceViewer to render the presentation to the given \a surface using
+ the \a context and optional framebuffer id (\a fboId). If \a fboId is omitted, it defaults
+ to zero.
+
+ The source property of the attached presentation must be set before the viewer can be
+ initialized.
+
+ Returns whether the initialization succeeded.
+
+ \sa running, Q3DSPresentation::source, presentation()
+*/
+
+/*!
+ \fn QImage Q3DSSurfaceViewer::grab(const QRect &rect)
+
+ Grabs the data rendered to the framebuffer into an image using the given \a rect.
+ The \a rect parameter is optional. If it is omitted, the whole framebuffer is captured.
+*/
+
+/*!
+ \fn int Q3DSSurfaceViewer::fboId() const
+
+ Returns the framebuffer id given in initialization.
+
+ \sa initialize()
+*/
+
+/*!
+ \fn QSurface *Q3DSSurfaceViewer::surface() const
+
+ Returns the surface given in initialization.
+
+ \sa initialize()
+*/
+
+/*!
+ \fn QOpenGLContext *Q3DSSurfaceViewer::context() const
+
+ Returns the context given in initialization.
+
+ \sa initialize()
+*/
+
+/*!
+ \fn Q3DSViewerSettings *Q3DSSurfaceViewer::settings() const
+
+ Returns the settings object used by the Q3DSSurfaceViewer.
+*/
+
+/*!
+ \fn Q3DSPresentation *Q3DSSurfaceViewer::presentation() const
+
+ Returns the presentation object used by the Q3DSSurfaceViewer.
+*/
+
+/*!
+ \fn Q3DSSurfaceViewer::update()
+
+ Updates the surface viewer with a new frame.
+*/
+
+/*!
+ \fn Q3DSSurfaceViewer::shutdown()
+
+ Deallocates all resources of the viewer.
+*/
+
+/*!
+ \fn Q3DSSurfaceViewer::reset()
+
+ Deallocates and recreates all resources of the viewer and sets the presentation time
+ back to the beginning.
+*/
+
diff --git a/doc/src/12-cpp-reference/Q3DSViewerSettings.qdoc b/doc/src/12-cpp-reference/Q3DSViewerSettings.qdoc
new file mode 100644
index 00000000..d4029e3e
--- /dev/null
+++ b/doc/src/12-cpp-reference/Q3DSViewerSettings.qdoc
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Q3DSViewerSettings
+ \inheaderfile q3dsviewersettings.h
+ \inmodule QtStudio3D
+ \brief Qt 3D Studio presentation viewer settings.
+
+ Q3DSViewerSettings provides properties to define presentation independent viewer settings.
+
+ You should never construct this class yourself. You can ask for an instance
+ from \l{Q3DSSurfaceViewer::settings}{Q3DSSurfaceViewer}
+ or \l{Q3DSWidget::settings}{Q3DSWidget}.
+*/
+
+/*!
+ \fn Q3DSViewerSettings::Q3DSViewerSettings(QObject *parent = nullptr)
+ \internal
+*/
+
+/*!
+ \fn Q3DSViewerSettings::~Q3DSViewerSettings()
+ \internal
+*/
+
+/*!
+ \property Q3DSViewerSettings::matteColor
+
+ Specifies the color of the viewer area not occupied by the presentation.
+ Default value is black.
+*/
+
+/*!
+ \property Q3DSViewerSettings::showRenderStats
+
+ If this property is set to \c{true}, render statistics are displayed on the upper part
+ of the viewer.
+ Default value is \c{false}.
+*/
+
+/*!
+ \property Q3DSViewerSettings::shadeMode
+
+ The shading mode used for the viewed presentation.
+ The default value is \c{ShadeModeShaded}.
+*/
+
+/*!
+ \property Q3DSViewerSettings::scaleMode
+
+ The scaling mode used for the viewer presentation.
+ The default value is \c{ScaleModeCenter}.
+*/
+
+/*!
+ \enum Q3DSViewerSettings::ShadeMode
+
+ This enumeration specifies the possible shading modes.
+
+ \value ShadeModeShaded The objects in the presentation are shaded normally.
+ \value ShadeModeShadedWireframe The objects in the presentation are shaded
+ with a super-imposed wireframe on top of the normal shading. Only objects that specify
+ a tesselation mode will display this wireframe.
+*/
+
+/*!
+ \enum Q3DSViewerSettings::ScaleMode
+
+ This enumeration specifies the possible scaling modes.
+
+ \value ScaleModeFit Scales the presentation to fit the viewer.
+ \value ScaleModeFill Scales the presentation to fill the viewer.
+ \value ScaleModeCenter Centers the presentation into the viewer without scaling it.
+*/
+
+/*!
+ \fn void Q3DSViewerSettings::save(const QString &group, const QString &organization = QString(),
+ const QString &application = QString())
+
+ Persistently saves the viewer \l{QSettings}{settings} using \a group, \a organization and
+ \a application.
+*/
+
+/*!
+ \fn void Q3DSViewerSettings::load(const QString &group, const QString &organization = QString(),
+ const QString &application = QString())
+
+ Loads previously saved viewer \l{QSettings}{settings} using \a group, \a organization and
+ \a application.
+*/
diff --git a/doc/src/12-cpp-reference/Q3DSWidget.qdoc b/doc/src/12-cpp-reference/Q3DSWidget.qdoc
new file mode 100644
index 00000000..c7b4c4d1
--- /dev/null
+++ b/doc/src/12-cpp-reference/Q3DSWidget.qdoc
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Q3DSWidget
+ \inheaderfile q3dswidget.h
+ \inmodule QtStudio3D
+ \brief Displays a Qt 3D Studio presentation on a widget.
+
+ Q3DSWidget is used to specify a render widget for Qt 3D Studio presentation.
+
+ \section2 Example Usage
+
+ \code
+ Q3DSWidget viewer;
+ viewer.presentation()->setSource(QUrl(QStringLiteral("qrc:/my_presentation.uip")));
+ viewer.setUpdateInterval(0);
+ viewer.settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ viewer.settings()->setShowRenderStats(true);
+
+ // Register a scene element object for slide management (optional)
+ Q3DSSceneElement scene(viewer.presentation(), QStringLiteral("Scene"));
+
+ // Register an element object for attribute setting (optional)
+ Q3DSElement element(viewer.presentation(), QStringLiteral("Scene.Layer.myLabel"));
+
+ viewer.initialize();
+ \endcode
+
+ \sa Q3DSSurfaceViewer
+*/
+
+/*!
+ \property Q3DSWidget::updateInterval
+
+ Holds the viewer update interval in milliseconds. If the value is negative, the viewer doesn't
+ update the presentation automatically.
+
+ The default value is -1.
+
+ \sa QWidget::update()
+*/
+
+/*!
+ \property Q3DSWidget::running
+
+ The value of this property is \c true when the viewer has been initialized and the presentation
+ is running.
+
+ This property is read-only.
+*/
+
+/*!
+ \fn bool Q3DSWidget::initialize()
+
+ Initializes Q3DSWidget to render the presentation.
+
+ The source property of the attached presentation must be set before the viewer can be
+ initialized.
+
+ Returns whether the initialization succeeded.
+
+ \sa running, Q3DSPresentation::source, presentation()
+*/
+
+/*!
+ \fn Q3DSViewerSettings *Q3DSWidget::settings() const
+
+ Returns the settings object used by the Q3DSWidget.
+*/
+
+/*!
+ \fn Q3DSPresentation *Q3DSWidget::presentation() const
+
+ Returns the presentation object used by the Q3DSWidget.
+*/
+
+/*!
+ \fn Q3DSWidget::shutdown()
+
+ Deallocates all resources of the viewer.
+*/
+
+/*!
+ \fn Q3DSWidget::reset()
+
+ Deallocates and recreates all resources of the viewer and sets the presentation time
+ back to the beginning.
+*/
+
+/*!
+ \fn Q3DSWidget::mousePressEvent(QMouseEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::mouseReleaseEvent(QMouseEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::mouseMoveEvent(QMouseEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::wheelEvent(QWheelEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::keyPressEvent(QKeyEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::keyReleaseEvent(QKeyEvent *event)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::initializeGL()
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::resizeGL(int w, int h)
+ \reimp
+*/
+
+/*!
+ \fn Q3DSWidget::paintGL()
+ \reimp
+*/
+
diff --git a/doc/src/12-cpp-reference/cpp-index.qdoc b/doc/src/12-cpp-reference/cpp-index.qdoc
new file mode 100644
index 00000000..8503f28b
--- /dev/null
+++ b/doc/src/12-cpp-reference/cpp-index.qdoc
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module QtStudio3D
+ \title Qt 3D Studio C++ Classes
+ \keyword C++ API
+ \ingroup modules
+
+ \brief Qt 3D Studio provides a number of C++ classes to view and control the presentation.
+
+ To include the definitions of the module's classes, use the following directive:
+
+ \badcode
+ #include <QtStudio3D>
+ \endcode
+
+ To link against the module, add this line to your \l qmake \c .pro file:
+
+ \badcode
+ QT += studio3d
+ \endcode
+*/
diff --git a/doc/src/13-contact-us.qdoc b/doc/src/13-contact-us.qdoc
new file mode 100644
index 00000000..e139da02
--- /dev/null
+++ b/doc/src/13-contact-us.qdoc
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+Got questions about Qt 3D Studio? Suggestions or requests for new
+features? We would (truly) love to hear from you.
+
+You can either \l{TODO}{send us an email},
+or visit the \l{TODO}{Qt 3D Studio
+web site} which includes both a Knowledge Base as well as a ticket
+system for filing and tracking your requests.
+
+*/
diff --git a/doc/src/contents.qdoc b/doc/src/contents.qdoc
new file mode 100644
index 00000000..f860c807
--- /dev/null
+++ b/doc/src/contents.qdoc
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\contentspage {Qt 3D Studio}
+\page qt3dstudio-toc.html
+\title Qt 3D Studio TOC
+
+\omit
+This file is used for generating a TOC in a .qch file.
+\endomit
+
+\list
+ \li \l {index.html}{Concepts}
+ \li \l {Studio Index}{Studio}
+ \include studio-index.qdoc toc
+ \li \l {Viewer Index}{Viewer}
+ \include viewer-index.qdoc toc
+ \li \l {QML API}{QML API Reference}
+ \include qml-index.qdoc toc
+ \li \l {C++ API}{C++ API Reference}
+ \include cpp-index.qdoc toc
+ \li \l {Runtime}
+ \include runtime-index.qdoc toc
+ \li \l {File Formats}
+ \include formats-index.qdoc toc
+ \omit
+ TODO: Needs to be checked. Maybe a rewrite, or just remove it all.
+ \li \l {Integrating with Qt 3D Studio}
+ \include integrating-index.qdoc toc
+ \endomit
+ \li \l {Best Practices}
+ \include practices-index.qdoc toc
+ \li \l {Copyright Notices}
+\endlist
+*/
diff --git a/doc/src/images/3D_Content/00_transparentmap.png b/doc/src/images/3D_Content/00_transparentmap.png
new file mode 100644
index 00000000..82ebf4dc
--- /dev/null
+++ b/doc/src/images/3D_Content/00_transparentmap.png
Binary files differ
diff --git a/doc/src/images/3D_Content/01_texture_map.png b/doc/src/images/3D_Content/01_texture_map.png
new file mode 100644
index 00000000..00639254
--- /dev/null
+++ b/doc/src/images/3D_Content/01_texture_map.png
Binary files differ
diff --git a/doc/src/images/3D_Content/01b_modelingStart.png b/doc/src/images/3D_Content/01b_modelingStart.png
new file mode 100644
index 00000000..ac2cfe4d
--- /dev/null
+++ b/doc/src/images/3D_Content/01b_modelingStart.png
Binary files differ
diff --git a/doc/src/images/3D_Content/02_texture_elements.png b/doc/src/images/3D_Content/02_texture_elements.png
new file mode 100644
index 00000000..ea43ac67
--- /dev/null
+++ b/doc/src/images/3D_Content/02_texture_elements.png
Binary files differ
diff --git a/doc/src/images/3D_Content/03_backdropItem.png b/doc/src/images/3D_Content/03_backdropItem.png
new file mode 100644
index 00000000..e1b08cdc
--- /dev/null
+++ b/doc/src/images/3D_Content/03_backdropItem.png
Binary files differ
diff --git a/doc/src/images/3D_Content/04_UVSpace.png b/doc/src/images/3D_Content/04_UVSpace.png
new file mode 100644
index 00000000..35898b17
--- /dev/null
+++ b/doc/src/images/3D_Content/04_UVSpace.png
Binary files differ
diff --git a/doc/src/images/3D_Content/05_TexturedModel.png b/doc/src/images/3D_Content/05_TexturedModel.png
new file mode 100644
index 00000000..84c129b3
--- /dev/null
+++ b/doc/src/images/3D_Content/05_TexturedModel.png
Binary files differ
diff --git a/doc/src/images/3D_Content/07_freezeTransforms.png b/doc/src/images/3D_Content/07_freezeTransforms.png
new file mode 100644
index 00000000..ce5a51a5
--- /dev/null
+++ b/doc/src/images/3D_Content/07_freezeTransforms.png
Binary files differ
diff --git a/doc/src/images/3D_Content/08_adjustPivots.png b/doc/src/images/3D_Content/08_adjustPivots.png
new file mode 100644
index 00000000..92394409
--- /dev/null
+++ b/doc/src/images/3D_Content/08_adjustPivots.png
Binary files differ
diff --git a/doc/src/images/3D_Content/FBX-Maya.png b/doc/src/images/3D_Content/FBX-Maya.png
new file mode 100644
index 00000000..0928120a
--- /dev/null
+++ b/doc/src/images/3D_Content/FBX-Maya.png
Binary files differ
diff --git a/doc/src/images/3D_Content/Item_panel_parenting.png b/doc/src/images/3D_Content/Item_panel_parenting.png
new file mode 100644
index 00000000..4278fe33
--- /dev/null
+++ b/doc/src/images/3D_Content/Item_panel_parenting.png
Binary files differ
diff --git a/doc/src/images/3D_Content/Lists.png b/doc/src/images/3D_Content/Lists.png
new file mode 100644
index 00000000..4b554c52
--- /dev/null
+++ b/doc/src/images/3D_Content/Lists.png
Binary files differ
diff --git a/doc/src/images/3D_Content/Materials_InspectorPalette.png b/doc/src/images/3D_Content/Materials_InspectorPalette.png
new file mode 100644
index 00000000..4de01c85
--- /dev/null
+++ b/doc/src/images/3D_Content/Materials_InspectorPalette.png
Binary files differ
diff --git a/doc/src/images/3D_Content/UVTab.png b/doc/src/images/3D_Content/UVTab.png
new file mode 100644
index 00000000..901fac89
--- /dev/null
+++ b/doc/src/images/3D_Content/UVTab.png
Binary files differ
diff --git a/doc/src/images/3D_Content/center.png b/doc/src/images/3D_Content/center.png
new file mode 100644
index 00000000..522e33b3
--- /dev/null
+++ b/doc/src/images/3D_Content/center.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaMax01.png b/doc/src/images/3D_Content/colladaMax01.png
new file mode 100644
index 00000000..2af41a8a
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaMax01.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaMax02.png b/doc/src/images/3D_Content/colladaMax02.png
new file mode 100644
index 00000000..052748c2
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaMax02.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaMaya01.png b/doc/src/images/3D_Content/colladaMaya01.png
new file mode 100644
index 00000000..c08cc047
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaMaya01.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaMaya02.png b/doc/src/images/3D_Content/colladaMaya02.png
new file mode 100644
index 00000000..fd0f9172
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaMaya02.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaMaya03.png b/doc/src/images/3D_Content/colladaMaya03.png
new file mode 100644
index 00000000..e6b26863
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaMaya03.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaMaya04.png b/doc/src/images/3D_Content/colladaMaya04.png
new file mode 100644
index 00000000..fd946f66
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaMaya04.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaModo01.png b/doc/src/images/3D_Content/colladaModo01.png
new file mode 100644
index 00000000..9b37748b
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaModo01.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaModo02.png b/doc/src/images/3D_Content/colladaModo02.png
new file mode 100644
index 00000000..d14ae073
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaModo02.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaModo03.png b/doc/src/images/3D_Content/colladaModo03.png
new file mode 100644
index 00000000..1150fdc7
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaModo03.png
Binary files differ
diff --git a/doc/src/images/3D_Content/colladaModo04.png b/doc/src/images/3D_Content/colladaModo04.png
new file mode 100644
index 00000000..73e744a7
--- /dev/null
+++ b/doc/src/images/3D_Content/colladaModo04.png
Binary files differ
diff --git a/doc/src/images/3D_Content/export_DragDAE.png b/doc/src/images/3D_Content/export_DragDAE.png
new file mode 100644
index 00000000..333cc268
--- /dev/null
+++ b/doc/src/images/3D_Content/export_DragDAE.png
Binary files differ
diff --git a/doc/src/images/3D_Content/export_diffuseColor.png b/doc/src/images/3D_Content/export_diffuseColor.png
new file mode 100644
index 00000000..7220b4a2
--- /dev/null
+++ b/doc/src/images/3D_Content/export_diffuseColor.png
Binary files differ
diff --git a/doc/src/images/3D_Content/export_dragToScene.png b/doc/src/images/3D_Content/export_dragToScene.png
new file mode 100644
index 00000000..b7257ef6
--- /dev/null
+++ b/doc/src/images/3D_Content/export_dragToScene.png
Binary files differ
diff --git a/doc/src/images/3D_Content/export_exportSettings.png b/doc/src/images/3D_Content/export_exportSettings.png
new file mode 100644
index 00000000..c61dd5df
--- /dev/null
+++ b/doc/src/images/3D_Content/export_exportSettings.png
Binary files differ
diff --git a/doc/src/images/3D_Content/export_project.png b/doc/src/images/3D_Content/export_project.png
new file mode 100644
index 00000000..11ae3141
--- /dev/null
+++ b/doc/src/images/3D_Content/export_project.png
Binary files differ
diff --git a/doc/src/images/3D_Content/export_triangulateMesh.png b/doc/src/images/3D_Content/export_triangulateMesh.png
new file mode 100644
index 00000000..fab96a57
--- /dev/null
+++ b/doc/src/images/3D_Content/export_triangulateMesh.png
Binary files differ
diff --git a/doc/src/images/3D_Content/image_toMaterial.png b/doc/src/images/3D_Content/image_toMaterial.png
new file mode 100644
index 00000000..dadccc38
--- /dev/null
+++ b/doc/src/images/3D_Content/image_toMaterial.png
Binary files differ
diff --git a/doc/src/images/3D_Content/modeling_glow.png b/doc/src/images/3D_Content/modeling_glow.png
new file mode 100644
index 00000000..dd6bb9f1
--- /dev/null
+++ b/doc/src/images/3D_Content/modeling_glow.png
Binary files differ
diff --git a/doc/src/images/3D_Content/modeling_needle.png b/doc/src/images/3D_Content/modeling_needle.png
new file mode 100644
index 00000000..a25ff720
--- /dev/null
+++ b/doc/src/images/3D_Content/modeling_needle.png
Binary files differ
diff --git a/doc/src/images/3D_Content/selectPolys_MakeMaterial.png b/doc/src/images/3D_Content/selectPolys_MakeMaterial.png
new file mode 100644
index 00000000..021b2fdd
--- /dev/null
+++ b/doc/src/images/3D_Content/selectPolys_MakeMaterial.png
Binary files differ
diff --git a/doc/src/images/3D_Content/text01.png b/doc/src/images/3D_Content/text01.png
new file mode 100644
index 00000000..c7a98d2e
--- /dev/null
+++ b/doc/src/images/3D_Content/text01.png
Binary files differ
diff --git a/doc/src/images/3D_Content/text02.png b/doc/src/images/3D_Content/text02.png
new file mode 100644
index 00000000..3c8309b2
--- /dev/null
+++ b/doc/src/images/3D_Content/text02.png
Binary files differ
diff --git a/doc/src/images/3D_Content/text03.png b/doc/src/images/3D_Content/text03.png
new file mode 100644
index 00000000..058b56b5
--- /dev/null
+++ b/doc/src/images/3D_Content/text03.png
Binary files differ
diff --git a/doc/src/images/3D_Content/texture_inspectorPalette.png b/doc/src/images/3D_Content/texture_inspectorPalette.png
new file mode 100644
index 00000000..e3870868
--- /dev/null
+++ b/doc/src/images/3D_Content/texture_inspectorPalette.png
Binary files differ
diff --git a/doc/src/images/3D_Content/texture_selection.png b/doc/src/images/3D_Content/texture_selection.png
new file mode 100644
index 00000000..47efbc33
--- /dev/null
+++ b/doc/src/images/3D_Content/texture_selection.png
Binary files differ
diff --git a/doc/src/images/3D_Content/timeline_material.png b/doc/src/images/3D_Content/timeline_material.png
new file mode 100644
index 00000000..564c030e
--- /dev/null
+++ b/doc/src/images/3D_Content/timeline_material.png
Binary files differ
diff --git a/doc/src/images/AA-GeometryAliasing.png b/doc/src/images/AA-GeometryAliasing.png
new file mode 100644
index 00000000..38751740
--- /dev/null
+++ b/doc/src/images/AA-GeometryAliasing.png
Binary files differ
diff --git a/doc/src/images/AA-ReflectionAliasing.png b/doc/src/images/AA-ReflectionAliasing.png
new file mode 100644
index 00000000..f26ee505
--- /dev/null
+++ b/doc/src/images/AA-ReflectionAliasing.png
Binary files differ
diff --git a/doc/src/images/AA-TextureAliasing.png b/doc/src/images/AA-TextureAliasing.png
new file mode 100644
index 00000000..db8aa193
--- /dev/null
+++ b/doc/src/images/AA-TextureAliasing.png
Binary files differ
diff --git a/doc/src/images/AA-TextureAliasing2.png b/doc/src/images/AA-TextureAliasing2.png
new file mode 100644
index 00000000..b734696e
--- /dev/null
+++ b/doc/src/images/AA-TextureAliasing2.png
Binary files differ
diff --git a/doc/src/images/ApplicationPreferences.png b/doc/src/images/ApplicationPreferences.png
new file mode 100644
index 00000000..0e86ca92
--- /dev/null
+++ b/doc/src/images/ApplicationPreferences.png
Binary files differ
diff --git a/doc/src/images/Component.png b/doc/src/images/Component.png
new file mode 100644
index 00000000..1313ca7e
--- /dev/null
+++ b/doc/src/images/Component.png
Binary files differ
diff --git a/doc/src/images/DDS-Dialog.png b/doc/src/images/DDS-Dialog.png
new file mode 100644
index 00000000..2eb87390
--- /dev/null
+++ b/doc/src/images/DDS-Dialog.png
Binary files differ
diff --git a/doc/src/images/DDS-Formats.png b/doc/src/images/DDS-Formats.png
new file mode 100644
index 00000000..01ac072d
--- /dev/null
+++ b/doc/src/images/DDS-Formats.png
Binary files differ
diff --git a/doc/src/images/DisableDepthTest.png b/doc/src/images/DisableDepthTest.png
new file mode 100644
index 00000000..875b3390
--- /dev/null
+++ b/doc/src/images/DisableDepthTest.png
Binary files differ
diff --git a/doc/src/images/Effects-DOF-Debug.png b/doc/src/images/Effects-DOF-Debug.png
new file mode 100644
index 00000000..b623935c
--- /dev/null
+++ b/doc/src/images/Effects-DOF-Debug.png
Binary files differ
diff --git a/doc/src/images/Effects-DOF.png b/doc/src/images/Effects-DOF.png
new file mode 100644
index 00000000..4061aaf6
--- /dev/null
+++ b/doc/src/images/Effects-DOF.png
Binary files differ
diff --git a/doc/src/images/Effects-FXAA.png b/doc/src/images/Effects-FXAA.png
new file mode 100644
index 00000000..4a0052c3
--- /dev/null
+++ b/doc/src/images/Effects-FXAA.png
Binary files differ
diff --git a/doc/src/images/Effects-GaussianBlur.png b/doc/src/images/Effects-GaussianBlur.png
new file mode 100644
index 00000000..a6da9080
--- /dev/null
+++ b/doc/src/images/Effects-GaussianBlur.png
Binary files differ
diff --git a/doc/src/images/Effects-HDRBloomTonemap.png b/doc/src/images/Effects-HDRBloomTonemap.png
new file mode 100644
index 00000000..8ad677a6
--- /dev/null
+++ b/doc/src/images/Effects-HDRBloomTonemap.png
Binary files differ
diff --git a/doc/src/images/Effects-MotionBlur.png b/doc/src/images/Effects-MotionBlur.png
new file mode 100644
index 00000000..5ca5a987
--- /dev/null
+++ b/doc/src/images/Effects-MotionBlur.png
Binary files differ
diff --git a/doc/src/images/Effects-TiltShift-Debug.png b/doc/src/images/Effects-TiltShift-Debug.png
new file mode 100644
index 00000000..dfea44ef
--- /dev/null
+++ b/doc/src/images/Effects-TiltShift-Debug.png
Binary files differ
diff --git a/doc/src/images/Effects-TiltShift.png b/doc/src/images/Effects-TiltShift.png
new file mode 100644
index 00000000..79dd6a90
--- /dev/null
+++ b/doc/src/images/Effects-TiltShift.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeAdd.png b/doc/src/images/LayerBlendModeAdd.png
new file mode 100644
index 00000000..f3f57df4
--- /dev/null
+++ b/doc/src/images/LayerBlendModeAdd.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeColorburn.png b/doc/src/images/LayerBlendModeColorburn.png
new file mode 100644
index 00000000..b34a93f7
--- /dev/null
+++ b/doc/src/images/LayerBlendModeColorburn.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeColordodge.png b/doc/src/images/LayerBlendModeColordodge.png
new file mode 100644
index 00000000..714058c3
--- /dev/null
+++ b/doc/src/images/LayerBlendModeColordodge.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeMultiply.png b/doc/src/images/LayerBlendModeMultiply.png
new file mode 100644
index 00000000..3f208b7f
--- /dev/null
+++ b/doc/src/images/LayerBlendModeMultiply.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeNormal.png b/doc/src/images/LayerBlendModeNormal.png
new file mode 100644
index 00000000..777963a2
--- /dev/null
+++ b/doc/src/images/LayerBlendModeNormal.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeOverlay.png b/doc/src/images/LayerBlendModeOverlay.png
new file mode 100644
index 00000000..af9db8a5
--- /dev/null
+++ b/doc/src/images/LayerBlendModeOverlay.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeScreen.png b/doc/src/images/LayerBlendModeScreen.png
new file mode 100644
index 00000000..f3f57df4
--- /dev/null
+++ b/doc/src/images/LayerBlendModeScreen.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModeSubtract.png b/doc/src/images/LayerBlendModeSubtract.png
new file mode 100644
index 00000000..f997611f
--- /dev/null
+++ b/doc/src/images/LayerBlendModeSubtract.png
Binary files differ
diff --git a/doc/src/images/LayerBlendModes.png b/doc/src/images/LayerBlendModes.png
new file mode 100644
index 00000000..37e7c1d9
--- /dev/null
+++ b/doc/src/images/LayerBlendModes.png
Binary files differ
diff --git a/doc/src/images/Overview.png b/doc/src/images/Overview.png
new file mode 100644
index 00000000..be9e7f5b
--- /dev/null
+++ b/doc/src/images/Overview.png
Binary files differ
diff --git a/doc/src/images/Runtime-AODistances.jpg b/doc/src/images/Runtime-AODistances.jpg
new file mode 100644
index 00000000..bd7eb449
--- /dev/null
+++ b/doc/src/images/Runtime-AODistances.jpg
Binary files differ
diff --git a/doc/src/images/Runtime-AOSoftnesses.jpg b/doc/src/images/Runtime-AOSoftnesses.jpg
new file mode 100644
index 00000000..ae8551cb
--- /dev/null
+++ b/doc/src/images/Runtime-AOSoftnesses.jpg
Binary files differ
diff --git a/doc/src/images/Runtime-ApplicationScaleMode.png b/doc/src/images/Runtime-ApplicationScaleMode.png
new file mode 100644
index 00000000..f35cb000
--- /dev/null
+++ b/doc/src/images/Runtime-ApplicationScaleMode.png
Binary files differ
diff --git a/doc/src/images/Runtime-CameraModes.png b/doc/src/images/Runtime-CameraModes.png
new file mode 100644
index 00000000..8d3bb123
--- /dev/null
+++ b/doc/src/images/Runtime-CameraModes.png
Binary files differ
diff --git a/doc/src/images/Runtime-LayerSizing.png b/doc/src/images/Runtime-LayerSizing.png
new file mode 100644
index 00000000..036b5cfd
--- /dev/null
+++ b/doc/src/images/Runtime-LayerSizing.png
Binary files differ
diff --git a/doc/src/images/Studio-Action.png b/doc/src/images/Studio-Action.png
new file mode 100644
index 00000000..d981231f
--- /dev/null
+++ b/doc/src/images/Studio-Action.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Alias.png b/doc/src/images/Studio-Basic-Alias.png
new file mode 100644
index 00000000..4ec03b0d
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Alias.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Camera.png b/doc/src/images/Studio-Basic-Camera.png
new file mode 100644
index 00000000..649810b1
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Camera.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Component.png b/doc/src/images/Studio-Basic-Component.png
new file mode 100644
index 00000000..06278830
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Component.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Cone.png b/doc/src/images/Studio-Basic-Cone.png
new file mode 100644
index 00000000..0346bc5c
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Cone.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Cube.png b/doc/src/images/Studio-Basic-Cube.png
new file mode 100644
index 00000000..f5a5e9e4
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Cube.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Cylinder.png b/doc/src/images/Studio-Basic-Cylinder.png
new file mode 100644
index 00000000..c441406c
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Cylinder.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Group.png b/doc/src/images/Studio-Basic-Group.png
new file mode 100644
index 00000000..81728eb2
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Group.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Layer.png b/doc/src/images/Studio-Basic-Layer.png
new file mode 100644
index 00000000..69aac4c0
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Layer.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Light.png b/doc/src/images/Studio-Basic-Light.png
new file mode 100644
index 00000000..be50e424
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Light.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Rectangle.png b/doc/src/images/Studio-Basic-Rectangle.png
new file mode 100644
index 00000000..c068fd1a
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Rectangle.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Sphere.png b/doc/src/images/Studio-Basic-Sphere.png
new file mode 100644
index 00000000..c7914c47
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Sphere.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Text.png b/doc/src/images/Studio-Basic-Text.png
new file mode 100644
index 00000000..ef8067b1
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Text.png
Binary files differ
diff --git a/doc/src/images/Studio-Project-Libraries.png b/doc/src/images/Studio-Project-Libraries.png
new file mode 100644
index 00000000..30d40055
--- /dev/null
+++ b/doc/src/images/Studio-Project-Libraries.png
Binary files differ
diff --git a/doc/src/images/Studio-Project-MissingAsset.png b/doc/src/images/Studio-Project-MissingAsset.png
new file mode 100644
index 00000000..bdd83eaf
--- /dev/null
+++ b/doc/src/images/Studio-Project-MissingAsset.png
Binary files differ
diff --git a/doc/src/images/Studio-SceneView.png b/doc/src/images/Studio-SceneView.png
new file mode 100644
index 00000000..13afa019
--- /dev/null
+++ b/doc/src/images/Studio-SceneView.png
Binary files differ
diff --git a/doc/src/images/Studio-Slide-Main.png b/doc/src/images/Studio-Slide-Main.png
new file mode 100644
index 00000000..e08d61df
--- /dev/null
+++ b/doc/src/images/Studio-Slide-Main.png
Binary files differ
diff --git a/doc/src/images/Studio-Slide-Master.png b/doc/src/images/Studio-Slide-Master.png
new file mode 100644
index 00000000..d0c948ba
--- /dev/null
+++ b/doc/src/images/Studio-Slide-Master.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-ActionBadge.png b/doc/src/images/Studio-Timeline-ActionBadge.png
new file mode 100644
index 00000000..29dc4383
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-ActionBadge.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Animation-Keyframes.png b/doc/src/images/Studio-Timeline-Animation-Keyframes.png
new file mode 100644
index 00000000..60d7a053
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Animation-Keyframes.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Animation.png b/doc/src/images/Studio-Timeline-Animation.png
new file mode 100644
index 00000000..31884923
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Animation.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Breadcrumb.png b/doc/src/images/Studio-Timeline-Breadcrumb.png
new file mode 100644
index 00000000..831abdae
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Breadcrumb.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Eyeball.png b/doc/src/images/Studio-Timeline-Eyeball.png
new file mode 100644
index 00000000..256743ca
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Eyeball.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Interpolation.png b/doc/src/images/Studio-Timeline-Interpolation.png
new file mode 100644
index 00000000..b3b46ded
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Interpolation.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Lock.png b/doc/src/images/Studio-Timeline-Lock.png
new file mode 100644
index 00000000..664a76da
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Lock.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Overview.png b/doc/src/images/Studio-Timeline-Overview.png
new file mode 100644
index 00000000..c96a97e0
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Overview.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-SceneGraph.png b/doc/src/images/Studio-Timeline-SceneGraph.png
new file mode 100644
index 00000000..6b101865
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-SceneGraph.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-Shy.png b/doc/src/images/Studio-Timeline-Shy.png
new file mode 100644
index 00000000..2950b70f
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-Shy.png
Binary files differ
diff --git a/doc/src/images/Studio-Toolbar-Animation.png b/doc/src/images/Studio-Toolbar-Animation.png
new file mode 100644
index 00000000..702989b0
--- /dev/null
+++ b/doc/src/images/Studio-Toolbar-Animation.png
Binary files differ
diff --git a/doc/src/images/Studio-Toolbar-EditCameras.png b/doc/src/images/Studio-Toolbar-EditCameras.png
new file mode 100644
index 00000000..0241df21
--- /dev/null
+++ b/doc/src/images/Studio-Toolbar-EditCameras.png
Binary files differ
diff --git a/doc/src/images/Studio-Toolbar-Playback.png b/doc/src/images/Studio-Toolbar-Playback.png
new file mode 100644
index 00000000..63a69807
--- /dev/null
+++ b/doc/src/images/Studio-Toolbar-Playback.png
Binary files differ
diff --git a/doc/src/images/Studio-Toolbar-Preview.png b/doc/src/images/Studio-Toolbar-Preview.png
new file mode 100644
index 00000000..cb3f7043
--- /dev/null
+++ b/doc/src/images/Studio-Toolbar-Preview.png
Binary files differ
diff --git a/doc/src/images/Studio-Toolbar-Selection.png b/doc/src/images/Studio-Toolbar-Selection.png
new file mode 100644
index 00000000..aaaaa190
--- /dev/null
+++ b/doc/src/images/Studio-Toolbar-Selection.png
Binary files differ
diff --git a/doc/src/images/Studio-Toolbar-Transform.png b/doc/src/images/Studio-Toolbar-Transform.png
new file mode 100644
index 00000000..984a955e
--- /dev/null
+++ b/doc/src/images/Studio-Toolbar-Transform.png
Binary files differ
diff --git a/doc/src/images/Studio-fx.png b/doc/src/images/Studio-fx.png
new file mode 100644
index 00000000..e0a8fecd
--- /dev/null
+++ b/doc/src/images/Studio-fx.png
Binary files differ
diff --git a/doc/src/images/Workflow-Solid.png b/doc/src/images/Workflow-Solid.png
new file mode 100644
index 00000000..d8a6f1ab
--- /dev/null
+++ b/doc/src/images/Workflow-Solid.png
Binary files differ
diff --git a/doc/src/images/add-diffuse-map-subpresentation.png b/doc/src/images/add-diffuse-map-subpresentation.png
new file mode 100644
index 00000000..4ed39f1d
--- /dev/null
+++ b/doc/src/images/add-diffuse-map-subpresentation.png
Binary files differ
diff --git a/doc/src/images/add-diffuse-map.png b/doc/src/images/add-diffuse-map.png
new file mode 100644
index 00000000..0b9c3bf8
--- /dev/null
+++ b/doc/src/images/add-diffuse-map.png
Binary files differ
diff --git a/doc/src/images/addAssets.png b/doc/src/images/addAssets.png
new file mode 100644
index 00000000..7c521360
--- /dev/null
+++ b/doc/src/images/addAssets.png
Binary files differ
diff --git a/doc/src/images/animationIconActive.png b/doc/src/images/animationIconActive.png
new file mode 100644
index 00000000..40c27d94
--- /dev/null
+++ b/doc/src/images/animationIconActive.png
Binary files differ
diff --git a/doc/src/images/animationIconInactive.png b/doc/src/images/animationIconInactive.png
new file mode 100644
index 00000000..c96ca628
--- /dev/null
+++ b/doc/src/images/animationIconInactive.png
Binary files differ
diff --git a/doc/src/images/animationIcons.png b/doc/src/images/animationIcons.png
new file mode 100644
index 00000000..da3ddac0
--- /dev/null
+++ b/doc/src/images/animationIcons.png
Binary files differ
diff --git a/doc/src/images/camera-scale-mode.png b/doc/src/images/camera-scale-mode.png
new file mode 100644
index 00000000..0b5247dc
--- /dev/null
+++ b/doc/src/images/camera-scale-mode.png
Binary files differ
diff --git a/doc/src/images/component_icon.png b/doc/src/images/component_icon.png
new file mode 100644
index 00000000..3ec953d6
--- /dev/null
+++ b/doc/src/images/component_icon.png
Binary files differ
diff --git a/doc/src/images/component_timeline.png b/doc/src/images/component_timeline.png
new file mode 100644
index 00000000..6703a123
--- /dev/null
+++ b/doc/src/images/component_timeline.png
Binary files differ
diff --git a/doc/src/images/createNewProject.png b/doc/src/images/createNewProject.png
new file mode 100644
index 00000000..da75fc1b
--- /dev/null
+++ b/doc/src/images/createNewProject.png
Binary files differ
diff --git a/doc/src/images/createNewProject2.png b/doc/src/images/createNewProject2.png
new file mode 100644
index 00000000..3332e62c
--- /dev/null
+++ b/doc/src/images/createNewProject2.png
Binary files differ
diff --git a/doc/src/images/layer-position-properties.png b/doc/src/images/layer-position-properties.png
new file mode 100644
index 00000000..bb3ce6d1
--- /dev/null
+++ b/doc/src/images/layer-position-properties.png
Binary files differ
diff --git a/doc/src/images/layer-sub-presentation.png b/doc/src/images/layer-sub-presentation.png
new file mode 100644
index 00000000..c706b330
--- /dev/null
+++ b/doc/src/images/layer-sub-presentation.png
Binary files differ
diff --git a/doc/src/images/moreinfoicon.png b/doc/src/images/moreinfoicon.png
new file mode 100644
index 00000000..45f5870f
--- /dev/null
+++ b/doc/src/images/moreinfoicon.png
Binary files differ
diff --git a/doc/src/images/newProjectDialog.png b/doc/src/images/newProjectDialog.png
new file mode 100644
index 00000000..ace26192
--- /dev/null
+++ b/doc/src/images/newProjectDialog.png
Binary files differ
diff --git a/doc/src/images/objectTimeline.png b/doc/src/images/objectTimeline.png
new file mode 100644
index 00000000..630be04a
--- /dev/null
+++ b/doc/src/images/objectTimeline.png
Binary files differ
diff --git a/doc/src/images/presentation-settings.png b/doc/src/images/presentation-settings.png
new file mode 100644
index 00000000..3cbbcede
--- /dev/null
+++ b/doc/src/images/presentation-settings.png
Binary files differ
diff --git a/doc/src/images/presentation-size.png b/doc/src/images/presentation-size.png
new file mode 100644
index 00000000..da243b0f
--- /dev/null
+++ b/doc/src/images/presentation-size.png
Binary files differ
diff --git a/doc/src/images/sampleAssets.png b/doc/src/images/sampleAssets.png
new file mode 100644
index 00000000..f735bb31
--- /dev/null
+++ b/doc/src/images/sampleAssets.png
Binary files differ
diff --git a/doc/src/images/slidePalette.png b/doc/src/images/slidePalette.png
new file mode 100644
index 00000000..f160d5e7
--- /dev/null
+++ b/doc/src/images/slidePalette.png
Binary files differ
diff --git a/doc/src/images/slidePlayMode.png b/doc/src/images/slidePlayMode.png
new file mode 100644
index 00000000..53bcbfdb
--- /dev/null
+++ b/doc/src/images/slidePlayMode.png
Binary files differ
diff --git a/doc/src/images/studio_128.png b/doc/src/images/studio_128.png
new file mode 100644
index 00000000..ae896d0a
--- /dev/null
+++ b/doc/src/images/studio_128.png
Binary files differ
diff --git a/doc/src/images/subpresentation-dialog.png b/doc/src/images/subpresentation-dialog.png
new file mode 100644
index 00000000..8e1f11d5
--- /dev/null
+++ b/doc/src/images/subpresentation-dialog.png
Binary files differ
diff --git a/doc/src/images/timeline.png b/doc/src/images/timeline.png
new file mode 100644
index 00000000..57ce2632
--- /dev/null
+++ b/doc/src/images/timeline.png
Binary files differ
diff --git a/doc/src/images/uia-file.png b/doc/src/images/uia-file.png
new file mode 100644
index 00000000..f1a73e27
--- /dev/null
+++ b/doc/src/images/uia-file.png
Binary files differ
diff --git a/doc/src/images/view-scale-mode.png b/doc/src/images/view-scale-mode.png
new file mode 100644
index 00000000..5c437a26
--- /dev/null
+++ b/doc/src/images/view-scale-mode.png
Binary files differ
diff --git a/doc/src/images/viewer_128.png b/doc/src/images/viewer_128.png
new file mode 100644
index 00000000..19f52b12
--- /dev/null
+++ b/doc/src/images/viewer_128.png
Binary files differ
diff --git a/doc/src/images/welcomeScreen.png b/doc/src/images/welcomeScreen.png
new file mode 100644
index 00000000..2d4c2858
--- /dev/null
+++ b/doc/src/images/welcomeScreen.png
Binary files differ
diff --git a/examples/examples.pro b/examples/examples.pro
new file mode 100644
index 00000000..21a33d48
--- /dev/null
+++ b/examples/examples.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ studio3d
diff --git a/examples/studio3d/qmlbehaviors/qmlbehaviors.uia b/examples/studio3d/qmlbehaviors/qmlbehaviors.uia
new file mode 100644
index 00000000..1f0bb850
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/qmlbehaviors.uia
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://qt.io/qt3dstudio/uia">
+ <assets initial="qmlbehaviors">
+ <presentation id="qmlbehaviors" src="qmlbehaviors.uip"/>
+ </assets>
+
+ <statemachine ref="#logic">
+ <visual-states>
+ <state ref="Initial">
+ <enter>
+ <goto-slide element="main:Scene" rel="next"/>
+ </enter>
+ </state>
+ </visual-states>
+ </statemachine>
+</application>
diff --git a/examples/studio3d/qmlbehaviors/qmlbehaviors.uip b/examples/studio3d/qmlbehaviors/qmlbehaviors.uip
new file mode 100644
index 00000000..2653fc03
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/qmlbehaviors.uip
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Classes >
+ <Behavior id="Billboard" name="Billboard" sourcepath="scripts\Billboard.qml" />
+ <Behavior id="CatchEvents" name="CatchEvents" sourcepath="scripts\CatchEvents.qml" />
+ <Behavior id="Keyboard" name="Keyboard" sourcepath="scripts\Keyboard.qml" />
+ <Behavior id="SineWave" name="SineWave" sourcepath="scripts\SineWave.qml" />
+ <Behavior id="Toggle" name="Toggle" sourcepath="scripts\Toggle.qml" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" >
+ <Behavior id="Billboard_002" class="#Billboard" />
+ </Camera>
+ <Light id="Light" />
+ <Model id="Cube2" >
+ <Material id="Material_001" />
+ <Behavior id="SineWave_001" class="#SineWave" />
+ <Model id="Cube" >
+ <Material id="Material" />
+ <Behavior id="Billboard_001" class="#Billboard" />
+ </Model>
+ </Model>
+ <Model id="Sphere" >
+ <Material id="Material_002" />
+ </Model>
+ <Model id="Rectangle" >
+ <Material id="Material_003" />
+ <Behavior id="Toggle_001" class="#Toggle" />
+ </Model>
+ </Layer>
+ <Behavior id="CatchEvents_001" class="#CatchEvents" />
+ <Behavior id="Keyboard_001" class="#Keyboard" />
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lightambient="0.333333 0 0" lighttype="Directional" rotation="29 36 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="PingPong" >
+ <Add ref="#Billboard_002" name="Billboard" renderCamera="#Cube2" />
+ <Add ref="#Cube2" name="Cube2" position="-410.66 -269.615 131.722" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -410.66 100 100 3.706 514.024 100 100 6.958 -17.5718 100 100 10 -531.565 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 -246.021 100 100 3.706 -141.615 100 100 6.958 394.782 100 100 10 -154.656 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 131.722 100 100 3.706 131.722 100 100 6.958 131.722 100 100 10 131.722 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.x" type="EaseInOut" />
+ <AnimationTrack property="rotation.y" type="EaseInOut" />
+ <AnimationTrack property="rotation.z" type="EaseInOut" />
+ <Action id="Cube2-Action" eyeball="True" triggerObject="#Cube2" event="onPressureDown" targetObject="#SineWave_001" handler="toggle" />
+ </Add>
+ <Add ref="#Material_001" />
+ <Add ref="#SineWave_001" name="SineWave" ampOffset="0" amplitude="45" />
+ <Add ref="#Cube" name="Cube" position="-531.565 -276.656 131.722" scale="1 1 1" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 113.361 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material" name="Material" />
+ <Add ref="#Billboard_001" name="Billboard" billboardType="Face Camera" renderCamera="#Camera" startImmediately="True" yOnly="False" />
+ <Add ref="#Sphere" name="Sphere" position="191.969 4.33009 0" sourcepath="#Sphere" />
+ <Add ref="#Material_002" />
+ <Add ref="#Rectangle" name="Rectangle" position="56.2916 1.44336 0" sourcepath="#Rectangle" />
+ <Add ref="#Material_003" />
+ <Add ref="#Toggle_001" name="Toggle" >
+ <Action id="Toggle-Action" eyeball="True" triggerObject="#Toggle_001" event="onToggle" targetObject="#Material_002" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 0 1" />
+ </Action>
+ <Action id="Toggle-Action_001" eyeball="True" triggerObject="#Toggle_001" event="onUntoggle" targetObject="#Material_002" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="1 1 1" />
+ </Action>
+ </Add>
+ <Add ref="#CatchEvents_001" name="CatchEvents" />
+ <Add ref="#Keyboard_001" name="Keyboard" >
+ <Action id="Keyboard-Action" eyeball="True" triggerObject="#Keyboard_001" event="onLEFTDown" targetObject="#Sphere" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="scale" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="2 2 2" />
+ </Action>
+ <Action id="Keyboard-Action_001" eyeball="True" triggerObject="#Keyboard_001" event="onLEFTUp" targetObject="#Sphere" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="scale" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="1 1 1" />
+ </Action>
+ </Add>
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/examples/studio3d/qmlbehaviors/scripts/Billboard.qml b/examples/studio3d/qmlbehaviors/scripts/Billboard.qml
new file mode 100644
index 00000000..de4ae3f5
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/scripts/Billboard.qml
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*[[
+ <Property name="renderCamera" formalName="Render Camera" type="ObjectRef" default="Scene.Layer.Camera" description="The camera which will be rendering the scene." />
+ <Property name="billboardType" formalName="Billboard Type" type="StringList" default="Face Camera" list="Face Camera,Match Camera Rotation" description="Always face the camera, or only match its rotation." />
+ <Property name="yOnly" formalName="Y-Axis Only?" type="Boolean" default="False" description="Only rotate the object about the global y-axis?" />
+ <Property name="startImmediately" formalName="Start Immediately?" type="Boolean" default="True" publishLevel="Advanced" description="Start immediately, or wait for the Enable action to be called?" />
+
+ <Handler name="start" formalName="Start" category="Billboard" description="Begin keeping the parent object billboarded." />
+ <Handler name="stop" formalName="Stop" category="Billboard" description="Stop rotating the parent object." />
+]]*/
+
+import QtQml 2.2
+
+QtObject {
+ //External:
+ property string renderCamera
+ property string billboardType
+ property bool yOnly
+ property bool startImmediately
+ //Internal:
+ property bool running: false
+ property var updateFunction
+
+ function start() {
+ running = true;
+ }
+
+ function stop() {
+ running = false;
+ }
+
+ function onInitialize() {
+ if (billboardType === "Face Camera") {
+ if (!yOnly)
+ updateFunction = faceCamera;
+ else
+ updateFunction = faceCameraGlobalY;
+ }
+ else {
+ if (!yOnly)
+ updateFunction = matchRotation;
+ else
+ updateFunction = matchRotationGlobalY;
+ }
+
+ if (startImmediately)
+ start();
+ }
+
+ function onUpdate() {
+ if (!running)
+ return;
+
+ updateFunction();
+ }
+
+ function faceCamera() {
+ var cameraTransform = Qt3ds.calculateGlobalTransform(renderCamera);
+ var cameraSpot = cameraTransform.row(3).toVector3d();
+ var myTransform = Qt3ds.calculateGlobalTransform();
+ var mySpot = myTransform.row(3).toVector3d();
+
+ var matrix = Qt3ds.calculateGlobalTransform(Qt3ds.getParent()).inverted();
+ matrix.m41 = 0;
+ matrix.m42 = 0;
+ matrix.m43 = 0;
+
+ var rotateRay = cameraSpot
+ .minus(mySpot)
+ .times(matrix);
+
+ var rotation = Qt3ds.lookAt(rotateRay);
+ setAttributeVector("rotation", rotation);
+ }
+
+ function faceCameraGlobalY() {
+ var cameraTransform = Qt3ds.calculateGlobalTransform(renderCamera);
+ var cameraSpot = cameraTransform.row(3).toVector3d();
+ var myTransform = Qt3ds.calculateGlobalTransform();
+ var mySpot = myTransform.row(3).toVector3d();
+
+ var rotateRay = cameraSpot.minus(mySpot);
+
+ var rotation = getAttributeVector("rotation");
+ rotation.y = Math.atan2(rotateRay.x, rotateRay.z);
+ setAttributeVector("rotation", rotation);
+ }
+
+ function matchRotation() {
+ var cameraTransform = Qt3ds.calculateGlobalTransform(renderCamera);
+ var cameraSpot = cameraTransform.row(3).toVector3d();
+
+ var matrix = Qt3ds.calculateGlobalTransform(Qt3ds.getParent()).inverted();
+ matrix.m41 = 0;
+ matrix.m42 = 0;
+ matrix.m43 = 0;
+
+ var rotateRay = Qt.vector3d(0, 0, 1)
+ .times(cameraTransform)
+ .minus(cameraSpot)
+ .times(matrix);
+
+ var rotation = Qt3ds.lookAt(rotateRay);
+ setAttributeVector("rotation", rotation);
+ }
+
+ function matchRotationGlobalY() {
+ var cameraTransform = Qt3ds.calculateGlobalTransform(renderCamera);
+ var cameraSpot = cameraTransform.row(3).toVector3d();
+
+ var rotateRay = Qt.vector3d(0, 0, 1)
+ .times(cameraTransform)
+ .minus(cameraSpot)
+
+ var rotation = getAttributeVector("rotation");
+ rotation.y = Qt3ds.lookAt(rotateRay).y;
+ setAttributeVector("rotation", rotation);
+ }
+
+ function getAttributeVector(name) {
+ var vec = Qt.vector3d(0, 0, 0);
+ Qt3ds.getAttribute(name + ".x", vec.x);
+ Qt3ds.getAttribute(name + ".y", vec.y);
+ Qt3ds.getAttribute(name + ".z", vec.z);
+ return vec;
+ }
+
+ function setAttributeVector(name, vec) {
+ Qt3ds.setAttribute(name + ".x", vec.x);
+ Qt3ds.setAttribute(name + ".y", vec.y);
+ Qt3ds.setAttribute(name + ".z", vec.z);
+ }
+}
diff --git a/examples/studio3d/qmlbehaviors/scripts/CatchEvents.qml b/examples/studio3d/qmlbehaviors/scripts/CatchEvents.qml
new file mode 100644
index 00000000..f5b14a80
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/scripts/CatchEvents.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml 2.2
+
+QtObject {
+ function onInitialize() {
+ Qt3ds.registerForEvent("onPressureDown", onMouseDown);
+ Qt3ds.registerForEvent("onPressureUp", onMouseUp);
+ }
+
+ function onMouseDown() {
+ console.log("Mouse down!");
+ }
+
+ function onMouseUp() {
+ console.log("Mouse up!");
+ }
+}
diff --git a/examples/studio3d/qmlbehaviors/scripts/DateTime.qml b/examples/studio3d/qmlbehaviors/scripts/DateTime.qml
new file mode 100644
index 00000000..79773dc5
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/scripts/DateTime.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml 2.2
+
+QtObject {
+ function onUpdate() {
+ var date = new Date();
+ var timeString = date.getDate() + "/" + (date.getMonth()+1) + "/" + date.getFullYear()
+ + " " + date.getHours() + ":" + date.getMinutes() + "." + date.getSeconds();
+ Qt3ds.setAttribute("textstring", timeString);
+ }
+}
diff --git a/examples/studio3d/qmlbehaviors/scripts/Keyboard.qml b/examples/studio3d/qmlbehaviors/scripts/Keyboard.qml
new file mode 100644
index 00000000..9a1d86f1
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/scripts/Keyboard.qml
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*[[
+<Event name="onLEFTDown" category="Navigation" />
+<Event name="onLEFTUp" category="Navigation" />
+<Event name="onRIGHTDown" category="Navigation" />
+<Event name="onRIGHTUp" category="Navigation" />
+<Event name="onUPDown" category="Navigation" />
+<Event name="onUPUp" category="Navigation" />
+<Event name="onDOWNDown" category="Navigation" />
+<Event name="onDOWNUp" category="Navigation" />
+]]*/
+
+import QtQml 2.2
+
+QtObject {
+ property var keyNames: ["NOKEY",
+ "ESCAPE",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "0",
+ "SUBTRACT",
+ "EQUALS",
+ "BACK",
+ "TAB",
+ "Q",
+ "W",
+ "E",
+ "R",
+ "T",
+ "Y",
+ "U",
+ "I",
+ "O",
+ "P",
+ "LBRACKET",
+ "RBRACKET",
+ "RETURN",
+ "LCONTROL",
+ "A",
+ "S",
+ "D",
+ "F",
+ "G",
+ "H",
+ "J",
+ "K",
+ "L",
+ "SEMICOLON",
+ "APOSTROPHE",
+ "GRAVE",
+ "LSHIFT",
+ "BACKSLASH",
+ "Z",
+ "X",
+ "C",
+ "V",
+ "B",
+ "N",
+ "M",
+ "COMMA",
+ "PERIOD",
+ "SLASH",
+ "RSHIFT",
+ "MULTIPLY",
+ "LALT",
+ "SPACE",
+ "CAPITAL",
+ "F1",
+ "F2", // 60
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "F9",
+ "F10",
+ "NUMLOCK",
+ "SCROLL", // 70
+ "NUMPAD7",
+ "NUMPAD8",
+ "NUMPAD9",
+ "NUMPADSUBTRACT",
+ "NUMPAD4",
+ "NUMPAD5",
+ "NUMPAD6",
+ "NUMPADADD",
+ "NUMPAD1",
+ "NUMPAD2", // 80
+ "NUMPAD3",
+ "NUMPAD0",
+ "NUMPADDECIMAL",
+ "NOOP",
+ "ZENKAKUHANKAKU",
+ "102ND",
+ "F11",
+ "F12",
+ "F13",
+ "F14", // 90
+ "HIRAGANA",
+ "HENKAN",
+ "KATAKANAHIRAGANA",
+ "MUHENKAN",
+ "KPJPCOMMA",
+ "NUMPADENTER",
+ "RCONTROL",
+ "NUMPADDIVIDE",
+ "PRINTSCREEN",
+ "RALT", // 100
+ "LINEFEED",
+ "HOME",
+ "UP",
+ "PGUP",
+ "LEFT",
+ "RIGHT",
+ "END",
+ "DOWN",
+ "PGDN",
+ "INSERT", // 110
+ "DELETE",
+ "MACRO",
+ "MUTE",
+ "VOLUMEDOWN",
+ "VOLUMEUP",
+ "POWER",
+ "KPEQUAL",
+ "KPPLUSMINUS",
+ "PAUSE",
+ "SCALE"]
+
+ function onInitialize() {
+ Qt3ds.registerForEvent("onKeyDown", onKeyDown);
+ Qt3ds.registerForEvent("onKeyUp", onKeyUp);
+ }
+
+ function onKeyDown(keyCode) {
+ Qt3ds.fireEvent("on" + keyNames[keyCode] + "Down");
+ }
+
+ function onKeyUp(keyCode) {
+ Qt3ds.fireEvent("on" + keyNames[keyCode] + "Up");
+ }
+}
diff --git a/examples/studio3d/qmlbehaviors/scripts/SineWave.qml b/examples/studio3d/qmlbehaviors/scripts/SineWave.qml
new file mode 100644
index 00000000..4aa9daf7
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/scripts/SineWave.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*[[
+ <Property name="attribute" formalName="Attribute Name" description="Attribute on the parent element to change." animatable="False" type="String" default="rotation.x" />
+ <Property name="ampOffset" formalName="Center Value" description="Value to center around." animatable="False" type="Float" default="0" />
+ <Property name="amplitude" formalName="Amplitude" description="Maximum value added to/subtracted from the center." animatable="True" type="Float" default="50" />
+ <Property name="period" formalName="Period" description="Number of seconds to complete one full cycle." animatable="False" type="Float" default="5" />
+ <Property name="timeOffset" formalName="Start Time Offset" description="Start the sine wave at a different point." animatable="False" type="Float" default="0" />
+ <Property name="startImmediately" formalName="Start Immediately?" description="Start immediately or wait for the Start action to be called?" animatable="False" type="Boolean" default="True" />
+
+ <Handler name="start" formalName="Start" description="Start the Sine Wave control of the property." />
+ <Handler name="stop" formalName="Stop" description="Stop the Sine Wave control of the property." />
+ <Handler name="toggle" formalName="Toggle" description="If the behavior is running, stop it; otherwise, start it." />
+
+ <Event name="onStarted" description="Fires when the Sine Wave is started." />
+ <Event name="onStopped" description="Fires when the Sine Wave is stopped." />
+]]*/
+
+import QtQml 2.2
+
+QtObject {
+ //External:
+ property string attribute
+ property real ampOffset
+ property real amplitude
+ property real period
+ property real timeOffset
+ property bool startImmediately
+ //Internal:
+ property bool running: false
+ property bool inDegrees: false
+ property real elapsedTime: 0
+
+ function start() {
+ if (!running) {
+ running = true;
+ Qt3ds.fireEvent("onStarted");
+ }
+ }
+
+ function stop() {
+ if (running) {
+ running = false;
+ Qt3ds.fireEvent("onStopped");
+ }
+ }
+
+ function toggle() {
+ if (running)
+ stop();
+ else
+ start();
+ }
+
+ function onInitialize() {
+ if (attribute.indexOf("rotation") != -1)
+ inDegrees = true;
+
+ if (startImmediately)
+ start();
+ }
+
+ function onUpdate() {
+ if (!running)
+ return;
+
+ if (inDegrees) {
+ ampOffset *= (Math.PI / 180);
+ amplitude *= (Math.PI / 180);
+ }
+
+ elapsedTime += Qt3ds.getDeltaTime();
+ var value = ampOffset + amplitude * Math.cos(elapsedTime * Math.PI * 2 / period);
+ Qt3ds.setAttribute(attribute, value);
+ }
+}
diff --git a/examples/studio3d/qmlbehaviors/scripts/Toggle.qml b/examples/studio3d/qmlbehaviors/scripts/Toggle.qml
new file mode 100644
index 00000000..aa71f264
--- /dev/null
+++ b/examples/studio3d/qmlbehaviors/scripts/Toggle.qml
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*[[
+ <Property name="attribute" formalName="Attribute Name" description="Attribute on the parent element to change." animatable="False" type="String" default="rotation.x" />
+ <Property name="firstValue" formalName="First Value" description="Value when not toggled." animatable="False" type="Float" default="0" />
+ <Property name="secondValue" formalName="Second Value" description="Value when toggled." animatable="False" type="Float" default="1" />
+ <Property name="timerInterval" formalName="Timer Interval" description="Interval for the toggles." animatable="False" type="Float" default="500" />
+ <Property name="startImmediately" formalName="Start Immediately?" description="Start immediately or wait for the Start action to be called?" animatable="False" type="Boolean" default="True" />
+
+ <Handler name="start" formalName="Start" description="Start the toggling." />
+ <Handler name="stop" formalName="Stop" description="Stop the toggling." />
+
+ <Event name="onToggle" description="Fires when toggled." />
+ <Event name="onUntoggle" description="Fires when untoggled." />
+]]*/
+
+import QtQml 2.2
+
+QtObject {
+ //External:
+ property string attribute
+ property real firstValue
+ property real secondValue
+ property real timerInterval
+ property bool startImmediately
+ //Internal:
+ property int index: 0
+ property bool running: false
+ property real timer: 0
+
+ function start() {
+ running = true;
+ Qt3ds.setAttribute(attribute, firstValue);
+ }
+
+ function stop() {
+ running = false;
+ }
+
+ function toggle() {
+ if (index == 0) {
+ Qt3ds.setAttribute(attribute, secondValue);
+ Qt3ds.fireEvent("onToggle");
+ } else if (index == 1) {
+ Qt3ds.setAttribute(attribute, firstValue);
+ Qt3ds.fireEvent("onUntoggle");
+ }
+ index++;
+ if (index > 1)
+ index = 0;
+ }
+
+ function onInitialize() {
+ if (startImmediately)
+ start();
+ }
+
+ function onUpdate() {
+ if (!running)
+ return;
+
+ timer += Qt3ds.getDeltaTime();
+ var interval = timerInterval / 1000;
+ while (timer >= interval) {
+ timer -= interval;
+ toggle();
+ }
+ }
+}
diff --git a/examples/studio3d/qmldynamickeyframes/main.cpp b/examples/studio3d/qmldynamickeyframes/main.cpp
new file mode 100644
index 00000000..adddbdce
--- /dev/null
+++ b/examples/studio3d/qmldynamickeyframes/main.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QGuiApplication>
+#include <QtCore/QDir>
+#include <QtQuick/QQuickView>
+#include <QtQml/QQmlEngine>
+#include <QtCore/QLoggingCategory>
+
+#ifdef USE_EMBEDDED_FONTS
+#include <QtGui/QFontDatabase>
+#include <QtCore/QDebug>
+#endif
+
+int main(int argc, char *argv[])
+{
+#ifdef USE_EMBEDDED_FONTS
+ qputenv("QT_QPA_FONTDIR",".");
+#endif
+
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+#ifdef USE_EMBEDDED_FONTS
+ int fontId = QFontDatabase::addApplicationFont(":/res/Font/TitilliumWeb-Regular.ttf");
+ QStringList loadedFontFamilies = QFontDatabase::applicationFontFamilies(fontId);
+ if (!loadedFontFamilies.empty()) {
+ QString fontName = loadedFontFamilies.at(0);
+ QGuiApplication::setFont(QFont(fontName));
+ } else {
+ qWarning("Error: failed to load font");
+ }
+#endif
+
+ QQuickView viewer;
+
+ viewer.setSource(QUrl("qrc:/main.qml"));
+
+ viewer.setTitle(QStringLiteral("Qt 3D Studio Dynamic Keyframes Example"));
+ viewer.setResizeMode(QQuickView::SizeRootObjectToView);
+ viewer.show();
+
+ return app.exec();
+}
diff --git a/examples/studio3d/qmldynamickeyframes/presentation/dyn_key.uip b/examples/studio3d/qmldynamickeyframes/presentation/dyn_key.uip
new file mode 100644
index 00000000..30696019
--- /dev/null
+++ b/examples/studio3d/qmldynamickeyframes/presentation/dyn_key.uip
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Sphere" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle" >
+ <Material id="Material_001" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_002" />
+ </Model>
+ <Model id="Rectangle3" >
+ <Material id="Material_003" />
+ </Model>
+ <Model id="Rectangle4" >
+ <Material id="Material_004" />
+ </Model>
+ <Model id="Rectangle5" >
+ <Material id="Material_005" />
+ </Model>
+ <Model id="Rectangle6" >
+ <Material id="Material_006" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" endtime="2000" />
+ <Add ref="#Camera" endtime="2000" />
+ <Add ref="#Light" endtime="2000" />
+ <Add ref="#Sphere" name="Sphere" endtime="2000" position="-300 0 0" scale="1 1 1" sourcepath="#Sphere" />
+ <Add ref="#Material" />
+ <State id="Scene-Ball_PingPong" name="Ball_PingPong" playmode="PingPong" >
+ <Set ref="#Layer" endtime="2000" />
+ <Set ref="#Camera" endtime="2000" />
+ <Set ref="#Light" endtime="2000" />
+ <Set ref="#Sphere" endtime="2000" position="-282 0 0" scale="1 1 1" >
+ <AnimationTrack property="position.x" type="EaseInOut" dynamic="True" >0 -300 100 100 2 300 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" dynamic="True" >0 0 100 100 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" dynamic="True" >0 0 100 100 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" dynamic="True" >0 1 100 100 2 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" dynamic="True" >0 1.001 100 100 2 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" dynamic="True" >0 1 100 100 2 1 100 100</AnimationTrack>
+ </Set>
+ <Add ref="#Rectangle" name="Rectangle" endtime="2000" position="-550 -320.429 0" scale="0.1 0.1 0.1" sourcepath="#Rectangle" />
+ <Add ref="#Material_001" />
+ </State>
+ <State id="Scene-Ball_ToCenter+Scale" name="Ball_ToCenter+Scale" playmode="PingPong" playthroughto="Previous" >
+ <Set ref="#Layer" endtime="2000" />
+ <Set ref="#Camera" endtime="2000" />
+ <Set ref="#Light" endtime="2000" />
+ <Set ref="#Sphere" endtime="2000" position="-300 0 0" scale="1 1 1" >
+ <AnimationTrack property="position.x" type="EaseInOut" dynamic="True" >0 -300 0 0 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" dynamic="True" >0 0 0 0 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" dynamic="True" >0 0 0 0 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" dynamic="True" >0 1 0 0 2 3 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" dynamic="True" >0 1 0 0 2 3 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" dynamic="True" >0 1 0 0 2 3 100 100</AnimationTrack>
+ </Set>
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="2000" position="-550 -320.429 0" scale="0.1 0.1 0.1" sourcepath="#Rectangle" />
+ <Add ref="#Material_002" />
+ <Add ref="#Rectangle3" name="Rectangle3" endtime="2000" position="-530 -320.429 0" scale="0.1 0.1 0.1" sourcepath="#Rectangle" />
+ <Add ref="#Material_003" />
+ </State>
+ <State id="Scene-Ball_ToStart+Scale" name="Ball_ToStart+Scale" playmode="PingPong" playthroughto="#Scene-Ball_PingPong" >
+ <Set ref="#Layer" endtime="2000" />
+ <Set ref="#Camera" endtime="2000" />
+ <Set ref="#Light" endtime="2000" />
+ <Set ref="#Sphere" endtime="2000" position="-300 0 0" scale="1 1 1" >
+ <AnimationTrack property="position.x" type="EaseInOut" dynamic="True" >0 363.953 100 100 2 -300 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" dynamic="True" >0 0 100 100 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" dynamic="True" >0 0 100 100 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" dynamic="True" >0 1 100 100 2 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" dynamic="True" >0 1.1 100 100 2 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" dynamic="True" >0 1 100 100 2 1 100 100</AnimationTrack>
+ </Set>
+ <Add ref="#Rectangle4" name="Rectangle4" endtime="2000" position="-550 -320.429 0" scale="0.1 0.1 0.1" sourcepath="#Rectangle" />
+ <Add ref="#Material_004" />
+ <Add ref="#Rectangle5" name="Rectangle5" endtime="2000" position="-530 -320.429 0" scale="0.1 0.1 0.1" sourcepath="#Rectangle" />
+ <Add ref="#Material_005" />
+ <Add ref="#Rectangle6" name="Rectangle6" endtime="2000" position="-510 -320.429 0" scale="0.1 0.1 0.1" sourcepath="#Rectangle" />
+ <Add ref="#Material_006" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/examples/studio3d/qmldynamickeyframes/qml/qmldynamickeyframes/main.qml b/examples/studio3d/qmldynamickeyframes/qml/qmldynamickeyframes/main.qml
new file mode 100644
index 00000000..002d0d84
--- /dev/null
+++ b/examples/studio3d/qmldynamickeyframes/qml/qmldynamickeyframes/main.qml
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtStudio3D 1.0
+
+Item {
+ id: mainview
+ width: 1280
+ height: 768
+ visible: true
+
+ // Qt 3D Studio element
+ //
+ // The presentation displayed in this example consists of three simple slides with ping-pong
+ // animations:
+ //
+ // Slide 1: Move ball to the right side of the screen
+ // Slide 2: Move ball to center of the screen and scale it up
+ // Slide 3: Move ball back to the initial position on the left side of the screen
+ //
+ // Because the animations in the presentation are defined dynamic, the current position
+ // and scale of the ball are used as the initial keyframes for animations whenever
+ // a slide is changed.
+ Studio3D {
+ id: studio3D
+ anchors.fill: parent
+
+ // ViewerSettings item is used to specify presentation independent viewer settings.
+ ViewerSettings {
+ scaleMode: ViewerSettings.ScaleModeFill
+ showRenderStats: false
+ }
+
+ // Presentation item is used to control the presentation.
+ Presentation {
+ source: "qrc:/presentation/dyn_key.uip"
+
+ // SceneElement item is used to listen for slide changes of a scene in the presentation.
+ // You can also change the slides via its properties.
+ SceneElement {
+ id: scene
+ elementPath: "Scene"
+ onCurrentSlideIndexChanged: {
+ console.log("Current slide : " + currentSlideIndex + " ("
+ + currentSlideName + ")");
+ }
+ onPreviousSlideIndexChanged: {
+ console.log("Previous slide: " + previousSlideIndex + " ("
+ + previousSlideName + ")");
+ }
+ }
+
+ // Element item is used to change element attributes
+ Element {
+ id: materialElement
+ elementPath: "Scene.Layer.Sphere.Material"
+ }
+
+ property int desiredSlideIndex: 1
+ property int colorIndex: 0
+ property var colorArray: [
+ [1.0, 1.0, 1.0],
+ [1.0, 0.0, 0.0],
+ [0.0, 1.0, 0.0],
+ [0.0, 0.0, 1.0],
+ [0.0, 1.0, 1.0],
+ [1.0, 0.0, 1.0],
+ [1.0, 1.0, 0.0]
+ ]
+
+ function nextSlide() {
+ // Separate desiredSlideIndex variable is used to keep track of the desired slide,
+ // because SceneElement's currentSlideIndex property works asynchronously.
+ // This way the button click always changes the slide even if you click
+ // it twice during the same frame.
+ desiredSlideIndex = desiredSlideIndex != 3 ? desiredSlideIndex + 1 : 1;
+ scene.currentSlideIndex = desiredSlideIndex
+ slideButtonText.text = "Change Slide (" + desiredSlideIndex + ")"
+ }
+
+ function resetTime() {
+ scene.goToTime(0);
+ }
+
+ function changeColor() {
+ colorIndex = colorIndex >= colorArray.length - 1 ? colorIndex = 0 : colorIndex + 1;
+ materialElement.setAttribute("diffuse.r", colorArray[colorIndex][0]);
+ materialElement.setAttribute("diffuse.g", colorArray[colorIndex][1]);
+ materialElement.setAttribute("diffuse.b", colorArray[colorIndex][2]);
+ changeColorButton.color = Qt.rgba(colorArray[colorIndex][0],
+ colorArray[colorIndex][1],
+ colorArray[colorIndex][2], 1.0);
+ }
+ }
+ onRunningChanged: console.log("Presentation running")
+ }
+
+ // Some buttons to control the scene
+ Rectangle {
+ id: slideButton
+ anchors.left: parent.left
+ anchors.top: parent.top
+ width: 200
+ height: 50
+ border.color: "red"
+ border.width: 3
+ color: "white"
+ Text {
+ id: slideButtonText
+ anchors.fill: parent
+ text: "Change Slide (1)"
+ font.pointSize: 16
+ verticalAlignment: Qt.AlignVCenter
+ horizontalAlignment: Qt.AlignHCenter
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ studio3D.presentation.nextSlide();
+ }
+ }
+ }
+ Rectangle {
+ id: resetTimeButton
+ anchors.left: parent.left
+ anchors.top: slideButton.bottom
+ width: 200
+ height: 50
+ border.color: "red"
+ border.width: 3
+ color: "white"
+ Text {
+ anchors.fill: parent
+ text: "Reset Time"
+ font.pointSize: 16
+ verticalAlignment: Qt.AlignVCenter
+ horizontalAlignment: Qt.AlignHCenter
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ studio3D.presentation.resetTime();
+ }
+ }
+ }
+ Rectangle {
+ id: changeColorButton
+ anchors.left: parent.left
+ anchors.top: resetTimeButton.bottom
+ width: 200
+ height: 50
+ border.color: "red"
+ border.width: 3
+ color: "white"
+ Text {
+ anchors.fill: parent
+ text: "Change Color"
+ font.pointSize: 16
+ verticalAlignment: Qt.AlignVCenter
+ horizontalAlignment: Qt.AlignHCenter
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ studio3D.presentation.changeColor();
+ }
+ }
+ }
+}
diff --git a/examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.pro b/examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.pro
new file mode 100644
index 00000000..c1345ecc
--- /dev/null
+++ b/examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+
+QT += qml quick
+
+integrity: DEFINES += USE_EMBEDDED_FONTS
+
+target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET
+INSTALLS += target
+
+SOURCES += main.cpp
+
+RESOURCES += qmldynamickeyframes.qrc
+
+OTHER_FILES += qml/qmldynamickeyframes/* \
+ doc/src/* \
+ doc/images/*
+
+# Icon in case example is included in installer
+exists(example.ico): RC_ICONS = example.ico
diff --git a/examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.qrc b/examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.qrc
new file mode 100644
index 00000000..d53280d2
--- /dev/null
+++ b/examples/studio3d/qmldynamickeyframes/qmldynamickeyframes.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="main.qml">qml/qmldynamickeyframes/main.qml</file>
+ <file>presentation/dyn_key.uip</file>
+ </qresource>
+</RCC>
diff --git a/examples/studio3d/qmlstreamer/main.cpp b/examples/studio3d/qmlstreamer/main.cpp
new file mode 100644
index 00000000..82b640a8
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/main.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QGuiApplication>
+#include <QtQuick/QQuickView>
+#include <QtQml/QQmlEngine>
+
+#ifdef USE_EMBEDDED_FONTS
+#include <QtGui/QFontDatabase>
+#include <QtCore/QDebug>
+#endif
+
+int main(int argc, char *argv[])
+{
+#ifdef USE_EMBEDDED_FONTS
+ qputenv("QT_QPA_FONTDIR",".");
+#endif
+
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+#ifdef USE_EMBEDDED_FONTS
+ int fontId = QFontDatabase::addApplicationFont(":/res/Font/TitilliumWeb-Regular.ttf");
+ QStringList loadedFontFamilies = QFontDatabase::applicationFontFamilies(fontId);
+ if (!loadedFontFamilies.empty()) {
+ QString fontName = loadedFontFamilies.at(0);
+ QGuiApplication::setFont(QFont(fontName));
+ } else {
+ qWarning("Error: failed to load font");
+ }
+#endif
+
+ QQuickView viewer;
+
+ viewer.setSource(QUrl("qrc:/main.qml"));
+
+ viewer.setTitle(QStringLiteral("Qt 3D Studio QmlStreamer Example"));
+ viewer.setResizeMode(QQuickView::SizeRootObjectToView);
+ viewer.show();
+
+ return app.exec();
+}
diff --git a/examples/studio3d/qmlstreamer/presentation/images/dummy.png b/examples/studio3d/qmlstreamer/presentation/images/dummy.png
new file mode 100644
index 00000000..6e401328
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/presentation/images/dummy.png
Binary files differ
diff --git a/examples/studio3d/qmlstreamer/presentation/rotating_cube.uia b/examples/studio3d/qmlstreamer/presentation/rotating_cube.uia
new file mode 100644
index 00000000..6006dcb6
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/presentation/rotating_cube.uia
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://qt.io/qt3dstudio/uia">
+ <assets initial="rotating_cube">
+ <presentation id="rotating_cube" src="rotating_cube.uip"/>
+ <presentation-qml id="red-fill" args="scripts/RedFill.qml" />
+ </assets>
+</application>
diff --git a/examples/studio3d/qmlstreamer/presentation/rotating_cube.uip b/examples/studio3d/qmlstreamer/presentation/rotating_cube.uip
new file mode 100644
index 00000000..322177af
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/presentation/rotating_cube.uip
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Cube" >
+ <Material id="Material" >
+ <Image id="Material_diffusemap" />
+ </Material>
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" endtime="2000" />
+ <Add ref="#Camera" endtime="2000" />
+ <Add ref="#Light" endtime="2000" />
+ <State id="Scene-Rotating_Cube" name="Rotating_Cube" playmode="PingPong" >
+ <Set ref="#Layer" endtime="2000" />
+ <Set ref="#Camera" endtime="2000" />
+ <Set ref="#Light" endtime="2000" />
+ <Add ref="#Cube" name="Cube" endtime="2000" position="-349.297 168.875 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -349.297 100 100 2 334.863 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 168.875 100 100 2 -160.215 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 2 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 2 -16.4917 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 2 -154.887 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 2 270.405 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material" diffuse="1 1 1" diffusemap="#Material_diffusemap" />
+ <Add ref="#Material_diffusemap" sourcepath=".\images\dummy.png" subpresentation="red-fill" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/examples/studio3d/qmlstreamer/presentation/scripts/RedFill.qml b/examples/studio3d/qmlstreamer/presentation/scripts/RedFill.qml
new file mode 100644
index 00000000..7ee3063f
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/presentation/scripts/RedFill.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+
+Item {
+ width: 1024
+ height: 512
+ Rectangle {
+ id: rectangle
+ x: 0
+ y: 0
+ width: 0
+ height: 512
+ color: "red"
+ }
+ Text {
+ anchors.fill: parent
+ text: "QML"
+ font.pixelSize: 200
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ PropertyAnimation {
+ target: rectangle
+ property: "width"
+ from: 0
+ to: 1024
+ duration: 3000
+ loops: Animation.Infinite
+ running: true
+ }
+}
diff --git a/examples/studio3d/qmlstreamer/qml/qmlstreamer/main.qml b/examples/studio3d/qmlstreamer/qml/qmlstreamer/main.qml
new file mode 100644
index 00000000..6ffe4210
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/qml/qmlstreamer/main.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtStudio3D 1.0
+
+Item {
+ id: mainview
+ width: 1280
+ height: 768
+ visible: true
+
+ // Qt 3D Studio presentation element
+ //
+ // The presentation consists of as simple rotating cube with QML item as texture.
+ Studio3D {
+ id: studio3D
+ anchors.fill: parent
+ ViewerSettings {
+ scaleMode: ViewerSettings.ScaleModeFill
+ }
+ Presentation {
+ source: "qrc:/presentation/rotating_cube.uia"
+ SubPresentationSettings {
+ qmlStreams: [
+ QmlStream {
+ presentationId: "red-fill"
+ RedFill {
+ width: 1024
+ height: 512
+ }
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/examples/studio3d/qmlstreamer/qmlstreamer.pro b/examples/studio3d/qmlstreamer/qmlstreamer.pro
new file mode 100644
index 00000000..48392e17
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/qmlstreamer.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+
+QT += qml quick
+
+integrity: DEFINES += USE_EMBEDDED_FONTS
+
+target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET
+INSTALLS += target
+
+SOURCES += main.cpp
+
+RESOURCES += qmlstreamer.qrc
+
+OTHER_FILES += qml/qmlstreamer/* \
+ doc/src/* \
+ doc/images/*
+
+# Icon in case example is included in installer
+exists(example.ico): RC_ICONS = example.ico
diff --git a/examples/studio3d/qmlstreamer/qmlstreamer.qrc b/examples/studio3d/qmlstreamer/qmlstreamer.qrc
new file mode 100644
index 00000000..94d833ea
--- /dev/null
+++ b/examples/studio3d/qmlstreamer/qmlstreamer.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="main.qml">qml/qmlstreamer/main.qml</file>
+ <file>presentation/rotating_cube.uip</file>
+ <file>presentation/rotating_cube.uia</file>
+ <file>presentation/images/dummy.png</file>
+ <file alias="RedFill.qml">presentation/scripts/RedFill.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/studio3d/studio3d.pro b/examples/studio3d/studio3d.pro
new file mode 100644
index 00000000..434b30aa
--- /dev/null
+++ b/examples/studio3d/studio3d.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+
+!package {
+ SUBDIRS += \
+ qmldynamickeyframes \
+ qmlstreamer \
+ widgetviewer \
+ surfaceviewer \
+ surfaceviewer_offscreen
+}
diff --git a/examples/studio3d/surfaceviewer/main.cpp b/examples/studio3d/surfaceviewer/main.cpp
new file mode 100644
index 00000000..12fcdd0b
--- /dev/null
+++ b/examples/studio3d/surfaceviewer/main.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtStudio3D/Q3DSSurfaceViewer>
+#include <QtStudio3D/Q3DSViewerSettings>
+#include <QtStudio3D/Q3DSPresentation>
+#include <QtStudio3D/Q3DSSceneElement>
+#include <QtStudio3D/Q3DSElement>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
+#include <QtGui/QOpenGLContext>
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ QWindow window;
+
+ QSize size(1200, 800);
+ window.resize(size);
+ window.setSurfaceType(QSurface::OpenGLSurface);
+ window.setTitle(QStringLiteral("Qt 3D Studio surface viewer example"));
+ window.create();
+
+ QOpenGLContext context;
+ context.setFormat(window.format());
+ context.create();
+
+ Q3DSSurfaceViewer viewer;
+ viewer.presentation()->setSource(QUrl(QStringLiteral("qrc:/presentation/circling_cube.uip")));
+ viewer.setUpdateInterval(0);
+ viewer.settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ viewer.settings()->setShowRenderStats(true);
+
+ Q3DSSceneElement sceneElement(viewer.presentation(), QStringLiteral("Scene"));
+ Q3DSElement counterElement(viewer.presentation(), QStringLiteral("Scene.Layer.Loopcounter"));
+
+ viewer.initialize(&window, &context);
+
+ window.show();
+
+ int n = 0;
+ QString loopCounter = QStringLiteral("Loop %1");
+ QObject::connect(&sceneElement, &Q3DSSceneElement::currentSlideIndexChanged, [&]() {
+ if (sceneElement.currentSlideIndex() == 1)
+ n++;
+ counterElement.setAttribute(QStringLiteral("textstring"), loopCounter.arg(n));
+ });
+
+ return app.exec();
+}
diff --git a/examples/studio3d/surfaceviewer/presentation/circling_cube.uip b/examples/studio3d/surfaceviewer/presentation/circling_cube.uip
new file mode 100644
index 00000000..8f76b0a7
--- /dev/null
+++ b/examples/studio3d/surfaceviewer/presentation/circling_cube.uip
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Light id="Light2" />
+ <Model id="Cube" >
+ <Material id="Material" />
+ </Model>
+ <Light id="Light2_001" />
+ <Model id="Cube_001" >
+ <Material id="Material_001" />
+ </Model>
+ <Text id="Loopcounter" />
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Point" position="500 500 -500" rotation="36.8649 -268.216 350.188" />
+ <Add ref="#Loopcounter" name="Loopcounter" endtime="8000" font="TitilliumWeb-Regular" horzalign="Left" position="-546.345 288.675 0" scale="1 1 1" textstring="Loop: 1" />
+ <State id="Scene-Circling cube" name="Circling cube" playmode="Play Through To..." >
+ <Set ref="#Layer" endtime="4000" />
+ <Set ref="#Camera" endtime="4000" />
+ <Set ref="#Light" endtime="4000" />
+ <Add ref="#Light2" name="Light2" endtime="4000" lighttype="Point" position="-500 -500 -500" rotation="-52.8052 -40.339 113.184" />
+ <Add ref="#Cube" name="Cube" endtime="4000" position="-399.815 10.1036 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -400 0 0 0.5 -200 0 0 1 0 0 0 1.5 200 0 0 2 400 0 0 2.509 200 0 0 3 0 0 0 3.502 -200
+ 0 0 4 -400 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 0 0 0 0.5 120 0 0 1 200 0 0 1.5 120 0 0 2 0 0 0 2.509 -120 0 0 3 -200 0 0 3.502 -120
+ 0 0 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 0 0 0.5 0 0 0 1 0 0 0 1.5 0 0 0 2 0 0 0 2.509 0 0 0 3 0 0 0 3.502 0
+ 0 0 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 0 0 1 -90 0 0 2 -180 0 0 3 -270 0 0 4 -360 0 0</AnimationTrack>
+ </Add>
+ <Add ref="#Material" diffuse="0.12549 0.301961 0.909804" >
+ <AnimationTrack property="diffuse.x" type="EaseInOut" >0 0.160784 100 100 2 1 100 100 4 0.160784 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.y" type="EaseInOut" >0 0.956863 100 100 2 0 100 100 4 0.956863 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.z" type="EaseInOut" >0 0.0745098 100 100 2 0 100 100 4 0.0745098 100 100</AnimationTrack>
+ </Add>
+ </State>
+ <State id="Scene-Scaling cube" name="Scaling cube" playmode="Play Through To..." playthroughto="Previous" >
+ <Set ref="#Layer" endtime="4000" />
+ <Set ref="#Camera" endtime="4000" />
+ <Set ref="#Light" endtime="4000" />
+ <Add ref="#Light2_001" name="Light2" endtime="4000" lighttype="Point" position="-500 -500 -500" rotation="-52.8052 -40.339 113.184" />
+ <Add ref="#Cube_001" name="Cube" endtime="4000" position="-400 0 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -400 100 100 2 -206.589 100 100 4 -400 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 0 100 100 2 0 100 100 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 2 0 100 100 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 1 100 100 2 2 100 100 4 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 1 100 100 2 2 100 100 4 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 2 2 100 100 4 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_001" diffuse="0.12549 0.301961 0.909804" >
+ <AnimationTrack property="diffuse.x" type="EaseInOut" >0 0.160784 100 100 2 1 100 100 4 0.160784 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.y" type="EaseInOut" >0 0.956863 100 100 2 0 100 100 4 0.956863 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.z" type="EaseInOut" >0 0.0745098 100 100 2 0 100 100 4 0.0745098 100 100</AnimationTrack>
+ </Add>
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/examples/studio3d/surfaceviewer/presentation/fonts/TitilliumWeb-Regular.ttf b/examples/studio3d/surfaceviewer/presentation/fonts/TitilliumWeb-Regular.ttf
new file mode 100644
index 00000000..6da82193
--- /dev/null
+++ b/examples/studio3d/surfaceviewer/presentation/fonts/TitilliumWeb-Regular.ttf
Binary files differ
diff --git a/examples/studio3d/surfaceviewer/surfaceviewer.pro b/examples/studio3d/surfaceviewer/surfaceviewer.pro
new file mode 100644
index 00000000..667c6282
--- /dev/null
+++ b/examples/studio3d/surfaceviewer/surfaceviewer.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+
+QT += studio3d
+
+target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET
+INSTALLS += target
+
+SOURCES += main.cpp
+
+RESOURCES += surfaceviewer.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
diff --git a/examples/studio3d/surfaceviewer/surfaceviewer.qrc b/examples/studio3d/surfaceviewer/surfaceviewer.qrc
new file mode 100644
index 00000000..ed050d32
--- /dev/null
+++ b/examples/studio3d/surfaceviewer/surfaceviewer.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>presentation/circling_cube.uip</file>
+ </qresource>
+</RCC>
diff --git a/examples/studio3d/surfaceviewer_offscreen/main.cpp b/examples/studio3d/surfaceviewer_offscreen/main.cpp
new file mode 100644
index 00000000..eb26803a
--- /dev/null
+++ b/examples/studio3d/surfaceviewer_offscreen/main.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtStudio3D/Q3DSSurfaceViewer>
+#include <QtStudio3D/Q3DSViewerSettings>
+#include <QtStudio3D/Q3DSPresentation>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QOffscreenSurface>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QSurfaceFormat format;
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+
+ QOpenGLContext context;
+ context.setFormat(format);
+ if (!context.create())
+ qFatal("Failed to create OpenGL context");
+
+ // Must have a "surface". Depending on the platform this may be a small
+ // window, pbuffer surface, or even nothing (in case surfaceless contexts are
+ // supported) under the hood.
+ QOffscreenSurface surface;
+ surface.setFormat(context.format());
+ surface.create();
+
+ if (!context.makeCurrent(&surface))
+ qFatal("makeCurrent failed");
+
+ const QSize size(1280, 800);
+ QOpenGLFramebufferObject fbo(size, QOpenGLFramebufferObject::CombinedDepthStencil);
+
+ Q3DSSurfaceViewer viewer;
+ viewer.presentation()->setSource(QUrl(QStringLiteral("qrc:/presentation/circling_cube.uip")));
+ viewer.settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ // Will call update() manually when a new frame is wanted.
+ viewer.setUpdateInterval(-1);
+
+ // Automatic sizing must be turned off.
+ viewer.setAutoSize(false);
+
+ // Provide the render target size instead.
+ viewer.setSize(size);
+
+ if (!viewer.initialize(&surface, &context, fbo.handle()))
+ qFatal("Initialization failed");
+
+ // Render a few frames, read them back, and save into png files.
+ qint64 t = 0;
+ for (int frame = 1; frame <= 20; ++frame) {
+ // Advance animations manually. By default animations would advance
+ // based on whatever time the rendering, readback and PNG generation
+ // throttle this thread to. That is not ideal so maintain our own
+ // "global time".
+ viewer.presentation()->setGlobalAnimationTime(t);
+ t += 16; // 60 fps
+
+ // Render the next frame.
+ viewer.update();
+
+ // Write it to a file.
+ const QString fn = QString(QLatin1String("output_%1.png")).arg(frame);
+ fbo.toImage().save(fn);
+
+ qDebug("Rendered and saved frame %d to %s", frame, qPrintable(fn));
+ }
+
+ // Now one could do the following to generate a 60 fps video from these frames:
+ // ffmpeg -r 60 -f image2 -s 1280x800 -i output_%d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p output.mp4
+
+ return 0;
+}
diff --git a/examples/studio3d/surfaceviewer_offscreen/presentation/circling_cube.uip b/examples/studio3d/surfaceviewer_offscreen/presentation/circling_cube.uip
new file mode 100644
index 00000000..3dc6c6c0
--- /dev/null
+++ b/examples/studio3d/surfaceviewer_offscreen/presentation/circling_cube.uip
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Light id="Light2" />
+ <Model id="Cube" >
+ <Material id="Material" />
+ </Model>
+ <Light id="Light2_001" />
+ <Model id="Cube_001" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Point" position="500 500 -500" rotation="36.8649 -268.216 350.188" />
+ <State id="Scene-Circling cube" name="Circling cube" playmode="Play Through To..." >
+ <Set ref="#Layer" endtime="4000" />
+ <Set ref="#Camera" endtime="4000" />
+ <Set ref="#Light" endtime="4000" />
+ <Add ref="#Light2" name="Light2" endtime="4000" lighttype="Point" position="-500 -500 -500" rotation="-52.8052 -40.339 113.184" />
+ <Add ref="#Cube" name="Cube" endtime="4000" position="-399.815 10.1036 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -400 0 0 0.5 -200 0 0 1 0 0 0 1.5 200 0 0 2 400 0 0 2.509 200 0 0 3 0 0 0 3.502 -200
+ 0 0 4 -400 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 0 0 0 0.5 120 0 0 1 200 0 0 1.5 120 0 0 2 0 0 0 2.509 -120 0 0 3 -200 0 0 3.502 -120
+ 0 0 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 0 0 0.5 0 0 0 1 0 0 0 1.5 0 0 0 2 0 0 0 2.509 0 0 0 3 0 0 0 3.502 0
+ 0 0 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 0 0 1 -90 0 0 2 -180 0 0 3 -270 0 0 4 -360 0 0</AnimationTrack>
+ </Add>
+ <Add ref="#Material" diffuse="0.12549 0.301961 0.909804" >
+ <AnimationTrack property="diffuse.x" type="EaseInOut" >0 0.160784 100 100 2 1 100 100 4 0.160784 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.y" type="EaseInOut" >0 0.956863 100 100 2 0 100 100 4 0.956863 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.z" type="EaseInOut" >0 0.0745098 100 100 2 0 100 100 4 0.0745098 100 100</AnimationTrack>
+ </Add>
+ </State>
+ <State id="Scene-Scaling cube" name="Scaling cube" playmode="Play Through To..." playthroughto="Previous" >
+ <Set ref="#Layer" endtime="4000" />
+ <Set ref="#Camera" endtime="4000" />
+ <Set ref="#Light" endtime="4000" />
+ <Add ref="#Light2_001" name="Light2" endtime="4000" lighttype="Point" position="-500 -500 -500" rotation="-52.8052 -40.339 113.184" />
+ <Add ref="#Cube_001" name="Cube" endtime="4000" position="-400 0 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -400 100 100 2 -206.589 100 100 4 -400 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 0 100 100 2 0 100 100 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 2 0 100 100 4 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 1 100 100 2 2 100 100 4 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 1 100 100 2 2 100 100 4 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 2 2 100 100 4 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_001" diffuse="0.12549 0.301961 0.909804" >
+ <AnimationTrack property="diffuse.x" type="EaseInOut" >0 0.160784 100 100 2 1 100 100 4 0.160784 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.y" type="EaseInOut" >0 0.956863 100 100 2 0 100 100 4 0.956863 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.z" type="EaseInOut" >0 0.0745098 100 100 2 0 100 100 4 0.0745098 100 100</AnimationTrack>
+ </Add>
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.pro b/examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.pro
new file mode 100644
index 00000000..6d782f6f
--- /dev/null
+++ b/examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+
+QT += studio3d
+
+target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET
+INSTALLS += target
+
+SOURCES += main.cpp
+
+RESOURCES += surfaceviewer_offscreen.qrc
+
+OTHER_FILES += doc/src/* \
+ doc/images/*
diff --git a/examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.qrc b/examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.qrc
new file mode 100644
index 00000000..ed050d32
--- /dev/null
+++ b/examples/studio3d/surfaceviewer_offscreen/surfaceviewer_offscreen.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>presentation/circling_cube.uip</file>
+ </qresource>
+</RCC>
diff --git a/examples/studio3d/widgetviewer/main.cpp b/examples/studio3d/widgetviewer/main.cpp
new file mode 100644
index 00000000..dd0b3a57
--- /dev/null
+++ b/examples/studio3d/widgetviewer/main.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWidgets/QApplication>
+#include <QtCore/QFile>
+
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ // Enable high DPI scaling
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ // Setting the application settings before the creation of the main window is important,
+ // as this also initializes the settings.
+ QCoreApplication::setOrganizationName("The Qt Company");
+ QCoreApplication::setOrganizationDomain("qt.io");
+ QCoreApplication::setApplicationName("Qt 3D Studio Viewer Example");
+
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.resize(1280, 720);
+ w.show();
+
+ // Load an application style
+ QFile styleFile(":/resources/style/dark.qss");
+ styleFile.open(QFile::ReadOnly);
+
+ // Apply the loaded stylesheet
+ QString style(styleFile.readAll());
+ a.setStyleSheet(style);
+
+ return a.exec();
+}
diff --git a/examples/studio3d/widgetviewer/mainwindow.cpp b/examples/studio3d/widgetviewer/mainwindow.cpp
new file mode 100644
index 00000000..b57c1ba2
--- /dev/null
+++ b/examples/studio3d/widgetviewer/mainwindow.cpp
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDebug>
+#include <QtCore/QSettings>
+#include <QtCore/QFileInfo>
+#include <QtCore/QMimeData>
+#include <QtWidgets/QFileDialog>
+#include <QtWidgets/QMessageBox>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QWindow>
+#include <QtQml/QQmlContext>
+#include <QtQml/QQmlEngine>
+#include <QtStudio3D/Q3DSPresentation>
+#include <QtStudio3D/Q3DSViewerSettings>
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+
+ ui->actionOpen->setShortcut(QKeySequence::Open);
+ QList<QKeySequence> shortcuts;
+ shortcuts.push_back(QKeySequence(QKeySequence::Quit));
+ shortcuts.push_back(QKeySequence("CTRL+Q"));
+ ui->actionQuit->setShortcuts(shortcuts);
+ ui->actionFull_Screen->setShortcut(QKeySequence::FullScreen);
+ ui->actionReload->setShortcut(QKeySequence::Refresh);
+
+ QStringList strArg = QApplication::arguments();
+ if (strArg.size() >= 2) {
+ QFileInfo theFilePath(strArg[1]);
+ if (theFilePath.exists()) {
+ m_openFileDir = theFilePath.path();
+ ui->widget->presentation()->setSource(strArg[1]);
+ QSettings().setValue("PreviousOpenFolder", m_openFileDir);
+ }
+ }
+
+ m_embeddedMode = false;
+ m_startInFullscreen = false;
+ QStringList::const_iterator constIterator;
+ for (constIterator = strArg.constBegin(); constIterator != strArg.constEnd(); ++constIterator) {
+ if (!(*constIterator).compare("-embedded")) {
+ m_embeddedMode = true;
+ } else if (!(*constIterator).compare("-fullscreen")) {
+ // When in fullscreen also enable embedded mode
+ m_embeddedMode = true;
+ m_startInFullscreen = true;
+ }
+ }
+
+ // Hide menu when we are in embedded mode
+ if (m_embeddedMode)
+ ui->menuBar->hide();
+
+ QSettings settings;
+ ui->actionBorder->setChecked(settings.value("ShowMatte", false).toBool());
+ ui->actionFull_Screen->setChecked(settings.value("FullScreen", false).toBool());
+ ui->actionShowOnScreenStats->setChecked(settings.value("ShowOnScreenStats", false).toBool());
+
+ // Set runtime states
+ ui->widget->settings()->setMatteColor(settings.value("ShowMatte", false).toBool()
+ ? QColor(50, 50, 50) : Qt::black);
+ ui->widget->settings()->setShowRenderStats(settings.value("ShowOnScreenStats", false).toBool());
+ if (!m_startInFullscreen)
+ m_startInFullscreen = settings.value("FullScreen", false).toBool();
+
+ addAction(ui->actionFull_Screen);
+ addAction(ui->actionShowOnScreenStats);
+ addAction(ui->actionBorder);
+ addAction(ui->actionShadeMode);
+
+ // Disable hotkeys when we are in embedded mode
+ if (!m_embeddedMode) {
+ addAction(ui->actionReload);
+ addAction(ui->actionQuit);
+ addAction(ui->actionOpen);
+ }
+
+ // Allow drag'n'dropping
+ setAcceptDrops(true);
+
+ ui->widget->setUpdateInterval(0);
+
+ connect(ui->widget, &Q3DSWidget::runningChanged, this, &MainWindow::updateUI);
+}
+
+MainWindow::~MainWindow()
+{
+ QSettings settings;
+ settings.setValue("FullScreen", this->isFullScreen());
+ settings.setValue("ShowMatte", ui->widget->settings()->matteColor() != Qt::black);
+ settings.setValue("ShowOnScreenStats", ui->widget->settings()->isShowRenderStats());
+ // Don't save the window geometry if we are in fullscreen mode.
+ // This is invalid geometry and actually breaks our ability to start on a second monitor
+ if (!this->isFullScreen()) {
+ settings.setValue("WindowGeometry", saveGeometry());
+ settings.setValue("WindowState", saveState());
+ }
+ delete ui;
+}
+
+void MainWindow::toggleFullscreenMode(bool inFullscreen)
+{
+ if (inFullscreen) {
+ showFullScreen();
+ ui->menuBar->hide();
+ } else {
+ showNormal();
+ if (!m_embeddedMode)
+ ui->menuBar->show();
+ }
+ updateScaleUI();
+}
+
+void MainWindow::on_actionFull_Screen_triggered()
+{
+ bool isFullScreen = this->isFullScreen();
+ if (!isFullScreen) {
+ QSettings settings;
+ settings.setValue("WindowGeometry", saveGeometry());
+ settings.setValue("WindowState", saveState());
+ }
+ toggleFullscreenMode(!isFullScreen);
+}
+
+void MainWindow::on_actionBorder_triggered()
+{
+ if (ui->widget->settings()->matteColor() == Qt::black)
+ ui->widget->settings()->setMatteColor(QColor(50, 50, 50));
+ else
+ ui->widget->settings()->setMatteColor(Qt::black);
+}
+
+void MainWindow::on_actionShowOnScreenStats_triggered()
+{
+ bool showStats = !ui->widget->settings()->isShowRenderStats();
+ ui->widget->settings()->setShowRenderStats(showStats);
+}
+
+void MainWindow::on_actionShadeMode_triggered()
+{
+ Q3DSViewerSettings::ShadeMode shadeMode = ui->widget->settings()->shadeMode();
+ if (shadeMode == Q3DSViewerSettings::ShadeModeShaded)
+ ui->widget->settings()->setShadeMode(Q3DSViewerSettings::ShadeModeShadedWireframe);
+ else
+ ui->widget->settings()->setShadeMode(Q3DSViewerSettings::ShadeModeShaded);
+}
+
+void MainWindow::on_actionQuit_triggered()
+{
+ close();
+}
+
+void MainWindow::on_actionOpen_triggered()
+{
+ QSettings settings;
+ if (m_openFileDir.size() == 0)
+ m_openFileDir = settings.value("PreviousOpenFolder", QString("")).toString();
+
+ QString filename = QFileDialog::getOpenFileName(
+ this, tr("Open File or Project"), m_openFileDir,
+ tr("All supported formats (*.uip *.uia *.uiab);;Studio UI Presentation "
+ "(*.uip);;Application file (*.uia);;Binary Application (*.uiab)"),
+ NULL);
+
+ if (filename.size() == 0)
+ return;
+
+ QFileInfo theInfo(filename);
+ m_openFileDir = theInfo.path();
+ settings.setValue("PreviousOpenFolder", m_openFileDir);
+
+ loadFile(filename);
+}
+
+void MainWindow::on_actionReload_triggered()
+{
+ ui->widget->reset();
+ updateScaleUI();
+}
+
+void MainWindow::loadFile(const QString &filename)
+{
+ ui->widget->presentation()->setSource(QUrl::fromLocalFile(filename));
+ ui->widget->initialize();
+ updateScaleUI();
+}
+
+void MainWindow::on_actionCenter_triggered()
+{
+ ui->widget->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeCenter);
+ updateScaleUI();
+}
+
+void MainWindow::on_actionScale_To_Fit_triggered()
+{
+ ui->widget->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ updateScaleUI();
+}
+
+void MainWindow::on_actionScale_To_Fill_triggered()
+{
+ ui->widget->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ updateScaleUI();
+}
+
+QString MainWindow::convertMimeDataToFilename(const QMimeData *mimeData)
+{
+ if (mimeData->hasUrls()) {
+ for (const QUrl &url : mimeData->urls()) {
+ QString str = url.toLocalFile();
+ if (str.isEmpty() == false) {
+ if ((QFileInfo(str).suffix() == "uip") || (QFileInfo(str).suffix() == "uia")
+ || (QFileInfo(str).suffix() == "uiab")) {
+ // Allow uip, uia and uia binary
+ return str;
+ }
+ }
+ }
+ }
+ return QString();
+}
+
+void MainWindow::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (convertMimeDataToFilename(event->mimeData()).isEmpty() == false)
+ event->acceptProposedAction();
+}
+
+void MainWindow::dropEvent(QDropEvent *event)
+{
+ QString fileName = convertMimeDataToFilename(event->mimeData());
+ if (fileName.isEmpty() == false)
+ loadFile(fileName);
+}
+
+void MainWindow::showEvent(QShowEvent *event)
+{
+ QMainWindow::showEvent(event);
+ restoreGeometry(QSettings().value("WindowGeometry").toByteArray());
+ restoreState(QSettings().value("WindowState").toByteArray());
+ if (m_startInFullscreen || this->isFullScreen()) {
+ m_startInFullscreen = false; // only once
+ toggleFullscreenMode(true);
+ }
+ if (ui->widget->isRunning() == false && !ui->widget->presentation()->source().isEmpty()) {
+ if (!ui->widget->initialize()) {
+ QString msg = QStringLiteral("Unable to initialize OpenGL.\nThis may be because your "
+ "graphic device is not sufficient, or simply because your driver is too old.\n"
+ "\nPlease try upgrading your graphics driver and try again.");
+ QMessageBox::critical(NULL, "Fatal Error", msg, QMessageBox::Close);
+ QCoreApplication::exit(1);
+ }
+ }
+}
+
+void MainWindow::updateUI()
+{
+ QString name = ui->widget->presentation()->source().toString();
+ setWindowTitle(tr("%1Qt 3D Studio Viewer example").arg(name.size()
+ ? name.append(" - ") : name));
+ updateScaleUI();
+ QWindow *w = windowHandle();
+ if (w) {
+ if (!QQmlEngine::contextForObject(w)) {
+ QQmlEngine *engine = new QQmlEngine(this);
+ QQmlContext *context = new QQmlContext(engine, this);
+ QQmlEngine::setContextForObject(w, context);
+ }
+ }
+}
+
+void MainWindow::updateScaleUI()
+{
+ ui->actionCenter->setChecked(false);
+ ui->actionScale_To_Fit->setChecked(false);
+ ui->actionScale_To_Fill->setChecked(false);
+ Q3DSViewerSettings::ScaleMode mode = ui->widget->settings()->scaleMode();
+ if (mode == Q3DSViewerSettings::ScaleModeCenter)
+ ui->actionCenter->setChecked(true);
+ else if (mode == Q3DSViewerSettings::ScaleModeFill)
+ ui->actionScale_To_Fill->setChecked(true);
+ else
+ ui->actionScale_To_Fit->setChecked(true);
+}
diff --git a/examples/studio3d/widgetviewer/mainwindow.h b/examples/studio3d/widgetviewer/mainwindow.h
new file mode 100644
index 00000000..271768ec
--- /dev/null
+++ b/examples/studio3d/widgetviewer/mainwindow.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtWidgets/QMainWindow>
+#include <QtStudio3D/Q3DSWidget>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+class MainWindow;
+}
+class QMimeData;
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+
+ void loadFile(const QString &filename);
+
+protected:
+ // Qt event handling
+ void dragEnterEvent(QDragEnterEvent *event) override;
+ void dropEvent(QDropEvent *event) override;
+ void showEvent(QShowEvent *event) override;
+
+private:
+ Ui::MainWindow *ui;
+
+ void toggleFullscreenMode(bool inFullscreen);
+ QString convertMimeDataToFilename(const QMimeData *mimeData);
+
+private Q_SLOTS:
+ void on_actionFull_Screen_triggered();
+ void on_actionBorder_triggered();
+ void on_actionShowOnScreenStats_triggered();
+ void on_actionShadeMode_triggered();
+ void on_actionQuit_triggered();
+ void on_actionOpen_triggered();
+ void on_actionReload_triggered();
+ void on_actionCenter_triggered();
+ void on_actionScale_To_Fit_triggered();
+ void on_actionScale_To_Fill_triggered();
+ void updateUI();
+ void updateScaleUI();
+
+private:
+ QString m_openFileDir;
+ bool m_embeddedMode; // when true hide menu and disable some hotkeys
+ bool m_startInFullscreen; // this flag will be true when started with -fullscreen flag
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/studio3d/widgetviewer/mainwindow.ui b/examples/studio3d/widgetviewer/mainwindow.ui
new file mode 100644
index 00000000..cea8bf66
--- /dev/null
+++ b/examples/studio3d/widgetviewer/mainwindow.ui
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1042</width>
+ <height>556</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qt 3D Studio Viewer example</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="Q3DSWidget" name="widget" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1042</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>File</string>
+ </property>
+ <addaction name="actionOpen"/>
+ <addaction name="actionReload"/>
+ <addaction name="separator"/>
+ <addaction name="actionQuit"/>
+ </widget>
+ <widget class="QMenu" name="menuView">
+ <property name="title">
+ <string>View</string>
+ </property>
+ <widget class="QMenu" name="menuScale_Mode">
+ <property name="toolTip">
+ <string>Set application scale mode (-scalemode [center,fit,fill] command line parameter)</string>
+ </property>
+ <property name="title">
+ <string>Scale Mode</string>
+ </property>
+ <addaction name="actionCenter"/>
+ <addaction name="actionScale_To_Fit"/>
+ <addaction name="actionScale_To_Fill"/>
+ </widget>
+ <addaction name="actionFull_Screen"/>
+ <addaction name="actionBorder"/>
+ <addaction name="menuScale_Mode"/>
+ <addaction name="actionShadeMode"/>
+ <addaction name="actionShowOnScreenStats"/>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuView"/>
+ </widget>
+ <action name="actionQuit">
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ </action>
+ <action name="actionFull_Screen">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Full Screen</string>
+ </property>
+ <property name="shortcut">
+ <string>F11</string>
+ </property>
+ </action>
+ <action name="actionBorder">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Matte</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="actionShadeMode">
+ <property name="text">
+ <string>Shade Mode</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle between shaded only and wireframe on shaded</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+W</string>
+ </property>
+ </action>
+ <action name="actionShowOnScreenStats">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Render Statistics</string>
+ </property>
+ <property name="shortcut">
+ <string>F1</string>
+ </property>
+ </action>
+ <action name="actionOpen">
+ <property name="text">
+ <string>Open...</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="actionReload">
+ <property name="text">
+ <string>Reload</string>
+ </property>
+ </action>
+ <action name="actionCenter">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Center</string>
+ </property>
+ <property name="toolTip">
+ <string>Center content and use design dimensions</string>
+ </property>
+ </action>
+ <action name="actionScale_To_Fit">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Scale To Fit</string>
+ </property>
+ <property name="toolTip">
+ <string>Fit content to available space but maintain aspect ratio</string>
+ </property>
+ </action>
+ <action name="actionScale_To_Fill">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Scale To Fill</string>
+ </property>
+ <property name="toolTip">
+ <string>Use entire screen space for content, changing aspect ratio as necessary</string>
+ </property>
+ </action>
+ <action name="actionToggle_Scale_Mode">
+ <property name="text">
+ <string>Toggle Scale Mode</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle between the various scale modes</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+S</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>Q3DSWidget</class>
+ <extends>QWidget</extends>
+ <header>q3dswidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/studio3d/widgetviewer/resources/style/checkbox.png b/examples/studio3d/widgetviewer/resources/style/checkbox.png
new file mode 100644
index 00000000..b4a9aa3b
--- /dev/null
+++ b/examples/studio3d/widgetviewer/resources/style/checkbox.png
Binary files differ
diff --git a/examples/studio3d/widgetviewer/resources/style/dark.qss b/examples/studio3d/widgetviewer/resources/style/dark.qss
new file mode 100644
index 00000000..0bb5af7f
--- /dev/null
+++ b/examples/studio3d/widgetviewer/resources/style/dark.qss
@@ -0,0 +1,450 @@
+QToolTip
+{
+ border: 1px solid black;
+ background-color: #ffa02f;
+ padding: 1px;
+ border-radius: 3px;
+ opacity: 100;
+}
+
+QWidget
+{
+ color: #b1b1b1;
+ background-color: #323232;
+}
+
+QWidget:item:hover
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #ca0619);
+ color: #000000;
+}
+
+QWidget:item:selected
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QMenuBar::item
+{
+ background: transparent;
+}
+
+QMenuBar::item:selected
+{
+ background: transparent;
+ border: 1px solid #ffaa00;
+}
+
+QMenuBar::item:pressed
+{
+ background: #444;
+ border: 1px solid #000;
+ background-color: QLinearGradient(
+ x1:0, y1:0,
+ x2:0, y2:1,
+ stop:1 #212121,
+ stop:0.4 #343434/*,
+ stop:0.2 #343434,
+ stop:0.1 #ffaa00*/
+ );
+ margin-bottom:-1px;
+ padding-bottom:1px;
+}
+
+QMenu
+{
+ border: 1px solid #000;
+}
+
+QMenu::item
+{
+ padding: 4px 20px 4px 20px;
+}
+
+QMenu::item:selected
+{
+ color: #000000;
+}
+
+QWidget:disabled
+{
+ color: #404040;
+ background-color: #323232;
+}
+
+QAbstractItemView
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0.1 #646464, stop: 1 #5d5d5d);
+}
+
+QLineEdit
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0 #646464, stop: 1 #5d5d5d);
+ padding: 1px;
+ border-style: solid;
+ border: 1px solid #1e1e1e;
+ border-radius: 5;
+}
+
+QPushButton
+{
+ color: #b1b1b1;
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
+ border-width: 1px;
+ border-color: #1e1e1e;
+ border-style: solid;
+ border-radius: 6;
+ padding: 3px;
+ font-size: 12px;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+QPushButton:pressed
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
+}
+
+QComboBox
+{
+ selection-background-color: #ffaa00;
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
+ border-style: solid;
+ border: 1px solid #1e1e1e;
+ border-radius: 5;
+}
+
+QComboBox:hover,QPushButton:hover
+{
+ border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+
+QComboBox:on
+{
+ padding-top: 3px;
+ padding-left: 4px;
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
+ selection-background-color: #ffaa00;
+}
+
+QComboBox QAbstractItemView
+{
+ border: 2px solid darkgray;
+ selection-background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QComboBox::drop-down
+{
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 15px;
+
+ border-left-width: 0px;
+ border-left-color: darkgray;
+ border-left-style: solid; /* just a single line */
+ border-top-right-radius: 3px; /* same radius as the QComboBox */
+ border-bottom-right-radius: 3px;
+ }
+
+QComboBox::down-arrow
+{
+ image: url(:/resources/style/down_arrow.png);
+}
+
+QGroupBox:focus
+{
+ border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QTextEdit:focus
+{
+ border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QScrollBar:horizontal {
+ border: 1px solid #222222;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);
+ height: 7px;
+ margin: 0px 16px 0 16px;
+}
+
+QScrollBar::handle:horizontal
+{
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);
+ min-height: 20px;
+ border-radius: 2px;
+}
+
+QScrollBar::add-line:horizontal {
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);
+ width: 14px;
+ subcontrol-position: right;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal {
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);
+ width: 14px;
+ subcontrol-position: left;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::right-arrow:horizontal, QScrollBar::left-arrow:horizontal
+{
+ border: 1px solid black;
+ width: 1px;
+ height: 1px;
+ background: white;
+}
+
+QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
+{
+ background: none;
+}
+
+QScrollBar:vertical
+{
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);
+ width: 7px;
+ margin: 16px 0 16px 0;
+ border: 1px solid #222222;
+}
+
+QScrollBar::handle:vertical
+{
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);
+ min-height: 20px;
+ border-radius: 2px;
+}
+
+QScrollBar::add-line:vertical
+{
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+ height: 14px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:vertical
+{
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #d7801a, stop: 1 #ffa02f);
+ height: 14px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
+{
+ border: 1px solid black;
+ width: 1px;
+ height: 1px;
+ background: white;
+}
+
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
+{
+ background: none;
+}
+
+QTextEdit
+{
+ background-color: #242424;
+}
+
+QPlainTextEdit
+{
+ background-color: #242424;
+}
+
+QHeaderView::section
+{
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, stop: 0.6 #434343, stop:1 #656565);
+ color: white;
+ padding-left: 4px;
+ border: 1px solid #6c6c6c;
+}
+
+QCheckBox:disabled
+{
+ color: #414141;
+}
+
+QDockWidget::title
+{
+ padding-left: 10px;
+ spacing: 3px; /* spacing between items in the tool bar */
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);
+}
+
+QDockWidget::close-button, QDockWidget::float-button
+{
+ text-align: center;
+ spacing: 1px; /* spacing between items in the tool bar */
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);
+}
+
+QDockWidget::close-button:hover, QDockWidget::float-button:hover
+{
+ background: #242424;
+}
+
+QDockWidget::close-button:pressed, QDockWidget::float-button:pressed
+{
+ padding: 1px -1px -1px 1px;
+}
+
+QMainWindow::separator
+{
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);
+ color: white;
+ padding-left: 4px;
+ border: 1px solid #4c4c4c;
+ spacing: 3px; /* spacing between items in the tool bar */
+}
+
+QMainWindow::separator:hover
+{
+
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #d7801a, stop:0.5 #b56c17 stop:1 #ffa02f);
+ color: white;
+ padding-left: 4px;
+ border: 1px solid #6c6c6c;
+ spacing: 3px; /* spacing between items in the tool bar */
+}
+
+QToolBar::handle
+{
+ spacing: 3px; /* spacing between items in the tool bar */
+ background: url(:/resources/style/handle.png);
+}
+
+QMenu::separator
+{
+ height: 2px;
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);
+ color: white;
+ padding-left: 4px;
+ margin-left: 10px;
+ margin-right: 5px;
+}
+
+QProgressBar
+{
+ border: 2px solid grey;
+ border-radius: 5px;
+ text-align: center;
+}
+
+QProgressBar::chunk
+{
+ background-color: #d7801a;
+ width: 2.15px;
+ margin: 0.5px;
+}
+
+QTabBar::tab {
+ color: #b1b1b1;
+ border: 1px solid #444;
+ border-bottom-style: none;
+ background-color: #323232;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ margin-right: -1px;
+}
+
+QTabWidget::pane {
+ border: 1px solid #444;
+ top: 1px;
+}
+
+QTabBar::tab:last
+{
+ margin-right: 0; /* the last selected tab has nothing to overlap with on the right */
+ border-top-right-radius: 3px;
+}
+
+QTabBar::tab:first:!selected
+{
+ margin-left: 0px; /* the last selected tab has nothing to overlap with on the right */
+ border-top-left-radius: 3px;
+}
+
+QTabBar::tab:!selected
+{
+ color: #b1b1b1;
+ border-bottom-style: solid;
+ margin-top: 3px;
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
+}
+
+QTabBar::tab:selected
+{
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ margin-bottom: 0px;
+}
+
+QTabBar::tab:!selected:hover
+{
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434, stop:0.2 #343434, stop:0.1 #ffaa00);
+}
+
+QRadioButton::indicator:checked, QRadioButton::indicator:unchecked{
+ color: #b1b1b1;
+ background-color: #323232;
+ border: 1px solid #b1b1b1;
+ border-radius: 6px;
+}
+
+QRadioButton::indicator:checked
+{
+ background-color: qradialgradient(
+ cx: 0.5, cy: 0.5,
+ fx: 0.5, fy: 0.5,
+ radius: 1.0,
+ stop: 0.25 #ffaa00,
+ stop: 0.3 #323232
+ );
+}
+
+QCheckBox::indicator{
+ color: #b1b1b1;
+ background-color: #323232;
+ border: 1px solid #b1b1b1;
+ width: 9px;
+ height: 9px;
+}
+
+QRadioButton::indicator
+{
+ border-radius: 6px;
+}
+
+QRadioButton::indicator:hover, QCheckBox::indicator:hover
+{
+ border: 1px solid #ffaa00;
+}
+
+QCheckBox::indicator:checked
+{
+ image:url(:/resources/style/checkbox.png);
+}
+
+QCheckBox::indicator:disabled, QRadioButton::indicator:disabled
+{
+ border: 1px solid #444;
+}
diff --git a/examples/studio3d/widgetviewer/resources/style/down_arrow.png b/examples/studio3d/widgetviewer/resources/style/down_arrow.png
new file mode 100644
index 00000000..db581cb7
--- /dev/null
+++ b/examples/studio3d/widgetviewer/resources/style/down_arrow.png
Binary files differ
diff --git a/examples/studio3d/widgetviewer/resources/style/handle.png b/examples/studio3d/widgetviewer/resources/style/handle.png
new file mode 100644
index 00000000..fd50400f
--- /dev/null
+++ b/examples/studio3d/widgetviewer/resources/style/handle.png
Binary files differ
diff --git a/examples/studio3d/widgetviewer/widgetviewer.pro b/examples/studio3d/widgetviewer/widgetviewer.pro
new file mode 100644
index 00000000..3959f894
--- /dev/null
+++ b/examples/studio3d/widgetviewer/widgetviewer.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+QT += widgets studio3d
+
+TARGET = widgetviewer
+
+target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET
+INSTALLS += target
+
+HEADERS += mainwindow.h
+FORMS += mainwindow.ui
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp
+RESOURCES += widgetviewer.qrc
diff --git a/examples/studio3d/widgetviewer/widgetviewer.qrc b/examples/studio3d/widgetviewer/widgetviewer.qrc
new file mode 100644
index 00000000..f9c5b44a
--- /dev/null
+++ b/examples/studio3d/widgetviewer/widgetviewer.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/">
+ <file>resources/style/dark.qss</file>
+ <file>resources/style/checkbox.png</file>
+ <file>resources/style/down_arrow.png</file>
+ <file>resources/style/handle.png</file>
+ </qresource>
+</RCC>
diff --git a/features/nostrictstrings.prf b/features/nostrictstrings.prf
new file mode 100644
index 00000000..bdedc847
--- /dev/null
+++ b/features/nostrictstrings.prf
@@ -0,0 +1,2 @@
+QMAKE_CFLAGS ~= s/-Zc:strictStrings//
+QMAKE_CXXFLAGS ~= s/-Zc:strictStrings//
diff --git a/qt3dstudio.pro b/qt3dstudio.pro
new file mode 100644
index 00000000..8c20dc0d
--- /dev/null
+++ b/qt3dstudio.pro
@@ -0,0 +1,7 @@
+requires(qtHaveModule(widgets))
+requires(qtHaveModule(multimedia))
+requires(qtHaveModule(quick))
+requires(qtHaveModule(qml))
+requires(qtHaveModule(opengl))
+
+load(qt_parts)
diff --git a/src/3rdparty/3rdparty.pro b/src/3rdparty/3rdparty.pro
new file mode 100644
index 00000000..2fbb3332
--- /dev/null
+++ b/src/3rdparty/3rdparty.pro
@@ -0,0 +1,12 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS += \
+ Lua \
+ EASTL
+
+!boot2qt:!android:!integrity {
+ SUBDIRS += \
+ pcre \
+ ColladaDOM/TinyXML \
+ ColladaDOM
+}
diff --git a/src/3rdparty/ColladaDOM b/src/3rdparty/ColladaDOM
new file mode 160000
+Subproject eee97c048f9cdc1cc05d6a516a3da56a13accd6
diff --git a/src/3rdparty/EASTL b/src/3rdparty/EASTL
new file mode 160000
+Subproject fd897f94965fdb5e56a47292afc0bd35bd88131
diff --git a/src/3rdparty/Lua b/src/3rdparty/Lua
new file mode 160000
+Subproject 940cf58b3109f41c2791a28e8a9db5b4af45919
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2.h
new file mode 100644
index 00000000..f64ec00b
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2.h
@@ -0,0 +1,677 @@
+#ifndef __gl2_h_
+#define __gl2_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
+*/
+
+#include <GLES2/gl2platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_NONE 0
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2ext.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2ext.h
new file mode 100644
index 00000000..2d055961
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2ext.h
@@ -0,0 +1,2946 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
+*/
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* Generated on date 20151015 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]
+ * Versions emitted: _nomatch_^
+ * Default extensions included: gles2
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_KHR_blend_equation_advanced
+#define GL_KHR_blend_equation_advanced 1
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_SCREEN_KHR 0x9295
+#define GL_OVERLAY_KHR 0x9296
+#define GL_DARKEN_KHR 0x9297
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLORBURN_KHR 0x929A
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_EXCLUSION_KHR 0x92A0
+#define GL_HSL_HUE_KHR 0x92AD
+#define GL_HSL_SATURATION_KHR 0x92AE
+#define GL_HSL_COLOR_KHR 0x92AF
+#define GL_HSL_LUMINOSITY_KHR 0x92B0
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void);
+#endif
+#endif /* GL_KHR_blend_equation_advanced */
+
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_KHR_context_flush_control 1
+#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#endif /* GL_KHR_context_flush_control */
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+typedef void (GL_APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_SAMPLER 0x82E6
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define GL_DEBUG_SOURCE_API_KHR 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define GL_BUFFER_KHR 0x82E0
+#define GL_SHADER_KHR 0x82E1
+#define GL_PROGRAM_KHR 0x82E2
+#define GL_VERTEX_ARRAY_KHR 0x8074
+#define GL_QUERY_KHR 0x82E3
+#define GL_PROGRAM_PIPELINE_KHR 0x82E4
+#define GL_SAMPLER_KHR 0x82E6
+#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define GL_DEBUG_OUTPUT_KHR 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define GL_STACK_OVERFLOW_KHR 0x0503
+#define GL_STACK_UNDERFLOW_KHR 0x0504
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void);
+GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params);
+#endif
+#endif /* GL_KHR_debug */
+
+#ifndef GL_KHR_no_error
+#define GL_KHR_no_error 1
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#endif /* GL_KHR_no_error */
+
+#ifndef GL_KHR_robust_buffer_access_behavior
+#define GL_KHR_robust_buffer_access_behavior 1
+#endif /* GL_KHR_robust_buffer_access_behavior */
+
+#ifndef GL_KHR_robustness
+#define GL_KHR_robustness 1
+#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3
+#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252
+#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define GL_NO_RESET_NOTIFICATION_KHR 0x8261
+#define GL_CONTEXT_LOST_KHR 0x0507
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsKHR (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvKHR (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivKHR (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#endif
+#endif /* GL_KHR_robustness */
+
+#ifndef GL_KHR_texture_compression_astc_hdr
+#define GL_KHR_texture_compression_astc_hdr 1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif /* GL_KHR_texture_compression_astc_hdr */
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
+#ifndef GL_KHR_texture_compression_astc_sliced_3d
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+#endif /* GL_KHR_texture_compression_astc_sliced_3d */
+
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+typedef void *GLeglImageOES;
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+#endif /* GL_OES_EGL_image */
+
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#endif /* GL_OES_EGL_image_external */
+
+#ifndef GL_OES_EGL_image_external_essl3
+#define GL_OES_EGL_image_external_essl3 1
+#endif /* GL_OES_EGL_image_external_essl3 */
+
+#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */
+
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#define GL_ETC1_RGB8_OES 0x8D64
+#endif /* GL_OES_compressed_ETC1_RGB8_texture */
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifndef GL_OES_copy_image
+#define GL_OES_copy_image 1
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyImageSubDataOES (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+#endif /* GL_OES_copy_image */
+
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif /* GL_OES_depth24 */
+
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#endif /* GL_OES_depth32 */
+
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif /* GL_OES_depth_texture */
+
+#ifndef GL_OES_draw_buffers_indexed
+#define GL_OES_draw_buffers_indexed 1
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+typedef void (GL_APIENTRYP PFNGLENABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIOESPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEnableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationiOES (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparateiOES (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunciOES (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparateiOES (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaskiOES (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediOES (GLenum target, GLuint index);
+#endif
+#endif /* GL_OES_draw_buffers_indexed */
+
+#ifndef GL_OES_draw_elements_base_vertex
+#define GL_OES_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexOES (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_OES_draw_elements_base_vertex */
+
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif /* GL_OES_element_index_uint */
+
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif /* GL_OES_fbo_render_mipmap */
+
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif /* GL_OES_fragment_precision_high */
+
+#ifndef GL_OES_geometry_point_size
+#define GL_OES_geometry_point_size 1
+#endif /* GL_OES_geometry_point_size */
+
+#ifndef GL_OES_geometry_shader
+#define GL_OES_geometry_shader 1
+#define GL_GEOMETRY_SHADER_OES 0x8DD9
+#define GL_GEOMETRY_SHADER_BIT_OES 0x00000004
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define GL_LAYER_PROVOKING_VERTEX_OES 0x825E
+#define GL_LINES_ADJACENCY_OES 0x000A
+#define GL_LINE_STRIP_ADJACENCY_OES 0x000B
+#define GL_TRIANGLES_ADJACENCY_OES 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_OES 0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION_OES 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_OES 0x8E4E
+#define GL_UNDEFINED_VERTEX_OES 0x8260
+#define GL_PRIMITIVES_GENERATED_OES 0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS_OES 0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureOES (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+#endif /* GL_OES_geometry_shader */
+
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#endif
+#endif /* GL_OES_get_program_binary */
+
+#ifndef GL_OES_gpu_shader5
+#define GL_OES_gpu_shader5 1
+#endif /* GL_OES_gpu_shader5 */
+
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void *GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_OES_mapbuffer */
+
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif /* GL_OES_packed_depth_stencil */
+
+#ifndef GL_OES_primitive_bounding_box
+#define GL_OES_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_OES 0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxOES (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_OES_primitive_bounding_box */
+
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#define GL_ALPHA8_OES 0x803C
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGB565_OES 0x8D62
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA8_OES 0x8058
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB10_A2_EXT 0x8059
+#endif /* GL_OES_required_internalformat */
+
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif /* GL_OES_rgb8_rgba8 */
+
+#ifndef GL_OES_sample_shading
+#define GL_OES_sample_shading 1
+#define GL_SAMPLE_SHADING_OES 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37
+typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGOESPROC) (GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMinSampleShadingOES (GLfloat value);
+#endif
+#endif /* GL_OES_sample_shading */
+
+#ifndef GL_OES_sample_variables
+#define GL_OES_sample_variables 1
+#endif /* GL_OES_sample_variables */
+
+#ifndef GL_OES_shader_image_atomic
+#define GL_OES_shader_image_atomic 1
+#endif /* GL_OES_shader_image_atomic */
+
+#ifndef GL_OES_shader_io_blocks
+#define GL_OES_shader_io_blocks 1
+#endif /* GL_OES_shader_io_blocks */
+
+#ifndef GL_OES_shader_multisample_interpolation
+#define GL_OES_shader_multisample_interpolation 1
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D
+#endif /* GL_OES_shader_multisample_interpolation */
+
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#endif /* GL_OES_standard_derivatives */
+
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#endif /* GL_OES_stencil1 */
+
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#endif /* GL_OES_stencil4 */
+
+#ifndef GL_OES_surfaceless_context
+#define GL_OES_surfaceless_context 1
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#endif /* GL_OES_surfaceless_context */
+
+#ifndef GL_OES_tessellation_point_size
+#define GL_OES_tessellation_point_size 1
+#endif /* GL_OES_tessellation_point_size */
+
+#ifndef GL_OES_tessellation_shader
+#define GL_OES_tessellation_shader 1
+#define GL_PATCHES_OES 0x000E
+#define GL_PATCH_VERTICES_OES 0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define GL_TESS_GEN_MODE_OES 0x8E76
+#define GL_TESS_GEN_SPACING_OES 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_OES 0x8E78
+#define GL_TESS_GEN_POINT_MODE_OES 0x8E79
+#define GL_ISOLINES_OES 0x8E7A
+#define GL_QUADS_OES 0x0007
+#define GL_FRACTIONAL_ODD_OES 0x8E7B
+#define GL_FRACTIONAL_EVEN_OES 0x8E7C
+#define GL_MAX_PATCH_VERTICES_OES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS_OES 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define GL_IS_PER_PATCH_OES 0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define GL_TESS_CONTROL_SHADER_OES 0x8E88
+#define GL_TESS_EVALUATION_SHADER_OES 0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT_OES 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPatchParameteriOES (GLenum pname, GLint value);
+#endif
+#endif /* GL_OES_tessellation_shader */
+
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_SAMPLER_3D_OES 0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+#endif /* GL_OES_texture_3D */
+
+#ifndef GL_OES_texture_border_clamp
+#define GL_OES_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_OES 0x1004
+#define GL_CLAMP_TO_BORDER_OES 0x812D
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexParameterIivOES (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivOES (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivOES (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivOES (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivOES (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivOES (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivOES (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivOES (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_OES_texture_border_clamp */
+
+#ifndef GL_OES_texture_buffer
+#define GL_OES_texture_buffer 1
+#define GL_TEXTURE_BUFFER_OES 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_OES 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_OES 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_OES 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define GL_SAMPLER_BUFFER_OES 0x8DC2
+#define GL_INT_SAMPLER_BUFFER_OES 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define GL_IMAGE_BUFFER_OES 0x9051
+#define GL_INT_IMAGE_BUFFER_OES 0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES 0x9067
+#define GL_TEXTURE_BUFFER_OFFSET_OES 0x919D
+#define GL_TEXTURE_BUFFER_SIZE_OES 0x919E
+typedef void (GL_APIENTRYP PFNGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexBufferOES (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRangeOES (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_OES_texture_buffer */
+
+#ifndef GL_OES_texture_compression_astc
+#define GL_OES_texture_compression_astc 1
+#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
+#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1
+#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2
+#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3
+#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4
+#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5
+#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6
+#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7
+#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8
+#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
+#endif /* GL_OES_texture_compression_astc */
+
+#ifndef GL_OES_texture_cube_map_array
+#define GL_OES_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_OES 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY_OES 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY_OES 0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#endif /* GL_OES_texture_cube_map_array */
+
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif /* GL_OES_texture_float */
+
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif /* GL_OES_texture_float_linear */
+
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#define GL_HALF_FLOAT_OES 0x8D61
+#endif /* GL_OES_texture_half_float */
+
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif /* GL_OES_texture_half_float_linear */
+
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif /* GL_OES_texture_npot */
+
+#ifndef GL_OES_texture_stencil8
+#define GL_OES_texture_stencil8 1
+#define GL_STENCIL_INDEX_OES 0x1901
+#define GL_STENCIL_INDEX8_OES 0x8D48
+#endif /* GL_OES_texture_stencil8 */
+
+#ifndef GL_OES_texture_storage_multisample_2d_array
+#define GL_OES_texture_storage_multisample_2d_array 1
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage3DMultisampleOES (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_OES_texture_storage_multisample_2d_array */
+
+#ifndef GL_OES_texture_view
+#define GL_OES_texture_view 1
+#define GL_TEXTURE_VIEW_MIN_LEVEL_OES 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS_OES 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER_OES 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS_OES 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureViewOES (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+#endif /* GL_OES_texture_view */
+
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+#endif /* GL_OES_vertex_array_object */
+
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif /* GL_OES_vertex_half_float */
+
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_INT_10_10_10_2_OES 0x8DF7
+#endif /* GL_OES_vertex_type_10_10_10_2 */
+
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#define GL_3DC_X_AMD 0x87F9
+#define GL_3DC_XY_AMD 0x87FA
+#endif /* GL_AMD_compressed_3DC_texture */
+
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#define GL_ATC_RGB_AMD 0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#endif /* GL_AMD_compressed_ATC_texture */
+
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+#endif /* GL_AMD_performance_monitor */
+
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#define GL_Z400_BINARY_AMD 0x8740
+#endif /* GL_AMD_program_binary_Z400 */
+
+#ifndef GL_ANDROID_extension_pack_es31a
+#define GL_ANDROID_extension_pack_es31a 1
+#endif /* GL_ANDROID_extension_pack_es31a */
+
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+#endif /* GL_ANGLE_depth_texture */
+
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* GL_ANGLE_framebuffer_blit */
+
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ANGLE_framebuffer_multisample */
+
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_ANGLE_instanced_arrays */
+
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+#endif /* GL_ANGLE_pack_reverse_row_order */
+
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#define GL_PROGRAM_BINARY_ANGLE 0x93A6
+#endif /* GL_ANGLE_program_binary */
+
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#endif /* GL_ANGLE_texture_compression_dxt3 */
+
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#endif /* GL_ANGLE_texture_compression_dxt5 */
+
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+#endif /* GL_ANGLE_texture_usage */
+
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+#endif /* GL_ANGLE_translated_shader_source */
+
+#ifndef GL_APPLE_clip_distance
+#define GL_APPLE_clip_distance 1
+#define GL_MAX_CLIP_DISTANCES_APPLE 0x0D32
+#define GL_CLIP_DISTANCE0_APPLE 0x3000
+#define GL_CLIP_DISTANCE1_APPLE 0x3001
+#define GL_CLIP_DISTANCE2_APPLE 0x3002
+#define GL_CLIP_DISTANCE3_APPLE 0x3003
+#define GL_CLIP_DISTANCE4_APPLE 0x3004
+#define GL_CLIP_DISTANCE5_APPLE 0x3005
+#define GL_CLIP_DISTANCE6_APPLE 0x3006
+#define GL_CLIP_DISTANCE7_APPLE 0x3007
+#endif /* GL_APPLE_clip_distance */
+
+#ifndef GL_APPLE_color_buffer_packed_float
+#define GL_APPLE_color_buffer_packed_float 1
+#endif /* GL_APPLE_color_buffer_packed_float */
+
+#ifndef GL_APPLE_copy_texture_levels
+#define GL_APPLE_copy_texture_levels 1
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+#endif /* GL_APPLE_copy_texture_levels */
+
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE 0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif
+#endif /* GL_APPLE_framebuffer_multisample */
+
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_RAW_422_APPLE 0x8A51
+#endif /* GL_APPLE_rgb_422 */
+
+#ifndef GL_APPLE_sync
+#define GL_APPLE_sync 1
+#define GL_SYNC_OBJECT_APPLE 0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define GL_OBJECT_TYPE_APPLE 0x9112
+#define GL_SYNC_CONDITION_APPLE 0x9113
+#define GL_SYNC_STATUS_APPLE 0x9114
+#define GL_SYNC_FLAGS_APPLE 0x9115
+#define GL_SYNC_FENCE_APPLE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE 0x9118
+#define GL_SIGNALED_APPLE 0x9119
+#define GL_ALREADY_SIGNALED_APPLE 0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define GL_CONDITION_SATISFIED_APPLE 0x911C
+#define GL_WAIT_FAILED_APPLE 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+#endif /* GL_APPLE_sync */
+
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#define GL_BGRA_EXT 0x80E1
+#define GL_BGRA8_EXT 0x93A1
+#endif /* GL_APPLE_texture_format_BGRA8888 */
+
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+#endif /* GL_APPLE_texture_max_level */
+
+#ifndef GL_APPLE_texture_packed_float
+#define GL_APPLE_texture_packed_float 1
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B
+#define GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E
+#define GL_R11F_G11F_B10F_APPLE 0x8C3A
+#define GL_RGB9_E5_APPLE 0x8C3D
+#endif /* GL_APPLE_texture_packed_float */
+
+#ifndef GL_ARM_mali_program_binary
+#define GL_ARM_mali_program_binary 1
+#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+#endif /* GL_ARM_mali_program_binary */
+
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+#endif /* GL_ARM_mali_shader_binary */
+
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif /* GL_ARM_rgba8 */
+
+#ifndef GL_ARM_shader_framebuffer_fetch
+#define GL_ARM_shader_framebuffer_fetch 1
+#define GL_FETCH_PER_SAMPLE_ARM 0x8F65
+#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66
+#endif /* GL_ARM_shader_framebuffer_fetch */
+
+#ifndef GL_ARM_shader_framebuffer_fetch_depth_stencil
+#define GL_ARM_shader_framebuffer_fetch_depth_stencil 1
+#endif /* GL_ARM_shader_framebuffer_fetch_depth_stencil */
+
+#ifndef GL_DMP_program_binary
+#define GL_DMP_program_binary 1
+#define GL_SMAPHS30_PROGRAM_BINARY_DMP 0x9251
+#define GL_SMAPHS_PROGRAM_BINARY_DMP 0x9252
+#define GL_DMP_PROGRAM_BINARY_DMP 0x9253
+#endif /* GL_DMP_program_binary */
+
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#define GL_SHADER_BINARY_DMP 0x9250
+#endif /* GL_DMP_shader_binary */
+
+#ifndef GL_EXT_YUV_target
+#define GL_EXT_YUV_target 1
+#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
+#endif /* GL_EXT_YUV_target */
+
+#ifndef GL_EXT_base_instance
+#define GL_EXT_base_instance 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedBaseInstanceEXT (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#endif
+#endif /* GL_EXT_base_instance */
+
+#ifndef GL_EXT_blend_func_extended
+#define GL_EXT_blend_func_extended 1
+#define GL_SRC1_COLOR_EXT 0x88F9
+#define GL_SRC1_ALPHA_EXT 0x8589
+#define GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB
+#define GL_SRC_ALPHA_SATURATE_EXT 0x0308
+#define GL_LOCATION_INDEX_EXT 0x930F
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindFragDataLocationIndexedEXT (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocationIndexEXT (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetFragDataIndexEXT (GLuint program, const GLchar *name);
+#endif
+#endif /* GL_EXT_blend_func_extended */
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#endif /* GL_EXT_blend_minmax */
+
+#ifndef GL_EXT_buffer_storage
+#define GL_EXT_buffer_storage 1
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
+#define GL_MAP_COHERENT_BIT_EXT 0x0080
+#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
+#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
+#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#endif
+#endif /* GL_EXT_buffer_storage */
+
+#ifndef GL_EXT_color_buffer_float
+#define GL_EXT_color_buffer_float 1
+#endif /* GL_EXT_color_buffer_float */
+
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_RG16F_EXT 0x822F
+#define GL_R16F_EXT 0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#endif /* GL_EXT_color_buffer_half_float */
+
+#ifndef GL_EXT_copy_image
+#define GL_EXT_copy_image 1
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyImageSubDataEXT (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+#endif /* GL_EXT_copy_image */
+
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_EXT_debug_label */
+
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+#endif /* GL_EXT_debug_marker */
+
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+#endif /* GL_EXT_discard_framebuffer */
+
+#ifndef GL_EXT_disjoint_timer_query
+#define GL_EXT_disjoint_timer_query 1
+#define GL_QUERY_COUNTER_BITS_EXT 0x8864
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#define GL_TIMESTAMP_EXT 0x8E28
+#define GL_GPU_DISJOINT_EXT 0x8FBB
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+#endif /* GL_EXT_disjoint_timer_query */
+
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define GL_DRAW_BUFFER0_EXT 0x8825
+#define GL_DRAW_BUFFER1_EXT 0x8826
+#define GL_DRAW_BUFFER2_EXT 0x8827
+#define GL_DRAW_BUFFER3_EXT 0x8828
+#define GL_DRAW_BUFFER4_EXT 0x8829
+#define GL_DRAW_BUFFER5_EXT 0x882A
+#define GL_DRAW_BUFFER6_EXT 0x882B
+#define GL_DRAW_BUFFER7_EXT 0x882C
+#define GL_DRAW_BUFFER8_EXT 0x882D
+#define GL_DRAW_BUFFER9_EXT 0x882E
+#define GL_DRAW_BUFFER10_EXT 0x882F
+#define GL_DRAW_BUFFER11_EXT 0x8830
+#define GL_DRAW_BUFFER12_EXT 0x8831
+#define GL_DRAW_BUFFER13_EXT 0x8832
+#define GL_DRAW_BUFFER14_EXT 0x8833
+#define GL_DRAW_BUFFER15_EXT 0x8834
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_EXT_draw_buffers */
+
+#ifndef GL_EXT_draw_buffers_indexed
+#define GL_EXT_draw_buffers_indexed 1
+typedef void (GL_APIENTRYP PFNGLENABLEIEXTPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIEXTPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIEXTPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIEXTPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIEXTPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIEXTPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEnableiEXT (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiEXT (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationiEXT (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparateiEXT (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunciEXT (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparateiEXT (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaskiEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT (GLenum target, GLuint index);
+#endif
+#endif /* GL_EXT_draw_buffers_indexed */
+
+#ifndef GL_EXT_draw_elements_base_vertex
+#define GL_EXT_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_EXT_draw_elements_base_vertex */
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_draw_instanced */
+
+#ifndef GL_EXT_float_blend
+#define GL_EXT_float_blend 1
+#endif /* GL_EXT_float_blend */
+
+#ifndef GL_EXT_geometry_point_size
+#define GL_EXT_geometry_point_size 1
+#endif /* GL_EXT_geometry_point_size */
+
+#ifndef GL_EXT_geometry_shader
+#define GL_EXT_geometry_shader 1
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F
+#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_UNDEFINED_VERTEX_EXT 0x8260
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+#endif /* GL_EXT_geometry_shader */
+
+#ifndef GL_EXT_gpu_shader5
+#define GL_EXT_gpu_shader5 1
+#endif /* GL_EXT_gpu_shader5 */
+
+#ifndef GL_EXT_instanced_arrays
+#define GL_EXT_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorEXT (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_EXT_instanced_arrays */
+
+#ifndef GL_EXT_map_buffer_range
+#define GL_EXT_map_buffer_range 1
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void *GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+#endif /* GL_EXT_map_buffer_range */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifndef GL_EXT_multi_draw_indirect
+#define GL_EXT_multi_draw_indirect 1
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysIndirectEXT (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsIndirectEXT (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif
+#endif /* GL_EXT_multi_draw_indirect */
+
+#ifndef GL_EXT_multisampled_compatibility
+#define GL_EXT_multisampled_compatibility 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#endif /* GL_EXT_multisampled_compatibility */
+
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+#endif /* GL_EXT_multisampled_render_to_texture */
+
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_EXT_multiview_draw_buffers 1
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index);
+GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data);
+#endif
+#endif /* GL_EXT_multiview_draw_buffers */
+
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#endif /* GL_EXT_occlusion_query_boolean */
+
+#ifndef GL_EXT_post_depth_coverage
+#define GL_EXT_post_depth_coverage 1
+#endif /* GL_EXT_post_depth_coverage */
+
+#ifndef GL_EXT_primitive_bounding_box
+#define GL_EXT_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxEXT (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_EXT_primitive_bounding_box */
+
+#ifndef GL_EXT_pvrtc_sRGB
+#define GL_EXT_pvrtc_sRGB 1
+#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
+#endif /* GL_EXT_pvrtc_sRGB */
+
+#ifndef GL_EXT_raster_multisample
+#define GL_EXT_raster_multisample 1
+#define GL_RASTER_MULTISAMPLE_EXT 0x9327
+#define GL_RASTER_SAMPLES_EXT 0x9328
+#define GL_MAX_RASTER_SAMPLES_EXT 0x9329
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C
+typedef void (GL_APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_EXT_raster_multisample */
+
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif /* GL_EXT_read_format_bgra */
+
+#ifndef GL_EXT_render_snorm
+#define GL_EXT_render_snorm 1
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM_EXT 0x8F98
+#define GL_RG16_SNORM_EXT 0x8F99
+#define GL_RGBA16_SNORM_EXT 0x8F9B
+#endif /* GL_EXT_render_snorm */
+
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_EXT_robustness */
+
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#endif /* GL_EXT_sRGB */
+
+#ifndef GL_EXT_sRGB_write_control
+#define GL_EXT_sRGB_write_control 1
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#endif /* GL_EXT_sRGB_write_control */
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+#endif /* GL_EXT_separate_shader_objects */
+
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#endif /* GL_EXT_shader_framebuffer_fetch */
+
+#ifndef GL_EXT_shader_implicit_conversions
+#define GL_EXT_shader_implicit_conversions 1
+#endif /* GL_EXT_shader_implicit_conversions */
+
+#ifndef GL_EXT_shader_integer_mix
+#define GL_EXT_shader_integer_mix 1
+#endif /* GL_EXT_shader_integer_mix */
+
+#ifndef GL_EXT_shader_io_blocks
+#define GL_EXT_shader_io_blocks 1
+#endif /* GL_EXT_shader_io_blocks */
+
+#ifndef GL_EXT_shader_pixel_local_storage
+#define GL_EXT_shader_pixel_local_storage 1
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67
+#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
+#endif /* GL_EXT_shader_pixel_local_storage */
+
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif /* GL_EXT_shader_texture_lod */
+
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#endif /* GL_EXT_shadow_samplers */
+
+#ifndef GL_EXT_sparse_texture
+#define GL_EXT_sparse_texture 1
+#define GL_TEXTURE_SPARSE_EXT 0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT 0x91A7
+#define GL_NUM_SPARSE_LEVELS_EXT 0x91AA
+#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT 0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_EXT 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_EXT 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_EXT 0x9197
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_3D 0x806F
+#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+typedef void (GL_APIENTRYP PFNGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexPageCommitmentEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#endif
+#endif /* GL_EXT_sparse_texture */
+
+#ifndef GL_EXT_tessellation_point_size
+#define GL_EXT_tessellation_point_size 1
+#endif /* GL_EXT_tessellation_point_size */
+
+#ifndef GL_EXT_tessellation_shader
+#define GL_EXT_tessellation_shader 1
+#define GL_PATCHES_EXT 0x000E
+#define GL_PATCH_VERTICES_EXT 0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75
+#define GL_TESS_GEN_MODE_EXT 0x8E76
+#define GL_TESS_GEN_SPACING_EXT 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78
+#define GL_TESS_GEN_POINT_MODE_EXT 0x8E79
+#define GL_ISOLINES_EXT 0x8E7A
+#define GL_QUADS_EXT 0x0007
+#define GL_FRACTIONAL_ODD_EXT 0x8E7B
+#define GL_FRACTIONAL_EVEN_EXT 0x8E7C
+#define GL_MAX_PATCH_VERTICES_EXT 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_IS_PER_PATCH_EXT 0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308
+#define GL_TESS_CONTROL_SHADER_EXT 0x8E88
+#define GL_TESS_EVALUATION_SHADER_EXT 0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIEXTPROC) (GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPatchParameteriEXT (GLenum pname, GLint value);
+#endif
+#endif /* GL_EXT_tessellation_shader */
+
+#ifndef GL_EXT_texture_border_clamp
+#define GL_EXT_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004
+#define GL_CLAMP_TO_BORDER_EXT 0x812D
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivEXT (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivEXT (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivEXT (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivEXT (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_EXT_texture_border_clamp */
+
+#ifndef GL_EXT_texture_buffer
+#define GL_EXT_texture_buffer 1
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D
+#define GL_TEXTURE_BUFFER_SIZE_EXT 0x919E
+typedef void (GL_APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEEXTPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_EXT_texture_buffer */
+
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#endif /* GL_EXT_texture_compression_dxt1 */
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifndef GL_EXT_texture_cube_map_array
+#define GL_EXT_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#endif /* GL_EXT_texture_cube_map_array */
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifndef GL_EXT_texture_filter_minmax
+#define GL_EXT_texture_filter_minmax 1
+#endif /* GL_EXT_texture_filter_minmax */
+
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif /* GL_EXT_texture_format_BGRA8888 */
+
+#ifndef GL_EXT_texture_norm16
+#define GL_EXT_texture_norm16 1
+#define GL_R16_EXT 0x822A
+#define GL_RG16_EXT 0x822C
+#define GL_RGBA16_EXT 0x805B
+#define GL_RGB16_EXT 0x8054
+#define GL_RGB16_SNORM_EXT 0x8F9A
+#endif /* GL_EXT_texture_norm16 */
+
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#define GL_RED_EXT 0x1903
+#define GL_RG_EXT 0x8227
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#endif /* GL_EXT_texture_rg */
+
+#ifndef GL_EXT_texture_sRGB_R8
+#define GL_EXT_texture_sRGB_R8 1
+#define GL_SR8_EXT 0x8FBD
+#endif /* GL_EXT_texture_sRGB_R8 */
+
+#ifndef GL_EXT_texture_sRGB_RG8
+#define GL_EXT_texture_sRGB_RG8 1
+#define GL_SRG8_EXT 0x8FBE
+#endif /* GL_EXT_texture_sRGB_RG8 */
+
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#endif /* GL_EXT_texture_sRGB_decode */
+
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGB32F_EXT 0x8815
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_R32F_EXT 0x822E
+#define GL_RG32F_EXT 0x8230
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+#endif /* GL_EXT_texture_storage */
+
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#endif /* GL_EXT_texture_type_2_10_10_10_REV */
+
+#ifndef GL_EXT_texture_view
+#define GL_EXT_texture_view 1
+#define GL_TEXTURE_VIEW_MIN_LEVEL_EXT 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE
+typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+#endif /* GL_EXT_texture_view */
+
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#endif /* GL_EXT_unpack_subimage */
+
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
+#endif /* GL_FJ_shader_binary_GCCSO */
+
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+#endif /* GL_IMG_multisampled_render_to_texture */
+
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+#endif /* GL_IMG_program_binary */
+
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif /* GL_IMG_read_format */
+
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#define GL_SGX_BINARY_IMG 0x8C0A
+#endif /* GL_IMG_shader_binary */
+
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif /* GL_IMG_texture_compression_pvrtc */
+
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_IMG_texture_compression_pvrtc2 1
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+#endif /* GL_IMG_texture_compression_pvrtc2 */
+
+#ifndef GL_IMG_texture_filter_cubic
+#define GL_IMG_texture_filter_cubic 1
+#define GL_CUBIC_IMG 0x9139
+#define GL_CUBIC_MIPMAP_NEAREST_IMG 0x913A
+#define GL_CUBIC_MIPMAP_LINEAR_IMG 0x913B
+#endif /* GL_IMG_texture_filter_cubic */
+
+#ifndef GL_INTEL_framebuffer_CMAA
+#define GL_INTEL_framebuffer_CMAA 1
+typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
+#endif
+#endif /* GL_INTEL_framebuffer_CMAA */
+
+#ifndef GL_INTEL_performance_query
+#define GL_INTEL_performance_query 1
+#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
+#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001
+#define GL_PERFQUERY_WAIT_INTEL 0x83FB
+#define GL_PERFQUERY_FLUSH_INTEL 0x83FA
+#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9
+#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0
+#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1
+#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2
+#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3
+#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4
+#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5
+#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8
+#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9
+#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA
+#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB
+#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC
+#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD
+#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE
+#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF
+#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500
+typedef void (GL_APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (GL_APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (GL_APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (GL_APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
+typedef void (GL_APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
+typedef void (GL_APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle);
+GL_APICALL void GL_APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle);
+GL_APICALL void GL_APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle);
+GL_APICALL void GL_APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
+GL_APICALL void GL_APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
+GL_APICALL void GL_APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
+GL_APICALL void GL_APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+GL_APICALL void GL_APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GL_APICALL void GL_APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
+GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#endif
+#endif /* GL_INTEL_performance_query */
+
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (GL_APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleNV (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GL_APICALL GLuint64 GL_APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GL_APICALL void GL_APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GL_APICALL void GL_APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GL_APICALL GLboolean GL_APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL GLboolean GL_APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
+
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+#define GL_BLEND_OVERLAP_NV 0x9281
+#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define GL_BLUE_NV 0x1905
+#define GL_COLORBURN_NV 0x929A
+#define GL_COLORDODGE_NV 0x9299
+#define GL_CONJOINT_NV 0x9284
+#define GL_CONTRAST_NV 0x92A1
+#define GL_DARKEN_NV 0x9297
+#define GL_DIFFERENCE_NV 0x929E
+#define GL_DISJOINT_NV 0x9283
+#define GL_DST_ATOP_NV 0x928F
+#define GL_DST_IN_NV 0x928B
+#define GL_DST_NV 0x9287
+#define GL_DST_OUT_NV 0x928D
+#define GL_DST_OVER_NV 0x9289
+#define GL_EXCLUSION_NV 0x92A0
+#define GL_GREEN_NV 0x1904
+#define GL_HARDLIGHT_NV 0x929B
+#define GL_HARDMIX_NV 0x92A9
+#define GL_HSL_COLOR_NV 0x92AF
+#define GL_HSL_HUE_NV 0x92AD
+#define GL_HSL_LUMINOSITY_NV 0x92B0
+#define GL_HSL_SATURATION_NV 0x92AE
+#define GL_INVERT_OVG_NV 0x92B4
+#define GL_INVERT_RGB_NV 0x92A3
+#define GL_LIGHTEN_NV 0x9298
+#define GL_LINEARBURN_NV 0x92A5
+#define GL_LINEARDODGE_NV 0x92A4
+#define GL_LINEARLIGHT_NV 0x92A7
+#define GL_MINUS_CLAMPED_NV 0x92B3
+#define GL_MINUS_NV 0x929F
+#define GL_MULTIPLY_NV 0x9294
+#define GL_OVERLAY_NV 0x9296
+#define GL_PINLIGHT_NV 0x92A8
+#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define GL_PLUS_CLAMPED_NV 0x92B1
+#define GL_PLUS_DARKER_NV 0x9292
+#define GL_PLUS_NV 0x9291
+#define GL_RED_NV 0x1903
+#define GL_SCREEN_NV 0x9295
+#define GL_SOFTLIGHT_NV 0x929C
+#define GL_SRC_ATOP_NV 0x928E
+#define GL_SRC_IN_NV 0x928A
+#define GL_SRC_NV 0x9286
+#define GL_SRC_OUT_NV 0x928C
+#define GL_SRC_OVER_NV 0x9288
+#define GL_UNCORRELATED_NV 0x9282
+#define GL_VIVIDLIGHT_NV 0x92A6
+#define GL_XOR_NV 0x1506
+typedef void (GL_APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendParameteriNV (GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glBlendBarrierNV (void);
+#endif
+#endif /* GL_NV_blend_equation_advanced */
+
+#ifndef GL_NV_blend_equation_advanced_coherent
+#define GL_NV_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+typedef void (GL_APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GL_APICALL void GL_APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_conservative_raster
+#define GL_NV_conservative_raster 1
+#define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
+#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347
+#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348
+#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349
+typedef void (GL_APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
+#endif
+#endif /* GL_NV_conservative_raster */
+
+#ifndef GL_NV_copy_buffer
+#define GL_NV_copy_buffer 1
+#define GL_COPY_READ_BUFFER_NV 0x8F36
+#define GL_COPY_WRITE_BUFFER_NV 0x8F37
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATANVPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyBufferSubDataNV (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif
+#endif /* GL_NV_copy_buffer */
+
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_SAMPLES_NV 0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV 0x00008000
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+#endif /* GL_NV_coverage_sample */
+
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#endif /* GL_NV_depth_nonlinear */
+
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define GL_DRAW_BUFFER0_NV 0x8825
+#define GL_DRAW_BUFFER1_NV 0x8826
+#define GL_DRAW_BUFFER2_NV 0x8827
+#define GL_DRAW_BUFFER3_NV 0x8828
+#define GL_DRAW_BUFFER4_NV 0x8829
+#define GL_DRAW_BUFFER5_NV 0x882A
+#define GL_DRAW_BUFFER6_NV 0x882B
+#define GL_DRAW_BUFFER7_NV 0x882C
+#define GL_DRAW_BUFFER8_NV 0x882D
+#define GL_DRAW_BUFFER9_NV 0x882E
+#define GL_DRAW_BUFFER10_NV 0x882F
+#define GL_DRAW_BUFFER11_NV 0x8830
+#define GL_DRAW_BUFFER12_NV 0x8831
+#define GL_DRAW_BUFFER13_NV 0x8832
+#define GL_DRAW_BUFFER14_NV 0x8833
+#define GL_DRAW_BUFFER15_NV 0x8834
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_NV_draw_buffers */
+
+#ifndef GL_NV_draw_instanced
+#define GL_NV_draw_instanced 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_NV_draw_instanced */
+
+#ifndef GL_NV_explicit_attrib_location
+#define GL_NV_explicit_attrib_location 1
+#endif /* GL_NV_explicit_attrib_location */
+
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+#endif /* GL_NV_fbo_color_attachments */
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+#endif /* GL_NV_fence */
+
+#ifndef GL_NV_fill_rectangle
+#define GL_NV_fill_rectangle 1
+#define GL_FILL_RECTANGLE_NV 0x933C
+#endif /* GL_NV_fill_rectangle */
+
+#ifndef GL_NV_fragment_coverage_to_color
+#define GL_NV_fragment_coverage_to_color 1
+#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV 0x92DD
+#define GL_FRAGMENT_COVERAGE_COLOR_NV 0x92DE
+typedef void (GL_APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFragmentCoverageColorNV (GLuint color);
+#endif
+#endif /* GL_NV_fragment_coverage_to_color */
+
+#ifndef GL_NV_fragment_shader_interlock
+#define GL_NV_fragment_shader_interlock 1
+#endif /* GL_NV_fragment_shader_interlock */
+
+#ifndef GL_NV_framebuffer_blit
+#define GL_NV_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_NV 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* GL_NV_framebuffer_blit */
+
+#ifndef GL_NV_framebuffer_mixed_samples
+#define GL_NV_framebuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_TABLE_NV 0x9331
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#define GL_DEPTH_SAMPLES_NV 0x932D
+#define GL_STENCIL_SAMPLES_NV 0x932E
+#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F
+#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330
+#define GL_COVERAGE_MODULATION_NV 0x9332
+#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v);
+GL_APICALL void GL_APIENTRY glCoverageModulationNV (GLenum components);
+#endif
+#endif /* GL_NV_framebuffer_mixed_samples */
+
+#ifndef GL_NV_framebuffer_multisample
+#define GL_NV_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56
+#define GL_MAX_SAMPLES_NV 0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_NV_framebuffer_multisample */
+
+#ifndef GL_NV_generate_mipmap_sRGB
+#define GL_NV_generate_mipmap_sRGB 1
+#endif /* GL_NV_generate_mipmap_sRGB */
+
+#ifndef GL_NV_geometry_shader_passthrough
+#define GL_NV_geometry_shader_passthrough 1
+#endif /* GL_NV_geometry_shader_passthrough */
+
+#ifndef GL_NV_image_formats
+#define GL_NV_image_formats 1
+#endif /* GL_NV_image_formats */
+
+#ifndef GL_NV_instanced_arrays
+#define GL_NV_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_NV_instanced_arrays */
+
+#ifndef GL_NV_internalformat_sample_query
+#define GL_NV_internalformat_sample_query 1
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_MULTISAMPLES_NV 0x9371
+#define GL_SUPERSAMPLE_SCALE_X_NV 0x9372
+#define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373
+#define GL_CONFORMANT_NV 0x9374
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_NV_internalformat_sample_query */
+
+#ifndef GL_NV_non_square_matrices
+#define GL_NV_non_square_matrices 1
+#define GL_FLOAT_MAT2x3_NV 0x8B65
+#define GL_FLOAT_MAT2x4_NV 0x8B66
+#define GL_FLOAT_MAT3x2_NV 0x8B67
+#define GL_FLOAT_MAT3x4_NV 0x8B68
+#define GL_FLOAT_MAT4x2_NV 0x8B69
+#define GL_FLOAT_MAT4x3_NV 0x8B6A
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+#endif /* GL_NV_non_square_matrices */
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_ROUNDED_RECT_NV 0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define GL_ROUNDED_RECT2_NV 0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define GL_ROUNDED_RECT4_NV 0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define GL_ROUNDED_RECT8_NV 0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define GL_RELATIVE_RECT_NV 0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define GL_FONT_UNAVAILABLE_NV 0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define GL_CONIC_CURVE_TO_NV 0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define GL_PATH_PROJECTION_NV 0x1701
+#define GL_PATH_MODELVIEW_NV 0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV 0x936D
+typedef GLuint (GL_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (GL_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (GL_APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (GL_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (GL_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (GL_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (GL_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_path_rendering_shared_edge
+#define GL_NV_path_rendering_shared_edge 1
+#define GL_SHARED_EDGE_NV 0xC0
+#endif /* GL_NV_path_rendering_shared_edge */
+
+#ifndef GL_NV_polygon_mode
+#define GL_NV_polygon_mode 1
+#define GL_POLYGON_MODE_NV 0x0B40
+#define GL_POLYGON_OFFSET_POINT_NV 0x2A01
+#define GL_POLYGON_OFFSET_LINE_NV 0x2A02
+#define GL_POINT_NV 0x1B00
+#define GL_LINE_NV 0x1B01
+#define GL_FILL_NV 0x1B02
+typedef void (GL_APIENTRYP PFNGLPOLYGONMODENVPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonModeNV (GLenum face, GLenum mode);
+#endif
+#endif /* GL_NV_polygon_mode */
+
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#define GL_READ_BUFFER_NV 0x0C02
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+#endif /* GL_NV_read_buffer */
+
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif /* GL_NV_read_buffer_front */
+
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif /* GL_NV_read_depth */
+
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif /* GL_NV_read_depth_stencil */
+
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif /* GL_NV_read_stencil */
+
+#ifndef GL_NV_sRGB_formats
+#define GL_NV_sRGB_formats 1
+#define GL_SLUMINANCE_NV 0x8C46
+#define GL_SLUMINANCE_ALPHA_NV 0x8C44
+#define GL_SRGB8_NV 0x8C41
+#define GL_SLUMINANCE8_NV 0x8C47
+#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+#define GL_ETC1_SRGB8_NV 0x88EE
+#endif /* GL_NV_sRGB_formats */
+
+#ifndef GL_NV_sample_locations
+#define GL_NV_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340
+#define GL_SAMPLE_LOCATION_NV 0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
+#endif
+#endif /* GL_NV_sample_locations */
+
+#ifndef GL_NV_sample_mask_override_coverage
+#define GL_NV_sample_mask_override_coverage 1
+#endif /* GL_NV_sample_mask_override_coverage */
+
+#ifndef GL_NV_shader_noperspective_interpolation
+#define GL_NV_shader_noperspective_interpolation 1
+#endif /* GL_NV_shader_noperspective_interpolation */
+
+#ifndef GL_NV_shadow_samplers_array
+#define GL_NV_shadow_samplers_array 1
+#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4
+#endif /* GL_NV_shadow_samplers_array */
+
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_NV_shadow_samplers_cube 1
+#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5
+#endif /* GL_NV_shadow_samplers_cube */
+
+#ifndef GL_NV_texture_border_clamp
+#define GL_NV_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_NV 0x1004
+#define GL_CLAMP_TO_BORDER_NV 0x812D
+#endif /* GL_NV_texture_border_clamp */
+
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif /* GL_NV_texture_compression_s3tc_update */
+
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif /* GL_NV_texture_npot_2D_mipmap */
+
+#ifndef GL_NV_viewport_array
+#define GL_NV_viewport_array 1
+#define GL_MAX_VIEWPORTS_NV 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_NV 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_NV 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDNVPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVNVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFNVPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VNVPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLENABLEINVPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEINVPROC) (GLenum target, GLuint index);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDINVPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfNV (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvNV (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvNV (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedNV (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvNV (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfNV (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vNV (GLenum target, GLuint index, GLfloat *data);
+GL_APICALL void GL_APIENTRY glEnableiNV (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiNV (GLenum target, GLuint index);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index);
+#endif
+#endif /* GL_NV_viewport_array */
+
+#ifndef GL_NV_viewport_array2
+#define GL_NV_viewport_array2 1
+#endif /* GL_NV_viewport_array2 */
+
+#ifndef GL_OVR_multiview
+#define GL_OVR_multiview 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_MAX_VIEWS_OVR 0x9631
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview */
+
+#ifndef GL_OVR_multiview2
+#define GL_OVR_multiview2 1
+#endif /* GL_OVR_multiview2 */
+
+#ifndef GL_OVR_multiview_multisampled_render_to_texture
+#define GL_OVR_multiview_multisampled_render_to_texture 1
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview_multisampled_render_to_texture */
+
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#define GL_ALPHA_TEST_QCOM 0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM 0x0BC2
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+#endif /* GL_QCOM_alpha_test */
+
+#ifndef GL_QCOM_binning_control
+#define GL_QCOM_binning_control 1
+#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+#endif /* GL_QCOM_binning_control */
+
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+#endif /* GL_QCOM_driver_control */
+
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, void **params);
+#endif
+#endif /* GL_QCOM_extended_get */
+
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+#endif /* GL_QCOM_extended_get2 */
+
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+#endif /* GL_QCOM_perfmon_global_mode */
+
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+#endif /* GL_QCOM_tiled_rendering */
+
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+#endif /* GL_QCOM_writeonly_rendering */
+
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#define GL_SHADER_BINARY_VIV 0x8FC4
+#endif /* GL_VIV_shader_binary */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2platform.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2platform.h
new file mode 100644
index 00000000..89d4d44d
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES2/gl2platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3.h
new file mode 100644
index 00000000..d51d2e65
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3.h
@@ -0,0 +1,1213 @@
+#ifndef __gl3_h_
+#define __gl3_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.0
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_NONE 0
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER 0x0C02
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_RED 0x1903
+#define GL_RGB8 0x8051
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_RG8 0x822B
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl31.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl31.h
new file mode 100644
index 00000000..9b89a0ac
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl31.h
@@ -0,0 +1,1528 @@
+#ifndef __gl31_h_
+#define __gl31_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision$ on $Date$
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.[01]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_NONE 0
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER 0x0C02
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_RED 0x1903
+#define GL_RGB8 0x8051
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_RG8 0x822B
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifndef GL_ES_VERSION_3_1
+#define GL_ES_VERSION_3_1 1
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_STENCIL_INDEX 0x1901
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+#endif
+#endif /* GL_ES_VERSION_3_1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl32.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl32.h
new file mode 100644
index 00000000..a2c36119
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl32.h
@@ -0,0 +1,1829 @@
+#ifndef __gl32_h_
+#define __gl32_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision$ on $Date$
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.[012]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_NONE 0
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER 0x0C02
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_RED 0x1903
+#define GL_RGB8 0x8051
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_RG8 0x822B
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifndef GL_ES_VERSION_3_1
+#define GL_ES_VERSION_3_1 1
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_STENCIL_INDEX 0x1901
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+#endif
+#endif /* GL_ES_VERSION_3_1 */
+
+#ifndef GL_ES_VERSION_3_2
+#define GL_ES_VERSION_3_2 1
+typedef void (GL_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_MULTISAMPLE_LINE_WIDTH_RANGE 0x9381
+#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY 0x9382
+#define GL_MULTIPLY 0x9294
+#define GL_SCREEN 0x9295
+#define GL_OVERLAY 0x9296
+#define GL_DARKEN 0x9297
+#define GL_LIGHTEN 0x9298
+#define GL_COLORDODGE 0x9299
+#define GL_COLORBURN 0x929A
+#define GL_HARDLIGHT 0x929B
+#define GL_SOFTLIGHT 0x929C
+#define GL_DIFFERENCE 0x929E
+#define GL_EXCLUSION 0x92A0
+#define GL_HSL_HUE 0x92AD
+#define GL_HSL_SATURATION 0x92AE
+#define GL_HSL_COLOR 0x92AF
+#define GL_HSL_LUMINOSITY 0x92B0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_UNDEFINED_VERTEX 0x8260
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_PRIMITIVE_BOUNDING_BOX 0x92BE
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_LOSE_CONTEXT_ON_RESET 0x8252
+#define GL_GUILTY_CONTEXT_RESET 0x8253
+#define GL_INNOCENT_CONTEXT_RESET 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
+#define GL_NO_RESET_NOTIFICATION 0x8261
+#define GL_CONTEXT_LOST 0x0507
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_PATCHES 0x000E
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_ISOLINES 0x8E7A
+#define GL_QUADS 0x0007
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendBarrier (void);
+GL_APICALL void GL_APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroup (void);
+GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glEnablei (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisablei (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBox (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatus (void);
+GL_APICALL void GL_APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GL_APICALL void GL_APIENTRY glMinSampleShading (GLfloat value);
+GL_APICALL void GL_APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_ES_VERSION_3_2 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3ext.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3ext.h
new file mode 100644
index 00000000..4d4ea96c
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3ext.h
@@ -0,0 +1,24 @@
+#ifndef __gl3ext_h_
+#define __gl3ext_h_
+
+/* $Revision: 17809 $ on $Date:: 2012-05-14 08:03:36 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* OpenGL ES 3 Extensions
+ *
+ * After an OES extension's interactions with OpenGl ES 3.0 have been documented,
+ * its tokens and function definitions should be added to this file in a manner
+ * that does not conflict with gl2ext.h or gl3.h.
+ *
+ * Tokens and function definitions for extensions that have become standard
+ * features in OpenGL ES 3.0 will not be added to this file.
+ *
+ * Applications using OpenGL-ES-2-only extensions should include gl2ext.h
+ */
+
+#endif /* __gl3ext_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3platform.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3platform.h
new file mode 100644
index 00000000..b1e869dd
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/GLES3/gl3platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl3platform_h_
+#define __gl3platform_h_
+
+/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl3platform_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/MinKD.c b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/MinKD.c
new file mode 100644
index 00000000..a96752bf
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/MinKD.c
@@ -0,0 +1,317 @@
+#include "kd.h"
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <memory.h>
+#include <pthread.h>
+#include <dirent.h>
+
+
+KDFile* kdFopen(const KDchar* pathname, const KDchar* mode)
+{
+ FILE* retval;
+ retval = fopen( pathname, mode );
+ return (KDFile*)retval;
+}
+
+
+KDsize kdFread(void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fread( buffer, size, count, (FILE*)file );
+}
+
+/* kdFwrite: Write to a file. */
+KDsize kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fwrite( buffer, size, count, (FILE*)file );
+}
+
+KDint kdFclose(KDFile *file)
+{
+ return fclose( (FILE*)file );
+}
+
+/* kdCosf: Cosine function. */
+KDfloat32 kdCosf(KDfloat32 x) { return cosf( x ); }
+
+/* kdSinf: Sine function. */
+KDfloat32 kdSinf(KDfloat32 x) { return sinf( x ); }
+
+KDfloat32 kdSqrtf(KDfloat32 x ) { return sqrtf( x ); }
+
+KDfloat32 kdTanf( KDfloat32 x ) { return tanf( x ); }
+
+KDint kdAbs(KDint i)
+{
+ return i < 0 ? -i : i;
+}
+
+
+KDfloat32 kdFabsf(KDfloat32 i) { return fabs( i ); }
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+
+KDint kdStrcpy_s(KDchar* buf, KDsize buflen, const KDchar* src)
+{
+ return kdStrncpy_s(buf, buflen, src, -1);
+}
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KDint kdStrncpy_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srclen)
+{
+ if ( srclen == (KDsize)-1)
+ srclen = buflen;
+ const char* term = memchr(src, 0, srclen);
+ if (term)
+ srclen = term - src;
+ if (srclen >= buflen) {
+ if (buflen)
+ *buf = 0;
+ return KD_EINVAL;
+ }
+ memcpy(buf, src, srclen);
+ buf[srclen] = 0;
+ return 0;
+}
+
+/* kdStrncat_s: Concatenate two strings. */
+KDint kdStrncat_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srcmaxlen)
+{
+ size_t origlen = strlen(buf);
+ const char* p = memchr(src, 0, srcmaxlen);
+ if (p)
+ srcmaxlen = p - src;
+ if (origlen + srcmaxlen >= buflen)
+ {
+ /* spec says "buf[0] is set to 0". But that's bad if buflen == 0!
+ * kdStrncpy_s's spec is better here. */
+ if (buflen)
+ buf[0] = 0;
+ return KD_ERANGE;
+ }
+ memcpy(buf + origlen, src, srcmaxlen);
+ buf[origlen + srcmaxlen] = 0;
+ return 0;
+}
+/* kdMemset: Set bytes in memory to a value. */
+void* kdMemset(void *buf, KDint byte, KDsize len) { return memset( buf, byte, len ); }
+
+/* kdStrcmp: Compares two strings. */
+KDint kdStrcmp(const KDchar *str1, const KDchar *str2) { return strcmp( str1, str2); }
+
+/* kdStrlen: Determine the length of a string. */
+KDsize kdStrlen(const KDchar *str) { return strlen( str ); }
+
+void* kdMalloc( KDsize size ) { return malloc(size); }
+
+void kdFree( void* ptr ) { free( ptr ); }
+
+void* kdMemcpy(void *buf, const void *src, KDsize len) { return memcpy( buf, src, len ); }
+
+struct KDThreadMutex
+{
+ pthread_mutex_t p_mutex;
+};
+
+/* kdThreadMutexCreate: Create a mutex. */
+KD_API KDThreadMutex* kdThreadMutexCreate(const void *mutexattr)
+{
+ KDThreadMutex* mutex = malloc(sizeof(KDThreadMutex));
+ if (mutex)
+ {
+ if (pthread_mutex_init(&mutex->p_mutex, NULL) == 0)
+ {
+ return mutex;
+ }
+ free(mutex);
+ }
+
+ return KD_NULL;
+}
+
+/* kdThreadMutexFree: Free a mutex. */
+KDint kdThreadMutexFree(KDThreadMutex *mutex)
+{
+ int res;
+ res = pthread_mutex_destroy(&mutex->p_mutex);
+ // If the mutex destroy failed, don't free the memory.
+ // Per OpenKODE spec, this is undefined behaviour, and
+ // we can leak the memory. The reason for this is that
+ // later allocations may fail if they happen to go
+ // to the same memory
+ if (!res)
+ free(mutex);
+ return 0;
+}
+
+/* kdThreadMutexLock: Lock a mutex. */
+KDint kdThreadMutexLock(KDThreadMutex *mutex)
+{
+ (void)pthread_mutex_lock(&mutex->p_mutex);
+ return 0;
+}
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KDint kdThreadMutexUnlock(KDThreadMutex *mutex)
+{
+ pthread_mutex_unlock(&mutex->p_mutex);
+ return 0;
+}
+
+struct KDThreadAttr
+{
+ pthread_attr_t p_attr;
+};
+
+struct KDThread
+{
+ pthread_t Handle;
+ uint8_t Detached;
+ uint8_t IsRunning;
+ uint8_t UserThread;
+ void* (*UserThreadProc)(void*);
+ void* UserArg;
+};
+/* kdThreadCreate: Create a new thread. */
+KDThread * kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg)
+{
+ pthread_t thread;
+ int retval;
+ const pthread_attr_t* p_attr;
+ if ( attr )
+ p_attr = &attr->p_attr;
+ else
+ p_attr = KD_NULL;
+
+ retval = pthread_create( &thread, p_attr, start_routine, arg );
+ if ( retval != 0 )
+ {
+ return KD_NULL;
+ }
+ KDThread* newThread = (KDThread*)malloc( sizeof( KDThread ) );
+ if ( newThread == KD_NULL ) return KD_NULL;
+ newThread->Handle = thread;
+ newThread->Detached = 0;
+ newThread->IsRunning = 1;
+ newThread->UserThread = 1;
+ newThread->UserThreadProc = start_routine;
+ newThread->UserArg = arg;
+ return newThread;
+}
+
+/* kdThreadExit: Terminate this thread. */
+void kdThreadExit(void *retval)
+{
+ pthread_exit( retval );
+}
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KDint kdThreadJoin(KDThread *thread, void **retval)
+{
+ int join_retval;
+ join_retval = pthread_join( thread->Handle, retval );
+ if ( join_retval == 0 ) free( thread );
+ return join_retval;
+}
+
+typedef struct KDDirInternal {
+ DIR *dir;
+ KDDirent ent;
+} KDDirInternal;
+
+/* kdOpenDir: Open a directory ready for listing. */
+KDDir *kdOpenDir(const KDchar *pathname)
+{
+ DIR* dir = opendir( pathname );
+ if ( dir == KD_NULL ) return KD_NULL;
+ KDDirInternal* retval = (KDDirInternal*)malloc( sizeof( KDDirInternal ));
+ if ( retval == KD_NULL ) return KD_NULL;
+ memset( retval, 0, sizeof( *retval ) );
+ retval->dir = dir;
+ return (KDDir*)retval;
+}
+
+/* kdReadDir: Return the next file in a directory. */
+KDDirent* kdReadDir(KDDir *dir)
+{
+ struct dirent *sysDirEnt;
+ KDDirent *dirent = NULL;
+
+ sysDirEnt = readdir(((KDDirInternal *)dir)->dir);
+
+ if (sysDirEnt) {
+ dirent = &((KDDirInternal *)dir)->ent;
+ dirent->d_name = sysDirEnt->d_name;
+ }
+ return dirent;
+}
+
+/* kdCloseDir: Close a directory. */
+KDint kdCloseDir(KDDir *dir)
+{
+ closedir(((KDDirInternal *)dir)->dir);
+ free(dir);
+ return 0;
+}
+
+KDint kdSetWindowPropertyiv(KDWindow * win, KDint prop, const KDint32 * val)
+{
+ return 0;
+}
+
+void kdDefaultEvent(const KDEvent *event )
+{
+
+}
+
+typedef long long NvS64;
+
+KDust kdGetTimeUST(void)
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+
+ return (NvS64)tp.tv_sec * (NvS64)1000000000 +
+ (NvS64)tp.tv_nsec;
+}
+
+static KDTm* gmlocaltime(
+ const KDtime *timep,
+ KDTm *result,
+ struct tm* (* func)(const time_t* timep, struct tm* result))
+{
+ struct tm tm;
+ time_t t = *timep;
+ (*func)(&t, &tm);
+ result->tm_sec = tm.tm_sec;
+ result->tm_min = tm.tm_min;
+ result->tm_hour = tm.tm_hour;
+ result->tm_mday = tm.tm_mday;
+ result->tm_mon = tm.tm_mon;
+ result->tm_year = tm.tm_year;
+ result->tm_wday = tm.tm_wday;
+ result->tm_yday = tm.tm_yday;
+ return result;
+}
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+KDTm* kdGmtime_r(const KDtime* timep, KDTm* result)
+{
+ return gmlocaltime(timep, result, &gmtime_r);
+}
+
+KDTm* kdLocaltime_r(const KDtime* timep, KDTm* result)
+{
+ return gmlocaltime(timep, result, &localtime_r);
+}
+
+//===========================================================================
+// kdCreateEvent: Create an event for posting.
+//===========================================================================
+KDEvent* kdCreateEvent(void)
+{
+ //Memory leak and there isn't much I am going to do about this now
+ KDEvent* newEvent = (KDEvent*)malloc( sizeof( KDEvent ));
+ memset( newEvent, 0, sizeof( KDEvent ));
+ return newEvent;
+}
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_extwindowprops.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_extwindowprops.h
new file mode 100644
index 00000000..4428a568
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_extwindowprops.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_extwindowprops_h_
+#define __kd_QT3DS_extwindowprops_h_
+#include <KD/kd.h>
+#include <EGL/eglext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_WINDOWPROPERTY_FULLSCREEN: Control over resizing a window to fill the complete screen */
+
+// KDboolean - set the window to fullscreen mode
+#define KD_WINDOWPROPERTY_FULLSCREEN_QT3DS 9999
+
+// KDint - set which KD_DISPLAY_* display that the window should be opened on
+#define KD_WINDOWPROPERTY_DISPLAY_QT3DS 9998
+
+// KDboolean - sets whether overlay should be used to create window
+#define KD_WINDOWPROPERTY_OVERLAY_QT3DS 9997
+
+#define KD_DISPLAY_PRIMARY_QT3DS 0
+#define KD_DISPLAY_INTERNAL0_QT3DS 0
+#define KD_DISPLAY_INTERNAL1_QT3DS 1
+#define KD_DISPLAY_INTERNAL2_QT3DS 2
+#define KD_DISPLAY_INTERNAL3_QT3DS 3
+#define KD_DISPLAY_EXTERNAL0_QT3DS 1000
+#define KD_DISPLAY_EXTERNAL1_QT3DS 1001
+#define KD_DISPLAY_EXTERNAL2_QT3DS 1002
+#define KD_DISPLAY_EXTERNAL3_QT3DS 1003
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_extwindowprops_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_multitouch.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_multitouch.h
new file mode 100644
index 00000000..e230b029
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/Qt3DS_multitouch.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_multitouch_h_
+#define __kd_QT3DS_multitouch_h_
+#include <KD/kd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_IOGROUP_MULTITOUCH: I/O group for Multitouch input devices. */
+#define KD_IOGROUP_MULTITOUCH_QT3DS 0x40004000
+#define KD_STATE_MULTITOUCH_AVAILABILITY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 0)
+#define KD_INPUT_MULTITOUCH_FINGERS_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 1)
+#define KD_INPUT_MULTITOUCH_WIDTH_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 2)
+#define KD_INPUT_MULTITOUCH_X_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 3)
+#define KD_INPUT_MULTITOUCH_Y_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 4)
+#define KD_INPUT_MULTITOUCH_X2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 5)
+#define KD_INPUT_MULTITOUCH_Y2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 6)
+#define KD_INPUT_MULTITOUCH_PRESSURE_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 7)
+#define KD_INPUT_MULTITOUCH_GESTURES_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 8)
+#define KD_INPUT_MULTITOUCH_RELX_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 9)
+#define KD_INPUT_MULTITOUCH_RELY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 10)
+
+/* KD_EVENT_INPUT_MULTITOUCH_QT3DS: Multitouch event. */
+#define KD_EVENT_INPUT_MULTITOUCH_QT3DS 1001
+typedef struct KDEventInputMultitouchDataNV
+{
+ KDint32 index;
+ KDint8 fingers;
+ KDint8 width;
+ KDint16 x;
+ KDint16 y;
+ KDint16 x2;
+ KDint16 y2;
+ KDint16 pressure;
+} KDEventInputMultitouchDataNV;
+
+/* KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS: Multitouch gesture event. */
+#define KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS 1002
+
+/* kdGetEventInputMultitouchDataNV: Get auxiliary event data for multitouch input. */
+KD_API KDint KD_APIENTRY kdGetEventInputMultitouchDataNV(const KDEvent *event,
+ KDEventInputMultitouchDataNV *data);
+
+/* kdSetEventInputMultitouchActiveNV: Activate Multitouch input events */
+KD_API KDint KD_APIENTRY kdSetEventInputMultitouchActiveNV(KDboolean activate);
+
+/* kdEnableEventInputMultitouchMergeNV: Activate merging of Multitouch input events */
+KD_API void KD_APIENTRY kdEnableEventInputMultitouchMergeNV(KDboolean enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_multitouch_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kd.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kd.h
new file mode 100644
index 00000000..f7ccea03
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kd.h
@@ -0,0 +1,991 @@
+/* Reference KD/kd.h for OpenKODE Core 1.0.3 */
+#ifndef __kd_h_
+#define __kd_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kdplatform.h"
+
+
+
+/*******************************************************
+ * Introduction
+ *******************************************************/
+
+/*******************************************************
+ * OpenKODE conformance
+ *******************************************************/
+
+/*******************************************************
+ * Overview
+ *******************************************************/
+
+/*******************************************************
+ * Programming environment
+ *******************************************************/
+#define KD_VERSION_1_0 1
+typedef char KDchar;
+typedef signed char KDint8;
+typedef unsigned char KDuint8;
+typedef int KDint;
+typedef unsigned int KDuint;
+typedef float KDfloat32;
+typedef KDint KDboolean;
+typedef KDint64 KDtime;
+typedef KDint64 KDust;
+typedef KDint64 KDoff;
+typedef KDuint32 KDmode;
+#define KDINT32_MIN (-0x7fffffff-1)
+#define KDINT32_MAX 0x7fffffff
+#define KDUINT32_MAX 0xffffffffU
+#define KD_TRUE 1
+#define KD_FALSE 0
+#ifdef __cplusplus
+ const int KD_NULL = 0; /* Yes, int. See Stroustrup 3rd edition. */
+#else
+ #define KD_NULL ((void *)0)
+#endif
+
+/*******************************************************
+ * Errors
+ *******************************************************/
+#define KD_EACCES 1
+#define KD_EADDRINUSE 2
+#define KD_EADDRNOTAVAIL 3
+#define KD_EAFNOSUPPORT 4
+#define KD_EAGAIN (5)
+#define KD_EALREADY 6
+#define KD_EBADF 7
+#define KD_EBUSY 8
+#define KD_ECONNREFUSED 9
+#define KD_ECONNRESET 10
+#define KD_EDEADLK 11
+#define KD_EDESTADDRREQ 12
+#define KD_EEXIST 13
+#define KD_EFBIG 14
+#define KD_EHOSTUNREACH 15
+#define KD_EHOST_NOT_FOUND 16
+#define KD_EINVAL 17
+#define KD_EIO 18
+#define KD_EILSEQ 19
+#define KD_EISCONN 20
+#define KD_EISDIR 21
+#define KD_EMFILE 22
+#define KD_ENAMETOOLONG 23
+#define KD_ENOENT 24
+#define KD_ENOMEM 25
+#define KD_ENOSPC 26
+#define KD_ENOSYS 27
+#define KD_ENOTCONN 28
+#define KD_ENO_DATA 29
+#define KD_ENO_RECOVERY 30
+#define KD_EOPNOTSUPP 31
+#define KD_EOVERFLOW 32
+#define KD_EPERM 33
+#define KD_ERANGE 35
+#define KD_ETIMEDOUT (36)
+#define KD_ETRY_AGAIN 37
+
+/* kdGetError: Get last error indication. */
+KD_API KDint KD_APIENTRY kdGetError(void);
+
+/* kdSetError: Set last error indication. */
+KD_API void KD_APIENTRY kdSetError(KDint error);
+
+/*******************************************************
+ * Versioning and attribute queries
+ *******************************************************/
+
+/* kdQueryAttribi: Obtain the value of a numeric OpenKODE Core attribute. */
+KD_API KDint KD_APIENTRY kdQueryAttribi(KDint attribute, KDint *value);
+
+/* kdQueryAttribcv: Obtain the value of a string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryAttribcv(KDint attribute);
+#define KD_ATTRIB_VENDOR 39
+#define KD_ATTRIB_VERSION 40
+#define KD_ATTRIB_PLATFORM 41
+
+/* kdQueryIndexedAttribcv: Obtain the value of an indexed string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryIndexedAttribcv(KDint attribute, KDint index);
+
+/*******************************************************
+ * Threads and synchronization
+ *******************************************************/
+
+/* kdThreadAttrCreate: Create a thread attribute object. */
+typedef struct KDThreadAttr KDThreadAttr;
+KD_API KDThreadAttr *KD_APIENTRY kdThreadAttrCreate(void);
+
+/* kdThreadAttrFree: Free a thread attribute object. */
+KD_API KDint KD_APIENTRY kdThreadAttrFree(KDThreadAttr *attr);
+
+/* kdThreadAttrSetDetachState: Set detachstate attribute. */
+#define KD_THREAD_CREATE_JOINABLE 0
+#define KD_THREAD_CREATE_DETACHED 1
+KD_API KDint KD_APIENTRY kdThreadAttrSetDetachState(KDThreadAttr *attr, KDint detachstate);
+
+/* kdThreadAttrSetStackSize: Set stacksize attribute. */
+KD_API KDint KD_APIENTRY kdThreadAttrSetStackSize(KDThreadAttr *attr, KDsize stacksize);
+
+/* kdThreadCreate: Create a new thread. */
+typedef struct KDThread KDThread;
+KD_API KDThread *KD_APIENTRY kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg);
+
+/* kdThreadExit: Terminate this thread. */
+KD_API KD_NORETURN void KD_APIENTRY kdThreadExit(void *retval);
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KD_API KDint KD_APIENTRY kdThreadJoin(KDThread *thread, void **retval);
+
+/* kdThreadDetach: Allow resources to be freed as soon as a thread terminates. */
+KD_API KDint KD_APIENTRY kdThreadDetach(KDThread *thread);
+
+/* kdThreadSelf: Return calling thread&#8217;s ID. */
+KD_API KDThread *KD_APIENTRY kdThreadSelf(void);
+
+/* kdThreadOnce: Wrap initialization code so it is executed only once. */
+#ifndef KD_NO_STATIC_DATA
+typedef struct KDThreadOnce {
+ void *impl;
+} KDThreadOnce;
+#define KD_THREAD_ONCE_INIT { 0 }
+KD_API KDint KD_APIENTRY kdThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void));
+#endif /* ndef KD_NO_STATIC_DATA */
+
+/* kdThreadMutexCreate: Create a mutex. */
+typedef struct KDThreadMutex KDThreadMutex;
+KD_API KDThreadMutex *KD_APIENTRY kdThreadMutexCreate(const void *mutexattr);
+
+/* kdThreadMutexFree: Free a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexFree(KDThreadMutex *mutex);
+
+/* kdThreadMutexLock: Lock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexLock(KDThreadMutex *mutex);
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexUnlock(KDThreadMutex *mutex);
+
+/* kdThreadCondCreate: Create a condition variable. */
+typedef struct KDThreadCond KDThreadCond;
+KD_API KDThreadCond *KD_APIENTRY kdThreadCondCreate(const void *attr);
+
+/* kdThreadCondFree: Free a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondFree(KDThreadCond *cond);
+
+/* kdThreadCondSignal, kdThreadCondBroadcast: Signal a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondSignal(KDThreadCond *cond);
+KD_API KDint KD_APIENTRY kdThreadCondBroadcast(KDThreadCond *cond);
+
+/* kdThreadCondWait: Wait for a condition variable to be signalled. */
+KD_API KDint KD_APIENTRY kdThreadCondWait(KDThreadCond *cond, KDThreadMutex *mutex);
+
+/* kdThreadSemCreate: Create a semaphore. */
+typedef struct KDThreadSem KDThreadSem;
+KD_API KDThreadSem *KD_APIENTRY kdThreadSemCreate(KDuint value);
+
+/* kdThreadSemFree: Free a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemFree(KDThreadSem *sem);
+
+/* kdThreadSemWait: Lock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemWait(KDThreadSem *sem);
+
+/* kdThreadSemPost: Unlock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemPost(KDThreadSem *sem);
+
+/*******************************************************
+ * Events
+ *******************************************************/
+
+/* KDEvent: Struct type containing an event. */
+typedef struct KDEvent KDEvent;
+#define KD_EVENT_USER 0x40000000
+
+/* kdWaitEvent: Get next event from thread&#8217;s event queue. */
+KD_API const KDEvent *KD_APIENTRY kdWaitEvent(KDust timeout);
+
+/* kdSetEventUserptr: Set the userptr for global events. */
+KD_API void KD_APIENTRY kdSetEventUserptr(void *userptr);
+
+/* kdDefaultEvent: Perform default processing on an unrecognized event. */
+KD_API void KD_APIENTRY kdDefaultEvent(const KDEvent *event);
+
+/* kdPumpEvents: Pump the thread&#8217;s event queue, performing callbacks. */
+KD_API KDint KD_APIENTRY kdPumpEvents(void);
+
+/* kdInstallCallback: Install or remove a callback function for event processing. */
+typedef void (KD_APIENTRY KDCallbackFunc)(const KDEvent *event);
+KD_API KDint KD_APIENTRY kdInstallCallback(KDCallbackFunc *func, KDint eventtype, void *eventuserptr);
+
+/* kdCreateEvent: Create an event for posting. */
+KD_API KDEvent *KD_APIENTRY kdCreateEvent(void);
+
+/* kdPostEvent, kdPostThreadEvent: Post an event into a queue. */
+KD_API KDint KD_APIENTRY kdPostEvent(KDEvent *event);
+KD_API KDint KD_APIENTRY kdPostThreadEvent(KDEvent *event, KDThread *thread);
+typedef struct KDEventUser {
+ union {
+ KDint64 i64;
+ void *p;
+ struct {
+ KDint32 a;
+ KDint32 b;
+ } i32pair;
+ } value1;
+ union {
+ KDint64 i64;
+ struct {
+ union {
+ KDint32 i32;
+ void *p;
+ } value2;
+ union {
+ KDint32 i32;
+ void *p;
+ } value3;
+ } i32orp;
+ } value23;
+} KDEventUser;
+
+/* kdFreeEvent: Abandon an event instead of posting it. */
+KD_API void KD_APIENTRY kdFreeEvent(KDEvent *event);
+
+/*******************************************************
+ * System events
+ *******************************************************/
+
+/* KD_EVENT_QUIT: Event to request to quit application. */
+#define KD_EVENT_QUIT 43
+
+/* KD_EVENT_PAUSE: Application pause event. */
+#define KD_EVENT_PAUSE 45
+
+/* KD_EVENT_RESUME: Application resume event. */
+#define KD_EVENT_RESUME 46
+
+/* KD_EVENT_ORIENTATION: Orientation change event. */
+#define KD_EVENT_ORIENTATION 48
+
+/* KD_IOGROUP_EVENT: I/O group for OpenKODE Core system events implemented as state values. */
+#define KD_IOGROUP_EVENT 0x100
+#define KD_STATE_EVENT_USING_BATTERY (KD_IOGROUP_EVENT + 0)
+#define KD_STATE_EVENT_LOW_BATTERY (KD_IOGROUP_EVENT + 1)
+
+
+/* KD_IOGROUP_ORIENTATION: I/O group for OpenKODE Core orientation state. */
+#define KD_IOGROUP_ORIENTATION 0x200
+#define KD_STATE_ORIENTATION_OVERALL (KD_IOGROUP_ORIENTATION + 0)
+#define KD_STATE_ORIENTATION_SCREEN (KD_IOGROUP_ORIENTATION + 1)
+#define KD_STATE_ORIENTATION_RENDERING (KD_IOGROUP_ORIENTATION + 2)
+#define KD_STATE_ORIENTATION_LOCKSURFACE (KD_IOGROUP_ORIENTATION + 3)
+
+
+/*******************************************************
+ * Application startup and exit.
+ *******************************************************/
+
+/* kdMain: The application-defined main function. */
+KDint KD_APIENTRY kdMain(KDint argc, const KDchar *const *argv);
+
+/* kdExit: Exit the application. */
+KD_API KD_NORETURN void KD_APIENTRY kdExit(KDint status);
+
+/*******************************************************
+ * Utility library functions
+ *******************************************************/
+
+/* kdAbs: Compute the absolute value of an integer. */
+KD_API KDint KD_APIENTRY kdAbs(KDint i);
+
+/* kdStrtof: Convert a string to a floating point number. */
+KD_API KDfloat32 KD_APIENTRY kdStrtof(const KDchar *s, KDchar **endptr);
+
+/* kdStrtol, kdStrtoul: Convert a string to an integer. */
+KD_API KDint KD_APIENTRY kdStrtol(const KDchar *s, KDchar **endptr, KDint base);
+KD_API KDuint KD_APIENTRY kdStrtoul(const KDchar *s, KDchar **endptr, KDint base);
+
+/* kdLtostr, kdUltostr: Convert an integer to a string. */
+#define KD_LTOSTR_MAXLEN ((sizeof(KDint)*8*3+6)/10+2)
+#define KD_ULTOSTR_MAXLEN ((sizeof(KDint)*8+2)/3+1)
+KD_API KDssize KD_APIENTRY kdLtostr(KDchar *buffer, KDsize buflen, KDint number);
+KD_API KDssize KD_APIENTRY kdUltostr(KDchar *buffer, KDsize buflen, KDuint number, KDint base);
+
+/* kdFtostr: Convert a float to a string. */
+#define KD_FTOSTR_MAXLEN 16
+KD_API KDssize KD_APIENTRY kdFtostr(KDchar *buffer, KDsize buflen, KDfloat32 number);
+
+/* kdCryptoRandom: Return random data. */
+KD_API KDint KD_APIENTRY kdCryptoRandom(KDuint8 *buf, KDsize buflen);
+
+/*******************************************************
+ * Locale specific functions
+ *******************************************************/
+
+/* kdGetLocale: Determine the current language and locale. */
+KD_API const KDchar *KD_APIENTRY kdGetLocale(void);
+
+/*******************************************************
+ * Memory allocation
+ *******************************************************/
+
+/* kdMalloc: Allocate memory. */
+KD_API void *KD_APIENTRY kdMalloc(KDsize size);
+
+/* kdFree: Free allocated memory block. */
+KD_API void KD_APIENTRY kdFree(void *ptr);
+
+/* kdRealloc: Resize memory block. */
+KD_API void *KD_APIENTRY kdRealloc(void *ptr, KDsize size);
+
+/*******************************************************
+ * Thread-local storage.
+ *******************************************************/
+
+/* kdGetTLS: Get the thread-local storage pointer. */
+KD_API void *KD_APIENTRY kdGetTLS(void);
+
+/* kdSetTLS: Set the thread-local storage pointer. */
+KD_API void KD_APIENTRY kdSetTLS(void *ptr);
+
+/*******************************************************
+ * Mathematical functions
+ *******************************************************/
+#define KD_E_F 2.71828175F
+#define KD_PI_F 3.14159274F
+#define KD_PI_2_F 1.57079637F
+#define KD_2PI_F 6.28318548F
+#define KD_LOG2E_F 1.44269502F
+#define KD_LOG10E_F 0.434294492F
+#define KD_LN2_F 0.693147182F
+#define KD_LN10_F 2.30258512F
+#define KD_PI_4_F 0.785398185F
+#define KD_1_PI_F 0.318309873F
+#define KD_2_PI_F 0.636619747F
+#define KD_2_SQRTPI_F 1.12837923F
+#define KD_SQRT2_F 1.41421354F
+#define KD_SQRT1_2_F 0.707106769F
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_FLT_MAX 3.40282346638528860e+38F
+#define KD_FLT_MIN 1.17549435e-38F
+/* KD_INFINITY is defined in kdplatform.h since no portable definition
+ * is possible. */
+#define kdIsNan(x) (((x) != (x)) ? 1 : 0)
+#define KD_HUGE_VALF KD_INFINITY
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+/* kdAcosf: Arc cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdAcosf(KDfloat32 x);
+
+/* kdAsinf: Arc sine function. */
+KD_API KDfloat32 KD_APIENTRY kdAsinf(KDfloat32 x);
+
+/* kdAtanf: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtanf(KDfloat32 x);
+
+/* kdAtan2f: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtan2f(KDfloat32 y, KDfloat32 x);
+
+/* kdCosf: Cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdCosf(KDfloat32 x);
+
+/* kdSinf: Sine function. */
+KD_API KDfloat32 KD_APIENTRY kdSinf(KDfloat32 x);
+
+/* kdTanf: Tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdTanf(KDfloat32 x);
+
+/* kdExpf: Exponential function. */
+KD_API KDfloat32 KD_APIENTRY kdExpf(KDfloat32 x);
+
+/* kdLogf: Natural logarithm function. */
+KD_API KDfloat32 KD_APIENTRY kdLogf(KDfloat32 x);
+
+/* kdFabsf: Absolute value. */
+KD_API KDfloat32 KD_APIENTRY kdFabsf(KDfloat32 x);
+
+/* kdPowf: Power function. */
+KD_API KDfloat32 KD_APIENTRY kdPowf(KDfloat32 x, KDfloat32 y);
+
+/* kdSqrtf: Square root function. */
+KD_API KDfloat32 KD_APIENTRY kdSqrtf(KDfloat32 x);
+
+/* kdCeilf: Return ceiling value. */
+KD_API KDfloat32 KD_APIENTRY kdCeilf(KDfloat32 x);
+
+/* kdFloorf: Return floor value. */
+KD_API KDfloat32 KD_APIENTRY kdFloorf(KDfloat32 x);
+
+/* kdRoundf: Round value to nearest integer. */
+KD_API KDfloat32 KD_APIENTRY kdRoundf(KDfloat32 x);
+
+/* kdInvsqrtf: Inverse square root function. */
+KD_API KDfloat32 KD_APIENTRY kdInvsqrtf(KDfloat32 x);
+
+/* kdFmodf: Calculate floating point remainder. */
+KD_API KDfloat32 KD_APIENTRY kdFmodf(KDfloat32 x, KDfloat32 y);
+
+/*******************************************************
+ * String and memory functions
+ *******************************************************/
+
+/* kdMemchr: Scan memory for a byte value. */
+KD_API void *KD_APIENTRY kdMemchr(const void *src, KDint byte, KDsize len);
+
+/* kdMemcmp: Compare two memory regions. */
+KD_API KDint KD_APIENTRY kdMemcmp(const void *src1, const void *src2, KDsize len);
+
+/* kdMemcpy: Copy a memory region, no overlapping. */
+KD_API void *KD_APIENTRY kdMemcpy(void *buf, const void *src, KDsize len);
+
+/* kdMemmove: Copy a memory region, overlapping allowed. */
+KD_API void *KD_APIENTRY kdMemmove(void *buf, const void *src, KDsize len);
+
+/* kdMemset: Set bytes in memory to a value. */
+KD_API void *KD_APIENTRY kdMemset(void *buf, KDint byte, KDsize len);
+
+/* kdStrchr: Scan string for a byte value. */
+KD_API KDchar *KD_APIENTRY kdStrchr(const KDchar *str, KDint ch);
+
+/* kdStrcmp: Compares two strings. */
+KD_API KDint KD_APIENTRY kdStrcmp(const KDchar *str1, const KDchar *str2);
+
+/* kdStrlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrlen(const KDchar *str);
+
+/* kdStrnlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrnlen(const KDchar *str, KDsize maxlen);
+
+/* kdStrncat_s: Concatenate two strings. */
+KD_API KDint KD_APIENTRY kdStrncat_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srcmaxlen);
+
+/* kdStrncmp: Compares two strings with length limit. */
+KD_API KDint KD_APIENTRY kdStrncmp(const KDchar *str1, const KDchar *str2, KDsize maxlen);
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrcpy_s(KDchar *buf, KDsize buflen, const KDchar *src);
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrncpy_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srclen);
+
+/*******************************************************
+ * Time functions
+ *******************************************************/
+
+/* kdGetTimeUST: Get the current unadjusted system time. */
+KD_API KDust KD_APIENTRY kdGetTimeUST(void);
+
+/* kdTime: Get the current wall clock time. */
+KD_API KDtime KD_APIENTRY kdTime(KDtime *timep);
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+typedef struct KDTm {
+ KDint32 tm_sec;
+ KDint32 tm_min;
+ KDint32 tm_hour;
+ KDint32 tm_mday;
+ KDint32 tm_mon;
+ KDint32 tm_year;
+ KDint32 tm_wday;
+ KDint32 tm_yday;
+} KDTm;
+KD_API KDTm *KD_APIENTRY kdGmtime_r(const KDtime *timep, KDTm *result);
+KD_API KDTm *KD_APIENTRY kdLocaltime_r(const KDtime *timep, KDTm *result);
+
+/* kdUSTAtEpoch: Get the UST corresponding to KDtime 0. */
+KD_API KDust KD_APIENTRY kdUSTAtEpoch(void);
+
+/*******************************************************
+ * Timer functions
+ *******************************************************/
+
+/* kdSetTimer: Set timer. */
+#define KD_TIMER_ONESHOT 61
+#define KD_TIMER_PERIODIC_AVERAGE 62
+#define KD_TIMER_PERIODIC_MINIMUM 63
+typedef struct KDTimer KDTimer;
+KD_API KDTimer *KD_APIENTRY kdSetTimer(KDint64 interval, KDint periodic, void *eventuserptr);
+
+/* kdCancelTimer: Cancel and free a timer. */
+KD_API KDint KD_APIENTRY kdCancelTimer(KDTimer *timer);
+
+/* KD_EVENT_TIMER: Timer fire event. */
+#define KD_EVENT_TIMER 42
+
+/*******************************************************
+ * File system
+ *******************************************************/
+#define KD_EOF (-1)
+
+/* kdFopen: Open a file from the file system. */
+typedef struct KDFile KDFile;
+KD_API KDFile *KD_APIENTRY kdFopen(const KDchar *pathname, const KDchar *mode);
+
+/* kdFclose: Close an open file. */
+KD_API KDint KD_APIENTRY kdFclose(KDFile *file);
+
+/* kdFflush: Flush an open file. */
+KD_API KDint KD_APIENTRY kdFflush(KDFile *file);
+
+/* kdFread: Read from a file. */
+KD_API KDsize KD_APIENTRY kdFread(void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdFwrite: Write to a file. */
+KD_API KDsize KD_APIENTRY kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdGetc: Read next byte from an open file. */
+KD_API KDint KD_APIENTRY kdGetc(KDFile *file);
+
+/* kdPutc: Write a byte to an open file. */
+KD_API KDint KD_APIENTRY kdPutc(KDint c, KDFile *file);
+
+/* kdFgets: Read a line of text from an open file. */
+KD_API KDchar *KD_APIENTRY kdFgets(KDchar *buffer, KDsize buflen, KDFile *file);
+
+/* kdFEOF: Check for end of file. */
+KD_API KDint KD_APIENTRY kdFEOF(KDFile *file);
+
+/* kdFerror: Check for an error condition on an open file. */
+KD_API KDint KD_APIENTRY kdFerror(KDFile *file);
+
+/* kdClearerr: Clear a file&#8217;s error and end-of-file indicators. */
+KD_API void KD_APIENTRY kdClearerr(KDFile *file);
+
+/* kdFseek: Reposition the file position indicator in a file. */
+typedef enum {
+ KD_SEEK_SET = 0,
+ KD_SEEK_CUR = 1,
+ KD_SEEK_END = 2
+} KDfileSeekOrigin;
+KD_API KDint KD_APIENTRY kdFseek(KDFile *file, KDoff offset, KDfileSeekOrigin origin);
+
+/* kdFtell: Get the file position of an open file. */
+KD_API KDoff KD_APIENTRY kdFtell(KDFile *file);
+
+/* kdMkdir: Create new directory. */
+KD_API KDint KD_APIENTRY kdMkdir(const KDchar *pathname);
+
+/* kdRmdir: Delete a directory. */
+KD_API KDint KD_APIENTRY kdRmdir(const KDchar *pathname);
+
+/* kdRename: Rename a file. */
+KD_API KDint KD_APIENTRY kdRename(const KDchar *src, const KDchar *dest);
+
+/* kdRemove: Delete a file. */
+KD_API KDint KD_APIENTRY kdRemove(const KDchar *pathname);
+
+/* kdTruncate: Truncate or extend a file. */
+KD_API KDint KD_APIENTRY kdTruncate(const KDchar *pathname, KDoff length);
+
+/* kdStat, kdFstat: Return information about a file. */
+typedef struct KDStat {
+ KDmode st_mode;
+ KDoff st_size;
+ KDtime st_mtime;
+} KDStat;
+KD_API KDint KD_APIENTRY kdStat(const KDchar *pathname, struct KDStat *buf);
+KD_API KDint KD_APIENTRY kdFstat(KDFile *file, struct KDStat *buf);
+#define KD_ISREG(m) ((m) & 0x8000)
+#define KD_ISDIR(m) ((m) & 0x4000)
+
+/* kdAccess: Determine whether the application can access a file or directory. */
+KD_API KDint KD_APIENTRY kdAccess(const KDchar *pathname, KDint amode);
+#define KD_R_OK 4
+#define KD_W_OK 2
+#define KD_X_OK 1
+
+/* kdOpenDir: Open a directory ready for listing. */
+typedef struct KDDir KDDir;
+KD_API KDDir *KD_APIENTRY kdOpenDir(const KDchar *pathname);
+
+/* kdReadDir: Return the next file in a directory. */
+typedef struct KDDirent {
+ const KDchar *d_name;
+} KDDirent;
+KD_API KDDirent *KD_APIENTRY kdReadDir(KDDir *dir);
+
+/* kdCloseDir: Close a directory. */
+KD_API KDint KD_APIENTRY kdCloseDir(KDDir *dir);
+
+/* kdGetFree: Get free space on a drive. */
+KD_API KDoff KD_APIENTRY kdGetFree(const KDchar *pathname);
+
+/*******************************************************
+ * Network sockets
+ *******************************************************/
+
+/* KDSockaddr: Struct type for socket address. */
+typedef struct KDSockaddr {
+ KDuint16 family;
+ union {
+#define KD_AF_INET 70
+ struct {
+ KDuint16 port;
+ KDuint32 address;
+ } sin;
+ } data;
+} KDSockaddr;
+
+/* kdNameLookup: Look up a hostname. */
+KD_API KDint KD_APIENTRY kdNameLookup(KDint af, const KDchar *hostname, void *eventuserptr);
+
+/* kdNameLookupCancel: Selectively cancels ongoing kdNameLookup operations. */
+KD_API void KD_APIENTRY kdNameLookupCancel(void *eventuserptr);
+
+/* kdSocketCreate: Creates a socket. */
+typedef struct KDSocket KDSocket;
+KD_API KDSocket *KD_APIENTRY kdSocketCreate(KDint type, void *eventuserptr);
+#define KD_SOCK_TCP 64
+#define KD_SOCK_UDP 65
+
+/* kdSocketClose: Closes a socket. */
+KD_API KDint KD_APIENTRY kdSocketClose(KDSocket *socket);
+
+/* kdSocketBind: Bind a socket. */
+KD_API KDint KD_APIENTRY kdSocketBind(KDSocket *socket, const struct KDSockaddr *addr, KDboolean reuse);
+#define KD_INADDR_ANY 0
+
+/* kdSocketGetName: Get the local address of a socket. */
+KD_API KDint KD_APIENTRY kdSocketGetName(KDSocket *socket, struct KDSockaddr *addr);
+
+/* kdSocketConnect: Connects a socket. */
+KD_API KDint KD_APIENTRY kdSocketConnect(KDSocket *socket, const KDSockaddr *addr);
+
+/* kdSocketListen: Listen on a socket. */
+KD_API KDint KD_APIENTRY kdSocketListen(KDSocket *socket, KDint backlog);
+
+/* kdSocketAccept: Accept an incoming connection. */
+KD_API KDSocket *KD_APIENTRY kdSocketAccept(KDSocket *socket, KDSockaddr *addr, void *eventuserptr);
+
+/* kdSocketSend, kdSocketSendTo: Send data to a socket. */
+KD_API KDint KD_APIENTRY kdSocketSend(KDSocket *socket, const void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketSendTo(KDSocket *socket, const void *buf, KDint len, const KDSockaddr *addr);
+
+/* kdSocketRecv, kdSocketRecvFrom: Receive data from a socket. */
+KD_API KDint KD_APIENTRY kdSocketRecv(KDSocket *socket, void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketRecvFrom(KDSocket *socket, void *buf, KDint len, KDSockaddr *addr);
+
+/* kdHtonl: Convert a 32-bit integer from host to network byte order. */
+KD_API KDuint32 KD_APIENTRY kdHtonl(KDuint32 hostlong);
+
+/* kdHtons: Convert a 16-bit integer from host to network byte order. */
+KD_API KDuint16 KD_APIENTRY kdHtons(KDuint16 hostshort);
+
+/* kdNtohl: Convert a 32-bit integer from network to host byte order. */
+KD_API KDuint32 KD_APIENTRY kdNtohl(KDuint32 netlong);
+
+/* kdNtohs: Convert a 16-bit integer from network to host byte order. */
+KD_API KDuint16 KD_APIENTRY kdNtohs(KDuint16 netshort);
+
+/* kdInetAton: Convert a &#8220;dotted quad&#8221; format address to an integer. */
+KD_API KDint KD_APIENTRY kdInetAton(const KDchar *cp, KDuint32 *inp);
+
+/* kdInetNtop: Convert a network address to textual form. */
+#define KD_INET_ADDRSTRLEN 16
+typedef struct KDInAddr {
+ KDuint32 s_address; // Renamed this from s_addr as it causes a conflict with winsock2.h
+} KDInAddr;
+KD_API const KDchar *KD_APIENTRY kdInetNtop(KDuint af, const void *src, KDchar *dst, KDsize cnt);
+
+/* KD_EVENT_SOCKET_READABLE: Event to indicate that a socket is readable. */
+#define KD_EVENT_SOCKET_READABLE 49
+typedef struct KDEventSocketReadable {
+ KDSocket *socket;
+} KDEventSocketReadable;
+
+/* KD_EVENT_SOCKET_WRITABLE: Event to indicate that a socket is writable. */
+#define KD_EVENT_SOCKET_WRITABLE 50
+typedef struct KDEventSocketWritable {
+ KDSocket *socket;
+} KDEventSocketWritable;
+
+/* KD_EVENT_SOCKET_CONNECT_COMPLETE: Event generated when a socket connect is complete */
+#define KD_EVENT_SOCKET_CONNECT_COMPLETE 51
+typedef struct KDEventSocketConnect {
+ KDSocket *socket;
+ KDint32 error;
+} KDEventSocketConnect;
+
+/* KD_EVENT_SOCKET_INCOMING: Event generated when a listening socket detects an incoming connection or an error. */
+#define KD_EVENT_SOCKET_INCOMING 52
+typedef struct KDEventSocketIncoming {
+ KDSocket *socket;
+} KDEventSocketIncoming;
+
+/* KD_EVENT_NAME_LOOKUP_COMPLETE: kdNameLookup complete event. */
+#define KD_EVENT_NAME_LOOKUP_COMPLETE 53
+typedef struct KDEventNameLookup {
+ KDint32 error;
+ KDint32 resultlen;
+ const KDSockaddr *result;
+ KDboolean more;
+} KDEventNameLookup;
+
+/*******************************************************
+ * Input/output
+ *******************************************************/
+
+/* KD_EVENT_STATE: State changed event. */
+#define KD_EVENT_STATE 55
+
+typedef struct KDEventState {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventState;
+
+/* KD_EVENT_INPUT: Input changed event. */
+#define KD_EVENT_INPUT 56
+
+typedef struct KDEventInput {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventInput;
+
+/* KD_EVENT_INPUT_JOG: Jogdial jog event. */
+#define KD_EVENT_INPUT_JOG 71
+typedef struct KDEventInputJog {
+ KDint32 index;
+ KDint32 count;
+} KDEventInputJog;
+
+/* KD_EVENT_INPUT_POINTER: Pointer input changed event. */
+#define KD_EVENT_INPUT_POINTER 57
+typedef struct KDEventInputPointer {
+ KDint32 index;
+ KDint32 select;
+ KDint32 x;
+ KDint32 y;
+} KDEventInputPointer;
+
+/* KD_EVENT_INPUT_STICK: Joystick stick changed event. */
+#define KD_EVENT_INPUT_STICK 58
+typedef struct KDEventInputStick {
+ KDint32 index;
+ KDint32 x;
+ KDint32 y;
+ KDint32 z;
+} KDEventInputStick;
+
+/* kdStateGeti, kdStateGetl, kdStateGetf: get state value(s) */
+KD_API KDint KD_APIENTRY kdStateGeti(KDint startidx, KDuint numidxs, KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetl(KDint startidx, KDuint numidxs, KDint64 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetf(KDint startidx, KDuint numidxs, KDfloat32 *buffer);
+
+/* kdOutputSeti, kdOutputSetf: set outputs */
+KD_API KDint KD_APIENTRY kdOutputSeti(KDint startidx, KDuint numidxs, const KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdOutputSetf(KDint startidx, KDuint numidxs, const KDfloat32 *buffer);
+#define KD_IO_CONTROLLER_STRIDE 64
+
+/* KD_IOGROUP_GAMEKEYS: I/O group for game keys. */
+#define KD_IOGROUP_GAMEKEYS 0x1000
+#define KD_STATE_GAMEKEYS_AVAILABILITY (KD_IOGROUP_GAMEKEYS + 0)
+#define KD_INPUT_GAMEKEYS_UP (KD_IOGROUP_GAMEKEYS + 1)
+#define KD_INPUT_GAMEKEYS_LEFT (KD_IOGROUP_GAMEKEYS + 2)
+#define KD_INPUT_GAMEKEYS_RIGHT (KD_IOGROUP_GAMEKEYS + 3)
+#define KD_INPUT_GAMEKEYS_DOWN (KD_IOGROUP_GAMEKEYS + 4)
+#define KD_INPUT_GAMEKEYS_FIRE (KD_IOGROUP_GAMEKEYS + 5)
+#define KD_INPUT_GAMEKEYS_A (KD_IOGROUP_GAMEKEYS + 6)
+#define KD_INPUT_GAMEKEYS_B (KD_IOGROUP_GAMEKEYS + 7)
+#define KD_INPUT_GAMEKEYS_C (KD_IOGROUP_GAMEKEYS + 8)
+#define KD_INPUT_GAMEKEYS_D (KD_IOGROUP_GAMEKEYS + 9)
+
+/* KD_IOGROUP_GAMEKEYSNC: I/O group for game keys, no chording. */
+#define KD_IOGROUP_GAMEKEYSNC 0x1100
+#define KD_STATE_GAMEKEYSNC_AVAILABILITY (KD_IOGROUP_GAMEKEYSNC + 0)
+#define KD_INPUT_GAMEKEYSNC_UP (KD_IOGROUP_GAMEKEYSNC + 1)
+#define KD_INPUT_GAMEKEYSNC_LEFT (KD_IOGROUP_GAMEKEYSNC + 2)
+#define KD_INPUT_GAMEKEYSNC_RIGHT (KD_IOGROUP_GAMEKEYSNC + 3)
+#define KD_INPUT_GAMEKEYSNC_DOWN (KD_IOGROUP_GAMEKEYSNC + 4)
+#define KD_INPUT_GAMEKEYSNC_FIRE (KD_IOGROUP_GAMEKEYSNC + 5)
+#define KD_INPUT_GAMEKEYSNC_A (KD_IOGROUP_GAMEKEYSNC + 6)
+#define KD_INPUT_GAMEKEYSNC_B (KD_IOGROUP_GAMEKEYSNC + 7)
+#define KD_INPUT_GAMEKEYSNC_C (KD_IOGROUP_GAMEKEYSNC + 8)
+#define KD_INPUT_GAMEKEYSNC_D (KD_IOGROUP_GAMEKEYSNC + 9)
+
+/* KD_IOGROUP_PHONEKEYPAD: I/O group for phone keypad. */
+#define KD_IOGROUP_PHONEKEYPAD 0x2000
+#define KD_STATE_PHONEKEYPAD_AVAILABILITY (KD_IOGROUP_PHONEKEYPAD + 0)
+#define KD_INPUT_PHONEKEYPAD_0 (KD_IOGROUP_PHONEKEYPAD + 1)
+#define KD_INPUT_PHONEKEYPAD_1 (KD_IOGROUP_PHONEKEYPAD + 2)
+#define KD_INPUT_PHONEKEYPAD_2 (KD_IOGROUP_PHONEKEYPAD + 3)
+#define KD_INPUT_PHONEKEYPAD_3 (KD_IOGROUP_PHONEKEYPAD + 4)
+#define KD_INPUT_PHONEKEYPAD_4 (KD_IOGROUP_PHONEKEYPAD + 5)
+#define KD_INPUT_PHONEKEYPAD_5 (KD_IOGROUP_PHONEKEYPAD + 6)
+#define KD_INPUT_PHONEKEYPAD_6 (KD_IOGROUP_PHONEKEYPAD + 7)
+#define KD_INPUT_PHONEKEYPAD_7 (KD_IOGROUP_PHONEKEYPAD + 8)
+#define KD_INPUT_PHONEKEYPAD_8 (KD_IOGROUP_PHONEKEYPAD + 9)
+#define KD_INPUT_PHONEKEYPAD_9 (KD_IOGROUP_PHONEKEYPAD + 10)
+#define KD_INPUT_PHONEKEYPAD_STAR (KD_IOGROUP_PHONEKEYPAD + 11)
+#define KD_INPUT_PHONEKEYPAD_HASH (KD_IOGROUP_PHONEKEYPAD + 12)
+#define KD_INPUT_PHONEKEYPAD_LEFTSOFT (KD_IOGROUP_PHONEKEYPAD + 13)
+#define KD_INPUT_PHONEKEYPAD_RIGHTSOFT (KD_IOGROUP_PHONEKEYPAD + 14)
+#define KD_STATE_PHONEKEYPAD_ORIENTATION (KD_IOGROUP_PHONEKEYPAD + 15)
+
+/* KD_IOGROUP_VIBRATE: I/O group for vibrate. */
+#define KD_IOGROUP_VIBRATE 0x3000
+#define KD_STATE_VIBRATE_AVAILABILITY (KD_IOGROUP_VIBRATE + 0)
+#define KD_STATE_VIBRATE_MINFREQUENCY (KD_IOGROUP_VIBRATE + 1)
+#define KD_STATE_VIBRATE_MAXFREQUENCY (KD_IOGROUP_VIBRATE + 2)
+#define KD_OUTPUT_VIBRATE_VOLUME (KD_IOGROUP_VIBRATE + 3)
+#define KD_OUTPUT_VIBRATE_FREQUENCY (KD_IOGROUP_VIBRATE + 4)
+
+/* KD_IOGROUP_POINTER: I/O group for pointer. */
+#define KD_IOGROUP_POINTER 0x4000
+#define KD_STATE_POINTER_AVAILABILITY (KD_IOGROUP_POINTER + 0)
+#define KD_INPUT_POINTER_X (KD_IOGROUP_POINTER + 1)
+#define KD_INPUT_POINTER_Y (KD_IOGROUP_POINTER + 2)
+#define KD_INPUT_POINTER_SELECT (KD_IOGROUP_POINTER + 3)
+
+/* KD_IOGROUP_BACKLIGHT: I/O group for backlight. */
+#define KD_IOGROUP_BACKLIGHT 0x5000
+#define KD_STATE_BACKLIGHT_AVAILABILITY (KD_IOGROUP_BACKLIGHT + 0)
+#define KD_OUTPUT_BACKLIGHT_FORCE (KD_IOGROUP_BACKLIGHT + 1)
+
+/* KD_IOGROUP_JOGDIAL: I/O group for a jog dial. */
+#define KD_IOGROUP_JOGDIAL 0x6000
+#define KD_STATE_JOGDIAL_AVAILABILITY (KD_IOGROUP_JOGDIAL + 0)
+#define KD_INPUT_JOGDIAL_UP (KD_IOGROUP_JOGDIAL + 1)
+#define KD_INPUT_JOGDIAL_LEFT (KD_IOGROUP_JOGDIAL + 2)
+#define KD_INPUT_JOGDIAL_RIGHT (KD_IOGROUP_JOGDIAL + 3)
+#define KD_INPUT_JOGDIAL_DOWN (KD_IOGROUP_JOGDIAL + 4)
+#define KD_INPUT_JOGDIAL_SELECT (KD_IOGROUP_JOGDIAL + 5)
+
+/* KD_IOGROUP_STICK: I/O group for joystick. */
+#define KD_IOGROUP_STICK 0x7000
+#define KD_STATE_STICK_AVAILABILITY (KD_IOGROUP_STICK + 0)
+#define KD_INPUT_STICK_X (KD_IOGROUP_STICK + 1)
+#define KD_INPUT_STICK_Y (KD_IOGROUP_STICK + 2)
+#define KD_INPUT_STICK_Z (KD_IOGROUP_STICK + 3)
+#define KD_INPUT_STICK_BUTTON (KD_IOGROUP_STICK + 4)
+#define KD_IO_STICK_STRIDE 8
+
+/* KD_IOGROUP_DPAD: I/O group for D-pad. */
+#define KD_IOGROUP_DPAD 0x8000
+#define KD_STATE_DPAD_AVAILABILITY (KD_IOGROUP_DPAD + 0)
+#define KD_STATE_DPAD_COPY (KD_IOGROUP_DPAD + 1)
+#define KD_INPUT_DPAD_UP (KD_IOGROUP_DPAD + 2)
+#define KD_INPUT_DPAD_LEFT (KD_IOGROUP_DPAD + 3)
+#define KD_INPUT_DPAD_RIGHT (KD_IOGROUP_DPAD + 4)
+#define KD_INPUT_DPAD_DOWN (KD_IOGROUP_DPAD + 5)
+#define KD_INPUT_DPAD_SELECT (KD_IOGROUP_DPAD + 6)
+#define KD_IO_DPAD_STRIDE 8
+
+/* KD_IOGROUP_BUTTONS: I/O group for buttons associated with joystick or D-pad. */
+#define KD_IOGROUP_BUTTONS 0x9000
+#define KD_STATE_BUTTONS_AVAILABILITY (KD_IOGROUP_BUTTONS + 0)
+#define KD_INPUT_BUTTONS_0 (KD_IOGROUP_BUTTONS + 1)
+
+/* KD_IO_UNDEFINED: I/O items reserved for implementation-dependent use. */
+#define KD_IO_UNDEFINED 0x40000000
+
+/*******************************************************
+ * Windowing
+ *******************************************************/
+#ifdef KD_WINDOW_SUPPORTED
+#include <EGL/egl.h>
+typedef struct KDWindow KDWindow;
+
+/* kdCreateWindow: Create a window. */
+KD_API KDWindow *KD_APIENTRY kdCreateWindow(EGLDisplay display, EGLConfig config, void *eventuserptr);
+
+/* kdDestroyWindow: Destroy a window. */
+KD_API KDint KD_APIENTRY kdDestroyWindow(KDWindow *window);
+
+/* kdSetWindowPropertybv, kdSetWindowPropertyiv, kdSetWindowPropertycv: Set a window property to request a change in the on-screen representation of the window. */
+KD_API KDint KD_APIENTRY kdSetWindowPropertybv(KDWindow *window, KDint pname, const KDboolean *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertyiv(KDWindow *window, KDint pname, const KDint32 *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertycv(KDWindow *window, KDint pname, const KDchar *param);
+
+/* kdGetWindowPropertybv, kdGetWindowPropertyiv, kdGetWindowPropertycv: Get the current value of a window property. */
+KD_API KDint KD_APIENTRY kdGetWindowPropertybv(KDWindow *window, KDint pname, KDboolean *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertyiv(KDWindow *window, KDint pname, KDint32 *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertycv(KDWindow *window, KDint pname, KDchar *param, KDsize *size);
+
+/* kdRealizeWindow: Realize the window as a displayable entity and get the native window handle for passing to EGL. */
+KD_API KDint KD_APIENTRY kdRealizeWindow(KDWindow *window, EGLNativeWindowType *nativewindow);
+
+/* KD_WINDOWPROPERTY_SIZE: Window client area width and height. */
+#define KD_WINDOWPROPERTY_SIZE 66
+
+/* KD_WINDOWPROPERTY_VISIBILITY: Window visibility status. */
+#define KD_WINDOWPROPERTY_VISIBILITY 67
+
+/* KD_WINDOWPROPERTY_FOCUS: Window input focus status. */
+#define KD_WINDOWPROPERTY_FOCUS 68
+
+/* KD_WINDOWPROPERTY_CAPTION: Window caption. */
+#define KD_WINDOWPROPERTY_CAPTION 69
+
+/* KD_EVENT_WINDOW_CLOSE: Event to request to close window. */
+#define KD_EVENT_WINDOW_CLOSE 44
+
+/* KD_EVENT_WINDOWPROPERTY_CHANGE: Notification about realized window property change. */
+#define KD_EVENT_WINDOWPROPERTY_CHANGE 47
+typedef struct KDEventWindowProperty {
+ KDint32 pname;
+} KDEventWindowProperty;
+
+/* KD_EVENT_WINDOW_FOCUS: Event for change of window&#8217;s focus state. */
+#define KD_EVENT_WINDOW_FOCUS 60
+typedef struct KDEventWindowFocus {
+ KDint32 focusstate;
+} KDEventWindowFocus;
+
+/* KD_EVENT_WINDOW_REDRAW: Event to notify need to redraw the window. */
+#define KD_EVENT_WINDOW_REDRAW 59
+#endif /* KD_WINDOW_SUPPORTED */
+
+/*******************************************************
+ * Assertions and logging
+ *******************************************************/
+
+/* kdHandleAssertion: Handle assertion failure. */
+KD_API void KD_APIENTRY kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber);
+
+/* kdLogMessage: Output a log message. */
+#ifdef KD_NDEBUG
+#define kdLogMessage(s)
+#else
+KD_API void KD_APIENTRY kdLogMessage(const KDchar *string);
+#endif
+
+/* struct KDEvent delayed to the end as it uses event data structs from
+ * other parts of the .h file. */
+struct KDEvent {
+ KDust timestamp;
+ KDint32 type;
+ void *userptr;
+ union KDEventData {
+ KDEventState state;
+ KDEventInput input;
+ KDEventInputJog inputjog;
+ KDEventInputPointer inputpointer;
+ KDEventInputStick inputstick;
+ KDEventSocketReadable socketreadable;
+ KDEventSocketWritable socketwritable;
+ KDEventSocketConnect socketconnect;
+ KDEventSocketIncoming socketincoming;
+ KDEventNameLookup namelookup;
+#ifdef KD_WINDOW_SUPPORTED
+ KDEventWindowProperty windowproperty;
+ KDEventWindowFocus windowfocus;
+#endif /* KD_WINDOW_SUPPORTED */
+ KDEventUser user;
+ } data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kdplatform.h b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kdplatform.h
new file mode 100644
index 00000000..3cf09f52
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs/KD/kdplatform.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Sample KD/kdplatform.h for OpenKODE Core 1.0.3 */
+#ifndef __kdplatform_h_
+#define __kdplatform_h_
+
+#define KD_API
+#define KD_APIENTRY
+
+typedef int KDint32;
+typedef unsigned int KDuint32;
+typedef long long KDint64;
+typedef unsigned long long KDuint64;
+typedef short KDint16;
+typedef unsigned short KDuint16;
+typedef unsigned long KDuintptr;
+typedef unsigned long KDsize;
+typedef long KDssize;
+#define KDINT_MIN (-0x7fffffff-1)
+#define KDINT_MAX 0x7fffffff
+#define KDUINT_MAX 0xffffffffU
+#define KDINT64_MIN (-0x7fffffffffffffffLL-1)
+#define KDINT64_MAX 0x7fffffffffffffffLL
+#define KDUINT64_MAX 0xffffffffffffffffULL
+#define KDSSIZE_MIN (-0x7fffffff-1)
+#define KDSSIZE_MAX 0x7fffffff
+#define KDSIZE_MAX 0xffffffffU
+#define KDUINTPTR_MAX 0xffffffffU
+#define KD_NORETURN
+#define KD_WINDOW_SUPPORTED
+#ifdef KD_NDEBUG
+#define kdAssert(c)
+#else
+#define kdAssert(c) ((void)( (c) ? 0 : (kdHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+#define KD_INFINITY_BITS 0x7f800000u
+#define KD_INFINITY (kdBitsToFloatNV(KD_INFINITY_BITS))
+
+KD_API float KD_APIENTRY kdBitsToFloatNV(KDuint32 x);
+
+
+/** KHR_formatted extension */
+#include <stdarg.h>
+typedef va_list KDVaListKHR;
+
+// If there are problems with including stdarg.h here under any of the Windows
+// operating systems, we might want to change it back to using char* instead of
+// va_list
+//typedef char *KDVaListKHR;
+
+
+#define KD_VA_START_KHR(ap, parmN) \
+ do {ap = (KDVaListKHR)&parmN + sizeof(parmN);} while(0)
+
+#define KD_VA_ARG_CHAR_KHR(ap) (KDchar)va_arg(ap, KDint)
+#define KD_VA_ARG_CHARPTR_KHR(ap) (KDchar*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16_KHR(ap) (KDint16)va_arg(ap, KDint)
+#define KD_VA_ARG_INT32_KHR(ap) va_arg(ap, KDint32)
+#define KD_VA_ARG_INT_KHR(ap) va_arg(ap, KDint)
+#define KD_VA_ARG_INT64_KHR(ap) va_arg(ap, KDint64)
+#define KD_VA_ARG_INTPTR_KHR(ap) (KDint*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16PTR_KHR(ap) (KDint16*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_FLOAT32_KHR(ap) (KDfloat32)(va_arg(ap, double))
+#define KD_VA_ARG_PTR_KHR(ap) (void *)va_arg(ap, char *)
+
+#define KD_VA_END_KHR(ap) \
+ do {ap = (KDVaListKHR)0;} while(0)
+
+#endif /* __kdplatform_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_extwindowprops.h b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_extwindowprops.h
new file mode 100644
index 00000000..4428a568
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_extwindowprops.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_extwindowprops_h_
+#define __kd_QT3DS_extwindowprops_h_
+#include <KD/kd.h>
+#include <EGL/eglext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_WINDOWPROPERTY_FULLSCREEN: Control over resizing a window to fill the complete screen */
+
+// KDboolean - set the window to fullscreen mode
+#define KD_WINDOWPROPERTY_FULLSCREEN_QT3DS 9999
+
+// KDint - set which KD_DISPLAY_* display that the window should be opened on
+#define KD_WINDOWPROPERTY_DISPLAY_QT3DS 9998
+
+// KDboolean - sets whether overlay should be used to create window
+#define KD_WINDOWPROPERTY_OVERLAY_QT3DS 9997
+
+#define KD_DISPLAY_PRIMARY_QT3DS 0
+#define KD_DISPLAY_INTERNAL0_QT3DS 0
+#define KD_DISPLAY_INTERNAL1_QT3DS 1
+#define KD_DISPLAY_INTERNAL2_QT3DS 2
+#define KD_DISPLAY_INTERNAL3_QT3DS 3
+#define KD_DISPLAY_EXTERNAL0_QT3DS 1000
+#define KD_DISPLAY_EXTERNAL1_QT3DS 1001
+#define KD_DISPLAY_EXTERNAL2_QT3DS 1002
+#define KD_DISPLAY_EXTERNAL3_QT3DS 1003
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_extwindowprops_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_multitouch.h b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_multitouch.h
new file mode 100644
index 00000000..e230b029
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/Qt3DS_multitouch.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_multitouch_h_
+#define __kd_QT3DS_multitouch_h_
+#include <KD/kd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_IOGROUP_MULTITOUCH: I/O group for Multitouch input devices. */
+#define KD_IOGROUP_MULTITOUCH_QT3DS 0x40004000
+#define KD_STATE_MULTITOUCH_AVAILABILITY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 0)
+#define KD_INPUT_MULTITOUCH_FINGERS_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 1)
+#define KD_INPUT_MULTITOUCH_WIDTH_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 2)
+#define KD_INPUT_MULTITOUCH_X_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 3)
+#define KD_INPUT_MULTITOUCH_Y_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 4)
+#define KD_INPUT_MULTITOUCH_X2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 5)
+#define KD_INPUT_MULTITOUCH_Y2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 6)
+#define KD_INPUT_MULTITOUCH_PRESSURE_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 7)
+#define KD_INPUT_MULTITOUCH_GESTURES_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 8)
+#define KD_INPUT_MULTITOUCH_RELX_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 9)
+#define KD_INPUT_MULTITOUCH_RELY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 10)
+
+/* KD_EVENT_INPUT_MULTITOUCH_QT3DS: Multitouch event. */
+#define KD_EVENT_INPUT_MULTITOUCH_QT3DS 1001
+typedef struct KDEventInputMultitouchDataNV
+{
+ KDint32 index;
+ KDint8 fingers;
+ KDint8 width;
+ KDint16 x;
+ KDint16 y;
+ KDint16 x2;
+ KDint16 y2;
+ KDint16 pressure;
+} KDEventInputMultitouchDataNV;
+
+/* KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS: Multitouch gesture event. */
+#define KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS 1002
+
+/* kdGetEventInputMultitouchDataNV: Get auxiliary event data for multitouch input. */
+KD_API KDint KD_APIENTRY kdGetEventInputMultitouchDataNV(const KDEvent *event,
+ KDEventInputMultitouchDataNV *data);
+
+/* kdSetEventInputMultitouchActiveNV: Activate Multitouch input events */
+KD_API KDint KD_APIENTRY kdSetEventInputMultitouchActiveNV(KDboolean activate);
+
+/* kdEnableEventInputMultitouchMergeNV: Activate merging of Multitouch input events */
+KD_API void KD_APIENTRY kdEnableEventInputMultitouchMergeNV(KDboolean enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_multitouch_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kd.h b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kd.h
new file mode 100644
index 00000000..f7ccea03
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kd.h
@@ -0,0 +1,991 @@
+/* Reference KD/kd.h for OpenKODE Core 1.0.3 */
+#ifndef __kd_h_
+#define __kd_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kdplatform.h"
+
+
+
+/*******************************************************
+ * Introduction
+ *******************************************************/
+
+/*******************************************************
+ * OpenKODE conformance
+ *******************************************************/
+
+/*******************************************************
+ * Overview
+ *******************************************************/
+
+/*******************************************************
+ * Programming environment
+ *******************************************************/
+#define KD_VERSION_1_0 1
+typedef char KDchar;
+typedef signed char KDint8;
+typedef unsigned char KDuint8;
+typedef int KDint;
+typedef unsigned int KDuint;
+typedef float KDfloat32;
+typedef KDint KDboolean;
+typedef KDint64 KDtime;
+typedef KDint64 KDust;
+typedef KDint64 KDoff;
+typedef KDuint32 KDmode;
+#define KDINT32_MIN (-0x7fffffff-1)
+#define KDINT32_MAX 0x7fffffff
+#define KDUINT32_MAX 0xffffffffU
+#define KD_TRUE 1
+#define KD_FALSE 0
+#ifdef __cplusplus
+ const int KD_NULL = 0; /* Yes, int. See Stroustrup 3rd edition. */
+#else
+ #define KD_NULL ((void *)0)
+#endif
+
+/*******************************************************
+ * Errors
+ *******************************************************/
+#define KD_EACCES 1
+#define KD_EADDRINUSE 2
+#define KD_EADDRNOTAVAIL 3
+#define KD_EAFNOSUPPORT 4
+#define KD_EAGAIN (5)
+#define KD_EALREADY 6
+#define KD_EBADF 7
+#define KD_EBUSY 8
+#define KD_ECONNREFUSED 9
+#define KD_ECONNRESET 10
+#define KD_EDEADLK 11
+#define KD_EDESTADDRREQ 12
+#define KD_EEXIST 13
+#define KD_EFBIG 14
+#define KD_EHOSTUNREACH 15
+#define KD_EHOST_NOT_FOUND 16
+#define KD_EINVAL 17
+#define KD_EIO 18
+#define KD_EILSEQ 19
+#define KD_EISCONN 20
+#define KD_EISDIR 21
+#define KD_EMFILE 22
+#define KD_ENAMETOOLONG 23
+#define KD_ENOENT 24
+#define KD_ENOMEM 25
+#define KD_ENOSPC 26
+#define KD_ENOSYS 27
+#define KD_ENOTCONN 28
+#define KD_ENO_DATA 29
+#define KD_ENO_RECOVERY 30
+#define KD_EOPNOTSUPP 31
+#define KD_EOVERFLOW 32
+#define KD_EPERM 33
+#define KD_ERANGE 35
+#define KD_ETIMEDOUT (36)
+#define KD_ETRY_AGAIN 37
+
+/* kdGetError: Get last error indication. */
+KD_API KDint KD_APIENTRY kdGetError(void);
+
+/* kdSetError: Set last error indication. */
+KD_API void KD_APIENTRY kdSetError(KDint error);
+
+/*******************************************************
+ * Versioning and attribute queries
+ *******************************************************/
+
+/* kdQueryAttribi: Obtain the value of a numeric OpenKODE Core attribute. */
+KD_API KDint KD_APIENTRY kdQueryAttribi(KDint attribute, KDint *value);
+
+/* kdQueryAttribcv: Obtain the value of a string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryAttribcv(KDint attribute);
+#define KD_ATTRIB_VENDOR 39
+#define KD_ATTRIB_VERSION 40
+#define KD_ATTRIB_PLATFORM 41
+
+/* kdQueryIndexedAttribcv: Obtain the value of an indexed string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryIndexedAttribcv(KDint attribute, KDint index);
+
+/*******************************************************
+ * Threads and synchronization
+ *******************************************************/
+
+/* kdThreadAttrCreate: Create a thread attribute object. */
+typedef struct KDThreadAttr KDThreadAttr;
+KD_API KDThreadAttr *KD_APIENTRY kdThreadAttrCreate(void);
+
+/* kdThreadAttrFree: Free a thread attribute object. */
+KD_API KDint KD_APIENTRY kdThreadAttrFree(KDThreadAttr *attr);
+
+/* kdThreadAttrSetDetachState: Set detachstate attribute. */
+#define KD_THREAD_CREATE_JOINABLE 0
+#define KD_THREAD_CREATE_DETACHED 1
+KD_API KDint KD_APIENTRY kdThreadAttrSetDetachState(KDThreadAttr *attr, KDint detachstate);
+
+/* kdThreadAttrSetStackSize: Set stacksize attribute. */
+KD_API KDint KD_APIENTRY kdThreadAttrSetStackSize(KDThreadAttr *attr, KDsize stacksize);
+
+/* kdThreadCreate: Create a new thread. */
+typedef struct KDThread KDThread;
+KD_API KDThread *KD_APIENTRY kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg);
+
+/* kdThreadExit: Terminate this thread. */
+KD_API KD_NORETURN void KD_APIENTRY kdThreadExit(void *retval);
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KD_API KDint KD_APIENTRY kdThreadJoin(KDThread *thread, void **retval);
+
+/* kdThreadDetach: Allow resources to be freed as soon as a thread terminates. */
+KD_API KDint KD_APIENTRY kdThreadDetach(KDThread *thread);
+
+/* kdThreadSelf: Return calling thread&#8217;s ID. */
+KD_API KDThread *KD_APIENTRY kdThreadSelf(void);
+
+/* kdThreadOnce: Wrap initialization code so it is executed only once. */
+#ifndef KD_NO_STATIC_DATA
+typedef struct KDThreadOnce {
+ void *impl;
+} KDThreadOnce;
+#define KD_THREAD_ONCE_INIT { 0 }
+KD_API KDint KD_APIENTRY kdThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void));
+#endif /* ndef KD_NO_STATIC_DATA */
+
+/* kdThreadMutexCreate: Create a mutex. */
+typedef struct KDThreadMutex KDThreadMutex;
+KD_API KDThreadMutex *KD_APIENTRY kdThreadMutexCreate(const void *mutexattr);
+
+/* kdThreadMutexFree: Free a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexFree(KDThreadMutex *mutex);
+
+/* kdThreadMutexLock: Lock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexLock(KDThreadMutex *mutex);
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexUnlock(KDThreadMutex *mutex);
+
+/* kdThreadCondCreate: Create a condition variable. */
+typedef struct KDThreadCond KDThreadCond;
+KD_API KDThreadCond *KD_APIENTRY kdThreadCondCreate(const void *attr);
+
+/* kdThreadCondFree: Free a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondFree(KDThreadCond *cond);
+
+/* kdThreadCondSignal, kdThreadCondBroadcast: Signal a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondSignal(KDThreadCond *cond);
+KD_API KDint KD_APIENTRY kdThreadCondBroadcast(KDThreadCond *cond);
+
+/* kdThreadCondWait: Wait for a condition variable to be signalled. */
+KD_API KDint KD_APIENTRY kdThreadCondWait(KDThreadCond *cond, KDThreadMutex *mutex);
+
+/* kdThreadSemCreate: Create a semaphore. */
+typedef struct KDThreadSem KDThreadSem;
+KD_API KDThreadSem *KD_APIENTRY kdThreadSemCreate(KDuint value);
+
+/* kdThreadSemFree: Free a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemFree(KDThreadSem *sem);
+
+/* kdThreadSemWait: Lock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemWait(KDThreadSem *sem);
+
+/* kdThreadSemPost: Unlock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemPost(KDThreadSem *sem);
+
+/*******************************************************
+ * Events
+ *******************************************************/
+
+/* KDEvent: Struct type containing an event. */
+typedef struct KDEvent KDEvent;
+#define KD_EVENT_USER 0x40000000
+
+/* kdWaitEvent: Get next event from thread&#8217;s event queue. */
+KD_API const KDEvent *KD_APIENTRY kdWaitEvent(KDust timeout);
+
+/* kdSetEventUserptr: Set the userptr for global events. */
+KD_API void KD_APIENTRY kdSetEventUserptr(void *userptr);
+
+/* kdDefaultEvent: Perform default processing on an unrecognized event. */
+KD_API void KD_APIENTRY kdDefaultEvent(const KDEvent *event);
+
+/* kdPumpEvents: Pump the thread&#8217;s event queue, performing callbacks. */
+KD_API KDint KD_APIENTRY kdPumpEvents(void);
+
+/* kdInstallCallback: Install or remove a callback function for event processing. */
+typedef void (KD_APIENTRY KDCallbackFunc)(const KDEvent *event);
+KD_API KDint KD_APIENTRY kdInstallCallback(KDCallbackFunc *func, KDint eventtype, void *eventuserptr);
+
+/* kdCreateEvent: Create an event for posting. */
+KD_API KDEvent *KD_APIENTRY kdCreateEvent(void);
+
+/* kdPostEvent, kdPostThreadEvent: Post an event into a queue. */
+KD_API KDint KD_APIENTRY kdPostEvent(KDEvent *event);
+KD_API KDint KD_APIENTRY kdPostThreadEvent(KDEvent *event, KDThread *thread);
+typedef struct KDEventUser {
+ union {
+ KDint64 i64;
+ void *p;
+ struct {
+ KDint32 a;
+ KDint32 b;
+ } i32pair;
+ } value1;
+ union {
+ KDint64 i64;
+ struct {
+ union {
+ KDint32 i32;
+ void *p;
+ } value2;
+ union {
+ KDint32 i32;
+ void *p;
+ } value3;
+ } i32orp;
+ } value23;
+} KDEventUser;
+
+/* kdFreeEvent: Abandon an event instead of posting it. */
+KD_API void KD_APIENTRY kdFreeEvent(KDEvent *event);
+
+/*******************************************************
+ * System events
+ *******************************************************/
+
+/* KD_EVENT_QUIT: Event to request to quit application. */
+#define KD_EVENT_QUIT 43
+
+/* KD_EVENT_PAUSE: Application pause event. */
+#define KD_EVENT_PAUSE 45
+
+/* KD_EVENT_RESUME: Application resume event. */
+#define KD_EVENT_RESUME 46
+
+/* KD_EVENT_ORIENTATION: Orientation change event. */
+#define KD_EVENT_ORIENTATION 48
+
+/* KD_IOGROUP_EVENT: I/O group for OpenKODE Core system events implemented as state values. */
+#define KD_IOGROUP_EVENT 0x100
+#define KD_STATE_EVENT_USING_BATTERY (KD_IOGROUP_EVENT + 0)
+#define KD_STATE_EVENT_LOW_BATTERY (KD_IOGROUP_EVENT + 1)
+
+
+/* KD_IOGROUP_ORIENTATION: I/O group for OpenKODE Core orientation state. */
+#define KD_IOGROUP_ORIENTATION 0x200
+#define KD_STATE_ORIENTATION_OVERALL (KD_IOGROUP_ORIENTATION + 0)
+#define KD_STATE_ORIENTATION_SCREEN (KD_IOGROUP_ORIENTATION + 1)
+#define KD_STATE_ORIENTATION_RENDERING (KD_IOGROUP_ORIENTATION + 2)
+#define KD_STATE_ORIENTATION_LOCKSURFACE (KD_IOGROUP_ORIENTATION + 3)
+
+
+/*******************************************************
+ * Application startup and exit.
+ *******************************************************/
+
+/* kdMain: The application-defined main function. */
+KDint KD_APIENTRY kdMain(KDint argc, const KDchar *const *argv);
+
+/* kdExit: Exit the application. */
+KD_API KD_NORETURN void KD_APIENTRY kdExit(KDint status);
+
+/*******************************************************
+ * Utility library functions
+ *******************************************************/
+
+/* kdAbs: Compute the absolute value of an integer. */
+KD_API KDint KD_APIENTRY kdAbs(KDint i);
+
+/* kdStrtof: Convert a string to a floating point number. */
+KD_API KDfloat32 KD_APIENTRY kdStrtof(const KDchar *s, KDchar **endptr);
+
+/* kdStrtol, kdStrtoul: Convert a string to an integer. */
+KD_API KDint KD_APIENTRY kdStrtol(const KDchar *s, KDchar **endptr, KDint base);
+KD_API KDuint KD_APIENTRY kdStrtoul(const KDchar *s, KDchar **endptr, KDint base);
+
+/* kdLtostr, kdUltostr: Convert an integer to a string. */
+#define KD_LTOSTR_MAXLEN ((sizeof(KDint)*8*3+6)/10+2)
+#define KD_ULTOSTR_MAXLEN ((sizeof(KDint)*8+2)/3+1)
+KD_API KDssize KD_APIENTRY kdLtostr(KDchar *buffer, KDsize buflen, KDint number);
+KD_API KDssize KD_APIENTRY kdUltostr(KDchar *buffer, KDsize buflen, KDuint number, KDint base);
+
+/* kdFtostr: Convert a float to a string. */
+#define KD_FTOSTR_MAXLEN 16
+KD_API KDssize KD_APIENTRY kdFtostr(KDchar *buffer, KDsize buflen, KDfloat32 number);
+
+/* kdCryptoRandom: Return random data. */
+KD_API KDint KD_APIENTRY kdCryptoRandom(KDuint8 *buf, KDsize buflen);
+
+/*******************************************************
+ * Locale specific functions
+ *******************************************************/
+
+/* kdGetLocale: Determine the current language and locale. */
+KD_API const KDchar *KD_APIENTRY kdGetLocale(void);
+
+/*******************************************************
+ * Memory allocation
+ *******************************************************/
+
+/* kdMalloc: Allocate memory. */
+KD_API void *KD_APIENTRY kdMalloc(KDsize size);
+
+/* kdFree: Free allocated memory block. */
+KD_API void KD_APIENTRY kdFree(void *ptr);
+
+/* kdRealloc: Resize memory block. */
+KD_API void *KD_APIENTRY kdRealloc(void *ptr, KDsize size);
+
+/*******************************************************
+ * Thread-local storage.
+ *******************************************************/
+
+/* kdGetTLS: Get the thread-local storage pointer. */
+KD_API void *KD_APIENTRY kdGetTLS(void);
+
+/* kdSetTLS: Set the thread-local storage pointer. */
+KD_API void KD_APIENTRY kdSetTLS(void *ptr);
+
+/*******************************************************
+ * Mathematical functions
+ *******************************************************/
+#define KD_E_F 2.71828175F
+#define KD_PI_F 3.14159274F
+#define KD_PI_2_F 1.57079637F
+#define KD_2PI_F 6.28318548F
+#define KD_LOG2E_F 1.44269502F
+#define KD_LOG10E_F 0.434294492F
+#define KD_LN2_F 0.693147182F
+#define KD_LN10_F 2.30258512F
+#define KD_PI_4_F 0.785398185F
+#define KD_1_PI_F 0.318309873F
+#define KD_2_PI_F 0.636619747F
+#define KD_2_SQRTPI_F 1.12837923F
+#define KD_SQRT2_F 1.41421354F
+#define KD_SQRT1_2_F 0.707106769F
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_FLT_MAX 3.40282346638528860e+38F
+#define KD_FLT_MIN 1.17549435e-38F
+/* KD_INFINITY is defined in kdplatform.h since no portable definition
+ * is possible. */
+#define kdIsNan(x) (((x) != (x)) ? 1 : 0)
+#define KD_HUGE_VALF KD_INFINITY
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+/* kdAcosf: Arc cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdAcosf(KDfloat32 x);
+
+/* kdAsinf: Arc sine function. */
+KD_API KDfloat32 KD_APIENTRY kdAsinf(KDfloat32 x);
+
+/* kdAtanf: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtanf(KDfloat32 x);
+
+/* kdAtan2f: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtan2f(KDfloat32 y, KDfloat32 x);
+
+/* kdCosf: Cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdCosf(KDfloat32 x);
+
+/* kdSinf: Sine function. */
+KD_API KDfloat32 KD_APIENTRY kdSinf(KDfloat32 x);
+
+/* kdTanf: Tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdTanf(KDfloat32 x);
+
+/* kdExpf: Exponential function. */
+KD_API KDfloat32 KD_APIENTRY kdExpf(KDfloat32 x);
+
+/* kdLogf: Natural logarithm function. */
+KD_API KDfloat32 KD_APIENTRY kdLogf(KDfloat32 x);
+
+/* kdFabsf: Absolute value. */
+KD_API KDfloat32 KD_APIENTRY kdFabsf(KDfloat32 x);
+
+/* kdPowf: Power function. */
+KD_API KDfloat32 KD_APIENTRY kdPowf(KDfloat32 x, KDfloat32 y);
+
+/* kdSqrtf: Square root function. */
+KD_API KDfloat32 KD_APIENTRY kdSqrtf(KDfloat32 x);
+
+/* kdCeilf: Return ceiling value. */
+KD_API KDfloat32 KD_APIENTRY kdCeilf(KDfloat32 x);
+
+/* kdFloorf: Return floor value. */
+KD_API KDfloat32 KD_APIENTRY kdFloorf(KDfloat32 x);
+
+/* kdRoundf: Round value to nearest integer. */
+KD_API KDfloat32 KD_APIENTRY kdRoundf(KDfloat32 x);
+
+/* kdInvsqrtf: Inverse square root function. */
+KD_API KDfloat32 KD_APIENTRY kdInvsqrtf(KDfloat32 x);
+
+/* kdFmodf: Calculate floating point remainder. */
+KD_API KDfloat32 KD_APIENTRY kdFmodf(KDfloat32 x, KDfloat32 y);
+
+/*******************************************************
+ * String and memory functions
+ *******************************************************/
+
+/* kdMemchr: Scan memory for a byte value. */
+KD_API void *KD_APIENTRY kdMemchr(const void *src, KDint byte, KDsize len);
+
+/* kdMemcmp: Compare two memory regions. */
+KD_API KDint KD_APIENTRY kdMemcmp(const void *src1, const void *src2, KDsize len);
+
+/* kdMemcpy: Copy a memory region, no overlapping. */
+KD_API void *KD_APIENTRY kdMemcpy(void *buf, const void *src, KDsize len);
+
+/* kdMemmove: Copy a memory region, overlapping allowed. */
+KD_API void *KD_APIENTRY kdMemmove(void *buf, const void *src, KDsize len);
+
+/* kdMemset: Set bytes in memory to a value. */
+KD_API void *KD_APIENTRY kdMemset(void *buf, KDint byte, KDsize len);
+
+/* kdStrchr: Scan string for a byte value. */
+KD_API KDchar *KD_APIENTRY kdStrchr(const KDchar *str, KDint ch);
+
+/* kdStrcmp: Compares two strings. */
+KD_API KDint KD_APIENTRY kdStrcmp(const KDchar *str1, const KDchar *str2);
+
+/* kdStrlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrlen(const KDchar *str);
+
+/* kdStrnlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrnlen(const KDchar *str, KDsize maxlen);
+
+/* kdStrncat_s: Concatenate two strings. */
+KD_API KDint KD_APIENTRY kdStrncat_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srcmaxlen);
+
+/* kdStrncmp: Compares two strings with length limit. */
+KD_API KDint KD_APIENTRY kdStrncmp(const KDchar *str1, const KDchar *str2, KDsize maxlen);
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrcpy_s(KDchar *buf, KDsize buflen, const KDchar *src);
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrncpy_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srclen);
+
+/*******************************************************
+ * Time functions
+ *******************************************************/
+
+/* kdGetTimeUST: Get the current unadjusted system time. */
+KD_API KDust KD_APIENTRY kdGetTimeUST(void);
+
+/* kdTime: Get the current wall clock time. */
+KD_API KDtime KD_APIENTRY kdTime(KDtime *timep);
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+typedef struct KDTm {
+ KDint32 tm_sec;
+ KDint32 tm_min;
+ KDint32 tm_hour;
+ KDint32 tm_mday;
+ KDint32 tm_mon;
+ KDint32 tm_year;
+ KDint32 tm_wday;
+ KDint32 tm_yday;
+} KDTm;
+KD_API KDTm *KD_APIENTRY kdGmtime_r(const KDtime *timep, KDTm *result);
+KD_API KDTm *KD_APIENTRY kdLocaltime_r(const KDtime *timep, KDTm *result);
+
+/* kdUSTAtEpoch: Get the UST corresponding to KDtime 0. */
+KD_API KDust KD_APIENTRY kdUSTAtEpoch(void);
+
+/*******************************************************
+ * Timer functions
+ *******************************************************/
+
+/* kdSetTimer: Set timer. */
+#define KD_TIMER_ONESHOT 61
+#define KD_TIMER_PERIODIC_AVERAGE 62
+#define KD_TIMER_PERIODIC_MINIMUM 63
+typedef struct KDTimer KDTimer;
+KD_API KDTimer *KD_APIENTRY kdSetTimer(KDint64 interval, KDint periodic, void *eventuserptr);
+
+/* kdCancelTimer: Cancel and free a timer. */
+KD_API KDint KD_APIENTRY kdCancelTimer(KDTimer *timer);
+
+/* KD_EVENT_TIMER: Timer fire event. */
+#define KD_EVENT_TIMER 42
+
+/*******************************************************
+ * File system
+ *******************************************************/
+#define KD_EOF (-1)
+
+/* kdFopen: Open a file from the file system. */
+typedef struct KDFile KDFile;
+KD_API KDFile *KD_APIENTRY kdFopen(const KDchar *pathname, const KDchar *mode);
+
+/* kdFclose: Close an open file. */
+KD_API KDint KD_APIENTRY kdFclose(KDFile *file);
+
+/* kdFflush: Flush an open file. */
+KD_API KDint KD_APIENTRY kdFflush(KDFile *file);
+
+/* kdFread: Read from a file. */
+KD_API KDsize KD_APIENTRY kdFread(void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdFwrite: Write to a file. */
+KD_API KDsize KD_APIENTRY kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdGetc: Read next byte from an open file. */
+KD_API KDint KD_APIENTRY kdGetc(KDFile *file);
+
+/* kdPutc: Write a byte to an open file. */
+KD_API KDint KD_APIENTRY kdPutc(KDint c, KDFile *file);
+
+/* kdFgets: Read a line of text from an open file. */
+KD_API KDchar *KD_APIENTRY kdFgets(KDchar *buffer, KDsize buflen, KDFile *file);
+
+/* kdFEOF: Check for end of file. */
+KD_API KDint KD_APIENTRY kdFEOF(KDFile *file);
+
+/* kdFerror: Check for an error condition on an open file. */
+KD_API KDint KD_APIENTRY kdFerror(KDFile *file);
+
+/* kdClearerr: Clear a file&#8217;s error and end-of-file indicators. */
+KD_API void KD_APIENTRY kdClearerr(KDFile *file);
+
+/* kdFseek: Reposition the file position indicator in a file. */
+typedef enum {
+ KD_SEEK_SET = 0,
+ KD_SEEK_CUR = 1,
+ KD_SEEK_END = 2
+} KDfileSeekOrigin;
+KD_API KDint KD_APIENTRY kdFseek(KDFile *file, KDoff offset, KDfileSeekOrigin origin);
+
+/* kdFtell: Get the file position of an open file. */
+KD_API KDoff KD_APIENTRY kdFtell(KDFile *file);
+
+/* kdMkdir: Create new directory. */
+KD_API KDint KD_APIENTRY kdMkdir(const KDchar *pathname);
+
+/* kdRmdir: Delete a directory. */
+KD_API KDint KD_APIENTRY kdRmdir(const KDchar *pathname);
+
+/* kdRename: Rename a file. */
+KD_API KDint KD_APIENTRY kdRename(const KDchar *src, const KDchar *dest);
+
+/* kdRemove: Delete a file. */
+KD_API KDint KD_APIENTRY kdRemove(const KDchar *pathname);
+
+/* kdTruncate: Truncate or extend a file. */
+KD_API KDint KD_APIENTRY kdTruncate(const KDchar *pathname, KDoff length);
+
+/* kdStat, kdFstat: Return information about a file. */
+typedef struct KDStat {
+ KDmode st_mode;
+ KDoff st_size;
+ KDtime st_mtime;
+} KDStat;
+KD_API KDint KD_APIENTRY kdStat(const KDchar *pathname, struct KDStat *buf);
+KD_API KDint KD_APIENTRY kdFstat(KDFile *file, struct KDStat *buf);
+#define KD_ISREG(m) ((m) & 0x8000)
+#define KD_ISDIR(m) ((m) & 0x4000)
+
+/* kdAccess: Determine whether the application can access a file or directory. */
+KD_API KDint KD_APIENTRY kdAccess(const KDchar *pathname, KDint amode);
+#define KD_R_OK 4
+#define KD_W_OK 2
+#define KD_X_OK 1
+
+/* kdOpenDir: Open a directory ready for listing. */
+typedef struct KDDir KDDir;
+KD_API KDDir *KD_APIENTRY kdOpenDir(const KDchar *pathname);
+
+/* kdReadDir: Return the next file in a directory. */
+typedef struct KDDirent {
+ const KDchar *d_name;
+} KDDirent;
+KD_API KDDirent *KD_APIENTRY kdReadDir(KDDir *dir);
+
+/* kdCloseDir: Close a directory. */
+KD_API KDint KD_APIENTRY kdCloseDir(KDDir *dir);
+
+/* kdGetFree: Get free space on a drive. */
+KD_API KDoff KD_APIENTRY kdGetFree(const KDchar *pathname);
+
+/*******************************************************
+ * Network sockets
+ *******************************************************/
+
+/* KDSockaddr: Struct type for socket address. */
+typedef struct KDSockaddr {
+ KDuint16 family;
+ union {
+#define KD_AF_INET 70
+ struct {
+ KDuint16 port;
+ KDuint32 address;
+ } sin;
+ } data;
+} KDSockaddr;
+
+/* kdNameLookup: Look up a hostname. */
+KD_API KDint KD_APIENTRY kdNameLookup(KDint af, const KDchar *hostname, void *eventuserptr);
+
+/* kdNameLookupCancel: Selectively cancels ongoing kdNameLookup operations. */
+KD_API void KD_APIENTRY kdNameLookupCancel(void *eventuserptr);
+
+/* kdSocketCreate: Creates a socket. */
+typedef struct KDSocket KDSocket;
+KD_API KDSocket *KD_APIENTRY kdSocketCreate(KDint type, void *eventuserptr);
+#define KD_SOCK_TCP 64
+#define KD_SOCK_UDP 65
+
+/* kdSocketClose: Closes a socket. */
+KD_API KDint KD_APIENTRY kdSocketClose(KDSocket *socket);
+
+/* kdSocketBind: Bind a socket. */
+KD_API KDint KD_APIENTRY kdSocketBind(KDSocket *socket, const struct KDSockaddr *addr, KDboolean reuse);
+#define KD_INADDR_ANY 0
+
+/* kdSocketGetName: Get the local address of a socket. */
+KD_API KDint KD_APIENTRY kdSocketGetName(KDSocket *socket, struct KDSockaddr *addr);
+
+/* kdSocketConnect: Connects a socket. */
+KD_API KDint KD_APIENTRY kdSocketConnect(KDSocket *socket, const KDSockaddr *addr);
+
+/* kdSocketListen: Listen on a socket. */
+KD_API KDint KD_APIENTRY kdSocketListen(KDSocket *socket, KDint backlog);
+
+/* kdSocketAccept: Accept an incoming connection. */
+KD_API KDSocket *KD_APIENTRY kdSocketAccept(KDSocket *socket, KDSockaddr *addr, void *eventuserptr);
+
+/* kdSocketSend, kdSocketSendTo: Send data to a socket. */
+KD_API KDint KD_APIENTRY kdSocketSend(KDSocket *socket, const void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketSendTo(KDSocket *socket, const void *buf, KDint len, const KDSockaddr *addr);
+
+/* kdSocketRecv, kdSocketRecvFrom: Receive data from a socket. */
+KD_API KDint KD_APIENTRY kdSocketRecv(KDSocket *socket, void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketRecvFrom(KDSocket *socket, void *buf, KDint len, KDSockaddr *addr);
+
+/* kdHtonl: Convert a 32-bit integer from host to network byte order. */
+KD_API KDuint32 KD_APIENTRY kdHtonl(KDuint32 hostlong);
+
+/* kdHtons: Convert a 16-bit integer from host to network byte order. */
+KD_API KDuint16 KD_APIENTRY kdHtons(KDuint16 hostshort);
+
+/* kdNtohl: Convert a 32-bit integer from network to host byte order. */
+KD_API KDuint32 KD_APIENTRY kdNtohl(KDuint32 netlong);
+
+/* kdNtohs: Convert a 16-bit integer from network to host byte order. */
+KD_API KDuint16 KD_APIENTRY kdNtohs(KDuint16 netshort);
+
+/* kdInetAton: Convert a &#8220;dotted quad&#8221; format address to an integer. */
+KD_API KDint KD_APIENTRY kdInetAton(const KDchar *cp, KDuint32 *inp);
+
+/* kdInetNtop: Convert a network address to textual form. */
+#define KD_INET_ADDRSTRLEN 16
+typedef struct KDInAddr {
+ KDuint32 s_address; // Renamed this from s_addr as it causes a conflict with winsock2.h
+} KDInAddr;
+KD_API const KDchar *KD_APIENTRY kdInetNtop(KDuint af, const void *src, KDchar *dst, KDsize cnt);
+
+/* KD_EVENT_SOCKET_READABLE: Event to indicate that a socket is readable. */
+#define KD_EVENT_SOCKET_READABLE 49
+typedef struct KDEventSocketReadable {
+ KDSocket *socket;
+} KDEventSocketReadable;
+
+/* KD_EVENT_SOCKET_WRITABLE: Event to indicate that a socket is writable. */
+#define KD_EVENT_SOCKET_WRITABLE 50
+typedef struct KDEventSocketWritable {
+ KDSocket *socket;
+} KDEventSocketWritable;
+
+/* KD_EVENT_SOCKET_CONNECT_COMPLETE: Event generated when a socket connect is complete */
+#define KD_EVENT_SOCKET_CONNECT_COMPLETE 51
+typedef struct KDEventSocketConnect {
+ KDSocket *socket;
+ KDint32 error;
+} KDEventSocketConnect;
+
+/* KD_EVENT_SOCKET_INCOMING: Event generated when a listening socket detects an incoming connection or an error. */
+#define KD_EVENT_SOCKET_INCOMING 52
+typedef struct KDEventSocketIncoming {
+ KDSocket *socket;
+} KDEventSocketIncoming;
+
+/* KD_EVENT_NAME_LOOKUP_COMPLETE: kdNameLookup complete event. */
+#define KD_EVENT_NAME_LOOKUP_COMPLETE 53
+typedef struct KDEventNameLookup {
+ KDint32 error;
+ KDint32 resultlen;
+ const KDSockaddr *result;
+ KDboolean more;
+} KDEventNameLookup;
+
+/*******************************************************
+ * Input/output
+ *******************************************************/
+
+/* KD_EVENT_STATE: State changed event. */
+#define KD_EVENT_STATE 55
+
+typedef struct KDEventState {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventState;
+
+/* KD_EVENT_INPUT: Input changed event. */
+#define KD_EVENT_INPUT 56
+
+typedef struct KDEventInput {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventInput;
+
+/* KD_EVENT_INPUT_JOG: Jogdial jog event. */
+#define KD_EVENT_INPUT_JOG 71
+typedef struct KDEventInputJog {
+ KDint32 index;
+ KDint32 count;
+} KDEventInputJog;
+
+/* KD_EVENT_INPUT_POINTER: Pointer input changed event. */
+#define KD_EVENT_INPUT_POINTER 57
+typedef struct KDEventInputPointer {
+ KDint32 index;
+ KDint32 select;
+ KDint32 x;
+ KDint32 y;
+} KDEventInputPointer;
+
+/* KD_EVENT_INPUT_STICK: Joystick stick changed event. */
+#define KD_EVENT_INPUT_STICK 58
+typedef struct KDEventInputStick {
+ KDint32 index;
+ KDint32 x;
+ KDint32 y;
+ KDint32 z;
+} KDEventInputStick;
+
+/* kdStateGeti, kdStateGetl, kdStateGetf: get state value(s) */
+KD_API KDint KD_APIENTRY kdStateGeti(KDint startidx, KDuint numidxs, KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetl(KDint startidx, KDuint numidxs, KDint64 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetf(KDint startidx, KDuint numidxs, KDfloat32 *buffer);
+
+/* kdOutputSeti, kdOutputSetf: set outputs */
+KD_API KDint KD_APIENTRY kdOutputSeti(KDint startidx, KDuint numidxs, const KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdOutputSetf(KDint startidx, KDuint numidxs, const KDfloat32 *buffer);
+#define KD_IO_CONTROLLER_STRIDE 64
+
+/* KD_IOGROUP_GAMEKEYS: I/O group for game keys. */
+#define KD_IOGROUP_GAMEKEYS 0x1000
+#define KD_STATE_GAMEKEYS_AVAILABILITY (KD_IOGROUP_GAMEKEYS + 0)
+#define KD_INPUT_GAMEKEYS_UP (KD_IOGROUP_GAMEKEYS + 1)
+#define KD_INPUT_GAMEKEYS_LEFT (KD_IOGROUP_GAMEKEYS + 2)
+#define KD_INPUT_GAMEKEYS_RIGHT (KD_IOGROUP_GAMEKEYS + 3)
+#define KD_INPUT_GAMEKEYS_DOWN (KD_IOGROUP_GAMEKEYS + 4)
+#define KD_INPUT_GAMEKEYS_FIRE (KD_IOGROUP_GAMEKEYS + 5)
+#define KD_INPUT_GAMEKEYS_A (KD_IOGROUP_GAMEKEYS + 6)
+#define KD_INPUT_GAMEKEYS_B (KD_IOGROUP_GAMEKEYS + 7)
+#define KD_INPUT_GAMEKEYS_C (KD_IOGROUP_GAMEKEYS + 8)
+#define KD_INPUT_GAMEKEYS_D (KD_IOGROUP_GAMEKEYS + 9)
+
+/* KD_IOGROUP_GAMEKEYSNC: I/O group for game keys, no chording. */
+#define KD_IOGROUP_GAMEKEYSNC 0x1100
+#define KD_STATE_GAMEKEYSNC_AVAILABILITY (KD_IOGROUP_GAMEKEYSNC + 0)
+#define KD_INPUT_GAMEKEYSNC_UP (KD_IOGROUP_GAMEKEYSNC + 1)
+#define KD_INPUT_GAMEKEYSNC_LEFT (KD_IOGROUP_GAMEKEYSNC + 2)
+#define KD_INPUT_GAMEKEYSNC_RIGHT (KD_IOGROUP_GAMEKEYSNC + 3)
+#define KD_INPUT_GAMEKEYSNC_DOWN (KD_IOGROUP_GAMEKEYSNC + 4)
+#define KD_INPUT_GAMEKEYSNC_FIRE (KD_IOGROUP_GAMEKEYSNC + 5)
+#define KD_INPUT_GAMEKEYSNC_A (KD_IOGROUP_GAMEKEYSNC + 6)
+#define KD_INPUT_GAMEKEYSNC_B (KD_IOGROUP_GAMEKEYSNC + 7)
+#define KD_INPUT_GAMEKEYSNC_C (KD_IOGROUP_GAMEKEYSNC + 8)
+#define KD_INPUT_GAMEKEYSNC_D (KD_IOGROUP_GAMEKEYSNC + 9)
+
+/* KD_IOGROUP_PHONEKEYPAD: I/O group for phone keypad. */
+#define KD_IOGROUP_PHONEKEYPAD 0x2000
+#define KD_STATE_PHONEKEYPAD_AVAILABILITY (KD_IOGROUP_PHONEKEYPAD + 0)
+#define KD_INPUT_PHONEKEYPAD_0 (KD_IOGROUP_PHONEKEYPAD + 1)
+#define KD_INPUT_PHONEKEYPAD_1 (KD_IOGROUP_PHONEKEYPAD + 2)
+#define KD_INPUT_PHONEKEYPAD_2 (KD_IOGROUP_PHONEKEYPAD + 3)
+#define KD_INPUT_PHONEKEYPAD_3 (KD_IOGROUP_PHONEKEYPAD + 4)
+#define KD_INPUT_PHONEKEYPAD_4 (KD_IOGROUP_PHONEKEYPAD + 5)
+#define KD_INPUT_PHONEKEYPAD_5 (KD_IOGROUP_PHONEKEYPAD + 6)
+#define KD_INPUT_PHONEKEYPAD_6 (KD_IOGROUP_PHONEKEYPAD + 7)
+#define KD_INPUT_PHONEKEYPAD_7 (KD_IOGROUP_PHONEKEYPAD + 8)
+#define KD_INPUT_PHONEKEYPAD_8 (KD_IOGROUP_PHONEKEYPAD + 9)
+#define KD_INPUT_PHONEKEYPAD_9 (KD_IOGROUP_PHONEKEYPAD + 10)
+#define KD_INPUT_PHONEKEYPAD_STAR (KD_IOGROUP_PHONEKEYPAD + 11)
+#define KD_INPUT_PHONEKEYPAD_HASH (KD_IOGROUP_PHONEKEYPAD + 12)
+#define KD_INPUT_PHONEKEYPAD_LEFTSOFT (KD_IOGROUP_PHONEKEYPAD + 13)
+#define KD_INPUT_PHONEKEYPAD_RIGHTSOFT (KD_IOGROUP_PHONEKEYPAD + 14)
+#define KD_STATE_PHONEKEYPAD_ORIENTATION (KD_IOGROUP_PHONEKEYPAD + 15)
+
+/* KD_IOGROUP_VIBRATE: I/O group for vibrate. */
+#define KD_IOGROUP_VIBRATE 0x3000
+#define KD_STATE_VIBRATE_AVAILABILITY (KD_IOGROUP_VIBRATE + 0)
+#define KD_STATE_VIBRATE_MINFREQUENCY (KD_IOGROUP_VIBRATE + 1)
+#define KD_STATE_VIBRATE_MAXFREQUENCY (KD_IOGROUP_VIBRATE + 2)
+#define KD_OUTPUT_VIBRATE_VOLUME (KD_IOGROUP_VIBRATE + 3)
+#define KD_OUTPUT_VIBRATE_FREQUENCY (KD_IOGROUP_VIBRATE + 4)
+
+/* KD_IOGROUP_POINTER: I/O group for pointer. */
+#define KD_IOGROUP_POINTER 0x4000
+#define KD_STATE_POINTER_AVAILABILITY (KD_IOGROUP_POINTER + 0)
+#define KD_INPUT_POINTER_X (KD_IOGROUP_POINTER + 1)
+#define KD_INPUT_POINTER_Y (KD_IOGROUP_POINTER + 2)
+#define KD_INPUT_POINTER_SELECT (KD_IOGROUP_POINTER + 3)
+
+/* KD_IOGROUP_BACKLIGHT: I/O group for backlight. */
+#define KD_IOGROUP_BACKLIGHT 0x5000
+#define KD_STATE_BACKLIGHT_AVAILABILITY (KD_IOGROUP_BACKLIGHT + 0)
+#define KD_OUTPUT_BACKLIGHT_FORCE (KD_IOGROUP_BACKLIGHT + 1)
+
+/* KD_IOGROUP_JOGDIAL: I/O group for a jog dial. */
+#define KD_IOGROUP_JOGDIAL 0x6000
+#define KD_STATE_JOGDIAL_AVAILABILITY (KD_IOGROUP_JOGDIAL + 0)
+#define KD_INPUT_JOGDIAL_UP (KD_IOGROUP_JOGDIAL + 1)
+#define KD_INPUT_JOGDIAL_LEFT (KD_IOGROUP_JOGDIAL + 2)
+#define KD_INPUT_JOGDIAL_RIGHT (KD_IOGROUP_JOGDIAL + 3)
+#define KD_INPUT_JOGDIAL_DOWN (KD_IOGROUP_JOGDIAL + 4)
+#define KD_INPUT_JOGDIAL_SELECT (KD_IOGROUP_JOGDIAL + 5)
+
+/* KD_IOGROUP_STICK: I/O group for joystick. */
+#define KD_IOGROUP_STICK 0x7000
+#define KD_STATE_STICK_AVAILABILITY (KD_IOGROUP_STICK + 0)
+#define KD_INPUT_STICK_X (KD_IOGROUP_STICK + 1)
+#define KD_INPUT_STICK_Y (KD_IOGROUP_STICK + 2)
+#define KD_INPUT_STICK_Z (KD_IOGROUP_STICK + 3)
+#define KD_INPUT_STICK_BUTTON (KD_IOGROUP_STICK + 4)
+#define KD_IO_STICK_STRIDE 8
+
+/* KD_IOGROUP_DPAD: I/O group for D-pad. */
+#define KD_IOGROUP_DPAD 0x8000
+#define KD_STATE_DPAD_AVAILABILITY (KD_IOGROUP_DPAD + 0)
+#define KD_STATE_DPAD_COPY (KD_IOGROUP_DPAD + 1)
+#define KD_INPUT_DPAD_UP (KD_IOGROUP_DPAD + 2)
+#define KD_INPUT_DPAD_LEFT (KD_IOGROUP_DPAD + 3)
+#define KD_INPUT_DPAD_RIGHT (KD_IOGROUP_DPAD + 4)
+#define KD_INPUT_DPAD_DOWN (KD_IOGROUP_DPAD + 5)
+#define KD_INPUT_DPAD_SELECT (KD_IOGROUP_DPAD + 6)
+#define KD_IO_DPAD_STRIDE 8
+
+/* KD_IOGROUP_BUTTONS: I/O group for buttons associated with joystick or D-pad. */
+#define KD_IOGROUP_BUTTONS 0x9000
+#define KD_STATE_BUTTONS_AVAILABILITY (KD_IOGROUP_BUTTONS + 0)
+#define KD_INPUT_BUTTONS_0 (KD_IOGROUP_BUTTONS + 1)
+
+/* KD_IO_UNDEFINED: I/O items reserved for implementation-dependent use. */
+#define KD_IO_UNDEFINED 0x40000000
+
+/*******************************************************
+ * Windowing
+ *******************************************************/
+#ifdef KD_WINDOW_SUPPORTED
+#include <EGL/egl.h>
+typedef struct KDWindow KDWindow;
+
+/* kdCreateWindow: Create a window. */
+KD_API KDWindow *KD_APIENTRY kdCreateWindow(EGLDisplay display, EGLConfig config, void *eventuserptr);
+
+/* kdDestroyWindow: Destroy a window. */
+KD_API KDint KD_APIENTRY kdDestroyWindow(KDWindow *window);
+
+/* kdSetWindowPropertybv, kdSetWindowPropertyiv, kdSetWindowPropertycv: Set a window property to request a change in the on-screen representation of the window. */
+KD_API KDint KD_APIENTRY kdSetWindowPropertybv(KDWindow *window, KDint pname, const KDboolean *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertyiv(KDWindow *window, KDint pname, const KDint32 *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertycv(KDWindow *window, KDint pname, const KDchar *param);
+
+/* kdGetWindowPropertybv, kdGetWindowPropertyiv, kdGetWindowPropertycv: Get the current value of a window property. */
+KD_API KDint KD_APIENTRY kdGetWindowPropertybv(KDWindow *window, KDint pname, KDboolean *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertyiv(KDWindow *window, KDint pname, KDint32 *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertycv(KDWindow *window, KDint pname, KDchar *param, KDsize *size);
+
+/* kdRealizeWindow: Realize the window as a displayable entity and get the native window handle for passing to EGL. */
+KD_API KDint KD_APIENTRY kdRealizeWindow(KDWindow *window, EGLNativeWindowType *nativewindow);
+
+/* KD_WINDOWPROPERTY_SIZE: Window client area width and height. */
+#define KD_WINDOWPROPERTY_SIZE 66
+
+/* KD_WINDOWPROPERTY_VISIBILITY: Window visibility status. */
+#define KD_WINDOWPROPERTY_VISIBILITY 67
+
+/* KD_WINDOWPROPERTY_FOCUS: Window input focus status. */
+#define KD_WINDOWPROPERTY_FOCUS 68
+
+/* KD_WINDOWPROPERTY_CAPTION: Window caption. */
+#define KD_WINDOWPROPERTY_CAPTION 69
+
+/* KD_EVENT_WINDOW_CLOSE: Event to request to close window. */
+#define KD_EVENT_WINDOW_CLOSE 44
+
+/* KD_EVENT_WINDOWPROPERTY_CHANGE: Notification about realized window property change. */
+#define KD_EVENT_WINDOWPROPERTY_CHANGE 47
+typedef struct KDEventWindowProperty {
+ KDint32 pname;
+} KDEventWindowProperty;
+
+/* KD_EVENT_WINDOW_FOCUS: Event for change of window&#8217;s focus state. */
+#define KD_EVENT_WINDOW_FOCUS 60
+typedef struct KDEventWindowFocus {
+ KDint32 focusstate;
+} KDEventWindowFocus;
+
+/* KD_EVENT_WINDOW_REDRAW: Event to notify need to redraw the window. */
+#define KD_EVENT_WINDOW_REDRAW 59
+#endif /* KD_WINDOW_SUPPORTED */
+
+/*******************************************************
+ * Assertions and logging
+ *******************************************************/
+
+/* kdHandleAssertion: Handle assertion failure. */
+KD_API void KD_APIENTRY kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber);
+
+/* kdLogMessage: Output a log message. */
+#ifdef KD_NDEBUG
+#define kdLogMessage(s)
+#else
+KD_API void KD_APIENTRY kdLogMessage(const KDchar *string);
+#endif
+
+/* struct KDEvent delayed to the end as it uses event data structs from
+ * other parts of the .h file. */
+struct KDEvent {
+ KDust timestamp;
+ KDint32 type;
+ void *userptr;
+ union KDEventData {
+ KDEventState state;
+ KDEventInput input;
+ KDEventInputJog inputjog;
+ KDEventInputPointer inputpointer;
+ KDEventInputStick inputstick;
+ KDEventSocketReadable socketreadable;
+ KDEventSocketWritable socketwritable;
+ KDEventSocketConnect socketconnect;
+ KDEventSocketIncoming socketincoming;
+ KDEventNameLookup namelookup;
+#ifdef KD_WINDOW_SUPPORTED
+ KDEventWindowProperty windowproperty;
+ KDEventWindowFocus windowfocus;
+#endif /* KD_WINDOW_SUPPORTED */
+ KDEventUser user;
+ } data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kdplatform.h b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kdplatform.h
new file mode 100644
index 00000000..3cf09f52
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs/KD/kdplatform.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Sample KD/kdplatform.h for OpenKODE Core 1.0.3 */
+#ifndef __kdplatform_h_
+#define __kdplatform_h_
+
+#define KD_API
+#define KD_APIENTRY
+
+typedef int KDint32;
+typedef unsigned int KDuint32;
+typedef long long KDint64;
+typedef unsigned long long KDuint64;
+typedef short KDint16;
+typedef unsigned short KDuint16;
+typedef unsigned long KDuintptr;
+typedef unsigned long KDsize;
+typedef long KDssize;
+#define KDINT_MIN (-0x7fffffff-1)
+#define KDINT_MAX 0x7fffffff
+#define KDUINT_MAX 0xffffffffU
+#define KDINT64_MIN (-0x7fffffffffffffffLL-1)
+#define KDINT64_MAX 0x7fffffffffffffffLL
+#define KDUINT64_MAX 0xffffffffffffffffULL
+#define KDSSIZE_MIN (-0x7fffffff-1)
+#define KDSSIZE_MAX 0x7fffffff
+#define KDSIZE_MAX 0xffffffffU
+#define KDUINTPTR_MAX 0xffffffffU
+#define KD_NORETURN
+#define KD_WINDOW_SUPPORTED
+#ifdef KD_NDEBUG
+#define kdAssert(c)
+#else
+#define kdAssert(c) ((void)( (c) ? 0 : (kdHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+#define KD_INFINITY_BITS 0x7f800000u
+#define KD_INFINITY (kdBitsToFloatNV(KD_INFINITY_BITS))
+
+KD_API float KD_APIENTRY kdBitsToFloatNV(KDuint32 x);
+
+
+/** KHR_formatted extension */
+#include <stdarg.h>
+typedef va_list KDVaListKHR;
+
+// If there are problems with including stdarg.h here under any of the Windows
+// operating systems, we might want to change it back to using char* instead of
+// va_list
+//typedef char *KDVaListKHR;
+
+
+#define KD_VA_START_KHR(ap, parmN) \
+ do {ap = (KDVaListKHR)&parmN + sizeof(parmN);} while(0)
+
+#define KD_VA_ARG_CHAR_KHR(ap) (KDchar)va_arg(ap, KDint)
+#define KD_VA_ARG_CHARPTR_KHR(ap) (KDchar*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16_KHR(ap) (KDint16)va_arg(ap, KDint)
+#define KD_VA_ARG_INT32_KHR(ap) va_arg(ap, KDint32)
+#define KD_VA_ARG_INT_KHR(ap) va_arg(ap, KDint)
+#define KD_VA_ARG_INT64_KHR(ap) va_arg(ap, KDint64)
+#define KD_VA_ARG_INTPTR_KHR(ap) (KDint*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16PTR_KHR(ap) (KDint16*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_FLOAT32_KHR(ap) (KDfloat32)(va_arg(ap, double))
+#define KD_VA_ARG_PTR_KHR(ap) (void *)va_arg(ap, char *)
+
+#define KD_VA_END_KHR(ap) \
+ do {ap = (KDVaListKHR)0;} while(0)
+
+#endif /* __kdplatform_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/MinKD.c b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/MinKD.c
new file mode 100644
index 00000000..144aaf34
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/MinKD.c
@@ -0,0 +1,327 @@
+#include "kd.h"
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#ifndef __INTEGRITY
+#include <memory.h>
+#endif
+#include <pthread.h>
+#include <dirent.h>
+
+#ifdef __INTEGRITY
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC 4
+#endif
+#endif
+
+KDFile* kdFopen(const KDchar* pathname, const KDchar* mode)
+{
+ FILE* retval;
+ retval = fopen( pathname, mode );
+ return (KDFile*)retval;
+}
+
+
+KDsize kdFread(void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fread( buffer, size, count, (FILE*)file );
+}
+
+/* kdFwrite: Write to a file. */
+KDsize kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fwrite( buffer, size, count, (FILE*)file );
+}
+
+KDint kdFclose(KDFile *file)
+{
+ return fclose( (FILE*)file );
+}
+
+/* kdCosf: Cosine function. */
+KDfloat32 kdCosf(KDfloat32 x) { return cosf( x ); }
+
+/* kdSinf: Sine function. */
+KDfloat32 kdSinf(KDfloat32 x) { return sinf( x ); }
+
+KDfloat32 kdSqrtf(KDfloat32 x ) { return sqrtf( x ); }
+
+KDfloat32 kdTanf( KDfloat32 x ) { return tanf( x ); }
+
+KDint kdAbs(KDint i)
+{
+ return i < 0 ? -i : i;
+}
+
+
+KDfloat32 kdFabsf(KDfloat32 i) { return fabs( i ); }
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+
+KDint kdStrcpy_s(KDchar* buf, KDsize buflen, const KDchar* src)
+{
+ return kdStrncpy_s(buf, buflen, src, -1);
+}
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KDint kdStrncpy_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srclen)
+{
+ const char* term;
+ if ( srclen == (KDsize)-1)
+ srclen = buflen;
+ term = memchr(src, 0, srclen);
+ if (term)
+ srclen = term - src;
+ if (srclen >= buflen) {
+ if (buflen)
+ *buf = 0;
+ return KD_EINVAL;
+ }
+ memcpy(buf, src, srclen);
+ buf[srclen] = 0;
+ return 0;
+}
+
+/* kdStrncat_s: Concatenate two strings. */
+KDint kdStrncat_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srcmaxlen)
+{
+ size_t origlen = strlen(buf);
+ const char* p = memchr(src, 0, srcmaxlen);
+ if (p)
+ srcmaxlen = p - src;
+ if (origlen + srcmaxlen >= buflen)
+ {
+ /* spec says "buf[0] is set to 0". But that's bad if buflen == 0!
+ * kdStrncpy_s's spec is better here. */
+ if (buflen)
+ buf[0] = 0;
+ return KD_ERANGE;
+ }
+ memcpy(buf + origlen, src, srcmaxlen);
+ buf[origlen + srcmaxlen] = 0;
+ return 0;
+}
+/* kdMemset: Set bytes in memory to a value. */
+void* kdMemset(void *buf, KDint byte, KDsize len) { return memset( buf, byte, len ); }
+
+/* kdStrcmp: Compares two strings. */
+KDint kdStrcmp(const KDchar *str1, const KDchar *str2) { return strcmp( str1, str2); }
+
+/* kdStrlen: Determine the length of a string. */
+KDsize kdStrlen(const KDchar *str) { return strlen( str ); }
+
+void* kdMalloc( KDsize size ) { return malloc(size); }
+
+void kdFree( void* ptr ) { free( ptr ); }
+
+void* kdMemcpy(void *buf, const void *src, KDsize len) { return memcpy( buf, src, len ); }
+
+struct KDThreadMutex
+{
+ pthread_mutex_t p_mutex;
+};
+
+/* kdThreadMutexCreate: Create a mutex. */
+KD_API KDThreadMutex* kdThreadMutexCreate(const void *mutexattr)
+{
+ KDThreadMutex* mutex = malloc(sizeof(KDThreadMutex));
+ if (mutex)
+ {
+ if (pthread_mutex_init(&mutex->p_mutex, NULL) == 0)
+ {
+ return mutex;
+ }
+ free(mutex);
+ }
+
+ return KD_NULL;
+}
+
+/* kdThreadMutexFree: Free a mutex. */
+KDint kdThreadMutexFree(KDThreadMutex *mutex)
+{
+ int res;
+ res = pthread_mutex_destroy(&mutex->p_mutex);
+ // If the mutex destroy failed, don't free the memory.
+ // Per OpenKODE spec, this is undefined behaviour, and
+ // we can leak the memory. The reason for this is that
+ // later allocations may fail if they happen to go
+ // to the same memory
+ if (!res)
+ free(mutex);
+ return 0;
+}
+
+/* kdThreadMutexLock: Lock a mutex. */
+KDint kdThreadMutexLock(KDThreadMutex *mutex)
+{
+ (void)pthread_mutex_lock(&mutex->p_mutex);
+ return 0;
+}
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KDint kdThreadMutexUnlock(KDThreadMutex *mutex)
+{
+ pthread_mutex_unlock(&mutex->p_mutex);
+ return 0;
+}
+
+struct KDThreadAttr
+{
+ pthread_attr_t p_attr;
+};
+
+struct KDThread
+{
+ pthread_t Handle;
+ uint8_t Detached;
+ uint8_t IsRunning;
+ uint8_t UserThread;
+ void* (*UserThreadProc)(void*);
+ void* UserArg;
+};
+/* kdThreadCreate: Create a new thread. */
+KDThread * kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg)
+{
+ pthread_t thread;
+ int retval;
+ const pthread_attr_t* p_attr;
+ KDThread* newThread;
+ if ( attr )
+ p_attr = &attr->p_attr;
+ else
+ p_attr = KD_NULL;
+
+ retval = pthread_create( &thread, p_attr, start_routine, arg );
+ if ( retval != 0 )
+ {
+ return KD_NULL;
+ }
+ newThread = (KDThread*)malloc( sizeof( KDThread ) );
+ if ( newThread == KD_NULL ) return KD_NULL;
+ newThread->Handle = thread;
+ newThread->Detached = 0;
+ newThread->IsRunning = 1;
+ newThread->UserThread = 1;
+ newThread->UserThreadProc = start_routine;
+ newThread->UserArg = arg;
+ return newThread;
+}
+
+/* kdThreadExit: Terminate this thread. */
+void kdThreadExit(void *retval)
+{
+ pthread_exit( retval );
+}
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KDint kdThreadJoin(KDThread *thread, void **retval)
+{
+ int join_retval;
+ join_retval = pthread_join( thread->Handle, retval );
+ if ( join_retval == 0 ) free( thread );
+ return join_retval;
+}
+
+typedef struct KDDirInternal {
+ DIR *dir;
+ KDDirent ent;
+} KDDirInternal;
+
+/* kdOpenDir: Open a directory ready for listing. */
+KDDir *kdOpenDir(const KDchar *pathname)
+{
+ KDDirInternal* retval;
+ DIR* dir = opendir( pathname );
+ if ( dir == KD_NULL ) return KD_NULL;
+ retval = (KDDirInternal*)malloc( sizeof( KDDirInternal ));
+ if ( retval == KD_NULL ) return KD_NULL;
+ memset( retval, 0, sizeof( *retval ) );
+ retval->dir = dir;
+ return (KDDir*)retval;
+}
+
+/* kdReadDir: Return the next file in a directory. */
+KDDirent* kdReadDir(KDDir *dir)
+{
+ struct dirent *sysDirEnt;
+ KDDirent *dirent = NULL;
+
+ sysDirEnt = readdir(((KDDirInternal *)dir)->dir);
+
+ if (sysDirEnt) {
+ dirent = &((KDDirInternal *)dir)->ent;
+ dirent->d_name = sysDirEnt->d_name;
+ }
+ return dirent;
+}
+
+/* kdCloseDir: Close a directory. */
+KDint kdCloseDir(KDDir *dir)
+{
+ closedir(((KDDirInternal *)dir)->dir);
+ free(dir);
+ return 0;
+}
+
+KDint kdSetWindowPropertyiv(KDWindow * win, KDint prop, const KDint32 * val)
+{
+ return 0;
+}
+
+void kdDefaultEvent(const KDEvent *event )
+{
+
+}
+
+typedef long long NvS64;
+
+KDust kdGetTimeUST(void)
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+
+ return (NvS64)tp.tv_sec * (NvS64)1000000000 +
+ (NvS64)tp.tv_nsec;
+}
+
+static KDTm* gmlocaltime(
+ const KDtime *timep,
+ KDTm *result,
+ struct tm* (* func)(const time_t* timep, struct tm* result))
+{
+ struct tm tm;
+ time_t t = *timep;
+ (*func)(&t, &tm);
+ result->tm_sec = tm.tm_sec;
+ result->tm_min = tm.tm_min;
+ result->tm_hour = tm.tm_hour;
+ result->tm_mday = tm.tm_mday;
+ result->tm_mon = tm.tm_mon;
+ result->tm_year = tm.tm_year;
+ result->tm_wday = tm.tm_wday;
+ result->tm_yday = tm.tm_yday;
+ return result;
+}
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+KDTm* kdGmtime_r(const KDtime* timep, KDTm* result)
+{
+ return gmlocaltime(timep, result, &gmtime_r);
+}
+
+KDTm* kdLocaltime_r(const KDtime* timep, KDTm* result)
+{
+ return gmlocaltime(timep, result, &localtime_r);
+}
+
+//===========================================================================
+// kdCreateEvent: Create an event for posting.
+//===========================================================================
+KDEvent* kdCreateEvent(void)
+{
+ //Memory leak and there isn't much I am going to do about this now
+ KDEvent* newEvent = (KDEvent*)malloc( sizeof( KDEvent ));
+ memset( newEvent, 0, sizeof( KDEvent ));
+ return newEvent;
+}
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_extwindowprops.h b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_extwindowprops.h
new file mode 100644
index 00000000..4428a568
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_extwindowprops.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_extwindowprops_h_
+#define __kd_QT3DS_extwindowprops_h_
+#include <KD/kd.h>
+#include <EGL/eglext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_WINDOWPROPERTY_FULLSCREEN: Control over resizing a window to fill the complete screen */
+
+// KDboolean - set the window to fullscreen mode
+#define KD_WINDOWPROPERTY_FULLSCREEN_QT3DS 9999
+
+// KDint - set which KD_DISPLAY_* display that the window should be opened on
+#define KD_WINDOWPROPERTY_DISPLAY_QT3DS 9998
+
+// KDboolean - sets whether overlay should be used to create window
+#define KD_WINDOWPROPERTY_OVERLAY_QT3DS 9997
+
+#define KD_DISPLAY_PRIMARY_QT3DS 0
+#define KD_DISPLAY_INTERNAL0_QT3DS 0
+#define KD_DISPLAY_INTERNAL1_QT3DS 1
+#define KD_DISPLAY_INTERNAL2_QT3DS 2
+#define KD_DISPLAY_INTERNAL3_QT3DS 3
+#define KD_DISPLAY_EXTERNAL0_QT3DS 1000
+#define KD_DISPLAY_EXTERNAL1_QT3DS 1001
+#define KD_DISPLAY_EXTERNAL2_QT3DS 1002
+#define KD_DISPLAY_EXTERNAL3_QT3DS 1003
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_extwindowprops_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_multitouch.h b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_multitouch.h
new file mode 100644
index 00000000..e230b029
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/Qt3DS_multitouch.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_multitouch_h_
+#define __kd_QT3DS_multitouch_h_
+#include <KD/kd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_IOGROUP_MULTITOUCH: I/O group for Multitouch input devices. */
+#define KD_IOGROUP_MULTITOUCH_QT3DS 0x40004000
+#define KD_STATE_MULTITOUCH_AVAILABILITY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 0)
+#define KD_INPUT_MULTITOUCH_FINGERS_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 1)
+#define KD_INPUT_MULTITOUCH_WIDTH_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 2)
+#define KD_INPUT_MULTITOUCH_X_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 3)
+#define KD_INPUT_MULTITOUCH_Y_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 4)
+#define KD_INPUT_MULTITOUCH_X2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 5)
+#define KD_INPUT_MULTITOUCH_Y2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 6)
+#define KD_INPUT_MULTITOUCH_PRESSURE_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 7)
+#define KD_INPUT_MULTITOUCH_GESTURES_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 8)
+#define KD_INPUT_MULTITOUCH_RELX_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 9)
+#define KD_INPUT_MULTITOUCH_RELY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 10)
+
+/* KD_EVENT_INPUT_MULTITOUCH_QT3DS: Multitouch event. */
+#define KD_EVENT_INPUT_MULTITOUCH_QT3DS 1001
+typedef struct KDEventInputMultitouchDataNV
+{
+ KDint32 index;
+ KDint8 fingers;
+ KDint8 width;
+ KDint16 x;
+ KDint16 y;
+ KDint16 x2;
+ KDint16 y2;
+ KDint16 pressure;
+} KDEventInputMultitouchDataNV;
+
+/* KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS: Multitouch gesture event. */
+#define KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS 1002
+
+/* kdGetEventInputMultitouchDataNV: Get auxiliary event data for multitouch input. */
+KD_API KDint KD_APIENTRY kdGetEventInputMultitouchDataNV(const KDEvent *event,
+ KDEventInputMultitouchDataNV *data);
+
+/* kdSetEventInputMultitouchActiveNV: Activate Multitouch input events */
+KD_API KDint KD_APIENTRY kdSetEventInputMultitouchActiveNV(KDboolean activate);
+
+/* kdEnableEventInputMultitouchMergeNV: Activate merging of Multitouch input events */
+KD_API void KD_APIENTRY kdEnableEventInputMultitouchMergeNV(KDboolean enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_multitouch_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kd.h b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kd.h
new file mode 100644
index 00000000..f7ccea03
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kd.h
@@ -0,0 +1,991 @@
+/* Reference KD/kd.h for OpenKODE Core 1.0.3 */
+#ifndef __kd_h_
+#define __kd_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kdplatform.h"
+
+
+
+/*******************************************************
+ * Introduction
+ *******************************************************/
+
+/*******************************************************
+ * OpenKODE conformance
+ *******************************************************/
+
+/*******************************************************
+ * Overview
+ *******************************************************/
+
+/*******************************************************
+ * Programming environment
+ *******************************************************/
+#define KD_VERSION_1_0 1
+typedef char KDchar;
+typedef signed char KDint8;
+typedef unsigned char KDuint8;
+typedef int KDint;
+typedef unsigned int KDuint;
+typedef float KDfloat32;
+typedef KDint KDboolean;
+typedef KDint64 KDtime;
+typedef KDint64 KDust;
+typedef KDint64 KDoff;
+typedef KDuint32 KDmode;
+#define KDINT32_MIN (-0x7fffffff-1)
+#define KDINT32_MAX 0x7fffffff
+#define KDUINT32_MAX 0xffffffffU
+#define KD_TRUE 1
+#define KD_FALSE 0
+#ifdef __cplusplus
+ const int KD_NULL = 0; /* Yes, int. See Stroustrup 3rd edition. */
+#else
+ #define KD_NULL ((void *)0)
+#endif
+
+/*******************************************************
+ * Errors
+ *******************************************************/
+#define KD_EACCES 1
+#define KD_EADDRINUSE 2
+#define KD_EADDRNOTAVAIL 3
+#define KD_EAFNOSUPPORT 4
+#define KD_EAGAIN (5)
+#define KD_EALREADY 6
+#define KD_EBADF 7
+#define KD_EBUSY 8
+#define KD_ECONNREFUSED 9
+#define KD_ECONNRESET 10
+#define KD_EDEADLK 11
+#define KD_EDESTADDRREQ 12
+#define KD_EEXIST 13
+#define KD_EFBIG 14
+#define KD_EHOSTUNREACH 15
+#define KD_EHOST_NOT_FOUND 16
+#define KD_EINVAL 17
+#define KD_EIO 18
+#define KD_EILSEQ 19
+#define KD_EISCONN 20
+#define KD_EISDIR 21
+#define KD_EMFILE 22
+#define KD_ENAMETOOLONG 23
+#define KD_ENOENT 24
+#define KD_ENOMEM 25
+#define KD_ENOSPC 26
+#define KD_ENOSYS 27
+#define KD_ENOTCONN 28
+#define KD_ENO_DATA 29
+#define KD_ENO_RECOVERY 30
+#define KD_EOPNOTSUPP 31
+#define KD_EOVERFLOW 32
+#define KD_EPERM 33
+#define KD_ERANGE 35
+#define KD_ETIMEDOUT (36)
+#define KD_ETRY_AGAIN 37
+
+/* kdGetError: Get last error indication. */
+KD_API KDint KD_APIENTRY kdGetError(void);
+
+/* kdSetError: Set last error indication. */
+KD_API void KD_APIENTRY kdSetError(KDint error);
+
+/*******************************************************
+ * Versioning and attribute queries
+ *******************************************************/
+
+/* kdQueryAttribi: Obtain the value of a numeric OpenKODE Core attribute. */
+KD_API KDint KD_APIENTRY kdQueryAttribi(KDint attribute, KDint *value);
+
+/* kdQueryAttribcv: Obtain the value of a string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryAttribcv(KDint attribute);
+#define KD_ATTRIB_VENDOR 39
+#define KD_ATTRIB_VERSION 40
+#define KD_ATTRIB_PLATFORM 41
+
+/* kdQueryIndexedAttribcv: Obtain the value of an indexed string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryIndexedAttribcv(KDint attribute, KDint index);
+
+/*******************************************************
+ * Threads and synchronization
+ *******************************************************/
+
+/* kdThreadAttrCreate: Create a thread attribute object. */
+typedef struct KDThreadAttr KDThreadAttr;
+KD_API KDThreadAttr *KD_APIENTRY kdThreadAttrCreate(void);
+
+/* kdThreadAttrFree: Free a thread attribute object. */
+KD_API KDint KD_APIENTRY kdThreadAttrFree(KDThreadAttr *attr);
+
+/* kdThreadAttrSetDetachState: Set detachstate attribute. */
+#define KD_THREAD_CREATE_JOINABLE 0
+#define KD_THREAD_CREATE_DETACHED 1
+KD_API KDint KD_APIENTRY kdThreadAttrSetDetachState(KDThreadAttr *attr, KDint detachstate);
+
+/* kdThreadAttrSetStackSize: Set stacksize attribute. */
+KD_API KDint KD_APIENTRY kdThreadAttrSetStackSize(KDThreadAttr *attr, KDsize stacksize);
+
+/* kdThreadCreate: Create a new thread. */
+typedef struct KDThread KDThread;
+KD_API KDThread *KD_APIENTRY kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg);
+
+/* kdThreadExit: Terminate this thread. */
+KD_API KD_NORETURN void KD_APIENTRY kdThreadExit(void *retval);
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KD_API KDint KD_APIENTRY kdThreadJoin(KDThread *thread, void **retval);
+
+/* kdThreadDetach: Allow resources to be freed as soon as a thread terminates. */
+KD_API KDint KD_APIENTRY kdThreadDetach(KDThread *thread);
+
+/* kdThreadSelf: Return calling thread&#8217;s ID. */
+KD_API KDThread *KD_APIENTRY kdThreadSelf(void);
+
+/* kdThreadOnce: Wrap initialization code so it is executed only once. */
+#ifndef KD_NO_STATIC_DATA
+typedef struct KDThreadOnce {
+ void *impl;
+} KDThreadOnce;
+#define KD_THREAD_ONCE_INIT { 0 }
+KD_API KDint KD_APIENTRY kdThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void));
+#endif /* ndef KD_NO_STATIC_DATA */
+
+/* kdThreadMutexCreate: Create a mutex. */
+typedef struct KDThreadMutex KDThreadMutex;
+KD_API KDThreadMutex *KD_APIENTRY kdThreadMutexCreate(const void *mutexattr);
+
+/* kdThreadMutexFree: Free a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexFree(KDThreadMutex *mutex);
+
+/* kdThreadMutexLock: Lock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexLock(KDThreadMutex *mutex);
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexUnlock(KDThreadMutex *mutex);
+
+/* kdThreadCondCreate: Create a condition variable. */
+typedef struct KDThreadCond KDThreadCond;
+KD_API KDThreadCond *KD_APIENTRY kdThreadCondCreate(const void *attr);
+
+/* kdThreadCondFree: Free a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondFree(KDThreadCond *cond);
+
+/* kdThreadCondSignal, kdThreadCondBroadcast: Signal a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondSignal(KDThreadCond *cond);
+KD_API KDint KD_APIENTRY kdThreadCondBroadcast(KDThreadCond *cond);
+
+/* kdThreadCondWait: Wait for a condition variable to be signalled. */
+KD_API KDint KD_APIENTRY kdThreadCondWait(KDThreadCond *cond, KDThreadMutex *mutex);
+
+/* kdThreadSemCreate: Create a semaphore. */
+typedef struct KDThreadSem KDThreadSem;
+KD_API KDThreadSem *KD_APIENTRY kdThreadSemCreate(KDuint value);
+
+/* kdThreadSemFree: Free a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemFree(KDThreadSem *sem);
+
+/* kdThreadSemWait: Lock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemWait(KDThreadSem *sem);
+
+/* kdThreadSemPost: Unlock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemPost(KDThreadSem *sem);
+
+/*******************************************************
+ * Events
+ *******************************************************/
+
+/* KDEvent: Struct type containing an event. */
+typedef struct KDEvent KDEvent;
+#define KD_EVENT_USER 0x40000000
+
+/* kdWaitEvent: Get next event from thread&#8217;s event queue. */
+KD_API const KDEvent *KD_APIENTRY kdWaitEvent(KDust timeout);
+
+/* kdSetEventUserptr: Set the userptr for global events. */
+KD_API void KD_APIENTRY kdSetEventUserptr(void *userptr);
+
+/* kdDefaultEvent: Perform default processing on an unrecognized event. */
+KD_API void KD_APIENTRY kdDefaultEvent(const KDEvent *event);
+
+/* kdPumpEvents: Pump the thread&#8217;s event queue, performing callbacks. */
+KD_API KDint KD_APIENTRY kdPumpEvents(void);
+
+/* kdInstallCallback: Install or remove a callback function for event processing. */
+typedef void (KD_APIENTRY KDCallbackFunc)(const KDEvent *event);
+KD_API KDint KD_APIENTRY kdInstallCallback(KDCallbackFunc *func, KDint eventtype, void *eventuserptr);
+
+/* kdCreateEvent: Create an event for posting. */
+KD_API KDEvent *KD_APIENTRY kdCreateEvent(void);
+
+/* kdPostEvent, kdPostThreadEvent: Post an event into a queue. */
+KD_API KDint KD_APIENTRY kdPostEvent(KDEvent *event);
+KD_API KDint KD_APIENTRY kdPostThreadEvent(KDEvent *event, KDThread *thread);
+typedef struct KDEventUser {
+ union {
+ KDint64 i64;
+ void *p;
+ struct {
+ KDint32 a;
+ KDint32 b;
+ } i32pair;
+ } value1;
+ union {
+ KDint64 i64;
+ struct {
+ union {
+ KDint32 i32;
+ void *p;
+ } value2;
+ union {
+ KDint32 i32;
+ void *p;
+ } value3;
+ } i32orp;
+ } value23;
+} KDEventUser;
+
+/* kdFreeEvent: Abandon an event instead of posting it. */
+KD_API void KD_APIENTRY kdFreeEvent(KDEvent *event);
+
+/*******************************************************
+ * System events
+ *******************************************************/
+
+/* KD_EVENT_QUIT: Event to request to quit application. */
+#define KD_EVENT_QUIT 43
+
+/* KD_EVENT_PAUSE: Application pause event. */
+#define KD_EVENT_PAUSE 45
+
+/* KD_EVENT_RESUME: Application resume event. */
+#define KD_EVENT_RESUME 46
+
+/* KD_EVENT_ORIENTATION: Orientation change event. */
+#define KD_EVENT_ORIENTATION 48
+
+/* KD_IOGROUP_EVENT: I/O group for OpenKODE Core system events implemented as state values. */
+#define KD_IOGROUP_EVENT 0x100
+#define KD_STATE_EVENT_USING_BATTERY (KD_IOGROUP_EVENT + 0)
+#define KD_STATE_EVENT_LOW_BATTERY (KD_IOGROUP_EVENT + 1)
+
+
+/* KD_IOGROUP_ORIENTATION: I/O group for OpenKODE Core orientation state. */
+#define KD_IOGROUP_ORIENTATION 0x200
+#define KD_STATE_ORIENTATION_OVERALL (KD_IOGROUP_ORIENTATION + 0)
+#define KD_STATE_ORIENTATION_SCREEN (KD_IOGROUP_ORIENTATION + 1)
+#define KD_STATE_ORIENTATION_RENDERING (KD_IOGROUP_ORIENTATION + 2)
+#define KD_STATE_ORIENTATION_LOCKSURFACE (KD_IOGROUP_ORIENTATION + 3)
+
+
+/*******************************************************
+ * Application startup and exit.
+ *******************************************************/
+
+/* kdMain: The application-defined main function. */
+KDint KD_APIENTRY kdMain(KDint argc, const KDchar *const *argv);
+
+/* kdExit: Exit the application. */
+KD_API KD_NORETURN void KD_APIENTRY kdExit(KDint status);
+
+/*******************************************************
+ * Utility library functions
+ *******************************************************/
+
+/* kdAbs: Compute the absolute value of an integer. */
+KD_API KDint KD_APIENTRY kdAbs(KDint i);
+
+/* kdStrtof: Convert a string to a floating point number. */
+KD_API KDfloat32 KD_APIENTRY kdStrtof(const KDchar *s, KDchar **endptr);
+
+/* kdStrtol, kdStrtoul: Convert a string to an integer. */
+KD_API KDint KD_APIENTRY kdStrtol(const KDchar *s, KDchar **endptr, KDint base);
+KD_API KDuint KD_APIENTRY kdStrtoul(const KDchar *s, KDchar **endptr, KDint base);
+
+/* kdLtostr, kdUltostr: Convert an integer to a string. */
+#define KD_LTOSTR_MAXLEN ((sizeof(KDint)*8*3+6)/10+2)
+#define KD_ULTOSTR_MAXLEN ((sizeof(KDint)*8+2)/3+1)
+KD_API KDssize KD_APIENTRY kdLtostr(KDchar *buffer, KDsize buflen, KDint number);
+KD_API KDssize KD_APIENTRY kdUltostr(KDchar *buffer, KDsize buflen, KDuint number, KDint base);
+
+/* kdFtostr: Convert a float to a string. */
+#define KD_FTOSTR_MAXLEN 16
+KD_API KDssize KD_APIENTRY kdFtostr(KDchar *buffer, KDsize buflen, KDfloat32 number);
+
+/* kdCryptoRandom: Return random data. */
+KD_API KDint KD_APIENTRY kdCryptoRandom(KDuint8 *buf, KDsize buflen);
+
+/*******************************************************
+ * Locale specific functions
+ *******************************************************/
+
+/* kdGetLocale: Determine the current language and locale. */
+KD_API const KDchar *KD_APIENTRY kdGetLocale(void);
+
+/*******************************************************
+ * Memory allocation
+ *******************************************************/
+
+/* kdMalloc: Allocate memory. */
+KD_API void *KD_APIENTRY kdMalloc(KDsize size);
+
+/* kdFree: Free allocated memory block. */
+KD_API void KD_APIENTRY kdFree(void *ptr);
+
+/* kdRealloc: Resize memory block. */
+KD_API void *KD_APIENTRY kdRealloc(void *ptr, KDsize size);
+
+/*******************************************************
+ * Thread-local storage.
+ *******************************************************/
+
+/* kdGetTLS: Get the thread-local storage pointer. */
+KD_API void *KD_APIENTRY kdGetTLS(void);
+
+/* kdSetTLS: Set the thread-local storage pointer. */
+KD_API void KD_APIENTRY kdSetTLS(void *ptr);
+
+/*******************************************************
+ * Mathematical functions
+ *******************************************************/
+#define KD_E_F 2.71828175F
+#define KD_PI_F 3.14159274F
+#define KD_PI_2_F 1.57079637F
+#define KD_2PI_F 6.28318548F
+#define KD_LOG2E_F 1.44269502F
+#define KD_LOG10E_F 0.434294492F
+#define KD_LN2_F 0.693147182F
+#define KD_LN10_F 2.30258512F
+#define KD_PI_4_F 0.785398185F
+#define KD_1_PI_F 0.318309873F
+#define KD_2_PI_F 0.636619747F
+#define KD_2_SQRTPI_F 1.12837923F
+#define KD_SQRT2_F 1.41421354F
+#define KD_SQRT1_2_F 0.707106769F
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_FLT_MAX 3.40282346638528860e+38F
+#define KD_FLT_MIN 1.17549435e-38F
+/* KD_INFINITY is defined in kdplatform.h since no portable definition
+ * is possible. */
+#define kdIsNan(x) (((x) != (x)) ? 1 : 0)
+#define KD_HUGE_VALF KD_INFINITY
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+/* kdAcosf: Arc cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdAcosf(KDfloat32 x);
+
+/* kdAsinf: Arc sine function. */
+KD_API KDfloat32 KD_APIENTRY kdAsinf(KDfloat32 x);
+
+/* kdAtanf: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtanf(KDfloat32 x);
+
+/* kdAtan2f: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtan2f(KDfloat32 y, KDfloat32 x);
+
+/* kdCosf: Cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdCosf(KDfloat32 x);
+
+/* kdSinf: Sine function. */
+KD_API KDfloat32 KD_APIENTRY kdSinf(KDfloat32 x);
+
+/* kdTanf: Tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdTanf(KDfloat32 x);
+
+/* kdExpf: Exponential function. */
+KD_API KDfloat32 KD_APIENTRY kdExpf(KDfloat32 x);
+
+/* kdLogf: Natural logarithm function. */
+KD_API KDfloat32 KD_APIENTRY kdLogf(KDfloat32 x);
+
+/* kdFabsf: Absolute value. */
+KD_API KDfloat32 KD_APIENTRY kdFabsf(KDfloat32 x);
+
+/* kdPowf: Power function. */
+KD_API KDfloat32 KD_APIENTRY kdPowf(KDfloat32 x, KDfloat32 y);
+
+/* kdSqrtf: Square root function. */
+KD_API KDfloat32 KD_APIENTRY kdSqrtf(KDfloat32 x);
+
+/* kdCeilf: Return ceiling value. */
+KD_API KDfloat32 KD_APIENTRY kdCeilf(KDfloat32 x);
+
+/* kdFloorf: Return floor value. */
+KD_API KDfloat32 KD_APIENTRY kdFloorf(KDfloat32 x);
+
+/* kdRoundf: Round value to nearest integer. */
+KD_API KDfloat32 KD_APIENTRY kdRoundf(KDfloat32 x);
+
+/* kdInvsqrtf: Inverse square root function. */
+KD_API KDfloat32 KD_APIENTRY kdInvsqrtf(KDfloat32 x);
+
+/* kdFmodf: Calculate floating point remainder. */
+KD_API KDfloat32 KD_APIENTRY kdFmodf(KDfloat32 x, KDfloat32 y);
+
+/*******************************************************
+ * String and memory functions
+ *******************************************************/
+
+/* kdMemchr: Scan memory for a byte value. */
+KD_API void *KD_APIENTRY kdMemchr(const void *src, KDint byte, KDsize len);
+
+/* kdMemcmp: Compare two memory regions. */
+KD_API KDint KD_APIENTRY kdMemcmp(const void *src1, const void *src2, KDsize len);
+
+/* kdMemcpy: Copy a memory region, no overlapping. */
+KD_API void *KD_APIENTRY kdMemcpy(void *buf, const void *src, KDsize len);
+
+/* kdMemmove: Copy a memory region, overlapping allowed. */
+KD_API void *KD_APIENTRY kdMemmove(void *buf, const void *src, KDsize len);
+
+/* kdMemset: Set bytes in memory to a value. */
+KD_API void *KD_APIENTRY kdMemset(void *buf, KDint byte, KDsize len);
+
+/* kdStrchr: Scan string for a byte value. */
+KD_API KDchar *KD_APIENTRY kdStrchr(const KDchar *str, KDint ch);
+
+/* kdStrcmp: Compares two strings. */
+KD_API KDint KD_APIENTRY kdStrcmp(const KDchar *str1, const KDchar *str2);
+
+/* kdStrlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrlen(const KDchar *str);
+
+/* kdStrnlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrnlen(const KDchar *str, KDsize maxlen);
+
+/* kdStrncat_s: Concatenate two strings. */
+KD_API KDint KD_APIENTRY kdStrncat_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srcmaxlen);
+
+/* kdStrncmp: Compares two strings with length limit. */
+KD_API KDint KD_APIENTRY kdStrncmp(const KDchar *str1, const KDchar *str2, KDsize maxlen);
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrcpy_s(KDchar *buf, KDsize buflen, const KDchar *src);
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrncpy_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srclen);
+
+/*******************************************************
+ * Time functions
+ *******************************************************/
+
+/* kdGetTimeUST: Get the current unadjusted system time. */
+KD_API KDust KD_APIENTRY kdGetTimeUST(void);
+
+/* kdTime: Get the current wall clock time. */
+KD_API KDtime KD_APIENTRY kdTime(KDtime *timep);
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+typedef struct KDTm {
+ KDint32 tm_sec;
+ KDint32 tm_min;
+ KDint32 tm_hour;
+ KDint32 tm_mday;
+ KDint32 tm_mon;
+ KDint32 tm_year;
+ KDint32 tm_wday;
+ KDint32 tm_yday;
+} KDTm;
+KD_API KDTm *KD_APIENTRY kdGmtime_r(const KDtime *timep, KDTm *result);
+KD_API KDTm *KD_APIENTRY kdLocaltime_r(const KDtime *timep, KDTm *result);
+
+/* kdUSTAtEpoch: Get the UST corresponding to KDtime 0. */
+KD_API KDust KD_APIENTRY kdUSTAtEpoch(void);
+
+/*******************************************************
+ * Timer functions
+ *******************************************************/
+
+/* kdSetTimer: Set timer. */
+#define KD_TIMER_ONESHOT 61
+#define KD_TIMER_PERIODIC_AVERAGE 62
+#define KD_TIMER_PERIODIC_MINIMUM 63
+typedef struct KDTimer KDTimer;
+KD_API KDTimer *KD_APIENTRY kdSetTimer(KDint64 interval, KDint periodic, void *eventuserptr);
+
+/* kdCancelTimer: Cancel and free a timer. */
+KD_API KDint KD_APIENTRY kdCancelTimer(KDTimer *timer);
+
+/* KD_EVENT_TIMER: Timer fire event. */
+#define KD_EVENT_TIMER 42
+
+/*******************************************************
+ * File system
+ *******************************************************/
+#define KD_EOF (-1)
+
+/* kdFopen: Open a file from the file system. */
+typedef struct KDFile KDFile;
+KD_API KDFile *KD_APIENTRY kdFopen(const KDchar *pathname, const KDchar *mode);
+
+/* kdFclose: Close an open file. */
+KD_API KDint KD_APIENTRY kdFclose(KDFile *file);
+
+/* kdFflush: Flush an open file. */
+KD_API KDint KD_APIENTRY kdFflush(KDFile *file);
+
+/* kdFread: Read from a file. */
+KD_API KDsize KD_APIENTRY kdFread(void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdFwrite: Write to a file. */
+KD_API KDsize KD_APIENTRY kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdGetc: Read next byte from an open file. */
+KD_API KDint KD_APIENTRY kdGetc(KDFile *file);
+
+/* kdPutc: Write a byte to an open file. */
+KD_API KDint KD_APIENTRY kdPutc(KDint c, KDFile *file);
+
+/* kdFgets: Read a line of text from an open file. */
+KD_API KDchar *KD_APIENTRY kdFgets(KDchar *buffer, KDsize buflen, KDFile *file);
+
+/* kdFEOF: Check for end of file. */
+KD_API KDint KD_APIENTRY kdFEOF(KDFile *file);
+
+/* kdFerror: Check for an error condition on an open file. */
+KD_API KDint KD_APIENTRY kdFerror(KDFile *file);
+
+/* kdClearerr: Clear a file&#8217;s error and end-of-file indicators. */
+KD_API void KD_APIENTRY kdClearerr(KDFile *file);
+
+/* kdFseek: Reposition the file position indicator in a file. */
+typedef enum {
+ KD_SEEK_SET = 0,
+ KD_SEEK_CUR = 1,
+ KD_SEEK_END = 2
+} KDfileSeekOrigin;
+KD_API KDint KD_APIENTRY kdFseek(KDFile *file, KDoff offset, KDfileSeekOrigin origin);
+
+/* kdFtell: Get the file position of an open file. */
+KD_API KDoff KD_APIENTRY kdFtell(KDFile *file);
+
+/* kdMkdir: Create new directory. */
+KD_API KDint KD_APIENTRY kdMkdir(const KDchar *pathname);
+
+/* kdRmdir: Delete a directory. */
+KD_API KDint KD_APIENTRY kdRmdir(const KDchar *pathname);
+
+/* kdRename: Rename a file. */
+KD_API KDint KD_APIENTRY kdRename(const KDchar *src, const KDchar *dest);
+
+/* kdRemove: Delete a file. */
+KD_API KDint KD_APIENTRY kdRemove(const KDchar *pathname);
+
+/* kdTruncate: Truncate or extend a file. */
+KD_API KDint KD_APIENTRY kdTruncate(const KDchar *pathname, KDoff length);
+
+/* kdStat, kdFstat: Return information about a file. */
+typedef struct KDStat {
+ KDmode st_mode;
+ KDoff st_size;
+ KDtime st_mtime;
+} KDStat;
+KD_API KDint KD_APIENTRY kdStat(const KDchar *pathname, struct KDStat *buf);
+KD_API KDint KD_APIENTRY kdFstat(KDFile *file, struct KDStat *buf);
+#define KD_ISREG(m) ((m) & 0x8000)
+#define KD_ISDIR(m) ((m) & 0x4000)
+
+/* kdAccess: Determine whether the application can access a file or directory. */
+KD_API KDint KD_APIENTRY kdAccess(const KDchar *pathname, KDint amode);
+#define KD_R_OK 4
+#define KD_W_OK 2
+#define KD_X_OK 1
+
+/* kdOpenDir: Open a directory ready for listing. */
+typedef struct KDDir KDDir;
+KD_API KDDir *KD_APIENTRY kdOpenDir(const KDchar *pathname);
+
+/* kdReadDir: Return the next file in a directory. */
+typedef struct KDDirent {
+ const KDchar *d_name;
+} KDDirent;
+KD_API KDDirent *KD_APIENTRY kdReadDir(KDDir *dir);
+
+/* kdCloseDir: Close a directory. */
+KD_API KDint KD_APIENTRY kdCloseDir(KDDir *dir);
+
+/* kdGetFree: Get free space on a drive. */
+KD_API KDoff KD_APIENTRY kdGetFree(const KDchar *pathname);
+
+/*******************************************************
+ * Network sockets
+ *******************************************************/
+
+/* KDSockaddr: Struct type for socket address. */
+typedef struct KDSockaddr {
+ KDuint16 family;
+ union {
+#define KD_AF_INET 70
+ struct {
+ KDuint16 port;
+ KDuint32 address;
+ } sin;
+ } data;
+} KDSockaddr;
+
+/* kdNameLookup: Look up a hostname. */
+KD_API KDint KD_APIENTRY kdNameLookup(KDint af, const KDchar *hostname, void *eventuserptr);
+
+/* kdNameLookupCancel: Selectively cancels ongoing kdNameLookup operations. */
+KD_API void KD_APIENTRY kdNameLookupCancel(void *eventuserptr);
+
+/* kdSocketCreate: Creates a socket. */
+typedef struct KDSocket KDSocket;
+KD_API KDSocket *KD_APIENTRY kdSocketCreate(KDint type, void *eventuserptr);
+#define KD_SOCK_TCP 64
+#define KD_SOCK_UDP 65
+
+/* kdSocketClose: Closes a socket. */
+KD_API KDint KD_APIENTRY kdSocketClose(KDSocket *socket);
+
+/* kdSocketBind: Bind a socket. */
+KD_API KDint KD_APIENTRY kdSocketBind(KDSocket *socket, const struct KDSockaddr *addr, KDboolean reuse);
+#define KD_INADDR_ANY 0
+
+/* kdSocketGetName: Get the local address of a socket. */
+KD_API KDint KD_APIENTRY kdSocketGetName(KDSocket *socket, struct KDSockaddr *addr);
+
+/* kdSocketConnect: Connects a socket. */
+KD_API KDint KD_APIENTRY kdSocketConnect(KDSocket *socket, const KDSockaddr *addr);
+
+/* kdSocketListen: Listen on a socket. */
+KD_API KDint KD_APIENTRY kdSocketListen(KDSocket *socket, KDint backlog);
+
+/* kdSocketAccept: Accept an incoming connection. */
+KD_API KDSocket *KD_APIENTRY kdSocketAccept(KDSocket *socket, KDSockaddr *addr, void *eventuserptr);
+
+/* kdSocketSend, kdSocketSendTo: Send data to a socket. */
+KD_API KDint KD_APIENTRY kdSocketSend(KDSocket *socket, const void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketSendTo(KDSocket *socket, const void *buf, KDint len, const KDSockaddr *addr);
+
+/* kdSocketRecv, kdSocketRecvFrom: Receive data from a socket. */
+KD_API KDint KD_APIENTRY kdSocketRecv(KDSocket *socket, void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketRecvFrom(KDSocket *socket, void *buf, KDint len, KDSockaddr *addr);
+
+/* kdHtonl: Convert a 32-bit integer from host to network byte order. */
+KD_API KDuint32 KD_APIENTRY kdHtonl(KDuint32 hostlong);
+
+/* kdHtons: Convert a 16-bit integer from host to network byte order. */
+KD_API KDuint16 KD_APIENTRY kdHtons(KDuint16 hostshort);
+
+/* kdNtohl: Convert a 32-bit integer from network to host byte order. */
+KD_API KDuint32 KD_APIENTRY kdNtohl(KDuint32 netlong);
+
+/* kdNtohs: Convert a 16-bit integer from network to host byte order. */
+KD_API KDuint16 KD_APIENTRY kdNtohs(KDuint16 netshort);
+
+/* kdInetAton: Convert a &#8220;dotted quad&#8221; format address to an integer. */
+KD_API KDint KD_APIENTRY kdInetAton(const KDchar *cp, KDuint32 *inp);
+
+/* kdInetNtop: Convert a network address to textual form. */
+#define KD_INET_ADDRSTRLEN 16
+typedef struct KDInAddr {
+ KDuint32 s_address; // Renamed this from s_addr as it causes a conflict with winsock2.h
+} KDInAddr;
+KD_API const KDchar *KD_APIENTRY kdInetNtop(KDuint af, const void *src, KDchar *dst, KDsize cnt);
+
+/* KD_EVENT_SOCKET_READABLE: Event to indicate that a socket is readable. */
+#define KD_EVENT_SOCKET_READABLE 49
+typedef struct KDEventSocketReadable {
+ KDSocket *socket;
+} KDEventSocketReadable;
+
+/* KD_EVENT_SOCKET_WRITABLE: Event to indicate that a socket is writable. */
+#define KD_EVENT_SOCKET_WRITABLE 50
+typedef struct KDEventSocketWritable {
+ KDSocket *socket;
+} KDEventSocketWritable;
+
+/* KD_EVENT_SOCKET_CONNECT_COMPLETE: Event generated when a socket connect is complete */
+#define KD_EVENT_SOCKET_CONNECT_COMPLETE 51
+typedef struct KDEventSocketConnect {
+ KDSocket *socket;
+ KDint32 error;
+} KDEventSocketConnect;
+
+/* KD_EVENT_SOCKET_INCOMING: Event generated when a listening socket detects an incoming connection or an error. */
+#define KD_EVENT_SOCKET_INCOMING 52
+typedef struct KDEventSocketIncoming {
+ KDSocket *socket;
+} KDEventSocketIncoming;
+
+/* KD_EVENT_NAME_LOOKUP_COMPLETE: kdNameLookup complete event. */
+#define KD_EVENT_NAME_LOOKUP_COMPLETE 53
+typedef struct KDEventNameLookup {
+ KDint32 error;
+ KDint32 resultlen;
+ const KDSockaddr *result;
+ KDboolean more;
+} KDEventNameLookup;
+
+/*******************************************************
+ * Input/output
+ *******************************************************/
+
+/* KD_EVENT_STATE: State changed event. */
+#define KD_EVENT_STATE 55
+
+typedef struct KDEventState {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventState;
+
+/* KD_EVENT_INPUT: Input changed event. */
+#define KD_EVENT_INPUT 56
+
+typedef struct KDEventInput {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventInput;
+
+/* KD_EVENT_INPUT_JOG: Jogdial jog event. */
+#define KD_EVENT_INPUT_JOG 71
+typedef struct KDEventInputJog {
+ KDint32 index;
+ KDint32 count;
+} KDEventInputJog;
+
+/* KD_EVENT_INPUT_POINTER: Pointer input changed event. */
+#define KD_EVENT_INPUT_POINTER 57
+typedef struct KDEventInputPointer {
+ KDint32 index;
+ KDint32 select;
+ KDint32 x;
+ KDint32 y;
+} KDEventInputPointer;
+
+/* KD_EVENT_INPUT_STICK: Joystick stick changed event. */
+#define KD_EVENT_INPUT_STICK 58
+typedef struct KDEventInputStick {
+ KDint32 index;
+ KDint32 x;
+ KDint32 y;
+ KDint32 z;
+} KDEventInputStick;
+
+/* kdStateGeti, kdStateGetl, kdStateGetf: get state value(s) */
+KD_API KDint KD_APIENTRY kdStateGeti(KDint startidx, KDuint numidxs, KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetl(KDint startidx, KDuint numidxs, KDint64 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetf(KDint startidx, KDuint numidxs, KDfloat32 *buffer);
+
+/* kdOutputSeti, kdOutputSetf: set outputs */
+KD_API KDint KD_APIENTRY kdOutputSeti(KDint startidx, KDuint numidxs, const KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdOutputSetf(KDint startidx, KDuint numidxs, const KDfloat32 *buffer);
+#define KD_IO_CONTROLLER_STRIDE 64
+
+/* KD_IOGROUP_GAMEKEYS: I/O group for game keys. */
+#define KD_IOGROUP_GAMEKEYS 0x1000
+#define KD_STATE_GAMEKEYS_AVAILABILITY (KD_IOGROUP_GAMEKEYS + 0)
+#define KD_INPUT_GAMEKEYS_UP (KD_IOGROUP_GAMEKEYS + 1)
+#define KD_INPUT_GAMEKEYS_LEFT (KD_IOGROUP_GAMEKEYS + 2)
+#define KD_INPUT_GAMEKEYS_RIGHT (KD_IOGROUP_GAMEKEYS + 3)
+#define KD_INPUT_GAMEKEYS_DOWN (KD_IOGROUP_GAMEKEYS + 4)
+#define KD_INPUT_GAMEKEYS_FIRE (KD_IOGROUP_GAMEKEYS + 5)
+#define KD_INPUT_GAMEKEYS_A (KD_IOGROUP_GAMEKEYS + 6)
+#define KD_INPUT_GAMEKEYS_B (KD_IOGROUP_GAMEKEYS + 7)
+#define KD_INPUT_GAMEKEYS_C (KD_IOGROUP_GAMEKEYS + 8)
+#define KD_INPUT_GAMEKEYS_D (KD_IOGROUP_GAMEKEYS + 9)
+
+/* KD_IOGROUP_GAMEKEYSNC: I/O group for game keys, no chording. */
+#define KD_IOGROUP_GAMEKEYSNC 0x1100
+#define KD_STATE_GAMEKEYSNC_AVAILABILITY (KD_IOGROUP_GAMEKEYSNC + 0)
+#define KD_INPUT_GAMEKEYSNC_UP (KD_IOGROUP_GAMEKEYSNC + 1)
+#define KD_INPUT_GAMEKEYSNC_LEFT (KD_IOGROUP_GAMEKEYSNC + 2)
+#define KD_INPUT_GAMEKEYSNC_RIGHT (KD_IOGROUP_GAMEKEYSNC + 3)
+#define KD_INPUT_GAMEKEYSNC_DOWN (KD_IOGROUP_GAMEKEYSNC + 4)
+#define KD_INPUT_GAMEKEYSNC_FIRE (KD_IOGROUP_GAMEKEYSNC + 5)
+#define KD_INPUT_GAMEKEYSNC_A (KD_IOGROUP_GAMEKEYSNC + 6)
+#define KD_INPUT_GAMEKEYSNC_B (KD_IOGROUP_GAMEKEYSNC + 7)
+#define KD_INPUT_GAMEKEYSNC_C (KD_IOGROUP_GAMEKEYSNC + 8)
+#define KD_INPUT_GAMEKEYSNC_D (KD_IOGROUP_GAMEKEYSNC + 9)
+
+/* KD_IOGROUP_PHONEKEYPAD: I/O group for phone keypad. */
+#define KD_IOGROUP_PHONEKEYPAD 0x2000
+#define KD_STATE_PHONEKEYPAD_AVAILABILITY (KD_IOGROUP_PHONEKEYPAD + 0)
+#define KD_INPUT_PHONEKEYPAD_0 (KD_IOGROUP_PHONEKEYPAD + 1)
+#define KD_INPUT_PHONEKEYPAD_1 (KD_IOGROUP_PHONEKEYPAD + 2)
+#define KD_INPUT_PHONEKEYPAD_2 (KD_IOGROUP_PHONEKEYPAD + 3)
+#define KD_INPUT_PHONEKEYPAD_3 (KD_IOGROUP_PHONEKEYPAD + 4)
+#define KD_INPUT_PHONEKEYPAD_4 (KD_IOGROUP_PHONEKEYPAD + 5)
+#define KD_INPUT_PHONEKEYPAD_5 (KD_IOGROUP_PHONEKEYPAD + 6)
+#define KD_INPUT_PHONEKEYPAD_6 (KD_IOGROUP_PHONEKEYPAD + 7)
+#define KD_INPUT_PHONEKEYPAD_7 (KD_IOGROUP_PHONEKEYPAD + 8)
+#define KD_INPUT_PHONEKEYPAD_8 (KD_IOGROUP_PHONEKEYPAD + 9)
+#define KD_INPUT_PHONEKEYPAD_9 (KD_IOGROUP_PHONEKEYPAD + 10)
+#define KD_INPUT_PHONEKEYPAD_STAR (KD_IOGROUP_PHONEKEYPAD + 11)
+#define KD_INPUT_PHONEKEYPAD_HASH (KD_IOGROUP_PHONEKEYPAD + 12)
+#define KD_INPUT_PHONEKEYPAD_LEFTSOFT (KD_IOGROUP_PHONEKEYPAD + 13)
+#define KD_INPUT_PHONEKEYPAD_RIGHTSOFT (KD_IOGROUP_PHONEKEYPAD + 14)
+#define KD_STATE_PHONEKEYPAD_ORIENTATION (KD_IOGROUP_PHONEKEYPAD + 15)
+
+/* KD_IOGROUP_VIBRATE: I/O group for vibrate. */
+#define KD_IOGROUP_VIBRATE 0x3000
+#define KD_STATE_VIBRATE_AVAILABILITY (KD_IOGROUP_VIBRATE + 0)
+#define KD_STATE_VIBRATE_MINFREQUENCY (KD_IOGROUP_VIBRATE + 1)
+#define KD_STATE_VIBRATE_MAXFREQUENCY (KD_IOGROUP_VIBRATE + 2)
+#define KD_OUTPUT_VIBRATE_VOLUME (KD_IOGROUP_VIBRATE + 3)
+#define KD_OUTPUT_VIBRATE_FREQUENCY (KD_IOGROUP_VIBRATE + 4)
+
+/* KD_IOGROUP_POINTER: I/O group for pointer. */
+#define KD_IOGROUP_POINTER 0x4000
+#define KD_STATE_POINTER_AVAILABILITY (KD_IOGROUP_POINTER + 0)
+#define KD_INPUT_POINTER_X (KD_IOGROUP_POINTER + 1)
+#define KD_INPUT_POINTER_Y (KD_IOGROUP_POINTER + 2)
+#define KD_INPUT_POINTER_SELECT (KD_IOGROUP_POINTER + 3)
+
+/* KD_IOGROUP_BACKLIGHT: I/O group for backlight. */
+#define KD_IOGROUP_BACKLIGHT 0x5000
+#define KD_STATE_BACKLIGHT_AVAILABILITY (KD_IOGROUP_BACKLIGHT + 0)
+#define KD_OUTPUT_BACKLIGHT_FORCE (KD_IOGROUP_BACKLIGHT + 1)
+
+/* KD_IOGROUP_JOGDIAL: I/O group for a jog dial. */
+#define KD_IOGROUP_JOGDIAL 0x6000
+#define KD_STATE_JOGDIAL_AVAILABILITY (KD_IOGROUP_JOGDIAL + 0)
+#define KD_INPUT_JOGDIAL_UP (KD_IOGROUP_JOGDIAL + 1)
+#define KD_INPUT_JOGDIAL_LEFT (KD_IOGROUP_JOGDIAL + 2)
+#define KD_INPUT_JOGDIAL_RIGHT (KD_IOGROUP_JOGDIAL + 3)
+#define KD_INPUT_JOGDIAL_DOWN (KD_IOGROUP_JOGDIAL + 4)
+#define KD_INPUT_JOGDIAL_SELECT (KD_IOGROUP_JOGDIAL + 5)
+
+/* KD_IOGROUP_STICK: I/O group for joystick. */
+#define KD_IOGROUP_STICK 0x7000
+#define KD_STATE_STICK_AVAILABILITY (KD_IOGROUP_STICK + 0)
+#define KD_INPUT_STICK_X (KD_IOGROUP_STICK + 1)
+#define KD_INPUT_STICK_Y (KD_IOGROUP_STICK + 2)
+#define KD_INPUT_STICK_Z (KD_IOGROUP_STICK + 3)
+#define KD_INPUT_STICK_BUTTON (KD_IOGROUP_STICK + 4)
+#define KD_IO_STICK_STRIDE 8
+
+/* KD_IOGROUP_DPAD: I/O group for D-pad. */
+#define KD_IOGROUP_DPAD 0x8000
+#define KD_STATE_DPAD_AVAILABILITY (KD_IOGROUP_DPAD + 0)
+#define KD_STATE_DPAD_COPY (KD_IOGROUP_DPAD + 1)
+#define KD_INPUT_DPAD_UP (KD_IOGROUP_DPAD + 2)
+#define KD_INPUT_DPAD_LEFT (KD_IOGROUP_DPAD + 3)
+#define KD_INPUT_DPAD_RIGHT (KD_IOGROUP_DPAD + 4)
+#define KD_INPUT_DPAD_DOWN (KD_IOGROUP_DPAD + 5)
+#define KD_INPUT_DPAD_SELECT (KD_IOGROUP_DPAD + 6)
+#define KD_IO_DPAD_STRIDE 8
+
+/* KD_IOGROUP_BUTTONS: I/O group for buttons associated with joystick or D-pad. */
+#define KD_IOGROUP_BUTTONS 0x9000
+#define KD_STATE_BUTTONS_AVAILABILITY (KD_IOGROUP_BUTTONS + 0)
+#define KD_INPUT_BUTTONS_0 (KD_IOGROUP_BUTTONS + 1)
+
+/* KD_IO_UNDEFINED: I/O items reserved for implementation-dependent use. */
+#define KD_IO_UNDEFINED 0x40000000
+
+/*******************************************************
+ * Windowing
+ *******************************************************/
+#ifdef KD_WINDOW_SUPPORTED
+#include <EGL/egl.h>
+typedef struct KDWindow KDWindow;
+
+/* kdCreateWindow: Create a window. */
+KD_API KDWindow *KD_APIENTRY kdCreateWindow(EGLDisplay display, EGLConfig config, void *eventuserptr);
+
+/* kdDestroyWindow: Destroy a window. */
+KD_API KDint KD_APIENTRY kdDestroyWindow(KDWindow *window);
+
+/* kdSetWindowPropertybv, kdSetWindowPropertyiv, kdSetWindowPropertycv: Set a window property to request a change in the on-screen representation of the window. */
+KD_API KDint KD_APIENTRY kdSetWindowPropertybv(KDWindow *window, KDint pname, const KDboolean *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertyiv(KDWindow *window, KDint pname, const KDint32 *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertycv(KDWindow *window, KDint pname, const KDchar *param);
+
+/* kdGetWindowPropertybv, kdGetWindowPropertyiv, kdGetWindowPropertycv: Get the current value of a window property. */
+KD_API KDint KD_APIENTRY kdGetWindowPropertybv(KDWindow *window, KDint pname, KDboolean *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertyiv(KDWindow *window, KDint pname, KDint32 *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertycv(KDWindow *window, KDint pname, KDchar *param, KDsize *size);
+
+/* kdRealizeWindow: Realize the window as a displayable entity and get the native window handle for passing to EGL. */
+KD_API KDint KD_APIENTRY kdRealizeWindow(KDWindow *window, EGLNativeWindowType *nativewindow);
+
+/* KD_WINDOWPROPERTY_SIZE: Window client area width and height. */
+#define KD_WINDOWPROPERTY_SIZE 66
+
+/* KD_WINDOWPROPERTY_VISIBILITY: Window visibility status. */
+#define KD_WINDOWPROPERTY_VISIBILITY 67
+
+/* KD_WINDOWPROPERTY_FOCUS: Window input focus status. */
+#define KD_WINDOWPROPERTY_FOCUS 68
+
+/* KD_WINDOWPROPERTY_CAPTION: Window caption. */
+#define KD_WINDOWPROPERTY_CAPTION 69
+
+/* KD_EVENT_WINDOW_CLOSE: Event to request to close window. */
+#define KD_EVENT_WINDOW_CLOSE 44
+
+/* KD_EVENT_WINDOWPROPERTY_CHANGE: Notification about realized window property change. */
+#define KD_EVENT_WINDOWPROPERTY_CHANGE 47
+typedef struct KDEventWindowProperty {
+ KDint32 pname;
+} KDEventWindowProperty;
+
+/* KD_EVENT_WINDOW_FOCUS: Event for change of window&#8217;s focus state. */
+#define KD_EVENT_WINDOW_FOCUS 60
+typedef struct KDEventWindowFocus {
+ KDint32 focusstate;
+} KDEventWindowFocus;
+
+/* KD_EVENT_WINDOW_REDRAW: Event to notify need to redraw the window. */
+#define KD_EVENT_WINDOW_REDRAW 59
+#endif /* KD_WINDOW_SUPPORTED */
+
+/*******************************************************
+ * Assertions and logging
+ *******************************************************/
+
+/* kdHandleAssertion: Handle assertion failure. */
+KD_API void KD_APIENTRY kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber);
+
+/* kdLogMessage: Output a log message. */
+#ifdef KD_NDEBUG
+#define kdLogMessage(s)
+#else
+KD_API void KD_APIENTRY kdLogMessage(const KDchar *string);
+#endif
+
+/* struct KDEvent delayed to the end as it uses event data structs from
+ * other parts of the .h file. */
+struct KDEvent {
+ KDust timestamp;
+ KDint32 type;
+ void *userptr;
+ union KDEventData {
+ KDEventState state;
+ KDEventInput input;
+ KDEventInputJog inputjog;
+ KDEventInputPointer inputpointer;
+ KDEventInputStick inputstick;
+ KDEventSocketReadable socketreadable;
+ KDEventSocketWritable socketwritable;
+ KDEventSocketConnect socketconnect;
+ KDEventSocketIncoming socketincoming;
+ KDEventNameLookup namelookup;
+#ifdef KD_WINDOW_SUPPORTED
+ KDEventWindowProperty windowproperty;
+ KDEventWindowFocus windowfocus;
+#endif /* KD_WINDOW_SUPPORTED */
+ KDEventUser user;
+ } data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kdplatform.h b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kdplatform.h
new file mode 100644
index 00000000..3cf09f52
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs/KD/kdplatform.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Sample KD/kdplatform.h for OpenKODE Core 1.0.3 */
+#ifndef __kdplatform_h_
+#define __kdplatform_h_
+
+#define KD_API
+#define KD_APIENTRY
+
+typedef int KDint32;
+typedef unsigned int KDuint32;
+typedef long long KDint64;
+typedef unsigned long long KDuint64;
+typedef short KDint16;
+typedef unsigned short KDuint16;
+typedef unsigned long KDuintptr;
+typedef unsigned long KDsize;
+typedef long KDssize;
+#define KDINT_MIN (-0x7fffffff-1)
+#define KDINT_MAX 0x7fffffff
+#define KDUINT_MAX 0xffffffffU
+#define KDINT64_MIN (-0x7fffffffffffffffLL-1)
+#define KDINT64_MAX 0x7fffffffffffffffLL
+#define KDUINT64_MAX 0xffffffffffffffffULL
+#define KDSSIZE_MIN (-0x7fffffff-1)
+#define KDSSIZE_MAX 0x7fffffff
+#define KDSIZE_MAX 0xffffffffU
+#define KDUINTPTR_MAX 0xffffffffU
+#define KD_NORETURN
+#define KD_WINDOW_SUPPORTED
+#ifdef KD_NDEBUG
+#define kdAssert(c)
+#else
+#define kdAssert(c) ((void)( (c) ? 0 : (kdHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+#define KD_INFINITY_BITS 0x7f800000u
+#define KD_INFINITY (kdBitsToFloatNV(KD_INFINITY_BITS))
+
+KD_API float KD_APIENTRY kdBitsToFloatNV(KDuint32 x);
+
+
+/** KHR_formatted extension */
+#include <stdarg.h>
+typedef va_list KDVaListKHR;
+
+// If there are problems with including stdarg.h here under any of the Windows
+// operating systems, we might want to change it back to using char* instead of
+// va_list
+//typedef char *KDVaListKHR;
+
+
+#define KD_VA_START_KHR(ap, parmN) \
+ do {ap = (KDVaListKHR)&parmN + sizeof(parmN);} while(0)
+
+#define KD_VA_ARG_CHAR_KHR(ap) (KDchar)va_arg(ap, KDint)
+#define KD_VA_ARG_CHARPTR_KHR(ap) (KDchar*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16_KHR(ap) (KDint16)va_arg(ap, KDint)
+#define KD_VA_ARG_INT32_KHR(ap) va_arg(ap, KDint32)
+#define KD_VA_ARG_INT_KHR(ap) va_arg(ap, KDint)
+#define KD_VA_ARG_INT64_KHR(ap) va_arg(ap, KDint64)
+#define KD_VA_ARG_INTPTR_KHR(ap) (KDint*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16PTR_KHR(ap) (KDint16*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_FLOAT32_KHR(ap) (KDfloat32)(va_arg(ap, double))
+#define KD_VA_ARG_PTR_KHR(ap) (void *)va_arg(ap, char *)
+
+#define KD_VA_END_KHR(ap) \
+ do {ap = (KDVaListKHR)0;} while(0)
+
+#endif /* __kdplatform_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_extwindowprops.h b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_extwindowprops.h
new file mode 100644
index 00000000..4428a568
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_extwindowprops.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_extwindowprops_h_
+#define __kd_QT3DS_extwindowprops_h_
+#include <KD/kd.h>
+#include <EGL/eglext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_WINDOWPROPERTY_FULLSCREEN: Control over resizing a window to fill the complete screen */
+
+// KDboolean - set the window to fullscreen mode
+#define KD_WINDOWPROPERTY_FULLSCREEN_QT3DS 9999
+
+// KDint - set which KD_DISPLAY_* display that the window should be opened on
+#define KD_WINDOWPROPERTY_DISPLAY_QT3DS 9998
+
+// KDboolean - sets whether overlay should be used to create window
+#define KD_WINDOWPROPERTY_OVERLAY_QT3DS 9997
+
+#define KD_DISPLAY_PRIMARY_QT3DS 0
+#define KD_DISPLAY_INTERNAL0_QT3DS 0
+#define KD_DISPLAY_INTERNAL1_QT3DS 1
+#define KD_DISPLAY_INTERNAL2_QT3DS 2
+#define KD_DISPLAY_INTERNAL3_QT3DS 3
+#define KD_DISPLAY_EXTERNAL0_QT3DS 1000
+#define KD_DISPLAY_EXTERNAL1_QT3DS 1001
+#define KD_DISPLAY_EXTERNAL2_QT3DS 1002
+#define KD_DISPLAY_EXTERNAL3_QT3DS 1003
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_extwindowprops_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_multitouch.h b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_multitouch.h
new file mode 100644
index 00000000..e230b029
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/Qt3DS_multitouch.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_multitouch_h_
+#define __kd_QT3DS_multitouch_h_
+#include <KD/kd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_IOGROUP_MULTITOUCH: I/O group for Multitouch input devices. */
+#define KD_IOGROUP_MULTITOUCH_QT3DS 0x40004000
+#define KD_STATE_MULTITOUCH_AVAILABILITY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 0)
+#define KD_INPUT_MULTITOUCH_FINGERS_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 1)
+#define KD_INPUT_MULTITOUCH_WIDTH_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 2)
+#define KD_INPUT_MULTITOUCH_X_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 3)
+#define KD_INPUT_MULTITOUCH_Y_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 4)
+#define KD_INPUT_MULTITOUCH_X2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 5)
+#define KD_INPUT_MULTITOUCH_Y2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 6)
+#define KD_INPUT_MULTITOUCH_PRESSURE_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 7)
+#define KD_INPUT_MULTITOUCH_GESTURES_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 8)
+#define KD_INPUT_MULTITOUCH_RELX_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 9)
+#define KD_INPUT_MULTITOUCH_RELY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 10)
+
+/* KD_EVENT_INPUT_MULTITOUCH_QT3DS: Multitouch event. */
+#define KD_EVENT_INPUT_MULTITOUCH_QT3DS 1001
+typedef struct KDEventInputMultitouchDataNV
+{
+ KDint32 index;
+ KDint8 fingers;
+ KDint8 width;
+ KDint16 x;
+ KDint16 y;
+ KDint16 x2;
+ KDint16 y2;
+ KDint16 pressure;
+} KDEventInputMultitouchDataNV;
+
+/* KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS: Multitouch gesture event. */
+#define KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS 1002
+
+/* kdGetEventInputMultitouchDataNV: Get auxiliary event data for multitouch input. */
+KD_API KDint KD_APIENTRY kdGetEventInputMultitouchDataNV(const KDEvent *event,
+ KDEventInputMultitouchDataNV *data);
+
+/* kdSetEventInputMultitouchActiveNV: Activate Multitouch input events */
+KD_API KDint KD_APIENTRY kdSetEventInputMultitouchActiveNV(KDboolean activate);
+
+/* kdEnableEventInputMultitouchMergeNV: Activate merging of Multitouch input events */
+KD_API void KD_APIENTRY kdEnableEventInputMultitouchMergeNV(KDboolean enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_multitouch_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kd.h b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kd.h
new file mode 100644
index 00000000..f7ccea03
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kd.h
@@ -0,0 +1,991 @@
+/* Reference KD/kd.h for OpenKODE Core 1.0.3 */
+#ifndef __kd_h_
+#define __kd_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kdplatform.h"
+
+
+
+/*******************************************************
+ * Introduction
+ *******************************************************/
+
+/*******************************************************
+ * OpenKODE conformance
+ *******************************************************/
+
+/*******************************************************
+ * Overview
+ *******************************************************/
+
+/*******************************************************
+ * Programming environment
+ *******************************************************/
+#define KD_VERSION_1_0 1
+typedef char KDchar;
+typedef signed char KDint8;
+typedef unsigned char KDuint8;
+typedef int KDint;
+typedef unsigned int KDuint;
+typedef float KDfloat32;
+typedef KDint KDboolean;
+typedef KDint64 KDtime;
+typedef KDint64 KDust;
+typedef KDint64 KDoff;
+typedef KDuint32 KDmode;
+#define KDINT32_MIN (-0x7fffffff-1)
+#define KDINT32_MAX 0x7fffffff
+#define KDUINT32_MAX 0xffffffffU
+#define KD_TRUE 1
+#define KD_FALSE 0
+#ifdef __cplusplus
+ const int KD_NULL = 0; /* Yes, int. See Stroustrup 3rd edition. */
+#else
+ #define KD_NULL ((void *)0)
+#endif
+
+/*******************************************************
+ * Errors
+ *******************************************************/
+#define KD_EACCES 1
+#define KD_EADDRINUSE 2
+#define KD_EADDRNOTAVAIL 3
+#define KD_EAFNOSUPPORT 4
+#define KD_EAGAIN (5)
+#define KD_EALREADY 6
+#define KD_EBADF 7
+#define KD_EBUSY 8
+#define KD_ECONNREFUSED 9
+#define KD_ECONNRESET 10
+#define KD_EDEADLK 11
+#define KD_EDESTADDRREQ 12
+#define KD_EEXIST 13
+#define KD_EFBIG 14
+#define KD_EHOSTUNREACH 15
+#define KD_EHOST_NOT_FOUND 16
+#define KD_EINVAL 17
+#define KD_EIO 18
+#define KD_EILSEQ 19
+#define KD_EISCONN 20
+#define KD_EISDIR 21
+#define KD_EMFILE 22
+#define KD_ENAMETOOLONG 23
+#define KD_ENOENT 24
+#define KD_ENOMEM 25
+#define KD_ENOSPC 26
+#define KD_ENOSYS 27
+#define KD_ENOTCONN 28
+#define KD_ENO_DATA 29
+#define KD_ENO_RECOVERY 30
+#define KD_EOPNOTSUPP 31
+#define KD_EOVERFLOW 32
+#define KD_EPERM 33
+#define KD_ERANGE 35
+#define KD_ETIMEDOUT (36)
+#define KD_ETRY_AGAIN 37
+
+/* kdGetError: Get last error indication. */
+KD_API KDint KD_APIENTRY kdGetError(void);
+
+/* kdSetError: Set last error indication. */
+KD_API void KD_APIENTRY kdSetError(KDint error);
+
+/*******************************************************
+ * Versioning and attribute queries
+ *******************************************************/
+
+/* kdQueryAttribi: Obtain the value of a numeric OpenKODE Core attribute. */
+KD_API KDint KD_APIENTRY kdQueryAttribi(KDint attribute, KDint *value);
+
+/* kdQueryAttribcv: Obtain the value of a string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryAttribcv(KDint attribute);
+#define KD_ATTRIB_VENDOR 39
+#define KD_ATTRIB_VERSION 40
+#define KD_ATTRIB_PLATFORM 41
+
+/* kdQueryIndexedAttribcv: Obtain the value of an indexed string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryIndexedAttribcv(KDint attribute, KDint index);
+
+/*******************************************************
+ * Threads and synchronization
+ *******************************************************/
+
+/* kdThreadAttrCreate: Create a thread attribute object. */
+typedef struct KDThreadAttr KDThreadAttr;
+KD_API KDThreadAttr *KD_APIENTRY kdThreadAttrCreate(void);
+
+/* kdThreadAttrFree: Free a thread attribute object. */
+KD_API KDint KD_APIENTRY kdThreadAttrFree(KDThreadAttr *attr);
+
+/* kdThreadAttrSetDetachState: Set detachstate attribute. */
+#define KD_THREAD_CREATE_JOINABLE 0
+#define KD_THREAD_CREATE_DETACHED 1
+KD_API KDint KD_APIENTRY kdThreadAttrSetDetachState(KDThreadAttr *attr, KDint detachstate);
+
+/* kdThreadAttrSetStackSize: Set stacksize attribute. */
+KD_API KDint KD_APIENTRY kdThreadAttrSetStackSize(KDThreadAttr *attr, KDsize stacksize);
+
+/* kdThreadCreate: Create a new thread. */
+typedef struct KDThread KDThread;
+KD_API KDThread *KD_APIENTRY kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg);
+
+/* kdThreadExit: Terminate this thread. */
+KD_API KD_NORETURN void KD_APIENTRY kdThreadExit(void *retval);
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KD_API KDint KD_APIENTRY kdThreadJoin(KDThread *thread, void **retval);
+
+/* kdThreadDetach: Allow resources to be freed as soon as a thread terminates. */
+KD_API KDint KD_APIENTRY kdThreadDetach(KDThread *thread);
+
+/* kdThreadSelf: Return calling thread&#8217;s ID. */
+KD_API KDThread *KD_APIENTRY kdThreadSelf(void);
+
+/* kdThreadOnce: Wrap initialization code so it is executed only once. */
+#ifndef KD_NO_STATIC_DATA
+typedef struct KDThreadOnce {
+ void *impl;
+} KDThreadOnce;
+#define KD_THREAD_ONCE_INIT { 0 }
+KD_API KDint KD_APIENTRY kdThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void));
+#endif /* ndef KD_NO_STATIC_DATA */
+
+/* kdThreadMutexCreate: Create a mutex. */
+typedef struct KDThreadMutex KDThreadMutex;
+KD_API KDThreadMutex *KD_APIENTRY kdThreadMutexCreate(const void *mutexattr);
+
+/* kdThreadMutexFree: Free a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexFree(KDThreadMutex *mutex);
+
+/* kdThreadMutexLock: Lock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexLock(KDThreadMutex *mutex);
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexUnlock(KDThreadMutex *mutex);
+
+/* kdThreadCondCreate: Create a condition variable. */
+typedef struct KDThreadCond KDThreadCond;
+KD_API KDThreadCond *KD_APIENTRY kdThreadCondCreate(const void *attr);
+
+/* kdThreadCondFree: Free a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondFree(KDThreadCond *cond);
+
+/* kdThreadCondSignal, kdThreadCondBroadcast: Signal a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondSignal(KDThreadCond *cond);
+KD_API KDint KD_APIENTRY kdThreadCondBroadcast(KDThreadCond *cond);
+
+/* kdThreadCondWait: Wait for a condition variable to be signalled. */
+KD_API KDint KD_APIENTRY kdThreadCondWait(KDThreadCond *cond, KDThreadMutex *mutex);
+
+/* kdThreadSemCreate: Create a semaphore. */
+typedef struct KDThreadSem KDThreadSem;
+KD_API KDThreadSem *KD_APIENTRY kdThreadSemCreate(KDuint value);
+
+/* kdThreadSemFree: Free a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemFree(KDThreadSem *sem);
+
+/* kdThreadSemWait: Lock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemWait(KDThreadSem *sem);
+
+/* kdThreadSemPost: Unlock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemPost(KDThreadSem *sem);
+
+/*******************************************************
+ * Events
+ *******************************************************/
+
+/* KDEvent: Struct type containing an event. */
+typedef struct KDEvent KDEvent;
+#define KD_EVENT_USER 0x40000000
+
+/* kdWaitEvent: Get next event from thread&#8217;s event queue. */
+KD_API const KDEvent *KD_APIENTRY kdWaitEvent(KDust timeout);
+
+/* kdSetEventUserptr: Set the userptr for global events. */
+KD_API void KD_APIENTRY kdSetEventUserptr(void *userptr);
+
+/* kdDefaultEvent: Perform default processing on an unrecognized event. */
+KD_API void KD_APIENTRY kdDefaultEvent(const KDEvent *event);
+
+/* kdPumpEvents: Pump the thread&#8217;s event queue, performing callbacks. */
+KD_API KDint KD_APIENTRY kdPumpEvents(void);
+
+/* kdInstallCallback: Install or remove a callback function for event processing. */
+typedef void (KD_APIENTRY KDCallbackFunc)(const KDEvent *event);
+KD_API KDint KD_APIENTRY kdInstallCallback(KDCallbackFunc *func, KDint eventtype, void *eventuserptr);
+
+/* kdCreateEvent: Create an event for posting. */
+KD_API KDEvent *KD_APIENTRY kdCreateEvent(void);
+
+/* kdPostEvent, kdPostThreadEvent: Post an event into a queue. */
+KD_API KDint KD_APIENTRY kdPostEvent(KDEvent *event);
+KD_API KDint KD_APIENTRY kdPostThreadEvent(KDEvent *event, KDThread *thread);
+typedef struct KDEventUser {
+ union {
+ KDint64 i64;
+ void *p;
+ struct {
+ KDint32 a;
+ KDint32 b;
+ } i32pair;
+ } value1;
+ union {
+ KDint64 i64;
+ struct {
+ union {
+ KDint32 i32;
+ void *p;
+ } value2;
+ union {
+ KDint32 i32;
+ void *p;
+ } value3;
+ } i32orp;
+ } value23;
+} KDEventUser;
+
+/* kdFreeEvent: Abandon an event instead of posting it. */
+KD_API void KD_APIENTRY kdFreeEvent(KDEvent *event);
+
+/*******************************************************
+ * System events
+ *******************************************************/
+
+/* KD_EVENT_QUIT: Event to request to quit application. */
+#define KD_EVENT_QUIT 43
+
+/* KD_EVENT_PAUSE: Application pause event. */
+#define KD_EVENT_PAUSE 45
+
+/* KD_EVENT_RESUME: Application resume event. */
+#define KD_EVENT_RESUME 46
+
+/* KD_EVENT_ORIENTATION: Orientation change event. */
+#define KD_EVENT_ORIENTATION 48
+
+/* KD_IOGROUP_EVENT: I/O group for OpenKODE Core system events implemented as state values. */
+#define KD_IOGROUP_EVENT 0x100
+#define KD_STATE_EVENT_USING_BATTERY (KD_IOGROUP_EVENT + 0)
+#define KD_STATE_EVENT_LOW_BATTERY (KD_IOGROUP_EVENT + 1)
+
+
+/* KD_IOGROUP_ORIENTATION: I/O group for OpenKODE Core orientation state. */
+#define KD_IOGROUP_ORIENTATION 0x200
+#define KD_STATE_ORIENTATION_OVERALL (KD_IOGROUP_ORIENTATION + 0)
+#define KD_STATE_ORIENTATION_SCREEN (KD_IOGROUP_ORIENTATION + 1)
+#define KD_STATE_ORIENTATION_RENDERING (KD_IOGROUP_ORIENTATION + 2)
+#define KD_STATE_ORIENTATION_LOCKSURFACE (KD_IOGROUP_ORIENTATION + 3)
+
+
+/*******************************************************
+ * Application startup and exit.
+ *******************************************************/
+
+/* kdMain: The application-defined main function. */
+KDint KD_APIENTRY kdMain(KDint argc, const KDchar *const *argv);
+
+/* kdExit: Exit the application. */
+KD_API KD_NORETURN void KD_APIENTRY kdExit(KDint status);
+
+/*******************************************************
+ * Utility library functions
+ *******************************************************/
+
+/* kdAbs: Compute the absolute value of an integer. */
+KD_API KDint KD_APIENTRY kdAbs(KDint i);
+
+/* kdStrtof: Convert a string to a floating point number. */
+KD_API KDfloat32 KD_APIENTRY kdStrtof(const KDchar *s, KDchar **endptr);
+
+/* kdStrtol, kdStrtoul: Convert a string to an integer. */
+KD_API KDint KD_APIENTRY kdStrtol(const KDchar *s, KDchar **endptr, KDint base);
+KD_API KDuint KD_APIENTRY kdStrtoul(const KDchar *s, KDchar **endptr, KDint base);
+
+/* kdLtostr, kdUltostr: Convert an integer to a string. */
+#define KD_LTOSTR_MAXLEN ((sizeof(KDint)*8*3+6)/10+2)
+#define KD_ULTOSTR_MAXLEN ((sizeof(KDint)*8+2)/3+1)
+KD_API KDssize KD_APIENTRY kdLtostr(KDchar *buffer, KDsize buflen, KDint number);
+KD_API KDssize KD_APIENTRY kdUltostr(KDchar *buffer, KDsize buflen, KDuint number, KDint base);
+
+/* kdFtostr: Convert a float to a string. */
+#define KD_FTOSTR_MAXLEN 16
+KD_API KDssize KD_APIENTRY kdFtostr(KDchar *buffer, KDsize buflen, KDfloat32 number);
+
+/* kdCryptoRandom: Return random data. */
+KD_API KDint KD_APIENTRY kdCryptoRandom(KDuint8 *buf, KDsize buflen);
+
+/*******************************************************
+ * Locale specific functions
+ *******************************************************/
+
+/* kdGetLocale: Determine the current language and locale. */
+KD_API const KDchar *KD_APIENTRY kdGetLocale(void);
+
+/*******************************************************
+ * Memory allocation
+ *******************************************************/
+
+/* kdMalloc: Allocate memory. */
+KD_API void *KD_APIENTRY kdMalloc(KDsize size);
+
+/* kdFree: Free allocated memory block. */
+KD_API void KD_APIENTRY kdFree(void *ptr);
+
+/* kdRealloc: Resize memory block. */
+KD_API void *KD_APIENTRY kdRealloc(void *ptr, KDsize size);
+
+/*******************************************************
+ * Thread-local storage.
+ *******************************************************/
+
+/* kdGetTLS: Get the thread-local storage pointer. */
+KD_API void *KD_APIENTRY kdGetTLS(void);
+
+/* kdSetTLS: Set the thread-local storage pointer. */
+KD_API void KD_APIENTRY kdSetTLS(void *ptr);
+
+/*******************************************************
+ * Mathematical functions
+ *******************************************************/
+#define KD_E_F 2.71828175F
+#define KD_PI_F 3.14159274F
+#define KD_PI_2_F 1.57079637F
+#define KD_2PI_F 6.28318548F
+#define KD_LOG2E_F 1.44269502F
+#define KD_LOG10E_F 0.434294492F
+#define KD_LN2_F 0.693147182F
+#define KD_LN10_F 2.30258512F
+#define KD_PI_4_F 0.785398185F
+#define KD_1_PI_F 0.318309873F
+#define KD_2_PI_F 0.636619747F
+#define KD_2_SQRTPI_F 1.12837923F
+#define KD_SQRT2_F 1.41421354F
+#define KD_SQRT1_2_F 0.707106769F
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_FLT_MAX 3.40282346638528860e+38F
+#define KD_FLT_MIN 1.17549435e-38F
+/* KD_INFINITY is defined in kdplatform.h since no portable definition
+ * is possible. */
+#define kdIsNan(x) (((x) != (x)) ? 1 : 0)
+#define KD_HUGE_VALF KD_INFINITY
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+/* kdAcosf: Arc cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdAcosf(KDfloat32 x);
+
+/* kdAsinf: Arc sine function. */
+KD_API KDfloat32 KD_APIENTRY kdAsinf(KDfloat32 x);
+
+/* kdAtanf: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtanf(KDfloat32 x);
+
+/* kdAtan2f: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtan2f(KDfloat32 y, KDfloat32 x);
+
+/* kdCosf: Cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdCosf(KDfloat32 x);
+
+/* kdSinf: Sine function. */
+KD_API KDfloat32 KD_APIENTRY kdSinf(KDfloat32 x);
+
+/* kdTanf: Tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdTanf(KDfloat32 x);
+
+/* kdExpf: Exponential function. */
+KD_API KDfloat32 KD_APIENTRY kdExpf(KDfloat32 x);
+
+/* kdLogf: Natural logarithm function. */
+KD_API KDfloat32 KD_APIENTRY kdLogf(KDfloat32 x);
+
+/* kdFabsf: Absolute value. */
+KD_API KDfloat32 KD_APIENTRY kdFabsf(KDfloat32 x);
+
+/* kdPowf: Power function. */
+KD_API KDfloat32 KD_APIENTRY kdPowf(KDfloat32 x, KDfloat32 y);
+
+/* kdSqrtf: Square root function. */
+KD_API KDfloat32 KD_APIENTRY kdSqrtf(KDfloat32 x);
+
+/* kdCeilf: Return ceiling value. */
+KD_API KDfloat32 KD_APIENTRY kdCeilf(KDfloat32 x);
+
+/* kdFloorf: Return floor value. */
+KD_API KDfloat32 KD_APIENTRY kdFloorf(KDfloat32 x);
+
+/* kdRoundf: Round value to nearest integer. */
+KD_API KDfloat32 KD_APIENTRY kdRoundf(KDfloat32 x);
+
+/* kdInvsqrtf: Inverse square root function. */
+KD_API KDfloat32 KD_APIENTRY kdInvsqrtf(KDfloat32 x);
+
+/* kdFmodf: Calculate floating point remainder. */
+KD_API KDfloat32 KD_APIENTRY kdFmodf(KDfloat32 x, KDfloat32 y);
+
+/*******************************************************
+ * String and memory functions
+ *******************************************************/
+
+/* kdMemchr: Scan memory for a byte value. */
+KD_API void *KD_APIENTRY kdMemchr(const void *src, KDint byte, KDsize len);
+
+/* kdMemcmp: Compare two memory regions. */
+KD_API KDint KD_APIENTRY kdMemcmp(const void *src1, const void *src2, KDsize len);
+
+/* kdMemcpy: Copy a memory region, no overlapping. */
+KD_API void *KD_APIENTRY kdMemcpy(void *buf, const void *src, KDsize len);
+
+/* kdMemmove: Copy a memory region, overlapping allowed. */
+KD_API void *KD_APIENTRY kdMemmove(void *buf, const void *src, KDsize len);
+
+/* kdMemset: Set bytes in memory to a value. */
+KD_API void *KD_APIENTRY kdMemset(void *buf, KDint byte, KDsize len);
+
+/* kdStrchr: Scan string for a byte value. */
+KD_API KDchar *KD_APIENTRY kdStrchr(const KDchar *str, KDint ch);
+
+/* kdStrcmp: Compares two strings. */
+KD_API KDint KD_APIENTRY kdStrcmp(const KDchar *str1, const KDchar *str2);
+
+/* kdStrlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrlen(const KDchar *str);
+
+/* kdStrnlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrnlen(const KDchar *str, KDsize maxlen);
+
+/* kdStrncat_s: Concatenate two strings. */
+KD_API KDint KD_APIENTRY kdStrncat_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srcmaxlen);
+
+/* kdStrncmp: Compares two strings with length limit. */
+KD_API KDint KD_APIENTRY kdStrncmp(const KDchar *str1, const KDchar *str2, KDsize maxlen);
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrcpy_s(KDchar *buf, KDsize buflen, const KDchar *src);
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrncpy_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srclen);
+
+/*******************************************************
+ * Time functions
+ *******************************************************/
+
+/* kdGetTimeUST: Get the current unadjusted system time. */
+KD_API KDust KD_APIENTRY kdGetTimeUST(void);
+
+/* kdTime: Get the current wall clock time. */
+KD_API KDtime KD_APIENTRY kdTime(KDtime *timep);
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+typedef struct KDTm {
+ KDint32 tm_sec;
+ KDint32 tm_min;
+ KDint32 tm_hour;
+ KDint32 tm_mday;
+ KDint32 tm_mon;
+ KDint32 tm_year;
+ KDint32 tm_wday;
+ KDint32 tm_yday;
+} KDTm;
+KD_API KDTm *KD_APIENTRY kdGmtime_r(const KDtime *timep, KDTm *result);
+KD_API KDTm *KD_APIENTRY kdLocaltime_r(const KDtime *timep, KDTm *result);
+
+/* kdUSTAtEpoch: Get the UST corresponding to KDtime 0. */
+KD_API KDust KD_APIENTRY kdUSTAtEpoch(void);
+
+/*******************************************************
+ * Timer functions
+ *******************************************************/
+
+/* kdSetTimer: Set timer. */
+#define KD_TIMER_ONESHOT 61
+#define KD_TIMER_PERIODIC_AVERAGE 62
+#define KD_TIMER_PERIODIC_MINIMUM 63
+typedef struct KDTimer KDTimer;
+KD_API KDTimer *KD_APIENTRY kdSetTimer(KDint64 interval, KDint periodic, void *eventuserptr);
+
+/* kdCancelTimer: Cancel and free a timer. */
+KD_API KDint KD_APIENTRY kdCancelTimer(KDTimer *timer);
+
+/* KD_EVENT_TIMER: Timer fire event. */
+#define KD_EVENT_TIMER 42
+
+/*******************************************************
+ * File system
+ *******************************************************/
+#define KD_EOF (-1)
+
+/* kdFopen: Open a file from the file system. */
+typedef struct KDFile KDFile;
+KD_API KDFile *KD_APIENTRY kdFopen(const KDchar *pathname, const KDchar *mode);
+
+/* kdFclose: Close an open file. */
+KD_API KDint KD_APIENTRY kdFclose(KDFile *file);
+
+/* kdFflush: Flush an open file. */
+KD_API KDint KD_APIENTRY kdFflush(KDFile *file);
+
+/* kdFread: Read from a file. */
+KD_API KDsize KD_APIENTRY kdFread(void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdFwrite: Write to a file. */
+KD_API KDsize KD_APIENTRY kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdGetc: Read next byte from an open file. */
+KD_API KDint KD_APIENTRY kdGetc(KDFile *file);
+
+/* kdPutc: Write a byte to an open file. */
+KD_API KDint KD_APIENTRY kdPutc(KDint c, KDFile *file);
+
+/* kdFgets: Read a line of text from an open file. */
+KD_API KDchar *KD_APIENTRY kdFgets(KDchar *buffer, KDsize buflen, KDFile *file);
+
+/* kdFEOF: Check for end of file. */
+KD_API KDint KD_APIENTRY kdFEOF(KDFile *file);
+
+/* kdFerror: Check for an error condition on an open file. */
+KD_API KDint KD_APIENTRY kdFerror(KDFile *file);
+
+/* kdClearerr: Clear a file&#8217;s error and end-of-file indicators. */
+KD_API void KD_APIENTRY kdClearerr(KDFile *file);
+
+/* kdFseek: Reposition the file position indicator in a file. */
+typedef enum {
+ KD_SEEK_SET = 0,
+ KD_SEEK_CUR = 1,
+ KD_SEEK_END = 2
+} KDfileSeekOrigin;
+KD_API KDint KD_APIENTRY kdFseek(KDFile *file, KDoff offset, KDfileSeekOrigin origin);
+
+/* kdFtell: Get the file position of an open file. */
+KD_API KDoff KD_APIENTRY kdFtell(KDFile *file);
+
+/* kdMkdir: Create new directory. */
+KD_API KDint KD_APIENTRY kdMkdir(const KDchar *pathname);
+
+/* kdRmdir: Delete a directory. */
+KD_API KDint KD_APIENTRY kdRmdir(const KDchar *pathname);
+
+/* kdRename: Rename a file. */
+KD_API KDint KD_APIENTRY kdRename(const KDchar *src, const KDchar *dest);
+
+/* kdRemove: Delete a file. */
+KD_API KDint KD_APIENTRY kdRemove(const KDchar *pathname);
+
+/* kdTruncate: Truncate or extend a file. */
+KD_API KDint KD_APIENTRY kdTruncate(const KDchar *pathname, KDoff length);
+
+/* kdStat, kdFstat: Return information about a file. */
+typedef struct KDStat {
+ KDmode st_mode;
+ KDoff st_size;
+ KDtime st_mtime;
+} KDStat;
+KD_API KDint KD_APIENTRY kdStat(const KDchar *pathname, struct KDStat *buf);
+KD_API KDint KD_APIENTRY kdFstat(KDFile *file, struct KDStat *buf);
+#define KD_ISREG(m) ((m) & 0x8000)
+#define KD_ISDIR(m) ((m) & 0x4000)
+
+/* kdAccess: Determine whether the application can access a file or directory. */
+KD_API KDint KD_APIENTRY kdAccess(const KDchar *pathname, KDint amode);
+#define KD_R_OK 4
+#define KD_W_OK 2
+#define KD_X_OK 1
+
+/* kdOpenDir: Open a directory ready for listing. */
+typedef struct KDDir KDDir;
+KD_API KDDir *KD_APIENTRY kdOpenDir(const KDchar *pathname);
+
+/* kdReadDir: Return the next file in a directory. */
+typedef struct KDDirent {
+ const KDchar *d_name;
+} KDDirent;
+KD_API KDDirent *KD_APIENTRY kdReadDir(KDDir *dir);
+
+/* kdCloseDir: Close a directory. */
+KD_API KDint KD_APIENTRY kdCloseDir(KDDir *dir);
+
+/* kdGetFree: Get free space on a drive. */
+KD_API KDoff KD_APIENTRY kdGetFree(const KDchar *pathname);
+
+/*******************************************************
+ * Network sockets
+ *******************************************************/
+
+/* KDSockaddr: Struct type for socket address. */
+typedef struct KDSockaddr {
+ KDuint16 family;
+ union {
+#define KD_AF_INET 70
+ struct {
+ KDuint16 port;
+ KDuint32 address;
+ } sin;
+ } data;
+} KDSockaddr;
+
+/* kdNameLookup: Look up a hostname. */
+KD_API KDint KD_APIENTRY kdNameLookup(KDint af, const KDchar *hostname, void *eventuserptr);
+
+/* kdNameLookupCancel: Selectively cancels ongoing kdNameLookup operations. */
+KD_API void KD_APIENTRY kdNameLookupCancel(void *eventuserptr);
+
+/* kdSocketCreate: Creates a socket. */
+typedef struct KDSocket KDSocket;
+KD_API KDSocket *KD_APIENTRY kdSocketCreate(KDint type, void *eventuserptr);
+#define KD_SOCK_TCP 64
+#define KD_SOCK_UDP 65
+
+/* kdSocketClose: Closes a socket. */
+KD_API KDint KD_APIENTRY kdSocketClose(KDSocket *socket);
+
+/* kdSocketBind: Bind a socket. */
+KD_API KDint KD_APIENTRY kdSocketBind(KDSocket *socket, const struct KDSockaddr *addr, KDboolean reuse);
+#define KD_INADDR_ANY 0
+
+/* kdSocketGetName: Get the local address of a socket. */
+KD_API KDint KD_APIENTRY kdSocketGetName(KDSocket *socket, struct KDSockaddr *addr);
+
+/* kdSocketConnect: Connects a socket. */
+KD_API KDint KD_APIENTRY kdSocketConnect(KDSocket *socket, const KDSockaddr *addr);
+
+/* kdSocketListen: Listen on a socket. */
+KD_API KDint KD_APIENTRY kdSocketListen(KDSocket *socket, KDint backlog);
+
+/* kdSocketAccept: Accept an incoming connection. */
+KD_API KDSocket *KD_APIENTRY kdSocketAccept(KDSocket *socket, KDSockaddr *addr, void *eventuserptr);
+
+/* kdSocketSend, kdSocketSendTo: Send data to a socket. */
+KD_API KDint KD_APIENTRY kdSocketSend(KDSocket *socket, const void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketSendTo(KDSocket *socket, const void *buf, KDint len, const KDSockaddr *addr);
+
+/* kdSocketRecv, kdSocketRecvFrom: Receive data from a socket. */
+KD_API KDint KD_APIENTRY kdSocketRecv(KDSocket *socket, void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketRecvFrom(KDSocket *socket, void *buf, KDint len, KDSockaddr *addr);
+
+/* kdHtonl: Convert a 32-bit integer from host to network byte order. */
+KD_API KDuint32 KD_APIENTRY kdHtonl(KDuint32 hostlong);
+
+/* kdHtons: Convert a 16-bit integer from host to network byte order. */
+KD_API KDuint16 KD_APIENTRY kdHtons(KDuint16 hostshort);
+
+/* kdNtohl: Convert a 32-bit integer from network to host byte order. */
+KD_API KDuint32 KD_APIENTRY kdNtohl(KDuint32 netlong);
+
+/* kdNtohs: Convert a 16-bit integer from network to host byte order. */
+KD_API KDuint16 KD_APIENTRY kdNtohs(KDuint16 netshort);
+
+/* kdInetAton: Convert a &#8220;dotted quad&#8221; format address to an integer. */
+KD_API KDint KD_APIENTRY kdInetAton(const KDchar *cp, KDuint32 *inp);
+
+/* kdInetNtop: Convert a network address to textual form. */
+#define KD_INET_ADDRSTRLEN 16
+typedef struct KDInAddr {
+ KDuint32 s_address; // Renamed this from s_addr as it causes a conflict with winsock2.h
+} KDInAddr;
+KD_API const KDchar *KD_APIENTRY kdInetNtop(KDuint af, const void *src, KDchar *dst, KDsize cnt);
+
+/* KD_EVENT_SOCKET_READABLE: Event to indicate that a socket is readable. */
+#define KD_EVENT_SOCKET_READABLE 49
+typedef struct KDEventSocketReadable {
+ KDSocket *socket;
+} KDEventSocketReadable;
+
+/* KD_EVENT_SOCKET_WRITABLE: Event to indicate that a socket is writable. */
+#define KD_EVENT_SOCKET_WRITABLE 50
+typedef struct KDEventSocketWritable {
+ KDSocket *socket;
+} KDEventSocketWritable;
+
+/* KD_EVENT_SOCKET_CONNECT_COMPLETE: Event generated when a socket connect is complete */
+#define KD_EVENT_SOCKET_CONNECT_COMPLETE 51
+typedef struct KDEventSocketConnect {
+ KDSocket *socket;
+ KDint32 error;
+} KDEventSocketConnect;
+
+/* KD_EVENT_SOCKET_INCOMING: Event generated when a listening socket detects an incoming connection or an error. */
+#define KD_EVENT_SOCKET_INCOMING 52
+typedef struct KDEventSocketIncoming {
+ KDSocket *socket;
+} KDEventSocketIncoming;
+
+/* KD_EVENT_NAME_LOOKUP_COMPLETE: kdNameLookup complete event. */
+#define KD_EVENT_NAME_LOOKUP_COMPLETE 53
+typedef struct KDEventNameLookup {
+ KDint32 error;
+ KDint32 resultlen;
+ const KDSockaddr *result;
+ KDboolean more;
+} KDEventNameLookup;
+
+/*******************************************************
+ * Input/output
+ *******************************************************/
+
+/* KD_EVENT_STATE: State changed event. */
+#define KD_EVENT_STATE 55
+
+typedef struct KDEventState {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventState;
+
+/* KD_EVENT_INPUT: Input changed event. */
+#define KD_EVENT_INPUT 56
+
+typedef struct KDEventInput {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventInput;
+
+/* KD_EVENT_INPUT_JOG: Jogdial jog event. */
+#define KD_EVENT_INPUT_JOG 71
+typedef struct KDEventInputJog {
+ KDint32 index;
+ KDint32 count;
+} KDEventInputJog;
+
+/* KD_EVENT_INPUT_POINTER: Pointer input changed event. */
+#define KD_EVENT_INPUT_POINTER 57
+typedef struct KDEventInputPointer {
+ KDint32 index;
+ KDint32 select;
+ KDint32 x;
+ KDint32 y;
+} KDEventInputPointer;
+
+/* KD_EVENT_INPUT_STICK: Joystick stick changed event. */
+#define KD_EVENT_INPUT_STICK 58
+typedef struct KDEventInputStick {
+ KDint32 index;
+ KDint32 x;
+ KDint32 y;
+ KDint32 z;
+} KDEventInputStick;
+
+/* kdStateGeti, kdStateGetl, kdStateGetf: get state value(s) */
+KD_API KDint KD_APIENTRY kdStateGeti(KDint startidx, KDuint numidxs, KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetl(KDint startidx, KDuint numidxs, KDint64 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetf(KDint startidx, KDuint numidxs, KDfloat32 *buffer);
+
+/* kdOutputSeti, kdOutputSetf: set outputs */
+KD_API KDint KD_APIENTRY kdOutputSeti(KDint startidx, KDuint numidxs, const KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdOutputSetf(KDint startidx, KDuint numidxs, const KDfloat32 *buffer);
+#define KD_IO_CONTROLLER_STRIDE 64
+
+/* KD_IOGROUP_GAMEKEYS: I/O group for game keys. */
+#define KD_IOGROUP_GAMEKEYS 0x1000
+#define KD_STATE_GAMEKEYS_AVAILABILITY (KD_IOGROUP_GAMEKEYS + 0)
+#define KD_INPUT_GAMEKEYS_UP (KD_IOGROUP_GAMEKEYS + 1)
+#define KD_INPUT_GAMEKEYS_LEFT (KD_IOGROUP_GAMEKEYS + 2)
+#define KD_INPUT_GAMEKEYS_RIGHT (KD_IOGROUP_GAMEKEYS + 3)
+#define KD_INPUT_GAMEKEYS_DOWN (KD_IOGROUP_GAMEKEYS + 4)
+#define KD_INPUT_GAMEKEYS_FIRE (KD_IOGROUP_GAMEKEYS + 5)
+#define KD_INPUT_GAMEKEYS_A (KD_IOGROUP_GAMEKEYS + 6)
+#define KD_INPUT_GAMEKEYS_B (KD_IOGROUP_GAMEKEYS + 7)
+#define KD_INPUT_GAMEKEYS_C (KD_IOGROUP_GAMEKEYS + 8)
+#define KD_INPUT_GAMEKEYS_D (KD_IOGROUP_GAMEKEYS + 9)
+
+/* KD_IOGROUP_GAMEKEYSNC: I/O group for game keys, no chording. */
+#define KD_IOGROUP_GAMEKEYSNC 0x1100
+#define KD_STATE_GAMEKEYSNC_AVAILABILITY (KD_IOGROUP_GAMEKEYSNC + 0)
+#define KD_INPUT_GAMEKEYSNC_UP (KD_IOGROUP_GAMEKEYSNC + 1)
+#define KD_INPUT_GAMEKEYSNC_LEFT (KD_IOGROUP_GAMEKEYSNC + 2)
+#define KD_INPUT_GAMEKEYSNC_RIGHT (KD_IOGROUP_GAMEKEYSNC + 3)
+#define KD_INPUT_GAMEKEYSNC_DOWN (KD_IOGROUP_GAMEKEYSNC + 4)
+#define KD_INPUT_GAMEKEYSNC_FIRE (KD_IOGROUP_GAMEKEYSNC + 5)
+#define KD_INPUT_GAMEKEYSNC_A (KD_IOGROUP_GAMEKEYSNC + 6)
+#define KD_INPUT_GAMEKEYSNC_B (KD_IOGROUP_GAMEKEYSNC + 7)
+#define KD_INPUT_GAMEKEYSNC_C (KD_IOGROUP_GAMEKEYSNC + 8)
+#define KD_INPUT_GAMEKEYSNC_D (KD_IOGROUP_GAMEKEYSNC + 9)
+
+/* KD_IOGROUP_PHONEKEYPAD: I/O group for phone keypad. */
+#define KD_IOGROUP_PHONEKEYPAD 0x2000
+#define KD_STATE_PHONEKEYPAD_AVAILABILITY (KD_IOGROUP_PHONEKEYPAD + 0)
+#define KD_INPUT_PHONEKEYPAD_0 (KD_IOGROUP_PHONEKEYPAD + 1)
+#define KD_INPUT_PHONEKEYPAD_1 (KD_IOGROUP_PHONEKEYPAD + 2)
+#define KD_INPUT_PHONEKEYPAD_2 (KD_IOGROUP_PHONEKEYPAD + 3)
+#define KD_INPUT_PHONEKEYPAD_3 (KD_IOGROUP_PHONEKEYPAD + 4)
+#define KD_INPUT_PHONEKEYPAD_4 (KD_IOGROUP_PHONEKEYPAD + 5)
+#define KD_INPUT_PHONEKEYPAD_5 (KD_IOGROUP_PHONEKEYPAD + 6)
+#define KD_INPUT_PHONEKEYPAD_6 (KD_IOGROUP_PHONEKEYPAD + 7)
+#define KD_INPUT_PHONEKEYPAD_7 (KD_IOGROUP_PHONEKEYPAD + 8)
+#define KD_INPUT_PHONEKEYPAD_8 (KD_IOGROUP_PHONEKEYPAD + 9)
+#define KD_INPUT_PHONEKEYPAD_9 (KD_IOGROUP_PHONEKEYPAD + 10)
+#define KD_INPUT_PHONEKEYPAD_STAR (KD_IOGROUP_PHONEKEYPAD + 11)
+#define KD_INPUT_PHONEKEYPAD_HASH (KD_IOGROUP_PHONEKEYPAD + 12)
+#define KD_INPUT_PHONEKEYPAD_LEFTSOFT (KD_IOGROUP_PHONEKEYPAD + 13)
+#define KD_INPUT_PHONEKEYPAD_RIGHTSOFT (KD_IOGROUP_PHONEKEYPAD + 14)
+#define KD_STATE_PHONEKEYPAD_ORIENTATION (KD_IOGROUP_PHONEKEYPAD + 15)
+
+/* KD_IOGROUP_VIBRATE: I/O group for vibrate. */
+#define KD_IOGROUP_VIBRATE 0x3000
+#define KD_STATE_VIBRATE_AVAILABILITY (KD_IOGROUP_VIBRATE + 0)
+#define KD_STATE_VIBRATE_MINFREQUENCY (KD_IOGROUP_VIBRATE + 1)
+#define KD_STATE_VIBRATE_MAXFREQUENCY (KD_IOGROUP_VIBRATE + 2)
+#define KD_OUTPUT_VIBRATE_VOLUME (KD_IOGROUP_VIBRATE + 3)
+#define KD_OUTPUT_VIBRATE_FREQUENCY (KD_IOGROUP_VIBRATE + 4)
+
+/* KD_IOGROUP_POINTER: I/O group for pointer. */
+#define KD_IOGROUP_POINTER 0x4000
+#define KD_STATE_POINTER_AVAILABILITY (KD_IOGROUP_POINTER + 0)
+#define KD_INPUT_POINTER_X (KD_IOGROUP_POINTER + 1)
+#define KD_INPUT_POINTER_Y (KD_IOGROUP_POINTER + 2)
+#define KD_INPUT_POINTER_SELECT (KD_IOGROUP_POINTER + 3)
+
+/* KD_IOGROUP_BACKLIGHT: I/O group for backlight. */
+#define KD_IOGROUP_BACKLIGHT 0x5000
+#define KD_STATE_BACKLIGHT_AVAILABILITY (KD_IOGROUP_BACKLIGHT + 0)
+#define KD_OUTPUT_BACKLIGHT_FORCE (KD_IOGROUP_BACKLIGHT + 1)
+
+/* KD_IOGROUP_JOGDIAL: I/O group for a jog dial. */
+#define KD_IOGROUP_JOGDIAL 0x6000
+#define KD_STATE_JOGDIAL_AVAILABILITY (KD_IOGROUP_JOGDIAL + 0)
+#define KD_INPUT_JOGDIAL_UP (KD_IOGROUP_JOGDIAL + 1)
+#define KD_INPUT_JOGDIAL_LEFT (KD_IOGROUP_JOGDIAL + 2)
+#define KD_INPUT_JOGDIAL_RIGHT (KD_IOGROUP_JOGDIAL + 3)
+#define KD_INPUT_JOGDIAL_DOWN (KD_IOGROUP_JOGDIAL + 4)
+#define KD_INPUT_JOGDIAL_SELECT (KD_IOGROUP_JOGDIAL + 5)
+
+/* KD_IOGROUP_STICK: I/O group for joystick. */
+#define KD_IOGROUP_STICK 0x7000
+#define KD_STATE_STICK_AVAILABILITY (KD_IOGROUP_STICK + 0)
+#define KD_INPUT_STICK_X (KD_IOGROUP_STICK + 1)
+#define KD_INPUT_STICK_Y (KD_IOGROUP_STICK + 2)
+#define KD_INPUT_STICK_Z (KD_IOGROUP_STICK + 3)
+#define KD_INPUT_STICK_BUTTON (KD_IOGROUP_STICK + 4)
+#define KD_IO_STICK_STRIDE 8
+
+/* KD_IOGROUP_DPAD: I/O group for D-pad. */
+#define KD_IOGROUP_DPAD 0x8000
+#define KD_STATE_DPAD_AVAILABILITY (KD_IOGROUP_DPAD + 0)
+#define KD_STATE_DPAD_COPY (KD_IOGROUP_DPAD + 1)
+#define KD_INPUT_DPAD_UP (KD_IOGROUP_DPAD + 2)
+#define KD_INPUT_DPAD_LEFT (KD_IOGROUP_DPAD + 3)
+#define KD_INPUT_DPAD_RIGHT (KD_IOGROUP_DPAD + 4)
+#define KD_INPUT_DPAD_DOWN (KD_IOGROUP_DPAD + 5)
+#define KD_INPUT_DPAD_SELECT (KD_IOGROUP_DPAD + 6)
+#define KD_IO_DPAD_STRIDE 8
+
+/* KD_IOGROUP_BUTTONS: I/O group for buttons associated with joystick or D-pad. */
+#define KD_IOGROUP_BUTTONS 0x9000
+#define KD_STATE_BUTTONS_AVAILABILITY (KD_IOGROUP_BUTTONS + 0)
+#define KD_INPUT_BUTTONS_0 (KD_IOGROUP_BUTTONS + 1)
+
+/* KD_IO_UNDEFINED: I/O items reserved for implementation-dependent use. */
+#define KD_IO_UNDEFINED 0x40000000
+
+/*******************************************************
+ * Windowing
+ *******************************************************/
+#ifdef KD_WINDOW_SUPPORTED
+#include <EGL/egl.h>
+typedef struct KDWindow KDWindow;
+
+/* kdCreateWindow: Create a window. */
+KD_API KDWindow *KD_APIENTRY kdCreateWindow(EGLDisplay display, EGLConfig config, void *eventuserptr);
+
+/* kdDestroyWindow: Destroy a window. */
+KD_API KDint KD_APIENTRY kdDestroyWindow(KDWindow *window);
+
+/* kdSetWindowPropertybv, kdSetWindowPropertyiv, kdSetWindowPropertycv: Set a window property to request a change in the on-screen representation of the window. */
+KD_API KDint KD_APIENTRY kdSetWindowPropertybv(KDWindow *window, KDint pname, const KDboolean *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertyiv(KDWindow *window, KDint pname, const KDint32 *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertycv(KDWindow *window, KDint pname, const KDchar *param);
+
+/* kdGetWindowPropertybv, kdGetWindowPropertyiv, kdGetWindowPropertycv: Get the current value of a window property. */
+KD_API KDint KD_APIENTRY kdGetWindowPropertybv(KDWindow *window, KDint pname, KDboolean *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertyiv(KDWindow *window, KDint pname, KDint32 *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertycv(KDWindow *window, KDint pname, KDchar *param, KDsize *size);
+
+/* kdRealizeWindow: Realize the window as a displayable entity and get the native window handle for passing to EGL. */
+KD_API KDint KD_APIENTRY kdRealizeWindow(KDWindow *window, EGLNativeWindowType *nativewindow);
+
+/* KD_WINDOWPROPERTY_SIZE: Window client area width and height. */
+#define KD_WINDOWPROPERTY_SIZE 66
+
+/* KD_WINDOWPROPERTY_VISIBILITY: Window visibility status. */
+#define KD_WINDOWPROPERTY_VISIBILITY 67
+
+/* KD_WINDOWPROPERTY_FOCUS: Window input focus status. */
+#define KD_WINDOWPROPERTY_FOCUS 68
+
+/* KD_WINDOWPROPERTY_CAPTION: Window caption. */
+#define KD_WINDOWPROPERTY_CAPTION 69
+
+/* KD_EVENT_WINDOW_CLOSE: Event to request to close window. */
+#define KD_EVENT_WINDOW_CLOSE 44
+
+/* KD_EVENT_WINDOWPROPERTY_CHANGE: Notification about realized window property change. */
+#define KD_EVENT_WINDOWPROPERTY_CHANGE 47
+typedef struct KDEventWindowProperty {
+ KDint32 pname;
+} KDEventWindowProperty;
+
+/* KD_EVENT_WINDOW_FOCUS: Event for change of window&#8217;s focus state. */
+#define KD_EVENT_WINDOW_FOCUS 60
+typedef struct KDEventWindowFocus {
+ KDint32 focusstate;
+} KDEventWindowFocus;
+
+/* KD_EVENT_WINDOW_REDRAW: Event to notify need to redraw the window. */
+#define KD_EVENT_WINDOW_REDRAW 59
+#endif /* KD_WINDOW_SUPPORTED */
+
+/*******************************************************
+ * Assertions and logging
+ *******************************************************/
+
+/* kdHandleAssertion: Handle assertion failure. */
+KD_API void KD_APIENTRY kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber);
+
+/* kdLogMessage: Output a log message. */
+#ifdef KD_NDEBUG
+#define kdLogMessage(s)
+#else
+KD_API void KD_APIENTRY kdLogMessage(const KDchar *string);
+#endif
+
+/* struct KDEvent delayed to the end as it uses event data structs from
+ * other parts of the .h file. */
+struct KDEvent {
+ KDust timestamp;
+ KDint32 type;
+ void *userptr;
+ union KDEventData {
+ KDEventState state;
+ KDEventInput input;
+ KDEventInputJog inputjog;
+ KDEventInputPointer inputpointer;
+ KDEventInputStick inputstick;
+ KDEventSocketReadable socketreadable;
+ KDEventSocketWritable socketwritable;
+ KDEventSocketConnect socketconnect;
+ KDEventSocketIncoming socketincoming;
+ KDEventNameLookup namelookup;
+#ifdef KD_WINDOW_SUPPORTED
+ KDEventWindowProperty windowproperty;
+ KDEventWindowFocus windowfocus;
+#endif /* KD_WINDOW_SUPPORTED */
+ KDEventUser user;
+ } data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kdplatform.h b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kdplatform.h
new file mode 100644
index 00000000..aba94c28
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs/KD/kdplatform.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Sample KD/kdplatform.h for OpenKODE Core 1.0.3 */
+#ifndef __kdplatform_h_
+#define __kdplatform_h_
+
+#define KD_API
+#define KD_APIENTRY
+
+typedef int KDint32;
+typedef unsigned int KDuint32;
+typedef long long KDint64;
+typedef unsigned long long KDuint64;
+typedef short KDint16;
+typedef unsigned short KDuint16;
+typedef unsigned long KDuintptr;
+typedef unsigned long KDsize;
+typedef long KDssize;
+#define KDINT_MIN (-0x7fffffff-1)
+#define KDINT_MAX 0x7fffffff
+#define KDUINT_MAX 0xffffffffU
+#define KDINT64_MIN (-0x7fffffffffffffffLL-1)
+#define KDINT64_MAX 0x7fffffffffffffffLL
+#define KDUINT64_MAX 0xffffffffffffffffULL
+#define KDSSIZE_MIN (-0x7fffffff-1)
+#define KDSSIZE_MAX 0x7fffffff
+#define KDSIZE_MAX 0xffffffffU
+#define KDUINTPTR_MAX 0xffffffffU
+#define KD_NORETURN
+
+// no EGL on macOS
+//#define KD_WINDOW_SUPPORTED
+
+#ifdef KD_NDEBUG
+#define kdAssert(c)
+#else
+#define kdAssert(c) ((void)( (c) ? 0 : (kdHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+#define KD_INFINITY_BITS 0x7f800000u
+#define KD_INFINITY (kdBitsToFloatNV(KD_INFINITY_BITS))
+
+KD_API float KD_APIENTRY kdBitsToFloatNV(KDuint32 x);
+
+
+/** KHR_formatted extension */
+#include <stdarg.h>
+typedef va_list KDVaListKHR;
+
+// If there are problems with including stdarg.h here under any of the Windows
+// operating systems, we might want to change it back to using char* instead of
+// va_list
+//typedef char *KDVaListKHR;
+
+
+#define KD_VA_START_KHR(ap, parmN) \
+ do {ap = (KDVaListKHR)&parmN + sizeof(parmN);} while(0)
+
+#define KD_VA_ARG_CHAR_KHR(ap) (KDchar)va_arg(ap, KDint)
+#define KD_VA_ARG_CHARPTR_KHR(ap) (KDchar*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16_KHR(ap) (KDint16)va_arg(ap, KDint)
+#define KD_VA_ARG_INT32_KHR(ap) va_arg(ap, KDint32)
+#define KD_VA_ARG_INT_KHR(ap) va_arg(ap, KDint)
+#define KD_VA_ARG_INT64_KHR(ap) va_arg(ap, KDint64)
+#define KD_VA_ARG_INTPTR_KHR(ap) (KDint*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16PTR_KHR(ap) (KDint16*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_FLOAT32_KHR(ap) (KDfloat32)(va_arg(ap, double))
+#define KD_VA_ARG_PTR_KHR(ap) (void *)va_arg(ap, char *)
+
+#define KD_VA_END_KHR(ap) \
+ do {ap = (KDVaListKHR)0;} while(0)
+
+#endif /* __kdplatform_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/MinKD.c b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/MinKD.c
new file mode 100644
index 00000000..29c4f476
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/MinKD.c
@@ -0,0 +1,326 @@
+#include "kd.h"
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <memory.h>
+#include <pthread.h>
+#include <dirent.h>
+
+#include <mach/mach_time.h>
+
+
+KDFile* kdFopen(const KDchar* pathname, const KDchar* mode)
+{
+ FILE* retval;
+ retval = fopen( pathname, mode );
+ return (KDFile*)retval;
+}
+
+
+KDsize kdFread(void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fread( buffer, size, count, (FILE*)file );
+}
+
+/* kdFwrite: Write to a file. */
+KDsize kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fwrite( buffer, size, count, (FILE*)file );
+}
+
+KDint kdFclose(KDFile *file)
+{
+ return fclose( (FILE*)file );
+}
+
+/* kdCosf: Cosine function. */
+KDfloat32 kdCosf(KDfloat32 x) { return cosf( x ); }
+
+/* kdSinf: Sine function. */
+KDfloat32 kdSinf(KDfloat32 x) { return sinf( x ); }
+
+KDfloat32 kdSqrtf(KDfloat32 x ) { return sqrtf( x ); }
+
+KDfloat32 kdTanf( KDfloat32 x ) { return tanf( x ); }
+
+KDint kdAbs(KDint i)
+{
+ return i < 0 ? -i : i;
+}
+
+
+KDfloat32 kdFabsf(KDfloat32 i) { return fabs( i ); }
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+
+KDint kdStrcpy_s(KDchar* buf, KDsize buflen, const KDchar* src)
+{
+ return kdStrncpy_s(buf, buflen, src, -1);
+}
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KDint kdStrncpy_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srclen)
+{
+ if ( srclen == (KDsize)-1)
+ srclen = buflen;
+ const char* term = memchr(src, 0, srclen);
+ if (term)
+ srclen = term - src;
+ if (srclen >= buflen) {
+ if (buflen)
+ *buf = 0;
+ return KD_EINVAL;
+ }
+ memcpy(buf, src, srclen);
+ buf[srclen] = 0;
+ return 0;
+}
+
+/* kdStrncat_s: Concatenate two strings. */
+KDint kdStrncat_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srcmaxlen)
+{
+ size_t origlen = strlen(buf);
+ const char* p = memchr(src, 0, srcmaxlen);
+ if (p)
+ srcmaxlen = p - src;
+ if (origlen + srcmaxlen >= buflen)
+ {
+ /* spec says "buf[0] is set to 0". But that's bad if buflen == 0!
+ * kdStrncpy_s's spec is better here. */
+ if (buflen)
+ buf[0] = 0;
+ return KD_ERANGE;
+ }
+ memcpy(buf + origlen, src, srcmaxlen);
+ buf[origlen + srcmaxlen] = 0;
+ return 0;
+}
+/* kdMemset: Set bytes in memory to a value. */
+void* kdMemset(void *buf, KDint byte, KDsize len) { return memset( buf, byte, len ); }
+
+/* kdStrcmp: Compares two strings. */
+KDint kdStrcmp(const KDchar *str1, const KDchar *str2) { return strcmp( str1, str2); }
+
+/* kdStrlen: Determine the length of a string. */
+KDsize kdStrlen(const KDchar *str) { return strlen( str ); }
+
+void* kdMalloc( KDsize size ) { return malloc(size); }
+
+void kdFree( void* ptr ) { free( ptr ); }
+
+void* kdMemcpy(void *buf, const void *src, KDsize len) { return memcpy( buf, src, len ); }
+
+struct KDThreadMutex
+{
+ pthread_mutex_t p_mutex;
+};
+
+/* kdThreadMutexCreate: Create a mutex. */
+KD_API KDThreadMutex* kdThreadMutexCreate(const void *mutexattr)
+{
+ KDThreadMutex* mutex = malloc(sizeof(KDThreadMutex));
+ if (mutex)
+ {
+ if (pthread_mutex_init(&mutex->p_mutex, NULL) == 0)
+ {
+ return mutex;
+ }
+ free(mutex);
+ }
+
+ return KD_NULL;
+}
+
+/* kdThreadMutexFree: Free a mutex. */
+KDint kdThreadMutexFree(KDThreadMutex *mutex)
+{
+ int res;
+ res = pthread_mutex_destroy(&mutex->p_mutex);
+ // If the mutex destroy failed, don't free the memory.
+ // Per OpenKODE spec, this is undefined behaviour, and
+ // we can leak the memory. The reason for this is that
+ // later allocations may fail if they happen to go
+ // to the same memory
+ if (!res)
+ free(mutex);
+ return 0;
+}
+
+/* kdThreadMutexLock: Lock a mutex. */
+KDint kdThreadMutexLock(KDThreadMutex *mutex)
+{
+ (void)pthread_mutex_lock(&mutex->p_mutex);
+ return 0;
+}
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KDint kdThreadMutexUnlock(KDThreadMutex *mutex)
+{
+ pthread_mutex_unlock(&mutex->p_mutex);
+ return 0;
+}
+
+struct KDThreadAttr
+{
+ pthread_attr_t p_attr;
+};
+
+struct KDThread
+{
+ pthread_t Handle;
+ uint8_t Detached;
+ uint8_t IsRunning;
+ uint8_t UserThread;
+ void* (*UserThreadProc)(void*);
+ void* UserArg;
+};
+/* kdThreadCreate: Create a new thread. */
+KDThread * kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg)
+{
+ pthread_t thread;
+ int retval;
+ const pthread_attr_t* p_attr;
+ if ( attr )
+ p_attr = &attr->p_attr;
+ else
+ p_attr = KD_NULL;
+
+ retval = pthread_create( &thread, p_attr, start_routine, arg );
+ if ( retval != 0 )
+ {
+ return KD_NULL;
+ }
+ KDThread* newThread = (KDThread*)malloc( sizeof( KDThread ) );
+ if ( newThread == KD_NULL ) return KD_NULL;
+ newThread->Handle = thread;
+ newThread->Detached = 0;
+ newThread->IsRunning = 1;
+ newThread->UserThread = 1;
+ newThread->UserThreadProc = start_routine;
+ newThread->UserArg = arg;
+ return newThread;
+}
+
+/* kdThreadExit: Terminate this thread. */
+void kdThreadExit(void *retval)
+{
+ pthread_exit( retval );
+}
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KDint kdThreadJoin(KDThread *thread, void **retval)
+{
+ int join_retval;
+ join_retval = pthread_join( thread->Handle, retval );
+ if ( join_retval == 0 ) free( thread );
+ return join_retval;
+}
+
+typedef struct KDDirInternal {
+ DIR *dir;
+ KDDirent ent;
+} KDDirInternal;
+
+/* kdOpenDir: Open a directory ready for listing. */
+KDDir *kdOpenDir(const KDchar *pathname)
+{
+ DIR* dir = opendir( pathname );
+ if ( dir == KD_NULL ) return KD_NULL;
+ KDDirInternal* retval = (KDDirInternal*)malloc( sizeof( KDDirInternal ));
+ if ( retval == KD_NULL ) return KD_NULL;
+ memset( retval, 0, sizeof( *retval ) );
+ retval->dir = dir;
+ return (KDDir*)retval;
+}
+
+/* kdReadDir: Return the next file in a directory. */
+KDDirent* kdReadDir(KDDir *dir)
+{
+ struct dirent *sysDirEnt;
+ KDDirent *dirent = NULL;
+
+ sysDirEnt = readdir(((KDDirInternal *)dir)->dir);
+
+ if (sysDirEnt) {
+ dirent = &((KDDirInternal *)dir)->ent;
+ dirent->d_name = sysDirEnt->d_name;
+ }
+ return dirent;
+}
+
+/* kdCloseDir: Close a directory. */
+KDint kdCloseDir(KDDir *dir)
+{
+ closedir(((KDDirInternal *)dir)->dir);
+ free(dir);
+ return 0;
+}
+
+#if 0
+KDint kdSetWindowPropertyiv(KDWindow * win, KDint prop, const KDint32 * val)
+{
+ return 0;
+}
+#endif
+
+void kdDefaultEvent(const KDEvent *event )
+{
+
+}
+
+typedef long long NvS64;
+
+KDust kdGetTimeUST(void)
+{
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+
+ uint64_t time = mach_absolute_time();
+
+ // convert to nanoseconds
+ time *= info.numer;
+ time /= info.denom;
+
+ return (NvS64)time;
+}
+
+static KDTm* gmlocaltime(
+ const KDtime *timep,
+ KDTm *result,
+ struct tm* (* func)(const time_t* timep, struct tm* result))
+{
+ struct tm tm;
+ time_t t = *timep;
+ (*func)(&t, &tm);
+ result->tm_sec = tm.tm_sec;
+ result->tm_min = tm.tm_min;
+ result->tm_hour = tm.tm_hour;
+ result->tm_mday = tm.tm_mday;
+ result->tm_mon = tm.tm_mon;
+ result->tm_year = tm.tm_year;
+ result->tm_wday = tm.tm_wday;
+ result->tm_yday = tm.tm_yday;
+ return result;
+}
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+KDTm* kdGmtime_r(const KDtime* timep, KDTm* result)
+{
+ return gmlocaltime(timep, result, &gmtime_r);
+}
+
+KDTm* kdLocaltime_r(const KDtime* timep, KDTm* result)
+{
+ return gmlocaltime(timep, result, &localtime_r);
+}
+
+//===========================================================================
+// kdCreateEvent: Create an event for posting.
+//===========================================================================
+KDEvent* kdCreateEvent(void)
+{
+ //Memory leak and there isn't much I am going to do about this now
+ KDEvent* newEvent = (KDEvent*)malloc( sizeof( KDEvent ));
+ memset( newEvent, 0, sizeof( KDEvent ));
+ return newEvent;
+}
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_extwindowprops.h b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_extwindowprops.h
new file mode 100644
index 00000000..4428a568
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_extwindowprops.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_extwindowprops_h_
+#define __kd_QT3DS_extwindowprops_h_
+#include <KD/kd.h>
+#include <EGL/eglext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_WINDOWPROPERTY_FULLSCREEN: Control over resizing a window to fill the complete screen */
+
+// KDboolean - set the window to fullscreen mode
+#define KD_WINDOWPROPERTY_FULLSCREEN_QT3DS 9999
+
+// KDint - set which KD_DISPLAY_* display that the window should be opened on
+#define KD_WINDOWPROPERTY_DISPLAY_QT3DS 9998
+
+// KDboolean - sets whether overlay should be used to create window
+#define KD_WINDOWPROPERTY_OVERLAY_QT3DS 9997
+
+#define KD_DISPLAY_PRIMARY_QT3DS 0
+#define KD_DISPLAY_INTERNAL0_QT3DS 0
+#define KD_DISPLAY_INTERNAL1_QT3DS 1
+#define KD_DISPLAY_INTERNAL2_QT3DS 2
+#define KD_DISPLAY_INTERNAL3_QT3DS 3
+#define KD_DISPLAY_EXTERNAL0_QT3DS 1000
+#define KD_DISPLAY_EXTERNAL1_QT3DS 1001
+#define KD_DISPLAY_EXTERNAL2_QT3DS 1002
+#define KD_DISPLAY_EXTERNAL3_QT3DS 1003
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_extwindowprops_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_multitouch.h b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_multitouch.h
new file mode 100644
index 00000000..e230b029
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/Qt3DS_multitouch.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_multitouch_h_
+#define __kd_QT3DS_multitouch_h_
+#include <KD/kd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_IOGROUP_MULTITOUCH: I/O group for Multitouch input devices. */
+#define KD_IOGROUP_MULTITOUCH_QT3DS 0x40004000
+#define KD_STATE_MULTITOUCH_AVAILABILITY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 0)
+#define KD_INPUT_MULTITOUCH_FINGERS_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 1)
+#define KD_INPUT_MULTITOUCH_WIDTH_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 2)
+#define KD_INPUT_MULTITOUCH_X_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 3)
+#define KD_INPUT_MULTITOUCH_Y_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 4)
+#define KD_INPUT_MULTITOUCH_X2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 5)
+#define KD_INPUT_MULTITOUCH_Y2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 6)
+#define KD_INPUT_MULTITOUCH_PRESSURE_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 7)
+#define KD_INPUT_MULTITOUCH_GESTURES_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 8)
+#define KD_INPUT_MULTITOUCH_RELX_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 9)
+#define KD_INPUT_MULTITOUCH_RELY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 10)
+
+/* KD_EVENT_INPUT_MULTITOUCH_QT3DS: Multitouch event. */
+#define KD_EVENT_INPUT_MULTITOUCH_QT3DS 1001
+typedef struct KDEventInputMultitouchDataNV
+{
+ KDint32 index;
+ KDint8 fingers;
+ KDint8 width;
+ KDint16 x;
+ KDint16 y;
+ KDint16 x2;
+ KDint16 y2;
+ KDint16 pressure;
+} KDEventInputMultitouchDataNV;
+
+/* KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS: Multitouch gesture event. */
+#define KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS 1002
+
+/* kdGetEventInputMultitouchDataNV: Get auxiliary event data for multitouch input. */
+KD_API KDint KD_APIENTRY kdGetEventInputMultitouchDataNV(const KDEvent *event,
+ KDEventInputMultitouchDataNV *data);
+
+/* kdSetEventInputMultitouchActiveNV: Activate Multitouch input events */
+KD_API KDint KD_APIENTRY kdSetEventInputMultitouchActiveNV(KDboolean activate);
+
+/* kdEnableEventInputMultitouchMergeNV: Activate merging of Multitouch input events */
+KD_API void KD_APIENTRY kdEnableEventInputMultitouchMergeNV(KDboolean enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_multitouch_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kd.h b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kd.h
new file mode 100644
index 00000000..f7ccea03
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kd.h
@@ -0,0 +1,991 @@
+/* Reference KD/kd.h for OpenKODE Core 1.0.3 */
+#ifndef __kd_h_
+#define __kd_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kdplatform.h"
+
+
+
+/*******************************************************
+ * Introduction
+ *******************************************************/
+
+/*******************************************************
+ * OpenKODE conformance
+ *******************************************************/
+
+/*******************************************************
+ * Overview
+ *******************************************************/
+
+/*******************************************************
+ * Programming environment
+ *******************************************************/
+#define KD_VERSION_1_0 1
+typedef char KDchar;
+typedef signed char KDint8;
+typedef unsigned char KDuint8;
+typedef int KDint;
+typedef unsigned int KDuint;
+typedef float KDfloat32;
+typedef KDint KDboolean;
+typedef KDint64 KDtime;
+typedef KDint64 KDust;
+typedef KDint64 KDoff;
+typedef KDuint32 KDmode;
+#define KDINT32_MIN (-0x7fffffff-1)
+#define KDINT32_MAX 0x7fffffff
+#define KDUINT32_MAX 0xffffffffU
+#define KD_TRUE 1
+#define KD_FALSE 0
+#ifdef __cplusplus
+ const int KD_NULL = 0; /* Yes, int. See Stroustrup 3rd edition. */
+#else
+ #define KD_NULL ((void *)0)
+#endif
+
+/*******************************************************
+ * Errors
+ *******************************************************/
+#define KD_EACCES 1
+#define KD_EADDRINUSE 2
+#define KD_EADDRNOTAVAIL 3
+#define KD_EAFNOSUPPORT 4
+#define KD_EAGAIN (5)
+#define KD_EALREADY 6
+#define KD_EBADF 7
+#define KD_EBUSY 8
+#define KD_ECONNREFUSED 9
+#define KD_ECONNRESET 10
+#define KD_EDEADLK 11
+#define KD_EDESTADDRREQ 12
+#define KD_EEXIST 13
+#define KD_EFBIG 14
+#define KD_EHOSTUNREACH 15
+#define KD_EHOST_NOT_FOUND 16
+#define KD_EINVAL 17
+#define KD_EIO 18
+#define KD_EILSEQ 19
+#define KD_EISCONN 20
+#define KD_EISDIR 21
+#define KD_EMFILE 22
+#define KD_ENAMETOOLONG 23
+#define KD_ENOENT 24
+#define KD_ENOMEM 25
+#define KD_ENOSPC 26
+#define KD_ENOSYS 27
+#define KD_ENOTCONN 28
+#define KD_ENO_DATA 29
+#define KD_ENO_RECOVERY 30
+#define KD_EOPNOTSUPP 31
+#define KD_EOVERFLOW 32
+#define KD_EPERM 33
+#define KD_ERANGE 35
+#define KD_ETIMEDOUT (36)
+#define KD_ETRY_AGAIN 37
+
+/* kdGetError: Get last error indication. */
+KD_API KDint KD_APIENTRY kdGetError(void);
+
+/* kdSetError: Set last error indication. */
+KD_API void KD_APIENTRY kdSetError(KDint error);
+
+/*******************************************************
+ * Versioning and attribute queries
+ *******************************************************/
+
+/* kdQueryAttribi: Obtain the value of a numeric OpenKODE Core attribute. */
+KD_API KDint KD_APIENTRY kdQueryAttribi(KDint attribute, KDint *value);
+
+/* kdQueryAttribcv: Obtain the value of a string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryAttribcv(KDint attribute);
+#define KD_ATTRIB_VENDOR 39
+#define KD_ATTRIB_VERSION 40
+#define KD_ATTRIB_PLATFORM 41
+
+/* kdQueryIndexedAttribcv: Obtain the value of an indexed string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryIndexedAttribcv(KDint attribute, KDint index);
+
+/*******************************************************
+ * Threads and synchronization
+ *******************************************************/
+
+/* kdThreadAttrCreate: Create a thread attribute object. */
+typedef struct KDThreadAttr KDThreadAttr;
+KD_API KDThreadAttr *KD_APIENTRY kdThreadAttrCreate(void);
+
+/* kdThreadAttrFree: Free a thread attribute object. */
+KD_API KDint KD_APIENTRY kdThreadAttrFree(KDThreadAttr *attr);
+
+/* kdThreadAttrSetDetachState: Set detachstate attribute. */
+#define KD_THREAD_CREATE_JOINABLE 0
+#define KD_THREAD_CREATE_DETACHED 1
+KD_API KDint KD_APIENTRY kdThreadAttrSetDetachState(KDThreadAttr *attr, KDint detachstate);
+
+/* kdThreadAttrSetStackSize: Set stacksize attribute. */
+KD_API KDint KD_APIENTRY kdThreadAttrSetStackSize(KDThreadAttr *attr, KDsize stacksize);
+
+/* kdThreadCreate: Create a new thread. */
+typedef struct KDThread KDThread;
+KD_API KDThread *KD_APIENTRY kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg);
+
+/* kdThreadExit: Terminate this thread. */
+KD_API KD_NORETURN void KD_APIENTRY kdThreadExit(void *retval);
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KD_API KDint KD_APIENTRY kdThreadJoin(KDThread *thread, void **retval);
+
+/* kdThreadDetach: Allow resources to be freed as soon as a thread terminates. */
+KD_API KDint KD_APIENTRY kdThreadDetach(KDThread *thread);
+
+/* kdThreadSelf: Return calling thread&#8217;s ID. */
+KD_API KDThread *KD_APIENTRY kdThreadSelf(void);
+
+/* kdThreadOnce: Wrap initialization code so it is executed only once. */
+#ifndef KD_NO_STATIC_DATA
+typedef struct KDThreadOnce {
+ void *impl;
+} KDThreadOnce;
+#define KD_THREAD_ONCE_INIT { 0 }
+KD_API KDint KD_APIENTRY kdThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void));
+#endif /* ndef KD_NO_STATIC_DATA */
+
+/* kdThreadMutexCreate: Create a mutex. */
+typedef struct KDThreadMutex KDThreadMutex;
+KD_API KDThreadMutex *KD_APIENTRY kdThreadMutexCreate(const void *mutexattr);
+
+/* kdThreadMutexFree: Free a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexFree(KDThreadMutex *mutex);
+
+/* kdThreadMutexLock: Lock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexLock(KDThreadMutex *mutex);
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexUnlock(KDThreadMutex *mutex);
+
+/* kdThreadCondCreate: Create a condition variable. */
+typedef struct KDThreadCond KDThreadCond;
+KD_API KDThreadCond *KD_APIENTRY kdThreadCondCreate(const void *attr);
+
+/* kdThreadCondFree: Free a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondFree(KDThreadCond *cond);
+
+/* kdThreadCondSignal, kdThreadCondBroadcast: Signal a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondSignal(KDThreadCond *cond);
+KD_API KDint KD_APIENTRY kdThreadCondBroadcast(KDThreadCond *cond);
+
+/* kdThreadCondWait: Wait for a condition variable to be signalled. */
+KD_API KDint KD_APIENTRY kdThreadCondWait(KDThreadCond *cond, KDThreadMutex *mutex);
+
+/* kdThreadSemCreate: Create a semaphore. */
+typedef struct KDThreadSem KDThreadSem;
+KD_API KDThreadSem *KD_APIENTRY kdThreadSemCreate(KDuint value);
+
+/* kdThreadSemFree: Free a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemFree(KDThreadSem *sem);
+
+/* kdThreadSemWait: Lock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemWait(KDThreadSem *sem);
+
+/* kdThreadSemPost: Unlock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemPost(KDThreadSem *sem);
+
+/*******************************************************
+ * Events
+ *******************************************************/
+
+/* KDEvent: Struct type containing an event. */
+typedef struct KDEvent KDEvent;
+#define KD_EVENT_USER 0x40000000
+
+/* kdWaitEvent: Get next event from thread&#8217;s event queue. */
+KD_API const KDEvent *KD_APIENTRY kdWaitEvent(KDust timeout);
+
+/* kdSetEventUserptr: Set the userptr for global events. */
+KD_API void KD_APIENTRY kdSetEventUserptr(void *userptr);
+
+/* kdDefaultEvent: Perform default processing on an unrecognized event. */
+KD_API void KD_APIENTRY kdDefaultEvent(const KDEvent *event);
+
+/* kdPumpEvents: Pump the thread&#8217;s event queue, performing callbacks. */
+KD_API KDint KD_APIENTRY kdPumpEvents(void);
+
+/* kdInstallCallback: Install or remove a callback function for event processing. */
+typedef void (KD_APIENTRY KDCallbackFunc)(const KDEvent *event);
+KD_API KDint KD_APIENTRY kdInstallCallback(KDCallbackFunc *func, KDint eventtype, void *eventuserptr);
+
+/* kdCreateEvent: Create an event for posting. */
+KD_API KDEvent *KD_APIENTRY kdCreateEvent(void);
+
+/* kdPostEvent, kdPostThreadEvent: Post an event into a queue. */
+KD_API KDint KD_APIENTRY kdPostEvent(KDEvent *event);
+KD_API KDint KD_APIENTRY kdPostThreadEvent(KDEvent *event, KDThread *thread);
+typedef struct KDEventUser {
+ union {
+ KDint64 i64;
+ void *p;
+ struct {
+ KDint32 a;
+ KDint32 b;
+ } i32pair;
+ } value1;
+ union {
+ KDint64 i64;
+ struct {
+ union {
+ KDint32 i32;
+ void *p;
+ } value2;
+ union {
+ KDint32 i32;
+ void *p;
+ } value3;
+ } i32orp;
+ } value23;
+} KDEventUser;
+
+/* kdFreeEvent: Abandon an event instead of posting it. */
+KD_API void KD_APIENTRY kdFreeEvent(KDEvent *event);
+
+/*******************************************************
+ * System events
+ *******************************************************/
+
+/* KD_EVENT_QUIT: Event to request to quit application. */
+#define KD_EVENT_QUIT 43
+
+/* KD_EVENT_PAUSE: Application pause event. */
+#define KD_EVENT_PAUSE 45
+
+/* KD_EVENT_RESUME: Application resume event. */
+#define KD_EVENT_RESUME 46
+
+/* KD_EVENT_ORIENTATION: Orientation change event. */
+#define KD_EVENT_ORIENTATION 48
+
+/* KD_IOGROUP_EVENT: I/O group for OpenKODE Core system events implemented as state values. */
+#define KD_IOGROUP_EVENT 0x100
+#define KD_STATE_EVENT_USING_BATTERY (KD_IOGROUP_EVENT + 0)
+#define KD_STATE_EVENT_LOW_BATTERY (KD_IOGROUP_EVENT + 1)
+
+
+/* KD_IOGROUP_ORIENTATION: I/O group for OpenKODE Core orientation state. */
+#define KD_IOGROUP_ORIENTATION 0x200
+#define KD_STATE_ORIENTATION_OVERALL (KD_IOGROUP_ORIENTATION + 0)
+#define KD_STATE_ORIENTATION_SCREEN (KD_IOGROUP_ORIENTATION + 1)
+#define KD_STATE_ORIENTATION_RENDERING (KD_IOGROUP_ORIENTATION + 2)
+#define KD_STATE_ORIENTATION_LOCKSURFACE (KD_IOGROUP_ORIENTATION + 3)
+
+
+/*******************************************************
+ * Application startup and exit.
+ *******************************************************/
+
+/* kdMain: The application-defined main function. */
+KDint KD_APIENTRY kdMain(KDint argc, const KDchar *const *argv);
+
+/* kdExit: Exit the application. */
+KD_API KD_NORETURN void KD_APIENTRY kdExit(KDint status);
+
+/*******************************************************
+ * Utility library functions
+ *******************************************************/
+
+/* kdAbs: Compute the absolute value of an integer. */
+KD_API KDint KD_APIENTRY kdAbs(KDint i);
+
+/* kdStrtof: Convert a string to a floating point number. */
+KD_API KDfloat32 KD_APIENTRY kdStrtof(const KDchar *s, KDchar **endptr);
+
+/* kdStrtol, kdStrtoul: Convert a string to an integer. */
+KD_API KDint KD_APIENTRY kdStrtol(const KDchar *s, KDchar **endptr, KDint base);
+KD_API KDuint KD_APIENTRY kdStrtoul(const KDchar *s, KDchar **endptr, KDint base);
+
+/* kdLtostr, kdUltostr: Convert an integer to a string. */
+#define KD_LTOSTR_MAXLEN ((sizeof(KDint)*8*3+6)/10+2)
+#define KD_ULTOSTR_MAXLEN ((sizeof(KDint)*8+2)/3+1)
+KD_API KDssize KD_APIENTRY kdLtostr(KDchar *buffer, KDsize buflen, KDint number);
+KD_API KDssize KD_APIENTRY kdUltostr(KDchar *buffer, KDsize buflen, KDuint number, KDint base);
+
+/* kdFtostr: Convert a float to a string. */
+#define KD_FTOSTR_MAXLEN 16
+KD_API KDssize KD_APIENTRY kdFtostr(KDchar *buffer, KDsize buflen, KDfloat32 number);
+
+/* kdCryptoRandom: Return random data. */
+KD_API KDint KD_APIENTRY kdCryptoRandom(KDuint8 *buf, KDsize buflen);
+
+/*******************************************************
+ * Locale specific functions
+ *******************************************************/
+
+/* kdGetLocale: Determine the current language and locale. */
+KD_API const KDchar *KD_APIENTRY kdGetLocale(void);
+
+/*******************************************************
+ * Memory allocation
+ *******************************************************/
+
+/* kdMalloc: Allocate memory. */
+KD_API void *KD_APIENTRY kdMalloc(KDsize size);
+
+/* kdFree: Free allocated memory block. */
+KD_API void KD_APIENTRY kdFree(void *ptr);
+
+/* kdRealloc: Resize memory block. */
+KD_API void *KD_APIENTRY kdRealloc(void *ptr, KDsize size);
+
+/*******************************************************
+ * Thread-local storage.
+ *******************************************************/
+
+/* kdGetTLS: Get the thread-local storage pointer. */
+KD_API void *KD_APIENTRY kdGetTLS(void);
+
+/* kdSetTLS: Set the thread-local storage pointer. */
+KD_API void KD_APIENTRY kdSetTLS(void *ptr);
+
+/*******************************************************
+ * Mathematical functions
+ *******************************************************/
+#define KD_E_F 2.71828175F
+#define KD_PI_F 3.14159274F
+#define KD_PI_2_F 1.57079637F
+#define KD_2PI_F 6.28318548F
+#define KD_LOG2E_F 1.44269502F
+#define KD_LOG10E_F 0.434294492F
+#define KD_LN2_F 0.693147182F
+#define KD_LN10_F 2.30258512F
+#define KD_PI_4_F 0.785398185F
+#define KD_1_PI_F 0.318309873F
+#define KD_2_PI_F 0.636619747F
+#define KD_2_SQRTPI_F 1.12837923F
+#define KD_SQRT2_F 1.41421354F
+#define KD_SQRT1_2_F 0.707106769F
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_FLT_MAX 3.40282346638528860e+38F
+#define KD_FLT_MIN 1.17549435e-38F
+/* KD_INFINITY is defined in kdplatform.h since no portable definition
+ * is possible. */
+#define kdIsNan(x) (((x) != (x)) ? 1 : 0)
+#define KD_HUGE_VALF KD_INFINITY
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+/* kdAcosf: Arc cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdAcosf(KDfloat32 x);
+
+/* kdAsinf: Arc sine function. */
+KD_API KDfloat32 KD_APIENTRY kdAsinf(KDfloat32 x);
+
+/* kdAtanf: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtanf(KDfloat32 x);
+
+/* kdAtan2f: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtan2f(KDfloat32 y, KDfloat32 x);
+
+/* kdCosf: Cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdCosf(KDfloat32 x);
+
+/* kdSinf: Sine function. */
+KD_API KDfloat32 KD_APIENTRY kdSinf(KDfloat32 x);
+
+/* kdTanf: Tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdTanf(KDfloat32 x);
+
+/* kdExpf: Exponential function. */
+KD_API KDfloat32 KD_APIENTRY kdExpf(KDfloat32 x);
+
+/* kdLogf: Natural logarithm function. */
+KD_API KDfloat32 KD_APIENTRY kdLogf(KDfloat32 x);
+
+/* kdFabsf: Absolute value. */
+KD_API KDfloat32 KD_APIENTRY kdFabsf(KDfloat32 x);
+
+/* kdPowf: Power function. */
+KD_API KDfloat32 KD_APIENTRY kdPowf(KDfloat32 x, KDfloat32 y);
+
+/* kdSqrtf: Square root function. */
+KD_API KDfloat32 KD_APIENTRY kdSqrtf(KDfloat32 x);
+
+/* kdCeilf: Return ceiling value. */
+KD_API KDfloat32 KD_APIENTRY kdCeilf(KDfloat32 x);
+
+/* kdFloorf: Return floor value. */
+KD_API KDfloat32 KD_APIENTRY kdFloorf(KDfloat32 x);
+
+/* kdRoundf: Round value to nearest integer. */
+KD_API KDfloat32 KD_APIENTRY kdRoundf(KDfloat32 x);
+
+/* kdInvsqrtf: Inverse square root function. */
+KD_API KDfloat32 KD_APIENTRY kdInvsqrtf(KDfloat32 x);
+
+/* kdFmodf: Calculate floating point remainder. */
+KD_API KDfloat32 KD_APIENTRY kdFmodf(KDfloat32 x, KDfloat32 y);
+
+/*******************************************************
+ * String and memory functions
+ *******************************************************/
+
+/* kdMemchr: Scan memory for a byte value. */
+KD_API void *KD_APIENTRY kdMemchr(const void *src, KDint byte, KDsize len);
+
+/* kdMemcmp: Compare two memory regions. */
+KD_API KDint KD_APIENTRY kdMemcmp(const void *src1, const void *src2, KDsize len);
+
+/* kdMemcpy: Copy a memory region, no overlapping. */
+KD_API void *KD_APIENTRY kdMemcpy(void *buf, const void *src, KDsize len);
+
+/* kdMemmove: Copy a memory region, overlapping allowed. */
+KD_API void *KD_APIENTRY kdMemmove(void *buf, const void *src, KDsize len);
+
+/* kdMemset: Set bytes in memory to a value. */
+KD_API void *KD_APIENTRY kdMemset(void *buf, KDint byte, KDsize len);
+
+/* kdStrchr: Scan string for a byte value. */
+KD_API KDchar *KD_APIENTRY kdStrchr(const KDchar *str, KDint ch);
+
+/* kdStrcmp: Compares two strings. */
+KD_API KDint KD_APIENTRY kdStrcmp(const KDchar *str1, const KDchar *str2);
+
+/* kdStrlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrlen(const KDchar *str);
+
+/* kdStrnlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrnlen(const KDchar *str, KDsize maxlen);
+
+/* kdStrncat_s: Concatenate two strings. */
+KD_API KDint KD_APIENTRY kdStrncat_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srcmaxlen);
+
+/* kdStrncmp: Compares two strings with length limit. */
+KD_API KDint KD_APIENTRY kdStrncmp(const KDchar *str1, const KDchar *str2, KDsize maxlen);
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrcpy_s(KDchar *buf, KDsize buflen, const KDchar *src);
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrncpy_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srclen);
+
+/*******************************************************
+ * Time functions
+ *******************************************************/
+
+/* kdGetTimeUST: Get the current unadjusted system time. */
+KD_API KDust KD_APIENTRY kdGetTimeUST(void);
+
+/* kdTime: Get the current wall clock time. */
+KD_API KDtime KD_APIENTRY kdTime(KDtime *timep);
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+typedef struct KDTm {
+ KDint32 tm_sec;
+ KDint32 tm_min;
+ KDint32 tm_hour;
+ KDint32 tm_mday;
+ KDint32 tm_mon;
+ KDint32 tm_year;
+ KDint32 tm_wday;
+ KDint32 tm_yday;
+} KDTm;
+KD_API KDTm *KD_APIENTRY kdGmtime_r(const KDtime *timep, KDTm *result);
+KD_API KDTm *KD_APIENTRY kdLocaltime_r(const KDtime *timep, KDTm *result);
+
+/* kdUSTAtEpoch: Get the UST corresponding to KDtime 0. */
+KD_API KDust KD_APIENTRY kdUSTAtEpoch(void);
+
+/*******************************************************
+ * Timer functions
+ *******************************************************/
+
+/* kdSetTimer: Set timer. */
+#define KD_TIMER_ONESHOT 61
+#define KD_TIMER_PERIODIC_AVERAGE 62
+#define KD_TIMER_PERIODIC_MINIMUM 63
+typedef struct KDTimer KDTimer;
+KD_API KDTimer *KD_APIENTRY kdSetTimer(KDint64 interval, KDint periodic, void *eventuserptr);
+
+/* kdCancelTimer: Cancel and free a timer. */
+KD_API KDint KD_APIENTRY kdCancelTimer(KDTimer *timer);
+
+/* KD_EVENT_TIMER: Timer fire event. */
+#define KD_EVENT_TIMER 42
+
+/*******************************************************
+ * File system
+ *******************************************************/
+#define KD_EOF (-1)
+
+/* kdFopen: Open a file from the file system. */
+typedef struct KDFile KDFile;
+KD_API KDFile *KD_APIENTRY kdFopen(const KDchar *pathname, const KDchar *mode);
+
+/* kdFclose: Close an open file. */
+KD_API KDint KD_APIENTRY kdFclose(KDFile *file);
+
+/* kdFflush: Flush an open file. */
+KD_API KDint KD_APIENTRY kdFflush(KDFile *file);
+
+/* kdFread: Read from a file. */
+KD_API KDsize KD_APIENTRY kdFread(void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdFwrite: Write to a file. */
+KD_API KDsize KD_APIENTRY kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdGetc: Read next byte from an open file. */
+KD_API KDint KD_APIENTRY kdGetc(KDFile *file);
+
+/* kdPutc: Write a byte to an open file. */
+KD_API KDint KD_APIENTRY kdPutc(KDint c, KDFile *file);
+
+/* kdFgets: Read a line of text from an open file. */
+KD_API KDchar *KD_APIENTRY kdFgets(KDchar *buffer, KDsize buflen, KDFile *file);
+
+/* kdFEOF: Check for end of file. */
+KD_API KDint KD_APIENTRY kdFEOF(KDFile *file);
+
+/* kdFerror: Check for an error condition on an open file. */
+KD_API KDint KD_APIENTRY kdFerror(KDFile *file);
+
+/* kdClearerr: Clear a file&#8217;s error and end-of-file indicators. */
+KD_API void KD_APIENTRY kdClearerr(KDFile *file);
+
+/* kdFseek: Reposition the file position indicator in a file. */
+typedef enum {
+ KD_SEEK_SET = 0,
+ KD_SEEK_CUR = 1,
+ KD_SEEK_END = 2
+} KDfileSeekOrigin;
+KD_API KDint KD_APIENTRY kdFseek(KDFile *file, KDoff offset, KDfileSeekOrigin origin);
+
+/* kdFtell: Get the file position of an open file. */
+KD_API KDoff KD_APIENTRY kdFtell(KDFile *file);
+
+/* kdMkdir: Create new directory. */
+KD_API KDint KD_APIENTRY kdMkdir(const KDchar *pathname);
+
+/* kdRmdir: Delete a directory. */
+KD_API KDint KD_APIENTRY kdRmdir(const KDchar *pathname);
+
+/* kdRename: Rename a file. */
+KD_API KDint KD_APIENTRY kdRename(const KDchar *src, const KDchar *dest);
+
+/* kdRemove: Delete a file. */
+KD_API KDint KD_APIENTRY kdRemove(const KDchar *pathname);
+
+/* kdTruncate: Truncate or extend a file. */
+KD_API KDint KD_APIENTRY kdTruncate(const KDchar *pathname, KDoff length);
+
+/* kdStat, kdFstat: Return information about a file. */
+typedef struct KDStat {
+ KDmode st_mode;
+ KDoff st_size;
+ KDtime st_mtime;
+} KDStat;
+KD_API KDint KD_APIENTRY kdStat(const KDchar *pathname, struct KDStat *buf);
+KD_API KDint KD_APIENTRY kdFstat(KDFile *file, struct KDStat *buf);
+#define KD_ISREG(m) ((m) & 0x8000)
+#define KD_ISDIR(m) ((m) & 0x4000)
+
+/* kdAccess: Determine whether the application can access a file or directory. */
+KD_API KDint KD_APIENTRY kdAccess(const KDchar *pathname, KDint amode);
+#define KD_R_OK 4
+#define KD_W_OK 2
+#define KD_X_OK 1
+
+/* kdOpenDir: Open a directory ready for listing. */
+typedef struct KDDir KDDir;
+KD_API KDDir *KD_APIENTRY kdOpenDir(const KDchar *pathname);
+
+/* kdReadDir: Return the next file in a directory. */
+typedef struct KDDirent {
+ const KDchar *d_name;
+} KDDirent;
+KD_API KDDirent *KD_APIENTRY kdReadDir(KDDir *dir);
+
+/* kdCloseDir: Close a directory. */
+KD_API KDint KD_APIENTRY kdCloseDir(KDDir *dir);
+
+/* kdGetFree: Get free space on a drive. */
+KD_API KDoff KD_APIENTRY kdGetFree(const KDchar *pathname);
+
+/*******************************************************
+ * Network sockets
+ *******************************************************/
+
+/* KDSockaddr: Struct type for socket address. */
+typedef struct KDSockaddr {
+ KDuint16 family;
+ union {
+#define KD_AF_INET 70
+ struct {
+ KDuint16 port;
+ KDuint32 address;
+ } sin;
+ } data;
+} KDSockaddr;
+
+/* kdNameLookup: Look up a hostname. */
+KD_API KDint KD_APIENTRY kdNameLookup(KDint af, const KDchar *hostname, void *eventuserptr);
+
+/* kdNameLookupCancel: Selectively cancels ongoing kdNameLookup operations. */
+KD_API void KD_APIENTRY kdNameLookupCancel(void *eventuserptr);
+
+/* kdSocketCreate: Creates a socket. */
+typedef struct KDSocket KDSocket;
+KD_API KDSocket *KD_APIENTRY kdSocketCreate(KDint type, void *eventuserptr);
+#define KD_SOCK_TCP 64
+#define KD_SOCK_UDP 65
+
+/* kdSocketClose: Closes a socket. */
+KD_API KDint KD_APIENTRY kdSocketClose(KDSocket *socket);
+
+/* kdSocketBind: Bind a socket. */
+KD_API KDint KD_APIENTRY kdSocketBind(KDSocket *socket, const struct KDSockaddr *addr, KDboolean reuse);
+#define KD_INADDR_ANY 0
+
+/* kdSocketGetName: Get the local address of a socket. */
+KD_API KDint KD_APIENTRY kdSocketGetName(KDSocket *socket, struct KDSockaddr *addr);
+
+/* kdSocketConnect: Connects a socket. */
+KD_API KDint KD_APIENTRY kdSocketConnect(KDSocket *socket, const KDSockaddr *addr);
+
+/* kdSocketListen: Listen on a socket. */
+KD_API KDint KD_APIENTRY kdSocketListen(KDSocket *socket, KDint backlog);
+
+/* kdSocketAccept: Accept an incoming connection. */
+KD_API KDSocket *KD_APIENTRY kdSocketAccept(KDSocket *socket, KDSockaddr *addr, void *eventuserptr);
+
+/* kdSocketSend, kdSocketSendTo: Send data to a socket. */
+KD_API KDint KD_APIENTRY kdSocketSend(KDSocket *socket, const void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketSendTo(KDSocket *socket, const void *buf, KDint len, const KDSockaddr *addr);
+
+/* kdSocketRecv, kdSocketRecvFrom: Receive data from a socket. */
+KD_API KDint KD_APIENTRY kdSocketRecv(KDSocket *socket, void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketRecvFrom(KDSocket *socket, void *buf, KDint len, KDSockaddr *addr);
+
+/* kdHtonl: Convert a 32-bit integer from host to network byte order. */
+KD_API KDuint32 KD_APIENTRY kdHtonl(KDuint32 hostlong);
+
+/* kdHtons: Convert a 16-bit integer from host to network byte order. */
+KD_API KDuint16 KD_APIENTRY kdHtons(KDuint16 hostshort);
+
+/* kdNtohl: Convert a 32-bit integer from network to host byte order. */
+KD_API KDuint32 KD_APIENTRY kdNtohl(KDuint32 netlong);
+
+/* kdNtohs: Convert a 16-bit integer from network to host byte order. */
+KD_API KDuint16 KD_APIENTRY kdNtohs(KDuint16 netshort);
+
+/* kdInetAton: Convert a &#8220;dotted quad&#8221; format address to an integer. */
+KD_API KDint KD_APIENTRY kdInetAton(const KDchar *cp, KDuint32 *inp);
+
+/* kdInetNtop: Convert a network address to textual form. */
+#define KD_INET_ADDRSTRLEN 16
+typedef struct KDInAddr {
+ KDuint32 s_address; // Renamed this from s_addr as it causes a conflict with winsock2.h
+} KDInAddr;
+KD_API const KDchar *KD_APIENTRY kdInetNtop(KDuint af, const void *src, KDchar *dst, KDsize cnt);
+
+/* KD_EVENT_SOCKET_READABLE: Event to indicate that a socket is readable. */
+#define KD_EVENT_SOCKET_READABLE 49
+typedef struct KDEventSocketReadable {
+ KDSocket *socket;
+} KDEventSocketReadable;
+
+/* KD_EVENT_SOCKET_WRITABLE: Event to indicate that a socket is writable. */
+#define KD_EVENT_SOCKET_WRITABLE 50
+typedef struct KDEventSocketWritable {
+ KDSocket *socket;
+} KDEventSocketWritable;
+
+/* KD_EVENT_SOCKET_CONNECT_COMPLETE: Event generated when a socket connect is complete */
+#define KD_EVENT_SOCKET_CONNECT_COMPLETE 51
+typedef struct KDEventSocketConnect {
+ KDSocket *socket;
+ KDint32 error;
+} KDEventSocketConnect;
+
+/* KD_EVENT_SOCKET_INCOMING: Event generated when a listening socket detects an incoming connection or an error. */
+#define KD_EVENT_SOCKET_INCOMING 52
+typedef struct KDEventSocketIncoming {
+ KDSocket *socket;
+} KDEventSocketIncoming;
+
+/* KD_EVENT_NAME_LOOKUP_COMPLETE: kdNameLookup complete event. */
+#define KD_EVENT_NAME_LOOKUP_COMPLETE 53
+typedef struct KDEventNameLookup {
+ KDint32 error;
+ KDint32 resultlen;
+ const KDSockaddr *result;
+ KDboolean more;
+} KDEventNameLookup;
+
+/*******************************************************
+ * Input/output
+ *******************************************************/
+
+/* KD_EVENT_STATE: State changed event. */
+#define KD_EVENT_STATE 55
+
+typedef struct KDEventState {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventState;
+
+/* KD_EVENT_INPUT: Input changed event. */
+#define KD_EVENT_INPUT 56
+
+typedef struct KDEventInput {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventInput;
+
+/* KD_EVENT_INPUT_JOG: Jogdial jog event. */
+#define KD_EVENT_INPUT_JOG 71
+typedef struct KDEventInputJog {
+ KDint32 index;
+ KDint32 count;
+} KDEventInputJog;
+
+/* KD_EVENT_INPUT_POINTER: Pointer input changed event. */
+#define KD_EVENT_INPUT_POINTER 57
+typedef struct KDEventInputPointer {
+ KDint32 index;
+ KDint32 select;
+ KDint32 x;
+ KDint32 y;
+} KDEventInputPointer;
+
+/* KD_EVENT_INPUT_STICK: Joystick stick changed event. */
+#define KD_EVENT_INPUT_STICK 58
+typedef struct KDEventInputStick {
+ KDint32 index;
+ KDint32 x;
+ KDint32 y;
+ KDint32 z;
+} KDEventInputStick;
+
+/* kdStateGeti, kdStateGetl, kdStateGetf: get state value(s) */
+KD_API KDint KD_APIENTRY kdStateGeti(KDint startidx, KDuint numidxs, KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetl(KDint startidx, KDuint numidxs, KDint64 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetf(KDint startidx, KDuint numidxs, KDfloat32 *buffer);
+
+/* kdOutputSeti, kdOutputSetf: set outputs */
+KD_API KDint KD_APIENTRY kdOutputSeti(KDint startidx, KDuint numidxs, const KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdOutputSetf(KDint startidx, KDuint numidxs, const KDfloat32 *buffer);
+#define KD_IO_CONTROLLER_STRIDE 64
+
+/* KD_IOGROUP_GAMEKEYS: I/O group for game keys. */
+#define KD_IOGROUP_GAMEKEYS 0x1000
+#define KD_STATE_GAMEKEYS_AVAILABILITY (KD_IOGROUP_GAMEKEYS + 0)
+#define KD_INPUT_GAMEKEYS_UP (KD_IOGROUP_GAMEKEYS + 1)
+#define KD_INPUT_GAMEKEYS_LEFT (KD_IOGROUP_GAMEKEYS + 2)
+#define KD_INPUT_GAMEKEYS_RIGHT (KD_IOGROUP_GAMEKEYS + 3)
+#define KD_INPUT_GAMEKEYS_DOWN (KD_IOGROUP_GAMEKEYS + 4)
+#define KD_INPUT_GAMEKEYS_FIRE (KD_IOGROUP_GAMEKEYS + 5)
+#define KD_INPUT_GAMEKEYS_A (KD_IOGROUP_GAMEKEYS + 6)
+#define KD_INPUT_GAMEKEYS_B (KD_IOGROUP_GAMEKEYS + 7)
+#define KD_INPUT_GAMEKEYS_C (KD_IOGROUP_GAMEKEYS + 8)
+#define KD_INPUT_GAMEKEYS_D (KD_IOGROUP_GAMEKEYS + 9)
+
+/* KD_IOGROUP_GAMEKEYSNC: I/O group for game keys, no chording. */
+#define KD_IOGROUP_GAMEKEYSNC 0x1100
+#define KD_STATE_GAMEKEYSNC_AVAILABILITY (KD_IOGROUP_GAMEKEYSNC + 0)
+#define KD_INPUT_GAMEKEYSNC_UP (KD_IOGROUP_GAMEKEYSNC + 1)
+#define KD_INPUT_GAMEKEYSNC_LEFT (KD_IOGROUP_GAMEKEYSNC + 2)
+#define KD_INPUT_GAMEKEYSNC_RIGHT (KD_IOGROUP_GAMEKEYSNC + 3)
+#define KD_INPUT_GAMEKEYSNC_DOWN (KD_IOGROUP_GAMEKEYSNC + 4)
+#define KD_INPUT_GAMEKEYSNC_FIRE (KD_IOGROUP_GAMEKEYSNC + 5)
+#define KD_INPUT_GAMEKEYSNC_A (KD_IOGROUP_GAMEKEYSNC + 6)
+#define KD_INPUT_GAMEKEYSNC_B (KD_IOGROUP_GAMEKEYSNC + 7)
+#define KD_INPUT_GAMEKEYSNC_C (KD_IOGROUP_GAMEKEYSNC + 8)
+#define KD_INPUT_GAMEKEYSNC_D (KD_IOGROUP_GAMEKEYSNC + 9)
+
+/* KD_IOGROUP_PHONEKEYPAD: I/O group for phone keypad. */
+#define KD_IOGROUP_PHONEKEYPAD 0x2000
+#define KD_STATE_PHONEKEYPAD_AVAILABILITY (KD_IOGROUP_PHONEKEYPAD + 0)
+#define KD_INPUT_PHONEKEYPAD_0 (KD_IOGROUP_PHONEKEYPAD + 1)
+#define KD_INPUT_PHONEKEYPAD_1 (KD_IOGROUP_PHONEKEYPAD + 2)
+#define KD_INPUT_PHONEKEYPAD_2 (KD_IOGROUP_PHONEKEYPAD + 3)
+#define KD_INPUT_PHONEKEYPAD_3 (KD_IOGROUP_PHONEKEYPAD + 4)
+#define KD_INPUT_PHONEKEYPAD_4 (KD_IOGROUP_PHONEKEYPAD + 5)
+#define KD_INPUT_PHONEKEYPAD_5 (KD_IOGROUP_PHONEKEYPAD + 6)
+#define KD_INPUT_PHONEKEYPAD_6 (KD_IOGROUP_PHONEKEYPAD + 7)
+#define KD_INPUT_PHONEKEYPAD_7 (KD_IOGROUP_PHONEKEYPAD + 8)
+#define KD_INPUT_PHONEKEYPAD_8 (KD_IOGROUP_PHONEKEYPAD + 9)
+#define KD_INPUT_PHONEKEYPAD_9 (KD_IOGROUP_PHONEKEYPAD + 10)
+#define KD_INPUT_PHONEKEYPAD_STAR (KD_IOGROUP_PHONEKEYPAD + 11)
+#define KD_INPUT_PHONEKEYPAD_HASH (KD_IOGROUP_PHONEKEYPAD + 12)
+#define KD_INPUT_PHONEKEYPAD_LEFTSOFT (KD_IOGROUP_PHONEKEYPAD + 13)
+#define KD_INPUT_PHONEKEYPAD_RIGHTSOFT (KD_IOGROUP_PHONEKEYPAD + 14)
+#define KD_STATE_PHONEKEYPAD_ORIENTATION (KD_IOGROUP_PHONEKEYPAD + 15)
+
+/* KD_IOGROUP_VIBRATE: I/O group for vibrate. */
+#define KD_IOGROUP_VIBRATE 0x3000
+#define KD_STATE_VIBRATE_AVAILABILITY (KD_IOGROUP_VIBRATE + 0)
+#define KD_STATE_VIBRATE_MINFREQUENCY (KD_IOGROUP_VIBRATE + 1)
+#define KD_STATE_VIBRATE_MAXFREQUENCY (KD_IOGROUP_VIBRATE + 2)
+#define KD_OUTPUT_VIBRATE_VOLUME (KD_IOGROUP_VIBRATE + 3)
+#define KD_OUTPUT_VIBRATE_FREQUENCY (KD_IOGROUP_VIBRATE + 4)
+
+/* KD_IOGROUP_POINTER: I/O group for pointer. */
+#define KD_IOGROUP_POINTER 0x4000
+#define KD_STATE_POINTER_AVAILABILITY (KD_IOGROUP_POINTER + 0)
+#define KD_INPUT_POINTER_X (KD_IOGROUP_POINTER + 1)
+#define KD_INPUT_POINTER_Y (KD_IOGROUP_POINTER + 2)
+#define KD_INPUT_POINTER_SELECT (KD_IOGROUP_POINTER + 3)
+
+/* KD_IOGROUP_BACKLIGHT: I/O group for backlight. */
+#define KD_IOGROUP_BACKLIGHT 0x5000
+#define KD_STATE_BACKLIGHT_AVAILABILITY (KD_IOGROUP_BACKLIGHT + 0)
+#define KD_OUTPUT_BACKLIGHT_FORCE (KD_IOGROUP_BACKLIGHT + 1)
+
+/* KD_IOGROUP_JOGDIAL: I/O group for a jog dial. */
+#define KD_IOGROUP_JOGDIAL 0x6000
+#define KD_STATE_JOGDIAL_AVAILABILITY (KD_IOGROUP_JOGDIAL + 0)
+#define KD_INPUT_JOGDIAL_UP (KD_IOGROUP_JOGDIAL + 1)
+#define KD_INPUT_JOGDIAL_LEFT (KD_IOGROUP_JOGDIAL + 2)
+#define KD_INPUT_JOGDIAL_RIGHT (KD_IOGROUP_JOGDIAL + 3)
+#define KD_INPUT_JOGDIAL_DOWN (KD_IOGROUP_JOGDIAL + 4)
+#define KD_INPUT_JOGDIAL_SELECT (KD_IOGROUP_JOGDIAL + 5)
+
+/* KD_IOGROUP_STICK: I/O group for joystick. */
+#define KD_IOGROUP_STICK 0x7000
+#define KD_STATE_STICK_AVAILABILITY (KD_IOGROUP_STICK + 0)
+#define KD_INPUT_STICK_X (KD_IOGROUP_STICK + 1)
+#define KD_INPUT_STICK_Y (KD_IOGROUP_STICK + 2)
+#define KD_INPUT_STICK_Z (KD_IOGROUP_STICK + 3)
+#define KD_INPUT_STICK_BUTTON (KD_IOGROUP_STICK + 4)
+#define KD_IO_STICK_STRIDE 8
+
+/* KD_IOGROUP_DPAD: I/O group for D-pad. */
+#define KD_IOGROUP_DPAD 0x8000
+#define KD_STATE_DPAD_AVAILABILITY (KD_IOGROUP_DPAD + 0)
+#define KD_STATE_DPAD_COPY (KD_IOGROUP_DPAD + 1)
+#define KD_INPUT_DPAD_UP (KD_IOGROUP_DPAD + 2)
+#define KD_INPUT_DPAD_LEFT (KD_IOGROUP_DPAD + 3)
+#define KD_INPUT_DPAD_RIGHT (KD_IOGROUP_DPAD + 4)
+#define KD_INPUT_DPAD_DOWN (KD_IOGROUP_DPAD + 5)
+#define KD_INPUT_DPAD_SELECT (KD_IOGROUP_DPAD + 6)
+#define KD_IO_DPAD_STRIDE 8
+
+/* KD_IOGROUP_BUTTONS: I/O group for buttons associated with joystick or D-pad. */
+#define KD_IOGROUP_BUTTONS 0x9000
+#define KD_STATE_BUTTONS_AVAILABILITY (KD_IOGROUP_BUTTONS + 0)
+#define KD_INPUT_BUTTONS_0 (KD_IOGROUP_BUTTONS + 1)
+
+/* KD_IO_UNDEFINED: I/O items reserved for implementation-dependent use. */
+#define KD_IO_UNDEFINED 0x40000000
+
+/*******************************************************
+ * Windowing
+ *******************************************************/
+#ifdef KD_WINDOW_SUPPORTED
+#include <EGL/egl.h>
+typedef struct KDWindow KDWindow;
+
+/* kdCreateWindow: Create a window. */
+KD_API KDWindow *KD_APIENTRY kdCreateWindow(EGLDisplay display, EGLConfig config, void *eventuserptr);
+
+/* kdDestroyWindow: Destroy a window. */
+KD_API KDint KD_APIENTRY kdDestroyWindow(KDWindow *window);
+
+/* kdSetWindowPropertybv, kdSetWindowPropertyiv, kdSetWindowPropertycv: Set a window property to request a change in the on-screen representation of the window. */
+KD_API KDint KD_APIENTRY kdSetWindowPropertybv(KDWindow *window, KDint pname, const KDboolean *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertyiv(KDWindow *window, KDint pname, const KDint32 *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertycv(KDWindow *window, KDint pname, const KDchar *param);
+
+/* kdGetWindowPropertybv, kdGetWindowPropertyiv, kdGetWindowPropertycv: Get the current value of a window property. */
+KD_API KDint KD_APIENTRY kdGetWindowPropertybv(KDWindow *window, KDint pname, KDboolean *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertyiv(KDWindow *window, KDint pname, KDint32 *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertycv(KDWindow *window, KDint pname, KDchar *param, KDsize *size);
+
+/* kdRealizeWindow: Realize the window as a displayable entity and get the native window handle for passing to EGL. */
+KD_API KDint KD_APIENTRY kdRealizeWindow(KDWindow *window, EGLNativeWindowType *nativewindow);
+
+/* KD_WINDOWPROPERTY_SIZE: Window client area width and height. */
+#define KD_WINDOWPROPERTY_SIZE 66
+
+/* KD_WINDOWPROPERTY_VISIBILITY: Window visibility status. */
+#define KD_WINDOWPROPERTY_VISIBILITY 67
+
+/* KD_WINDOWPROPERTY_FOCUS: Window input focus status. */
+#define KD_WINDOWPROPERTY_FOCUS 68
+
+/* KD_WINDOWPROPERTY_CAPTION: Window caption. */
+#define KD_WINDOWPROPERTY_CAPTION 69
+
+/* KD_EVENT_WINDOW_CLOSE: Event to request to close window. */
+#define KD_EVENT_WINDOW_CLOSE 44
+
+/* KD_EVENT_WINDOWPROPERTY_CHANGE: Notification about realized window property change. */
+#define KD_EVENT_WINDOWPROPERTY_CHANGE 47
+typedef struct KDEventWindowProperty {
+ KDint32 pname;
+} KDEventWindowProperty;
+
+/* KD_EVENT_WINDOW_FOCUS: Event for change of window&#8217;s focus state. */
+#define KD_EVENT_WINDOW_FOCUS 60
+typedef struct KDEventWindowFocus {
+ KDint32 focusstate;
+} KDEventWindowFocus;
+
+/* KD_EVENT_WINDOW_REDRAW: Event to notify need to redraw the window. */
+#define KD_EVENT_WINDOW_REDRAW 59
+#endif /* KD_WINDOW_SUPPORTED */
+
+/*******************************************************
+ * Assertions and logging
+ *******************************************************/
+
+/* kdHandleAssertion: Handle assertion failure. */
+KD_API void KD_APIENTRY kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber);
+
+/* kdLogMessage: Output a log message. */
+#ifdef KD_NDEBUG
+#define kdLogMessage(s)
+#else
+KD_API void KD_APIENTRY kdLogMessage(const KDchar *string);
+#endif
+
+/* struct KDEvent delayed to the end as it uses event data structs from
+ * other parts of the .h file. */
+struct KDEvent {
+ KDust timestamp;
+ KDint32 type;
+ void *userptr;
+ union KDEventData {
+ KDEventState state;
+ KDEventInput input;
+ KDEventInputJog inputjog;
+ KDEventInputPointer inputpointer;
+ KDEventInputStick inputstick;
+ KDEventSocketReadable socketreadable;
+ KDEventSocketWritable socketwritable;
+ KDEventSocketConnect socketconnect;
+ KDEventSocketIncoming socketincoming;
+ KDEventNameLookup namelookup;
+#ifdef KD_WINDOW_SUPPORTED
+ KDEventWindowProperty windowproperty;
+ KDEventWindowFocus windowfocus;
+#endif /* KD_WINDOW_SUPPORTED */
+ KDEventUser user;
+ } data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kdplatform.h b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kdplatform.h
new file mode 100644
index 00000000..ed85ed02
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs/KD/kdplatform.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Sample KD/kdplatform.h for OpenKODE Core 1.0.3 */
+#ifndef __kdplatform_h_
+#define __kdplatform_h_
+
+#define KD_API
+#define KD_APIENTRY
+
+typedef int KDint32;
+typedef unsigned int KDuint32;
+typedef long long KDint64;
+typedef unsigned long long KDuint64;
+typedef short KDint16;
+typedef unsigned short KDuint16;
+typedef unsigned long KDuintptr;
+typedef unsigned long KDsize;
+typedef long KDssize;
+#define KDINT_MIN (-0x7fffffff-1)
+#define KDINT_MAX 0x7fffffff
+#define KDUINT_MAX 0xffffffffU
+#define KDINT64_MIN (-0x7fffffffffffffffLL-1)
+#define KDINT64_MAX 0x7fffffffffffffffLL
+#define KDUINT64_MAX 0xffffffffffffffffULL
+#define KDSSIZE_MIN (-0x7fffffff-1)
+#define KDSSIZE_MAX 0x7fffffff
+#define KDSIZE_MAX 0xffffffffU
+#define KDUINTPTR_MAX 0xffffffffU
+#define KD_NORETURN
+// removed, no EGL on macOS
+//#define KD_WINDOW_SUPPORTED
+#ifdef KD_NDEBUG
+#define kdAssert(c)
+#else
+#define kdAssert(c) ((void)( (c) ? 0 : (kdHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+#define KD_INFINITY_BITS 0x7f800000u
+#define KD_INFINITY (kdBitsToFloatNV(KD_INFINITY_BITS))
+
+KD_API float KD_APIENTRY kdBitsToFloatNV(KDuint32 x);
+
+
+/** KHR_formatted extension */
+#include <stdarg.h>
+typedef va_list KDVaListKHR;
+
+// If there are problems with including stdarg.h here under any of the Windows
+// operating systems, we might want to change it back to using char* instead of
+// va_list
+//typedef char *KDVaListKHR;
+
+
+#define KD_VA_START_KHR(ap, parmN) \
+ do {ap = (KDVaListKHR)&parmN + sizeof(parmN);} while(0)
+
+#define KD_VA_ARG_CHAR_KHR(ap) (KDchar)va_arg(ap, KDint)
+#define KD_VA_ARG_CHARPTR_KHR(ap) (KDchar*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16_KHR(ap) (KDint16)va_arg(ap, KDint)
+#define KD_VA_ARG_INT32_KHR(ap) va_arg(ap, KDint32)
+#define KD_VA_ARG_INT_KHR(ap) va_arg(ap, KDint)
+#define KD_VA_ARG_INT64_KHR(ap) va_arg(ap, KDint64)
+#define KD_VA_ARG_INTPTR_KHR(ap) (KDint*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16PTR_KHR(ap) (KDint16*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_FLOAT32_KHR(ap) (KDfloat32)(va_arg(ap, double))
+#define KD_VA_ARG_PTR_KHR(ap) (void *)va_arg(ap, char *)
+
+#define KD_VA_END_KHR(ap) \
+ do {ap = (KDVaListKHR)0;} while(0)
+
+#endif /* __kdplatform_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/gl.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/gl.h
new file mode 100644
index 00000000..1d2cd0ad
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/gl.h
@@ -0,0 +1,1543 @@
+/*
+** NOTE: This is a version of gl.h extracted from Visual C++ 7.1 checked in
+** to the source tree so Linux and Windows builds can use the same headers.
+** The only modification to the file is to define "WINGDIAPI" and "APIENTRY"
+** for non-Win32 builds.
+*/
+
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+
+Copyright (c) 1985-96, Microsoft Corporation
+
+Module Name:
+
+ gl.h
+
+Abstract:
+
+ Procedure declarations, constant definitions and macros for the OpenGL
+ component.
+
+--*/
+
+#ifndef __gl_h_
+#ifndef __GL_H__
+
+#define __gl_h_
+#define __GL_H__
+
+#if !defined (_WIN32)
+#define WINGDIAPI
+#define APIENTRY
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright 1996 Silicon Graphics, Inc.
+** All Rights Reserved.
+**
+** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
+** the contents of this file may not be disclosed to third parties, copied or
+** duplicated in any form, in whole or in part, without the prior written
+** permission of Silicon Graphics, Inc.
+**
+** RESTRICTED RIGHTS LEGEND:
+** Use, duplication or disclosure by the Government is subject to restrictions
+** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
+** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
+** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
+** rights reserved under the Copyright Laws of the United States.
+*/
+
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void GLvoid;
+
+/*************************************************************/
+
+/* Version */
+#define GL_VERSION_1_1 1
+
+/* AccumOp */
+#define GL_ACCUM 0x0100
+#define GL_LOAD 0x0101
+#define GL_RETURN 0x0102
+#define GL_MULT 0x0103
+#define GL_ADD 0x0104
+
+/* AlphaFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* AttribMask */
+#define GL_CURRENT_BIT 0x00000001
+#define GL_POINT_BIT 0x00000002
+#define GL_LINE_BIT 0x00000004
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_HINT_BIT 0x00008000
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0x000fffff
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON 0x0009
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* Boolean */
+#define GL_TRUE 1
+#define GL_FALSE 0
+
+/* ClearBufferMask */
+/* GL_COLOR_BUFFER_BIT */
+/* GL_ACCUM_BUFFER_BIT */
+/* GL_STENCIL_BUFFER_BIT */
+/* GL_DEPTH_BUFFER_BIT */
+
+/* ClientArrayType */
+/* GL_VERTEX_ARRAY */
+/* GL_NORMAL_ARRAY */
+/* GL_COLOR_ARRAY */
+/* GL_INDEX_ARRAY */
+/* GL_TEXTURE_COORD_ARRAY */
+/* GL_EDGE_FLAG_ARRAY */
+
+/* ClipPlaneName */
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+
+/* ColorMaterialFace */
+/* GL_FRONT */
+/* GL_BACK */
+/* GL_FRONT_AND_BACK */
+
+/* ColorMaterialParameter */
+/* GL_AMBIENT */
+/* GL_DIFFUSE */
+/* GL_SPECULAR */
+/* GL_EMISSION */
+/* GL_AMBIENT_AND_DIFFUSE */
+
+/* ColorPointerType */
+/* GL_BYTE */
+/* GL_UNSIGNED_BYTE */
+/* GL_SHORT */
+/* GL_UNSIGNED_SHORT */
+/* GL_INT */
+/* GL_UNSIGNED_INT */
+/* GL_FLOAT */
+/* GL_DOUBLE */
+
+/* CullFaceMode */
+/* GL_FRONT */
+/* GL_BACK */
+/* GL_FRONT_AND_BACK */
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_DOUBLE 0x140A
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* DrawBufferMode */
+#define GL_NONE 0
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+
+/* Enable */
+/* GL_FOG */
+/* GL_LIGHTING */
+/* GL_TEXTURE_1D */
+/* GL_TEXTURE_2D */
+/* GL_LINE_STIPPLE */
+/* GL_POLYGON_STIPPLE */
+/* GL_CULL_FACE */
+/* GL_ALPHA_TEST */
+/* GL_BLEND */
+/* GL_INDEX_LOGIC_OP */
+/* GL_COLOR_LOGIC_OP */
+/* GL_DITHER */
+/* GL_STENCIL_TEST */
+/* GL_DEPTH_TEST */
+/* GL_CLIP_PLANE0 */
+/* GL_CLIP_PLANE1 */
+/* GL_CLIP_PLANE2 */
+/* GL_CLIP_PLANE3 */
+/* GL_CLIP_PLANE4 */
+/* GL_CLIP_PLANE5 */
+/* GL_LIGHT0 */
+/* GL_LIGHT1 */
+/* GL_LIGHT2 */
+/* GL_LIGHT3 */
+/* GL_LIGHT4 */
+/* GL_LIGHT5 */
+/* GL_LIGHT6 */
+/* GL_LIGHT7 */
+/* GL_TEXTURE_GEN_S */
+/* GL_TEXTURE_GEN_T */
+/* GL_TEXTURE_GEN_R */
+/* GL_TEXTURE_GEN_Q */
+/* GL_MAP1_VERTEX_3 */
+/* GL_MAP1_VERTEX_4 */
+/* GL_MAP1_COLOR_4 */
+/* GL_MAP1_INDEX */
+/* GL_MAP1_NORMAL */
+/* GL_MAP1_TEXTURE_COORD_1 */
+/* GL_MAP1_TEXTURE_COORD_2 */
+/* GL_MAP1_TEXTURE_COORD_3 */
+/* GL_MAP1_TEXTURE_COORD_4 */
+/* GL_MAP2_VERTEX_3 */
+/* GL_MAP2_VERTEX_4 */
+/* GL_MAP2_COLOR_4 */
+/* GL_MAP2_INDEX */
+/* GL_MAP2_NORMAL */
+/* GL_MAP2_TEXTURE_COORD_1 */
+/* GL_MAP2_TEXTURE_COORD_2 */
+/* GL_MAP2_TEXTURE_COORD_3 */
+/* GL_MAP2_TEXTURE_COORD_4 */
+/* GL_POINT_SMOOTH */
+/* GL_LINE_SMOOTH */
+/* GL_POLYGON_SMOOTH */
+/* GL_SCISSOR_TEST */
+/* GL_COLOR_MATERIAL */
+/* GL_NORMALIZE */
+/* GL_AUTO_NORMAL */
+/* GL_VERTEX_ARRAY */
+/* GL_NORMAL_ARRAY */
+/* GL_COLOR_ARRAY */
+/* GL_INDEX_ARRAY */
+/* GL_TEXTURE_COORD_ARRAY */
+/* GL_EDGE_FLAG_ARRAY */
+/* GL_POLYGON_OFFSET_POINT */
+/* GL_POLYGON_OFFSET_LINE */
+/* GL_POLYGON_OFFSET_FILL */
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FeedBackMode */
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+
+/* FeedBackToken */
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_LINE_RESET_TOKEN 0x0707
+
+/* FogMode */
+/* GL_LINEAR */
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+
+
+/* FogParameter */
+/* GL_FOG_COLOR */
+/* GL_FOG_DENSITY */
+/* GL_FOG_END */
+/* GL_FOG_INDEX */
+/* GL_FOG_MODE */
+/* GL_FOG_START */
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetMapTarget */
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+
+/* GetPixelMap */
+/* GL_PIXEL_MAP_I_TO_I */
+/* GL_PIXEL_MAP_S_TO_S */
+/* GL_PIXEL_MAP_I_TO_R */
+/* GL_PIXEL_MAP_I_TO_G */
+/* GL_PIXEL_MAP_I_TO_B */
+/* GL_PIXEL_MAP_I_TO_A */
+/* GL_PIXEL_MAP_R_TO_R */
+/* GL_PIXEL_MAP_G_TO_G */
+/* GL_PIXEL_MAP_B_TO_B */
+/* GL_PIXEL_MAP_A_TO_A */
+
+/* GetPointerTarget */
+/* GL_VERTEX_ARRAY_POINTER */
+/* GL_NORMAL_ARRAY_POINTER */
+/* GL_COLOR_ARRAY_POINTER */
+/* GL_INDEX_ARRAY_POINTER */
+/* GL_TEXTURE_COORD_ARRAY_POINTER */
+/* GL_EDGE_FLAG_ARRAY_POINTER */
+
+/* GetTarget */
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LIST_MODE 0x0B30
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_SHADE_MODEL 0x0B54
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_FOG 0x0B60
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_COLOR 0x0B66
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_NORMALIZE 0x0BA1
+#define GL_VIEWPORT 0x0BA2
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_DITHER 0x0BD0
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND 0x0BE2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_READ_BUFFER 0x0C02
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_INDEX_MODE 0x0C30
+#define GL_RGBA_MODE 0x0C31
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_RENDER_MODE 0x0C40
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_INDEX_BITS 0x0D51
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+/* GL_TEXTURE_BINDING_1D */
+/* GL_TEXTURE_BINDING_2D */
+/* GL_VERTEX_ARRAY */
+/* GL_NORMAL_ARRAY */
+/* GL_COLOR_ARRAY */
+/* GL_INDEX_ARRAY */
+/* GL_TEXTURE_COORD_ARRAY */
+/* GL_EDGE_FLAG_ARRAY */
+/* GL_VERTEX_ARRAY_SIZE */
+/* GL_VERTEX_ARRAY_TYPE */
+/* GL_VERTEX_ARRAY_STRIDE */
+/* GL_NORMAL_ARRAY_TYPE */
+/* GL_NORMAL_ARRAY_STRIDE */
+/* GL_COLOR_ARRAY_SIZE */
+/* GL_COLOR_ARRAY_TYPE */
+/* GL_COLOR_ARRAY_STRIDE */
+/* GL_INDEX_ARRAY_TYPE */
+/* GL_INDEX_ARRAY_STRIDE */
+/* GL_TEXTURE_COORD_ARRAY_SIZE */
+/* GL_TEXTURE_COORD_ARRAY_TYPE */
+/* GL_TEXTURE_COORD_ARRAY_STRIDE */
+/* GL_EDGE_FLAG_ARRAY_STRIDE */
+/* GL_POLYGON_OFFSET_FACTOR */
+/* GL_POLYGON_OFFSET_UNITS */
+
+/* GetTextureParameter */
+/* GL_TEXTURE_MAG_FILTER */
+/* GL_TEXTURE_MIN_FILTER */
+/* GL_TEXTURE_WRAP_S */
+/* GL_TEXTURE_WRAP_T */
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BORDER 0x1005
+/* GL_TEXTURE_RED_SIZE */
+/* GL_TEXTURE_GREEN_SIZE */
+/* GL_TEXTURE_BLUE_SIZE */
+/* GL_TEXTURE_ALPHA_SIZE */
+/* GL_TEXTURE_LUMINANCE_SIZE */
+/* GL_TEXTURE_INTENSITY_SIZE */
+/* GL_TEXTURE_PRIORITY */
+/* GL_TEXTURE_RESIDENT */
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+/* GL_PERSPECTIVE_CORRECTION_HINT */
+/* GL_POINT_SMOOTH_HINT */
+/* GL_LINE_SMOOTH_HINT */
+/* GL_POLYGON_SMOOTH_HINT */
+/* GL_FOG_HINT */
+/* GL_PHONG_HINT */
+
+/* IndexPointerType */
+/* GL_SHORT */
+/* GL_INT */
+/* GL_FLOAT */
+/* GL_DOUBLE */
+
+/* LightModelParameter */
+/* GL_LIGHT_MODEL_AMBIENT */
+/* GL_LIGHT_MODEL_LOCAL_VIEWER */
+/* GL_LIGHT_MODEL_TWO_SIDE */
+
+/* LightName */
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+
+/* LightParameter */
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+
+/* InterleavedArrays */
+/* GL_V2F */
+/* GL_V3F */
+/* GL_C4UB_V2F */
+/* GL_C4UB_V3F */
+/* GL_C3F_V3F */
+/* GL_N3F_V3F */
+/* GL_C4F_N3F_V3F */
+/* GL_T2F_V3F */
+/* GL_T4F_V4F */
+/* GL_T2F_C4UB_V3F */
+/* GL_T2F_C3F_V3F */
+/* GL_T2F_N3F_V3F */
+/* GL_T2F_C4F_N3F_V3F */
+/* GL_T4F_C4F_N3F_V4F */
+
+/* ListMode */
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+
+/* ListNameType */
+/* GL_BYTE */
+/* GL_UNSIGNED_BYTE */
+/* GL_SHORT */
+/* GL_UNSIGNED_SHORT */
+/* GL_INT */
+/* GL_UNSIGNED_INT */
+/* GL_FLOAT */
+/* GL_2_BYTES */
+/* GL_3_BYTES */
+/* GL_4_BYTES */
+
+/* LogicOp */
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+
+/* MapTarget */
+/* GL_MAP1_COLOR_4 */
+/* GL_MAP1_INDEX */
+/* GL_MAP1_NORMAL */
+/* GL_MAP1_TEXTURE_COORD_1 */
+/* GL_MAP1_TEXTURE_COORD_2 */
+/* GL_MAP1_TEXTURE_COORD_3 */
+/* GL_MAP1_TEXTURE_COORD_4 */
+/* GL_MAP1_VERTEX_3 */
+/* GL_MAP1_VERTEX_4 */
+/* GL_MAP2_COLOR_4 */
+/* GL_MAP2_INDEX */
+/* GL_MAP2_NORMAL */
+/* GL_MAP2_TEXTURE_COORD_1 */
+/* GL_MAP2_TEXTURE_COORD_2 */
+/* GL_MAP2_TEXTURE_COORD_3 */
+/* GL_MAP2_TEXTURE_COORD_4 */
+/* GL_MAP2_VERTEX_3 */
+/* GL_MAP2_VERTEX_4 */
+
+/* MaterialFace */
+/* GL_FRONT */
+/* GL_BACK */
+/* GL_FRONT_AND_BACK */
+
+/* MaterialParameter */
+#define GL_EMISSION 0x1600
+#define GL_SHININESS 0x1601
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+/* GL_AMBIENT */
+/* GL_DIFFUSE */
+/* GL_SPECULAR */
+
+/* MatrixMode */
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+
+/* MeshMode1 */
+/* GL_POINT */
+/* GL_LINE */
+
+/* MeshMode2 */
+/* GL_POINT */
+/* GL_LINE */
+/* GL_FILL */
+
+/* NormalPointerType */
+/* GL_BYTE */
+/* GL_SHORT */
+/* GL_INT */
+/* GL_FLOAT */
+/* GL_DOUBLE */
+
+/* PixelCopyType */
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+
+/* PixelFormat */
+#define GL_COLOR_INDEX 0x1900
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelMap */
+/* GL_PIXEL_MAP_I_TO_I */
+/* GL_PIXEL_MAP_S_TO_S */
+/* GL_PIXEL_MAP_I_TO_R */
+/* GL_PIXEL_MAP_I_TO_G */
+/* GL_PIXEL_MAP_I_TO_B */
+/* GL_PIXEL_MAP_I_TO_A */
+/* GL_PIXEL_MAP_R_TO_R */
+/* GL_PIXEL_MAP_G_TO_G */
+/* GL_PIXEL_MAP_B_TO_B */
+/* GL_PIXEL_MAP_A_TO_A */
+
+/* PixelStore */
+/* GL_UNPACK_SWAP_BYTES */
+/* GL_UNPACK_LSB_FIRST */
+/* GL_UNPACK_ROW_LENGTH */
+/* GL_UNPACK_SKIP_ROWS */
+/* GL_UNPACK_SKIP_PIXELS */
+/* GL_UNPACK_ALIGNMENT */
+/* GL_PACK_SWAP_BYTES */
+/* GL_PACK_LSB_FIRST */
+/* GL_PACK_ROW_LENGTH */
+/* GL_PACK_SKIP_ROWS */
+/* GL_PACK_SKIP_PIXELS */
+/* GL_PACK_ALIGNMENT */
+
+/* PixelTransfer */
+/* GL_MAP_COLOR */
+/* GL_MAP_STENCIL */
+/* GL_INDEX_SHIFT */
+/* GL_INDEX_OFFSET */
+/* GL_RED_SCALE */
+/* GL_RED_BIAS */
+/* GL_GREEN_SCALE */
+/* GL_GREEN_BIAS */
+/* GL_BLUE_SCALE */
+/* GL_BLUE_BIAS */
+/* GL_ALPHA_SCALE */
+/* GL_ALPHA_BIAS */
+/* GL_DEPTH_SCALE */
+/* GL_DEPTH_BIAS */
+
+/* PixelType */
+#define GL_BITMAP 0x1A00
+/* GL_BYTE */
+/* GL_UNSIGNED_BYTE */
+/* GL_SHORT */
+/* GL_UNSIGNED_SHORT */
+/* GL_INT */
+/* GL_UNSIGNED_INT */
+/* GL_FLOAT */
+
+/* PolygonMode */
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+
+/* ReadBufferMode */
+/* GL_FRONT_LEFT */
+/* GL_FRONT_RIGHT */
+/* GL_BACK_LEFT */
+/* GL_BACK_RIGHT */
+/* GL_FRONT */
+/* GL_BACK */
+/* GL_LEFT */
+/* GL_RIGHT */
+/* GL_AUX0 */
+/* GL_AUX1 */
+/* GL_AUX2 */
+/* GL_AUX3 */
+
+/* RenderingMode */
+#define GL_RENDER 0x1C00
+#define GL_FEEDBACK 0x1C01
+#define GL_SELECT 0x1C02
+
+/* ShadingModel */
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+
+
+/* StencilFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+/* GL_INVERT */
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TextureCoordName */
+#define GL_S 0x2000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+
+/* TexCoordPointerType */
+/* GL_SHORT */
+/* GL_INT */
+/* GL_FLOAT */
+/* GL_DOUBLE */
+
+/* TextureEnvMode */
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+/* GL_BLEND */
+/* GL_REPLACE */
+
+/* TextureEnvParameter */
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
+
+/* TextureEnvTarget */
+#define GL_TEXTURE_ENV 0x2300
+
+/* TextureGenMode */
+#define GL_EYE_LINEAR 0x2400
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_SPHERE_MAP 0x2402
+
+/* TextureGenParameter */
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_PLANE 0x2502
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+/* GL_TEXTURE_BORDER_COLOR */
+/* GL_TEXTURE_PRIORITY */
+
+/* TextureTarget */
+/* GL_TEXTURE_1D */
+/* GL_TEXTURE_2D */
+/* GL_PROXY_TEXTURE_1D */
+/* GL_PROXY_TEXTURE_2D */
+
+/* TextureWrapMode */
+#define GL_CLAMP 0x2900
+#define GL_REPEAT 0x2901
+
+/* VertexPointerType */
+/* GL_SHORT */
+/* GL_INT */
+/* GL_FLOAT */
+/* GL_DOUBLE */
+
+/* ClientAttribMask */
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff
+
+/* polygon_offset */
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_FILL 0x8037
+
+/* texture */
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+
+/* texture_object */
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+
+/* vertex_array */
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+
+/* Extensions */
+#define GL_EXT_vertex_array 1
+#define GL_EXT_bgra 1
+#define GL_EXT_paletted_texture 1
+#define GL_WIN_swap_hint 1
+#define GL_WIN_draw_range_elements 1
+// #define GL_WIN_phong_shading 1
+// #define GL_WIN_specular_fog 1
+
+/* EXT_vertex_array */
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+#define GL_DOUBLE_EXT GL_DOUBLE
+
+/* EXT_bgra */
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+
+/* EXT_paletted_texture */
+
+/* These must match the GL_COLOR_TABLE_*_SGI enumerants */
+#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8
+#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF
+
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+
+/* WIN_draw_range_elements */
+#define GL_MAX_ELEMENTS_VERTICES_WIN 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_WIN 0x80E9
+
+/* WIN_phong_shading */
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+
+/* WIN_specular_fog */
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+
+/* For compatibility with OpenGL v1.0 */
+#define GL_LOGIC_OP GL_INDEX_LOGIC_OP
+#define GL_TEXTURE_COMPONENTS GL_TEXTURE_INTERNAL_FORMAT
+
+/*************************************************************/
+
+WINGDIAPI void APIENTRY glAccum (GLenum op, GLfloat value);
+WINGDIAPI void APIENTRY glAlphaFunc (GLenum func, GLclampf ref);
+WINGDIAPI GLboolean APIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences);
+WINGDIAPI void APIENTRY glArrayElement (GLint i);
+WINGDIAPI void APIENTRY glBegin (GLenum mode);
+WINGDIAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
+WINGDIAPI void APIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+WINGDIAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+WINGDIAPI void APIENTRY glCallList (GLuint list);
+WINGDIAPI void APIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists);
+WINGDIAPI void APIENTRY glClear (GLbitfield mask);
+WINGDIAPI void APIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+WINGDIAPI void APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+WINGDIAPI void APIENTRY glClearDepth (GLclampd depth);
+WINGDIAPI void APIENTRY glClearIndex (GLfloat c);
+WINGDIAPI void APIENTRY glClearStencil (GLint s);
+WINGDIAPI void APIENTRY glClipPlane (GLenum plane, const GLdouble *equation);
+WINGDIAPI void APIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue);
+WINGDIAPI void APIENTRY glColor3bv (const GLbyte *v);
+WINGDIAPI void APIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue);
+WINGDIAPI void APIENTRY glColor3dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue);
+WINGDIAPI void APIENTRY glColor3fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glColor3i (GLint red, GLint green, GLint blue);
+WINGDIAPI void APIENTRY glColor3iv (const GLint *v);
+WINGDIAPI void APIENTRY glColor3s (GLshort red, GLshort green, GLshort blue);
+WINGDIAPI void APIENTRY glColor3sv (const GLshort *v);
+WINGDIAPI void APIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+WINGDIAPI void APIENTRY glColor3ubv (const GLubyte *v);
+WINGDIAPI void APIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue);
+WINGDIAPI void APIENTRY glColor3uiv (const GLuint *v);
+WINGDIAPI void APIENTRY glColor3us (GLushort red, GLushort green, GLushort blue);
+WINGDIAPI void APIENTRY glColor3usv (const GLushort *v);
+WINGDIAPI void APIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+WINGDIAPI void APIENTRY glColor4bv (const GLbyte *v);
+WINGDIAPI void APIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+WINGDIAPI void APIENTRY glColor4dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+WINGDIAPI void APIENTRY glColor4fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha);
+WINGDIAPI void APIENTRY glColor4iv (const GLint *v);
+WINGDIAPI void APIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha);
+WINGDIAPI void APIENTRY glColor4sv (const GLshort *v);
+WINGDIAPI void APIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+WINGDIAPI void APIENTRY glColor4ubv (const GLubyte *v);
+WINGDIAPI void APIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+WINGDIAPI void APIENTRY glColor4uiv (const GLuint *v);
+WINGDIAPI void APIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha);
+WINGDIAPI void APIENTRY glColor4usv (const GLushort *v);
+WINGDIAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+WINGDIAPI void APIENTRY glColorMaterial (GLenum face, GLenum mode);
+WINGDIAPI void APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+WINGDIAPI void APIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+WINGDIAPI void APIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+WINGDIAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+WINGDIAPI void APIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+WINGDIAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+WINGDIAPI void APIENTRY glCullFace (GLenum mode);
+WINGDIAPI void APIENTRY glDeleteLists (GLuint list, GLsizei range);
+WINGDIAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+WINGDIAPI void APIENTRY glDepthFunc (GLenum func);
+WINGDIAPI void APIENTRY glDepthMask (GLboolean flag);
+WINGDIAPI void APIENTRY glDepthRange (GLclampd zNear, GLclampd zFar);
+WINGDIAPI void APIENTRY glDisable (GLenum cap);
+WINGDIAPI void APIENTRY glDisableClientState (GLenum array);
+WINGDIAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+WINGDIAPI void APIENTRY glDrawBuffer (GLenum mode);
+WINGDIAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+WINGDIAPI void APIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+WINGDIAPI void APIENTRY glEdgeFlag (GLboolean flag);
+WINGDIAPI void APIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer);
+WINGDIAPI void APIENTRY glEdgeFlagv (const GLboolean *flag);
+WINGDIAPI void APIENTRY glEnable (GLenum cap);
+WINGDIAPI void APIENTRY glEnableClientState (GLenum array);
+WINGDIAPI void APIENTRY glEnd (void);
+WINGDIAPI void APIENTRY glEndList (void);
+WINGDIAPI void APIENTRY glEvalCoord1d (GLdouble u);
+WINGDIAPI void APIENTRY glEvalCoord1dv (const GLdouble *u);
+WINGDIAPI void APIENTRY glEvalCoord1f (GLfloat u);
+WINGDIAPI void APIENTRY glEvalCoord1fv (const GLfloat *u);
+WINGDIAPI void APIENTRY glEvalCoord2d (GLdouble u, GLdouble v);
+WINGDIAPI void APIENTRY glEvalCoord2dv (const GLdouble *u);
+WINGDIAPI void APIENTRY glEvalCoord2f (GLfloat u, GLfloat v);
+WINGDIAPI void APIENTRY glEvalCoord2fv (const GLfloat *u);
+WINGDIAPI void APIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2);
+WINGDIAPI void APIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+WINGDIAPI void APIENTRY glEvalPoint1 (GLint i);
+WINGDIAPI void APIENTRY glEvalPoint2 (GLint i, GLint j);
+WINGDIAPI void APIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer);
+WINGDIAPI void APIENTRY glFinish (void);
+WINGDIAPI void APIENTRY glFlush (void);
+WINGDIAPI void APIENTRY glFogf (GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glFogfv (GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glFogi (GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glFogiv (GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glFrontFace (GLenum mode);
+WINGDIAPI void APIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+WINGDIAPI GLuint APIENTRY glGenLists (GLsizei range);
+WINGDIAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+WINGDIAPI void APIENTRY glGetBooleanv (GLenum pname, GLboolean *params);
+WINGDIAPI void APIENTRY glGetClipPlane (GLenum plane, GLdouble *equation);
+WINGDIAPI void APIENTRY glGetDoublev (GLenum pname, GLdouble *params);
+WINGDIAPI GLenum APIENTRY glGetError (void);
+WINGDIAPI void APIENTRY glGetFloatv (GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v);
+WINGDIAPI void APIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v);
+WINGDIAPI void APIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v);
+WINGDIAPI void APIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glGetPixelMapfv (GLenum map, GLfloat *values);
+WINGDIAPI void APIENTRY glGetPixelMapuiv (GLenum map, GLuint *values);
+WINGDIAPI void APIENTRY glGetPixelMapusv (GLenum map, GLushort *values);
+WINGDIAPI void APIENTRY glGetPointerv (GLenum pname, GLvoid* *params);
+WINGDIAPI void APIENTRY glGetPolygonStipple (GLubyte *mask);
+WINGDIAPI const GLubyte * APIENTRY glGetString (GLenum name);
+WINGDIAPI void APIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params);
+WINGDIAPI void APIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+WINGDIAPI void APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+WINGDIAPI void APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+WINGDIAPI void APIENTRY glHint (GLenum target, GLenum mode);
+WINGDIAPI void APIENTRY glIndexMask (GLuint mask);
+WINGDIAPI void APIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+WINGDIAPI void APIENTRY glIndexd (GLdouble c);
+WINGDIAPI void APIENTRY glIndexdv (const GLdouble *c);
+WINGDIAPI void APIENTRY glIndexf (GLfloat c);
+WINGDIAPI void APIENTRY glIndexfv (const GLfloat *c);
+WINGDIAPI void APIENTRY glIndexi (GLint c);
+WINGDIAPI void APIENTRY glIndexiv (const GLint *c);
+WINGDIAPI void APIENTRY glIndexs (GLshort c);
+WINGDIAPI void APIENTRY glIndexsv (const GLshort *c);
+WINGDIAPI void APIENTRY glIndexub (GLubyte c);
+WINGDIAPI void APIENTRY glIndexubv (const GLubyte *c);
+WINGDIAPI void APIENTRY glInitNames (void);
+WINGDIAPI void APIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer);
+WINGDIAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
+WINGDIAPI GLboolean APIENTRY glIsList (GLuint list);
+WINGDIAPI GLboolean APIENTRY glIsTexture (GLuint texture);
+WINGDIAPI void APIENTRY glLightModelf (GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glLightModeli (GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glLightModeliv (GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glLightf (GLenum light, GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glLighti (GLenum light, GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glLineStipple (GLint factor, GLushort pattern);
+WINGDIAPI void APIENTRY glLineWidth (GLfloat width);
+WINGDIAPI void APIENTRY glListBase (GLuint base);
+WINGDIAPI void APIENTRY glLoadIdentity (void);
+WINGDIAPI void APIENTRY glLoadMatrixd (const GLdouble *m);
+WINGDIAPI void APIENTRY glLoadMatrixf (const GLfloat *m);
+WINGDIAPI void APIENTRY glLoadName (GLuint name);
+WINGDIAPI void APIENTRY glLogicOp (GLenum opcode);
+WINGDIAPI void APIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+WINGDIAPI void APIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+WINGDIAPI void APIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+WINGDIAPI void APIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+WINGDIAPI void APIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2);
+WINGDIAPI void APIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2);
+WINGDIAPI void APIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+WINGDIAPI void APIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+WINGDIAPI void APIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glMateriali (GLenum face, GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glMatrixMode (GLenum mode);
+WINGDIAPI void APIENTRY glMultMatrixd (const GLdouble *m);
+WINGDIAPI void APIENTRY glMultMatrixf (const GLfloat *m);
+WINGDIAPI void APIENTRY glNewList (GLuint list, GLenum mode);
+WINGDIAPI void APIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz);
+WINGDIAPI void APIENTRY glNormal3bv (const GLbyte *v);
+WINGDIAPI void APIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz);
+WINGDIAPI void APIENTRY glNormal3dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
+WINGDIAPI void APIENTRY glNormal3fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glNormal3i (GLint nx, GLint ny, GLint nz);
+WINGDIAPI void APIENTRY glNormal3iv (const GLint *v);
+WINGDIAPI void APIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz);
+WINGDIAPI void APIENTRY glNormal3sv (const GLshort *v);
+WINGDIAPI void APIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+WINGDIAPI void APIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+WINGDIAPI void APIENTRY glPassThrough (GLfloat token);
+WINGDIAPI void APIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values);
+WINGDIAPI void APIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values);
+WINGDIAPI void APIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values);
+WINGDIAPI void APIENTRY glPixelStoref (GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glPixelTransferf (GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glPixelTransferi (GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor);
+WINGDIAPI void APIENTRY glPointSize (GLfloat size);
+WINGDIAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
+WINGDIAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+WINGDIAPI void APIENTRY glPolygonStipple (const GLubyte *mask);
+WINGDIAPI void APIENTRY glPopAttrib (void);
+WINGDIAPI void APIENTRY glPopClientAttrib (void);
+WINGDIAPI void APIENTRY glPopMatrix (void);
+WINGDIAPI void APIENTRY glPopName (void);
+WINGDIAPI void APIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+WINGDIAPI void APIENTRY glPushAttrib (GLbitfield mask);
+WINGDIAPI void APIENTRY glPushClientAttrib (GLbitfield mask);
+WINGDIAPI void APIENTRY glPushMatrix (void);
+WINGDIAPI void APIENTRY glPushName (GLuint name);
+WINGDIAPI void APIENTRY glRasterPos2d (GLdouble x, GLdouble y);
+WINGDIAPI void APIENTRY glRasterPos2dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glRasterPos2f (GLfloat x, GLfloat y);
+WINGDIAPI void APIENTRY glRasterPos2fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glRasterPos2i (GLint x, GLint y);
+WINGDIAPI void APIENTRY glRasterPos2iv (const GLint *v);
+WINGDIAPI void APIENTRY glRasterPos2s (GLshort x, GLshort y);
+WINGDIAPI void APIENTRY glRasterPos2sv (const GLshort *v);
+WINGDIAPI void APIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z);
+WINGDIAPI void APIENTRY glRasterPos3dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z);
+WINGDIAPI void APIENTRY glRasterPos3fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glRasterPos3i (GLint x, GLint y, GLint z);
+WINGDIAPI void APIENTRY glRasterPos3iv (const GLint *v);
+WINGDIAPI void APIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z);
+WINGDIAPI void APIENTRY glRasterPos3sv (const GLshort *v);
+WINGDIAPI void APIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+WINGDIAPI void APIENTRY glRasterPos4dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+WINGDIAPI void APIENTRY glRasterPos4fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w);
+WINGDIAPI void APIENTRY glRasterPos4iv (const GLint *v);
+WINGDIAPI void APIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w);
+WINGDIAPI void APIENTRY glRasterPos4sv (const GLshort *v);
+WINGDIAPI void APIENTRY glReadBuffer (GLenum mode);
+WINGDIAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+WINGDIAPI void APIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+WINGDIAPI void APIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2);
+WINGDIAPI void APIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+WINGDIAPI void APIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2);
+WINGDIAPI void APIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2);
+WINGDIAPI void APIENTRY glRectiv (const GLint *v1, const GLint *v2);
+WINGDIAPI void APIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+WINGDIAPI void APIENTRY glRectsv (const GLshort *v1, const GLshort *v2);
+WINGDIAPI GLint APIENTRY glRenderMode (GLenum mode);
+WINGDIAPI void APIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+WINGDIAPI void APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+WINGDIAPI void APIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z);
+WINGDIAPI void APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z);
+WINGDIAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+WINGDIAPI void APIENTRY glSelectBuffer (GLsizei size, GLuint *buffer);
+WINGDIAPI void APIENTRY glShadeModel (GLenum mode);
+WINGDIAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+WINGDIAPI void APIENTRY glStencilMask (GLuint mask);
+WINGDIAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+WINGDIAPI void APIENTRY glTexCoord1d (GLdouble s);
+WINGDIAPI void APIENTRY glTexCoord1dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glTexCoord1f (GLfloat s);
+WINGDIAPI void APIENTRY glTexCoord1fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glTexCoord1i (GLint s);
+WINGDIAPI void APIENTRY glTexCoord1iv (const GLint *v);
+WINGDIAPI void APIENTRY glTexCoord1s (GLshort s);
+WINGDIAPI void APIENTRY glTexCoord1sv (const GLshort *v);
+WINGDIAPI void APIENTRY glTexCoord2d (GLdouble s, GLdouble t);
+WINGDIAPI void APIENTRY glTexCoord2dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glTexCoord2f (GLfloat s, GLfloat t);
+WINGDIAPI void APIENTRY glTexCoord2fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glTexCoord2i (GLint s, GLint t);
+WINGDIAPI void APIENTRY glTexCoord2iv (const GLint *v);
+WINGDIAPI void APIENTRY glTexCoord2s (GLshort s, GLshort t);
+WINGDIAPI void APIENTRY glTexCoord2sv (const GLshort *v);
+WINGDIAPI void APIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r);
+WINGDIAPI void APIENTRY glTexCoord3dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r);
+WINGDIAPI void APIENTRY glTexCoord3fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glTexCoord3i (GLint s, GLint t, GLint r);
+WINGDIAPI void APIENTRY glTexCoord3iv (const GLint *v);
+WINGDIAPI void APIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r);
+WINGDIAPI void APIENTRY glTexCoord3sv (const GLshort *v);
+WINGDIAPI void APIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+WINGDIAPI void APIENTRY glTexCoord4dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+WINGDIAPI void APIENTRY glTexCoord4fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q);
+WINGDIAPI void APIENTRY glTexCoord4iv (const GLint *v);
+WINGDIAPI void APIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q);
+WINGDIAPI void APIENTRY glTexCoord4sv (const GLshort *v);
+WINGDIAPI void APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+WINGDIAPI void APIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param);
+WINGDIAPI void APIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params);
+WINGDIAPI void APIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+WINGDIAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+WINGDIAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+WINGDIAPI void APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+WINGDIAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+WINGDIAPI void APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+WINGDIAPI void APIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+WINGDIAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+WINGDIAPI void APIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z);
+WINGDIAPI void APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
+WINGDIAPI void APIENTRY glVertex2d (GLdouble x, GLdouble y);
+WINGDIAPI void APIENTRY glVertex2dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glVertex2f (GLfloat x, GLfloat y);
+WINGDIAPI void APIENTRY glVertex2fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glVertex2i (GLint x, GLint y);
+WINGDIAPI void APIENTRY glVertex2iv (const GLint *v);
+WINGDIAPI void APIENTRY glVertex2s (GLshort x, GLshort y);
+WINGDIAPI void APIENTRY glVertex2sv (const GLshort *v);
+WINGDIAPI void APIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z);
+WINGDIAPI void APIENTRY glVertex3dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z);
+WINGDIAPI void APIENTRY glVertex3fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glVertex3i (GLint x, GLint y, GLint z);
+WINGDIAPI void APIENTRY glVertex3iv (const GLint *v);
+WINGDIAPI void APIENTRY glVertex3s (GLshort x, GLshort y, GLshort z);
+WINGDIAPI void APIENTRY glVertex3sv (const GLshort *v);
+WINGDIAPI void APIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+WINGDIAPI void APIENTRY glVertex4dv (const GLdouble *v);
+WINGDIAPI void APIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+WINGDIAPI void APIENTRY glVertex4fv (const GLfloat *v);
+WINGDIAPI void APIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w);
+WINGDIAPI void APIENTRY glVertex4iv (const GLint *v);
+WINGDIAPI void APIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w);
+WINGDIAPI void APIENTRY glVertex4sv (const GLshort *v);
+WINGDIAPI void APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+WINGDIAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+/* EXT_vertex_array */
+typedef void (APIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRY * PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);
+typedef void (APIENTRY * PFNGLARRAYELEMENTARRAYEXTPROC)(GLenum mode, GLsizei count, const GLvoid* pi);
+
+/* WIN_draw_range_elements */
+typedef void (APIENTRY * PFNGLDRAWRANGEELEMENTSWINPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+
+/* WIN_swap_hint */
+typedef void (APIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+/* EXT_paletted_texture */
+typedef void (APIENTRY * PFNGLCOLORTABLEEXTPROC)
+ (GLenum target, GLenum internalFormat, GLsizei width, GLenum format,
+ GLenum type, const GLvoid *data);
+typedef void (APIENTRY * PFNGLCOLORSUBTABLEEXTPROC)
+ (GLenum target, GLsizei start, GLsizei count, GLenum format,
+ GLenum type, const GLvoid *data);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEEXTPROC)
+ (GLenum target, GLenum format, GLenum type, GLvoid *data);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)
+ (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)
+ (GLenum target, GLenum pname, GLfloat *params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#if !defined (_WIN32)
+#undef WINGDIAPI
+#undef APIENTRY
+#endif
+
+#endif /* __GL_H__ */
+#endif /* __gl_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glcorearb.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glcorearb.h
new file mode 100644
index 00000000..07cb03e1
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glcorearb.h
@@ -0,0 +1,4533 @@
+#ifndef __glcorearb_h_
+#define __glcorearb_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* glcorearb.h replaces gl3.h. It is for use with OpenGL core
+ * profile implementations.
+ *
+ * glcorearb.h last updated on $Date: 2012-09-19 19:02:24 -0700 (Wed, 19 Sep 2012) $
+ *
+ * RELEASE NOTES - 2012/09/19
+ *
+ * glcorearb.h should be placed in the same directory as gl.h and
+ * included as
+ * '<GL/glcorearb.h>'.
+ *
+ * glcorearb.h includes only APIs in the latest OpenGL core profile
+ * implementation together with APIs in newer ARB extensions which can be
+ * can be supported by the core profile. It does not, and never will
+ * include functionality removed from the core profile, such as
+ * fixed-function vertex and fragment processing.
+ *
+ * It is not possible to #include both <GL/glcorearb.h> and either of
+ * <GL/gl.h> or <GL/glext.h> in the same source file.
+ *
+ * Feedback can be given by registering for the Khronos Bugzilla
+ * (www.khronos.org/bugzilla) and filing issues there under product
+ * "OpenGL", category "Registry".
+ */
+
+/* Function declaration macros - to move into glplatform.h */
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+/* Base GL types */
+
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef unsigned short GLhalf;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void GLvoid;
+
+/*************************************************************/
+
+#ifndef GL_VERSION_1_1
+/* AttribMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+/* AlphaFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+/* BlendingFactorSrc */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* DrawBufferMode */
+#define GL_NONE 0
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+#define GL_FRONT_AND_BACK 0x0408
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+/* GetPName */
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_VIEWPORT 0x0BA2
+#define GL_DITHER 0x0BD0
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND 0x0BE2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_READ_BUFFER 0x0C02
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+/* GetTextureParameter */
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_DOUBLE 0x140A
+/* ErrorCode */
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+/* LogicOp */
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+/* MatrixMode (for gl3.h, FBO attachment type) */
+#define GL_TEXTURE 0x1702
+/* PixelCopyType */
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+/* PixelFormat */
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+/* PolygonMode */
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+/* StencilOp */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+/* TextureMinFilter */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+/* TextureTarget */
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+/* PixelInternalFormat */
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#endif
+
+#ifndef GL_ARB_imaging
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#endif
+
+#ifndef GL_VERSION_2_1
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#endif
+
+#ifndef GL_VERSION_3_0
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+/* Reuse tokens from ARB_depth_buffer_float */
+/* reuse GL_DEPTH_COMPONENT32F */
+/* reuse GL_DEPTH32F_STENCIL8 */
+/* reuse GL_FLOAT_32_UNSIGNED_INT_24_8_REV */
+/* Reuse tokens from ARB_framebuffer_object */
+/* reuse GL_INVALID_FRAMEBUFFER_OPERATION */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */
+/* reuse GL_FRAMEBUFFER_DEFAULT */
+/* reuse GL_FRAMEBUFFER_UNDEFINED */
+/* reuse GL_DEPTH_STENCIL_ATTACHMENT */
+/* reuse GL_INDEX */
+/* reuse GL_MAX_RENDERBUFFER_SIZE */
+/* reuse GL_DEPTH_STENCIL */
+/* reuse GL_UNSIGNED_INT_24_8 */
+/* reuse GL_DEPTH24_STENCIL8 */
+/* reuse GL_TEXTURE_STENCIL_SIZE */
+/* reuse GL_TEXTURE_RED_TYPE */
+/* reuse GL_TEXTURE_GREEN_TYPE */
+/* reuse GL_TEXTURE_BLUE_TYPE */
+/* reuse GL_TEXTURE_ALPHA_TYPE */
+/* reuse GL_TEXTURE_DEPTH_TYPE */
+/* reuse GL_UNSIGNED_NORMALIZED */
+/* reuse GL_FRAMEBUFFER_BINDING */
+/* reuse GL_DRAW_FRAMEBUFFER_BINDING */
+/* reuse GL_RENDERBUFFER_BINDING */
+/* reuse GL_READ_FRAMEBUFFER */
+/* reuse GL_DRAW_FRAMEBUFFER */
+/* reuse GL_READ_FRAMEBUFFER_BINDING */
+/* reuse GL_RENDERBUFFER_SAMPLES */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */
+/* reuse GL_FRAMEBUFFER_COMPLETE */
+/* reuse GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */
+/* reuse GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */
+/* reuse GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER */
+/* reuse GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER */
+/* reuse GL_FRAMEBUFFER_UNSUPPORTED */
+/* reuse GL_MAX_COLOR_ATTACHMENTS */
+/* reuse GL_COLOR_ATTACHMENT0 */
+/* reuse GL_COLOR_ATTACHMENT1 */
+/* reuse GL_COLOR_ATTACHMENT2 */
+/* reuse GL_COLOR_ATTACHMENT3 */
+/* reuse GL_COLOR_ATTACHMENT4 */
+/* reuse GL_COLOR_ATTACHMENT5 */
+/* reuse GL_COLOR_ATTACHMENT6 */
+/* reuse GL_COLOR_ATTACHMENT7 */
+/* reuse GL_COLOR_ATTACHMENT8 */
+/* reuse GL_COLOR_ATTACHMENT9 */
+/* reuse GL_COLOR_ATTACHMENT10 */
+/* reuse GL_COLOR_ATTACHMENT11 */
+/* reuse GL_COLOR_ATTACHMENT12 */
+/* reuse GL_COLOR_ATTACHMENT13 */
+/* reuse GL_COLOR_ATTACHMENT14 */
+/* reuse GL_COLOR_ATTACHMENT15 */
+/* reuse GL_DEPTH_ATTACHMENT */
+/* reuse GL_STENCIL_ATTACHMENT */
+/* reuse GL_FRAMEBUFFER */
+/* reuse GL_RENDERBUFFER */
+/* reuse GL_RENDERBUFFER_WIDTH */
+/* reuse GL_RENDERBUFFER_HEIGHT */
+/* reuse GL_RENDERBUFFER_INTERNAL_FORMAT */
+/* reuse GL_STENCIL_INDEX1 */
+/* reuse GL_STENCIL_INDEX4 */
+/* reuse GL_STENCIL_INDEX8 */
+/* reuse GL_STENCIL_INDEX16 */
+/* reuse GL_RENDERBUFFER_RED_SIZE */
+/* reuse GL_RENDERBUFFER_GREEN_SIZE */
+/* reuse GL_RENDERBUFFER_BLUE_SIZE */
+/* reuse GL_RENDERBUFFER_ALPHA_SIZE */
+/* reuse GL_RENDERBUFFER_DEPTH_SIZE */
+/* reuse GL_RENDERBUFFER_STENCIL_SIZE */
+/* reuse GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */
+/* reuse GL_MAX_SAMPLES */
+/* Reuse tokens from ARB_framebuffer_sRGB */
+/* reuse GL_FRAMEBUFFER_SRGB */
+/* Reuse tokens from ARB_half_float_vertex */
+/* reuse GL_HALF_FLOAT */
+/* Reuse tokens from ARB_map_buffer_range */
+/* reuse GL_MAP_READ_BIT */
+/* reuse GL_MAP_WRITE_BIT */
+/* reuse GL_MAP_INVALIDATE_RANGE_BIT */
+/* reuse GL_MAP_INVALIDATE_BUFFER_BIT */
+/* reuse GL_MAP_FLUSH_EXPLICIT_BIT */
+/* reuse GL_MAP_UNSYNCHRONIZED_BIT */
+/* Reuse tokens from ARB_texture_compression_rgtc */
+/* reuse GL_COMPRESSED_RED_RGTC1 */
+/* reuse GL_COMPRESSED_SIGNED_RED_RGTC1 */
+/* reuse GL_COMPRESSED_RG_RGTC2 */
+/* reuse GL_COMPRESSED_SIGNED_RG_RGTC2 */
+/* Reuse tokens from ARB_texture_rg */
+/* reuse GL_RG */
+/* reuse GL_RG_INTEGER */
+/* reuse GL_R8 */
+/* reuse GL_R16 */
+/* reuse GL_RG8 */
+/* reuse GL_RG16 */
+/* reuse GL_R16F */
+/* reuse GL_R32F */
+/* reuse GL_RG16F */
+/* reuse GL_RG32F */
+/* reuse GL_R8I */
+/* reuse GL_R8UI */
+/* reuse GL_R16I */
+/* reuse GL_R16UI */
+/* reuse GL_R32I */
+/* reuse GL_R32UI */
+/* reuse GL_RG8I */
+/* reuse GL_RG8UI */
+/* reuse GL_RG16I */
+/* reuse GL_RG16UI */
+/* reuse GL_RG32I */
+/* reuse GL_RG32UI */
+/* Reuse tokens from ARB_vertex_array_object */
+/* reuse GL_VERTEX_ARRAY_BINDING */
+#endif
+
+#ifndef GL_VERSION_3_1
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+/* Reuse tokens from ARB_copy_buffer */
+/* reuse GL_COPY_READ_BUFFER */
+/* reuse GL_COPY_WRITE_BUFFER */
+/* Reuse tokens from ARB_draw_instanced (none) */
+/* Reuse tokens from ARB_uniform_buffer_object */
+/* reuse GL_UNIFORM_BUFFER */
+/* reuse GL_UNIFORM_BUFFER_BINDING */
+/* reuse GL_UNIFORM_BUFFER_START */
+/* reuse GL_UNIFORM_BUFFER_SIZE */
+/* reuse GL_MAX_VERTEX_UNIFORM_BLOCKS */
+/* reuse GL_MAX_FRAGMENT_UNIFORM_BLOCKS */
+/* reuse GL_MAX_COMBINED_UNIFORM_BLOCKS */
+/* reuse GL_MAX_UNIFORM_BUFFER_BINDINGS */
+/* reuse GL_MAX_UNIFORM_BLOCK_SIZE */
+/* reuse GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS */
+/* reuse GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT */
+/* reuse GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */
+/* reuse GL_ACTIVE_UNIFORM_BLOCKS */
+/* reuse GL_UNIFORM_TYPE */
+/* reuse GL_UNIFORM_SIZE */
+/* reuse GL_UNIFORM_NAME_LENGTH */
+/* reuse GL_UNIFORM_BLOCK_INDEX */
+/* reuse GL_UNIFORM_OFFSET */
+/* reuse GL_UNIFORM_ARRAY_STRIDE */
+/* reuse GL_UNIFORM_MATRIX_STRIDE */
+/* reuse GL_UNIFORM_IS_ROW_MAJOR */
+/* reuse GL_UNIFORM_BLOCK_BINDING */
+/* reuse GL_UNIFORM_BLOCK_DATA_SIZE */
+/* reuse GL_UNIFORM_BLOCK_NAME_LENGTH */
+/* reuse GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS */
+/* reuse GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES */
+/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER */
+/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER */
+/* reuse GL_INVALID_INDEX */
+#endif
+
+#ifndef GL_VERSION_3_2
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+/* reuse GL_MAX_VARYING_COMPONENTS */
+/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */
+/* Reuse tokens from ARB_depth_clamp */
+/* reuse GL_DEPTH_CLAMP */
+/* Reuse tokens from ARB_draw_elements_base_vertex (none) */
+/* Reuse tokens from ARB_fragment_coord_conventions (none) */
+/* Reuse tokens from ARB_provoking_vertex */
+/* reuse GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION */
+/* reuse GL_FIRST_VERTEX_CONVENTION */
+/* reuse GL_LAST_VERTEX_CONVENTION */
+/* reuse GL_PROVOKING_VERTEX */
+/* Reuse tokens from ARB_seamless_cube_map */
+/* reuse GL_TEXTURE_CUBE_MAP_SEAMLESS */
+/* Reuse tokens from ARB_sync */
+/* reuse GL_MAX_SERVER_WAIT_TIMEOUT */
+/* reuse GL_OBJECT_TYPE */
+/* reuse GL_SYNC_CONDITION */
+/* reuse GL_SYNC_STATUS */
+/* reuse GL_SYNC_FLAGS */
+/* reuse GL_SYNC_FENCE */
+/* reuse GL_SYNC_GPU_COMMANDS_COMPLETE */
+/* reuse GL_UNSIGNALED */
+/* reuse GL_SIGNALED */
+/* reuse GL_ALREADY_SIGNALED */
+/* reuse GL_TIMEOUT_EXPIRED */
+/* reuse GL_CONDITION_SATISFIED */
+/* reuse GL_WAIT_FAILED */
+/* reuse GL_TIMEOUT_IGNORED */
+/* reuse GL_SYNC_FLUSH_COMMANDS_BIT */
+/* reuse GL_TIMEOUT_IGNORED */
+/* Reuse tokens from ARB_texture_multisample */
+/* reuse GL_SAMPLE_POSITION */
+/* reuse GL_SAMPLE_MASK */
+/* reuse GL_SAMPLE_MASK_VALUE */
+/* reuse GL_MAX_SAMPLE_MASK_WORDS */
+/* reuse GL_TEXTURE_2D_MULTISAMPLE */
+/* reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE */
+/* reuse GL_TEXTURE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE */
+/* reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_TEXTURE_SAMPLES */
+/* reuse GL_TEXTURE_FIXED_SAMPLE_LOCATIONS */
+/* reuse GL_SAMPLER_2D_MULTISAMPLE */
+/* reuse GL_INT_SAMPLER_2D_MULTISAMPLE */
+/* reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE */
+/* reuse GL_SAMPLER_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_MAX_COLOR_TEXTURE_SAMPLES */
+/* reuse GL_MAX_DEPTH_TEXTURE_SAMPLES */
+/* reuse GL_MAX_INTEGER_SAMPLES */
+/* Don't need to reuse tokens from ARB_vertex_array_bgra since they're already in 1.2 core */
+#endif
+
+#ifndef GL_VERSION_3_3
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+/* Reuse tokens from ARB_blend_func_extended */
+/* reuse GL_SRC1_COLOR */
+/* reuse GL_ONE_MINUS_SRC1_COLOR */
+/* reuse GL_ONE_MINUS_SRC1_ALPHA */
+/* reuse GL_MAX_DUAL_SOURCE_DRAW_BUFFERS */
+/* Reuse tokens from ARB_explicit_attrib_location (none) */
+/* Reuse tokens from ARB_occlusion_query2 */
+/* reuse GL_ANY_SAMPLES_PASSED */
+/* Reuse tokens from ARB_sampler_objects */
+/* reuse GL_SAMPLER_BINDING */
+/* Reuse tokens from ARB_shader_bit_encoding (none) */
+/* Reuse tokens from ARB_texture_rgb10_a2ui */
+/* reuse GL_RGB10_A2UI */
+/* Reuse tokens from ARB_texture_swizzle */
+/* reuse GL_TEXTURE_SWIZZLE_R */
+/* reuse GL_TEXTURE_SWIZZLE_G */
+/* reuse GL_TEXTURE_SWIZZLE_B */
+/* reuse GL_TEXTURE_SWIZZLE_A */
+/* reuse GL_TEXTURE_SWIZZLE_RGBA */
+/* Reuse tokens from ARB_timer_query */
+/* reuse GL_TIME_ELAPSED */
+/* reuse GL_TIMESTAMP */
+/* Reuse tokens from ARB_vertex_type_2_10_10_10_rev */
+/* reuse GL_INT_2_10_10_10_REV */
+#endif
+
+#ifndef GL_VERSION_4_0
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+/* Reuse tokens from ARB_texture_query_lod (none) */
+/* Reuse tokens from ARB_draw_buffers_blend (none) */
+/* Reuse tokens from ARB_draw_indirect */
+/* reuse GL_DRAW_INDIRECT_BUFFER */
+/* reuse GL_DRAW_INDIRECT_BUFFER_BINDING */
+/* Reuse tokens from ARB_gpu_shader5 */
+/* reuse GL_GEOMETRY_SHADER_INVOCATIONS */
+/* reuse GL_MAX_GEOMETRY_SHADER_INVOCATIONS */
+/* reuse GL_MIN_FRAGMENT_INTERPOLATION_OFFSET */
+/* reuse GL_MAX_FRAGMENT_INTERPOLATION_OFFSET */
+/* reuse GL_FRAGMENT_INTERPOLATION_OFFSET_BITS */
+/* reuse GL_MAX_VERTEX_STREAMS */
+/* Reuse tokens from ARB_gpu_shader_fp64 */
+/* reuse GL_DOUBLE_VEC2 */
+/* reuse GL_DOUBLE_VEC3 */
+/* reuse GL_DOUBLE_VEC4 */
+/* reuse GL_DOUBLE_MAT2 */
+/* reuse GL_DOUBLE_MAT3 */
+/* reuse GL_DOUBLE_MAT4 */
+/* reuse GL_DOUBLE_MAT2x3 */
+/* reuse GL_DOUBLE_MAT2x4 */
+/* reuse GL_DOUBLE_MAT3x2 */
+/* reuse GL_DOUBLE_MAT3x4 */
+/* reuse GL_DOUBLE_MAT4x2 */
+/* reuse GL_DOUBLE_MAT4x3 */
+/* Reuse tokens from ARB_shader_subroutine */
+/* reuse GL_ACTIVE_SUBROUTINES */
+/* reuse GL_ACTIVE_SUBROUTINE_UNIFORMS */
+/* reuse GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS */
+/* reuse GL_ACTIVE_SUBROUTINE_MAX_LENGTH */
+/* reuse GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH */
+/* reuse GL_MAX_SUBROUTINES */
+/* reuse GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS */
+/* reuse GL_NUM_COMPATIBLE_SUBROUTINES */
+/* reuse GL_COMPATIBLE_SUBROUTINES */
+/* Reuse tokens from ARB_tessellation_shader */
+/* reuse GL_PATCHES */
+/* reuse GL_PATCH_VERTICES */
+/* reuse GL_PATCH_DEFAULT_INNER_LEVEL */
+/* reuse GL_PATCH_DEFAULT_OUTER_LEVEL */
+/* reuse GL_TESS_CONTROL_OUTPUT_VERTICES */
+/* reuse GL_TESS_GEN_MODE */
+/* reuse GL_TESS_GEN_SPACING */
+/* reuse GL_TESS_GEN_VERTEX_ORDER */
+/* reuse GL_TESS_GEN_POINT_MODE */
+/* reuse GL_ISOLINES */
+/* reuse GL_FRACTIONAL_ODD */
+/* reuse GL_FRACTIONAL_EVEN */
+/* reuse GL_MAX_PATCH_VERTICES */
+/* reuse GL_MAX_TESS_GEN_LEVEL */
+/* reuse GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS */
+/* reuse GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS */
+/* reuse GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS */
+/* reuse GL_MAX_TESS_PATCH_COMPONENTS */
+/* reuse GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS */
+/* reuse GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS */
+/* reuse GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS */
+/* reuse GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS */
+/* reuse GL_MAX_TESS_CONTROL_INPUT_COMPONENTS */
+/* reuse GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS */
+/* reuse GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS */
+/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER */
+/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER */
+/* reuse GL_TESS_EVALUATION_SHADER */
+/* reuse GL_TESS_CONTROL_SHADER */
+/* Reuse tokens from ARB_texture_buffer_object_rgb32 (none) */
+/* Reuse tokens from ARB_transform_feedback2 */
+/* reuse GL_TRANSFORM_FEEDBACK */
+/* reuse GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED */
+/* reuse GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE */
+/* reuse GL_TRANSFORM_FEEDBACK_BINDING */
+/* Reuse tokens from ARB_transform_feedback3 */
+/* reuse GL_MAX_TRANSFORM_FEEDBACK_BUFFERS */
+/* reuse GL_MAX_VERTEX_STREAMS */
+#endif
+
+#ifndef GL_VERSION_4_1
+/* Reuse tokens from ARB_ES2_compatibility */
+/* reuse GL_FIXED */
+/* reuse GL_IMPLEMENTATION_COLOR_READ_TYPE */
+/* reuse GL_IMPLEMENTATION_COLOR_READ_FORMAT */
+/* reuse GL_LOW_FLOAT */
+/* reuse GL_MEDIUM_FLOAT */
+/* reuse GL_HIGH_FLOAT */
+/* reuse GL_LOW_INT */
+/* reuse GL_MEDIUM_INT */
+/* reuse GL_HIGH_INT */
+/* reuse GL_SHADER_COMPILER */
+/* reuse GL_SHADER_BINARY_FORMATS */
+/* reuse GL_NUM_SHADER_BINARY_FORMATS */
+/* reuse GL_MAX_VERTEX_UNIFORM_VECTORS */
+/* reuse GL_MAX_VARYING_VECTORS */
+/* reuse GL_MAX_FRAGMENT_UNIFORM_VECTORS */
+/* reuse GL_RGB565 */
+/* Reuse tokens from ARB_get_program_binary */
+/* reuse GL_PROGRAM_BINARY_RETRIEVABLE_HINT */
+/* reuse GL_PROGRAM_BINARY_LENGTH */
+/* reuse GL_NUM_PROGRAM_BINARY_FORMATS */
+/* reuse GL_PROGRAM_BINARY_FORMATS */
+/* Reuse tokens from ARB_separate_shader_objects */
+/* reuse GL_VERTEX_SHADER_BIT */
+/* reuse GL_FRAGMENT_SHADER_BIT */
+/* reuse GL_GEOMETRY_SHADER_BIT */
+/* reuse GL_TESS_CONTROL_SHADER_BIT */
+/* reuse GL_TESS_EVALUATION_SHADER_BIT */
+/* reuse GL_ALL_SHADER_BITS */
+/* reuse GL_PROGRAM_SEPARABLE */
+/* reuse GL_ACTIVE_PROGRAM */
+/* reuse GL_PROGRAM_PIPELINE_BINDING */
+/* Reuse tokens from ARB_shader_precision (none) */
+/* Reuse tokens from ARB_vertex_attrib_64bit - all are in GL 3.0 and 4.0 already */
+/* Reuse tokens from ARB_viewport_array - some are in GL 1.1 and ARB_provoking_vertex already */
+/* reuse GL_MAX_VIEWPORTS */
+/* reuse GL_VIEWPORT_SUBPIXEL_BITS */
+/* reuse GL_VIEWPORT_BOUNDS_RANGE */
+/* reuse GL_LAYER_PROVOKING_VERTEX */
+/* reuse GL_VIEWPORT_INDEX_PROVOKING_VERTEX */
+/* reuse GL_UNDEFINED_VERTEX */
+#endif
+
+#ifndef GL_VERSION_4_2
+/* Reuse tokens from ARB_base_instance (none) */
+/* Reuse tokens from ARB_shading_language_420pack (none) */
+/* Reuse tokens from ARB_transform_feedback_instanced (none) */
+/* Reuse tokens from ARB_compressed_texture_pixel_storage */
+/* reuse GL_UNPACK_COMPRESSED_BLOCK_WIDTH */
+/* reuse GL_UNPACK_COMPRESSED_BLOCK_HEIGHT */
+/* reuse GL_UNPACK_COMPRESSED_BLOCK_DEPTH */
+/* reuse GL_UNPACK_COMPRESSED_BLOCK_SIZE */
+/* reuse GL_PACK_COMPRESSED_BLOCK_WIDTH */
+/* reuse GL_PACK_COMPRESSED_BLOCK_HEIGHT */
+/* reuse GL_PACK_COMPRESSED_BLOCK_DEPTH */
+/* reuse GL_PACK_COMPRESSED_BLOCK_SIZE */
+/* Reuse tokens from ARB_conservative_depth (none) */
+/* Reuse tokens from ARB_internalformat_query */
+/* reuse GL_NUM_SAMPLE_COUNTS */
+/* Reuse tokens from ARB_map_buffer_alignment */
+/* reuse GL_MIN_MAP_BUFFER_ALIGNMENT */
+/* Reuse tokens from ARB_shader_atomic_counters */
+/* reuse GL_ATOMIC_COUNTER_BUFFER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_BINDING */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_START */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_SIZE */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER */
+/* reuse GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_VERTEX_ATOMIC_COUNTERS */
+/* reuse GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS */
+/* reuse GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS */
+/* reuse GL_MAX_GEOMETRY_ATOMIC_COUNTERS */
+/* reuse GL_MAX_FRAGMENT_ATOMIC_COUNTERS */
+/* reuse GL_MAX_COMBINED_ATOMIC_COUNTERS */
+/* reuse GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE */
+/* reuse GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS */
+/* reuse GL_ACTIVE_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX */
+/* reuse GL_UNSIGNED_INT_ATOMIC_COUNTER */
+/* Reuse tokens from ARB_shader_image_load_store */
+/* reuse GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT */
+/* reuse GL_ELEMENT_ARRAY_BARRIER_BIT */
+/* reuse GL_UNIFORM_BARRIER_BIT */
+/* reuse GL_TEXTURE_FETCH_BARRIER_BIT */
+/* reuse GL_SHADER_IMAGE_ACCESS_BARRIER_BIT */
+/* reuse GL_COMMAND_BARRIER_BIT */
+/* reuse GL_PIXEL_BUFFER_BARRIER_BIT */
+/* reuse GL_TEXTURE_UPDATE_BARRIER_BIT */
+/* reuse GL_BUFFER_UPDATE_BARRIER_BIT */
+/* reuse GL_FRAMEBUFFER_BARRIER_BIT */
+/* reuse GL_TRANSFORM_FEEDBACK_BARRIER_BIT */
+/* reuse GL_ATOMIC_COUNTER_BARRIER_BIT */
+/* reuse GL_ALL_BARRIER_BITS */
+/* reuse GL_MAX_IMAGE_UNITS */
+/* reuse GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS */
+/* reuse GL_IMAGE_BINDING_NAME */
+/* reuse GL_IMAGE_BINDING_LEVEL */
+/* reuse GL_IMAGE_BINDING_LAYERED */
+/* reuse GL_IMAGE_BINDING_LAYER */
+/* reuse GL_IMAGE_BINDING_ACCESS */
+/* reuse GL_IMAGE_1D */
+/* reuse GL_IMAGE_2D */
+/* reuse GL_IMAGE_3D */
+/* reuse GL_IMAGE_2D_RECT */
+/* reuse GL_IMAGE_CUBE */
+/* reuse GL_IMAGE_BUFFER */
+/* reuse GL_IMAGE_1D_ARRAY */
+/* reuse GL_IMAGE_2D_ARRAY */
+/* reuse GL_IMAGE_CUBE_MAP_ARRAY */
+/* reuse GL_IMAGE_2D_MULTISAMPLE */
+/* reuse GL_IMAGE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_INT_IMAGE_1D */
+/* reuse GL_INT_IMAGE_2D */
+/* reuse GL_INT_IMAGE_3D */
+/* reuse GL_INT_IMAGE_2D_RECT */
+/* reuse GL_INT_IMAGE_CUBE */
+/* reuse GL_INT_IMAGE_BUFFER */
+/* reuse GL_INT_IMAGE_1D_ARRAY */
+/* reuse GL_INT_IMAGE_2D_ARRAY */
+/* reuse GL_INT_IMAGE_CUBE_MAP_ARRAY */
+/* reuse GL_INT_IMAGE_2D_MULTISAMPLE */
+/* reuse GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_UNSIGNED_INT_IMAGE_1D */
+/* reuse GL_UNSIGNED_INT_IMAGE_2D */
+/* reuse GL_UNSIGNED_INT_IMAGE_3D */
+/* reuse GL_UNSIGNED_INT_IMAGE_2D_RECT */
+/* reuse GL_UNSIGNED_INT_IMAGE_CUBE */
+/* reuse GL_UNSIGNED_INT_IMAGE_BUFFER */
+/* reuse GL_UNSIGNED_INT_IMAGE_1D_ARRAY */
+/* reuse GL_UNSIGNED_INT_IMAGE_2D_ARRAY */
+/* reuse GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY */
+/* reuse GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE */
+/* reuse GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_MAX_IMAGE_SAMPLES */
+/* reuse GL_IMAGE_BINDING_FORMAT */
+/* reuse GL_IMAGE_FORMAT_COMPATIBILITY_TYPE */
+/* reuse GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE */
+/* reuse GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS */
+/* reuse GL_MAX_VERTEX_IMAGE_UNIFORMS */
+/* reuse GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS */
+/* reuse GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS */
+/* reuse GL_MAX_GEOMETRY_IMAGE_UNIFORMS */
+/* reuse GL_MAX_FRAGMENT_IMAGE_UNIFORMS */
+/* reuse GL_MAX_COMBINED_IMAGE_UNIFORMS */
+/* Reuse tokens from ARB_shading_language_packing (none) */
+/* Reuse tokens from ARB_texture_storage */
+/* reuse GL_TEXTURE_IMMUTABLE_FORMAT */
+#endif
+
+#ifndef GL_VERSION_4_3
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+/* Reuse tokens from ARB_arrays_of_arrays (none, GLSL only) */
+/* Reuse tokens from ARB_fragment_layer_viewport (none, GLSL only) */
+/* Reuse tokens from ARB_shader_image_size (none, GLSL only) */
+/* Reuse tokens from ARB_ES3_compatibility */
+/* reuse GL_COMPRESSED_RGB8_ETC2 */
+/* reuse GL_COMPRESSED_SRGB8_ETC2 */
+/* reuse GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 */
+/* reuse GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 */
+/* reuse GL_COMPRESSED_RGBA8_ETC2_EAC */
+/* reuse GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC */
+/* reuse GL_COMPRESSED_R11_EAC */
+/* reuse GL_COMPRESSED_SIGNED_R11_EAC */
+/* reuse GL_COMPRESSED_RG11_EAC */
+/* reuse GL_COMPRESSED_SIGNED_RG11_EAC */
+/* reuse GL_PRIMITIVE_RESTART_FIXED_INDEX */
+/* reuse GL_ANY_SAMPLES_PASSED_CONSERVATIVE */
+/* reuse GL_MAX_ELEMENT_INDEX */
+/* Reuse tokens from ARB_clear_buffer_object (none) */
+/* Reuse tokens from ARB_compute_shader */
+/* reuse GL_COMPUTE_SHADER */
+/* reuse GL_MAX_COMPUTE_UNIFORM_BLOCKS */
+/* reuse GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS */
+/* reuse GL_MAX_COMPUTE_IMAGE_UNIFORMS */
+/* reuse GL_MAX_COMPUTE_SHARED_MEMORY_SIZE */
+/* reuse GL_MAX_COMPUTE_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_COMPUTE_ATOMIC_COUNTERS */
+/* reuse GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_COMPUTE_LOCAL_INVOCATIONS */
+/* reuse GL_MAX_COMPUTE_WORK_GROUP_COUNT */
+/* reuse GL_MAX_COMPUTE_WORK_GROUP_SIZE */
+/* reuse GL_COMPUTE_LOCAL_WORK_SIZE */
+/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER */
+/* reuse GL_DISPATCH_INDIRECT_BUFFER */
+/* reuse GL_DISPATCH_INDIRECT_BUFFER_BINDING */
+/* Reuse tokens from ARB_copy_image (none) */
+/* Reuse tokens from KHR_debug */
+/* reuse GL_DEBUG_OUTPUT_SYNCHRONOUS */
+/* reuse GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH */
+/* reuse GL_DEBUG_CALLBACK_FUNCTION */
+/* reuse GL_DEBUG_CALLBACK_USER_PARAM */
+/* reuse GL_DEBUG_SOURCE_API */
+/* reuse GL_DEBUG_SOURCE_WINDOW_SYSTEM */
+/* reuse GL_DEBUG_SOURCE_SHADER_COMPILER */
+/* reuse GL_DEBUG_SOURCE_THIRD_PARTY */
+/* reuse GL_DEBUG_SOURCE_APPLICATION */
+/* reuse GL_DEBUG_SOURCE_OTHER */
+/* reuse GL_DEBUG_TYPE_ERROR */
+/* reuse GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR */
+/* reuse GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR */
+/* reuse GL_DEBUG_TYPE_PORTABILITY */
+/* reuse GL_DEBUG_TYPE_PERFORMANCE */
+/* reuse GL_DEBUG_TYPE_OTHER */
+/* reuse GL_MAX_DEBUG_MESSAGE_LENGTH */
+/* reuse GL_MAX_DEBUG_LOGGED_MESSAGES */
+/* reuse GL_DEBUG_LOGGED_MESSAGES */
+/* reuse GL_DEBUG_SEVERITY_HIGH */
+/* reuse GL_DEBUG_SEVERITY_MEDIUM */
+/* reuse GL_DEBUG_SEVERITY_LOW */
+/* reuse GL_DEBUG_TYPE_MARKER */
+/* reuse GL_DEBUG_TYPE_PUSH_GROUP */
+/* reuse GL_DEBUG_TYPE_POP_GROUP */
+/* reuse GL_DEBUG_SEVERITY_NOTIFICATION */
+/* reuse GL_MAX_DEBUG_GROUP_STACK_DEPTH */
+/* reuse GL_DEBUG_GROUP_STACK_DEPTH */
+/* reuse GL_BUFFER */
+/* reuse GL_SHADER */
+/* reuse GL_PROGRAM */
+/* reuse GL_QUERY */
+/* reuse GL_PROGRAM_PIPELINE */
+/* reuse GL_SAMPLER */
+/* reuse GL_DISPLAY_LIST */
+/* reuse GL_MAX_LABEL_LENGTH */
+/* reuse GL_DEBUG_OUTPUT */
+/* reuse GL_CONTEXT_FLAG_DEBUG_BIT */
+/* reuse GL_STACK_UNDERFLOW */
+/* reuse GL_STACK_OVERFLOW */
+/* Reuse tokens from ARB_explicit_uniform_location */
+/* reuse GL_MAX_UNIFORM_LOCATIONS */
+/* Reuse tokens from ARB_framebuffer_no_attachments */
+/* reuse GL_FRAMEBUFFER_DEFAULT_WIDTH */
+/* reuse GL_FRAMEBUFFER_DEFAULT_HEIGHT */
+/* reuse GL_FRAMEBUFFER_DEFAULT_LAYERS */
+/* reuse GL_FRAMEBUFFER_DEFAULT_SAMPLES */
+/* reuse GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS */
+/* reuse GL_MAX_FRAMEBUFFER_WIDTH */
+/* reuse GL_MAX_FRAMEBUFFER_HEIGHT */
+/* reuse GL_MAX_FRAMEBUFFER_LAYERS */
+/* reuse GL_MAX_FRAMEBUFFER_SAMPLES */
+/* Reuse tokens from ARB_internalformat_query2 */
+/* reuse GL_INTERNALFORMAT_SUPPORTED */
+/* reuse GL_INTERNALFORMAT_PREFERRED */
+/* reuse GL_INTERNALFORMAT_RED_SIZE */
+/* reuse GL_INTERNALFORMAT_GREEN_SIZE */
+/* reuse GL_INTERNALFORMAT_BLUE_SIZE */
+/* reuse GL_INTERNALFORMAT_ALPHA_SIZE */
+/* reuse GL_INTERNALFORMAT_DEPTH_SIZE */
+/* reuse GL_INTERNALFORMAT_STENCIL_SIZE */
+/* reuse GL_INTERNALFORMAT_SHARED_SIZE */
+/* reuse GL_INTERNALFORMAT_RED_TYPE */
+/* reuse GL_INTERNALFORMAT_GREEN_TYPE */
+/* reuse GL_INTERNALFORMAT_BLUE_TYPE */
+/* reuse GL_INTERNALFORMAT_ALPHA_TYPE */
+/* reuse GL_INTERNALFORMAT_DEPTH_TYPE */
+/* reuse GL_INTERNALFORMAT_STENCIL_TYPE */
+/* reuse GL_MAX_WIDTH */
+/* reuse GL_MAX_HEIGHT */
+/* reuse GL_MAX_DEPTH */
+/* reuse GL_MAX_LAYERS */
+/* reuse GL_MAX_COMBINED_DIMENSIONS */
+/* reuse GL_COLOR_COMPONENTS */
+/* reuse GL_DEPTH_COMPONENTS */
+/* reuse GL_STENCIL_COMPONENTS */
+/* reuse GL_COLOR_RENDERABLE */
+/* reuse GL_DEPTH_RENDERABLE */
+/* reuse GL_STENCIL_RENDERABLE */
+/* reuse GL_FRAMEBUFFER_RENDERABLE */
+/* reuse GL_FRAMEBUFFER_RENDERABLE_LAYERED */
+/* reuse GL_FRAMEBUFFER_BLEND */
+/* reuse GL_READ_PIXELS */
+/* reuse GL_READ_PIXELS_FORMAT */
+/* reuse GL_READ_PIXELS_TYPE */
+/* reuse GL_TEXTURE_IMAGE_FORMAT */
+/* reuse GL_TEXTURE_IMAGE_TYPE */
+/* reuse GL_GET_TEXTURE_IMAGE_FORMAT */
+/* reuse GL_GET_TEXTURE_IMAGE_TYPE */
+/* reuse GL_MIPMAP */
+/* reuse GL_MANUAL_GENERATE_MIPMAP */
+/* reuse GL_AUTO_GENERATE_MIPMAP */
+/* reuse GL_COLOR_ENCODING */
+/* reuse GL_SRGB_READ */
+/* reuse GL_SRGB_WRITE */
+/* reuse GL_FILTER */
+/* reuse GL_VERTEX_TEXTURE */
+/* reuse GL_TESS_CONTROL_TEXTURE */
+/* reuse GL_TESS_EVALUATION_TEXTURE */
+/* reuse GL_GEOMETRY_TEXTURE */
+/* reuse GL_FRAGMENT_TEXTURE */
+/* reuse GL_COMPUTE_TEXTURE */
+/* reuse GL_TEXTURE_SHADOW */
+/* reuse GL_TEXTURE_GATHER */
+/* reuse GL_TEXTURE_GATHER_SHADOW */
+/* reuse GL_SHADER_IMAGE_LOAD */
+/* reuse GL_SHADER_IMAGE_STORE */
+/* reuse GL_SHADER_IMAGE_ATOMIC */
+/* reuse GL_IMAGE_TEXEL_SIZE */
+/* reuse GL_IMAGE_COMPATIBILITY_CLASS */
+/* reuse GL_IMAGE_PIXEL_FORMAT */
+/* reuse GL_IMAGE_PIXEL_TYPE */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE */
+/* reuse GL_TEXTURE_COMPRESSED_BLOCK_WIDTH */
+/* reuse GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT */
+/* reuse GL_TEXTURE_COMPRESSED_BLOCK_SIZE */
+/* reuse GL_CLEAR_BUFFER */
+/* reuse GL_TEXTURE_VIEW */
+/* reuse GL_VIEW_COMPATIBILITY_CLASS */
+/* reuse GL_FULL_SUPPORT */
+/* reuse GL_CAVEAT_SUPPORT */
+/* reuse GL_IMAGE_CLASS_4_X_32 */
+/* reuse GL_IMAGE_CLASS_2_X_32 */
+/* reuse GL_IMAGE_CLASS_1_X_32 */
+/* reuse GL_IMAGE_CLASS_4_X_16 */
+/* reuse GL_IMAGE_CLASS_2_X_16 */
+/* reuse GL_IMAGE_CLASS_1_X_16 */
+/* reuse GL_IMAGE_CLASS_4_X_8 */
+/* reuse GL_IMAGE_CLASS_2_X_8 */
+/* reuse GL_IMAGE_CLASS_1_X_8 */
+/* reuse GL_IMAGE_CLASS_11_11_10 */
+/* reuse GL_IMAGE_CLASS_10_10_10_2 */
+/* reuse GL_VIEW_CLASS_128_BITS */
+/* reuse GL_VIEW_CLASS_96_BITS */
+/* reuse GL_VIEW_CLASS_64_BITS */
+/* reuse GL_VIEW_CLASS_48_BITS */
+/* reuse GL_VIEW_CLASS_32_BITS */
+/* reuse GL_VIEW_CLASS_24_BITS */
+/* reuse GL_VIEW_CLASS_16_BITS */
+/* reuse GL_VIEW_CLASS_8_BITS */
+/* reuse GL_VIEW_CLASS_S3TC_DXT1_RGB */
+/* reuse GL_VIEW_CLASS_S3TC_DXT1_RGBA */
+/* reuse GL_VIEW_CLASS_S3TC_DXT3_RGBA */
+/* reuse GL_VIEW_CLASS_S3TC_DXT5_RGBA */
+/* reuse GL_VIEW_CLASS_RGTC1_RED */
+/* reuse GL_VIEW_CLASS_RGTC2_RG */
+/* reuse GL_VIEW_CLASS_BPTC_UNORM */
+/* reuse GL_VIEW_CLASS_BPTC_FLOAT */
+/* Reuse tokens from ARB_invalidate_subdata (none) */
+/* Reuse tokens from ARB_multi_draw_indirect (none) */
+/* Reuse tokens from ARB_program_interface_query */
+/* reuse GL_UNIFORM */
+/* reuse GL_UNIFORM_BLOCK */
+/* reuse GL_PROGRAM_INPUT */
+/* reuse GL_PROGRAM_OUTPUT */
+/* reuse GL_BUFFER_VARIABLE */
+/* reuse GL_SHADER_STORAGE_BLOCK */
+/* reuse GL_VERTEX_SUBROUTINE */
+/* reuse GL_TESS_CONTROL_SUBROUTINE */
+/* reuse GL_TESS_EVALUATION_SUBROUTINE */
+/* reuse GL_GEOMETRY_SUBROUTINE */
+/* reuse GL_FRAGMENT_SUBROUTINE */
+/* reuse GL_COMPUTE_SUBROUTINE */
+/* reuse GL_VERTEX_SUBROUTINE_UNIFORM */
+/* reuse GL_TESS_CONTROL_SUBROUTINE_UNIFORM */
+/* reuse GL_TESS_EVALUATION_SUBROUTINE_UNIFORM */
+/* reuse GL_GEOMETRY_SUBROUTINE_UNIFORM */
+/* reuse GL_FRAGMENT_SUBROUTINE_UNIFORM */
+/* reuse GL_COMPUTE_SUBROUTINE_UNIFORM */
+/* reuse GL_TRANSFORM_FEEDBACK_VARYING */
+/* reuse GL_ACTIVE_RESOURCES */
+/* reuse GL_MAX_NAME_LENGTH */
+/* reuse GL_MAX_NUM_ACTIVE_VARIABLES */
+/* reuse GL_MAX_NUM_COMPATIBLE_SUBROUTINES */
+/* reuse GL_NAME_LENGTH */
+/* reuse GL_TYPE */
+/* reuse GL_ARRAY_SIZE */
+/* reuse GL_OFFSET */
+/* reuse GL_BLOCK_INDEX */
+/* reuse GL_ARRAY_STRIDE */
+/* reuse GL_MATRIX_STRIDE */
+/* reuse GL_IS_ROW_MAJOR */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_INDEX */
+/* reuse GL_BUFFER_BINDING */
+/* reuse GL_BUFFER_DATA_SIZE */
+/* reuse GL_NUM_ACTIVE_VARIABLES */
+/* reuse GL_ACTIVE_VARIABLES */
+/* reuse GL_REFERENCED_BY_VERTEX_SHADER */
+/* reuse GL_REFERENCED_BY_TESS_CONTROL_SHADER */
+/* reuse GL_REFERENCED_BY_TESS_EVALUATION_SHADER */
+/* reuse GL_REFERENCED_BY_GEOMETRY_SHADER */
+/* reuse GL_REFERENCED_BY_FRAGMENT_SHADER */
+/* reuse GL_REFERENCED_BY_COMPUTE_SHADER */
+/* reuse GL_TOP_LEVEL_ARRAY_SIZE */
+/* reuse GL_TOP_LEVEL_ARRAY_STRIDE */
+/* reuse GL_LOCATION */
+/* reuse GL_LOCATION_INDEX */
+/* reuse GL_IS_PER_PATCH */
+/* Reuse tokens from ARB_robust_buffer_access_behavior (none) */
+/* Reuse tokens from ARB_shader_storage_buffer_object */
+/* reuse GL_SHADER_STORAGE_BUFFER */
+/* reuse GL_SHADER_STORAGE_BUFFER_BINDING */
+/* reuse GL_SHADER_STORAGE_BUFFER_START */
+/* reuse GL_SHADER_STORAGE_BUFFER_SIZE */
+/* reuse GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS */
+/* reuse GL_MAX_SHADER_STORAGE_BLOCK_SIZE */
+/* reuse GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT */
+/* reuse GL_SHADER_STORAGE_BARRIER_BIT */
+/* reuse GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES */
+/* Reuse tokens from ARB_stencil_texturing */
+/* reuse GL_DEPTH_STENCIL_TEXTURE_MODE */
+/* Reuse tokens from ARB_texture_buffer_range */
+/* reuse GL_TEXTURE_BUFFER_OFFSET */
+/* reuse GL_TEXTURE_BUFFER_SIZE */
+/* reuse GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT */
+/* Reuse tokens from ARB_texture_query_levels (none) */
+/* Reuse tokens from ARB_texture_storage_multisample (none) */
+/* Reuse tokens from ARB_texture_view */
+/* reuse GL_TEXTURE_VIEW_MIN_LEVEL */
+/* reuse GL_TEXTURE_VIEW_NUM_LEVELS */
+/* reuse GL_TEXTURE_VIEW_MIN_LAYER */
+/* reuse GL_TEXTURE_VIEW_NUM_LAYERS */
+/* reuse GL_TEXTURE_IMMUTABLE_LEVELS */
+/* Reuse tokens from ARB_vertex_attrib_binding */
+/* reuse GL_VERTEX_ATTRIB_BINDING */
+/* reuse GL_VERTEX_ATTRIB_RELATIVE_OFFSET */
+/* reuse GL_VERTEX_BINDING_DIVISOR */
+/* reuse GL_VERTEX_BINDING_OFFSET */
+/* reuse GL_VERTEX_BINDING_STRIDE */
+/* reuse GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET */
+/* reuse GL_MAX_VERTEX_ATTRIB_BINDINGS */
+#endif
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#endif
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#endif
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_HALF_FLOAT 0x140B
+#endif
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#endif
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#endif
+
+#ifndef GL_ARB_texture_rg
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#endif
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#endif
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#endif
+
+#ifndef GL_ARB_copy_buffer
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_READ_BUFFER GL_COPY_READ_BUFFER_BINDING
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_COPY_WRITE_BUFFER GL_COPY_WRITE_BUFFER_BINDING
+#endif
+
+#ifndef GL_ARB_depth_clamp
+#define GL_DEPTH_CLAMP 0x864F
+#endif
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#endif
+
+#ifndef GL_ARB_fragment_coord_conventions
+#endif
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+#endif
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#endif
+
+#ifndef GL_ARB_sync
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#endif
+
+#ifndef GL_ARB_texture_multisample
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#endif
+
+#ifndef GL_ARB_vertex_array_bgra
+/* reuse GL_BGRA */
+#endif
+
+#ifndef GL_ARB_draw_buffers_blend
+#endif
+
+#ifndef GL_ARB_sample_shading
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+#endif
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#endif
+
+#ifndef GL_ARB_texture_gather
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+#endif
+
+#ifndef GL_ARB_texture_query_lod
+#endif
+
+#ifndef GL_ARB_shading_language_include
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+#endif
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+#endif
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_SRC1_COLOR 0x88F9
+/* reuse GL_SRC1_ALPHA */
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#endif
+
+#ifndef GL_ARB_explicit_attrib_location
+#endif
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#endif
+
+#ifndef GL_ARB_sampler_objects
+#define GL_SAMPLER_BINDING 0x8919
+#endif
+
+#ifndef GL_ARB_shader_bit_encoding
+#endif
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_RGB10_A2UI 0x906F
+#endif
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#endif
+
+#ifndef GL_ARB_timer_query
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+#endif
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+/* reuse GL_UNSIGNED_INT_2_10_10_10_REV */
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#endif
+
+#ifndef GL_ARB_draw_indirect
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#endif
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+/* reuse GL_MAX_VERTEX_STREAMS */
+#endif
+
+#ifndef GL_ARB_gpu_shader_fp64
+/* reuse GL_DOUBLE */
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#endif
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+/* reuse GL_UNIFORM_SIZE */
+/* reuse GL_UNIFORM_NAME_LENGTH */
+#endif
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_PATCHES 0x000E
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+/* reuse GL_TRIANGLES */
+/* reuse GL_QUADS */
+#define GL_ISOLINES 0x8E7A
+/* reuse GL_EQUAL */
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+/* reuse GL_CCW */
+/* reuse GL_CW */
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#endif
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+/* reuse GL_RGB32F */
+/* reuse GL_RGB32UI */
+/* reuse GL_RGB32I */
+#endif
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED GL_TRANSFORM_FEEDBACK_PAUSED
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE GL_TRANSFORM_FEEDBACK_ACTIVE
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#endif
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#endif
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_RGB565 0x8D62
+#endif
+
+#ifndef GL_ARB_get_program_binary
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#endif
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#endif
+
+#ifndef GL_ARB_shader_precision
+#endif
+
+#ifndef GL_ARB_vertex_attrib_64bit
+/* reuse GL_RGB32I */
+/* reuse GL_DOUBLE_VEC2 */
+/* reuse GL_DOUBLE_VEC3 */
+/* reuse GL_DOUBLE_VEC4 */
+/* reuse GL_DOUBLE_MAT2 */
+/* reuse GL_DOUBLE_MAT3 */
+/* reuse GL_DOUBLE_MAT4 */
+/* reuse GL_DOUBLE_MAT2x3 */
+/* reuse GL_DOUBLE_MAT2x4 */
+/* reuse GL_DOUBLE_MAT3x2 */
+/* reuse GL_DOUBLE_MAT3x4 */
+/* reuse GL_DOUBLE_MAT4x2 */
+/* reuse GL_DOUBLE_MAT4x3 */
+#endif
+
+#ifndef GL_ARB_viewport_array
+/* reuse GL_SCISSOR_BOX */
+/* reuse GL_VIEWPORT */
+/* reuse GL_DEPTH_RANGE */
+/* reuse GL_SCISSOR_TEST */
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+/* reuse GL_FIRST_VERTEX_CONVENTION */
+/* reuse GL_LAST_VERTEX_CONVENTION */
+/* reuse GL_PROVOKING_VERTEX */
+#endif
+
+#ifndef GL_ARB_cl_event
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+#endif
+
+#ifndef GL_ARB_debug_output
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#endif
+
+#ifndef GL_ARB_robustness
+/* reuse GL_NO_ERROR */
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+#endif
+
+#ifndef GL_ARB_shader_stencil_export
+#endif
+
+#ifndef GL_ARB_base_instance
+#endif
+
+#ifndef GL_ARB_shading_language_420pack
+#endif
+
+#ifndef GL_ARB_transform_feedback_instanced
+#endif
+
+#ifndef GL_ARB_compressed_texture_pixel_storage
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#endif
+
+#ifndef GL_ARB_conservative_depth
+#endif
+
+#ifndef GL_ARB_internalformat_query
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#endif
+
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#endif
+
+#ifndef GL_ARB_shader_atomic_counters
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#endif
+
+#ifndef GL_ARB_shader_image_load_store
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#endif
+
+#ifndef GL_ARB_shading_language_packing
+#endif
+
+#ifndef GL_ARB_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif
+
+#ifndef GL_KHR_debug
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_DISPLAY_LIST 0x82E7
+/* DISPLAY_LIST used in compatibility profile only */
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+/* reuse GL_STACK_UNDERFLOW */
+/* reuse GL_STACK_OVERFLOW */
+#endif
+
+#ifndef GL_ARB_arrays_of_arrays
+#endif
+
+#ifndef GL_ARB_clear_buffer_object
+#endif
+
+#ifndef GL_ARB_compute_shader
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_LOCAL_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_COMPUTE_LOCAL_WORK_SIZE 0x8267
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#endif
+
+#ifndef GL_ARB_copy_image
+#endif
+
+#ifndef GL_ARB_texture_view
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#endif
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#endif
+
+#ifndef GL_ARB_robustness_isolation
+#endif
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#endif
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#endif
+
+#ifndef GL_ARB_fragment_layer_viewport
+#endif
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#endif
+
+#ifndef GL_ARB_internalformat_query2
+/* reuse GL_IMAGE_FORMAT_COMPATIBILITY_TYPE */
+/* reuse GL_NUM_SAMPLE_COUNTS */
+/* reuse GL_RENDERBUFFER */
+/* reuse GL_SAMPLES */
+/* reuse GL_TEXTURE_1D */
+/* reuse GL_TEXTURE_1D_ARRAY */
+/* reuse GL_TEXTURE_2D */
+/* reuse GL_TEXTURE_2D_ARRAY */
+/* reuse GL_TEXTURE_3D */
+/* reuse GL_TEXTURE_CUBE_MAP */
+/* reuse GL_TEXTURE_CUBE_MAP_ARRAY */
+/* reuse GL_TEXTURE_RECTANGLE */
+/* reuse GL_TEXTURE_BUFFER */
+/* reuse GL_TEXTURE_2D_MULTISAMPLE */
+/* reuse GL_TEXTURE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_TEXTURE_COMPRESSED */
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_MAX_WIDTH 0x827E
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_MIPMAP 0x8293
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_COLOR_ENCODING 0x8296
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_SRGB_DECODE_ARB 0x8299
+#define GL_FILTER 0x829A
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#endif
+
+#ifndef GL_ARB_invalidate_subdata
+#endif
+
+#ifndef GL_ARB_multi_draw_indirect
+#endif
+
+#ifndef GL_ARB_program_interface_query
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+/* reuse GL_ATOMIC_COUNTER_BUFFER */
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+#define GL_IS_PER_PATCH 0x92E7
+/* reuse GL_NUM_COMPATIBLE_SUBROUTINES */
+/* reuse GL_COMPATIBLE_SUBROUTINES */
+#endif
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#endif
+
+#ifndef GL_ARB_shader_image_size
+#endif
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x2000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS
+/* reuse GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS */
+#endif
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#endif
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#endif
+
+#ifndef GL_ARB_texture_query_levels
+#endif
+
+#ifndef GL_ARB_texture_storage_multisample
+#endif
+
+
+/*************************************************************/
+
+#include <stddef.h>
+#ifndef GL_VERSION_2_0
+/* GL type for program/shader text */
+typedef char GLchar;
+#endif
+
+#ifndef GL_VERSION_1_5
+/* GL types for handling large vertex buffer objects */
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+/* GL types for handling large vertex buffer objects */
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+#endif
+
+#ifndef GL_ARB_shader_objects
+/* GL types for program/shader text and shader object handles */
+typedef char GLcharARB;
+typedef unsigned int GLhandleARB;
+#endif
+
+/* GL type for "half" precision (s10e5) float data in host memory */
+#ifndef GL_ARB_half_float_pixel
+typedef unsigned short GLhalfARB;
+#endif
+
+#ifndef GL_NV_half_float
+typedef unsigned short GLhalfNV;
+#endif
+
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glxext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GL_EXT_timer_query extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
+#endif
+#endif
+
+#ifndef GL_EXT_timer_query
+typedef int64_t GLint64EXT;
+typedef uint64_t GLuint64EXT;
+#endif
+
+#ifndef GL_ARB_sync
+typedef int64_t GLint64;
+typedef uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+#endif
+
+#ifndef GL_ARB_cl_event
+/* These incomplete types let us declare types compatible with OpenCL's cl_context and cl_event */
+struct _cl_context;
+struct _cl_event;
+#endif
+
+#ifndef GL_ARB_debug_output
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
+#ifndef GL_AMD_debug_output
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
+#ifndef GL_KHR_debug
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
+#ifndef GL_NV_vdpau_interop
+typedef GLintptr GLvdpauSurfaceNV;
+#endif
+
+#ifndef GL_VERSION_1_0
+#define GL_VERSION_1_0 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glCullFace (GLenum mode);
+GLAPI void APIENTRY glFrontFace (GLenum mode);
+GLAPI void APIENTRY glHint (GLenum target, GLenum mode);
+GLAPI void APIENTRY glLineWidth (GLfloat width);
+GLAPI void APIENTRY glPointSize (GLfloat size);
+GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
+GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glDrawBuffer (GLenum mode);
+GLAPI void APIENTRY glClear (GLbitfield mask);
+GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void APIENTRY glClearStencil (GLint s);
+GLAPI void APIENTRY glClearDepth (GLdouble depth);
+GLAPI void APIENTRY glStencilMask (GLuint mask);
+GLAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GLAPI void APIENTRY glDepthMask (GLboolean flag);
+GLAPI void APIENTRY glDisable (GLenum cap);
+GLAPI void APIENTRY glEnable (GLenum cap);
+GLAPI void APIENTRY glFinish (void);
+GLAPI void APIENTRY glFlush (void);
+GLAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GLAPI void APIENTRY glLogicOp (GLenum opcode);
+GLAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GLAPI void APIENTRY glDepthFunc (GLenum func);
+GLAPI void APIENTRY glPixelStoref (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
+GLAPI void APIENTRY glReadBuffer (GLenum mode);
+GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void APIENTRY glGetBooleanv (GLenum pname, GLboolean *params);
+GLAPI void APIENTRY glGetDoublev (GLenum pname, GLdouble *params);
+GLAPI GLenum APIENTRY glGetError (void);
+GLAPI void APIENTRY glGetFloatv (GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *params);
+GLAPI const GLubyte * APIENTRY glGetString (GLenum name);
+GLAPI void APIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
+GLAPI void APIENTRY glDepthRange (GLdouble near, GLdouble far);
+GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef void (APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (APIENTRYP PFNGLPOINTSIZEPROC) (GLfloat size);
+typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLDRAWBUFFERPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (APIENTRYP PFNGLCLEARDEPTHPROC) (GLdouble depth);
+typedef void (APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (APIENTRYP PFNGLLOGICOPPROC) (GLenum opcode);
+typedef void (APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (APIENTRYP PFNGLPIXELSTOREFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLREADBUFFERPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+typedef void (APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *params);
+typedef void (APIENTRYP PFNGLGETDOUBLEVPROC) (GLenum pname, GLdouble *params);
+typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
+typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLDEPTHRANGEPROC) (GLdouble near, GLdouble far);
+typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_VERSION_1_1
+#define GL_VERSION_1_1 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void APIENTRY glGetPointerv (GLenum pname, GLvoid* *params);
+GLAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GLAPI void APIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
+GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GLAPI GLboolean APIENTRY glIsTexture (GLuint texture);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, GLvoid* *params);
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void APIENTRY glBlendEquation (GLenum mode);
+GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum texture);
+GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, GLvoid *img);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount);
+GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint id);
+GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQuery (GLenum target);
+GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer);
+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+GLAPI GLvoid* APIENTRY glMapBuffer (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GLAPI void APIENTRY glCompileShader (GLuint shader);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum type);
+GLAPI void APIENTRY glDeleteProgram (GLuint program);
+GLAPI void APIENTRY glDeleteShader (GLuint shader);
+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid* *pointer);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
+GLAPI GLboolean APIENTRY glIsShader (GLuint shader);
+GLAPI void APIENTRY glLinkProgram (GLuint program);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
+GLAPI void APIENTRY glUseProgram (GLuint program);
+GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glValidateProgram (GLuint program);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+/* OpenGL 3.0 also reuses entry points from these extensions: */
+/* ARB_framebuffer_object */
+/* ARB_map_buffer_range */
+/* ARB_vertex_array_object */
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glEnablei (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisablei (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedback (void);
+GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const *varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp);
+GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRender (void);
+GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI const GLubyte * APIENTRY glGetStringi (GLenum name, GLuint index);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar* const *varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+#endif
+
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+/* OpenGL 3.1 also reuses entry points from these extensions: */
+/* ARB_copy_buffer */
+/* ARB_uniform_buffer_object */
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount);
+GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index);
+#endif
+
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+/* OpenGL 3.2 also reuses entry points from these extensions: */
+/* ARB_draw_elements_base_vertex */
+/* ARB_provoking_vertex */
+/* ARB_sync */
+/* ARB_texture_multisample */
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+/* OpenGL 3.3 also reuses entry points from these extensions: */
+/* ARB_blend_func_extended */
+/* ARB_sampler_objects */
+/* ARB_explicit_attrib_location, but it has none */
+/* ARB_occlusion_query2 (no entry points) */
+/* ARB_shader_bit_encoding (no entry points) */
+/* ARB_texture_rgb10_a2ui (no entry points) */
+/* ARB_texture_swizzle (no entry points) */
+/* ARB_timer_query */
+/* ARB_vertex_type_2_10_10_10_rev */
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+#endif
+
+#ifndef GL_VERSION_4_0
+#define GL_VERSION_4_0 1
+/* OpenGL 4.0 also reuses entry points from these extensions: */
+/* ARB_texture_query_lod (no entry points) */
+/* ARB_draw_indirect */
+/* ARB_gpu_shader5 (no entry points) */
+/* ARB_gpu_shader_fp64 */
+/* ARB_shader_subroutine */
+/* ARB_tessellation_shader */
+/* ARB_texture_buffer_object_rgb32 (no entry points) */
+/* ARB_texture_cube_map_array (no entry points) */
+/* ARB_texture_gather (no entry points) */
+/* ARB_transform_feedback2 */
+/* ARB_transform_feedback3 */
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShading (GLfloat value);
+GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+
+#ifndef GL_VERSION_4_1
+#define GL_VERSION_4_1 1
+/* OpenGL 4.1 reuses entry points from these extensions: */
+/* ARB_ES2_compatibility */
+/* ARB_get_program_binary */
+/* ARB_separate_shader_objects */
+/* ARB_shader_precision (no entry points) */
+/* ARB_vertex_attrib_64bit */
+/* ARB_viewport_array */
+#endif
+
+#ifndef GL_VERSION_4_2
+#define GL_VERSION_4_2 1
+/* OpenGL 4.2 reuses entry points from these extensions: */
+/* ARB_base_instance */
+/* ARB_shading_language_420pack (no entry points) */
+/* ARB_transform_feedback_instanced */
+/* ARB_compressed_texture_pixel_storage (no entry points) */
+/* ARB_conservative_depth (no entry points) */
+/* ARB_internalformat_query */
+/* ARB_map_buffer_alignment (no entry points) */
+/* ARB_shader_atomic_counters */
+/* ARB_shader_image_load_store */
+/* ARB_shading_language_packing (no entry points) */
+/* ARB_texture_storage */
+#endif
+
+#ifndef GL_VERSION_4_3
+#define GL_VERSION_4_3 1
+/* OpenGL 4.3 reuses entry points from these extensions: */
+/* ARB_arrays_of_arrays (no entry points, GLSL only) */
+/* ARB_fragment_layer_viewport (no entry points, GLSL only) */
+/* ARB_shader_image_size (no entry points, GLSL only) */
+/* ARB_ES3_compatibility (no entry points) */
+/* ARB_clear_buffer_object */
+/* ARB_compute_shader */
+/* ARB_copy_image */
+/* KHR_debug (includes ARB_debug_output commands promoted to KHR without suffixes) */
+/* ARB_explicit_uniform_location (no entry points) */
+/* ARB_framebuffer_no_attachments */
+/* ARB_internalformat_query2 */
+/* ARB_invalidate_subdata */
+/* ARB_multi_draw_indirect */
+/* ARB_program_interface_query */
+/* ARB_robust_buffer_access_behavior (no entry points) */
+/* ARB_shader_storage_buffer_object */
+/* ARB_stencil_texturing (no entry points) */
+/* ARB_texture_buffer_range */
+/* ARB_texture_query_levels (no entry points) */
+/* ARB_texture_storage_multisample */
+/* ARB_texture_view */
+/* ARB_vertex_attrib_binding */
+#endif
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_ARB_depth_buffer_float 1
+#endif
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_ARB_framebuffer_object 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmap (GLenum target);
+GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#endif
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_ARB_framebuffer_sRGB 1
+#endif
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_ARB_half_float_vertex 1
+#endif
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI GLvoid* APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc 1
+#endif
+
+#ifndef GL_ARB_texture_rg
+#define GL_ARB_texture_rg 1
+#endif
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_ARB_vertex_array_object 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArray (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+#endif
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_ARB_uniform_buffer_object 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const *uniformNames, GLuint *uniformIndices);
+GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* const *uniformNames, GLuint *uniformIndices);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif
+
+#ifndef GL_ARB_depth_clamp
+#define GL_ARB_depth_clamp 1
+#endif
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#define GL_ARB_draw_elements_base_vertex 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount, GLint basevertex);
+GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint *basevertex);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount, GLint basevertex);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint *basevertex);
+#endif
+
+#ifndef GL_ARB_fragment_coord_conventions
+#define GL_ARB_fragment_coord_conventions 1
+#endif
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_ARB_provoking_vertex 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glProvokingVertex (GLenum mode);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+#endif
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_ARB_seamless_cube_map 1
+#endif
+
+#ifndef GL_ARB_sync
+#define GL_ARB_sync 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GLAPI GLboolean APIENTRY glIsSync (GLsync sync);
+GLAPI void APIENTRY glDeleteSync (GLsync sync);
+GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+
+#ifndef GL_ARB_texture_multisample
+#define GL_ARB_texture_multisample 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaski (GLuint index, GLbitfield mask);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask);
+#endif
+
+#ifndef GL_ARB_vertex_array_bgra
+#define GL_ARB_vertex_array_bgra 1
+#endif
+
+#ifndef GL_ARB_draw_buffers_blend
+#define GL_ARB_draw_buffers_blend 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+
+#ifndef GL_ARB_sample_shading
+#define GL_ARB_sample_shading 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value);
+#endif
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_ARB_texture_cube_map_array 1
+#endif
+
+#ifndef GL_ARB_texture_gather
+#define GL_ARB_texture_gather 1
+#endif
+
+#ifndef GL_ARB_texture_query_lod
+#define GL_ARB_texture_query_lod 1
+#endif
+
+#ifndef GL_ARB_shading_language_include
+#define GL_ARB_shading_language_include 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar* *path, const GLint *length);
+GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar* *path, const GLint *length);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_ARB_texture_compression_bptc 1
+#endif
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_ARB_blend_func_extended 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name);
+#endif
+
+#ifndef GL_ARB_explicit_attrib_location
+#define GL_ARB_explicit_attrib_location 1
+#endif
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ARB_occlusion_query2 1
+#endif
+
+#ifndef GL_ARB_sampler_objects
+#define GL_ARB_sampler_objects 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler);
+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_ARB_shader_bit_encoding
+#define GL_ARB_shader_bit_encoding 1
+#endif
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_ARB_texture_rgb10_a2ui 1
+#endif
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_ARB_texture_swizzle 1
+#endif
+
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target);
+GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+#endif
+
+#ifndef GL_ARB_draw_indirect
+#define GL_ARB_draw_indirect 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const GLvoid *indirect);
+GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect);
+#endif
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_ARB_gpu_shader5 1
+#endif
+
+#ifndef GL_ARB_gpu_shader_fp64
+#define GL_ARB_gpu_shader_fp64 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x);
+GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params);
+#endif
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ARB_shader_subroutine 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices);
+GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params);
+GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices);
+typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+#endif
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_ARB_tessellation_shader 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values);
+#endif
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+#define GL_ARB_texture_buffer_object_rgb32 1
+#endif
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_ARB_transform_feedback2 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedback (void);
+GLAPI void APIENTRY glResumeTransformFeedback (void);
+GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+#endif
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_ARB_transform_feedback3 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream);
+GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id);
+GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_ARB_ES2_compatibility 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glReleaseShaderCompiler (void);
+GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
+GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GLAPI void APIENTRY glClearDepthf (GLfloat d);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+#endif
+
+#ifndef GL_ARB_get_program_binary
+#define GL_ARB_get_program_binary 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length);
+GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+#endif
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_ARB_separate_shader_objects 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar* const *strings);
+GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0);
+GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar* const *strings);
+typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+#ifndef GL_ARB_vertex_attrib_64bit
+#define GL_ARB_vertex_attrib_64bit 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+#endif
+
+#ifndef GL_ARB_viewport_array
+#define GL_ARB_viewport_array 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v);
+GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f);
+GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f);
+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
+#endif
+
+#ifndef GL_ARB_cl_event
+#define GL_ARB_cl_event 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context * context, struct _cl_event * event, GLbitfield flags);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context * context, struct _cl_event * event, GLbitfield flags);
+#endif
+
+#ifndef GL_ARB_debug_output
+#define GL_ARB_debug_output 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const GLvoid *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif
+
+#ifndef GL_ARB_robustness
+#define GL_ARB_robustness 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void);
+GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *img);
+GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, GLvoid *img);
+GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *img);
+typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, GLvoid *img);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+#endif
+
+#ifndef GL_ARB_shader_stencil_export
+#define GL_ARB_shader_stencil_export 1
+#endif
+
+#ifndef GL_ARB_base_instance
+#define GL_ARB_base_instance 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#endif
+
+#ifndef GL_ARB_shading_language_420pack
+#define GL_ARB_shading_language_420pack 1
+#endif
+
+#ifndef GL_ARB_transform_feedback_instanced
+#define GL_ARB_transform_feedback_instanced 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount);
+GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#endif
+
+#ifndef GL_ARB_compressed_texture_pixel_storage
+#define GL_ARB_compressed_texture_pixel_storage 1
+#endif
+
+#ifndef GL_ARB_conservative_depth
+#define GL_ARB_conservative_depth 1
+#endif
+
+#ifndef GL_ARB_internalformat_query
+#define GL_ARB_internalformat_query 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_ARB_map_buffer_alignment 1
+#endif
+
+#ifndef GL_ARB_shader_atomic_counters
+#define GL_ARB_shader_atomic_counters 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_shader_image_load_store
+#define GL_ARB_shader_image_load_store 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+#endif
+
+#ifndef GL_ARB_shading_language_packing
+#define GL_ARB_shading_language_packing 1
+#endif
+
+#ifndef GL_ARB_texture_storage
+#define GL_ARB_texture_storage 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glTexStorage1D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GLAPI void APIENTRY glPopDebugGroup (void);
+GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+#ifndef GL_ARB_arrays_of_arrays
+#define GL_ARB_arrays_of_arrays 1
+#endif
+
+#ifndef GL_ARB_clear_buffer_object
+#define GL_ARB_clear_buffer_object 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, GLsizeiptr offset, GLsizeiptr size, const void *data);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, GLsizeiptr offset, GLsizeiptr size, const void *data);
+#endif
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+#endif
+
+#ifndef GL_ARB_copy_image
+#define GL_ARB_copy_image 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+
+#ifndef GL_ARB_texture_view
+#define GL_ARB_texture_view 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_ARB_vertex_attrib_binding 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glVertexArrayBindVertexBufferEXT (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexArrayVertexAttribFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribIFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+#endif
+
+#ifndef GL_ARB_robustness_isolation
+#define GL_ARB_robustness_isolation 1
+#endif
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_ARB_ES3_compatibility 1
+#endif
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_ARB_explicit_uniform_location 1
+#endif
+
+#ifndef GL_ARB_fragment_layer_viewport
+#define GL_ARB_fragment_layer_viewport 1
+#endif
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_ARB_framebuffer_no_attachments 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedFramebufferParameteriEXT (GLuint framebuffer, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetNamedFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_internalformat_query2
+#define GL_ARB_internalformat_query2 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+#endif
+
+#ifndef GL_ARB_invalidate_subdata
+#define GL_ARB_invalidate_subdata 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level);
+GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer);
+GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ARB_multi_draw_indirect
+#define GL_ARB_multi_draw_indirect 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif
+
+#ifndef GL_ARB_program_interface_query
+#define GL_ARB_program_interface_query 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+#endif
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#define GL_ARB_robust_buffer_access_behavior 1
+#endif
+
+#ifndef GL_ARB_shader_image_size
+#define GL_ARB_shader_image_size 1
+#endif
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_ARB_shader_storage_buffer_object 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+#endif
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_ARB_stencil_texturing 1
+#endif
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_ARB_texture_buffer_range 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTextureBufferRangeEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+
+#ifndef GL_ARB_texture_query_levels
+#define GL_ARB_texture_query_levels 1
+#endif
+
+#ifndef GL_ARB_texture_storage_multisample
+#define GL_ARB_texture_storage_multisample 1
+#ifdef GLCOREARB_PROTOTYPES
+GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage2DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage3DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif /* GLCOREARB_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glew.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glew.h
new file mode 100644
index 00000000..0cd6ae3a
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glew.h
@@ -0,0 +1,16126 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __glew_h__
+#define __glew_h__
+#define __GLEW_H__
+
+#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H)
+#error gl.h included before glew.h
+#endif
+#if defined(__glext_h_) || defined(__GLEXT_H_)
+#error glext.h included before glew.h
+#endif
+#if defined(__gl_ATI_h_)
+#error glATI.h included before glew.h
+#endif
+
+#define __gl_h_
+#define __GL_H__
+#define __X_GL_H
+#define __glext_h_
+#define __GLEXT_H_
+#define __gl_ATI_h_
+
+#if defined(_WIN32)
+
+/*
+ * GLEW does not include <windows.h> to avoid name space pollution.
+ * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t
+ * defined properly.
+ */
+/* <windef.h> */
+#ifndef APIENTRY
+#define GLEW_APIENTRY_DEFINED
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define APIENTRY __stdcall
+# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__)
+# define APIENTRY __stdcall
+# else
+# define APIENTRY
+# endif
+#endif
+#ifndef GLAPI
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define GLAPI extern
+# endif
+#endif
+/* <winnt.h> */
+#ifndef CALLBACK
+#define GLEW_CALLBACK_DEFINED
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define CALLBACK __attribute__ ((__stdcall__))
+# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
+# define CALLBACK __stdcall
+# else
+# define CALLBACK
+# endif
+#endif
+/* <wingdi.h> and <winnt.h> */
+#ifndef WINGDIAPI
+#define GLEW_WINGDIAPI_DEFINED
+#define WINGDIAPI __declspec(dllimport)
+#endif
+/* <ctype.h> */
+#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED)
+typedef unsigned short wchar_t;
+# define _WCHAR_T_DEFINED
+#endif
+/* <stddef.h> */
+#if !defined(_W64)
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) && !defined(__MINGW64__)
+# ifdef _WIN64
+typedef __int64 ptrdiff_t;
+# else
+typedef _W64 int ptrdiff_t;
+# endif
+# define _PTRDIFF_T_DEFINED
+# define _PTRDIFF_T_
+#endif
+
+#ifndef GLAPI
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# define GLAPI extern
+# else
+# define GLAPI WINGDIAPI
+# endif
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY APIENTRY
+#endif
+
+/*
+ * GLEW_STATIC is defined for static library.
+ * GLEW_BUILD is defined for building the DLL library.
+ */
+
+#ifdef GLEW_STATIC
+# define GLEWAPI extern
+#else
+# ifdef GLEW_BUILD
+# define GLEWAPI extern __declspec(dllexport)
+# else
+# define GLEWAPI extern __declspec(dllimport)
+# endif
+#endif
+
+#else /* _UNIX */
+
+/*
+ * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO
+ * C. On my system, this amounts to _3 lines_ of included code, all of
+ * them pretty much harmless. If you know of a way of detecting 32 vs
+ * 64 _targets_ at compile time you are free to replace this with
+ * something that's portable. For now, _this_ is the portable solution.
+ * (mem, 2004-01-04)
+ */
+
+#include <stddef.h>
+
+/* SGI MIPSPro doesn't like stdint.h in C++ mode */
+/* ID: 3376260 Solaris 9 has inttypes.h, but not stdint.h */
+
+#if (defined(__sgi) || defined(__sun)) && !defined(__GNUC__)
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
+
+#define GLEW_APIENTRY_DEFINED
+#define APIENTRY
+
+/*
+ * GLEW_STATIC is defined for static library.
+ */
+
+#ifdef GLEW_STATIC
+# define GLEWAPI extern
+#else
+# if defined(__GNUC__) && __GNUC__>=4
+# define GLEWAPI extern __attribute__ ((visibility("default")))
+# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# define GLEWAPI extern __global
+# else
+# define GLEWAPI extern
+# endif
+#endif
+
+/* <glu.h> */
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----------------------------- GL_VERSION_1_1 ---------------------------- */
+
+#ifndef GL_VERSION_1_1
+#define GL_VERSION_1_1 1
+
+typedef unsigned int GLenum;
+typedef unsigned int GLbitfield;
+typedef unsigned int GLuint;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned char GLboolean;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned long GLulong;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void GLvoid;
+#if defined(_MSC_VER) && _MSC_VER < 1400
+typedef __int64 GLint64EXT;
+typedef unsigned __int64 GLuint64EXT;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+typedef signed long long GLint64EXT;
+typedef unsigned long long GLuint64EXT;
+#else
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+#include <inttypes.h>
+# endif
+typedef int64_t GLint64EXT;
+typedef uint64_t GLuint64EXT;
+#endif
+typedef GLint64EXT GLint64;
+typedef GLuint64EXT GLuint64;
+typedef struct __GLsync *GLsync;
+
+typedef char GLchar;
+
+#define GL_ZERO 0
+#define GL_FALSE 0
+#define GL_LOGIC_OP 0x0BF1
+#define GL_NONE 0
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_NO_ERROR 0
+#define GL_POINTS 0x0000
+#define GL_CURRENT_BIT 0x00000001
+#define GL_TRUE 1
+#define GL_ONE 1
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_POINT_BIT 0x00000002
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_BIT 0x00000004
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON 0x0009
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_ACCUM 0x0100
+#define GL_LOAD 0x0101
+#define GL_RETURN 0x0102
+#define GL_MULT 0x0103
+#define GL_ADD 0x0104
+#define GL_NEVER 0x0200
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_EXP 0x0800
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_EXP2 0x0801
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LIST_MODE 0x0B30
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_SHADE_MODEL 0x0B54
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_FOG 0x0B60
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_COLOR 0x0B66
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_NORMALIZE 0x0BA1
+#define GL_VIEWPORT 0x0BA2
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_DITHER 0x0BD0
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND 0x0BE2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_READ_BUFFER 0x0C02
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_INDEX_MODE 0x0C30
+#define GL_RGBA_MODE 0x0C31
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_RENDER_MODE 0x0C40
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_INDEX_BITS 0x0D51
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_DOUBLE 0x140A
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+#define GL_EMISSION 0x1600
+#define GL_SHININESS 0x1601
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_COLOR_INDEX 0x1900
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_BITMAP 0x1A00
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+#define GL_RENDER 0x1C00
+#define GL_FEEDBACK 0x1C01
+#define GL_SELECT 0x1C02
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_S 0x2000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV 0x2300
+#define GL_EYE_LINEAR 0x2400
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_SPHERE_MAP 0x2402
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_PLANE 0x2502
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_CLAMP 0x2900
+#define GL_REPEAT 0x2901
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_R3_G3_B2 0x2A10
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_LIGHT0 0x4000
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_HINT_BIT 0x00008000
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0x000fffff
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff
+
+GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value);
+GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref);
+GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI void GLAPIENTRY glArrayElement (GLint i);
+GLAPI void GLAPIENTRY glBegin (GLenum mode);
+GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture);
+GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GLAPI void GLAPIENTRY glCallList (GLuint list);
+GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists);
+GLAPI void GLAPIENTRY glClear (GLbitfield mask);
+GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void GLAPIENTRY glClearDepth (GLclampd depth);
+GLAPI void GLAPIENTRY glClearIndex (GLfloat c);
+GLAPI void GLAPIENTRY glClearStencil (GLint s);
+GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation);
+GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v);
+GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue);
+GLAPI void GLAPIENTRY glColor3iv (const GLint *v);
+GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue);
+GLAPI void GLAPIENTRY glColor3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v);
+GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue);
+GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v);
+GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue);
+GLAPI void GLAPIENTRY glColor3usv (const GLushort *v);
+GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v);
+GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI void GLAPIENTRY glColor4iv (const GLint *v);
+GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha);
+GLAPI void GLAPIENTRY glColor4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v);
+GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v);
+GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha);
+GLAPI void GLAPIENTRY glColor4usv (const GLushort *v);
+GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode);
+GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glCullFace (GLenum mode);
+GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range);
+GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GLAPI void GLAPIENTRY glDepthFunc (GLenum func);
+GLAPI void GLAPIENTRY glDepthMask (GLboolean flag);
+GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar);
+GLAPI void GLAPIENTRY glDisable (GLenum cap);
+GLAPI void GLAPIENTRY glDisableClientState (GLenum array);
+GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode);
+GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag);
+GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag);
+GLAPI void GLAPIENTRY glEnable (GLenum cap);
+GLAPI void GLAPIENTRY glEnableClientState (GLenum array);
+GLAPI void GLAPIENTRY glEnd (void);
+GLAPI void GLAPIENTRY glEndList (void);
+GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u);
+GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u);
+GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u);
+GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u);
+GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v);
+GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u);
+GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v);
+GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u);
+GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2);
+GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+GLAPI void GLAPIENTRY glEvalPoint1 (GLint i);
+GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j);
+GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer);
+GLAPI void GLAPIENTRY glFinish (void);
+GLAPI void GLAPIENTRY glFlush (void);
+GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glFrontFace (GLenum mode);
+GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range);
+GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params);
+GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation);
+GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params);
+GLAPI GLenum GLAPIENTRY glGetError (void);
+GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v);
+GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v);
+GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v);
+GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values);
+GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values);
+GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values);
+GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params);
+GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask);
+GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name);
+GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params);
+GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode);
+GLAPI void GLAPIENTRY glIndexMask (GLuint mask);
+GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glIndexd (GLdouble c);
+GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c);
+GLAPI void GLAPIENTRY glIndexf (GLfloat c);
+GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c);
+GLAPI void GLAPIENTRY glIndexi (GLint c);
+GLAPI void GLAPIENTRY glIndexiv (const GLint *c);
+GLAPI void GLAPIENTRY glIndexs (GLshort c);
+GLAPI void GLAPIENTRY glIndexsv (const GLshort *c);
+GLAPI void GLAPIENTRY glIndexub (GLubyte c);
+GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c);
+GLAPI void GLAPIENTRY glInitNames (void);
+GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer);
+GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap);
+GLAPI GLboolean GLAPIENTRY glIsList (GLuint list);
+GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture);
+GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern);
+GLAPI void GLAPIENTRY glLineWidth (GLfloat width);
+GLAPI void GLAPIENTRY glListBase (GLuint base);
+GLAPI void GLAPIENTRY glLoadIdentity (void);
+GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m);
+GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glLoadName (GLuint name);
+GLAPI void GLAPIENTRY glLogicOp (GLenum opcode);
+GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2);
+GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2);
+GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glMatrixMode (GLenum mode);
+GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m);
+GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m);
+GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode);
+GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v);
+GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz);
+GLAPI void GLAPIENTRY glNormal3iv (const GLint *v);
+GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz);
+GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void GLAPIENTRY glPassThrough (GLfloat token);
+GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values);
+GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values);
+GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values);
+GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor);
+GLAPI void GLAPIENTRY glPointSize (GLfloat size);
+GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode);
+GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask);
+GLAPI void GLAPIENTRY glPopAttrib (void);
+GLAPI void GLAPIENTRY glPopClientAttrib (void);
+GLAPI void GLAPIENTRY glPopMatrix (void);
+GLAPI void GLAPIENTRY glPopName (void);
+GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask);
+GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask);
+GLAPI void GLAPIENTRY glPushMatrix (void);
+GLAPI void GLAPIENTRY glPushName (GLuint name);
+GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y);
+GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y);
+GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y);
+GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v);
+GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y);
+GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v);
+GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z);
+GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v);
+GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z);
+GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w);
+GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v);
+GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glReadBuffer (GLenum mode);
+GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2);
+GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2);
+GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2);
+GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2);
+GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2);
+GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode);
+GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer);
+GLAPI void GLAPIENTRY glShadeModel (GLenum mode);
+GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GLAPI void GLAPIENTRY glStencilMask (GLuint mask);
+GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s);
+GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s);
+GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord1i (GLint s);
+GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord1s (GLshort s);
+GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t);
+GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t);
+GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t);
+GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t);
+GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r);
+GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r);
+GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r);
+GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r);
+GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q);
+GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v);
+GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param);
+GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params);
+GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y);
+GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y);
+GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y);
+GLAPI void GLAPIENTRY glVertex2iv (const GLint *v);
+GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y);
+GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v);
+GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z);
+GLAPI void GLAPIENTRY glVertex3iv (const GLint *v);
+GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z);
+GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v);
+GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v);
+GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v);
+GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w);
+GLAPI void GLAPIENTRY glVertex4iv (const GLint *v);
+GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v);
+GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1)
+
+#endif /* GL_VERSION_1_1 */
+
+/* ---------------------------------- GLU ---------------------------------- */
+
+#ifndef GLEW_NO_GLU
+/* this is where we can safely include GLU */
+# if defined(__APPLE__) && defined(__MACH__)
+# include <OpenGL/glu.h>
+# else
+# include <GL/glu.h>
+# endif
+#endif
+
+/* ----------------------------- GL_VERSION_1_2 ---------------------------- */
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+
+#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D)
+#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements)
+#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D)
+#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D)
+
+#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2)
+
+#endif /* GL_VERSION_1_2 */
+
+/* ---------------------------- GL_VERSION_1_2_1 --------------------------- */
+
+#ifndef GL_VERSION_1_2_1
+#define GL_VERSION_1_2_1 1
+
+#define GLEW_VERSION_1_2_1 GLEW_GET_VAR(__GLEW_VERSION_1_2_1)
+
+#endif /* GL_VERSION_1_2_1 */
+
+/* ----------------------------- GL_VERSION_1_3 ---------------------------- */
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_SUBTRACT 0x84E7
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_MULTISAMPLE_BIT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+
+#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture)
+#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture)
+#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D)
+#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D)
+#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D)
+#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D)
+#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D)
+#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D)
+#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage)
+#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd)
+#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf)
+#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd)
+#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf)
+#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d)
+#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv)
+#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f)
+#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv)
+#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i)
+#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv)
+#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s)
+#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv)
+#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d)
+#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv)
+#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f)
+#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv)
+#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i)
+#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv)
+#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s)
+#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv)
+#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d)
+#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv)
+#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f)
+#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv)
+#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i)
+#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv)
+#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s)
+#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv)
+#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d)
+#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv)
+#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f)
+#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv)
+#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i)
+#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv)
+#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s)
+#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv)
+#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage)
+
+#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3)
+
+#endif /* GL_VERSION_1_3 */
+
+/* ----------------------------- GL_VERSION_1_4 ---------------------------- */
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+
+typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p);
+
+#define glBlendColor GLEW_GET_FUN(__glewBlendColor)
+#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation)
+#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate)
+#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer)
+#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd)
+#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv)
+#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf)
+#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv)
+#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays)
+#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements)
+#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf)
+#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv)
+#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri)
+#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv)
+#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b)
+#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv)
+#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d)
+#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv)
+#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f)
+#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv)
+#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i)
+#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv)
+#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s)
+#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv)
+#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub)
+#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv)
+#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui)
+#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv)
+#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us)
+#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv)
+#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer)
+#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d)
+#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv)
+#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f)
+#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv)
+#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i)
+#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv)
+#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s)
+#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv)
+#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d)
+#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv)
+#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f)
+#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv)
+#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i)
+#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv)
+#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s)
+#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv)
+
+#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4)
+
+#endif /* GL_VERSION_1_4 */
+
+/* ----------------------------- GL_VERSION_1_5 ---------------------------- */
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+
+#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORD GL_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY
+#define GL_SRC0_RGB GL_SOURCE0_RGB
+#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
+#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA
+#define GL_SRC1_RGB GL_SOURCE1_RGB
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA
+#define GL_SRC2_RGB GL_SOURCE2_RGB
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id);
+typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target);
+
+#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery)
+#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer)
+#define glBufferData GLEW_GET_FUN(__glewBufferData)
+#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData)
+#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers)
+#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries)
+#define glEndQuery GLEW_GET_FUN(__glewEndQuery)
+#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers)
+#define glGenQueries GLEW_GET_FUN(__glewGenQueries)
+#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv)
+#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv)
+#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData)
+#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv)
+#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv)
+#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv)
+#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer)
+#define glIsQuery GLEW_GET_FUN(__glewIsQuery)
+#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer)
+#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer)
+
+#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5)
+
+#endif /* GL_VERSION_1_5 */
+
+/* ----------------------------- GL_VERSION_2_0 ---------------------------- */
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+
+#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+
+typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
+typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
+typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source);
+typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader);
+typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths);
+typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
+
+#define glAttachShader GLEW_GET_FUN(__glewAttachShader)
+#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation)
+#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate)
+#define glCompileShader GLEW_GET_FUN(__glewCompileShader)
+#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram)
+#define glCreateShader GLEW_GET_FUN(__glewCreateShader)
+#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram)
+#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader)
+#define glDetachShader GLEW_GET_FUN(__glewDetachShader)
+#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray)
+#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers)
+#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray)
+#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib)
+#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform)
+#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders)
+#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation)
+#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog)
+#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv)
+#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog)
+#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource)
+#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv)
+#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation)
+#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv)
+#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv)
+#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv)
+#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv)
+#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv)
+#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv)
+#define glIsProgram GLEW_GET_FUN(__glewIsProgram)
+#define glIsShader GLEW_GET_FUN(__glewIsShader)
+#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram)
+#define glShaderSource GLEW_GET_FUN(__glewShaderSource)
+#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate)
+#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate)
+#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate)
+#define glUniform1f GLEW_GET_FUN(__glewUniform1f)
+#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv)
+#define glUniform1i GLEW_GET_FUN(__glewUniform1i)
+#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv)
+#define glUniform2f GLEW_GET_FUN(__glewUniform2f)
+#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv)
+#define glUniform2i GLEW_GET_FUN(__glewUniform2i)
+#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv)
+#define glUniform3f GLEW_GET_FUN(__glewUniform3f)
+#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv)
+#define glUniform3i GLEW_GET_FUN(__glewUniform3i)
+#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv)
+#define glUniform4f GLEW_GET_FUN(__glewUniform4f)
+#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv)
+#define glUniform4i GLEW_GET_FUN(__glewUniform4i)
+#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv)
+#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv)
+#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv)
+#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv)
+#define glUseProgram GLEW_GET_FUN(__glewUseProgram)
+#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram)
+#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d)
+#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv)
+#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f)
+#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv)
+#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s)
+#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv)
+#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d)
+#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv)
+#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f)
+#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv)
+#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s)
+#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv)
+#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d)
+#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv)
+#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f)
+#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv)
+#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s)
+#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv)
+#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv)
+#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv)
+#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv)
+#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub)
+#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv)
+#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv)
+#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv)
+#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv)
+#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d)
+#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv)
+#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f)
+#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv)
+#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv)
+#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s)
+#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv)
+#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv)
+#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv)
+#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv)
+#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer)
+
+#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0)
+
+#endif /* GL_VERSION_2_0 */
+
+/* ----------------------------- GL_VERSION_2_1 ---------------------------- */
+
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+
+#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv)
+#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv)
+#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv)
+#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv)
+#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv)
+#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv)
+
+#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1)
+
+#endif /* GL_VERSION_2_1 */
+
+/* ----------------------------- GL_VERSION_3_0 ---------------------------- */
+
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+
+#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES
+#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5
+#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1
+#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3
+#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB
+#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0
+#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4
+#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2
+#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_DEPTH_BUFFER 0x8223
+#define GL_STENCIL_BUFFER 0x8224
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_ALPHA_INTEGER 0x8D97
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+
+typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum);
+typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum);
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*);
+typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
+typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*);
+typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*);
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*);
+
+#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender)
+#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback)
+#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation)
+#define glClampColor GLEW_GET_FUN(__glewClampColor)
+#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi)
+#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv)
+#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv)
+#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv)
+#define glColorMaski GLEW_GET_FUN(__glewColorMaski)
+#define glDisablei GLEW_GET_FUN(__glewDisablei)
+#define glEnablei GLEW_GET_FUN(__glewEnablei)
+#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender)
+#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback)
+#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v)
+#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation)
+#define glGetStringi GLEW_GET_FUN(__glewGetStringi)
+#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv)
+#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv)
+#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying)
+#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv)
+#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv)
+#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv)
+#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi)
+#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv)
+#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv)
+#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings)
+#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui)
+#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv)
+#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui)
+#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv)
+#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui)
+#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv)
+#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui)
+#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv)
+#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i)
+#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv)
+#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui)
+#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv)
+#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i)
+#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv)
+#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui)
+#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv)
+#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i)
+#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv)
+#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui)
+#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv)
+#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv)
+#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i)
+#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv)
+#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv)
+#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv)
+#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui)
+#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv)
+#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv)
+#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer)
+
+#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0)
+
+#endif /* GL_VERSION_3_0 */
+
+/* ----------------------------- GL_VERSION_3_1 ---------------------------- */
+
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei);
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint);
+typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint);
+
+#define glDrawArraysInstanced GLEW_GET_FUN(__glewDrawArraysInstanced)
+#define glDrawElementsInstanced GLEW_GET_FUN(__glewDrawElementsInstanced)
+#define glPrimitiveRestartIndex GLEW_GET_FUN(__glewPrimitiveRestartIndex)
+#define glTexBuffer GLEW_GET_FUN(__glewTexBuffer)
+
+#define GLEW_VERSION_3_1 GLEW_GET_VAR(__GLEW_VERSION_3_1)
+
+#endif /* GL_VERSION_3_1 */
+
+/* ----------------------------- GL_VERSION_3_2 ---------------------------- */
+
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum, GLenum, GLint64 *);
+typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *);
+
+#define glFramebufferTexture GLEW_GET_FUN(__glewFramebufferTexture)
+#define glGetBufferParameteri64v GLEW_GET_FUN(__glewGetBufferParameteri64v)
+#define glGetInteger64i_v GLEW_GET_FUN(__glewGetInteger64i_v)
+
+#define GLEW_VERSION_3_2 GLEW_GET_VAR(__GLEW_VERSION_3_2)
+
+#endif /* GL_VERSION_3_2 */
+
+/* ----------------------------- GL_VERSION_3_3 ---------------------------- */
+
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_RGB10_A2UI 0x906F
+
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+
+#define glVertexAttribDivisor GLEW_GET_FUN(__glewVertexAttribDivisor)
+
+#define GLEW_VERSION_3_3 GLEW_GET_VAR(__GLEW_VERSION_3_3)
+
+#endif /* GL_VERSION_3_3 */
+
+/* ----------------------------- GL_VERSION_4_0 ---------------------------- */
+
+#ifndef GL_VERSION_4_0
+#define GL_VERSION_4_0 1
+
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value);
+
+#define glBlendEquationSeparatei GLEW_GET_FUN(__glewBlendEquationSeparatei)
+#define glBlendEquationi GLEW_GET_FUN(__glewBlendEquationi)
+#define glBlendFuncSeparatei GLEW_GET_FUN(__glewBlendFuncSeparatei)
+#define glBlendFunci GLEW_GET_FUN(__glewBlendFunci)
+#define glMinSampleShading GLEW_GET_FUN(__glewMinSampleShading)
+
+#define GLEW_VERSION_4_0 GLEW_GET_VAR(__GLEW_VERSION_4_0)
+
+#endif /* GL_VERSION_4_0 */
+
+/* ----------------------------- GL_VERSION_4_1 ---------------------------- */
+
+#ifndef GL_VERSION_4_1
+#define GL_VERSION_4_1 1
+
+#define GLEW_VERSION_4_1 GLEW_GET_VAR(__GLEW_VERSION_4_1)
+
+#endif /* GL_VERSION_4_1 */
+
+/* ----------------------------- GL_VERSION_4_2 ---------------------------- */
+
+#ifndef GL_VERSION_4_2
+#define GL_VERSION_4_2 1
+
+#define GLEW_VERSION_4_2 GLEW_GET_VAR(__GLEW_VERSION_4_2)
+
+#endif /* GL_VERSION_4_2 */
+
+/* -------------------------- GL_3DFX_multisample -------------------------- */
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+
+#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample)
+
+#endif /* GL_3DFX_multisample */
+
+/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+
+typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+
+#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX)
+
+#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer)
+
+#endif /* GL_3DFX_tbuffer */
+
+/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+
+#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1)
+
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+/* ----------------------- GL_AMD_blend_minmax_factor ---------------------- */
+
+#ifndef GL_AMD_blend_minmax_factor
+#define GL_AMD_blend_minmax_factor 1
+
+#define GL_FACTOR_MIN_AMD 0x901C
+#define GL_FACTOR_MAX_AMD 0x901D
+
+#define GLEW_AMD_blend_minmax_factor GLEW_GET_VAR(__GLEW_AMD_blend_minmax_factor)
+
+#endif /* GL_AMD_blend_minmax_factor */
+
+/* ----------------------- GL_AMD_conservative_depth ----------------------- */
+
+#ifndef GL_AMD_conservative_depth
+#define GL_AMD_conservative_depth 1
+
+#define GLEW_AMD_conservative_depth GLEW_GET_VAR(__GLEW_AMD_conservative_depth)
+
+#endif /* GL_AMD_conservative_depth */
+
+/* -------------------------- GL_AMD_debug_output -------------------------- */
+
+#ifndef GL_AMD_debug_output
+#define GL_AMD_debug_output 1
+
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message);
+
+#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD)
+#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD)
+#define glDebugMessageInsertAMD GLEW_GET_FUN(__glewDebugMessageInsertAMD)
+#define glGetDebugMessageLogAMD GLEW_GET_FUN(__glewGetDebugMessageLogAMD)
+
+#define GLEW_AMD_debug_output GLEW_GET_VAR(__GLEW_AMD_debug_output)
+
+#endif /* GL_AMD_debug_output */
+
+/* ---------------------- GL_AMD_depth_clamp_separate ---------------------- */
+
+#ifndef GL_AMD_depth_clamp_separate
+#define GL_AMD_depth_clamp_separate 1
+
+#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E
+#define GL_DEPTH_CLAMP_FAR_AMD 0x901F
+
+#define GLEW_AMD_depth_clamp_separate GLEW_GET_VAR(__GLEW_AMD_depth_clamp_separate)
+
+#endif /* GL_AMD_depth_clamp_separate */
+
+/* ----------------------- GL_AMD_draw_buffers_blend ----------------------- */
+
+#ifndef GL_AMD_draw_buffers_blend
+#define GL_AMD_draw_buffers_blend 1
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+
+#define glBlendEquationIndexedAMD GLEW_GET_FUN(__glewBlendEquationIndexedAMD)
+#define glBlendEquationSeparateIndexedAMD GLEW_GET_FUN(__glewBlendEquationSeparateIndexedAMD)
+#define glBlendFuncIndexedAMD GLEW_GET_FUN(__glewBlendFuncIndexedAMD)
+#define glBlendFuncSeparateIndexedAMD GLEW_GET_FUN(__glewBlendFuncSeparateIndexedAMD)
+
+#define GLEW_AMD_draw_buffers_blend GLEW_GET_VAR(__GLEW_AMD_draw_buffers_blend)
+
+#endif /* GL_AMD_draw_buffers_blend */
+
+/* ----------------------- GL_AMD_multi_draw_indirect ---------------------- */
+
+#ifndef GL_AMD_multi_draw_indirect
+#define GL_AMD_multi_draw_indirect 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void* indirect, GLsizei primcount, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void* indirect, GLsizei primcount, GLsizei stride);
+
+#define glMultiDrawArraysIndirectAMD GLEW_GET_FUN(__glewMultiDrawArraysIndirectAMD)
+#define glMultiDrawElementsIndirectAMD GLEW_GET_FUN(__glewMultiDrawElementsIndirectAMD)
+
+#define GLEW_AMD_multi_draw_indirect GLEW_GET_VAR(__GLEW_AMD_multi_draw_indirect)
+
+#endif /* GL_AMD_multi_draw_indirect */
+
+/* ------------------------- GL_AMD_name_gen_delete ------------------------ */
+
+#ifndef GL_AMD_name_gen_delete
+#define GL_AMD_name_gen_delete 1
+
+#define GL_DATA_BUFFER_AMD 0x9151
+#define GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define GL_QUERY_OBJECT_AMD 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define GL_SAMPLER_OBJECT_AMD 0x9155
+
+typedef void (GLAPIENTRY * PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint* names);
+typedef void (GLAPIENTRY * PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint* names);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name);
+
+#define glDeleteNamesAMD GLEW_GET_FUN(__glewDeleteNamesAMD)
+#define glGenNamesAMD GLEW_GET_FUN(__glewGenNamesAMD)
+#define glIsNameAMD GLEW_GET_FUN(__glewIsNameAMD)
+
+#define GLEW_AMD_name_gen_delete GLEW_GET_VAR(__GLEW_AMD_name_gen_delete)
+
+#endif /* GL_AMD_name_gen_delete */
+
+/* ----------------------- GL_AMD_performance_monitor ---------------------- */
+
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+
+typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
+typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString);
+typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList);
+
+#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD)
+#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD)
+#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD)
+#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD)
+#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD)
+#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD)
+#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD)
+#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD)
+#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD)
+#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD)
+#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD)
+
+#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor)
+
+#endif /* GL_AMD_performance_monitor */
+
+/* ------------------------ GL_AMD_sample_positions ------------------------ */
+
+#ifndef GL_AMD_sample_positions
+#define GL_AMD_sample_positions 1
+
+#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
+
+typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat* val);
+
+#define glSetMultisamplefvAMD GLEW_GET_FUN(__glewSetMultisamplefvAMD)
+
+#define GLEW_AMD_sample_positions GLEW_GET_VAR(__GLEW_AMD_sample_positions)
+
+#endif /* GL_AMD_sample_positions */
+
+/* ------------------ GL_AMD_seamless_cubemap_per_texture ------------------ */
+
+#ifndef GL_AMD_seamless_cubemap_per_texture
+#define GL_AMD_seamless_cubemap_per_texture 1
+
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB 0x884F
+
+#define GLEW_AMD_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_AMD_seamless_cubemap_per_texture)
+
+#endif /* GL_AMD_seamless_cubemap_per_texture */
+
+/* ---------------------- GL_AMD_shader_stencil_export --------------------- */
+
+#ifndef GL_AMD_shader_stencil_export
+#define GL_AMD_shader_stencil_export 1
+
+#define GLEW_AMD_shader_stencil_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_export)
+
+#endif /* GL_AMD_shader_stencil_export */
+
+/* ------------------------ GL_AMD_texture_texture4 ------------------------ */
+
+#ifndef GL_AMD_texture_texture4
+#define GL_AMD_texture_texture4 1
+
+#define GLEW_AMD_texture_texture4 GLEW_GET_VAR(__GLEW_AMD_texture_texture4)
+
+#endif /* GL_AMD_texture_texture4 */
+
+/* --------------- GL_AMD_transform_feedback3_lines_triangles -------------- */
+
+#ifndef GL_AMD_transform_feedback3_lines_triangles
+#define GL_AMD_transform_feedback3_lines_triangles 1
+
+#define GLEW_AMD_transform_feedback3_lines_triangles GLEW_GET_VAR(__GLEW_AMD_transform_feedback3_lines_triangles)
+
+#endif /* GL_AMD_transform_feedback3_lines_triangles */
+
+/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */
+
+#ifndef GL_AMD_vertex_shader_tessellator
+#define GL_AMD_vertex_shader_tessellator 1
+
+#define GL_SAMPLER_BUFFER_AMD 0x9001
+#define GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define GL_TESSELLATION_MODE_AMD 0x9004
+#define GL_TESSELLATION_FACTOR_AMD 0x9005
+#define GL_DISCRETE_AMD 0x9006
+#define GL_CONTINUOUS_AMD 0x9007
+
+typedef void (GLAPIENTRY * PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor);
+typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
+
+#define glTessellationFactorAMD GLEW_GET_FUN(__glewTessellationFactorAMD)
+#define glTessellationModeAMD GLEW_GET_FUN(__glewTessellationModeAMD)
+
+#define GLEW_AMD_vertex_shader_tessellator GLEW_GET_VAR(__GLEW_AMD_vertex_shader_tessellator)
+
+#endif /* GL_AMD_vertex_shader_tessellator */
+
+/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */
+
+#ifndef GL_APPLE_aux_depth_stencil
+#define GL_APPLE_aux_depth_stencil 1
+
+#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+
+#define GLEW_APPLE_aux_depth_stencil GLEW_GET_VAR(__GLEW_APPLE_aux_depth_stencil)
+
+#endif /* GL_APPLE_aux_depth_stencil */
+
+/* ------------------------ GL_APPLE_client_storage ------------------------ */
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+
+#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage)
+
+#endif /* GL_APPLE_client_storage */
+
+/* ------------------------- GL_APPLE_element_array ------------------------ */
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+
+#define GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount);
+
+#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE)
+#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE)
+#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE)
+#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE)
+#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE)
+
+#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array)
+
+#endif /* GL_APPLE_element_array */
+
+/* ----------------------------- GL_APPLE_fence ---------------------------- */
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+
+#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE)
+#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE)
+#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE)
+#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE)
+#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE)
+#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE)
+#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE)
+#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE)
+
+#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence)
+
+#endif /* GL_APPLE_fence */
+
+/* ------------------------- GL_APPLE_float_pixels ------------------------- */
+
+#ifndef GL_APPLE_float_pixels
+#define GL_APPLE_float_pixels 1
+
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+
+#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels)
+
+#endif /* GL_APPLE_float_pixels */
+
+/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */
+
+#ifndef GL_APPLE_flush_buffer_range
+#define GL_APPLE_flush_buffer_range 1
+
+#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+
+typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
+
+#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE)
+#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE)
+
+#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range)
+
+#endif /* GL_APPLE_flush_buffer_range */
+
+/* ----------------------- GL_APPLE_object_purgeable ----------------------- */
+
+#ifndef GL_APPLE_object_purgeable
+#define GL_APPLE_object_purgeable 1
+
+#define GL_BUFFER_OBJECT_APPLE 0x85B3
+#define GL_RELEASED_APPLE 0x8A19
+#define GL_VOLATILE_APPLE 0x8A1A
+#define GL_RETAINED_APPLE 0x8A1B
+#define GL_UNDEFINED_APPLE 0x8A1C
+#define GL_PURGEABLE_APPLE 0x8A1D
+
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params);
+typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+
+#define glGetObjectParameterivAPPLE GLEW_GET_FUN(__glewGetObjectParameterivAPPLE)
+#define glObjectPurgeableAPPLE GLEW_GET_FUN(__glewObjectPurgeableAPPLE)
+#define glObjectUnpurgeableAPPLE GLEW_GET_FUN(__glewObjectUnpurgeableAPPLE)
+
+#define GLEW_APPLE_object_purgeable GLEW_GET_VAR(__GLEW_APPLE_object_purgeable)
+
+#endif /* GL_APPLE_object_purgeable */
+
+/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */
+
+#ifndef GL_APPLE_pixel_buffer
+#define GL_APPLE_pixel_buffer 1
+
+#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10
+
+#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer)
+
+#endif /* GL_APPLE_pixel_buffer */
+
+/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */
+
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_422_APPLE 0x8A1F
+
+#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422)
+
+#endif /* GL_APPLE_rgb_422 */
+
+/* --------------------------- GL_APPLE_row_bytes -------------------------- */
+
+#ifndef GL_APPLE_row_bytes
+#define GL_APPLE_row_bytes 1
+
+#define GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+
+#define GLEW_APPLE_row_bytes GLEW_GET_VAR(__GLEW_APPLE_row_bytes)
+
+#endif /* GL_APPLE_row_bytes */
+
+/* ------------------------ GL_APPLE_specular_vector ----------------------- */
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+
+#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector)
+
+#endif /* GL_APPLE_specular_vector */
+
+/* ------------------------- GL_APPLE_texture_range ------------------------ */
+
+#ifndef GL_APPLE_texture_range
+#define GL_APPLE_texture_range 1
+
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params);
+typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+
+#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE)
+#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE)
+
+#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range)
+
+#endif /* GL_APPLE_texture_range */
+
+/* ------------------------ GL_APPLE_transform_hint ------------------------ */
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+
+#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint)
+
+#endif /* GL_APPLE_transform_hint */
+
+/* ---------------------- GL_APPLE_vertex_array_object --------------------- */
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+
+#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE)
+#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE)
+#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE)
+#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE)
+
+#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object)
+
+#endif /* GL_APPLE_vertex_array_object */
+
+/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CLIENT_APPLE 0x85B4
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer);
+
+#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE)
+#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE)
+#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE)
+
+#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range)
+
+#endif /* GL_APPLE_vertex_array_range */
+
+/* ------------------- GL_APPLE_vertex_program_evaluators ------------------ */
+
+#ifndef GL_APPLE_vertex_program_evaluators
+#define GL_APPLE_vertex_program_evaluators 1
+
+#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points);
+typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points);
+
+#define glDisableVertexAttribAPPLE GLEW_GET_FUN(__glewDisableVertexAttribAPPLE)
+#define glEnableVertexAttribAPPLE GLEW_GET_FUN(__glewEnableVertexAttribAPPLE)
+#define glIsVertexAttribEnabledAPPLE GLEW_GET_FUN(__glewIsVertexAttribEnabledAPPLE)
+#define glMapVertexAttrib1dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1dAPPLE)
+#define glMapVertexAttrib1fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1fAPPLE)
+#define glMapVertexAttrib2dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2dAPPLE)
+#define glMapVertexAttrib2fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2fAPPLE)
+
+#define GLEW_APPLE_vertex_program_evaluators GLEW_GET_VAR(__GLEW_APPLE_vertex_program_evaluators)
+
+#endif /* GL_APPLE_vertex_program_evaluators */
+
+/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+
+#define GL_YCBCR_422_APPLE 0x85B9
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+
+#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422)
+
+#endif /* GL_APPLE_ycbcr_422 */
+
+/* ------------------------ GL_ARB_ES2_compatibility ----------------------- */
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_ARB_ES2_compatibility 1
+
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f);
+typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision);
+typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length);
+
+#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf)
+#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef)
+#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat)
+#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler)
+#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary)
+
+#define GLEW_ARB_ES2_compatibility GLEW_GET_VAR(__GLEW_ARB_ES2_compatibility)
+
+#endif /* GL_ARB_ES2_compatibility */
+
+/* -------------------------- GL_ARB_base_instance ------------------------- */
+
+#ifndef GL_ARB_base_instance
+#define GL_ARB_base_instance 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLuint baseinstance);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex, GLuint baseinstance);
+
+#define glDrawArraysInstancedBaseInstance GLEW_GET_FUN(__glewDrawArraysInstancedBaseInstance)
+#define glDrawElementsInstancedBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseInstance)
+#define glDrawElementsInstancedBaseVertexBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertexBaseInstance)
+
+#define GLEW_ARB_base_instance GLEW_GET_VAR(__GLEW_ARB_base_instance)
+
+#endif /* GL_ARB_base_instance */
+
+/* ----------------------- GL_ARB_blend_func_extended ---------------------- */
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_ARB_blend_func_extended 1
+
+#define GL_SRC1_COLOR 0x88F9
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name);
+
+#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed)
+#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex)
+
+#define GLEW_ARB_blend_func_extended GLEW_GET_VAR(__GLEW_ARB_blend_func_extended)
+
+#endif /* GL_ARB_blend_func_extended */
+
+/* ---------------------------- GL_ARB_cl_event ---------------------------- */
+
+#ifndef GL_ARB_cl_event
+#define GL_ARB_cl_event 1
+
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+
+typedef struct _cl_context *cl_context;
+typedef struct _cl_event *cl_event;
+
+typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context context, cl_event event, GLbitfield flags);
+
+#define glCreateSyncFromCLeventARB GLEW_GET_FUN(__glewCreateSyncFromCLeventARB)
+
+#define GLEW_ARB_cl_event GLEW_GET_VAR(__GLEW_ARB_cl_event)
+
+#endif /* GL_ARB_cl_event */
+
+/* ----------------------- GL_ARB_color_buffer_float ----------------------- */
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+
+typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+
+#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB)
+
+#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float)
+
+#endif /* GL_ARB_color_buffer_float */
+
+/* -------------------------- GL_ARB_compatibility ------------------------- */
+
+#ifndef GL_ARB_compatibility
+#define GL_ARB_compatibility 1
+
+#define GLEW_ARB_compatibility GLEW_GET_VAR(__GLEW_ARB_compatibility)
+
+#endif /* GL_ARB_compatibility */
+
+/* ---------------- GL_ARB_compressed_texture_pixel_storage ---------------- */
+
+#ifndef GL_ARB_compressed_texture_pixel_storage
+#define GL_ARB_compressed_texture_pixel_storage 1
+
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+
+#define GLEW_ARB_compressed_texture_pixel_storage GLEW_GET_VAR(__GLEW_ARB_compressed_texture_pixel_storage)
+
+#endif /* GL_ARB_compressed_texture_pixel_storage */
+
+/* ----------------------- GL_ARB_conservative_depth ----------------------- */
+
+#ifndef GL_ARB_conservative_depth
+#define GL_ARB_conservative_depth 1
+
+#define GLEW_ARB_conservative_depth GLEW_GET_VAR(__GLEW_ARB_conservative_depth)
+
+#endif /* GL_ARB_conservative_depth */
+
+/* --------------------------- GL_ARB_copy_buffer -------------------------- */
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+
+typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);
+
+#define glCopyBufferSubData GLEW_GET_FUN(__glewCopyBufferSubData)
+
+#define GLEW_ARB_copy_buffer GLEW_GET_VAR(__GLEW_ARB_copy_buffer)
+
+#endif /* GL_ARB_copy_buffer */
+
+/* -------------------------- GL_ARB_debug_output -------------------------- */
+
+#ifndef GL_ARB_debug_output
+#define GL_ARB_debug_output 1
+
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam);
+
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
+typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf);
+typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog);
+
+#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB)
+#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB)
+#define glDebugMessageInsertARB GLEW_GET_FUN(__glewDebugMessageInsertARB)
+#define glGetDebugMessageLogARB GLEW_GET_FUN(__glewGetDebugMessageLogARB)
+
+#define GLEW_ARB_debug_output GLEW_GET_VAR(__GLEW_ARB_debug_output)
+
+#endif /* GL_ARB_debug_output */
+
+/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_ARB_depth_buffer_float 1
+
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+
+#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float)
+
+#endif /* GL_ARB_depth_buffer_float */
+
+/* --------------------------- GL_ARB_depth_clamp -------------------------- */
+
+#ifndef GL_ARB_depth_clamp
+#define GL_ARB_depth_clamp 1
+
+#define GL_DEPTH_CLAMP 0x864F
+
+#define GLEW_ARB_depth_clamp GLEW_GET_VAR(__GLEW_ARB_depth_clamp)
+
+#endif /* GL_ARB_depth_clamp */
+
+/* -------------------------- GL_ARB_depth_texture ------------------------- */
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+
+#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture)
+
+#endif /* GL_ARB_depth_texture */
+
+/* -------------------------- GL_ARB_draw_buffers -------------------------- */
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB)
+
+#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers)
+
+#endif /* GL_ARB_draw_buffers */
+
+/* ----------------------- GL_ARB_draw_buffers_blend ----------------------- */
+
+#ifndef GL_ARB_draw_buffers_blend
+#define GL_ARB_draw_buffers_blend 1
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+
+#define glBlendEquationSeparateiARB GLEW_GET_FUN(__glewBlendEquationSeparateiARB)
+#define glBlendEquationiARB GLEW_GET_FUN(__glewBlendEquationiARB)
+#define glBlendFuncSeparateiARB GLEW_GET_FUN(__glewBlendFuncSeparateiARB)
+#define glBlendFunciARB GLEW_GET_FUN(__glewBlendFunciARB)
+
+#define GLEW_ARB_draw_buffers_blend GLEW_GET_VAR(__GLEW_ARB_draw_buffers_blend)
+
+#endif /* GL_ARB_draw_buffers_blend */
+
+/* -------------------- GL_ARB_draw_elements_base_vertex ------------------- */
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#define GL_ARB_draw_elements_base_vertex 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex);
+
+#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex)
+#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex)
+#define glDrawRangeElementsBaseVertex GLEW_GET_FUN(__glewDrawRangeElementsBaseVertex)
+#define glMultiDrawElementsBaseVertex GLEW_GET_FUN(__glewMultiDrawElementsBaseVertex)
+
+#define GLEW_ARB_draw_elements_base_vertex GLEW_GET_VAR(__GLEW_ARB_draw_elements_base_vertex)
+
+#endif /* GL_ARB_draw_elements_base_vertex */
+
+/* -------------------------- GL_ARB_draw_indirect ------------------------- */
+
+#ifndef GL_ARB_draw_indirect
+#define GL_ARB_draw_indirect 1
+
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect);
+
+#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect)
+#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect)
+
+#define GLEW_ARB_draw_indirect GLEW_GET_VAR(__GLEW_ARB_draw_indirect)
+
+#endif /* GL_ARB_draw_indirect */
+
+/* ------------------------- GL_ARB_draw_instanced ------------------------- */
+
+#ifndef GL_ARB_draw_instanced
+#define GL_ARB_draw_instanced 1
+
+#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced)
+
+#endif /* GL_ARB_draw_instanced */
+
+/* -------------------- GL_ARB_explicit_attrib_location -------------------- */
+
+#ifndef GL_ARB_explicit_attrib_location
+#define GL_ARB_explicit_attrib_location 1
+
+#define GLEW_ARB_explicit_attrib_location GLEW_GET_VAR(__GLEW_ARB_explicit_attrib_location)
+
+#endif /* GL_ARB_explicit_attrib_location */
+
+/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */
+
+#ifndef GL_ARB_fragment_coord_conventions
+#define GL_ARB_fragment_coord_conventions 1
+
+#define GLEW_ARB_fragment_coord_conventions GLEW_GET_VAR(__GLEW_ARB_fragment_coord_conventions)
+
+#endif /* GL_ARB_fragment_coord_conventions */
+
+/* ------------------------ GL_ARB_fragment_program ------------------------ */
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+
+#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program)
+
+#endif /* GL_ARB_fragment_program */
+
+/* --------------------- GL_ARB_fragment_program_shadow -------------------- */
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+
+#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow)
+
+#endif /* GL_ARB_fragment_program_shadow */
+
+/* ------------------------- GL_ARB_fragment_shader ------------------------ */
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+
+#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader)
+
+#endif /* GL_ARB_fragment_shader */
+
+/* ----------------------- GL_ARB_framebuffer_object ----------------------- */
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_ARB_framebuffer_object 1
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_INDEX 0x8222
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_SRGB 0x8C40
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer)
+#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer)
+#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer)
+#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus)
+#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers)
+#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers)
+#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer)
+#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D)
+#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D)
+#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D)
+#define glFramebufferTextureLayer GLEW_GET_FUN(__glewFramebufferTextureLayer)
+#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers)
+#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers)
+#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap)
+#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv)
+#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv)
+#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer)
+#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer)
+#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage)
+#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample)
+
+#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object)
+
+#endif /* GL_ARB_framebuffer_object */
+
+/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_ARB_framebuffer_sRGB 1
+
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+
+#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB)
+
+#endif /* GL_ARB_framebuffer_sRGB */
+
+/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */
+
+#ifndef GL_ARB_geometry_shader4
+#define GL_ARB_geometry_shader4 1
+
+#define GL_LINES_ADJACENCY_ARB 0xA
+#define GL_LINE_STRIP_ADJACENCY_ARB 0xB
+#define GL_TRIANGLES_ADJACENCY_ARB 0xC
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);
+
+#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB)
+#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB)
+#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB)
+#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB)
+
+#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4)
+
+#endif /* GL_ARB_geometry_shader4 */
+
+/* ----------------------- GL_ARB_get_program_binary ----------------------- */
+
+#ifndef GL_ARB_get_program_binary
+#define GL_ARB_get_program_binary 1
+
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+
+#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary)
+#define glProgramBinary GLEW_GET_FUN(__glewProgramBinary)
+#define glProgramParameteri GLEW_GET_FUN(__glewProgramParameteri)
+
+#define GLEW_ARB_get_program_binary GLEW_GET_VAR(__GLEW_ARB_get_program_binary)
+
+#endif /* GL_ARB_get_program_binary */
+
+/* --------------------------- GL_ARB_gpu_shader5 -------------------------- */
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_ARB_gpu_shader5 1
+
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+
+#define GLEW_ARB_gpu_shader5 GLEW_GET_VAR(__GLEW_ARB_gpu_shader5)
+
+#endif /* GL_ARB_gpu_shader5 */
+
+/* ------------------------- GL_ARB_gpu_shader_fp64 ------------------------ */
+
+#ifndef GL_ARB_gpu_shader_fp64
+#define GL_ARB_gpu_shader_fp64 1
+
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+
+#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv)
+#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT)
+#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT)
+#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT)
+#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT)
+#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT)
+#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT)
+#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT)
+#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT)
+#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT)
+#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT)
+#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT)
+#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT)
+#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT)
+#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT)
+#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT)
+#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT)
+#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT)
+#define glUniform1d GLEW_GET_FUN(__glewUniform1d)
+#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv)
+#define glUniform2d GLEW_GET_FUN(__glewUniform2d)
+#define glUniform2dv GLEW_GET_FUN(__glewUniform2dv)
+#define glUniform3d GLEW_GET_FUN(__glewUniform3d)
+#define glUniform3dv GLEW_GET_FUN(__glewUniform3dv)
+#define glUniform4d GLEW_GET_FUN(__glewUniform4d)
+#define glUniform4dv GLEW_GET_FUN(__glewUniform4dv)
+#define glUniformMatrix2dv GLEW_GET_FUN(__glewUniformMatrix2dv)
+#define glUniformMatrix2x3dv GLEW_GET_FUN(__glewUniformMatrix2x3dv)
+#define glUniformMatrix2x4dv GLEW_GET_FUN(__glewUniformMatrix2x4dv)
+#define glUniformMatrix3dv GLEW_GET_FUN(__glewUniformMatrix3dv)
+#define glUniformMatrix3x2dv GLEW_GET_FUN(__glewUniformMatrix3x2dv)
+#define glUniformMatrix3x4dv GLEW_GET_FUN(__glewUniformMatrix3x4dv)
+#define glUniformMatrix4dv GLEW_GET_FUN(__glewUniformMatrix4dv)
+#define glUniformMatrix4x2dv GLEW_GET_FUN(__glewUniformMatrix4x2dv)
+#define glUniformMatrix4x3dv GLEW_GET_FUN(__glewUniformMatrix4x3dv)
+
+#define GLEW_ARB_gpu_shader_fp64 GLEW_GET_VAR(__GLEW_ARB_gpu_shader_fp64)
+
+#endif /* GL_ARB_gpu_shader_fp64 */
+
+/* ------------------------ GL_ARB_half_float_pixel ------------------------ */
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+
+#define GL_HALF_FLOAT_ARB 0x140B
+
+#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel)
+
+#endif /* GL_ARB_half_float_pixel */
+
+/* ------------------------ GL_ARB_half_float_vertex ----------------------- */
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_ARB_half_float_vertex 1
+
+#define GL_HALF_FLOAT 0x140B
+
+#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex)
+
+#endif /* GL_ARB_half_float_vertex */
+
+/* ----------------------------- GL_ARB_imaging ---------------------------- */
+
+#ifndef GL_ARB_imaging
+#define GL_ARB_imaging 1
+
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_IGNORE_BORDER 0x8150
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_WRAP_BORDER 0x8152
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+
+#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable)
+#define glColorTable GLEW_GET_FUN(__glewColorTable)
+#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv)
+#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv)
+#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D)
+#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D)
+#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf)
+#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv)
+#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri)
+#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv)
+#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable)
+#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable)
+#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D)
+#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D)
+#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable)
+#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv)
+#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv)
+#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter)
+#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv)
+#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv)
+#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram)
+#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv)
+#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv)
+#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax)
+#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv)
+#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv)
+#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter)
+#define glHistogram GLEW_GET_FUN(__glewHistogram)
+#define glMinmax GLEW_GET_FUN(__glewMinmax)
+#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram)
+#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax)
+#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D)
+
+#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging)
+
+#endif /* GL_ARB_imaging */
+
+/* ------------------------ GL_ARB_instanced_arrays ------------------------ */
+
+#ifndef GL_ARB_instanced_arrays
+#define GL_ARB_instanced_arrays 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
+
+#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB)
+#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB)
+#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB)
+
+#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays)
+
+#endif /* GL_ARB_instanced_arrays */
+
+/* ---------------------- GL_ARB_internalformat_query ---------------------- */
+
+#ifndef GL_ARB_internalformat_query
+#define GL_ARB_internalformat_query 1
+
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+
+typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
+
+#define glGetInternalformativ GLEW_GET_FUN(__glewGetInternalformativ)
+
+#define GLEW_ARB_internalformat_query GLEW_GET_VAR(__GLEW_ARB_internalformat_query)
+
+#endif /* GL_ARB_internalformat_query */
+
+/* ---------------------- GL_ARB_map_buffer_alignment ---------------------- */
+
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_ARB_map_buffer_alignment 1
+
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+
+#define GLEW_ARB_map_buffer_alignment GLEW_GET_VAR(__GLEW_ARB_map_buffer_alignment)
+
+#endif /* GL_ARB_map_buffer_alignment */
+
+/* ------------------------ GL_ARB_map_buffer_range ------------------------ */
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+
+#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange)
+#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange)
+
+#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range)
+
+#endif /* GL_ARB_map_buffer_range */
+
+/* ------------------------- GL_ARB_matrix_palette ------------------------- */
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+
+typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices);
+typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices);
+
+#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB)
+#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB)
+#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB)
+#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB)
+#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB)
+
+#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette)
+
+#endif /* GL_ARB_matrix_palette */
+
+/* --------------------------- GL_ARB_multisample -------------------------- */
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+
+#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB)
+
+#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample)
+
+#endif /* GL_ARB_multisample */
+
+/* -------------------------- GL_ARB_multitexture -------------------------- */
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+
+typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+
+#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB)
+#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB)
+#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB)
+#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB)
+#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB)
+#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB)
+#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB)
+#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB)
+#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB)
+#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB)
+#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB)
+#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB)
+#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB)
+#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB)
+#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB)
+#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB)
+#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB)
+#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB)
+#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB)
+#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB)
+#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB)
+#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB)
+#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB)
+#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB)
+#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB)
+#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB)
+#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB)
+#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB)
+#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB)
+#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB)
+#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB)
+#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB)
+#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB)
+#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB)
+
+#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture)
+
+#endif /* GL_ARB_multitexture */
+
+/* ------------------------- GL_ARB_occlusion_query ------------------------ */
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id);
+
+#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB)
+#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB)
+#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB)
+#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB)
+#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB)
+#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB)
+#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB)
+#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB)
+
+#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query)
+
+#endif /* GL_ARB_occlusion_query */
+
+/* ------------------------ GL_ARB_occlusion_query2 ------------------------ */
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ARB_occlusion_query2 1
+
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+
+#define GLEW_ARB_occlusion_query2 GLEW_GET_VAR(__GLEW_ARB_occlusion_query2)
+
+#endif /* GL_ARB_occlusion_query2 */
+
+/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+
+#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object)
+
+#endif /* GL_ARB_pixel_buffer_object */
+
+/* ------------------------ GL_ARB_point_parameters ------------------------ */
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat* params);
+
+#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB)
+#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB)
+
+#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters)
+
+#endif /* GL_ARB_point_parameters */
+
+/* -------------------------- GL_ARB_point_sprite -------------------------- */
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+
+#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite)
+
+#endif /* GL_ARB_point_sprite */
+
+/* ------------------------ GL_ARB_provoking_vertex ------------------------ */
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_ARB_provoking_vertex 1
+
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+
+typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+
+#define glProvokingVertex GLEW_GET_FUN(__glewProvokingVertex)
+
+#define GLEW_ARB_provoking_vertex GLEW_GET_VAR(__GLEW_ARB_provoking_vertex)
+
+#endif /* GL_ARB_provoking_vertex */
+
+/* --------------------------- GL_ARB_robustness --------------------------- */
+
+#ifndef GL_ARB_robustness
+#define GL_ARB_robustness 1
+
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+
+typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table);
+typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img);
+typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image);
+typedef void (GLAPIENTRY * PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values);
+typedef void (GLAPIENTRY * PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint* v);
+typedef void (GLAPIENTRY * PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values);
+typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values);
+typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values);
+typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern);
+typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span);
+typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data);
+
+#define glGetGraphicsResetStatusARB GLEW_GET_FUN(__glewGetGraphicsResetStatusARB)
+#define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB)
+#define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB)
+#define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB)
+#define glGetnHistogramARB GLEW_GET_FUN(__glewGetnHistogramARB)
+#define glGetnMapdvARB GLEW_GET_FUN(__glewGetnMapdvARB)
+#define glGetnMapfvARB GLEW_GET_FUN(__glewGetnMapfvARB)
+#define glGetnMapivARB GLEW_GET_FUN(__glewGetnMapivARB)
+#define glGetnMinmaxARB GLEW_GET_FUN(__glewGetnMinmaxARB)
+#define glGetnPixelMapfvARB GLEW_GET_FUN(__glewGetnPixelMapfvARB)
+#define glGetnPixelMapuivARB GLEW_GET_FUN(__glewGetnPixelMapuivARB)
+#define glGetnPixelMapusvARB GLEW_GET_FUN(__glewGetnPixelMapusvARB)
+#define glGetnPolygonStippleARB GLEW_GET_FUN(__glewGetnPolygonStippleARB)
+#define glGetnSeparableFilterARB GLEW_GET_FUN(__glewGetnSeparableFilterARB)
+#define glGetnTexImageARB GLEW_GET_FUN(__glewGetnTexImageARB)
+#define glGetnUniformdvARB GLEW_GET_FUN(__glewGetnUniformdvARB)
+#define glGetnUniformfvARB GLEW_GET_FUN(__glewGetnUniformfvARB)
+#define glGetnUniformivARB GLEW_GET_FUN(__glewGetnUniformivARB)
+#define glGetnUniformuivARB GLEW_GET_FUN(__glewGetnUniformuivARB)
+#define glReadnPixelsARB GLEW_GET_FUN(__glewReadnPixelsARB)
+
+#define GLEW_ARB_robustness GLEW_GET_VAR(__GLEW_ARB_robustness)
+
+#endif /* GL_ARB_robustness */
+
+/* ------------------------- GL_ARB_sample_shading ------------------------- */
+
+#ifndef GL_ARB_sample_shading
+#define GL_ARB_sample_shading 1
+
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+
+typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value);
+
+#define glMinSampleShadingARB GLEW_GET_FUN(__glewMinSampleShadingARB)
+
+#define GLEW_ARB_sample_shading GLEW_GET_VAR(__GLEW_ARB_sample_shading)
+
+#endif /* GL_ARB_sample_shading */
+
+/* ------------------------- GL_ARB_sampler_objects ------------------------ */
+
+#ifndef GL_ARB_sampler_objects
+#define GL_ARB_sampler_objects 1
+
+#define GL_SAMPLER_BINDING 0x8919
+
+typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers);
+typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* params);
+
+#define glBindSampler GLEW_GET_FUN(__glewBindSampler)
+#define glDeleteSamplers GLEW_GET_FUN(__glewDeleteSamplers)
+#define glGenSamplers GLEW_GET_FUN(__glewGenSamplers)
+#define glGetSamplerParameterIiv GLEW_GET_FUN(__glewGetSamplerParameterIiv)
+#define glGetSamplerParameterIuiv GLEW_GET_FUN(__glewGetSamplerParameterIuiv)
+#define glGetSamplerParameterfv GLEW_GET_FUN(__glewGetSamplerParameterfv)
+#define glGetSamplerParameteriv GLEW_GET_FUN(__glewGetSamplerParameteriv)
+#define glIsSampler GLEW_GET_FUN(__glewIsSampler)
+#define glSamplerParameterIiv GLEW_GET_FUN(__glewSamplerParameterIiv)
+#define glSamplerParameterIuiv GLEW_GET_FUN(__glewSamplerParameterIuiv)
+#define glSamplerParameterf GLEW_GET_FUN(__glewSamplerParameterf)
+#define glSamplerParameterfv GLEW_GET_FUN(__glewSamplerParameterfv)
+#define glSamplerParameteri GLEW_GET_FUN(__glewSamplerParameteri)
+#define glSamplerParameteriv GLEW_GET_FUN(__glewSamplerParameteriv)
+
+#define GLEW_ARB_sampler_objects GLEW_GET_VAR(__GLEW_ARB_sampler_objects)
+
+#endif /* GL_ARB_sampler_objects */
+
+/* ------------------------ GL_ARB_seamless_cube_map ----------------------- */
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_ARB_seamless_cube_map 1
+
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+
+#define GLEW_ARB_seamless_cube_map GLEW_GET_VAR(__GLEW_ARB_seamless_cube_map)
+
+#endif /* GL_ARB_seamless_cube_map */
+
+/* --------------------- GL_ARB_separate_shader_objects -------------------- */
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_ARB_separate_shader_objects 1
+
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint x, GLuint y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+
+#define glActiveShaderProgram GLEW_GET_FUN(__glewActiveShaderProgram)
+#define glBindProgramPipeline GLEW_GET_FUN(__glewBindProgramPipeline)
+#define glCreateShaderProgramv GLEW_GET_FUN(__glewCreateShaderProgramv)
+#define glDeleteProgramPipelines GLEW_GET_FUN(__glewDeleteProgramPipelines)
+#define glGenProgramPipelines GLEW_GET_FUN(__glewGenProgramPipelines)
+#define glGetProgramPipelineInfoLog GLEW_GET_FUN(__glewGetProgramPipelineInfoLog)
+#define glGetProgramPipelineiv GLEW_GET_FUN(__glewGetProgramPipelineiv)
+#define glIsProgramPipeline GLEW_GET_FUN(__glewIsProgramPipeline)
+#define glProgramUniform1d GLEW_GET_FUN(__glewProgramUniform1d)
+#define glProgramUniform1dv GLEW_GET_FUN(__glewProgramUniform1dv)
+#define glProgramUniform1f GLEW_GET_FUN(__glewProgramUniform1f)
+#define glProgramUniform1fv GLEW_GET_FUN(__glewProgramUniform1fv)
+#define glProgramUniform1i GLEW_GET_FUN(__glewProgramUniform1i)
+#define glProgramUniform1iv GLEW_GET_FUN(__glewProgramUniform1iv)
+#define glProgramUniform1ui GLEW_GET_FUN(__glewProgramUniform1ui)
+#define glProgramUniform1uiv GLEW_GET_FUN(__glewProgramUniform1uiv)
+#define glProgramUniform2d GLEW_GET_FUN(__glewProgramUniform2d)
+#define glProgramUniform2dv GLEW_GET_FUN(__glewProgramUniform2dv)
+#define glProgramUniform2f GLEW_GET_FUN(__glewProgramUniform2f)
+#define glProgramUniform2fv GLEW_GET_FUN(__glewProgramUniform2fv)
+#define glProgramUniform2i GLEW_GET_FUN(__glewProgramUniform2i)
+#define glProgramUniform2iv GLEW_GET_FUN(__glewProgramUniform2iv)
+#define glProgramUniform2ui GLEW_GET_FUN(__glewProgramUniform2ui)
+#define glProgramUniform2uiv GLEW_GET_FUN(__glewProgramUniform2uiv)
+#define glProgramUniform3d GLEW_GET_FUN(__glewProgramUniform3d)
+#define glProgramUniform3dv GLEW_GET_FUN(__glewProgramUniform3dv)
+#define glProgramUniform3f GLEW_GET_FUN(__glewProgramUniform3f)
+#define glProgramUniform3fv GLEW_GET_FUN(__glewProgramUniform3fv)
+#define glProgramUniform3i GLEW_GET_FUN(__glewProgramUniform3i)
+#define glProgramUniform3iv GLEW_GET_FUN(__glewProgramUniform3iv)
+#define glProgramUniform3ui GLEW_GET_FUN(__glewProgramUniform3ui)
+#define glProgramUniform3uiv GLEW_GET_FUN(__glewProgramUniform3uiv)
+#define glProgramUniform4d GLEW_GET_FUN(__glewProgramUniform4d)
+#define glProgramUniform4dv GLEW_GET_FUN(__glewProgramUniform4dv)
+#define glProgramUniform4f GLEW_GET_FUN(__glewProgramUniform4f)
+#define glProgramUniform4fv GLEW_GET_FUN(__glewProgramUniform4fv)
+#define glProgramUniform4i GLEW_GET_FUN(__glewProgramUniform4i)
+#define glProgramUniform4iv GLEW_GET_FUN(__glewProgramUniform4iv)
+#define glProgramUniform4ui GLEW_GET_FUN(__glewProgramUniform4ui)
+#define glProgramUniform4uiv GLEW_GET_FUN(__glewProgramUniform4uiv)
+#define glProgramUniformMatrix2dv GLEW_GET_FUN(__glewProgramUniformMatrix2dv)
+#define glProgramUniformMatrix2fv GLEW_GET_FUN(__glewProgramUniformMatrix2fv)
+#define glProgramUniformMatrix2x3dv GLEW_GET_FUN(__glewProgramUniformMatrix2x3dv)
+#define glProgramUniformMatrix2x3fv GLEW_GET_FUN(__glewProgramUniformMatrix2x3fv)
+#define glProgramUniformMatrix2x4dv GLEW_GET_FUN(__glewProgramUniformMatrix2x4dv)
+#define glProgramUniformMatrix2x4fv GLEW_GET_FUN(__glewProgramUniformMatrix2x4fv)
+#define glProgramUniformMatrix3dv GLEW_GET_FUN(__glewProgramUniformMatrix3dv)
+#define glProgramUniformMatrix3fv GLEW_GET_FUN(__glewProgramUniformMatrix3fv)
+#define glProgramUniformMatrix3x2dv GLEW_GET_FUN(__glewProgramUniformMatrix3x2dv)
+#define glProgramUniformMatrix3x2fv GLEW_GET_FUN(__glewProgramUniformMatrix3x2fv)
+#define glProgramUniformMatrix3x4dv GLEW_GET_FUN(__glewProgramUniformMatrix3x4dv)
+#define glProgramUniformMatrix3x4fv GLEW_GET_FUN(__glewProgramUniformMatrix3x4fv)
+#define glProgramUniformMatrix4dv GLEW_GET_FUN(__glewProgramUniformMatrix4dv)
+#define glProgramUniformMatrix4fv GLEW_GET_FUN(__glewProgramUniformMatrix4fv)
+#define glProgramUniformMatrix4x2dv GLEW_GET_FUN(__glewProgramUniformMatrix4x2dv)
+#define glProgramUniformMatrix4x2fv GLEW_GET_FUN(__glewProgramUniformMatrix4x2fv)
+#define glProgramUniformMatrix4x3dv GLEW_GET_FUN(__glewProgramUniformMatrix4x3dv)
+#define glProgramUniformMatrix4x3fv GLEW_GET_FUN(__glewProgramUniformMatrix4x3fv)
+#define glUseProgramStages GLEW_GET_FUN(__glewUseProgramStages)
+#define glValidateProgramPipeline GLEW_GET_FUN(__glewValidateProgramPipeline)
+
+#define GLEW_ARB_separate_shader_objects GLEW_GET_VAR(__GLEW_ARB_separate_shader_objects)
+
+#endif /* GL_ARB_separate_shader_objects */
+
+/* --------------------- GL_ARB_shader_atomic_counters --------------------- */
+
+#ifndef GL_ARB_shader_atomic_counters
+#define GL_ARB_shader_atomic_counters 1
+
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint* params);
+
+#define glGetActiveAtomicCounterBufferiv GLEW_GET_FUN(__glewGetActiveAtomicCounterBufferiv)
+
+#define GLEW_ARB_shader_atomic_counters GLEW_GET_VAR(__GLEW_ARB_shader_atomic_counters)
+
+#endif /* GL_ARB_shader_atomic_counters */
+
+/* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */
+
+#ifndef GL_ARB_shader_bit_encoding
+#define GL_ARB_shader_bit_encoding 1
+
+#define GLEW_ARB_shader_bit_encoding GLEW_GET_VAR(__GLEW_ARB_shader_bit_encoding)
+
+#endif /* GL_ARB_shader_bit_encoding */
+
+/* --------------------- GL_ARB_shader_image_load_store -------------------- */
+
+#ifndef GL_ARB_shader_image_load_store
+#define GL_ARB_shader_image_load_store 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GLAPIENTRY * PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+
+#define glBindImageTexture GLEW_GET_FUN(__glewBindImageTexture)
+#define glMemoryBarrier GLEW_GET_FUN(__glewMemoryBarrier)
+
+#define GLEW_ARB_shader_image_load_store GLEW_GET_VAR(__GLEW_ARB_shader_image_load_store)
+
+#endif /* GL_ARB_shader_image_load_store */
+
+/* ------------------------- GL_ARB_shader_objects ------------------------- */
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+
+typedef char GLcharARB;
+typedef unsigned int GLhandleARB;
+
+typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj);
+typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source);
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params);
+typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+
+#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB)
+#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB)
+#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB)
+#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB)
+#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB)
+#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB)
+#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB)
+#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB)
+#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB)
+#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB)
+#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB)
+#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB)
+#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB)
+#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB)
+#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB)
+#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB)
+#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB)
+#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB)
+#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB)
+#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB)
+#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB)
+#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB)
+#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB)
+#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB)
+#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB)
+#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB)
+#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB)
+#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB)
+#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB)
+#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB)
+#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB)
+#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB)
+#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB)
+#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB)
+#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB)
+#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB)
+#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB)
+#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB)
+#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB)
+
+#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects)
+
+#endif /* GL_ARB_shader_objects */
+
+/* ------------------------ GL_ARB_shader_precision ------------------------ */
+
+#ifndef GL_ARB_shader_precision
+#define GL_ARB_shader_precision 1
+
+#define GLEW_ARB_shader_precision GLEW_GET_VAR(__GLEW_ARB_shader_precision)
+
+#endif /* GL_ARB_shader_precision */
+
+/* ---------------------- GL_ARB_shader_stencil_export --------------------- */
+
+#ifndef GL_ARB_shader_stencil_export
+#define GL_ARB_shader_stencil_export 1
+
+#define GLEW_ARB_shader_stencil_export GLEW_GET_VAR(__GLEW_ARB_shader_stencil_export)
+
+#endif /* GL_ARB_shader_stencil_export */
+
+/* ------------------------ GL_ARB_shader_subroutine ----------------------- */
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ARB_shader_subroutine 1
+
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values);
+typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name);
+typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices);
+
+#define glGetActiveSubroutineName GLEW_GET_FUN(__glewGetActiveSubroutineName)
+#define glGetActiveSubroutineUniformName GLEW_GET_FUN(__glewGetActiveSubroutineUniformName)
+#define glGetActiveSubroutineUniformiv GLEW_GET_FUN(__glewGetActiveSubroutineUniformiv)
+#define glGetProgramStageiv GLEW_GET_FUN(__glewGetProgramStageiv)
+#define glGetSubroutineIndex GLEW_GET_FUN(__glewGetSubroutineIndex)
+#define glGetSubroutineUniformLocation GLEW_GET_FUN(__glewGetSubroutineUniformLocation)
+#define glGetUniformSubroutineuiv GLEW_GET_FUN(__glewGetUniformSubroutineuiv)
+#define glUniformSubroutinesuiv GLEW_GET_FUN(__glewUniformSubroutinesuiv)
+
+#define GLEW_ARB_shader_subroutine GLEW_GET_VAR(__GLEW_ARB_shader_subroutine)
+
+#endif /* GL_ARB_shader_subroutine */
+
+/* ----------------------- GL_ARB_shader_texture_lod ----------------------- */
+
+#ifndef GL_ARB_shader_texture_lod
+#define GL_ARB_shader_texture_lod 1
+
+#define GLEW_ARB_shader_texture_lod GLEW_GET_VAR(__GLEW_ARB_shader_texture_lod)
+
+#endif /* GL_ARB_shader_texture_lod */
+
+/* ---------------------- GL_ARB_shading_language_100 ---------------------- */
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+
+#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100)
+
+#endif /* GL_ARB_shading_language_100 */
+
+/* -------------------- GL_ARB_shading_language_420pack -------------------- */
+
+#ifndef GL_ARB_shading_language_420pack
+#define GL_ARB_shading_language_420pack 1
+
+#define GLEW_ARB_shading_language_420pack GLEW_GET_VAR(__GLEW_ARB_shading_language_420pack)
+
+#endif /* GL_ARB_shading_language_420pack */
+
+/* -------------------- GL_ARB_shading_language_include -------------------- */
+
+#ifndef GL_ARB_shading_language_include
+#define GL_ARB_shading_language_include 1
+
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+
+typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length);
+typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name);
+typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string);
+
+#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB)
+#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB)
+#define glGetNamedStringARB GLEW_GET_FUN(__glewGetNamedStringARB)
+#define glGetNamedStringivARB GLEW_GET_FUN(__glewGetNamedStringivARB)
+#define glIsNamedStringARB GLEW_GET_FUN(__glewIsNamedStringARB)
+#define glNamedStringARB GLEW_GET_FUN(__glewNamedStringARB)
+
+#define GLEW_ARB_shading_language_include GLEW_GET_VAR(__GLEW_ARB_shading_language_include)
+
+#endif /* GL_ARB_shading_language_include */
+
+/* -------------------- GL_ARB_shading_language_packing -------------------- */
+
+#ifndef GL_ARB_shading_language_packing
+#define GL_ARB_shading_language_packing 1
+
+#define GLEW_ARB_shading_language_packing GLEW_GET_VAR(__GLEW_ARB_shading_language_packing)
+
+#endif /* GL_ARB_shading_language_packing */
+
+/* ----------------------------- GL_ARB_shadow ----------------------------- */
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+
+#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow)
+
+#endif /* GL_ARB_shadow */
+
+/* ------------------------- GL_ARB_shadow_ambient ------------------------- */
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+
+#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient)
+
+#endif /* GL_ARB_shadow_ambient */
+
+/* ------------------------------ GL_ARB_sync ------------------------------ */
+
+#ifndef GL_ARB_sync
+#define GL_ARB_sync 1
+
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+
+typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout);
+typedef void (GLAPIENTRY * PFNGLDELETESYNCPROC) (GLsync GLsync);
+typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags);
+typedef void (GLAPIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETSYNCIVPROC) (GLsync GLsync,GLenum pname,GLsizei bufSize,GLsizei* length, GLint *values);
+typedef GLboolean (GLAPIENTRY * PFNGLISSYNCPROC) (GLsync GLsync);
+typedef void (GLAPIENTRY * PFNGLWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout);
+
+#define glClientWaitSync GLEW_GET_FUN(__glewClientWaitSync)
+#define glDeleteSync GLEW_GET_FUN(__glewDeleteSync)
+#define glFenceSync GLEW_GET_FUN(__glewFenceSync)
+#define glGetInteger64v GLEW_GET_FUN(__glewGetInteger64v)
+#define glGetSynciv GLEW_GET_FUN(__glewGetSynciv)
+#define glIsSync GLEW_GET_FUN(__glewIsSync)
+#define glWaitSync GLEW_GET_FUN(__glewWaitSync)
+
+#define GLEW_ARB_sync GLEW_GET_VAR(__GLEW_ARB_sync)
+
+#endif /* GL_ARB_sync */
+
+/* ----------------------- GL_ARB_tessellation_shader ---------------------- */
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_ARB_tessellation_shader 1
+
+#define GL_PATCHES 0xE
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_ISOLINES 0x8E7A
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+
+typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat* values);
+typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+
+#define glPatchParameterfv GLEW_GET_FUN(__glewPatchParameterfv)
+#define glPatchParameteri GLEW_GET_FUN(__glewPatchParameteri)
+
+#define GLEW_ARB_tessellation_shader GLEW_GET_VAR(__GLEW_ARB_tessellation_shader)
+
+#endif /* GL_ARB_tessellation_shader */
+
+/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+
+#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp)
+
+#endif /* GL_ARB_texture_border_clamp */
+
+/* ---------------------- GL_ARB_texture_buffer_object --------------------- */
+
+#ifndef GL_ARB_texture_buffer_object
+#define GL_ARB_texture_buffer_object 1
+
+#define GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+
+typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+
+#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB)
+
+#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object)
+
+#endif /* GL_ARB_texture_buffer_object */
+
+/* ------------------- GL_ARB_texture_buffer_object_rgb32 ------------------ */
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+#define GL_ARB_texture_buffer_object_rgb32 1
+
+#define GLEW_ARB_texture_buffer_object_rgb32 GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object_rgb32)
+
+#endif /* GL_ARB_texture_buffer_object_rgb32 */
+
+/* ----------------------- GL_ARB_texture_compression ---------------------- */
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img);
+
+#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB)
+#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB)
+#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB)
+#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB)
+#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB)
+#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB)
+#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB)
+
+#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression)
+
+#endif /* GL_ARB_texture_compression */
+
+/* -------------------- GL_ARB_texture_compression_bptc -------------------- */
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_ARB_texture_compression_bptc 1
+
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+
+#define GLEW_ARB_texture_compression_bptc GLEW_GET_VAR(__GLEW_ARB_texture_compression_bptc)
+
+#endif /* GL_ARB_texture_compression_bptc */
+
+/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc 1
+
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+
+#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc)
+
+#endif /* GL_ARB_texture_compression_rgtc */
+
+/* ------------------------ GL_ARB_texture_cube_map ------------------------ */
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+
+#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map)
+
+#endif /* GL_ARB_texture_cube_map */
+
+/* --------------------- GL_ARB_texture_cube_map_array --------------------- */
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_ARB_texture_cube_map_array 1
+
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+
+#define GLEW_ARB_texture_cube_map_array GLEW_GET_VAR(__GLEW_ARB_texture_cube_map_array)
+
+#endif /* GL_ARB_texture_cube_map_array */
+
+/* ------------------------- GL_ARB_texture_env_add ------------------------ */
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+
+#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add)
+
+#endif /* GL_ARB_texture_env_add */
+
+/* ----------------------- GL_ARB_texture_env_combine ---------------------- */
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+
+#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine)
+
+#endif /* GL_ARB_texture_env_combine */
+
+/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+
+#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar)
+
+#endif /* GL_ARB_texture_env_crossbar */
+
+/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+
+#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3)
+
+#endif /* GL_ARB_texture_env_dot3 */
+
+/* -------------------------- GL_ARB_texture_float ------------------------- */
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+
+#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float)
+
+#endif /* GL_ARB_texture_float */
+
+/* ------------------------- GL_ARB_texture_gather ------------------------- */
+
+#ifndef GL_ARB_texture_gather
+#define GL_ARB_texture_gather 1
+
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+
+#define GLEW_ARB_texture_gather GLEW_GET_VAR(__GLEW_ARB_texture_gather)
+
+#endif /* GL_ARB_texture_gather */
+
+/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+
+#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat)
+
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+/* ----------------------- GL_ARB_texture_multisample ---------------------- */
+
+#ifndef GL_ARB_texture_multisample
+#define GL_ARB_texture_multisample 1
+
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+
+typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+
+#define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv)
+#define glSampleMaski GLEW_GET_FUN(__glewSampleMaski)
+#define glTexImage2DMultisample GLEW_GET_FUN(__glewTexImage2DMultisample)
+#define glTexImage3DMultisample GLEW_GET_FUN(__glewTexImage3DMultisample)
+
+#define GLEW_ARB_texture_multisample GLEW_GET_VAR(__GLEW_ARB_texture_multisample)
+
+#endif /* GL_ARB_texture_multisample */
+
+/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+
+#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two)
+
+#endif /* GL_ARB_texture_non_power_of_two */
+
+/* ------------------------ GL_ARB_texture_query_lod ----------------------- */
+
+#ifndef GL_ARB_texture_query_lod
+#define GL_ARB_texture_query_lod 1
+
+#define GLEW_ARB_texture_query_lod GLEW_GET_VAR(__GLEW_ARB_texture_query_lod)
+
+#endif /* GL_ARB_texture_query_lod */
+
+/* ------------------------ GL_ARB_texture_rectangle ----------------------- */
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+
+#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle)
+
+#endif /* GL_ARB_texture_rectangle */
+
+/* --------------------------- GL_ARB_texture_rg --------------------------- */
+
+#ifndef GL_ARB_texture_rg
+#define GL_ARB_texture_rg 1
+
+#define GL_RED 0x1903
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+
+#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg)
+
+#endif /* GL_ARB_texture_rg */
+
+/* ----------------------- GL_ARB_texture_rgb10_a2ui ----------------------- */
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_ARB_texture_rgb10_a2ui 1
+
+#define GL_RGB10_A2UI 0x906F
+
+#define GLEW_ARB_texture_rgb10_a2ui GLEW_GET_VAR(__GLEW_ARB_texture_rgb10_a2ui)
+
+#endif /* GL_ARB_texture_rgb10_a2ui */
+
+/* ------------------------- GL_ARB_texture_storage ------------------------ */
+
+#ifndef GL_ARB_texture_storage
+#define GL_ARB_texture_storage 1
+
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glTexStorage1D GLEW_GET_FUN(__glewTexStorage1D)
+#define glTexStorage2D GLEW_GET_FUN(__glewTexStorage2D)
+#define glTexStorage3D GLEW_GET_FUN(__glewTexStorage3D)
+#define glTextureStorage1DEXT GLEW_GET_FUN(__glewTextureStorage1DEXT)
+#define glTextureStorage2DEXT GLEW_GET_FUN(__glewTextureStorage2DEXT)
+#define glTextureStorage3DEXT GLEW_GET_FUN(__glewTextureStorage3DEXT)
+
+#define GLEW_ARB_texture_storage GLEW_GET_VAR(__GLEW_ARB_texture_storage)
+
+#endif /* GL_ARB_texture_storage */
+
+/* ------------------------- GL_ARB_texture_swizzle ------------------------ */
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_ARB_texture_swizzle 1
+
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+
+#define GLEW_ARB_texture_swizzle GLEW_GET_VAR(__GLEW_ARB_texture_swizzle)
+
+#endif /* GL_ARB_texture_swizzle */
+
+/* --------------------------- GL_ARB_timer_query -------------------------- */
+
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params);
+typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+
+#define glGetQueryObjecti64v GLEW_GET_FUN(__glewGetQueryObjecti64v)
+#define glGetQueryObjectui64v GLEW_GET_FUN(__glewGetQueryObjectui64v)
+#define glQueryCounter GLEW_GET_FUN(__glewQueryCounter)
+
+#define GLEW_ARB_timer_query GLEW_GET_VAR(__GLEW_ARB_timer_query)
+
+#endif /* GL_ARB_timer_query */
+
+/* ----------------------- GL_ARB_transform_feedback2 ---------------------- */
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_ARB_transform_feedback2 1
+
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+
+typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids);
+typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+
+#define glBindTransformFeedback GLEW_GET_FUN(__glewBindTransformFeedback)
+#define glDeleteTransformFeedbacks GLEW_GET_FUN(__glewDeleteTransformFeedbacks)
+#define glDrawTransformFeedback GLEW_GET_FUN(__glewDrawTransformFeedback)
+#define glGenTransformFeedbacks GLEW_GET_FUN(__glewGenTransformFeedbacks)
+#define glIsTransformFeedback GLEW_GET_FUN(__glewIsTransformFeedback)
+#define glPauseTransformFeedback GLEW_GET_FUN(__glewPauseTransformFeedback)
+#define glResumeTransformFeedback GLEW_GET_FUN(__glewResumeTransformFeedback)
+
+#define GLEW_ARB_transform_feedback2 GLEW_GET_VAR(__GLEW_ARB_transform_feedback2)
+
+#endif /* GL_ARB_transform_feedback2 */
+
+/* ----------------------- GL_ARB_transform_feedback3 ---------------------- */
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_ARB_transform_feedback3 1
+
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+
+typedef void (GLAPIENTRY * PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (GLAPIENTRY * PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params);
+
+#define glBeginQueryIndexed GLEW_GET_FUN(__glewBeginQueryIndexed)
+#define glDrawTransformFeedbackStream GLEW_GET_FUN(__glewDrawTransformFeedbackStream)
+#define glEndQueryIndexed GLEW_GET_FUN(__glewEndQueryIndexed)
+#define glGetQueryIndexediv GLEW_GET_FUN(__glewGetQueryIndexediv)
+
+#define GLEW_ARB_transform_feedback3 GLEW_GET_VAR(__GLEW_ARB_transform_feedback3)
+
+#endif /* GL_ARB_transform_feedback3 */
+
+/* ------------------ GL_ARB_transform_feedback_instanced ------------------ */
+
+#ifndef GL_ARB_transform_feedback_instanced
+#define GL_ARB_transform_feedback_instanced 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei primcount);
+
+#define glDrawTransformFeedbackInstanced GLEW_GET_FUN(__glewDrawTransformFeedbackInstanced)
+#define glDrawTransformFeedbackStreamInstanced GLEW_GET_FUN(__glewDrawTransformFeedbackStreamInstanced)
+
+#define GLEW_ARB_transform_feedback_instanced GLEW_GET_VAR(__GLEW_ARB_transform_feedback_instanced)
+
+#endif /* GL_ARB_transform_feedback_instanced */
+
+/* ------------------------ GL_ARB_transpose_matrix ------------------------ */
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]);
+typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]);
+
+#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB)
+#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB)
+#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB)
+#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB)
+
+#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix)
+
+#endif /* GL_ARB_transpose_matrix */
+
+/* ---------------------- GL_ARB_uniform_buffer_object --------------------- */
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_ARB_uniform_buffer_object 1
+
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data);
+typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices);
+typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+
+#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase)
+#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange)
+#define glGetActiveUniformBlockName GLEW_GET_FUN(__glewGetActiveUniformBlockName)
+#define glGetActiveUniformBlockiv GLEW_GET_FUN(__glewGetActiveUniformBlockiv)
+#define glGetActiveUniformName GLEW_GET_FUN(__glewGetActiveUniformName)
+#define glGetActiveUniformsiv GLEW_GET_FUN(__glewGetActiveUniformsiv)
+#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v)
+#define glGetUniformBlockIndex GLEW_GET_FUN(__glewGetUniformBlockIndex)
+#define glGetUniformIndices GLEW_GET_FUN(__glewGetUniformIndices)
+#define glUniformBlockBinding GLEW_GET_FUN(__glewUniformBlockBinding)
+
+#define GLEW_ARB_uniform_buffer_object GLEW_GET_VAR(__GLEW_ARB_uniform_buffer_object)
+
+#endif /* GL_ARB_uniform_buffer_object */
+
+/* ------------------------ GL_ARB_vertex_array_bgra ----------------------- */
+
+#ifndef GL_ARB_vertex_array_bgra
+#define GL_ARB_vertex_array_bgra 1
+
+#define GL_BGRA 0x80E1
+
+#define GLEW_ARB_vertex_array_bgra GLEW_GET_VAR(__GLEW_ARB_vertex_array_bgra)
+
+#endif /* GL_ARB_vertex_array_bgra */
+
+/* ----------------------- GL_ARB_vertex_array_object ---------------------- */
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_ARB_vertex_array_object 1
+
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
+typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
+typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array);
+
+#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray)
+#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays)
+#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays)
+#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray)
+
+#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object)
+
+#endif /* GL_ARB_vertex_array_object */
+
+/* ----------------------- GL_ARB_vertex_attrib_64bit ---------------------- */
+
+#ifndef GL_ARB_vertex_attrib_64bit
+#define GL_ARB_vertex_attrib_64bit 1
+
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+
+#define glGetVertexAttribLdv GLEW_GET_FUN(__glewGetVertexAttribLdv)
+#define glVertexAttribL1d GLEW_GET_FUN(__glewVertexAttribL1d)
+#define glVertexAttribL1dv GLEW_GET_FUN(__glewVertexAttribL1dv)
+#define glVertexAttribL2d GLEW_GET_FUN(__glewVertexAttribL2d)
+#define glVertexAttribL2dv GLEW_GET_FUN(__glewVertexAttribL2dv)
+#define glVertexAttribL3d GLEW_GET_FUN(__glewVertexAttribL3d)
+#define glVertexAttribL3dv GLEW_GET_FUN(__glewVertexAttribL3dv)
+#define glVertexAttribL4d GLEW_GET_FUN(__glewVertexAttribL4d)
+#define glVertexAttribL4dv GLEW_GET_FUN(__glewVertexAttribL4dv)
+#define glVertexAttribLPointer GLEW_GET_FUN(__glewVertexAttribLPointer)
+
+#define GLEW_ARB_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_64bit)
+
+#endif /* GL_ARB_vertex_attrib_64bit */
+
+/* -------------------------- GL_ARB_vertex_blend -------------------------- */
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights);
+typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights);
+
+#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB)
+#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB)
+#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB)
+#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB)
+#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB)
+#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB)
+#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB)
+#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB)
+#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB)
+#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB)
+
+#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend)
+
+#endif /* GL_ARB_vertex_blend */
+
+/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+
+#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB)
+#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB)
+#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB)
+#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB)
+#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB)
+#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB)
+#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB)
+#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB)
+#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB)
+#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB)
+#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB)
+
+#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object)
+
+#endif /* GL_ARB_vertex_buffer_object */
+
+/* ------------------------- GL_ARB_vertex_program ------------------------- */
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
+
+#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB)
+#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB)
+#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB)
+#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB)
+#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB)
+#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB)
+#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB)
+#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB)
+#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB)
+#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB)
+#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB)
+#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB)
+#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB)
+#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB)
+#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB)
+#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB)
+#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB)
+#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB)
+#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB)
+#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB)
+#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB)
+#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB)
+#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB)
+#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB)
+#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB)
+#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB)
+#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB)
+#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB)
+#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB)
+#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB)
+#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB)
+#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB)
+#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB)
+#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB)
+#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB)
+#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB)
+#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB)
+#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB)
+#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB)
+#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB)
+#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB)
+#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB)
+#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB)
+#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB)
+#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB)
+#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB)
+#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB)
+#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB)
+#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB)
+#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB)
+#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB)
+#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB)
+#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB)
+#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB)
+#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB)
+#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB)
+#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB)
+#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB)
+#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB)
+#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB)
+#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB)
+#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB)
+
+#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program)
+
+#endif /* GL_ARB_vertex_program */
+
+/* -------------------------- GL_ARB_vertex_shader ------------------------- */
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+
+typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name);
+
+#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB)
+#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB)
+#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB)
+
+#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader)
+
+#endif /* GL_ARB_vertex_shader */
+
+/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_INT_2_10_10_10_REV 0x8D9F
+
+typedef void (GLAPIENTRY * PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (GLAPIENTRY * PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint* color);
+typedef void (GLAPIENTRY * PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (GLAPIENTRY * PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint* color);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint* color);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint* coords);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (GLAPIENTRY * PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint* value);
+
+#define glColorP3ui GLEW_GET_FUN(__glewColorP3ui)
+#define glColorP3uiv GLEW_GET_FUN(__glewColorP3uiv)
+#define glColorP4ui GLEW_GET_FUN(__glewColorP4ui)
+#define glColorP4uiv GLEW_GET_FUN(__glewColorP4uiv)
+#define glMultiTexCoordP1ui GLEW_GET_FUN(__glewMultiTexCoordP1ui)
+#define glMultiTexCoordP1uiv GLEW_GET_FUN(__glewMultiTexCoordP1uiv)
+#define glMultiTexCoordP2ui GLEW_GET_FUN(__glewMultiTexCoordP2ui)
+#define glMultiTexCoordP2uiv GLEW_GET_FUN(__glewMultiTexCoordP2uiv)
+#define glMultiTexCoordP3ui GLEW_GET_FUN(__glewMultiTexCoordP3ui)
+#define glMultiTexCoordP3uiv GLEW_GET_FUN(__glewMultiTexCoordP3uiv)
+#define glMultiTexCoordP4ui GLEW_GET_FUN(__glewMultiTexCoordP4ui)
+#define glMultiTexCoordP4uiv GLEW_GET_FUN(__glewMultiTexCoordP4uiv)
+#define glNormalP3ui GLEW_GET_FUN(__glewNormalP3ui)
+#define glNormalP3uiv GLEW_GET_FUN(__glewNormalP3uiv)
+#define glSecondaryColorP3ui GLEW_GET_FUN(__glewSecondaryColorP3ui)
+#define glSecondaryColorP3uiv GLEW_GET_FUN(__glewSecondaryColorP3uiv)
+#define glTexCoordP1ui GLEW_GET_FUN(__glewTexCoordP1ui)
+#define glTexCoordP1uiv GLEW_GET_FUN(__glewTexCoordP1uiv)
+#define glTexCoordP2ui GLEW_GET_FUN(__glewTexCoordP2ui)
+#define glTexCoordP2uiv GLEW_GET_FUN(__glewTexCoordP2uiv)
+#define glTexCoordP3ui GLEW_GET_FUN(__glewTexCoordP3ui)
+#define glTexCoordP3uiv GLEW_GET_FUN(__glewTexCoordP3uiv)
+#define glTexCoordP4ui GLEW_GET_FUN(__glewTexCoordP4ui)
+#define glTexCoordP4uiv GLEW_GET_FUN(__glewTexCoordP4uiv)
+#define glVertexAttribP1ui GLEW_GET_FUN(__glewVertexAttribP1ui)
+#define glVertexAttribP1uiv GLEW_GET_FUN(__glewVertexAttribP1uiv)
+#define glVertexAttribP2ui GLEW_GET_FUN(__glewVertexAttribP2ui)
+#define glVertexAttribP2uiv GLEW_GET_FUN(__glewVertexAttribP2uiv)
+#define glVertexAttribP3ui GLEW_GET_FUN(__glewVertexAttribP3ui)
+#define glVertexAttribP3uiv GLEW_GET_FUN(__glewVertexAttribP3uiv)
+#define glVertexAttribP4ui GLEW_GET_FUN(__glewVertexAttribP4ui)
+#define glVertexAttribP4uiv GLEW_GET_FUN(__glewVertexAttribP4uiv)
+#define glVertexP2ui GLEW_GET_FUN(__glewVertexP2ui)
+#define glVertexP2uiv GLEW_GET_FUN(__glewVertexP2uiv)
+#define glVertexP3ui GLEW_GET_FUN(__glewVertexP3ui)
+#define glVertexP3uiv GLEW_GET_FUN(__glewVertexP3uiv)
+#define glVertexP4ui GLEW_GET_FUN(__glewVertexP4ui)
+#define glVertexP4uiv GLEW_GET_FUN(__glewVertexP4uiv)
+
+#define GLEW_ARB_vertex_type_2_10_10_10_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_2_10_10_10_rev)
+
+#endif /* GL_ARB_vertex_type_2_10_10_10_rev */
+
+/* ------------------------- GL_ARB_viewport_array ------------------------- */
+
+#ifndef GL_ARB_viewport_array
+#define GL_ARB_viewport_array 1
+
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd * v);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble* data);
+typedef void (GLAPIENTRY * PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint * v);
+typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint * v);
+typedef void (GLAPIENTRY * PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat * v);
+
+#define glDepthRangeArrayv GLEW_GET_FUN(__glewDepthRangeArrayv)
+#define glDepthRangeIndexed GLEW_GET_FUN(__glewDepthRangeIndexed)
+#define glGetDoublei_v GLEW_GET_FUN(__glewGetDoublei_v)
+#define glGetFloati_v GLEW_GET_FUN(__glewGetFloati_v)
+#define glScissorArrayv GLEW_GET_FUN(__glewScissorArrayv)
+#define glScissorIndexed GLEW_GET_FUN(__glewScissorIndexed)
+#define glScissorIndexedv GLEW_GET_FUN(__glewScissorIndexedv)
+#define glViewportArrayv GLEW_GET_FUN(__glewViewportArrayv)
+#define glViewportIndexedf GLEW_GET_FUN(__glewViewportIndexedf)
+#define glViewportIndexedfv GLEW_GET_FUN(__glewViewportIndexedfv)
+
+#define GLEW_ARB_viewport_array GLEW_GET_VAR(__GLEW_ARB_viewport_array)
+
+#endif /* GL_ARB_viewport_array */
+
+/* --------------------------- GL_ARB_window_pos --------------------------- */
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p);
+
+#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB)
+#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB)
+#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB)
+#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB)
+#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB)
+#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB)
+#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB)
+#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB)
+#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB)
+#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB)
+#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB)
+#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB)
+#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB)
+#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB)
+#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB)
+#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB)
+
+#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos)
+
+#endif /* GL_ARB_window_pos */
+
+/* ------------------------- GL_ATIX_point_sprites ------------------------- */
+
+#ifndef GL_ATIX_point_sprites
+#define GL_ATIX_point_sprites 1
+
+#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0
+#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1
+#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2
+#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3
+#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4
+#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5
+
+#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites)
+
+#endif /* GL_ATIX_point_sprites */
+
+/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */
+
+#ifndef GL_ATIX_texture_env_combine3
+#define GL_ATIX_texture_env_combine3 1
+
+#define GL_MODULATE_ADD_ATIX 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745
+#define GL_MODULATE_SUBTRACT_ATIX 0x8746
+
+#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3)
+
+#endif /* GL_ATIX_texture_env_combine3 */
+
+/* ----------------------- GL_ATIX_texture_env_route ----------------------- */
+
+#ifndef GL_ATIX_texture_env_route
+#define GL_ATIX_texture_env_route 1
+
+#define GL_SECONDARY_COLOR_ATIX 0x8747
+#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748
+#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749
+
+#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route)
+
+#endif /* GL_ATIX_texture_env_route */
+
+/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */
+
+#ifndef GL_ATIX_vertex_shader_output_point_size
+#define GL_ATIX_vertex_shader_output_point_size 1
+
+#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E
+
+#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size)
+
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+
+/* -------------------------- GL_ATI_draw_buffers -------------------------- */
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs);
+
+#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI)
+
+#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers)
+
+#endif /* GL_ATI_draw_buffers */
+
+/* -------------------------- GL_ATI_element_array ------------------------- */
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer);
+
+#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI)
+#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI)
+#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI)
+
+#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array)
+
+#endif /* GL_ATI_element_array */
+
+/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+
+typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+
+#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI)
+#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI)
+#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI)
+#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI)
+
+#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap)
+
+#endif /* GL_ATI_envmap_bumpmap */
+
+/* ------------------------- GL_ATI_fragment_shader ------------------------ */
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value);
+
+#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI)
+#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI)
+#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI)
+#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI)
+#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI)
+#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI)
+#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI)
+#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI)
+#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI)
+#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI)
+#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI)
+#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI)
+#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI)
+#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI)
+
+#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader)
+
+#endif /* GL_ATI_fragment_shader */
+
+/* ------------------------ GL_ATI_map_object_buffer ----------------------- */
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+
+typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+
+#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI)
+#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI)
+
+#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer)
+
+#endif /* GL_ATI_map_object_buffer */
+
+/* ----------------------------- GL_ATI_meminfo ---------------------------- */
+
+#ifndef GL_ATI_meminfo
+#define GL_ATI_meminfo 1
+
+#define GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+
+#define GLEW_ATI_meminfo GLEW_GET_VAR(__GLEW_ATI_meminfo)
+
+#endif /* GL_ATI_meminfo */
+
+/* -------------------------- GL_ATI_pn_triangles -------------------------- */
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+
+typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+
+#define glPNTrianglesfATI GLEW_GET_FUN(__glewPNTrianglesfATI)
+#define glPNTrianglesiATI GLEW_GET_FUN(__glewPNTrianglesiATI)
+
+#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles)
+
+#endif /* GL_ATI_pn_triangles */
+
+/* ------------------------ GL_ATI_separate_stencil ------------------------ */
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+
+typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+
+#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI)
+#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI)
+
+#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil)
+
+#endif /* GL_ATI_separate_stencil */
+
+/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */
+
+#ifndef GL_ATI_shader_texture_lod
+#define GL_ATI_shader_texture_lod 1
+
+#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod)
+
+#endif /* GL_ATI_shader_texture_lod */
+
+/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+
+#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader)
+
+#endif /* GL_ATI_text_fragment_shader */
+
+/* --------------------- GL_ATI_texture_compression_3dc -------------------- */
+
+#ifndef GL_ATI_texture_compression_3dc
+#define GL_ATI_texture_compression_3dc 1
+
+#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837
+
+#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc)
+
+#endif /* GL_ATI_texture_compression_3dc */
+
+/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+
+#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3)
+
+#endif /* GL_ATI_texture_env_combine3 */
+
+/* -------------------------- GL_ATI_texture_float ------------------------- */
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+
+#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float)
+
+#endif /* GL_ATI_texture_float */
+
+/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+
+#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once)
+
+#endif /* GL_ATI_texture_mirror_once */
+
+/* ----------------------- GL_ATI_vertex_array_object ---------------------- */
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+
+typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve);
+typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+
+#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI)
+#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI)
+#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI)
+#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI)
+#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI)
+#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI)
+#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI)
+#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI)
+#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI)
+#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI)
+#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI)
+#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI)
+
+#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object)
+
+#endif /* GL_ATI_vertex_array_object */
+
+/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+
+#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI)
+#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI)
+#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI)
+
+#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object)
+
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+/* ------------------------- GL_ATI_vertex_streams ------------------------- */
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_SOURCE_ATI 0x876C
+#define GL_VERTEX_STREAM0_ATI 0x876D
+#define GL_VERTEX_STREAM1_ATI 0x876E
+#define GL_VERTEX_STREAM2_ATI 0x876F
+#define GL_VERTEX_STREAM3_ATI 0x8770
+#define GL_VERTEX_STREAM4_ATI 0x8771
+#define GL_VERTEX_STREAM5_ATI 0x8772
+#define GL_VERTEX_STREAM6_ATI 0x8773
+#define GL_VERTEX_STREAM7_ATI 0x8774
+
+typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v);
+
+#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI)
+#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI)
+#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI)
+#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI)
+#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI)
+#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI)
+#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI)
+#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI)
+#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI)
+#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI)
+#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI)
+#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI)
+#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI)
+#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI)
+#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI)
+#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI)
+#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI)
+#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI)
+#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI)
+#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI)
+#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI)
+#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI)
+#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI)
+#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI)
+#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI)
+#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI)
+#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI)
+#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI)
+#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI)
+#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI)
+#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI)
+#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI)
+#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI)
+#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI)
+#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI)
+#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI)
+#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI)
+
+#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams)
+
+#endif /* GL_ATI_vertex_streams */
+
+/* --------------------------- GL_EXT_422_pixels --------------------------- */
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+
+#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels)
+
+#endif /* GL_EXT_422_pixels */
+
+/* ---------------------------- GL_EXT_Cg_shader --------------------------- */
+
+#ifndef GL_EXT_Cg_shader
+#define GL_EXT_Cg_shader 1
+
+#define GL_CG_VERTEX_SHADER_EXT 0x890E
+#define GL_CG_FRAGMENT_SHADER_EXT 0x890F
+
+#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader)
+
+#endif /* GL_EXT_Cg_shader */
+
+/* ------------------------------ GL_EXT_abgr ------------------------------ */
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+
+#define GL_ABGR_EXT 0x8000
+
+#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr)
+
+#endif /* GL_EXT_abgr */
+
+/* ------------------------------ GL_EXT_bgra ------------------------------ */
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+
+#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra)
+
+#endif /* GL_EXT_bgra */
+
+/* ------------------------ GL_EXT_bindable_uniform ------------------------ */
+
+#ifndef GL_EXT_bindable_uniform
+#define GL_EXT_bindable_uniform 1
+
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+
+typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+
+#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT)
+#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT)
+#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT)
+
+#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform)
+
+#endif /* GL_EXT_bindable_uniform */
+
+/* --------------------------- GL_EXT_blend_color -------------------------- */
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+
+typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+
+#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT)
+
+#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color)
+
+#endif /* GL_EXT_blend_color */
+
+/* --------------------- GL_EXT_blend_equation_separate -------------------- */
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+
+#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT)
+
+#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate)
+
+#endif /* GL_EXT_blend_equation_separate */
+
+/* ----------------------- GL_EXT_blend_func_separate ---------------------- */
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+
+typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+
+#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT)
+
+#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate)
+
+#endif /* GL_EXT_blend_func_separate */
+
+/* ------------------------- GL_EXT_blend_logic_op ------------------------- */
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+
+#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op)
+
+#endif /* GL_EXT_blend_logic_op */
+
+/* -------------------------- GL_EXT_blend_minmax -------------------------- */
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_BLEND_EQUATION_EXT 0x8009
+
+typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+
+#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT)
+
+#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax)
+
+#endif /* GL_EXT_blend_minmax */
+
+/* ------------------------- GL_EXT_blend_subtract ------------------------- */
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+
+#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract)
+
+#endif /* GL_EXT_blend_subtract */
+
+/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+
+#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint)
+
+#endif /* GL_EXT_clip_volume_hint */
+
+/* ------------------------------ GL_EXT_cmyka ----------------------------- */
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+
+#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka)
+
+#endif /* GL_EXT_cmyka */
+
+/* ------------------------- GL_EXT_color_subtable ------------------------- */
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+
+typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+
+#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT)
+#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT)
+
+#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable)
+
+#endif /* GL_EXT_color_subtable */
+
+/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+
+typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
+
+#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT)
+#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT)
+
+#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array)
+
+#endif /* GL_EXT_compiled_vertex_array */
+
+/* --------------------------- GL_EXT_convolution -------------------------- */
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span);
+typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column);
+
+#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT)
+#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT)
+#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT)
+#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT)
+#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT)
+#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT)
+#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT)
+#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT)
+#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT)
+#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT)
+#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT)
+#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT)
+#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT)
+
+#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution)
+
+#endif /* GL_EXT_convolution */
+
+/* ------------------------ GL_EXT_coordinate_frame ------------------------ */
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+
+typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer);
+
+#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT)
+#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT)
+
+#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame)
+
+#endif /* GL_EXT_coordinate_frame */
+
+/* -------------------------- GL_EXT_copy_texture -------------------------- */
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT)
+#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT)
+#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT)
+#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT)
+#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT)
+
+#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture)
+
+#endif /* GL_EXT_copy_texture */
+
+/* --------------------------- GL_EXT_cull_vertex -------------------------- */
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+
+typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params);
+
+#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT)
+#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT)
+
+#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex)
+
+#endif /* GL_EXT_cull_vertex */
+
+/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+
+typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+
+#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT)
+
+#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test)
+
+#endif /* GL_EXT_depth_bounds_test */
+
+/* ----------------------- GL_EXT_direct_state_access ---------------------- */
+
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+
+#define GL_PROGRAM_MATRIX_EXT 0x8E2D
+#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
+#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
+
+typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);
+typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);
+typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img);
+typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels);
+typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access);
+typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m);
+typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f);
+typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode);
+typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode);
+typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param);
+typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage);
+typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data);
+typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string);
+typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param);
+typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+
+#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT)
+#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT)
+#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT)
+#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT)
+#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT)
+#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT)
+#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT)
+#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT)
+#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT)
+#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT)
+#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT)
+#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT)
+#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT)
+#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT)
+#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT)
+#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT)
+#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT)
+#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT)
+#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT)
+#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT)
+#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT)
+#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT)
+#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT)
+#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT)
+#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT)
+#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT)
+#define glDisableClientStateiEXT GLEW_GET_FUN(__glewDisableClientStateiEXT)
+#define glDisableVertexArrayAttribEXT GLEW_GET_FUN(__glewDisableVertexArrayAttribEXT)
+#define glDisableVertexArrayEXT GLEW_GET_FUN(__glewDisableVertexArrayEXT)
+#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT)
+#define glEnableClientStateiEXT GLEW_GET_FUN(__glewEnableClientStateiEXT)
+#define glEnableVertexArrayAttribEXT GLEW_GET_FUN(__glewEnableVertexArrayAttribEXT)
+#define glEnableVertexArrayEXT GLEW_GET_FUN(__glewEnableVertexArrayEXT)
+#define glFlushMappedNamedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedNamedBufferRangeEXT)
+#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT)
+#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT)
+#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT)
+#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT)
+#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT)
+#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT)
+#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT)
+#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT)
+#define glGetDoublei_vEXT GLEW_GET_FUN(__glewGetDoublei_vEXT)
+#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT)
+#define glGetFloati_vEXT GLEW_GET_FUN(__glewGetFloati_vEXT)
+#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT)
+#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT)
+#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT)
+#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT)
+#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT)
+#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT)
+#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT)
+#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT)
+#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT)
+#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT)
+#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT)
+#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT)
+#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT)
+#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT)
+#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT)
+#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT)
+#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT)
+#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT)
+#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT)
+#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT)
+#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT)
+#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT)
+#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT)
+#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT)
+#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT)
+#define glGetPointeri_vEXT GLEW_GET_FUN(__glewGetPointeri_vEXT)
+#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT)
+#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT)
+#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT)
+#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT)
+#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT)
+#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT)
+#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT)
+#define glGetVertexArrayIntegeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayIntegeri_vEXT)
+#define glGetVertexArrayIntegervEXT GLEW_GET_FUN(__glewGetVertexArrayIntegervEXT)
+#define glGetVertexArrayPointeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayPointeri_vEXT)
+#define glGetVertexArrayPointervEXT GLEW_GET_FUN(__glewGetVertexArrayPointervEXT)
+#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT)
+#define glMapNamedBufferRangeEXT GLEW_GET_FUN(__glewMapNamedBufferRangeEXT)
+#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT)
+#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT)
+#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT)
+#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT)
+#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT)
+#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT)
+#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT)
+#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT)
+#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT)
+#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT)
+#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT)
+#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT)
+#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT)
+#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT)
+#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT)
+#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT)
+#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT)
+#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT)
+#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT)
+#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT)
+#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT)
+#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT)
+#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT)
+#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT)
+#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT)
+#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT)
+#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT)
+#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT)
+#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT)
+#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT)
+#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT)
+#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT)
+#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT)
+#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT)
+#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT)
+#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT)
+#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT)
+#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT)
+#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT)
+#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT)
+#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT)
+#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT)
+#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT)
+#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT)
+#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT)
+#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT)
+#define glNamedCopyBufferSubDataEXT GLEW_GET_FUN(__glewNamedCopyBufferSubDataEXT)
+#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT)
+#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT)
+#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT)
+#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT)
+#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT)
+#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT)
+#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT)
+#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT)
+#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT)
+#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT)
+#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT)
+#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT)
+#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT)
+#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT)
+#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT)
+#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT)
+#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT)
+#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT)
+#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT)
+#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT)
+#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT)
+#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT)
+#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT)
+#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT)
+#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT)
+#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT)
+#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT)
+#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT)
+#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT)
+#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT)
+#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT)
+#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT)
+#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT)
+#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT)
+#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT)
+#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT)
+#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT)
+#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT)
+#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT)
+#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT)
+#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT)
+#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT)
+#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT)
+#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT)
+#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT)
+#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT)
+#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT)
+#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT)
+#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT)
+#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT)
+#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT)
+#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT)
+#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT)
+#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT)
+#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT)
+#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT)
+#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT)
+#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT)
+#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT)
+#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT)
+#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT)
+#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT)
+#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT)
+#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT)
+#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT)
+#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT)
+#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT)
+#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT)
+#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT)
+#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT)
+#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT)
+#define glVertexArrayColorOffsetEXT GLEW_GET_FUN(__glewVertexArrayColorOffsetEXT)
+#define glVertexArrayEdgeFlagOffsetEXT GLEW_GET_FUN(__glewVertexArrayEdgeFlagOffsetEXT)
+#define glVertexArrayFogCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayFogCoordOffsetEXT)
+#define glVertexArrayIndexOffsetEXT GLEW_GET_FUN(__glewVertexArrayIndexOffsetEXT)
+#define glVertexArrayMultiTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayMultiTexCoordOffsetEXT)
+#define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT)
+#define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT)
+#define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT)
+#define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT)
+#define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT)
+#define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT)
+
+#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access)
+
+#endif /* GL_EXT_direct_state_access */
+
+/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */
+
+#ifndef GL_EXT_draw_buffers2
+#define GL_EXT_draw_buffers2 1
+
+typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data);
+typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);
+
+#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT)
+#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT)
+#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT)
+#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT)
+#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT)
+#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT)
+
+#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2)
+
+#endif /* GL_EXT_draw_buffers2 */
+
+/* ------------------------- GL_EXT_draw_instanced ------------------------- */
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+
+#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT)
+#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT)
+
+#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced)
+
+#endif /* GL_EXT_draw_instanced */
+
+/* ----------------------- GL_EXT_draw_range_elements ---------------------- */
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+
+typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+
+#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT)
+
+#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements)
+
+#endif /* GL_EXT_draw_range_elements */
+
+/* ---------------------------- GL_EXT_fog_coord --------------------------- */
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+
+#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT)
+#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT)
+#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT)
+#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT)
+#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT)
+
+#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord)
+
+#endif /* GL_EXT_fog_coord */
+
+/* ------------------------ GL_EXT_fragment_lighting ----------------------- */
+
+#ifndef GL_EXT_fragment_lighting
+#define GL_EXT_fragment_lighting 1
+
+#define GL_FRAGMENT_LIGHTING_EXT 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405
+#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406
+#define GL_LIGHT_ENV_MODE_EXT 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B
+#define GL_FRAGMENT_LIGHT0_EXT 0x840C
+#define GL_FRAGMENT_LIGHT7_EXT 0x8413
+
+typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param);
+
+#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT)
+#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT)
+#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT)
+#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT)
+#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT)
+#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT)
+#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT)
+#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT)
+#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT)
+#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT)
+#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT)
+#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT)
+#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT)
+#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT)
+#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT)
+#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT)
+#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT)
+#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT)
+
+#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting)
+
+#endif /* GL_EXT_fragment_lighting */
+
+/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+
+typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT)
+
+#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit)
+
+#endif /* GL_EXT_framebuffer_blit */
+
+/* --------------------- GL_EXT_framebuffer_multisample -------------------- */
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT)
+
+#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample)
+
+#endif /* GL_EXT_framebuffer_multisample */
+
+/* --------------- GL_EXT_framebuffer_multisample_blit_scaled -------------- */
+
+#ifndef GL_EXT_framebuffer_multisample_blit_scaled
+#define GL_EXT_framebuffer_multisample_blit_scaled 1
+
+#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
+#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB
+
+#define GLEW_EXT_framebuffer_multisample_blit_scaled GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample_blit_scaled)
+
+#endif /* GL_EXT_framebuffer_multisample_blit_scaled */
+
+/* ----------------------- GL_EXT_framebuffer_object ----------------------- */
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT)
+#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT)
+#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT)
+#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT)
+#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT)
+#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT)
+#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT)
+#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT)
+#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT)
+#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT)
+#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT)
+#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT)
+#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT)
+#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT)
+#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT)
+#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT)
+#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT)
+
+#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object)
+
+#endif /* GL_EXT_framebuffer_object */
+
+/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */
+
+#ifndef GL_EXT_framebuffer_sRGB
+#define GL_EXT_framebuffer_sRGB 1
+
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+
+#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB)
+
+#endif /* GL_EXT_framebuffer_sRGB */
+
+/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */
+
+#ifndef GL_EXT_geometry_shader4
+#define GL_EXT_geometry_shader4 1
+
+#define GL_LINES_ADJACENCY_EXT 0xA
+#define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+#define GL_TRIANGLES_ADJACENCY_EXT 0xC
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+#define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+
+#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT)
+#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT)
+#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT)
+
+#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4)
+
+#endif /* GL_EXT_geometry_shader4 */
+
+/* --------------------- GL_EXT_gpu_program_parameters --------------------- */
+
+#ifndef GL_EXT_gpu_program_parameters
+#define GL_EXT_gpu_program_parameters 1
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params);
+
+#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT)
+#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT)
+
+#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters)
+
+#endif /* GL_EXT_gpu_program_parameters */
+
+/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */
+
+#ifndef GL_EXT_gpu_shader4
+#define GL_EXT_gpu_shader4 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
+#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+
+typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+
+#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT)
+#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT)
+#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT)
+#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT)
+#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT)
+#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT)
+#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT)
+#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT)
+#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT)
+#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT)
+#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT)
+#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT)
+#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT)
+#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT)
+#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT)
+#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT)
+#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT)
+#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT)
+#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT)
+#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT)
+#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT)
+#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT)
+#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT)
+#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT)
+#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT)
+#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT)
+#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT)
+#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT)
+#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT)
+#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT)
+#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT)
+#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT)
+#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT)
+#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT)
+
+#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4)
+
+#endif /* GL_EXT_gpu_shader4 */
+
+/* ---------------------------- GL_EXT_histogram --------------------------- */
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target);
+
+#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT)
+#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT)
+#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT)
+#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT)
+#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT)
+#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT)
+#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT)
+#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT)
+#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT)
+#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT)
+
+#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram)
+
+#endif /* GL_EXT_histogram */
+
+/* ----------------------- GL_EXT_index_array_formats ---------------------- */
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+
+#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats)
+
+#endif /* GL_EXT_index_array_formats */
+
+/* --------------------------- GL_EXT_index_func --------------------------- */
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+
+typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref);
+
+#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT)
+
+#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func)
+
+#endif /* GL_EXT_index_func */
+
+/* ------------------------- GL_EXT_index_material ------------------------- */
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+
+typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+
+#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT)
+
+#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material)
+
+#endif /* GL_EXT_index_material */
+
+/* -------------------------- GL_EXT_index_texture ------------------------- */
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+
+#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture)
+
+#endif /* GL_EXT_index_texture */
+
+/* -------------------------- GL_EXT_light_texture ------------------------- */
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+
+typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+
+#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT)
+#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT)
+#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT)
+
+#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture)
+
+#endif /* GL_EXT_light_texture */
+
+/* ------------------------- GL_EXT_misc_attribute ------------------------- */
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+
+#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute)
+
+#endif /* GL_EXT_misc_attribute */
+
+/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
+typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount);
+
+#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT)
+#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT)
+
+#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays)
+
+#endif /* GL_EXT_multi_draw_arrays */
+
+/* --------------------------- GL_EXT_multisample -------------------------- */
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+
+#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT)
+#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT)
+
+#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample)
+
+#endif /* GL_EXT_multisample */
+
+/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */
+
+#ifndef GL_EXT_packed_depth_stencil
+#define GL_EXT_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+
+#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil)
+
+#endif /* GL_EXT_packed_depth_stencil */
+
+/* -------------------------- GL_EXT_packed_float -------------------------- */
+
+#ifndef GL_EXT_packed_float
+#define GL_EXT_packed_float 1
+
+#define GL_R11F_G11F_B10F_EXT 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+
+#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float)
+
+#endif /* GL_EXT_packed_float */
+
+/* -------------------------- GL_EXT_packed_pixels ------------------------- */
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+
+#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels)
+
+#endif /* GL_EXT_packed_pixels */
+
+/* ------------------------ GL_EXT_paletted_texture ------------------------ */
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8
+#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params);
+
+#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT)
+#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT)
+#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT)
+#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT)
+
+#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture)
+
+#endif /* GL_EXT_paletted_texture */
+
+/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+
+#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object)
+
+#endif /* GL_EXT_pixel_buffer_object */
+
+/* ------------------------- GL_EXT_pixel_transform ------------------------ */
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+
+typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT)
+#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT)
+#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT)
+#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT)
+#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT)
+#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT)
+
+#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform)
+
+#endif /* GL_EXT_pixel_transform */
+
+/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+
+#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table)
+
+#endif /* GL_EXT_pixel_transform_color_table */
+
+/* ------------------------ GL_EXT_point_parameters ------------------------ */
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat* params);
+
+#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT)
+#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT)
+
+#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters)
+
+#endif /* GL_EXT_point_parameters */
+
+/* ------------------------- GL_EXT_polygon_offset ------------------------- */
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+
+typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+
+#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT)
+
+#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset)
+
+#endif /* GL_EXT_polygon_offset */
+
+/* ------------------------ GL_EXT_provoking_vertex ------------------------ */
+
+#ifndef GL_EXT_provoking_vertex
+#define GL_EXT_provoking_vertex 1
+
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_PROVOKING_VERTEX_EXT 0x8E4F
+
+typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode);
+
+#define glProvokingVertexEXT GLEW_GET_FUN(__glewProvokingVertexEXT)
+
+#define GLEW_EXT_provoking_vertex GLEW_GET_VAR(__GLEW_EXT_provoking_vertex)
+
+#endif /* GL_EXT_provoking_vertex */
+
+/* ------------------------- GL_EXT_rescale_normal ------------------------- */
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+
+#define GL_RESCALE_NORMAL_EXT 0x803A
+
+#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal)
+
+#endif /* GL_EXT_rescale_normal */
+
+/* -------------------------- GL_EXT_scene_marker -------------------------- */
+
+#ifndef GL_EXT_scene_marker
+#define GL_EXT_scene_marker 1
+
+typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void);
+
+#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT)
+#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT)
+
+#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker)
+
+#endif /* GL_EXT_scene_marker */
+
+/* ------------------------- GL_EXT_secondary_color ------------------------ */
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+
+#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT)
+#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT)
+#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT)
+#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT)
+#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT)
+#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT)
+#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT)
+#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT)
+#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT)
+#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT)
+#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT)
+#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT)
+#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT)
+#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT)
+#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT)
+#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT)
+#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT)
+
+#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color)
+
+#endif /* GL_EXT_secondary_color */
+
+/* --------------------- GL_EXT_separate_shader_objects -------------------- */
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+
+#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
+
+typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
+typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string);
+typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
+
+#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT)
+#define glCreateShaderProgramEXT GLEW_GET_FUN(__glewCreateShaderProgramEXT)
+#define glUseShaderProgramEXT GLEW_GET_FUN(__glewUseShaderProgramEXT)
+
+#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects)
+
+#endif /* GL_EXT_separate_shader_objects */
+
+/* --------------------- GL_EXT_separate_specular_color -------------------- */
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+
+#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color)
+
+#endif /* GL_EXT_separate_specular_color */
+
+/* --------------------- GL_EXT_shader_image_load_store -------------------- */
+
+#ifndef GL_EXT_shader_image_load_store
+#define GL_EXT_shader_image_load_store 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define GL_IMAGE_1D_EXT 0x904C
+#define GL_IMAGE_2D_EXT 0x904D
+#define GL_IMAGE_3D_EXT 0x904E
+#define GL_IMAGE_2D_RECT_EXT 0x904F
+#define GL_IMAGE_CUBE_EXT 0x9050
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define GL_INT_IMAGE_1D_EXT 0x9057
+#define GL_INT_IMAGE_2D_EXT 0x9058
+#define GL_INT_IMAGE_3D_EXT 0x9059
+#define GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define GL_INT_IMAGE_CUBE_EXT 0x905B
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+
+typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers);
+
+#define glBindImageTextureEXT GLEW_GET_FUN(__glewBindImageTextureEXT)
+#define glMemoryBarrierEXT GLEW_GET_FUN(__glewMemoryBarrierEXT)
+
+#define GLEW_EXT_shader_image_load_store GLEW_GET_VAR(__GLEW_EXT_shader_image_load_store)
+
+#endif /* GL_EXT_shader_image_load_store */
+
+/* -------------------------- GL_EXT_shadow_funcs -------------------------- */
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+
+#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs)
+
+#endif /* GL_EXT_shadow_funcs */
+
+/* --------------------- GL_EXT_shared_texture_palette --------------------- */
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+
+#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette)
+
+#endif /* GL_EXT_shared_texture_palette */
+
+/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */
+
+#ifndef GL_EXT_stencil_clear_tag
+#define GL_EXT_stencil_clear_tag 1
+
+#define GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+
+#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag)
+
+#endif /* GL_EXT_stencil_clear_tag */
+
+/* ------------------------ GL_EXT_stencil_two_side ------------------------ */
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+
+typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+
+#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT)
+
+#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side)
+
+#endif /* GL_EXT_stencil_two_side */
+
+/* -------------------------- GL_EXT_stencil_wrap -------------------------- */
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+
+#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap)
+
+#endif /* GL_EXT_stencil_wrap */
+
+/* --------------------------- GL_EXT_subtexture --------------------------- */
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+
+#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT)
+#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT)
+#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT)
+
+#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture)
+
+#endif /* GL_EXT_subtexture */
+
+/* ----------------------------- GL_EXT_texture ---------------------------- */
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+
+#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture)
+
+#endif /* GL_EXT_texture */
+
+/* ---------------------------- GL_EXT_texture3D --------------------------- */
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+
+#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT)
+
+#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D)
+
+#endif /* GL_EXT_texture3D */
+
+/* -------------------------- GL_EXT_texture_array ------------------------- */
+
+#ifndef GL_EXT_texture_array
+#define GL_EXT_texture_array 1
+
+#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+
+typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+
+#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT)
+
+#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array)
+
+#endif /* GL_EXT_texture_array */
+
+/* ---------------------- GL_EXT_texture_buffer_object --------------------- */
+
+#ifndef GL_EXT_texture_buffer_object
+#define GL_EXT_texture_buffer_object 1
+
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+
+typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+
+#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT)
+
+#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object)
+
+#endif /* GL_EXT_texture_buffer_object */
+
+/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */
+
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+
+#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1)
+
+#endif /* GL_EXT_texture_compression_dxt1 */
+
+/* -------------------- GL_EXT_texture_compression_latc -------------------- */
+
+#ifndef GL_EXT_texture_compression_latc
+#define GL_EXT_texture_compression_latc 1
+
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+
+#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc)
+
+#endif /* GL_EXT_texture_compression_latc */
+
+/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */
+
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_EXT_texture_compression_rgtc 1
+
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+
+#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc)
+
+#endif /* GL_EXT_texture_compression_rgtc */
+
+/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc)
+
+#endif /* GL_EXT_texture_compression_s3tc */
+
+/* ------------------------ GL_EXT_texture_cube_map ------------------------ */
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_EXT_texture_cube_map 1
+
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+
+#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map)
+
+#endif /* GL_EXT_texture_cube_map */
+
+/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */
+
+#ifndef GL_EXT_texture_edge_clamp
+#define GL_EXT_texture_edge_clamp 1
+
+#define GL_CLAMP_TO_EDGE_EXT 0x812F
+
+#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp)
+
+#endif /* GL_EXT_texture_edge_clamp */
+
+/* --------------------------- GL_EXT_texture_env -------------------------- */
+
+#ifndef GL_EXT_texture_env
+#define GL_EXT_texture_env 1
+
+#define GL_TEXTURE_ENV0_EXT 0
+#define GL_ENV_BLEND_EXT 0
+#define GL_TEXTURE_ENV_SHIFT_EXT 0
+#define GL_ENV_REPLACE_EXT 0
+#define GL_ENV_ADD_EXT 0
+#define GL_ENV_SUBTRACT_EXT 0
+#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0
+#define GL_ENV_REVERSE_SUBTRACT_EXT 0
+#define GL_ENV_REVERSE_BLEND_EXT 0
+#define GL_ENV_COPY_EXT 0
+#define GL_ENV_MODULATE_EXT 0
+
+#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env)
+
+#endif /* GL_EXT_texture_env */
+
+/* ------------------------- GL_EXT_texture_env_add ------------------------ */
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+
+#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add)
+
+#endif /* GL_EXT_texture_env_add */
+
+/* ----------------------- GL_EXT_texture_env_combine ---------------------- */
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+
+#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine)
+
+#endif /* GL_EXT_texture_env_combine */
+
+/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+
+#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3)
+
+#endif /* GL_EXT_texture_env_dot3 */
+
+/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+
+#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic)
+
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+/* ------------------------- GL_EXT_texture_integer ------------------------ */
+
+#ifndef GL_EXT_texture_integer
+#define GL_EXT_texture_integer 1
+
+#define GL_RGBA32UI_EXT 0x8D70
+#define GL_RGB32UI_EXT 0x8D71
+#define GL_ALPHA32UI_EXT 0x8D72
+#define GL_INTENSITY32UI_EXT 0x8D73
+#define GL_LUMINANCE32UI_EXT 0x8D74
+#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define GL_RGBA16UI_EXT 0x8D76
+#define GL_RGB16UI_EXT 0x8D77
+#define GL_ALPHA16UI_EXT 0x8D78
+#define GL_INTENSITY16UI_EXT 0x8D79
+#define GL_LUMINANCE16UI_EXT 0x8D7A
+#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define GL_RGBA8UI_EXT 0x8D7C
+#define GL_RGB8UI_EXT 0x8D7D
+#define GL_ALPHA8UI_EXT 0x8D7E
+#define GL_INTENSITY8UI_EXT 0x8D7F
+#define GL_LUMINANCE8UI_EXT 0x8D80
+#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define GL_RGBA32I_EXT 0x8D82
+#define GL_RGB32I_EXT 0x8D83
+#define GL_ALPHA32I_EXT 0x8D84
+#define GL_INTENSITY32I_EXT 0x8D85
+#define GL_LUMINANCE32I_EXT 0x8D86
+#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define GL_RGBA16I_EXT 0x8D88
+#define GL_RGB16I_EXT 0x8D89
+#define GL_ALPHA16I_EXT 0x8D8A
+#define GL_INTENSITY16I_EXT 0x8D8B
+#define GL_LUMINANCE16I_EXT 0x8D8C
+#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define GL_RGBA8I_EXT 0x8D8E
+#define GL_RGB8I_EXT 0x8D8F
+#define GL_ALPHA8I_EXT 0x8D90
+#define GL_INTENSITY8I_EXT 0x8D91
+#define GL_LUMINANCE8I_EXT 0x8D92
+#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define GL_RED_INTEGER_EXT 0x8D94
+#define GL_GREEN_INTEGER_EXT 0x8D95
+#define GL_BLUE_INTEGER_EXT 0x8D96
+#define GL_ALPHA_INTEGER_EXT 0x8D97
+#define GL_RGB_INTEGER_EXT 0x8D98
+#define GL_RGBA_INTEGER_EXT 0x8D99
+#define GL_BGR_INTEGER_EXT 0x8D9A
+#define GL_BGRA_INTEGER_EXT 0x8D9B
+#define GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+
+#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT)
+#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT)
+#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT)
+#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT)
+#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT)
+#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT)
+
+#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer)
+
+#endif /* GL_EXT_texture_integer */
+
+/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+
+#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias)
+
+#endif /* GL_EXT_texture_lod_bias */
+
+/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+
+#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp)
+
+#endif /* GL_EXT_texture_mirror_clamp */
+
+/* ------------------------- GL_EXT_texture_object ------------------------- */
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+
+typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences);
+typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures);
+typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures);
+typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities);
+
+#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT)
+#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT)
+#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT)
+#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT)
+#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT)
+#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT)
+
+#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object)
+
+#endif /* GL_EXT_texture_object */
+
+/* --------------------- GL_EXT_texture_perturb_normal --------------------- */
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+
+typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+
+#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT)
+
+#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal)
+
+#endif /* GL_EXT_texture_perturb_normal */
+
+/* ------------------------ GL_EXT_texture_rectangle ----------------------- */
+
+#ifndef GL_EXT_texture_rectangle
+#define GL_EXT_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8
+
+#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle)
+
+#endif /* GL_EXT_texture_rectangle */
+
+/* -------------------------- GL_EXT_texture_sRGB -------------------------- */
+
+#ifndef GL_EXT_texture_sRGB
+#define GL_EXT_texture_sRGB 1
+
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB8_EXT 0x8C41
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define GL_SLUMINANCE_EXT 0x8C46
+#define GL_SLUMINANCE8_EXT 0x8C47
+#define GL_COMPRESSED_SRGB_EXT 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+
+#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB)
+
+#endif /* GL_EXT_texture_sRGB */
+
+/* ----------------------- GL_EXT_texture_sRGB_decode ---------------------- */
+
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+
+#define GLEW_EXT_texture_sRGB_decode GLEW_GET_VAR(__GLEW_EXT_texture_sRGB_decode)
+
+#endif /* GL_EXT_texture_sRGB_decode */
+
+/* --------------------- GL_EXT_texture_shared_exponent -------------------- */
+
+#ifndef GL_EXT_texture_shared_exponent
+#define GL_EXT_texture_shared_exponent 1
+
+#define GL_RGB9_E5_EXT 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+
+#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent)
+
+#endif /* GL_EXT_texture_shared_exponent */
+
+/* -------------------------- GL_EXT_texture_snorm ------------------------- */
+
+#ifndef GL_EXT_texture_snorm
+#define GL_EXT_texture_snorm 1
+
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_ALPHA_SNORM 0x9010
+#define GL_LUMINANCE_SNORM 0x9011
+#define GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define GL_INTENSITY_SNORM 0x9013
+#define GL_ALPHA8_SNORM 0x9014
+#define GL_LUMINANCE8_SNORM 0x9015
+#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define GL_INTENSITY8_SNORM 0x9017
+#define GL_ALPHA16_SNORM 0x9018
+#define GL_LUMINANCE16_SNORM 0x9019
+#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define GL_INTENSITY16_SNORM 0x901B
+
+#define GLEW_EXT_texture_snorm GLEW_GET_VAR(__GLEW_EXT_texture_snorm)
+
+#endif /* GL_EXT_texture_snorm */
+
+/* ------------------------- GL_EXT_texture_swizzle ------------------------ */
+
+#ifndef GL_EXT_texture_swizzle
+#define GL_EXT_texture_swizzle 1
+
+#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+
+#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle)
+
+#endif /* GL_EXT_texture_swizzle */
+
+/* --------------------------- GL_EXT_timer_query -------------------------- */
+
+#ifndef GL_EXT_timer_query
+#define GL_EXT_timer_query 1
+
+#define GL_TIME_ELAPSED_EXT 0x88BF
+
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params);
+typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params);
+
+#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT)
+#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT)
+
+#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query)
+
+#endif /* GL_EXT_timer_query */
+
+/* ----------------------- GL_EXT_transform_feedback ----------------------- */
+
+#ifndef GL_EXT_transform_feedback
+#define GL_EXT_transform_feedback 1
+
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+
+typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode);
+
+#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT)
+#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT)
+#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT)
+#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT)
+#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT)
+#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT)
+#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT)
+
+#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback)
+
+#endif /* GL_EXT_transform_feedback */
+
+/* -------------------------- GL_EXT_vertex_array -------------------------- */
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+
+#define GL_DOUBLE_EXT 0x140A
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+
+typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer);
+
+#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT)
+#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT)
+#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT)
+#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT)
+#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT)
+#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT)
+#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT)
+#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT)
+
+#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array)
+
+#endif /* GL_EXT_vertex_array */
+
+/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */
+
+#ifndef GL_EXT_vertex_array_bgra
+#define GL_EXT_vertex_array_bgra 1
+
+#define GL_BGRA 0x80E1
+
+#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra)
+
+#endif /* GL_EXT_vertex_array_bgra */
+
+/* ----------------------- GL_EXT_vertex_attrib_64bit ---------------------- */
+
+#ifndef GL_EXT_vertex_attrib_64bit
+#define GL_EXT_vertex_attrib_64bit 1
+
+#define GL_DOUBLE_MAT2_EXT 0x8F46
+#define GL_DOUBLE_MAT3_EXT 0x8F47
+#define GL_DOUBLE_MAT4_EXT 0x8F48
+#define GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define GL_DOUBLE_MAT4x3_EXT 0x8F4E
+#define GL_DOUBLE_VEC2_EXT 0x8FFC
+#define GL_DOUBLE_VEC3_EXT 0x8FFD
+#define GL_DOUBLE_VEC4_EXT 0x8FFE
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+
+#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT)
+#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT)
+#define glVertexAttribL1dEXT GLEW_GET_FUN(__glewVertexAttribL1dEXT)
+#define glVertexAttribL1dvEXT GLEW_GET_FUN(__glewVertexAttribL1dvEXT)
+#define glVertexAttribL2dEXT GLEW_GET_FUN(__glewVertexAttribL2dEXT)
+#define glVertexAttribL2dvEXT GLEW_GET_FUN(__glewVertexAttribL2dvEXT)
+#define glVertexAttribL3dEXT GLEW_GET_FUN(__glewVertexAttribL3dEXT)
+#define glVertexAttribL3dvEXT GLEW_GET_FUN(__glewVertexAttribL3dvEXT)
+#define glVertexAttribL4dEXT GLEW_GET_FUN(__glewVertexAttribL4dEXT)
+#define glVertexAttribL4dvEXT GLEW_GET_FUN(__glewVertexAttribL4dvEXT)
+#define glVertexAttribLPointerEXT GLEW_GET_FUN(__glewVertexAttribLPointerEXT)
+
+#define GLEW_EXT_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_EXT_vertex_attrib_64bit)
+
+#endif /* GL_EXT_vertex_attrib_64bit */
+
+/* -------------------------- GL_EXT_vertex_shader ------------------------- */
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+
+typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components);
+typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data);
+typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr);
+typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr);
+typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+
+#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT)
+#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT)
+#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT)
+#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT)
+#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT)
+#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT)
+#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT)
+#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT)
+#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT)
+#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT)
+#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT)
+#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT)
+#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT)
+#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT)
+#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT)
+#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT)
+#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT)
+#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT)
+#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT)
+#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT)
+#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT)
+#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT)
+#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT)
+#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT)
+#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT)
+#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT)
+#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT)
+#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT)
+#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT)
+#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT)
+#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT)
+#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT)
+#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT)
+#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT)
+#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT)
+#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT)
+#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT)
+#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT)
+#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT)
+#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT)
+#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT)
+#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT)
+
+#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader)
+
+#endif /* GL_EXT_vertex_shader */
+
+/* ------------------------ GL_EXT_vertex_weighting ------------------------ */
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+
+#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define GL_MODELVIEW0_EXT 0x1700
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight);
+
+#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT)
+#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT)
+#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT)
+
+#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting)
+
+#endif /* GL_EXT_vertex_weighting */
+
+/* ------------------------- GL_EXT_x11_sync_object ------------------------ */
+
+#ifndef GL_EXT_x11_sync_object
+#define GL_EXT_x11_sync_object 1
+
+#define GL_SYNC_X11_FENCE_EXT 0x90E1
+
+typedef GLsync (GLAPIENTRY * PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+
+#define glImportSyncEXT GLEW_GET_FUN(__glewImportSyncEXT)
+
+#define GLEW_EXT_x11_sync_object GLEW_GET_VAR(__GLEW_EXT_x11_sync_object)
+
+#endif /* GL_EXT_x11_sync_object */
+
+/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */
+
+#ifndef GL_GREMEDY_frame_terminator
+#define GL_GREMEDY_frame_terminator 1
+
+typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void);
+
+#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY)
+
+#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator)
+
+#endif /* GL_GREMEDY_frame_terminator */
+
+/* ------------------------ GL_GREMEDY_string_marker ----------------------- */
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+
+typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string);
+
+#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY)
+
+#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker)
+
+#endif /* GL_GREMEDY_string_marker */
+
+/* --------------------- GL_HP_convolution_border_modes -------------------- */
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+
+#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes)
+
+#endif /* GL_HP_convolution_border_modes */
+
+/* ------------------------- GL_HP_image_transform ------------------------- */
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+
+typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP)
+#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP)
+#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP)
+#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP)
+#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP)
+#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP)
+
+#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform)
+
+#endif /* GL_HP_image_transform */
+
+/* -------------------------- GL_HP_occlusion_test ------------------------- */
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+
+#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test)
+
+#endif /* GL_HP_occlusion_test */
+
+/* ------------------------- GL_HP_texture_lighting ------------------------ */
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+
+#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting)
+
+#endif /* GL_HP_texture_lighting */
+
+/* --------------------------- GL_IBM_cull_vertex -------------------------- */
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+
+#define GL_CULL_VERTEX_IBM 103050
+
+#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex)
+
+#endif /* GL_IBM_cull_vertex */
+
+/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+
+typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride);
+
+#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM)
+#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM)
+
+#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays)
+
+#endif /* GL_IBM_multimode_draw_arrays */
+
+/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010
+
+#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip)
+
+#endif /* GL_IBM_rasterpos_clip */
+
+/* --------------------------- GL_IBM_static_data -------------------------- */
+
+#ifndef GL_IBM_static_data
+#define GL_IBM_static_data 1
+
+#define GL_ALL_STATIC_DATA_IBM 103060
+#define GL_STATIC_VERTEX_ARRAY_IBM 103061
+
+#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data)
+
+#endif /* GL_IBM_static_data */
+
+/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_IBM_texture_mirrored_repeat 1
+
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+
+#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat)
+
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride);
+
+#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM)
+#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM)
+#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM)
+#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM)
+#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM)
+#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM)
+#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM)
+#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM)
+
+#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists)
+
+#endif /* GL_IBM_vertex_array_lists */
+
+/* -------------------------- GL_INGR_color_clamp -------------------------- */
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+
+#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp)
+
+#endif /* GL_INGR_color_clamp */
+
+/* ------------------------- GL_INGR_interlace_read ------------------------ */
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+
+#define GL_INTERLACE_READ_INGR 0x8568
+
+#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read)
+
+#endif /* GL_INGR_interlace_read */
+
+/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+
+typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer);
+
+#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL)
+#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL)
+#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL)
+#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL)
+
+#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays)
+
+#endif /* GL_INTEL_parallel_arrays */
+
+/* ------------------------ GL_INTEL_texture_scissor ----------------------- */
+
+#ifndef GL_INTEL_texture_scissor
+#define GL_INTEL_texture_scissor 1
+
+typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc);
+typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh);
+
+#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL)
+#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL)
+
+#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor)
+
+#endif /* GL_INTEL_texture_scissor */
+
+/* -------------------------- GL_KTX_buffer_region ------------------------- */
+
+#ifndef GL_KTX_buffer_region
+#define GL_KTX_buffer_region 1
+
+#define GL_KTX_FRONT_REGION 0x0
+#define GL_KTX_BACK_REGION 0x1
+#define GL_KTX_Z_REGION 0x2
+#define GL_KTX_STENCIL_REGION 0x3
+
+typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDPROC) (void);
+typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONPROC) (GLenum region);
+typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest);
+typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONPROC) (GLenum region);
+typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glBufferRegionEnabled GLEW_GET_FUN(__glewBufferRegionEnabled)
+#define glDeleteBufferRegion GLEW_GET_FUN(__glewDeleteBufferRegion)
+#define glDrawBufferRegion GLEW_GET_FUN(__glewDrawBufferRegion)
+#define glNewBufferRegion GLEW_GET_FUN(__glewNewBufferRegion)
+#define glReadBufferRegion GLEW_GET_FUN(__glewReadBufferRegion)
+
+#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region)
+
+#endif /* GL_KTX_buffer_region */
+
+/* ------------------------- GL_MESAX_texture_stack ------------------------ */
+
+#ifndef GL_MESAX_texture_stack
+#define GL_MESAX_texture_stack 1
+
+#define GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+
+#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack)
+
+#endif /* GL_MESAX_texture_stack */
+
+/* -------------------------- GL_MESA_pack_invert -------------------------- */
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+
+#define GL_PACK_INVERT_MESA 0x8758
+
+#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert)
+
+#endif /* GL_MESA_pack_invert */
+
+/* ------------------------- GL_MESA_resize_buffers ------------------------ */
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+
+typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void);
+
+#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA)
+
+#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers)
+
+#endif /* GL_MESA_resize_buffers */
+
+/* --------------------------- GL_MESA_window_pos -------------------------- */
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p);
+
+#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA)
+#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA)
+#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA)
+#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA)
+#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA)
+#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA)
+#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA)
+#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA)
+#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA)
+#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA)
+#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA)
+#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA)
+#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA)
+#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA)
+#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA)
+#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA)
+#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA)
+#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA)
+#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA)
+#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA)
+#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA)
+#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA)
+#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA)
+#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA)
+
+#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos)
+
+#endif /* GL_MESA_window_pos */
+
+/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+
+#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture)
+
+#endif /* GL_MESA_ycbcr_texture */
+
+/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */
+
+#ifndef GL_NVX_gpu_memory_info
+#define GL_NVX_gpu_memory_info 1
+
+#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+
+#define GLEW_NVX_gpu_memory_info GLEW_GET_VAR(__GLEW_NVX_gpu_memory_info)
+
+#endif /* GL_NVX_gpu_memory_info */
+
+/* --------------------------- GL_NV_blend_square -------------------------- */
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+
+#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square)
+
+#endif /* GL_NV_blend_square */
+
+/* ------------------------ GL_NV_conditional_render ----------------------- */
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+
+typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void);
+
+#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV)
+#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV)
+
+#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render)
+
+#endif /* GL_NV_conditional_render */
+
+/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+
+#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color)
+
+#endif /* GL_NV_copy_depth_to_color */
+
+/* ---------------------------- GL_NV_copy_image --------------------------- */
+
+#ifndef GL_NV_copy_image
+#define GL_NV_copy_image 1
+
+typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glCopyImageSubDataNV GLEW_GET_FUN(__glewCopyImageSubDataNV)
+
+#define GLEW_NV_copy_image GLEW_GET_VAR(__GLEW_NV_copy_image)
+
+#endif /* GL_NV_copy_image */
+
+/* ------------------------ GL_NV_depth_buffer_float ----------------------- */
+
+#ifndef GL_NV_depth_buffer_float
+#define GL_NV_depth_buffer_float 1
+
+#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);
+typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);
+
+#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV)
+#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV)
+#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV)
+
+#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float)
+
+#endif /* GL_NV_depth_buffer_float */
+
+/* --------------------------- GL_NV_depth_clamp --------------------------- */
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+
+#define GL_DEPTH_CLAMP_NV 0x864F
+
+#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp)
+
+#endif /* GL_NV_depth_clamp */
+
+/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */
+
+#ifndef GL_NV_depth_range_unclamped
+#define GL_NV_depth_range_unclamped 1
+
+#define GL_SAMPLE_COUNT_BITS_NV 0x8864
+#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865
+#define GL_QUERY_RESULT_NV 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867
+#define GL_SAMPLE_COUNT_NV 0x8914
+
+#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped)
+
+#endif /* GL_NV_depth_range_unclamped */
+
+/* ---------------------------- GL_NV_evaluators --------------------------- */
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+
+typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points);
+typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points);
+typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params);
+
+#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV)
+#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV)
+#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV)
+#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV)
+#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV)
+#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV)
+#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV)
+#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV)
+#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV)
+
+#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators)
+
+#endif /* GL_NV_evaluators */
+
+/* ----------------------- GL_NV_explicit_multisample ---------------------- */
+
+#ifndef GL_NV_explicit_multisample
+#define GL_NV_explicit_multisample 1
+
+#define GL_SAMPLE_POSITION_NV 0x8E50
+#define GL_SAMPLE_MASK_NV 0x8E51
+#define GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+
+typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val);
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);
+typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);
+
+#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV)
+#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV)
+#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV)
+
+#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample)
+
+#endif /* GL_NV_explicit_multisample */
+
+/* ------------------------------ GL_NV_fence ------------------------------ */
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
+typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences);
+typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence);
+typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence);
+
+#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV)
+#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV)
+#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV)
+#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV)
+#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV)
+#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV)
+#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV)
+
+#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence)
+
+#endif /* GL_NV_fence */
+
+/* --------------------------- GL_NV_float_buffer -------------------------- */
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+
+#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer)
+
+#endif /* GL_NV_float_buffer */
+
+/* --------------------------- GL_NV_fog_distance -------------------------- */
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+
+#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance)
+
+#endif /* GL_NV_fog_distance */
+
+/* ------------------------- GL_NV_fragment_program ------------------------ */
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]);
+
+#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV)
+#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV)
+#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV)
+#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV)
+#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV)
+#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV)
+
+#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program)
+
+#endif /* GL_NV_fragment_program */
+
+/* ------------------------ GL_NV_fragment_program2 ------------------------ */
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+
+#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2)
+
+#endif /* GL_NV_fragment_program2 */
+
+/* ------------------------ GL_NV_fragment_program4 ------------------------ */
+
+#ifndef GL_NV_fragment_program4
+#define GL_NV_fragment_program4 1
+
+#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4)
+
+#endif /* GL_NV_fragment_program4 */
+
+/* --------------------- GL_NV_fragment_program_option --------------------- */
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+
+#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option)
+
+#endif /* GL_NV_fragment_program_option */
+
+/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */
+
+#ifndef GL_NV_framebuffer_multisample_coverage
+#define GL_NV_framebuffer_multisample_coverage 1
+
+#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+
+typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+
+#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV)
+
+#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage)
+
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+/* ------------------------ GL_NV_geometry_program4 ------------------------ */
+
+#ifndef GL_NV_geometry_program4
+#define GL_NV_geometry_program4 1
+
+#define GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
+
+#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV)
+
+#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4)
+
+#endif /* GL_NV_geometry_program4 */
+
+/* ------------------------- GL_NV_geometry_shader4 ------------------------ */
+
+#ifndef GL_NV_geometry_shader4
+#define GL_NV_geometry_shader4 1
+
+#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4)
+
+#endif /* GL_NV_geometry_shader4 */
+
+/* --------------------------- GL_NV_gpu_program4 -------------------------- */
+
+#ifndef GL_NV_gpu_program4
+#define GL_NV_gpu_program4 1
+
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+
+#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV)
+#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV)
+#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV)
+#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV)
+#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV)
+#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV)
+#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV)
+#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV)
+#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV)
+#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV)
+#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV)
+#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV)
+
+#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4)
+
+#endif /* GL_NV_gpu_program4 */
+
+/* --------------------------- GL_NV_gpu_program5 -------------------------- */
+
+#ifndef GL_NV_gpu_program5
+#define GL_NV_gpu_program5 1
+
+#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F
+
+#define GLEW_NV_gpu_program5 GLEW_GET_VAR(__GLEW_NV_gpu_program5)
+
+#endif /* GL_NV_gpu_program5 */
+
+/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */
+
+#ifndef GL_NV_gpu_program_fp64
+#define GL_NV_gpu_program_fp64 1
+
+#define GLEW_NV_gpu_program_fp64 GLEW_GET_VAR(__GLEW_NV_gpu_program_fp64)
+
+#endif /* GL_NV_gpu_program_fp64 */
+
+/* --------------------------- GL_NV_gpu_shader5 --------------------------- */
+
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+
+#define glGetUniformi64vNV GLEW_GET_FUN(__glewGetUniformi64vNV)
+#define glGetUniformui64vNV GLEW_GET_FUN(__glewGetUniformui64vNV)
+#define glProgramUniform1i64NV GLEW_GET_FUN(__glewProgramUniform1i64NV)
+#define glProgramUniform1i64vNV GLEW_GET_FUN(__glewProgramUniform1i64vNV)
+#define glProgramUniform1ui64NV GLEW_GET_FUN(__glewProgramUniform1ui64NV)
+#define glProgramUniform1ui64vNV GLEW_GET_FUN(__glewProgramUniform1ui64vNV)
+#define glProgramUniform2i64NV GLEW_GET_FUN(__glewProgramUniform2i64NV)
+#define glProgramUniform2i64vNV GLEW_GET_FUN(__glewProgramUniform2i64vNV)
+#define glProgramUniform2ui64NV GLEW_GET_FUN(__glewProgramUniform2ui64NV)
+#define glProgramUniform2ui64vNV GLEW_GET_FUN(__glewProgramUniform2ui64vNV)
+#define glProgramUniform3i64NV GLEW_GET_FUN(__glewProgramUniform3i64NV)
+#define glProgramUniform3i64vNV GLEW_GET_FUN(__glewProgramUniform3i64vNV)
+#define glProgramUniform3ui64NV GLEW_GET_FUN(__glewProgramUniform3ui64NV)
+#define glProgramUniform3ui64vNV GLEW_GET_FUN(__glewProgramUniform3ui64vNV)
+#define glProgramUniform4i64NV GLEW_GET_FUN(__glewProgramUniform4i64NV)
+#define glProgramUniform4i64vNV GLEW_GET_FUN(__glewProgramUniform4i64vNV)
+#define glProgramUniform4ui64NV GLEW_GET_FUN(__glewProgramUniform4ui64NV)
+#define glProgramUniform4ui64vNV GLEW_GET_FUN(__glewProgramUniform4ui64vNV)
+#define glUniform1i64NV GLEW_GET_FUN(__glewUniform1i64NV)
+#define glUniform1i64vNV GLEW_GET_FUN(__glewUniform1i64vNV)
+#define glUniform1ui64NV GLEW_GET_FUN(__glewUniform1ui64NV)
+#define glUniform1ui64vNV GLEW_GET_FUN(__glewUniform1ui64vNV)
+#define glUniform2i64NV GLEW_GET_FUN(__glewUniform2i64NV)
+#define glUniform2i64vNV GLEW_GET_FUN(__glewUniform2i64vNV)
+#define glUniform2ui64NV GLEW_GET_FUN(__glewUniform2ui64NV)
+#define glUniform2ui64vNV GLEW_GET_FUN(__glewUniform2ui64vNV)
+#define glUniform3i64NV GLEW_GET_FUN(__glewUniform3i64NV)
+#define glUniform3i64vNV GLEW_GET_FUN(__glewUniform3i64vNV)
+#define glUniform3ui64NV GLEW_GET_FUN(__glewUniform3ui64NV)
+#define glUniform3ui64vNV GLEW_GET_FUN(__glewUniform3ui64vNV)
+#define glUniform4i64NV GLEW_GET_FUN(__glewUniform4i64NV)
+#define glUniform4i64vNV GLEW_GET_FUN(__glewUniform4i64vNV)
+#define glUniform4ui64NV GLEW_GET_FUN(__glewUniform4ui64NV)
+#define glUniform4ui64vNV GLEW_GET_FUN(__glewUniform4ui64vNV)
+
+#define GLEW_NV_gpu_shader5 GLEW_GET_VAR(__GLEW_NV_gpu_shader5)
+
+#endif /* GL_NV_gpu_shader5 */
+
+/* ---------------------------- GL_NV_half_float --------------------------- */
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+
+#define GL_HALF_FLOAT_NV 0x140B
+
+typedef unsigned short GLhalf;
+
+typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue);
+typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha);
+typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz);
+typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y);
+typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z);
+typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight);
+typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight);
+
+#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV)
+#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV)
+#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV)
+#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV)
+#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV)
+#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV)
+#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV)
+#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV)
+#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV)
+#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV)
+#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV)
+#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV)
+#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV)
+#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV)
+#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV)
+#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV)
+#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV)
+#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV)
+#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV)
+#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV)
+#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV)
+#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV)
+#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV)
+#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV)
+#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV)
+#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV)
+#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV)
+#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV)
+#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV)
+#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV)
+#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV)
+#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV)
+#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV)
+#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV)
+#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV)
+#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV)
+#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV)
+#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV)
+#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV)
+#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV)
+#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV)
+#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV)
+#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV)
+#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV)
+#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV)
+#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV)
+
+#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float)
+
+#endif /* GL_NV_half_float */
+
+/* ------------------------ GL_NV_light_max_exponent ----------------------- */
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+
+#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent)
+
+#endif /* GL_NV_light_max_exponent */
+
+/* ----------------------- GL_NV_multisample_coverage ---------------------- */
+
+#ifndef GL_NV_multisample_coverage
+#define GL_NV_multisample_coverage 1
+
+#define GL_COVERAGE_SAMPLES_NV 0x80A9
+#define GL_COLOR_SAMPLES_NV 0x8E20
+
+#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage)
+
+#endif /* GL_NV_multisample_coverage */
+
+/* --------------------- GL_NV_multisample_filter_hint --------------------- */
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+
+#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint)
+
+#endif /* GL_NV_multisample_filter_hint */
+
+/* ------------------------- GL_NV_occlusion_query ------------------------- */
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+
+typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+
+#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV)
+#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV)
+#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV)
+#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV)
+#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV)
+#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV)
+#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV)
+
+#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query)
+
+#endif /* GL_NV_occlusion_query */
+
+/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+
+#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil)
+
+#endif /* GL_NV_packed_depth_stencil */
+
+/* --------------------- GL_NV_parameter_buffer_object --------------------- */
+
+#ifndef GL_NV_parameter_buffer_object
+#define GL_NV_parameter_buffer_object 1
+
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+
+typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params);
+
+#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV)
+#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV)
+#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV)
+
+#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object)
+
+#endif /* GL_NV_parameter_buffer_object */
+
+/* --------------------- GL_NV_parameter_buffer_object2 -------------------- */
+
+#ifndef GL_NV_parameter_buffer_object2
+#define GL_NV_parameter_buffer_object2 1
+
+#define GLEW_NV_parameter_buffer_object2 GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object2)
+
+#endif /* GL_NV_parameter_buffer_object2 */
+
+/* -------------------------- GL_NV_path_rendering ------------------------- */
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_BOLD_BIT_NV 0x01
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_MOVE_TO_NV 0x02
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_GLYPH_HAS_KERNING_NV 0x100
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_FONT_X_MIN_BOUNDS_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_NV 0x00100000
+#define GL_FONT_ASCENDER_NV 0x00200000
+#define GL_FONT_DESCENDER_NV 0x00400000
+#define GL_FONT_HEIGHT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_NV 0x08000000
+#define GL_FONT_HAS_KERNING_NV 0x10000000
+
+typedef void (GLAPIENTRY * PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GLAPIENTRY * PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLCOVERSTROKEPATHNVPROC) (GLuint name, GLenum coverMode);
+typedef void (GLAPIENTRY * PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLuint (GLAPIENTRY * PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOMMANDSNVPROC) (GLuint name, GLubyte* commands);
+typedef void (GLAPIENTRY * PFNGLGETPATHCOORDSNVPROC) (GLuint name, GLfloat* coords);
+typedef void (GLAPIENTRY * PFNGLGETPATHDASHARRAYNVPROC) (GLuint name, GLfloat* dashArray);
+typedef GLfloat (GLAPIENTRY * PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef void (GLAPIENTRY * PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint fistPathName, GLsizei numPaths, GLsizei stride, GLfloat* metrics);
+typedef void (GLAPIENTRY * PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (GLAPIENTRY * PFNGLGETPATHPARAMETERFVNVPROC) (GLuint name, GLenum param, GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHPARAMETERIVNVPROC) (GLuint name, GLenum param, GLint* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef void (GLAPIENTRY * PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint* value);
+typedef void (GLAPIENTRY * PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef GLboolean (GLAPIENTRY * PFNGLISPATHNVPROC) (GLuint path);
+typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat* coeffs);
+typedef void (GLAPIENTRY * PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords);
+typedef void (GLAPIENTRY * PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void* coords);
+typedef void (GLAPIENTRY * PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum zfunc);
+typedef void (GLAPIENTRY * PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat* dashArray);
+typedef void (GLAPIENTRY * PFNGLPATHFOGGENNVPROC) (GLenum genMode);
+typedef void (GLAPIENTRY * PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GLAPIENTRY * PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const GLvoid*charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat* value);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (GLAPIENTRY * PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint* value);
+typedef void (GLAPIENTRY * PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLint units);
+typedef void (GLAPIENTRY * PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void* pathString);
+typedef void (GLAPIENTRY * PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords);
+typedef void (GLAPIENTRY * PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void* coords);
+typedef void (GLAPIENTRY * PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat* coeffs);
+typedef GLboolean (GLAPIENTRY * PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat* x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (GLAPIENTRY * PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GLAPIENTRY * PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat* transformValues);
+typedef void (GLAPIENTRY * PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint paths[], const GLfloat weights[]);
+
+#define glCopyPathNV GLEW_GET_FUN(__glewCopyPathNV)
+#define glCoverFillPathInstancedNV GLEW_GET_FUN(__glewCoverFillPathInstancedNV)
+#define glCoverFillPathNV GLEW_GET_FUN(__glewCoverFillPathNV)
+#define glCoverStrokePathInstancedNV GLEW_GET_FUN(__glewCoverStrokePathInstancedNV)
+#define glCoverStrokePathNV GLEW_GET_FUN(__glewCoverStrokePathNV)
+#define glDeletePathsNV GLEW_GET_FUN(__glewDeletePathsNV)
+#define glGenPathsNV GLEW_GET_FUN(__glewGenPathsNV)
+#define glGetPathColorGenfvNV GLEW_GET_FUN(__glewGetPathColorGenfvNV)
+#define glGetPathColorGenivNV GLEW_GET_FUN(__glewGetPathColorGenivNV)
+#define glGetPathCommandsNV GLEW_GET_FUN(__glewGetPathCommandsNV)
+#define glGetPathCoordsNV GLEW_GET_FUN(__glewGetPathCoordsNV)
+#define glGetPathDashArrayNV GLEW_GET_FUN(__glewGetPathDashArrayNV)
+#define glGetPathLengthNV GLEW_GET_FUN(__glewGetPathLengthNV)
+#define glGetPathMetricRangeNV GLEW_GET_FUN(__glewGetPathMetricRangeNV)
+#define glGetPathMetricsNV GLEW_GET_FUN(__glewGetPathMetricsNV)
+#define glGetPathParameterfvNV GLEW_GET_FUN(__glewGetPathParameterfvNV)
+#define glGetPathParameterivNV GLEW_GET_FUN(__glewGetPathParameterivNV)
+#define glGetPathSpacingNV GLEW_GET_FUN(__glewGetPathSpacingNV)
+#define glGetPathTexGenfvNV GLEW_GET_FUN(__glewGetPathTexGenfvNV)
+#define glGetPathTexGenivNV GLEW_GET_FUN(__glewGetPathTexGenivNV)
+#define glInterpolatePathsNV GLEW_GET_FUN(__glewInterpolatePathsNV)
+#define glIsPathNV GLEW_GET_FUN(__glewIsPathNV)
+#define glIsPointInFillPathNV GLEW_GET_FUN(__glewIsPointInFillPathNV)
+#define glIsPointInStrokePathNV GLEW_GET_FUN(__glewIsPointInStrokePathNV)
+#define glPathColorGenNV GLEW_GET_FUN(__glewPathColorGenNV)
+#define glPathCommandsNV GLEW_GET_FUN(__glewPathCommandsNV)
+#define glPathCoordsNV GLEW_GET_FUN(__glewPathCoordsNV)
+#define glPathCoverDepthFuncNV GLEW_GET_FUN(__glewPathCoverDepthFuncNV)
+#define glPathDashArrayNV GLEW_GET_FUN(__glewPathDashArrayNV)
+#define glPathFogGenNV GLEW_GET_FUN(__glewPathFogGenNV)
+#define glPathGlyphRangeNV GLEW_GET_FUN(__glewPathGlyphRangeNV)
+#define glPathGlyphsNV GLEW_GET_FUN(__glewPathGlyphsNV)
+#define glPathParameterfNV GLEW_GET_FUN(__glewPathParameterfNV)
+#define glPathParameterfvNV GLEW_GET_FUN(__glewPathParameterfvNV)
+#define glPathParameteriNV GLEW_GET_FUN(__glewPathParameteriNV)
+#define glPathParameterivNV GLEW_GET_FUN(__glewPathParameterivNV)
+#define glPathStencilDepthOffsetNV GLEW_GET_FUN(__glewPathStencilDepthOffsetNV)
+#define glPathStencilFuncNV GLEW_GET_FUN(__glewPathStencilFuncNV)
+#define glPathStringNV GLEW_GET_FUN(__glewPathStringNV)
+#define glPathSubCommandsNV GLEW_GET_FUN(__glewPathSubCommandsNV)
+#define glPathSubCoordsNV GLEW_GET_FUN(__glewPathSubCoordsNV)
+#define glPathTexGenNV GLEW_GET_FUN(__glewPathTexGenNV)
+#define glPointAlongPathNV GLEW_GET_FUN(__glewPointAlongPathNV)
+#define glStencilFillPathInstancedNV GLEW_GET_FUN(__glewStencilFillPathInstancedNV)
+#define glStencilFillPathNV GLEW_GET_FUN(__glewStencilFillPathNV)
+#define glStencilStrokePathInstancedNV GLEW_GET_FUN(__glewStencilStrokePathInstancedNV)
+#define glStencilStrokePathNV GLEW_GET_FUN(__glewStencilStrokePathNV)
+#define glTransformPathNV GLEW_GET_FUN(__glewTransformPathNV)
+#define glWeightPathsNV GLEW_GET_FUN(__glewWeightPathsNV)
+
+#define GLEW_NV_path_rendering GLEW_GET_VAR(__GLEW_NV_path_rendering)
+
+#endif /* GL_NV_path_rendering */
+
+/* ------------------------- GL_NV_pixel_data_range ------------------------ */
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+
+typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer);
+
+#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV)
+#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV)
+
+#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range)
+
+#endif /* GL_NV_pixel_data_range */
+
+/* --------------------------- GL_NV_point_sprite -------------------------- */
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params);
+
+#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV)
+#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV)
+
+#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite)
+
+#endif /* GL_NV_point_sprite */
+
+/* -------------------------- GL_NV_present_video -------------------------- */
+
+#ifndef GL_NV_present_video
+#define GL_NV_present_video 1
+
+#define GL_FRAME_NV 0x8E26
+#define GL_FIELDS_NV 0x8E27
+#define GL_CURRENT_TIME_NV 0x8E28
+#define GL_NUM_FILL_STREAMS_NV 0x8E29
+#define GL_PRESENT_TIME_NV 0x8E2A
+#define GL_PRESENT_DURATION_NV 0x8E2B
+
+typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params);
+typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+
+#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV)
+#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV)
+#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV)
+#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV)
+#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV)
+#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV)
+
+#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video)
+
+#endif /* GL_NV_present_video */
+
+/* ------------------------ GL_NV_primitive_restart ------------------------ */
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void);
+
+#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV)
+#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV)
+
+#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart)
+
+#endif /* GL_NV_primitive_restart */
+
+/* ------------------------ GL_NV_register_combiners ----------------------- */
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+
+typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params);
+
+#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV)
+#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV)
+#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV)
+#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV)
+#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV)
+#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV)
+#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV)
+#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV)
+#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV)
+#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV)
+#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV)
+#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV)
+#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV)
+
+#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners)
+
+#endif /* GL_NV_register_combiners */
+
+/* ----------------------- GL_NV_register_combiners2 ----------------------- */
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+
+typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params);
+
+#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV)
+#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV)
+
+#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2)
+
+#endif /* GL_NV_register_combiners2 */
+
+/* ------------------------ GL_NV_shader_buffer_load ----------------------- */
+
+#ifndef GL_NV_shader_buffer_load
+#define GL_NV_shader_buffer_load 1
+
+#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define GL_GPU_ADDRESS_NV 0x8F34
+#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+
+typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT* result);
+typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERRESIDENTNVPROC) (GLenum target);
+typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target);
+typedef void (GLAPIENTRY * PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access);
+typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value);
+typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value);
+typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value);
+
+#define glGetBufferParameterui64vNV GLEW_GET_FUN(__glewGetBufferParameterui64vNV)
+#define glGetIntegerui64vNV GLEW_GET_FUN(__glewGetIntegerui64vNV)
+#define glGetNamedBufferParameterui64vNV GLEW_GET_FUN(__glewGetNamedBufferParameterui64vNV)
+#define glIsBufferResidentNV GLEW_GET_FUN(__glewIsBufferResidentNV)
+#define glIsNamedBufferResidentNV GLEW_GET_FUN(__glewIsNamedBufferResidentNV)
+#define glMakeBufferNonResidentNV GLEW_GET_FUN(__glewMakeBufferNonResidentNV)
+#define glMakeBufferResidentNV GLEW_GET_FUN(__glewMakeBufferResidentNV)
+#define glMakeNamedBufferNonResidentNV GLEW_GET_FUN(__glewMakeNamedBufferNonResidentNV)
+#define glMakeNamedBufferResidentNV GLEW_GET_FUN(__glewMakeNamedBufferResidentNV)
+#define glProgramUniformui64NV GLEW_GET_FUN(__glewProgramUniformui64NV)
+#define glProgramUniformui64vNV GLEW_GET_FUN(__glewProgramUniformui64vNV)
+#define glUniformui64NV GLEW_GET_FUN(__glewUniformui64NV)
+#define glUniformui64vNV GLEW_GET_FUN(__glewUniformui64vNV)
+
+#define GLEW_NV_shader_buffer_load GLEW_GET_VAR(__GLEW_NV_shader_buffer_load)
+
+#endif /* GL_NV_shader_buffer_load */
+
+/* ---------------------- GL_NV_tessellation_program5 ---------------------- */
+
+#ifndef GL_NV_tessellation_program5
+#define GL_NV_tessellation_program5 1
+
+#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+
+#define GLEW_NV_tessellation_program5 GLEW_GET_VAR(__GLEW_NV_tessellation_program5)
+
+#endif /* GL_NV_tessellation_program5 */
+
+/* -------------------------- GL_NV_texgen_emboss -------------------------- */
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+
+#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss)
+
+#endif /* GL_NV_texgen_emboss */
+
+/* ------------------------ GL_NV_texgen_reflection ------------------------ */
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+
+#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection)
+
+#endif /* GL_NV_texgen_reflection */
+
+/* ------------------------- GL_NV_texture_barrier ------------------------- */
+
+#ifndef GL_NV_texture_barrier
+#define GL_NV_texture_barrier 1
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREBARRIERNVPROC) (void);
+
+#define glTextureBarrierNV GLEW_GET_FUN(__glewTextureBarrierNV)
+
+#define GLEW_NV_texture_barrier GLEW_GET_VAR(__GLEW_NV_texture_barrier)
+
+#endif /* GL_NV_texture_barrier */
+
+/* --------------------- GL_NV_texture_compression_vtc --------------------- */
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+
+#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc)
+
+#endif /* GL_NV_texture_compression_vtc */
+
+/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+
+#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4)
+
+#endif /* GL_NV_texture_env_combine4 */
+
+/* ---------------------- GL_NV_texture_expand_normal ---------------------- */
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+
+#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal)
+
+#endif /* GL_NV_texture_expand_normal */
+
+/* ----------------------- GL_NV_texture_multisample ----------------------- */
+
+#ifndef GL_NV_texture_multisample
+#define GL_NV_texture_multisample 1
+
+#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045
+#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+
+#define glTexImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage2DMultisampleCoverageNV)
+#define glTexImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage3DMultisampleCoverageNV)
+#define glTextureImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage2DMultisampleCoverageNV)
+#define glTextureImage2DMultisampleNV GLEW_GET_FUN(__glewTextureImage2DMultisampleNV)
+#define glTextureImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage3DMultisampleCoverageNV)
+#define glTextureImage3DMultisampleNV GLEW_GET_FUN(__glewTextureImage3DMultisampleNV)
+
+#define GLEW_NV_texture_multisample GLEW_GET_VAR(__GLEW_NV_texture_multisample)
+
+#endif /* GL_NV_texture_multisample */
+
+/* ------------------------ GL_NV_texture_rectangle ------------------------ */
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+
+#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle)
+
+#endif /* GL_NV_texture_rectangle */
+
+/* -------------------------- GL_NV_texture_shader ------------------------- */
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+
+#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader)
+
+#endif /* GL_NV_texture_shader */
+
+/* ------------------------- GL_NV_texture_shader2 ------------------------- */
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+
+#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2)
+
+#endif /* GL_NV_texture_shader2 */
+
+/* ------------------------- GL_NV_texture_shader3 ------------------------- */
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+
+#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3)
+
+#endif /* GL_NV_texture_shader3 */
+
+/* ------------------------ GL_NV_transform_feedback ----------------------- */
+
+#ifndef GL_NV_transform_feedback
+#define GL_NV_transform_feedback 1
+
+#define GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define GL_TEXTURE_COORD_NV 0x8C79
+#define GL_CLIP_DISTANCE_NV 0x8C7A
+#define GL_VERTEX_ID_NV 0x8C7B
+#define GL_PRIMITIVE_ID_NV 0x8C7C
+#define GL_GENERIC_ATTRIB_NV 0x8C7D
+#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define GL_ACTIVE_VARYINGS_NV 0x8C81
+#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define GL_RASTERIZER_DISCARD_NV 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+
+typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);
+typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);
+typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);
+typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+
+#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV)
+#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV)
+#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV)
+#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV)
+#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV)
+#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV)
+#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV)
+#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV)
+#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV)
+#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV)
+#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV)
+
+#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback)
+
+#endif /* GL_NV_transform_feedback */
+
+/* ----------------------- GL_NV_transform_feedback2 ----------------------- */
+
+#ifndef GL_NV_transform_feedback2
+#define GL_NV_transform_feedback2 1
+
+#define GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+
+typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
+typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint* ids);
+typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
+
+#define glBindTransformFeedbackNV GLEW_GET_FUN(__glewBindTransformFeedbackNV)
+#define glDeleteTransformFeedbacksNV GLEW_GET_FUN(__glewDeleteTransformFeedbacksNV)
+#define glDrawTransformFeedbackNV GLEW_GET_FUN(__glewDrawTransformFeedbackNV)
+#define glGenTransformFeedbacksNV GLEW_GET_FUN(__glewGenTransformFeedbacksNV)
+#define glIsTransformFeedbackNV GLEW_GET_FUN(__glewIsTransformFeedbackNV)
+#define glPauseTransformFeedbackNV GLEW_GET_FUN(__glewPauseTransformFeedbackNV)
+#define glResumeTransformFeedbackNV GLEW_GET_FUN(__glewResumeTransformFeedbackNV)
+
+#define GLEW_NV_transform_feedback2 GLEW_GET_VAR(__GLEW_NV_transform_feedback2)
+
+#endif /* GL_NV_transform_feedback2 */
+
+/* -------------------------- GL_NV_vdpau_interop -------------------------- */
+
+#ifndef GL_NV_vdpau_interop
+#define GL_NV_vdpau_interop 1
+
+#define GL_SURFACE_STATE_NV 0x86EB
+#define GL_SURFACE_REGISTERED_NV 0x86FD
+#define GL_SURFACE_MAPPED_NV 0x8700
+#define GL_WRITE_DISCARD_NV 0x88BE
+
+typedef GLintptr GLvdpauSurfaceNV;
+
+typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values);
+typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress);
+typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces);
+typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef void (GLAPIENTRY * PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
+typedef void (GLAPIENTRY * PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV* surfaces);
+typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
+
+#define glVDPAUFiniNV GLEW_GET_FUN(__glewVDPAUFiniNV)
+#define glVDPAUGetSurfaceivNV GLEW_GET_FUN(__glewVDPAUGetSurfaceivNV)
+#define glVDPAUInitNV GLEW_GET_FUN(__glewVDPAUInitNV)
+#define glVDPAUIsSurfaceNV GLEW_GET_FUN(__glewVDPAUIsSurfaceNV)
+#define glVDPAUMapSurfacesNV GLEW_GET_FUN(__glewVDPAUMapSurfacesNV)
+#define glVDPAURegisterOutputSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterOutputSurfaceNV)
+#define glVDPAURegisterVideoSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterVideoSurfaceNV)
+#define glVDPAUSurfaceAccessNV GLEW_GET_FUN(__glewVDPAUSurfaceAccessNV)
+#define glVDPAUUnmapSurfacesNV GLEW_GET_FUN(__glewVDPAUUnmapSurfacesNV)
+#define glVDPAUUnregisterSurfaceNV GLEW_GET_FUN(__glewVDPAUUnregisterSurfaceNV)
+
+#define GLEW_NV_vdpau_interop GLEW_GET_VAR(__GLEW_NV_vdpau_interop)
+
+#endif /* GL_NV_vdpau_interop */
+
+/* ------------------------ GL_NV_vertex_array_range ----------------------- */
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+
+typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer);
+
+#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV)
+#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV)
+
+#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range)
+
+#endif /* GL_NV_vertex_array_range */
+
+/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+
+#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2)
+
+#endif /* GL_NV_vertex_array_range2 */
+
+/* ------------------- GL_NV_vertex_attrib_integer_64bit ------------------- */
+
+#ifndef GL_NV_vertex_attrib_integer_64bit
+#define GL_NV_vertex_attrib_integer_64bit 1
+
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT* params);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+
+#define glGetVertexAttribLi64vNV GLEW_GET_FUN(__glewGetVertexAttribLi64vNV)
+#define glGetVertexAttribLui64vNV GLEW_GET_FUN(__glewGetVertexAttribLui64vNV)
+#define glVertexAttribL1i64NV GLEW_GET_FUN(__glewVertexAttribL1i64NV)
+#define glVertexAttribL1i64vNV GLEW_GET_FUN(__glewVertexAttribL1i64vNV)
+#define glVertexAttribL1ui64NV GLEW_GET_FUN(__glewVertexAttribL1ui64NV)
+#define glVertexAttribL1ui64vNV GLEW_GET_FUN(__glewVertexAttribL1ui64vNV)
+#define glVertexAttribL2i64NV GLEW_GET_FUN(__glewVertexAttribL2i64NV)
+#define glVertexAttribL2i64vNV GLEW_GET_FUN(__glewVertexAttribL2i64vNV)
+#define glVertexAttribL2ui64NV GLEW_GET_FUN(__glewVertexAttribL2ui64NV)
+#define glVertexAttribL2ui64vNV GLEW_GET_FUN(__glewVertexAttribL2ui64vNV)
+#define glVertexAttribL3i64NV GLEW_GET_FUN(__glewVertexAttribL3i64NV)
+#define glVertexAttribL3i64vNV GLEW_GET_FUN(__glewVertexAttribL3i64vNV)
+#define glVertexAttribL3ui64NV GLEW_GET_FUN(__glewVertexAttribL3ui64NV)
+#define glVertexAttribL3ui64vNV GLEW_GET_FUN(__glewVertexAttribL3ui64vNV)
+#define glVertexAttribL4i64NV GLEW_GET_FUN(__glewVertexAttribL4i64NV)
+#define glVertexAttribL4i64vNV GLEW_GET_FUN(__glewVertexAttribL4i64vNV)
+#define glVertexAttribL4ui64NV GLEW_GET_FUN(__glewVertexAttribL4ui64NV)
+#define glVertexAttribL4ui64vNV GLEW_GET_FUN(__glewVertexAttribL4ui64vNV)
+#define glVertexAttribLFormatNV GLEW_GET_FUN(__glewVertexAttribLFormatNV)
+
+#define GLEW_NV_vertex_attrib_integer_64bit GLEW_GET_VAR(__GLEW_NV_vertex_attrib_integer_64bit)
+
+#endif /* GL_NV_vertex_attrib_integer_64bit */
+
+/* ------------------- GL_NV_vertex_buffer_unified_memory ------------------ */
+
+#ifndef GL_NV_vertex_buffer_unified_memory
+#define GL_NV_vertex_buffer_unified_memory 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+
+typedef void (GLAPIENTRY * PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+typedef void (GLAPIENTRY * PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT result[]);
+typedef void (GLAPIENTRY * PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+typedef void (GLAPIENTRY * PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+
+#define glBufferAddressRangeNV GLEW_GET_FUN(__glewBufferAddressRangeNV)
+#define glColorFormatNV GLEW_GET_FUN(__glewColorFormatNV)
+#define glEdgeFlagFormatNV GLEW_GET_FUN(__glewEdgeFlagFormatNV)
+#define glFogCoordFormatNV GLEW_GET_FUN(__glewFogCoordFormatNV)
+#define glGetIntegerui64i_vNV GLEW_GET_FUN(__glewGetIntegerui64i_vNV)
+#define glIndexFormatNV GLEW_GET_FUN(__glewIndexFormatNV)
+#define glNormalFormatNV GLEW_GET_FUN(__glewNormalFormatNV)
+#define glSecondaryColorFormatNV GLEW_GET_FUN(__glewSecondaryColorFormatNV)
+#define glTexCoordFormatNV GLEW_GET_FUN(__glewTexCoordFormatNV)
+#define glVertexAttribFormatNV GLEW_GET_FUN(__glewVertexAttribFormatNV)
+#define glVertexAttribIFormatNV GLEW_GET_FUN(__glewVertexAttribIFormatNV)
+#define glVertexFormatNV GLEW_GET_FUN(__glewVertexFormatNV)
+
+#define GLEW_NV_vertex_buffer_unified_memory GLEW_GET_VAR(__GLEW_NV_vertex_buffer_unified_memory)
+
+#endif /* GL_NV_vertex_buffer_unified_memory */
+
+/* -------------------------- GL_NV_vertex_program ------------------------- */
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+
+typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences);
+typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program);
+typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params);
+typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids);
+typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v);
+typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v);
+
+#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV)
+#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV)
+#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV)
+#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV)
+#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV)
+#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV)
+#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV)
+#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV)
+#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV)
+#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV)
+#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV)
+#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV)
+#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV)
+#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV)
+#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV)
+#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV)
+#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV)
+#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV)
+#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV)
+#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV)
+#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV)
+#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV)
+#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV)
+#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV)
+#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV)
+#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV)
+#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV)
+#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV)
+#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV)
+#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV)
+#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV)
+#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV)
+#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV)
+#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV)
+#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV)
+#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV)
+#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV)
+#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV)
+#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV)
+#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV)
+#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV)
+#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV)
+#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV)
+#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV)
+#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV)
+#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV)
+#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV)
+#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV)
+#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV)
+#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV)
+#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV)
+#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV)
+#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV)
+#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV)
+#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV)
+#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV)
+#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV)
+#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV)
+#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV)
+#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV)
+#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV)
+#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV)
+#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV)
+#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV)
+
+#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program)
+
+#endif /* GL_NV_vertex_program */
+
+/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+
+#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1)
+
+#endif /* GL_NV_vertex_program1_1 */
+
+/* ------------------------- GL_NV_vertex_program2 ------------------------- */
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+
+#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2)
+
+#endif /* GL_NV_vertex_program2 */
+
+/* ---------------------- GL_NV_vertex_program2_option --------------------- */
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+
+#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option)
+
+#endif /* GL_NV_vertex_program2_option */
+
+/* ------------------------- GL_NV_vertex_program3 ------------------------- */
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+
+#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+
+#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3)
+
+#endif /* GL_NV_vertex_program3 */
+
+/* ------------------------- GL_NV_vertex_program4 ------------------------- */
+
+#ifndef GL_NV_vertex_program4
+#define GL_NV_vertex_program4 1
+
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+
+#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4)
+
+#endif /* GL_NV_vertex_program4 */
+
+/* -------------------------- GL_NV_video_capture -------------------------- */
+
+#ifndef GL_NV_video_capture
+#define GL_NV_video_capture 1
+
+#define GL_VIDEO_BUFFER_NV 0x9020
+#define GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define GL_FIELD_UPPER_NV 0x9022
+#define GL_FIELD_LOWER_NV 0x9023
+#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define GL_PARTIAL_SUCCESS_NV 0x902E
+#define GL_SUCCESS_NV 0x902F
+#define GL_FAILURE_NV 0x9030
+#define GL_YCBYCR8_422_NV 0x9031
+#define GL_YCBAYCR8A_4224_NV 0x9032
+#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+
+typedef void (GLAPIENTRY * PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+typedef void (GLAPIENTRY * PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint* params);
+typedef GLenum (GLAPIENTRY * PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint* sequence_num, GLuint64EXT *capture_time);
+typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble* params);
+typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint* params);
+
+#define glBeginVideoCaptureNV GLEW_GET_FUN(__glewBeginVideoCaptureNV)
+#define glBindVideoCaptureStreamBufferNV GLEW_GET_FUN(__glewBindVideoCaptureStreamBufferNV)
+#define glBindVideoCaptureStreamTextureNV GLEW_GET_FUN(__glewBindVideoCaptureStreamTextureNV)
+#define glEndVideoCaptureNV GLEW_GET_FUN(__glewEndVideoCaptureNV)
+#define glGetVideoCaptureStreamdvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamdvNV)
+#define glGetVideoCaptureStreamfvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamfvNV)
+#define glGetVideoCaptureStreamivNV GLEW_GET_FUN(__glewGetVideoCaptureStreamivNV)
+#define glGetVideoCaptureivNV GLEW_GET_FUN(__glewGetVideoCaptureivNV)
+#define glVideoCaptureNV GLEW_GET_FUN(__glewVideoCaptureNV)
+#define glVideoCaptureStreamParameterdvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterdvNV)
+#define glVideoCaptureStreamParameterfvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterfvNV)
+#define glVideoCaptureStreamParameterivNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterivNV)
+
+#define GLEW_NV_video_capture GLEW_GET_VAR(__GLEW_NV_video_capture)
+
+#endif /* GL_NV_video_capture */
+
+/* ------------------------ GL_OES_byte_coordinates ------------------------ */
+
+#ifndef GL_OES_byte_coordinates
+#define GL_OES_byte_coordinates 1
+
+#define GL_BYTE 0x1400
+
+#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates)
+
+#endif /* GL_OES_byte_coordinates */
+
+/* ------------------- GL_OES_compressed_paletted_texture ------------------ */
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+
+#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture)
+
+#endif /* GL_OES_compressed_paletted_texture */
+
+/* --------------------------- GL_OES_read_format -------------------------- */
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+
+#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format)
+
+#endif /* GL_OES_read_format */
+
+/* ------------------------ GL_OES_single_precision ------------------------ */
+
+#ifndef GL_OES_single_precision
+#define GL_OES_single_precision 1
+
+typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth);
+typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation);
+typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+
+#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES)
+#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES)
+#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES)
+#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES)
+#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES)
+#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES)
+
+#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision)
+
+#endif /* GL_OES_single_precision */
+
+/* ---------------------------- GL_OML_interlace --------------------------- */
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+
+#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace)
+
+#endif /* GL_OML_interlace */
+
+/* ---------------------------- GL_OML_resample ---------------------------- */
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+
+#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample)
+
+#endif /* GL_OML_resample */
+
+/* ---------------------------- GL_OML_subsample --------------------------- */
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+
+#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample)
+
+#endif /* GL_OML_subsample */
+
+/* --------------------------- GL_PGI_misc_hints --------------------------- */
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000
+#define GL_CONSERVE_MEMORY_HINT_PGI 107005
+#define GL_RECLAIM_MEMORY_HINT_PGI 107006
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012
+#define GL_ALWAYS_FAST_HINT_PGI 107020
+#define GL_ALWAYS_SOFT_HINT_PGI 107021
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030
+#define GL_STRICT_LIGHTING_HINT_PGI 107031
+#define GL_STRICT_SCISSOR_HINT_PGI 107032
+#define GL_FULL_STIPPLE_HINT_PGI 107033
+#define GL_CLIP_NEAR_HINT_PGI 107040
+#define GL_CLIP_FAR_HINT_PGI 107041
+#define GL_WIDE_LINE_HINT_PGI 107042
+#define GL_BACK_NORMALS_HINT_PGI 107043
+
+#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints)
+
+#endif /* GL_PGI_misc_hints */
+
+/* -------------------------- GL_PGI_vertex_hints -------------------------- */
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_VERTEX_DATA_HINT_PGI 107050
+#define GL_VERTEX_CONSISTENT_HINT_PGI 107051
+#define GL_MATERIAL_SIDE_HINT_PGI 107052
+#define GL_MAX_VERTEX_HINT_PGI 107053
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+
+#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints)
+
+#endif /* GL_PGI_vertex_hints */
+
+/* ----------------------- GL_REND_screen_coordinates ---------------------- */
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+
+#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates)
+
+#endif /* GL_REND_screen_coordinates */
+
+/* ------------------------------- GL_S3_s3tc ------------------------------ */
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#define GL_RGBA_DXT5_S3TC 0x83A4
+#define GL_RGBA4_DXT5_S3TC 0x83A5
+
+#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc)
+
+#endif /* GL_S3_s3tc */
+
+/* -------------------------- GL_SGIS_color_range -------------------------- */
+
+#ifndef GL_SGIS_color_range
+#define GL_SGIS_color_range 1
+
+#define GL_EXTENDED_RANGE_SGIS 0x85A5
+#define GL_MIN_RED_SGIS 0x85A6
+#define GL_MAX_RED_SGIS 0x85A7
+#define GL_MIN_GREEN_SGIS 0x85A8
+#define GL_MAX_GREEN_SGIS 0x85A9
+#define GL_MIN_BLUE_SGIS 0x85AA
+#define GL_MAX_BLUE_SGIS 0x85AB
+#define GL_MIN_ALPHA_SGIS 0x85AC
+#define GL_MAX_ALPHA_SGIS 0x85AD
+
+#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range)
+
+#endif /* GL_SGIS_color_range */
+
+/* ------------------------- GL_SGIS_detail_texture ------------------------ */
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+
+typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points);
+
+#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS)
+#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS)
+
+#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture)
+
+#endif /* GL_SGIS_detail_texture */
+
+/* -------------------------- GL_SGIS_fog_function ------------------------- */
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+
+typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points);
+
+#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS)
+#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS)
+
+#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function)
+
+#endif /* GL_SGIS_fog_function */
+
+/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+
+#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap)
+
+#endif /* GL_SGIS_generate_mipmap */
+
+/* -------------------------- GL_SGIS_multisample -------------------------- */
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+
+typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+
+#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS)
+#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS)
+
+#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample)
+
+#endif /* GL_SGIS_multisample */
+
+/* ------------------------- GL_SGIS_pixel_texture ------------------------- */
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+
+#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture)
+
+#endif /* GL_SGIS_pixel_texture */
+
+/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+
+#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen)
+
+#endif /* GL_SGIS_point_line_texgen */
+
+/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+
+typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points);
+typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points);
+
+#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS)
+#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS)
+
+#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture)
+
+#endif /* GL_SGIS_sharpen_texture */
+
+/* --------------------------- GL_SGIS_texture4D --------------------------- */
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+
+typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels);
+typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels);
+
+#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS)
+#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS)
+
+#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D)
+
+#endif /* GL_SGIS_texture4D */
+
+/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+
+#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp)
+
+#endif /* GL_SGIS_texture_border_clamp */
+
+/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+
+#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp)
+
+#endif /* GL_SGIS_texture_edge_clamp */
+
+/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+
+typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights);
+typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights);
+
+#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS)
+#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS)
+
+#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4)
+
+#endif /* GL_SGIS_texture_filter4 */
+
+/* -------------------------- GL_SGIS_texture_lod -------------------------- */
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+
+#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod)
+
+#endif /* GL_SGIS_texture_lod */
+
+/* ------------------------- GL_SGIS_texture_select ------------------------ */
+
+#ifndef GL_SGIS_texture_select
+#define GL_SGIS_texture_select 1
+
+#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select)
+
+#endif /* GL_SGIS_texture_select */
+
+/* ----------------------------- GL_SGIX_async ----------------------------- */
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+
+#define GL_ASYNC_MARKER_SGIX 0x8329
+
+typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp);
+typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp);
+
+#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX)
+#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX)
+#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX)
+#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX)
+#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX)
+#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX)
+
+#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async)
+
+#endif /* GL_SGIX_async */
+
+/* ------------------------ GL_SGIX_async_histogram ------------------------ */
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+
+#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram)
+
+#endif /* GL_SGIX_async_histogram */
+
+/* -------------------------- GL_SGIX_async_pixel -------------------------- */
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+
+#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel)
+
+#endif /* GL_SGIX_async_pixel */
+
+/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+
+#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax)
+
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+/* ---------------------------- GL_SGIX_clipmap ---------------------------- */
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+
+#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap)
+
+#endif /* GL_SGIX_clipmap */
+
+/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+
+#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy)
+
+#endif /* GL_SGIX_convolution_accuracy */
+
+/* ------------------------- GL_SGIX_depth_texture ------------------------- */
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+
+#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture)
+
+#endif /* GL_SGIX_depth_texture */
+
+/* -------------------------- GL_SGIX_flush_raster ------------------------- */
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+
+typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void);
+
+#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX)
+
+#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster)
+
+#endif /* GL_SGIX_flush_raster */
+
+/* --------------------------- GL_SGIX_fog_offset -------------------------- */
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+
+#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset)
+
+#endif /* GL_SGIX_fog_offset */
+
+/* -------------------------- GL_SGIX_fog_texture -------------------------- */
+
+#ifndef GL_SGIX_fog_texture
+#define GL_SGIX_fog_texture 1
+
+#define GL_TEXTURE_FOG_SGIX 0
+#define GL_FOG_PATCHY_FACTOR_SGIX 0
+#define GL_FRAGMENT_FOG_SGIX 0
+
+typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname);
+
+#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX)
+
+#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture)
+
+#endif /* GL_SGIX_fog_texture */
+
+/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */
+
+#ifndef GL_SGIX_fragment_specular_lighting
+#define GL_SGIX_fragment_specular_lighting 1
+
+typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param);
+typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data);
+typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data);
+
+#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX)
+#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX)
+#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX)
+#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX)
+#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX)
+#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX)
+#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX)
+#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX)
+#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX)
+#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX)
+#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX)
+#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX)
+#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX)
+#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX)
+#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX)
+#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX)
+#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX)
+
+#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting)
+
+#endif /* GL_SGIX_fragment_specular_lighting */
+
+/* --------------------------- GL_SGIX_framezoom --------------------------- */
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+
+typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+
+#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX)
+
+#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom)
+
+#endif /* GL_SGIX_framezoom */
+
+/* --------------------------- GL_SGIX_interlace --------------------------- */
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+
+#define GL_INTERLACE_SGIX 0x8094
+
+#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace)
+
+#endif /* GL_SGIX_interlace */
+
+/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+
+#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1)
+
+#endif /* GL_SGIX_ir_instrument1 */
+
+/* ------------------------- GL_SGIX_list_priority ------------------------- */
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+
+#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority)
+
+#endif /* GL_SGIX_list_priority */
+
+/* ------------------------- GL_SGIX_pixel_texture ------------------------- */
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+
+typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+
+#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX)
+
+#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture)
+
+#endif /* GL_SGIX_pixel_texture */
+
+/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */
+
+#ifndef GL_SGIX_pixel_texture_bits
+#define GL_SGIX_pixel_texture_bits 1
+
+#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits)
+
+#endif /* GL_SGIX_pixel_texture_bits */
+
+/* ------------------------ GL_SGIX_reference_plane ------------------------ */
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+
+typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation);
+
+#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX)
+
+#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane)
+
+#endif /* GL_SGIX_reference_plane */
+
+/* ---------------------------- GL_SGIX_resample --------------------------- */
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+
+#define GL_PACK_RESAMPLE_SGIX 0x842E
+#define GL_UNPACK_RESAMPLE_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#define GL_RESAMPLE_REPLICATE_SGIX 0x8433
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434
+
+#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample)
+
+#endif /* GL_SGIX_resample */
+
+/* ----------------------------- GL_SGIX_shadow ---------------------------- */
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+
+#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow)
+
+#endif /* GL_SGIX_shadow */
+
+/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+
+#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient)
+
+#endif /* GL_SGIX_shadow_ambient */
+
+/* ----------------------------- GL_SGIX_sprite ---------------------------- */
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params);
+
+#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX)
+#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX)
+#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX)
+#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX)
+
+#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite)
+
+#endif /* GL_SGIX_sprite */
+
+/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+
+typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+
+#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX)
+
+#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer)
+
+#endif /* GL_SGIX_tag_sample_buffer */
+
+/* ------------------------ GL_SGIX_texture_add_env ------------------------ */
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+
+#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env)
+
+#endif /* GL_SGIX_texture_add_env */
+
+/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+
+#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp)
+
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+
+#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias)
+
+#endif /* GL_SGIX_texture_lod_bias */
+
+/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+
+#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer)
+
+#endif /* GL_SGIX_texture_multi_buffer */
+
+/* ------------------------- GL_SGIX_texture_range ------------------------- */
+
+#ifndef GL_SGIX_texture_range
+#define GL_SGIX_texture_range 1
+
+#define GL_RGB_SIGNED_SGIX 0x85E0
+#define GL_RGBA_SIGNED_SGIX 0x85E1
+#define GL_ALPHA_SIGNED_SGIX 0x85E2
+#define GL_LUMINANCE_SIGNED_SGIX 0x85E3
+#define GL_INTENSITY_SIGNED_SGIX 0x85E4
+#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5
+#define GL_RGB16_SIGNED_SGIX 0x85E6
+#define GL_RGBA16_SIGNED_SGIX 0x85E7
+#define GL_ALPHA16_SIGNED_SGIX 0x85E8
+#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9
+#define GL_INTENSITY16_SIGNED_SGIX 0x85EA
+#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB
+#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC
+#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED
+#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE
+#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF
+#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0
+#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1
+#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2
+#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3
+#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4
+#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5
+#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6
+#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7
+#define GL_MIN_LUMINANCE_SGIS 0x85F8
+#define GL_MAX_LUMINANCE_SGIS 0x85F9
+#define GL_MIN_INTENSITY_SGIS 0x85FA
+#define GL_MAX_INTENSITY_SGIS 0x85FB
+
+#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range)
+
+#endif /* GL_SGIX_texture_range */
+
+/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+
+#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias)
+
+#endif /* GL_SGIX_texture_scale_bias */
+
+/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+
+#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip)
+
+#endif /* GL_SGIX_vertex_preclip */
+
+/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */
+
+#ifndef GL_SGIX_vertex_preclip_hint
+#define GL_SGIX_vertex_preclip_hint 1
+
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+
+#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint)
+
+#endif /* GL_SGIX_vertex_preclip_hint */
+
+/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+
+#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb)
+
+#endif /* GL_SGIX_ycrcb */
+
+/* -------------------------- GL_SGI_color_matrix -------------------------- */
+
+#ifndef GL_SGI_color_matrix
+#define GL_SGI_color_matrix 1
+
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+
+#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix)
+
+#endif /* GL_SGI_color_matrix */
+
+/* --------------------------- GL_SGI_color_table -------------------------- */
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params);
+typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table);
+typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table);
+
+#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI)
+#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI)
+#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI)
+#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI)
+#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI)
+#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI)
+#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI)
+
+#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table)
+
+#endif /* GL_SGI_color_table */
+
+/* ----------------------- GL_SGI_texture_color_table ---------------------- */
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+
+#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table)
+
+#endif /* GL_SGI_texture_color_table */
+
+/* ------------------------- GL_SUNX_constant_data ------------------------- */
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+
+typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void);
+
+#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX)
+
+#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data)
+
+#endif /* GL_SUNX_constant_data */
+
+/* -------------------- GL_SUN_convolution_border_modes -------------------- */
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+
+#define GL_WRAP_BORDER_SUN 0x81D4
+
+#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes)
+
+#endif /* GL_SUN_convolution_border_modes */
+
+/* -------------------------- GL_SUN_global_alpha -------------------------- */
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+
+#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN)
+#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN)
+#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN)
+#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN)
+#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN)
+#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN)
+#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN)
+#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN)
+
+#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha)
+
+#endif /* GL_SUN_global_alpha */
+
+/* --------------------------- GL_SUN_mesh_array --------------------------- */
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+
+#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array)
+
+#endif /* GL_SUN_mesh_array */
+
+/* ------------------------ GL_SUN_read_video_pixels ----------------------- */
+
+#ifndef GL_SUN_read_video_pixels
+#define GL_SUN_read_video_pixels 1
+
+typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+
+#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN)
+
+#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels)
+
+#endif /* GL_SUN_read_video_pixels */
+
+/* --------------------------- GL_SUN_slice_accum -------------------------- */
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+
+#define GL_SLICE_ACCUM_SUN 0x85CC
+
+#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum)
+
+#endif /* GL_SUN_slice_accum */
+
+/* -------------------------- GL_SUN_triangle_list ------------------------- */
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+
+#define GL_RESTART_SUN 0x01
+#define GL_REPLACE_MIDDLE_SUN 0x02
+#define GL_REPLACE_OLDEST_SUN 0x03
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code);
+
+#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN)
+#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN)
+#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN)
+#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN)
+#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN)
+#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN)
+#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN)
+
+#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list)
+
+#endif /* GL_SUN_triangle_list */
+
+/* ----------------------------- GL_SUN_vertex ----------------------------- */
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v);
+
+#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN)
+#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN)
+#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN)
+#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN)
+#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN)
+#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN)
+#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN)
+#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN)
+#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN)
+#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN)
+#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN)
+#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN)
+#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN)
+#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN)
+#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN)
+#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN)
+#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN)
+#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN)
+#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN)
+#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN)
+#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN)
+#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN)
+#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN)
+#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN)
+#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN)
+#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN)
+#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN)
+#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN)
+#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN)
+#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN)
+#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN)
+#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN)
+#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN)
+#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN)
+#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN)
+
+#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex)
+
+#endif /* GL_SUN_vertex */
+
+/* -------------------------- GL_WIN_phong_shading ------------------------- */
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+
+#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading)
+
+#endif /* GL_WIN_phong_shading */
+
+/* -------------------------- GL_WIN_specular_fog -------------------------- */
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+
+#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog)
+
+#endif /* GL_WIN_specular_fog */
+
+/* ---------------------------- GL_WIN_swap_hint --------------------------- */
+
+#ifndef GL_WIN_swap_hint
+#define GL_WIN_swap_hint 1
+
+typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN)
+
+#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint)
+
+#endif /* GL_WIN_swap_hint */
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+#define GLEW_FUN_EXPORT
+#else
+#define GLEW_FUN_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX)
+#define GLEW_VAR_EXPORT
+#else
+#define GLEW_VAR_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#if defined(GLEW_MX) && defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D;
+
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv;
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage;
+
+GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate;
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries;
+GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers;
+GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv;
+GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv;
+GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer;
+GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer;
+
+GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader;
+GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate;
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader;
+GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram;
+GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader;
+GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray;
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray;
+GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform;
+GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders;
+GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv;
+GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog;
+GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource;
+GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv;
+GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram;
+GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader;
+GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram;
+GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource;
+GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate;
+GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate;
+GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer;
+
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv;
+
+GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender;
+GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback;
+GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation;
+GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv;
+GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv;
+GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski;
+GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei;
+GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei;
+GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender;
+GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback;
+GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v;
+GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation;
+GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv;
+GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv;
+GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced;
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex;
+GLEW_FUN_EXPORT PFNGLTEXBUFFERPROC __glewTexBuffer;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v;
+GLEW_FUN_EXPORT PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v;
+
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIPROC __glewBlendEquationi;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCIPROC __glewBlendFunci;
+GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading;
+
+GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX;
+
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD;
+
+GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD;
+GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD;
+GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD;
+
+GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD;
+GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD;
+GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD;
+GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD;
+GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD;
+GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD;
+
+GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD;
+
+GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD;
+GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE;
+GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE;
+GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE;
+GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE;
+GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE;
+
+GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE;
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE;
+GLEW_FUN_EXPORT PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE;
+GLEW_FUN_EXPORT PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE;
+
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE;
+GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE;
+
+GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE;
+
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE;
+GLEW_FUN_EXPORT PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE;
+GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef;
+GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat;
+GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler;
+GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstancedBaseInstance;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed;
+GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex;
+
+GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB;
+
+GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB;
+
+GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData;
+
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB;
+GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB;
+GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB;
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB;
+GLEW_FUN_EXPORT PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer;
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary;
+GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri;
+
+GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d;
+GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv;
+GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d;
+GLEW_FUN_EXPORT PFNGLUNIFORM2DVPROC __glewUniform2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORM3DPROC __glewUniform3d;
+GLEW_FUN_EXPORT PFNGLUNIFORM3DVPROC __glewUniform3dv;
+GLEW_FUN_EXPORT PFNGLUNIFORM4DPROC __glewUniform4d;
+GLEW_FUN_EXPORT PFNGLUNIFORM4DVPROC __glewUniform4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv;
+
+GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv;
+GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter;
+GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram;
+GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax;
+GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram;
+GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax;
+GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB;
+
+GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ;
+
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange;
+
+GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB;
+GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB;
+
+GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB;
+
+GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB;
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB;
+GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB;
+GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB;
+GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB;
+GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB;
+GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB;
+
+GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex;
+
+GLEW_FUN_EXPORT PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB;
+GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB;
+GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB;
+GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB;
+GLEW_FUN_EXPORT PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB;
+GLEW_FUN_EXPORT PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB;
+GLEW_FUN_EXPORT PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB;
+GLEW_FUN_EXPORT PFNGLGETNMAPIVARBPROC __glewGetnMapivARB;
+GLEW_FUN_EXPORT PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB;
+GLEW_FUN_EXPORT PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB;
+GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB;
+GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB;
+GLEW_FUN_EXPORT PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB;
+GLEW_FUN_EXPORT PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB;
+GLEW_FUN_EXPORT PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB;
+GLEW_FUN_EXPORT PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB;
+GLEW_FUN_EXPORT PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB;
+
+GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB;
+
+GLEW_FUN_EXPORT PFNGLBINDSAMPLERPROC __glewBindSampler;
+GLEW_FUN_EXPORT PFNGLDELETESAMPLERSPROC __glewDeleteSamplers;
+GLEW_FUN_EXPORT PFNGLGENSAMPLERSPROC __glewGenSamplers;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv;
+GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv;
+GLEW_FUN_EXPORT PFNGLISSAMPLERPROC __glewIsSampler;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri;
+GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv;
+
+GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram;
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv;
+GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline;
+
+GLEW_FUN_EXPORT PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __glewGetActiveAtomicCounterBufferiv;
+
+GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREPROC __glewBindImageTexture;
+GLEW_FUN_EXPORT PFNGLMEMORYBARRIERPROC __glewMemoryBarrier;
+
+GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB;
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB;
+GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB;
+GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB;
+GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB;
+GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB;
+GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB;
+GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB;
+GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB;
+GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB;
+GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB;
+GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB;
+GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB;
+GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB;
+GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB;
+GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB;
+
+GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName;
+GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName;
+GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv;
+GLEW_FUN_EXPORT PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex;
+GLEW_FUN_EXPORT PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv;
+GLEW_FUN_EXPORT PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv;
+
+GLEW_FUN_EXPORT PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB;
+GLEW_FUN_EXPORT PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB;
+GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB;
+GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB;
+GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB;
+GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB;
+
+GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync;
+GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync;
+GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync;
+GLEW_FUN_EXPORT PFNGLGETINTEGER64VPROC __glewGetInteger64v;
+GLEW_FUN_EXPORT PFNGLGETSYNCIVPROC __glewGetSynciv;
+GLEW_FUN_EXPORT PFNGLISSYNCPROC __glewIsSync;
+GLEW_FUN_EXPORT PFNGLWAITSYNCPROC __glewWaitSync;
+
+GLEW_FUN_EXPORT PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv;
+GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri;
+
+GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB;
+
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB;
+
+GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv;
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample;
+
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE1DPROC __glewTexStorage1D;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DPROC __glewTexStorage2D;
+GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DPROC __glewTexStorage3D;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v;
+GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter;
+
+GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback;
+GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback;
+GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks;
+GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback;
+GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback;
+GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback;
+
+GLEW_FUN_EXPORT PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream;
+GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed;
+GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv;
+
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __glewDrawTransformFeedbackInstanced;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __glewDrawTransformFeedbackStreamInstanced;
+
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB;
+GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB;
+GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB;
+
+GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName;
+GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv;
+GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices;
+GLEW_FUN_EXPORT PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding;
+
+GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays;
+GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays;
+GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer;
+
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB;
+GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB;
+
+GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB;
+GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB;
+GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB;
+GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB;
+GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB;
+GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB;
+GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB;
+GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB;
+
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB;
+GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB;
+GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB;
+
+GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB;
+GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB;
+GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB;
+
+GLEW_FUN_EXPORT PFNGLCOLORP3UIPROC __glewColorP3ui;
+GLEW_FUN_EXPORT PFNGLCOLORP3UIVPROC __glewColorP3uiv;
+GLEW_FUN_EXPORT PFNGLCOLORP4UIPROC __glewColorP4ui;
+GLEW_FUN_EXPORT PFNGLCOLORP4UIVPROC __glewColorP4uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv;
+GLEW_FUN_EXPORT PFNGLNORMALP3UIPROC __glewNormalP3ui;
+GLEW_FUN_EXPORT PFNGLNORMALP3UIVPROC __glewNormalP3uiv;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui;
+GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXP2UIPROC __glewVertexP2ui;
+GLEW_FUN_EXPORT PFNGLVERTEXP2UIVPROC __glewVertexP2uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXP3UIPROC __glewVertexP3ui;
+GLEW_FUN_EXPORT PFNGLVERTEXP3UIVPROC __glewVertexP3uiv;
+GLEW_FUN_EXPORT PFNGLVERTEXP4UIPROC __glewVertexP4ui;
+GLEW_FUN_EXPORT PFNGLVERTEXP4UIVPROC __glewVertexP4uiv;
+
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v;
+GLEW_FUN_EXPORT PFNGLGETFLOATI_VPROC __glewGetFloati_v;
+GLEW_FUN_EXPORT PFNGLSCISSORARRAYVPROC __glewScissorArrayv;
+GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDPROC __glewScissorIndexed;
+GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv;
+GLEW_FUN_EXPORT PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv;
+GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf;
+GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv;
+
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB;
+
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI;
+
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI;
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI;
+GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI;
+
+GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI;
+GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI;
+GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI;
+GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI;
+
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI;
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI;
+GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI;
+GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI;
+GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI;
+GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI;
+GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI;
+GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI;
+GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI;
+GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI;
+
+GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI;
+
+GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI;
+GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI;
+
+GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI;
+GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI;
+
+GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI;
+GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI;
+GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI;
+GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI;
+GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI;
+
+GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI;
+GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI;
+GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI;
+GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI;
+
+GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT;
+
+GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT;
+
+GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT;
+GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT;
+
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT;
+GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT;
+GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT;
+
+GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT;
+GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT;
+GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT;
+
+GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT;
+GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT;
+GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT;
+GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT;
+GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT;
+GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT;
+GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT;
+GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT;
+GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT;
+GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT;
+GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT;
+GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT;
+GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT;
+GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT;
+GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT;
+GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT;
+GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT;
+GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT;
+GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT;
+GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT;
+GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT;
+GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT;
+
+GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT;
+GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT;
+
+GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT;
+GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT;
+GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT;
+GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT;
+GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT;
+GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT;
+GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT;
+GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT;
+GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT;
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT;
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT;
+GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT;
+GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT;
+GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT;
+GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT;
+GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT;
+
+GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT;
+
+GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT;
+
+GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT;
+GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT;
+GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT;
+
+GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT;
+
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT;
+GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT;
+
+GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT;
+
+GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT;
+GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT;
+
+GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT;
+
+GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT;
+GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT;
+
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT;
+GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT;
+GLEW_FUN_EXPORT PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT;
+
+GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT;
+GLEW_FUN_EXPORT PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT;
+
+GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT;
+
+GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT;
+GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT;
+GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT;
+
+GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT;
+GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT;
+GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT;
+GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT;
+GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT;
+
+GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT;
+
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT;
+GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT;
+GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT;
+GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT;
+GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT;
+
+GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT;
+GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT;
+GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT;
+
+GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT;
+GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT;
+GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT;
+GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT;
+GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT;
+GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT;
+GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT;
+GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT;
+GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT;
+GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT;
+GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT;
+GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT;
+GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT;
+GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT;
+GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT;
+GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT;
+
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT;
+
+GLEW_FUN_EXPORT PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT;
+
+GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY;
+
+GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY;
+
+GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP;
+GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP;
+GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP;
+
+GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM;
+GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM;
+
+GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM;
+GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM;
+GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM;
+
+GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL;
+GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL;
+GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL;
+GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL;
+
+GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL;
+GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL;
+
+GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled;
+GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion;
+GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion;
+GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONPROC __glewNewBufferRegion;
+GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONPROC __glewReadBufferRegion;
+
+GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA;
+
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA;
+GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA;
+
+GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV;
+GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV;
+
+GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV;
+GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV;
+
+GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV;
+GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV;
+GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV;
+GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV;
+GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV;
+GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV;
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV;
+GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV;
+
+GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV;
+GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV;
+GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV;
+GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV;
+GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV;
+GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV;
+GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV;
+
+GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV;
+
+GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV;
+
+GLEW_FUN_EXPORT PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV;
+GLEW_FUN_EXPORT PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV;
+
+GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV;
+GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV;
+GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV;
+GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV;
+GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV;
+GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV;
+GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV;
+GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV;
+GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV;
+
+GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV;
+GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV;
+GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV;
+GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV;
+GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV;
+GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV;
+GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV;
+
+GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV;
+
+GLEW_FUN_EXPORT PFNGLCOPYPATHNVPROC __glewCopyPathNV;
+GLEW_FUN_EXPORT PFNGLCOVERFILLPATHINSTANCEDNVPROC __glewCoverFillPathInstancedNV;
+GLEW_FUN_EXPORT PFNGLCOVERFILLPATHNVPROC __glewCoverFillPathNV;
+GLEW_FUN_EXPORT PFNGLCOVERSTROKEPATHINSTANCEDNVPROC __glewCoverStrokePathInstancedNV;
+GLEW_FUN_EXPORT PFNGLCOVERSTROKEPATHNVPROC __glewCoverStrokePathNV;
+GLEW_FUN_EXPORT PFNGLDELETEPATHSNVPROC __glewDeletePathsNV;
+GLEW_FUN_EXPORT PFNGLGENPATHSNVPROC __glewGenPathsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOLORGENFVNVPROC __glewGetPathColorGenfvNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOLORGENIVNVPROC __glewGetPathColorGenivNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOMMANDSNVPROC __glewGetPathCommandsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHCOORDSNVPROC __glewGetPathCoordsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHDASHARRAYNVPROC __glewGetPathDashArrayNV;
+GLEW_FUN_EXPORT PFNGLGETPATHLENGTHNVPROC __glewGetPathLengthNV;
+GLEW_FUN_EXPORT PFNGLGETPATHMETRICRANGENVPROC __glewGetPathMetricRangeNV;
+GLEW_FUN_EXPORT PFNGLGETPATHMETRICSNVPROC __glewGetPathMetricsNV;
+GLEW_FUN_EXPORT PFNGLGETPATHPARAMETERFVNVPROC __glewGetPathParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETPATHPARAMETERIVNVPROC __glewGetPathParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETPATHSPACINGNVPROC __glewGetPathSpacingNV;
+GLEW_FUN_EXPORT PFNGLGETPATHTEXGENFVNVPROC __glewGetPathTexGenfvNV;
+GLEW_FUN_EXPORT PFNGLGETPATHTEXGENIVNVPROC __glewGetPathTexGenivNV;
+GLEW_FUN_EXPORT PFNGLINTERPOLATEPATHSNVPROC __glewInterpolatePathsNV;
+GLEW_FUN_EXPORT PFNGLISPATHNVPROC __glewIsPathNV;
+GLEW_FUN_EXPORT PFNGLISPOINTINFILLPATHNVPROC __glewIsPointInFillPathNV;
+GLEW_FUN_EXPORT PFNGLISPOINTINSTROKEPATHNVPROC __glewIsPointInStrokePathNV;
+GLEW_FUN_EXPORT PFNGLPATHCOLORGENNVPROC __glewPathColorGenNV;
+GLEW_FUN_EXPORT PFNGLPATHCOMMANDSNVPROC __glewPathCommandsNV;
+GLEW_FUN_EXPORT PFNGLPATHCOORDSNVPROC __glewPathCoordsNV;
+GLEW_FUN_EXPORT PFNGLPATHCOVERDEPTHFUNCNVPROC __glewPathCoverDepthFuncNV;
+GLEW_FUN_EXPORT PFNGLPATHDASHARRAYNVPROC __glewPathDashArrayNV;
+GLEW_FUN_EXPORT PFNGLPATHFOGGENNVPROC __glewPathFogGenNV;
+GLEW_FUN_EXPORT PFNGLPATHGLYPHRANGENVPROC __glewPathGlyphRangeNV;
+GLEW_FUN_EXPORT PFNGLPATHGLYPHSNVPROC __glewPathGlyphsNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERFNVPROC __glewPathParameterfNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERFVNVPROC __glewPathParameterfvNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERINVPROC __glewPathParameteriNV;
+GLEW_FUN_EXPORT PFNGLPATHPARAMETERIVNVPROC __glewPathParameterivNV;
+GLEW_FUN_EXPORT PFNGLPATHSTENCILDEPTHOFFSETNVPROC __glewPathStencilDepthOffsetNV;
+GLEW_FUN_EXPORT PFNGLPATHSTENCILFUNCNVPROC __glewPathStencilFuncNV;
+GLEW_FUN_EXPORT PFNGLPATHSTRINGNVPROC __glewPathStringNV;
+GLEW_FUN_EXPORT PFNGLPATHSUBCOMMANDSNVPROC __glewPathSubCommandsNV;
+GLEW_FUN_EXPORT PFNGLPATHSUBCOORDSNVPROC __glewPathSubCoordsNV;
+GLEW_FUN_EXPORT PFNGLPATHTEXGENNVPROC __glewPathTexGenNV;
+GLEW_FUN_EXPORT PFNGLPOINTALONGPATHNVPROC __glewPointAlongPathNV;
+GLEW_FUN_EXPORT PFNGLSTENCILFILLPATHINSTANCEDNVPROC __glewStencilFillPathInstancedNV;
+GLEW_FUN_EXPORT PFNGLSTENCILFILLPATHNVPROC __glewStencilFillPathNV;
+GLEW_FUN_EXPORT PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC __glewStencilStrokePathInstancedNV;
+GLEW_FUN_EXPORT PFNGLSTENCILSTROKEPATHNVPROC __glewStencilStrokePathNV;
+GLEW_FUN_EXPORT PFNGLTRANSFORMPATHNVPROC __glewTransformPathNV;
+GLEW_FUN_EXPORT PFNGLWEIGHTPATHSNVPROC __glewWeightPathsNV;
+
+GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV;
+GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV;
+
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV;
+GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV;
+GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV;
+GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV;
+
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV;
+GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV;
+
+GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV;
+GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV;
+GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV;
+GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV;
+GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV;
+
+GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV;
+GLEW_FUN_EXPORT PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV;
+GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV;
+GLEW_FUN_EXPORT PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV;
+GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV;
+GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV;
+GLEW_FUN_EXPORT PFNGLUNIFORMUI64NVPROC __glewUniformui64NV;
+GLEW_FUN_EXPORT PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV;
+GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV;
+
+GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV;
+GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV;
+GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV;
+GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV;
+GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV;
+GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV;
+GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV;
+GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV;
+
+GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV;
+GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV;
+GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV;
+GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV;
+
+GLEW_FUN_EXPORT PFNGLVDPAUFININVPROC __glewVDPAUFiniNV;
+GLEW_FUN_EXPORT PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV;
+GLEW_FUN_EXPORT PFNGLVDPAUINITNVPROC __glewVDPAUInitNV;
+GLEW_FUN_EXPORT PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV;
+GLEW_FUN_EXPORT PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV;
+GLEW_FUN_EXPORT PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV;
+GLEW_FUN_EXPORT PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV;
+GLEW_FUN_EXPORT PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV;
+GLEW_FUN_EXPORT PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV;
+GLEW_FUN_EXPORT PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV;
+
+GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV;
+GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV;
+
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV;
+
+GLEW_FUN_EXPORT PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV;
+GLEW_FUN_EXPORT PFNGLCOLORFORMATNVPROC __glewColorFormatNV;
+GLEW_FUN_EXPORT PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV;
+GLEW_FUN_EXPORT PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV;
+GLEW_FUN_EXPORT PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV;
+GLEW_FUN_EXPORT PFNGLINDEXFORMATNVPROC __glewIndexFormatNV;
+GLEW_FUN_EXPORT PFNGLNORMALFORMATNVPROC __glewNormalFormatNV;
+GLEW_FUN_EXPORT PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV;
+GLEW_FUN_EXPORT PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV;
+GLEW_FUN_EXPORT PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV;
+
+GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV;
+GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV;
+GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV;
+GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV;
+GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV;
+GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV;
+GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV;
+GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV;
+GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV;
+GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV;
+GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV;
+GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV;
+GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV;
+GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV;
+
+GLEW_FUN_EXPORT PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV;
+GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV;
+GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV;
+GLEW_FUN_EXPORT PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV;
+GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV;
+GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV;
+
+GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES;
+GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES;
+GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES;
+GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES;
+GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES;
+GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES;
+
+GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS;
+GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS;
+GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS;
+GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS;
+
+GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS;
+GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS;
+GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS;
+
+GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS;
+GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS;
+
+GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX;
+GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX;
+GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX;
+GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX;
+GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX;
+GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX;
+
+GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX;
+
+GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX;
+
+GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX;
+GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX;
+GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX;
+
+GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX;
+
+GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX;
+
+GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX;
+
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX;
+GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX;
+
+GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX;
+
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI;
+GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI;
+GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI;
+GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI;
+GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI;
+
+GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX;
+
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN;
+GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN;
+
+GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN;
+
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN;
+
+GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN;
+GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN;
+
+GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN;
+
+#if defined(GLEW_MX) && !defined(_WIN32)
+struct GLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_2;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_blend_minmax_factor;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_multi_draw_indirect;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles;
+GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_object_purgeable;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_row_bytes;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators;
+GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_base_instance;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compressed_texture_pixel_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_conservative_depth;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_get_program_binary;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader5;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_alignment;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_atomic_counters;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_load_store;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_420pack;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_packing;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_meminfo;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample_blit_scaled;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_provoking_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB_decode;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_snorm;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_attrib_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_EXT_x11_sync_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator;
+GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test;
+GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat;
+GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists;
+GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays;
+GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor;
+GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos;
+GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_coverage;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_path_rendering;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_barrier;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vdpau_interop;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_attrib_integer_64bit;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_buffer_unified_memory;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4;
+GLEW_VAR_EXPORT GLboolean __GLEW_NV_video_capture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format;
+GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample;
+GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample;
+GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints;
+GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates;
+GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list;
+GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog;
+GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint;
+
+#ifdef GLEW_MX
+}; /* GLEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------- */
+
+/* error codes */
+#define GLEW_OK 0
+#define GLEW_NO_ERROR 0
+#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */
+#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* Need at least OpenGL 1.1 */
+#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* Need at least GLX 1.2 */
+
+/* string codes */
+#define GLEW_VERSION 1
+#define GLEW_VERSION_MAJOR 2
+#define GLEW_VERSION_MINOR 3
+#define GLEW_VERSION_MICRO 4
+
+/* API */
+#ifdef GLEW_MX
+
+typedef struct GLEWContextStruct GLEWContext;
+GLEWAPI GLenum glewContextInit (GLEWContext* ctx);
+GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name);
+
+#define glewInit() glewContextInit(glewGetContext())
+#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x)
+#define glewIsExtensionSupported(x) glewIsSupported(x)
+
+#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x))
+#ifdef _WIN32
+# define GLEW_GET_FUN(x) glewGetContext()->x
+#else
+# define GLEW_GET_FUN(x) x
+#endif
+
+#else /* GLEW_MX */
+
+GLEWAPI GLenum glewInit ();
+GLEWAPI GLboolean glewIsSupported (const char* name);
+#define glewIsExtensionSupported(x) glewIsSupported(x)
+
+#define GLEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define GLEW_GET_FUN(x) x
+
+#endif /* GLEW_MX */
+
+GLEWAPI GLboolean glewExperimental;
+GLEWAPI GLboolean glewGetExtension (const char* name);
+GLEWAPI const GLubyte* glewGetErrorString (GLenum error);
+GLEWAPI const GLubyte* glewGetString (GLenum name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef GLEW_APIENTRY_DEFINED
+#undef GLEW_APIENTRY_DEFINED
+#undef APIENTRY
+#undef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#ifdef GLEW_CALLBACK_DEFINED
+#undef GLEW_CALLBACK_DEFINED
+#undef CALLBACK
+#endif
+
+#ifdef GLEW_WINGDIAPI_DEFINED
+#undef GLEW_WINGDIAPI_DEFINED
+#undef WINGDIAPI
+#endif
+
+#undef GLAPI
+/* #undef GLEWAPI */
+
+#endif /* __glew_h__ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glext.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glext.h
new file mode 100644
index 00000000..5a6dbc4c
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glext.h
@@ -0,0 +1,11163 @@
+#ifndef __glext_h_
+#define __glext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 28221 $ on $Date: 2014-09-18 20:11:05 -0700 (Thu, 18 Sep 2014) $
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#define GL_GLEXT_VERSION 20140918
+
+/* Generated C header for:
+ * API: gl
+ * Profile: compatibility
+ * Versions considered: .*
+ * Versions emitted: 1\.[2-9]|[234]\.[0-9]
+ * Default extensions included: gl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_VERSION_1_2 */
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, void *img);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum texture);
+GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, void *img);
+GLAPI void APIENTRY glClientActiveTexture (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1d (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1f (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1i (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1s (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2i (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2s (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m);
+#endif
+#endif /* GL_VERSION_1_3 */
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFogCoordf (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfv (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoordd (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddv (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointer (GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3i (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3iv (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3s (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3us (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glWindowPos2d (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2f (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2i (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos2s (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2sv (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3sv (const GLshort *v);
+GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void APIENTRY glBlendEquation (GLenum mode);
+#endif
+#endif /* GL_VERSION_1_4 */
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#include <stddef.h>
+typedef ptrdiff_t GLsizeiptr;
+typedef ptrdiff_t GLintptr;
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_COORD 0x8451
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC2_ALPHA 0x858A
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint id);
+GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQuery (GLenum target);
+GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer);
+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_VERSION_1_5 */
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+typedef char GLchar;
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_TEXTURE_COORDS 0x8871
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GLAPI void APIENTRY glCompileShader (GLuint shader);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum type);
+GLAPI void APIENTRY glDeleteProgram (GLuint program);
+GLAPI void APIENTRY glDeleteShader (GLuint shader);
+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
+GLAPI GLboolean APIENTRY glIsShader (GLuint shader);
+GLAPI void APIENTRY glLinkProgram (GLuint program);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GLAPI void APIENTRY glUseProgram (GLuint program);
+GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glValidateProgram (GLuint program);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_VERSION_2_0 */
+
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+#endif /* GL_VERSION_2_1 */
+
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_INDEX 0x8222
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_ALPHA_INTEGER 0x8D97
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glEnablei (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisablei (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedback (void);
+GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp);
+GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRender (void);
+GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
+GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmap (GLenum target);
+GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void *APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glBindVertexArray (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
+#endif
+#endif /* GL_VERSION_3_0 */
+
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index);
+GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif
+#endif /* GL_VERSION_3_1 */
+
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+typedef struct __GLsync *GLsync;
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glxext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GL_EXT_timer_query extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
+#endif
+#endif
+typedef uint64_t GLuint64;
+typedef int64_t GLint64;
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+GLAPI void APIENTRY glProvokingVertex (GLenum mode);
+GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GLAPI GLboolean APIENTRY glIsSync (GLsync sync);
+GLAPI void APIENTRY glDeleteSync (GLsync sync);
+GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+#endif
+#endif /* GL_VERSION_3_2 */
+
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_SRC1_COLOR 0x88F9
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+#define GL_INT_2_10_10_10_REV 0x8D9F
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler);
+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target);
+GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params);
+GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color);
+#endif
+#endif /* GL_VERSION_3_3 */
+
+#ifndef GL_VERSION_4_0
+#define GL_VERSION_4_0 1
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define GL_PATCHES 0x000E
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_ISOLINES 0x8E7A
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params);
+typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices);
+typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values);
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShading (GLfloat value);
+GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x);
+GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params);
+GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices);
+GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params);
+GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values);
+GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedback (void);
+GLAPI void APIENTRY glResumeTransformFeedback (void);
+GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id);
+GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream);
+GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id);
+GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif
+#endif /* GL_VERSION_4_0 */
+
+#ifndef GL_VERSION_4_1
+#define GL_VERSION_4_1 1
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_RGB565 0x8D62
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f);
+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReleaseShaderCompiler (void);
+GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GLAPI void APIENTRY glClearDepthf (GLfloat d);
+GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0);
+GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v);
+GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f);
+GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data);
+#endif
+#endif /* GL_VERSION_4_1 */
+
+#ifndef GL_VERSION_4_2
+#define GL_VERSION_4_2 1
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers);
+GLAPI void APIENTRY glTexStorage1D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount);
+GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#endif
+#endif /* GL_VERSION_4_2 */
+
+#ifndef GL_VERSION_4_3
+#define GL_VERSION_4_3 1
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_MAX_WIDTH 0x827E
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_MIPMAP 0x8293
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_COLOR_ENCODING 0x8296
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_FILTER 0x829A
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_DISPLAY_LIST 0x82E7
+typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level);
+GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer);
+GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GLAPI void APIENTRY glPopDebugGroup (void);
+GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_VERSION_4_3 */
+
+#ifndef GL_VERSION_4_4
+#define GL_VERSION_4_4 1
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define GL_MAP_PERSISTENT_BIT 0x0040
+#define GL_MAP_COHERENT_BIT 0x0080
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+#define GL_CLEAR_TEXTURE 0x9365
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferStorage (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glClearTexImage (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glBindBuffersBase (GLenum target, GLuint first, GLsizei count, const GLuint *buffers);
+GLAPI void APIENTRY glBindBuffersRange (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+GLAPI void APIENTRY glBindTextures (GLuint first, GLsizei count, const GLuint *textures);
+GLAPI void APIENTRY glBindSamplers (GLuint first, GLsizei count, const GLuint *samplers);
+GLAPI void APIENTRY glBindImageTextures (GLuint first, GLsizei count, const GLuint *textures);
+GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+#endif
+#endif /* GL_VERSION_4_4 */
+
+#ifndef GL_VERSION_4_5
+#define GL_VERSION_4_5 1
+#define GL_CONTEXT_LOST 0x0507
+#define GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define GL_ZERO_TO_ONE 0x935F
+#define GL_CLIP_ORIGIN 0x935C
+#define GL_CLIP_DEPTH_MODE 0x935D
+#define GL_QUERY_WAIT_INVERTED 0x8E17
+#define GL_QUERY_NO_WAIT_INVERTED 0x8E18
+#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
+#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
+#define GL_MAX_CULL_DISTANCES 0x82F9
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define GL_TEXTURE_TARGET 0x1006
+#define GL_QUERY_TARGET 0x82EA
+#define GL_TEXTURE_BINDING 0x82EB
+#define GL_GUILTY_CONTEXT_RESET 0x8253
+#define GL_INNOCENT_CONTEXT_RESET 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET 0x8252
+#define GL_NO_RESET_NOTIFICATION 0x8261
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+typedef void (APIENTRYP PFNGLCLIPCONTROLPROC) (GLenum origin, GLenum depth);
+typedef void (APIENTRYP PFNGLCREATETRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) (GLuint xfb, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizei size);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKIVPROC) (GLuint xfb, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
+typedef void (APIENTRYP PFNGLCREATEBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEPROC) (GLuint buffer, GLsizei size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAPROC) (GLuint buffer, GLsizei size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizei size, const void *data);
+typedef void (APIENTRYP PFNGLCOPYNAMEDBUFFERSUBDATAPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizei size);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizei size, GLenum format, GLenum type, const void *data);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERPROC) (GLuint buffer, GLenum access);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizei length, GLbitfield access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizei length);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) (GLuint buffer, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVPROC) (GLuint buffer, GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizei size, void *data);
+typedef void (APIENTRYP PFNGLCREATEFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) (GLuint framebuffer, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) (GLuint framebuffer, GLenum buf);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) (GLuint framebuffer, GLenum src);
+typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, const GLfloat depth, GLint stencil);
+typedef void (APIENTRYP PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCREATERENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) (GLuint renderbuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCREATETEXTURESPROC) (GLenum target, GLsizei n, GLuint *textures);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERPROC) (GLuint texture, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEPROC) (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizei size);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFPROC) (GLuint texture, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIPROC) (GLuint texture, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLBINDTEXTUREUNITPROC) (GLuint unit, GLuint texture);
+typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVPROC) (GLuint texture, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVPROC) (GLuint texture, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCREATEVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLVERTEXARRAYELEMENTBUFFERPROC) (GLuint vaobj, GLuint buffer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBUFFERPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBUFFERSPROC) (GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBBINDINGPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBIFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBLFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYBINDINGDIVISORPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYIVPROC) (GLuint vaobj, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINDEXEDIVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINDEXED64IVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint64 *param);
+typedef void (APIENTRYP PFNGLCREATESAMPLERSPROC) (GLsizei n, GLuint *samplers);
+typedef void (APIENTRYP PFNGLCREATEPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef void (APIENTRYP PFNGLCREATEQUERIESPROC) (GLenum target, GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (APIENTRYP PFNGLGETTEXTURESUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels);
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (APIENTRYP PFNGLGETNMAPDVPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+typedef void (APIENTRYP PFNGLGETNMAPFVPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETNMAPIVPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPFVPROC) (GLenum map, GLsizei bufSize, GLfloat *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVPROC) (GLenum map, GLsizei bufSize, GLuint *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVPROC) (GLenum map, GLsizei bufSize, GLushort *values);
+typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEPROC) (GLsizei bufSize, GLubyte *pattern);
+typedef void (APIENTRYP PFNGLGETNCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+typedef void (APIENTRYP PFNGLGETNHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLGETNMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLTEXTUREBARRIERPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClipControl (GLenum origin, GLenum depth);
+GLAPI void APIENTRY glCreateTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glTransformFeedbackBufferBase (GLuint xfb, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackBufferRange (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizei size);
+GLAPI void APIENTRY glGetTransformFeedbackiv (GLuint xfb, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetTransformFeedbacki_v (GLuint xfb, GLenum pname, GLuint index, GLint *param);
+GLAPI void APIENTRY glGetTransformFeedbacki64_v (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
+GLAPI void APIENTRY glCreateBuffers (GLsizei n, GLuint *buffers);
+GLAPI void APIENTRY glNamedBufferStorage (GLuint buffer, GLsizei size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glNamedBufferData (GLuint buffer, GLsizei size, const void *data, GLenum usage);
+GLAPI void APIENTRY glNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizei size, const void *data);
+GLAPI void APIENTRY glCopyNamedBufferSubData (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizei size);
+GLAPI void APIENTRY glClearNamedBufferData (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferSubData (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizei size, GLenum format, GLenum type, const void *data);
+GLAPI void *APIENTRY glMapNamedBuffer (GLuint buffer, GLenum access);
+GLAPI void *APIENTRY glMapNamedBufferRange (GLuint buffer, GLintptr offset, GLsizei length, GLbitfield access);
+GLAPI GLboolean APIENTRY glUnmapNamedBuffer (GLuint buffer);
+GLAPI void APIENTRY glFlushMappedNamedBufferRange (GLuint buffer, GLintptr offset, GLsizei length);
+GLAPI void APIENTRY glGetNamedBufferParameteriv (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedBufferParameteri64v (GLuint buffer, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetNamedBufferPointerv (GLuint buffer, GLenum pname, void **params);
+GLAPI void APIENTRY glGetNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizei size, void *data);
+GLAPI void APIENTRY glCreateFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI void APIENTRY glNamedFramebufferRenderbuffer (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glNamedFramebufferParameteri (GLuint framebuffer, GLenum pname, GLint param);
+GLAPI void APIENTRY glNamedFramebufferTexture (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTextureLayer (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glNamedFramebufferDrawBuffer (GLuint framebuffer, GLenum buf);
+GLAPI void APIENTRY glNamedFramebufferDrawBuffers (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glNamedFramebufferReadBuffer (GLuint framebuffer, GLenum src);
+GLAPI void APIENTRY glInvalidateNamedFramebufferData (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateNamedFramebufferSubData (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glClearNamedFramebufferiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearNamedFramebufferuiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearNamedFramebufferfv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, const GLfloat depth, GLint stencil);
+GLAPI void APIENTRY glBlitNamedFramebuffer (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI GLenum APIENTRY glCheckNamedFramebufferStatus (GLuint framebuffer, GLenum target);
+GLAPI void APIENTRY glGetNamedFramebufferParameteriv (GLuint framebuffer, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameteriv (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glCreateRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glNamedRenderbufferStorage (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisample (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetNamedRenderbufferParameteriv (GLuint renderbuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glCreateTextures (GLenum target, GLsizei n, GLuint *textures);
+GLAPI void APIENTRY glTextureBuffer (GLuint texture, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glTextureBufferRange (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizei size);
+GLAPI void APIENTRY glTextureStorage1D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTextureStorage2D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureStorage3D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glTextureStorage2DMultisample (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage3DMultisample (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCompressedTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCopyTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glCopyTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureParameterf (GLuint texture, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glTextureParameterfv (GLuint texture, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glTextureParameteri (GLuint texture, GLenum pname, GLint param);
+GLAPI void APIENTRY glTextureParameterIiv (GLuint texture, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureParameterIuiv (GLuint texture, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glTextureParameteriv (GLuint texture, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glGenerateTextureMipmap (GLuint texture);
+GLAPI void APIENTRY glBindTextureUnit (GLuint unit, GLuint texture);
+GLAPI void APIENTRY glGetTextureImage (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetCompressedTextureImage (GLuint texture, GLint level, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetTextureLevelParameterfv (GLuint texture, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureLevelParameteriv (GLuint texture, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterfv (GLuint texture, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureParameterIiv (GLuint texture, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterIuiv (GLuint texture, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glGetTextureParameteriv (GLuint texture, GLenum pname, GLint *params);
+GLAPI void APIENTRY glCreateVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI void APIENTRY glDisableVertexArrayAttrib (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glEnableVertexArrayAttrib (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glVertexArrayElementBuffer (GLuint vaobj, GLuint buffer);
+GLAPI void APIENTRY glVertexArrayVertexBuffer (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexArrayVertexBuffers (GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+GLAPI void APIENTRY glVertexArrayAttribBinding (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexArrayAttribFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayAttribIFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayAttribLFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayBindingDivisor (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glGetVertexArrayiv (GLuint vaobj, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayIndexediv (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayIndexed64iv (GLuint vaobj, GLuint index, GLenum pname, GLint64 *param);
+GLAPI void APIENTRY glCreateSamplers (GLsizei n, GLuint *samplers);
+GLAPI void APIENTRY glCreateProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI void APIENTRY glCreateQueries (GLenum target, GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GLAPI void APIENTRY glGetTextureSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetCompressedTextureSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels);
+GLAPI GLenum APIENTRY glGetGraphicsResetStatus (void);
+GLAPI void APIENTRY glGetnCompressedTexImage (GLenum target, GLint lod, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetnTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetnUniformdv (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+GLAPI void APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GLAPI void APIENTRY glGetnMapdv (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+GLAPI void APIENTRY glGetnMapfv (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+GLAPI void APIENTRY glGetnMapiv (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+GLAPI void APIENTRY glGetnPixelMapfv (GLenum map, GLsizei bufSize, GLfloat *values);
+GLAPI void APIENTRY glGetnPixelMapuiv (GLenum map, GLsizei bufSize, GLuint *values);
+GLAPI void APIENTRY glGetnPixelMapusv (GLenum map, GLsizei bufSize, GLushort *values);
+GLAPI void APIENTRY glGetnPolygonStipple (GLsizei bufSize, GLubyte *pattern);
+GLAPI void APIENTRY glGetnColorTable (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+GLAPI void APIENTRY glGetnConvolutionFilter (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+GLAPI void APIENTRY glGetnSeparableFilter (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+GLAPI void APIENTRY glGetnHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glGetnMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glTextureBarrier (void);
+#endif
+#endif /* GL_VERSION_4_5 */
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_ARB_ES2_compatibility 1
+#endif /* GL_ARB_ES2_compatibility */
+
+#ifndef GL_ARB_ES3_1_compatibility
+#define GL_ARB_ES3_1_compatibility 1
+#endif /* GL_ARB_ES3_1_compatibility */
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_ARB_ES3_compatibility 1
+#endif /* GL_ARB_ES3_compatibility */
+
+#ifndef GL_ARB_arrays_of_arrays
+#define GL_ARB_arrays_of_arrays 1
+#endif /* GL_ARB_arrays_of_arrays */
+
+#ifndef GL_ARB_base_instance
+#define GL_ARB_base_instance 1
+#endif /* GL_ARB_base_instance */
+
+#ifndef GL_ARB_bindless_texture
+#define GL_ARB_bindless_texture 1
+typedef uint64_t GLuint64EXT;
+#define GL_UNSIGNED_INT64_ARB 0x140F
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleARB (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleARB (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentARB (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleARB (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentARB (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64ARB (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64ARB (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentARB (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glVertexAttribL1ui64ARB (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL1ui64vARB (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLui64vARB (GLuint index, GLenum pname, GLuint64EXT *params);
+#endif
+#endif /* GL_ARB_bindless_texture */
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_ARB_blend_func_extended 1
+#endif /* GL_ARB_blend_func_extended */
+
+#ifndef GL_ARB_buffer_storage
+#define GL_ARB_buffer_storage 1
+#endif /* GL_ARB_buffer_storage */
+
+#ifndef GL_ARB_cl_event
+#define GL_ARB_cl_event 1
+struct _cl_context;
+struct _cl_event;
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context *context, struct _cl_event *event, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context *context, struct _cl_event *event, GLbitfield flags);
+#endif
+#endif /* GL_ARB_cl_event */
+
+#ifndef GL_ARB_clear_buffer_object
+#define GL_ARB_clear_buffer_object 1
+#endif /* GL_ARB_clear_buffer_object */
+
+#ifndef GL_ARB_clear_texture
+#define GL_ARB_clear_texture 1
+#endif /* GL_ARB_clear_texture */
+
+#ifndef GL_ARB_clip_control
+#define GL_ARB_clip_control 1
+#endif /* GL_ARB_clip_control */
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp);
+#endif
+#endif /* GL_ARB_color_buffer_float */
+
+#ifndef GL_ARB_compatibility
+#define GL_ARB_compatibility 1
+#endif /* GL_ARB_compatibility */
+
+#ifndef GL_ARB_compressed_texture_pixel_storage
+#define GL_ARB_compressed_texture_pixel_storage 1
+#endif /* GL_ARB_compressed_texture_pixel_storage */
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+#endif /* GL_ARB_compute_shader */
+
+#ifndef GL_ARB_compute_variable_group_size
+#define GL_ARB_compute_variable_group_size 1
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344
+#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345
+#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDispatchComputeGroupSizeARB (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+#endif
+#endif /* GL_ARB_compute_variable_group_size */
+
+#ifndef GL_ARB_conditional_render_inverted
+#define GL_ARB_conditional_render_inverted 1
+#endif /* GL_ARB_conditional_render_inverted */
+
+#ifndef GL_ARB_conservative_depth
+#define GL_ARB_conservative_depth 1
+#endif /* GL_ARB_conservative_depth */
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+#endif /* GL_ARB_copy_buffer */
+
+#ifndef GL_ARB_copy_image
+#define GL_ARB_copy_image 1
+#endif /* GL_ARB_copy_image */
+
+#ifndef GL_ARB_cull_distance
+#define GL_ARB_cull_distance 1
+#endif /* GL_ARB_cull_distance */
+
+#ifndef GL_ARB_debug_output
+#define GL_ARB_debug_output 1
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif
+#endif /* GL_ARB_debug_output */
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_ARB_depth_buffer_float 1
+#endif /* GL_ARB_depth_buffer_float */
+
+#ifndef GL_ARB_depth_clamp
+#define GL_ARB_depth_clamp 1
+#endif /* GL_ARB_depth_clamp */
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#endif /* GL_ARB_depth_texture */
+
+#ifndef GL_ARB_derivative_control
+#define GL_ARB_derivative_control 1
+#endif /* GL_ARB_derivative_control */
+
+#ifndef GL_ARB_direct_state_access
+#define GL_ARB_direct_state_access 1
+#endif /* GL_ARB_direct_state_access */
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersARB (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_ARB_draw_buffers */
+
+#ifndef GL_ARB_draw_buffers_blend
+#define GL_ARB_draw_buffers_blend 1
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+#endif /* GL_ARB_draw_buffers_blend */
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#define GL_ARB_draw_elements_base_vertex 1
+#endif /* GL_ARB_draw_elements_base_vertex */
+
+#ifndef GL_ARB_draw_indirect
+#define GL_ARB_draw_indirect 1
+#endif /* GL_ARB_draw_indirect */
+
+#ifndef GL_ARB_draw_instanced
+#define GL_ARB_draw_instanced 1
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_ARB_draw_instanced */
+
+#ifndef GL_ARB_enhanced_layouts
+#define GL_ARB_enhanced_layouts 1
+#endif /* GL_ARB_enhanced_layouts */
+
+#ifndef GL_ARB_explicit_attrib_location
+#define GL_ARB_explicit_attrib_location 1
+#endif /* GL_ARB_explicit_attrib_location */
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_ARB_explicit_uniform_location 1
+#endif /* GL_ARB_explicit_uniform_location */
+
+#ifndef GL_ARB_fragment_coord_conventions
+#define GL_ARB_fragment_coord_conventions 1
+#endif /* GL_ARB_fragment_coord_conventions */
+
+#ifndef GL_ARB_fragment_layer_viewport
+#define GL_ARB_fragment_layer_viewport 1
+#endif /* GL_ARB_fragment_layer_viewport */
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string);
+typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramStringARB (GLenum target, GLenum format, GLsizei len, const void *string);
+GLAPI void APIENTRY glBindProgramARB (GLenum target, GLuint program);
+GLAPI void APIENTRY glDeleteProgramsARB (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glGenProgramsARB (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringARB (GLenum target, GLenum pname, void *string);
+GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
+#endif
+#endif /* GL_ARB_fragment_program */
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+#endif /* GL_ARB_fragment_program_shadow */
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif /* GL_ARB_fragment_shader */
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_ARB_framebuffer_no_attachments 1
+#endif /* GL_ARB_framebuffer_no_attachments */
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_ARB_framebuffer_object 1
+#endif /* GL_ARB_framebuffer_object */
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_ARB_framebuffer_sRGB 1
+#endif /* GL_ARB_framebuffer_sRGB */
+
+#ifndef GL_ARB_geometry_shader4
+#define GL_ARB_geometry_shader4 1
+#define GL_LINES_ADJACENCY_ARB 0x000A
+#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
+#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+#endif /* GL_ARB_geometry_shader4 */
+
+#ifndef GL_ARB_get_program_binary
+#define GL_ARB_get_program_binary 1
+#endif /* GL_ARB_get_program_binary */
+
+#ifndef GL_ARB_get_texture_sub_image
+#define GL_ARB_get_texture_sub_image 1
+#endif /* GL_ARB_get_texture_sub_image */
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_ARB_gpu_shader5 1
+#endif /* GL_ARB_gpu_shader5 */
+
+#ifndef GL_ARB_gpu_shader_fp64
+#define GL_ARB_gpu_shader_fp64 1
+#endif /* GL_ARB_gpu_shader_fp64 */
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+typedef unsigned short GLhalfARB;
+#define GL_HALF_FLOAT_ARB 0x140B
+#endif /* GL_ARB_half_float_pixel */
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_ARB_half_float_vertex 1
+#endif /* GL_ARB_half_float_vertex */
+
+#ifndef GL_ARB_imaging
+#define GL_ARB_imaging 1
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_EQUATION 0x8009
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, void *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTable (GLenum target, GLenum format, GLenum type, void *table);
+GLAPI void APIENTRY glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteri (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, void *image);
+GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilter (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+GLAPI void APIENTRY glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+GLAPI void APIENTRY glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmax (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogram (GLenum target);
+GLAPI void APIENTRY glResetMinmax (GLenum target);
+#endif
+#endif /* GL_ARB_imaging */
+
+#ifndef GL_ARB_indirect_parameters
+#define GL_ARB_indirect_parameters 1
+#define GL_PARAMETER_BUFFER_ARB 0x80EE
+#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#endif
+#endif /* GL_ARB_indirect_parameters */
+
+#ifndef GL_ARB_instanced_arrays
+#define GL_ARB_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_ARB_instanced_arrays */
+
+#ifndef GL_ARB_internalformat_query
+#define GL_ARB_internalformat_query 1
+#endif /* GL_ARB_internalformat_query */
+
+#ifndef GL_ARB_internalformat_query2
+#define GL_ARB_internalformat_query2 1
+#define GL_SRGB_DECODE_ARB 0x8299
+#endif /* GL_ARB_internalformat_query2 */
+
+#ifndef GL_ARB_invalidate_subdata
+#define GL_ARB_invalidate_subdata 1
+#endif /* GL_ARB_invalidate_subdata */
+
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_ARB_map_buffer_alignment 1
+#endif /* GL_ARB_map_buffer_alignment */
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+#endif /* GL_ARB_map_buffer_range */
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint index);
+GLAPI void APIENTRY glMatrixIndexubvARB (GLint size, const GLubyte *indices);
+GLAPI void APIENTRY glMatrixIndexusvARB (GLint size, const GLushort *indices);
+GLAPI void APIENTRY glMatrixIndexuivARB (GLint size, const GLuint *indices);
+GLAPI void APIENTRY glMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_ARB_matrix_palette */
+
+#ifndef GL_ARB_multi_bind
+#define GL_ARB_multi_bind 1
+#endif /* GL_ARB_multi_bind */
+
+#ifndef GL_ARB_multi_draw_indirect
+#define GL_ARB_multi_draw_indirect 1
+#endif /* GL_ARB_multi_draw_indirect */
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLfloat value, GLboolean invert);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleCoverageARB (GLfloat value, GLboolean invert);
+#endif
+#endif /* GL_ARB_multisample */
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glClientActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum target, const GLshort *v);
+#endif
+#endif /* GL_ARB_multitexture */
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueriesARB (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueriesARB (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQueryARB (GLuint id);
+GLAPI void APIENTRY glBeginQueryARB (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQueryARB (GLenum target);
+GLAPI void APIENTRY glGetQueryivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_ARB_occlusion_query */
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ARB_occlusion_query2 1
+#endif /* GL_ARB_occlusion_query2 */
+
+#ifndef GL_ARB_pipeline_statistics_query
+#define GL_ARB_pipeline_statistics_query 1
+#define GL_VERTICES_SUBMITTED_ARB 0x82EE
+#define GL_PRIMITIVES_SUBMITTED_ARB 0x82EF
+#define GL_VERTEX_SHADER_INVOCATIONS_ARB 0x82F0
+#define GL_TESS_CONTROL_SHADER_PATCHES_ARB 0x82F1
+#define GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB 0x82F2
+#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB 0x82F3
+#define GL_FRAGMENT_SHADER_INVOCATIONS_ARB 0x82F4
+#define GL_COMPUTE_SHADER_INVOCATIONS_ARB 0x82F5
+#define GL_CLIPPING_INPUT_PRIMITIVES_ARB 0x82F6
+#define GL_CLIPPING_OUTPUT_PRIMITIVES_ARB 0x82F7
+#endif /* GL_ARB_pipeline_statistics_query */
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#endif /* GL_ARB_pixel_buffer_object */
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfARB (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_ARB_point_parameters */
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+#endif /* GL_ARB_point_sprite */
+
+#ifndef GL_ARB_program_interface_query
+#define GL_ARB_program_interface_query 1
+#endif /* GL_ARB_program_interface_query */
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_ARB_provoking_vertex 1
+#endif /* GL_ARB_provoking_vertex */
+
+#ifndef GL_ARB_query_buffer_object
+#define GL_ARB_query_buffer_object 1
+#endif /* GL_ARB_query_buffer_object */
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#define GL_ARB_robust_buffer_access_behavior 1
+#endif /* GL_ARB_robust_buffer_access_behavior */
+
+#ifndef GL_ARB_robustness
+#define GL_ARB_robustness 1
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img);
+typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void *img);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+typedef void (APIENTRYP PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values);
+typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern);
+typedef void (APIENTRYP PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+typedef void (APIENTRYP PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void);
+GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img);
+GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, void *img);
+GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+GLAPI void APIENTRY glGetnMapdvARB (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+GLAPI void APIENTRY glGetnMapfvARB (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+GLAPI void APIENTRY glGetnMapivARB (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+GLAPI void APIENTRY glGetnPixelMapfvARB (GLenum map, GLsizei bufSize, GLfloat *values);
+GLAPI void APIENTRY glGetnPixelMapuivARB (GLenum map, GLsizei bufSize, GLuint *values);
+GLAPI void APIENTRY glGetnPixelMapusvARB (GLenum map, GLsizei bufSize, GLushort *values);
+GLAPI void APIENTRY glGetnPolygonStippleARB (GLsizei bufSize, GLubyte *pattern);
+GLAPI void APIENTRY glGetnColorTableARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+GLAPI void APIENTRY glGetnConvolutionFilterARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+GLAPI void APIENTRY glGetnSeparableFilterARB (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+GLAPI void APIENTRY glGetnHistogramARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+#endif
+#endif /* GL_ARB_robustness */
+
+#ifndef GL_ARB_robustness_isolation
+#define GL_ARB_robustness_isolation 1
+#endif /* GL_ARB_robustness_isolation */
+
+#ifndef GL_ARB_sample_shading
+#define GL_ARB_sample_shading 1
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
+#endif
+#endif /* GL_ARB_sample_shading */
+
+#ifndef GL_ARB_sampler_objects
+#define GL_ARB_sampler_objects 1
+#endif /* GL_ARB_sampler_objects */
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_ARB_seamless_cube_map 1
+#endif /* GL_ARB_seamless_cube_map */
+
+#ifndef GL_ARB_seamless_cubemap_per_texture
+#define GL_ARB_seamless_cubemap_per_texture 1
+#endif /* GL_ARB_seamless_cubemap_per_texture */
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_ARB_separate_shader_objects 1
+#endif /* GL_ARB_separate_shader_objects */
+
+#ifndef GL_ARB_shader_atomic_counters
+#define GL_ARB_shader_atomic_counters 1
+#endif /* GL_ARB_shader_atomic_counters */
+
+#ifndef GL_ARB_shader_bit_encoding
+#define GL_ARB_shader_bit_encoding 1
+#endif /* GL_ARB_shader_bit_encoding */
+
+#ifndef GL_ARB_shader_draw_parameters
+#define GL_ARB_shader_draw_parameters 1
+#endif /* GL_ARB_shader_draw_parameters */
+
+#ifndef GL_ARB_shader_group_vote
+#define GL_ARB_shader_group_vote 1
+#endif /* GL_ARB_shader_group_vote */
+
+#ifndef GL_ARB_shader_image_load_store
+#define GL_ARB_shader_image_load_store 1
+#endif /* GL_ARB_shader_image_load_store */
+
+#ifndef GL_ARB_shader_image_size
+#define GL_ARB_shader_image_size 1
+#endif /* GL_ARB_shader_image_size */
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef char GLcharARB;
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB obj);
+GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum pname);
+GLAPI void APIENTRY glDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj);
+GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum shaderType);
+GLAPI void APIENTRY glShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length);
+GLAPI void APIENTRY glCompileShaderARB (GLhandleARB shaderObj);
+GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj);
+GLAPI void APIENTRY glLinkProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB programObj);
+GLAPI void APIENTRY glValidateProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUniform1fARB (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2fARB (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1iARB (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2iARB (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params);
+GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+#endif /* GL_ARB_shader_objects */
+
+#ifndef GL_ARB_shader_precision
+#define GL_ARB_shader_precision 1
+#endif /* GL_ARB_shader_precision */
+
+#ifndef GL_ARB_shader_stencil_export
+#define GL_ARB_shader_stencil_export 1
+#endif /* GL_ARB_shader_stencil_export */
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_ARB_shader_storage_buffer_object 1
+#endif /* GL_ARB_shader_storage_buffer_object */
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ARB_shader_subroutine 1
+#endif /* GL_ARB_shader_subroutine */
+
+#ifndef GL_ARB_shader_texture_image_samples
+#define GL_ARB_shader_texture_image_samples 1
+#endif /* GL_ARB_shader_texture_image_samples */
+
+#ifndef GL_ARB_shader_texture_lod
+#define GL_ARB_shader_texture_lod 1
+#endif /* GL_ARB_shader_texture_lod */
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#endif /* GL_ARB_shading_language_100 */
+
+#ifndef GL_ARB_shading_language_420pack
+#define GL_ARB_shading_language_420pack 1
+#endif /* GL_ARB_shading_language_420pack */
+
+#ifndef GL_ARB_shading_language_include
+#define GL_ARB_shading_language_include 1
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length);
+GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ARB_shading_language_include */
+
+#ifndef GL_ARB_shading_language_packing
+#define GL_ARB_shading_language_packing 1
+#endif /* GL_ARB_shading_language_packing */
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+#endif /* GL_ARB_shadow */
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#endif /* GL_ARB_shadow_ambient */
+
+#ifndef GL_ARB_sparse_buffer
+#define GL_ARB_sparse_buffer 1
+#define GL_SPARSE_STORAGE_BIT_ARB 0x0400
+#define GL_SPARSE_BUFFER_PAGE_SIZE_ARB 0x82F8
+typedef void (APIENTRYP PFNGLBUFFERPAGECOMMITMENTARBPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLboolean commit);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTARBPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferPageCommitmentARB (GLenum target, GLintptr offset, GLsizeiptr size, GLboolean commit);
+GLAPI void APIENTRY glNamedBufferPageCommitmentEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+GLAPI void APIENTRY glNamedBufferPageCommitmentARB (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+#endif
+#endif /* GL_ARB_sparse_buffer */
+
+#ifndef GL_ARB_sparse_texture
+#define GL_ARB_sparse_texture 1
+#define GL_TEXTURE_SPARSE_ARB 0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7
+#define GL_NUM_SPARSE_LEVELS_ARB 0x91AA
+#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
+typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+#endif
+#endif /* GL_ARB_sparse_texture */
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_ARB_stencil_texturing 1
+#endif /* GL_ARB_stencil_texturing */
+
+#ifndef GL_ARB_sync
+#define GL_ARB_sync 1
+#endif /* GL_ARB_sync */
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_ARB_tessellation_shader 1
+#endif /* GL_ARB_tessellation_shader */
+
+#ifndef GL_ARB_texture_barrier
+#define GL_ARB_texture_barrier 1
+#endif /* GL_ARB_texture_barrier */
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+#endif /* GL_ARB_texture_border_clamp */
+
+#ifndef GL_ARB_texture_buffer_object
+#define GL_ARB_texture_buffer_object 1
+#define GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+#endif /* GL_ARB_texture_buffer_object */
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+#define GL_ARB_texture_buffer_object_rgb32 1
+#endif /* GL_ARB_texture_buffer_object_rgb32 */
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_ARB_texture_buffer_range 1
+#endif /* GL_ARB_texture_buffer_range */
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void *img);
+#endif
+#endif /* GL_ARB_texture_compression */
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_ARB_texture_compression_bptc 1
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+#endif /* GL_ARB_texture_compression_bptc */
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc 1
+#endif /* GL_ARB_texture_compression_rgtc */
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#endif /* GL_ARB_texture_cube_map */
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_ARB_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#endif /* GL_ARB_texture_cube_map_array */
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif /* GL_ARB_texture_env_add */
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#endif /* GL_ARB_texture_env_combine */
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+#endif /* GL_ARB_texture_env_crossbar */
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+#endif /* GL_ARB_texture_env_dot3 */
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#endif /* GL_ARB_texture_float */
+
+#ifndef GL_ARB_texture_gather
+#define GL_ARB_texture_gather 1
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+#endif /* GL_ARB_texture_gather */
+
+#ifndef GL_ARB_texture_mirror_clamp_to_edge
+#define GL_ARB_texture_mirror_clamp_to_edge 1
+#endif /* GL_ARB_texture_mirror_clamp_to_edge */
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+#ifndef GL_ARB_texture_multisample
+#define GL_ARB_texture_multisample 1
+#endif /* GL_ARB_texture_multisample */
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+#endif /* GL_ARB_texture_non_power_of_two */
+
+#ifndef GL_ARB_texture_query_levels
+#define GL_ARB_texture_query_levels 1
+#endif /* GL_ARB_texture_query_levels */
+
+#ifndef GL_ARB_texture_query_lod
+#define GL_ARB_texture_query_lod 1
+#endif /* GL_ARB_texture_query_lod */
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif /* GL_ARB_texture_rectangle */
+
+#ifndef GL_ARB_texture_rg
+#define GL_ARB_texture_rg 1
+#endif /* GL_ARB_texture_rg */
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_ARB_texture_rgb10_a2ui 1
+#endif /* GL_ARB_texture_rgb10_a2ui */
+
+#ifndef GL_ARB_texture_stencil8
+#define GL_ARB_texture_stencil8 1
+#endif /* GL_ARB_texture_stencil8 */
+
+#ifndef GL_ARB_texture_storage
+#define GL_ARB_texture_storage 1
+#endif /* GL_ARB_texture_storage */
+
+#ifndef GL_ARB_texture_storage_multisample
+#define GL_ARB_texture_storage_multisample 1
+#endif /* GL_ARB_texture_storage_multisample */
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_ARB_texture_swizzle 1
+#endif /* GL_ARB_texture_swizzle */
+
+#ifndef GL_ARB_texture_view
+#define GL_ARB_texture_view 1
+#endif /* GL_ARB_texture_view */
+
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+#endif /* GL_ARB_timer_query */
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_ARB_transform_feedback2 1
+#endif /* GL_ARB_transform_feedback2 */
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_ARB_transform_feedback3 1
+#endif /* GL_ARB_transform_feedback3 */
+
+#ifndef GL_ARB_transform_feedback_instanced
+#define GL_ARB_transform_feedback_instanced 1
+#endif /* GL_ARB_transform_feedback_instanced */
+
+#ifndef GL_ARB_transform_feedback_overflow_query
+#define GL_ARB_transform_feedback_overflow_query 1
+#define GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB 0x82EC
+#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB 0x82ED
+#endif /* GL_ARB_transform_feedback_overflow_query */
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m);
+#endif
+#endif /* GL_ARB_transpose_matrix */
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_ARB_uniform_buffer_object 1
+#endif /* GL_ARB_uniform_buffer_object */
+
+#ifndef GL_ARB_vertex_array_bgra
+#define GL_ARB_vertex_array_bgra 1
+#endif /* GL_ARB_vertex_array_bgra */
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_ARB_vertex_array_object 1
+#endif /* GL_ARB_vertex_array_object */
+
+#ifndef GL_ARB_vertex_attrib_64bit
+#define GL_ARB_vertex_attrib_64bit 1
+#endif /* GL_ARB_vertex_attrib_64bit */
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_ARB_vertex_attrib_binding 1
+#endif /* GL_ARB_vertex_attrib_binding */
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWeightbvARB (GLint size, const GLbyte *weights);
+GLAPI void APIENTRY glWeightsvARB (GLint size, const GLshort *weights);
+GLAPI void APIENTRY glWeightivARB (GLint size, const GLint *weights);
+GLAPI void APIENTRY glWeightfvARB (GLint size, const GLfloat *weights);
+GLAPI void APIENTRY glWeightdvARB (GLint size, const GLdouble *weights);
+GLAPI void APIENTRY glWeightubvARB (GLint size, const GLubyte *weights);
+GLAPI void APIENTRY glWeightusvARB (GLint size, const GLushort *weights);
+GLAPI void APIENTRY glWeightuivARB (GLint size, const GLuint *weights);
+GLAPI void APIENTRY glWeightPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glVertexBlendARB (GLint count);
+#endif
+#endif /* GL_ARB_vertex_blend */
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+typedef ptrdiff_t GLsizeiptrARB;
+typedef ptrdiff_t GLintptrARB;
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data);
+typedef void *(APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBufferARB (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffersARB (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffersARB (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBufferARB (GLuint buffer);
+GLAPI void APIENTRY glBufferDataARB (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data);
+GLAPI void APIENTRY glGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data);
+GLAPI void *APIENTRY glMapBufferARB (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum target);
+GLAPI void APIENTRY glGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointervARB (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_ARB_vertex_buffer_object */
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttrib1dARB (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fARB (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sARB (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sARB (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint index, GLenum pname, void **pointer);
+#endif
+#endif /* GL_ARB_vertex_program */
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name);
+#endif
+#endif /* GL_ARB_vertex_shader */
+
+#ifndef GL_ARB_vertex_type_10f_11f_11f_rev
+#define GL_ARB_vertex_type_10f_11f_11f_rev 1
+#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+#endif /* GL_ARB_vertex_type_2_10_10_10_rev */
+
+#ifndef GL_ARB_viewport_array
+#define GL_ARB_viewport_array 1
+#endif /* GL_ARB_viewport_array */
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dARB (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fARB (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iARB (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sARB (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svARB (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iARB (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sARB (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v);
+#endif
+#endif /* GL_ARB_window_pos */
+
+#ifndef GL_KHR_blend_equation_advanced
+#define GL_KHR_blend_equation_advanced 1
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_SCREEN_KHR 0x9295
+#define GL_OVERLAY_KHR 0x9296
+#define GL_DARKEN_KHR 0x9297
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLORBURN_KHR 0x929A
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_EXCLUSION_KHR 0x92A0
+#define GL_HSL_HUE_KHR 0x92AD
+#define GL_HSL_SATURATION_KHR 0x92AE
+#define GL_HSL_COLOR_KHR 0x92AF
+#define GL_HSL_LUMINOSITY_KHR 0x92B0
+typedef void (APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendBarrierKHR (void);
+#endif
+#endif /* GL_KHR_blend_equation_advanced */
+
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_KHR_context_flush_control 1
+#endif /* GL_KHR_context_flush_control */
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#endif /* GL_KHR_debug */
+
+#ifndef GL_KHR_robust_buffer_access_behavior
+#define GL_KHR_robust_buffer_access_behavior 1
+#endif /* GL_KHR_robust_buffer_access_behavior */
+
+#ifndef GL_KHR_robustness
+#define GL_KHR_robustness 1
+#define GL_CONTEXT_ROBUST_ACCESS 0x90F3
+#endif /* GL_KHR_robustness */
+
+#ifndef GL_KHR_texture_compression_astc_hdr
+#define GL_KHR_texture_compression_astc_hdr 1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif /* GL_KHR_texture_compression_astc_hdr */
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
+#ifndef GL_OES_byte_coordinates
+#define GL_OES_byte_coordinates 1
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2BOESPROC) (GLenum texture, GLbyte s, GLbyte t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD1BOESPROC) (GLbyte s);
+typedef void (APIENTRYP PFNGLTEXCOORD1BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD2BOESPROC) (GLbyte s, GLbyte t);
+typedef void (APIENTRYP PFNGLTEXCOORD2BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD3BOESPROC) (GLbyte s, GLbyte t, GLbyte r);
+typedef void (APIENTRYP PFNGLTEXCOORD3BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD4BOESPROC) (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+typedef void (APIENTRYP PFNGLTEXCOORD4BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX2BOESPROC) (GLbyte x, GLbyte y);
+typedef void (APIENTRYP PFNGLVERTEX2BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX3BOESPROC) (GLbyte x, GLbyte y, GLbyte z);
+typedef void (APIENTRYP PFNGLVERTEX3BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z, GLbyte w);
+typedef void (APIENTRYP PFNGLVERTEX4BVOESPROC) (const GLbyte *coords);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiTexCoord1bOES (GLenum texture, GLbyte s);
+GLAPI void APIENTRY glMultiTexCoord1bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord2bOES (GLenum texture, GLbyte s, GLbyte t);
+GLAPI void APIENTRY glMultiTexCoord2bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord3bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r);
+GLAPI void APIENTRY glMultiTexCoord3bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord4bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+GLAPI void APIENTRY glMultiTexCoord4bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord1bOES (GLbyte s);
+GLAPI void APIENTRY glTexCoord1bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord2bOES (GLbyte s, GLbyte t);
+GLAPI void APIENTRY glTexCoord2bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord3bOES (GLbyte s, GLbyte t, GLbyte r);
+GLAPI void APIENTRY glTexCoord3bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord4bOES (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+GLAPI void APIENTRY glTexCoord4bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex2bOES (GLbyte x, GLbyte y);
+GLAPI void APIENTRY glVertex2bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex3bOES (GLbyte x, GLbyte y, GLbyte z);
+GLAPI void APIENTRY glVertex3bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex4bOES (GLbyte x, GLbyte y, GLbyte z, GLbyte w);
+GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords);
+#endif
+#endif /* GL_OES_byte_coordinates */
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifndef GL_OES_fixed_point
+#define GL_OES_fixed_point 1
+typedef GLint GLfixed;
+#define GL_FIXED_OES 0x140C
+typedef void (APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref);
+typedef void (APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLfixed depth);
+typedef void (APIENTRYP PFNGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation);
+typedef void (APIENTRYP PFNGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLFOGXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum plane, GLfixed *equation);
+typedef void (APIENTRYP PFNGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLLINEWIDTHXOESPROC) (GLfixed width);
+typedef void (APIENTRYP PFNGLLOADMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLMULTMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (APIENTRYP PFNGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (APIENTRYP PFNGLORTHOXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size);
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units);
+typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLACCUMXOESPROC) (GLenum op, GLfixed value);
+typedef void (APIENTRYP PFNGLBITMAPXOESPROC) (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap);
+typedef void (APIENTRYP PFNGLBLENDCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCLEARACCUMXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCOLOR3XOESPROC) (GLfixed red, GLfixed green, GLfixed blue);
+typedef void (APIENTRYP PFNGLCOLOR3XVOESPROC) (const GLfixed *components);
+typedef void (APIENTRYP PFNGLCOLOR4XVOESPROC) (const GLfixed *components);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLEVALCOORD1XOESPROC) (GLfixed u);
+typedef void (APIENTRYP PFNGLEVALCOORD1XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLEVALCOORD2XOESPROC) (GLfixed u, GLfixed v);
+typedef void (APIENTRYP PFNGLEVALCOORD2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLFEEDBACKBUFFERXOESPROC) (GLsizei n, GLenum type, const GLfixed *buffer);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETMAPXVOESPROC) (GLenum target, GLenum query, GLfixed *v);
+typedef void (APIENTRYP PFNGLGETMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLGETPIXELMAPXVPROC) (GLenum map, GLint size, GLfixed *values);
+typedef void (APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERXVOESPROC) (GLenum target, GLint level, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLINDEXXOESPROC) (GLfixed component);
+typedef void (APIENTRYP PFNGLINDEXXVOESPROC) (const GLfixed *component);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMAP1XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+typedef void (APIENTRYP PFNGLMAP2XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+typedef void (APIENTRYP PFNGLMAPGRID1XOESPROC) (GLint n, GLfixed u1, GLfixed u2);
+typedef void (APIENTRYP PFNGLMAPGRID2XOESPROC) (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1XOESPROC) (GLenum texture, GLfixed s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2XOESPROC) (GLenum texture, GLfixed s, GLfixed t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLNORMAL3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLPASSTHROUGHXOESPROC) (GLfixed token);
+typedef void (APIENTRYP PFNGLPIXELMAPXPROC) (GLenum map, GLint size, const GLfixed *values);
+typedef void (APIENTRYP PFNGLPIXELSTOREXPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFERXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLPIXELZOOMXOESPROC) (GLfixed xfactor, GLfixed yfactor);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESXOESPROC) (GLsizei n, const GLuint *textures, const GLfixed *priorities);
+typedef void (APIENTRYP PFNGLRASTERPOS2XOESPROC) (GLfixed x, GLfixed y);
+typedef void (APIENTRYP PFNGLRASTERPOS2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRASTERPOS3XOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLRASTERPOS3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRASTERPOS4XOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+typedef void (APIENTRYP PFNGLRASTERPOS4XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRECTXOESPROC) (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+typedef void (APIENTRYP PFNGLRECTXVOESPROC) (const GLfixed *v1, const GLfixed *v2);
+typedef void (APIENTRYP PFNGLTEXCOORD1XOESPROC) (GLfixed s);
+typedef void (APIENTRYP PFNGLTEXCOORD1XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD2XOESPROC) (GLfixed s, GLfixed t);
+typedef void (APIENTRYP PFNGLTEXCOORD2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD3XOESPROC) (GLfixed s, GLfixed t, GLfixed r);
+typedef void (APIENTRYP PFNGLTEXCOORD3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD4XOESPROC) (GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (APIENTRYP PFNGLTEXCOORD4XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLVERTEX2XOESPROC) (GLfixed x);
+typedef void (APIENTRYP PFNGLVERTEX2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLVERTEX3XOESPROC) (GLfixed x, GLfixed y);
+typedef void (APIENTRYP PFNGLVERTEX3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLVERTEX4XOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLVERTEX4XVOESPROC) (const GLfixed *coords);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAlphaFuncxOES (GLenum func, GLfixed ref);
+GLAPI void APIENTRY glClearColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glClearDepthxOES (GLfixed depth);
+GLAPI void APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation);
+GLAPI void APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glDepthRangexOES (GLfixed n, GLfixed f);
+GLAPI void APIENTRY glFogxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glFogxvOES (GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glFrustumxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GLAPI void APIENTRY glGetClipPlanexOES (GLenum plane, GLfixed *equation);
+GLAPI void APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexEnvxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glLightModelxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glLineWidthxOES (GLfixed width);
+GLAPI void APIENTRY glLoadMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glMultMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMultiTexCoord4xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GLAPI void APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz);
+GLAPI void APIENTRY glOrthoxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glPointSizexOES (GLfixed size);
+GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
+GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert);
+GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glAccumxOES (GLenum op, GLfixed value);
+GLAPI void APIENTRY glBitmapxOES (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap);
+GLAPI void APIENTRY glBlendColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glClearAccumxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glColor3xOES (GLfixed red, GLfixed green, GLfixed blue);
+GLAPI void APIENTRY glColor3xvOES (const GLfixed *components);
+GLAPI void APIENTRY glColor4xvOES (const GLfixed *components);
+GLAPI void APIENTRY glConvolutionParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glConvolutionParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glEvalCoord1xOES (GLfixed u);
+GLAPI void APIENTRY glEvalCoord1xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glEvalCoord2xOES (GLfixed u, GLfixed v);
+GLAPI void APIENTRY glEvalCoord2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glFeedbackBufferxOES (GLsizei n, GLenum type, const GLfixed *buffer);
+GLAPI void APIENTRY glGetConvolutionParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetHistogramParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetLightxOES (GLenum light, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetMapxvOES (GLenum target, GLenum query, GLfixed *v);
+GLAPI void APIENTRY glGetMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glGetPixelMapxv (GLenum map, GLint size, GLfixed *values);
+GLAPI void APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexLevelParameterxvOES (GLenum target, GLint level, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glIndexxOES (GLfixed component);
+GLAPI void APIENTRY glIndexxvOES (const GLfixed *component);
+GLAPI void APIENTRY glLoadTransposeMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMap1xOES (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+GLAPI void APIENTRY glMap2xOES (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+GLAPI void APIENTRY glMapGrid1xOES (GLint n, GLfixed u1, GLfixed u2);
+GLAPI void APIENTRY glMapGrid2xOES (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+GLAPI void APIENTRY glMultTransposeMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMultiTexCoord1xOES (GLenum texture, GLfixed s);
+GLAPI void APIENTRY glMultiTexCoord1xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord2xOES (GLenum texture, GLfixed s, GLfixed t);
+GLAPI void APIENTRY glMultiTexCoord2xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord3xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+GLAPI void APIENTRY glMultiTexCoord3xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord4xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glNormal3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glPassThroughxOES (GLfixed token);
+GLAPI void APIENTRY glPixelMapx (GLenum map, GLint size, const GLfixed *values);
+GLAPI void APIENTRY glPixelStorex (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glPixelTransferxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glPixelZoomxOES (GLfixed xfactor, GLfixed yfactor);
+GLAPI void APIENTRY glPrioritizeTexturesxOES (GLsizei n, const GLuint *textures, const GLfixed *priorities);
+GLAPI void APIENTRY glRasterPos2xOES (GLfixed x, GLfixed y);
+GLAPI void APIENTRY glRasterPos2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRasterPos3xOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glRasterPos3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRasterPos4xOES (GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+GLAPI void APIENTRY glRasterPos4xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRectxOES (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+GLAPI void APIENTRY glRectxvOES (const GLfixed *v1, const GLfixed *v2);
+GLAPI void APIENTRY glTexCoord1xOES (GLfixed s);
+GLAPI void APIENTRY glTexCoord1xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord2xOES (GLfixed s, GLfixed t);
+GLAPI void APIENTRY glTexCoord2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord3xOES (GLfixed s, GLfixed t, GLfixed r);
+GLAPI void APIENTRY glTexCoord3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord4xOES (GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GLAPI void APIENTRY glTexCoord4xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glVertex2xOES (GLfixed x);
+GLAPI void APIENTRY glVertex2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glVertex3xOES (GLfixed x, GLfixed y);
+GLAPI void APIENTRY glVertex3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glVertex4xOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glVertex4xvOES (const GLfixed *coords);
+#endif
+#endif /* GL_OES_fixed_point */
+
+#ifndef GL_OES_query_matrix
+#define GL_OES_query_matrix 1
+typedef GLbitfield (APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed *mantissa, GLint *exponent);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLbitfield APIENTRY glQueryMatrixxOES (GLfixed *mantissa, GLint *exponent);
+#endif
+#endif /* GL_OES_query_matrix */
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif /* GL_OES_read_format */
+
+#ifndef GL_OES_single_precision
+#define GL_OES_single_precision 1
+typedef void (APIENTRYP PFNGLCLEARDEPTHFOESPROC) (GLclampf depth);
+typedef void (APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat *equation);
+typedef void (APIENTRYP PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearDepthfOES (GLclampf depth);
+GLAPI void APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation);
+GLAPI void APIENTRY glDepthRangefOES (GLclampf n, GLclampf f);
+GLAPI void APIENTRY glFrustumfOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+GLAPI void APIENTRY glGetClipPlanefOES (GLenum plane, GLfloat *equation);
+GLAPI void APIENTRY glOrthofOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#endif
+#endif /* GL_OES_single_precision */
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+#endif /* GL_3DFX_multisample */
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTbufferMask3DFX (GLuint mask);
+#endif
+#endif /* GL_3DFX_tbuffer */
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+#ifndef GL_AMD_blend_minmax_factor
+#define GL_AMD_blend_minmax_factor 1
+#define GL_FACTOR_MIN_AMD 0x901C
+#define GL_FACTOR_MAX_AMD 0x901D
+#endif /* GL_AMD_blend_minmax_factor */
+
+#ifndef GL_AMD_conservative_depth
+#define GL_AMD_conservative_depth 1
+#endif /* GL_AMD_conservative_depth */
+
+#ifndef GL_AMD_debug_output
+#define GL_AMD_debug_output 1
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#endif
+#endif /* GL_AMD_debug_output */
+
+#ifndef GL_AMD_depth_clamp_separate
+#define GL_AMD_depth_clamp_separate 1
+#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E
+#define GL_DEPTH_CLAMP_FAR_AMD 0x901F
+#endif /* GL_AMD_depth_clamp_separate */
+
+#ifndef GL_AMD_draw_buffers_blend
+#define GL_AMD_draw_buffers_blend 1
+typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#endif
+#endif /* GL_AMD_draw_buffers_blend */
+
+#ifndef GL_AMD_gcn_shader
+#define GL_AMD_gcn_shader 1
+#endif /* GL_AMD_gcn_shader */
+
+#ifndef GL_AMD_gpu_shader_int64
+#define GL_AMD_gpu_shader_int64 1
+typedef int64_t GLint64EXT;
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params);
+GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_AMD_gpu_shader_int64 */
+
+#ifndef GL_AMD_interleaved_elements
+#define GL_AMD_interleaved_elements 1
+#define GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4
+#define GL_VERTEX_ID_SWIZZLE_AMD 0x91A5
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribParameteriAMD (GLuint index, GLenum pname, GLint param);
+#endif
+#endif /* GL_AMD_interleaved_elements */
+
+#ifndef GL_AMD_multi_draw_indirect
+#define GL_AMD_multi_draw_indirect 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectAMD (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride);
+#endif
+#endif /* GL_AMD_multi_draw_indirect */
+
+#ifndef GL_AMD_name_gen_delete
+#define GL_AMD_name_gen_delete 1
+#define GL_DATA_BUFFER_AMD 0x9151
+#define GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define GL_QUERY_OBJECT_AMD 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define GL_SAMPLER_OBJECT_AMD 0x9155
+typedef void (APIENTRYP PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint *names);
+typedef void (APIENTRYP PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint *names);
+typedef GLboolean (APIENTRYP PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenNamesAMD (GLenum identifier, GLuint num, GLuint *names);
+GLAPI void APIENTRY glDeleteNamesAMD (GLenum identifier, GLuint num, const GLuint *names);
+GLAPI GLboolean APIENTRY glIsNameAMD (GLenum identifier, GLuint name);
+#endif
+#endif /* GL_AMD_name_gen_delete */
+
+#ifndef GL_AMD_occlusion_query_event
+#define GL_AMD_occlusion_query_event 1
+#define GL_OCCLUSION_QUERY_EVENT_MASK_AMD 0x874F
+#define GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD 0x00000001
+#define GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD 0x00000002
+#define GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD 0x00000004
+#define GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD 0x00000008
+#define GL_QUERY_ALL_EVENT_BITS_AMD 0xFFFFFFFF
+typedef void (APIENTRYP PFNGLQUERYOBJECTPARAMETERUIAMDPROC) (GLenum target, GLuint id, GLenum pname, GLuint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glQueryObjectParameteruiAMD (GLenum target, GLuint id, GLenum pname, GLuint param);
+#endif
+#endif /* GL_AMD_occlusion_query_event */
+
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+#endif /* GL_AMD_performance_monitor */
+
+#ifndef GL_AMD_pinned_memory
+#define GL_AMD_pinned_memory 1
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+#endif /* GL_AMD_pinned_memory */
+
+#ifndef GL_AMD_query_buffer_object
+#define GL_AMD_query_buffer_object 1
+#define GL_QUERY_BUFFER_AMD 0x9192
+#define GL_QUERY_BUFFER_BINDING_AMD 0x9193
+#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194
+#endif /* GL_AMD_query_buffer_object */
+
+#ifndef GL_AMD_sample_positions
+#define GL_AMD_sample_positions 1
+#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
+typedef void (APIENTRYP PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat *val);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLfloat *val);
+#endif
+#endif /* GL_AMD_sample_positions */
+
+#ifndef GL_AMD_seamless_cubemap_per_texture
+#define GL_AMD_seamless_cubemap_per_texture 1
+#endif /* GL_AMD_seamless_cubemap_per_texture */
+
+#ifndef GL_AMD_shader_atomic_counter_ops
+#define GL_AMD_shader_atomic_counter_ops 1
+#endif /* GL_AMD_shader_atomic_counter_ops */
+
+#ifndef GL_AMD_shader_stencil_export
+#define GL_AMD_shader_stencil_export 1
+#endif /* GL_AMD_shader_stencil_export */
+
+#ifndef GL_AMD_shader_trinary_minmax
+#define GL_AMD_shader_trinary_minmax 1
+#endif /* GL_AMD_shader_trinary_minmax */
+
+#ifndef GL_AMD_sparse_texture
+#define GL_AMD_sparse_texture 1
+#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
+#define GL_MIN_SPARSE_LEVEL_AMD 0x919B
+#define GL_MIN_LOD_WARNING_AMD 0x919C
+#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001
+typedef void (APIENTRYP PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexStorageSparseAMD (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+GLAPI void APIENTRY glTextureStorageSparseAMD (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+#endif
+#endif /* GL_AMD_sparse_texture */
+
+#ifndef GL_AMD_stencil_operation_extended
+#define GL_AMD_stencil_operation_extended 1
+#define GL_SET_AMD 0x874A
+#define GL_REPLACE_VALUE_AMD 0x874B
+#define GL_STENCIL_OP_VALUE_AMD 0x874C
+#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D
+typedef void (APIENTRYP PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value);
+#endif
+#endif /* GL_AMD_stencil_operation_extended */
+
+#ifndef GL_AMD_texture_texture4
+#define GL_AMD_texture_texture4 1
+#endif /* GL_AMD_texture_texture4 */
+
+#ifndef GL_AMD_transform_feedback3_lines_triangles
+#define GL_AMD_transform_feedback3_lines_triangles 1
+#endif /* GL_AMD_transform_feedback3_lines_triangles */
+
+#ifndef GL_AMD_transform_feedback4
+#define GL_AMD_transform_feedback4 1
+#define GL_STREAM_RASTERIZATION_AMD 0x91A0
+#endif /* GL_AMD_transform_feedback4 */
+
+#ifndef GL_AMD_vertex_shader_layer
+#define GL_AMD_vertex_shader_layer 1
+#endif /* GL_AMD_vertex_shader_layer */
+
+#ifndef GL_AMD_vertex_shader_tessellator
+#define GL_AMD_vertex_shader_tessellator 1
+#define GL_SAMPLER_BUFFER_AMD 0x9001
+#define GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define GL_TESSELLATION_MODE_AMD 0x9004
+#define GL_TESSELLATION_FACTOR_AMD 0x9005
+#define GL_DISCRETE_AMD 0x9006
+#define GL_CONTINUOUS_AMD 0x9007
+typedef void (APIENTRYP PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTessellationFactorAMD (GLfloat factor);
+GLAPI void APIENTRY glTessellationModeAMD (GLenum mode);
+#endif
+#endif /* GL_AMD_vertex_shader_tessellator */
+
+#ifndef GL_AMD_vertex_shader_viewport_index
+#define GL_AMD_vertex_shader_viewport_index 1
+#endif /* GL_AMD_vertex_shader_viewport_index */
+
+#ifndef GL_APPLE_aux_depth_stencil
+#define GL_APPLE_aux_depth_stencil 1
+#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+#endif /* GL_APPLE_aux_depth_stencil */
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+#endif /* GL_APPLE_client_storage */
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+#define GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerAPPLE (GLenum type, const void *pointer);
+GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+#endif /* GL_APPLE_element_array */
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);
+typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenFencesAPPLE (GLsizei n, GLuint *fences);
+GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glSetFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint fence);
+GLAPI void APIENTRY glFinishFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum object, GLuint name);
+GLAPI void APIENTRY glFinishObjectAPPLE (GLenum object, GLint name);
+#endif
+#endif /* GL_APPLE_fence */
+
+#ifndef GL_APPLE_float_pixels
+#define GL_APPLE_float_pixels 1
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+#endif /* GL_APPLE_float_pixels */
+
+#ifndef GL_APPLE_flush_buffer_range
+#define GL_APPLE_flush_buffer_range 1
+#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+typedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferParameteriAPPLE (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_APPLE_flush_buffer_range */
+
+#ifndef GL_APPLE_object_purgeable
+#define GL_APPLE_object_purgeable 1
+#define GL_BUFFER_OBJECT_APPLE 0x85B3
+#define GL_RELEASED_APPLE 0x8A19
+#define GL_VOLATILE_APPLE 0x8A1A
+#define GL_RETAINED_APPLE 0x8A1B
+#define GL_UNDEFINED_APPLE 0x8A1C
+#define GL_PURGEABLE_APPLE 0x8A1D
+typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#endif
+#endif /* GL_APPLE_object_purgeable */
+
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_RAW_422_APPLE 0x8A51
+#endif /* GL_APPLE_rgb_422 */
+
+#ifndef GL_APPLE_row_bytes
+#define GL_APPLE_row_bytes 1
+#define GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+#endif /* GL_APPLE_row_bytes */
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif /* GL_APPLE_specular_vector */
+
+#ifndef GL_APPLE_texture_range
+#define GL_APPLE_texture_range 1
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const void *pointer);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureRangeAPPLE (GLenum target, GLsizei length, const void *pointer);
+GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_APPLE_texture_range */
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+#endif /* GL_APPLE_transform_hint */
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint array);
+#endif
+#endif /* GL_APPLE_vertex_array_object */
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CLIENT_APPLE 0x85B4
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei length, void *pointer);
+GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei length, void *pointer);
+GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum pname, GLint param);
+#endif
+#endif /* GL_APPLE_vertex_array_range */
+
+#ifndef GL_APPLE_vertex_program_evaluators
+#define GL_APPLE_vertex_program_evaluators 1
+#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#endif
+#endif /* GL_APPLE_vertex_program_evaluators */
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+#define GL_YCBCR_422_APPLE 0x85B9
+#endif /* GL_APPLE_ycbcr_422 */
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersATI (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_ATI_draw_buffers */
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerATI (GLenum type, const void *pointer);
+GLAPI void APIENTRY glDrawElementArrayATI (GLenum mode, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+#endif /* GL_ATI_element_array */
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBumpParameterivATI (GLenum pname, const GLint *param);
+GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum pname, GLfloat *param);
+#endif
+#endif /* GL_ATI_envmap_bumpmap */
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_REG_6_ATI 0x8927
+#define GL_REG_7_ATI 0x8928
+#define GL_REG_8_ATI 0x8929
+#define GL_REG_9_ATI 0x892A
+#define GL_REG_10_ATI 0x892B
+#define GL_REG_11_ATI 0x892C
+#define GL_REG_12_ATI 0x892D
+#define GL_REG_13_ATI 0x892E
+#define GL_REG_14_ATI 0x892F
+#define GL_REG_15_ATI 0x8930
+#define GL_REG_16_ATI 0x8931
+#define GL_REG_17_ATI 0x8932
+#define GL_REG_18_ATI 0x8933
+#define GL_REG_19_ATI 0x8934
+#define GL_REG_20_ATI 0x8935
+#define GL_REG_21_ATI 0x8936
+#define GL_REG_22_ATI 0x8937
+#define GL_REG_23_ATI 0x8938
+#define GL_REG_24_ATI 0x8939
+#define GL_REG_25_ATI 0x893A
+#define GL_REG_26_ATI 0x893B
+#define GL_REG_27_ATI 0x893C
+#define GL_REG_28_ATI 0x893D
+#define GL_REG_29_ATI 0x893E
+#define GL_REG_30_ATI 0x893F
+#define GL_REG_31_ATI 0x8940
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_CON_8_ATI 0x8949
+#define GL_CON_9_ATI 0x894A
+#define GL_CON_10_ATI 0x894B
+#define GL_CON_11_ATI 0x894C
+#define GL_CON_12_ATI 0x894D
+#define GL_CON_13_ATI 0x894E
+#define GL_CON_14_ATI 0x894F
+#define GL_CON_15_ATI 0x8950
+#define GL_CON_16_ATI 0x8951
+#define GL_CON_17_ATI 0x8952
+#define GL_CON_18_ATI 0x8953
+#define GL_CON_19_ATI 0x8954
+#define GL_CON_20_ATI 0x8955
+#define GL_CON_21_ATI 0x8956
+#define GL_CON_22_ATI 0x8957
+#define GL_CON_23_ATI 0x8958
+#define GL_CON_24_ATI 0x8959
+#define GL_CON_25_ATI 0x895A
+#define GL_CON_26_ATI 0x895B
+#define GL_CON_27_ATI 0x895C
+#define GL_CON_28_ATI 0x895D
+#define GL_CON_29_ATI 0x895E
+#define GL_CON_30_ATI 0x895F
+#define GL_CON_31_ATI 0x8960
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint range);
+GLAPI void APIENTRY glBindFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glBeginFragmentShaderATI (void);
+GLAPI void APIENTRY glEndFragmentShaderATI (void);
+GLAPI void APIENTRY glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle);
+GLAPI void APIENTRY glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle);
+GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value);
+#endif
+#endif /* GL_ATI_fragment_shader */
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+typedef void *(APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void *APIENTRY glMapObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint buffer);
+#endif
+#endif /* GL_ATI_map_object_buffer */
+
+#ifndef GL_ATI_meminfo
+#define GL_ATI_meminfo 1
+#define GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+#endif /* GL_ATI_meminfo */
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_ATI_pixel_format_float 1
+#define GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#endif /* GL_ATI_pixel_format_float */
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPNTrianglesiATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glPNTrianglesfATI (GLenum pname, GLfloat param);
+#endif
+#endif /* GL_ATI_pn_triangles */
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+#endif /* GL_ATI_separate_stencil */
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+#endif /* GL_ATI_text_fragment_shader */
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+#endif /* GL_ATI_texture_env_combine3 */
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+#endif /* GL_ATI_texture_float */
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+#endif /* GL_ATI_texture_mirror_once */
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void *pointer, GLenum usage);
+typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei size, const void *pointer, GLenum usage);
+GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve);
+GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFreeObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params);
+GLAPI void APIENTRY glVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ATI_vertex_array_object */
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_STREAM0_ATI 0x876C
+#define GL_VERTEX_STREAM1_ATI 0x876D
+#define GL_VERTEX_STREAM2_ATI 0x876E
+#define GL_VERTEX_STREAM3_ATI 0x876F
+#define GL_VERTEX_STREAM4_ATI 0x8770
+#define GL_VERTEX_STREAM5_ATI 0x8771
+#define GL_VERTEX_STREAM6_ATI 0x8772
+#define GL_VERTEX_STREAM7_ATI 0x8773
+#define GL_VERTEX_SOURCE_ATI 0x8774
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexStream1sATI (GLenum stream, GLshort x);
+GLAPI void APIENTRY glVertexStream1svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream1iATI (GLenum stream, GLint x);
+GLAPI void APIENTRY glVertexStream1ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream1fATI (GLenum stream, GLfloat x);
+GLAPI void APIENTRY glVertexStream1fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream1dATI (GLenum stream, GLdouble x);
+GLAPI void APIENTRY glVertexStream1dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream2sATI (GLenum stream, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexStream2svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream2iATI (GLenum stream, GLint x, GLint y);
+GLAPI void APIENTRY glVertexStream2ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexStream2fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexStream2dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexStream4svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexStream4ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexStream4fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexStream4dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI void APIENTRY glNormalStream3bvATI (GLenum stream, const GLbyte *coords);
+GLAPI void APIENTRY glNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+GLAPI void APIENTRY glNormalStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz);
+GLAPI void APIENTRY glNormalStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void APIENTRY glNormalStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI void APIENTRY glNormalStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum stream);
+GLAPI void APIENTRY glVertexBlendEnviATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param);
+#endif
+#endif /* GL_ATI_vertex_streams */
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+#endif /* GL_EXT_422_pixels */
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#define GL_ABGR_EXT 0x8000
+#endif /* GL_EXT_abgr */
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+#endif /* GL_EXT_bgra */
+
+#ifndef GL_EXT_bindable_uniform
+#define GL_EXT_bindable_uniform 1
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+typedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer);
+GLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location);
+GLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint program, GLint location);
+#endif
+#endif /* GL_EXT_bindable_uniform */
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColorEXT (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#endif
+#endif /* GL_EXT_blend_color */
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha);
+#endif
+#endif /* GL_EXT_blend_equation_separate */
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+#endif /* GL_EXT_blend_func_separate */
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+#endif /* GL_EXT_blend_logic_op */
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_BLEND_EQUATION_EXT 0x8009
+typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_blend_minmax */
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+#endif /* GL_EXT_blend_subtract */
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+#endif /* GL_EXT_clip_volume_hint */
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+#endif /* GL_EXT_cmyka */
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+#endif /* GL_EXT_color_subtable */
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count);
+GLAPI void APIENTRY glUnlockArraysEXT (void);
+#endif
+#endif /* GL_EXT_compiled_vertex_array */
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, void *image);
+GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+#endif
+#endif /* GL_EXT_convolution */
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);
+typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);
+typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);
+typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);
+typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);
+typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);
+typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);
+typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);
+typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);
+typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);
+typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz);
+GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz);
+GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz);
+GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glTangent3iEXT (GLint tx, GLint ty, GLint tz);
+GLAPI void APIENTRY glTangent3ivEXT (const GLint *v);
+GLAPI void APIENTRY glTangent3sEXT (GLshort tx, GLshort ty, GLshort tz);
+GLAPI void APIENTRY glTangent3svEXT (const GLshort *v);
+GLAPI void APIENTRY glBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz);
+GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz);
+GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz);
+GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glBinormal3iEXT (GLint bx, GLint by, GLint bz);
+GLAPI void APIENTRY glBinormal3ivEXT (const GLint *v);
+GLAPI void APIENTRY glBinormal3sEXT (GLshort bx, GLshort by, GLshort bz);
+GLAPI void APIENTRY glBinormal3svEXT (const GLshort *v);
+GLAPI void APIENTRY glTangentPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glBinormalPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_coordinate_frame */
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_EXT_copy_texture */
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCullParameterdvEXT (GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glCullParameterfvEXT (GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_cull_vertex */
+
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+typedef void (APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_EXT_debug_label */
+
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+typedef void (APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GLAPI void APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GLAPI void APIENTRY glPopGroupMarkerEXT (void);
+#endif
+#endif /* GL_EXT_debug_marker */
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthBoundsEXT (GLclampd zmin, GLclampd zmax);
+#endif
+#endif /* GL_EXT_depth_bounds_test */
+
+/* GL_EXT_direct_state_access */
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+#define GL_PROGRAM_MATRIX 0x8E2D
+#define GL_TRANSPOSE_PROGRAM_MATRIX 0x8E2E
+#define GL_PROGRAM_MATRIX_STACK_DEPTH 0x8E2F
+typedef void (APIENTRYP PFNGLMATRIXLOADFPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADDPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTFPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXROTATEFPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXROTATEDPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEFPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEDPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXFRUSTUMPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXORTHOPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXPOPPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXPUSHPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDPROC) (GLenum mode, const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMatrixLoadf (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadd (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultf (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultd (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixLoadIdentity (GLenum mode);
+GLAPI void APIENTRY glMatrixRotatef (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixRotated (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixScalef (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixScaled (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixTranslatef (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixTranslated (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixFrustum (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixOrtho (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixPop (GLenum mode);
+GLAPI void APIENTRY glMatrixPush (GLenum mode);
+GLAPI void APIENTRY glMatrixLoadTransposef (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadTransposed (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultTransposef (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultTransposed (GLenum mode, const GLdouble *m);
+#endif
+#endif /* GL_EXT_direct_state_access */
+
+#ifndef GL_EXT_draw_buffers2
+#define GL_EXT_draw_buffers2 1
+typedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+#endif
+#endif /* GL_EXT_draw_buffers2 */
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_draw_instanced */
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+#endif
+#endif /* GL_EXT_draw_range_elements */
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordfEXT (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoorddEXT (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_fog_coord */
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* GL_EXT_framebuffer_blit */
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_EXT_framebuffer_multisample */
+
+#ifndef GL_EXT_framebuffer_multisample_blit_scaled
+#define GL_EXT_framebuffer_multisample_blit_scaled 1
+#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
+#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB
+#endif /* GL_EXT_framebuffer_multisample_blit_scaled */
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmapEXT (GLenum target);
+#endif
+#endif /* GL_EXT_framebuffer_object */
+
+#ifndef GL_EXT_framebuffer_sRGB
+#define GL_EXT_framebuffer_sRGB 1
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#endif /* GL_EXT_framebuffer_sRGB */
+
+#ifndef GL_EXT_geometry_shader4
+#define GL_EXT_geometry_shader4 1
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+#endif
+#endif /* GL_EXT_geometry_shader4 */
+
+#ifndef GL_EXT_gpu_program_parameters
+#define GL_EXT_gpu_program_parameters 1
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#endif
+#endif /* GL_EXT_gpu_program_parameters */
+
+#ifndef GL_EXT_gpu_shader4
+#define GL_EXT_gpu_shader4 1
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
+#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1uiEXT (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value);
+#endif
+#endif /* GL_EXT_gpu_shader4 */
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+#define GL_TABLE_TOO_LARGE_EXT 0x8031
+typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogramEXT (GLenum target);
+GLAPI void APIENTRY glResetMinmaxEXT (GLenum target);
+#endif
+#endif /* GL_EXT_histogram */
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+#define GL_IUI_V2F_EXT 0x81AD
+#define GL_IUI_V3F_EXT 0x81AE
+#define GL_IUI_N3F_V2F_EXT 0x81AF
+#define GL_IUI_N3F_V3F_EXT 0x81B0
+#define GL_T2F_IUI_V2F_EXT 0x81B1
+#define GL_T2F_IUI_V3F_EXT 0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4
+#endif /* GL_EXT_index_array_formats */
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+#define GL_INDEX_TEST_EXT 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT 0x81B6
+#define GL_INDEX_TEST_REF_EXT 0x81B7
+typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexFuncEXT (GLenum func, GLclampf ref);
+#endif
+#endif /* GL_EXT_index_func */
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+#define GL_INDEX_MATERIAL_EXT 0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA
+typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexMaterialEXT (GLenum face, GLenum mode);
+#endif
+#endif /* GL_EXT_index_material */
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+#endif /* GL_EXT_index_texture */
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyTextureEXT (GLenum mode);
+GLAPI void APIENTRY glTextureLightEXT (GLenum pname);
+GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode);
+#endif
+#endif /* GL_EXT_light_texture */
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+#endif /* GL_EXT_misc_attribute */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskEXT (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern);
+#endif
+#endif /* GL_EXT_multisample */
+
+#ifndef GL_EXT_packed_depth_stencil
+#define GL_EXT_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+#endif /* GL_EXT_packed_depth_stencil */
+
+#ifndef GL_EXT_packed_float
+#define GL_EXT_packed_float 1
+#define GL_R11F_G11F_B10F_EXT 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+#endif /* GL_EXT_packed_float */
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+#endif /* GL_EXT_packed_pixels */
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void *data);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glGetColorTableEXT (GLenum target, GLenum format, GLenum type, void *data);
+GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_paletted_texture */
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#endif /* GL_EXT_pixel_buffer_object */
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTransformParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTransformParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_pixel_transform */
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+#endif /* GL_EXT_pixel_transform_color_table */
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfEXT (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvEXT (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_EXT_point_parameters */
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias);
+#endif
+#endif /* GL_EXT_polygon_offset */
+
+#ifndef GL_EXT_polygon_offset_clamp
+#define GL_EXT_polygon_offset_clamp 1
+#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_EXT_polygon_offset_clamp */
+
+#ifndef GL_EXT_provoking_vertex
+#define GL_EXT_provoking_vertex 1
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_PROVOKING_VERTEX_EXT 0x8E4F
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_provoking_vertex */
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#define GL_RESCALE_NORMAL_EXT 0x803A
+#endif /* GL_EXT_rescale_normal */
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3iEXT (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_secondary_color */
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
+typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program);
+GLAPI void APIENTRY glActiveProgramEXT (GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string);
+#endif
+#endif /* GL_EXT_separate_shader_objects */
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif /* GL_EXT_separate_specular_color */
+
+#ifndef GL_EXT_shader_image_load_formatted
+#define GL_EXT_shader_image_load_formatted 1
+#endif /* GL_EXT_shader_image_load_formatted */
+
+#ifndef GL_EXT_shader_image_load_store
+#define GL_EXT_shader_image_load_store 1
+#define GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define GL_IMAGE_1D_EXT 0x904C
+#define GL_IMAGE_2D_EXT 0x904D
+#define GL_IMAGE_3D_EXT 0x904E
+#define GL_IMAGE_2D_RECT_EXT 0x904F
+#define GL_IMAGE_CUBE_EXT 0x9050
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define GL_INT_IMAGE_1D_EXT 0x9057
+#define GL_INT_IMAGE_2D_EXT 0x9058
+#define GL_INT_IMAGE_3D_EXT 0x9059
+#define GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define GL_INT_IMAGE_CUBE_EXT 0x905B
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindImageTextureEXT (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers);
+#endif
+#endif /* GL_EXT_shader_image_load_store */
+
+#ifndef GL_EXT_shader_integer_mix
+#define GL_EXT_shader_integer_mix 1
+#endif /* GL_EXT_shader_integer_mix */
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif /* GL_EXT_shadow_funcs */
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+#endif /* GL_EXT_shared_texture_palette */
+
+#ifndef GL_EXT_stencil_clear_tag
+#define GL_EXT_stencil_clear_tag 1
+#define GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+typedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilClearTagEXT (GLsizei stencilTagBits, GLuint stencilClearTag);
+#endif
+#endif /* GL_EXT_stencil_clear_tag */
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum face);
+#endif
+#endif /* GL_EXT_stencil_two_side */
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+#endif /* GL_EXT_stencil_wrap */
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_EXT_subtexture */
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT 0x8065
+#endif /* GL_EXT_texture */
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_EXT_texture3D */
+
+#ifndef GL_EXT_texture_array
+#define GL_EXT_texture_array 1
+#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#endif
+#endif /* GL_EXT_texture_array */
+
+#ifndef GL_EXT_texture_buffer_object
+#define GL_EXT_texture_buffer_object 1
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+typedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+#endif /* GL_EXT_texture_buffer_object */
+
+#ifndef GL_EXT_texture_compression_latc
+#define GL_EXT_texture_compression_latc 1
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+#endif /* GL_EXT_texture_compression_latc */
+
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_EXT_texture_compression_rgtc 1
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#endif /* GL_EXT_texture_compression_rgtc */
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_EXT_texture_cube_map 1
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+#endif /* GL_EXT_texture_cube_map */
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif /* GL_EXT_texture_env_add */
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+#endif /* GL_EXT_texture_env_combine */
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+#endif /* GL_EXT_texture_env_dot3 */
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifndef GL_EXT_texture_integer
+#define GL_EXT_texture_integer 1
+#define GL_RGBA32UI_EXT 0x8D70
+#define GL_RGB32UI_EXT 0x8D71
+#define GL_ALPHA32UI_EXT 0x8D72
+#define GL_INTENSITY32UI_EXT 0x8D73
+#define GL_LUMINANCE32UI_EXT 0x8D74
+#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define GL_RGBA16UI_EXT 0x8D76
+#define GL_RGB16UI_EXT 0x8D77
+#define GL_ALPHA16UI_EXT 0x8D78
+#define GL_INTENSITY16UI_EXT 0x8D79
+#define GL_LUMINANCE16UI_EXT 0x8D7A
+#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define GL_RGBA8UI_EXT 0x8D7C
+#define GL_RGB8UI_EXT 0x8D7D
+#define GL_ALPHA8UI_EXT 0x8D7E
+#define GL_INTENSITY8UI_EXT 0x8D7F
+#define GL_LUMINANCE8UI_EXT 0x8D80
+#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define GL_RGBA32I_EXT 0x8D82
+#define GL_RGB32I_EXT 0x8D83
+#define GL_ALPHA32I_EXT 0x8D84
+#define GL_INTENSITY32I_EXT 0x8D85
+#define GL_LUMINANCE32I_EXT 0x8D86
+#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define GL_RGBA16I_EXT 0x8D88
+#define GL_RGB16I_EXT 0x8D89
+#define GL_ALPHA16I_EXT 0x8D8A
+#define GL_INTENSITY16I_EXT 0x8D8B
+#define GL_LUMINANCE16I_EXT 0x8D8C
+#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define GL_RGBA8I_EXT 0x8D8E
+#define GL_RGB8I_EXT 0x8D8F
+#define GL_ALPHA8I_EXT 0x8D90
+#define GL_INTENSITY8I_EXT 0x8D91
+#define GL_LUMINANCE8I_EXT 0x8D92
+#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define GL_RED_INTEGER_EXT 0x8D94
+#define GL_GREEN_INTEGER_EXT 0x8D95
+#define GL_BLUE_INTEGER_EXT 0x8D96
+#define GL_ALPHA_INTEGER_EXT 0x8D97
+#define GL_RGB_INTEGER_EXT 0x8D98
+#define GL_RGBA_INTEGER_EXT 0x8D99
+#define GL_BGR_INTEGER_EXT 0x8D9A
+#define GL_BGRA_INTEGER_EXT 0x8D9B
+#define GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI void APIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#endif
+#endif /* GL_EXT_texture_integer */
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#endif /* GL_EXT_texture_lod_bias */
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#endif /* GL_EXT_texture_mirror_clamp */
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI void APIENTRY glBindTextureEXT (GLenum target, GLuint texture);
+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures);
+GLAPI void APIENTRY glGenTexturesEXT (GLsizei n, GLuint *textures);
+GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint texture);
+GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+#endif /* GL_EXT_texture_object */
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_texture_perturb_normal */
+
+#ifndef GL_EXT_texture_sRGB
+#define GL_EXT_texture_sRGB 1
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB8_EXT 0x8C41
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define GL_SLUMINANCE_EXT 0x8C46
+#define GL_SLUMINANCE8_EXT 0x8C47
+#define GL_COMPRESSED_SRGB_EXT 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif /* GL_EXT_texture_sRGB */
+
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#endif /* GL_EXT_texture_sRGB_decode */
+
+#ifndef GL_EXT_texture_shared_exponent
+#define GL_EXT_texture_shared_exponent 1
+#define GL_RGB9_E5_EXT 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+#endif /* GL_EXT_texture_shared_exponent */
+
+#ifndef GL_EXT_texture_snorm
+#define GL_EXT_texture_snorm 1
+#define GL_ALPHA_SNORM 0x9010
+#define GL_LUMINANCE_SNORM 0x9011
+#define GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define GL_INTENSITY_SNORM 0x9013
+#define GL_ALPHA8_SNORM 0x9014
+#define GL_LUMINANCE8_SNORM 0x9015
+#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define GL_INTENSITY8_SNORM 0x9017
+#define GL_ALPHA16_SNORM 0x9018
+#define GL_LUMINANCE16_SNORM 0x9019
+#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define GL_INTENSITY16_SNORM 0x901B
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#endif /* GL_EXT_texture_snorm */
+
+#ifndef GL_EXT_texture_swizzle
+#define GL_EXT_texture_swizzle 1
+#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+#endif /* GL_EXT_texture_swizzle */
+
+#ifndef GL_EXT_timer_query
+#define GL_EXT_timer_query 1
+#define GL_TIME_ELAPSED_EXT 0x88BF
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+#endif /* GL_EXT_timer_query */
+
+#ifndef GL_EXT_transform_feedback
+#define GL_EXT_transform_feedback 1
+#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackEXT (void);
+GLAPI void APIENTRY glBindBufferRangeEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseEXT (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#endif
+#endif /* GL_EXT_transform_feedback */
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glArrayElementEXT (GLint i);
+GLAPI void APIENTRY glColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glDrawArraysEXT (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer);
+GLAPI void APIENTRY glGetPointervEXT (GLenum pname, void **params);
+GLAPI void APIENTRY glIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+#endif
+#endif /* GL_EXT_vertex_array */
+
+#ifndef GL_EXT_vertex_array_bgra
+#define GL_EXT_vertex_array_bgra 1
+#endif /* GL_EXT_vertex_array_bgra */
+
+#ifndef GL_EXT_vertex_attrib_64bit
+#define GL_EXT_vertex_attrib_64bit 1
+#define GL_DOUBLE_VEC2_EXT 0x8FFC
+#define GL_DOUBLE_VEC3_EXT 0x8FFD
+#define GL_DOUBLE_VEC4_EXT 0x8FFE
+#define GL_DOUBLE_MAT2_EXT 0x8F46
+#define GL_DOUBLE_MAT3_EXT 0x8F47
+#define GL_DOUBLE_MAT4_EXT 0x8F48
+#define GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define GL_DOUBLE_MAT4x3_EXT 0x8F4E
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1dEXT (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2dEXT (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdvEXT (GLuint index, GLenum pname, GLdouble *params);
+#endif
+#endif /* GL_EXT_vertex_attrib_64bit */
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const void *addr);
+typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const void *addr);
+typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);
+typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);
+typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);
+typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);
+typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);
+typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);
+typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const void *addr);
+typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, void **data);
+typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVertexShaderEXT (void);
+GLAPI void APIENTRY glEndVertexShaderEXT (void);
+GLAPI void APIENTRY glBindVertexShaderEXT (GLuint id);
+GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint range);
+GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint id);
+GLAPI void APIENTRY glShaderOp1EXT (GLenum op, GLuint res, GLuint arg1);
+GLAPI void APIENTRY glShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+GLAPI void APIENTRY glShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+GLAPI void APIENTRY glSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glInsertComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI void APIENTRY glExtractComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+GLAPI void APIENTRY glSetInvariantEXT (GLuint id, GLenum type, const void *addr);
+GLAPI void APIENTRY glSetLocalConstantEXT (GLuint id, GLenum type, const void *addr);
+GLAPI void APIENTRY glVariantbvEXT (GLuint id, const GLbyte *addr);
+GLAPI void APIENTRY glVariantsvEXT (GLuint id, const GLshort *addr);
+GLAPI void APIENTRY glVariantivEXT (GLuint id, const GLint *addr);
+GLAPI void APIENTRY glVariantfvEXT (GLuint id, const GLfloat *addr);
+GLAPI void APIENTRY glVariantdvEXT (GLuint id, const GLdouble *addr);
+GLAPI void APIENTRY glVariantubvEXT (GLuint id, const GLubyte *addr);
+GLAPI void APIENTRY glVariantusvEXT (GLuint id, const GLushort *addr);
+GLAPI void APIENTRY glVariantuivEXT (GLuint id, const GLuint *addr);
+GLAPI void APIENTRY glVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const void *addr);
+GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint id);
+GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint id);
+GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum light, GLenum value);
+GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum face, GLenum value);
+GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value);
+GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum unit, GLenum value);
+GLAPI GLuint APIENTRY glBindParameterEXT (GLenum value);
+GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint id, GLenum cap);
+GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetVariantPointervEXT (GLuint id, GLenum value, void **data);
+GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+#endif
+#endif /* GL_EXT_vertex_shader */
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW0_EXT 0x1700
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexWeightfEXT (GLfloat weight);
+GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *weight);
+GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_vertex_weighting */
+
+#ifndef GL_EXT_x11_sync_object
+#define GL_EXT_x11_sync_object 1
+#define GL_SYNC_X11_FENCE_EXT 0x90E1
+typedef GLsync (APIENTRYP PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glImportSyncEXT (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+#endif
+#endif /* GL_EXT_x11_sync_object */
+
+#ifndef GL_GREMEDY_frame_terminator
+#define GL_GREMEDY_frame_terminator 1
+typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameTerminatorGREMEDY (void);
+#endif
+#endif /* GL_GREMEDY_frame_terminator */
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void *string);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei len, const void *string);
+#endif
+#endif /* GL_GREMEDY_string_marker */
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+#define GL_IGNORE_BORDER_HP 0x8150
+#define GL_CONSTANT_BORDER_HP 0x8151
+#define GL_REPLICATE_BORDER_HP 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154
+#endif /* GL_HP_convolution_border_modes */
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+#define GL_IMAGE_SCALE_X_HP 0x8155
+#define GL_IMAGE_SCALE_Y_HP 0x8156
+#define GL_IMAGE_TRANSLATE_X_HP 0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP 0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B
+#define GL_IMAGE_MAG_FILTER_HP 0x815C
+#define GL_IMAGE_MIN_FILTER_HP 0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E
+#define GL_CUBIC_HP 0x815F
+#define GL_AVERAGE_HP 0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP 0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImageTransformParameteriHP (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_HP_image_transform */
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+#endif /* GL_HP_occlusion_test */
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP 0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169
+#endif /* GL_HP_texture_lighting */
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+#define GL_CULL_VERTEX_IBM 103050
+#endif /* GL_IBM_cull_vertex */
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride);
+#endif
+#endif /* GL_IBM_multimode_draw_arrays */
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262
+#endif /* GL_IBM_rasterpos_clip */
+
+#ifndef GL_IBM_static_data
+#define GL_IBM_static_data 1
+#define GL_ALL_STATIC_DATA_IBM 103060
+#define GL_STATIC_VERTEX_ARRAY_IBM 103061
+typedef void (APIENTRYP PFNGLFLUSHSTATICDATAIBMPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushStaticDataIBM (GLenum target);
+#endif
+#endif /* GL_IBM_static_data */
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_IBM_texture_mirrored_repeat 1
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint stride, const GLboolean **pointer, GLint ptrstride);
+GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glIndexPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glNormalPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glVertexPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+#endif
+#endif /* GL_IBM_vertex_array_lists */
+
+#ifndef GL_INGR_blend_func_separate
+#define GL_INGR_blend_func_separate 1
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+#endif /* GL_INGR_blend_func_separate */
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+#endif /* GL_INGR_color_clamp */
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+#define GL_INTERLACE_READ_INGR 0x8568
+#endif /* GL_INGR_interlace_read */
+
+#ifndef GL_INTEL_fragment_shader_ordering
+#define GL_INTEL_fragment_shader_ordering 1
+#endif /* GL_INTEL_fragment_shader_ordering */
+
+#ifndef GL_INTEL_map_texture
+#define GL_INTEL_map_texture 1
+#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
+#define GL_LAYOUT_DEFAULT_INTEL 0
+#define GL_LAYOUT_LINEAR_INTEL 1
+#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2
+typedef void (APIENTRYP PFNGLSYNCTEXTUREINTELPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level);
+typedef void *(APIENTRYP PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSyncTextureINTEL (GLuint texture);
+GLAPI void APIENTRY glUnmapTexture2DINTEL (GLuint texture, GLint level);
+GLAPI void *APIENTRY glMapTexture2DINTEL (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout);
+#endif
+#endif /* GL_INTEL_map_texture */
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexPointervINTEL (GLint size, GLenum type, const void **pointer);
+GLAPI void APIENTRY glNormalPointervINTEL (GLenum type, const void **pointer);
+GLAPI void APIENTRY glColorPointervINTEL (GLint size, GLenum type, const void **pointer);
+GLAPI void APIENTRY glTexCoordPointervINTEL (GLint size, GLenum type, const void **pointer);
+#endif
+#endif /* GL_INTEL_parallel_arrays */
+
+#ifndef GL_INTEL_performance_query
+#define GL_INTEL_performance_query 1
+#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
+#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001
+#define GL_PERFQUERY_WAIT_INTEL 0x83FB
+#define GL_PERFQUERY_FLUSH_INTEL 0x83FA
+#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9
+#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0
+#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1
+#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2
+#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3
+#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4
+#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5
+#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8
+#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9
+#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA
+#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB
+#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC
+#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD
+#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE
+#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF
+#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500
+typedef void (APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle);
+typedef void (APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
+typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
+typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
+typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle);
+GLAPI void APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
+GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
+GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
+GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#endif
+#endif /* GL_INTEL_performance_query */
+
+#ifndef GL_MESAX_texture_stack
+#define GL_MESAX_texture_stack 1
+#define GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+#endif /* GL_MESAX_texture_stack */
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+#define GL_PACK_INVERT_MESA 0x8758
+#endif /* GL_MESA_pack_invert */
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glResizeBuffersMESA (void);
+#endif
+#endif /* GL_MESA_resize_buffers */
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dMESA (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fMESA (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iMESA (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sMESA (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iMESA (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sMESA (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v);
+#endif
+#endif /* GL_MESA_window_pos */
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+#endif /* GL_MESA_ycbcr_texture */
+
+#ifndef GL_NVX_conditional_render
+#define GL_NVX_conditional_render 1
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNVX (GLuint id);
+GLAPI void APIENTRY glEndConditionalRenderNVX (void);
+#endif
+#endif /* GL_NVX_conditional_render */
+
+#ifndef GL_NVX_gpu_memory_info
+#define GL_NVX_gpu_memory_info 1
+#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+#endif /* GL_NVX_gpu_memory_info */
+
+#ifndef GL_NV_bindless_multi_draw_indirect
+#define GL_NV_bindless_multi_draw_indirect 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+#endif
+#endif /* GL_NV_bindless_multi_draw_indirect */
+
+#ifndef GL_NV_bindless_multi_draw_indirect_count
+#define GL_NV_bindless_multi_draw_indirect_count 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSCOUNTNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSCOUNTNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessCountNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessCountNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+#endif
+#endif /* GL_NV_bindless_multi_draw_indirect_count */
+
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleNV (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
+
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+#define GL_BLEND_OVERLAP_NV 0x9281
+#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define GL_BLUE_NV 0x1905
+#define GL_COLORBURN_NV 0x929A
+#define GL_COLORDODGE_NV 0x9299
+#define GL_CONJOINT_NV 0x9284
+#define GL_CONTRAST_NV 0x92A1
+#define GL_DARKEN_NV 0x9297
+#define GL_DIFFERENCE_NV 0x929E
+#define GL_DISJOINT_NV 0x9283
+#define GL_DST_ATOP_NV 0x928F
+#define GL_DST_IN_NV 0x928B
+#define GL_DST_NV 0x9287
+#define GL_DST_OUT_NV 0x928D
+#define GL_DST_OVER_NV 0x9289
+#define GL_EXCLUSION_NV 0x92A0
+#define GL_GREEN_NV 0x1904
+#define GL_HARDLIGHT_NV 0x929B
+#define GL_HARDMIX_NV 0x92A9
+#define GL_HSL_COLOR_NV 0x92AF
+#define GL_HSL_HUE_NV 0x92AD
+#define GL_HSL_LUMINOSITY_NV 0x92B0
+#define GL_HSL_SATURATION_NV 0x92AE
+#define GL_INVERT_OVG_NV 0x92B4
+#define GL_INVERT_RGB_NV 0x92A3
+#define GL_LIGHTEN_NV 0x9298
+#define GL_LINEARBURN_NV 0x92A5
+#define GL_LINEARDODGE_NV 0x92A4
+#define GL_LINEARLIGHT_NV 0x92A7
+#define GL_MINUS_CLAMPED_NV 0x92B3
+#define GL_MINUS_NV 0x929F
+#define GL_MULTIPLY_NV 0x9294
+#define GL_OVERLAY_NV 0x9296
+#define GL_PINLIGHT_NV 0x92A8
+#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define GL_PLUS_CLAMPED_NV 0x92B1
+#define GL_PLUS_DARKER_NV 0x9292
+#define GL_PLUS_NV 0x9291
+#define GL_RED_NV 0x1903
+#define GL_SCREEN_NV 0x9295
+#define GL_SOFTLIGHT_NV 0x929C
+#define GL_SRC_ATOP_NV 0x928E
+#define GL_SRC_IN_NV 0x928A
+#define GL_SRC_NV 0x9286
+#define GL_SRC_OUT_NV 0x928C
+#define GL_SRC_OVER_NV 0x9288
+#define GL_UNCORRELATED_NV 0x9282
+#define GL_VIVIDLIGHT_NV 0x92A6
+#define GL_XOR_NV 0x1506
+typedef void (APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLBLENDBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendParameteriNV (GLenum pname, GLint value);
+GLAPI void APIENTRY glBlendBarrierNV (void);
+#endif
+#endif /* GL_NV_blend_equation_advanced */
+
+#ifndef GL_NV_blend_equation_advanced_coherent
+#define GL_NV_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif /* GL_NV_blend_square */
+
+#ifndef GL_NV_compute_program5
+#define GL_NV_compute_program5 1
+#define GL_COMPUTE_PROGRAM_NV 0x90FB
+#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
+#endif /* GL_NV_compute_program5 */
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+#endif /* GL_NV_copy_depth_to_color */
+
+#ifndef GL_NV_copy_image
+#define GL_NV_copy_image 1
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyImageSubDataNV (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+#endif /* GL_NV_copy_image */
+
+#ifndef GL_NV_deep_texture3D
+#define GL_NV_deep_texture3D 1
+#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0
+#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1
+#endif /* GL_NV_deep_texture3D */
+
+#ifndef GL_NV_depth_buffer_float
+#define GL_NV_depth_buffer_float 1
+#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glClearDepthdNV (GLdouble depth);
+GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax);
+#endif
+#endif /* GL_NV_depth_buffer_float */
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#define GL_DEPTH_CLAMP_NV 0x864F
+#endif /* GL_NV_depth_clamp */
+
+#ifndef GL_NV_draw_texture
+#define GL_NV_draw_texture 1
+typedef void (APIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawTextureNV (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+#endif
+#endif /* GL_NV_draw_texture */
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points);
+typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points);
+GLAPI void APIENTRY glMapParameterivNV (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points);
+GLAPI void APIENTRY glGetMapParameterivNV (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glEvalMapsNV (GLenum target, GLenum mode);
+#endif
+#endif /* GL_NV_evaluators */
+
+#ifndef GL_NV_explicit_multisample
+#define GL_NV_explicit_multisample 1
+#define GL_SAMPLE_POSITION_NV 0x8E50
+#define GL_SAMPLE_MASK_NV 0x8E51
+#define GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);
+typedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetMultisamplefvNV (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaskIndexedNV (GLuint index, GLbitfield mask);
+GLAPI void APIENTRY glTexRenderbufferNV (GLenum target, GLuint renderbuffer);
+#endif
+#endif /* GL_NV_explicit_multisample */
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GLAPI GLboolean APIENTRY glIsFenceNV (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceNV (GLuint fence);
+GLAPI void APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFinishFenceNV (GLuint fence);
+GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+#endif /* GL_NV_fence */
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+#endif /* GL_NV_float_buffer */
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+#endif /* GL_NV_fog_distance */
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+#endif /* GL_NV_fragment_program */
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+#endif /* GL_NV_fragment_program2 */
+
+#ifndef GL_NV_fragment_program4
+#define GL_NV_fragment_program4 1
+#endif /* GL_NV_fragment_program4 */
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+#endif /* GL_NV_fragment_program_option */
+
+#ifndef GL_NV_framebuffer_multisample_coverage
+#define GL_NV_framebuffer_multisample_coverage 1
+#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+#ifndef GL_NV_geometry_program4
+#define GL_NV_geometry_program4 1
+#define GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit);
+GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+#endif /* GL_NV_geometry_program4 */
+
+#ifndef GL_NV_geometry_shader4
+#define GL_NV_geometry_shader4 1
+#endif /* GL_NV_geometry_shader4 */
+
+#ifndef GL_NV_gpu_program4
+#define GL_NV_gpu_program4 1
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+#endif
+#endif /* GL_NV_gpu_program4 */
+
+#ifndef GL_NV_gpu_program5
+#define GL_NV_gpu_program5 1
+#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F
+#define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
+#define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45
+typedef void (APIENTRYP PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC) (GLenum target, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC) (GLenum target, GLuint index, GLuint *param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramSubroutineParametersuivNV (GLenum target, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramSubroutineParameteruivNV (GLenum target, GLuint index, GLuint *param);
+#endif
+#endif /* GL_NV_gpu_program5 */
+
+#ifndef GL_NV_gpu_program5_mem_extended
+#define GL_NV_gpu_program5_mem_extended 1
+#endif /* GL_NV_gpu_program5_mem_extended */
+
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+#endif /* GL_NV_gpu_shader5 */
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+typedef unsigned short GLhalfNV;
+#define GL_HALF_FLOAT_NV 0x140B
+typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);
+typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
+typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV s);
+GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum target, GLhalfNV s);
+GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
+GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
+GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
+GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
+GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x);
+GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+#endif /* GL_NV_half_float */
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+#endif /* GL_NV_light_max_exponent */
+
+#ifndef GL_NV_multisample_coverage
+#define GL_NV_multisample_coverage 1
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#endif /* GL_NV_multisample_coverage */
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+#endif /* GL_NV_multisample_filter_hint */
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glEndOcclusionQueryNV (void);
+GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_NV_occlusion_query */
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+#endif /* GL_NV_packed_depth_stencil */
+
+#ifndef GL_NV_parameter_buffer_object
+#define GL_NV_parameter_buffer_object 1
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params);
+#endif
+#endif /* GL_NV_parameter_buffer_object */
+
+#ifndef GL_NV_parameter_buffer_object2
+#define GL_NV_parameter_buffer_object2 1
+#endif /* GL_NV_parameter_buffer_object2 */
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_ROUNDED_RECT_NV 0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define GL_ROUNDED_RECT2_NV 0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define GL_ROUNDED_RECT4_NV 0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define GL_ROUNDED_RECT8_NV 0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define GL_RELATIVE_RECT_NV 0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define GL_FONT_UNAVAILABLE_NV 0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define GL_CONIC_CURVE_TO_NV 0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define GL_2_BYTES_NV 0x1407
+#define GL_3_BYTES_NV 0x1408
+#define GL_4_BYTES_NV 0x1409
+#define GL_EYE_LINEAR_NV 0x2400
+#define GL_OBJECT_LINEAR_NV 0x2401
+#define GL_CONSTANT_NV 0x8576
+#define GL_PATH_PROJECTION_NV 0x1701
+#define GL_PATH_MODELVIEW_NV 0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV 0x936D
+typedef GLuint (APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode);
+typedef void (APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value);
+typedef GLboolean (APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenPathsNV (GLsizei range);
+GLAPI void APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GLAPI GLboolean APIENTRY glIsPathNV (GLuint path);
+GLAPI void APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GLAPI void APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GLAPI void APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GLAPI void APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GLAPI void APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GLAPI void APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GLAPI void APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GLAPI void APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GLAPI void APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GLAPI void APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GLAPI void APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GLAPI void APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GLAPI void APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathFogGenNV (GLenum genMode);
+GLAPI void APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GLAPI void APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GLAPI void APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GLAPI void APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GLAPI void APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GLAPI void APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GLAPI void APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GLAPI void APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GLAPI void APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value);
+GLAPI GLboolean APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GLAPI GLboolean APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GLAPI GLfloat APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GLAPI GLboolean APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GLAPI void APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GLAPI void APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GLAPI void APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GLAPI GLenum APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI GLenum APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, const void *pointer);
+typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, const void *pointer);
+GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target);
+#endif
+#endif /* GL_NV_pixel_data_range */
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameterivNV (GLenum pname, const GLint *params);
+#endif
+#endif /* GL_NV_point_sprite */
+
+#ifndef GL_NV_present_video
+#define GL_NV_present_video 1
+#define GL_FRAME_NV 0x8E26
+#define GL_FIELDS_NV 0x8E27
+#define GL_CURRENT_TIME_NV 0x8E28
+#define GL_NUM_FILL_STREAMS_NV 0x8E29
+#define GL_PRESENT_TIME_NV 0x8E2A
+#define GL_PRESENT_DURATION_NV 0x8E2B
+typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+GLAPI void APIENTRY glGetVideoivNV (GLuint video_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideouivNV (GLuint video_slot, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glGetVideoi64vNV (GLuint video_slot, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVideoui64vNV (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#endif
+#endif /* GL_NV_present_video */
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveRestartNV (void);
+GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index);
+#endif
+#endif /* GL_NV_primitive_restart */
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerParameterfvNV (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glCombinerParameterfNV (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glCombinerParameterivNV (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCombinerParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+GLAPI void APIENTRY glFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params);
+#endif
+#endif /* GL_NV_register_combiners */
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_NV_register_combiners2 */
+
+#ifndef GL_NV_shader_atomic_counters
+#define GL_NV_shader_atomic_counters 1
+#endif /* GL_NV_shader_atomic_counters */
+
+#ifndef GL_NV_shader_atomic_float
+#define GL_NV_shader_atomic_float 1
+#endif /* GL_NV_shader_atomic_float */
+
+#ifndef GL_NV_shader_atomic_int64
+#define GL_NV_shader_atomic_int64 1
+#endif /* GL_NV_shader_atomic_int64 */
+
+#ifndef GL_NV_shader_buffer_load
+#define GL_NV_shader_buffer_load 1
+#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define GL_GPU_ADDRESS_NV 0x8F34
+#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result);
+typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access);
+GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target);
+GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target);
+GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access);
+GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer);
+GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer);
+GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result);
+GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_NV_shader_buffer_load */
+
+#ifndef GL_NV_shader_buffer_store
+#define GL_NV_shader_buffer_store 1
+#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010
+#endif /* GL_NV_shader_buffer_store */
+
+#ifndef GL_NV_shader_storage_buffer_object
+#define GL_NV_shader_storage_buffer_object 1
+#endif /* GL_NV_shader_storage_buffer_object */
+
+#ifndef GL_NV_shader_thread_group
+#define GL_NV_shader_thread_group 1
+#define GL_WARP_SIZE_NV 0x9339
+#define GL_WARPS_PER_SM_NV 0x933A
+#define GL_SM_COUNT_NV 0x933B
+#endif /* GL_NV_shader_thread_group */
+
+#ifndef GL_NV_shader_thread_shuffle
+#define GL_NV_shader_thread_shuffle 1
+#endif /* GL_NV_shader_thread_shuffle */
+
+#ifndef GL_NV_tessellation_program5
+#define GL_NV_tessellation_program5 1
+#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+#endif /* GL_NV_tessellation_program5 */
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+#endif /* GL_NV_texgen_emboss */
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+#endif /* GL_NV_texgen_reflection */
+
+#ifndef GL_NV_texture_barrier
+#define GL_NV_texture_barrier 1
+typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureBarrierNV (void);
+#endif
+#endif /* GL_NV_texture_barrier */
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif /* GL_NV_texture_compression_vtc */
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+#endif /* GL_NV_texture_env_combine4 */
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#endif /* GL_NV_texture_expand_normal */
+
+#ifndef GL_NV_texture_multisample
+#define GL_NV_texture_multisample 1
+#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045
+#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage2DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTexImage3DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage2DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage3DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage2DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+#endif
+#endif /* GL_NV_texture_multisample */
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+#endif /* GL_NV_texture_rectangle */
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+#endif /* GL_NV_texture_shader */
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#endif /* GL_NV_texture_shader2 */
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+#endif /* GL_NV_texture_shader3 */
+
+#ifndef GL_NV_transform_feedback
+#define GL_NV_transform_feedback 1
+#define GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define GL_TEXTURE_COORD_NV 0x8C79
+#define GL_CLIP_DISTANCE_NV 0x8C7A
+#define GL_VERTEX_ID_NV 0x8C7B
+#define GL_PRIMITIVE_ID_NV 0x8C7C
+#define GL_GENERIC_ATTRIB_NV 0x8C7D
+#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define GL_ACTIVE_VARYINGS_NV 0x8C81
+#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define GL_RASTERIZER_DISCARD_NV 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+#define GL_LAYER_NV 0x8DAA
+#define GL_NEXT_BUFFER_NV -2
+#define GL_SKIP_COMPONENTS4_NV -3
+#define GL_SKIP_COMPONENTS3_NV -4
+#define GL_SKIP_COMPONENTS2_NV -5
+#define GL_SKIP_COMPONENTS1_NV -6
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackNV (void);
+GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLsizei count, const GLint *attribs, GLenum bufferMode);
+GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+GLAPI void APIENTRY glActiveVaryingNV (GLuint program, const GLchar *name);
+GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location);
+GLAPI void APIENTRY glTransformFeedbackStreamAttribsNV (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#endif
+#endif /* GL_NV_transform_feedback */
+
+#ifndef GL_NV_transform_feedback2
+#define GL_NV_transform_feedback2 1
+#define GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindTransformFeedbackNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedbackNV (void);
+GLAPI void APIENTRY glResumeTransformFeedbackNV (void);
+GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
+#endif
+#endif /* GL_NV_transform_feedback2 */
+
+#ifndef GL_NV_uniform_buffer_unified_memory
+#define GL_NV_uniform_buffer_unified_memory 1
+#define GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E
+#define GL_UNIFORM_BUFFER_ADDRESS_NV 0x936F
+#define GL_UNIFORM_BUFFER_LENGTH_NV 0x9370
+#endif /* GL_NV_uniform_buffer_unified_memory */
+
+#ifndef GL_NV_vdpau_interop
+#define GL_NV_vdpau_interop 1
+typedef GLintptr GLvdpauSurfaceNV;
+#define GL_SURFACE_STATE_NV 0x86EB
+#define GL_SURFACE_REGISTERED_NV 0x86FD
+#define GL_SURFACE_MAPPED_NV 0x8700
+#define GL_WRITE_DISCARD_NV 0x88BE
+typedef void (APIENTRYP PFNGLVDPAUINITNVPROC) (const void *vdpDevice, const void *getProcAddress);
+typedef void (APIENTRYP PFNGLVDPAUFININVPROC) (void);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLboolean (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
+typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVDPAUInitNV (const void *vdpDevice, const void *getProcAddress);
+GLAPI void APIENTRY glVDPAUFiniNV (void);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLboolean APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access);
+GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#endif
+#endif /* GL_NV_vdpau_interop */
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushVertexArrayRangeNV (void);
+GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei length, const void *pointer);
+#endif
+#endif /* GL_NV_vertex_array_range */
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif /* GL_NV_vertex_array_range2 */
+
+#ifndef GL_NV_vertex_attrib_integer_64bit
+#define GL_NV_vertex_attrib_integer_64bit 1
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+#endif
+#endif /* GL_NV_vertex_attrib_integer_64bit */
+
+#ifndef GL_NV_vertex_buffer_unified_memory
+#define GL_NV_vertex_buffer_unified_memory 1
+#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride);
+GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result);
+#endif
+#endif /* GL_NV_vertex_buffer_unified_memory */
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences);
+GLAPI void APIENTRY glBindProgramNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params);
+GLAPI void APIENTRY glGenProgramsNV (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program);
+GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint index, GLenum pname, void **pointer);
+GLAPI GLboolean APIENTRY glIsProgramNV (GLuint id);
+GLAPI void APIENTRY glLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+GLAPI void APIENTRY glProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glProgramParameters4dvNV (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameters4fvNV (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+GLAPI void APIENTRY glVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glVertexAttrib1dNV (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fNV (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sNV (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sNV (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+#endif /* GL_NV_vertex_program */
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif /* GL_NV_vertex_program1_1 */
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif /* GL_NV_vertex_program2 */
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+#endif /* GL_NV_vertex_program2_option */
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+#endif /* GL_NV_vertex_program3 */
+
+#ifndef GL_NV_vertex_program4
+#define GL_NV_vertex_program4 1
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_NV_vertex_program4 */
+
+#ifndef GL_NV_video_capture
+#define GL_NV_video_capture 1
+#define GL_VIDEO_BUFFER_NV 0x9020
+#define GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define GL_FIELD_UPPER_NV 0x9022
+#define GL_FIELD_LOWER_NV 0x9023
+#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define GL_PARTIAL_SUCCESS_NV 0x902E
+#define GL_SUCCESS_NV 0x902F
+#define GL_FAILURE_NV 0x9030
+#define GL_YCBYCR8_422_NV 0x9031
+#define GL_YCBAYCR8A_4224_NV 0x9032
+#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+typedef void (APIENTRYP PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+typedef GLenum (APIENTRYP PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glBindVideoCaptureStreamBufferNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+GLAPI void APIENTRY glBindVideoCaptureStreamTextureNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+GLAPI void APIENTRY glEndVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glGetVideoCaptureivNV (GLuint video_capture_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+GLAPI GLenum APIENTRY glVideoCaptureNV (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+GLAPI void APIENTRY glVideoCaptureStreamParameterivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#endif
+#endif /* GL_NV_video_capture */
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+#endif /* GL_OML_interlace */
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+#endif /* GL_OML_resample */
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+#endif /* GL_OML_subsample */
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI 0x1A219
+#define GL_CLIP_NEAR_HINT_PGI 0x1A220
+#define GL_CLIP_FAR_HINT_PGI 0x1A221
+#define GL_WIDE_LINE_HINT_PGI 0x1A222
+#define GL_BACK_NORMALS_HINT_PGI 0x1A223
+typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glHintPGI (GLenum target, GLint mode);
+#endif
+#endif /* GL_PGI_misc_hints */
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+#define GL_VERTEX_DATA_HINT_PGI 0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI 0x1A22D
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#endif /* GL_PGI_vertex_hints */
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+#endif /* GL_REND_screen_coordinates */
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#define GL_RGBA_DXT5_S3TC 0x83A4
+#define GL_RGBA4_DXT5_S3TC 0x83A5
+#endif /* GL_S3_s3tc */
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS 0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+#endif /* GL_SGIS_detail_texture */
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+#define GL_FOG_FUNC_SGIS 0x812A
+#define GL_FOG_FUNC_POINTS_SGIS 0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C
+typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogFuncSGIS (GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *points);
+#endif
+#endif /* GL_SGIS_fog_function */
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+#endif /* GL_SGIS_generate_mipmap */
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskSGIS (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternSGIS (GLenum pattern);
+#endif
+#endif /* GL_SGIS_multisample */
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+#define GL_PIXEL_TEXTURE_SGIS 0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_SGIS_pixel_texture */
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+#endif /* GL_SGIS_point_line_texgen */
+
+#ifndef GL_SGIS_point_parameters
+#define GL_SGIS_point_parameters 1
+#define GL_POINT_SIZE_MIN_SGIS 0x8126
+#define GL_POINT_SIZE_MAX_SGIS 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define GL_DISTANCE_ATTENUATION_SGIS 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvSGIS (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_SGIS_point_parameters */
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+#define GL_LINEAR_SHARPEN_SGIS 0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+#endif /* GL_SGIS_sharpen_texture */
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133
+#define GL_TEXTURE_4D_SGIS 0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS 0x8135
+#define GL_TEXTURE_4DSIZE_SGIS 0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS 0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS 0x814F
+typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_SGIS_texture4D */
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+#endif /* GL_SGIS_texture_border_clamp */
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_SGIS_texture_color_mask 1
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF
+typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+#endif /* GL_SGIS_texture_color_mask */
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+#endif /* GL_SGIS_texture_edge_clamp */
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+#define GL_FILTER4_SGIS 0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147
+typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);
+typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights);
+GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+#endif /* GL_SGIS_texture_filter4 */
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+#endif /* GL_SGIS_texture_lod */
+
+#ifndef GL_SGIS_texture_select
+#define GL_SGIS_texture_select 1
+#define GL_DUAL_ALPHA4_SGIS 0x8110
+#define GL_DUAL_ALPHA8_SGIS 0x8111
+#define GL_DUAL_ALPHA12_SGIS 0x8112
+#define GL_DUAL_ALPHA16_SGIS 0x8113
+#define GL_DUAL_LUMINANCE4_SGIS 0x8114
+#define GL_DUAL_LUMINANCE8_SGIS 0x8115
+#define GL_DUAL_LUMINANCE12_SGIS 0x8116
+#define GL_DUAL_LUMINANCE16_SGIS 0x8117
+#define GL_DUAL_INTENSITY4_SGIS 0x8118
+#define GL_DUAL_INTENSITY8_SGIS 0x8119
+#define GL_DUAL_INTENSITY12_SGIS 0x811A
+#define GL_DUAL_INTENSITY16_SGIS 0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D
+#define GL_QUAD_ALPHA4_SGIS 0x811E
+#define GL_QUAD_ALPHA8_SGIS 0x811F
+#define GL_QUAD_LUMINANCE4_SGIS 0x8120
+#define GL_QUAD_LUMINANCE8_SGIS 0x8121
+#define GL_QUAD_INTENSITY4_SGIS 0x8122
+#define GL_QUAD_INTENSITY8_SGIS 0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125
+#endif /* GL_SGIS_texture_select */
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+#define GL_ASYNC_MARKER_SGIX 0x8329
+typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);
+typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);
+typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint marker);
+GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *markerp);
+GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *markerp);
+GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei range);
+GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range);
+GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint marker);
+#endif
+#endif /* GL_SGIX_async */
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+#endif /* GL_SGIX_async_histogram */
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+#endif /* GL_SGIX_async_pixel */
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_SGIX_calligraphic_fragment 1
+#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183
+#endif /* GL_SGIX_calligraphic_fragment */
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F
+#endif /* GL_SGIX_clipmap */
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+#endif /* GL_SGIX_convolution_accuracy */
+
+#ifndef GL_SGIX_depth_pass_instrument
+#define GL_SGIX_depth_pass_instrument 1
+#endif /* GL_SGIX_depth_pass_instrument */
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+#endif /* GL_SGIX_depth_texture */
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushRasterSGIX (void);
+#endif
+#endif /* GL_SGIX_flush_raster */
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+#endif /* GL_SGIX_fog_offset */
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_SGIX_fragment_lighting 1
+#define GL_FRAGMENT_LIGHTING_SGIX 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405
+#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406
+#define GL_LIGHT_ENV_MODE_SGIX 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define GL_FRAGMENT_LIGHT0_SGIX 0x840C
+#define GL_FRAGMENT_LIGHT1_SGIX 0x840D
+#define GL_FRAGMENT_LIGHT2_SGIX 0x840E
+#define GL_FRAGMENT_LIGHT3_SGIX 0x840F
+#define GL_FRAGMENT_LIGHT4_SGIX 0x8410
+#define GL_FRAGMENT_LIGHT5_SGIX 0x8411
+#define GL_FRAGMENT_LIGHT6_SGIX 0x8412
+#define GL_FRAGMENT_LIGHT7_SGIX 0x8413
+typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum face, GLenum mode);
+GLAPI void APIENTRY glFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightiSGIX (GLenum light, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params);
+GLAPI void APIENTRY glLightEnviSGIX (GLenum pname, GLint param);
+#endif
+#endif /* GL_SGIX_fragment_lighting */
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+#define GL_FRAMEZOOM_SGIX 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D
+typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameZoomSGIX (GLint factor);
+#endif
+#endif /* GL_SGIX_framezoom */
+
+#ifndef GL_SGIX_igloo_interface
+#define GL_SGIX_igloo_interface 1
+typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const void *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum pname, const void *params);
+#endif
+#endif /* GL_SGIX_igloo_interface */
+
+#ifndef GL_SGIX_instruments
+#define GL_SGIX_instruments 1
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181
+typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);
+typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);
+typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetInstrumentsSGIX (void);
+GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei size, GLint *buffer);
+GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *marker_p);
+GLAPI void APIENTRY glReadInstrumentsSGIX (GLint marker);
+GLAPI void APIENTRY glStartInstrumentsSGIX (void);
+GLAPI void APIENTRY glStopInstrumentsSGIX (GLint marker);
+#endif
+#endif /* GL_SGIX_instruments */
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+#define GL_INTERLACE_SGIX 0x8094
+#endif /* GL_SGIX_interlace */
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+#define GL_IR_INSTRUMENT1_SGIX 0x817F
+#endif /* GL_SGIX_ir_instrument1 */
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+#define GL_LIST_PRIORITY_SGIX 0x8182
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params);
+GLAPI void APIENTRY glListParameterfSGIX (GLuint list, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glListParameteriSGIX (GLuint list, GLenum pname, GLint param);
+GLAPI void APIENTRY glListParameterivSGIX (GLuint list, GLenum pname, const GLint *params);
+#endif
+#endif /* GL_SGIX_list_priority */
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+#define GL_PIXEL_TEX_GEN_SGIX 0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B
+typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenSGIX (GLenum mode);
+#endif
+#endif /* GL_SGIX_pixel_texture */
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_SGIX_pixel_tiles 1
+#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140
+#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141
+#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142
+#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143
+#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144
+#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145
+#endif /* GL_SGIX_pixel_tiles */
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_SGIX_polynomial_ffd 1
+#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001
+#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002
+#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194
+#define GL_TEXTURE_DEFORMATION_SGIX 0x8195
+#define GL_DEFORMATIONS_MASK_SGIX 0x8196
+#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+GLAPI void APIENTRY glDeformSGIX (GLbitfield mask);
+GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield mask);
+#endif
+#endif /* GL_SGIX_polynomial_ffd */
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+#define GL_REFERENCE_PLANE_SGIX 0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E
+typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation);
+#endif
+#endif /* GL_SGIX_reference_plane */
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+#define GL_PACK_RESAMPLE_SGIX 0x842C
+#define GL_UNPACK_RESAMPLE_SGIX 0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX 0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#endif /* GL_SGIX_resample */
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SGIX_scalebias_hint 1
+#define GL_SCALEBIAS_HINT_SGIX 0x8322
+#endif /* GL_SGIX_scalebias_hint */
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+#endif /* GL_SGIX_shadow */
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+#endif /* GL_SGIX_shadow_ambient */
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+#define GL_SPRITE_SGIX 0x8148
+#define GL_SPRITE_MODE_SGIX 0x8149
+#define GL_SPRITE_AXIS_SGIX 0x814A
+#define GL_SPRITE_TRANSLATION_SGIX 0x814B
+#define GL_SPRITE_AXIAL_SGIX 0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum pname, const GLint *params);
+#endif
+#endif /* GL_SGIX_sprite */
+
+#ifndef GL_SGIX_subsample
+#define GL_SGIX_subsample 1
+#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0
+#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1
+#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2
+#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3
+#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4
+#endif /* GL_SGIX_subsample */
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTagSampleBufferSGIX (void);
+#endif
+#endif /* GL_SGIX_tag_sample_buffer */
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE
+#endif /* GL_SGIX_texture_add_env */
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190
+#endif /* GL_SGIX_texture_lod_bias */
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif /* GL_SGIX_texture_multi_buffer */
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif /* GL_SGIX_texture_scale_bias */
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+#endif /* GL_SGIX_vertex_preclip */
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+#define GL_YCRCB_422_SGIX 0x81BB
+#define GL_YCRCB_444_SGIX 0x81BC
+#endif /* GL_SGIX_ycrcb */
+
+#ifndef GL_SGIX_ycrcb_subsample
+#define GL_SGIX_ycrcb_subsample 1
+#endif /* GL_SGIX_ycrcb_subsample */
+
+#ifndef GL_SGIX_ycrcba
+#define GL_SGIX_ycrcba 1
+#define GL_YCRCB_SGIX 0x8318
+#define GL_YCRCBA_SGIX 0x8319
+#endif /* GL_SGIX_ycrcba */
+
+#ifndef GL_SGI_color_matrix
+#define GL_SGI_color_matrix 1
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif /* GL_SGI_color_matrix */
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTableSGI (GLenum target, GLenum format, GLenum type, void *table);
+GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params);
+#endif
+#endif /* GL_SGI_color_table */
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+#endif /* GL_SGI_texture_color_table */
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFinishTextureSUNX (void);
+#endif
+#endif /* GL_SUNX_constant_data */
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+#define GL_WRAP_BORDER_SUN 0x81D4
+#endif /* GL_SUN_convolution_border_modes */
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint factor);
+GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat factor);
+GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble factor);
+GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint factor);
+#endif
+#endif /* GL_SUN_global_alpha */
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+#endif /* GL_SUN_mesh_array */
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+#define GL_SLICE_ACCUM_SUN 0x85CC
+#endif /* GL_SUN_slice_accum */
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+#define GL_RESTART_SUN 0x0001
+#define GL_REPLACE_MIDDLE_SUN 0x0002
+#define GL_REPLACE_OLDEST_SUN 0x0003
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint code);
+GLAPI void APIENTRY glReplacementCodeusSUN (GLushort code);
+GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte code);
+GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *code);
+GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *code);
+GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *code);
+GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum type, GLsizei stride, const void **pointer);
+#endif
+#endif /* GL_SUN_triangle_list */
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+#endif /* GL_SUN_vertex */
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+#endif /* GL_WIN_phong_shading */
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+#endif /* GL_WIN_specular_fog */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glfuncdef.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glfuncdef.h
new file mode 100644
index 00000000..cd50a3a3
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glfuncdef.h
@@ -0,0 +1,343 @@
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise Under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2012 NVIDIA Corporation. All rights reserved.
+
+/*
+** Copyright (c) 2013-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+*/
+
+
+/// @file glfuncdef.h
+/// this is our internal OpenGL function header define
+
+#ifndef __gl_func_def_h_
+#define __gl_func_def_h_
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------
+ * GL2 core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const char* name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawBuffers( GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const char* name);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const char* name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+
+/*-------------------------------------------------------------------------
+ * GL3 core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFragDataLocation (GLuint program, GLuint colorNumber, const GLchar * name);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params);
+GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex( GLuint program, const GLchar *uniformBlockName);
+GL_APICALL GLvoid* GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glQueryCounter (GLuint id, GLenum target);
+GL_APICALL void GL_APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+/*-------------------------------------------------------------------------
+ * GL4 core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val );
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glMinSampleShading (GLfloat value );
+GL_APICALL void GL_APIENTRY glPatchParameteri (GLenum pname, GLint value );
+GL_APICALL void GL_APIENTRY glPatchParameterfv (GLenum pname, GLint value );
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLint target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline);
+
+
+/*-------------------------------------------------------------------------
+ * GL4 NV extensions
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GL_APICALL void GL_APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glPathFogGenNV (GLenum genMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GL_APICALL void GL_APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glMatrixLoadf (GLenum mode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glBlendBarrierNV( void );
+GL_APICALL void GL_APIENTRY glBlendParameteriNV( GLenum pname, GLint value );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl_func_def_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glu.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glu.h
new file mode 100644
index 00000000..54bc52bc
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glu.h
@@ -0,0 +1,607 @@
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+
+Copyright (c) 1985-95, Microsoft Corporation
+
+Module Name:
+
+ glu.h
+
+Abstract:
+
+ Procedure declarations, constant definitions and macros for the OpenGL
+ Utility Library.
+
+--*/
+
+#ifndef __glu_h__
+#ifndef __GLU_H__
+
+#define __glu_h__
+#define __GLU_H__
+
+#include <GL/gl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright 1991-1993, Silicon Graphics, Inc.
+** All Rights Reserved.
+**
+** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
+** the contents of this file may not be disclosed to third parties, copied or
+** duplicated in any form, in whole or in part, without the prior written
+** permission of Silicon Graphics, Inc.
+**
+** RESTRICTED RIGHTS LEGEND:
+** Use, duplication or disclosure by the Government is subject to restrictions
+** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
+** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
+** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
+** rights reserved under the Copyright Laws of the United States.
+*/
+
+/*
+** Return the error string associated with a particular error code.
+** This will return 0 for an invalid error code.
+**
+** The generic function prototype that can be compiled for ANSI or Unicode
+** is defined as follows:
+**
+** LPCTSTR APIENTRY gluErrorStringWIN (GLenum errCode);
+*/
+#ifdef UNICODE
+#define gluErrorStringWIN(errCode) ((LPCSTR) gluErrorUnicodeStringEXT(errCode))
+#else
+#define gluErrorStringWIN(errCode) ((LPCWSTR) gluErrorString(errCode))
+#endif
+
+/* XXX APIENTRY and CALLBACK defined added by aritger */
+#ifndef APIENTRY
+# define APIENTRY
+#endif
+
+#ifndef CALLBACK
+# define CALLBACK
+#endif
+
+const GLubyte* APIENTRY gluErrorString (
+ GLenum errCode);
+
+/* XXX aritger: gluErrorUnicodeStringEXT() appears to be a MicroSoft addition */
+#if defined(_WIN32)
+const wchar_t* APIENTRY gluErrorUnicodeStringEXT (
+ GLenum errCode);
+#endif
+
+const GLubyte* APIENTRY gluGetString (
+ GLenum name);
+
+void APIENTRY gluOrtho2D (
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top);
+
+void APIENTRY gluPerspective (
+ GLdouble fovy,
+ GLdouble aspect,
+ GLdouble zNear,
+ GLdouble zFar);
+
+void APIENTRY gluPickMatrix (
+ GLdouble x,
+ GLdouble y,
+ GLdouble width,
+ GLdouble height,
+ GLint viewport[4]);
+
+void APIENTRY gluLookAt (
+ GLdouble eyex,
+ GLdouble eyey,
+ GLdouble eyez,
+ GLdouble centerx,
+ GLdouble centery,
+ GLdouble centerz,
+ GLdouble upx,
+ GLdouble upy,
+ GLdouble upz);
+
+int APIENTRY gluProject (
+ GLdouble objx,
+ GLdouble objy,
+ GLdouble objz,
+ const GLdouble modelMatrix[16],
+ const GLdouble projMatrix[16],
+ const GLint viewport[4],
+ GLdouble *winx,
+ GLdouble *winy,
+ GLdouble *winz);
+
+int APIENTRY gluUnProject (
+ GLdouble winx,
+ GLdouble winy,
+ GLdouble winz,
+ const GLdouble modelMatrix[16],
+ const GLdouble projMatrix[16],
+ const GLint viewport[4],
+ GLdouble *objx,
+ GLdouble *objy,
+ GLdouble *objz);
+
+
+int APIENTRY gluScaleImage (
+ GLenum format,
+ GLint widthin,
+ GLint heightin,
+ GLenum typein,
+ const void *datain,
+ GLint widthout,
+ GLint heightout,
+ GLenum typeout,
+ void *dataout);
+
+
+int APIENTRY gluBuild1DMipmaps (
+ GLenum target,
+ GLint components,
+ GLint width,
+ GLenum format,
+ GLenum type,
+ const void *data);
+
+int APIENTRY gluBuild2DMipmaps (
+ GLenum target,
+ GLint components,
+ GLint width,
+ GLint height,
+ GLenum format,
+ GLenum type,
+ const void *data);
+
+#ifdef __cplusplus
+
+class GLUnurbs;
+class GLUquadric;
+class GLUtesselator;
+
+/* backwards compatibility: */
+typedef class GLUnurbs GLUnurbsObj;
+typedef class GLUquadric GLUquadricObj;
+typedef class GLUtesselator GLUtesselatorObj;
+typedef class GLUtesselator GLUtriangulatorObj;
+
+#else
+
+typedef struct GLUnurbs GLUnurbs;
+typedef struct GLUquadric GLUquadric;
+typedef struct GLUtesselator GLUtesselator;
+
+/* backwards compatibility: */
+typedef struct GLUnurbs GLUnurbsObj;
+typedef struct GLUquadric GLUquadricObj;
+typedef struct GLUtesselator GLUtesselatorObj;
+typedef struct GLUtesselator GLUtriangulatorObj;
+
+#endif
+
+// (NVIDIA change: pbrown) GLUcallbackFuncPtr is a general-purpose function
+// pointer type for GLU callbacks. We declare a "void" argument list in the
+// prototype as a least-common-denominator to avoid "function declaration
+// isn't a prototype" warnings from GCC (which until late 2010 didn't have a
+// good way to temporarily change warning state via #pragma). Most, but not
+// all, GLU callbacks do take one or more arguments, so will likely need
+// manual casts. The fundamental problem is that the actual argument list is
+// typically a function of the <which> argument in the
+// glu{Tess,Nurbs}Callback, so there is no good way to check for correctness
+// at compile time.
+typedef void (CALLBACK* GLUcallbackFuncPtr)(void);
+
+GLUquadric* APIENTRY gluNewQuadric (void);
+void APIENTRY gluDeleteQuadric (
+ GLUquadric *state);
+
+void APIENTRY gluQuadricNormals (
+ GLUquadric *quadObject,
+ GLenum normals);
+
+void APIENTRY gluQuadricTexture (
+ GLUquadric *quadObject,
+ GLboolean textureCoords);
+
+void APIENTRY gluQuadricOrientation (
+ GLUquadric *quadObject,
+ GLenum orientation);
+
+void APIENTRY gluQuadricDrawStyle (
+ GLUquadric *quadObject,
+ GLenum drawStyle);
+
+void APIENTRY gluCylinder (
+ GLUquadric *qobj,
+ GLdouble baseRadius,
+ GLdouble topRadius,
+ GLdouble height,
+ GLint slices,
+ GLint stacks);
+
+void APIENTRY gluDisk (
+ GLUquadric *qobj,
+ GLdouble innerRadius,
+ GLdouble outerRadius,
+ GLint slices,
+ GLint loops);
+
+void APIENTRY gluPartialDisk (
+ GLUquadric *qobj,
+ GLdouble innerRadius,
+ GLdouble outerRadius,
+ GLint slices,
+ GLint loops,
+ GLdouble startAngle,
+ GLdouble sweepAngle);
+
+void APIENTRY gluSphere (
+ GLUquadric *qobj,
+ GLdouble radius,
+ GLint slices,
+ GLint stacks);
+
+void APIENTRY gluQuadricCallback (
+ GLUquadric *qobj,
+ GLenum which,
+ GLUcallbackFuncPtr fn );
+
+GLUtesselator* APIENTRY gluNewTess(
+ void );
+
+void APIENTRY gluDeleteTess(
+ GLUtesselator *tess );
+
+void APIENTRY gluTessBeginPolygon(
+ GLUtesselator *tess,
+ void *polygon_data );
+
+void APIENTRY gluTessBeginContour(
+ GLUtesselator *tess );
+
+void APIENTRY gluTessVertex(
+ GLUtesselator *tess,
+ GLdouble coords[3],
+ void *data );
+
+void APIENTRY gluTessEndContour(
+ GLUtesselator *tess );
+
+void APIENTRY gluTessEndPolygon(
+ GLUtesselator *tess );
+
+void APIENTRY gluTessProperty(
+ GLUtesselator *tess,
+ GLenum which,
+ GLdouble value );
+
+void APIENTRY gluTessNormal(
+ GLUtesselator *tess,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z );
+
+void APIENTRY gluTessCallback(
+ GLUtesselator *tess,
+ GLenum which,
+ GLUcallbackFuncPtr fn );
+
+void APIENTRY gluGetTessProperty(
+ GLUtesselator *tess,
+ GLenum which,
+ GLdouble *value );
+
+GLUnurbs* APIENTRY gluNewNurbsRenderer (void);
+
+void APIENTRY gluDeleteNurbsRenderer (
+ GLUnurbs *nobj);
+
+void APIENTRY gluBeginSurface (
+ GLUnurbs *nobj);
+
+void APIENTRY gluBeginCurve (
+ GLUnurbs *nobj);
+
+void APIENTRY gluEndCurve (
+ GLUnurbs *nobj);
+
+void APIENTRY gluEndSurface (
+ GLUnurbs *nobj);
+
+void APIENTRY gluBeginTrim (
+ GLUnurbs *nobj);
+
+void APIENTRY gluEndTrim (
+ GLUnurbs *nobj);
+
+void APIENTRY gluPwlCurve (
+ GLUnurbs *nobj,
+ GLint count,
+ GLfloat *array,
+ GLint stride,
+ GLenum type);
+
+void APIENTRY gluNurbsCurve (
+ GLUnurbs *nobj,
+ GLint nknots,
+ GLfloat *knot,
+ GLint stride,
+ GLfloat *ctlarray,
+ GLint order,
+ GLenum type);
+
+void APIENTRY
+gluNurbsSurface(
+ GLUnurbs *nobj,
+ GLint sknot_count,
+ float *sknot,
+ GLint tknot_count,
+ GLfloat *tknot,
+ GLint s_stride,
+ GLint t_stride,
+ GLfloat *ctlarray,
+ GLint sorder,
+ GLint torder,
+ GLenum type);
+
+void APIENTRY
+gluLoadSamplingMatrices (
+ GLUnurbs *nobj,
+ const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4] );
+
+void APIENTRY
+gluNurbsProperty (
+ GLUnurbs *nobj,
+ GLenum property,
+ GLfloat value );
+
+void APIENTRY
+gluGetNurbsProperty (
+ GLUnurbs *nobj,
+ GLenum property,
+ GLfloat *value );
+
+void APIENTRY
+gluNurbsCallback (
+ GLUnurbs *nobj,
+ GLenum which,
+ GLUcallbackFuncPtr fn );
+
+
+/**** Callback function prototypes ****/
+
+/* gluQuadricCallback */
+typedef void (CALLBACK* GLUquadricErrorProc) (GLenum);
+
+/* gluTessCallback */
+typedef void (CALLBACK* GLUtessBeginProc) (GLenum);
+typedef void (CALLBACK* GLUtessEdgeFlagProc) (GLboolean);
+typedef void (CALLBACK* GLUtessVertexProc) (void *);
+typedef void (CALLBACK* GLUtessEndProc) (void);
+typedef void (CALLBACK* GLUtessErrorProc) (GLenum);
+typedef void (CALLBACK* GLUtessCombineProc) (GLdouble[3],
+ void*[4],
+ GLfloat[4],
+ void** );
+typedef void (CALLBACK* GLUtessBeginDataProc) (GLenum, void *);
+typedef void (CALLBACK* GLUtessEdgeFlagDataProc) (GLboolean, void *);
+typedef void (CALLBACK* GLUtessVertexDataProc) (void *, void *);
+typedef void (CALLBACK* GLUtessEndDataProc) (void *);
+typedef void (CALLBACK* GLUtessErrorDataProc) (GLenum, void *);
+typedef void (CALLBACK* GLUtessCombineDataProc) (GLdouble[3],
+ void*[4],
+ GLfloat[4],
+ void**,
+ void* );
+
+/* gluNurbsCallback */
+typedef void (CALLBACK* GLUnurbsErrorProc) (GLenum);
+
+
+/**** Generic constants ****/
+
+/* Version */
+#define GLU_VERSION_1_1 1
+#define GLU_VERSION_1_2 1
+
+/* Errors: (return value 0 = no error) */
+#define GLU_INVALID_ENUM 100900
+#define GLU_INVALID_VALUE 100901
+#define GLU_OUT_OF_MEMORY 100902
+#define GLU_INCOMPATIBLE_GL_VERSION 100903
+
+/* StringName */
+#define GLU_VERSION 100800
+#define GLU_EXTENSIONS 100801
+
+/* Boolean */
+#define GLU_TRUE GL_TRUE
+#define GLU_FALSE GL_FALSE
+
+
+/**** Quadric constants ****/
+
+/* QuadricNormal */
+#define GLU_SMOOTH 100000
+#define GLU_FLAT 100001
+#define GLU_NONE 100002
+
+/* QuadricDrawStyle */
+#define GLU_POINT 100010
+#define GLU_LINE 100011
+#define GLU_FILL 100012
+#define GLU_SILHOUETTE 100013
+
+/* QuadricOrientation */
+#define GLU_OUTSIDE 100020
+#define GLU_INSIDE 100021
+
+/* Callback types: */
+/* GLU_ERROR 100103 */
+
+
+/**** Tesselation constants ****/
+
+#define GLU_TESS_MAX_COORD 1.0e150
+
+/* TessProperty */
+#define GLU_TESS_WINDING_RULE 100140
+#define GLU_TESS_BOUNDARY_ONLY 100141
+#define GLU_TESS_TOLERANCE 100142
+
+/* TessWinding */
+#define GLU_TESS_WINDING_ODD 100130
+#define GLU_TESS_WINDING_NONZERO 100131
+#define GLU_TESS_WINDING_POSITIVE 100132
+#define GLU_TESS_WINDING_NEGATIVE 100133
+#define GLU_TESS_WINDING_ABS_GEQ_TWO 100134
+
+/* TessCallback */
+#define GLU_TESS_BEGIN 100100 /* void (CALLBACK*)(GLenum type) */
+#define GLU_TESS_VERTEX 100101 /* void (CALLBACK*)(void *data) */
+#define GLU_TESS_END 100102 /* void (CALLBACK*)(void) */
+#define GLU_TESS_ERROR 100103 /* void (CALLBACK*)(GLenum errno) */
+#define GLU_TESS_EDGE_FLAG 100104 /* void (CALLBACK*)(GLboolean boundaryEdge) */
+#define GLU_TESS_COMBINE 100105 /* void (CALLBACK*)(GLdouble coords[3],
+ void *data[4],
+ GLfloat weight[4],
+ void **dataOut) */
+#define GLU_TESS_BEGIN_DATA 100106 /* void (CALLBACK*)(GLenum type,
+ void *polygon_data) */
+#define GLU_TESS_VERTEX_DATA 100107 /* void (CALLBACK*)(void *data,
+ void *polygon_data) */
+#define GLU_TESS_END_DATA 100108 /* void (CALLBACK*)(void *polygon_data) */
+#define GLU_TESS_ERROR_DATA 100109 /* void (CALLBACK*)(GLenum errno,
+ void *polygon_data) */
+#define GLU_TESS_EDGE_FLAG_DATA 100110 /* void (CALLBACK*)(GLboolean boundaryEdge,
+ void *polygon_data) */
+#define GLU_TESS_COMBINE_DATA 100111 /* void (CALLBACK*)(GLdouble coords[3],
+ void *data[4],
+ GLfloat weight[4],
+ void **dataOut,
+ void *polygon_data) */
+
+/* TessError */
+#define GLU_TESS_ERROR1 100151
+#define GLU_TESS_ERROR2 100152
+#define GLU_TESS_ERROR3 100153
+#define GLU_TESS_ERROR4 100154
+#define GLU_TESS_ERROR5 100155
+#define GLU_TESS_ERROR6 100156
+#define GLU_TESS_ERROR7 100157
+#define GLU_TESS_ERROR8 100158
+
+#define GLU_TESS_MISSING_BEGIN_POLYGON GLU_TESS_ERROR1
+#define GLU_TESS_MISSING_BEGIN_CONTOUR GLU_TESS_ERROR2
+#define GLU_TESS_MISSING_END_POLYGON GLU_TESS_ERROR3
+#define GLU_TESS_MISSING_END_CONTOUR GLU_TESS_ERROR4
+#define GLU_TESS_COORD_TOO_LARGE GLU_TESS_ERROR5
+#define GLU_TESS_NEED_COMBINE_CALLBACK GLU_TESS_ERROR6
+
+/**** NURBS constants ****/
+
+/* NurbsProperty */
+#define GLU_AUTO_LOAD_MATRIX 100200
+#define GLU_CULLING 100201
+#define GLU_SAMPLING_TOLERANCE 100203
+#define GLU_DISPLAY_MODE 100204
+#define GLU_PARAMETRIC_TOLERANCE 100202
+#define GLU_SAMPLING_METHOD 100205
+#define GLU_U_STEP 100206
+#define GLU_V_STEP 100207
+
+/* NurbsSampling */
+#define GLU_PATH_LENGTH 100215
+#define GLU_PARAMETRIC_ERROR 100216
+#define GLU_DOMAIN_DISTANCE 100217
+
+
+/* NurbsTrim */
+#define GLU_MAP1_TRIM_2 100210
+#define GLU_MAP1_TRIM_3 100211
+
+/* NurbsDisplay */
+/* GLU_FILL 100012 */
+#define GLU_OUTLINE_POLYGON 100240
+#define GLU_OUTLINE_PATCH 100241
+
+/* NurbsCallback */
+/* GLU_ERROR 100103 */
+
+/* NurbsErrors */
+#define GLU_NURBS_ERROR1 100251
+#define GLU_NURBS_ERROR2 100252
+#define GLU_NURBS_ERROR3 100253
+#define GLU_NURBS_ERROR4 100254
+#define GLU_NURBS_ERROR5 100255
+#define GLU_NURBS_ERROR6 100256
+#define GLU_NURBS_ERROR7 100257
+#define GLU_NURBS_ERROR8 100258
+#define GLU_NURBS_ERROR9 100259
+#define GLU_NURBS_ERROR10 100260
+#define GLU_NURBS_ERROR11 100261
+#define GLU_NURBS_ERROR12 100262
+#define GLU_NURBS_ERROR13 100263
+#define GLU_NURBS_ERROR14 100264
+#define GLU_NURBS_ERROR15 100265
+#define GLU_NURBS_ERROR16 100266
+#define GLU_NURBS_ERROR17 100267
+#define GLU_NURBS_ERROR18 100268
+#define GLU_NURBS_ERROR19 100269
+#define GLU_NURBS_ERROR20 100270
+#define GLU_NURBS_ERROR21 100271
+#define GLU_NURBS_ERROR22 100272
+#define GLU_NURBS_ERROR23 100273
+#define GLU_NURBS_ERROR24 100274
+#define GLU_NURBS_ERROR25 100275
+#define GLU_NURBS_ERROR26 100276
+#define GLU_NURBS_ERROR27 100277
+#define GLU_NURBS_ERROR28 100278
+#define GLU_NURBS_ERROR29 100279
+#define GLU_NURBS_ERROR30 100280
+#define GLU_NURBS_ERROR31 100281
+#define GLU_NURBS_ERROR32 100282
+#define GLU_NURBS_ERROR33 100283
+#define GLU_NURBS_ERROR34 100284
+#define GLU_NURBS_ERROR35 100285
+#define GLU_NURBS_ERROR36 100286
+#define GLU_NURBS_ERROR37 100287
+
+/**** Backwards compatibility for old tesselator ****/
+
+void APIENTRY gluBeginPolygon( GLUtesselator *tess );
+
+void APIENTRY gluNextContour( GLUtesselator *tess,
+ GLenum type );
+
+void APIENTRY gluEndPolygon( GLUtesselator *tess );
+
+/* Contours types -- obsolete! */
+#define GLU_CW 100120
+#define GLU_CCW 100121
+#define GLU_INTERIOR 100122
+#define GLU_EXTERIOR 100123
+#define GLU_UNKNOWN 100124
+
+/* Names without "TESS_" prefix */
+#define GLU_BEGIN GLU_TESS_BEGIN
+#define GLU_VERTEX GLU_TESS_VERTEX
+#define GLU_END GLU_TESS_END
+#define GLU_ERROR GLU_TESS_ERROR
+#define GLU_EDGE_FLAG GLU_TESS_EDGE_FLAG
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GLU_H__ */
+#endif /* __glu_h__ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glut.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glut.h
new file mode 100644
index 00000000..65fd748d
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glut.h
@@ -0,0 +1,771 @@
+#ifndef __glut_h__
+#define __glut_h__
+
+/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998, 2000. */
+
+/* This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain. */
+
+#ifdef _WIN32
+
+/* GLUT 3.7 now tries to avoid including <windows.h>
+ to avoid name space pollution, but Win32's <GL/gl.h>
+ needs APIENTRY and WINGDIAPI defined properly. */
+# if 0
+ /* This would put tons of macros and crap in our clean name space. */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# else
+ /* XXX This is from Win32's <windef.h> */
+# ifndef APIENTRY
+# define GLUT_APIENTRY_DEFINED
+ /* Cygwin and MingW32 are two free GNU-based Open Source compilation
+ environments for Win32. Note that __CYGWIN32__ is deprecated
+ in favor of simply __CYGWIN__. */
+# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+# ifdef i386
+# define APIENTRY __attribute__ ((stdcall))
+# else
+# define APIENTRY
+# endif
+# else
+# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
+# define APIENTRY __stdcall
+# else
+# define APIENTRY
+# endif
+# endif
+# endif
+ /* XXX This is from Win32's <winnt.h> */
+# ifndef CALLBACK
+# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+# define CALLBACK __attribute__ ((stdcall))
+# else
+# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC) || defined(_M_IA64)) && !defined(MIDL_PASS)
+# define CALLBACK __stdcall
+# else
+# define CALLBACK
+# endif
+# endif
+# endif
+ /* XXX This is from Win32's <wingdi.h> and <winnt.h> */
+# ifndef WINGDIAPI
+# define GLUT_WINGDIAPI_DEFINED
+# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+# define WINGDIAPI
+# else
+# define WINGDIAPI __declspec(dllimport)
+# endif
+# endif
+# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+ /* Rely on Cygwin32/MingW32 <stddef.h> to set wchar_t. */
+ /* XXX Warning. The Cygwin32/MingW32 definition for wchar_t
+ is an "int" instead of the "short" used by Windows. */
+# include <stddef.h>
+# else
+ /* XXX This is from Win32's <ctype.h> */
+# ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+# define _WCHAR_T_DEFINED
+# endif
+# endif
+# endif
+
+/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA
+ in your compile preprocessor options. */
+# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA)
+# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */
+# pragma comment (lib, "user32.lib") /* link with Windows User lib */
+# pragma comment (lib, "gdi32.lib") /* link with Windows GDI lib */
+/* To enable automatic SGI OpenGL for Windows library usage for GLUT,
+ define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */
+# ifdef GLUT_USE_SGI_OPENGL
+# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */
+# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */
+# if defined(GLUT_STATIC_LIB)
+# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */
+# else
+# pragma comment (lib, "glut.lib") /* link with Win32 GLUT lib */
+# endif
+# else
+# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */
+# pragma comment (lib, "glustatic.lib") /* link with Microsoft OpenGL Utility lib */
+# if defined(GLUT_STATIC_LIB)
+# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */
+# else
+# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */
+# endif
+# endif
+# endif
+
+/* To disable supression of annoying warnings about floats being promoted
+ to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor
+ options. */
+# if defined(_MSC_VER) && !defined(GLUT_NO_WARNING_DISABLE)
+# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */
+# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */
+# endif
+
+/* Win32 has an annoying issue where there are multiple C run-time
+ libraries (CRTs). If the executable is linked with a different CRT
+ from the GLUT DLL, the GLUT DLL will not share the same CRT static
+ data seen by the executable. In particular, atexit callbacks registered
+ in the executable will not be called if GLUT calls its (different)
+ exit routine). GLUT is typically built with the
+ "/MD" option (the CRT with multithreading DLL support), but the Visual
+ C++ linker default is "/ML" (the single threaded CRT).
+
+ One workaround to this issue is requiring users to always link with
+ the same CRT as GLUT is compiled with. That requires users supply a
+ non-standard option. GLUT 3.7 has its own built-in workaround where
+ the executable's "exit" function pointer is covertly passed to GLUT.
+ GLUT then calls the executable's exit function pointer to ensure that
+ any "atexit" calls registered by the application are called if GLUT
+ needs to exit.
+
+ Note that the __glut*WithExit routines should NEVER be called directly.
+ To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
+
+/* XXX This is from Win32's <process.h> */
+# if !defined(_MSC_VER) && !defined(__cdecl)
+ /* Define __cdecl for non-Microsoft compilers. */
+# define __cdecl
+# define GLUT_DEFINED___CDECL
+# endif
+# ifndef _CRTIMP
+# ifdef _NTSDK
+ /* Definition compatible with NT SDK */
+# define _CRTIMP
+# else
+ /* Current definition */
+# ifdef _DLL
+# define _CRTIMP __declspec(dllimport)
+# else
+# define _CRTIMP
+# endif
+# endif
+# define GLUT_DEFINED__CRTIMP
+# endif
+
+/* GLUT API entry point declarations for Win32. */
+# ifdef GLUT_BUILDING_LIB
+# define GLUTAPI __declspec(dllexport)
+# else
+# ifdef _DLL
+# define GLUTAPI __declspec(dllimport)
+# else
+# define GLUTAPI extern
+# endif
+# endif
+
+/* GLUT callback calling convention for Win32. */
+# define GLUTCALLBACK __cdecl
+
+#endif /* _WIN32 */
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+# ifndef GLUT_BUILDING_LIB
+# if __BORLANDC__
+# if defined(_BUILDRTLDLL)
+void __cdecl __export exit(int __status);
+# else
+void __cdecl exit(int __status);
+# endif
+# else
+# if _MSC_VER >= 1200
+ extern _CRTIMP __declspec(noreturn) void __cdecl exit(int);
+# else
+ extern _CRTIMP void __cdecl exit(int);
+# endif
+# endif
+# endif
+#else
+/* non-Win32 case. */
+/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */
+# define APIENTRY
+# define GLUT_APIENTRY_DEFINED
+# define CALLBACK
+/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */
+# define GLUTAPI extern
+# define GLUTCALLBACK
+/* Prototype exit for the non-Win32 case (see above). */
+# ifdef __GNUC__
+extern void exit(int __status) __attribute__((__noreturn__));
+# else
+extern void exit(int);
+# endif
+#endif
+
+/**
+ GLUT API revision history:
+
+ GLUT_API_VERSION is updated to reflect incompatible GLUT
+ API changes (interface changes, semantic changes, deletions,
+ or additions).
+
+ GLUT_API_VERSION=1 First public release of GLUT. 11/29/94
+
+ GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling,
+ extension. Supports new input devices like tablet, dial and button
+ box, and Spaceball. Easy to query OpenGL extensions.
+
+ GLUT_API_VERSION=3 glutMenuStatus added.
+
+ GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer,
+ glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic
+ video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc,
+ glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat,
+ glutJoystickFunc, glutForceJoystickFunc, glutStrokeWidthf,
+ glutStrokeLengthf (NOT FINALIZED!).
+**/
+#ifndef GLUT_API_VERSION /* allow this to be overriden */
+#define GLUT_API_VERSION 3
+#endif
+
+/**
+ GLUT implementation revision history:
+
+ GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT
+ API revisions and implementation revisions (ie, bug fixes).
+
+ GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of
+ GLUT Xlib-based implementation. 11/29/94
+
+ GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of
+ GLUT Xlib-based implementation providing GLUT version 2
+ interfaces.
+
+ GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95
+
+ GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95
+
+ GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95
+
+ GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96
+
+ GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner
+ and video resize. 1/3/97
+
+ GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines.
+
+ GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release.
+
+ GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling.
+
+ GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support.
+
+ GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface.
+
+ GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa <GL/glut.h>
+
+ GLUT_XLIB_IMPLEMENTATION=16 mjk's early GLUT 3.8
+
+ GLUT_XLIB_IMPLEMENTATION=17 mjk's GLUT 3.8 with glutStrokeWidthf and glutStrokeLengthf
+**/
+#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */
+#define GLUT_XLIB_IMPLEMENTATION 17
+#endif
+
+/* Display mode bit masks. */
+#define GLUT_RGB 0
+#define GLUT_RGBA GLUT_RGB
+#define GLUT_INDEX 1
+#define GLUT_SINGLE 0
+#define GLUT_DOUBLE 2
+#define GLUT_ACCUM 4
+#define GLUT_ALPHA 8
+#define GLUT_DEPTH 16
+#define GLUT_STENCIL 32
+#if (GLUT_API_VERSION >= 2)
+#define GLUT_MULTISAMPLE 128
+#define GLUT_STEREO 256
+#endif
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_LUMINANCE 512
+#endif
+
+/* Mouse buttons. */
+#define GLUT_LEFT_BUTTON 0
+#define GLUT_MIDDLE_BUTTON 1
+#define GLUT_RIGHT_BUTTON 2
+
+/* Mouse button state. */
+#define GLUT_DOWN 0
+#define GLUT_UP 1
+
+#if (GLUT_API_VERSION >= 2)
+/* function keys */
+#define GLUT_KEY_F1 1
+#define GLUT_KEY_F2 2
+#define GLUT_KEY_F3 3
+#define GLUT_KEY_F4 4
+#define GLUT_KEY_F5 5
+#define GLUT_KEY_F6 6
+#define GLUT_KEY_F7 7
+#define GLUT_KEY_F8 8
+#define GLUT_KEY_F9 9
+#define GLUT_KEY_F10 10
+#define GLUT_KEY_F11 11
+#define GLUT_KEY_F12 12
+/* directional keys */
+#define GLUT_KEY_LEFT 100
+#define GLUT_KEY_UP 101
+#define GLUT_KEY_RIGHT 102
+#define GLUT_KEY_DOWN 103
+#define GLUT_KEY_PAGE_UP 104
+#define GLUT_KEY_PAGE_DOWN 105
+#define GLUT_KEY_HOME 106
+#define GLUT_KEY_END 107
+#define GLUT_KEY_INSERT 108
+#endif
+
+/* Entry/exit state. */
+#define GLUT_LEFT 0
+#define GLUT_ENTERED 1
+
+/* Menu usage state. */
+#define GLUT_MENU_NOT_IN_USE 0
+#define GLUT_MENU_IN_USE 1
+
+/* Visibility state. */
+#define GLUT_NOT_VISIBLE 0
+#define GLUT_VISIBLE 1
+
+/* Window status state. */
+#define GLUT_HIDDEN 0
+#define GLUT_FULLY_RETAINED 1
+#define GLUT_PARTIALLY_RETAINED 2
+#define GLUT_FULLY_COVERED 3
+
+/* Color index component selection values. */
+#define GLUT_RED 0
+#define GLUT_GREEN 1
+#define GLUT_BLUE 2
+
+#ifdef _WIN32
+/* Stroke font constants (use these in GLUT program). */
+#define GLUT_STROKE_ROMAN ((void*)0)
+#define GLUT_STROKE_MONO_ROMAN ((void*)1)
+
+/* Bitmap font constants (use these in GLUT program). */
+#define GLUT_BITMAP_9_BY_15 ((void*)2)
+#define GLUT_BITMAP_8_BY_13 ((void*)3)
+#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
+#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_BITMAP_HELVETICA_10 ((void*)6)
+#define GLUT_BITMAP_HELVETICA_12 ((void*)7)
+#define GLUT_BITMAP_HELVETICA_18 ((void*)8)
+#endif
+#else
+/* Stroke font opaque addresses (use constants instead in source code). */
+GLUTAPI void *glutStrokeRoman;
+GLUTAPI void *glutStrokeMonoRoman;
+
+/* Stroke font constants (use these in GLUT program). */
+#define GLUT_STROKE_ROMAN (&glutStrokeRoman)
+#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman)
+
+/* Bitmap font opaque addresses (use constants instead in source code). */
+GLUTAPI void *glutBitmap9By15;
+GLUTAPI void *glutBitmap8By13;
+GLUTAPI void *glutBitmapTimesRoman10;
+GLUTAPI void *glutBitmapTimesRoman24;
+GLUTAPI void *glutBitmapHelvetica10;
+GLUTAPI void *glutBitmapHelvetica12;
+GLUTAPI void *glutBitmapHelvetica18;
+
+/* Bitmap font constants (use these in GLUT program). */
+#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15)
+#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13)
+#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10)
+#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24)
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10)
+#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12)
+#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18)
+#endif
+#endif
+
+/* glutGet parameters. */
+#define GLUT_WINDOW_X ((GLenum) 100)
+#define GLUT_WINDOW_Y ((GLenum) 101)
+#define GLUT_WINDOW_WIDTH ((GLenum) 102)
+#define GLUT_WINDOW_HEIGHT ((GLenum) 103)
+#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104)
+#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105)
+#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106)
+#define GLUT_WINDOW_RED_SIZE ((GLenum) 107)
+#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108)
+#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109)
+#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110)
+#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111)
+#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112)
+#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113)
+#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114)
+#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115)
+#define GLUT_WINDOW_RGBA ((GLenum) 116)
+#define GLUT_WINDOW_PARENT ((GLenum) 117)
+#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118)
+#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119)
+#if (GLUT_API_VERSION >= 2)
+#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120)
+#define GLUT_WINDOW_STEREO ((GLenum) 121)
+#endif
+#if (GLUT_API_VERSION >= 3)
+#define GLUT_WINDOW_CURSOR ((GLenum) 122)
+#endif
+#define GLUT_SCREEN_WIDTH ((GLenum) 200)
+#define GLUT_SCREEN_HEIGHT ((GLenum) 201)
+#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202)
+#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203)
+#define GLUT_MENU_NUM_ITEMS ((GLenum) 300)
+#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400)
+#define GLUT_INIT_WINDOW_X ((GLenum) 500)
+#define GLUT_INIT_WINDOW_Y ((GLenum) 501)
+#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502)
+#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503)
+#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504)
+#if (GLUT_API_VERSION >= 2)
+#define GLUT_ELAPSED_TIME ((GLenum) 700)
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123)
+#endif
+
+#if (GLUT_API_VERSION >= 2)
+/* glutDeviceGet parameters. */
+#define GLUT_HAS_KEYBOARD ((GLenum) 600)
+#define GLUT_HAS_MOUSE ((GLenum) 601)
+#define GLUT_HAS_SPACEBALL ((GLenum) 602)
+#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603)
+#define GLUT_HAS_TABLET ((GLenum) 604)
+#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605)
+#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606)
+#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607)
+#define GLUT_NUM_DIALS ((GLenum) 608)
+#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609)
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610)
+#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611)
+#define GLUT_HAS_JOYSTICK ((GLenum) 612)
+#define GLUT_OWNS_JOYSTICK ((GLenum) 613)
+#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614)
+#define GLUT_JOYSTICK_AXES ((GLenum) 615)
+#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616)
+#endif
+
+#if (GLUT_API_VERSION >= 3)
+/* glutLayerGet parameters. */
+#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800)
+#define GLUT_LAYER_IN_USE ((GLenum) 801)
+#define GLUT_HAS_OVERLAY ((GLenum) 802)
+#define GLUT_TRANSPARENT_INDEX ((GLenum) 803)
+#define GLUT_NORMAL_DAMAGED ((GLenum) 804)
+#define GLUT_OVERLAY_DAMAGED ((GLenum) 805)
+
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+/* glutVideoResizeGet parameters. */
+#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900)
+#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901)
+#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902)
+#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903)
+#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904)
+#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905)
+#define GLUT_VIDEO_RESIZE_X ((GLenum) 906)
+#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907)
+#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908)
+#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909)
+#endif
+
+/* glutUseLayer parameters. */
+#define GLUT_NORMAL ((GLenum) 0)
+#define GLUT_OVERLAY ((GLenum) 1)
+
+/* glutGetModifiers return mask. */
+#define GLUT_ACTIVE_SHIFT 1
+#define GLUT_ACTIVE_CTRL 2
+#define GLUT_ACTIVE_ALT 4
+
+/* glutSetCursor parameters. */
+/* Basic arrows. */
+#define GLUT_CURSOR_RIGHT_ARROW 0
+#define GLUT_CURSOR_LEFT_ARROW 1
+/* Symbolic cursor shapes. */
+#define GLUT_CURSOR_INFO 2
+#define GLUT_CURSOR_DESTROY 3
+#define GLUT_CURSOR_HELP 4
+#define GLUT_CURSOR_CYCLE 5
+#define GLUT_CURSOR_SPRAY 6
+#define GLUT_CURSOR_WAIT 7
+#define GLUT_CURSOR_TEXT 8
+#define GLUT_CURSOR_CROSSHAIR 9
+/* Directional cursors. */
+#define GLUT_CURSOR_UP_DOWN 10
+#define GLUT_CURSOR_LEFT_RIGHT 11
+/* Sizing cursors. */
+#define GLUT_CURSOR_TOP_SIDE 12
+#define GLUT_CURSOR_BOTTOM_SIDE 13
+#define GLUT_CURSOR_LEFT_SIDE 14
+#define GLUT_CURSOR_RIGHT_SIDE 15
+#define GLUT_CURSOR_TOP_LEFT_CORNER 16
+#define GLUT_CURSOR_TOP_RIGHT_CORNER 17
+#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18
+#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19
+/* Inherit from parent window. */
+#define GLUT_CURSOR_INHERIT 100
+/* Blank cursor. */
+#define GLUT_CURSOR_NONE 101
+/* Fullscreen crosshair (if available). */
+#define GLUT_CURSOR_FULL_CROSSHAIR 102
+#endif
+
+/* GLUT initialization sub-API. */
+GLUTAPI void APIENTRY glutInit(int *argcp, char **argv);
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
+#ifndef GLUT_BUILDING_LIB
+static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
+#define glutInit glutInit_ATEXIT_HACK
+#endif
+#endif
+GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI void APIENTRY glutInitDisplayString(const char *string);
+#endif
+GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y);
+GLUTAPI void APIENTRY glutInitWindowSize(int width, int height);
+GLUTAPI void APIENTRY glutMainLoop(void);
+
+/* GLUT window sub-API. */
+GLUTAPI int APIENTRY glutCreateWindow(const char *title);
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
+#ifndef GLUT_BUILDING_LIB
+static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
+#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
+#endif
+#endif
+GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height);
+GLUTAPI void APIENTRY glutDestroyWindow(int win);
+GLUTAPI void APIENTRY glutPostRedisplay(void);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
+GLUTAPI void APIENTRY glutPostWindowRedisplay(int win);
+#endif
+GLUTAPI void APIENTRY glutSwapBuffers(void);
+GLUTAPI int APIENTRY glutGetWindow(void);
+GLUTAPI void APIENTRY glutSetWindow(int win);
+GLUTAPI void APIENTRY glutSetWindowTitle(const char *title);
+GLUTAPI void APIENTRY glutSetIconTitle(const char *title);
+GLUTAPI void APIENTRY glutPositionWindow(int x, int y);
+GLUTAPI void APIENTRY glutReshapeWindow(int width, int height);
+GLUTAPI void APIENTRY glutPopWindow(void);
+GLUTAPI void APIENTRY glutPushWindow(void);
+GLUTAPI void APIENTRY glutIconifyWindow(void);
+GLUTAPI void APIENTRY glutShowWindow(void);
+GLUTAPI void APIENTRY glutHideWindow(void);
+#if (GLUT_API_VERSION >= 3)
+GLUTAPI void APIENTRY glutFullScreen(void);
+GLUTAPI void APIENTRY glutSetCursor(int cursor);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI void APIENTRY glutWarpPointer(int x, int y);
+#endif
+
+/* GLUT overlay sub-API. */
+GLUTAPI void APIENTRY glutEstablishOverlay(void);
+GLUTAPI void APIENTRY glutRemoveOverlay(void);
+GLUTAPI void APIENTRY glutUseLayer(GLenum layer);
+GLUTAPI void APIENTRY glutPostOverlayRedisplay(void);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
+GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win);
+#endif
+GLUTAPI void APIENTRY glutShowOverlay(void);
+GLUTAPI void APIENTRY glutHideOverlay(void);
+#endif
+
+/* GLUT menu sub-API. */
+GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int));
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int));
+#ifndef GLUT_BUILDING_LIB
+static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); }
+#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
+#endif
+#endif
+GLUTAPI void APIENTRY glutDestroyMenu(int menu);
+GLUTAPI int APIENTRY glutGetMenu(void);
+GLUTAPI void APIENTRY glutSetMenu(int menu);
+GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value);
+GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu);
+GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value);
+GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu);
+GLUTAPI void APIENTRY glutRemoveMenuItem(int item);
+GLUTAPI void APIENTRY glutAttachMenu(int button);
+GLUTAPI void APIENTRY glutDetachMenu(int button);
+
+/* GLUT window callback sub-API. */
+GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void));
+GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height));
+GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
+GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
+GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
+GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
+GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state));
+GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state));
+GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void));
+GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value);
+GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state));
+#if (GLUT_API_VERSION >= 2)
+GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
+GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
+GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
+GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state));
+GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state));
+GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value));
+GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
+GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
+#if (GLUT_API_VERSION >= 3)
+GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y));
+GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void));
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state));
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
+GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
+GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval);
+#endif
+#endif
+#endif
+
+/* GLUT color index sub-API. */
+GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue);
+GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component);
+GLUTAPI void APIENTRY glutCopyColormap(int win);
+
+/* GLUT state retrieval sub-API. */
+GLUTAPI int APIENTRY glutGet(GLenum type);
+GLUTAPI int APIENTRY glutDeviceGet(GLenum type);
+#if (GLUT_API_VERSION >= 2)
+/* GLUT extension support sub-API */
+GLUTAPI int APIENTRY glutExtensionSupported(const char *name);
+#endif
+#if (GLUT_API_VERSION >= 3)
+GLUTAPI int APIENTRY glutGetModifiers(void);
+GLUTAPI int APIENTRY glutLayerGet(GLenum type);
+#endif
+
+/* GLUT font sub-API */
+GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character);
+GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character);
+GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character);
+GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character);
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string);
+GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string);
+#endif
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 17)
+GLUTAPI float APIENTRY glutStrokeWidthf(void *font, int character);
+GLUTAPI float APIENTRY glutStrokeLengthf(void *font, const unsigned char *string);
+#endif
+
+/* GLUT pre-built models sub-API */
+GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
+GLUTAPI void APIENTRY glutWireCube(GLdouble size);
+GLUTAPI void APIENTRY glutSolidCube(GLdouble size);
+GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
+GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
+GLUTAPI void APIENTRY glutWireDodecahedron(void);
+GLUTAPI void APIENTRY glutSolidDodecahedron(void);
+GLUTAPI void APIENTRY glutWireTeapot(GLdouble size);
+GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size);
+GLUTAPI void APIENTRY glutWireOctahedron(void);
+GLUTAPI void APIENTRY glutSolidOctahedron(void);
+GLUTAPI void APIENTRY glutWireTetrahedron(void);
+GLUTAPI void APIENTRY glutSolidTetrahedron(void);
+GLUTAPI void APIENTRY glutWireIcosahedron(void);
+GLUTAPI void APIENTRY glutSolidIcosahedron(void);
+
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
+/* GLUT video resize sub-API. */
+GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param);
+GLUTAPI void APIENTRY glutSetupVideoResizing(void);
+GLUTAPI void APIENTRY glutStopVideoResizing(void);
+GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height);
+GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height);
+
+/* GLUT debugging sub-API. */
+GLUTAPI void APIENTRY glutReportErrors(void);
+#endif
+
+#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
+/* GLUT device control sub-API. */
+/* glutSetKeyRepeat modes. */
+#define GLUT_KEY_REPEAT_OFF 0
+#define GLUT_KEY_REPEAT_ON 1
+#define GLUT_KEY_REPEAT_DEFAULT 2
+
+/* Joystick button masks. */
+#define GLUT_JOYSTICK_BUTTON_A 1
+#define GLUT_JOYSTICK_BUTTON_B 2
+#define GLUT_JOYSTICK_BUTTON_C 4
+#define GLUT_JOYSTICK_BUTTON_D 8
+
+GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore);
+GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode);
+GLUTAPI void APIENTRY glutForceJoystickFunc(void);
+
+/* GLUT game mode sub-API. */
+/* glutGameModeGet. */
+#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0)
+#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1)
+#define GLUT_GAME_MODE_WIDTH ((GLenum) 2)
+#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3)
+#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4)
+#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5)
+#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6)
+
+GLUTAPI void APIENTRY glutGameModeString(const char *string);
+GLUTAPI int APIENTRY glutEnterGameMode(void);
+GLUTAPI void APIENTRY glutLeaveGameMode(void);
+GLUTAPI int APIENTRY glutGameModeGet(GLenum mode);
+#endif
+
+#ifdef __cplusplus
+}
+
+#endif
+
+#ifdef GLUT_APIENTRY_DEFINED
+# undef GLUT_APIENTRY_DEFINED
+# undef APIENTRY
+#endif
+
+#ifdef GLUT_WINGDIAPI_DEFINED
+# undef GLUT_WINGDIAPI_DEFINED
+# undef WINGDIAPI
+#endif
+
+#ifdef GLUT_DEFINED___CDECL
+# undef GLUT_DEFINED___CDECL
+# undef __cdecl
+#endif
+
+#ifdef GLUT_DEFINED__CRTIMP
+# undef GLUT_DEFINED__CRTIMP
+# undef _CRTIMP
+#endif
+
+#endif /* __glut_h__ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glx.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glx.h
new file mode 100644
index 00000000..66ad53c6
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glx.h
@@ -0,0 +1,357 @@
+#ifndef __glx_h__
+#define __glx_h__
+
+/*
+** The contents of this file are subject to the GLX Public License Version 1.0
+** (the "License"). You may not use this file except in compliance with the
+** License. You may obtain a copy of the License at Silicon Graphics, Inc.,
+** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043
+** or at http://www.sgi.com/software/opensource/glx/license.html.
+**
+** Software distributed under the License is distributed on an "AS IS"
+** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY
+** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
+** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific
+** language governing rights and limitations under the License.
+**
+** The Original Software is GLX version 1.2 source code, released February,
+** 1999. The developer of the Original Software is Silicon Graphics, Inc.
+** Those portions of the Subject Software created by Silicon Graphics, Inc.
+** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved.
+**
+** $Header: //sw/main/drivers/OpenGL/win/glx/include/glx.h#21 $
+*/
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/gl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Names for attributes to glXGetConfig.
+ */
+#define GLX_USE_GL 1 /* support GLX rendering */
+#define GLX_BUFFER_SIZE 2 /* depth of the color buffer */
+#define GLX_LEVEL 3 /* level in plane stacking */
+#define GLX_RGBA 4 /* true if RGBA mode */
+#define GLX_DOUBLEBUFFER 5 /* double buffering supported */
+#define GLX_STEREO 6 /* stereo buffering supported */
+#define GLX_AUX_BUFFERS 7 /* number of aux buffers */
+#define GLX_RED_SIZE 8 /* number of red component bits */
+#define GLX_GREEN_SIZE 9 /* number of green component bits */
+#define GLX_BLUE_SIZE 10 /* number of blue component bits */
+#define GLX_ALPHA_SIZE 11 /* number of alpha component bits */
+#define GLX_DEPTH_SIZE 12 /* number of depth bits */
+#define GLX_STENCIL_SIZE 13 /* number of stencil bits */
+#define GLX_ACCUM_RED_SIZE 14 /* number of red accum bits */
+#define GLX_ACCUM_GREEN_SIZE 15 /* number of green accum bits */
+#define GLX_ACCUM_BLUE_SIZE 16 /* number of blue accum bits */
+#define GLX_ACCUM_ALPHA_SIZE 17 /* number of alpha accum bits */
+
+/*
+ * Error return values from glXGetConfig. Success is indicated by
+ * a value of 0.
+ */
+#define GLX_BAD_SCREEN 1 /* screen # is bad */
+#define GLX_BAD_ATTRIBUTE 2 /* attribute to get is bad */
+#define GLX_NO_EXTENSION 3 /* no glx extension on server */
+#define GLX_BAD_VISUAL 4 /* visual # not known by GLX */
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+/*
+ * Names for attributes to glXGetClientString.
+ */
+#define GLX_VENDOR 0x1
+#define GLX_VERSION 0x2
+#define GLX_EXTENSIONS 0x3
+
+#ifndef GLX_VERSION_1_3
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_DONT_CARE 0xFFFFFFFF
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#endif
+
+#ifndef GLX_VERSION_1_4
+#define GLX_SAMPLE_BUFFERS 0x186a0
+#define GLX_SAMPLES 0x186a1
+#endif
+
+#ifndef GLX_ARB_get_proc_address
+typedef void (*__GLXextFuncPtr)(void);
+#endif
+
+/*
+ * GLX resources.
+ */
+typedef XID GLXContextID;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+typedef XID GLXPbuffer;
+typedef XID GLXWindow;
+typedef XID GLXFBConfigID;
+
+/*
+ * GLXContext is a pointer to opaque data.
+ */
+typedef struct __GLXcontextRec *GLXContext;
+
+/*
+ * GLXFBConfig is a pointer to opaque data.
+ */
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+
+
+/**********************************************************************/
+
+/*
+ * GLX 1.0 functions.
+ */
+extern XVisualInfo* glXChooseVisual(Display *dpy, int screen,
+ int *attrib_list);
+
+extern void glXCopyContext(Display *dpy, GLXContext src,
+ GLXContext dst, unsigned long mask);
+
+extern GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis,
+ GLXContext share_list, Bool direct);
+
+extern GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis,
+ Pixmap pixmap);
+
+extern void glXDestroyContext(Display *dpy, GLXContext ctx);
+
+extern void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pix);
+
+extern int glXGetConfig(Display *dpy, XVisualInfo *vis,
+ int attrib, int *value);
+
+extern GLXContext glXGetCurrentContext(void);
+
+extern GLXDrawable glXGetCurrentDrawable(void);
+
+extern Bool glXIsDirect(Display *dpy, GLXContext ctx);
+
+extern Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable,
+ GLXContext ctx);
+
+extern Bool glXQueryExtension(Display *dpy, int *error_base, int *event_base);
+
+extern Bool glXQueryVersion(Display *dpy, int *major, int *minor);
+
+extern void glXSwapBuffers(Display *dpy, GLXDrawable drawable);
+
+extern void glXUseXFont(Font font, int first, int count, int list_base);
+
+extern void glXWaitGL(void);
+
+extern void glXWaitX(void);
+
+
+#ifndef GLX_VERSION_1_1
+#define GLX_VERSION_1_1 1
+/*
+ * GLX 1.1 functions.
+ */
+extern const char *glXGetClientString(Display *dpy, int name);
+
+extern const char *glXQueryServerString(Display *dpy, int screen, int name);
+
+extern const char *glXQueryExtensionsString(Display *dpy, int screen);
+#endif
+
+
+#ifndef GLX_VERSION_1_2
+#define GLX_VERSION_1_2 1
+/*
+ * GLX 1.2 functions.
+ */
+extern Display *glXGetCurrentDisplay(void);
+#endif
+
+#ifndef GLX_VERSION_1_3
+#define GLX_VERSION_1_3 1
+/*
+ * GLX 1.3 functions.
+ */
+extern GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen,
+ const int *attrib_list, int *nelements);
+
+extern GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config,
+ int render_type, GLXContext share_list,
+ Bool direct);
+
+extern GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config,
+ const int *attrib_list);
+
+extern GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config,
+ Pixmap pixmap, const int *attrib_list);
+
+extern GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config,
+ Window win, const int *attrib_list);
+
+extern void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf);
+
+extern void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap);
+
+extern void glXDestroyWindow(Display *dpy, GLXWindow win);
+
+extern GLXDrawable glXGetCurrentReadDrawable(void);
+
+extern int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
+ int attribute, int *value);
+
+extern GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements);
+
+extern void glXGetSelectedEvent(Display *dpy, GLXDrawable draw,
+ unsigned long *event_mask);
+
+extern XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config);
+
+extern Bool glXMakeContextCurrent(Display *display, GLXDrawable draw,
+ GLXDrawable read, GLXContext ctx);
+
+extern int glXQueryContext(Display *dpy, GLXContext ctx,
+ int attribute, int *value);
+
+extern void glXQueryDrawable(Display *dpy, GLXDrawable draw,
+ int attribute, unsigned int *value);
+
+extern void glXSelectEvent(Display *dpy, GLXDrawable draw,
+ unsigned long event_mask);
+
+typedef GLXFBConfig * ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements);
+typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);
+typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
+typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
+typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win);
+typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);
+typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void);
+typedef Display * ( * PFNGLXGETCURRENTDISPLAYPROC) (void);
+typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value);
+typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask);
+typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+#endif
+
+
+#ifndef GLX_VERSION_1_4
+#define GLX_VERSION_1_4 1
+/*
+ * GLX 1.4 functions and typedefs.
+ */
+extern __GLXextFuncPtr glXGetProcAddress (const GLubyte *);
+typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName);
+#endif
+
+
+
+/**********************************************************************/
+
+/*
+ * ARB_get_proc_address
+ */
+#ifndef GLX_ARB_get_proc_address
+#define GLX_ARB_get_proc_address 1
+/* Don't wrap this in GLX_GLXEXT_PROTOTYPES! */
+extern void (*glXGetProcAddressARB(const GLubyte *procName))(void);
+typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName);
+#endif
+
+/**********************************************************************/
+
+/*** Should these go here, or in another header? */
+/*
+ * GLX Events
+ */
+typedef struct {
+ int event_type; /* GLX_DAMAGED or GLX_SAVED */
+ int draw_type; /* GLX_WINDOW or GLX_PBUFFER */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came for SendEvent request */
+ Display *display; /* display the event was read from */
+ GLXDrawable drawable; /* XID of Drawable */
+ unsigned int buffer_mask; /* mask indicating which buffers are affected */
+ unsigned int aux_buffer; /* which aux buffer was affected */
+ int x, y;
+ int width, height;
+ int count; /* if nonzero, at least this many more */
+} GLXPbufferClobberEvent;
+
+typedef union __GLXEvent {
+ GLXPbufferClobberEvent glxpbufferclobber;
+ long pad[24];
+} GLXEvent;
+
+#ifndef GLX_GLXEXT_LEGACY
+#include <GL/glxext.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__glx_h__ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxew.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxew.h
new file mode 100644
index 00000000..6d249f73
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxew.h
@@ -0,0 +1,1587 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __glxew_h__
+#define __glxew_h__
+#define __GLXEW_H__
+
+#ifdef __glxext_h_
+#error glxext.h included before glxew.h
+#endif
+
+#if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__)
+#error glx.h included before glxew.h
+#endif
+
+#define __glxext_h_
+
+#define GLX_H
+#define __GLX_glx_h__
+#define __glx_h__
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmd.h>
+#include <GL/glew.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------- GLX_VERSION_1_0 --------------------------- */
+
+#ifndef GLX_VERSION_1_0
+#define GLX_VERSION_1_0 1
+
+#define GLX_USE_GL 1
+#define GLX_BUFFER_SIZE 2
+#define GLX_LEVEL 3
+#define GLX_RGBA 4
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_BAD_SCREEN 1
+#define GLX_BAD_ATTRIBUTE 2
+#define GLX_NO_EXTENSION 3
+#define GLX_BAD_VISUAL 4
+#define GLX_BAD_CONTEXT 5
+#define GLX_BAD_VALUE 6
+#define GLX_BAD_ENUM 7
+
+typedef XID GLXDrawable;
+typedef XID GLXPixmap;
+#ifdef __sun
+typedef struct __glXContextRec *GLXContext;
+#else
+typedef struct __GLXcontextRec *GLXContext;
+#endif
+
+typedef unsigned int GLXVideoDeviceNV;
+
+extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase);
+extern Bool glXQueryVersion (Display *dpy, int *major, int *minor);
+extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value);
+extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList);
+extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap);
+extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix);
+extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+extern void glXDestroyContext (Display *dpy, GLXContext ctx);
+extern Bool glXIsDirect (Display *dpy, GLXContext ctx);
+extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask);
+extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx);
+extern GLXContext glXGetCurrentContext (void);
+extern GLXDrawable glXGetCurrentDrawable (void);
+extern void glXWaitGL (void);
+extern void glXWaitX (void);
+extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable);
+extern void glXUseXFont (Font font, int first, int count, int listBase);
+
+#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0)
+
+#endif /* GLX_VERSION_1_0 */
+
+/* ---------------------------- GLX_VERSION_1_1 --------------------------- */
+
+#ifndef GLX_VERSION_1_1
+#define GLX_VERSION_1_1
+
+#define GLX_VENDOR 0x1
+#define GLX_VERSION 0x2
+#define GLX_EXTENSIONS 0x3
+
+extern const char* glXQueryExtensionsString (Display *dpy, int screen);
+extern const char* glXGetClientString (Display *dpy, int name);
+extern const char* glXQueryServerString (Display *dpy, int screen, int name);
+
+#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1)
+
+#endif /* GLX_VERSION_1_1 */
+
+/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */
+
+#ifndef GLX_VERSION_1_2
+#define GLX_VERSION_1_2 1
+
+typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void);
+
+#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay)
+
+#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2)
+
+#endif /* GLX_VERSION_1_2 */
+
+/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */
+
+#ifndef GLX_VERSION_1_3
+#define GLX_VERSION_1_3 1
+
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#define GLX_PIXMAP_BIT 0x00000002
+#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define GLX_AUX_BUFFERS_BIT 0x00000010
+#define GLX_CONFIG_CAVEAT 0x20
+#define GLX_DEPTH_BUFFER_BIT 0x00000020
+#define GLX_X_VISUAL_TYPE 0x22
+#define GLX_TRANSPARENT_TYPE 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define GLX_TRANSPARENT_RED_VALUE 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define GLX_STENCIL_BUFFER_BIT 0x00000040
+#define GLX_ACCUM_BUFFER_BIT 0x00000080
+#define GLX_NONE 0x8000
+#define GLX_SLOW_CONFIG 0x8001
+#define GLX_TRUE_COLOR 0x8002
+#define GLX_DIRECT_COLOR 0x8003
+#define GLX_PSEUDO_COLOR 0x8004
+#define GLX_STATIC_COLOR 0x8005
+#define GLX_GRAY_SCALE 0x8006
+#define GLX_STATIC_GRAY 0x8007
+#define GLX_TRANSPARENT_RGB 0x8008
+#define GLX_TRANSPARENT_INDEX 0x8009
+#define GLX_VISUAL_ID 0x800B
+#define GLX_SCREEN 0x800C
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_X_RENDERABLE 0x8012
+#define GLX_FBCONFIG_ID 0x8013
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_COLOR_INDEX_TYPE 0x8015
+#define GLX_MAX_PBUFFER_WIDTH 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define GLX_MAX_PBUFFER_PIXELS 0x8018
+#define GLX_PRESERVED_CONTENTS 0x801B
+#define GLX_LARGEST_PBUFFER 0x801C
+#define GLX_WIDTH 0x801D
+#define GLX_HEIGHT 0x801E
+#define GLX_EVENT_MASK 0x801F
+#define GLX_DAMAGED 0x8020
+#define GLX_SAVED 0x8021
+#define GLX_WINDOW 0x8022
+#define GLX_PBUFFER 0x8023
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define GLX_DONT_CARE 0xFFFFFFFF
+
+typedef XID GLXFBConfigID;
+typedef XID GLXPbuffer;
+typedef XID GLXWindow;
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+
+typedef struct {
+ int event_type;
+ int draw_type;
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ GLXDrawable drawable;
+ unsigned int buffer_mask;
+ unsigned int aux_buffer;
+ int x, y;
+ int width, height;
+ int count;
+} GLXPbufferClobberEvent;
+typedef union __GLXEvent {
+ GLXPbufferClobberEvent glxpbufferclobber;
+ long pad[24];
+} GLXEvent;
+
+typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);
+typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
+typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win);
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);
+typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements);
+typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
+typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value);
+typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask);
+
+#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig)
+#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext)
+#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer)
+#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap)
+#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow)
+#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer)
+#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap)
+#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow)
+#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable)
+#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib)
+#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs)
+#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent)
+#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig)
+#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent)
+#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext)
+#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable)
+#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent)
+
+#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3)
+
+#endif /* GLX_VERSION_1_3 */
+
+/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */
+
+#ifndef GLX_VERSION_1_4
+#define GLX_VERSION_1_4 1
+
+#define GLX_SAMPLE_BUFFERS 100000
+#define GLX_SAMPLES 100001
+
+extern void ( * glXGetProcAddress (const GLubyte *procName)) (void);
+
+#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4)
+
+#endif /* GLX_VERSION_1_4 */
+
+/* -------------------------- GLX_3DFX_multisample ------------------------- */
+
+#ifndef GLX_3DFX_multisample
+#define GLX_3DFX_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_3DFX 0x8050
+#define GLX_SAMPLES_3DFX 0x8051
+
+#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample)
+
+#endif /* GLX_3DFX_multisample */
+
+/* ------------------------ GLX_AMD_gpu_association ------------------------ */
+
+#ifndef GLX_AMD_gpu_association
+#define GLX_AMD_gpu_association 1
+
+#define GLX_GPU_VENDOR_AMD 0x1F00
+#define GLX_GPU_RENDERER_STRING_AMD 0x1F01
+#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define GLX_GPU_RAM_AMD 0x21A3
+#define GLX_GPU_CLOCK_AMD 0x21A4
+#define GLX_GPU_NUM_PIPES_AMD 0x21A5
+#define GLX_GPU_NUM_SIMD_AMD 0x21A6
+#define GLX_GPU_NUM_RB_AMD 0x21A7
+#define GLX_GPU_NUM_SPI_AMD 0x21A8
+
+#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association)
+
+#endif /* GLX_AMD_gpu_association */
+
+/* ------------------------- GLX_ARB_create_context ------------------------ */
+
+#ifndef GLX_ARB_create_context
+#define GLX_ARB_create_context 1
+
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+
+typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+
+#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB)
+
+#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context)
+
+#endif /* GLX_ARB_create_context */
+
+/* --------------------- GLX_ARB_create_context_profile -------------------- */
+
+#ifndef GLX_ARB_create_context_profile
+#define GLX_ARB_create_context_profile 1
+
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+#define GLXEW_ARB_create_context_profile GLXEW_GET_VAR(__GLXEW_ARB_create_context_profile)
+
+#endif /* GLX_ARB_create_context_profile */
+
+/* ------------------- GLX_ARB_create_context_robustness ------------------- */
+
+#ifndef GLX_ARB_create_context_robustness
+#define GLX_ARB_create_context_robustness 1
+
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+
+#define GLXEW_ARB_create_context_robustness GLXEW_GET_VAR(__GLXEW_ARB_create_context_robustness)
+
+#endif /* GLX_ARB_create_context_robustness */
+
+/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */
+
+#ifndef GLX_ARB_fbconfig_float
+#define GLX_ARB_fbconfig_float 1
+
+#define GLX_RGBA_FLOAT_BIT 0x00000004
+#define GLX_RGBA_FLOAT_TYPE 0x20B9
+
+#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float)
+
+#endif /* GLX_ARB_fbconfig_float */
+
+/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */
+
+#ifndef GLX_ARB_framebuffer_sRGB
+#define GLX_ARB_framebuffer_sRGB 1
+
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+
+#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB)
+
+#endif /* GLX_ARB_framebuffer_sRGB */
+
+/* ------------------------ GLX_ARB_get_proc_address ----------------------- */
+
+#ifndef GLX_ARB_get_proc_address
+#define GLX_ARB_get_proc_address 1
+
+extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void);
+
+#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address)
+
+#endif /* GLX_ARB_get_proc_address */
+
+/* -------------------------- GLX_ARB_multisample -------------------------- */
+
+#ifndef GLX_ARB_multisample
+#define GLX_ARB_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB 100001
+
+#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample)
+
+#endif /* GLX_ARB_multisample */
+
+/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */
+
+#ifndef GLX_ARB_vertex_buffer_object
+#define GLX_ARB_vertex_buffer_object 1
+
+#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095
+
+#define GLXEW_ARB_vertex_buffer_object GLXEW_GET_VAR(__GLXEW_ARB_vertex_buffer_object)
+
+#endif /* GLX_ARB_vertex_buffer_object */
+
+/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */
+
+#ifndef GLX_ATI_pixel_format_float
+#define GLX_ATI_pixel_format_float 1
+
+#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100
+
+#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float)
+
+#endif /* GLX_ATI_pixel_format_float */
+
+/* ------------------------- GLX_ATI_render_texture ------------------------ */
+
+#ifndef GLX_ATI_render_texture
+#define GLX_ATI_render_texture 1
+
+#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800
+#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801
+#define GLX_TEXTURE_FORMAT_ATI 0x9802
+#define GLX_TEXTURE_TARGET_ATI 0x9803
+#define GLX_MIPMAP_TEXTURE_ATI 0x9804
+#define GLX_TEXTURE_RGB_ATI 0x9805
+#define GLX_TEXTURE_RGBA_ATI 0x9806
+#define GLX_NO_TEXTURE_ATI 0x9807
+#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808
+#define GLX_TEXTURE_1D_ATI 0x9809
+#define GLX_TEXTURE_2D_ATI 0x980A
+#define GLX_MIPMAP_LEVEL_ATI 0x980B
+#define GLX_CUBE_MAP_FACE_ATI 0x980C
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810
+#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811
+#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812
+#define GLX_FRONT_LEFT_ATI 0x9813
+#define GLX_FRONT_RIGHT_ATI 0x9814
+#define GLX_BACK_LEFT_ATI 0x9815
+#define GLX_BACK_RIGHT_ATI 0x9816
+#define GLX_AUX0_ATI 0x9817
+#define GLX_AUX1_ATI 0x9818
+#define GLX_AUX2_ATI 0x9819
+#define GLX_AUX3_ATI 0x981A
+#define GLX_AUX4_ATI 0x981B
+#define GLX_AUX5_ATI 0x981C
+#define GLX_AUX6_ATI 0x981D
+#define GLX_AUX7_ATI 0x981E
+#define GLX_AUX8_ATI 0x981F
+#define GLX_AUX9_ATI 0x9820
+#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821
+#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822
+
+typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer);
+typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list);
+typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer);
+
+#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI)
+#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI)
+#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI)
+
+#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture)
+
+#endif /* GLX_ATI_render_texture */
+
+/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */
+
+#ifndef GLX_EXT_create_context_es2_profile
+#define GLX_EXT_create_context_es2_profile 1
+
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+#define GLXEW_EXT_create_context_es2_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es2_profile)
+
+#endif /* GLX_EXT_create_context_es2_profile */
+
+/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */
+
+#ifndef GLX_EXT_fbconfig_packed_float
+#define GLX_EXT_fbconfig_packed_float 1
+
+#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008
+#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1
+
+#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float)
+
+#endif /* GLX_EXT_fbconfig_packed_float */
+
+/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */
+
+#ifndef GLX_EXT_framebuffer_sRGB
+#define GLX_EXT_framebuffer_sRGB 1
+
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2
+
+#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB)
+
+#endif /* GLX_EXT_framebuffer_sRGB */
+
+/* ------------------------- GLX_EXT_import_context ------------------------ */
+
+#ifndef GLX_EXT_import_context
+#define GLX_EXT_import_context 1
+
+#define GLX_SHARE_CONTEXT_EXT 0x800A
+#define GLX_VISUAL_ID_EXT 0x800B
+#define GLX_SCREEN_EXT 0x800C
+
+typedef XID GLXContextID;
+
+typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context);
+typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context);
+typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID);
+typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value);
+
+#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT)
+#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT)
+#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT)
+#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT)
+
+#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context)
+
+#endif /* GLX_EXT_import_context */
+
+/* -------------------------- GLX_EXT_scene_marker ------------------------- */
+
+#ifndef GLX_EXT_scene_marker
+#define GLX_EXT_scene_marker 1
+
+#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker)
+
+#endif /* GLX_EXT_scene_marker */
+
+/* -------------------------- GLX_EXT_swap_control ------------------------- */
+
+#ifndef GLX_EXT_swap_control
+#define GLX_EXT_swap_control 1
+
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+
+typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval);
+
+#define glXSwapIntervalEXT GLXEW_GET_FUN(__glewXSwapIntervalEXT)
+
+#define GLXEW_EXT_swap_control GLXEW_GET_VAR(__GLXEW_EXT_swap_control)
+
+#endif /* GLX_EXT_swap_control */
+
+/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */
+
+#ifndef GLX_EXT_texture_from_pixmap
+#define GLX_EXT_texture_from_pixmap 1
+
+#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define GLX_Y_INVERTED_EXT 0x20D4
+#define GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define GLX_TEXTURE_TARGET_EXT 0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT 0x20D7
+#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+#define GLX_TEXTURE_1D_EXT 0x20DB
+#define GLX_TEXTURE_2D_EXT 0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+#define GLX_FRONT_LEFT_EXT 0x20DE
+#define GLX_FRONT_RIGHT_EXT 0x20DF
+#define GLX_BACK_LEFT_EXT 0x20E0
+#define GLX_BACK_RIGHT_EXT 0x20E1
+#define GLX_AUX0_EXT 0x20E2
+#define GLX_AUX1_EXT 0x20E3
+#define GLX_AUX2_EXT 0x20E4
+#define GLX_AUX3_EXT 0x20E5
+#define GLX_AUX4_EXT 0x20E6
+#define GLX_AUX5_EXT 0x20E7
+#define GLX_AUX6_EXT 0x20E8
+#define GLX_AUX7_EXT 0x20E9
+#define GLX_AUX8_EXT 0x20EA
+#define GLX_AUX9_EXT 0x20EB
+
+typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list);
+typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer);
+
+#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT)
+#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT)
+
+#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap)
+
+#endif /* GLX_EXT_texture_from_pixmap */
+
+/* -------------------------- GLX_EXT_visual_info -------------------------- */
+
+#ifndef GLX_EXT_visual_info
+#define GLX_EXT_visual_info 1
+
+#define GLX_X_VISUAL_TYPE_EXT 0x22
+#define GLX_TRANSPARENT_TYPE_EXT 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24
+#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28
+#define GLX_NONE_EXT 0x8000
+#define GLX_TRUE_COLOR_EXT 0x8002
+#define GLX_DIRECT_COLOR_EXT 0x8003
+#define GLX_PSEUDO_COLOR_EXT 0x8004
+#define GLX_STATIC_COLOR_EXT 0x8005
+#define GLX_GRAY_SCALE_EXT 0x8006
+#define GLX_STATIC_GRAY_EXT 0x8007
+#define GLX_TRANSPARENT_RGB_EXT 0x8008
+#define GLX_TRANSPARENT_INDEX_EXT 0x8009
+
+#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info)
+
+#endif /* GLX_EXT_visual_info */
+
+/* ------------------------- GLX_EXT_visual_rating ------------------------- */
+
+#ifndef GLX_EXT_visual_rating
+#define GLX_EXT_visual_rating 1
+
+#define GLX_VISUAL_CAVEAT_EXT 0x20
+#define GLX_SLOW_VISUAL_EXT 0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
+
+#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating)
+
+#endif /* GLX_EXT_visual_rating */
+
+/* -------------------------- GLX_INTEL_swap_event ------------------------- */
+
+#ifndef GLX_INTEL_swap_event
+#define GLX_INTEL_swap_event 1
+
+#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180
+#define GLX_COPY_COMPLETE_INTEL 0x8181
+#define GLX_FLIP_COMPLETE_INTEL 0x8182
+#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000
+
+#define GLXEW_INTEL_swap_event GLXEW_GET_VAR(__GLXEW_INTEL_swap_event)
+
+#endif /* GLX_INTEL_swap_event */
+
+/* -------------------------- GLX_MESA_agp_offset -------------------------- */
+
+#ifndef GLX_MESA_agp_offset
+#define GLX_MESA_agp_offset 1
+
+typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer);
+
+#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA)
+
+#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset)
+
+#endif /* GLX_MESA_agp_offset */
+
+/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */
+
+#ifndef GLX_MESA_copy_sub_buffer
+#define GLX_MESA_copy_sub_buffer 1
+
+typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height);
+
+#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA)
+
+#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer)
+
+#endif /* GLX_MESA_copy_sub_buffer */
+
+/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */
+
+#ifndef GLX_MESA_pixmap_colormap
+#define GLX_MESA_pixmap_colormap 1
+
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
+
+#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA)
+
+#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap)
+
+#endif /* GLX_MESA_pixmap_colormap */
+
+/* ------------------------ GLX_MESA_release_buffers ----------------------- */
+
+#ifndef GLX_MESA_release_buffers
+#define GLX_MESA_release_buffers 1
+
+typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d);
+
+#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA)
+
+#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers)
+
+#endif /* GLX_MESA_release_buffers */
+
+/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */
+
+#ifndef GLX_MESA_set_3dfx_mode
+#define GLX_MESA_set_3dfx_mode 1
+
+#define GLX_3DFX_WINDOW_MODE_MESA 0x1
+#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2
+
+typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode);
+
+#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA)
+
+#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode)
+
+#endif /* GLX_MESA_set_3dfx_mode */
+
+/* ------------------------- GLX_MESA_swap_control ------------------------- */
+
+#ifndef GLX_MESA_swap_control
+#define GLX_MESA_swap_control 1
+
+typedef int ( * PFNGLXGETSWAPINTERVALMESAPROC) (void);
+typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval);
+
+#define glXGetSwapIntervalMESA GLXEW_GET_FUN(__glewXGetSwapIntervalMESA)
+#define glXSwapIntervalMESA GLXEW_GET_FUN(__glewXSwapIntervalMESA)
+
+#define GLXEW_MESA_swap_control GLXEW_GET_VAR(__GLXEW_MESA_swap_control)
+
+#endif /* GLX_MESA_swap_control */
+
+/* --------------------------- GLX_NV_copy_image --------------------------- */
+
+#ifndef GLX_NV_copy_image
+#define GLX_NV_copy_image 1
+
+typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+#define glXCopyImageSubDataNV GLXEW_GET_FUN(__glewXCopyImageSubDataNV)
+
+#define GLXEW_NV_copy_image GLXEW_GET_VAR(__GLXEW_NV_copy_image)
+
+#endif /* GLX_NV_copy_image */
+
+/* -------------------------- GLX_NV_float_buffer -------------------------- */
+
+#ifndef GLX_NV_float_buffer
+#define GLX_NV_float_buffer 1
+
+#define GLX_FLOAT_COMPONENTS_NV 0x20B0
+
+#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer)
+
+#endif /* GLX_NV_float_buffer */
+
+/* ---------------------- GLX_NV_multisample_coverage ---------------------- */
+
+#ifndef GLX_NV_multisample_coverage
+#define GLX_NV_multisample_coverage 1
+
+#define GLX_COLOR_SAMPLES_NV 0x20B3
+#define GLX_COVERAGE_SAMPLES_NV 100001
+
+#define GLXEW_NV_multisample_coverage GLXEW_GET_VAR(__GLXEW_NV_multisample_coverage)
+
+#endif /* GLX_NV_multisample_coverage */
+
+/* -------------------------- GLX_NV_present_video ------------------------- */
+
+#ifndef GLX_NV_present_video
+#define GLX_NV_present_video 1
+
+#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0
+
+typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list);
+typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements);
+
+#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV)
+#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV)
+
+#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video)
+
+#endif /* GLX_NV_present_video */
+
+/* --------------------------- GLX_NV_swap_group --------------------------- */
+
+#ifndef GLX_NV_swap_group
+#define GLX_NV_swap_group 1
+
+typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier);
+typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group);
+typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count);
+typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers);
+typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier);
+typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen);
+
+#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV)
+#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV)
+#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV)
+#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV)
+#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV)
+#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV)
+
+#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group)
+
+#endif /* GLX_NV_swap_group */
+
+/* ----------------------- GLX_NV_vertex_array_range ----------------------- */
+
+#ifndef GLX_NV_vertex_array_range
+#define GLX_NV_vertex_array_range 1
+
+typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer);
+
+#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV)
+#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV)
+
+#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range)
+
+#endif /* GLX_NV_vertex_array_range */
+
+/* -------------------------- GLX_NV_video_capture ------------------------- */
+
+#ifndef GLX_NV_video_capture
+#define GLX_NV_video_capture 1
+
+#define GLX_DEVICE_ID_NV 0x20CD
+#define GLX_UNIQUE_ID_NV 0x20CE
+#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+
+typedef XID GLXVideoCaptureDeviceNV;
+
+typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (Display* dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device);
+typedef GLXVideoCaptureDeviceNV * ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (Display* dpy, int screen, int *nelements);
+typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device);
+typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value);
+typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device);
+
+#define glXBindVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXBindVideoCaptureDeviceNV)
+#define glXEnumerateVideoCaptureDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoCaptureDevicesNV)
+#define glXLockVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXLockVideoCaptureDeviceNV)
+#define glXQueryVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXQueryVideoCaptureDeviceNV)
+#define glXReleaseVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoCaptureDeviceNV)
+
+#define GLXEW_NV_video_capture GLXEW_GET_VAR(__GLXEW_NV_video_capture)
+
+#endif /* GLX_NV_video_capture */
+
+/* -------------------------- GLX_NV_video_output -------------------------- */
+
+#ifndef GLX_NV_video_output
+#define GLX_NV_video_output 1
+
+#define GLX_VIDEO_OUT_COLOR_NV 0x20C3
+#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4
+#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5
+#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define GLX_VIDEO_OUT_FRAME_NV 0x20C8
+#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9
+#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA
+#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB
+#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC
+
+typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer);
+typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice);
+typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice);
+typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf);
+typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock);
+
+#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV)
+#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV)
+#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV)
+#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV)
+#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV)
+#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV)
+
+#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output)
+
+#endif /* GLX_NV_video_output */
+
+/* -------------------------- GLX_OML_swap_method -------------------------- */
+
+#ifndef GLX_OML_swap_method
+#define GLX_OML_swap_method 1
+
+#define GLX_SWAP_METHOD_OML 0x8060
+#define GLX_SWAP_EXCHANGE_OML 0x8061
+#define GLX_SWAP_COPY_OML 0x8062
+#define GLX_SWAP_UNDEFINED_OML 0x8063
+
+#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method)
+
+#endif /* GLX_OML_swap_method */
+
+/* -------------------------- GLX_OML_sync_control ------------------------- */
+
+#ifndef GLX_OML_sync_control
+#define GLX_OML_sync_control 1
+
+typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator);
+typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
+typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
+typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc);
+typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc);
+
+#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML)
+#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML)
+#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML)
+#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML)
+#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML)
+
+#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control)
+
+#endif /* GLX_OML_sync_control */
+
+/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */
+
+#ifndef GLX_SGIS_blended_overlay
+#define GLX_SGIS_blended_overlay 1
+
+#define GLX_BLENDED_RGBA_SGIS 0x8025
+
+#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay)
+
+#endif /* GLX_SGIS_blended_overlay */
+
+/* -------------------------- GLX_SGIS_color_range ------------------------- */
+
+#ifndef GLX_SGIS_color_range
+#define GLX_SGIS_color_range 1
+
+#define GLX_MIN_RED_SGIS 0
+#define GLX_MAX_GREEN_SGIS 0
+#define GLX_MIN_BLUE_SGIS 0
+#define GLX_MAX_ALPHA_SGIS 0
+#define GLX_MIN_GREEN_SGIS 0
+#define GLX_MIN_ALPHA_SGIS 0
+#define GLX_MAX_RED_SGIS 0
+#define GLX_EXTENDED_RANGE_SGIS 0
+#define GLX_MAX_BLUE_SGIS 0
+
+#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range)
+
+#endif /* GLX_SGIS_color_range */
+
+/* -------------------------- GLX_SGIS_multisample ------------------------- */
+
+#ifndef GLX_SGIS_multisample
+#define GLX_SGIS_multisample 1
+
+#define GLX_SAMPLE_BUFFERS_SGIS 100000
+#define GLX_SAMPLES_SGIS 100001
+
+#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample)
+
+#endif /* GLX_SGIS_multisample */
+
+/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */
+
+#ifndef GLX_SGIS_shared_multisample
+#define GLX_SGIS_shared_multisample 1
+
+#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
+#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
+
+#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample)
+
+#endif /* GLX_SGIS_shared_multisample */
+
+/* --------------------------- GLX_SGIX_fbconfig --------------------------- */
+
+#ifndef GLX_SGIX_fbconfig
+#define GLX_SGIX_fbconfig 1
+
+#define GLX_WINDOW_BIT_SGIX 0x00000001
+#define GLX_RGBA_BIT_SGIX 0x00000001
+#define GLX_PIXMAP_BIT_SGIX 0x00000002
+#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define GLX_SCREEN_EXT 0x800C
+#define GLX_DRAWABLE_TYPE_SGIX 0x8010
+#define GLX_RENDER_TYPE_SGIX 0x8011
+#define GLX_X_RENDERABLE_SGIX 0x8012
+#define GLX_FBCONFIG_ID_SGIX 0x8013
+#define GLX_RGBA_TYPE_SGIX 0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015
+
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+
+typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap);
+typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis);
+typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config);
+
+#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX)
+#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX)
+#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX)
+#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX)
+#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX)
+#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX)
+
+#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig)
+
+#endif /* GLX_SGIX_fbconfig */
+
+/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */
+
+#ifndef GLX_SGIX_hyperpipe
+#define GLX_SGIX_hyperpipe 1
+
+#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001
+#define GLX_PIPE_RECT_SGIX 0x00000001
+#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002
+#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002
+#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003
+#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004
+#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
+#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91
+#define GLX_BAD_HYPERPIPE_SGIX 92
+#define GLX_HYPERPIPE_ID_SGIX 0x8030
+
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int networkId;
+} GLXHyperpipeNetworkSGIX;
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int XOrigin;
+ int YOrigin;
+ int maxHeight;
+ int maxWidth;
+} GLXPipeRectLimits;
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int channel;
+ unsigned int participationType;
+ int timeSlice;
+} GLXHyperpipeConfigSGIX;
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int srcXOrigin;
+ int srcYOrigin;
+ int srcWidth;
+ int srcHeight;
+ int destXOrigin;
+ int destYOrigin;
+ int destWidth;
+ int destHeight;
+} GLXPipeRect;
+
+typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId);
+typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId);
+typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList);
+typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId);
+typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList);
+typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList);
+typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes);
+typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes);
+
+#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX)
+#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX)
+#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX)
+#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX)
+#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX)
+#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX)
+#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX)
+#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX)
+
+#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe)
+
+#endif /* GLX_SGIX_hyperpipe */
+
+/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */
+
+#ifndef GLX_SGIX_pbuffer
+#define GLX_SGIX_pbuffer 1
+
+#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
+#define GLX_PBUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
+#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
+#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
+#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040
+#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080
+#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100
+#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017
+#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018
+#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019
+#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A
+#define GLX_PRESERVED_CONTENTS_SGIX 0x801B
+#define GLX_LARGEST_PBUFFER_SGIX 0x801C
+#define GLX_WIDTH_SGIX 0x801D
+#define GLX_HEIGHT_SGIX 0x801E
+#define GLX_EVENT_MASK_SGIX 0x801F
+#define GLX_DAMAGED_SGIX 0x8020
+#define GLX_SAVED_SGIX 0x8021
+#define GLX_WINDOW_SGIX 0x8022
+#define GLX_PBUFFER_SGIX 0x8023
+#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000
+
+typedef XID GLXPbufferSGIX;
+typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX;
+
+typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list);
+typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf);
+typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask);
+typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask);
+
+#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX)
+#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX)
+#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX)
+#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX)
+#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX)
+
+#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer)
+
+#endif /* GLX_SGIX_pbuffer */
+
+/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */
+
+#ifndef GLX_SGIX_swap_barrier
+#define GLX_SGIX_swap_barrier 1
+
+typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier);
+typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max);
+
+#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX)
+#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX)
+
+#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier)
+
+#endif /* GLX_SGIX_swap_barrier */
+
+/* -------------------------- GLX_SGIX_swap_group -------------------------- */
+
+#ifndef GLX_SGIX_swap_group
+#define GLX_SGIX_swap_group 1
+
+typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member);
+
+#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX)
+
+#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group)
+
+#endif /* GLX_SGIX_swap_group */
+
+/* ------------------------- GLX_SGIX_video_resize ------------------------- */
+
+#ifndef GLX_SGIX_video_resize
+#define GLX_SGIX_video_resize 1
+
+#define GLX_SYNC_FRAME_SGIX 0x00000000
+#define GLX_SYNC_SWAP_SGIX 0x00000001
+
+typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window);
+typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h);
+typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype);
+typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h);
+typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+
+#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX)
+#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX)
+#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX)
+#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX)
+#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX)
+
+#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize)
+
+#endif /* GLX_SGIX_video_resize */
+
+/* ---------------------- GLX_SGIX_visual_select_group --------------------- */
+
+#ifndef GLX_SGIX_visual_select_group
+#define GLX_SGIX_visual_select_group 1
+
+#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028
+
+#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group)
+
+#endif /* GLX_SGIX_visual_select_group */
+
+/* ---------------------------- GLX_SGI_cushion ---------------------------- */
+
+#ifndef GLX_SGI_cushion
+#define GLX_SGI_cushion 1
+
+typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion);
+
+#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI)
+
+#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion)
+
+#endif /* GLX_SGI_cushion */
+
+/* ----------------------- GLX_SGI_make_current_read ----------------------- */
+
+#ifndef GLX_SGI_make_current_read
+#define GLX_SGI_make_current_read 1
+
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void);
+typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+
+#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI)
+#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI)
+
+#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read)
+
+#endif /* GLX_SGI_make_current_read */
+
+/* -------------------------- GLX_SGI_swap_control ------------------------- */
+
+#ifndef GLX_SGI_swap_control
+#define GLX_SGI_swap_control 1
+
+typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
+
+#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI)
+
+#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control)
+
+#endif /* GLX_SGI_swap_control */
+
+/* --------------------------- GLX_SGI_video_sync -------------------------- */
+
+#ifndef GLX_SGI_video_sync
+#define GLX_SGI_video_sync 1
+
+typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int* count);
+typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count);
+
+#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI)
+#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI)
+
+#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync)
+
+#endif /* GLX_SGI_video_sync */
+
+/* --------------------- GLX_SUN_get_transparent_index --------------------- */
+
+#ifndef GLX_SUN_get_transparent_index
+#define GLX_SUN_get_transparent_index 1
+
+typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex);
+
+#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN)
+
+#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index)
+
+#endif /* GLX_SUN_get_transparent_index */
+
+/* -------------------------- GLX_SUN_video_resize ------------------------- */
+
+#ifndef GLX_SUN_video_resize
+#define GLX_SUN_video_resize 1
+
+#define GLX_VIDEO_RESIZE_SUN 0x8171
+#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD
+
+typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor);
+typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor);
+
+#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN)
+#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN)
+
+#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize)
+
+#endif /* GLX_SUN_video_resize */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+#define GLXEW_EXPORT
+#else
+#define GLXEW_EXPORT extern
+#endif /* GLEW_MX */
+
+extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay;
+
+extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig;
+extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext;
+extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer;
+extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap;
+extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow;
+extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer;
+extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap;
+extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow;
+extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable;
+extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib;
+extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs;
+extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent;
+extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig;
+extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent;
+extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext;
+extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable;
+extern PFNGLXSELECTEVENTPROC __glewXSelectEvent;
+
+extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB;
+
+extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI;
+extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI;
+extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI;
+
+extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT;
+extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT;
+extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT;
+extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT;
+
+extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT;
+
+extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT;
+extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT;
+
+extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA;
+
+extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA;
+
+extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA;
+
+extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA;
+
+extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA;
+
+extern PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA;
+extern PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA;
+
+extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV;
+
+extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV;
+extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV;
+
+extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV;
+extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV;
+extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV;
+extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV;
+extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV;
+extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV;
+
+extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV;
+extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV;
+
+extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV;
+extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV;
+extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV;
+extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV;
+extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV;
+
+extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV;
+extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV;
+extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV;
+extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV;
+extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV;
+extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV;
+
+extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML;
+extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML;
+extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML;
+extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML;
+extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML;
+
+extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX;
+extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX;
+extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX;
+extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX;
+extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX;
+extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX;
+
+extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX;
+extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX;
+extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX;
+extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX;
+extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX;
+extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX;
+extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX;
+extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX;
+
+extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX;
+extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX;
+extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX;
+extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX;
+extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX;
+
+extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX;
+extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX;
+
+extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX;
+
+extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX;
+extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX;
+extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX;
+extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX;
+extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX;
+
+extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI;
+
+extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI;
+extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI;
+
+extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI;
+
+extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI;
+extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI;
+
+extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN;
+
+extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN;
+extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN;
+
+#if defined(GLEW_MX)
+struct GLXEWContextStruct
+{
+#endif /* GLEW_MX */
+
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3;
+GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4;
+GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object;
+GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float;
+GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info;
+GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating;
+GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode;
+GLXEW_EXPORT GLboolean __GLXEW_MESA_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image;
+GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer;
+GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage;
+GLXEW_EXPORT GLboolean __GLXEW_NV_present_video;
+GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group;
+GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range;
+GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture;
+GLXEW_EXPORT GLboolean __GLXEW_NV_video_output;
+GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method;
+GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize;
+GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control;
+GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync;
+GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index;
+GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize;
+
+#ifdef GLEW_MX
+}; /* GLXEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef GLEW_MX
+
+typedef struct GLXEWContextStruct GLXEWContext;
+extern GLenum glxewContextInit (GLXEWContext* ctx);
+extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name);
+
+#define glxewInit() glxewContextInit(glxewGetContext())
+#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x)
+
+#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x))
+#define GLXEW_GET_FUN(x) x
+
+#else /* GLEW_MX */
+
+#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define GLXEW_GET_FUN(x) x
+
+extern GLboolean glxewIsSupported (const char* name);
+
+#endif /* GLEW_MX */
+
+extern GLboolean glxewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __glxew_h__ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxext.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxext.h
new file mode 100644
index 00000000..cccee18d
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/glxext.h
@@ -0,0 +1,941 @@
+#ifndef __glxext_h_
+#define __glxext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: This software was created using the
+** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
+** not been independently verified as being compliant with the OpenGL(R)
+** version 1.2.1 Specification.
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+/*************************************************************/
+
+/* Header file version number, required by OpenGL ABI for Linux */
+/* glxext.h last updated 2009/01/08 */
+/* Current version at http://www.opengl.org/registry/ */
+#define GLX_GLXEXT_VERSION 21
+
+#ifndef GLX_ARB_get_proc_address
+#endif
+
+#ifndef GLX_ARB_multisample
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB 100001
+#endif
+
+#ifndef GLX_ARB_fbconfig_float
+#define GLX_RGBA_FLOAT_TYPE_ARB 0x20B9
+#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004
+#endif
+
+#ifndef GLX_ARB_create_context
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#endif
+
+#ifndef GLX_SGIS_multisample
+#define GLX_SAMPLE_BUFFERS_SGIS 100000
+#define GLX_SAMPLES_SGIS 100001
+#endif
+
+#ifndef GLX_EXT_visual_info
+#define GLX_X_VISUAL_TYPE_EXT 0x22
+#define GLX_TRANSPARENT_TYPE_EXT 0x23
+#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24
+#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25
+#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26
+#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28
+#define GLX_NONE_EXT 0x8000
+#define GLX_TRUE_COLOR_EXT 0x8002
+#define GLX_DIRECT_COLOR_EXT 0x8003
+#define GLX_PSEUDO_COLOR_EXT 0x8004
+#define GLX_STATIC_COLOR_EXT 0x8005
+#define GLX_GRAY_SCALE_EXT 0x8006
+#define GLX_STATIC_GRAY_EXT 0x8007
+#define GLX_TRANSPARENT_RGB_EXT 0x8008
+#define GLX_TRANSPARENT_INDEX_EXT 0x8009
+#endif
+
+#ifndef GLX_SGI_swap_control
+#endif
+
+#ifndef GLX_SGI_video_sync
+#endif
+
+#ifndef GLX_SGI_make_current_read
+#endif
+
+#ifndef GLX_SGIX_video_source
+#endif
+
+#ifndef GLX_EXT_visual_rating
+#define GLX_VISUAL_CAVEAT_EXT 0x20
+#define GLX_SLOW_VISUAL_EXT 0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
+/* reuse GLX_NONE_EXT */
+#endif
+
+#ifndef GLX_EXT_import_context
+#define GLX_SHARE_CONTEXT_EXT 0x800A
+#define GLX_VISUAL_ID_EXT 0x800B
+#define GLX_SCREEN_EXT 0x800C
+#endif
+
+#ifndef GLX_SGIX_fbconfig
+#define GLX_WINDOW_BIT_SGIX 0x00000001
+#define GLX_PIXMAP_BIT_SGIX 0x00000002
+#define GLX_RGBA_BIT_SGIX 0x00000001
+#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define GLX_DRAWABLE_TYPE_SGIX 0x8010
+#define GLX_RENDER_TYPE_SGIX 0x8011
+#define GLX_X_RENDERABLE_SGIX 0x8012
+#define GLX_FBCONFIG_ID_SGIX 0x8013
+#define GLX_RGBA_TYPE_SGIX 0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015
+/* reuse GLX_SCREEN_EXT */
+#endif
+
+#ifndef GLX_SGIX_pbuffer
+#define GLX_PBUFFER_BIT_SGIX 0x00000004
+#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000
+#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
+#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
+#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
+#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040
+#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080
+#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100
+#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016
+#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017
+#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018
+#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019
+#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A
+#define GLX_PRESERVED_CONTENTS_SGIX 0x801B
+#define GLX_LARGEST_PBUFFER_SGIX 0x801C
+#define GLX_WIDTH_SGIX 0x801D
+#define GLX_HEIGHT_SGIX 0x801E
+#define GLX_EVENT_MASK_SGIX 0x801F
+#define GLX_DAMAGED_SGIX 0x8020
+#define GLX_SAVED_SGIX 0x8021
+#define GLX_WINDOW_SGIX 0x8022
+#define GLX_PBUFFER_SGIX 0x8023
+#endif
+
+#ifndef GLX_SGI_cushion
+#endif
+
+#ifndef GLX_SGIX_video_resize
+#define GLX_SYNC_FRAME_SGIX 0x00000000
+#define GLX_SYNC_SWAP_SGIX 0x00000001
+#endif
+
+#ifndef GLX_SGIX_dmbuffer
+#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024
+#endif
+
+#ifndef GLX_SGIX_swap_group
+#endif
+
+#ifndef GLX_SGIX_swap_barrier
+#endif
+
+#ifndef GLX_SGIS_blended_overlay
+#define GLX_BLENDED_RGBA_SGIS 0x8025
+#endif
+
+#ifndef GLX_SGIS_shared_multisample
+#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
+#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
+#endif
+
+#ifndef GLX_SUN_get_transparent_index
+#endif
+
+#ifndef GLX_3DFX_multisample
+#define GLX_SAMPLE_BUFFERS_3DFX 0x8050
+#define GLX_SAMPLES_3DFX 0x8051
+#endif
+
+#ifndef GLX_MESA_copy_sub_buffer
+#endif
+
+#ifndef GLX_MESA_pixmap_colormap
+#endif
+
+#ifndef GLX_MESA_release_buffers
+#endif
+
+#ifndef GLX_MESA_set_3dfx_mode
+#define GLX_3DFX_WINDOW_MODE_MESA 0x1
+#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2
+#endif
+
+#ifndef GLX_SGIX_visual_select_group
+#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028
+#endif
+
+#ifndef GLX_OML_swap_method
+#define GLX_SWAP_METHOD_OML 0x8060
+#define GLX_SWAP_EXCHANGE_OML 0x8061
+#define GLX_SWAP_COPY_OML 0x8062
+#define GLX_SWAP_UNDEFINED_OML 0x8063
+#endif
+
+#ifndef GLX_OML_sync_control
+#endif
+
+#ifndef GLX_NV_float_buffer
+#define GLX_FLOAT_COMPONENTS_NV 0x20B0
+#endif
+
+#ifndef GLX_SGIX_hyperpipe
+#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
+#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91
+#define GLX_BAD_HYPERPIPE_SGIX 92
+#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001
+#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002
+#define GLX_PIPE_RECT_SGIX 0x00000001
+#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002
+#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003
+#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004
+#define GLX_HYPERPIPE_ID_SGIX 0x8030
+#endif
+
+#ifndef GLX_MESA_agp_offset
+#endif
+
+
+/*************************************************************/
+
+#ifndef GLX_ARB_get_proc_address
+/*
+ * Linux OpenGL ABI specifies glXGetProcAddressARB should be
+ * in glx.h moving related defines there as well.
+ */
+#endif
+
+#ifndef GLX_SGIX_video_source
+typedef XID GLXVideoSourceSGIX;
+#endif
+
+#ifndef GLX_SGIX_fbconfig
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+#endif
+
+#ifndef GLX_SGIX_pbuffer
+typedef XID GLXPbufferSGIX;
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came for SendEvent request */
+ Display *display; /* display the event was read from */
+ GLXDrawable drawable; /* i.d. of Drawable */
+ int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */
+ int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */
+ unsigned int mask; /* mask indicating which buffers are affected*/
+ int x, y;
+ int width, height;
+ int count; /* if nonzero, at least this many more */
+} GLXBufferClobberEventSGIX;
+#endif
+
+#ifndef GLX_NV_swap_group
+#endif
+
+#ifndef GLX_NV_video_out
+/*
+ * GLXVideoDeviceNV is an opaque handle to a video device (part of the
+ * GLX_NV_video_out extension).
+ */
+typedef unsigned int GLXVideoDeviceNV;
+
+/* glXBindVideoImageNV iVideoBuffer values (NV_video_out) */
+#define GLX_VIDEO_OUT_COLOR_NV 0x20C3
+#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4
+#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5
+#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+
+/* glXSendPbufferToVideoNV iBufferType values (NV_video_out) */
+#define GLX_VIDEO_OUT_FRAME_NV 0x20C8
+#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9
+#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA
+#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB
+#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC
+#endif
+
+#ifndef GLX_EXT_fbconfig_packed_float
+#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1
+#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008
+#endif
+
+#ifndef GLX_EXT_framebuffer_sRGB
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2
+#endif
+
+#ifndef GLX_EXT_texture_from_pixmap
+/* New glXGetFBConfigAttrib <attrib_list> tokens */
+#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define GLX_Y_INVERTED_EXT 0x20D4
+
+/* New glXCreatePixmap attributes and glXQueryDrawable attributes */
+#define GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define GLX_TEXTURE_TARGET_EXT 0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT 0x20D7
+
+/* Values for GLX_TEXTURE_FORMAT_EXT */
+#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+
+/* Bits for GLX_BIND_TO_TEXTURE_TARGETS_EXT mask */
+#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+
+/* Values for GLX_TEXTURE_TARGET_EXT */
+#define GLX_TEXTURE_1D_EXT 0x20DB
+#define GLX_TEXTURE_2D_EXT 0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+
+/*
+ * Values for the buffer parameter of glXBindTexImageEXT and
+ * glXReleaseTexImageEXT
+ */
+#define GLX_FRONT_LEFT_EXT 0x20DE
+#define GLX_FRONT_RIGHT_EXT 0x20DF
+#define GLX_BACK_LEFT_EXT 0x20E0
+#define GLX_BACK_RIGHT_EXT 0x20E1
+#define GLX_FRONT_EXT GLX_FRONT_LEFT_EXT
+#define GLX_BACK_EXT GLX_BACK_LEFT_EXT
+#define GLX_AUX0_EXT 0x20E2
+#define GLX_AUX1_EXT 0x20E3
+#define GLX_AUX2_EXT 0x20E4
+#define GLX_AUX3_EXT 0x20E5
+#define GLX_AUX4_EXT 0x20E6
+#define GLX_AUX5_EXT 0x20E7
+#define GLX_AUX6_EXT 0x20E8
+#define GLX_AUX7_EXT 0x20E9
+#define GLX_AUX8_EXT 0x20EA
+#define GLX_AUX9_EXT 0x20EB
+
+#endif
+
+#ifndef GLX_NV_multisample_coverage
+#define GLX_COVERAGE_SAMPLES_NV GLX_SAMPLES_ARB
+#define GLX_COLOR_SAMPLES_NV 0x20B3
+#endif
+
+#ifndef GLX_NV_video_capture
+typedef struct GLXVideoCaptureDeviceNVRec *GLXVideoCaptureDeviceNV;
+
+#define GLX_DEVICE_ID_NV 0x20CD
+#define GLX_UNIQUE_ID_NV 0x20CE
+#endif
+
+#ifndef GLX_EXT_swap_control
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#endif
+
+#ifndef GLX_EXT_swap_control_tear
+#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
+#endif
+
+/* Define int32_t and int64_t types for UST/MSC */
+/* (as used in the GLX_OML_sync_control extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined( __VMS ) || defined(__FreeBSD__)
+#include <inttypes.h>
+#elif (defined(__sun__) && defined(__svr4__)) || (defined(__sun) && defined(__SVR4))
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__) || defined(__linux__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+#else
+#error "int32_t and int64_t are undefined!"
+#endif
+
+#ifndef GLX_ARB_get_proc_address
+/* Moved to glx.h */
+#endif
+
+#ifndef GLX_ARB_multisample
+#define GLX_ARB_multisample 1
+#endif
+
+#ifndef GLX_ARB_fbconfig_float
+#define GLX_ARB_fbconfig_float 1
+#endif
+
+#ifndef GLX_ARB_create_context
+#define GLX_ARB_create_context 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern GLXContext glXCreateContextAttribsARB (Display *, GLXFBConfig, GLXContext, Bool, const int *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+#endif
+
+#ifndef GLX_SGIS_multisample
+#define GLX_SGIS_multisample 1
+#endif
+
+#ifndef GLX_EXT_visual_info
+#define GLX_EXT_visual_info 1
+#endif
+
+#ifndef GLX_SGI_swap_control
+#define GLX_SGI_swap_control 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern int glXSwapIntervalSGI (int);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
+#endif
+
+#ifndef GLX_EXT_swap_control
+#define GLX_EXT_swap_control 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern int glXSwapIntervalEXT (Display *dpy, GLXDrawable drawable, int interval);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef int ( * PFNGLXSWAPINTERVALEXTPROC) (Display *dpy, GLXDrawable drawable, int interval);
+#endif
+
+#ifndef GLX_EXT_swap_control_tear
+#define GLX_EXT_swap_control_tear 1
+#endif
+
+#ifndef GLX_SGI_video_sync
+#define GLX_SGI_video_sync 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern int glXGetVideoSyncSGI (unsigned int *);
+extern int glXWaitVideoSyncSGI (int, int, unsigned int *);
+extern int glXGetRefreshRateSGI(unsigned int *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count);
+typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count);
+typedef int ( * PFNGLXGETREFRESHRATESGIPROC) (unsigned int *);
+#endif
+
+#ifndef GLX_SGI_make_current_read
+#define GLX_SGI_make_current_read 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Bool glXMakeCurrentReadSGI (Display *, GLXDrawable, GLXDrawable, GLXContext);
+extern GLXDrawable glXGetCurrentReadDrawableSGI (void);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void);
+#endif
+
+#ifndef GLX_SGIX_video_source
+#define GLX_SGIX_video_source 1
+#ifdef _VL_H
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (Display *, int, VLServer, VLPath, int, VLNode);
+extern void glXDestroyGLXVideoSourceSGIX (Display *, GLXVideoSourceSGIX);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef GLXVideoSourceSGIX ( * PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);
+typedef void ( * PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (Display *dpy, GLXVideoSourceSGIX glxvideosource);
+#endif /* _VL_H */
+#endif
+
+#ifndef GLX_EXT_visual_rating
+#define GLX_EXT_visual_rating 1
+#endif
+
+#ifndef GLX_EXT_import_context
+#define GLX_EXT_import_context 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Display * glXGetCurrentDisplayEXT (void);
+extern int glXQueryContextInfoEXT (Display *, GLXContext, int, int *);
+extern GLXContextID glXGetContextIDEXT (const GLXContext);
+extern GLXContext glXImportContextEXT (Display *, GLXContextID);
+extern void glXFreeContextEXT (Display *, GLXContext);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Display * ( * PFNGLXGETCURRENTDISPLAYEXTPROC) (void);
+typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display *dpy, GLXContext context, int attribute, int *value);
+typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context);
+typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display *dpy, GLXContextID contextID);
+typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display *dpy, GLXContext context);
+#endif
+
+#ifndef GLX_SGIX_fbconfig
+#define GLX_SGIX_fbconfig 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern int glXGetFBConfigAttribSGIX (Display *, GLXFBConfigSGIX, int, int *);
+extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (Display *, int, int *, int *);
+extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (Display *, GLXFBConfigSGIX, Pixmap);
+extern GLXContext glXCreateContextWithConfigSGIX (Display *, GLXFBConfigSGIX, int, GLXContext, Bool);
+extern XVisualInfo * glXGetVisualFromFBConfigSGIX (Display *, GLXFBConfigSGIX);
+extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (Display *, XVisualInfo *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements);
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);
+typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config);
+typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display *dpy, XVisualInfo *vis);
+#endif
+
+#ifndef GLX_SGIX_pbuffer
+#define GLX_SGIX_pbuffer 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *);
+extern void glXDestroyGLXPbufferSGIX (Display *, GLXPbufferSGIX);
+extern int glXQueryGLXPbufferSGIX (Display *, GLXPbufferSGIX, int, unsigned int *);
+extern void glXSelectEventSGIX (Display *, GLXDrawable, unsigned long);
+extern void glXGetSelectedEventSGIX (Display *, GLXDrawable, unsigned long *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef GLXPbufferSGIX ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);
+typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf);
+typedef int ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);
+typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long mask);
+typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long *mask);
+#endif
+
+#ifndef GLX_SGI_cushion
+#define GLX_SGI_cushion 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void glXCushionSGI (Display *, Window, float);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef void ( * PFNGLXCUSHIONSGIPROC) (Display *dpy, Window window, float cushion);
+#endif
+
+#ifndef GLX_SGIX_video_resize
+#define GLX_SGIX_video_resize 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern int glXBindChannelToWindowSGIX (Display *, int, int, Window);
+extern int glXChannelRectSGIX (Display *, int, int, int, int, int, int);
+extern int glXQueryChannelRectSGIX (Display *, int, int, int *, int *, int *, int *);
+extern int glXQueryChannelDeltasSGIX (Display *, int, int, int *, int *, int *, int *);
+extern int glXChannelRectSyncSGIX (Display *, int, int, GLenum);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display *display, int screen, int channel, Window window);
+typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int x, int y, int w, int h);
+typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display *display, int screen, int channel, int *x, int *y, int *w, int *h);
+typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display *display, int screen, int channel, GLenum synctype);
+#endif
+
+#ifndef GLX_SGIX_dmbuffer
+#define GLX_SGIX_dmbuffer 1
+#ifdef _DM_BUFFER_H_
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Bool glXAssociateDMPbufferSGIX (Display *, GLXPbufferSGIX, DMparams *, DMbuffer);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Bool ( * PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);
+#endif /* _DM_BUFFER_H_ */
+#endif
+
+#ifndef GLX_SGIX_swap_group
+#define GLX_SGIX_swap_group 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member);
+#endif
+
+#ifndef GLX_SGIX_swap_barrier
+#define GLX_SGIX_swap_barrier 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void glXBindSwapBarrierSGIX (Display *, GLXDrawable, int);
+extern Bool glXQueryMaxSwapBarriersSGIX (Display *, int, int *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier);
+typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max);
+#endif
+
+#ifndef GLX_SUN_get_transparent_index
+#define GLX_SUN_get_transparent_index 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Status glXGetTransparentIndexSUN (Display *, Window, Window, long *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display *dpy, Window overlay, Window underlay, long *pTransparentIndex);
+#endif
+
+#ifndef GLX_MESA_copy_sub_buffer
+#define GLX_MESA_copy_sub_buffer 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void glXCopySubBufferMESA (Display *, GLXDrawable, int, int, int, int);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
+#endif
+
+#ifndef GLX_MESA_pixmap_colormap
+#define GLX_MESA_pixmap_colormap 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern GLXPixmap glXCreateGLXPixmapMESA (Display *, XVisualInfo *, Pixmap, Colormap);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
+#endif
+
+#ifndef GLX_MESA_release_buffers
+#define GLX_MESA_release_buffers 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Bool glXReleaseBuffersMESA (Display *, GLXDrawable);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display *dpy, GLXDrawable drawable);
+#endif
+
+#ifndef GLX_MESA_set_3dfx_mode
+#define GLX_MESA_set_3dfx_mode 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Bool glXSet3DfxModeMESA (int);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Bool ( * PFNGLXSET3DFXMODEMESAPROC) (int mode);
+#endif
+
+#ifndef GLX_SGIX_visual_select_group
+#define GLX_SGIX_visual_select_group 1
+#endif
+
+#ifndef GLX_OML_swap_method
+#define GLX_OML_swap_method 1
+#endif
+
+#ifndef GLX_OML_sync_control
+#define GLX_OML_sync_control 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Bool glXGetSyncValuesOML (Display *, GLXDrawable, int64_t *, int64_t *, int64_t *);
+extern Bool glXGetMscRateOML (Display *, GLXDrawable, int32_t *, int32_t *);
+extern int64_t glXSwapBuffersMscOML (Display *, GLXDrawable, int64_t, int64_t, int64_t);
+extern Bool glXWaitForMscOML (Display *, GLXDrawable, int64_t, int64_t, int64_t, int64_t *, int64_t *, int64_t *);
+extern Bool glXWaitForSbcOML (Display *, GLXDrawable, int64_t, int64_t *, int64_t *, int64_t *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc);
+typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
+typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
+typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);
+typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc);
+#endif
+
+#ifndef GLX_NV_float_buffer
+#define GLX_NV_float_buffer 1
+#endif
+
+#ifndef GLX_SGIX_hyperpipe
+#define GLX_SGIX_hyperpipe 1
+
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int networkId;
+} GLXHyperpipeNetworkSGIX;
+
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int channel;
+ unsigned int
+ participationType;
+ int timeSlice;
+} GLXHyperpipeConfigSGIX;
+
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int srcXOrigin, srcYOrigin, srcWidth, srcHeight;
+ int destXOrigin, destYOrigin, destWidth, destHeight;
+} GLXPipeRect;
+
+typedef struct {
+ char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX];
+ int XOrigin, YOrigin, maxHeight, maxWidth;
+} GLXPipeRectLimits;
+
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern GLXHyperpipeNetworkSGIX * glXQueryHyperpipeNetworkSGIX (Display *, int *);
+extern int glXHyperpipeConfigSGIX (Display *, int, int, GLXHyperpipeConfigSGIX *, int *);
+extern GLXHyperpipeConfigSGIX * glXQueryHyperpipeConfigSGIX (Display *, int, int *);
+extern int glXDestroyHyperpipeConfigSGIX (Display *, int);
+extern int glXBindHyperpipeSGIX (Display *, int);
+extern int glXQueryHyperpipeBestAttribSGIX (Display *, int, int, int, void *, void *);
+extern int glXHyperpipeAttribSGIX (Display *, int, int, int, void *);
+extern int glXQueryHyperpipeAttribSGIX (Display *, int, int, int, void *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes);
+typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId);
+typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes);
+typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId);
+typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId);
+typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList);
+typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList);
+typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList);
+#endif
+
+#ifndef GLX_MESA_agp_offset
+#define GLX_MESA_agp_offset 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern unsigned int glXGetAGPOffsetMESA (const void *);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void *pointer);
+#endif
+
+/*
+ * GLX_NV_vertex_array_range is not a real extension name...
+ */
+#ifndef GLX_NV_vertex_array_range
+#define GLX_NV_vertex_array_range 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void *glXAllocateMemoryNV(GLsizei size, GLfloat readfreq,
+ GLfloat writefreq, GLfloat priority);
+
+extern void glXFreeMemoryNV(GLvoid *pointer);
+#endif
+typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size,
+ GLfloat readfreq,
+ GLfloat writefreq,
+ GLfloat priority);
+
+typedef void ( * PFNGLXFREEMEMORYNVPROC) (GLvoid *pointer);
+#endif
+
+#ifndef GLX_NV_swap_group
+#define GLX_NV_swap_group 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern Bool glXJoinSwapGroupNV(Display *dpy, GLXDrawable drawable,
+ GLuint group);
+
+extern Bool glXBindSwapBarrierNV(Display *dpy, GLuint group, GLuint barrier);
+
+extern Bool glXQuerySwapGroupNV(Display *dpy, GLXDrawable drawable,
+ GLuint *group, GLuint *barrier);
+
+extern Bool glXQueryMaxSwapGroupsNV(Display *dpy, int screen,
+ GLuint *maxGroups, GLuint *maxBarriers);
+
+extern Bool glXQueryFrameCountNV(Display *dpy, int screen, GLuint *count);
+
+extern Bool glXResetFrameCountNV(Display *dpy, int screen);
+#endif
+typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display *dpy,
+ GLXDrawable drawable,
+ GLuint group);
+
+typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display *dpy,
+ GLuint group,
+ GLuint barrier);
+
+typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display *dpy,
+ GLXDrawable drawable,
+ GLuint *group,
+ GLuint *barrier);
+
+typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display *dpy,
+ int screen,
+ GLuint *maxGroups,
+ GLuint *maxBarriers);
+
+typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display *dpy,
+ int screen,
+ GLuint *count);
+
+typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display *dpy, int screen);
+#endif
+
+#ifndef GLX_NV_video_out
+#define GLX_NV_video_out 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern int glXGetVideoDeviceNV(Display *dpy, int screen, int numVideoDevices,
+ GLXVideoDeviceNV *pVideoDevice);
+
+extern int glXReleaseVideoDeviceNV(Display *dpy, int screen,
+ GLXVideoDeviceNV VideoDevice);
+
+extern int glXBindVideoImageNV(Display *dpy, GLXVideoDeviceNV VideoDevice,
+ GLXPbuffer pbuf, int iVideoBuffer);
+
+extern int glXReleaseVideoImageNV(Display *dpy, GLXPbuffer pbuf);
+
+extern int glXSendPbufferToVideoNV(Display *dpy, GLXPbuffer pbuf,
+ int iBufferType,
+ unsigned long *pulCounterPbuffer,
+ GLboolean bBlock);
+
+extern int glXGetVideoInfoNV(Display *dpy, int screen,
+ GLXVideoDeviceNV VideoDevice,
+ unsigned long *pulCounterOutputPbuffer,
+ unsigned long *pulCounterOutputVideo);
+#endif
+typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display *dpy,
+ int screen,
+ int numVideoDevices,
+ GLXVideoDeviceNV *pVideoDevice);
+
+typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display *dpy,
+ int screen,
+ GLXVideoDeviceNV VideoDevice);
+
+typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display *dpy,
+ GLXVideoDeviceNV VideoDevice,
+ GLXPbuffer pbuf,
+ int iVideoBuffer);
+
+typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display *dpy,
+ GLXPbuffer pbuf);
+
+typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display *dpy,
+ GLXPbuffer pbuf,
+ int iBufferType,
+ unsigned long *pulCounterPbuffer,
+ GLboolean bBlock);
+
+typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display *dpy, int screen,
+ GLXVideoDeviceNV VideoDevice,
+ unsigned long *pulCounterOutputPbuffer,
+ unsigned long *pulCounterOutputVideo);
+#endif
+
+#ifndef GLX_EXT_fbconfig_packed_float
+#define GLX_EXT_fbconfig_packed_float 1
+#endif
+
+#ifndef GLX_EXT_framebuffer_sRGB
+#define GLX_EXT_framebuffer_sRGB 1
+#endif
+
+#ifndef GLX_EXT_texture_from_pixmap
+#define GLX_EXT_texture_from_pixmap
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void glXBindTexImageEXT(Display *dpy, GLXDrawable drawable,
+ int buffer, const int *attrib_list);
+extern void glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable,
+ int buffer);
+#endif
+typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display *dpy,
+ GLXDrawable drawable,
+ int buffer,
+ const int *attrib_list);
+typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display *dpy,
+ GLXDrawable drawable,
+ int buffer);
+#endif
+
+#ifndef GLX_NV_present_video
+#define GLX_NV_present_video
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern unsigned int *glXEnumerateVideoDevicesNV(Display *dpy,
+ int screen,
+ int *nelements);
+extern int glXBindVideoDeviceNV(Display *dpy,
+ unsigned int video_slot,
+ unsigned int video_device,
+ const int *attrib_list);
+#endif
+typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy,
+ int screen,
+ int *nelements);
+typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display *dpy,
+ unsigned int video_slot,
+ unsigned int video_device,
+ const int *attrib_list);
+#endif
+
+#ifndef GLX_NV_multisample_coverage
+#define GLX_NV_multisample_coverage 1
+#endif
+
+#ifndef GLX_NV_video_capture
+#define GLX_NV_video_capture
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern GLXVideoCaptureDeviceNV*
+ glXEnumerateVideoCaptureDevicesNV(Display *dpy,
+ int screen,
+ int *nelements);
+extern void glXLockVideoCaptureDeviceNV(Display *dpy,
+ GLXVideoCaptureDeviceNV device);
+extern void glXReleaseVideoCaptureDeviceNV(Display *dpy,
+ GLXVideoCaptureDeviceNV device);
+extern int glXBindVideoCaptureDeviceNV(Display *dpy,
+ unsigned int video_capture_slot,
+ GLXVideoCaptureDeviceNV device);
+extern int glXQueryVideoCaptureDeviceNV(Display *dpy,
+ GLXVideoCaptureDeviceNV device,
+ int attribute,
+ int *value);
+#endif
+typedef GLXVideoCaptureDeviceNV* ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC)
+ (Display *dpy,
+ int screen,
+ int *nelements);
+typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC)
+ (Display *dpy,
+ GLXVideoCaptureDeviceNV device);
+
+typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC)
+ (Display *dpy,
+ GLXVideoCaptureDeviceNV device);
+typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC)
+ (Display *dpy,
+ unsigned int video_capture_slot,
+ GLXVideoCaptureDeviceNV device);
+typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC)
+ (Display *dpy,
+ GLXVideoCaptureDeviceNV device,
+ int attribute,
+ int *value);
+#endif
+
+#ifndef GLX_NV_copy_image
+#define GLX_NV_copy_image 1
+#ifdef GLX_GLXEXT_PROTOTYPES
+extern void glXCopyImageSubDataNV (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif /* GLX_GLXEXT_PROTOTYPES */
+typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/nvogldebug.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/nvogldebug.h
new file mode 100644
index 00000000..10e43b4b
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/nvogldebug.h
@@ -0,0 +1,794 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+* This file defines the "__NvOglDebugConfig" and NVX_debug_control interfaces.
+* Its purpose is to aid debugging and development by providing a simple way for
+* applications to control global "debug variables" in the driver.
+*/
+
+#ifndef __nvogldebug_h_
+#define __nvogldebug_h_
+
+// An OpenGL implementation can have combinations of internal driver
+// and hardware state that are difficult to achieve by clever use of
+// the extended OpenGL API alone. This extension provides for
+// arbitrary modifications to driver state and behavior at runtime.
+// The exact driver behaviors that can be modified are not specified
+// here, but may be specified by layered extensions.
+
+typedef enum __GLdebugControlFunctionEnum {
+ GL_DEBUG_CONTROL_FUNCTION_IS_SUPPORTED_NVX = 10,
+ GL_DEBUG_CONTROL_FUNCTION_EVICT_OBJECT_NVX = 11,
+ GL_DEBUG_CONTROL_FUNCTION_GET_BUGFIX_PRESENT = 12,
+ GL_DEBUG_CONTROL_FUNCTION_ENABLES = 13,
+ GL_DEBUG_CONTROL_FUNCTION_DETECT_FALLBACK = 14,
+ GL_DEBUG_CONTROL_FUNCTION_CLAW = 15,
+ GL_DEBUG_CONTROL_FUNCTION_GET_STATISTIC = 16,
+ GL_DEBUG_CONTROL_FUNCTION_DO_QUADRO_SLOWDOWN = 17,
+ GL_DEBUG_CONTROL_FUNCTION_BUFFER_OBJECT = 18,
+ GL_DEBUG_CONTROL_FUNCTION_GET_CAPS = 19,
+ GL_DEBUG_CONTROL_FUNCTION_DO_QUADRO_SLOWDOWN_US = 20,
+ GL_DEBUG_CONTROL_FUNCTION_GET_GENERIC_STATISTIC = 21,
+ GL_DEBUG_CONTROL_FUNCTION_INJECT_RC_ERROR = 22,
+ GL_DEBUG_CONTROL_FUNCTION_FORCE_MEMSTRATEGY = 23,
+ GL_DEBUG_CONTROL_FUNCTION_QUERY_APPDB = 24,
+ GL_DEBUG_CONTROL_FUNCTION_SEND_3D_METHOD = 25,
+ GL_DEBUG_CONTROL_FUNCTION_GL_VERSION_3_2 = 26,
+ GL_DEBUG_CONTROL_FUNCTION_SET_CYCLESTATS_STATE = 27,
+ GL_DEBUG_CONTROL_FUNCTION_WWMP = 28,
+ GL_DEBUG_CONTROL_FUNCTION_SET_STATE_OBJECT_GPU = 29,
+ GL_DEBUG_CONTROL_FUNCTION_NVOGTEST_TEST_START = 30,
+ GL_DEBUG_CONTROL_FUNCTION_DUAL_CORE = 31,
+ GL_DEBUG_CONTROL_FUNCTION_THREADING_OPTIMIZATIONS = 32,
+ GL_DEBUG_CONTROL_FUNCTION_NX6PLUSMODE_FORCE_SYNC = 33,
+ GL_DEBUG_CONTROL_FUNCTION_LOOP_ENHANCE = 34,
+ GL_DEBUG_CONTROL_FUNCTION_APICOGL = 35,
+ GL_DEBUG_CONTROL_FUNCTION_GET_GPU_ADDRESS = 36,
+ GL_DEBUG_CONTROL_FUNCTION_EXTRA_CGC_OPTIONS = 37,
+ GL_DEBUG_CONTROL_FUNCTION_ES2_READ_BUFFER_AUTO_STEREO = 38,
+ GL_DEBUG_CONTROL_FUNCTION_ES2_SET_STEREO_PARAMS = 39,
+ GL_DEBUG_CONTROL_FUNCTION_ES2_DISK_CACHE_ENABLE = 40,
+ GL_DEBUG_CONTROL_FUNCTION_INDEX_REORDERING_CONFIG = 41,
+ GL_DEBUG_CONTROL_FUNCTION_INDEX_REORDERING_STATS = 42,
+} __GLdebugControlFunction;
+
+typedef struct __GLdebugControlIsSupportedRec {
+ __GLdebugControlFunction function; // [IN]
+ GLboolean isSupported; // [OUT]
+} __GLdebugControlIsSupported;
+
+typedef struct __GLdebugControlEvictObjectRec {
+ GLuint objType; // [IN]
+ GLuint id; // [IN]
+} __GLdebugControlEvictObject;
+
+typedef enum {
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_393272 = 1, // memhdrs not locked properly on download/eviction
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_LAYERED_CLEAR_PUSHBUFFER_OVERFLOW = 2,
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_395052 = 3, // xfb falls back when raster disabled
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_399272 = 4, // geometry program output size hardware bug
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_391451 = 5, // xfb can't capture layer
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_389986 = 6, // invalid shader uniform array element being updated
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_393139 = 7, // General Vista fixes, especially multi-threading related
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_412399 = 8, // ZCull GL_NEVER bug.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_369989 = 9, // update internal bindings in PopClientAttribs()
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_424295 = 10, // CopyTexImage path crashed when reading from a source with S8D24 internal buffer but no stencil image bound
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_429286 = 11, // __glGenerateMipmaps copies texture level specification correctly
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_426399 = 12, // ActiveTexture produces GL_INVALID_ENUM, not GL_INVALID_OPERATION for invalid textures
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_431407 = 13, // CopyTexSubImage crashed when the texture was not initialized
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_438799 = 14, // NP2 texture base_level bugs.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_440068 = 15, // AA pbuffers incorrectly swapped
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_441074 = 16, // GetRenderbufferParameteriv returns 0 for STENCIL_SIZE
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_416094 = 17, // corruption in primitive restart
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_462805 = 18, // wrong memspace for PBO texsubimage
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_468172 = 19, // DSA uniform calls crash with invalid program ID
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_469086 = 20, // VBO pulling of an edge flag array crashes
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_MAP_BUFFER_RANGE = 21, // Assorted MBR bugs from first implementation
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_466357 = 22, // UINT variable modifier is supported
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_455345 = 23, // Texture API target mismatch bug (tested by tex_match nvogtest)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_306875 = 24, // Erroneous in-band updates to constant buffers (PaBO)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_480517 = 25, // glMatrixMode returns GL_INVALID_OPERATION when active texture is out of range
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_482923 = 26, // Bufferobject counter normalization bug
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_445457 = 27, // Texture array mipmap generation bug
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_489472 = 28, // Shared VBO data store changes not handled
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_458167 = 29, // Dangling gc->buffers.fbo.zeroObject->dp pointer
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_SHADEBLO_GLSL = 30, // ShadeBLo GLSL support, developed after the extension string was added
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_491100 = 31, // Failing to download missing mip levels when BASE_LEVEL is changed
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_VBUM_CLIENTATTRIB = 32, // Interaction between VBUM and ClientAttribDefault
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_505040 = 33, // Interop counters cleanup
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_502904 = 34, // EXT_texture_swizzle interaction with sRGB
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_502904_VTG = 35, // Vertex/Tess/Geometry program EXT_texture_swizzle interaction with sRGB
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_TEX_MAXSIZE_BDR = 36, // cubemap and array textures don't handle border properly
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_489261 = 37, // Unbind a VBO from a VAO
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_430878 = 38, // Fall out of SFR for a 3D blit
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_MODS_CLIPID_TEST = 39, // driver has a MODS hack to force the use of clip IDs for basic functional testing (GL_DEBUG_CONTROL_ENABLE_MODS_CLIPID_TEST)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_505040_2 = 40, // changes for state machine of VBO memory allocation strategy (state_init)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_505040_3 = 41, // changes for state machine of VBO memory allocation strategy (state_vid)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_LOD_FP_ONLY = 42, // Only allow the LOD instruction in fragment programs
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_522575 = 43, // Keep track of lockedCount in the mutex table for GL_DEBUG_CONTROL_GET_GENERIC_STATISTIC_MUTEX_WORD
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_515687 = 44, // ARB_texture_rg: GL_RED should be legal GL_DEPTH_TEXTURE_MODE
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_EXPMS_VCAA = 45, // VCAA depth surface can now be fetch by explicit_multisample
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_VBUM_MBR = 46, // MapBufferRange orphan+discard doesn't work with vbum/shadeblo
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_MAPPED_BUFFER_CRASH = 47, // Deleting a context while a buffer is mapped will crash
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_MAPPED_BUFFER_CRASH_NV4X = 48, // Deleting a context while a buffer is mapped will crash (on NV4X)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_NULL_COMPRESSED_TEXIMG = 49, // Allow NULL for glCompressedTexImage*D
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_SHADER_SUBROUTINE_CHANGE = 50, // Change to NV_shader_subroutine API
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_DSA_TOKENHELPER_BUG_560077 = 51,
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_571236 = 52, // Interactions of dualcore, client-state, and deprecation
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_578086 = 53, // Fixes for max attrib fragment programs
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_SEAMLESS_CUBEMAP = 54, // seamless cubemap enum changed
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_GL32_MAX_COMPONENTS_QUERIES = 55, // driver implements new GL3.2 MAX_*_COMPONENTS queries
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_GL32_GETBUFFERPARAMETERI64V = 56, // driver implements missing 64b buffer parameter query
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_576302 = 57,
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_LOADIM_MULTISAMPLE_TEX = 58, // image_load_store converted to use GL3.2 multisample texture syntax
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_VOTE_IMPLEMENTED = 59, // does NV_gpu_program5 code include support for TGALL/TGANY/TGEQ?
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_424330 = 60,
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_ALPHA_CB_FIX = 61, // Set alpha circular buffer size for gf10y
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_GETINTEGER64I_V = 62, // glGetInteger64i_v is present.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_2DMSARRAY_RENAMED = 63, // Assembly token 2DMSARRAY has been renamed to ARRAY2DMS
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_607673 = 64, // Assembler properly rejects POPA with a CC mask
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_599222 = 65, // Disabled vbo slots are still remembered across context switches.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_TEXBO_GETTEXLEVELPARAM = 66, // Support gettexlevelparameter on buffer textures
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_618201 = 67, // Subsequent VBO ArrayElement calls with different enables cause crash
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_INT64_DIV_MOD = 68, // Supports 64 bit integer DIV and MOD instructions
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_635764 = 69, // Draw without attrib 0 enabled
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_PIXELPATH_PACKED_PIXELS = 71, // support for packed pixel types in the pixel path, part of ARB_texture_rgb10_a2ui
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BEGINQUERYINDEXED = 72, // XFB3 change from using separate query targets to using indexed query targets
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_INDEXED_TXWAR = 73, // Support texture format WAR on indexed texture
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_SHADER_SUBROUTINE_CHANGE2 = 74,// Further shader subroutine changes
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_FRAGMENT_SMID = 75, // Supports the "fragment.smid" binding for MODS (bug 663067).
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BIND_SAMPLER_UINT = 76, // ARB_sampler_objects' BindSampler implementation accepts a uint (bug 668718).
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_MISC_GL33_GL40_FIXES = 77, // Contains fixes for miscellaneous OpenGL 3.3/4.0 impl. bugs
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_663779 = 78, // Support IPA instruction on FPOS attribute
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_368610 = 79, // Sharing FBOs between display connections and closing owning connection
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_674780 = 80, // Driver does not crash when given negative values for sampler texture indices
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_681447 = 81, // glGetIntegerv() support for GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_SUBROUTINE_QUERY_CRASH = 82, // querying information about compatible subroutines from an unbound program crashes
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_IPA_FOGCOORD = 83, // Support IPA instruction on fogcoord
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_710489 = 84, // DSA + VAO fixes, mostly for glGetVertexArrayIntegeri_vEXT
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_PPO_FIXES = 85, // Deleting a bound user pipeline updates properly and bindprogrampipeline updates active programs
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_676759 = 86, // Linker fixes for uniform arrays with 64-bit components.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_741073 = 87, // Linker handles Cg bug in handling matrix uniform arrays where only the last element is used.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_664244 = 88, // Problems with arrays of GLSL subroutine uniforms, crashes on R256 x64
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_744350 = 89, // Problems with FL-predicated subroutine calls
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_751609 = 90, // Crash can occur when doing too many CE operations back-to-back.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_728033 = 91, // New format support for cuda interop has been added to R270 and above.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_762723 = 92, // UBO only allows 12 bindings
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_763409 = 93, // Supports DX11 - OGL interop, R270 and above.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_747891 = 94, // Errors during GLX context creation can cause a hang without this fix.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_758921 = 95, // ClientAttribDefault resets the primitive restart state.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_762974 = 96, // Bad interaction of UBO and EXT_bindable_uniform in the same program.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_779707 = 97, // BPTC textures don't require CompressedSubImage3D on 4 block boundaries
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_746642 = 98, // Addresses returned by VBUM are made virtual to allow modeswitching with XP
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_790472 = 99, // Querying GLSL uniform array names returns "foo[0]" and UBO uniforms return locations of -1
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_792522 = 100, // Fix issue with aa downsample of fbo with mixed dimensions attachments
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_796862 = 101, // Context creation of version 1.0 should result in latest OpenGL version
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_625498 = 102, // Fix dual-core issue with glCallLists (see dlist_hell nvogtest)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_809142 = 103, // Incorrect restore of the program binary refcount causes memory leak
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_800902 = 104, // X crashes when making current to GLX window whose X window is gone
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_362397 = 105, // DivByZero expection when a Buffer attached to a texbo is resized to less than 1px.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_826092 = 106, // GL_ARB_pixel_buffer_object: check if GL errors are correctly set
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_822935 = 107, // LoopEnhance nvogtest support
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_857702 = 108, // driver good enough to handle glsl_ils_fmt* tests
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_845118 = 109, // Need to look at read drawable during read fbo validation
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_856656 = 110, // no known compiler exceptions on glsl_ils_misc* (can run test)
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_852161 = 111, // glMaterial doesn't update GLSL material built-in inside dlist
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_860989 = 112, // program tracking bits not updated by glPopAttrib
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_870498 = 113, // If drawbuffer settings do not match FBO attachment causes a crash
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_876641 = 114, // crash binding the same FBO to two threads simultaneously
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_879671 = 115, // drawElementsInstanced might crash if we copy not enabled vertex data
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_906242 = 116, // glFramebufferTexture and friends are not setting a GL error when the <texture> argument is zero
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_909200 = 117, // assembly CBUFFER and BUFFER4 arrays are sized with correct units
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_918415 = 118, // glMakeBufferNonResidentNV doesn't ensure the buffer is resident before doing its business
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_874617 = 119, // Fix for use-after-delete using FBO
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_920825 = 120, // Fix crash on calling glReadPixels with invalid parameters
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_930245 = 121, // Fix crash on calling glGetBufferPointervOES if buffer object name 0 is bound to target
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_930248 = 122, // Fix crash on glCopyTexSubImage3DOES when x or y is negative value
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_930253 = 123, // Fix crash on glDrawBuffersNV when <bufs> is NULL
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_930290 = 124, // call to glEGLImageTargetTexture2DOES when texture target is 0 excutes without error
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_934987 = 125, // Properly round non-antialiased line widths
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_874933 = 126, // LDDM non-CUDA-interop buffers allocated within CUDA reserved address range
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_936396 = 127, // Linux: Damage events are not generated on parents of GL drawables when GL drawable is created after the Damage object
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_882002 = 128, // Fix mip-mapped compressed NPOT texture's edges
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_937411 = 129, // Fix issues with drawElementeInstanced path and usage of vertex attrib divisor
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_940255 = 130, // Fix crash on querying EGL_STEREO_LAYOUT_NVX surface attribute value using eglQuerySurface
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_945327 = 131, // Fixed MT event and thread handle leaks
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_IS_OBJECT = 132, // The IsObject routines behave correct in that they return FALSE until first bind
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_953084 = 133, // Fix texture completeness check for EGLImage creation
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_960878 = 134, // NV_path_rendering is broken when programmable shaders are in use
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_874652 = 135, // [Cg/AR20] Illegit shader compiles without error: Illegit unreferenced function does not fail to compile
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_952196 = 136, // [Cg/AR20] Assert in vertex shader compilation when same attribute is assigned to multiple varyings
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_968228 = 137, // Default state for UNIFORM_BUFFER_{START,SIZE} is fixed to 0, instead of original -1.
+ GL_DEBUG_CONTROL_GET_BUGFIX_PRESENT_BUG_968768 = 138, // Early Z logic is broken for stencil func GL_NEVER
+} __GLdebugControlGetBugfixPresentEnum;
+
+typedef struct __GLdebugControlGetBugfixPresentRec {
+ __GLdebugControlGetBugfixPresentEnum bugfix; // [IN]
+ GLboolean isSupported; // [OUT]
+} __GLdebugControlGetBugfixPresent;
+
+typedef enum {
+ GL_DEBUG_CONTROL_ENABLE_AGGRESSIVE_EVICTION = 1,
+ GL_DEBUG_CONTROL_ENABLE_MODS_CLIPID_TEST = 2,
+ GL_DEBUG_CONTROL_ENABLE_WSPERF_PUSH = 3,
+ GL_DEBUG_CONTROL_ENABLE_WSPERF_POP = 4,
+ GL_DEBUG_CONTROL_ENABLE_WSPERF_REINIT_GC = 5, // Required before changes take affect
+ GL_DEBUG_CONTROL_ENABLE_WS_VARRAY = 6,
+ GL_DEBUG_CONTROL_ENABLE_SDDR = 7,
+ GL_DEBUG_CONTROL_ENABLE_SDSR = 8,
+ GL_DEBUG_CONTROL_ENABLE_LAZY_VBUM = 9,
+ GL_DEBUG_CONTROL_ENABLE_LOOP_ENHANCE = 10,
+ GL_DEBUG_CONTROL_ENABLE_VAB_IMMEDIATE_MODE = 11,
+ GL_DEBUG_CONTROL_ENABLE_VAB_VERTEXARRAY = 12,
+ GL_DEBUG_CONTROL_ENABLE_CLAW = 13,
+} __GLdebugControlEnableEnum;
+
+// may return an error if the enable isn't supported
+typedef struct __GLdebugControlEnablesRec {
+ __GLdebugControlEnableEnum cap; // [IN]
+ GLboolean enable; // [IN]
+ GLboolean success; // [OUT]
+} __GLdebugControlEnables;
+
+typedef enum {
+ GL_DEBUG_CONTROL_DETECT_FALLBACK_SOFTWARE_VALIDATE = 1,
+} __GLdebugControlDetectFallbackType;
+
+typedef struct __GLdebugControlDetectFallbackRec {
+ // If a fallback of the specified type has occurred since the last reset,
+ // this operation returns GL_TRUE in <result>. If <reset> is GL_TRUE, the
+ // fallback flag will be reset.
+ __GLdebugControlDetectFallbackType type; // [IN]
+ GLboolean reset; // [IN]
+ GLboolean result; // [OUT]
+} __GLdebugControlDetectFallback;
+
+typedef enum {
+ GL_DEBUG_CONTROL_DUAL_CORE_CMD_CHECK_POSSIBLE = 1,
+ GL_DEBUG_CONTROL_DUAL_CORE_CMD_CURRENT_MODE,
+ GL_DEBUG_CONTROL_DUAL_CORE_CMD_ENTER,
+ GL_DEBUG_CONTROL_DUAL_CORE_CMD_LEAVE
+} __GLdebugControlDualCoreCmd;
+
+typedef struct __GLdebugControlDualCoreRec {
+ int size; // [IN] size of this struct; the cmd is ignored if there is a size mismatch
+ __GLdebugControlDualCoreCmd cmd; // [IN]
+ GLint arg1; // [IN]
+ GLint result; // [OUT]
+ GLint success; // [OUT]
+} __GLdebugControlDualCore;
+
+
+typedef enum {
+ GL_DEBUG_CONTROL_LE_INIT,
+ GL_DEBUG_CONTROL_LE_GET_LOOP,
+ GL_DEBUG_CONTROL_LE_CHECK_LOOP,
+ GL_DEBUG_CONTROL_LE_RESET_LOOP,
+ GL_DEBUG_CONTROL_LE_DESTROY
+} __GLdebugControlLEcmd;
+
+typedef enum {
+ GL_DEBUG_CONTROL_LE_SUCCESS,
+ GL_DEBUG_CONTROL_LE_LOOP_REPLACED,
+ GL_DEBUG_CONTROL_LE_NO_MORE_AVAILABLE, // indicates no more loops or applicatiosns available
+ GL_DEBUG_CONTROL_LE_FAIL,
+ GL_DEBUG_CONTROL_LE_FAIL_DUE_TO_OGL32,
+ GL_DEBUG_CONTROL_LE_FAIL_STRUCT_MISMATCH,
+} __GLdebugControlLEreturnCodes;
+
+
+typedef struct __GLdebugControlLERec {
+ __GLdebugControlLEcmd cmd; // [IN]
+ int structSize; // [IN]
+ __GLdebugControlLEreturnCodes result; // [OUT]
+ union {
+ struct {
+ int appNumber; // [IN]
+ } init;
+ struct {
+ int loopNumber; // [IN]
+ void *pFunction; // [OUT]
+ GLboolean color; // [OUT]
+ GLboolean texture; // [OUT]
+ GLboolean index; // [OUT]
+ } getLoop;
+ } u;
+} __GLdebugControlLE;
+
+
+typedef struct __GLdebugControlApicOglRec {
+ void (*callbackProcDrawArrays)(void* basePtr, const GLint *first, const GLsizei *count, GLsizei primcount); // [IN]
+} __GLdebugControlApicOgl;
+
+typedef enum {
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_DISABLE_ALL = 1,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_GET_GLSL_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_SET_GLSL_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_GET_VIEWPORT_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_SET_VIEWPORT_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_GET_MATRIX_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_SET_MATRIX_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_GET_GLSTATE_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_SET_GLSTATE_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_GET_FB_STATUS_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_SET_FB_STATUS_CACHE,
+ GL_DEBUG_CONTROL_THREADING_OPT_CMD_ENABLE_ALL = 0x0000FFFF,
+} __GLdebugControlThreadingOptimizationsCmd;
+
+typedef struct __GLdebugControlThreadingOptimizationsRec {
+ int size; // [IN] size of this struct; the cmd is ignored if there is a size mismatch
+ __GLdebugControlThreadingOptimizationsCmd cmd; // [IN]
+ GLint arg1; // [IN]
+ GLint result; // [OUT]
+ GLint success; // [OUT]
+} __GLdebugControlThreadingOptimizations;
+
+typedef enum {
+ GL_DEBUG_CONTROL_CLAW_CMD_RESET = 1,
+ GL_DEBUG_CONTROL_CLAW_CMD_GET_ENABLES,
+ GL_DEBUG_CONTROL_CLAW_CMD_SET_ENABLES_AND_RESET,
+ GL_DEBUG_CONTROL_CLAW_CMD_DISALLOW,
+ GL_DEBUG_CONTROL_CLAW_CMD_SET_OVERRIDE_ENABLES_AND_RESET,
+} __GLdebugControlClawCmd;
+
+typedef struct __GLdebugControlClawRec {
+ int size; // [IN] size of this struct; the cmd is ignored if there is a size mismatch
+ __GLdebugControlClawCmd cmd; // [IN]
+ GLint arg1; // [IN]
+ GLint result; // [OUT]
+ GLint error; // [OUT]
+} __GLdebugControlClaw;
+
+typedef enum {
+ // nvogtest test tagging
+ GL_DEBUG_CONTROL_GET_GENERIC_STATISTIC_TAG_TEST = 0,
+ GL_DEBUG_CONTROL_GET_GENERIC_STATISTIC_MUTEX_WORD = 1,
+} __GLdebugControlGetGenericStatisticType;
+
+typedef struct __GLdebugControlGetGenericStatisticRec {
+ // If a fallback of the specified type has occurred since the last reset,
+ // this operation returns GL_TRUE in <result>. If <reset> is GL_TRUE, the
+ // fallback flag will be reset. If the driver understands the type, <success>
+ // will be set to GL_TRUE, GL_FALSE otherwise.
+ __GLdebugControlGetGenericStatisticType type; // [IN]
+ GLboolean reset; // [IN]
+ GLboolean success; // [OUT]
+ unsigned int result; // [OUT]
+} __GLdebugControlGetGenericStatistic;
+
+typedef enum {
+ // for blits (copypixels, drawpixels, readpixels, pbo teximage, copyteximage),
+ // report which path performed the blit. Also count number of shaders
+ // replaced, and fragment shaders that use constant color rendering.
+ GL_DEBUG_CONTROL_GET_STATISTIC_BLIT_2D = 1,
+ GL_DEBUG_CONTROL_GET_STATISTIC_BLIT_3D = 2,
+ GL_DEBUG_CONTROL_GET_STATISTIC_BLIT_CE = 3,
+ GL_DEBUG_CONTROL_GET_STATISTIC_BLIT_M2M = 4,
+ GL_DEBUG_CONTROL_GET_STATISTIC_SHADER_REPLACEMENT = 5,
+ GL_DEBUG_CONTROL_GET_STATISTIC_CONSTANT_COLOR_RENDERING = 6,
+ GL_DEBUG_CONTROL_GET_STATISTIC_BLIT_3D_PFM = 7, // PixelsFromMemory in 3D class (GK20A+)
+} __GLdebugControlGetStatisticType;
+
+typedef struct __GLdebugControlGetStatisticRec {
+ // If a fallback of the specified type has occurred since the last reset,
+ // this operation returns GL_TRUE in <result>. If <reset> is GL_TRUE, the
+ // fallback flag will be reset.
+ __GLdebugControlGetStatisticType type; // [IN]
+ GLboolean reset; // [IN]
+ unsigned int result; // [OUT]
+} __GLdebugControlGetStatistic;
+
+typedef struct __GLdebugControlDoQuadroSlowdownRec {
+ // Activates a test which will hang if the card is a GeForce.
+ // when used with GL_DEBUG_CONTROL_FUNCTION_DO_QUADRO_SLOWDOWN_US, value used as microseconds
+ // when used with GL_DEBUG_CONTROL_FUNCTION_DO_QUADRO_SLOWDOWN, value used as clock ticks
+ unsigned int value; // [IN]
+} __GLdebugControlDoQuadroSlowdown;
+
+typedef enum {
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_INIT,
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_STREAM_VID,
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_STREAM_SYSHEAP,
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_MAP_FOR_READ,
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_FALLBACK,
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_MIGHT_STALL,
+ __GL_DEBUG_CONTROL_BUFFER_OBJECT_STATE_INTEROP
+} __GLdebugControlBufferObjectState;
+
+typedef enum {
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_GPU_READ_VTX = 0,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_GPU_READ_INDEX,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_GPU_READ_BLIT,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_CPU_READ,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_CPU_WRITE,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_GPU_WRITE_BLIT,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_USER_MAP_AS_UPDATE,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_USER_MAP_AS_READ,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_SYNC_UPDATE_STALL,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_GPU_WRITE_BLIT_NONCOHERENT,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_GPU_HIGH_PRIORITY,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_INTEROP_VIDMEM,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_INTEROP_SYSMEM,
+ __GL_DEBUG_CONTROL_BUFFER_COUNTER_COUNT
+} __GLdebugControlBufferCounter;
+
+typedef enum {
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_INVALID = 0,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_MALLOC,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_SYSHEAP,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_DMA_CACHED,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_DMA_CACHED_NONCOHERENT,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_VID_ONLY,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_VID_PLUS_MALLOC,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_VID_PLUS_SYSHEAP,
+
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_ANY_GPU_PREFER_SYSHEAP,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_ANY_GPU_PREFER_VID,
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_ANY_GPU_PREFER_CACHED,
+
+ __GL_DEBUG_CONTROL_BUFFER_ALLOC_STRATEGY_COUNT,
+} __GLdebugControlBufferAllocStrategy;
+
+typedef enum {
+ GL_DEBUG_CONTROL_BUFFER_OBJECT_SET_STALLING = 1,
+ GL_DEBUG_CONTROL_BUFFER_OBJECT_GET_STATE = 2,
+ GL_DEBUG_CONTROL_BUFFER_OBJECT_HIDE_STALLING = 3,
+ GL_DEBUG_CONTROL_BUFFER_OBJECT_TAP_COUNTER = 4,
+ GL_DEBUG_CONTROL_BUFFER_OBJECT_SET_COUNTER = 5,
+} __GLdebugControlBufferObjectCmd;
+
+typedef struct __GLdebugControlBufferObjectRec {
+ __GLdebugControlBufferObjectCmd cmd; // [IN]
+ unsigned int bit; // [IN]
+ unsigned int inc; // [IN]
+ GLenum target; // [IN]
+ GLboolean hideStalling; // [IN]
+ unsigned int state; // [OUT]
+} __GLdebugControlBufferObject;
+
+typedef enum {
+ GL_DEBUG_CONTROL_INDEX_REORDERING_CONFIG_READ,
+ GL_DEBUG_CONTROL_INDEX_REORDERING_CONFIG_WRITE,
+} __GLdebugControlIndexReorderingConfigCmd;
+
+typedef struct __GLdebugControlIndexReorderingConfigRec {
+ __GLdebugControlIndexReorderingConfigCmd cmd; // [IN]
+ unsigned int enabled;
+ unsigned int minHitCnt;
+ unsigned int minIndCnt;
+ unsigned int synchronous;
+ unsigned int subranges;
+ float margin;
+ float thresholdACMR;
+ unsigned int ignoreThreshold; //Mostly for testing
+ unsigned int forceReorder; //Mostly for testing
+ unsigned int postTransformCacheSize;
+ unsigned int cacheModel;
+} __GLdebugControlIndexReorderingConfig;
+
+typedef struct __GLdebugControlIndexReorderingStatsRec {
+ unsigned int count;
+} __GLdebugControlIndexReorderingStats;
+
+typedef enum {
+ // Capability types to be returned by GL_DEBUG_CONTROL_FUNCTION_GET_CAPS.
+ // The type of <result> depends on the requested capability. The comment
+ // after the type specifies the return type.
+ GL_DEBUG_CONTROL_GET_CAPS_IS_QUADRO = 1, // Out Type: GLboolean
+ GL_DEBUG_CONTROL_GET_CAPS_IS_FORCED_SYSMEM = 2, // Out Type: GLboolean
+ GL_DEBUG_CONTROL_GET_CAPS_HAS_SHADOW_MAPPING_BUG_280195 = 3, // Out Type: GLboolean
+
+ GL_DEBUG_CONTROL_GET_CAPS_HAS_INDEX_LIMIT = 4, // Out Type: GLboolean
+} __GLdebugControlGetCapsType;
+
+typedef struct __GLdebugControlGetCapsRec {
+ // Returns internal data directly from the driver. <success> is set to
+ // GL_TRUE if the operation was successful.
+ // The type of <result> depends upon the capability that is requested.
+ __GLdebugControlGetCapsType type; // [IN]
+ GLboolean success; // [OUT]
+ void* result; // [OUT]
+} __GLdebugControlGetCaps;
+
+typedef enum {
+ GL_DEBUG_CONTROL_INJECT_RC_ERROR_PARSE_ERROR,
+ GL_DEBUG_CONTROL_INJECT_RC_ERROR_DATA_ERROR,
+} __GLdebugControlInjectRcErrorType;
+
+typedef struct __GLdebugControlInjectRcErrorRec {
+ __GLdebugControlInjectRcErrorType type; // [IN]
+ GLboolean success; // [OUT]
+} __GLdebugControlInjectRcError;
+
+typedef struct __GLdebugControlQueryAppdbRec {
+ GLuint *size; // [IN / OUT]
+ GLchar *data; // [OUT, optional]
+} __GLdebugControlQueryAppdb;
+
+// Sends a 3D subchannel method
+// **DO NOT CALL IN CHECKED IN TESTS**
+typedef struct __GLdebugControlSend3DMethod {
+ GLuint method; // [IN]
+ GLuint data; // [IN]
+} __GLdebugControlSend3DMethod;
+
+typedef struct __GLdebugControlSetCycleStatsState {
+ GLuint stateIndex; // [IN]
+ GLuint stateValue; // [IN]
+} __GLdebugControlSetCycleStatsState;
+
+typedef enum {
+ GL_DEBUG_CONTROL_WWMP_INSTALL_SIGNAL_HANDLER,
+ GL_DEBUG_CONTROL_WWMP_ADD_WRITE_WATCH,
+ GL_DEBUG_CONTROL_WWMP_DISABLE,
+ GL_DEBUG_CONTROL_WWMP_GET_STATE,
+} __GLdebugControlWWMPCmd;
+
+typedef struct __GLdebugControlWWMPRec {
+ __GLdebugControlWWMPCmd cmd; // [IN]
+ union {
+ struct {
+ GLboolean result; // [OUT]
+ void* trackAdr; // [IN]
+ volatile GLintptr **watchAdr; // [OUT]
+ volatile GLintptr *watchValue; // [OUT]
+ void** trackDat; // [OUT]
+ GLboolean *isTracked; // [OUT]
+ } addWriteWatch;
+ struct {
+ GLboolean enabled; // [OUT]
+ int sigactionPending; // [OUT]
+ int sigactionInitialized; // [OUT]
+ }getState;
+ } u;
+} __GLdebugControlWWMP;
+
+typedef struct __GLdebugControlSetStateObjectGPURec {
+ GLuint64EXT handle; // [IN]
+ GLint dynamiccount; // [IN]
+ const GLvoid *dynamicprops; // [IN]
+} __GLdebugControlSetStateObjectGPU;
+
+typedef enum {
+ GL_DEBUG_CONTROL_GET_GPU_ADDRESS_BUFFER_OBJECT = 0,
+} __GLdebugControlGetGPUAddressObjectType;
+
+typedef struct __GLdebugControlGetGPUAddressRec {
+ __GLdebugControlGetGPUAddressObjectType objectType; // [IN]
+ GLenum target; // [IN]
+ GLboolean success; // [OUT]
+ GLuint64EXT address; // [OUT]
+ GLuint64EXT size; // [OUT]
+} __GLdebugControlGetGPUAddress;
+
+typedef struct __GLdebugControlExtraCgcOptionsRec {
+ GLuint argc; // [IN]
+ GLchar **argv; // [IN]
+ GLboolean success; // [OUT]
+} __GLdebugControlExtraCgcOptions;
+
+typedef struct __GLdebugControlNvogtestTestStartRec {
+ GLboolean dcWasRestored; // [OUT]
+} __GLdebugControlNvogtestTestStart;
+
+typedef enum {
+ GL_DEBUG_CONTROL_ES2_LEFT_EYE,
+ GL_DEBUG_CONTROL_ES2_RIGHT_EYE,
+} __GLdebugControlES2StereoEye;
+
+typedef struct __GLdebugControlES2ReadBufferAutoStereoRec {
+ GLuint eye; // [IN]
+ GLenum mode; // [IN]
+} __GLdebugControlES2ReadBufferAutoStereo;
+
+typedef struct __GLdebugControlES2SetStereoParamsRec {
+ GLuint control; // 0 => Stereo Disabled, else Enabled
+ GLuint method; // NvGlStereoMethod
+ GLuint changeSep;
+ float separation;
+ float convergence;
+ float cutoff;
+ float cutoffDir;
+ GLuint screenWidth;
+} __GLdebugControlES2SetStereoParams;
+
+typedef struct __GLdebugControlES2DiskCacheCtrl {
+ GLboolean enable;
+ GLuint numEntries;
+ GLuint numHits;
+ GLboolean deleteCachedFiles;
+ GLboolean blobEnable;
+ GLuint numBlobEntries;
+ GLuint numBlobHits;
+} __GLdebugControlES2DiskCacheCtrl;
+
+struct __GLdebugControlParametersRec
+{
+ __GLdebugControlFunction function;
+
+ // Note: This union is only aligned to 4B. Adding a member with a uint64 in it
+ // will cause it to be aligned to 8B and break compatibility.
+ union
+ {
+ __GLdebugControlIsSupported isSupported;
+ __GLdebugControlEvictObject evictObject;
+ __GLdebugControlGetBugfixPresent getBugfixPresent;
+ __GLdebugControlEnables enables;
+ __GLdebugControlDetectFallback detectFallback;
+ __GLdebugControlClaw claw;
+ __GLdebugControlGetGenericStatistic getGenericStatistic;
+ __GLdebugControlGetStatistic getStatistic;
+ __GLdebugControlDoQuadroSlowdown slowdown;
+ __GLdebugControlBufferObject bufObject;
+ __GLdebugControlGetCaps getCaps;
+ __GLdebugControlInjectRcError injectRcError;
+ __GLdebugControlQueryAppdb queryAppdb;
+ __GLdebugControlSend3DMethod send3DMethod;
+ __GLdebugControlSetCycleStatsState setCycleStatsState;
+ __GLdebugControlWWMP wwmp;
+ // Add new entries to u2 instead of u.
+ } u;
+
+ // This union is 8B-aligned.
+ union
+ {
+ GLuint64EXT x; // force 8B alignment.
+ __GLdebugControlSetStateObjectGPU setStateObjectGPU;
+ __GLdebugControlThreadingOptimizations threadOptimizations;
+ __GLdebugControlDualCore dualCore;
+ __GLdebugControlLE loopEnhance;
+ __GLdebugControlApicOgl apicOgl;
+ __GLdebugControlGetGPUAddress getGPUAddress;
+ __GLdebugControlExtraCgcOptions extraCgcOptions;
+ __GLdebugControlNvogtestTestStart nvogtestTestStart;
+ __GLdebugControlES2ReadBufferAutoStereo readBufferAutoStereo;
+ __GLdebugControlES2SetStereoParams setStereoParams;
+ __GLdebugControlES2DiskCacheCtrl diskCacheCtrl;
+ __GLdebugControlIndexReorderingConfig ibrCfg;
+ __GLdebugControlIndexReorderingStats ibrStats;
+ } u2;
+};
+
+
+// All implementations that export this entrypoint support the function
+// IS_SUPPORTED. Whether or not other functions are supported is
+// implementation defined.
+//
+// The correct usage is as follows. Let's say you want to use the function
+// EVICT_OBJECT:
+//
+// 1) glDebugControlNVX( {IS_SUPPORTED, EVICT_OBJECT, &result} );
+// 2) stop if result is FALSE
+// 3) glDebugControlNVX( {EVICT_OBJECT, objType, id} );
+//
+#define PROC_DebugControlNVX gl6813513874685413
+
+
+// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// The remainder of this file is the legacy interface. It is still used by
+// nvogtest and nvapi. Eventually uses of the old interface will be ported to
+// the new interface, at which time the old interface will be removed.
+//
+// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+// bump this every time you change the list of recognized <pname> values.
+#define __NVOGLDEBUG_ENUM_VERSION 3
+
+// The following values may be passed as <pname> to
+// __NvOglDebugSeti and __NvOglDebugGeti.
+//
+// __NVOGLDEBUG_USER_1 and __NVOGLDEBUG_USER_2 should never be used in
+// checked-in code. Their purpose is for quick hacks while debugging or
+// developing new code. By including them here a priori, an engineer can
+// quickly use them without modifying a key .h file that causes recompilation
+// of the world.
+//
+// __NVOGLDEBUG_NVTRACE_LEVEL refers to the nvTraceLevel.
+//
+#define __NVOGLDEBUG_USER_1 0x8C50
+#define __NVOGLDEBUG_USER_2 0x8C51
+#define __NVOGLDEBUG_NVTRACE_LEVEL 0x8C52
+#define __NVOGLDEBUG_NVTRACE_OPTIONS 0x8C53
+#define __NVOGLDEBUG_VERSION 0x8C54
+#define __NVOGLDEBUG_TAG_TEST 0x8C55
+
+#define __NVOGLDEBUG_NVEXPERT_LEVEL 0x8C56
+#define __NVOGLDEBUG_NVEXPERT_CALLBACK 0x8C57
+#define __NVOGLDEBUG_NVEXPERT_MASK0 0x8C58
+
+#define __NVOGLDEBUG_TEMP0 0x8C59
+#define __NVOGLDEBUG_TEMP1 0x8C5A
+#define __NVOGLDEBUG_TEMP2 0x8C5B
+#define __NVOGLDEBUG_TEMP3 0x8C5C
+#define __NVOGLDEBUG_TEMP4 0x8C5D
+#define __NVOGLDEBUG_INSTRUMENTATION_ENABLED 0x8C5E
+#define __NVOGLDEBUG_OPTIONS 0x8C5F
+
+#define __NVOGLDEBUG_NVTRACE_MASK0 0x8C60
+#define __NVOGLDEBUG_NVTRACE_MASK1 0x8C61
+#define __NVOGLDEBUG_NVTRACE_MASK2 0x8C62
+#define __NVOGLDEBUG_NVTRACE_MASK3 0x8C63
+#define __NVOGLDEBUG_NVTRACE_MASK4 0x8C64
+#define __NVOGLDEBUG_NVTRACE_MASK5 0x8C65
+#define __NVOGLDEBUG_NVTRACE_MASK6 0x8C66
+#define __NVOGLDEBUG_NVTRACE_MASK7 0x8C67
+#define __NVOGLDEBUG_NVTRACE_MASK8 0x8C68
+#define __NVOGLDEBUG_NVTRACE_MASK9 0x8C69
+#define __NVOGLDEBUG_NVTRACE_MASK10 0x8C6A
+#define __NVOGLDEBUG_NVTRACE_MASK11 0x8C6B
+#define __NVOGLDEBUG_NVTRACE_MASK12 0x8C6C
+#define __NVOGLDEBUG_NVTRACE_MASK13 0x8C6D
+#define __NVOGLDEBUG_NVTRACE_MASK14 0x8C6E
+#define __NVOGLDEBUG_NVTRACE_MASK15 0x8C6F
+
+
+// Used to set the value of a debug variable. Returns the old value.
+// XXX deprecated, do not use
+int GLAPIENTRY __NvOglDebugSeti (unsigned int pname, int param);
+typedef int (GLAPIENTRY * PFN__NVOGLDEBUGSETIPROC) (unsigned int pname, int param);
+
+// Used to get the value of a debug variable.
+// XXX deprecated, do not use
+int GLAPIENTRY __NvOglDebugGeti (unsigned int pname);
+typedef int (GLAPIENTRY * PFN__NVOGLDEBUGGETIPROC) (unsigned int pname);
+
+// Used to set the value of a debug variable. Returns the old value.
+// XXX deprecated, do not use
+void* GLAPIENTRY __NvOglDebugSetv (unsigned int pname, void* param);
+typedef void* (GLAPIENTRY * PFN__NVOGLDEBUGSETVPROC) (unsigned int pname, void* param);
+
+// Used to get the value of a debug variable.
+// XXX deprecated, do not use
+void* GLAPIENTRY __NvOglDebugGetv (unsigned int pname);
+typedef void* (GLAPIENTRY * PFN__NVOGLDEBUGGETVPROC) (unsigned int pname);
+
+// keep this in sync with the ogl driver!!!
+#define OGL_PERF_STRAT_CLAW_ENABLED 0x00000001
+#define OGL_PERF_STRAT_CLAW_IGNORE_TRASH 0x00000040
+#define OGL_PERF_STRAT_CLAW_FORCE_EXECUTE_BLOCK 0x00000200
+#define OGL_PERF_STRAT_CLAW_FORCE_EXECUTE_PIKACHOU 0x00000400
+#define OGL_PERF_STRAT_CLAW_PIXEL_ACCURATE 0x00008000
+
+#if defined(QT3DS_MACINTOSH_OSX)
+
+// Used to emulate the debug control API via gldSetInteger. Values of 5000 or greater
+// are reserved for internal driver use.
+enum GLDVendorIntegerParameter
+{
+ GLD_NVIDIA_DEBUG_CONTROL = 5000,
+};
+
+#endif
+
+#endif
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglew.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglew.h
new file mode 100644
index 00000000..05f054fc
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglew.h
@@ -0,0 +1,1363 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+** Copyright (c) 2007 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+#ifndef __wglew_h__
+#define __wglew_h__
+#define __WGLEW_H__
+
+#ifdef __wglext_h_
+#error wglext.h included before wglew.h
+#endif
+
+#define __wglext_h_
+
+#if !defined(WINAPI)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+#include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+#endif
+
+/*
+ * GLEW_STATIC needs to be set when using the static version.
+ * GLEW_BUILD is set when building the DLL version.
+ */
+#ifdef GLEW_STATIC
+# define GLEWAPI extern
+#else
+# ifdef GLEW_BUILD
+# define GLEWAPI extern __declspec(dllexport)
+# else
+# define GLEWAPI extern __declspec(dllimport)
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------- WGL_3DFX_multisample ------------------------- */
+
+#ifndef WGL_3DFX_multisample
+#define WGL_3DFX_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_3DFX 0x2060
+#define WGL_SAMPLES_3DFX 0x2061
+
+#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample)
+
+#endif /* WGL_3DFX_multisample */
+
+/* ------------------------- WGL_3DL_stereo_control ------------------------ */
+
+#ifndef WGL_3DL_stereo_control
+#define WGL_3DL_stereo_control 1
+
+#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055
+#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056
+#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057
+#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058
+
+typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState);
+
+#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL)
+
+#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control)
+
+#endif /* WGL_3DL_stereo_control */
+
+/* ------------------------ WGL_AMD_gpu_association ------------------------ */
+
+#ifndef WGL_AMD_gpu_association
+#define WGL_AMD_gpu_association 1
+
+#define WGL_GPU_VENDOR_AMD 0x1F00
+#define WGL_GPU_RENDERER_STRING_AMD 0x1F01
+#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define WGL_GPU_RAM_AMD 0x21A3
+#define WGL_GPU_CLOCK_AMD 0x21A4
+#define WGL_GPU_NUM_PIPES_AMD 0x21A5
+#define WGL_GPU_NUM_SIMD_AMD 0x21A6
+#define WGL_GPU_NUM_RB_AMD 0x21A7
+#define WGL_GPU_NUM_SPI_AMD 0x21A8
+
+typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id);
+typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int* attribList);
+typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc);
+typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc);
+typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT* ids);
+typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void* data);
+typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc);
+
+#define wglBlitContextFramebufferAMD WGLEW_GET_FUN(__wglewBlitContextFramebufferAMD)
+#define wglCreateAssociatedContextAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAMD)
+#define wglCreateAssociatedContextAttribsAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAttribsAMD)
+#define wglDeleteAssociatedContextAMD WGLEW_GET_FUN(__wglewDeleteAssociatedContextAMD)
+#define wglGetContextGPUIDAMD WGLEW_GET_FUN(__wglewGetContextGPUIDAMD)
+#define wglGetCurrentAssociatedContextAMD WGLEW_GET_FUN(__wglewGetCurrentAssociatedContextAMD)
+#define wglGetGPUIDsAMD WGLEW_GET_FUN(__wglewGetGPUIDsAMD)
+#define wglGetGPUInfoAMD WGLEW_GET_FUN(__wglewGetGPUInfoAMD)
+#define wglMakeAssociatedContextCurrentAMD WGLEW_GET_FUN(__wglewMakeAssociatedContextCurrentAMD)
+
+#define WGLEW_AMD_gpu_association WGLEW_GET_VAR(__WGLEW_AMD_gpu_association)
+
+#endif /* WGL_AMD_gpu_association */
+
+/* ------------------------- WGL_ARB_buffer_region ------------------------- */
+
+#ifndef WGL_ARB_buffer_region
+#define WGL_ARB_buffer_region 1
+
+#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
+#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
+#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
+
+typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
+typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
+typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
+
+#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB)
+#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB)
+#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB)
+#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB)
+
+#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region)
+
+#endif /* WGL_ARB_buffer_region */
+
+/* ------------------------- WGL_ARB_create_context ------------------------ */
+
+#ifndef WGL_ARB_create_context
+#define WGL_ARB_create_context 1
+
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#define ERROR_INVALID_PROFILE_ARB 0x2096
+
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList);
+
+#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB)
+
+#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context)
+
+#endif /* WGL_ARB_create_context */
+
+/* --------------------- WGL_ARB_create_context_profile -------------------- */
+
+#ifndef WGL_ARB_create_context_profile
+#define WGL_ARB_create_context_profile 1
+
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+#define WGLEW_ARB_create_context_profile WGLEW_GET_VAR(__WGLEW_ARB_create_context_profile)
+
+#endif /* WGL_ARB_create_context_profile */
+
+/* ------------------- WGL_ARB_create_context_robustness ------------------- */
+
+#ifndef WGL_ARB_create_context_robustness
+#define WGL_ARB_create_context_robustness 1
+
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+
+#define WGLEW_ARB_create_context_robustness WGLEW_GET_VAR(__WGLEW_ARB_create_context_robustness)
+
+#endif /* WGL_ARB_create_context_robustness */
+
+/* ----------------------- WGL_ARB_extensions_string ----------------------- */
+
+#ifndef WGL_ARB_extensions_string
+#define WGL_ARB_extensions_string 1
+
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+
+#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB)
+
+#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string)
+
+#endif /* WGL_ARB_extensions_string */
+
+/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */
+
+#ifndef WGL_ARB_framebuffer_sRGB
+#define WGL_ARB_framebuffer_sRGB 1
+
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+
+#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB)
+
+#endif /* WGL_ARB_framebuffer_sRGB */
+
+/* ----------------------- WGL_ARB_make_current_read ----------------------- */
+
+#ifndef WGL_ARB_make_current_read
+#define WGL_ARB_make_current_read 1
+
+#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043
+#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+
+#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB)
+#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB)
+
+#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read)
+
+#endif /* WGL_ARB_make_current_read */
+
+/* -------------------------- WGL_ARB_multisample -------------------------- */
+
+#ifndef WGL_ARB_multisample
+#define WGL_ARB_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+
+#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample)
+
+#endif /* WGL_ARB_multisample */
+
+/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */
+
+#ifndef WGL_ARB_pbuffer
+#define WGL_ARB_pbuffer 1
+
+#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
+#define WGL_PBUFFER_LARGEST_ARB 0x2033
+#define WGL_PBUFFER_WIDTH_ARB 0x2034
+#define WGL_PBUFFER_HEIGHT_ARB 0x2035
+#define WGL_PBUFFER_LOST_ARB 0x2036
+
+DECLARE_HANDLE(HPBUFFERARB);
+
+typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
+
+#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB)
+#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB)
+#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB)
+#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB)
+#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB)
+
+#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer)
+
+#endif /* WGL_ARB_pbuffer */
+
+/* -------------------------- WGL_ARB_pixel_format ------------------------- */
+
+#ifndef WGL_ARB_pixel_format
+#define WGL_ARB_pixel_format 1
+
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_DRAW_TO_BITMAP_ARB 0x2002
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NEED_PALETTE_ARB 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+#define WGL_SWAP_METHOD_ARB 0x2007
+#define WGL_NUMBER_OVERLAYS_ARB 0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
+#define WGL_TRANSPARENT_ARB 0x200A
+#define WGL_SHARE_DEPTH_ARB 0x200C
+#define WGL_SHARE_STENCIL_ARB 0x200D
+#define WGL_SHARE_ACCUM_ARB 0x200E
+#define WGL_SUPPORT_GDI_ARB 0x200F
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_STEREO_ARB 0x2012
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201A
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_ALPHA_SHIFT_ARB 0x201C
+#define WGL_ACCUM_BITS_ARB 0x201D
+#define WGL_ACCUM_RED_BITS_ARB 0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_SWAP_EXCHANGE_ARB 0x2028
+#define WGL_SWAP_COPY_ARB 0x2029
+#define WGL_SWAP_UNDEFINED_ARB 0x202A
+#define WGL_TYPE_RGBA_ARB 0x202B
+#define WGL_TYPE_COLORINDEX_ARB 0x202C
+#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues);
+
+#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB)
+#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB)
+#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB)
+
+#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format)
+
+#endif /* WGL_ARB_pixel_format */
+
+/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */
+
+#ifndef WGL_ARB_pixel_format_float
+#define WGL_ARB_pixel_format_float 1
+
+#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+
+#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float)
+
+#endif /* WGL_ARB_pixel_format_float */
+
+/* ------------------------- WGL_ARB_render_texture ------------------------ */
+
+#ifndef WGL_ARB_render_texture
+#define WGL_ARB_render_texture 1
+
+#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+#define WGL_TEXTURE_FORMAT_ARB 0x2072
+#define WGL_TEXTURE_TARGET_ARB 0x2073
+#define WGL_MIPMAP_TEXTURE_ARB 0x2074
+#define WGL_TEXTURE_RGB_ARB 0x2075
+#define WGL_TEXTURE_RGBA_ARB 0x2076
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+#define WGL_TEXTURE_1D_ARB 0x2079
+#define WGL_TEXTURE_2D_ARB 0x207A
+#define WGL_MIPMAP_LEVEL_ARB 0x207B
+#define WGL_CUBE_MAP_FACE_ARB 0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define WGL_FRONT_LEFT_ARB 0x2083
+#define WGL_FRONT_RIGHT_ARB 0x2084
+#define WGL_BACK_LEFT_ARB 0x2085
+#define WGL_BACK_RIGHT_ARB 0x2086
+#define WGL_AUX0_ARB 0x2087
+#define WGL_AUX1_ARB 0x2088
+#define WGL_AUX2_ARB 0x2089
+#define WGL_AUX3_ARB 0x208A
+#define WGL_AUX4_ARB 0x208B
+#define WGL_AUX5_ARB 0x208C
+#define WGL_AUX6_ARB 0x208D
+#define WGL_AUX7_ARB 0x208E
+#define WGL_AUX8_ARB 0x208F
+#define WGL_AUX9_ARB 0x2090
+
+typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList);
+
+#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB)
+#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB)
+#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB)
+
+#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture)
+
+#endif /* WGL_ARB_render_texture */
+
+/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */
+
+#ifndef WGL_ATI_pixel_format_float
+#define WGL_ATI_pixel_format_float 1
+
+#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
+#define GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+
+#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float)
+
+#endif /* WGL_ATI_pixel_format_float */
+
+/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */
+
+#ifndef WGL_ATI_render_texture_rectangle
+#define WGL_ATI_render_texture_rectangle 1
+
+#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5
+
+#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle)
+
+#endif /* WGL_ATI_render_texture_rectangle */
+
+/* ------------------- WGL_EXT_create_context_es2_profile ------------------ */
+
+#ifndef WGL_EXT_create_context_es2_profile
+#define WGL_EXT_create_context_es2_profile 1
+
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
+#define WGLEW_EXT_create_context_es2_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es2_profile)
+
+#endif /* WGL_EXT_create_context_es2_profile */
+
+/* -------------------------- WGL_EXT_depth_float -------------------------- */
+
+#ifndef WGL_EXT_depth_float
+#define WGL_EXT_depth_float 1
+
+#define WGL_DEPTH_FLOAT_EXT 0x2040
+
+#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float)
+
+#endif /* WGL_EXT_depth_float */
+
+/* ---------------------- WGL_EXT_display_color_table ---------------------- */
+
+#ifndef WGL_EXT_display_color_table
+#define WGL_EXT_display_color_table 1
+
+typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
+typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length);
+
+#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT)
+#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT)
+#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT)
+#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT)
+
+#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table)
+
+#endif /* WGL_EXT_display_color_table */
+
+/* ----------------------- WGL_EXT_extensions_string ----------------------- */
+
+#ifndef WGL_EXT_extensions_string
+#define WGL_EXT_extensions_string 1
+
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
+
+#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT)
+
+#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string)
+
+#endif /* WGL_EXT_extensions_string */
+
+/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */
+
+#ifndef WGL_EXT_framebuffer_sRGB
+#define WGL_EXT_framebuffer_sRGB 1
+
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+
+#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB)
+
+#endif /* WGL_EXT_framebuffer_sRGB */
+
+/* ----------------------- WGL_EXT_make_current_read ----------------------- */
+
+#ifndef WGL_EXT_make_current_read
+#define WGL_EXT_make_current_read 1
+
+#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043
+
+typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+
+#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT)
+#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT)
+
+#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read)
+
+#endif /* WGL_EXT_make_current_read */
+
+/* -------------------------- WGL_EXT_multisample -------------------------- */
+
+#ifndef WGL_EXT_multisample
+#define WGL_EXT_multisample 1
+
+#define WGL_SAMPLE_BUFFERS_EXT 0x2041
+#define WGL_SAMPLES_EXT 0x2042
+
+#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample)
+
+#endif /* WGL_EXT_multisample */
+
+/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */
+
+#ifndef WGL_EXT_pbuffer
+#define WGL_EXT_pbuffer 1
+
+#define WGL_DRAW_TO_PBUFFER_EXT 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
+#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
+#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
+#define WGL_PBUFFER_LARGEST_EXT 0x2033
+#define WGL_PBUFFER_WIDTH_EXT 0x2034
+#define WGL_PBUFFER_HEIGHT_EXT 0x2035
+
+DECLARE_HANDLE(HPBUFFEREXT);
+
+typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList);
+typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
+typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
+typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue);
+typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
+
+#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT)
+#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT)
+#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT)
+#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT)
+#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT)
+
+#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer)
+
+#endif /* WGL_EXT_pbuffer */
+
+/* -------------------------- WGL_EXT_pixel_format ------------------------- */
+
+#ifndef WGL_EXT_pixel_format
+#define WGL_EXT_pixel_format 1
+
+#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
+#define WGL_DRAW_TO_WINDOW_EXT 0x2001
+#define WGL_DRAW_TO_BITMAP_EXT 0x2002
+#define WGL_ACCELERATION_EXT 0x2003
+#define WGL_NEED_PALETTE_EXT 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
+#define WGL_SWAP_METHOD_EXT 0x2007
+#define WGL_NUMBER_OVERLAYS_EXT 0x2008
+#define WGL_NUMBER_UNDERLAYS_EXT 0x2009
+#define WGL_TRANSPARENT_EXT 0x200A
+#define WGL_TRANSPARENT_VALUE_EXT 0x200B
+#define WGL_SHARE_DEPTH_EXT 0x200C
+#define WGL_SHARE_STENCIL_EXT 0x200D
+#define WGL_SHARE_ACCUM_EXT 0x200E
+#define WGL_SUPPORT_GDI_EXT 0x200F
+#define WGL_SUPPORT_OPENGL_EXT 0x2010
+#define WGL_DOUBLE_BUFFER_EXT 0x2011
+#define WGL_STEREO_EXT 0x2012
+#define WGL_PIXEL_TYPE_EXT 0x2013
+#define WGL_COLOR_BITS_EXT 0x2014
+#define WGL_RED_BITS_EXT 0x2015
+#define WGL_RED_SHIFT_EXT 0x2016
+#define WGL_GREEN_BITS_EXT 0x2017
+#define WGL_GREEN_SHIFT_EXT 0x2018
+#define WGL_BLUE_BITS_EXT 0x2019
+#define WGL_BLUE_SHIFT_EXT 0x201A
+#define WGL_ALPHA_BITS_EXT 0x201B
+#define WGL_ALPHA_SHIFT_EXT 0x201C
+#define WGL_ACCUM_BITS_EXT 0x201D
+#define WGL_ACCUM_RED_BITS_EXT 0x201E
+#define WGL_ACCUM_GREEN_BITS_EXT 0x201F
+#define WGL_ACCUM_BLUE_BITS_EXT 0x2020
+#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021
+#define WGL_DEPTH_BITS_EXT 0x2022
+#define WGL_STENCIL_BITS_EXT 0x2023
+#define WGL_AUX_BUFFERS_EXT 0x2024
+#define WGL_NO_ACCELERATION_EXT 0x2025
+#define WGL_GENERIC_ACCELERATION_EXT 0x2026
+#define WGL_FULL_ACCELERATION_EXT 0x2027
+#define WGL_SWAP_EXCHANGE_EXT 0x2028
+#define WGL_SWAP_COPY_EXT 0x2029
+#define WGL_SWAP_UNDEFINED_EXT 0x202A
+#define WGL_TYPE_RGBA_EXT 0x202B
+#define WGL_TYPE_COLORINDEX_EXT 0x202C
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues);
+
+#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT)
+#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT)
+#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT)
+
+#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format)
+
+#endif /* WGL_EXT_pixel_format */
+
+/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */
+
+#ifndef WGL_EXT_pixel_format_packed_float
+#define WGL_EXT_pixel_format_packed_float 1
+
+#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
+
+#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float)
+
+#endif /* WGL_EXT_pixel_format_packed_float */
+
+/* -------------------------- WGL_EXT_swap_control ------------------------- */
+
+#ifndef WGL_EXT_swap_control
+#define WGL_EXT_swap_control 1
+
+typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
+
+#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT)
+#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT)
+
+#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control)
+
+#endif /* WGL_EXT_swap_control */
+
+/* --------------------- WGL_I3D_digital_video_control --------------------- */
+
+#ifndef WGL_I3D_digital_video_control
+#define WGL_I3D_digital_video_control 1
+
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+
+typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue);
+
+#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D)
+#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D)
+
+#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control)
+
+#endif /* WGL_I3D_digital_video_control */
+
+/* ----------------------------- WGL_I3D_gamma ----------------------------- */
+
+#ifndef WGL_I3D_gamma
+#define WGL_I3D_gamma 1
+
+#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E
+#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
+
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue);
+typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue);
+
+#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D)
+#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D)
+#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D)
+#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D)
+
+#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma)
+
+#endif /* WGL_I3D_gamma */
+
+/* ---------------------------- WGL_I3D_genlock ---------------------------- */
+
+#ifndef WGL_I3D_genlock
+#define WGL_I3D_genlock 1
+
+#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+
+typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
+typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge);
+typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource);
+typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay);
+
+#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D)
+#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D)
+#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D)
+#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D)
+#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D)
+#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D)
+#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D)
+#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D)
+#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D)
+#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D)
+#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D)
+#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D)
+
+#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock)
+
+#endif /* WGL_I3D_genlock */
+
+/* -------------------------- WGL_I3D_image_buffer ------------------------- */
+
+#ifndef WGL_I3D_image_buffer
+#define WGL_I3D_image_buffer 1
+
+#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
+#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
+
+typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count);
+typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
+typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
+typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count);
+
+#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D)
+#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D)
+#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D)
+#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D)
+
+#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer)
+
+#endif /* WGL_I3D_image_buffer */
+
+/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */
+
+#ifndef WGL_I3D_swap_frame_lock
+#define WGL_I3D_swap_frame_lock 1
+
+typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID);
+typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag);
+
+#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D)
+#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D)
+#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D)
+#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D)
+
+#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock)
+
+#endif /* WGL_I3D_swap_frame_lock */
+
+/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */
+
+#ifndef WGL_I3D_swap_frame_usage
+#define WGL_I3D_swap_frame_usage 1
+
+typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
+typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
+
+#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D)
+#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D)
+#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D)
+#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D)
+
+#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage)
+
+#endif /* WGL_I3D_swap_frame_usage */
+
+/* --------------------------- WGL_NV_DX_interop --------------------------- */
+
+#ifndef WGL_NV_DX_interop
+#define WGL_NV_DX_interop 1
+
+#define WGL_ACCESS_READ_ONLY_NV 0x0000
+#define WGL_ACCESS_READ_WRITE_NV 0x0001
+#define WGL_ACCESS_WRITE_DISCARD_NV 0x0002
+
+typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
+typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects);
+typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
+typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice);
+typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access);
+typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle);
+typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects);
+typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
+
+#define wglDXCloseDeviceNV WGLEW_GET_FUN(__wglewDXCloseDeviceNV)
+#define wglDXLockObjectsNV WGLEW_GET_FUN(__wglewDXLockObjectsNV)
+#define wglDXObjectAccessNV WGLEW_GET_FUN(__wglewDXObjectAccessNV)
+#define wglDXOpenDeviceNV WGLEW_GET_FUN(__wglewDXOpenDeviceNV)
+#define wglDXRegisterObjectNV WGLEW_GET_FUN(__wglewDXRegisterObjectNV)
+#define wglDXSetResourceShareHandleNV WGLEW_GET_FUN(__wglewDXSetResourceShareHandleNV)
+#define wglDXUnlockObjectsNV WGLEW_GET_FUN(__wglewDXUnlockObjectsNV)
+#define wglDXUnregisterObjectNV WGLEW_GET_FUN(__wglewDXUnregisterObjectNV)
+
+#define WGLEW_NV_DX_interop WGLEW_GET_VAR(__WGLEW_NV_DX_interop)
+
+#endif /* WGL_NV_DX_interop */
+
+/* --------------------------- WGL_NV_copy_image --------------------------- */
+
+#ifndef WGL_NV_copy_image
+#define WGL_NV_copy_image 1
+
+typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+#define wglCopyImageSubDataNV WGLEW_GET_FUN(__wglewCopyImageSubDataNV)
+
+#define WGLEW_NV_copy_image WGLEW_GET_VAR(__WGLEW_NV_copy_image)
+
+#endif /* WGL_NV_copy_image */
+
+/* -------------------------- WGL_NV_float_buffer -------------------------- */
+
+#ifndef WGL_NV_float_buffer
+#define WGL_NV_float_buffer 1
+
+#define WGL_FLOAT_COMPONENTS_NV 0x20B0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define WGL_TEXTURE_FLOAT_R_NV 0x20B5
+#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
+#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
+#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
+
+#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer)
+
+#endif /* WGL_NV_float_buffer */
+
+/* -------------------------- WGL_NV_gpu_affinity -------------------------- */
+
+#ifndef WGL_NV_gpu_affinity
+#define WGL_NV_gpu_affinity 1
+
+#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0
+#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1
+
+DECLARE_HANDLE(HGPUNV);
+typedef struct _GPU_DEVICE {
+ DWORD cb;
+ CHAR DeviceName[32];
+ CHAR DeviceString[128];
+ DWORD Flags;
+ RECT rcVirtualScreen;
+} GPU_DEVICE, *PGPU_DEVICE;
+
+typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList);
+typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc);
+typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
+typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
+typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu);
+
+#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV)
+#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV)
+#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV)
+#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV)
+#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV)
+
+#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity)
+
+#endif /* WGL_NV_gpu_affinity */
+
+/* ---------------------- WGL_NV_multisample_coverage ---------------------- */
+
+#ifndef WGL_NV_multisample_coverage
+#define WGL_NV_multisample_coverage 1
+
+#define WGL_COVERAGE_SAMPLES_NV 0x2042
+#define WGL_COLOR_SAMPLES_NV 0x20B9
+
+#define WGLEW_NV_multisample_coverage WGLEW_GET_VAR(__WGLEW_NV_multisample_coverage)
+
+#endif /* WGL_NV_multisample_coverage */
+
+/* -------------------------- WGL_NV_present_video ------------------------- */
+
+#ifndef WGL_NV_present_video
+#define WGL_NV_present_video 1
+
+#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0
+
+DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
+
+typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList);
+typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList);
+typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue);
+
+#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV)
+#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV)
+#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV)
+
+#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video)
+
+#endif /* WGL_NV_present_video */
+
+/* ---------------------- WGL_NV_render_depth_texture ---------------------- */
+
+#ifndef WGL_NV_render_depth_texture
+#define WGL_NV_render_depth_texture 1
+
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
+#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+#define WGL_DEPTH_COMPONENT_NV 0x20A7
+
+#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture)
+
+#endif /* WGL_NV_render_depth_texture */
+
+/* -------------------- WGL_NV_render_texture_rectangle -------------------- */
+
+#ifndef WGL_NV_render_texture_rectangle
+#define WGL_NV_render_texture_rectangle 1
+
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define WGL_TEXTURE_RECTANGLE_NV 0x20A2
+
+#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle)
+
+#endif /* WGL_NV_render_texture_rectangle */
+
+/* --------------------------- WGL_NV_swap_group --------------------------- */
+
+#ifndef WGL_NV_swap_group
+#define WGL_NV_swap_group 1
+
+typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
+typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
+typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count);
+typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers);
+typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group, GLuint *barrier);
+typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
+
+#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV)
+#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV)
+#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV)
+#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV)
+#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV)
+#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV)
+
+#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group)
+
+#endif /* WGL_NV_swap_group */
+
+/* ----------------------- WGL_NV_vertex_array_range ----------------------- */
+
+#ifndef WGL_NV_vertex_array_range
+#define WGL_NV_vertex_array_range 1
+
+typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
+
+#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV)
+#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV)
+
+#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range)
+
+#endif /* WGL_NV_vertex_array_range */
+
+/* -------------------------- WGL_NV_video_capture ------------------------- */
+
+#ifndef WGL_NV_video_capture
+#define WGL_NV_video_capture 1
+
+#define WGL_UNIQUE_ID_NV 0x20CE
+#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+
+DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
+
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
+typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList);
+typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
+
+#define wglBindVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewBindVideoCaptureDeviceNV)
+#define wglEnumerateVideoCaptureDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoCaptureDevicesNV)
+#define wglLockVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewLockVideoCaptureDeviceNV)
+#define wglQueryVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewQueryVideoCaptureDeviceNV)
+#define wglReleaseVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoCaptureDeviceNV)
+
+#define WGLEW_NV_video_capture WGLEW_GET_VAR(__WGLEW_NV_video_capture)
+
+#endif /* WGL_NV_video_capture */
+
+/* -------------------------- WGL_NV_video_output -------------------------- */
+
+#ifndef WGL_NV_video_output
+#define WGL_NV_video_output 1
+
+#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0
+#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1
+#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+#define WGL_VIDEO_OUT_COLOR_NV 0x20C3
+#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4
+#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5
+#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define WGL_VIDEO_OUT_FRAME 0x20C8
+#define WGL_VIDEO_OUT_FIELD_1 0x20C9
+#define WGL_VIDEO_OUT_FIELD_2 0x20CA
+#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
+#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
+
+DECLARE_HANDLE(HPVIDEODEV);
+
+typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);
+typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);
+typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock);
+
+#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV)
+#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV)
+#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV)
+#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV)
+#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV)
+#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV)
+
+#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output)
+
+#endif /* WGL_NV_video_output */
+
+/* -------------------------- WGL_OML_sync_control ------------------------- */
+
+#ifndef WGL_OML_sync_control
+#define WGL_OML_sync_control 1
+
+typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator);
+typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc);
+typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
+typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc);
+typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc);
+
+#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML)
+#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML)
+#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML)
+#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML)
+#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML)
+#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML)
+
+#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control)
+
+#endif /* WGL_OML_sync_control */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+#define WGLEW_EXPORT
+#else
+#define WGLEW_EXPORT GLEWAPI
+#endif /* GLEW_MX */
+
+#ifdef GLEW_MX
+struct WGLEWContextStruct
+{
+#endif /* GLEW_MX */
+
+WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL;
+
+WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD;
+WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD;
+WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD;
+WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD;
+WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD;
+WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD;
+WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD;
+WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD;
+WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD;
+
+WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB;
+WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB;
+WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB;
+WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB;
+
+WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB;
+
+WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB;
+
+WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB;
+WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB;
+
+WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB;
+WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB;
+WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB;
+WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB;
+WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB;
+
+WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB;
+
+WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB;
+WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB;
+WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB;
+
+WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT;
+WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT;
+
+WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT;
+
+WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT;
+WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT;
+
+WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT;
+WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT;
+WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT;
+WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT;
+WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT;
+
+WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT;
+WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT;
+
+WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT;
+WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT;
+
+WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D;
+WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D;
+
+WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D;
+WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D;
+WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D;
+WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D;
+
+WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D;
+WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D;
+WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D;
+WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D;
+WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D;
+WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D;
+
+WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D;
+WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D;
+WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D;
+WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D;
+
+WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D;
+WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D;
+WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D;
+WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D;
+
+WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D;
+WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D;
+WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D;
+WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D;
+
+WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV;
+WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV;
+WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV;
+WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV;
+WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV;
+WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV;
+WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV;
+WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV;
+
+WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV;
+
+WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV;
+WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV;
+WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV;
+WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV;
+WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV;
+
+WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV;
+WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV;
+WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV;
+
+WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV;
+WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV;
+WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV;
+WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV;
+WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV;
+WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV;
+
+WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV;
+WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV;
+
+WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV;
+WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV;
+WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV;
+WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV;
+WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV;
+
+WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV;
+WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV;
+WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV;
+WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV;
+WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV;
+WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV;
+
+WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML;
+WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML;
+WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML;
+WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML;
+WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML;
+WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML;
+WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control;
+WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float;
+WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture;
+WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float;
+WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float;
+WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock;
+WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage;
+WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop;
+WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image;
+WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer;
+WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity;
+WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage;
+WGLEW_EXPORT GLboolean __WGLEW_NV_present_video;
+WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture;
+WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle;
+WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group;
+WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range;
+WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture;
+WGLEW_EXPORT GLboolean __WGLEW_NV_video_output;
+WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control;
+
+#ifdef GLEW_MX
+}; /* WGLEWContextStruct */
+#endif /* GLEW_MX */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef GLEW_MX
+
+typedef struct WGLEWContextStruct WGLEWContext;
+GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx);
+GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name);
+
+#define wglewInit() wglewContextInit(wglewGetContext())
+#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x)
+
+#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x))
+#define WGLEW_GET_FUN(x) wglewGetContext()->x
+
+#else /* GLEW_MX */
+
+#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x)
+#define WGLEW_GET_FUN(x) x
+
+GLEWAPI GLboolean wglewIsSupported (const char* name);
+
+#endif /* GLEW_MX */
+
+GLEWAPI GLboolean wglewGetExtension (const char* name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef GLEWAPI
+
+#endif /* __wglew_h__ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglext.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglext.h
new file mode 100644
index 00000000..ac632cce
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/GL/wglext.h
@@ -0,0 +1,421 @@
+#ifndef __wglext_h_
+#define __wglext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+*/
+
+#ifndef GLAPI
+# define GLAPI __stdcall
+# define __DEFINED_GLAPI
+#endif
+
+DECLARE_HANDLE(HPBUFFERARB);
+DECLARE_HANDLE(HPVIDEODEVICE);
+DECLARE_HANDLE(HGPUNV);
+DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
+DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
+
+ /* WGL_NV_gpu_affinity */
+typedef struct _GPU_DEVICE {
+ DWORD cb;
+ CHAR DeviceName[32];
+ CHAR DeviceString[128];
+ DWORD Flags;
+ RECT rcVirtualScreen;
+} GPU_DEVICE, *PGPU_DEVICE;
+
+/*************************************************************/
+
+/* Extensions */
+#define WGL_ARB_buffer_region 1
+#define WGL_ARB_create_context_robustness 1
+#define WGL_ARB_extensions_string 1
+#define WGL_ARB_make_current_read 1
+#define WGL_ARB_multisample 1
+#define WGL_ARB_pbuffer 1
+#define WGL_ARB_pixel_format 1
+#define WGL_ARB_pixel_format_float 1
+#define WGL_ARB_render_texture 1
+#define WGL_ATI_pixel_format_float 1
+#define WGL_EXT_create_context_es2_profile 1
+#define WGL_EXT_extensions_string 1
+#define WGL_EXT_framebuffer_sRGB 1
+#define WGL_EXT_pixel_format_packed_float 1
+#define WGL_EXT_swap_control 1
+#define WGL_NV_allocate_memory 1
+#define WGL_NV_copy_image 1
+#define WGL_NV_float_buffer 1
+#define WGL_NV_multisample_coverage 1
+#define WGL_NV_render_depth_texture 1
+#define WGL_NV_render_texture_rectangle 1
+#define WGL_NV_video_output 1
+#define WGL_KTX_buffer_region 1
+#define WGL_I3D_genlock 1
+#define WGL_NV_swap_group 1
+#define WGL_NV_gpu_affinity 1
+#define WGL_NV_present_video 1
+#define WGL_ARB_create_context 1
+#define WGL_NV_video_capture 1
+
+/* ARB_buffer_region */
+#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
+#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
+#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
+
+/* ARB_pixel_format */
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_DRAW_TO_BITMAP_ARB 0x2002
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NEED_PALETTE_ARB 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+#define WGL_SWAP_METHOD_ARB 0x2007
+#define WGL_NUMBER_OVERLAYS_ARB 0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
+#define WGL_TRANSPARENT_ARB 0x200A
+#define WGL_SHARE_DEPTH_ARB 0x200C
+#define WGL_SHARE_STENCIL_ARB 0x200D
+#define WGL_SHARE_ACCUM_ARB 0x200E
+#define WGL_SUPPORT_GDI_ARB 0x200F
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_STEREO_ARB 0x2012
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201A
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_ALPHA_SHIFT_ARB 0x201C
+#define WGL_ACCUM_BITS_ARB 0x201D
+#define WGL_ACCUM_RED_BITS_ARB 0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_SWAP_EXCHANGE_ARB 0x2028
+#define WGL_SWAP_COPY_ARB 0x2029
+#define WGL_SWAP_UNDEFINED_ARB 0x202A
+#define WGL_TYPE_RGBA_ARB 0x202B
+#define WGL_TYPE_COLORINDEX_ARB 0x202C
+#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+
+/* ARB_pbuffer */
+#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
+#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
+#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
+#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
+#define WGL_PBUFFER_LARGEST_ARB 0x2033
+#define WGL_PBUFFER_WIDTH_ARB 0x2034
+#define WGL_PBUFFER_HEIGHT_ARB 0x2035
+#define WGL_PBUFFER_LOST_ARB 0x2036
+
+/* ARB_multisample */
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+
+/* I3D_genlock */
+#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+
+/* ARB_render_texture */
+#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+#define WGL_TEXTURE_FORMAT_ARB 0x2072
+#define WGL_TEXTURE_TARGET_ARB 0x2073
+#define WGL_MIPMAP_TEXTURE_ARB 0x2074
+#define WGL_TEXTURE_RGB_ARB 0x2075
+#define WGL_TEXTURE_RGBA_ARB 0x2076
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+#define WGL_TEXTURE_1D_ARB 0x2079
+#define WGL_TEXTURE_2D_ARB 0x207A
+#define WGL_MIPMAP_LEVEL_ARB 0x207B
+#define WGL_CUBE_MAP_FACE_ARB 0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define WGL_FRONT_LEFT_ARB 0x2083
+#define WGL_FRONT_RIGHT_ARB 0x2084
+#define WGL_BACK_LEFT_ARB 0x2085
+#define WGL_BACK_RIGHT_ARB 0x2086
+#define WGL_AUX0_ARB 0x2087
+#define WGL_AUX1_ARB 0x2088
+#define WGL_AUX2_ARB 0x2089
+#define WGL_AUX3_ARB 0x208A
+#define WGL_AUX4_ARB 0x208B
+#define WGL_AUX5_ARB 0x208C
+#define WGL_AUX6_ARB 0x208D
+#define WGL_AUX7_ARB 0x208E
+#define WGL_AUX8_ARB 0x208F
+#define WGL_AUX9_ARB 0x2090
+
+/* NV_render_depth_texture */
+#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
+#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+#define WGL_DEPTH_COMPONENT_NV 0x20A7
+
+/* NV_float_buffer */
+#define WGL_FLOAT_COMPONENTS_NV 0x20B0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define WGL_TEXTURE_FLOAT_R_NV 0x20B5
+#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
+#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
+#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
+
+/* NV_render_texture_rectangle */
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define WGL_TEXTURE_RECTANGLE_NV 0x20A2
+
+/* ARB_make_current_read */
+#define WGL_ERROR_INVALID_PIXEL_TYPE_ARB 0x2043
+#define WGL_ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+
+/* ATI_pixel_format_float */
+#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
+
+/* WGL_NV_video_output */
+#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0
+#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1
+#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+#define WGL_VIDEO_OUT_COLOR_NV 0x20C3
+#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4
+#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5
+#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define WGL_VIDEO_OUT_FRAME_NV 0x20C8
+#define WGL_VIDEO_OUT_FIELD_1_NV 0x20C9
+#define WGL_VIDEO_OUT_FIELD_2_NV 0x20CA
+#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
+#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
+
+/* ARB_pixel_format_float */
+#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+
+/* EXT_pixel_format_packed_float */
+#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
+
+/* NV_gpu_affinity */
+#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0
+#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1
+
+/* EXT_framebuffer_sRGB */
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+
+/* NV_multisample_coverage */
+#define WGL_COVERAGE_SAMPLES_NV 0x2042
+#define WGL_COLOR_SAMPLES_NV 0x20B9
+
+/* NV_present_video */
+#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0
+
+/* ARB_create_context */
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_ERROR_INVALID_VERSION_ARB 0x2095
+
+/* NV_video_capture */
+#define WGL_UNIQUE_ID_NV 0x20CE
+
+/* EXT_create_context_es2_profile */
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x0004
+
+/* ARB_create_context_robustness */
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x0004
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+
+
+/*************************************************************/
+
+
+/* WGL_ARB_buffer_region */
+typedef HANDLE (GLAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hdc, int iLayerPlane, UINT uType);
+typedef void (GLAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
+typedef BOOL (GLAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
+typedef BOOL (GLAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
+
+/* WGL_ARB_create_context */
+typedef HGLRC (APIENTRY * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC, HGLRC, const int *);
+
+/* WGL_ARB_extensions_string */
+typedef const char * (GLAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+
+/* WGL_ARB_pbuffer */
+typedef HPBUFFERARB (GLAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
+typedef HDC (GLAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
+typedef int (GLAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hdc);
+typedef BOOL (GLAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
+typedef BOOL (GLAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
+
+/* WGL_ARB_render_texture */
+typedef BOOL (GLAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (GLAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
+typedef BOOL (GLAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList);
+
+/* WGL_NV_video_output */
+typedef BOOL (GLAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, INT iVideoStreams, HPVIDEODEVICE* phpVideoDevice);
+typedef BOOL (GLAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEVICE hpVideoDevice);
+typedef BOOL (GLAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEVICE hpVideoDevice, HPBUFFERARB hPbuffer, INT iVideoBuffer);
+typedef BOOL (GLAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, INT iVideoBuffer);
+typedef BOOL (GLAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, INT iBufferType, unsigned long * pulCounterPbuffer, BOOL bBlock);
+typedef BOOL (GLAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEVICE hpVideoDevice, unsigned long * pulCounterOutputVideo, unsigned long * pulCounterOutputPbuffer);
+
+/* WGL_ARB_pixel_format */
+typedef BOOL (GLAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
+typedef BOOL (GLAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
+typedef BOOL (GLAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+
+/* WGL_EXT_extensions_string */
+typedef const char * (GLAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
+
+/* WGL_EXT_swap_control */
+typedef int (GLAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
+typedef int (GLAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
+
+/* WGL_NV_allocate_memory */
+typedef void * (GLAPI * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority);
+typedef void (GLAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
+
+/* WGL_KTX_buffer_region */
+typedef UINT (GLAPI * PFNWGLNEWBUFFERREGIONPROC) (UINT type);
+typedef void (GLAPI * PFNWGLDELETEBUFFERREGIONPROC) (UINT region);
+typedef void (GLAPI * PFNWGLREADBUFFERREGIONPROC) (UINT region, int x, int y, GLint width, GLint height);
+typedef void (GLAPI * PFNWGLDRAWBUFFERREGIONPROC) (UINT region, int x, int y, GLint width, GLint height, int xDest, int yDest);
+typedef UINT (GLAPI * PFNWGLBUFFERREGIONENABLEDPROC) (void);
+
+/* WGL_I3D_genlock */
+typedef BOOL (GLAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hdc);
+typedef BOOL (GLAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hdc);
+typedef BOOL (GLAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hdc, BOOL * pFlag);
+typedef BOOL (GLAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hdc, UINT uSource);
+typedef BOOL (GLAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hdc, UINT * uSource);
+typedef BOOL (GLAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hdc, UINT uEdge);
+typedef BOOL (GLAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hdc, UINT * uEdge);
+typedef BOOL (GLAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hdc, UINT uRate);
+typedef BOOL (GLAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hdc, UINT * uRate);
+typedef BOOL (GLAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hdc, UINT uDelay);
+typedef BOOL (GLAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hdc, UINT * uDelay);
+typedef BOOL (GLAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hdc, UINT * uMaxLineDelay, UINT * uMaxPixelDelay);
+
+/* WGL_NV_swap_group */
+typedef BOOL (GLAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
+typedef BOOL (GLAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
+typedef BOOL (GLAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint * group, GLuint * barrier);
+typedef BOOL (GLAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint * maxGroups, GLuint * maxBarriers);
+typedef BOOL (GLAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint * count);
+typedef BOOL (GLAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
+
+/* WGL_ARB_make_current_read */
+typedef BOOL (GLAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
+typedef HDC (GLAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);
+
+/* WGL_NV_copy_image */
+typedef BOOL (GLAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+
+/* WGL_NV_gpu_affinity */
+typedef BOOL (GLAPI * PFNWGLENUMGPUSNVPROC) (UINT iIndex, HGPUNV *hGpu);
+typedef BOOL (GLAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iIndex, PGPU_DEVICE pGpuDevice);
+typedef HDC (GLAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *pGpuList);
+typedef BOOL (GLAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iIndex, HGPUNV *hGpu);
+typedef BOOL (GLAPI * PFNWGLDELETEDCNVPROC) (HDC hAffinityDC);
+
+/* WGL_NV_present_video */
+typedef INT (GLAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
+typedef BOOL (GLAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, UINT uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int * piAttribList);
+typedef BOOL (GLAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (INT iAttribute, INT *piValue);
+
+/* WGL_NV_video_capture */
+typedef BOOL (GLAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hVideoDevice);
+typedef UINT (GLAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDC, HVIDEOINPUTDEVICENV *phDeviceList);
+typedef BOOL (GLAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDC, HVIDEOINPUTDEVICENV hDevice);
+typedef BOOL (GLAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDC, HVIDEOINPUTDEVICENV hDevice, INT iAttribute, INT *piValue);
+typedef BOOL (GLAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDC, HVIDEOINPUTDEVICENV hDevice);
+
+/* WGL_NVX_DX_interop */
+#define WGL_ACCESS_READ_ONLY_NVX 0x0000
+#define WGL_ACCESS_READ_WRITE_NVX 0x0001
+#define WGL_ACCESS_WRITE_DISCARD_NVX 0x0002
+typedef HANDLE (GLAPI * PFNWGLDXOPENDEVICENVXPROC) (void *dxDevice);
+typedef BOOL (GLAPI * PFNWGLDXCLOSEDEVICENVXPROC) (HANDLE hDevice);
+typedef HANDLE (GLAPI * PFNWGLDXREGISTEROBJECTNVXPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
+typedef BOOL (GLAPI * PFNWGLDXUNREGISTEROBJECTNVXPROC) (HANDLE hDevice, HANDLE hObject);
+typedef BOOL (GLAPI * PFNWGLDXOBJECTACCESSNVXPROC) (HANDLE hObject, GLenum access);
+typedef BOOL (GLAPI * PFNWGLDXLOCKOBJECTSNVXPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
+typedef BOOL (GLAPI * PFNWGLDXUNLOCKOBJECTSNVXPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
+
+#ifdef __DEFINED_GLAPI
+# undef GLAPI
+# undef __DEFINED_GLAPI
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __wglext_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_extwindowprops.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_extwindowprops.h
new file mode 100644
index 00000000..4428a568
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_extwindowprops.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_extwindowprops_h_
+#define __kd_QT3DS_extwindowprops_h_
+#include <KD/kd.h>
+#include <EGL/eglext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_WINDOWPROPERTY_FULLSCREEN: Control over resizing a window to fill the complete screen */
+
+// KDboolean - set the window to fullscreen mode
+#define KD_WINDOWPROPERTY_FULLSCREEN_QT3DS 9999
+
+// KDint - set which KD_DISPLAY_* display that the window should be opened on
+#define KD_WINDOWPROPERTY_DISPLAY_QT3DS 9998
+
+// KDboolean - sets whether overlay should be used to create window
+#define KD_WINDOWPROPERTY_OVERLAY_QT3DS 9997
+
+#define KD_DISPLAY_PRIMARY_QT3DS 0
+#define KD_DISPLAY_INTERNAL0_QT3DS 0
+#define KD_DISPLAY_INTERNAL1_QT3DS 1
+#define KD_DISPLAY_INTERNAL2_QT3DS 2
+#define KD_DISPLAY_INTERNAL3_QT3DS 3
+#define KD_DISPLAY_EXTERNAL0_QT3DS 1000
+#define KD_DISPLAY_EXTERNAL1_QT3DS 1001
+#define KD_DISPLAY_EXTERNAL2_QT3DS 1002
+#define KD_DISPLAY_EXTERNAL3_QT3DS 1003
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_extwindowprops_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_multitouch.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_multitouch.h
new file mode 100644
index 00000000..e230b029
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/Qt3DS_multitouch.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __kd_QT3DS_multitouch_h_
+#define __kd_QT3DS_multitouch_h_
+#include <KD/kd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* KD_IOGROUP_MULTITOUCH: I/O group for Multitouch input devices. */
+#define KD_IOGROUP_MULTITOUCH_QT3DS 0x40004000
+#define KD_STATE_MULTITOUCH_AVAILABILITY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 0)
+#define KD_INPUT_MULTITOUCH_FINGERS_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 1)
+#define KD_INPUT_MULTITOUCH_WIDTH_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 2)
+#define KD_INPUT_MULTITOUCH_X_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 3)
+#define KD_INPUT_MULTITOUCH_Y_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 4)
+#define KD_INPUT_MULTITOUCH_X2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 5)
+#define KD_INPUT_MULTITOUCH_Y2_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 6)
+#define KD_INPUT_MULTITOUCH_PRESSURE_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 7)
+#define KD_INPUT_MULTITOUCH_GESTURES_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 8)
+#define KD_INPUT_MULTITOUCH_RELX_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 9)
+#define KD_INPUT_MULTITOUCH_RELY_QT3DS (KD_IOGROUP_MULTITOUCH_QT3DS + 10)
+
+/* KD_EVENT_INPUT_MULTITOUCH_QT3DS: Multitouch event. */
+#define KD_EVENT_INPUT_MULTITOUCH_QT3DS 1001
+typedef struct KDEventInputMultitouchDataNV
+{
+ KDint32 index;
+ KDint8 fingers;
+ KDint8 width;
+ KDint16 x;
+ KDint16 y;
+ KDint16 x2;
+ KDint16 y2;
+ KDint16 pressure;
+} KDEventInputMultitouchDataNV;
+
+/* KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS: Multitouch gesture event. */
+#define KD_EVENT_INPUT_MULTITOUCH_GESTURE_QT3DS 1002
+
+/* kdGetEventInputMultitouchDataNV: Get auxiliary event data for multitouch input. */
+KD_API KDint KD_APIENTRY kdGetEventInputMultitouchDataNV(const KDEvent *event,
+ KDEventInputMultitouchDataNV *data);
+
+/* kdSetEventInputMultitouchActiveNV: Activate Multitouch input events */
+KD_API KDint KD_APIENTRY kdSetEventInputMultitouchActiveNV(KDboolean activate);
+
+/* kdEnableEventInputMultitouchMergeNV: Activate merging of Multitouch input events */
+KD_API void KD_APIENTRY kdEnableEventInputMultitouchMergeNV(KDboolean enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_QT3DS_multitouch_h_ */
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kd.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kd.h
new file mode 100644
index 00000000..f7ccea03
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kd.h
@@ -0,0 +1,991 @@
+/* Reference KD/kd.h for OpenKODE Core 1.0.3 */
+#ifndef __kd_h_
+#define __kd_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kdplatform.h"
+
+
+
+/*******************************************************
+ * Introduction
+ *******************************************************/
+
+/*******************************************************
+ * OpenKODE conformance
+ *******************************************************/
+
+/*******************************************************
+ * Overview
+ *******************************************************/
+
+/*******************************************************
+ * Programming environment
+ *******************************************************/
+#define KD_VERSION_1_0 1
+typedef char KDchar;
+typedef signed char KDint8;
+typedef unsigned char KDuint8;
+typedef int KDint;
+typedef unsigned int KDuint;
+typedef float KDfloat32;
+typedef KDint KDboolean;
+typedef KDint64 KDtime;
+typedef KDint64 KDust;
+typedef KDint64 KDoff;
+typedef KDuint32 KDmode;
+#define KDINT32_MIN (-0x7fffffff-1)
+#define KDINT32_MAX 0x7fffffff
+#define KDUINT32_MAX 0xffffffffU
+#define KD_TRUE 1
+#define KD_FALSE 0
+#ifdef __cplusplus
+ const int KD_NULL = 0; /* Yes, int. See Stroustrup 3rd edition. */
+#else
+ #define KD_NULL ((void *)0)
+#endif
+
+/*******************************************************
+ * Errors
+ *******************************************************/
+#define KD_EACCES 1
+#define KD_EADDRINUSE 2
+#define KD_EADDRNOTAVAIL 3
+#define KD_EAFNOSUPPORT 4
+#define KD_EAGAIN (5)
+#define KD_EALREADY 6
+#define KD_EBADF 7
+#define KD_EBUSY 8
+#define KD_ECONNREFUSED 9
+#define KD_ECONNRESET 10
+#define KD_EDEADLK 11
+#define KD_EDESTADDRREQ 12
+#define KD_EEXIST 13
+#define KD_EFBIG 14
+#define KD_EHOSTUNREACH 15
+#define KD_EHOST_NOT_FOUND 16
+#define KD_EINVAL 17
+#define KD_EIO 18
+#define KD_EILSEQ 19
+#define KD_EISCONN 20
+#define KD_EISDIR 21
+#define KD_EMFILE 22
+#define KD_ENAMETOOLONG 23
+#define KD_ENOENT 24
+#define KD_ENOMEM 25
+#define KD_ENOSPC 26
+#define KD_ENOSYS 27
+#define KD_ENOTCONN 28
+#define KD_ENO_DATA 29
+#define KD_ENO_RECOVERY 30
+#define KD_EOPNOTSUPP 31
+#define KD_EOVERFLOW 32
+#define KD_EPERM 33
+#define KD_ERANGE 35
+#define KD_ETIMEDOUT (36)
+#define KD_ETRY_AGAIN 37
+
+/* kdGetError: Get last error indication. */
+KD_API KDint KD_APIENTRY kdGetError(void);
+
+/* kdSetError: Set last error indication. */
+KD_API void KD_APIENTRY kdSetError(KDint error);
+
+/*******************************************************
+ * Versioning and attribute queries
+ *******************************************************/
+
+/* kdQueryAttribi: Obtain the value of a numeric OpenKODE Core attribute. */
+KD_API KDint KD_APIENTRY kdQueryAttribi(KDint attribute, KDint *value);
+
+/* kdQueryAttribcv: Obtain the value of a string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryAttribcv(KDint attribute);
+#define KD_ATTRIB_VENDOR 39
+#define KD_ATTRIB_VERSION 40
+#define KD_ATTRIB_PLATFORM 41
+
+/* kdQueryIndexedAttribcv: Obtain the value of an indexed string OpenKODE Core attribute. */
+KD_API const KDchar *KD_APIENTRY kdQueryIndexedAttribcv(KDint attribute, KDint index);
+
+/*******************************************************
+ * Threads and synchronization
+ *******************************************************/
+
+/* kdThreadAttrCreate: Create a thread attribute object. */
+typedef struct KDThreadAttr KDThreadAttr;
+KD_API KDThreadAttr *KD_APIENTRY kdThreadAttrCreate(void);
+
+/* kdThreadAttrFree: Free a thread attribute object. */
+KD_API KDint KD_APIENTRY kdThreadAttrFree(KDThreadAttr *attr);
+
+/* kdThreadAttrSetDetachState: Set detachstate attribute. */
+#define KD_THREAD_CREATE_JOINABLE 0
+#define KD_THREAD_CREATE_DETACHED 1
+KD_API KDint KD_APIENTRY kdThreadAttrSetDetachState(KDThreadAttr *attr, KDint detachstate);
+
+/* kdThreadAttrSetStackSize: Set stacksize attribute. */
+KD_API KDint KD_APIENTRY kdThreadAttrSetStackSize(KDThreadAttr *attr, KDsize stacksize);
+
+/* kdThreadCreate: Create a new thread. */
+typedef struct KDThread KDThread;
+KD_API KDThread *KD_APIENTRY kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg);
+
+/* kdThreadExit: Terminate this thread. */
+KD_API KD_NORETURN void KD_APIENTRY kdThreadExit(void *retval);
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KD_API KDint KD_APIENTRY kdThreadJoin(KDThread *thread, void **retval);
+
+/* kdThreadDetach: Allow resources to be freed as soon as a thread terminates. */
+KD_API KDint KD_APIENTRY kdThreadDetach(KDThread *thread);
+
+/* kdThreadSelf: Return calling thread&#8217;s ID. */
+KD_API KDThread *KD_APIENTRY kdThreadSelf(void);
+
+/* kdThreadOnce: Wrap initialization code so it is executed only once. */
+#ifndef KD_NO_STATIC_DATA
+typedef struct KDThreadOnce {
+ void *impl;
+} KDThreadOnce;
+#define KD_THREAD_ONCE_INIT { 0 }
+KD_API KDint KD_APIENTRY kdThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void));
+#endif /* ndef KD_NO_STATIC_DATA */
+
+/* kdThreadMutexCreate: Create a mutex. */
+typedef struct KDThreadMutex KDThreadMutex;
+KD_API KDThreadMutex *KD_APIENTRY kdThreadMutexCreate(const void *mutexattr);
+
+/* kdThreadMutexFree: Free a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexFree(KDThreadMutex *mutex);
+
+/* kdThreadMutexLock: Lock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexLock(KDThreadMutex *mutex);
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KD_API KDint KD_APIENTRY kdThreadMutexUnlock(KDThreadMutex *mutex);
+
+/* kdThreadCondCreate: Create a condition variable. */
+typedef struct KDThreadCond KDThreadCond;
+KD_API KDThreadCond *KD_APIENTRY kdThreadCondCreate(const void *attr);
+
+/* kdThreadCondFree: Free a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondFree(KDThreadCond *cond);
+
+/* kdThreadCondSignal, kdThreadCondBroadcast: Signal a condition variable. */
+KD_API KDint KD_APIENTRY kdThreadCondSignal(KDThreadCond *cond);
+KD_API KDint KD_APIENTRY kdThreadCondBroadcast(KDThreadCond *cond);
+
+/* kdThreadCondWait: Wait for a condition variable to be signalled. */
+KD_API KDint KD_APIENTRY kdThreadCondWait(KDThreadCond *cond, KDThreadMutex *mutex);
+
+/* kdThreadSemCreate: Create a semaphore. */
+typedef struct KDThreadSem KDThreadSem;
+KD_API KDThreadSem *KD_APIENTRY kdThreadSemCreate(KDuint value);
+
+/* kdThreadSemFree: Free a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemFree(KDThreadSem *sem);
+
+/* kdThreadSemWait: Lock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemWait(KDThreadSem *sem);
+
+/* kdThreadSemPost: Unlock a semaphore. */
+KD_API KDint KD_APIENTRY kdThreadSemPost(KDThreadSem *sem);
+
+/*******************************************************
+ * Events
+ *******************************************************/
+
+/* KDEvent: Struct type containing an event. */
+typedef struct KDEvent KDEvent;
+#define KD_EVENT_USER 0x40000000
+
+/* kdWaitEvent: Get next event from thread&#8217;s event queue. */
+KD_API const KDEvent *KD_APIENTRY kdWaitEvent(KDust timeout);
+
+/* kdSetEventUserptr: Set the userptr for global events. */
+KD_API void KD_APIENTRY kdSetEventUserptr(void *userptr);
+
+/* kdDefaultEvent: Perform default processing on an unrecognized event. */
+KD_API void KD_APIENTRY kdDefaultEvent(const KDEvent *event);
+
+/* kdPumpEvents: Pump the thread&#8217;s event queue, performing callbacks. */
+KD_API KDint KD_APIENTRY kdPumpEvents(void);
+
+/* kdInstallCallback: Install or remove a callback function for event processing. */
+typedef void (KD_APIENTRY KDCallbackFunc)(const KDEvent *event);
+KD_API KDint KD_APIENTRY kdInstallCallback(KDCallbackFunc *func, KDint eventtype, void *eventuserptr);
+
+/* kdCreateEvent: Create an event for posting. */
+KD_API KDEvent *KD_APIENTRY kdCreateEvent(void);
+
+/* kdPostEvent, kdPostThreadEvent: Post an event into a queue. */
+KD_API KDint KD_APIENTRY kdPostEvent(KDEvent *event);
+KD_API KDint KD_APIENTRY kdPostThreadEvent(KDEvent *event, KDThread *thread);
+typedef struct KDEventUser {
+ union {
+ KDint64 i64;
+ void *p;
+ struct {
+ KDint32 a;
+ KDint32 b;
+ } i32pair;
+ } value1;
+ union {
+ KDint64 i64;
+ struct {
+ union {
+ KDint32 i32;
+ void *p;
+ } value2;
+ union {
+ KDint32 i32;
+ void *p;
+ } value3;
+ } i32orp;
+ } value23;
+} KDEventUser;
+
+/* kdFreeEvent: Abandon an event instead of posting it. */
+KD_API void KD_APIENTRY kdFreeEvent(KDEvent *event);
+
+/*******************************************************
+ * System events
+ *******************************************************/
+
+/* KD_EVENT_QUIT: Event to request to quit application. */
+#define KD_EVENT_QUIT 43
+
+/* KD_EVENT_PAUSE: Application pause event. */
+#define KD_EVENT_PAUSE 45
+
+/* KD_EVENT_RESUME: Application resume event. */
+#define KD_EVENT_RESUME 46
+
+/* KD_EVENT_ORIENTATION: Orientation change event. */
+#define KD_EVENT_ORIENTATION 48
+
+/* KD_IOGROUP_EVENT: I/O group for OpenKODE Core system events implemented as state values. */
+#define KD_IOGROUP_EVENT 0x100
+#define KD_STATE_EVENT_USING_BATTERY (KD_IOGROUP_EVENT + 0)
+#define KD_STATE_EVENT_LOW_BATTERY (KD_IOGROUP_EVENT + 1)
+
+
+/* KD_IOGROUP_ORIENTATION: I/O group for OpenKODE Core orientation state. */
+#define KD_IOGROUP_ORIENTATION 0x200
+#define KD_STATE_ORIENTATION_OVERALL (KD_IOGROUP_ORIENTATION + 0)
+#define KD_STATE_ORIENTATION_SCREEN (KD_IOGROUP_ORIENTATION + 1)
+#define KD_STATE_ORIENTATION_RENDERING (KD_IOGROUP_ORIENTATION + 2)
+#define KD_STATE_ORIENTATION_LOCKSURFACE (KD_IOGROUP_ORIENTATION + 3)
+
+
+/*******************************************************
+ * Application startup and exit.
+ *******************************************************/
+
+/* kdMain: The application-defined main function. */
+KDint KD_APIENTRY kdMain(KDint argc, const KDchar *const *argv);
+
+/* kdExit: Exit the application. */
+KD_API KD_NORETURN void KD_APIENTRY kdExit(KDint status);
+
+/*******************************************************
+ * Utility library functions
+ *******************************************************/
+
+/* kdAbs: Compute the absolute value of an integer. */
+KD_API KDint KD_APIENTRY kdAbs(KDint i);
+
+/* kdStrtof: Convert a string to a floating point number. */
+KD_API KDfloat32 KD_APIENTRY kdStrtof(const KDchar *s, KDchar **endptr);
+
+/* kdStrtol, kdStrtoul: Convert a string to an integer. */
+KD_API KDint KD_APIENTRY kdStrtol(const KDchar *s, KDchar **endptr, KDint base);
+KD_API KDuint KD_APIENTRY kdStrtoul(const KDchar *s, KDchar **endptr, KDint base);
+
+/* kdLtostr, kdUltostr: Convert an integer to a string. */
+#define KD_LTOSTR_MAXLEN ((sizeof(KDint)*8*3+6)/10+2)
+#define KD_ULTOSTR_MAXLEN ((sizeof(KDint)*8+2)/3+1)
+KD_API KDssize KD_APIENTRY kdLtostr(KDchar *buffer, KDsize buflen, KDint number);
+KD_API KDssize KD_APIENTRY kdUltostr(KDchar *buffer, KDsize buflen, KDuint number, KDint base);
+
+/* kdFtostr: Convert a float to a string. */
+#define KD_FTOSTR_MAXLEN 16
+KD_API KDssize KD_APIENTRY kdFtostr(KDchar *buffer, KDsize buflen, KDfloat32 number);
+
+/* kdCryptoRandom: Return random data. */
+KD_API KDint KD_APIENTRY kdCryptoRandom(KDuint8 *buf, KDsize buflen);
+
+/*******************************************************
+ * Locale specific functions
+ *******************************************************/
+
+/* kdGetLocale: Determine the current language and locale. */
+KD_API const KDchar *KD_APIENTRY kdGetLocale(void);
+
+/*******************************************************
+ * Memory allocation
+ *******************************************************/
+
+/* kdMalloc: Allocate memory. */
+KD_API void *KD_APIENTRY kdMalloc(KDsize size);
+
+/* kdFree: Free allocated memory block. */
+KD_API void KD_APIENTRY kdFree(void *ptr);
+
+/* kdRealloc: Resize memory block. */
+KD_API void *KD_APIENTRY kdRealloc(void *ptr, KDsize size);
+
+/*******************************************************
+ * Thread-local storage.
+ *******************************************************/
+
+/* kdGetTLS: Get the thread-local storage pointer. */
+KD_API void *KD_APIENTRY kdGetTLS(void);
+
+/* kdSetTLS: Set the thread-local storage pointer. */
+KD_API void KD_APIENTRY kdSetTLS(void *ptr);
+
+/*******************************************************
+ * Mathematical functions
+ *******************************************************/
+#define KD_E_F 2.71828175F
+#define KD_PI_F 3.14159274F
+#define KD_PI_2_F 1.57079637F
+#define KD_2PI_F 6.28318548F
+#define KD_LOG2E_F 1.44269502F
+#define KD_LOG10E_F 0.434294492F
+#define KD_LN2_F 0.693147182F
+#define KD_LN10_F 2.30258512F
+#define KD_PI_4_F 0.785398185F
+#define KD_1_PI_F 0.318309873F
+#define KD_2_PI_F 0.636619747F
+#define KD_2_SQRTPI_F 1.12837923F
+#define KD_SQRT2_F 1.41421354F
+#define KD_SQRT1_2_F 0.707106769F
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_FLT_MAX 3.40282346638528860e+38F
+#define KD_FLT_MIN 1.17549435e-38F
+/* KD_INFINITY is defined in kdplatform.h since no portable definition
+ * is possible. */
+#define kdIsNan(x) (((x) != (x)) ? 1 : 0)
+#define KD_HUGE_VALF KD_INFINITY
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+/* kdAcosf: Arc cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdAcosf(KDfloat32 x);
+
+/* kdAsinf: Arc sine function. */
+KD_API KDfloat32 KD_APIENTRY kdAsinf(KDfloat32 x);
+
+/* kdAtanf: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtanf(KDfloat32 x);
+
+/* kdAtan2f: Arc tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdAtan2f(KDfloat32 y, KDfloat32 x);
+
+/* kdCosf: Cosine function. */
+KD_API KDfloat32 KD_APIENTRY kdCosf(KDfloat32 x);
+
+/* kdSinf: Sine function. */
+KD_API KDfloat32 KD_APIENTRY kdSinf(KDfloat32 x);
+
+/* kdTanf: Tangent function. */
+KD_API KDfloat32 KD_APIENTRY kdTanf(KDfloat32 x);
+
+/* kdExpf: Exponential function. */
+KD_API KDfloat32 KD_APIENTRY kdExpf(KDfloat32 x);
+
+/* kdLogf: Natural logarithm function. */
+KD_API KDfloat32 KD_APIENTRY kdLogf(KDfloat32 x);
+
+/* kdFabsf: Absolute value. */
+KD_API KDfloat32 KD_APIENTRY kdFabsf(KDfloat32 x);
+
+/* kdPowf: Power function. */
+KD_API KDfloat32 KD_APIENTRY kdPowf(KDfloat32 x, KDfloat32 y);
+
+/* kdSqrtf: Square root function. */
+KD_API KDfloat32 KD_APIENTRY kdSqrtf(KDfloat32 x);
+
+/* kdCeilf: Return ceiling value. */
+KD_API KDfloat32 KD_APIENTRY kdCeilf(KDfloat32 x);
+
+/* kdFloorf: Return floor value. */
+KD_API KDfloat32 KD_APIENTRY kdFloorf(KDfloat32 x);
+
+/* kdRoundf: Round value to nearest integer. */
+KD_API KDfloat32 KD_APIENTRY kdRoundf(KDfloat32 x);
+
+/* kdInvsqrtf: Inverse square root function. */
+KD_API KDfloat32 KD_APIENTRY kdInvsqrtf(KDfloat32 x);
+
+/* kdFmodf: Calculate floating point remainder. */
+KD_API KDfloat32 KD_APIENTRY kdFmodf(KDfloat32 x, KDfloat32 y);
+
+/*******************************************************
+ * String and memory functions
+ *******************************************************/
+
+/* kdMemchr: Scan memory for a byte value. */
+KD_API void *KD_APIENTRY kdMemchr(const void *src, KDint byte, KDsize len);
+
+/* kdMemcmp: Compare two memory regions. */
+KD_API KDint KD_APIENTRY kdMemcmp(const void *src1, const void *src2, KDsize len);
+
+/* kdMemcpy: Copy a memory region, no overlapping. */
+KD_API void *KD_APIENTRY kdMemcpy(void *buf, const void *src, KDsize len);
+
+/* kdMemmove: Copy a memory region, overlapping allowed. */
+KD_API void *KD_APIENTRY kdMemmove(void *buf, const void *src, KDsize len);
+
+/* kdMemset: Set bytes in memory to a value. */
+KD_API void *KD_APIENTRY kdMemset(void *buf, KDint byte, KDsize len);
+
+/* kdStrchr: Scan string for a byte value. */
+KD_API KDchar *KD_APIENTRY kdStrchr(const KDchar *str, KDint ch);
+
+/* kdStrcmp: Compares two strings. */
+KD_API KDint KD_APIENTRY kdStrcmp(const KDchar *str1, const KDchar *str2);
+
+/* kdStrlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrlen(const KDchar *str);
+
+/* kdStrnlen: Determine the length of a string. */
+KD_API KDsize KD_APIENTRY kdStrnlen(const KDchar *str, KDsize maxlen);
+
+/* kdStrncat_s: Concatenate two strings. */
+KD_API KDint KD_APIENTRY kdStrncat_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srcmaxlen);
+
+/* kdStrncmp: Compares two strings with length limit. */
+KD_API KDint KD_APIENTRY kdStrncmp(const KDchar *str1, const KDchar *str2, KDsize maxlen);
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrcpy_s(KDchar *buf, KDsize buflen, const KDchar *src);
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KD_API KDint KD_APIENTRY kdStrncpy_s(KDchar *buf, KDsize buflen, const KDchar *src, KDsize srclen);
+
+/*******************************************************
+ * Time functions
+ *******************************************************/
+
+/* kdGetTimeUST: Get the current unadjusted system time. */
+KD_API KDust KD_APIENTRY kdGetTimeUST(void);
+
+/* kdTime: Get the current wall clock time. */
+KD_API KDtime KD_APIENTRY kdTime(KDtime *timep);
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+typedef struct KDTm {
+ KDint32 tm_sec;
+ KDint32 tm_min;
+ KDint32 tm_hour;
+ KDint32 tm_mday;
+ KDint32 tm_mon;
+ KDint32 tm_year;
+ KDint32 tm_wday;
+ KDint32 tm_yday;
+} KDTm;
+KD_API KDTm *KD_APIENTRY kdGmtime_r(const KDtime *timep, KDTm *result);
+KD_API KDTm *KD_APIENTRY kdLocaltime_r(const KDtime *timep, KDTm *result);
+
+/* kdUSTAtEpoch: Get the UST corresponding to KDtime 0. */
+KD_API KDust KD_APIENTRY kdUSTAtEpoch(void);
+
+/*******************************************************
+ * Timer functions
+ *******************************************************/
+
+/* kdSetTimer: Set timer. */
+#define KD_TIMER_ONESHOT 61
+#define KD_TIMER_PERIODIC_AVERAGE 62
+#define KD_TIMER_PERIODIC_MINIMUM 63
+typedef struct KDTimer KDTimer;
+KD_API KDTimer *KD_APIENTRY kdSetTimer(KDint64 interval, KDint periodic, void *eventuserptr);
+
+/* kdCancelTimer: Cancel and free a timer. */
+KD_API KDint KD_APIENTRY kdCancelTimer(KDTimer *timer);
+
+/* KD_EVENT_TIMER: Timer fire event. */
+#define KD_EVENT_TIMER 42
+
+/*******************************************************
+ * File system
+ *******************************************************/
+#define KD_EOF (-1)
+
+/* kdFopen: Open a file from the file system. */
+typedef struct KDFile KDFile;
+KD_API KDFile *KD_APIENTRY kdFopen(const KDchar *pathname, const KDchar *mode);
+
+/* kdFclose: Close an open file. */
+KD_API KDint KD_APIENTRY kdFclose(KDFile *file);
+
+/* kdFflush: Flush an open file. */
+KD_API KDint KD_APIENTRY kdFflush(KDFile *file);
+
+/* kdFread: Read from a file. */
+KD_API KDsize KD_APIENTRY kdFread(void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdFwrite: Write to a file. */
+KD_API KDsize KD_APIENTRY kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file);
+
+/* kdGetc: Read next byte from an open file. */
+KD_API KDint KD_APIENTRY kdGetc(KDFile *file);
+
+/* kdPutc: Write a byte to an open file. */
+KD_API KDint KD_APIENTRY kdPutc(KDint c, KDFile *file);
+
+/* kdFgets: Read a line of text from an open file. */
+KD_API KDchar *KD_APIENTRY kdFgets(KDchar *buffer, KDsize buflen, KDFile *file);
+
+/* kdFEOF: Check for end of file. */
+KD_API KDint KD_APIENTRY kdFEOF(KDFile *file);
+
+/* kdFerror: Check for an error condition on an open file. */
+KD_API KDint KD_APIENTRY kdFerror(KDFile *file);
+
+/* kdClearerr: Clear a file&#8217;s error and end-of-file indicators. */
+KD_API void KD_APIENTRY kdClearerr(KDFile *file);
+
+/* kdFseek: Reposition the file position indicator in a file. */
+typedef enum {
+ KD_SEEK_SET = 0,
+ KD_SEEK_CUR = 1,
+ KD_SEEK_END = 2
+} KDfileSeekOrigin;
+KD_API KDint KD_APIENTRY kdFseek(KDFile *file, KDoff offset, KDfileSeekOrigin origin);
+
+/* kdFtell: Get the file position of an open file. */
+KD_API KDoff KD_APIENTRY kdFtell(KDFile *file);
+
+/* kdMkdir: Create new directory. */
+KD_API KDint KD_APIENTRY kdMkdir(const KDchar *pathname);
+
+/* kdRmdir: Delete a directory. */
+KD_API KDint KD_APIENTRY kdRmdir(const KDchar *pathname);
+
+/* kdRename: Rename a file. */
+KD_API KDint KD_APIENTRY kdRename(const KDchar *src, const KDchar *dest);
+
+/* kdRemove: Delete a file. */
+KD_API KDint KD_APIENTRY kdRemove(const KDchar *pathname);
+
+/* kdTruncate: Truncate or extend a file. */
+KD_API KDint KD_APIENTRY kdTruncate(const KDchar *pathname, KDoff length);
+
+/* kdStat, kdFstat: Return information about a file. */
+typedef struct KDStat {
+ KDmode st_mode;
+ KDoff st_size;
+ KDtime st_mtime;
+} KDStat;
+KD_API KDint KD_APIENTRY kdStat(const KDchar *pathname, struct KDStat *buf);
+KD_API KDint KD_APIENTRY kdFstat(KDFile *file, struct KDStat *buf);
+#define KD_ISREG(m) ((m) & 0x8000)
+#define KD_ISDIR(m) ((m) & 0x4000)
+
+/* kdAccess: Determine whether the application can access a file or directory. */
+KD_API KDint KD_APIENTRY kdAccess(const KDchar *pathname, KDint amode);
+#define KD_R_OK 4
+#define KD_W_OK 2
+#define KD_X_OK 1
+
+/* kdOpenDir: Open a directory ready for listing. */
+typedef struct KDDir KDDir;
+KD_API KDDir *KD_APIENTRY kdOpenDir(const KDchar *pathname);
+
+/* kdReadDir: Return the next file in a directory. */
+typedef struct KDDirent {
+ const KDchar *d_name;
+} KDDirent;
+KD_API KDDirent *KD_APIENTRY kdReadDir(KDDir *dir);
+
+/* kdCloseDir: Close a directory. */
+KD_API KDint KD_APIENTRY kdCloseDir(KDDir *dir);
+
+/* kdGetFree: Get free space on a drive. */
+KD_API KDoff KD_APIENTRY kdGetFree(const KDchar *pathname);
+
+/*******************************************************
+ * Network sockets
+ *******************************************************/
+
+/* KDSockaddr: Struct type for socket address. */
+typedef struct KDSockaddr {
+ KDuint16 family;
+ union {
+#define KD_AF_INET 70
+ struct {
+ KDuint16 port;
+ KDuint32 address;
+ } sin;
+ } data;
+} KDSockaddr;
+
+/* kdNameLookup: Look up a hostname. */
+KD_API KDint KD_APIENTRY kdNameLookup(KDint af, const KDchar *hostname, void *eventuserptr);
+
+/* kdNameLookupCancel: Selectively cancels ongoing kdNameLookup operations. */
+KD_API void KD_APIENTRY kdNameLookupCancel(void *eventuserptr);
+
+/* kdSocketCreate: Creates a socket. */
+typedef struct KDSocket KDSocket;
+KD_API KDSocket *KD_APIENTRY kdSocketCreate(KDint type, void *eventuserptr);
+#define KD_SOCK_TCP 64
+#define KD_SOCK_UDP 65
+
+/* kdSocketClose: Closes a socket. */
+KD_API KDint KD_APIENTRY kdSocketClose(KDSocket *socket);
+
+/* kdSocketBind: Bind a socket. */
+KD_API KDint KD_APIENTRY kdSocketBind(KDSocket *socket, const struct KDSockaddr *addr, KDboolean reuse);
+#define KD_INADDR_ANY 0
+
+/* kdSocketGetName: Get the local address of a socket. */
+KD_API KDint KD_APIENTRY kdSocketGetName(KDSocket *socket, struct KDSockaddr *addr);
+
+/* kdSocketConnect: Connects a socket. */
+KD_API KDint KD_APIENTRY kdSocketConnect(KDSocket *socket, const KDSockaddr *addr);
+
+/* kdSocketListen: Listen on a socket. */
+KD_API KDint KD_APIENTRY kdSocketListen(KDSocket *socket, KDint backlog);
+
+/* kdSocketAccept: Accept an incoming connection. */
+KD_API KDSocket *KD_APIENTRY kdSocketAccept(KDSocket *socket, KDSockaddr *addr, void *eventuserptr);
+
+/* kdSocketSend, kdSocketSendTo: Send data to a socket. */
+KD_API KDint KD_APIENTRY kdSocketSend(KDSocket *socket, const void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketSendTo(KDSocket *socket, const void *buf, KDint len, const KDSockaddr *addr);
+
+/* kdSocketRecv, kdSocketRecvFrom: Receive data from a socket. */
+KD_API KDint KD_APIENTRY kdSocketRecv(KDSocket *socket, void *buf, KDint len);
+KD_API KDint KD_APIENTRY kdSocketRecvFrom(KDSocket *socket, void *buf, KDint len, KDSockaddr *addr);
+
+/* kdHtonl: Convert a 32-bit integer from host to network byte order. */
+KD_API KDuint32 KD_APIENTRY kdHtonl(KDuint32 hostlong);
+
+/* kdHtons: Convert a 16-bit integer from host to network byte order. */
+KD_API KDuint16 KD_APIENTRY kdHtons(KDuint16 hostshort);
+
+/* kdNtohl: Convert a 32-bit integer from network to host byte order. */
+KD_API KDuint32 KD_APIENTRY kdNtohl(KDuint32 netlong);
+
+/* kdNtohs: Convert a 16-bit integer from network to host byte order. */
+KD_API KDuint16 KD_APIENTRY kdNtohs(KDuint16 netshort);
+
+/* kdInetAton: Convert a &#8220;dotted quad&#8221; format address to an integer. */
+KD_API KDint KD_APIENTRY kdInetAton(const KDchar *cp, KDuint32 *inp);
+
+/* kdInetNtop: Convert a network address to textual form. */
+#define KD_INET_ADDRSTRLEN 16
+typedef struct KDInAddr {
+ KDuint32 s_address; // Renamed this from s_addr as it causes a conflict with winsock2.h
+} KDInAddr;
+KD_API const KDchar *KD_APIENTRY kdInetNtop(KDuint af, const void *src, KDchar *dst, KDsize cnt);
+
+/* KD_EVENT_SOCKET_READABLE: Event to indicate that a socket is readable. */
+#define KD_EVENT_SOCKET_READABLE 49
+typedef struct KDEventSocketReadable {
+ KDSocket *socket;
+} KDEventSocketReadable;
+
+/* KD_EVENT_SOCKET_WRITABLE: Event to indicate that a socket is writable. */
+#define KD_EVENT_SOCKET_WRITABLE 50
+typedef struct KDEventSocketWritable {
+ KDSocket *socket;
+} KDEventSocketWritable;
+
+/* KD_EVENT_SOCKET_CONNECT_COMPLETE: Event generated when a socket connect is complete */
+#define KD_EVENT_SOCKET_CONNECT_COMPLETE 51
+typedef struct KDEventSocketConnect {
+ KDSocket *socket;
+ KDint32 error;
+} KDEventSocketConnect;
+
+/* KD_EVENT_SOCKET_INCOMING: Event generated when a listening socket detects an incoming connection or an error. */
+#define KD_EVENT_SOCKET_INCOMING 52
+typedef struct KDEventSocketIncoming {
+ KDSocket *socket;
+} KDEventSocketIncoming;
+
+/* KD_EVENT_NAME_LOOKUP_COMPLETE: kdNameLookup complete event. */
+#define KD_EVENT_NAME_LOOKUP_COMPLETE 53
+typedef struct KDEventNameLookup {
+ KDint32 error;
+ KDint32 resultlen;
+ const KDSockaddr *result;
+ KDboolean more;
+} KDEventNameLookup;
+
+/*******************************************************
+ * Input/output
+ *******************************************************/
+
+/* KD_EVENT_STATE: State changed event. */
+#define KD_EVENT_STATE 55
+
+typedef struct KDEventState {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventState;
+
+/* KD_EVENT_INPUT: Input changed event. */
+#define KD_EVENT_INPUT 56
+
+typedef struct KDEventInput {
+ KDint32 index;
+ union {
+ KDint32 i;
+ KDint64 l;
+ KDfloat32 f;
+ } value;
+} KDEventInput;
+
+/* KD_EVENT_INPUT_JOG: Jogdial jog event. */
+#define KD_EVENT_INPUT_JOG 71
+typedef struct KDEventInputJog {
+ KDint32 index;
+ KDint32 count;
+} KDEventInputJog;
+
+/* KD_EVENT_INPUT_POINTER: Pointer input changed event. */
+#define KD_EVENT_INPUT_POINTER 57
+typedef struct KDEventInputPointer {
+ KDint32 index;
+ KDint32 select;
+ KDint32 x;
+ KDint32 y;
+} KDEventInputPointer;
+
+/* KD_EVENT_INPUT_STICK: Joystick stick changed event. */
+#define KD_EVENT_INPUT_STICK 58
+typedef struct KDEventInputStick {
+ KDint32 index;
+ KDint32 x;
+ KDint32 y;
+ KDint32 z;
+} KDEventInputStick;
+
+/* kdStateGeti, kdStateGetl, kdStateGetf: get state value(s) */
+KD_API KDint KD_APIENTRY kdStateGeti(KDint startidx, KDuint numidxs, KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetl(KDint startidx, KDuint numidxs, KDint64 *buffer);
+KD_API KDint KD_APIENTRY kdStateGetf(KDint startidx, KDuint numidxs, KDfloat32 *buffer);
+
+/* kdOutputSeti, kdOutputSetf: set outputs */
+KD_API KDint KD_APIENTRY kdOutputSeti(KDint startidx, KDuint numidxs, const KDint32 *buffer);
+KD_API KDint KD_APIENTRY kdOutputSetf(KDint startidx, KDuint numidxs, const KDfloat32 *buffer);
+#define KD_IO_CONTROLLER_STRIDE 64
+
+/* KD_IOGROUP_GAMEKEYS: I/O group for game keys. */
+#define KD_IOGROUP_GAMEKEYS 0x1000
+#define KD_STATE_GAMEKEYS_AVAILABILITY (KD_IOGROUP_GAMEKEYS + 0)
+#define KD_INPUT_GAMEKEYS_UP (KD_IOGROUP_GAMEKEYS + 1)
+#define KD_INPUT_GAMEKEYS_LEFT (KD_IOGROUP_GAMEKEYS + 2)
+#define KD_INPUT_GAMEKEYS_RIGHT (KD_IOGROUP_GAMEKEYS + 3)
+#define KD_INPUT_GAMEKEYS_DOWN (KD_IOGROUP_GAMEKEYS + 4)
+#define KD_INPUT_GAMEKEYS_FIRE (KD_IOGROUP_GAMEKEYS + 5)
+#define KD_INPUT_GAMEKEYS_A (KD_IOGROUP_GAMEKEYS + 6)
+#define KD_INPUT_GAMEKEYS_B (KD_IOGROUP_GAMEKEYS + 7)
+#define KD_INPUT_GAMEKEYS_C (KD_IOGROUP_GAMEKEYS + 8)
+#define KD_INPUT_GAMEKEYS_D (KD_IOGROUP_GAMEKEYS + 9)
+
+/* KD_IOGROUP_GAMEKEYSNC: I/O group for game keys, no chording. */
+#define KD_IOGROUP_GAMEKEYSNC 0x1100
+#define KD_STATE_GAMEKEYSNC_AVAILABILITY (KD_IOGROUP_GAMEKEYSNC + 0)
+#define KD_INPUT_GAMEKEYSNC_UP (KD_IOGROUP_GAMEKEYSNC + 1)
+#define KD_INPUT_GAMEKEYSNC_LEFT (KD_IOGROUP_GAMEKEYSNC + 2)
+#define KD_INPUT_GAMEKEYSNC_RIGHT (KD_IOGROUP_GAMEKEYSNC + 3)
+#define KD_INPUT_GAMEKEYSNC_DOWN (KD_IOGROUP_GAMEKEYSNC + 4)
+#define KD_INPUT_GAMEKEYSNC_FIRE (KD_IOGROUP_GAMEKEYSNC + 5)
+#define KD_INPUT_GAMEKEYSNC_A (KD_IOGROUP_GAMEKEYSNC + 6)
+#define KD_INPUT_GAMEKEYSNC_B (KD_IOGROUP_GAMEKEYSNC + 7)
+#define KD_INPUT_GAMEKEYSNC_C (KD_IOGROUP_GAMEKEYSNC + 8)
+#define KD_INPUT_GAMEKEYSNC_D (KD_IOGROUP_GAMEKEYSNC + 9)
+
+/* KD_IOGROUP_PHONEKEYPAD: I/O group for phone keypad. */
+#define KD_IOGROUP_PHONEKEYPAD 0x2000
+#define KD_STATE_PHONEKEYPAD_AVAILABILITY (KD_IOGROUP_PHONEKEYPAD + 0)
+#define KD_INPUT_PHONEKEYPAD_0 (KD_IOGROUP_PHONEKEYPAD + 1)
+#define KD_INPUT_PHONEKEYPAD_1 (KD_IOGROUP_PHONEKEYPAD + 2)
+#define KD_INPUT_PHONEKEYPAD_2 (KD_IOGROUP_PHONEKEYPAD + 3)
+#define KD_INPUT_PHONEKEYPAD_3 (KD_IOGROUP_PHONEKEYPAD + 4)
+#define KD_INPUT_PHONEKEYPAD_4 (KD_IOGROUP_PHONEKEYPAD + 5)
+#define KD_INPUT_PHONEKEYPAD_5 (KD_IOGROUP_PHONEKEYPAD + 6)
+#define KD_INPUT_PHONEKEYPAD_6 (KD_IOGROUP_PHONEKEYPAD + 7)
+#define KD_INPUT_PHONEKEYPAD_7 (KD_IOGROUP_PHONEKEYPAD + 8)
+#define KD_INPUT_PHONEKEYPAD_8 (KD_IOGROUP_PHONEKEYPAD + 9)
+#define KD_INPUT_PHONEKEYPAD_9 (KD_IOGROUP_PHONEKEYPAD + 10)
+#define KD_INPUT_PHONEKEYPAD_STAR (KD_IOGROUP_PHONEKEYPAD + 11)
+#define KD_INPUT_PHONEKEYPAD_HASH (KD_IOGROUP_PHONEKEYPAD + 12)
+#define KD_INPUT_PHONEKEYPAD_LEFTSOFT (KD_IOGROUP_PHONEKEYPAD + 13)
+#define KD_INPUT_PHONEKEYPAD_RIGHTSOFT (KD_IOGROUP_PHONEKEYPAD + 14)
+#define KD_STATE_PHONEKEYPAD_ORIENTATION (KD_IOGROUP_PHONEKEYPAD + 15)
+
+/* KD_IOGROUP_VIBRATE: I/O group for vibrate. */
+#define KD_IOGROUP_VIBRATE 0x3000
+#define KD_STATE_VIBRATE_AVAILABILITY (KD_IOGROUP_VIBRATE + 0)
+#define KD_STATE_VIBRATE_MINFREQUENCY (KD_IOGROUP_VIBRATE + 1)
+#define KD_STATE_VIBRATE_MAXFREQUENCY (KD_IOGROUP_VIBRATE + 2)
+#define KD_OUTPUT_VIBRATE_VOLUME (KD_IOGROUP_VIBRATE + 3)
+#define KD_OUTPUT_VIBRATE_FREQUENCY (KD_IOGROUP_VIBRATE + 4)
+
+/* KD_IOGROUP_POINTER: I/O group for pointer. */
+#define KD_IOGROUP_POINTER 0x4000
+#define KD_STATE_POINTER_AVAILABILITY (KD_IOGROUP_POINTER + 0)
+#define KD_INPUT_POINTER_X (KD_IOGROUP_POINTER + 1)
+#define KD_INPUT_POINTER_Y (KD_IOGROUP_POINTER + 2)
+#define KD_INPUT_POINTER_SELECT (KD_IOGROUP_POINTER + 3)
+
+/* KD_IOGROUP_BACKLIGHT: I/O group for backlight. */
+#define KD_IOGROUP_BACKLIGHT 0x5000
+#define KD_STATE_BACKLIGHT_AVAILABILITY (KD_IOGROUP_BACKLIGHT + 0)
+#define KD_OUTPUT_BACKLIGHT_FORCE (KD_IOGROUP_BACKLIGHT + 1)
+
+/* KD_IOGROUP_JOGDIAL: I/O group for a jog dial. */
+#define KD_IOGROUP_JOGDIAL 0x6000
+#define KD_STATE_JOGDIAL_AVAILABILITY (KD_IOGROUP_JOGDIAL + 0)
+#define KD_INPUT_JOGDIAL_UP (KD_IOGROUP_JOGDIAL + 1)
+#define KD_INPUT_JOGDIAL_LEFT (KD_IOGROUP_JOGDIAL + 2)
+#define KD_INPUT_JOGDIAL_RIGHT (KD_IOGROUP_JOGDIAL + 3)
+#define KD_INPUT_JOGDIAL_DOWN (KD_IOGROUP_JOGDIAL + 4)
+#define KD_INPUT_JOGDIAL_SELECT (KD_IOGROUP_JOGDIAL + 5)
+
+/* KD_IOGROUP_STICK: I/O group for joystick. */
+#define KD_IOGROUP_STICK 0x7000
+#define KD_STATE_STICK_AVAILABILITY (KD_IOGROUP_STICK + 0)
+#define KD_INPUT_STICK_X (KD_IOGROUP_STICK + 1)
+#define KD_INPUT_STICK_Y (KD_IOGROUP_STICK + 2)
+#define KD_INPUT_STICK_Z (KD_IOGROUP_STICK + 3)
+#define KD_INPUT_STICK_BUTTON (KD_IOGROUP_STICK + 4)
+#define KD_IO_STICK_STRIDE 8
+
+/* KD_IOGROUP_DPAD: I/O group for D-pad. */
+#define KD_IOGROUP_DPAD 0x8000
+#define KD_STATE_DPAD_AVAILABILITY (KD_IOGROUP_DPAD + 0)
+#define KD_STATE_DPAD_COPY (KD_IOGROUP_DPAD + 1)
+#define KD_INPUT_DPAD_UP (KD_IOGROUP_DPAD + 2)
+#define KD_INPUT_DPAD_LEFT (KD_IOGROUP_DPAD + 3)
+#define KD_INPUT_DPAD_RIGHT (KD_IOGROUP_DPAD + 4)
+#define KD_INPUT_DPAD_DOWN (KD_IOGROUP_DPAD + 5)
+#define KD_INPUT_DPAD_SELECT (KD_IOGROUP_DPAD + 6)
+#define KD_IO_DPAD_STRIDE 8
+
+/* KD_IOGROUP_BUTTONS: I/O group for buttons associated with joystick or D-pad. */
+#define KD_IOGROUP_BUTTONS 0x9000
+#define KD_STATE_BUTTONS_AVAILABILITY (KD_IOGROUP_BUTTONS + 0)
+#define KD_INPUT_BUTTONS_0 (KD_IOGROUP_BUTTONS + 1)
+
+/* KD_IO_UNDEFINED: I/O items reserved for implementation-dependent use. */
+#define KD_IO_UNDEFINED 0x40000000
+
+/*******************************************************
+ * Windowing
+ *******************************************************/
+#ifdef KD_WINDOW_SUPPORTED
+#include <EGL/egl.h>
+typedef struct KDWindow KDWindow;
+
+/* kdCreateWindow: Create a window. */
+KD_API KDWindow *KD_APIENTRY kdCreateWindow(EGLDisplay display, EGLConfig config, void *eventuserptr);
+
+/* kdDestroyWindow: Destroy a window. */
+KD_API KDint KD_APIENTRY kdDestroyWindow(KDWindow *window);
+
+/* kdSetWindowPropertybv, kdSetWindowPropertyiv, kdSetWindowPropertycv: Set a window property to request a change in the on-screen representation of the window. */
+KD_API KDint KD_APIENTRY kdSetWindowPropertybv(KDWindow *window, KDint pname, const KDboolean *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertyiv(KDWindow *window, KDint pname, const KDint32 *param);
+KD_API KDint KD_APIENTRY kdSetWindowPropertycv(KDWindow *window, KDint pname, const KDchar *param);
+
+/* kdGetWindowPropertybv, kdGetWindowPropertyiv, kdGetWindowPropertycv: Get the current value of a window property. */
+KD_API KDint KD_APIENTRY kdGetWindowPropertybv(KDWindow *window, KDint pname, KDboolean *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertyiv(KDWindow *window, KDint pname, KDint32 *param);
+KD_API KDint KD_APIENTRY kdGetWindowPropertycv(KDWindow *window, KDint pname, KDchar *param, KDsize *size);
+
+/* kdRealizeWindow: Realize the window as a displayable entity and get the native window handle for passing to EGL. */
+KD_API KDint KD_APIENTRY kdRealizeWindow(KDWindow *window, EGLNativeWindowType *nativewindow);
+
+/* KD_WINDOWPROPERTY_SIZE: Window client area width and height. */
+#define KD_WINDOWPROPERTY_SIZE 66
+
+/* KD_WINDOWPROPERTY_VISIBILITY: Window visibility status. */
+#define KD_WINDOWPROPERTY_VISIBILITY 67
+
+/* KD_WINDOWPROPERTY_FOCUS: Window input focus status. */
+#define KD_WINDOWPROPERTY_FOCUS 68
+
+/* KD_WINDOWPROPERTY_CAPTION: Window caption. */
+#define KD_WINDOWPROPERTY_CAPTION 69
+
+/* KD_EVENT_WINDOW_CLOSE: Event to request to close window. */
+#define KD_EVENT_WINDOW_CLOSE 44
+
+/* KD_EVENT_WINDOWPROPERTY_CHANGE: Notification about realized window property change. */
+#define KD_EVENT_WINDOWPROPERTY_CHANGE 47
+typedef struct KDEventWindowProperty {
+ KDint32 pname;
+} KDEventWindowProperty;
+
+/* KD_EVENT_WINDOW_FOCUS: Event for change of window&#8217;s focus state. */
+#define KD_EVENT_WINDOW_FOCUS 60
+typedef struct KDEventWindowFocus {
+ KDint32 focusstate;
+} KDEventWindowFocus;
+
+/* KD_EVENT_WINDOW_REDRAW: Event to notify need to redraw the window. */
+#define KD_EVENT_WINDOW_REDRAW 59
+#endif /* KD_WINDOW_SUPPORTED */
+
+/*******************************************************
+ * Assertions and logging
+ *******************************************************/
+
+/* kdHandleAssertion: Handle assertion failure. */
+KD_API void KD_APIENTRY kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber);
+
+/* kdLogMessage: Output a log message. */
+#ifdef KD_NDEBUG
+#define kdLogMessage(s)
+#else
+KD_API void KD_APIENTRY kdLogMessage(const KDchar *string);
+#endif
+
+/* struct KDEvent delayed to the end as it uses event data structs from
+ * other parts of the .h file. */
+struct KDEvent {
+ KDust timestamp;
+ KDint32 type;
+ void *userptr;
+ union KDEventData {
+ KDEventState state;
+ KDEventInput input;
+ KDEventInputJog inputjog;
+ KDEventInputPointer inputpointer;
+ KDEventInputStick inputstick;
+ KDEventSocketReadable socketreadable;
+ KDEventSocketWritable socketwritable;
+ KDEventSocketConnect socketconnect;
+ KDEventSocketIncoming socketincoming;
+ KDEventNameLookup namelookup;
+#ifdef KD_WINDOW_SUPPORTED
+ KDEventWindowProperty windowproperty;
+ KDEventWindowFocus windowfocus;
+#endif /* KD_WINDOW_SUPPORTED */
+ KDEventUser user;
+ } data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kd_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kdplatform.h b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kdplatform.h
new file mode 100644
index 00000000..3cf09f52
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs/KD/kdplatform.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* Sample KD/kdplatform.h for OpenKODE Core 1.0.3 */
+#ifndef __kdplatform_h_
+#define __kdplatform_h_
+
+#define KD_API
+#define KD_APIENTRY
+
+typedef int KDint32;
+typedef unsigned int KDuint32;
+typedef long long KDint64;
+typedef unsigned long long KDuint64;
+typedef short KDint16;
+typedef unsigned short KDuint16;
+typedef unsigned long KDuintptr;
+typedef unsigned long KDsize;
+typedef long KDssize;
+#define KDINT_MIN (-0x7fffffff-1)
+#define KDINT_MAX 0x7fffffff
+#define KDUINT_MAX 0xffffffffU
+#define KDINT64_MIN (-0x7fffffffffffffffLL-1)
+#define KDINT64_MAX 0x7fffffffffffffffLL
+#define KDUINT64_MAX 0xffffffffffffffffULL
+#define KDSSIZE_MIN (-0x7fffffff-1)
+#define KDSSIZE_MAX 0x7fffffff
+#define KDSIZE_MAX 0xffffffffU
+#define KDUINTPTR_MAX 0xffffffffU
+#define KD_NORETURN
+#define KD_WINDOW_SUPPORTED
+#ifdef KD_NDEBUG
+#define kdAssert(c)
+#else
+#define kdAssert(c) ((void)( (c) ? 0 : (kdHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+#define KD_INFINITY_BITS 0x7f800000u
+#define KD_INFINITY (kdBitsToFloatNV(KD_INFINITY_BITS))
+
+KD_API float KD_APIENTRY kdBitsToFloatNV(KDuint32 x);
+
+
+/** KHR_formatted extension */
+#include <stdarg.h>
+typedef va_list KDVaListKHR;
+
+// If there are problems with including stdarg.h here under any of the Windows
+// operating systems, we might want to change it back to using char* instead of
+// va_list
+//typedef char *KDVaListKHR;
+
+
+#define KD_VA_START_KHR(ap, parmN) \
+ do {ap = (KDVaListKHR)&parmN + sizeof(parmN);} while(0)
+
+#define KD_VA_ARG_CHAR_KHR(ap) (KDchar)va_arg(ap, KDint)
+#define KD_VA_ARG_CHARPTR_KHR(ap) (KDchar*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16_KHR(ap) (KDint16)va_arg(ap, KDint)
+#define KD_VA_ARG_INT32_KHR(ap) va_arg(ap, KDint32)
+#define KD_VA_ARG_INT_KHR(ap) va_arg(ap, KDint)
+#define KD_VA_ARG_INT64_KHR(ap) va_arg(ap, KDint64)
+#define KD_VA_ARG_INTPTR_KHR(ap) (KDint*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_INT16PTR_KHR(ap) (KDint16*)(KD_VA_ARG_PTR_KHR(ap))
+#define KD_VA_ARG_FLOAT32_KHR(ap) (KDfloat32)(va_arg(ap, double))
+#define KD_VA_ARG_PTR_KHR(ap) (void *)va_arg(ap, char *)
+
+#define KD_VA_END_KHR(ap) \
+ do {ap = (KDVaListKHR)0;} while(0)
+
+#endif /* __kdplatform_h_ */
+
diff --git a/src/3rdparty/RuntimePlatformSpecific/Windows/Qt3DSLibs/KD/MinKD.c b/src/3rdparty/RuntimePlatformSpecific/Windows/Qt3DSLibs/KD/MinKD.c
new file mode 100644
index 00000000..5124ec05
--- /dev/null
+++ b/src/3rdparty/RuntimePlatformSpecific/Windows/Qt3DSLibs/KD/MinKD.c
@@ -0,0 +1,330 @@
+#include "KD/kd.h"
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <memory.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <malloc.h>
+
+
+KDFile* kdFopen(const KDchar* pathname, const KDchar* mode)
+{
+ FILE* retval;
+ retval = fopen( pathname, mode );
+ return (KDFile*)retval;
+}
+
+
+KDsize kdFread(void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fread( buffer, size, count, (FILE*)file );
+}
+
+/* kdFwrite: Write to a file. */
+KDsize kdFwrite(const void *buffer, KDsize size, KDsize count, KDFile *file)
+{
+ return fwrite( buffer, size, count, (FILE*)file );
+}
+
+KDint kdFclose(KDFile *file)
+{
+ return fclose( (FILE*)file );
+}
+
+/* kdCosf: Cosine function. */
+KDfloat32 kdCosf(KDfloat32 x) { return cosf( x ); }
+
+/* kdSinf: Sine function. */
+KDfloat32 kdSinf(KDfloat32 x) { return sinf( x ); }
+
+KDfloat32 kdSqrtf(KDfloat32 x ) { return sqrtf( x ); }
+
+KDfloat32 kdTanf( KDfloat32 x ) { return tanf( x ); }
+
+KDint kdAbs(KDint i)
+{
+ return i < 0 ? -i : i;
+}
+
+
+KDfloat32 kdFabsf(KDfloat32 i) { return fabs( i ); }
+
+/* kdStrcpy_s: Copy a string with an overrun check. */
+
+KDint kdStrcpy_s(KDchar* buf, KDsize buflen, const KDchar* src)
+{
+ return kdStrncpy_s(buf, buflen, src, -1);
+}
+
+/* kdStrncpy_s: Copy a string with an overrun check. */
+KDint kdStrncpy_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srclen)
+{
+ const char* term;
+ if ( srclen == (KDsize)-1)
+ srclen = buflen;
+
+ term = (const char*)memchr(src, 0, srclen);
+ if (term)
+ srclen = term - src;
+ if (srclen >= buflen) {
+ if (buflen)
+ *buf = 0;
+ return KD_EINVAL;
+ }
+ memcpy(buf, src, srclen);
+ buf[srclen] = 0;
+ return 0;
+}
+
+/* kdStrncat_s: Concatenate two strings. */
+KDint kdStrncat_s(KDchar* buf, KDsize buflen, const KDchar* src, KDsize srcmaxlen)
+{
+ size_t origlen = strlen(buf);
+ const char* p = (const char*)memchr(src, 0, srcmaxlen);
+ if (p)
+ srcmaxlen = p - src;
+ if (origlen + srcmaxlen >= buflen)
+ {
+ /* spec says "buf[0] is set to 0". But that's bad if buflen == 0!
+ * kdStrncpy_s's spec is better here. */
+ if (buflen)
+ buf[0] = 0;
+ return KD_ERANGE;
+ }
+ memcpy(buf + origlen, src, srcmaxlen);
+ buf[origlen + srcmaxlen] = 0;
+ return 0;
+}
+/* kdMemset: Set bytes in memory to a value. */
+void* kdMemset(void *buf, KDint byte, KDsize len) { return memset( buf, byte, len ); }
+
+/* kdStrcmp: Compares two strings. */
+KDint kdStrcmp(const KDchar *str1, const KDchar *str2) { return strcmp( str1, str2); }
+
+/* kdStrlen: Determine the length of a string. */
+KDsize kdStrlen(const KDchar *str) { return strlen( str ); }
+
+void* kdMalloc( KDsize size ) { return malloc(size); }
+
+void kdFree( void* ptr ) { free( ptr ); }
+
+void* kdMemcpy(void *buf, const void *src, KDsize len) { return memcpy( buf, src, len ); }
+
+struct KDThreadMutex
+{
+ CRITICAL_SECTION p_mutex;
+};
+
+/* kdThreadMutexCreate: Create a mutex. */
+KD_API KDThreadMutex* kdThreadMutexCreate(const void *mutexattr)
+{
+ KDThreadMutex* mutex = (KDThreadMutex*)malloc(sizeof(KDThreadMutex));
+ if (mutex)
+ {
+ InitializeCriticalSection(&mutex->p_mutex);
+ return mutex;
+ }
+
+ return KD_NULL;
+}
+
+/* kdThreadMutexFree: Free a mutex. */
+KDint kdThreadMutexFree(KDThreadMutex *mutex)
+{
+ DeleteCriticalSection(&mutex->p_mutex);
+ free(mutex);
+ return 0;
+}
+
+/* kdThreadMutexLock: Lock a mutex. */
+KDint kdThreadMutexLock(KDThreadMutex *mutex)
+{
+ (void)EnterCriticalSection(&mutex->p_mutex);
+ return 0;
+}
+
+/* kdThreadMutexUnlock: Unlock a mutex. */
+KDint kdThreadMutexUnlock(KDThreadMutex *mutex)
+{
+ LeaveCriticalSection(&mutex->p_mutex);
+ return 0;
+}
+
+struct KDThreadAttr
+{
+ SECURITY_ATTRIBUTES p_attr;
+};
+
+typedef unsigned char uint8_t;
+typedef HANDLE pthread_t;
+
+struct KDThread
+{
+ HANDLE Handle;
+ uint8_t Detached;
+ uint8_t IsRunning;
+ INT UserThread;
+ void* (*UserThreadProc)(void*);
+ void* UserArg;
+};
+
+
+static DWORD WINAPI ThreadProc( __in LPVOID lpParameter )
+{
+ struct KDThread* threadPtr = (struct KDThread*)lpParameter;
+ return (DWORD)threadPtr->UserThreadProc( threadPtr->UserArg );
+}
+/* kdThreadCreate: Create a new thread. */
+KDThread * kdThreadCreate(const KDThreadAttr *attr, void *(*start_routine)(void *), void *arg)
+{
+ pthread_t thread;
+ int retval;
+ SECURITY_ATTRIBUTES* p_attr;
+ struct KDThread* newThread;
+ if ( attr )
+ p_attr = (const SECURITY_ATTRIBUTES*)( &attr->p_attr );
+ else
+ p_attr = KD_NULL;
+ newThread = (struct KDThread*) malloc( sizeof(struct KDThread ) );
+ if ( newThread == KD_NULL ) return KD_NULL;
+ newThread->Handle;
+ newThread->Detached = 0;
+ newThread->IsRunning = 1;
+ newThread->UserThreadProc = start_routine;
+ newThread->UserArg = arg;
+
+ newThread->Handle = CreateThread( p_attr, 0, ThreadProc, newThread, 0, &newThread->UserThread );
+ if ( newThread->Handle == 0 )
+ {
+ free( newThread );
+ return KD_NULL;
+ }
+ return newThread;
+}
+
+/* kdThreadExit: Terminate this thread. */
+void kdThreadExit(void *retval)
+{
+ ExitThread( (DWORD)retval );
+}
+
+/* kdThreadJoin: Wait for termination of another thread. */
+KDint kdThreadJoin(KDThread *thread, void **retval)
+{
+ WaitForSingleObject( thread->Handle, INFINITE );
+ CloseHandle( thread->Handle );
+ free( thread );
+ return 0;
+}
+
+typedef struct KDDirInternal {
+ WIN32_FIND_DATAA ffd;
+ HANDLE hFind;
+ KDDirent dirEnt;
+ char pathBuffer[MAX_PATH];
+} KDDirInternal;
+
+/* kdOpenDir: Open a directory ready for listing. */
+KDDir *kdOpenDir(const KDchar *pathname)
+{
+ KDDirInternal* retval = (KDDirInternal*)malloc( sizeof( KDDirInternal ));
+ if ( retval == NULL ) { return NULL; }
+
+ memset( retval, 0, sizeof( KDDirInternal ) );
+
+
+ retval->hFind = FindFirstFileA( pathname, &retval->ffd );
+
+ if ( retval->hFind ) { free(retval ); return KD_NULL; };
+ if ( retval == KD_NULL ) return KD_NULL;
+ memset( retval, 0, sizeof( *retval ) );
+ return (KDDir*)retval;
+}
+
+/* kdReadDir: Return the next file in a directory. */
+KDDirent* kdReadDir(KDDir *dir)
+{
+ KDDirInternal* theDir = (KDDirInternal *)dir;
+ INT success;
+ if ( *theDir->ffd.cFileName == 0
+ || theDir->hFind == INVALID_HANDLE_VALUE )
+ return NULL;
+
+ strcpy_s( theDir->pathBuffer, MAX_PATH, theDir->ffd.cFileName );
+ theDir->dirEnt.d_name = theDir->pathBuffer;
+
+ success = FindNextFile(theDir->hFind, &theDir->ffd);
+ if ( success == 0 )
+ theDir->ffd.cFileName[0] = 0;
+
+ return &theDir->dirEnt;
+}
+
+/* kdCloseDir: Close a directory. */
+KDint kdCloseDir(KDDir *dir)
+{
+ KDDirInternal* theDir = (KDDirInternal *)dir;
+ FindClose( theDir->hFind );
+ free(theDir);
+ return 0;
+}
+
+KDint kdSetWindowPropertyiv(KDWindow * win, KDint prop, const KDint32 * val)
+{
+ return 0;
+}
+
+void kdDefaultEvent(const KDEvent *event )
+{
+
+}
+
+typedef long long NvS64;
+
+//Stubbed and not implemented.
+
+KDust kdGetTimeUST(void)
+{
+ KDust retval;
+ memset( &retval, 0, sizeof( retval ) );
+ return retval;
+}
+
+/* kdGmtime_r, kdLocaltime_r: Convert a seconds-since-epoch time into broken-down time. */
+KDTm* kdGmtime_r(const KDtime* timep, KDTm* result)
+{
+ return NULL;
+}
+
+KDTm* kdLocaltime_r(const KDtime* timep, KDTm* result)
+{
+ return NULL;
+}
+
+//===========================================================================
+// kdCreateEvent: Create an event for posting.
+//===========================================================================
+KDEvent* kdCreateEvent(void)
+{
+ //Memory leak and there isn't much I am going to do about this now
+ KDEvent* newEvent = (KDEvent*)malloc( sizeof( KDEvent ));
+ memset( newEvent, 0, sizeof( KDEvent ));
+ return newEvent;
+}
+
+KDfloat32 kdInvsqrtf(KDfloat32 x)
+{
+ long i;
+ float x2, y;
+ const float threehalfs = 1.5F;
+
+ x2 = x * 0.5F;
+ y = x;
+ i = * ( long * ) &y; // evil floating point bit level hacking
+ i = 0x5f3759df - ( i >> 1 );
+ y = * ( float * ) &i;
+ y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
+
+ return y;
+}
diff --git a/src/3rdparty/color/CColor.cpp b/src/3rdparty/color/CColor.cpp
new file mode 100644
index 00000000..02e0ad3c
--- /dev/null
+++ b/src/3rdparty/color/CColor.cpp
@@ -0,0 +1,722 @@
+/****************************************************************************\
+Datei : Color.cpp
+Projekt: Farbverwaltung
+Inhalt : CColor Implementierung
+Datum : 10.01.1999
+Autor : Christian Rodemeyer
+Hinweis: (c) 1999 by Christian Rodemeyer
+ Info �ber HLS Konvertierungsfunktion
+ - Foley and Van Dam: "Fundamentals of Interactive Computer Graphics"
+ - MSDN: 'HLS Color Spaces'
+ - MSDN: 'Converting Colors Between RGB and HLS'
+\****************************************************************************/
+#include "stdafx.h"
+
+#include "CColor.h"
+#include <math.h>
+#include <assert.h>
+
+float GetMin( float in1, float in2 );
+float GetMin( float in1, float in2 )
+{
+ return ( in1 < in2 ) ? in1 : in2;
+}
+
+float GetMax( float in1, float in2 );
+float GetMax( float in1, float in2 )
+{
+ return ( in1 > in2 ) ? in1 : in2;
+}
+
+/****************************************************************************\
+ CColor: Implementierung
+\****************************************************************************/
+const CColor::DNamedColor CColor::m_namedColor[CColor::numNamedColors] =
+{
+ {aliceblue , "aliceblue"},
+ {antiquewhite , "antiquewhite"},
+ {aqua , "aqua"},
+ {aquamarine , "aquamarine"},
+ {azure , "azure"},
+ {beige , "beige"},
+ {bisque , "bisque"},
+ {black , "black"},
+ {blanchedalmond , "blanchedalmond"},
+ {blue , "blue"},
+ {blueviolet , "blueviolet"},
+ {brown , "brown"},
+ {burlywood , "burlywood"},
+ {cadetblue , "cadetblue"},
+ {chartreuse , "chartreuse"},
+ {chocolate , "chocolate"},
+ {coral , "coral"},
+ {cornflower , "cornflower"},
+ {cornsilk , "cornsilk"},
+ {crimson , "crimson"},
+ {cyan , "cyan"},
+ {darkblue , "darkblue"},
+ {darkcyan , "darkcyan"},
+ {darkgoldenrod , "darkgoldenrod"},
+ {darkgray , "darkgray"},
+ {darkgreen , "darkgreen"},
+ {darkkhaki , "darkkhaki"},
+ {darkmagenta , "darkmagenta"},
+ {darkolivegreen , "darkolivegreen"},
+ {darkorange , "darkorange"},
+ {darkorchid , "darkorchid"},
+ {darkred , "darkred"},
+ {darksalmon , "darksalmon"},
+ {darkseagreen , "darkseagreen"},
+ {darkslateblue , "darkslateblue"},
+ {darkslategray , "darkslategray"},
+ {darkturquoise , "darkturquoise"},
+ {darkviolet , "darkviolet"},
+ {deeppink , "deeppink"},
+ {deepskyblue , "deepskyblue"},
+ {dimgray , "dimgray"},
+ {dodgerblue , "dodgerblue"},
+ {firebrick , "firebrick"},
+ {floralwhite , "floralwhite"},
+ {forestgreen , "forestgreen"},
+ {fuchsia , "fuchsia"},
+ {gainsboro , "gainsboro"},
+ {ghostwhite , "ghostwhite"},
+ {gold , "gold"},
+ {goldenrod , "goldenrod"},
+ {gray , "gray"},
+ {green , "green"},
+ {greenyellow , "greenyellow"},
+ {honeydew , "honeydew"},
+ {hotpink , "hotpink"},
+ {indianred , "indianred"},
+ {indigo , "indigo"},
+ {ivory , "ivory"},
+ {khaki , "khaki"},
+ {lavender , "lavender"},
+ {lavenderblush , "lavenderblush"},
+ {lawngreen , "lawngreen"},
+ {lemonchiffon , "lemonchiffon"},
+ {lightblue , "lightblue"},
+ {lightcoral , "lightcoral"},
+ {lightcyan , "lightcyan"},
+ {lightgoldenrodyellow , "lightgoldenrodyellow"},
+ {lightgreen , "lightgreen"},
+ {lightgrey , "lightgrey"},
+ {lightpink , "lightpink"},
+ {lightsalmon , "lightsalmon"},
+ {lightseagreen , "lightseagreen"},
+ {lightskyblue , "lightskyblue"},
+ {lightslategray , "lightslategray"},
+ {lightsteelblue , "lightsteelblue"},
+ {lightyellow , "lightyellow"},
+ {lime , "lime"},
+ {limegreen , "limegreen"},
+ {linen , "linen"},
+ {magenta , "magenta"},
+ {maroon , "maroon"},
+ {mediumaquamarine , "mediumaquamarine"},
+ {mediumblue , "mediumblue"},
+ {mediumorchid , "mediumorchid"},
+ {mediumpurple , "mediumpurple"},
+ {mediumseagreen , "mediumseagreen"},
+ {mediumslateblue , "mediumslateblue"},
+ {mediumspringgreen , "mediumspringgreen"},
+ {mediumturquoise , "mediumturquoise"},
+ {mediumvioletred , "mediumvioletred"},
+ {midnightblue , "midnightblue"},
+ {mintcream , "mintcream"},
+ {mistyrose , "mistyrose"},
+ {moccasin , "moccasin"},
+ {navajowhite , "navajowhite"},
+ {navy , "navy"},
+ {oldlace , "oldlace"},
+ {olive , "olive"},
+ {olivedrab , "olivedrab"},
+ {orange , "orange"},
+ {orangered , "orangered"},
+ {orchid , "orchid"},
+ {palegoldenrod , "palegoldenrod"},
+ {palegreen , "palegreen"},
+ {paleturquoise , "paleturquoise"},
+ {palevioletred , "palevioletred"},
+ {papayawhip , "papayawhip"},
+ {peachpuff , "peachpuff"},
+ {peru , "peru"},
+ {pink , "pink"},
+ {plum , "plum"},
+ {powderblue , "powderblue"},
+ {purple , "purple"},
+ {red , "red"},
+ {rosybrown , "rosybrown"},
+ {royalblue , "royalblue"},
+ {saddlebrown , "saddlebrown"},
+ {salmon , "salmon"},
+ {sandybrown , "sandybrown"},
+ {seagreen , "seagreen"},
+ {seashell , "seashell"},
+ {sienna , "sienna"},
+ {silver , "silver"},
+ {skyblue , "skyblue"},
+ {slateblue , "slateblue"},
+ {slategray , "slategray"},
+ {snow , "snow"},
+ {springgreen , "springgreen"},
+ {steelblue , "steelblue"},
+ {tan , "tan"},
+ {teal , "teal"},
+ {thistle , "thistle"},
+ {tomato , "tomato"},
+ {turquoise , "turquoise"},
+ {violet , "violet"},
+ {wheat , "wheat"},
+ {white , "white"},
+ {whitesmoke , "whitesmoke"},
+ {yellow , "yellow"},
+ {yellowgreen , "yellowgreen"}
+};
+
+const char* CColor::GetNameFromIndex(int i)
+{
+ assert(0 <= i && i < numNamedColors);
+
+ return m_namedColor[i].name;
+}
+
+CColor CColor::GetColorFromIndex(int i)
+{
+ if ( i < 0 ) i = 0;
+ else if ( i >= numNamedColors ) i = numNamedColors - 1;
+
+ return m_namedColor[i].color;
+}
+
+CColor CColor::FromString(const char* pcColor)
+{
+ CColor t( 0, 0, 0) ;
+ t.SetString(pcColor);
+
+ return t;
+}
+
+CColor::CColor(COLORTYPE cr) :
+ m_colorref(cr),
+ m_hue( 0.0 ),
+ m_saturation( 0.0 ),
+ m_luminance( 0.0 ),
+ m_bIsRGB(true),
+ m_bIsHLS(false)
+{
+}
+
+CColor::CColor(const QColor &c) :
+ CColor(c.red(), c.green(), c.blue())
+{
+}
+
+CColor::operator COLORTYPE() const
+{
+ return RGB( GetRed( ), GetGreen( ), GetBlue( ) );
+}
+
+CColor::operator QColor() const
+{
+ return QColor( GetRed( ), GetGreen( ), GetBlue( ) );
+}
+
+// RGB
+
+void CColor::SetColor(COLORTYPE color)
+{
+ this->SetRGB(GetRValue(color), GetGValue(color), GetBValue(color));
+}
+
+CColor::CColor( int red, int green, int blue ):
+ m_hue( 0.0 ),
+ m_saturation( 0.0 ),
+ m_luminance( 0.0 ),
+ m_bIsRGB( true ),
+ m_bIsHLS( false )
+{
+ this->SetRGB( red, green, blue );
+}
+
+void CColor::SetRed(int red)
+{
+ red &= 0xFF;
+
+ ToRGB();
+ m_color[c_red] = static_cast<unsigned char>(red);
+ m_bIsHLS = false;
+}
+
+void CColor::SetGreen(int green)
+{
+ green &= 0xFF;
+
+ ToRGB();
+ m_color[c_green] = static_cast<unsigned char>(green);
+ m_bIsHLS = false;
+}
+
+void CColor::SetBlue(int blue)
+{
+ blue &= 0xFF;
+
+ ToRGB();
+ m_color[c_blue] = static_cast<unsigned char>(blue);
+ m_bIsHLS = false;
+}
+
+void CColor::SetRGB(int red, int green, int blue)
+{
+ red &= 0xFF;
+ blue &= 0xFF;
+ green &= 0xFF;
+
+ m_color[c_red] = static_cast<unsigned char>(red);
+ m_color[c_green] = static_cast<unsigned char>(green);
+ m_color[c_blue] = static_cast<unsigned char>(blue);
+ m_bIsHLS = false;
+ m_bIsRGB = true;
+}
+
+unsigned int CColor::GetRed() const
+{
+ const_cast<CColor*>(this)->ToRGB();
+
+ return m_color[c_red];
+}
+
+unsigned int CColor::GetGreen() const
+{
+ const_cast<CColor*>(this)->ToRGB();
+
+ return m_color[c_green];
+}
+
+unsigned int CColor::GetBlue() const
+{
+ const_cast<CColor*>(this)->ToRGB();
+
+ return m_color[c_blue];
+}
+
+COLORTYPE CColor::GetRGBColor()
+{
+ const_cast<CColor*>(this)->ToRGB();
+
+ return (RGB(m_color[c_red], m_color[c_green], m_color[c_blue])) ;
+}
+
+// HSL
+
+void CColor::SetHue(float hue)
+{
+ if ( hue < 0 ) hue = 0;
+ else if ( hue > 360 ) hue = 360;
+
+ ToHLS();
+ m_hue = hue;
+ m_bIsRGB = false;
+}
+
+void CColor::SetSaturation(float saturation)
+{
+ if ( saturation < 0 ) saturation = 0;
+ else if ( saturation > 1 ) saturation = 1;
+
+ ToHLS();
+ m_saturation = saturation;
+ m_bIsRGB = false;
+}
+
+void CColor::SetLuminance(float luminance)
+{
+ if ( luminance < 0 ) luminance = 0;
+ else if ( luminance > 1 ) luminance = 1;
+
+ ToHLS();
+ m_luminance = luminance;
+ m_bIsRGB = false;
+}
+
+void CColor::SetHLS(float hue, float luminance, float saturation)
+{
+ if ( hue < 0 ) hue = 0;
+ else if ( hue > 360 ) hue = 360;
+ if ( saturation < 0 ) saturation = 0;
+ else if ( saturation > 1 ) saturation = 1;
+ if ( luminance < 0 ) luminance = 0;
+ else if ( luminance > 1 ) luminance = 1;
+
+ m_hue = hue;
+ m_luminance = luminance;
+ m_saturation = saturation;
+ m_bIsRGB = false;
+ m_bIsHLS = true;
+}
+
+float CColor::GetHue() const
+{
+ const_cast<CColor*>(this)->ToHLS();
+
+ return m_hue;
+}
+
+float CColor::GetSaturation() const
+{
+ const_cast<CColor*>(this)->ToHLS();
+
+ return m_saturation;
+}
+
+float CColor::GetLuminance() const
+{
+ const_cast<CColor*>(this)->ToHLS();
+
+ return m_luminance;
+}
+
+// Konvertierung
+
+void CColor::ToHLS()
+{
+ if (!m_bIsHLS)
+ {
+ // Konvertierung
+ unsigned char minval = static_cast<unsigned char>( GetMin(m_color[c_red], GetMin(m_color[c_green], m_color[c_blue])) );
+ unsigned char maxval = static_cast<unsigned char>( GetMax(m_color[c_red], GetMax(m_color[c_green], m_color[c_blue])) );
+ float mdiff = float(maxval) - float(minval);
+ float msum = float(maxval) + float(minval);
+
+ m_luminance = msum / 510.0f;
+
+ if (maxval == minval)
+ {
+ m_saturation = 0.0f;
+ m_hue = 0.0f;
+ }
+ else
+ {
+ float rnorm = (maxval - m_color[c_red] ) / mdiff;
+ float gnorm = (maxval - m_color[c_green]) / mdiff;
+ float bnorm = (maxval - m_color[c_blue] ) / mdiff;
+
+ m_saturation = (m_luminance <= 0.5f) ? (mdiff / msum) : (mdiff / (510.0f - msum));
+
+ if (m_color[c_red] == maxval)
+ m_hue = 60.0f * (6.0f + bnorm - gnorm);
+
+ if (m_color[c_green] == maxval)
+ m_hue = 60.0f * (2.0f + rnorm - bnorm);
+
+ if (m_color[c_blue] == maxval)
+ m_hue = 60.0f * (4.0f + gnorm - rnorm);
+
+ if (m_hue > 360.0f)
+ m_hue = m_hue - 360.0f;
+ }
+
+ m_bIsHLS = true;
+ }
+}
+
+void CColor::ToRGB()
+{
+ if (!m_bIsRGB)
+ {
+ if (m_saturation == 0.0) // Grauton, einfacher Fall
+ {
+ m_color[c_red] = m_color[c_green] = m_color[c_blue] = (unsigned char)(m_luminance * 255.0);
+ }
+ else
+ {
+ float rm1, rm2;
+
+ if (m_luminance <= 0.5f)
+ rm2 = m_luminance + m_luminance * m_saturation;
+ else
+ rm2 = m_luminance + m_saturation - m_luminance * m_saturation;
+
+ rm1 = 2.0f * m_luminance - rm2;
+ m_color[c_red] = ToRGB1(rm1, rm2, m_hue + 120.0f);
+ m_color[c_green] = ToRGB1(rm1, rm2, m_hue);
+ m_color[c_blue] = ToRGB1(rm1, rm2, m_hue - 120.0f);
+ }
+
+ m_bIsRGB = true;
+ }
+}
+
+unsigned char CColor::ToRGB1(float rm1, float rm2, float rh)
+{
+ if (rh > 360.0f)
+ rh -= 360.0f;
+ else
+ if (rh < 0.0f)
+ rh += 360.0f;
+
+ if (rh < 60.0f)
+ rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;
+ else
+ if (rh < 180.0f)
+ rm1 = rm2;
+ else
+ if (rh < 240.0f)
+ rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f;
+
+ return static_cast<unsigned char>(rm1 * 255);
+}
+
+// Stringkonvertierung im Format RRGGBB
+
+Q3DStudio::CString CColor::GetString() const
+{
+ Q3DStudio::CString color;
+ color.Format( _UIC( "%02X%02X%02X" ), GetRed(), GetGreen(), GetBlue());
+
+ return color;
+}
+
+bool CColor::SetString( const char* pcColor)
+{
+ int r, g, b;
+ bool bRet = false;
+
+ if (sscanf(pcColor, "%2x%2x%2x", &r, &g, &b) != 3)
+ {
+ m_color[c_red] = m_color[c_green] = m_color[c_blue] = 0;
+ }
+ else
+ {
+ m_color[c_red] = static_cast<unsigned char>(r);
+ m_color[c_green] = static_cast<unsigned char>(g);
+ m_color[c_blue] = static_cast<unsigned char>(b);
+ m_bIsRGB = true;
+ m_bIsHLS = false;
+ bRet = true;
+ }
+
+ return (bRet) ;
+}
+
+Q3DStudio::CString CColor::GetName() const
+{
+ Q3DStudio::CString theRetStr;
+
+ const_cast<CColor*>(this)->ToRGB();
+ int i = numNamedColors;
+ while (i-- && m_colorref != m_namedColor[i].color) { }
+ if (i < 0)
+ {
+ theRetStr = L"#" + GetString();
+ }
+ else
+ theRetStr = m_namedColor[i].name;
+
+ return (theRetStr);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// global functions
+/////////////////////////////////////////////////////////////////////////////
+
+COLORTYPE GetHueColor(int iHue)
+{
+ COLORTYPE theHueColor ;
+ unsigned char r, g, b;
+
+ HSVToRGB( r, g, b, (float) iHue, 1.0f, 1.0f );
+
+ theHueColor = RGB( r, g, b );
+
+ return (theHueColor) ;
+}
+
+// r,g,b values are from 0 to 1
+// h = [0,360], s = [0,1], v = [0,1]
+// if s == 0, then h = -1 (undefined)
+
+void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )
+{
+ float min, max, delta;
+
+ min = GetMin( GetMin( r, g ), b );
+ max = GetMax( GetMax( r, g ), b );
+ *v = max; // v
+ delta = max - min;
+ if ( max != 0 )
+ *s = delta / max; // s
+ else
+ {
+ // r = g = b = 0 // s = 0, v is undefined
+ *s = 0;
+ *h = -1;
+ return;
+ }
+ if ( r == max )
+ *h = ( g - b ) / delta; // between yellow & magenta
+ else
+ if( g == max )
+ *h = 2 + ( b - r ) / delta; // between cyan & yellow
+ else
+ *h = 4 + ( r - g ) / delta; // between magenta & cyan
+ *h *= 60; // degrees
+ if ( *h < 0 )
+ *h += 360;
+}
+
+void RGBToHSV( unsigned char r, unsigned char g, unsigned char b, float* h, float* s, float* v )
+{
+ // Convert an RGB to HSV
+
+ float fRed, fGreen, fBlue;
+
+ // convert 0-255 values to 0-1 range
+ fRed = ( ( float ) r ) / 255.0f;
+ fGreen = ( ( float ) g ) / 255.0f;
+ fBlue = ( ( float ) b ) / 255.0f;
+
+ RGBtoHSV( fRed, fGreen, fBlue, h, s, v );
+}
+
+void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
+{
+ int i;
+ float f, p, q, t;
+
+ if ( s == 0 )
+ {
+ // achromatic (grey)
+ *r = *g = *b = v;
+ return;
+ }
+
+ h /= 60; // sector 0 to 5
+ i = ( int ) floor( h );
+ f = h - i; // factorial part of h
+ p = v * ( 1 - s );
+ q = v * ( 1 - s * f );
+ t = v * ( 1 - s * ( 1 - f ) );
+
+ switch( i )
+ {
+ case 0:
+ *r = v;
+ *g = t;
+ *b = p;
+ break;
+
+ case 1:
+ *r = q;
+ *g = v;
+ *b = p;
+ break;
+
+ case 2:
+ *r = p;
+ *g = v;
+ *b = t;
+ break;
+
+ case 3:
+ *r = p;
+ *g = q;
+ *b = v;
+ break;
+
+ case 4:
+ *r = t;
+ *g = p;
+ *b = v;
+ break;
+
+ default: // case 5:
+ *r = v;
+ *g = p;
+ *b = q;
+ break;
+ }
+}
+
+void HSVToRGB( unsigned char& r, unsigned char& g, unsigned char& b, float h, float s, float v )
+{
+ // Convert an HSV to RGB
+
+ float fRed, fGreen, fBlue;
+
+ HSVtoRGB( &fRed, &fGreen, &fBlue, h, s, v );
+
+ r = ( unsigned char ) ( fRed * 255.0f );
+ g = ( unsigned char ) ( fGreen * 255.0f );
+ b = ( unsigned char ) ( fBlue * 255.0f );
+}
+
+short GetHueValue( COLORTYPE inColor )
+{
+ float theHue, theSaturation, theBright;
+ short theHueValue;
+
+ RGBToHSV( GetRValue( inColor ), GetGValue( inColor ), GetBValue( inColor ), &theHue, &theSaturation, &theBright );
+
+ theHueValue = ( short ) theHue;
+
+ return theHueValue;
+}
+
+short GetSaturationValue( COLORTYPE inColor )
+{
+ float theHue, theSaturation, theBright;
+ short theSaturationValue;
+
+ RGBToHSV( GetRValue( inColor ), GetGValue( inColor ), GetBValue( inColor ), &theHue, &theSaturation, &theBright );
+
+ theSaturationValue = ( short ) ( theSaturation * 255.0f );
+
+ return theSaturationValue;
+}
+
+short GetBrightnessValue( COLORTYPE inColor )
+{
+ float theHue, theSaturation, theBright;
+ short theBrightnessValue;
+
+ RGBToHSV( GetRValue( inColor ), GetGValue( inColor ), GetBValue( inColor ), &theHue, &theSaturation, &theBright );
+
+ theBrightnessValue = ( short ) ( theBright * 255.0f );
+
+ return theBrightnessValue;
+}
+
+CColor CColor::GetFractionalColor( long inIndex, long inCount )
+{
+ double theE = .2;
+ double theRCenter = 1.0 / 6;
+ double theGCenter = 3.0 / 6;
+ double theBCenter = 5.0 / 6;
+ double theRCenter2 = 7.0 / 6;
+ double theBCenter2 = -1.0 / 6;
+
+ double theInv2eSquare = -1.0 / ( 2 * theE * theE );
+ double theMag = 60 / theE;
+
+ double thePos = (double)inIndex / inCount;
+ double theR = theMag * exp( ( thePos - theRCenter ) * ( thePos - theRCenter ) * theInv2eSquare );
+ double theG = theMag * exp( ( thePos - theGCenter ) * ( thePos - theGCenter ) * theInv2eSquare );
+ double theB = theMag * exp( ( thePos - theBCenter ) * ( thePos - theBCenter ) * theInv2eSquare );
+
+ double theR2 = theMag * exp( ( thePos - theRCenter2 ) * ( thePos - theRCenter2 ) * theInv2eSquare );
+ double theB2 = theMag * exp( ( thePos - theBCenter2 ) * ( thePos - theBCenter2 ) * theInv2eSquare );
+
+ theR += theR2;
+ theB += theB2;
+
+ return CColor( (char)( theR + .5 ), (char)( theG + .5 ), (char)( theB + .5 ) );
+}
+
+QColor CColor::getQColor() const
+{
+ const_cast<CColor *>(this)->ToRGB();
+
+ return QColor(m_color[c_red], m_color[c_green], m_color[c_blue]);
+}
diff --git a/src/3rdparty/color/CColor.h b/src/3rdparty/color/CColor.h
new file mode 100644
index 00000000..2009e52f
--- /dev/null
+++ b/src/3rdparty/color/CColor.h
@@ -0,0 +1,298 @@
+/****************************************************************************\
+Datei : Color.h
+Projekt: Farbverwaltung
+Inhalt : CColor Deklaration
+Datum : 10.01.1999
+Autor : Christian Rodemeyer
+Hinweis: (c) 1999 by Christian Rodemeyer
+\****************************************************************************/
+#pragma once
+
+#ifndef INCLUDED_COLOR_H
+#define INCLUDED_COLOR_H
+
+/****************************************************************************\
+ CColor: Repr�sentiert einen Farbwert
+\****************************************************************************/
+
+typedef unsigned long COLORTYPE;
+
+#include "UICString.h"
+#include <QColor>
+
+class CColor
+{
+public:
+
+ // COLORREF Konvertierung
+ // ----------------------
+ CColor( COLORTYPE cr = 0 );
+ CColor( int red, int green, int blue );
+ CColor( const QColor& c );
+ operator COLORTYPE() const;
+
+ operator QColor() const;
+
+ // RGB - Routinen
+ // --------------
+ void SetRed(int red); // 0..255
+ void SetGreen(int green); // 0..255
+ void SetBlue(int blue); // 0..255
+ void SetRGB(int red, int green, int blue);
+ void SetColor(COLORTYPE color);
+
+ unsigned int GetRed() const; // 0..255
+ unsigned int GetGreen() const; // 0..255
+ unsigned int GetBlue() const; // 0..255
+ COLORTYPE GetRGBColor();
+
+ // HLS - Routinen
+ // --------------
+ void SetHue(float hue); // 0.0 .. 360.0
+ void SetLuminance(float luminance); // 0.0 .. 1.0
+ void SetSaturation(float saturation); // 0.0 .. 1.0
+ void SetHLS(float hue, float luminance, float saturation);
+
+ float GetHue() const; // 0.0 .. 360.0
+ float GetLuminance() const; // 0.0 .. 1.0
+ float GetSaturation() const; // 0.0 .. 1.0
+
+ // String Konvertierung
+ // ---------------------
+ Q3DStudio::CString GetString() const; // Liefert String im Format RRGGBB
+ bool SetString( const char* pcColor); // Erwartet String im Format RRGGBB
+ QColor getQColor() const;
+
+ // Benannte Web Farben
+ // -------------------
+ Q3DStudio::CString GetName() const; // Liefert String mit benannter Farbe oder #RRGGBB falls kein Name bekannt
+
+ static CColor FromString( const char* pcColor);
+ static const char* GetNameFromIndex(int i);
+ static CColor GetColorFromIndex(int i);
+ static int GetNumNames() {return numNamedColors;}
+ static CColor GetFractionalColor( long inIndex, long inCount );
+
+ enum ENamedColor // Named Colors, could be used as COLORREF
+ {
+ none = 0x7FFFFFFF, // keine Farbe
+ aliceblue = 0x00FFF8F0, // RGB(0xF0, 0xF8, 0xFF)
+ antiquewhite = 0x00D7EBFA, // RGB(0xFA, 0xEB, 0xD7)
+ aqua = 0x00FFFF00, // RGB(0x00, 0xFF, 0xFF)
+ aquamarine = 0x00D4FF7F, // RGB(0x7F, 0xFF, 0xD4)
+ azure = 0x00FFFFF0, // RGB(0xF0, 0xFF, 0xFF)
+ beige = 0x00DCF5F5, // RGB(0xF5, 0xF5, 0xDC)
+ bisque = 0x00C4E4FF, // RGB(0xFF, 0xE4, 0xC4)
+ black = 0x00000000, // RGB(0x00, 0x00, 0x00)
+ blanchedalmond = 0x00CDEBFF, // RGB(0xFF, 0xEB, 0xCD)
+ blue = 0x00FF0000, // RGB(0x00, 0x00, 0xFF)
+ blueviolet = 0x00E22B8A, // RGB(0x8A, 0x2B, 0xE2)
+ brown = 0x002A2AA5, // RGB(0xA5, 0x2A, 0x2A)
+ burlywood = 0x0087B8DE, // RGB(0xDE, 0xB8, 0x87)
+ cadetblue = 0x00A09E5F, // RGB(0x5F, 0x9E, 0xA0)
+ chartreuse = 0x0000FF7F, // RGB(0x7F, 0xFF, 0x00)
+ chocolate = 0x001E69D2, // RGB(0xD2, 0x69, 0x1E)
+ coral = 0x00507FFF, // RGB(0xFF, 0x7F, 0x50)
+ cornflower = 0x00ED9564, // RGB(0x64, 0x95, 0xED)
+ cornsilk = 0x00DCF8FF, // RGB(0xFF, 0xF8, 0xDC)
+ crimson = 0x003C14DC, // RGB(0xDC, 0x14, 0x3C)
+ cyan = 0x00FFFF00, // RGB(0x00, 0xFF, 0xFF)
+ darkblue = 0x008B0000, // RGB(0x00, 0x00, 0x8B)
+ darkcyan = 0x008B8B00, // RGB(0x00, 0x8B, 0x8B)
+ darkgoldenrod = 0x000B86B8, // RGB(0xB8, 0x86, 0x0B)
+ darkgray = 0x00A9A9A9, // RGB(0xA9, 0xA9, 0xA9)
+ darkgreen = 0x00006400, // RGB(0x00, 0x64, 0x00)
+ darkkhaki = 0x006BB7BD, // RGB(0xBD, 0xB7, 0x6B)
+ darkmagenta = 0x008B008B, // RGB(0x8B, 0x00, 0x8B)
+ darkolivegreen = 0x002F6B55, // RGB(0x55, 0x6B, 0x2F)
+ darkorange = 0x00008CFF, // RGB(0xFF, 0x8C, 0x00)
+ darkorchid = 0x00CC3299, // RGB(0x99, 0x32, 0xCC)
+ darkred = 0x0000008B, // RGB(0x8B, 0x00, 0x00)
+ darksalmon = 0x007A96E9, // RGB(0xE9, 0x96, 0x7A)
+ darkseagreen = 0x008BBC8F, // RGB(0x8F, 0xBC, 0x8B)
+ darkslateblue = 0x008B3D48, // RGB(0x48, 0x3D, 0x8B)
+ darkslategray = 0x004F4F2F, // RGB(0x2F, 0x4F, 0x4F)
+ darkturquoise = 0x00D1CE00, // RGB(0x00, 0xCE, 0xD1)
+ darkviolet = 0x00D30094, // RGB(0x94, 0x00, 0xD3)
+ deeppink = 0x009314FF, // RGB(0xFF, 0x14, 0x93)
+ deepskyblue = 0x00FFBF00, // RGB(0x00, 0xBF, 0xFF)
+ dimgray = 0x00696969, // RGB(0x69, 0x69, 0x69)
+ dodgerblue = 0x00FF901E, // RGB(0x1E, 0x90, 0xFF)
+ firebrick = 0x002222B2, // RGB(0xB2, 0x22, 0x22)
+ floralwhite = 0x00F0FAFF, // RGB(0xFF, 0xFA, 0xF0)
+ forestgreen = 0x00228B22, // RGB(0x22, 0x8B, 0x22)
+ fuchsia = 0x00FF00FF, // RGB(0xFF, 0x00, 0xFF)
+ gainsboro = 0x00DCDCDC, // RGB(0xDC, 0xDC, 0xDC)
+ ghostwhite = 0x00FFF8F8, // RGB(0xF8, 0xF8, 0xFF)
+ gold = 0x0000D7FF, // RGB(0xFF, 0xD7, 0x00)
+ goldenrod = 0x0020A5DA, // RGB(0xDA, 0xA5, 0x20)
+ gray = 0x00808080, // RGB(0x80, 0x80, 0x80)
+ green = 0x00008000, // RGB(0x00, 0x80, 0x00)
+ greenyellow = 0x002FFFAD, // RGB(0xAD, 0xFF, 0x2F)
+ honeydew = 0x00F0FFF0, // RGB(0xF0, 0xFF, 0xF0)
+ hotpink = 0x00B469FF, // RGB(0xFF, 0x69, 0xB4)
+ indianred = 0x005C5CCD, // RGB(0xCD, 0x5C, 0x5C)
+ indigo = 0x0082004B, // RGB(0x4B, 0x00, 0x82)
+ ivory = 0x00F0FFFF, // RGB(0xFF, 0xFF, 0xF0)
+ khaki = 0x008CE6F0, // RGB(0xF0, 0xE6, 0x8C)
+ lavender = 0x00FAE6E6, // RGB(0xE6, 0xE6, 0xFA)
+ lavenderblush = 0x00F5F0FF, // RGB(0xFF, 0xF0, 0xF5)
+ lawngreen = 0x0000FC7C, // RGB(0x7C, 0xFC, 0x00)
+ lemonchiffon = 0x00CDFAFF, // RGB(0xFF, 0xFA, 0xCD)
+ lightblue = 0x00E6D8AD, // RGB(0xAD, 0xD8, 0xE6)
+ lightcoral = 0x008080F0, // RGB(0xF0, 0x80, 0x80)
+ lightcyan = 0x00FFFFE0, // RGB(0xE0, 0xFF, 0xFF)
+ lightgoldenrodyellow = 0x00D2FAFA, // RGB(0xFA, 0xFA, 0xD2)
+ lightgreen = 0x0090EE90, // RGB(0x90, 0xEE, 0x90)
+ lightgrey = 0x00D3D3D3, // RGB(0xD3, 0xD3, 0xD3)
+ lightpink = 0x00C1B6FF, // RGB(0xFF, 0xB6, 0xC1)
+ lightsalmon = 0x007AA0FF, // RGB(0xFF, 0xA0, 0x7A)
+ lightseagreen = 0x00AAB220, // RGB(0x20, 0xB2, 0xAA)
+ lightskyblue = 0x00FACE87, // RGB(0x87, 0xCE, 0xFA)
+ lightslategray = 0x00998877, // RGB(0x77, 0x88, 0x99)
+ lightsteelblue = 0x00DEC4B0, // RGB(0xB0, 0xC4, 0xDE)
+ lightyellow = 0x00E0FFFF, // RGB(0xFF, 0xFF, 0xE0)
+ lime = 0x0000FF00, // RGB(0x00, 0xFF, 0x00)
+ limegreen = 0x0032CD32, // RGB(0x32, 0xCD, 0x32)
+ linen = 0x00E6F0FA, // RGB(0xFA, 0xF0, 0xE6)
+ magenta = 0x00FF00FF, // RGB(0xFF, 0x00, 0xFF)
+ maroon = 0x00000080, // RGB(0x80, 0x00, 0x00)
+ mediumaquamarine = 0x00AACD66, // RGB(0x66, 0xCD, 0xAA)
+ mediumblue = 0x00CD0000, // RGB(0x00, 0x00, 0xCD)
+ mediumorchid = 0x00D355BA, // RGB(0xBA, 0x55, 0xD3)
+ mediumpurple = 0x00DB7093, // RGB(0x93, 0x70, 0xDB)
+ mediumseagreen = 0x0071B33C, // RGB(0x3C, 0xB3, 0x71)
+ mediumslateblue = 0x00EE687B, // RGB(0x7B, 0x68, 0xEE)
+ mediumspringgreen = 0x009AFA00, // RGB(0x00, 0xFA, 0x9A)
+ mediumturquoise = 0x00CCD148, // RGB(0x48, 0xD1, 0xCC)
+ mediumvioletred = 0x008515C7, // RGB(0xC7, 0x15, 0x85)
+ midnightblue = 0x00701919, // RGB(0x19, 0x19, 0x70)
+ mintcream = 0x00FAFFF5, // RGB(0xF5, 0xFF, 0xFA)
+ mistyrose = 0x00E1E4FF, // RGB(0xFF, 0xE4, 0xE1)
+ moccasin = 0x00B5E4FF, // RGB(0xFF, 0xE4, 0xB5)
+ navajowhite = 0x00ADDEFF, // RGB(0xFF, 0xDE, 0xAD)
+ navy = 0x00800000, // RGB(0x00, 0x00, 0x80)
+ oldlace = 0x00E6F5FD, // RGB(0xFD, 0xF5, 0xE6)
+ olive = 0x00008080, // RGB(0x80, 0x80, 0x00)
+ olivedrab = 0x00238E6B, // RGB(0x6B, 0x8E, 0x23)
+ orange = 0x0000A5FF, // RGB(0xFF, 0xA5, 0x00)
+ orangered = 0x000045FF, // RGB(0xFF, 0x45, 0x00)
+ orchid = 0x00D670DA, // RGB(0xDA, 0x70, 0xD6)
+ palegoldenrod = 0x00AAE8EE, // RGB(0xEE, 0xE8, 0xAA)
+ palegreen = 0x0098FB98, // RGB(0x98, 0xFB, 0x98)
+ paleturquoise = 0x00EEEEAF, // RGB(0xAF, 0xEE, 0xEE)
+ palevioletred = 0x009370DB, // RGB(0xDB, 0x70, 0x93)
+ papayawhip = 0x00D5EFFF, // RGB(0xFF, 0xEF, 0xD5)
+ peachpuff = 0x00B9DAFF, // RGB(0xFF, 0xDA, 0xB9)
+ peru = 0x003F85CD, // RGB(0xCD, 0x85, 0x3F)
+ pink = 0x00CBC0FF, // RGB(0xFF, 0xC0, 0xCB)
+ plum = 0x00DDA0DD, // RGB(0xDD, 0xA0, 0xDD)
+ powderblue = 0x00E6E0B0, // RGB(0xB0, 0xE0, 0xE6)
+ purple = 0x00800080, // RGB(0x80, 0x00, 0x80)
+ red = 0x000000FF, // RGB(0xFF, 0x00, 0x00)
+ rosybrown = 0x008F8FBC, // RGB(0xBC, 0x8F, 0x8F)
+ royalblue = 0x00E16941, // RGB(0x41, 0x69, 0xE1)
+ saddlebrown = 0x0013458B, // RGB(0x8B, 0x45, 0x13)
+ salmon = 0x007280FA, // RGB(0xFA, 0x80, 0x72)
+ sandybrown = 0x0060A4F4, // RGB(0xF4, 0xA4, 0x60)
+ seagreen = 0x00578B2E, // RGB(0x2E, 0x8B, 0x57)
+ seashell = 0x00EEF5FF, // RGB(0xFF, 0xF5, 0xEE)
+ sienna = 0x002D52A0, // RGB(0xA0, 0x52, 0x2D)
+ silver = 0x00C0C0C0, // RGB(0xC0, 0xC0, 0xC0)
+ skyblue = 0x00EBCE87, // RGB(0x87, 0xCE, 0xEB)
+ slateblue = 0x00CD5A6A, // RGB(0x6A, 0x5A, 0xCD)
+ slategray = 0x00908070, // RGB(0x70, 0x80, 0x90)
+ snow = 0x00FAFAFF, // RGB(0xFF, 0xFA, 0xFA)
+ springgreen = 0x007FFF00, // RGB(0x00, 0xFF, 0x7F)
+ steelblue = 0x00B48246, // RGB(0x46, 0x82, 0xB4)
+ tan = 0x008CB4D2, // RGB(0xD2, 0xB4, 0x8C)
+ teal = 0x00808000, // RGB(0x00, 0x80, 0x80)
+ thistle = 0x00D8BFD8, // RGB(0xD8, 0xBF, 0xD8)
+ tomato = 0x004763FF, // RGB(0xFF, 0x63, 0x47)
+ turquoise = 0x00D0E040, // RGB(0x40, 0xE0, 0xD0)
+ violet = 0x00EE82EE, // RGB(0xEE, 0x82, 0xEE)
+ wheat = 0x00B3DEF5, // RGB(0xF5, 0xDE, 0xB3)
+ white = 0x00FFFFFF, // RGB(0xFF, 0xFF, 0xFF)
+ whitesmoke = 0x00F5F5F5, // RGB(0xF5, 0xF5, 0xF5)
+ yellow = 0x0000FFFF, // RGB(0xFF, 0xFF, 0x00)
+ yellowgreen = 0x0032CD9A, // RGB(0x9A, 0xCD, 0x32)
+ };
+
+ enum ENamedColorIndex
+ {
+ i_aliceblue, i_antiquewhite, i_aqua, i_aquamarine, i_azure, i_beige, i_bisque, i_black,
+ i_blanchedalmond, i_blue, i_blueviolet, i_brown, i_burlywood, i_cadetblue, i_chartreuse,
+ i_chocolate, i_coral, i_cornflower, i_cornsilk, i_crimson, i_cyan, i_darkblue, i_darkcyan,
+ i_darkgoldenrod, i_darkgray, i_darkgreen, i_darkkhaki, i_darkmagenta, i_darkolivegreen,
+ i_darkorange, i_darkorchid, i_darkred, i_darksalmon, i_darkseagreen, i_darkslateblue,
+ i_darkslategray, i_darkturquoise, i_darkviolet, i_deeppink, i_deepskyblue, i_dimgray,
+ i_dodgerblue, i_firebrick, i_floralwhite, i_forestgreen, i_fuchsia, i_gainsboro,
+ i_ghostwhite, i_gold, i_goldenrod, i_gray, i_green, i_greenyellow, i_honeydew, i_hotpink,
+ i_indianred, i_indigo, i_ivory, i_khaki, i_lavender, i_lavenderblush, i_lawngreen,
+ i_lemonchiffon, i_lightblue, i_lightcoral, i_lightcyan, i_lightgoldenrodyellow,
+ i_lightgreen, i_lightgrey, i_lightpink, i_lightsalmon, i_lightseagreen, i_lightskyblue,
+ i_lightslategray, i_lightsteelblue, i_lightyellow, i_lime, i_limegreen, i_linen,
+ i_magenta, i_maroon, i_mediumaquamarine, i_mediumblue, i_mediumorchid, i_mediumpurple,
+ i_mediumseagreen, i_mediumslateblue, i_mediumspringgreen, i_mediumturquoise,
+ i_mediumvioletred, i_midnightblue, i_mintcream, i_mistyrose, i_moccasin, i_navajowhite,
+ i_navy, i_oldlace, i_olive, i_olivedrab, i_orange, i_orangered, i_orchid, i_palegoldenrod,
+ i_palegreen, i_paleturquoise, i_palevioletred, i_papayawhip, i_peachpuff, i_peru, i_pink,
+ i_plum, i_powderblue, i_purple, i_red, i_rosybrown, i_royalblue, i_saddlebrown, i_salmon,
+ i_sandybrown, i_seagreen, i_seashell, i_sienna, i_silver, i_skyblue, i_slateblue,
+ i_slategray, i_snow, i_springgreen, i_steelblue, i_tan, i_teal, i_thistle, i_tomato,
+ i_turquoise, i_violet, i_wheat, i_white, i_whitesmoke, i_yellow, i_yellowgreen,
+ numNamedColors
+ };
+
+private:
+
+ // Konvertierung
+ // -------------
+ void ToRGB(); // logisch konstant, nicht physikalisch
+ void ToHLS(); // logisch konstant, nicht physikalisch
+ static unsigned char ToRGB1(float rm1, float rm2, float rh);
+
+ // Daten
+ // -----
+ union // Byteweiser Zugriff auf die COLORREF Struktur
+ {
+ COLORTYPE m_colorref;
+ unsigned char m_color[4];
+ };
+ enum {c_red = 0, c_green = 1, c_blue = 2, c_null = 3}; // enum Hack f�r colorbyte-Index
+
+ float m_hue; // 0.0 .. 360.0 // Winkel
+ float m_saturation; // 0.0 .. 1.0 // Prozent
+ float m_luminance; // 0.0 .. 1.0 // Prozent
+
+ // Flag f�r Lazy Evaluation
+ bool m_bIsRGB;
+ bool m_bIsHLS;
+
+ // statische Konstanten f�r benannte Farben
+ struct DNamedColor
+ {
+ COLORTYPE color;
+ const char* name;
+ };
+ static const DNamedColor m_namedColor[numNamedColors];
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// global functions
+/////////////////////////////////////////////////////////////////////////////
+
+COLORTYPE GetHueColor(int iHue) ;
+
+void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v );
+void RGBToHSV( unsigned char r, unsigned char g, unsigned char b, float* h, float *s, float* v );
+
+void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v );
+void HSVToRGB( unsigned char& r, unsigned char& g, unsigned char& b, float h, float s, float v );
+
+short GetHueValue( COLORTYPE inColor );
+short GetSaturationValue( COLORTYPE inColor );
+short GetBrightnessValue( COLORTYPE inColor );
+
+
+#endif
diff --git a/src/3rdparty/pcre b/src/3rdparty/pcre
new file mode 160000
+Subproject 50b7967a78f8f7b1b45444577662ba20ed2643c
diff --git a/src/3rdparty/utf8cpp/2.3.2/doc/ReleaseNotes b/src/3rdparty/utf8cpp/2.3.2/doc/ReleaseNotes
new file mode 100644
index 00000000..15a4ae81
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/doc/ReleaseNotes
@@ -0,0 +1,11 @@
+utf8 cpp library
+Release 2.3.2
+
+A bug fix release plus minor performance improvements. Thanks to all who reported bugs.
+
+Changes from version 2.3.1
+- Bug fix [3506114]: potential crash in replace_invalid
+- Bug fix [3426789]: documentation typo
+- Bug fix [3215839]: name clash with std::next
+
+Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes
diff --git a/src/3rdparty/utf8cpp/2.3.2/doc/utf8cpp.html b/src/3rdparty/utf8cpp/2.3.2/doc/utf8cpp.html
new file mode 100644
index 00000000..06849b1d
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/doc/utf8cpp.html
@@ -0,0 +1,1795 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st November 2002), see www.w3.org">
+ <meta name="description" content=
+ "A simple, portable and lightweigt C++ library for easy handling of UTF-8 encoded strings">
+ <meta name="keywords" content="UTF-8 C++ portable utf8 unicode generic templates">
+ <meta name="author" content="Nemanja Trifunovic">
+ <title>
+ UTF8-CPP: UTF-8 with C++ in a Portable Way
+ </title>
+ <style type="text/css">
+ <!--
+ span.return_value {
+ color: brown;
+ }
+ span.keyword {
+ color: blue;
+ }
+ span.preprocessor {
+ color: navy;
+ }
+ span.literal {
+ color: olive;
+ }
+ span.comment {
+ color: green;
+ }
+ code {
+ font-weight: bold;
+ }
+ ul.toc {
+ list-style-type: none;
+ }
+ p.version {
+ font-size: small;
+ font-style: italic;
+ }
+ -->
+ </style>
+ </head>
+ <body>
+ <h1>
+ UTF8-CPP: UTF-8 with C++ in a Portable Way
+ </h1>
+ <p>
+ <a href="https://sourceforge.net/projects/utfcpp">The Sourceforge project page</a>
+ </p>
+ <div id="toc">
+ <h2>
+ Table of Contents
+ </h2>
+ <ul class="toc">
+ <li>
+ <a href="#introduction">Introduction</a>
+ </li>
+ <li>
+ <a href="#examples">Examples of Use</a>
+ <ul class="toc">
+ <li>
+ <a href=#introsample>Introductionary Sample </a>
+ </li>
+ <li>
+ <a href=#validfile>Checking if a file contains valid UTF-8 text</a>
+ </li>
+ <li>
+ <a href=#fixinvalid>Ensure that a string contains valid UTF-8 text</a>
+ </li>
+ </ul>
+ <li>
+ <a href="#reference">Reference</a>
+ <ul class="toc">
+ <li>
+ <a href="#funutf8">Functions From utf8 Namespace </a>
+ </li>
+ <li>
+ <a href="#typesutf8">Types From utf8 Namespace </a>
+ </li>
+ <li>
+ <a href="#fununchecked">Functions From utf8::unchecked Namespace </a>
+ </li>
+ <li>
+ <a href="#typesunchecked">Types From utf8::unchecked Namespace </a>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <a href="#points">Points of Interest</a>
+ </li>
+ <li>
+ <a href="#conclusion">Conclusion</a>
+ </li>
+ <li>
+ <a href="#links">Links</a>
+ </li>
+ </ul>
+ </div>
+ <h2 id="introduction">
+ Introduction
+ </h2>
+ <p>
+ Many C++ developers miss an easy and portable way of handling Unicode encoded
+ strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic,
+ and while some work is being done to introduce Unicode to the next incarnation
+ called C++0x, for the moment nothing of the sort is available. In the meantime,
+ developers use third party libraries like ICU, OS specific capabilities, or simply
+ roll out their own solutions.
+ </p>
+ <p>
+ In order to easily handle UTF-8 encoded Unicode strings, I came up with a small
+ generic library. For anybody used to work with STL algorithms and iterators, it should be
+ easy and natural to use. The code is freely available for any purpose - check out
+ the license at the beginning of the utf8.h file. If you run into
+ bugs or performance issues, please let me know and I'll do my best to address them.
+ </p>
+ <p>
+ The purpose of this article is not to offer an introduction to Unicode in general,
+ and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out
+ <a href="http://www.unicode.org/">Unicode Home Page</a> or some other source of
+ information for Unicode. Also, it is not my aim to advocate the use of UTF-8
+ encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from
+ C++, I am sure you have good reasons for it.
+ </p>
+ <h2 id="examples">
+ Examples of use
+ </h2>
+ <h3 id="introsample">
+ Introductionary Sample
+ </h3>
+ <p>
+ To illustrate the use of the library, let's start with a small but complete program
+ that opens a file containing UTF-8 encoded text, reads it line by line, checks each line
+ for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
+ </p>
+<pre>
+<span class="preprocessor">#include &lt;fstream&gt;</span>
+<span class="preprocessor">#include &lt;iostream&gt;</span>
+<span class="preprocessor">#include &lt;string&gt;</span>
+<span class="preprocessor">#include &lt;vector&gt;</span>
+<span class="preprocessor">#include "utf8.h"</span>
+<span class="keyword">using namespace</span> std;
+<span class="keyword">int</span> main(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)
+{
+ <span class="keyword">if</span> (argc != <span class="literal">2</span>) {
+ cout &lt;&lt; <span class="literal">"\nUsage: docsample filename\n"</span>;
+ <span class="keyword">return</span> <span class="literal">0</span>;
+ }
+
+ <span class="keyword">const char</span>* test_file_path = argv[1];
+ <span class="comment">// Open the test file (contains UTF-8 encoded text)</span>
+ ifstream fs8(test_file_path);
+ <span class="keyword">if</span> (!fs8.is_open()) {
+ cout &lt;&lt; <span class=
+"literal">"Could not open "</span> &lt;&lt; test_file_path &lt;&lt; endl;
+ <span class="keyword">return</span> <span class="literal">0</span>;
+ }
+
+ <span class="keyword">unsigned</span> line_count = <span class="literal">1</span>;
+ string line;
+ <span class="comment">// Play with all the lines in the file</span>
+ <span class="keyword">while</span> (getline(fs8, line)) {
+ <span class="comment">// check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)</span>
+ string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+ <span class="keyword">if</span> (end_it != line.end()) {
+ cout &lt;&lt; <span class=
+"literal">"Invalid UTF-8 encoding detected at line "</span> &lt;&lt; line_count &lt;&lt; <span
+ class="literal">"\n"</span>;
+ cout &lt;&lt; <span class=
+"literal">"This part is fine: "</span> &lt;&lt; string(line.begin(), end_it) &lt;&lt; <span
+ class="literal">"\n"</span>;
+ }
+
+ <span class="comment">// Get the line length (at least for the valid part)</span>
+ <span class="keyword">int</span> length = utf8::distance(line.begin(), end_it);
+ cout &lt;&lt; <span class=
+"literal">"Length of line "</span> &lt;&lt; line_count &lt;&lt; <span class=
+"literal">" is "</span> &lt;&lt; length &lt;&lt; <span class="literal">"\n"</span>;
+
+ <span class="comment">// Convert it to utf-16</span>
+ vector&lt;unsigned short&gt; utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+
+ <span class="comment">// And back to utf-8</span>
+ string utf8line;
+ utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+
+ <span class="comment">// Confirm that the conversion went OK:</span>
+ <span class="keyword">if</span> (utf8line != string(line.begin(), end_it))
+ cout &lt;&lt; <span class=
+"literal">"Error in UTF-16 conversion at line: "</span> &lt;&lt; line_count &lt;&lt; <span
+ class="literal">"\n"</span>;
+
+ line_count++;
+ }
+ <span class="keyword">return</span> <span class="literal">0</span>;
+}
+</pre>
+ <p>
+ In the previous code sample, for each line we performed
+ a detection of invalid UTF-8 sequences with <code>find_invalid</code>; the number
+ of characters (more precisely - the number of Unicode code points, including the end
+ of line and even BOM if there is one) in each line was
+ determined with a use of <code>utf8::distance</code>; finally, we have converted
+ each line to UTF-16 encoding with <code>utf8to16</code> and back to UTF-8 with
+ <code>utf16to8</code>.
+ </p>
+ <h3 id="validfile">Checking if a file contains valid UTF-8 text</h3>
+<p>
+Here is a function that checks whether the content of a file is valid UTF-8 encoded text without
+reading the content into the memory:
+</p>
+<pre>
+<span class="keyword">bool</span> valid_utf8_file(i<span class="keyword">const char</span>* file_name)
+{
+ ifstream ifs(file_name);
+ <span class="keyword">if</span> (!ifs)
+ <span class="keyword">return false</span>; <span class="comment">// even better, throw here</span>
+
+ istreambuf_iterator&lt;<span class="keyword">char</span>&gt; it(ifs.rdbuf());
+ istreambuf_iterator&lt;<span class="keyword">char</span>&gt; eos;
+
+ <span class="keyword">return</span> utf8::is_valid(it, eos);
+}
+</pre>
+<p>
+Because the function <code>utf8::is_valid()</code> works with input iterators, we were able
+to pass an <code>istreambuf_iterator</code> to it and read the content of the file directly
+without loading it to the memory first.</p>
+<p>
+Note that other functions that take input iterator arguments can be used in a similar way. For
+instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just
+do something like:
+</p>
+<pre>
+ utf8::utf8to16(it, eos, back_inserter(u16string));
+</pre>
+ <h3 id="fixinvalid">Ensure that a string contains valid UTF-8 text</h3>
+<p>
+If we have some text that "probably" contains UTF-8 encoded text and we want to
+replace any invalid UTF-8 sequence with a replacement character, something like
+the following function may be used:
+</p>
+<pre>
+<span class="keyword">void</span> fix_utf8_string(std::string&amp; str)
+{
+ std::string temp;
+ utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
+ str = temp;
+}
+</pre>
+<p>The function will replace any invalid UTF-8 sequence with a Unicode replacement character.
+There is an overloaded function that enables the caller to supply their own replacement character.
+</p>
+ <h2 id="reference">
+ Reference
+ </h2>
+ <h3 id="funutf8">
+ Functions From utf8 Namespace
+ </h3>
+ <h4>
+ utf8::append
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
+ to a UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator append(uint32_t cp, octet_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an output iterator.<br>
+ <code>cp</code>: a 32 bit integer representing a code point to append to the
+ sequence.<br>
+ <code>result</code>: an output iterator to the place in the sequence where to
+ append the code point.<br>
+ <span class="return_value">Return value</span>: an iterator pointing to the place
+ after the newly appended sequence.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
+class="literal">0</span>,<span class="literal">0</span>,<span class=
+"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
+<span class="keyword">unsigned char</span>* end = append(<span class=
+"literal">0x0448</span>, u);
+assert (u[<span class="literal">0</span>] == <span class=
+"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
+"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
+"literal">0</span>);
+</pre>
+ <p>
+ Note that <code>append</code> does not allocate any memory - it is the burden of
+ the caller to make sure there is enough memory allocated for the operation. To make
+ things more interesting, <code>append</code> can add anywhere between 1 and 4
+ octets to the sequence. In practice, you would most often want to use
+ <code>std::back_inserter</code> to ensure that the necessary memory is allocated.
+ </p>
+ <p>
+ In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
+ is thrown.
+ </p>
+ <h4>
+ utf8::next
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code
+ point and moves the iterator to the next position.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t next(octet_iterator&amp; it, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ beginning of the next code point.<br>
+ <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+ gets equal to <code>end</code> during the extraction of a code point, an
+ <code>utf8::not_enough_room</code> exception is thrown.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = next(w, twochars + <span class="literal">6</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars + <span class="literal">3</span>);
+</pre>
+ <p>
+ This function is typically used to iterate through a UTF-8 encoded string.
+ </p>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown.
+ </p>
+ <h4>
+ utf8::peek_next
+ </h4>
+ <p class="version">
+ Available in version 2.1 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code
+ point for the following sequence without changing the value of the iterator.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: an iterator pointing to the beginning of an UTF-8
+ encoded code point.<br>
+ <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+ gets equal to <code>end</code> during the extraction of a code point, an
+ <code>utf8::not_enough_room</code> exception is thrown.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = peek_next(w, twochars + <span class="literal">6</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown.
+ </p>
+ <h4>
+ utf8::prior
+ </h4>
+ <p class="version">
+ Available in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t prior(octet_iterator&amp; it, octet_iterator start);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: a bidirectional iterator.<br>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <code>start</code>: an iterator to the beginning of the sequence where the search
+ for the beginning of a code point is performed. It is a
+ safety measure to prevent passing the beginning of the string in the search for a
+ UTF-8 lead octet.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars + <span class=
+"literal">3</span>;
+<span class="keyword">int</span> cp = prior (w, twochars);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ This function has two purposes: one is two iterate backwards through a UTF-8
+ encoded string. Note that it is usually a better idea to iterate forward instead,
+ since <code>utf8::next</code> is faster. The second purpose is to find a beginning
+ of a UTF-8 sequence if we have a random position within a string. Note that in that
+ case <code>utf8::prior</code> may not detect an invalid UTF-8 sequence in some scenarios:
+ for instance if there are superfluous trail octets, it will just skip them.
+ </p>
+ <p>
+ <code>it</code> will typically point to the beginning of
+ a code point, and <code>start</code> will point to the
+ beginning of the string to ensure we don't go backwards too far. <code>it</code> is
+ decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
+ beginning with that octet is decoded to a 32 bit representation and returned.
+ </p>
+ <p>
+ In case <code>start</code> is reached before a UTF-8 lead octet is hit, or if an
+ invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
+ exception is thrown.
+ </p>
+ <p>In case <code>start</code> equals <code>it</code>, a <code>not_enough_room</code>
+ exception is thrown.
+ <h4>
+ utf8::previous
+ </h4>
+ <p class="version">
+ Deprecated in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t previous(octet_iterator&amp; it, octet_iterator pass_start);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: a random access iterator.<br>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <code>pass_start</code>: an iterator to the point in the sequence where the search
+ for the beginning of a code point is aborted if no result was reached. It is a
+ safety measure to prevent passing the beginning of the string in the search for a
+ UTF-8 lead octet.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars + <span class=
+"literal">3</span>;
+<span class="keyword">int</span> cp = previous (w, twochars - <span class=
+"literal">1</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ <code>utf8::previous</code> is deprecated, and <code>utf8::prior</code> should
+ be used instead, although the existing code can continue using this function.
+ The problem is the parameter <code>pass_start</code> that points to the position
+ just before the beginning of the sequence. Standard containers don't have the
+ concept of "pass start" and the function can not be used with their iterators.
+ </p>
+ <p>
+ <code>it</code> will typically point to the beginning of
+ a code point, and <code>pass_start</code> will point to the octet just before the
+ beginning of the string to ensure we don't go backwards too far. <code>it</code> is
+ decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
+ beginning with that octet is decoded to a 32 bit representation and returned.
+ </p>
+ <p>
+ In case <code>pass_start</code> is reached before a UTF-8 lead octet is hit, or if an
+ invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
+ exception is thrown
+ </p>
+ <h4>
+ utf8::advance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Advances an iterator by the specified number of code points within an UTF-8
+ sequence.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename distance_type&gt;
+<span class=
+"keyword">void</span> advance (octet_iterator&amp; it, distance_type n, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>distance_type</code>: an integral type convertible to <code>octet_iterator</code>'s difference type.<br>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ nth following code point.<br>
+ <code>n</code>: a positive integer that shows how many code points we want to
+ advance.<br>
+ <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+ gets equal to <code>end</code> during the extraction of a code point, an
+ <code>utf8::not_enough_room</code> exception is thrown.<br>
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars;
+advance (w, <span class="literal">2</span>, twochars + <span class="literal">6</span>);
+assert (w == twochars + <span class="literal">5</span>);
+</pre>
+ <p>
+ This function works only "forward". In case of a negative <code>n</code>, there is
+ no effect.
+ </p>
+ <p>
+ In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
+ is thrown.
+ </p>
+ <h4>
+ utf8::distance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the
+ number of code points between them.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class=
+"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
+ <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
+ point in the sequence we are trying to determine the length. It can be the
+ beginning of a new code point, or not.<br>
+ <span class="return_value">Return value</span> the distance between the iterators,
+ in code points.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+size_t dist = utf8::distance(twochars, twochars + <span class="literal">5</span>);
+assert (dist == <span class="literal">2</span>);
+</pre>
+ <p>
+ This function is used to find the length (in code points) of a UTF-8 encoded
+ string. The reason it is called <em>distance</em>, rather than, say,
+ <em>length</em> is mainly because developers are used that <em>length</em> is an
+ O(1) function. Computing the length of an UTF-8 string is a linear operation, and
+ it looked better to model it after <code>std::distance</code> algorithm.
+ </p>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown. If <code>last</code> does not point to the past-of-end of a UTF-8 seqence,
+ a <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::utf16to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-16 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, <span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>u16bit_iterator</code>: an input iterator.<br>
+ <code>octet_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned short</span> utf16string[] = {<span class=
+"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
+"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
+"literal">0xdd1e</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf16to8(utf16string, utf16string + <span class=
+"literal">5</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">10</span>);
+</pre>
+ <p>
+ In case of invalid UTF-16 sequence, a <code>utf8::invalid_utf16</code> exception is
+ thrown.
+ </p>
+ <h4>
+ utf8::utf8to16
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts an UTF-8 encoded string to UTF-16
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>u16bit_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
+ pass-the-end of the UTF-8 encoded string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-16 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-16 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
+vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
+"literal">9</span>, back_inserter(utf16result));
+assert (utf16result.size() == <span class="literal">4</span>);
+assert (utf16result[<span class="literal">2</span>] == <span class=
+"literal">0xd834</span>);
+assert (utf16result[<span class="literal">3</span>] == <span class=
+"literal">0xdd1e</span>);
+</pre>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
+ <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::utf32to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-32 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an output iterator.<br>
+ <code>u32bit_iterator</code>: an input iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">int</span> utf32string[] = {<span class=
+"literal">0x448</span>, <span class="literal">0x65E5</span>, <span class=
+"literal">0x10346</span>, <span class="literal">0</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf32to8(utf32string, utf32string + <span class=
+"literal">3</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">9</span>);
+</pre>
+ <p>
+ In case of invalid UTF-32 string, a <code>utf8::invalid_code_point</code> exception
+ is thrown.
+ </p>
+ <h4>
+ utf8::utf8to32
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-8 encoded string to UTF-32.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> u32bit_iterator&gt;
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>u32bit_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
+ to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-32 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-32 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+vector&lt;<span class="keyword">int</span>&gt; utf32result;
+utf8to32(twochars, twochars + <span class=
+"literal">5</span>, back_inserter(utf32result));
+assert (utf32result.size() == <span class="literal">2</span>);
+</pre>
+ <p>
+ In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+ thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
+ <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::find_invalid
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Detects an invalid sequence within a UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+ test for validity.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
+ for validity.<br>
+ <span class="return_value">Return value</span>: an iterator pointing to the first
+ invalid octet in the UTF-8 string. In case none were found, equals
+ <code>end</code>.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> utf_invalid[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
+<span class=
+"keyword">char</span>* invalid = find_invalid(utf_invalid, utf_invalid + <span class=
+"literal">6</span>);
+assert (invalid == utf_invalid + <span class="literal">5</span>);
+</pre>
+ <p>
+ This function is typically used to make sure a UTF-8 string is valid before
+ processing it with other functions. It is especially important to call it if before
+ doing any of the <em>unchecked</em> operations on it.
+ </p>
+ <h4>
+ utf8::is_valid
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Checks whether a sequence of octets is a valid UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class="keyword">bool</span> is_valid(octet_iterator start, octet_iterator end);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+ test for validity.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
+ for validity.<br>
+ <span class="return_value">Return value</span>: <code>true</code> if the sequence
+ is a valid UTF-8 string; <code>false</code> if not.
+ </p>
+ Example of use:
+<pre>
+<span class="keyword">char</span> utf_invalid[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
+<span class="keyword">bool</span> bvalid = is_valid(utf_invalid, utf_invalid + <span
+class="literal">6</span>);
+assert (bvalid == false);
+</pre>
+ <p>
+ <code>is_valid</code> is a shorthand for <code>find_invalid(start, end) ==
+ end;</code>. You may want to use it to make sure that a byte seqence is a valid
+ UTF-8 string without the need to know where it fails if it is not valid.
+ </p>
+ <h4>
+ utf8::replace_invalid
+ </h4>
+ <p class="version">
+ Available in version 2.0 and later.
+ </p>
+ <p>
+ Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> output_iterator&gt;
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> output_iterator&gt;
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>output_iterator</code>: an output iterator.<br>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+ look for invalid UTF-8 sequences.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to look
+ for invalid UTF-8 sequences.<br>
+ <code>out</code>: An output iterator to the range where the result of replacement
+ is stored.<br>
+ <code>replacement</code>: A Unicode code point for the replacement marker. The
+ version without this parameter assumes the value <code>0xfffd</code><br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the UTF-8 string with replaced invalid sequences.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> invalid_sequence[] = <span class=
+"literal">"a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z"</span>;
+vector&lt;<span class="keyword">char</span>&gt; replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), <span
+ class="literal">'?'</span>);
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+<span class="keyword">char</span>* fixed_invalid_sequence = <span class=
+"literal">"a????z"</span>;
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+</pre>
+ <p>
+ <code>replace_invalid</code> does not perform in-place replacement of invalid
+ sequences. Rather, it produces a copy of the original string with the invalid
+ sequences replaced with a replacement marker. Therefore, <code>out</code> must not
+ be in the <code>[start, end]</code> range.
+ </p>
+ <p>
+ If <code>end</code> does not point to the past-of-end of a UTF-8 sequence, a
+ <code>utf8::not_enough_room</code> exception is thrown.
+ </p>
+ <h4>
+ utf8::starts_with_bom
+ </h4>
+ <p class="version">
+ Available in version 2.3 and later. Relaces deprecated <code>is_bom()</code> function.
+ </p>
+ <p>
+ Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class="keyword">bool</span> starts_with_bom (octet_iterator it, octet_iterator end);
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: beginning of the octet sequence to check<br>
+ <code>end</code>: pass-end of the sequence to check<br>
+ <span class="return_value">Return value</span>: <code>true</code> if the sequence
+ starts with a UTF-8 byte order mark; <code>false</code> if not.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
+"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
+"literal">0xbf</span>};
+<span class="keyword">bool</span> bbom = starts_with_bom(byte_order_mark, byte_order_mark + <span class="keyword">sizeof</span>(byte_order_mark));
+assert (bbom == <span class="literal">true</span>);
+</pre>
+ <p>
+ The typical use of this function is to check the first three bytes of a file. If
+ they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
+ encoded text.
+ </p>
+ <h4>
+ utf8::is_bom
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later. Deprecated in version 2.3. <code>starts_with_bom()</code> should be used
+ instead.
+ </p>
+ <p>
+ Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM)
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class="keyword">bool</span> is_bom (octet_iterator it); <span class="comment"> // Deprecated</span>
+</pre>
+ <p>
+ <code>octet_iterator</code>: an input iterator.<br>
+ <code>it</code>: beginning of the 3-octet sequence to check<br>
+ <span class="return_value">Return value</span>: <code>true</code> if the sequence
+ is UTF-8 byte order mark; <code>false</code> if not.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
+"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
+"literal">0xbf</span>};
+<span class="keyword">bool</span> bbom = is_bom(byte_order_mark);
+assert (bbom == <span class="literal">true</span>);
+</pre>
+ <p>
+ The typical use of this function is to check the first three bytes of a file. If
+ they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
+ encoded text.
+ </p>
+ <p>
+ If a sequence is
+ shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated
+ in favor of <code>starts_with_bom()</code>that takes the end of sequence as an argument.
+ </p>
+ <h3 id="typesutf8">
+ Types From utf8 Namespace
+ </h3>
+ <h4>utf8::exception
+ </h4>
+ <p class="version">
+ Available in version 2.3 and later.
+ </p>
+ <p>
+ Base class for the exceptions thrown by UTF CPP library functions.
+ </p>
+<pre>
+<span class="keyword">class</span> exception : <span class="keyword">public</span> std::exception {};
+</pre>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">try</span> {
+ code_that_uses_utf_cpp_library();
+}
+<span class="keyword">catch</span>(<span class="keyword">const</span> utf8::exception&amp; utfcpp_ex) {
+ cerr &lt;&lt; utfcpp_ex.what();
+}
+</pre>
+
+ <h4>utf8::invalid_code_point
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP functions such as <code>advance</code> and <code>next</code> if an UTF-8 sequence represents and invalid code point.
+ </p>
+
+<pre>
+<span class="keyword">class</span> invalid_code_point : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>:
+ uint32_t code_point() <span class="keyword">const</span>;
+};
+
+</pre>
+ <p>
+ Member function <code>code_point()</code> can be used to determine the invalid code point that
+ caused the exception to be thrown.
+ </p>
+ <h4>utf8::invalid_utf8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP functions such as <code>next</code> and <code>prior</code> if an invalid UTF-8 sequence
+ is detected during decoding.
+ </p>
+
+<pre>
+<span class="keyword">class</span> invalid_utf8 : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>:
+ uint8_t utf8_octet() <span class="keyword">const</span>;
+};
+</pre>
+
+ <p>
+ Member function <code>utf8_octet()</code> can be used to determine the beginning of the byte
+ sequence that caused the exception to be thrown.
+ </p>
+</pre>
+ <h4>utf8::invalid_utf16
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP function <code>utf16to8</code> if an invalid UTF-16 sequence
+ is detected during decoding.
+ </p>
+
+<pre>
+<span class="keyword">class</span> invalid_utf16 : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>:
+ uint16_t utf16_word() <span class="keyword">const</span>;
+};
+</pre>
+
+ <p>
+ Member function <code>utf16_word()</code> can be used to determine the UTF-16 code unit
+ that caused the exception to be thrown.
+ </p>
+ <h4>utf8::not_enough_room
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Thrown by UTF8 CPP functions such as <code>next</code> if the end of the decoded UTF-8 sequence
+ was reached before the code point was decoded.
+ </p>
+
+<pre>
+<span class="keyword">class</span> not_enough_room : <span class="keyword">public</span> exception {};
+</pre>
+ <h4>
+ utf8::iterator
+ </h4>
+ <p class="version">
+ Available in version 2.0 and later.
+ </p>
+ <p>
+ Adapts the underlying octet iterator to iterate over the sequence of code points,
+ rather than raw octets.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
+<span class="keyword">class</span> iterator;
+</pre>
+
+ <h5>Member functions</h5>
+ <dl>
+ <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
+ constructed with its default constructor.
+ <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it,
+ const octet_iterator&amp; range_start,
+ const octet_iterator&amp; range_end);</code> <dd> a constructor
+ that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
+ and sets the range in which the iterator is considered valid.
+ <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
+ underlying <code>octet_iterator</code>.
+ <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
+ the underlying <code>octet_iterator</code> is pointing to and returns the code point.
+ <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are equal.
+ <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are not equal.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
+ the iterator to the next UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
+ the iterator to the previous UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+ </dl>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; it(threechars, threechars, threechars + <span class="literal">9</span>);
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; it2 = it;
+assert (it2 == it);
+assert (*it == <span class="literal">0x10346</span>);
+assert (*(++it) == <span class="literal">0x65e5</span>);
+assert ((*it++) == <span class="literal">0x65e5</span>);
+assert (*it == <span class="literal">0x0448</span>);
+assert (it != it2);
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; endit (threechars + <span class="literal">9</span>, threechars, threechars + <span class="literal">9</span>);
+assert (++it == endit);
+assert (*(--it) == <span class="literal">0x0448</span>);
+assert ((*it--) == <span class="literal">0x0448</span>);
+assert (*it == <span class="literal">0x65e5</span>);
+assert (--it == utf8::iterator&lt;<span class="keyword">char</span>*&gt;(threechars, threechars, threechars + <span class="literal">9</span>));
+assert (*it == <span class="literal">0x10346</span>);
+</pre>
+ <p>
+ The purpose of <code>utf8::iterator</code> adapter is to enable easy iteration as well as the use of STL
+ algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of
+ <code>utf8::next()</code> and <code>utf8::prior()</code> functions.
+ </p>
+ <p>
+ Note that <code>utf8::iterator</code> adapter is a checked iterator. It operates on the range specified in
+ the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators
+ require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically,
+ the range will be determined by sequence container functions <code>begin</code> and <code>end</code>, i.e.:
+ </p>
+<pre>
+std::string s = <span class="literal">"example"</span>;
+utf8::iterator i (s.begin(), s.begin(), s.end());
+</pre>
+ <h3 id="fununchecked">
+ Functions From utf8::unchecked Namespace
+ </h3>
+ <h4>
+ utf8::unchecked::append
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
+ to a UTF-8 string.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator append(uint32_t cp, octet_iterator result);
+
+</pre>
+ <p>
+ <code>cp</code>: A 32 bit integer representing a code point to append to the
+ sequence.<br>
+ <code>result</code>: An output iterator to the place in the sequence where to
+ append the code point.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the newly appended sequence.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
+class="literal">0</span>,<span class="literal">0</span>,<span class=
+"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
+<span class="keyword">unsigned char</span>* end = unchecked::append(<span class=
+"literal">0x0448</span>, u);
+assert (u[<span class="literal">0</span>] == <span class=
+"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
+"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
+"literal">0</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::append</code>. It does not
+ check for validity of the supplied code point, and may produce an invalid UTF-8
+ sequence.
+ </p>
+ <h4>
+ utf8::unchecked::next
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point
+ and moves the iterator to the next position.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t next(octet_iterator&amp; it);
+
+</pre>
+ <p>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ beginning of the next code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = unchecked::next(w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars + <span class="literal">3</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::next</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::peek_next
+ </h4>
+ <p class="version">
+ Available in version 2.1 and later.
+ </p>
+ <p>
+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t peek_next(octet_iterator it);
+
+</pre>
+ <p>
+ <code>it</code>: an iterator pointing to the beginning of an UTF-8
+ encoded code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ processed UTF-8 code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = unchecked::peek_next(w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::peek_next</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::prior
+ </h4>
+ <p class="version">
+ Available in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t prior(octet_iterator&amp; it);
+
+</pre>
+ <p>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
+<span class="keyword">int</span> cp = unchecked::prior (w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::prior</code>. It does not
+ check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+ </p>
+ <h4>
+ utf8::unchecked::previous (deprecated, see utf8::unchecked::prior)
+ </h4>
+ <p class="version">
+ Deprecated in version 1.02 and later.
+ </p>
+ <p>
+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+ decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+ code point and returns the 32 bits representation of the code point.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t previous(octet_iterator&amp; it);
+
+</pre>
+ <p>
+ <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+ After the function returns, it is decremented to point to the beginning of the
+ previous code point.<br>
+ <span class="return_value">Return value</span>: the 32 bit representation of the
+ previous code point.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
+<span class="keyword">int</span> cp = unchecked::previous (w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+ <p>
+ The reason this function is deprecated is just the consistency with the "checked"
+ versions, where <code>prior</code> should be used instead of <code>previous</code>.
+ In fact, <code>unchecked::previous</code> behaves exactly the same as <code>
+ unchecked::prior</code>
+ </p>
+ <p>
+ This is a faster but less safe version of <code>utf8::previous</code>. It does not
+ check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+ </p>
+ <h4>
+ utf8::unchecked::advance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Advances an iterator by the specified number of code points within an UTF-8
+ sequence.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename distance_type&gt;
+<span class="keyword">void</span> advance (octet_iterator&amp; it, distance_type n);
+
+</pre>
+ <p>
+ <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+ encoded code point. After the function returns, it is incremented to point to the
+ nth following code point.<br>
+ <code>n</code>: a positive integer that shows how many code points we want to
+ advance.<br>
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+unchecked::advance (w, <span class="literal">2</span>);
+assert (w == twochars + <span class="literal">5</span>);
+</pre>
+ <p>
+ This function works only "forward". In case of a negative <code>n</code>, there is
+ no effect.
+ </p>
+ <p>
+ This is a faster but less safe version of <code>utf8::advance</code>. It does not
+ check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+ </p>
+ <h4>
+ utf8::unchecked::distance
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the
+ number of code points between them.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class=
+"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
+</pre>
+ <p>
+ <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
+ <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
+ point in the sequence we are trying to determine the length. It can be the
+ beginning of a new code point, or not.<br>
+ <span class="return_value">Return value</span> the distance between the iterators,
+ in code points.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+size_t dist = utf8::unchecked::distance(twochars, twochars + <span class=
+"literal">5</span>);
+assert (dist == <span class="literal">2</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::distance</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf16to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-16 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, <span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">unsigned short</span> utf16string[] = {<span class=
+"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
+"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
+"literal">0xdd1e</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+unchecked::utf16to8(utf16string, utf16string + <span class=
+"literal">5</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">10</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf16to8</code>. It does not
+ check for validity of the supplied UTF-16 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf8to16
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts an UTF-8 encoded string to UTF-16
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
+ pass-the-end of the UTF-8 encoded string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-16 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-16 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
+vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
+"literal">9</span>, back_inserter(utf16result));
+assert (utf16result.size() == <span class="literal">4</span>);
+assert (utf16result[<span class="literal">2</span>] == <span class=
+"literal">0xd834</span>);
+assert (utf16result[<span class="literal">3</span>] == <span class=
+"literal">0xdd1e</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf8to16</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf32to8
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-32 encoded string to UTF-8.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> u32bit_iterator&gt;
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
+ string to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-8 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-8 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">int</span> utf32string[] = {<span class=
+"literal">0x448</span>, <span class="literal">0x65e5</span>, <span class=
+"literal">0x10346</span>, <span class="literal">0</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf32to8(utf32string, utf32string + <span class=
+"literal">3</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">9</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf32to8</code>. It does not
+ check for validity of the supplied UTF-32 sequence.
+ </p>
+ <h4>
+ utf8::unchecked::utf8to32
+ </h4>
+ <p class="version">
+ Available in version 1.0 and later.
+ </p>
+ <p>
+ Converts a UTF-8 encoded string to UTF-32.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+
+</pre>
+ <p>
+ <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+ string to convert.<br>
+ <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
+ to convert.<br>
+ <code>result</code>: an output iterator to the place in the UTF-32 string where to
+ append the result of conversion.<br>
+ <span class="return_value">Return value</span>: An iterator pointing to the place
+ after the appended UTF-32 string.
+ </p>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+vector&lt;<span class="keyword">int</span>&gt; utf32result;
+unchecked::utf8to32(twochars, twochars + <span class=
+"literal">5</span>, back_inserter(utf32result));
+assert (utf32result.size() == <span class="literal">2</span>);
+</pre>
+ <p>
+ This is a faster but less safe version of <code>utf8::utf8to32</code>. It does not
+ check for validity of the supplied UTF-8 sequence.
+ </p>
+ <h3 id="typesunchecked">
+ Types From utf8::unchecked Namespace
+ </h3>
+ <h4>
+ utf8::iterator
+ </h4>
+ <p class="version">
+ Available in version 2.0 and later.
+ </p>
+ <p>
+ Adapts the underlying octet iterator to iterate over the sequence of code points,
+ rather than raw octets.
+ </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
+<span class="keyword">class</span> iterator;
+</pre>
+
+ <h5>Member functions</h5>
+ <dl>
+ <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
+ constructed with its default constructor.
+ <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it);
+ </code> <dd> a constructor
+ that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
+ <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
+ underlying <code>octet_iterator</code>.
+ <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
+ the underlying <code>octet_iterator</code> is pointing to and returns the code point.
+ <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are equal.
+ <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
+ <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+ if the two underlaying iterators are not equal.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
+ the iterator to the next UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+ <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
+ the iterator to the previous UTF-8 encoded code point.
+ <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+ </dl>
+ <p>
+ Example of use:
+ </p>
+<pre>
+<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
+utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it(threechars);
+utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == <span class="literal">0x10346</span>);
+assert (*(++un_it) == <span class="literal">0x65e5</span>);
+assert ((*un_it++) == <span class="literal">0x65e5</span>);
+assert (*un_it == <span class="literal">0x0448</span>);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_endit (threechars + <span class="literal">9</span>);
+assert (++un_it == un_endit);
+assert (*(--un_it) == <span class="literal">0x0448</span>);
+assert ((*un_it--) == <span class="literal">0x0448</span>);
+assert (*un_it == <span class="literal">0x65e5</span>);
+assert (--un_it == utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt;(threechars));
+assert (*un_it == <span class="literal">0x10346</span>);
+</pre>
+ <p>
+ This is an unchecked version of <code>utf8::iterator</code>. It is faster in many cases, but offers
+ no validity or range checks.
+ </p>
+ <h2 id="points">
+ Points of interest
+ </h2>
+ <h4>
+ Design goals and decisions
+ </h4>
+ <p>
+ The library was designed to be:
+ </p>
+ <ol>
+ <li>
+ Generic: for better or worse, there are many C++ string classes out there, and
+ the library should work with as many of them as possible.
+ </li>
+ <li>
+ Portable: the library should be portable both accross different platforms and
+ compilers. The only non-portable code is a small section that declares unsigned
+ integers of different sizes: three typedefs. They can be changed by the users of
+ the library if they don't match their platform. The default setting should work
+ for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives.
+ </li>
+ <li>
+ Lightweight: follow the "pay only for what you use" guideline.
+ </li>
+ <li>
+ Unintrusive: avoid forcing any particular design or even programming style on the
+ user. This is a library, not a framework.
+ </li>
+ </ol>
+ <h4>
+ Alternatives
+ </h4>
+ <p>
+ In case you want to look into other means of working with UTF-8 strings from C++,
+ here is the list of solutions I am aware of:
+ </p>
+ <ol>
+ <li>
+ <a href="http://icu.sourceforge.net/">ICU Library</a>. It is very powerful,
+ complete, feature-rich, mature, and widely used. Also big, intrusive,
+ non-generic, and doesn't play well with the Standard Library. I definitelly
+ recommend looking at ICU even if you don't plan to use it.
+ </li>
+ <li>
+ <a href=
+ "http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html">Glib::ustring</a>.
+ A class specifically made to work with UTF-8 strings, and also feel like
+ <code>std::string</code>. If you prefer to have yet another string class in your
+ code, it may be worth a look. Be aware of the licensing issues, though.
+ </li>
+ <li>
+ Platform dependent solutions: Windows and POSIX have functions to convert strings
+ from one encoding to another. That is only a subset of what my library offers,
+ but if that is all you need it may be good enough, especially given the fact that
+ these functions are mature and tested in production.
+ </li>
+ </ol>
+ <h2 id="conclusion">
+ Conclusion
+ </h2>
+ <p>
+ Until Unicode becomes officially recognized by the C++ Standard Library, we need to
+ use other means to work with UTF-8 strings. Template functions I describe in this
+ article may be a good step in this direction.
+ </p>
+ <h2 id="links">
+ Links
+ </h2>
+ <ol>
+ <li>
+ <a href="http://www.unicode.org/">The Unicode Consortium</a>.
+ </li>
+ <li>
+ <a href="http://icu.sourceforge.net/">ICU Library</a>.
+ </li>
+ <li>
+ <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8 at Wikipedia</a>
+ </li>
+ <li>
+ <a href="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ for
+ Unix/Linux</a>
+ </li>
+ </ol>
+ </body>
+</html>
diff --git a/src/3rdparty/utf8cpp/2.3.2/qt_attribution.json b/src/3rdparty/utf8cpp/2.3.2/qt_attribution.json
new file mode 100644
index 00000000..adaaf096
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/qt_attribution.json
@@ -0,0 +1,12 @@
+{
+ "Id": "utf8cpp",
+ "Name": "Utf8Cpp",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio Studio and Runtime components.",
+
+ "Description": "A simple, portable and lightweight generic library for handling UTF-8 encoded strings.",
+ "Homepage": "http://utfcpp.sourceforge.net/",
+ "License": "Boost Software License",
+ "LicenseId": "BSL-1.0",
+ "Copyright": "Copyright 2006 Nemanja Trifunovic"
+}
diff --git a/src/3rdparty/utf8cpp/2.3.2/source/utf8.h b/src/3rdparty/utf8cpp/2.3.2/source/utf8.h
new file mode 100644
index 00000000..82b13f59
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/source/utf8.h
@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/src/3rdparty/utf8cpp/2.3.2/source/utf8/checked.h b/src/3rdparty/utf8cpp/2.3.2/source/utf8/checked.h
new file mode 100644
index 00000000..3b006444
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/source/utf8/checked.h
@@ -0,0 +1,327 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_t cp;
+ public:
+ invalid_code_point(uint32_t cp) : cp(cp) {}
+ virtual const char* what() const throw() { return "Invalid code point"; }
+ uint32_t code_point() const {return cp;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_t u8;
+ public:
+ invalid_utf8 (uint8_t u) : u8(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-8"; }
+ uint8_t utf8_octet() const {return u8;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_t u16;
+ public:
+ invalid_utf16 (uint16_t u) : u16(u) {}
+ virtual const char* what() const throw() { return "Invalid UTF-16"; }
+ uint16_t utf16_word() const {return u16;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const throw() { return "Not enough space"; }
+ };
+
+ /// The library API - functions intended to be called by the users
+
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (!utf8::internal::is_code_point_valid(cp))
+ throw invalid_code_point(cp);
+
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ throw not_enough_room();
+ case internal::INVALID_LEAD:
+ utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ utf8::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it, octet_iterator end)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it, octet_iterator end)
+ {
+ return utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it, octet_iterator start)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ return utf8::peek_next(it, end);
+ }
+
+ /// Deprecated in versions that include "prior"
+ template <typename octet_iterator>
+ uint32_t previous(octet_iterator& it, octet_iterator pass_start)
+ {
+ octet_iterator end = it;
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == pass_start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ octet_iterator temp = it;
+ return utf8::next(temp, end);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n, octet_iterator end)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ if (utf8::internal::is_trail_surrogate(trail_surrogate))
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ else
+ throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::next(start, end);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start != end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ iterator () {};
+ explicit iterator (const octet_iterator& octet_it,
+ const octet_iterator& range_start,
+ const octet_iterator& range_end) :
+ it(octet_it), range_start(range_start), range_end(range_end)
+ {
+ if (it < range_start || it > range_end)
+ throw std::out_of_range("Invalid utf-8 iterator position");
+ }
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#endif //header guard
+
+
diff --git a/src/3rdparty/utf8cpp/2.3.2/source/utf8/core.h b/src/3rdparty/utf8cpp/2.3.2/source/utf8/core.h
new file mode 100644
index 00000000..693d388c
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/source/utf8/core.h
@@ -0,0 +1,329 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+namespace utf8
+{
+ // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+ // You may need to change them to match your system.
+ // These typedefs have the same names as ones from cstdint, or boost/cstdint
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+ // Unicode constants
+ // Leading (high) surrogates: 0xd800 - 0xdbff
+ // Trailing (low) surrogates: 0xdc00 - 0xdfff
+ const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
+ const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
+ const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+ const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+ const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
+ const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_t>(0xffff & oc);
+ }
+ template<typename octet_type>
+ inline bool is_trail(octet_type oc)
+ {
+ return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+ }
+
+ template <typename u16>
+ inline bool is_lead_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 cp)
+ {
+ return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+ }
+
+ template <typename octet_iterator>
+ inline typename std::iterator_traits<octet_iterator>::difference_type
+ sequence_length(octet_iterator lead_it)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// get_sequence_x functions decode utf-8 sequences of the length x
+ template <typename octet_iterator>
+ utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+ template <typename octet_iterator>
+ utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ // Save the original value of it so we can go back in case of failure
+ // Of course, it does not make much sense with i.e. stream iterators
+ octet_iterator original_it = it;
+
+ uint32_t cp = 0;
+ // Determine the sequence length based on the lead octet
+ typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+ const octet_difference_type length = utf8::internal::sequence_length(it);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+
+ //Deprecated in release 2.3
+ template <typename octet_iterator>
+ inline bool is_bom (octet_iterator it)
+ {
+ return (
+ (utf8::internal::mask8(*it++)) == bom[0] &&
+ (utf8::internal::mask8(*it++)) == bom[1] &&
+ (utf8::internal::mask8(*it)) == bom[2]
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/src/3rdparty/utf8cpp/2.3.2/source/utf8/unchecked.h b/src/3rdparty/utf8cpp/2.3.2/source/utf8/unchecked.h
new file mode 100644
index 00000000..b4547fad
--- /dev/null
+++ b/src/3rdparty/utf8cpp/2.3.2/source/utf8/unchecked.h
@@ -0,0 +1,228 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it)
+ {
+ uint32_t cp = utf8::internal::mask8(*it);
+ typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+ switch (length) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it)
+ {
+ while (utf8::internal::is_trail(*(--it))) ;
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+
+ // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
+ template <typename octet_iterator>
+ inline uint32_t previous(octet_iterator& it)
+ {
+ return utf8::unchecked::prior(it);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n)
+ {
+ for (distance_type i = 0; i < n; ++i)
+ utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::unchecked::next(start);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ public:
+ iterator () {};
+ explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/src/Authoring/Authoring.pro b/src/Authoring/Authoring.pro
new file mode 100644
index 00000000..0e59066d
--- /dev/null
+++ b/src/Authoring/Authoring.pro
@@ -0,0 +1,19 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+# Optional license handler
+isEmpty(TQTC_LICENSE_MANAGING): TQTC_LICENSE_MANAGING=$$(TQTC_LICENSE_MANAGING)
+!isEmpty(TQTC_LICENSE_MANAGING): SUBDIRS += licensehandler.pro
+
+SUBDIRS += \
+ UICDM.pro \
+ Qt3DSState.pro \
+ CoreLib.pro \
+ CommonLib.pro \
+ Q3DStudio.pro \
+ PresentationCompiler.pro
+
+win32 {
+ SUBDIRS += MorphLines.pro
+ qtConfig(qt3dstudio-fbx): SUBDIRS += FBXLineExporter.pro
+}
diff --git a/src/Authoring/Build/versionnumber.h b/src/Authoring/Build/versionnumber.h
new file mode 100644
index 00000000..d60e3609
--- /dev/null
+++ b/src/Authoring/Build/versionnumber.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define FILEVER 0, 2, 1, 0
+#define PRODUCTVER 0, 2, 1, 0
+#define STRFILEVER "0,2,1,0\0"
+#define STRMAJVER "0.2.1\0"
+#define STRPRODUCTVER "0.2.1\0"
+
+#define STRCOMMENTS "\0"
+#define STRCOMPANYNAME "The Qt Company Ltd\0"
+#define STRCOPYRIGHT "Copyright (C) 2017 The Qt Company Ltd.\0"
+#define STRPRODUCTNAME "Qt 3D Studio "
diff --git a/src/Authoring/Client/Code/Core/ClientErrorIDs.h b/src/Authoring/Client/Code/Core/ClientErrorIDs.h
new file mode 100644
index 00000000..69dfa7ec
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/ClientErrorIDs.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef __CLIENTERRORIDS_H__
+#define __CLIENTERRORIDS_H__
+
+#include "UICExceptions.h"
+
+//==============================================================================
+// Defines
+//==============================================================================
+
+///< Base = 0x80040000
+
+const unsigned long GLOBALCLIENT_START_ERROR_RANGE = 10000; ///< 0x80042710
+const unsigned long GLOBALCLIENT_END_ERROR_RANGE = 10499; ///< 0x80042903
+const unsigned long CONTROLLER_START_ERROR_RANGE = 10500; ///< 0x80042904
+const unsigned long EVENT_START_ERROR_RANGE = 11000; ///< 0x80042AF8
+const unsigned long GIT_START_ERROR_RANGE = 11500; ///< 0x80042CEC
+const unsigned long ICE_START_ERROR_RANGE = 12000; ///< 0x80042EE0
+const unsigned long IOLIBRARY_START_ERROR_RANGE = 12500; ///< 0x800430D4
+const unsigned long LIBRARY_START_ERROR_RANGE = 13000; ///< 0x800432C8
+const unsigned long OBJECTMODEL_START_ERROR_RANGE = 13500; ///< 0x800434BC
+const unsigned long PLAYERCP_START_ERROR_RANGE = 14000; ///< 0x800436B0
+const unsigned long PLAYER_START_ERROR_RANGE = 14500; ///< 0x800438A4
+const unsigned long RENDER_START_ERROR_RANGE = 15000; ///< 0x80043A98
+const unsigned long COMPRESSION_START_ERROR_RANGE = 15400; ///< 0x80043C28
+const unsigned long SCRIPTENGINE_START_ERROR_RANGE = 15500; ///< 0x80043C8C
+const unsigned long UNUSED1 = 16000; ///< 0x80043E80
+const unsigned long TIMER_START_ERROR_RANGE = 16500; ///< 0x80044074
+const unsigned long TRANSM_START_ERROR_RANGE = 17000; ///< 0x80044268
+const unsigned long TYPES_START_ERROR_RANGE = 17500; ///< 0x8004445C
+const unsigned long UTILITY_START_ERROR_RANGE = 18000; ///< 0x80044650
+
+const unsigned long PLUGIN3DS_START_ERROR_RANGE = 18400; ///< 0x800447E0
+const unsigned long PLUGINUICA_START_ERROR_RANGE = 18450; ///< 0x80044812
+const unsigned long PLUGINUICB_START_ERROR_RANGE = 18500; ///< 0x
+const unsigned long PLUGINUICI_START_ERROR_RANGE = 18550; ///< 0x
+const unsigned long PLUGINUICM_START_ERROR_RANGE = 18600; ///< 0x
+const unsigned long PLUGINBVS_START_ERROR_RANGE = 18650; ///< 0x
+const unsigned long PLUGINAKS_START_ERROR_RANGE = 18700; ///< 0x
+const unsigned long PLUGINIMG_START_ERROR_RANGE = 18750; ///< 0x
+const unsigned long PLUGINMP3_START_ERROR_RANGE = 18800; ///< 0x
+const unsigned long PLUGINUICTM_START_ERROR_RANGE = 18850; ///< 0x
+const unsigned long PLUGINWMM_START_ERROR_RANGE = 19900; ///< 0x
+
+const unsigned long UICCLIENT_START_ERROR_RANGE = 20000; ///< 0x80044e20
+
+const unsigned long INSTALLER_START_ERROR_RANGE = 21000; ///< 0x80045208
+const unsigned long INSTANCEDATA_START_ERROR_RANGE = 21500; ///< 0x
+const unsigned long SHARED_START_ERROR_RANGE = 21600; ///< 0x
+const unsigned long GLRENDER_START_ERROR_RANGE = 21700; ///< 0x
+
+// NOTE: The Component project has many, many objects, each of which may
+// have many many errors. Leave a large block of numbers reserved for the
+// Component errors. Each element should also leave room at the end of
+// its sub-allocation so the list can grow with the least amount of trauma.
+const unsigned long COMPONENT_START_ERROR_RANGE = 22000; ///< 0x
+const unsigned long UNUSED5 = 27000; ///< 0x
+
+#ifndef FACILITY_ITF
+#define FACILITY_ITF 0x0004
+#endif
+
+#ifndef MAKE_HRESULT
+#define MAKE_HRESULT(sev,fac,code) \
+ ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+#endif
+
+//==============================================================================
+// HRESULTS
+//==============================================================================
+#define GLOBALCLIENT_ERROR(inID, inName) \
+ const HRESULT inName = \
+ MAKE_HRESULT(LEVEL_ERROR, FACILITY_ITF, GLOBALCLIENT_START_ERROR_RANGE + inID);
+
+GLOBALCLIENT_ERROR(
+ 0, GLOBALCLIENT_E_FATALERROR) ///< 0x80042710 - Sell the farm jenny, the cows have all gone home
+GLOBALCLIENT_ERROR(1, GLOBALCLIENT_E_FAILEDTORENDER) ///< 0x80042711
+
+const HRESULT GLOBALCLIENT_E_STARTRANGE =
+ MAKE_HRESULT(LEVEL_ERROR, FACILITY_ITF, GLOBALCLIENT_START_ERROR_RANGE);
+const HRESULT GLOBALCLIENT_E_ENDRANGE =
+ MAKE_HRESULT(LEVEL_ERROR, FACILITY_ITF, GLOBALCLIENT_END_ERROR_RANGE);
+
+//==============================================================================
+// Logging bits for seperate modules
+//==============================================================================
+
+const unsigned long LOGTYPE_GLOBALCLIENT = 0x00000001;
+const unsigned long LOGTYPE_STUDIOCLIENT = 0x00000002;
+const unsigned long LOGTYPE_CONTROLLER = 0x00000004;
+const unsigned long LOGTYPE_COMPONENT = 0x00000008;
+const unsigned long LOGTYPE_PLAYERCP = 0x00000010;
+const unsigned long LOGTYPE_PLAYER = 0x00000020;
+const unsigned long LOGTYPE_RENDER = 0x00000040;
+const unsigned long LOGTYPE_SCRIPTENGINE = 0x00000080;
+const unsigned long LOGTYPE_LIBRARY = 0x00000100;
+const unsigned long LOGTYPE_BVS = 0x00000200;
+const unsigned long LOGTYPE_TRANSM = 0x00000400;
+const unsigned long LOGTYPE_UTILITY = 0x00000800;
+const unsigned long LOGTYPE_TYPES = 0x00001000;
+const unsigned long LOGTYPE_REFCOUNTS = 0x00002000;
+const unsigned long LOGTYPE_OBJECTMODEL = 0x00004000;
+const unsigned long LOGTYPE_ICELIB = 0x00008000;
+const unsigned long LOGTYPE_THREAD = 0x00008001;
+
+// Save 0x80000000 to use as a flag to identify
+// the next range of bit masks
+// const unsigned long UNUSED_ID = 0x80000001;
+
+typedef struct _TSLogTypeEntry
+{
+ long m_LogTypeBitMask;
+ char m_LogTypeName[15];
+
+} TSLogTypeEntry;
+
+const TSLogTypeEntry g_LogTypeNameMap[] = {
+ { LOGTYPE_GLOBALCLIENT, "GLOBAL" },
+ { LOGTYPE_STUDIOCLIENT, "CLIENT" },
+ { LOGTYPE_CONTROLLER, "CONTROLLER" },
+ { LOGTYPE_COMPONENT, "COMPONENT" },
+ { LOGTYPE_PLAYERCP, "CONNECTPOINT" },
+ { LOGTYPE_PLAYER, "PLAYER" },
+ { LOGTYPE_RENDER, "RENDER" },
+ { LOGTYPE_SCRIPTENGINE, "SCRIPT" },
+ { LOGTYPE_LIBRARY, "LIBRARY" },
+ { LOGTYPE_BVS, "BVS" },
+ { LOGTYPE_TRANSM, "TRANSM" },
+ { LOGTYPE_UTILITY, "UTILITY" },
+ { LOGTYPE_TYPES, "TYPES" },
+ { LOGTYPE_REFCOUNTS, "REFCOUNTS" },
+ { LOGTYPE_OBJECTMODEL, "OBJECTMODEL" },
+ { LOGTYPE_ICELIB, "ICELIB" },
+ { LOGTYPE_THREAD, "THREAD" },
+};
+
+const long g_LogTypeNameMapSize = sizeof(g_LogTypeNameMap) / sizeof(TSLogTypeEntry);
+
+#endif // #ifndef __CLIENTERRORIDS_H__
diff --git a/src/Authoring/Client/Code/Core/Commands/Cmd.cpp b/src/Authoring/Client/Code/Core/Commands/Cmd.cpp
new file mode 100644
index 00000000..1d9cbd2e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/Cmd.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "Cmd.h"
+
+//=============================================================================
+/**
+ * Constructor: By default, all commands should set the modified flag.
+ */
+//=============================================================================
+CCmd::CCmd()
+ : m_Committed(false)
+ , m_Undoable(true)
+ , m_ShouldSetModified(true)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+//=============================================================================
+CCmd::~CCmd()
+{
+}
+
+//=============================================================================
+/**
+ * Set this command as being committed.
+ * This is used by the CmdStack to avoid merging commands that should not be.
+ * A command is automatically committed when it is undone (to avoid merges after
+ * a redo command).
+ *
+ * @param inCommitted the new value for the committed flag.
+ */
+//=============================================================================
+void CCmd::SetCommitted(bool inCommitted)
+{
+ m_Committed = inCommitted;
+}
+
+//=============================================================================
+/**
+ * Returns true if this command is committed.
+ * If the command is committed no commands should be merged into it, but it
+ * can be merged into others. After the merge the committed flag should be
+ * carried over to the other command.
+ */
+//=============================================================================
+bool CCmd::IsCommitted()
+{
+ return m_Committed;
+}
+
+//=============================================================================
+/**
+ * @return a semi-descriptive string of this command.
+ */
+//=============================================================================
+QString CCmd::ToString()
+{
+ Q3DStudio::CString theString;
+ theString.Format(_UIC("Command - %d"), GetType());
+
+ return theString.toQString();
+}
+
+//=============================================================================
+/**
+ * Allows you to dynamically specify whether or not a command should mark the
+ * doc as dirty or not.
+ *
+ * @param inShouldSetModifiedFlag true if the modified flag should be set on the doc
+ */
+//=============================================================================
+void CCmd::SetModifiedFlag(bool inShouldSetModifiedFlag)
+{
+ m_ShouldSetModified = inShouldSetModifiedFlag;
+}
+
+//=============================================================================
+/**
+ * This tells the Command Stack whether or not this command is modifying the
+ * document. It is used to turn on/off the document's save flag.
+ *
+ * @return true if the document was modified.
+ */
+//=============================================================================
+bool CCmd::ShouldSetModifiedFlag()
+{
+ return m_ShouldSetModified;
+}
+
+//=============================================================================
+/**
+ * Set whether this command can be undone or not.
+ *
+ * @param inUndoable true if this command is to be undoable.
+ */
+//=============================================================================
+void CCmd::SetUndoable(bool inUndoable)
+{
+ m_Undoable = inUndoable;
+}
+
+//=============================================================================
+/**
+ * Checks to see if this command can be undone.
+ * If it cannot be undone then the CmdStack will not put it into the Undo
+ * list and will not modify the Redo list when this is performed. The CmdStack
+ * will delete this command immediately.
+ *
+ * @return true if this command can be undone.
+ */
+//=============================================================================
+bool CCmd::IsUndoable()
+{
+ return m_Undoable;
+}
+
+//=============================================================================
+/**
+ * Checks to see if the incoming command can be merged with this command.
+ * The incoming command and this command should not be modified in any way.
+ * @param inCommand the command to see if this can be merged with
+ * @return true if the command can be merged.
+ */
+//=============================================================================
+bool CCmd::CanMerge(CCmd *inCommand)
+{
+ Q_UNUSED(inCommand);
+ return false;
+}
+
+//=============================================================================
+/**
+ * Merge the incoming command into this one.
+ * The incoming command should not be modified in any way, this command will
+ * reflect the merge.
+ * This method should only be called after CanMerge has returned successfully
+ * and this command is not committed.
+ * @param inCommand the command to be merged into this one.
+ */
+//=============================================================================
+void CCmd::Merge(CCmd *inCommand)
+{
+ Q_UNUSED(inCommand);
+}
+
+//=============================================================================
+/**
+ * Get the type of command this is.
+ * The primary useage is for CanMerge to check the type of command.
+ * @return the type of command this is.
+ */
+//=============================================================================
+CCmd::ECmdType CCmd::GetType()
+{
+ return GENERIC;
+}
diff --git a/src/Authoring/Client/Code/Core/Commands/Cmd.h b/src/Authoring/Client/Code/Core/Commands/Cmd.h
new file mode 100644
index 00000000..9c6c68b8
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/Cmd.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_H
+#define INCLUDED_CMD_H 1
+
+#pragma once
+
+#include "UICString.h"
+
+class CCmd
+{
+public:
+ // All the types of commands that can be fired off.
+ // This is mostly used in the CanMerge functions.
+ enum ECmdType {
+ REARRANGE,
+ DROP_REARRANGE,
+ DELETE_OBJECT,
+ ADD_OBJECT,
+ KEYFRAME_CHANGE,
+ PROPERTY_CHANGE,
+ VECTOR_CHANGE,
+ COLOR_CHANGE,
+ TIMERANGE_CHANGE,
+ TIMERANGE_TRUNCATION,
+ BATCH,
+ REMOVE_TRACK,
+ INTERPOLATION_CHANGE,
+ GENERIC,
+ ACTION_ADD,
+ ACTION_DELETE,
+ ACTION_MOVE,
+ ACTION_CUT,
+ ACTION_COPY,
+ ACTION_PASTE,
+ ACTIONPARAM_SET,
+ REFRESH_RESOURCE,
+ DATAMODEL_SET_PROPERTY,
+ DATAMODEL_SET_PROPERTY_INSTANCE_GUID,
+ DATAMODEL_CLEAR_PROPERTY_INSTANCE_GUID
+ };
+
+ virtual ~CCmd();
+
+ //==========================================================================
+ /**
+ * Perform the action this command is supposed to do.
+ * This is called by the CmdStack when the command is first issued and
+ * when the command is to be redone.
+ * The return code of this is used to refresh whichever views need to be
+ * refreshed, and is used as an argument to StudioDoc::UpdateAllViews. This
+ * is returned to avoid batched commands causing multiple refreshes.
+ *
+ * @return a long used for the UpdateViews mask.
+ */
+ //==========================================================================
+ virtual unsigned long Do() = 0;
+
+ //==========================================================================
+ /**
+ * Undo the action that was performed.
+ * This only needs to be functional if the command can be undoable.
+ * This function is called by the CmdStack when this command is to be undone.
+ * The return code of this is used to refresh whichever views need to be
+ * refreshed, and is used as an argument to StudioDoc::UpdateAllViews. This
+ * is returned to avoid batched commands causing multiple refreshes.
+ *
+ * @return a long used for the UpdateViews mask.
+ */
+ //==========================================================================
+ virtual unsigned long Undo() = 0;
+
+ virtual ECmdType GetType();
+
+ virtual bool CanMerge(CCmd *inCommand);
+ virtual void Merge(CCmd *inCommand);
+
+ virtual void SetUndoable(bool inUndoable);
+ virtual bool IsUndoable();
+
+ virtual bool IsCommitted();
+ virtual void SetCommitted(bool inCommitted);
+
+ virtual void SetModifiedFlag(bool inShouldSetModifiedFlag);
+ virtual bool ShouldSetModifiedFlag();
+
+ virtual QString ToString();
+
+ virtual bool IsInvalidated() { return false; }
+
+protected:
+ CCmd();
+ bool m_Committed;
+ bool m_Undoable;
+ bool m_ShouldSetModified;
+};
+
+//==============================================================================
+/**
+ * Commands that do not modify the uip file, thus should not dirty the presentation and not
+ * undoable.
+ */
+class CNonModifyingCmd : public CCmd
+{
+public:
+ CNonModifyingCmd()
+ {
+ m_ShouldSetModified = false;
+ m_Undoable = false;
+ };
+};
+
+#endif // INCLUDED_CMD_H
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.cpp b/src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.cpp
new file mode 100644
index 00000000..24cab68e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "CmdActivateSlide.h"
+#include "Doc.h"
+#include "UICDMSlides.h"
+#include "UICDMStudioSystem.h"
+#include "SlideSystem.h"
+#include "ClientDataModelBridge.h"
+
+#include <QObject>
+
+CCmdActivateSlide::CCmdActivateSlide(CDoc *inDoc, UICDM::CUICDMSlideHandle inSlideHandle)
+ : m_Doc(inDoc)
+ , m_SlideHandle(inSlideHandle)
+ , m_ForceRefresh(true)
+{
+}
+
+CCmdActivateSlide::CCmdActivateSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance)
+ : m_Doc(inDoc)
+ , m_ForceRefresh(true)
+{
+ CClientDataModelBridge *theBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ Q3DStudio::CId theId = theBridge->GetGUID(inInstance);
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theId));
+ m_SlideHandle = theSlideSystem->GetActiveSlide(theMasterSlide);
+}
+
+CCmdActivateSlide::~CCmdActivateSlide()
+{
+}
+
+unsigned long CCmdActivateSlide::Do()
+{
+ m_Doc->NotifyActiveSlideChanged(m_SlideHandle, m_ForceRefresh);
+ return 0;
+}
+
+unsigned long CCmdActivateSlide::Undo()
+{
+ return 0;
+}
+
+QString CCmdActivateSlide::ToString()
+{
+ return QObject::tr("Activate Slide");
+}
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.h b/src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.h
new file mode 100644
index 00000000..f211f4d4
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdActivateSlide.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_ACTIVATE_SLIDE_H
+#define INCLUDED_CMD_ACTIVATE_SLIDE_H 1
+
+#pragma once
+
+#include "Cmd.h"
+#include "UICDMHandles.h"
+
+class CDoc;
+
+namespace UICDM {
+class ISlideSystem;
+class CUICDMSlideHandle;
+};
+
+class CCmdActivateSlide : public CNonModifyingCmd
+{
+public:
+ CCmdActivateSlide(CDoc *inDoc, UICDM::CUICDMSlideHandle inSlideHandle);
+ CCmdActivateSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance);
+ virtual ~CCmdActivateSlide();
+
+ unsigned long Do() override;
+ unsigned long Undo() override;
+
+ QString ToString() override;
+
+ void SetForceRefresh(bool inForce) { m_ForceRefresh = inForce; }
+
+protected:
+ CDoc *m_Doc;
+ UICDM::CUICDMSlideHandle m_SlideHandle;
+ bool m_ForceRefresh;
+};
+#endif // INCLUDED_CMD_ACTIVATE_SLIDE_H
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdBatch.cpp b/src/Authoring/Client/Code/Core/Commands/CmdBatch.cpp
new file mode 100644
index 00000000..cd4c0750
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdBatch.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//#ifndef INCLUDED_CMD_BATCH_H
+#include "CmdBatch.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "StudioFullSystem.h"
+#include "UICDMSignals.h"
+#include "Core.h"
+#include "Dispatch.h"
+//#endif
+
+//=============================================================================
+/**
+ * Constructor. Nothing new here...
+ */
+//=============================================================================
+CCmdBatch::CCmdBatch(CDoc *inDoc)
+ : m_ExecutionCount(0)
+ , m_Dispatch(inDoc->GetCore()->GetDispatch())
+{
+ m_Undoable = true;
+}
+
+CCmdBatch::CCmdBatch(CCore *inCore)
+ : m_ExecutionCount(0)
+ , m_Dispatch(inCore->GetDispatch())
+{
+ m_Undoable = true;
+}
+
+//=============================================================================
+/**
+ * Destructor, deletes all commands added to this.
+ */
+//=============================================================================
+CCmdBatch::~CCmdBatch()
+{
+ this->Clear();
+}
+
+//=============================================================================
+/**
+ * Add a command to this batch.
+ * Any time comparable batches are created the commands MUST be added in the
+ * same order so that they can merge properly. All commands added to this will
+ * be deleted by this object when it is deleted itself.
+ *
+ * @param inCommand the command to be added to this batch.
+ */
+//=============================================================================
+void CCmdBatch::AddCommand(CCmd *inCommand, bool inAddFront)
+{
+ if (inAddFront)
+ m_CommandList.insert(m_CommandList.begin(), inCommand);
+ else
+ m_CommandList.push_back(inCommand);
+}
+
+//=============================================================================
+/**
+ * Calls Do on every sub command.
+ */
+//=============================================================================
+unsigned long CCmdBatch::Do()
+{
+ unsigned long theUpdateFlags = 0;
+
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Dispatch);
+
+ TCmdList::iterator thePos = m_CommandList.begin();
+ thePos += m_ExecutionCount;
+
+ for (; thePos != m_CommandList.end(); ++thePos) {
+ theUpdateFlags |= (*thePos)->Do();
+ ++m_ExecutionCount;
+ }
+
+ return theUpdateFlags;
+}
+
+//=============================================================================
+/**
+ * Calls undo on every sub command.
+ */
+//=============================================================================
+unsigned long CCmdBatch::Undo()
+{
+ unsigned long theUpdateFlags = 0;
+
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Dispatch);
+
+ TCmdList::reverse_iterator thePos = m_CommandList.rbegin();
+ for (; thePos != m_CommandList.rend(); ++thePos) {
+ theUpdateFlags |= (*thePos)->Undo();
+ }
+
+ m_ExecutionCount = 0;
+
+ return theUpdateFlags;
+}
+
+//=============================================================================
+/**
+ * @return the type of command that this is.
+ */
+//=============================================================================
+CCmd::ECmdType CCmdBatch::GetType()
+{
+ return CCmd::BATCH;
+}
+
+//=============================================================================
+/**
+ * If inCommand is a Batch command and both batches have the same number of
+ * sub commands and each sub command can merge with it's counterpart then this
+ * will return true. Sub commands are merged to the sub command in the other
+ * batch at the same index.
+ *
+ * @param inCommand the command to be check if it can be merged.
+ * @return true if a merge can be done.
+ */
+//=============================================================================
+bool CCmdBatch::CanMerge(CCmd *inCommand)
+{
+ bool theRetVal = false;
+
+ // Check the type to make sure it is the same as this.
+ if (inCommand->GetType() == this->GetType()) {
+ CCmdBatch *theCommand = reinterpret_cast<CCmdBatch *>(inCommand);
+ // Make sure both commands are the same size.
+ if (theCommand->m_CommandList.size() == m_CommandList.size()) {
+ // Go through all the sub commands and compare each one to the one at the same index on
+ // the other command.
+ TCmdList::iterator myPos = m_CommandList.begin();
+ TCmdList::iterator itsPos = theCommand->m_CommandList.begin();
+
+ theRetVal = true;
+ for (; myPos != m_CommandList.end(); ++myPos, ++itsPos) {
+ // Stop checking if one cannot merge.
+ if (!(*myPos)->CanMerge(*itsPos)) {
+ // Set the return value to false, cannot merge.
+ theRetVal = false;
+ break;
+ }
+ }
+ }
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Perform the merge of the two batch commands.
+ * This will call Merge on each sub command of this with the command at the same
+ * index on inCommand.
+ *
+ * @param inCommand the command to be merged.
+ */
+//=============================================================================
+void CCmdBatch::Merge(CCmd *inCommand)
+{
+ CCmdBatch *theCommand = reinterpret_cast<CCmdBatch *>(inCommand);
+
+ // Go through all the sub commands and merge each one with the one at the same index on the
+ // other command.
+ TCmdList::iterator myPos = m_CommandList.begin();
+ TCmdList::iterator itsPos = theCommand->m_CommandList.begin();
+
+ for (; myPos != m_CommandList.end(); ++myPos, ++itsPos) {
+ (*myPos)->Merge(*itsPos);
+ }
+}
+
+//=============================================================================
+/**
+ * This just uses the description of the first command within it, or blank if
+ * there are no sub commands.
+ *
+ * @return a description of this command.
+ */
+//=============================================================================
+QString CCmdBatch::ToString()
+{
+ if (m_CommandList.size() > 0) {
+ CCmd *theFirstCommand = m_CommandList.at(0);
+ return theFirstCommand->ToString();
+ }
+ return {};
+}
+
+//=============================================================================
+/**
+ * Set the committed state of this command.
+ * This will set committed on all sub commands as well.
+ *
+ * @param inCommitted the new status of the committed flag.
+ */
+//=============================================================================
+void CCmdBatch::SetCommitted(bool inCommitted)
+{
+ CCmd::SetCommitted(inCommitted);
+
+ TCmdList::iterator thePos = m_CommandList.begin();
+ for (; thePos != m_CommandList.end(); ++thePos) {
+ (*thePos)->SetCommitted(inCommitted);
+ }
+}
+
+//=============================================================================
+/**
+ * Checks to see if this command is undoable.
+ * This will return true if it's undoable flag is true and if it has sub commands
+ * and if all the sub commands can be undone.
+ *
+ * @return true if this can be undone.
+ */
+//=============================================================================
+bool CCmdBatch::IsUndoable()
+{
+ bool isUndoable = m_Undoable;
+
+ /* I am commenting this out because I feel this is more correct.
+ if ( m_CommandList.size( ) == 0 )
+ {
+ isUndoable = false;
+ }
+ else
+ {
+ */
+ TCmdList::iterator thePos = m_CommandList.begin();
+ for (; thePos != m_CommandList.end(); ++thePos) {
+ isUndoable &= (*thePos)->IsUndoable();
+ }
+ //}
+ return isUndoable;
+}
+
+//=============================================================================
+/**
+ * Deletes all the commands within this and empties the list.
+ */
+//=============================================================================
+void CCmdBatch::Clear()
+{
+ TCmdList::iterator thePos = m_CommandList.begin();
+ for (; thePos != m_CommandList.end(); ++thePos) {
+ delete (*thePos);
+ }
+
+ m_CommandList.clear();
+ m_ExecutionCount = 0;
+}
+
+//=============================================================================
+/**
+ * Get the number of command objects within this batch, nice for testing.
+ * @return the number of command objects in this batch, not recursive.
+ */
+//=============================================================================
+size_t CCmdBatch::GetCommandCount()
+{
+ return m_CommandList.size();
+}
+
+//==============================================================================
+/**
+ * Go through the command list to erase any invalid commands
+ * @return true if there command list is empty
+ */
+bool CCmdBatch::IsInvalidated()
+{
+ TCmdList::iterator thePos = m_CommandList.begin();
+ while (thePos != m_CommandList.end()) {
+ if ((*thePos)->IsInvalidated()) {
+ delete (*thePos);
+ thePos = m_CommandList.erase(thePos);
+ } else
+ ++thePos;
+ }
+ // if there are no more commands than, this batch is considered invalidated.
+ return (m_CommandList.empty());
+}
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdBatch.h b/src/Authoring/Client/Code/Core/Commands/CmdBatch.h
new file mode 100644
index 00000000..e8564169
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdBatch.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_CMD_BATCH_H
+#define INCLUDED_CMD_BATCH_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Cmd.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CDoc;
+class CDispatch;
+class CCore;
+namespace UICDM {
+class IStudioFullSystemSignalSender;
+}
+
+//==============================================================================
+/**
+* CCmdBatch
+*/
+class CCmdBatch : public CCmd
+{
+ typedef std::vector<CCmd *> TCmdList;
+
+public:
+ CCmdBatch(CDoc *inDoc);
+ CCmdBatch(CCore *inCore);
+ virtual ~CCmdBatch();
+
+ void AddCommand(CCmd *inCommand, bool inAddFront = false);
+
+ unsigned long Do() override;
+ unsigned long Undo() override;
+
+ CCmd::ECmdType GetType() override;
+ bool IsInvalidated() override;
+
+ bool CanMerge(CCmd *inCommand) override;
+ void Merge(CCmd *inCommand) override;
+ void SetCommitted(bool inCommitted) override;
+ bool IsUndoable() override;
+ QString ToString() override;
+ size_t GetCommandCount();
+ void Clear();
+
+protected:
+ TCmdList m_CommandList;
+ long m_ExecutionCount;
+
+ CDispatch *m_Dispatch;
+};
+
+#endif // INCLUDED_CMD_BATCH_H
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdCloseWindow.h b/src/Authoring/Client/Code/Core/Commands/CmdCloseWindow.h
new file mode 100644
index 00000000..6203a89c
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdCloseWindow.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_CMD_CLOSE_WINDOW_H
+#define INCLUDED_CMD_CLOSE_WINDOW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Cmd.h"
+#include "DialogControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// CCmd to close a modal window
+//==============================================================================
+class CCmdCloseWindow : public CCmd
+{
+public:
+ CCmdCloseWindow(CDialogControl *inDialog)
+ : m_Dialog(inDialog)
+ {
+ SetUndoable(false);
+ }
+
+ unsigned long Do() override
+ {
+ if (m_Dialog)
+ m_Dialog->EndWindow();
+ return 0;
+ }
+
+ unsigned long Undo() override { return 0; }
+
+protected:
+ CDialogControl *m_Dialog;
+};
+
+#endif // INCLUDED_CMD_CLOSE_WINDOW_H
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp b/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp
new file mode 100644
index 00000000..bde0cab9
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "CmdDataModel.h"
+#include <boost/bind.hpp>
+#include <boost/utility.hpp>
+#include <boost/function.hpp>
+#include <boost/bind/apply.hpp>
+#include "UICDMTransactions.h"
+#include "UICDMStudioSystem.h"
+#include "Doc.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include <boost/make_shared.hpp>
+#include "foundation/Qt3DSLogging.h"
+
+using namespace boost;
+
+namespace UICDM {
+
+void SApplicationState::Store(CDoc &inDoc)
+{
+ m_Dirty = inDoc.IsModified();
+ m_SelectedInstance = inDoc.GetSelectedInstance();
+ m_ActiveSlide = inDoc.GetActiveSlide();
+ m_ActiveLayer = inDoc.GetActiveLayer();
+}
+
+void SApplicationState::Notify(const SApplicationState &inOther, CDoc &inDoc)
+{
+ if (m_Dirty != inOther.m_Dirty)
+ inDoc.SetModifiedFlag(m_Dirty);
+
+ if (m_ActiveLayer != inOther.m_ActiveLayer)
+ inDoc.SetActiveLayer(m_ActiveLayer);
+
+ if (m_ActiveSlide != inOther.m_ActiveSlide)
+ inDoc.NotifyActiveSlideChanged(m_ActiveSlide, true);
+
+ if (m_SelectedInstance != inOther.m_SelectedInstance)
+ inDoc.SelectUICDMObject(m_SelectedInstance);
+}
+
+// We clear the selection just as a precaution because we want to be sure that
+// if this command tends to delete things that there is nothing referring
+// to a deleted item
+void SApplicationState::PreNotify(const SApplicationState &inOther, CDoc &inDoc)
+{
+ if (m_SelectedInstance != inOther.m_SelectedInstance) {
+ inDoc.DeselectAllItems(false);
+ }
+}
+
+CmdDataModel::CmdDataModel(CDoc &inDoc)
+ : m_Doc(inDoc)
+{
+}
+CmdDataModel::~CmdDataModel()
+{
+}
+
+void CmdDataModel::SetName(const Q3DStudio::CString &inName)
+{
+ m_Name = inName;
+}
+Q3DStudio::CString CmdDataModel::GetName() const
+{
+ return m_Name;
+}
+bool CmdDataModel::HasTransactions()
+{
+ return m_Consumer != NULL
+ && ((CTransactionConsumer *)m_Consumer.get())->m_TransactionList.size() > 0;
+}
+
+bool CmdDataModel::ConsumerExists()
+{
+ return m_Consumer != NULL;
+}
+
+void CmdDataModel::SetConsumer(ITransactionProducer *inProducer)
+{
+ if (!ConsumerExists())
+ m_Consumer = std::make_shared<CTransactionConsumer>();
+ inProducer->SetConsumer(m_Consumer);
+}
+
+void CmdDataModel::ReleaseConsumer(ITransactionProducer *inProducer, bool inRunNotifications)
+{
+ inProducer->SetConsumer(TTransactionConsumerPtr());
+ if (inRunNotifications)
+ RunDoNotifications();
+}
+
+void CmdDataModel::SetConsumer()
+{
+ if (!ConsumerExists()) {
+ m_Doc.GetCore()->GetDispatch();
+ SetConsumer(m_Doc.GetStudioSystem());
+ m_Doc.GetAssetGraph()->SetConsumer(m_Consumer);
+ m_BeforeDoAppState.Store(m_Doc);
+ }
+}
+
+void CmdDataModel::ReleaseConsumer(bool inRunNotifications)
+{
+ if (ConsumerExists()) {
+ m_Doc.GetAssetGraph()->SetConsumer(TTransactionConsumerPtr());
+ if (HasTransactions())
+ m_Doc.SetModifiedFlag(true);
+ m_AfterDoAppState.Store(m_Doc);
+ ReleaseConsumer(m_Doc.GetStudioSystem(), inRunNotifications);
+ }
+}
+
+void CmdDataModel::DataModelUndo()
+{
+ if (ConsumerExists() && HasTransactions()) {
+ qCInfo(qt3ds::TRACE_INFO) << "Undoing " << m_Name.GetCharStar()
+ << " generated from: " << m_File.GetCharStar() << "(" << m_Line << ")";
+ m_AfterDoAppState.Store(m_Doc);
+ m_AfterDoAppState.PreNotify(m_BeforeDoAppState, m_Doc);
+ Undo(m_Consumer->m_TransactionList);
+ RunUndoNotifications();
+ }
+}
+
+void CmdDataModel::RunUndoNotifications()
+{
+ if (ConsumerExists()) {
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Doc.GetCore()->GetDispatch());
+ NotifyReverse(m_Consumer->m_UndoNotifications);
+ m_BeforeDoAppState.Notify(m_AfterDoAppState, m_Doc);
+ }
+}
+
+void CmdDataModel::DataModelRedo()
+{
+ if (ConsumerExists() && HasTransactions()) {
+ qCInfo(qt3ds::TRACE_INFO) << "Redoing " << m_Name.GetCharStar()
+ << " generated from: " << m_File.GetCharStar() << "(" << m_Line << ")";
+ m_BeforeDoAppState.Store(m_Doc);
+ m_BeforeDoAppState.PreNotify(m_AfterDoAppState, m_Doc);
+ Redo(m_Consumer->m_TransactionList);
+ RunDoNotifications();
+ }
+}
+
+void CmdDataModel::RunDoNotifications()
+{
+ if (ConsumerExists()) {
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Doc.GetCore()->GetDispatch());
+ Notify(m_Consumer->m_DoNotifications);
+ m_AfterDoAppState.Notify(m_BeforeDoAppState, m_Doc);
+ }
+}
+
+void CmdDataModel::DataModelRollback()
+{
+ if (ConsumerExists()) {
+ DataModelUndo();
+ m_Consumer->m_DoNotifications.clear();
+ m_Consumer->m_UndoNotifications.clear();
+ m_Consumer->m_TransactionList.clear();
+ }
+}
+}
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModel.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModel.h
new file mode 100644
index 00000000..6442eb18
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModel.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef CMDDATAMODELH
+#define CMDDATAMODELH
+#include "UICDMHandles.h"
+#include "UICString.h"
+
+class CDoc;
+class CDispatch;
+
+namespace UICDM {
+class ITransactionConsumer;
+class ITransactionProducer;
+struct CTransactionConsumer;
+
+struct SApplicationState
+{
+ bool m_Dirty;
+ UICDM::CUICDMInstanceHandle m_SelectedInstance;
+ UICDM::CUICDMSlideHandle m_ActiveSlide;
+ UICDM::CUICDMInstanceHandle m_ActiveLayer;
+
+ SApplicationState()
+ : m_Dirty(false)
+ {
+ }
+ void Store(CDoc &inDoc);
+ void PreNotify(const SApplicationState &inOther, CDoc &inDoc);
+ void Notify(const SApplicationState &inOther, CDoc &inDoc);
+};
+
+class CmdDataModel
+{
+public:
+ Q3DStudio::CString m_Name;
+ Q3DStudio::CString m_File;
+ int m_Line;
+
+ CmdDataModel(CDoc &inDoc);
+ ~CmdDataModel();
+ void SetName(const Q3DStudio::CString &inName);
+ Q3DStudio::CString GetName() const;
+ bool HasTransactions();
+ bool ConsumerExists();
+ void SetConsumer();
+ void ReleaseConsumer(bool inRunNotifications = true);
+ void DataModelUndo();
+ void DataModelRedo();
+ void DataModelRollback();
+ void RunDoNotifications();
+ void RunUndoNotifications();
+ void CheckForSelectionChange(CUICDMInstanceHandle inOldInstance,
+ CUICDMInstanceHandle inNewInstance);
+
+protected:
+ std::shared_ptr<CTransactionConsumer> m_Consumer;
+ CDoc &m_Doc;
+
+ // The application state before this command
+ SApplicationState m_BeforeDoAppState;
+ // The application state after this command.
+ SApplicationState m_AfterDoAppState;
+
+private:
+ void SetConsumer(ITransactionProducer *inProducer);
+ void ReleaseConsumer(ITransactionProducer *inProducer, bool inRunNotifications);
+};
+
+struct SScopedDataModelConsumer
+{
+ CmdDataModel &m_Cmd;
+ bool m_Opened;
+ SScopedDataModelConsumer(CmdDataModel &cmd)
+ : m_Cmd(cmd)
+ , m_Opened(false)
+ {
+ if (cmd.ConsumerExists() == false) {
+ m_Cmd.SetConsumer();
+ m_Opened = true;
+ }
+ }
+ ~SScopedDataModelConsumer()
+ {
+ if (m_Opened)
+ m_Cmd.ReleaseConsumer();
+ }
+};
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelActionSetValue.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelActionSetValue.h
new file mode 100644
index 00000000..02fab5d7
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelActionSetValue.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_ACTION_SETVALUE_H
+#define INCLUDED_CMD_DATAMODEL_ACTION_SETVALUE_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+#include "UICDMActionCore.h"
+#include "UICDMActionSystem.h"
+#include "UICDMMetaData.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+
+using namespace UICDM;
+
+class CCmdDataModelActionSetValue : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ CUICDMActionHandle m_Action;
+ QString m_NiceText;
+
+public: // Construction
+ CCmdDataModelActionSetValue(CDoc *inDoc, CUICDMActionHandle inAction,
+ const QString &inNiceText)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Action(inAction)
+ , m_NiceText(inNiceText)
+ {
+ }
+
+ virtual void DoOperation() = 0;
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ DoOperation();
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override { return m_NiceText; }
+};
+
+class CCmdDataModelActionSetTriggerObject : public CCmdDataModelActionSetValue
+{
+protected: // Members
+ SObjectRefType m_Object;
+
+ bool m_ResetEvent;
+ wstring m_Event;
+
+public: // Construction
+ CCmdDataModelActionSetTriggerObject(CDoc *inDoc, CUICDMActionHandle inAction,
+ const SObjectRefType &inObject)
+ : CCmdDataModelActionSetValue(inDoc, inAction, "Set Trigger Object")
+ , m_Object(inObject)
+ , m_ResetEvent(false)
+ {
+ }
+
+ void DoOperation() override
+ {
+ m_Doc->GetStudioSystem()->GetActionCore()->SetTriggerObject(m_Action, m_Object);
+ if (m_ResetEvent) {
+ m_Doc->GetStudioSystem()->GetActionCore()->SetEvent(m_Action, m_Event);
+ }
+ }
+
+ virtual void ResetEvent(wstring inEvent)
+ {
+ m_ResetEvent = true;
+ m_Event = inEvent;
+ }
+};
+
+class CCmdDataModelActionSetEvent : public CCmdDataModelActionSetValue
+{
+protected: // Members
+ wstring m_Event;
+
+public: // Construction
+ CCmdDataModelActionSetEvent(CDoc *inDoc, CUICDMActionHandle inAction, const wstring &inEvent)
+ : CCmdDataModelActionSetValue(inDoc, inAction, "Set Event")
+ , m_Event(inEvent)
+ {
+ }
+
+ void DoOperation() override
+ {
+ m_Doc->GetStudioSystem()->GetActionCore()->SetEvent(m_Action, m_Event);
+ }
+};
+
+class CCmdDataModelActionResetHandler : public CCmdDataModelActionSetValue
+{
+protected: // Members
+ bool m_ResetHandler;
+ wstring m_Handler;
+
+protected: // helper functions
+ virtual void ResetHandlerHandle()
+ {
+ m_Doc->GetStudioSystem()->GetActionCore()->SetHandler(m_Action, m_Handler);
+ }
+
+ virtual void ResetHandlerArguments(const wstring &inHandler)
+ {
+ m_Handler = inHandler;
+ m_Doc->GetStudioSystem()->GetClientDataModelBridge()->ResetHandlerArguments(m_Action,
+ m_Handler);
+ }
+
+public: // Construction
+ CCmdDataModelActionResetHandler(CDoc *inDoc, CUICDMActionHandle inAction,
+ const QString &inNiceText)
+ : CCmdDataModelActionSetValue(inDoc, inAction, inNiceText)
+ , m_ResetHandler(false)
+ {
+ }
+
+ // Changing Trigger Object may make the current Action Name to be unapplicable.
+ // Changing Action Name may make the current Action Args to be unapplicable.
+ // If that's the case, Reset the Action Name and/or Action Args.
+ virtual void ResetHandler(const wstring &inHandler)
+ {
+ m_ResetHandler = true;
+ m_Handler = inHandler;
+ }
+};
+
+class CCmdDataModelActionSetTargetObject : public CCmdDataModelActionResetHandler
+{
+protected: // Members
+ SObjectRefType m_Object;
+
+public: // Construction
+ CCmdDataModelActionSetTargetObject(CDoc *inDoc, CUICDMActionHandle inAction,
+ const SObjectRefType &inObject)
+ : CCmdDataModelActionResetHandler(inDoc, inAction, "Set Target Object")
+ , m_Object(inObject)
+ {
+ }
+
+ void DoOperation() override
+ {
+ m_Doc->GetStudioSystem()->GetActionCore()->SetTargetObject(m_Action, m_Object);
+ if (m_ResetHandler) {
+ ResetHandlerHandle();
+ ResetHandlerArguments(m_Handler);
+ }
+ }
+};
+
+class CCmdDataModelActionSetHandler : public CCmdDataModelActionResetHandler
+{
+protected: // Members
+ UICDM::wstring m_Handler;
+
+public: // Construction
+ CCmdDataModelActionSetHandler(CDoc *inDoc, CUICDMActionHandle inAction,
+ UICDM::wstring inHandler)
+ : CCmdDataModelActionResetHandler(inDoc, inAction, "Set Handler")
+ , m_Handler(inHandler)
+ {
+ }
+
+ void DoOperation() override
+ {
+ m_Doc->GetStudioSystem()->GetActionCore()->SetHandler(m_Action, m_Handler);
+ if (m_ResetHandler)
+ ResetHandlerArguments(m_Handler);
+ }
+};
+
+class CCmdDataModelActionSetArgumentValue : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ CUICDMHandlerArgHandle m_HandlerArgument;
+ SValue m_Value;
+
+public: // Construction
+ CCmdDataModelActionSetArgumentValue(CDoc *inDoc, CUICDMHandlerArgHandle inHandlerArgument,
+ SValue inValue)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_HandlerArgument(inHandlerArgument)
+ , m_Value(inValue)
+ {
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ m_Doc->GetStudioSystem()->GetClientDataModelBridge()->SetHandlerArgumentValue(
+ m_HandlerArgument, m_Value);
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Set Action Argument Value");
+ }
+};
+
+class CCmdDataModelActionSetEyeball : public CCmdDataModelActionSetValue
+{
+protected: // Members
+ bool m_Value;
+ CUICDMSlideHandle m_ActiveSlide;
+
+public: // Construction
+ CCmdDataModelActionSetEyeball(CDoc *inDoc, CUICDMSlideHandle inActiveSlide,
+ CUICDMActionHandle inAction, bool inValue)
+ : CCmdDataModelActionSetValue(inDoc, inAction, "Set Action Eyeball")
+ , m_Value(inValue)
+ , m_ActiveSlide(inActiveSlide)
+ {
+ }
+
+ void DoOperation() override
+ {
+ m_Doc->GetStudioSystem()->GetActionSystem()->SetActionEyeballValue(m_ActiveSlide, m_Action,
+ m_Value);
+ }
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelBase.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelBase.h
new file mode 100644
index 00000000..106890b9
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelBase.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_BASE_H
+#define INCLUDED_CMD_DATAMODEL_BASE_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+
+//==============================================================================
+/**
+ * Base class that provide basic Update/Finalize functionality, when changing UICDM data.
+ */
+template <class TDataType>
+class CCmdDataModelBase : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ TDataType m_Value;
+
+public: // Construction
+ CCmdDataModelBase(CDoc *inDoc, TDataType inValue)
+ : CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Value(inValue)
+ {
+ }
+
+ virtual void DoOperation() = 0;
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ SetConsumer();
+ DoOperation();
+ } else {
+ DataModelRedo();
+ }
+
+ return 0;
+ }
+
+ virtual void Update(const TDataType &inValue)
+ {
+ if (!ConsumerExists())
+ SetConsumer();
+ m_Value = inValue;
+ DoOperation();
+ }
+
+ void Finalize(const TDataType &inValue)
+ {
+ if (ConsumerExists()) {
+ m_Value = inValue;
+ DoOperation();
+ }
+ ReleaseConsumer();
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override = 0;
+
+ TDataType GetValue() const { return m_Value; }
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelChangeKeyframe.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelChangeKeyframe.h
new file mode 100644
index 00000000..2dc1b0f2
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelChangeKeyframe.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_CHANGEKEYFRAME_H
+#define INCLUDED_CMD_DATAMODEL_CHANGEKEYFRAME_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+#include "UICDMAnimation.h"
+#include "CmdDataModelBase.h"
+#include "UICDMStudioSystem.h"
+
+class CCmdDataModelSetKeyframeTime : public CCmdDataModelBase<float>
+{
+protected: // Members
+ UICDM::CUICDMKeyframeHandle m_Keyframe;
+
+public: // Construction
+ //@param inTime is in secs
+ CCmdDataModelSetKeyframeTime(CDoc *inDoc, UICDM::CUICDMKeyframeHandle inKeyframe, float inTime)
+ : CCmdDataModelBase(inDoc, inTime)
+ , m_Keyframe(inKeyframe)
+ {
+ }
+ ~CCmdDataModelSetKeyframeTime() {}
+
+ void DoOperation() override
+ {
+ UICDM::IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ UICDM::TKeyframe theKeyframe = theAnimationCore->GetKeyframeData(m_Keyframe);
+ theKeyframe = SetKeyframeSeconds(theKeyframe, m_Value);
+ theAnimationCore->SetKeyframeData(m_Keyframe, theKeyframe);
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Set Keyframe Time");
+ }
+};
+
+class CCmdDataModelSetKeyframeValue : public CCmdDataModelBase<float>
+{
+protected: // Members
+ UICDM::CUICDMKeyframeHandle m_Keyframe;
+
+public: // Construction
+ //@param inTime is in secs
+ CCmdDataModelSetKeyframeValue(CDoc *inDoc, UICDM::CUICDMKeyframeHandle inKeyframe,
+ float inValue)
+ : CCmdDataModelBase(inDoc, inValue)
+ , m_Keyframe(inKeyframe)
+ {
+ }
+ ~CCmdDataModelSetKeyframeValue() {}
+
+ void DoOperation() override
+ {
+ UICDM::IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ UICDM::TKeyframe theKeyframe = theAnimationCore->GetKeyframeData(m_Keyframe);
+ theKeyframe = SetKeyframeValue(theKeyframe, m_Value);
+ theAnimationCore->SetKeyframeData(m_Keyframe, theKeyframe);
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Set Keyframe Value");
+ }
+};
+
+class CCmdDataModelChangeDynamicKeyframe : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ typedef std::set<UICDM::CUICDMAnimationHandle> TTrackList;
+ CDoc *m_Doc;
+ TTrackList m_Tracks; // 1..n tracks affected, unique list
+ bool m_Dynamic;
+
+public: // Construction
+ CCmdDataModelChangeDynamicKeyframe(CDoc *inDoc, UICDM::CUICDMAnimationHandle inHandle,
+ bool inDynamic)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Dynamic(inDynamic)
+ {
+ AddHandle(inHandle);
+ }
+ ~CCmdDataModelChangeDynamicKeyframe() {}
+
+ void AddHandle(UICDM::CUICDMAnimationHandle inHandle) { m_Tracks.insert(inHandle); }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ UICDM::IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ TTrackList::iterator theIter = m_Tracks.begin();
+ for (; theIter != m_Tracks.end(); ++theIter)
+ theAnimationCore->SetFirstKeyframeDynamic(*theIter, m_Dynamic);
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Dynamic Keyframe");
+ }
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelDeanimate.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelDeanimate.h
new file mode 100644
index 00000000..2360efa0
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelDeanimate.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_DEANIMATE_H
+#define INCLUDED_CMD_DATAMODEL_DEANIMATE_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+#include "CmdDataModelBase.h"
+#include "UICDMPropertyDefinition.h"
+#include "UICDMDataCore.h"
+
+// Keyframes are always set at the property level, never for individual animation handle.
+class CCmdDataModelAnimate : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ UICDM::CUICDMInstanceHandle m_Instance;
+ UICDM::CUICDMPropertyHandle m_Property;
+
+public: // Construction
+ CCmdDataModelAnimate(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Instance(inInstance)
+ , m_Property(inProperty)
+ {
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ using namespace UICDM;
+
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ IStudioAnimationSystem *theAnimationSystem =
+ m_Doc->GetStudioSystem()->GetAnimationSystem();
+ theAnimationSystem->Animate(m_Instance, m_Property);
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Animate");
+ }
+};
+
+// Keyframes are always set at the property level, never for individual animation handle.
+class CCmdDataModelDeanimate : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ UICDM::CUICDMInstanceHandle m_Instance;
+ UICDM::CUICDMPropertyHandle m_Property;
+
+public: // Construction
+ CCmdDataModelDeanimate(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Instance(inInstance)
+ , m_Property(inProperty)
+ {
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ using namespace UICDM;
+
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+
+ IStudioAnimationSystem *theAnimationSystem =
+ m_Doc->GetStudioSystem()->GetAnimationSystem();
+ theAnimationSystem->Deanimate(m_Instance, m_Property);
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Deanimate");
+ }
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelDeleteInstance.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelDeleteInstance.h
new file mode 100644
index 00000000..8a9fec37
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelDeleteInstance.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_DELETEINSTANCE_H
+#define INCLUDED_CMD_DATAMODEL_DELETEINSTANCE_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+
+class CCmdDataModelDeleteInstance : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ UICDM::CUICDMInstanceHandle m_Instance;
+
+public: // Construction
+ CCmdDataModelDeleteInstance(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Instance(inInstance)
+ {
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ SetConsumer();
+ m_Doc->GetStudioSystem()->GetPropertySystem()->DeleteInstance(m_Instance);
+ ReleaseConsumer();
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Delete Instance");
+ }
+};
+
+class CCmdDataModelDeleteComponentInstance : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ UICDM::CUICDMInstanceHandle m_Instance;
+
+public: // Construction
+ CCmdDataModelDeleteComponentInstance(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance)
+ : CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Instance(inInstance)
+ {
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ SetConsumer();
+ UICDM::ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetSlideByInstance(m_Instance);
+ theSlideSystem->DeleteSlideByIndex(theSlide, 0);
+
+ ReleaseConsumer();
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Delete Component Instance");
+ }
+};
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h
new file mode 100644
index 00000000..e483b507
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelInsertKeyframe.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_INSERTKEYFRAME_H
+#define INCLUDED_CMD_DATAMODEL_INSERTKEYFRAME_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+#include "UICDMAnimation.h"
+#include "CmdDataModelBase.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMAnimation.h"
+
+// This will animate the property if it is not already animated
+class CCmdDataModelInsertKeyframe : public CCmd, public UICDM::CmdDataModel
+{
+public:
+ struct STimeKeyframeData
+ {
+ UICDM::CUICDMPropertyHandle m_Property;
+ float m_KeyframeTime;
+ UICDM::SGetOrSetKeyframeInfo m_Infos[3];
+ size_t m_ValidInfoCount;
+
+ STimeKeyframeData(UICDM::CUICDMPropertyHandle inProperty, float inKeyframeTime,
+ UICDM::SGetOrSetKeyframeInfo *inInfos, size_t inInfoCount)
+ : m_Property(inProperty)
+ , m_KeyframeTime(inKeyframeTime)
+ {
+ m_ValidInfoCount = inInfoCount <= 3 ? inInfoCount : 3;
+ for (size_t idx = 0, end = m_ValidInfoCount; idx < end; ++idx) {
+ m_Infos[idx] = inInfos[idx];
+ }
+ }
+ };
+
+protected:
+ typedef std::vector<STimeKeyframeData> TKeyframeDataList;
+
+protected: // Members
+ CDoc *m_Doc;
+ UICDM::CUICDMInstanceHandle m_Instance;
+ TKeyframeDataList m_KeyframeDataList;
+
+public: // Construction
+ //@param inTime is in secs
+ CCmdDataModelInsertKeyframe(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty, float inKeyframeTime,
+ UICDM::SGetOrSetKeyframeInfo *inInfos, size_t inInfoCount)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_Instance(inInstance)
+ {
+ AddKeyframeData(inProperty, inKeyframeTime, inInfos, inInfoCount);
+ }
+ ~CCmdDataModelInsertKeyframe() {}
+
+ void AddKeyframeData(UICDM::CUICDMPropertyHandle inProperty, float inTime,
+ UICDM::SGetOrSetKeyframeInfo *inInfos, size_t inInfoCount)
+ {
+ m_KeyframeDataList.push_back(STimeKeyframeData(inProperty, inTime, inInfos, inInfoCount));
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ UICDM::IStudioAnimationSystem *theAnimationSystem =
+ m_Doc->GetStudioSystem()->GetAnimationSystem();
+ // if there are existing keyframes exist at the same times, the values are overridden. (
+ // That's how it always work in studio anyways )
+ for (size_t i = 0; i < m_KeyframeDataList.size(); ++i)
+ theAnimationSystem->SetOrCreateKeyframe(
+ m_Instance, m_KeyframeDataList[i].m_Property,
+ m_KeyframeDataList[i].m_KeyframeTime, m_KeyframeDataList[i].m_Infos,
+ m_KeyframeDataList[i].m_ValidInfoCount);
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Insert Keyframe");
+ }
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModelRemoveKeyframe.h b/src/Authoring/Client/Code/Core/Commands/CmdDataModelRemoveKeyframe.h
new file mode 100644
index 00000000..f0b3d714
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModelRemoveKeyframe.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_DATAMODEL_REMOVEKEYFRAME_H
+#define INCLUDED_CMD_DATAMODEL_REMOVEKEYFRAME_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "Doc.h"
+#include "UICDMHandles.h"
+#include "UICDMAnimation.h"
+#include "CmdDataModelBase.h"
+#include "UICDMStudioSystem.h"
+
+class CCmdDataModelRemoveKeyframe : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ std::vector<UICDM::CUICDMKeyframeHandle> m_Keyframes; // 1..n keyframes to be deleted
+
+public: // Construction
+ //@param inTime is in secs
+ CCmdDataModelRemoveKeyframe(CDoc *inDoc, UICDM::CUICDMKeyframeHandle inKeyframe)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ {
+ AddKeyframeHandle(inKeyframe);
+ }
+ ~CCmdDataModelRemoveKeyframe() {}
+
+ void AddKeyframeHandle(UICDM::CUICDMKeyframeHandle inKeyframe)
+ {
+ m_Keyframes.push_back(inKeyframe);
+ }
+
+ //======================================================================
+ // Do/Redo
+ //======================================================================
+ unsigned long Do() override
+ {
+ if (!ConsumerExists()) {
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ UICDM::IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ for (size_t i = 0; i < m_Keyframes.size(); ++i)
+ theAnimationCore->EraseKeyframe(m_Keyframes[i]);
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // Undo
+ //======================================================================
+ unsigned long Undo() override
+ {
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+ }
+
+ //======================================================================
+ // ToString
+ //======================================================================
+ QString ToString() override
+ {
+ return QObject::tr("Delete Keyframe");
+ }
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdGeneric.h b/src/Authoring/Client/Code/Core/Commands/CmdGeneric.h
new file mode 100644
index 00000000..023413a3
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdGeneric.h
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_CMD_GENERIC_H
+#define INCLUDED_CMD_GENERIC_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#ifndef INCLUDED_CMD_H
+#include "Cmd.h"
+#endif
+#include "StudioConst.h"
+
+class CNull
+{
+};
+class CDoc;
+
+template <typename TClass, typename TArgType = CNull>
+class CCmdGeneric : public CCmd
+{
+ typedef void (TClass::*TDoUndoMethod)();
+ typedef void (TClass::*TOneArgDoUndoMethod)(TArgType);
+
+public:
+ //==========================================================================
+ /**
+ * Create a Generic command that calls the specified methods on Do and Undo.
+ * This is a class for simple commands, makes it a bit quicker to make stuff.
+ * The class takes in a do method with 0 or 1 args defined by each constructor
+ * and a similar undo method
+ *
+ * @param inObject the object the methods are being called on.
+ * @param inDoMethod the method to be called on Do.
+ * @param inUndoMethod the method to be called on Undo.
+ * @param inDescription the description for this command.
+ */
+ //==========================================================================
+ CCmdGeneric(TClass *inObject, TDoUndoMethod inDoMethod, TDoUndoMethod inUndoMethod,
+ Q3DStudio::CString inDescription, long inUpdateFlags = 0)
+ {
+ m_Object = inObject;
+ m_DoMethod = inDoMethod;
+ m_UndoMethod = inUndoMethod;
+ m_Description = inDescription;
+ m_NumArgs = 0;
+ m_UpdateFlags = inUpdateFlags;
+ }
+
+ CCmdGeneric(TClass *inObject, TOneArgDoUndoMethod inDoMethod, TOneArgDoUndoMethod inUndoMethod,
+ TArgType inDoArg, TArgType inUndoArg, const QString &inDescription,
+ long inUpdateFlags = 0)
+ {
+ m_Object = inObject;
+ m_OneArgDoMethod = inDoMethod;
+ m_OneArgUndoMethod = inUndoMethod;
+ m_DoArg = inDoArg;
+ m_UndoArg = inUndoArg;
+ m_Description = inDescription;
+ m_NumArgs = 1;
+ m_UpdateFlags = inUpdateFlags;
+ m_DoMethod = NULL;
+ m_UndoMethod = NULL;
+ }
+
+ CCmdGeneric(TClass *inObject, TDoUndoMethod inDoMethod)
+ {
+ m_Object = inObject;
+ m_DoMethod = inDoMethod;
+ m_UndoMethod = NULL;
+ m_NumArgs = 0;
+ m_UpdateFlags = 0;
+
+ SetUndoable(false);
+ }
+
+ CCmdGeneric(TClass *inObject, TOneArgDoUndoMethod inDoMethod, TArgType inDoArg)
+ {
+ m_Object = inObject;
+ m_OneArgDoMethod = inDoMethod;
+ m_OneArgUndoMethod = NULL;
+ m_DoArg = inDoArg;
+ m_NumArgs = 1;
+ m_UpdateFlags = 0;
+
+ SetUndoable(false);
+ }
+
+ virtual ~CCmdGeneric() {}
+
+ //==========================================================================
+ /**
+ * Performs this command, just calls the Do method on the object.
+ *
+ * @return 0.
+ */
+ //==========================================================================
+ unsigned long Do() override
+ {
+ if (m_NumArgs == 0) {
+ (m_Object->*m_DoMethod)();
+ } else if (m_NumArgs == 1) {
+ (m_Object->*m_OneArgDoMethod)(m_DoArg);
+ }
+
+ return m_UpdateFlags;
+ }
+
+ //==========================================================================
+ /**
+ * Undoes this command, just calls the Undo method on the object.
+ *
+ * @return 0.
+ */
+ //==========================================================================
+ unsigned long Undo() override
+ {
+ if (m_NumArgs == 0) {
+ (m_Object->*m_UndoMethod)();
+ } else if (m_NumArgs == 1) {
+ (m_Object->*m_OneArgUndoMethod)(m_UndoArg);
+ }
+
+ return m_UpdateFlags;
+ }
+
+ //==========================================================================
+ /**
+ * @return CCmd::GENERIC
+ */
+ //==========================================================================
+ CCmd::ECmdType GetType() override { return CCmd::GENERIC; }
+
+ //==========================================================================
+ /**
+ * NOP.
+ */
+ //==========================================================================
+ bool CanMerge(CCmd *inCommand) override
+ {
+ Q_UNUSED(inCommand);
+ return false;
+ }
+
+ //==========================================================================
+ /**
+ * NOP.
+ */
+ //==========================================================================
+ void Merge(CCmd *inCommand) override { Q_UNUSED(inCommand); }
+
+ //==========================================================================
+ /**
+ * @return the description from the constructor.
+ */
+ //==========================================================================
+ QString ToString() override { return m_Description; }
+
+protected:
+ TClass *m_Object;
+ TDoUndoMethod m_DoMethod;
+ TDoUndoMethod m_UndoMethod;
+ QString m_Description;
+ TOneArgDoUndoMethod m_OneArgDoMethod;
+ TOneArgDoUndoMethod m_OneArgUndoMethod;
+ TArgType m_DoArg;
+ TArgType m_UndoArg;
+ long m_NumArgs;
+ long m_UpdateFlags;
+};
+
+#endif // INCLUDED_CMD_GENERIC_H
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdLocateReference.cpp b/src/Authoring/Client/Code/Core/Commands/CmdLocateReference.cpp
new file mode 100644
index 00000000..1b7e6b88
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdLocateReference.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "CmdLocateReference.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMDataCore.h"
+#include "UICDMSlides.h"
+#include "UICDMSlideCore.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CCmdLocateReference::CCmdLocateReference(CDoc *inDoc, const Q3DStudio::CFilePath &inOldPath,
+ const Q3DStudio::CFilePath &inNewPath)
+ : UICDM::CmdDataModel(*inDoc)
+ , m_Doc(inDoc)
+ , m_OldPath(inOldPath)
+ , m_NewPath(inNewPath)
+{
+ // Convert the path to relative
+ if (m_OldPath.IsAbsolute()) {
+ m_OldPath = m_Doc->GetRelativePathToDoc(m_OldPath);
+ ASSERT(!m_OldPath.IsAbsolute());
+ }
+ if (m_NewPath.IsAbsolute()) {
+ m_NewPath = m_Doc->GetRelativePathToDoc(m_NewPath);
+ ASSERT(!m_NewPath.IsAbsolute());
+ }
+
+ m_Bridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ m_PropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ m_SlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ m_SlideCore = m_Doc->GetStudioSystem()->GetSlideCore();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CCmdLocateReference::~CCmdLocateReference()
+{
+}
+
+//=============================================================================
+/**
+ * Do/Redo
+ */
+unsigned long CCmdLocateReference::Do()
+{
+ if (!ConsumerExists()) {
+ UICDM::SScopedDataModelConsumer __scopedConsumer(*this);
+ LocateReference();
+ } else {
+ DataModelRedo();
+ }
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Undo
+ */
+unsigned long CCmdLocateReference::Undo()
+{
+ if (ConsumerExists()) {
+ DataModelUndo();
+ }
+ return 0;
+}
+
+//=============================================================================
+/**
+ * LocateReference
+ */
+void CCmdLocateReference::LocateReference()
+{
+ using namespace UICDM;
+ // Get all instances that are derived from ItemBase instance (they should have sourcepath
+ // property)
+ // Iterate through each instance derived from ItemBase and get the sourcepath property value.
+ TInstanceHandleList theInstances = m_Bridge->GetItemBaseInstances();
+ for (TInstanceHandleList::const_iterator theIter = theInstances.begin();
+ theIter != theInstances.end(); ++theIter) {
+ // Check if the instance is in master slide and if the property is unlinked.
+ // This will determine how we should update the value.
+ CUICDMSlideHandle theSlide = m_SlideSystem->GetAssociatedSlide(*theIter);
+ if (theSlide.Valid() && m_SlideSystem->IsMasterSlide(theSlide)
+ && !m_SlideSystem->IsPropertyLinked(*theIter, m_Bridge->GetSourcePathProperty())) {
+ // If the instance is in master slide and the property is unlinked, we need to update
+ // the value from each slides
+ size_t theSlideCount =
+ m_SlideSystem->GetSlideCount(m_SlideSystem->GetAssociatedSlide(*theIter));
+ for (size_t theSlideIndex = 0; theSlideIndex < theSlideCount; ++theSlideIndex) {
+ CUICDMSlideHandle theSpecificSlide =
+ m_SlideSystem->GetSlideByIndex(theSlide, theSlideIndex);
+ UpdateSourcePath(*theIter, theSpecificSlide);
+ }
+ } else {
+ UpdateSourcePath(*theIter);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Update sourcepath property from a specific instance (and maybe from specific slide) if it meets
+ * the criteria
+ * @param inInstance the instance to update
+ * @param inSpecificSlide the slide to update, if valid
+ */
+void CCmdLocateReference::UpdateSourcePath(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSpecificSlide)
+{
+ // Get the sourcepath value
+ Q3DStudio::CFilePath thePath;
+ Q3DStudio::CString theIdentifier;
+ GetSourcePath(inInstance, inSpecificSlide, thePath, theIdentifier);
+
+ // compare path. subclass should implement ComparePath function
+ if (ComparePath(thePath)) {
+ // Set to New Path. subclass should implement GetNewPath function
+ SetSourcePath(inInstance, inSpecificSlide, GetNewPath(thePath), theIdentifier);
+ }
+}
+
+//=============================================================================
+/**
+ * Get sourcepath property from a specific instance
+ * @param inInstance the instance to query
+ * @param inSpecificSlide the slide to query, if valid
+ * @param outPath the sourcepath without the identifier
+ * @param outIdentifier the identifier
+ */
+void CCmdLocateReference::GetSourcePath(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSpecificSlide,
+ Q3DStudio::CFilePath &outPath,
+ Q3DStudio::CString &outIdentifier)
+{
+ // Get the sourcepath property value
+ UICDM::SValue theValue;
+ bool theGetValue = false;
+
+ if (inSpecificSlide.Valid())
+ theGetValue = m_SlideCore->GetSpecificInstancePropertyValue(
+ inSpecificSlide, inInstance, m_Bridge->GetSourcePathProperty(), theValue);
+ else {
+ UICDM::SValue temp;
+ theGetValue = m_PropertySystem->GetInstancePropertyValue(
+ inInstance, m_Bridge->GetSourcePathProperty(), temp);
+ if (theGetValue)
+ theValue = temp.toOldSkool();
+ }
+
+ if (theGetValue) {
+ Q3DStudio::CFilePath theSourcePath(UICDM::get<UICDM::TDataStrPtr>(theValue)->GetData());
+
+ // Split the source path and the identifier
+ outIdentifier = theSourcePath.GetIdentifier();
+ outPath = theSourcePath.GetPathWithoutIdentifier();
+ } else {
+ outIdentifier.Clear();
+ outPath.Clear();
+ }
+}
+
+//=============================================================================
+/**
+ * Set sourcepath property for a specific instance
+ * @param inInstance the instance to set value to
+ * @param inSpecificSlide the slide to set value to, if valid
+ * @param inPath the sourcepath without the identifier
+ * @param inIdentifier the identifier
+ */
+void CCmdLocateReference::SetSourcePath(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSpecificSlide,
+ const Q3DStudio::CFilePath &inPath,
+ const Q3DStudio::CString &inIdentifier)
+{
+ Q3DStudio::CFilePath theSourcePath(inPath);
+ theSourcePath.SetIdentifier(inIdentifier);
+ UICDM::SValue theValue(UICDM::TDataStrPtr(new UICDM::CDataStr(theSourcePath)));
+
+ if (inSpecificSlide.Valid())
+ m_SlideCore->ForceSetInstancePropertyValue(inSpecificSlide, inInstance,
+ m_Bridge->GetSourcePathProperty(), theValue);
+ else
+ m_PropertySystem->SetInstancePropertyValue(inInstance, m_Bridge->GetSourcePathProperty(),
+ theValue);
+}
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inDoc CDoc
+ * @param inOldPath the old file path
+ * @param inNewPath the new file path
+ */
+CCmdLocateFile::CCmdLocateFile(CDoc *inDoc, const Q3DStudio::CFilePath &inOldPath,
+ const Q3DStudio::CFilePath &inNewPath)
+ : CCmdLocateReference(inDoc, inOldPath, inNewPath)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CCmdLocateFile::~CCmdLocateFile()
+{
+}
+
+//=============================================================================
+/**
+ * ComparePath
+ */
+bool CCmdLocateFile::ComparePath(const Q3DStudio::CFilePath &inPath)
+{
+ // Do a caseless comparison between inPath and the old path
+ return inPath.Compare(m_OldPath, false);
+}
+
+//=============================================================================
+/**
+ * GetNewPath
+ */
+Q3DStudio::CFilePath CCmdLocateFile::GetNewPath(const Q3DStudio::CFilePath &inPath)
+{
+ // Simply replace inPath with the new path
+ Q_UNUSED(inPath);
+ return m_NewPath;
+}
+
+//=============================================================================
+/**
+ * ToString
+ */
+QString CCmdLocateFile::ToString()
+{
+ return QObject::tr("Locate File");
+}
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inDoc CDoc
+ * @param inOldPath the old folder path
+ * @param inNewPath the new folder path
+ */
+CCmdLocateFolder::CCmdLocateFolder(CDoc *inDoc, const Q3DStudio::CFilePath &inOldPath,
+ const Q3DStudio::CFilePath &inNewPath)
+ : CCmdLocateReference(inDoc, inOldPath, inNewPath)
+{
+ // Need to add last backslash to compare directories
+ m_OldPath.AddTrailingBackslash();
+ m_NewPath.AddTrailingBackslash();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CCmdLocateFolder::~CCmdLocateFolder()
+{
+}
+
+//=============================================================================
+/**
+ * ComparePath
+ */
+bool CCmdLocateFolder::ComparePath(const Q3DStudio::CFilePath &inPath)
+{
+ // check if inPath is in the m_OldPath folder
+ return inPath.IsInSubDirectory(m_OldPath);
+}
+
+//=============================================================================
+/**
+ * GetNewPath
+ */
+Q3DStudio::CFilePath CCmdLocateFolder::GetNewPath(const Q3DStudio::CFilePath &inPath)
+{
+ // Change inPath from old folder to new folder
+ Q3DStudio::CFilePath theNewPath(m_NewPath + inPath.Extract(m_OldPath.Length()));
+ return theNewPath;
+}
+
+//=============================================================================
+/**
+ * ToString
+ */
+QString CCmdLocateFolder::ToString()
+{
+ return QObject::tr("Locate Folder");
+}
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdLocateReference.h b/src/Authoring/Client/Code/Core/Commands/CmdLocateReference.h
new file mode 100644
index 00000000..1cab2984
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdLocateReference.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_CMD_LOCATE_REFERENCE_H
+#define INCLUDED_CMD_LOCATE_REFERENCE_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "Cmd.h"
+#include "CmdDataModel.h"
+#include "UICFileTools.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CDoc;
+class CClientDataModelBridge;
+namespace UICDM {
+class IPropertySystem;
+class ISlideSystem;
+class ISlideCore;
+}
+
+// Left clicking on the Broken Link Icon opens a pop-up menu
+//
+// The menu has a single item
+// If the Broken Link is a Folder: "Locate Folder"
+// If the Broken Link is a File: "Locate File"
+// Selecting this will open a file browser dialog allowing the use to choose any folder (for
+// broken folder) or file (for broken file) in the Project path
+// This operation will replace the old (broken) path substring with the new path substring in
+// all references in the scene
+// For broken folders this will effectively fix all files that are broken in the path
+// (commonly occurs when a folder is moved)
+// For broken files this will only fix the specific file that was located
+// The project palette will update to reflect the changes
+
+class CCmdLocateReference : public CCmd, public UICDM::CmdDataModel
+{
+protected: // Members
+ CDoc *m_Doc;
+ Q3DStudio::CFilePath m_OldPath;
+ Q3DStudio::CFilePath m_NewPath;
+ CClientDataModelBridge *m_Bridge;
+ UICDM::IPropertySystem *m_PropertySystem;
+ UICDM::ISlideSystem *m_SlideSystem;
+ UICDM::ISlideCore *m_SlideCore;
+
+public:
+ CCmdLocateReference(CDoc *inDoc, const Q3DStudio::CFilePath &inOldPath,
+ const Q3DStudio::CFilePath &inNewPath);
+ ~CCmdLocateReference();
+
+ unsigned long Do() override;
+ unsigned long Undo() override;
+ QString ToString() override = 0;
+
+protected:
+ void LocateReference();
+ void UpdateSourcePath(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSpecificSlide = 0);
+ void GetSourcePath(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSpecificSlide, Q3DStudio::CFilePath &outPath,
+ Q3DStudio::CString &outIdentifier);
+ void SetSourcePath(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSpecificSlide, const Q3DStudio::CFilePath &inPath,
+ const Q3DStudio::CString &inIdentifier);
+
+ // subclasses should implement the following methods
+ virtual bool ComparePath(const Q3DStudio::CFilePath &inPath) = 0;
+ virtual Q3DStudio::CFilePath GetNewPath(const Q3DStudio::CFilePath &inPath) = 0;
+};
+
+class CCmdLocateFile : public CCmdLocateReference
+{
+public:
+ CCmdLocateFile(CDoc *inDoc, const Q3DStudio::CFilePath &inOldPath,
+ const Q3DStudio::CFilePath &inNewPath);
+ ~CCmdLocateFile();
+
+ bool ComparePath(const Q3DStudio::CFilePath &inPath) override;
+ Q3DStudio::CFilePath GetNewPath(const Q3DStudio::CFilePath &inPath) override;
+
+ QString ToString() override;
+};
+
+class CCmdLocateFolder : public CCmdLocateReference
+{
+public:
+ CCmdLocateFolder(CDoc *inDoc, const Q3DStudio::CFilePath &inOldPath,
+ const Q3DStudio::CFilePath &inNewPath);
+ ~CCmdLocateFolder();
+
+ bool ComparePath(const Q3DStudio::CFilePath &inPath) override;
+ Q3DStudio::CFilePath GetNewPath(const Q3DStudio::CFilePath &inPath) override;
+
+ QString ToString() override;
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdStack.cpp b/src/Authoring/Client/Code/Core/Commands/CmdStack.cpp
new file mode 100644
index 00000000..aa58ca82
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdStack.cpp
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "CmdStack.h"
+#include "Cmd.h"
+#include "CmdStackModifier.h"
+
+CCmdStack::CCmdStack()
+{
+ m_Listener = NULL;
+ m_MaxUndoStackSize = 100;
+ m_CommandStackModifier = NULL;
+}
+
+CCmdStack::~CCmdStack()
+{
+ // Delete all the commands that are in the queues.
+ Clear();
+}
+
+//=============================================================================
+/**
+ * Add a command to be executed.
+ * If the command can be undone then it will be added to the undo/redo list.
+ * Any commands that are in the redo list will be deleted and the redo list will
+ * be flushed. If this command can be merged with the previous command then it
+ * will be, after it is executed. If it is merged then it will be deleted
+ * immediately. If the command cannot be undone then it will be deleted
+ * immediately.
+ *
+ * @param inCommand the command to be executed.
+ * @return bool true if inCommand was deleted, false otherwise.
+ */
+//=============================================================================
+bool CCmdStack::ExecuteCommand(CCmd *inCommand)
+{
+ // Default the delete to true.
+ bool shouldDeleteCommand = true;
+ // Execute the command.
+ unsigned long theUpdateMask = inCommand->Do();
+
+
+ // If the listener is not null then do the notifications.
+ if (m_Listener != NULL) {
+ m_Listener->CommandUpdate(theUpdateMask);
+
+ // Set the modified flag if it needs to be set.
+ if (inCommand->ShouldSetModifiedFlag()) {
+ m_Listener->SetCommandModifiedFlag(TRUE);
+ }
+ }
+
+ // If the command can be undone then see if it needs to be merged or added to the undo list.
+ if (inCommand->IsUndoable()) {
+ // If there are previous commands then see if the command should be merged.
+ if (m_UndoList.size() != 0) {
+ CCmd *thePreviousCommand = m_UndoList.back();
+ // If the previous command is committed then add the command.
+ if (thePreviousCommand->IsCommitted()) {
+ // Add the command and don't delete it.
+ m_UndoList.push_back(inCommand);
+ shouldDeleteCommand = false;
+ }
+ // Check if it can be merged.
+ else if (thePreviousCommand->CanMerge(inCommand)) {
+ inCommand->Merge(thePreviousCommand);
+ delete thePreviousCommand;
+ m_UndoList.pop_back();
+ m_UndoList.push_back(inCommand);
+ shouldDeleteCommand = false;
+ } else {
+ // Add the command and don't delete it.
+ m_UndoList.push_back(inCommand);
+ shouldDeleteCommand = false;
+ }
+ } else {
+ // This is the first command in the list.
+ m_UndoList.push_back(inCommand);
+ shouldDeleteCommand = false;
+ }
+
+ // Cannot redo after a new command that can be undone.
+ EmptyRedoStack();
+ }
+
+ // Delete the command if it needs to be.
+ if (shouldDeleteCommand) {
+ delete inCommand;
+ }
+
+ // Keep the undo list below it's max size.
+ while (m_UndoList.size() > m_MaxUndoStackSize) {
+ CCmd *theLastCommand = m_UndoList.front();
+ delete theLastCommand;
+ m_UndoList.erase(m_UndoList.begin());
+ }
+
+ return shouldDeleteCommand;
+}
+
+//=============================================================================
+/**
+ * Perform a single undo operation.
+ * This will take the last command to be executed and undo it then push it onto
+ * the redo stack. The command is set to committed so it will not be merged with
+ * any other commands.
+ */
+//=============================================================================
+void CCmdStack::Undo()
+{
+
+ if (m_CommandStackModifier) {
+ if (m_CommandStackModifier->PreUndo() == false)
+ return;
+ }
+ if (m_UndoList.size() > 0) {
+ CCmd *theLastCommand = m_UndoList.back();
+ m_UndoList.pop_back();
+
+ unsigned long theUpdateMask = theLastCommand->Undo();
+
+
+ // Once a command is undone then it is considered committed. Prevents merging after this has
+ // been redone.
+ theLastCommand->SetCommitted(true);
+
+ m_RedoList.push_back(theLastCommand);
+
+ // If the listener is not null then do the notifications.
+ if (m_Listener != NULL) {
+ m_Listener->CommandUpdate(theUpdateMask);
+
+ // Set the modified flag if it needs to be set.
+ if (theLastCommand->ShouldSetModifiedFlag()) {
+ m_Listener->SetCommandModifiedFlag(TRUE);
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Perform a single redo operation.
+ * This will take the last command to be undone and redo it, then push it onto
+ * the undo stack.
+ */
+//=============================================================================
+void CCmdStack::Redo()
+{
+ if (m_RedoList.size() > 0) {
+ CCmd *theLastCommand = m_RedoList.back();
+ m_RedoList.pop_back();
+
+ unsigned long theUpdateMask = theLastCommand->Do();
+
+ m_UndoList.push_back(theLastCommand);
+
+ // If the listener is not null then do the notifications.
+ if (m_Listener != NULL) {
+ m_Listener->CommandUpdate(theUpdateMask);
+
+ // Set the modified flag if it needs to be set.
+ if (theLastCommand->ShouldSetModifiedFlag()) {
+ m_Listener->SetCommandModifiedFlag(TRUE);
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * @return true if an undo operation can be done.
+ */
+//=============================================================================
+bool CCmdStack::CanUndo()
+{
+ if (m_CommandStackModifier && m_CommandStackModifier->CanUndo())
+ return true;
+ return m_UndoList.size() > 0;
+}
+
+//=============================================================================
+/**
+ * @return true if a redo operation can be done.
+ */
+//=============================================================================
+bool CCmdStack::CanRedo()
+{
+ return m_RedoList.size() > 0;
+}
+
+//=============================================================================
+/**
+ * Commit the last command on the undo stack.
+ * This marks the last command as committed and prevents it from merging with
+ * any future commands.
+ */
+//=============================================================================
+void CCmdStack::CommitLastCommand()
+{
+ if (m_UndoList.size() > 0) {
+ CCmd *theLastCommand = m_UndoList.back();
+ theLastCommand->SetCommitted(true);
+ }
+}
+
+//=============================================================================
+/**
+ * Clear the entire undo/redo stack.
+ * This is used when a new presentation is loaded and all the previous commands
+ * are no longer needed. All commands will be deleted.
+ */
+//=============================================================================
+void CCmdStack::Clear()
+{
+ EmptyRedoStack();
+ EmptyUndoStack();
+}
+
+//=============================================================================
+/**
+ * Clear any invalid commands
+ * This is called when commands are invalidated due objects being deleted.
+ */
+//=============================================================================
+void CCmdStack::ClearInvalid()
+{
+ TCmdList::iterator thePos = m_UndoList.begin();
+ while (thePos != m_UndoList.end()) {
+ if ((*thePos)->IsInvalidated()) // continue with the next item that comes after.
+ {
+ delete (*thePos);
+ thePos = m_UndoList.erase(thePos);
+ } else
+ ++thePos;
+ }
+ thePos = m_RedoList.begin();
+ while (thePos != m_RedoList.end()) {
+ if ((*thePos)->IsInvalidated()) // continue with the next item that comes after.
+ {
+ delete (*thePos);
+ thePos = m_RedoList.erase(thePos);
+ } else
+ ++thePos;
+ }
+}
+
+//=============================================================================
+/**
+ * Clears out the undo stack and deletes all the commands within it.
+ * This is used on delete and when a new presentation is loaded up.
+ */
+//=============================================================================
+void CCmdStack::EmptyUndoStack()
+{
+ TCmdList::iterator thePos;
+ for (thePos = m_UndoList.begin(); thePos != m_UndoList.end(); ++thePos) {
+ delete (*thePos);
+ }
+
+ m_UndoList.clear();
+}
+
+//=============================================================================
+/**
+ * Clears out the redo stack and deletes all the commands within it.
+ * This is used after a new command is added redo can no longer be done. The
+ * commands can be deleted because they can never be executed again.
+ */
+//=============================================================================
+void CCmdStack::EmptyRedoStack()
+{
+ TCmdList::iterator thePos;
+ for (thePos = m_RedoList.begin(); thePos != m_RedoList.end(); ++thePos) {
+ delete (*thePos);
+ }
+
+ m_RedoList.clear();
+}
+
+//=============================================================================
+/**
+ * Gets the description of the next Undo command.
+ *
+ * @return the description or "" if no undo command is available.
+ */
+//=============================================================================
+QString CCmdStack::GetUndoDescription()
+{
+ QString theDescription;
+ if (m_UndoList.size() > 0) {
+ theDescription = m_UndoList.back()->ToString();
+ }
+ return theDescription;
+}
+
+//=============================================================================
+/**
+ * Gets the description of the next Redo command.
+ *
+ * @return the description of "" if no redo command is available.
+ */
+//=============================================================================
+QString CCmdStack::GetRedoDescription()
+{
+ QString theDescription;
+ if (m_RedoList.size() > 0) {
+ theDescription = m_RedoList.back()->ToString();
+ }
+ return theDescription;
+}
+
+void CCmdStack::SetCommandStackModifier(ICmdStackModifier *inModifier)
+{
+ m_CommandStackModifier = inModifier;
+}
+
+//=============================================================================
+/**
+ * Set a listener on this command stack which will be notified every time a
+ * command has executed which should set the modified flag.
+ *
+ * @param inListener the listener to be notified.
+ */
+//=============================================================================
+void CCmdStack::SetModificationListener(CModificationListener *inListener)
+{
+ m_Listener = inListener;
+}
+
+//=============================================================================
+/**
+ * Get the list of commands that can be undone.
+ */
+CCmdStack::TCmdList CCmdStack::GetUndoStack()
+{
+ return m_UndoList;
+}
+
+//=============================================================================
+/**
+ * Get the list of commands that can be redone.
+ */
+CCmdStack::TCmdList CCmdStack::GetRedoStack()
+{
+ return m_RedoList;
+}
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdStack.h b/src/Authoring/Client/Code/Core/Commands/CmdStack.h
new file mode 100644
index 00000000..4ad23ae9
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdStack.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_STACK_H
+#define INCLUDED_CMD_STACK_H 1
+
+#pragma once
+
+#include "UICString.h"
+
+class CCmd;
+class ICmdStackModifier;
+
+//=============================================================================
+/**
+ * Class to listen for changes on the command listener.
+ */
+//=============================================================================
+class CModificationListener
+{
+public:
+ //==========================================================================
+ /**
+ * This is called every time a command is executed which modifies the
+ * modified flag on the command stack. It is used to notify the interested
+ * document that a change has occurred.
+ */
+ //==========================================================================
+ virtual void SetCommandModifiedFlag(bool inModified) = 0;
+
+ //==========================================================================
+ /**
+ * Called when a command modifies one or more of the views and the views
+ * need to be redrawn.
+ *
+ * @param inUpdateFlags flags of what needs to be redrawn.
+ */
+ //==========================================================================
+ virtual void CommandUpdate(unsigned long inUpdateFlags) = 0;
+};
+
+class CCmdStack
+{
+public:
+ typedef std::vector<CCmd *> TCmdList;
+
+ CCmdStack();
+ virtual ~CCmdStack();
+
+ bool ExecuteCommand(CCmd *inCommand);
+ void Undo();
+ void Redo();
+
+ bool CanUndo();
+ bool CanRedo();
+
+ QString GetUndoDescription();
+ QString GetRedoDescription();
+
+ void CommitLastCommand();
+
+ void Clear();
+ void ClearInvalid();
+
+ void SetCommandStackModifier(ICmdStackModifier *inModifier);
+ void SetModificationListener(CModificationListener *inListener);
+
+ TCmdList GetUndoStack();
+ TCmdList GetRedoStack();
+ void EmptyRedoStack();
+
+protected:
+ void EmptyUndoStack();
+
+ ICmdStackModifier *m_CommandStackModifier;
+
+ TCmdList m_UndoList;
+ TCmdList m_RedoList;
+
+ unsigned long m_MaxUndoStackSize;
+
+ CModificationListener *m_Listener;
+};
+#endif // INCLUDED_CMD_STACK_H
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdStackModifier.h b/src/Authoring/Client/Code/Core/Commands/CmdStackModifier.h
new file mode 100644
index 00000000..13f47bf9
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Commands/CmdStackModifier.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef CMDSTACKMODIFIERH
+#define CMDSTACKMODIFIERH
+
+class ICmdStackModifier
+{
+protected:
+ virtual ~ICmdStackModifier() {}
+public:
+ virtual bool CanUndo() = 0;
+ // false means kill the undo without actually undoing anything
+ virtual bool PreUndo() = 0;
+};
+#endif \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Core/Core.cpp b/src/Authoring/Client/Code/Core/Core/Core.cpp
new file mode 100644
index 00000000..d9004ebe
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Core/Core.cpp
@@ -0,0 +1,515 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+#include "stdafx.h"
+#include "Core.h"
+#include "Doc.h"
+#include "Dispatch.h"
+#include "HotKeys.h"
+#include "StudioProjectSettings.h"
+#include "FileOutputStream.h"
+#include "FormattedOutputStream.h"
+#include "Exceptions.h"
+#include "UICFileTools.h"
+#include "Cmd.h"
+#include "StudioPreferences.h"
+#include "UICStateApplication.h"
+
+//==============================================================================
+// Construction
+CCore::CCore()
+ : m_Doc(NULL)
+ , m_Dispatch(new CDispatch())
+ , m_CmdStack(new CCmdStack())
+ , m_HotKeys(new CHotKeys())
+ , m_JustSaved(false)
+{
+ m_StudioProjectSettings = new CStudioProjectSettings(this);
+ m_Dispatch->AddPresentationChangeListener(this);
+ m_CmdStack->SetModificationListener(this);
+ m_Doc = new CDoc(this);
+}
+
+CCore::~CCore()
+{
+ m_BuildConfigurations.Clear();
+ m_CmdStack->Clear();
+ delete m_Doc;
+ delete m_Dispatch;
+ delete m_CmdStack;
+ delete m_HotKeys;
+ delete m_StudioProjectSettings;
+}
+
+void CCore::Initialize()
+{
+ LoadBuildConfigurations();
+ RegisterGlobalKeyboardShortcuts(m_HotKeys);
+}
+
+CDoc *CCore::GetDoc() const
+{
+ return m_Doc;
+}
+
+CDispatch *CCore::GetDispatch()
+{
+ return m_Dispatch;
+}
+
+CCmdStack *CCore::GetCmdStack()
+{
+ return m_CmdStack;
+}
+
+CHotKeys *CCore::GetHotKeys()
+{
+ return m_HotKeys;
+}
+
+CStudioProjectSettings *CCore::GetStudioProjectSettings()
+{
+ return m_StudioProjectSettings;
+}
+
+Q3DStudio::CBuildConfigurations &CCore::GetBuildConfigurations()
+{
+ return m_BuildConfigurations;
+}
+
+//=============================================================================
+/**
+ * Load all the build configurations
+ */
+bool CCore::LoadBuildConfigurations()
+{
+ using namespace Q3DStudio;
+ // See if we can find the build configurations where they are located first
+ CFilePath theCurrentPath(CUICFile::GetApplicationDirectory().GetAbsolutePath());
+ CFilePath theMainDir = theCurrentPath.GetDirectory()
+ .GetDirectory()
+ .GetDirectory(); //.GetDirectory(); // Developing directory
+ CFilePath theStudioDir =
+ CFilePath::CombineBaseAndRelative(theMainDir, CFilePath(L"Studio/Build Configurations"));
+ CUICFile theConfigurationDirectory(theStudioDir);
+ if (!theStudioDir.IsDirectory())
+ theConfigurationDirectory = CUICFile(
+ CUICFile::GetApplicationDirectory().GetAbsolutePath(),
+ Q3DStudio::CString(L"Build Configurations")); // Installed directory // TODO: Localize
+
+ Q3DStudio::CBuildConfigParser theParser(m_BuildConfigurations);
+ bool theSuccess = theParser.LoadConfigurations(theConfigurationDirectory);
+ if (!theSuccess) {
+ m_Dispatch->FireOnBuildConfigurationFileParseFail(theParser.GetErrorMessage());
+ } else {
+ InitAndValidateBuildConfiguration();
+ }
+
+ return theSuccess;
+}
+
+//=============================================================================
+/**
+ * If the build configuration saved doesn't exist, use the first one
+ * also verify all the properties required existed, else use the first option available
+ */
+void CCore::InitAndValidateBuildConfiguration()
+{
+ Q3DStudio::CBuildConfiguration *theConfig =
+ m_BuildConfigurations.GetConfiguration(CStudioPreferences::GetPreviewConfig());
+ if (!theConfig) {
+ Q3DStudio::CBuildConfigurations::TBuildConfigurations &theConfigurations =
+ m_BuildConfigurations.GetConfigurations();
+ if (theConfigurations.size()) {
+ CStudioPreferences::SetPreviewConfig(theConfigurations.begin()->first);
+ theConfig = theConfigurations.begin()->second;
+ }
+ }
+ if (theConfig) {
+ Q3DStudio::CBuildConfiguration::TConfigProperties &theConfigProperties =
+ theConfig->GetBuildProperties();
+ Q3DStudio::CBuildConfiguration::TConfigProperties::iterator theConfigPropIter;
+ for (theConfigPropIter = theConfigProperties.begin();
+ theConfigPropIter != theConfigProperties.end(); ++theConfigPropIter) {
+ const Q3DStudio::CString &thePropName = theConfigPropIter->GetName();
+ Q3DStudio::CString theStoredValue = CStudioPreferences::GetPreviewProperty(thePropName);
+ if (!theConfigPropIter->HasValue(theStoredValue)) {
+ // add this property in
+ if (theConfigPropIter->GetAcceptableValues().size())
+ CStudioPreferences::SetPreviewProperty(
+ thePropName, theConfigPropIter->GetValue(0).GetName());
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Call by the mainframe to register the keyboard settings.
+ * @param inShortcutHandler the handler for the keyboard actions.
+ */
+void CCore::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ m_Doc->RegisterGlobalKeyboardShortcuts(inShortcutHandler);
+
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CCmdStack>(m_CmdStack, &CCmdStack::Undo), Qt::ControlModifier,
+ Qt::Key_Z);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CCmdStack>(m_CmdStack, &CCmdStack::Redo),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_Z);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CCmdStack>(m_CmdStack, &CCmdStack::Redo), Qt::ControlModifier,
+ Qt::Key_Y);
+
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CCore>(this, &CCore::DumpCommandQueue), Qt::ControlModifier,
+ Qt::Key_F6);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CCore>(this, &CCore::SetTimebarStartAffectsChildren), 0,
+ Qt::Key_BracketLeft);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CCore>(this, &CCore::SetTimebarEndAffectsChildren), 0,
+ Qt::Key_BracketRight);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CCore>(this, &CCore::SetTimebarStart), Qt::ControlModifier,
+ Qt::Key_BracketLeft);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CCore>(this, &CCore::SetTimebarEnd), Qt::ControlModifier,
+ Qt::Key_BracketRight);
+}
+
+void CCore::GetCreateDirectoryFileName(const CUICFile &inDocument,
+ Q3DStudio::CFilePath &outFinalDir,
+ Q3DStudio::CFilePath &outFinalDoc)
+{
+ using namespace Q3DStudio;
+ CFilePath theOriginal(inDocument.GetAbsolutePath());
+ CFilePath theName(theOriginal.GetFileName());
+ CString theStem(theOriginal.GetFileStem());
+ CFilePath theDir = theOriginal.GetDirectory();
+ outFinalDir = CFilePath::CombineBaseAndRelative(theDir, theStem);
+ outFinalDoc = CFilePath::CombineBaseAndRelative(outFinalDir, theName);
+}
+
+//=============================================================================
+/**
+ * Call to create a new document.
+ * This will clear out the current doc (if there is one) then create a new one.
+ */
+void CCore::OnNewDocument(const CUICFile &inDocument, bool inCreateDirectory)
+{
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Dispatch);
+
+ m_Doc->CloseDocument();
+
+ Q3DStudio::CFilePath theDocument(inDocument.GetAbsolutePath());
+
+ if (inCreateDirectory) {
+ using namespace Q3DStudio;
+ Q3DStudio::CFilePath theFinalDir;
+ GetCreateDirectoryFileName(inDocument, theFinalDir, theDocument);
+ CFilePath::CombineBaseAndRelative(theFinalDir, CFilePath(L"effects")).CreateDir(true);
+ CFilePath::CombineBaseAndRelative(theFinalDir, CFilePath(L"fonts")).CreateDir(true);
+ CFilePath::CombineBaseAndRelative(theFinalDir, CFilePath(L"maps")).CreateDir(true);
+ CFilePath::CombineBaseAndRelative(theFinalDir, CFilePath(L"materials")).CreateDir(true);
+ CFilePath::CombineBaseAndRelative(theFinalDir, CFilePath(L"models")).CreateDir(true);
+ CFilePath::CombineBaseAndRelative(theFinalDir, CFilePath(L"scripts")).CreateDir(true);
+ }
+
+ m_Doc->SetDocumentPath(theDocument);
+ m_Doc->CreateNewDocument();
+
+ // Serialize the new document.
+ m_Doc->SaveDocument(theDocument);
+
+#ifdef DRIVE_DESIGN_STUDIO
+ // Update the uia file if possible.
+ uic::state::IApplication::EnsureApplicationFile(theDocument.GetCharStar(), QStringList());
+#endif
+}
+
+//=============================================================================
+/**
+ * Call to save the current document.
+ * This will do all the prompting, directory stuff necessary and perform the
+ * saving of the document.
+ */
+void CCore::OnSaveDocument(const CUICFile &inDocument, bool inSaveCopy /*= false*/)
+{
+ m_JustSaved = true;
+ GetDispatch()->FireOnSavingPresentation(&inDocument);
+ bool isSuccess = false;
+ try {
+ OnSaveDocumentCatcher(inDocument, inSaveCopy);
+ m_Dispatch->FireOnSaveDocument(inDocument, true, inSaveCopy);
+ isSuccess = true;
+ } catch (...) { /** TODO: implement stacktrace*/
+ }
+
+ if (!isSuccess)
+ m_Dispatch->FireOnSaveDocument(inDocument, false, inSaveCopy);
+}
+
+//=============================================================================
+/**
+ * Called by OnSaveDocument, to allow the error reporting to be inserted.
+ * Because of the nature of the error reporting, OnSaveDocument has to have
+ * a certain structure that limits it (C type variables, no object destructors).
+ * If we are saving a copy, then set the m_SaveCopy flag to true. This will
+ * leave the document in a dirty state and not update it to point to the new
+ * file path.
+*/
+void CCore::OnSaveDocumentCatcher(const CUICFile &inDocument, bool inSaveCopy /*= false*/)
+{
+ m_Dispatch->FireOnProgressBegin(Q3DStudio::CString::fromQString(QObject::tr("Saving...")), inDocument.GetName(),
+ Q3DStudio::CString::fromQString(QObject::tr("Saving...")));
+
+ bool theDisplaySaveFailDialog = false;
+ bool theFileExists = inDocument.Exists();
+ CUICFile theTempFile(inDocument);
+
+ // Test for readonly files
+ if (theFileExists && inDocument.CanWrite() == false)
+ theDisplaySaveFailDialog = true;
+ else {
+ try {
+ // if file already exists, write to a temp file first, to prevent corrupting the
+ // original file.
+ if (theFileExists) {
+ theTempFile = CUICFile::GetTemporaryFile();
+ // sanity check: if we fail to get a temporary file
+ if (theTempFile.GetAbsolutePosixPath().IsEmpty()) { // too bad, we'll have to use
+ // the original (which might be
+ // the only writeable file)
+ theTempFile = inDocument;
+ theFileExists = false;
+ }
+ }
+
+ m_Doc->SaveDocument(theTempFile);
+
+ // update the original file
+ if (theFileExists)
+ theTempFile.CopyTo(inDocument);
+
+ // If we are saving normally and not a copy, then we need to update the current document
+ // to make sure it points to the saved file and make it not-dirty. If we are saving a
+ // copy
+ // then we will leave the document with the original file path dirty state
+ if (!inSaveCopy) {
+ m_Doc->SetDocumentPath(inDocument);
+ m_Doc->SetModifiedFlag(false);
+ }
+ } catch (CStudioException &) // one of our exceptions, show the standard save error.
+ {
+ theDisplaySaveFailDialog = true;
+ } catch (...) {
+ m_Dispatch->FireOnSaveFail(false);
+ }
+ }
+ // clean up
+ if (theFileExists)
+ theTempFile.DeleteFile();
+
+ if (theDisplaySaveFailDialog) {
+ m_Dispatch->FireOnSaveFail(true);
+ }
+
+ m_Dispatch->FireOnProgressEnd();
+}
+
+void CCore::SetCommandStackModifier(ICmdStackModifier *inModifier)
+{
+ m_CmdStack->SetCommandStackModifier(inModifier);
+}
+//=============================================================================
+/**
+ * This is used for do/undo/redo and handles the execution of the command.
+ * The command must have been new'd up, this will take responsibility for
+ * deleting the command.
+ * @param inCommand the command to be executed.
+ * @return bool true if inCommand was deleted, false otherwise
+ * @see CCmdStack::ExecuteCommand.
+ */
+bool CCore::ExecuteCommand(CCmd *inCommand, bool inIsSynchronous)
+{
+ if (!inIsSynchronous) {
+ m_Dispatch->FireOnAsynchronousCommand(inCommand);
+ return false;
+ } else
+ return m_CmdStack->ExecuteCommand(inCommand);
+}
+
+//=============================================================================
+/**
+ * Commit the last command to be executed.
+ * @see CCmdStack::CommitLastCommand.
+ */
+void CCore::CommitCurrentCommand()
+{
+ m_CmdStack->CommitLastCommand();
+}
+
+//=============================================================================
+/**
+ * Callback from the CommandStack to change whether or not this is modified.
+ * This is used when the execution of commands changes the modified state of
+ * the project.
+ */
+void CCore::SetCommandModifiedFlag(bool inIsModified)
+{
+ if (inIsModified)
+ m_Doc->SetModifiedFlag();
+}
+
+//=============================================================================
+/**
+ * Callback from the CommandStack for the change flags after a command was
+ * executed.
+ */
+void CCore::CommandUpdate(unsigned long /*inFlags*/)
+{
+}
+
+//=============================================================================
+/**
+ * Notification from the dispatch that a new presentation is being created.
+ */
+void CCore::OnNewPresentation()
+{
+ m_CmdStack->Clear();
+}
+
+//=============================================================================
+/**
+ * Notification from the dispatch that the current presentation is closing.
+ */
+void CCore::OnClosingPresentation()
+{
+ m_StudioProjectSettings->Reset();
+ m_CmdStack->Clear();
+}
+
+//==============================================================================
+/**
+ * Helper function to remove invalid characters not accepted by windows when
+ * exporting a component.
+ * Invalid characters include: \/:*?"<>|
+ */
+void CCore::RemoveInvalidCharsInComponentName(Q3DStudio::CString &ioComponentName)
+{
+ if (ioComponentName.Find('\\') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("\\", "");
+
+ if (ioComponentName.Find('/') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("/", "");
+
+ if (ioComponentName.Find(':') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace(":", "");
+
+ if (ioComponentName.Find('*') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("*", "");
+
+ if (ioComponentName.Find('?') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("?", "");
+
+ if (ioComponentName.Find('"') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("\"", "");
+
+ if (ioComponentName.Find('<') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("<", "");
+
+ if (ioComponentName.Find('>') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace(">", "");
+
+ if (ioComponentName.Find('|') != Q3DStudio::CString::ENDOFSTRING)
+ ioComponentName.Replace("|", "");
+}
+
+void CCore::DeselectAllKeyframes()
+{
+ m_Doc->DeselectAllKeyframes();
+}
+
+//==============================================================================
+/**
+ * Called by hotkeys to set the start time of the currently selected object.
+ */
+void CCore::SetTimebarStart()
+{
+ m_Doc->TruncateTimebar(true, false);
+}
+
+//==============================================================================
+/**
+ * Called by hotkeys to set the end time of the currently selected object.
+ */
+void CCore::SetTimebarEnd()
+{
+ m_Doc->TruncateTimebar(false, false);
+}
+
+//==============================================================================
+/**
+ * Called by hotkeys to set the start time of the currently selected object.
+ * Affects children objects
+ */
+void CCore::SetTimebarStartAffectsChildren()
+{
+ m_Doc->TruncateTimebar(true, true);
+}
+
+//==============================================================================
+/**
+ * Called by hotkeys to set the end time of the currently selected object.
+ * Affects children objects
+ */
+void CCore::SetTimebarEndAffectsChildren()
+{
+ m_Doc->TruncateTimebar(false, true);
+}
+
+//==============================================================================
+/**
+ * Debugging utility to dump the command queue to a file.
+ */
+void CCore::DumpCommandQueue()
+{
+ CFileOutputStream theOutputStream("CommandStack.txt");
+ CCmdStack::TCmdList theUndoCommands = m_CmdStack->GetUndoStack();
+ CCmdStack::TCmdList::iterator thePos = theUndoCommands.begin();
+ for (; thePos != theUndoCommands.end(); ++thePos) {
+ Q3DStudio::CString theText = Q3DStudio::CString::fromQString((*thePos)->ToString());
+ theOutputStream.Write(theText.GetCharStar(), theText.Length() + 1);
+ theOutputStream.Write("\r\n", 2);
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Core/Core.h b/src/Authoring/Client/Code/Core/Core/Core.h
new file mode 100644
index 00000000..e057e4e3
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Core/Core.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+#include "CmdStack.h"
+#include "DispatchListeners.h"
+#include "BuildConfigParser.h"
+
+//==============================================================================
+// Forwards
+class CDoc;
+class CDispatch;
+class CCmdStack;
+class CHotKeys;
+class CStudioProjectSettings;
+namespace Q3DStudio {
+class CFilePath;
+}
+
+class CCore : public CModificationListener, public CPresentationChangeListener
+{
+protected: // Members
+ CDoc *m_Doc;
+ CDispatch *m_Dispatch;
+ CCmdStack *m_CmdStack;
+ CHotKeys *m_HotKeys;
+ CStudioProjectSettings *m_StudioProjectSettings;
+ Q3DStudio::CBuildConfigurations m_BuildConfigurations;
+ bool m_JustSaved;
+
+public: // Construction
+ CCore();
+ ~CCore();
+
+public: // Methods
+ void Initialize();
+
+ CDoc *GetDoc() const;
+ CDispatch *GetDispatch();
+ CCmdStack *GetCmdStack();
+ CHotKeys *GetHotKeys();
+ CStudioProjectSettings *GetStudioProjectSettings();
+ Q3DStudio::CBuildConfigurations &GetBuildConfigurations();
+
+ bool LoadBuildConfigurations();
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+
+ void OnNewDocument(const CUICFile &inDocument, bool inCreateDirectory);
+ void OnSaveDocument(const CUICFile &inDocument, bool inSaveCopy = false);
+ void OnSaveDocumentCatcher(const CUICFile &inDocument, bool inSaveCopy = false);
+ void SetCommandStackModifier(ICmdStackModifier *inModifier);
+ bool ExecuteCommand(CCmd *inCommand, bool inIsSynchronous = true);
+ void CommitCurrentCommand();
+ void SetCommandModifiedFlag(bool inModified) override;
+ void CommandUpdate(unsigned long inUpdateFlags) override;
+
+ void GetCreateDirectoryFileName(const CUICFile &inDocument, Q3DStudio::CFilePath &outFinalDir,
+ Q3DStudio::CFilePath &outFinalDoc);
+
+ // CPresentationListener
+ void OnNewPresentation() override;
+ void OnClosingPresentation() override;
+
+ bool CanUndo();
+ bool CanRedo();
+ void RemoveInvalidCharsInComponentName(Q3DStudio::CString &ioComponentName);
+ void DeselectAllKeyframes();
+ void SetTimebarStart();
+ void SetTimebarEnd();
+ void SetTimebarStartAffectsChildren();
+ void SetTimebarEndAffectsChildren();
+ void DumpCommandQueue();
+ bool HasJustSaved() { return m_JustSaved; }
+ void SetJustSaved(bool inJustSaved) { m_JustSaved = inJustSaved; }
+
+protected:
+ void InitAndValidateBuildConfiguration();
+};
diff --git a/src/Authoring/Client/Code/Core/Core/Dispatch.cpp b/src/Authoring/Client/Code/Core/Core/Dispatch.cpp
new file mode 100644
index 00000000..e54bccea
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Core/Dispatch.cpp
@@ -0,0 +1,693 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "Dispatch.h"
+#include "DispatchListeners.h"
+#include "MasterP.h"
+#include "UICFile.h"
+#include "Cmd.h"
+#include "boost/signals.hpp"
+#include "boost/signals/connection.hpp"
+#include "boost/make_shared.hpp"
+#include "SelectedValueImpl.h"
+
+namespace {
+struct SSignalConnection : public UICDM::ISignalConnection, boost::noncopyable
+{
+ boost::BOOST_SIGNALS_NAMESPACE::scoped_connection m_connection;
+ SSignalConnection(const boost::BOOST_SIGNALS_NAMESPACE::connection &inConnection)
+ : m_connection(inConnection)
+ {
+ }
+};
+}
+
+#define CONNECT(x) std::make_shared<SSignalConnection>(x.connect(inCallback))
+
+struct SDispatchSignalSystem
+{
+ boost::signal<void(Q3DStudio::SSelectedValue)> m_SelectionChanged;
+};
+
+//=============================================================================
+/**
+ * Constructor for a CDispatch object.
+ */
+CDispatch::CDispatch()
+ : m_DataModelBeginDepth(0)
+ , m_SignalSystem(std::make_shared<SDispatchSignalSystem>())
+{
+}
+
+//==============================================================================
+/**
+ * Releases the object.
+ */
+CDispatch::~CDispatch()
+{
+}
+
+void CDispatch::AddDataModelListener(IDataModelListener *inListener)
+{
+ m_DataModelListeners.AddListener(inListener);
+}
+void CDispatch::RemoveDataModelListener(IDataModelListener *inListener)
+{
+ m_DataModelListeners.RemoveListener(inListener);
+}
+// These are counted, so you can begin,begin,end,end and you will
+// get overall just one begin and one end event sent.
+// This is specifically to allow batching commands wrap their inner commands
+// with the begin/end notification set.
+void CDispatch::FireBeginDataModelNotifications()
+{
+ ++m_DataModelBeginDepth;
+ if (m_DataModelBeginDepth == 1)
+ m_DataModelListeners.FireEvent(&IDataModelListener::OnBeginDataModelNotifications);
+}
+
+bool CDispatch::AreDataModificationsHappening() const
+{
+ return m_DataModelBeginDepth > 0;
+}
+
+void CDispatch::FireEndDataModelNotifications()
+{
+ if (m_DataModelBeginDepth)
+ --m_DataModelBeginDepth;
+ if (!m_DataModelBeginDepth) {
+ // if there is already an exception in the stack, we should not call the below function,
+ // as there is a high chance that there is going to be another exception
+ if (!std::uncaught_exception()) {
+ m_DataModelListeners.FireEvent(&IDataModelListener::OnEndDataModelNotifications);
+ }
+ }
+}
+
+void CDispatch::FireImmediateRefreshInstance(UICDM::CUICDMInstanceHandle inInstance)
+{
+ m_DataModelListeners.FireEvent(&IDataModelListener::OnImmediateRefreshInstanceSingle,
+ inInstance);
+}
+
+void CDispatch::FireImmediateRefreshInstance(UICDM::CUICDMInstanceHandle *inInstances,
+ long inInstanceCount)
+{
+ m_DataModelListeners.FireEvent(&IDataModelListener::OnImmediateRefreshInstanceMultiple,
+ inInstances, inInstanceCount);
+}
+
+void CDispatch::AddReloadListener(IReloadListener *inListener)
+{
+ m_ReloadListeners.AddListener(inListener);
+}
+
+void CDispatch::RemoveReloadListener(IReloadListener *inListener)
+{
+ m_ReloadListeners.RemoveListener(inListener);
+}
+
+void CDispatch::FireReloadEffectInstance(UICDM::CUICDMInstanceHandle inInstance)
+{
+ m_ReloadListeners.FireEvent(&IReloadListener::OnReloadEffectInstance, inInstance);
+}
+
+void CDispatch::AddDocumentBufferCacheListener(IDocumentBufferCacheListener *inListener)
+{
+ m_DocumentBufferCacheListeners.AddListener(inListener);
+}
+void CDispatch::RemoveDocumentBufferCacheListener(IDocumentBufferCacheListener *inListener)
+{
+ m_DocumentBufferCacheListeners.RemoveListener(inListener);
+}
+void CDispatch::FireDocumentBufferCacheInvalidated(const Q3DStudio::CString &inCache)
+{
+ m_DocumentBufferCacheListeners.FireEvent(&IDocumentBufferCacheListener::OnBufferInvalidated,
+ inCache);
+}
+
+//==============================================================================
+/**
+ * Registers a listener for drag operations on the scene. This function removes
+ * the listener from the list if it is already there before adding it again.
+ * This prevents multiple instances of the same listener from registering for
+ * the event.
+ * @param inListener The listener to be registered.
+ */
+void CDispatch::AddSceneDragListener(CSceneDragListener *inListener)
+{
+ m_SceneDragListeners.AddListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Removes all instances of the specified listener from the registration list.
+ * @param inListener The listener to be unregistered
+ */
+void CDispatch::RemoveSceneDragListener(CSceneDragListener *inListener)
+{
+ m_SceneDragListeners.RemoveListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Fires a scene mouse down event to interested listeners.
+ * @param inPoint The mouse postion at the time of the event, in client coordinates.
+ */
+void CDispatch::FireSceneMouseDown(SceneDragSenderType::Enum inSender, const QPoint &inPoint, int inToolMode)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnSceneMouseDown, inSender, inPoint,
+ inToolMode);
+}
+
+void CDispatch::FireSceneMouseUp(SceneDragSenderType::Enum inSender)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnSceneMouseUp, inSender);
+}
+
+//==============================================================================
+/**
+ * Fires a scene mouse move event to interested listeners.
+ * @param inPoint The mouse's current position in client coordinates.
+ * @param inToolMode The current studio toolmode, minus the select mode.
+ * @param inFlags The mouse flags (see MSDN WM_MOUSEMOVE).
+ */
+void CDispatch::FireSceneMouseDrag(SceneDragSenderType::Enum inSender, const QPoint &inPoint, int inToolMode,
+ int inFlags)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnSceneMouseDrag, inSender, inPoint,
+ inToolMode, inFlags);
+}
+
+void CDispatch::FireSceneMouseMove(SceneDragSenderType::Enum inSender, const QPoint &inPoint)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnSceneMouseMove, inSender, inPoint);
+}
+
+void CDispatch::FireSceneMouseDblClick(SceneDragSenderType::Enum inSender, const QPoint &inPoint)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnSceneMouseDblClick, inSender, inPoint);
+}
+
+//==============================================================================
+/**
+ * Fires a scene mouse wheel event to interested listeners.
+ * @param inDelta the distance rotated expressed in multiples or divisions of WHEEL_DELTA
+ * @param inToolMode The current studio toolmode.
+ */
+void CDispatch::FireSceneMouseWheel(SceneDragSenderType::Enum inSender, short inDelta,
+ int inToolMode)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnSceneMouseWheel, inSender, inDelta,
+ inToolMode);
+}
+
+//==============================================================================
+/**
+ * Used for nudging selected objects in the scene.
+ */
+void CDispatch::FireOnNudge(ENudgeDirection inNudgeDirection, int inToolMode, Qt::KeyboardModifiers inFlags)
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnNudge, inNudgeDirection, inToolMode,
+ inFlags);
+}
+
+//==============================================================================
+/**
+ * Finished nudging, clears the acceleration.
+ */
+void CDispatch::FireOnNudgeDone()
+{
+ m_SceneDragListeners.FireEvent(&CSceneDragListener::OnNudgeDone);
+}
+
+UICDM::TSignalConnectionPtr
+CDispatch::ConnectSelectionChange(std::function<void(Q3DStudio::SSelectedValue)> inCallback)
+{
+ return CONNECT(m_SignalSystem->m_SelectionChanged);
+}
+
+void CDispatch::FireSelectionChange(Q3DStudio::SSelectedValue inValue)
+{
+ m_SignalSystem->m_SelectionChanged(inValue);
+}
+
+//=============================================================================
+/**
+ * Add a listener to be notified of presentation changes.
+ * @param inListener the listener to be added.
+ */
+void CDispatch::AddPresentationChangeListener(CPresentationChangeListener *inListener)
+{
+ m_PresentationChangeListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Remove a listener from the list of listeners to be notified of presentation changes.
+ * @param inListener the listener to be removed.
+ */
+void CDispatch::RemovePresentationChangeListener(CPresentationChangeListener *inListener)
+{
+ m_PresentationChangeListeners.RemoveListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Notify all the presentation change listeners that a presentation or a subpresentation is loading
+ * To be exact, this is fired just before the presentation is to be loaded
+ */
+void CDispatch::FireOnLoadingPresentation(bool inIsSubPresentation /*= false */)
+{
+ m_PresentationChangeListeners.FireEvent(&CPresentationChangeListener::OnLoadingPresentation,
+ inIsSubPresentation);
+}
+
+//=============================================================================
+/**
+ * Notify when a subpresentation has been loaded.
+ * Called if FireOnLoadingPresentation has been called earlier.
+ */
+void CDispatch::FireOnLoadedSubPresentation()
+{
+ m_PresentationChangeListeners.FireEvent(&CPresentationChangeListener::OnLoadedSubPresentation);
+}
+
+//=============================================================================
+/**
+ * Notify all the presentation change listeners that a new presentation was loaded.
+ */
+void CDispatch::FireOnNewPresentation()
+{
+ UICPROFILE(FireOnNewPresentation);
+
+ m_PresentationChangeListeners.FireEvent(&CPresentationChangeListener::OnNewPresentation);
+}
+
+//=============================================================================
+/**
+ * Notify all the presentation change listeners that the current presentation is closing.
+ */
+void CDispatch::FireOnClosingPresentation()
+{
+ m_PresentationChangeListeners.FireEvent(&CPresentationChangeListener::OnClosingPresentation);
+}
+
+void CDispatch::FireOnSavingPresentation(const CUICFile *inNewPresentationFile)
+{
+ m_PresentationChangeListeners.FireEvent(&CPresentationChangeListener::OnSavingPresentation,
+ inNewPresentationFile);
+}
+
+void CDispatch::FireOnExportingAsset(UICDM::CUICDMInstanceHandle inInstance)
+{
+ m_PresentationChangeListeners.FireEvent(&CPresentationChangeListener::OnExportingAsset,
+ inInstance);
+}
+
+void CDispatch::FireOnPresentationModifiedExternally()
+{
+ m_PresentationChangeListeners.FireEvent(
+ &CPresentationChangeListener::OnPresentationModifiedExternally);
+}
+
+void CDispatch::AddClientPlayChangeListener(CClientPlayChangeListener *inListener)
+{
+ m_ClientPlayChangeListeners.AddListener(inListener);
+}
+
+void CDispatch::RemoveClientPlayChangeListener(CClientPlayChangeListener *inListener)
+{
+ m_ClientPlayChangeListeners.RemoveListener(inListener);
+}
+
+void CDispatch::FireOnPlayStart()
+{
+ m_ClientPlayChangeListeners.FireEvent(&CClientPlayChangeListener::OnPlayStart);
+}
+
+void CDispatch::FireOnPlayStop()
+{
+ m_ClientPlayChangeListeners.FireEvent(&CClientPlayChangeListener::OnPlayStop);
+}
+
+void CDispatch::FireOnTimeChanged(long inTime)
+{
+ try {
+ m_ClientPlayChangeListeners.FireEvent(&CClientPlayChangeListener::OnTimeChanged, inTime);
+ }
+ // Temporary fix for the stuck playhead problem on a crash
+ // this should be fixed by addressing the actual crash
+ catch (...) {
+ }
+}
+
+//=============================================================================
+/**
+ * Add a navigation listener to this.
+ */
+void CDispatch::AddNavigationListener(CNavigationListener *inListener)
+{
+ m_NavigationListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Remove a navigation listener from this.
+ */
+void CDispatch::RemoveNavigationListener(CNavigationListener *inListener)
+{
+ m_NavigationListeners.RemoveListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Fire an event to the navigation listeners to navigate to the URL.
+ * This is used to update the assistant palette to the specified URL.
+ */
+void CDispatch::FireOnNavigate(const Q3DStudio::CString &inURL, bool inForceDisplay)
+{
+ m_NavigationListeners.FireEvent(&CNavigationListener::OnNavigate, inURL, inForceDisplay);
+}
+
+//=============================================================================
+/**
+ * Add a file open listener to this.
+ */
+void CDispatch::AddFileOpenListener(CFileOpenListener *inListener)
+{
+ m_FileOpenListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Remove a file open listener from this.
+ */
+void CDispatch::RemoveFileOpenListener(CFileOpenListener *inListener)
+{
+ m_FileOpenListeners.RemoveListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Fire an event to all the file open listeners that a has been opened.
+ */
+void CDispatch::FireOnOpenDocument(const CUICFile &inFile, bool inSucceeded)
+{
+ m_FileOpenListeners.FireEvent(&CFileOpenListener::OnOpenDocument, inFile, inSucceeded);
+}
+
+//=============================================================================
+/**
+ * Fire an event to all the file open listeners that a has been saved.
+ */
+void CDispatch::FireOnSaveDocument(const CUICFile &inFile, bool inSucceeded, bool inSaveCopy)
+{
+ m_FileOpenListeners.FireEvent(&CFileOpenListener::OnSaveDocument, inFile, inSucceeded,
+ inSaveCopy);
+}
+
+//=============================================================================
+/**
+ * Fire an event to all the file open listeners that a has been saved.
+ */
+void CDispatch::FireOnDocumentPathChanged(const CUICFile &inNewPath)
+{
+ m_FileOpenListeners.FireEvent(&CFileOpenListener::OnDocumentPathChanged, inNewPath);
+}
+
+//=============================================================================
+/**
+ * Adds a toolbar change listener
+ */
+void CDispatch::AddToolbarChangeListener(CToolbarChangeListener *inListener)
+{
+ m_ToolbarChangeListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Removes a toolbar change listener
+ */
+void CDispatch::RemoveToolbarChangeListener(CToolbarChangeListener *inListener)
+{
+ m_ToolbarChangeListeners.RemoveListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Fire an event to all the toolbar change listeners
+ */
+void CDispatch::FireOnToolbarChange() // long inToolType, bool inEnabled )
+{
+ m_ToolbarChangeListeners.FireEvent(&CToolbarChangeListener::OnToolbarChange);
+}
+
+//=============================================================================
+/**
+ * Adds a selected node property change listener
+ */
+void CDispatch::AddSelectedNodePropChangeListener(CSelectedNodePropChangeListener *inListener)
+{
+ m_SelectedNodePropChangeListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Removes a selected node property change listener
+ */
+void CDispatch::RemoveSelectedNodePropChangeListener(CSelectedNodePropChangeListener *inListener)
+{
+ m_SelectedNodePropChangeListeners.RemoveListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Fire an event to all the selected node property change listeners
+ */
+void CDispatch::FireOnSelectedNodePropChange(const Q3DStudio::CString &inPropertyName)
+{
+ m_SelectedNodePropChangeListeners.FireEvent(
+ &CSelectedNodePropChangeListener::OnPropValueChanged, inPropertyName);
+}
+
+//=============================================================================
+/**
+ * Fire an event to all the selected node property change listeners
+ */
+void CDispatch::FireOnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis)
+{
+ m_SelectedNodePropChangeListeners.FireEvent(&CSelectedNodePropChangeListener::OnMouseDragged,
+ inConstrainXAxis, inConstrainYAxis);
+}
+
+//=============================================================================
+/**
+ * Adds a edit camera change listener
+ */
+void CDispatch::AddEditCameraChangeListener(CEditCameraChangeListener *inListener)
+{
+ m_EditCameraChangeListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Removes a edit camera change listener
+ */
+void CDispatch::RemoveEditCameraChangeListener(CEditCameraChangeListener *inListener)
+{
+ m_EditCameraChangeListeners.RemoveListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Fire an event on changing active camera to all the render mode change listeners
+ */
+void CDispatch::FireOnEditCameraChanged()
+{
+ m_EditCameraChangeListeners.FireEvent(&CEditCameraChangeListener::OnEditCameraChanged);
+}
+
+//=============================================================================
+/**
+ * Fire an event on changing active camera to all the render mode change listeners
+ */
+void CDispatch::FireOnCamerasTransformed()
+{
+ m_EditCameraChangeListeners.FireEvent(&CEditCameraChangeListener::OnEditCamerasTransformed);
+}
+
+void CDispatch::FireAuthorZoomChanged()
+{
+ m_EditCameraChangeListeners.FireEvent(&CEditCameraChangeListener::OnAuthorZoomChanged);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Async messages from the core
+void CDispatch::AddCoreAsynchronousEventListener(CCoreAsynchronousEventListener *inListener)
+{
+ m_CoreAsynchronousEventListeners.AddListener(inListener);
+}
+
+void CDispatch::RemoveCoreAsynchronousEventListener(CCoreAsynchronousEventListener *inListener)
+{
+ m_CoreAsynchronousEventListeners.RemoveListener(inListener);
+}
+
+void CDispatch::FireOnAsynchronousCommand(CCmd *inCmd)
+{
+ m_CoreAsynchronousEventListeners.FireEvent(
+ &CCoreAsynchronousEventListener::OnAsynchronousCommand, inCmd);
+}
+
+struct SGenericAsyncCommand : public CCmd
+{
+ std::function<void()> m_Function;
+ SGenericAsyncCommand(std::function<void()> inFunc)
+ : m_Function(inFunc)
+ {
+ SetUndoable(false);
+ m_ShouldSetModified = false;
+ }
+
+ unsigned long Do() override
+ {
+ m_Function();
+ return 0;
+ }
+ unsigned long Undo() override { return 0; }
+};
+
+void CDispatch::FireOnAsynchronousCommand(std::function<void()> inFunction)
+{
+ FireOnAsynchronousCommand(new SGenericAsyncCommand(inFunction));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Cleanly display app status messages
+void CDispatch::AddAppStatusListener(CAppStatusListener *inListener)
+{
+ m_AppStatusListeners.AddListener(inListener);
+}
+
+void CDispatch::RemoveAppStatusListener(CAppStatusListener *inListener)
+{
+ m_AppStatusListeners.RemoveListener(inListener);
+}
+
+void CDispatch::FireOnDisplayAppStatus(Q3DStudio::CString &inStatusMsg)
+{
+ m_AppStatusListeners.FireEvent(&CAppStatusListener::OnDisplayAppStatus, inStatusMsg);
+}
+
+void CDispatch::FireOnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle)
+{
+ m_AppStatusListeners.FireEvent(&CAppStatusListener::OnProgressBegin, inActionText, inFileName,
+ inWindowTitle);
+}
+
+void CDispatch::FireOnProgressEnd()
+{
+ m_AppStatusListeners.FireEvent(&CAppStatusListener::OnProgressEnd);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Failure notification
+void CDispatch::AddFailListener(CFailListener *inListener)
+{
+ m_FailListeners.AddListener(inListener);
+}
+
+void CDispatch::RemoveFailListener(CFailListener *inListener)
+{
+ m_FailListeners.RemoveListener(inListener);
+}
+
+void CDispatch::FireOnAssetDeleteFail()
+{
+ m_FailListeners.FireEvent(&CFailListener::OnAssetDeleteFail);
+}
+
+void CDispatch::FireOnPasteFail()
+{
+ m_FailListeners.FireEvent(&CFailListener::OnPasteFail);
+}
+
+void CDispatch::FireOnBuildConfigurationFileParseFail(const Q3DStudio::CString &inMessage)
+{
+ m_FailListeners.FireEvent(&CFailListener::OnBuildconfigurationFileParseFail, inMessage);
+}
+
+void CDispatch::FireOnSaveFail(bool inKnownError)
+{
+ m_FailListeners.FireEvent(&CFailListener::OnSaveFail, inKnownError);
+}
+
+void CDispatch::FireOnProjectVariableFail(const Q3DStudio::CString &inMessage)
+{
+ m_FailListeners.FireEvent(&CFailListener::OnProjectVariableFail, inMessage);
+}
+
+void CDispatch::FireOnErrorFail(const Q3DStudio::CString &inText)
+{
+ m_FailListeners.FireEvent(&CFailListener::OnErrorFail, inText);
+}
+
+void CDispatch::FireOnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription)
+{
+ m_FailListeners.FireEvent(&CFailListener::OnRefreshResourceFail, inResourceName, inDescription);
+}
+
+void CDispatch::AddRendererListener(CRendererListener *inListener)
+{
+ m_RendererListeners.AddListener(inListener);
+}
+
+void CDispatch::RemoveRendererListener(CRendererListener *inListener)
+{
+ m_RendererListeners.RemoveListener(inListener);
+}
+
+void CDispatch::FireOnRendererInitialized()
+{
+ m_RendererListeners.FireEvent(&CRendererListener::OnRendererInitialized);
+}
diff --git a/src/Authoring/Client/Code/Core/Core/Dispatch.h b/src/Authoring/Client/Code/Core/Core/Dispatch.h
new file mode 100644
index 00000000..7d90220c
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Core/Dispatch.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_DISPATCH_H
+#define INCLUDED_DISPATCH_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CoreConst.h"
+#include "StudioObjectTypes.h"
+#include "UICId.h"
+#include "Multicaster.h"
+#include "UICDMHandles.h"
+#include "UICDMSignals.h"
+#include "SelectedValue.h"
+
+#include <QPoint>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CSceneDragListener;
+class CSelectionChangeListener;
+class CAsset;
+class CUICFile;
+class CURL;
+class CPresentationChangeListener;
+class CResourceChangeListener;
+class CClientPlayChangeListener;
+class CAppStatusListener;
+class CNavigationListener;
+class CFileOpenListener;
+class CToolbarChangeListener;
+class CSelectedNodePropChangeListener;
+class CEditCameraChangeListener;
+class CTimelineChangeListener;
+class CInspectableBase;
+class CCoreAsynchronousEventListener;
+class CCmd;
+class CFailListener;
+class CSharedBufferChangeListener;
+class CSharedBuffer;
+class IReloadListener;
+class IDataModelListener;
+class IDocumentBufferCacheListener;
+class IDocumentResourcesListener;
+class CRendererListener;
+struct SDispatchSignalSystem;
+
+//==============================================================================
+/**
+ * Dispatches commands
+ */
+//==============================================================================
+class CDispatch
+{
+public:
+ CDispatch();
+ virtual ~CDispatch();
+
+ void AddDataModelListener(IDataModelListener *inListener);
+ void RemoveDataModelListener(IDataModelListener *inListener);
+ // These are counted, so you can begin,begin,end,end and you will
+ // get overall just one begin and one end event sent.
+ // This is specifically to allow batching commands wrap their inner commands
+ // with the begin/end notification set.
+ void FireBeginDataModelNotifications();
+ bool AreDataModificationsHappening() const;
+ void FireEndDataModelNotifications();
+ // Called so select views can refresh at a high rate (inspector and 3d view) when an object
+ // is dragged (or when multiple keyframes are dragged.
+ // Most views should ignore this or ensure they filter the message by at least their instance.
+ // Inproperty may be 0 in which case it should be assumed all properties may have changed
+ void FireImmediateRefreshInstance(UICDM::CUICDMInstanceHandle inInstance);
+ void FireImmediateRefreshInstance(UICDM::CUICDMInstanceHandle *inInstance,
+ long inInstanceCount);
+
+ void AddReloadListener(IReloadListener *inListener);
+ void RemoveReloadListener(IReloadListener *inListener);
+ void FireReloadEffectInstance(UICDM::CUICDMInstanceHandle inInstance);
+
+ void AddDocumentBufferCacheListener(IDocumentBufferCacheListener *inListener);
+ void RemoveDocumentBufferCacheListener(IDocumentBufferCacheListener *inListener);
+ void FireDocumentBufferCacheInvalidated(const Q3DStudio::CString &inCache);
+
+ // Scene drag
+ void AddSceneDragListener(CSceneDragListener *inListener);
+ void RemoveSceneDragListener(CSceneDragListener *inListener);
+ void FireSceneMouseDown(SceneDragSenderType::Enum inSender, const QPoint &inPoint, int inToolMode);
+ void FireSceneMouseDrag(SceneDragSenderType::Enum inSender, const QPoint &inPoint, int inToolMode,
+ int inFlags);
+ void FireSceneMouseMove(SceneDragSenderType::Enum inSender, const QPoint &inPoint);
+ void FireSceneMouseDblClick(SceneDragSenderType::Enum inSender, const QPoint &inPoint);
+ void FireSceneMouseWheel(SceneDragSenderType::Enum inSender, short inDelta, int inToolMode);
+ void FireOnNudge(ENudgeDirection inNudgeDirection, int inToolMode, Qt::KeyboardModifiers inFlags);
+ void FireOnNudgeDone();
+ void FireSceneMouseUp(SceneDragSenderType::Enum inSender);
+
+ // Selection Change new skool.
+
+ UICDM::TSignalConnectionPtr
+ ConnectSelectionChange(std::function<void(Q3DStudio::SSelectedValue)> inListener);
+ void FireSelectionChange(Q3DStudio::SSelectedValue inValue);
+
+ void AddPresentationChangeListener(CPresentationChangeListener *inListener);
+ void RemovePresentationChangeListener(CPresentationChangeListener *inListener);
+ void FireOnLoadingPresentation(bool inIsSubPresentation = false);
+ void FireOnLoadedSubPresentation();
+ void FireOnNewPresentation();
+ void FireOnClosingPresentation();
+ void FireOnSavingPresentation(const CUICFile *inNewPresentationFile = NULL);
+ void FireOnExportingAsset(UICDM::CUICDMInstanceHandle inInstance);
+ void FireOnPresentationModifiedExternally();
+
+ void AddClientPlayChangeListener(CClientPlayChangeListener *inListener);
+ void RemoveClientPlayChangeListener(CClientPlayChangeListener *inListener);
+ void FireOnPlayStart();
+ void FireOnPlayStop();
+ void FireOnTimeChanged(long inTime);
+
+ void AddNavigationListener(CNavigationListener *inListener);
+ void RemoveNavigationListener(CNavigationListener *inListener);
+ void FireOnNavigate(const Q3DStudio::CString &inURL, bool inForceDisplay);
+
+ void AddFileOpenListener(CFileOpenListener *inListener);
+ void RemoveFileOpenListener(CFileOpenListener *inListener);
+ void FireOnOpenDocument(const CUICFile &inFile, bool inSucceeded);
+ void FireOnSaveDocument(const CUICFile &inFile, bool inSucceeded, bool inSaveCopy);
+ void FireOnDocumentPathChanged(const CUICFile &inNewPath);
+
+ // Toolbar changes
+ void AddToolbarChangeListener(CToolbarChangeListener *inListener);
+ void RemoveToolbarChangeListener(CToolbarChangeListener *inListener);
+ void FireOnToolbarChange();
+
+ // State Property changes
+ void AddSelectedNodePropChangeListener(CSelectedNodePropChangeListener *inListener);
+ void RemoveSelectedNodePropChangeListener(CSelectedNodePropChangeListener *inListener);
+ void FireOnSelectedNodePropChange(const Q3DStudio::CString &inPropertyName);
+ void FireOnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis);
+
+ // Edit Camera changes
+ void AddEditCameraChangeListener(CEditCameraChangeListener *inListener);
+ void RemoveEditCameraChangeListener(CEditCameraChangeListener *inListener);
+ void FireOnEditCameraChanged();
+ void FireOnCamerasTransformed();
+ void FireAuthorZoomChanged();
+
+ // Asynchronous events originating in the core
+ void AddCoreAsynchronousEventListener(CCoreAsynchronousEventListener *inListener);
+ void RemoveCoreAsynchronousEventListener(CCoreAsynchronousEventListener *inListener);
+ void FireOnAsynchronousCommand(CCmd *inCmd);
+ void FireOnAsynchronousCommand(std::function<void()> inFunction);
+
+ // Cleanly display app status messages
+ void AddAppStatusListener(CAppStatusListener *inListener);
+ void RemoveAppStatusListener(CAppStatusListener *inListener);
+ void FireOnDisplayAppStatus(Q3DStudio::CString &inStatusMsg);
+ void FireOnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle);
+ void FireOnProgressEnd();
+
+ // Failure notification
+ void AddFailListener(CFailListener *inListener);
+ void RemoveFailListener(CFailListener *inListener);
+ void FireOnAssetDeleteFail();
+ void FireOnPasteFail();
+ void FireOnBuildConfigurationFileParseFail(const Q3DStudio::CString &inMessage);
+ void FireOnSaveFail(bool inKnownError);
+ void FireOnProjectVariableFail(const Q3DStudio::CString &inMessage);
+ void FireOnErrorFail(const Q3DStudio::CString &inText);
+ void FireOnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription);
+
+ void AddRendererListener(CRendererListener *inListener);
+ void RemoveRendererListener(CRendererListener *inListener);
+ void FireOnRendererInitialized();
+
+protected:
+ CMulticaster<IDocumentBufferCacheListener *> m_DocumentBufferCacheListeners;
+ long m_DataModelBeginDepth;
+ CMulticaster<IReloadListener *> m_ReloadListeners;
+ CMulticaster<IDataModelListener *> m_DataModelListeners;
+ CMulticaster<IDocumentResourcesListener *> m_DocumentResourcesListeners;
+ CMulticaster<CSceneDragListener *> m_SceneDragListeners;
+ CMulticaster<CSelectionChangeListener *> m_SelectionListeners;
+ CMulticaster<CPresentationChangeListener *> m_PresentationChangeListeners;
+ CMulticaster<CResourceChangeListener *> m_ResourceChangeListeners;
+ CMulticaster<CClientPlayChangeListener *> m_ClientPlayChangeListeners;
+ CMulticaster<CNavigationListener *> m_NavigationListeners;
+ CMulticaster<CFileOpenListener *> m_FileOpenListeners;
+ CMulticaster<CToolbarChangeListener *> m_ToolbarChangeListeners;
+ CMulticaster<CSelectedNodePropChangeListener *> m_SelectedNodePropChangeListeners;
+ CMulticaster<CEditCameraChangeListener *> m_EditCameraChangeListeners;
+ CMulticaster<CTimelineChangeListener *> m_TimelineChangeListeners;
+ CMulticaster<CCoreAsynchronousEventListener *> m_CoreAsynchronousEventListeners;
+ CMulticaster<CAppStatusListener *> m_AppStatusListeners;
+ CMulticaster<CFailListener *> m_FailListeners;
+ CMulticaster<CSharedBufferChangeListener *> m_SharedBufferChangeListeners;
+ CMulticaster<CRendererListener *> m_RendererListeners;
+ std::shared_ptr<SDispatchSignalSystem> m_SignalSystem;
+};
+
+struct CDispatchDataModelNotificationScope
+{
+ CDispatch &m_Dispatch;
+ CDispatchDataModelNotificationScope(CDispatch &dispatch)
+ : m_Dispatch(dispatch)
+ {
+ m_Dispatch.FireBeginDataModelNotifications();
+ }
+ ~CDispatchDataModelNotificationScope()
+ {
+ // if there is already an exception in the stack, we should not call the below function,
+ // exception in a destructor is bad news and there is a high chance that there is going to
+ // be another exception
+ // however we are still reducing the data model begin depth
+ m_Dispatch.FireEndDataModelNotifications();
+ }
+};
+struct CDispatchDataModelImmediateScope
+{
+ CDispatch &m_Dispatch;
+ UICDM::CUICDMInstanceHandle m_Instance;
+
+ CDispatchDataModelImmediateScope(CDispatch &dispatch, UICDM::CUICDMInstanceHandle instance)
+ : m_Dispatch(dispatch)
+ , m_Instance(instance)
+ {
+ }
+ ~CDispatchDataModelImmediateScope()
+ {
+ // if there is already an exception in the stack, we should not call the below function,
+ // exception in a destructor is bad news and there is a high chance that there is going to
+ // be another exception
+ if (!std::uncaught_exception()) {
+ m_Dispatch.FireImmediateRefreshInstance(m_Instance);
+ }
+ }
+};
+
+#endif // INCLUDED_DISPATCH_H
diff --git a/src/Authoring/Client/Code/Core/Core/DispatchListeners.h b/src/Authoring/Client/Code/Core/Core/DispatchListeners.h
new file mode 100644
index 00000000..77aff0e2
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Core/DispatchListeners.h
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_DISPATCHLISTENERS_H
+#define INCLUDED_DISPATCHLISTENERS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CoreConst.h"
+#include "UICId.h"
+#include "Pt.h"
+#include "UICDMHandles.h"
+#include <QPoint>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+class CAsset;
+class CUICFile;
+class CURL;
+class ISelectable;
+class CCmd;
+class CSharedBuffer;
+
+//=============================================================================
+/**
+ * Listener for drag events on the scene
+ */
+//=============================================================================
+class CSceneDragListener
+{
+public:
+ virtual ~CSceneDragListener() {}
+ virtual void OnSceneMouseDown(SceneDragSenderType::Enum inSender, QPoint inPoint, int inToolMode)
+ {
+ Q_UNUSED(inSender);
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inToolMode);
+ }
+
+ virtual void OnSceneMouseDrag(SceneDragSenderType::Enum inSender, QPoint inPoint, int inToolMode,
+ int inFlags)
+ {
+ Q_UNUSED(inSender);
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inToolMode);
+ Q_UNUSED(inFlags);
+ }
+
+ virtual void OnSceneMouseMove(SceneDragSenderType::Enum /*inSender*/, QPoint /*inPoint*/) {}
+
+ virtual void OnSceneMouseUp(SceneDragSenderType::Enum inSender) = 0;
+
+ virtual void OnSceneMouseDblClick(SceneDragSenderType::Enum inSender, QPoint inPoint)
+ {
+ Q_UNUSED(inSender);
+ Q_UNUSED(inPoint);
+ }
+
+ virtual void OnSceneMouseWheel(SceneDragSenderType::Enum inSender, short inDelta,
+ int inToolMode)
+ {
+ Q_UNUSED(inSender);
+ Q_UNUSED(inDelta);
+ Q_UNUSED(inToolMode);
+ }
+
+ virtual void OnNudge(ENudgeDirection inNudgeDirection, int inToolMode, int inFlags)
+ {
+ Q_UNUSED(inNudgeDirection);
+ Q_UNUSED(inToolMode);
+ Q_UNUSED(inFlags);
+ }
+
+ virtual void OnNudgeDone() {}
+};
+
+//=============================================================================
+/**
+ * Listener for timebar change events
+ */
+//=============================================================================
+class CTimeBarChangeListener
+{
+public:
+ virtual ~CTimeBarChangeListener() {}
+ virtual void OnTimeBarChange(CAsset *inAsset) = 0;
+};
+
+//=============================================================================
+/**
+ * Listener for object time dependent change events
+ */
+//=============================================================================
+class CTimeDependentChangeListener
+{
+public:
+ virtual ~CTimeDependentChangeListener() {}
+ virtual void OnTimeDependentChange(CAsset *inAsset) = 0;
+};
+
+//=============================================================================
+/**
+ * Listener for toolbar change events
+ */
+//=============================================================================
+class CToolbarChangeListener
+{
+public:
+ virtual ~CToolbarChangeListener() {}
+ virtual void OnToolbarChange() = 0;
+};
+
+//=============================================================================
+/**
+ * Listener for changes to the presentation.
+ */
+class CPresentationChangeListener
+{
+public:
+ virtual ~CPresentationChangeListener() {}
+ //==========================================================================
+ /**
+ * New presentation or subpresentation (e.g. subtree such as component or pasted object) is
+ * being loaded.
+ */
+ virtual void OnLoadingPresentation(bool inIsSubPresentation)
+ {
+ Q_UNUSED(inIsSubPresentation);
+ }
+ //==========================================================================
+ /**
+ * A subpresentation is loaded.
+ */
+ virtual void OnLoadedSubPresentation() {}
+ //==========================================================================
+ /**
+ * New presentation is being created.
+ */
+ virtual void OnNewPresentation() {}
+
+ //==========================================================================
+ /**
+ * The current presentation is being closed.
+ */
+ virtual void OnClosingPresentation() {}
+
+ //==========================================================================
+ /**
+ * The current presentation is being saved.
+ */
+ virtual void OnSavingPresentation(const CUICFile *inNewPresentationFile)
+ {
+ Q_UNUSED(inNewPresentationFile);
+ }
+
+ virtual void OnExportingAsset(UICDM::CUICDMInstanceHandle inInstance)
+ {
+ Q_UNUSED(inInstance);
+ }
+
+ virtual void OnPresentationModifiedExternally() {}
+};
+
+class CClientPlayChangeListener
+{
+public:
+ virtual ~CClientPlayChangeListener() {}
+
+ //==========================================================================
+ /**
+ * The presentation is being played (preview in studio)
+ */
+ virtual void OnPlayStart(){}
+
+ //==========================================================================
+ /**
+ * The presentation is being stopped (preview in studio)
+ */
+ virtual void OnPlayStop(){}
+
+ //==========================================================================
+ /**
+ * The presentation time has changed.
+ * @param inTime the new client time.
+ */
+ virtual void OnTimeChanged(long inTime) = 0;
+};
+
+class CNavigationListener
+{
+public:
+ virtual void OnNavigate(const Q3DStudio::CString &inURL, bool inForceDisplay) = 0;
+};
+
+class CFileOpenListener
+{
+public:
+ virtual void OnOpenDocument(const CUICFile &inFilename, bool inSucceeded) = 0;
+ virtual void OnSaveDocument(const CUICFile &inFilename, bool inSucceeded, bool inSaveCopy) = 0;
+ virtual void OnDocumentPathChanged(const CUICFile &inNewPath) = 0;
+};
+
+class CSelectedNodePropChangeListener
+{
+public:
+ virtual void OnPropValueChanged(const Q3DStudio::CString &inPropertyName) = 0;
+ virtual void OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis) = 0;
+};
+
+//=============================================================================
+/**
+ * Listener for edit camera change events
+ */
+//=============================================================================
+class CEditCameraChangeListener
+{
+public:
+ virtual void OnEditCameraChanged() = 0;
+ virtual void OnEditCamerasTransformed() = 0;
+ virtual void OnAuthorZoomChanged() = 0;
+};
+
+class CTimelineChangeListener
+{
+public:
+ virtual void OnTimelineLayoutChanged() = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Listener for async events originating in the core
+class CCoreAsynchronousEventListener
+{
+public:
+ virtual ~CCoreAsynchronousEventListener() {}
+ virtual void OnAsynchronousCommand(CCmd *inCmd) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Clean way for anyone to set the app status message
+class CAppStatusListener
+{
+public:
+ virtual ~CAppStatusListener() {}
+ virtual void OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg) = 0;
+ virtual void OnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle) = 0;
+ virtual void OnProgressEnd() = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Notification of failures
+class CFailListener
+{
+public:
+ virtual ~CFailListener() {}
+ virtual void OnAssetDeleteFail() = 0;
+ virtual void OnPasteFail() = 0;
+ virtual void OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage) = 0;
+ virtual void OnSaveFail(bool inKnownError) = 0;
+ virtual void OnProjectVariableFail(const Q3DStudio::CString &inMessage) = 0;
+ virtual void OnErrorFail(const Q3DStudio::CString &inText) = 0;
+ virtual void OnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription) = 0;
+};
+
+class IDataModelListener
+{
+public:
+ virtual ~IDataModelListener() {}
+ // Fired before a large group of notifications come out so views can
+ // only refresh their view once.
+ virtual void OnBeginDataModelNotifications() = 0;
+ // Fired after a large gruop of notifications (onInstancePropertyChanged, etc) come out
+ // so views can be careful about refreshing their data and there view
+ virtual void OnEndDataModelNotifications() = 0;
+
+ // Fired during 3d drag or mouse move events (or keyframe drag) or likewise
+ // events so that views that need to update based on the new data can.
+ virtual void OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance) = 0;
+ // Same thing, but fired when more than one instance is being refreshed.
+ virtual void OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance,
+ long inInstanceCount) = 0;
+};
+
+class IReloadListener
+{
+public:
+ virtual void OnReloadEffectInstance(UICDM::CUICDMInstanceHandle inInstance) = 0;
+};
+
+class IDocumentBufferCacheListener
+{
+public:
+ virtual ~IDocumentBufferCacheListener() {}
+ // I can't get reference messages to work with the dispatch system.
+ virtual void OnBufferInvalidated(Q3DStudio::CString inString) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// For StudioRenderer to send messages
+class CRendererListener
+{
+public:
+ virtual void OnRendererInitialized() = 0;
+};
+
+#endif // INCLUDED_DISPATCHLISTENERS_H
diff --git a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
new file mode 100644
index 00000000..86885246
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
@@ -0,0 +1,2064 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "ClientDataModelBridge.h"
+#include "Doc.h"
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include "StandardExtensions.h"
+#include <fstream>
+#include "UICDMSlideCore.h"
+#include "UICDMSlideGraphCore.h"
+
+#include "StudioFullSystem.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMAnimation.h"
+#include "UICDMSlides.h"
+#include "UICDMDataCore.h"
+#include "UICDMActionCore.h"
+#include "GraphUtils.h"
+#include "StudioCoreSystem.h"
+
+#include "Core.h"
+#include "RelativePathTools.h"
+#include "FormattedInputStream.h"
+#include "FormattedOutputStream.h"
+#include "Dispatch.h"
+#include "UICFileTools.h"
+#include <boost/make_shared.hpp>
+
+using namespace UICDM;
+using namespace std;
+using namespace boost;
+
+inline SLong4 GuidToLong4(Q3DStudio::CId inGuid)
+{
+ Q3DStudio::TGUIDPacked thePacked(inGuid);
+ SLong4 theGuid(thePacked.Data1, thePacked.Data2, thePacked.Data3, thePacked.Data4);
+ return theGuid;
+}
+
+CClientDataModelBridge::CClientDataModelBridge(
+ UICDM::IDataCore *inDataCore, UICDM::ISlideCore *inSlideCore,
+ UICDM::ISlideGraphCore *inSlideGraphCore, UICDM::IAnimationCore *inAnimationCore,
+ std::shared_ptr<UICDM::IMetaData> inNewMetaData,
+ std::shared_ptr<UICDM::SComposerObjectDefinitions> inDefinitions, CDoc *inDoc)
+ : m_DataCore(inDataCore)
+ , m_SlideCore(inSlideCore)
+ , m_SlideGraphCore(inSlideGraphCore)
+ , m_AnimationCore(inAnimationCore)
+ , m_NewMetaData(inNewMetaData)
+ , m_ObjectDefinitions(inDefinitions)
+ , m_Doc(inDoc)
+ , m_DefaultMaterial(inDefinitions->m_Material)
+ , m_SceneImage(inDefinitions->m_Image)
+ , m_Node(inDefinitions->m_Node)
+ , m_Layer(inDefinitions->m_Layer)
+ , m_Model(inDefinitions->m_Model)
+ , m_Light(inDefinitions->m_Light)
+ , m_Camera(inDefinitions->m_Camera)
+ , m_Text(inDefinitions->m_Text)
+ , m_Group(inDefinitions->m_Group)
+ , m_Component(inDefinitions->m_Component)
+ , m_Behavior(inDefinitions->m_Behavior)
+ , m_Scene(inDefinitions->m_Scene)
+ , m_SlideItem(inDefinitions->m_Slide)
+ , m_ActionItem(inDefinitions->m_Action)
+ , m_SceneAsset(inDefinitions->m_Asset)
+ , m_Effect(inDefinitions->m_Effect)
+ , m_RenderPlugin(inDefinitions->m_RenderPlugin)
+ , m_MaterialBase(inDefinitions->m_MaterialBase)
+ , m_CustomMaterial(inDefinitions->m_CustomMaterial)
+ , m_Alias(inDefinitions->m_Alias)
+ , m_Path(inDefinitions->m_Path)
+ , m_Lightmaps(inDefinitions->m_Lightmaps)
+ , m_CacheEnabled(false)
+{
+}
+
+CClientDataModelBridge::~CClientDataModelBridge()
+{
+}
+
+CUICDMSlideHandle CClientDataModelBridge::CreateNonMasterSlide(CUICDMSlideHandle inMasterSlide,
+ Q3DStudio::CId inGuid,
+ const Q3DStudio::CString &inName)
+{
+ CUICDMInstanceHandle theInstance = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(theInstance, m_SlideItem.m_Instance);
+ m_DataCore->SetInstancePropertyValue(theInstance, m_SlideItem.m_ComponentId,
+ GuidToLong4(inGuid));
+ SetName(theInstance, inName);
+ CUICDMSlideHandle theSlide = m_SlideCore->CreateSlide(theInstance);
+ m_SlideCore->DeriveSlide(theSlide, inMasterSlide);
+ return theSlide;
+}
+
+// Get the Scene or Component Asset of inAsset by querying the Parent
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetSceneOrComponentInstance(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (IsSceneInstance(inInstance) || IsComponentInstance(inInstance))
+ return inInstance;
+
+ if (!IsImageInstance(inInstance)) {
+ return GetSceneOrComponentInstance(GetParentInstance(inInstance));
+ } else {
+ // Special case for Image because Image is a property of Material. Find which Material uses
+ // this image.
+ // This portion of code may never get executed though, but just in case...
+ UICDM::CUICDMInstanceHandle theParentInstance;
+ UICDM::CUICDMPropertyHandle theProperty;
+ if (!GetMaterialFromImageInstance(inInstance, theParentInstance, theProperty)) {
+ GetLayerFromImageProbeInstance(inInstance, theParentInstance, theProperty);
+ }
+ GetSceneOrComponentInstance(theParentInstance);
+ }
+
+ // Something is really wrong if we reach here.... Probably the Graph is not setup correctly
+ ASSERT(0);
+ return 0;
+}
+
+CUICDMSlideGraphHandle
+CClientDataModelBridge::GetOrCreateGraph(UICDM::CUICDMInstanceHandle inInstance)
+{
+ UICDM::CUICDMInstanceHandle theSceneComponentInstance = GetSceneOrComponentInstance(inInstance);
+ Q3DStudio::CId theGuid = GetGUID(theSceneComponentInstance);
+ CUICDMInstanceHandle existing = GetInstanceByGUIDDerivedFrom(
+ GuidToLong4(theGuid), m_SlideItem.m_Instance, m_SlideItem.m_ComponentId);
+ if (existing.Valid()) {
+ // There is an implicit assumption here that the slide graph is one level deep, i.e. only
+ // the
+ // root has children.
+ CUICDMSlideHandle theSlide = m_SlideCore->GetSlideByInstance(existing);
+ if (m_SlideCore->GetParentSlide(theSlide).Valid())
+ theSlide = m_SlideCore->GetParentSlide(theSlide);
+ return m_SlideGraphCore->GetSlideGraph(theSlide);
+ }
+ ClearCache();
+ CUICDMInstanceHandle rootInstance = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(rootInstance, m_SlideItem.m_Instance);
+ m_DataCore->SetInstancePropertyValue(rootInstance, m_SlideItem.m_ComponentId,
+ GuidToLong4(theGuid));
+ SetName(rootInstance, Q3DStudio::CString::fromQString(QObject::tr("Master Slide")));
+ CUICDMSlideHandle masterSlide = m_SlideCore->CreateSlide(rootInstance);
+ CUICDMSlideGraphHandle retval(m_SlideGraphCore->CreateSlideGraph(masterSlide));
+ CUICDMSlideHandle theSlide1Handle =
+ CreateNonMasterSlide(masterSlide, theGuid, Q3DStudio::CString::fromQString(QObject::tr("Slide1")));
+
+ // always activate slide 1 on create
+ m_SlideGraphCore->SetGraphActiveSlide(retval, theSlide1Handle);
+
+ return retval;
+}
+
+CUICDMSlideHandle
+CClientDataModelBridge::GetOrCreateGraphRoot(UICDM::CUICDMInstanceHandle inInstance)
+{
+ return m_SlideGraphCore->GetGraphRoot(GetOrCreateGraph(inInstance));
+}
+
+CUICDMSlideHandle GetSlideByIndex(CUICDMSlideGraphHandle inGraph, int inIndex,
+ ISlideCore &inSlideCore, ISlideGraphCore &inSlideGraphCore)
+{
+ CUICDMSlideHandle theRoot = inSlideGraphCore.GetGraphRoot(inGraph);
+ if (inIndex == 0)
+ return theRoot;
+ --inIndex;
+ TSlideHandleList theSlides;
+ inSlideCore.GetChildSlides(theRoot, theSlides);
+ return theSlides.at(inIndex);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::CreateAssetInstance(Q3DStudio::CId &inId,
+ EStudioObjectType inObjectType)
+{
+ CUICDMInstanceHandle existing = GetInstanceByGUID(inId);
+ if (existing.Valid())
+ return existing;
+
+ ClearCache();
+ CUICDMInstanceHandle theNewInstance = m_DataCore->CreateInstance();
+ switch (inObjectType) {
+ case OBJTYPE_MATERIAL:
+ m_DataCore->DeriveInstance(theNewInstance, m_DefaultMaterial.m_Instance);
+ break;
+ case OBJTYPE_MODEL:
+ m_DataCore->DeriveInstance(theNewInstance, m_Model.m_Instance);
+ break;
+ case OBJTYPE_TEXT:
+ m_DataCore->DeriveInstance(theNewInstance, m_Text.m_Instance);
+ break;
+ case OBJTYPE_GROUP:
+ m_DataCore->DeriveInstance(theNewInstance, m_Group.m_Instance);
+ break;
+ case OBJTYPE_COMPONENT:
+ m_DataCore->DeriveInstance(theNewInstance, m_Component.m_Instance);
+ break;
+ case OBJTYPE_IMAGE:
+ m_DataCore->DeriveInstance(theNewInstance, m_SceneImage.m_Instance);
+ break;
+ case OBJTYPE_LIGHT:
+ m_DataCore->DeriveInstance(theNewInstance, m_Light.m_Instance);
+ break;
+ case OBJTYPE_CAMERA:
+ m_DataCore->DeriveInstance(theNewInstance, m_Camera.m_Instance);
+ break;
+ case OBJTYPE_LAYER:
+ m_DataCore->DeriveInstance(theNewInstance, m_Layer.m_Instance);
+ break;
+ case OBJTYPE_BEHAVIOR:
+ m_DataCore->DeriveInstance(theNewInstance, m_Behavior.m_Instance);
+ break;
+ case OBJTYPE_SCENE:
+ m_DataCore->DeriveInstance(theNewInstance, m_Scene.m_Instance);
+ break;
+ case OBJTYPE_EFFECT:
+ m_DataCore->DeriveInstance(theNewInstance, m_Effect.m_Instance);
+ break;
+ case OBJTYPE_ALIAS:
+ m_DataCore->DeriveInstance(theNewInstance, m_Alias.m_Instance);
+ break;
+ case OBJTYPE_LIGHTMAPS:
+ m_DataCore->DeriveInstance(theNewInstance, m_Lightmaps.m_Instance);
+ break;
+ }
+
+ m_DataCore->SetInstancePropertyValue(theNewInstance, GetObjectDefinitions().m_Guided.m_GuidProp,
+ GuidToLong4(inId));
+
+#if _DEBUG
+ if (inObjectType == OBJTYPE_MATERIAL)
+ ASSERT(GetMaterialInstanceByGUID(inId).Valid());
+ else if (inObjectType == OBJTYPE_MODEL)
+ ASSERT(GetModelInstanceByGUID(inId).Valid());
+ else
+ ASSERT(GetInstanceByGUID(inId).Valid());
+#endif
+
+ return theNewInstance;
+}
+
+UICDM::CUICDMInstanceHandle CClientDataModelBridge::GetSlideInstance()
+{
+ return m_SlideItem.m_Instance;
+}
+
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetSlideComponentIdProperty()
+{
+ return m_SlideItem.m_ComponentId;
+}
+
+UICDM::CUICDMInstanceHandle CClientDataModelBridge::GetActionInstance()
+{
+ return m_ActionItem.m_Instance;
+}
+
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetActionEyeball()
+{
+ return m_ActionItem.m_ActionEyeball;
+}
+
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetImportId()
+{
+ return m_SceneAsset.m_ImportId;
+}
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetNameProperty()
+{
+ return GetObjectDefinitions().m_Named.m_NameProp;
+}
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetIdProperty()
+{
+ return GetObjectDefinitions().m_Guided.m_GuidProp;
+}
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetTypeProperty()
+{
+ return GetObjectDefinitions().m_Typed.m_TypeProp;
+}
+UICDM::CUICDMPropertyHandle CClientDataModelBridge::GetSourcePathProperty()
+{
+ return m_SceneAsset.m_SourcePath;
+}
+
+bool CClientDataModelBridge::IsInternalProperty(const TCharStr &inPropertyName) const
+{
+ return (inPropertyName == L"name" || inPropertyName == L"importid" || inPropertyName == L"type"
+ || inPropertyName == L"id" || inPropertyName == L"componentid"
+ || inPropertyName == L"rotationorder" || inPropertyName == L"orientation"
+ || inPropertyName == L"starttime" || inPropertyName == L"endtime"
+ || inPropertyName == L"eyeball" || inPropertyName == L"shy"
+ || inPropertyName == L"locked" || inPropertyName == L"timebarcolor"
+ || inPropertyName == L"timebartext");
+}
+
+// Find the owning component. Note: inInstanceHandle may or may not have a client representation,
+// e.g. Images do not, so we can't use CAsset::GetControllingComponent.
+// Returns NULL if can't find one or its in the scene.
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetOwningComponentInstance(UICDM::CUICDMInstanceHandle inInstanceHandle)
+{
+ int theSlideIndex;
+ return GetOwningComponentInstance(inInstanceHandle, theSlideIndex);
+}
+
+// Find the owning component. Note: inInstanceHandle may or may not have a client representation,
+// e.g. Images do not, so we can't use CAsset::GetControllingComponent.
+// Returns NULL if can't find one or its in the scene.
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetOwningComponentInstance(UICDM::CUICDMInstanceHandle inInstanceHandle,
+ int &outSlideIndex)
+{
+ if (!inInstanceHandle.Valid())
+ return {};
+
+ // get the slide this instance is in
+ CUICDMSlideHandle theSlideHandle =
+ m_SlideGraphCore->GetAssociatedGraph(inInstanceHandle).second;
+ if (!theSlideHandle.Valid())
+ return {};
+
+ return GetOwningComponentInstance(theSlideHandle, outSlideIndex);
+}
+
+// Find the owning component of the Slide Handle
+// Returns NULL if can't find one.
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetOwningComponentInstance(UICDM::CUICDMSlideHandle inSlideHandle,
+ int &outSlideIndex)
+{
+ SLong4 theComponentGuid = GetComponentGuid(inSlideHandle);
+ if (!GuidValid(theComponentGuid))
+ return {};
+ Q3DStudio::CId theId(theComponentGuid.m_Longs[0], theComponentGuid.m_Longs[1],
+ theComponentGuid.m_Longs[2], theComponentGuid.m_Longs[3]);
+
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ outSlideIndex = theSlideSystem->GetSlideIndex(inSlideHandle);
+ return GetInstanceByGUID(theComponentGuid);
+}
+
+// Find the owning component of the Slide Handle
+// Returns NULL if can't find one.
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetOwningComponentInstance(UICDM::CUICDMSlideHandle inSlideHandle)
+{
+ int theSlideIndex;
+ return GetOwningComponentInstance(inSlideHandle, theSlideIndex);
+}
+
+// Find the component Guid of the Slide Handle
+SLong4 CClientDataModelBridge::GetComponentGuid(UICDM::CUICDMSlideHandle inSlideHandle)
+{
+ UICDM::SLong4 theComponentGuid;
+
+ // get the master slide (because only master knows which component instance)
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ CUICDMSlideHandle theMasterSlideHandle = theSlideSystem->GetMasterSlide(inSlideHandle);
+ if (!theMasterSlideHandle.Valid())
+ return theComponentGuid;
+
+ CUICDMInstanceHandle theOwningComponentInstance =
+ theSlideSystem->GetSlideInstance(theMasterSlideHandle);
+ if (!theOwningComponentInstance.Valid())
+ return theComponentGuid;
+
+ SValue theValue;
+ if (m_DataCore->GetInstancePropertyValue(theOwningComponentInstance, m_SlideItem.m_ComponentId,
+ theValue))
+ theComponentGuid = theValue.getData<SLong4>();
+
+ return theComponentGuid;
+}
+
+//==============================================================================
+/**
+ * Helper method to check whether this asset is active.
+ * An asset is active if it meets the following criteria
+ * 1. It's eyeball is on
+ * 2. the current time falls within it's timebar
+ */
+bool CClientDataModelBridge::IsActive(UICDM::CUICDMInstanceHandle inInstanceHandle,
+ long inCurrentTime)
+{
+ // Check the eyeball
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ UICDM::SValue theValue;
+ thePropertySystem->GetInstancePropertyValue(inInstanceHandle, GetSceneAsset().m_Eyeball,
+ theValue);
+ if (!UICDM::get<bool>(theValue))
+ return false;
+
+ // check current time is within the timebar
+ thePropertySystem->GetInstancePropertyValue(inInstanceHandle, GetSceneAsset().m_StartTime,
+ theValue);
+ long theStartTime = UICDM::get<qt3ds::QT3DSI32>(theValue);
+ thePropertySystem->GetInstancePropertyValue(inInstanceHandle, GetSceneAsset().m_EndTime,
+ theValue);
+ long theEndTime = UICDM::get<qt3ds::QT3DSI32>(theValue);
+ if (inCurrentTime < theStartTime || inCurrentTime > theEndTime)
+ return false;
+
+ // has to be active if all the above succeed
+ return true;
+}
+
+//==============================================================================
+/**
+ * Get the active slide index of this component (or scene)
+ * @param inAsset the controlling component (component or scene)
+ */
+UICDM::CUICDMSlideHandle
+CClientDataModelBridge::GetComponentActiveSlide(UICDM::CUICDMInstanceHandle inComponent)
+{
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ Q3DStudio::CId theId = GetGUID(inComponent);
+ CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theId));
+ return theSlideSystem->GetActiveSlide(theMasterSlide);
+}
+
+UICDM::CUICDMSlideHandle
+CClientDataModelBridge::GetComponentSlide(UICDM::CUICDMInstanceHandle inComponent, long inIndex)
+{
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ Q3DStudio::CId theId = GetGUID(inComponent);
+ CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theId));
+ return theSlideSystem->GetSlideByIndex(theMasterSlide, inIndex);
+}
+
+//
+void CClientDataModelBridge::SetName(UICDM::CUICDMInstanceHandle inInstanceHandle,
+ const Q3DStudio::CString &inName)
+{
+ TDataStrPtr theName(new CDataStr(inName));
+ CUICDMSlideHandle theAssociatedSlide =
+ m_Doc->GetStudioSystem()->GetFullSystem()->GetSlideSystem()->GetAssociatedSlide(
+ inInstanceHandle);
+ if (theAssociatedSlide.Valid())
+ m_Doc->GetStudioSystem()->GetFullSystem()->GetSlideCore()->ForceSetInstancePropertyValue(
+ theAssociatedSlide, inInstanceHandle, GetNameProperty(), theName);
+ else {
+ UICDM::TDataCorePtr theDataCore =
+ m_Doc->GetStudioSystem()->GetFullSystem()->GetCoreSystem()->GetDataCore();
+ theDataCore->SetInstancePropertyValue(inInstanceHandle, GetNameProperty(), theName);
+ }
+}
+
+Q3DStudio::CString CClientDataModelBridge::GetName(UICDM::CUICDMInstanceHandle inInstanceHandle)
+{
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ TDataStrPtr theString;
+ if (m_Doc->GetStudioSystem()->IsInstance(inInstanceHandle)) {
+ SValue theValue;
+ if (thePropertySystem->GetInstancePropertyValue(inInstanceHandle, GetNameProperty(),
+ theValue)
+ && GetValueType(theValue) == DataModelDataType::String)
+ theString = UICDM::get<TDataStrPtr>(theValue);
+ }
+ return (theString) ? Q3DStudio::CString(theString->GetData()) : "";
+}
+
+bool CClientDataModelBridge::IsActiveComponent(UICDM::CUICDMInstanceHandle inInstance)
+{
+ using namespace UICDM;
+ using namespace Q3DStudio;
+ CDoc &theDoc(*m_Doc);
+ CUICDMInstanceHandle theInstance = inInstance;
+ CUICDMSlideHandle theSlide = theDoc.GetActiveSlide();
+ SLong4 theGuid = GetComponentGuid(theSlide);
+ CId theActiveComponentId(theGuid.m_Longs[0], theGuid.m_Longs[1], theGuid.m_Longs[2],
+ theGuid.m_Longs[3]);
+ CId theInstanceId = GetGUID(theInstance);
+ return theActiveComponentId == theInstanceId;
+}
+
+// Helper for getting the type as a wstring... returns "" if it can't figure things out
+std::wstring GetInstanceType(IPropertySystem *inPropertySystem, CUICDMInstanceHandle inInstance)
+{
+ std::wstring theReturn(L"");
+ try {
+ CUICDMPropertyHandle theProperty =
+ inPropertySystem->GetAggregateInstancePropertyByName(inInstance, L"type");
+ SValue theTypeValue;
+ if (theProperty
+ && inPropertySystem->GetInstancePropertyValue(inInstance, theProperty, theTypeValue)) {
+ theReturn.assign(UICDM::get<TDataStrPtr>(theTypeValue)->GetData());
+ }
+ } catch (...) {
+ theReturn.assign(L"");
+ }
+
+ return theReturn;
+}
+
+// Find which material that uses this image instance
+bool CClientDataModelBridge::GetMaterialFromImageInstance(
+ UICDM::CUICDMInstanceHandle inInstance, UICDM::CUICDMInstanceHandle &outMaterialInstance,
+ UICDM::CUICDMPropertyHandle &outProperty)
+{
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ SLong4 theDeletedImageLong4 =
+ GetNamedInstancePropertyValue<SLong4>(thePropertySystem, inInstance, L"id");
+
+ TInstanceHandleList theInstances;
+ m_DataCore->GetInstancesDerivedFrom(
+ theInstances, m_DefaultMaterial.m_Instance); // Get all default material instances
+ size_t theInstanceCount = theInstances.size();
+ for (size_t theInstanceIndex = 0; theInstanceIndex < theInstanceCount; ++theInstanceIndex) {
+ CUICDMInstanceHandle theInstance = theInstances[theInstanceIndex];
+ std::wstring theWideTypeString(GetInstanceType(thePropertySystem, theInstance));
+ if (theWideTypeString == L"Material") {
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(theInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount;
+ ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(theInstance, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ SLong4 theLong4PropertyValue = GetSpecificInstancePropertyValue<SLong4>(
+ thePropertySystem, theInstance, theProperty);
+ if (theDeletedImageLong4 == theLong4PropertyValue) {
+ outMaterialInstance = theInstance;
+ outProperty = theProperty;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ m_DataCore->GetInstancesDerivedFrom(
+ theInstances, m_CustomMaterial.m_Instance); // Get all custom material instances
+ theInstanceCount = theInstances.size();
+ for (size_t theInstanceIndex = 0; theInstanceIndex < theInstanceCount; ++theInstanceIndex) {
+ CUICDMInstanceHandle theInstance = theInstances[theInstanceIndex];
+ std::wstring theWideTypeString(GetInstanceType(thePropertySystem, theInstance));
+ if (theWideTypeString == L"CustomMaterial") {
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(theInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount;
+ ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(theInstance, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ SLong4 theLong4PropertyValue = GetSpecificInstancePropertyValue<SLong4>(
+ thePropertySystem, theInstance, theProperty);
+ if (theDeletedImageLong4 == theLong4PropertyValue) {
+ outMaterialInstance = theInstance;
+ outProperty = theProperty;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool CClientDataModelBridge::GetLayerFromImageProbeInstance(
+ UICDM::CUICDMInstanceHandle inInstance, UICDM::CUICDMInstanceHandle &outLayerInstance,
+ UICDM::CUICDMPropertyHandle &outProperty)
+{
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ SLong4 theDeletedImageLong4 =
+ GetNamedInstancePropertyValue<SLong4>(thePropertySystem, inInstance, L"id");
+
+ TInstanceHandleList theInstances;
+ m_DataCore->GetInstancesDerivedFrom(
+ theInstances, this->m_Layer.m_Instance); // Get all default Layer instances
+ size_t theInstanceCount = theInstances.size();
+
+ for (size_t theInstanceIndex = 0; theInstanceIndex < theInstanceCount; ++theInstanceIndex) {
+ CUICDMInstanceHandle theInstance = theInstances[theInstanceIndex];
+ std::wstring theWideTypeString(GetInstanceType(thePropertySystem, theInstance));
+ if (theWideTypeString == L"Layer") {
+ // Layer should have only one image property, which is the light probe, but this is a
+ // little more
+ // generic should anyone ever add more in the future.
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(theInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount;
+ ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(theInstance, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ SLong4 theLong4PropertyValue = GetSpecificInstancePropertyValue<SLong4>(
+ thePropertySystem, theInstance, theProperty);
+ if (theDeletedImageLong4 == theLong4PropertyValue) {
+ outLayerInstance = theInstance;
+ outProperty = theProperty;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// enable caching between BeginRender() to EndRender()
+// assumption: instances (CSimpleDataCore.m_Objects) remain constant between BeginRender to
+// EndRender
+void CClientDataModelBridge::BeginRender()
+{
+ ClearCache();
+}
+
+void CClientDataModelBridge::EndRender()
+{
+ ClearCache();
+}
+
+void CClientDataModelBridge::ClearCache()
+{
+ m_CacheImageInstances.clear();
+ m_CacheMaterialInstances.clear();
+ m_CacheModelInstances.clear();
+}
+
+// requirement: inInstance must be derived from instance that has Guid property!
+bool CClientDataModelBridge::DerivedGuidMatches(IDataCore &inDataCore,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SLong4 inGuid)
+{
+ SValue theLong4;
+ if (inDataCore.GetInstancePropertyValue(inInstance, inProperty, theLong4)
+ && Equals(inGuid, theLong4.toOldSkool())) {
+ return true;
+ }
+ return false;
+}
+
+UICDM::CUICDMInstanceHandle CClientDataModelBridge::GetInstanceByGUID(const Q3DStudio::CId &inId)
+{
+ return GetInstanceByGUID(GuidToLong4(inId));
+}
+
+void CClientDataModelBridge::ClearInstanceGUIDCache(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty)
+{
+ if (inProperty == GetObjectDefinitions().m_Guided.m_GuidProp) {
+ TInstanceToGUIDHash::iterator theEntry(m_CachedInstanceToGUIDHash.find(inInstance));
+ if (theEntry != m_CachedInstanceToGUIDHash.end()) {
+ m_CachedGUIDToInstancesHash.erase(theEntry->second);
+ m_CachedInstanceToGUIDHash.erase(theEntry);
+ }
+ }
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetInstanceByGUID(SLong4 inLong4)
+{
+ if (inLong4 == SLong4(0, 0, 0, 0))
+ return 0;
+ if (m_InstanceCachePropertyChangedConnection == NULL && m_Doc->GetStudioSystem()
+ && m_Doc->GetStudioSystem()->GetFullSystem()) {
+ IStudioFullSystemSignalProvider *theProvider(
+ m_Doc->GetStudioSystem()->GetFullSystem()->GetSignalProvider());
+ m_InstanceCachePropertyChangedConnection = theProvider->ConnectInstancePropertyValue(
+ std::bind(&CClientDataModelBridge::ClearInstanceGUIDCache, this, std::placeholders::_1,
+ std::placeholders::_2));
+ m_InstanceCacheInstanceDeletedConnection = theProvider->ConnectInstanceDeleted(
+ std::bind(&CClientDataModelBridge::ClearInstanceGUIDCache, this, std::placeholders::_1,
+ GetObjectDefinitions().m_Guided.m_GuidProp));
+ }
+ TGUIDInstanceHash::iterator theEntry(m_CachedGUIDToInstancesHash.find(inLong4));
+ if (theEntry != m_CachedGUIDToInstancesHash.end()) {
+ if (m_DataCore->IsInstance(theEntry->second))
+ return theEntry->second;
+ else {
+ m_CachedInstanceToGUIDHash.erase(theEntry->second);
+ m_CachedGUIDToInstancesHash.erase(theEntry);
+ }
+ }
+ CUICDMInstanceHandle retval = MaybeCacheGetInstanceByGUIDDerivedFrom(
+ inLong4, m_CachedGuidInstances, GetObjectDefinitions().m_Guided.m_Instance,
+ GetObjectDefinitions().m_Guided.m_GuidProp);
+ m_CachedGUIDToInstancesHash.insert(std::make_pair(inLong4, retval));
+ m_CachedInstanceToGUIDHash.insert(std::make_pair(retval, inLong4));
+ return retval;
+}
+
+UICDM::SLong4 CClientDataModelBridge::GetInstanceGUID(UICDM::CUICDMInstanceHandle inInstance)
+{
+ std::pair<TInstanceToGUIDHash::iterator, bool> theEntry(
+ m_CachedInstanceToGUIDHash.insert(std::make_pair(inInstance, SLong4())));
+ if (theEntry.second) {
+ Q3DStudio::CId theInstanceGuid;
+ theInstanceGuid.Generate();
+
+ const Q3DStudio::TGUIDPacked thePackedInstanceGuid(theInstanceGuid);
+ SLong4 theInstanceLong4;
+ theInstanceLong4.m_Longs[0] = thePackedInstanceGuid.Data1;
+ theInstanceLong4.m_Longs[1] = thePackedInstanceGuid.Data2;
+ theInstanceLong4.m_Longs[2] = thePackedInstanceGuid.Data3;
+ theInstanceLong4.m_Longs[3] = thePackedInstanceGuid.Data4;
+ m_DataCore->SetInstancePropertyValue(inInstance, GetObjectDefinitions().m_Guided.m_GuidProp,
+ SValue(theInstanceLong4));
+ m_CachedGUIDToInstancesHash.insert(std::make_pair(theInstanceLong4, inInstance));
+ m_CachedInstanceToGUIDHash.insert(std::make_pair(inInstance, theInstanceLong4));
+ return theInstanceLong4;
+ }
+ return theEntry.first->second;
+}
+
+void CClientDataModelBridge::SetInstanceGUID(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::SLong4 inGuid)
+{
+ m_DataCore->SetInstancePropertyValue(inInstance, GetObjectDefinitions().m_Guided.m_GuidProp,
+ SValue(inGuid));
+ m_CachedGUIDToInstancesHash.clear();
+ m_CachedInstanceToGUIDHash.clear();
+ erase_if(m_CachedGuidInstances,
+ std::bind(std::equal_to<UICDM::CUICDMInstanceHandle>(), inInstance,
+ std::placeholders::_1));
+ erase_if(m_CacheImageInstances,
+ std::bind(std::equal_to<UICDM::CUICDMInstanceHandle>(), inInstance,
+ std::placeholders::_1));
+ erase_if(m_CacheMaterialInstances,
+ std::bind(std::equal_to<UICDM::CUICDMInstanceHandle>(), inInstance,
+ std::placeholders::_1));
+ erase_if(m_CacheModelInstances,
+ std::bind(std::equal_to<UICDM::CUICDMInstanceHandle>(), inInstance,
+ std::placeholders::_1));
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetImageInstanceByGUID(const Q3DStudio::CId &inId)
+{
+ return GetImageInstanceByGUID(GuidToLong4(inId));
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetImageInstanceByGUID(SLong4 inLong4)
+{
+ if (inLong4 == SLong4(0, 0, 0, 0)) // invalid GUID
+ return 0;
+ return GetInstanceByGUID(inLong4);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetMaterialInstanceByGUID(const Q3DStudio::CId &inId)
+{
+ return GetMaterialInstanceByGUID(GuidToLong4(inId));
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetMaterialInstanceByGUID(SLong4 inLong4)
+{
+ return MaybeCacheGetInstanceByGUIDDerivedFrom(inLong4, m_CacheMaterialInstances,
+ m_DefaultMaterial.m_Instance,
+ GetObjectDefinitions().m_Guided.m_GuidProp);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetModelInstanceByGUID(const Q3DStudio::CId &inId)
+{
+ return GetModelInstanceByGUID(GuidToLong4(inId));
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetModelInstanceByGUID(SLong4 inLong4)
+{
+ return MaybeCacheGetInstanceByGUIDDerivedFrom(inLong4, m_CacheModelInstances,
+ m_Model.m_Instance,
+ GetObjectDefinitions().m_Guided.m_GuidProp);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetComponentInstanceByGUID(const Q3DStudio::CId &inId)
+{
+ return GetComponentInstanceByGUID(GuidToLong4(inId));
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetComponentInstanceByGUID(SLong4 inLong4)
+{
+ return GetInstanceByGUIDDerivedFrom(inLong4, m_SlideItem.m_Instance, m_SlideItem.m_ComponentId);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::MaybeCacheGetInstanceByGUIDDerivedFrom(
+ SLong4 inLong4, TInstanceHandleList &ioCacheInstances, CUICDMInstanceHandle inParentHandle,
+ CUICDMPropertyHandle inProperty)
+{
+ if (m_CacheEnabled) {
+ if (ioCacheInstances.empty())
+ m_DataCore->GetInstancesDerivedFrom(ioCacheInstances, inParentHandle); // build cache
+ return GetInstanceByGUIDDerivedFrom(inLong4, ioCacheInstances, inProperty);
+ } else
+ return GetInstanceByGUIDDerivedFrom(inLong4, inParentHandle, inProperty);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetInstanceByGUIDDerivedFrom(
+ SLong4 inLong4, CUICDMInstanceHandle inParentHandle, CUICDMPropertyHandle inProperty)
+{
+ // Run through all the instances derived from parent, and if a guid matches return that
+ // instance.
+ TInstanceHandleList instances;
+ m_DataCore->GetInstancesDerivedFrom(instances, inParentHandle);
+ return GetInstanceByGUIDDerivedFrom(inLong4, instances, inProperty);
+}
+
+CUICDMInstanceHandle CClientDataModelBridge::GetInstanceByGUIDDerivedFrom(
+ SLong4 inLong4, const TInstanceHandleList &instances, CUICDMPropertyHandle inProperty)
+{
+ // Run through all the instances derived from parent, and if a guid matches return that
+ // instance.
+ TInstanceHandleList::const_iterator existing =
+ find_if(instances.begin(), instances.end(),
+ std::bind(CClientDataModelBridge::DerivedGuidMatches, std::ref(*m_DataCore),
+ std::placeholders::_1, inProperty, inLong4));
+ if (existing != instances.end())
+ return *existing;
+ return 0;
+}
+
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetInstance(UICDM::CUICDMInstanceHandle inRoot,
+ const UICDM::SObjectRefType &inValue)
+{
+ using namespace UICDM;
+ using namespace boost;
+ switch (inValue.GetReferenceType()) {
+ case ObjectReferenceType::Absolute:
+ return GetInstanceByGUID(get<SLong4>(inValue.m_Value));
+ case ObjectReferenceType::Relative: {
+ Q3DStudio::CString thePath(UICDM::get<UICDM::TDataStrPtr>(inValue.m_Value)->GetData());
+ IObjectReferenceHelper *theObjRefHelper = m_Doc->GetDataModelObjectReferenceHelper();
+ if (theObjRefHelper) {
+ bool theFullResolvedFlag;
+ CRelativePathTools::EPathType thePathType;
+ return CRelativePathTools::FindAssetInstanceByObjectPath(
+ m_Doc, inRoot, thePath, thePathType, theFullResolvedFlag, theObjRefHelper);
+ }
+ } break;
+ }
+ return 0;
+}
+// Get the instance handle from the info stored in inValue
+// inValue can be either of type long and TDataStrPtr only
+// if it's long, it's the instance handle stored as long
+// if it's long4, it's the GUID
+// if it's a string, it's a path and so we need to decode the path to find the asset
+UICDM::CUICDMInstanceHandle CClientDataModelBridge::GetInstance(UICDM::CUICDMInstanceHandle inRoot,
+ const UICDM::SValue &inValue)
+{
+ using namespace UICDM;
+ using namespace boost;
+ return GetInstance(inRoot, ConvertToObjectRef(inValue));
+}
+
+std::pair<UICDM::CUICDMInstanceHandle, UICDM::SLong4>
+CClientDataModelBridge::CreateImageInstance(UICDM::CUICDMInstanceHandle inSourceInstance,
+ CUICDMPropertyHandle inSlot,
+ CUICDMSlideHandle inUICDMSlide)
+{
+ CUICDMInstanceHandle theNewInstance =
+ m_Doc->GetStudioSystem()
+ ->GetPropertySystem()
+ ->CreateInstance(); // this should call CDataCoreProducer::CreateInstance(). If there is
+ // Consumer, the action can be undo
+ m_DataCore->DeriveInstance(theNewInstance, m_SceneImage.m_Instance);
+
+ // Set non-per-slide information *before* associating with slide
+
+ SValue theName;
+ m_DataCore->GetInstancePropertyValue(inSourceInstance, GetNameProperty(), theName);
+ m_DataCore->SetInstancePropertyValue(theNewInstance, GetNameProperty(), theName);
+
+ Q3DStudio::CId theInstanceGuid;
+ theInstanceGuid.Generate();
+
+ const Q3DStudio::TGUIDPacked thePackedInstanceGuid(theInstanceGuid);
+ SLong4 theInstanceLong4;
+ theInstanceLong4.m_Longs[0] = thePackedInstanceGuid.Data1;
+ theInstanceLong4.m_Longs[1] = thePackedInstanceGuid.Data2;
+ theInstanceLong4.m_Longs[2] = thePackedInstanceGuid.Data3;
+ theInstanceLong4.m_Longs[3] = thePackedInstanceGuid.Data4;
+ m_DataCore->SetInstancePropertyValue(theNewInstance, GetObjectDefinitions().m_Guided.m_GuidProp,
+ SValue(theInstanceLong4));
+
+ // Library objects does not need to be associated with any slide.
+ if (inUICDMSlide.Valid())
+ m_Doc->GetStudioSystem()->GetSlideSystem()->AssociateInstanceWithSlide(inUICDMSlide,
+ theNewInstance);
+
+ if (m_DefaultMaterial.m_SpecularReflection.m_Property
+ == inSlot) { // Special case by spec, new "Specular Reflection" slot images hard set to
+ // mapping mode "Environment"
+ m_DataCore->SetInstancePropertyValue(theNewInstance, m_SceneImage.m_TextureMapping,
+ TDataStrPtr(new CDataStr(L"Environmental Mapping")));
+ } else if (m_Layer.m_LightProbe.m_Property == inSlot
+ || m_Layer.m_LightProbe2.m_Property == inSlot) {
+ m_DataCore->SetInstancePropertyValue(theNewInstance, m_SceneImage.m_TextureMapping,
+ TDataStrPtr(new CDataStr(L"Light Probe")));
+ } else if (m_MaterialBase.m_IblProbe.m_Property == inSlot) {
+ m_DataCore->SetInstancePropertyValue(theNewInstance, m_SceneImage.m_TextureMapping,
+ TDataStrPtr(new CDataStr(L"IBL Override")));
+ }
+
+ return std::make_pair(theNewInstance, theInstanceLong4);
+}
+
+Q3DStudio::CId CClientDataModelBridge::GetId(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty) const
+{
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ SValue theSourceValue;
+ if (m_DataCore->IsInstance(inInstance)
+ && thePropertySystem->HasAggregateInstanceProperty(
+ inInstance, inProperty) // check if the property exists before querying the value
+ && thePropertySystem->GetInstancePropertyValue(
+ inInstance, inProperty,
+ theSourceValue)) // this function may throw error if the property doesn't exist
+ {
+ SLong4 theLong4 = UICDM::get<SLong4>(theSourceValue);
+ return Q3DStudio::CId(theLong4.m_Longs[0], theLong4.m_Longs[1], theLong4.m_Longs[2],
+ theLong4.m_Longs[3]);
+ }
+ return Q3DStudio::CId();
+}
+
+// Check whether this instance is inside the current active component
+bool CClientDataModelBridge::IsInActiveComponent(UICDM::CUICDMInstanceHandle inInstance)
+{
+ UICDM::CUICDMInstanceHandle theActiveRoot = m_Doc->GetActiveRootInstance();
+ return (theActiveRoot == GetOwningComponentInstance(inInstance));
+}
+
+// Check whether inInstance is inside inComponentInstance
+bool CClientDataModelBridge::IsInComponent(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inComponentInstance)
+{
+ return (GetOwningComponentInstance(inInstance) == inComponentInstance);
+}
+
+//==============================================================================
+/**
+ * Get the component that this instance is a member of.
+ * The component is the independent group or the Scene. inIsFirstCall is used
+ * to ignore the first independent group in order to get it's parent.
+ * @param inIsFirstCall true if the child is to be ignored as being a component.
+ * @return the parent component, or this if the parent is NULL.
+ */
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetParentComponent(UICDM::CUICDMInstanceHandle inInstance,
+ bool inIsFirstCall /*= true*/)
+{
+ if (!inIsFirstCall && (IsSceneInstance(inInstance) || IsComponentInstance(inInstance)))
+ return inInstance;
+
+ UICDM::CUICDMInstanceHandle theParentInstance = GetParentInstance(inInstance);
+ if (theParentInstance.Valid())
+ return GetParentComponent(theParentInstance, false);
+ else
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Get a unique, non-conflicting name for a child.
+ * This will stip off all trailing numbers, find the base name then find a
+ * non-used index from the base name.
+ * If nothing already exists at inDesiredName then no index will be added.
+ * @param inDesiredName the desired base name for the object.
+ * @return a unique name that no other child has.
+ */
+Q3DStudio::CString
+CClientDataModelBridge::GetUniqueChildName(UICDM::CUICDMInstanceHandle inParent,
+ UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CString inDesiredName)
+{
+ // fyi, if we get abc123, theBaseName gets abc and theBaseIndex gets 123
+
+ Q3DStudio::CString theBaseName = inDesiredName;
+ Q3DStudio::CString theBaseIndex;
+
+ // Strip off all trailing numbers to get the base name
+ if (theBaseName.Length() > 0) {
+ wchar_t theLastChar = static_cast<const wchar_t *>(theBaseName)[theBaseName.Length() - 1];
+ while (theBaseName.Length() > 0 && theLastChar >= '0' && theLastChar <= '9') {
+ // get a wchar_t* so we can index
+ const wchar_t *theBasePtr = theBaseName;
+ // find where the desired character is
+ long theDesiredOffset = theBaseName.Length() - 1;
+ // make a CString of the desired character and concatenate with the existing base index
+ theBaseIndex = Q3DStudio::CString(theBasePtr + theDesiredOffset, 1) + theBaseIndex;
+
+ // take out that last character
+ theBaseName = theBaseName.Extract(0, theBaseName.Length() - 1);
+
+ // get the new last char
+ if (theBaseName.Length() > 0)
+ theLastChar = static_cast<const wchar_t *>(theBaseName)[theBaseName.Length() - 1];
+ }
+ }
+
+ UICDM::CUICDMInstanceHandle theExistingChild = 0;
+ // If there is a base name then use it
+ if (theBaseName.Length() > 0)
+ theExistingChild = GetChildByName(inParent, inDesiredName);
+ else // there is no base name, just set it to a random setting so it'll fall into the while loop
+ theExistingChild = inParent;
+
+ Q3DStudio::CString theUniqueName = inDesiredName;
+
+ if (theExistingChild != 0 && theExistingChild != inInstance) {
+ long theIndex;
+ if (theBaseIndex.Length() != 0)
+ theIndex = atoi(theBaseIndex.GetCharStar());
+ else
+ theIndex = 2;
+
+ // If the name is in use then increment the index until one is found.
+ while (theExistingChild != 0 && theExistingChild != inInstance) {
+ theUniqueName.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(theBaseName), theIndex);
+ ++theIndex;
+ theExistingChild = GetChildByName(inParent, theUniqueName);
+ }
+ }
+
+ return theUniqueName;
+}
+
+bool CClientDataModelBridge::CheckNameUnique(UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CString inDesiredName)
+{
+ UICDM::CUICDMInstanceHandle theExistingChild = 0;
+ if (inDesiredName.Length() > 0)
+ theExistingChild = GetChildByName(GetParentInstance(inInstance), inDesiredName);
+
+ return ((int)theExistingChild == 0 || theExistingChild == inInstance);
+}
+
+//=============================================================================
+/**
+ * Get SourcePath value for this instance
+ */
+Q3DStudio::CString
+CClientDataModelBridge::GetSourcePath(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ if (inInstance.Valid()) {
+ UICDM::SValue theValue;
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ thePropertySystem->GetInstancePropertyValue(inInstance, m_SceneAsset.m_SourcePath,
+ theValue);
+ return UICDM::get<TDataStrPtr>(theValue)->GetData();
+ } else
+ return L"";
+}
+
+//=============================================================================
+/**
+ * Get all instances that are derived from ItemBase Instance.
+ */
+TInstanceHandleList CClientDataModelBridge::GetItemBaseInstances() const
+{
+ TInstanceHandleList theInstances;
+ m_DataCore->GetInstancesDerivedFrom(theInstances, m_SceneAsset.m_Instance);
+ return theInstances;
+}
+
+inline void AddSourcePathToList(std::set<Q3DStudio::CString> &ioSourcePathList,
+ const SValue &inValue)
+{
+ Q3DStudio::CFilePath theSourcePath = UICDM::get<TDataStrPtr>(inValue)->GetData();
+ theSourcePath = theSourcePath.GetPathWithoutIdentifier();
+ if (theSourcePath != L"")
+ ioSourcePathList.insert(theSourcePath);
+}
+
+//=============================================================================
+/**
+ * Get list of values from all instances derived from inParentInstance
+ */
+std::vector<SValue> CClientDataModelBridge::GetValueList(CUICDMInstanceHandle inParentInstance,
+ CUICDMPropertyHandle inProperty,
+ IValueFilter *inFilter) const
+{
+ std::vector<SValue> theValueList;
+ TInstanceHandleList theInstances;
+ m_DataCore->GetInstancesDerivedFrom(theInstances, inParentInstance);
+
+ // Iterate through each instance derived from inParentInstance and get the inProperty property
+ // value.
+ for (TInstanceHandleList::const_iterator theIter = theInstances.begin();
+ theIter != theInstances.end(); ++theIter) {
+ // Skip the parent instance.
+ if (*theIter == inParentInstance)
+ continue;
+
+ GetValueListFromAllSlides(*theIter, inProperty, theValueList, inFilter);
+ }
+
+ return theValueList;
+}
+
+//=============================================================================
+/**
+ * Get list of values from all slides
+ */
+void CClientDataModelBridge::GetValueListFromAllSlides(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ std::vector<SValue> &outValueList,
+ IValueFilter *inFilter) const
+{
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ ISlideCore *theSlideCore = m_Doc->GetStudioSystem()->GetSlideCore();
+
+ // Check if the instance is in master slide and if the property is unlinked.
+ // This will determine how we should query the value.
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetAssociatedSlide(inInstance);
+ if (theSlide.Valid() && theSlideSystem->IsMasterSlide(theSlide)
+ && !theSlideSystem->IsPropertyLinked(inInstance, inProperty)) {
+ // If the instance is in master slide and the property is unlinked, we need to query the
+ // value from each slides
+ size_t theSlideCount =
+ theSlideSystem->GetSlideCount(theSlideSystem->GetAssociatedSlide(inInstance));
+ for (size_t theSlideIndex = 0; theSlideIndex < theSlideCount; ++theSlideIndex) {
+ UICDM::SValue theValue;
+ CUICDMSlideHandle theSpecificSlide =
+ theSlideSystem->GetSlideByIndex(theSlide, theSlideIndex);
+ if (theSlideCore->GetSpecificInstancePropertyValue(theSpecificSlide, inInstance,
+ inProperty, theValue)
+ && (inFilter == NULL || inFilter->KeepValue(inInstance, inProperty, theValue)))
+ outValueList.push_back(theValue);
+ }
+ } else {
+ // Else, we can get the property value
+ UICDM::SValue theValue;
+ if (thePropertySystem->GetInstancePropertyValue(inInstance, inProperty, theValue)
+ && (inFilter == NULL
+ || inFilter->KeepValue(inInstance, inProperty, theValue.toOldSkool())))
+ outValueList.push_back(theValue.toOldSkool());
+ }
+}
+
+// Temporary hack to keep the layer's sourcepath property from setting off the file-not-found
+// warnings. This will go away when we get to the point where we can do better.
+struct SValueListFilter : public IValueFilter
+{
+ const CClientDataModelBridge &m_Bridge;
+ SValueListFilter(const CClientDataModelBridge &bridge)
+ : m_Bridge(bridge)
+ {
+ }
+ bool KeepValue(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle /*inProperty*/,
+ const UICDM::SValue & /*inValue*/) override
+ {
+ return !m_Bridge.IsLayerInstance(inInstance);
+ }
+};
+
+//=============================================================================
+/**
+ * Get SourcePath list from all instances
+ */
+std::set<Q3DStudio::CString> CClientDataModelBridge::GetSourcePathList() const
+{
+ // Get the source path property list
+ SValueListFilter theFilter(*this);
+ std::vector<SValue> theValueList =
+ GetValueList(m_SceneAsset.m_Instance, m_SceneAsset.m_SourcePath, &theFilter);
+
+ // Translate from SValue to Q3DStudio::CString and also remove the identifier
+ std::set<Q3DStudio::CString> theSourcePathList;
+ for (std::vector<SValue>::iterator theIter = theValueList.begin();
+ theIter != theValueList.end(); ++theIter)
+ AddSourcePathToList(theSourcePathList, *theIter);
+
+ return theSourcePathList;
+}
+
+inline void AddStringToList(std::set<Q3DStudio::CString> &ioStringList, const SValue &inValue)
+{
+ Q3DStudio::CString theString = UICDM::get<TDataStrPtr>(inValue)->GetData();
+ if (theString != L"")
+ ioStringList.insert(theString);
+}
+
+//=============================================================================
+/**
+ * Get Font file list from all Text instances
+ */
+std::set<Q3DStudio::CString> CClientDataModelBridge::GetFontFileList() const
+{
+ // Get the font name property list
+ std::vector<SValue> theValueList = GetValueList(m_Text.m_Instance, m_Text.m_Font);
+ std::set<Q3DStudio::CString> theFontNameList;
+ for (std::vector<SValue>::iterator theIter = theValueList.begin();
+ theIter != theValueList.end(); ++theIter)
+ AddStringToList(theFontNameList, *theIter);
+
+ // early return
+ if (theFontNameList.empty())
+ return theFontNameList;
+
+ // Translate the font name to font file
+ std::set<Q3DStudio::CString> theFontFileList;
+ std::vector<std::pair<Q3DStudio::CString, Q3DStudio::CString>> theFontNameFileList;
+ m_Doc->GetProjectFonts(theFontNameFileList);
+ for (std::set<Q3DStudio::CString>::iterator theFontNameIter = theFontNameList.begin();
+ theFontNameIter != theFontNameList.end(); ++theFontNameIter) {
+ // Given the font name, try to get the font file from the list of fonts registered in
+ // Studio.
+ // If the font is not found, it means that we are using missing font file.
+ // Create some non-existing path to inform user that this font is missing.
+ bool theFontFound = false;
+ Q3DStudio::CFilePath theFontFile;
+ for (size_t idx = 0, end = theFontNameFileList.size(); idx < end; ++idx) {
+ if (theFontNameFileList[idx].first == *theFontNameIter) {
+ theFontFound = true;
+ theFontFile = theFontNameFileList[idx].second;
+ break;
+ }
+ }
+ if (!theFontFound) {
+ theFontFile = L"fonts\\File with font name [";
+ theFontFile.append(*theFontNameIter);
+ theFontFile.append(" ]");
+ }
+ theFontFileList.insert(theFontFile);
+ }
+ return theFontFileList;
+}
+
+static void GetDynamicObjecTextures(IDataCore &inDataCore, IPropertySystem &inPropertySystem,
+ CUICDMInstanceHandle inBaseInstance,
+ std::vector<SValue> &outValues,
+ const CClientDataModelBridge &inBridge)
+{
+ std::vector<SValue> &theValueList(outValues);
+ // Get all effect instances
+ TInstanceHandleList theDerivedInstances;
+ inDataCore.GetInstancesDerivedFrom(theDerivedInstances, inBaseInstance);
+
+ // Iterate each effect instance and check if it has Texture property
+ IPropertySystem *thePropertySystem = &inPropertySystem;
+ for (TInstanceHandleList::const_iterator theIter = theDerivedInstances.begin();
+ theIter != theDerivedInstances.end(); ++theIter) {
+ CUICDMInstanceHandle theInstance = *theIter;
+
+ // Skip the parent instance
+ // This works because when we import a custom material, we create a new class that is
+ // derived from the
+ // custom material base instance. We then add all properties and defaults to this new
+ // class. Finally
+ // we derive all scene level instances from this new class. Thus the new class's parent is
+ // the base instance
+ // and the new class is the parent of the scene level instance.
+ TInstanceHandleList theParentList;
+ inDataCore.GetInstanceParents(theInstance, theParentList);
+ if (std::find(theParentList.begin(), theParentList.end(), inBaseInstance)
+ != theParentList.end())
+ continue;
+
+ // Iterate through all property and check if it is Texture property
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(theInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ UICDM::AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(theInstance, theProperty);
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Texture) {
+ // Get the value list of texture property
+ inBridge.GetValueListFromAllSlides(theInstance, theProperty, theValueList);
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Get texture list from all effect instances
+ */
+std::set<Q3DStudio::CString> CClientDataModelBridge::GetDynamicObjectTextureList() const
+{
+ std::vector<SValue> theValueList;
+
+ // Get all effect instances
+ TInstanceHandleList theEffectInstances;
+ m_DataCore->GetInstancesDerivedFrom(theEffectInstances, m_Effect.m_Instance);
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ GetDynamicObjecTextures(*m_DataCore, *thePropertySystem, m_Effect.m_Instance, theValueList,
+ *this);
+ GetDynamicObjecTextures(*m_DataCore, *thePropertySystem, m_CustomMaterial.m_Instance,
+ theValueList, *this);
+
+ // Translate from SValue to Q3DStudio::CString and also remove the identifier
+ std::set<Q3DStudio::CString> theSourcePathList;
+ for (std::vector<SValue>::iterator theIter = theValueList.begin();
+ theIter != theValueList.end(); ++theIter)
+ AddSourcePathToList(theSourcePathList, *theIter);
+
+ return theSourcePathList;
+}
+
+bool CClientDataModelBridge::IsLockedAtAll(UICDM::CUICDMInstanceHandle inInstance)
+{
+ UICDM::SValue theValue;
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ if (thePropertySystem->HasAggregateInstanceProperty(inInstance, GetSceneAsset().m_Locked)) {
+ thePropertySystem->GetInstancePropertyValue(inInstance, GetSceneAsset().m_Locked, theValue);
+ return UICDM::get<bool>(theValue);
+ }
+ return false;
+}
+
+bool CClientDataModelBridge::IsDuplicateable(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (!inInstance.Valid())
+ return false;
+
+ EStudioObjectType theObjectType = GetObjectType(inInstance);
+ if (theObjectType == OBJTYPE_SCENE || theObjectType == OBJTYPE_MATERIAL
+ || theObjectType == OBJTYPE_IMAGE)
+ return false;
+ // If we are delving inside component and selecting the component itself (the component is root
+ // in timeline palette)
+ else if (theObjectType == OBJTYPE_COMPONENT && IsActiveComponent(inInstance))
+ return false;
+ else
+ return !IsLockedAtAll(inInstance);
+}
+
+bool CClientDataModelBridge::IsMultiSelectable(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (!m_DataCore->IsInstance(inInstance))
+ return false;
+ EStudioObjectType theObjectType = GetObjectType(inInstance);
+
+ bool isPotentiallySelectable = theObjectType == OBJTYPE_LIGHT || theObjectType == OBJTYPE_CAMERA
+ || theObjectType == OBJTYPE_MODEL || theObjectType == OBJTYPE_GROUP
+ || theObjectType == OBJTYPE_COMPONENT || theObjectType == OBJTYPE_TEXT
+ || theObjectType == OBJTYPE_ALIAS || theObjectType == OBJTYPE_PATH;
+
+ if (!isPotentiallySelectable)
+ return false;
+
+ // If we are delving inside component and selecting the component itself (the component is root
+ // in timeline palette)
+ if (theObjectType == OBJTYPE_COMPONENT && IsActiveComponent(inInstance))
+ return false;
+
+ return !IsLockedAtAll(inInstance);
+}
+
+bool CClientDataModelBridge::CanDelete(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (!inInstance.Valid())
+ return false;
+
+ switch (GetObjectType(inInstance)) {
+ case OBJTYPE_MODEL:
+ case OBJTYPE_TEXT:
+ case OBJTYPE_GROUP:
+ case OBJTYPE_CAMERA:
+ case OBJTYPE_LIGHT:
+ case OBJTYPE_IMAGE:
+ case OBJTYPE_ALIAS:
+ case OBJTYPE_PATH:
+ case OBJTYPE_PATHANCHORPOINT:
+ case OBJTYPE_SUBPATH:
+ case OBJTYPE_EFFECT:
+ return !IsLockedAtAll(inInstance);
+ break;
+ case OBJTYPE_COMPONENT:
+ return !IsLockedAtAll(inInstance) && !IsActiveComponent(inInstance);
+ break;
+ case OBJTYPE_LAYER:
+ // We could not delete a layer if
+ // 1. if the deleted layer is in master slide, and there is only 1 master layer
+ // otherwise it means it is not the last layer, and can be deleted.
+ if (IsMaster(inInstance)) {
+ UICDM::ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ UICDM::TInstanceHandleList theInstanceList;
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetAssociatedSlide(inInstance);
+ theSlideSystem->GetAssociatedInstances(theMasterSlide, theInstanceList);
+ long theMasterLayerCount = 0;
+ for (UICDM::TInstanceHandleList::const_iterator theIter = theInstanceList.begin();
+ theIter != theInstanceList.end(); ++theIter) {
+ if (IsLayerInstance(*theIter))
+ ++theMasterLayerCount;
+ }
+ if (theMasterLayerCount == 1)
+ return false;
+ }
+
+ return !IsLockedAtAll(inInstance);
+ break;
+ case OBJTYPE_BEHAVIOR:
+ return true;
+ break;
+ case OBJTYPE_MATERIAL:
+ case OBJTYPE_LIGHTMAPS:
+ case OBJTYPE_SCENE:
+ return false;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+bool CClientDataModelBridge::IsMaster(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (IsSceneInstance(inInstance))
+ return true;
+ else {
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlideHandle = theSlideSystem->GetAssociatedSlide(inInstance);
+ return theSlideSystem->IsMasterSlide(theSlideHandle);
+ }
+}
+
+//=============================================================================
+/**
+ * Get the layer that this instance lies in.
+ */
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetResidingLayer(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (!inInstance.Valid())
+ return 0;
+
+ if (IsLayerInstance(inInstance))
+ return inInstance;
+ else {
+ UICDM::CUICDMInstanceHandle theParent = GetParentInstance(inInstance);
+ if (theParent.Valid())
+ return GetResidingLayer(theParent);
+ else
+ return 0;
+ }
+}
+
+//=============================================================================
+/**
+ * Get a child object by it's name in the active Slide.
+ * This is meant to only be used by GetUniqueChildName, names are not Unique
+ * so this should be used with extreme care.
+ * @param inName the name of the child object to fetch.
+ * @return the child that was found.
+ */
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetChildByName(UICDM::CUICDMInstanceHandle inParent,
+ Q3DStudio::CString inName)
+{
+ Q3DStudio::CGraphIterator theChildren;
+ GetAssetChildren(m_Doc, inParent, theChildren);
+
+ for (; !theChildren.IsDone(); ++theChildren) {
+ UICDM::CUICDMInstanceHandle theChildInstance = theChildren.GetCurrent();
+ if (GetName(theChildInstance) == inName)
+ return theChildInstance;
+ }
+ return 0;
+}
+
+Q3DStudio::CId CClientDataModelBridge::GetGUID(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return GetId(inInstance, GetObjectDefinitions().m_Guided.m_GuidProp);
+}
+
+UICDM::CUICDMInstanceHandle
+CClientDataModelBridge::GetParentInstance(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (IsImageInstance(inInstance)) {
+ UICDM::CUICDMInstanceHandle theParentInstance;
+ UICDM::CUICDMPropertyHandle theProperty;
+ if (!GetMaterialFromImageInstance(inInstance, theParentInstance, theProperty))
+ this->GetLayerFromImageProbeInstance(inInstance, theParentInstance, theProperty);
+ return theParentInstance;
+ } else {
+ Q3DStudio::TGraphPtr theGraph = m_Doc->GetAssetGraph();
+ if (theGraph->IsExist(inInstance))
+ return theGraph->GetParent(inInstance);
+ else
+ return 0;
+ }
+}
+
+EStudioObjectType CClientDataModelBridge::GetObjectType(UICDM::CUICDMInstanceHandle inInstance)
+{
+ SValue theTypeValue;
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ thePropertySystem->GetInstancePropertyValue(inInstance, GetTypeProperty(), theTypeValue);
+ std::wstring theType(UICDM::get<TDataStrPtr>(theTypeValue)->GetData());
+
+ if (theType == L"Behavior")
+ return OBJTYPE_BEHAVIOR;
+ else if (theType == L"Camera")
+ return OBJTYPE_CAMERA;
+ else if (theType == L"Group")
+ return OBJTYPE_GROUP;
+ else if (theType == L"Component")
+ return OBJTYPE_COMPONENT;
+ else if (theType == L"Image" || theType == L"LibraryImage")
+ return OBJTYPE_IMAGE;
+ else if (theType == L"Layer")
+ return OBJTYPE_LAYER;
+ else if (theType == L"Light")
+ return OBJTYPE_LIGHT;
+ else if (theType == L"Material")
+ return OBJTYPE_MATERIAL;
+ else if (theType == L"Model")
+ return OBJTYPE_MODEL;
+ else if (theType == L"Alias")
+ return OBJTYPE_ALIAS;
+ else if (theType == L"Scene")
+ return OBJTYPE_SCENE;
+ else if (theType == L"Slide")
+ return OBJTYPE_SLIDE;
+ else if (theType == L"Text")
+ return OBJTYPE_TEXT;
+ else if (theType == L"Effect")
+ return OBJTYPE_EFFECT;
+ else if (theType == L"RenderPlugin")
+ return OBJTYPE_RENDERPLUGIN;
+ else if (theType == L"CustomMaterial")
+ return OBJTYPE_CUSTOMMATERIAL;
+ else if (theType == L"ReferencedMaterial")
+ return OBJTYPE_REFERENCEDMATERIAL;
+ else if (theType == L"Path")
+ return OBJTYPE_PATH;
+ else if (theType == L"PathAnchorPoint")
+ return OBJTYPE_PATHANCHORPOINT;
+ else if (theType == L"SubPath")
+ return OBJTYPE_SUBPATH;
+ else if (theType == L"Lightmaps")
+ return OBJTYPE_LIGHTMAPS;
+ else {
+ ASSERT(0);
+ return OBJTYPE_UNKNOWN;
+ }
+}
+
+bool CClientDataModelBridge::IsBehaviorInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Behavior.m_Instance);
+}
+
+bool CClientDataModelBridge::IsCameraInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Camera.m_Instance);
+}
+
+bool CClientDataModelBridge::IsGroupInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Group.m_Instance);
+}
+
+bool CClientDataModelBridge::IsActionInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_ActionItem.m_Instance);
+}
+
+bool CClientDataModelBridge::IsComponentInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Component.m_Instance);
+}
+
+bool CClientDataModelBridge::IsLayerInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Layer.m_Instance);
+}
+
+bool CClientDataModelBridge::IsLightInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Light.m_Instance);
+}
+bool CClientDataModelBridge::IsModelInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Model.m_Instance);
+}
+
+bool CClientDataModelBridge::IsMaterialBaseInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_MaterialBase.m_Instance);
+}
+
+bool CClientDataModelBridge::IsMaterialInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_DefaultMaterial.m_Instance);
+}
+
+bool CClientDataModelBridge::IsImageInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_SceneImage.m_Instance);
+}
+
+bool CClientDataModelBridge::IsSceneInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Scene.m_Instance);
+}
+
+bool CClientDataModelBridge::IsTextInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Text.m_Instance);
+}
+
+bool CClientDataModelBridge::IsEffectInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Effect.m_Instance);
+}
+
+bool CClientDataModelBridge::IsRenderPluginInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_RenderPlugin.m_Instance);
+}
+
+bool CClientDataModelBridge::IsCustomMaterialInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_CustomMaterial.m_Instance);
+}
+
+bool CClientDataModelBridge::IsReferencedMaterialInstance(
+ UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(
+ inInstance, m_ObjectDefinitions->m_ReferencedMaterial.m_Instance);
+}
+
+bool CClientDataModelBridge::IsLightmapsInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Lightmaps.m_Instance);
+}
+
+bool CClientDataModelBridge::IsNodeType(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Node.m_Instance);
+}
+bool CClientDataModelBridge::IsSceneGraphInstance(UICDM::CUICDMInstanceHandle inInstance) const
+{
+ if (m_DataCore->IsInstance(inInstance) == false)
+ return false;
+ return IsNodeType(inInstance) || IsSceneInstance(inInstance) || IsImageInstance(inInstance)
+ || IsMaterialInstance(inInstance) || IsCustomMaterialInstance(inInstance)
+ || IsReferencedMaterialInstance(inInstance) || IsRenderPluginInstance(inInstance)
+ || IsEffectInstance(inInstance) || IsBehaviorInstance(inInstance);
+}
+
+bool SActionInvalidProperty::operator()(UICDM::CUICDMPropertyHandle inProperty)
+{
+ using namespace UICDM;
+ AdditionalMetaDataType::Value theType =
+ m_PropertySystem.GetAdditionalMetaDataType(m_Instance, inProperty);
+ if (theType == AdditionalMetaDataType::Image || theType == AdditionalMetaDataType::Texture
+ || theType == AdditionalMetaDataType::ObjectRef || theType == AdditionalMetaDataType::Mesh
+ || theType == AdditionalMetaDataType::Import)
+ return true;
+ return false;
+}
+
+// Get all actions that used this instance as either the trigger or target object
+void CClientDataModelBridge::GetReferencedActions(CUICDMInstanceHandle inReferencedInstance,
+ long inReferencedMode,
+ TActionHandleList &outActions)
+{
+ IActionCore *theActionCore = m_Doc->GetStudioSystem()->GetActionCore();
+ TActionHandleList theActions;
+ theActionCore->GetActions(theActions);
+ bool theRefViaOwner = ((inReferencedMode & REFERENCED_AS_OWNER) != 0);
+ bool theRefViaTrigger = ((inReferencedMode & REFERENCED_AS_TRIGGER) != 0);
+ bool theRefViaTarget = ((inReferencedMode & REFERENCED_AS_TARGET) != 0);
+
+ for (TActionHandleList::iterator theIter = theActions.begin(); theIter != theActions.end();
+ ++theIter) {
+ SActionInfo theActionInfo = theActionCore->GetActionInfo(*theIter);
+
+ if (!inReferencedInstance.Valid()
+ || (theRefViaOwner && inReferencedInstance == theActionInfo.m_Owner)
+ || (theRefViaTarget
+ && inReferencedInstance
+ == GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject))
+ || (theRefViaTrigger
+ && inReferencedInstance
+ == GetInstance(theActionInfo.m_Owner, theActionInfo.m_TriggerObject)))
+ outActions.push_back(*theIter);
+ }
+}
+
+void CClientDataModelBridge::UpdateHandlerArgumentValue(UICDM::HandlerArgumentType::Value inArgType,
+ UICDM::CUICDMInstanceHandle inTargetObject,
+ UICDM::SValue inOrigValue,
+ UICDM::SValue inNewValue)
+{
+ IActionCore *theActionCore = m_Doc->GetStudioSystem()->GetActionCore();
+ TActionHandleList theActions;
+ GetReferencedActions(inTargetObject, UICDM::REFERENCED_AS_TARGET, theActions);
+
+ for (TActionHandleList::iterator theAction = theActions.begin(); theAction != theActions.end();
+ ++theAction) {
+ THandlerArgHandleList theArgList;
+ theActionCore->GetHandlerArguments(*theAction, theArgList);
+
+ for (THandlerArgHandleList::iterator theArg = theArgList.begin();
+ theArg != theArgList.end(); ++theArg) {
+ SHandlerArgumentInfo theInfo(theActionCore->GetHandlerArgumentInfo(*theArg));
+ if (theInfo.m_ArgType == inArgType && theInfo.m_Value == inOrigValue) {
+ theActionCore->SetHandlerArgumentValue(*theArg, inNewValue);
+ }
+ }
+ }
+}
+
+std::wstring CClientDataModelBridge::GetDefaultHandler(CUICDMInstanceHandle inInstance,
+ std::wstring inOldHandler)
+{
+ IMetaData *theMetaData = m_Doc->GetStudioSystem()->GetActionMetaData();
+
+ // We try to maintain old handler whenever possible.
+ // This is to fix bug 6569: Maintain handler option under action palette when changing target
+ // object
+ if (inOldHandler != L""
+ && theMetaData->FindHandlerByName(inInstance, inOldHandler.c_str()).Valid())
+ return inOldHandler;
+
+ // This is to fix bug 5106: Default action for components should be Go To Slide
+ std::wstring theHandlerName;
+ if (m_DataCore->IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions->m_SlideOwner.m_Instance)) {
+ theHandlerName = L"Go to Slide";
+ // Verify that Go to Slide is valid, just in case MetaData.xml is changed
+ if (theMetaData->FindHandlerByName(inInstance, theHandlerName.c_str()).Valid())
+ return theHandlerName;
+ }
+
+ // Default to the first handler found
+ THandlerHandleList theHandlerList;
+ GetHandlers(inInstance, theHandlerList);
+ if (theHandlerList.size() > 0)
+ theHandlerName = theMetaData->GetHandlerInfo(theHandlerList[0])->m_Name.wide_str();
+ else
+ theHandlerName = L""; // set to unknown handler
+ return theHandlerName;
+}
+
+std::wstring CClientDataModelBridge::GetDefaultEvent(CUICDMInstanceHandle inInstance,
+ std::wstring inOldEvent)
+{
+ IMetaData *theMetaData = m_Doc->GetStudioSystem()->GetActionMetaData();
+
+ // We try to maintain old event whenever possible.
+ if (inOldEvent != L"" && theMetaData->FindEvent(inInstance, inOldEvent.c_str()).Valid())
+ return inOldEvent;
+
+ // Default to the first event found
+ std::wstring theEventName;
+ TEventHandleList theEventList;
+ GetEvents(inInstance, theEventList);
+ if (theEventList.size() > 0)
+ theEventName = theMetaData->GetEventInfo(theEventList[0])->m_Name.wide_str();
+ else
+ theEventName = L""; // set to unknown event
+ return theEventName;
+}
+
+// TODO : We should change the argument of Property to hold on to a long instead of
+// the string.
+// The long represents the property id which is what we really need. using the name, we need to do
+// all those conversion
+
+void CClientDataModelBridge::ResetHandlerArguments(CUICDMActionHandle inAction,
+ CUICDMHandlerHandle inHandler)
+{
+ // Remove old args
+ IActionCore *theActionCore = m_Doc->GetStudioSystem()->GetActionCore();
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ THandlerArgHandleList theOldArgs;
+ theActionCore->GetHandlerArguments(inAction, theOldArgs);
+ for (THandlerArgHandleList::iterator theArg = theOldArgs.begin(); theArg != theOldArgs.end();
+ ++theArg) {
+ theActionCore->RemoveHandlerArgument(*theArg);
+ }
+
+ if (inHandler.Valid()) // there could be no valid handler for this type of object
+ {
+ IMetaData &theNewMetaData(*m_Doc->GetStudioSystem()->GetActionMetaData());
+ typedef vector<SMetaDataHandlerArgumentInfo> THandlerArgMetaDataList;
+
+ THandlerArgMetaDataList theNewArgs;
+ theNewMetaData.GetHandlerArguments(inHandler, theNewArgs);
+
+ for (THandlerArgMetaDataList::const_iterator theIter = theNewArgs.begin();
+ theIter != theNewArgs.end(); ++theIter) {
+ const SMetaDataHandlerArgumentInfo &theArgMetaData(*theIter);
+ CUICDMHandlerArgHandle theArgument = theActionCore->AddHandlerArgument(
+ inAction, theArgMetaData.m_Name, theArgMetaData.m_ArgType,
+ theArgMetaData.GetDataType());
+ SValue theValue = theArgMetaData.m_DefaultValue;
+ switch (theArgMetaData.m_ArgType) {
+ case HandlerArgumentType::Event:
+ theValue = 0; // TODO: Hardcode for now. Should query event meta data list.
+ break;
+ case HandlerArgumentType::Property: {
+ SActionInfo theActionInfo = theActionCore->GetActionInfo(inAction);
+ CUICDMInstanceHandle theTargetObject =
+ GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject);
+ UICDM::TPropertyHandleList theProperties;
+ m_DataCore->GetAggregateInstanceProperties(theTargetObject, theProperties);
+ erase_if(theProperties,
+ SActionInvalidProperty(*thePropertySystem, theTargetObject));
+ if (theProperties.size() > 0) {
+ theValue = UICDM::TDataStrPtr(new UICDM::CDataStr(
+ thePropertySystem->GetName(theProperties[0]).wide_str()));
+ }
+ } break;
+ case HandlerArgumentType::Slide: {
+ std::list<Q3DStudio::CString> theSlideNames;
+ GetSlideNamesOfAction(inAction, theSlideNames);
+ if (theSlideNames.size() > 0)
+ theValue = TDataStrPtr(new CDataStr(*theSlideNames.begin()));
+ } break;
+ }
+ theActionCore->SetHandlerArgumentValue(theArgument, theValue.toOldSkool());
+ }
+
+ // now find out all those Dependent argument and set it to the type of the
+ // property
+ // I am assuming there is 1 and only 1 for Dependent and
+ // Property which is true for all our use cases
+ const SActionInfo &theActionInfo = theActionCore->GetActionInfo(inAction);
+ DataModelDataType::Value theDataType = DataModelDataType::None;
+ CUICDMHandlerArgHandle theDependentArg = 0;
+ CUICDMInstanceHandle theDependentInstance;
+ CUICDMPropertyHandle theDependentProperty;
+ for (THandlerArgHandleList::const_iterator theIterator =
+ theActionInfo.m_HandlerArgs.begin();
+ theIterator != theActionInfo.m_HandlerArgs.end(); ++theIterator) {
+ const SHandlerArgumentInfo &theArgument =
+ theActionCore->GetHandlerArgumentInfo(*theIterator);
+ if (theArgument.m_ArgType == HandlerArgumentType::Property) {
+ SActionInfo theActionInfo = theActionCore->GetActionInfo(inAction);
+ theDependentInstance =
+ GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject);
+ TCharStr thePropertyName =
+ UICDM::get<UICDM::TDataStrPtr>(theArgument.m_Value)->GetData();
+ theDependentProperty =
+ GetAggregateInstancePropertyByName(theDependentInstance, thePropertyName);
+ theDataType = thePropertySystem->GetDataType(theDependentProperty);
+ } else if (theArgument.m_ArgType == HandlerArgumentType::Dependent) {
+ theDependentArg = *theIterator;
+ }
+ }
+
+ if (theDataType != DataModelDataType::None && theDependentArg != 0) {
+ // found
+ SetArgTypeDependentDefaultValue(theDependentArg, theDataType, theDependentInstance,
+ theDependentProperty);
+ }
+ }
+}
+// Resolve the path
+void CClientDataModelBridge::ResetHandlerArguments(UICDM::CUICDMActionHandle inAction,
+ const std::wstring &inHandler)
+{
+ IActionCore &theActionCore = *m_Doc->GetStudioSystem()->GetActionCore();
+ const SActionInfo &theInfo(theActionCore.GetActionInfo(inAction));
+ ResetHandlerArguments(inAction,
+ ResolveHandler(theInfo.m_Owner, theInfo.m_TargetObject, inHandler));
+}
+
+UICDM::CUICDMEventHandle
+CClientDataModelBridge::ResolveEvent(UICDM::CUICDMInstanceHandle inResolveRoot,
+ const UICDM::SObjectRefType &inResolution,
+ const std::wstring &inEventName)
+{
+ CUICDMInstanceHandle theInstance = GetInstance(inResolveRoot, inResolution);
+ if (theInstance.Valid() == false)
+ return 0;
+ IMetaData &theMetaData(*m_Doc->GetStudioSystem()->GetActionMetaData());
+ return theMetaData.FindEvent(theInstance, inEventName.c_str());
+}
+
+UICDM::CUICDMHandlerHandle
+CClientDataModelBridge::ResolveHandler(UICDM::CUICDMInstanceHandle inResolveRoot,
+ const UICDM::SObjectRefType &inResolution,
+ const std::wstring &inHandlerName)
+{
+ CUICDMInstanceHandle theInstance = GetInstance(inResolveRoot, inResolution);
+ if (theInstance.Valid() == false)
+ return 0;
+ IMetaData &theMetaData(*m_Doc->GetStudioSystem()->GetActionMetaData());
+ return theMetaData.FindHandlerByName(theInstance, inHandlerName.c_str());
+}
+
+UICDM::CUICDMEventHandle CClientDataModelBridge::ResolveEvent(const UICDM::SActionInfo &inInfo)
+{
+ return ResolveEvent(inInfo.m_Owner, inInfo.m_TriggerObject, inInfo.m_Event);
+}
+
+UICDM::CUICDMHandlerHandle CClientDataModelBridge::ResolveHandler(const UICDM::SActionInfo &inInfo)
+{
+ return ResolveHandler(inInfo.m_Owner, inInfo.m_TargetObject, inInfo.m_Handler);
+}
+
+void CClientDataModelBridge::SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ const SValue &inValue)
+{
+ IActionCore *theActionCore = m_Doc->GetStudioSystem()->GetActionCore();
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ theActionCore->SetHandlerArgumentValue(inHandlerArgument, inValue);
+
+ const SHandlerArgumentInfo &theHandlerArgument =
+ theActionCore->GetHandlerArgumentInfo(inHandlerArgument);
+ if (theHandlerArgument.m_ArgType == HandlerArgumentType::Property) {
+ // for property type, we will go find the dependent type and update it to the value type of
+ // this property
+ const SActionInfo &theActionInfo =
+ theActionCore->GetActionInfo(theHandlerArgument.m_Action);
+ CUICDMInstanceHandle theInstance =
+ GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject);
+ TCharStr thePropertyName =
+ UICDM::get<UICDM::TDataStrPtr>(theHandlerArgument.m_Value)->GetData();
+ CUICDMPropertyHandle thePropertyHandle =
+ GetAggregateInstancePropertyByName(theInstance, thePropertyName);
+ DataModelDataType::Value theDataType = thePropertySystem->GetDataType(thePropertyHandle);
+
+ // now find all the dependent argument, assuming only 1 exist and set it to the data type
+ for (THandlerArgHandleList::const_iterator theIterator =
+ theActionInfo.m_HandlerArgs.begin();
+ theIterator != theActionInfo.m_HandlerArgs.end(); ++theIterator) {
+ const SHandlerArgumentInfo &theArgument =
+ theActionCore->GetHandlerArgumentInfo(*theIterator);
+ if (theArgument.m_ArgType == HandlerArgumentType::Dependent) {
+ SetArgTypeDependentDefaultValue(*theIterator, theDataType, theInstance,
+ thePropertyHandle);
+ break;
+ }
+ }
+ }
+}
+
+void CClientDataModelBridge::GetActionDependentProperty(CUICDMActionHandle inAction,
+ CUICDMInstanceHandle &outInstance,
+ CUICDMPropertyHandle &outProperty)
+{
+ IActionCore *theActionCore = m_Doc->GetStudioSystem()->GetActionCore();
+ const SActionInfo &theActionInfo = theActionCore->GetActionInfo(inAction);
+ outInstance = GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject);
+ for (THandlerArgHandleList::const_iterator theIterator = theActionInfo.m_HandlerArgs.begin();
+ theIterator != theActionInfo.m_HandlerArgs.end(); ++theIterator) {
+ const SHandlerArgumentInfo &theArgument =
+ theActionCore->GetHandlerArgumentInfo(*theIterator);
+ if (theArgument.m_ArgType == HandlerArgumentType::Property) {
+ TCharStr thePropertyName =
+ UICDM::get<UICDM::TDataStrPtr>(theArgument.m_Value)->GetData();
+ outProperty = GetAggregateInstancePropertyByName(outInstance, thePropertyName);
+ break;
+ }
+ }
+}
+
+void CClientDataModelBridge::GetSlideNamesOfAction(UICDM::CUICDMActionHandle inAction,
+ std::list<Q3DStudio::CString> &outSlideNames)
+{
+ SActionInfo theActionInfo = m_Doc->GetStudioSystem()->GetActionCore()->GetActionInfo(inAction);
+ CUICDMInstanceHandle theTargetInstance =
+ GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject);
+ Q3DStudio::CId theTargetId = GetGUID(theTargetInstance);
+
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theTargetId));
+ size_t theSlideCount = theSlideSystem->GetSlideCount(theMasterSlide);
+
+ for (size_t theSlideIndex = 1; theSlideIndex < theSlideCount;
+ ++theSlideIndex) // Index 0 refers to Master Slide, so start from index 1
+ {
+ CUICDMSlideHandle theSlideHandle =
+ theSlideSystem->GetSlideByIndex(theMasterSlide, theSlideIndex);
+ CUICDMInstanceHandle theInstanceHandle = theSlideSystem->GetSlideInstance(theSlideHandle);
+ outSlideNames.push_back(GetName(theInstanceHandle));
+ }
+}
+
+void CClientDataModelBridge::SetArgTypeDependentDefaultValue(
+ CUICDMHandlerArgHandle inHandlerArgument, DataModelDataType::Value inDataType,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty)
+{
+ SValue theValue;
+ SetDefault(inDataType, theValue);
+ // Special case for string, check if there is a stringlist for this property
+ if (inDataType == DataModelDataType::String) {
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ TMetaDataData theData =
+ thePropertySystem->GetAdditionalMetaDataData(inInstance, inProperty);
+ if (theData.getType() == AdditionalMetaDataType::StringList) {
+ UICDM::TMetaDataStringList theStringList =
+ UICDM::get<UICDM::TMetaDataStringList>(theData);
+ if (theStringList.size() > 0)
+ theValue = TDataStrPtr(new CDataStr(theStringList[0].wide_str()));
+ }
+ }
+ m_Doc->GetStudioSystem()->GetActionCore()->SetHandlerArgumentValue(inHandlerArgument, theValue);
+}
+
+void CClientDataModelBridge::GetEvents(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::TEventHandleList &outEvents)
+{
+ if (m_Doc->GetStudioSystem()->IsInstance(inInstance))
+ m_Doc->GetStudioSystem()->GetActionMetaData()->GetEvents(inInstance, outEvents);
+}
+
+UICDM::SEventInfo CClientDataModelBridge::GetEventInfo(UICDM::CUICDMEventHandle inEvent)
+{
+ if (inEvent.Valid() == false)
+ return SEventInfo();
+ return m_Doc->GetStudioSystem()->GetActionMetaData()->GetEventInfo(inEvent);
+}
+
+void CClientDataModelBridge::GetHandlers(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::THandlerHandleList &outHandles)
+{
+ if (m_Doc->GetStudioSystem()->IsInstance(inInstance))
+ m_Doc->GetStudioSystem()->GetActionMetaData()->GetHandlers(inInstance, outHandles);
+}
+
+UICDM::SHandlerInfo CClientDataModelBridge::GetHandlerInfo(UICDM::CUICDMHandlerHandle inHandler)
+{
+ if (inHandler.Valid() == false)
+ return SHandlerInfo();
+ return m_Doc->GetStudioSystem()->GetActionMetaData()->GetHandlerInfo(inHandler);
+}
+
+CUICDMPropertyHandle
+CClientDataModelBridge::GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inPropertyName)
+{
+ return m_DataCore->GetAggregateInstancePropertyByName(inInstance, inPropertyName);
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
new file mode 100644
index 00000000..4fbc0760
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
@@ -0,0 +1,435 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef CLIENTDATAMODELBRIDGEH
+#define CLIENTDATAMODELBRIDGEH
+
+#include "UICDMHandles.h"
+#include "UICDMDataTypes.h"
+#include "UICId.h"
+#include "UICDMActionInfo.h"
+#include "StudioObjectTypes.h"
+#include "Graph.h"
+#include "Pt.h"
+#include "UICDMMetaData.h"
+#include "UICDMComposerTypeDefinitions.h"
+
+class CDoc;
+
+namespace UICDM {
+class IDataCore;
+class ISlideGraphCore;
+class ISlideCore;
+class IAnimationCore;
+struct SUICDMPropertyDefinition;
+class IPropertySystem;
+class IInstancePropertyCore;
+class ISignalConnection;
+class IMetaData;
+}
+
+struct SLong4Hasher
+{
+ std::size_t operator()(const UICDM::SLong4 &inObject) const
+ {
+ return std::hash<unsigned long>()(inObject.m_Longs[0])
+ ^ std::hash<unsigned long>()(inObject.m_Longs[1])
+ ^ std::hash<unsigned long>()(inObject.m_Longs[2])
+ ^ std::hash<unsigned long>()(inObject.m_Longs[3]);
+ }
+};
+
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Material>
+ SDataModelDefaultMaterial;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Image> SDataModelSceneImage;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Node> SDataModelNode;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Layer> SDataModelLayer;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Model> SDataModelModel;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Light> SDataModelLight;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Camera> SDataModelCamera;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Text> SDataModelText;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Group> SDataModelGroup;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Component> SDataModelComponent;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Behavior> SDataModelBehavior;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Scene> SDataModelScene;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Slide> SDataModelSlide;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Action> SDataModelAction;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Asset> SDataModelSceneAsset;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Effect> SDataModelEffect;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::RenderPlugin>
+ SDataModelRenderPlugin;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::MaterialBase>
+ SDataModelMaterialBase;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::CustomMaterial>
+ SDataModelCustomMaterial;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Lightmaps> SDataModelLightmaps;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Alias> SDataModelAlias;
+typedef UICDM::SComposerObjectDefinition<UICDM::ComposerObjectTypes::Path> SDataModelPath;
+
+struct IValueFilter
+{
+ virtual ~IValueFilter() {}
+ virtual bool KeepValue(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty,
+ const UICDM::SValue &inValue) = 0;
+};
+
+struct SActionInvalidProperty
+{
+ UICDM::CUICDMInstanceHandle m_Instance;
+ UICDM::IPropertySystem &m_PropertySystem;
+ SActionInvalidProperty(UICDM::IPropertySystem &ps, UICDM::CUICDMInstanceHandle inInstance)
+ : m_Instance(inInstance)
+ , m_PropertySystem(ps)
+ {
+ }
+ bool operator()(UICDM::CUICDMPropertyHandle inProperty);
+};
+
+class CClientDataModelBridge
+{
+ Q_DISABLE_COPY(CClientDataModelBridge)
+
+ UICDM::IDataCore *m_DataCore;
+ UICDM::ISlideCore *m_SlideCore;
+ UICDM::ISlideGraphCore *m_SlideGraphCore;
+ UICDM::IAnimationCore *m_AnimationCore;
+ std::shared_ptr<UICDM::IMetaData> m_NewMetaData;
+ std::shared_ptr<UICDM::SComposerObjectDefinitions> m_ObjectDefinitions;
+ CDoc *m_Doc;
+
+ SDataModelDefaultMaterial &m_DefaultMaterial;
+ SDataModelSceneImage &m_SceneImage;
+ SDataModelNode &m_Node;
+ SDataModelLayer &m_Layer;
+ SDataModelModel &m_Model;
+ SDataModelLight &m_Light;
+ SDataModelCamera &m_Camera;
+ SDataModelText &m_Text;
+ SDataModelGroup &m_Group;
+ SDataModelComponent &m_Component;
+ SDataModelBehavior &m_Behavior;
+ SDataModelScene &m_Scene;
+ SDataModelSlide &m_SlideItem;
+ SDataModelAction &m_ActionItem;
+ SDataModelSceneAsset &m_SceneAsset;
+ SDataModelEffect &m_Effect;
+ SDataModelRenderPlugin &m_RenderPlugin;
+ SDataModelMaterialBase &m_MaterialBase;
+ SDataModelCustomMaterial &m_CustomMaterial;
+ SDataModelAlias &m_Alias;
+ SDataModelPath &m_Path;
+ SDataModelLightmaps &m_Lightmaps;
+
+ // cache to increase performance
+ bool m_CacheEnabled;
+
+ typedef std::unordered_map<UICDM::SLong4, UICDM::CUICDMInstanceHandle, SLong4Hasher>
+ TGUIDInstanceHash;
+ typedef std::unordered_map<int, UICDM::SLong4> TInstanceToGUIDHash;
+
+ TGUIDInstanceHash m_CachedGUIDToInstancesHash;
+ std::shared_ptr<UICDM::ISignalConnection> m_InstanceCachePropertyChangedConnection;
+ std::shared_ptr<UICDM::ISignalConnection> m_InstanceCacheInstanceDeletedConnection;
+ TInstanceToGUIDHash m_CachedInstanceToGUIDHash;
+
+ UICDM::TInstanceHandleList m_CachedGuidInstances;
+ UICDM::TInstanceHandleList m_CacheImageInstances;
+ UICDM::TInstanceHandleList m_CacheMaterialInstances;
+ UICDM::TInstanceHandleList m_CacheModelInstances;
+
+public:
+ CClientDataModelBridge(UICDM::IDataCore *inDataCore, UICDM::ISlideCore *inSlideCore,
+ UICDM::ISlideGraphCore *inSlideGraphCore,
+ UICDM::IAnimationCore *inAnimationCore,
+ std::shared_ptr<UICDM::IMetaData> inNewMetaData,
+ std::shared_ptr<UICDM::SComposerObjectDefinitions> inDefinitions,
+ CDoc *inDoc);
+ virtual ~CClientDataModelBridge();
+
+ virtual UICDM::CUICDMInstanceHandle CreateAssetInstance(Q3DStudio::CId &inId,
+ EStudioObjectType inObjectType);
+ virtual UICDM::CUICDMSlideGraphHandle GetOrCreateGraph(UICDM::CUICDMInstanceHandle inInstance);
+ virtual UICDM::CUICDMSlideHandle GetOrCreateGraphRoot(UICDM::CUICDMInstanceHandle inInstance);
+ virtual UICDM::CUICDMInstanceHandle GetSlideInstance();
+ virtual UICDM::CUICDMPropertyHandle GetSlideComponentIdProperty();
+ virtual UICDM::CUICDMPropertyHandle GetNameProperty();
+ virtual UICDM::CUICDMPropertyHandle GetIdProperty();
+ virtual UICDM::CUICDMPropertyHandle GetTypeProperty();
+ virtual UICDM::CUICDMPropertyHandle GetSourcePathProperty();
+ virtual UICDM::CUICDMInstanceHandle GetActionInstance();
+ virtual UICDM::CUICDMPropertyHandle GetActionEyeball();
+ virtual UICDM::CUICDMPropertyHandle GetImportId();
+
+ virtual UICDM::SComposerObjectDefinitions &GetObjectDefinitions()
+ {
+ return *m_ObjectDefinitions;
+ }
+ virtual const UICDM::SComposerObjectDefinitions &GetObjectDefinitions() const
+ {
+ return *m_ObjectDefinitions;
+ }
+
+ virtual bool IsInternalProperty(const UICDM::TCharStr &inPropertyName) const;
+
+ virtual UICDM::CUICDMInstanceHandle
+ GetOwningComponentInstance(UICDM::CUICDMInstanceHandle inInstanceHandle);
+ virtual UICDM::CUICDMInstanceHandle
+ GetOwningComponentInstance(UICDM::CUICDMInstanceHandle inInstanceHandle, int &outSlideIndex);
+ virtual UICDM::CUICDMInstanceHandle
+ GetOwningComponentInstance(UICDM::CUICDMSlideHandle inSlideHandle, int &outSlideIndex);
+ virtual UICDM::CUICDMInstanceHandle
+ GetOwningComponentInstance(UICDM::CUICDMSlideHandle inSlideHandle);
+ virtual UICDM::SLong4 GetComponentGuid(UICDM::CUICDMSlideHandle inSlideHandle);
+
+ virtual bool IsActive(UICDM::CUICDMInstanceHandle inInstanceHandle, long inCurrentTime);
+
+ virtual UICDM::CUICDMSlideHandle
+ GetComponentActiveSlide(UICDM::CUICDMInstanceHandle inComponent);
+ virtual UICDM::CUICDMSlideHandle GetComponentSlide(UICDM::CUICDMInstanceHandle inComponent,
+ long inIndex);
+
+ const SDataModelDefaultMaterial &GetDefaultMaterial() const { return m_DefaultMaterial; }
+ const SDataModelSceneImage &GetSceneImage() const { return m_SceneImage; }
+ const SDataModelNode &GetNode() const { return m_Node; }
+ const SDataModelLayer &GetLayer() const { return m_Layer; }
+ const SDataModelModel &GetModel() const { return m_Model; }
+ const SDataModelLight &GetLight() const { return m_Light; }
+ const SDataModelCamera &GetCamera() const { return m_Camera; }
+ const SDataModelText &GetText() const { return m_Text; }
+ const SDataModelGroup &GetGroup() const { return m_Group; }
+ const SDataModelComponent &GetComponent() const { return m_Component; }
+ const SDataModelBehavior &GetBehavior() const { return m_Behavior; }
+ const SDataModelScene &GetScene() const { return m_Scene; }
+ const SDataModelSceneAsset &GetSceneAsset() const { return m_SceneAsset; }
+ const SDataModelSlide &GetSlide() const { return m_SlideItem; }
+ const SDataModelEffect &GetEffect() const { return m_Effect; }
+ const SDataModelAlias &GetAlias() const { return m_Alias; }
+ const SDataModelPath &GetPath() const { return m_Path; }
+ const SDataModelLightmaps &GetLightmaps() const { return m_Lightmaps; }
+
+ // Is this the instance that owns the document's currently active slide?
+ bool IsActiveComponent(UICDM::CUICDMInstanceHandle inInstance);
+
+public: // Operations which likely don't belong on this class
+ virtual bool GetMaterialFromImageInstance(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle &outMaterialInstance,
+ UICDM::CUICDMPropertyHandle &outProperty);
+ virtual bool GetLayerFromImageProbeInstance(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle &outLayerInstance,
+ UICDM::CUICDMPropertyHandle &outProperty);
+
+public: // Bridging to Actions. These needs to be here as UICDM has no hierarchy info and we need to
+ // resolve the path to idenitfy the object referenced
+ // We should really reconsider to have the hierachcy store outside of UICDM.
+ void GetReferencedActions(UICDM::CUICDMInstanceHandle inReferencedInstance,
+ long inReferencedMode, UICDM::TActionHandleList &outActions);
+ void UpdateHandlerArgumentValue(UICDM::HandlerArgumentType::Value inArgType,
+ UICDM::CUICDMInstanceHandle inTargetObject,
+ UICDM::SValue inOrigValue, UICDM::SValue inNewValue);
+ std::wstring GetDefaultHandler(UICDM::CUICDMInstanceHandle inInstance,
+ std::wstring inOldHandler = L"");
+ std::wstring GetDefaultEvent(UICDM::CUICDMInstanceHandle inInstance,
+ std::wstring inOldEvent = L"");
+ void ResetHandlerArguments(UICDM::CUICDMActionHandle inAction,
+ UICDM::CUICDMHandlerHandle inHandler);
+ // Resolve the path
+ void ResetHandlerArguments(UICDM::CUICDMActionHandle inAction, const std::wstring &inHandler);
+ UICDM::CUICDMEventHandle ResolveEvent(UICDM::CUICDMInstanceHandle inResolveRoot,
+ const UICDM::SObjectRefType &inResolution,
+ const std::wstring &inEventName);
+ UICDM::CUICDMHandlerHandle ResolveHandler(UICDM::CUICDMInstanceHandle inResolveRoot,
+ const UICDM::SObjectRefType &inResolution,
+ const std::wstring &inHandlerName);
+ UICDM::CUICDMEventHandle ResolveEvent(const UICDM::SActionInfo &inInfo);
+ UICDM::CUICDMHandlerHandle ResolveHandler(const UICDM::SActionInfo &inInfo);
+ void SetHandlerArgumentValue(UICDM::CUICDMHandlerArgHandle inHandlerArgument,
+ const UICDM::SValue &inValue);
+ void GetActionDependentProperty(UICDM::CUICDMActionHandle inAction,
+ UICDM::CUICDMInstanceHandle &outInstance,
+ UICDM::CUICDMPropertyHandle &outProperty);
+ void GetSlideNamesOfAction(UICDM::CUICDMActionHandle inAction,
+ std::list<Q3DStudio::CString> &outSlideNames);
+
+protected:
+ void SetArgTypeDependentDefaultValue(UICDM::CUICDMHandlerArgHandle inHandlerArgument,
+ UICDM::DataModelDataType::Value inDataType,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+
+public: // TODO: We should really consider having CStudioCoreSystem or CStudioFullSystem manages the
+ // MetaData, so that we can query directly from within
+ void GetEvents(UICDM::CUICDMInstanceHandle inInstance, UICDM::TEventHandleList &outEvents);
+ UICDM::SEventInfo GetEventInfo(UICDM::CUICDMEventHandle inEvent);
+
+ void GetHandlers(UICDM::CUICDMInstanceHandle inInstance, UICDM::THandlerHandleList &outHandles);
+ UICDM::SHandlerInfo GetHandlerInfo(UICDM::CUICDMHandlerHandle inHandler);
+
+ UICDM::CUICDMPropertyHandle
+ GetAggregateInstancePropertyByName(UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::TCharStr &inStr);
+
+private:
+ UICDM::CUICDMInstanceHandle
+ GetInstanceByGUIDDerivedFrom(UICDM::SLong4 inLong4, UICDM::CUICDMInstanceHandle inParentHandle,
+ UICDM::CUICDMPropertyHandle inProperty);
+ UICDM::CUICDMInstanceHandle
+ GetInstanceByGUIDDerivedFrom(UICDM::SLong4 inLong4, const UICDM::TInstanceHandleList &instances,
+ UICDM::CUICDMPropertyHandle inProperty);
+ UICDM::CUICDMInstanceHandle MaybeCacheGetInstanceByGUIDDerivedFrom(
+ UICDM::SLong4 inLong4, UICDM::TInstanceHandleList &ioCacheInstances,
+ UICDM::CUICDMInstanceHandle inParentHandle, UICDM::CUICDMPropertyHandle inProperty);
+ static bool DerivedGuidMatches(UICDM::IDataCore &inDataCore,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty, UICDM::SLong4 inGuid);
+ void ClearCache();
+ UICDM::CUICDMInstanceHandle GetSceneOrComponentInstance(UICDM::CUICDMInstanceHandle inInstance);
+ UICDM::CUICDMSlideHandle CreateNonMasterSlide(UICDM::CUICDMSlideHandle inMasterSlide,
+ Q3DStudio::CId inGuid,
+ const Q3DStudio::CString &inName);
+
+public: // helpers
+ void BeginRender(); // enable cache to increase performance
+ void EndRender(); // disable cache
+ UICDM::CUICDMInstanceHandle GetInstanceByGUID(const Q3DStudio::CId &inId);
+ UICDM::CUICDMInstanceHandle GetInstanceByGUID(UICDM::SLong4 inLong4);
+ // GUIDS are auto-generated, but is sometimes necessary to hard-set a specific guid
+ UICDM::SLong4 GetInstanceGUID(UICDM::CUICDMInstanceHandle);
+ void SetInstanceGUID(UICDM::CUICDMInstanceHandle, UICDM::SLong4 inGuid);
+ void ClearInstanceGUIDCache(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ UICDM::CUICDMInstanceHandle GetImageInstanceByGUID(const Q3DStudio::CId &inId);
+ UICDM::CUICDMInstanceHandle GetImageInstanceByGUID(UICDM::SLong4 inLong4);
+ UICDM::CUICDMInstanceHandle GetMaterialInstanceByGUID(const Q3DStudio::CId &inId);
+ UICDM::CUICDMInstanceHandle GetMaterialInstanceByGUID(UICDM::SLong4 inLong4);
+ UICDM::CUICDMInstanceHandle GetModelInstanceByGUID(const Q3DStudio::CId &inId);
+ UICDM::CUICDMInstanceHandle GetModelInstanceByGUID(UICDM::SLong4 inLong4);
+ UICDM::CUICDMInstanceHandle GetComponentInstanceByGUID(const Q3DStudio::CId &inId);
+ UICDM::CUICDMInstanceHandle GetComponentInstanceByGUID(UICDM::SLong4 inLong4);
+ UICDM::CUICDMInstanceHandle GetInstance(UICDM::CUICDMInstanceHandle inRoot,
+ const UICDM::SValue &inValue);
+ UICDM::CUICDMInstanceHandle GetInstance(UICDM::CUICDMInstanceHandle inRoot,
+ const UICDM::SObjectRefType &inValue);
+ UICDM::TInstanceHandleList GetItemBaseInstances() const;
+
+ std::pair<UICDM::CUICDMInstanceHandle, UICDM::SLong4>
+ CreateImageInstance(UICDM::CUICDMInstanceHandle inSourceInstance,
+ UICDM::CUICDMPropertyHandle inSlot, UICDM::CUICDMSlideHandle inUICDMSlide);
+
+ void SetName(UICDM::CUICDMInstanceHandle inInstanceHandle, const Q3DStudio::CString &inName);
+ Q3DStudio::CString GetName(UICDM::CUICDMInstanceHandle inInstanceHandle);
+
+ // Convenience functions to get GUID property value from instance handle
+private:
+ Q3DStudio::CId GetId(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty) const;
+
+ // Helper for old methods in CAsset
+public:
+ bool IsInActiveComponent(UICDM::CUICDMInstanceHandle inInstance);
+ bool IsInComponent(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inComponentInstance);
+ UICDM::CUICDMInstanceHandle GetParentComponent(UICDM::CUICDMInstanceHandle inInstance,
+ bool inIsFirstCall = true);
+ Q3DStudio::CString GetUniqueChildName(UICDM::CUICDMInstanceHandle inParent,
+ UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CString inDesiredName);
+ bool CheckNameUnique(UICDM::CUICDMInstanceHandle inInstance, Q3DStudio::CString inDesiredName);
+ Q3DStudio::CString GetSourcePath(UICDM::CUICDMInstanceHandle inInstance) const;
+ std::set<Q3DStudio::CString> GetSourcePathList() const;
+ std::set<Q3DStudio::CString> GetFontFileList() const;
+ std::set<Q3DStudio::CString> GetDynamicObjectTextureList() const;
+ bool IsLockedAtAll(UICDM::CUICDMInstanceHandle inInstance);
+ bool IsDuplicateable(UICDM::CUICDMInstanceHandle inInstance);
+ bool IsMultiSelectable(UICDM::CUICDMInstanceHandle inInstance);
+ bool CanDelete(UICDM::CUICDMInstanceHandle inInstance);
+ bool IsMaster(UICDM::CUICDMInstanceHandle inInstance);
+ UICDM::CUICDMInstanceHandle GetResidingLayer(UICDM::CUICDMInstanceHandle inInstance);
+ void GetValueListFromAllSlides(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty,
+ std::vector<UICDM::SValue> &outValueList,
+ IValueFilter *inFilter = NULL) const;
+
+protected:
+ UICDM::CUICDMInstanceHandle GetChildByName(UICDM::CUICDMInstanceHandle inParent,
+ Q3DStudio::CString inChildName);
+ std::vector<UICDM::SValue>
+ GetValueList(UICDM::CUICDMInstanceHandle inParentInstance,
+ UICDM::CUICDMPropertyHandle inProperty,
+ IValueFilter *inFilter = NULL) const;
+
+public:
+ Q3DStudio::CId GetGUID(UICDM::CUICDMInstanceHandle inInstance) const;
+
+ UICDM::CUICDMInstanceHandle GetParentInstance(UICDM::CUICDMInstanceHandle inInstance);
+
+ // TODO: EStudioObjectType and EASSETTYPE can't co-exist, one must go. Think EStudioObjectType
+ // should win since things are better classified
+ EStudioObjectType GetObjectType(UICDM::CUICDMInstanceHandle inInstance);
+ bool IsBehaviorInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsCameraInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsGroupInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsActionInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsComponentInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsLayerInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsLightInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsModelInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsMaterialBaseInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsMaterialInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsReferencedMaterialInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsImageInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsSceneInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsTextInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsEffectInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsRenderPluginInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsCustomMaterialInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsLightmapsInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+ bool IsNodeType(UICDM::CUICDMInstanceHandle inInstance) const;
+ // Returns true if this instance would be in the scene graph
+ bool IsSceneGraphInstance(UICDM::CUICDMInstanceHandle inInstance) const;
+};
+
+inline UICDM::SLong4 GuidtoSLong4(const Q3DStudio::CId &inId)
+{
+ Q3DStudio::TGUIDPacked thePacked(inId);
+ return UICDM::SLong4(thePacked.Data1, thePacked.Data2, thePacked.Data3, thePacked.Data4);
+}
+
+inline Q3DStudio::CId Long4ToGuid(const UICDM::SLong4 &inLong4)
+{
+ return Q3DStudio::CId(inLong4.m_Longs[0], inLong4.m_Longs[1], inLong4.m_Longs[2],
+ inLong4.m_Longs[3]);
+}
+
+inline bool GuidValid(const UICDM::SLong4 &inLong4)
+{
+ return (inLong4.m_Longs[0] && inLong4.m_Longs[1] && inLong4.m_Longs[2] && inLong4.m_Longs[3]);
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/ComposerEditorInterface.cpp b/src/Authoring/Client/Code/Core/Doc/ComposerEditorInterface.cpp
new file mode 100644
index 00000000..c6ae433e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/ComposerEditorInterface.cpp
@@ -0,0 +1,598 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "IComposerEditorInterface.h"
+#include "UICImport.h"
+#include "UICImportTranslation.h"
+#include "Graph.h"
+#include "StandardExtensions.h"
+#include "EASTL/hash_map.h"
+
+using namespace Q3DStudio::ComposerImport;
+using namespace qt3ds::foundation;
+
+namespace {
+// base class between performing refresh and performing
+// imports
+
+struct STCharPtrHash
+{
+ size_t operator()(TCharPtr nm) const
+ {
+#ifdef KDAB_TEMPORARILY_REMOVED
+ StaticAssert<sizeof(wchar_t) == sizeof(char16_t)>::valid_expression();
+#endif
+ return eastl::hash<const char16_t *>()(reinterpret_cast<const char16_t *>(nm));
+ }
+};
+struct STCharPtrEqualTo
+{
+ bool operator()(TCharPtr lhs, TCharPtr rhs) const { return AreEqual(lhs, rhs); }
+};
+
+struct SComposerImportBase
+{
+ IDocumentEditor &m_Editor;
+ CFilePath m_DocumentPath;
+ CFilePath m_DestImportDir;
+ CFilePath m_DestImportFile;
+ Q3DStudio::CFilePath m_Relativeimportfile;
+ qt3ds::QT3DSI32 m_StartTime;
+ UICDM::IStringTable &m_StringTable;
+ SComposerImportBase(
+ IDocumentEditor &inEditor,
+ const Q3DStudio::CFilePath &docPath /// Root directory where the studio file sits.
+ ,
+ const Q3DStudio::CFilePath &inFullPathToImportFile, long inStartTime,
+ UICDM::IStringTable &inStringTable)
+ : m_Editor(inEditor)
+ , m_DocumentPath(docPath)
+ , m_DestImportDir(inFullPathToImportFile
+ .GetDirectory()) // Directory where we are saving the import file
+ , m_DestImportFile(inFullPathToImportFile)
+ , m_Relativeimportfile(
+ Q3DStudio::CFilePath::GetRelativePathFromBase(m_DocumentPath, inFullPathToImportFile))
+ , m_StartTime(inStartTime)
+ , m_StringTable(inStringTable)
+ {
+ }
+};
+
+struct SComposerImportInterface : public SComposerImportBase, public IComposerEditorInterface
+{
+ typedef eastl::hash_map<TImportId, CUICDMInstanceHandle, STCharPtrHash, STCharPtrEqualTo>
+ TImportInstanceMap;
+ CUICDMInstanceHandle m_Parent;
+ CUICDMInstanceHandle m_Root;
+ CUICDMSlideHandle m_Slide;
+ Q3DStudio::CString m_TypeBuffer;
+ qt3ds::QT3DSI32 m_StartTime;
+ Import *m_ImportObj;
+ TImportInstanceMap m_ImportToInstanceMap;
+
+ // When we are refreshing, the root assets is the group we are refreshing.
+ SComposerImportInterface(
+ Q3DStudio::IDocumentEditor &editor, UICDM::CDataModelHandle parent // Parent object
+ ,
+ UICDM::CDataModelHandle root, UICDM::CUICDMSlideHandle slide,
+ const Q3DStudio::CFilePath &docPath /// Root directory where the studio file sits.
+ ,
+ const Q3DStudio::CFilePath &inFullPathToImportFile, long inStartTime,
+ UICDM::IStringTable &inStringTable)
+ : SComposerImportBase(editor, docPath, inFullPathToImportFile, inStartTime, inStringTable)
+ , m_Parent(parent)
+ , m_Root(root)
+ , m_Slide(slide)
+ , m_StartTime(inStartTime)
+ , m_ImportObj(NULL)
+ {
+ m_Editor.BeginAggregateOperation();
+ }
+
+ // Fires the 'do' notifications
+ ~SComposerImportInterface() { m_Editor.EndAggregateOperation(); }
+
+ // IComposerEditorInterface
+
+ bool HasError() override { return m_Root.Valid() == false; }
+
+ const wchar_t *GetRelativeimportfile() const {return nullptr;}
+
+ void Finalize(const Q3DStudio::CFilePath &inFilePath) override
+ {
+ m_Editor.SetSpecificInstancePropertyValue(
+ m_Slide, m_Root, L"sourcepath",
+ std::make_shared<CDataStr>((const wchar_t *)m_Relativeimportfile));
+ m_Editor.SetSpecificInstancePropertyValue(
+ m_Slide, m_Root, L"importfile",
+ std::make_shared<CDataStr>((const wchar_t *)m_Relativeimportfile));
+ }
+
+ CUICDMInstanceHandle FindInstance(TImportId inImportHdl) override
+ {
+ TImportInstanceMap::const_iterator entry(m_ImportToInstanceMap.find(inImportHdl));
+ if (entry != m_ImportToInstanceMap.end())
+ return entry->second;
+ return 0;
+ }
+
+ void AddInstanceMap(CUICDMInstanceHandle instanceHandle, TImportId inImportId) override
+ {
+ if (inImportId == NULL || *inImportId == 0) {
+ assert(0);
+ return;
+ }
+ bool success =
+ m_ImportToInstanceMap
+ .insert(eastl::make_pair(m_StringTable.RegisterStr(inImportId), instanceHandle))
+ .second;
+ (void)success;
+ assert(success);
+ }
+ CUICDMInstanceHandle GetRoot() override { return m_Root; }
+
+ const Q3DStudio::CFilePath &GetDestImportFile() override { return m_DestImportFile; }
+
+ // IComposerEditor
+ // Object is stack created for now
+ void Release() override {}
+
+ void BeginImport(Import &importObj) override { m_ImportObj = &importObj; }
+
+ void RemoveChild(TImportId parent, TImportId child) override
+ {
+ CUICDMInstanceHandle childHandle = FindInstance(child);
+ CUICDMInstanceHandle parentHandle = FindInstance(parent);
+ if (childHandle.Valid() && parentHandle.Valid()) {
+ CUICDMInstanceHandle parentId = m_Editor.GetParent(childHandle);
+ // If the child was moved, we don't remove it. Only on the case where
+ // it has it's original parent.
+ if (parentId == parentHandle)
+ m_Editor.RemoveChild(parentHandle, childHandle);
+ }
+ }
+
+ void RemoveInstance(TImportId inInstance) override
+ {
+ CUICDMInstanceHandle instance = FindInstance(inInstance);
+ if (instance.Valid())
+ m_Editor.DeleteInstance(instance);
+ }
+
+ CUICDMInstanceHandle CreateInstance(ComposerObjectTypes::Enum type, CUICDMInstanceHandle parent,
+ TImportId inImportId)
+ {
+ if (parent.Valid() == false) {
+ assert(0);
+ return 0;
+ }
+
+ // Map the type to the object type.
+ CUICDMInstanceHandle retval = m_Editor.CreateSceneGraphInstance(type, parent, m_Slide);
+ m_Editor.SetSpecificInstancePropertyValue(0, retval, L"importid",
+ std::make_shared<CDataStr>(inImportId));
+ m_Editor.SetSpecificInstancePropertyValue(
+ m_Slide, retval, L"importfile",
+ std::make_shared<CDataStr>((const wchar_t *)m_Relativeimportfile));
+ AddInstanceMap(retval, inImportId);
+ return retval;
+ }
+
+ /**
+ * Note that instance properties that point to files (sourcepath generally) point to files
+ * relative to the import file. You need to do combineBaseAndRelative with those files
+ * and the a new getRelativeFromBase with the final file in order to transfer data
+ * successfully. The time to do this sort of thing is upon create or update instance.
+ */
+ void CreateRootInstance(TImportId inImportId, ComposerObjectTypes::Enum type) override
+ {
+ CUICDMInstanceHandle retval = m_Root;
+ if (m_Root.Valid() == false) {
+ retval = CreateInstance(type, m_Parent, inImportId);
+ m_Root = retval;
+ if (m_StartTime >= 0)
+ m_Editor.SetStartTime(retval, m_StartTime);
+ } else
+ AddInstanceMap(m_Root, inImportId);
+
+ QT3DS_ASSERT(m_Root.Valid());
+ }
+
+ void CreateInstance(TImportId inImportId, ComposerObjectTypes::Enum type,
+ TImportId inParent) override
+ {
+ CUICDMInstanceHandle theParent(FindInstance(inParent));
+ if (theParent.Valid())
+ CreateInstance(type, theParent, inImportId);
+ }
+
+ void UpdateInstanceProperties(TImportId inInstance, const PropertyValue *propertBuffer,
+ QT3DSU32 propertyBufferSize) override
+ {
+ CUICDMInstanceHandle hdl(FindInstance(inInstance));
+ if (hdl.Valid() == false)
+ return;
+
+ if (m_Editor.IsInstance(hdl) == false)
+ return;
+
+ for (QT3DSU32 idx = 0; idx < propertyBufferSize; ++idx) {
+ const PropertyValue &value(propertBuffer[idx]);
+ SValue theValue(value.m_Value);
+
+ DataModelDataType::Value theType = GetValueType(theValue);
+ if (value.m_Name == ComposerPropertyNames::sourcepath) {
+ // re-work the path to be relative to where the main document
+ // is saved instead of where the import result is saved
+ TDataStrPtr value = UICDM::get<TDataStrPtr>(theValue);
+ if (value->GetLength()) {
+ Q3DStudio::CString valueStr(value->GetData());
+ Q3DStudio::CFilePath fullPath =
+ Q3DStudio::CFilePath::CombineBaseAndRelative(m_DestImportDir, valueStr);
+ Q3DStudio::CString relativePath =
+ Q3DStudio::CFilePath::GetRelativePathFromBase(m_DocumentPath, fullPath);
+ theValue = std::make_shared<CDataStr>(relativePath.c_str());
+ }
+ } else if (theType == DataModelDataType::StringRef) {
+ SStringRef theRef = get<SStringRef>(theValue);
+ SLong4 theGuid;
+ CUICDMInstanceHandle target = FindInstance(theRef.m_Id);
+ if (target.Valid())
+ theGuid = m_Editor.GetGuidForInstance(target);
+ theValue = theGuid;
+ }
+
+ // Note that we explicitly set the property values on the instance,
+ // not on any given slide.
+ m_Editor.SetSpecificInstancePropertyValue(
+ 0, hdl, ComposerPropertyNames::Convert(value.m_Name), theValue);
+ }
+ }
+ void AddChild(TImportId parent, TImportId child, TImportId inSibling) override
+ {
+ CUICDMInstanceHandle theParent(FindInstance(parent));
+ CUICDMInstanceHandle theChild(FindInstance(child));
+ CUICDMInstanceHandle theSibling(FindInstance(inSibling));
+
+ if (theParent.Valid() && theChild.Valid())
+ m_Editor.AddChild(theParent, theChild, theSibling);
+ }
+
+ void RemoveAnimation(TImportId inInstance, const wchar_t *propName, long propSubIndex) override
+ {
+ CUICDMInstanceHandle hdl(FindInstance(inInstance));
+ if (hdl.Valid())
+ m_Editor.RemoveAnimation(m_Slide, hdl, propName, propSubIndex);
+ }
+ void UpdateAnimation(TImportId inInstance, const wchar_t *propName, long propSubIndex,
+ EAnimationType animType, const float *animData, QT3DSU32 numFloats) override
+ {
+ CUICDMInstanceHandle hdl(FindInstance(inInstance));
+ if (hdl.Valid()) {
+ if (m_Editor.IsAnimationArtistEdited(m_Slide, hdl, propName, propSubIndex) == false) {
+ CUICDMAnimationHandle anim = m_Editor.CreateOrSetAnimation(
+ m_Slide, hdl, propName, propSubIndex, animType, animData, numFloats, false);
+ m_Editor.SetIsArtistEdited(anim, false);
+ }
+ }
+ }
+ void AddAnimation(TImportId inInstance, const wchar_t *propName, long propSubIndex,
+ EAnimationType animType, const float *animData, QT3DSU32 numFloats) override
+ {
+ UpdateAnimation(inInstance, propName, propSubIndex, animType, animData, numFloats);
+ }
+
+ void EndImport() override {}
+};
+
+struct SComposerRefreshInterface : public SComposerImportBase, public IComposerEditor
+{
+ TIdMultiMap &m_IdToSlideInstances;
+ bool m_HasError;
+ CGraph &m_AssetGraph;
+
+ struct SSlideInstanceIdMapIterator
+ {
+ const vector<pair<CUICDMSlideHandle, CUICDMInstanceHandle>> *m_CurrentItems;
+ size_t m_CurrentTreeIdx;
+ size_t m_CurrentTreeEnd;
+ TCharPtr m_Id;
+
+ SSlideInstanceIdMapIterator(TImportId inImportId, TIdMultiMap &inItems,
+ UICDM::IStringTable &inStringTable)
+ : m_CurrentItems(NULL)
+ , m_CurrentTreeIdx(0)
+ , m_CurrentTreeEnd(0)
+ , m_Id(inStringTable.RegisterStr(inImportId))
+ {
+ FindNextValidList(inItems);
+ }
+ void FindNextValidList(TIdMultiMap &inItems)
+ {
+ m_CurrentTreeIdx = 0;
+ m_CurrentTreeEnd = 0;
+ m_CurrentItems = NULL;
+ TIdMultiMap::const_iterator theFind = inItems.find(m_Id);
+ if (theFind != inItems.end()) {
+ m_CurrentItems = &theFind->second;
+ m_CurrentTreeIdx = 0;
+ m_CurrentTreeEnd = theFind->second.size();
+ }
+ }
+ bool IsDone() const
+ {
+ if (m_CurrentTreeIdx >= m_CurrentTreeEnd)
+ return true;
+ return false;
+ }
+ void Next()
+ {
+ if (m_CurrentTreeIdx < m_CurrentTreeEnd) {
+ ++m_CurrentTreeIdx;
+ }
+ }
+ CUICDMSlideHandle GetCurrentSlide() { return (*m_CurrentItems)[m_CurrentTreeIdx].first; }
+
+ CUICDMInstanceHandle GetCurrentInstance()
+ {
+ return (*m_CurrentItems)[m_CurrentTreeIdx].second;
+ }
+ };
+
+ SComposerRefreshInterface(Q3DStudio::IDocumentEditor &editor, TIdMultiMap &inIdToInstanceMap,
+ const Q3DStudio::CFilePath &docPath,
+ const Q3DStudio::CFilePath &inDestimportfile, long inStartTime,
+ UICDM::IStringTable &inStringTable, CGraph &inAssetGraph)
+ : SComposerImportBase(editor, docPath, inDestimportfile, inStartTime, inStringTable)
+ , m_IdToSlideInstances(inIdToInstanceMap)
+ , m_HasError(false)
+ , m_AssetGraph(inAssetGraph)
+ {
+ }
+
+ void Release() override {}
+ void BeginImport(Import &) override {}
+
+ void RemoveChild(TImportId inParentId, TImportId inChildId) override
+ {
+ for (SSlideInstanceIdMapIterator theIterator(inParentId, m_IdToSlideInstances,
+ m_StringTable);
+ theIterator.IsDone() == false; theIterator.Next()) {
+ CUICDMInstanceHandle theParent = theIterator.GetCurrentInstance();
+ for (long idx = 0; idx < m_AssetGraph.GetChildCount(theParent); ++idx) {
+ CUICDMInstanceHandle theChild = m_AssetGraph.GetChild(theParent, idx);
+ CString theImportId = m_Editor.GetImportId(theChild);
+ if (m_Editor.GetAssociatedSlide(theChild) == theIterator.GetCurrentSlide()
+ && theImportId == inChildId) {
+ m_Editor.RemoveChild(theParent, theChild);
+ --idx;
+ }
+ }
+ }
+ }
+
+ void RemoveInstance(TImportId inParentId) override
+ {
+ SSlideInstanceIdMapIterator theIterator(inParentId, m_IdToSlideInstances, m_StringTable);
+ if (!theIterator.IsDone()) {
+ for (size_t parentIdx = 0, parentEnd = theIterator.m_CurrentTreeEnd;
+ parentIdx < parentEnd; ++parentIdx) {
+ if (m_Editor.IsInstance(theIterator.GetCurrentInstance()))
+ m_Editor.DeleteInstance(theIterator.GetCurrentInstance());
+ }
+ m_IdToSlideInstances.erase(theIterator.m_Id);
+ }
+ }
+ /**
+ * Note that instance properties that point to files (sourcepath generally) point to files
+ * relative to the import file. You need to do combineBaseAndRelative with those files
+ * and the a new getRelativeFromBase with the final file in order to transfer data
+ * successfully. The time to do this sort of thing is upon create or update instance.
+ */
+ void CreateRootInstance(TImportId /*inImportId*/, ComposerObjectTypes::Enum /*type*/) override {}
+ // inParent may be null (or an invalid handle) if the instance doesn't have a parent (images)
+ void CreateInstance(TImportId inImportId, ComposerObjectTypes::Enum type,
+ TImportId inParent) override
+ {
+ const wchar_t *theInsertId(m_StringTable.GetWideStr(inImportId));
+ pair<TIdMultiMap::iterator, bool> theInserter(m_IdToSlideInstances.insert(
+ make_pair(theInsertId, vector<pair<CUICDMSlideHandle, CUICDMInstanceHandle>>())));
+
+ for (SSlideInstanceIdMapIterator theIterator(inParent, m_IdToSlideInstances, m_StringTable);
+ theIterator.IsDone() == false; theIterator.Next()) {
+ CUICDMInstanceHandle theParent = theIterator.GetCurrentInstance();
+ CUICDMInstanceHandle newInstance =
+ m_Editor.CreateSceneGraphInstance(type, theParent, theIterator.GetCurrentSlide());
+ if (m_StartTime >= 0)
+ m_Editor.SetSpecificInstancePropertyValue(0, newInstance, L"starttime",
+ m_StartTime);
+ m_Editor.SetSpecificInstancePropertyValue(0, newInstance, L"importid",
+ std::make_shared<CDataStr>(inImportId));
+ m_Editor.SetSpecificInstancePropertyValue(
+ 0, newInstance, L"importfile", std::make_shared<CDataStr>(m_Relativeimportfile));
+ insert_unique(theInserter.first->second,
+ make_pair(theIterator.GetCurrentSlide(), newInstance));
+ }
+ }
+
+ // We guarantee that all instances will be created before their properties are updated thus you
+ // can resolve references during this updateInstanceProperties call if necessary.
+ void UpdateInstanceProperties(TImportId inInstance, const PropertyValue *propertBuffer,
+ QT3DSU32 propertyBufferSize) override
+ {
+ for (SSlideInstanceIdMapIterator theIterator(inInstance, m_IdToSlideInstances,
+ m_StringTable);
+ theIterator.IsDone() == false; theIterator.Next()) {
+ CUICDMInstanceHandle hdl = theIterator.GetCurrentInstance();
+ for (QT3DSU32 idx = 0; idx < propertyBufferSize; ++idx) {
+ const PropertyValue &value(propertBuffer[idx]);
+ SValue theValue(value.m_Value);
+
+ DataModelDataType::Value theType = GetValueType(theValue);
+ if (value.m_Name == ComposerPropertyNames::sourcepath) {
+ // re-work the path to be relative to where the main document
+ // is saved instead of where the import result is saved
+ TDataStrPtr value = UICDM::get<TDataStrPtr>(theValue);
+ if (value->GetLength()) {
+ Q3DStudio::CString valueStr(value->GetData());
+ Q3DStudio::CFilePath fullPath =
+ Q3DStudio::CFilePath::CombineBaseAndRelative(m_DestImportDir, valueStr);
+ Q3DStudio::CString relativePath =
+ Q3DStudio::CFilePath::GetRelativePathFromBase(m_DocumentPath, fullPath);
+ theValue = std::make_shared<CDataStr>(relativePath.c_str());
+ }
+ } else if (theType == DataModelDataType::StringRef) {
+ SStringRef theRef = get<SStringRef>(theValue);
+ SLong4 theGuid;
+ // We are going to cheat here and look for a child of the current instance
+ // in the current slide who has the same import id;
+ for (long childIdx = 0, childCount = m_AssetGraph.GetChildCount(hdl);
+ childIdx < childCount; ++childIdx) {
+ CUICDMInstanceHandle target = m_AssetGraph.GetChild(hdl, childIdx);
+ if (m_Editor.GetAssociatedSlide(hdl) == theIterator.GetCurrentSlide()
+ && m_Editor.GetImportId(target).Compare(theRef.m_Id)) {
+ theGuid = m_Editor.GetGuidForInstance(target);
+ theValue = theGuid;
+ }
+ }
+ }
+ // Note that we explicitly set the property values on the instance,
+ // not on any given slide.
+ m_Editor.SetSpecificInstancePropertyValue(
+ 0, hdl, ComposerPropertyNames::Convert(value.m_Name), theValue);
+ }
+ }
+ }
+ // This is called even for new instances where we told you the parent because
+ // they may be out of order so if the child already has this parent relationship you need
+ // to check the order and ensure that is also (somewhat) correct.
+ void AddChild(TImportId parent, TImportId child, TImportId nextSiblingId) override
+ {
+ TIdMultiMap::iterator theParentList =
+ m_IdToSlideInstances.find(m_StringTable.RegisterStr(parent));
+ TIdMultiMap::iterator theChildList =
+ m_IdToSlideInstances.find(m_StringTable.RegisterStr(child));
+ if (theParentList == m_IdToSlideInstances.end()
+ || theChildList == m_IdToSlideInstances.end())
+ return;
+ size_t numItems = NVMin(theParentList->second.size(), theChildList->second.size());
+ for (size_t idx = 0; idx < numItems; ++idx) {
+ CUICDMSlideHandle theParentSlide = theParentList->second[idx].first;
+ CUICDMInstanceHandle theParent(theParentList->second[idx].second);
+ CUICDMInstanceHandle theChild(theChildList->second[idx].second);
+ CUICDMInstanceHandle nextSibling;
+ if (!IsTrivial(nextSiblingId)) {
+ for (long childIdx = 0, childCount = m_AssetGraph.GetChildCount(theParent);
+ childIdx < childCount; ++childIdx) {
+ CUICDMInstanceHandle theSibling = m_AssetGraph.GetChild(theParent, childIdx);
+ if (m_Editor.GetAssociatedSlide(theSibling) == theParentSlide
+ && m_Editor.GetImportId(theSibling).Compare(nextSiblingId)) {
+ nextSibling = theSibling;
+ break;
+ }
+ }
+ }
+ if (nextSibling.Valid())
+ m_AssetGraph.MoveBefore(theChild, nextSibling);
+ else
+ m_AssetGraph.MoveTo(theChild, theParent, COpaquePosition::LAST);
+ }
+ }
+
+ void RemoveAnimation(TImportId inInstance, const wchar_t *propName, long propSubIndex) override
+ {
+ for (SSlideInstanceIdMapIterator theIterator(inInstance, m_IdToSlideInstances,
+ m_StringTable);
+ theIterator.IsDone() == false; theIterator.Next())
+ m_Editor.RemoveAnimation(theIterator.GetCurrentSlide(),
+ theIterator.GetCurrentInstance(), propName, propSubIndex);
+ }
+ void UpdateAnimation(TImportId inInstance, const wchar_t *propName, long propSubIndex,
+ EAnimationType animType, const float *animData, QT3DSU32 numFloats) override
+ {
+ for (SSlideInstanceIdMapIterator theIterator(inInstance, m_IdToSlideInstances,
+ m_StringTable);
+ theIterator.IsDone() == false; theIterator.Next()) {
+ if (m_Editor.AnimationExists(theIterator.GetCurrentSlide(),
+ theIterator.GetCurrentInstance(), propName, propSubIndex)
+ && m_Editor.IsAnimationArtistEdited(theIterator.GetCurrentSlide(),
+ theIterator.GetCurrentInstance(), propName,
+ propSubIndex)
+ == false) {
+ CUICDMAnimationHandle anim = m_Editor.CreateOrSetAnimation(
+ theIterator.GetCurrentSlide(), theIterator.GetCurrentInstance(), propName,
+ propSubIndex, animType, animData, numFloats, false);
+ m_Editor.SetIsArtistEdited(anim, false);
+ }
+ }
+ }
+
+ void AddAnimation(TImportId inInstance, const wchar_t *propName, long propSubIndex,
+ EAnimationType animType, const float *animData, QT3DSU32 numFloats) override
+ {
+ for (SSlideInstanceIdMapIterator theIterator(inInstance, m_IdToSlideInstances,
+ m_StringTable);
+ theIterator.IsDone() == false; theIterator.Next()) {
+ if (!m_Editor.AnimationExists(theIterator.GetCurrentSlide(),
+ theIterator.GetCurrentInstance(), propName,
+ propSubIndex)) {
+ CUICDMAnimationHandle anim = m_Editor.CreateOrSetAnimation(
+ theIterator.GetCurrentSlide(), theIterator.GetCurrentInstance(), propName,
+ propSubIndex, animType, animData, numFloats, false);
+ m_Editor.SetIsArtistEdited(anim, false);
+ }
+ }
+ }
+
+ void EndImport() override {}
+};
+}
+
+std::shared_ptr<IComposerEditorInterface> IComposerEditorInterface::CreateEditorInterface(
+ Q3DStudio::IDocumentEditor &editor, UICDM::CDataModelHandle parent // Parent object
+ ,
+ UICDM::CDataModelHandle root, UICDM::CUICDMSlideHandle slide,
+ const Q3DStudio::CFilePath &docPath, const Q3DStudio::CFilePath &destimportfile,
+ long inStartTime, UICDM::IStringTable &inStringTable)
+{
+ return std::make_shared<SComposerImportInterface>(std::ref(editor), parent, root, slide,
+ docPath, destimportfile, inStartTime,
+ std::ref(inStringTable));
+}
+
+// The refresh interface is setup to refresh multiple trees automatically
+std::shared_ptr<IComposerEditor> IComposerEditorInterface::CreateEditorInterface(
+ Q3DStudio::IDocumentEditor &editor, TIdMultiMap &inRoots, const Q3DStudio::CFilePath &docPath,
+ const Q3DStudio::CFilePath &destimportfile, long inStartTime,
+ UICDM::IStringTable &inStringTable, CGraph &inAssetGraph)
+{
+ return std::make_shared<SComposerRefreshInterface>(
+ std::ref(editor), std::ref(inRoots), docPath, destimportfile, inStartTime,
+ std::ref(inStringTable), std::ref(inAssetGraph));
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.cpp b/src/Authoring/Client/Code/Core/Doc/Doc.cpp
new file mode 100644
index 00000000..9b3ab1f4
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/Doc.cpp
@@ -0,0 +1,2869 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICOptions.h"
+#include "Doc.h"
+#include "Core.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMActionCore.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+#include "UICDMSignals.h"
+#include "IKeyframesManager.h"
+#include "FileInputStream.h"
+#include "FileOutputStream.h"
+#include "BufferedInputStream.h"
+#include "BufferedOutputStream.h"
+#include "FormattedInputStream.h"
+#include "FormattedOutputStream.h"
+#include "DataModelObjectReferenceHelper.h"
+#include "MasterP.h"
+#include "Dispatch.h"
+#include "Exceptions.h"
+#include "StudioClipboard.h"
+#include "HotKeys.h"
+#include "StudioProjectSettings.h"
+#include "StudioPreferences.h"
+#include "StudioFullSystem.h"
+#include "UICDMDataCore.h"
+#include "CmdDataModelDeleteInstance.h"
+#include "PlaybackClock.h"
+#include "ColorConversion.h"
+#include "WGLRenderContext.h"
+#include "IDocumentEditor.h"
+#include "IDocumentBufferCache.h"
+#include "StudioCoreSystem.h"
+#include "UICDMXML.h"
+#include "foundation/IOStreams.h"
+#include "UICDMWStrOpsImpl.h"
+#include "IComposerSerializer.h"
+#include "UICFileTools.h"
+#include "ProjectSettingsSerializer.h"
+#include "CmdBatch.h"
+#include "IDirectoryWatchingSystem.h"
+#include "StandardExtensions.h"
+#include "IDocSceneGraph.h"
+#include "UICTextRenderer.h"
+#include "SelectedValueImpl.h"
+#include "UICRenderPathManager.h"
+#include "EASTL/sort.h"
+#include "foundation/Qt3DSLogging.h"
+
+#include <QtCore/qfileinfo.h>
+
+using std::ref;
+using std::shared_ptr;
+
+//==============================================================================
+// Constants
+//==============================================================================
+const long STUDIO_FILE_VERSION = 3;
+const long STUDIO_LAST_SUPPORTED_FILE_VERSION = 1;
+
+IMPLEMENT_OBJECT_COUNTER(CDoc)
+
+struct SDocTransactionCommand : public CCmd
+{
+ QString m_CommandName;
+ std::shared_ptr<UICDM::CmdDataModel> m_DataModelTransactions;
+ bool m_DoneOnce;
+ CDispatch &m_Dispatch;
+
+ SDocTransactionCommand(std::shared_ptr<UICDM::CmdDataModel> dmt,
+ const QString &cmdName, CDispatch &dispatch)
+ : m_CommandName(cmdName)
+ , m_DataModelTransactions(dmt)
+ , m_DoneOnce(false)
+ , m_Dispatch(dispatch)
+ {
+ m_ShouldSetModified = false;
+ }
+
+ ECmdType GetType() override { return CCmd::GENERIC; }
+
+ unsigned long Do() override
+ {
+ if (!m_DoneOnce) {
+ m_DataModelTransactions->RunDoNotifications();
+ } else {
+ if (m_DataModelTransactions) {
+ CDispatchDataModelNotificationScope __dispatchScope(m_Dispatch);
+ m_DataModelTransactions->DataModelRedo();
+ }
+ }
+ m_DoneOnce = true;
+
+ return 0;
+ }
+ unsigned long Undo() override
+ {
+ if (m_DataModelTransactions) {
+ CDispatchDataModelNotificationScope __dispatchScope(m_Dispatch);
+ m_DataModelTransactions->DataModelUndo();
+ }
+ return 0;
+ }
+
+ QString ToString() override { return m_CommandName; }
+};
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CDoc::CDoc(CCore *inCore)
+ : m_PlayMode(PLAYMODE_STOP)
+ , m_CurrentViewTime(0)
+ , m_ActiveLayer(0)
+ , m_Core(NULL)
+ , m_IsModified(false)
+ , m_IsTemporary(true)
+ , m_DocumentPath("")
+ , m_DataManager(NULL)
+ , m_KeyframesManager(NULL)
+ , m_DataModelObjectRefHelper(NULL)
+ , m_AssetGraph(TAssetGraphPtr())
+ , m_TransactionDepth(0)
+ , m_RenderContext(NULL)
+ , m_WindowHandle(NULL)
+{
+ ADDTO_OBJECT_COUNTER(CDoc)
+
+ m_DataModelObjectRefHelper = new CObjectReferenceHelper(this);
+
+ m_PlaybackClock = new CPlaybackClock(this);
+
+ m_Core = inCore;
+}
+
+//==============================================================================
+/**
+* Destructor
+*/
+CDoc::~CDoc()
+{
+ REMOVEFROM_OBJECT_COUNTER(CDoc)
+
+ m_SelectedObject = Q3DStudio::SSelectedValue(); // because on shutdown, the selected object ptr
+ // cannot be assumed to be valid.
+ CleanupData();
+
+ ClosePresentation();
+
+ if (m_SceneInstance.Valid()) {
+ m_AssetGraph->RemoveNode(m_SceneInstance);
+ m_SceneInstance = 0;
+ }
+
+ // Destroy Asset Graph
+ m_AssetGraph = TAssetGraphPtr();
+
+ delete m_DataModelObjectRefHelper;
+ delete m_PlaybackClock;
+}
+
+//=============================================================================
+/**
+ * Set the state of this document as being modified or not.
+ * This should affect the closing/saving of the core.
+ */
+void CDoc::SetModifiedFlag(bool inIsModified)
+{
+ m_IsModified = inIsModified;
+}
+
+void CDoc::SetKeyframesManager(IKeyframesManager *inManager)
+{
+ m_KeyframesManager = inManager;
+}
+
+IKeyframesManager *CDoc::GetKeyframesManager()
+{
+ return m_KeyframesManager;
+}
+
+UICDM::IAnimationCore *CDoc::GetAnimationCore()
+{
+ return GetStudioSystem()->GetAnimationCore();
+}
+
+UICDM::IPropertySystem *CDoc::GetPropertySystem()
+{
+ return GetStudioSystem()->GetPropertySystem();
+}
+
+void CDoc::SetInstancePropertyValue(UICDM::CUICDMInstanceHandle inInstance,
+ const std::wstring &inPropertyName,
+ const UICDM::SValue &inValue)
+{
+ UICDM::IPropertySystem *thePropertySystem = GetStudioSystem()->GetPropertySystem();
+ UICDM::CUICDMPropertyHandle theProperty =
+ thePropertySystem->GetAggregateInstancePropertyByName(inInstance, inPropertyName.c_str());
+ if (theProperty.Valid())
+ thePropertySystem->SetInstancePropertyValue(inInstance, theProperty, inValue);
+}
+
+Q3DStudio::IDocumentBufferCache &CDoc::GetBufferCache()
+{
+ if (!m_DocumentBufferCache)
+ m_DocumentBufferCache = Q3DStudio::IDocumentBufferCache::CreateBufferCache(*this);
+ return *m_DocumentBufferCache.get();
+}
+
+Q3DStudio::IDocumentReader &CDoc::GetDocumentReader()
+{
+ if (!m_SceneEditor)
+ m_SceneEditor = Q3DStudio::IInternalDocumentEditor::CreateEditor(*this);
+ return *m_SceneEditor;
+}
+
+Q3DStudio::IDocumentEditor &CDoc::OpenTransaction(const Q3DStudio::CString &inCmdName,
+ const char *inFile, int inLine)
+{
+ ++m_TransactionDepth;
+ if (m_TransactionDepth == 1) {
+ assert(!m_OpenTransaction);
+ m_OpenTransaction = std::make_shared<UICDM::CmdDataModel>(std::ref(*this));
+ m_OpenTransaction->SetName(inCmdName);
+ m_OpenTransaction->SetConsumer();
+ m_Core->SetCommandStackModifier(this);
+ qCInfo(qt3ds::TRACE_INFO) << inFile << "(" << inLine << "): Transaction opened: "
+ << inCmdName.toQString();
+ m_OpenTransaction->m_File = inFile;
+ m_OpenTransaction->m_Line = inLine;
+ CCmdStack *theCommandStack = m_Core->GetCmdStack();
+ if (theCommandStack)
+ theCommandStack->EmptyRedoStack();
+ } else
+ qCInfo(qt3ds::TRACE_INFO) << inFile << "(" << inLine << "): Open Transaction: "
+ << inCmdName.toQString();
+
+ if (!m_SceneEditor) {
+ m_SceneEditor = Q3DStudio::IInternalDocumentEditor::CreateEditor(*this);
+ }
+ return *m_SceneEditor;
+}
+
+Q3DStudio::IDocumentEditor &CDoc::MaybeOpenTransaction(const Q3DStudio::CString &cmdName,
+ const char *inFile, int inLine)
+{
+ if (!m_OpenTransaction)
+ return OpenTransaction(cmdName, inFile, inLine);
+ return *m_SceneEditor;
+}
+
+bool CDoc::IsTransactionOpened() const
+{
+ return m_OpenTransaction ? true : false;
+}
+
+void CDoc::RollbackTransaction()
+{
+ if (m_OpenTransaction)
+ m_OpenTransaction->DataModelRollback();
+}
+
+void CDoc::CloseTransaction()
+{
+ if (m_TransactionDepth) {
+ --m_TransactionDepth;
+ if (m_TransactionDepth == 0) {
+ assert(m_OpenTransaction);
+ IKnowWhatIAmDoingForceCloseTransaction();
+ }
+ }
+}
+
+void CDoc::IKnowWhatIAmDoingForceCloseTransaction()
+{
+ if (m_OpenTransaction) {
+ qCInfo(qt3ds::TRACE_INFO) << "Closing transaction";
+ // Ensure hasTransaction will return false right at this second.
+ std::shared_ptr<UICDM::CmdDataModel> theTransaction(m_OpenTransaction);
+ m_OpenTransaction = std::shared_ptr<UICDM::CmdDataModel>();
+
+ m_Core->SetCommandStackModifier(NULL);
+ // Release the consumer without running notifications because our command will run
+ // the notifications when it first gets executed.
+ theTransaction->ReleaseConsumer(false);
+ if (theTransaction->HasTransactions()) {
+ SDocTransactionCommand *newCommand = new SDocTransactionCommand(
+ theTransaction, theTransaction->GetName().toQString(), *m_Core->GetDispatch());
+ // Execute the command synchronously. If you are getting crashes due to UI refreshes
+ // then
+ // you need to run your entire change system in a postmessage of some sort.
+ m_Core->ExecuteCommand(newCommand);
+ }
+ qCInfo(qt3ds::TRACE_INFO) << theTransaction->m_File.GetCharStar() << "("
+ << theTransaction->m_Line << "): Transaction closed";
+ }
+ m_TransactionDepth = 0;
+}
+
+bool CDoc::CanUndo()
+{
+ return (m_OpenTransaction != nullptr);
+}
+
+bool CDoc::PreUndo()
+{
+ if (m_OpenTransaction && m_OpenTransaction->HasTransactions()) {
+ qCInfo(qt3ds::TRACE_INFO) << "PreUndo begin";
+ const Q3DStudio::CString theCommandName(m_OpenTransaction->GetName());
+ // In this case we want the command to absolutely immediately commit; we don't want it
+ // to wait until a further post message else the previous command is the one that will get
+ // undone.
+ IKnowWhatIAmDoingForceCloseTransaction();
+ qCInfo(qt3ds::TRACE_INFO) << "PreUndo end";
+ return true;
+ }
+ return false;
+}
+
+void CDoc::GetOrUpdateFileList(std::vector<Q3DStudio::CString> &ioMyList,
+ std::vector<Q3DStudio::CString> &outResult,
+ const wchar_t **inExtensionList) const
+{
+ if (ioMyList.empty()) {
+ Q3DStudio::CFilePath dirPath(GetDocumentPath().GetAbsolutePath());
+ dirPath = dirPath.GetDirectory();
+ std::vector<Q3DStudio::CFilePath> files;
+ dirPath.RecursivelyFindFilesOfType(inExtensionList, files, true);
+ for (size_t idx = 0, end = files.size(); idx < end; ++idx)
+ ioMyList.push_back(files[idx]);
+ }
+ outResult = ioMyList;
+}
+
+//=============================================================================
+/**
+ * Check to see if this document has been modified since the last save.
+ */
+bool CDoc::IsModified()
+{
+ return m_IsModified;
+}
+
+bool CDoc::IsValid() const
+{
+ return !m_DocumentPath.GetPath().IsEmpty();
+}
+//=============================================================================
+/**
+ * Get the Asset from inSelectedItem, if exists
+ */
+UICDM::CUICDMInstanceHandle
+CDoc::GetInstanceFromSelectable(Q3DStudio::SSelectedValue inSelectedItem)
+{
+ if (inSelectedItem.getType() == Q3DStudio::SelectedValueTypes::Instance) {
+ // This is UICDM asset. Find corresponding CAsset if there is any
+ return inSelectedItem.getData<UICDM::CUICDMInstanceHandle>();
+ } else if (inSelectedItem.getType() == Q3DStudio::SelectedValueTypes::MultipleInstances) {
+ const UICDM::TInstanceHandleList &theData =
+ *inSelectedItem.getDataPtr<UICDM::TInstanceHandleList>();
+ if (theData.empty() == false)
+ return theData[0];
+ }
+
+ return 0;
+}
+
+UICDM::CUICDMInstanceHandle CDoc::GetSelectedInstance()
+{
+ return GetInstanceFromSelectable(m_SelectedObject);
+}
+
+CCore *CDoc::GetCore()
+{
+ return m_Core;
+}
+
+//=============================================================================
+/**
+ * Calls NotifyActiveSlideChanged( UICDM::CUICDMSlideHandle inNewActiveSlide, bool
+ *inForceRefresh )
+ * Could not make this on optional param because someone is calling from CGenericCmd that
+ * seems to only allow 1 param.
+ */
+void CDoc::NotifyActiveSlideChanged(UICDM::CUICDMSlideHandle inNewActiveSlide)
+{
+ NotifyActiveSlideChanged(inNewActiveSlide, false);
+}
+
+void CDoc::SetActiveSlideChange(UICDM::CUICDMSlideHandle inNewActiveSlide)
+{
+ if (!inNewActiveSlide.Valid())
+ inNewActiveSlide = GetActiveSlide();
+
+ if (m_ActiveSlide != inNewActiveSlide) {
+ // Ensure that events are batched if they aren't already
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Core->GetDispatch());
+ ASSERT(inNewActiveSlide.Valid());
+
+ m_ActiveSlide = inNewActiveSlide;
+
+ DeselectAllItems(false);
+ m_ActiveLayer = 0;
+
+ UICDM::ISlideSystem *theSlideSystem = m_StudioSystem->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theMasterSlide = theSlideSystem->GetMasterSlide(inNewActiveSlide);
+
+ long theNewIndex = theSlideSystem->GetSlideIndex(inNewActiveSlide);
+ theSlideSystem->SetActiveSlide(theMasterSlide, theNewIndex);
+
+ m_PlaybackClock->Reset();
+
+ // Disable the active layer and set it lazily.
+
+ // Set active slide to UICDM
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the active slide for the document.
+ * The active slide is used for when something other than the Scene is
+ * acting as the root of the presentation, as when delving into a component
+ * or such.
+ *
+ * When changing time contexts (master slides):
+ * Go to the last-edited/currently displayed slide of that context (default: Slide1)
+ * Select whatever was last selected in that context (default: the context element itself)
+ *
+ * When clicking on a slide:
+ * If the clicked-on slide is the current slide, select and inspect the time context itself
+ * If the clicked-on slide is different:
+ * If the was-selected item was non-master, select and inspect the time context itself
+ * If the was-selected item was master, continue to leave that item selected and inspected.
+ *
+ * @param inNewActiveSlide the new slide handle to be the active root of the doc.
+ * @param inForceRefresh forces a refresh of the active time context no matter what, if the
+ * inNewRoot is NULL and this is true, then it will refresh the active time context
+ * @param inIgnoreLastDisplayTime false to always restore the last displayed time when this context
+ * was active. E.g. when this would be true is when we are playing through, time should always start
+ * from 0 then.
+ */
+void CDoc::NotifyActiveSlideChanged(UICDM::CUICDMSlideHandle inNewActiveSlide, bool inForceRefresh,
+ bool inIgnoreLastDisplayTime /*= false */)
+{
+ using namespace UICDM;
+
+ UICDM::CUICDMSlideHandle theLastActiveSlide = m_ActiveSlide;
+
+ // Record the last selected object in that slide
+ ISlideSystem *theSlideSystem = GetStudioSystem()->GetSlideSystem();
+ theSlideSystem->SetSlideSelectedInstance(theLastActiveSlide, GetSelectedInstance());
+ UICDM::CUICDMInstanceHandle theNextSelectedInstance = GetSelectedInstance();
+
+ // If we are forcing a refresh. and the incoming root is not valid, use the existing active time
+ // context
+ if (!inNewActiveSlide.Valid())
+ inNewActiveSlide = GetActiveSlide();
+
+ // We have a new root context
+ if (inForceRefresh || theLastActiveSlide != inNewActiveSlide) {
+ ASSERT(inNewActiveSlide.Valid());
+
+ // Notify the system of a slide change. Do it.
+ if (theLastActiveSlide != inNewActiveSlide) {
+ SetActiveSlideChange(inNewActiveSlide);
+ if (inIgnoreLastDisplayTime)
+ m_StudioSystem->GetSlideSystem()->SetComponentSeconds(
+ m_StudioSystem->GetSlideSystem()->GetMasterSlide(inNewActiveSlide), 0);
+ }
+
+ CUICDMSlideHandle theLastMasterSlide =
+ m_StudioSystem->GetSlideSystem()->GetMasterSlide(theLastActiveSlide);
+ CUICDMSlideHandle theNewMasterSlide =
+ m_StudioSystem->GetSlideSystem()->GetMasterSlide(inNewActiveSlide);
+
+ int theIndex = m_StudioSystem->GetSlideSystem()->GetSlideIndex(inNewActiveSlide);
+ m_StudioSystem->GetFullSystem()->GetSignalSender()->SendActiveSlide(
+ theNewMasterSlide, theIndex, inNewActiveSlide);
+
+ // If the slide *did* change then we have some somewhat complex logic
+ // If we didn't change time contexts...
+ if (theLastMasterSlide == theNewMasterSlide) {
+ // If we are reselecting the current slide, select the component.
+ if (theLastActiveSlide == inNewActiveSlide)
+ theNextSelectedInstance = 0;
+
+ if (theNextSelectedInstance.Valid()) {
+ // Discard selected instance if nonmaster
+ if (theNewMasterSlide
+ != GetDocumentReader().GetAssociatedSlide(theNextSelectedInstance))
+ theNextSelectedInstance = 0;
+ }
+ }
+ // If we did change time contexts
+ else {
+ theNextSelectedInstance = theSlideSystem->GetSlideSelectedInstance(inNewActiveSlide);
+ // If nothing was selected, then select the component.
+ }
+
+ if (theNextSelectedInstance.Valid() == false)
+ theNextSelectedInstance = GetDocumentReader().GetComponentForSlide(inNewActiveSlide);
+
+ SelectUICDMObject(theNextSelectedInstance);
+ }
+}
+
+//=============================================================================
+/**
+ * @returns the first enabled layer in the active time context
+ */
+UICDM::CUICDMInstanceHandle CDoc::GetFirstSelectableLayer()
+{
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+
+ Q3DStudio::CGraphIterator theLayers;
+ GetAssetChildrenInSlide(this, m_SceneInstance,
+ theBridge->GetComponentActiveSlide(m_SceneInstance), theLayers,
+ OBJTYPE_LAYER);
+
+ UICDM::CUICDMInstanceHandle theFoundLayer = 0;
+
+ for (; !theLayers.IsDone(); ++theLayers) {
+ if (!theBridge->IsLockedAtAll(theLayers.GetCurrent())
+ && m_StudioSystem->IsInstance(theLayers.GetCurrent())) {
+ theFoundLayer = theLayers.GetCurrent();
+ break;
+ }
+ }
+
+ return theFoundLayer;
+}
+
+UICDM::CUICDMInstanceHandle CDoc::GetActiveRootInstance()
+{
+ if (m_ActiveSlide.Valid())
+ return m_StudioSystem->GetClientDataModelBridge()->GetOwningComponentInstance(
+ m_ActiveSlide);
+ return m_SceneInstance;
+}
+
+//=============================================================================
+/**
+ * Returns the current active slide
+ * The timeline is always displaying the active root.
+ */
+UICDM::CUICDMSlideHandle CDoc::GetActiveSlide()
+{
+ if (m_ActiveSlide.Valid())
+ return m_ActiveSlide;
+ if (m_SceneInstance.Valid())
+ return m_StudioSystem->GetClientDataModelBridge()->GetComponentSlide(m_SceneInstance, 0);
+ ASSERT(false); // something is wrong if m_SceneInstance is not valid
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Get the currently active layer.
+ * The active layer is the layer of the last selected asset or the first enabled layer after
+ * the slide is switched and is held onto mainly for determining which layer
+ * to drop an object onto when dropping on the scene.
+ */
+UICDM::CUICDMInstanceHandle CDoc::GetActiveLayer()
+{
+ if (m_ActiveLayer.Valid() == false)
+ m_ActiveLayer = GetFirstSelectableLayer();
+ return m_ActiveLayer;
+}
+
+//=============================================================================
+/**
+ * Set the currently active layer.
+ * The active layer is the layer of the last selected asset or the first enabled layer after
+ * the slide is switched and is held onto mainly for determining which layer
+ * to drop an object onto when dropping on the scene.
+ */
+void CDoc::SetActiveLayer(UICDM::CUICDMInstanceHandle inLayerInstance)
+{
+ m_ActiveLayer = inLayerInstance;
+}
+
+//=============================================================================
+/**
+ * Informs that a layer has been deleted. If this is the active one, try to promote another.
+ */
+
+void CDoc::OnLayerDeleted(UICDM::CUICDMInstanceHandle inLayerInstance)
+{
+ if (m_ActiveLayer == inLayerInstance)
+ m_ActiveLayer = 0;
+}
+
+//=============================================================================
+/**
+ * Deselects all the items and keyframes that are currently selected.
+ */
+void CDoc::DeselectAllItems(bool inSendEvent)
+{
+ if (inSendEvent)
+ NotifySelectionChanged();
+ else
+ SetSelection();
+
+ // Remove selection on keyframes.
+ DeselectAllKeyframes();
+}
+
+//=============================================================================
+/**
+ * Cuts the selected object
+ */
+void CDoc::CutSelectedObject()
+{
+ CutObject(m_SelectedValue.GetSelectedInstances());
+}
+
+void CDoc::CutObject(UICDM::TInstanceHandleList inInstances)
+{
+ if (CHotKeys::isFocusOnTextEditControl())
+ return;
+ if (inInstances.empty())
+ return;
+ bool theContinueCutFlag = true;
+ for (size_t idx = 0, end = inInstances.size(); idx < end && theContinueCutFlag; ++idx) {
+ UICDM::CUICDMInstanceHandle inInstance(inInstances[idx]);
+ if (!GetDocumentReader().IsInstance(inInstance))
+ return;
+
+ // Build the list of targets
+ Q3DStudio::CString theListOfTargets;
+ GetActionDependencies(inInstance, theListOfTargets);
+
+ if (!theListOfTargets.IsEmpty()) {
+ if (m_DeletingReferencedObjectHandler)
+ m_DeletingReferencedObjectHandler->DisplayMessageBox(theListOfTargets);
+ // theContinueCutFlag = false;
+ }
+ }
+ using namespace Q3DStudio;
+
+ if (theContinueCutFlag) {
+ CFilePath thePath(GetDocumentReader().CopySceneGraphObjects(inInstances));
+ CUICFile theFile(thePath);
+ CStudioClipboard::CopyObjectToClipboard(
+ theFile, false, false,
+ m_StudioSystem->GetClientDataModelBridge()->GetObjectType(inInstances[0]));
+ SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Cut Object"))->DeleteInstances(inInstances);
+ }
+}
+
+void CDoc::CopyObject(UICDM::TInstanceHandleList inInstances)
+{
+ if (CHotKeys::isFocusOnTextEditControl())
+ return;
+ if (inInstances.empty())
+ return;
+ using namespace Q3DStudio;
+ CFilePath thePath(GetDocumentReader().CopySceneGraphObjects(inInstances));
+ CUICFile theFile(thePath);
+ CStudioClipboard::CopyObjectToClipboard(
+ theFile, false, false,
+ m_StudioSystem->GetClientDataModelBridge()->GetObjectType(inInstances[0]));
+}
+
+void CDoc::PasteObject(UICDM::CUICDMInstanceHandle inInstance)
+{
+ using namespace Q3DStudio;
+ UICDM::CUICDMInstanceHandle theInstance(inInstance);
+ qint64 dummy = 0;
+ CUICFile theTempAPFile = CStudioClipboard::GetObjectFromClipboard(false, dummy);
+ SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Paste Object"))
+ ->PasteSceneGraphObject(theTempAPFile.GetAbsolutePath(), theInstance, true,
+ DocumentEditorInsertType::LastChild, CPt());
+}
+
+void CDoc::PasteObjectMaster(UICDM::CUICDMInstanceHandle inInstance)
+{
+ using namespace Q3DStudio;
+ UICDM::CUICDMInstanceHandle theInstance(inInstance);
+ qint64 dummy = 0;
+ CUICFile theTempAPFile = CStudioClipboard::GetObjectFromClipboard(false, dummy);
+ SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Paste Object"))
+ ->PasteSceneGraphObjectMaster(theTempAPFile.GetAbsolutePath(), theInstance, true,
+ DocumentEditorInsertType::LastChild, CPt());
+}
+
+//=============================================================================
+/**
+ * Deletes the selected object
+ */
+void CDoc::DeleteSelectedObject()
+{
+ UICDM::TInstanceHandleList theSelectedHandles = m_SelectedValue.GetSelectedInstances();
+ if (!theSelectedHandles.empty()) {
+ DeleteObject(theSelectedHandles);
+ }
+}
+
+void CDoc::DeleteObject(const UICDM::TInstanceHandleList &inInstances)
+{
+
+ // We don't deselect all items because that will happen
+ // automagically because we are listening to the events coming out
+ // of the system around delete.
+ DeselectAllKeyframes();
+
+ CClientDataModelBridge *theClientBridge = GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::TInstanceHandleList deletableInstances;
+ for (size_t idx = 0, end = inInstances.size(); idx < end; ++idx) {
+
+ // find all the custom items created for it and remove it all
+ if (theClientBridge->CanDelete(inInstances[idx])) {
+ Q3DStudio::CString theListOfTargets;
+ GetActionDependencies(inInstances[idx], theListOfTargets);
+
+ if (!theListOfTargets.IsEmpty()) {
+ if (m_DeletingReferencedObjectHandler)
+ m_DeletingReferencedObjectHandler->DisplayMessageBox(theListOfTargets);
+ }
+
+ deletableInstances.push_back(inInstances[idx]);
+ }
+ }
+
+ if (deletableInstances.empty() == false) {
+ NotifySelectionChanged();
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Delete"))->DeleteInstances(deletableInstances);
+ }
+}
+
+//=============================================================================
+/**
+ * Checks and return a string of objects that have actions referencing inAsset.
+ * @inAsset The asset to check for dependencies.
+ * @ioActionDependencies String representation of objects that have actions referencing it.
+ */
+void CDoc::GetActionDependencies(UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CString &ioActionDependencies)
+{
+ // Step 1 : Get all actions affecting myself and all my descendents
+ UICDM::TActionHandleList theAffectedActions;
+ GetActionDependencies(inInstance, theAffectedActions);
+
+ // Set of unique owner names
+ typedef std::set<Q3DStudio::CString> TActionOwners;
+ TActionOwners theActionOwners;
+
+ UICDM::IActionCore *theActionCore = m_StudioSystem->GetActionCore();
+ UICDM::TActionHandleList::iterator thePos = theAffectedActions.begin();
+ UICDM::TActionHandleList::iterator theEnd = theAffectedActions.end();
+
+ // Filter away those actions that is owned by myself or my descendants, which anyway the
+ // actions are going away too.
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ for (; thePos != theEnd; ++thePos) {
+ const UICDM::SActionInfo &theActionInfo = theActionCore->GetActionInfo(*thePos);
+ UICDM::CUICDMInstanceHandle theOwnerHandle = theActionInfo.m_Owner;
+
+ if (theOwnerHandle != inInstance && theOwnerHandle.Valid()
+ && !IsAscendant(theOwnerHandle, inInstance, m_AssetGraph))
+ theActionOwners.insert(theBridge->GetName(theOwnerHandle));
+ }
+
+ // Iterate the set and form the output string
+ TActionOwners::iterator theActionOwnersPos = theActionOwners.begin();
+ TActionOwners::iterator theActionOwnersEnd = theActionOwners.end();
+ for (; theActionOwnersPos != theActionOwnersEnd; ++theActionOwnersPos) {
+ if (ioActionDependencies.IsEmpty())
+ ioActionDependencies += *theActionOwnersPos;
+ else
+ ioActionDependencies += ", " + *theActionOwnersPos;
+ }
+}
+
+//=============================================================================
+/**
+ * Checks and return a string of objects that have actions referencing inAsset.
+ * @inAsset The asset to check for dependencies.
+ * @ioActionList List of actions.
+ */
+void CDoc::GetActionDependencies(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::TActionHandleList &ioActionList)
+{
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ theBridge->GetReferencedActions(
+ inInstance, UICDM::REFERENCED_AS_TRIGGER | UICDM::REFERENCED_AS_TARGET, ioActionList);
+
+ Q3DStudio::CGraphIterator theChildren;
+ GetAssetChildren(this, inInstance, theChildren);
+ for (; !theChildren.IsDone(); ++theChildren) {
+ GetActionDependencies(theChildren.GetCurrent(), ioActionList);
+ }
+}
+
+//=============================================================================
+/**
+ * Deletes the selected items, this is the primary handler of the delete key.
+ */
+void CDoc::DeleteSelectedItems()
+{
+ // If there are keyframes selected, delete them
+ if (!DeleteSelectedKeys()) {
+ // If there are no keyframes selected, delete whatever asset is selected
+ DeleteSelectedObject();
+ }
+}
+
+//=============================================================================
+/**
+ * Only deletes keyframes, this is useful for when you don't wanna chekc objects
+ */
+bool CDoc::DeleteSelectedKeys()
+{
+ if (m_KeyframesManager)
+ return m_KeyframesManager->RemoveKeyframes(false);
+
+ return false;
+}
+
+//=============================================================================
+/**
+ * Sets keyframes on all the changed properties of the selected object.
+ */
+void CDoc::SetChangedKeyframes()
+{
+ if (m_KeyframesManager)
+ m_KeyframesManager->SetChangedKeyframes();
+}
+
+bool CDoc::SetSelection(Q3DStudio::SSelectedValue inNewSelection)
+{
+ if (inNewSelection != m_SelectedObject) {
+ UICDM::CUICDMInstanceHandle theNewSelectedInstance =
+ GetInstanceFromSelectable(inNewSelection);
+
+ if (theNewSelectedInstance.Valid()) {
+ // Do not allow selection if asset is locked.
+ if (m_StudioSystem->GetClientDataModelBridge()->IsLockedAtAll(theNewSelectedInstance))
+ return false; // bail!
+ }
+ m_SelectedObject = inNewSelection;
+
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+
+ // Handle CAsset's specific code
+ if (theNewSelectedInstance.Valid()) {
+ // Check if we do not select a SlideInspectable. Refer to
+ // CStudioApp::GetInspectableFromSelectable.
+ UICDM::CUICDMSlideHandle theCurrentActiveSlide = GetActiveSlide();
+ if (theNewSelectedInstance
+ != theBridge->GetOwningComponentInstance(theCurrentActiveSlide)) {
+ // If the newly selected object is in the scene then make the layer it belongs to
+ // the 'active' layer.
+ UICDM::CUICDMInstanceHandle theActiveLayer = 0;
+
+ UICDM::CUICDMInstanceHandle theSelectedInstance = GetSelectedInstance();
+ theActiveLayer = theBridge->GetResidingLayer(theSelectedInstance);
+
+ if (theActiveLayer.Valid() && theBridge->IsLockedAtAll(theActiveLayer))
+ theActiveLayer = 0;
+
+ if (!theActiveLayer.Valid())
+ theActiveLayer = GetFirstSelectableLayer();
+
+ if (theActiveLayer.Valid() && theBridge->IsLockedAtAll(theActiveLayer))
+ theActiveLayer = 0;
+
+ SetActiveLayer(theActiveLayer);
+ }
+ }
+
+ return true;
+ }
+ return false;
+}
+
+void CDoc::NotifySelectionChanged(Q3DStudio::SSelectedValue inNewSelection)
+{
+ m_SelectedValue = inNewSelection;
+ if (SetSelection(inNewSelection)) {
+ m_Core->GetDispatch()->FireSelectionChange(inNewSelection);
+ }
+}
+
+template <typename TDataType>
+struct SReferenceTransaction : public UICDM::ITransaction
+{
+ TDataType &m_TargetData;
+ TDataType m_OldData;
+ TDataType m_NewData;
+ SReferenceTransaction(const char *inFile, int inLine, TDataType &inTarget, TDataType inOldData,
+ TDataType inNewData)
+ : ITransaction(inFile, inLine)
+ , m_TargetData(inTarget)
+ , m_OldData(inOldData)
+ , m_NewData(inNewData)
+ {
+ }
+ void Do() override { m_TargetData = m_NewData; }
+ void Undo() override { m_TargetData = m_OldData; }
+};
+
+void CDoc::SetActiveSlideWithTransaction(UICDM::CUICDMSlideHandle inNewActiveSlide)
+{
+ using namespace UICDM;
+ CUICDMSlideHandle theActiveSlide = m_ActiveSlide;
+ m_ActiveSlide = inNewActiveSlide;
+ TTransactionConsumerPtr theConsumer = m_StudioSystem->GetFullSystem()->GetConsumer();
+ if (theConsumer)
+ theConsumer->OnTransaction(std::make_shared<SReferenceTransaction<CUICDMSlideHandle>>(
+ __FILE__, __LINE__, ref(m_ActiveSlide), theActiveSlide, inNewActiveSlide));
+}
+
+void CDoc::SetSceneGraph(std::shared_ptr<Q3DStudio::IDocSceneGraph> inGraph)
+{
+ m_SceneGraph = inGraph;
+}
+
+inline Q3DStudio::CString ConvertToWide(const char8_t *inStr)
+{
+ eastl::basic_string<char16_t> theConvertStr;
+ qt3ds::foundation::ConvertUTF(inStr, 0, theConvertStr);
+ return Q3DStudio::CString(theConvertStr.c_str());
+}
+
+void CDoc::GetProjectFonts(
+ std::vector<std::pair<Q3DStudio::CString, Q3DStudio::CString>> &outFontNameFileList)
+{
+ outFontNameFileList.clear();
+ uic::render::ITextRenderer *theRenderer = m_SceneGraph->GetTextRenderer();
+ if (theRenderer) {
+ qt3ds::render::NVConstDataRef<uic::render::SRendererFontEntry> theProjectFonts =
+ theRenderer->GetProjectFontList();
+ for (uint32_t idx = 0, end = theProjectFonts.size(); idx < end; ++idx)
+ outFontNameFileList.push_back(
+ std::make_pair(ConvertToWide(theProjectFonts[idx].m_FontName),
+ ConvertToWide(theProjectFonts[idx].m_FontFile)));
+ }
+}
+
+void CDoc::GetProjectFonts(std::vector<Q3DStudio::CString> &outFonts)
+{
+ outFonts.clear();
+ uic::render::ITextRenderer *theRenderer = m_SceneGraph->GetTextRenderer();
+ if (theRenderer) {
+ qt3ds::render::NVConstDataRef<uic::render::SRendererFontEntry> theProjectFonts =
+ theRenderer->GetProjectFontList();
+ for (uint32_t idx = 0, end = theProjectFonts.size(); idx < end; ++idx)
+ outFonts.push_back(ConvertToWide(theProjectFonts[idx].m_FontName));
+ }
+}
+
+Q3DStudio::CString CDoc::GetProjectFontName(const Q3DStudio::CFilePath &inFullPathToFontFile)
+{
+ uic::render::ITextRenderer *theRenderer = m_SceneGraph->GetTextRenderer();
+ Q3DStudio::CString theFont;
+ if (theRenderer) {
+ qt3ds::render::NVConstDataRef<uic::render::SRendererFontEntry> theProjectFonts =
+ theRenderer->GetProjectFontList();
+ qCInfo(qt3ds::TRACE_INFO) << "Attempting to find font: "
+ << inFullPathToFontFile.GetCharStar();
+ for (uint32_t idx = 0, end = theProjectFonts.size(); idx < end; ++idx) {
+ // Using a CFilePath here instead of a CString means the file path object will normalize
+ // the data coming from fontconfig. For example, they always use forward slashes
+ // instead of
+ // back slashes.
+ Q3DStudio::CFilePath theFontFile(ConvertToWide(theProjectFonts[idx].m_FontFile));
+ if (inFullPathToFontFile == theFontFile) {
+ qCInfo(qt3ds::TRACE_INFO) << "Matching against: " << theFontFile.GetCharStar()
+ << " SUCCEEDED";
+ theFont = ConvertToWide(theProjectFonts[idx].m_FontName);
+ break;
+ } else {
+ qCInfo(qt3ds::TRACE_INFO) << "Matching against: " << theFontFile.GetCharStar()
+ << " FAILED";
+ }
+ }
+ }
+ return theFont;
+}
+
+void CDoc::OnSlideDeleted(UICDM::CUICDMSlideHandle inSlide)
+{
+ using namespace UICDM;
+ if (inSlide == m_ActiveSlide) {
+ ISlideSystem &theSlideSystem = *m_StudioSystem->GetFullSystem()->GetSlideSystem();
+ CUICDMSlideHandle theMaster = theSlideSystem.GetMasterSlide(inSlide);
+ CUICDMSlideHandle theFirstSlide = theSlideSystem.GetSlideByIndex(theMaster, 1);
+ CUICDMSlideHandle theNewSlide;
+ if (theFirstSlide == inSlide)
+ theNewSlide = theSlideSystem.GetSlideByIndex(theMaster, 2);
+ else
+ theNewSlide = theFirstSlide;
+ SetActiveSlideWithTransaction(theNewSlide);
+ }
+}
+void CDoc::OnInstanceDeleted(UICDM::CUICDMInstanceHandle inInstance)
+{
+ UICDM::TTransactionConsumerPtr theConsumer = m_StudioSystem->GetFullSystem()->GetConsumer();
+ if (GetSelectedInstance() == inInstance)
+ DeselectAllItems();
+
+ if (m_ActiveLayer == inInstance)
+ m_ActiveLayer = 0;
+
+ using namespace UICDM;
+ CClientDataModelBridge &theBridge(*m_StudioSystem->GetClientDataModelBridge());
+ SComposerObjectDefinitions &theDefinitions(theBridge.GetObjectDefinitions());
+ IDataCore &theCore(*m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore());
+ if (theCore.IsInstanceOrDerivedFrom(inInstance, theDefinitions.m_SlideOwner.m_Instance)) {
+ CUICDMSlideHandle theSlide = theBridge.GetComponentActiveSlide(inInstance);
+ if (theSlide == m_ActiveSlide) {
+ // empty loop intentional, finding the next component parent.
+ CUICDMInstanceHandle theParent;
+ for (theParent = m_AssetGraph->GetParent(inInstance); theParent.Valid()
+ && !theCore.IsInstanceOrDerivedFrom(theParent,
+ theDefinitions.m_SlideOwner.m_Instance);
+ theParent = m_AssetGraph->GetParent(theParent))
+ ;
+
+ if (theParent.Valid()) {
+ QT3DS_ASSERT(theCore.IsInstanceOrDerivedFrom(theParent,
+ theDefinitions.m_SlideOwner.m_Instance));
+ m_ActiveSlide = theBridge.GetComponentActiveSlide(theParent);
+ } else {
+ QT3DS_ASSERT(false);
+ // This is fine because setting the active slide to zero will force it to default
+ // to the scene's first slide.
+ m_ActiveSlide = 0;
+ }
+ }
+ }
+}
+
+Q3DStudio::SSelectedValue CDoc::SetupInstanceSelection(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (m_StudioSystem->IsInstance(inInstance)
+ && !m_StudioSystem->GetClientDataModelBridge()->IsLockedAtAll(inInstance)) {
+ return Q3DStudio::SSelectedValue(inInstance);
+ }
+ return Q3DStudio::SSelectedValue();
+}
+
+//==============================================================================
+/**
+ * Select UICDM Object given its instance handle.
+ * @param inInstanceHandle The instance handle of the UICDM Object to be selected
+ */
+void CDoc::SelectUICDMObject(UICDM::CUICDMInstanceHandle inInstanceHandle)
+{
+ UICDM::TInstanceHandleList theObjects = m_SelectedValue.GetSelectedInstances();
+ if (std::find(theObjects.begin(), theObjects.end(), inInstanceHandle) == theObjects.end())
+ NotifySelectionChanged(SetupInstanceSelection(inInstanceHandle));
+ else
+ NotifySelectionChanged(theObjects);
+}
+
+void CDoc::ToggleUICDMObjectToSelection(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (m_StudioSystem->GetClientDataModelBridge()->IsMultiSelectable(inInstance)) {
+ UICDM::TInstanceHandleList theNewHandles;
+ if (m_SelectedValue.getType() != Q3DStudio::SelectedValueTypes::MultipleInstances) {
+ // Attempt conversion if possible.
+ if (m_SelectedValue.getType() == Q3DStudio::SelectedValueTypes::Instance) {
+ UICDM::CUICDMInstanceHandle theCurrentlySelectedInstance =
+ m_SelectedValue.getData<UICDM::CUICDMInstanceHandle>();
+ if (m_StudioSystem->GetClientDataModelBridge()->IsMultiSelectable(
+ theCurrentlySelectedInstance))
+ theNewHandles.push_back(theCurrentlySelectedInstance);
+ }
+ } else
+ theNewHandles = m_SelectedValue.getData<UICDM::TInstanceHandleList>();
+
+ UICDM::TInstanceHandleList::iterator iter =
+ std::find(theNewHandles.begin(), theNewHandles.end(), inInstance);
+ if (iter == theNewHandles.end())
+ theNewHandles.push_back(inInstance);
+ else
+ theNewHandles.erase(iter);
+ NotifySelectionChanged(theNewHandles);
+ }
+}
+
+void CDoc::SelectAndNavigateToUICDMObject(UICDM::CUICDMInstanceHandle inInstanceHandle)
+{
+ if (inInstanceHandle.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ Q3DStudio::IDocumentReader &theReader(GetDocumentReader());
+ UICDM::CUICDMSlideHandle theAssociatedSlide = theReader.GetAssociatedSlide(inInstanceHandle);
+ UICDM::CUICDMInstanceHandle theNewComponent =
+ theReader.GetComponentForSlide(theAssociatedSlide);
+ UICDM::CUICDMInstanceHandle theOldComponent = theReader.GetComponentForSlide(GetActiveSlide());
+ if (theNewComponent.Valid() && theNewComponent != theOldComponent) {
+ // Get the currently active slide for the new component.
+ UICDM::CUICDMSlideHandle theActiveSlide =
+ theReader.GetComponentActiveSlide(theNewComponent);
+ NotifyActiveSlideChanged(theActiveSlide, true);
+ }
+ NotifySelectionChanged(SetupInstanceSelection(inInstanceHandle));
+}
+
+//=============================================================================
+/**
+ * Get the latest end time of the children of the Active Root.
+ */
+long CDoc::GetLatestEndTime()
+{
+ long theTime = 0;
+ Q3DStudio::CGraphIterator theChildren;
+ GetAssetChildrenInTimeParent(GetActiveRootInstance(), this, true, theChildren,
+ GetActiveSlide());
+ for (; !theChildren.IsDone(); ++theChildren) {
+ UICDM::CUICDMInstanceHandle theChildAsset = theChildren.GetCurrent();
+ long theChildEnd = GetDocumentReader().GetTimeRange(theChildAsset).second;
+ if ((theChildEnd > theTime))
+ theTime = theChildEnd;
+ }
+ return theTime;
+}
+
+void CDoc::OnComponentSeconds()
+{
+ long theTime = GetCurrentClientTime();
+
+ m_CurrentViewTime = theTime;
+ UICPROFILE(NotifyTimeChanged_UpdateAllViews);
+
+ m_Core->GetDispatch()->FireOnTimeChanged(m_CurrentViewTime);
+}
+//==============================================================================
+/**
+ * Tell Client that the time has changed and update views accordingly.
+ * Set the current time on the current time context to be inNewTime.
+ * @param inNewTime The time to set Client to (in milliseconds)
+ */
+void CDoc::NotifyTimeChanged(long inNewTime)
+{
+ if (m_PlaybackClock)
+ m_PlaybackClock->OnTimeChange(inNewTime);
+ DoNotifyTimeChanged(inNewTime);
+}
+
+void CDoc::DoNotifyTimeChanged(long inNewTime)
+{
+ UICPROFILE(NotifyTimeChanged);
+
+ // Make sure time is within valid range
+ long theMinTime = 0; // min time is always 0
+ if (inNewTime < theMinTime)
+ inNewTime = theMinTime;
+ else {
+ long theLatestEndTime = GetLatestEndTime();
+ if (inNewTime > theLatestEndTime)
+ inNewTime = theLatestEndTime;
+ }
+
+ // Update UICDM
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ m_StudioSystem->GetSlideSystem()->GetMasterSlide(GetActiveSlide());
+ // TODO: fix precision issue from converting to/from float & long. choose 1 type
+ m_StudioSystem->GetSlideSystem()->SetComponentSeconds(theMasterSlide, (float)inNewTime / 1000);
+}
+
+//==============================================================================
+/**
+ * Sets the timebar time range of the currently selected object in the timeline
+ * @param inSetStart true to set the Start time, false sets the End time
+ * @param inAffectsChildren true if the children should have their start/end times in sync
+ */
+void CDoc::TruncateTimebar(bool inSetStart, bool inAffectsChildren)
+{
+ Q_UNUSED(inAffectsChildren);
+
+ UICDM::CUICDMInstanceHandle theSelectedInstance = GetSelectedInstance();
+ // Cannot change the time bars for a material
+ if (theSelectedInstance.Valid())
+ Q3DStudio::ScopedDocumentEditor(*this, L"Truncate Time Range", __FILE__, __LINE__)
+ ->TruncateTimeRange(theSelectedInstance, inSetStart, GetCurrentViewTime());
+}
+
+//==============================================================================
+/**
+ * Tell Client to be in either PLAY or PAUSE mode.
+ * This potentially changes the current mode of the Client, whether it should
+ * Play or Pause.
+ * @param inPlayMode Either PLAYMODE_PLAY or PLAYMODE_STOP
+ * @param inRestoreTime whether there is a time to restore for time context
+ */
+void CDoc::SetPlayMode(EPlayMode inPlayMode, long inRestoreTime /*= -1*/)
+{
+ if (m_PlayMode != inPlayMode) // if there is a change
+ {
+ m_PlayMode = inPlayMode;
+
+ // Play or stop?
+ if (inPlayMode == PLAYMODE_PLAY) {
+ // Set Client to PLAY
+ m_PlaybackClock->StartPlayback();
+
+ m_Core->GetDispatch()->FireOnPlayStart();
+ } else {
+ // Set Client to STOP
+ if (inRestoreTime >= 0)
+ NotifyTimeChanged(inRestoreTime); // update views as indicated by client
+ else {
+ m_PlaybackClock->StopPlayback();
+ }
+ m_Core->GetDispatch()->FireOnPlayStop();
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Determine if Studio is playing the presentation.
+ * @return true if Studio is currently in play mode
+ */
+bool CDoc::IsPlaying()
+{
+ return (m_PlayMode == PLAYMODE_PLAY);
+}
+
+//==============================================================================
+/**
+ * Returns the time Client believes it to be.
+ * This requests the current time from Client. This allows in-place previewing
+ * of the presentation in Studio.
+ * @return The current time of Client in milliseconds.
+ */
+long CDoc::GetCurrentClientTime()
+{
+ if (m_ActiveSlide.Valid())
+ return m_StudioSystem->GetSlideSystem()->GetComponentSecondsLong(m_ActiveSlide);
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Get the current visible time.
+ * This differs by the current client time in that you can move the playhead
+ * without Client updating, causing the view time to change but not client time.
+ * This usually happens when control-dragging the playhead.
+ * @return the current view time.
+ */
+long CDoc::GetCurrentViewTime() const
+{
+ return m_CurrentViewTime;
+}
+
+void CDoc::SetDirectoryWatchingSystem(
+ std::shared_ptr<Q3DStudio::IDirectoryWatchingSystem> inSystem)
+{
+ m_DirectoryWatchingSystem = inSystem;
+}
+
+Q3DStudio::IDirectoryWatchingSystem *CDoc::GetDirectoryWatchingSystem()
+{
+ return m_DirectoryWatchingSystem ? m_DirectoryWatchingSystem.get() : NULL;
+}
+
+void CDoc::SetDocumentPath(const CUICFile &inDocumentPath)
+{
+ Q3DStudio::CString theDocPath = inDocumentPath.GetName();
+ // We always need to have a document path.
+ if (theDocPath.Length() == 0) {
+ ASSERT(false); // User should have specified which file.
+ m_DocumentPath = CreateUntitledDocument();
+ } else {
+ m_DocumentPath = inDocumentPath;
+ if (!m_DocumentPath.Exists()) {
+ // If the file doesn't exist, create it.
+ Q3DStudio::CFilePath(m_DocumentPath.GetPath()).Touch();
+ }
+ }
+
+ // Document path should always be absolute path
+ ASSERT(!CUICFile::IsPathRelative(m_DocumentPath.GetPath()));
+ // Document path should exist.
+ Q_ASSERT(m_DocumentPath.Exists());
+
+ m_Core->GetDispatch()->FireOnDocumentPathChanged(m_DocumentPath);
+}
+
+//=============================================================================
+/**
+ * Create Untitled document in user directory
+ */
+CUICFile CDoc::CreateUntitledDocument() const
+{
+ Q3DStudio::CFilePath theAppDirectory = Q3DStudio::CFilePath::GetUserApplicationDirectory();
+ Q3DStudio::CFilePath theUICDirectory = Q3DStudio::CFilePath::CombineBaseAndRelative(
+ theAppDirectory, Q3DStudio::CFilePath(L"UIComposer/Untitled"));
+ theUICDirectory.CreateDir(true);
+ Q3DStudio::CFilePath theUICFilePath = Q3DStudio::CFilePath::CombineBaseAndRelative(
+ theUICDirectory, Q3DStudio::CFilePath(L"Untitled.uip"));
+ // Keep jokers from screwing with our system.
+ if (theUICFilePath.IsDirectory())
+ theUICFilePath.DeleteThisDirectory(true);
+
+ if (!theUICFilePath.IsFile())
+ theUICFilePath.Touch();
+ return CUICFile(theUICFilePath);
+}
+
+void CDoc::SetImportFailedHandler(std::shared_ptr<Q3DStudio::IImportFailedHandler> inHandler)
+{
+ m_ImportFailedHandler = inHandler;
+}
+
+std::shared_ptr<Q3DStudio::IImportFailedHandler> CDoc::GetImportFailedHandler()
+{
+ return m_ImportFailedHandler;
+}
+
+void CDoc::SetDocMessageBoxHandler(
+ std::shared_ptr<Q3DStudio::IDeletingReferencedObjectHandler> inHandler)
+{
+ m_DeletingReferencedObjectHandler = inHandler;
+}
+
+CUICFile CDoc::GetDocumentPath() const
+{
+ return m_DocumentPath;
+}
+
+//=============================================================================
+/**
+ * Given an absolute path, return true if it is in doc's subdirectory.
+ */
+bool CDoc::IsInDocSubDirectory(const Q3DStudio::CString &inPath) const
+{
+ Q3DStudio::CFilePath thePath(inPath);
+ if (thePath.IsInSubDirectory(GetDocumentDirectory())) {
+ return true;
+ }
+ return false;
+}
+
+Q3DStudio::CString CDoc::GetDocumentDirectory() const
+{
+ Q3DStudio::CFilePath thePath(m_DocumentPath.GetAbsolutePath());
+ return thePath.GetDirectory();
+}
+
+//=============================================================================
+/**
+ * Given an absolute path, return the relative path to doc if it is in doc's subdirectory.
+ * Else, return normalized path so that we can easily do string comparison to compare path.
+ * This is used when we drag image / behavior / other files to scene.
+ * In future we may want to return path to handle importing files from $CommonAssets.
+ */
+Q3DStudio::CString CDoc::GetRelativePathToDoc(const Q3DStudio::CFilePath &inPath)
+{
+ Q3DStudio::CFilePath thePath(inPath);
+ Q3DStudio::CFilePath theDocumentPath(GetDocumentDirectory());
+ if (thePath.IsInSubDirectory(theDocumentPath))
+ thePath.ConvertToRelative(theDocumentPath);
+
+ return thePath;
+}
+
+//=============================================================================
+/**
+ * Given a path (may be relative or absolute), return the path with respect to doc.
+ * If the path is relative, it will be resolved based on document path.
+ * Else, return normalized path so that we can easily do string comparison to compare path.
+ * In future we may want to resolve path based on $CommonAssets.
+ */
+Q3DStudio::CString CDoc::GetResolvedPathToDoc(const Q3DStudio::CFilePath &inPath)
+{
+ // If it is a relative path, resolve it.
+ if (inPath.IsAbsolute() == false) {
+ ASSERT(m_DocumentPath.Exists()); // Sanity check that document path has been set properly.
+
+ return Q3DStudio::CFilePath::CombineBaseAndRelative(GetDocumentDirectory(), inPath);
+ }
+ return inPath;
+}
+
+//=============================================================================
+/**
+ * Close the current document.
+ * This will remove all the items from the scene, perform all the cleanup.
+ * The state of the Doc is invalid after this and a CreateNewDocument or LoadDocument must be called
+ * following this, for a new presentation.
+ */
+void CDoc::CloseDocument()
+{
+ // selection would be invalid from this point onwards
+ DeselectAllItems();
+
+ m_SceneEditor = std::shared_ptr<Q3DStudio::IInternalDocumentEditor>();
+ if (m_DocumentBufferCache) {
+ // Ensure old buffers aren't picked up for the same relative path.
+ m_DocumentBufferCache->Clear();
+ }
+
+ CDispatchDataModelNotificationScope __dispatchScope(*GetCore()->GetDispatch());
+ SetPlayMode(PLAYMODE_STOP);
+
+ m_Core->GetDispatch()->FireOnClosingPresentation();
+
+ // clean up all studio data
+ CleanupData();
+
+ ClosePresentation();
+
+ if (m_SceneInstance.Valid()) {
+ m_AssetGraph->RemoveNode(m_SceneInstance);
+ m_SceneInstance = 0;
+
+ // Destroy Asset Graph
+ m_AssetGraph = TAssetGraphPtr();
+ }
+
+ // Clear the modified flag - no data loaded
+ SetModifiedFlag(false);
+}
+
+//=============================================================================
+/**
+ * Called when the core opens a UIP file.
+ */
+void CDoc::LoadDocument(const CUICFile &inDocument)
+{
+ ResetData();
+
+ CFileInputStream theFileStream(inDocument.GetAbsolutePosixPath());
+ CBufferedInputStream theBufferedStream(&theFileStream, inDocument.Length());
+ SetDocumentPath(inDocument); // SetDocumentPath before LoadPresentation because we need
+ // DocumentPath to load relative resources such as images
+ LoadPresentationFile(&theBufferedStream);
+}
+
+//=============================================================================
+/**
+ * Save Document
+ */
+void CDoc::SaveDocument(const CUICFile &inDocument)
+{
+ CFileOutputStream theFileStream(inDocument.GetAbsolutePosixPath());
+ // Exceptions here get propagated to the crash dialog.
+ CBufferedOutputStream theBufferStream(&theFileStream);
+ SavePresentationFile(&theBufferStream);
+ theBufferStream.Close();
+}
+
+//=============================================================================
+/**
+ * This will create and load a new document with all the default resources.
+ * This should only be called on an empty document (after CloseDocument) and
+ * will do all the creation of the resources (default Layer, Light, Camera etc)
+ */
+void CDoc::CreateNewDocument()
+{
+ using namespace UICDM;
+ using namespace Q3DStudio;
+
+ CDispatchDataModelNotificationScope __dispatchScope(*m_Core->GetDispatch());
+ ResetData();
+
+ CreatePresentation();
+
+ // Create the default objects in the scene
+ CUICDMSlideHandle theSlide =
+ m_StudioSystem->GetClientDataModelBridge()->GetOrCreateGraphRoot(m_SceneInstance);
+ IDataCore &theDataCore(
+ *m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetTransactionlessDataCore());
+ ISlideSystem &theSlideSystem(*m_StudioSystem->GetFullSystem()->GetSlideSystem());
+ SComposerObjectDefinitions &theObjectDefinitions(
+ m_StudioSystem->GetClientDataModelBridge()->GetObjectDefinitions());
+ IMetaData &theMetaData(*m_StudioSystem->GetActionMetaData());
+
+ CUICDMInstanceHandle theLayer = IDocumentEditor::CreateSceneGraphInstance(
+ ComposerObjectTypes::Convert(ComposerObjectTypes::Layer), m_SceneInstance, theSlide,
+ theDataCore, theSlideSystem, theObjectDefinitions, *m_AssetGraph, theMetaData);
+
+ IDocumentEditor::CreateSceneGraphInstance(
+ ComposerObjectTypes::Convert(ComposerObjectTypes::Camera), theLayer, theSlide, theDataCore,
+ theSlideSystem, theObjectDefinitions, *m_AssetGraph, theMetaData);
+ IDocumentEditor::CreateSceneGraphInstance(
+ ComposerObjectTypes::Convert(ComposerObjectTypes::Light), theLayer, theSlide, theDataCore,
+ theSlideSystem, theObjectDefinitions, *m_AssetGraph, theMetaData);
+
+ OnNewPresentation();
+
+ // Override the modified flag that's set when we create the default resources.
+ SetModifiedFlag(false);
+}
+
+//=============================================================================
+/**
+ * Create a new presentation within Client.
+ */
+void CDoc::CreatePresentation()
+{
+ // m_SceneInstance should be invalid
+ ASSERT(!m_SceneInstance.Valid());
+
+ // eclee TODO: Move these to ComponentFactory
+ // Create the top-level scene object
+ Q3DStudio::CId theSceneId(SCENE_GUID);
+
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ m_SceneInstance = theBridge->CreateAssetInstance(theSceneId, OBJTYPE_SCENE);
+
+ // Initialize Asset Graph
+ m_AssetGraph = TAssetGraph::CreateGraph();
+ m_AssetGraph->AddRoot(m_SceneInstance);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ ::CColor theColor = CStudioPreferences::GetEditViewBackgroundColor();
+// SetEditViewBackgroundColor( theColor );
+#endif
+}
+
+void CDoc::ClosePresentation()
+{
+ OnPresentationDeactivated();
+}
+
+//==============================================================================
+/**
+ * Step the client (this is really overridding update in client)
+ */
+void CDoc::ClientStep()
+{
+ m_PlaybackClock->UpdateTime();
+}
+
+//=============================================================================
+/**
+void CDoc::SetEditViewBackgroundColor( ::CColor& inColor )
+{
+ m_EditCameraContainer->SetBackgroundColor( inColor );
+}
+*/
+
+//=============================================================================
+/**
+ * Removes all StudioObjects from the Map
+ * This cleans up all of the CStudioObjects that Studio owns.
+ * This is called when shutdown and prior to loading or creating a new presentation.
+ * Nothing should be instantiated in this call, since this is called in the destructor.
+ */
+void CDoc::CleanupData()
+{
+ // Make sure selection is cleared
+ DeselectAllItems();
+
+ // Clear references that are now invalid
+ m_ActiveSlide = 0;
+ SetActiveLayer(0);
+}
+
+/**
+ * Called when we are preparing to load or create a new presentation.
+ */
+void CDoc::ResetData()
+{
+ ResetDataCore();
+}
+
+//=============================================================================
+/**
+ * Process a copy command.
+ * This will copy Actions, Keyframes or objects, depending on what is selected.
+ * If the Action Palette is visible, then this will do an Action copy.
+ * If there are any keyframes selected then this will do a keyframe copy
+ */
+void CDoc::HandleCopy()
+{
+ if (CanCopyAction()) {
+ ASSERT(0); // Dispatch ... and/or, what?
+ // m_StudioApp->GetViews( )->GetActionControl( )->OnCopyAction( );
+ } else if (m_KeyframesManager && m_KeyframesManager->HasSelectedKeyframes()) {
+ if (CanCopyKeyframe())
+ m_KeyframesManager->CopyKeyframes();
+ } else if (CanCopyObject()) {
+ CopyObject(m_SelectedValue.GetSelectedInstances());
+ }
+}
+
+//=============================================================================
+/**
+ * Process a paste command.
+ * If there is an action on the clipboard, and the action palette is visible,
+ * this will paste the action.
+ * Otherwise, this will paste an object if the clipboard data has an object
+ * data type in it, else it will attempt to paste keyframes.
+ */
+void CDoc::HandlePaste()
+{
+ if (CanPasteAction()) {
+ ASSERT(0); // dispatch
+ // m_StudioApp->GetViews( )->GetActionControl( )->OnPasteAction( );
+ // m_StudioApp->GetViews( )->OnShowAction( );
+ } else if (CanPasteObject()) {
+ PasteObject(GetSelectedInstance());
+ } else {
+ if (m_KeyframesManager)
+ m_KeyframesManager->PasteKeyframes();
+ }
+}
+
+//=============================================================================
+/**
+ * Process a paste command for Master Slide.
+ * If there is an action on the clipboard, and the action palette is visible,
+ * this will paste the action.
+ * Otherwise, this will paste an object if the clipboard data has an object
+ * data type in it, else it will attempt to paste keyframes.
+ */
+void CDoc::HandleMasterPaste()
+{
+ using namespace Q3DStudio;
+
+ if (CanPasteAction()) {
+ ASSERT(0); // dispatch
+ // m_StudioApp->GetViews( )->GetActionControl( )->OnPasteAction( );
+ // m_StudioApp->GetViews( )->OnShowAction( );
+ } else if (CanPasteObject()) {
+ UICDM::CUICDMInstanceHandle theSelectedInstance = GetSelectedInstance();
+ long theTargetObjectType =
+ GetStudioSystem()->GetClientDataModelBridge()->GetObjectType(theSelectedInstance);
+ UICDM::ISlideSystem *theSlideSystem = GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theTargetSlide =
+ theSlideSystem->GetAssociatedSlide(theSelectedInstance);
+
+ if (theTargetObjectType != OBJTYPE_SCENE && theTargetObjectType != OBJTYPE_COMPONENT) {
+ if (theTargetSlide && theSlideSystem->IsMasterSlide(theTargetSlide)) {
+ UICDM::CUICDMSlideHandle theMasterSlideHandle =
+ theSlideSystem->GetMasterSlide(theTargetSlide);
+ if (theMasterSlideHandle.Valid())
+ theTargetSlide = theMasterSlideHandle;
+ PasteObjectMaster(theSelectedInstance);
+ } else
+ PasteObject(theSelectedInstance);
+ } else {
+ UICDM::CUICDMSlideHandle theMasterSlideHandle =
+ theSlideSystem->GetMasterSlide(theTargetSlide);
+ if (theMasterSlideHandle.Valid())
+ theTargetSlide = theMasterSlideHandle;
+ PasteObjectMaster(theSelectedInstance);
+ }
+ } else {
+ if (m_KeyframesManager)
+ m_KeyframesManager->PasteKeyframes();
+ }
+}
+
+//=============================================================================
+/**
+ * Process a cut command.
+ * This will copy/cut Action, if the Action Palette is visible, and an action
+ * is selected. Otherwise the following holds true.
+ * This will copy Keyframes or objects, depending on what is selected.
+ * If there are any keyframes selected then this will do a keyframe copy
+ * The object/keyframe(s) will then be deleted.
+ */
+void CDoc::HandleCut()
+{
+ // we only need to check if it can be copied.
+ // if it can be copied, then it can be cut.
+ if (CanCopyAction()) {
+ ASSERT(0); // dispatch
+ // m_StudioApp->GetViews( )->GetActionControl( )->OnCutAction( );
+ } else if (m_KeyframesManager && m_KeyframesManager->HasSelectedKeyframes()) {
+ m_KeyframesManager->RemoveKeyframes(true);
+ } else if (CanCopyObject()) {
+ CutSelectedObject();
+ }
+}
+
+bool CDoc::CanCopyObject(const UICDM::TInstanceHandleList &inInstances)
+{
+ if (inInstances.empty())
+ return false;
+
+ bool retval = true;
+ const UICDM::TInstanceHandleList &theInstances = (inInstances);
+ for (size_t idx = 0, end = theInstances.size(); idx < end && retval; ++idx)
+ retval &= m_StudioSystem->GetClientDataModelBridge()->IsDuplicateable(theInstances[idx]);
+ return retval;
+}
+//==============================================================================
+/**
+ * Check to see if an object can be copied into the clipboard
+ */
+bool CDoc::CanCopyObject()
+{
+ return CanCopyObject(m_SelectedValue.GetSelectedInstances());
+}
+
+//==============================================================================
+/**
+ * Check to see if a keyframe can be copied into the clipboard
+ */
+bool CDoc::CanCopyKeyframe()
+{
+ return (m_KeyframesManager) ? m_KeyframesManager->CanPerformKeyframeCopy() : false;
+}
+
+//==============================================================================
+/**
+ * Check to see if an Action can be copied onto the clipboard.
+ * @return true if an Action can be copied onto the clipboard.
+ */
+bool CDoc::CanCopyAction()
+{
+ bool theCanCopy = false;
+
+ // TODO: Refactor selection
+ // Only if views are already created;
+ // Otherwise we can neither obtain the ActionControl,
+ // nor can we check if the ActionControl can perform a copy.
+ // if ( m_StudioApp->GetViews( )->AreViewsCreated( ) )
+ //{
+ // theCanCopy = m_StudioApp->GetViews( )->GetActionControl( )->CanCopyAction( );
+ //}
+
+ return theCanCopy;
+}
+
+//==============================================================================
+/**
+ * Check to see if an object can be pasted into the Scene.
+ */
+bool CDoc::CanPasteObject()
+{
+ bool theCanPasteFlag = false;
+
+ UICDM::CUICDMInstanceHandle theSelectedInstance = GetSelectedInstance();
+ if (theSelectedInstance.Valid()) {
+ // Check if there is object on clipboard and if the object type on clipboard can be attached
+ // to theSelectedInstance
+ theCanPasteFlag = CStudioClipboard::CanPasteObject(
+ GetStudioSystem()->GetClientDataModelBridge()->GetObjectType(theSelectedInstance));
+
+ // Only allow component paste if we are in the component.
+ if (theCanPasteFlag
+ && m_StudioSystem->GetClientDataModelBridge()->GetObjectType(theSelectedInstance)
+ == OBJTYPE_COMPONENT)
+ theCanPasteFlag &=
+ m_StudioSystem->GetClientDataModelBridge()->IsActiveComponent(theSelectedInstance);
+ }
+ return theCanPasteFlag;
+}
+
+//==============================================================================
+/**
+ * Check to see if a keyframe can be pasted from the clipboard
+ */
+bool CDoc::CanPasteKeyframe()
+{
+ return (m_KeyframesManager) ? m_KeyframesManager->CanPerformKeyframePaste() : false;
+}
+
+//==============================================================================
+/**
+ * Check to see if an action can be pasted from the clipboard.
+ * Paste action is only allowed if there is an Action on the clipboard, an asset
+ * is selected, and the Timeline is in focus.
+ * @return true if we can paste an action.
+ */
+bool CDoc::CanPasteAction()
+{
+ bool theCanPaste = false;
+
+ // TODO: Refactor selection
+ // CViews* theViews = m_StudioApp->GetViews( );
+
+ //// Only if views are already created;
+ //// Otherwise we can neither obtain the ActionControl,
+ //// nor can we check if the ActionControl can perform a paste.
+ // if ( m_StudioApp->GetViews( )->AreViewsCreated( ) )
+ //{
+ // theCanPaste = theViews->GetActionControl( )->CanPasteAction( ) && (
+ //theViews->GetTimelineControl( )->IsInFocus( ) || theViews->GetActionControl( )->IsInFocus( )
+ //);
+ //}
+
+ return theCanPaste;
+}
+
+//==============================================================================
+/**
+ * Check to see if an object or keyframe(s) can be copied into the clipboard
+ */
+bool CDoc::CanCopy()
+{
+ return CanCopyKeyframe() || CanCopyObject() || CanCopyAction();
+}
+
+//==============================================================================
+/**
+ * Check to see if an object or keyframe(s) can be pasted into the Scene.
+ */
+bool CDoc::CanPaste()
+{
+ return CanPasteKeyframe() || CanPasteObject() || CanPasteAction();
+}
+
+//==============================================================================
+/**
+ * Check to see if an object or keyframe(s) can be cut.
+ */
+bool CDoc::CanCut()
+{
+ bool theReturn = false;
+
+ if (CanCopy()) {
+ if (CanCopyAction()) {
+ // If you can copy an Action, you jolly well can delete it.
+ // ie. An action is currently selected, and the ActionControl (aka Action Palette) is in
+ // focus.
+ theReturn = true;
+ } else if (CanCopyObject()) {
+ // Check the Object is not the scene
+ // the Object cannot be the last layer as well
+ UICDM::TInstanceHandleList theInstances = m_SelectedValue.GetSelectedInstances();
+ bool canDelete = !theInstances.empty();
+ for (size_t idx = 0, end = theInstances.size() && canDelete; idx < end; ++idx) {
+ canDelete = GetDocumentReader().IsInstance(theInstances[idx])
+ && GetStudioSystem()->GetClientDataModelBridge()->CanDelete(theInstances[idx]);
+ }
+ theReturn = canDelete;
+ } else // Any keyframe can be cut
+ {
+ theReturn = true;
+ }
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * Handles the duplicate command passed by mainframe.
+ * Makes a copy of the currently selected item (if there is one) and attaches
+ * it to the same parent as the original.
+ */
+void CDoc::HandleDuplicateCommand()
+{
+ UICDM::CUICDMInstanceHandle theSelectedInstance = GetSelectedInstance();
+
+ // If we have a valid object to duplicate
+ if (m_StudioSystem->GetClientDataModelBridge()->IsDuplicateable(theSelectedInstance)) {
+ using namespace Q3DStudio;
+ SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Duplicate Object"))
+ ->DuplicateInstance(GetSelectedInstance());
+ }
+}
+
+//=============================================================================
+/**
+ * Verify that an asset can be renamed. Only actions are affected by rename at this point, so prompt
+ * user to proceed if the actions will be hosed.
+ */
+bool CDoc::VerifyCanRename(UICDM::CUICDMInstanceHandle inAsset)
+{
+ bool theResult = true;
+ std::set<Q3DStudio::CString> theAffectedList;
+ GetActionsAffectedByRename(inAsset, theAffectedList);
+ if (!theAffectedList.empty()) {
+ Q3DStudio::CString theFormulatedString;
+ std::set<Q3DStudio::CString>::iterator thePos = theAffectedList.begin();
+ for (; thePos != theAffectedList.end(); ++thePos) {
+ if (theFormulatedString.IsEmpty())
+ theFormulatedString += (*thePos);
+ else
+ theFormulatedString += ", " + (*thePos);
+ }
+
+ ASSERT(0); // Dialogs by dispatch
+ // Q3DStudio::CString theTitle( ::LoadResourceString( IDS_RENAME_OBJ_CONFIRM_TITLE ) );
+ // Q3DStudio::CString theFormat( ::LoadResourceString( IDS_RENAME_OBJ_CONFIRM_MSG ) );
+ // Q3DStudio::CString theMessage;
+ // theMessage.Format( theFormat, static_cast<const wchar_t*>( theFormulatedString ) );
+ //
+ // if ( m_StudioApp->GetDialogs( )->DisplayMessageBox( theTitle, theMessage,
+ // CUICMessageBox::ICON_WARNING, true ) == CUICMessageBox::MSGBX_CANCEL )
+ theResult = false;
+ }
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Load a stream of a UIP file.
+ */
+void CDoc::LoadPresentationFile(CBufferedInputStream *inInputStream)
+{
+ Q3DStudio::CString theOrigFileName;
+
+ // Let any interested parties know that a presentation is going to be loaded
+ m_Core->GetDispatch()->FireOnLoadingPresentation();
+
+ LoadStudioData(inInputStream);
+
+ // We have a new presentation and a new active time context (scene)
+ OnNewPresentation();
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ m_StudioSystem->GetClientDataModelBridge()->GetComponentSlide(m_SceneInstance, 0);
+ UICDM::CUICDMSlideHandle theChildSlide =
+ m_StudioSystem->GetClientDataModelBridge()->GetComponentSlide(m_SceneInstance, 1);
+ m_StudioSystem->GetFullSystem()->GetSignalSender()->SendActiveSlide(theMasterSlide, 1,
+ theChildSlide);
+}
+
+//=============================================================================
+/**
+ * Register all the events for hotkeys that are active for the entire application.
+ * Hotkeys for the entire application are ones that are not view specific in
+ * scope.
+ * @param inShortcutHandler the global shortcut handler.
+ */
+void CDoc::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CDoc>(this, &CDoc::DeleteSelectedItems), 0, Qt::Key_Delete);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CDoc>(this, &CDoc::DeleteSelectedItems), 0, Qt::Key_Backspace);
+
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CDoc>(this, &CDoc::SetChangedKeyframes), 0, Qt::Key_F6);
+
+ inShortcutHandler->RegisterKeyEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::DeselectAllItems),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_A);
+ inShortcutHandler->RegisterKeyEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::HandlePaste),
+ Qt::ControlModifier, Qt::Key_V);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CDoc>(this, &CDoc::HandleMasterPaste),
+ Qt::ControlModifier | Qt::AltModifier, Qt::Key_V);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CDoc>(this, &CDoc::HandleDuplicateCommand),
+ Qt::ControlModifier, Qt::Key_D);
+ inShortcutHandler->RegisterKeyEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::HandleCopy),
+ Qt::ControlModifier, Qt::Key_C);
+ inShortcutHandler->RegisterKeyEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::HandleCut),
+ Qt::ControlModifier, Qt::Key_X);
+
+ // Move nudge
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ 0, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ 0, Qt::Key_Down);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ 0, Qt::Key_Left);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ 0, Qt::Key_Right);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ShiftModifier, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ShiftModifier, Qt::Key_Down);
+
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone), 0,
+ Qt::Key_Up);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone), 0,
+ Qt::Key_Down);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone), 0,
+ Qt::Key_Left);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone), 0,
+ Qt::Key_Right);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ShiftModifier, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ShiftModifier, Qt::Key_Down);
+
+ // Rotation nudge
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ControlModifier, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ControlModifier, Qt::Key_Down);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ControlModifier, Qt::Key_Left);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ControlModifier, Qt::Key_Right);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ShiftModifier | Qt::ControlModifier,
+ Qt::Key_Up);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ShiftModifier | Qt::ControlModifier,
+ Qt::Key_Down);
+
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ControlModifier, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ControlModifier, Qt::Key_Down);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ControlModifier, Qt::Key_Left);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ControlModifier, Qt::Key_Right);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ShiftModifier | Qt::ControlModifier,
+ Qt::Key_Up);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ShiftModifier | Qt::ControlModifier,
+ Qt::Key_Down);
+
+ // Scale nudge
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::AltModifier, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::AltModifier, Qt::Key_Down);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::AltModifier, Qt::Key_Left);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::AltModifier, Qt::Key_Right);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ShiftModifier | Qt::AltModifier,
+ Qt::Key_Up);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeKey),
+ Qt::ShiftModifier | Qt::AltModifier,
+ Qt::Key_Down);
+
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::AltModifier, Qt::Key_Up);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::AltModifier, Qt::Key_Down);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::AltModifier, Qt::Key_Left);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::AltModifier, Qt::Key_Right);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ShiftModifier | Qt::AltModifier,
+ Qt::Key_Up);
+ inShortcutHandler->RegisterKeyUpEvent(new CDynHotKeyConsumer<CDoc>(this, &CDoc::OnNudgeDone),
+ Qt::ShiftModifier | Qt::AltModifier,
+ Qt::Key_Down);
+}
+
+//==============================================================================
+/**
+ * Loads the Studio object data from an archive
+ * Loads Studio object data from a presentation file archive.
+ * @param inArchive CArchive from which to load the data objects.
+ */
+void CDoc::LoadStudioData(CBufferedInputStream *inInputStream)
+{
+ using namespace std;
+ using namespace UICDM;
+ using namespace Q3DStudio;
+
+ UICPROFILE(LoadStudioData);
+ bool theModifiedFlag = false;
+
+ try {
+ // Disable all property change signals until the load is complete.
+ // This cuts down on a lot of redraw calls.
+ CDispatchDataModelNotificationScope __dispatchScope(*GetCore()->GetDispatch());
+
+ qt3ds::QT3DSI32 theVersion = 0;
+ {
+ std::shared_ptr<IDOMReader> theReaderPtr =
+ CreateDOMReader(*inInputStream, theVersion);
+ if (!theReaderPtr)
+ throw CInvalidFileFormatException();
+
+ IDOMReader &theReader(*theReaderPtr);
+
+ theReader.Att("version", theVersion);
+
+ CProjectSettingsSerializer theProjectSettingsSerializer(
+ m_Core->GetStudioProjectSettings());
+ theReader.Serialize(L"ProjectSettings", theProjectSettingsSerializer);
+
+ if (m_AssetGraph)
+ m_AssetGraph->Clear();
+ else
+ m_AssetGraph = TAssetGraph::CreateGraph();
+
+ // We definitely don't want a million events firing off during this deserialization.
+ std::shared_ptr<IComposerSerializer> theSerializer(CreateTransactionlessSerializer());
+ theSerializer->SerializeScene(theReader, GetDocumentDirectory(), (int)theVersion);
+ }
+
+ // Setup the Presentation and Scene
+ // Asset Graph has only one root and that's the scene
+ m_SceneInstance = m_AssetGraph->GetRoot(0);
+ m_ActiveSlide =
+ m_StudioSystem->GetClientDataModelBridge()->GetComponentSlide(m_SceneInstance, 1);
+ // Update from version 1 to current version here
+ if (theVersion == 1) {
+ // Ensure the scene editor even exists.
+ GetDocumentReader();
+ if (m_SceneGraph && m_SceneGraph->GetTextRenderer()) {
+ m_SceneGraph->GetTextRenderer()->ClearProjectFontDirectories();
+ m_SceneGraph->GetTextRenderer()->AddProjectFontDirectory(
+ GetDocumentDirectory().GetCharStar());
+ m_SceneEditor->ReplaceTextFontNameWithTextFileStem(
+ *m_SceneGraph->GetTextRenderer());
+ theModifiedFlag = true;
+ }
+ }
+ } catch (...) {
+ CleanupData();
+ throw; // pass the error along to the caller, so the appropriate error message can be
+ // feedback
+ }
+ SetModifiedFlag(theModifiedFlag);
+}
+
+//==============================================================================
+/**
+ * Create new data core. Typically in construction or loading a new presentation
+ */
+void CDoc::ResetDataCore()
+{
+ m_Connections.clear();
+ if (m_StudioSystem)
+ m_StudioSystem->ResetDatabase();
+ else
+ m_StudioSystem = std::make_shared<UICDM::CStudioSystem>(this);
+
+ // Setup defaults
+ UICDM::IStudioAnimationSystem *theAnimationSystem = GetStudioSystem()->GetAnimationSystem();
+ theAnimationSystem->SetInterpolation(CStudioPreferences::GetInterpolation());
+ theAnimationSystem->SetAutoKeyframe(CStudioPreferences::IsAutosetKeyframesOn());
+}
+
+void CDoc::SetupDataCoreSignals()
+{
+ // Setup the cascading of instance delete notifications so that we can reset our selection.
+ std::shared_ptr<UICDM::IDataCore> theDataCore =
+ m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore();
+ std::shared_ptr<UICDM::IDataCoreSignalProvider> theProvider =
+ std::dynamic_pointer_cast<UICDM::IDataCoreSignalProvider>(theDataCore);
+ std::shared_ptr<UICDM::ISlideCoreSignalProvider> theSlideProvider =
+ std::dynamic_pointer_cast<UICDM::ISlideCoreSignalProvider>(
+ m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetSlideCore());
+
+ if (theProvider)
+ m_Connections.push_back(theProvider->ConnectBeforeInstanceDeleted(
+ std::bind(&CDoc::OnInstanceDeleted, this, std::placeholders::_1)));
+ if (theSlideProvider)
+ m_Connections.push_back(theSlideProvider->ConnectBeforeSlideDeleted(
+ std::bind(&CDoc::OnSlideDeleted, this, std::placeholders::_1)));
+ m_Connections.push_back(
+ m_StudioSystem->GetFullSystem()->GetSignalProvider()->ConnectComponentSeconds(
+ std::bind(&CDoc::OnComponentSeconds, this)));
+ m_Connections.push_back(
+ m_StudioSystem->GetFullSystem()->GetSignalProvider()->ConnectActiveSlide(
+ std::bind(&CDoc::OnComponentSeconds, this)));
+}
+
+std::shared_ptr<Q3DStudio::IComposerSerializer> CDoc::CreateSerializer()
+{
+ using namespace UICDM;
+ using namespace Q3DStudio;
+ CStudioFullSystem &theFullSystem(*m_StudioSystem->GetFullSystem());
+ CStudioCoreSystem &theCoreSystem(*theFullSystem.GetCoreSystem());
+ CClientDataModelBridge &theClientBridge(*GetStudioSystem()->GetClientDataModelBridge());
+ return IComposerSerializer::CreateGraphSlideSerializer(
+ *theCoreSystem.GetDataCore(), *theCoreSystem.GetNewMetaData(),
+ *theCoreSystem.GetSlideCore(), *theCoreSystem.GetAnimationCore(),
+ *theCoreSystem.GetActionCore(), *m_AssetGraph, *theFullSystem.GetSlideSystem(),
+ *theFullSystem.GetActionSystem(), *theCoreSystem.GetSlideGraphCore(),
+ theClientBridge.GetObjectDefinitions(), m_ImportFailedHandler,
+ *theCoreSystem.GetGuideSystem(), *GetSceneGraph()->GetPathManager());
+}
+
+std::shared_ptr<Q3DStudio::IComposerSerializer> CDoc::CreateTransactionlessSerializer()
+{
+ using namespace UICDM;
+ using namespace Q3DStudio;
+ CStudioFullSystem &theFullSystem(*m_StudioSystem->GetFullSystem());
+ CStudioCoreSystem &theCoreSystem(*theFullSystem.GetCoreSystem());
+ CClientDataModelBridge &theClientBridge(*GetStudioSystem()->GetClientDataModelBridge());
+ return IComposerSerializer::CreateGraphSlideSerializer(
+ *theCoreSystem.GetTransactionlessDataCore(), *theCoreSystem.GetNewMetaData(),
+ *theCoreSystem.GetTransactionlessSlideCore(),
+ *theCoreSystem.GetTransactionlessAnimationCore(),
+ *theCoreSystem.GetTransactionlessActionCore(), *m_AssetGraph,
+ *theFullSystem.GetSlideSystem(), *theFullSystem.GetActionSystem(),
+ *theCoreSystem.GetTransactionlessSlideGraphCore(), theClientBridge.GetObjectDefinitions(),
+ m_ImportFailedHandler, *theCoreSystem.GetGuideSystem(), *GetSceneGraph()->GetPathManager());
+}
+
+std::shared_ptr<UICDM::IDOMWriter> CDoc::CreateDOMWriter()
+{
+ using namespace UICDM;
+ qt3ds::QT3DSI32 theFileVersion = STUDIO_FILE_VERSION;
+ TStringTablePtr theStringTable(
+ m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore()->GetStringTablePtr());
+ std::shared_ptr<IDOMWriter> theWriterPtr(
+ IDOMWriter::CreateDOMWriter(L"UIP", theStringTable).first);
+ IDOMWriter &theWriter(*theWriterPtr);
+ theWriter.Att(L"version", theFileVersion);
+ theWriter.Begin(L"Project");
+ return theWriterPtr;
+}
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+
+struct SBufferedInputStreamInStream : public qt3ds::foundation::IInStream
+{
+ CBufferedInputStream &m_Stream;
+
+ SBufferedInputStreamInStream(CBufferedInputStream &str)
+ : m_Stream(str)
+ {
+ }
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ long amountRead = m_Stream.Read(data.begin(), data.size());
+ if (amountRead < 0)
+ amountRead = 0;
+ return static_cast<QT3DSU32>(amountRead);
+ }
+};
+
+struct SBufferedOutputStreamOutStream : public UICDM::IOutStream
+{
+ CBufferedOutputStream &m_Stream;
+
+ SBufferedOutputStreamOutStream(CBufferedOutputStream &str)
+ : m_Stream(str)
+ {
+ }
+
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ m_Stream.Write(data.begin(), data.size());
+ return true;
+ }
+};
+
+inline std::shared_ptr<UICDM::IDOMReader>
+DoCreateDOMReader(qt3ds::foundation::IInStream &inStream,
+ std::shared_ptr<UICDM::IStringTable> theStringTable, qt3ds::QT3DSI32 &outVersion)
+{
+ using namespace UICDM;
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SDOMElement *theElement = CDOMSerializer::Read(*theFactory, inStream);
+ outVersion = 0;
+ if (theElement != NULL) {
+ std::shared_ptr<IDOMReader> retval =
+ IDOMReader::CreateDOMReader(*theElement, theStringTable, theFactory);
+
+ IDOMReader &theReader(*retval);
+ theReader.Att("version", outVersion);
+ if (outVersion > STUDIO_FILE_VERSION || outVersion < STUDIO_LAST_SUPPORTED_FILE_VERSION)
+ return std::shared_ptr<UICDM::IDOMReader>();
+ if (!theReader.MoveToFirstChild(L"Project"))
+ return std::shared_ptr<UICDM::IDOMReader>();
+
+ return retval;
+ }
+ return std::shared_ptr<UICDM::IDOMReader>();
+}
+
+std::shared_ptr<UICDM::IDOMReader> CDoc::CreateDOMReader(const Q3DStudio::CString &inFilePath,
+ qt3ds::QT3DSI32 &outVersion)
+{
+ using namespace UICDM;
+
+ TStringTablePtr theStringTable(
+ m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore()->GetStringTablePtr());
+ CFileSeekableIOStream theStream(inFilePath.GetCharStar(), FileReadFlags());
+ if (!theStream.IsOpen())
+ return std::shared_ptr<UICDM::IDOMReader>();
+ return DoCreateDOMReader(theStream, theStringTable, outVersion);
+}
+
+std::shared_ptr<UICDM::IDOMReader> CDoc::CreateDOMReader(CBufferedInputStream &inStream,
+ qt3ds::QT3DSI32 &outVersion)
+{
+ using namespace UICDM;
+ TStringTablePtr theStringTable(
+ m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore()->GetStringTablePtr());
+ SBufferedInputStreamInStream theStream(inStream);
+ return DoCreateDOMReader(theStream, theStringTable, outVersion);
+}
+using std::pair;
+using std::make_pair;
+using uic::render::SImageTextureData;
+
+static bool SourcePathImageBufferLessThan(const pair<Q3DStudio::CString, SImageTextureData> &lhs,
+ const pair<Q3DStudio::CString, SImageTextureData> &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+struct SBufferFilter
+{
+ Q3DStudio::TCharPtrToSlideInstanceMap &m_Map;
+ UICDM::IStringTable &m_StringTable;
+ SBufferFilter(Q3DStudio::TCharPtrToSlideInstanceMap &inMap, UICDM::IStringTable &inStrTable)
+ : m_Map(inMap)
+ , m_StringTable(inStrTable)
+ {
+ }
+
+ // We want to filter out items that aren't in the map, so we need to return true
+ // if the item is not in the map.
+ bool operator()(const std::pair<Q3DStudio::CString, SImageTextureData> &inItem) const
+ {
+ return m_Map.find(m_StringTable.GetWideStr(inItem.first.c_str())) == m_Map.end();
+ }
+};
+//==============================================================================
+/**
+ * SavePresentationFile: Saves the presentation file.
+ * @param inArchive CArchive for saving data
+ * @return true if saved successfully
+ */
+void CDoc::SavePresentationFile(CBufferedOutputStream *inOutputStream)
+{
+ using namespace std;
+ using namespace UICDM;
+ using namespace Q3DStudio;
+
+ std::shared_ptr<IDOMWriter> theWriterPtr(CreateDOMWriter());
+
+ IDOMWriter &theWriter(*theWriterPtr);
+
+ CProjectSettingsSerializer theProjectSettingsSerializer(m_Core->GetStudioProjectSettings());
+ theWriter.Serialize(L"ProjectSettings", theProjectSettingsSerializer);
+ // Ensure we have a buffer cache.
+ GetBufferCache();
+ // Ensure all images that can be referenced in any way are loaded into the document buffer
+ // cache.
+ if (m_SceneEditor && m_DocumentBufferCache) {
+ CClientDataModelBridge &theBridge = *(m_StudioSystem->GetClientDataModelBridge());
+ IPropertySystem &thePropertySystem = *(m_StudioSystem->GetPropertySystem());
+ TCharPtrToSlideInstanceMap sourcePathToInstanceMap;
+ m_SceneEditor->GetSourcePathToInstanceMap(sourcePathToInstanceMap);
+ // Ensure the image is loaded in the image buffer system
+ // because this scans the image for alpha bits.
+ for (TCharPtrToSlideInstanceMap::iterator theIter = sourcePathToInstanceMap.begin(),
+ end = sourcePathToInstanceMap.end();
+ theIter != end; ++theIter) {
+ const TSlideInstanceList &theList = theIter->second;
+ if (theList.empty())
+ continue;
+ bool isImage = false;
+ bool isInstance = false;
+ for (size_t slideInstanceIdx = 0, slideInstanceEnd = theList.size();
+ slideInstanceIdx < slideInstanceEnd && !isInstance; ++slideInstanceIdx) {
+ CUICDMInstanceHandle theInstance = theList[slideInstanceIdx].second;
+ isInstance = m_StudioSystem->IsInstance(theInstance);
+ if (isInstance)
+ isImage = thePropertySystem.IsInstanceOrDerivedFrom(
+ theInstance, theBridge.GetObjectDefinitions().m_Image.m_Instance);
+ }
+ if (isImage)
+ m_DocumentBufferCache->GetOrCreateImageBuffer(CFilePath(theIter->first));
+ }
+
+ std::vector<pair<Q3DStudio::CString, SImageTextureData>> theImageBuffers;
+ m_DocumentBufferCache->GetImageBuffers(theImageBuffers);
+
+ // Remove buffers that aren't in the map.
+ erase_if(
+ theImageBuffers,
+ SBufferFilter(sourcePathToInstanceMap,
+ *m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetStringTablePtr()));
+ if (theImageBuffers.empty() == false) {
+ // Ensure the source paths are always written out in the same order to keep source
+ // control reasonable
+ std::sort(theImageBuffers.begin(), theImageBuffers.end(),
+ SourcePathImageBufferLessThan);
+ IDOMWriter::Scope __BufferData(theWriter, L"BufferData");
+ for (size_t idx = 0, end = theImageBuffers.size(); idx < end; ++idx) {
+ SImageTextureData theBuffer = theImageBuffers[idx].second;
+ if (theBuffer.m_TextureFlags.HasTransparency()) {
+ IDOMWriter::Scope __ImageScope(theWriter, L"ImageBuffer");
+ theWriter.Att(L"sourcepath", theImageBuffers[idx].first.c_str());
+ theWriter.Att(L"hasTransparency", L"True");
+ }
+ }
+ }
+ }
+
+ std::shared_ptr<IComposerSerializer> theSerializer(CreateSerializer());
+ theSerializer->SerializeScene(theWriter);
+
+ SBufferedOutputStreamOutStream theStream(*inOutputStream);
+ CDOMSerializer::WriteXMLHeader(theStream);
+ CDOMSerializer::Write(*theWriter.GetTopElement(), theStream);
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CDoc::SetKeyframeInterpolation()
+{
+ if (m_KeyframesManager)
+ m_KeyframesManager->SetKeyframeInterpolation();
+}
+
+bool CDoc::OnNudgeKey(int inChar, int inRepeatCount, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inRepeatCount);
+
+ bool theHandledFlag = true;
+ ENudgeDirection theDir = NUDGE_NEG_X;
+ switch (inChar) {
+ case Qt::Key_Up:
+ if (CHotKeys::IsKeyDown(Qt::ShiftModifier))
+ theDir = NUDGE_POS_Z;
+ else {
+ if (CHotKeys::IsKeyDown(Qt::ControlModifier))
+ theDir = NUDGE_NEG_Y;
+ else
+ theDir = NUDGE_POS_Y;
+ }
+ break;
+
+ case Qt::Key_Down:
+ if (CHotKeys::IsKeyDown(Qt::ShiftModifier))
+ theDir = NUDGE_NEG_Z;
+ else {
+ if (CHotKeys::IsKeyDown(Qt::ControlModifier))
+ theDir = NUDGE_POS_Y;
+ else
+ theDir = NUDGE_NEG_Y;
+ }
+ break;
+
+ case Qt::Key_Left:
+ theDir = NUDGE_NEG_X;
+ break;
+
+ case Qt::Key_Right:
+ theDir = NUDGE_POS_X;
+ break;
+
+ default:
+ theHandledFlag = false;
+ break;
+ }
+
+ // TODO: need to know the tool mode
+ // Previously we query m_StudioApp->GetToolMode( ) but this is not possible anymore.
+ // Temporarily we use the keyboard to decide
+ long theToolMode = STUDIO_TOOLMODE_MOVE;
+ if (CHotKeys::IsKeyDown(Qt::ControlModifier))
+ theToolMode = STUDIO_TOOLMODE_ROTATE;
+ else if (CHotKeys::IsKeyDown(Qt::AltModifier))
+ theToolMode = STUDIO_TOOLMODE_SCALE;
+ m_Core->GetDispatch()->FireOnNudge(theDir, theToolMode, inFlags);
+
+ return theHandledFlag;
+}
+
+void CDoc::OnNudgeDone()
+{
+ m_Core->GetDispatch()->FireOnNudgeDone();
+}
+
+void CDoc::DeselectAllKeyframes()
+{
+ if (m_KeyframesManager)
+ m_KeyframesManager->DeselectAllKeyframes();
+}
+
+//==============================================================================
+/**
+ * Recursive function to get all actions affected by renaming the asset with inObjectId.
+ * I think the logic behind this is that once the parent will affect all children's path
+ *reference, and hence all its descendants' action must be checked as well.
+ */
+void CDoc::GetActionsAffectedByRename(UICDM::CUICDMInstanceHandle inAsset,
+ std::set<Q3DStudio::CString> &ioActionsAffected)
+{
+ if (!inAsset)
+ return;
+ ASSERT(0);
+ Q_UNUSED(ioActionsAffected);
+ // TODO : UICDMActionCore needs to support relative/absolute reference, and needs to implement
+ // something similar to GetAllAffectedByRename
+ // refer to CSAction::AffectedByRename on how this was implemented
+
+ // CActionManager::TActionList theActions = m_ActionManager->GetAllAffectedByRename(
+ // inAsset->GetAssetID( ) );
+ // CActionManager::TActionList::iterator thePos = theActions.begin( );
+ // for ( ; thePos != theActions.end( ); ++thePos )
+ // ioActionsAffected.insert( ( *thePos )->GetOwningState( )->GetAsset( )->GetName( ) );
+ //
+ //// process the children
+ // Q3DStudio::CGraphIterator theChildren;
+ // GetAssetChildren( this, inAsset, theChildren );
+ // for ( ; !theChildren.IsDone( ); ++theChildren )
+ //{
+ // CAsset* theChild = static_cast<CAsset*>( theChildren.GetCurrent( ) );
+ // GetActionsAffectedByRename( theChild, ioActionsAffected );
+ //}
+}
+
+//==============================================================================
+/**
+ * Image is a property of the material.
+ * Recursively iterate the images involved by the object and do either of following:
+ * a. schedule remove instance if ( outBatch != NULL )
+ * b. list the source GUID of the image if ( outImageIdList != NULL )
+ * This is so that ScheduleRemoveImageInstances & GetImageInstancesSourceGUID can share code
+ */
+void CDoc::IterateImageInstances(UICDM::CUICDMInstanceHandle inInstance,
+ std::vector<Q3DStudio::CId> *outImageIdList)
+{
+ CClientDataModelBridge *theClientBridge = GetStudioSystem()->GetClientDataModelBridge();
+
+ if (theClientBridge->IsSceneInstance(inInstance)
+ || theClientBridge->IsComponentInstance(inInstance)) // If this is a Component, return.
+ // Iterating Component has been handled
+ // by other function such as
+ // ScheduleRemoveComponentInstances
+ return;
+
+ UICDM::IPropertySystem *thePropertySystem = GetStudioSystem()->GetPropertySystem();
+ UICDM::ISlideSystem *theSlideSystem = GetStudioSystem()->GetSlideSystem();
+
+ Q3DStudio::CGraphIterator theSourceChildIterator;
+ GetAssetChildren(this, inInstance, theSourceChildIterator);
+
+ for (; !theSourceChildIterator.IsDone(); ++theSourceChildIterator) {
+ UICDM::CUICDMInstanceHandle theChildInstance = theSourceChildIterator.GetCurrent();
+ if (theClientBridge->IsMaterialInstance(theChildInstance)) {
+ UICDM::TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(theChildInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount;
+ ++thePropertyIndex) {
+ UICDM::CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ UICDM::AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(theChildInstance, theProperty);
+
+ if (theAdditionalMetaDataType == UICDM::AdditionalMetaDataType::Image) {
+ UICDM::CUICDMSlideHandle theSlide =
+ theSlideSystem->GetAssociatedSlide(theChildInstance);
+ bool theIsMaster = theSlideSystem->IsMasterSlide(theSlide);
+ if (!theIsMaster
+ || theSlideSystem->IsPropertyLinked(theChildInstance, theProperty)) {
+ UICDM::SValue theValue;
+ thePropertySystem->GetInstancePropertyValue(theChildInstance, theProperty,
+ theValue);
+ UICDM::SLong4 theDataModelImageGuid = UICDM::get<UICDM::SLong4>(theValue);
+
+ UICDM::CUICDMInstanceHandle theImageInstance =
+ theClientBridge->GetImageInstanceByGUID(theDataModelImageGuid);
+ if (theImageInstance.Valid()) {
+ // Get the image source guid
+ if (outImageIdList) {
+ outImageIdList->push_back(
+ Q3DStudio::CId(theDataModelImageGuid.m_Longs[0],
+ theDataModelImageGuid.m_Longs[1],
+ theDataModelImageGuid.m_Longs[2],
+ theDataModelImageGuid.m_Longs[3]));
+ }
+ }
+ } else {
+ UICDM::SValue theValue;
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theClientBridge->GetOrCreateGraphRoot(theChildInstance);
+
+ size_t theNumSlides = theSlideSystem->GetSlideCount(theMasterSlide);
+ for (size_t theSlideIndex = 0; theSlideIndex < theNumSlides;
+ ++theSlideIndex) {
+ if (theSlideSystem->GetSlidePropertyValue(
+ theSlideIndex, theChildInstance, theProperty, theValue)) {
+ UICDM::SLong4 theDataModelImageGuid =
+ UICDM::get<UICDM::SLong4>(theValue);
+ UICDM::CUICDMInstanceHandle theImageInstance =
+ theClientBridge->GetImageInstanceByGUID(theDataModelImageGuid);
+ if (theImageInstance.Valid()) {
+ // Get the image source guid
+ if (outImageIdList) {
+ outImageIdList->push_back(
+ Q3DStudio::CId(theDataModelImageGuid.m_Longs[0],
+ theDataModelImageGuid.m_Longs[1],
+ theDataModelImageGuid.m_Longs[2],
+ theDataModelImageGuid.m_Longs[3]));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ IterateImageInstances(theChildInstance, outImageIdList);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * @returns the object based on the selection mode
+ */
+UICDM::CUICDMInstanceHandle CDoc::GetObjectbySelectMode(UICDM::CUICDMInstanceHandle inInstance,
+ bool inGroupMode)
+{
+ UICDM::CUICDMInstanceHandle theResult = inInstance;
+
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ if (!theBridge->IsInActiveComponent(inInstance)) {
+ UICDM::CUICDMInstanceHandle theParent = theBridge->GetParentInstance(inInstance);
+ if (theParent.Valid())
+ theResult = GetObjectbySelectMode(theParent, inGroupMode);
+ else
+ theResult = 0;
+ } else {
+ if (inGroupMode) {
+ UICDM::CUICDMInstanceHandle theGroup = GetTopmostGroup(inInstance);
+ if (theGroup.Valid())
+ theResult = theGroup;
+ }
+ }
+ return theResult;
+}
+
+//=============================================================================
+/**
+ * @returns the topmost group object that owns this instance
+ */
+UICDM::CUICDMInstanceHandle CDoc::GetTopmostGroup(UICDM::CUICDMInstanceHandle inInstance)
+{
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+
+ if (theBridge->IsGroupInstance(inInstance)) {
+ UICDM::CUICDMInstanceHandle theGroup = inInstance;
+
+ // If this group has a parent
+ UICDM::CUICDMInstanceHandle theParent = theBridge->GetParentInstance(inInstance);
+ if (theParent.Valid()) {
+ UICDM::CUICDMInstanceHandle theParentGroup;
+ // Get the group object of the parent
+ if (GetActiveRootInstance()
+ == inInstance) { // check if this component is the active time context now
+ theGroup = 0;
+ } else // all other cases, try to get parent's topmost group, if any
+ {
+ theParentGroup = GetTopmostGroup(theParent);
+ }
+
+ // If another group was found higher up the chain, then it is the topmost group
+ if (theParentGroup)
+ theGroup = theParentGroup;
+ }
+
+ return theGroup;
+ } else {
+ UICDM::CUICDMInstanceHandle theParent = theBridge->GetParentInstance(inInstance);
+ if (theParent.Valid())
+ return GetTopmostGroup(theParent);
+ else
+ return 0;
+ }
+}
+
+//==============================================================================
+/**
+ * Image is a property of the material, find out all images involved by the delete
+ * object and scehedule a remove instances.
+ */
+void CDoc::ScheduleRemoveImageInstances(UICDM::CUICDMInstanceHandle inInstance,
+ CCmdBatch * /*outBatch*/)
+{
+ IterateImageInstances(inInstance, NULL);
+}
+
+//==============================================================================
+/**
+ * Remove all DataModel instances and schedule a delete
+ */
+void CDoc::ScheduleRemoveDataModelInstances(UICDM::CUICDMInstanceHandle inInstance,
+ CCmdBatch *outBatch)
+{
+ // remove my children
+ Q3DStudio::CGraphIterator theSourceChildIterator;
+ GetAssetChildren(this, inInstance, theSourceChildIterator);
+ for (; !theSourceChildIterator.IsDone(); ++theSourceChildIterator) {
+ ScheduleRemoveDataModelInstances(theSourceChildIterator.GetCurrent(), outBatch);
+ }
+
+ // Remove myself
+ CCmd *theCmd = new CCmdDataModelDeleteInstance(this, inInstance);
+ outBatch->AddCommand(theCmd);
+}
+
+//==============================================================================
+/**
+ * inObject may be a Component or it may have children Component, find out all Components involved
+ * by the delete
+ * object and scehedule a remove instances.
+ */
+void CDoc::ScheduleRemoveComponentInstances(UICDM::CUICDMInstanceHandle inInstance,
+ CCmdBatch *outBatch)
+{
+ CClientDataModelBridge *theClientBridge = GetStudioSystem()->GetClientDataModelBridge();
+ if (theClientBridge->IsComponentInstance(inInstance)) {
+ Q3DStudio::CId theInstanceId = theClientBridge->GetGUID(inInstance);
+ UICDM::CUICDMInstanceHandle theInstance =
+ theClientBridge->GetComponentInstanceByGUID(theInstanceId);
+ CCmd *theCmd = new CCmdDataModelDeleteComponentInstance(this, theInstance);
+ outBatch->AddCommand(theCmd);
+ }
+ // Recursively find the Component
+ Q3DStudio::CGraphIterator theSourceChildIterator;
+ GetAssetChildren(this, inInstance, theSourceChildIterator);
+ for (; !theSourceChildIterator.IsDone(); ++theSourceChildIterator) {
+ ScheduleRemoveComponentInstances(theSourceChildIterator.GetCurrent(), outBatch);
+ }
+}
+
+void CDoc::SetDefaultKeyframeInterpolation(bool inSmooth)
+{
+ CStudioPreferences::SetInterpolation(inSmooth);
+ GetStudioSystem()->GetAnimationSystem()->SetInterpolation(inSmooth);
+}
+
+void CDoc::AddToGraph(UICDM::CUICDMInstanceHandle inParentInstance,
+ UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (!inInstance.Valid())
+ return;
+
+ ASSERT(!m_AssetGraph->IsExist(inInstance));
+ m_AssetGraph->AddChild(inParentInstance, inInstance);
+}
+
+void CDoc::OnNewPresentation()
+{
+ m_PlaybackClock->Reset();
+ m_Core->GetDispatch()->FireOnNewPresentation();
+
+ // true to refresh
+ NotifyActiveSlideChanged(
+ m_StudioSystem->GetClientDataModelBridge()->GetComponentActiveSlide(m_SceneInstance), true);
+
+ // Boot up the document editor so we can listen to file system changes
+ // and get master behaviors updated.
+ GetDocumentReader();
+ SetupDataCoreSignals();
+}
+
+void CDoc::OnPresentationDeactivated()
+{
+}
+
+void CDoc::CheckActionDependencies(UICDM::CUICDMInstanceHandle inInstance)
+{
+ Q3DStudio::CString theListOfTargets;
+ GetActionDependencies(inInstance, theListOfTargets);
+
+ if (!theListOfTargets.IsEmpty()) {
+ if (m_DeletingReferencedObjectHandler)
+ m_DeletingReferencedObjectHandler->DisplayMessageBox(theListOfTargets);
+ }
+}
+
+QString CDoc::GetDocumentUIAFile()
+{
+ Q3DStudio::CString docDir = GetDocumentDirectory();
+ Q3DStudio::CString docName
+ = Q3DStudio::CFilePath(GetDocumentPath().GetName()).GetFileStem();
+ QString file;
+ std::vector<Q3DStudio::CFilePath> dirFiles;
+ Q3DStudio::CFilePath thePath(docDir);
+ thePath.ListFilesAndDirectories(dirFiles);
+ for (size_t idx = 0, end = dirFiles.size(); idx < end; ++idx) {
+ if (dirFiles[idx].IsFile()) {
+ Q3DStudio::CString ext = dirFiles[idx].GetExtension();
+ if (ext.CompareNoCase("uia") && dirFiles[idx].GetFileStem() == docName) {
+ file = dirFiles[idx].toQString();
+ break;
+ }
+ }
+ }
+ return file;
+}
+
+void CDoc::LoadUIASubpresentations(const QString &uiaFile,
+ QVector<SubPresentationRecord> &subpresentations)
+{
+ const QFileInfo info(uiaFile);
+ QString initialPresentation = info.fileName().split(".").first();
+
+ if (QFileInfo::exists(uiaFile)) {
+ UICDM::TStringTablePtr theStringTable = UICDM::IStringTable::CreateStringTable();
+ std::shared_ptr<UICDM::IDOMFactory> theDomFact =
+ UICDM::IDOMFactory::CreateDOMFactory(theStringTable);
+
+ qt3ds::foundation::CFileSeekableIOStream theStream(
+ uiaFile, qt3ds::foundation::FileReadFlags());
+
+ UICDM::SDOMElement *theElem = UICDM::CDOMSerializer::Read(*theDomFact, theStream);
+ if (theElem) {
+ std::shared_ptr<UICDM::IDOMReader> theReader =
+ UICDM::IDOMReader::CreateDOMReader(*theElem, theStringTable, theDomFact);
+ if (theReader->MoveToFirstChild("assets")) {
+ UICDM::TXMLStr initial = nullptr;
+
+ // initial should be the same as document name
+ if (theReader->Att("initial", initial))
+ initialPresentation = QString(initial.c_str());
+
+ for (bool success = theReader->MoveToFirstChild(); success;
+ success = theReader->MoveToNextSibling()) {
+ if (UICDM::AreEqual(theReader->GetElementName(), L"presentation") ||
+ UICDM::AreEqual(theReader->GetElementName(), L"presentation-qml")) {
+ UICDM::TXMLStr src = nullptr;
+ UICDM::TXMLStr id = nullptr;
+ UICDM::TXMLStr args = nullptr;
+ SubPresentationRecord rec;
+
+ rec.m_type = QString::fromWCharArray(theReader->GetElementName());
+ theReader->Att("id", id);
+ rec.m_id = QString(id.c_str());
+ if (rec.m_id != initialPresentation) {
+ if (theReader->Att("src", src))
+ rec.m_argsOrSrc = QString(src.c_str());
+ if (theReader->Att("args", args))
+ rec.m_argsOrSrc = QString(args.c_str());
+
+ subpresentations.push_back(rec);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.h b/src/Authoring/Client/Code/Core/Doc/Doc.h
new file mode 100644
index 00000000..e13c6616
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/Doc.h
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_DOC_H
+#define INCLUDED_DOC_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Conditional.h"
+#include "UICFile.h"
+#include "UICRect.h"
+#include "IDoc.h"
+#include "GUIDUtilities.h"
+#include "StudioErrorIDs.h"
+#include "GraphUtils.h"
+#include "CmdStackModifier.h"
+#include "UICColor.h"
+#include "SelectedValueImpl.h"
+#include "Utility/CoreConst.h"
+#include <quuid.h>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CScene;
+class CCamera;
+class CLight;
+class CHotKeys;
+class CCmdBatch;
+class CStudioProjectSettings;
+class CView;
+class ISelectable;
+class CBufferedInputStream;
+class CBufferedOutputStream;
+class CDataManager;
+class CClientDataModelBridge;
+class IUICDMSerializer;
+class IKeyframesManager;
+class IObjectReferenceHelper;
+class CCore;
+class CRenderContext;
+class CPlaybackClock;
+
+namespace Q3DStudio {
+class IInternalDocumentEditor;
+class CFilePath;
+class IInternalDirectoryWatchingSystem;
+class IDirectoryWatchingSystem;
+class IImportFailedHandler;
+class IDeletingReferencedObjectHandler;
+class CTransactionCloseListenerSignaller;
+class IDocSceneGraph;
+struct SSelectedValue;
+}
+
+namespace UICDM {
+class CStudioSystem;
+class ISignalConnection;
+class CmdDataModel;
+}
+
+struct SDocumentDataModelListener;
+
+namespace std {
+template <>
+struct hash<GUID>
+{
+ size_t operator()(const GUID &guid) const
+ {
+ QUuid quuid;
+ quuid.data1 = guid.Data1;
+ quuid.data2 = guid.Data2;
+ quuid.data3 = guid.Data3;
+ memcpy(quuid.data4, guid.Data4, 8);
+ return qHash(quuid);
+ }
+};
+struct AreGuidsEqual
+{
+
+ bool operator()(const GUID &lhs, const GUID &rhs) const
+ {
+ return memcmp(&lhs, &rhs, sizeof(GUID)) == 0;
+ }
+};
+}
+
+
+struct SubPresentationRecord
+{
+ QString m_type;
+ QString m_id;
+ QString m_argsOrSrc;
+
+ SubPresentationRecord() {}
+ SubPresentationRecord(const QString &type, const QString &id, const QString &args)
+ : m_type(type), m_id(id), m_argsOrSrc(args)
+ {
+
+ }
+
+ SubPresentationRecord &operator = (const SubPresentationRecord& o)
+ {
+ m_type = o.m_type;
+ m_id = o.m_id;
+ m_argsOrSrc = o.m_argsOrSrc;
+ return *this;
+ }
+};
+
+//==============================================================================
+// CDoc Class
+//==============================================================================
+
+class CDoc : public IDoc, public ICmdStackModifier
+{
+
+public:
+ friend struct SDocumentDataModelListener;
+ CDoc(CCore *inCore);
+ virtual ~CDoc();
+
+ DEFINE_OBJECT_COUNTER(CDoc)
+
+ void
+ SetDirectoryWatchingSystem(std::shared_ptr<Q3DStudio::IDirectoryWatchingSystem> inSystem);
+ void SetImportFailedHandler(std::shared_ptr<Q3DStudio::IImportFailedHandler> inHandler);
+ std::shared_ptr<Q3DStudio::IImportFailedHandler> GetImportFailedHandler();
+ void SetDocMessageBoxHandler(
+ std::shared_ptr<Q3DStudio::IDeletingReferencedObjectHandler> inHandler);
+
+ // The system may be null in the case where we are running without a UI.
+ Q3DStudio::IDirectoryWatchingSystem *GetDirectoryWatchingSystem();
+ void SetDocumentPath(const CUICFile &inFile);
+ CUICFile GetDocumentPath() const;
+ bool IsInDocSubDirectory(const Q3DStudio::CString &inPath) const;
+ Q3DStudio::CString GetDocumentDirectory() const;
+ Q3DStudio::CString GetRelativePathToDoc(const Q3DStudio::CFilePath &inPath);
+ Q3DStudio::CString GetResolvedPathToDoc(const Q3DStudio::CFilePath &inPath);
+
+ CUICFile CreateUntitledDocument() const;
+
+ void CloseDocument();
+ void LoadDocument(const CUICFile &inDocument);
+ void SaveDocument(const CUICFile &inDocument);
+ void CreateNewDocument();
+ QString GetDocumentUIAFile();
+ void LoadUIASubpresentations(const QString &uiaFile,
+ QVector<SubPresentationRecord> &subpresentations);
+
+ bool IsModified();
+ bool IsValid() const;
+
+ UICDM::CUICDMInstanceHandle GetInstanceFromSelectable(Q3DStudio::SSelectedValue inSelectedItem);
+ UICDM::CUICDMInstanceHandle GetSelectedInstance();
+
+ void CutSelectedObject();
+ void DeleteSelectedObject();
+ bool DeleteSelectedKeys();
+ void SetChangedKeyframes();
+
+ // Cut object to clipboard
+ void CutObject(UICDM::TInstanceHandleList inInstance);
+ void CutObject(UICDM::CUICDMInstanceHandle inInstance)
+ {
+ UICDM::TInstanceHandleList objects;
+ objects.push_back(inInstance);
+ CutObject(objects);
+ }
+ // copy object to clipboard
+ void CopyObject(UICDM::TInstanceHandleList inInstance);
+ void CopyObject(UICDM::CUICDMInstanceHandle inInstance)
+ {
+ UICDM::TInstanceHandleList objects;
+ objects.push_back(inInstance);
+ CopyObject(objects);
+ }
+ // paste object to clipboard
+ void PasteObject(UICDM::CUICDMInstanceHandle inInstance);
+ void PasteObjectMaster(UICDM::CUICDMInstanceHandle inInstance);
+ void DeleteObject(const UICDM::TInstanceHandleList &inInstances);
+
+ void DeleteObject(UICDM::CUICDMInstanceHandle inInstance)
+ {
+ UICDM::TInstanceHandleList theInstances;
+ theInstances.push_back(inInstance);
+ DeleteObject(theInstances);
+ }
+
+ void ClientStep();
+
+ void HandleCopy();
+ void HandlePaste();
+ void HandleMasterPaste();
+ void HandleCut();
+
+ bool CanCopyObject(); // specifically for objects
+ bool CanCopyObject(const UICDM::TInstanceHandleList &inInstances); // specifically for objects
+ bool CanCopyKeyframe(); // specifically for keyframes
+ bool CanCopyAction(); // specifically for actions
+ bool CanPasteObject(); // specifically for objects
+ bool CanPasteKeyframe(); // specifically for keyframes
+ bool CanPasteAction(); // specifically for actions
+
+ bool CanPaste(); // for objects or keyframes or actions
+ bool CanCopy(); // for objects or keyframes or actions
+ bool CanCut(); // for objects or keyframes or actions
+ void HandleDuplicateCommand();
+
+ bool VerifyCanRename(UICDM::CUICDMInstanceHandle inAsset);
+
+ void DeselectAllItems(bool inSendEvent);
+ void DeselectAllItems() { DeselectAllItems(true); }
+
+ UICDM::CUICDMInstanceHandle GetActiveLayer();
+ void SetActiveLayer(UICDM::CUICDMInstanceHandle inLayerInstance);
+ UICDM::CUICDMSlideHandle GetActiveSlide();
+ void OnLayerDeleted(UICDM::CUICDMInstanceHandle inLayerInstance);
+
+ void SetPlayMode(EPlayMode inPlayMode, long inRestoreTime = -1);
+ bool IsPlaying();
+ long GetCurrentClientTime();
+
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+
+ UICDM::CUICDMInstanceHandle GetSceneInstance() { return m_SceneInstance; }
+
+ // IDoc
+ virtual UICDM::CUICDMInstanceHandle GetActiveRootInstance();
+ long GetCurrentViewTime() const override;
+ virtual void OnComponentSeconds();
+ // Notify time changed and set the playback clock to this time.
+ void NotifyTimeChanged(long inNewTime) override;
+ // Notify time changed.
+ virtual void DoNotifyTimeChanged(long inNewTime);
+ void NotifyActiveSlideChanged(UICDM::CUICDMSlideHandle inNewActiveSlide) override;
+ void NotifyActiveSlideChanged(UICDM::CUICDMSlideHandle inNewActiveSlide,
+ bool inForceRefresh,
+ bool inIgnoreLastDisplayTime = false) override;
+ virtual void
+ NotifySelectionChanged(Q3DStudio::SSelectedValue inNewSelection = Q3DStudio::SSelectedValue()) override;
+ virtual Q3DStudio::SSelectedValue GetSelectedValue() const { return m_SelectedValue; }
+ void SetKeyframeInterpolation() override;
+ void DeselectAllKeyframes() override;
+ void SetModifiedFlag(bool inIsModified = true) override;
+ void SetKeyframesManager(IKeyframesManager *inManager) override;
+ IKeyframesManager *GetKeyframesManager() override;
+ UICDM::IPropertySystem *GetPropertySystem() override;
+ UICDM::IAnimationCore *GetAnimationCore() override;
+ void SetInstancePropertyValue(UICDM::CUICDMInstanceHandle inInstance,
+ const std::wstring &inPropertyName,
+ const UICDM::SValue &inValue) override;
+ Q3DStudio::IDocumentBufferCache &GetBufferCache() override;
+ Q3DStudio::IDocumentReader &GetDocumentReader() override;
+ Q3DStudio::IDocumentEditor &OpenTransaction(const Q3DStudio::CString &inCmdName,
+ const char *inFile, int inLine) override;
+ Q3DStudio::IDocumentEditor &MaybeOpenTransaction(const Q3DStudio::CString &cmdName,
+ const char *inFile, int inLine) override;
+ bool IsTransactionOpened() const override;
+ void RollbackTransaction() override;
+ void CloseTransaction() override;
+ void IKnowWhatIAmDoingForceCloseTransaction() override;
+
+ std::shared_ptr<Q3DStudio::IComposerSerializer> CreateSerializer() override;
+ virtual std::shared_ptr<Q3DStudio::IComposerSerializer> CreateTransactionlessSerializer();
+ // Create a DOM writer that is opened to the project element. This is where the serializer
+ // should write to.
+ std::shared_ptr<UICDM::IDOMWriter> CreateDOMWriter() override;
+ // Create a DOM reader and check that the top element's version is correct. Opens the reader
+ // to the project element.
+ virtual std::shared_ptr<UICDM::IDOMReader>
+ CreateDOMReader(const Q3DStudio::CString &inFilePath, qt3ds::QT3DSI32 &outVersion) override;
+ virtual std::shared_ptr<UICDM::IDOMReader> CreateDOMReader(CBufferedInputStream &inStream,
+ qt3ds::QT3DSI32 &outVersion);
+
+ void SelectUICDMObject(UICDM::CUICDMInstanceHandle inInstanceHandle);
+ // multiselect support
+ void ToggleUICDMObjectToSelection(UICDM::CUICDMInstanceHandle inInstanceHandle);
+ void SelectAndNavigateToUICDMObject(UICDM::CUICDMInstanceHandle inInstanceHandle);
+ long GetLatestEndTime();
+
+ CCore *GetCore() override;
+
+ void TruncateTimebar(bool inSetStart, bool inAffectsChildren);
+
+ // Helper methods for Edit Camera
+ // These need to move to the render system.
+ // They are view specific properties and have nothing to do with
+ // the document.
+ /*
+ CEditCameraContainer* GetEditCameraContainer( );
+ CCamera* GetCurrentEditCamera( );
+ CLight* GetEditingLight( );
+ long GetEditingFillMode( );
+ bool IsInEditMode( );
+ void SetEditViewBackgroundColor( ::CColor& inColor
+ );
+ Q3DStudio::CColor GetEditViewBackgroundColor( );
+ */
+
+ UICDM::CStudioSystem *GetStudioSystem() override { return m_StudioSystem.get(); }
+
+ IObjectReferenceHelper *GetDataModelObjectReferenceHelper() const
+ {
+ return m_DataModelObjectRefHelper;
+ }
+
+ void SetDefaultKeyframeInterpolation(bool inSmooth);
+ void ScheduleRemoveImageInstances(UICDM::CUICDMInstanceHandle inInstance, CCmdBatch *outBatch);
+ void ScheduleRemoveDataModelInstances(UICDM::CUICDMInstanceHandle inInstance,
+ CCmdBatch *outBatch);
+ void ScheduleRemoveComponentInstances(UICDM::CUICDMInstanceHandle inInstance,
+ CCmdBatch *outBatch);
+
+ TAssetGraphPtr GetAssetGraph() { return m_AssetGraph; }
+ virtual void AddToGraph(UICDM::CUICDMInstanceHandle inParentInstance,
+ UICDM::CUICDMInstanceHandle inInstance);
+
+ // helper
+ void IterateImageInstances(UICDM::CUICDMInstanceHandle inInstance,
+ std::vector<Q3DStudio::CId> *outImageIdList);
+ UICDM::CUICDMInstanceHandle GetObjectbySelectMode(UICDM::CUICDMInstanceHandle inInstance,
+ bool inGroupMode);
+
+ // ICmdStackModifier
+ bool CanUndo() override;
+ bool PreUndo() override;
+
+ void CheckActionDependencies(UICDM::CUICDMInstanceHandle inInstance);
+ void SetActiveSlideWithTransaction(UICDM::CUICDMSlideHandle inNewActiveSlide);
+
+ void SetSceneGraph(std::shared_ptr<Q3DStudio::IDocSceneGraph> inGraph);
+ Q3DStudio::IDocSceneGraph *GetSceneGraph() { return m_SceneGraph.get(); }
+
+ void GetProjectFonts(
+ std::vector<std::pair<Q3DStudio::CString, Q3DStudio::CString>> &outFontNameFileList);
+ void GetProjectFonts(std::vector<Q3DStudio::CString> &outFonts);
+ Q3DStudio::CString
+ GetProjectFontName(const Q3DStudio::CFilePath
+ &inFullPathToFontFile); // Given a font file, return the font name
+
+protected:
+ // Set the active slide, return true if delving
+ void SetActiveSlideChange(UICDM::CUICDMSlideHandle inNewActiveSlide);
+ void OnSlideDeleted(UICDM::CUICDMSlideHandle inSlide);
+ void OnInstanceDeleted(UICDM::CUICDMInstanceHandle inInstance);
+ Q3DStudio::SSelectedValue SetupInstanceSelection(UICDM::CUICDMInstanceHandle inInstance);
+ // Set the selection, but don't send an event.
+ bool SetSelection(Q3DStudio::SSelectedValue inNewSelection = Q3DStudio::SSelectedValue());
+ void LoadPresentationFile(CBufferedInputStream *inInputStream);
+ void SavePresentationFile(CBufferedOutputStream *inOutputStream);
+
+ void CleanupData();
+ void ResetData();
+ void LoadStudioData(CBufferedInputStream *inInputStream);
+ void ResetDataCore();
+ void SetupDataCoreSignals();
+
+ void CreatePresentation();
+ void ClosePresentation();
+
+ void DeleteSelectedItems();
+ void GetActionDependencies(UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CString &ioActionDependencies);
+ void GetActionDependencies(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::TActionHandleList &ioActionList);
+
+ bool OnNudgeKey(int inChar, int inRepeatCount, Qt::KeyboardModifiers modifiers);
+ void OnNudgeDone();
+
+ UICDM::CUICDMInstanceHandle GetFirstSelectableLayer();
+ UICDM::CUICDMInstanceHandle GetTopmostGroup(UICDM::CUICDMInstanceHandle inInstance);
+
+ void GetActionsAffectedByRename(UICDM::CUICDMInstanceHandle inAsset,
+ std::set<Q3DStudio::CString> &ioActionsAffected);
+
+ bool isFocusOnTextEditControl();
+
+ //==========================================================================
+ // Protected Fields
+ //==========================================================================
+
+ long m_PlayMode; ///< This tracks whether we're playing a client presentation or not.
+ Q3DStudio::SSelectedValue m_SelectedObject; ///< DIE USELESS COMMENTS DIE.
+ long m_CurrentViewTime; ///< The current time that is displayed by the playhead, not necessarily
+ ///the client time.
+ UICDM::CUICDMInstanceHandle m_SceneInstance; ///< Pointer to the root level Scene object.
+ UICDM::CUICDMSlideHandle m_ActiveSlide; ///< The currently active Slide Handle.
+ UICDM::CUICDMInstanceHandle m_ActiveLayer; ///< The currently active layer.
+ CPlaybackClock *m_PlaybackClock; ///< Playback clock. This is used when user clicks "Play"
+ CCore *m_Core;
+ bool m_IsModified;
+ bool m_IsTemporary;
+ CUICFile m_DocumentPath;
+
+ CDataManager *m_DataManager; ///< Manager for handling data properties.
+
+ std::shared_ptr<UICDM::CStudioSystem> m_StudioSystem;
+
+ IKeyframesManager *m_KeyframesManager; ///< To support menu actions for selected keys
+
+ IObjectReferenceHelper *m_DataModelObjectRefHelper; ///< To support object reference control
+
+ TAssetGraphPtr m_AssetGraph;
+
+ std::shared_ptr<Q3DStudio::IInternalDocumentEditor> m_SceneEditor;
+ std::shared_ptr<SDocumentDataModelListener> m_DataModelListener;
+ std::shared_ptr<Q3DStudio::IDocumentBufferCache> m_DocumentBufferCache;
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>> m_Connections;
+ std::shared_ptr<Q3DStudio::IDirectoryWatchingSystem> m_DirectoryWatchingSystem;
+ std::shared_ptr<Q3DStudio::IImportFailedHandler> m_ImportFailedHandler;
+ std::shared_ptr<Q3DStudio::IDeletingReferencedObjectHandler>
+ m_DeletingReferencedObjectHandler;
+ long m_TransactionDepth;
+ std::shared_ptr<UICDM::CmdDataModel> m_OpenTransaction;
+ std::shared_ptr<Q3DStudio::IDocSceneGraph> m_SceneGraph;
+ Q3DStudio::SSelectedValue m_SelectedValue;
+
+ void GetOrUpdateFileList(std::vector<Q3DStudio::CString> &ioMyList,
+ std::vector<Q3DStudio::CString> &outResult,
+ const wchar_t **inExtensionList) const;
+
+public:
+ void OnNewPresentation();
+ void OnPresentationDeactivated();
+
+protected:
+ CRenderContext *m_RenderContext; ///< The render context attached to this player's window.
+ UICRenderDevice m_WindowHandle; ///< The window handle to which to render
+ Q3DStudio::CRect m_ClientSize;
+ Q3DStudio::CRect m_SceneRect; ///< The dimensions of the active scene view
+};
+
+#endif // INCLUDED_DOC_H
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp
new file mode 100644
index 00000000..e926b0eb
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "IDocumentBufferCache.h"
+#include "Doc.h"
+#include "foundation/Qt3DS.h"
+#include "UICDMStringTable.h"
+#include "EASTL/hash_map.h"
+#include "UICRenderBufferManager.h"
+#include "foundation/StringTable.h"
+#include "UICRenderMesh.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "IDocSceneGraph.h"
+#include <unordered_map>
+
+using namespace Q3DStudio;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace std;
+using qt3ds::foundation::IStringTable;
+using qt3ds::foundation::CRegisteredString;
+
+namespace {
+
+using std::unordered_map;
+typedef unordered_map<const wchar_t *, SRenderMesh *> TStringBufferMap;
+
+struct SModelBufferOrImage
+{
+ // A file can contain multiple model buffers and we want to be accurate about reflecting this.
+ TStringBufferMap m_ModelBuffers;
+ Option<SImageTextureData> m_ImageBuffer;
+
+ SModelBufferOrImage() {}
+ SModelBufferOrImage(SImageTextureData &imageBuffer)
+ : m_ImageBuffer(imageBuffer)
+ {
+ }
+ void AddModelBuffer(const wchar_t *inBufferPath, SRenderMesh *inBuffer)
+ {
+ pair<TStringBufferMap::iterator, bool> theInsertResult(
+ m_ModelBuffers.insert(make_pair(inBufferPath, inBuffer)));
+ if (theInsertResult.second == false)
+ theInsertResult.first->second = inBuffer;
+ }
+ SModelBufferAndPath FindModelBuffer(const wchar_t *inFullPath)
+ {
+ TStringBufferMap::iterator theBuffer = m_ModelBuffers.find(inFullPath);
+ if (theBuffer != m_ModelBuffers.end())
+ return SModelBufferAndPath(theBuffer->second, CFilePath(inFullPath));
+ return SModelBufferAndPath();
+ }
+ void Release() {}
+};
+
+struct SDocBufferCache : public IDocumentBufferCache
+{
+ CDoc &m_Doc;
+ // This object cannot at this time have a ref count to the
+ // buffer manager because in some cases will be destroyed after the gl context
+ // is shut down thus causing chaos when the vertex buffers are released.
+
+ typedef unordered_map<const wchar_t *, SModelBufferOrImage> TBufferHashMap;
+
+ UICDM::TStringTablePtr m_StringTablePtr;
+ TBufferHashMap m_Buffers;
+ bool m_HasPrimitiveBuffers;
+
+ SDocBufferCache(CDoc &inDoc)
+ : m_Doc(inDoc)
+ , m_StringTablePtr(UICDM::IStringTable::CreateStringTable())
+ , m_HasPrimitiveBuffers(false)
+ {
+ }
+
+ ~SDocBufferCache() { m_Buffers.clear(); }
+
+ IBufferManager *GetBufferManager()
+ {
+ if (m_Doc.GetSceneGraph()) {
+ return m_Doc.GetSceneGraph()->GetBufferManager();
+ }
+ return NULL;
+ }
+
+ void Reset()
+ {
+ m_Buffers.clear();
+ m_HasPrimitiveBuffers = false;
+ if (GetBufferManager())
+ GetBufferManager()->Clear();
+ }
+
+ void InvalidateBuffer(const CFilePath &inPath) override
+ {
+ CFilePath theFullPath = m_Doc.GetResolvedPathToDoc(inPath);
+ if (GetBufferManager())
+ GetBufferManager()->InvalidateBuffer(
+ GetBufferManager()->GetStringTable().RegisterStr(theFullPath.c_str()));
+
+ TBufferHashMap::iterator entry(
+ m_Buffers.find(m_StringTablePtr->RegisterStr(inPath.GetPathWithoutIdentifier())));
+ if (entry != m_Buffers.end()) {
+ const_cast<SModelBufferOrImage &>(entry->second).Release();
+ m_Buffers.erase(entry);
+ m_Doc.GetCore()->GetDispatch()->FireDocumentBufferCacheInvalidated(inPath);
+ }
+ }
+
+ // Names are declared in the same order as the primitives
+ // offset by the empty primitive
+ const wchar_t **GetPrimitiveNames() override
+ {
+ static const wchar_t *retval[] = {
+ L"#Rectangle", L"#Sphere", L"#Cone", L"#Cylinder", L"#Cube", NULL,
+ };
+ return retval;
+ }
+
+ const wchar_t *GetPrimitiveName(EPrimitiveType inPrimitiveType) override
+ {
+ if (inPrimitiveType != PRIMITIVETYPE_UNKNOWN) {
+ int theType(inPrimitiveType - 1);
+ const wchar_t **theNames = GetPrimitiveNames();
+ for (const wchar_t **theIter = theNames; theIter && *theIter; ++theIter, --theType) {
+ if (theType == 0)
+ return *theIter;
+ }
+ }
+ return L"";
+ }
+
+ void AddModelBuffer(const CFilePath inFile, SRenderMesh *inBuffer)
+ {
+ const wchar_t *thePath(m_StringTablePtr->RegisterStr(inFile.GetPathWithoutIdentifier()));
+ TBufferHashMap::iterator theBufPtr =
+ m_Buffers.insert(make_pair(thePath, SModelBufferOrImage())).first;
+ const wchar_t *theFileWithId(m_StringTablePtr->RegisterStr(inFile));
+ theBufPtr->second.AddModelBuffer(theFileWithId, inBuffer);
+ }
+
+ void BuildPrimitive(EPrimitiveType inPrimitiveType)
+ {
+ const wchar_t *thePrimitiveName(GetPrimitiveName(inPrimitiveType));
+ if (GetBufferManager()) {
+ SRenderMesh *theBuffer = GetBufferManager()->LoadMesh(
+ GetBufferManager()->GetStringTable().RegisterStr(thePrimitiveName));
+ AddModelBuffer(CFilePath(thePrimitiveName), theBuffer);
+ }
+ }
+
+ void CheckAndCreatePrimitiveBuffers()
+ {
+ if (m_HasPrimitiveBuffers)
+ return;
+ m_HasPrimitiveBuffers = true;
+ BuildPrimitive(PRIMITIVETYPE_BOX);
+ BuildPrimitive(PRIMITIVETYPE_CONE);
+ BuildPrimitive(PRIMITIVETYPE_CYLINDER);
+ BuildPrimitive(PRIMITIVETYPE_RECT);
+ BuildPrimitive(PRIMITIVETYPE_SPHERE);
+ }
+
+ SModelBufferAndPath GetOrCreateModelBuffer(const CFilePath &inPath) override
+ {
+ CheckAndCreatePrimitiveBuffers();
+
+ const TBufferHashMap::iterator entry(
+ m_Buffers.find(m_StringTablePtr->RegisterStr(inPath.GetPathWithoutIdentifier())));
+ if (entry != m_Buffers.end()) {
+ SModelBufferAndPath retval =
+ entry->second.FindModelBuffer(m_StringTablePtr->RegisterStr(inPath.c_str()));
+ if (retval.m_ModelBuffer)
+ return retval;
+ }
+
+ if (inPath.size() == 0 || inPath[0] == '#')
+ return SModelBufferAndPath();
+
+ CFilePath theFullPath(m_Doc.GetResolvedPathToDoc(inPath));
+ SModelBufferAndPath retval;
+ if (theFullPath.IsFile()) {
+ if (GetBufferManager()) {
+ SRenderMesh *theMesh = GetBufferManager()->LoadMesh(
+ GetBufferManager()->GetStringTable().RegisterStr(theFullPath.c_str()));
+ if (theMesh) {
+ theFullPath.SetIdentifier(theMesh->m_MeshId);
+ retval = SModelBufferAndPath(theMesh, theFullPath);
+ }
+ }
+ }
+ if (retval.m_ModelBuffer)
+ AddModelBuffer(inPath, retval.m_ModelBuffer);
+ return retval;
+ }
+
+ SImageTextureData GetOrCreateImageBuffer(const CFilePath &inPath) override
+ {
+ const TBufferHashMap::iterator entry(m_Buffers.find(m_StringTablePtr->RegisterStr(inPath)));
+ if (entry != m_Buffers.end() && entry->second.m_ImageBuffer.hasValue())
+ return entry->second.m_ImageBuffer;
+ CFilePath thePath(m_Doc.GetResolvedPathToDoc(inPath));
+ SImageTextureData retval;
+ if (thePath.IsFile() && GetBufferManager()) {
+ retval = GetBufferManager()->LoadRenderImage(
+ GetBufferManager()->GetStringTable().RegisterStr(thePath));
+ }
+ if (retval.m_Texture)
+ m_Buffers.insert(
+ make_pair(m_StringTablePtr->RegisterStr(inPath), SModelBufferOrImage(retval)));
+ return retval;
+ }
+
+ virtual void
+ GetImageBuffers(std::vector<std::pair<Q3DStudio::CString, SImageTextureData>> &outBuffers) override
+ {
+ for (TBufferHashMap::iterator theIter = m_Buffers.begin(), theEnd = m_Buffers.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->second.m_ImageBuffer.hasValue())
+ outBuffers.push_back(
+ make_pair(Q3DStudio::CString(theIter->first), theIter->second.m_ImageBuffer));
+ }
+ }
+
+ void Clear() override { Reset(); }
+};
+}
+
+std::shared_ptr<IDocumentBufferCache> IDocumentBufferCache::CreateBufferCache(CDoc &inDoc)
+{
+ return std::make_shared<SDocBufferCache>(std::ref(inDoc));
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
new file mode 100644
index 00000000..c115b4ba
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
@@ -0,0 +1,4874 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "IDocumentEditor.h"
+#include "Doc.h"
+#include "UICFileTools.h"
+#include "StudioFullSystem.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "StudioCoreSystem.h"
+#include "StudioFullSystem.h"
+#include "CmdDataModel.h"
+#include "UICDMStudioSystem.h"
+#include "SlideSystem.h"
+#include "UICDMAnimation.h"
+#include "ClientDataModelBridge.h"
+#include "Cmd.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "UICImportPerformImport.h"
+#include "UICImportTranslation.h"
+#include "UICImport.h"
+#include "UICFileTools.h"
+#include "StudioFullSystem.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "StudioCoreSystem.h"
+#include "IDocumentBufferCache.h"
+#include "UICImportMesh.h"
+#include "UICDMSlideGraphCore.h"
+#include "IComposerEditorInterface.h"
+#include "UICDMXML.h"
+#include "foundation/IOStreams.h"
+#include "IComposerSerializer.h"
+#include "UICDMWStrOpsImpl.h"
+#include "UICDMMetaData.h"
+#include "DocumentResourceManagerLuaParser.h"
+#include "DocumentResourceManagerScriptParser.h"
+#include "DocumentResourceManagerRenderPluginParser.h"
+#include "DocumentResourceManagerCustomMaterialParser.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "IDirectoryWatchingSystem.h"
+#include "UICDMActionCore.h"
+#include "ActionSystem.h"
+#include "StandardExtensions.h"
+#include "UICRenderMesh.h"
+#include "UICRenderImage.h"
+#include "IDocSceneGraph.h"
+#include "UICTextRenderer.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "Q3DStudioNVFoundation.h"
+#include "UICDMGuides.h"
+#include "UICRenderPathManager.h"
+#include "UICImportPath.h"
+#include "DynamicLua.h"
+#include "Dialogs.h"
+#include "foundation/Qt3DSLogging.h"
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtCore/qdir.h>
+#include <unordered_set>
+
+extern "C" {
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+}
+
+namespace {
+
+using namespace Q3DStudio;
+using namespace UICDM;
+using namespace UICIMP;
+using namespace Q3DStudio::ComposerImport;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using std::unordered_map;
+
+inline float ToDeg(float numberRad)
+{
+ // NVMathUtil.h. can't include it due to compile errors
+ return (QT3DSF32)57.29577951308232286465 * numberRad;
+}
+
+inline SFloat3 ToUICDM(QT3DSVec3 inData)
+{
+ return SFloat3(inData.x, inData.y, inData.z);
+}
+
+inline SFloat2 ToUICDM(QT3DSVec2 inData)
+{
+ return SFloat2(inData.x, inData.y);
+}
+
+inline QT3DSVec2 ToFnd(SFloat2 value)
+{
+ return QT3DSVec2(value.m_Floats[0], value.m_Floats[1]);
+}
+
+inline QT3DSF32 ToUICDM(Option<QT3DSF32> inValue, QT3DSF32 inDefault)
+{
+ if (inValue.hasValue())
+ return *inValue;
+ return inDefault;
+}
+
+inline bool ToUICDM(Option<bool> inValue, bool inDefault)
+{
+ if (inValue.hasValue())
+ return *inValue;
+ return inDefault;
+}
+
+struct ScopedBoolean
+{
+ bool &m_Value;
+ ScopedBoolean(bool &val)
+ : m_Value(val)
+ {
+ m_Value = !m_Value;
+ }
+ ~ScopedBoolean() { m_Value = !m_Value; }
+};
+
+typedef qt3ds::foundation::NVScopedRefCounted<uic::render::IInputStreamFactory> TStreamFactoryPtr;
+
+struct SImportXmlErrorHandler : public CXmlErrorHandler
+{
+ std::shared_ptr<IImportFailedHandler> m_handler;
+ QString m_fullPathToDocument;
+ SImportXmlErrorHandler(std::shared_ptr<IImportFailedHandler> hdl,
+ const Q3DStudio::CString &inFullPathToDocument)
+ : m_handler(hdl)
+ , m_fullPathToDocument(inFullPathToDocument.toQString())
+ {
+ }
+ void OnXmlError(TWideXMLCharPtr errorName, int line, int) override
+ {
+ if (m_handler) {
+ const QString str = QObject::tr("Failed to parse Lua data\n%1 on line %2\n")
+ .arg(Q3DStudio::CString(errorName).toQString()).arg(line);
+ m_handler->DisplayImportFailed(m_fullPathToDocument, str, false);
+ }
+ }
+};
+
+class CDocEditor : public Q3DStudio::IInternalDocumentEditor
+{
+
+ CDoc &m_Doc;
+ Q3DStudio::CGraph &m_AssetGraph;
+ CStudioSystem &m_StudioSystem;
+ IDataCore &m_DataCore;
+ ISlideSystem &m_SlideSystem;
+ ISlideCore &m_SlideCore;
+ ISlideGraphCore &m_SlideGraphCore;
+ IAnimationCore &m_AnimationCore;
+ CClientDataModelBridge &m_Bridge;
+ IPropertySystem &m_PropertySystem;
+ IMetaData &m_MetaData;
+ IActionSystem &m_ActionSystem;
+ IActionCore &m_ActionCore;
+ IStudioAnimationSystem &m_AnimationSystem;
+ IGuideSystem &m_GuideSystem;
+ // Items should be added to every slide the parent object exists in.
+ std::shared_ptr<ISignalConnection> m_ProjectDirWatcher;
+ bool m_IgnoreDirChange;
+ TCharPtrToSlideInstanceMap m_SourcePathInstanceMap;
+ unordered_map<TCharPtr, TCharPtr> m_ImportFileToDAEMap;
+ UICDM::IStringTable &m_StringTable;
+ Q3DStudio::Foundation::SStudioFoundation m_Foundation;
+ TStreamFactoryPtr m_InputStreamFactory;
+ std::unordered_map<long, QT3DSU32> m_GraphOrderMap;
+ IDynamicLua *m_LuaState;
+
+public:
+ CDocEditor(CDoc &inDoc)
+ : m_Doc(inDoc)
+ , m_AssetGraph(*m_Doc.GetAssetGraph())
+ , m_StudioSystem(*m_Doc.GetStudioSystem())
+ , m_DataCore(*m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetDataCore())
+ , m_SlideSystem(*m_StudioSystem.GetFullSystem()->GetSlideSystem())
+ , m_SlideCore(*m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetSlideCore())
+ , m_SlideGraphCore(*m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetSlideGraphCore())
+ , m_AnimationCore(*m_StudioSystem.GetFullSystem()->GetAnimationCore())
+ , m_Bridge(*m_StudioSystem.GetClientDataModelBridge())
+ , m_PropertySystem(*m_StudioSystem.GetPropertySystem())
+ , m_MetaData(*m_StudioSystem.GetActionMetaData())
+ , m_ActionSystem(*m_StudioSystem.GetActionSystem())
+ , m_ActionCore(*m_StudioSystem.GetFullSystem()->GetActionCore())
+ , m_AnimationSystem(*m_StudioSystem.GetAnimationSystem())
+ , m_GuideSystem(*m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetGuideSystem())
+ , m_IgnoreDirChange(false)
+ , m_StringTable(m_DataCore.GetStringTable())
+ , m_Foundation(Q3DStudio::Foundation::SStudioFoundation::Create())
+ , m_InputStreamFactory(uic::render::IInputStreamFactory::Create(*m_Foundation.m_Foundation))
+ , m_LuaState(NULL)
+
+ {
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ IDirectoryWatchingSystem *theSystem(m_Doc.GetDirectoryWatchingSystem());
+ if (theSystem)
+ m_ProjectDirWatcher =
+ theSystem->AddDirectory(m_Doc.GetDocumentDirectory().toQString(),
+ std::bind(&CDocEditor::OnProjectDirChanged, this,
+ std::placeholders::_1));
+ }
+ virtual ~CDocEditor()
+ {
+ if (m_LuaState)
+ m_LuaState->Release();
+ m_LuaState = NULL;
+ }
+ ///////////////////////////////////////////////////////////////////
+ // IDocumentReader
+ //////////////////////////////////////////////////////////////////
+
+ bool IsInstance(CUICDMInstanceHandle instance) const override
+ {
+ return m_DataCore.IsInstance(instance);
+ }
+
+ bool IsCurrentlyActive(TInstanceHandle inInstance) const override
+ {
+ SValue startTime, endTime, eyeball;
+ IPropertySystem &thePropertySystem(m_PropertySystem);
+ ISlideSystem &theSlideSystem(m_SlideSystem);
+ if (IsInstance(inInstance)
+ && thePropertySystem.GetInstancePropertyValue(
+ inInstance, m_Bridge.GetSceneAsset().m_StartTime, startTime)
+ && thePropertySystem.GetInstancePropertyValue(
+ inInstance, m_Bridge.GetSceneAsset().m_EndTime, endTime)
+ && thePropertySystem.GetInstancePropertyValue(
+ inInstance, m_Bridge.GetSceneAsset().m_Eyeball, eyeball)) {
+ bool eyeballVal = UICDM::get<bool>(eyeball);
+ long theStart = UICDM::get<qt3ds::QT3DSI32>(startTime);
+ long theEnd = UICDM::get<qt3ds::QT3DSI32>(endTime);
+ CUICDMInstanceHandle theInstance(inInstance);
+ SInstanceSlideInformation theSlideInfo(
+ theSlideSystem.GetInstanceSlideInformation(theInstance));
+ CUICDMSlideHandle theAssociatedSlide = theSlideInfo.m_AssociatedSlide;
+ CUICDMSlideHandle theMaster = theSlideInfo.m_MasterSlide;
+ CUICDMSlideHandle theActiveSlide = theSlideInfo.m_ActiveSlide;
+ if (theAssociatedSlide == theMaster || theAssociatedSlide == theActiveSlide) {
+ long theViewTime = theSlideInfo.m_ComponentMilliseconds;
+ return eyeballVal && theStart <= theViewTime && theEnd > 0 && theEnd >= theViewTime;
+ }
+ }
+ return false;
+ }
+
+ TPropertyHandle FindProperty(CUICDMInstanceHandle instance,
+ const wchar_t *inPropName) const override
+ {
+ return m_DataCore.GetAggregateInstancePropertyByName(instance, inPropName);
+ }
+
+ Option<SValue> GetRawInstancePropertyValue(TInstanceHandle instance,
+ TPropertyHandle inProperty) const override
+ {
+ SValue theValue;
+ if (m_PropertySystem.GetInstancePropertyValue(instance, inProperty, theValue))
+ return theValue.toOldSkool();
+ return Empty();
+ }
+
+ Option<SValue> GetInstancePropertyValue(TInstanceHandle instance,
+ TPropertyHandle inProperty) const override
+ {
+ AdditionalMetaDataType::Value thePropertyMetaData =
+ m_PropertySystem.GetAdditionalMetaDataType(instance, inProperty);
+ if (thePropertyMetaData == AdditionalMetaDataType::Image) {
+ TInstanceHandle theImageInstance = GetImageInstanceForProperty(instance, inProperty);
+ if (theImageInstance)
+ return GetRawInstancePropertyValue(theImageInstance,
+ m_Bridge.GetSourcePathProperty());
+ } else {
+ return GetRawInstancePropertyValue(instance, inProperty);
+ }
+ return Empty();
+ }
+
+ TInstanceHandle GetImageInstanceForProperty(TInstanceHandle instance,
+ TPropertyHandle inProperty) const override
+ {
+ UICDM::CUICDMSlideHandle theAssociatedSlide(m_SlideSystem.GetAssociatedSlide(instance));
+ SValue theGuid;
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theAssociatedSlide, instance, inProperty,
+ theGuid)
+ || m_DataCore.GetInstancePropertyValue(instance, inProperty, theGuid)) {
+ return m_Bridge.GetInstanceByGUID(get<SLong4>(theGuid));
+ }
+ return TInstanceHandle();
+ }
+
+ Option<SValue> GetSpecificInstancePropertyValue(TSlideHandle inSlide,
+ TInstanceHandle instance,
+ TPropertyHandle inProperty) const override
+ {
+ SValue theValue;
+ SValue theTempValue;
+ if (inSlide.Valid()) {
+ if (m_SlideCore.GetSpecificInstancePropertyValue(inSlide, instance, inProperty,
+ theValue))
+ return theValue;
+ } else if (m_DataCore.GetInstancePropertyValue(instance, inProperty, theTempValue))
+ return theTempValue.toOldSkool();
+ return Empty();
+ }
+
+ Q3DStudio::CString GetObjectTypeName(TInstanceHandle instance) const override
+ {
+ if (IsInstance(instance)) {
+ Option<TCharStr> theTypeName = m_MetaData.GetTypeForInstance(instance);
+ if (theTypeName.hasValue())
+ return CString(theTypeName->wide_str());
+ }
+ return Q3DStudio::CString();
+ }
+
+ // Get every property value associated with this instance, from the data core up. The
+ // associated slide will be NULL for the
+ // data core.
+ void GetAllPropertyValues(TInstanceHandle instance, TPropertyHandle inProperty,
+ TSlideValuePairList &outValues) const override
+ {
+ TSlideHandle theSlide(GetAssociatedSlide(instance));
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(instance, inProperty, theValue))
+ outValues.push_back(make_pair(0, theValue.toOldSkool()));
+
+ if (theSlide.Valid()) {
+ SValue theSlideValue;
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theSlide, instance, inProperty,
+ theSlideValue))
+ outValues.push_back(make_pair(theSlide, theSlideValue));
+
+ TSlideHandleList theChildren;
+ m_SlideCore.GetChildSlides(theSlide, theChildren);
+ for (size_t idx = 0, end = theChildren.size(); idx < end; ++idx) {
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theChildren[idx], instance,
+ inProperty, theSlideValue))
+ outValues.push_back(make_pair(theChildren[idx], theSlideValue));
+ }
+ }
+ }
+
+ TSlideHandle GetAssociatedSlide(TInstanceHandle inInstance) const override
+ {
+ TSlideHandle retval = m_SlideSystem.GetAssociatedSlide(inInstance);
+ return retval;
+ }
+
+ bool IsMasterSlide(TSlideHandle inSlide) const override
+ {
+ return m_SlideSystem.IsMasterSlide(inSlide);
+ }
+
+ TInstanceHandle GetAssociatedComponent(TInstanceHandle inInstance) const override
+ {
+ return GetComponentForSlide(GetAssociatedSlide(inInstance));
+ }
+
+ TSlideHandle GetActiveSlide(TInstanceHandle /*inInstance*/) const override
+ {
+ return m_Doc.GetActiveSlide();
+ }
+
+ TSlideHandle GetComponentActiveSlide(TInstanceHandle inInstance) const override
+ {
+ return m_Bridge.GetComponentActiveSlide(inInstance);
+ }
+
+ TInstanceHandle GetComponentForSlide(TSlideHandle inSlide) const override
+ {
+ return m_Bridge.GetOwningComponentInstance(inSlide);
+ }
+
+ void GetAllAssociatedSlides(TInstanceHandle inInstance, TSlideList &outList) const override
+ {
+ TSlideHandle retval = m_SlideSystem.GetAssociatedSlide(inInstance);
+ if (retval.Valid()) {
+ m_SlideCore.GetChildSlides(retval, outList);
+ outList.insert(outList.begin(), retval);
+ }
+ }
+
+ bool IsComponent(TInstanceHandle inInstance) const override
+ {
+ if (IsInstance(inInstance))
+ return m_DataCore.IsInstanceOrDerivedFrom(
+ inInstance, m_Bridge.GetObjectDefinitions().m_SlideOwner.m_Instance);
+
+ return false;
+ }
+
+ void GetAllPaths(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ TSlideStringList &outPaths) const
+ {
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ if (!m_DataCore.IsInstanceOrDerivedFrom(inInstance, theDefinitions.m_Asset.m_Instance)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(inInstance, inProperty, theValue)) {
+ TDataStrPtr theStr(get<TDataStrPtr>(theValue));
+ if (theStr && theStr->GetLength())
+ outPaths.push_back(make_pair(CUICDMSlideHandle(0), CString(theStr->GetData())));
+ }
+
+ TSlideHandleList theSlides;
+ GetAllAssociatedSlides(inInstance, theSlides);
+
+ SValue theSlideValue;
+ for (size_t idx = 0, end = theSlides.size(); idx < end; ++idx) {
+ CUICDMSlideHandle theSlide(theSlides[idx]);
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theSlide, inInstance, inProperty,
+ theSlideValue)) {
+ TDataStrPtr theStr(get<TDataStrPtr>(theSlideValue));
+ if (theStr && theStr->GetLength())
+ outPaths.push_back(make_pair(theSlide, CString(theStr->GetData())));
+ }
+ }
+ }
+
+ void GetAllSourcePaths(CUICDMInstanceHandle inInstance, TSlideStringList &outPaths) const override
+ {
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ GetAllPaths(inInstance, theDefinitions.m_Asset.m_SourcePath, outPaths);
+ }
+
+ void GetPathToInstanceMap(TCharPtrToSlideInstanceMap &outInstanceMap,
+ UICDM::CUICDMPropertyHandle inProperty,
+ bool inIncludeIdentifiers = true) const
+ {
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ TInstanceHandleList existing;
+ TSlideStringList thePaths;
+ m_DataCore.GetInstancesDerivedFrom(existing, theDefinitions.m_Asset.m_Instance);
+ outInstanceMap.clear();
+ for (size_t idx = 0, end = existing.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theAsset(existing[idx]);
+ thePaths.clear();
+ GetAllPaths(theAsset, inProperty, thePaths);
+
+ for (size_t pathIdx = 0, pathEnd = thePaths.size(); pathIdx < pathEnd; ++pathIdx) {
+ const pair<UICDM::CUICDMSlideHandle, Q3DStudio::CString> &theSlideStr(
+ thePaths[pathIdx]);
+ CFilePath thePath(theSlideStr.second);
+ if (inIncludeIdentifiers == false)
+ thePath = thePath.GetPathWithoutIdentifier();
+ const wchar_t *theString = m_DataCore.GetStringTable().RegisterStr(
+ thePath.GetPathWithoutIdentifier().c_str());
+ pair<TCharPtrToSlideInstanceMap::iterator, bool> theInsertResult(
+ outInstanceMap.insert(make_pair(theString, TSlideInstanceList())));
+ insert_unique(theInsertResult.first->second,
+ make_pair(theSlideStr.first, theAsset));
+ }
+ }
+ }
+
+ void GetSourcePathToInstanceMap(TCharPtrToSlideInstanceMap &outInstanceMap,
+ bool inIncludeIdentifiers = true) const override
+ {
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ GetPathToInstanceMap(outInstanceMap, theDefinitions.m_Asset.m_SourcePath,
+ inIncludeIdentifiers);
+ }
+
+ void GetImportPathToInstanceMap(TCharPtrToSlideInstanceMap &outInstanceMap) const override
+ {
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ GetPathToInstanceMap(outInstanceMap, theDefinitions.m_Asset.m_ImportFile, false);
+ }
+
+ bool CanPropertyBeLinked(TInstanceHandle inInstance, TPropertyHandle inProperty) const override
+ {
+ if (inProperty == m_Bridge.GetAlias().m_ReferencedNode.m_Property)
+ return false;
+ return m_SlideSystem.CanPropertyBeLinked(inInstance, inProperty);
+ }
+
+ // Return true if a property is linked (exists only on the associated slide && the slide is a
+ // master slide).
+ bool IsPropertyLinked(TInstanceHandle inInstance, TPropertyHandle inProperty) const override
+ {
+ if (IsInstance(inInstance)) {
+ AdditionalMetaDataType::Value thePropertyMetaData =
+ m_PropertySystem.GetAdditionalMetaDataType(inInstance, inProperty);
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ if (theAssociatedSlide.Valid() && m_SlideSystem.IsMasterSlide(theAssociatedSlide)) {
+ SValue theValue;
+ if (thePropertyMetaData == AdditionalMetaDataType::Image) {
+ UICDM::CUICDMInstanceHandle theInstance =
+ GetImageInstanceForProperty(inInstance, inProperty);
+ if (theInstance)
+ return IsPropertyLinked(theInstance, m_Bridge.GetSourcePathProperty());
+ return true; // No image means the property is linked.
+ }
+ return m_SlideSystem.IsPropertyLinked(inInstance, inProperty);
+ }
+ }
+ return false;
+ }
+
+ TSlideHandle GetSlideForProperty(TInstanceHandle inInstance,
+ TPropertyHandle inProperty) const override
+ {
+ TSlideHandle associatedSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ if (associatedSlide.Valid()) {
+ TSlideHandle theMaster = m_SlideCore.GetParentSlide(associatedSlide);
+ bool isMaster = true;
+ if (theMaster.Valid() == false || associatedSlide != theMaster)
+ isMaster = false;
+ if (isMaster && m_SlideSystem.IsPropertyLinked(inInstance, inProperty))
+ return theMaster;
+ return GetActiveSlide(inInstance);
+ }
+ return 0;
+ }
+
+ bool IsImported(TInstanceHandle instance) const override
+ {
+ SValue theValue;
+ if (IsInstance(instance)
+ && m_PropertySystem.GetInstancePropertyValue(instance, m_Bridge.GetImportId(),
+ theValue)) {
+ return get<TDataStrPtr>(theValue)->GetLength() > 0;
+ }
+ return false;
+ }
+
+ CString GetImportId(TInstanceHandle inInstance) const override
+ {
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(
+ inInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_ImportId, theValue)) {
+ TDataStrPtr theStr(get<TDataStrPtr>(theValue));
+ if (theStr)
+ return m_StringTable.RegisterStr(theStr->GetData());
+ }
+ return m_StringTable.RegisterStr(L"");
+ }
+
+ CString GetFileId(TInstanceHandle inInstance) const override
+ {
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(
+ inInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_FileId, theValue)) {
+ TDataStrPtr theStr(get<TDataStrPtr>(theValue));
+ if (theStr)
+ return m_StringTable.RegisterStr(theStr->GetData());
+ }
+ return m_StringTable.RegisterStr(L"");
+ }
+
+ std::pair<long, long> GetTimeRange(TInstanceHandle instance) const override
+ {
+ SValue theStart, theEnd;
+ bool result = m_PropertySystem.GetInstancePropertyValue(
+ instance, m_Bridge.GetSceneAsset().m_StartTime, theStart)
+ && m_PropertySystem.GetInstancePropertyValue(
+ instance, m_Bridge.GetSceneAsset().m_EndTime, theEnd);
+ if (result) {
+ return std::make_pair(static_cast<long>(get<qt3ds::QT3DSI32>(theStart)),
+ static_cast<long>(get<qt3ds::QT3DSI32>(theEnd)));
+ }
+ assert(0);
+ return std::make_pair(0L, 0L);
+ }
+
+ std::pair<long, long> GetTimeRangeInSlide(CUICDMSlideHandle inSlide,
+ TInstanceHandle instance) const override
+ {
+ SValue theStart, theEnd;
+ bool result = m_SlideCore.GetSpecificInstancePropertyValue(
+ inSlide, instance, m_Bridge.GetSceneAsset().m_StartTime, theStart)
+ && m_SlideCore.GetSpecificInstancePropertyValue(
+ inSlide, instance, m_Bridge.GetSceneAsset().m_EndTime, theEnd);
+ if (result) {
+ return std::make_pair(static_cast<long>(get<qt3ds::QT3DSI32>(theStart)),
+ static_cast<long>(get<qt3ds::QT3DSI32>(theEnd)));
+ }
+ assert(0);
+ return std::make_pair((long)0, (long)0);
+ }
+
+ UICDM::SLong4 GetGuidForInstance(CUICDMInstanceHandle instance) const override
+ {
+ if (IsInstance(instance)) {
+ Q3DStudio::CId theId(m_Bridge.GetGUID(instance));
+ TGUIDPacked thePackedGUID(theId);
+ return UICDM::SLong4(thePackedGUID.Data1, thePackedGUID.Data2, thePackedGUID.Data3,
+ thePackedGUID.Data4);
+ }
+ return UICDM::SLong4();
+ }
+ TInstanceHandle GetInstanceForGuid(const UICDM::SLong4 &inGuid) const override
+ {
+ return m_Bridge.GetInstanceByGUID(inGuid);
+ }
+ TInstanceHandle GetInstanceForObjectRef(TInstanceHandle inRoot,
+ const UICDM::SObjectRefType &inReference) const override
+ {
+ return m_Bridge.GetInstance(inRoot, inReference);
+ }
+ CUICDMInstanceHandle GetParent(CUICDMInstanceHandle child) const override
+ {
+ return m_AssetGraph.GetParent(child);
+ }
+
+ // Get all the children if this instance in this slide. If the slide is invalid,
+ // the get all the children of this parent in all slides.
+ void GetChildren(TSlideHandle inSlide, TInstanceHandle inParent,
+ TInstanceList &outChildren) const override
+ {
+ for (long theChildIdx = 0, theChildCount = m_AssetGraph.GetChildCount(inParent);
+ theChildIdx < theChildCount; ++theChildIdx) {
+ TInstanceHandle theChild(m_AssetGraph.GetChild(inParent, theChildIdx));
+ if (inSlide.Valid()) {
+ if (m_SlideSystem.GetAssociatedSlide(theChild) == inSlide)
+ outChildren.push_back(theChild);
+ } else
+ outChildren.push_back(theChild);
+ }
+ }
+
+ bool IsInSceneGraph(TInstanceHandle child) const override { return m_AssetGraph.IsExist(child); }
+
+ // If the path has any sub-path children, then yes it is externalizeable.
+ bool IsPathExternalizeable(TInstanceHandle path) const override
+ {
+ for (QT3DSI32 idx = 0, end = m_AssetGraph.GetChildCount(path); idx < end; ++idx) {
+ TInstanceHandle theChild = m_AssetGraph.GetChild(path, idx);
+ if (GetObjectTypeName(theChild) == L"SubPath")
+ return true;
+ }
+ return false;
+ }
+
+ bool IsPathInternalizeable(TInstanceHandle path) const override
+ {
+ Option<TDataStrPtr> theStr =
+ const_cast<CDocEditor *>(this)->GetTypedInstancePropertyValue<TDataStrPtr>(
+ path, m_Bridge.GetSourcePathProperty());
+ if (theStr.hasValue() && (*theStr) && (*theStr)->GetLength())
+ return true;
+ return false;
+ }
+
+ bool AnimationExists(TSlideHandle inSlide, TInstanceHandle instance,
+ const wchar_t *propName, long subIndex) override
+ {
+ CUICDMPropertyHandle propHdl =
+ m_DataCore.GetAggregateInstancePropertyByName(instance, propName);
+ if (propHdl.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (inSlide.Valid() == false) {
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(instance);
+ if (theSlide.Valid() == false) {
+ assert(0);
+ return false;
+ }
+ if (m_SlideSystem.IsPropertyLinked(instance, propHdl))
+ theSlide = m_SlideSystem.GetMasterSlide(theSlide);
+ inSlide = theSlide;
+ }
+ return m_AnimationCore.GetAnimation(inSlide, instance, propHdl, subIndex).Valid();
+ }
+
+ bool IsAnimationArtistEdited(TSlideHandle inSlide, CUICDMInstanceHandle instance,
+ const wchar_t *propName, long subIndex) override
+ {
+ CUICDMPropertyHandle propHdl =
+ m_DataCore.GetAggregateInstancePropertyByName(instance, propName);
+ if (propHdl.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (inSlide.Valid() == false) {
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(instance);
+ if (theSlide.Valid() == false) {
+ assert(0);
+ return false;
+ }
+ if (m_SlideSystem.IsPropertyLinked(instance, propHdl))
+ theSlide = m_SlideSystem.GetMasterSlide(theSlide);
+ inSlide = theSlide;
+ }
+
+ CUICDMAnimationHandle animHandle =
+ m_AnimationCore.GetAnimation(inSlide, instance, propHdl, subIndex);
+ if (animHandle.Valid() == false)
+ return false;
+ return m_AnimationCore.IsArtistEdited(animHandle);
+ }
+
+ pair<std::shared_ptr<UICDM::IDOMWriter>, CFilePath>
+ DoCopySceneGraphObject(const TInstanceHandleList &inInstances)
+ {
+ if (inInstances.empty())
+ return pair<std::shared_ptr<UICDM::IDOMWriter>, CFilePath>();
+
+ std::shared_ptr<IDOMWriter> theWriter(m_Doc.CreateDOMWriter());
+ TInstanceHandleList theInstances = ToGraphOrdering(inInstances);
+ m_Doc.CreateSerializer()->SerializeSceneGraphObjects(*theWriter, theInstances,
+ GetActiveSlide(inInstances[0]));
+ CFilePath theFile = WriteWriterToFile(*theWriter, L"SceneGraph");
+ return make_pair(theWriter, theFile);
+ }
+
+ // Not exposed through public interface yet
+ std::shared_ptr<UICDM::IDOMReader>
+ CopySceneGraphObjectsToMemory(const UICDM::TInstanceHandleList &instanceList)
+ {
+ return DoCopySceneGraphObject(instanceList).first->CreateDOMReader();
+ }
+
+ // Exposed through document reader interface
+ virtual std::shared_ptr<UICDM::IDOMReader>
+ CopySceneGraphObjectToMemory(CUICDMInstanceHandle inInstance) override
+ {
+ TInstanceHandleList instanceList;
+ instanceList.push_back(inInstance);
+ return CopySceneGraphObjectsToMemory(instanceList);
+ }
+
+ struct SFilePtrOutStream : public IOutStream
+ {
+ TFilePtr m_File;
+ SFilePtrOutStream(TFilePtr f)
+ : m_File(f)
+ {
+ }
+
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ return m_File->Write(data.begin(), data.size()) == data.size();
+ }
+ };
+
+ CFilePath WriteWriterToFile(IDOMWriter &inWriter, const CString &inStem)
+ {
+ CFilePath theTempFileDir = CFilePath::CombineBaseAndRelative(
+ CFilePath::GetUserApplicationDirectory(), CFilePath(L"UIComposer\\temp_files"));
+ theTempFileDir.CreateDir(true);
+ CFilePath theFinalPath;
+ {
+ TFilePtr theFile = SFileTools::FindUniqueDestFile(theTempFileDir, inStem, L"uip");
+
+ theFinalPath = theFile->m_Path;
+
+ CUICFile::AddTempFile(theFile->m_Path);
+
+ SFilePtrOutStream theFileStream(theFile);
+
+ CDOMSerializer::Write(*inWriter.GetTopElement(), theFileStream);
+ }
+ return theFinalPath;
+ }
+
+ CFilePath CopySceneGraphObjects(TInstanceHandleList inInstances) override
+ {
+ if (inInstances.empty())
+ return L"";
+ bool shouldCopy = true;
+ for (size_t idx = 0, end = inInstances.size(); idx < end && shouldCopy; ++idx)
+ shouldCopy = IsInstance(inInstances[idx]);
+
+ if (!shouldCopy)
+ return L"";
+
+ return DoCopySceneGraphObject(inInstances).second;
+ }
+
+ CFilePath CopyAction(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide) override
+ {
+ std::shared_ptr<IComposerSerializer> theSerializer(m_Doc.CreateSerializer());
+ std::shared_ptr<UICDM::IDOMWriter> theWriter(
+ IDOMWriter::CreateDOMWriter(L"UIPActionFragment", m_DataCore.GetStringTablePtr())
+ .first);
+ theSerializer->SerializeAction(*theWriter, inSlide, inAction);
+ return WriteWriterToFile(*theWriter, L"Action");
+ }
+
+ std::shared_ptr<UICDM::IDOMReader> CopySlide(CUICDMSlideHandle inSlide) override
+ {
+ if (m_SlideSystem.IsMasterSlide(inSlide)) {
+ QT3DS_ASSERT(false);
+ return std::shared_ptr<UICDM::IDOMReader>();
+ }
+ std::shared_ptr<IComposerSerializer> theSerializer(m_Doc.CreateSerializer());
+ std::shared_ptr<UICDM::IDOMWriter> theWriter(
+ IDOMWriter::CreateDOMWriter(L"UIPSlideFragment", m_DataCore.GetStringTablePtr()).first);
+ theSerializer->SerializeSlide(*theWriter, inSlide);
+#ifdef _DEBUG
+ WriteWriterToFile(*theWriter, L"Slide");
+#endif
+ return theWriter->CreateDOMReader();
+ }
+
+ IDynamicLua *GetLuaContext() override
+ {
+ EnsureLuaState();
+ return m_LuaState;
+ }
+
+ qt3ds::NVFoundationBase &GetFoundation() override { return *m_Foundation.m_Foundation; }
+
+ void ParseSourcePathsOutOfEffectFile(Q3DStudio::CString inFile,
+ std::vector<Q3DStudio::CString> &outFilePaths) override
+ {
+ qt3ds::foundation::CFileSeekableIOStream theStream(inFile,
+ qt3ds::foundation::FileReadFlags());
+ if (theStream.IsOpen()) {
+ std::shared_ptr<IDOMFactory> theFactory =
+ IDOMFactory::CreateDOMFactory(m_DataCore.GetStringTablePtr());
+ SImportXmlErrorHandler theImportHandler(m_Doc.GetImportFailedHandler(), inFile);
+ UICDM::SDOMElement *theElem =
+ CDOMSerializer::Read(*theFactory, theStream, &theImportHandler);
+
+ CFilePath theFilePath(inFile);
+ CFilePath theFileDir(theFilePath.GetDirectory());
+ if (theElem) {
+ std::shared_ptr<IDOMReader> theReader = IDOMReader::CreateDOMReader(
+ *theElem, m_DataCore.GetStringTablePtr(), theFactory);
+ if (theReader->MoveToFirstChild("MetaData")) {
+ for (bool success = theReader->MoveToFirstChild("Property"); success;
+ success = theReader->MoveToNextSibling("Property")) {
+ const char8_t *type = "", *defValue = "";
+ theReader->Att("type", type);
+ theReader->Att("default", defValue);
+ if (UICDM::AreEqual(type, "Texture")) {
+ CFilePath theDefPath =
+ CFilePath::CombineBaseAndRelative(theFileDir, defValue);
+ if (theDefPath.IsFile())
+ outFilePaths.push_back(defValue);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Q3DStudio::CString GetCustomMaterialName(const Q3DStudio::CString &inFullPathToFile) const override
+ {
+ Q3DStudio::CString retval;
+ qt3ds::foundation::CFileSeekableIOStream theStream(inFullPathToFile,
+ qt3ds::foundation::FileReadFlags());
+ if (theStream.IsOpen()) {
+ std::shared_ptr<IDOMFactory> theFactory =
+ IDOMFactory::CreateDOMFactory(m_DataCore.GetStringTablePtr());
+ SImportXmlErrorHandler theImportHandler(m_Doc.GetImportFailedHandler(),
+ inFullPathToFile);
+ UICDM::SDOMElement *theElem =
+ CDOMSerializer::Read(*theFactory, theStream, &theImportHandler);
+ if (theElem) {
+ // OK, then this just may be a valid material file. Get the file stem of the path.
+ Q3DStudio::CFilePath thePath(inFullPathToFile);
+ retval = thePath.GetFileStem();
+ std::shared_ptr<IDOMReader> theReader = IDOMReader::CreateDOMReader(
+ *theElem, m_DataCore.GetStringTablePtr(), theFactory);
+ const char8_t *attValue;
+ if (theReader->UnregisteredAtt("formalName", attValue) && !isTrivial(attValue)) {
+ retval.assign(attValue);
+ }
+ }
+ }
+ return retval;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // IDocumentEditor
+ //////////////////////////////////////////////////////////////////
+
+ void BeginAggregateOperation() override
+ {
+ m_StudioSystem.GetFullSystem()->BeginAggregateOperation();
+ }
+ void EndAggregateOperation() override
+ {
+ m_StudioSystem.GetFullSystem()->EndAggregateOperation();
+ }
+ void Rollback() override { m_Doc.RollbackTransaction(); }
+ // Release when finished editing
+ void Release() override { m_Doc.CloseTransaction(); }
+
+ bool FilterForNotInSlideAndNotInstance(Q3DStudio::TIdentifier inInstance,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inTargetInstance)
+ {
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ CUICDMSlideHandle theParentSlide = m_SlideSystem.GetMasterSlide(theAssociatedSlide);
+ if (inTargetInstance == CUICDMInstanceHandle(inInstance)
+ || (theAssociatedSlide != inSlide && theAssociatedSlide != theParentSlide))
+ return true; // The object is *not* in present in this slide or is the target instance
+ // the object *is* present in this slide.
+ return false;
+ }
+
+ void SetTimeRangeToParent(CUICDMInstanceHandle inInstance)
+ {
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ if (theAssociatedSlide.Valid() == false)
+ return;
+
+ TSlideHandleList theChildSlides;
+ m_SlideCore.GetChildSlides(theAssociatedSlide, theChildSlides);
+ theChildSlides.insert(theChildSlides.begin(), theAssociatedSlide);
+ CUICDMInstanceHandle theParent = m_AssetGraph.GetParent(inInstance);
+
+ CUICDMPropertyHandle theStartProp = m_Bridge.GetObjectDefinitions().m_Asset.m_StartTime;
+ CUICDMPropertyHandle theEndProp = m_Bridge.GetObjectDefinitions().m_Asset.m_EndTime;
+ bool isParentSlideOwner =
+ m_Bridge.GetObjectDefinitions().IsA(theParent, ComposerObjectTypes::SlideOwner);
+
+ for (size_t slideIdx = 0, slideEnd = theChildSlides.size(); slideIdx < slideEnd;
+ ++slideIdx) {
+ CUICDMSlideHandle theChildSlide(theChildSlides[slideIdx]);
+ pair<long, long> destTimeRange(0, 0);
+ if (isParentSlideOwner) {
+ // Get the previous item in the current slide.
+ CGraphIterator theIterator;
+ theIterator +=
+ Q3DStudio::TFilter(std::bind(&CDocEditor::FilterForNotInSlideAndNotInstance,
+ this, std::placeholders::_1, theChildSlide,
+ inInstance));
+ m_AssetGraph.GetChildren(theIterator, theParent);
+ CUICDMInstanceHandle thePreviousItem;
+ if (theIterator.IsDone())
+ continue;
+
+ // Perform max/min of sibing times.
+ for (; theIterator.IsDone() == false; ++theIterator) {
+ pair<long, long> theSiblingTime =
+ GetTimeRangeInSlide(theChildSlide, theIterator.GetCurrent());
+ destTimeRange.first = min(destTimeRange.first, theSiblingTime.first);
+ destTimeRange.second = max(destTimeRange.second, theSiblingTime.second);
+ }
+ } else {
+ destTimeRange = GetTimeRangeInSlide(theChildSlide, theParent);
+ }
+ // ensure the time range is sane.
+ destTimeRange.first = min(destTimeRange.first, destTimeRange.second);
+ SetTimeRangeInSlide(theChildSlide, inInstance, destTimeRange.first,
+ destTimeRange.second);
+ }
+ }
+
+ virtual CUICDMInstanceHandle
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Enum inType, TInstanceHandle inParent,
+ TSlideHandle inSlide, TInstanceHandle inTargetId = TInstanceHandle()) override
+ {
+ CUICDMInstanceHandle retval = IDocumentEditor::CreateSceneGraphInstance(
+ ComposerObjectTypes::Convert(inType), inParent, inSlide, m_DataCore, m_SlideSystem,
+ m_Bridge.GetObjectDefinitions(), m_AssetGraph, m_MetaData, inTargetId);
+ SetTimeRangeToParent(retval);
+ return retval;
+ }
+
+ TInstanceHandle CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Enum inType,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inInsertType,
+ const CPt &inPosition,
+ EPrimitiveType inPrimitiveType,
+ long inStartTime) override
+ {
+ TInstanceHandle retval(CreateSceneGraphInstance(inType, inParent, inSlide));
+
+ Q3DStudio::CString theName;
+ if (inType == ComposerObjectTypes::Model) {
+ const wchar_t *theSourcePath = m_Doc.GetBufferCache().GetPrimitiveName(inPrimitiveType);
+ QT3DS_ASSERT(!IsTrivial(theSourcePath));
+
+ // Trigger material generation.
+ SetInstancePropertyValue(retval, m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath,
+ std::make_shared<CDataStr>(theSourcePath));
+
+ theName = Q3DStudio::CString(theSourcePath + 1);
+ } else {
+ theName = GetName(retval);
+ }
+ SetName(retval, theName, true);
+ SetTimeRangeToParent(retval);
+
+ if (inType == ComposerObjectTypes::Layer) {
+ CreateSceneGraphInstance(ComposerObjectTypes::Camera, retval, inSlide);
+ CreateSceneGraphInstance(ComposerObjectTypes::Light, retval, inSlide);
+ }
+
+ if (inStartTime != -1)
+ SetStartTime(retval, inStartTime);
+
+ if (m_DataCore.IsInstanceOrDerivedFrom(
+ retval, m_Bridge.GetObjectDefinitions().m_SlideOwner.m_Instance))
+ m_Bridge.GetOrCreateGraphRoot(retval);
+
+ // EnsureUniqueName( retval );
+
+ return FinalizeAddOrDrop(retval, inParent, inInsertType, inPosition, false);
+ }
+
+ TCharPtr GetSourcePath(CUICDMInstanceHandle inInstance)
+ {
+ Option<SValue> theValue = GetInstancePropertyValue(
+ inInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath);
+ if (theValue.hasValue()) {
+ TDataStrPtr theStr(get<TDataStrPtr>(*theValue));
+ if (theStr)
+ return theStr->GetData();
+ }
+ return L"";
+ }
+
+ void DoDeleteInstance(CUICDMInstanceHandle instance)
+ {
+ // For delete, the metadata needs to participate in the undo/redo system.
+ m_MetaData.SetConsumer(m_StudioSystem.GetFullSystem()->GetConsumer());
+ TInstanceHandleList theDeleteDependentInstances;
+ if (instance == m_Doc.GetSceneInstance()) {
+ // Something is really really wrong here. Scene should never be deleted.
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (m_Bridge.IsMaterialInstance(instance)) {
+ // Go through all slides this material is involved in and
+ // its root properties and eliminate any image references
+ // found
+ std::vector<Q3DStudio::CId> imageIdList;
+ m_Doc.IterateImageInstances(instance, &imageIdList);
+ for (size_t idx = 0, end = imageIdList.size(); idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theInstance =
+ m_Bridge.GetInstanceByGUID(imageIdList[idx]);
+ if (IsInstance(theInstance))
+ m_DataCore.DeleteInstance(theInstance);
+ }
+ }
+ if (m_Bridge.IsMaterialBaseInstance(instance)) {
+ // Find all material instances that may reference this instance.
+ // Ensure they are marked as dirty at this point but do not change their reference
+ // target
+ // because a material type operation may have happened.
+ TInstanceHandleList derivedInstances;
+ m_DataCore.GetInstancesDerivedFrom(
+ derivedInstances,
+ this->m_Bridge.GetObjectDefinitions().m_ReferencedMaterial.m_Instance);
+ for (size_t idx = 0, end = derivedInstances.size(); idx < end; ++idx) {
+ TInstanceHandle theInstance = derivedInstances[idx];
+ TPropertyHandle theProperty =
+ this->m_Bridge.GetObjectDefinitions()
+ .m_ReferencedMaterial.m_ReferencedMaterial.m_Property;
+ // Find all instances of this reference type.
+ std::vector<std::pair<TSlideHandle, UICDM::SObjectRefType>> slideValues;
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(theInstance, theProperty, theValue)) {
+ slideValues.push_back(
+ std::make_pair(TSlideHandle(), theValue.getData<UICDM::SObjectRefType>()));
+ }
+
+ TSlideHandleList theSlides;
+ GetAllAssociatedSlides(theInstance, theSlides);
+
+ SValue theSlideValue;
+ for (size_t idx = 0, end = theSlides.size(); idx < end; ++idx) {
+ CUICDMSlideHandle theSlide(theSlides[idx]);
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theSlide, theInstance,
+ theProperty, theSlideValue))
+ slideValues.push_back(std::make_pair(
+ TSlideHandle(), theSlideValue.getData<UICDM::SObjectRefType>()));
+ }
+
+ for (size_t valueIdx = 0, valueEnd = slideValues.size(); valueIdx < valueEnd;
+ ++valueIdx) {
+ std::pair<TSlideHandle, UICDM::SObjectRefType> &theEntry(slideValues[valueIdx]);
+ TInstanceHandle theResolvedInstance =
+ GetInstanceForObjectRef(theInstance, theEntry.second);
+ if (theResolvedInstance == instance) {
+ if (theEntry.first.Valid())
+ m_SlideCore.SetInstancePropertyValue(theEntry.first, theInstance,
+ theProperty, theEntry.second);
+ else
+ m_DataCore.SetInstancePropertyValue(theInstance, theProperty,
+ theEntry.second);
+ }
+ }
+ }
+
+ } else if (m_Bridge.IsImageInstance(instance)) {
+ // Unassign the image property from material
+ CUICDMInstanceHandle theParent;
+ CUICDMPropertyHandle theProperty;
+
+ if (!m_Bridge.GetMaterialFromImageInstance(instance, theParent, theProperty))
+ m_Bridge.GetLayerFromImageProbeInstance(instance, theParent, theProperty);
+ if (theParent.Valid())
+ m_PropertySystem.SetInstancePropertyValue(theParent, theProperty, SLong4());
+ } else if (m_Bridge.IsBehaviorInstance(instance) || m_Bridge.IsEffectInstance(instance)) {
+ // Check if this is the last instance that uses the same sourcepath property
+ // If yes, delete the parent as well
+ CUICDMInstanceHandle theObjectDefInstance;
+ if (m_Bridge.IsBehaviorInstance(instance))
+ theObjectDefInstance = m_Bridge.GetObjectDefinitions().m_Behavior.m_Instance;
+ else
+ theObjectDefInstance = m_Bridge.GetObjectDefinitions().m_Effect.m_Instance;
+
+ // First, we need to get the parent instance that has the same sourcepath property
+ CFilePath theSourcePath(GetSourcePath(instance));
+ TInstanceHandleList theParents;
+ CUICDMInstanceHandle theInstanceParent;
+ m_DataCore.GetInstanceParents(instance, theParents);
+ for (size_t idx = 0; idx < theParents.size(); ++idx) {
+ CUICDMInstanceHandle theParent(theParents[idx]);
+ if (m_DataCore.IsInstanceOrDerivedFrom(theParent, theObjectDefInstance)
+ && theParent != theObjectDefInstance
+ && theSourcePath == GetSourcePath(theParent)) {
+ theInstanceParent = theParent;
+ break;
+ }
+ }
+
+ // Now that we got the parent, we check how many children the parent has
+ TInstanceHandleList theInstanceChildren;
+ m_DataCore.GetInstancesDerivedFrom(
+ theInstanceChildren,
+ theInstanceParent); // this will return theInstanceParent as well
+ if (theInstanceChildren.size() == 2) {
+ // if there are only 2 children: theInstanceParent and instance
+ // delete theInstanceParent as well
+ QT3DS_ASSERT((theInstanceChildren[0] == theInstanceParent
+ && theInstanceChildren[1] == instance)
+ || (theInstanceChildren[1] == theInstanceParent
+ && theInstanceChildren[0] == instance));
+ theDeleteDependentInstances.push_back(theInstanceParent);
+ }
+ }
+
+ // Note that the instance and its parents are still valid.
+ // we delete from the bottom of the asset graph upwards.
+ m_DataCore.DeleteInstance(instance);
+ if (m_AssetGraph.IsExist(instance))
+ m_AssetGraph.RemoveNode(instance);
+
+ for (size_t idx = 0; idx < theDeleteDependentInstances.size(); ++idx) {
+ QT3DS_ASSERT(!m_AssetGraph.IsExist(theDeleteDependentInstances[idx]));
+ m_DataCore.DeleteInstance(theDeleteDependentInstances[idx]);
+ }
+ }
+
+ void RecursiveDeleteInstanceInSceneGraph(CUICDMInstanceHandle instance)
+ {
+ while (m_AssetGraph.GetChildCount(instance))
+ RecursiveDeleteInstanceInSceneGraph(m_AssetGraph.GetChild(instance, 0));
+ DoDeleteInstance(instance);
+ }
+
+ void DeleteInstances(UICDM::TInstanceHandleList instances) override
+ {
+ for (size_t idx = 0, end = instances.size(); idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theInstance(instances[idx]);
+ if (theInstance == m_Doc.GetSceneInstance()) {
+ // Something is really really wrong here. Scene should never be deleted.
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (m_AssetGraph.IsExist(theInstance))
+ RecursiveDeleteInstanceInSceneGraph(theInstance);
+ else
+ DoDeleteInstance(theInstance);
+ }
+ }
+
+ void SetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle instance,
+ TPropertyHandle propName, const SValue &value) override
+ {
+ if (inSlide.Valid() == false)
+ m_DataCore.SetInstancePropertyValue(instance, propName, value);
+ else
+ m_SlideCore.ForceSetInstancePropertyValue(inSlide, instance, propName, value);
+
+ IInstancePropertyCoreSignalSender *theSender =
+ dynamic_cast<CStudioPropertySystem &>(m_PropertySystem).GetPropertyCoreSignalSender();
+ theSender->SignalInstancePropertyValue(instance, propName, value);
+ }
+
+ void CheckMeshSubsets(TInstanceHandle instance, TPropertyHandle propName,
+ Option<pair<CUICDMSlideHandle, SValue>> inValue = Empty())
+ {
+ // Simply ensure we have enough materials for all the subsets.
+ TSlideValuePairList theValues;
+ GetAllPropertyValues(instance, propName, theValues);
+ if (inValue.hasValue()) {
+ size_t idx = 0;
+ for (size_t end = theValues.size(); idx < end; ++idx) {
+ if (theValues[idx].first == inValue->first) {
+ theValues[idx].second = inValue->second;
+ break;
+ }
+ }
+ if (idx == theValues.size())
+ theValues.push_back(*inValue);
+ }
+
+ QT3DSU32 numSubsets = 0;
+ for (size_t propIdx = 0, propEnd = theValues.size(); propIdx < propEnd; ++propIdx) {
+ TDataStrPtr newValue(get<TDataStrPtr>(theValues[propIdx].second));
+ SRenderMesh *theBuffer = m_Doc.GetBufferCache().GetOrCreateModelBuffer(
+ Q3DStudio::CFilePath(newValue->GetData()));
+ if (theBuffer)
+ numSubsets = NVMax(numSubsets, (QT3DSU32)theBuffer->m_Subsets.size());
+ }
+
+ TInstanceHandleList theMaterials;
+ // Child count is required in the loop on purpose.
+ for (long child = 0; child < m_AssetGraph.GetChildCount(instance); ++child) {
+ CUICDMInstanceHandle theMaterial(m_AssetGraph.GetChild(instance, child));
+ if (m_Bridge.IsMaterialBaseInstance(theMaterial)) {
+ if (theMaterials.size() < numSubsets)
+ theMaterials.push_back(theMaterial);
+ else {
+ // One less material
+ DeleteInstance(theMaterial);
+ --child;
+ }
+ }
+ }
+
+ QT3DSU32 numMaterials = (QT3DSU32)theMaterials.size();
+ // Note that I create the materials in the associated slide of the instance,
+ // not the active slide at this time. This is because materials
+ // need to be with the asset at all times and aren't attached via slides
+ // but are assumed to be there.
+ for (; numMaterials < numSubsets; ++numMaterials)
+ theMaterials.push_back(CreateSceneGraphInstance(ComposerObjectTypes::Material, instance,
+ GetAssociatedSlide(instance)));
+
+ // Now go through and if possible ensure that on each slide the name of the material matches
+ // the subset name.
+ for (size_t propIdx = 0, propEnd = theValues.size(); propIdx < propEnd; ++propIdx) {
+ TDataStrPtr newValue(get<TDataStrPtr>(theValues[propIdx].second));
+ SRenderMesh *theBuffer = m_Doc.GetBufferCache().GetOrCreateModelBuffer(
+ Q3DStudio::CFilePath(newValue->GetData()));
+ if (theBuffer == NULL)
+ continue;
+ for (long subsetIdx = 0, subsetEnd = theBuffer->m_Subsets.size(); subsetIdx < subsetEnd;
+ ++subsetIdx) {
+#ifdef KDAB_TEMPORARILY_REMOVED
+ StaticAssert<sizeof(wchar_t) == sizeof(char16_t)>::valid_expression();
+#endif
+ const wstring &theSubsetName =
+ Q3DStudio::CString(theBuffer->m_Subsets[subsetIdx].m_Name.c_str()).c_str();
+ if (theSubsetName.size()) {
+ CUICDMInstanceHandle theMaterial(theMaterials[subsetIdx]);
+ SValue theValue;
+ CUICDMSlideHandle theSlide(theValues[propIdx].first);
+ CUICDMPropertyHandle theNameProp(
+ m_Bridge.GetObjectDefinitions().m_Named.m_NameProp);
+ SValue theDMValue;
+ if (theSlide.Valid()) {
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theSlide, theMaterial,
+ theNameProp, theValue)
+ == true
+ && AreEqual(get<TDataStrPtr>(theValue)->GetData(),
+ theSubsetName.c_str())
+ == false)
+ m_SlideCore.ForceSetInstancePropertyValue(
+ theSlide, theMaterial, theNameProp,
+ std::make_shared<CDataStr>(theSubsetName.c_str()));
+ } else if (m_DataCore.GetInstancePropertyValue(theMaterial, theNameProp,
+ theDMValue)
+ == false
+ || AreEqual(get<TDataStrPtr>(theDMValue)->GetData(),
+ theSubsetName.c_str())
+ == false) {
+ m_DataCore.SetInstancePropertyValue(
+ theMaterial, theNameProp,
+ std::make_shared<CDataStr>(theSubsetName.c_str()));
+ }
+ }
+ }
+ }
+ }
+
+ struct PathMaterialSlots
+ {
+ enum Enum {
+ Stroke = 1,
+ Fill = 1 << 1,
+ FillAndStroke = Stroke | Fill,
+ };
+ };
+
+ static PathMaterialSlots::Enum GetPathMaterialSlots(const wchar_t *inPathType,
+ const wchar_t *inPaintStyle)
+ {
+ if (AreEqual(inPathType, L"Geometry"))
+ return PathMaterialSlots::Stroke;
+ if (AreEqual(inPaintStyle, L"Filled and Stroked"))
+ return PathMaterialSlots::FillAndStroke;
+ if (AreEqual(inPaintStyle, L"Filled"))
+ return PathMaterialSlots::Fill;
+ return PathMaterialSlots::Stroke;
+ }
+
+ eastl::pair<TInstanceHandle, Q3DStudio::DocumentEditorInsertType::Enum>
+ GetInsertTypeForFirstChild(TInstanceHandle instance)
+ {
+ if (m_AssetGraph.GetChildCount(instance))
+ return eastl::make_pair(TInstanceHandle(m_AssetGraph.GetChild(instance, 0)),
+ Q3DStudio::DocumentEditorInsertType::PreviousSibling);
+ return eastl::make_pair(instance, Q3DStudio::DocumentEditorInsertType::LastChild);
+ }
+
+ void CreatePathMaterial(TInstanceHandle instance, bool isStroke, bool hasStroke)
+ {
+ const wchar_t *materialName = isStroke ? L"Stroke" : L"Fill";
+ TInstanceHandle firstChild;
+ if (m_AssetGraph.GetChildCount(instance))
+ firstChild = m_AssetGraph.GetChild(instance, 0);
+ TInstanceHandle theMaterial = CreateSceneGraphInstance(
+ ComposerObjectTypes::Material, instance, GetAssociatedSlide(instance));
+ if (firstChild.Valid()) {
+ if (isStroke)
+ m_AssetGraph.MoveBefore(theMaterial, firstChild);
+ else {
+ if (!hasStroke)
+ m_AssetGraph.MoveBefore(theMaterial, firstChild);
+ else
+ m_AssetGraph.MoveAfter(theMaterial, firstChild);
+ }
+ }
+ SetName(theMaterial, materialName);
+ }
+
+ // Normal way in to the system.
+ void SetInstancePropertyValue(TInstanceHandle instance, TPropertyHandle propName,
+ const SValue &value, bool inAutoDelete = true) override
+ {
+ IPropertySystem &thePropertySystem(m_PropertySystem);
+ SValue currentValue;
+ AdditionalMetaDataType::Value theProperytMetaData =
+ thePropertySystem.GetAdditionalMetaDataType(instance, propName);
+ TSlideHandle theNewSlide(GetSlideForProperty(instance, propName));
+ if (theProperytMetaData == AdditionalMetaDataType::Image) {
+ TDataStrPtr theImageSourcePath = get<TDataStrPtr>(value);
+ bool hasValue = theImageSourcePath && theImageSourcePath->GetLength() > 0;
+ UICDM::CUICDMInstanceHandle theImageInstance =
+ GetImageInstanceForProperty(instance, propName);
+ if (hasValue) {
+ if (theImageInstance.Valid() == false)
+ theImageInstance = CreateImageInstanceForMaterialOrLayer(instance, propName);
+
+ if (theImageInstance)
+ SetInstancePropertyValue(theImageInstance, m_Bridge.GetSourcePathProperty(),
+ value, inAutoDelete);
+ } else {
+ if (theImageInstance.Valid()) {
+ TSlideHandle theInstanceSlide = GetAssociatedSlide(instance);
+ if (m_SlideSystem.IsMasterSlide(theInstanceSlide)) {
+ if (IsPropertyLinked(instance, propName) && inAutoDelete)
+ DeleteImageInstanceFromMaterialOrLayer(instance, propName);
+ else
+ SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetSourcePathProperty(), value,
+ inAutoDelete);
+ } else {
+ DeleteImageInstanceFromMaterialOrLayer(instance, propName);
+ }
+ }
+ }
+ } else if (theProperytMetaData == AdditionalMetaDataType::Mesh) {
+ CheckMeshSubsets(instance, propName, make_pair(theNewSlide, value));
+ thePropertySystem.SetInstancePropertyValue(instance, propName, value);
+ } else if (theProperytMetaData == AdditionalMetaDataType::PathBuffer) {
+ if (inAutoDelete) {
+ TDataStrPtr newValue(get<TDataStrPtr>(value));
+ if (newValue->GetLength()) {
+ eastl::vector<TInstanceHandle> subPathChildren;
+ for (QT3DSI32 idx = 0, end = m_AssetGraph.GetChildCount(instance); idx < end;
+ ++idx) {
+ TInstanceHandle child = m_AssetGraph.GetChild(instance, idx);
+ if (GetObjectTypeName(child) == L"SubPath")
+ subPathChildren.push_back(child);
+ }
+ for (QT3DSU32 idx = 0, end = subPathChildren.size(); idx < end; ++idx) {
+ DeleteInstance(subPathChildren[idx]);
+ }
+ }
+ }
+ thePropertySystem.SetInstancePropertyValue(instance, propName, value);
+ } else if (theProperytMetaData == AdditionalMetaDataType::Import && inAutoDelete) {
+ TInstanceList childList;
+ GetChildren(theNewSlide, instance, childList);
+ for (size_t idx = 0, end = childList.size(); idx < end; ++idx) {
+ if (IsImported(childList[idx]))
+ DeleteInstance(childList[idx]);
+ }
+ // Run import operation with no handler for errors is the best I can do right now.
+
+ TDataStrPtr newValue(get<TDataStrPtr>(value));
+
+ CFilePath docPath =
+ CFilePath(m_Doc.GetDocumentPath().GetAbsolutePath());
+ CFilePath docDir(docPath.GetDirectory());
+ STranslationLog log;
+ CFilePath theFullPathToDocument(
+ m_Doc.GetResolvedPathToDoc(CFilePath(newValue->GetData())));
+ if (newValue && *newValue->GetData() && theFullPathToDocument.Exists()) {
+ std::pair<long, long> times = GetTimeRange(instance);
+ DoImport(theFullPathToDocument, theFullPathToDocument,
+ m_AssetGraph.GetParent(instance), instance, theNewSlide, docDir, log,
+ std::bind(CPerformImport::ImportToComposerFromImportFile,
+ std::placeholders::_1, std::placeholders::_2),
+ DocumentEditorInsertType::Unknown, CPt(), times.first);
+ }
+ thePropertySystem.SetInstancePropertyValue(instance, propName, value);
+ } else if (propName == m_Bridge.GetObjectDefinitions().m_Path.m_PathType
+ || propName == m_Bridge.GetObjectDefinitions().m_Path.m_PaintStyle) {
+ TDataStrPtr oldPathType = GetTypedInstancePropertyValue<TDataStrPtr>(
+ instance, m_Bridge.GetObjectDefinitions().m_Path.m_PathType);
+ TDataStrPtr oldPaintStyle = GetTypedInstancePropertyValue<TDataStrPtr>(
+ instance, m_Bridge.GetObjectDefinitions().m_Path.m_PaintStyle);
+ TDataStrPtr newPathType;
+ TDataStrPtr newPaintStyle;
+ if (propName == m_Bridge.GetObjectDefinitions().m_Path.m_PathType) {
+ newPaintStyle = oldPaintStyle;
+ newPathType = get<TDataStrPtr>(value);
+ } else {
+ newPathType = oldPathType;
+ newPaintStyle = get<TDataStrPtr>(value);
+ }
+ PathMaterialSlots::Enum oldMaterialSlot =
+ GetPathMaterialSlots(oldPathType->GetData(), oldPaintStyle->GetData());
+ PathMaterialSlots::Enum newMaterialSlot =
+ GetPathMaterialSlots(newPathType->GetData(), newPaintStyle->GetData());
+ if (oldMaterialSlot != newMaterialSlot) {
+ bool hasStroke = (((int)oldMaterialSlot) & PathMaterialSlots::Stroke) > 0;
+ bool hasFill = (((int)oldMaterialSlot) & PathMaterialSlots::Fill) > 0;
+ bool needsStroke = (((int)newMaterialSlot) & PathMaterialSlots::Stroke) > 0;
+ bool needsFill = (((int)newMaterialSlot) & PathMaterialSlots::Fill) > 0;
+ // first, remove any materials that should not be there.
+ UICDM::CUICDMInstanceHandle firstMaterial;
+ UICDM::CUICDMInstanceHandle secondMaterial;
+ for (int idx = 0, end = m_AssetGraph.GetChildCount(instance); idx < end; ++idx) {
+ TInstanceHandle childAsset = m_AssetGraph.GetChild(instance, idx);
+ if (m_Bridge.IsMaterialInstance(childAsset)) {
+ if (firstMaterial.Valid())
+ secondMaterial = childAsset;
+ else
+ firstMaterial = childAsset;
+ }
+ }
+ if (hasStroke && !needsStroke) {
+ if (firstMaterial.Valid())
+ DeleteInstance(firstMaterial);
+ }
+ if (hasFill && !needsFill) {
+ if (hasStroke) {
+ if (secondMaterial.Valid())
+ DeleteInstance(secondMaterial);
+ } else if (firstMaterial.Valid())
+ DeleteInstance(firstMaterial);
+ }
+
+ if (needsStroke && !hasStroke) {
+ CreatePathMaterial(instance, true, false);
+ }
+ if (needsFill && !hasFill) {
+ CreatePathMaterial(instance, false, needsStroke);
+ }
+ }
+ // Now set the property for reals
+ thePropertySystem.SetInstancePropertyValue(instance, propName, value);
+ } else {
+ if (propName != m_Bridge.GetAlias().m_ReferencedNode.m_Property)
+ thePropertySystem.SetInstancePropertyValue(instance, propName, value);
+ else {
+ // Alias properties are set in the scene graph, not in the slides. This
+ // makes the runtime expansion easier and stops problems such as someone unlinking
+ // the alias
+ // node reference and setting it to different values on different slides.
+ m_DataCore.SetInstancePropertyValue(instance, propName, value);
+ }
+ }
+ }
+
+ TInstanceHandle CreateImageInstanceForMaterialOrLayer(TInstanceHandle instance,
+ TPropertyHandle propName)
+ {
+ // Check to make sure there isn't one already assigned here.
+ {
+ UICDM::CUICDMInstanceHandle theImageInstance =
+ GetImageInstanceForProperty(instance, propName);
+ if (theImageInstance.Valid())
+ return theImageInstance;
+ }
+
+ CUICDMSlideHandle theSlide(GetAssociatedSlide(instance));
+ TInstanceHandle theImageInstance =
+ CreateSceneGraphInstance(ComposerObjectTypes::Image, instance, theSlide);
+ const Q3DStudio::TGUIDPacked thePackedGuid(m_Bridge.GetGUID(theImageInstance));
+ UICDM::SLong4 theImageGuid(thePackedGuid.Data1, thePackedGuid.Data2, thePackedGuid.Data3,
+ thePackedGuid.Data4);
+ m_SlideCore.ForceSetInstancePropertyValue(theSlide, instance, propName, theImageGuid);
+ if (propName == m_Bridge.GetObjectDefinitions().m_Material.m_SpecularReflection)
+ SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TextureMapping,
+ std::make_shared<CDataStr>(L"Environmental Mapping"), false);
+ else if (propName == m_Bridge.GetObjectDefinitions().m_Layer.m_LightProbe
+ || propName == m_Bridge.GetObjectDefinitions().m_Layer.m_LightProbe2)
+ SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TextureMapping,
+ std::make_shared<CDataStr>(L"Light Probe"), false);
+ else if (propName == m_Bridge.GetObjectDefinitions().m_MaterialBase.m_IblProbe)
+ SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TextureMapping,
+ std::make_shared<CDataStr>(L"IBL Override"), false);
+ return theImageInstance;
+ }
+
+ void DeleteImageInstanceFromMaterialOrLayer(TInstanceHandle instance, TPropertyHandle propName)
+ {
+ CUICDMSlideHandle theAssociatedSlide(GetAssociatedSlide(instance));
+ UICDM::CUICDMInstanceHandle theImageInstance =
+ GetImageInstanceForProperty(instance, propName);
+ if (theImageInstance.Valid()) {
+ DeleteInstance(theImageInstance);
+ m_SlideCore.SetInstancePropertyValue(theAssociatedSlide, instance, propName, SLong4());
+ }
+ }
+
+ TInstanceHandle SetInstancePropertyValueAsImage(TInstanceHandle instance,
+ TPropertyHandle propName,
+ const Q3DStudio::CString &inSourcePath) override
+ {
+ CFilePath thePath = m_Doc.GetResolvedPathToDoc(inSourcePath);
+ assert(thePath.IsFile());
+ if (!thePath.IsFile())
+ return 0;
+ CUICDMSlideHandle theSlide(GetAssociatedSlide(instance));
+
+ TInstanceHandle theImageInstance =
+ CreateImageInstanceForMaterialOrLayer(instance, propName);
+ TDataStrPtr thePtrPath(new CDataStr(inSourcePath, inSourcePath.size()));
+ SetInstancePropertyValue(instance, propName, thePtrPath);
+
+ return theImageInstance;
+ }
+
+ virtual TInstanceHandle
+ SetInstancePropertyValueAsRenderable(TInstanceHandle instance, TPropertyHandle propName,
+ const Q3DStudio::CString &inSourcePath) override
+ {
+ CFilePath thePath = m_Doc.GetResolvedPathToDoc(inSourcePath);
+ // Delete any existing renderable object children.
+ vector<TInstanceHandle> childrenToDelete;
+ for (long idx = 0, end = m_AssetGraph.GetChildCount(instance); idx < end; ++idx) {
+ TInstanceHandle existingChild = m_AssetGraph.GetChild(instance, idx);
+ if (m_Bridge.IsRenderPluginInstance(existingChild))
+ childrenToDelete.push_back(existingChild);
+ }
+ for (size_t childIdx = 0, childEnd = childrenToDelete.size(); childIdx < childEnd;
+ ++childIdx)
+ DeleteInstance(childrenToDelete[childIdx]);
+
+ SetInstancePropertyValue(instance, propName,
+ std::make_shared<UICDM::CDataStr>(inSourcePath.c_str()), true);
+ // If this is a render plugin
+ if (thePath.Exists() && thePath.GetExtension().CompareNoCase("plugin")) {
+ CUICDMSlideHandle theSlide(GetAssociatedSlide(instance));
+ return LoadRenderPlugin(thePath, instance, theSlide,
+ DocumentEditorInsertType::LastChild, -1);
+ }
+ return TInstanceHandle();
+ }
+
+ void SetMaterialType(TInstanceHandle instance,
+ const Q3DStudio::CString &inRelativePathToMaterialFile) override
+ {
+ const Q3DStudio::CString existing = m_Bridge.GetSourcePath(instance);
+ if (existing == inRelativePathToMaterialFile)
+ return;
+
+ TInstanceHandle model = m_AssetGraph.GetParent(instance);
+ TInstanceHandle newMaterial;
+ TSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(model);
+ // Keep material names the same so that if you change the material type
+ // any relative path links will still work.
+ // Next bug is harder (keep id's the same).
+ Q3DStudio::CString theName = GetName(instance);
+ SLong4 theGuid = m_Bridge.GetInstanceGUID(instance);
+ TInstanceHandle nextChild = m_AssetGraph.GetSibling(instance, true);
+ // Now get all the actions on the material and re-add them.
+
+ TActionHandleList theActions;
+ m_ActionCore.GetActions(instance, theActions);
+ std::vector<SActionInfo> theActionData;
+ std::vector<std::vector<SHandlerArgumentInfo>> theActionDataArgs;
+ for (size_t actionIdx = 0, actionEnd = theActions.size(); actionIdx < actionEnd;
+ ++actionIdx) {
+ theActionData.push_back(m_ActionCore.GetActionInfo(theActions[actionIdx]));
+ theActionDataArgs.push_back(std::vector<SHandlerArgumentInfo>());
+ std::vector<SHandlerArgumentInfo> &theInfoList(theActionDataArgs.back());
+ for (size_t argIdx = 0, argEnd = theActionData.back().m_HandlerArgs.size();
+ argIdx < argEnd; ++argIdx)
+ theInfoList.push_back(m_ActionCore.GetHandlerArgumentInfo(
+ theActionData.back().m_HandlerArgs[argIdx]));
+ }
+
+ // save lightmap values since we want to pass on the current lightmaps settings to the new
+ // material
+ Option<SValue> theLightmapIndirectValue = GetInstancePropertyValue(
+ instance, m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapIndirect);
+ Option<SValue> theLightmapRadiosityValue = GetInstancePropertyValue(
+ instance, m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapRadiosity);
+ Option<SValue> theLightmapShadowValue = GetInstancePropertyValue(
+ instance, m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapShadow);
+
+ DeleteInstance(instance);
+ if (inRelativePathToMaterialFile == "Standard Material")
+ newMaterial =
+ CreateSceneGraphInstance(ComposerObjectTypes::Material, model, theSlide, instance);
+ else if (inRelativePathToMaterialFile == "Referenced Material")
+ newMaterial = CreateSceneGraphInstance(ComposerObjectTypes::ReferencedMaterial, model,
+ theSlide, instance);
+ else {
+ CFilePath thePath = m_Doc.GetResolvedPathToDoc(inRelativePathToMaterialFile);
+ newMaterial = LoadCustomMaterial(thePath, model, theSlide,
+ DocumentEditorInsertType::LastChild, 0, instance);
+ }
+
+ if (newMaterial.Valid()) {
+ if (nextChild.Valid())
+ m_AssetGraph.MoveBefore(newMaterial, nextChild);
+ }
+
+ // restore current lightmap settings for new material
+ if (theLightmapIndirectValue.hasValue())
+ SetInstancePropertyValue(newMaterial,
+ m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapIndirect,
+ theLightmapIndirectValue, false);
+ if (theLightmapRadiosityValue.hasValue())
+ SetInstancePropertyValue(
+ newMaterial, m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapRadiosity,
+ theLightmapRadiosityValue, false);
+ if (theLightmapShadowValue.hasValue())
+ SetInstancePropertyValue(newMaterial,
+ m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapShadow,
+ theLightmapShadowValue, false);
+
+ SetName(newMaterial, theName, false);
+ m_Bridge.SetInstanceGUID(newMaterial, theGuid);
+ // Copy all actions from old material instance to new material instance
+ for (size_t actionIdx = 0, actionEnd = theActionData.size(); actionIdx < actionEnd;
+ ++actionIdx) {
+ const SActionInfo &theSourceInfo(theActionData[actionIdx]);
+
+ CUICDMActionHandle theNewAction = AddAction(
+ theSourceInfo.m_Slide, newMaterial, theSourceInfo.m_Event, theSourceInfo.m_Handler);
+ m_ActionCore.SetTriggerObject(theNewAction, theSourceInfo.m_TriggerObject);
+ m_ActionCore.SetTargetObject(theNewAction, theSourceInfo.m_TargetObject);
+ std::vector<SHandlerArgumentInfo> &theInfoList(theActionDataArgs[actionIdx]);
+ for (size_t argIdx = 0, argEnd = theInfoList.size(); argIdx < argEnd; ++argIdx) {
+ const SHandlerArgumentInfo &theArgData(theInfoList[argIdx]);
+ CUICDMHandlerArgHandle theParamHandle = m_ActionCore.AddHandlerArgument(
+ theNewAction, theArgData.m_Name, theArgData.m_ArgType, theArgData.m_ValueType);
+ m_ActionCore.SetHandlerArgumentValue(theParamHandle, theArgData.m_Value);
+ }
+ }
+ m_Doc.SelectUICDMObject(newMaterial);
+ }
+
+ void SetSlideName(TInstanceHandle inSlideInstance, TPropertyHandle propName,
+ const wchar_t *inOldName, const wchar_t *inNewName) override
+ {
+ SValue theOldValue = std::make_shared<CDataStr>(inOldName);
+ SValue theNewValue = std::make_shared<CDataStr>(inNewName);
+
+ // Update the slide name property value
+ IPropertySystem &thePropertySystem(m_PropertySystem);
+ thePropertySystem.SetInstancePropertyValue(inSlideInstance, propName, theNewValue);
+
+ // Find all actions that point to the old slide name, and change it to new name
+ // First, we need to get the owning component instance, for example inSlideInstance is owned
+ // by Scene
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetSlideByInstance(inSlideInstance);
+ if (theSlide.Valid() == false) {
+ assert(0);
+ return;
+ }
+ CUICDMInstanceHandle theComponentInstance = m_Bridge.GetOwningComponentInstance(theSlide);
+ if (theComponentInstance.Valid() == false) {
+ assert(0);
+ return;
+ }
+
+ // Next, get list of all actions
+ TActionHandleList theActions;
+ m_ActionCore.GetActions(theActions);
+ for (TActionHandleList::iterator theIter = theActions.begin(); theIter != theActions.end();
+ ++theIter) {
+ // Check if the action target object is the owning component instance, for example if
+ // the target object is the Scene
+ SActionInfo theActionInfo = m_ActionCore.GetActionInfo(*theIter);
+ CUICDMInstanceHandle theTargetInstance =
+ m_Bridge.GetInstance(theActionInfo.m_Owner, theActionInfo.m_TargetObject);
+ if (theTargetInstance == theComponentInstance) {
+ CUICDMHandlerHandle theHandler = m_Bridge.ResolveHandler(theActionInfo);
+ if (theHandler.Valid()) {
+ for (THandlerArgHandleList::const_iterator theArgHandle =
+ theActionInfo.m_HandlerArgs.begin();
+ theArgHandle != theActionInfo.m_HandlerArgs.end(); ++theArgHandle) {
+ // and check if handler is Slide type (for example "Go to Slide") that
+ // points to the old slide
+ const SHandlerArgumentInfo &theArgumentInfo =
+ m_ActionCore.GetHandlerArgumentInfo(*theArgHandle);
+ Option<SMetaDataHandlerArgumentInfo> theArgMetaData(
+ m_MetaData.FindHandlerArgumentByName(theHandler,
+ theArgumentInfo.m_Name));
+ if (theArgMetaData.hasValue()
+ && theArgMetaData->m_ArgType == HandlerArgumentType::Slide) {
+ SValue theHandlerValue;
+ m_ActionCore.GetHandlerArgumentValue(*theArgHandle, theHandlerValue);
+ if (Equals(theHandlerValue, theOldValue))
+ // Update action handler argument to point to new slide name
+ m_ActionCore.SetHandlerArgumentValue(*theArgHandle, theNewValue);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void CopyProperties(TSlideHandle inSourceSlide, TInstanceHandle inSourceInstance,
+ TSlideHandle inDestSlide, TInstanceHandle inDestInstance)
+ {
+ m_SlideCore.CopyProperties(inSourceSlide, inSourceInstance, inDestSlide, inDestInstance);
+ m_AnimationCore.CopyAnimations(inSourceSlide, inSourceInstance, inDestSlide,
+ inDestInstance);
+ }
+
+ void UnlinkProperty(TInstanceHandle instance, TPropertyHandle propName) override
+ {
+ IPropertySystem &thePropertySystem(m_PropertySystem);
+ AdditionalMetaDataType::Value thePropertyMetaData =
+ thePropertySystem.GetAdditionalMetaDataType(instance, propName);
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(instance);
+ SValue theValue;
+ if (thePropertyMetaData == AdditionalMetaDataType::Image) {
+ UICDM::CUICDMInstanceHandle theInstance;
+ if (m_SlideCore.GetSpecificInstancePropertyValue(theAssociatedSlide, instance, propName,
+ theValue)) {
+ SLong4 theGuid(get<SLong4>(theValue));
+ theInstance = m_Bridge.GetInstanceByGUID(theGuid);
+ }
+ if (theInstance.Valid() == false)
+ theInstance = CreateImageInstanceForMaterialOrLayer(instance, propName);
+
+ if (theInstance)
+ UnlinkProperty(theInstance, m_Bridge.GetSourcePathProperty());
+ } else {
+ // Note that we get the value *before* unlinking.
+ m_SlideSystem.UnlinkProperty(instance, propName);
+ // WE ignore mesh and import properties because for mesh properties, regardless of link
+ // or unlink status, the materials need to stay in the associated slide of the model.
+ // for imported hierarchies, the operation of recursively going down the tree and
+ // manually
+ // setting up a new import hierarchy is too tedious; the artist can just re-import
+ // the data.
+ }
+ }
+ void LinkProperty(TInstanceHandle instance, TPropertyHandle propName) override
+ {
+ IPropertySystem &thePropertySystem(m_PropertySystem);
+ AdditionalMetaDataType::Value thePropertyMetaData =
+ thePropertySystem.GetAdditionalMetaDataType(instance, propName);
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(instance);
+ SValue theValue;
+ if (thePropertyMetaData == AdditionalMetaDataType::Image
+ && m_SlideCore.GetSpecificInstancePropertyValue(theAssociatedSlide, instance, propName,
+ theValue)) {
+ SLong4 theGuid(get<SLong4>(theValue));
+ UICDM::CUICDMInstanceHandle theInstance = m_Bridge.GetInstanceByGUID(theGuid);
+ if (theInstance) {
+ LinkProperty(theInstance, m_Bridge.GetSourcePathProperty());
+ // If the instance has no source path property, then we get rid of it automatically.
+ m_SlideCore.GetSpecificInstancePropertyValue(
+ theAssociatedSlide, theInstance, m_Bridge.GetSourcePathProperty(), theValue);
+ UICDM::TDataStrPtr theSourcePath(get<TDataStrPtr>(theValue));
+ if (!theSourcePath || theSourcePath->GetLength() == 0) {
+ DeleteImageInstanceFromMaterialOrLayer(instance, propName);
+ }
+ }
+ } else {
+ if (thePropertyMetaData == AdditionalMetaDataType::Import) {
+ TSlideHandleList theChildren;
+ m_SlideCore.GetChildSlides(theAssociatedSlide, theChildren);
+ for (size_t idx = 0, end = theChildren.size(); idx < end; ++idx) {
+ CUICDMSlideHandle theChildSlide(theChildren[idx]);
+ for (long childIdx = 0; childIdx < m_AssetGraph.GetChildCount(instance);
+ ++childIdx) {
+ TInstanceHandle theChild(m_AssetGraph.GetChild(instance, childIdx));
+ if (GetAssociatedSlide(theChild) == theChildSlide && IsImported(theChild)) {
+ DeleteInstance(theChild);
+ --childIdx;
+ }
+ }
+ }
+ }
+ m_SlideSystem.LinkProperty(instance, propName);
+ }
+ }
+
+ void SetTimeRange(TInstanceHandle inInstance, long inStart, long inEnd) override
+ {
+ SetStartTime(inInstance, inStart);
+ SetEndTime(inInstance, inEnd);
+ }
+
+ void SetTimeRangeInSlide(TSlideHandle inSlide, TInstanceHandle inInstance, long inStart,
+ long inEnd) override
+ {
+ m_SlideCore.ForceSetInstancePropertyValue(inSlide, inInstance,
+ m_Bridge.GetSceneAsset().m_StartTime,
+ static_cast<qt3ds::QT3DSI32>(inStart));
+ m_SlideCore.ForceSetInstancePropertyValue(inSlide, inInstance,
+ m_Bridge.GetSceneAsset().m_EndTime,
+ static_cast<qt3ds::QT3DSI32>(inEnd));
+ }
+
+ void SetStartTime(TInstanceHandle inInstance, long inStart) override
+ {
+ m_PropertySystem.SetInstancePropertyValue(inInstance, m_Bridge.GetSceneAsset().m_StartTime,
+ static_cast<qt3ds::QT3DSI32>(inStart));
+ }
+
+ void SetEndTime(TInstanceHandle inInstance, long inEnd) override
+ {
+ m_PropertySystem.SetInstancePropertyValue(inInstance, m_Bridge.GetSceneAsset().m_EndTime,
+ static_cast<qt3ds::QT3DSI32>(inEnd));
+ }
+
+ bool IsAssetNotInActiveSlide(Q3DStudio::TIdentifier inIdentifier)
+ {
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(inIdentifier);
+ CUICDMSlideHandle theActiveSlide = m_Doc.GetActiveSlide();
+ // return true to filter the object, apparently.
+ bool isInCurrentSlide =
+ theSlide == theActiveSlide || theSlide == m_SlideSystem.GetMasterSlide(theActiveSlide);
+ return !isInCurrentSlide;
+ }
+ // The original implementation of this function is absolutely not correct
+ // in all cases.
+ void GetAssetChildrenInActiveSlide(CUICDMInstanceHandle inInstance, CGraphIterator &outIterator)
+ {
+ outIterator +=
+ Q3DStudio::TFilter(std::bind(&CDocEditor::IsAssetNotInActiveSlide, this,
+ std::placeholders::_1));
+ m_AssetGraph.GetChildren(outIterator, inInstance);
+ }
+
+ void ResizeTimeRange(TInstanceHandle inInstance, long inTime, bool inSetStart) override
+ {
+ // Get the current time range
+ std::pair<long, long> theTimeRange = GetTimeRange(inInstance);
+
+ // Change the start time or end time
+ if (inSetStart) {
+ // Never let the start time get less than 0
+ if (inTime < 0)
+ inTime = 0;
+ // Never let the start time get more than the end time
+ else if (inTime > theTimeRange.second)
+ inTime = theTimeRange.second;
+ // Set start time
+ SetStartTime(inInstance, inTime);
+ } else {
+ // Never let the end time get less than the start time
+ if (inTime < theTimeRange.first)
+ inTime = theTimeRange.first;
+ // Set end time
+ SetEndTime(inInstance, inTime);
+ }
+
+ // Iterate children and see if we need to resize children time as well
+ CGraphIterator theChildren;
+ GetAssetChildrenInActiveSlide(inInstance, theChildren);
+ for (; !theChildren.IsDone(); ++theChildren) {
+ TInstanceHandle theChild = theChildren.GetCurrent();
+ std::pair<long, long> theChildTimeRange = GetTimeRange(theChild);
+ if (inSetStart) {
+ // If we are resizing start time, if child's start time == parent's child time
+ // then we need to resize child as well
+ if (theChildTimeRange.first == theTimeRange.first)
+ ResizeTimeRange(theChild, inTime, inSetStart);
+ } else {
+ // If we are resizing end time, if child's end time == parent's end time
+ // then we need to resize child as well
+ if (theChildTimeRange.second == theTimeRange.second)
+ ResizeTimeRange(theChild, inTime, inSetStart);
+ }
+ }
+ }
+
+ void OffsetTimeRange(TInstanceHandle inInstance, long inOffset) override
+ {
+ // Get the current time range
+ std::pair<long, long> theTimeRange = GetTimeRange(inInstance);
+
+ // Do not allow the object to go into negative time
+ if (inOffset < 0 && (-inOffset) > theTimeRange.first) {
+ inOffset = -theTimeRange.first;
+ }
+ SetTimeRange(inInstance, theTimeRange.first + inOffset, theTimeRange.second + inOffset);
+ // Offset all the keyframes linked to animations of this instance by this offset.
+ m_AnimationCore.OffsetAnimations(m_Doc.GetActiveSlide(), inInstance, inOffset);
+
+ // Offset children time as well
+ CGraphIterator theChildren;
+ GetAssetChildrenInActiveSlide(inInstance, theChildren);
+ for (; !theChildren.IsDone(); ++theChildren) {
+ OffsetTimeRange(theChildren.GetCurrent(), inOffset);
+ }
+ }
+
+ void TruncateTimeRange(TInstanceHandle inInstance, bool inSetStart, long inTime) override
+ {
+ if (m_Bridge.IsMaterialInstance(inInstance) || m_Bridge.IsImageInstance(inInstance))
+ return; // bail!
+
+ // Set the time range if the instance is not the current Component or Scene
+ if (inInstance != m_Doc.GetActiveRootInstance()) {
+ std::pair<long, long> theRange(GetTimeRange(inInstance));
+ if (inSetStart)
+ theRange.first = inTime;
+ else
+ theRange.second = inTime;
+
+ // Ensure the time range is valid before going further.
+ if (theRange.first <= theRange.second)
+ SetTimeRange(inInstance, theRange.first, theRange.second);
+ }
+
+ CGraphIterator theChildren;
+ GetAssetChildrenInActiveSlide(inInstance, theChildren);
+ for (; !theChildren.IsDone(); ++theChildren)
+ TruncateTimeRange(theChildren.GetCurrent(), inSetStart, inTime);
+ }
+
+ void SetTimebarColor(TInstanceHandle inInstance, ::CColor inColor) override
+ {
+ m_PropertySystem.SetInstancePropertyValue(
+ inInstance, m_Bridge.GetSceneAsset().m_TimebarColor,
+ UICDM::SFloat3(inColor.GetRed() / 255.0f, inColor.GetGreen() / 255.0f,
+ inColor.GetBlue() / 255.0f));
+ }
+
+ void SetTimebarText(TInstanceHandle inInstance, const Q3DStudio::CString &inComment) override
+ {
+ m_PropertySystem.SetInstancePropertyValue(inInstance,
+ m_Bridge.GetSceneAsset().m_TimebarText,
+ UICDM::SStringRef(inComment.c_str()));
+ }
+
+ void AddChild(CUICDMInstanceHandle parent, CUICDMInstanceHandle child,
+ TInstanceHandle inNextSibling) override
+ {
+ TInstanceHandle currentParent = m_AssetGraph.GetParent(child);
+ if (currentParent.Valid() == false)
+ m_AssetGraph.AddChild(parent, child);
+ if (inNextSibling.Valid())
+ m_AssetGraph.MoveBefore(child, inNextSibling);
+ else
+ m_AssetGraph.MoveTo(child, parent, COpaquePosition::LAST);
+ }
+ void RemoveChild(CUICDMInstanceHandle parent, CUICDMInstanceHandle child) override
+ {
+ if (m_AssetGraph.GetParent(child) == parent) {
+ m_AssetGraph.RemoveChild(child, false);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TKeyframeType>
+ void AddKeyframes(CUICDMAnimationHandle animHandle, const float *keyframeValues, long numValues,
+ long inOffsetInSeconds)
+ {
+ long numFloatsPerKeyframe = sizeof(TKeyframeType) / sizeof(float);
+ if (numValues % numFloatsPerKeyframe) {
+ QT3DS_ASSERT(false);
+ }
+ const TKeyframeType *keyframes = reinterpret_cast<const TKeyframeType *>(keyframeValues);
+ long numKeyframes = numValues / numFloatsPerKeyframe;
+ for (long idx = 0; idx < numKeyframes; ++idx) {
+ TKeyframeType theData(keyframes[idx]);
+ theData.m_KeyframeSeconds += inOffsetInSeconds;
+ m_AnimationCore.InsertKeyframe(animHandle, theData);
+ }
+ }
+
+ void SetKeyframeTime(TKeyframeHandle inKeyframe, long inTime) override
+ {
+ float theTimeinSecs = static_cast<float>(inTime) / 1000.f;
+ // round off to 4 decimal place to workaround precision issues
+ // TODO: fix this, either all talk float OR long. choose one.
+ theTimeinSecs = ceilf(theTimeinSecs * 10000.0f) / 10000.0f;
+ TKeyframe theData = m_AnimationCore.GetKeyframeData(inKeyframe);
+ // Function programming paradigm, returns new value instead of changing
+ // current value.
+ theData = UICDM::SetKeyframeSeconds(theData, theTimeinSecs);
+ m_AnimationCore.SetKeyframeData(inKeyframe, theData);
+ }
+
+ void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) override
+ {
+ m_AnimationCore.DeleteAllKeyframes(inAnimation);
+ }
+
+ void KeyframeProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inDoDiffValue) override
+ {
+ m_AnimationSystem.KeyframeProperty(inInstance, inProperty, inDoDiffValue);
+ }
+
+ virtual CUICDMAnimationHandle
+ CreateOrSetAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle instance,
+ const wchar_t *propName, long subIndex, EAnimationType animType,
+ const float *keyframeValues, long numValues, bool /*inUserEdited*/) override
+ {
+ CUICDMPropertyHandle propHdl =
+ m_DataCore.GetAggregateInstancePropertyByName(instance, propName);
+ if (propHdl.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ if (inSlide.Valid() == false) {
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(instance);
+ if (theSlide.Valid() == false) {
+ assert(0);
+ return 0;
+ }
+ if (m_SlideSystem.IsPropertyLinked(instance, propHdl))
+ theSlide = m_SlideSystem.GetMasterSlide(theSlide);
+ inSlide = theSlide;
+ }
+
+ CUICDMAnimationHandle animHandle =
+ m_AnimationCore.GetAnimation(inSlide, instance, propHdl, subIndex);
+
+ if (animHandle.Valid() == true)
+ m_AnimationCore.DeleteAnimation(animHandle);
+
+ animHandle =
+ m_AnimationCore.CreateAnimation(inSlide, instance, propHdl, subIndex, animType, false);
+
+ long theStartTime = GetTimeRange(instance).first;
+ long theTimeOffsetInSeconds = long(theStartTime / 1000.f);
+
+ switch (animType) {
+ case EAnimationTypeLinear:
+ AddKeyframes<SLinearKeyframe>(animHandle, keyframeValues, numValues,
+ theTimeOffsetInSeconds);
+ break;
+ case EAnimationTypeBezier:
+ AddKeyframes<SBezierKeyframe>(animHandle, keyframeValues, numValues,
+ theTimeOffsetInSeconds);
+ break;
+ case EAnimationTypeEaseInOut:
+ AddKeyframes<SEaseInEaseOutKeyframe>(animHandle, keyframeValues, numValues,
+ theTimeOffsetInSeconds);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ AddKeyframes<SLinearKeyframe>(animHandle, keyframeValues, numValues,
+ theTimeOffsetInSeconds);
+ break;
+ }
+ return animHandle;
+ }
+ bool RemoveAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle instance,
+ const wchar_t *propName, long subIndex) override
+ {
+ CUICDMPropertyHandle propHdl =
+ m_DataCore.GetAggregateInstancePropertyByName(instance, propName);
+ if (propHdl.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ CUICDMAnimationHandle animHandle =
+ m_AnimationCore.GetAnimation(inSlide, instance, propHdl, subIndex);
+ if (animHandle.Valid()) {
+ m_AnimationCore.DeleteAnimation(animHandle);
+ return true;
+ }
+ return false;
+ }
+
+ void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) override
+ {
+ m_AnimationCore.SetIsArtistEdited(inAnimation, inEdited);
+ }
+
+ UICDM::CUICDMInstanceHandle
+ FinalizeAddOrDrop(UICDM::CUICDMInstanceHandle inInstance, UICDM::CUICDMInstanceHandle inParent,
+ DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition,
+ bool inSetTimeRangeToParent, bool inSelectInstanceWhenFinished = true)
+ {
+ if (inPosition.x != 0 && inPosition.y != 0) {
+ Q3DStudio::IDocSceneGraph *theGraph(m_Doc.GetSceneGraph());
+ QT3DSVec3 thePos(0, 0, 0);
+ if (theGraph) {
+ thePos = theGraph->GetIntendedPosition(inInstance, inPosition);
+ SetPosition(inInstance, SFloat3(thePos.x, thePos.y, thePos.z));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ RearrangeObject(inInstance, inParent, inInsertType);
+ if (inSetTimeRangeToParent)
+ SetTimeRangeToParent(inInstance);
+ if (inSelectInstanceWhenFinished)
+ m_Doc.SelectUICDMObject(inInstance);
+ return inInstance;
+ }
+
+ CString GetName(CUICDMInstanceHandle inInstance) const override
+ {
+ Option<SValue> theValue = GetInstancePropertyValue(
+ inInstance, m_Bridge.GetObjectDefinitions().m_Named.m_NameProp);
+ if (theValue.hasValue()) {
+ TDataStrPtr theNamePtr(get<TDataStrPtr>(*theValue));
+ if (theNamePtr)
+ return theNamePtr->GetData();
+ }
+ return L"";
+ }
+
+ CString GetSourcePath(CUICDMInstanceHandle inInstance) const override
+ {
+ Option<SValue> theValue = GetInstancePropertyValue(
+ inInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath);
+ if (theValue.hasValue()) {
+ TDataStrPtr theNamePtr(get<TDataStrPtr>(*theValue));
+ if (theNamePtr)
+ return theNamePtr->GetData();
+ }
+ return L"";
+ }
+
+ TInstanceHandle GetFirstBaseClass(CUICDMInstanceHandle inInstance) const override
+ {
+ TInstanceHandleList theList;
+ m_DataCore.GetInstanceParents(inInstance, theList);
+ if (theList.size())
+ return theList[0];
+ return 0;
+ }
+
+ void SetName(CUICDMInstanceHandle inInstance, const CString &inName,
+ bool inMakeUnique = false) override
+ {
+ CString theUniqueName = inName;
+ if (inMakeUnique)
+ theUniqueName = m_Bridge.GetUniqueChildName(GetParent(inInstance), inInstance, inName);
+
+ SetInstancePropertyValue(inInstance, m_Bridge.GetNameProperty(),
+ std::make_shared<CDataStr>(theUniqueName.c_str()), false);
+ }
+
+ TInstanceHandleList DoPasteSceneGraphObject(std::shared_ptr<IDOMReader> inReader,
+ TInstanceHandle inNewRoot,
+ bool inGenerateUniqueName,
+ DocumentEditorInsertType::Enum inInsertType,
+ const CPt &inPosition)
+ {
+ std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
+ TInstanceHandleList retval = theSerializer->SerializeSceneGraphObject(
+ *inReader, m_Doc.GetDocumentDirectory(), inNewRoot, GetActiveSlide(inNewRoot));
+ for (size_t idx = 0, end = retval.size(); idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theInstance(retval[idx]);
+ if (inInsertType == DocumentEditorInsertType::NextSibling)
+ theInstance = retval[end - idx - 1];
+
+ FinalizeAddOrDrop(theInstance, inNewRoot, inInsertType, inPosition, false);
+
+ SetName(theInstance, GetName(theInstance), inGenerateUniqueName);
+ }
+
+ return retval;
+ }
+
+ TInstanceHandleList PasteSceneGraphObject(const CFilePath &inFilePath,
+ TInstanceHandle inNewRoot,
+ bool inGenerateUniqueName,
+ DocumentEditorInsertType::Enum inInsertType,
+ const CPt &inPosition) override
+ {
+ qt3ds::QT3DSI32 theVersion = 0;
+ std::shared_ptr<IDOMReader> theReader = m_Doc.CreateDOMReader(inFilePath, theVersion);
+ if (!theReader)
+ return TInstanceHandleList();
+ return DoPasteSceneGraphObject(theReader, inNewRoot, inGenerateUniqueName, inInsertType,
+ inPosition);
+ }
+
+ virtual TInstanceHandleList
+ PasteSceneGraphObjectMaster(const CFilePath &inFilePath, TInstanceHandle inNewRoot,
+ bool inGenerateUniqueName,
+ DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition) override
+ {
+ qt3ds::QT3DSI32 theVersion = 0;
+ std::shared_ptr<IDOMReader> theReader = m_Doc.CreateDOMReader(inFilePath, theVersion);
+ if (!theReader)
+ return TInstanceHandleList();
+
+ std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
+ TInstanceHandleList retval = theSerializer->SerializeSceneGraphObject(
+ *theReader, m_Doc.GetDocumentDirectory(), inNewRoot,
+ m_Doc.GetStudioSystem()->GetSlideSystem()->GetMasterSlide(GetActiveSlide(inNewRoot)));
+ for (size_t idx = 0, end = retval.size(); idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theInstance(retval[idx]);
+ if (inInsertType == DocumentEditorInsertType::NextSibling)
+ theInstance = retval[end - idx - 1];
+
+ FinalizeAddOrDrop(theInstance, inNewRoot, inInsertType, inPosition, false);
+
+ SetName(theInstance, GetName(theInstance), inGenerateUniqueName);
+ }
+
+ return retval;
+ }
+
+ SFloat3 GetPosition(CUICDMInstanceHandle inInstance)
+ {
+ Option<SValue> theValue =
+ GetInstancePropertyValue(inInstance, m_Bridge.GetObjectDefinitions().m_Node.m_Position);
+ if (theValue.hasValue())
+ return get<SFloat3>(*theValue);
+ return SFloat3();
+ }
+
+ void SetPosition(CUICDMInstanceHandle inInstance, const SFloat3 &inPos)
+ {
+ SetInstancePropertyValue(inInstance, m_Bridge.GetObjectDefinitions().m_Node.m_Position,
+ inPos, false);
+ }
+
+ QT3DSU32 BuildGraphOrderItem(UICDM::CUICDMInstanceHandle inInstance, QT3DSU32 inCurrentIndex)
+ {
+ m_GraphOrderMap.insert(std::make_pair(inInstance.GetHandleValue(), inCurrentIndex));
+ ++inCurrentIndex;
+ for (long childIdx = 0, childEnd = m_AssetGraph.GetChildCount(inInstance);
+ childIdx < childEnd; ++childIdx) {
+ inCurrentIndex =
+ BuildGraphOrderItem(m_AssetGraph.GetChild(inInstance, childIdx), inCurrentIndex);
+ }
+ return inCurrentIndex;
+ }
+
+ QT3DSU32 GetInstanceGraphOrder(UICDM::CUICDMInstanceHandle inInstance)
+ {
+ if (m_GraphOrderMap.size() == 0) {
+ BuildGraphOrderItem(m_AssetGraph.GetRoot(0), 0);
+ }
+ std::unordered_map<long, QT3DSU32>::iterator iter = m_GraphOrderMap.find(inInstance);
+ if (iter != m_GraphOrderMap.end())
+ return iter->second;
+ return QT3DS_MAX_U32;
+ }
+
+ bool GraphOrderLessThan(UICDM::CUICDMInstanceHandle lhs, UICDM::CUICDMInstanceHandle rhs)
+ {
+ return GetInstanceGraphOrder(lhs) < GetInstanceGraphOrder(rhs);
+ }
+
+ UICDM::TInstanceHandleList ToGraphOrdering(const UICDM::TInstanceHandleList &inInstances)
+ {
+ UICDM::TInstanceHandleList sortableList(inInstances);
+ m_GraphOrderMap.clear();
+ std::sort(sortableList.begin(), sortableList.end(),
+ std::bind(&CDocEditor::GraphOrderLessThan, this, std::placeholders::_1,
+ std::placeholders::_2));
+ return sortableList;
+ }
+
+ void RearrangeObjects(const UICDM::TInstanceHandleList &inInstances,
+ TInstanceHandle inDest,
+ DocumentEditorInsertType::Enum inInsertType) override
+ {
+ // The operations here are carefully constructed to ensure the various views can handle the
+ // messages.
+ // The timeline, for instance, requires that before a create operation happens all remove
+ // operations have happened.
+
+ UICDM::TInstanceHandleList sortableList(ToGraphOrdering(inInstances));
+ for (size_t idx = 0, end = sortableList.size(); idx < end; ++idx) {
+ m_AssetGraph.RemoveChild(sortableList[idx], false);
+ }
+
+ TInstanceHandle theParent(inDest);
+ if (inInsertType == DocumentEditorInsertType::PreviousSibling
+ || inInsertType == DocumentEditorInsertType::NextSibling) {
+ theParent = GetParent(inDest);
+ }
+
+ for (size_t idx = 0, end = sortableList.size(); idx < end; ++idx) {
+ m_AssetGraph.AddChild(theParent, sortableList[idx]);
+ }
+
+ for (size_t idx = 0, end = sortableList.size(); idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theInstance(sortableList[idx]);
+ // If the insert type is next sibling, we have to reverse the list
+ // in order to respect the ordering.
+ if (inInsertType == DocumentEditorInsertType::NextSibling)
+ theInstance = sortableList[end - idx - 1];
+
+ if (inInsertType == DocumentEditorInsertType::PreviousSibling)
+ m_AssetGraph.MoveBefore(theInstance, inDest);
+ else if (inInsertType == DocumentEditorInsertType::NextSibling)
+ m_AssetGraph.MoveAfter(theInstance, inDest);
+ else if (inInsertType == DocumentEditorInsertType::LastChild)
+ m_AssetGraph.MoveTo(theInstance, inDest, COpaquePosition::LAST);
+ }
+ }
+
+ CUICDMInstanceHandle MakeComponent(const UICDM::TInstanceHandleList &inInstances) override
+ {
+ if (inInstances.empty())
+ return CUICDMInstanceHandle();
+
+ UICDM::TInstanceHandleList theInstances = ToGraphOrdering(inInstances);
+ // Do this in reverse order.
+ // first add new component.
+ CUICDMSlideHandle theSlide = GetAssociatedSlide(theInstances[0]);
+
+ TInstanceHandle component = CreateSceneGraphInstance(
+ ComposerObjectTypes::Component, theInstances[0], theSlide,
+ DocumentEditorInsertType::NextSibling, CPt(), PRIMITIVETYPE_UNKNOWN, 0);
+
+ // After consultation with Stephen Mendoza about this we decided *not* to move the start
+ // position to the component.
+ // as this breaks embedded animations unless you move the position animations to the
+ // component as well.
+ pair<long, long> theStartEndTimes = GetTimeRange(theInstances[0]);
+
+ CString theName = GetName(theInstances[0]);
+
+ // now cut the group
+ std::shared_ptr<IDOMReader> theReader(CopySceneGraphObjectsToMemory(theInstances));
+ DeleteInstances(theInstances);
+
+ std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
+ CUICDMSlideHandle theComponentSlide(m_Bridge.GetComponentActiveSlide(component));
+
+ // Paste into the master slide of the new component
+ theSerializer->SerializeSceneGraphObject(*theReader, m_Doc.GetDocumentDirectory(),
+ component,
+ m_SlideSystem.GetMasterSlide(theComponentSlide));
+
+ SetTimeRange(component, theStartEndTimes.first, theStartEndTimes.second);
+ SetName(component, theName);
+
+ m_Doc.SelectUICDMObject(component);
+ return component;
+ }
+
+ void DuplicateInstances(const UICDM::TInstanceHandleList &inInstances) override
+ {
+
+ TInstanceHandleList theInstances = ToGraphOrdering(inInstances);
+ if (theInstances.empty())
+ return;
+ DuplicateInstances(theInstances, theInstances.back(),
+ DocumentEditorInsertType::NextSibling);
+ }
+
+ TInstanceHandleList DuplicateInstances(const UICDM::TInstanceHandleList &inInstances,
+ TInstanceHandle inDest,
+ DocumentEditorInsertType::Enum inInsertType) override
+ {
+ UICDM::TInstanceHandleList theInstances(ToGraphOrdering(inInstances));
+ std::shared_ptr<IDOMReader> theReader(CopySceneGraphObjectsToMemory(theInstances));
+ return DoPasteSceneGraphObject(theReader, inDest, true, inInsertType, CPt());
+ }
+
+ CUICDMActionHandle AddAction(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ const wstring &inEvent, const wstring &inHandler) override
+ {
+ Q3DStudio::CId theGuid = m_Bridge.GetGUID(inOwner);
+ Q3DStudio::TGUIDPacked thePacked(theGuid);
+ SLong4 theInitialTriggerTarget(thePacked.Data1, thePacked.Data2, thePacked.Data3,
+ thePacked.Data4);
+ CUICDMActionHandle theAction =
+ m_ActionSystem.CreateAction(inSlide, inOwner, theInitialTriggerTarget);
+ m_ActionCore.SetEvent(theAction, inEvent);
+ m_ActionCore.SetHandler(theAction, inHandler);
+ m_Bridge.ResetHandlerArguments(theAction, inHandler);
+ return theAction;
+ }
+
+ void DeleteAction(CUICDMActionHandle inAction) override
+ {
+ m_ActionSystem.DeleteAction(inAction);
+ }
+
+ CUICDMActionHandle PasteAction(const CFilePath &inFilePath,
+ CUICDMInstanceHandle inNewRoot) override
+ {
+ CFileSeekableIOStream theStream(inFilePath, FileReadFlags());
+ if (theStream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ std::shared_ptr<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_DataCore.GetStringTablePtr()));
+ SDOMElement *theElem = CDOMSerializer::Read(*theFactory, theStream);
+ if (theElem == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ std::shared_ptr<IDOMReader> theReader(
+ IDOMReader::CreateDOMReader(*theElem, m_DataCore.GetStringTablePtr(), theFactory));
+ std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
+ return theSerializer->SerializeAction(*theReader, inNewRoot, GetActiveSlide(inNewRoot));
+ }
+
+ bool ContainsSlideByName(const CString &inName, CUICDMSlideHandle inMasterSlide)
+ {
+ size_t existingCount = m_SlideSystem.GetSlideCount(inMasterSlide);
+ for (size_t idx = 0; idx < existingCount; ++idx) {
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetSlideByIndex(inMasterSlide, idx);
+ CUICDMInstanceHandle theInstance(m_SlideSystem.GetSlideInstance(theSlide));
+ if (GetName(theInstance) == inName)
+ return true;
+ }
+ return false;
+ }
+
+ CString GenerateUniqueSlideName(const CString &inStem, CUICDMSlideHandle inMasterSlide,
+ int inStartIndex)
+ {
+ size_t theStartIndex = inStartIndex;
+ if (theStartIndex < 0)
+ theStartIndex = m_SlideSystem.GetSlideCount(inMasterSlide);
+
+ CString baseName = inStem;
+ int nameIdx = (int)theStartIndex;
+ wchar_t nameBuf[16];
+ WStrOps<int>().ToStr(nameIdx, toDataRef(nameBuf, 16));
+ CString theNameStr = baseName;
+ theNameStr.append(nameBuf);
+ while (ContainsSlideByName(theNameStr, inMasterSlide)) {
+ ++nameIdx;
+ WStrOps<int>().ToStr(nameIdx, toDataRef(nameBuf, 16));
+ theNameStr = baseName;
+ theNameStr.append(nameBuf);
+ }
+ return theNameStr;
+ }
+
+ void CheckSlideGroupPlayThroughTo(CUICDMSlideHandle inSlide)
+ {
+ CUICDMSlideHandle theMaster(m_SlideSystem.GetMasterSlide(inSlide));
+ size_t slideCount(m_SlideSystem.GetSlideCount(theMaster));
+ for (size_t idx = 1; idx < slideCount; ++idx) {
+ bool hasPrevious = idx > 1;
+ bool hasNext = idx < slideCount - 1;
+ CUICDMSlideHandle theCurrentSlide = m_SlideSystem.GetSlideByIndex(theMaster, idx);
+ CUICDMInstanceHandle theSlideInstance = m_SlideCore.GetSlideInstance(theCurrentSlide);
+ SValue theValue;
+ CUICDMPropertyHandle theProp = m_Bridge.GetObjectDefinitions().m_Slide.m_PlaythroughTo;
+ m_DataCore.GetInstancePropertyValue(theSlideInstance, theProp, theValue);
+ SStringOrInt theData(get<SStringOrInt>(theValue));
+ if (theData.GetType() == SStringOrIntTypes::Int) {
+ CUICDMSlideHandle theSlide((int)get<long>(theData.m_Value));
+ if (m_SlideCore.IsSlide(theSlide) == false) {
+ theData = SStringOrInt(std::make_shared<CDataStr>(L"Next"));
+ m_DataCore.SetInstancePropertyValue(theSlideInstance, theProp, theData);
+ }
+ }
+ // Note that we explicitly run this next section to take care of the situation
+ // where the target playthroughto slide was deleted and now we have to deal with it.
+ if ((hasNext || hasPrevious) && theData.GetType() == SStringOrIntTypes::String) {
+ TDataStrPtr theStrPtr = get<TDataStrPtr>(theData.m_Value);
+ if (hasNext == false && AreEqual(L"Next", theStrPtr->GetData()))
+ m_DataCore.SetInstancePropertyValue(
+ theSlideInstance, theProp,
+ SStringOrInt(std::make_shared<CDataStr>(L"Previous")));
+ else if (hasPrevious == false && AreEqual(L"Previous", theStrPtr->GetData()))
+ m_DataCore.SetInstancePropertyValue(
+ theSlideInstance, theProp,
+ SStringOrInt(std::make_shared<CDataStr>(L"Next")));
+ }
+ if (slideCount == 2) {
+ theProp = m_Bridge.GetObjectDefinitions().m_Slide.m_PlayMode;
+ m_DataCore.GetInstancePropertyValue(theSlideInstance, theProp, theValue);
+ TDataStrPtr theStrPtr = get<TDataStrPtr>(theValue);
+ if (AreEqual(theStrPtr->GetData(), L"Play Through To..."))
+ m_DataCore.SetInstancePropertyValue(theSlideInstance, theProp,
+ std::make_shared<CDataStr>(L"Looping"));
+ }
+ }
+ }
+
+ CUICDMSlideHandle AddSlide(CUICDMSlideHandle inMasterSlide, int inIndex = -1) override
+ {
+ CString theNewName = GenerateUniqueSlideName(L"Slide", inMasterSlide, inIndex);
+ CUICDMSlideHandle theNewSlide = m_SlideSystem.DuplicateSlide(inMasterSlide, inIndex);
+ CUICDMInstanceHandle newInstance(m_SlideSystem.GetSlideInstance(theNewSlide));
+ m_DataCore.SetInstancePropertyValue(newInstance,
+ m_Bridge.GetObjectDefinitions().m_Named.m_NameProp,
+ std::make_shared<CDataStr>(theNewName.c_str()));
+ m_Doc.SetActiveSlideWithTransaction(theNewSlide);
+ int newSlideIndex = m_SlideSystem.GetSlideIndex(theNewSlide);
+ m_SlideSystem.SetActiveSlide(inMasterSlide, newSlideIndex);
+ m_Doc.NotifyActiveSlideChanged(theNewSlide, true);
+ CheckSlideGroupPlayThroughTo(theNewSlide);
+ CUICDMInstanceHandle theInstance = m_Doc.GetSelectedInstance();
+ if (theInstance.Valid() && GetAssociatedSlide(theInstance) != inMasterSlide)
+ m_Doc.SelectUICDMObject(0);
+ return theNewSlide;
+ }
+
+ // Only valid if the master slide has more than one slide.
+ void DeleteSlide(CUICDMSlideHandle inSlide) override
+ {
+ TInstanceHandleList theInstances;
+ m_SlideSystem.GetAssociatedInstances(inSlide, theInstances);
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ // Action instances are also associated with slides but they need to be deleted
+ // by UICDM when the action itself is deleted rather than by us right here.
+ TInstanceHandle theInstance(theInstances[idx]);
+ if (m_SlideSystem.GetAssociatedSlide(theInstance) == inSlide && IsInstance(theInstance)
+ && m_DataCore.IsInstanceOrDerivedFrom(
+ theInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_Instance)) {
+ DeleteInstance(theInstance);
+ }
+ }
+
+ CUICDMSlideHandle theMaster = m_SlideCore.GetParentSlide(inSlide);
+ size_t theCount = m_SlideSystem.GetSlideCount(theMaster);
+ if (theCount < 2) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ TInstanceHandleList theSlideInstances;
+ m_SlideCore.DeleteSlide(inSlide, theSlideInstances);
+ m_DataCore.DeleteInstance(theSlideInstances[0]);
+ CheckSlideGroupPlayThroughTo(theMaster);
+ }
+
+ void RearrangeSlide(CUICDMSlideHandle inSlide, int inNewIndex) override
+ {
+ CUICDMSlideHandle theMaster = m_SlideSystem.GetMasterSlide(inSlide);
+ int theOldIndex = m_SlideSystem.GetSlideIndex(inSlide);
+ m_SlideSystem.RearrangeSlide(theMaster, theOldIndex, inNewIndex);
+ CheckSlideGroupPlayThroughTo(theMaster);
+ }
+
+ CUICDMSlideHandle DuplicateSlide(CUICDMSlideHandle inSlide) override
+ {
+ std::shared_ptr<IDOMReader> theReader(CopySlide(inSlide));
+ if (!theReader)
+ return 0;
+
+ CUICDMSlideHandle theMaster = m_SlideSystem.GetMasterSlide(inSlide);
+ int theIndex = m_SlideSystem.GetSlideIndex(inSlide);
+ std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
+
+ CString theNewName = GenerateUniqueSlideName(L"Slide", theMaster, theIndex + 1);
+
+ CUICDMSlideHandle theNewSlide = theSerializer->SerializeSlide(
+ *theReader, m_Doc.GetDocumentDirectory(), theMaster, theIndex);
+
+ CUICDMInstanceHandle newInstance(m_SlideSystem.GetSlideInstance(theNewSlide));
+ m_DataCore.SetInstancePropertyValue(newInstance,
+ m_Bridge.GetObjectDefinitions().m_Named.m_NameProp,
+ std::make_shared<CDataStr>(theNewName.c_str()));
+
+ // Ensure the active slide change gets recorded in the transaction system so that
+ // undo will place us back at the old slide before things start reading from the object
+ // model.
+ int newSlideIndex = m_SlideSystem.GetSlideIndex(theNewSlide);
+ m_SlideSystem.SetActiveSlide(theMaster, newSlideIndex);
+ m_Doc.SetActiveSlideWithTransaction(theNewSlide);
+
+ m_Doc.NotifyActiveSlideChanged(theNewSlide, true);
+ CheckSlideGroupPlayThroughTo(theNewSlide);
+ return theNewSlide;
+ }
+
+ CUICDMGuideHandle CreateGuide(const UICDM::SGuideInfo &inInfo) override
+ {
+ CUICDMGuideHandle retval = m_GuideSystem.CreateGuide();
+ m_GuideSystem.SetGuideInfo(retval, inInfo);
+ return retval;
+ }
+
+ void UpdateGuide(CUICDMGuideHandle hdl, const UICDM::SGuideInfo &inInfo) override
+ {
+ m_GuideSystem.SetGuideInfo(hdl, inInfo);
+ }
+
+ void DeleteGuide(CUICDMGuideHandle hdl) override { m_GuideSystem.DeleteGuide(hdl); }
+
+ void ClearGuides() override
+ {
+ UICDM::TGuideHandleList theGuides(GetGuides());
+ for (size_t idx = 0, end = theGuides.size(); idx < end; ++idx)
+ DeleteGuide(theGuides[idx]);
+ }
+
+ UICDM::TGuideHandleList GetGuides() const override { return m_GuideSystem.GetAllGuides(); }
+
+ UICDM::SGuideInfo GetGuideInfo(UICDM::CUICDMGuideHandle inGuide) const override
+ {
+ return m_GuideSystem.GetGuideInfo(inGuide);
+ }
+
+ bool IsGuideValid(UICDM::CUICDMGuideHandle inGuide) const override
+ {
+ return m_GuideSystem.IsGuideValid(inGuide);
+ }
+
+ bool AreGuidesEditable() const override { return m_GuideSystem.AreGuidesEditable(); }
+
+ void SetGuidesEditable(bool val) override
+ {
+ m_GuideSystem.SetGuidesEditable(val);
+ if (m_Doc.GetSelectedValue().getType() == Q3DStudio::SelectedValueTypes::Guide
+ && val == false)
+ m_Doc.NotifySelectionChanged();
+ }
+
+ TInstanceHandle DoImport(
+ CFilePath inImportFilePath, Q3DStudio::CString importSrc, CUICDMInstanceHandle inParent,
+ CUICDMInstanceHandle inRoot, CUICDMSlideHandle inSlide, Q3DStudio::CString inDocDir,
+ STranslationLog &inTranslationLog,
+ function<SImportResult(IComposerEditorInterface &, Q3DStudio::CString)> inImportFunction,
+ DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition, long inStartTime)
+ {
+ CFilePath outputDir(inImportFilePath.GetDirectory());
+ bool alwaysKeepDirectory = outputDir.Exists();
+ bool keepDirectory = false;
+ CUICDMInstanceHandle theRealParent = inInsertType == DocumentEditorInsertType::LastChild
+ ? inParent
+ : CUICDMInstanceHandle(m_AssetGraph.GetParent(inParent));
+ // We have to pass in the real parent to the editor interface so that object lifetimes can
+ // be
+ // setup correctly as the import tree is being built.
+ std::shared_ptr<IComposerEditorInterface> importToComposer =
+ IComposerEditorInterface::CreateEditorInterface(*this, theRealParent, inRoot, inSlide,
+ inDocDir, inImportFilePath, inStartTime,
+ m_StringTable);
+
+ CDispatch &theDispatch(*m_Doc.GetCore()->GetDispatch());
+ CFilePath theDestFile(importToComposer->GetDestImportFile());
+ try {
+ theDispatch.FireOnProgressBegin(Q3DStudio::CString::fromQString(QObject::tr("Loading...")), importSrc,
+ Q3DStudio::CString::fromQString(QObject::tr("Loading...")));
+ SImportResult result = inImportFunction(*importToComposer, theDestFile);
+ bool forceError = importToComposer->HasError();
+ if (!forceError)
+ importToComposer->Finalize(result.m_FilePath);
+ keepDirectory = alwaysKeepDirectory || forceError == false;
+ theDispatch.FireOnProgressEnd();
+ IDocumentEditor::DisplayImportErrors(importSrc.toQString(), result.m_Error,
+ m_Doc.GetImportFailedHandler(), inTranslationLog,
+ forceError);
+ if (!forceError) {
+ CUICDMInstanceHandle theImportRoot = importToComposer->GetRoot();
+ CFilePath theRelPath(m_Doc.GetRelativePathToDoc(theDestFile));
+ SValue theSourcePathValue(std::make_shared<CDataStr>(theRelPath.c_str()));
+ CUICDMPropertyHandle theProp(m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath);
+ if (inSlide.Valid())
+ m_SlideCore.ForceSetInstancePropertyValue(inSlide, theImportRoot, theProp,
+ theSourcePathValue);
+ else
+ m_DataCore.SetInstancePropertyValue(theImportRoot, theProp, theSourcePathValue);
+
+ CUICDMInstanceHandle retval =
+ FinalizeAddOrDrop(importToComposer->GetRoot(), inParent, inInsertType,
+ inPosition, inStartTime == -1);
+ SetName(retval, theRelPath.GetFileStem(), true);
+
+ return retval;
+ }
+ } catch (...) {
+ theDispatch.FireOnProgressEnd();
+ m_Doc.RollbackTransaction(); // Run away!!!
+ }
+ return 0;
+ }
+
+ TInstanceHandle ImportDAE(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ const Q3DStudio::CString &inImportFileExtension,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) override
+ {
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ // If we already have an import file that points back to this DAE then we need to
+ // not import the DAE but import the import file again.
+
+ CFilePath importSrc = CFilePath(inFullPathToDocument);
+ if (importSrc.Exists() == false)
+ return 0;
+ CFilePath theRelativeDAE = m_Doc.GetRelativePathToDoc(importSrc);
+
+ CFilePath docPath =
+ CFilePath(m_Doc.GetDocumentPath().GetAbsolutePath());
+ CFilePath docDir(docPath.GetDirectory());
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+ if (docPath.size() == 0) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(importSrc.toQString(),
+ QObject::tr("UIComposer Document Has No Path"),
+ false);
+ return 0;
+ }
+ if (!importSrc.IsFile()) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(importSrc.toQString(),
+ QObject::tr("Source File Doesn't Exist"), false);
+ return 0;
+ }
+
+ Q3DStudio::CString fname = importSrc.GetFileStem();
+
+ CFilePath importsDir = CFilePath::CombineBaseAndRelative(docDir, CFilePath(L"Imports"));
+ if (importsDir.Exists() == false)
+ importsDir.CreateDir(true);
+
+ CFilePath outputDir = Q3DStudio::SFileTools::FindUniqueDestDirectory(importsDir, fname);
+ Q3DStudio::CString outputFileName(fname + L"." + inImportFileExtension);
+ SColladaTranslator translator(importSrc.toQString());
+ TInstanceHandle retval =
+ DoImport(CFilePath::CombineBaseAndRelative(outputDir, outputFileName), importSrc,
+ inParent, 0, inSlide, docDir, translator.m_TranslationLog,
+ std::bind(CPerformImport::ImportToComposer, translator,
+ std::placeholders::_1, std::placeholders::_2), inDropType,
+ inPosition, inStartTime);
+ if (retval.Valid()) {
+ CFilePath theRelativeImport = m_Doc.GetRelativePathToDoc(outputFileName);
+ m_ImportFileToDAEMap.insert(
+ make_pair(m_StringTable.RegisterStr(theRelativeImport.c_str()),
+ m_StringTable.RegisterStr(theRelativeDAE.c_str())));
+ }
+
+ return retval;
+ }
+
+ TInstanceHandle LoadImportFile(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) override
+ {
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ CFilePath docPath =
+ CFilePath(m_Doc.GetDocumentPath().GetAbsolutePath());
+ CFilePath docDir(docPath.GetDirectory());
+ STranslationLog log;
+ return DoImport(inFullPathToDocument, inFullPathToDocument, inParent, 0, inSlide, docDir,
+ log, std::bind(CPerformImport::ImportToComposerFromImportFile,
+ std::placeholders::_1, std::placeholders::_2),
+ inDropType, inPosition, inStartTime);
+ }
+
+ TInstanceHandle AutomapImage(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) override
+ {
+ (void)inStartTime;
+
+ CFilePath imageSrc(inFullPathToDocument);
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+
+ if (!imageSrc.IsFile()) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(imageSrc.toQString(),
+ QObject::tr("Image File Doesn't Exist"), false);
+ return 0;
+ }
+ CFilePath relativePath = m_Doc.GetRelativePathToDoc(imageSrc);
+ SImageTextureData theImageBuffer =
+ m_Doc.GetBufferCache().GetOrCreateImageBuffer(relativePath);
+ if (theImageBuffer.m_Texture == NULL) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(imageSrc.toQString(),
+ QObject::tr("Can't Load Image File"), false);
+ return 0;
+ }
+
+ // Automap the image to a rectangle
+
+ UICDM::CUICDMInstanceHandle theModelInstance =
+ CreateSceneGraphInstance(ComposerObjectTypes::Model, inParent, inSlide);
+ m_PropertySystem.SetInstancePropertyValue(
+ theModelInstance, m_Bridge.GetSourcePathProperty(),
+ std::make_shared<UICDM::CDataStr>(
+ m_Doc.GetBufferCache().GetPrimitiveName(PRIMITIVETYPE_RECT)));
+ // Create the default material
+ UICDM::CUICDMInstanceHandle theMaterialInstance =
+ CreateSceneGraphInstance(ComposerObjectTypes::Material, theModelInstance, inSlide);
+ // Load the image as the child of the material
+ UICDM::CUICDMInstanceHandle theImageInstance = SetInstancePropertyValueAsImage(
+ theMaterialInstance, m_Bridge.GetDefaultMaterial().m_DiffuseMap1, relativePath);
+
+ if (inStartTime != -1)
+ SetStartTime(theModelInstance, inStartTime);
+
+ STextureDetails theDetails = theImageBuffer.m_Texture->GetTextureDetails();
+ float theHeight = theDetails.m_Height / 100.0f;
+ float theWidth = theDetails.m_Width / 100.0f;
+ UICDM::SFloat3 theScale = UICDM::SFloat3(2, 2, 1); // Default, per Danc.
+ if (theHeight != 0 && theWidth != 0)
+ theScale = UICDM::SFloat3(theWidth, theHeight, 1);
+ m_PropertySystem.SetInstancePropertyValue(theModelInstance, m_Bridge.GetNode().m_Scale,
+ theScale);
+
+ CFilePath theFilePath(inFullPathToDocument);
+ SetName(theModelInstance, theFilePath.GetFileStem(), true);
+
+ // Set the image as the property of the first diffuse map.
+ return FinalizeAddOrDrop(theModelInstance, inParent, inDropType, inPosition,
+ inStartTime == -1);
+ }
+
+ TInstanceHandle LoadMesh(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) override
+ {
+ CFilePath imageSrc(inFullPathToDocument);
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+ if (!imageSrc.IsFile()) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(imageSrc.toQString(),
+ QObject::tr("Source File Doesn't Exist"), false);
+ return 0;
+ }
+ Q3DStudio::CString theRelativePath(m_Doc.GetRelativePathToDoc(inFullPathToDocument));
+ SModelBufferAndPath theModelBuffer =
+ m_Doc.GetBufferCache().GetOrCreateModelBuffer(theRelativePath);
+ if (theModelBuffer.m_ModelBuffer == NULL) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(imageSrc.toQString(),
+ QObject::tr("Could Not Load Model Buffer"), false);
+ return 0;
+ }
+ // Ensure we include the model buffer version in the relative path
+ theRelativePath = m_Doc.GetRelativePathToDoc(theModelBuffer.m_FilePath);
+
+ UICDM::CUICDMInstanceHandle theModelInstance =
+ CreateSceneGraphInstance(ComposerObjectTypes::Model, inParent, inSlide);
+
+ SValue theValue(std::make_shared<UICDM::CDataStr>(theRelativePath));
+ m_PropertySystem.SetInstancePropertyValue(theModelInstance,
+ m_Bridge.GetSourcePathProperty(), theValue);
+
+ if (inStartTime != -1)
+ SetStartTime(theModelInstance, inStartTime);
+
+ CheckMeshSubsets(theModelInstance, m_Bridge.GetSourcePathProperty());
+
+ SetName(theModelInstance, imageSrc.GetFileStem(), true);
+
+ return FinalizeAddOrDrop(theModelInstance, inParent, inDropType, inPosition,
+ inStartTime == -1);
+ }
+
+ static void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
+ {
+ (void)ud;
+ (void)osize; /* not used */
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
+ } else
+ return realloc(ptr, nsize);
+ }
+
+ QString LoadLuaFile(const CFilePath &inFile)
+ {
+ QString retval;
+ lua_State *L = lua_newstate(l_alloc, NULL);
+ if (L) {
+ luaL_openlibs(L); /* Load Lua libraries */
+
+ /* Load the file containing the script we are going to run */
+ int status = luaL_loadfile(L, inFile.GetCharStar());
+ if (status) {
+ /* If something went wrong, error message is at the top of */
+ /* the stack */
+ retval.append(lua_tostring(L, -1));
+ }
+ lua_close(L);
+ }
+ return retval;
+ }
+
+ QString LoadScriptFile(const CFilePath &inFile)
+ {
+ QString retval;
+
+ QQmlEngine engine;
+ QString path = QString::fromWCharArray(inFile);
+ path.replace('\\', '/');
+ QQmlComponent component(&engine, QUrl::fromLocalFile(path),
+ QQmlComponent::CompilationMode::PreferSynchronous);
+ if (component.status() == QQmlComponent::Error)
+ retval = component.errorString().toUtf8().data();
+
+ return retval;
+ }
+
+ void DisplayLoadWarnings(const QString &inSrcPath,
+ std::vector<SMetaDataLoadWarning> &inWarnings,
+ const QString &inLoadError)
+ {
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+ if ((inWarnings.empty() && inLoadError.size() == 0) || !theHandler)
+ return;
+
+ QString resultDialogStr;
+
+ for (size_t idx = 0, end = inWarnings.size(); idx < end; ++idx) {
+ QString theTypeStr;
+ QString theMessageStr;
+
+ switch (inWarnings[idx].m_Type) {
+ case MetaDataLoadWarningType::InvalidProperty:
+ theTypeStr = QObject::tr("Invalid Property");
+ break;
+ case MetaDataLoadWarningType::InvalidEvent:
+ theTypeStr = QObject::tr("Invalid Event");
+ break;
+ case MetaDataLoadWarningType::InvalidHandler:
+ theTypeStr = QObject::tr("Invalid Handler");
+ break;
+ }
+
+ switch (inWarnings[idx].m_Message) {
+ case MetaDataLoadWarningMessage::GeneralError:
+ theMessageStr = QObject::tr("General Error");
+ break;
+ case MetaDataLoadWarningMessage::MissingName:
+ theMessageStr = QObject::tr("Missing Name");
+ break;
+ case MetaDataLoadWarningMessage::InvalidDefault:
+ theMessageStr = QObject::tr("Invalid Default");
+ break;
+ }
+
+ if (inWarnings[idx].m_ExtraInfo.size()) {
+ theMessageStr.append(" ");
+ theMessageStr.append(QString::fromStdWString(inWarnings[idx].m_ExtraInfo.wide_str()));
+ }
+
+ const QString theBuffer = QStringLiteral("%1: %2\n").arg(theTypeStr).arg(theMessageStr);
+
+ resultDialogStr.append(theBuffer);
+ }
+ if (inLoadError.size()) {
+ resultDialogStr.append(QObject::tr("\nError parsing script file: "));
+ resultDialogStr.append(inLoadError);
+ }
+ if (resultDialogStr.size())
+ theHandler->DisplayImportFailed(inSrcPath, resultDialogStr, true);
+ }
+
+ // Apply meta data to a new dynamic instance. This sets up the default properties to
+ // be what the meta data specifies.
+ void ApplyDynamicMetaData(CUICDMInstanceHandle inDynamicInstance,
+ CUICDMInstanceHandle inDynamic)
+ {
+ std::vector<SMetaDataLoadWarning> theWarnings;
+ // For all of the object std::ref properties, check if they have an absolute path
+ // reference (path starts with "Scene". If they do, then attempt to resolve the reference.
+ vector<CUICDMMetaDataPropertyHandle> theProperties;
+ m_MetaData.GetSpecificMetaDataProperties(inDynamic, theProperties);
+ for (size_t propIdx = 0, propEnd = theProperties.size(); propIdx < propEnd; ++propIdx) {
+ SMetaDataPropertyInfo theInfo(
+ m_MetaData.GetMetaDataPropertyInfo(theProperties[propIdx]));
+ if (theInfo.m_CompleteType == CompleteMetaDataType::ObjectRef
+ && GetValueType(theInfo.m_DefaultValue) == DataModelDataType::ObjectRef) {
+ SObjectRefType theRef(get<SObjectRefType>(theInfo.m_DefaultValue));
+ wstring theData;
+ wstring theOriginalData;
+ if (theRef.GetReferenceType() == ObjectReferenceType::Relative) {
+ TDataStrPtr theRefValue = get<TDataStrPtr>(theRef.m_Value);
+ if (theRefValue) {
+ theData.assign(theRefValue->GetData());
+ }
+ }
+ theOriginalData = theData;
+
+ if (theData.find(L"Scene") == 0 || theData.size() == 0) {
+ CUICDMInstanceHandle currentInstance = inDynamicInstance;
+ // Resolve this absolute reference string and override the default values
+ // in the datacore to be this exact datatype
+ if (theData.find(L"Scene") == 0) {
+ wstring theItemName;
+ // Walk through the data and attempt to find each object in the asset graph
+ // ignoring slides or anything else.
+ if (theData.size() > 6)
+ theData = theData.substr(6);
+ else
+ theData = L"";
+ currentInstance = m_Doc.GetSceneInstance();
+ while (theData.size() && currentInstance.Valid()) {
+ wstring::size_type thePos = theData.find(L".");
+ if (thePos != wstring::npos) {
+ theItemName = theData.substr(0, thePos);
+ theData = theData.substr(thePos + 1);
+ } else {
+ theItemName = theData;
+ theData = L"";
+ }
+ // Attempt to find the item in the asset graph.
+ long theChildCount = m_AssetGraph.GetChildCount(currentInstance);
+ CUICDMInstanceHandle lastInstance = currentInstance;
+ currentInstance = 0;
+ for (long childIdx = 0;
+ childIdx < theChildCount && currentInstance.Valid() == false;
+ ++childIdx) {
+ CUICDMInstanceHandle theChild =
+ m_AssetGraph.GetChild(lastInstance, childIdx);
+ CString theName(GetName(theChild));
+ if (theName.Compare(theItemName.c_str()))
+ currentInstance = theChild;
+ }
+ }
+ }
+
+ if (currentInstance.Valid()) {
+ CId theId(m_Bridge.GetGUID(currentInstance));
+
+ TGUIDPacked thePackedGuid(theId);
+ UICDM::SLong4 theGuid(thePackedGuid.Data1, thePackedGuid.Data2,
+ thePackedGuid.Data3, thePackedGuid.Data4);
+ theRef.m_Value = theGuid;
+ // Override the default value with a valid instance.
+ m_DataCore.SetInstancePropertyValue(inDynamic, theInfo.m_Property, theRef);
+ }
+ }
+ }
+ }
+ }
+
+ class ISpecificDynamicInstance
+ {
+ public:
+ virtual ~ISpecificDynamicInstance() {}
+
+ virtual CUICDMInstanceHandle GetRootInstance() = 0;
+ // returns an error if there was one. Empty string means no error.
+ virtual QString LoadInstanceData(const CFilePath &inAbsPath) = 0;
+
+ virtual std::shared_ptr<IDOMReader>
+ ParseInstanceDefinition(const CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory) = 0;
+ };
+
+ virtual TInstanceHandle LoadDynamicInstance(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime,
+ ISpecificDynamicInstance &inSpecificInstance,
+ bool inFinalize)
+ {
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ TInstanceHandleList existing;
+ m_DataCore.GetInstancesDerivedFrom(existing, inSpecificInstance.GetRootInstance());
+ CFilePath theRelativePath(m_Doc.GetRelativePathToDoc(inFullPathToDocument));
+ TInstanceHandleList theParents;
+ CUICDMInstanceHandle theParentInstance;
+ for (size_t idx = 0, end = existing.size(); idx < end && theParentInstance.Valid() == false;
+ ++idx) {
+ CUICDMInstanceHandle theBehavior(existing[idx]);
+ theParents.clear();
+ m_DataCore.GetInstanceParents(theBehavior, theParents);
+ if (theParents.empty() || theParents[0] != inSpecificInstance.GetRootInstance())
+ continue;
+ // Ensure this object is *directly* derived from behavior, not indirectly.
+ if (theRelativePath == GetSourcePath(existing[idx]))
+ theParentInstance = existing[idx];
+ }
+
+ if (theParentInstance.Valid() == false) {
+ std::shared_ptr<IDOMReader> theReaderPtr(inSpecificInstance.ParseInstanceDefinition(
+ inFullPathToDocument, m_DataCore.GetStringTablePtr(),
+ m_Doc.GetImportFailedHandler(), *m_InputStreamFactory));
+ if (theReaderPtr) {
+ theParentInstance = m_DataCore.CreateInstance();
+ m_DataCore.DeriveInstance(theParentInstance, inSpecificInstance.GetRootInstance());
+ m_DataCore.SetInstancePropertyValue(
+ theParentInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath,
+ std::make_shared<CDataStr>((const wchar_t *)theRelativePath));
+
+ m_DataCore.SetInstancePropertyValue(
+ theParentInstance, m_Bridge.GetObjectDefinitions().m_Named.m_NameProp,
+ std::make_shared<CDataStr>(theRelativePath.GetFileStem().c_str()));
+ std::vector<SMetaDataLoadWarning> theWarnings;
+ m_MetaData.LoadInstance(*theReaderPtr, theParentInstance,
+ theRelativePath.GetFileStem().c_str(), theWarnings);
+ QString theLoadError = inSpecificInstance.LoadInstanceData(inFullPathToDocument);
+ DisplayLoadWarnings(inFullPathToDocument.toQString(), theWarnings, theLoadError);
+ }
+ }
+ if (theParentInstance.Valid()) {
+ TInstanceHandle retval(IDocumentEditor::CreateSceneGraphInstance(
+ theParentInstance, inParent, inSlide, m_DataCore, m_SlideSystem,
+ m_Bridge.GetObjectDefinitions(), m_AssetGraph, m_MetaData));
+
+ ApplyDynamicMetaData(retval, theParentInstance);
+ if (inStartTime != -1)
+ SetStartTime(retval, inStartTime);
+
+ // Set unique name
+ SetName(retval, GetName(retval), true);
+
+ if (inFinalize)
+ return FinalizeAddOrDrop(retval, inParent, inDropType, CPt(), inStartTime == -1);
+ return retval;
+ }
+ return 0;
+ }
+
+ struct CLuaDynamicInstanceLoader : public ISpecificDynamicInstance
+ {
+ CDocEditor &m_Editor;
+ CLuaDynamicInstanceLoader(CDocEditor &ed)
+ : m_Editor(ed)
+ {
+ }
+
+ CUICDMInstanceHandle GetRootInstance() override
+ {
+ return m_Editor.m_Bridge.GetObjectDefinitions().m_Behavior.m_Instance;
+ }
+ // returns an error if there was one. Empty string means no error.
+ QString LoadInstanceData(const CFilePath &inAbsPath) override
+ {
+ return m_Editor.LoadLuaFile(inAbsPath);
+ }
+
+ virtual std::shared_ptr<IDOMReader>
+ ParseInstanceDefinition(const CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory) override
+ {
+ return IDocumentEditor::ParseLuaFile(inFullPathToDocument, inStringTable, inHandler,
+ inInputStreamFactory);
+ }
+ };
+
+ struct CScriptDynamicInstanceLoader : public ISpecificDynamicInstance
+ {
+ CDocEditor &m_Editor;
+ CScriptDynamicInstanceLoader(CDocEditor &ed)
+ : m_Editor(ed)
+ {
+ }
+
+ CUICDMInstanceHandle GetRootInstance() override
+ {
+ return m_Editor.m_Bridge.GetObjectDefinitions().m_Behavior.m_Instance;
+ }
+ // returns an error if there was one. Empty string means no error.
+ QString LoadInstanceData(const CFilePath &inAbsPath) override
+ {
+ return m_Editor.LoadScriptFile(inAbsPath);
+ }
+
+ virtual std::shared_ptr<IDOMReader>
+ ParseInstanceDefinition(const CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory) override
+ {
+ return IDocumentEditor::ParseScriptFile(inFullPathToDocument, inStringTable, inHandler,
+ inInputStreamFactory);
+ }
+ };
+
+ TInstanceHandle LoadBehavior(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime) override
+ {
+ if (inFullPathToDocument.Find(".lua") != Q3DStudio::CString::ENDOFSTRING) {
+ CLuaDynamicInstanceLoader loader(*this);
+ return LoadDynamicInstance(inFullPathToDocument, inParent, inSlide,
+ inDropType, inStartTime, loader, true);
+ } else {
+ CScriptDynamicInstanceLoader loader(*this);
+ return LoadDynamicInstance(inFullPathToDocument, inParent, inSlide,
+ inDropType, inStartTime, loader, true);
+ }
+ }
+
+ struct CRenderPluginDynamicInstanceLoader : public ISpecificDynamicInstance
+ {
+ CDocEditor &m_Editor;
+ CRenderPluginDynamicInstanceLoader(CDocEditor &ed)
+ : m_Editor(ed)
+ {
+ }
+
+ CUICDMInstanceHandle GetRootInstance() override
+ {
+ return m_Editor.m_Bridge.GetObjectDefinitions().m_RenderPlugin.m_Instance;
+ }
+ // returns an error if there was one. Empty string means no error.
+ QString LoadInstanceData(const CFilePath &) override
+ {
+ // We would want to ask the render system to possibly load the dll at this point.
+ return QString();
+ }
+
+ virtual std::shared_ptr<IDOMReader>
+ ParseInstanceDefinition(const CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory) override
+ {
+ return IDocumentEditor::ParsePluginFile(inFullPathToDocument, inStringTable, inHandler,
+ inInputStreamFactory);
+ }
+ };
+
+ TInstanceHandle LoadRenderPlugin(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime) override
+ {
+ CRenderPluginDynamicInstanceLoader loader(*this);
+ TInstanceHandle retval = LoadDynamicInstance(inFullPathToDocument, inParent, inSlide,
+ inDropType, inStartTime, loader, false);
+ // Insert at the beginning.
+ if (m_AssetGraph.GetChildCount(inParent) > 1)
+ RearrangeObject(retval, m_AssetGraph.GetChild(inParent, 0),
+ DocumentEditorInsertType::PreviousSibling);
+ return retval;
+ };
+
+ TInstanceHandle CreateText(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) override
+ {
+ (void)inStartTime;
+
+ CFilePath theFontFile(inFullPathToDocument);
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+
+ if (!theFontFile.IsFile()) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(theFontFile.toQString(),
+ QObject::tr("Font File Doesn't Exist"), false);
+ return 0;
+ }
+
+ // Get the font name of the font file
+ CString theFontName = m_Doc.GetProjectFontName(theFontFile);
+ if (theFontName.size() == 0) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(theFontFile.toQString(),
+ QObject::tr("Unable to load Font File"), false);
+ return 0;
+ }
+
+ // Create text instance
+ UICDM::CUICDMInstanceHandle theTextInstance =
+ CreateSceneGraphInstance(ComposerObjectTypes::Text, inParent, inSlide);
+
+ // Set the Font property to the font file
+ m_PropertySystem.SetInstancePropertyValue(theTextInstance, m_Bridge.GetText().m_Font,
+ std::make_shared<UICDM::CDataStr>(theFontName));
+
+ if (inStartTime != -1)
+ SetStartTime(theTextInstance, inStartTime);
+
+ // Set unique name
+ SetName(theTextInstance, GetName(theTextInstance), true);
+
+ return FinalizeAddOrDrop(theTextInstance, inParent, inDropType, inPosition,
+ inStartTime == -1);
+ }
+
+ typedef void (IMetaData::*TDynamicObjectLoader)(const char *inShaderFile,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &stream);
+
+ TInstanceHandle LoadDynamicObject(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType, long inStartTime,
+ TDynamicObjectLoader inLoader,
+ TInstanceHandle inDerivationParent,
+ TInstanceHandle inTargetId = TInstanceHandle())
+ {
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ CFilePath theShaderFile(inFullPathToDocument);
+ if (theShaderFile.GetExtension() == "nvmpe") {
+ // If user drag-drop nvmpe file, we find the corresponding glsl file and use it to load
+ // the effect.
+ theShaderFile = theShaderFile.substr(0, theShaderFile.Length() - 5);
+ theShaderFile.append("glsl");
+ }
+
+ TInstanceHandleList existing;
+ m_DataCore.GetInstancesDerivedFrom(existing, inDerivationParent);
+ CFilePath theRelativePath(m_Doc.GetRelativePathToDoc(theShaderFile));
+ TInstanceHandleList theParents;
+ CUICDMInstanceHandle theParentInstance;
+ for (size_t idx = 0, end = existing.size(); idx < end && theParentInstance.Valid() == false;
+ ++idx) {
+ CUICDMInstanceHandle theEffect(existing[idx]);
+ theParents.clear();
+ m_DataCore.GetInstanceParents(theEffect, theParents);
+ if (theParents.empty() || theParents[0] != inDerivationParent)
+ continue;
+ // Ensure this object is *directly* derived from Effect, not indirectly.
+ if (theRelativePath == GetSourcePath(existing[idx]))
+ theParentInstance = existing[idx];
+ }
+
+ if (theParentInstance.Valid() == false) {
+ if (theShaderFile.Exists()) {
+ theParentInstance = m_DataCore.CreateInstance();
+ m_DataCore.DeriveInstance(theParentInstance, inDerivationParent);
+ m_DataCore.SetInstancePropertyValue(
+ theParentInstance, m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath,
+ std::make_shared<CDataStr>((const wchar_t *)theRelativePath));
+
+ m_DataCore.SetInstancePropertyValue(
+ theParentInstance, m_Bridge.GetObjectDefinitions().m_Named.m_NameProp,
+ std::make_shared<CDataStr>(theRelativePath.GetFileStem().c_str()));
+
+ std::vector<SMetaDataLoadWarning> theWarnings;
+ QString shaderFile = QString::fromWCharArray(theShaderFile);
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream(
+ m_InputStreamFactory->GetStreamForFile(shaderFile));
+ (m_MetaData.*inLoader)(m_StringTable.GetNarrowStr(theRelativePath),
+ theParentInstance,
+ theRelativePath.GetFileStem().c_str(),
+ theWarnings,
+ *theStream);
+ DisplayLoadWarnings(shaderFile, theWarnings, QString());
+ } else {
+ if (theHandler)
+ theHandler->DisplayImportFailed(theShaderFile.toQString(),
+ QObject::tr("Unable to load Shader File"),
+ false);
+ return 0;
+ }
+ }
+
+ TInstanceHandle retval(IDocumentEditor::CreateSceneGraphInstance(
+ theParentInstance, inParent, inSlide, m_DataCore, m_SlideSystem,
+ m_Bridge.GetObjectDefinitions(), m_AssetGraph, m_MetaData, inTargetId));
+
+ if (inStartTime != -1)
+ SetStartTime(retval, inStartTime);
+
+ // Set unique name
+ SetName(retval, GetName(retval), true);
+
+ return FinalizeAddOrDrop(retval, inParent, inDropType, CPt(), inStartTime == -1);
+ }
+
+ TInstanceHandle LoadEffect(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType, long inStartTime) override
+ {
+ return LoadDynamicObject(inFullPathToDocument, inParent, inSlide, inDropType, inStartTime,
+ &IMetaData::LoadEffectInstance,
+ m_Bridge.GetObjectDefinitions().m_Effect.m_Instance);
+ }
+
+ TInstanceHandle LoadCustomMaterial(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime,
+ TInstanceHandle inTargetId = TInstanceHandle()) override
+ {
+ return LoadDynamicObject(inFullPathToDocument, inParent, inSlide, inDropType, inStartTime,
+ &IMetaData::LoadMaterialInstance,
+ m_Bridge.GetObjectDefinitions().m_CustomMaterial.m_Instance,
+ inTargetId);
+ }
+
+ static void eatspace(const char8_t *str)
+ {
+ while (!isTrivial(str) && *str == ' ') {
+ ++str;
+ }
+ }
+
+ static void *LuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
+ {
+ CDocEditor *ctx = reinterpret_cast<CDocEditor *>(ud);
+ if (nsize == 0) {
+ if (ptr)
+ ctx->m_Foundation.m_AllocatorCallback->deallocate(ptr);
+ return NULL;
+ } else {
+ if (nsize < osize && ptr)
+ return ptr;
+
+ void *newMem = ctx->m_Foundation.m_AllocatorCallback->allocate(nsize, "lua memory",
+ __FILE__, __LINE__);
+ if (osize && ptr) {
+ size_t copyAmt = NVMin(osize, nsize);
+ memCopy(newMem, ptr, (QT3DSU32)copyAmt);
+ ctx->m_Foundation.m_AllocatorCallback->deallocate(ptr);
+ }
+ return newMem;
+ }
+ }
+
+ void EnsureLuaState()
+ {
+ if (m_LuaState == NULL) {
+ Q3DStudio::CFilePath thePath;
+ thePath.GetModuleFilePath();
+ Q3DStudio::CFilePath theAppDir = thePath.GetDirectory();
+ Q3DStudio::CFilePath theAbsoluteLuaDirectory =
+ CFilePath::CombineBaseAndRelative(theAppDir, "res\\lua");
+ Q3DStudio::CFilePath theLuaDll =
+ CFilePath::CombineBaseAndRelative(theAbsoluteLuaDirectory, "lua5.1.dll");
+
+ m_LuaState =
+ IDynamicLua::CreateDynamicLua(*m_Foundation.m_Foundation, theLuaDll.GetCharStar());
+ if (m_LuaState) {
+ m_LuaState->AddLibraryPath(theAbsoluteLuaDirectory.GetCharStar(),
+ IDynamicLua::LuaModule);
+ m_LuaState->AddLibraryPath(theAbsoluteLuaDirectory.GetCharStar(),
+ IDynamicLua::CModule);
+ CFilePath theSVGLoader = CFilePath::CombineBaseAndRelative(theAbsoluteLuaDirectory,
+ "parse_to_cubic.lua");
+ m_LuaState->LoadLuaFile(theSVGLoader.GetCharStar(), "SVGPARSER");
+ }
+ }
+ }
+
+ void SetUniqueName(TInstanceHandle inItem, const char8_t *inNameBase,
+ eastl::vector<Q3DStudio::CString> &inExistingNames)
+ {
+ Q3DStudio::CString theName(inNameBase);
+ QT3DSU32 idx = 1;
+ while (eastl::find(inExistingNames.begin(), inExistingNames.end(), theName)
+ != inExistingNames.end()) {
+ char8_t nameBuffer[64];
+ sprintf(nameBuffer, "%d", idx);
+ ++idx;
+ theName.assign(inNameBase);
+ theName.append("_");
+ theName.append(nameBuffer);
+ }
+ SetName(inItem, theName, false);
+ inExistingNames.push_back(theName);
+ }
+
+ void ParseSVGGroupChildren(TInstanceHandle inNewItem, TSlideHandle inSlide)
+ {
+ IDynamicLua::Scope __itemScope(*m_LuaState);
+ QT3DSI32 childIndex = 1;
+ eastl::vector<Q3DStudio::CString> existingNames;
+ for (bool success = m_LuaState->GetChildFromTopOfStackTable(childIndex); success;
+ ++childIndex, success = m_LuaState->GetChildFromTopOfStackTable(childIndex)) {
+ ParseSVGItem(inNewItem, inSlide, existingNames);
+ m_LuaState->SetTop(__itemScope.m_Top);
+ }
+ }
+
+ TInstanceHandle ParseSVGGroup(TInstanceHandle inParent, TSlideHandle inSlide,
+ eastl::vector<Q3DStudio::CString> &inExistingNames)
+ {
+ eastl::string itemType = m_LuaState->StringFromTopOfStackTable("TYPE");
+ eastl::string itemName = m_LuaState->StringFromTopOfStackTable("name");
+ if (itemName.size() == 0)
+ itemName = "Group";
+ // bool success = m_LuaState->GetChildFromTopOfStackTable( 1 );
+ TInstanceHandle retval =
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Group, inParent, inSlide);
+ SetUniqueName(retval, itemName.c_str(), inExistingNames);
+ ParseSVGGroupChildren(retval, inSlide);
+ return retval;
+ }
+
+ TInstanceHandle ParseSVGPath(TInstanceHandle inParent, TSlideHandle inSlide,
+ eastl::vector<Q3DStudio::CString> &inExistingNames)
+ {
+ QT3DSF32 strokeWidth = ToUICDM(m_LuaState->NumberFromTopOfStackTable("stroke-width"), 1.0f);
+ QT3DSF32 pathOpacity = ToUICDM(m_LuaState->NumberFromTopOfStackTable("opacity"), 100.0f);
+ QT3DSF32 fillOpacity = ToUICDM(m_LuaState->NumberFromTopOfStackTable("fill-opacity"), 100.0f);
+ QT3DSF32 strokeOpacity =
+ ToUICDM(m_LuaState->NumberFromTopOfStackTable("stroke-opacity"), 100.0f);
+ Option<QT3DSVec3> fillColor = m_LuaState->Vec3FromTopOfStackTable("fill");
+ Option<QT3DSVec3> strokeColor = m_LuaState->Vec3FromTopOfStackTable("stroke");
+ eastl::string pathName = m_LuaState->StringFromTopOfStackTable("name");
+ QT3DSI32 childIndex = 1;
+ eastl::vector<Q3DStudio::CString> existingNames;
+ bool hasStroke = strokeColor.hasValue();
+ bool hasFill = fillColor.hasValue();
+ if (!hasStroke && !hasFill)
+ return TInstanceHandle();
+ TInstanceHandle retval =
+ CreateSceneGraphInstance(ComposerObjectTypes::Path, inParent, inSlide);
+ SetUniqueName(retval, pathName.c_str(), inExistingNames);
+ CreateSceneGraphInstance(ComposerObjectTypes::Material, retval, inSlide);
+ {
+ TInstanceHandle strokeMaterial = m_AssetGraph.GetChild(retval, 0);
+ SetName(strokeMaterial, L"Stroke");
+ }
+ eastl::vector<qt3ds::QT3DSVec2> thePoints;
+ UICDM::ISlideCore &theSlideCore(
+ *m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetTransactionlessSlideCore());
+ SComposerObjectDefinitions &theDefs(m_Bridge.GetObjectDefinitions());
+ for (bool success = m_LuaState->GetChildFromTopOfStackTable(childIndex); success;
+ ++childIndex, success = m_LuaState->GetChildFromTopOfStackTable(childIndex)) {
+ TInstanceHandle subpath =
+ CreateSceneGraphInstance(ComposerObjectTypes::SubPath, retval, inSlide);
+ wchar_t theNameBuffer[256];
+ swprintf(theNameBuffer, 256, L"SubPath_%d", childIndex);
+ SetName(subpath, theNameBuffer);
+ bool isClosed = ToUICDM(m_LuaState->BooleanFromTopOfStackTable("closepath"), true);
+ theSlideCore.ForceSetInstancePropertyValue(inSlide, subpath, theDefs.m_SubPath.m_Closed,
+ isClosed);
+ // Note that this pops the child off the stack so it is no longer available as it is the
+ // first argument
+ // to the coordinates function.
+ if (!m_LuaState->ExecuteFunction("SVGPARSER", "coordinates", 1, 1))
+ continue;
+ int theTop1 = m_LuaState->GetTop();
+ thePoints.clear();
+ m_LuaState->ParseFloatingPointPairArray(thePoints);
+ int theTop2 = m_LuaState->GetTop();
+ QT3DSU32 numAnchors = (thePoints.size() / 3) + 1;
+ if (thePoints.size() == 0)
+ numAnchors = 0;
+ // Update points so that control points are relative to their respective anchors
+ for (QT3DSU32 anchorIdx = 0, anchorEnd = numAnchors; anchorIdx < anchorEnd; ++anchorIdx) {
+ QT3DSU32 pointIdx = anchorIdx * 3;
+ QT3DSVec2 position = thePoints[pointIdx];
+ if (pointIdx) {
+ QT3DSVec2 incomingControl = thePoints[pointIdx - 1];
+ incomingControl -= position;
+ thePoints[pointIdx - 1] = incomingControl;
+ }
+ if (anchorIdx < (numAnchors - 1)) {
+ QT3DSVec2 outgoingControl = thePoints[pointIdx + 1];
+ outgoingControl -= position;
+ thePoints[pointIdx + 1] = outgoingControl;
+ }
+ }
+
+ for (QT3DSU32 idx = 0, end = numAnchors; idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle anchorCanon =
+ m_MetaData.GetCanonicalInstanceForType(L"PathAnchorPoint");
+ TInstanceHandle anchor = m_DataCore.CreateInstance();
+ TInstanceHandle theDerivationParent(anchorCanon);
+ m_DataCore.DeriveInstance(anchor, theDerivationParent);
+ if (inSlide.Valid())
+ m_SlideSystem.AssociateInstanceWithSlide(inSlide, anchor);
+ m_AssetGraph.AddChild(subpath, anchor);
+ QT3DSU32 pointIdx = idx * 3;
+ QT3DSVec2 position(thePoints[pointIdx]);
+ QT3DSVec2 incoming(0, 0);
+ QT3DSVec2 outgoing(0, 0);
+ Option<float> angle;
+
+ if (idx > 0) {
+ incoming = QT3DSVec2(thePoints[pointIdx - 1]);
+ if (incoming.magnitudeSquared() > .001f)
+ angle = ToDeg(NVAtan2(incoming.y, incoming.x));
+ }
+
+ if (idx < (numAnchors - 1)) {
+ outgoing = QT3DSVec2(thePoints[pointIdx + 1]);
+ if (!idx || (angle.hasValue() == false)) {
+ angle = ToDeg(NVAtan2(outgoing.y, outgoing.x)) + 180.0f;
+ }
+ }
+
+ if (!angle.hasValue())
+ angle = 0.0f;
+
+ float incomingdistance = incoming.magnitude();
+ float outgoingdistance = outgoing.magnitude();
+
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, anchor, theDefs.m_PathAnchorPoint.m_Position.m_Property,
+ SFloat2(position.x, position.y));
+
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, anchor, theDefs.m_PathAnchorPoint.m_IncomingAngle.m_Property, *angle);
+
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, anchor, theDefs.m_PathAnchorPoint.m_IncomingDistance.m_Property,
+ incomingdistance);
+
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, anchor, theDefs.m_PathAnchorPoint.m_OutgoingDistance.m_Property,
+ outgoingdistance);
+ }
+ int theTop = m_LuaState->GetTop();
+ (void)theTop;
+ }
+
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, retval, m_Bridge.GetObjectDefinitions().m_Node.m_Opacity, pathOpacity);
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, retval, m_Bridge.GetObjectDefinitions().m_Path.m_Width, strokeWidth);
+
+ if (hasFill) {
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, retval, m_Bridge.GetObjectDefinitions().m_Path.m_PathType,
+ TDataStrPtr(new CDataStr(L"Painted")));
+ QT3DSI32 fillMaterialIndex = 1;
+ if (hasStroke == false) {
+ fillMaterialIndex = 0;
+ SetInstancePropertyValue(retval,
+ m_Bridge.GetObjectDefinitions().m_Path.m_PaintStyle,
+ TDataStrPtr(new CDataStr(L"Filled")));
+ } else
+ SetInstancePropertyValue(retval,
+ m_Bridge.GetObjectDefinitions().m_Path.m_PaintStyle,
+ TDataStrPtr(new CDataStr(L"Filled and Stroked")));
+
+ UICDM::CUICDMInstanceHandle theFillMaterial =
+ m_AssetGraph.GetChild(retval, fillMaterialIndex);
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, theFillMaterial, m_Bridge.GetObjectDefinitions().m_Material.m_DiffuseColor,
+ ToUICDM(*fillColor));
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, theFillMaterial, m_Bridge.GetObjectDefinitions().m_Material.m_Opacity,
+ fillOpacity);
+ }
+ if (hasStroke) {
+ UICDM::CUICDMInstanceHandle theStrokeMaterial = m_AssetGraph.GetChild(retval, 0);
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, theStrokeMaterial,
+ m_Bridge.GetObjectDefinitions().m_Material.m_DiffuseColor, ToUICDM(*strokeColor));
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, theStrokeMaterial, m_Bridge.GetObjectDefinitions().m_Material.m_Opacity,
+ strokeOpacity);
+ }
+ return retval;
+ }
+
+ TInstanceHandle ParseSVGItem(TInstanceHandle inParent, TSlideHandle inSlide,
+ eastl::vector<Q3DStudio::CString> &inExistingNames)
+ {
+ IDynamicLua::Scope __itemScope(*m_LuaState);
+ eastl::string objType = m_LuaState->StringFromTopOfStackTable("TYPE");
+ if (objType == "group")
+ return ParseSVGGroup(inParent, inSlide, inExistingNames);
+ else
+ return ParseSVGPath(inParent, inSlide, inExistingNames);
+ }
+
+ virtual TInstanceHandle LoadPathBuffer(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime)
+ {
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+ Q3DStudio::CString relPath = m_Doc.GetRelativePathToDoc(inFullPathToDocument);
+ TInstanceHandle retval =
+ CreateSceneGraphInstance(ComposerObjectTypes::Path, inParent, inSlide);
+ Q3DStudio::CFilePath theFilePath(relPath);
+
+ SetName(retval, theFilePath.GetFileStem().GetCharStar(), true);
+ CreateSceneGraphInstance(ComposerObjectTypes::Material, retval, inSlide);
+ {
+ TInstanceHandle strokeMaterial = m_AssetGraph.GetChild(retval, 0);
+ SetName(strokeMaterial, L"Stroke");
+ }
+
+ UICDM::ISlideCore &theSlideCore(
+ *m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetTransactionlessSlideCore());
+ theSlideCore.ForceSetInstancePropertyValue(
+ inSlide, retval, m_Bridge.GetObjectDefinitions().m_Path.m_PathType,
+ TDataStrPtr(new CDataStr(L"Painted")));
+ SetInstancePropertyValue(retval, m_Bridge.GetObjectDefinitions().m_Asset.m_SourcePath,
+ TDataStrPtr(new CDataStr(relPath.c_str())));
+ FinalizeAddOrDrop(retval, inParent, inDropType, CPt(), inStartTime == -1, false);
+ return retval;
+ }
+
+ virtual TInstanceHandle LoadPath(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType, long inStartTime)
+ {
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+ eastl::vector<QT3DSU8> fileData;
+ {
+ CFileSeekableIOStream theFile(inFullPathToDocument, FileReadFlags());
+ if (theFile.IsOpen()) {
+ QT3DSU8 buf[1024];
+
+ for (QT3DSU32 amountRead = theFile.Read(toDataRef(buf, 1024)); amountRead;
+ amountRead = theFile.Read(toDataRef(buf, 1024))) {
+ fileData.insert(fileData.end(), buf, buf + amountRead);
+ }
+ }
+ }
+ if (fileData.size() == 0)
+ return TInstanceHandle();
+
+ fileData.push_back(0);
+ fileData.push_back(0); // just in case utf-16
+ EnsureLuaState();
+ IDynamicLua::Scope __parseScope(*m_LuaState);
+ eastl::vector<QT3DSVec2> thePoints;
+ TInstanceHandle retval;
+ if (m_LuaState->ExecuteFunction("SVGPARSER", "pathsfromxml",
+ (const char8_t *)fileData.data())) {
+ // Build list of names already under parent.
+ eastl::vector<Q3DStudio::CString> existingNames;
+ for (QT3DSI32 idx = 0, end = m_AssetGraph.GetChildCount(inParent); idx < end; ++idx) {
+ existingNames.push_back(GetName(m_AssetGraph.GetChild(inParent, idx)));
+ }
+ TInstanceHandle newItem = ParseSVGItem(inParent, inSlide, existingNames);
+ if (!retval.Valid())
+ retval = newItem;
+ }
+ if (retval.Valid()) {
+ FinalizeAddOrDrop(retval, inParent, inDropType, CPt(), inStartTime == -1, false);
+ }
+
+ return retval;
+ }
+
+ TInstanceHandle ImportFile(DocumentEditorFileType::Enum inFileType,
+ const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ const Q3DStudio::CString &inImportFileExtension,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) override
+ {
+ std::shared_ptr<IImportFailedHandler> theHandler(m_Doc.GetImportFailedHandler());
+ switch (inFileType) {
+ case DocumentEditorFileType::DAE:
+ return ImportDAE(inFullPathToDocument, inParent, inSlide, inImportFileExtension,
+ inDropType, inPosition, inStartTime);
+ case DocumentEditorFileType::Image:
+ return AutomapImage(inFullPathToDocument, inParent, inSlide, inDropType, inPosition,
+ inStartTime);
+ case DocumentEditorFileType::Mesh:
+ return LoadMesh(inFullPathToDocument, inParent, inSlide, inDropType, inPosition,
+ inStartTime);
+ case DocumentEditorFileType::Import:
+ return LoadImportFile(inFullPathToDocument, inParent, inSlide, inDropType, inPosition,
+ inStartTime);
+ case DocumentEditorFileType::Behavior:
+ return LoadBehavior(inFullPathToDocument, inParent, inSlide, inDropType, inStartTime);
+ case DocumentEditorFileType::Font:
+ return CreateText(inFullPathToDocument, inParent, inSlide, inDropType, inPosition,
+ inStartTime);
+ case DocumentEditorFileType::Effect:
+ return LoadEffect(inFullPathToDocument, inParent, inSlide, inDropType, inStartTime);
+ case DocumentEditorFileType::Material:
+ return LoadCustomMaterial(inFullPathToDocument, inParent, inSlide, inDropType,
+ inStartTime);
+ case DocumentEditorFileType::Path: {
+ Q3DStudio::CFilePath thePath(inFullPathToDocument);
+ if (thePath.GetExtension().CompareNoCase("path")) {
+ return LoadPathBuffer(inFullPathToDocument, inParent, inSlide, inDropType,
+ inStartTime);
+ } else
+ return LoadPath(inFullPathToDocument, inParent, inSlide, inDropType, inStartTime);
+ }
+ default: {
+ if (theHandler)
+ theHandler->DisplayImportFailed(inFullPathToDocument.toQString(),
+ QObject::tr("Unsupported Document Editor Type (at this time!)"),
+ false);
+ break;
+ }
+ }
+ return 0;
+ }
+
+ void DepthFirstAddImportChildren(TSlideHandle inSlide, TInstanceHandle inInstance,
+ TIdMultiMap &inMap, std::unordered_set<int> &ioAddedChildren)
+ {
+ TCharPtr theId = m_StringTable.RegisterStr(GetImportId(inInstance).c_str());
+ if (!IsTrivial(theId) && m_SlideSystem.GetAssociatedSlide(inInstance) == inSlide) {
+ pair<TIdMultiMap::iterator, bool> theResult =
+ inMap.insert(make_pair(theId, vector<pair<TSlideHandle, TInstanceHandle>>()));
+ insert_unique(theResult.first->second, make_pair(inSlide, inInstance));
+ ioAddedChildren.insert(inInstance);
+ }
+
+ for (long idx = 0, end = m_AssetGraph.GetChildCount(inInstance); idx < end; ++idx) {
+ TInstanceHandle theInstance = m_AssetGraph.GetChild(inInstance, idx);
+ DepthFirstAddImportChildren(inSlide, theInstance, inMap, ioAddedChildren);
+ }
+ }
+
+ // Precondition is that our source path to instance map
+ // has all of the source-path-to-instance hooks already looked up.
+ void DoRefreshImport(const CFilePath &inOldFile, const CFilePath &inNewFile)
+ {
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ vector<CFilePath> importFileList;
+
+ // Find which import files use this dae file.
+ for (TCharPtrToSlideInstanceMap::iterator theIter = m_SourcePathInstanceMap.begin(),
+ end = m_SourcePathInstanceMap.end();
+ theIter != end; ++theIter) {
+ CFilePath theSource(theIter->first);
+ if (theSource.GetExtension().Compare(L"import", CString::ENDOFSTRING, false)) {
+ CFilePath theFullPath = m_Doc.GetResolvedPathToDoc(theSource);
+ if (theFullPath.Exists() && theFullPath.IsFile()) {
+ if (std::find(importFileList.begin(), importFileList.end(),
+ theFullPath.GetPathWithoutIdentifier())
+ == importFileList.end()) {
+ ImportPtrOrError theImport = Import::Load(theFullPath);
+ if (theImport.m_Value) {
+ CFilePath theSrcFile = CFilePath::CombineBaseAndRelative(
+ CFilePath(theImport.m_Value->GetDestDir()),
+ CFilePath(theImport.m_Value->GetSrcFile()));
+ if (theSrcFile.Compare(inOldFile.c_str(), CString::ENDOFSTRING, false))
+ importFileList.push_back(theFullPath.GetPathWithoutIdentifier());
+
+ theImport.m_Value->Release();
+ }
+ }
+ }
+ }
+ }
+ TCharPtrToSlideInstanceMap theImportPaths;
+ GetImportPathToInstanceMap(theImportPaths);
+ std::unordered_set<int> theAddedInstances;
+
+ // OK, for each import file
+ // 1. Find each group in the system using that import file as its source path.
+ // 2. for each group we find, build a map of import id->item that we will use to
+ // communicate the import changes to the item.
+ // 4. Run the refresh process using a composer editor that runs off of our
+ // mappings
+ TIdMultiMap theGroupIdMap;
+ for (size_t importIdx = 0, end = importFileList.size(); importIdx < end; ++importIdx) {
+ theGroupIdMap.clear();
+ CFilePath theImportFilePath = importFileList[importIdx];
+ CFilePath theImportRelativePath = m_Doc.GetRelativePathToDoc(theImportFilePath);
+ TCharPtrToSlideInstanceMap::iterator theIter =
+ m_SourcePathInstanceMap.find(m_StringTable.RegisterStr(theImportRelativePath));
+ if (theIter == m_SourcePathInstanceMap.end())
+ continue;
+ // First pass just build the group id entries. This avoids us copying hashtables which
+ // may
+ // be quite expensive
+ for (TSlideInstanceList::iterator theSlideInst = theIter->second.begin(),
+ theSlideInstEnd = theIter->second.end();
+ theSlideInst != theSlideInstEnd; ++theSlideInst) {
+ TInstanceHandle theRoot = theSlideInst->second;
+ TSlideHandle theSlide = theSlideInst->first;
+
+ // For a depth first search of all children of this object *in this slide*,
+ // if they have an import id then add them to the map.
+ DepthFirstAddImportChildren(theSlide, theRoot, theGroupIdMap, theAddedInstances);
+ TIdMultiMap::iterator theGroupId =
+ theGroupIdMap
+ .insert(make_pair(m_StringTable.GetWideStr(GetImportId(theRoot)),
+ vector<pair<CUICDMSlideHandle, CUICDMInstanceHandle>>()))
+ .first;
+ insert_unique(theGroupId->second, make_pair(theSlide, theRoot));
+ theAddedInstances.insert(theRoot);
+ }
+ // Since some objects may be completely free standing, we need to go through *all*
+ // objects.
+ // Unfortunately the first revision of the system didn't put import paths on objects so
+ // we need both the above loop *and* to consider every object who's import path matches
+ // out import document's relative path.
+ theIter = theImportPaths.find(m_StringTable.RegisterStr(theImportRelativePath));
+ TSlideHandleList theAssociatedSlides;
+ if (theIter != theImportPaths.end()) {
+ vector<pair<CUICDMSlideHandle, CUICDMInstanceHandle>> &theInstances =
+ theIter->second;
+ for (size_t freeInstanceIdx = 0, end = theInstances.size(); freeInstanceIdx < end;
+ ++freeInstanceIdx) {
+ if (theAddedInstances.find(theInstances[freeInstanceIdx].second)
+ != theAddedInstances.end())
+ continue;
+ theAssociatedSlides.clear();
+ CUICDMInstanceHandle theInstance(theInstances[freeInstanceIdx].second);
+ GetAllAssociatedSlides(theInstance, theAssociatedSlides);
+ TIdMultiMap::iterator theInstanceId =
+ theGroupIdMap
+ .insert(
+ make_pair(m_StringTable.GetWideStr(GetImportId(theInstance)),
+ vector<pair<CUICDMSlideHandle, CUICDMInstanceHandle>>()))
+ .first;
+ for (size_t slideIdx = 0, slideEnd = theAssociatedSlides.size();
+ slideIdx < slideEnd; ++slideIdx)
+ insert_unique(theInstanceId->second,
+ make_pair(theAssociatedSlides[slideIdx], theInstance));
+ theAddedInstances.insert(theInstance);
+ }
+ }
+
+ //
+ // OK, we have distinct maps sorted on a per-slide basis for all trees of children
+ // of this asset. We now need to attempt to run the refresh algorithm.
+
+ UICIMP::ImportPtrOrError theImportPtr = UICIMP::Import::Load(theImportFilePath);
+ if (theImportPtr.m_Value == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ if (inNewFile.Exists() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ // Select correct translator according to file type
+ ITranslator *translator = nullptr;
+ STranslationLog *translationLog = nullptr;
+ Q3DStudio::CString newExtension(inNewFile.GetExtension());
+ Q3DStudio::CString oldExtension(inOldFile.GetExtension());
+ if (newExtension.Compare(CDialogs::GetWideDAEFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)
+ && oldExtension.Compare(CDialogs::GetWideDAEFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)) {
+ SColladaTranslator *colladaTranslator = new SColladaTranslator(inNewFile.toQString());
+ translationLog = &(colladaTranslator->m_TranslationLog);
+ translator = colladaTranslator;
+#ifdef QT_3DSTUDIO_FBX
+ } else if (newExtension.Compare(CDialogs::GetWideFbxFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)
+ && oldExtension.Compare(CDialogs::GetWideFbxFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)) {
+ SFbxTranslator *fbxTranslator = new SFbxTranslator(inNewFile.toQString());
+ translationLog = &(fbxTranslator->m_TranslationLog);
+ translator = fbxTranslator;
+#endif
+ } else {
+ STranslationLog emptyLog;
+ IDocumentEditor::DisplayImportErrors(inNewFile.toQString(),
+ ImportErrorCodes::TranslationToImportFailed,
+ m_Doc.GetImportFailedHandler(), emptyLog, true);
+ continue;
+ }
+
+ std::shared_ptr<IComposerEditor> theComposer(
+ IComposerEditorInterface::CreateEditorInterface(
+ *this, theGroupIdMap, m_Doc.GetDocumentDirectory(), theImportFilePath, 0,
+ m_StringTable, m_AssetGraph));
+
+ SImportResult theImportResult = CPerformImport::RefreshToComposer(
+ *translator, *theComposer, *theImportPtr.m_Value, theImportFilePath);
+
+ IDocumentEditor::DisplayImportErrors(inNewFile.toQString(), theImportResult.m_Error,
+ m_Doc.GetImportFailedHandler(),
+ *translationLog, false);
+ }
+ }
+
+ void RefreshImport(const CFilePath &inOldFile, const CFilePath &inNewFile) override
+ {
+ CDispatch &theDispatch(*m_Doc.GetCore()->GetDispatch());
+ theDispatch.FireOnProgressBegin(Q3DStudio::CString::fromQString(QObject::tr("Refreshing Import File")), inOldFile,
+ Q3DStudio::CString::fromQString(QObject::tr("Refreshing Import File")));
+ ScopedBoolean __ignoredDirs(m_IgnoreDirChange);
+ try {
+ m_SourcePathInstanceMap.clear();
+ GetSourcePathToInstanceMap(m_SourcePathInstanceMap, false);
+ DoRefreshImport(inOldFile, inNewFile);
+ } catch (...) {
+ }
+ theDispatch.FireOnProgressEnd();
+ }
+
+ void ExternalizePath(TInstanceHandle path) override
+ {
+ CFilePath thePathsDirectory(
+ CFilePath::CombineBaseAndRelative(m_Doc.GetDocumentDirectory(), L"paths"));
+ thePathsDirectory.CreateDir(true);
+ Q3DStudio::CString theName = GetName(path);
+ CFilePath theTargetFileName(CFilePath::CombineBaseAndRelative(thePathsDirectory, theName));
+ theTargetFileName.append(".path");
+ if (theTargetFileName.Exists()) {
+ CFilePath tempPath(theTargetFileName.substr(0, theTargetFileName.size() - 5));
+ QT3DSU32 index = 1;
+ do {
+ wchar_t buffer[64];
+ swprintf(buffer, 64, L"%d", index);
+ tempPath.append(L"_");
+ tempPath.append(buffer);
+ ++index;
+ } while (tempPath.Exists());
+ theTargetFileName = tempPath;
+ theTargetFileName.append(".path");
+ }
+ NVScopedRefCounted<IPathBufferBuilder> theBuilder(
+ IPathBufferBuilder::CreateBuilder(*this->m_Foundation.m_Foundation));
+
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ TPropertyHandle positionProp(theDefinitions.m_PathAnchorPoint.m_Position.m_Property);
+ TPropertyHandle angleProp(theDefinitions.m_PathAnchorPoint.m_IncomingAngle.m_Property);
+ TPropertyHandle incomingdistanceProp(
+ theDefinitions.m_PathAnchorPoint.m_IncomingDistance.m_Property);
+ TPropertyHandle outgoingdistanceProp(
+ theDefinitions.m_PathAnchorPoint.m_OutgoingDistance.m_Property);
+ TPropertyHandle closedProp(theDefinitions.m_SubPath.m_Closed.m_Property);
+
+ eastl::vector<TInstanceHandle> theSubPathChildren;
+
+ for (QT3DSI32 pathChildIdx = 0, pathChildEnd = m_AssetGraph.GetChildCount(path);
+ pathChildIdx < pathChildEnd; ++pathChildIdx) {
+ TInstanceHandle pathChild(m_AssetGraph.GetChild(path, pathChildIdx));
+ if (GetObjectTypeName(pathChild) == L"SubPath") {
+ theSubPathChildren.push_back(pathChild);
+ bool isClosed = GetTypedInstancePropertyValue<bool>(pathChild, closedProp);
+ TInstanceHandle theLastAnchor;
+ for (QT3DSI32 subPathChildIdx = 0,
+ subPathChildEnd = m_AssetGraph.GetChildCount(pathChild);
+ subPathChildIdx < subPathChildEnd; ++subPathChildIdx) {
+ TInstanceHandle theAnchor(m_AssetGraph.GetChild(pathChild, subPathChildIdx));
+ QT3DSVec2 position =
+ ToFnd(GetTypedInstancePropertyValue<SFloat2>(theAnchor, positionProp));
+ if (subPathChildIdx == 0)
+ theBuilder->MoveTo(position);
+ else {
+ QT3DSVec2 prevPos = ToFnd(
+ GetTypedInstancePropertyValue<SFloat2>(theLastAnchor, positionProp));
+ QT3DSF32 prevAngle =
+ GetTypedInstancePropertyValue<float>(theLastAnchor, angleProp) + 180.0f;
+ QT3DSF32 prevDistance = GetTypedInstancePropertyValue<float>(
+ theLastAnchor, outgoingdistanceProp);
+ QT3DSVec2 c1 = IPathManager::GetControlPointFromAngleDistance(
+ prevPos, prevAngle, prevDistance);
+
+ QT3DSF32 angle = GetTypedInstancePropertyValue<float>(theAnchor, angleProp);
+ QT3DSF32 distance =
+ GetTypedInstancePropertyValue<float>(theAnchor, incomingdistanceProp);
+ QT3DSVec2 c2 = IPathManager::GetControlPointFromAngleDistance(position, angle,
+ distance);
+ theBuilder->CubicCurveTo(c1, c2, position);
+ }
+ theLastAnchor = theAnchor;
+ }
+ if (isClosed)
+ theBuilder->Close();
+ }
+ }
+ SPathBuffer theBuffer = theBuilder->GetPathBuffer();
+ CFileSeekableIOStream theWriter(theTargetFileName, FileWriteFlags());
+ theBuffer.Save(theWriter);
+
+ for (QT3DSU32 idx = 0, end = theSubPathChildren.size(); idx < end; ++idx)
+ DeleteInstance(theSubPathChildren[idx]);
+
+ CFilePath relativeFileName(
+ CFilePath::GetRelativePathFromBase(m_Doc.GetDocumentDirectory(), theTargetFileName));
+ SetInstancePropertyValue(path, theDefinitions.m_Asset.m_SourcePath,
+ TDataStrPtr(new CDataStr(relativeFileName.c_str())));
+ }
+ static SFloat2 NextDataItem(NVConstDataRef<QT3DSF32> inData, QT3DSU32 &inDataIdx)
+ {
+ SFloat2 retval(inData[inDataIdx], inData[inDataIdx + 1]);
+ inDataIdx += 2;
+ return retval;
+ }
+
+ static QT3DSF32 ToMinimalAngle(QT3DSF32 inAngle)
+ {
+ while (inAngle > 360.0f)
+ inAngle -= 360.0f;
+ while (inAngle < 0.0f)
+ inAngle += 360.0f;
+ return inAngle;
+ }
+
+ void InternalizePath(TInstanceHandle path) override
+ {
+ Option<TDataStrPtr> thePathOpt =
+ GetTypedInstancePropertyValue<TDataStrPtr>(path, m_Bridge.GetSourcePathProperty());
+ if (thePathOpt.hasValue() == false || !(*thePathOpt))
+ return;
+ CFilePath thePathToPathFile = CFilePath::CombineBaseAndRelative(
+ m_Doc.GetDocumentDirectory(), (*thePathOpt)->GetData());
+ CFileSeekableIOStream theReader(thePathToPathFile, FileReadFlags());
+ if (theReader.IsOpen() == false)
+ return;
+ UICIMP::SPathBuffer *theLoadedBuffer =
+ UICIMP::SPathBuffer::Load(theReader, *m_Foundation.m_Foundation);
+ if (theLoadedBuffer == NULL)
+ return;
+
+ SetInstancePropertyValue(path, m_Bridge.GetSourcePathProperty(),
+ TDataStrPtr(new CDataStr()), false);
+
+ // Get rid of any existing sub path children. There shouldn't be any but who knows.
+ eastl::vector<TInstanceHandle> theSubPathChildren;
+
+ for (QT3DSI32 pathChildIdx = 0, pathChildEnd = m_AssetGraph.GetChildCount(path);
+ pathChildIdx < pathChildEnd; ++pathChildIdx) {
+ TInstanceHandle pathChild(m_AssetGraph.GetChild(path, pathChildIdx));
+ if (GetObjectTypeName(pathChild) == L"SubPath")
+ theSubPathChildren.push_back(pathChild);
+ }
+
+ for (QT3DSU32 idx = 0, end = theSubPathChildren.size(); idx < end; ++idx)
+ DeleteInstance(theSubPathChildren[idx]);
+
+ QT3DSU32 dataIdx = 0;
+
+ TInstanceHandle theCurrentSubPath;
+ TInstanceHandle theCurrentAnchorPoint;
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+ TPropertyHandle positionProp(theDefinitions.m_PathAnchorPoint.m_Position.m_Property);
+ TPropertyHandle angleProp(theDefinitions.m_PathAnchorPoint.m_IncomingAngle.m_Property);
+ TPropertyHandle incomingdistanceProp(
+ theDefinitions.m_PathAnchorPoint.m_IncomingDistance.m_Property);
+ TPropertyHandle outgoingdistanceProp(
+ theDefinitions.m_PathAnchorPoint.m_OutgoingDistance.m_Property);
+ TPropertyHandle closedProp(theDefinitions.m_SubPath.m_Closed.m_Property);
+ UICDM::ISlideCore &theSlideCore(
+ *m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetTransactionlessSlideCore());
+ TSlideHandle theCurrentSlide = GetAssociatedSlide(path);
+ QT3DSU32 subPathIndex = 0;
+ wchar_t theNameBuffer[256];
+ QT3DSVec2 theCurrentPosition;
+
+ for (QT3DSU32 idx = 0, end = theLoadedBuffer->m_Commands.size(); idx < end; ++idx) {
+ switch (theLoadedBuffer->m_Commands[idx]) {
+ case UICIMP::PathCommand::MoveTo:
+ theCurrentSubPath = CreateSceneGraphInstance(UICDM::ComposerObjectTypes::SubPath,
+ path, theCurrentSlide);
+ if (subPathIndex)
+ swprintf(theNameBuffer, 256, L"SubPath_%d", subPathIndex);
+ else
+ swprintf(theNameBuffer, 256, L"SubPath");
+ SetName(theCurrentSubPath, theNameBuffer);
+ theCurrentAnchorPoint =
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::PathAnchorPoint,
+ theCurrentSubPath, theCurrentSlide);
+ SetName(theCurrentAnchorPoint, L"PathAnchorPoint");
+ theCurrentPosition = ToFnd(NextDataItem(theLoadedBuffer->m_Data, dataIdx));
+ theSlideCore.ForceSetInstancePropertyValue(theCurrentSlide, theCurrentAnchorPoint,
+ positionProp,
+ ToUICDM(theCurrentPosition));
+ ++subPathIndex;
+ break;
+ case UICIMP::PathCommand::CubicCurveTo: {
+ QT3DSVec2 c1 = ToFnd(NextDataItem(theLoadedBuffer->m_Data, dataIdx));
+ QT3DSVec2 c2 = ToFnd(NextDataItem(theLoadedBuffer->m_Data, dataIdx));
+ QT3DSVec2 p2 = ToFnd(NextDataItem(theLoadedBuffer->m_Data, dataIdx));
+ QT3DSVec2 outgoing =
+ IPathManager::GetAngleDistanceFromControlPoint(theCurrentPosition, c1);
+ outgoing.x += 180.0f;
+ outgoing.x = ToMinimalAngle(outgoing.x);
+ QT3DSVec2 incoming = IPathManager::GetAngleDistanceFromControlPoint(p2, c2);
+ incoming.x = ToMinimalAngle(incoming.x);
+ theSlideCore.ForceSetInstancePropertyValue(theCurrentSlide, theCurrentAnchorPoint,
+ outgoingdistanceProp, outgoing.y);
+ if (fabs(outgoing.y) > .01f) // if the control point is not on the anchor point.
+ theSlideCore.ForceSetInstancePropertyValue(
+ theCurrentSlide, theCurrentAnchorPoint, angleProp, outgoing.x);
+ theCurrentPosition = p2;
+ theCurrentAnchorPoint =
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::PathAnchorPoint,
+ theCurrentSubPath, theCurrentSlide);
+ SetName(theCurrentAnchorPoint, L"PathAnchorPoint");
+ theSlideCore.ForceSetInstancePropertyValue(theCurrentSlide, theCurrentAnchorPoint,
+ positionProp,
+ ToUICDM(theCurrentPosition));
+ theSlideCore.ForceSetInstancePropertyValue(theCurrentSlide, theCurrentAnchorPoint,
+ incomingdistanceProp, incoming.y);
+ if (fabs(incoming.y) > .01f)
+ theSlideCore.ForceSetInstancePropertyValue(
+ theCurrentSlide, theCurrentAnchorPoint, angleProp, incoming.x);
+ } break;
+ case UICIMP::PathCommand::Close:
+ theSlideCore.ForceSetInstancePropertyValue(theCurrentSlide, theCurrentSubPath,
+ closedProp, true);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ theLoadedBuffer->Free(m_Foundation.m_Foundation->getAllocator());
+ }
+
+ void ReplaceTextFontNameWithTextFileStem(uic::render::ITextRenderer &inRenderer) override
+ {
+ TInstanceHandleList theTextInstances;
+ m_DataCore.GetInstancesDerivedFrom(theTextInstances, m_Bridge.GetText().m_Instance);
+ TSlideHandleList theChildSlides;
+ for (size_t idx = 0, end = theTextInstances.size(); idx < end; ++idx) {
+ SValue theValue;
+ UICDM::CUICDMInstanceHandle theTextHandle(theTextInstances[idx]);
+ if (m_DataCore.GetInstancePropertyValue(theTextHandle, m_Bridge.GetText().m_Font,
+ theValue)) {
+ UICDM::TDataStrPtr theDataStr(UICDM::get<UICDM::TDataStrPtr>(theValue));
+ if (theDataStr && theDataStr->GetLength()) {
+
+ Option<CRegisteredString> theNewValueOpt = inRenderer.GetFontNameForFont(
+ m_StringTable.GetNarrowStr(theDataStr->GetData()));
+ if (theNewValueOpt.hasValue()) {
+ CRegisteredString theNewValue(*theNewValueOpt);
+ const wchar_t *theWideValue = m_StringTable.GetWideStr(theNewValue);
+ if (wcscmp(theWideValue, theDataStr->GetData()) != 0)
+ m_DataCore.SetInstancePropertyValue(
+ theTextHandle, m_Bridge.GetText().m_Font,
+ std::make_shared<CDataStr>(theWideValue));
+ }
+ }
+ }
+ UICDM::CUICDMSlideHandle theAssociatedSlide = GetAssociatedSlide(theTextHandle);
+ if (theAssociatedSlide.Valid()) {
+ theChildSlides.clear();
+ m_SlideCore.GetChildSlides(theAssociatedSlide, theChildSlides);
+ theChildSlides.insert(theChildSlides.begin(), theAssociatedSlide);
+ for (size_t theSlideIdx = 0, theSlideEnd = theChildSlides.size();
+ theSlideIdx < theSlideEnd; ++theSlideIdx) {
+ SValue theSlideValue;
+ if (m_SlideCore.GetSpecificInstancePropertyValue(
+ theChildSlides[theSlideIdx], theTextHandle, m_Bridge.GetText().m_Font,
+ theSlideValue)) {
+ UICDM::TDataStrPtr theDataStr(
+ UICDM::get<UICDM::TDataStrPtr>(theSlideValue));
+ if (theDataStr && theDataStr->GetLength()) {
+ Option<CRegisteredString> theNewValueOpt =
+ inRenderer.GetFontNameForFont(
+ m_StringTable.GetNarrowStr(theDataStr->GetData()));
+ if (theNewValueOpt.hasValue()) {
+ CRegisteredString theNewValue(*theNewValueOpt);
+ const wchar_t *theWideValue = m_StringTable.GetWideStr(theNewValue);
+ m_SlideCore.ForceSetInstancePropertyValue(
+ theChildSlides[theSlideIdx], theTextHandle,
+ m_Bridge.GetText().m_Font,
+ std::make_shared<CDataStr>(theWideValue));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void BuildDAEMap(const TFileModificationList &inList)
+ {
+ for (size_t fileIdx = 0, fileEnd = inList.size(); fileIdx < fileEnd; ++fileIdx) {
+ const SFileModificationRecord &theRecord(inList[fileIdx]);
+ CString theExtension = theRecord.m_File.GetExtension();
+ bool isImport = theExtension.Compare(L"import", CString::ENDOFSTRING, false);
+ CFilePath theRelativePath(m_Doc.GetRelativePathToDoc(theRecord.m_File));
+
+ if (theRecord.m_ModificationType == FileModificationType::InfoChanged
+ || theRecord.m_ModificationType == FileModificationType::Destroyed) {
+ if (isImport)
+ m_ImportFileToDAEMap.erase(theRelativePath);
+ continue;
+ }
+ if (isImport) {
+ UICIMP::ImportPtrOrError theImportPtr = UICIMP::Import::Load(theRecord.m_File);
+ if (theImportPtr.m_Value) {
+ CFilePath theDestDir = theImportPtr.m_Value->GetDestDir();
+ CFilePath theSrcFile = theImportPtr.m_Value->GetSrcFile();
+ CFilePath theFullSrcPath =
+ CFilePath::CombineBaseAndRelative(theDestDir, theSrcFile);
+ TCharPtr theDAERelativePath =
+ m_StringTable.RegisterStr(m_Doc.GetRelativePathToDoc(theFullSrcPath));
+ pair<unordered_map<TCharPtr, TCharPtr>::iterator, bool> theInsertResult =
+ m_ImportFileToDAEMap.insert(
+ make_pair(m_StringTable.RegisterStr(theRelativePath.c_str()),
+ theDAERelativePath));
+ theImportPtr.m_Value->Release();
+ if (theInsertResult.second == false)
+ theInsertResult.first->second = theDAERelativePath;
+ }
+ }
+ }
+ }
+
+ static const char *ModificationTypeToString(FileModificationType::Enum inType)
+ {
+ switch (inType) {
+ case FileModificationType::Created:
+ return "Created";
+ case FileModificationType::Destroyed:
+ return "Destroyed";
+ case FileModificationType::InfoChanged:
+ return "InfoChanged";
+ case FileModificationType::Modified:
+ return "Modified";
+ case FileModificationType::NoChange:
+ return "NoChange";
+ default:
+ return "Unknown";
+ }
+ }
+
+ void OnProjectDirChanged(const TFileModificationList &inList)
+ {
+ if (m_IgnoreDirChange == true) {
+ BuildDAEMap(inList);
+ return;
+ }
+ CDispatch &theDispatch(*m_Doc.GetCore()->GetDispatch());
+ bool hasProgressFired = false;
+ bool hasDispatchNotificationScope = false;
+ bool requestRender = false;
+
+ if (inList.size() == 1
+ && m_Doc.GetDocumentPath().GetName() == inList[0].m_File.GetFileName()
+ && inList[0].m_ModificationType == FileModificationType::Modified) {
+ if (!m_Doc.GetCore()->HasJustSaved()) {
+ CDispatch &theDispatch(*m_Doc.GetCore()->GetDispatch());
+ theDispatch.FireOnPresentationModifiedExternally();
+ return;
+ }
+ m_Doc.GetCore()->SetJustSaved(false);
+ }
+
+#define ENSURE_PROGRESS \
+ if (!hasProgressFired) { \
+ theDispatch.FireOnProgressBegin(Q3DStudio::CString::fromQString(QObject::tr("Updating project")), L"", L""); \
+ hasProgressFired = true; \
+ }
+
+ m_SourcePathInstanceMap.clear();
+ GetSourcePathToInstanceMap(m_SourcePathInstanceMap);
+ TInstanceHandleList theParents;
+ SComposerObjectDefinitions &theDefinitions(m_Bridge.GetObjectDefinitions());
+
+ for (size_t fileIdx = 0, fileEnd = inList.size(); fileIdx < fileEnd; ++fileIdx) {
+ const SFileModificationRecord &theRecord(inList[fileIdx]);
+
+ CString theExtension = theRecord.m_File.GetExtension();
+ bool isImport = theExtension.Compare(L"import", CString::ENDOFSTRING, false);
+ CFilePath theRelativePath(m_Doc.GetRelativePathToDoc(theRecord.m_File));
+ const wchar_t *theString(
+ m_DataCore.GetStringTable().RegisterStr(theRelativePath.c_str()));
+
+ if ((theExtension.CompareNoCase(L"ttf")
+ || theExtension.CompareNoCase(L"otf")) // should use CDialogs::IsFontFileExtension
+ && m_Doc.GetSceneGraph() && m_Doc.GetSceneGraph()->GetTextRenderer()) {
+ m_Doc.GetSceneGraph()->GetTextRenderer()->ReloadFonts();
+ CFilePath thePath = m_Doc.GetDocumentDirectory();
+ CFilePath theFontCache = CFilePath::CombineBaseAndRelative(thePath, L"fontcache");
+ theFontCache.DeleteThisDirectory(true);
+ }
+
+ if (theRecord.m_ModificationType == FileModificationType::InfoChanged
+ || theRecord.m_ModificationType == FileModificationType::Destroyed) {
+ if (isImport)
+ m_ImportFileToDAEMap.erase(theRelativePath);
+ continue;
+ }
+
+ if (theExtension.CompareNoCase(L"uia")) {
+ if (m_Doc.GetDocumentUIAFile() == theRecord.m_File.toQString()) {
+ QVector<SubPresentationRecord> subpresentations;
+ QVector<QString> subIds;
+
+ m_Doc.LoadUIASubpresentations(m_Doc.GetDocumentUIAFile(),
+ subpresentations);
+
+ for (SubPresentationRecord &r : subpresentations)
+ subIds.push_back(r.m_id);
+
+ bool renderableReset = false;
+ // find all renderables from layers and textures and check they are
+ // still using correct values
+ TInstanceHandleList renderableInstances;
+ m_DataCore.GetInstancesDerivedFrom(renderableInstances,
+ theDefinitions.m_Layer.m_Instance);
+ m_DataCore.GetInstancesDerivedFrom(renderableInstances,
+ theDefinitions.m_Image.m_Instance);
+ for (int rid = 0; rid < renderableInstances.size(); ++rid) {
+ TPropertyHandleList theProperties;
+ CUICDMInstanceHandle theInstance = renderableInstances[rid];
+ m_PropertySystem.GetAggregateInstanceProperties(theInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0;
+ thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ UICDM::AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ m_PropertySystem.GetAdditionalMetaDataType(theInstance,
+ theProperty);
+ if (theAdditionalMetaDataType
+ == AdditionalMetaDataType::Renderable) {
+ std::vector<SValue> theValueList;
+ m_Bridge.GetValueListFromAllSlides(theInstance, theProperty,
+ theValueList);
+ for (SValue &val : theValueList) {
+ QString valString = val.toQVariant().toString();
+ if (valString.isEmpty() == false
+ && subIds.contains(valString) == false) {
+ SetInstancePropertyValueAsRenderable(theInstance,
+ theProperty,
+ Q3DStudio::CString());
+ m_StudioSystem.GetFullSystem()->GetSignalSender()
+ ->SendInstancePropertyValue(theInstance,
+ theProperty);
+ renderableReset = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (renderableReset) {
+ // Notify user that the values were reset
+ // somehow
+ }
+ }
+ }
+
+ QDir modifiedPath = QDir::cleanPath(QString::fromWCharArray(theString));
+ TCharPtrToSlideInstanceMap::iterator theFind = m_SourcePathInstanceMap.end();
+ for (TCharPtrToSlideInstanceMap::iterator it = m_SourcePathInstanceMap.begin();
+ it != m_SourcePathInstanceMap.end(); ++it) {
+ QDir sourcePath = QDir::cleanPath(QString::fromWCharArray(it->first));
+ if (sourcePath == modifiedPath) {
+ theFind = it;
+ break;
+ }
+ }
+
+ if (theFind == m_SourcePathInstanceMap.end())
+ continue;
+
+ const TSlideInstanceList &theInstances(theFind->second);
+ if (theRecord.m_ModificationType != FileModificationType::Created) {
+ requestRender = true;
+ m_Doc.GetBufferCache().InvalidateBuffer(theRelativePath);
+ }
+
+ qCInfo(qt3ds::TRACE_INFO) << "Change detected: " << theRelativePath.GetCharStar() << " "
+ << ModificationTypeToString(theRecord.m_ModificationType);
+
+ if (isImport) {
+ UICIMP::ImportPtrOrError theImportPtr = UICIMP::Import::Load(theRecord.m_File);
+ if (theImportPtr.m_Value) {
+ ENSURE_PROGRESS;
+ CFilePath theDestDir = theImportPtr.m_Value->GetDestDir();
+ CFilePath theSrcFile = theImportPtr.m_Value->GetSrcFile();
+ CFilePath theFullSrcPath =
+ CFilePath::CombineBaseAndRelative(theDestDir, theSrcFile);
+ TCharPtr theDAERelativePath =
+ m_StringTable.RegisterStr(m_Doc.GetRelativePathToDoc(theFullSrcPath));
+ pair<unordered_map<TCharPtr, TCharPtr>::iterator, bool> theInsertResult =
+ m_ImportFileToDAEMap.insert(
+ make_pair(m_StringTable.RegisterStr(theRelativePath.c_str()),
+ theDAERelativePath));
+ theImportPtr.m_Value->Release();
+ if (theInsertResult.second == false)
+ theInsertResult.first->second = theDAERelativePath;
+ }
+ } else if ((theExtension.Compare(L"lua", CString::ENDOFSTRING, false) ||
+ theExtension.Compare(L"qml", CString::ENDOFSTRING, false))
+ && theRecord.m_ModificationType != FileModificationType::Created
+ && theInstances.empty() == false) {
+ bool isLua = theExtension.Compare(L"lua", CString::ENDOFSTRING, false);
+ // First, refresh the parent behavior.
+ if (!hasDispatchNotificationScope) {
+ theDispatch.FireBeginDataModelNotifications();
+ hasDispatchNotificationScope = true;
+ }
+
+ for (size_t instIdx = 0, instEnd = theInstances.size(); instIdx < instEnd;
+ ++instIdx) {
+ ENSURE_PROGRESS;
+ CUICDMInstanceHandle theBehavior = theInstances[instIdx].second;
+ theParents.clear();
+ m_DataCore.GetInstanceParents(theBehavior, theParents);
+
+ if (theParents.empty()
+ || theParents[0] != theDefinitions.m_Behavior.m_Instance) {
+ // This indicates we are dealing with a scene instance.
+ // In this case we want to clear any intermediate cached
+ // values from the instance itself so that new defaults
+ // in the file will show through to the UI.
+ m_DataCore.RemoveCachedValues(theBehavior);
+ } else {
+ std::shared_ptr<IDOMReader> theReaderPtr;
+ if (isLua) {
+ theReaderPtr = ParseLuaFile(theRecord.m_File,
+ m_DataCore.GetStringTablePtr(),
+ m_Doc.GetImportFailedHandler(),
+ *m_InputStreamFactory);
+ } else {
+ theReaderPtr = ParseScriptFile(theRecord.m_File,
+ m_DataCore.GetStringTablePtr(),
+ m_Doc.GetImportFailedHandler(),
+ *m_InputStreamFactory);
+ }
+ if (!theReaderPtr) {
+ // then effectively no change...
+ QT3DS_ASSERT(false);
+ } else {
+ std::vector<SMetaDataLoadWarning> theWarnings;
+ m_MetaData.LoadInstance(*theReaderPtr, theBehavior,
+ theRelativePath.GetFileStem().c_str(),
+ theWarnings);
+ if (isLua) {
+ CLuaDynamicInstanceLoader inSpecificInstance(*this);
+ QString theLoadError =
+ inSpecificInstance.LoadInstanceData(theRecord.m_File);
+ DisplayLoadWarnings(theRecord.m_File.toQString(),
+ theWarnings, theLoadError);
+ } else {
+ CScriptDynamicInstanceLoader inSpecificInstance(*this);
+ QString theLoadError =
+ inSpecificInstance.LoadInstanceData(theRecord.m_File);
+ DisplayLoadWarnings(theRecord.m_File.toQString(),
+ theWarnings, theLoadError);
+ }
+ }
+ }
+ }
+ } else if (theExtension.Compare(L"effect", CString::ENDOFSTRING, false)
+ && theRecord.m_ModificationType != FileModificationType::Created
+ && theInstances.empty() == false) {
+ CString theNameStr = GetName(theInstances[0].second);
+ std::vector<SMetaDataLoadWarning> theWarnings;
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream(
+ m_InputStreamFactory->GetStreamForFile(
+ QString::fromWCharArray(theRecord.m_File)));
+ if (theStream) {
+ m_MetaData.LoadEffectInstance(m_StringTable.GetNarrowStr(theRelativePath),
+ theInstances[0].second,
+ TCharStr(theNameStr),
+ theWarnings, *theStream);
+ }
+
+ for (size_t i = 0; i < theInstances.size(); ++i) {
+ theDispatch.FireReloadEffectInstance(theInstances[i].second);
+ theDispatch.FireImmediateRefreshInstance(theInstances[i].second);
+ }
+ }
+ // There used to be an extension here for meshes
+ // but that causes the product to delete materials in some cases which loses work.
+ // so that experiment failed and we will just have to let the users manually updated
+ // their
+ // meshes through the dropdown if they need them updated.
+ }
+ if (hasProgressFired)
+ theDispatch.FireOnProgressEnd();
+ if (requestRender && m_Doc.GetSceneGraph())
+ m_Doc.GetSceneGraph()->RequestRender();
+ if (hasDispatchNotificationScope)
+ theDispatch.FireEndDataModelNotifications();
+ }
+};
+}
+
+void IDocumentEditor::DisplayImportErrors(const QString &inImportSource,
+ ImportErrorCodes::Enum inImportError,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ STranslationLog &inTranslationLog, bool inForceError)
+{
+ bool isError = false;
+ Q3DStudio::CString resultDialogStr;
+ std::shared_ptr<IImportFailedHandler> theHandler(inHandler);
+ if (inImportError == ImportErrorCodes::TranslationToImportFailed || inForceError) {
+ isError = true;
+ resultDialogStr = "Failed to import file";
+ }
+
+ for (size_t idx = 0; idx < inTranslationLog.m_Warnings.size(); ++idx) {
+ const std::pair<ESceneGraphWarningCode, Q3DStudio::CString> &warning(
+ inTranslationLog.m_Warnings[idx]);
+ const wchar_t *formatStr = L"Unrecognized warning";
+ switch (warning.first) {
+ case ESceneGraphWarningCode_OnlySupportTriangles:
+ formatStr = L"Model %ls contains geometric elements other than triangles";
+ break;
+ case ESceneGraphWarningCode_TrianglesDuplicateSemantic:
+ formatStr = L"Triangle contains duplicate semantics, ex: 1 triangle has multiple "
+ L"TEXCOORD (multiple UV maps)";
+ break;
+ case ESceneGraphWarningCode_MissingSourceFile:
+ formatStr = L"Couldn't find a source image file %ls";
+ break;
+ case ESceneGraphWarningCode_LockedDestFile:
+ formatStr = L"An image or mesh file %ls is not writeable";
+ break;
+ case ESceneGraphWarningCode_VertexBufferTooLarge:
+ formatStr = L"A single mesh exceeds the maximum vertex count of 65535";
+ break;
+ }
+ wchar_t buf[1024] = { 0 };
+ swprintf(buf, 1024, formatStr, warning.second.c_str());
+ if (resultDialogStr.size())
+ resultDialogStr.append('\n');
+ resultDialogStr.append(buf);
+ }
+ if (resultDialogStr.size()) {
+ if (theHandler)
+ theHandler->DisplayImportFailed(inImportSource, resultDialogStr.toQString(), !isError);
+ }
+}
+
+CUICDMPropertyHandle *
+IDocumentEditor::GetAlwaysUnlinkedProperties(UICDM::SComposerObjectDefinitions &inDefs)
+{
+ SComposerObjectDefinitions &theDefs(inDefs);
+ static CUICDMPropertyHandle theProperties[5];
+ theProperties[0] = theDefs.m_Asset.m_StartTime;
+ theProperties[1] = theDefs.m_Asset.m_EndTime;
+ theProperties[2] = theDefs.m_Asset.m_Eyeball;
+ theProperties[3] = theDefs.m_Asset.m_Shy;
+ theProperties[4] = CUICDMPropertyHandle();
+ return theProperties;
+}
+
+void IDocumentEditor::UnlinkAlwaysUnlinkedProperties(CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinitions &inDefs,
+ ISlideSystem &inSlideSystem)
+{
+ CUICDMPropertyHandle *theUnlinked(GetAlwaysUnlinkedProperties(inDefs));
+ for (CUICDMPropertyHandle *theHandle = theUnlinked; theHandle->Valid(); ++theHandle)
+ inSlideSystem.UnlinkProperty(inInstance, *theHandle);
+}
+
+CUICDMInstanceHandle IDocumentEditor::CreateSceneGraphInstance(
+ const wchar_t *inType, TInstanceHandle inParent, TSlideHandle inSlide,
+ UICDM::IDataCore &inDataCore, UICDM::ISlideSystem &inSlideSystem,
+ UICDM::SComposerObjectDefinitions &inObjectDefs, Q3DStudio::CGraph &inAssetGraph,
+ UICDM::IMetaData &inMetaData, TInstanceHandle inTargetId)
+{
+ return CreateSceneGraphInstance(inMetaData.GetCanonicalInstanceForType(inType), inParent,
+ inSlide, inDataCore, inSlideSystem, inObjectDefs, inAssetGraph,
+ inMetaData, inTargetId);
+}
+
+CUICDMInstanceHandle IDocumentEditor::CreateSceneGraphInstance(
+ CUICDMInstanceHandle inMaster, TInstanceHandle inParent, TSlideHandle inSlide,
+ UICDM::IDataCore &inDataCore, UICDM::ISlideSystem &inSlideSystem,
+ UICDM::SComposerObjectDefinitions &inObjectDefs, Q3DStudio::CGraph &inAssetGraph,
+ UICDM::IMetaData &inMetaData, TInstanceHandle inTargetId)
+{
+ Option<TCharStr> theTypeOpt = inMetaData.GetTypeForInstance(inMaster);
+ if (theTypeOpt.hasValue() == false)
+ return 0;
+
+ SComposerObjectDefinitions &theDefs(inObjectDefs);
+ TInstanceHandle retval = inDataCore.CreateInstance(inTargetId);
+ TInstanceHandle theDerivationParent(inMaster);
+ inDataCore.DeriveInstance(retval, theDerivationParent);
+
+ if (inParent.Valid())
+ inAssetGraph.AddChild(inParent, retval);
+ else
+ inAssetGraph.AddRoot(retval);
+
+ if (inSlide.Valid()) {
+ inSlideSystem.AssociateInstanceWithSlide(inSlide, retval);
+ UnlinkAlwaysUnlinkedProperties(retval, inObjectDefs, inSlideSystem);
+ }
+
+ Q3DStudio::CId theId;
+ if (ComposerObjectTypes::Convert(theTypeOpt->wide_str()) == UICDM::ComposerObjectTypes::Scene)
+ theId = SCENE_GUID;
+ else
+ theId.Generate();
+
+ TGUIDPacked thePackedGuid(theId);
+ SLong4 theLong4Id(thePackedGuid.Data1, thePackedGuid.Data2, thePackedGuid.Data3,
+ thePackedGuid.Data4);
+ inDataCore.SetInstancePropertyValue(retval, theDefs.m_Guided.m_GuidProp, theLong4Id);
+ return retval;
+}
+
+std::shared_ptr<IDOMReader>
+IDocumentEditor::ParseLuaFile(const CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory)
+{
+ using namespace LuaParser;
+ std::shared_ptr<UICDM::IStringTable> theStringTable(inStringTable);
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SImportXmlErrorHandler theXmlErrorHandler(inHandler, inFullPathToDocument);
+ std::shared_ptr<IDOMReader> theReaderPtr(
+ SLuaParser::ParseLuaFile(theFactory, inStringTable, inFullPathToDocument.GetCharStar(),
+ theXmlErrorHandler, inInputStreamFactory));
+
+ if (!theReaderPtr) {
+ QT3DS_ASSERT(false);
+ if (inHandler)
+ inHandler->DisplayImportFailed(inFullPathToDocument.toQString(),
+ QObject::tr("Failed to parse Lua data"),
+ false);
+ }
+ return theReaderPtr;
+}
+
+std::shared_ptr<IDOMReader>
+IDocumentEditor::ParseScriptFile(const CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory)
+{
+ using namespace ScriptParser;
+ std::shared_ptr<UICDM::IStringTable> theStringTable(inStringTable);
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SImportXmlErrorHandler theXmlErrorHandler(inHandler, inFullPathToDocument);
+ std::shared_ptr<IDOMReader> theReaderPtr(
+ SScriptParser::ParseScriptFile(theFactory, inStringTable,
+ inFullPathToDocument.GetCharStar(),
+ theXmlErrorHandler, inInputStreamFactory));
+
+ if (!theReaderPtr) {
+ QT3DS_ASSERT(false);
+ if (inHandler) {
+ inHandler->DisplayImportFailed(inFullPathToDocument.toQString(),
+ QObject::tr("Failed to parse script data"),
+ false);
+ }
+ }
+ return theReaderPtr;
+}
+
+std::shared_ptr<IDOMReader>
+IDocumentEditor::ParsePluginFile(const Q3DStudio::CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory)
+{
+ std::shared_ptr<UICDM::IStringTable> theStringTable(inStringTable);
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SImportXmlErrorHandler theXmlErrorHandler(inHandler, inFullPathToDocument);
+
+ std::shared_ptr<IDOMReader> theReaderPtr = CRenderPluginParser::ParseFile(
+ theFactory, theStringTable, theStringTable->GetNarrowStr(inFullPathToDocument),
+ theXmlErrorHandler, inInputStreamFactory);
+ if (!theReaderPtr) {
+ QT3DS_ASSERT(false);
+ if (inHandler)
+ inHandler->DisplayImportFailed(inFullPathToDocument.toQString(),
+ QObject::tr("Failed to parse Lua data"),
+ false);
+ }
+ CRenderPluginParser::NavigateToMetadata(theReaderPtr);
+ return theReaderPtr;
+}
+
+std::shared_ptr<IDOMReader>
+IDocumentEditor::ParseCustomMaterialFile(const Q3DStudio::CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory)
+{
+ std::shared_ptr<UICDM::IStringTable> theStringTable(inStringTable);
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SImportXmlErrorHandler theXmlErrorHandler(inHandler, inFullPathToDocument);
+
+ std::shared_ptr<IDOMReader> theReaderPtr = CRenderPluginParser::ParseFile(
+ theFactory, theStringTable, theStringTable->GetNarrowStr(inFullPathToDocument),
+ theXmlErrorHandler, inInputStreamFactory);
+ if (!theReaderPtr) {
+ QT3DS_ASSERT(false);
+ if (inHandler)
+ inHandler->DisplayImportFailed(inFullPathToDocument.toQString(),
+ QObject::tr("Failed to parse Lua data"),
+ false);
+ }
+ CCustomMaterialParser::NavigateToMetadata(theReaderPtr);
+ return theReaderPtr;
+}
+
+ScopedDocumentEditor::ScopedDocumentEditor(IDoc &inDoc, const Q3DStudio::CString &inCommandName,
+ const char *inFile, int inLine)
+ : m_Editor(inDoc.OpenTransaction(inCommandName, inFile, inLine))
+{
+}
+
+CUpdateableDocumentEditor::~CUpdateableDocumentEditor()
+{
+ if (HasEditor()) {
+ qCWarning(qt3ds::WARNING) << m_File << "(" << m_Line
+ << "): Document editor committed upon destruction";
+ CommitEditor();
+ }
+}
+
+IDocumentEditor &CUpdateableDocumentEditor::EnsureEditor(const wchar_t *inCommandName,
+ const char *inFile, int inLine)
+{
+ if (!HasEditor()) {
+ m_File = inFile;
+ m_Line = inLine;
+ }
+ return m_EditorIDocDoc.MaybeOpenTransaction(inCommandName, inFile, inLine);
+}
+
+bool CUpdateableDocumentEditor::HasEditor() const
+{
+ return m_EditorIDocDoc.IsTransactionOpened() && m_File != NULL;
+}
+
+void CUpdateableDocumentEditor::FireImmediateRefresh(UICDM::CUICDMInstanceHandle *inInstances,
+ long inInstanceCount)
+{
+ m_EditorIDocDoc.GetCore()->GetDispatch()->FireImmediateRefreshInstance(inInstances,
+ inInstanceCount);
+}
+
+void CUpdateableDocumentEditor::CommitEditor()
+{
+ if (HasEditor()) {
+ m_EditorIDocDoc.CloseTransaction();
+ m_File = NULL;
+ }
+}
+
+void CUpdateableDocumentEditor::RollbackEditor()
+{
+ if (HasEditor()) {
+ m_EditorIDocDoc.RollbackTransaction();
+ m_EditorIDocDoc.CloseTransaction();
+ m_File = NULL;
+ }
+}
+
+std::shared_ptr<IInternalDocumentEditor> IInternalDocumentEditor::CreateEditor(CDoc &doc)
+{
+ return std::shared_ptr<IInternalDocumentEditor>(new CDocEditor(doc));
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentEditorEnumerations.h b/src/Authoring/Client/Code/Core/Doc/DocumentEditorEnumerations.h
new file mode 100644
index 00000000..8985f608
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/DocumentEditorEnumerations.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef DOCUMENTEDITORENUMERATIONSH
+#define DOCUMENTEDITORENUMERATIONSH
+
+#include "qtAuthoring-config.h"
+
+namespace Q3DStudio {
+struct DocumentEditorFileType
+{
+ enum Enum {
+ Unknown = 0,
+ DAE,
+ Mesh,
+ Import,
+ Image,
+ Behavior,
+ FBX,
+ Font,
+ Effect,
+ Material,
+ Path,
+ Sound,
+ };
+};
+
+struct DocumentEditorInsertType
+{
+ enum Enum {
+ Unknown = 0,
+ LastChild,
+ PreviousSibling,
+ NextSibling,
+ };
+};
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/DynamicLua.cpp b/src/Authoring/Client/Code/Core/Doc/DynamicLua.cpp
new file mode 100644
index 00000000..d35467a8
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/DynamicLua.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "DynamicLua.h"
+#define _NOMINMAX
+#include "foundation/Qt3DSMath.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "WINDOWS/DynamicLibLoader.h"
+#include "EASTL/string.h"
+#include "foundation/Utils.h"
+
+using namespace Q3DStudio;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::intrinsics;
+
+namespace {
+struct lua_State;
+
+#define LUA_REGISTRYINDEX (-10000)
+#define LUA_ENVIRONINDEX (-10001)
+#define LUA_GLOBALSINDEX (-10002)
+#define lua_upvalueindex(i) (LUA_GLOBALSINDEX - (i))
+#define lua_tostring(L, i) lua_tolstring(L, (i), NULL)
+#define lua_setglobal(L, s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
+#define lua_getglobal(L, s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
+#define LUA_TNONE (-1)
+
+#define LUA_TNIL 0
+#define LUA_TBOOLEAN 1
+#define LUA_TLIGHTUSERDATA 2
+#define LUA_TNUMBER 3
+#define LUA_TSTRING 4
+#define LUA_TTABLE 5
+#define LUA_TFUNCTION 6
+#define LUA_TUSERDATA 7
+#define LUA_TTHREAD 8
+
+#define lua_isfunction(L, n) (lua_type(L, (n)) == LUA_TFUNCTION)
+#define lua_istable(L, n) (lua_type(L, (n)) == LUA_TTABLE)
+#define lua_isnumber(L, n) (lua_type(L, (n)) == LUA_TNUMBER)
+#define lua_islightuserdata(L, n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
+#define lua_isnil(L, n) (lua_type(L, (n)) == LUA_TNIL)
+#define lua_isboolean(L, n) (lua_type(L, (n)) == LUA_TBOOLEAN)
+#define lua_isthread(L, n) (lua_type(L, (n)) == LUA_TTHREAD)
+#define lua_isnone(L, n) (lua_type(L, (n)) == LUA_TNONE)
+#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
+#define lua_pop(L, n) lua_settop(L, -(n)-1)
+
+struct DynLua : public IDynamicLua
+{
+
+ typedef void *(*TAllocFn)(void *ud, void *ptr, size_t osize, size_t nsize);
+ typedef lua_State *(*TOpenFn)(TAllocFn, void *ud);
+ typedef void (*TCloseFn)(lua_State *st);
+ typedef int (*TIntLuaFn)(lua_State *st);
+ typedef void (*TVoidLuaIntFn)(lua_State *st, int arg);
+ typedef void (*TVoidLuaVoidPtrFn)(lua_State *L, void *p);
+ typedef void (*TVoidLuaIntCharPtrFn)(lua_State *L, int idx, const char *k);
+ typedef void (*TVoidLuaCharPtrFn)(lua_State *L, const char *k);
+ typedef int (*TIntLuaIntIntIntFn)(lua_State *L, int nargs, int nresults, int errfunc);
+ typedef const char *(*TCharPtrLuaIntSizeTFn)(lua_State *L, int idx, size_t *len);
+ typedef int (*TIntLuaCharPtrFn)(lua_State *L, const char *filename);
+ typedef int (*TIntLuaIntFn)(lua_State *L, int idx);
+ typedef float (*TFloatLuaIntFn)(lua_State *L, int idx);
+ typedef void (*TVoidLuaIntIntFn)(lua_State *L, int index, int n);
+ typedef void (*TVoidLuaFloatFn)(lua_State *L, float num);
+
+#define ITERATE_REQUIRED_LUA_FUNCTIONS \
+ HANDLE_LUA_FUNCTION(lua_newstate, TOpenFn) \
+ HANDLE_LUA_FUNCTION(lua_close, TCloseFn) \
+ HANDLE_LUA_FUNCTION(lua_gettop, TIntLuaFn) \
+ HANDLE_LUA_FUNCTION(lua_settop, TVoidLuaIntFn) \
+ HANDLE_LUA_FUNCTION(luaL_openlibs, TCloseFn) \
+ HANDLE_LUA_FUNCTION(lua_pushlightuserdata, TVoidLuaVoidPtrFn) \
+ HANDLE_LUA_FUNCTION(lua_setfield, TVoidLuaIntCharPtrFn) \
+ HANDLE_LUA_FUNCTION(lua_getfield, TVoidLuaIntCharPtrFn) \
+ HANDLE_LUA_FUNCTION(lua_pushstring, TVoidLuaCharPtrFn) \
+ HANDLE_LUA_FUNCTION(lua_pushnumber, TVoidLuaFloatFn) \
+ HANDLE_LUA_FUNCTION(lua_pushnil, TCloseFn) \
+ HANDLE_LUA_FUNCTION(lua_pcall, TIntLuaIntIntIntFn) \
+ HANDLE_LUA_FUNCTION(lua_tolstring, TCharPtrLuaIntSizeTFn) \
+ HANDLE_LUA_FUNCTION(luaL_loadfile, TIntLuaCharPtrFn) \
+ HANDLE_LUA_FUNCTION(lua_type, TIntLuaIntFn) \
+ HANDLE_LUA_FUNCTION(lua_next, TIntLuaIntFn) \
+ HANDLE_LUA_FUNCTION(lua_insert, TVoidLuaIntFn) \
+ HANDLE_LUA_FUNCTION(lua_tonumber, TFloatLuaIntFn) \
+ HANDLE_LUA_FUNCTION(lua_toboolean, TIntLuaIntFn) \
+ HANDLE_LUA_FUNCTION(lua_rawgeti, TVoidLuaIntIntFn) \
+ HANDLE_LUA_FUNCTION(lua_objlen, TIntLuaIntFn)
+
+#define HANDLE_LUA_FUNCTION(name, type) type name;
+
+ ITERATE_REQUIRED_LUA_FUNCTIONS
+
+#undef HANDLE_LUA_FUNCTION
+
+ NVFoundationBase &m_Foundation;
+ uic::render::CLoadedDynamicLibrary *m_LuaLibrary;
+ lua_State *m_LuaState;
+ eastl::string m_TempStr;
+
+ static void *LuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
+ {
+ DynLua &theLua = *reinterpret_cast<DynLua *>(ud);
+ NVAllocatorCallback &theAlloc = theLua.m_Foundation.getAllocator();
+ if (nsize == 0) {
+ if (ptr)
+ theAlloc.deallocate(ptr);
+ return NULL;
+ } else {
+ if (nsize < osize && ptr)
+ return ptr;
+
+ void *newMem = theAlloc.allocate(nsize, "lua_mem", __FILE__, __LINE__);
+ if (osize && ptr) {
+ size_t copyAmt = NVMin(osize, nsize);
+ memCopy(newMem, ptr, (QT3DSU32)copyAmt);
+ theAlloc.deallocate(ptr);
+ }
+ return newMem;
+ }
+ }
+
+ void *FindLuaFunction(const char *inName, NVFoundationBase &fnd)
+ {
+ void *retval = m_LuaLibrary->FindFunction(inName);
+ if (!retval)
+ qCCritical(INVALID_OPERATION, "Failed to find lua function %s", inName);
+ return retval;
+ }
+
+ DynLua(NVFoundationBase &fnd, const char8_t *pathToLuaDll)
+ : m_Foundation(fnd)
+ , m_LuaLibrary(uic::render::CLoadedDynamicLibrary::Create(pathToLuaDll, fnd))
+ , m_LuaState(NULL)
+ {
+ if (m_LuaLibrary) {
+ bool success = true;
+#define HANDLE_LUA_FUNCTION(name, type) \
+ name = reinterpret_cast<type>(FindLuaFunction(#name, fnd)); \
+ if (name == NULL) \
+ success = false;
+
+ ITERATE_REQUIRED_LUA_FUNCTIONS
+
+ #undef HANDLE_LUA_FUNCTION
+
+ if (success) {
+ m_LuaState = (*lua_newstate)(LuaAlloc, this);
+ luaL_openlibs(m_LuaState);
+ }
+ }
+ }
+
+ ~DynLua()
+ {
+ if (m_LuaState)
+ lua_close(m_LuaState);
+ m_LuaState = NULL;
+ if (m_LuaLibrary)
+ NVDelete(m_Foundation.getAllocator(), m_LuaLibrary);
+ m_LuaLibrary = NULL;
+ }
+
+ void AddLibraryPath(const char8_t *inPath, PathType inType) override
+ {
+ const char8_t *extName = inType == LuaModule ? "lua" : "dll";
+ const char8_t *fieldName = inType == LuaModule ? "path" : "cpath";
+ lua_getglobal(m_LuaState, "package");
+ lua_getfield(m_LuaState, -1,
+ fieldName); // get field "path"/"cpath" from table at top of stack (-1)
+ const char8_t *outOriginalPath =
+ lua_tostring(m_LuaState, -1); // grab path string from top of stack
+
+ eastl::string cur_path(outOriginalPath);
+ cur_path.append(";");
+ cur_path.append(inPath);
+ cur_path.append("/?.");
+ cur_path.append(extName);
+
+ lua_pop(m_LuaState, 1); // get rid of the string on the stack we just pushed on line 3
+ lua_pushstring(m_LuaState, cur_path.c_str()); // push the new one
+ lua_setfield(
+ m_LuaState, -2,
+ fieldName); // set the field "path"/"cpath" in table at -2 with value at top of stack
+ lua_pop(m_LuaState, 1); // get rid of package table from top of stack
+ }
+
+ bool LoadLuaFile(const char8_t *inFname, const char8_t *inGlobalVarName) override
+ {
+ luaL_loadfile(m_LuaState, inFname);
+ int error = lua_pcall(m_LuaState, 0, 1, 0);
+ if (error) {
+ const char8_t *errorStr = lua_tostring(m_LuaState, -1);
+ qCWarning(WARNING, "Error loading lua file: %s", errorStr);
+ return false;
+ } else {
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, inGlobalVarName);
+ }
+ lua_settop(m_LuaState, 0);
+ return true;
+ }
+
+ int GetTop() override { return lua_gettop(m_LuaState); }
+ void SetTop(int inTop) override { lua_settop(m_LuaState, inTop); }
+
+ Option<QT3DSF32> NumberFromTopOfStackTable(const char8_t *inKeyName) override
+ {
+ lua_getfield(m_LuaState, -1, inKeyName);
+ Option<QT3DSF32> retval;
+ if (!lua_isnil(m_LuaState, -1))
+ retval = lua_tonumber(m_LuaState, -1);
+ lua_pop(m_LuaState, 1);
+ return retval;
+ }
+
+ Option<QT3DSVec3> Vec3FromTopOfStackTable(const char8_t *inKeyName) override
+ {
+ lua_getfield(m_LuaState, -1, inKeyName);
+ Option<QT3DSVec3> retval;
+ if (lua_istable(m_LuaState, -1)) {
+ QT3DSVec3 result;
+ lua_getfield(m_LuaState, -1, "r");
+ if (lua_isnumber(m_LuaState, -1))
+ result.x = lua_tonumber(m_LuaState, -1);
+ lua_pop(m_LuaState, 1);
+ lua_getfield(m_LuaState, -1, "g");
+ if (lua_isnumber(m_LuaState, -1))
+ result.y = lua_tonumber(m_LuaState, -1);
+ lua_pop(m_LuaState, 1);
+ lua_getfield(m_LuaState, -1, "b");
+ if (lua_isnumber(m_LuaState, -1))
+ result.z = lua_tonumber(m_LuaState, -1);
+ lua_pop(m_LuaState, 1);
+ retval = result;
+ }
+ lua_pop(m_LuaState, 1);
+ return retval;
+ }
+
+ qt3ds::foundation::Option<bool> BooleanFromTopOfStackTable(const char8_t *inKeyName) override
+ {
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ lua_getfield(m_LuaState, -1, inKeyName);
+ bool retval = lua_toboolean(m_LuaState, -1) ? true : false;
+ lua_pop(m_LuaState, 1);
+ return retval;
+ }
+
+ eastl::string StringFromTopOfStackTable(const char8_t *inKeyName) override
+ {
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ lua_getfield(m_LuaState, -1, inKeyName);
+ eastl::string retval;
+ if (!lua_isnil(m_LuaState, -1)) {
+ retval.assign(nonNull(lua_tostring(m_LuaState, -1)));
+ }
+ lua_pop(m_LuaState, 1);
+ return retval;
+ }
+ // inIndex is 1 based, not zero based. Uses rawgeti so don't expect metadata to work.
+ // Returns true if the child is nonnull. If it returns false, it pops the null off the stack
+ // leaving the table.
+ bool GetChildFromTopOfStackTable(QT3DSI32 inIndex) override
+ {
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ lua_rawgeti(m_LuaState, -1, inIndex);
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1);
+ return false;
+ }
+ return true;
+ }
+
+ int GetNumChildrenFromTopOfStackTable() override
+ {
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ return lua_objlen(m_LuaState, -1);
+ }
+
+ bool ExecuteFunction(const char8_t *inGlobalVarName, const char8_t *fnName,
+ const char8_t *fnArg) override
+ {
+ int top = lua_gettop(m_LuaState);
+ lua_getglobal(m_LuaState, inGlobalVarName);
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_settop(m_LuaState, top);
+ return false;
+ }
+ lua_getfield(m_LuaState, -1, fnName);
+
+ if (!lua_isfunction(m_LuaState, -1)) {
+ lua_settop(m_LuaState, top);
+ return false;
+ }
+
+ lua_pushstring(m_LuaState, fnArg);
+ int error = lua_pcall(m_LuaState, 1, 1, 0);
+ if (error) {
+ const char8_t *errorStr = lua_tostring(m_LuaState, -1);
+ qCWarning(WARNING, "Error loading lua file: %s", errorStr);
+ return false;
+ }
+ return true;
+ }
+
+ bool ExecuteFunction(const char8_t *inGlobalVarName, const char8_t *fnName, int numArgs,
+ int numResults) override
+ {
+ int top = lua_gettop(m_LuaState);
+ lua_getglobal(m_LuaState, inGlobalVarName);
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_settop(m_LuaState, top);
+ return false;
+ }
+ lua_getfield(m_LuaState, -1, fnName);
+ if (!lua_isfunction(m_LuaState, -1)) {
+ lua_settop(m_LuaState, top);
+ return false;
+ }
+ // get rid of table.
+ lua_insert(m_LuaState, -2);
+ lua_pop(m_LuaState, 1);
+ if (!lua_isfunction(m_LuaState, -1)) {
+ lua_settop(m_LuaState, top);
+ return false;
+ }
+ // insert the arguments in same order above the function definition
+ // Currently:
+ // arg0
+ // argn
+ // fn
+ for (int idx = 0, end = numArgs; idx < end; ++idx)
+ lua_insert(m_LuaState, -1 - numArgs);
+ // now:
+ // fn
+ // arg0,
+ // argn
+ int error = lua_pcall(m_LuaState, numArgs, numResults, 0);
+ if (error) {
+ const char8_t *errorStr = lua_tostring(m_LuaState, -1);
+ qCWarning(WARNING, "Error loading lua file: %s", errorStr);
+ return false;
+ }
+ return true;
+ }
+
+ bool BeginTableIteration() override
+ {
+ lua_pushnil(m_LuaState);
+ return lua_next(m_LuaState, -2) ? true : false;
+ }
+
+ bool NextTableIteration(int numPops) override
+ {
+ // pop the value off the stack
+ if (numPops > 0)
+ lua_pop(m_LuaState, numPops);
+ return lua_next(m_LuaState, -2) ? true : false;
+ }
+
+ void ParseFloatingPointPairArray(eastl::vector<QT3DSVec2> &outFloats) override
+ {
+ for (bool success = BeginTableIteration(); success; success = NextTableIteration(0)) {
+ int top = lua_gettop(m_LuaState);
+ QT3DSVec2 result(0, 0);
+ if (BeginTableIteration()) {
+ result.x = lua_tonumber(m_LuaState, -1);
+ if (NextTableIteration(1))
+ result.y = lua_tonumber(m_LuaState, -1);
+ }
+ // Pop the value off, not certain where everything ends up.
+ lua_settop(m_LuaState, top - 1);
+ outFloats.push_back(result);
+ }
+ lua_pop(m_LuaState, 1);
+ }
+
+ void Release() override
+ {
+ NVAllocatorCallback *cback = &m_Foundation.getAllocator();
+ NVDelete(*cback, this);
+ }
+};
+}
+
+IDynamicLua *IDynamicLua::CreateDynamicLua(qt3ds::NVFoundationBase &fnd, const char8_t *dllPath)
+{
+ DynLua *retval = QT3DS_NEW(fnd.getAllocator(), DynLua)(fnd, dllPath);
+ // If the lookup system was successful.
+ if (retval->m_LuaState)
+ return retval;
+
+ retval->Release();
+ return NULL;
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/DynamicLua.h b/src/Authoring/Client/Code/Core/Doc/DynamicLua.h
new file mode 100644
index 00000000..635c9236
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/DynamicLua.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSOption.h"
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace Q3DStudio {
+
+class IDynamicLua
+{
+protected:
+ virtual ~IDynamicLua() {}
+public:
+ struct Scope
+ {
+ IDynamicLua &m_Lua;
+ int m_Top;
+ Scope(IDynamicLua &inLua)
+ : m_Lua(inLua)
+ , m_Top(inLua.GetTop())
+ {
+ }
+ ~Scope() { m_Lua.SetTop(m_Top); }
+ };
+ enum PathType {
+ LuaModule = 0,
+ CModule,
+ };
+
+ virtual void AddLibraryPath(const char8_t *inPath, PathType inType) = 0;
+ // Load a file, storing result into global var named 'name'
+ virtual bool LoadLuaFile(const char8_t *inFname, const char8_t *inGlobalVarName) = 0;
+ virtual int GetTop() = 0;
+ virtual void SetTop(int inTop) = 0;
+ // Assuming a table is top of stack.
+ virtual qt3ds::foundation::Option<qt3ds::QT3DSF32>
+ NumberFromTopOfStackTable(const char8_t *inKeyName) = 0;
+ virtual qt3ds::foundation::Option<qt3ds::QT3DSVec3>
+ Vec3FromTopOfStackTable(const char8_t *inKeyName) = 0;
+ virtual qt3ds::foundation::Option<bool> BooleanFromTopOfStackTable(const char8_t *inKeyName) = 0;
+ virtual eastl::string StringFromTopOfStackTable(const char8_t *inKeyName) = 0;
+ // inIndex is 1 based, not zero based. Uses rawgeti so don't expect metadata to work.
+ // Returns true if the child is nonnull. If it returns false, it pops the null off the stack
+ // leaving the table.
+ virtual bool GetChildFromTopOfStackTable(qt3ds::QT3DSI32 inIndex) = 0;
+ virtual int GetNumChildrenFromTopOfStackTable() = 0;
+ // Execute a function assumed to be found from a global table.
+ // Expects one result and leaves it on the stack.
+ virtual bool ExecuteFunction(const char8_t *inGlobalVarName, const char8_t *fnName,
+ const char8_t *fnArg) = 0;
+
+ // Assumes the arguments are TOS already
+ virtual bool ExecuteFunction(const char8_t *inGlobalVarName, const char8_t *fnName, int numArgs,
+ int numResults) = 0;
+ // Begin table iteration, assuming table is TOS
+ virtual bool BeginTableIteration() = 0;
+ // pop the value off the stack, and call lua_next again
+ virtual bool NextTableIteration(int numPops) = 0;
+ // This is specifically to handle parsing an array of floating point pairs
+ //{ {x,y}, {x1,y1}, {x2,y2} }
+ virtual void ParseFloatingPointPairArray(eastl::vector<qt3ds::QT3DSVec2> &outFloats) = 0;
+ virtual void Release() = 0;
+
+ static IDynamicLua *CreateDynamicLua(qt3ds::NVFoundationBase &fnd, const char8_t *dllPath);
+};
+} \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Doc/Exceptions.h b/src/Authoring/Client/Code/Core/Doc/Exceptions.h
new file mode 100644
index 00000000..809e6dd6
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/Exceptions.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_EXCEPTIONS_H
+#define INCLUDED_EXCEPTIONS_H 1
+
+#pragma once
+
+#include "StudioException.h"
+#include "UICString.h"
+
+class CGeneralException : public CStudioException
+{
+public:
+ CGeneralException(const Q3DStudio::CString &inDescription)
+ : m_Description(inDescription)
+ {
+ }
+ virtual ~CGeneralException() {}
+
+ const wchar_t *GetDescription() const override
+ {
+ return static_cast<const wchar_t *>(m_Description);
+ }
+
+protected:
+ Q3DStudio::CString m_Description;
+};
+
+class CNoClientException : public CStudioException
+{
+public:
+ CNoClientException() {}
+ virtual ~CNoClientException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Client is not installed"));
+ }
+};
+
+class CClientCreationException : public CStudioException
+{
+public:
+ CClientCreationException() {}
+ virtual ~CClientCreationException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Unable to create Client"));
+ }
+};
+
+class CInvalidFileFormatException : public CStudioException
+{
+public:
+ CInvalidFileFormatException() {}
+ virtual ~CInvalidFileFormatException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Invalid file format"));
+ }
+};
+
+class CUnsupportedFileFormatException : public CStudioException
+{
+public:
+ CUnsupportedFileFormatException() {}
+ virtual ~CUnsupportedFileFormatException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Unsupported file format"));
+ }
+};
+
+class CENotImplException : public CStudioException
+{
+public:
+ CENotImplException() {}
+ virtual ~CENotImplException() {}
+ const wchar_t *GetDescription() const override { return Q3DStudio::CString(_UIC("ENOTIMPL")); }
+};
+
+class CInvalidArgumentsException : public CStudioException
+{
+public:
+ CInvalidArgumentsException() {}
+ virtual ~CInvalidArgumentsException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Invalid Argument"));
+ }
+};
+
+class CNullPointerException : public CStudioException
+{
+public:
+ CNullPointerException() {}
+ virtual ~CNullPointerException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Null Pointer Error"));
+ }
+};
+
+class CUnexpectedResultException : public CStudioException
+{
+public:
+ CUnexpectedResultException() {}
+ virtual ~CUnexpectedResultException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Unexpected Result"));
+ }
+};
+
+class CClientFailException : public CStudioException
+{
+public:
+ CClientFailException() {}
+ virtual ~CClientFailException() {}
+ const wchar_t *GetDescription() const override
+ {
+ return Q3DStudio::CString(_UIC("Client Failure"));
+ }
+};
+
+// Any referenced (e.g. Data File) load errors
+class CLoadReferencedFileException : public CGeneralException
+{
+public:
+ CLoadReferencedFileException(const wchar_t *inFilePath, const Q3DStudio::CString &inDescription)
+ : CGeneralException(inDescription)
+ {
+ if (inFilePath)
+ m_FilePath = inFilePath;
+ }
+ virtual ~CLoadReferencedFileException() {}
+ const wchar_t *GetFilePath() const { return static_cast<const wchar_t *>(m_FilePath); }
+
+protected:
+ Q3DStudio::CString m_FilePath;
+};
+
+#endif // INCLUDED_EXCEPTIONS_H
diff --git a/src/Authoring/Client/Code/Core/Doc/GraphUtils.cpp b/src/Authoring/Client/Code/Core/Doc/GraphUtils.cpp
new file mode 100644
index 00000000..34d95c59
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/GraphUtils.cpp
@@ -0,0 +1,431 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "GraphUtils.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+
+//==============================================================================
+// Filters
+//==============================================================================
+
+//==============================================================================
+/**
+ * Excludes those which are not inGraphableType
+ */
+bool FilterForGraphableType(CDoc * /*inDoc*/, EGraphableType inGraphableType,
+ Q3DStudio::TIdentifier /*inGraphable*/)
+{
+ EGraphableType theGraphableType = EGRAPHABLE_TYPE_ASSET;
+ return theGraphableType != inGraphableType;
+}
+
+//==============================================================================
+/**
+ * Excludes those which are not inGraphableType
+ */
+const Q3DStudio::TFilter FilterForGraphableType(CDoc *inDoc, EGraphableType inGraphableType)
+{
+ return boost::bind(FilterForGraphableType, inDoc, inGraphableType, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those which are not inAssetType
+ */
+bool FilterForAssetType(CDoc *inDoc, EStudioObjectType inObjectType,
+ Q3DStudio::TIdentifier inGraphable)
+{
+ return inDoc->GetStudioSystem()->GetClientDataModelBridge()->GetObjectType(inGraphable)
+ != inObjectType;
+}
+
+//==============================================================================
+/**
+ * Excludes those which are not inAssetType
+ */
+const Q3DStudio::TFilter FilterForAssetType(CDoc *inDoc, EStudioObjectType inObjectType)
+{
+ return boost::bind(FilterForAssetType, inDoc, inObjectType, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those which are inAssetType
+ */
+bool FilterAwayAssetType(CDoc *inDoc, EStudioObjectType inObjectType,
+ Q3DStudio::TIdentifier inGraphable)
+{
+ return inDoc->GetStudioSystem()->GetClientDataModelBridge()->GetObjectType(inGraphable)
+ == inObjectType;
+}
+
+//==============================================================================
+/**
+ * Excludes those which are inAssetType
+ */
+const Q3DStudio::TFilter FilterAwayAssetType(CDoc *inDoc, EStudioObjectType inObjectType)
+{
+ return boost::bind(FilterAwayAssetType, inDoc, inObjectType, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those which are not node. This compares the high bit of the type ID
+ */
+bool FilterForNodeType(CDoc *inDoc, Q3DStudio::TIdentifier inGraphable)
+{
+ return !inDoc->GetStudioSystem()->GetClientDataModelBridge()->IsNodeType(inGraphable);
+}
+
+//==============================================================================
+/**
+ * Excludes those which are not node. This compares the high bit of the type ID
+ */
+const Q3DStudio::TFilter FilterForNodeType(CDoc *inDoc)
+{
+ return boost::bind(FilterForNodeType, inDoc, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those who doesn't exist in SlideIndex
+ */
+bool FilterForSlide(CDoc *inDoc, UICDM::CUICDMSlideHandle inSlide,
+ Q3DStudio::TIdentifier inGraphable)
+{
+ try {
+ UICDM::ISlideSystem *theSlideSystem = inDoc->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetAssociatedSlide(inGraphable);
+ return !(theSlideSystem->IsMasterSlide(theSlide) || inSlide == theSlide);
+ } catch (UICDM::SlideNotFound &error) {
+ Q_UNUSED(error);
+ return false;
+ }
+}
+
+//==============================================================================
+/**
+ * Excludes those who doesn't exist in SlideIndex
+ */
+const Q3DStudio::TFilter FilterForSlide(CDoc *inDoc, UICDM::CUICDMSlideHandle inSlide)
+{
+ return boost::bind(FilterForSlide, inDoc, inSlide, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those whose controlling timeparent are different from inControllingTimeParent
+ */
+bool FilterForControllingTimeParent(CDoc *inDoc,
+ UICDM::CUICDMInstanceHandle inControllingTimeParent,
+ Q3DStudio::TIdentifier inGraphable)
+{
+ return inDoc->GetStudioSystem()->GetClientDataModelBridge()->GetOwningComponentInstance(
+ static_cast<UICDM::CUICDMInstanceHandle>(inGraphable))
+ != inControllingTimeParent;
+}
+
+//==============================================================================
+/**
+ * Excludes those whose controlling timeparent are different from inControllingTimeParent
+ */
+const Q3DStudio::TFilter
+FilterForControllingTimeParent(CDoc *inDoc, UICDM::CUICDMInstanceHandle inControllingTimeParent)
+{
+ return boost::bind(FilterForControllingTimeParent, inDoc, inControllingTimeParent, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those that are not in active component
+ */
+bool FilterForActiveComponent(CDoc *inDoc, UICDM::CUICDMSlideHandle inActiveComponentSlide,
+ Q3DStudio::TIdentifier inGraphable)
+{
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::ISlideSystem *theSlideSystem = inDoc->GetStudioSystem()->GetSlideSystem();
+
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetAssociatedSlide(inGraphable);
+ if (theBridge->IsInActiveComponent(inGraphable)
+ && (theSlideSystem->IsMasterSlide(theSlide) || theSlide == inActiveComponentSlide))
+ return false; // I'm in the active component and on the right slide, don't filter me!
+ return true;
+}
+
+//==============================================================================
+/**
+ * Excludes those that are not in active component
+ */
+const Q3DStudio::TFilter FilterForActiveComponent(CDoc *inDoc,
+ UICDM::CUICDMSlideHandle inActiveComponentSlide)
+{
+ return boost::bind(FilterForActiveComponent, inDoc, inActiveComponentSlide, _1);
+}
+
+//==============================================================================
+/**
+ * Excludes those that don't exist in current slide
+ */
+bool FilterForCurrentSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inTimeParent,
+ Q3DStudio::TIdentifier inGraphable)
+{
+ UICDM::ISlideSystem *theSlideSystem = inDoc->GetStudioSystem()->GetSlideSystem();
+
+ UICDM::CUICDMSlideHandle theSlideHandle = theSlideSystem->GetAssociatedSlide(inGraphable);
+
+ // Get the current slide index
+ UICDM::CUICDMSlideHandle theCurrentSlide =
+ inDoc->GetStudioSystem()->GetClientDataModelBridge()->GetComponentActiveSlide(inTimeParent);
+ if (theSlideSystem->IsMasterSlide(theSlideHandle) || (theCurrentSlide == theSlideHandle))
+ return false;
+ else
+ return true;
+}
+
+//==============================================================================
+/**
+ * Excludes those that don't exist in current slide
+ */
+const Q3DStudio::TFilter FilterForCurrentSlide(CDoc *inDoc,
+ UICDM::CUICDMInstanceHandle inTimeParent)
+{
+ return boost::bind(FilterForCurrentSlide, inDoc, inTimeParent, _1);
+}
+
+//==============================================================================
+// Helper functions to get children from the graph
+//==============================================================================
+
+inline void ApplyDefaultAssetCriterias(CDoc *inDoc, Q3DStudio::CGraphIterator &outIterator,
+ EStudioObjectType inObjectType)
+{
+ outIterator.ClearCriterias();
+ outIterator += FilterForGraphableType(inDoc, EGRAPHABLE_TYPE_ASSET);
+
+ if (inObjectType != OBJTYPE_UNKNOWN)
+ outIterator += FilterForAssetType(inDoc, inObjectType); // compare the asset type id
+}
+
+inline void GetChildrenFromGraph(Q3DStudio::TGraphPtr inGraph, Q3DStudio::TIdentifier inIdentifier,
+ Q3DStudio::CGraphIterator &outIterator)
+{
+ if (inGraph->IsExist(inIdentifier))
+ inGraph->GetChildren(outIterator, inIdentifier);
+}
+
+inline void GetReverseChildrenFromGraph(Q3DStudio::TGraphPtr inGraph,
+ Q3DStudio::TIdentifier inIdentifier,
+ Q3DStudio::CGraphIterator &outIterator)
+{
+ if (inGraph->IsExist(inIdentifier))
+ inGraph->GetReverseChildren(outIterator, inIdentifier);
+}
+
+//==============================================================================
+/**
+ * Returns an iterator for Asset Children
+ * This queries AssetGraph and applies filter to get only EGRAPHABLE_TYPE_ASSET children
+ * An optional filter is applied to get asset of a certain type
+ */
+void GetAssetChildren(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CGraphIterator &outIterator, EStudioObjectType inObjectType)
+{
+ TAssetGraphPtr theGraph = inDoc->GetAssetGraph();
+ ApplyDefaultAssetCriterias(inDoc, outIterator, inObjectType);
+ GetChildrenFromGraph(theGraph, inInstance, outIterator);
+}
+
+//==============================================================================
+/**
+ * Returns an iterator for Asset Children from a certain slide.
+ * This is similar to GetAssetChildren with additional filter:
+ * check if it exists in inSlide or Master.
+ * Used primarily for displaying objects in the timeline in the correct order.
+ */
+void GetAssetChildrenInSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSlide,
+ Q3DStudio::CGraphIterator &outIterator, EStudioObjectType inObjectType)
+{
+ TAssetGraphPtr theGraph = inDoc->GetAssetGraph();
+ ApplyDefaultAssetCriterias(inDoc, outIterator, inObjectType);
+ outIterator += FilterForSlide(inDoc, inSlide);
+ GetChildrenFromGraph(theGraph, inInstance, outIterator);
+}
+
+//==============================================================================
+/**
+ * Returns an iterator for Asset Children that are in same Time Context
+ * This is similar to GetAssetChildren with additional filter:
+ * check if the controlling timeparent is the same
+ */
+void GetAssetChildrenInTimeParent(UICDM::CUICDMInstanceHandle inInstance, CDoc *inDoc,
+ bool inIsAssetTimeParent, Q3DStudio::CGraphIterator &outIterator,
+ UICDM::CUICDMSlideHandle inActiveComponentSlide)
+{
+ // TODO: for inFilterActiveComponentSlideIndex, just pass in the SlideHandle
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ TAssetGraphPtr theGraph = inDoc->GetAssetGraph();
+ ApplyDefaultAssetCriterias(inDoc, outIterator, OBJTYPE_UNKNOWN);
+ outIterator += FilterForControllingTimeParent(
+ inDoc,
+ inIsAssetTimeParent ? inInstance : theBridge->GetOwningComponentInstance(inInstance));
+ if (inActiveComponentSlide.Valid())
+ outIterator += FilterForActiveComponent(inDoc, inActiveComponentSlide);
+ GetChildrenFromGraph(theGraph, inInstance, outIterator);
+}
+
+//==============================================================================
+/**
+ * Returns an iterator for Asset Children in current slide. This is used to find which asset to
+ *be rendered
+ * The children are returned in reverse order
+ */
+void GetAssetChildrenInCurrentSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CGraphIterator &outIterator,
+ EStudioObjectType inObjectType)
+{
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ TAssetGraphPtr theGraph = inDoc->GetAssetGraph();
+ ApplyDefaultAssetCriterias(inDoc, outIterator, inObjectType);
+ // get the asset from the active slide of the containing Component
+ UICDM::CUICDMInstanceHandle theTimeParentInstance =
+ (theBridge->IsSceneInstance(inInstance) || theBridge->IsComponentInstance(inInstance))
+ ? inInstance
+ : theBridge->GetOwningComponentInstance(inInstance);
+ if (theTimeParentInstance.Valid()) // theComponent should never be NULL. But there are some
+ // exceptional cases such as Edit Camera & Edit Layer
+ {
+ outIterator += FilterForCurrentSlide(inDoc, theTimeParentInstance);
+ // for rendering, we do in reverse order
+ GetReverseChildrenFromGraph(theGraph, inInstance, outIterator);
+ }
+}
+
+//==============================================================================
+// Other useful functions related to graph traversal
+//==============================================================================
+
+//==============================================================================
+/**
+ * Returns true if inAncestor is parent, grandparent, etc of inDescendant
+ */
+bool IsAscendant(Q3DStudio::TIdentifier inDescendant, Q3DStudio::TIdentifier inAncestor,
+ Q3DStudio::TGraphPtr inGraph)
+{
+ // We get the parent of inDescendant and compare it with inAncestor
+ Q3DStudio::TIdentifier theDescendantParent = inGraph->GetParent(inDescendant);
+ if (theDescendantParent) {
+ if (theDescendantParent == inAncestor)
+ return true;
+ else
+ return IsAscendant(theDescendantParent, inAncestor, inGraph);
+ } else
+ return false;
+}
+
+//==============================================================================
+/**
+ * Get the sibling node (get the node before or after) inNode from CGraphIterator
+ * This will not change the iterator
+ * Note that if this function is used frequently, consider moving it to inside CGraphIterator
+ * so we can use std::find on m_Results
+ */
+Q3DStudio::TIdentifier GetSibling(const Q3DStudio::TIdentifier inNode, bool inAfter,
+ const Q3DStudio::CGraphIterator &inIterator)
+{
+ size_t theCount = inIterator.GetCount();
+ size_t theIndex = 0;
+ Q3DStudio::TIdentifier theSiblingNode = 0;
+
+ for (theIndex = 0; theIndex < theCount; ++theIndex) {
+ if (inIterator.GetResult(theIndex) == inNode)
+ break;
+ }
+
+ if (inAfter)
+ ++theIndex; // Get next node
+ else
+ --theIndex; // Get previous node
+
+ if (theIndex < theCount && theIndex >= 0)
+ theSiblingNode = inIterator.GetResult(theIndex);
+
+ return theSiblingNode;
+}
+
+#include <iostream>
+//==============================================================================
+/**
+ * Prints the subtree of the asset
+ */
+void PrintAssetSubTree(UICDM::CUICDMInstanceHandle inInstance, CDoc *inDoc, char *prefix)
+{
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ std::cout << prefix << theBridge->GetName(inInstance).GetCharStar() << std::endl;
+
+ // Go through each asset and pass update to each child
+ Q3DStudio::CGraphIterator theChildren;
+ GetAssetChildrenInCurrentSlide(inDoc, inInstance, theChildren);
+ for (; !theChildren.IsDone(); ++theChildren) {
+ PrintAssetSubTree(theChildren.GetCurrent(), inDoc, prefix);
+ }
+}
+
+//==============================================================================
+/**
+ * Prints all the slides under a master slide
+ */
+void PrintSlideInfo(CDoc *m_Doc, char *prefix, UICDM::CUICDMSlideHandle theMasterSlide)
+{
+ size_t slideCountBefore =
+ m_Doc->GetStudioSystem()->GetSlideSystem()->GetSlideCount(theMasterSlide);
+ for (size_t i = 0; i < slideCountBefore; ++i) {
+ UICDM::CUICDMSlideHandle slideHdl =
+ m_Doc->GetStudioSystem()->GetSlideSystem()->GetSlideByIndex(theMasterSlide, i);
+ Q3DStudio::CString name = m_Doc->GetStudioSystem()->GetClientDataModelBridge()->GetName(
+ m_Doc->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(slideHdl));
+ std::cout << " : " << name.GetCharStar() << std::endl;
+
+ UICDM::CUICDMInstanceHandle slideInstance =
+ m_Doc->GetStudioSystem()->GetClientDataModelBridge()->GetOwningComponentInstance(
+ slideHdl);
+ PrintAssetSubTree(slideInstance, m_Doc, prefix);
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/GraphUtils.h b/src/Authoring/Client/Code/Core/Doc/GraphUtils.h
new file mode 100644
index 00000000..3bb0e8e0
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/GraphUtils.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_GRAPH_UTILS_H
+#define INCLUDED_GRAPH_UTILS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Graph.h"
+#include "StudioObjectTypes.h"
+#include "UICDMHandles.h"
+#include "IGraphable.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CDoc;
+
+typedef std::shared_ptr<Q3DStudio::CGraph> TAssetGraphPtr;
+typedef Q3DStudio::CGraph TAssetGraph;
+
+//==============================================================================
+// Filters
+//==============================================================================
+bool FilterForGraphableType(CDoc *inDoc, EGraphableType inGraphableType,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterForGraphableType(CDoc *inDoc, EGraphableType inGraphableType);
+
+bool FilterForAssetType(CDoc *inDoc, EStudioObjectType inObjectType,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterForAssetType(CDoc *inDoc, EStudioObjectType inObjectType);
+
+bool FilterAwayAssetType(CDoc *inDoc, EStudioObjectType inObjectType,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterAwayAssetType(CDoc *inDoc, EStudioObjectType inObjectType);
+
+bool FilterForNodeType(CDoc *inDoc, Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterForNodeType(CDoc *inDoc);
+
+bool FilterForSlide(CDoc *inDoc, UICDM::CUICDMSlideHandle inSlide,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterForSlide(CDoc *inDoc, UICDM::CUICDMSlideHandle inSlide);
+
+bool FilterForControllingTimeParent(CDoc *inDoc,
+ UICDM::CUICDMInstanceHandle inControllingTimeParent,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter
+FilterForControllingTimeParent(CDoc *inDoc, UICDM::CUICDMInstanceHandle inControllingTimeParent);
+
+bool FilterForActiveComponent(CDoc *inDoc, UICDM::CUICDMSlideHandle inActiveComponentSlide,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterForActiveComponent(CDoc *inDoc,
+ UICDM::CUICDMSlideHandle inActiveComponentSlide);
+
+bool FilterForCurrentSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inTimeParent,
+ Q3DStudio::TIdentifier inGraphable);
+const Q3DStudio::TFilter FilterForCurrentSlide(CDoc *inDoc,
+ UICDM::CUICDMInstanceHandle inTimeParent);
+
+//==============================================================================
+// Helper functions to get children from the graph
+//==============================================================================
+void GetAssetChildren(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CGraphIterator &outIterator,
+ EStudioObjectType inObjectType = OBJTYPE_UNKNOWN);
+void GetAssetChildrenInSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMSlideHandle inSlide,
+ Q3DStudio::CGraphIterator &outIterator,
+ EStudioObjectType inObjectType = OBJTYPE_UNKNOWN);
+void GetAssetChildrenInTimeParent(UICDM::CUICDMInstanceHandle inInstance, CDoc *inDoc,
+ bool inIsAssetTimeParent, Q3DStudio::CGraphIterator &outIterator,
+ UICDM::CUICDMSlideHandle inActiveComponentSlide = 0);
+void GetAssetChildrenInCurrentSlide(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ Q3DStudio::CGraphIterator &outIterator,
+ EStudioObjectType inObjectType = OBJTYPE_UNKNOWN);
+
+//==============================================================================
+// Other useful functions related to graph traversal
+//==============================================================================
+bool IsAscendant(Q3DStudio::TIdentifier inDescendant, Q3DStudio::TIdentifier inAncestor,
+ Q3DStudio::TGraphPtr inGraph);
+
+Q3DStudio::TIdentifier GetSibling(const Q3DStudio::TIdentifier inNode, bool inAfter,
+ const Q3DStudio::CGraphIterator &inIterator);
+
+void PrintAssetSubTree(UICDM::CUICDMInstanceHandle inInstance, CDoc *m_Doc, char *prefix);
+void PrintSlideInfo(CDoc *m_Doc, char *prefix, UICDM::CUICDMSlideHandle theMasterSlide);
+
+#endif // INCLUDED_GRAPH_UTILS_H
diff --git a/src/Authoring/Client/Code/Core/Doc/IComposerEditorInterface.h b/src/Authoring/Client/Code/Core/Doc/IComposerEditorInterface.h
new file mode 100644
index 00000000..ea4dc15b
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IComposerEditorInterface.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ICOMPOSERIMPORTINTERFACEH
+#define ICOMPOSERIMPORTINTERFACEH
+#include "IDocumentEditor.h"
+#include "UICImportPerformImport.h"
+
+namespace UICDM {
+class IStringTable;
+};
+
+namespace Q3DStudio {
+class CGraph;
+
+namespace ComposerImport {
+
+ using namespace Q3DStudio;
+ using namespace UICDM;
+ using namespace UICIMP;
+ using std::unordered_map;
+ using std::vector;
+ using std::pair;
+
+ // For the children of this instance that are associated with this slide,
+ // update their information.
+ typedef unordered_map<const wchar_t *, vector<pair<CUICDMSlideHandle, CUICDMInstanceHandle>>>
+ TIdMultiMap;
+
+ // Interface between the import library (which defines IComposerEditor)
+ // and the document (which provides IDocumentEditor)
+ class IComposerEditorInterface : public IComposerEditor
+ {
+ protected:
+ ~IComposerEditorInterface(){}
+
+ public:
+ friend class std::shared_ptr<IComposerEditorInterface>;
+
+ virtual bool HasError() = 0;
+ // This file path contains the import document id.
+ virtual void Finalize(const Q3DStudio::CFilePath &inDestFilePath) = 0;
+ virtual CUICDMInstanceHandle FindInstance(TImportId inImportHdl) = 0;
+ virtual CUICDMInstanceHandle GetRoot() = 0;
+ virtual const Q3DStudio::CFilePath &GetDestImportFile() = 0;
+ virtual void AddInstanceMap(CUICDMInstanceHandle instanceHandle, TImportId inImportId) = 0;
+
+ static std::shared_ptr<IComposerEditorInterface> CreateEditorInterface(
+ Q3DStudio::IDocumentEditor &editor, UICDM::CDataModelHandle parent // Parent object
+ ,
+ UICDM::CDataModelHandle root, UICDM::CUICDMSlideHandle slide,
+ const Q3DStudio::CFilePath &docPath, const Q3DStudio::CFilePath &fullPathToImportFile,
+ long inStartTime, UICDM::IStringTable &inStringTable);
+
+ // The refresh interface is setup to refresh multiple trees automatically
+ static std::shared_ptr<IComposerEditor>
+ CreateEditorInterface(Q3DStudio::IDocumentEditor &editor, TIdMultiMap &inRoots,
+ const Q3DStudio::CFilePath &docPath,
+ const Q3DStudio::CFilePath &fullPathToImportFile, long inStartTime,
+ UICDM::IStringTable &inStringTable, CGraph &inAssetGraph);
+ };
+}
+}
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
new file mode 100644
index 00000000..5e8e96ea
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
@@ -0,0 +1,2864 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "IComposerSerializer.h"
+#include "UICDMDataCore.h"
+#include "UICDMSlideCore.h"
+#include "UICDMAnimation.h"
+#include "UICDMActionCore.h"
+#include "UICDMXML.h"
+#include "UICDMWStrOps.h"
+#include "SlideSystem.h"
+#include "ActionSystem.h"
+#include "Graph.h"
+#include "UICDMWStrOpsImpl.h"
+#include "StandardExtensions.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "GUIDUtilities.h"
+#include "IDocumentEditor.h"
+#include "Q3DStudioNVFoundation.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderPathManager.h"
+#include "UICDMGuides.h"
+#include "foundation/Qt3DSLogging.h"
+#include <unordered_map>
+#include <unordered_set>
+
+using namespace UICDM;
+using namespace std;
+using namespace Q3DStudio;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+
+namespace std {
+template <>
+struct hash<SLong4>
+{
+ size_t operator()(const SLong4 &inValue) const
+ {
+ hash<unsigned long> hasher;
+ return hasher(inValue.m_Longs[0] ^ inValue.m_Longs[1] ^ inValue.m_Longs[2]
+ ^ inValue.m_Longs[3]);
+ }
+};
+}
+
+namespace UICDM {
+
+template <>
+struct WStrOps<GuideDirections::Enum>
+{
+ QT3DSU32 ToStr(GuideDirections::Enum value, NVDataRef<char8_t> buffer)
+ {
+ const char8_t *directionName = NULL;
+ switch (value) {
+ case GuideDirections::Horizontal:
+ directionName = "Horizontal";
+ break;
+ case GuideDirections::Vertical:
+ directionName = "Vertical";
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ if (directionName != NULL)
+ return _snprintf(buffer.begin(), buffer.size(), "%s", directionName);
+ else {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ }
+ bool StrTo(const char8_t *buffer, GuideDirections::Enum &item)
+ {
+ if (AreEqual("Horizontal", buffer)) {
+ item = GuideDirections::Horizontal;
+ return true;
+ }
+ if (AreEqual("Vertical", buffer)) {
+ item = GuideDirections::Vertical;
+ return true;
+ }
+ return false;
+ }
+};
+}
+
+namespace {
+
+typedef qt3ds::foundation::NVScopedRefCounted<uic::render::IInputStreamFactory> TStreamFactoryPtr;
+
+using std::hash;
+
+template <typename TOperator>
+static void HandleKeyframe(SLinearKeyframe &inKeyframe, TOperator &inOperator)
+{
+ inOperator(inKeyframe.m_KeyframeSeconds);
+ inOperator(inKeyframe.m_KeyframeSeconds);
+}
+
+template <typename TOperator>
+static void HandleKeyframe(SBezierKeyframe &inKeyframe, TOperator &inOperator)
+{
+ inOperator(inKeyframe.m_KeyframeSeconds);
+ inOperator(inKeyframe.m_KeyframeValue);
+ inOperator(inKeyframe.m_InTangentTime);
+ inOperator(inKeyframe.m_InTangentValue);
+ inOperator(inKeyframe.m_OutTangentTime);
+ inOperator(inKeyframe.m_OutTangentValue);
+}
+
+template <typename TOperator>
+static void HandleKeyframe(SEaseInEaseOutKeyframe &inKeyframe, TOperator &inOperator)
+{
+ inOperator(inKeyframe.m_KeyframeSeconds);
+ inOperator(inKeyframe.m_KeyframeValue);
+ inOperator(inKeyframe.m_EaseIn);
+ inOperator(inKeyframe.m_EaseOut);
+}
+
+template <typename TItemType>
+struct SVectorWriteOperator
+{
+ vector<TItemType> &m_Vector;
+ SVectorWriteOperator(vector<TItemType> &vec)
+ : m_Vector(vec)
+ {
+ }
+ void operator()(const TItemType &inValue) { m_Vector.push_back(inValue); }
+};
+
+template <typename TItemType>
+struct SMemReadOperator
+{
+ const TItemType *m_Ptr;
+ const TItemType *m_End;
+ SMemReadOperator(const TItemType *s, const TItemType *e)
+ : m_Ptr(s)
+ , m_End(e)
+ {
+ }
+
+ bool IsDone() { return m_Ptr >= m_End; }
+
+ void operator()(TItemType &outValue)
+ {
+ if (m_Ptr < m_End) {
+ outValue = *m_Ptr;
+ ++m_Ptr;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+};
+
+template <typename TKeyframeType>
+static void WriteKeyframes(TKeyframeHandleList &inKeyframes, IAnimationCore &inCore,
+ vector<float> &outValues)
+{
+ SVectorWriteOperator<float> theOperator(outValues);
+ for (size_t idx = 0, end = inKeyframes.size(); idx < end; ++idx) {
+ TKeyframe theKeyframeVariant(inCore.GetKeyframeData(inKeyframes[idx]));
+ TKeyframeType theData(get<TKeyframeType>(theKeyframeVariant));
+ HandleKeyframe(theData, theOperator);
+ }
+}
+
+template <typename TKeyframeType>
+static void ReadKeyframes(CUICDMAnimationHandle inAnimation, IAnimationCore &inCore,
+ const float *inStart, const float *inEnd)
+{
+ SMemReadOperator<float> theOperator(inStart, inEnd);
+ while (theOperator.IsDone() == false) {
+ TKeyframeType theData;
+ HandleKeyframe(theData, theOperator);
+ inCore.InsertKeyframe(inAnimation, theData);
+ }
+}
+
+struct SPropertyMatcher
+{
+ CUICDMPropertyHandle rhs;
+ SPropertyMatcher(CUICDMPropertyHandle _rhs)
+ : rhs(_rhs)
+ {
+ }
+ bool operator()(const pair<CUICDMPropertyHandle, SValue> &lhs) const
+ {
+ return lhs.first == rhs;
+ }
+};
+
+struct SPropertyMatches
+{
+ CUICDMPropertyHandle m_Prop;
+ SPropertyMatches(CUICDMPropertyHandle inProp)
+ : m_Prop(inProp)
+ {
+ }
+ bool operator()(const pair<CUICDMPropertyHandle, SValue> &inValue)
+ {
+ return inValue.first == m_Prop;
+ }
+};
+
+struct SAnimationMatcher
+{
+ IAnimationCore &m_Core;
+ CUICDMAnimationHandle rhs;
+ SAnimationMatcher(IAnimationCore &impl, CUICDMAnimationHandle _rhs)
+ : m_Core(impl)
+ , rhs(_rhs)
+ {
+ }
+ bool operator()(CUICDMAnimationHandle lhs) const
+ {
+ SAnimationInfo lhsInfo(m_Core.GetAnimationInfo(lhs));
+ SAnimationInfo rhsInfo(m_Core.GetAnimationInfo(rhs));
+ QT3DS_ASSERT(lhsInfo.m_Instance == rhsInfo.m_Instance);
+ return lhsInfo.m_Property == rhsInfo.m_Property && lhsInfo.m_Index == rhsInfo.m_Index;
+ }
+};
+
+struct SAttributeNameSorter
+{
+ IDataCore &m_Core;
+ SAttributeNameSorter(IDataCore &inImpl)
+ : m_Core(inImpl)
+ {
+ }
+
+ bool operator()(const pair<CUICDMPropertyHandle, SValue> &lhsPair,
+ const pair<CUICDMPropertyHandle, SValue> &rhsPair)
+ {
+ TCharStr lhs(m_Core.GetProperty(lhsPair.first).m_Name);
+ TCharStr rhs(m_Core.GetProperty(rhsPair.first).m_Name);
+ if (lhs == rhs)
+ return false;
+ if (lhs == L"name")
+ return true;
+ if (rhs == L"name")
+ return false;
+ return lhs.compare(rhs) < 0;
+ }
+};
+
+// Erase all properties that *are* on this instance from the property vector.
+struct SMetaDataPropertyEraser
+{
+ CUICDMInstanceHandle m_Instance;
+ SComposerObjectDefinitions &m_MetaData;
+ SMetaDataPropertyEraser(CUICDMInstanceHandle inst, SComposerObjectDefinitions &meta)
+ : m_Instance(inst)
+ , m_MetaData(meta)
+ {
+ }
+
+ bool operator()(const pair<CUICDMPropertyHandle, SValue> &inProperty)
+ {
+ bool required = inProperty.first == m_MetaData.m_Named.m_NameProp
+ || inProperty.first == m_MetaData.m_Asset.m_SourcePath;
+ return !required;
+ }
+};
+using std::unordered_set;
+using std::unordered_map;
+using std::tuple;
+
+// Algorithm to write is to run through the graph, starting at the root instances
+// and write out the instances as we come to them.
+struct SComposerSerializerImpl : public IComposerSerializer
+{
+ typedef unordered_set<CUICDMInstanceHandle, hash<int>> TInstanceSet;
+ typedef unordered_set<CUICDMSlideHandle, hash<int>> TSlideSet;
+ typedef unordered_set<CUICDMActionHandle, hash<int>> TActionSet;
+ typedef vector<CUICDMInstanceHandle> TInstanceList;
+ typedef unordered_map<int, TCharPtr> THandleToIdMap;
+ typedef unordered_map<TCharPtr, int> TIdToHandleMap;
+ typedef unordered_map<SLong4, int> TGUIDToHandleMap;
+ typedef unordered_map<int, SLong4> THandleToGUIDMap;
+ typedef unordered_map<CUICDMInstanceHandle, int, hash<int>> TInstanceIntMap;
+ typedef unordered_map<CUICDMInstanceHandle, TCharPtr, hash<int>> TInstanceToSiblingMap;
+
+ IDataCore &m_DataCore;
+ IMetaData &m_MetaData;
+ ISlideCore &m_SlideCore;
+ IAnimationCore &m_AnimationCore;
+ IActionCore &m_ActionCore;
+ ISlideSystem &m_SlideSystem;
+ ISlideGraphCore &m_SlideGraphCore;
+ IActionSystem &m_ActionSystem;
+ CGraph &m_AssetGraph;
+ IGuideSystem &m_GuideSystem;
+ SComposerObjectDefinitions &m_ObjectDefinitions;
+ UICDM::IStringTable &m_StringTable;
+ std::shared_ptr<Q3DStudio::IImportFailedHandler> m_ImportFailedHandler;
+ uic::render::IPathManager &m_PathManager;
+
+ // The instances we have discovered when we are writing
+ THandleToIdMap m_HandleToIdMap;
+ TIdToHandleMap m_IdToHandleMap;
+
+ TGUIDToHandleMap m_GUIDToHandleMap;
+ THandleToGUIDMap m_HandleToGUIDMap;
+
+ CUICDMSlideHandle m_ActiveSlide;
+ CUICDMSlideHandle m_ActiveSlideParent;
+
+ THandleToIdMap m_ActionToIdMap;
+ TIdToHandleMap m_IdToActionMap;
+
+ THandleToIdMap m_SlideToIdMap;
+ TIdToHandleMap m_IdToSlideMap;
+
+ TInstanceSet m_InstanceSet;
+ TSlideSet m_SlideSet;
+ TInstanceSet m_ExternalReferences;
+ TActionSet m_ExternalActions;
+ TSlideSet m_ExternalSlides;
+
+ TInstanceSet m_MasterObjectsSet;
+ TIdToHandleMap m_SourcePathToMasterInstances;
+
+ TInstanceIntMap m_InstanceToGraphDepthMap;
+
+ // These are cleared just before use
+ MemoryBuffer<RawAllocator> m_TempBuffer;
+ MemoryBuffer<RawAllocator> m_ValueBuffer;
+ eastl::string m_ConvertStr;
+
+ Q3DStudio::Foundation::SStudioFoundation m_Foundation;
+ TStreamFactoryPtr m_InputStreamFactory;
+
+ // we want to preserve file ids on save but never on a paste operation.
+ bool m_PreserveFileIds;
+
+ TInstanceToSiblingMap m_NewInstancesToSiblings;
+
+ Option<int> m_UIPVersion;
+
+ SComposerSerializerImpl(IDataCore &inDataCore, IMetaData &inMetaData, ISlideCore &inSlideCore,
+ IAnimationCore &inAnimationCore, IActionCore &inActionCore,
+ CGraph &inAssetGraph, ISlideSystem &inSlideSystem,
+ IActionSystem &inActionSystem, ISlideGraphCore &inSlideGraphCore,
+ SComposerObjectDefinitions &inObjectDefinitions,
+ std::shared_ptr<Q3DStudio::IImportFailedHandler> inFailedHandler,
+ IGuideSystem &inGuideSystem, uic::render::IPathManager &inPathManager)
+ : m_DataCore(inDataCore)
+ , m_MetaData(inMetaData)
+ , m_SlideCore(inSlideCore)
+ , m_AnimationCore(inAnimationCore)
+ , m_ActionCore(inActionCore)
+ , m_SlideSystem(inSlideSystem)
+ , m_SlideGraphCore(inSlideGraphCore)
+ , m_ActionSystem(inActionSystem)
+ , m_AssetGraph(inAssetGraph)
+ , m_GuideSystem(inGuideSystem)
+ , m_ObjectDefinitions(inObjectDefinitions)
+ , m_StringTable(inDataCore.GetStringTable())
+ , m_ImportFailedHandler(inFailedHandler)
+ , m_PathManager(inPathManager)
+ , m_Foundation(Q3DStudio::Foundation::SStudioFoundation::Create())
+ , m_InputStreamFactory(uic::render::IInputStreamFactory::Create(*m_Foundation.m_Foundation))
+ , m_PreserveFileIds(true)
+ {
+ }
+
+ void reset()
+ {
+ m_HandleToIdMap.clear();
+ m_IdToHandleMap.clear();
+
+ m_GUIDToHandleMap.clear();
+ m_HandleToGUIDMap.clear();
+
+ m_ActiveSlide = 0;
+ m_ActiveSlideParent = 0;
+
+ m_ActionToIdMap.clear();
+ m_IdToActionMap.clear();
+
+ m_SlideToIdMap.clear();
+ m_IdToSlideMap.clear();
+
+ m_InstanceSet.clear();
+ m_SlideSet.clear();
+ m_ExternalReferences.clear();
+ m_ExternalActions.clear();
+ m_ExternalSlides.clear();
+
+ m_MasterObjectsSet.clear();
+ m_SourcePathToMasterInstances.clear();
+
+ m_InstanceToGraphDepthMap.clear();
+
+ m_NewInstancesToSiblings.clear();
+
+ m_UIPVersion = Option<int>();
+ }
+
+ TCharPtr AddId(const wstring &inId, CUICDMInstanceHandle inHandle)
+ {
+ TCharPtr theIdStr = m_StringTable.RegisterStr(inId.c_str());
+ m_IdToHandleMap.insert(make_pair(theIdStr, inHandle));
+ m_HandleToIdMap.insert(make_pair(inHandle, theIdStr));
+ if (m_PreserveFileIds)
+ m_DataCore.SetInstancePropertyValue(inHandle, m_ObjectDefinitions.m_Asset.m_FileId,
+ std::make_shared<CDataStr>(inId.c_str()));
+ return theIdStr;
+ }
+
+ TCharPtr SetId(const wstring &inId, CUICDMInstanceHandle inHandle)
+ {
+ TCharPtr theIdStr = m_StringTable.RegisterStr(inId.c_str());
+ m_IdToHandleMap.insert(make_pair(theIdStr, inHandle)).first->second = inHandle;
+ m_HandleToIdMap.insert(make_pair(inHandle, theIdStr)).first->second = theIdStr;
+ if (m_PreserveFileIds)
+ m_DataCore.SetInstancePropertyValue(inHandle, m_ObjectDefinitions.m_Asset.m_FileId,
+ std::make_shared<CDataStr>(inId.c_str()));
+ return theIdStr;
+ }
+
+ TCharPtr AddActionId(const wstring &inId, CUICDMActionHandle inHandle)
+ {
+ TCharPtr theIdStr = m_StringTable.RegisterStr(inId.c_str());
+ m_IdToActionMap.insert(make_pair(theIdStr, inHandle));
+ m_ActionToIdMap.insert(make_pair(inHandle, theIdStr));
+ return theIdStr;
+ }
+
+ TCharPtr AddSlideId(const wstring &inId, CUICDMSlideHandle inHandle)
+ {
+ TCharPtr theIdStr = m_StringTable.RegisterStr(inId.c_str());
+ m_IdToSlideMap.insert(make_pair(theIdStr, inHandle));
+ m_SlideToIdMap.insert(make_pair(inHandle, theIdStr));
+ return theIdStr;
+ }
+
+ CUICDMInstanceHandle GetInstanceById(TCharPtr inId)
+ {
+ if (IsTrivial(inId))
+ return 0;
+ if (inId[0] == '#')
+ ++inId;
+
+ inId = m_StringTable.RegisterStr(inId);
+ TIdToHandleMap::iterator find = m_IdToHandleMap.find(inId);
+ if (find != m_IdToHandleMap.end())
+ return find->second;
+ return 0;
+ }
+
+ CUICDMSlideHandle GetSlideById(TCharPtr inId)
+ {
+ if (IsTrivial(inId))
+ return 0;
+ if (inId[0] == '#')
+ ++inId;
+
+ inId = m_StringTable.RegisterStr(inId);
+ TIdToHandleMap::iterator find = m_IdToSlideMap.find(inId);
+ if (find != m_IdToSlideMap.end())
+ return find->second;
+ return 0;
+ }
+
+ CUICDMActionHandle GetActionById(TCharPtr inId)
+ {
+ if (IsTrivial(inId))
+ return 0;
+ if (inId[0] == '#')
+ ++inId;
+
+ inId = m_StringTable.RegisterStr(inId);
+ TIdToHandleMap::iterator find = m_IdToActionMap.find(inId);
+ if (find != m_IdToActionMap.end())
+ return find->second;
+ return 0;
+ }
+
+ void AddGuid(SLong4 inId, int inHandle)
+ {
+ m_GUIDToHandleMap.insert(make_pair(inId, inHandle));
+ m_HandleToGUIDMap.insert(make_pair(inHandle, inId));
+ }
+
+ SLong4 GetInstanceGuid(CUICDMInstanceHandle inInstance)
+ {
+ THandleToGUIDMap::iterator find = m_HandleToGUIDMap.find(inInstance);
+ if (find != m_HandleToGUIDMap.end())
+ return find->second;
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(inInstance, m_ObjectDefinitions.m_Guided.m_GuidProp,
+ theValue)) {
+ SLong4 theGuid = UICDM::get<SLong4>(theValue);
+ AddGuid(theGuid, inInstance);
+ return theGuid;
+ }
+ return SLong4();
+ }
+
+ TCharPtr GetInstanceName(CUICDMInstanceHandle inInstance)
+ {
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ SValue theValue;
+ if (theAssociatedSlide.Valid()
+ && m_SlideCore.GetSpecificInstancePropertyValue(theAssociatedSlide, inInstance,
+ m_ObjectDefinitions.m_Named.m_NameProp,
+ theValue)) {
+ TDataStrPtr theName(get<TDataStrPtr>(theValue));
+ TCharPtr retval = theName->GetData();
+ if (!IsTrivial(retval))
+ return retval;
+ }
+ SValue theDCValue;
+ if (m_DataCore.GetInstancePropertyValue(inInstance, m_ObjectDefinitions.m_Named.m_NameProp,
+ theDCValue)) {
+ TDataStrPtr theName(get<TDataStrPtr>(theDCValue));
+ TCharPtr retval = theName->GetData();
+ if (!IsTrivial(retval))
+ return retval;
+ }
+ Option<TCharStr> theTypeStr = m_MetaData.GetTypeForInstance(inInstance);
+ if (theTypeStr.hasValue())
+ return m_StringTable.RegisterStr(theTypeStr->wide_str());
+ QT3DS_ASSERT(false);
+ return L"";
+ }
+
+ TCharPtr GetInstanceName(CUICDMInstanceHandle inInstance, CUICDMSlideHandle inSlide)
+ {
+ SValue theValue;
+ if (m_SlideCore.GetSpecificInstancePropertyValue(
+ inSlide, inInstance, m_ObjectDefinitions.m_Named.m_NameProp, theValue)) {
+ TDataStrPtr theName(get<TDataStrPtr>(theValue));
+ TCharPtr retval = theName->GetData();
+ if (!IsTrivial(retval))
+ return retval;
+ }
+ return GetInstanceName(inInstance);
+ }
+
+ TCharPtr GetId(const wstring &inIdStem)
+ {
+ // Create an ID for this instance
+ wstring theTypeStr(inIdStem);
+ wstring theTypeStem(theTypeStr);
+ wstring::size_type thePos = theTypeStem.find_last_of('_');
+ if (thePos != wstring::npos && thePos < theTypeStem.size() - 2) {
+ if (theTypeStem[thePos + 1] >= '0' && theTypeStem[thePos + 1] <= '1')
+ theTypeStem = theTypeStem.substr(0, thePos);
+ }
+ QT3DSU32 idIdx = 1;
+
+ while (m_IdToActionMap.find(m_StringTable.RegisterStr(theTypeStr.c_str()))
+ != m_IdToActionMap.end()
+ || m_IdToHandleMap.find(m_StringTable.RegisterStr(theTypeStr.c_str()))
+ != m_IdToHandleMap.end()
+ || m_IdToSlideMap.find(m_StringTable.RegisterStr(theTypeStr.c_str()))
+ != m_IdToSlideMap.end()) {
+ wchar_t theBuffer[16];
+ swprintf(theBuffer, 16, L"_%03d", idIdx);
+ theTypeStr = theTypeStem + theBuffer;
+ ++idIdx;
+ }
+ return m_StringTable.RegisterStr(theTypeStr.c_str());
+ }
+
+ TCharPtr GetInstanceId(CUICDMInstanceHandle inInstance)
+ {
+ QT3DS_ASSERT(inInstance.Valid());
+ THandleToIdMap::iterator theFind(m_HandleToIdMap.find(inInstance));
+ if (theFind != m_HandleToIdMap.end())
+ return theFind->second;
+
+ TCharStr theName(GetInstanceName(inInstance));
+ Option<TCharStr> theType = m_MetaData.GetTypeForInstance(inInstance);
+ if (theType.hasValue() == false) {
+ QT3DS_ASSERT(false);
+ return L"";
+ }
+
+ // for most instances we just want a simple id based on the object name.
+ // for images, however, we want do to something else.
+ TCharPtr theNewId = L"";
+ if (m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_Image.m_Instance)) {
+ CUICDMInstanceHandle theMaterial = m_AssetGraph.GetParent(inInstance);
+ if (theMaterial.Valid()) {
+ wstring theIdStr(GetInstanceId(theMaterial));
+ SLong4 theGuid = GetInstanceGuid(inInstance);
+ theIdStr.append(L"_");
+ TPropertyHandleList theProperties;
+ m_DataCore.GetAggregateInstanceProperties(theMaterial, theProperties);
+ CUICDMPropertyHandle theProperty;
+ for (size_t propIdx = 0, propEnd = theProperties.size();
+ propIdx < propEnd && theProperty.Valid() == false; ++propIdx) {
+ SValue theValue;
+ const SUICDMPropertyDefinition &theDefinition(
+ m_DataCore.GetProperty(theProperties[propIdx]));
+ if (theDefinition.m_Type == DataModelDataType::Long4) {
+ SValue theDCValue;
+ if (m_DataCore.GetInstancePropertyValue(theMaterial, theProperties[propIdx],
+ theDCValue)) {
+ SLong4 thePropGuid = get<SLong4>(theDCValue);
+ if (thePropGuid == theGuid)
+ theProperty = theProperties[propIdx];
+ }
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ if (theProperty.Valid() == false && theSlide.Valid()
+ && m_SlideCore.GetSpecificInstancePropertyValue(
+ theSlide, theMaterial, theProperties[propIdx], theValue)) {
+ SLong4 thePropGuid = get<SLong4>(theValue);
+ if (thePropGuid == theGuid)
+ theProperty = theProperties[propIdx];
+ }
+ }
+ }
+ if (theProperty.Valid()) {
+ theIdStr.append(m_DataCore.GetProperty(theProperty).m_Name.wide_str());
+ theNewId = GetId(theIdStr);
+ }
+ }
+ }
+
+ if (IsTrivial(theNewId))
+ theNewId = GetId(theName.wide_str());
+ return AddId(theNewId, inInstance);
+ }
+
+ TCharPtr GetActionId(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+ {
+ QT3DS_ASSERT(inAction.Valid());
+ THandleToIdMap::iterator theFind(m_ActionToIdMap.find(inAction));
+ if (theFind != m_ActionToIdMap.end())
+ return theFind->second;
+
+ wstring theActionName(GetInstanceName(inInstance, inSlide));
+ theActionName.append(L"-Action");
+
+ TCharPtr theNewId = GetId(theActionName);
+ return AddActionId(theNewId, inAction);
+ }
+
+ // If this function is called with an invalid instance and we don't already have an id
+ // then we assume we have an external reference and lookup the instance via the component id.
+ TCharPtr GetSlideId(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance)
+ {
+ QT3DS_ASSERT(inSlide.Valid());
+ THandleToIdMap::iterator theFind(m_SlideToIdMap.find(inSlide));
+ if (theFind != m_SlideToIdMap.end())
+ return theFind->second;
+
+ if (inInstance.Valid() == false) {
+ m_ExternalSlides.insert(inSlide);
+ CUICDMSlideHandle theMaster = m_SlideSystem.GetMasterSlide(inSlide);
+ CUICDMInstanceHandle theSlideData = m_SlideCore.GetSlideInstance(theMaster);
+ SValue theValue;
+ m_DataCore.GetInstancePropertyValue(
+ theSlideData, m_ObjectDefinitions.m_Slide.m_ComponentId, theValue);
+ SLong4 theComponent = get<SLong4>(theValue);
+ inInstance = FindInstanceByGUID(theComponent);
+ QT3DS_ASSERT(inInstance.Valid());
+ }
+
+ wstring theSlideName(GetInstanceName(inInstance));
+ theSlideName.append(L"-");
+ theSlideName.append(GetSlideName(inSlide));
+
+ TCharPtr theNewId = GetId(theSlideName);
+ return AddSlideId(theNewId, inSlide);
+ }
+
+ SLong4 GetGuid(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty)
+ {
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(inInstance, inProperty, theValue)) {
+ SLong4 theLongValue(get<SLong4>(theValue));
+ if (theLongValue.m_Longs[0] || theLongValue.m_Longs[1] || theLongValue.m_Longs[2]
+ || theLongValue.m_Longs[3])
+ return theLongValue;
+ }
+ CUICDMSlideHandle theSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ SValue theSlideValue;
+ if (theSlide.Valid()
+ && m_SlideCore.GetInstancePropertyValue(theSlide, inInstance, inProperty,
+ theSlideValue)) {
+ SLong4 theLongValue(get<SLong4>(theSlideValue));
+ return theLongValue;
+ }
+ return SLong4();
+ }
+
+ void GetAllInstanceGuids()
+ {
+ TInstanceHandleList theInstances;
+ m_DataCore.GetInstancesDerivedFrom(theInstances, m_ObjectDefinitions.m_Guided.m_Instance);
+ // sort the instances so parents appear before children. This stabilizes the ids used
+ // somewhat.
+ std::sort(theInstances.begin(), theInstances.end(), std::less<int>());
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theInstance(theInstances[idx]);
+ SLong4 theGuid = GetGuid(theInstance, m_ObjectDefinitions.m_Guided.m_GuidProp);
+ if (theGuid.Valid()) {
+ AddGuid(theGuid, theInstance);
+ }
+ SValue theInstanceIdValue;
+ if (m_DataCore.GetInstancePropertyValue(
+ theInstance, m_ObjectDefinitions.m_Asset.m_FileId, theInstanceIdValue)) {
+ TDataStrPtr theNamePtr = UICDM::get<TDataStrPtr>(theInstanceIdValue);
+ if (theNamePtr && !IsTrivial(theNamePtr->GetData())) {
+ const wchar_t *theId = GetId(theNamePtr->GetData());
+ AddId(theId, theInstance);
+ }
+ }
+ }
+ }
+
+ void BuildSourcePathMasterObjectMap()
+ {
+ TInstanceHandleList theInstances;
+ TInstanceHandleList theParents;
+ // We need to check the source path.
+ m_DataCore.GetInstancesDerivedFrom(theInstances, m_ObjectDefinitions.m_Asset.m_Instance);
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theInstance(theInstances[idx]);
+ // Find master objects by finding all asset instances that derive from non-canonical
+ // instances.
+ // these non-canonical parents *must* be master objects.
+ theParents.clear();
+ m_DataCore.GetInstanceParents(theInstance, theParents);
+ if (theParents.size() != 1)
+ continue;
+ // If the parent is canonical then continue;
+ if (m_MetaData.GetTypeForCanonicalInstance(theParents[0]).hasValue())
+ continue;
+ // Finally, this must mean the object is canonical.
+ CUICDMInstanceHandle theMaster(theParents[0]);
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(
+ theMaster, m_ObjectDefinitions.m_Asset.m_SourcePath, theValue)) {
+ TDataStrPtr theStr(get<TDataStrPtr>(theValue));
+ const wchar_t *thePath(theStr->GetData());
+ if (!IsTrivial(thePath))
+ m_SourcePathToMasterInstances.insert(
+ make_pair(m_StringTable.RegisterStr(thePath), theMaster));
+ }
+ }
+ }
+
+ CUICDMInstanceHandle FindInstanceByGUID(SLong4 theGuid)
+ {
+ if (m_GUIDToHandleMap.size() == 0)
+ GetAllInstanceGuids();
+ if (theGuid.Valid() == false)
+ return 0;
+
+ TGUIDToHandleMap::iterator theIter(m_GUIDToHandleMap.find(theGuid));
+ if (theIter != m_GUIDToHandleMap.end())
+ return theIter->second;
+ return 0;
+ }
+
+ const wchar_t *WriteDataModelValue(const SValue &_inValue, TCharStr &theValueStr)
+ {
+ DataModelDataType::Value theValueType(GetValueType(_inValue));
+ SValue theValue(_inValue);
+ // Transform the value into something we can deal with.
+ if (theValueType == DataModelDataType::ObjectRef) {
+ const SObjectRefType &theRef(get<SObjectRefType>(theValue));
+ switch (theRef.GetReferenceType()) {
+ case ObjectReferenceType::Absolute:
+ theValue = get<SLong4>(theRef.m_Value);
+ break;
+ case ObjectReferenceType::Relative:
+ theValue = get<TDataStrPtr>(theRef.m_Value);
+ break;
+ default:
+ theValue = SLong4();
+ break;
+ }
+ } else if (theValueType == DataModelDataType::StringOrInt) {
+ const SStringOrInt &theData(get<SStringOrInt>(theValue));
+ if (theData.GetType() == SStringOrIntTypes::Int) {
+ CUICDMSlideHandle theHandle(get<long>(theData.m_Value));
+ wstring theSlideId(L"#");
+ theSlideId.append(GetSlideId(theHandle, 0));
+ theValue = std::make_shared<CDataStr>(theSlideId.c_str());
+ } else
+ theValue = get<TDataStrPtr>(theData.m_Value);
+ }
+ // Resolve SLong4 properties;
+ if (GetValueType(theValue) == DataModelDataType::Long4) {
+ SLong4 theDataValue = get<SLong4>(theValue);
+ CUICDMInstanceHandle theInstance = FindInstanceByGUID(theDataValue);
+ if (theInstance.Valid() == false)
+ theValueStr = L"";
+ else {
+ theValueStr.assign(L"#");
+ theValueStr.append(GetInstanceId(theInstance));
+ if (m_InstanceSet.find(theInstance) == m_InstanceSet.end())
+ m_ExternalReferences.insert(theInstance);
+ }
+ } else {
+ m_TempBuffer.clear();
+ WCharTWriter theWriter(m_TempBuffer);
+ WStrOps<SValue>().ToBuf(theValue, theWriter);
+
+ if (GetValueType(theValue) == DataModelDataType::String || m_TempBuffer.size()) {
+ char buffer[] = { 0, 0, 0, 0 };
+ m_TempBuffer.write(buffer, 4);
+ theValueStr.assign((const wchar_t *)m_TempBuffer.begin());
+ }
+ }
+ return theValueStr.wide_str();
+ }
+
+ SValue ParseValue(DataModelDataType::Value inType, TCharPtr inValue)
+ {
+ if (IsTrivial(inValue)) {
+ SValue retval;
+ SetDefault(inType, retval);
+ return retval;
+ }
+
+ if (inType == DataModelDataType::ObjectRef)
+ return ParseObjectRef(inValue);
+
+ if (inType == DataModelDataType::StringOrInt) {
+ if (inValue[0] == '#') {
+ CUICDMSlideHandle theSlide = GetSlideById(inValue + 1);
+ QT3DS_ASSERT(theSlide.Valid());
+ return SStringOrInt((long)theSlide.GetHandleValue());
+ } else
+ return SStringOrInt(std::make_shared<CDataStr>(inValue));
+ }
+
+ qt3ds::foundation::ConvertUTF(
+ reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(inValue), 0,
+ m_ConvertStr);
+ // Create a destructible value
+ m_ValueBuffer.clear();
+ m_ValueBuffer.write(m_ConvertStr.c_str(), m_ConvertStr.size() + 1);
+ // Clear the destination buffer
+ m_TempBuffer.clear();
+
+ DataModelDataType::Value theParseType(inType);
+ if (inType == DataModelDataType::Long4)
+ theParseType = DataModelDataType::StringRef;
+
+ WCharTReader theReader((char8_t *)m_ValueBuffer.begin(), m_TempBuffer, m_StringTable);
+ SValue retval = WStrOps<SValue>().BufTo(theParseType, theReader);
+
+ if (inType == DataModelDataType::Long4) {
+ SLong4 theFinalValue;
+ SStringRef theRef(get<SStringRef>(retval));
+ CUICDMInstanceHandle theRefInstance(GetInstanceById(theRef.m_Id));
+ if (theRefInstance.Valid()) {
+ THandleToGUIDMap::iterator theGuidFind = m_HandleToGUIDMap.find(theRefInstance);
+ if (theGuidFind != m_HandleToGUIDMap.end())
+ theFinalValue = theGuidFind->second;
+ }
+ return theFinalValue;
+ }
+ return retval;
+ }
+ const wchar_t *WriteObjectRef(const SObjectRefType &inValue, TCharStr &ioValueStr)
+ {
+ return WriteDataModelValue(SValue(inValue), ioValueStr);
+ }
+
+ SObjectRefType ParseObjectRef(TCharPtr inValue)
+ {
+ // One of two things, either an ID reference *or* pure string.
+ if (IsTrivial(inValue))
+ return SObjectRefType(SLong4());
+ if (inValue[0] == '#') {
+ // absolute reference.
+ CUICDMInstanceHandle theInstance = GetInstanceById(inValue + 1);
+ return theInstance.Valid() ? GetInstanceGuid(theInstance) : 0;
+ } else {
+ return std::make_shared<CDataStr>(inValue);
+ }
+ }
+
+ void SerializePropertyList(UICDM::IDOMWriter &inWriter, TPropertyHandleValuePairList &inList)
+ {
+ sort(inList.begin(), inList.end(), SAttributeNameSorter(m_DataCore));
+
+ TCharStr theValueStr;
+
+ for (size_t idx = 0, end = inList.size(); idx < end; ++idx) {
+ const pair<CUICDMPropertyHandle, SValue> &theValue(inList[idx]);
+ TCharStr theName(m_DataCore.GetProperty(theValue.first).m_Name);
+ WriteDataModelValue(theValue.second, theValueStr);
+ if (GetValueType(theValue.second) == DataModelDataType::String || theValueStr.size())
+ inWriter.Att(theName.wide_str(), theValueStr.wide_str());
+ }
+ }
+
+ struct SAnimationHandleLessThan
+ {
+ IDataCore &m_DataCore;
+ IAnimationCore &m_AnimationCore;
+ SAnimationHandleLessThan(IDataCore &inDC, IAnimationCore &inAc)
+ : m_DataCore(inDC)
+ , m_AnimationCore(inAc)
+ {
+ }
+
+ inline bool operator()(CUICDMAnimationHandle lhs, CUICDMAnimationHandle rhs) const
+ {
+ SAnimationInfo lhsInfo(m_AnimationCore.GetAnimationInfo(lhs));
+ SAnimationInfo rhsInfo(m_AnimationCore.GetAnimationInfo(rhs));
+ const SUICDMPropertyDefinition &theLhsDef(m_DataCore.GetProperty(lhsInfo.m_Property));
+ const SUICDMPropertyDefinition &theRhsDef(m_DataCore.GetProperty(rhsInfo.m_Property));
+ int theComparison = theLhsDef.m_Name.compare(theRhsDef.m_Name);
+ if (theComparison == 0)
+ return lhsInfo.m_Index < rhsInfo.m_Index;
+ return theComparison < 0;
+ }
+ };
+
+ void SerializeAnimations(IDOMWriter &inWriter, TAnimationHandleList &inAnimations)
+ {
+ TKeyframeHandleList theKeyframes;
+ vector<float> theValues;
+ std::stable_sort(inAnimations.begin(), inAnimations.end(),
+ SAnimationHandleLessThan(m_DataCore, m_AnimationCore));
+ for (size_t idx = 0, end = inAnimations.size(); idx < end; ++idx) {
+ theKeyframes.clear();
+ theValues.clear();
+
+ IDOMWriter::Scope __animScope(inWriter, L"AnimationTrack");
+
+ SAnimationInfo theInfo(m_AnimationCore.GetAnimationInfo(inAnimations[idx]));
+ CUICDMMetaDataPropertyHandle theMetaDataProperty =
+ m_MetaData.GetMetaDataProperty(theInfo.m_Instance, theInfo.m_Property);
+ if (theMetaDataProperty.Valid() == false)
+ continue;
+
+ SMetaDataPropertyInfo thePropertyInfo(
+ m_MetaData.GetMetaDataPropertyInfo(theMetaDataProperty));
+ wstring theName = thePropertyInfo.m_Name.wide_str();
+ size_t theArity = get<1>(GetDatatypeAnimatableAndArity(thePropertyInfo.GetDataType()));
+ if (theArity > 1) {
+ theName.append(L".");
+ switch (theInfo.m_Index) {
+ case 0:
+ theName.append(L"x");
+ break;
+ case 1:
+ theName.append(L"y");
+ break;
+ case 2:
+ theName.append(L"z");
+ break;
+ case 3:
+ theName.append(L"w");
+ break;
+ }
+ }
+ inWriter.Att(L"property", theName.c_str());
+ inWriter.Att(L"type", theInfo.m_AnimationType);
+
+ if (theInfo.m_DynamicFirstKeyframe)
+ inWriter.Att(L"dynamic", true);
+
+ if (!theInfo.m_ArtistEdited)
+ inWriter.Att(L"artistedited", theInfo.m_ArtistEdited);
+
+ m_AnimationCore.GetKeyframes(inAnimations[idx], theKeyframes);
+
+ switch (theInfo.m_AnimationType) {
+ case EAnimationTypeLinear:
+ WriteKeyframes<SLinearKeyframe>(theKeyframes, m_AnimationCore, theValues);
+ break;
+ case EAnimationTypeBezier:
+ WriteKeyframes<SBezierKeyframe>(theKeyframes, m_AnimationCore, theValues);
+ break;
+ case EAnimationTypeEaseInOut:
+ WriteKeyframes<SEaseInEaseOutKeyframe>(theKeyframes, m_AnimationCore, theValues);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ if (theValues.size()) {
+ m_TempBuffer.clear();
+ WCharTWriter theWriter(m_TempBuffer);
+ theWriter.Write(toConstDataRef(&theValues[0], (QT3DSU32)theValues.size()), 30,
+ inWriter.GetTabs() + 1);
+ wchar_t buffer = L'\0';
+ theWriter.Write(buffer);
+ inWriter.Value((const wchar_t *)m_TempBuffer.begin());
+ }
+ }
+ }
+
+ void ParseAnimation(IDOMReader &inReader, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+ {
+ IDOMReader::Scope __animScope(inReader);
+ EAnimationType theAnimationType;
+ TCharStr thePropertyName;
+ bool firstKeyframeDynamic = false;
+
+ inReader.Att(L"property", thePropertyName);
+ inReader.Att(L"type", theAnimationType);
+ inReader.Att(L"dynamic", firstKeyframeDynamic);
+ bool artistEdited;
+ if (!inReader.Att(L"artistedited", artistEdited))
+ artistEdited = true;
+
+ uint32_t subIndex = 0;
+ uint32_t theSeparator = thePropertyName.rfind('.');
+ if (theSeparator != TCharStr::npos) {
+ wchar_t theEndItem = thePropertyName[theSeparator + 1];
+ thePropertyName = thePropertyName.substr(0, theSeparator);
+ switch (theEndItem) {
+ // sub index is already 0
+ case 'x':
+ case 'r':
+ break;
+ case 'y':
+ case 'g':
+ subIndex = 1;
+ break;
+ case 'z':
+ case 'b':
+ subIndex = 2;
+ break;
+ case 'w':
+ case 'a':
+ subIndex = 3;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ CUICDMMetaDataPropertyHandle theProperty =
+ m_MetaData.GetMetaDataProperty(inInstance, thePropertyName);
+ if (theProperty.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SMetaDataPropertyInfo theInfo(m_MetaData.GetMetaDataPropertyInfo(theProperty));
+ std::tuple<bool, size_t> theAnimAndArity = GetDatatypeAnimatableAndArity(theInfo.GetDataType());
+ if (std::get<0>(theAnimAndArity) == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (std::get<1>(theAnimAndArity) <= subIndex) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ // When duplicating a slide the system will copy values from the master slide to the child
+ // slide.
+ // Then it will expect the file saved out to apply itself to the child slide. If the source
+ // slide
+ // has an animation in this slot then it is conceivable the animation here already exists,
+ // and we really
+ // just need to apply the properties and keyframes we read from the file to this animation.
+ // This hack fix should only apply to instances where we have an active slide (i.e.
+ // duplicate slide).
+ if (m_ActiveSlide == inSlide) {
+ // Simple way of overriding all animation info: Delete the object and re-create.
+ CUICDMAnimationHandle animHandle =
+ m_AnimationCore.GetAnimation(inSlide, inInstance, theInfo.m_Property, subIndex);
+ if (animHandle.Valid() == true)
+ m_AnimationCore.DeleteAnimation(animHandle);
+ }
+ CUICDMAnimationHandle theAnimation =
+ m_AnimationCore.CreateAnimation(inSlide, inInstance, theInfo.m_Property, subIndex,
+ theAnimationType, firstKeyframeDynamic);
+ m_ValueBuffer.clear();
+ m_TempBuffer.clear();
+ const char8_t *theElemValue;
+ inReader.Value(theElemValue);
+ if (!IsTrivial(theElemValue)) {
+ // Create temporary we can destructively parse
+ // Create a destructible value
+ m_ValueBuffer.clear();
+ m_ValueBuffer.write(theElemValue, (QT3DSU32)strlen(theElemValue) + 1);
+ // Clear the destination buffer
+ m_TempBuffer.clear();
+ NVConstDataRef<float> theFloatValues;
+ WCharTReader theReader((char8_t *)m_ValueBuffer.begin(), m_TempBuffer, m_StringTable);
+ theReader.ReadBuffer(theFloatValues);
+ const float *theStart = theFloatValues.begin(), *theEnd = theFloatValues.end();
+ switch (theAnimationType) {
+ case EAnimationTypeLinear:
+ ReadKeyframes<SLinearKeyframe>(theAnimation, m_AnimationCore, theStart, theEnd);
+ break;
+ case EAnimationTypeBezier:
+ ReadKeyframes<SBezierKeyframe>(theAnimation, m_AnimationCore, theStart, theEnd);
+ break;
+ case EAnimationTypeEaseInOut:
+ ReadKeyframes<SEaseInEaseOutKeyframe>(theAnimation, m_AnimationCore, theStart,
+ theEnd);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ m_AnimationCore.SetIsArtistEdited(theAnimation, artistEdited);
+ }
+
+ void SerializeAction(IDOMWriter &inWriter, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance, CUICDMActionHandle inAction)
+ {
+ TCharStr valueStr;
+ IDOMWriter::Scope __actionScope(inWriter, L"Action");
+
+ CUICDMActionHandle theAction(inAction);
+ SActionInfo theInfo(m_ActionCore.GetActionInfo(theAction));
+ inWriter.Att(L"id", GetActionId(theAction, inSlide, inInstance));
+ bool eyeball = m_ActionSystem.GetActionEyeballValue(inSlide, theAction);
+ inWriter.Att(L"eyeball", eyeball);
+
+ WriteObjectRef(theInfo.m_TriggerObject, valueStr);
+ inWriter.Att(L"triggerObject", valueStr);
+
+ if (theInfo.m_Event.size())
+ inWriter.Att(L"event", theInfo.m_Event.c_str());
+
+ WriteObjectRef(theInfo.m_TargetObject, valueStr);
+ inWriter.Att(L"targetObject", valueStr);
+
+ if (theInfo.m_Handler.size()) {
+ inWriter.Att(L"handler", theInfo.m_Handler.c_str());
+
+ for (size_t handlerArgIdx = 0, handlerArgEnd = theInfo.m_HandlerArgs.size();
+ handlerArgIdx < handlerArgEnd; ++handlerArgIdx) {
+ SHandlerArgumentInfo theArgInfo(
+ m_ActionCore.GetHandlerArgumentInfo(theInfo.m_HandlerArgs[handlerArgIdx]));
+ IDOMWriter::Scope argScope(inWriter, L"HandlerArgument");
+ inWriter.Att(L"name", theArgInfo.m_Name);
+
+ DataModelDataType::Value theArgType(GetValueType(theArgInfo.m_Value));
+ SValue theArgValue(theArgInfo.m_Value);
+ if (theArgInfo.m_ArgType == HandlerArgumentType::Event) {
+ theArgType = DataModelDataType::String;
+ auto theEventHandle = get<qt3ds::QT3DSI32>(theArgInfo.m_Value);
+ theArgValue = SValue(std::make_shared<CDataStr>(
+ m_MetaData.GetEventInfo(theEventHandle)->m_Name.wide_str()));
+ }
+
+ if (theArgType != DataModelDataType::Float)
+ inWriter.Att(L"type", theArgType);
+ if (theArgInfo.m_ArgType != HandlerArgumentType::None)
+ inWriter.Att(L"argtype", theArgInfo.m_ArgType);
+
+ SValue theDefault;
+ SetDefault(theArgType, theDefault);
+ if (!Equals(theArgInfo.m_Value, theDefault)) {
+ WriteDataModelValue(theArgValue, valueStr);
+ inWriter.Att(L"value", valueStr);
+ }
+ }
+ }
+ }
+
+ void SerializeActions(IDOMWriter &inWriter, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance, TActionHandleList &inActions)
+ {
+ // We sort the actions just by action handle. This keeps the file in the same order because
+ // actions are created in file order and their handle values increment monotonically.
+ std::stable_sort(inActions.begin(), inActions.end(), std::less<int>());
+ for (size_t idx = 0, end = inActions.size(); idx < end; ++idx) {
+ SerializeAction(inWriter, inSlide, inInstance, inActions[idx]);
+ }
+ }
+
+ CUICDMInstanceHandle ResolveObjectRef(CUICDMInstanceHandle inInstance,
+ const SObjectRefType &inRef)
+ {
+ if (inRef.GetReferenceType() == ObjectReferenceType::Absolute) {
+ SLong4 theGuid = get<SLong4>(inRef.m_Value);
+ if (theGuid.Valid())
+ return FindInstanceByGUID(theGuid);
+ return 0;
+ }
+ TDataStrPtr theStrPtr(get<TDataStrPtr>(inRef.m_Value));
+ if (theStrPtr == NULL)
+ return 0;
+ wstring theParseStr(theStrPtr->GetData());
+
+ // Get rid of this or this. since it's referrng to inInstance
+ wstring theThisStr(L"this");
+ if (theParseStr.substr(0, theThisStr.size()) == theThisStr) {
+ theParseStr = theParseStr.substr(theThisStr.size());
+ if (theParseStr[0] == L'.')
+ theParseStr = theParseStr.substr(1);
+ }
+
+ wstring theParentStr(L"parent.");
+ CUICDMInstanceHandle theSourceInstance(inInstance);
+ while (theParseStr.find(theParentStr) != wstring::npos) {
+ CUICDMInstanceHandle theParentInstance = m_AssetGraph.GetParent(inInstance);
+ // this check is here since scene has no parent, see Bug#6532
+ if (theParentInstance.Valid())
+ theSourceInstance = theParentInstance;
+ else
+ return CUICDMInstanceHandle(0);
+ theParseStr = theParseStr.substr(theParentStr.size());
+ }
+ while (theParseStr.size()) {
+ wstring::size_type periodPos = theParseStr.find('.');
+ wstring theNameStr = theParseStr;
+ if (periodPos != wstring::npos) {
+ theNameStr = theParseStr.substr(0, periodPos);
+ theParseStr = theParseStr.substr(periodPos + 1);
+ } else
+ theParseStr = L"";
+ CUICDMInstanceHandle theParent(theSourceInstance);
+ bool theFound = false;
+ for (long childIdx = 0, childEnd = m_AssetGraph.GetChildCount(theSourceInstance);
+ childIdx < childEnd && !theFound; ++childIdx) {
+ CUICDMInstanceHandle theChild = m_AssetGraph.GetChild(theSourceInstance, childIdx);
+ if (theNameStr == GetInstanceName(theChild)) {
+ theSourceInstance = theChild;
+ theFound = true;
+ }
+ }
+ if (!theFound)
+ return CUICDMInstanceHandle(0);
+ }
+ return theSourceInstance;
+ }
+
+ CUICDMActionHandle ParseAction(IDOMReader &inReader, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+ {
+ IDOMReader::Scope __actionScope(inReader);
+ CUICDMActionHandle theAction;
+ TCharPtr theActionId;
+ bool isRef = false;
+ if (inReader.Att(L"id", theActionId)) {
+ theAction = m_ActionSystem.CreateAction(inSlide, inInstance, SLong4());
+ AddActionId(theActionId, theAction);
+ } else if (inReader.Att(L"ref", theActionId)) {
+ theAction = GetActionById(theActionId + 1);
+ isRef = true;
+ }
+ bool eyeball = false;
+ inReader.Att(L"eyeball", eyeball);
+ m_ActionSystem.SetActionEyeballValue(inSlide, theAction, eyeball);
+ // Referenced actions can only set eyeball property on various slides, they can't
+ // set anything else, so we can return safely here.
+ if (isRef)
+ return theAction;
+
+ const wchar_t *tempStr;
+ if (inReader.Att(L"triggerObject", tempStr))
+ m_ActionCore.SetTriggerObject(theAction, ParseObjectRef(tempStr));
+ if (inReader.Att(L"event", tempStr))
+ m_ActionCore.SetEvent(theAction, tempStr);
+ SObjectRefType theTargetRef;
+ if (inReader.Att(L"targetObject", tempStr)) {
+ theTargetRef = ParseObjectRef(tempStr);
+ m_ActionCore.SetTargetObject(theAction, theTargetRef);
+ }
+
+ CUICDMHandlerHandle theHandler;
+ if (inReader.Att(L"handler", tempStr)) {
+ m_ActionCore.SetHandler(theAction, tempStr);
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ TCharStr theName;
+ inReader.Att(L"name", theName);
+ DataModelDataType::Value theDataType(DataModelDataType::Float);
+ inReader.Att(L"type", theDataType);
+ HandlerArgumentType::Value theArgType(HandlerArgumentType::None);
+ inReader.Att(L"argtype", theArgType);
+
+ tempStr = NULL;
+ inReader.UnregisteredAtt(L"value", tempStr);
+ SValue theValue = ParseValue(theDataType, tempStr);
+ if (theArgType == HandlerArgumentType::Event) {
+ TDataStrPtr theStr;
+ if (GetValueType(theValue) == DataModelDataType::String)
+ theStr = get<TDataStrPtr>(theValue);
+ if (theStr) {
+ CUICDMInstanceHandle theTargetInstance =
+ ResolveObjectRef(inInstance, theTargetRef);
+ CUICDMEventHandle theEvent = 0;
+ if (theTargetInstance.Valid())
+ theEvent = m_MetaData.FindEvent(theTargetInstance, theStr->GetData());
+ theValue = SValue((qt3ds::QT3DSI32) theEvent);
+ }
+ }
+
+ CUICDMHandlerArgHandle theArgHandle = m_ActionCore.AddHandlerArgument(
+ theAction, theName.wide_str(), theArgType, theDataType);
+ m_ActionCore.SetHandlerArgumentValue(theArgHandle, theValue);
+ }
+ }
+ return theAction;
+ }
+
+ void GetInstanceSlideInformation(CUICDMInstanceHandle inInstance, CUICDMSlideHandle inSlide,
+ CUICDMSlideHandle inSlideParent,
+ TPropertyHandleValuePairList &ioValues,
+ TAnimationHandleList &ioAnimations,
+ TActionHandleList &ioActions)
+ {
+ m_SlideCore.GetSpecificInstancePropertyValues(inSlide, inInstance, ioValues);
+ m_AnimationCore.GetSpecificInstanceAnimations(inSlide, inInstance, ioAnimations);
+ m_ActionCore.GetActions(inSlide, inInstance, ioActions);
+
+ // During Partial serialization we pull parent properties and such up onto the active
+ // slide during write process, overriding where necessary
+ if (inSlideParent.Valid()) {
+ TPropertyHandleValuePairList theParentValues;
+ TAnimationHandleList theParentAnimations;
+ TActionHandleList theParentActions;
+
+ m_SlideCore.GetSpecificInstancePropertyValues(inSlideParent, inInstance,
+ theParentValues);
+ m_AnimationCore.GetSpecificInstanceAnimations(inSlideParent, inInstance,
+ theParentAnimations);
+ m_ActionCore.GetActions(inSlideParent, inInstance, theParentActions);
+
+ // Ensure the current slide values override the parent slide values.
+ for (size_t idx = 0, end = theParentValues.size(); idx < end; ++idx)
+ insert_unique_if(ioValues, theParentValues[idx],
+ SPropertyMatcher(theParentValues[idx].first));
+
+ for (size_t idx = 0, end = theParentAnimations.size(); idx < end; ++idx)
+ insert_unique_if(ioAnimations, theParentAnimations[idx],
+ SAnimationMatcher(m_AnimationCore, theParentAnimations[idx]));
+
+ // And we just blindly copy over all the actions because actions can't override each
+ // other.
+ ioActions.insert(ioActions.end(), theParentActions.begin(), theParentActions.end());
+ }
+
+ SanitizeHandleValuePairList(inInstance, ioValues);
+ CUICDMPropertyHandle *theUnlinked(
+ IDocumentEditor::GetAlwaysUnlinkedProperties(m_ObjectDefinitions));
+ // Note that we are explicitly re-querying the iovalues size.
+ for (size_t idx = 0; idx < ioValues.size(); ++idx) {
+ CUICDMPropertyHandle theProperty(ioValues[idx].first);
+ for (CUICDMPropertyHandle *theHandle = theUnlinked; theHandle->Valid(); ++theHandle) {
+ if (theProperty == *theHandle
+ && Equals(ioValues[idx].second.toOldSkool(),
+ m_MetaData.GetDefaultValue(inInstance, theProperty).toOldSkool())) {
+ ioValues.erase(ioValues.begin() + idx);
+ --idx;
+ }
+ }
+ }
+ }
+
+ TCharPtr GetSlideName(CUICDMSlideHandle inSlide)
+ {
+ if (inSlide.Valid() == false)
+ return L"";
+ CUICDMInstanceHandle theSlideInstance(m_SlideCore.GetSlideInstance(inSlide));
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(theSlideInstance,
+ m_ObjectDefinitions.m_Named.m_NameProp, theValue)) {
+ TDataStrPtr theName = get<TDataStrPtr>(theValue);
+ if (theName)
+ return theName->GetData();
+ }
+ return L"";
+ }
+
+ CUICDMSlideHandle GetAssociatedSlide(CUICDMInstanceHandle inInstance)
+ {
+ if (inInstance.Valid() == false)
+ return 0;
+ CUICDMSlideHandle theAssociatedSlide = m_SlideSystem.GetAssociatedSlide(inInstance);
+ if (theAssociatedSlide == m_ActiveSlideParent)
+ return m_ActiveSlide;
+ return theAssociatedSlide;
+ }
+ // Properties that should never be written out to a file.
+ struct SInvalidProperytEqual
+ {
+ SComposerObjectDefinitions &m_ObjectDefinitions;
+ bool m_IsImageOrMaterial;
+ SInvalidProperytEqual(SComposerObjectDefinitions &inDefs, bool inIsImageOrMaterial)
+ : m_ObjectDefinitions(inDefs)
+ , m_IsImageOrMaterial(inIsImageOrMaterial)
+ {
+ }
+ bool IsGeneralInvalidProperty(CUICDMPropertyHandle inProperty) const
+ {
+ return inProperty == m_ObjectDefinitions.m_Guided.m_GuidProp
+ || inProperty == m_ObjectDefinitions.m_Asset.m_FileId;
+ }
+ bool IsImageOrMaterialInvalidProperty(CUICDMPropertyHandle inProperty) const
+ {
+ return inProperty == m_ObjectDefinitions.m_Asset.m_StartTime
+ || inProperty == m_ObjectDefinitions.m_Asset.m_EndTime;
+ }
+
+ bool operator()(const TPropertyHandleValuePair &inProperty) const
+ {
+ return IsGeneralInvalidProperty(inProperty.first)
+ || (m_IsImageOrMaterial && IsImageOrMaterialInvalidProperty(inProperty.first));
+ }
+ };
+
+ void SanitizeHandleValuePairList(CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outList)
+ {
+ bool isImageOrMaterial =
+ m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_ObjectDefinitions.m_Image.m_Instance)
+ || m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_Material.m_Instance);
+ erase_if(outList, SInvalidProperytEqual(m_ObjectDefinitions, isImageOrMaterial));
+ }
+
+ void GetSpecificInstancePropertyValues(CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outList)
+ {
+ m_DataCore.GetSpecificInstancePropertyValues(inInstance, outList);
+ SanitizeHandleValuePairList(inInstance, outList);
+ }
+ void GetSlidePropertyValues(CUICDMSlideHandle inSlide, TPropertyHandleValuePairList &outList)
+ {
+ CUICDMInstanceHandle theSlideInstance(m_SlideCore.GetSlideInstance(inSlide));
+ if (theSlideInstance.Valid() == false)
+ return;
+
+ m_DataCore.GetSpecificInstancePropertyValues(theSlideInstance, outList);
+ erase_if(outList, SPropertyMatches(m_ObjectDefinitions.m_Slide.m_ComponentId));
+ erase_if(outList, SPropertyMatches(m_ObjectDefinitions.m_Named.m_NameProp));
+ erase_if(outList, SPropertyMatches(m_ObjectDefinitions.m_Typed.m_TypeProp));
+ }
+
+ Option<pair<CUICDMPropertyHandle, SValue>> ParseValue(CUICDMInstanceHandle inInstance,
+ TCharPtr inPropName, TCharPtr inValue)
+ {
+ CUICDMPropertyHandle theProperty =
+ m_DataCore.GetAggregateInstancePropertyByName(inInstance, inPropName);
+ if (theProperty.Valid() == false) {
+ return Empty();
+ }
+ DataModelDataType::Value theType = m_DataCore.GetProperty(theProperty).m_Type;
+ return make_pair(theProperty, ParseValue(theType, inValue));
+ }
+
+ void ParseInstanceProperties(IDOMReader &inReader, CUICDMInstanceHandle inInstance,
+ vector<pair<TCharPtr, TCharPtr>> &outExtraAttributes,
+ TPropertyHandleValuePairList &outProperties)
+ {
+ bool hasNoLifetime =
+ m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_ObjectDefinitions.m_Image.m_Instance)
+ || m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_Material.m_Instance);
+
+ bool checkConversionToV3LayerFormat = false;
+ if (m_UIPVersion.hasValue() && *m_UIPVersion < 3
+ && m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_Layer.m_Instance))
+ checkConversionToV3LayerFormat = true;
+
+ for (eastl::pair<TCharPtr, TCharPtr> theAtt = inReader.GetFirstAttribute();
+ !IsTrivial(theAtt.first); theAtt = inReader.GetNextAttribute()) {
+ Option<pair<CUICDMPropertyHandle, SValue>> theValue =
+ ParseValue(inInstance, theAtt.first, theAtt.second);
+ bool ignoreProperty = theValue.hasValue() == false
+ || (hasNoLifetime
+ && (theValue->first == m_ObjectDefinitions.m_Asset.m_StartTime.m_Property
+ || theValue->first == m_ObjectDefinitions.m_Asset.m_EndTime.m_Property));
+ if (ignoreProperty) {
+ bool keepProperty = true;
+ if (checkConversionToV3LayerFormat) {
+ if (AreEqual(theAtt.first, L"location") || AreEqual(theAtt.first, L"size")) {
+ keepProperty = false;
+ SValue theValueUnion = ParseValue(DataModelDataType::Float2, theAtt.second);
+ SFloat2 theValue(theValueUnion.getData<SFloat2>());
+ SValue theFirstValue(theValue.m_Floats[0]);
+ SValue theSecondValue(theValue.m_Floats[1]);
+ if (AreEqual(theAtt.first, L"location")) {
+ CUICDMPropertyHandle theLeft, theTop;
+ theLeft =
+ m_DataCore.GetAggregateInstancePropertyByName(inInstance, L"left");
+ theTop =
+ m_DataCore.GetAggregateInstancePropertyByName(inInstance, L"top");
+ outProperties.push_back(std::make_pair(theLeft, theFirstValue));
+ outProperties.push_back(std::make_pair(theTop, theSecondValue));
+ } else {
+ CUICDMPropertyHandle theWidth, theHeight;
+ theWidth =
+ m_DataCore.GetAggregateInstancePropertyByName(inInstance, L"width");
+ theHeight = m_DataCore.GetAggregateInstancePropertyByName(inInstance,
+ L"height");
+ outProperties.push_back(std::make_pair(theWidth, theFirstValue));
+ outProperties.push_back(std::make_pair(theHeight, theSecondValue));
+ }
+ }
+ }
+ if (keepProperty)
+ outExtraAttributes.push_back(std::make_pair(theAtt.first, theAtt.second));
+ } else
+ outProperties.push_back(std::make_pair(theValue->first, theValue->second));
+ }
+ }
+
+ void ParseAndSetInstanceProperties(IDOMReader &inReader, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ vector<pair<TCharPtr, TCharPtr>> &outExtraAttributes,
+ TPropertyHandleValuePairList &ioProperties)
+ {
+ outExtraAttributes.clear();
+ ioProperties.clear();
+
+ ParseInstanceProperties(inReader, inInstance, outExtraAttributes, ioProperties);
+ if (inSlide.Valid()) {
+ for (size_t idx = 0, end = ioProperties.size(); idx < end; ++idx)
+ m_SlideCore.ForceSetInstancePropertyValue(inSlide, inInstance,
+ ioProperties[idx].first,
+ ioProperties[idx].second.toOldSkool());
+ } else {
+ for (size_t idx = 0, end = ioProperties.size(); idx < end; ++idx)
+ m_DataCore.SetInstancePropertyValue(inInstance, ioProperties[idx].first,
+ ioProperties[idx].second);
+ }
+ }
+
+ pair<CUICDMSlideHandle, CUICDMInstanceHandle> CreateSlide()
+ {
+ CUICDMInstanceHandle slideInstance = m_DataCore.CreateInstance();
+ m_DataCore.DeriveInstance(slideInstance, m_ObjectDefinitions.m_Slide.m_Instance);
+ CUICDMSlideHandle masterSlide = m_SlideCore.CreateSlide(slideInstance);
+ return make_pair(masterSlide, slideInstance);
+ }
+
+ // Monster function that writes out all instance information. There are a lot of rules
+ // observed here, mainly so we don't write out more than we have to.
+ // An instance is in a default scope (the scope of its parent) unless it has a "slide" property.
+ // Its properties within that scope are written as attributes and any animations or actions
+ // added as direct children are in the default scope.
+ // A slide owner system may declare a master slide child in which case the master slide now
+ // because the default scope. This element is also necessary to unambiguously state the order
+ // of all slide children.
+ // The element may then declare slides as children where sub-slide-specific information goes.
+ // Finally, the element's scene graph children will be declared.
+ bool Serialize(IDOMWriter &inWriter, CUICDMInstanceHandle inInstance, bool inWriteParentRefs)
+ {
+ if (m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_ObjectDefinitions.m_Asset.m_Instance)
+ == false
+ && m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_PathAnchorPoint.m_Instance)
+ == false)
+ return false;
+
+ Option<TCharStr> theType = m_MetaData.GetTypeForInstance(inInstance);
+ if (theType.hasValue() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ wstring theMasterRef;
+
+ TInstanceHandleList theParents;
+ m_DataCore.GetInstanceParents(inInstance, theParents);
+
+ // For non-canonical parents (meaning parents that are setup at runtime
+ // during normal project operations
+ // we need to save them out into the master classes section
+ QT3DS_ASSERT(theParents.size() == 1);
+ if (!theParents.empty()) {
+ Option<TCharStr> theCanonicalType =
+ m_MetaData.GetTypeForCanonicalInstance(theParents[0]);
+ // Meaning this isn't a canonical instance
+ if (theCanonicalType.hasValue() == false) {
+ CUICDMInstanceHandle theMaster(theParents[0]);
+ m_MasterObjectsSet.insert(theParents[0]);
+ theMasterRef = L"#";
+ theMasterRef.append(GetInstanceId(theMaster));
+ }
+ }
+
+ IDOMWriter::Scope __instanceScope(inWriter, theType->wide_str());
+ inWriter.Att(L"id", GetInstanceId(inInstance));
+
+ m_InstanceSet.insert(inInstance);
+
+ CUICDMSlideHandle theAssociatedSlide = GetAssociatedSlide(inInstance);
+
+ if (theAssociatedSlide.Valid())
+ m_SlideSet.insert(theAssociatedSlide);
+
+ bool isSlideOwner = m_DataCore.IsInstanceOrDerivedFrom(
+ inInstance, m_ObjectDefinitions.m_SlideOwner.m_Instance);
+ if (isSlideOwner) {
+ // Ensure we mark all of those slides.
+ SLong4 theGuid = GetGuid(inInstance, m_ObjectDefinitions.m_Guided.m_GuidProp);
+ CUICDMSlideHandle theMasterSlide = m_SlideSystem.GetMasterSlideByComponentGuid(theGuid);
+ if (theMasterSlide.Valid()) {
+ TSlideHandleList theChildSlides;
+ m_SlideCore.GetChildSlides(theMasterSlide, theChildSlides);
+ m_SlideSet.insert(theMasterSlide);
+ for (size_t slideIdx = 0, slideEnd = theChildSlides.size(); slideIdx < slideEnd;
+ ++slideIdx)
+ m_SlideSet.insert(theChildSlides[slideIdx]);
+ }
+ }
+ /////////////////////////////////////////////////////////////////////////
+ /// Write out object attributes
+ ////////////////////////////////////////////////////////////////////////
+
+ // Write out the properties for the active slide.
+ TPropertyHandleValuePairList theValues;
+ GetSpecificInstancePropertyValues(inInstance, theValues);
+ SerializePropertyList(inWriter, theValues);
+
+ if (theMasterRef.size())
+ inWriter.Att(L"class", theMasterRef.c_str());
+
+ if (inWriteParentRefs) {
+ CUICDMInstanceHandle theParent(m_AssetGraph.GetParent(inInstance));
+ if (theParent.Valid()) {
+ wstring theParentRef(L"#");
+ theParentRef.append(GetInstanceId(theParent));
+ m_ExternalReferences.insert(theParent);
+ inWriter.Att(L"graphparent", theParentRef.c_str());
+ }
+
+ CUICDMInstanceHandle theSibling = m_AssetGraph.GetSibling(inInstance, true);
+ if (theSibling.Valid()) {
+ wstring theSiblingRef(L"#");
+ theSiblingRef.append(GetInstanceId(theSibling));
+ m_ExternalReferences.insert(theSibling);
+ inWriter.Att(L"graphsibling", theSiblingRef.c_str());
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////
+ // Write out the graph children of this instance.
+ CGraphIterator theChildren;
+
+ // We only duplicate things you can see, so if you are on a master slide
+ // we only duplicate master children.
+ TSlideHandleList theActiveSlideChildren;
+ if (m_ActiveSlide.Valid())
+ m_SlideCore.GetChildSlides(m_ActiveSlide, theActiveSlideChildren);
+
+ m_AssetGraph.GetChildren(theChildren, inInstance.GetHandleValue());
+ for (; theChildren.IsDone() == false; ++theChildren) {
+ bool isNonmasterActiveSlideChild = false;
+ if (theActiveSlideChildren.size()) {
+ // If we a copying from a master slide, we don't want nonmaster
+ // only children of this object.
+ CUICDMInstanceHandle theChildHandle = theChildren.GetCurrent();
+ CUICDMSlideHandle theChildAssociatedSlide = GetAssociatedSlide(theChildHandle);
+ isNonmasterActiveSlideChild =
+ std::find(theActiveSlideChildren.begin(), theActiveSlideChildren.end(),
+ theChildAssociatedSlide)
+ != theActiveSlideChildren.end();
+ }
+ if (!isNonmasterActiveSlideChild)
+ Serialize(inWriter, theChildren.GetCurrent(), false);
+ }
+
+ return true;
+ }
+
+ // Pass 1 creates all the instances and registeres
+ UICDM::TInstanceHandleList
+ CreateAndRegisterInstances(IDOMReader &inReader, bool inReturnInstances,
+ CUICDMInstanceHandle inParent = CUICDMInstanceHandle())
+ {
+ IDOMReader::Scope __childScope(inReader);
+ TInstanceHandleList theNewInstances;
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+
+ UICDM::CUICDMInstanceHandle theNewInstance;
+ TCharPtr theParentRef = L"";
+ if (inReader.Att(L"graphparent", theParentRef))
+ inParent = GetInstanceById(theParentRef + 1);
+ TCharPtr theSiblingRef = L"";
+ bool theSilbingExists = false;
+ if (inReader.Att(L"graphsibling", theSiblingRef))
+ theSilbingExists = true;
+
+ TCharPtr theId;
+ inReader.Att(L"id", theId);
+ TCharPtr theMasterRef;
+ if (inReader.Att(L"class", theMasterRef) && GetInstanceById(theMasterRef + 1).Valid()) {
+ theNewInstance = IDocumentEditor::CreateSceneGraphInstance(
+ GetInstanceById(theMasterRef + 1), inParent, 0, m_DataCore, m_SlideSystem,
+ m_ObjectDefinitions, m_AssetGraph, m_MetaData);
+ } else {
+ TCharPtr theType(inReader.GetElementName());
+ theNewInstance = IDocumentEditor::CreateSceneGraphInstance(
+ theType, inParent, 0, m_DataCore, m_SlideSystem, m_ObjectDefinitions,
+ m_AssetGraph, m_MetaData);
+ }
+
+ if (theSilbingExists)
+ m_NewInstancesToSiblings.insert(std::make_pair(theNewInstance, theSiblingRef + 1));
+
+ SLong4 theGuid = GetGuid(theNewInstance, m_ObjectDefinitions.m_Guided.m_GuidProp);
+ if (m_PreserveFileIds)
+ m_DataCore.SetInstancePropertyValue(theNewInstance,
+ m_ObjectDefinitions.m_Asset.m_FileId,
+ std::make_shared<CDataStr>(theId));
+ SetId(theId, theNewInstance);
+ AddGuid(theGuid, theNewInstance);
+
+ CreateAndRegisterInstances(inReader, false, theNewInstance);
+ if (inReturnInstances)
+ theNewInstances.push_back(theNewInstance);
+ }
+ return theNewInstances;
+ }
+
+ void _MoveNewInstanceToItsPlaceRecursive(CUICDMInstanceHandle inNewInstance)
+ {
+ TInstanceToSiblingMap::iterator itr = m_NewInstancesToSiblings.find(inNewInstance);
+ if (itr != m_NewInstancesToSiblings.end()) {
+ CUICDMInstanceHandle theSibling = GetInstanceById((*itr).second);
+ if (theSibling.Valid()) {
+ _MoveNewInstanceToItsPlaceRecursive(theSibling);
+
+ m_AssetGraph.MoveBefore(inNewInstance, theSibling);
+ }
+
+ m_NewInstancesToSiblings.erase(itr);
+ }
+ }
+
+ void ReadInstanceProperties(IDOMReader &inReader)
+ {
+ IDOMReader::Scope __childScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ TCharPtr theId;
+ inReader.Att(L"id", theId);
+
+ CUICDMInstanceHandle theNewInstance = GetInstanceById(theId);
+ if (theNewInstance.Valid() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ TPropertyHandleValuePairList theValues;
+ vector<pair<TCharPtr, TCharPtr>> theExtraAtts;
+ ParseAndSetInstanceProperties(inReader, 0, theNewInstance, theExtraAtts, theValues);
+ ReadInstanceProperties(inReader);
+
+ // Make the instance in the right place if it's a new instance
+ _MoveNewInstanceToItsPlaceRecursive(theNewInstance);
+ }
+ }
+
+ void WriteSlideMasterOverrides(IDOMWriter &inWriter, CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent)
+ {
+ TPropertyHandleValuePairList theValues;
+ TAnimationHandleList theAnimations;
+ TActionHandleList theMasterActions;
+ TActionHandleList theActions;
+
+ // Sometimes this gets called for action instances. In that case we should just ignore the
+ // call.
+ if (m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_ObjectDefinitions.m_Asset.m_Instance)
+ == false)
+ return;
+
+ if (inParent.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ m_ActionCore.GetActions(inParent, inInstance, theMasterActions);
+ GetInstanceSlideInformation(inInstance, inSlide, 0, theValues, theAnimations, theActions);
+
+ vector<pair<size_t, bool>> theEyeballChanges;
+ for (size_t idx = 0, end = theMasterActions.size(); idx < end; ++idx) {
+ bool masterEyeball =
+ m_ActionSystem.GetActionEyeballValue(inParent, theMasterActions[idx]);
+ bool childEyeball =
+ m_ActionSystem.GetActionEyeballValue(inSlide, theMasterActions[idx]);
+ if (masterEyeball != childEyeball)
+ theEyeballChanges.push_back(make_pair(idx, childEyeball));
+ }
+ if (theValues.size() || theAnimations.size() || theActions.size()
+ || theEyeballChanges.size()) {
+ // When we copy slides we can get into here. During normal serialization this can't
+ // happen.
+ if (inParent == m_ActiveSlideParent)
+ m_ExternalReferences.insert(inInstance);
+
+ IDOMWriter::Scope __instanceScope(inWriter, L"Set");
+ wstring theRef = GetInstanceId(inInstance);
+ theRef.insert(0, L"#");
+ inWriter.Att(L"ref", theRef.c_str());
+ SerializePropertyList(inWriter, theValues);
+ SerializeAnimations(inWriter, theAnimations);
+ SerializeActions(inWriter, inSlide, inInstance, theActions);
+ for (size_t idx = 0, end = theEyeballChanges.size(); idx < end; ++idx) {
+ CUICDMActionHandle theAction(theMasterActions[theEyeballChanges[idx].first]);
+ IDOMWriter::Scope __actionScope(inWriter, L"Action");
+ wstring theRef(L"#");
+ bool hadAction = m_ActionToIdMap.find(theAction) != m_ActionToIdMap.end();
+ theRef.append(GetActionId(theAction, inParent, inInstance));
+ inWriter.Att(L"ref", theRef.c_str());
+ inWriter.Att(L"eyeball", theEyeballChanges[idx].second);
+ if (!hadAction)
+ m_ExternalActions.insert(theAction);
+ }
+ }
+ }
+
+ void WriteSlideInstance(IDOMWriter &inWriter, CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent)
+ {
+ TPropertyHandleValuePairList theValues;
+ TAnimationHandleList theAnimations;
+ TActionHandleList theActions;
+
+ // Sometimes this gets called for action instances. In that case we should just ignore the
+ // call.
+ if (m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_ObjectDefinitions.m_Asset.m_Instance)
+ == false)
+ return;
+
+ GetInstanceSlideInformation(inInstance, inSlide, inParent, theValues, theAnimations,
+ theActions);
+ // When copying slides, we don't automatically add all the instances like we do when we
+ // cut/paste
+ const wchar_t *commandName = L"Set";
+ if (inSlide == m_ActiveSlide || inSlide == m_SlideSystem.GetAssociatedSlide(inInstance))
+ commandName = L"Add";
+
+ if (AreEqual(commandName, L"Add") || theValues.size() || theAnimations.size()
+ || theActions.size()) {
+ IDOMWriter::Scope __instanceScope(inWriter, commandName);
+ wstring theRef = GetInstanceId(inInstance);
+ theRef.insert(0, L"#");
+ inWriter.Att(L"ref", theRef.c_str());
+ SerializePropertyList(inWriter, theValues);
+ SerializeAnimations(inWriter, theAnimations);
+ SerializeActions(inWriter, inSlide, inInstance, theActions);
+ }
+ }
+
+ struct SInstanceNotInSet
+ {
+ const TInstanceSet &m_Set;
+ SInstanceNotInSet(const TInstanceSet &s)
+ : m_Set(s)
+ {
+ }
+
+ bool operator()(CUICDMInstanceHandle inInstance)
+ {
+ return m_Set.find(inInstance) == m_Set.end();
+ }
+ };
+
+ // Get the set of instances associated with a slide but filtered by our
+ // m_InstanceSet, meaning ignore instances that aren't scene graph instances
+ // and that haven't been written out.
+ void GetFilteredAssociatedInstances(CUICDMSlideHandle inSlide,
+ TInstanceHandleList &outInstances)
+ {
+ m_SlideSystem.GetAssociatedInstances(inSlide, outInstances);
+ erase_if(outInstances, SInstanceNotInSet(m_InstanceSet));
+ }
+
+ CUICDMInstanceHandle GetSlideComponent(CUICDMSlideHandle inSlide)
+ {
+ CUICDMSlideHandle theMasterSlide = m_SlideSystem.GetMasterSlide(inSlide);
+ CUICDMInstanceHandle theMasterInstance(m_SlideCore.GetSlideInstance(theMasterSlide));
+ SLong4 theComponentGuid =
+ GetGuid(theMasterInstance, m_ObjectDefinitions.m_Slide.m_ComponentId);
+ CUICDMInstanceHandle theComponent = FindInstanceByGUID(theComponentGuid);
+ return theComponent;
+ }
+
+ struct SInstanceOrderSorter
+ {
+ const TInstanceIntMap &m_DepthMap;
+ SInstanceOrderSorter(const TInstanceIntMap &inMap)
+ : m_DepthMap(inMap)
+ {
+ }
+ int GetInstanceOrder(CUICDMInstanceHandle inHdl) const
+ {
+ TInstanceIntMap::const_iterator theIter = m_DepthMap.find(inHdl);
+ if (theIter != m_DepthMap.end())
+ return theIter->second;
+ return QT3DS_MAX_I32;
+ }
+ bool operator()(CUICDMInstanceHandle lhs, CUICDMInstanceHandle rhs) const
+ {
+ return GetInstanceOrder(lhs) < GetInstanceOrder(rhs);
+ }
+ bool operator()(const std::pair<CUICDMSlideHandle, CUICDMInstanceHandle> &lhs,
+ const std::pair<CUICDMSlideHandle, CUICDMInstanceHandle> &rhs) const
+ {
+ return GetInstanceOrder(lhs.second) < GetInstanceOrder(rhs.second);
+ }
+ };
+
+ void SortSlideInstanceList(TInstanceHandleList &inInstances) const
+ {
+ std::stable_sort(inInstances.begin(), inInstances.end(),
+ SInstanceOrderSorter(m_InstanceToGraphDepthMap));
+ }
+
+ void SerializeSlides(IDOMWriter &inWriter, bool inSlideCopy = false)
+ {
+ if (m_ActiveSlide.Valid()) {
+ m_SlideSet.erase(m_ActiveSlide);
+ m_SlideSet.erase(m_ActiveSlideParent);
+
+ IDOMWriter::Scope __writeScope(inWriter, L"ActiveState");
+
+ TInstanceHandleList theInstances;
+ if (inSlideCopy == false) {
+ GetFilteredAssociatedInstances(m_ActiveSlide, theInstances);
+ SortSlideInstanceList(theInstances);
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theInstance(theInstances[idx]);
+ WriteSlideInstance(inWriter, theInstance, m_ActiveSlide, m_ActiveSlideParent);
+ }
+ } else {
+ inWriter.Att(L"name", GetSlideName(m_ActiveSlide));
+ TPropertyHandleValuePairList theValues;
+ GetSlidePropertyValues(m_ActiveSlide, theValues);
+ SerializePropertyList(inWriter, theValues);
+
+ CUICDMInstanceHandle theComponent = GetSlideComponent(m_ActiveSlide);
+
+ TInstanceHandleList theParentInstances;
+ m_SlideSystem.GetAssociatedInstances(m_ActiveSlide, theInstances);
+ theInstances.push_back(theComponent);
+ theParentInstances.push_back(theComponent);
+ if (m_ActiveSlideParent.Valid())
+ m_SlideSystem.GetAssociatedInstances(m_ActiveSlideParent, theParentInstances);
+
+ SortSlideInstanceList(theInstances);
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theInstance(theInstances[idx]);
+
+ // If this is an instance associated with master slide
+ if (find(theParentInstances.begin(), theParentInstances.end(), theInstance)
+ != theParentInstances.end())
+ WriteSlideMasterOverrides(inWriter, theInstance, m_ActiveSlide,
+ m_ActiveSlideParent);
+ else
+ WriteSlideInstance(inWriter, theInstance, m_ActiveSlide, 0);
+ }
+ }
+ } // m_ActiveSlide.valid;
+ std::vector<std::pair<CUICDMSlideHandle, CUICDMInstanceHandle>> theSerializationSlides;
+ theSerializationSlides.reserve(m_SlideSet.size());
+ TSlideSet theMasterSlideSet;
+ for (TSlideSet::iterator theIter = m_SlideSet.begin(), end = m_SlideSet.end();
+ theIter != end; ++theIter) {
+ CUICDMSlideHandle theSlide = *theIter;
+ CUICDMSlideHandle theMasterSlide = m_SlideCore.GetParentSlide(theSlide);
+ if (theMasterSlide.Valid() && theMasterSlideSet.insert(theMasterSlide).second) {
+ CUICDMInstanceHandle theSlideOwner(GetSlideComponent(theMasterSlide));
+ if (theSlideOwner.Valid())
+ theSerializationSlides.push_back(std::make_pair(theMasterSlide, theSlideOwner));
+ }
+ }
+ // Sort the slides by the depth index of their component.
+ std::stable_sort(theSerializationSlides.begin(), theSerializationSlides.end(),
+ SInstanceOrderSorter(m_InstanceToGraphDepthMap));
+ for (size_t slideSetIdx = 0, slideSetEnd = theSerializationSlides.size();
+ slideSetIdx < slideSetEnd; ++slideSetIdx) {
+ CUICDMSlideHandle theMasterSlide = theSerializationSlides[slideSetIdx].first;
+ CUICDMInstanceHandle theComponent = theSerializationSlides[slideSetIdx].second;
+ IDOMWriter::Scope __masterScope(inWriter, L"State");
+
+ inWriter.Att(L"name", GetSlideName(theMasterSlide));
+ wstring theComponentRef = L"#";
+ theComponentRef.append(GetInstanceId(theComponent));
+ inWriter.Att(L"component", theComponentRef.c_str());
+
+ TPropertyHandleValuePairList theValues;
+ GetSlidePropertyValues(theMasterSlide, theValues);
+ SerializePropertyList(inWriter, theValues);
+
+ TInstanceHandleList theInstances;
+ GetFilteredAssociatedInstances(theMasterSlide, theInstances);
+
+ theInstances.push_back(theComponent);
+ SortSlideInstanceList(theInstances);
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theInstance(theInstances[idx]);
+ if (m_InstanceSet.find(theInstance) == m_InstanceSet.end())
+ continue;
+ WriteSlideInstance(inWriter, theInstance, theMasterSlide, 0);
+ }
+ TSlideHandleList theChildren;
+ m_SlideCore.GetChildSlides(theMasterSlide, theChildren);
+ // Generate ids for all of the slides before we attempt to write them out
+ // else a reference to a further slide may generate an external slide reference
+ // which wouldn't be our intention.
+ for (size_t idx = 0, end = theChildren.size(); idx < end; ++idx) {
+ CUICDMSlideHandle theChildSlide(theChildren[idx]);
+ GetSlideId(theChildSlide, theComponent);
+ }
+ for (size_t idx = 0, end = theChildren.size(); idx < end; ++idx) {
+ CUICDMSlideHandle theChildSlide(theChildren[idx]);
+ m_SlideSet.erase(theChildSlide);
+ IDOMWriter::Scope __childSlideScope(inWriter, L"State");
+ inWriter.Att(L"id", GetSlideId(theChildSlide, theComponent));
+ inWriter.Att(L"name", GetSlideName(theChildSlide));
+ theValues.clear();
+ GetSlidePropertyValues(theChildSlide, theValues);
+ SerializePropertyList(inWriter, theValues);
+ for (size_t masterIdx = 0, masterEnd = theInstances.size(); masterIdx < masterEnd;
+ ++masterIdx)
+ WriteSlideMasterOverrides(inWriter, theInstances[masterIdx], theChildSlide,
+ theMasterSlide);
+
+ TInstanceHandleList theChildInstances;
+ GetFilteredAssociatedInstances(theChildSlide, theChildInstances);
+ SortSlideInstanceList(theChildInstances);
+ for (size_t instIdx = 0, instEnd = theChildInstances.size(); instIdx < instEnd;
+ ++instIdx) {
+ // Don't write out the master instances again, we did that with a special
+ // function just
+ // for them above.
+ if (find(theInstances.begin(), theInstances.end(), theChildInstances[instIdx])
+ != theInstances.end())
+ continue;
+
+ WriteSlideInstance(inWriter, theChildInstances[instIdx], theChildSlide, 0);
+ }
+ }
+ }
+ }
+
+ // Structure to record the information needed to parse an action so we
+ // can delay action parsing to allow relative path resolution which
+ // allows correct event name resolution
+ // Probably a better fix would be to delay the event name resolution
+ // until the event handle is actually needed but that is too risky to
+ // attempt right now.
+ struct SActionParseRecord
+ {
+ void *m_ReaderScope;
+ CUICDMSlideHandle m_Slide;
+ CUICDMInstanceHandle m_Instance;
+ SActionParseRecord()
+ : m_ReaderScope(NULL)
+ {
+ }
+ SActionParseRecord(void *inReaderScope, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+ : m_ReaderScope(inReaderScope)
+ , m_Slide(inSlide)
+ , m_Instance(inInstance)
+ {
+ }
+ };
+
+ void ParseSlide(IDOMReader &inReader, CUICDMSlideHandle inSlide, SLong4 inComponentId,
+ vector<SActionParseRecord> &inUnparsedActions)
+ {
+ IDOMReader::Scope __stateScope(inReader);
+ TPropertyHandleValuePairList theValues;
+ vector<pair<TCharPtr, TCharPtr>> theExtraAtts;
+ ParseAndSetInstanceProperties(inReader, 0, m_SlideCore.GetSlideInstance(inSlide),
+ theExtraAtts, theValues);
+ // Slides require a two-pass parsing system because slides can refer to each other via id.
+ {
+ IDOMReader::Scope __stateChildrenScope(inReader);
+ // Preparse the slide first to create all child slides in the graph.
+ for (bool success = inReader.MoveToFirstChild(L"State"); success;
+ success = inReader.MoveToNextSibling(L"State")) {
+ // On the first pass, just create ids for the slides. This is because we can have
+ // references to other slides
+ // via id *in* the slide data.
+ {
+ const wchar_t *theId = L"";
+ inReader.Att(L"Id", theId);
+ pair<CUICDMSlideHandle, CUICDMInstanceHandle> theChildSlideInstPair =
+ CreateSlide();
+ m_SlideCore.DeriveSlide(theChildSlideInstPair.first, inSlide);
+ m_DataCore.SetInstancePropertyValue(theChildSlideInstPair.second,
+ m_ObjectDefinitions.m_Slide.m_ComponentId,
+ inComponentId);
+ if (!IsTrivial(theId))
+ AddSlideId(theId, theChildSlideInstPair.first);
+ }
+ }
+ }
+ // Some older files don't have slide ids so we need to be able to parse those files
+ // correctly. If the file doesn't have a slide id then we effectively use the
+ // slide index.
+ TSlideHandleList theChildren;
+ m_SlideCore.GetChildSlides(inSlide, theChildren);
+ TSlideHandleList::iterator theCurrentChild(theChildren.begin());
+ TSlideHandleList::iterator theLastChild(theChildren.end());
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetElementName(), L"Set")
+ || AreEqual(inReader.GetElementName(), L"Add")) {
+ TCharPtr theRef;
+ inReader.Att(L"ref", theRef);
+ CUICDMInstanceHandle theInstance = GetInstanceById(theRef + 1);
+ if (theInstance.Valid() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ // Sometimes we will read the component's properties *inside* the component.
+ // this happens if you attach an action inside of a component.
+ // In this case we don't want to also associate the component with the slide where
+ // the
+ // action exists.
+ bool IsAlreadyAssociated = m_SlideSystem.GetAssociatedSlide(theInstance).Valid();
+ bool IsGuidDifferent = !(
+ GetGuid(theInstance, m_ObjectDefinitions.m_Guided.m_GuidProp) == inComponentId);
+ if (!IsAlreadyAssociated && IsGuidDifferent) {
+ m_SlideSystem.AssociateInstanceWithSlide(inSlide, theInstance);
+ IDocumentEditor::UnlinkAlwaysUnlinkedProperties(
+ theInstance, m_ObjectDefinitions, m_SlideSystem);
+ }
+
+ ParseAndSetInstanceProperties(inReader, inSlide, theInstance, theExtraAtts,
+ theValues);
+ // Reset the reader pointer after delving into the children
+ IDOMReader::Scope __instanceScope(inReader);
+ for (bool childSuccess = inReader.MoveToFirstChild(); childSuccess;
+ childSuccess = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetElementName(), L"AnimationTrack"))
+ ParseAnimation(inReader, inSlide, theInstance);
+ else if (AreEqual(inReader.GetElementName(), L"Action"))
+ inUnparsedActions.push_back(
+ SActionParseRecord(inReader.GetScope(), inSlide, theInstance));
+ }
+ } else if (AreEqual(inReader.GetElementName(), L"State")) {
+ const wchar_t *theId = L"";
+ inReader.Att(L"Id", theId);
+ CUICDMSlideHandle theSlide;
+ if (!IsTrivial(theId))
+ theSlide = GetSlideById(theId);
+ else
+ theSlide = *theCurrentChild;
+
+ QT3DS_ASSERT(theSlide.Valid());
+ QT3DS_ASSERT(theSlide = *theCurrentChild);
+ ++theCurrentChild;
+
+ if (theSlide.Valid())
+ ParseSlide(inReader, theSlide, inComponentId, inUnparsedActions);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ void ReadSlides(IDOMReader &inReader)
+ {
+ vector<SActionParseRecord> theUnparsedActions;
+ IDOMReader::Scope __logicScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetElementName(), L"ActiveState")) {
+ if (m_ActiveSlide.Valid() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ Q3DStudio::CId theSceneId(SCENE_GUID);
+ TGUIDPacked thePackedGuid(theSceneId);
+ SLong4 theSceneGuid(thePackedGuid.Data1, thePackedGuid.Data2, thePackedGuid.Data3,
+ thePackedGuid.Data4);
+ ParseSlide(inReader, m_ActiveSlide, theSceneGuid, theUnparsedActions);
+ } else if (AreEqual(inReader.GetElementName(), L"State")) {
+ TCharPtr componentRef = L"";
+ inReader.Att(L"component", componentRef);
+ CUICDMInstanceHandle component = GetInstanceById(componentRef + 1);
+ if (component.Valid() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ // Ensure that the component doesn't already have a slide graph associated with it.
+ TSlideGraphHandleList theGraphs;
+ m_SlideGraphCore.GetSlideGraphs(theGraphs);
+ SLong4 theComponentGuid =
+ GetGuid(component, m_ObjectDefinitions.m_Guided.m_GuidProp);
+ bool foundDuplicateGraph = false;
+ for (size_t idx = 0, end = theGraphs.size();
+ idx < end && foundDuplicateGraph == false; ++idx) {
+ CUICDMSlideHandle theMaster = m_SlideGraphCore.GetGraphRoot(theGraphs[idx]);
+ CUICDMInstanceHandle theSlideInstance = m_SlideCore.GetSlideInstance(theMaster);
+ SValue theValue;
+ if (m_DataCore.GetInstancePropertyValue(
+ theSlideInstance, m_ObjectDefinitions.m_Slide.m_ComponentId,
+ theValue)) {
+ SLong4 theLocalGuid = UICDM::get<SLong4>(theValue);
+ if (theLocalGuid == theComponentGuid) {
+ const char8_t *theErrorRef;
+ inReader.Att("component", theErrorRef);
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Duplicate master slide found: "
+ << theErrorRef;
+ foundDuplicateGraph = true;
+ }
+ }
+ }
+ if (foundDuplicateGraph == false) {
+ pair<CUICDMSlideHandle, CUICDMInstanceHandle> theSlideInstPair = CreateSlide();
+ m_SlideGraphCore.CreateSlideGraph(theSlideInstPair.first);
+ m_DataCore.SetInstancePropertyValue(theSlideInstPair.second,
+ m_ObjectDefinitions.m_Slide.m_ComponentId,
+ theComponentGuid);
+ ParseSlide(inReader, theSlideInstPair.first, theComponentGuid,
+ theUnparsedActions);
+ m_SlideSystem.SetActiveSlide(theSlideInstPair.first, 1);
+ }
+ }
+ }
+
+ for (size_t actionIdx = 0, actionEnd = theUnparsedActions.size(); actionIdx < actionEnd;
+ ++actionIdx) {
+ SActionParseRecord &theRecord(theUnparsedActions[actionIdx]);
+ inReader.SetScope(theRecord.m_ReaderScope);
+
+ ParseAction(inReader, theRecord.m_Slide, theRecord.m_Instance);
+ }
+ }
+
+ void WriteExternalReferences(IDOMWriter &inWriter)
+ {
+ // First filter the external references via the instance set
+ for (TInstanceSet::iterator theIter = m_InstanceSet.begin(), end = m_InstanceSet.end();
+ theIter != end; ++theIter)
+ m_ExternalReferences.erase(*theIter);
+
+ if (m_ExternalReferences.empty() && m_ExternalActions.empty() && m_ExternalSlides.empty())
+ return;
+
+ IDOMWriter::Scope __refScope(inWriter, L"ExternalReferences");
+ wstring theWriteBuf;
+ wstring theId;
+ wchar_t tempBuf[256];
+ for (TInstanceSet::iterator theIter = m_ExternalReferences.begin(),
+ theEnd = m_ExternalReferences.end();
+ theIter != theEnd; ++theIter) {
+ IDOMWriter::Scope __refScope(inWriter, L"Reference");
+ theId.assign(L"#");
+ theId.append(GetInstanceId(*theIter));
+ inWriter.Att(L"ref", theId.c_str());
+ theWriteBuf.clear();
+ SLong4 theGuid = GetInstanceGuid(*theIter);
+ for (size_t idx = 0; idx < 4; ++idx) {
+ WStrOps<qt3ds::QT3DSU32>().ToStr(theGuid.m_Longs[idx], toDataRef(tempBuf, 256));
+ if (idx)
+ theWriteBuf.append(L" ");
+ theWriteBuf.append(tempBuf);
+ }
+ inWriter.Att(L"guid", theWriteBuf.c_str());
+ }
+ for (TActionSet::iterator theIter = m_ExternalActions.begin(),
+ theEnd = m_ExternalActions.end();
+ theIter != theEnd; ++theIter) {
+ CUICDMActionHandle theAction(*theIter);
+ IDOMWriter::Scope __refScope(inWriter, L"ActionReference");
+ theId.assign(L"#");
+ theId.append(GetActionId(theAction, 0, 0));
+ inWriter.Att(L"ref", theId.c_str());
+
+ inWriter.Att(L"handle", (int)theAction);
+ }
+ for (TSlideSet::iterator theIter = m_ExternalSlides.begin(),
+ theEnd = m_ExternalSlides.end();
+ theIter != theEnd; ++theIter) {
+ CUICDMSlideHandle theSlide(*theIter);
+ IDOMWriter::Scope __refScope(inWriter, L"SlideReference");
+ theId.assign(L"#");
+ theId.append(GetSlideId(theSlide, 0));
+ inWriter.Att(L"ref", theId.c_str());
+ inWriter.Att(L"handle", (int)theSlide);
+ }
+ }
+
+ struct SMasterObjectSorter
+ {
+ IDataCore &m_DataCore;
+ CUICDMPropertyHandle m_SourcePathProperty;
+ SMasterObjectSorter(IDataCore &inDataCore, CUICDMPropertyHandle inSourcePathProperty)
+ : m_DataCore(inDataCore)
+ , m_SourcePathProperty(inSourcePathProperty)
+ {
+ }
+ bool operator()(CUICDMInstanceHandle lhs, CUICDMInstanceHandle rhs) const
+ {
+ SValue lhsValue, rhsValue;
+ m_DataCore.GetInstancePropertyValue(lhs, m_SourcePathProperty, lhsValue);
+ m_DataCore.GetInstancePropertyValue(rhs, m_SourcePathProperty, rhsValue);
+ TDataStrPtr lhsStr = UICDM::get<TDataStrPtr>(lhsValue);
+ TDataStrPtr rhsStr = UICDM::get<TDataStrPtr>(rhsValue);
+ return QString::compare(QString::fromWCharArray(lhsStr->GetData()), QString::fromWCharArray(rhsStr->GetData())) < 0;
+ }
+ };
+
+ void AddGraphInstanceToOrderMap(CUICDMInstanceHandle inInstance)
+ {
+ m_InstanceToGraphDepthMap.insert(
+ std::make_pair(inInstance, (int)m_InstanceToGraphDepthMap.size()));
+ }
+
+ void BuildGraphOrderMap(const CUICDMInstanceHandle *inTopInstances, QT3DSU32 inCount)
+ {
+ /* Code for breadth first ordering
+ TInstanceHandleList theNextInstancesList;
+ TInstanceHandleList theCurrentInstancesList;
+ m_AssetGraph.GetDepthFirst(
+ for ( QT3DSU32 idx =0; idx < inCount; ++idx )
+ theNextInstancesList.push_back( inTopInstances[idx] );
+
+ do
+ {
+ std::swap( theCurrentInstancesList, theNextInstancesList );
+ theNextInstancesList.clear();
+ for ( size_t idx = 0, end = theCurrentInstancesList.size(); idx < end; ++idx )
+ {
+ CUICDMInstanceHandle theCurrentInstance( theCurrentInstancesList[idx] );
+ AddGraphInstanceToOrderMap( theCurrentInstance );
+ for ( int childIdx = 0, childEnd = m_AssetGraph.GetChildCount(
+ theCurrentInstance ); childIdx < childEnd; ++childIdx )
+ theNextInstancesList.push_back( m_AssetGraph.GetChild(
+ theCurrentInstance, childIdx ) );
+ }
+ }while( theNextInstancesList.size() );
+ */
+ CGraphIterator theIter;
+ m_AssetGraph.GetDepthFirst(theIter, m_AssetGraph.GetRoot(0));
+ for (; theIter.IsDone() == false; ++theIter) {
+ AddGraphInstanceToOrderMap(theIter.GetCurrent());
+ }
+ }
+
+ void DoSerializeScene(IDOMWriter &inWriter, const CUICDMInstanceHandle *inTopInstances,
+ QT3DSU32 inCount, bool inWriteParentRefs = false)
+ {
+ GetAllInstanceGuids();
+ {
+ IDOMWriter::Scope graphScope(inWriter, L"Graph");
+ for (QT3DSU32 idx = 0; idx < inCount; ++idx)
+ Serialize(inWriter, inTopInstances[idx], inWriteParentRefs);
+ }
+ if (m_MasterObjectsSet.size()) {
+ {
+ IDOMWriter::Scope masterScope(inWriter, L"Classes");
+ TInstanceList theMasterObjectsList;
+ theMasterObjectsList.insert(theMasterObjectsList.end(), m_MasterObjectsSet.begin(),
+ m_MasterObjectsSet.end());
+ std::stable_sort(
+ theMasterObjectsList.begin(), theMasterObjectsList.end(),
+ SMasterObjectSorter(m_DataCore, m_ObjectDefinitions.m_Asset.m_SourcePath));
+ for (TInstanceList::iterator theIter = theMasterObjectsList.begin(),
+ end = theMasterObjectsList.end();
+ theIter != end; ++theIter) {
+ CUICDMInstanceHandle theMaster(*theIter);
+ Option<TCharStr> theType = m_MetaData.GetTypeForInstance(theMaster);
+ if (theType.hasValue() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ IDOMWriter::Scope instScope(inWriter, theType->wide_str());
+ inWriter.Att(L"id", GetInstanceId(theMaster));
+ // Write out all the properties that are on the instance but are not on *this*
+ // instance in the meta data.
+ TPropertyHandleValuePairList theProperties;
+ GetSpecificInstancePropertyValues(theMaster, theProperties);
+ erase_if(theProperties,
+ SMetaDataPropertyEraser(theMaster, m_ObjectDefinitions));
+ SerializePropertyList(inWriter, theProperties);
+ }
+ }
+ inWriter.MoveBefore(L"Classes", L"Graph");
+ }
+ {
+ BuildGraphOrderMap(inTopInstances, inCount);
+ IDOMWriter::Scope stateScope(inWriter, L"Logic");
+ SerializeSlides(inWriter, inWriteParentRefs);
+ }
+
+ WriteExternalReferences(inWriter);
+ }
+
+ void ReadExternalReferences(IDOMReader &inReader)
+ {
+ IDOMReader::Scope __externalReferencesScope(inReader);
+ if (inReader.MoveToFirstChild(L"ExternalReferences")) {
+ GetAllInstanceGuids();
+ TCharStr theRef;
+ TCharStr theGuidBuf;
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetElementName(), L"Reference")) {
+ inReader.Att(L"ref", theRef);
+ inReader.Att(L"guid", theGuidBuf);
+ SLong4 theGuid;
+ const wchar_t *theStartPtr(theGuidBuf.wide_str());
+ wchar_t *theEndPtr(NULL);
+ for (size_t idx = 0; idx < 4; ++idx) {
+ theGuid.m_Longs[idx] = wcstol(theStartPtr, &theEndPtr, 10);
+ theStartPtr = theEndPtr;
+ }
+ CUICDMInstanceHandle theInstance = FindInstanceByGUID(theGuid);
+ if (theInstance.Valid())
+ AddId(theRef.wide_str() + 1, theInstance);
+ } else if (AreEqual(inReader.GetElementName(), L"ActionReference")) {
+ inReader.Att(L"ref", theRef);
+ inReader.Att(L"handle", theGuidBuf);
+ long theHandleValue(wcstol(theGuidBuf.wide_str(), NULL, 10));
+ CUICDMActionHandle theAction(theHandleValue);
+ QT3DS_ASSERT(m_ActionCore.HandleValid(theAction));
+ AddActionId(theRef.wide_str() + 1, theAction);
+ } else if (AreEqual(inReader.GetElementName(), L"SlideReference")) {
+ inReader.Att(L"ref", theRef);
+ inReader.Att(L"handle", theGuidBuf);
+ long theHandleValue(wcstol(theGuidBuf.wide_str(), NULL, 10));
+ CUICDMSlideHandle theSlide(theHandleValue);
+ QT3DS_ASSERT(m_SlideCore.IsSlide(theSlide));
+ AddSlideId(theRef.wide_str() + 1, theSlide);
+ }
+ }
+ }
+ }
+
+ UICDM::TInstanceHandleList DoSerializeScene(IDOMReader &inReader,
+ const CFilePath &inDocumentDirectory,
+ CUICDMInstanceHandle inNewRoot)
+ {
+ // Attempt to work correctly whether we are pointing to the project or not.
+ IDOMReader::Scope __outerScope(inReader);
+ if (AreEqual(inReader.GetElementName(), L"UIP"))
+ inReader.MoveToFirstChild(L"Project");
+
+ {
+ ReadExternalReferences(inReader);
+ IDOMReader::Scope __masterScope(inReader);
+ if (inReader.MoveToFirstChild(L"Classes")) {
+ BuildSourcePathMasterObjectMap();
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ const wchar_t *theSourcePath;
+ // Ignore master objects that already exist in the project.
+ if (inReader.Att(L"sourcepath", theSourcePath) == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ CUICDMInstanceHandle theMaster;
+ TIdToHandleMap::iterator theFind(m_SourcePathToMasterInstances.find(
+ m_StringTable.RegisterStr(theSourcePath)));
+ if (theFind != m_SourcePathToMasterInstances.end()) {
+ theMaster = theFind->second;
+ } else {
+ CFilePath theFullPath = CFilePath::CombineBaseAndRelative(
+ inDocumentDirectory, CFilePath(theSourcePath));
+
+ const wchar_t *theType(inReader.GetElementName());
+ CUICDMInstanceHandle theCanonicalType(
+ m_MetaData.GetCanonicalInstanceForType(theType));
+ if (theCanonicalType.Valid() == false) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ theMaster = m_DataCore.CreateInstance();
+ m_DataCore.DeriveInstance(theMaster, theCanonicalType);
+ TPropertyHandleValuePairList theValues;
+ vector<pair<TCharPtr, TCharPtr>> theExtraAtts;
+ m_SourcePathToMasterInstances.insert(
+ make_pair(m_StringTable.RegisterStr(theSourcePath), theMaster));
+
+ if (theFullPath.Exists()) {
+ if (theFullPath.GetExtension().Compare(L"lua", CString::ENDOFSTRING,
+ false)) {
+ // If we can't parse the lua file, go on.
+ std::shared_ptr<IDOMReader> theLuaPtr =
+ IDocumentEditor::ParseLuaFile(
+ theFullPath, m_DataCore.GetStringTablePtr(),
+ m_ImportFailedHandler, *m_InputStreamFactory);
+ if (theLuaPtr) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ // Now the magic section
+ m_MetaData.LoadInstance(*theLuaPtr, theMaster,
+ theFullPath.GetFileStem().c_str(),
+ warnings);
+ }
+ } else if (theFullPath.GetExtension().Compare(L"qml",
+ CString::ENDOFSTRING,
+ false)) {
+ std::shared_ptr<IDOMReader> theScriptPtr =
+ IDocumentEditor::ParseScriptFile(
+ theFullPath, m_DataCore.GetStringTablePtr(),
+ m_ImportFailedHandler, *m_InputStreamFactory);
+ if (theScriptPtr) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ m_MetaData.LoadInstance(*theScriptPtr, theMaster,
+ theFullPath.GetFileStem().c_str(),
+ warnings);
+ }
+ } else if (theFullPath.GetExtension().Compare(
+ L"glsl", CString::ENDOFSTRING, false)
+ || theFullPath.GetExtension().Compare(
+ L"effect", CString::ENDOFSTRING, false)) {
+ if (theFullPath.Exists()) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ // Now the magic section
+ NVScopedRefCounted<uic::render::IRefCountedInputStream>
+ theStream = m_InputStreamFactory->GetStreamForFile(
+ QString::fromWCharArray(theFullPath));
+ if (theStream) {
+ m_MetaData.LoadEffectInstance(
+ m_StringTable.GetNarrowStr(theSourcePath),
+ theMaster,
+ theFullPath.GetFileStem().c_str(),
+ warnings,
+ *theStream);
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ } else if (theFullPath.GetExtension().Compare(
+ L"plugin", CString::ENDOFSTRING, false)) {
+ std::shared_ptr<IDOMReader> thePluginPtr =
+ IDocumentEditor::ParsePluginFile(
+ theFullPath, m_DataCore.GetStringTablePtr(),
+ m_ImportFailedHandler, *m_InputStreamFactory);
+ if (thePluginPtr) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ // Now the magic section
+ m_MetaData.LoadInstance(*thePluginPtr, theMaster,
+ theFullPath.GetFileStem().c_str(),
+ warnings);
+ }
+ } else if (theFullPath.GetExtension().Compare(
+ L"material", CString::ENDOFSTRING, false)) {
+ if (theFullPath.Exists()) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ NVScopedRefCounted<uic::render::IRefCountedInputStream>
+ theStream = m_InputStreamFactory->GetStreamForFile(
+ QString::fromWCharArray(theFullPath));
+ if (theStream) {
+ // Now the magic section
+ m_MetaData.LoadMaterialInstance(
+ m_StringTable.GetNarrowStr(theSourcePath),
+ theMaster,
+ theFullPath.GetFileStem().c_str(),
+ warnings,
+ *theStream);
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ ASSERT(false);
+ }
+ ParseAndSetInstanceProperties(inReader, 0, theMaster, theExtraAtts,
+ theValues);
+ }
+ const wchar_t *theId;
+ inReader.Att(L"id", theId);
+ AddId(theId, theMaster);
+ }
+ }
+ }
+
+ TInstanceHandleList retval;
+ {
+ IDOMReader::Scope __graphScope(inReader);
+ if (!inReader.MoveToFirstChild(L"Graph")) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ {
+ // Parse the graph in two passes. First pass just creates the base instances
+ // and sets up their GUID's
+ // Second pass does the actual parsing of their properties. This allows us to
+ // reference
+ // things through the graph in an easier fasion.
+ // pass 1
+ retval = CreateAndRegisterInstances(inReader, true, inNewRoot);
+ // pass 2
+ ReadInstanceProperties(inReader);
+ }
+ }
+ {
+ IDOMReader::Scope __logicScope(inReader);
+ if (!inReader.MoveToFirstChild(L"Logic")) {
+ QT3DS_ASSERT(false);
+ return TInstanceHandleList();
+ }
+ ReadSlides(inReader);
+ }
+
+ return retval;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // Public API
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ struct ScopedPreserveFileIds
+ {
+ bool &m_PreserveFileIds;
+ ScopedPreserveFileIds(bool &inPreserveVariable)
+ : m_PreserveFileIds(inPreserveVariable)
+ {
+ m_PreserveFileIds = inPreserveVariable;
+ // The act of preserving file ids means that we have to write information
+ // into UICDM. Nothing expects this at this time and this information really shouldn't
+ // be transmitted into the universe. Transmitting the changes could cause the rendering
+ // system to render the scene a bunch.
+ m_PreserveFileIds = true;
+ SetUICDMSignalsEnabled(false);
+ }
+ ~ScopedPreserveFileIds()
+ {
+ m_PreserveFileIds = false;
+ SetUICDMSignalsEnabled(true);
+ }
+ };
+
+ void SerializeScene(IDOMWriter &inWriter) override
+ {
+ reset();
+ ScopedPreserveFileIds __preserveFileIds(m_PreserveFileIds);
+
+ vector<CUICDMInstanceHandle> theGraphRoots;
+ CGraphIterator theIterator;
+ m_AssetGraph.GetRoots(theIterator);
+ for (; theIterator.IsDone() == false; ++theIterator)
+ theGraphRoots.push_back(theIterator.GetCurrent());
+
+ if (theGraphRoots.empty())
+ return;
+ QT3DS_ASSERT(theGraphRoots.size() == 1);
+ DoSerializeScene(inWriter, &theGraphRoots[0], 1);
+ TGuideHandleList theGuides = m_GuideSystem.GetAllGuides();
+ // sort the guides by handle value to keep the file as stable as possible.
+ std::sort(theGuides.begin(), theGuides.end());
+ {
+ IDOMWriter::Scope fileScope(inWriter, "Guides");
+ if (!m_GuideSystem.AreGuidesEditable())
+ inWriter.Att("locked", true);
+
+ for (size_t idx = 0, end = theGuides.size(); idx < end; ++idx) {
+ UICDM::SGuideInfo theGuideInfo = m_GuideSystem.GetGuideInfo(theGuides[idx]);
+ IDOMWriter::Scope guideScope(inWriter, "Guide");
+ inWriter.Att("direction", theGuideInfo.m_Direction);
+ inWriter.Att("position", theGuideInfo.m_Position);
+ inWriter.Att(L"width", theGuideInfo.m_Width);
+ }
+ }
+ }
+
+ void SerializeScene(IDOMReader &inReader, const CFilePath &inDocumentDirectory,
+ int inUIPVersion) override
+ {
+ reset();
+ ScopedPreserveFileIds __preserveFileIds(m_PreserveFileIds);
+ m_UIPVersion = inUIPVersion;
+ DoSerializeScene(inReader, inDocumentDirectory, 0);
+ if (inReader.MoveToFirstChild(L"Guides")) {
+ bool isLocked;
+ if (inReader.Att("locked", isLocked))
+ m_GuideSystem.SetGuidesEditable(!isLocked);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ UICDM::SGuideInfo theInfo;
+ inReader.Att("direction", theInfo.m_Direction);
+ inReader.Att("position", theInfo.m_Position);
+ inReader.Att("width", theInfo.m_Width);
+ m_GuideSystem.SetGuideInfo(m_GuideSystem.CreateGuide(), theInfo);
+ }
+ }
+ }
+
+ // Read a partial serialization into this slide, attaching the instance as the last child of the
+ // new root.
+ virtual UICDM::TInstanceHandleList
+ SerializeSceneGraphObject(IDOMReader &inReader, const CFilePath &inDocumentDirectory,
+ CUICDMInstanceHandle inNewRoot, CUICDMSlideHandle inActiveSlide) override
+ {
+ reset();
+ m_ActiveSlide = inActiveSlide;
+ m_PreserveFileIds = false;
+ return DoSerializeScene(inReader, inDocumentDirectory, inNewRoot);
+ }
+
+ // Write this instance and its children (and possibly its slides) to a writer.
+ // Equivalent to the older partial serialization system
+ void SerializeSceneGraphObjects(IDOMWriter &inWriter,
+ const TInstanceHandleList &inInstances,
+ CUICDMSlideHandle inActiveSlide) override
+ {
+ if (inInstances.empty())
+ return;
+ reset();
+ QT3DS_ASSERT(inActiveSlide.Valid());
+ m_ActiveSlide = inActiveSlide;
+ m_PreserveFileIds = false;
+ // It is fine if the parent is invalid
+ m_ActiveSlideParent = m_SlideCore.GetParentSlide(m_ActiveSlide);
+ DoSerializeScene(inWriter, inInstances.data(), (QT3DSU32)inInstances.size());
+ }
+
+ // Save and load just a single action
+ void SerializeAction(UICDM::IDOMWriter &inWriter, CUICDMSlideHandle inSlide,
+ CUICDMActionHandle inAction) override
+ {
+ reset();
+ m_PreserveFileIds = false;
+ const SActionInfo &theInfo(m_ActionCore.GetActionInfo(inAction));
+ SerializeAction(inWriter, inSlide, theInfo.m_Owner, inAction);
+ WriteExternalReferences(inWriter);
+ }
+
+ // Load a new action onto this root object
+ UICDM::CUICDMActionHandle SerializeAction(UICDM::IDOMReader &inReader,
+ UICDM::CUICDMInstanceHandle inNewRoot,
+ UICDM::CUICDMSlideHandle inSlide) override
+ {
+ reset();
+ m_PreserveFileIds = false;
+ ReadExternalReferences(inReader);
+ if (inReader.MoveToFirstChild(L"Action"))
+ return ParseAction(inReader, inSlide, inNewRoot);
+ return 0;
+ }
+
+ struct SInstanceInVector
+ {
+ const TInstanceHandleList &m_Vec;
+ SInstanceInVector(const TInstanceHandleList &v)
+ : m_Vec(v)
+ {
+ }
+ bool operator()(CUICDMInstanceHandle hdl)
+ {
+ return find(m_Vec.begin(), m_Vec.end(), hdl) != m_Vec.end();
+ }
+ };
+
+ struct SParentInSlide
+ {
+ CUICDMSlideHandle m_Slide;
+ ISlideSystem &m_SlideSystem;
+ CGraph &m_AssetGraph;
+
+ SParentInSlide(CUICDMSlideHandle inSlide, ISlideSystem &inSystem, CGraph &inAssetGraph)
+ : m_Slide(inSlide)
+ , m_SlideSystem(inSystem)
+ , m_AssetGraph(inAssetGraph)
+ {
+ }
+
+ bool operator()(CUICDMInstanceHandle inInstance)
+ {
+ CUICDMInstanceHandle theParent = m_AssetGraph.GetParent(inInstance);
+ if (theParent.Valid() && m_SlideSystem.GetAssociatedSlide(theParent) == m_Slide)
+ return true;
+ return false;
+ }
+ };
+
+ void SerializeSlide(UICDM::IDOMWriter &inWriter, UICDM::CUICDMSlideHandle inSlide) override
+ {
+ reset();
+ m_PreserveFileIds = false;
+ m_ActiveSlide = inSlide;
+ // It is fine if the parent is invalid
+ m_ActiveSlideParent = m_SlideCore.GetParentSlide(m_ActiveSlide);
+ TInstanceHandleList theSlideInstances;
+ m_SlideSystem.GetAssociatedInstances(inSlide, theSlideInstances);
+ if (m_ActiveSlideParent.Valid()) {
+ TInstanceHandleList theParentInstances;
+ m_SlideSystem.GetAssociatedInstances(m_ActiveSlideParent, theParentInstances);
+ erase_if(theSlideInstances, SInstanceInVector(theParentInstances));
+ erase_if(theSlideInstances, SParentInSlide(inSlide, m_SlideSystem, m_AssetGraph));
+ }
+ CUICDMInstanceHandle *theInstancePtr = NULL;
+ if (theSlideInstances.size()) {
+ BuildGraphOrderMap(theInstancePtr, (QT3DSU32)theSlideInstances.size());
+ SortSlideInstanceList(theSlideInstances);
+ theInstancePtr = &theSlideInstances[0];
+ }
+ DoSerializeScene(inWriter, theInstancePtr, (QT3DSU32)theSlideInstances.size(), true);
+ }
+
+ CUICDMSlideHandle SerializeSlide(UICDM::IDOMReader &inReader,
+ const CFilePath &inDocumentDirectory,
+ UICDM::CUICDMSlideHandle inMaster, int newIndex) override
+ {
+ reset();
+ m_PreserveFileIds = false;
+ m_ActiveSlideParent = inMaster;
+ CUICDMSlideHandle retval = m_SlideSystem.DuplicateSlide(inMaster, newIndex + 1);
+ m_ActiveSlide = retval;
+ CUICDMInstanceHandle theSlideInstance = m_SlideCore.GetSlideInstance(retval);
+ CUICDMInstanceHandle theMasterInstance(m_SlideSystem.GetSlideInstance(inMaster));
+ SLong4 theComponentGuid =
+ GetGuid(theMasterInstance, m_ObjectDefinitions.m_Slide.m_ComponentId);
+ m_DataCore.SetInstancePropertyValue(
+ theSlideInstance, m_ObjectDefinitions.m_Slide.m_ComponentId, theComponentGuid);
+ DoSerializeScene(inReader, inDocumentDirectory, 0);
+ return retval;
+ }
+};
+}
+
+std::shared_ptr<IComposerSerializer> IComposerSerializer::CreateGraphSlideSerializer(
+ IDataCore &inDataCore, IMetaData &inMetaData, ISlideCore &inSlideCore,
+ IAnimationCore &inAnimationCore, IActionCore &inActionCore, CGraph &inAssetGraph,
+ ISlideSystem &inSlideSystem, IActionSystem &inActionSystem, ISlideGraphCore &inSlideGraphCore,
+ SComposerObjectDefinitions &inObjectDefinitions,
+ std::shared_ptr<Q3DStudio::IImportFailedHandler> inFailedHandler, IGuideSystem &inGuideSystem,
+ uic::render::IPathManager &inPathManager)
+{
+ return std::shared_ptr<SComposerSerializerImpl>(new SComposerSerializerImpl(
+ inDataCore, inMetaData, inSlideCore, inAnimationCore, inActionCore, inAssetGraph,
+ inSlideSystem, inActionSystem, inSlideGraphCore, inObjectDefinitions, inFailedHandler,
+ inGuideSystem, inPathManager));
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h
new file mode 100644
index 00000000..901aa51b
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef COMPOSERSERIALIZERH
+#define COMPOSERSERIALIZERH
+#include "UICDMHandles.h"
+namespace uic {
+namespace render {
+ class IPathManager;
+}
+}
+
+namespace UICDM {
+class IDataCore;
+class IMetaData;
+class ISlideCore;
+class IAnimationCore;
+class IActionCore;
+class IDOMWriter;
+class IDOMReader;
+class ISlideSystem;
+class IActionSystem;
+class ISlideGraphCore;
+class IGuideSystem;
+class SComposerObjectDefinitions;
+};
+
+namespace Q3DStudio {
+class CGraph;
+class CFilePath;
+class IImportFailedHandler;
+
+// Serialize instance data on the data core, in the slides (including actions)
+// and in the animation system
+class IComposerSerializer
+{
+protected:
+ virtual ~IComposerSerializer() {}
+public:
+ // Empty graph roots means use the actual graph roots in the asset graph
+ virtual void SerializeScene(UICDM::IDOMWriter &inWriter) = 0;
+ // Write properties into the active slide until we get to a slide owner, then create new slides.
+ // inActiveSlide may be zero if the top item we find happens to be a scene or a component.
+ // The graph roots hold the top items
+ virtual void SerializeScene(UICDM::IDOMReader &inReader,
+ const Q3DStudio::CFilePath &inDocumentDirectory,
+ int inUIPVersion) = 0;
+
+ // Write this instance and its children (and possibly its slides) to a writer.
+ // Equivalent to the older partial serialization system
+ virtual void SerializeSceneGraphObjects(UICDM::IDOMWriter &inWriter,
+ const UICDM::TInstanceHandleList &inInstances,
+ UICDM::CUICDMSlideHandle inActiveSlide) = 0;
+
+ // Read a partial serialization into this slide, attaching the instance as the last child of the
+ // new root.
+ virtual UICDM::TInstanceHandleList SerializeSceneGraphObject(
+ UICDM::IDOMReader &inReader, const Q3DStudio::CFilePath &inDocumentDirectory,
+ UICDM::CUICDMInstanceHandle inNewRoot, UICDM::CUICDMSlideHandle inActiveSlide) = 0;
+
+ // Save and load just a single action
+ virtual void SerializeAction(UICDM::IDOMWriter &inWriter, UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMActionHandle inAction) = 0;
+ // Load a new action onto this root object
+ virtual UICDM::CUICDMActionHandle SerializeAction(UICDM::IDOMReader &inReader,
+ UICDM::CUICDMInstanceHandle inNewRoot,
+ UICDM::CUICDMSlideHandle inSlide) = 0;
+
+ virtual void SerializeSlide(UICDM::IDOMWriter &inWriter, UICDM::CUICDMSlideHandle inSlide) = 0;
+
+ virtual UICDM::CUICDMSlideHandle SerializeSlide(UICDM::IDOMReader &inReader,
+ const CFilePath &inDocumentDirectory,
+ UICDM::CUICDMSlideHandle inMaster,
+ int inNewIndex = -1) = 0;
+
+ friend class std::shared_ptr<IComposerSerializer>;
+
+ static std::shared_ptr<IComposerSerializer> CreateGraphSlideSerializer(
+ UICDM::IDataCore &inDataCore, UICDM::IMetaData &inMetaData, UICDM::ISlideCore &inSlideCore,
+ UICDM::IAnimationCore &inAnimationCore, UICDM::IActionCore &inActionCore,
+ CGraph &inAssetGraph, UICDM::ISlideSystem &inSlideSystem,
+ UICDM::IActionSystem &inActionSystem, UICDM::ISlideGraphCore &inSlideGraphCore,
+ UICDM::SComposerObjectDefinitions &inObjectDefinitions,
+ std::shared_ptr<Q3DStudio::IImportFailedHandler> inFailedHandler,
+ UICDM::IGuideSystem &inGuideSystem, uic::render::IPathManager &inPathManager);
+};
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IDataDrivenChangeListener.h b/src/Authoring/Client/Code/Core/Doc/IDataDrivenChangeListener.h
new file mode 100644
index 00000000..149e8cc5
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDataDrivenChangeListener.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_DATADRIVENCHANGE_LISTENER_H
+#define INCLUDED_DATADRIVENCHANGE_LISTENER_H 1
+
+#pragma once
+
+//==============================================================================
+/**
+ * @class IDataDrivenChangeListener
+ * @brief Provides an interface for notifying listeners that the data driven property (not
+ *the value) has changed.
+ */
+class IDataDrivenChangeListener
+{
+public:
+ virtual ~IDataDrivenChangeListener() {}
+ //==============================================================================
+ /**
+ * @param inIsDataDriven will be true if an item was set to data driven and false otherwise.
+ * @param inPropName property that is affected
+ */
+ virtual void OnDataDrivenChange(bool /*inIsDataDriven*/,
+ const Q3DStudio::CString & /*inPropName*/) = 0;
+
+ //==============================================================================
+ /**
+ * Called when if the data drive link is changed
+ * @param inPropName property that is affected
+ */
+ virtual void OnDataDrivenLinkValueChange(const Q3DStudio::CString & /*inPropName*/) = 0;
+};
+
+#endif // INCLUDED_DATADRIVENCHANGE_LISTENER_H
diff --git a/src/Authoring/Client/Code/Core/Doc/IDoc.h b/src/Authoring/Client/Code/Core/Doc/IDoc.h
new file mode 100644
index 00000000..b9e7495e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDoc.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_IDOC_H
+#define INCLUDED_IDOC_H
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMDataTypes.h"
+#include "UICDMValue.h"
+#include "SelectedValueImpl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CAsset;
+class IKeyframesManager;
+class ISelectable;
+class CCore;
+
+namespace qt3ds {
+namespace foundation {
+ class IInStream;
+}
+}
+namespace UICDM {
+class CUICDMInstanceHandle;
+class CUICDMSlideHandle;
+class CStudioSystem;
+class IPropertySystem;
+class IAnimationCore;
+class IDOMWriter;
+class IDOMReader;
+class ISignalConnection;
+}
+
+namespace Q3DStudio {
+class IDocumentEditor;
+class IDocumentReader;
+class IDocumentBufferCache;
+class CString;
+class IComposerSerializer;
+}
+
+//==============================================================================
+/**
+ * Doc
+ */
+class IDoc
+{
+public:
+ virtual long GetCurrentViewTime() const = 0;
+ virtual void NotifyTimeChanged(long inNewTime) = 0;
+ virtual void NotifyActiveSlideChanged(UICDM::CUICDMSlideHandle inNewActiveSlide) = 0;
+ virtual void NotifyActiveSlideChanged(UICDM::CUICDMSlideHandle inNewActiveSlide,
+ bool inForceRefresh,
+ bool inIgnoreLastDisplayTime = false) = 0;
+ virtual void NotifySelectionChanged(
+ Q3DStudio::SSelectedValue inNewSelection = Q3DStudio::SSelectedValue()) = 0;
+
+ virtual UICDM::CStudioSystem *GetStudioSystem() = 0;
+
+ virtual void SetKeyframeInterpolation() = 0;
+ virtual void DeselectAllKeyframes() = 0;
+
+ virtual void SetModifiedFlag(bool inIsModified = true) = 0;
+
+ virtual void SetKeyframesManager(IKeyframesManager *inManager) = 0;
+ virtual IKeyframesManager *GetKeyframesManager() = 0;
+
+ virtual UICDM::IPropertySystem *GetPropertySystem() = 0;
+ virtual UICDM::IAnimationCore *GetAnimationCore() = 0;
+ virtual void SetInstancePropertyValue(UICDM::CUICDMInstanceHandle inInstance,
+ const std::wstring &inPropertyName,
+ const UICDM::SValue &inValue) = 0;
+ // Return an editor to editing the scene graph of the document.
+ // This editor takes care of putting objects into the property slide
+ // as well as updating the world
+ virtual Q3DStudio::IDocumentBufferCache &GetBufferCache() = 0;
+
+ // Get an object responsible for reading the document
+ virtual Q3DStudio::IDocumentReader &GetDocumentReader() = 0;
+ // Open a transaction, change the model however you want to
+ // then close the transaction and a command will be generated which will
+ // automatically do most of the work of doing/undoing changes
+ // to the data model (and the graphs, and the selection state).
+ virtual Q3DStudio::IDocumentEditor &OpenTransaction(const Q3DStudio::CString &cmdName,
+ const char *inFile, int inLine) = 0;
+
+ // Get the document editor if a transaction has already been opened.
+ // Else open a new transaction.
+ virtual Q3DStudio::IDocumentEditor &MaybeOpenTransaction(const Q3DStudio::CString &cmdName,
+ const char *inFile, int inLine) = 0;
+ virtual bool IsTransactionOpened() const = 0;
+ // Undo whatever has been done and clear the transaction's
+ // internal data. Leave the transaction open and on the stack, however.
+ virtual void RollbackTransaction() = 0;
+ virtual void CloseTransaction() = 0;
+
+ // This should only be called from a global exception handler or something like that.
+ // This will close the transaction regardless of the open count.
+ // inAsynchronousCommit will in effect commit the command during a post-message callback.
+ // This is usually what you want because it will protect studio against crashes due to the
+ // command reconfiguring the UI. There are cases, however, when you really want the command to
+ // be
+ // committed right at this very moment (like just before undo).
+ virtual void IKnowWhatIAmDoingForceCloseTransaction() = 0;
+
+ virtual std::shared_ptr<Q3DStudio::IComposerSerializer> CreateSerializer() = 0;
+ // Create a DOM writer that is opened to the project element. This is where the serializer
+ // should write to.
+ virtual std::shared_ptr<UICDM::IDOMWriter> CreateDOMWriter() = 0;
+ // Create a DOM reader and check that the top element's version is correct. Opens the reader
+ // to the project element.
+ virtual std::shared_ptr<UICDM::IDOMReader>
+ CreateDOMReader(const Q3DStudio::CString &inFilePath, qt3ds::QT3DSI32 &outVersion) = 0;
+
+ virtual CCore *GetCore() = 0;
+};
+
+#define OPEN_TRANSACTION(name) OpenTransaction(name, __FILE__, __LINE__)
+
+#endif // INCLUDED_IDOC_H
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h b/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h
new file mode 100644
index 00000000..6183db8a
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef IDOC_SCENE_GRAPH_H
+#define IDOC_SCENE_GRAPH_H
+#include "UICRender.h"
+#include "UICDMHandles.h"
+#include "foundation/Qt3DSVec3.h"
+#include "Pt.h"
+namespace qt3ds {
+namespace foundation {
+ class IStringTable;
+}
+}
+
+#pragma once
+namespace Q3DStudio {
+using qt3ds::QT3DSVec3;
+using uic::render::IBufferManager;
+using uic::render::ITextRenderer;
+using uic::render::SGraphObject;
+using uic::render::IPathManager;
+
+class IDocSceneGraph
+{
+protected:
+ virtual ~IDocSceneGraph() {}
+public:
+ friend class std::shared_ptr<IDocSceneGraph>;
+
+ virtual ITextRenderer *GetTextRenderer() = 0;
+ virtual QT3DSVec3 GetIntendedPosition(UICDM::CUICDMInstanceHandle inHandle, CPt inPoint) = 0;
+ virtual IBufferManager *GetBufferManager() = 0;
+ virtual IPathManager *GetPathManager() = 0;
+ virtual qt3ds::foundation::IStringTable *GetRenderStringTable() = 0;
+ // Request that this object renders. May be ignored if a transaction
+ // is ongoing so we don't get multiple rendering per transaction.
+ virtual void RequestRender() = 0;
+};
+}
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h b/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h
new file mode 100644
index 00000000..312808cf
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_IDOCUMENTBUFFERCACHE_H
+#define INCLUDED_IDOCUMENTBUFFERCACHE_H
+#include "UICFileTools.h"
+#include "StudioObjectTypes.h"
+#include "UICRender.h"
+#include "UICRenderImageTextureData.h"
+
+namespace uic {
+namespace render {
+ struct SRenderMesh;
+ struct SImageTextureData;
+}
+}
+
+class CDoc;
+
+namespace Q3DStudio {
+class CFilePath;
+class CString;
+using uic::render::SRenderMesh;
+using uic::render::SImageTextureData;
+
+struct SModelBufferAndPath
+{
+ uic::render::SRenderMesh *m_ModelBuffer;
+ Q3DStudio::CFilePath m_FilePath;
+
+ SModelBufferAndPath(SRenderMesh *inBuffer, const Q3DStudio::CFilePath &inPath)
+ : m_ModelBuffer(inBuffer)
+ , m_FilePath(inPath)
+ {
+ }
+
+ SModelBufferAndPath()
+ : m_ModelBuffer(NULL)
+ {
+ }
+
+ operator SRenderMesh *() { return m_ModelBuffer; }
+ SRenderMesh *operator->() { return m_ModelBuffer; }
+};
+
+class IDocumentBufferCache
+{
+protected:
+ virtual ~IDocumentBufferCache() {}
+public:
+ friend class std::shared_ptr<IDocumentBufferCache>;
+ virtual const wchar_t **GetPrimitiveNames() = 0;
+ virtual const wchar_t *GetPrimitiveName(EPrimitiveType inPrimitiveType) = 0;
+ // Get or create the model buffer. May return NULL if the sourcepath doesn't
+ // map to a loadable model buffer.
+ // Takes a *relative* path from the document
+ virtual SModelBufferAndPath GetOrCreateModelBuffer(const CFilePath &inSourcePath) = 0;
+ //
+ // Get or create the image buffer. May return NULL if the sourcepath doesn't
+ // map to a loadable image buffer.
+ // Takes a *relative* path from the document
+ virtual SImageTextureData GetOrCreateImageBuffer(const CFilePath &inSourcePath) = 0;
+
+ virtual void
+ GetImageBuffers(std::vector<std::pair<Q3DStudio::CString, SImageTextureData>> &outBuffers) = 0;
+
+ // Takes a *relative* path from the document
+ virtual void InvalidateBuffer(const CFilePath &inSourcePath) = 0;
+
+ // Don't send events but just clear everything out. Used on document::close
+ virtual void Clear() = 0;
+
+ static std::shared_ptr<IDocumentBufferCache> CreateBufferCache(CDoc &inDoc);
+};
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
new file mode 100644
index 00000000..d0258ab4
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
@@ -0,0 +1,476 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_IDOCUMENTEDITOR_H
+#define INCLUDED_IDOCUMENTEDITOR_H
+#include "UICDMDataTypes.h"
+#include "UICDMAnimation.h"
+#include "StudioObjectTypes.h"
+#include "Pt.h"
+#include "UICImportErrorCodes.h"
+#include "DocumentEditorEnumerations.h"
+#include "IDocumentReader.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "CColor.h"
+#include "UICDMHandles.h"
+
+#pragma once
+
+class IDoc;
+class CDoc;
+
+namespace UICDM {
+class IDataCore;
+class ISlideCore;
+class ISlideSystem;
+class IMetaData;
+class SComposerObjectDefinitions;
+struct SGuideInfo;
+}
+
+namespace UICIMP {
+struct STranslationLog;
+}
+
+namespace uic {
+namespace render {
+ class IInputStreamFactory;
+ class ITextRenderer;
+}
+}
+
+namespace Q3DStudio {
+using std::wstring;
+class CGraph;
+class IInternalDocumentEditor;
+
+class IImportFailedHandler
+{
+protected:
+ virtual ~IImportFailedHandler() {}
+
+public:
+ virtual void DisplayImportFailed(const QString &inDocumentPath,
+ const QString &inDescription,
+ bool inWarningsOnly) = 0;
+};
+
+class IDeletingReferencedObjectHandler
+{
+protected:
+ virtual ~IDeletingReferencedObjectHandler() {}
+
+public:
+ virtual void DisplayMessageBox(const Q3DStudio::CString &inDescription) = 0;
+};
+
+class IDocumentEditor : public IDocumentReader
+{
+protected:
+ virtual ~IDocumentEditor() {}
+
+public:
+ // Undo whatever has been done so far.
+ virtual void Rollback() = 0;
+ // Release when finished editing
+ virtual void Release() = 0;
+
+ // Notify the subsystem that we will be modifying a lot of properties and data
+ // We filter events to only send one instance changed event per instance changed
+ // no animation events and no keyframe events.
+ virtual void BeginAggregateOperation() = 0;
+ virtual void EndAggregateOperation() = 0;
+
+ // Function callable without a document editor instance, used when loading document
+ static TInstanceHandle
+ CreateSceneGraphInstance(const wchar_t *inType, TInstanceHandle parent, TSlideHandle inSlide,
+ UICDM::IDataCore &inDataCore, UICDM::ISlideSystem &inSlideSystem,
+ UICDM::SComposerObjectDefinitions &inObjectDefs,
+ Q3DStudio::CGraph &inAssetGraph, UICDM::IMetaData &inMetaData,
+ TInstanceHandle inTargetId = TInstanceHandle());
+
+ static TInstanceHandle CreateSceneGraphInstance(
+ CUICDMInstanceHandle inMaster, TInstanceHandle parent, TSlideHandle inSlide,
+ UICDM::IDataCore &inDataCore, UICDM::ISlideSystem &inSlideSystem,
+ UICDM::SComposerObjectDefinitions &inObjectDefs, Q3DStudio::CGraph &inAssetGraph,
+ UICDM::IMetaData &inMetaData, TInstanceHandle inTargetId = TInstanceHandle());
+
+ static void UnlinkAlwaysUnlinkedProperties(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::SComposerObjectDefinitions &inDefs,
+ UICDM::ISlideSystem &inSlideSystem);
+
+ // Returns valid properties followed by exactly one invalid property.
+ static CUICDMPropertyHandle *
+ GetAlwaysUnlinkedProperties(UICDM::SComposerObjectDefinitions &inDefs);
+
+ // Create a new instance in the scene under this slide and such
+ // Target id must be an id of an invalid instance so that we can potentially change an object
+ // type while still maintaining references to that logical object.
+ virtual TInstanceHandle
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Enum type, TInstanceHandle parent,
+ TSlideHandle inSlide,
+ TInstanceHandle inTargetId = TInstanceHandle()) = 0;
+
+ virtual TInstanceHandle CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Enum type,
+ TInstanceHandle parent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inInsertType,
+ const CPt &inPosition,
+ EPrimitiveType inPrimitiveType,
+ long inStartTime) = 0;
+
+ virtual void DeleteInstances(UICDM::TInstanceHandleList inInstances) = 0;
+ // Delete this data model instance. Will recursively delete any attached children in the scene
+ // graph
+ // if this instance is represented in the scene graph.
+ void DeleteInstance(TInstanceHandle instance)
+ {
+ UICDM::TInstanceHandleList theInstances;
+ theInstances.push_back(instance);
+ DeleteInstances(theInstances);
+ }
+
+ // Set the instance's property value. This will set it in this slide if specified, else it is
+ // set
+ // in the datacore. Mainly for internal use. Most clients should use the API's below (note
+ // that lack of slide information
+ virtual void SetSpecificInstancePropertyValue(TSlideHandle inSlide, TInstanceHandle instance,
+ TPropertyHandle inProperty,
+ const SValue &value) = 0;
+ void SetSpecificInstancePropertyValue(TSlideHandle inSlide, TInstanceHandle instance,
+ const wchar_t *inProperty, const SValue &value)
+ {
+ SetSpecificInstancePropertyValue(inSlide, instance, FindProperty(instance, inProperty),
+ value);
+ }
+
+ // Set the property going through the property system and without a property lookup.
+ // autoDelete tells this object to do things like:
+ // delete the image that was there if the GUID is different.
+ // Delete the group subtree if the user imports a different path over the group.
+ virtual void SetInstancePropertyValue(TInstanceHandle instance, TPropertyHandle propName,
+ const SValue &value, bool autoDelete = true) = 0;
+
+ // Create an image, generate the GUID, and go from there.
+ // Returns an invalid instance in the case of failure.
+ // inSourcePath is assumed to !!already be document relative!!
+ // CDoc::GetRelativePathToDoc
+ // In fact, if ResolvePathToDoc doesn't return a valid file,
+ // the we will return 0 from this function.
+ virtual TInstanceHandle
+ SetInstancePropertyValueAsImage(TInstanceHandle instance, TPropertyHandle propName,
+ const Q3DStudio::CString &inSourcePath) = 0;
+
+ // If sourcepath resolves to a valid plugin file, we create a renderable item and add it as a
+ // child to the image.
+ // else we return nothing and just set the value as is.
+ virtual TInstanceHandle
+ SetInstancePropertyValueAsRenderable(TInstanceHandle instance, TPropertyHandle propName,
+ const Q3DStudio::CString &inSourcePath) = 0;
+
+ virtual void SetMaterialType(TInstanceHandle instance,
+ const Q3DStudio::CString &inRelativePathToMaterialFile) = 0;
+
+ // Set the slide name property value
+ // Also update all actions that point to the old slide name to new name
+ virtual void SetSlideName(TInstanceHandle instance, TPropertyHandle propName,
+ const wchar_t *inOldName, const wchar_t *inNewName) = 0;
+
+ virtual void SetName(CUICDMInstanceHandle inInstance, const CString &inName,
+ bool inMakeUnique = false) = 0;
+
+ // Linking/unlinking properties. Functions take care of creating/destroying
+ // images where necessary.
+ virtual void UnlinkProperty(TInstanceHandle instance, TPropertyHandle propName) = 0;
+ virtual void LinkProperty(TInstanceHandle instance, TPropertyHandle propName) = 0;
+
+ virtual void SetTimeRange(TInstanceHandle inInstance, long inStart, long inEnd) = 0;
+ virtual void SetTimeRangeInSlide(TSlideHandle inSlide, TInstanceHandle inInstance, long inStart,
+ long inEnd) = 0;
+ virtual void SetStartTime(TInstanceHandle inInstance, long inStart) = 0;
+ virtual void SetEndTime(TInstanceHandle inInstance, long inEnd) = 0;
+ virtual void ResizeTimeRange(TInstanceHandle inInstance, long inTime, bool inSetStart) = 0;
+ virtual void OffsetTimeRange(TInstanceHandle inInstance, long inOffset) = 0;
+ // called when the user hits '[' or ']'.
+ virtual void TruncateTimeRange(TInstanceHandle inInstance, bool inSetStart, long inTime) = 0;
+
+ virtual void SetTimebarColor(TInstanceHandle inInstance, ::CColor inColor) = 0;
+ virtual void SetTimebarText(TInstanceHandle inInstance,
+ const Q3DStudio::CString &inComment) = 0;
+
+ // Scene graph management.
+ virtual void AddChild(TInstanceHandle parent, TInstanceHandle child,
+ TInstanceHandle inNextSibling = TInstanceHandle()) = 0;
+ virtual void RemoveChild(TInstanceHandle parent, TInstanceHandle child) = 0;
+
+ // Set animation values. Animations that aren't considered user edited
+ // are replaced during refresh operations.
+ // CreateOrSetAnimation will offset each keyframe by the object's start time; thus the keyframe
+ // time space is expected to be normalized to the object's start time when being input to this
+ // function.
+ virtual CUICDMAnimationHandle
+ CreateOrSetAnimation(TSlideHandle inSlide, TInstanceHandle instance, const wchar_t *propName,
+ long subIndex, UICDM::EAnimationType animType, const float *keyframeValues,
+ long numValues, bool inUserEdited = true) = 0;
+ virtual bool RemoveAnimation(TSlideHandle inSlide, TInstanceHandle instance,
+ const wchar_t *propName, long subIndex) = 0;
+ virtual void SetKeyframeTime(TKeyframeHandle inKeyframe, long inTimeInMilliseconds) = 0;
+ virtual void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) = 0;
+ virtual void KeyframeProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inDoDiffValue) = 0;
+
+ // Only the import interface needs to worry about this. The animation system automatically
+ // sets the flag upon any change to an animation.
+ virtual void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) = 0;
+
+ // Paste a scene graph object into this system at this location. Returns the new object
+ //(but it sets the new object as the selected object so clients probably don't need this)
+ virtual UICDM::TInstanceHandleList
+ PasteSceneGraphObject(const CFilePath &inFilePath, CUICDMInstanceHandle inNewRoot,
+ bool inGenerateUniqueName, DocumentEditorInsertType::Enum inInsertType,
+ const CPt &inPosition) = 0;
+
+ virtual UICDM::TInstanceHandleList PasteSceneGraphObjectMaster(
+ const CFilePath &inFilePath, CUICDMInstanceHandle inNewRoot, bool inGenerateUniqueName,
+ DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition) = 0;
+
+ virtual void RearrangeObjects(const UICDM::TInstanceHandleList &inInstances,
+ TInstanceHandle inDest,
+ DocumentEditorInsertType::Enum inInsertType) = 0;
+
+ void RearrangeObject(TInstanceHandle inInstance, TInstanceHandle inDest,
+ DocumentEditorInsertType::Enum inInsertType)
+ {
+ UICDM::TInstanceHandleList theInstances;
+ theInstances.push_back(inInstance);
+ RearrangeObjects(theInstances, inDest, inInsertType);
+ }
+
+ // Returns the new component.
+ virtual TInstanceHandle MakeComponent(const UICDM::TInstanceHandleList &inInstances) = 0;
+
+ virtual UICDM::TInstanceHandleList
+ DuplicateInstances(const UICDM::TInstanceHandleList &inInstances, TInstanceHandle inDest,
+ DocumentEditorInsertType::Enum inInsertType) = 0;
+
+ TInstanceHandle DuplicateInstance(TInstanceHandle inInstance, TInstanceHandle inDest,
+ DocumentEditorInsertType::Enum inInsertType)
+ {
+ UICDM::TInstanceHandleList theInstances;
+ theInstances.push_back(inInstance);
+ theInstances = DuplicateInstances(theInstances, inDest, inInsertType);
+ if (theInstances.empty() == false)
+ return theInstances.back();
+ return TInstanceHandle();
+ }
+
+ virtual void DuplicateInstances(const UICDM::TInstanceHandleList &inInstances) = 0;
+ void DuplicateInstance(TInstanceHandle inInstance)
+ {
+ UICDM::TInstanceHandleList theInstances;
+ theInstances.push_back(inInstance);
+ return DuplicateInstances(theInstances);
+ }
+
+ virtual CUICDMActionHandle AddAction(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ const wstring &inEvent, const wstring &inHandler) = 0;
+
+ virtual void DeleteAction(CUICDMActionHandle inAction) = 0;
+
+ // Paste a given action into this new root object.
+ virtual CUICDMActionHandle PasteAction(const CFilePath &inFilePath,
+ CUICDMInstanceHandle inNewRoot) = 0;
+
+ virtual CUICDMSlideHandle AddSlide(CUICDMSlideHandle inMasterSlide, int inIndex = -1) = 0;
+
+ // Only valid if the master slide has more than one slide.
+ virtual void DeleteSlide(CUICDMSlideHandle inSlide) = 0;
+
+ virtual void RearrangeSlide(CUICDMSlideHandle inSlide, int inNewIndex) = 0;
+
+ virtual CUICDMSlideHandle DuplicateSlide(CUICDMSlideHandle inSlide) = 0;
+
+ virtual UICDM::CUICDMGuideHandle CreateGuide(const UICDM::SGuideInfo &inInfo) = 0;
+ virtual void UpdateGuide(UICDM::CUICDMGuideHandle hdl, const UICDM::SGuideInfo &inInfo) = 0;
+ virtual void DeleteGuide(UICDM::CUICDMGuideHandle hdl) = 0;
+ virtual void ClearGuides() = 0;
+
+ // Imports a colladafile and, if successful, returns the instance handle from the imported
+ // document.
+ // This function takes care of throwing up dialogues and such if the import fails.
+ // Returns an invalid handle (0) if the import fails.
+ // This is the only true import operation. The rest don't move the files into the
+ // document at this point.
+ virtual TInstanceHandle ImportDAE(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ const Q3DStudio::CString &inImportFileExtension,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) = 0;
+
+ virtual TInstanceHandle LoadImportFile(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(),
+ long inStartTime = -1) = 0;
+ // Automap an image into the scene
+ virtual TInstanceHandle AutomapImage(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) = 0;
+
+ virtual TInstanceHandle LoadMesh(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) = 0;
+
+ virtual TInstanceHandle LoadBehavior(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime) = 0;
+
+ virtual TInstanceHandle LoadRenderPlugin(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime) = 0;
+
+ virtual TInstanceHandle LoadCustomMaterial(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime,
+ TInstanceHandle inTargetId = TInstanceHandle()) = 0;
+
+ // Create text from the font file
+ virtual TInstanceHandle CreateText(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ const CPt &inPosition = CPt(), long inStartTime = -1) = 0;
+
+ virtual TInstanceHandle LoadEffect(const Q3DStudio::CString &inFullPathToDocument,
+ TInstanceHandle inParent, TSlideHandle inSlide,
+ DocumentEditorInsertType::Enum inDropType,
+ long inStartTime) = 0;
+
+ virtual TInstanceHandle
+ ImportFile(DocumentEditorFileType::Enum inFileType,
+ const Q3DStudio::CString &inFullPathToDocument, TInstanceHandle inParent,
+ TSlideHandle inSlide, const Q3DStudio::CString &inImportFileExtension,
+ DocumentEditorInsertType::Enum inDropType = DocumentEditorInsertType::LastChild,
+ const CPt &inPosition = CPt(), long inStartTime = -1) = 0;
+
+ // Refresh an import or dae file
+ // Absolute path to the file.
+ virtual void RefreshImport(const CFilePath &inOldFile, const CFilePath &inNewFile) = 0;
+
+ virtual void ReplaceTextFontNameWithTextFileStem(uic::render::ITextRenderer &inRenderer) = 0;
+
+ virtual void ExternalizePath(TInstanceHandle path) = 0;
+ virtual void InternalizePath(TInstanceHandle path) = 0;
+
+ static std::shared_ptr<IDOMReader>
+ ParseLuaFile(const Q3DStudio::CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory);
+
+ static std::shared_ptr<IDOMReader>
+ ParseScriptFile(const Q3DStudio::CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory);
+
+ static std::shared_ptr<IDOMReader>
+ ParsePluginFile(const Q3DStudio::CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory);
+
+ static std::shared_ptr<IDOMReader>
+ ParseCustomMaterialFile(const Q3DStudio::CFilePath &inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ uic::render::IInputStreamFactory &inInputStreamFactory);
+
+ static void DisplayImportErrors(const QString &inImportSource,
+ UICIMP::ImportErrorCodes::Enum inImportError,
+ std::shared_ptr<IImportFailedHandler> inHandler,
+ UICIMP::STranslationLog &inLog, bool inForceError = false);
+};
+
+struct ScopedDocumentEditor
+{
+ IDocumentEditor &m_Editor;
+ ScopedDocumentEditor(IDoc &inDoc, const Q3DStudio::CString &inCommandName, const char *inFile,
+ int inLine);
+ ~ScopedDocumentEditor() { m_Editor.Release(); }
+ IDocumentEditor *operator->() { return &m_Editor; }
+};
+
+#define SCOPED_DOCUMENT_EDITOR(doc, cmdname) ScopedDocumentEditor(doc, Q3DStudio::CString::fromQString(cmdname), __FILE__, __LINE__)
+
+class CUpdateableDocumentEditor
+{
+ IDoc &m_EditorIDocDoc;
+ const char *m_File;
+ int m_Line;
+
+ CUpdateableDocumentEditor(const CUpdateableDocumentEditor &other);
+ CUpdateableDocumentEditor &operator=(const CUpdateableDocumentEditor &other);
+
+public:
+ CUpdateableDocumentEditor(IDoc &inDoc)
+ : m_EditorIDocDoc(inDoc)
+ , m_File(NULL)
+ {
+ }
+ ~CUpdateableDocumentEditor();
+ IDoc &GetEditorDoc() { return m_EditorIDocDoc; }
+ bool HasEditor() const;
+ IDocumentEditor &EnsureEditor(const wchar_t *inCommandName, const char *inFile, int inLine);
+ void FireImmediateRefresh(UICDM::CUICDMInstanceHandle *inInstances, long inInstanceCount);
+ void FireImmediateRefresh(UICDM::CUICDMInstanceHandle inInstance)
+ {
+ FireImmediateRefresh(&inInstance, 1);
+ }
+ void CommitEditor();
+ void RollbackEditor();
+};
+
+#define ENSURE_EDITOR(cmdName) EnsureEditor(cmdName, __FILE__, __LINE__)
+
+class IInternalDocumentEditor : public IDocumentEditor
+{
+public:
+ virtual ~IInternalDocumentEditor() {}
+ static std::shared_ptr<IInternalDocumentEditor> CreateEditor(CDoc &doc);
+};
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h b/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h
new file mode 100644
index 00000000..59708e95
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef IDOCUMENTREADERH
+#define IDOCUMENTREADERH
+#include "UICDMDataTypes.h"
+#include "foundation/Qt3DSOption.h"
+#include <vector>
+#include <utility>
+#include "StudioObjectTypes.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "UICFileTools.h"
+
+namespace UICDM {
+class IDOMWriter;
+class IDOMReader;
+struct SGuideInfo;
+}
+
+namespace UICIMP {
+class ITranslator;
+struct STranslationLog;
+}
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace Q3DStudio {
+using std::shared_ptr;
+class IDynamicLua;
+
+typedef std::vector<std::pair<UICDM::CUICDMSlideHandle, UICDM::CUICDMInstanceHandle>>
+ TSlideInstanceList;
+typedef std::vector<std::pair<UICDM::CUICDMSlideHandle, Q3DStudio::CString>> TSlideStringList;
+typedef std::unordered_map<const wchar_t *, TSlideInstanceList> TCharPtrToSlideInstanceMap;
+using qt3ds::foundation::Option;
+using UICDM::CUICDMInstanceHandle;
+using UICDM::CUICDMPropertyHandle;
+using UICDM::CUICDMSlideHandle;
+using UICDM::CUICDMKeyframeHandle;
+using UICDM::CUICDMActionHandle;
+using UICDM::CUICDMAnimationHandle;
+using UICDM::SValue;
+using UICDM::IDOMReader;
+using UICDM::IDOMWriter;
+
+// Reader class to read complex information from the document. Encapsulates the various UICDM
+// subsystems
+// Implemented in DocumentEditor.cpp
+class IDocumentReader
+{
+protected:
+ virtual ~IDocumentReader() {}
+public:
+ typedef CUICDMInstanceHandle TInstanceHandle;
+ typedef CUICDMPropertyHandle TPropertyHandle;
+ typedef CUICDMSlideHandle TSlideHandle;
+ typedef CUICDMKeyframeHandle TKeyframeHandle;
+ typedef UICDM::SValue SValue;
+ typedef std::pair<TSlideHandle, SValue> TSlideValuePair;
+ typedef std::vector<TSlideValuePair> TSlideValuePairList;
+ typedef std::vector<TSlideHandle> TSlideList;
+ typedef std::vector<TInstanceHandle> TInstanceList;
+ typedef std::vector<TPropertyHandle> TPropertyList;
+
+ // Returns true if this handle points to a valid instance.
+ virtual bool IsInstance(TInstanceHandle inInstance) const = 0;
+ virtual bool IsCurrentlyActive(TInstanceHandle inInstance) const = 0;
+ // Find a property on an instance by name. Searches derivation parents as well
+ virtual TPropertyHandle FindProperty(TInstanceHandle instance, const wchar_t *inName) const = 0;
+ // Get the instance property value by going through the current slide
+ // This will convert image properties to source paths. If this is not desired, then use
+ virtual Option<SValue> GetInstancePropertyValue(TInstanceHandle instance,
+ TPropertyHandle inProperty) const = 0;
+ // This will not convert image properties to source paths, they will come across as guids.
+ virtual Option<SValue> GetRawInstancePropertyValue(TInstanceHandle instance,
+ TPropertyHandle inProperty) const = 0;
+ // Get an image instance by dereferencing this property pair
+ virtual TInstanceHandle GetImageInstanceForProperty(TInstanceHandle instance,
+ TPropertyHandle inProperty) const = 0;
+ // Get the property value for this instance from this slide without doing normal slide lookup.
+ // If inSlide isn't valid, returns the property value for this instance directly from the data
+ // core.
+ virtual Option<SValue> GetSpecificInstancePropertyValue(TSlideHandle inSlide,
+ TInstanceHandle instance,
+ TPropertyHandle inProperty) const = 0;
+
+ virtual Q3DStudio::CString GetObjectTypeName(TInstanceHandle instance) const = 0;
+
+ virtual CString GetName(CUICDMInstanceHandle inInstance) const = 0;
+ virtual TInstanceHandle GetFirstBaseClass(CUICDMInstanceHandle inInstance) const = 0;
+ virtual CString GetSourcePath(CUICDMInstanceHandle inInstance) const = 0;
+
+ template <typename TDataType>
+ inline Option<TDataType> GetTypedInstancePropertyValue(TInstanceHandle instance,
+ TPropertyHandle inProperty);
+ // Get every property value associated with this instance, from the data core up. The
+ // associated slide will be NULL for the
+ // data core.
+ virtual void GetAllPropertyValues(TInstanceHandle instance, TPropertyHandle inProperty,
+ TSlideValuePairList &outList) const = 0;
+ // Get the slide this instance was created under
+ virtual TSlideHandle GetAssociatedSlide(TInstanceHandle inInstance) const = 0;
+ // Is this a master slide?
+ virtual bool IsMasterSlide(TSlideHandle inSlide) const = 0;
+ // Get the component this instance was created under.
+ virtual TInstanceHandle GetAssociatedComponent(TInstanceHandle inInstance) const = 0;
+ // Get the slide that is currently active for this instance in the UI.
+ virtual TSlideHandle GetActiveSlide(TInstanceHandle inInstance) const = 0;
+ // Return the active slide for the given component.
+ virtual TSlideHandle GetComponentActiveSlide(TInstanceHandle inInstance) const = 0;
+ // Get the component who owns a given slide.
+ virtual TInstanceHandle GetComponentForSlide(TSlideHandle inSlide) const = 0;
+ // Get every slide, starting with the associated slide (the master slide) that
+ // this instance is associated with. So the first slide will be the slide this
+ // instance was created under, then next slides will be that associated slide's
+ // children.
+ virtual void GetAllAssociatedSlides(TInstanceHandle inInstance, TSlideList &outList) const = 0;
+
+ // Returns true if this object is the scene or a components
+ virtual bool IsComponent(TInstanceHandle inInstance) const = 0;
+
+ // Get all the source paths for this instance. If the slide is zero, this means the source
+ // path is set in the data core. Else this indicates exactly which slide the source path is
+ // set under.
+ virtual void GetAllSourcePaths(TInstanceHandle inInstance,
+ TSlideStringList &outPaths) const = 0;
+
+ // Get a map from string table string (datacore.GetStringTable().RegisterStr()) to
+ // a list of slide/instance pairs that indicate, for a given source path, which instances
+ // link to that source path and under which slide.
+ // Pass in true if you want the map keys to include the identifiers (#1, #2).
+ virtual void GetSourcePathToInstanceMap(TCharPtrToSlideInstanceMap &outInstanceMap,
+ bool inIncludeIdentifiers = true) const = 0;
+ // Get a map from string table string to list of slide/instance pairs that indicates, for a
+ // given source path,
+ // which instances link to that source path under which slide.
+ virtual void GetImportPathToInstanceMap(TCharPtrToSlideInstanceMap &outInstanceMap) const = 0;
+
+ // Return true if a property is linked (exists only on the associated slide).
+ virtual bool CanPropertyBeLinked(TInstanceHandle inInstance,
+ TPropertyHandle inProperty) const = 0;
+ virtual bool IsPropertyLinked(TInstanceHandle inInstance, TPropertyHandle inProperty) const = 0;
+
+ // If this property is linked, return the associated slide for the instance.
+ // If this property is unlinked, return the active slide.
+ virtual TSlideHandle GetSlideForProperty(TInstanceHandle inInstance,
+ TPropertyHandle inProperty) const = 0;
+ // Return true if this instance is an imported instance.
+ virtual bool IsImported(TInstanceHandle inInstance) const = 0;
+ virtual CString GetImportId(TInstanceHandle inInstance) const = 0;
+ virtual CString GetFileId(TInstanceHandle inInstance) const = 0;
+
+ // Return (start,end), inclusive, that represent this instance's lifetime.
+ virtual std::pair<long, long> GetTimeRange(TInstanceHandle instance) const = 0;
+ virtual std::pair<long, long> GetTimeRangeInSlide(CUICDMSlideHandle inSlide,
+ TInstanceHandle instance) const = 0;
+ // Get the GUID for a given instance.
+ virtual UICDM::SLong4 GetGuidForInstance(TInstanceHandle instance) const = 0;
+ virtual TInstanceHandle GetInstanceForGuid(const UICDM::SLong4 &inGuid) const = 0;
+ virtual TInstanceHandle
+ GetInstanceForObjectRef(TInstanceHandle inRootInstance,
+ const UICDM::SObjectRefType &inReference) const = 0;
+ // Get the scene graph parent of this instance
+ virtual TInstanceHandle GetParent(TInstanceHandle child) const = 0;
+ // Get all the children if this instance in this slide. If the slide is invalid,
+ // the get all the children of this parent in all slides.
+ virtual void GetChildren(TSlideHandle inSlide, TInstanceHandle inParent,
+ TInstanceList &outChildren) const = 0;
+ // Returns true if this instance is anywhere the scene graph
+ virtual bool IsInSceneGraph(TInstanceHandle child) const = 0;
+
+ virtual bool IsPathExternalizeable(TInstanceHandle path) const = 0;
+ virtual bool IsPathInternalizeable(TInstanceHandle path) const = 0;
+
+ virtual bool AnimationExists(TSlideHandle inSlide, TInstanceHandle instance,
+ const wchar_t *propName, long subIndex) = 0;
+ virtual bool IsAnimationArtistEdited(TSlideHandle inSlide, TInstanceHandle instance,
+ const wchar_t *propName, long subIndex) = 0;
+
+ virtual UICDM::TGuideHandleList GetGuides() const = 0;
+ virtual UICDM::SGuideInfo GetGuideInfo(UICDM::CUICDMGuideHandle inGuide) const = 0;
+ virtual bool IsGuideValid(UICDM::CUICDMGuideHandle inGuide) const = 0;
+ virtual bool AreGuidesEditable() const = 0;
+ // This can be done outside a transaction, hence it is an operation on the reader
+ // not on the editor.
+ virtual void SetGuidesEditable(bool inEditable) = 0;
+
+ // Given the active slide on the document (which we query) and an instance,
+ // produce a temporary file (CUICFile::GetTemporaryFile) and serialize this object
+ // to that temporary file.
+ virtual CFilePath CopySceneGraphObjects(UICDM::TInstanceHandleList inInstances) = 0;
+
+ CFilePath CopySceneGraphObject(CUICDMInstanceHandle inInstance)
+ {
+ UICDM::TInstanceHandleList theInstances;
+ theInstances.push_back(inInstance);
+ return CopySceneGraphObjects(theInstances);
+ }
+
+ // Copy the object just to a DOM representation, don't serialize to file.
+ virtual std::shared_ptr<UICDM::IDOMReader>
+ CopySceneGraphObjectToMemory(CUICDMInstanceHandle inInstance) = 0;
+
+ virtual CFilePath CopyAction(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide) = 0;
+
+ virtual void ParseSourcePathsOutOfEffectFile(Q3DStudio::CString inFile,
+ std::vector<Q3DStudio::CString> &outFilePaths) = 0;
+
+ virtual Q3DStudio::CString GetCustomMaterialName(const Q3DStudio::CString &inFullPathToFile) const = 0;
+
+ // Must not be a master slide. Used during duplicate slide.
+ virtual std::shared_ptr<UICDM::IDOMReader> CopySlide(CUICDMSlideHandle inSlide) = 0;
+
+ // Don't release this, it is owned and cached by the document. Also, reset top to 0 with a
+ // scope, please.
+ virtual IDynamicLua *GetLuaContext() = 0;
+ virtual qt3ds::NVFoundationBase &GetFoundation() = 0;
+};
+
+template <typename TDataType>
+inline Option<TDataType> IDocumentReader::GetTypedInstancePropertyValue(TInstanceHandle instance,
+ TPropertyHandle inProperty)
+{
+ Option<SValue> theValue = GetInstancePropertyValue(instance, inProperty);
+ if (theValue.isEmpty())
+ return qt3ds::foundation::Empty();
+ return UICDM::get<TDataType>(*theValue);
+}
+
+// Helper function needed by a few objects
+inline EStudioObjectType GetStudioObjectType(UICDM::ComposerObjectTypes::Enum inType)
+{
+ using namespace UICDM;
+ switch (inType) {
+ case ComposerObjectTypes::Scene:
+ return OBJTYPE_SCENE;
+ case ComposerObjectTypes::Layer:
+ return OBJTYPE_LAYER;
+ case ComposerObjectTypes::Behavior:
+ return OBJTYPE_BEHAVIOR;
+ case ComposerObjectTypes::Material:
+ return OBJTYPE_MATERIAL;
+ case ComposerObjectTypes::Camera:
+ return OBJTYPE_CAMERA;
+ case ComposerObjectTypes::Light:
+ return OBJTYPE_LIGHT;
+ case ComposerObjectTypes::Model:
+ return OBJTYPE_MODEL;
+ case ComposerObjectTypes::Group:
+ return OBJTYPE_GROUP;
+ case ComposerObjectTypes::Image:
+ return OBJTYPE_IMAGE;
+ case ComposerObjectTypes::Text:
+ return OBJTYPE_TEXT;
+ case ComposerObjectTypes::Component:
+ return OBJTYPE_COMPONENT;
+ case ComposerObjectTypes::Effect:
+ return OBJTYPE_EFFECT;
+ case ComposerObjectTypes::Path:
+ return OBJTYPE_PATH;
+ default: ;
+ }
+ return OBJTYPE_UNKNOWN;
+}
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IDragable.h b/src/Authoring/Client/Code/Core/Doc/IDragable.h
new file mode 100644
index 00000000..9e6c2781
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDragable.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __IDRAGABLE_H__
+#define __IDRAGABLE_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Enums
+//==============================================================================
+enum EUIC_FLAVOR {
+ EUIC_FLAVOR_FILE = 15,
+ EUIC_FLAVOR_TEXT = 1,
+ EUIC_FLAVOR_LISTBOX = 'LBOX',
+ EUIC_FLAVOR_BASIC_OBJECTS = 'UIBO',
+ EUIC_FLAVOR_ASSET_LIB = 'UILB',
+ EUIC_FLAVOR_ASSET_TL = 'UITL',
+ EUIC_FLAVOR_ASSET_UICFILE = 'UIFI',
+};
+
+//==============================================================================
+/**
+ * @class
+ * @brief IDragable provides an interface to abstract dragging from assets to be able
+ * to drag non-assets
+ */
+class IDragable
+{
+public:
+ virtual long GetFlavor() const = 0;
+};
+
+#endif // #ifndef __IDRAGABLE_H__
diff --git a/src/Authoring/Client/Code/Core/Doc/IDropTargetHelper.h b/src/Authoring/Client/Code/Core/Doc/IDropTargetHelper.h
new file mode 100644
index 00000000..d4b80a24
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IDropTargetHelper.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __IDROPTARGETHELPER_H__
+#define __IDROPTARGETHELPER_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Pt.h"
+
+class CCmd;
+
+namespace Q3DStudio {
+
+class IDropTargetHelper
+{
+public:
+ virtual void SetViewTimeAsStartTime() = 0;
+ virtual void SetObjectPosition(const CPt &inPoint) = 0;
+ virtual CCmd *GetCommand() = 0;
+};
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IKeyframe.h b/src/Authoring/Client/Code/Core/Doc/IKeyframe.h
new file mode 100644
index 00000000..52c21264
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IKeyframe.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_IKEYFRAME_H
+#define INCLUDED_IKEYFRAME_H 1
+
+#pragma once
+
+//==============================================================================
+/**
+ * Abstraction of a animation keyframe.
+ */
+//==============================================================================
+class IKeyframe
+{
+public:
+ virtual ~IKeyframe() {}
+
+ virtual bool IsSelected() const = 0;
+ /*
+ * return time in millisecs.
+ */
+ virtual long GetTime() const = 0;
+ /*
+ * @param inNewTime time in millisecs.
+ */
+ virtual void SetTime(const long inNewTime) = 0;
+ virtual void SetDynamic(bool inIsDynamic) = 0;
+ virtual bool IsDynamic() const = 0;
+};
+
+#endif // INCLUDED_IKEYFRAME_H
diff --git a/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h b/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h
new file mode 100644
index 00000000..da45d8a7
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/IKeyframesManager.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_IKEYFRAMES_MANAGER_H
+#define INCLUDED_IKEYFRAMES_MANAGER_H 1
+
+#pragma once
+
+//=============================================================================
+/**
+ * Interface to manage keyframes related actions
+ */
+//=============================================================================
+class IKeyframesManager
+{
+public:
+ virtual ~IKeyframesManager() {}
+
+ virtual bool HasSelectedKeyframes(bool inOnlyDynamic = false) = 0;
+ virtual bool HasDynamicKeyframes() = 0;
+ virtual bool CanPerformKeyframeCopy() = 0;
+ virtual bool CanPerformKeyframePaste() = 0;
+ virtual void CopyKeyframes() = 0;
+ virtual bool RemoveKeyframes(bool inPerformCopy) = 0;
+ virtual void PasteKeyframes() = 0;
+ virtual void SetKeyframeInterpolation() = 0;
+ virtual void SelectAllKeyframes() = 0;
+ virtual void DeselectAllKeyframes() = 0;
+ virtual void SetChangedKeyframes() = 0;
+};
+
+#endif // INCLUDED_IKEYFRAMES_MANAGER_H
diff --git a/src/Authoring/Client/Code/Core/Doc/INamable.h b/src/Authoring/Client/Code/Core/Doc/INamable.h
new file mode 100644
index 00000000..1013a98b
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/INamable.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __INAMABLE_H__
+#define __INAMABLE_H__
+
+#include <UICString.h>
+
+//==============================================================================
+/**
+ * @class : Interface to a asset which has a getter/setter for name property
+ */
+class INamable
+{
+public:
+ virtual Q3DStudio::CString GetName() const = 0;
+ virtual void SetName(const Q3DStudio::CString &inName) = 0;
+};
+
+#endif // #ifndef __INAMABLE_H__
diff --git a/src/Authoring/Client/Code/Core/Doc/PathImportTranslator.cpp b/src/Authoring/Client/Code/Core/Doc/PathImportTranslator.cpp
new file mode 100644
index 00000000..d4c566ae
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/PathImportTranslator.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "PathImportTranslator.h"
+#include "UICImportComposerTypes.h"
+#include "foundation/IOStreams.h"
+#include "DynamicLua.h"
+#include "UICImport.h"
+#include "UICImportPath.h"
+
+using namespace Q3DStudio;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace UICIMP;
+
+SPathImportTranslator::SPathImportTranslator(const QString &srcFile, IDynamicLua &inLuaState,
+ qt3ds::NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , m_SourceFile(srcFile)
+ , m_LuaState(inLuaState)
+ , m_Import(NULL)
+{
+}
+
+SPathImportTranslator::~SPathImportTranslator()
+{
+}
+
+void SPathImportTranslator::SetName(TInstanceHandle inItem, const wchar_t *inNameBase)
+{
+ m_Import->SetInstancePropertyValue(inItem, m_ObjectTypes.m_Asset.m_NameProp,
+ Q3DStudio::CString(inNameBase));
+}
+
+void SPathImportTranslator::SetUniqueName(TInstanceHandle inItem, const char8_t *inNameBase,
+ eastl::vector<Q3DStudio::CString> &inExistingNames)
+{
+ Q3DStudio::CString theName(inNameBase);
+ QT3DSU32 idx = 1;
+ while (eastl::find(inExistingNames.begin(), inExistingNames.end(), theName)
+ != inExistingNames.end()) {
+ char8_t nameBuffer[64];
+ sprintf(nameBuffer, "%d", idx);
+ ++idx;
+ theName.assign(inNameBase);
+ theName.append("_");
+ theName.append(nameBuffer);
+ }
+
+ m_Import->SetInstancePropertyValue(inItem, m_ObjectTypes.m_Asset.m_NameProp, theName);
+ inExistingNames.push_back(theName);
+}
+
+QT3DSU64 SPathImportTranslator::GetChild(TInstanceHandle inItem, QT3DSI32 inIndex)
+{
+ QT3DSU32 numChildren = m_Import->GetNumChildren(inItem);
+ m_ChildVector.resize(numChildren);
+ m_Import->GetChildren(inItem, toDataRef(m_ChildVector.data(), m_ChildVector.size()));
+ if (inIndex < (QT3DSI32)m_ChildVector.size())
+ return m_ChildVector[inIndex].m_Handle;
+ return 0;
+}
+
+QT3DSU64 SPathImportTranslator::CreateSceneGraphInstance(
+ UICDM::ComposerObjectTypes::Enum inObjectType, SPathImportTranslator::TInstanceHandle inParent,
+ const Q3DStudio::CString &inId)
+{
+ Q3DStudio::CString theIdStr(inId);
+ QT3DSU32 idx = 1;
+ while (m_Import->FindAnyInstanceById(theIdStr).hasValue()) {
+ char8_t nameBuffer[64];
+ sprintf(nameBuffer, "%d", idx);
+ ++idx;
+ theIdStr.assign(inId);
+ theIdStr.append("_");
+ theIdStr.append(nameBuffer);
+ }
+ TInstanceHandle retval = m_Import->CreateInstance(theIdStr, inObjectType);
+ if (inParent)
+ m_Import->AddChild(inParent, retval);
+ return retval;
+}
+
+void SPathImportTranslator::ParseSVGGroupChildren(TInstanceHandle inNewItem)
+{
+ IDynamicLua::Scope __itemScope(m_LuaState);
+ QT3DSI32 numChildren = m_LuaState.GetNumChildrenFromTopOfStackTable();
+ eastl::vector<Q3DStudio::CString> existingNames;
+ // parse children in reverse order so they will render correctly.
+ for (QT3DSI32 idx = 0; idx < numChildren; ++idx) {
+ QT3DSI32 relIdx = numChildren - idx;
+ m_LuaState.GetChildFromTopOfStackTable(relIdx);
+ ParseSVGItem(inNewItem, existingNames);
+ m_LuaState.SetTop(__itemScope.m_Top);
+ }
+}
+
+QT3DSU64 SPathImportTranslator::ParseSVGGroup(TInstanceHandle inParent,
+ eastl::vector<Q3DStudio::CString> &inExistingNames,
+ bool inRoot)
+{
+ eastl::string itemType = m_LuaState.StringFromTopOfStackTable("TYPE");
+ eastl::string itemName = m_LuaState.StringFromTopOfStackTable("name");
+ eastl::string idItem(itemName);
+ if (itemName.size() == 0)
+ itemName = "Group";
+ // bool success = m_LuaState.GetChildFromTopOfStackTable( 1 );
+ if (inRoot)
+ idItem = "__import__root__";
+ TInstanceHandle retval =
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Group, inParent, idItem.c_str());
+ SetUniqueName(retval, itemName.c_str(), inExistingNames);
+ ParseSVGGroupChildren(retval);
+ return retval;
+}
+
+namespace {
+QT3DSF32 ToUICDM(Option<QT3DSF32> inData, QT3DSF32 inDefault)
+{
+ if (inData.hasValue())
+ return *inData;
+ return inDefault;
+}
+SFloat3 ToUICDM(const QT3DSVec3 &inData)
+{
+ return SFloat3(inData.x, inData.y, inData.z);
+}
+bool ToUICDM(Option<bool> inData, bool inDefault)
+{
+ if (inData.hasValue())
+ return *inData;
+ return inDefault;
+}
+}
+
+QT3DSU64 SPathImportTranslator::ParseSVGPath(TInstanceHandle inParent,
+ eastl::vector<Q3DStudio::CString> &inExistingNames)
+{
+ QT3DSF32 strokeWidth = ToUICDM(m_LuaState.NumberFromTopOfStackTable("stroke-width"), 1.0f);
+ QT3DSF32 pathOpacity = ToUICDM(m_LuaState.NumberFromTopOfStackTable("opacity"), 100.0f);
+ QT3DSF32 fillOpacity = ToUICDM(m_LuaState.NumberFromTopOfStackTable("fill-opacity"), 100.0f);
+ QT3DSF32 strokeOpacity = ToUICDM(m_LuaState.NumberFromTopOfStackTable("stroke-opacity"), 100.0f);
+ Option<QT3DSVec3> fillColor = m_LuaState.Vec3FromTopOfStackTable("fill");
+ Option<QT3DSVec3> strokeColor = m_LuaState.Vec3FromTopOfStackTable("stroke");
+ eastl::string pathName = m_LuaState.StringFromTopOfStackTable("name");
+ QT3DSI32 childIndex = 1;
+ eastl::vector<Q3DStudio::CString> existingNames;
+ bool hasStroke = strokeColor.hasValue();
+ bool hasFill = fillColor.hasValue();
+ if (!hasStroke && !hasFill)
+ return TInstanceHandle();
+ TInstanceHandle retval =
+ CreateSceneGraphInstance(ComposerObjectTypes::Path, inParent, pathName.c_str());
+ SetUniqueName(retval, pathName.c_str(), inExistingNames);
+ CreateSceneGraphInstance(ComposerObjectTypes::Material, retval, "Stroke");
+ {
+ TInstanceHandle strokeMaterial = GetChild(retval, 0);
+ SetName(strokeMaterial, L"Stroke");
+ }
+ eastl::vector<qt3ds::QT3DSVec2> thePoints;
+ if (!m_Builder)
+ m_Builder = UICIMP::IPathBufferBuilder::CreateBuilder(m_Foundation);
+ else
+ m_Builder->Clear();
+
+ for (bool success = m_LuaState.GetChildFromTopOfStackTable(childIndex); success;
+ ++childIndex, success = m_LuaState.GetChildFromTopOfStackTable(childIndex)) {
+ bool isClosed = ToUICDM(m_LuaState.BooleanFromTopOfStackTable("closepath"), true);
+ // Note that this pops the child off the stack so it is no longer available as it is the
+ // first argument
+ // to the coordinates function.
+ if (!m_LuaState.ExecuteFunction("SVGPARSER", "coordinates", 1, 1))
+ continue;
+ int theTop1 = m_LuaState.GetTop();
+ thePoints.clear();
+ m_LuaState.ParseFloatingPointPairArray(thePoints);
+ int theTop2 = m_LuaState.GetTop();
+ QT3DSU32 numAnchors = (thePoints.size() / 3) + 1;
+ if (thePoints.size() == 0)
+ numAnchors = 0;
+
+ for (QT3DSU32 idx = 0, end = numAnchors; idx < end; ++idx) {
+ QT3DSU32 pointIdx = idx * 3;
+ QT3DSVec2 position(thePoints[pointIdx]);
+
+ if (idx) {
+ QT3DSVec2 c1(thePoints[pointIdx - 2]);
+ QT3DSVec2 c2(thePoints[pointIdx - 1]);
+ m_Builder->CubicCurveTo(c1, c2, position);
+ } else
+ m_Builder->MoveTo(position);
+ }
+ if (isClosed)
+ m_Builder->Close();
+ }
+
+ Q3DStudio::CString relativePath;
+ UICIMP::InstanceDesc thePathItem = m_Import->GetInstanceByHandle(retval);
+ UICIMP::SPathBuffer theBuffer(m_Builder->GetPathBuffer());
+ relativePath = m_Import->AddPathBuffer(theBuffer, thePathItem.m_Id).m_Value;
+ m_Import->SetInstancePropertyValue(retval, m_ObjectTypes.m_Asset.m_SourcePath, relativePath);
+ m_Import->SetInstancePropertyValue(retval, m_ObjectTypes.m_Node.m_Opacity, pathOpacity);
+ m_Import->SetInstancePropertyValue(retval, m_ObjectTypes.m_Path.m_Width, strokeWidth);
+
+ if (hasFill) {
+ m_Import->SetInstancePropertyValue(retval, m_ObjectTypes.m_Path.m_PathType, L"Painted");
+ QT3DSI32 fillMaterialIndex = 1;
+ if (hasStroke == false) {
+ fillMaterialIndex = 0;
+ m_Import->SetInstancePropertyValue(retval, m_ObjectTypes.m_Path.m_PaintStyle,
+ L"Filled");
+ } else {
+ m_Import->SetInstancePropertyValue(retval, m_ObjectTypes.m_Path.m_PaintStyle,
+ L"Filled and Stroked");
+ CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Material, retval, "Fill");
+ }
+
+ TInstanceHandle theFillMaterial = GetChild(retval, fillMaterialIndex);
+ m_Import->SetInstancePropertyValue(theFillMaterial, m_ObjectTypes.m_Material.m_DiffuseColor,
+ ToUICDM(*fillColor));
+ m_Import->SetInstancePropertyValue(theFillMaterial, m_ObjectTypes.m_Material.m_Opacity,
+ fillOpacity);
+ }
+ if (hasStroke) {
+ TInstanceHandle theStrokeMaterial = GetChild(retval, 0);
+ m_Import->SetInstancePropertyValue(
+ theStrokeMaterial, m_ObjectTypes.m_Material.m_DiffuseColor, ToUICDM(*strokeColor));
+ m_Import->SetInstancePropertyValue(theStrokeMaterial, m_ObjectTypes.m_Material.m_Opacity,
+ strokeOpacity);
+ }
+ return retval;
+}
+
+QT3DSU64 SPathImportTranslator::ParseSVGItem(TInstanceHandle inParent,
+ eastl::vector<Q3DStudio::CString> &inExistingNames,
+ bool inIsRoot)
+{
+ IDynamicLua::Scope __itemScope(m_LuaState);
+ eastl::string objType = m_LuaState.StringFromTopOfStackTable("TYPE");
+ if (objType == "group")
+ return ParseSVGGroup(inParent, inExistingNames, inIsRoot);
+ else
+ return ParseSVGPath(inParent, inExistingNames);
+}
+
+bool SPathImportTranslator::PerformTranslation(UICIMP::Import &import)
+{
+ m_Import = &import;
+ eastl::vector<QT3DSU8> fileData;
+ {
+ QFile theFile(m_SourceFile);
+ if (theFile.open(QIODevice::ReadOnly)) {
+ QT3DSU8 buf[1024];
+
+ for (qint64 amountRead = theFile.read(reinterpret_cast<char *>(buf), 1024); amountRead;
+ amountRead = theFile.read(reinterpret_cast<char *>(buf), 1024)) {
+ fileData.insert(fileData.end(), buf, buf + amountRead);
+ }
+ }
+ }
+ if (fileData.size() == 0)
+ return false;
+
+ fileData.push_back(0);
+ fileData.push_back(0); // just in case utf-16
+
+ IDynamicLua::Scope __parseScope(m_LuaState);
+
+ eastl::vector<QT3DSVec2> thePoints;
+ TIMPHandle retval(0);
+
+ if (m_LuaState.ExecuteFunction("SVGPARSER", "pathsfromxml", (const char8_t *)fileData.data())) {
+ // Build list of names already under parent.
+ eastl::vector<Q3DStudio::CString> existingNames;
+ TIMPHandle newItem = ParseSVGItem(0, existingNames, true);
+ if (!retval)
+ retval = newItem;
+ }
+ return retval ? true : false;
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/PathImportTranslator.h b/src/Authoring/Client/Code/Core/Doc/PathImportTranslator.h
new file mode 100644
index 00000000..600e688a
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/PathImportTranslator.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PATH_IMPORT_TRANSLATOR_H
+#define PATH_IMPORT_TRANSLATOR_H
+#include "UICImportTranslation.h"
+#include "UICImportComposerTypes.h"
+#include "UICImport.h"
+#include "foundation/Qt3DSRefCounted.h"
+namespace UICIMP {
+class IPathBufferBuilder;
+}
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace Q3DStudio {
+class IDynamicLua;
+struct SPathImportTranslator : public UICIMP::ITranslator
+{
+ typedef eastl::vector<Q3DStudio::CString> TNameList;
+ typedef QT3DSU64 TInstanceHandle;
+
+ qt3ds::NVFoundationBase &m_Foundation;
+ QString m_SourceFile;
+ UICIMP::STranslationLog m_TranslationLog;
+ IDynamicLua &m_LuaState;
+ UICIMP::Import *m_Import;
+ UICIMP::SImportComposerTypes m_ObjectTypes;
+ eastl::vector<UICIMP::InstanceDesc> m_ChildVector;
+ qt3ds::foundation::NVScopedRefCounted<UICIMP::IPathBufferBuilder> m_Builder;
+
+ SPathImportTranslator(const QString &srcFile, IDynamicLua &inLuaState,
+ qt3ds::NVFoundationBase &inFoundation);
+ ~SPathImportTranslator();
+
+ // Object is created on the stack, no reason to release.
+ void Release() override {}
+
+ const QString &GetSourceFile() override { return m_SourceFile; }
+ // Returning false causes the rest of the import or refresh process
+ // to fail.
+ bool PerformTranslation(UICIMP::Import &import) override;
+
+protected:
+ void SetName(TInstanceHandle inItem, const wchar_t *inNameBase);
+ void SetUniqueName(TInstanceHandle inItem, const char8_t *inNameBase,
+ eastl::vector<Q3DStudio::CString> &inExistingNames);
+ TInstanceHandle GetChild(TInstanceHandle inItem, qt3ds::QT3DSI32 inIndex);
+ TInstanceHandle CreateSceneGraphInstance(UICDM::ComposerObjectTypes::Enum inObjectTypes,
+ TInstanceHandle inParent,
+ const Q3DStudio::CString &inId);
+ TInstanceHandle ParseSVGItem(TInstanceHandle parentHandle, TNameList &existingChildNames,
+ bool inRoot = false);
+ void ParseSVGGroupChildren(TInstanceHandle inNewItem);
+ TInstanceHandle ParseSVGGroup(TInstanceHandle inParent,
+ eastl::vector<Q3DStudio::CString> &inExistingNames, bool inRoot);
+ TInstanceHandle ParseSVGPath(TInstanceHandle inParent,
+ eastl::vector<Q3DStudio::CString> &inExistingNames);
+};
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/RelativePathTools.cpp b/src/Authoring/Client/Code/Core/Doc/RelativePathTools.cpp
new file mode 100644
index 00000000..a93a35b0
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/RelativePathTools.cpp
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "RelativePathTools.h"
+#include "PathConstructionHelper.h"
+#include "StackTokenizer.h"
+#include "Doc.h"
+#include "IObjectReferenceHelper.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+#include "UICDMDataCore.h"
+
+namespace {
+bool IsEmpty(const UICDM::SObjectRefType &inObjectRefValue)
+{
+ switch (inObjectRefValue.GetReferenceType()) {
+ case UICDM::ObjectReferenceType::Absolute: {
+ UICDM::SLong4 theValue = UICDM::get<UICDM::SLong4>(inObjectRefValue.m_Value);
+ return theValue.m_Longs[0] == theValue.m_Longs[1]
+ && theValue.m_Longs[1] == theValue.m_Longs[2]
+ && theValue.m_Longs[2] == theValue.m_Longs[3] && theValue.m_Longs[3] == 0;
+ } break;
+ case UICDM::ObjectReferenceType::Relative: {
+ UICDM::TDataStrPtr thePath = UICDM::get<UICDM::TDataStrPtr>(inObjectRefValue.m_Value);
+ if (!thePath || thePath->GetLength() == 0)
+ return true;
+ } break;
+ case UICDM::ObjectReferenceType::Unknown:
+ return true;
+ break;
+ }
+ return false;
+}
+}
+//=============================================================================
+/**
+ * Determine if the asset reference is an GUID type
+ */
+bool CRelativePathTools::IsGUID(const UICDM::SObjectRefType &inObjectRefValue)
+{
+ return inObjectRefValue.GetReferenceType() == UICDM::ObjectReferenceType::Absolute;
+}
+
+//=============================================================================
+/**
+ * Determine if the asset reference is relative
+ */
+bool CRelativePathTools::IsRelativePath(const UICDM::SObjectRefType &inObjectRefValue)
+{
+ return !IsGUID(inObjectRefValue);
+}
+
+//=============================================================================
+/**
+ * Return the path type
+ */
+CRelativePathTools::EPathType
+CRelativePathTools::GetPathType(const UICDM::SObjectRefType &inObjectRefValue)
+{
+ // default to absolute pathing.
+ if (IsEmpty(inObjectRefValue))
+ return EPATHTYPE_GUID;
+
+ if (IsGUID(inObjectRefValue))
+ return EPATHTYPE_GUID;
+ else
+ return EPATHTYPE_RELATIVE;
+}
+
+//=============================================================================
+/**
+ * Build a object reference path, via Ids
+ */
+Q3DStudio::CString
+CRelativePathTools::BuildReferenceString(const UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::CUICDMInstanceHandle inRootInstance,
+ EPathType inPathType, CDoc *inDoc)
+{
+ switch (inPathType) {
+ case EPATHTYPE_GUID:
+ return BuildAbsoluteReferenceString(inInstance, inDoc);
+ case EPATHTYPE_RELATIVE:
+ return BuildRelativeReferenceString(inInstance, inRootInstance, inDoc);
+ };
+ return L"";
+}
+
+//=============================================================================
+/**
+ * Note that this uses object names rather than nice names, because script access is via
+ *property names, in the runtime.
+ */
+Q3DStudio::CString
+CRelativePathTools::BuildAbsoluteReferenceString(const UICDM::CUICDMInstanceHandle inInstance,
+ CDoc *inDoc)
+{
+ if (inInstance.Valid() == false)
+ return L"";
+ Q3DStudio::CString theNameStart;
+ Q3DStudio::CString theNameEnd(
+ CPathConstructionHelper::EscapeAssetName(LookupObjectName(inInstance, inDoc)));
+
+ UICDM::CUICDMInstanceHandle theParentInstance =
+ inDoc->GetStudioSystem()->GetClientDataModelBridge()->GetParentInstance(inInstance);
+ if (theParentInstance.Valid())
+ theNameStart = BuildAbsoluteReferenceString(theParentInstance, inDoc) + ".";
+ theNameStart += theNameEnd;
+ return theNameStart;
+}
+
+Q3DStudio::CString
+CRelativePathTools::BuildRelativeReferenceString(const UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::CUICDMInstanceHandle inRootInstance,
+ CDoc *inDoc)
+{
+ Q3DStudio::CString theAbsRelPath(BuildAbsoluteReferenceString(inInstance, inDoc));
+ Q3DStudio::CString theAbsRootPath(BuildAbsoluteReferenceString(inRootInstance, inDoc));
+ return CPathConstructionHelper::BuildRelativeReferenceString(theAbsRelPath, theAbsRootPath);
+}
+
+//=============================================================================
+/**
+ * Parse the specified path and return the id of the specified object, if the
+ * path does not points an object, the immediate object it manages to travesed to
+ * is return, worst case, the Scene is returned.
+ * @param inRootInstance it the based object passed in, mainly used for relative path
+ * @param inString the path to be resolved
+ * @param outPathType is the path type, either absolute or relative
+ * @param outIsFullyResolved defines whether the inString can completely resolved to an object
+ * @return theId of the object (or the object it manages to traverse to) N.B. this is required
+ * for the Object Ref Picker to highlight that parent object if that token is invalid.
+ */
+UICDM::CUICDMInstanceHandle CRelativePathTools::FindAssetInstanceByObjectPath(
+ CDoc *inDoc, const UICDM::CUICDMInstanceHandle &inRootInstance,
+ const Q3DStudio::CString &inString, EPathType &outPathType, bool &outIsResolved,
+ const IObjectReferenceHelper *inHelper /*= NULL */)
+{
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+
+ CStackTokenizer theTokenizer(inString, CPathConstructionHelper::GetPathDelimiter().GetAt(0),
+ CPathConstructionHelper::GetEscapeChar().GetAt(0));
+ // Default to the scene if asset cannot be found.
+ UICDM::CUICDMInstanceHandle theFoundInstance;
+
+ if (theTokenizer.HasNextPartition()) {
+ Q3DStudio::CString theCurrentToken(theTokenizer.GetCurrentPartition());
+
+ // this is the default path type
+ outPathType = EPATHTYPE_RELATIVE;
+
+ outIsResolved = false;
+
+ // Start parsing from this object
+ if (theCurrentToken.Compare(CPathConstructionHelper::GetThisString(), false)) {
+ outIsResolved = true;
+ theFoundInstance = inRootInstance;
+ outPathType = EPATHTYPE_RELATIVE;
+ } else if (theCurrentToken.Compare(CPathConstructionHelper::GetParentString(), false)) {
+ outIsResolved = true;
+ theFoundInstance = theBridge->GetParentInstance(inRootInstance);
+ outPathType = EPATHTYPE_RELATIVE;
+
+ // Special case for the scene
+ if (!theFoundInstance.Valid())
+ theFoundInstance = inRootInstance;
+ }
+
+ // otherwise, just use the scene (if it's "Scene" or otherwise)
+ ++theTokenizer;
+ }
+
+ if (theFoundInstance.Valid()) {
+ UICDM::CUICDMInstanceHandle theTimeParent =
+ theBridge->GetOwningComponentInstance(theFoundInstance);
+ if (theTimeParent.Valid()) {
+ UICDM::CUICDMSlideHandle theCurrentSlide =
+ theBridge->GetComponentActiveSlide(theTimeParent);
+ return DoFindAssetInstanceByObjectPath(inDoc, theFoundInstance, theTimeParent,
+ theCurrentSlide, theTokenizer, outIsResolved,
+ inHelper);
+ } else
+ return DoFindAssetInstanceByObjectPath(inDoc, theFoundInstance, theTimeParent, 0,
+ theTokenizer, outIsResolved, inHelper);
+ } else {
+ return inDoc->GetSceneInstance();
+ }
+}
+
+UICDM::SObjectRefType
+CRelativePathTools::CreateAssetRefValue(const UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::CUICDMInstanceHandle inRootInstance,
+ EPathType inPathType, CDoc *inDoc)
+{
+ UICDM::SObjectRefType theAssetRefValue;
+ switch (inPathType) {
+ case EPATHTYPE_GUID: {
+ Q3DStudio::TGUIDPacked thePacked(
+ inDoc->GetStudioSystem()->GetClientDataModelBridge()->GetGUID(inInstance));
+ UICDM::SLong4 theGuid(thePacked.Data1, thePacked.Data2, thePacked.Data3, thePacked.Data4);
+ theAssetRefValue = theGuid;
+ break;
+ }
+ case EPATHTYPE_RELATIVE: {
+ theAssetRefValue = UICDM::TDataStrPtr(
+ new UICDM::CDataStr(BuildRelativeReferenceString(inInstance, inRootInstance, inDoc)));
+ break;
+ }
+ default:
+ break;
+ }
+ return theAssetRefValue;
+}
+
+//==============================================================================
+/**
+ * Helper function for FindAssetInstanceByObjectPath( ) method.
+ * Given a root object and a tokenizer for parsing a path, this method will
+ * recurse down a tree of assets until it finds the desired one.
+ * @param inRootAsset the asset to start searching from
+ * @param ioTokenizer a string tokenizer to help parse path of asset.
+ * @return the source ID of the final asset
+ * @see FindAssetInstanceByObjectPath
+ */
+UICDM::CUICDMInstanceHandle CRelativePathTools::DoFindAssetInstanceByObjectPath(
+ CDoc *inDoc, const UICDM::CUICDMInstanceHandle &inRootInstance,
+ const UICDM::CUICDMInstanceHandle inTimeParentInstance, UICDM::CUICDMSlideHandle inSlide,
+ CStackTokenizer &ioTokenizer, bool &outIsResolved, const IObjectReferenceHelper *inHelper)
+{
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+
+ UICDM::CUICDMInstanceHandle theFoundInstance = inRootInstance;
+ // There is another object to parse
+ if (inRootInstance.Valid() && ioTokenizer.HasNextPartition()) {
+ Q3DStudio::CString theCurrentToken(ioTokenizer.GetCurrentPartition());
+ if (theCurrentToken.Length()) {
+ outIsResolved = false;
+ // Parent asset
+ if (theCurrentToken.Compare(CPathConstructionHelper::GetParentString(), false)) {
+ ++ioTokenizer;
+ UICDM::CUICDMInstanceHandle theParentInstance =
+ theBridge->GetParentInstance(inRootInstance);
+ if (theParentInstance.Valid()) {
+ outIsResolved = true;
+ theFoundInstance = DoFindAssetInstanceByObjectPath(
+ inDoc, theParentInstance, inTimeParentInstance, inSlide, ioTokenizer,
+ outIsResolved, inHelper);
+ }
+ }
+ // Find the asset by name
+ else {
+ Q3DStudio::CString theDesiredAssetName(ioTokenizer.GetCurrentPartition());
+
+ if (!outIsResolved && inHelper) {
+ UICDM::TInstanceHandleList theChildList;
+ if (inHelper->GetChildInstanceList(inRootInstance, theChildList, inSlide,
+ inTimeParentInstance)) {
+ for (size_t theIndex = 0; theIndex < theChildList.size(); ++theIndex) {
+ Q3DStudio::CString theCurrentAssetName(
+ LookupObjectName(theChildList[theIndex], inDoc));
+ if (theDesiredAssetName.Compare(theCurrentAssetName, false)) {
+ ++ioTokenizer;
+ outIsResolved = true;
+ theFoundInstance = DoFindAssetInstanceByObjectPath(
+ inDoc, theChildList[theIndex], inTimeParentInstance, inSlide,
+ ioTokenizer, outIsResolved, inHelper);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return outIsResolved ? theFoundInstance : UICDM::CUICDMInstanceHandle(0);
+}
+
+//==============================================================================
+/**
+ * Figures out the object name, used for script access. so that paths are valid in the runtime.
+ */
+Q3DStudio::CString
+CRelativePathTools::LookupObjectName(const UICDM::CUICDMInstanceHandle inInstance, CDoc *inDoc)
+{
+ UICDM::IPropertySystem *thePropertySystem = inDoc->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *theClientBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ if (theClientBridge->IsImageInstance(inInstance)) {
+ UICDM::CUICDMInstanceHandle theParentInstance;
+ UICDM::CUICDMPropertyHandle theProperty;
+ if (!theClientBridge->GetMaterialFromImageInstance(inInstance, theParentInstance,
+ theProperty))
+ theClientBridge->GetLayerFromImageProbeInstance(inInstance, theParentInstance,
+ theProperty);
+ UICDM::TCharStr theName = thePropertySystem->GetName(theProperty);
+ return theName.c_str();
+ } else {
+ UICDM::SValue theNameValue;
+ thePropertySystem->GetInstancePropertyValue(inInstance, theClientBridge->GetNameProperty(),
+ theNameValue);
+ UICDM::TDataStrPtr theName = UICDM::get<UICDM::TDataStrPtr>(theNameValue);
+ return theName->GetData();
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/RelativePathTools.h b/src/Authoring/Client/Code/Core/Doc/RelativePathTools.h
new file mode 100644
index 00000000..31c66f30
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/RelativePathTools.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_RELATIVEPATHTOOLS_H
+#define INCLUDED_RELATIVEPATHTOOLS_H 1
+
+#pragma once
+
+#include "UICDMDataTypes.h"
+#include "UICDMHandles.h"
+#include "UICString.h"
+
+class CAsset;
+class CStackTokenizer;
+class IObjectReferenceHelper;
+class CDoc;
+
+class CRelativePathTools
+{
+ //==============================================================================
+ // Enumeration
+ //==============================================================================
+public:
+ enum EPathType {
+ EPATHTYPE_GUID = 0,
+ EPATHTYPE_RELATIVE,
+ };
+
+ //==============================================================================
+ // Static Methods
+ //==============================================================================
+public:
+ static bool IsGUID(const UICDM::SObjectRefType &inObjectRefValue);
+ static bool IsRelativePath(const UICDM::SObjectRefType &inObjectRefValue);
+ static EPathType GetPathType(const UICDM::SObjectRefType &inObjectRefValue);
+
+ static Q3DStudio::CString BuildReferenceString(const UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::CUICDMInstanceHandle inRootInstance,
+ EPathType inPathType, CDoc *inDoc);
+ static Q3DStudio::CString
+ BuildAbsoluteReferenceString(const UICDM::CUICDMInstanceHandle inInstance, CDoc *inDoc);
+ static Q3DStudio::CString
+ BuildRelativeReferenceString(const UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::CUICDMInstanceHandle inRootInstance, CDoc *inDoc);
+ static UICDM::CUICDMInstanceHandle
+ FindAssetInstanceByObjectPath(CDoc *inDoc, const UICDM::CUICDMInstanceHandle &inRootInstance,
+ const Q3DStudio::CString &inString, EPathType &outPathType,
+ bool &outIsResolved,
+ const IObjectReferenceHelper *inHelper = NULL);
+ static UICDM::SObjectRefType
+ CreateAssetRefValue(const UICDM::CUICDMInstanceHandle inInstance,
+ const UICDM::CUICDMInstanceHandle inRootInstance, EPathType inPathType,
+ CDoc *inDoc);
+
+protected:
+ static UICDM::CUICDMInstanceHandle
+ DoFindAssetInstanceByObjectPath(CDoc *inDoc, const UICDM::CUICDMInstanceHandle &inRootInstance,
+ const UICDM::CUICDMInstanceHandle inTimeParentInstance,
+ UICDM::CUICDMSlideHandle inSlide, CStackTokenizer &ioTokenizer,
+ bool &outIsResolved, const IObjectReferenceHelper *inHelper);
+ static Q3DStudio::CString LookupObjectName(const UICDM::CUICDMInstanceHandle inInstance,
+ CDoc *inDoc);
+};
+
+#endif // INCLUDED_RELATIVEPATHTOOLS_H
diff --git a/src/Authoring/Client/Code/Core/Doc/SelectedValue.h b/src/Authoring/Client/Code/Core/Doc/SelectedValue.h
new file mode 100644
index 00000000..b43f5887
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/SelectedValue.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef SELECTED_VALUE_H
+#define SELECTED_VALUE_H
+#include "foundation/Qt3DSOption.h"
+
+namespace Q3DStudio {
+struct SelectedValueTypes
+{
+ enum Enum {
+ UnknownSelectedValueType = 0,
+ Instance, // CUICDMInstanceHandle
+ Slide, // CUICDMSlideHandle
+ SlideInsertion, // void*
+ Guide, // CUICDMGuideHandle
+ MultipleInstances, // std::vector<CUICDMInstanceHandle>
+ };
+};
+
+// Defined in SelectedValueImpl.h
+struct SSelectedValue;
+
+typedef qt3ds::foundation::Option<SSelectedValue> TSelectedValueOpt;
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/SelectedValueImpl.h b/src/Authoring/Client/Code/Core/Doc/SelectedValueImpl.h
new file mode 100644
index 00000000..048a4c7f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/SelectedValueImpl.h
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef SELECTED_VALUE_IMPL_H
+#define SELECTED_VALUE_IMPL_H
+#include "SelectedValue.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "UICDMHandles.h"
+#include "foundation/Qt3DSUnionCast.h"
+
+namespace Q3DStudio {
+
+struct SSlideInstanceWrapper
+{
+ UICDM::CUICDMInstanceHandle m_Instance;
+ UICDM::CUICDMSlideHandle m_Slide;
+#ifdef _WIN32
+ // We have a multiple unions which needs to be big enough
+ // This is strange on 32 bit systems but wrong on 64 bit.
+ // Align the structure to make it big enough.
+ size_t m_Padding;
+#endif
+ SSlideInstanceWrapper() {}
+ SSlideInstanceWrapper(UICDM::CUICDMInstanceHandle inst, UICDM::CUICDMSlideHandle slide)
+ : m_Instance(inst)
+ , m_Slide(slide)
+ {
+ }
+
+ bool operator==(const SSlideInstanceWrapper &inOther) const
+ {
+ return m_Instance == inOther.m_Instance && m_Slide == inOther.m_Slide;
+ }
+};
+
+struct SSlideInsertionWrapper
+{
+ void *m_UserData;
+ SSlideInsertionWrapper(void *ud = NULL)
+ : m_UserData(ud)
+ {
+ }
+
+ bool operator==(const SSlideInsertionWrapper &inOther) const
+ {
+ return m_UserData == inOther.m_UserData;
+ }
+};
+
+template <typename dtype>
+struct SSelectedValueTypeMap
+{
+};
+
+template <>
+struct SSelectedValueTypeMap<UICDM::CUICDMInstanceHandle>
+{
+ static SelectedValueTypes::Enum GetType() { return SelectedValueTypes::Instance; }
+};
+
+template <>
+struct SSelectedValueTypeMap<SSlideInstanceWrapper>
+{
+ static SelectedValueTypes::Enum GetType() { return SelectedValueTypes::Slide; }
+};
+
+template <>
+struct SSelectedValueTypeMap<UICDM::CUICDMGuideHandle>
+{
+ static SelectedValueTypes::Enum GetType() { return SelectedValueTypes::Guide; }
+};
+
+template <>
+struct SSelectedValueTypeMap<SSlideInsertionWrapper>
+{
+ static SelectedValueTypes::Enum GetType() { return SelectedValueTypes::SlideInsertion; }
+};
+
+template <>
+struct SSelectedValueTypeMap<UICDM::TInstanceHandleList>
+{
+ static SelectedValueTypes::Enum GetType() { return SelectedValueTypes::MultipleInstances; }
+};
+
+struct SSelectedValueTraits
+{
+ typedef SelectedValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(SSlideInstanceWrapper),
+ };
+
+ static TIdType getNoDataId() { return SelectedValueTypes::UnknownSelectedValueType; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SSelectedValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case SelectedValueTypes::Instance:
+ return inVisitor(*qt3ds::NVUnionCast<UICDM::CUICDMInstanceHandle *>(inData));
+ case SelectedValueTypes::Slide:
+ return inVisitor(*qt3ds::NVUnionCast<SSlideInstanceWrapper *>(inData));
+ case SelectedValueTypes::Guide:
+ return inVisitor(*qt3ds::NVUnionCast<UICDM::CUICDMGuideHandle *>(inData));
+ case SelectedValueTypes::SlideInsertion:
+ return inVisitor(*qt3ds::NVUnionCast<void **>(inData));
+ case SelectedValueTypes::MultipleInstances:
+ return inVisitor(*qt3ds::NVUnionCast<UICDM::TInstanceHandleList *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case SelectedValueTypes::UnknownSelectedValueType:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case SelectedValueTypes::Instance:
+ return inVisitor(*qt3ds::NVUnionCast<const UICDM::CUICDMInstanceHandle *>(inData));
+ case SelectedValueTypes::Slide:
+ return inVisitor(*qt3ds::NVUnionCast<const SSlideInstanceWrapper *>(inData));
+ case SelectedValueTypes::Guide:
+ return inVisitor(*qt3ds::NVUnionCast<const UICDM::CUICDMGuideHandle *>(inData));
+ case SelectedValueTypes::SlideInsertion:
+ return inVisitor(*qt3ds::NVUnionCast<const void **>(inData));
+ case SelectedValueTypes::MultipleInstances:
+ return inVisitor(*qt3ds::NVUnionCast<const UICDM::TInstanceHandleList *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case SelectedValueTypes::UnknownSelectedValueType:
+ return inVisitor();
+ }
+ }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SSelectedValueTraits,
+ SSelectedValueTraits::TBufferSize>,
+ SSelectedValueTraits::TBufferSize>
+ TSelectedValueUnionType;
+
+struct SSelectedValue : public TSelectedValueUnionType
+{
+
+ SSelectedValue() {}
+ SSelectedValue(const SSelectedValue &other)
+ : TSelectedValueUnionType(static_cast<const TSelectedValueUnionType &>(other))
+ {
+ }
+ SSelectedValue(UICDM::CUICDMInstanceHandle val)
+ : TSelectedValueUnionType(val)
+ {
+ }
+ SSelectedValue(SSlideInstanceWrapper val)
+ : TSelectedValueUnionType(val)
+ {
+ }
+ SSelectedValue(UICDM::CUICDMGuideHandle val)
+ : TSelectedValueUnionType(val)
+ {
+ }
+ SSelectedValue(SSlideInsertionWrapper val)
+ : TSelectedValueUnionType(val)
+ {
+ }
+ SSelectedValue(const UICDM::TInstanceHandleList &val)
+ : TSelectedValueUnionType(val)
+ {
+ }
+
+ SSelectedValue &operator=(const SSelectedValue &other)
+ {
+ TSelectedValueUnionType::operator=(static_cast<const TSelectedValueUnionType &>(other));
+ return *this;
+ }
+
+ bool empty() const { return getType() == SelectedValueTypes::UnknownSelectedValueType; }
+
+ operator bool() const { return !empty(); }
+
+ UICDM::TInstanceHandleList GetSelectedInstances() const
+ {
+ if (getType() == SelectedValueTypes::Instance) {
+ UICDM::TInstanceHandleList retval;
+ retval.push_back(getData<UICDM::CUICDMInstanceHandle>());
+ return retval;
+ } else if (getType() == SelectedValueTypes::MultipleInstances)
+ return getData<UICDM::TInstanceHandleList>();
+ return UICDM::TInstanceHandleList();
+ }
+};
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp
new file mode 100644
index 00000000..a4056aa4
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "StudioProjectSettings.h"
+#include "Core.h"
+#include "Preferences.h"
+#include "Doc.h"
+#include "CoreConst.h"
+#include "Dispatch.h"
+#include "CommonConstants.h"
+#include "StudioPreferences.h"
+#include "UICDESKey.h"
+#include "UICLargeInteger.h"
+#include "CColor.h"
+#include "UICColor.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioProjectSettings property page
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+CStudioProjectSettings::CStudioProjectSettings(CCore *inCore /*=NULL*/)
+ : m_Core(inCore)
+{
+ this->Reset();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CStudioProjectSettings::~CStudioProjectSettings()
+{
+}
+
+//==============================================================================
+/**
+ * Reset: Reset internal values
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettings::Reset()
+{
+ // Reset the internal variables
+
+ m_Author.clear();
+ m_Company.clear();
+
+ m_PresentationSize = CStudioPreferences::GetDefaultClientSize();
+
+ // fsaa
+ m_FSAAMode = FSAA_OFF;
+
+ m_MaintainAspect = false;
+
+ // do not embed fonts by default
+ m_EmbedFonts = false;
+
+ m_RotatePresentation = false;
+}
+
+//==============================================================================
+/**
+ * SetAuthor: Sets the author value
+ *
+ * @param inAuthor Author name
+ */
+//==============================================================================
+void CStudioProjectSettings::SetAuthor(const QString &inAuthor)
+{
+ if (m_Author != inAuthor) {
+ m_Author = inAuthor;
+ m_Core->GetDoc()->SetModifiedFlag();
+ }
+}
+
+//==============================================================================
+/**
+ * SetCompany: Sets the company value
+ *
+ * @param inCompany Company name
+ */
+//==============================================================================
+void CStudioProjectSettings::SetCompany(const QString &inCompany)
+{
+ if (m_Company != inCompany) {
+ m_Company = inCompany;
+ m_Core->GetDoc()->SetModifiedFlag();
+ }
+}
+
+//=============================================================================
+/**
+ * Set the size of the client presentation.
+ *
+ * @param inSize the size that the presentation should be.
+ */
+//=============================================================================
+void CStudioProjectSettings::SetPresentationSize(CPt inSize)
+{
+ if (m_PresentationSize != inSize) {
+ m_Core->GetDoc()->SetModifiedFlag();
+ m_PresentationSize = inSize;
+ }
+}
+
+//=============================================================================
+/**
+ * Restore all parameters to what they would be if they were fresh from the installation.
+ * Slightly different from a Reset, this will nuke the registry settings for the custom preview
+ * options and
+ * reset the preview app.
+ */
+void CStudioProjectSettings::RestoreDefaults()
+{
+ Reset();
+}
+
+//=============================================================================
+/**
+ * @return true if we are maintaining the aspect ratio for the scene
+ */
+bool CStudioProjectSettings::GetMaintainAspect()
+{
+ return m_MaintainAspect;
+}
+
+//=============================================================================
+/**
+ * @param inFlag true if we want to maintain the aspect ratio when changing sizes
+ */
+void CStudioProjectSettings::SetMaintainAspect(bool inFlag)
+{
+ if (m_MaintainAspect != inFlag) {
+ m_MaintainAspect = inFlag;
+ m_Core->GetDoc()->SetModifiedFlag();
+ }
+}
+
+//=============================================================================
+/**
+ * @param inEngine the rendering engine we want to use
+ */
+void CStudioProjectSettings::SetFSAAMode(long inFSAAMode)
+{
+ m_FSAAMode = inFSAAMode;
+ m_Core->GetDoc()->SetModifiedFlag();
+}
+
+//=============================================================================
+/**
+ * @return the flag on whether to embed fonts in am file
+ */
+bool CStudioProjectSettings::GetEmbedFonts()
+{
+ return m_EmbedFonts;
+}
+
+bool CStudioProjectSettings::GetRotatePresentation()
+{
+ return m_RotatePresentation;
+}
+
+void CStudioProjectSettings::SetRotatePresentation(bool inFlag)
+{
+ m_RotatePresentation = inFlag;
+}
+
+//=============================================================================
+/**
+ * @param inFlag the flag on whether to embed fonts in am file
+ */
+void CStudioProjectSettings::SetEmbedFonts(bool inFlag)
+{
+ if (m_EmbedFonts != inFlag) {
+ m_EmbedFonts = inFlag;
+ m_Core->GetDoc()->SetModifiedFlag();
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h
new file mode 100644
index 00000000..4d1c67a0
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PROJECT_SETTINGS_H
+#define INCLUDED_STUDIO_PROJECT_SETTINGS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "Pt.h"
+#include "CColor.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CCore;
+class CStudioProjectVariables;
+
+class CStudioProjectSettings
+{
+
+ // Construction
+public:
+ CStudioProjectSettings(CCore *inCore = NULL);
+ ~CStudioProjectSettings();
+
+ QString GetAuthor() { return m_Author; }
+ void SetAuthor(const QString &inAuthor);
+
+ QString GetCompany() { return m_Company; }
+ void SetCompany(const QString &inCompany);
+
+ CPt GetPresentationSize() { return m_PresentationSize; }
+ void SetPresentationSize(CPt inSize);
+
+ long GetFSAAMode() const { return m_FSAAMode; }
+ void SetFSAAMode(long inFSAAMode);
+
+ bool GetMaintainAspect();
+ void SetMaintainAspect(bool inFlag);
+
+ bool GetEmbedFonts();
+ void SetEmbedFonts(bool inFlag);
+
+ bool GetRotatePresentation();
+ void SetRotatePresentation(bool inFlag);
+
+ void Reset();
+ void RestoreDefaults();
+
+ // Implementation
+protected:
+ QString m_Author;
+ QString m_Company;
+
+ // TODO : remove m_EmbedFonts, m_FSAAMode
+ CPt m_PresentationSize;
+ long m_FSAAMode; ///< Fullscreen anti-aliasing mode
+ bool m_MaintainAspect;
+ bool m_RotatePresentation;
+ CCore *m_Core;
+
+ bool m_EmbedFonts; ///< Whether to embed fonts in am files
+};
+
+#endif // INCLUDED_STUDIO_PROJECT_SETTINGS_H
diff --git a/src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.cpp b/src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.cpp
new file mode 100644
index 00000000..2cb132df
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "Doc.h"
+#undef placeholder
+#include <boost/function.hpp>
+#include <boost/signal.hpp>
+#include <boost/signals/connection.hpp>
+#include "UICDMStudioSystem.h"
+#include "DataCoreProducer.h"
+#include "SlideCoreProducer.h"
+#include "SlideGraphCoreProducer.h"
+#include "AnimationCoreProducer.h"
+#include "SlideSystem.h"
+#include "ClientDataModelBridge.h"
+#include "StudioCoreSystem.h"
+#include "StudioFullSystem.h"
+#include "UICDMXML.h"
+#include "foundation/IOStreams.h"
+#include "StudioUtils.h"
+
+using namespace std;
+
+namespace UICDM {
+inline std::wstring GetFullPath(Q3DStudio::CString inSource)
+{
+#ifdef Q_OS_MACOS
+ if (inSource.Left(4) == "res/" || inSource.Left(4) == "res\\")
+ inSource = inSource.Mid(4);
+#endif
+ CUICFile theSourcePath(CUICFile::GetApplicationDirectory().GetAbsolutePath() + inSource);
+ return std::wstring(theSourcePath.GetAbsolutePath());
+}
+
+CStudioSystem::CStudioSystem(CDoc *inDoc)
+ : m_Doc(inDoc)
+{
+ ResetDatabase();
+}
+
+struct MaterialImagePropertyInfo : public IPropertyInstanceInfo
+{
+ std::shared_ptr<CClientDataModelBridge> m_Bridge;
+ CUICDMPropertyHandle m_Slot;
+ TDataCorePtr m_DataCore;
+ TSlideCorePtr m_SlideCore;
+ TAnimationCorePtr m_AnimationCore;
+ MaterialImagePropertyInfo(std::shared_ptr<CClientDataModelBridge> inBridge,
+ CUICDMPropertyHandle inSlot, TDataCorePtr inDataCore,
+ TSlideCorePtr inSlideCore, TAnimationCorePtr inAnimationCore)
+ : m_Bridge(inBridge)
+ , m_Slot(inSlot)
+ , m_DataCore(inDataCore)
+ , m_SlideCore(inSlideCore)
+ , m_AnimationCore(inAnimationCore)
+ {
+ }
+ /**
+ * Return the instance that relates to this property
+ */
+ CUICDMInstanceHandle GetInstanceForProperty(const SValue &inValue) override
+ {
+ SLong4 theId(get<SLong4>(inValue));
+ if (theId.m_Longs[0] && theId.m_Longs[1] && theId.m_Longs[2] && theId.m_Longs[3]) {
+ CUICDMInstanceHandle theImageInstance = m_Bridge->GetImageInstanceByGUID(theId);
+ return theImageInstance;
+ }
+ return 0;
+ }
+
+ static inline void SetPropertyIfOnInstance(const TSlideEntry &inEntry,
+ CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inDestInstance,
+ CUICDMSlideHandle inDestSlide,
+ TSlideCorePtr inSlideCore)
+ {
+ if (get<0>(inEntry) == inInstance)
+ inSlideCore->ForceSetInstancePropertyValue(inDestSlide, inDestInstance, get<1>(inEntry),
+ get<2>(inEntry));
+ }
+
+ static inline void
+ CopyAnimationIfOnInstance(CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inSourceSlide,
+ CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inDestInstance,
+ CUICDMSlideHandle inDestSlide, TAnimationCorePtr inAnimationCore)
+ {
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ if (theInfo.m_Instance == inInstance && theInfo.m_Slide == inSourceSlide)
+ CopyAnimation(inAnimationCore, inAnimation, inDestSlide, inDestInstance,
+ theInfo.m_Property, theInfo.m_Index);
+ }
+
+ /**
+ * Duplicate this instance and whichever properties and animations you desire,
+ * returning a new data model value that will be set on the newly created property.
+ */
+ SValue CreateInstanceForProperty(CUICDMSlideHandle inSourceSlide,
+ CUICDMSlideHandle inDestSlide,
+ CUICDMInstanceHandle inInstance) override
+ {
+ std::pair<UICDM::CUICDMInstanceHandle, UICDM::SLong4> theInstanceGuidPair(
+ m_Bridge->CreateImageInstance(inInstance, m_Slot, inDestSlide));
+ CUICDMInstanceHandle theNewInstance(theInstanceGuidPair.first);
+ TSlideEntryList theEntries;
+ m_SlideCore->GetSlidePropertyEntries(inSourceSlide, theEntries);
+ do_all(theEntries, std::bind(SetPropertyIfOnInstance, std::placeholders::_1,
+ inInstance, theNewInstance, inDestSlide, m_SlideCore));
+ TAnimationHandleList theAnimations;
+ m_AnimationCore->GetAnimations(theAnimations);
+ do_all(theAnimations, std::bind(CopyAnimationIfOnInstance, std::placeholders::_1,
+ inSourceSlide, inInstance, theNewInstance, inDestSlide,
+ m_AnimationCore));
+ return theInstanceGuidPair.second;
+ }
+};
+// Call before load.
+void CStudioSystem::ResetDatabase()
+{
+ std::shared_ptr<CStudioCoreSystem> theCore(new CStudioCoreSystem());
+ // Create the base object model studio *has* to have to survive.
+ std::shared_ptr<SComposerObjectDefinitions> theDefinitions =
+ std::make_shared<SComposerObjectDefinitions>(std::ref(*theCore->GetDataCore()),
+ std::ref(*theCore->GetNewMetaData()));
+
+ m_Bridge = std::shared_ptr<CClientDataModelBridge>(new CClientDataModelBridge(
+ theCore->GetDataCore().get(), theCore->GetSlideCore().get(),
+ theCore->GetSlideGraphCore().get(), theCore->GetAnimationCore().get(),
+ theCore->GetNewMetaData(), theDefinitions, m_Doc));
+ TNewMetaDataPtr theNewMetaData(theCore->GetNewMetaData());
+ std::shared_ptr<IStringTable> theStringTable(theNewMetaData->GetStringTablePtr());
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ Q3DStudio::CString theFullPath(Q3DStudio::CString::fromQString(
+ resourcePath()
+ + QStringLiteral("/DataModelMetadata/en-us/MetaData.xml")));
+ // Load the new meta data
+ {
+ qt3ds::foundation::CFileSeekableIOStream theStream(theFullPath,
+ qt3ds::foundation::FileReadFlags());
+ if (theStream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SDOMElement *theElement = CDOMSerializer::Read(*theFactory, theStream);
+ std::shared_ptr<IDOMReader> theReader =
+ IDOMReader::CreateDOMReader(*theElement, theStringTable);
+ theNewMetaData->Load(*theReader);
+ }
+
+ /*
+ //Save new version of new meta data
+ {
+ SDOMElement* newTopElement = theFactory->NextElement( L"MetaData" );
+ std::shared_ptr<IDOMWriter> theWriter( IDOMWriter::CreateDOMWriter( theFactory,
+ *newTopElement, theStringTable ).first );
+ theNewMetaData->Save( *theWriter);
+ CFileSeekableIOStream theStream( theFullPath.GetCharStar(), FileWriteFlags() );
+ CDOMSerializer::WriteXMLHeader( theStream );
+ CDOMSerializer::Write( *newTopElement, theStream );
+ }*/
+
+ m_StudioSystem = std::shared_ptr<CStudioFullSystem>(new CStudioFullSystem(
+ theCore, m_Bridge->GetSlideInstance(), m_Bridge->GetSlideComponentIdProperty(),
+ m_Bridge->GetActionInstance(), m_Bridge->GetActionEyeball()));
+}
+
+IMetaData *CStudioSystem::GetActionMetaData()
+{
+ return m_StudioSystem->GetCoreSystem()->GetNewMetaData().get();
+}
+
+ISlideSystem *CStudioSystem::GetSlideSystem()
+{
+ return m_StudioSystem->GetSlideSystem().get();
+}
+
+ISlideCore *CStudioSystem::GetSlideCore()
+{
+ return m_StudioSystem->GetSlideCore().get();
+}
+
+IPropertySystem *CStudioSystem::GetPropertySystem()
+{
+ return m_StudioSystem->GetPropertySystem().get();
+}
+IStudioFullSystemSignalProvider *CStudioSystem::GetFullSystemSignalProvider()
+{
+ return m_StudioSystem->GetSignalProvider();
+}
+IAnimationCore *CStudioSystem::GetAnimationCore()
+{
+ return m_StudioSystem->GetAnimationCore().get();
+}
+IStudioAnimationSystem *CStudioSystem::GetAnimationSystem()
+{
+ return m_StudioSystem->GetAnimationSystem().get();
+}
+IActionCore *CStudioSystem::GetActionCore()
+{
+ return m_StudioSystem->GetActionCore().get();
+}
+IActionSystem *CStudioSystem::GetActionSystem()
+{
+ return m_StudioSystem->GetActionSystem().get();
+}
+
+void CStudioSystem::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_StudioSystem->SetConsumer(inConsumer);
+}
+
+bool CStudioSystem::IsInstance(CUICDMInstanceHandle inInstance) const
+{
+ return m_StudioSystem->GetCoreSystem()->GetDataCore()->IsInstance(inInstance);
+}
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.h b/src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.h
new file mode 100644
index 00000000..a26ee129
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Doc/UICDMStudioSystem.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSTUDIOSYSTEMH
+#define UICDMSTUDIOSYSTEMH
+#include "UICDMTransactions.h"
+#include "UICDMHandles.h"
+
+class CDoc;
+class CClientDataModelBridge;
+
+namespace UICDM {
+class IPropertySystem;
+class ISlideCore;
+class ISlideGraphCore;
+class ISlideSystem;
+class IInstancePropertyCore;
+class ITransactionConsumer;
+class IAnimationCore;
+class IActionCore;
+class CStudioFullSystem;
+class IStudioFullSystemSignalProvider;
+class IStudioAnimationSystem;
+class IActionSystem;
+class ISignalConnection;
+class IMetaData;
+
+class CStudioSystem : public ITransactionProducer
+{
+ CDoc *m_Doc;
+ std::shared_ptr<CClientDataModelBridge> m_Bridge;
+ std::shared_ptr<CStudioFullSystem> m_StudioSystem;
+ // Properties that refer to instance may require special handling.
+
+public:
+ CStudioSystem(CDoc *inDoc);
+ // Call before load.
+ void ResetDatabase();
+
+ IMetaData *GetActionMetaData();
+ CClientDataModelBridge *GetClientDataModelBridge() const { return m_Bridge.get(); }
+ ISlideSystem *GetSlideSystem();
+ ISlideCore *GetSlideCore();
+ IPropertySystem *GetPropertySystem();
+ IStudioFullSystemSignalProvider *GetFullSystemSignalProvider();
+ IAnimationCore *GetAnimationCore();
+ IStudioAnimationSystem *GetAnimationSystem();
+ IActionCore *GetActionCore();
+ IActionSystem *GetActionSystem();
+
+ CStudioFullSystem *GetFullSystem() { return m_StudioSystem.get(); }
+
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+ bool IsInstance(CUICDMInstanceHandle inInstance) const;
+};
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Include/UICKeyDefs.h b/src/Authoring/Client/Code/Core/Include/UICKeyDefs.h
new file mode 100644
index 00000000..90336ff5
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Include/UICKeyDefs.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __UICKEYDEFS_H__
+#define __UICKEYDEFS_H__
+
+enum EUICKeyDefines {
+ // We start this at 0x30 so all alpha-numeric keyCodes will match Studio 1.5 Windows virtual key
+ // codes
+ UIC_KEY_0 = 0x30, // 0
+ UIC_KEY_1, // 1
+ UIC_KEY_2, // 2
+ UIC_KEY_3, // 3
+ UIC_KEY_4, // 4
+ UIC_KEY_5, // 5
+ UIC_KEY_6, // 6
+ UIC_KEY_7, // 7
+ UIC_KEY_8, // 8
+ UIC_KEY_9, // 9
+
+ // We start this at 0x41 so all alpha-numeric keyCodes will match Studio 1.5 Windows virtual key
+ // codes
+ UIC_KEY_A = 0x41, // A
+ UIC_KEY_B, // B
+ UIC_KEY_C, // C
+ UIC_KEY_D, // D
+ UIC_KEY_E, // E
+ UIC_KEY_F, // F
+ UIC_KEY_G, // G
+ UIC_KEY_H, // H
+ UIC_KEY_I, // I
+ UIC_KEY_J, // J
+ UIC_KEY_K, // K
+ UIC_KEY_L, // L
+ UIC_KEY_M, // M
+ UIC_KEY_N, // N
+ UIC_KEY_O, // O
+ UIC_KEY_P, // P
+ UIC_KEY_Q, // Q
+ UIC_KEY_R, // R
+ UIC_KEY_S, // S
+ UIC_KEY_T, // T
+ UIC_KEY_U, // U
+ UIC_KEY_V, // V
+ UIC_KEY_W, // W
+ UIC_KEY_X, // X
+ UIC_KEY_Y, // Y
+ UIC_KEY_Z, // Z
+
+ // The actual value of these items is not important
+ UIC_KEY_BACK, // BACKSPACE key
+ UIC_KEY_TAB, // TAB key
+ UIC_KEY_CLEAR, // CLEAR key
+ UIC_KEY_RETURN, // ENTER key
+ UIC_KEY_SHIFT, // SHIFT key
+ UIC_KEY_CONTROL, // CTRL key
+ UIC_KEY_PAUSE, // PAUSE key
+ UIC_KEY_CAPITAL, // CAPS LOCK key
+ UIC_KEY_ESCAPE, // ESC key
+ UIC_KEY_SPACE, // SPACEBAR
+ UIC_KEY_PRIOR, // PAGE UP key
+ UIC_KEY_NEXT, // PAGE DOWN key
+ UIC_KEY_END, // END key
+ UIC_KEY_HOME, // HOME key
+ UIC_KEY_LEFT, // LEFT ARROW key
+ UIC_KEY_UP, // UP ARROW key
+ UIC_KEY_RIGHT, // RIGHT ARROW key
+ UIC_KEY_DOWN, // DOWN ARROW key
+ UIC_KEY_SELECT, // SELECT key
+ UIC_KEY_PRINT, // PRINT key
+ UIC_KEY_SNAPSHOT, // PRINT SCREEN key
+ UIC_KEY_INSERT, // INS key
+ UIC_KEY_DELETE, // DEL key
+ UIC_KEY_HELP, // HELP key
+ UIC_KEY_NUMPAD0, // Numeric keypad 0 key
+ UIC_KEY_NUMPAD1, // Numeric keypad 1 key
+ UIC_KEY_NUMPAD2, // Numeric keypad 2 key
+ UIC_KEY_NUMPAD3, // Numeric keypad 3 key
+ UIC_KEY_NUMPAD4, // Numeric keypad 4 key
+ UIC_KEY_NUMPAD5, // Numeric keypad 5 key
+ UIC_KEY_NUMPAD6, // Numeric keypad 6 key
+ UIC_KEY_NUMPAD7, // Numeric keypad 7 key
+ UIC_KEY_NUMPAD8, // Numeric keypad 8 key
+ UIC_KEY_NUMPAD9, // Numeric keypad 9 key
+ UIC_KEY_MULTIPLY, // Multiply key
+ UIC_KEY_ADD, // Add key
+ UIC_KEY_SEPARATOR, // Separator key
+ UIC_KEY_SUBTRACT, // Subtract key
+ UIC_KEY_DECIMAL, // Decimal key
+ UIC_KEY_DIVIDE, // Divide key
+ UIC_KEY_F1, // F1 key
+ UIC_KEY_F2, // F2 key
+ UIC_KEY_F3, // F3 key
+ UIC_KEY_F4, // F4 key
+ UIC_KEY_F5, // F5 key
+ UIC_KEY_F6, // F6 key
+ UIC_KEY_F7, // F7 key
+ UIC_KEY_F8, // F8 key
+ UIC_KEY_F9, // F9 key
+ UIC_KEY_F10, // F10 key
+ UIC_KEY_F11, // F11 key
+ UIC_KEY_F12, // F12 key
+ UIC_KEY_F13, // F13 key
+ UIC_KEY_F14, // F14 key
+ UIC_KEY_F15, // F15 key
+ UIC_KEY_F16, // F16 key
+ UIC_KEY_F17, // F17 key
+ UIC_KEY_F18, // F18 key
+ UIC_KEY_F19, // F19 key
+ UIC_KEY_F20, // F20 key
+ UIC_KEY_F21, // F21 key
+ UIC_KEY_F22, // F22 key
+ UIC_KEY_F23, // F23 key
+ UIC_KEY_F24, // F24 key
+ UIC_KEY_NUMLOCK, // NUM LOCK key
+ UIC_KEY_SCROLL, // SCROLL LOCK key
+ UIC_KEY_LSHIFT, // Left SHIFT key
+ UIC_KEY_RSHIFT, // Right SHIFT key
+ UIC_KEY_LCONTROL, // Left CONTROL key
+ UIC_KEY_RCONTROL, // Right CONTROL key
+ UIC_KEY_LMENU, // Left MENU key
+ UIC_KEY_RMENU, // Right MENU key
+ UIC_KEY_COLON_SEMICOLON, //
+ UIC_KEY_PLUS_EQUALS, //
+ UIC_KEY_COMMA_LT, //
+ UIC_KEY_MINUS_UNDERSCORE, //
+ UIC_KEY_PERIOD_GT, //
+ UIC_KEY_FORWARDSLASH_QUESTIONMARK, //
+ UIC_KEY_TILDE_DIACRITIC, //
+ UIC_KEY_OPENBRACKET_OPENBRACE, //
+ UIC_KEY_BACKWARDSLASH_SEPARATOR, //
+ UIC_KEY_CLOSEBRACKET_CLOSEBRACE, //
+ UIC_KEY_SINGLEQUOTE_DOUBLEQUOTE, //
+};
+
+#endif // #ifndef __UICKEYDEFS_H__
diff --git a/src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.cpp b/src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.cpp
new file mode 100644
index 00000000..134416e9
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "StdAfx.h"
+#include "Q3DStudioNVFoundation.h"
+#include "foundation/TrackingAllocator.h"
+#include <string>
+
+namespace Q3DStudio {
+namespace Foundation {
+
+SStudioFoundation SStudioFoundation::Create()
+{
+ SStudioFoundation retval;
+ retval.m_AllocatorCallback =
+ std::make_shared<qt3ds::foundation::CAllocator>();
+ retval.m_Foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *retval.m_AllocatorCallback);
+ return retval;
+}
+}
+}
diff --git a/src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.h b/src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.h
new file mode 100644
index 00000000..6c5ebfeb
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Q3DStudioNVFoundation.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STUDIO_QT3DS_FOUNDATION_H
+#define INCLUDED_STUDIO_QT3DS_FOUNDATION_H 1
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSRefCounted.h"
+
+#pragma once
+
+namespace Q3DStudio {
+namespace Foundation {
+
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ typedef std::shared_ptr<NVAllocatorCallback> TAllocatorPtr;
+ typedef NVScopedRefCounted<NVFoundation> TFoundationPtr;
+
+ struct SStudioFoundation
+ {
+ TAllocatorPtr m_AllocatorCallback;
+ TFoundationPtr m_Foundation;
+
+ static SStudioFoundation Create();
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/StdAfx.cpp b/src/Authoring/Client/Code/Core/StdAfx.cpp
new file mode 100644
index 00000000..a2b66c1f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/StdAfx.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// stdafx.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/src/Authoring/Client/Code/Core/StdAfx.h b/src/Authoring/Client/Code/Core/StdAfx.h
new file mode 100644
index 00000000..9171f434
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/StdAfx.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// CoreLib Precompiled Header
+//==============================================================================
+#ifdef __cplusplus
+#pragma once
+#include "UICMacros.h"
+
+#ifdef _WIN32
+//==============================================================================
+// Disable certain warnings since warnings are errors
+//==============================================================================
+#pragma warning(disable : 4702) // Unreachable code
+#pragma warning(disable : 4290) // C++ Exception Specification ignored
+#pragma warning(disable : 4514) // unreferenced inline function
+#pragma warning(disable : 4819)
+#endif
+
+//==============================================================================
+// Common Includes
+//==============================================================================
+#include <stdio.h> // Standard includes MUST come first
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+#ifdef _WIN32
+//==============================================================================
+// Windows Includes
+//==============================================================================
+#include <winsock2.h> //must include before windows.h to avoid winsock.h defines.
+#define UIC_LITTLE_ENDIAN
+#include <windows.h>
+//==============================================================================
+// ATL Includes
+//==============================================================================
+#include <atlbase.h>
+// You may derive a class from CComModule and use it if you want to override
+// something, but do not change the name of _Module
+extern CComModule _Module;
+
+#include <atlcom.h>
+#include <atlctl.h>
+#include <atlhost.h>
+
+#include <COMMCTRL.H>
+#include <LIMITS.H>
+#include <CONTROL.H>
+#endif
+
+#include <assert.h>
+#ifndef ASSERT
+#define ASSERT(a) assert(a)
+#endif
+
+//==============================================================================
+// STL Includes
+//==============================================================================
+#ifdef _WIN32
+#pragma warning(push, 3) // Temporarily pop to warning level 3 while including standard headers
+#pragma warning(disable : 4018) // Disable mismatched < STL warning
+#endif
+#include <vector>
+#include <map>
+#include <deque>
+#include <string>
+#include <stack>
+#include <set>
+#include <list>
+#include <utility>
+#include <algorithm>
+#include <stdexcept>
+#include <limits>
+#ifdef _WIN32
+#pragma warning(pop) // Pop out to previous warning level (probably level 4)
+#endif
+
+//==============================================================================
+// Memory Manager Includes
+//==============================================================================
+#ifdef USE_MEMORY_MANAGER
+#include <mmgr.h>
+#endif
+
+//==============================================================================
+// Common Player Includes
+//==============================================================================
+#include "UICMath.h"
+#include "UICPoint.h"
+#include "UICRect.h"
+#include "UICString.h"
+#include "UICMessageBox.h"
+#include "UICObjectCounter.h"
+#include "PlatformTypes.h"
+#include "PlatformMacros.h"
+#include "PlatformStrings.h"
+#include "PlatformConversion.h"
+#include "CommonConstants.h"
+#include "UICExceptions.h"
+#include "UICExceptionConstants.h"
+#include "UICLog.h"
+#include "Mutex.h"
+#include "Guard.h"
+#include "Thread.h"
+#include "Conditional.h"
+#include "STLHelpers.h"
+#include "GenericFunctor.h"
+#include "UICRender.h"
+
+#include <QtGlobal>
+
+//==============================================================================
+// Global Variables
+//==============================================================================
+UIC_LOGEXTERN; // Enables access to the logger for all files. See UICLog for more info.
+
+// I put these in to help with some of the data model compile times.
+#ifdef _WIN32
+#pragma warning(push)
+#pragma warning(disable : 4100)
+#pragma warning(disable : 4512)
+#pragma warning(disable : 4702)
+#pragma warning(disable : 4996)
+#endif
+#include <boost/shared_ptr.hpp>
+#include <boost/variant.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+#ifdef _WIN32
+#pragma warning(pop)
+
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4189) // local variable is initialized but not referenced
+#endif
+#endif
diff --git a/src/Authoring/Client/Code/Core/Timer/Timer.cpp b/src/Authoring/Client/Code/Core/Timer/Timer.cpp
new file mode 100644
index 00000000..ee5b3f04
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Timer/Timer.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Timer.h"
+
+CTimer::CTimer()
+ : m_CurrentTime(0)
+ , m_Offset(0)
+ , m_Pause(true)
+{
+}
+
+CTimer::~CTimer()
+{
+}
+
+//==============================================================================
+/**
+ * Changes the timer state from Pause to "Run" or "Playing"
+ *
+ * This recalculates the time offset from the last pause.
+ * Turns off manual mode.
+ */
+void CTimer::Play()
+{
+ m_Pause = false;
+ m_Timer.Start();
+}
+
+//==============================================================================
+/**
+ * Resets the timer offset
+ *
+ * Turns off manual mode
+ */
+void CTimer::Reset()
+{
+ m_CurrentTime = 0;
+ m_Offset = 0;
+
+ m_Timer.Reset();
+ m_Timer.Start();
+}
+
+//==============================================================================
+/**
+ * Pauses the timer
+ */
+void CTimer::Pause()
+{
+ if (!m_Pause) {
+ // Grab the currentTime before we leave this function, only for the first time
+ m_CurrentTime = GetTime();
+ m_Pause = true;
+ }
+}
+
+//==============================================================================
+/**
+ * Unpauses the timer
+ */
+void CTimer::Resume()
+{
+ if (m_Pause) {
+ m_Offset = m_CurrentTime - m_Timer.ElapsedMilliSecs();
+ m_Pause = false;
+ }
+}
+
+//==============================================================================
+/**
+ * Returns the current timer time in milliseconds
+ */
+long CTimer::GetTime()
+{
+ if (m_Pause)
+ return m_CurrentTime;
+ else
+ return m_Timer.ElapsedMilliSecs() + m_Offset;
+}
+
+//==============================================================================
+/**
+ * Returns the current timer time in microseconds
+ */
+TLarge CTimer::GetHiResTime()
+{
+ if (m_Pause)
+ return m_CurrentTime * 1000;
+ else
+ return m_Timer.ElapsedMicroSecs() + (m_Offset * 1000);
+}
+
+//==============================================================================
+/**
+ * Stops the hi-res timer
+ */
+void CTimer::Stop()
+{
+ m_Timer.Stop();
+}
diff --git a/src/Authoring/Client/Code/Core/Timer/Timer.h b/src/Authoring/Client/Code/Core/Timer/Timer.h
new file mode 100644
index 00000000..f890f3c8
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Timer/Timer.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __TIMER_H_
+#define __TIMER_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+#include "UICTime.h"
+#include "HiResTimer.h"
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CTimer
+ * @brief This timer class controls the elapsed time in a presentation.
+ */
+class CTimer
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+protected:
+ long m_CurrentTime; ///< The current time
+ long m_Offset;
+ bool m_Pause;
+ CHiResTimer m_Timer;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Construction
+public:
+ CTimer();
+ virtual ~CTimer();
+
+public:
+ long GetTime();
+ void Play();
+ void Reset();
+ void Pause();
+ void Resume();
+ void Stop();
+
+ TLarge GetHiResTime();
+};
+
+#endif //__TIMER_H_
diff --git a/src/Authoring/Client/Code/Core/Types/BoolProbe.h b/src/Authoring/Client/Code/Core/Types/BoolProbe.h
new file mode 100644
index 00000000..23844be2
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/BoolProbe.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __BOOLPROBE_H_
+#define __BOOLPROBE_H_
+
+#include <stack>
+
+class CBoolProbe : public std::stack<bool>
+{
+public:
+ CBoolProbe() { std::stack<bool>::push(false); }
+
+ //==============================================================================
+ /**
+ * If true has ever been pushed onto the stack, all the elements
+ * below will be true regardless what is being pushed.
+ *
+ * @see operator=
+ * @see Copy
+ */
+ void push(const bool &inValue) { std::stack<bool>::push(inValue || std::stack<bool>::top()); }
+};
+
+#endif //__BOOLPROBE_H_
diff --git a/src/Authoring/Client/Code/Core/Types/BoolScanner.h b/src/Authoring/Client/Code/Core/Types/BoolScanner.h
new file mode 100644
index 00000000..5654a429
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/BoolScanner.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __BOOLSCANNER_H_
+#define __BOOLSCANNER_H_
+
+#include <stack>
+
+class CBoolScanner : public std::stack<bool>
+{
+public:
+ CBoolScanner() { std::stack<bool>::push(false); }
+
+ //==============================================================================
+ /**
+ * If true has ever been pushed onto the stack, all the elements above
+ * will return true.
+ *
+ * @see operator=
+ * @see Copy
+ */
+ void pop()
+ {
+ bool theLastTop = std::stack<bool>::top();
+ std::stack<bool>::pop();
+ std::stack<bool>::top() |= theLastTop;
+ }
+};
+
+#endif //__BOOLSCANNER_H_
diff --git a/src/Authoring/Client/Code/Core/Types/BoundingBox.cpp b/src/Authoring/Client/Code/Core/Types/BoundingBox.cpp
new file mode 100644
index 00000000..ebff5f0b
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/BoundingBox.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "BoundingBox.h"
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "OptimizedArithmetic.h"
+#include <vector>
+
+namespace Q3DStudio {
+
+/**
+ * Empty Constructor. An empty box is a maximized inverted box which
+ * ensures that an expand with an empty box is a no-op. If an empty box was
+ * a point at 0,0,0 an expand would expand a box to always include 0,0,0 which
+ * would be incorrect if the box was offset and did not previously include 0,0,0.
+ */
+CBoundingBox::CBoundingBox()
+ : m_MinCorner(FLT_MAX, FLT_MAX, FLT_MAX)
+ , m_MaxCorner(-FLT_MAX, -FLT_MAX, -FLT_MAX)
+ , m_Orthographic(false)
+{
+}
+
+/**
+ * Constructor using two points in space. The created box is guaranteed to
+ * have correct min/max corners even if the given corners are not correct.
+ *
+ * @param inCorner1 is one spanning corner of the box
+ * @param inCorner2 is the other spanning corner of the box
+ */
+CBoundingBox::CBoundingBox(const CVector3 &inCorner1, const CVector3 &inCorner2)
+ : m_MinCorner(inCorner1)
+ , m_MaxCorner(inCorner2)
+ , m_Orthographic(false)
+{
+ m_MinCorner.Minimize(inCorner2);
+ m_MaxCorner.Maximize(inCorner1);
+}
+
+/**
+ * Copy Constructor.
+ *
+ * @param inBox is the source box
+ */
+CBoundingBox::CBoundingBox(const CBoundingBox &inBox)
+ : m_MinCorner(inBox.m_MinCorner)
+ , m_MaxCorner(inBox.m_MaxCorner)
+ , m_Orthographic(inBox.m_Orthographic)
+{
+}
+
+/**
+ * Reset bounding box to be empty which is different than the box having
+ * both corners at 0,0,0.
+ */
+void CBoundingBox::Clear()
+{
+ m_MinCorner.Set(FLT_MAX, FLT_MAX, FLT_MAX);
+ m_MaxCorner.Set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ m_Orthographic = false;
+}
+
+/**
+ * Query box for emptyness. Empty means not having any points at all and
+ * is different from a box with both corners at 0,0,0. An empty box is
+ * guaranteed not ever to expand another box.
+ */
+bool CBoundingBox::IsEmpty() const
+{
+ return m_MinCorner == CVector3(FLT_MAX, FLT_MAX, FLT_MAX)
+ && m_MaxCorner == CVector3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+}
+
+/**
+ * Expands this box to represent a volume capable of holding both the old
+ * box and the box given as an argument.
+ *
+ * @param inBox is the box that may expand the current box
+ * @return this box which is the resulting expanded box
+ */
+CBoundingBox &CBoundingBox::Expand(const CBoundingBox &inBox)
+{
+ m_MinCorner.Minimize(inBox.m_MinCorner);
+ m_MaxCorner.Maximize(inBox.m_MaxCorner);
+
+ return *this;
+}
+
+/**
+ * Expands this box to represent a volume capable of including the incoming point.
+ *
+ * @param inPoint is the vertex which needs to be contained within this box
+ * @return this box which is the resulting expanded box
+ */
+CBoundingBox &CBoundingBox::Expand(const CVector3 &inPoint)
+{
+ m_MinCorner.Minimize(inPoint);
+ m_MaxCorner.Maximize(inPoint);
+
+ return *this;
+}
+
+/**
+ * Get the max corner of the box.
+ *
+ * @return the max point of the box
+ */
+const CVector3 &CBoundingBox::MaxPoint() const
+{
+ return m_MaxCorner;
+}
+
+/**
+ * Get the min corner of the box.
+ *
+ * @return the min point of the box
+ */
+const CVector3 &CBoundingBox::MinPoint() const
+{
+ return m_MinCorner;
+}
+
+/**
+ * Transforms the bounding box using the given matrix. The resulting box
+ * is guaranteed to keep the min/max corners min/maxed even of the
+ * applied matrix results in a rotation that flips one or more corners.
+ * Note that each corner has to be translated individually and all
+ * eight corners have to be processed to spen the new box.
+ *
+ * @param inTransform is the matrix that will apply the transform
+ * @return this box which is rotated, scaled or modified by the given matrix
+ */
+CBoundingBox &CBoundingBox::Transform(const CMatrix &inTransform)
+{
+ // Don't mess with an empty box since it may make it not empty
+ if (!IsEmpty())
+ COptimizedArithmetic::TransformBoundingBox(&m_MinCorner.x, &m_MaxCorner.x,
+ inTransform.m[0]);
+
+ return *this;
+}
+
+/**
+ * Get the min corner of the box.
+ *
+ * @return the min point of the box
+ */
+void CBoundingBox::GetCorners(CVector3 outCorners[8]) const
+{
+ outCorners[0] = m_MinCorner;
+
+ outCorners[1].x = m_MaxCorner.x;
+ outCorners[1].y = m_MinCorner.y;
+ outCorners[1].z = m_MinCorner.z;
+
+ outCorners[2].x = m_MinCorner.x;
+ outCorners[2].y = m_MaxCorner.y;
+ outCorners[2].z = m_MinCorner.z;
+
+ outCorners[3].x = m_MaxCorner.x;
+ outCorners[3].y = m_MaxCorner.y;
+ outCorners[3].z = m_MinCorner.z;
+
+ outCorners[4].x = m_MinCorner.x;
+ outCorners[4].y = m_MinCorner.y;
+ outCorners[4].z = m_MaxCorner.z;
+
+ outCorners[5].x = m_MaxCorner.x;
+ outCorners[5].y = m_MinCorner.y;
+ outCorners[5].z = m_MaxCorner.z;
+
+ outCorners[6].x = m_MinCorner.x;
+ outCorners[6].y = m_MaxCorner.y;
+ outCorners[6].z = m_MaxCorner.z;
+
+ outCorners[7] = m_MaxCorner;
+}
+
+/**
+ * Get whether or not this bounding box should be rendered with an
+ * orthographic camera.
+ * @return true if the box should be rendered orthographically.
+ */
+bool CBoundingBox::GetOrthographic() const
+{
+ return m_Orthographic;
+}
+
+/**
+ * Set whether or not this bounding box should be rendered with an
+ * orthographic camera.
+ * @param inOrthographic true by default
+ */
+void CBoundingBox::SetOrthographic(const bool &inOrthographic)
+{
+ m_Orthographic = inOrthographic;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/BoundingBox.h b/src/Authoring/Client/Code/Core/Types/BoundingBox.h
new file mode 100644
index 00000000..a920b444
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/BoundingBox.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+#include "Matrix.h"
+#include "Vector3.h"
+
+namespace Q3DStudio {
+
+class CBoundingBox
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ CVector3 m_MinCorner; ///< smallest x,y,z corner
+ CVector3 m_MaxCorner; ///< biggest x,y,z corner
+ bool m_Orthographic; ///< FIX:should be moved outside of the class?
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CBoundingBox();
+ CBoundingBox(const CVector3 &inCorner1, const CVector3 &inCorner2);
+ CBoundingBox(const CBoundingBox &inBox);
+
+public: // Access
+ bool IsEmpty() const;
+ const CVector3 &MaxPoint() const;
+ const CVector3 &MinPoint() const;
+ void GetCorners(CVector3 outCorners[8]) const;
+
+public: // Operations
+ void Clear();
+ CBoundingBox &Expand(const CBoundingBox &inBox);
+ CBoundingBox &Expand(const CVector3 &inVertex);
+ CBoundingBox &Transform(const CMatrix &inTransform);
+
+public: // Orthographic methods
+ bool GetOrthographic() const;
+ void SetOrthographic(const bool &inOrthographic = true);
+};
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/CachedMatrix.cpp b/src/Authoring/Client/Code/Core/Types/CachedMatrix.cpp
new file mode 100644
index 00000000..cac4faf8
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/CachedMatrix.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "CachedMatrix.h"
+#include "OptimizedArithmetic.h"
+#include <math.h>
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor.
+ */
+CCachedMatrix::CCachedMatrix() /*:
+ m_Translation( 0,0,0 ),
+ m_Rotation( 0,0,0 ),
+ m_Scale( 1,1,1 ),
+ m_Pivot( 0,0,0 ),
+ m_SinX( ::sin( 0.0f ) ),
+ m_SinY( ::sin( 0.0f ) ),
+ m_SinZ( ::sin( 0.0f ) ),
+ m_CosX( ::cos( 0.0f ) ),
+ m_CosY( ::cos( 0.0f ) ),
+ m_CosZ( ::cos( 0.0f ) )*/
+{
+ Set(CVector3(0, 0, 0), CRotation3(0, 0, 0), CVector3(1, 1, 1), CVector3(0, 0, 0), true);
+}
+
+//==============================================================================
+/**
+ * Private constructor - disallow this.
+ */
+CCachedMatrix::CCachedMatrix(const CMatrix &inMatrix)
+ : CMatrix(inMatrix)
+{
+}
+
+//==============================================================================
+/**
+ * Private constructor - disallow this.
+ */
+CCachedMatrix::CCachedMatrix(float in00, float in01, float in02, float in03, float in10, float in11,
+ float in12, float in13, float in20, float in21, float in22, float in23,
+ float in30, float in31, float in32, float in33)
+ : CMatrix(in00, in01, in02, in03, in10, in11, in12, in13, in20, in21, in22, in23, in30, in31,
+ in32, in33)
+{
+}
+
+//==============================================================================
+/**
+ * Heavily optimized assignment method - and lazy too!
+ * This has the same result as creating four full 4x4 matrices and multiplying
+ * them together. It's also cached meaning it won't recompute a matrix if
+ * the components are the same. The whole method can be replaced with:
+ *
+ * *this = m_ScaleMatrix * m_PivotMatrix * m_RotMatrix * m_TransMatrix;
+ *
+ * @param inTranslation translation coordinates
+ * @param inRotation euler angle rotations
+ * @param inScale scaling dimensions
+ * @param inPivot pivot offset vector
+ * @return reference to this modified matrix
+ */
+void CCachedMatrix::Set(const CVector3 &inTranslation, const CRotation3 &inRotation,
+ const CVector3 &inScale, const CVector3 &inPivot, const long inRotOrder,
+ const long inOrientation, const bool inForce /*= false*/)
+{
+ bool theTranslationSame = !inForce && inTranslation.x == m_Translation.x
+ && inTranslation.y == m_Translation.y && inTranslation.z == m_Translation.z;
+ bool theRotationSame = !inForce && inRotation.x == m_Rotation.x && inRotation.y == m_Rotation.y
+ && inRotation.z == m_Rotation.z;
+ bool theScaleSame =
+ !inForce && inScale.x == m_Scale.x && inScale.y == m_Scale.y && inScale.z == m_Scale.z;
+ bool thePivotSame =
+ !inForce && inPivot.x == m_Pivot.x && inPivot.y == m_Pivot.y && inPivot.z == m_Pivot.z;
+
+ // Bail out if not change. Manual comparison to use fast exact match and not overloaded
+ // operator with epsilon tolerance
+ if (theTranslationSame && theRotationSame && theScaleSame && thePivotSame)
+ return;
+
+ // Recreate the base matrices if needed
+ if (!theTranslationSame) {
+ m_TransMatrix.SetTranslate(inTranslation);
+ m_Translation = inTranslation;
+ }
+
+ if (!theRotationSame) {
+ m_RotMatrix.SetRotate(inRotation, inRotOrder, inOrientation);
+ m_Rotation = inRotation;
+ }
+
+ if (!theScaleSame) {
+ m_ScaleMatrix.SetScale(inScale);
+ m_Scale = inScale;
+ }
+
+ if (!thePivotSame || !theScaleSame) {
+ Q3DStudio::CVector3 theScaledPivot;
+ theScaledPivot.x = -inPivot.x * inScale.x;
+ theScaledPivot.y = -inPivot.y * inScale.y;
+ theScaledPivot.z = -inPivot.z * inScale.z;
+ m_PivotMatrix.SetTranslate(theScaledPivot);
+ m_Pivot = inPivot;
+ }
+
+ // Update the transform.
+ // COptimizedArithmetic::MatrixMultiply( m_PivotMatrix.m[0], m_RotMatrix.m[0], m[0] );
+ // COptimizedArithmetic::MatrixMultiply( m[0], m_TransMatrix.m[0], m_PivotMatrix.m[0] ); //
+ //put into the pivot as a temporary location
+ // COptimizedArithmetic::MatrixMultiply( m_ScaleMatrix.m[0], m_PivotMatrix.m[0], m[0] );
+
+ if (!theRotationSame || !thePivotSame || !theScaleSame) {
+ COptimizedArithmetic::MatrixMultiply(m_ScaleMatrix.m[0], m_PivotMatrix.m[0], m[0]);
+ COptimizedArithmetic::MatrixMultiply(m[0], m_RotMatrix.m[0],
+ m_ScalePivotRotationMatrix.m[0]);
+ }
+
+ if (!theTranslationSame || !theRotationSame || !thePivotSame || !theScaleSame)
+ COptimizedArithmetic::MatrixMultiply(m_ScalePivotRotationMatrix.m[0], m_TransMatrix.m[0],
+ m[0]);
+
+ // *this = m_ScaleMatrix * m_PivotMatrix * m_RotMatrix * m_TransMatrix; // Distributed
+ //original - plain speak
+}
+
+/*
+// Generate these functions as inline code, not as function calls:
+//#pragma intrinsic ( sin, cos, memcpy, memset )
+
+// Recalculate X trig?
+ if ( m_Rotation.x != inRotation.x )
+ {
+ m_Rotation.x = inRotation.x;
+ m_SinX = ::sin( inRotation.x );
+ m_CosX = ::cos( inRotation.x );
+ }
+
+ // Recalculate Y trig?
+ if ( m_Rotation.y != inRotation.y )
+ {
+ m_Rotation.y = inRotation.y;
+ m_SinY = ::sin( inRotation.y );
+ m_CosY = ::cos( inRotation.y );
+ }
+
+ // Recalculate Z trig?
+ if ( m_Rotation.z != inRotation.z )
+ {
+ m_Rotation.z = inRotation.z;
+ m_SinZ = ::sin( inRotation.z );
+ m_CosZ = ::cos( inRotation.z );
+ }
+
+ // Precalulate the scaled rotation 3x3 matrix and populate the rotation section of our 4x4
+matrix
+ float r1 = inScale.x * (( m_CosZ * m_CosY ) + ( m_SinX * m_SinY * m_SinZ ));
+m[0][0] = r1;
+ float r4 = inScale.x * ( m_CosX * m_SinZ );
+m[0][1] = r4;
+ float r7 = - inScale.x * (( m_SinY * m_CosZ ) + ( m_SinZ * m_CosY * m_SinX ));
+m[0][2] = r7;
+ m[0][3] = 0;
+
+ float r2 = - inScale.y * (( m_SinZ * m_CosY ) + ( m_SinX * m_SinY * m_CosZ ));
+m[1][0] = r2;
+ float r5 = inScale.y * ( m_CosX * m_CosZ );
+m[1][1] = r5;
+ float r8 = inScale.y * (( m_SinY * m_SinZ ) + ( m_SinX * m_CosY * m_CosZ ));
+m[1][2] = r8;
+ m[1][3] = 0;
+
+ float r3 = inScale.z * ( m_SinY * m_CosX );
+m[2][0] = r3;
+ float r6 = - inScale.z * ( m_SinX );
+m[2][1] = r6;
+ float r9 = inScale.z * ( m_CosX * m_CosY );
+m[2][2] = r9;
+ m[2][3] = 0;
+
+ // Reuse the scaled rotation matrix in the translation/pivot section of out 4x4 matrix
+ m[3][0] = inTranslation.x - r1 * inPivot.x - r2 * inPivot.y - r3 * inPivot.z;
+ m[3][1] = inTranslation.y - r4 * inPivot.x - r5 * inPivot.y - r6 * inPivot.z;
+ m[3][2] = inTranslation.z - r7 * inPivot.x - r8 * inPivot.y - r9 * inPivot.z;
+ m[3][3] = 1.0f;
+
+ m_Translation = inTranslation;
+ m_Rotation = inRotation;
+ m_Scale = inScale;
+ m_Pivot = inPivot;
+*/
+
+}; // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/CachedMatrix.h b/src/Authoring/Client/Code/Core/Types/CachedMatrix.h
new file mode 100644
index 00000000..0acc3e37
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/CachedMatrix.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Matrix.h"
+#include "Vector3.h"
+#include "Rotation3.h"
+
+#include <math.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * @class CCachedMatrix
+ * @brief Cached matrix combining translation, scale, rotation and pivot.
+ *
+ * The trig functions in rotate is killing us so we cache these.
+ */
+class CCachedMatrix : public CMatrix
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ CVector3 m_Translation; ///< Last transformation vector
+ CRotation3 m_Rotation; ///< Last rotation angles
+ CVector3 m_Scale; ///< Last scale vector
+ CVector3 m_Pivot; ///< Last pivot vector
+
+ CMatrix m_TransMatrix; ///< Last transformation matrix
+ CMatrix m_RotMatrix; ///< Last rotation matrix
+ CMatrix m_ScaleMatrix; ///< Last scale matrix
+ CMatrix m_PivotMatrix; ///< Last pivot matrix
+
+ CMatrix m_ScalePivotRotationMatrix; ///< Last scale*pivot*rotation matrix
+
+ /* float m_SinX; ///< Sin of last x rotation
+ float m_SinY; ///< Sin of last y rotation
+ float m_SinZ; ///< Sin of last z rotation
+ float m_CosX; ///< Cos of last x rotation
+ float m_CosY; ///< Cos of last y rotation
+ float m_CosZ; ///< Cos of last z rotation
+ */
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CCachedMatrix();
+
+private:
+ CCachedMatrix(const CMatrix &inMatrix);
+ CCachedMatrix(float in00, float in01, float in02, float in03, float in10, float in11,
+ float in12, float in13, float in20, float in21, float in22, float in23,
+ float in30, float in31, float in32, float in33);
+
+public: // Access
+ void Set(const CVector3 &inTranslation, const CRotation3 &inRotation, const CVector3 &inScale,
+ const CVector3 &inPivot, const long inRotOrder = CMatrix::s_DefaultOrder,
+ const long inOrientation = CMatrix::LEFT_HANDED, const bool inForce = false);
+
+ inline void SinCos(const float inValue, float &outSin, float &outCos)
+ {
+ outSin = ::sin(inValue);
+ outCos = ::cos(inValue);
+ };
+
+ void ConvertLeftToRight()
+ {
+ m[0][2] = -m[0][2];
+ m[1][2] = -m[1][2];
+ m[2][0] = -m[2][0];
+ m[2][1] = -m[2][1];
+ m[2][3] = -m[2][3];
+ m[3][2] = -m[3][2];
+ }
+};
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Frustum.cpp b/src/Authoring/Client/Code/Core/Types/Frustum.cpp
new file mode 100644
index 00000000..0222a2f4
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Frustum.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "Frustum.h"
+#include "Matrix.h"
+#include "BoundingBox.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// CONSTRUCTION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Construct an empty frustum
+ */
+
+CFrustum::CFrustum()
+{
+}
+
+//==============================================================================
+/**
+ * Construct a fustum from a view/projection matrix.
+ * http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
+ */
+
+void CFrustum::Set(const CMatrix &inProjection)
+{
+#define M(x, y) inProjection.m[x][y]
+ // Left clipping plane
+ m_Planes[SIDE_LEFT].m_Normal.x = M(0, 3) + M(0, 0);
+ m_Planes[SIDE_LEFT].m_Normal.y = M(1, 3) + M(1, 0);
+ m_Planes[SIDE_LEFT].m_Normal.z = M(2, 3) + M(2, 0);
+ m_Planes[SIDE_LEFT].m_D = M(3, 3) + M(3, 0);
+
+ // Right clipping plane
+ m_Planes[SIDE_RIGHT].m_Normal.x = M(0, 3) - M(0, 0);
+ m_Planes[SIDE_RIGHT].m_Normal.y = M(1, 3) - M(1, 0);
+ m_Planes[SIDE_RIGHT].m_Normal.z = M(2, 3) - M(2, 0);
+ m_Planes[SIDE_RIGHT].m_D = M(3, 3) - M(3, 0);
+
+ // Top clipping plane
+ m_Planes[SIDE_TOP].m_Normal.x = M(0, 3) - M(0, 1);
+ m_Planes[SIDE_TOP].m_Normal.y = M(1, 3) - M(1, 1);
+ m_Planes[SIDE_TOP].m_Normal.z = M(2, 3) - M(2, 1);
+ m_Planes[SIDE_TOP].m_D = M(3, 3) - M(3, 1);
+
+ // Bottom clipping plane
+ m_Planes[SIDE_BOTTOM].m_Normal.x = M(0, 3) + M(0, 1);
+ m_Planes[SIDE_BOTTOM].m_Normal.y = M(1, 3) + M(1, 1);
+ m_Planes[SIDE_BOTTOM].m_Normal.z = M(2, 3) + M(2, 1);
+ m_Planes[SIDE_BOTTOM].m_D = M(3, 3) + M(3, 1);
+
+ // Near clipping plane
+ m_Planes[SIDE_NEAR].m_Normal.x = M(0, 2);
+ m_Planes[SIDE_NEAR].m_Normal.y = M(1, 2);
+ m_Planes[SIDE_NEAR].m_Normal.z = M(2, 2);
+ m_Planes[SIDE_NEAR].m_D = M(3, 2);
+
+ // Far clipping plane
+ m_Planes[SIDE_FAR].m_Normal.x = M(0, 3) - M(0, 2);
+ m_Planes[SIDE_FAR].m_Normal.y = M(1, 3) - M(1, 2);
+ m_Planes[SIDE_FAR].m_Normal.z = M(2, 3) - M(2, 2);
+ m_Planes[SIDE_FAR].m_D = M(3, 3) - M(3, 2);
+
+ // Normalize normals the normal norm
+ for (long thePlaneIndex = 0; thePlaneIndex < SIDE_COUNT; ++thePlaneIndex)
+ m_Planes[thePlaneIndex].Normalize();
+}
+
+//==============================================================================
+// ACCESS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Check the given box against this frustum to see if it's completely inside,
+ * partially inside or completely outside. Being completely outside is a
+ * criterion for culling. Being completely inside is also very good to know
+ * since there is no need to futher check containment of children as they
+ * too will all be inside.
+ */
+CFrustum::EContainment CFrustum::CheckContainment(const CBoundingBox &inBox) const
+{
+ EContainment theResult = CONTAINMENT_FULL;
+
+ for (long thePlaneIndex = 0; theResult != CONTAINMENT_NONE && thePlaneIndex < SIDE_COUNT;
+ ++thePlaneIndex)
+
+ switch (m_Planes[thePlaneIndex].CheckRelation(inBox)) {
+ // Return NONE immediately if the box is completely outside one of the planes
+ case CPlane::RELATION_BACK:
+ theResult = CONTAINMENT_NONE;
+ break;
+
+ // Flag as PARTIAL if the box clips any plane
+ case CPlane::RELATION_CLIPPED:
+ theResult = CONTAINMENT_PARTIAL;
+ break;
+
+ // Stay FULL only if all planes report front
+ case CPlane::RELATION_FRONT:
+ default:
+ break;
+ }
+
+ return theResult;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Frustum.h b/src/Authoring/Client/Code/Core/Types/Frustum.h
new file mode 100644
index 00000000..1af2ef41
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Frustum.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Plane.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CMatrix;
+class CBoundingBox;
+
+//==============================================================================
+/**
+ * @class CFrustum
+ * @brief Geometrical primitive aiding the culling of visible objects.
+ */
+class CFrustum
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+public:
+ enum { SIDE_TOP = 0, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT, SIDE_FAR, SIDE_NEAR, SIDE_COUNT };
+
+ enum EContainment {
+ CONTAINMENT_FULL, ///< Volume is completely inside the frustum
+ CONTAINMENT_PARTIAL, ///< Vaolume is partially inside the frustum
+ CONTAINMENT_NONE ///< No part of the volume is inside the frustum
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ CPlane m_Planes[SIDE_COUNT];
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+public: // Construction
+ CFrustum();
+ void Set(const CMatrix &inProjection);
+
+public: // Access
+ EContainment CheckContainment(const CBoundingBox &inBox) const;
+};
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Matrix.cpp b/src/Authoring/Client/Code/Core/Types/Matrix.cpp
new file mode 100644
index 00000000..e9f3287f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Matrix.cpp
@@ -0,0 +1,1244 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+
+#include "Matrix.h"
+#include "OptimizedArithmetic.h"
+#include "Vector3.h"
+#include "Rotation3.h"
+#include <cmath>
+
+#include "EulerAngles.h"
+
+namespace Q3DStudio {
+
+const float IDENTITY_MATRIX[4][4] = {
+ { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 }
+};
+
+//==============================================================================
+/**
+* Constructs the CMatrix object, setting it to the identitiy
+*/
+CMatrix::CMatrix()
+{
+ // Initialize the fields.
+ ::memcpy(&m, &IDENTITY_MATRIX, sizeof(m));
+}
+
+//==============================================================================
+/**
+ * Constructs and initializes the object given a source matrix.
+ */
+CMatrix::CMatrix(const CMatrix &inMatrix)
+{
+ ::memcpy(&m, &inMatrix.m, sizeof(m));
+}
+
+//==============================================================================
+/**
+ * Constructs and initializes the object given all elements of the matrix.
+ */
+CMatrix::CMatrix(float in00, float in01, float in02, float in03, float in10, float in11, float in12,
+ float in13, float in20, float in21, float in22, float in23, float in30, float in31,
+ float in32, float in33)
+{
+ m[0][0] = in00;
+ m[0][1] = in01;
+ m[0][2] = in02;
+ m[0][3] = in03;
+
+ m[1][0] = in10;
+ m[1][1] = in11;
+ m[1][2] = in12;
+ m[1][3] = in13;
+
+ m[2][0] = in20;
+ m[2][1] = in21;
+ m[2][2] = in22;
+ m[2][3] = in23;
+
+ m[3][0] = in30;
+ m[3][1] = in31;
+ m[3][2] = in32;
+ m[3][3] = in33;
+}
+
+//==============================================================================
+/**
+ * Set: Sets the values of this matrix with the given matrix.
+ *
+ * @param inMatrix
+ */
+void CMatrix::Set(const CMatrix &inMatrix)
+{
+ ::memcpy(&m, &inMatrix.m, sizeof(m));
+}
+
+//==============================================================================
+/**
+ * Provides (row, column) access to the matrix.
+ *
+ * @param inRow The row index into the matrix
+ * @param inColumn The column index into the array
+ *
+ * @return a reference to the element
+ */
+float &CMatrix::operator()(const long &inRow, const long &inColumn)
+{
+ // Check bounds of input
+ if (!CheckBounds(inRow, inColumn)) {
+ // throw out_of_range exception
+ }
+
+ return m[inRow][inColumn];
+}
+
+//==============================================================================
+/**
+ * Provides direct access to array elements.
+ * @return a reference to the matrix 4x4
+ */
+CMatrix::TArray &CMatrix::GetArray()
+{
+ return m;
+}
+
+//==============================================================================
+/**
+ * Provides (row, column) access to the matrix.
+ *
+ * @param inRow The row index into the matrix
+ * @param inColumn The column index into the array
+ *
+ * @return a copy of the element
+ */
+float CMatrix::operator()(const long &inRow, const long &inColumn) const
+{
+ // Check bounds of input
+ if (!CheckBounds(inRow, inColumn)) {
+ // throw out_of_range exception
+ }
+
+ return m[inRow][inColumn];
+}
+
+//==============================================================================
+/**
+ * Adds this matrix to the matrix being passed in and returns the sum.
+ *
+ * This method does not modify this matrix.
+ *
+ * @param inMatrix The matrix to add to this matrix
+ *
+ * @return The sum of the two matrices.
+ */
+CMatrix CMatrix::operator+(const CMatrix &inMatrix) const
+{
+ CMatrix theSum;
+
+ for (long theRow = 0; theRow < 4; ++theRow) {
+ for (long theColumn = 0; theColumn < 4; ++theColumn) {
+ theSum.m[theRow][theColumn] = m[theRow][theColumn] + inMatrix.m[theRow][theColumn];
+ }
+ }
+
+ return theSum;
+}
+
+//==============================================================================
+/**
+ * Subtracts the matrix passed in from this matrix and returns the difference.
+ *
+ * This method does not modify this matrix.
+ *
+ * @param inMatrix The matrix to subtract from this matrix
+ *
+ * @return The sum of the two matrices.
+ */
+CMatrix CMatrix::operator-(const CMatrix &inMatrix) const
+{
+ CMatrix theDiff;
+
+ for (long theRow = 0; theRow < 4; ++theRow) {
+ for (long theColumn = 0; theColumn < 4; ++theColumn) {
+ theDiff.m[theRow][theColumn] = m[theRow][theColumn] - inMatrix.m[theRow][theColumn];
+ }
+ }
+
+ return theDiff;
+}
+
+//==============================================================================
+/**
+ * Multiiply this by the one passed in and return the new matrix.
+ *
+ * This method does not modify this matrix.
+ *
+ * @param inMatrix The matrix to multiply to this matrix
+ *
+ * @return The product of the two matrices.
+ */
+CMatrix CMatrix::operator*(const CMatrix &inMatrix) const
+{
+ CMatrix theCat;
+ COptimizedArithmetic::MatrixMultiply(m[0], inMatrix.m[0], theCat.m[0]);
+
+ return theCat;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is equal to the matrix being passed in.
+ *
+ * @param inMatrix The matrix to to test for equality with this matrix.
+ *
+ * @return true if the matrices are equal, otherwise false.
+ */
+bool CMatrix::operator==(const CMatrix &inMatrix) const
+{
+ bool theEqualFlag = true;
+
+ for (long theRow = 0; theEqualFlag && theRow < 4; ++theRow) {
+ for (long theColumn = 0; theEqualFlag && theColumn < 4; ++theColumn) {
+ if (inMatrix.m[theRow][theColumn] != m[theRow][theColumn]) {
+ theEqualFlag = false;
+ }
+ }
+ }
+
+ return theEqualFlag;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is NOT equal to the matrix being passed in.
+ *
+ * @param inMatrix The matrix to to test for inequality with this matrix.
+ *
+ * @return true if the matrices are NOT equal, otherwise false.
+ */
+bool CMatrix::operator!=(const CMatrix &inMatrix) const
+{
+ bool theNotEqualFlag = false;
+
+ for (long theRow = 0; !theNotEqualFlag && theRow < 4; ++theRow) {
+ for (long theColumn = 0; !theNotEqualFlag && theColumn < 4; ++theColumn) {
+ if (inMatrix.m[theRow][theColumn] != m[theRow][theColumn]) {
+ theNotEqualFlag = true;
+ }
+ }
+ }
+
+ return theNotEqualFlag;
+}
+
+//==============================================================================
+/**
+ * operator =: Assign the value of this vector.
+ *
+ * Long Description.
+ *
+ * @param CMatrix& inMatrix
+ */
+CMatrix &CMatrix::operator=(const CMatrix &inMatrix)
+{
+ // Check for self assignment
+ if (this != &inMatrix) {
+ ::memcpy(&m, &inMatrix.m, sizeof(m));
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Add a matrix to this matrix.
+ *
+ * This method does modify this matrix.
+ *
+ * @param inMatrix The matrix to add to this.
+ *
+ * @return this modified matrix.
+ */
+CMatrix &CMatrix::operator+=(const CMatrix &inMatrix)
+{
+ for (long theRow = 0; theRow < 4; ++theRow) {
+ for (long theColumn = 0; theColumn < 4; ++theColumn) {
+ m[theRow][theColumn] += inMatrix.m[theRow][theColumn];
+ }
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Subtract a matrix from this matrix.
+ *
+ * This method does modify this matrix.
+ *
+ * @param inMatrix The matrix to subtract from this.
+ *
+ * @return this modified matrix.
+ */
+CMatrix &CMatrix::operator-=(const CMatrix &inMatrix)
+{
+ for (long theRow = 0; theRow < 4; ++theRow) {
+ for (long theColumn = 0; theColumn < 4; ++theColumn) {
+ m[theRow][theColumn] -= inMatrix.m[theRow][theColumn];
+ }
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Multiply a matrix to this matrix.
+ *
+ * This method does modify this matrix.
+ *
+ * @param inMatrix The matrix to multiply to this.
+ *
+ * @return this modified matrix.
+ */
+CMatrix &CMatrix::operator*=(const CMatrix &inMatrix)
+{
+ CMatrix theCat;
+ COptimizedArithmetic::MatrixMultiply(m[0], inMatrix.m[0], theCat.m[0]);
+
+ *this = theCat;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets this matrix to the given rotation and translation vectors and returns this.
+ *
+ * @param inVector The vector to translate the matrix by.
+ *
+ * @return This matrix after the translation.
+ */
+/*CMatrix& CMatrix::Set( const CVector3& inVector )
+{
+ CMatrix theTransMatrix ( MakeTranslate( inVector ) );
+
+ // Modify this matrix
+ this *= theTransMatrix;
+
+ return *this;
+}*/
+
+//==============================================================================
+/**
+ * Translates this matrix by the given vector and returns this.
+ *
+ * @param inVector The vector to translate the matrix by.
+ *
+ * @return This matrix after the translation.
+ */
+CMatrix &CMatrix::Translate(const CVector3 &inVector)
+{
+ CMatrix theTransMatrix(MakeTranslate(inVector));
+
+ // Modify this matrix
+ *this *= theTransMatrix;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Rotates this matrix by the given rotation vector and returns this.
+ *
+ * @param inRotation The vector to rotate the matrix by.
+ *
+ * @return This matrix after the rotation.
+ */
+CMatrix &CMatrix::Rotate(const CRotation3 &inRotation)
+{
+ CMatrix theRotateMatrix(MakeRotate(inRotation));
+
+ // Modify this matrix
+ *this *= theRotateMatrix;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Scales this matrix by the given vector and returns this.
+ *
+ * @param inScale The vector to scale the matrix by.
+ *
+ * @return This matrix after the rotation.
+ */
+CMatrix &CMatrix::Scale(const CVector3 &inScale)
+{
+ CMatrix theScaleMatrix(MakeScale(inScale));
+
+ // Modify this matrix
+ *this *= theScaleMatrix;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Returns the translation vector implicit in this matrix.
+ *
+ * @return The vector representing the translation portion of the matrix.
+ */
+CVector3 CMatrix::GetTranslation() const
+{
+ CVector3 theLocation(m[3][0], m[3][1], m[3][2]);
+
+ return theLocation;
+}
+
+//==============================================================================
+/**
+ * Returns the x component(axis) from the matrix.
+ *
+ * @return The x axis vector.
+ */
+CVector3 CMatrix::GetXComponent() const
+{
+ CVector3 theXComponent(m[0][0], m[0][1], m[0][2]);
+
+ return theXComponent;
+}
+
+//==============================================================================
+/**
+ * Returns the y component(axis) from the matrix.
+ *
+ * @return The y axis vector.
+ */
+CVector3 CMatrix::GetYComponent() const
+{
+ CVector3 theYComponent(m[1][0], m[1][1], m[1][2]);
+
+ return theYComponent;
+}
+
+//==============================================================================
+/**
+ * Returns the z component(axis) from the matrix.
+ *
+ * @return The z axis vector.
+ */
+CVector3 CMatrix::GetZComponent() const
+{
+ CVector3 theZComponent(m[2][0], m[2][1], m[2][2]);
+
+ return theZComponent;
+}
+
+//==============================================================================
+/**
+ * Rotate this matrix to face the specified matrix.
+ *
+ * @param inMatrix The maxtirx we are to face.
+ * @return This matrix after the rotation.
+ */
+CMatrix &CMatrix::Billboard(const CMatrix &inMatrix, bool inFreeRotateFlag /*= false*/)
+{
+ CVector3 theStartPos = GetTranslation();
+ CVector3 theTargetPos = inMatrix.GetTranslation();
+ CVector3 theUp = inMatrix.GetYComponent();
+ CVector3 theDistance(theStartPos - theTargetPos);
+
+ // Create the initial Z axis
+ CVector3 theZ(theStartPos - theTargetPos);
+ theZ.Normalize();
+
+ // Create the X and Y
+ CVector3 theY(theUp);
+ CVector3 theX(theY.CrossProduct(theZ));
+
+ // Billboard: Finalize the info and lock the Y axis (like a tree)
+ if (!inFreeRotateFlag) {
+ theZ = theX.CrossProduct(theY);
+ theX.Normalize();
+ theY.Normalize();
+ theZ.Normalize();
+ }
+
+ // LookAt: Finalize the info with no locked axis (free rotate)
+ else {
+ theY = theZ.CrossProduct(theX);
+ theX.Normalize();
+ theY.Normalize();
+ }
+
+ // Copy it into the matrix
+ m[0][0] = theX.x;
+ m[0][1] = theX.y;
+ m[0][2] = theX.z;
+
+ m[1][0] = theY.x;
+ m[1][1] = theY.y;
+ m[1][2] = theY.z;
+
+ m[2][0] = theZ.x;
+ m[2][1] = theZ.y;
+ m[2][2] = theZ.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Rotate this matrix to align with the rotation of the specified matrix.
+ *
+ * @param inMatrix The maxtrix we are cloning.
+ * @param inMirrorFlag Flag indicating that we should flip the z and face the
+ *opposite direction.
+ * @return This matrix after the rotation.
+ */
+CMatrix &CMatrix::CloneRotation(const CMatrix &inMatrix, bool inMirrorFlag /*= false*/)
+{
+ // Create the axes
+ CVector3 theZ(inMatrix.GetZComponent());
+ if (inMirrorFlag)
+ theZ *= -1;
+ CVector3 theY(inMatrix.GetYComponent());
+ CVector3 theX(theY.CrossProduct(theZ));
+
+ // Normalize
+ theX.Normalize();
+ theY.Normalize();
+ theZ.Normalize();
+
+ // Copy it into the matrix
+ m[0][0] = theX.x;
+ m[0][1] = theX.y;
+ m[0][2] = theX.z;
+
+ m[1][0] = theY.x;
+ m[1][1] = theY.y;
+ m[1][2] = theY.z;
+
+ m[2][0] = theZ.x;
+ m[2][1] = theZ.y;
+ m[2][2] = theZ.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Translates this matrix by the given x, y, and z and returns this.
+ *
+ * @param inX X portion of vector to translate by
+ * @param inY Y portion of vector to translate by
+ * @param inZ Z portion of vector to translate by
+ *
+ * @return This matrix after the translation.
+ */
+CMatrix &CMatrix::Translate(const float &inX, const float &inY, const float &inZ)
+{
+ CVector3 theVector(inX, inY, inZ);
+
+ return Translate(theVector);
+}
+
+//==============================================================================
+/**
+ * Initializes this matrix as a Translation Matrix given a translation vector.
+ * NOTE: These were created to avoid temporary intermediate matrices.
+ * @param inTranslate the Vector that contains the Translation
+ */
+void CMatrix::SetTranslate(const CVector3 &inTranslate)
+{
+ Identity();
+
+ // Set tranlate portion of matrix.
+ m[3][0] = inTranslate.x;
+ m[3][1] = inTranslate.y;
+ m[3][2] = inTranslate.z;
+}
+
+//==============================================================================
+/**
+ * Initializes this matrix as a Rotation Matrix given a rotation vector.
+ * NOTE: These were created to avoid temporary intermediate matrices.
+ * @param inRotation the Vector that contains the Rotation
+ * @param inRotOrder the rotation order (see CMatrix::ERotationOrder)
+ * @param inOrientation the handedness (see CMatrix::EOrientation)
+ */
+void CMatrix::SetRotate(const CRotation3 &inRotation, long inRotOrder, long inOrientation)
+{
+ if (inOrientation == CMatrix::RIGHT_HANDED) {
+ // Convert to left-handed
+
+ EulerAngleConverter::EulerAngles theEulerAngles;
+ INT32 theRotationOrder;
+ FormatEulerAngles(inRotOrder, -inRotation.x, -inRotation.y, -inRotation.z, theRotationOrder,
+ theEulerAngles.x, theEulerAngles.y, theEulerAngles.z);
+ theEulerAngles.w = static_cast<FLOAT>(theRotationOrder);
+
+ EulerAngleConverter::CEulerAngleConverter theConverter;
+ theConverter.Eul_ToHMatrix(theEulerAngles, m);
+
+ m[0][2] *= -1;
+ m[1][2] *= -1;
+ m[2][0] *= -1;
+ m[2][1] *= -1;
+
+ // Set tranlate portion of matrix.
+ m[3][0] = 0.0f;
+ m[3][1] = 0.0f;
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ } else {
+
+ // The original code
+ // Left-handed hard-coded YXZ rotation.
+
+ // Precalculate the sins and cosins.
+ float theSinX = ::sin(inRotation.x);
+ float theCosX = ::cos(inRotation.x);
+ float theSinY = ::sin(inRotation.y);
+ float theCosY = ::cos(inRotation.y);
+ float theSinZ = ::sin(inRotation.z);
+ float theCosZ = ::cos(inRotation.z);
+
+ // Fill out the matrix.
+ m[0][0] = (theCosZ * theCosY) + (theSinX * theSinY * theSinZ);
+ m[0][1] = -theCosX * -theSinZ;
+ m[0][2] = -(theSinY * theCosZ) + (theSinZ * theCosY * theSinX);
+
+ m[1][0] = -(theSinZ * theCosY) + (theSinX * theSinY * theCosZ);
+ m[1][1] = theCosX * theCosZ;
+ m[1][2] = (theSinY * theSinZ) + (theSinX * theCosY * theCosZ);
+
+ m[2][0] = theSinY * theCosX;
+ m[2][1] = -theSinX;
+ m[2][2] = theCosX * theCosY;
+
+ // Set tranlate portion of matrix.
+ m[3][0] = 0.0f;
+ m[3][1] = 0.0f;
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+
+ } // Left-Handed
+}
+
+//==============================================================================
+/**
+* Re-arrange euler angles information to a format useable by EulerAngleConverter
+* @param inRotationOrder the rotation order enum from Studio
+* @param inXAngle the x-axis rotation from Studio
+* @param inYAngle the y-axis rotation from Studio
+* @param inZAngle the z-axis rotation from Studio
+* @param outRotationOrder the rotation order useable by EulerAngleConverter
+* @param outFirstAngle the first euler angle used in EulerAngleConverter
+* @param outSecondAngle the second euler angle used in EulerAngleConverter
+* @param outThirdAngle the third euler angle used in EulerAngleConverter
+*/
+void CMatrix::FormatEulerAngles(INT32 inRotationOrder, FLOAT inXAngle, FLOAT inYAngle,
+ FLOAT inZAngle, INT32 &outRotationOrder, FLOAT &outFirstAngle,
+ FLOAT &outSecondAngle, FLOAT &outThirdAngle)
+{
+ if (inRotationOrder == XYZ) {
+ outRotationOrder = EulOrdXYZs;
+ outFirstAngle = inXAngle;
+ outSecondAngle = inYAngle;
+ outThirdAngle = inZAngle;
+ } else if (inRotationOrder == YZX) {
+ outRotationOrder = EulOrdYZXs;
+ outFirstAngle = inYAngle;
+ outSecondAngle = inZAngle;
+ outThirdAngle = inXAngle;
+ } else if (inRotationOrder == ZXY) {
+ outRotationOrder = EulOrdZXYs;
+ outFirstAngle = inZAngle;
+ outSecondAngle = inXAngle;
+ outThirdAngle = inYAngle;
+ } else if (inRotationOrder == XZY) {
+ outRotationOrder = EulOrdXZYs;
+ outFirstAngle = inXAngle;
+ outSecondAngle = inZAngle;
+ outThirdAngle = inYAngle;
+ } else if (inRotationOrder == YXZ) {
+ outRotationOrder = EulOrdYXZs;
+ outFirstAngle = inYAngle;
+ outSecondAngle = inXAngle;
+ outThirdAngle = inZAngle;
+ } else if (inRotationOrder == ZYX) {
+ outRotationOrder = EulOrdZYXs;
+ outFirstAngle = inZAngle;
+ outSecondAngle = inYAngle;
+ outThirdAngle = inXAngle;
+ }
+ //
+ else if (inRotationOrder == XYZr) {
+ outRotationOrder = EulOrdXYZr;
+ outFirstAngle = inXAngle;
+ outSecondAngle = inYAngle;
+ outThirdAngle = inZAngle;
+ } else if (inRotationOrder == YZXr) {
+ outRotationOrder = EulOrdYZXr;
+ outFirstAngle = inYAngle;
+ outSecondAngle = inZAngle;
+ outThirdAngle = inXAngle;
+ } else if (inRotationOrder == ZXYr) {
+ outRotationOrder = EulOrdZXYr;
+ outFirstAngle = inZAngle;
+ outSecondAngle = inXAngle;
+ outThirdAngle = inYAngle;
+ } else if (inRotationOrder == XZYr) {
+ outRotationOrder = EulOrdXZYr;
+ outFirstAngle = inXAngle;
+ outSecondAngle = inZAngle;
+ outThirdAngle = inYAngle;
+ } else if (inRotationOrder == YXZr) {
+ outRotationOrder = EulOrdYXZr;
+ outFirstAngle = inYAngle;
+ outSecondAngle = inXAngle;
+ outThirdAngle = inZAngle;
+ } else if (inRotationOrder == ZYXr) {
+ outRotationOrder = EulOrdZYXr;
+ outFirstAngle = inZAngle;
+ outSecondAngle = inYAngle;
+ outThirdAngle = inXAngle;
+ } else {
+ // assert( false );
+ }
+}
+
+//==============================================================================
+/**
+ * Initializes this matrix as a Scale Matrix given the Scale Vector.
+ * NOTE: These were created to avoid temporary intermediate matrices.
+ * @param inScale.
+ */
+void CMatrix::SetScale(const CVector3 &inScale)
+{
+ Identity();
+ // Create a scaled identity matrix.
+ m[0][0] = inScale.x;
+ m[1][1] = inScale.y;
+ m[2][2] = inScale.z;
+}
+
+//==============================================================================
+/**
+ * Set this matrix to the all zeros.
+ *
+ * @return this matrix as a zero matrix.
+ */
+CMatrix &CMatrix::Zero()
+{
+ m[0][0] = 0;
+ m[0][1] = 0;
+ m[0][2] = 0;
+ m[0][3] = 0;
+
+ m[1][0] = 0;
+ m[1][1] = 0;
+ m[1][2] = 0;
+ m[1][3] = 0;
+
+ m[2][0] = 0;
+ m[2][1] = 0;
+ m[2][2] = 0;
+ m[2][3] = 0;
+
+ m[3][0] = 0;
+ m[3][1] = 0;
+ m[3][2] = 0;
+ m[3][3] = 0;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Set this matrix to the Identity.
+ *
+ * @return this matrix as an identity matrix
+ */
+CMatrix &CMatrix::Identity()
+{
+ ::memcpy(&m, &IDENTITY_MATRIX, sizeof(m));
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the current matrix to describe a perspective matrix that produces
+ * a perspective projection. This is a DX style 0..1 clipping prjection matrix.
+ *
+ * A = (r+l)/(r-l)
+ * B = (t+b)/(t-b)
+ * C = f/(f-n)
+ * D = -fn/(f-n)
+ *
+ * 2n/(r-l) 0 0 0
+ * 0 2n/(t-b) 0 0
+ * A B C 1
+ * 0 0 D 0
+ */
+CMatrix &CMatrix::Frustum(const bool &inOrthographic, const float &inNear, const float &inFar,
+ const float &inLeft, const float &inTop, const float &inRight,
+ const float &inBottom)
+{
+ float theWidth = static_cast<float>(inRight - inLeft);
+ float theHeight = static_cast<float>(inBottom - inTop);
+ float theClipDist = inFar - inNear;
+
+ if (theWidth > 0 && theHeight > 0 && theClipDist > 0) {
+ float theWidthRecip = 1.0f / theWidth;
+ float theHeightRecip = 1.0f / theHeight;
+ float theClipRecip = 1.0f / theClipDist;
+
+ Identity();
+ if (inOrthographic) {
+ m[0][0] = 2.0f * theWidthRecip;
+ m[1][1] = 2.0f * theHeightRecip;
+ m[2][2] = 1.0f * theClipRecip;
+
+ m[3][0] = -(inRight + inLeft) * theWidthRecip;
+ m[3][1] = -(inTop + inBottom) * theHeightRecip;
+ m[3][2] = (-inFar * theClipRecip) + 1; //-(inFar+inNear) * theClipRecip;
+ m[3][3] = 1.0;
+ } else {
+ m[0][0] = 2.0f * inNear * theWidthRecip;
+ m[1][1] = 2.0f * inNear * theHeightRecip;
+ m[2][0] = -(inRight + inLeft) * theWidthRecip;
+ m[2][1] = -(inBottom + inTop) * theHeightRecip;
+ m[2][2] = inFar * theClipRecip; // C
+ m[2][3] = 1.0f;
+ m[3][2] = (-inFar * inNear) * theClipRecip; // D
+ m[3][3] = 0.0f;
+ }
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Flip the matrix along its diagonal.
+ *
+ * @return this matrix, transposed.
+ */
+CMatrix &CMatrix::Transpose()
+{
+ CMatrix theHoldMatrix(*this);
+
+ // Loop through and flip all the data on the matrix
+ for (long theRow = 0; theRow < 4; ++theRow) {
+ for (long theColumn = 0; theColumn < 4; ++theColumn) {
+ // flip elements along the diagonal by reading from the hold matrix
+ m[theRow][theColumn] = theHoldMatrix.m[theColumn][theRow];
+ }
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Validates the the row and column being passed in does not overstep the
+ * matrix array bounds.
+ *
+ * @param inRow The row index into the array
+ * @param inColumn The column index into the array
+ *
+ * @return true if the row/column is within range, otherwise false
+ */
+bool CMatrix::CheckBounds(const long &inRow, const long &inColumn) const
+{
+ return ((inRow < 4 && inRow >= 0) && (inColumn < 4 && inColumn >= 0));
+}
+
+//==============================================================================
+/**
+ * Creates a translation matrix from the incoming vector.
+ *
+ * @param inVector The vector from which the translation matrix is created
+ *from.
+ *
+ * @return The translation matrix.
+ */
+CMatrix CMatrix::MakeTranslate(const CVector3 &inVector) const
+{
+ CMatrix theTranslation;
+
+ // Set tranlate portion of matrix.
+ theTranslation.m[3][0] = inVector.x;
+ theTranslation.m[3][1] = inVector.y;
+ theTranslation.m[3][2] = inVector.z;
+
+ return theTranslation;
+}
+
+//==============================================================================
+/**
+ * Creates a rotation matrix from the incoming vector.
+ *
+ * @param inRotation The rotation vector from which the rotation matrix
+ *is created from.
+ *
+ * @return The rotation matrix.
+ */
+CMatrix CMatrix::MakeRotate(const CRotation3 &inRotation) const
+{
+ CMatrix theRotation;
+
+ // Precalculate the sins and cosins.
+ float theSinX = (float)sin(inRotation.x);
+ float theSinY = (float)sin(inRotation.y);
+ float theSinZ = (float)sin(inRotation.z);
+ float theCosX = (float)cos(inRotation.x);
+ float theCosY = (float)cos(inRotation.y);
+ float theCosZ = (float)cos(inRotation.z);
+
+ // Fill out the matrix.
+ theRotation.m[0][0] = (theCosZ * theCosY) + (theSinX * theSinY * theSinZ);
+ theRotation.m[0][1] = -theCosX * -theSinZ;
+ theRotation.m[0][2] = -(theSinY * theCosZ) + (theSinZ * theCosY * theSinX);
+
+ theRotation.m[1][0] = -(theSinZ * theCosY) + (theSinX * theSinY * theCosZ);
+ theRotation.m[1][1] = theCosX * theCosZ;
+ theRotation.m[1][2] = (theSinY * theSinZ) + (theSinX * theCosY * theCosZ);
+
+ theRotation.m[2][0] = theSinY * theCosX;
+ theRotation.m[2][1] = -theSinX;
+ theRotation.m[2][2] = theCosX * theCosY;
+
+ return theRotation;
+}
+
+//==============================================================================
+/**
+ * Creates a scale matrix from the incoming vector.
+ *
+ * @param inVector The vector from which the scale matrix is created from.
+ *
+ * @return The scale matrix.
+ */
+CMatrix CMatrix::MakeScale(const CVector3 &inScale) const
+{
+ CMatrix theScale;
+
+ // Create a scaled identity matrix.
+ theScale.m[0][0] = inScale.x;
+ theScale.m[1][1] = inScale.y;
+ theScale.m[2][2] = inScale.z;
+
+ return theScale;
+}
+
+//==============================================================================
+/**
+ * Performs a matrix concatenation ( mulitplication ) of this matrix by the one passed
+ *in.
+ */
+CMatrix CMatrix::Concatenate(const CMatrix &inMatrix) const
+{
+ CMatrix theCat;
+
+ COptimizedArithmetic::MatrixMultiply(m[0], inMatrix.m[0], theCat.m[0]);
+ /*
+ theCat.m[ 0 ][ 0 ] = m[ 0 ][ 0 ] * inMatrix.m[ 0 ][ 0 ] + m[ 0 ][ 1 ] * inMatrix.m[ 1 ][
+ 0 ] + m[ 0 ][ 2 ] * inMatrix.m[ 2 ][ 0 ] + m[ 0 ][ 3 ] * inMatrix.m[ 3 ][ 0 ];
+ theCat.m[ 0 ][ 1 ] = m[ 0 ][ 0 ] * inMatrix.m[ 0 ][ 1 ] + m[ 0 ][ 1 ] * inMatrix.m[ 1 ][
+ 1 ] + m[ 0 ][ 2 ] * inMatrix.m[ 2 ][ 1 ] + m[ 0 ][ 3 ] * inMatrix.m[ 3 ][ 1 ];
+ theCat.m[ 0 ][ 2 ] = m[ 0 ][ 0 ] * inMatrix.m[ 0 ][ 2 ] + m[ 0 ][ 1 ] * inMatrix.m[ 1 ][
+ 2 ] + m[ 0 ][ 2 ] * inMatrix.m[ 2 ][ 2 ] + m[ 0 ][ 3 ] * inMatrix.m[ 3 ][ 2 ];
+ theCat.m[ 0 ][ 3 ] = m[ 0 ][ 0 ] * inMatrix.m[ 0 ][ 3 ] + m[ 0 ][ 1 ] * inMatrix.m[ 1 ][
+ 3 ] + m[ 0 ][ 2 ] * inMatrix.m[ 2 ][ 3 ] + m[ 0 ][ 3 ] * inMatrix.m[ 3 ][ 3 ];
+
+ theCat.m[ 1 ][ 0 ] = m[ 1 ][ 0 ] * inMatrix.m[ 0 ][ 0 ] + m[ 1 ][ 1 ] * inMatrix.m[ 1 ][
+ 0 ] + m[ 1 ][ 2 ] * inMatrix.m[ 2 ][ 0 ] + m[ 1 ][ 3 ] * inMatrix.m[ 3 ][ 0 ];
+ theCat.m[ 1 ][ 1 ] = m[ 1 ][ 0 ] * inMatrix.m[ 0 ][ 1 ] + m[ 1 ][ 1 ] * inMatrix.m[ 1 ][
+ 1 ] + m[ 1 ][ 2 ] * inMatrix.m[ 2 ][ 1 ] + m[ 1 ][ 3 ] * inMatrix.m[ 3 ][ 1 ];
+ theCat.m[ 1 ][ 2 ] = m[ 1 ][ 0 ] * inMatrix.m[ 0 ][ 2 ] + m[ 1 ][ 1 ] * inMatrix.m[ 1 ][
+ 2 ] + m[ 1 ][ 2 ] * inMatrix.m[ 2 ][ 2 ] + m[ 1 ][ 3 ] * inMatrix.m[ 3 ][ 2 ];
+ theCat.m[ 1 ][ 3 ] = m[ 1 ][ 0 ] * inMatrix.m[ 0 ][ 3 ] + m[ 1 ][ 1 ] * inMatrix.m[ 1 ][
+ 3 ] + m[ 1 ][ 2 ] * inMatrix.m[ 2 ][ 3 ] + m[ 1 ][ 3 ] * inMatrix.m[ 3 ][ 3 ];
+
+ theCat.m[ 2 ][ 0 ] = m[ 2 ][ 0 ] * inMatrix.m[ 0 ][ 0 ] + m[ 2 ][ 1 ] * inMatrix.m[ 1 ][
+ 0 ] + m[ 2 ][ 2 ] * inMatrix.m[ 2 ][ 0 ] + m[ 2 ][ 3 ] * inMatrix.m[ 3 ][ 0 ];
+ theCat.m[ 2 ][ 1 ] = m[ 2 ][ 0 ] * inMatrix.m[ 0 ][ 1 ] + m[ 2 ][ 1 ] * inMatrix.m[ 1 ][
+ 1 ] + m[ 2 ][ 2 ] * inMatrix.m[ 2 ][ 1 ] + m[ 2 ][ 3 ] * inMatrix.m[ 3 ][ 1 ];
+ theCat.m[ 2 ][ 2 ] = m[ 2 ][ 0 ] * inMatrix.m[ 0 ][ 2 ] + m[ 2 ][ 1 ] * inMatrix.m[ 1 ][
+ 2 ] + m[ 2 ][ 2 ] * inMatrix.m[ 2 ][ 2 ] + m[ 2 ][ 3 ] * inMatrix.m[ 3 ][ 2 ];
+ theCat.m[ 2 ][ 3 ] = m[ 2 ][ 0 ] * inMatrix.m[ 0 ][ 3 ] + m[ 2 ][ 1 ] * inMatrix.m[ 1 ][
+ 3 ] + m[ 2 ][ 2 ] * inMatrix.m[ 2 ][ 3 ] + m[ 2 ][ 3 ] * inMatrix.m[ 3 ][ 3 ];
+
+ theCat.m[ 3 ][ 0 ] = m[ 3 ][ 0 ] * inMatrix.m[ 0 ][ 0 ] + m[ 3 ][ 1 ] * inMatrix.m[ 1 ][
+ 0 ] + m[ 3 ][ 2 ] * inMatrix.m[ 2 ][ 0 ] + m[ 3 ][ 3 ] * inMatrix.m[ 3 ][ 0 ];
+ theCat.m[ 3 ][ 1 ] = m[ 3 ][ 0 ] * inMatrix.m[ 0 ][ 1 ] + m[ 3 ][ 1 ] * inMatrix.m[ 1 ][
+ 1 ] + m[ 3 ][ 2 ] * inMatrix.m[ 2 ][ 1 ] + m[ 3 ][ 3 ] * inMatrix.m[ 3 ][ 1 ];
+ theCat.m[ 3 ][ 2 ] = m[ 3 ][ 0 ] * inMatrix.m[ 0 ][ 2 ] + m[ 3 ][ 1 ] * inMatrix.m[ 1 ][
+ 2 ] + m[ 3 ][ 2 ] * inMatrix.m[ 2 ][ 2 ] + m[ 3 ][ 3 ] * inMatrix.m[ 3 ][ 2 ];
+ theCat.m[ 3 ][ 3 ] = m[ 3 ][ 0 ] * inMatrix.m[ 0 ][ 3 ] + m[ 3 ][ 1 ] * inMatrix.m[ 1 ][
+ 3 ] + m[ 3 ][ 2 ] * inMatrix.m[ 2 ][ 3 ] + m[ 3 ][ 3 ] * inMatrix.m[ 3 ][ 3 ];
+ */
+ return theCat;
+}
+
+//==============================================================================
+/**
+ * Inverts the matrix.
+ *
+ * Attempts to invert this matrix. If the matrix is singular, the inversion
+ * can not be done.
+ *
+ * @return true if the matrix was inverted, otherwise false if the matrix
+ * is singular.
+ */
+float CMatrix::Invert()
+{
+ float theDeterminant(0.0f);
+
+ if (IsAffine()) {
+ theDeterminant = InvertAffine();
+ } else {
+ theDeterminant = InvertNonSingular();
+ }
+
+ return theDeterminant;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is affine.
+ *
+ * T
+ * An affine matrix has the last column being [ 0 0 0 1 ]
+ *
+ * @return true if the matrix is affine, otherwise false.
+ */
+bool CMatrix::IsAffine() const
+{
+ return ((m[0][3] == 0.0 && m[1][3] == 0.0 && m[2][3] == 0.0 && m[3][3] == 1.0) ? true : false);
+}
+
+//==============================================================================
+/**
+ * Computes the inverse of a 3D affine matrix; i.e. a matrix with a dimen-
+ * sionality of 4 where the right column has the entries (0, 0, 0, 1).
+ *
+ * This procedure treats the 4 by 4 matrix as a block matrix and
+ * calculates the inverse of one submatrix for a significant perform-
+ * ance improvement over a general procedure that can invert any non-
+ * singular matrix:
+ * -- -- -- --
+ * | | -1 | -1 |
+ * | A 0 | | A 0 |
+ * -1 | | | |
+ * M = | | = | -1 |
+ * | C 1 | | -C A 1 |
+ * | | | |
+ * -- -- -- --
+ *
+ * where M is a 4 by 4 matrix,
+ * A is the 3 by 3 upper left submatrix of M,
+ * C is the 1 by 3 lower left submatrix of M.
+ *
+ * @return determinant of matrix
+ *
+ */
+float CMatrix::InvertAffine()
+{
+ const float PRECISIONLIMIT(1.0e-07f);
+ float theDeterminant(0.0f);
+ float thePositiveDet(0.0f);
+ float theNegativeDet(0.0f);
+ float theTempDet(0.0f);
+ CMatrix theInverse;
+
+ /*
+ * Calculate the determinant of submatrix A and determine if the
+ * the matrix is singular as limited by the float precision.
+ */
+ theTempDet = m[0][0] * m[1][1] * m[2][2];
+ if (theTempDet >= 0.0)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m[0][1] * m[1][2] * m[2][0];
+ if (theTempDet >= 0.0)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m[0][2] * m[1][0] * m[2][1];
+ if (theTempDet >= 0.0)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m[0][2] * m[1][1] * m[2][0];
+ if (theTempDet >= 0.0)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m[0][1] * m[1][0] * m[2][2];
+ if (theTempDet >= 0.0)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m[0][0] * m[1][2] * m[2][1];
+ if (theTempDet >= 0.0)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theDeterminant = thePositiveDet + theNegativeDet;
+ float theTrueDeterminate = theDeterminant; // Grab the old determinate from the otha sheeiit.
+
+ // Is the submatrix A nonsingular? (i.e. there is an inverse?)
+ if ((theDeterminant != 0.0)
+ || (::abs(theDeterminant / (thePositiveDet - theNegativeDet)) >= PRECISIONLIMIT)) {
+ // Calculate inverse(A) = adj(A) / det(A)
+ theDeterminant = 1.0f / theDeterminant;
+ theInverse.m[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * theDeterminant;
+ theInverse.m[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * theDeterminant;
+ theInverse.m[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * theDeterminant;
+ theInverse.m[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) * theDeterminant;
+ theInverse.m[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * theDeterminant;
+ theInverse.m[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * theDeterminant;
+ theInverse.m[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * theDeterminant;
+ theInverse.m[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * theDeterminant;
+ theInverse.m[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * theDeterminant;
+
+ // Calculate -C * inverse(A)
+ theInverse.m[3][0] = -(m[3][0] * theInverse.m[0][0] + m[3][1] * theInverse.m[1][0]
+ + m[3][2] * theInverse.m[2][0]);
+ theInverse.m[3][1] = -(m[3][0] * theInverse.m[0][1] + m[3][1] * theInverse.m[1][1]
+ + m[3][2] * theInverse.m[2][1]);
+ theInverse.m[3][2] = -(m[3][0] * theInverse.m[0][2] + m[3][1] * theInverse.m[1][2]
+ + m[3][2] * theInverse.m[2][2]);
+
+ // Fill in last column
+ theInverse.m[0][3] = theInverse.m[1][3] = theInverse.m[2][3] = 0.0;
+ theInverse.m[3][3] = 1.0;
+ ;
+
+ // Assing ourselves to the inverse
+ *this = theInverse;
+ }
+
+ return theTrueDeterminate;
+}
+
+//==============================================================================
+/**
+ * Inverts a nonsingular matrix.
+ *
+ * @return Determinant of matrix.
+ */
+float CMatrix::InvertNonSingular()
+{
+ return 0.0f;
+}
+
+//==============================================================================
+/**
+ * Calculate the determinant of this 4x4 matrix.
+ *
+ * @return the determinant of this matrix.
+ */
+float CMatrix::Determinant() const
+{
+ return m[0][0] * Determinant3x3(m[1][1], m[2][1], m[3][1], m[1][2], m[2][2], m[3][2], m[1][3],
+ m[2][3], m[3][3])
+ - m[0][1] * Determinant3x3(m[1][0], m[2][0], m[3][0], m[1][2], m[2][2], m[3][2], m[1][3],
+ m[2][3], m[3][3])
+ + m[0][2] * Determinant3x3(m[1][0], m[2][0], m[3][0], m[1][1], m[2][1], m[3][1], m[1][3],
+ m[2][3], m[3][3])
+ - m[0][3] * Determinant3x3(m[1][0], m[2][0], m[3][0], m[1][1], m[2][1], m[3][1], m[1][2],
+ m[2][2], m[3][2]);
+}
+
+//==============================================================================
+/**
+ * Calculate the determinant of a 3x3 matrix in the form
+ *
+ * | inA1, inB1, inC1 |
+ * | inA2, inB2, inC2 |
+ * | inA3, inB3, inC3 |
+ *
+ * @return the derminant
+ */
+float CMatrix::Determinant3x3(const float &inA1, const float &inA2, const float &inA3,
+ const float &inB1, const float &inB2, const float &inB3,
+ const float &inC1, const float &inC2, const float &inC3) const
+{
+ return inA1 * Determinant2x2(inB2, inB3, inC2, inC3)
+ - inB1 * Determinant2x2(inA2, inA3, inC2, inC3)
+ + inC1 * Determinant2x2(inA2, inA3, inB2, inB3);
+}
+
+//==============================================================================
+/**
+ * Calculate the determinant of a 2x2 matrix.
+ *
+ * @return the determinant of the matrix.
+ */
+float CMatrix::Determinant2x2(const float &inA, const float &inB, const float &inC,
+ const float &inD) const
+{
+ return inA * inD - inB * inC;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is the identity matrix
+ *
+ * @return true if this is the identity, otherwise false
+ */
+bool CMatrix::IsIdentity() const
+{
+ // Create and identity matrix
+ CMatrix theIdentity;
+
+ return (theIdentity == *this ? true : false);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Matrix.h b/src/Authoring/Client/Code/Core/Types/Matrix.h
new file mode 100644
index 00000000..49a5b8d9
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Matrix.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __MATRIX_H_
+#define __MATRIX_H_
+#include <QtGlobal>
+
+#include "Vector3.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+namespace Q3DStudio {
+class CRotation3;
+};
+
+typedef qint32 INT32;
+typedef float FLOAT;
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CMatrix: A simple, row major matrix in the form:
+ *
+ * | m0 m1 m2 m3 | or | m0 m1
+ *m2 w |
+ * | m4 m5 m6 m7 | | m4 m5
+ *m6 w |
+ * | m8 m9 m10 m11 | | m8 m9
+ *m10 w |
+ * | m12 m13 m14 m15 | | tX tY
+ *tZ w |
+ *
+ * Rotations are concatenated in the the following order: YXZ
+ * All rotations are clockwise when viewed down the positive axis towards to origin.
+ */
+class CMatrix
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+public:
+ enum ERotationOrder {
+ // maya and studio uses "static"
+ XYZ = 0,
+ YZX,
+ ZXY,
+ XZY,
+ YXZ,
+ ZYX,
+ // adding "relative" because 3ds max uses this
+ XYZr,
+ YZXr,
+ ZXYr,
+ XZYr,
+ YXZr,
+ ZYXr
+ };
+
+ enum EOrientation { LEFT_HANDED = 0, RIGHT_HANDED };
+
+ typedef float TArray[4][4];
+
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ static const long s_DefaultOrder = YXZ;
+
+ // Field members
+public:
+ TArray m; ///< 16 elements in a 4 x 4
+
+ // Construction/Destruction
+public:
+ CMatrix();
+ CMatrix(const CMatrix &inMatrix);
+ CMatrix(float in00, float in01, float in02, float in03, float in10, float in11, float in12,
+ float in13, float in20, float in21, float in22, float in23, float in30, float in31,
+ float in32, float in33);
+ virtual ~CMatrix() {}
+
+ // Set functions for MatrixScriptObject
+public:
+ void Set(const CMatrix &inMatrix);
+
+ // Equality operators
+public:
+ bool operator==(const CMatrix &inMatrix) const;
+ bool operator!=(const CMatrix &inMatrix) const;
+
+ // Assignment operators
+public:
+ CMatrix &operator=(const CMatrix &inMatrix);
+ CMatrix &operator+=(const CMatrix &inMatrix);
+ CMatrix &operator-=(const CMatrix &inMatrix);
+ CMatrix &operator*=(const CMatrix &inMatrix);
+
+ // Access operators
+public:
+ float &operator()(const long &inRow, const long &inColumn);
+ float operator()(const long &inRow, const long &inColumn) const;
+ TArray &GetArray();
+
+ // Binary operators
+public:
+ CMatrix operator+(const CMatrix &inMatrix) const;
+ CMatrix operator-(const CMatrix &inMatrix) const;
+ CMatrix operator*(const CMatrix &inMatrix) const;
+
+ // Matrix functions
+public:
+ CMatrix &Zero();
+ CMatrix &Identity();
+ CMatrix &Orthographic(const float &inNear, const float &inFar, const float &inWidth,
+ const float &inHeight);
+ CMatrix &Frustum(const bool &inOrthographic, const float &inNear, const float &inFar,
+ const float &inLeft, const float &inTop, const float &inRight,
+ const float &inBottom);
+ CMatrix &Transpose();
+ CMatrix &Translate(const CVector3 &inVector);
+ CMatrix &Translate(const float &inX, const float &inY, const float &inZ);
+ CMatrix &Rotate(const CRotation3 &inRotation);
+ CMatrix &Scale(const CVector3 &inVector);
+ float Determinant() const;
+ float Invert();
+ bool IsIdentity() const;
+
+ CVector3 GetTranslation() const;
+ CVector3 GetXComponent() const;
+ CVector3 GetYComponent() const;
+ CVector3 GetZComponent() const;
+
+ CMatrix &Billboard(const CMatrix &inMatrix, bool inFreeRotateFlag = false);
+ CMatrix &CloneRotation(const CMatrix &inMatrix, bool inMirrorFlag = false);
+
+ void SetTranslate(const CVector3 &inTranslate);
+ void SetRotate(const CRotation3 &inRotation, long inRotOder, long inOrientation);
+ void SetScale(const CVector3 &inScale);
+
+ // Implemntation
+protected:
+ bool IsAffine() const;
+ bool CheckBounds(const long &inRow, const long &inColumn) const;
+ CMatrix MakeTranslate(const CVector3 &inVector) const;
+ CMatrix MakeRotate(const CRotation3 &inRotation) const;
+ CMatrix MakeScale(const CVector3 &inScale) const;
+ CMatrix Concatenate(const CMatrix &inMatrix) const;
+ float InvertAffine();
+ float InvertNonSingular();
+ float Determinant2x2(const float &inA, const float &inB, const float &inC,
+ const float &inD) const;
+ float Determinant3x3(const float &inA1, const float &inA2, const float &inA3, const float &inB1,
+ const float &inB2, const float &inB3, const float &inC1, const float &inC2,
+ const float &inC3) const;
+ void FormatEulerAngles(INT32 inRotationOrder, FLOAT inXAngle, FLOAT inYAngle, FLOAT inZAngle,
+ INT32 &outRotationOrder, FLOAT &outFirstAngle, FLOAT &outSecondAngle,
+ FLOAT &outThirdAngle);
+};
+
+} // namespace Q3DStudio
+
+#endif // __MATRIX_H_
diff --git a/src/Authoring/Client/Code/Core/Types/MatrixStack.h b/src/Authoring/Client/Code/Core/Types/MatrixStack.h
new file mode 100644
index 00000000..8dcc253a
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/MatrixStack.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __MATRIXSTACK_H_
+#define __MATRIXSTACK_H_
+
+#include <stack>
+#include "Matrix.h"
+
+class CMatrixStack : public std::stack<Q3DStudio::CMatrix>
+{
+public:
+ //==============================================================================
+ /**
+ * Constructor initializes the stack with an identity matrix up top.
+ */
+ CMatrixStack() { std::stack<Q3DStudio::CMatrix>::push(Q3DStudio::CMatrix()); }
+
+ /**
+ * Push a matrix onto the stack and autmatically multiply this new matrix
+ * at the top of the stack with the old top matrix. This is when you
+ * continually push local matrices onto this stack since this auto
+ * multiplication esures that the top matrix is the global matrix.
+ *
+ * @param inMatrix matrix to be pushed and muliplied onto the stack
+ */
+ void push(const Q3DStudio::CMatrix &inMatrix)
+ {
+ std::stack<Q3DStudio::CMatrix>::push(inMatrix * top());
+ }
+};
+
+#endif //__MATRIXSTACK_H_
diff --git a/src/Authoring/Client/Code/Core/Types/OpaqueData.h b/src/Authoring/Client/Code/Core/Types/OpaqueData.h
new file mode 100644
index 00000000..c41dd83f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/OpaqueData.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+/**
+ * @class IOpaqueData
+ * @brief Interface to data which may or may not be know by the system.
+ */
+class IOpaqueData
+{
+ // Access
+public:
+ // Returns the four byte signature of the type of data implemented here (e.g. ModeBuffer =
+ // 'UICMB')
+ virtual unsigned long GetOpaqueDataType() const = 0;
+};
diff --git a/src/Authoring/Client/Code/Core/Types/Pixel.cpp b/src/Authoring/Client/Code/Core/Types/Pixel.cpp
new file mode 100644
index 00000000..03600306
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Pixel.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "Pixel.h"
+
+//==============================================================================
+/**
+ * Constructs a CPixel
+ */
+CPixel::CPixel()
+ : r(0)
+ , g(0)
+ , b(0)
+ , a(0)
+{
+}
+//==============================================================================
+/**
+ * Constructs a CPixel
+ */
+CPixel::CPixel(const unsigned char &inRed, const unsigned char &inGreen,
+ const unsigned char &inBlue, const unsigned char &inAlpha)
+ : r(inRed)
+ , g(inGreen)
+ , b(inBlue)
+ , a(inAlpha)
+{
+}
+
+//==============================================================================
+/**
+ * Destroys a CPixel
+ */
+CPixel::~CPixel()
+{
+}
+
+//==============================================================================
+/**
+ * Constructs a copy of the class.
+ */
+CPixel::CPixel(const CPixel &inPixel)
+ : r(inPixel.r)
+ , g(inPixel.g)
+ , b(inPixel.b)
+ , a(inPixel.a)
+{
+}
+
+//==============================================================================
+/**
+ * Handles the assigment of two CPixel's.
+ */
+CPixel &CPixel::operator=(const CPixel &inPixel)
+{
+ if (&inPixel != this) {
+ r = inPixel.r;
+ g = inPixel.g;
+ b = inPixel.b;
+ a = inPixel.a;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the RGBA components of the color.
+ *
+ * Each color component is a floating point value between 0.0f (not present/
+ * transparent) and 1.0f (full saturation/opaque).
+ *
+ * @param inRed The red component of the color.
+ * @param inGreen The green component of the color.
+ * @param inBlue The blue component of the color.
+ * @param inAlpha The alpha component of the color.
+ */
+void CPixel::Set(const unsigned char &inRed, const unsigned char &inGreen,
+ const unsigned char &inBlue, const unsigned char &inAlpha)
+{
+ r = inRed;
+ g = inGreen;
+ b = inBlue;
+ a = inAlpha;
+}
+
+//==============================================================================
+/**
+ * Gets the RGBA components of the color.
+ *
+ * Each color component is a floating point value between 0.0f (not present/
+ * transparent) and 1.0f (full saturation/opaque).
+ *
+ * @param outRed The red component of the color.
+ * @param outGreen The green component of the color.
+ * @param outBlue The blue component of the color.
+ * @param outAlpha The alpha component of the color.
+ */
+void CPixel::Get(unsigned char &outRed, unsigned char &outGreen, unsigned char &outBlue,
+ unsigned char &outAlpha)
+{
+ outRed = r;
+ outGreen = g;
+ outBlue = b;
+ outAlpha = a;
+} \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Types/Pixel.h b/src/Authoring/Client/Code/Core/Types/Pixel.h
new file mode 100644
index 00000000..81499f81
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Pixel.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __UICPIXEL_H_
+#define __UICPIXEL_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CPixel
+ * @brief A color class, giving you control over RGB and A.
+ */
+class CPixel
+{
+ //==============================================================================
+ // Field Members
+ //==============================================================================
+public:
+ unsigned char r; ///< Red component
+ unsigned char g; ///< Green componenct
+ unsigned char b; ///< Blue componenct
+ unsigned char a; ///< Alpha componenct
+
+ //==============================================================================
+ // Member Fucntions
+ //==============================================================================
+
+ // Construction
+public:
+ CPixel();
+ CPixel(const unsigned char &inRed, const unsigned char &inGreen, const unsigned char &inBlue,
+ const unsigned char &inAlpha);
+ CPixel(const CPixel &inPixel);
+ ~CPixel();
+
+ // Operators
+public:
+ CPixel &operator=(const CPixel &inPixel);
+
+ // Data access
+public:
+ void Set(const unsigned char &inRed, const unsigned char &inGreen, const unsigned char &inBlue,
+ const unsigned char &inAlpha);
+ void Get(unsigned char &outRed, unsigned char &outGreen, unsigned char &outBlue,
+ unsigned char &outAlpha);
+};
+
+#endif // __PIXEL_H_ \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Types/Plane.cpp b/src/Authoring/Client/Code/Core/Types/Plane.cpp
new file mode 100644
index 00000000..e54f2a3f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Plane.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "Plane.h"
+#include "Matrix.h"
+#include "BoundingBox.h"
+#include "Vector3.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// CONSTRUCTION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Construct a default plane. MF: Hmmm should the normal be zero?
+ */
+
+CPlane::CPlane()
+ : m_D(0)
+{
+}
+
+//==============================================================================
+/**
+ * Construct a given plane.
+ */
+
+CPlane::CPlane(const CVector3 &inNormal, const float &inDistance)
+ : m_Normal(inNormal)
+ , m_D(inDistance)
+{
+}
+
+//==============================================================================
+// OPERATORS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Normalize the representation of the plane
+ */
+void CPlane::Normalize()
+{
+ float theInvLength = 1.0f / m_Normal.Length();
+
+ m_Normal *= theInvLength;
+ m_D *= theInvLength;
+}
+
+//==============================================================================
+/**
+ * See if the given box is inside, outside or straddling this plane.
+ */
+CPlane::ERelation CPlane::CheckRelation(const CBoundingBox &inBox) const
+{
+ CVector3 theNearPoint(inBox.MaxPoint());
+ CVector3 theFarPoint(inBox.MinPoint());
+
+ // Find the corners that most likely to straddle this plane
+ // by finding the one furthest in the direction of the
+ // normals and the other in the furthest opposite direction.
+ if (m_Normal.x > 0) {
+ theNearPoint.x = inBox.MinPoint().x;
+ theFarPoint.x = inBox.MaxPoint().x;
+ }
+ if (m_Normal.y > 0) {
+ theNearPoint.y = inBox.MinPoint().y;
+ theFarPoint.y = inBox.MaxPoint().y;
+ }
+ if (m_Normal.z > 0) {
+ theNearPoint.z = inBox.MinPoint().z;
+ theFarPoint.z = inBox.MaxPoint().z;
+ }
+
+ // If the near point is in front then all points are in front...
+ if (m_Normal.DotProduct(theNearPoint) + m_D > 0)
+ return CPlane::RELATION_FRONT;
+
+ // If the near point is in back but the far point is in front, then the box clips...
+ if (m_Normal.DotProduct(theFarPoint) + m_D > 0)
+ return CPlane::RELATION_CLIPPED;
+
+ // Else, all points are behind.
+ return CPlane::RELATION_BACK;
+}
+
+}; // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Plane.h b/src/Authoring/Client/Code/Core/Types/Plane.h
new file mode 100644
index 00000000..73194f6a
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Plane.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Vector3.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CBoundingBox;
+
+//==============================================================================
+/**
+ * @class CPlane
+ * @brief Geometrical primitive - a boundless plane.
+ */
+class CPlane
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+public:
+ enum ERelation { RELATION_FRONT, RELATION_BACK, RELATION_CLIPPED };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ CVector3 m_Normal; ///< Normal vector of the plane
+ float m_D; ///< Distance to plane from 0,0,0
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CPlane();
+ CPlane(const CVector3 &inNormal, const float &inDistance);
+
+public: // Access
+ void Normalize();
+ ERelation CheckRelation(const CBoundingBox &inBox) const;
+};
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/ProductStack.h b/src/Authoring/Client/Code/Core/Types/ProductStack.h
new file mode 100644
index 00000000..efd59697
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/ProductStack.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __PRODUCTSTACK_H_
+#define __PRODUCTSTACK_H_
+
+template <class T>
+struct CProductStack : public std::stack<T>
+{
+ CProductStack(const T &inTop) { std::stack<T>::push(inTop); }
+ void push(const T &inValue) { std::stack<T>::push(inValue * std::stack<T>::top()); }
+};
+
+#endif //__PRODUCTSTACK_H_
diff --git a/src/Authoring/Client/Code/Core/Types/PropertyPublishLevels.h b/src/Authoring/Client/Code/Core/Types/PropertyPublishLevels.h
new file mode 100644
index 00000000..3b79f891
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/PropertyPublishLevels.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_PUBLISH_LEVELS_H
+#define INCLUDED_PROPERTY_PUBLISH_LEVELS_H 1
+
+#pragma once
+
+enum EPublishLevel {
+ PUBLISH_LEVEL_UNKNOWN = 0,
+ PUBLISH_LEVEL_HIDDEN, ///< Hidden Property
+ PUBLISH_LEVEL_BASIC, ///< Basic Property
+ PUBLISH_LEVEL_INTERMEDIATE, ///< Not used
+ PUBLISH_LEVEL_ADVANCED, ///< Advance Property
+ PUBLISH_LEVEL_SHARED, ///< Shared (Buffer-only) Property
+};
+
+#endif // INCLUDED_PROPERTY_PUBLISH_LEVELS_H \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Types/Rotation3.cpp b/src/Authoring/Client/Code/Core/Types/Rotation3.cpp
new file mode 100644
index 00000000..d9c9443e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Rotation3.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <math.h>
+#include "Rotation3.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* Constructs the CRotation object, setting its value to (x = 0.0f, y = 0.0f, z=0.0f).
+*/
+CRotation3::CRotation3()
+{
+ x = 0.0f;
+ y = 0.0f;
+ z = 0.0f;
+}
+
+//==============================================================================
+/**
+ * Constructs a copy of the CRotation3 object.
+ *
+ * @param inRotation The source for the copy operation.
+ */
+CRotation3::CRotation3(const CRotation3 &inRotation)
+{
+ x = inRotation.x;
+ y = inRotation.y;
+ z = inRotation.z;
+}
+
+//==============================================================================
+/**
+* Constructs the CVector3 object, setting its value to the X, Y, Z passed in.
+* Values are in Degrees.
+*/
+CRotation3::CRotation3(const float &inX, const float &inY, const float &inZ)
+{
+ SetAngles(inX, inY, inZ);
+}
+
+CRotation3::~CRotation3()
+{
+}
+
+bool CRotation3::operator==(const CRotation3 &inOther) const
+{
+ return CVector3::operator==(inOther);
+}
+
+bool CRotation3::operator==(const CVector3 &inOther) const
+{
+ return CVector3::operator==(inOther);
+}
+
+void CRotation3::SetXDegrees(const float &inX)
+{
+ x = (float)(inX * UIC3D_DEGREES_TO_RADIANS);
+}
+void CRotation3::SetYDegrees(const float &inY)
+{
+ y = (float)(inY * UIC3D_DEGREES_TO_RADIANS);
+}
+void CRotation3::SetZDegrees(const float &inZ)
+{
+ z = (float)(inZ * UIC3D_DEGREES_TO_RADIANS);
+}
+
+void CRotation3::SetXRadians(const float &inX)
+{
+ x = inX;
+}
+void CRotation3::SetYRadians(const float &inY)
+{
+ y = inY;
+}
+void CRotation3::SetZRadians(const float &inZ)
+{
+ z = inZ;
+}
+
+float CRotation3::GetXDegrees() const
+{
+ return (float)(x * UIC3D_RADIANS_TO_DEGREES);
+}
+float CRotation3::GetYDegrees() const
+{
+ return (float)(y * UIC3D_RADIANS_TO_DEGREES);
+}
+float CRotation3::GetZDegrees() const
+{
+ return (float)(z * UIC3D_RADIANS_TO_DEGREES);
+}
+
+float CRotation3::GetXRadians() const
+{
+ return x;
+}
+float CRotation3::GetYRadians() const
+{
+ return y;
+}
+float CRotation3::GetZRadians() const
+{
+ return z;
+}
+
+//==============================================================================
+/**
+ * Sets the rotation vector as angles in degrees, storing them to radians.
+ *
+ * @param inXRotation The x component of the vector in degrees.
+ * @param inYRotation The y component of the vector in degrees.
+ * @param inZRotation The z component of the vector in degrees.
+ */
+void CRotation3::Set(const float &inXRotation, const float &inYRotation, const float &inZRotation)
+{
+ return SetAngles(inXRotation, inYRotation, inZRotation);
+}
+
+//==============================================================================
+/**
+ * Gets the rotation vector as angles in degrees, converting them from radians.
+ *
+ * @param outXRotation The x component of the vector in degrees.
+ * @param outYRotation The y component of the vector in degrees.
+ * @param outZRotation The z component of the vector in degrees.
+ */
+void CRotation3::Get(float &outXRotation, float &outYRotation, float &outZRotation) const
+{
+ GetAngles(outXRotation, outYRotation, outZRotation);
+}
+
+//==============================================================================
+/**
+ * Sets the rotation vector as angles in degrees, storing them to radians.
+ *
+ * @param inXRotation The x component of the vector in degrees.
+ * @param inYRotation The y component of the vector in degrees.
+ * @param inZRotation The z component of the vector in degrees.
+ *
+ * @return HRESULT Always returns S_OK.
+ */
+void CRotation3::SetAngles(const float &inXRotation, const float &inYRotation,
+ const float &inZRotation)
+{
+ x = (float)(inXRotation * UIC3D_DEGREES_TO_RADIANS);
+ y = (float)(inYRotation * UIC3D_DEGREES_TO_RADIANS);
+ z = (float)(inZRotation * UIC3D_DEGREES_TO_RADIANS);
+}
+
+//==============================================================================
+/**
+ * Gets the rotation vector as angles in degrees, converting them from radians.
+ *
+ * @param outXRotation The x component of the vector in degrees.
+ * @param outYRotation The y component of the vector in degrees.
+ * @param outZRotation The z component of the vector in degrees.
+ *
+ * @return HRESULT Always returns S_OK.
+ */
+void CRotation3::GetAngles(float &outXRotation, float &outYRotation, float &outZRotation) const
+{
+ outXRotation = (float)(x * UIC3D_RADIANS_TO_DEGREES);
+ outYRotation = (float)(y * UIC3D_RADIANS_TO_DEGREES);
+ outZRotation = (float)(z * UIC3D_RADIANS_TO_DEGREES);
+}
+
+//==============================================================================
+/**
+ * Sets the rotation vector as angles in radians, storing them to radians.
+ *
+ * @param inXRotation The x component of the vector in radians.
+ * @param inYRotation The y component of the vector in radians.
+ * @param inZRotation The z component of the vector in radians.
+ *
+ * @return HRESULT Always returns S_OK.
+ */
+void CRotation3::SetRadians(const float &inXRotation, const float &inYRotation,
+ const float &inZRotation)
+{
+ x = inXRotation;
+ y = inYRotation;
+ z = inZRotation;
+}
+
+//==============================================================================
+/**
+ * Gets the rotation vector as angles in radians, from storage as radians.
+ *
+ * @param outXRotation The x component of the vector in radians.
+ * @param outYRotation The y component of the vector in radians.
+ * @param outZRotation The z component of the vector in radians.
+ *
+ * @return HRESULT Always returns S_OK.
+ */
+void CRotation3::GetRadians(float &outXRotation, float &outYRotation, float &outZRotation) const
+{
+ outXRotation = x;
+ outYRotation = y;
+ outZRotation = z;
+}
+
+//==============================================================================
+/**
+ * Equals operator for the CVector3 object.
+ *
+ * @return The new rotation vector after assignment.
+ */
+CVector3 &CRotation3::operator=(const CVector3 &inRotation)
+{
+ if (&inRotation != this) {
+ x = inRotation.x;
+ y = inRotation.y;
+ z = inRotation.z;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the rotation to "look at" the specifed vector.
+ */
+void CRotation3::LookAt(const CVector3 &inVector)
+{
+ /*
+ A function lookAt that takes a vector and does not return anything, it just
+ modifies the object. This code is setting the values as degrees, but if you
+ need radians then just use thePitch and theYaw.
+ */
+
+ double theMag = sqrt(inVector.x * inVector.x + inVector.z * inVector.z);
+ double thePitch = -(atan2(static_cast<double>(inVector.y), theMag));
+ double theYaw = atan2(inVector.x, inVector.z);
+
+ x = (float)thePitch;
+ y = (float)theYaw;
+ z = 0;
+
+ // x = ( thePitch / ( PI ) ) * 180;
+ // y = ( theYaw / ( 2 * PI ) ) * 360;
+ // z = 0;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Rotation3.h b/src/Authoring/Client/Code/Core/Types/Rotation3.h
new file mode 100644
index 00000000..cfbe8f57
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Rotation3.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __ROTATION3_H_
+#define __ROTATION3_H_
+
+#include "Vector3.h"
+#include "UICObjectCounter.h"
+
+namespace Q3DStudio {
+
+#ifndef __CommonConstants_H__
+const double UIC3D_DEGREES_TO_RADIANS = (6.2831856f / 360.0f);
+const double UIC3D_RADIANS_TO_DEGREES = (360.0f / 6.2831856f);
+#endif
+
+class CRotation3 : public CVector3
+{
+
+ // Construction
+public:
+ CRotation3();
+ CRotation3(const CRotation3 &inRotation);
+ CRotation3(const float &inX, const float &inY, const float &inZ);
+ virtual ~CRotation3();
+
+ // Access
+public:
+ virtual bool operator==(const CRotation3 &inOther) const;
+ virtual bool operator==(const CVector3 &inOther) const;
+ virtual void SetXDegrees(const float &inX);
+ virtual void SetYDegrees(const float &inY);
+ virtual void SetZDegrees(const float &inZ);
+
+ virtual void SetXRadians(const float &inX);
+ virtual void SetYRadians(const float &inY);
+ virtual void SetZRadians(const float &inZ);
+
+ virtual float GetXDegrees() const;
+ virtual float GetYDegrees() const;
+ virtual float GetZDegrees() const;
+
+ virtual float GetXRadians() const;
+ virtual float GetYRadians() const;
+ virtual float GetZRadians() const;
+
+ virtual void Get(float &outXRotation, float &outYRotation, float &outZRotation) const;
+ virtual void Set(const float &inXRotation, const float &inYRotation, const float &inZRotation);
+ virtual void GetAngles(float &outXRotation, float &outYRotation, float &outZRotation) const;
+ virtual void SetAngles(const float &inXRotation, const float &inYRotation,
+ const float &inZRotation);
+ virtual void GetRadians(float &outXRotation, float &outYRotation, float &outZRotation) const;
+ virtual void SetRadians(const float &inXRotation, const float &inYRotation,
+ const float &inZRotation);
+
+ virtual void LookAt(const CVector3 &inVector);
+
+ // Operators
+public:
+ virtual CVector3 &operator=(const CVector3 &inRotation);
+};
+
+} // namespace Q3DStudio
+
+#endif //__ROTATION3_H_
diff --git a/src/Authoring/Client/Code/Core/Types/TypesErrorIDs.h b/src/Authoring/Client/Code/Core/Types/TypesErrorIDs.h
new file mode 100644
index 00000000..af3b6ce3
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/TypesErrorIDs.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __TYPESERRORIDS_H__
+#define __TYPESERRORIDS_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ClientErrorIDs.h"
+
+//==============================================================================
+// HRESULTS
+//==============================================================================
+#define TYPES_ERROR(inID, inName) \
+ const HRESULT inName = MAKE_HRESULT(LEVEL_ERROR, FACILITY_ITF, TYPES_START_ERROR_RANGE + inID);
+
+TYPES_ERROR(0, TYPES_E_FAIL)
+TYPES_ERROR(1, TYPES_E_COLOR_FAIL)
+TYPES_ERROR(2, TYPES_E_MATRIX_FAIL)
+TYPES_ERROR(3, TYPES_E_PLANE_FAIL)
+TYPES_ERROR(4, TYPES_E_QUATERNION_FAIL)
+TYPES_ERROR(5, TYPES_E_ROTATION3_FAIL)
+TYPES_ERROR(6, TYPES_E_VECTOR2_FAIL)
+TYPES_ERROR(7, TYPES_E_VECTOR3_FAIL)
+TYPES_ERROR(8, TYPES_E_VECTOR4_FAIL)
+TYPES_ERROR(9, TYPES_E_TRAVERSALSTACK_FAIL)
+
+#endif // #ifndef __TYPESERRORIDS_H__ \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Types/UICColor.cpp b/src/Authoring/Client/Code/Core/Types/UICColor.cpp
new file mode 100644
index 00000000..2968f80c
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/UICColor.cpp
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICColor.h"
+#include <stdio.h>
+#include "ColorConversion.h"
+
+#define CLAMP_COLOR(x, y, z) \
+ if (x > y) \
+ x = y; \
+ if (x < z) \
+ x = z;
+
+namespace Q3DStudio {
+
+IMPLEMENT_OBJECT_COUNTER(CColor)
+
+//==============================================================================
+/**
+ * Constructs a CColor
+ */
+CColor::CColor()
+ : COLORNORMALIZER(255.0f)
+ , r(0.0f)
+ , g(0.0f)
+ , b(0.0f)
+ , a(1.0f)
+{
+ ADDTO_OBJECT_COUNTER(CColor)
+}
+
+//==============================================================================
+/**
+ * Constructs a CColor
+ */
+CColor::CColor(float inRed, float inGreen, float inBlue, float inAlpha)
+ : COLORNORMALIZER(255.0f)
+ , r(inRed)
+ , g(inGreen)
+ , b(inBlue)
+ , a(inAlpha)
+{
+ ADDTO_OBJECT_COUNTER(CColor)
+}
+
+//==============================================================================
+/**
+ * Constructs a copy of the class.
+ */
+CColor::CColor(const CColor &inColor)
+ : COLORNORMALIZER(255.0f)
+ , r(inColor.r)
+ , g(inColor.g)
+ , b(inColor.b)
+ , a(inColor.a)
+{
+ ADDTO_OBJECT_COUNTER(CColor)
+}
+
+//==============================================================================
+/**
+ * Constructs based on a long that represent the color in RGB
+ */
+CColor::CColor(long inColorLong)
+ : COLORNORMALIZER(255.0f)
+ , a(1.0f)
+{
+ ADDTO_OBJECT_COUNTER(CColor)
+ SetRGB(inColorLong);
+}
+
+//==============================================================================
+/**
+ * Destroys a CColor
+ */
+CColor::~CColor()
+{
+ REMOVEFROM_OBJECT_COUNTER(CColor)
+}
+
+//==============================================================================
+/**
+ * Handles the assigment of two CColor's.
+ */
+CColor &CColor::operator=(const CColor &inColor)
+{
+ if (&inColor != this) {
+ r = inColor.r;
+ g = inColor.g;
+ b = inColor.b;
+ a = inColor.a;
+ }
+
+ return *this;
+}
+
+void CColor::SetR(float inR)
+{
+ r = inR;
+}
+void CColor::SetG(float inG)
+{
+ g = inG;
+}
+void CColor::SetB(float inB)
+{
+ b = inB;
+}
+void CColor::SetA(float inA)
+{
+ a = inA;
+}
+
+float CColor::GetR() const
+{
+ return r;
+}
+float CColor::GetG() const
+{
+ return g;
+}
+float CColor::GetB() const
+{
+ return b;
+}
+float CColor::GetA() const
+{
+ return a;
+}
+
+void CColor::SetR255(long inR)
+{
+ r = inR / COLORNORMALIZER;
+ CLAMP_COLOR(r, COLORNORMALIZER, 0);
+}
+
+void CColor::SetG255(long inG)
+{
+ g = inG / COLORNORMALIZER;
+ CLAMP_COLOR(g, COLORNORMALIZER, 0);
+}
+
+void CColor::SetB255(long inB)
+{
+ b = inB / COLORNORMALIZER;
+ CLAMP_COLOR(b, COLORNORMALIZER, 0);
+}
+
+void CColor::SetA255(long inA)
+{
+ a = inA / COLORNORMALIZER;
+ CLAMP_COLOR(a, COLORNORMALIZER, 0);
+}
+
+long CColor::GetR255() const
+{
+ // Add .5 to combat the rounding off issue
+ long temp = (long)((r * COLORNORMALIZER) + .5);
+ CLAMP_COLOR(temp, (long)COLORNORMALIZER, 0);
+ return temp;
+}
+
+long CColor::GetG255() const
+{
+ // Add .5 to combat the rounding off issue
+ long temp = (long)((g * COLORNORMALIZER) + .5);
+ CLAMP_COLOR(temp, (long)COLORNORMALIZER, 0);
+ return temp;
+}
+
+long CColor::GetB255() const
+{
+ // Add .5 to combat the rounding off issue
+ long temp = (long)((b * COLORNORMALIZER) + .5);
+ CLAMP_COLOR(temp, (long)COLORNORMALIZER, 0);
+ return temp;
+}
+
+long CColor::GetA255() const
+{
+ // Add .5 to combat the rounding off issue
+ long temp = (long)((a * COLORNORMALIZER) + .5);
+ CLAMP_COLOR(temp, (long)COLORNORMALIZER, 0);
+ return temp;
+}
+
+//==============================================================================
+/**
+ * Sets the RGBA components of the color.
+ *
+ * Each color component is a floating point value between 0.0f (not present/
+ * transparent) and 1.0f (full saturation/opaque).
+ *
+ * @param inRed The red component of the color.
+ * @param inGreen The green component of the color.
+ * @param inBlue The blue component of the color.
+ * @param inAlpha The alpha component of the color.
+ */
+void CColor::Set(float inRed, float inGreen, float inBlue, float inAlpha)
+{
+ r = inRed;
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g = inGreen;
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b = inBlue;
+ CLAMP_COLOR(b, 1.f, 0.f);
+
+ a = inAlpha;
+ CLAMP_COLOR(a, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Sets the RGBA components of the color.
+ *
+ * Each color component is a floating point value between 0.0f (not present/
+ * transparent) and 1.0f (full saturation/opaque).
+ *
+ * @param inRed The red component of the color.
+ * @param inGreen The green component of the color.
+ * @param inBlue The blue component of the color.
+ * @param inAlpha The alpha component of the color.
+ */
+void CColor::Set255(long inRed, long inGreen, long inBlue, long inAlpha)
+{
+ SetR255(inRed);
+ SetG255(inGreen);
+ SetB255(inBlue);
+ SetA255(inAlpha);
+}
+
+//==============================================================================
+/**
+ * Gets the RGBA components of the color.
+ *
+ * @param outRed The red component of the color.
+ * @param outGreen The green component of the color.
+ * @param outBlue The blue component of the color.
+ * @param outAlpha The alpha component of the color.
+ */
+void CColor::Get255(long &outRed, long &outGreen, long &outBlue, long &outAlpha)
+{
+ outRed = GetR255();
+ outGreen = GetG255();
+ outBlue = GetB255();
+ outAlpha = GetA255();
+}
+
+//==============================================================================
+/**
+ * Gets the RGBA components of the color.
+ *
+ * Each color component is a floating point value between 0.0f (not present/
+ * transparent) and 1.0f (full saturation/opaque).
+ *
+ * @param outRed The red component of the color.
+ * @param outGreen The green component of the color.
+ * @param outBlue The blue component of the color.
+ * @param outAlpha The alpha component of the color.
+ */
+void CColor::Get(float &outRed, float &outGreen, float &outBlue, float &outAlpha)
+{
+ outRed = r;
+ outGreen = g;
+ outBlue = b;
+ outAlpha = a;
+}
+
+//==============================================================================
+/**
+ * Sets the color value formatted as a D3DRGB type.
+ *
+ * @param inRGB A long composed of RGB values.
+ */
+void CColor::SetRGB(long inRGB)
+{
+ r = static_cast<float>(CColorConversion::GetRed(inRGB)) / COLORNORMALIZER;
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g = static_cast<float>(CColorConversion::GetGreen(inRGB)) / COLORNORMALIZER;
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b = static_cast<float>(CColorConversion::GetBlue(inRGB)) / COLORNORMALIZER;
+ CLAMP_COLOR(b, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * GetRGB: Returns the color value formatted as a D3DRGB type.
+ *
+ * @param inRGB A long composed of RGB values.
+ */
+void CColor::GetRGB(long &outRGB)
+{
+ outRGB = CColorConversion::MakeRGBA(r, g, b, a);
+}
+
+//==============================================================================
+/**
+ * SetRGB: Set the color from short char between 0 and 255
+ */
+void CColor::SetRGB(unsigned char inRed, unsigned char inGreen, unsigned char inBlue,
+ unsigned char inAlpha)
+{
+ r = inRed / COLORNORMALIZER;
+ g = inGreen / COLORNORMALIZER;
+ b = inBlue / COLORNORMALIZER;
+ a = inAlpha / COLORNORMALIZER;
+}
+
+//==============================================================================
+/**
+ * GetRGB: Returns the color as char values between 0 and 255.
+ */
+void CColor::GetRGB(unsigned char &outRed, unsigned char &outGreen, unsigned char &outBlue,
+ unsigned char &outAlpha)
+{
+ outRed = static_cast<unsigned char>(r * COLORNORMALIZER);
+ outGreen = static_cast<unsigned char>(g * COLORNORMALIZER);
+ outBlue = static_cast<unsigned char>(b * COLORNORMALIZER);
+ outAlpha = static_cast<unsigned char>(a * COLORNORMALIZER);
+}
+
+//==============================================================================
+/**
+ * Changes the color value to be its negative.
+ *
+ * Each color component is a modified by subtracting 1.0f from its value
+ * thus producing the color negative.
+ */
+void CColor::Invert()
+{
+ r = static_cast<float>(1.0f - r);
+ g = static_cast<float>(1.0f - g);
+ b = static_cast<float>(1.0f - b);
+ a = static_cast<float>(1.0f - a);
+}
+
+//==============================================================================
+/**
+ * Scales the color value by the specifed factor.
+ *
+ * Each color component is a multiplied by the given factor thus producing
+ * a scaled version of the original color. If the scale factor is 1.0f, then
+ * the result is the original color.
+ *
+ * @param inScaleFactor The scale factor by which each color component is
+ * multiplied. If the value is 1.0f, the color will not be changed.
+ *
+ * @return HRESULT Always returns S_OK.
+ */
+void CColor::Scale(float inScaleFactor)
+{
+ r *= inScaleFactor;
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g *= inScaleFactor;
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b *= inScaleFactor;
+ CLAMP_COLOR(b, 1.f, 0.f);
+
+ a *= inScaleFactor;
+ CLAMP_COLOR(a, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Changes the contrast of the color value.
+ *
+ * The RGB components of the color are modified by linearly interpolating
+ * the component between 50% gray and its current value using the following
+ * formula:
+ *
+ * new = 0.5f + inContrast * (current - 0.5f)
+ *
+ * Where 'inContrast' is the weighting factor of the interpolation. If
+ * 'inContrast' is 0.0f, then the color becomes 50% gray. If it is 1.0f,
+ * then the new color is the same as the original. If it is greater than
+ * 1.0f, then the contrast is increased.
+ *
+ * @param inContrast The weighing factor for altering the color's contrast.
+ */
+void CColor::AdjustContrast(float inContrast)
+{
+ r = static_cast<float>(0.5f + inContrast * (r - 0.5f));
+ g = static_cast<float>(0.5f + inContrast * (g - 0.5f));
+ b = static_cast<float>(0.5f + inContrast * (b - 0.5f));
+}
+
+//==============================================================================
+/**
+ * AdjustSaturation: Changes the saturation of the color value.
+ *
+ * The RGB components of the color are modified by linearly interpolating
+ * the component between an unsaturated value and its current value using
+ * the following formula:
+ *
+ * Approximate values for each component's contribution to luminance.<BR>
+ * Based upon the NTSC standard described in ITU-R Recommendation BT.709.<BR>
+ * grey = current.red * 0.2125f + current.green * 0.7154f + current.blue * 0.0721f
+ * new = grey + inSaturation * (current - grey)
+ *
+ * Where 'inSaturation' is the weighting factor of the interpolation. If
+ * 'inSaturation' is 0.0f, then the color becomes grayscale. If it is 1.0f,
+ * then the new color is the same as the original. If it is greater than 1.0f,
+ * then the saturation is increased.
+ *
+ * @param inSaturation The weighting factor for altering the color's saturation.
+ */
+void CColor::AdjustSaturation(float inSaturation)
+{
+ float theGrey = static_cast<float>(r * 0.2125f + g * 0.7154f + b * 0.0721f);
+
+ r = theGrey + inSaturation * (r - theGrey);
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g = theGrey + inSaturation * (g - theGrey);
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b = theGrey + inSaturation * (b - theGrey);
+ CLAMP_COLOR(b, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Adds the specified color to the current color.
+ *
+ * The RGBA components of 'inColor' are added to the components of the
+ * current color.
+ *
+ * @param inColor The color to add to the current color.
+ */
+void CColor::Add(const CColor &inColor)
+{
+ r += inColor.r;
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g += inColor.g;
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b += inColor.b;
+ CLAMP_COLOR(b, 1.f, 0.f);
+
+ a += inColor.a;
+ CLAMP_COLOR(a, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Subtracts the specified color from the current color.
+ *
+ * The RGBA components of 'inColor' are subtracted from the components of the
+ * current color.
+ *
+ * @param inColor The color to subtract from the current color.
+ */
+void CColor::Subtract(const CColor &inColor)
+{
+ r -= inColor.r;
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g -= inColor.g;
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b -= inColor.b;
+ CLAMP_COLOR(b, 1.f, 0.f);
+
+ a -= inColor.a;
+ CLAMP_COLOR(a, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Blends the specified color into the current color.
+ *
+ * The RGBA components of 'inColor' are blended into the components of the
+ * current color by multiplying each component together.
+ *
+ * @param inColor The color to blend into the current color.
+ */
+void CColor::Blend(const CColor &inColor)
+{
+ r *= inColor.r;
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g *= inColor.g;
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b *= inColor.b;
+ CLAMP_COLOR(b, 1.f, 0.f);
+
+ a *= inColor.a;
+ CLAMP_COLOR(a, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Performs a linear interpolation between the current
+ * color and the specified color, treating both as 4-D vectors.
+ *
+ * The current color acts as the source of the interpolation and 'inColor'
+ * acts as the target. The interpolation of each component uses the following
+ * formula:
+ *
+ * new = current + inWeight * (inColor - current)
+ *
+ * Where 'inWeight' is the weighting factor for the interpolation. If 'inWeight'
+ * is 0.0f, then the color remains the current color. If it is 1.0f, then the
+ * new color is the same as 'inColor'.
+ *
+ * @param inColor The target color of the interpolation.
+ * @param inWeight The weighting factor for the interpolation.
+ */
+void CColor::InterploateLinear(const CColor &inColor, float inWeight)
+{
+ r = inColor.r + inWeight * (r - inColor.r);
+ CLAMP_COLOR(r, 1.f, 0.f);
+
+ g = inColor.g + inWeight * (g - inColor.g);
+ CLAMP_COLOR(g, 1.f, 0.f);
+
+ b = inColor.b + inWeight * (b - inColor.b);
+ CLAMP_COLOR(b, 1.f, 0.f);
+
+ a = inColor.a + inWeight * (a - inColor.a);
+ CLAMP_COLOR(a, 1.f, 0.f);
+}
+
+//==============================================================================
+/**
+ * Transforms the current Color into a string
+ *
+ * This method takes the current values of the Color and returns them
+ * in a string in the format R G B A
+ */
+Q3DStudio::CString CColor::toString()
+{
+ Q3DStudio::CString theStringBuffer;
+ unsigned char theRed;
+ unsigned char theGreen;
+ unsigned char theBlue;
+ unsigned char theAlpha;
+
+ GetRGB(theRed, theGreen, theBlue, theAlpha);
+ theStringBuffer.Format(_UIC("%.3hd %.3hd %.3hd %.3hd"), theRed, theGreen, theBlue, theAlpha);
+
+ return theStringBuffer;
+}
+
+bool CColor::operator==(const CColor &inOther) const
+{
+ return r == inOther.r && g == inOther.g && b == inOther.b && a == inOther.a;
+}
+
+//==============================================================================
+/**
+ * Takes the values of the string and sets the Color to those values.
+ *
+ * This method takes the values of the string and stores them in this
+ * Color. The string must be in the format of R G B A
+ */
+void CColor::fromString(const Q3DStudio::CString &inStringValue)
+{
+ short theRed;
+ short theGreen;
+ short theBlue;
+ short theAlpha;
+
+ ::sscanf(inStringValue.GetCharStar(), "%hd %hd %hd %hd", &theRed, &theGreen, &theBlue,
+ &theAlpha);
+ SetRGB(static_cast<unsigned char>(theRed), static_cast<unsigned char>(theGreen),
+ static_cast<unsigned char>(theBlue), static_cast<unsigned char>(theAlpha));
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/UICColor.h b/src/Authoring/Client/Code/Core/Types/UICColor.h
new file mode 100644
index 00000000..7759d857
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/UICColor.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __CCOLOR_H_
+#define __CCOLOR_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+#include "UICObjectCounter.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CColor
+ * @brief A color class, giving you control over RGB and A.
+ */
+class CColor
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+
+protected:
+ const float COLORNORMALIZER;
+
+ //==============================================================================
+ // Field Members
+ //==============================================================================
+public:
+ float r; ///< Red component of color
+ float g; ///< Green componenct of color
+ float b; ///< Blue componenct of color
+ float a; ///< Alpha componenct of color
+
+ DEFINE_OBJECT_COUNTER(CColor)
+
+ //==============================================================================
+ // Member Fucntions
+ //==============================================================================
+
+ // Construction
+public:
+ CColor();
+ CColor(float inRed, float inGreen, float inBlue, float inAlpha = 1.0f);
+ CColor(const CColor &inColor);
+ CColor(long inColorLong);
+ ~CColor();
+
+ // Operators
+public:
+ CColor &operator=(const CColor &inColor);
+
+ // Data access
+public:
+ // Values between 1,0
+ void SetR(float inR);
+ void SetG(float inG);
+ void SetB(float inB);
+ void SetA(float inA);
+
+ float GetR() const;
+ float GetG() const;
+ float GetB() const;
+ float GetA() const;
+
+ // Values between 255, 0
+ void SetR255(long inR);
+ void SetG255(long inG);
+ void SetB255(long inB);
+ void SetA255(long inA);
+
+ long GetR255() const;
+ long GetG255() const;
+ long GetB255() const;
+ long GetA255() const;
+
+ void Set(float inRed, float inGreen, float inBlue, float inAlpha = 1.0f);
+ void Set255(long inRed, long inGreen, long inBlue, long inAlpha = 255.0f);
+ void Get255(long &outRed, long &outGreen, long &outBlue, long &outAlpha);
+ void Get(float &outRed, float &outGreen, float &outBlue, float &outAlpha);
+ void SetRGB(long inRGB);
+ void GetRGB(long &outRGB);
+ void SetRGB(unsigned char inRed, unsigned char inGreen, unsigned char inBlue,
+ unsigned char inAlpha = 255);
+ void GetRGB(unsigned char &outRed, unsigned char &outGreen, unsigned char &outBlue,
+ unsigned char &outAlpha);
+ void ToFloat(float *outColor)
+ {
+ outColor[0] = r;
+ outColor[1] = g;
+ outColor[2] = b;
+ outColor[3] = a;
+ }
+
+ Q3DStudio::CString toString();
+ void fromString(const Q3DStudio::CString &inStringValue);
+
+ // Operations
+public:
+ void InterploateLinear(const CColor &inColor, float inWeight);
+ void Blend(const CColor &inColor);
+ void Subtract(const CColor &inColor);
+ void Add(const CColor &inColor);
+ void AdjustSaturation(float inSaturation);
+ void AdjustContrast(float inContrast);
+ void Scale(float inScaleFactor);
+ void Invert();
+ bool operator==(const CColor &inOther) const;
+};
+
+} // namespace Q3DStudio
+
+#endif // __CCOLOR_H_
diff --git a/src/Authoring/Client/Code/Core/Types/Vector2.cpp b/src/Authoring/Client/Code/Core/Types/Vector2.cpp
new file mode 100644
index 00000000..9534ef65
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Vector2.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "Vector2.h"
+#include <math.h>
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* Constructs the CVector2 object, setting its value to (x = 0.0f, y = 0.0f).
+*/
+CVector2::CVector2()
+ : x(0.0)
+ , y(0.0)
+{
+}
+
+//==============================================================================
+/**
+* Constructs the CVector2 object, setting its value to the X and Y passed in.
+*/
+CVector2::CVector2(float inX, float inY)
+ : x(inX)
+ , y(inY)
+{
+}
+
+//==============================================================================
+/**
+* Constructs a copy of the CVector2 object.
+*
+* @param inVector The source for the copy operation.
+*/
+CVector2::CVector2(const CVector2 &inVector)
+{
+ x = inVector.x;
+ y = inVector.y;
+}
+
+//==============================================================================
+/**
+ * Sets the x,y for the current vector given a vector.
+ *
+ * @param inVector The source vector
+ */
+void CVector2::Set(const CVector2 &inVector)
+{
+ x = inVector.x;
+ y = inVector.y;
+}
+
+//==============================================================================
+/**
+ * Gets the x and y components for the current vector.
+ *
+ * @param outX The x component of the vector.
+ * @param outY The y component of the vector.
+ */
+void CVector2::Get(float &outX, float &outY) const
+{
+ outX = x;
+ outY = y;
+}
+
+//==============================================================================
+/**
+ * Sets the x and y components for the current vector.
+ *
+ * @param inX The x component of the vector.
+ * @param inY The y component of the vector.
+ */
+void CVector2::Set(float inX, float inY)
+{
+ x = inX;
+ y = inY;
+}
+
+//==============================================================================
+/**
+ * Equals operator for the Vector2 object.
+ *
+ * @return The new vector after assignment.
+ */
+CVector2 &CVector2::operator=(const CVector2 &inVector)
+{
+ if (&inVector != this) {
+ x = inVector.x;
+ y = inVector.y;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Tests to see if two vectors are equal.
+ *
+ * @return true if vectors are equal, otherwise false.
+ */
+bool CVector2::operator==(const CVector2 &inVector) const
+{
+ return (x == inVector.x && y == inVector.y);
+}
+
+//==============================================================================
+/**
+ * Tests to see if two vectors are NOT equal.
+ *
+ * @return true if vectors are NOT equal, otherwise false.
+ */
+bool CVector2::operator!=(const CVector2 &inVector) const
+{
+ return (x != inVector.x || y != inVector.y);
+}
+
+//==============================================================================
+/**
+ * Computes the sum of two vectors.
+ *
+ * @param inVector2 The vector to be added to the current vector.
+ *
+ * @return The sum vector.
+ */
+CVector2 CVector2::operator+(const CVector2 &inVector) const
+{
+ CVector2 theSum;
+
+ theSum.x = x + inVector.x;
+ theSum.y = y + inVector.y;
+
+ return theSum;
+}
+
+//==============================================================================
+/**
+ * Subtracts the given vector from the current vector.
+ *
+ * @param inVector2 The vector to be subtracted from the current vector.
+ *
+ * @return The difference vector.
+ */
+CVector2 CVector2::operator-(const CVector2 &inVector) const
+{
+ CVector2 theDiff;
+
+ theDiff.x = x - inVector.x;
+ theDiff.y = y - inVector.y;
+
+ return theDiff;
+}
+
+//==============================================================================
+/**
+ * Multiplies by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ *
+ * @return The scaled vector.
+ */
+CVector2 CVector2::operator*(float inScalar) const
+{
+ CVector2 theProduct;
+
+ theProduct.x = inScalar * x;
+ theProduct.y = inScalar * y;
+
+ return theProduct;
+}
+
+//==============================================================================
+/**
+ * Divides by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ *
+ * @return The scaled vector.
+ */
+CVector2 CVector2::operator/(float inScalar) const
+{
+ CVector2 theDivide;
+ float theInverse = static_cast<float>(1.0 / inScalar);
+
+ theDivide.x = theInverse * x;
+ theDivide.y = theInverse * y;
+
+ return theDivide;
+}
+
+//==============================================================================
+/**
+ * Adds the current vector to this vector.
+ *
+ * @param inVector2 The vector to be added to the current vector.
+ *
+ * @return The sum vector.
+ */
+CVector2 CVector2::operator+=(const CVector2 &inVector)
+{
+ x += inVector.x;
+ y += inVector.y;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Subtracts the current vector from the this vector.
+ *
+ * @param inVector2 The vector to be subtracted from the current vector.
+ *
+ * @return The difference vector.
+ */
+CVector2 CVector2::operator-=(const CVector2 &inVector)
+{
+ x -= inVector.x;
+ y -= inVector.y;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Multiplies this vector by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ *
+ * @return The scaled vector.
+ */
+CVector2 CVector2::operator*=(float inScalar)
+{
+ x *= inScalar;
+ y *= inScalar;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Divides this vector by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ *
+ * @return The scaled vector.
+ */
+CVector2 CVector2::operator/=(float inScalar)
+{
+ float theInverse = static_cast<float>(1.0 / inScalar);
+
+ x *= theInverse;
+ y *= theInverse;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Calculates the length (magnitude) of the current vector.
+ *
+ * @param outLength The magnitude of the vector
+ *
+ * @return The length of the vector.
+ */
+float CVector2::Length()
+{
+ return static_cast<float>(::sqrt(static_cast<double>(x * x + y * y)));
+}
+
+//==============================================================================
+/**
+ * Calculates the squared length (squared magnitude) of the current vector.
+ *
+ * @param outLengthSquared The squared magnitude of the vector
+ */
+float CVector2::LengthSquared()
+{
+ return x * x + y * y;
+}
+
+//==============================================================================
+/**
+ * Normalizes the current vector making it a unit vector.
+ *
+ * The normalized vector is defined to be:
+ *
+ * V norm = V / Magnitude(V)
+ */
+void CVector2::Normalize()
+{
+ float theVectorLength = Length();
+
+ // TODO change this to epsilon or something.
+ if (theVectorLength > 1e-06) {
+ float theInvLength = static_cast<float>(1.0 / theVectorLength);
+ x *= theInvLength;
+ y *= theInvLength;
+ }
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the minimum between
+ * the given vector and this vector.
+ *
+ * @param inVector The vector that whose elements are tested against the
+ * current vector to build the minimum.
+ */
+void CVector2::Minimize(const CVector2 &inVector)
+{
+ if (inVector.x < x) {
+ x = inVector.x;
+ }
+ if (inVector.y < y) {
+ y = inVector.y;
+ }
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the maximum between
+ * the given vector and this vector.
+ *
+ * @param inVector The vector that whose elements are tested against the
+ * current vector to build the maximum.
+ */
+void CVector2::Maximize(const CVector2 &inVector)
+{
+ if (inVector.x > x) {
+ x = inVector.x;
+ }
+ if (inVector.y > y) {
+ y = inVector.y;
+ }
+}
+
+//==============================================================================
+/**
+ * Calculates the dot product of the this vector and the vector supplied as
+ * an argument.
+ *
+ * @param inVector2 The vector that is used to calculate the dot product with
+ * the current vector.
+ *
+ * @return The result of the calculation.
+ */
+float CVector2::DotProduct(const CVector2 &inVector)
+{
+ return x * inVector.x + y * inVector.y;
+}
+
+//==============================================================================
+/**
+ * Transforms the current vector into a string
+ *
+ * This method takes the current values of the Vector and returns them
+ * in a string in the format X Y Z
+ */
+Q3DStudio::CString CVector2::toString()
+{
+ Q3DStudio::CString theStringBuffer;
+ theStringBuffer.Format(_UIC("%.6f %.6f"), x, y);
+ return theStringBuffer;
+}
+
+//==============================================================================
+/**
+ * Takes the values of the string and sets the vector to those values.
+ *
+ * This method takes the values of the string and stores them in this
+ * vector. The string must be in the format of X Y Z
+ */
+void CVector2::fromString(const Q3DStudio::CString &inStringValue)
+{
+ ::sscanf(inStringValue.GetCharStar(), "%f %f", &x, &y);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Vector2.h b/src/Authoring/Client/Code/Core/Types/Vector2.h
new file mode 100644
index 00000000..4c592579
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Vector2.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __VECTOR2_H_
+#define __VECTOR2_H_
+
+#include "UICString.h"
+
+namespace Q3DStudio {
+// TODO Remove these soon.
+typedef long IMatrix;
+typedef long IVector4;
+
+class CVector2
+{
+ // Field members are public for obvious speed reasons. Using an unnamed union, which allows
+ // two names for one variable.
+public:
+ float x; ///< X portion of vector
+ float y; ///< Y portion of vector
+
+ // Construction
+public:
+ CVector2();
+ CVector2(float inX, float inY);
+ CVector2(const CVector2 &inVector);
+ ~CVector2() {}
+
+ // Access
+public:
+ void Set(const CVector2 &inVector);
+ void Get(float &outX, float &outY) const;
+ void Set(float inX, float inY);
+ float GetX() const { return x; }
+ float GetY() const { return y; }
+ void SetX(float inX) { x = inX; }
+ void SetY(float inY) { y = inY; }
+
+ // Operators
+public:
+ CVector2 &operator=(const CVector2 &inVector);
+ bool operator==(const CVector2 &inVector) const;
+ bool operator!=(const CVector2 &inVector) const;
+ CVector2 operator+(const CVector2 &inVector) const;
+ CVector2 operator-(const CVector2 &inVector) const;
+ CVector2 operator*(float inScalar) const;
+ CVector2 operator/(float inScalar) const;
+ CVector2 operator+=(const CVector2 &inVector);
+ CVector2 operator-=(const CVector2 &inVector);
+ CVector2 operator*=(float inScalar);
+ CVector2 operator/=(float inScalar);
+
+ // Functions
+public:
+ void Normalize();
+ void Minimize(const CVector2 &inVector);
+ void Maximize(const CVector2 &inVector);
+ float DotProduct(const CVector2 &inVector);
+ float LengthSquared();
+ float Length();
+ Q3DStudio::CString toString();
+ void fromString(const Q3DStudio::CString &inStringValue);
+};
+
+} // namespace Q3DStudio
+
+#endif //__VECTOR2_H_ \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Types/Vector3.cpp b/src/Authoring/Client/Code/Core/Types/Vector3.cpp
new file mode 100644
index 00000000..e23e2ff3
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Vector3.cpp
@@ -0,0 +1,579 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+
+#include <stdio.h>
+#include <math.h>
+
+#include "Vector3.h"
+#include "Rotation3.h"
+#include "Matrix.h"
+
+namespace Q3DStudio {
+
+IMPLEMENT_OBJECT_COUNTER(CVector3)
+
+//==============================================================================
+/**
+* Constructs the CVector3 object, setting its value to (x = 0.0f, y = 0.0f).
+*/
+CVector3::CVector3()
+ : x(0.0f)
+ , y(0.0f)
+ , z(0.0f)
+{
+ ADDTO_OBJECT_COUNTER(CVector3)
+}
+
+//==============================================================================
+/**
+* Constructs the CVector3 object, setting its value to the X, Y, Z passed in.
+*/
+CVector3::CVector3(float inX, float inY, float inZ)
+ : x(inX)
+ , y(inY)
+ , z(inZ)
+{
+ ADDTO_OBJECT_COUNTER(CVector3)
+}
+
+//==============================================================================
+/**
+ * Constructs a copy of the CRotation3 object.
+ *
+ * @param inRotation The source for the copy operation.
+ */
+CVector3::CVector3(const CRotation3 &inRotation)
+{
+ ADDTO_OBJECT_COUNTER(CVector3)
+ inRotation.Get(x, y, z);
+}
+
+//==============================================================================
+/**
+ * Constructs a copy of the CVector3 object.
+ *
+ * @param inVector The source for the copy operation.
+ */
+CVector3::CVector3(const CVector3 &inVector)
+ : x(inVector.x)
+ , y(inVector.y)
+ , z(inVector.z)
+{
+ ADDTO_OBJECT_COUNTER(CVector3)
+}
+
+CVector3::~CVector3()
+{
+ REMOVEFROM_OBJECT_COUNTER(CVector3)
+}
+
+//==============================================================================
+/**
+ * Equals operator for the Vector3 object.
+ *
+ * @return The new vector after assignment.
+ */
+CVector3 &CVector3::operator=(const CVector3 &inVector)
+{
+ if (&inVector != this) {
+ x = inVector.x;
+ y = inVector.y;
+ z = inVector.z;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Returns either the x,y, or z position of the vector.
+ *
+ * @param inIndex The index into the vector array.
+ *
+ * @return A reference to either the x,y, or z portion of the vector.
+ */
+float CVector3::operator[](long inIndex) const
+{
+ // Check boundries
+ if (!CheckBounds(inIndex)) {
+ // Throw exception
+ }
+
+ float theReturn;
+ switch (inIndex) {
+ case 0:
+ theReturn = x;
+ break;
+
+ case 1:
+ theReturn = y;
+ break;
+
+ case 2:
+ theReturn = z;
+ break;
+
+ default:
+ theReturn = 12345;
+ // Throw exception
+ break;
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * Tests to see if two vectors are equal.
+ *
+ * @return true if vectors are equal, otherwise false.
+ */
+bool CVector3::operator==(const CVector3 &inVector) const
+{
+ return (x == inVector.x && y == inVector.y && z == inVector.z);
+}
+
+//==============================================================================
+/**
+ * Tests to see if two vectors are NOT equal.
+ *
+ * @return true if vectors are NOT equal, otherwise false.
+ */
+bool CVector3::operator!=(const CVector3 &inVector) const
+{
+ return (x != inVector.x || y != inVector.y || z != inVector.z);
+}
+
+//==============================================================================
+/**
+ * Computes the sum of two vectors.
+ *
+ * @param inVector3 The vector to be added to the current vector.
+ * @return The sum vector.
+ */
+CVector3 CVector3::operator+(const CVector3 &inVector) const
+{
+ CVector3 theSum;
+
+ theSum.x = x + inVector.x;
+ theSum.y = y + inVector.y;
+ theSum.z = z + inVector.z;
+
+ return theSum;
+}
+
+//==============================================================================
+/**
+ * Subtracts the given vector from the current vector.
+ *
+ * @param inVector3 The vector to be subtracted from the current vector.
+ * @return The difference vector.
+ */
+CVector3 CVector3::operator-(const CVector3 &inVector) const
+{
+ CVector3 theDiff;
+
+ theDiff.x = x - inVector.x;
+ theDiff.y = y - inVector.y;
+ theDiff.z = z - inVector.z;
+
+ return theDiff;
+}
+
+//==============================================================================
+/**
+ * Multiplies by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ * @return The scaled vector.
+ */
+CVector3 CVector3::operator*(float inScalar) const
+{
+ CVector3 theProduct;
+
+ theProduct.x = inScalar * x;
+ theProduct.y = inScalar * y;
+ theProduct.z = inScalar * z;
+
+ return theProduct;
+}
+
+//==============================================================================
+/**
+ * Divides by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ * @return The scaled vector.
+ */
+CVector3 CVector3::operator/(float inScalar) const
+{
+ CVector3 theDivide;
+ float theInverse = static_cast<float>(1.0f / inScalar);
+
+ theDivide.x = theInverse * x;
+ theDivide.y = theInverse * y;
+ theDivide.z = theInverse * z;
+
+ return theDivide;
+}
+
+//==============================================================================
+/**
+ * Adds the current vector to this vector.
+ *
+ * @param inVector3 The vector to be added to the current vector.
+ * @return The sum vector.
+ */
+CVector3 &CVector3::operator+=(const CVector3 &inVector)
+{
+ x += inVector.x;
+ y += inVector.y;
+ z += inVector.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Subtracts the current vector from the this vector.
+ *
+ * @param inVector3 The vector to be subtracted from the current vector.
+ * @return The difference vector.
+ */
+CVector3 &CVector3::operator-=(const CVector3 &inVector)
+{
+ x -= inVector.x;
+ y -= inVector.y;
+ z -= inVector.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Multiplies this vector by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ * @return The scaled vector.
+ */
+CVector3 &CVector3::operator*=(float inScalar)
+{
+ x *= inScalar;
+ y *= inScalar;
+ z *= inScalar;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Divides this vector by the scalar.
+ *
+ * @param inScalar The scalar to use on the vector.
+ * @return The scaled vector.
+ */
+CVector3 &CVector3::operator/=(float inScalar)
+{
+ float theInverse = static_cast<float>(1.0f / inScalar);
+
+ x *= theInverse;
+ y *= theInverse;
+ z *= theInverse;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the x and y components for the current vector.
+ *
+ * @param inX The x component of the vector.
+ * @param inY The y component of the vector.
+ * @param inZ The Z component of the vector.
+ */
+void CVector3::Set(const float &inX, const float &inY, const float &inZ)
+{
+ x = inX;
+ y = inY;
+ z = inZ;
+}
+
+//==============================================================================
+/**
+ * Sets the x,y and z for the current vector given a vector.
+ *
+ * @param inVector The source vector
+ */
+void CVector3::Set(const CVector3 &inVector)
+{
+ x = inVector.x;
+ y = inVector.y;
+ z = inVector.z;
+}
+
+//==============================================================================
+/**
+ * Gets the x and y components for the current vector.
+ *
+ * @param outX The x component of the vector.
+ * @param outY The y component of the vector.
+ * @param outZ The z component of the vector.
+ */
+void CVector3::Get(float &outX, float &outY, float &outZ) const
+{
+ outX = x;
+ outY = y;
+ outZ = z;
+}
+
+//==============================================================================
+/**
+ * Calculates the length (magnitude) of the current vector.
+ *
+ * @param outLength The magnitude of the vector
+ * @return The length of the vector.
+ */
+float CVector3::Length() const
+{
+ return static_cast<float>(::sqrt(static_cast<double>(x * x + y * y + z * z)));
+}
+
+//==============================================================================
+/**
+ * Calculates the squared length (squared magnitude) of the current vector.
+ *
+ * @param outLengthSquared The squared magnitude of the vector
+ */
+float CVector3::LengthSquared() const
+{
+ return x * x + y * y + z * z;
+}
+
+//==============================================================================
+/**
+ * Normalizes the current vector making it a unit vector.
+ *
+ * The normalized vector is defined to be:
+ * V norm = V / Magnitude(V)
+ */
+CVector3 &CVector3::Normalize()
+{
+ float theVectorLength = Length();
+
+ // TODO change this to epsilon or something.
+ if (theVectorLength > 1e-06) {
+ float theInvLength = static_cast<float>(1.0 / theVectorLength);
+ x *= theInvLength;
+ y *= theInvLength;
+ z *= theInvLength;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Calculates the dot product of the this vector and the vector supplied as
+ * an argument.
+ *
+ * @param inVector3 The vector that is used to calculate the dot product with
+ * the current vector.
+ *
+ * @return The result of the calculation.
+ */
+float CVector3::DotProduct(const CVector3 &inVector) const
+{
+ return x * inVector.x + y * inVector.y + z * inVector.z;
+}
+
+//==============================================================================
+/**
+ * Returns the cross product of this vector and the vector passed in.
+ *
+ * @param inVector3 The vector that is used to calculate the cross product
+ * with the current vector.
+ * @return result cross product vector
+ */
+CVector3 CVector3::CrossProduct(const CVector3 &inVector) const
+{
+ CVector3 theCrossProduct;
+
+ theCrossProduct.x = y * inVector.z - z * inVector.y;
+ theCrossProduct.y = z * inVector.x - x * inVector.z;
+ theCrossProduct.z = x * inVector.y - y * inVector.x;
+
+ return theCrossProduct;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the minimum between
+ * the given vector and this vector.
+ *
+ * @param inVector3 The vector that whose elements are tested against the
+ * current vector to build the minimum.
+ */
+CVector3 &CVector3::Minimize(const CVector3 &inVector)
+{
+ if (inVector.x < x)
+ x = inVector.x;
+
+ if (inVector.y < y)
+ y = inVector.y;
+
+ if (inVector.z < z)
+ z = inVector.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the maximum between
+ * the given vector and this vector.
+ *
+ * @param inVector3 The vector that whose elements are tested against the
+ * current vector to build the maximum.
+ */
+CVector3 &CVector3::Maximize(const CVector3 &inVector)
+{
+ if (inVector.x > x)
+ x = inVector.x;
+
+ if (inVector.y > y)
+ y = inVector.y;
+
+ if (inVector.z > z)
+ z = inVector.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Validates the index being passed in does not overstep the vertex array bounds.
+ *
+ * @param inIndex The index into the vector
+ * @return true if within range, otherwise false
+ */
+bool CVector3::CheckBounds(long inIndex) const
+{
+ return (inIndex <= 3 && inIndex >= 0);
+}
+
+//==============================================================================
+/**
+ * Transforms this vector by the given matrix.
+ *
+ * The martrix is row column of the form (Matrix[row][column]):
+ *
+ * | m0 m1 m2 w |
+ * | m4 m5 m6 w |
+ * | m8 m9 m10 w |
+ * | tX tY tZ w |
+ *
+ * @inMatrix the transform matrix
+ * @inTranslate is false if you only want to rotate the vector
+ * @return this matrix
+ */
+CVector3 &CVector3::Transform(const CMatrix &inMatrix, bool inTranslate)
+{
+ float theX = x;
+ float theY = y;
+ float theZ = z;
+ float theW = inTranslate ? 1.0f : 0;
+
+ x = theX * inMatrix.m[0][0] + theY * inMatrix.m[1][0] + theZ * inMatrix.m[2][0]
+ + theW * inMatrix.m[3][0];
+ y = theX * inMatrix.m[0][1] + theY * inMatrix.m[1][1] + theZ * inMatrix.m[2][1]
+ + theW * inMatrix.m[3][1];
+ z = theX * inMatrix.m[0][2] + theY * inMatrix.m[1][2] + theZ * inMatrix.m[2][2]
+ + theW * inMatrix.m[3][2];
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Calculates the distance between this vector and another.
+ *
+ * @param inVector3 the vector to which the distance is being calculated.
+ * @return distance between vectors
+ */
+float CVector3::Distance(const CVector3 &inVector) const
+{
+ float theDx = x - inVector.x;
+ float theDy = y - inVector.y;
+ float theDz = z - inVector.z;
+ return static_cast<float>(sqrt(theDx * theDx + theDy * theDy + theDz * theDz));
+}
+
+//==============================================================================
+/**
+ * Calculates the squared distance between this vector and another.
+ *
+ * @param inVector the vector to which the distance is being calculated.
+ * @return squared distance between vectors
+ */
+float CVector3::DistanceSquared(const CVector3 &inVector) const
+{
+ float theDx = x - inVector.x;
+ float theDy = y - inVector.y;
+ float theDz = z - inVector.z;
+ return theDx * theDx + theDy * theDy + theDz * theDz;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector by performing a linear interpolation between the
+ * current vector and the given vector.
+ *
+ * The interpolation is created using the following formula:
+ *
+ * Vnew = Vorig + inInterpParam( inVector2 - Vorig )
+ *
+ * @param inVector The vector that acts as the second vector for the interpolation.
+ * @return this interpolated vector.
+ */
+CVector3 &CVector3::InterpolateLinear(const CVector3 &inVector, float inInterpParam)
+{
+ CVector3 theTempVector1(inVector * inInterpParam);
+ CVector3 theTempVector2(*this * inInterpParam);
+
+ *this += theTempVector1 - theTempVector2;
+
+ return *this;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Types/Vector3.h b/src/Authoring/Client/Code/Core/Types/Vector3.h
new file mode 100644
index 00000000..85348a04
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Vector3.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __VECTOR3_H_
+#define __VECTOR3_H_
+
+#include "UICObjectCounter.h"
+
+namespace Q3DStudio {
+
+class CMatrix;
+class CRotation3;
+
+class CVector3
+{
+ // public field members for fast access (use unions to provide two names for one variable)
+public:
+ float x; ///< X portion of vector
+ float y; ///< Y portion of vector
+ float z; ///< Z portion of vector
+
+ DEFINE_OBJECT_COUNTER(CVector3)
+
+ // Construction
+public:
+ CVector3();
+ CVector3(float inX, float inY, float inZ);
+ CVector3(const CRotation3 &inRotation);
+ CVector3(const CVector3 &inVector);
+ ~CVector3();
+ // Access
+public:
+ void Get(float &outX, float &outY, float &inZ) const;
+ void Set(const float &inX, const float &inY, const float &inZ);
+ void Set(const CVector3 &inVector);
+ float GetX() const { return x; }
+ float GetY() const { return y; }
+ float GetZ() const { return z; }
+ void SetX(const float &inX) { x = inX; }
+ void SetY(const float &inY) { y = inY; }
+ void SetZ(const float &inZ) { z = inZ; }
+
+ // Operators
+public:
+ float operator[](long inIndex) const;
+ bool operator==(const CVector3 &inVector) const;
+ bool operator!=(const CVector3 &inVector) const;
+ CVector3 operator+(const CVector3 &inVector) const;
+ CVector3 operator-(const CVector3 &inVector) const;
+ CVector3 operator*(float inScalar) const;
+ CVector3 operator/(float inScalar) const;
+ CVector3 &operator=(const CVector3 &inVector);
+ CVector3 &operator+=(const CVector3 &inVector);
+ CVector3 &operator-=(const CVector3 &inVector);
+ CVector3 &operator*=(float inScalar);
+ CVector3 &operator/=(float inScalar);
+
+ // Functions
+public:
+ float Distance(const CVector3 &inVector) const;
+ float DistanceSquared(const CVector3 &inVector) const;
+ float DotProduct(const CVector3 &inVector) const;
+ float LengthSquared() const;
+ float Length() const;
+ CVector3 CrossProduct(const CVector3 &inVector) const;
+ CVector3 &Normalize();
+ CVector3 &Minimize(const CVector3 &inVector);
+ CVector3 &Maximize(const CVector3 &inVector);
+ CVector3 &InterpolateLinear(const CVector3 &inVector, float inInterpParam);
+ CVector3 &Transform(const CMatrix &inMatrix, bool inTranslate = true);
+
+ // Implementation
+protected:
+ bool CheckBounds(long inIndex) const;
+};
+
+} // namespace Q3DStudio
+
+#endif //__VECTOR2_H_
diff --git a/src/Authoring/Client/Code/Core/Types/Vertex.h b/src/Authoring/Client/Code/Core/Types/Vertex.h
new file mode 100644
index 00000000..d49ea6bf
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Types/Vertex.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __VERTEX_H_
+#define __VERTEX_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Vector2.h"
+#include "Vector3.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CVertex: A simple, agnostic vertex data type (V3, N3, T2).
+ */
+class CVertex
+{
+public:
+ Q3DStudio::CVector3 m_Position; ///< x, y, and z position values
+ Q3DStudio::CVector3 m_Normal; ///< nx, ny, and nz components of the vertex normal
+ Q3DStudio::CVector3 m_Tangent; ///< tangent
+ Q3DStudio::CVector2 m_Texture; ///< u and v texture coordinates
+
+ // Construction
+public:
+ CVertex(const CVertex &inVertex)
+ : m_Position(inVertex.m_Position)
+ , m_Normal(inVertex.m_Normal)
+ , m_Tangent(inVertex.m_Tangent)
+ , m_Texture(inVertex.m_Texture)
+ {
+ }
+ CVertex(float inX, float inY, float inZ, float inU = 0.0f, float inV = 0.0f, float inNX = 0.0f,
+ float inNY = 0.0f, float inNZ = 0.0f, float inTX = 0.0f, float inTY = 0.0f,
+ float inTZ = 0.0f)
+ : m_Position(inX, inY, inZ)
+ , m_Normal(inNX, inNY, inNZ)
+ , m_Tangent(inTX, inTY, inTZ)
+ , m_Texture(inU, inV)
+ {
+ }
+ CVertex(){}
+
+ // Opertators
+public:
+ CVertex &operator=(const CVertex &inVertex)
+ {
+ // Check for self assignment
+ if (&inVertex != this) {
+ m_Position = inVertex.m_Position;
+ m_Normal = inVertex.m_Normal;
+ m_Texture = inVertex.m_Texture;
+ m_Tangent = inVertex.m_Tangent;
+ }
+
+ return *this;
+ }
+
+ bool operator==(const CVertex &inVertex) const
+ {
+ return m_Position == inVertex.m_Position && m_Normal == inVertex.m_Normal
+ && m_Tangent == inVertex.m_Tangent && m_Texture == inVertex.m_Texture;
+ }
+};
+
+#endif //__VERTEX_H_ \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/UICOptions.h b/src/Authoring/Client/Code/Core/UICOptions.h
new file mode 100644
index 00000000..bb9b5ccc
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/UICOptions.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Studio Configuration Header
+//==============================================================================
+#pragma once
+
+//==============================================================================
+// Configure features to be included/excluded
+//==============================================================================
+#ifndef INCLUDE_EDIT_CAMERA
+#define INCLUDE_EDIT_CAMERA
+#endif
diff --git a/src/Authoring/Client/Code/Core/Utility/BuildConfigParser.cpp b/src/Authoring/Client/Code/Core/Utility/BuildConfigParser.cpp
new file mode 100644
index 00000000..71deddcd
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/BuildConfigParser.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+
+#include "BuildConfigParser.h"
+#include "UICFileTools.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const auto STR_TAG_PROJECT = QStringLiteral("project");
+const auto STR_TAG_INTEGRATION = QStringLiteral("uic:integration");
+const auto STR_TAG_PREVIEW = QStringLiteral("uic:preview");
+const auto STR_TAG_DEPLOY = QStringLiteral("uic:deploy");
+const auto STR_TAG_PROPERTY = QStringLiteral("uic:property");
+const auto STR_TAG_VALUE = QStringLiteral("uic:value");
+
+const auto STR_PARAM_NAME = QStringLiteral("name");
+const auto STR_PARAM_LABEL = QStringLiteral("label");
+const auto STR_PARAM_HELP = QStringLiteral("help");
+
+//===============================================================================
+/**
+ * Constructor
+ */
+CBuildConfigParser::CBuildConfigParser(CBuildConfigurations &inConfigurations)
+ : m_BuildConfigurations(inConfigurations)
+ , m_CurrentConfiguration(nullptr)
+ , m_CurrentProperty(nullptr)
+ , m_TagStarted(false)
+{
+}
+
+//===============================================================================
+/**
+ * Destructor
+ */
+CBuildConfigParser::~CBuildConfigParser()
+{
+}
+
+//===============================================================================
+/**
+ * Load all the build configuration files in the directory.
+ * @param inDirectory the directory to look for all the configuration files
+ * @return true if all files parsed successfully, else false
+ */
+bool CBuildConfigParser::LoadConfigurations(CUICFile &inDirectory)
+{
+ m_ErrorMessage.clear();
+
+ CFileIterator theFileIter = inDirectory.GetSubItems();
+ while (!theFileIter.IsDone()) {
+ CUICFile theCurrentFile(theFileIter.GetCurrent());
+ m_CurrentFile = theCurrentFile.GetAbsolutePath();
+
+ if (theCurrentFile.GetExtension().CompareNoCase(L"build")) {
+ m_CurrentConfiguration = new CBuildConfiguration(m_CurrentFile);
+ QFile file(theCurrentFile.GetAbsolutePath().toQString());
+ file.open(QFile::ReadOnly);
+ QXmlStreamReader reader(&file);
+ reader.setNamespaceProcessing(false);
+ while (!reader.atEnd()) {
+ QXmlStreamReader::TokenType token = reader.readNext();
+ if (token == QXmlStreamReader::StartElement)
+ StartElement(reader.qualifiedName().toString(),reader.attributes());
+ else if (token == QXmlStreamReader::Characters)
+ HandleCharacterData(reader.text().toString(),0);
+ else if (token == QXmlStreamReader::EndElement)
+ EndElement(reader.qualifiedName().toString());
+ }
+ if (reader.hasError()) {
+ m_ErrorMessage += reader.errorString();
+ delete m_CurrentConfiguration;
+ m_CurrentConfiguration = nullptr;
+ } else {
+ DocumentFinished();
+ }
+ file.close();
+ }
+ ++theFileIter;
+ }
+
+ // Check the error message to see if parse successful or fail
+ if (m_ErrorMessage.isEmpty())
+ return true;
+ else
+ return false;
+}
+
+
+//===============================================================================
+/**
+ * Callback when completed the parsing. Add the build configuration loaded to the
+ * stored list
+ */
+void CBuildConfigParser::DocumentFinished()
+{
+ if (m_CurrentConfiguration) {
+ m_BuildConfigurations.AddConfiguration(m_CurrentConfiguration);
+ m_CurrentConfiguration = nullptr;
+ }
+}
+
+//===============================================================================
+/**
+ * Callback when starting parsing an element
+ */
+void CBuildConfigParser::StartElement(const QString &inElementName,
+ const QXmlStreamAttributes &inAttributes)
+{
+ if (inElementName == STR_TAG_PROJECT) {
+ ParseProjectAttributes(inAttributes);
+ } else if (inElementName == STR_TAG_PROPERTY) {
+ CBuildConfiguration::SConfigProperty theProperty;
+ ParsePropertyAttributes(theProperty, inAttributes);
+ m_CurrentProperty = &m_CurrentConfiguration->AddProperty(theProperty);
+ } else if (inElementName == STR_TAG_VALUE) {
+ ParseValueAttributes(inAttributes);
+ } else if (inElementName == STR_TAG_PREVIEW || inElementName == STR_TAG_DEPLOY) {
+ m_TagStarted = true;
+ m_ElementData = "";
+ }
+}
+
+//===============================================================================
+/**
+ * Callback after finished parsing an element
+ */
+void CBuildConfigParser::EndElement(const QString &inElementName)
+{
+ if (inElementName == STR_TAG_PREVIEW)
+ m_CurrentConfiguration->SetPreviewApp(m_ElementData);
+ else if (inElementName == STR_TAG_DEPLOY)
+ m_CurrentConfiguration->SetDeployApp(m_ElementData);
+ m_TagStarted = false;
+}
+
+//===============================================================================
+/**
+ * Callback when handling the value of an element
+ */
+void CBuildConfigParser::HandleCharacterData(const QString &data, int /*inLen*/)
+{
+ if (m_TagStarted)
+ m_ElementData += Q3DStudio::CString::fromQString(data);
+}
+
+//===============================================================================
+/**
+ * Read in all the project related attributes
+ */
+void CBuildConfigParser::ParseProjectAttributes(const QXmlStreamAttributes &inAttributes)
+{
+ for (const QXmlStreamAttribute &attrib : inAttributes) {
+ if (attrib.name() == STR_PARAM_NAME)
+ m_CurrentConfiguration->SetName(attrib.value().toUtf8().constData());
+ }
+}
+
+//===============================================================================
+/**
+ * Read in all the property related attributes
+ */
+void CBuildConfigParser::ParsePropertyAttributes(CBuildConfiguration::SConfigProperty &inProperty,
+ const QXmlStreamAttributes &inAttributes)
+{
+ for (const QXmlStreamAttribute &attrib : inAttributes) {
+ if (attrib.name() == STR_PARAM_NAME)
+ inProperty.SetName(attrib.value().toUtf8().constData());
+ else if (attrib.name() == STR_PARAM_LABEL)
+ inProperty.SetLabel(attrib.value().toUtf8().constData());
+ else if (attrib.name() == STR_PARAM_HELP)
+ inProperty.SetHelp(attrib.value().toUtf8().constData());
+ }
+}
+
+//===============================================================================
+/**
+ * Read in all the property value related attributes
+ */
+void CBuildConfigParser::ParseValueAttributes(const QXmlStreamAttributes &inAttributes)
+{
+ CBuildConfiguration::SConfigPropertyValue theValue;
+ for (const QXmlStreamAttribute &attrib : inAttributes) {
+ if (attrib.name() == STR_PARAM_NAME)
+ theValue.SetName(attrib.value().toUtf8().constData());
+ else if (attrib.name() == STR_PARAM_LABEL)
+ theValue.SetLabel(attrib.value().toUtf8().constData());
+ }
+
+ using namespace Q3DStudio;
+ Q3DStudio::CString thePropertyName = m_CurrentProperty->GetName();
+ if (thePropertyName == L"MODE") {
+ Q3DStudio::CString theValueName(theValue.GetName());
+ if (theValueName == L"Debug") {
+ CFilePath theFilePath;
+ theFilePath.GetModuleFilePath();
+ CFilePath theDir = theFilePath.GetDirectory().GetFileStem();
+ // If this isn't a developer build.
+ if (theDir.Compare(L"release", CFilePath::ENDOFSTRING, false) == false
+ && theDir.Compare(L"debug", CFilePath::ENDOFSTRING, false) == false)
+ return;
+ }
+ }
+
+ m_CurrentProperty->AddValue(theValue);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Client/Code/Core/Utility/BuildConfigParser.h b/src/Authoring/Client/Code/Core/Utility/BuildConfigParser.h
new file mode 100644
index 00000000..33c429b2
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/BuildConfigParser.h
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_BUILD_CONFIG_PARSER_H
+#define INCLUDED_BUILD_CONFIG_PARSER_H
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <list>
+
+#include <QMetaType>
+#include "UICFile.h"
+#include <QtCore/qxmlstream.h>
+
+
+namespace Q3DStudio {
+
+//=============================================================================
+/**
+ * Wrapper class to store a Build configuration.
+ */
+class CBuildConfiguration
+{
+public:
+ struct SConfigPropertyValue
+ {
+ protected:
+ CString m_Name; ///< name of property value
+ CString m_Label; ///< display name of property value
+
+ public:
+ const CString &GetName() { return m_Name; }
+ void SetName(const CString &inName) { m_Name = inName; }
+
+ const CString &GetLabel() { return m_Label; }
+ void SetLabel(const CString &inLabel) { m_Label = inLabel; }
+ };
+
+ typedef std::vector<SConfigPropertyValue> TConfigPropertyValues; ///< List of property values
+ struct SConfigProperty
+ {
+ protected:
+ CString m_Name; ///< name of property
+ CString m_Label; ///< display name of property
+ CString m_Help; ///< help string of property
+ TConfigPropertyValues m_AcceptableValues; ///< List of acceptable values
+
+ public:
+ const CString &GetName() { return m_Name; }
+ void SetName(const CString &inName) { m_Name = inName; }
+
+ const CString &GetLabel() { return m_Label; }
+ void SetLabel(const CString &inLabel) { m_Label = inLabel; }
+
+ const CString &GetHelp() { return m_Help; }
+ void SetHelp(const CString &inHelp) { m_Help = inHelp; }
+
+ void AddValue(SConfigPropertyValue &inValue) { m_AcceptableValues.push_back(inValue); }
+
+ bool HasValue(const CString &inPropertyValue)
+ {
+ TConfigPropertyValues::iterator theIter;
+ for (theIter = m_AcceptableValues.begin(); theIter != m_AcceptableValues.end();
+ ++theIter) {
+ if (theIter->GetName() == inPropertyValue)
+ return true;
+ }
+ return false;
+ }
+
+ SConfigPropertyValue &GetValue(long inIndex) { return m_AcceptableValues.at(inIndex); }
+
+ TConfigPropertyValues &GetAcceptableValues() { return m_AcceptableValues; }
+ };
+
+ typedef std::list<SConfigProperty> TConfigProperties; ///< List of properties
+
+protected:
+ CString m_Name; ///< Name of this configuration
+ CString m_Path; ///< Absolute path of this configuration
+ CString m_PreviewApp; ///< preview application syntax
+ CString m_DeployApp; ///< delploy application syntax
+ TConfigProperties m_ConfigProperties; ///< List of properties
+
+public:
+ CBuildConfiguration(const CString &inPath)
+ : m_Path(inPath)
+ {
+ }
+
+ const CString &GetPath() { return m_Path; }
+ void SetPath(const CString &inPath) { m_Path = inPath; }
+
+ const CString &GetName() { return m_Name; }
+ void SetName(const CString &inName) { m_Name = inName; }
+
+ const CString &GetPreviewApp() { return m_PreviewApp; }
+ void SetPreviewApp(const CString &inPreviewApp) { m_PreviewApp = inPreviewApp; }
+
+ const CString &GetDeployApp() { return m_DeployApp; }
+ void SetDeployApp(const CString &inDeployApp) { m_DeployApp = inDeployApp; }
+
+ SConfigProperty &AddProperty(SConfigProperty &inProperty)
+ {
+ m_ConfigProperties.push_back(inProperty);
+ return m_ConfigProperties.back();
+ }
+
+ SConfigProperty *GetProperty(const CString &inPropertyName)
+ {
+ TConfigProperties::iterator theIter;
+ for (theIter = m_ConfigProperties.begin(); theIter != m_ConfigProperties.end(); ++theIter) {
+ if (theIter->GetName() == inPropertyName)
+ return &*theIter;
+ }
+
+ return nullptr;
+ }
+
+ TConfigProperties &GetBuildProperties() { return m_ConfigProperties; }
+};
+
+//=============================================================================
+/**
+ * Wrapper class to store a list of Build configurations.
+ */
+class CBuildConfigurations
+{
+public:
+ typedef std::map<CString, CBuildConfiguration *>
+ TBuildConfigurations; ///< List of build configurations, sorted by name
+
+public:
+ void AddConfiguration(CBuildConfiguration *inConfig)
+ {
+ m_BuildConfigurations.insert(std::make_pair(inConfig->GetName(), inConfig));
+ }
+
+ CBuildConfiguration *GetConfiguration(const CString &inName)
+ {
+ TBuildConfigurations::iterator theFind = m_BuildConfigurations.find(inName);
+ if (theFind != m_BuildConfigurations.end())
+ return theFind->second;
+ else
+ return NULL;
+ }
+
+ TBuildConfigurations &GetConfigurations() { return m_BuildConfigurations; }
+
+ void Clear()
+ {
+ TBuildConfigurations::iterator theIter;
+ for (theIter = m_BuildConfigurations.begin(); theIter != m_BuildConfigurations.end();
+ ++theIter) {
+ delete theIter->second;
+ }
+ m_BuildConfigurations.clear();
+ }
+
+protected:
+ TBuildConfigurations m_BuildConfigurations; ///< list of build configurations
+};
+
+//=============================================================================
+/**
+ * Parser for build configurations (.build) files in "Build Configurations" folder
+ */
+class CBuildConfigParser
+{
+ CBuildConfigParser(const CBuildConfigParser &other);
+ CBuildConfigParser &operator=(const CBuildConfigParser &other);
+
+public:
+ CBuildConfigParser(CBuildConfigurations &inConfigurations);
+ virtual ~CBuildConfigParser();
+
+public:
+ bool LoadConfigurations(CUICFile &inDirectory);
+ CString GetErrorMessage() { return CString::fromQString(m_ErrorMessage); }
+
+protected:
+ void ParseProjectAttributes(const QXmlStreamAttributes &inAttributes);
+ void ParsePropertyAttributes(CBuildConfiguration::SConfigProperty &inProperty,
+ const QXmlStreamAttributes &inAttributes);
+ void ParseValueAttributes(const QXmlStreamAttributes &inAttributes);
+
+protected:
+ void StartElement(const QString &inElementName,
+ const QXmlStreamAttributes &inAttributes);
+ void HandleCharacterData(const QString &data, int inLen);
+ void EndElement(const QString &inElementName);
+ void DocumentFinished();
+
+protected:
+ CBuildConfigurations &m_BuildConfigurations; ///< Working list of build configurations
+ CBuildConfiguration *m_CurrentConfiguration; ///< Current parsing configuration
+ CBuildConfiguration::SConfigProperty *m_CurrentProperty; ///< Current parsing property
+ CString m_CurrentFile; ///< Current Parse file
+ CString m_ElementData; ///< Element Data read in
+ QString m_ErrorMessage; ///< Consolidated error messages
+ bool m_TagStarted; ///< Hacked to signify tag started
+};
+
+} // namespace Q3DStudio
+
+Q_DECLARE_METATYPE(Q3DStudio::CBuildConfiguration *)
+Q_DECLARE_METATYPE(Q3DStudio::CBuildConfiguration::SConfigPropertyValue *)
+
+#endif // INCLUDED_BUILD_CONFIG_PARSER_H
diff --git a/src/Authoring/Client/Code/Core/Utility/ColorConversion.cpp b/src/Authoring/Client/Code/Core/Utility/ColorConversion.cpp
new file mode 100644
index 00000000..b03f81c6
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/ColorConversion.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "ColorConversion.h"
+
+//==============================================================================
+/**
+* Returns the red portion of the color
+*
+* @param inRGBA A long composed of RGBA values.
+*/
+unsigned char CColorConversion::GetRed(long inRGBA)
+{
+ return static_cast<unsigned char>(0xFF & inRGBA);
+}
+
+//==============================================================================
+/**
+* Returns the green portion of the color
+*
+* @param inRGBA A long composed of RGBA values.
+*/
+unsigned char CColorConversion::GetGreen(long inRGBA)
+{
+ return static_cast<unsigned char>(0xFF & inRGBA >> 8);
+}
+
+//==============================================================================
+/**
+* Returns the blue portion of the color
+*
+* @param inRGBA A long composed of RGBA values.
+*/
+unsigned char CColorConversion::GetBlue(long inRGBA)
+{
+ return static_cast<unsigned char>(0xFF & inRGBA >> 16);
+}
+
+//==============================================================================
+/**
+* Returns the alpha portion of the color
+*
+* @param inRGBA A long composed of RGBA values.
+*/
+unsigned char CColorConversion::GetAlpha(long inRGBA)
+{
+ return static_cast<unsigned char>(0xFF & inRGBA >> 24);
+}
+
+//==============================================================================
+/**
+* MakeRGB: Creates an RGBA long from float portions (0.0-1.0)
+*
+* @param inRed Red portion
+* @param inGreen Green portion
+* @param inBlue Blue portion
+* @param inAlpha Alpha portion
+*/
+long CColorConversion::MakeRGBA(float inRed, float inGreen, float inBlue, float inAlpha)
+{
+ return MakeRGBA(static_cast<long>(inRed * 255), static_cast<long>(inGreen * 255),
+ static_cast<long>(inBlue * 255), static_cast<long>(inAlpha * 255));
+}
+
+//==============================================================================
+/**
+* MakeRGBA: Creates an RGBA long from long portions (0-255)
+*
+* @param inRed Red portion
+* @param inGreen Green portion
+* @param inBlue Blue portion
+* @param inAlpha Alpha portion
+*/
+long CColorConversion::MakeRGBA(long inRed, long inGreen, long inBlue, long inAlpha)
+{
+ return ((inAlpha << 24) | (inBlue << 16) | (inGreen << 8) | inRed);
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/ColorConversion.h b/src/Authoring/Client/Code/Core/Utility/ColorConversion.h
new file mode 100644
index 00000000..3ef58487
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/ColorConversion.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __CCOLORCONVERSION_H_
+#define __CCOLORCONVERSION_H_
+
+class CColorConversion
+{
+public:
+ // Operations
+ static unsigned char GetRed(long inRGBA);
+ static unsigned char GetGreen(long inRGBA);
+ static unsigned char GetBlue(long inRGBA);
+ static unsigned char GetAlpha(long inRGBA);
+ static long MakeRGBA(float inRed, float inGreen, float inBlue, float inAlpha = 1.0f);
+ static long MakeRGBA(long inRed, long inGreen, long inBlue, long inAlpha = 255);
+};
+
+#endif // __CCOLORCONVERSION_H_ \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Utility/CoreConst.h b/src/Authoring/Client/Code/Core/Utility/CoreConst.h
new file mode 100644
index 00000000..9d446c96
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/CoreConst.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtGlobal>
+
+#include "UICId.h"
+
+/// Update masks. Each view will check their mask against the HINT passed in via UpdateAllViews (in
+/// their OnUpdate). If
+/// their bit is set, they will requery the document for the entire presentation's data. Otherwise,
+/// they'll ignore the
+/// update.
+// These are the new operation update masks
+namespace UPDATEMASK {
+const long NONE = 0x00000000;
+const long UPDATECLIENT = 0x00000010; // Update the Client Scene
+const long NEWRESOURCE = 0x00000100; // We've added a new item to the Library
+const long NEWRESOURCE_LOADING =
+ 0x00000200; // This is when we're loading items from the Library - not everything exists yet
+const long PROPERTYCHANGE = 0x00000400; // Property on the selected object changed
+const long ASSOCIATIONCHANGE = 0x00000800; // An association changed (added or removed)
+const long SELECTIONCHANGE = 0x00001000; // The selected object changed
+const long RESOURCECHANGE = 0x00002000; // A resource changed (usually a refresh from file)
+const long TIMECHANGE = 0x00004000; // The time of the active time context changed
+const long NEWPRESENTATION = 0x00008000; // New presentation created - start from scratch
+const long CONFIGCHANGE = 0x00020000; // Configuration/Preferences were changed
+const long NEWCOMMAND = 0x00040000; // A new CStudioCommand object was committed
+const long COMMANDCHANGE = 0x00080000; // A command property has changed (been undone/redone)
+const long REACQUIRE = 0x00100000; // Dump stored data and get everything new from Client - resync
+const long KEYFRAMEADD = 0x00200000; // A keyframe was inserted
+const long KEYFRAMEDELETE = 0x00400000; // A keyframe was removed
+const long KEYFRAMESELECT = 0x00800000; // A keyframe was selected
+const long KEYFRAMEDESELECT = 0x01000000; // A keyframe was deselected
+const long KEYFRAMEMOVE = 0x02000000; // A keyframe was moved (time was changed)
+const long TIMEBARCHANGE =
+ 0x04000000; // Position of a timebar has changed (primarily due to undo/redo)
+const long INITSTORAGEPALETTE =
+ 0x08000000; // Clear storage palette tabs and create the default tabs
+const long SHOWHELPPALETTE = 0x10000000; // Show the Help Palette if it is not already showing
+const long RESETDATA = 0x20000000; // Reset the data in the view by clearing the view's contents
+const long PLAYMODECHANGE = 0x40000000; // The Studio play mode has changed
+}
+
+enum ENudgeDirection {
+ NUDGE_NEG_X = -1,
+ NUDGE_NEG_Y = -2,
+ NUDGE_NEG_Z = -3,
+ NUDGE_POS_X = 1,
+ NUDGE_POS_Y = 2,
+ NUDGE_POS_Z = 3
+};
+
+// Used for play mode notifications inside the Document.
+enum EPlayMode {
+ PLAYMODE_STOP = 1,
+ PLAYMODE_PLAY = 2,
+};
+
+/// Define used to reference a GUID used internally in Client.
+static const GUID GUID_SCENE = {
+ 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
+};
+
+// Used to determine if a keyframe needs to be set on F6.
+// This is determined by FLOAT_NUM_DECIMAL_PLACES and should not be larger than
+// .1^FLOAT_NUM_DECIMAL_PLACES.
+const float FLOAT_DIFF_TOLERANCES = .001f;
+
+// Length of the animation tracks. This needs to be at least 1 ms longer
+// than the limit of the timeline.
+// This is currently 10 min, 18 sec. The limit is therefore 10 min, 20 sec, 1 ms.
+// set to long max.
+const long ANIMATION_TRACK_LIMIT = LONG_MAX - 1;
+
+// Snapping grid settings
+enum ESnapGridResolution {
+ SNAPGRID_SECONDS = 0,
+ SNAPGRID_HALFSECONDS = 1,
+ SNAPGRID_TICKMARKS = 2,
+};
+
+// Client Tool Mode Constants
+const long STUDIO_TOOLMODE_SCALE = 0x01;
+const long STUDIO_TOOLMODE_MOVE = 0x02;
+const long STUDIO_TOOLMODE_ROTATE = 0x04;
+const long STUDIO_TOOLMODE_CAMERA_PAN = 0x10;
+const long STUDIO_TOOLMODE_CAMERA_ZOOM = 0x20;
+const long STUDIO_TOOLMODE_CAMERA_ROTATE = 0x40;
+
+const long STUDIO_CAMERATOOL_MASK = 0xF0;
+
+/// Defines the base duration of the presentation on creation (on File | New).
+const long DEFAULT_DURATION = 10000;
+
+// Client Select Mode Constants
+const long STUDIO_SELECTMODE_ENTITY = 0x01;
+const long STUDIO_SELECTMODE_GROUP = 0x02;
+
+struct SceneDragSenderType
+{
+ enum Enum {
+ Unknown = 0,
+ Matte,
+ SceneWindow,
+ };
+};
diff --git a/src/Authoring/Client/Code/Core/Utility/CoreUtils.cpp b/src/Authoring/Client/Code/Core/Utility/CoreUtils.cpp
new file mode 100644
index 00000000..1bbfb9fb
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/CoreUtils.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CoreUtils.h"
+
+//==============================================================================
+/**
+ * Converts a double to a long, rounding up as necessary.
+ * @param inDouble double value to be converted
+ * @return rounded-up long value
+ */
+long dtol(double inDouble)
+{
+ return static_cast<long>(inDouble + 0.5);
+}
+
+int dtoi(double inDouble)
+{
+ return static_cast<int>(inDouble + 0.5);
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/CoreUtils.h b/src/Authoring/Client/Code/Core/Utility/CoreUtils.h
new file mode 100644
index 00000000..b55c0de0
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/CoreUtils.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_CORE_UTILS_H
+#define INCLUDED_CORE_UTILS_H 1
+
+#pragma once
+
+//==============================================================================
+// Functions
+//==============================================================================
+long dtol(double inDouble);
+int dtoi(double inDouble);
+
+#endif // INCLUDED_CORE_UTILS_H
diff --git a/src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.cpp b/src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.cpp
new file mode 100644
index 00000000..5236a21f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DataModelObjectReferenceHelper.h"
+#include "Core.h"
+#include "Doc.h"
+#include "GraphUtils.h"
+
+// UICDM
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+#include "StudioFullSystem.h"
+#include "UICDMDataCore.h"
+#include "Graph.h"
+
+inline void GetAllowableParentSlides(CClientDataModelBridge *inBridge,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::TSlideHandleList &inList)
+{
+ if (!inInstance.Valid())
+ return;
+
+ UICDM::CUICDMSlideHandle theSlide = 0;
+ UICDM::CUICDMInstanceHandle theTimeParent = inBridge->GetOwningComponentInstance(inInstance);
+ if (theTimeParent.Valid()) {
+ if (inBridge->IsMaster(inInstance)) {
+ // we use master time context if parent is a master object
+ theSlide = inBridge->GetComponentSlide(theTimeParent, 0);
+ } else // else, we use the current time context of the parent
+ theSlide = inBridge->GetComponentActiveSlide(theTimeParent);
+
+ // depth first, so that we have Scene at the beginning of the list.
+ GetAllowableParentSlides(inBridge, theTimeParent, inList);
+ }
+
+ if (theSlide.Valid())
+ inList.push_back(theSlide);
+}
+
+CObjectReferenceHelper::CObjectReferenceHelper(CDoc *inDoc)
+ : m_Doc(inDoc)
+{
+}
+
+CObjectReferenceHelper::~CObjectReferenceHelper()
+{
+}
+
+IObjectReferenceHelper::SObjectRefInfo
+CObjectReferenceHelper::GetInfo(const UICDM::CUICDMInstanceHandle &inInstance) const
+{
+ // UICDM
+ using namespace UICDM;
+ CClientDataModelBridge *theClientBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+
+ if (inInstance.Valid()) {
+ IObjectReferenceHelper::SObjectRefInfo theInfo;
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ // Type
+ theInfo.m_Type = theClientBridge->GetObjectType(inInstance);
+ // Name
+ if (theInfo.m_Type != OBJTYPE_IMAGE) {
+ SValue theNameValue;
+ thePropertySystem->GetInstancePropertyValue(
+ inInstance, theClientBridge->GetNameProperty(), theNameValue);
+ TDataStrPtr theName = UICDM::get<TDataStrPtr>(theNameValue);
+ if (theName)
+ theInfo.m_Name = theName->GetData();
+ } else {
+ UICDM::CUICDMInstanceHandle theParentInstance;
+ UICDM::CUICDMPropertyHandle theProperty;
+ if (!theClientBridge->GetMaterialFromImageInstance(inInstance, theParentInstance,
+ theProperty))
+ theClientBridge->GetLayerFromImageProbeInstance(inInstance, theParentInstance,
+ theProperty);
+ if (theParentInstance.Valid() && theProperty.Valid())
+ theInfo.m_Name =
+ thePropertySystem->GetFormalName(theParentInstance, theProperty).c_str();
+ }
+ // Master, by checking if guid property is linked.
+ theInfo.m_Master = m_Doc->GetStudioSystem()->GetSlideSystem()->IsPropertyLinked(
+ inInstance, theClientBridge->GetIdProperty());
+
+ return theInfo;
+ }
+
+ return IObjectReferenceHelper::SObjectRefInfo();
+}
+
+// Return the list of slide handles that is 'accessible' via this base id.
+UICDM::TSlideHandleList
+CObjectReferenceHelper::GetSlideList(const UICDM::CUICDMInstanceHandle inInstance) const
+{
+ UICDM::TSlideHandleList theList;
+ if (inInstance.Valid()) {
+ CClientDataModelBridge *theBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::CUICDMSlideHandle theCurrentSlide = m_Doc->GetActiveSlide();
+ if (theBridge->IsComponentInstance(inInstance)) {
+ // if selected object is a component, and we are inside it
+ GetAllowableParentSlides(theBridge, inInstance, theList);
+ } else {
+ // not a component, or we are outside of a component
+ GetAllowableParentSlides(theBridge, theBridge->GetOwningComponentInstance(inInstance),
+ theList);
+ }
+ theList.push_back(theCurrentSlide); // this is always appended
+ }
+ return theList;
+}
+
+// Return all children under inSlideIndex
+bool CObjectReferenceHelper::GetChildInstanceList(
+ const UICDM::CUICDMInstanceHandle &inInstance, UICDM::TInstanceHandleList &outList,
+ UICDM::CUICDMSlideHandle inSlide, const UICDM::CUICDMInstanceHandle &inOwningInstance) const
+{
+ (void)inOwningInstance;
+ CClientDataModelBridge *theClientBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ if (inInstance.Valid()) {
+ // ASSERT(0); // Should this work for more than Materials?
+ if (theClientBridge->IsMaterialInstance(inInstance)) { // UICDM objects
+ long theSlideIndex = m_Doc->GetStudioSystem()->GetSlideSystem()->GetSlideIndex(inSlide);
+ GetPropertyAsChildrenList(inInstance, outList, theSlideIndex);
+ return true;
+ // no support for actual hierarchy.
+ }
+ Q3DStudio::CGraphIterator theChildren;
+ m_Doc->GetAssetGraph()->GetChildren(theChildren, inInstance);
+ for (; !theChildren.IsDone(); ++theChildren) {
+ outList.push_back(theChildren.GetCurrent());
+ }
+ return true;
+ }
+ return false;
+}
+
+//==============================================================================
+/**
+ * Figures out the object (displayed) name for a given instance
+ */
+Q3DStudio::CString
+CObjectReferenceHelper::LookupObjectFormalName(const UICDM::CUICDMInstanceHandle inInstance) const
+{
+ UICDM::IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *theClientBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ if (theClientBridge->IsImageInstance(inInstance)) {
+ UICDM::CUICDMInstanceHandle theParentInstance;
+ UICDM::CUICDMPropertyHandle theProperty;
+ if (!theClientBridge->GetMaterialFromImageInstance(inInstance, theParentInstance,
+ theProperty))
+ theClientBridge->GetLayerFromImageProbeInstance(inInstance, theParentInstance,
+ theProperty);
+ UICDM::TCharStr theFormalName =
+ thePropertySystem->GetFormalName(theParentInstance, theProperty);
+ return theFormalName.c_str();
+ } else {
+ UICDM::SValue theNameValue;
+ thePropertySystem->GetInstancePropertyValue(inInstance, theClientBridge->GetNameProperty(),
+ theNameValue);
+ if (GetValueType(theNameValue) == UICDM::DataModelDataType::String) {
+ UICDM::TDataStrPtr theName = UICDM::get<UICDM::TDataStrPtr>(theNameValue);
+ return theName->GetData();
+ }
+ return L"";
+ }
+}
+
+//==============================================================================
+/**
+ * String returned for displaying relative path values in the Object Ref Picker
+ */
+Q3DStudio::CString CObjectReferenceHelper::GetObjectReferenceString(
+ const UICDM::CUICDMInstanceHandle &inBaseInstance, CRelativePathTools::EPathType inPathType,
+ const UICDM::CUICDMInstanceHandle &inInstance) const
+{
+ return CRelativePathTools::BuildReferenceString(inInstance, inBaseInstance, inPathType, m_Doc);
+}
+
+//==============================================================================
+/**
+ * NOTE: inId is never a UICDM object, till we support dynamic properties OR actions for UICDM
+ * objects.
+ */
+bool CObjectReferenceHelper::ResolvePath(const UICDM::CUICDMInstanceHandle &inInstance,
+ const Q3DStudio::CString &inPathValue,
+ CRelativePathTools::EPathType &outType,
+ UICDM::CUICDMInstanceHandle &outResolvedInstance)
+{
+ if (inInstance.Valid()) {
+ bool theFullResolvedFlag;
+ outResolvedInstance = CRelativePathTools::FindAssetInstanceByObjectPath(
+ m_Doc, inInstance, inPathValue, outType, theFullResolvedFlag, this);
+ return outResolvedInstance.Valid();
+ }
+ return false;
+}
+using namespace UICDM;
+
+UICDM::CUICDMInstanceHandle
+CObjectReferenceHelper::Resolve(const UICDM::SValue &inObjectRefValue,
+ const UICDM::CUICDMInstanceHandle &inBaseInstance) const
+{
+ CClientDataModelBridge *theBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ if (inBaseInstance.Valid()) {
+ SValue theRefValue(inObjectRefValue);
+ UICDM::DataModelDataType::Value theValueType = GetValueType(inObjectRefValue);
+ if (theValueType == DataModelDataType::ObjectRef) {
+ const SObjectRefType &theRef(UICDM::get<SObjectRefType>(inObjectRefValue));
+ switch (theRef.GetReferenceType()) {
+ case ObjectReferenceType::Absolute:
+ theRefValue = UICDM::get<SLong4>(theRef.m_Value);
+ break;
+ case ObjectReferenceType::Relative:
+ theRefValue = UICDM::get<TDataStrPtr>(theRef.m_Value);
+ break;
+ default:
+ break;
+ }
+ theValueType = GetValueType(theRefValue);
+ }
+ if (theValueType == UICDM::DataModelDataType::String) // route it through the function that
+ // can determine both old client and
+ // new UICDM objects
+ {
+ bool theFullResolvedFlag = false;
+ CRelativePathTools::EPathType theUnusedPathType;
+ return CRelativePathTools::FindAssetInstanceByObjectPath(
+ m_Doc, inBaseInstance, UICDM::get<UICDM::TDataStrPtr>(theRefValue)->GetData(),
+ theUnusedPathType, theFullResolvedFlag, this);
+ } else if (theValueType == UICDM::DataModelDataType::Long) {
+ return UICDM::get<qt3ds::QT3DSI32>(theRefValue);
+ } else if (theValueType == UICDM::DataModelDataType::Long4) {
+ UICDM::SLong4 theGuid = UICDM::get<UICDM::SLong4>(theRefValue);
+ return theBridge->GetInstanceByGUID(theGuid);
+ }
+ }
+ return UICDM::CUICDMInstanceHandle();
+}
+
+//==============================================================================
+/**
+ * This is triggered when values are changed in the Object Ref picker, make sure the path type is
+ * preserved.
+ */
+UICDM::SObjectRefType
+CObjectReferenceHelper::GetAssetRefValue(const UICDM::CUICDMInstanceHandle &inInstance,
+ const UICDM::CUICDMInstanceHandle &inBaseInstance,
+ CRelativePathTools::EPathType inPathType) const
+{
+ return CRelativePathTools::CreateAssetRefValue(inInstance, inBaseInstance, inPathType, m_Doc);
+}
+
+void CObjectReferenceHelper::GetPropertyAsChildrenList(
+ const UICDM::CUICDMInstanceHandle &inInstance, UICDM::TInstanceHandleList &outList,
+ long inSlideIndex) const
+{
+ if (inInstance.Valid()) {
+ CClientDataModelBridge *theClientBridge =
+ m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ using namespace UICDM;
+
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(inInstance, theProperties);
+
+ for (size_t thePropertyIndex = 0; thePropertyIndex < theProperties.size();
+ ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(inInstance, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ SValue theValue;
+ if ((inSlideIndex >= 0
+ && theSlideSystem->GetSlidePropertyValue(inSlideIndex, inInstance, theProperty,
+ theValue))
+ || m_Doc->GetStudioSystem()->GetFullSystem()->GetCanonicalInstancePropertyValue(
+ inInstance, theProperty, theValue)) {
+ SLong4 theLong4 = UICDM::get<SLong4>(theValue);
+ if (theLong4.m_Longs[0] != 0 || theLong4.m_Longs[1] != 0
+ || theLong4.m_Longs[2] != 0 || theLong4.m_Longs[3] != 0) {
+ CUICDMInstanceHandle theImageInstance =
+ theClientBridge->GetInstanceByGUID(theLong4);
+ outList.push_back(theImageInstance);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.h b/src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.h
new file mode 100644
index 00000000..ac35ef37
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/DataModelObjectReferenceHelper.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_OBJECT_REFERENCE_HELPER_H
+#define INCLUDED_OBJECT_REFERENCE_HELPER_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "IObjectReferenceHelper.h"
+#include "UICDMHandles.h"
+
+//==============================================================================
+/**
+ * Implementation of IObjectReferenceHelper
+ * For now, this cross from the old client to new UICDM boundaries, and shield that logic from
+ *the actual control classes.
+ * Eventually, when all assets is converted to UICDM land, the meat of all these functions can
+ *change accordingly.
+ */
+class CObjectReferenceHelper : public IObjectReferenceHelper
+{
+public:
+ CObjectReferenceHelper(CDoc *inDoc);
+ ~CObjectReferenceHelper();
+
+ SObjectRefInfo GetInfo(const UICDM::CUICDMInstanceHandle &inInstance) const override;
+
+ virtual UICDM::TSlideHandleList
+ GetSlideList(const UICDM::CUICDMInstanceHandle inInstance) const override;
+ bool GetChildInstanceList(const UICDM::CUICDMInstanceHandle &inInstance,
+ UICDM::TInstanceHandleList &outList,
+ UICDM::CUICDMSlideHandle inSlide,
+ const UICDM::CUICDMInstanceHandle &inOwningInstance) const override;
+ virtual Q3DStudio::CString
+ LookupObjectFormalName(const UICDM::CUICDMInstanceHandle inInstance) const override;
+
+ virtual Q3DStudio::CString
+ GetObjectReferenceString(const UICDM::CUICDMInstanceHandle &inBaseInstance,
+ CRelativePathTools::EPathType inPathType,
+ const UICDM::CUICDMInstanceHandle &inInstance) const override;
+ bool ResolvePath(const UICDM::CUICDMInstanceHandle &inInstance,
+ const Q3DStudio::CString &inPathValue,
+ CRelativePathTools::EPathType &outType,
+ UICDM::CUICDMInstanceHandle &outResolveInstance) override;
+ virtual UICDM::CUICDMInstanceHandle
+ Resolve(const UICDM::SValue &inObjectRefValue,
+ const UICDM::CUICDMInstanceHandle &inBaseInstance) const override;
+
+ virtual UICDM::SObjectRefType
+ GetAssetRefValue(const UICDM::CUICDMInstanceHandle &inInstance,
+ const UICDM::CUICDMInstanceHandle &inBaseInstance,
+ CRelativePathTools::EPathType inPathType) const override;
+
+protected: // UICDM
+ void GetPropertyAsChildrenList(const UICDM::CUICDMInstanceHandle &inInstance,
+ UICDM::TInstanceHandleList &outList, long inSlideIndex) const;
+
+protected:
+ CDoc *m_Doc;
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Utility/DataTypesConverter.h b/src/Authoring/Client/Code/Core/Utility/DataTypesConverter.h
new file mode 100644
index 00000000..a17d5418
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/DataTypesConverter.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMDataTypes.h"
+#include "UICDMMetaData.h"
+#include "Vector2.h"
+#include "Rotation3.h"
+#include "Vector3.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+
+// Convenience functions to convert from CoreLibProject/Types Files to UICDMDataTypes
+inline UICDM::SValue ConvertToSValue(const Q3DStudio::CVector2 &inValue)
+{
+ UICDM::SFloat2 theFloat2;
+ theFloat2.m_Floats[0] = inValue.GetX();
+ theFloat2.m_Floats[1] = inValue.GetY();
+ return (UICDM::SValue(theFloat2));
+}
+inline UICDM::SValue ConvertToSValue(const Q3DStudio::CVector3 &inValue)
+{
+ UICDM::SFloat3 theFloat3;
+ theFloat3.m_Floats[0] = inValue.GetX();
+ theFloat3.m_Floats[1] = inValue.GetY();
+ theFloat3.m_Floats[2] = inValue.GetZ();
+ return (UICDM::SValue(theFloat3));
+}
+
+inline UICDM::SValue ConvertToSValue(const Q3DStudio::CRotation3 &inValue)
+{
+ UICDM::SFloat3 theFloat3;
+ theFloat3.m_Floats[0] = inValue.GetXDegrees();
+ theFloat3.m_Floats[1] = inValue.GetYDegrees();
+ theFloat3.m_Floats[2] = inValue.GetZDegrees();
+ return (UICDM::SValue(theFloat3));
+}
+
+inline UICDM::SValue ConvertToSValue(float inX, float inY)
+{
+ return (UICDM::SValue(UICDM::SFloat2(inX, inY)));
+}
+
+inline UICDM::SValue ConvertToSValue(float inX, float inY, float inZ)
+{
+ return (UICDM::SValue(UICDM::SFloat3(inX, inY, inZ)));
+}
+
+inline UICDM::SValue ConvertToSValue(const qt3ds::QT3DSVec2 &inValue)
+{
+ UICDM::SFloat2 theFloat2;
+ theFloat2.m_Floats[0] = inValue.x;
+ theFloat2.m_Floats[1] = inValue.y;
+ return (UICDM::SValue(theFloat2));
+}
+
+inline UICDM::SValue ConvertToSValue(const qt3ds::QT3DSVec3 &inValue)
+{
+ UICDM::SFloat3 theFloat3;
+ theFloat3.m_Floats[0] = inValue.x;
+ theFloat3.m_Floats[1] = inValue.y;
+ theFloat3.m_Floats[2] = inValue.z;
+ return (UICDM::SValue(theFloat3));
+}
+
+inline UICDM::SValue ConvertToSValue(const wchar_t *inValue)
+{
+ return UICDM::TDataStrPtr(new UICDM::CDataStr(inValue));
+}
+
+inline UICDM::SValue ConvertToSValue(const std::wstring &inValue)
+{
+ return UICDM::TDataStrPtr(new UICDM::CDataStr(inValue.c_str()));
+}
+
+inline UICDM::SValue ConvertToSValue(const char *inValue)
+{
+ return UICDM::TDataStrPtr(new UICDM::CDataStr(Q3DStudio::CString(inValue)));
+}
+
+inline UICDM::SValue ConvertToSValue(const Q3DStudio::CString &inValue)
+{
+ return UICDM::TDataStrPtr(new UICDM::CDataStr(inValue));
+}
+
+inline UICDM::TMetaDataStringList ConvertToStringList(Q3DStudio::CString inValue)
+{
+ // Convert the incoming string attribute into a list
+ UICDM::TMetaDataStringList theList;
+
+ Q3DStudio::CString theDelimiter(_UIC(","));
+ long theStartIndex = 0;
+ long theEndIndex = theStartIndex;
+ for (;;) {
+ theEndIndex = inValue.Find(theDelimiter, theStartIndex);
+ if (theEndIndex == Q3DStudio::CString::ENDOFSTRING)
+ break;
+ theList.push_back(inValue.Extract(theStartIndex, theEndIndex - theStartIndex).Unique());
+ theStartIndex = theEndIndex + 1;
+ }
+ if (inValue.Length() > 0) {
+ theList.push_back(inValue.Extract(theStartIndex).Unique());
+ }
+
+ return theList;
+}
+
+inline Q3DStudio::CString ConvertFromStringList(UICDM::TMetaDataStringList inList)
+{
+ size_t theNumListItems = inList.size();
+ Q3DStudio::CString theData = "";
+ if (theNumListItems > 0) {
+ for (UICDM::TMetaDataStringList::iterator theIterator = inList.begin();
+ theIterator != inList.end(); ++theIterator) {
+ theData += theIterator->c_str();
+ if (theIterator + 1 != inList.end())
+ theData += _UIC(",");
+ }
+ }
+ return theData;
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/GenericFunctor.h b/src/Authoring/Client/Code/Core/Utility/GenericFunctor.h
new file mode 100644
index 00000000..406227ae
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/GenericFunctor.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_GENERIC_FUNCTOR_H
+#define INCLUDED_GENERIC_FUNCTOR_H 1
+
+#pragma once
+
+#define CREATE_LISTENER(listenerClass, implementorClass, function) \
+ new CSpecific##listenerClass<implementorClass>(this, &implementorClass::function)
+
+#define GENERIC_FUNCTOR(FunctorName, FunctionName) \
+ class FunctorName \
+ { \
+ public: \
+ virtual void FunctionName() = 0; \
+ virtual ~FunctorName() {}; \
+ }; \
+ \
+ template <class TClass> \
+ class CSpecific##FunctorName : public FunctorName \
+ { \
+ public: \
+ typedef void (TClass::*TFunction)(); \
+ CSpecific##FunctorName(TClass *inObject, TFunction inFunction) \
+ { \
+ m_Object = inObject; \
+ m_Function = inFunction; \
+ } \
+ \
+ virtual void FunctionName() { (m_Object->*m_Function)(); } \
+ \
+ TClass *m_Object; \
+ void (TClass::*m_Function)(); \
+ };
+
+#define GENERIC_FUNCTOR_1(FunctorName, FunctionName, Arg1) \
+ class FunctorName \
+ { \
+ public: \
+ virtual void FunctionName(Arg1) = 0; \
+ virtual ~FunctorName() {}; \
+ }; \
+ \
+ template <class TClass> \
+ class CSpecific##FunctorName : public FunctorName \
+ { \
+ public: \
+ typedef void (TClass::*TFunction)(Arg1); \
+ CSpecific##FunctorName(TClass *inObject, void (TClass::*inFunction)(Arg1)) \
+ { \
+ m_Object = inObject; \
+ m_Function = inFunction; \
+ } \
+ \
+ virtual void FunctionName(Arg1 inArg1) { (m_Object->*m_Function)(inArg1); } \
+ \
+ TClass *m_Object; \
+ void (TClass::*m_Function)(Arg1); \
+ };
+
+#define GENERIC_FUNCTOR_2(FunctorName, FunctionName, Arg1, Arg2) \
+ class FunctorName \
+ { \
+ public: \
+ virtual void FunctionName(Arg1, Arg2) = 0; \
+ virtual ~FunctorName() {}; \
+ }; \
+ \
+ template <class TClass> \
+ class CSpecific##FunctorName : public FunctorName \
+ { \
+ public: \
+ CSpecific##FunctorName(TClass *inObject, void (TClass::*inFunction)(Arg1, Arg2)) \
+ { \
+ m_Object = inObject; \
+ m_Function = inFunction; \
+ } \
+ \
+ virtual void FunctionName(Arg1 inArg1, Arg2 inArg2) \
+ { \
+ (m_Object->*m_Function)(inArg1, inArg2); \
+ } \
+ \
+ TClass *m_Object; \
+ void (TClass::*m_Function)(Arg1, Arg2); \
+ };
+#endif // INCLUDED_GENERIC_FUNCTOR_H
diff --git a/src/Authoring/Client/Code/Core/Utility/HotKeys.cpp b/src/Authoring/Client/Code/Core/Utility/HotKeys.cpp
new file mode 100644
index 00000000..e9f2857b
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/HotKeys.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "HotKeys.h"
+#include "StringTokenizer.h"
+
+#include "Studio/_Win/UI/SceneView.h"
+#include "Studio/MainFrm.h"
+#include "Studio/Controls/TextEdit.h"
+#include "Studio/Controls/WidgetControl.h"
+
+#include <QGuiApplication>
+#include <QKeyEvent>
+#include <QtQuickWidgets/QQuickWidget>
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/QQuickItem>
+
+class KeyEventFilter : public QObject
+{
+public:
+ KeyEventFilter(CHotKeys* hotkeys)
+ : QObject(qApp)
+ , m_hotkeys(hotkeys)
+ {
+ }
+
+ bool eventFilter(QObject *watched, QEvent *event) override
+ {
+ if (qobject_cast<CSceneView *>(watched) == nullptr
+ && qobject_cast<CMainFrame *>(watched) == nullptr ) {
+ return false;
+ }
+
+ //ignore global shortcuts when we are in a text field
+ auto quickWidget = dynamic_cast<QQuickWidget *>(qApp->focusObject());
+ if (quickWidget) {
+ auto focusItem = quickWidget->quickWindow()->activeFocusItem();
+ if (focusItem) {
+ auto superClass = focusItem->metaObject()->superClass();
+ if (superClass && QByteArray(superClass->className()) == "QQuickTextField")
+ return false;
+ }
+
+ }
+
+ //ignore global shortcuts if we are in an "old" style textedit
+ if (m_hotkeys->isFocusOnTextEditControl())
+ return false;
+
+ switch (event->type()) {
+ case QEvent::ShortcutOverride:
+ case QEvent::KeyPress: {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ return m_hotkeys->OnKeyDown(ke->key(), ke->count(), ke->modifiers()) ||
+ m_hotkeys->OnChar(ke->key(), ke->count(), ke->modifiers());
+ }
+ case QEvent::KeyRelease: {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ return m_hotkeys->OnKeyUp(ke->key(), ke->count(), ke->modifiers());
+ }
+ default:
+ break;
+ }
+ return false;
+ }
+
+private:
+ CHotKeys* m_hotkeys;
+};
+
+//==============================================================================
+// Defines
+//==============================================================================
+
+IMPLEMENT_OBJECT_COUNTER(CHotKeys)
+
+//=============================================================================
+/**
+ * Constructor, nothing interesting.
+ */
+//=============================================================================
+CHotKeys::CHotKeys()
+ : m_CaptureKeys(false)
+{
+ ADDTO_OBJECT_COUNTER(CHotKeys)
+
+ m_EventFilter = new KeyEventFilter(this);
+ qApp->installEventFilter(m_EventFilter);
+}
+
+//=============================================================================
+/**
+ * Destructor, have to delete all the listeners.
+ * This is not the cleanest way to do this but, oh well.
+ */
+//=============================================================================
+CHotKeys::~CHotKeys()
+{
+ qApp->removeEventFilter(m_EventFilter);
+ this->ClearAllEvents();
+ REMOVEFROM_OBJECT_COUNTER(CHotKeys)
+}
+
+//=============================================================================
+/**
+ * Clears and deletes all the events from this.
+ */
+//=============================================================================
+void CHotKeys::ClearAllEvents()
+{
+ // Delete all the OnChar listeners
+ THotKeyMap::iterator theMapPos = m_KeyCharMap.begin();
+ for (; theMapPos != m_KeyCharMap.end(); ++theMapPos) {
+ THotKeyList::iterator theListPos = theMapPos->second.begin();
+ for (; theListPos != theMapPos->second.end(); ++theListPos) {
+ SHotKeyInfo *theInfo = (*theListPos);
+ delete theInfo->Consumer;
+ delete theInfo;
+ }
+ }
+
+ m_KeyCharMap.clear();
+
+ // Delete all the OnKeyDown listeners.
+ theMapPos = m_KeyDownMap.begin();
+ for (; theMapPos != m_KeyDownMap.end(); ++theMapPos) {
+ THotKeyList::iterator theListPos = theMapPos->second.begin();
+ for (; theListPos != theMapPos->second.end(); ++theListPos) {
+ SHotKeyInfo *theInfo = (*theListPos);
+ delete theInfo->Consumer;
+ delete theInfo;
+ }
+ }
+
+ m_KeyDownMap.clear();
+
+ // Delete all the OnKeyUp listeners.
+ theMapPos = m_KeyUpMap.begin();
+ for (; theMapPos != m_KeyUpMap.end(); ++theMapPos) {
+ THotKeyList::iterator theListPos = theMapPos->second.begin();
+ for (; theListPos != theMapPos->second.end(); ++theListPos) {
+ SHotKeyInfo *theInfo = (*theListPos);
+ delete theInfo->Consumer;
+ delete theInfo;
+ }
+ }
+
+ m_KeyUpMap.clear();
+}
+
+//=============================================================================
+/**
+ * Register a consumer to get called on the equivalent of OnChar.
+ * This will call the consumer when all the modifiers are met and the character
+ * has been received. If a modifier such as MOD_SHIFT is set but the key is not
+ * pressed then the consumer will not be called.
+ *
+ * If there are duplicate listeners for the same exact event the previous one
+ * will be removed.
+ *
+ * @param inConsumer the consumer to add for events, this will be deleted by this.
+ * @param inModifiers mask of keyboard modifiers- MOD_SHIFT, MOD_CONTROL, MOD_MENU...
+ * @param inCharacter the character the event is to occur on.
+ */
+//=============================================================================
+void CHotKeys::RegisterKeyEvent(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inCharacter)
+{
+ // Remove any previous consumers.
+ this->RemoveConsumers(inModifiers, inCharacter, &m_KeyCharMap);
+ this->InsertConsumer(inConsumer, inModifiers, inCharacter, &m_KeyCharMap);
+}
+
+//=============================================================================
+/**
+ * Register a consumer to get called on the equivalent of OnKeyDown.
+ * This will call the consumer when all the modifiers are met and the character
+ * has been received. If a modifier such as MOD_SHIFT is set but the key is not
+ * pressed then the consumer will not be called.
+ *
+ * If there are duplicate listeners for the same exact event the previous one
+ * will be removed.
+ *
+ * @param inConsumer the consumer to add for events, this will be deleted by this.
+ * @param inModifiers mask of keyboard modifiers- MOD_SHIFT, MOD_CONTROL, MOD_MENU...
+ * @param inVirtualKey the virtualkey the event is to occur on.
+ */
+//=============================================================================
+void CHotKeys::RegisterKeyDownEvent(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inVirtualKey)
+{
+ // Remove any previous consumers.
+ this->RemoveConsumers(inModifiers, inVirtualKey, &m_KeyDownMap);
+ this->InsertConsumer(inConsumer, inModifiers, inVirtualKey, &m_KeyDownMap);
+}
+
+//=============================================================================
+/**
+ * Register a consumer to get called on the equivalent of OnKeyUp.
+ * This will call the consumer when all the modifiers are met and the character
+ * has been received. If a modifier such as MOD_SHIFT is set but the key is not
+ * pressed then the consumer will not be called.
+ *
+ * If there are duplicate listeners for the same exact event the previous one
+ * will be removed.
+ *
+ * @param inConsumer the consumer to add for events, this will be deleted by this.
+ * @param inModifiers mask of keyboard modifiers- MOD_SHIFT, MOD_CONTROL, MOD_MENU...
+ * @param inVirtualKey the virtualkey the event is to occur on.
+ */
+//=============================================================================
+void CHotKeys::RegisterKeyUpEvent(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inVirtualKey)
+{
+ // Remove any previous consumers.
+ this->RemoveConsumers(inModifiers, inVirtualKey, &m_KeyUpMap);
+ this->InsertConsumer(inConsumer, inModifiers, inVirtualKey, &m_KeyUpMap);
+}
+
+//=============================================================================
+/**
+ * Register a consumer to get called on the equivalent of OnChar.
+ * This will call the consumer when all the modifiers are met and the character
+ * has been received. If a modifier such as MOD_SHIFT is set but the key is not
+ * pressed then the consumer will not be called.
+ *
+ * If there are duplicate listeners for the same exact event the previous one
+ * will be removed.
+ *
+ * @param inConsumer the consumer to which to add this key
+ * @param inString the string containing key/mods. This needs to be in the form of
+ *key/:Mod/,Mod/,Mod ie x/:ctrl/,shift
+ * see IDS_HK_SEPARATOR & IDS_HK_MOD_SEPARATOR & IDS_HK_CTRL -
+ *IDS_HK_ALPHALOCK for useful info in creating these strings
+ */
+void CHotKeys::RegisterKeyEvent(CHotKeyConsumer *inConsumer, const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifiers theMod;
+ int theKey;
+ GetModAndKeyFromString(inString, theMod, theKey);
+
+ RegisterKeyEvent(inConsumer, theMod, theKey);
+}
+
+//=============================================================================
+/**
+ * Register a consumer to get called on the equivalent of OnKeyDown.
+ * This will call the consumer when all the modifiers are met and the character
+ * has been received. If a modifier such as MOD_SHIFT is set but the key is not
+ * pressed then the consumer will not be called.
+ *
+ * If there are duplicate listeners for the same exact event the previous one
+ * will be removed.
+ *
+ */
+void CHotKeys::RegisterKeyDownEvent(CHotKeyConsumer *inConsumer, const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifiers theMod;
+ int theVirtualKey;
+ GetModAndKeyFromString(inString, theMod, theVirtualKey);
+
+ RegisterKeyDownEvent(inConsumer, theMod, theVirtualKey);
+}
+
+//=============================================================================
+/**
+ * Register a consumer to get called on the equivalent of OnKeyUp.
+ * This will call the consumer when all the modifiers are met and the character
+ * has been received. If a modifier such as MOD_SHIFT is set but the key is not
+ * pressed then the consumer will not be called.
+ *
+ * If there are duplicate listeners for the same exact event the previous one
+ * will be removed.
+ *
+ */
+void CHotKeys::RegisterKeyUpEvent(CHotKeyConsumer *inConsumer, const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifiers theMod;
+ int theVirtualKey;
+ GetModAndKeyFromString(inString, theMod, theVirtualKey);
+
+ RegisterKeyUpEvent(inConsumer, theMod, theVirtualKey);
+}
+
+//=============================================================================
+/**
+ * Remove a previous key char event.
+ * This removes a consumer from the list of events, the consumer is also deleted.
+ *
+ * @param inModifiers the modifiers for the event.
+ * @param inCharacter the character for the event.
+ */
+//=============================================================================
+void CHotKeys::UnregisterKeyEvent(Qt::KeyboardModifiers inModifiers, int inCharacter)
+{
+ this->RemoveConsumers(inModifiers, inCharacter, &m_KeyCharMap);
+}
+
+//=============================================================================
+/**
+ * Remove a previous key down event.
+ * This removes a consumer from the list of events, the consumer is also deleted.
+ *
+ * @param inModifiers the modifiers for the event.
+ * @param inVirtualKey the virtualkey for the event.
+ */
+//=============================================================================
+void CHotKeys::UnregisterKeyDownEvent(Qt::KeyboardModifiers inModifiers, int inVirtualKey)
+{
+ this->RemoveConsumers(inModifiers, inVirtualKey, &m_KeyDownMap);
+}
+
+//=============================================================================
+/**
+ * Remove a previous key up event.
+ * This removes a consumer from the list of events, the consumer is also deleted.
+ *
+ * @param inModifiers the modifiers for the event.
+ * @param inVirtualKey the virtualkey for the event.
+ */
+//=============================================================================
+void CHotKeys::UnregisterKeyUpEvent(Qt::KeyboardModifiers inModifiers, int inVirtualKey)
+{
+ this->RemoveConsumers(inModifiers, inVirtualKey, &m_KeyUpMap);
+}
+
+void CHotKeys::UnregisterKeyEvent(const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifiers theMod;
+ int theKey;
+ GetModAndKeyFromString(inString, theMod, theKey);
+
+ UnregisterKeyEvent(theMod, theKey);
+}
+
+void CHotKeys::UnregisterKeyDownEvent(const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifiers theMod;
+ int theVirtualKey;
+ GetModAndKeyFromString(inString, theMod, theVirtualKey);
+
+ UnregisterKeyDownEvent(theMod, theVirtualKey);
+}
+
+void CHotKeys::UnregisterKeyUpEvent(const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifiers theMod;
+ int theVirtualKey;
+ GetModAndKeyFromString(inString, theMod, theVirtualKey);
+
+ UnregisterKeyUpEvent(theMod, theVirtualKey);
+}
+
+//=============================================================================
+/**
+ * Called by owner window on a WM_CHAR event.
+ *
+ * @param inChar the character received.
+ * @param inRepeatCount the repeat count.
+ * @param inFlags the flags.
+ */
+//=============================================================================
+bool CHotKeys::OnChar(int inChar, int inRepeatCount, Qt::KeyboardModifiers inFlags)
+{
+ return FireEvent(inChar, inRepeatCount, inFlags, &m_KeyCharMap);
+}
+
+//=============================================================================
+/**
+ * Called by owner window on a WM_KEYDOWN event.
+ *
+ * @param inChar the character received.
+ * @param inRepeatCount the repeat count.
+ * @param inFlags the flags.
+ */
+//=============================================================================
+bool CHotKeys::OnKeyDown(int inVirtualKey, int inRepeatCount,
+ Qt::KeyboardModifiers modifiers)
+{
+ return FireEvent(inVirtualKey, inRepeatCount, modifiers, &m_KeyDownMap);
+}
+
+//=============================================================================
+/**
+ * Called by owner window on a WM_KEYUP event.
+ *
+ * @param inChar the character received.
+ * @param inRepeatCount the repeat count.
+ * @param inFlags the flags.
+ */
+//=============================================================================
+bool CHotKeys::OnKeyUp(int inVirtualKey, int inRepeatCount, Qt::KeyboardModifiers modifiers)
+{
+ return FireEvent(inVirtualKey, inRepeatCount, modifiers, &m_KeyUpMap);
+}
+
+//=============================================================================
+/**
+ * Helper function for adding consumers to the map.
+ *
+ * @param inConsumer the consumer to be added.
+ * @param inModifiers the keyboard modifiers.
+ * @param inCharacter the character to be pressed.
+ * @param inMap the map the consumer is to be added to.
+ */
+//=============================================================================
+void CHotKeys::InsertConsumer(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inCharacter, THotKeyMap *inMap)
+{
+ SHotKeyInfo *theInfo = new SHotKeyInfo;
+ theInfo->Consumer = inConsumer;
+ theInfo->Character = inCharacter;
+ theInfo->Modifiers = inModifiers;
+
+ THotKeyMap::iterator theMapPos = inMap->find(inCharacter);
+ // There is already a list, just add this one to it.
+ if (theMapPos != inMap->end()) {
+ theMapPos->second.push_back(theInfo);
+ } else {
+ // Add a new list to the map
+ THotKeyList theList;
+ theList.push_back(theInfo);
+ inMap->insert(std::pair<unsigned int, THotKeyList>(inCharacter, theList));
+ }
+}
+
+//=============================================================================
+/**
+ * Remove all the consumers listening for the specified event.
+ *
+ * @param inModifiers the keyboard modifiers.
+ * @param inCharacter the character to be pressed.
+ * @param inMap the map to remove the consumers from.
+ */
+//=============================================================================
+void CHotKeys::RemoveConsumers(Qt::KeyboardModifiers inModifiers, int inCharacter,
+ THotKeyMap *inMap)
+{
+ THotKeyMap::iterator theMapPos = inMap->find(inCharacter);
+ if (theMapPos != inMap->end()) {
+ THotKeyList::iterator theListPos = theMapPos->second.begin();
+ while (theListPos != theMapPos->second.end()) {
+ if ((*theListPos)->Modifiers == inModifiers) {
+ SHotKeyInfo *theInfo = (*theListPos);
+ delete theInfo->Consumer;
+ delete theInfo;
+
+ theListPos = theMapPos->second.erase(theListPos);
+ } else
+ ++theListPos;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Fire off an event for the specified char.
+ * This will go through the map for the event and find all applicable consumers
+ * then call OnHotKeyEvent on that consumer.
+ *
+ * @param inChar the character that was pressed.
+ * @param inRepeatCount the number of times the character was pressed.
+ * @param inFlags the flags from the WM_KEY* call.
+ * @param inMap the map to find the consumers in.
+ * @return true if the event was dispatched.
+ */
+//=============================================================================
+bool CHotKeys::FireEvent(int inChar, int inRepeatCount, Qt::KeyboardModifiers modifiers,
+ THotKeyMap *inMap)
+{
+ bool theRetVal = false;
+
+ // Get the state of the keys before iterating through the key events. If a key event takes a
+ // while to
+ // be dispatched then the state of the modifier key may change and will cause incorrect results.
+ unsigned int isMenuDown = modifiers & Qt::AltModifier;
+ unsigned int isControlDown = modifiers & Qt::ControlModifier;
+ unsigned int isShiftDown = modifiers & Qt::ShiftModifier;
+
+ // If the keys are captured by a window and not modified, then don't send this
+ // event to the registered consumers. This is mainly a hack to allow the command
+ // window to work properly.
+ if (m_CaptureKeys && !(isMenuDown || isControlDown || isShiftDown))
+ return false;
+
+ // Find the list of consumers for inChar
+ THotKeyMap::iterator theMapPos = inMap->find(inChar);
+ if (theMapPos != inMap->end()) {
+ // Go through all the consumers checking if their key modifiers are met
+ THotKeyList::iterator theListPos = theMapPos->second.begin();
+ for (; theListPos != theMapPos->second.end(); ++theListPos) {
+ SHotKeyInfo *theHotKeyInfo = *theListPos;
+ // Check to see if the modifier is set and the key is down or neither of them are set
+ // for each of the modifiers.
+ if ((isMenuDown == (theHotKeyInfo->Modifiers & Qt::AltModifier))
+ && (isControlDown == (theHotKeyInfo->Modifiers & Qt::ControlModifier))
+ && (isShiftDown == (theHotKeyInfo->Modifiers & Qt::ShiftModifier))) {
+ // If all the modifiers are correct then call the event.
+ theRetVal = theHotKeyInfo->Consumer->OnHotKeyEvent(inChar, inRepeatCount, modifiers);
+ }
+ }
+ }
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Indicates whether the specified key is currently down or not.
+ * @param inKeyCode The key to be checked
+ * @return true if the key is down, otherwise false
+ */
+bool CHotKeys::IsKeyDown(Qt::KeyboardModifier inKeyCode)
+{
+ return qApp->keyboardModifiers() & inKeyCode;
+}
+
+//=============================================================================
+/**
+ * Retrieves the current status of the various modifier keys.
+ * @return flag containing all of the modifier keys that are currently depressed
+ */
+Qt::KeyboardModifiers CHotKeys::GetCurrentKeyModifiers()
+{
+ return qApp->keyboardModifiers();
+}
+
+bool CHotKeys::isFocusOnTextEditControl()
+{
+ auto widgetControl = dynamic_cast<WidgetControl *>(qApp->focusObject());
+ if (widgetControl) {
+ auto control = widgetControl->getControl();
+ if (control && dynamic_cast<CTextEdit *>(control->FocusedChild()))
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * returns the mod and key.... mod will include all mods that came in comma delimeted
+ *
+ * @param inString a string containing a key combo to parse
+ */
+void CHotKeys::GetModAndKeyFromString(const Q3DStudio::CString &inString, Qt::KeyboardModifiers &inMod,
+ int &inKey)
+{
+ inMod = 0;
+ inKey = 0;
+ CStringTokenizer theTokenizer(inString, L"/:"); // TODO: Localize
+ Q3DStudio::CString theMods = theTokenizer.GetCurrentPartition();
+ ++theTokenizer;
+ Q3DStudio::CString theKey = theTokenizer.GetCurrentPartition();
+ CStringTokenizer theModTokenizer(theMods, L"/,"); // TODO: Localize
+ while (theModTokenizer.HasNextPartition()) {
+ Q3DStudio::CString theCurrentMod = theModTokenizer.GetCurrentPartition();
+ inMod |= GetModifierFromString(theCurrentMod);
+ ++theModTokenizer;
+ }
+ inKey = GetKeyFromString(theKey);
+}
+
+//=============================================================================
+/**
+ * returns the unsigned int equivalent of a string modifer type
+ *
+ * @param inString a string containing a modifier
+ */
+Qt::KeyboardModifier CHotKeys::GetModifierFromString(const Q3DStudio::CString &inString)
+{
+ Qt::KeyboardModifier theRetVal = Qt::NoModifier;
+
+#ifndef WIN32
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (inString == ::LoadResourceString(IDS_HK_CMD))
+ theRetVal = MODIFIER_COMMAND;
+ else if (inString == ::LoadResourceString(IDS_HK_ALPHALOCK))
+ theRetVal = MODIFIER_CAPS;
+#endif
+#endif
+ if (inString == L"ctrl") // TODO: Localize
+ theRetVal = Qt::ControlModifier;
+ else if (inString == L"shift") // TODO: Localize
+ theRetVal = Qt::ShiftModifier;
+ else if (inString == L"alt") // TODO: Localize
+ theRetVal = Qt::AltModifier;
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Finds a character or a unicode key depending on lenght of the string
+ *
+ * @param inChar the ascii or key code for the char
+ */
+int CHotKeys::GetKeyFromString(Q3DStudio::CString inChar)
+{
+ int theRetVal = 0;
+ if (inChar.Length() == 1) {
+ Q3DStudio::CString theLowerCase = inChar.ToLower();
+ char theChar = static_cast<char>(theLowerCase[(long)0]);
+ theRetVal = theChar;
+ } else if (inChar.Length() > 1) {
+ theRetVal = atoi(inChar.GetCharStar());
+ }
+ return theRetVal;
+}
+
+void CHotKeys::CaptureHotKeys()
+{
+ m_CaptureKeys = true;
+}
+
+void CHotKeys::ReleaseHotKeys()
+{
+ m_CaptureKeys = false;
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/HotKeys.h b/src/Authoring/Client/Code/Core/Utility/HotKeys.h
new file mode 100644
index 00000000..865fd0d8
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/HotKeys.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_HOT_KEYS_H
+#define INCLUDED_HOT_KEYS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+#include "UICObjectCounter.h"
+
+#include <QtGlobal>
+
+class KeyEventFilter;
+
+//=============================================================================
+/**
+ * Pure-Virtual class for destination of key events.
+ */
+//=============================================================================
+class CHotKeyConsumer
+{
+public:
+ virtual ~CHotKeyConsumer() = default;
+ virtual bool OnHotKeyEvent(int inChar, int inRepeatCount,
+ Qt::KeyboardModifiers modifiers) = 0;
+};
+
+//=============================================================================
+/**
+ * Dynamic implementation of CHotKeyConsumer to route events to functions.
+ */
+//=============================================================================
+template <class Fixture>
+class CDynHotKeyConsumer : public CHotKeyConsumer
+{
+ typedef void (Fixture::*TEventMethod)();
+ typedef bool (Fixture::*TSmartEventMethod)(int inChar, int inRepeatCount,
+ Qt::KeyboardModifiers modifiers);
+ typedef bool (Fixture::*TBoolEventMethod)();
+ typedef int (Fixture::*TIntEventMethod)();
+
+public:
+ //==========================================================================
+ /**
+ * Create a HotKeyConsumer mapping the event to a function with no arguments.
+ *
+ * @param inObject the object the method is to be called on.
+ * @param inEventMethod the method that is to be called.
+ */
+ //==========================================================================
+ CDynHotKeyConsumer(Fixture *inObject, TEventMethod inEventMethod)
+ {
+ m_Object = inObject;
+ m_Method = inEventMethod;
+ m_SmartMethod = NULL;
+ m_BoolMethod = NULL;
+ m_IntMethod = NULL;
+ }
+
+ //==========================================================================
+ /**
+ * Create a HotKeyConsumer mapping the event to a function with normal key args.
+ *
+ * @param inObject the object the method is to be called on.
+ * @param inEventMethod the method that is to be called.
+ */
+ //==========================================================================
+ CDynHotKeyConsumer(Fixture *inObject, TSmartEventMethod inEventMethod)
+ {
+ m_Object = inObject;
+ m_Method = NULL;
+ m_SmartMethod = inEventMethod;
+ m_BoolMethod = NULL;
+ m_IntMethod = NULL;
+ }
+
+ CDynHotKeyConsumer(Fixture *inObject, TBoolEventMethod inEventMethod)
+ {
+ m_Object = inObject;
+ m_Method = NULL;
+ m_SmartMethod = NULL;
+ m_BoolMethod = inEventMethod;
+ m_IntMethod = NULL;
+ }
+
+ //==========================================================================
+ /**
+ * Create a HotKeyConsumer mapping the event to a function with normal key args.
+ *
+ * @param inObject the object the method is to be called on.
+ * @param inEventMethod the method that is to be called.
+ */
+ //==========================================================================
+ CDynHotKeyConsumer(Fixture *inObject, TIntEventMethod inEventMethod)
+ {
+ m_Object = inObject;
+ m_Method = NULL;
+ m_SmartMethod = NULL;
+ m_BoolMethod = NULL;
+ m_IntMethod = inEventMethod;
+ }
+
+ //==========================================================================
+ /**
+ * Copy constructor.
+ */
+ //==========================================================================
+ CDynHotKeyConsumer(const CDynHotKeyConsumer &inConsumer)
+ {
+ m_Object = inConsumer.m_Object;
+ m_Method = inConsumer.m_Method;
+ m_SmartMethod = inConsumer.m_SmartMethod;
+ }
+
+ //==========================================================================
+ /**
+ * This gets called on a registered key event, and in turn calls the function
+ * that this was created with.
+ *
+ * @see WM_KEYDOWN for argument descriptions.
+ */
+ //==========================================================================
+ bool OnHotKeyEvent(int inChar, int inRepeatCount,
+ Qt::KeyboardModifiers modifiers) override
+ {
+ bool theRetVal = true;
+
+ // Determine which method to call...
+ if (m_Method != NULL)
+ (m_Object->*m_Method)();
+ else if (m_SmartMethod != NULL)
+ theRetVal = (m_Object->*m_SmartMethod)(inChar, inRepeatCount, modifiers);
+ else if (m_BoolMethod != NULL)
+ theRetVal = (m_Object->*m_BoolMethod)();
+ else
+ (m_Object->*m_IntMethod)();
+
+ return theRetVal;
+ }
+
+protected:
+ Fixture *m_Object;
+ TEventMethod m_Method;
+ TBoolEventMethod m_BoolMethod;
+ TIntEventMethod m_IntMethod;
+ TSmartEventMethod m_SmartMethod;
+};
+
+class CHotKeys
+{
+public:
+ enum Modifier {
+
+ MODIFIER_CONTROL = Qt::ControlModifier,
+ MODIFIER_SHIFT = Qt::ShiftModifier,
+ MODIFIER_ALT = Qt::AltModifier,
+
+ MOUSE_LBUTTON = 0x100000,
+ MOUSE_MBUTTON = 0x200000,
+ MOUSE_RBUTTON = 0x400000
+ };
+ Q_DECLARE_FLAGS(Modifiers, Modifier)
+
+public:
+ CHotKeys();
+ ~CHotKeys();
+
+ DEFINE_OBJECT_COUNTER(CHotKeys)
+
+ void RegisterKeyEvent(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inCharacter);
+ void RegisterKeyDownEvent(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inVirtualKey);
+ void RegisterKeyUpEvent(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inVirtualKey);
+
+ void RegisterKeyEvent(CHotKeyConsumer *inConsumer, const Q3DStudio::CString &inString);
+ void RegisterKeyDownEvent(CHotKeyConsumer *inConsumer, const Q3DStudio::CString &inString);
+ void RegisterKeyUpEvent(CHotKeyConsumer *inConsumer, const Q3DStudio::CString &inString);
+
+ void UnregisterKeyEvent(Qt::KeyboardModifiers inModifiers, int inCharacter);
+ void UnregisterKeyDownEvent(Qt::KeyboardModifiers inModifiers, int inVirtualKey);
+ void UnregisterKeyUpEvent(Qt::KeyboardModifiers inModifiers, int inVirtualKey);
+
+ void UnregisterKeyEvent(const Q3DStudio::CString &inString);
+ void UnregisterKeyDownEvent(const Q3DStudio::CString &inString);
+ void UnregisterKeyUpEvent(const Q3DStudio::CString &inString);
+
+ bool OnChar(int inChar, int inRepeatCount, Qt::KeyboardModifiers modifiers);
+ bool OnKeyDown(int inChar, int inRepeatCount, Qt::KeyboardModifiers modifiers);
+ bool OnKeyUp(int inChar, int inRepeatCount, Qt::KeyboardModifiers modifiers);
+
+ void ClearAllEvents();
+
+ void CaptureHotKeys();
+ void ReleaseHotKeys();
+
+ static bool IsKeyDown(Qt::KeyboardModifier inKeyCode);
+ static Qt::KeyboardModifiers GetCurrentKeyModifiers();
+ static bool isFocusOnTextEditControl();
+
+protected:
+ struct SHotKeyInfo
+ {
+ CHotKeyConsumer *Consumer;
+ int Character;
+ Qt::KeyboardModifiers Modifiers;
+ };
+
+ typedef std::vector<SHotKeyInfo *> THotKeyList;
+ typedef std::map<unsigned int, THotKeyList> THotKeyMap;
+
+ THotKeyMap m_KeyCharMap;
+ THotKeyMap m_KeyDownMap;
+ THotKeyMap m_KeyUpMap;
+ KeyEventFilter *m_EventFilter;
+ bool m_CaptureKeys; ///< Boolean that ignores all non-modified keys
+
+ void InsertConsumer(CHotKeyConsumer *inConsumer, Qt::KeyboardModifiers inModifiers,
+ int inCharacter, THotKeyMap *inMap);
+ void RemoveConsumers(Qt::KeyboardModifiers inModifiers, int inCharacter, THotKeyMap *inMap);
+ bool FireEvent(int inChar, int inRepeatCount, Qt::KeyboardModifiers modifiers,
+ THotKeyMap *inMap);
+ Qt::KeyboardModifier GetModifierFromString(const Q3DStudio::CString &inString);
+ int GetKeyFromString(Q3DStudio::CString inChar);
+ void GetModAndKeyFromString(const Q3DStudio::CString &inString, Qt::KeyboardModifiers &inMod,
+ int &inKey);
+};
+#endif // INCLUDED_HOT_KEYS_H
diff --git a/src/Authoring/Client/Code/Core/Utility/IDirectoryWatchingSystem.h b/src/Authoring/Client/Code/Core/Utility/IDirectoryWatchingSystem.h
new file mode 100644
index 00000000..21a565ed
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/IDirectoryWatchingSystem.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef IDIRECTORYWATCHINGSYSTEMH
+#define IDIRECTORYWATCHINGSYSTEMH
+#include <vector>
+#include <QtCore/qstring.h>
+
+namespace UICDM {
+class ISignalConnection;
+}
+
+namespace Q3DStudio {
+struct SFileModificationRecord;
+
+typedef std::function<void(const std::vector<SFileModificationRecord> &)> TFileModCallbackType;
+// A function that takes no arguments and returns nothing.
+typedef std::function<void(void)> TCallbackFunc;
+typedef std::function<void(TCallbackFunc)> TCallbackCaller;
+
+// Wrap the file path system for finding directory differences with a nice wrapper that takes care
+// of
+// using an event to cut down on the number of times we query the file path API.
+class IDirectoryWatchingSystem
+{
+protected:
+ virtual ~IDirectoryWatchingSystem() {}
+public:
+ // Add this directory to the system. Clients will get an *immediate* callback with all of the
+ // files underneath this directory listed as created. They will then get callbacks as files
+ // change.
+ // All of the callbacks, for now, are in the UI thread so you don't need to bounce off the
+ // message router.
+ // This will remain constant even if we move the query into another thread (which really isn't
+ // likely).
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ AddDirectory(const QString &inDirectory, TFileModCallbackType inCallback) = 0;
+
+ friend class std::shared_ptr<IDirectoryWatchingSystem>;
+ /**
+ * Create a directory watcher that signals to listeners via the callback caller that things
+ *have changed.
+ * The callback caller is expected to execute the provided callback func in the UI thread.
+ */
+ static std::shared_ptr<IDirectoryWatchingSystem>
+ CreateThreadedDirectoryWatchingSystem(TCallbackCaller inCaller);
+};
+}
+#endif
diff --git a/src/Authoring/Client/Code/Core/Utility/IObjectReferenceHelper.h b/src/Authoring/Client/Code/Core/Utility/IObjectReferenceHelper.h
new file mode 100644
index 00000000..2163886d
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/IObjectReferenceHelper.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_IOBJECT_REFERENCE_HELPER_H
+#define INCLUDED_IOBJECT_REFERENCE_HELPER_H 1
+
+#pragma once
+
+#include "RelativePathTools.h"
+#include "StudioObjectTypes.h"
+#include "UICDMHandles.h"
+#include "UICDMValue.h"
+
+//==============================================================================
+/**
+ * Interface to abstract data model specific logic.
+ */
+class IObjectReferenceHelper
+{
+public:
+ struct SObjectRefInfo
+ {
+ Q3DStudio::CString m_Name;
+ EStudioObjectType m_Type;
+ bool m_Master;
+
+ SObjectRefInfo(Q3DStudio::CString inName, EStudioObjectType inType, bool inMaster)
+ : m_Name(inName)
+ , m_Type(inType)
+ , m_Master(inMaster)
+ {
+ }
+ SObjectRefInfo()
+ : m_Type(OBJTYPE_UNKNOWN)
+ , m_Master(false)
+ {
+ }
+ };
+
+public:
+ virtual ~IObjectReferenceHelper() {}
+
+public:
+ virtual SObjectRefInfo GetInfo(const UICDM::CUICDMInstanceHandle &inInstance) const = 0;
+
+ virtual UICDM::TSlideHandleList
+ GetSlideList(const UICDM::CUICDMInstanceHandle inInstance) const = 0;
+ virtual bool
+ GetChildInstanceList(const UICDM::CUICDMInstanceHandle &inInstance,
+ UICDM::TInstanceHandleList &outlist, UICDM::CUICDMSlideHandle inSlide,
+ const UICDM::CUICDMInstanceHandle &inOwningInstance) const = 0;
+ virtual Q3DStudio::CString
+ LookupObjectFormalName(const UICDM::CUICDMInstanceHandle inInstance) const = 0;
+
+ virtual Q3DStudio::CString
+ GetObjectReferenceString(const UICDM::CUICDMInstanceHandle &inBaseInstance,
+ CRelativePathTools::EPathType inPathType,
+ const UICDM::CUICDMInstanceHandle &inInstance) const = 0;
+ virtual bool ResolvePath(const UICDM::CUICDMInstanceHandle &inInstance,
+ const Q3DStudio::CString &inPathValue,
+ CRelativePathTools::EPathType &outType,
+ UICDM::CUICDMInstanceHandle &outResolvedInstance) = 0;
+ virtual UICDM::CUICDMInstanceHandle
+ Resolve(const UICDM::SValue &inObjectRefValue,
+ const UICDM::CUICDMInstanceHandle &inBaseInstance) const = 0;
+ virtual UICDM::SObjectRefType
+ GetAssetRefValue(const UICDM::CUICDMInstanceHandle &inInstance,
+ const UICDM::CUICDMInstanceHandle &inBaseInstance,
+ CRelativePathTools::EPathType inPathType) const = 0;
+};
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.cpp b/src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.cpp
new file mode 100644
index 00000000..83dbff71
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.cpp
@@ -0,0 +1,755 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "StdAfx.h"
+
+#include <math.h>
+#include <float.h>
+
+#include "OptimizedArithmetic.h"
+#include "Matrix.h"
+
+#ifdef WIN32
+#include "cpuid.h"
+#endif
+
+#include "UICMath.h"
+
+void SSE_MatrixMultiply(const float *inSource1, const float *inSource2, float *outDest);
+void C_MatrixMultiply(const float *inSource1, const float *inSource2, float *outDest);
+bool C_IntersectTriangle(bool inUseFrontface, bool inUseBackface, const float *inOrig,
+ const float *inDirection, const float *inTestV0, const float *inTestV1,
+ const float *inTestV2, float *outIntersection, float *outIntersectOffset);
+void C_TransformBoundingBox(float *ioMinBox, float *ioMaxBox, const float *inTransform);
+
+// Static initializers of all the available functions.
+// These should all default to the most common implementation (C most likely).
+FMatrixMultiply COptimizedArithmetic::MatrixMultiply(C_MatrixMultiply);
+FIntersectTriangle COptimizedArithmetic::IntersectTriangle(C_IntersectTriangle);
+FTransformBoundingBox COptimizedArithmetic::TransformBoundingBox(C_TransformBoundingBox);
+
+// Static initializer which allows auto-initialization.
+COptArithInitializer COptimizedArithmetic::m_Initializer;
+
+//==============================================================================
+/**
+ * Constructor of the auto-initializer, this just initializes COptimizedArithmetic.
+ * This should only be called automatically by the static on COptimizedArithmetic.
+ */
+COptArithInitializer::COptArithInitializer()
+{
+ COptimizedArithmetic::Initialize();
+}
+
+//==============================================================================
+/**
+ * Private constructor, does nothing. Unnecessary since the class is all static.
+ */
+COptimizedArithmetic::COptimizedArithmetic()
+{
+}
+
+COptimizedArithmetic::~COptimizedArithmetic()
+{
+}
+
+//==============================================================================
+/**
+ * Initializes all the potential optimized functions and determines which methods
+ * to use.
+ */
+void COptimizedArithmetic::Initialize()
+{
+ if (HasSSE())
+ MatrixMultiply = SSE_MatrixMultiply;
+ else
+ MatrixMultiply = C_MatrixMultiply;
+
+ IntersectTriangle = C_IntersectTriangle;
+ TransformBoundingBox = C_TransformBoundingBox;
+}
+
+//==============================================================================
+/**
+ * Checks to see if MMX is available.
+ * This will check if the processor has the feature and the OS supports it.
+ * @return true if MMX is supported.
+ */
+bool COptimizedArithmetic::HasMMX()
+{
+ bool hasMMX = false;
+#ifdef WIN32
+ _p_info info;
+ _cpuid(&info);
+
+ hasMMX = (info.feature & _CPU_FEATURE_MMX) && (info.checks & _CPU_FEATURE_MMX)
+ && (info.os_support & _CPU_FEATURE_MMX);
+#endif
+ return hasMMX;
+}
+
+//==============================================================================
+/**
+ * Checks to see if SSE is available.
+ * This will check if the processor has the feature and the OS supports it.
+ * @return true if SSE is supported.
+ */
+bool COptimizedArithmetic::HasSSE()
+{
+ bool hasSSE = false;
+#if defined(WIN32) && !defined(_AMD64_)
+ _p_info info;
+ _cpuid(&info);
+
+ hasSSE = (info.feature & _CPU_FEATURE_SSE) && (info.checks & _CPU_FEATURE_SSE)
+ && (info.os_support & _CPU_FEATURE_SSE);
+#endif
+ return hasSSE;
+}
+
+//==============================================================================
+/**
+ * Checks to see if SSE2 is available.
+ * This will check if the processor has the feature and the OS supports it.
+ * @return true if SSE2 is supported.
+ */
+bool COptimizedArithmetic::HasSSE2()
+{
+ bool hasSSE2 = false;
+#if defined(WIN32) && !defined(_AMD64_)
+ _p_info info;
+ _cpuid(&info);
+
+ hasSSE2 = (info.feature & _CPU_FEATURE_SSE2) && (info.checks & _CPU_FEATURE_SSE2)
+ && (info.os_support & _CPU_FEATURE_SSE2);
+#endif
+ return hasSSE2;
+}
+
+//==============================================================================
+/**
+ * Checks to see if 3DNow! is available.
+ * This will check if the processor has the feature and the OS supports it.
+ * @return true if 3DNow! is supported.
+ */
+bool COptimizedArithmetic::Has3DNow()
+{
+ bool has3DNow = false;
+#if defined(WIN32) && !defined(_AMD64_)
+ _p_info info;
+ _cpuid(&info);
+
+ has3DNow = (info.feature & _CPU_FEATURE_3DNOW) && (info.checks & _CPU_FEATURE_3DNOW)
+ && (info.os_support & _CPU_FEATURE_3DNOW);
+#endif
+ return has3DNow;
+}
+
+#if defined(WIN32) && !defined(_AMD64_)
+//==============================================================================
+/**
+ * The following code is part of an SSE matrix multiplication algorithm developed
+ * by Intel. The original document can be found at:
+ * http://cedar.intel.com/media/pdf/appnotes/ap930/24504501.pdf
+ * The document is titled: Streaming 'SIMD Extensions- Matrix Multiplication'
+ */
+//==============================================================================
+
+// Offset for mat[i][j], w is an row width, t == 1 for transposed access.
+#define mi(w, t, i, j) 4 * ((i * w + j) * (1 - t) + (j * w + i) * t)
+
+// Load & multiply.
+#define flm(k, i, j, m, n, a, b) \
+ __asm fld dword ptr[edx + mi(m, a, i, k)] __asm fmul dword ptr[ecx + mi(n, b, k, j)]
+
+#define e4(i, j, l, m, n, a, b) \
+ flm(0, i, j, m, n, a, b) flm(1, i, j, m, n, a, b) flm(2, i, j, m, n, a, b) \
+ flm(3, i, j, m, n, a, b) __asm faddp st(1), \
+ st(0) __asm fxch st(2) __asm faddp st(1), st(0) __asm faddp st(1), \
+ st(0) __asm fstp dword ptr[eax + mi(l, 0, i, j)]
+
+//==============================================================================
+/**
+ * Main entry point for the SSE Matrix Multiplication.
+ * This is 4x4 matrix multiplication.
+ *
+ * @param inSource1 the first matrix to be multiplied (must be 16 floats long).
+ * @param inSource2 the second matrix to be multiplied (must be 16 floats long).
+ * @param outDestination where the result goes, this cannot be either of the sources.
+ */
+void SSE_MatrixMultiply(const float *inSource1, const float *inSource2, float *outDestination)
+{
+ __asm mov edx, DWORD PTR inSource1;
+ __asm mov ecx, DWORD PTR inSource2;
+ __asm mov eax, DWORD PTR outDestination;
+ e4(0, 0, 4, 4, 4, 0, 0) e4(0, 1, 4, 4, 4, 0, 0) e4(0, 2, 4, 4, 4, 0, 0) e4(0, 3, 4, 4, 4, 0, 0)
+ e4(1, 0, 4, 4, 4, 0, 0) e4(1, 1, 4, 4, 4, 0, 0) e4(1, 2, 4, 4, 4, 0, 0)
+ e4(1, 3, 4, 4, 4, 0, 0) e4(2, 0, 4, 4, 4, 0, 0) e4(2, 1, 4, 4, 4, 0, 0)
+ e4(2, 2, 4, 4, 4, 0, 0) e4(2, 3, 4, 4, 4, 0, 0) e4(3, 0, 4, 4, 4, 0, 0)
+ e4(3, 1, 4, 4, 4, 0, 0) e4(3, 2, 4, 4, 4, 0, 0) e4(3, 3, 4, 4, 4, 0, 0)
+}
+#else
+// No SSE_MatrixMultiply on non-windows.
+void SSE_MatrixMultiply(const float *inSource1, const float *inSource2, float *outDestination)
+{
+}
+#endif
+
+//==============================================================================
+/**
+ * Standard C MatrixMultiplication, copied from CMatrix::Concatenate.
+ * This is 4x4 matrix multiplication.
+ *
+ * @param inSource1 the first matrix to be multiplied (must be 16 floats long).
+ * @param inSource2 the second matrix to be multiplied (must be 16 floats long).
+ * @param outDestination where the result goes, this cannot be either of the sources.
+ */
+void C_MatrixMultiply(const float *inSource1, const float *inSource2, float *outDest)
+{
+ outDest[0] = inSource1[0] * inSource2[0] + inSource1[1] * inSource2[4]
+ + inSource1[2] * inSource2[8] + inSource1[3] * inSource2[12];
+ outDest[1] = inSource1[0] * inSource2[1] + inSource1[1] * inSource2[5]
+ + inSource1[2] * inSource2[9] + inSource1[3] * inSource2[13];
+ outDest[2] = inSource1[0] * inSource2[2] + inSource1[1] * inSource2[6]
+ + inSource1[2] * inSource2[10] + inSource1[3] * inSource2[14];
+ outDest[3] = inSource1[0] * inSource2[3] + inSource1[1] * inSource2[7]
+ + inSource1[2] * inSource2[11] + inSource1[3] * inSource2[15];
+
+ outDest[4] = inSource1[4] * inSource2[0] + inSource1[5] * inSource2[4]
+ + inSource1[6] * inSource2[8] + inSource1[7] * inSource2[12];
+ outDest[5] = inSource1[4] * inSource2[1] + inSource1[5] * inSource2[5]
+ + inSource1[6] * inSource2[9] + inSource1[7] * inSource2[13];
+ outDest[6] = inSource1[4] * inSource2[2] + inSource1[5] * inSource2[6]
+ + inSource1[6] * inSource2[10] + inSource1[7] * inSource2[14];
+ outDest[7] = inSource1[4] * inSource2[3] + inSource1[5] * inSource2[7]
+ + inSource1[6] * inSource2[11] + inSource1[7] * inSource2[15];
+
+ outDest[8] = inSource1[8] * inSource2[0] + inSource1[9] * inSource2[4]
+ + inSource1[10] * inSource2[8] + inSource1[11] * inSource2[12];
+ outDest[9] = inSource1[8] * inSource2[1] + inSource1[9] * inSource2[5]
+ + inSource1[10] * inSource2[9] + inSource1[11] * inSource2[13];
+ outDest[10] = inSource1[8] * inSource2[2] + inSource1[9] * inSource2[6]
+ + inSource1[10] * inSource2[10] + inSource1[11] * inSource2[14];
+ outDest[11] = inSource1[8] * inSource2[3] + inSource1[9] * inSource2[7]
+ + inSource1[10] * inSource2[11] + inSource1[11] * inSource2[15];
+
+ outDest[12] = inSource1[12] * inSource2[0] + inSource1[13] * inSource2[4]
+ + inSource1[14] * inSource2[8] + inSource1[15] * inSource2[12];
+ outDest[13] = inSource1[12] * inSource2[1] + inSource1[13] * inSource2[5]
+ + inSource1[14] * inSource2[9] + inSource1[15] * inSource2[13];
+ outDest[14] = inSource1[12] * inSource2[2] + inSource1[13] * inSource2[6]
+ + inSource1[14] * inSource2[10] + inSource1[15] * inSource2[14];
+ outDest[15] = inSource1[12] * inSource2[3] + inSource1[13] * inSource2[7]
+ + inSource1[14] * inSource2[11] + inSource1[15] * inSource2[15];
+}
+
+//==============================================================================
+/**
+ * Subtract inRHS from inLHS. This subtracts the values of each component of
+ * inRHS from inLHS.
+ * @param inLHS the vector that is to be subtracted from.
+ * @param inRHS the vector that is to be subtracted.
+ * @param outVect the result, this can be inLHS or inRHS.
+ */
+/*
+static inline void C_VectorSubtract( const float* inLHS, const float* inRHS, float* outVect )
+{
+ outVect[0] = inLHS[0] - inRHS[0];
+ outVect[1] = inLHS[1] - inRHS[1];
+ outVect[2] = inLHS[2] - inRHS[2];
+}
+/*/
+#define C_VectorSubtract(inLHS, inRHS, outVect) \
+ { \
+ outVect[0] = inLHS[0] - inRHS[0]; \
+ outVect[1] = inLHS[1] - inRHS[1]; \
+ outVect[2] = inLHS[2] - inRHS[2]; \
+ }
+
+#define C_VectorSum(inLHS, inRHS, outVect) \
+ { \
+ outVect[0] = inLHS[0] + inRHS[0]; \
+ outVect[1] = inLHS[1] + inRHS[1]; \
+ outVect[2] = inLHS[2] + inRHS[2]; \
+ }
+
+#define C_VectorCopy(inVect, outVect) \
+ { \
+ outVect[0] = outVect[0]; \
+ outVect[1] = outVect[0]; \
+ outVect[2] = outVect[0]; \
+ }
+
+/**/
+
+//==============================================================================
+/**
+ * Calculates the dot product between the two vectors.
+ * @param inVect1 the first vector to calculate the dot product with.
+ * @param inVect2 the second vector to calculate the dot product with.
+ * @return the dot product of the two vectors.
+ */
+/*
+static inline float C_VectorDotProduct( const float* inVect1, const float* inVect2 )
+{
+ return inVect1[0] * inVect2[0] + inVect1[1] * inVect2[1] + inVect1[2] * inVect2[2];
+}
+/*/
+#define C_VectorDotProduct(inVect1, inVect2) \
+ (inVect1[0] * inVect2[0] + inVect1[1] * inVect2[1] + inVect1[2] * inVect2[2])
+/**/
+
+//==============================================================================
+/**
+ * Calculates the cross product of the two vectors.
+ * @param inVector1 the first vector to calculate the cross product with.
+ * @param inVector2
+ */
+/*
+static inline void C_VectorCrossProduct( const float* inVector1, const float* inVector2, float*
+outVect )
+{
+ outVect[0] = inVector1[1] * inVector2[2] - inVector1[2] * inVector2[1];
+ outVect[1] = inVector1[2] * inVector2[0] - inVector1[0] * inVector2[2];
+ outVect[2] = inVector1[0] * inVector2[1] - inVector1[1] * inVector2[0];
+}
+/*/
+#define C_VectorCrossProduct(inVector1, inVector2, outVect) \
+ { \
+ outVect[0] = inVector1[1] * inVector2[2] - inVector1[2] * inVector2[1]; \
+ outVect[1] = inVector1[2] * inVector2[0] - inVector1[0] * inVector2[2]; \
+ outVect[2] = inVector1[0] * inVector2[1] - inVector1[1] * inVector2[0]; \
+ }
+/**/
+
+//==============================================================================
+/**
+ * Scales a vector by inScale amount.
+ * @param inVector the vector to scale.
+ * @param inScale the amount to scale the vector.
+ * @param outVect the result, this can be same vector as inVector.
+ */
+static inline void C_VectorScale(const float *inVector, float inScale, float *outVect)
+{
+ outVect[0] = inVector[0] * inScale;
+ outVect[1] = inVector[1] * inScale;
+ outVect[2] = inVector[2] * inScale;
+}
+
+//==============================================================================
+/**
+ * Set the components of one vector to the components of another vector.
+ * @param outDest the vector to be set.
+ * @param inSource the value to set outDest as.
+ */
+/*
+static inline void C_SetVector( float* outDest, const float* inSource )
+{
+ outDest[0] = inSource[0];
+ outDest[1] = inSource[1];
+ outDest[2] = inSource[2];
+}
+/*/
+#define C_SetVector(outDest, inSource) \
+ { \
+ outDest[0] = inSource[0]; \
+ outDest[1] = inSource[1]; \
+ outDest[2] = inSource[2]; \
+ }
+/**/
+
+//==============================================================================
+/**
+ * Transform the vector by the given matrix.
+ * The martrix is row column of the form (Matrix[row][column]):
+ *
+ * | m0 m1 m2 w |
+ * | m4 m5 m6 w |
+ * | m8 m9 m10 w |
+ * | tX tY tZ w |
+ *
+ * @param ioVector the input data and the return data, this vector will be modified.
+ * @param inMatrix the transform matrix.
+ * @param inTranslate is false if you only want to rotate the vector
+ */
+static inline void C_VectorTransform(float *ioVector, const float *inMatrix,
+ bool inTranslate = true)
+{
+ float theX = ioVector[0];
+ float theY = ioVector[1];
+ float theZ = ioVector[2];
+ float theW = inTranslate ? 1.0f : 0;
+
+ ioVector[0] =
+ theX * inMatrix[0] + theY * inMatrix[4] + theZ * inMatrix[8] + theW * inMatrix[12];
+ ioVector[1] =
+ theX * inMatrix[1] + theY * inMatrix[5] + theZ * inMatrix[9] + theW * inMatrix[13];
+ ioVector[2] =
+ theX * inMatrix[2] + theY * inMatrix[6] + theZ * inMatrix[10] + theW * inMatrix[14];
+}
+/*/
+#define C_VectorTransform( ioVector, inMatrix, inTranslate ) {
+\
+ float theX = ioVector[0];
+\
+ float theY = ioVector[1];
+\
+ float theZ = ioVector[2];
+\
+ float theW = ( inTranslate ? 1.0f : 0 );
+\
+ \
+ ioVector[0] = theX * inMatrix[ 0 ] + theY * inMatrix[ 4 ] + theZ * inMatrix[ 8 ] + theW *
+inMatrix[ 12 ]; \
+ ioVector[1] = theX * inMatrix[ 1 ] + theY * inMatrix[ 5 ] + theZ * inMatrix[ 9 ] + theW *
+inMatrix[ 13 ]; \
+ ioVector[2] = theX * inMatrix[ 2 ] + theY * inMatrix[ 6 ] + theZ * inMatrix[ 10 ] + theW *
+inMatrix[ 14 ]; \
+}
+/**/
+
+//==============================================================================
+/**
+ * Modified ioDestination to contain components that are the maximum between
+ * ioDestination and inComparison.
+ * @param ioDestination the source of the comparison, also the result of the operation.
+ * @param inComparison the vector whose components are to be compared.
+ */
+/*
+static inline void C_VectorMaximize( float* ioDestination, const float* inComparison )
+{
+ if ( ioDestination[0] < inComparison[0] )
+ ioDestination[0] = inComparison[0];
+ if ( ioDestination[1] < inComparison[1] )
+ ioDestination[1] = inComparison[1];
+ if ( ioDestination[2] < inComparison[2] )
+ ioDestination[2] = inComparison[2];
+}
+/*/
+#define C_VectorMaximize(ioDestination, inComparison) \
+ { \
+ if (ioDestination[0] < inComparison[0]) \
+ ioDestination[0] = inComparison[0]; \
+ if (ioDestination[1] < inComparison[1]) \
+ ioDestination[1] = inComparison[1]; \
+ if (ioDestination[2] < inComparison[2]) \
+ ioDestination[2] = inComparison[2]; \
+ }
+/**/
+
+//==============================================================================
+/**
+ * Modified ioDestination to contain components that are the minimum between
+ * ioDestination and inComparison.
+ * @param ioDestination the source of the comparison, also the result of the operation.
+ * @param inComparison the vector whose components are to be compared.
+ */
+/*
+static inline void C_VectorMinimize( float* ioDestination, const float* inComparison )
+{
+ if ( ioDestination[0] > inComparison[0] )
+ ioDestination[0] = inComparison[0];
+ if ( ioDestination[1] > inComparison[1] )
+ ioDestination[1] = inComparison[1];
+ if ( ioDestination[2] > inComparison[2] )
+ ioDestination[2] = inComparison[2];
+}
+/*/
+#define C_VectorMinimize(ioDestination, inComparison) \
+ { \
+ if (ioDestination[0] > inComparison[0]) \
+ ioDestination[0] = inComparison[0]; \
+ if (ioDestination[1] > inComparison[1]) \
+ ioDestination[1] = inComparison[1]; \
+ if (ioDestination[2] > inComparison[2]) \
+ ioDestination[2] = inComparison[2]; \
+ }
+/**/
+
+//==============================================================================
+/*
+ * IntersectTriangle: Check the poly (defined by the 3 verticies) for intersection.
+ *
+ * Given a ray origin (orig) and direction (dir), and three vertices of
+ * of a triangle, this function returns true and the interpolated texture
+ * coordinates if the ray intersects the triangle
+ *
+ * We use the parametric equation of plane relative to trigon T. To solve for the values of the
+ *parametric variables, we
+ * utilise the calculation of a generalized perp operator on plane which is defined as:
+ * Given plane Pi and vector in plane A:
+ * Perp( A ) lies in Pi and is perpendicular to A
+ *
+ * For further details, please refer to the reference links
+ *
+ * @param inUseBackface bool This is a vertex of the poly face.
+ * @param inOrig float[3] This is the origin of the Pickray (3D
+ *space).
+ * @param inDirection float[3] This is the direction of the Pickray.
+ * @param inTestV0 float[3] This is a vertex of the poly face.
+ * @param inTestV1 float[3] This is a vertex of the poly face.
+ * @param inTestV2 float[3] This is a vertex of the poly face.
+ * @param outIntersection float[3] This will return the point on the ray where
+ *intersection occured.
+ * @param outIntersectOffset float outIntersection = inOrig + theIntersectionOffset
+ ** inDirection;
+ *
+ * @return true if intersection occured. false otherwise.
+ *
+ * References
+ * http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm
+ * http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm#intersect_RayTriangle()
+ *
+ * Didier Badouel, "An Efficient Ray-Polygon Intersection" in Graphics Gems (1990)
+ * Francis Hill, "The Pleasures of 'Perp Dot' Products" in Graphics Gems IV (1994)
+ * [Note: the first critical definition has a typo, and should be: a^ = (-ay, ax).]
+ * Tomas Moller & Eric Haines, Real-Time Rendering, Chapter 10 "Intersection Test Methods"
+ *(1999)
+ * Tomas Moller & Ben Trumbore, "Fast, Minimum Storage Ray-Triangle Intersection", J. Graphics
+ *Tools 2(1), 21-28 (1997)
+ * Joseph O'Rourke, Computational Geometry in C (2nd Edition), Section 7.3 "Segment-Triangle
+ *Intersection" (1998)
+ * J.P. Snyder and A.H. Barr, "Ray Tracing Complex Models Containing Surface Tessellations",
+ *ACM Comp Graphics 21, (1987)
+ */
+bool C_IntersectTriangle(bool inUseFrontface, bool inUseBackface, const float *inOrig,
+ const float *inDirection, const float *inTestV0, const float *inTestV1,
+ const float *inTestV2, float *outIntersection, float *outIntersectOffset)
+{
+ // Holds the return value
+ // We've split this into 2 data bits: "DoContinue" and "Return"
+ // DoContinue | Return
+ // 0 0 = 0
+ // 0 1 = 1
+ // 1 0 = 2
+ // 1 1 = 3
+ long theReturn = 2;
+
+ // trigon vectors :
+ // triangle edge vectors and plane normal
+ float theTEdge1[3];
+ C_VectorSubtract(inTestV1, inTestV0, theTEdge1);
+ float theTEdge2[3];
+ C_VectorSubtract(inTestV2, inTestV0, theTEdge2);
+ float theTNormal[3];
+ C_VectorCrossProduct(theTEdge1, theTEdge2, theTNormal);
+
+ // Check for backface, give up if we are current checking a backfacing trigon and is not
+ // required
+ if ((!inUseFrontface && C_VectorDotProduct(theTNormal, inDirection) < -Q3DStudio::SQREPSILON)
+ || (!inUseBackface && C_VectorDotProduct(theTNormal, inDirection) > Q3DStudio::SQREPSILON)) {
+ // the trigon is facing the wrong way
+ // DoContinue = false;
+ // Return = false;
+ theReturn = 0;
+ }
+
+ if (theReturn && !theTNormal[0] && !theTNormal[1] && !theTNormal[2]) {
+ // the trigon is not well formed
+ theReturn = 0;
+ }
+
+ if (theReturn) {
+ float theVV0Orig[3]; // vector from V0 to Orig
+ C_VectorSubtract(inOrig, inTestV0, theVV0Orig);
+ float theDot0 = C_VectorDotProduct(theVV0Orig, theTNormal)
+ * -1; // the dot prod of theVVOrig & theTNormal
+ float theDot1 =
+ C_VectorDotProduct(inDirection, theTNormal); // the dot prod of inDirection & theTNormal
+ *outIntersectOffset = theDot0 / theDot1; // something to hold theDot0 / theDot1
+
+ if (theReturn >= 2) // ok to continue
+ {
+ if (::abs(theDot1) < Q3DStudio::SQREPSILON) {
+ // ray is parallel to triangle plane
+ if (theDot0 == 0) {
+ // ray lies in triangle plane
+ // return the Orig ( correct me if i m wrong here )
+ C_VectorCopy(inOrig, outIntersection);
+
+ // DoContinue = false;
+ // Return = true;
+ theReturn = 1;
+ } else {
+ // ray disjoint from plane
+ // DoContinue = false;
+ // Return = false;
+ theReturn = 0;
+ }
+ }
+ }
+
+ if (theReturn >= 2) // ok to continue
+ {
+ // get intersect point of ray with triangle plane
+ if (*outIntersectOffset < -Q3DStudio::EPSILON) {
+ // ray goes away from triangle => no intersect
+ // DoContinue = false;
+ // Return = false;
+ theReturn = 0;
+ }
+ }
+
+ if (theReturn >= 2) // ok to continue
+ {
+ // for a segment, also test if (r > 1.0) => no intersect
+ // outIntersection = inOrig + theIntersectionOffset * inDirection;
+ C_VectorScale(inDirection, *outIntersectOffset, outIntersection);
+ C_VectorSum(inOrig, outIntersection, outIntersection);
+
+ // is outIntersection inside the trigon?
+ float theEdge1Edge1 = C_VectorDotProduct(theTEdge1, theTEdge1);
+ float theEdge1Edge2 = C_VectorDotProduct(theTEdge1, theTEdge2);
+ float theEdge2Edge2 = C_VectorDotProduct(theTEdge2, theTEdge2);
+ float theVV0Isect[3];
+ C_VectorSubtract(outIntersection, inTestV0, theVV0Isect);
+ float theV0IsectEdge2 = C_VectorDotProduct(theVV0Isect, theTEdge2);
+ float theV0IsectEdge1 = C_VectorDotProduct(theVV0Isect, theTEdge1);
+ float theDiff = theEdge1Edge2 * theEdge1Edge2 - theEdge1Edge1 * theEdge2Edge2;
+
+ // get and test s, t parametric coords
+ // for details, refer to link
+ float theS, theT;
+ // s = (uv * wv - vv * wu) / D;
+ theS = (theEdge1Edge2 * theV0IsectEdge2 - theEdge2Edge2 * theV0IsectEdge1) / theDiff;
+
+ if (theS < -Q3DStudio::EPSILON || theS > (1.0f + Q3DStudio::EPSILON)) {
+ // theIntersection is outside trigon
+ // Return = false;
+ // DoContinue = false;
+ theReturn = 0;
+ }
+
+ // t = (uv * wu - uu * wv) / D;
+ theT = (theEdge1Edge2 * theV0IsectEdge1 - theEdge1Edge1 * theV0IsectEdge2) / theDiff;
+
+ if (theT < -Q3DStudio::EPSILON || (theS + theT) > (1.0 + Q3DStudio::EPSILON)) {
+ // theIntersection is outside trigon
+ // Return = false;
+ // DoContinue = false;
+ theReturn = 0;
+ }
+
+ if (theReturn >= 2) {
+ theReturn = 1; // just to make sure our return value is true at this point
+ }
+ }
+ }
+
+ // returns true or false, we are interested in only the "Return" bit
+ return 1 == (theReturn & 1);
+}
+
+//==============================================================================
+/**
+ * Transforms the bounding box using the given matrix. The resulting box
+ * is guaranteed to keep the min/max corners min/maxed even of the
+ * applied matrix results in a rotation that flips one or more corners.
+ * Note that each corner has to be translated individually and all
+ * eight corners have to be processed to spen the new box.
+ *
+ * @param ioMinBox on input the local min, on output the global min.
+ * @param ioMaxBox on input the local max, on output the global max.
+ * @param inTransform is the matrix that will apply the transform
+ */
+void C_TransformBoundingBox(float *ioMinBox, float *ioMaxBox, const float *inTransform)
+{
+ float theCorner[3];
+
+ // Store the original min and max box values
+ float theOrigMinBox[3];
+ theOrigMinBox[0] = ioMinBox[0];
+ theOrigMinBox[1] = ioMinBox[1];
+ theOrigMinBox[2] = ioMinBox[2];
+
+ float theOrigMaxBox[3];
+ theOrigMaxBox[0] = ioMaxBox[0];
+ theOrigMaxBox[1] = ioMaxBox[1];
+ theOrigMaxBox[2] = ioMaxBox[2];
+
+ // Reset bounding box to be empty which is different than the box having both corners at 0,0,0.
+ ioMinBox[0] = FLT_MAX;
+ ioMinBox[1] = FLT_MAX;
+ ioMinBox[2] = FLT_MAX;
+ ioMaxBox[0] = -FLT_MAX;
+ ioMaxBox[1] = -FLT_MAX;
+ ioMaxBox[2] = -FLT_MAX;
+
+ // Create and test the implicit 8 corners of the box
+ C_SetVector(theCorner, theOrigMaxBox);
+ // transform the corner by the specified transform
+ C_VectorTransform(theCorner, inTransform);
+ // check and modify the min box.
+ C_VectorMinimize(ioMinBox, theCorner);
+ // check and modify the max box.
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ // Repeat for each corner.
+
+ C_SetVector(theCorner, theOrigMinBox);
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ C_SetVector(theCorner, theOrigMaxBox);
+ theCorner[0] = theOrigMinBox[0];
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ C_SetVector(theCorner, theOrigMaxBox);
+ theCorner[1] = theOrigMinBox[1];
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ C_SetVector(theCorner, theOrigMaxBox);
+ theCorner[2] = theOrigMinBox[2];
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ C_SetVector(theCorner, theOrigMinBox);
+ theCorner[0] = theOrigMaxBox[0];
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ C_SetVector(theCorner, theOrigMinBox);
+ theCorner[1] = theOrigMaxBox[1];
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+
+ C_SetVector(theCorner, theOrigMinBox);
+ theCorner[2] = theOrigMaxBox[2];
+ C_VectorTransform(theCorner, inTransform);
+ C_VectorMinimize(ioMinBox, theCorner);
+ C_VectorMaximize(ioMaxBox, theCorner);
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.h b/src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.h
new file mode 100644
index 00000000..198fc5cc
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/OptimizedArithmetic.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+// tiny helper class to provide auto-initialization.
+class COptArithInitializer
+{
+public:
+ COptArithInitializer();
+};
+
+// Function definitions for the optimized functions. Documentation for them can be found on the
+// specific implementations
+// though the functionality should be the same between all implementations.
+typedef void (*FMatrixMultiply)(const float *inSource1, const float *inSource2, float *outDest);
+typedef bool (*FIntersectTriangle)(bool inUseFrontface, bool inUseBackface, const float *inOrig,
+ const float *inDirection, const float *inTestV0,
+ const float *inTestV1, const float *inTestV2,
+ float *outIntersection, float *outIntersectOffset);
+typedef void (*FTransformBoundingBox)(float *ioMinBox, float *ioMaxBox, const float *inTransform);
+
+class COptimizedArithmetic
+{
+public:
+ // Public accessors for the optimized functions.
+ // useage: COptimizedArithmetic::MatrixMultiply( ... );
+ static FMatrixMultiply MatrixMultiply;
+ static FIntersectTriangle IntersectTriangle;
+ static FTransformBoundingBox TransformBoundingBox;
+
+protected:
+ // static member variable used only for auto-initialization of this class.
+ static COptArithInitializer m_Initializer;
+
+private:
+ COptimizedArithmetic();
+ virtual ~COptimizedArithmetic();
+
+public:
+ static void Initialize();
+
+ // getters for checking what capabilities are available on the platform.
+ static bool HasMMX();
+ static bool HasSSE();
+ static bool HasSSE2();
+ static bool Has3DNow();
+};
diff --git a/src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.cpp b/src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.cpp
new file mode 100644
index 00000000..b68eef9e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PathConstructionHelper.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "StackTokenizer.h"
+
+//==============================================================================
+//// Constants
+//==============================================================================
+static const Q3DStudio::CString SOURCEPATHDELIMITER(L"."); // can only be single char!
+static const Q3DStudio::CString SOURCEPATHESCAPECHAR(L"\\"); // can only be single char!
+static const Q3DStudio::CString SOURCEPATHSCENE(L"Scene");
+static const Q3DStudio::CString SOURCEPATHPARENT(L"parent");
+static const Q3DStudio::CString SOURCEPATHTHIS(L"this");
+
+//=============================================================================
+/**
+ * Create a absolute path reference string
+ */
+Q3DStudio::CString
+CPathConstructionHelper::BuildAbsoluteReferenceString(CDoc *inDoc,
+ UICDM::CUICDMInstanceHandle inInstance)
+{
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ Q3DStudio::CString theNameStart;
+ Q3DStudio::CString theNameEnd = EscapeAssetName(theBridge->GetName(inInstance));
+
+ UICDM::CUICDMInstanceHandle theParentInstance = theBridge->GetParentInstance(inInstance);
+ if (theParentInstance.Valid()) {
+ theNameStart = BuildAbsoluteReferenceString(inDoc, theParentInstance);
+ theNameStart += ".";
+ }
+ theNameStart += theNameEnd;
+
+ return theNameStart;
+}
+
+//=============================================================================
+/**
+ * Create a relative path reference string
+ */
+Q3DStudio::CString CPathConstructionHelper::BuildRelativeReferenceString(
+ CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance, UICDM::CUICDMInstanceHandle inRootInstance)
+{
+ Q3DStudio::CString theAbsRelPath = BuildAbsoluteReferenceString(inDoc, inInstance);
+ Q3DStudio::CString theAbsRootPath = BuildAbsoluteReferenceString(inDoc, inRootInstance);
+
+ return CPathConstructionHelper::BuildRelativeReferenceString(theAbsRelPath, theAbsRootPath);
+}
+
+//=============================================================================
+/**
+ * helper method to create therelative path reference string based on it's
+ * absolute path string and the root object absolute path string
+ */
+Q3DStudio::CString
+CPathConstructionHelper::BuildRelativeReferenceString(Q3DStudio::CString &inAbsObjPath,
+ Q3DStudio::CString &inAbsRootPath)
+{
+ Q3DStudio::CString theRelPath = ""; // SOURCEPATHTHIS;
+ CStackTokenizer theAbsRelTokenizer(inAbsObjPath, SOURCEPATHDELIMITER.GetAt(0),
+ SOURCEPATHESCAPECHAR.GetAt(0));
+ CStackTokenizer theAbsRootTokenizer(inAbsRootPath, SOURCEPATHDELIMITER.GetAt(0),
+ SOURCEPATHESCAPECHAR.GetAt(0));
+
+ // Validate the strings
+ if (theAbsRelTokenizer.HasNextPartition() && theAbsRootTokenizer.HasNextPartition()) {
+ // Bypass all common roots
+ while (theAbsRelTokenizer.HasNextPartition() && theAbsRootTokenizer.HasNextPartition()
+ && theAbsRelTokenizer.GetCurrentPartition()
+ == theAbsRootTokenizer.GetCurrentPartition()) {
+ ++theAbsRelTokenizer;
+ ++theAbsRootTokenizer;
+ }
+
+ // Grab the remaining path from the relative item
+ Q3DStudio::CString theRelPathRemaining;
+ while (theAbsRelTokenizer.HasNextPartition()) {
+ theRelPathRemaining += SOURCEPATHDELIMITER;
+ theRelPathRemaining +=
+ CPathConstructionHelper::EscapeAssetName(theAbsRelTokenizer.GetCurrentPartition());
+ ++theAbsRelTokenizer;
+ }
+
+ // Add the appropriate number of "parents" and a "this"
+ while (theAbsRootTokenizer.HasNextPartition()) {
+ if (theRelPath.Length() > 0)
+ theRelPath += SOURCEPATHDELIMITER;
+ theRelPath += SOURCEPATHPARENT;
+ ++theAbsRootTokenizer;
+ }
+
+ // Append the remaining path, if neccessary
+ if (theRelPathRemaining.Length()) {
+ theRelPath += theRelPathRemaining;
+ }
+ }
+
+ if (theRelPath.Length() == 0)
+ theRelPath = SOURCEPATHTHIS;
+ else if (theRelPath[(long)0] == '.') {
+ Q3DStudio::CString theTempString = theRelPath;
+ theRelPath = SOURCEPATHTHIS;
+ theRelPath += theTempString;
+ }
+
+ return theRelPath;
+}
+
+//=============================================================================
+/**
+ * Format the string correctly by appending the appropriate escape character
+ */
+Q3DStudio::CString CPathConstructionHelper::EscapeAssetName(Q3DStudio::CString inAssetName)
+{
+ static Q3DStudio::CString theEscapedEscape(SOURCEPATHESCAPECHAR + SOURCEPATHESCAPECHAR);
+ inAssetName.Replace(SOURCEPATHESCAPECHAR, theEscapedEscape); // move these to const strings
+
+ static Q3DStudio::CString theEscapedDelimiter(SOURCEPATHESCAPECHAR + SOURCEPATHDELIMITER);
+ inAssetName.Replace(SOURCEPATHDELIMITER, theEscapedDelimiter);
+ return inAssetName;
+}
+
+//=============================================================================
+/**
+ * Return the string value that specifies "this"
+ */
+const Q3DStudio::CString &CPathConstructionHelper::GetThisString()
+{
+ return SOURCEPATHTHIS;
+}
+
+//=============================================================================
+/**
+ * Return the string value that specifies the escape character
+ */
+const Q3DStudio::CString &CPathConstructionHelper::GetEscapeChar()
+{
+ return SOURCEPATHESCAPECHAR;
+}
+
+//=============================================================================
+/**
+ * Return the string value that specifies "Scene"
+ */
+const Q3DStudio::CString &CPathConstructionHelper::GetSceneString()
+{
+ return SOURCEPATHSCENE;
+}
+
+//=============================================================================
+/**
+ * Return the string value that specifies "parent"
+ */
+const Q3DStudio::CString &CPathConstructionHelper::GetParentString()
+{
+ return SOURCEPATHPARENT;
+}
+
+//=============================================================================
+/**
+ * Return the string value that specifies teh delimiter
+ */
+const Q3DStudio::CString &CPathConstructionHelper::GetPathDelimiter()
+{
+ return SOURCEPATHDELIMITER;
+} \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.h b/src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.h
new file mode 100644
index 00000000..7648c6f7
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/PathConstructionHelper.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PATHCONSTRUCTIONHELPER_H
+#define INCLUDED_PATHCONSTRUCTIONHELPER_H 1
+
+#include "UICDMHandles.h"
+#include "UICString.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+#pragma once
+
+class CDoc;
+
+//==============================================================================
+/**
+ * @class CPathConstructionHelper
+ */
+class CPathConstructionHelper
+{
+ //==============================================================================
+ // Static Methods
+ //==============================================================================
+public:
+ static Q3DStudio::CString BuildAbsoluteReferenceString(CDoc *inDoc,
+ UICDM::CUICDMInstanceHandle inInstance);
+ static Q3DStudio::CString
+ BuildRelativeReferenceString(CDoc *inDoc, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inRootInstance);
+ static Q3DStudio::CString BuildRelativeReferenceString(Q3DStudio::CString &inAbsObjPath,
+ Q3DStudio::CString &inAbsRootPath);
+ static Q3DStudio::CString EscapeAssetName(Q3DStudio::CString inAssetName);
+
+ static const Q3DStudio::CString &GetThisString();
+ static const Q3DStudio::CString &GetEscapeChar();
+ static const Q3DStudio::CString &GetSceneString();
+ static const Q3DStudio::CString &GetParentString();
+ static const Q3DStudio::CString &GetPathDelimiter();
+};
+
+#endif // INCLUDED_PATHCONSTRUCTIONHELPER_H
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioClipboard.cpp b/src/Authoring/Client/Code/Core/Utility/StudioClipboard.cpp
new file mode 100644
index 00000000..874a87c1
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioClipboard.cpp
@@ -0,0 +1,325 @@
+/****************************************************************************
+ * *
+ ** Copyright (C) 1999-2004 NVIDIA Corporation.
+ ** Copyright (C) 2017 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of Qt 3D Studio.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioClipboard.h"
+
+#include "Literals.h"
+#include "StudioObjectTypes.h"
+#include "UICString.h"
+
+#include <QClipboard>
+#include <QDataStream>
+#include <QFile>
+#include <QGuiApplication>
+#include <QMimeData>
+
+CUICFile CStudioClipboard::s_InternalClipObject("");
+qint64 CStudioClipboard::s_InternalContextData = 0;
+EStudioObjectType CStudioClipboard::s_AssetType(OBJTYPE_UNKNOWN);
+qint64 CStudioClipboard::s_CopyProcessID = 0;
+
+//==============================================================================
+/**
+ * Destructor.
+ */
+CStudioClipboard::~CStudioClipboard()
+{
+}
+
+//==============================================================================
+/**
+ * Retrieve a previously stored object from the respective clipboard.
+ * @param inIsInternal true if we are retrieving for an internal operation like
+ *CmdMakeComponent or CmdDuplicateObject
+ * @param outContextData arbitrary data saved earlier
+ * @return the object that was retrieved from the respective clipboard.
+ */
+CUICFile CStudioClipboard::GetObjectFromClipboard(bool inIsInternal, qint64 &outContextData)
+{
+ if (inIsInternal)
+ return GetObjectFromInternalClipboard(outContextData);
+ else {
+ return GetObjectFromGlobalClipboard(outContextData, "application/x-qt3dstudio-clipboard"_L1);
+ }
+}
+
+//==============================================================================
+/**
+ * Store the given object to the respective clipboard.
+ * @param inTempFile The object to store to clipboard.
+ * @param inContextData any arbitrary data to be retrieved later
+ * @param inIsInternal true if we are storing for an internal operation like
+ *CmdMakeComponent or CmdDuplicateObject
+ * @param inAssetType asset type of object
+ */
+void CStudioClipboard::CopyObjectToClipboard(CUICFile &inFile, qint64 inContextData,
+ bool inIsInternal, EStudioObjectType inObjectType)
+{
+ s_AssetType = inObjectType;
+
+ if (inIsInternal) {
+ CopyObjectToInternalClipboard(inFile, inContextData);
+ } else {
+ CopyObjectToGlobalClipboard(inFile, inContextData, "application/x-qt3dstudio-clipboard"_L1);
+ }
+}
+
+//==============================================================================
+/**
+ * Returns true if there is an object available on the internal or global clipboard.
+ * Make sure the destination asset is capable of attaching the "Pastee".
+ * @param inDestType Asset type of destination asset
+ * @param inIsInternal true if we are checking this from an internal operation like
+ *CmdMakeComponent or CmdDuplicateObject
+ * @return true if there is an object available on the internal or global clipboard, and
+ *the object is paste-able onto the destination object
+ */
+bool CStudioClipboard::CanPasteObject(EStudioObjectType inDestType, bool inIsInternal /* = false */)
+{
+ if (inIsInternal) {
+ if (CStudioObjectTypes::AcceptableParent(s_AssetType, inDestType))
+ return s_InternalClipObject.Exists();
+ } else {
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ auto mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat("application/x-qt3dstudio-clipboard"_L1)) {
+ GetObjectFromGlobalClipboard("application/x-qt3dstudio-clipboard"_L1);
+ if (CStudioObjectTypes::AcceptableParent(s_AssetType, inDestType))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//==============================================================================
+/**
+ * Retrieve the object from the internal Clipboard.
+ * @param outContextData arbitrary data saved earlier
+ * @return CUICFile object that was retrieved from the internal Clipboard.
+ */
+CUICFile CStudioClipboard::GetObjectFromInternalClipboard(qint64 &outContextData)
+{
+ // Don't have to delete the InternalClipObject as the CmdPasteObject would delete the file later
+ outContextData = s_InternalContextData;
+ return s_InternalClipObject;
+}
+
+//==============================================================================
+/**
+ * Copy the input file to the internal clipboard.
+ * @param inFile The object to copy to the internal clipboard.
+ * @param inContextData any arbitrary data to be retrieved later
+ */
+void CStudioClipboard::CopyObjectToInternalClipboard(CUICFile &inFile, qint64 inContextData)
+{
+ s_InternalClipObject = inFile;
+ s_InternalContextData = inContextData;
+}
+
+//==============================================================================
+/**
+ * Retrieve the object from the global Clipboard.
+ * @param outContextData arbitrary data saved earlier
+ * @return CUICFile object that was retrieved from the global Clipboard.
+ */
+CUICFile CStudioClipboard::GetObjectFromGlobalClipboard(qint64 &outContextData,
+ const QString &inMimeType)
+{
+ CUICFile theTempAPFile = CUICFile::GetTemporaryFile();
+ GetObjectFromGlobalClipboard(inMimeType, &theTempAPFile, &outContextData);
+ return theTempAPFile;
+}
+
+//==============================================================================
+/**
+ * Copy the input file to the global clipboard.
+ * @param inFile The object to copy to the global clipboard.
+ * @param inContextData any arbitrary data to be retrieved later
+ */
+void CStudioClipboard::CopyObjectToGlobalClipboard(CUICFile &inFile, qint64 inContextData,
+ const QString &inMimeType)
+{
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_5_8);
+ QFile file(inFile.GetAbsolutePath().toQString());
+ if (!file.open(QIODevice::ReadOnly))
+ return;
+
+ stream << file.readAll();
+ // Append this after the copied data, so that pasting from prior versions of studio would still
+ // work.
+ stream << inContextData;
+ stream << (qint32)s_AssetType;
+ stream << s_CopyProcessID;
+
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData(inMimeType, data);
+ clipboard->setMimeData(mimeData);
+}
+
+//==============================================================================
+/**
+ * Returns the text that is being stored in the global clipboard.
+ * @return The text that was retrieved from the global clipboard.
+ */
+QString CStudioClipboard::GetTextFromClipboard()
+{
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ return clipboard->text();
+}
+
+//==============================================================================
+/**
+ * Copies input text to global clipboard.
+ * @param inText The text to copy to the global clipboard.
+ */
+void CStudioClipboard::CopyTextToClipboard(const QString &inText)
+{
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ clipboard->setText(inText);
+}
+
+//==============================================================================
+/**
+ * Returns true if there is text available on the global clipboard for a paste operation.
+ * @return true if there is text available on the global clipboard for a paste operation.
+ */
+bool CStudioClipboard::CanPasteText()
+{
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ auto mimeData = clipboard->mimeData();
+ return mimeData->hasText();
+}
+
+//==============================================================================
+/**
+ * Clears the global clipboard.
+ */
+void CStudioClipboard::ClearClipboard()
+{
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ clipboard->clear();
+}
+
+//==============================================================================
+/**
+ * Retrieve a previously stored action from the global clipboard.
+ * @return the object that was retrieved from the respective clipboard.
+ */
+CUICFile CStudioClipboard::GetActionFromClipboard()
+{
+ qint64 theContextData = 0;
+ return GetObjectFromGlobalClipboard(theContextData, "application/x-qt3dstudio-action"_L1);
+}
+
+//==============================================================================
+/**
+ * Copy an Action to the Clipboard.
+ * @param inFile The object to store to clipboard.
+ */
+void CStudioClipboard::CopyActionToClipboard(CUICFile &inFile)
+{
+ s_CopyProcessID = qApp->applicationPid();
+ CopyObjectToGlobalClipboard(inFile, 0, "application/x-qt3dstudio-action"_L1);
+}
+
+//==============================================================================
+/**
+ * Check if there are available actions on the clipboard for paste operations.
+ * @return true if Actions are available to be pasted.
+ */
+bool CStudioClipboard::CanPasteAction()
+{
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ auto mimeData = clipboard->mimeData();
+ return mimeData->hasFormat("application/x-qt3dstudio-action"_L1);
+}
+
+//==============================================================================
+/**
+ * Retrieve the object from the global Clipboard.
+ * @param inObj the OleDataObject to extract the data from
+ * @param inClipFormat the clipboard format that was registered for
+ * @param outContextData arbitrary data saved earlier
+ * @param outFile file to write clipboard data to, if any.
+ */
+void CStudioClipboard::GetObjectFromGlobalClipboard(const QString &inMimeType,
+ CUICFile *outFile /*= NULL */,
+ qint64 *outContextData /*= NULL */)
+{
+ QClipboard *clipboard = QGuiApplication::clipboard();
+ auto mimeData = clipboard->mimeData();
+ if (mimeData->hasFormat(inMimeType)) {
+ QByteArray clipboardData = mimeData->data(inMimeType);
+ QDataStream stream(&clipboardData, QIODevice::ReadOnly);
+ stream.setVersion(QDataStream::Qt_5_8);
+ QByteArray data;
+ stream >> data;
+ if (outFile) {
+ QFile file(outFile->GetAbsolutePath().toQString());
+ if (file.open(QIODevice::WriteOnly)) {
+ file.write(data);
+ file.close();
+ }
+ }
+ if (outContextData) {
+ stream >> *outContextData;
+ } else {
+ qint64 temp;
+ stream >> temp;
+ }
+ qint32 assetType;
+ stream >> assetType;
+ s_AssetType = (EStudioObjectType)assetType;
+ stream >> s_CopyProcessID;
+ }
+}
+
+//==============================================================================
+/**
+ * Determines if the object of the current paste operation was copied from
+ * another Studio instance. This function should be called only for global
+ * pastes.
+ * @return true if paste target is from another instance of Studio.
+ */
+bool CStudioClipboard::IsPastingAcrossInstances()
+{
+ return qApp->applicationPid() != s_CopyProcessID;
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioClipboard.h b/src/Authoring/Client/Code/Core/Utility/StudioClipboard.h
new file mode 100644
index 00000000..b81a27b4
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioClipboard.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STUDIOCLIPBOARD_H
+#define INCLUDED_STUDIOCLIPBOARD_H 1
+
+#include "UICFile.h"
+#include "StudioObjectTypes.h"
+
+class COleDataObject;
+
+class CStudioClipboard
+{
+protected:
+ CStudioClipboard(){}
+
+public:
+ virtual ~CStudioClipboard();
+
+ static CUICFile GetObjectFromClipboard(bool inIsInternal, qint64 &outContextData);
+ static void CopyObjectToClipboard(CUICFile &inFile, qint64 inContextData, bool inIsInternal,
+ EStudioObjectType inObjectType);
+ static bool CanPasteObject(EStudioObjectType inDestType, bool inIsInternal = false);
+ static bool IsPastingAcrossInstances();
+
+protected:
+ static CUICFile GetObjectFromInternalClipboard(qint64 &outContextData);
+ static void CopyObjectToInternalClipboard(CUICFile &inFile, qint64 inContextData);
+ static CUICFile GetObjectFromGlobalClipboard(qint64 &outContextData, const QString &inMimeType);
+ static void CopyObjectToGlobalClipboard(CUICFile &inFile, qint64 inContextData,
+ const QString &inMimeType);
+
+public:
+ static QString GetTextFromClipboard();
+ static void CopyTextToClipboard(const QString &);
+ static bool CanPasteText();
+
+ static void ClearClipboard(); ///< clears the global clipboard
+
+ // Copy/paste Actions
+ static CUICFile GetActionFromClipboard();
+ static void CopyActionToClipboard(CUICFile &inFile);
+ static bool CanPasteAction();
+
+protected:
+ static void GetObjectFromGlobalClipboard(const QString &inMimeType,
+ CUICFile *outFile = NULL, qint64 *outContextData = NULL);
+
+private:
+ static CUICFile s_InternalClipObject; ///< the cache for internal clipboard operations
+ static qint64 s_InternalContextData; ///< any arbitrary data for internal copy cmds.
+ static EStudioObjectType s_AssetType; ///< asset type of the clipobject
+ static qint64
+ s_CopyProcessID; ///< process ID of this executable during the copy (for global copies only)
+};
+
+#endif // INCLUDED_STUDIOCLIPBOARD_H
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioErrorIDs.h b/src/Authoring/Client/Code/Core/Utility/StudioErrorIDs.h
new file mode 100644
index 00000000..422bde6b
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioErrorIDs.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef _INCLUDED_STUDIO_ERRROR_IDS_H
+#define _INCLUDED_STUDIO_ERRROR_IDS_H
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ClientErrorIDs.h"
+
+//==============================================================================
+// HRESULTS
+//==============================================================================
+#ifdef WIN32
+#define STUDIO_ERROR(inID, inName) \
+ const HRESULT inName = \
+ MAKE_HRESULT(LEVEL_ERROR, FACILITY_ITF, UICCLIENT_START_ERROR_RANGE + inID);
+#else
+#ifndef HRESULT
+#define HRESULT quint32
+#endif
+#define STUDIO_ERROR(inID, inName) \
+ const HRESULT inName = \
+ MAKE_HRESULT(LEVEL_ERROR, FACILITY_ITF, UICCLIENT_START_ERROR_RANGE + inID);
+#endif
+
+// EngineeringTask (SDJ 02/09/05) Clean up this file or get rid of it!!!!
+
+STUDIO_ERROR(0, STUDIO_E_FAIL)
+/*STUDIO_ERROR( 1, STUDIO_E_INVALIDARGUMENT )
+STUDIO_ERROR( 2, STUDIO_E_NULLARGUMENT )
+STUDIO_ERROR( 3, STUDIO_E_STATEOUTOFRANGE )
+STUDIO_ERROR( 4, STUDIO_E_OUTOFMEMORY )
+STUDIO_ERROR( 5, STUDIO_E_NOTIMPL )
+*/
+STUDIO_ERROR(6, STUDIO_E_ACQUIREINTERFACE)
+/*STUDIO_ERROR( 7, STUDIO_E_CREATEASSET )
+STUDIO_ERROR( 8, STUDIO_E_OBJECTMAPLOOKUP )
+STUDIO_ERROR( 9, STUDIO_E_REGISTERSTATE )
+*/
+STUDIO_ERROR(10, STUDIO_E_NULLDOCUMENT)
+STUDIO_ERROR(11, STUDIO_E_NULLSTUDIOOBJECT)
+/*STUDIO_ERROR( 12, STUDIO_E_ILLEGALPROPERTYTYPE )
+STUDIO_ERROR( 13, STUDIO_E_ILLEGALSTATE )
+*/
+STUDIO_ERROR(14, STUDIO_E_NULLWINDOW)
+/*STUDIO_ERROR( 15, STUDIO_E_CREATEWINDOW )
+*/
+STUDIO_ERROR(16, STUDIO_E_NULLVIEW)
+
+STUDIO_ERROR(17, STUDIO_E_INVALIDPROGRAMSTATE)
+/*STUDIO_ERROR( 18, STUDIO_E_ASSOCIATIONFAILED )
+STUDIO_ERROR( 19, STUDIO_E_PROPERTYLOOKUPFAILED )
+*/
+STUDIO_ERROR(20, STUDIO_E_NULLCTRL)
+/*STUDIO_ERROR( 21, STUDIO_E_UNEXPECTEDPARAMETERTYPE )
+STUDIO_ERROR( 22, STUDIO_E_NULLASSET )
+*/
+STUDIO_ERROR(23, STUDIO_E_SCRIPTERROR)
+/*
+STUDIO_ERROR( 24, STUDIO_E_INVALIDURL )
+STUDIO_ERROR( 25, STUDIO_E_FAILHOTSWAP )
+*/
+STUDIO_ERROR(25, STUDIO_E_INVALIDEDITOR)
+/*
+STUDIO_ERROR( 26, STUDIO_E_INVALIDOPCODE )
+STUDIO_ERROR( 27, STUDIO_E_CACHEASSET )
+STUDIO_ERROR( 28, STUDIO_E_EXPORTFAIL ) /// Exporting a
+presentation failed for an unknown reason - fatal error
+STUDIO_ERROR( 29, STUDIO_E_NULLHANDLE )
+STUDIO_ERROR( 30, STUDIO_E_NULLDC )
+STUDIO_ERROR( 31, STUDIO_E_NULLKEYFRAME )
+STUDIO_ERROR( 32, STUDIO_E_CANCELEXPORT ) /// Exporting presentation
+failed, but only because the user cancelled the operation
+STUDIO_ERROR( 33, STUDIO_E_NULLDRAGOBJECT ) /// NULL Studio Object
+for drag and drop
+STUDIO_ERROR( 34, STUDIO_E_NULLCMD ) /// NULL
+undo/redo command (CCmd or subclass)
+STUDIO_ERROR( 35, STUDIO_E_GETTIMERANGE )
+STUDIO_ERROR( 36, STUDIO_E_RESTOREASSET )
+STUDIO_ERROR( 37, STUDIO_E_DRAGNDROP )
+STUDIO_ERROR( 38, STUDIO_E_NOTRANSFEROBJECT )
+STUDIO_ERROR( 39, STUDIO_E_INVALIDTRANSFEROBJECT )
+*/
+STUDIO_ERROR(42, STUDIO_E_EGLINITIALIZEERROR)
+
+#endif // #ifndef _INCLUDED_STUDIO_ERRROR_IDS_H
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp
new file mode 100644
index 00000000..fae06273
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#include "StudioObjectTypes.h"
+
+//==============================================================================
+bool CStudioObjectTypes::AcceptableParent(EStudioObjectType inChild, EStudioObjectType inParent)
+{
+ bool theAcceptible = false;
+ switch (inChild) {
+ case OBJTYPE_SCENE:
+ theAcceptible = false;
+ break;
+ case OBJTYPE_LAYER:
+ theAcceptible = (inParent == OBJTYPE_SCENE);
+ break;
+
+ case OBJTYPE_BEHAVIOR:
+ theAcceptible = (inParent == OBJTYPE_SCENE) || (inParent == OBJTYPE_LAYER)
+ || (inParent == OBJTYPE_BEHAVIOR) || (inParent == OBJTYPE_CAMERA)
+ || (inParent == OBJTYPE_LIGHT) || (inParent == OBJTYPE_MODEL)
+ || (inParent == OBJTYPE_GROUP) || (inParent == OBJTYPE_COMPONENT)
+ || (inParent == OBJTYPE_IMAGE) || (inParent == OBJTYPE_TEXT)
+ || (inParent == OBJTYPE_PATH);
+
+ break;
+ case OBJTYPE_MATERIAL:
+ theAcceptible = false;
+ break;
+ case OBJTYPE_TEXT:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_CAMERA:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_LIGHT:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_MODEL:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_GROUP:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_ALIAS:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_PATH:
+ // Skip the break because these cases have the same parent.
+ case OBJTYPE_COMPONENT:
+ theAcceptible = (inParent == OBJTYPE_LAYER) || (inParent == OBJTYPE_CAMERA)
+ || (inParent == OBJTYPE_LIGHT) || (inParent == OBJTYPE_MODEL)
+ || (inParent == OBJTYPE_GROUP) || (inParent == OBJTYPE_COMPONENT)
+ || (inParent == OBJTYPE_PATH);
+
+ break;
+ case OBJTYPE_IMAGE:
+ theAcceptible = false;
+ break;
+ case OBJTYPE_EFFECT:
+ theAcceptible = (inParent == OBJTYPE_LAYER) || (inParent == OBJTYPE_EFFECT);
+ break;
+ case OBJTYPE_CUSTOMMATERIAL:
+ theAcceptible = false; // TODO add drag and drop support
+ break;
+ }
+
+ return theAcceptible;
+};
+
+//==============================================================================
+// Object Icon Lookups
+//==============================================================================
+
+//=============================================================================
+/**
+ * Lame switch to get the normal state object specific icon.
+ * @return the icon to be used in the 'normal' state.
+ */
+const QString &CStudioObjectTypes::GetNormalIconName(EStudioObjectType inType)
+{
+ switch (inType) {
+ case OBJTYPE_CAMERA: {
+ static QString theString = "Objects-Camera-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_IMAGE: {
+ static QString theString = "Objects-Image-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_LIGHT: {
+ static QString theString = "Objects-Light-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_MODEL: {
+ static QString theString = "Objects-Model-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_GROUP: {
+ static QString theString = "Objects-Group-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_ALIAS: {
+ static QString theString = "Objects-Alias-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_PATH: {
+ static QString theString = "Objects-Path-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_PATHANCHORPOINT: {
+ static QString theString = "Objects-Anchor-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SUBPATH: {
+ static QString theString = "Objects-SubPath-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_COMPONENT: {
+ static QString theString = "Objects-Component-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_LAYER: {
+ static QString theString = "Objects-Layer-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_TEXT: {
+ static QString theString = "Objects-Text-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_MATERIAL:
+ case OBJTYPE_CUSTOMMATERIAL:
+ case OBJTYPE_REFERENCEDMATERIAL: {
+ static QString theString = "Objects-Material-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SCENE:
+ case OBJTYPE_SLIDE: {
+ static QString theString = "Objects-Scene-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_BEHAVIOR: {
+ static QString theString = "Objects-Behavior-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_EFFECT: {
+ static QString theString = "Objects-Effect-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SOUND: {
+ static QString theString = "Objects-Sound-Normal.png";
+ return theString;
+ }
+ default: {
+ static QString theString = "Objects-Model-Normal.png";
+ return theString;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Lame switch to get the disabled state object specific icon.
+ * @return the icon to be used in the disabled state.
+ */
+const QString &CStudioObjectTypes::GetDisabledIconName(EStudioObjectType inType)
+{
+ switch (inType) {
+ case OBJTYPE_CAMERA: {
+ static QString theString = "Objects-Camera-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_IMAGE: {
+ static QString theString = "Objects-Image-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_LIGHT: {
+ static QString theString = "Objects-Light-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_MODEL: {
+ static QString theString = "Objects-Model-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_GROUP: {
+ static QString theString = "Objects-Group-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_ALIAS: {
+ static QString theString = "Objects-Alias-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_PATH: {
+ static QString theString = "Objects-Path-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_PATHANCHORPOINT: {
+ static QString theString = "Objects-Anchor-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SUBPATH: {
+ static QString theString = "Objects-SubPath-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_COMPONENT: {
+ static QString theString = "Objects-Component-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_LAYER: {
+ static QString theString = "Objects-Layer-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_TEXT: {
+ static QString theString = "Objects-Text-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_MATERIAL:
+ case OBJTYPE_CUSTOMMATERIAL:
+ case OBJTYPE_REFERENCEDMATERIAL: {
+ static QString theString = "Objects-Material-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_SCENE: {
+ static QString theString = "Objects-Scene-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_BEHAVIOR: {
+ static QString theString = "Objects-Behavior-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_EFFECT: {
+ static QString theString = "Objects-Effect-Disabled.png";
+ return theString;
+ }
+ case OBJTYPE_SOUND: {
+ static QString theString = "Objects-Sound-Disabled.png";
+ return theString;
+ }
+ default: {
+ static QString theString = "Objects-Model-Disabled.png";
+ return theString;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Lame switch to get the highlight state object specific icon.
+ * @return the icon to be used in the highlighted state.
+ */
+const QString &CStudioObjectTypes::GetHighlightIconName(EStudioObjectType inType)
+{
+ switch (inType) {
+ case OBJTYPE_CAMERA: {
+ static QString theString = "Objects-Camera-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_IMAGE: {
+ static QString theString = "Objects-Image-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_LIGHT: {
+ static QString theString = "Objects-Light-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_MODEL: {
+ static QString theString = "Objects-Model-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_GROUP: {
+ static QString theString = "Objects-Group-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_PATH: {
+ static QString theString = "Objects-Path-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_PATHANCHORPOINT: {
+ static QString theString = "Objects-Anchor-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SUBPATH: {
+ static QString theString = "Objects-SubPath-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_ALIAS: {
+ static QString theString = "Objects-Alias-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_COMPONENT: {
+ static QString theString = "Objects-Component-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_LAYER: {
+ static QString theString = "Objects-Layer-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_TEXT: {
+ static QString theString = "Objects-Text-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_MATERIAL:
+ case OBJTYPE_CUSTOMMATERIAL:
+ case OBJTYPE_REFERENCEDMATERIAL: {
+ static QString theString = "Objects-Material-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SCENE: {
+ static QString theString = "Objects-Scene-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_BEHAVIOR: {
+ static QString theString = "Objects-Behavior-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_EFFECT: {
+ static QString theString = "Objects-Effect-Normal.png";
+ return theString;
+ }
+ case OBJTYPE_SOUND: {
+ static QString theString = "Objects-Sound-Normal.png";
+ return theString;
+ }
+ default: {
+ static QString theString = "Objects-Model-Normal.png";
+ return theString;
+ }
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h
new file mode 100644
index 00000000..e648770e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_STUDIO_OBJECTTYPES_H
+#define INCLUDED_STUDIO_OBJECTTYPES_H
+
+#pragma once
+
+#include "PropertyPublishLevels.h"
+#include "UICString.h"
+//
+// *******************************************************************
+// IMPORTANT: These object types (EStudioObjectType) line up with the
+// icons used for the timeline for each object type
+// *******************************************************************
+//
+
+enum EStudioObjectType {
+ OBJTYPE_UNKNOWN = 0x00000000,
+ OBJTYPE_SCENE = 0x00000001,
+ OBJTYPE_LAYER = 0x00000002,
+ OBJTYPE_BEHAVIOR = 0x00000004,
+ OBJTYPE_MATERIAL = 0x00000008,
+ OBJTYPE_CAMERA = 0x00000010,
+ OBJTYPE_LIGHT = 0x00000020,
+ OBJTYPE_MODEL = 0x00000040,
+ OBJTYPE_GROUP = 0x00000080,
+ OBJTYPE_IMAGE = 0x00000400,
+ OBJTYPE_TEXT = 0x00001000,
+ OBJTYPE_COMPONENT = 0x00002000,
+ OBJTYPE_SLIDE = 0x00004000,
+ OBJTYPE_EFFECT = 0x00008000,
+ OBJTYPE_RENDERPLUGIN = 0x00010000,
+ OBJTYPE_CUSTOMMATERIAL = 0x00020000,
+ OBJTYPE_REFERENCEDMATERIAL = 0x00040000,
+ OBJTYPE_GUIDE = 0x00080000,
+ OBJTYPE_ALIAS = 0x00100000,
+ OBJTYPE_PATH = 0x00200000,
+ OBJTYPE_PATHANCHORPOINT = 0x00400000,
+ OBJTYPE_SUBPATH = 0x00800000,
+ OBJTYPE_SOUND = 0x01000000,
+ OBJTYPE_LIGHTMAPS = 0x02000000,
+};
+
+typedef enum {
+ PRIMITIVETYPE_UNKNOWN = 0,
+ PRIMITIVETYPE_RECT,
+ PRIMITIVETYPE_SPHERE,
+ PRIMITIVETYPE_CONE,
+ PRIMITIVETYPE_CYLINDER,
+ PRIMITIVETYPE_BOX,
+
+} EPrimitiveType;
+
+typedef enum {
+ PRIMITIVEMODE_UNKNOWN = 0,
+ PRIMITIVEMODE_SINGLESIDED = 1,
+ PRIMITIVEMODE_DOUBLESIDED = 2,
+ PRIMITIVEMODE_SEPARATE_MATERIALS = 4,
+
+} EPrimitiveMode;
+
+/**
+Text box type.
+ */
+enum ETextTextType {
+ ETextTextTypeLine, ///<Line
+ ETextTextTypeParagraph, ///<Paragraph
+
+ ETextTextType_Last
+};
+
+/**
+Treatment of text by the rendering engine
+ */
+enum ETextRenderStyle {
+ ETextRenderStyleFlat, ///<The text will always face the camera and not scale
+ ETextRenderStyleDepth, ///<The text will always face the camera, but grow larger or smaller
+ ///based on distance
+ ETextRenderStyleFullPerspective, ///<The text is treated as full 3D
+
+ ETextRenderStyle_Last
+};
+
+/**
+Horizontal Alignment
+ */
+enum ETextHorzAlign {
+ ETextHorzAlignLeft, ///<Left
+ ETextHorzAlignCenter, ///<Center
+ ETextHorzAlignRight, ///<Right
+
+ ETextHorzAlign_Last
+};
+
+/**
+Vertical Alignment
+ */
+enum ETextVertAlign {
+ ETextVertAlignTop, ///<Top
+ ETextVertAlignMiddle, ///<Middle
+ ETextVertAlignBottom, ///<Bottom
+
+ ETextVertAlign_Last
+};
+
+class CStudioObjectTypes
+{
+public:
+ static bool AcceptableParent(EStudioObjectType inChild, EStudioObjectType inParent);
+
+ static const QString &GetNormalIconName(EStudioObjectType inType);
+ static const QString &GetDisabledIconName(EStudioObjectType inType);
+ static const QString &GetHighlightIconName(EStudioObjectType inType);
+
+};
+
+#endif // INCLUDED_STUDIO_OBJECTTYPES_H
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
new file mode 100644
index 00000000..aed2330d
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
@@ -0,0 +1,1854 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+#include "StudioPreferences.h"
+#include "Preferences.h"
+#include "CColor.h"
+#include "MasterP.h"
+#include "versionnumber.h"
+#include "CommonConstants.h"
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+#include <QtGui/qpalette.h>
+#include <QtQml/qqmlcontext.h>
+
+::CColor s_BaseColor;
+::CColor s_LightBaseColor;
+::CColor s_DarkBaseColor;
+::CColor s_NormalColor;
+::CColor s_MasterColor;
+::CColor s_InactiveColor;
+::CColor s_MouseOverHighlightColor;
+::CColor s_SelectColor;
+::CColor s_ButtonDownColor;
+::CColor s_TopRowColor;
+::CColor s_LayerBackgroundColor;
+::CColor s_LayerHighlightBGColor;
+::CColor s_ExtendedLockedLightColor;
+::CColor s_LockedBorderColor;
+::CColor s_ScrollThumbShadowColor;
+::CColor s_ScrollThumbGripHighlightColor;
+::CColor s_ScrollThumbGripShadowColor;
+::CColor s_ScrollThumbHighlightColor;
+::CColor s_ScrollBGOutlineColor;
+::CColor s_ScrollBGColor;
+::CColor s_TextBoxBGColorWithFocus;
+::CColor s_ControlRectBottomLineDarkColor;
+::CColor s_ControlRectBottomLineColor;
+::CColor s_ControlRectSideLineColor;
+::CColor s_ControlRectTopLineColor;
+::CColor s_ExtendedObjectLightColor;
+::CColor s_ComboEditBoxGradientStartColor;
+::CColor s_TimebarBorderColor;
+::CColor s_RowTopColor;
+::CColor s_ButtonHighlightColor;
+::CColor s_PropertyFloorColor;
+::CColor s_ButtonShadowColor;
+::CColor s_TreeFloorColor;
+::CColor s_TabButtonDownColor;
+::CColor s_DisabledTextColor;
+
+QColor s_studioColor1;
+QColor s_studioColor2;
+QColor s_studioColor3;
+QColor s_backgroundColor;
+QColor s_guideColor;
+QColor s_selectionColor;
+QColor s_textColor;
+QColor s_masterColor;
+QColor s_disabledColor;
+int s_fontSize;
+int s_controlBaseHeight;
+int s_idWidth;
+int s_valueWidth;
+QSize s_browserPopupSize;
+
+bool CStudioPreferences::m_SudoMode = false;
+bool CStudioPreferences::m_DebugTimes = false;
+
+// Static Consts
+const ::CColor CStudioPreferences::EDITVIEW_DEFAULTBGCOLOR = ::CColor("#262829");
+
+CStudioPreferences::CStudioPreferences()
+{
+}
+
+CStudioPreferences::~CStudioPreferences()
+{
+}
+
+//==============================================================================
+/**
+ * Loads the default preferences from the registry. Must be called after the
+ * registry root has been set up, and before calling any of the Get functions.
+ */
+void CStudioPreferences::LoadPreferences()
+{
+ s_BaseColor = CPreferences::GetUserPreferences("Preferences")
+ .GetColorValue("BaseColor", ::CColor("#262829"));
+
+ s_NormalColor = CPreferences::GetUserPreferences("Preferences")
+ .GetColorValue("NormalColor", ::CColor("#ffffff"));
+ s_MasterColor = CPreferences::GetUserPreferences("Preferences")
+ .GetColorValue("MasterColor", ::CColor("#5caa15"));
+
+ s_InactiveColor = ::CColor("#727476");
+
+ s_LightBaseColor = s_BaseColor;
+ s_LightBaseColor.SetLuminance(s_LightBaseColor.GetLuminance() + 0.07f);
+
+ s_DarkBaseColor = s_BaseColor;
+ s_DarkBaseColor.SetLuminance(s_DarkBaseColor.GetLuminance() - 0.10f);
+
+ s_MouseOverHighlightColor = s_BaseColor;
+ s_MouseOverHighlightColor.SetLuminance(s_MouseOverHighlightColor.GetLuminance() - 0.05f);
+
+ s_SelectColor = s_BaseColor;
+ s_SelectColor.SetLuminance(s_SelectColor.GetLuminance() - 0.10f);
+
+ s_ButtonDownColor = s_DarkBaseColor; // CPreferences::GetUserPreferences( "Preferences"
+ // ).GetColorValue( "ButtonDownColor", ::CColor( 118, 202,
+ // 8 ) );
+
+ m_SudoMode = CPreferences::GetUserPreferences().GetValue("sudo", false);
+ m_DebugTimes = CPreferences::GetUserPreferences().GetValue("DebugTimes", false);
+
+ s_TopRowColor = s_BaseColor;
+ s_TopRowColor.SetLuminance(s_TopRowColor.GetLuminance() - 0.10f);
+
+ s_ExtendedLockedLightColor = s_BaseColor;
+ s_ExtendedLockedLightColor.SetLuminance(s_ExtendedLockedLightColor.GetLuminance() + 0.07f);
+
+ s_LockedBorderColor = s_BaseColor;
+ s_LockedBorderColor.SetLuminance(s_LockedBorderColor.GetLuminance() - 0.07f);
+
+ s_ScrollThumbShadowColor = s_BaseColor;
+ s_ScrollThumbShadowColor.SetLuminance(s_ScrollThumbShadowColor.GetLuminance() - 0.50f);
+
+ s_ScrollThumbGripHighlightColor = s_BaseColor;
+ s_ScrollThumbGripHighlightColor.SetLuminance(s_ScrollThumbGripHighlightColor.GetLuminance()
+ + 0.15f);
+
+ s_ScrollThumbGripShadowColor = s_BaseColor;
+ s_ScrollThumbGripShadowColor.SetLuminance(s_ScrollThumbGripShadowColor.GetLuminance() - 0.30f);
+
+ s_ScrollThumbHighlightColor = s_BaseColor;
+ s_ScrollThumbHighlightColor.SetLuminance(s_ScrollThumbHighlightColor.GetLuminance() + 0.15f);
+
+ s_ScrollBGOutlineColor = s_BaseColor;
+ s_ScrollBGOutlineColor.SetLuminance(s_ScrollBGOutlineColor.GetLuminance() - 0.30f);
+
+ s_ScrollBGColor = s_BaseColor;
+ s_ScrollBGColor.SetLuminance(s_ScrollBGColor.GetLuminance() - 0.06f);
+
+ s_TextBoxBGColorWithFocus = s_BaseColor;
+ s_TextBoxBGColorWithFocus.SetLuminance(s_TextBoxBGColorWithFocus.GetLuminance() + 0.20f);
+
+ s_ControlRectBottomLineDarkColor = s_BaseColor;
+ s_ControlRectBottomLineDarkColor.SetLuminance(s_ControlRectBottomLineDarkColor.GetLuminance()
+ - 0.50f);
+
+ s_ControlRectBottomLineColor = s_BaseColor;
+ s_ControlRectBottomLineColor.SetLuminance(s_ControlRectBottomLineColor.GetLuminance() - 0.20f);
+
+ s_ControlRectSideLineColor = s_BaseColor;
+ s_ControlRectSideLineColor.SetLuminance(s_ControlRectSideLineColor.GetLuminance() - 0.20f);
+
+ s_ControlRectTopLineColor = s_BaseColor;
+ s_ControlRectTopLineColor.SetLuminance(s_ControlRectTopLineColor.GetLuminance() - 0.30f);
+
+ s_ExtendedObjectLightColor = s_BaseColor;
+ s_ExtendedObjectLightColor.SetLuminance(s_ExtendedObjectLightColor.GetLuminance() + 0.13f);
+
+ s_ComboEditBoxGradientStartColor = s_BaseColor;
+ s_ComboEditBoxGradientStartColor.SetLuminance(s_ComboEditBoxGradientStartColor.GetLuminance()
+ + 0.14f);
+
+ s_TimebarBorderColor = s_BaseColor;
+ s_TimebarBorderColor.SetLuminance(s_TimebarBorderColor.GetLuminance() - 0.45f);
+
+ s_RowTopColor = s_BaseColor;
+ s_RowTopColor.SetLuminance(s_RowTopColor.GetLuminance() - 0.45f);
+
+ s_ButtonHighlightColor = s_BaseColor;
+ s_ButtonHighlightColor.SetLuminance(s_ButtonHighlightColor.GetLuminance() + 0.14f);
+
+ s_PropertyFloorColor = s_BaseColor;
+ s_PropertyFloorColor.SetLuminance(s_PropertyFloorColor.GetLuminance() - 0.07f);
+
+ s_ButtonShadowColor = s_BaseColor;
+ s_ButtonShadowColor.SetLuminance(s_ButtonShadowColor.GetLuminance() - 0.45f);
+
+ s_TreeFloorColor = s_BaseColor;
+ s_TreeFloorColor.SetLuminance(s_TreeFloorColor.GetLuminance() - 0.07f);
+
+ s_TabButtonDownColor = ::CColor(175, 175, 175); // rgb value is 249, 255, 195
+ s_DisabledTextColor = ::CColor(128, 128, 128);
+
+ s_studioColor1 = QColor("#262829");
+ s_studioColor2 = QColor("#404244");
+ s_studioColor3 = QColor("#727476");
+ s_backgroundColor = QColor("#2e2f30");
+ s_guideColor = QColor("#f4be04");
+ s_selectionColor = QColor("#23516D");
+ s_textColor = QColor("#ffffff");
+ s_masterColor = QColor("#5caa15");
+ s_disabledColor = QColor("#727476");
+ s_fontSize = 12;
+ s_controlBaseHeight = 22;
+ s_idWidth = 130;
+ s_valueWidth = 250;
+ s_browserPopupSize = QSize(400, 400);
+}
+
+//==============================================================================
+/**
+ * Returns the state of the timeline snapping grid
+ * @return true if the snapping grid is active
+ */
+bool CStudioPreferences::IsTimelineSnappingGridActive()
+{
+ return CPreferences::GetUserPreferences().GetValue("SnappingGridActive", true);
+}
+
+//==============================================================================
+/**
+ * Sets the state of the timeline snapping grid
+ * @param inActiveFlag true if the snapping grid is active
+ */
+void CStudioPreferences::SetTimelineSnappingGridActive(bool inActive)
+{
+ CPreferences::GetUserPreferences().SetValue("SnappingGridActive", inActive);
+}
+
+//==============================================================================
+/**
+ * Gets the timeline snapping grid resolution
+ * @return Index value for the snapping resolution:
+ * (See StudioConst.h for these values)
+ */
+ESnapGridResolution CStudioPreferences::GetTimelineSnappingGridResolution()
+{
+ return (ESnapGridResolution)CPreferences::GetUserPreferences().GetLongValue(
+ "SnappingGridResolution", (long)SNAPGRID_SECONDS);
+}
+
+//==============================================================================
+/**
+ * Sets the timeline snapping grid resolution
+ * @param inSnappingResolution Index value for the snapping resolution:
+ * (See StudioConst.h for these values)
+ */
+void CStudioPreferences::SetTimelineSnappingGridResolution(ESnapGridResolution inResolution)
+{
+ CPreferences::GetUserPreferences().SetLongValue("SnappingGridResolution", (long)inResolution);
+}
+
+//==============================================================================
+/**
+ * Sets the default preview application.
+ * @param inApplication Application to use for preview.
+ */
+void CStudioPreferences::SetDefaultApplication(const Q3DStudio::CString &inApplication)
+{
+ CPreferences::GetUserPreferences().SetStringValue("PreviewAppString", inApplication);
+}
+
+//==============================================================================
+/**
+ * Returns the default preview application.
+ */
+Q3DStudio::CString CStudioPreferences::GetDefaultApplication()
+{
+ return CPreferences::GetUserPreferences().GetStringValue("PreviewAppString",
+ L"Quarterback"); // TODO: Localize
+}
+
+//==============================================================================
+/**
+ * Returns true if help should be shown on Studio launch.
+ * Checks the registry to determine if the Help Palette should be displayed
+ * on launch of Studio.
+ * @return TRUE if the Help Palette should be shown, otherwise FALSE.
+ */
+bool CStudioPreferences::ShowHelpOnLaunch()
+{
+ return CPreferences::GetUserPreferences().GetValue("ShowHelp", true);
+}
+
+//==============================================================================
+/**
+ * Sets the preference for showing the Help Palette on Studio launch.
+ * Changes a value in the registry (if the key could be opened) which determines
+ * whether or not to show the Help Palette on launch of Studio.
+ * @param inValue false to show the Help Palette on launch, otherwise false
+ */
+void CStudioPreferences::SetShowHelpOnLaunch(bool inShowHelp)
+{
+ CPreferences::GetUserPreferences().SetValue("ShowHelp", inShowHelp);
+}
+
+//==============================================================================
+/**
+ * Get the background color of the editing view
+ * @return the color of the editing view
+ */
+::CColor CStudioPreferences::GetEditViewBackgroundColor()
+{
+ return CPreferences::GetUserPreferences().GetColorValue("EditViewBGColor",
+ EDITVIEW_DEFAULTBGCOLOR);
+}
+
+//==============================================================================
+/**
+ * Set the background color of the editing view
+ * @param inColor the color of the editing view
+ */
+void CStudioPreferences::SetEditViewBackgroundColor(::CColor inColor)
+{
+ CPreferences::GetUserPreferences().SetColorValue("EditViewBGColor", inColor);
+}
+
+//==============================================================================
+/**
+ * Get the fill mode to render the geometries when in editing view
+ * @return true to render as solid, else as wireframe
+ */
+bool CStudioPreferences::GetEditViewFillMode()
+{
+ return CPreferences::GetUserPreferences().GetValue("EditViewFillMode", true);
+}
+
+//==============================================================================
+/**
+ * Set the fill mode to render the geometries when in editing view
+ * @param inRenderAsSolid true to render as solid, else as wireframe
+ */
+void CStudioPreferences::SetEditViewFillMode(bool inRenderAsSolid)
+{
+ CPreferences::GetUserPreferences().SetValue("EditViewFillMode", inRenderAsSolid);
+}
+
+//==============================================================================
+/**
+ * Get the preferred startup view. -1 means the scene view and positive value
+ * means the index of the editing camera, thus the view
+ */
+long CStudioPreferences::GetPreferredStartupView()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("PreferredStartupView", -1);
+}
+
+//==============================================================================
+/**
+ * Set the preferred startup view. -1 means the scene view and positive value
+ * means the index of the editing camera, thus the view
+ * @param inStartupView the preferred startup view of new presentation.
+ */
+void CStudioPreferences::SetPreferredStartupView(long inStartupView)
+{
+ CPreferences::GetUserPreferences().SetLongValue("PreferredStartupView", inStartupView);
+}
+
+//==============================================================================
+/**
+ * Indicates whether or not auto keyframing is turned on.
+ * Fetches the autoset keyframes preference from the registry.
+ * @return true if autoset keyframes is turned on, otherwise false
+ */
+bool CStudioPreferences::IsAutosetKeyframesOn()
+{
+ return CPreferences::GetUserPreferences().GetValue("AutosetKeyframes", true);
+}
+
+//==============================================================================
+/**
+ * Sets the autoset keyframe preference.
+ * Saves the autoset keyframes preference in the registry.
+ * @param inEnable TRUE to enable autosetting of keyframes
+ */
+void CStudioPreferences::SetAutosetKeyframesOn(bool inEnable)
+{
+ CPreferences::GetUserPreferences().SetValue("AutosetKeyframes", inEnable);
+}
+
+//==============================================================================
+/**
+ * Indicates whether or not displaying bounding box is turned on.
+ * Fetches the displaying bounding box preference from the registry.
+ * @return true if displaying bounding box is turned on, otherwise false
+ */
+bool CStudioPreferences::IsBoundingBoxesOn()
+{
+ return CPreferences::GetUserPreferences().GetValue("BoundingBoxes", true);
+}
+
+//==============================================================================
+/**
+ * Sets the preference to whether display the bounding box
+ * Saves the bounding box displaying preference in the registry.
+ * @param inEnable TRUE to enable display the bounding box
+ */
+void CStudioPreferences::SetBoundingBoxesOn(bool inEnable)
+{
+ CPreferences::GetUserPreferences().SetValue("BoundingBoxes", inEnable);
+}
+
+//==============================================================================
+/**
+ * Indicates whether or not displaying pivot point is turned on.
+ * Fetches the displaying pivot point preference from the registry.
+ * @return true if displaying pivot point is turned on, otherwise false
+ */
+bool CStudioPreferences::ShouldDisplayPivotPoint()
+{
+ return CPreferences::GetUserPreferences().GetValue("Display Pivot Point", true);
+}
+
+//==============================================================================
+/**
+ * Sets the preference to whether display the pivot point
+ * Saves the pivot point displaying preference in the registry.
+ * @param inEnable TRUE to enable display the pivot point
+ */
+void CStudioPreferences::SetDisplayPivotPoint(bool inEnable)
+{
+ return CPreferences::GetUserPreferences().SetValue("Display Pivot Point", inEnable);
+}
+
+//==============================================================================
+/**
+ * Indicates whether or not displaying geometry as wireframe.
+ * Fetches the displaying wireframe mode preference from the registry.
+ * @return true if displaying wireframe mode is turned on, otherwise false
+ */
+bool CStudioPreferences::IsWireframeModeOn()
+{
+ return CPreferences::GetUserPreferences().GetValue("WireframeMode", true);
+}
+
+//==============================================================================
+/**
+ * Sets the preference to whether display geometry in wireframe mode
+ * Saves thewireframe mode displaying preference in the registry.
+ * @param inEnable TRUE to enable display the bounding box
+ */
+void CStudioPreferences::SetWireframeModeOn(bool inEnable)
+{
+ CPreferences::GetUserPreferences().SetValue("WireframeMode", inEnable);
+}
+
+//==============================================================================
+/**
+ * Indicates whether or not to show tooltips on inspector palette.
+ * Retrieves tooltip visibility preference from the registry.
+ * @return true if tooltips should be shown, false if tooltips should not be shown.
+ */
+bool CStudioPreferences::ShouldShowTooltips()
+{
+ return CPreferences::GetUserPreferences().GetValue("ShowTooltips", true);
+}
+
+//==============================================================================
+/**
+ * Indicates whether or not to show tooltips on inspector palette.
+ * Saves tooltip visibility preference in the registry.
+ * @param inEnable true if tooltips should be shown, false if tooltips should not be shown.
+ */
+void CStudioPreferences::SetShowTooltips(bool inShowTooltips)
+{
+ CPreferences::GetUserPreferences().SetValue("ShowTooltips", inShowTooltips);
+}
+
+//==============================================================================
+/**
+ * @return the color to use for the background of a tooltip
+ */
+::CColor CStudioPreferences::GetTooltipBackgroundColor()
+{
+ ::CColor theTooltipBGColor(255, 255, 225);
+
+#ifdef WIN32
+ // On windows, get the color from the system
+ ::CColor theWinColor(::GetSysColor(COLOR_INFOBK));
+ theTooltipBGColor = theWinColor;
+#endif
+
+ return theTooltipBGColor;
+}
+
+//==============================================================================
+/**
+ * Returns the preferred location of the timeline's splitter bar.
+ */
+long CStudioPreferences::GetTimelineSplitterLocation()
+{
+ return CPreferences::GetUserPreferences("Timeline").GetLongValue("TimelineSplitterLoc", 250);
+}
+
+//==============================================================================
+/**
+ * Stores the location of the splitter bar in the timeline.
+ * @param inLocation location of the splitter
+ */
+void CStudioPreferences::SetTimelineSplitterLocation(long inLocation)
+{
+ CPreferences::GetUserPreferences("Timeline").SetLongValue("TimelineSplitterLoc", inLocation);
+}
+
+//==============================================================================
+/**
+ * Returns the preferred location of the Inspector Palette's splitter bar.
+ */
+long CStudioPreferences::GetInspectorSplitterLocation()
+{
+ return CPreferences::GetUserPreferences("Inspector").GetLongValue("InspectorSplitterLoc", 100);
+}
+
+//==============================================================================
+/**
+ * Stores the location of the splitter bar in the Inspector Palette.
+ * @param inLocation location of the splitter
+ */
+void CStudioPreferences::SetInspectorSplitterLocation(long inLocation)
+{
+ CPreferences::GetUserPreferences("Inspector").SetLongValue("InspectorSplitterLoc", inLocation);
+}
+
+//==============================================================================
+/**
+ * Gets the preferred method of interpolation.
+ * Indicates whether the user prefers smooth or linear interpolation by default.
+ * @return true indicates that smooth interpolation is preferred, false indicates linear
+ *interpolation.
+ */
+bool CStudioPreferences::GetInterpolation()
+{
+ return CPreferences::GetUserPreferences().GetValue("InterpolationPreference", true);
+}
+
+//==============================================================================
+/**
+ * Saves the preferred interpolation method in the registry.
+ * @param inSmooth true indicates smooth interpolation, false indicates linear
+ */
+void CStudioPreferences::SetInterpolation(bool inSmooth)
+{
+ CPreferences::GetUserPreferences().SetValue("InterpolationPreference", inSmooth);
+}
+
+//==============================================================================
+/**
+ * Gets the snapping range of the timebars from the registry.
+ * @return New range in milliseconds.
+ */
+long CStudioPreferences::GetSnapRange()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("SnapRange", (long)10);
+}
+
+//==============================================================================
+/**
+ * Sets the snapping range of the timebars by saving value in registry.
+ * @param inSnapRange New range in milliseconds.
+ */
+void CStudioPreferences::SetSnapRange(long inSnapRange)
+{
+ CPreferences::GetUserPreferences().SetLongValue("SnapRange", inSnapRange);
+}
+
+//==============================================================================
+/**
+ * Gets the delay between auto saves from the registry.
+ * @return autosave delay in minutes.
+ */
+long CStudioPreferences::GetAutoSaveDelay()
+{
+ // default delay is 10 minutes
+ return CPreferences::GetUserPreferences("AutoSave").GetLongValue("Delay", (long)10);
+}
+
+//==============================================================================
+/**
+ * Sets the delay between auto saves by saving value in registry.
+ * @param inDelay New autosave delay in minutes.
+ */
+void CStudioPreferences::SetAutoSaveDelay(long inAutoSaveDelay)
+{
+ CPreferences::GetUserPreferences("AutoSave").SetLongValue("Delay", inAutoSaveDelay);
+}
+
+//==============================================================================
+/**
+ * Returns true if Auto Saving is turned on.
+ * AutoSaving is turned OFF by default.
+ *
+ * @return true if autosaving is on.
+ */
+bool CStudioPreferences::GetAutoSavePreference()
+{
+ return CPreferences::GetUserPreferences("AutoSave").GetValue("Preference", false);
+}
+
+//==============================================================================
+/**
+ * Sets user preference of whether to autosave.
+ * @param inActive user autosave preference.
+ */
+void CStudioPreferences::SetAutoSavePreference(bool inActive)
+{
+ CPreferences::GetUserPreferences("AutoSave").SetValue("Preference", inActive);
+}
+
+//==============================================================================
+/**
+ * Gets the default object lifetime.
+ * The Preferences dialog can change the default object lifetime. When an
+ * object is created, this is how long it should be alive for by default.
+ * The value is stored in the registry.
+ * @return New lifetime in milliseconds.
+ */
+long CStudioPreferences::GetDefaultObjectLifetime()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("DefaultObjectLifetime", (long)10000);
+}
+
+//==============================================================================
+/**
+ * Sets the default object lifetime.
+ * The Preferences dialog can change the default object lifetime. When an
+ * object is created, this is how long it should be alive for by default.
+ * The value is stored in the registry.
+ * @param inAmount New lifetime in milliseconds.
+ */
+void CStudioPreferences::SetDefaultObjectLifetime(long inLifetime)
+{
+ CPreferences::GetUserPreferences().SetLongValue("DefaultObjectLifetime", inLifetime);
+}
+
+//==============================================================================
+/**
+ * Gets the current timebar setting.
+ * Timebars will be able to display different information such as user-defined
+ * comments or the start/end time of the timebar. This setting toggles between
+ * the two modes. The values are stored in the registry.
+ * @return true if time is being displayed
+ */
+bool CStudioPreferences::GetTimebarDisplayTime()
+{
+ return CPreferences::GetUserPreferences().GetValue("TimebarSetting", false);
+}
+
+//==============================================================================
+/**
+ * Sets the timebar setting.
+ * The Preferences dialog can change the default timebar setting. A timebar
+ * can show either time information, or comments entered by the user. The value
+ * is stored in the registry and preserved between sessions.
+ * @param inShowTime True if the time should be shown
+ */
+void CStudioPreferences::SetTimebarDisplayTime(bool inDisplayTime)
+{
+ CPreferences::GetUserPreferences().SetValue("TimebarSetting", inDisplayTime);
+}
+
+//==============================================================================
+/**
+ * Gets the amount to nudge the selection by.
+ * When an object is selected, it can be nudged by using the arrow keys. This
+ * function gets the nudge amount from the registry, or returns a default value
+ * if the registry entry does not exist. The nudge amount can be set with the
+ * Preferences dialog.
+ * @return The amount to nudge by
+ */
+double CStudioPreferences::GetNudgeAmount()
+{
+ return CPreferences::GetUserPreferences().GetValue("NudgeAmount", 10.0);
+}
+
+//==============================================================================
+/**
+ * Sets the amount to nudge the object by.
+ * When an object is selected, it can be nudged by using the arrow keys. This
+ * function stores the nudge amount in the registry.
+ * @param inAmount Amount to nudge by
+ */
+void CStudioPreferences::SetNudgeAmount(double inNudgeAmount)
+{
+ CPreferences::GetUserPreferences().SetValue("NudgeAmount", inNudgeAmount);
+}
+
+//==============================================================================
+/**
+ * Gets the advance property expanded flag
+ * When an object is selected, this universal flag is used for either toggle
+ * the advance properties on or off but will not be visually available in
+ * the application preference dialog and default to false.
+ * @return The expanded flag
+ */
+bool CStudioPreferences::GetAdvancePropertyExpandedFlag()
+{
+ return CPreferences::GetUserPreferences().GetValue("AdvancePropertyFlag", false);
+}
+
+//==============================================================================
+/**
+ * Sets the expanded flag for object when toggled
+ * @param inAdvancePropertyFlag Save the last toggle flag
+ */
+void CStudioPreferences::SetAdvancePropertyExpandedFlag(bool inAdvancePropertyFlag)
+{
+ CPreferences::GetUserPreferences().SetValue("AdvancePropertyFlag", inAdvancePropertyFlag);
+}
+
+Q3DStudio::CString CStudioPreferences::GetPreviewConfig()
+{
+ return CPreferences::GetUserPreferences().GetStringValue("Preview.Config", "");
+}
+
+void CStudioPreferences::SetPreviewConfig(const Q3DStudio::CString &inValue)
+{
+ CPreferences::GetUserPreferences().SetStringValue("Preview.Config", inValue);
+}
+
+// Preview Properties at the registry are prepend with Preview.
+Q3DStudio::CString CStudioPreferences::GetPreviewProperty(const Q3DStudio::CString &inName)
+{
+ Q3DStudio::CString theName = "Preview." + inName;
+ return CPreferences::GetUserPreferences().GetStringValue(theName, "");
+}
+
+void CStudioPreferences::SetPreviewProperty(const Q3DStudio::CString &inName,
+ const Q3DStudio::CString &inValue)
+{
+ Q3DStudio::CString theName = "Preview." + inName;
+ CPreferences::GetUserPreferences().SetStringValue(theName, inValue);
+}
+
+//=============================================================================
+/**
+ * Get whether we should show OpenGL Version Warning or Error Dialog
+ * This is used to disable / enable OpenGL Version checking
+ * @return true if user don't want to see the GL Version warning dialog
+ */
+bool CStudioPreferences::GetDontShowGLVersionDialog()
+{
+ return CPreferences::GetUserPreferences().GetValue("DontShowGLVersionDialog", false);
+}
+
+//=============================================================================
+/**
+ * Set whether we should show OpenGL Version Warning or Error Dialog
+ * This is used to disable / enable OpenGL Version checking
+ */
+void CStudioPreferences::SetDontShowGLVersionDialog(bool inValue)
+{
+ CPreferences::GetUserPreferences().SetValue("DontShowGLVersionDialog", inValue);
+}
+
+//==============================================================================
+/**
+ * Gets the size that the object reference dialog should be displayed.
+ * @return the size as a point.
+ */
+CPt CStudioPreferences::GetObjectReferenceGadgetSize()
+{
+ CPt theSize;
+ theSize.x = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("ObjectReferenceWidth", 250);
+ theSize.y = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("ObjectReferenceHeight", 250);
+ return theSize;
+}
+
+//==============================================================================
+/**
+ * Gets the position that the object reference dialog should be displayed.
+ * @return the position as a point.
+ */
+CPt CStudioPreferences::GetObjectReferenceGadgetPosition(const CPt &inDefault)
+{
+ CPt thePosition;
+ thePosition.x = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("ObjectReferenceXPos", inDefault.x);
+ thePosition.y = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("ObjectReferenceYPos", inDefault.y);
+ return thePosition;
+}
+
+//==============================================================================
+/**
+ * Gets the size that the property reference dialog should be displayed.
+ * @return the size as a point.
+ */
+CPt CStudioPreferences::GetPropertyReferenceGadgetSize()
+{
+ CPt theSize;
+ theSize.x = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("PropertyReferenceWidth", 250);
+ theSize.y = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("PropertyReferenceHeight", 250);
+ return theSize;
+}
+
+//==============================================================================
+/**
+ * Gets the position that the property reference dialog should be displayed.
+ * @return the position as a point.
+ */
+CPt CStudioPreferences::GetPropertyReferenceGadgetPosition(const CPt &inDefault)
+{
+ CPt thePosition;
+ thePosition.x = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("PropertyReferenceXPos", inDefault.x);
+ thePosition.y = CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .GetLongValue("PropertyReferenceYPos", inDefault.y);
+ return thePosition;
+}
+
+//==============================================================================
+/**
+ * Gets the size that the object reference dialog should be displayed.
+ * @return the size as a point.
+ */
+CPt CStudioPreferences::GetDefaultClientSize()
+{
+ CPt theSize;
+ theSize.x = CPreferences::GetUserPreferences().GetLongValue("DefaultClientWidth", 800);
+ theSize.y = CPreferences::GetUserPreferences().GetLongValue("DefaultClientHeight", 480);
+ return theSize;
+}
+
+bool CStudioPreferences::GetCanImportComponent()
+{
+ return CPreferences::GetUserPreferences().GetValue("CanImportComponent", false);
+}
+
+//==============================================================================
+/**
+ * Sets the size that the object reference dialog should be displayed.
+ */
+void CStudioPreferences::SetObjectReferenceGadgetSize(const CPt &inSize)
+{
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("ObjectReferenceWidth", inSize.x);
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("ObjectReferenceHeight", inSize.y);
+}
+
+//==============================================================================
+/**
+ * Sets the position that the object reference dialog should be displayed.
+ */
+void CStudioPreferences::SetObjectReferenceGadgetPosition(const CPt &inPosition)
+{
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("ObjectReferenceXPos", inPosition.x);
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("ObjectReferenceYPos", inPosition.y);
+}
+
+//==============================================================================
+/**
+ * Sets the size that the property reference dialog should be displayed.
+ */
+void CStudioPreferences::SetPropertyReferenceGadgetSize(const CPt &inSize)
+{
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("PropertyReferenceWidth", inSize.x);
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("PropertyReferenceHeight", inSize.y);
+}
+
+//==============================================================================
+/**
+ * Sets the position that the property reference dialog should be displayed.
+ */
+void CStudioPreferences::SetPropertyReferenceGadgetPosition(const CPt &inPosition)
+{
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("PropertyReferenceXPos", inPosition.x);
+ CPreferences::GetUserPreferences(L"ReferenceGadgets" /* TODO: Localize */)
+ .SetLongValue("PropertyReferenceYPos", inPosition.y);
+}
+
+//==============================================================================
+/**
+ * Gets the size that the object reference dialog should be displayed.
+ * @return the size as a point.
+ */
+CPt CStudioPreferences::GetHandlerReferenceGadgetSize()
+{
+ CPt theSize;
+ theSize.x = CPreferences::GetUserPreferences().GetLongValue("HandlerReferenceWidth", 250);
+ theSize.y = CPreferences::GetUserPreferences().GetLongValue("HandlerReferenceHeight", 250);
+ return theSize;
+}
+
+//==============================================================================
+/**
+ * Sets the size that the object reference dialog should be displayed.
+ */
+void CStudioPreferences::SetHandlerReferenceGadgetSize(const CPt &inSize)
+{
+ CPreferences::GetUserPreferences().SetLongValue("HandlerReferenceWidth", inSize.x);
+ CPreferences::GetUserPreferences().SetLongValue("HandlerReferenceHeight", inSize.y);
+}
+
+//==============================================================================
+/**
+ * Gets the size that the object reference dialog should be displayed.
+ * @return the size as a point.
+ */
+CPt CStudioPreferences::GetEventReferenceGadgetSize()
+{
+ CPt theSize;
+ theSize.x = CPreferences::GetUserPreferences().GetLongValue("EventReferenceWidth", 250);
+ theSize.y = CPreferences::GetUserPreferences().GetLongValue("EventReferenceHeight", 250);
+ return theSize;
+}
+
+//==============================================================================
+/**
+ * Sets the size that the object reference dialog should be displayed.
+ */
+void CStudioPreferences::SetEventReferenceGadgetSize(const CPt &inSize)
+{
+ CPreferences::GetUserPreferences().SetLongValue("EventReferenceWidth", inSize.x);
+ CPreferences::GetUserPreferences().SetLongValue("EventReferenceHeight", inSize.y);
+}
+
+//==============================================================================
+/**
+ * Gets the size that the object reference dialog should be displayed.
+ * @return the size as a point.
+ */
+CRct CStudioPreferences::GetMultilineTextLocation()
+{
+ CRct theLocation;
+ theLocation.position.x =
+ CPreferences::GetUserPreferences().GetLongValue("MultilineTextPosX", 0);
+ theLocation.position.y =
+ CPreferences::GetUserPreferences().GetLongValue("MultilineTextPosY", 0);
+ theLocation.size.x = CPreferences::GetUserPreferences().GetLongValue("MultilineTextSizeX", 200);
+ theLocation.size.y = CPreferences::GetUserPreferences().GetLongValue("MultilineTextSizeY", 250);
+ return theLocation;
+}
+
+//==============================================================================
+/**
+ * Sets the size that the object reference dialog should be displayed.
+ */
+void CStudioPreferences::SetMultilineTextLocation(const CRct &inLocation)
+{
+ CPreferences::GetUserPreferences().SetLongValue("MultilineTextPosX", inLocation.position.x);
+ CPreferences::GetUserPreferences().SetLongValue("MultilineTextPosY", inLocation.position.y);
+ CPreferences::GetUserPreferences().SetLongValue("MultilineTextSizeX", inLocation.size.x);
+ CPreferences::GetUserPreferences().SetLongValue("MultilineTextSizeY", inLocation.size.y);
+}
+
+//==============================================================================
+/**
+ * Get the amount of time that the playhead should be advanced/reduced when the
+ * '.' and ',' keys are used.
+ */
+long CStudioPreferences::GetTimeAdvanceAmount()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("TimeAdvance", 100);
+}
+
+//==============================================================================
+/**
+ * Sets the amount of time that the playhead should be advanced/reduced when the
+ * '.' and ',' keys are used.
+ */
+void CStudioPreferences::SetTimeAdvanceAmount(const long &inTime)
+{
+ CPreferences::GetUserPreferences().SetLongValue("TimeAdvance", inTime);
+}
+
+//==============================================================================
+/**
+ * Get the amount of time that the playhead should be advanced/reduced when the
+ * '<' and '>' keys are used.
+ */
+long CStudioPreferences::GetBigTimeAdvanceAmount()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("BigTimeAdvance", 200);
+}
+
+//==============================================================================
+/**
+ * Set the amount of time that the playhead should be advanced/reduced when the
+ * '<' and '>' keys are used.
+ */
+void CStudioPreferences::SetBigTimeAdvanceAmount(const long &inTime)
+{
+ CPreferences::GetUserPreferences().SetLongValue("BigTimeAdvance", inTime);
+}
+
+long CStudioPreferences::GetActionSplitterSize()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("ActionSplitterSize", 200);
+}
+
+void CStudioPreferences::SetActionSplitterSize(long inSize)
+{
+ CPreferences::GetUserPreferences().SetLongValue("ActionSplitterSize", inSize);
+}
+
+long CStudioPreferences::GetCustomPropertySplitterSize()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("CustomPropertySplitterSize", 200);
+}
+
+void CStudioPreferences::SetCustomPropertySplitterSize(long inSize)
+{
+ CPreferences::GetUserPreferences().SetLongValue("CustomPropertySplitterSize", inSize);
+}
+
+long CStudioPreferences::GetAssetSplitterSize()
+{
+ return CPreferences::GetUserPreferences().GetLongValue("AssetSplitterSize", 200);
+}
+
+void CStudioPreferences::SetAssetSplitterSize(long inSize)
+{
+ CPreferences::GetUserPreferences().SetLongValue("AssetSplitterSize", inSize);
+}
+
+//==============================================================================
+/**
+ * Gets whether or not to show the version dialog.
+ * Used in some of the serialization to display the file version, problably for
+ * debugging.
+ * @return true if the file version dialog should be displayed.
+ */
+bool CStudioPreferences::ShowVersionDialog()
+{
+ return CPreferences::GetUserPreferences().GetValue("ShowVersionDlg", false);
+}
+
+//==============================================================================
+/**
+ * Sets whether or not to show the version dialog.
+ * Used in some of the serialization to display the file version, problably for
+ * debugging.
+ * @param true if the file version dialog should be displayed.
+ */
+void CStudioPreferences::SetShowVersionDialog(bool inShowVersionDlg)
+{
+ CPreferences::GetUserPreferences().SetValue("ShowVersionDlg", inShowVersionDlg);
+}
+
+//==============================================================================
+/**
+ * Gets whether the client map file should be written out when exporting.
+ * The map file shows where all the file size is made up from and is good when
+ * really trying to get the file size down.
+ * @return true if the map file should be written.
+ */
+bool CStudioPreferences::ShouldWriteMapFile()
+{
+ return CPreferences::GetUserPreferences().GetValue("Map", false);
+}
+
+//==============================================================================
+/**
+ * Default color of the scene from a new presentation.
+ */
+::CColor CStudioPreferences::GetDefaultSceneColor()
+{
+ return CPreferences::GetUserPreferences().GetColorValue("SceneColor", ::CColor(0, 0, 0));
+}
+
+//==============================================================================
+/**
+ * Default color of new primitives.
+ */
+::CColor CStudioPreferences::GetDefaultPrimitiveColor()
+{
+ return CPreferences::GetUserPreferences().GetColorValue("PrimitiveColor",
+ ::CColor(255, 255, 255));
+}
+
+//==============================================================================
+/**
+ * True if debugging timebar lengths.
+ */
+bool CStudioPreferences::IsDebugTimes()
+{
+ return m_DebugTimes;
+}
+
+//==============================================================================
+/**
+ * Color used in between most tree items in the timeline.
+ */
+::CColor CStudioPreferences::GetTreeFloorColor()
+{
+ return s_BaseColor;
+}
+
+//==============================================================================
+/**
+ * @return darker shadow color for use around the edges of most controls
+ */
+::CColor CStudioPreferences::GetButtonShadowColor()
+{
+ return s_BaseColor;
+}
+
+//==============================================================================
+/**
+ * Color to use between property rows and as the darker color behind the highlights
+ * within the timeline.
+ */
+::CColor CStudioPreferences::GetPropertyFloorColor()
+{
+ return s_BaseColor;
+}
+
+::CColor CStudioPreferences::GetButtonHighlightColor()
+{
+ return s_BaseColor;
+}
+
+//==============================================================================
+/**
+ * Retrieves the color that should be used when the mouse goes over a row, such
+ * as in the timeline or inspector palettes.
+ */
+::CColor CStudioPreferences::GetSelectColor()
+{
+ return ::CColor("#46a2da");
+}
+
+::CColor CStudioPreferences::GetTimelineSelectColor()
+{
+ return ::CColor("#23516D"); // The normal select color (#46a2da) does not work with master color
+}
+
+//==============================================================================
+/**
+ * Retrieves the color that should be used when the mouse goes over a row, such
+ * as in the timeline or inspector palettes.
+ */
+::CColor CStudioPreferences::GetMouseOverHighlightColor()
+{
+ return s_MouseOverHighlightColor;
+}
+//==============================================================================
+/**
+ * @return the fill color of the top-most row of a palette (for instance, the fill color behind the
+ * time measure)
+ */
+::CColor CStudioPreferences::GetRowTopColor()
+{
+ return s_RowTopColor;
+}
+
+::CColor CStudioPreferences::GetTimeBarBorderColor()
+{
+ return s_TimebarBorderColor;
+}
+
+//=============================================================================
+/**
+ * @return color to use for the background of a property row in the timeline
+ */
+::CColor CStudioPreferences::GetPropertyBackgroundColor()
+{
+ return s_BaseColor;
+}
+
+//=============================================================================
+/**
+ * @return color to use for the background of a property row in the timeline
+ * when the mouse is over the row
+ */
+::CColor CStudioPreferences::GetPropertyMouseOverColor()
+{
+ return CStudioPreferences::GetMouseOverHighlightColor();
+}
+
+//=============================================================================
+/**
+ * @return color to use for the background of a property row in the timeline
+ */
+::CColor CStudioPreferences::GetComboEditBoxGradientStartColor()
+{
+ return s_ComboEditBoxGradientStartColor;
+}
+
+::CColor CStudioPreferences::GetPropertyTimbarLeft()
+{
+ return s_BaseColor;
+}
+
+//=============================================================================
+/**
+ * Returns the base color which is what most of the other colors derive from.
+ * The base color is also used to fill in empty areas of some controls and
+ * palettes.
+ * @return Base color from which most of the other colors are derived
+ */
+::CColor CStudioPreferences::GetBaseColor()
+{
+ return s_BaseColor;
+}
+
+//=============================================================================
+/**
+ * @return a lighter version of the base color
+ */
+::CColor CStudioPreferences::GetLightBaseColor()
+{
+ return s_LightBaseColor;
+}
+
+//=============================================================================
+/**
+ * @return a darker version of the base color
+ */
+::CColor CStudioPreferences::GetDarkBaseColor()
+{
+ return s_DarkBaseColor;
+}
+
+//=============================================================================
+/**
+ * Returns the normal color used for non-master items and text throughout the UI
+ */
+::CColor CStudioPreferences::GetNormalColor()
+{
+ return s_NormalColor;
+}
+
+//=============================================================================
+/**
+ * Returns the color for master items and text throughout the UI
+ */
+::CColor CStudioPreferences::GetMasterColor()
+{
+ return s_MasterColor;
+}
+
+//=============================================================================
+/**
+ * Returns the color for inactive items and text throughout the UI
+ */
+::CColor CStudioPreferences::GetInactiveColor()
+{
+ return s_InactiveColor;
+}
+
+//=============================================================================
+/**
+ * Returns the background color of the toolbars. This is now just the base color.
+ */
+::CColor CStudioPreferences::GetToolBarBaseColor()
+{
+ return GetBaseColor();
+}
+
+//=============================================================================
+/**
+ * Returns the background color of the menu bar
+ * sk - Ideally this would be the BaseColor (what the palettes are using) but there is a border with
+ * the windows color that
+ * I have not figured where it can be customized, so for the time being, that this fallback on the
+ * old window system color (jason prefers that anyways)
+ * This should be equivalent to if the associated code that uses this color, do not exist, but this
+ * will allow us to easily change the color when we want to.
+ */
+::CColor CStudioPreferences::GetMenuBarBaseColor()
+{
+ QColor theWinColor = QPalette().color(QPalette::Background);
+ return ::CColor(theWinColor.red(), theWinColor.green(), theWinColor.blue());
+}
+
+//=============================================================================
+/**
+ * Returns the "button down color" used by some procedurally drawn CButtonControls.
+ */
+::CColor CStudioPreferences::GetButtonDownColor()
+{
+ return s_ButtonDownColor;
+}
+
+::CColor CStudioPreferences::GetExtendedObjectLightColor()
+{
+ return s_ExtendedObjectLightColor;
+}
+
+::CColor CStudioPreferences::GetExtendedObjectDarkColor()
+{
+ return GetBaseColor();
+}
+
+//=============================================================================
+/**
+ * Controls, such as CTextEdit draw rects with different color sides around the
+ * control. This function retrieves the color for the top line of the rect.
+ */
+::CColor CStudioPreferences::GetControlRectTopLineColor()
+{
+ return s_ControlRectTopLineColor;
+}
+
+//=============================================================================
+/**
+ * Controls, such as CTextEdit draw rects with different color sides around the
+ * control. This function retrieves the color for the left and right lines of
+ * the rect.
+ */
+::CColor CStudioPreferences::GetControlRectSideLineColor()
+{
+ return s_ControlRectSideLineColor;
+}
+
+//=============================================================================
+/**
+ * Controls, such as CTextEdit draw rects with different color sides around the
+ * control. This function retrieves the color for the bottom line of the rect.
+ */
+::CColor CStudioPreferences::GetControlRectBottomLineColor()
+{
+ return s_ControlRectBottomLineColor;
+}
+
+//=============================================================================
+/**
+ * Controls, such as CTextEdit draw rects with different color sides around the
+ * control. This function retrieves the color for the bottom line of the rect,
+ * for certain controls that have a darker bottom line (see CComboTextBox).
+ */
+::CColor CStudioPreferences::GetControlRectBottomLineDarkColor()
+{
+ return s_ControlRectBottomLineDarkColor;
+}
+
+//=============================================================================
+/**
+ * Controls sometimes have a drop-shadow on the top of the control (an indented
+ * control) or on the bottom (an outdented control). This function returns the
+ * appropriate color.
+ */
+::CColor CStudioPreferences::GetControlShadowColor()
+{
+ ::CColor theColor = GetBaseColor();
+ return theColor;
+}
+
+//=============================================================================
+/**
+ * Fill color for text boxes that do not have focus.
+ */
+::CColor CStudioPreferences::GetTextBoxBGColorNoFocus()
+{
+ return s_BaseColor;
+}
+
+//=============================================================================
+/**
+ * Fill color for text boxes that do have focus.
+ */
+::CColor CStudioPreferences::GetTextBoxBGColorWithFocus()
+{
+ return s_TextBoxBGColorWithFocus;
+}
+
+//=============================================================================
+/**
+ * @return background color for scroll bars (behind thumb)
+ */
+::CColor CStudioPreferences::GetScrollBGColor()
+{
+ return s_ScrollBGColor;
+}
+
+//=============================================================================
+/**
+ * @return color for outline of the scroll bar (outside the thumb area)
+ */
+::CColor CStudioPreferences::GetScrollBGOutlineColor()
+{
+ return s_ScrollBGOutlineColor;
+}
+
+//=============================================================================
+/**
+ * @return color of the scroll bar thumb
+ */
+::CColor CStudioPreferences::GetScrollThumbBGColor()
+{
+ return s_BaseColor;
+}
+
+//=============================================================================
+/**
+ * @return color of the highlight on the top and side of the scroll bar thumb
+ */
+::CColor CStudioPreferences::GetScrollThumbHighlightColor()
+{
+ return s_ScrollThumbHighlightColor;
+}
+
+//=============================================================================
+/**
+ * @return color of the 3 light-lines in the middle of a scroll bar thumb
+ */
+::CColor CStudioPreferences::GetScrollThumbGripHighlightColor()
+{
+ return s_ScrollThumbGripHighlightColor;
+}
+
+//=============================================================================
+/**
+ * @return color of the 3 dark-lines in the middle of a scroll bar thumb
+ */
+::CColor CStudioPreferences::GetScrollThumbGripShadowColor()
+{
+ return s_ScrollThumbGripShadowColor;
+}
+
+//=============================================================================
+/**
+ * @return color for the outline of the scroll bar thumb (opposite side of the highlight)
+ */
+::CColor CStudioPreferences::GetScrollThumbShadowColor()
+{
+ return s_ScrollThumbShadowColor;
+}
+
+::CColor CStudioPreferences::GetLockedTimebarColor()
+{
+ return GetBaseColor();
+}
+
+::CColor CStudioPreferences::GetLockedBorderColor()
+{
+ return s_LockedBorderColor;
+}
+
+::CColor CStudioPreferences::GetExtendedLockedLightColor()
+{
+ return s_ExtendedLockedLightColor;
+}
+
+::CColor CStudioPreferences::GetExtendedLockedDarkColor()
+{
+ return GetLockedBorderColor();
+}
+
+//=============================================================================
+/**
+ * @return color for disabled (locked) text
+ */
+::CColor CStudioPreferences::GetLockedTextColor()
+{
+ return s_InactiveColor;
+}
+
+//=============================================================================
+/**
+ * @return color for background of layer rows in the timeline
+ */
+::CColor CStudioPreferences::GetLayerBackgroundColor()
+{
+ return ::CColor("#2e2f30");
+}
+
+//=============================================================================
+/**
+ * @return color of timeline row background for layers when mouse is over
+ */
+::CColor CStudioPreferences::GetGroupBackgroundColor()
+{
+ return ::CColor("#404244");
+}
+
+//=============================================================================
+/**
+ * @return default color for rows in the timeline (if not specified by one of these other color
+ * functions)
+ */
+::CColor CStudioPreferences::GetObjectBackgroundColor()
+{
+ return ::CColor("#404244");
+}
+
+//=============================================================================
+/**
+ * @return default color for object timebars in the timeline (if not specified by one of these other
+ * functions)
+ */
+::CColor CStudioPreferences::GetObjectTimebarColor()
+{
+ return ::CColor("#788ac5");
+}
+
+//=============================================================================
+/**
+ * @return default colors for specific timebars in the timeline
+ */
+::CColor CStudioPreferences::GetGroupTimebarColor()
+{
+ return ::CColor("#cbb0de");
+}
+
+::CColor CStudioPreferences::GetLayerTimebarColor()
+{
+ return ::CColor("#e7e0cd");
+}
+
+::CColor CStudioPreferences::GetBehaviorTimebarColor()
+{
+ return ::CColor("#91ba60");
+}
+
+::CColor CStudioPreferences::GetCameraTimebarColor()
+{
+ return ::CColor("#a0a1a2");
+}
+
+::CColor CStudioPreferences::GetLightTimebarColor()
+{
+ return ::CColor("#a0a1a2");
+}
+
+::CColor CStudioPreferences::GetModelTimebarColor()
+{
+ return ::CColor("#788ac5");
+}
+
+::CColor CStudioPreferences::GetComponentTimebarColor()
+{
+ return ::CColor("#bb7333");
+}
+
+::CColor CStudioPreferences::GetEffectTimebarColor()
+{
+ return ::CColor("#cb927f");
+}
+
+//==============================================================================
+/**
+ * Color for the top row of the inspector and timeline palettes (title row color).
+ */
+::CColor CStudioPreferences::GetTopRowColor()
+{
+ return s_TopRowColor;
+}
+
+//==============================================================================
+/**
+ * Color when the button is down on a tab control
+ */
+::CColor CStudioPreferences::GetTabButtonDownColor()
+{
+ return s_TabButtonDownColor;
+}
+
+//==============================================================================
+/**
+ * Color when text is disabled
+ */
+::CColor CStudioPreferences::GetDisabledTextColor()
+{
+ return s_DisabledTextColor;
+}
+
+//==============================================================================
+/**
+ * Colors for bounding boxes
+ */
+::CColor CStudioPreferences::GetSingleBoundingBoxColor()
+{
+ return ::CColor("#ff0000");
+}
+
+::CColor CStudioPreferences::GetGroupBoundingBoxColor()
+{
+ return ::CColor("#ff0000");
+}
+
+::CColor CStudioPreferences::GetLightBoundingBoxColor()
+{
+ return ::CColor("#ffff00");
+}
+
+//==============================================================================
+/**
+ * Colors for rulers and guides
+ */
+::CColor CStudioPreferences::GetRulerBackgroundColor()
+{
+ return ::CColor("#262829");
+}
+
+::CColor CStudioPreferences::GetRulerTickColor()
+{
+ return ::CColor("#727476");
+}
+
+::CColor CStudioPreferences::GetGuideColor()
+{
+ return ::CColor("#7a5f02"); // #f4be04 plus faked alpha 50%
+}
+
+::CColor CStudioPreferences::GetGuideSelectedColor()
+{
+ return ::CColor("#f4be04");
+}
+
+::CColor CStudioPreferences::GetGuideFillColor()
+{
+ return ::CColor("#140F00"); // #f4be04 plus faked alpha 8%
+}
+
+::CColor CStudioPreferences::GetGuideFillSelectedColor()
+{
+ return ::CColor("#7a5f02"); // #f4be04 plus faked alpha 50%
+}
+
+//==============================================================================
+/**
+ * Font face name for dialog
+ */
+QString CStudioPreferences::GetFontFaceName()
+{
+ return QStringLiteral("Segoe UI");
+}
+
+//==============================================================================
+/**
+ * Return the standard timeline row height
+ */
+long CStudioPreferences::GetRowSize()
+{
+ return 20;
+}
+
+//==============================================================================
+/**
+ * Return the timebar tip size for the tip that lies outside the timebar.
+ */
+long CStudioPreferences::GetTimebarTipSize()
+{
+ return 6;
+}
+
+//==============================================================================
+/**
+ * Return the timebar tip size for the tip that lies inside the timebar.
+ */
+long CStudioPreferences::GetTimebarInnerTipSize()
+{
+ return 3;
+}
+
+//==============================================================================
+/**
+ * Return the timeline name text size
+ */
+long CStudioPreferences::GetTimelineNameSize()
+{
+ return 400;
+}
+
+//==============================================================================
+/**
+ * Return the default comment size
+ */
+long CStudioPreferences::GetDefaultCommentSize()
+{
+ return 1500;
+}
+
+//==============================================================================
+/**
+ * @return the default height of a text edit box
+ */
+long CStudioPreferences::GetDefaultTextEditSize()
+{
+ long theReturnValue = 15;
+ return theReturnValue;
+}
+
+long CStudioPreferences::GetDefaultButtonWidth()
+{
+ return 16;
+}
+
+//==============================================================================
+/**
+ * @return The gutter size on the right and left edges of the inspector palette.
+ */
+long CStudioPreferences::GetInspectorGutterSize()
+{
+ return 5;
+}
+
+//==============================================================================
+/**
+ * @return The height of the top row of the timeline and inspector palettes.
+ */
+long CStudioPreferences::GetHeaderHeight()
+{
+ return 21;
+}
+
+bool CStudioPreferences::IsSudoMode()
+{
+ return m_SudoMode;
+}
+
+void CStudioPreferences::setQmlContextProperties(QQmlContext *qml)
+{
+ qml->setContextProperty(QStringLiteral("_studioColor1"), s_studioColor1);
+ qml->setContextProperty(QStringLiteral("_studioColor2"), s_studioColor2);
+ qml->setContextProperty(QStringLiteral("_studioColor3"), s_studioColor3);
+ qml->setContextProperty(QStringLiteral("_backgroundColor"), s_backgroundColor);
+ qml->setContextProperty(QStringLiteral("_guideColor"), s_guideColor);
+ qml->setContextProperty(QStringLiteral("_selectionColor"), s_selectionColor);
+ qml->setContextProperty(QStringLiteral("_textColor"), s_textColor);
+ qml->setContextProperty(QStringLiteral("_masterColor"), s_masterColor);
+ qml->setContextProperty(QStringLiteral("_disabledColor"), s_disabledColor);
+ qml->setContextProperty(QStringLiteral("_fontSize"), s_fontSize);
+ qml->setContextProperty(QStringLiteral("_controlBaseHeight"), s_controlBaseHeight);
+ qml->setContextProperty(QStringLiteral("_idWidth"), s_idWidth);
+ qml->setContextProperty(QStringLiteral("_valueWidth"), s_valueWidth);
+}
+
+QColor CStudioPreferences::studioColor1()
+{
+ return s_studioColor1;
+}
+
+QColor CStudioPreferences::studioColor2()
+{
+ return s_studioColor2;
+}
+
+QColor CStudioPreferences::studioColor3()
+{
+ return s_studioColor3;
+}
+
+QColor CStudioPreferences::backgroundColor()
+{
+ return s_backgroundColor;
+}
+
+QColor CStudioPreferences::guideColor()
+{
+ return s_guideColor;
+}
+
+QColor CStudioPreferences::selectionColor()
+{
+ return s_selectionColor;
+}
+
+QColor CStudioPreferences::textColor()
+{
+ return s_textColor;
+}
+
+QColor CStudioPreferences::masterColor()
+{
+ return s_masterColor;
+}
+
+QColor CStudioPreferences::disabledColor()
+{
+ return s_disabledColor;
+}
+
+int CStudioPreferences::fontSize()
+{
+ return s_fontSize;
+}
+
+int CStudioPreferences::controlBaseHeight()
+{
+ return s_controlBaseHeight;
+}
+
+int CStudioPreferences::idWidth()
+{
+ return s_idWidth;
+}
+
+int CStudioPreferences::valueWidth()
+{
+ return s_valueWidth;
+}
+
+QSize CStudioPreferences::browserPopupSize()
+{
+ return s_browserPopupSize;
+}
+
+Q3DStudio::CString CStudioPreferences::GetVersionString()
+{
+ Q3DStudio::CString theVersionNumber = STRPRODUCTVER;
+ theVersionNumber.Replace(",", ".");
+
+ return theVersionNumber;
+}
+
+//==============================================================================
+/**
+ * Returns the state of the timeline snapping grid
+ * @return true if the snapping grid is active
+ */
+bool CStudioPreferences::IsSlideIconVisible()
+{
+ return CPreferences::GetUserPreferences().GetValue("SlideIconVisible", true);
+}
+
+//==============================================================================
+/**
+ * Sets the state of the timeline snapping grid
+ * @param inActiveFlag true if the snapping grid is active
+ */
+void CStudioPreferences::SetSlideIconVisible(bool inVisible)
+{
+ CPreferences::GetUserPreferences().SetValue("SlideIconVisible", inVisible);
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
new file mode 100644
index 00000000..4a7c792e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PREFERENCES_H
+#define INCLUDED_STUDIO_PREFERENCES_H 1
+
+#pragma once
+
+#include <qglobal.h>
+
+#include "CoreConst.h"
+#include "UICFile.h"
+#include "Preferences.h"
+#include "Rct.h"
+
+QT_FORWARD_DECLARE_CLASS(QQmlContext)
+
+class CStudioPreferences
+{
+ CStudioPreferences();
+ virtual ~CStudioPreferences();
+
+public:
+ static void LoadPreferences();
+
+ static bool IsTimelineSnappingGridActive();
+ static void SetTimelineSnappingGridActive(bool inActive);
+
+ static ESnapGridResolution GetTimelineSnappingGridResolution();
+ static void SetTimelineSnappingGridResolution(ESnapGridResolution inResolution);
+
+ static CPreferences GetTrialSettings(const Q3DStudio::CString &inKeyName);
+
+ static bool ShowHelpOnLaunch();
+ static void SetShowHelpOnLaunch(bool inShowHelpOnLaunch);
+
+ static ::CColor GetEditViewBackgroundColor();
+ static void SetEditViewBackgroundColor(::CColor inColor);
+
+ static bool GetEditViewFillMode();
+ static void SetEditViewFillMode(bool inRenderAsSolid);
+
+ static long GetPreferredStartupView();
+ static void SetPreferredStartupView(long inStartupView);
+
+ static bool IsAutosetKeyframesOn();
+ static void SetAutosetKeyframesOn(bool inEnable);
+
+ static bool IsBoundingBoxesOn();
+ static void SetBoundingBoxesOn(bool inEnable);
+
+ static bool ShouldDisplayPivotPoint();
+ static void SetDisplayPivotPoint(bool inEnable);
+
+ static bool IsWireframeModeOn();
+ static void SetWireframeModeOn(bool inEnable);
+
+ static bool ShouldShowTooltips();
+ static void SetShowTooltips(bool inShowTooltips);
+
+ static ::CColor GetTooltipBackgroundColor();
+
+ static long GetTimelineSplitterLocation();
+ static void SetTimelineSplitterLocation(long inLocation);
+
+ static long GetInspectorSplitterLocation();
+ static void SetInspectorSplitterLocation(long inLocation);
+
+ static bool GetInterpolation();
+ static void SetInterpolation(bool inSmooth);
+
+ static long GetSnapRange();
+ static void SetSnapRange(long inSnapRange);
+
+ static long GetAutoSaveDelay();
+ static void SetAutoSaveDelay(long inAutoSaveDelay);
+
+ static bool GetAutoSavePreference();
+ static void SetAutoSavePreference(bool inActive);
+
+ static long GetDefaultObjectLifetime();
+ static void SetDefaultObjectLifetime(long inLifetime);
+
+ static bool GetTimebarDisplayTime();
+ static void SetTimebarDisplayTime(bool inDisplayTime);
+
+ static double GetNudgeAmount();
+ static void SetNudgeAmount(double inNudgeAbount);
+
+ static bool ShowVersionDialog();
+ static void SetShowVersionDialog(bool inShowVersionDialog);
+
+ static Q3DStudio::CString GetDefaultApplication();
+ static void SetDefaultApplication(const Q3DStudio::CString &inApplication);
+
+ static Q3DStudio::CString GetVersionString();
+
+ static bool GetDontShowGLVersionDialog();
+ static void SetDontShowGLVersionDialog(bool inValue);
+
+ static CPt GetObjectReferenceGadgetSize();
+ static void SetObjectReferenceGadgetSize(const CPt &inSize);
+
+ static CPt GetObjectReferenceGadgetPosition(const CPt &inDefault);
+ static void SetObjectReferenceGadgetPosition(const CPt &inPosition);
+
+ static CPt GetPropertyReferenceGadgetSize();
+ static void SetPropertyReferenceGadgetSize(const CPt &inSize);
+
+ static CPt GetPropertyReferenceGadgetPosition(const CPt &inDefault);
+ static void SetPropertyReferenceGadgetPosition(const CPt &inSize);
+
+ static CPt GetHandlerReferenceGadgetSize();
+ static void SetHandlerReferenceGadgetSize(const CPt &inSize);
+
+ static CPt GetEventReferenceGadgetSize();
+ static void SetEventReferenceGadgetSize(const CPt &inSize);
+
+ static CRct GetMultilineTextLocation();
+ static void SetMultilineTextLocation(const CRct &inSize);
+
+ static long GetTimeAdvanceAmount();
+ static void SetTimeAdvanceAmount(const long &inTime);
+ static long GetBigTimeAdvanceAmount();
+ static void SetBigTimeAdvanceAmount(const long &inTime);
+
+ static long GetActionSplitterSize();
+ static void SetActionSplitterSize(long inSize);
+
+ static long GetCustomPropertySplitterSize();
+ static void SetCustomPropertySplitterSize(long inSize);
+
+ static long GetAssetSplitterSize();
+ static void SetAssetSplitterSize(long inSize);
+
+ static CPt GetDefaultClientSize();
+ static bool GetCanImportComponent();
+
+ static bool GetAdvancePropertyExpandedFlag();
+ static void SetAdvancePropertyExpandedFlag(bool inAdvancePropertyFlag);
+
+ static Q3DStudio::CString GetPreviewConfig();
+ static void SetPreviewConfig(const Q3DStudio::CString &inValue);
+ static Q3DStudio::CString GetPreviewProperty(const Q3DStudio::CString &inName);
+ static void SetPreviewProperty(const Q3DStudio::CString &inName,
+ const Q3DStudio::CString &inValue);
+
+ static bool IsSlideIconVisible();
+ static void SetSlideIconVisible(bool inVisible);
+
+ static bool ShouldWriteMapFile();
+
+ static ::CColor GetDefaultSceneColor();
+ static ::CColor GetDefaultPrimitiveColor();
+
+ static bool IsDebugTimes();
+
+ static ::CColor GetBaseColor();
+ static ::CColor GetLightBaseColor();
+ static ::CColor GetDarkBaseColor();
+
+ static ::CColor GetNormalColor();
+ static ::CColor GetMasterColor();
+ static ::CColor GetInactiveColor();
+
+ static ::CColor GetMouseOverHighlightColor();
+ static ::CColor GetSelectColor();
+ static ::CColor GetTimelineSelectColor();
+
+ static ::CColor GetToolBarBaseColor();
+ static ::CColor GetMenuBarBaseColor();
+
+ static ::CColor GetButtonDownColor();
+ static ::CColor GetTreeFloorColor();
+ static ::CColor GetButtonShadowColor();
+ static ::CColor GetPropertyFloorColor();
+ static ::CColor GetButtonHighlightColor();
+ static ::CColor GetRowSelectedColor();
+ static ::CColor GetRowTopColor();
+ static ::CColor GetTimeBarBorderColor();
+ static ::CColor GetPropertyBackgroundColor();
+ static ::CColor GetPropertyMouseOverColor();
+ static ::CColor GetPropertyTimbarLeft();
+ static ::CColor GetExtendedObjectLightColor();
+ static ::CColor GetExtendedObjectDarkColor();
+ static ::CColor GetControlRectTopLineColor();
+ static ::CColor GetControlRectSideLineColor();
+ static ::CColor GetControlRectBottomLineColor();
+ static ::CColor GetControlRectBottomLineDarkColor();
+ static ::CColor GetControlShadowColor();
+ static ::CColor GetTextBoxBGColorNoFocus();
+ static ::CColor GetTextBoxBGColorWithFocus();
+ static ::CColor GetScrollBGColor();
+ static ::CColor GetScrollBGOutlineColor();
+ static ::CColor GetScrollThumbBGColor();
+ static ::CColor GetScrollThumbShadowColor();
+ static ::CColor GetScrollThumbHighlightColor();
+ static ::CColor GetScrollThumbGripHighlightColor();
+ static ::CColor GetScrollThumbGripShadowColor();
+ static ::CColor GetComboEditBoxGradientStartColor();
+
+ static ::CColor GetLockedTimebarColor();
+ static ::CColor GetLockedBorderColor();
+ static ::CColor GetExtendedLockedLightColor();
+ static ::CColor GetExtendedLockedDarkColor();
+ static ::CColor GetLockedTextColor();
+ static ::CColor GetLayerBackgroundColor();
+ static ::CColor GetGroupBackgroundColor();
+ static ::CColor GetObjectBackgroundColor();
+ static ::CColor GetObjectTimebarColor();
+ static ::CColor GetGroupTimebarColor();
+ static ::CColor GetLayerTimebarColor();
+ static ::CColor GetBehaviorTimebarColor();
+ static ::CColor GetEffectTimebarColor();
+ static ::CColor GetCameraTimebarColor();
+ static ::CColor GetLightTimebarColor();
+ static ::CColor GetModelTimebarColor();
+ static ::CColor GetComponentTimebarColor();
+ static ::CColor GetTopRowColor();
+ static ::CColor GetTabButtonDownColor();
+ static ::CColor GetDisabledTextColor();
+
+ static ::CColor GetSingleBoundingBoxColor();
+ static ::CColor GetGroupBoundingBoxColor();
+ static ::CColor GetLightBoundingBoxColor();
+
+ static ::CColor GetRulerBackgroundColor();
+ static ::CColor GetRulerTickColor();
+ static ::CColor GetGuideColor();
+ static ::CColor GetGuideSelectedColor();
+ static ::CColor GetGuideFillColor();
+ static ::CColor GetGuideFillSelectedColor();
+
+ static QString GetFontFaceName();
+
+ static long GetRowSize();
+ static long GetTimebarTipSize();
+ static long GetTimebarInnerTipSize();
+ static long GetTimelineNameSize();
+ static long GetDefaultCommentSize();
+ static long GetDefaultTextEditSize();
+ static long GetDefaultButtonWidth();
+ static long GetInspectorGutterSize();
+ static long GetHeaderHeight();
+
+ static bool IsSudoMode();
+
+ static void setQmlContextProperties(QQmlContext *qml);
+ static QColor studioColor1();
+ static QColor studioColor2();
+ static QColor studioColor3();
+ static QColor backgroundColor();
+ static QColor guideColor();
+ static QColor selectionColor();
+ static QColor textColor();
+ static QColor masterColor();
+ static QColor disabledColor();
+ static int fontSize();
+ static int controlBaseHeight();
+ static int idWidth();
+ static int valueWidth();
+ static QSize browserPopupSize();
+
+ // Default values that Studio will start out with or to restore
+ static const long GUTTER_SIZE = 10;
+ static const ::CColor EDITVIEW_DEFAULTBGCOLOR;
+ static const long PREFERREDSTARTUP_DEFAULTINDEX = -1;
+
+protected:
+ static bool m_SudoMode;
+ static bool m_DebugTimes;
+};
+#endif // INCLUDED_STUDIO_PREFERENCES_H
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.cpp b/src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.cpp
new file mode 100644
index 00000000..18cd80e5
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioProjectVariables.h"
+#include "Core.h"
+#include "Dispatch.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+//==============================================================================
+CStudioProjectVariables::CStudioProjectVariables(CCore *inCore)
+ : m_Core(inCore)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CStudioProjectVariables::~CStudioProjectVariables()
+{
+}
+
+//==============================================================================
+/**
+ * Cleanup all the existing environment variables. It's the responsibility of the
+ * listen for the change event to remove themselves. Calling Clear will not remove them
+ */
+//==============================================================================
+void CStudioProjectVariables::Clear()
+{
+ m_VariablesMap.clear();
+}
+
+//==============================================================================
+/**
+ * Forms all the environment into a CString. Each enviroment variable is seperated
+ * by a carriage return and a line feed. This is the format expected by the Project
+ * Settings UI
+ */
+//==============================================================================
+Q3DStudio::CString CStudioProjectVariables::GetProjectVariables() const
+{
+ // Formulate the string
+ Q3DStudio::CString theString;
+ TVariableMap::const_iterator theBegin = m_VariablesMap.begin();
+ TVariableMap::const_iterator theEnd = m_VariablesMap.end();
+ for (TVariableMap::const_iterator theIterator = theBegin; theIterator != theEnd;
+ ++theIterator) {
+ if (theIterator != theBegin)
+ theString += "\r\n";
+
+ theString += theIterator->first;
+ theString += " = ";
+ theString += theIterator->second;
+ }
+
+ return theString;
+}
+
+void CStudioProjectVariables::GetProjectVariables(std::list<Q3DStudio::CString> &ioVariables)
+{
+ Q3DStudio::CString theString;
+ TVariableMap::const_iterator theBegin = m_VariablesMap.begin();
+ TVariableMap::const_iterator theEnd = m_VariablesMap.end();
+ for (TVariableMap::const_iterator theIterator = theBegin; theIterator != theEnd;
+ ++theIterator) {
+ theString = theIterator->first;
+ theString += " = ";
+ theString += theIterator->second;
+ ioVariables.push_back(theString);
+ }
+}
+
+//==============================================================================
+/**
+ * Reset all the enviroment variables with this new set. Each entry in the list
+ * is one variable in the format {Variable} = Value.
+ */
+//==============================================================================
+bool CStudioProjectVariables::SetProjectVariables(std::list<Q3DStudio::CString> &inVariables)
+{
+ // copy the environment variables out
+ TVariableMap theOrigMap = m_VariablesMap;
+
+ // prepare m_VariablesMap for new settings
+ m_VariablesMap.clear();
+
+ bool theChangeFlag(false);
+ bool theVariableError(false);
+ Q3DStudio::CString theErrorMessage;
+ std::list<Q3DStudio::CString>::iterator theEnd = inVariables.end();
+ std::list<Q3DStudio::CString>::iterator theIterator = inVariables.begin();
+ for (; theIterator != theEnd; ++theIterator) {
+ // Decode the string into key and value
+ long theIndex = theIterator->Find('=');
+ if (theIndex != Q3DStudio::CString::ENDOFSTRING) {
+ Q3DStudio::CString theKey = theIterator->Left(theIndex);
+ theKey.TrimLeft();
+ theKey.TrimRight();
+ Q3DStudio::CString theValue = theIterator->Extract(theIndex + 1);
+ theValue.TrimLeft();
+ theValue.TrimRight();
+
+ // Strip the key of '{' and '}' if any and store key only as uppercase
+ long theBeginIndex = theKey.Find('{');
+ if (theBeginIndex != Q3DStudio::CString::ENDOFSTRING) {
+ long theEndIndex = theKey.Find('}');
+ if (theEndIndex != Q3DStudio::CString::ENDOFSTRING) {
+ theKey = theKey.Extract(theBeginIndex + 1, theEndIndex - theBeginIndex - 1);
+ }
+ }
+ theKey.ToUpper();
+
+ // find whether it exists
+ TVariableMap::iterator theMapIterator = theOrigMap.find(theKey);
+ if (theMapIterator == theOrigMap.end()) {
+ theChangeFlag = true;
+ } else {
+ if (theMapIterator->second != theValue) {
+ theChangeFlag = true;
+ }
+ theOrigMap.erase(theMapIterator);
+ }
+ m_VariablesMap.insert(std::make_pair(theKey, theValue));
+ } else {
+ Q3DStudio::CString theString = *theIterator;
+ theString.TrimLeft();
+ if (!theString.IsEmpty()) {
+ // Error encountered. Form the error message to be displayed
+ if (!theVariableError) {
+ theVariableError = true;
+ } else
+ theErrorMessage += "\n";
+ // Format error in this parameters
+ theErrorMessage += "\t";
+ theErrorMessage += *theIterator;
+ }
+ }
+ }
+
+ if (theVariableError) {
+ m_Core->GetDispatch()->FireOnProjectVariableFail(theErrorMessage);
+ }
+
+ if (theChangeFlag || 0 != theOrigMap.size()) // something was deleted
+ FireChangeEvent();
+
+ return theChangeFlag;
+}
+
+//==============================================================================
+/**
+ * Formulate a new string by parsing the input string and replace every instance
+ * of environment variable with it's corresponding value. If the environment is not
+ * found, it is replace with an empty string. The environement variable is identified
+ * by '{' and '}'
+ */
+//==============================================================================
+Q3DStudio::CString CStudioProjectVariables::ResolveString(const Q3DStudio::CString &inString)
+{
+ Q3DStudio::CString theReturnString;
+ long theStart = 0; // start index of string
+ long theBeginIndex = 0; // index of '{'
+ long theEndIndex = 0; // index of '}'
+ while (Q3DStudio::CString::ENDOFSTRING != theEndIndex) {
+ theBeginIndex = inString.Find('{', theStart);
+ if (Q3DStudio::CString::ENDOFSTRING != theBeginIndex) {
+ theReturnString += inString.Extract(theStart, theBeginIndex - theStart);
+ // find the corresponding '}'
+ theEndIndex = inString.Find('}', theBeginIndex + 1);
+ if (Q3DStudio::CString::ENDOFSTRING != theEndIndex) {
+ // resolve the string
+ Q3DStudio::CString theVariable =
+ inString.Extract(theBeginIndex + 1, theEndIndex - theBeginIndex - 1);
+ theVariable.ToUpper();
+ TVariableMap::const_iterator theMapIter = m_VariablesMap.find(theVariable);
+
+ if (m_VariablesMap.end() != theMapIter) {
+ theReturnString += theMapIter->second;
+ }
+ theStart = theEndIndex + 1;
+ } else
+ theReturnString += inString.Extract(theBeginIndex);
+ } else {
+ theEndIndex = theBeginIndex;
+ theReturnString += inString.Extract(theStart);
+ }
+ }
+
+ return theReturnString;
+}
+
+//==============================================================================
+/**
+ * Resolves the passed in variable and write out the resolved value if it exists.
+ * @param inVariable the environment to be resolved
+ * @param outValue the string to receive the resolved value
+ * @return true if the variable exists, else false
+ */
+//==============================================================================
+bool CStudioProjectVariables::ResolveVariable(const Q3DStudio::CString &inVariable,
+ Q3DStudio::CString &outValue,
+ bool inCaseInsensitive /* = true*/)
+{
+ // environment variable is wrapped by '{' and '}'
+ // so form the inVariable in this syntax before searching
+ // Q3DStudio::CString theVariable = "{" + inVariable + "}";
+ TVariableMap::const_iterator theMapIter;
+ if (inCaseInsensitive) {
+ Q3DStudio::CString theUpperInVariable = inVariable;
+ theUpperInVariable.ToUpper();
+ theMapIter = m_VariablesMap.find(theUpperInVariable);
+ } else {
+ theMapIter = m_VariablesMap.find(inVariable);
+ }
+ if (m_VariablesMap.end() != theMapIter) {
+ outValue = theMapIter->second;
+ return true;
+ } else
+ return false;
+}
+
+//=============================================================================
+/**
+ * Add a listener to the list of objects to be notified on a change.
+ * The listener gets told when the any of the environment changes.
+ * @param inChangeListener listener who intereste for changes.
+ */
+void CStudioProjectVariables::AddChangeListener(IVariableChangeListener *inChangeListener)
+{
+ m_ChangeListeners.AddListener(inChangeListener);
+}
+
+//=============================================================================
+/**
+ * Remove a listener from the list of objects to be notified on a change.
+ * @param inChangeListener the change listener to be removed.
+ */
+void CStudioProjectVariables::RemoveChangeListener(IVariableChangeListener *inChangeListener)
+{
+ m_ChangeListeners.RemoveListener(inChangeListener);
+}
+
+//=============================================================================
+/**
+ * Fire a change event for this object.
+ */
+void CStudioProjectVariables::FireChangeEvent()
+{
+ m_ChangeListeners.FireEvent(&IVariableChangeListener::OnVariableChanged);
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.h b/src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.h
new file mode 100644
index 00000000..3a13e18f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/StudioProjectVariables.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PROJECT_VARIABLES_H
+#define INCLUDED_STUDIO_PROJECT_VARIABLES_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Multicaster.h"
+#include "StdAfx.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CCore;
+
+class CStudioProjectVariables
+{
+ //==============================================================================
+ // Internal Classes
+ //==============================================================================
+public:
+ class IVariableChangeListener
+ {
+ public:
+ virtual void OnVariableChanged() = 0;
+ };
+
+ //==============================================================================
+ // Typedef
+ //==============================================================================
+protected:
+ typedef std::map<Q3DStudio::CString, Q3DStudio::CString>
+ TVariableMap; // change to new coding standard
+
+ //==============================================================================
+ // Construction
+ //==============================================================================
+public:
+ CStudioProjectVariables(CCore *inCore);
+ virtual ~CStudioProjectVariables();
+
+ //==============================================================================
+ // Member variables
+ //==============================================================================
+protected:
+ CCore *m_Core;
+ TVariableMap m_VariablesMap;
+ CMulticaster<IVariableChangeListener *> m_ChangeListeners;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ Q3DStudio::CString GetProjectVariables() const;
+ void GetProjectVariables(std::list<Q3DStudio::CString> &ioVariables);
+ bool SetProjectVariables(std::list<Q3DStudio::CString> &inVariables);
+ void Clear();
+
+ Q3DStudio::CString ResolveString(const Q3DStudio::CString &inString);
+ bool ResolveVariable(const Q3DStudio::CString &inVariable, Q3DStudio::CString &outValue,
+ bool inCaseInsensitive = true);
+
+ // Change listeners
+ void AddChangeListener(IVariableChangeListener *inListener);
+ void RemoveChangeListener(IVariableChangeListener *inListener);
+ virtual void FireChangeEvent();
+
+ // Used for serialization *only*
+ TVariableMap &UnsafeGetVariablesMap() { return m_VariablesMap; }
+};
+
+#endif // INCLUDED_STUDIO_PROJECT_VARIABLES_H
diff --git a/src/Authoring/Client/Code/Core/Utility/TestCmdUtils.cpp b/src/Authoring/Client/Code/Core/Utility/TestCmdUtils.cpp
new file mode 100644
index 00000000..935911b5
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/TestCmdUtils.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TestCmdUtils.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "GraphUtils.h"
+
+//=============================================================================
+/**
+ * Returns the nearest integer to a float, e.g. 3.4 -> 3; -2.7 -> -3;
+ * @param inX a float value
+ * @return the nearest integer
+ */
+// long round( float inX ) { return inX > 0 ? (long)(inX + 0.5) : (long)(inX - 0.5); };
+
+//=============================================================================
+/**
+ * Uses the command interface to add a child asset to a parent object on a
+ * particular slide and sets attributes on the new child object
+ * @param inParent the to/destination object, e.g. the scene, a layer
+ * @param inChild the from/source asset, e.g. a sphere
+ * @param inSlideIndex a slide index where zero is the master slide
+ * @return a pointer to the new child object or NULL if not added
+ */
+UICDM::CUICDMInstanceHandle TestCmdUtilsAddObject(CAsset *inParent, CAsset *inChild,
+ long inSlideIndex)
+{
+ Q_UNUSED(inParent);
+ Q_UNUSED(inChild);
+ Q_UNUSED(inSlideIndex);
+ return {};
+ // CCmdAddObject addObjectCmd( inParent->GetDoc( ), inParent->GetInstanceHandle( ),
+ // inChild->GetInstanceHandle( ), inSlideIndex );
+ // addObjectCmd.Do( );
+ // return addObjectCmd.GetAddedInstance( );
+}
+
+//==============================================================================
+/**
+ * Packages up a property's attributes into a string-based fingerprint that can
+ * be used for QA comparison
+ * @param inProperty the property in question
+ * @return a string representing the property name and other measurable attributes
+ */
+//==============================================================================
+// TODO: UICDM Fingerprint
+
+//==============================================================================
+/**
+ * Flatten a list of strings into a single comma-delimited string
+ * @param inFingerprint a list of strings
+ * @return a single string representing the list of strings
+ */
+//==============================================================================
+Q3DStudio::CString TestCmdUtilsFlatten(const TFingerprint &inFingerprint)
+{
+ Q3DStudio::CString theString = "(";
+ TFingerprint::const_iterator theIter = inFingerprint.begin();
+ for (; theIter != inFingerprint.end(); ++theIter)
+ theString += *theIter + ",";
+ theString += ")";
+ return theString;
+}
+
+//==============================================================================
+/**
+ * Compare two fingerprints for equality. Useful in debug mode
+ * to see which metrics do not match
+ * @param inFingerprint1 the first list of strings
+ * @param inFingerprint2 the second list of strings
+ * @return T if the lists are identical, otherwise F
+ */
+//==============================================================================
+bool TestCmdUtilsCompare(const TFingerprint &inFingerprint1, const TFingerprint &inFingerprint2)
+{
+ Q3DStudio::CString theString1 = TestCmdUtilsFlatten(inFingerprint1);
+ Q3DStudio::CString theString2 = TestCmdUtilsFlatten(inFingerprint2);
+ bool theSame = (theString1 == theString2);
+ if (!theSame) {
+ qDebug("\n");
+ qDebug(QString::fromWCharArray(theString1.c_str()).toLatin1().data());
+ qDebug("\n");
+ qDebug(QString::fromWCharArray(theString2.c_str()).toLatin1().data());
+ }
+ return theSame;
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/TestCmdUtils.h b/src/Authoring/Client/Code/Core/Utility/TestCmdUtils.h
new file mode 100644
index 00000000..be1c1b0e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/TestCmdUtils.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_TEST_CMD_UTILS_H
+#define INCLUDED_TEST_CMD_UTILS_H 1
+
+#pragma once
+
+#include "UICDMHandles.h"
+#include "StdAfx.h"
+
+class CAsset;
+class CAsset;
+class CNode;
+
+//==============================================================================
+// Templates
+//==============================================================================
+
+// A Fingerprint is list of string-based metrics and is used to aid QA comparison
+typedef std::list<Q3DStudio::CString> TFingerprint;
+
+//==============================================================================
+// Functions
+//==============================================================================
+
+UICDM::CUICDMInstanceHandle TestCmdUtilsAddObject(CAsset *inParent, CAsset *inChild,
+ long inSlideIndex);
+
+TFingerprint TestCmdUtilsMakeFingerprint(CNode *inNode);
+
+TFingerprint TestCmdUtilsMakeFingerprint(CAsset *inAsset, long inSlideIndex);
+
+Q3DStudio::CString TestCmdUtilsFlatten(const TFingerprint &inFingerprint);
+
+bool TestCmdUtilsCompare(const TFingerprint &inFingerprint1, const TFingerprint &inFingerprint2);
+
+// long round( float inX );
+
+#endif // INCLUDED_TEST_UTILS_H
diff --git a/src/Authoring/Client/Code/Core/Utility/cpuid.cpp b/src/Authoring/Client/Code/Core/Utility/cpuid.cpp
new file mode 100644
index 00000000..bd257214
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/cpuid.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "cpuid.h"
+
+extern "C" {
+
+// These are the bit flags that get set on calling cpuid
+// with register eax set to 1
+#define _MMX_FEATURE_BIT 0x00800000
+#define _SSE_FEATURE_BIT 0x02000000
+#define _SSE2_FEATURE_BIT 0x04000000
+
+// This bit is set when cpuid is called with
+// register set to 80000001h (only applicable to AMD)
+#define _3DNOW_FEATURE_BIT 0x80000000
+
+
+#ifndef _WIN32
+void __cpuid(int cpuInfo[4], int function_id)
+{
+ asm volatile
+ ("cpuid" : "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
+ : "a" (function_id), "c" (0));
+}
+#endif
+
+int IsCPUID()
+{
+ int CPUInfo[4];
+ int nIds;
+
+ // __cpuid with an InfoType argument of 0 returns the number of
+ // valid Ids in CPUInfo[0]
+ __cpuid(CPUInfo, 0);
+ nIds = CPUInfo[0];
+
+ return nIds;
+}
+
+/***
+* int _os_support(int feature)
+* - Checks if OS Supports the capablity or not
+*
+* Entry:
+* feature: the feature we want to check if OS supports it.
+*
+* Exit:
+* Returns 1 if OS support exist and 0 when OS doesn't support it.
+*
+****************************************************************/
+
+int _os_support(int feature)
+{
+#if defined(_AMD64_)
+ return 1;
+#elif defined(__clang__)
+ switch (feature) {
+#ifdef __SSE__
+ case _CPU_FEATURE_SSE:
+ return 1;
+#endif
+#ifdef __SSE2__
+ case _CPU_FEATURE_SSE2:
+ return 1;
+#endif
+#ifdef __SSE3__
+ case _CPU_FEATURE_3DNOW:
+ return 1;
+#endif
+ default:
+ return 0;
+ }
+#else
+ __try {
+ switch (feature) {
+ case _CPU_FEATURE_SSE:
+ __asm {
+ xorps xmm0, xmm0 // executing SSE instruction
+ }
+ break;
+ case _CPU_FEATURE_SSE2:
+ __asm {
+ xorpd xmm0, xmm0 // executing SSE2 instruction
+ }
+ break;
+ case _CPU_FEATURE_3DNOW:
+ __asm {
+ pfrcp mm0, mm0 // executing 3DNow! instruction
+ emms
+ }
+ break;
+ case _CPU_FEATURE_MMX:
+ __asm {
+ pxor mm0, mm0 // executing MMX instruction
+ emms
+ }
+ break;
+ }
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) {
+ return 0;
+ }
+ return 0;
+ }
+ return 1;
+#endif
+}
+
+/***
+*
+* void map_mname(int, int, const char *, char *)
+* - Maps family and model to processor name
+*
+****************************************************/
+
+void map_mname(int family, int model, const char *v_name, char *m_name)
+{
+ // Default to name not known
+ m_name[0] = '\0';
+
+ if (!strncmp("AuthenticAMD", v_name, 12)) {
+ switch (family) { // extract family code
+ case 4: // Am486/AM5x86
+ strcpy(m_name, "AMD Am486");
+ break;
+
+ case 5: // K6
+ switch (model) { // extract model code
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ strcpy(m_name, "AMD K5");
+ break;
+ case 6:
+ case 7:
+ strcpy(m_name, "AMD K6");
+ break;
+ case 8:
+ strcpy(m_name, "AMD K6-2");
+ break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ strcpy(m_name, "AMD K6-3");
+ break;
+ }
+ break;
+
+ case 6: // Athlon
+ // No model numbers are currently defined
+ strcpy(m_name, "AMD ATHLON");
+ break;
+ }
+ } else if (!strncmp("GenuineIntel", v_name, 12)) {
+ switch (family) { // extract family code
+ case 4:
+ switch (model) { // extract model code
+ case 0:
+ case 1:
+ strcpy(m_name, "INTEL 486DX");
+ break;
+ case 2:
+ strcpy(m_name, "INTEL 486SX");
+ break;
+ case 3:
+ strcpy(m_name, "INTEL 486DX2");
+ break;
+ case 4:
+ strcpy(m_name, "INTEL 486SL");
+ break;
+ case 5:
+ strcpy(m_name, "INTEL 486SX2");
+ break;
+ case 7:
+ strcpy(m_name, "INTEL 486DX2E");
+ break;
+ case 8:
+ strcpy(m_name, "INTEL 486DX4");
+ break;
+ }
+ break;
+
+ case 5:
+ switch (model) { // extract model code
+ case 1:
+ case 2:
+ case 3:
+ strcpy(m_name, "INTEL Pentium");
+ break;
+ case 4:
+ strcpy(m_name, "INTEL Pentium-MMX");
+ break;
+ }
+ break;
+
+ case 6:
+ switch (model) { // extract model code
+ case 1:
+ strcpy(m_name, "INTEL Pentium-Pro");
+ break;
+ case 3:
+ case 5:
+ strcpy(m_name, "INTEL Pentium-II");
+ break; // actual differentiation depends on cache settings
+ case 6:
+ strcpy(m_name, "INTEL Celeron");
+ break;
+ case 7:
+ case 8:
+ case 10:
+ strcpy(m_name, "INTEL Pentium-III");
+ break; // actual differentiation depends on cache settings
+ }
+ break;
+
+ case 15 | (0x00 << 4): // family 15, extended family 0x00
+ switch (model) {
+ case 0:
+ strcpy(m_name, "INTEL Pentium-4");
+ break;
+ }
+ break;
+ }
+ } else if (!strncmp("CyrixInstead", v_name, 12)) {
+ strcpy(m_name, "Cyrix");
+ } else if (!strncmp("CentaurHauls", v_name, 12)) {
+ strcpy(m_name, "Centaur");
+ }
+
+ if (!m_name[0]) {
+ strcpy(m_name, "Unknown");
+ }
+}
+
+/***
+*
+* int _cpuid (_p_info *pinfo)
+*
+* Entry:
+*
+* pinfo: pointer to _p_info.
+*
+* Exit:
+*
+* Returns int with capablity bit set even if pinfo = NULL
+*
+****************************************************/
+
+int _cpuid(_p_info *pinfo)
+{
+ int nModel = 0;
+ int nFamily = 0;
+ int nSteppingID = 0;
+ bool bSSE3Instructions;
+ int CPUInfo[4];
+ int CPUFeatures[4];
+ int feature = 0;
+ int os_support = 0;
+ union {
+ char cBuf[12 + 1];
+ struct
+ {
+ DWORD dw0;
+ DWORD dw1;
+ DWORD dw2;
+ } s;
+ } Ident;
+
+ if (!IsCPUID()) {
+ return 0;
+ }
+
+ // get the vendor string
+ __cpuid(CPUInfo, 0);
+ memset(Ident.cBuf, 0, sizeof(Ident));
+ (Ident.s.dw0) = CPUInfo[1];
+ (Ident.s.dw1) = CPUInfo[3];
+ (Ident.s.dw2) = CPUInfo[2];
+
+ // get cpu features
+ __cpuid(CPUFeatures, 1);
+ nSteppingID = CPUFeatures[0] & 0xf;
+ nModel = (CPUFeatures[0] >> 4) & 0xf;
+ nFamily = (CPUFeatures[0] >> 8) & 0xf;
+
+ bSSE3Instructions = (CPUFeatures[2] & 0x1);
+
+ if (bSSE3Instructions) {
+ feature |= _CPU_FEATURE_SSE;
+ feature |= _CPU_FEATURE_SSE2;
+ feature |= _CPU_FEATURE_SSE3;
+ if (_os_support(_CPU_FEATURE_SSE))
+ os_support |= _CPU_FEATURE_SSE;
+ if (_os_support(_CPU_FEATURE_SSE2))
+ os_support |= _CPU_FEATURE_SSE2;
+ if (_os_support(_CPU_FEATURE_SSE3))
+ os_support |= _CPU_FEATURE_SSE3;
+ }
+
+ if (pinfo) {
+ memset(pinfo, 0, sizeof(_p_info));
+
+ pinfo->os_support = os_support;
+ pinfo->feature = feature;
+ pinfo->family = nFamily;
+ pinfo->model = nModel; // retrieve model
+ pinfo->stepping = nSteppingID; // retrieve stepping
+
+ Ident.cBuf[12] = 0;
+ strcpy(pinfo->v_name, Ident.cBuf);
+
+ map_mname(pinfo->family, pinfo->model, pinfo->v_name, pinfo->model_name);
+
+ pinfo->checks = _CPU_FEATURE_SSE | _CPU_FEATURE_SSE2;
+ }
+
+ return feature;
+}
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/cpuid.h b/src/Authoring/Client/Code/Core/Utility/cpuid.h
new file mode 100644
index 00000000..9a48731e
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/cpuid.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _INC_CPUID
+#define _INC_CPUID
+
+#define _CPU_FEATURE_MMX 0x0001
+#define _CPU_FEATURE_SSE 0x0002
+#define _CPU_FEATURE_SSE2 0x0004
+#define _CPU_FEATURE_SSE3 0x0008
+#define _CPU_FEATURE_SSE4 0x0010
+#define _CPU_FEATURE_3DNOW 0x0020
+
+#define _MAX_VNAME_LEN 13
+#define _MAX_MNAME_LEN 30
+
+// Added by PB
+// MSDN Code to detect processor and OS capabilities. From CPUID code example.
+// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/vcsamcpuiddeterminecpucapabilities.asp
+
+typedef struct _processor_info
+{
+ char v_name[_MAX_VNAME_LEN]; // vendor name
+ char model_name[_MAX_MNAME_LEN]; // name of model
+ // e.g. Intel Pentium-Pro
+ int family; // family of the processor
+ // e.g. 6 = Pentium-Pro architecture
+ int model; // model of processor
+ // e.g. 1 = Pentium-Pro for family = 6
+ int stepping; // processor revision number
+ int feature; // processor feature
+ // (same as return value from _cpuid)
+ int os_support; // does OS Support the feature?
+ int checks; // mask of checked bits in feature
+ // and os_support fields
+} _p_info;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+ int
+ _cpuid(_p_info *);
+
+#endif
diff --git a/src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.cpp b/src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.cpp
new file mode 100644
index 00000000..39c97c8d
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsdirsystem.h"
+#include "q3dsdirwatcher.h"
+#include "UICDMSignals.h"
+
+using namespace UICDM;
+using namespace Q3DStudio;
+
+class Q3DSDirCallback : public ISignalConnection
+{
+public:
+ Q3DSDirCallback(QMap<QString, Q3DSDirWatcher> &watchers, const QString& path,
+ TFileModCallbackType callback)
+ : m_watchers(watchers), m_path(path), m_callback(callback)
+ {
+ if (m_watchers.contains(m_path))
+ m_watchers[m_path].addCallback(m_callback);
+ }
+
+ ~Q3DSDirCallback()
+ {
+ if (m_watchers.contains(m_path))
+ m_watchers[m_path].removeCallback(m_callback);
+ }
+
+private:
+ QMap<QString, Q3DSDirWatcher> &m_watchers;
+ QString m_path;
+ TFileModCallbackType m_callback;
+};
+
+Q3DSDirSystem::Q3DSDirSystem(TCallbackCaller caller) : m_callbackCaller(caller) {}
+
+std::shared_ptr<ISignalConnection> Q3DSDirSystem::AddDirectory(const QString &directory,
+ TFileModCallbackType callback)
+{
+ QString path = directory;
+
+ if (path.endsWith("\\") || path.endsWith("/"))
+ path = path.left(path.size() - 1);
+
+ for (auto it = m_watchers.begin(); it != m_watchers.end();) {
+ if (!it->hasCallbacks())
+ it = m_watchers.erase(it);
+ else
+ ++it;
+ }
+
+ if (!m_watchers.contains(path))
+ m_watchers.insert(path, Q3DSDirWatcher(m_callbackCaller, path));
+
+ return std::make_shared<Q3DSDirCallback>(m_watchers, path, callback);
+}
+
+std::shared_ptr<IDirectoryWatchingSystem>
+IDirectoryWatchingSystem::CreateThreadedDirectoryWatchingSystem(TCallbackCaller caller)
+{
+ return std::make_shared<Q3DSDirSystem>(caller);
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.h b/src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.h
new file mode 100644
index 00000000..bc18ddd7
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/q3dsdirsystem.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSDIRSYSTEM_H
+#define Q3DSDIRSYSTEM_H
+
+#include <QtCore/qmap.h>
+#include "IDirectoryWatchingSystem.h"
+
+class Q3DSDirWatcher;
+
+class Q3DSDirSystem : public Q3DStudio::IDirectoryWatchingSystem
+{
+public:
+ Q3DSDirSystem(Q3DStudio::TCallbackCaller caller);
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ AddDirectory(const QString &directory, Q3DStudio::TFileModCallbackType callback);
+
+private:
+ QMap<QString, Q3DSDirWatcher> m_watchers;
+ Q3DStudio::TCallbackCaller m_callbackCaller;
+};
+
+#endif // Q3DSDIRSYSTEM_H
diff --git a/src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.cpp b/src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.cpp
new file mode 100644
index 00000000..5f42d61f
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsdirwatcher.h"
+#include <QtCore/qdiriterator.h>
+
+using namespace Q3DStudio;
+
+Q3DSDirWatcher::Q3DSDirWatcher() : QObject(nullptr)
+{
+ createWatcher();
+}
+
+Q3DSDirWatcher::Q3DSDirWatcher(TCallbackCaller caller)
+ : QObject(nullptr), m_callbackCaller(caller)
+{
+ Q_ASSERT(m_callbackCaller);
+ createWatcher();
+}
+
+Q3DSDirWatcher::Q3DSDirWatcher(TCallbackCaller caller, const QString &path)
+ : Q3DSDirWatcher(caller)
+{
+ init(path);
+}
+
+Q3DSDirWatcher::Q3DSDirWatcher(const Q3DSDirWatcher &other)
+{
+ createWatcher();
+ assign(other);
+}
+
+Q3DSDirWatcher &Q3DSDirWatcher::operator=(const Q3DSDirWatcher &other)
+{
+ createWatcher();
+ assign(other);
+ return *this;
+}
+
+void Q3DSDirWatcher::assign(const Q3DSDirWatcher &other)
+{
+ init(other.m_root);
+ m_callbackCaller = other.m_callbackCaller;
+ m_callbacks = other.m_callbacks;
+ m_recordCache = other.m_recordCache;
+ m_records = other.m_records;
+}
+
+void Q3DSDirWatcher::init(const QString &path)
+{
+ addPathRecursively(path);
+ m_root = QDir(path).path();
+ m_files = m_watcher->files();
+ m_directories = m_watcher->directories();
+}
+
+void Q3DSDirWatcher::addCallback(TFileModCallbackType &callback)
+{
+ TFileModificationList records;
+ for (const QString &path : qAsConst(m_directories)) {
+ if (path != m_root)
+ records.push_back(getRecordFromCache(path, FileModificationType::Created));
+ }
+ for (const QString &path : qAsConst(m_files))
+ records.push_back(getRecordFromCache(path, FileModificationType::Created));
+
+ callback(records);
+
+ if (!m_callbacks.contains(&callback))
+ m_callbacks.insert(&callback, callback);
+}
+
+void Q3DSDirWatcher::removeCallback(TFileModCallbackType &callback)
+{
+ for (auto it = m_callbacks.begin(); it != m_callbacks.end();) {
+ if (it.key() == &callback)
+ it = m_callbacks.erase(it);
+ else
+ ++it;
+ }
+ //If no callbacks left, stop watching directories by restarting the watcher
+ if (!hasCallbacks())
+ createWatcher();
+}
+
+bool Q3DSDirWatcher::hasCallbacks() const
+{
+ return !m_callbacks.empty();
+}
+
+void Q3DSDirWatcher::directoryChanged(const QString &path)
+{
+ addPathRecursively(path);
+
+ handleChanges();
+ m_callbackCaller(std::bind(&Q3DSDirWatcher::sendRecords, this));
+}
+
+void Q3DSDirWatcher::fileChanged(const QString &path)
+{
+ addRecord(path, FileModificationType::Modified);
+
+ handleChanges();
+ m_callbackCaller(std::bind(&Q3DSDirWatcher::sendRecords, this));
+}
+
+void Q3DSDirWatcher::createWatcher()
+{
+ m_watcher = std::unique_ptr<QFileSystemWatcher>(new QFileSystemWatcher());
+ QObject::connect(m_watcher.get(), &QFileSystemWatcher::directoryChanged,
+ this, &Q3DSDirWatcher::directoryChanged);
+ QObject::connect(m_watcher.get(), &QFileSystemWatcher::fileChanged,
+ this, &Q3DSDirWatcher::fileChanged);
+}
+
+void Q3DSDirWatcher::addPathRecursively(const QString &path)
+{
+ QDir dir(path);
+ m_watcher->addPath(dir.path());
+ QDirIterator it(path, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ QString nextPath = it.next();
+ if (!nextPath.endsWith("."))
+ m_watcher->addPath(nextPath);
+ }
+}
+
+void Q3DSDirWatcher::addChanges(QStringList &to, const QStringList &from)
+{
+ const QStringList destroyed = QStringList::fromSet(to.toSet().subtract(from.toSet()));
+ const QStringList created = QStringList::fromSet(from.toSet().subtract(to.toSet()));
+
+ for (const QString &path : destroyed)
+ addRecord(path, FileModificationType::Destroyed);
+
+ for (const QString &path : created)
+ addRecord(path, FileModificationType::Created);
+
+ to = from;
+}
+
+template <typename T>
+QStringList removeDeletedPaths(QFileSystemWatcher &watcher, const QStringList &paths)
+{
+ QStringList removed;
+ for (const QString &str : paths) {
+ T path(str);
+ if (!path.exists())
+ removed.push_back(str);
+ }
+ if (!removed.empty())
+ return watcher.removePaths(removed);
+ return QStringList();
+}
+
+void Q3DSDirWatcher::handleChanges()
+{
+ removeDeletedPaths<QFile>(*m_watcher, m_watcher->files());
+ QStringList failures = removeDeletedPaths<QDir>(*m_watcher, m_watcher->directories());
+
+ //It seems that QFileSystemWatcher doesn't want to remove renamed
+ //directories from the watchlist if the directory contains files.
+ //If this happens restart the whole watcher and repopulate the watchlist
+ if (!failures.empty()) {
+ createWatcher();
+ addPathRecursively(m_root);
+ }
+
+ addChanges(m_directories, m_watcher->directories());
+ addChanges(m_files, m_watcher->files());
+}
+
+void Q3DSDirWatcher::sendRecords()
+{
+ if (!m_records.empty()) {
+ //A callback can cause the destruction of this object
+ //so member variables shouldn't be accessed after a callback
+ TFileModificationList records = m_records;
+ m_records.clear();
+ auto callbacks = m_callbacks;
+ for (auto it = callbacks.begin(); it != callbacks.end(); ++it) {
+ auto& callback = it.value();
+ callback(records);
+ }
+ }
+}
+
+void Q3DSDirWatcher::addRecord(const QString &path, FileModificationType::Enum type)
+{
+ m_records.push_back(getRecordFromCache(path, type));
+}
+
+SFileModificationRecord Q3DSDirWatcher::getRecordFromCache(const QString &path,
+ FileModificationType::Enum type)
+{
+ if (m_recordCache.contains(path)) {
+ m_recordCache[path].m_ModificationType = type;
+ return m_recordCache[path];
+ }
+
+ CFilePath filePath = CFilePath(CString::fromQString(path));
+ SFileInfoFlags flags = filePath.GetFileFlags();
+ SFileData data = filePath.GetFileData();
+ m_recordCache.insert(path, SFileModificationRecord(filePath, flags, data, type));
+ return m_recordCache[path];
+}
diff --git a/src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.h b/src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.h
new file mode 100644
index 00000000..7596eb88
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/Utility/q3dsdirwatcher.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSDIRWATCHER_H
+#define Q3DSDIRWATCHER_H
+
+#include <QtCore/qfilesystemwatcher.h>
+#include "IDirectoryWatchingSystem.h"
+#include "UICFileTools.h"
+
+class Q3DSDirWatcher : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q3DSDirWatcher();
+ Q3DSDirWatcher(Q3DStudio::TCallbackCaller caller);
+ Q3DSDirWatcher(Q3DStudio::TCallbackCaller caller, const QString &path);
+ Q3DSDirWatcher(const Q3DSDirWatcher &other);
+ Q3DSDirWatcher &operator=(const Q3DSDirWatcher &other);
+
+ void addCallback(Q3DStudio::TFileModCallbackType &callback);
+ void removeCallback(Q3DStudio::TFileModCallbackType &callback);
+ bool hasCallbacks() const;
+
+private Q_SLOTS:
+ void directoryChanged(const QString &path);
+ void fileChanged(const QString &path);
+
+private:
+ void init(const QString &path);
+ void assign(const Q3DSDirWatcher &other);
+ void createWatcher();
+ void addPathRecursively(const QString &path);
+ void addChanges(QStringList &to, const QStringList &from);
+ void handleChanges();
+ void sendRecords();
+ void addRecord(const QString &path, Q3DStudio::FileModificationType::Enum type);
+ Q3DStudio::SFileModificationRecord
+ getRecordFromCache(const QString &path, Q3DStudio::FileModificationType::Enum type);
+
+ std::unique_ptr<QFileSystemWatcher> m_watcher;
+ QString m_root;
+ QStringList m_directories;
+ QStringList m_files;
+
+ //TFileModCallbackType can't be compared so the pointer is needed for comparisons.
+ //A copy is also needed so that calls can be made after the pointed object has been
+ //destroyed. Pointed object is owned by Q3DSDirCallback.
+ QMap<Q3DStudio::TFileModCallbackType *, Q3DStudio::TFileModCallbackType> m_callbacks;
+ Q3DStudio::TCallbackCaller m_callbackCaller;
+ QMap<QString, Q3DStudio::SFileModificationRecord> m_recordCache;
+ Q3DStudio::TFileModificationList m_records;
+};
+
+#endif // Q3DSDIRWATCHER_H
diff --git a/src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.cpp b/src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.cpp
new file mode 100644
index 00000000..106a3493
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "PlaybackClock.h"
+#include "Doc.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+#include "UICDMDataCore.h"
+
+//==============================================================================
+// Static Member Initialization
+//==============================================================================
+
+UIC_DEFINE_THISFILE;
+
+using namespace UICDM;
+using namespace std;
+
+//====================================================================
+/**
+ *
+ */
+CPlaybackClock::CPlaybackClock(CDoc *inDoc)
+ : m_Doc(inDoc)
+ , m_LastAbsoluteTime(0)
+{
+}
+
+CPlaybackClock::~CPlaybackClock()
+{
+}
+
+// Called when the document is setting the time.
+// We need to ensure that
+void CPlaybackClock::OnTimeChange(long inNewTime)
+{
+ m_LastAbsoluteTime = m_ContextTimer.GetTime();
+ m_VirtualTime = inNewTime;
+}
+
+//====================================================================
+/**
+ * The core of the updating cycle, this will do all the attachments,
+ * detachments and events necessary for this time.
+ */
+void CPlaybackClock::UpdateTime()
+{
+ long lastAbsTime = m_LastAbsoluteTime;
+ m_LastAbsoluteTime = m_ContextTimer.GetTime();
+ m_VirtualTime += m_LastAbsoluteTime - lastAbsTime;
+
+ long theCurrentTime = 0;
+ switch (m_Policy) {
+ case PlaybackClockPolicy::Normal:
+ theCurrentTime = m_VirtualTime;
+ if (m_Looping) {
+ theCurrentTime = theCurrentTime % m_UpperBound;
+ m_VirtualTime = theCurrentTime;
+ }
+ break;
+ case PlaybackClockPolicy::RoundTrip: {
+ long numCycles = m_VirtualTime / m_UpperBound;
+ long cycleTime = m_VirtualTime % m_UpperBound;
+ if (m_Looping == false && numCycles > 1) {
+ theCurrentTime = 0;
+ } else {
+ if (numCycles % 2)
+ theCurrentTime = m_UpperBound - cycleTime;
+ else
+ theCurrentTime = cycleTime;
+ }
+ } break;
+ }
+
+ // Code to play through to another slides
+ if (theCurrentTime >= m_UpperBound)
+ OnReachedUpperBound();
+ else
+ m_Doc->DoNotifyTimeChanged(theCurrentTime);
+}
+
+void CPlaybackClock::OnReachedUpperBound()
+{
+ UICDM::CUICDMSlideHandle theActiveSlide(m_Doc->GetActiveSlide());
+ // clock has passed the end, check whether needs to switch slide
+ UICDM::CUICDMInstanceHandle theInstanceHandle =
+ GetSlideSystem()->GetSlideInstance(theActiveSlide);
+
+ // Get the play through state
+ UICDM::SValue theValue;
+ GetPropertySystem()->GetInstancePropertyValue(
+ theInstanceHandle, GetClientDataModelBridge()->GetSlide().m_PlayMode, theValue);
+ Q3DStudio::CString thePlayMode = UICDM::get<UICDM::TDataStrPtr>(theValue)->GetData();
+
+ if (thePlayMode == L"Play Through To...") {
+ // figure out which slide to activate
+ GetPropertySystem()->GetInstancePropertyValue(
+ theInstanceHandle, GetClientDataModelBridge()->GetSlide().m_PlaythroughTo, theValue);
+ SStringOrInt thePlaythroughTo = UICDM::get<SStringOrInt>(theValue);
+
+ UICDM::ISlideSystem *theSlideSystem = GetSlideSystem();
+ UICDM::CUICDMSlideHandle thePlaythroughToSlide;
+
+ if (thePlaythroughTo.GetType() == SStringOrIntTypes::String) {
+ Q3DStudio::CString theValue(get<TDataStrPtr>(thePlaythroughTo.m_Value)->GetData());
+ if (theValue == L"Next") {
+ size_t theNextSlideIndex = theSlideSystem->GetSlideIndex(theActiveSlide) + 1;
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlide(theActiveSlide);
+ size_t theSlideCount = theSlideSystem->GetSlideCount(theMasterSlide);
+ if (theNextSlideIndex < theSlideCount) {
+ // Activate the next slide
+ thePlaythroughToSlide =
+ theSlideSystem->GetSlideByIndex(theMasterSlide, theNextSlideIndex);
+ }
+ } else if (theValue == L"Previous") {
+ int thePrevSlideIndex = theSlideSystem->GetSlideIndex(theActiveSlide) - 1;
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlide(theActiveSlide);
+ if (thePrevSlideIndex > 0) // Index 0 refers to MasterSlide, so we check > 0
+ {
+ // Activate the prev slide
+ thePlaythroughToSlide =
+ theSlideSystem->GetSlideByIndex(theMasterSlide, thePrevSlideIndex);
+ }
+ }
+ } else {
+ // Extract the slide handle from the string
+ thePlaythroughToSlide = get<long>(thePlaythroughTo.m_Value);
+ }
+
+ if (thePlaythroughToSlide.Valid()) {
+ m_Doc->NotifyActiveSlideChanged(thePlaythroughToSlide, true, true);
+ UpdateClockProperties();
+ StartPlayback();
+ }
+ } else if (thePlayMode == L"Stop at end") {
+ m_Doc->DoNotifyTimeChanged(m_UpperBound);
+ }
+}
+
+//====================================================================
+/**
+ * Called when user clicks Play
+ */
+void CPlaybackClock::StartPlayback()
+{
+ UpdateClockProperties();
+ m_ContextTimer.Resume();
+}
+
+//====================================================================
+/**
+ * Called when user clicks Stop
+ */
+void CPlaybackClock::StopPlayback()
+{
+ m_ContextTimer.Pause();
+}
+
+//====================================================================
+/**
+ * This method will reset all local time calculations.
+ * So the next time read will be min time.
+ */
+void CPlaybackClock::Reset()
+{
+ m_ContextTimer.Reset();
+ m_ContextTimer.Pause();
+
+ m_LastAbsoluteTime = m_ContextTimer.GetTime();
+ m_VirtualTime = m_Doc->GetCurrentClientTime();
+}
+
+//====================================================================
+/**
+ * Sets the Clock properties based on the active slide
+ */
+void CPlaybackClock::UpdateClockProperties()
+{
+ UICDM::CUICDMInstanceHandle theInstanceHandle =
+ GetSlideSystem()->GetSlideInstance(m_Doc->GetActiveSlide());
+ ASSERT(theInstanceHandle.Valid());
+
+ UICDM::SValue theValue;
+ GetPropertySystem()->GetInstancePropertyValue(
+ theInstanceHandle, GetClientDataModelBridge()->GetSlide().m_InitialPlayState, theValue);
+ Q3DStudio::CString theInitialPlayState = UICDM::get<UICDM::TDataStrPtr>(theValue)->GetData();
+
+ GetPropertySystem()->GetInstancePropertyValue(
+ theInstanceHandle, GetClientDataModelBridge()->GetSlide().m_PlayMode, theValue);
+ Q3DStudio::CString thePlayMode = UICDM::get<UICDM::TDataStrPtr>(theValue)->GetData();
+
+ m_Policy = PlaybackClockPolicy::Normal;
+ m_Looping = false;
+
+ if (thePlayMode == L"Looping") // Loop
+ {
+ m_Looping = true;
+ } else if (thePlayMode == L"PingPong") // Ping Pong.
+ {
+ m_Policy = PlaybackClockPolicy::RoundTrip;
+ m_Looping = true;
+ } else if (thePlayMode == L"Ping") // Ping Pong Once.
+ {
+ m_Policy = PlaybackClockPolicy::RoundTrip;
+ m_Looping = false;
+ }
+
+ m_UpperBound = m_Doc->GetLatestEndTime();
+ m_VirtualTime = m_Doc->GetCurrentClientTime();
+}
+
+UICDM::IPropertySystem *CPlaybackClock::GetPropertySystem() const
+{
+ return m_Doc->GetStudioSystem()->GetPropertySystem();
+}
+UICDM::ISlideSystem *CPlaybackClock::GetSlideSystem() const
+{
+ return m_Doc->GetStudioSystem()->GetSlideSystem();
+}
+CClientDataModelBridge *CPlaybackClock::GetClientDataModelBridge() const
+{
+ return m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+}
diff --git a/src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.h b/src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.h
new file mode 100644
index 00000000..51d29544
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/VirtualAssets/PlaybackClock.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2002-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PLAYBACK_CLOCK
+#define INCLUDED_PLAYBACK_CLOCK 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMHandles.h"
+#include "Timer.h"
+
+class CDoc;
+class CClientDataModelBridge;
+
+namespace UICDM {
+class ISlideSystem;
+class IPropertySystem;
+}
+
+struct PlaybackClockPolicy
+{
+ enum Enum {
+ Normal,
+ RoundTrip,
+ };
+};
+
+//==============================================================================
+/**
+ * @class CPlaybackClock
+ */
+class CPlaybackClock
+{
+ // Field Variables
+protected:
+ PlaybackClockPolicy::Enum m_Policy;
+ bool m_Looping;
+ long m_UpperBound;
+
+ CDoc *m_Doc;
+ long m_LastAbsoluteTime;
+ long m_VirtualTime;
+
+ CTimer m_ContextTimer;
+
+ // Constructors
+public:
+ CPlaybackClock(CDoc *inDoc);
+ virtual ~CPlaybackClock();
+
+public:
+ virtual void UpdateTime();
+
+ // Playback Related
+ void StartPlayback();
+ void StopPlayback();
+ void Reset();
+ void OnTimeChange(long inNewTime);
+
+ // Implementation
+protected:
+ void UpdateClockProperties();
+ void OnReachedUpperBound();
+
+ // UICDM Helper functions.
+ inline UICDM::IPropertySystem *GetPropertySystem() const;
+ inline UICDM::ISlideSystem *GetSlideSystem() const;
+ inline CClientDataModelBridge *GetClientDataModelBridge() const;
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/VirtualAssets/VClock.h b/src/Authoring/Client/Code/Core/VirtualAssets/VClock.h
new file mode 100644
index 00000000..8d260e4a
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/VirtualAssets/VClock.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "VClockPolicy.h"
+
+template <typename TTimePolicy = CVClockPolicy>
+class CVClock
+{
+public:
+ CVClock();
+ virtual ~CVClock();
+
+ // Function for Setting the Policy
+ void SetUpperBound(long inUpperBound) { m_TimePolicy.SetUpperBound(inUpperBound); }
+ long GetUpperBound() { return m_TimePolicy.GetUpperBound(); }
+ void SetLowerBound(long inLowerBound) { m_TimePolicy.SetLowerBound(inLowerBound); }
+ long GetLowerBound() { return m_TimePolicy.GetLowerBound(); }
+ void SetClockType(long inClockType) { m_TimePolicy.SetClockType(inClockType); }
+ long GetClockType() { return m_TimePolicy.GetClockType(); }
+ void SetLooping(bool inLooping) { m_TimePolicy.SetLooping(inLooping); }
+ bool GetLooping() { return m_TimePolicy.GetLooping(); }
+
+ long UpdateClock(long inAbsoluteTime);
+ long GetTime();
+ void SetTime(long inTime, long inAbsoluteTime);
+
+protected:
+ bool AdjustTime(long &inVirtualTime, long inAdjustedTime, bool &outPonged);
+
+private:
+ TTimePolicy m_TimePolicy;
+
+ long m_VirtualTime;
+ long m_Marker; // The difference between the absolute time and the virtual time
+};
+
+//==============================================================================
+/**
+ * Constructor.
+ *
+ * Set the Field Values to a reasonable value.
+ *
+ */
+template <typename TTimePolicy>
+CVClock<TTimePolicy>::CVClock()
+ : m_VirtualTime(0)
+ , m_Marker(0)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor.
+ */
+template <typename TTimePolicy>
+CVClock<TTimePolicy>::~CVClock()
+{
+}
+
+//==============================================================================
+/**
+ * This will calculate the Virtual time based on the Parents virtual time.
+ *
+ * This function will also adjust the time based on clock Rate.
+ * and wether or not the Object is paused or not.
+ * Also the Clock Policy will adjust the time based on the Bounds.
+ * And context type.
+ *
+ * @param inAbsoluteTime The parents Virtual time.
+ * @param outPonged only valid for roundtrip clock policy (refer to
+ * CVClockPolicy::HandleRoundTrip), always false for normal clock policy
+ *
+ * @return The Adjusted Time.
+ */
+template <typename TTimePolicy>
+bool CVClock<TTimePolicy>::AdjustTime(long &outVirtualTime, long inAdjustedTime, bool &outPonged)
+{
+ bool theLooped = false;
+
+ // return of true implies that we looped and we need to reset out clock.
+ theLooped = m_TimePolicy.AdjustTime(outVirtualTime, outPonged);
+
+ if (theLooped) {
+ m_Marker = inAdjustedTime - outVirtualTime;
+ }
+
+ return theLooped;
+}
+
+//==============================================================================
+/**
+ * This will calculate the Virtual time based on the Parents virtual time.
+ * @param inAbsoluteTime the Virtual time of the parent.
+ * @return
+ */
+template <typename TTimePolicy>
+long CVClock<TTimePolicy>::UpdateClock(long inAbsoluteTime)
+{
+ // We have to calculate a new Virtual Time.
+ // Send the Virtual time off to the TimePolicy so it can process it.
+ m_VirtualTime = inAbsoluteTime - m_Marker;
+
+ if (m_VirtualTime < 0) {
+ m_VirtualTime = 0;
+ m_Marker = inAbsoluteTime;
+ }
+
+ // If AdjustTime returns true if we looped and we need to reset out clock.
+ bool thePonged;
+ AdjustTime(m_VirtualTime, inAbsoluteTime, thePonged);
+
+ return m_VirtualTime;
+}
+
+//==============================================================================
+/**
+ * Gets the Adjusted time of the Clock.
+ *
+ * @return the Virtual time.
+ */
+template <typename TTimePolicy>
+long CVClock<TTimePolicy>::GetTime()
+{
+ return m_VirtualTime;
+}
+
+template <typename TTimePolicy>
+void CVClock<TTimePolicy>::SetTime(long inTime, long inAbsoluteTime)
+{
+ m_VirtualTime = inTime;
+ m_Marker = inAbsoluteTime - m_VirtualTime;
+} \ No newline at end of file
diff --git a/src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.cpp b/src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.cpp
new file mode 100644
index 00000000..71dbd4a6
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+//==============================================================================
+// Includes
+//==============================================================================
+#include "VClockPolicy.h"
+#include "ClientErrorIDs.h"
+
+UIC_DEFINE_THISFILE;
+
+CVClockPolicy::CVClockPolicy()
+{
+ m_UpperBound = LONG_MAX;
+ m_LowerBound = 0;
+ m_Looping = false;
+ m_Type = POLICY_NORMAL;
+}
+
+CVClockPolicy::CVClockPolicy(const CVClockPolicy &inSource)
+{
+ m_UpperBound = inSource.m_UpperBound;
+ m_LowerBound = inSource.m_LowerBound;
+ m_Looping = inSource.m_Looping;
+ m_Type = inSource.m_Type;
+}
+
+long CVClockPolicy::ReverseTime(long inVirtualTime)
+{
+ return m_UpperBound - inVirtualTime;
+}
+//==============================================================================
+/**
+ * This will handle the Time calculation for a forward moving Timer.
+ *
+ * The incomming time will be adjusted based on the Range. Also the Time will
+ * get the Last value if we are not "Looping" otherwise loop to the start time.
+ *
+ * @param inVirtualTime the time from the Clock. it is a time relative to the last
+ *"Pause/Reset"
+ *
+ * @return the Adjusted Time.
+ */
+long CVClockPolicy::HandleNormal(long inVirtualTime, long inRange, bool &outLooped)
+{
+ long theLeftValue = 0;
+
+ outLooped = false;
+
+ if (inVirtualTime <= m_UpperBound) {
+ if (inVirtualTime >= m_LowerBound)
+ theLeftValue = inVirtualTime;
+ else
+ theLeftValue = m_LowerBound;
+ } else {
+ if (m_Looping) {
+ long theAdjustedTime = inVirtualTime % m_UpperBound;
+ theLeftValue = ((theAdjustedTime) % inRange) + m_LowerBound;
+ outLooped = true;
+ } else {
+ theLeftValue = m_UpperBound;
+ }
+ }
+
+ return theLeftValue;
+}
+
+//==============================================================================
+/**
+* This will determine the next clock value based on a policy that runs up and back.
+*
+* @param inVirtualTime the time from the Clock.
+* @param inRange the time from the Clock.
+* @param outPonged set to true when adjusted time reaches m_UpperBound .
+* ( i.e when clock reaches the 'pong' end )
+*
+* @return the Adjusted time.
+*/
+long CVClockPolicy::HandleRoundTrip(long inVirtualTime, long inRange, bool &outLooped,
+ bool &outPonged)
+{
+ Q_UNUSED(inRange);
+ long theLeftValue = 0;
+
+ outLooped = false;
+ outPonged = false;
+
+ // This is the up direction.
+ if (inVirtualTime <= m_UpperBound) {
+ theLeftValue = inVirtualTime;
+ outPonged = (theLeftValue == m_UpperBound);
+ }
+ // This is the Downward direction.
+ else {
+ // TODO : This codes doesn't seem correct. It should have uses the modulus similar to
+ // HandleNormal
+ // See the newly added failing (but commented out test case at VClock.cxx in RoundTripTest
+ theLeftValue = 2 * m_UpperBound - inVirtualTime;
+ if (theLeftValue < m_LowerBound) {
+ if (m_Looping) {
+ theLeftValue = 2 * m_LowerBound - theLeftValue;
+ outLooped = true;
+ } else {
+ theLeftValue = m_LowerBound;
+ }
+ }
+ }
+ return theLeftValue;
+}
+
+bool CVClockPolicy::AdjustTime(long &ioVirtualTime, bool &outPonged)
+{
+ long theLeftValue = 0;
+ long theRange = m_UpperBound - m_LowerBound;
+ bool theLooped = false;
+
+ outPonged = false; // initialize this
+ if (theRange > 0) {
+ switch (m_Type) {
+ case POLICY_NORMAL:
+ // Note: The Range should be one more than the Diff, since we are inclusive.
+ theLeftValue = this->HandleNormal(ioVirtualTime, theRange, theLooped);
+ outPonged = false;
+ break;
+ case POLICY_ROUNDTRIP:
+ theLeftValue = this->HandleRoundTrip(ioVirtualTime, theRange, theLooped, outPonged);
+ break;
+ default:
+ break;
+ }
+ } else {
+ theLeftValue = m_LowerBound;
+ theRange = 100;
+ }
+
+ ioVirtualTime = theLeftValue;
+
+ return theLooped;
+}
diff --git a/src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.h b/src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.h
new file mode 100644
index 00000000..c9a7b90a
--- /dev/null
+++ b/src/Authoring/Client/Code/Core/VirtualAssets/VClockPolicy.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_VCLOCKPOLICY
+#define INCLUDED_VCLOCKPOLICY
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+class CVClockPolicy
+{
+public:
+ enum EPolicy { POLICY_NORMAL = 1, POLICY_ROUNDTRIP = 2, POLICY_UNKNOWN = 3 };
+
+private:
+ long m_UpperBound;
+ long m_LowerBound;
+
+ bool m_Looping;
+ long m_Type;
+
+public:
+ CVClockPolicy(const CVClockPolicy &inSource);
+ CVClockPolicy();
+
+ bool AdjustTime(long &ioVirtualTime, bool &outPonged);
+ long ReverseTime(long inVirtualTime);
+
+ void SetUpperBound(long inUpperBound) { m_UpperBound = inUpperBound; }
+ long GetUpperBound() { return m_UpperBound; }
+ void SetLowerBound(long inLowerBound) { m_LowerBound = inLowerBound; }
+ long GetLowerBound() { return m_LowerBound; }
+ void SetClockType(long inClockType) { m_Type = inClockType; }
+ long GetClockType() { return m_Type; }
+ void SetLooping(bool inLooping) { m_Looping = inLooping; }
+ bool GetLooping() { return m_Looping; }
+private:
+ long HandleRoundTrip(long inVirtualTime, long inRange, bool &outLooped, bool &outPonged);
+ long HandleNormal(long inVirtualTime, long inRange, bool &outLooped);
+};
+
+#endif // INCLUDED_VCLOCKPOLICY
diff --git a/src/Authoring/Client/Code/Shared/CommonConstants.h b/src/Authoring/Client/Code/Shared/CommonConstants.h
new file mode 100644
index 00000000..582c9feb
--- /dev/null
+++ b/src/Authoring/Client/Code/Shared/CommonConstants.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __CommonConstants_H__
+#define __CommonConstants_H__
+
+// The current version of the player
+const float CURRENT_PLAYER_VERSION = 1.0f;
+
+// Current User Registry Keys
+const char UIC_CLIENT_PREFERENCES_VALUE[] = "Preferences";
+const char UIC_CLIENT_REGISTRY_KEY_BASE[] = "Software\\Qt3DStudio\\Client";
+const char UIC_CLIENT_REGISTRY_KEY_ROOT[] = "Software\\Qt3DStudio\\Client\\1.0";
+const char UIC_CLIENT_REGISTRY_KEY[] = "Software\\Qt3DStudio\\Client\\1.0\\Preferences";
+const char UIC_CLIENT_MESSAGES_KEY[] = "Software\\Qt3DStudio\\Client\\1.0\\Preferences\\Messages";
+
+// Local Machine Registry Keys
+const char UIC_CLIENT_PLUGINS_VALUE[] = "Plugins";
+const char UIC_CLIENT_EXTENSIONS_VALUE[] = "Extensions";
+const char UIC_CLIENT_LATESTVERSION_VALUE[] = "LatestVersion";
+const char UIC_CLIENT_CURRENTVERSION_VALUE[] = "CurrentVersion";
+
+const char UIC_CLIENT_PLUGINS_KEY[] = "Software\\Qt3DStudio\\Client\\1.0\\Plugins";
+const char UIC_CLIENT_EXTENSIONS_KEY[] = "Software\\Qt3DStudio\\Client\\1.0\\Extensions";
+const char UIC_CLIENT_LATESTVERSION_KEY[] = "Software\\Qt3DStudio\\Client\\1.0\\LatestVersion";
+const char UIC_CLIENT_CURRENTVERSION_KEY[] = "Software\\Qt3DStudio\\Client\\1.0\\CurrentVersion";
+
+// Preference Registry Keys
+const char UIC_CLIENT_INITIALIZED_VALUE[] = "Initialized";
+const char UIC_CLIENT_AUTOMATICUPDATE_VALUE[] = "AutomaticallyUpdate";
+const char UIC_CLIENT_FORCENOINSTALL_VALUE[] = "ForceNoInstall";
+const char UIC_CLIENT_FORCEINSTALL_VALUE[] = "ForceInstall";
+const char UIC_CLIENT_NOREGISTER_VALUE[] = "NoRegister";
+const char UIC_CLIENT_LOGMODE_VALUE[] = "LogMode"; // REG_DWORD, 0, 1, 2, 3
+const char UIC_CLIENT_LOGLEVEL_VALUE[] = "LogLevel"; // REG_DWORD, 0, 1, 2, 3
+const char UIC_CLIENT_LOGTHRESHOLD_VALUE[] = "LogThreshold"; // REG_DWORD, # of entries
+const char UIC_CLIENT_CONTEXTMENU_VALUE[] = "ContextMenu";
+
+const char UIC_CLIENT_TRACKERRORTYPES_VALUE[] = "TrackErrorTypes";
+const char UIC_CLIENT_REPORTINGLEVEL_VALUE[] = "ReportingLevel";
+const char UIC_CLIENT_ERRORACTION_VALUE[] = "ErrorAction";
+const char UIC_CLIENT_FILENAMELINENO_VALUE[] = "FileNameLineNo";
+
+const char UIC_CLIENT_ENABLESCRIPTDEBUGGER_VALUE[] = "EnableScriptDebugger";
+const char UIC_CLIENT_DEBUGMODE_VALUE[] = "DebugMode";
+const char UIC_CLIENT_MINTIMEPERFRAME_VALUE[] = "MinTimePerFrame";
+const char UIC_CLIENT_UPDATEURL_VALUE[] = "DebugUpdateUrl";
+const char UIC_CLIENT_LASTUPDATECHECK_VALUE[] = "LastUpdateCheck";
+const char UIC_CLIENT_OVERRIDELASTUPDATE_VALUE[] = "LastUpdateCheckOverride";
+const char UIC_CLIENT_UPDATEINTERVAL_VALUE[] = "UpdateInterval";
+const char UIC_CLIENT_DEPRECATEDPRESENTATION_VALUE[] = "DeprecatedPresentationWarning";
+const char UIC_CLIENT_OPENGLDRIVER_VALUE[] = "OpenGLDriverWarning";
+const char UIC_CLIENT_GRAPHICSRENDERER_VALUE[] = "ClientRenderer";
+const char UIC_CLIENT_LICENSEKEY_VALUE[] = "LicenseKey";
+
+/*
+const char UIC_CLIENT_AGREEEULA_VALUE [] = "AgreeEULA";
+const char UIC_CLIENT_LASTNAME_VALUE [] = "LastName";
+const char UIC_CLIENT_FIRSTNAME_VALUE [] = "FirstName";
+const char UIC_CLIENT_USEREMAIL_VALUE [] = "UserEmail";
+const char UIC_CLIENT_OVER13_VALUE [] = "UserOver13";
+const char UIC_CLIENT_MAILINGLIST_VALUE [] = "MailingList";
+*/
+
+// Uninstall Registry Keys
+const char UNINSTALL_REGISTRY_KEY[] =
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Qt3DStudioClient10";
+
+// Uninstall Registry Value Names
+const char UNINSTALL_DISPLAYNAME_VALUE[] = "DisplayName";
+const char UNINSTALL_COMMANDLINE_VALUE[] = "UninstallString";
+
+// File Names
+const char INSTALL_LOG_FILE_NAME[] = "Install.log";
+const char UNINSTALL_DATA_FILE_NAME[] = "Uninstal.dat";
+const char UIC_AUTO_UPDATER_EXE[] = "AMInstal.exe";
+const char UIC_CONTROL_PANEL[] = "AKCPanel.cpl";
+
+// Directory Names
+const char UIC_DIRECTORY[] = "\\The Qt Company\\";
+const char UIC_CLIENT_DIRECTORY[] = "Qt 3D Studio\\";
+const char UIC_TEMP_DIRECTORY[] = "Install\\";
+
+// Installer command line options
+const char REMOTE_COMMAND_LINE_OPTION[] = "remote";
+const char UNINSTALL_COMMAND_LINE_OPTION[] = "uninstall";
+const char SILENT_COMMAND_LINE_OPTION[] = "silent";
+const char INSTALLFROM_COMMAND_LINE_OPTION[] = "installfrom";
+
+// Uninstall file section names
+const char VERSION_SECTION_NAME[] = "Version";
+const char FILES_SECTION_NAME[] = "Files";
+const char DIR_SECTION_NAME[] = "Directories";
+const char REGKEY_SECTION_NAME[] = "RegKeys";
+const char REGVALUE_SECTION_NAME[] = "RegValues";
+
+// Uninstall file values
+const char FILEVERSION_VALUE[] = "FileVersion";
+const char REGISTRYROOT_HKLM[] = "HKLM";
+const char REGISTRYROOT_HKCU[] = "HKCU";
+
+// Misc
+const long CLIENT_UPDATE_INTERVAL = 7; ///< 7 days
+
+// OpenGL
+const char OPENGL_REQUIRED_EXTENSIONS[] =
+ "GL_EXT_bgra GL_WIN_swap_hint GL_ARB_multitexture GL_EXT_texture_env_combine";
+
+// Unwelcome Video Vendor
+const char UNSUPPORT_VIDEO_VENDOR[] = "Microsoft Corporation";
+
+// Action mask ids
+const unsigned long ACTION_LOG_BITMASK = 0x00000001; ///< Write to log file
+const unsigned long ACTION_DISPLAYMESSAGEBOX_BITMASK = 0x00000002; ///< Display a message box
+const unsigned long ACTION_DEBUGGEROUTPUT_BITMASK = 0x00000004; ///< Output to debugger window
+const unsigned long ACTION_DEBUGBREAK_BITMASK = 0x00000008; ///< Break at the spot
+
+// 3D constants
+const float UIC3D_DEGREES_TO_RADIANS = (float)0.0174532925199;
+const float UIC3D_RADIANS_TO_DEGREES = (float)57.2957795131;
+
+// Fullscreen anti-aliasing modes
+const long FSAA_OFF = 0x00000000; ///< No fullscreen anti-aliasing
+const long FSAA_1X = 0x00000001; ///< 1x sample
+const long FSAA_2X = 0x00000002; ///< 2x sample
+const long FSAA_4X = 0x00000004; ///< 4x sample
+const long FSAA_6X = 0x00000006; ///< 6x sample
+const long FSAA_8X = 0x00000008; ///< 8x sample
+
+#endif // __CommonConstants_H__
diff --git a/src/Authoring/Client/Code/Shared/Log/LogHelper.cpp b/src/Authoring/Client/Code/Shared/Log/LogHelper.cpp
new file mode 100644
index 00000000..6d77dfe1
--- /dev/null
+++ b/src/Authoring/Client/Code/Shared/Log/LogHelper.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "LogHelper.h"
+#include "UICMath.h"
+
+//==============================================================================
+// Statics
+//==============================================================================
+
+IUICLog2 *CLogHelper::s_UICLog2;
+
+//==============================================================================
+// Methods
+//==============================================================================
+
+#ifdef WIN32
+
+void CLogHelper::Log(long inLogType, const wchar_t *inFileName, long inLineNumber,
+ long inCategoryType, const wchar_t *inLogString, ...)
+{
+ if (s_UICLog2 != NULL) {
+ TSAddEntryIndirect theAddEntryIndirectStruct = { 0 };
+
+ theAddEntryIndirectStruct.m_StructSize = sizeof(theAddEntryIndirectStruct);
+ // theAddEntryIndirectStruct.m_LogStringId // not used
+ wcsncpy(theAddEntryIndirectStruct.m_LogString, inLogString,
+ Q3DStudio::MIN((size_t)MAX_PATH, wcslen(inLogString)));
+ va_start(theAddEntryIndirectStruct.m_LogParamList, inLogString);
+ wcsncpy(theAddEntryIndirectStruct.m_FileNameString, inFileName,
+ Q3DStudio::MIN((size_t)MAX_PATH, wcslen(inFileName)));
+ theAddEntryIndirectStruct.m_LineNumberLong = inLineNumber;
+ theAddEntryIndirectStruct.m_Mask = UICLOG_STRING;
+ theAddEntryIndirectStruct.m_Level = LOGLEVEL_CRITICAL;
+ theAddEntryIndirectStruct.m_LogType = inLogType;
+ theAddEntryIndirectStruct.m_CategoryType = inCategoryType;
+
+ s_UICLog2->AddEntryIndirect((long)&theAddEntryIndirectStruct);
+
+ va_end(theAddEntryIndirectStruct.m_LogParamList);
+ }
+}
+
+void CLogHelper::Log(long inLogType, const wchar_t *inFileName, long inLineNumber,
+ long inCategoryType, long inStringId, ...)
+{
+ if (s_UICLog2 != NULL) {
+ TSAddEntryIndirect theAddEntryIndirectStruct = { 0 };
+
+ theAddEntryIndirectStruct.m_StructSize = sizeof(theAddEntryIndirectStruct);
+ theAddEntryIndirectStruct.m_LogStringId = inStringId;
+
+ va_start(theAddEntryIndirectStruct.m_LogParamList, inStringId);
+ wcsncpy(theAddEntryIndirectStruct.m_FileNameString, inFileName,
+ Q3DStudio::MIN((size_t)MAX_PATH, wcslen(inFileName)));
+ theAddEntryIndirectStruct.m_LineNumberLong = inLineNumber;
+ theAddEntryIndirectStruct.m_Mask = UICLOG_ID;
+ theAddEntryIndirectStruct.m_Level = LOGLEVEL_CRITICAL;
+ theAddEntryIndirectStruct.m_LogType = inLogType;
+ theAddEntryIndirectStruct.m_CategoryType = inCategoryType;
+
+ s_UICLog2->AddEntryIndirect((long)&theAddEntryIndirectStruct);
+
+ va_end(theAddEntryIndirectStruct.m_LogParamList);
+ }
+}
+
+void CLogHelper::Trace(long inCategoryType, const wchar_t *inLogString, ...)
+{
+ try {
+ if (s_UICLog2 != NULL) {
+ TSAddEntryIndirect theAddEntryIndirectStruct = { 0 };
+
+ theAddEntryIndirectStruct.m_StructSize = sizeof(theAddEntryIndirectStruct);
+ wcsncpy(theAddEntryIndirectStruct.m_LogString, inLogString,
+ Q3DStudio::MIN((size_t)MAX_PATH, wcslen(inLogString)));
+ va_start(theAddEntryIndirectStruct.m_LogParamList, inLogString);
+ theAddEntryIndirectStruct.m_Mask = UICLOG_STRING;
+ theAddEntryIndirectStruct.m_Level = LOGLEVEL_INFO;
+ theAddEntryIndirectStruct.m_CategoryType = inCategoryType;
+
+ s_UICLog2->AddEntryIndirect((long)&theAddEntryIndirectStruct);
+
+ va_end(theAddEntryIndirectStruct.m_LogParamList);
+ }
+ }
+
+ catch (...) {
+ }
+}
+
+void CLogHelper::AddEntry(long inType, const wchar_t *inMsg)
+{
+ if (s_UICLog2 != NULL) {
+ s_UICLog2->AddEntry(inType, (BYTE *)inMsg);
+ }
+}
+
+void CLogHelper::Start()
+{
+ ::CoInitialize(NULL);
+
+ try {
+ if (s_UICLog2 == NULL) {
+ HRESULT theResult =
+ ::CoCreateInstance(__uuidof(UICLog), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUICLog2),
+ reinterpret_cast<void **>(&s_UICLog2));
+ if (!s_UICLog2 || S_OK != theResult) {
+ ::OutputDebugString(L"FAILED to create UICLog2 interface.\n");
+ }
+ }
+ }
+
+ catch (...) {
+ }
+}
+
+void CLogHelper::Stop()
+{
+ try {
+ if (s_UICLog2) {
+ s_UICLog2->Terminate();
+ s_UICLog2->Release();
+ s_UICLog2 = NULL;
+ }
+
+ ::CoUninitialize();
+ }
+
+ catch (...) {
+ }
+}
+
+#else
+
+void CLogHelper::Log(long inLogType, const wchar_t *inFileName, long inLineNumber,
+ long inCategoryType, const wchar_t *inLogString, ...)
+{
+
+}
+
+void CLogHelper::Log(long inLogType, const wchar_t *inFileName, long inLineNumber,
+ long inCategoryType, long inStringId, ...)
+{
+
+}
+
+void CLogHelper::Trace(long inCategoryType, const wchar_t *inLogString, ...)
+{
+
+}
+
+void CLogHelper::AddEntry(long inType, const wchar_t *inMsg)
+{
+
+}
+
+void CLogHelper::Start()
+{
+}
+
+void CLogHelper::Stop()
+{
+}
+
+#endif // WIN32
diff --git a/src/Authoring/Client/Code/Shared/Log/LogHelper.h b/src/Authoring/Client/Code/Shared/Log/LogHelper.h
new file mode 100644
index 00000000..f96f130d
--- /dev/null
+++ b/src/Authoring/Client/Code/Shared/Log/LogHelper.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __UICLOGHELPER_H_
+#define __UICLOGHELPER_H_
+
+#ifdef WIN32
+#include "LogProject.h"
+#else
+typedef long IUICLog2;
+#endif
+
+//==============================================================================
+/**
+ * @class CLogHelper
+ * @brief This class provides helper functions to assist with logging.
+ */
+//==============================================================================
+class CLogHelper
+{
+public:
+ static void Log(long inLogType, const wchar_t *inFileName, long inLineNumber,
+ long inCategoryType, const wchar_t *inLogString, ...);
+ static void Log(long inLogType, const wchar_t *inFileName, long inLineNumber,
+ long inCategoryType, long inStringId, ...);
+ static void Trace(long inCategoryType, const wchar_t *inLogString, ...);
+ static void AddEntry(long inType, const wchar_t *inMsg);
+ static void Start();
+ static void Stop();
+
+ static IUICLog2 *s_UICLog2;
+};
+
+#endif // __UICLOGHELPER_H_
diff --git a/src/Authoring/Client/Code/Shared/Log/LogProject.h b/src/Authoring/Client/Code/Shared/Log/LogProject.h
new file mode 100644
index 00000000..b41ea796
--- /dev/null
+++ b/src/Authoring/Client/Code/Shared/Log/LogProject.h
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma warning(disable : 4049) /* more than 64k source lines */
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+/* File created by MIDL compiler version 5.03.0280 */
+/* at Thu Nov 01 17:29:05 2001
+ */
+//@@MIDL_FILE_HEADING( )
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 440
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif // __RPCNDR_H_VERSION__
+
+#ifndef COM_NO_WINDOWS_H
+#include <winsock2.h>
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __LogProject_h__
+#define __LogProject_h__
+
+/* Forward Declarations */
+
+#ifndef __IUICLog_FWD_DEFINED__
+#define __IUICLog_FWD_DEFINED__
+typedef interface IUICLog IUICLog;
+#endif /* __IUICLog_FWD_DEFINED__ */
+
+#ifndef __IUICLog2_FWD_DEFINED__
+#define __IUICLog2_FWD_DEFINED__
+typedef interface IUICLog2 IUICLog2;
+#endif /* __IUICLog2_FWD_DEFINED__ */
+
+#ifndef __UICLog_FWD_DEFINED__
+#define __UICLog_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class UICLog UICLog;
+#else
+typedef struct UICLog UICLog;
+#endif /* __cplusplus */
+
+#endif /* __UICLog_FWD_DEFINED__ */
+
+#ifndef __UICLog2_FWD_DEFINED__
+#define __UICLog2_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class UICLog2 UICLog2;
+#else
+typedef struct UICLog2 UICLog2;
+#endif /* __cplusplus */
+
+#endif /* __UICLog2_FWD_DEFINED__ */
+
+/* header files for imported files */
+#include "oaidl.h"
+#include "ocidl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __RPC_FAR *__RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free(void __RPC_FAR *);
+
+#ifndef __IUICLog_INTERFACE_DEFINED__
+#define __IUICLog_INTERFACE_DEFINED__
+
+/* interface IUICLog */
+/* [unique][helpstring][dual][uuid][object] */
+
+EXTERN_C const IID IID_IUICLog;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+MIDL_INTERFACE("B6F844EB-07AF-4CF1-9350-E4A2A6576E0E")
+IUICLog : public IDispatch
+{
+public:
+ virtual /* [id] */ HRESULT STDMETHODCALLTYPE AddEntry(
+ /* [in] */ DWORD inLogType,
+ /* [in] */ BYTE __RPC_FAR * inLogEntry) = 0;
+
+ virtual /* [id] */ HRESULT STDMETHODCALLTYPE ReloadPreferences(void) = 0;
+
+ virtual /* [id] */ HRESULT STDMETHODCALLTYPE Terminate(void) = 0;
+};
+
+#else /* C style interface */
+
+typedef struct IUICLogVtbl
+{
+ BEGIN_INTERFACE
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *QueryInterface)
+ (IUICLog __RPC_FAR *This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG(STDMETHODCALLTYPE __RPC_FAR *AddRef)(IUICLog __RPC_FAR *This);
+
+ ULONG(STDMETHODCALLTYPE __RPC_FAR *Release)(IUICLog __RPC_FAR *This);
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount)
+ (IUICLog __RPC_FAR *This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo)
+ (IUICLog __RPC_FAR *This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames)
+ (IUICLog __RPC_FAR *This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
+
+ /* [local] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *Invoke)(
+ IUICLog __RPC_FAR *This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
+ /* [out] */ VARIANT __RPC_FAR *pVarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *AddEntry)(
+ IUICLog __RPC_FAR *This,
+ /* [in] */ DWORD inLogType,
+ /* [in] */ BYTE __RPC_FAR *inLogEntry);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *ReloadPreferences)(IUICLog __RPC_FAR *This);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *Terminate)(IUICLog __RPC_FAR *This);
+
+ END_INTERFACE
+} IUICLogVtbl;
+
+interface IUICLog
+{
+ CONST_VTBL struct IUICLogVtbl __RPC_FAR *lpVtbl;
+};
+
+#ifdef COBJMACROS
+
+#define IUICLog_QueryInterface(This, riid, ppvObject) \
+ (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
+
+#define IUICLog_AddRef(This) (This)->lpVtbl->AddRef(This)
+
+#define IUICLog_Release(This) (This)->lpVtbl->Release(This)
+
+#define IUICLog_GetTypeInfoCount(This, pctinfo) (This)->lpVtbl->GetTypeInfoCount(This, pctinfo)
+
+#define IUICLog_GetTypeInfo(This, iTInfo, lcid, ppTInfo) \
+ (This)->lpVtbl->GetTypeInfo(This, iTInfo, lcid, ppTInfo)
+
+#define IUICLog_GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId) \
+ (This)->lpVtbl->GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)
+
+#define IUICLog_Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, \
+ pExcepInfo, puArgErr) \
+ (This)->lpVtbl->Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, \
+ pExcepInfo, puArgErr)
+
+#define IUICLog_AddEntry(This, inLogType, inLogEntry) \
+ (This)->lpVtbl->AddEntry(This, inLogType, inLogEntry)
+
+#define IUICLog_ReloadPreferences(This) (This)->lpVtbl->ReloadPreferences(This)
+
+#define IUICLog_Terminate(This) (This)->lpVtbl->Terminate(This)
+
+#endif /* COBJMACROS */
+
+#endif /* C style interface */
+
+/* [id] */ HRESULT STDMETHODCALLTYPE IUICLog_AddEntry_Proxy(IUICLog __RPC_FAR *This,
+ /* [in] */ DWORD inLogType,
+ /* [in] */ BYTE __RPC_FAR *inLogEntry);
+
+void __RPC_STUB IUICLog_AddEntry_Stub(IRpcStubBuffer *This, IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage, DWORD *_pdwStubPhase);
+
+/* [id] */ HRESULT STDMETHODCALLTYPE IUICLog_ReloadPreferences_Proxy(IUICLog __RPC_FAR *This);
+
+void __RPC_STUB IUICLog_ReloadPreferences_Stub(IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage, DWORD *_pdwStubPhase);
+
+/* [id] */ HRESULT STDMETHODCALLTYPE IUICLog_Terminate_Proxy(IUICLog __RPC_FAR *This);
+
+void __RPC_STUB IUICLog_Terminate_Stub(IRpcStubBuffer *This, IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage, DWORD *_pdwStubPhase);
+
+#endif /* __IUICLog_INTERFACE_DEFINED__ */
+
+#ifndef __IUICLog2_INTERFACE_DEFINED__
+#define __IUICLog2_INTERFACE_DEFINED__
+
+/* interface IUICLog2 */
+/* [unique][helpstring][dual][uuid][object] */
+
+EXTERN_C const IID IID_IUICLog2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+MIDL_INTERFACE("18725949-89C4-460c-A092-75520BFFB542")
+IUICLog2 : public IUICLog
+{
+public:
+ virtual /* [id] */ HRESULT STDMETHODCALLTYPE AddEntryIndirect(
+ /* [in] */ LONG inStructPtr) = 0;
+};
+
+#else /* C style interface */
+
+typedef struct IUICLog2Vtbl
+{
+ BEGIN_INTERFACE
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *QueryInterface)
+ (IUICLog2 __RPC_FAR *This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG(STDMETHODCALLTYPE __RPC_FAR *AddRef)(IUICLog2 __RPC_FAR *This);
+
+ ULONG(STDMETHODCALLTYPE __RPC_FAR *Release)(IUICLog2 __RPC_FAR *This);
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount)
+ (IUICLog2 __RPC_FAR *This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo)
+ (IUICLog2 __RPC_FAR *This,
+ /* [in] */ UINT iTInfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
+
+ HRESULT(STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames)
+ (IUICLog2 __RPC_FAR *This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
+
+ /* [local] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *Invoke)(
+ IUICLog2 __RPC_FAR *This,
+ /* [in] */ DISPID dispIdMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
+ /* [out] */ VARIANT __RPC_FAR *pVarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *AddEntry)(
+ IUICLog2 __RPC_FAR *This,
+ /* [in] */ DWORD inLogType,
+ /* [in] */ BYTE __RPC_FAR *inLogEntry);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *ReloadPreferences)(IUICLog2 __RPC_FAR *This);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *Terminate)(IUICLog2 __RPC_FAR *This);
+
+ /* [id] */ HRESULT(STDMETHODCALLTYPE __RPC_FAR *AddEntryIndirect)(IUICLog2 __RPC_FAR *This,
+ /* [in] */ LONG inStructPtr);
+
+ END_INTERFACE
+} IUICLog2Vtbl;
+
+interface IUICLog2
+{
+ CONST_VTBL struct IUICLog2Vtbl __RPC_FAR *lpVtbl;
+};
+
+#ifdef COBJMACROS
+
+#define IUICLog2_QueryInterface(This, riid, ppvObject) \
+ (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
+
+#define IUICLog2_AddRef(This) (This)->lpVtbl->AddRef(This)
+
+#define IUICLog2_Release(This) (This)->lpVtbl->Release(This)
+
+#define IUICLog2_GetTypeInfoCount(This, pctinfo) (This)->lpVtbl->GetTypeInfoCount(This, pctinfo)
+
+#define IUICLog2_GetTypeInfo(This, iTInfo, lcid, ppTInfo) \
+ (This)->lpVtbl->GetTypeInfo(This, iTInfo, lcid, ppTInfo)
+
+#define IUICLog2_GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId) \
+ (This)->lpVtbl->GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)
+
+#define IUICLog2_Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, \
+ pExcepInfo, puArgErr) \
+ (This)->lpVtbl->Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, \
+ pExcepInfo, puArgErr)
+
+#define IUICLog2_AddEntry(This, inLogType, inLogEntry) \
+ (This)->lpVtbl->AddEntry(This, inLogType, inLogEntry)
+
+#define IUICLog2_ReloadPreferences(This) (This)->lpVtbl->ReloadPreferences(This)
+
+#define IUICLog2_Terminate(This) (This)->lpVtbl->Terminate(This)
+
+#define IUICLog2_AddEntryIndirect(This, inStructPtr) \
+ (This)->lpVtbl->AddEntryIndirect(This, inStructPtr)
+
+#endif /* COBJMACROS */
+
+#endif /* C style interface */
+
+/* [id] */ HRESULT STDMETHODCALLTYPE IUICLog2_AddEntryIndirect_Proxy(IUICLog2 __RPC_FAR *This,
+ /* [in] */ LONG inStructPtr);
+
+void __RPC_STUB IUICLog2_AddEntryIndirect_Stub(IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage, DWORD *_pdwStubPhase);
+
+#endif /* __IUICLog2_INTERFACE_DEFINED__ */
+
+#ifndef __LOGPROJECTLib_LIBRARY_DEFINED__
+#define __LOGPROJECTLib_LIBRARY_DEFINED__
+
+/* library LOGPROJECTLib */
+/* [helpstring][version][uuid] */
+
+EXTERN_C const IID LIBID_LOGPROJECTLib;
+
+EXTERN_C const CLSID CLSID_UICLog;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("DE411D6F-2BDA-444C-AC87-9171BAFD9E99") UICLog;
+#endif
+
+EXTERN_C const CLSID CLSID_UICLog2;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("4691F58A-9856-43c6-9269-7A8987AFC715") UICLog2;
+#endif
+#endif /* __LOGPROJECTLib_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Authoring/Client/Code/Shared/Log/LogTypes.h b/src/Authoring/Client/Code/Shared/Log/LogTypes.h
new file mode 100644
index 00000000..fca0a7e0
--- /dev/null
+++ b/src/Authoring/Client/Code/Shared/Log/LogTypes.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __UICLOGTYPES_H_
+#define __UICLOGTYPES_H_
+
+#ifndef MAX_PATH
+#define MAX_PATH 1024
+#endif
+
+#include <QtGlobal>
+
+//==============================================================================
+/**
+ * @typedef TSAddEntryIndirect
+ */
+//==============================================================================
+typedef struct _TSAddEntryIndirect
+{
+ long m_StructSize; ///< The size of this struct ( for versioning )
+ long m_LogStringId; ///< The ID of the log string in the resource DLL
+ wchar_t m_LogString[MAX_PATH]; ///< The log string (for quick debugging)
+ va_list m_LogParamList; ///< Variable parameter list
+ long m_LogType; ///< The log type (log/exception)
+ long m_CategoryType; ///< The category (component, render, etc)
+ wchar_t m_FileNameString[MAX_PATH]; ///< The file name
+ long m_LineNumberLong; ///< The line number
+ quint32 m_Mask; ///< The mask that identifies valid members of this struct
+ quint32 m_Level; ///< The mask that identifies valid members of this struct
+
+} TSAddEntryIndirect;
+
+//==============================================================================
+// TSAddEntryIndirect mask ids
+//==============================================================================
+
+const unsigned long UICLOG_STRING = 0x00000001; ///<
+const unsigned long UICLOG_ID = 0x00000002; ///<
+
+//==============================================================================
+// Log Modes
+//==============================================================================
+
+enum ELogMode ///< Logging mode determined by registry lookup
+{ LOGMODE_NONE = 0x00000000, ///< Log nothing
+ LOGMODE_LOG = 0x00000001, ///< Log logs
+ LOGMODE_EXCEPTION = 0x00000002, ///< Log exceptions
+ LOGMODE_ALL = LOGMODE_LOG | LOGMODE_EXCEPTION ///< Log everthing
+};
+
+//==============================================================================
+// Log Levels
+//==============================================================================
+
+enum ELogLevel {
+ LOGLEVEL_UNKNOWN = 0,
+ LOGLEVEL_CRITICAL = 1,
+ LOGLEVEL_WARNING = 2,
+ LOGLEVEL_INFO = 3,
+};
+
+#endif // __UICLOGTYPES_H_
diff --git a/src/Authoring/Client/Code/Shared/Log/UICLog.h b/src/Authoring/Client/Code/Shared/Log/UICLog.h
new file mode 100644
index 00000000..c0a2dc6d
--- /dev/null
+++ b/src/Authoring/Client/Code/Shared/Log/UICLog.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef _UICLOG_H__
+#define _UICLOG_H__
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "UICExceptions.h" // for UIC_THIS_FILE
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+#ifdef UIC_NO_LOGGING
+
+#define UIC_LOGRAW(inType, inMsg)
+#define UIC_LOGMSG(inMsg)
+#define UIC_LOGSTART
+#define UIC_LOGSTOP
+#define UIC_LOGGLOBAL
+#define UIC_LOGEXTERN
+#define UIC_LOG(inTypeId, inMessage)
+#define UIC_LOG1(inTypeId, inMessage, inParam1)
+#define UIC_LOG2(inTypeId, inMessage, inParam1, inParam2)
+#define UIC_LOGNOTYPE(inMessage)
+#define UIC_TRACE
+
+#else // #ifdef UIC_NO_LOGGING
+
+#include "LogTypes.h"
+#include "LogHelper.h"
+
+//==============================================================================
+// Macros
+//==============================================================================
+
+// NOTE: Use UIC_LOG, UIC_LOG1 and UIC_LOG2 as defined in UICExceptions.h instead of these.
+
+// Simple log entry with type
+#define UIC_LOGRAW(inType, inMsg) CLogHelper::AddEntry(inType, inMsg);
+
+// Simple log entry
+#define UIC_LOGMSG(inMsg) UIC_LOGRAW(LOGMODE_LOG, inMsg)
+
+// Create or link to singleton logger. Include this once in the startup code for each module
+#define UIC_LOGSTART CLogHelper::Start();
+
+// Release COM singleton. Include this once in the startup code for each module
+#define UIC_LOGSTOP CLogHelper::Stop();
+
+// Publish global log variable. Include this once OUTSIDE of a method to define the global
+// variable.
+#define UIC_LOGGLOBAL
+
+/*
+#define UIC_LOGGLOBAL \
+ IUICLog2* CLogHelper::s_UICLog2 = NULL; \
+ long CLogHelper::s_UICLogCount = 0;
+*/
+
+// Publish global log variable. Add this to every file, preferably in stdafx.h
+#define UIC_LOGEXTERN
+
+// A log entry with no extra parameters
+#define UIC_LOG(inTypeId, inMessage) \
+ CLogHelper::Log(LOGMODE_LOG, UIC_THIS_FILE, __LINE__, inTypeId, L#inMessage);
+
+// A log entry with one extra parameter
+#define UIC_LOG1(inTypeId, inMessage, inParam1) \
+ CLogHelper::Log(LOGMODE_LOG, UIC_THIS_FILE, __LINE__, inTypeId, L#inMessage, inParam1);
+
+// A log entry with two extra parameters
+#define UIC_LOG2(inTypeId, inMessage, inParam1, inParam2) \
+ CLogHelper::Log(LOGMODE_LOG, UIC_THIS_FILE, __LINE__, inTypeId, L#inMessage, inParam1, \
+ inParam2);
+
+// A log entry with no extra parameters
+#define UIC_LOGNOTYPE(inMessage) \
+ CLogHelper::Log(LOGMODE_LOG, UIC_THIS_FILE, __LINE__, 0, L#inMessage);
+
+#define UIC_TRACE CLogHelper::Trace
+
+#endif // #ifndef UIC_NO_LOGGING
+#endif // #ifndef _UICLOG_H__
diff --git a/src/Authoring/Common/Code/AutoPtr.h b/src/Authoring/Common/Code/AutoPtr.h
new file mode 100644
index 00000000..50060671
--- /dev/null
+++ b/src/Authoring/Common/Code/AutoPtr.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef AMXSMARTPTRH
+#define AMXSMARTPTRH
+#include <memory>
+#include "UICExceptions.h"
+#include "PlatformMacros.h"
+#ifdef WIN32
+#pragma warning(disable : 4284)
+#endif
+
+namespace Q3DStudio {
+//==========================================================================
+/**
+ * @class CAutoPtr
+ * Class to arrange aquisition, release, and destruction of different pointer types.
+ */
+template <class handler, class T>
+class CAutoPtr
+{
+public:
+ //=======================================================================
+ /**
+ * CTOR-Sets pointer value to null.
+ */
+ CAutoPtr()
+ : m_T(NULL)
+ {
+ }
+ //=======================================================================
+ /**
+ * Sets pointer value to the value passed in.
+ * @param inT the value to set the pointer to.
+ */
+ CAutoPtr(T *inT)
+ : m_T(handler::Acquire(inT))
+ {
+ }
+ //=======================================================================
+ /**
+ * Passes pointer from source object to this object.
+ */
+ CAutoPtr(const CAutoPtr<handler, T> &inSource) { m_T = handler::Acquire(inSource.Release()); }
+ //=======================================================================
+ /**
+ * calls handler::Destroy the m_t member variable.
+ */
+ ~CAutoPtr()
+ {
+ if (m_T) {
+ handler::Destroy(m_T);
+ m_T = NULL;
+ }
+ }
+ //=======================================================================
+ /**
+ * This objects 1. Destroys old pointer 2. Acquire's new value.
+ * This object takes ownership of the inT parameter.
+ *
+ * @param inT The pointer to set the value to.
+ * @return The returned value.
+ */
+ T *operator=(T *inT)
+ {
+ if (m_T == inT) {
+ return m_T;
+ }
+ if (m_T != NULL) {
+ handler::Destroy(m_T);
+ m_T = NULL;
+ }
+ m_T = handler::Acquire(inT);
+ return m_T;
+ }
+ //=======================================================================
+ /**
+ * Passes ownership from the passed in class to this class.
+ */
+ CAutoPtr<handler, T> &operator=(const CAutoPtr<handler, T> &other)
+ {
+ if (&other != this) {
+ m_T = handler::Acquire(other.Release());
+ }
+
+ return *this;
+ }
+ //=======================================================================
+ /**
+ * Returns pointer-to-T.
+ */
+ operator T *() const { return m_T; }
+ //=======================================================================
+ /**
+ * Throws if m_t is null, because you are essentially guaranteeing
+ * a dereference if a null parameter.
+ * @return reference-T.
+ */
+ T &operator*() const
+ {
+ UIC_THROWNULL(m_T, -1);
+ return *m_T;
+ }
+ //=======================================================================
+ /**
+ * Returns pointer-to-T, throws if T is null.
+ */
+ T *operator->() const
+ {
+ UIC_THROWNULL(m_T, -1);
+ return m_T;
+ }
+ //=======================================================================
+ /**
+ * @return Address of T, throws if m_t isn't null.
+ *
+ T** operator&() const
+ {
+ //This usually indicates an error
+ //UIC_THROWFALSE( m_T == NULL, AUTO_PTR_ERROR );
+ return &m_T;
+ }
+ CAutoPtr< handler, T >* operator&()
+ {
+ return this;
+ }*/
+
+ //=======================================================================
+ /**
+ * Releases the object from this objects control. This is akin to telling
+ * the auto pointer that it is no longer responsible for the pointer.
+ * @return The value of m_T;
+ */
+ T *Release() const
+ {
+ T *theTemp = m_T;
+ handler::Release(m_T);
+ m_T = NULL;
+ return theTemp;
+ }
+
+ //=======================================================================
+ /**
+ * @return true of other == m_T.
+ */
+ bool operator==(T *other) const
+ {
+ if (m_T == other) {
+ return true;
+ }
+ return false;
+ }
+
+ //=======================================================================
+ /**
+ * @return true if other != m_T.
+ */
+ bool operator!=(T *other) const
+ {
+ if (m_T == other) {
+ return false;
+ }
+ return true;
+ }
+ mutable T *m_T; ///< Pointer to class
+};
+//==========================================================================
+/**
+ * @class CDeleteHandler
+ * Handles the aquisition, release and destruction of classes that need to
+ * to be 'delete'd.
+ */
+template <class T>
+class CDeleteHandler
+{
+public:
+ //=======================================================================
+ /**
+ * Does aquisition action on pointer (in this case, nothing).
+ */
+ static inline T *Acquire(T *inT) { return inT; }
+ //=======================================================================
+ /**
+ * Does release action on pointer (in this case, nothing).
+ */
+ static inline T *Release(T *inT) { return inT; }
+ //=======================================================================
+ /**
+ * Does destruction action on pointer (in this case, delete's the pointer).
+ */
+ static inline void Destroy(T *inT) { delete inT; }
+};
+
+//==========================================================================
+/**
+ * @class CArrayDeleteHandler
+ * Handles the aquisition, release and destruction of classes that need to
+ * to be 'delete[]'d.
+ */
+template <class T>
+class CArrayDeleteHandler
+{
+public:
+ //=======================================================================
+ /**
+ * Does aquisition action on pointer (in this case, nothing).
+ */
+ static inline T *Acquire(T *inT) { return inT; }
+ //=======================================================================
+ /**
+ * Does release action on pointer (in this case, nothing).
+ */
+ static inline T *Release(T *inT) { return inT; }
+ //=======================================================================
+ /**
+ * Does destruction action on pointer (in this case, delete[]'s the pointer).
+ */
+ static inline void Destroy(T *inT) { delete[] inT; }
+};
+
+template <class T>
+class CAutoMemPtr : public CAutoPtr<CDeleteHandler<T>, T>
+{
+public:
+ CAutoMemPtr()
+ : CAutoPtr<CDeleteHandler<T>, T>()
+ {
+ }
+ CAutoMemPtr(T *inT)
+ : CAutoPtr<CDeleteHandler<T>, T>(inT)
+ {
+ }
+ CAutoMemPtr(const CAutoMemPtr<T> &inSource)
+ : CAutoPtr<CDeleteHandler<T>, T>(inSource)
+ {
+ }
+ T *operator=(T *inT) { return CAutoPtr<CDeleteHandler<T>, T>::operator=(inT); }
+ T *Release() const { return CAutoPtr<CDeleteHandler<T>, T>::Release(); }
+};
+
+template <class T>
+class CAutoArrayPtr : public CAutoPtr<CArrayDeleteHandler<T>, T>
+{
+public:
+ CAutoArrayPtr()
+ : CAutoPtr<CArrayDeleteHandler<T>, T>()
+ {
+ }
+ CAutoArrayPtr(T *inT)
+ : CAutoPtr<CArrayDeleteHandler<T>, T>(inT)
+ {
+ }
+ CAutoArrayPtr(const CAutoArrayPtr<T> &inSource)
+ : CAutoPtr<CArrayDeleteHandler<T>, T>(inSource)
+ {
+ }
+ T *operator=(T *inT) { return CAutoPtr<CArrayDeleteHandler<T>, T>::operator=(inT); }
+ T *Release() const { return CAutoPtr<CArrayDeleteHandler<T>, T>::Release(); }
+};
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/EulerAngles/EulerAngles.cpp b/src/Authoring/Common/Code/EulerAngles/EulerAngles.cpp
new file mode 100644
index 00000000..b9a01b10
--- /dev/null
+++ b/src/Authoring/Common/Code/EulerAngles/EulerAngles.cpp
@@ -0,0 +1,880 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include "EulerAngles.h"
+
+namespace EulerAngleConverter {
+
+//==============================================================================
+// Ctor and Dtor
+//==============================================================================
+//==============================================================================
+/**
+* Ctor
+*/
+CEulerAngleConverter::CEulerAngleConverter()
+{
+ m_OrderInfoBuffer[0] = '\0';
+}
+
+//==============================================================================
+/**
+* Dtor
+*/
+CEulerAngleConverter::~CEulerAngleConverter()
+{
+}
+
+//==============================================================================
+// Interfaces
+//==============================================================================
+//==============================================================================
+/**
+* Constructs a Euler angle & holds it in a EulerAngles struct
+*
+* @param ai, aj, ah = x rot, y rot, z rot ( radians )
+* @param order = the order this angle is in namely XYZ( static ), etc.
+* use the EulOrd**** macros to generate values
+* 0 to 23 is valid
+*/
+EulerAngles CEulerAngleConverter::Eul_(float ai, float aj, float ah, int order)
+{
+ EulerAngles ea;
+ ea.x = ai;
+ ea.y = aj;
+ ea.z = ah;
+ ea.w = (float)order;
+ return (ea);
+}
+
+//==============================================================================
+/**
+* Construct quaternion from Euler angles (in radians).
+*
+* @param ea = incoming angle( radians )
+*/
+Quat CEulerAngleConverter::Eul_ToQuat(EulerAngles ea)
+{
+ Quat qu;
+ double a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+ EulGetOrd((unsigned int)ea.w, i, j, k, h, n, s, f);
+ if (f == EulFrmR) {
+ float t = ea.x;
+ ea.x = ea.z;
+ ea.z = t;
+ }
+ if (n == EulParOdd)
+ ea.y = -ea.y;
+ ti = ea.x * 0.5;
+ tj = ea.y * 0.5;
+ th = ea.z * 0.5;
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+ if (s == EulRepYes) {
+ a[i] = cj * (cs + sc); /* Could speed up with */
+ a[j] = sj * (cc + ss); /* trig identities. */
+ a[k] = sj * (cs - sc);
+ qu.w = (float)(cj * (cc - ss));
+ } else {
+ a[i] = cj * sc - sj * cs;
+ a[j] = cj * ss + sj * cc;
+ a[k] = cj * cs - sj * sc;
+ qu.w = (float)(cj * cc + sj * ss);
+ }
+ if (n == EulParOdd)
+ a[j] = -a[j];
+ qu.x = (float)a[X];
+ qu.y = (float)a[Y];
+ qu.z = (float)a[Z];
+ return (qu);
+}
+
+//==============================================================================
+/**
+* Construct matrix from Euler angles (in radians).
+*
+* @param ea = incoming angle
+* @param M = outgoing matrix
+*/
+void CEulerAngleConverter::Eul_ToHMatrix(EulerAngles ea, HMatrix M)
+{
+ double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+ EulGetOrd((unsigned int)ea.w, i, j, k, h, n, s, f);
+ if (f == EulFrmR) {
+ float t = ea.x;
+ ea.x = ea.z;
+ ea.z = t;
+ }
+ if (n == EulParOdd) {
+ ea.x = -ea.x;
+ ea.y = -ea.y;
+ ea.z = -ea.z;
+ }
+ ti = ea.x;
+ tj = ea.y;
+ th = ea.z;
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+ if (s == EulRepYes) {
+ M[i][i] = (float)cj;
+ M[i][j] = (float)(sj * si);
+ M[i][k] = (float)(sj * ci);
+ M[j][i] = (float)(sj * sh);
+ M[j][j] = (float)(-cj * ss + cc);
+ M[j][k] = (float)(-cj * cs - sc);
+ M[k][i] = (float)(-sj * ch);
+ M[k][j] = (float)(cj * sc + cs);
+ M[k][k] = (float)(cj * cc - ss);
+ } else {
+ M[i][i] = (float)(cj * ch);
+ M[i][j] = (float)(sj * sc - cs);
+ M[i][k] = (float)(sj * cc + ss);
+ M[j][i] = (float)(cj * sh);
+ M[j][j] = (float)(sj * ss + cc);
+ M[j][k] = (float)(sj * cs - sc);
+ M[k][i] = (float)(-sj);
+ M[k][j] = (float)(cj * si);
+ M[k][k] = (float)(cj * ci);
+ }
+ M[W][X] = M[W][Y] = M[W][Z] = M[X][W] = M[Y][W] = M[Z][W] = 0.0;
+ M[W][W] = 1.0;
+}
+
+//==============================================================================
+/**
+* Convert matrix to Euler angles (in radians).
+*
+* @param M = incoming matrix
+* @param order = 0-23, use EulOrd**** to generate this value
+* @return a set of angles in radians!!!!
+*/
+EulerAngles CEulerAngleConverter::Eul_FromHMatrix(HMatrix M, int order)
+{
+ EulerAngles ea;
+ int i, j, k, h, n, s, f;
+ EulGetOrd(order, i, j, k, h, n, s, f);
+ if (s == EulRepYes) {
+ double sy = sqrt(M[i][j] * M[i][j] + M[i][k] * M[i][k]);
+ if (sy > 16 * FLT_EPSILON) {
+ ea.x = (float)(atan2((double)M[i][j], (double)M[i][k]));
+ ea.y = (float)(atan2((double)sy, (double)M[i][i]));
+ ea.z = (float)(atan2((double)M[j][i], -(double)M[k][i]));
+ } else {
+ ea.x = (float)(atan2(-(double)M[j][k], (double)M[j][j]));
+ ea.y = (float)(atan2((double)sy, (double)M[i][i]));
+ ea.z = 0;
+ }
+ } else {
+ double cy = sqrt(M[i][i] * M[i][i] + M[j][i] * M[j][i]);
+ if (cy > 16 * FLT_EPSILON) {
+ ea.x = (float)(atan2((double)M[k][j], (double)M[k][k]));
+ ea.y = (float)(atan2(-(double)M[k][i], (double)cy));
+ ea.z = (float)(atan2((double)M[j][i], (double)M[i][i]));
+ } else {
+ ea.x = (float)(atan2(-(double)M[j][k], (double)M[j][j]));
+ ea.y = (float)(atan2(-(double)M[k][i], (double)cy));
+ ea.z = 0;
+ }
+ }
+ if (n == EulParOdd) {
+ ea.x = -ea.x;
+ ea.y = -ea.y;
+ ea.z = -ea.z;
+ }
+ if (f == EulFrmR) {
+ float t = ea.x;
+ ea.x = ea.z;
+ ea.z = t;
+ }
+ ea.w = (float)order;
+ return (ea);
+}
+
+//==============================================================================
+/**
+* Convert quaternion to Euler angles (in radians).
+*
+* @param q = incoming quaternion
+* @param order = 0-23, use EulOrd**** to generate this value
+* @return the generated angles ( radians )
+*/
+EulerAngles CEulerAngleConverter::Eul_FromQuat(Quat q, int order)
+{
+ HMatrix M;
+ double Nq = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
+ double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
+ double xs = q.x * s, ys = q.y * s, zs = q.z * s;
+ double wx = q.w * xs, wy = q.w * ys, wz = q.w * zs;
+ double xx = q.x * xs, xy = q.x * ys, xz = q.x * zs;
+ double yy = q.y * ys, yz = q.y * zs, zz = q.z * zs;
+ M[X][X] = (float)(1.0 - (yy + zz));
+ M[X][Y] = (float)(xy - wz);
+ M[X][Z] = (float)(xz + wy);
+ M[Y][X] = (float)(xy + wz);
+ M[Y][Y] = (float)(1.0 - (xx + zz));
+ M[Y][Z] = (float)(yz - wx);
+ M[Z][X] = (float)(xz - wy);
+ M[Z][Y] = (float)(yz + wx);
+ M[Z][Z] = (float)(1.0 - (xx + yy));
+ M[W][X] = M[W][Y] = M[W][Z] = M[X][W] = M[Y][W] = M[Z][W] = 0.0;
+ M[W][W] = 1.0;
+ return (Eul_FromHMatrix(M, order));
+}
+
+//==============================================================================
+/**
+* Dump the Order information
+*
+* @param outStr = the holding string
+*/
+const char *CEulerAngleConverter::DumpOrderInfo()
+{
+ long theCount = 0;
+ long theOrder[24];
+ char theOrderStr[24][16];
+
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZr");
+
+ theCount = 0;
+ theOrder[theCount++] = EulOrdXYZs;
+ theOrder[theCount++] = EulOrdXYXs;
+ theOrder[theCount++] = EulOrdXZYs;
+ theOrder[theCount++] = EulOrdXZXs;
+ theOrder[theCount++] = EulOrdYZXs;
+ theOrder[theCount++] = EulOrdYZYs;
+ theOrder[theCount++] = EulOrdYXZs;
+ theOrder[theCount++] = EulOrdYXYs;
+ theOrder[theCount++] = EulOrdZXYs;
+ theOrder[theCount++] = EulOrdZXZs;
+ theOrder[theCount++] = EulOrdZYXs;
+ theOrder[theCount++] = EulOrdZYZs;
+
+ theOrder[theCount++] = EulOrdZYXr;
+ theOrder[theCount++] = EulOrdXYXr;
+ theOrder[theCount++] = EulOrdYZXr;
+ theOrder[theCount++] = EulOrdXZXr;
+ theOrder[theCount++] = EulOrdXZYr;
+ theOrder[theCount++] = EulOrdYZYr;
+ theOrder[theCount++] = EulOrdZXYr;
+ theOrder[theCount++] = EulOrdYXYr;
+ theOrder[theCount++] = EulOrdYXZr;
+ theOrder[theCount++] = EulOrdZXZr;
+ theOrder[theCount++] = EulOrdXYZr;
+ theOrder[theCount++] = EulOrdZYZr;
+
+ char theSubBuf[256];
+ ::sprintf(m_OrderInfoBuffer, "");
+ for (long theIndex = 0; theIndex < 24; ++theIndex) {
+ ::sprintf(theSubBuf, " %16s - %ld\n ", theOrderStr[theIndex], theOrder[theIndex]);
+ ::strcat(m_OrderInfoBuffer, theSubBuf);
+ }
+
+ return m_OrderInfoBuffer;
+}
+
+//==============================================================================
+/**
+* Converts a quaternion to a 4x4 matrix
+* http://skal.planet-d.net/matrixfaq.html
+*
+* @param inQuat == the quaternion
+* @param outMatrix == the matrix generated
+*/
+void ConvertQuatToMatrix(double inQuat[4], double outMatrix[16])
+{
+ const long theQuatX = 0;
+ const long theQuatY = 1;
+ const long theQuatZ = 2;
+ const long theQuatW = 3;
+
+ const double theXX = inQuat[theQuatX] * inQuat[theQuatX];
+ const double theXY = inQuat[theQuatX] * inQuat[theQuatY];
+ const double theXZ = inQuat[theQuatX] * inQuat[theQuatZ];
+ const double theXW = inQuat[theQuatX] * inQuat[theQuatW];
+ const double theYY = inQuat[theQuatY] * inQuat[theQuatY];
+ const double theYZ = inQuat[theQuatY] * inQuat[theQuatZ];
+ const double theYW = inQuat[theQuatY] * inQuat[theQuatW];
+ const double theZZ = inQuat[theQuatZ] * inQuat[theQuatZ];
+ const double theZW = inQuat[theQuatZ] * inQuat[theQuatW];
+
+ outMatrix[0] = 1 - 2 * (theYY + theZZ);
+ outMatrix[1] = 2 * (theXY + theZW);
+ outMatrix[2] = 2 * (theXZ - theYW); // followed the "written" formula, not the c-peudo-code
+ outMatrix[4] = 2 * (theXY - theZW); // followed the "written" formula, not the c-peudo-code
+ outMatrix[5] = 1 - 2 * (theXX + theZZ);
+ outMatrix[6] = 2 * (theYZ + theXW); // followed the "written" formula, not the c-peudo-code
+ outMatrix[8] = 2 * (theXZ + theYW); // followed the "written" formula, not the c-peudo-code
+ outMatrix[9] = 2 * (theYZ - theXW); // followed the "written" formula, not the c-peudo-code
+ outMatrix[10] = 1 - 2 * (theXX + theYY);
+
+ outMatrix[3] = outMatrix[7] = outMatrix[11] = outMatrix[12] = outMatrix[13] = outMatrix[14] = 0;
+ outMatrix[15] = 1;
+
+ TransposeMatrix(outMatrix); // this is for LH multi, need this to b RH multi
+}
+
+//==============================================================================
+/**
+* Transpose the give matrix
+* @param ioMatrix == the matrix to transpose
+*/
+void TransposeMatrix(double ioMatrix[16])
+{
+ // ioMatrix = 0 1 2 3
+ // 4 5 6 7
+ // 8 9 10 11
+ // 12 13 14 15
+ //
+ // swapping 1 with 4, 2 wisth 8, 6 with 9, 3 with 12, 7 with 13, 11 with 14
+ const long thePairs[][2] = { { 1, 4 }, { 2, 8 }, { 6, 9 }, { 3, 12 },
+ { 7, 13 }, { 11, 14 }, { -1, -1 } };
+
+ double theTemp;
+ for (long theIndex = 0; thePairs[theIndex][0] != -1; ++theIndex) {
+ theTemp = ioMatrix[thePairs[theIndex][0]];
+ ioMatrix[thePairs[theIndex][0]] = ioMatrix[thePairs[theIndex][1]];
+ ioMatrix[thePairs[theIndex][1]] = theTemp;
+ }
+}
+
+//==============================================================================
+/**
+* retireve the rotation axis info from the code
+* @param inCode
+* @param inOrder
+* @return the rotation axis
+*/
+long GetRotationAxis(long inCode, long inOrder)
+{
+ // zero out the others...
+ long theFlag = 0xf << (inOrder * 4);
+ inCode &= theFlag;
+ return inCode >> (inOrder * 4);
+}
+
+//==============================================================================
+/**
+* set the rotation axis info into the code
+* @param inAxis
+* @param inOrder
+* @param outCode
+* @return outCode
+*/
+long SetRotationAxis(long inAxis, long inOrder, long &outCode)
+{
+ // zero out existing axis...
+ long theFlag = 0xf << (inOrder * 4);
+ outCode &= ~theFlag;
+ // and set new axis in its place
+ outCode |= inAxis << (inOrder * 4);
+ return outCode;
+}
+
+//==============================================================================
+/**
+* Convert matrix to studio friendly euler angle
+* @param inNegScls == if the -ve scaling is present in the axes
+* @param inMatrixDouble16 == the matrix to convert
+* @param outEulerDouble3 == the resultant euler angle
+* @param outMatrixDouble16 == the buffer holding the final rotation matrix
+* @return TRUE ? success : otherwise
+*/
+bool ConvertMatrixToStudioEuler(bool inNegScls[3], double *inMatrixDouble16, double *outEulerDouble3,
+double *outMatrixDouble16)
+{
+ double theMatrixDouble16[16];
+ for (long theIdx = 0; theIdx < 16; ++theIdx)
+ theMatrixDouble16[theIdx] = inMatrixDouble16[theIdx];
+
+ double *theAxis[3];
+ theAxis[0] = theMatrixDouble16;
+ theAxis[1] = theMatrixDouble16 + 4;
+ theAxis[2] = theMatrixDouble16 + 8;
+
+ for (long theAxisIdx = 0; theAxisIdx < 3; ++theAxisIdx)
+ for (long theAxisUnit = 0; theAxisUnit < 3; ++theAxisUnit) // scale the axis
+ theAxis[theAxisIdx][theAxisUnit] =
+ theAxis[theAxisIdx][theAxisUnit] * (inNegScls[theAxisUnit] ? -1 : 1);
+
+ bool theResult =
+ ConvertMatrixToStudioEuler(theMatrixDouble16, outEulerDouble3, outMatrixDouble16);
+
+ // This condition can be proven by drawing a truth table
+ if ((inNegScls[0] && !inNegScls[1] && !inNegScls[2])
+ || (!inNegScls[0] && inNegScls[1] && !inNegScls[2])
+ || (!inNegScls[0] && !inNegScls[1] && inNegScls[2])
+ || (inNegScls[0] && inNegScls[1] && inNegScls[2])) {
+ // Odd count, inv polarity
+ // This requiremnt is required based on empirical experiment...
+ // u can always construct a few models and try the transformation if
+ // u are skeptical of this wierd swizzle
+ outEulerDouble3[0] *= -1;
+ outEulerDouble3[2] *= -1;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+* Convert matrix to studio friendly euler angle
+* @param inMatrixDouble16 == the matrix to convert
+* @param outEulerDouble3 == the resultant euler angle
+* @param outMatrixDouble16 == the buffer holding the final rotation matrix
+* @return TRUE ? success : otherwise
+*/
+bool ConvertMatrixToStudioEuler(double *inMatrixDouble16, double *outEulerDouble3,
+ double *outMatrixDouble16)
+{
+ bool theResult = false;
+
+ double *theXAxis = outMatrixDouble16;
+ double *theYAxis = outMatrixDouble16 + 4;
+ double *theZAxis = outMatrixDouble16 + 8;
+ memcpy(outMatrixDouble16, inMatrixDouble16, sizeof(double) * 16);
+
+ // use zaxis to find angle to reset y-axis rotation
+ double theYAngle;
+ if (theZAxis[2] != 0) {
+ theYAngle = atan(theZAxis[0] / theZAxis[2]);
+ // atan only from -90 to 90...
+ if (theZAxis[2] < 0)
+ theYAngle -= M_PI;
+ // just to keep it -180 - 180, so it's easier to see
+ if (theYAngle < -M_PI)
+ theYAngle += 2 * M_PI;
+ } else {
+ // ccw is +ve
+ if (theZAxis[0] > 0)
+ theYAngle = M_PI * 0.5;
+ else
+ theYAngle = -M_PI * 0.5;
+ }
+ RotateAxes(0, theYAngle, 0, theXAxis, theYAxis, theZAxis);
+
+ // use zaxis again to find angle to reset x-axis rotation
+ double theXAngle;
+ if (theZAxis[2] != 0) {
+ theXAngle = atan(theZAxis[1] / theZAxis[2]);
+ // atan only from -90 to 90...
+ if (theZAxis[2] < 0)
+ theXAngle -= M_PI;
+ // just to keep it -180 - 180, so it's easier to see
+ if (theXAngle < -M_PI)
+ theXAngle += 2 * M_PI;
+ } else {
+ // ccw is +ve
+ if (theZAxis[1] > 0)
+ theXAngle = M_PI * 0.5;
+ else
+ theXAngle = -M_PI * 0.5;
+ }
+ RotateAxes(theXAngle, 0, 0, theXAxis, theYAxis, theZAxis);
+
+ // use xaxis to find angle to reset z-axis rotation
+ double theZAngle;
+ if (theXAxis[0] != 0) {
+ theZAngle = atan(theXAxis[1] / theXAxis[0]);
+ // atan only from -90 to 90...
+ if (theXAxis[0] < 0)
+ theZAngle -= M_PI;
+ // just to keep it -180 - 180, so it's easier to see
+ if (theZAngle < -M_PI)
+ theZAngle += 2 * M_PI;
+ } else {
+ // ccw is +ve
+ if (theXAxis[1] > 0)
+ theZAngle = M_PI * 0.5;
+ else
+ theZAngle = -M_PI * 0.5;
+ }
+ RotateAxes(0, 0, theZAngle, theXAxis, theYAxis, theZAxis);
+
+ outEulerDouble3[0] = theXAngle * EulerAngleConverter::TO_DEGREE_MULTIPLIER;
+ // Studio's y rotation is opposite
+ outEulerDouble3[1] = -theYAngle * EulerAngleConverter::TO_DEGREE_MULTIPLIER;
+ outEulerDouble3[2] = theZAngle * EulerAngleConverter::TO_DEGREE_MULTIPLIER;
+
+ theResult = true;
+ return theResult;
+}
+
+//==============================================================================
+/**
+* rotate inPoint abt X for inRadian
+* @param inRadian == the rad of angle to rotate
+* @param inPoint == the point to rotate
+* @param outPoint == the resultant point
+*/
+void RotateX(double inRadian, double *inPoint, double *outPoint)
+{
+ double theMatrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
+ theMatrix[4] = cos(inRadian);
+ theMatrix[5] = sin(inRadian);
+ theMatrix[7] = -sin(inRadian);
+ theMatrix[8] = cos(inRadian);
+
+ double x = inPoint[0];
+ double y = inPoint[1];
+ double z = inPoint[2];
+ outPoint[0] = x * theMatrix[0] + y * theMatrix[3] + z * theMatrix[6];
+ outPoint[1] = x * theMatrix[1] + y * theMatrix[4] + z * theMatrix[7];
+ outPoint[2] = x * theMatrix[2] + y * theMatrix[5] + z * theMatrix[8];
+}
+
+//==============================================================================
+/**
+* rotate inPoint abt Y for inRadian
+* @param inRadian == the rad of angle to rotate
+* @param inPoint == the point to rotate
+* @param outPoint == the resultant point
+*/
+void RotateY(double inRadian, double *inPoint, double *outPoint)
+{
+ double theMatrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
+ theMatrix[0] = cos(inRadian);
+ theMatrix[2] = sin(inRadian);
+ theMatrix[6] = -sin(inRadian);
+ theMatrix[8] = cos(inRadian);
+
+ double x = inPoint[0];
+ double y = inPoint[1];
+ double z = inPoint[2];
+ outPoint[0] = x * theMatrix[0] + y * theMatrix[3] + z * theMatrix[6];
+ outPoint[1] = x * theMatrix[1] + y * theMatrix[4] + z * theMatrix[7];
+ outPoint[2] = x * theMatrix[2] + y * theMatrix[5] + z * theMatrix[8];
+}
+
+//==============================================================================
+/**
+* rotate inPoint abt Z for inRadian
+* @param inRadian == the rad of angle to rotate
+* @param inPoint == the point to rotate
+* @param outPoint == the resultant point
+*/
+void RotateZ(double inRadian, double *inPoint, double *outPoint)
+{
+ double theMatrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
+ theMatrix[0] = cos(inRadian);
+ theMatrix[1] = -sin(inRadian);
+ theMatrix[3] = sin(inRadian);
+ theMatrix[4] = cos(inRadian);
+
+ double x = inPoint[0];
+ double y = inPoint[1];
+ double z = inPoint[2];
+ outPoint[0] = x * theMatrix[0] + y * theMatrix[3] + z * theMatrix[6];
+ outPoint[1] = x * theMatrix[1] + y * theMatrix[4] + z * theMatrix[7];
+ outPoint[2] = x * theMatrix[2] + y * theMatrix[5] + z * theMatrix[8];
+}
+
+//==============================================================================
+/**
+* rotate 3 "affine axis" vectors abt inXRadian in the global space X axis
+* inYRadian in the global space Y axis, inZRadian in the global space Z axis
+* @param inXRadian == the angle to rotate in the global x
+* @param inYRadian == the angle to rotate in the global y
+* @param inZRadian == the angle to rotate in the globla z
+* @param outXAxis == the affine X axis
+* @param outYAxis == the affine Y axis
+* @param outZAxis == the affine Z axis
+*/
+void RotateAxes(double inXRadian, double inYRadian, double inZRadian, double *outXAxis,
+ double *outYAxis, double *outZAxis)
+{
+ RotateX(inXRadian, outXAxis, outXAxis);
+ RotateX(inXRadian, outYAxis, outYAxis);
+ RotateX(inXRadian, outZAxis, outZAxis);
+ //
+ RotateY(inYRadian, outXAxis, outXAxis);
+ RotateY(inYRadian, outYAxis, outYAxis);
+ RotateY(inYRadian, outZAxis, outZAxis);
+ //
+ RotateZ(inZRadian, outXAxis, outXAxis);
+ RotateZ(inZRadian, outYAxis, outYAxis);
+ RotateZ(inZRadian, outZAxis, outZAxis);
+}
+
+//==============================================================================
+/**
+* Adds a static rotation on one axis.
+*
+* @param inRotOrder
+* @param inRotSeq
+* @param inRots
+* @param outXAxis
+* @param outYAxis
+* @param outZAxis
+*/
+void DoAxes(long inRotOrder, long inRotSeq, double *inRots, double *outXAxis, double *outYAxis,
+ double *outZAxis)
+{
+ long theAxis = EulerAngleConverter::GetRotationAxis(inRotOrder, inRotSeq);
+
+ if (theAxis == EulerAngleConverter::ROTATE_X) {
+ EulerAngleConverter::RotateAxes(inRots[0], 0, 0, outXAxis, outYAxis, outZAxis);
+ } else if (theAxis == EulerAngleConverter::ROTATE_Y) {
+ EulerAngleConverter::RotateAxes(0, -inRots[1], 0, outXAxis, outYAxis, outZAxis);
+ } else if (theAxis == EulerAngleConverter::ROTATE_Z) {
+ EulerAngleConverter::RotateAxes(0, 0, -inRots[2], outXAxis, outYAxis, outZAxis);
+ }
+}
+
+//==============================================================================
+/**
+* Builds a rotation matrix based on static euler rotation and rotation order.
+*
+* This is used by StaticEulerToStudioEuler.
+*
+* @param inStaticEuler the static euler rotation
+* @param inRotateOrder the order of rotation
+* @param outMatrix the resultant rotation matrix
+*/
+void BuildMatrix(double *inStaticEuler, long *inRotateOrder, double *outMatrix)
+{
+ long theRotOrder = 0;
+ SetRotationAxis(inRotateOrder[0], ROTATE_FIRST, theRotOrder);
+ SetRotationAxis(inRotateOrder[1], ROTATE_SECOND, theRotOrder);
+ SetRotationAxis(inRotateOrder[2], ROTATE_THIRD, theRotOrder);
+
+ // set to identity
+ for (long theIndex = 0; theIndex < 16; ++theIndex)
+ if (theIndex / 4 == theIndex % 4)
+ outMatrix[theIndex] = 1;
+ else
+ outMatrix[theIndex] = 0;
+
+ double *theXAxis = outMatrix;
+ double *theYAxis = outMatrix + 4;
+ double *theZAxis = outMatrix + 8;
+ DoAxes(theRotOrder, ROTATE_FIRST, inStaticEuler, theXAxis, theYAxis, theZAxis);
+ DoAxes(theRotOrder, ROTATE_SECOND, inStaticEuler, theXAxis, theYAxis, theZAxis);
+ DoAxes(theRotOrder, ROTATE_THIRD, inStaticEuler, theXAxis, theYAxis, theZAxis);
+}
+
+//==============================================================================
+/**
+* Matrix multiple two double arrays
+*
+* This is used by StaticEulerToStudioEuler.
+*
+* @param inM1 first matrix
+* @param inM2 second matrix
+* @param outM3 resultant matrix
+*/
+void MatrixMultiply(double inM1[4][4], double inM2[4][4], double outM3[4][4])
+{
+ outM3[0][0] = inM1[0][0] * inM2[0][0] + inM1[1][0] * inM2[0][1] + inM1[2][0] * inM2[0][2]
+ + inM1[3][0] * inM2[0][3];
+ outM3[0][1] = inM1[0][1] * inM2[0][0] + inM1[1][1] * inM2[0][1] + inM1[2][1] * inM2[0][2]
+ + inM1[3][1] * inM2[0][3];
+ outM3[0][2] = inM1[0][2] * inM2[0][0] + inM1[1][2] * inM2[0][1] + inM1[2][2] * inM2[0][2]
+ + inM1[3][2] * inM2[0][3];
+ outM3[0][3] = inM1[0][3] * inM2[0][0] + inM1[1][3] * inM2[0][1] + inM1[2][3] * inM2[0][2]
+ + inM1[3][3] * inM2[0][3];
+ outM3[1][0] = inM1[0][0] * inM2[1][0] + inM1[1][0] * inM2[1][1] + inM1[2][0] * inM2[1][2]
+ + inM1[3][0] * inM2[1][3];
+ outM3[1][1] = inM1[0][1] * inM2[1][0] + inM1[1][1] * inM2[1][1] + inM1[2][1] * inM2[1][2]
+ + inM1[3][1] * inM2[1][3];
+ outM3[1][2] = inM1[0][2] * inM2[1][0] + inM1[1][2] * inM2[1][1] + inM1[2][2] * inM2[1][2]
+ + inM1[3][2] * inM2[1][3];
+ outM3[1][3] = inM1[0][3] * inM2[1][0] + inM1[1][3] * inM2[1][1] + inM1[2][3] * inM2[1][2]
+ + inM1[3][3] * inM2[1][3];
+ outM3[2][0] = inM1[0][0] * inM2[2][0] + inM1[1][0] * inM2[2][1] + inM1[2][0] * inM2[2][2]
+ + inM1[3][0] * inM2[2][3];
+ outM3[2][1] = inM1[0][1] * inM2[2][0] + inM1[1][1] * inM2[2][1] + inM1[2][1] * inM2[2][2]
+ + inM1[3][1] * inM2[2][3];
+ outM3[2][2] = inM1[0][2] * inM2[2][0] + inM1[1][2] * inM2[2][1] + inM1[2][2] * inM2[2][2]
+ + inM1[3][2] * inM2[2][3];
+ outM3[2][3] = inM1[0][3] * inM2[2][0] + inM1[1][3] * inM2[2][1] + inM1[2][3] * inM2[2][2]
+ + inM1[3][3] * inM2[2][3];
+ outM3[3][0] = inM1[0][0] * inM2[3][0] + inM1[1][0] * inM2[3][1] + inM1[2][0] * inM2[3][2]
+ + inM1[3][0] * inM2[3][3];
+ outM3[3][1] = inM1[0][1] * inM2[3][0] + inM1[1][1] * inM2[3][1] + inM1[2][1] * inM2[3][2]
+ + inM1[3][1] * inM2[3][3];
+ outM3[3][2] = inM1[0][2] * inM2[3][0] + inM1[1][2] * inM2[3][1] + inM1[2][2] * inM2[3][2]
+ + inM1[3][2] * inM2[3][3];
+ outM3[3][3] = inM1[0][3] * inM2[3][0] + inM1[1][3] * inM2[3][1] + inM1[2][3] * inM2[3][2]
+ + inM1[3][3] * inM2[3][3];
+}
+
+//==============================================================================
+/**
+* Retrieves a quaternion given an axis angle
+*
+* This is used by StaticEulerToStudioEuler.
+*
+* @param inXAxis XAxis orientation
+* @param inYAxis YAxix orientation
+* @param inZAxis ZAxis orientation
+* @param inAngleInDegrees angle in degrees
+* @param outDouble4 double[4] containing the quaternion
+*/
+void GetQuatFromAxisAngle(float inXAxis, float inYAxis, float inZAxis, double inAngleInDegrees,
+ double *outDouble4)
+{
+ TORAD(inAngleInDegrees);
+ double theHalfAngle = 0.5f * inAngleInDegrees;
+ double theSin = ::sin(theHalfAngle);
+ double qx, qy, qz, qw;
+ qx = theSin * inXAxis;
+ qy = theSin * inYAxis;
+ qz = theSin * inZAxis;
+ qw = ::cos(theHalfAngle);
+
+ // Normalize
+ const float SQREPSILON = 0.000001f;
+ double theNorm = qx * qx + qy * qy + qz * qz + qw * qw;
+ if (theNorm < SQREPSILON) {
+ qx = qy = qz = 0;
+ qw = 1.0f;
+ } else if (::abs(theNorm - 1.0f) > SQREPSILON) {
+ double theScale = 1.0f / ::sqrt(theNorm);
+ qx *= theScale;
+ qy *= theScale;
+ qz *= theScale;
+ qw *= theScale;
+ }
+ outDouble4[0] = qx;
+ outDouble4[1] = qy;
+ outDouble4[2] = qz;
+ outDouble4[3] = qw;
+}
+
+//==============================================================================
+/**
+* Converts from static euler rotation to Studio's euler rotation.
+*
+* This is an unoptimized version. But it works.
+*
+* @param inStaticEuler the static euler rotation, in degrees
+* @param inRotateOrder the order of rotation
+* @param outStaticEuler the resultant Studio's relative euler rotation, in degrees
+*/
+
+/* Previous implementation
+void StaticEulerToStudioEuler( double* inStaticEuler, long* inRotateOrder, double* outStudioEuler )
+{
+ double theStaticEuler[3];
+ theStaticEuler[0] = TORAD( inStaticEuler[0] );
+ theStaticEuler[1] = TORAD( inStaticEuler[1] );
+ theStaticEuler[2] = TORAD( inStaticEuler[2] );
+
+ long theRotateOrder[ 3 ] = { ROTATE_X, ROTATE_Y, ROTATE_Z };
+ if ( inRotateOrder != NULL )
+ {
+ ::memcpy( theRotateOrder, inRotateOrder, 3 * sizeof( long ) );
+ }
+
+ double the4x4[16];
+ double theNULL4x4[16];
+ BuildMatrix( theStaticEuler, theRotateOrder, the4x4 );
+ ConvertMatrixToStudioEuler( the4x4, outStudioEuler, theNULL4x4 );
+}
+*/
+void StaticEulerToStudioEuler(double *inStaticEuler, long *inRotateOrder, double *outStudioEuler)
+{
+ double theTempMatr[4][4];
+ double theQuat[3][4];
+ double theMatr1[4][4];
+ double theMatr2[4][4];
+
+ for (long theIndex = 0; theIndex < 3; ++theIndex) {
+ switch (inRotateOrder[theIndex]) {
+ case ROTATE_X:
+ GetQuatFromAxisAngle(1.0f, 0.0f, 0.0f, inStaticEuler[0], theQuat[theIndex]);
+ break;
+ case ROTATE_Y:
+ GetQuatFromAxisAngle(0.0f, 1.0f, 0.0f, inStaticEuler[1], theQuat[theIndex]);
+ break;
+ case ROTATE_Z:
+ GetQuatFromAxisAngle(0.0f, 0.0f, 1.0f, inStaticEuler[2], theQuat[theIndex]);
+ break;
+ }
+ }
+
+ EulerAngleConverter::ConvertQuatToMatrix(theQuat[0], reinterpret_cast<double *>(theMatr1));
+ EulerAngleConverter::ConvertQuatToMatrix(theQuat[1], reinterpret_cast<double *>(theMatr2));
+ MatrixMultiply(theMatr1, theMatr2, theTempMatr);
+ EulerAngleConverter::ConvertQuatToMatrix(theQuat[2], reinterpret_cast<double *>(theMatr1));
+ MatrixMultiply(theTempMatr, theMatr1, theMatr2);
+
+ ConvertMatrixToStudioEuler(reinterpret_cast<double *>(theMatr2), outStudioEuler,
+ reinterpret_cast<double *>(theMatr1));
+}
+
+} // end of namespace EulerAngleConverter
diff --git a/src/Authoring/Common/Code/EulerAngles/EulerAngles.h b/src/Authoring/Common/Code/EulerAngles/EulerAngles.h
new file mode 100644
index 00000000..8be53fb8
--- /dev/null
+++ b/src/Authoring/Common/Code/EulerAngles/EulerAngles.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Description
+//==============================================================================
+// EulerAngles.h - Support for 24 angle schemes
+// by Ken Shoemake, shoemake@graphics.cis.upenn.edu
+// in "Graphics Gems IV", Academic Press, 1994
+// http://vered.rose.utoronto.ca/people/david_dir/GEMS/GEMS.html
+// Order type constants, constructors, extractors
+// There are 24 possible conventions, designated by:
+// o EulAxI = axis used initially
+// o EulPar = parity of axis permutation
+// o EulRep = repetition of initial axis as last
+// o EulFrm = frame from which axes are taken
+// Axes I,J,K will be a permutation of X,Y,Z.
+// Axis H will be either I or K, depending on EulRep.
+// Frame S takes axes from initial static frame.
+// If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then
+// {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v
+// rotates v around Z by c radians.
+//
+
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef _EULERANGLES_H_
+#define _EULERANGLES_H_
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include "QuatTypes.h"
+
+#define EulFrmS 0
+#define EulFrmR 1
+#define EulFrm(ord) ((unsigned)(ord)&1)
+#define EulRepNo 0
+#define EulRepYes 1
+#define EulRep(ord) (((unsigned)(ord) >> 1) & 1)
+#define EulParEven 0
+#define EulParOdd 1
+#define EulPar(ord) (((unsigned)(ord) >> 2) & 1)
+#define EulSafe "\000\001\002\000"
+#define EulNext "\001\002\000\001"
+#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord) >> 3) & 3)]))
+#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) == EulParOdd)]))
+#define EulAxK(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) != EulParOdd)]))
+#define EulAxH(ord) ((EulRep(ord) == EulRepNo) ? EulAxK(ord) : EulAxI(ord))
+
+// EulGetOrd unpacks all useful information about order simultaneously.
+#define EulGetOrd(ord, i, j, k, h, n, s, f) \
+{ \
+ unsigned o = ord; \
+ f = o & 1; \
+ o = o >> 1; \
+ s = o & 1; \
+ o = o >> 1; \
+ n = o & 1; \
+ o = o >> 1; \
+ i = EulSafe[o & 3]; \
+ j = EulNext[i + n]; \
+ k = EulNext[i + 1 - n]; \
+ h = s ? k : i; \
+ }
+
+// EulOrd creates an order value between 0 and 23 from 4-tuple choices.
+#define EulOrd(i, p, r, f) (((((((i) << 1) + (p)) << 1) + (r)) << 1) + (f))
+
+// Static axes
+// X = 0, Y = 1, Z = 2 ref QuatPart
+#define EulOrdXYZs EulOrd(0, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdXYXs EulOrd(0, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdXZYs EulOrd(0, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdXZXs EulOrd(0, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdYZXs EulOrd(1, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdYZYs EulOrd(1, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdYXZs EulOrd(1, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdYXYs EulOrd(1, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdZXYs EulOrd(2, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdZXZs EulOrd(2, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdZYXs EulOrd(2, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdZYZs EulOrd(2, EulParOdd, EulRepYes, EulFrmS)
+
+// Rotating axes
+#define EulOrdZYXr EulOrd(0, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdXYXr EulOrd(0, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdYZXr EulOrd(0, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdXZXr EulOrd(0, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdXZYr EulOrd(1, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdYZYr EulOrd(1, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdZXYr EulOrd(1, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdYXYr EulOrd(1, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdYXZr EulOrd(2, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdZXZr EulOrd(2, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdXYZr EulOrd(2, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdZYZr EulOrd(2, EulParOdd, EulRepYes, EulFrmR)
+
+#ifndef M_PI
+#define M_PI 3.1415926535898
+#endif
+
+#define TODEG(x) x = (float)(x * 180 / M_PI);
+#define TORAD(x) x = (float)(x / 180 * M_PI);
+
+namespace EulerAngleConverter {
+const double TO_DEGREE_MULTIPLIER = 180 / M_PI;
+const double TO_RADIAN_MULTIPLIER = M_PI / 180;
+
+// encode rotate order & axes
+const long ROTATE_X = 1;
+const long ROTATE_Y = 2;
+const long ROTATE_Z = 3;
+const long ROTATE_FIRST = 0;
+const long ROTATE_SECOND = 1;
+const long ROTATE_THIRD = 2;
+long GetRotationAxis(long inCode, long inOrder);
+long SetRotationAxis(long inAxis, long inOrder, long &outCode);
+
+class CEulerAngleConverter
+{
+private:
+ char m_OrderInfoBuffer[1024];
+
+public:
+ CEulerAngleConverter();
+ virtual ~CEulerAngleConverter();
+
+public:
+ EulerAngles Eul_(float ai, float aj, float ah, int order);
+ Quat Eul_ToQuat(EulerAngles ea);
+ void Eul_ToHMatrix(EulerAngles ea, HMatrix M);
+ EulerAngles Eul_FromHMatrix(HMatrix M, int order);
+ EulerAngles Eul_FromQuat(Quat q, int order);
+
+ // Debug Stuff
+ const char *DumpOrderInfo();
+};
+
+void ConvertQuatToMatrix(double inQuat[4], double outMatrix[16]);
+void TransposeMatrix(double ioMatrix[16]);
+long GetRotationAxis(long inCode, long inOrder);
+long SetRotationAxis(long inAxis, long inOrder, long &outCode);
+
+bool ConvertMatrixToStudioEuler(bool inNegScls[3], double *inMatrixDouble16,
+ double *outEulerDouble3, double *outMatrixDouble16);
+bool ConvertMatrixToStudioEuler(double *inMatrixDouble16, double *outEulerDouble3,
+ double *outMatrixDouble16);
+void RotateX(double inRadian, double *inPoint, double *outPoint);
+void RotateY(double inRadian, double *inPoint, double *outPoint);
+void RotateZ(double inRadian, double *inPoint, double *outPoint);
+void RotateAxes(double inXRadian, double inYRadian, double inZRadian, double *inXAxis,
+ double *inYAxis, double *inZAxis);
+void DoAxes(long inRotOrder, long inRotSeq, double *inRots, double *inXAxis, double *inYAxis,
+ double *inZAxis);
+
+void StaticEulerToStudioEuler(double *inStaticEuler, long *inRotateOrder, double *outStudioEuler);
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/EulerAngles/QuatTypes.h b/src/Authoring/Common/Code/EulerAngles/QuatTypes.h
new file mode 100644
index 00000000..11826414
--- /dev/null
+++ b/src/Authoring/Common/Code/EulerAngles/QuatTypes.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef _QUATTYPES_H_
+#define _QUATTYPES_H_
+#pragma once
+
+//==============================================================================
+// Description
+//==============================================================================
+// QuatTypes.h - Basic type declarations
+// by Ken Shoemake, shoemake@graphics.cis.upenn.edu
+// in "Graphics Gems IV", Academic Press, 1994
+
+namespace EulerAngleConverter {
+typedef struct
+{
+ float x, y, z, w;
+} Quat; /* Quaternion */
+typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
+enum QuatPart { X, Y, Z, W };
+typedef Quat EulerAngles; /* (x,y,z)=ang 1,2,3, w=order code */
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/Exceptions/StudioException.h b/src/Authoring/Common/Code/Exceptions/StudioException.h
new file mode 100644
index 00000000..2bff6e79
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/StudioException.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_EXCEPTION_H
+#define INCLUDED_STUDIO_EXCEPTION_H 1
+
+#pragma once
+
+#ifdef WIN32
+#include <wchar.h>
+#endif
+
+class CStudioException
+{
+public:
+ virtual ~CStudioException() {}
+ virtual const wchar_t *GetDescription() const = 0;
+};
+#endif // INCLUDED_STUDIO_EXCEPTION_H
diff --git a/src/Authoring/Common/Code/Exceptions/UICExceptionClass.cpp b/src/Authoring/Common/Code/Exceptions/UICExceptionClass.cpp
new file mode 100644
index 00000000..39c807f3
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/UICExceptionClass.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+#include "UICExceptions.h"
+#include "UICExceptionClass.h"
+
+bool CUICExceptionClass::s_HandlingTypes = true;
+
+//==============================================================================
+/**
+ * Constructs a CUICExceptionClass object.
+ *
+ * This method creates a CUICExceptionClass object.
+ *
+ * @param <long> inlong The long to check for failure
+ * @param <const char*> inFileName The name of the file of the calling function
+ * @param <unsigned long> inLineNumber The line number of the calling function
+ * @param <long> inErrorCode The error code to handle if the
+ *failure occurs.
+ * @param <unsigned long> inType The type of error
+ * @param <va_list> inParameters A pointer to the optional arugments for
+ *string formatting purposes
+ */
+CUICExceptionClass::CUICExceptionClass(const wchar_t *inFileName, const unsigned long inLineNumber,
+ const long inErrorCode, const long inlong,
+ va_list inParameters)
+#ifdef KDAB_TEMPORARILY_REMOVED
+ : m_ParameterList(inParameters)
+ , m_LineNumber(inLineNumber)
+ , m_long(inlong)
+ , m_ErrorCode(inErrorCode)
+ , m_Type(0)
+#endif
+{
+ // Clear strings
+ *m_Location = 0;
+ *m_Description = 0;
+ *m_StackTrace = 0;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Copy the filename
+ _aswprintf(m_FileName, _arraysize(m_FileName) - 1, L"%ls", inFileName);
+
+ // TODO get stacktrace somehow
+
+ // Format the error string and handle the exception
+ FormatDescription();
+ HandleException();
+#endif
+}
+
+//==============================================================================
+/**
+ * Handles the exception
+ */
+void CUICExceptionClass::HandleException()
+{
+ // Check registry for changes
+ CUICExceptionClass::Initialize();
+
+ // Are we handling this type of exception?
+ //
+ // SDJ 9/19/01: m_Type does not appear to be initialized anywhere, so I removed this test
+ //
+ // if ( s_HandlingTypes & m_Type )
+
+ if (s_HandlingTypes) {
+ // Display the exception in the debugger output window?
+ Output2Debugger();
+
+ // Display the exception in a message box?
+ BreakInDebugger();
+
+ // Log the exception?
+ // Log2File();
+
+ // Display the exception in a message box?
+ DisplayMessageBox();
+ }
+}
+
+//==============================================================================
+/**
+ * Displays the exception description in a windows message box.
+ *
+ * @return bool TRUE the description was formatted correctly.
+ */
+bool CUICExceptionClass::FormatDescription()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ bool theResult = false;
+ // wchar_t theErrorString[MAX_ENTRY_LENGTH] = { 0 };
+ wchar_t theDescription[MAX_ENTRY_LENGTH] = { 0 };
+
+ // Format location and clear description
+ _aswprintf(m_Location, _arraysize(m_Location) - 1, L"%ls(%ld)", m_FileName, m_LineNumber);
+ m_Description[0] = 0;
+
+ // Is it our ErrorCode?
+ if (HRESULT_FACILITY(m_ErrorCode) == FACILITY_ITF) {
+ // Tack on a failing long?
+ if (FAILED(m_long)) {
+// Look up the error code in the string table
+// GetStringFromID( long_CODE( m_ErrorCode ), theErrorString );
+// theResult = _avswprintf( theDescription, MAX_ENTRY_LENGTH - 1, theErrorString, m_ParameterList )
+// > 0;
+
+#ifdef WIN32
+
+ // Add the long at the end
+ if (theResult) {
+ LPTSTR theMsgBuffer;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+ m_long, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&theMsgBuffer, 0, NULL);
+
+ // Strip off any CR/LF
+ if (theMsgBuffer != NULL) {
+ size_t nLen = ::wcslen(theMsgBuffer);
+ if (nLen > 1 && theMsgBuffer[nLen - 1] == '\n') {
+ theMsgBuffer[nLen - 1] = 0;
+ if (theMsgBuffer[nLen - 2] == '\r') {
+ theMsgBuffer[nLen - 2] = 0;
+ }
+ }
+ }
+
+ // else NULL buffer
+ else {
+ const int MSG_MAXSIZE = 32;
+ theMsgBuffer = (LPTSTR)LocalAlloc(0, MSG_MAXSIZE * sizeof(wchar_t));
+ if (theMsgBuffer != NULL) {
+ _snwprintf(theMsgBuffer, MSG_MAXSIZE, TEXT("0x%0lX"), m_long);
+ }
+ }
+
+ theResult = _aswprintf(m_Description, _arraysize(m_Description) - 1, L"%ls (%ls)",
+ theDescription, theMsgBuffer)
+ > 0;
+
+ LocalFree(theMsgBuffer);
+ }
+
+#else
+// NOT IMPLEMENTED ON THE MAC
+#endif
+ } else {
+ // Look up the error code in the string table
+ // GetStringFromID( long_CODE( m_ErrorCode ), theErrorString );
+ // theResult = _avswprintf( m_Description, _arraysize(m_Description) - 1,
+ // theErrorString, m_ParameterList ) > 0;
+ }
+ }
+
+ return theResult;
+#endif
+ return {};
+}
+
+//==============================================================================
+/**
+ * Breaks immediately in the debugger.
+ */
+void CUICExceptionClass::BreakInDebugger()
+{
+#ifdef _DEBUG
+#ifdef WIN32
+// ::DebugBreak( );
+#else
+#endif
+#endif
+}
+
+//==============================================================================
+/**
+ * Displays the exception description in a windows message box.
+ */
+void CUICExceptionClass::DisplayMessageBox()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Display the exception in a message box?
+ wchar_t theBufferString[MAX_ENTRY_LENGTH];
+ long theErrorCode = HRESULT_CODE(m_ErrorCode);
+
+ _aswprintf(theBufferString, MAX_ENTRY_LENGTH - 1,
+ L"A program exception was caught.\n%s\nFile: %s\nCode: 0x%lX\n\nAbort quits, Retry "
+ L"launches debugger and Ignore continues program execution.\n",
+ m_Description, m_Location, theErrorCode);
+ ::wcsncat(theBufferString, L"\r\n\r\n", MAX_ENTRY_LENGTH - 1);
+
+#ifdef _DEBUG
+ long thePressedButton;
+
+ // Display the dialog
+ thePressedButton = ::MessageBoxW(NULL, theBufferString, L"Exception",
+ MB_ABORTRETRYIGNORE | MB_ICONERROR | MB_DEFBUTTON3);
+ switch (thePressedButton) {
+ // Exit the application?
+ case IDABORT:
+ ::exit(1);
+ break;
+
+ // Launch the IDE debugger?
+ case IDRETRY:
+ ::DebugBreak();
+ break;
+
+ // If the button pressed is ignore, then just continue
+ default:
+ break;
+ }
+
+#endif // _DEBUG
+#endif
+}
+
+//==============================================================================
+/**
+ * Output the exception description to the development environment debug window.
+ */
+void CUICExceptionClass::Output2Debugger()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+#ifdef _DEBUG
+ wchar_t theBufferString[MAX_ENTRY_LENGTH];
+ long theErrorCode = HRESULT_CODE(m_ErrorCode);
+
+ // Format and output
+ _aswprintf(theBufferString, MAX_ENTRY_LENGTH - 1, L"%ls - %ls - 0x%lX\n", m_Location,
+ m_Description, theErrorCode);
+#endif
+
+#ifdef WIN32
+ ::OutputDebugStringW(theBufferString);
+#else
+// NOT IMPLEMENTED ON THE MAC
+#endif
+#endif
+}
+
+//==============================================================================
+/**
+ * Initialize all static members from preferences in registry.
+ *
+ * Method opens up the key at HKEY_CURRENT_USER/m_RegistryPreferencePath.
+ * The three DWORD values looked up are: TrackErrorTypes, ReportingLevel and ErrorAction
+ */
+void CUICExceptionClass::Initialize()
+{
+ /*
+ #ifdef WIN32
+ long theReturn;
+ HKEY theKey = NULL;
+ DWORD theValueType;
+ DWORD theDataSize;
+
+ // Open Key
+ theReturn = ::RegOpenKeyEx( HKEY_CURRENT_USER, UIC_CLIENT_REGISTRY_KEY, 0, KEY_READ,
+ &theKey );
+
+ if ( ERROR_SUCCESS == theReturn && theKey )
+ {
+ // Query the registry for the TrackErrorTypes value
+ theValueType = REG_DWORD;
+ theDataSize = sizeof(DWORD);
+ theReturn = ::RegQueryValueEx( theKey, UIC_CLIENT_TRACKERRORTYPES_VALUE, NULL,
+ &theValueType, reinterpret_cast<BYTE*>(&s_HandlingTypes), &theDataSize );
+
+ // Query the registry for the ReportingLevel value
+ theValueType = REG_DWORD;
+ theDataSize = sizeof(DWORD);
+ theReturn = ::RegQueryValueEx( theKey, UIC_CLIENT_REPORTINGLEVEL_VALUE, NULL,
+ &theValueType, reinterpret_cast<BYTE*>(&s_ReportingLevel), &theDataSize );
+
+ // Query the registry for the ErrorAction value
+ theValueType = REG_DWORD;
+ theDataSize = sizeof(DWORD);
+ theReturn = ::RegQueryValueEx( theKey, UIC_CLIENT_ERRORACTION_VALUE, NULL,
+ &theValueType, reinterpret_cast<BYTE*>(&s_Actions), &theDataSize );
+
+ // Close reg file
+ theReturn = ::RegCloseKey( theKey );
+ }
+ #else
+ // NOT IMPLEMENTED ON THE MAC
+ #endif
+ */
+}
+
+//==============================================================================
+/**
+ * Throws an exception
+ *
+ * This static method throws an exception.
+ * It may also just create an instance of the exception class if the
+ * the program is currently running in God Mode.
+ *
+ * @param <long> inlong The long to check for failure
+ * @param <const wchar_t*> inFileName The name of the file of the calling
+ *function
+ * @param <unsigned long> inLineNumber The line number of the calling function
+ * @param <long> inErrorCode The error code to handle if the failure
+ *occurs.
+ * @param <unsigned long> inType The type of error
+ * @param <...> Optional arugments for string
+ *formatting purposes
+ */
+void CUICExceptionClass::Throw(const wchar_t *inFileName, const unsigned long inLineNumber,
+ const long inErrorCode, ...)
+{
+ // Define a parameter list
+ va_list theParameters;
+
+ // Initalize the list to the parameter before the optional ones start
+ va_start(theParameters, inErrorCode);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Throw an exception
+ throw CUICExceptionClass(inFileName, inLineNumber, inErrorCode, S_FALSE, theParameters);
+#endif
+}
+
+//==============================================================================
+/**
+ * Throws an exception if the inlong fails.
+ *
+ * This static method throws an exception if the inlong is not S_OK.
+ * It may also just create an instance of the exception class if the
+ * the program is currently running in God Mode.
+ *
+ * @param <long> inlong The long to check for
+ *failure
+ * @param <const wchar_t*> inFileName The name of the file of the calling
+ *function
+ * @param <unsigned long> inLineNumber The line number of the calling function
+ * @param <long> inErrorCode The error code to handle if
+ *the failure occurs.
+ * @param <unsigned long> inType The type of error
+ * @param <...> Optional arugments for
+ *string formatting purposes
+ */
+void CUICExceptionClass::ThrowFail(const long inlong, const wchar_t *inFileName,
+ const unsigned long inLineNumber, const long inErrorCode, ...)
+{
+ // Define a parameter list
+ va_list theParameters;
+
+ // Initalize the list to the parameter before the optional ones start
+ va_start(theParameters, inErrorCode);
+
+ // If the the result is not good
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (FAILED(inlong)) {
+ // Throw an exception
+ throw CUICExceptionClass(inFileName, inLineNumber, inErrorCode, inlong, theParameters);
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Throws an exception if the inCondition is FALSE
+ *
+ * This static method throws an exception if the inCondition is FALSE.
+ * It may also just create an instance of the exception class if the
+ * the program is currently running in God Mode.
+ *
+ * @param <long> inlong The long to check for falsity :)
+ * @param <const wchar_t*> inFileName The name of the file of the calling
+ *function
+ * @param <unsigned long> inLineNumber The line number of the calling function
+ * @param <long> inErrorCode The error code to handle if the failure
+ *occurs.
+ * @param <unsigned long> inType The type of error
+ * @param <...> Optional arugments for string
+ *formatting purposes
+ */
+void CUICExceptionClass::ThrowFalse(bool inCondition, const wchar_t *inFileName,
+ const unsigned long inLineNumber, const long inErrorCode, ...)
+{
+ // Define a parameter list
+ va_list theParameters;
+
+ // Initalize the list to the parameter before the optional ones start
+ va_start(theParameters, inErrorCode);
+
+ // If the condition fails
+ if (!inCondition) {
+ // Throw an exception
+#ifdef KDAB_TEMPORARILY_REMOVED
+ throw CUICExceptionClass(inFileName, inLineNumber, inErrorCode, S_FALSE, theParameters);
+#endif
+ }
+}
diff --git a/src/Authoring/Common/Code/Exceptions/UICExceptionClass.h b/src/Authoring/Common/Code/Exceptions/UICExceptionClass.h
new file mode 100644
index 00000000..60f61eed
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/UICExceptionClass.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __UICEXCEPTIONCLASS_H_
+#define __UICEXCEPTIONCLASS_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "StudioException.h"
+#include "UICExceptionConstants.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+
+//==============================================================================
+// Constants
+//==============================================================================
+const short MAX_ENTRY_LENGTH = 2048;
+const short MAX_STACKTRACE_LENGTH = 1024;
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 1024
+#endif
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CExceptionClass
+ * @brief
+ */
+class CUICExceptionClass : public CStudioException
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+protected:
+ wchar_t m_FileName[_MAX_PATH]; ///< The file name where the exception occurred
+ wchar_t m_Location[_MAX_PATH]; ///< The location description
+ wchar_t m_Description[MAX_ENTRY_LENGTH]; ///< A description of the exception
+ wchar_t m_StackTrace[MAX_STACKTRACE_LENGTH]; ///< The stack when the exception was created.
+ long m_ErrorCode; ///< The error code (long)
+ long m_long; ///< The long that FAILED
+ va_list m_ParameterList; ///< The optional parameter list passed to the constructor ( sprintf
+ ///type functionality ).
+ unsigned long m_LineNumber; ///< The line number of the exception
+ unsigned long m_Type; ///< The type of exception
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Construction
+
+protected:
+ CUICExceptionClass(const wchar_t *inFileName, const unsigned long inLineNumber,
+ const long inErrorCode, const long inlong, va_list inParameters);
+ virtual ~CUICExceptionClass() {}
+
+ // Access
+
+public:
+ wchar_t *GetFileName() { return m_FileName; }
+ wchar_t *GetLocation() { return m_Location; }
+ wchar_t *GetStackTrace() { return m_StackTrace; };
+ const wchar_t *GetDescription() const override { return m_Description; }
+ long GetErrorCode() { return m_ErrorCode; }
+ long Getlong() { return m_long; }
+ unsigned long GetLineNumber() { return m_LineNumber; }
+ unsigned long GetType() { return m_Type; }
+
+ // Implementation
+
+protected:
+ // void GetStringFromID( unsigned long inID, wchar_t* outString );
+ bool FormatDescription();
+ void HandleException();
+ void BreakInDebugger();
+ void DisplayMessageBox();
+ // void Log2File();
+ void Output2Debugger();
+
+ //==============================================================================
+ // Static Methods
+ //==============================================================================
+
+public:
+ static void Throw(const wchar_t *inFileName, const unsigned long inLineNumber,
+ const long inErrorCode, ...);
+ static void ThrowFail(const long inlong, const wchar_t *inFileName,
+ const unsigned long inLineNumber, const long inErrorCode, ...);
+ static void ThrowFalse(bool inCondition, const wchar_t *inFileName,
+ const unsigned long inLineNumber, const long inErrorCode, ...);
+
+ static bool s_HandlingTypes;
+
+protected:
+ static void Initialize();
+};
+
+#endif //__UICEXCEPTIONCLASS_H_
diff --git a/src/Authoring/Common/Code/Exceptions/UICExceptionConstants.h b/src/Authoring/Common/Code/Exceptions/UICExceptionConstants.h
new file mode 100644
index 00000000..b776b39a
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/UICExceptionConstants.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef __UICEXCEPTIONCONSTANTS_H__
+#define __UICEXCEPTIONCONSTANTS_H__
+
+const unsigned long ERROR_TYPE_PLAYER = 0x00000001;
+const unsigned long ERROR_TYPE_LIBRARY = 0x00000002;
+const unsigned long ERROR_TYPE_CONTROLLER = 0x00000004;
+const unsigned long ERROR_TYPE_ICELIB = 0x00000008;
+const unsigned long ERROR_TYPE_IOLIBRARY = 0x00000010;
+const unsigned long ERROR_TYPE_OBJECT_MODEL = 0x00000020;
+const unsigned long ERROR_TYPE_GLOBAL_INTERFACE_TABLE = 0x00000040;
+const unsigned long ERROR_TYPE_COMPONENT = 0x00000080;
+const unsigned long ERROR_TYPE_RENDER = 0x00000100;
+const unsigned long ERROR_TYPE_SCRIPT_ENGINE = 0x00000200;
+const unsigned long ERROR_TYPE_STREAM = 0x00000400;
+const unsigned long ERROR_TYPE_TYPES = 0x00000800;
+const unsigned long ERROR_TYPE_UTILITY = 0x00001000;
+const unsigned long ERROR_TYPE_TRANSM = 0x00002000;
+const unsigned long ERROR_TYPE_INSTALLER = 0x00004000;
+
+#endif // #ifndef __UICEXCEPTIONCONSTANTS_H__ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Exceptions/UICExceptions.h b/src/Authoring/Common/Code/Exceptions/UICExceptions.h
new file mode 100644
index 00000000..f80b53e7
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/UICExceptions.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _UICEXCEPTIONS_H__
+#define _UICEXCEPTIONS_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "UICExceptionClass.h"
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+const unsigned long LEVEL_SUCCESS = 0x00000000;
+const unsigned long LEVEL_INFORMATIONAL = 0x00000001;
+const unsigned long LEVEL_WARNING = 0x00000002;
+const unsigned long LEVEL_ERROR = 0x00000003;
+
+//==============================================================================
+// Macros
+//==============================================================================
+
+#define WIDEN2(x) L##x
+#define WIDEN(x) WIDEN2(x)
+#define __WFILE__ WIDEN(__FILE__)
+#define UIC_DEFINE_THISFILE static wchar_t UIC_THIS_FILE[] = __WFILE__;
+
+// The class
+#define UIC_EXCEPTION CUICExceptionClass
+
+// An exception with no extra parameters.
+#define UIC_THROW(inErrorCode) UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode);
+
+// An exception with one extra paramter.
+#define UIC_THROW1(inErrorCode, inParam1) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode, inParam1);
+
+// An exception with two extra paramters.
+#define UIC_THROW2(inErrorCode, inParam1, inParam2) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode, inParam1, inParam2);
+
+// An exception with no extra parameters, only if inHResult doesn't SUCCEED().
+#define UIC_THROWFAIL(inHResult, inErrorCode) \
+ if (FAILED(inHResult)) \
+ UIC_EXCEPTION::ThrowFail(inHResult, __WFILE__, __LINE__, inErrorCode);
+
+// An exception with one extra paramter, is thrown only if inHResult doesn't SUCCEED().
+#define UIC_THROWFAIL1(inHResult, inErrorCode, inParam1) \
+ if (FAILED(inHResult)) \
+ UIC_EXCEPTION::ThrowFail(inHResult, __WFILE__, __LINE__, inErrorCode, inParam1);
+
+// An exception with two extra paramters, is thrown only if inHResult doesn't SUCCEED().
+#define UIC_THROWFAIL2(inHResult, inErrorCode, inParam1, inParam2) \
+ if (FAILED(inHResult)) \
+ UIC_EXCEPTION::ThrowFail(inHResult, __WFILE__, __LINE__, inErrorCode, inParam1, inParam2);
+
+// An exception with no extra parameters, only if inCondition is false.
+#define UIC_THROWFALSE(inCondition, inErrorCode) \
+ if (!(inCondition)) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode);
+
+// An exception with one extra paramter, is thrown only if inCondition is false.
+#define UIC_THROWFALSE1(inCondition, inErrorCode, inParam1) \
+ if (!(inCondition)) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode, inParam1);
+
+// An exception with two extra paramters, is thrown only if inCondition is false.
+#define UIC_THROWFALSE2(inCondition, inErrorCode, inParam1, inParam2) \
+ if (!(inCondition)) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode, inParam1, inParam2);
+
+// An exception with no extra parameters, only if inPointer is NULL.
+#define UIC_THROWNULL(inPointer, inErrorCode) \
+ if ((inPointer) == NULL) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode);
+
+// An exception with one extra parameters, only if inPointer is NULL.
+#define UIC_THROWNULL1(inPointer, inErrorCode, inParam1) \
+ if ((inPointer) == NULL) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode, inParam1);
+
+// An exception with two extra parameters, only if inPointer is NULL.
+#define UIC_THROWNULL2(inPointer, inErrorCode, inParam1, inParam2) \
+ if ((inPointer) == NULL) \
+ UIC_EXCEPTION::Throw(__WFILE__, __LINE__, inErrorCode, inParam1, inParam2);
+
+// Standard catch that transfers the HRESULT from the exception
+#define UIC_CATCH(outResult) \
+ catch (UIC_EXCEPTION & inException) { outResult = inException.GetErrorCode(); } \
+ catch (...) { outResult = E_FAIL; }
+
+// Catch that transfers the HRESULT and sets the resource string from the exception
+// DEPRECATED: DO not use!!!!!!!
+#define UIC_CATCHERRORINFO(outResult) \
+ catch (UIC_EXCEPTION & inException) { outResult = inException.GetErrorCode(); } \
+ catch (...) { outResult = E_FAIL; }
+
+// Wrapper around DOM calls to catch and translate exceptions resource strings to ErrorInfo
+#define UIC_DOMTRYCATCH(inStatement) \
+ { \
+ HRESULT theResult; \
+ \
+ try { \
+ theResult = inStatement; \
+ } \
+ UIC_CATCHERRORINFO(theResult) \
+ \
+ return theResult; \
+ }
+
+#ifndef _WIN32
+#define E_FAIL 0x80004005L
+#endif
+
+#endif // #ifndef _UICEXCEPTIONS_H__
diff --git a/src/Authoring/Common/Code/Exceptions/XMLException.cpp b/src/Authoring/Common/Code/Exceptions/XMLException.cpp
new file mode 100644
index 00000000..df3849e1
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/XMLException.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "XMLException.h"
+
+CXMLException::CXMLException(const wchar_t *inXMLDescription)
+{
+ wcscpy(m_Description, inXMLDescription);
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Exceptions/XMLException.h b/src/Authoring/Common/Code/Exceptions/XMLException.h
new file mode 100644
index 00000000..b6e49ef5
--- /dev/null
+++ b/src/Authoring/Common/Code/Exceptions/XMLException.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_XML_EXCEPTION_H
+#define INCLUDED_XML_EXCEPTION_H 1
+
+#pragma once
+
+const short XML_DESCRIPTION_LENGTH = 256;
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioException.h"
+
+class CXMLException : public CStudioException
+{
+
+public:
+ CXMLException(const wchar_t *inXMLDescription);
+ virtual ~CXMLException() {}
+ const wchar_t *GetDescription() const override { return m_Description; }
+
+protected:
+ wchar_t m_Description[XML_DESCRIPTION_LENGTH]; ///< A description of the exception
+};
+
+#endif // INCLUDED_XML_EXCEPTION_H
diff --git a/src/Authoring/Common/Code/FileIterator.h b/src/Authoring/Common/Code/FileIterator.h
new file mode 100644
index 00000000..0a91be22
--- /dev/null
+++ b/src/Authoring/Common/Code/FileIterator.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_FILE_ITERATOR_H
+#define INCLUDED_FILE_ITERATOR_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <vector>
+#include "UICString.h"
+
+class CUICFile;
+
+class CFileIterator
+{
+public:
+ CFileIterator(const CUICFile *inFile);
+ virtual ~CFileIterator();
+ virtual bool IsDone();
+ virtual void operator++();
+
+ virtual void operator+=(const long inNumToInc);
+ virtual CUICFile GetCurrent();
+
+ virtual size_t GetTotal();
+
+protected:
+ Q3DStudio::CString m_File;
+ size_t m_Index;
+ std::vector<Q3DStudio::CString> m_FileNames;
+};
+
+#endif // INCLUDED_FILE_ITERATOR_H
diff --git a/src/Authoring/Common/Code/GUIDUtilities.h b/src/Authoring/Common/Code/GUIDUtilities.h
new file mode 100644
index 00000000..ef9770a5
--- /dev/null
+++ b/src/Authoring/Common/Code/GUIDUtilities.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+//#include "UICTime.h"
+#include "UICString.h"
+#include "UICId.h"
+#include <stdio.h>
+
+/*
+ CId has been revamped to use the more robust OS-dependent GUID generator.
+ Because this utility file is heavily used all over the place,
+ the best option is to wrap it around CId.
+*/
+
+const GUID UNASSIGNED_GUID = { 0, 0, 0, "" };
+const GUID SCENE_GUID = {
+ 0xffffffff, 0xffff, 0xffff, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+};
+
+//==============================================================================
+/**
+ * less() Compared two GUIDs
+ *
+ * A compares two GUIDs
+ *
+ * @param <GUID> inGUID1 The GUID to compare to the second
+ * @param <GUID> inGUID2 The GUID to compare to the first
+ *
+ * @return <bool> true if GUID1 and GUID2 are equal, otherwise false.
+ */
+inline bool lessGUID(const GUID &inValL, const GUID &inValR)
+{
+ return ::memcmp(&inValL, &inValR, sizeof(inValR)) < 0;
+}
+
+//==============================================================================
+/**
+ * equal() Compared two GUIDs
+ *
+ * A compares two GUIDs
+ *
+ * @param <GUID> inGUID1 The GUID to compare to the second
+ * @param <GUID> inGUID2 The GUID to compare to the first
+ *
+ * @return <bool> true if GUID1 and GUID2 are equal, otherwise false.
+ */
+inline bool equalGUID(const GUID &inValL, const GUID &inValR)
+{
+ return ::memcmp(&inValL, &inValR, sizeof(inValR)) == 0;
+}
+
+//==============================================================================
+/**
+ * @class CGUIDCompare
+ * @brief A class that enacapsulates the compare operator for two GUIDs.
+ */
+class CGUIDCompare
+{
+public:
+ //==============================================================================
+ /*
+ * operator() Compared two GUIDs
+ *
+ * A compares two GUIDs
+ *
+ * @param <GUID> inGUID1 The GUID to compare to the second
+ * @param <GUID> inGUID2 The GUID to compare to the first
+ *
+ * @return <bool> true if GUID1 and GUID2 are equal, otherwise false.
+ */
+ bool operator()(const GUID &inValL, const GUID &inValR) const
+ {
+ return lessGUID(inValL, inValR);
+ }
+};
+
+class CGUIDTools
+{
+public:
+ //==============================================================================
+ /**
+ * Prepeare to generate GUIDs. If this method is not called the GUIDs will
+ * but evil GUIDs that are the same evertime the program runs.
+ * @param outGuid Returns the generated GUID
+ */
+ static void Initialize()
+ {
+ // Q3DStudio::CTime theTime( true );
+ //::srand( static_cast<unsigned int>( theTime.GetMilliSecs( ) ) );
+ }
+
+ //==============================================================================
+ /**
+ * GenerateGuid
+ * @note This is not a GUID. Correct creation involves spatial uniqueness and more:
+ * http://hegel.ittc.ukans.edu/topics/internet/internet-drafts/draft-l/draft-leach-uuids-guids-00.txt
+ * @param outGuid Returns the generated GUID
+ */
+ static void GenerateGuid(GUID &outGuid)
+ {
+ // Debug - non-random GUIDs
+ /* static long theGuidCount = 1;
+ GUID theGuid = {0};
+
+ theGuid.Data1 = theGuidCount;
+
+ ++theGuidCount;
+ outGuid = theGuid;*/
+
+ // ::rand is 16 bits, GUID is 128 bits, smear random bits over the whole GUID
+ // for ( long theSlot = 0; theSlot < sizeof(GUID)/sizeof(short); ++theSlot )
+ // reinterpret_cast<short*>( &outGuid )[theSlot] = static_cast<short>( ::rand() );
+
+ Q3DStudio::CId theID;
+ theID.Generate();
+ outGuid = theID.Convert();
+ }
+
+ static GUID FromString(const Q3DStudio::CString &inGuidStr)
+ {
+ GUID theGUID = { 0, 0, 0, "" };
+ // unsigned long theData[8];
+ // const char* theBuffer = inGuidStr.GetCharStar( );
+ //
+ //// All of the %02X formats get scaned into a 32bit long so we have to convert down
+ ///below....
+ //::sscanf( theBuffer, "{%08x-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ // &theGUID.Data1,
+ // &theGUID.Data2,
+ // &theGUID.Data3,
+ // &theData[0],
+ // &theData[1],
+ // &theData[2],
+ // &theData[3],
+ // &theData[4],
+ // &theData[5],
+ // &theData[6],
+ // &theData[7]);
+
+ //// This is where we convert the 32 values into unsigned chars.
+ // for ( long theIndex = 0; theIndex < 8; ++theIndex )
+ // theGUID.Data4[theIndex] = static_cast<unsigned char>( theData[theIndex] );
+
+ Q3DStudio::CId theID;
+ theID.FromString(inGuidStr);
+ theGUID = theID.Convert();
+
+ return theGUID;
+ }
+
+ static Q3DStudio::CString ToString(REFGUID inGuid)
+ {
+ Q3DStudio::CString theGuidStr;
+
+ // theGuidStr.Format( _UIC( "{%08X-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}" ),
+ // inGuid.Data1,
+ // inGuid.Data2,
+ // inGuid.Data3,
+ // inGuid.Data4[0],
+ // (unsigned long)
+ //inGuid.Data4[1],
+ // (unsigned long)
+ //inGuid.Data4[2],
+ // (unsigned long)
+ //inGuid.Data4[3],
+ // (unsigned long)
+ //inGuid.Data4[4],
+ // (unsigned long)
+ //inGuid.Data4[5],
+ // (unsigned long)
+ //inGuid.Data4[6],
+ // (unsigned long)
+ //inGuid.Data4[7] );
+
+ Q3DStudio::CId theID(inGuid);
+ theGuidStr = theID.ToString();
+
+ return theGuidStr;
+ }
+};
diff --git a/src/Authoring/Common/Code/Graph/Graph.cpp b/src/Authoring/Common/Code/Graph/Graph.cpp
new file mode 100644
index 00000000..d298edd1
--- /dev/null
+++ b/src/Authoring/Common/Code/Graph/Graph.cpp
@@ -0,0 +1,777 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICDMPrefix.h"
+#include <boost/bind.hpp>
+#include <boost/make_shared.hpp>
+#include "UICDMTransactions.h"
+#include "UICDMSignals.h"
+#include <boost/signal.hpp>
+#include <boost/signals/connection.hpp>
+#include "Graph.h"
+#include "GraphImpl.h"
+
+using namespace boost;
+using namespace boost::BOOST_SIGNALS_NAMESPACE;
+using namespace Q3DStudio;
+using namespace UICDM;
+
+//==============================================================================
+// Statics
+//==============================================================================
+const COpaquePosition COpaquePosition::FIRST = COpaquePosition(0);
+const COpaquePosition COpaquePosition::LAST = COpaquePosition(-1);
+
+namespace {
+struct SBoostSignalConnection : public ISignalConnection, noncopyable
+{
+ boost::BOOST_SIGNALS_NAMESPACE::scoped_connection m_connection;
+ SBoostSignalConnection(const boost::BOOST_SIGNALS_NAMESPACE::connection &inConnection)
+ : m_connection(inConnection)
+ {
+ }
+};
+
+#define CONNECT(x) TSignalConnectionPtr(new SBoostSignalConnection(x))
+#define CONNECT_SIGNAL(x) CONNECT(x.connect(inCallback))
+
+typedef Q3DStudio::Graph::SGraphNode<int, int> SGraphableImpl;
+typedef SGraphableImpl *TGraphableImplPtr;
+typedef SGraphableImpl::TNodeList TGraphableImplList;
+
+struct SGraphImpl;
+typedef SGraphImpl *TGraphImplPtr;
+
+// Transaction events are implemented by this small set of satellite classes.
+// These classes are stored in the transaction consumer and are called upone
+// to do or undo particular changes to the graph.
+
+struct SAddRemoveChildAction
+{
+ TGraphImplPtr m_Graph;
+ TIdentifier m_Parent;
+ TIdentifier m_Child;
+ long m_Index;
+ bool m_DeleteOnRemove;
+
+ SAddRemoveChildAction(TGraphImplPtr graph, TIdentifier parent, TIdentifier child, long idx,
+ bool deleteOnRemove)
+ : m_Graph(graph)
+ , m_Parent(
+ parent) // Parent may be null. Removing a child from null means removing from root.
+ , m_Child(child)
+ , m_Index(idx)
+ , m_DeleteOnRemove(deleteOnRemove)
+ {
+ }
+ void AddChild();
+ void RemoveChild();
+};
+
+struct SInsertChildTransaction : public UICDM::ITransaction, public SAddRemoveChildAction
+{
+ SInsertChildTransaction(const char *inFile, int inLine, const SAddRemoveChildAction &action)
+ : UICDM::ITransaction(inFile, inLine)
+ , SAddRemoveChildAction(action)
+ {
+ }
+ void Do() override { AddChild(); }
+ void Undo() override { RemoveChild(); }
+};
+
+struct SRemoveChildTransaction : public UICDM::ITransaction, public SAddRemoveChildAction
+{
+ SRemoveChildTransaction(const char *inFile, int inLine, const SAddRemoveChildAction &action)
+ : UICDM::ITransaction(inFile, inLine)
+ , SAddRemoveChildAction(action)
+ {
+ }
+ void Do() override { RemoveChild(); }
+ void Undo() override { AddChild(); }
+};
+
+struct SReorderChildTransaction : public UICDM::ITransaction
+{
+ TGraphImplPtr m_Graph;
+ TIdentifier m_Parent;
+ TIdentifier m_Child;
+ long m_OldIndex;
+ long m_NewIndex;
+
+ SReorderChildTransaction(const char *inFile, int inLine, TGraphImplPtr graph,
+ TIdentifier parent, TIdentifier child, long oldIdx, long newIdx)
+ : UICDM::ITransaction(inFile, inLine)
+ , m_Graph(graph)
+ , m_Parent(parent)
+ , m_Child(child)
+ , m_OldIndex(oldIdx)
+ , m_NewIndex(newIdx)
+ {
+ }
+ void Do() override;
+ void Undo() override;
+};
+
+static inline Graph::SGraphPosition ToGraph(const COpaquePosition &inPos)
+{
+ if (inPos == COpaquePosition::LAST)
+ return Graph::SGraphPosition::SEnd();
+ if (inPos == COpaquePosition::FIRST)
+ return Graph::SGraphPosition::SBegin();
+ return inPos.GetIndex();
+}
+
+static inline COpaquePosition FromGraph(Graph::SGraphPosition inPos)
+{
+ switch (inPos.GetType()) {
+ case Graph::SGraphPosition::Begin:
+ return COpaquePosition::FIRST;
+ case Graph::SGraphPosition::End:
+ return COpaquePosition::LAST;
+ case Graph::SGraphPosition::Invalid:
+ return COpaquePosition::s_Invalid;
+ case Graph::SGraphPosition::Index:
+ return inPos.GetIndex();
+ }
+ assert(0);
+ return COpaquePosition::s_Invalid;
+}
+
+// End section of graph transaction helpers.
+
+//==============================================================================
+/**
+ * Graph implementation.
+ * Graph mutator implementation is broken up into 2 components. There are external
+ * components that check arguments may send transactions and internal components that
+ * expect correct arguments and can be driven either by events or transactions.
+ * Methods start with "Do" are the internal interface used by the graph and by
+ * transactions to change graph state.
+ */
+struct SGraphImpl : public CGraph
+{
+public:
+ typedef std::map<TIdentifier, TGraphableImplPtr> TLookupMap;
+ SGraphImpl(TIdentifier inRoot)
+ {
+ if (inRoot != 0)
+ CreateImpl(inRoot);
+ }
+ void SetConsumer(std::shared_ptr<UICDM::ITransactionConsumer> inConsumer) override
+ {
+ m_Consumer = inConsumer;
+ }
+
+ virtual ~SGraphImpl() { ReleaseNodes(); }
+
+ // Graph node lifetime and manipulation helpers
+ void ReleaseNodes() { m_Graph.ReleaseNodes(); }
+
+ TGraphableImplPtr GetImpl(const TIdentifier inGraphable) const
+ {
+ return m_Graph.GetImpl(inGraphable);
+ }
+
+ TGraphableImplPtr CreateImpl(const TIdentifier inGraphable)
+ {
+ std::pair<TGraphableImplPtr, bool> result = m_Graph.CreateImpl(inGraphable);
+ assert(result.second);
+ return result.first;
+ }
+
+ TGraphableImplPtr GetOrCreateImpl(const TIdentifier inGraphable)
+ {
+ return m_Graph.CreateImpl(inGraphable).first;
+ }
+
+ void DeleteImpl(TGraphableImplPtr item) { m_Graph.DeleteImpl(item); }
+
+ TGraphableImplList::const_iterator FindNodeIter(const TGraphableImplPtr node,
+ const TGraphableImplPtr parent) const
+ {
+ if (node && parent) {
+ TGraphableImplList::const_iterator find =
+ std::find(parent->m_Children.begin(), parent->m_Children.end(), node);
+ return find;
+ }
+ if (parent)
+ return parent->m_Children.end();
+ assert(0);
+ return TGraphableImplList::const_iterator();
+ }
+
+ long FindNode(const TGraphableImplPtr node, const TGraphableImplList &inList)
+ {
+ TGraphableImplList::const_iterator find = std::find(inList.begin(), inList.end(), node);
+ return (long)(find - inList.begin());
+ }
+
+ long FindNode(const TGraphableImplPtr node, const TGraphableImplPtr parent)
+ {
+ if (node && parent)
+ return (long)(FindNodeIter(node, parent) - parent->m_Children.begin());
+ return 0;
+ }
+
+ long ResolveOpaquePosition(TGraphableImplPtr theParent, COpaquePosition inPosition) const
+ {
+ return m_Graph.ResolveGraphPosition(theParent, ToGraph(inPosition));
+ }
+
+ long ResolveOpaquePosition(TIdentifier theParent, COpaquePosition inPosition) const
+ {
+ Graph::SGraphPosition thePos(ToGraph(inPosition));
+ return m_Graph.ResolveGraphPosition(theParent, thePos);
+ }
+
+ // Add child to either the indicated parent or the graph's root
+ // list if no parent is indicated.
+ long DoAddChild(TIdentifier inParent, TIdentifier inChild, long inIndex)
+ {
+ return m_Graph.AddChild(inParent, inChild, inIndex);
+ }
+
+ // Remove this child from either the parent list or from the roots list
+ // if the parent is unspecified.
+ // Furthermore, delete the child if specified.
+ long DoRemoveChild(TIdentifier inParent, TIdentifier inChild, bool deleteChild)
+ {
+ return m_Graph.RemoveChild(inParent, inChild, deleteChild);
+ }
+
+ // Recursively delete sub children of the graph node
+ void ClearChildren(TGraphableImplPtr theChild)
+ {
+ while (theChild->m_Children.size())
+ RemoveChild(theChild->m_Children[0]->m_GraphableID, true);
+ }
+
+ void DoMove(const TIdentifier inNode, long oldIdx, long newIdx)
+ {
+ m_Graph.Move(inNode, oldIdx, newIdx);
+ }
+
+ void MoveWithEvent(const TIdentifier inNode, long newIdx)
+ {
+ TGraphableImplPtr node(GetImpl(inNode));
+ if (node) {
+ TIdentifier theParent(node->GetParentID());
+ long oldIdx = FindNode(node, node->GetParentList(m_Graph.m_Roots));
+ if (oldIdx != newIdx) {
+ DoMove(inNode, oldIdx, newIdx);
+ if (m_Consumer != NULL) {
+ m_Consumer->OnTransaction(std::make_shared<SReorderChildTransaction>(
+ __FILE__, __LINE__, this, node->GetParentID(), inNode, oldIdx, newIdx));
+ m_Consumer->OnDoNotification(bind(&SGraphImpl::SignalChildMoved, this,
+ theParent, inNode, oldIdx, newIdx));
+ m_Consumer->OnUndoNotification(bind(&SGraphImpl::SignalChildMoved, this,
+ theParent, inNode, newIdx, oldIdx));
+ }
+ }
+ }
+ }
+
+ // Begin external mutator interfaces
+
+ void AddChild(const TIdentifier inParent, const TIdentifier inChild,
+ COpaquePosition inPosition) override
+ {
+ bool created = false;
+ TGraphableImplPtr theChild(GetImpl(inChild));
+ if (theChild == NULL) {
+ theChild = CreateImpl(inChild);
+ created = true;
+ }
+ assert(theChild->m_Parent == NULL);
+ if (theChild) {
+ long theIndex = ResolveOpaquePosition(inParent, inPosition);
+ theIndex = DoAddChild(inParent, inChild, theIndex);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>(
+ std::make_shared<SInsertChildTransaction>(
+ __FILE__, __LINE__,
+ SAddRemoveChildAction(this, inParent, inChild, theIndex, created))));
+
+ m_Consumer->OnDoNotification(
+ bind(&SGraphImpl::SignalChildAdded, this, inParent, inChild, theIndex));
+ m_Consumer->OnUndoNotification(
+ bind(&SGraphImpl::SignalChildRemoved, this, inParent, inChild, theIndex));
+ }
+ }
+ }
+
+ void RemoveChild(const TIdentifier inNode, bool deleteNode) override
+ {
+ TGraphableImplPtr theChild(GetImpl(inNode));
+ if (theChild) {
+ if (deleteNode)
+ ClearChildren(theChild);
+ TIdentifier theParent = theChild->GetParentID();
+ long removeChildIdx = DoRemoveChild(theParent, inNode, deleteNode);
+ if (m_Consumer != NULL) {
+ m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>(
+ std::make_shared<SRemoveChildTransaction>(
+ __FILE__, __LINE__, SAddRemoveChildAction(this, theParent, inNode,
+ removeChildIdx, deleteNode))));
+
+ m_Consumer->OnDoNotification(
+ bind(&SGraphImpl::SignalChildRemoved, this, theParent, inNode, removeChildIdx));
+ m_Consumer->OnUndoNotification(
+ bind(&SGraphImpl::SignalChildAdded, this, theParent, inNode, removeChildIdx));
+ }
+ }
+ }
+
+ void ReParent(const TIdentifier inNode, const TIdentifier inNewParent) override
+ {
+ RemoveChild(inNode, false);
+ AddChild(inNewParent, inNode, COpaquePosition::LAST);
+ }
+
+ void MoveChild(const TIdentifier inChild, const COpaquePosition & /*inOldIdx*/,
+ const COpaquePosition &inNewIdx) override
+ {
+ Move(inChild, inNewIdx);
+ }
+
+ void Move(const TIdentifier inNode, COpaquePosition newIdx)
+ {
+ TGraphableImplPtr node(GetImpl(inNode));
+ if (node) {
+ long requestIdx = ResolveOpaquePosition(node->GetParentID(), newIdx);
+ MoveWithEvent(inNode, requestIdx);
+ }
+ }
+
+ virtual void Move(const TIdentifier inNode, const TIdentifier inOther, bool inAfter)
+ {
+ if (inNode == inOther)
+ return;
+ TGraphableImplPtr node(GetOrCreateImpl(inNode));
+ TGraphableImplPtr other(GetOrCreateImpl(inOther));
+ if (node && other) {
+ long newPos = GetNodePosition(inOther).GetIndex();
+ long currentPos = GetNodePosition(inNode).GetIndex();
+ // We know we will do an erase followed by an insert.
+ if (node->GetParentID() == other->GetParentID()) {
+ if (newPos > currentPos) {
+ if (inAfter == false)
+ --newPos;
+ }
+
+ if (newPos < currentPos) {
+ if (inAfter == true)
+ ++newPos;
+ }
+ } else {
+ if (inAfter)
+ ++newPos;
+ }
+
+ if (node->m_Parent != other->m_Parent) {
+ RemoveChild(inNode, false);
+ TIdentifier id = other->m_Parent ? other->m_Parent->m_GraphableID : 0;
+ AddChild(id, inNode, newPos);
+ } else {
+ MoveWithEvent(inNode, newPos);
+ }
+ return;
+ }
+ assert(0);
+ }
+
+ void MoveBefore(const TIdentifier inNode, const TIdentifier inOther) override
+ {
+ Move(inNode, inOther, false);
+ }
+ void MoveAfter(const TIdentifier inNode, const TIdentifier inOther) override
+ {
+ Move(inNode, inOther, true);
+ }
+
+ virtual void Insert(const TIdentifier inNode, const TIdentifier inOther, bool after)
+ {
+ if (GetImpl(inNode) == NULL)
+ AddRoot(inNode);
+ Move(inNode, inOther, after);
+ }
+
+ void InsertBefore(const TIdentifier inNode, const TIdentifier inOther) override
+ {
+ Insert(inNode, inOther, false);
+ }
+
+ void InsertAfter(const TIdentifier inNode, const TIdentifier inOther) override
+ {
+ Insert(inNode, inOther, true);
+ }
+
+ void MoveTo(const TIdentifier inNode, const TIdentifier inNewParent,
+ const COpaquePosition &inPosition) override
+ {
+ if (GetParent(inNode) != inNewParent
+ || !(GetNodePosition(inNode) == GetChildCount(inNewParent) - 1)) {
+ RemoveChild(inNode, false);
+ AddChild(inNewParent, inNode, inPosition);
+ }
+ }
+
+ void InsertTo(const TIdentifier inNode, const TIdentifier inNewParent,
+ const COpaquePosition &inPosition) override
+ {
+ AddChild(inNewParent, inNode, inPosition);
+ }
+
+ TIdentifier GetParent(const TIdentifier inChild) const override
+ {
+ return m_Graph.GetParent(inChild);
+ }
+ long GetChildCount(const TIdentifier inParent) const override
+ {
+ return m_Graph.GetChildCount(inParent);
+ }
+
+ TIdentifier GetChild(const TIdentifier inParent, long inIndex) const override
+ {
+ return m_Graph.GetChild(inParent, inIndex);
+ }
+
+ TIdentifier GetRoot(long inIndex) const override { return m_Graph.GetRoot(inIndex); }
+
+ size_t GetRootsCount() const override { return m_Graph.GetRootsCount(); }
+
+ TIdentifier GetSibling(const TIdentifier inNode, bool inAfter) const override
+ {
+ return m_Graph.GetSibling(inNode, inAfter);
+ }
+
+ bool IsExist(const TIdentifier inGraphable) const override
+ {
+ return m_Graph.IsExist(inGraphable);
+ }
+
+ COpaquePosition GetNodePosition(const TIdentifier inNode) const override
+ {
+ return FromGraph(m_Graph.GetNodePosition(inNode));
+ }
+
+ void Clear() override { ReleaseNodes(); }
+
+ template <typename TIteratorType>
+ void GetItems(CGraphIterator &outIterator, TIteratorType begin, TIteratorType end) const
+ {
+ outIterator.ClearResults();
+ for (TIteratorType theIter = begin; theIter != end; ++theIter)
+ outIterator.AddResult((*theIter)->m_GraphableID);
+ outIterator.ApplyCriterias();
+ }
+
+ // Iterators
+ void GetRoots(CGraphIterator &outIterator) const override
+ {
+ GetItems(outIterator, m_Graph.m_Roots.begin(), m_Graph.m_Roots.end());
+ }
+
+ void GetReverseRoots(CGraphIterator &outIterator) const override
+ {
+ GetItems(outIterator, m_Graph.m_Roots.rbegin(), m_Graph.m_Roots.rend());
+ }
+
+ void GetChildren(CGraphIterator &outIterator, const TIdentifier inParent) const override
+ {
+ const TGraphableImplPtr parent = GetImpl(inParent);
+ const TGraphableImplList &childList(parent ? parent->m_Children : m_Graph.m_Roots);
+ GetItems(outIterator, childList.begin(), childList.end());
+ }
+ void GetReverseChildren(CGraphIterator &outIterator, const TIdentifier inParent) const override
+ {
+ const TGraphableImplPtr parent = GetImpl(inParent);
+ const TGraphableImplList &childList(parent ? parent->m_Children : m_Graph.m_Roots);
+ GetItems(outIterator, childList.rbegin(), childList.rend());
+ }
+ void GetDepthFirst(CGraphIterator &outIterator, const TGraphableImplPtr inRoot) const
+ {
+ if (inRoot == NULL) {
+ assert(0);
+ return;
+ }
+ outIterator.AddResult(inRoot->m_GraphableID);
+ for (size_t idx = 0, size = inRoot->m_Children.size(); idx < size; ++idx)
+ GetDepthFirst(outIterator, inRoot->m_Children[idx]);
+ }
+
+ void GetDepthFirst(CGraphIterator &outIterator, const TIdentifier inRoot) const override
+ {
+ if (inRoot != 0) {
+ TGraphableImplPtr root = GetImpl(inRoot);
+ if (root)
+ GetDepthFirst(outIterator, root);
+ else {
+ assert(0);
+ }
+ } else {
+ for (size_t idx = 0, size = m_Graph.m_Roots.size(); idx < size; ++idx)
+ GetDepthFirst(outIterator, m_Graph.m_Roots[idx]);
+ }
+ outIterator.ApplyCriterias();
+ }
+
+ void SignalChildAdded(TIdentifier inParent, TIdentifier inChild, long inPos)
+ {
+ m_ChildAddedSignal(inParent, inChild, inPos);
+ }
+ void SignalChildRemoved(TIdentifier inParent, TIdentifier inChild, long inPos)
+ {
+ m_ChildRemoveSignal(inParent, inChild, inPos);
+ }
+ void SignalChildMoved(TIdentifier inParent, TIdentifier inChild, long inOldIdx, long inNewIdx)
+ {
+ m_ChildMoved(inParent, inChild, inOldIdx, inNewIdx);
+ }
+ // Signals
+ // Always in the form of parent,child.
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ ConnectChildAdded(std::function<void(TIdentifier, TIdentifier, long)> inCallback) override
+ {
+ return CONNECT(m_ChildAddedSignal.connect(inCallback));
+ }
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ ConnectChildRemoved(std::function<void(TIdentifier, TIdentifier, long)> inCallback) override
+ {
+ return CONNECT(m_ChildRemoveSignal.connect(inCallback));
+ }
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ ConnectChildMoved(std::function<void(TIdentifier, TIdentifier, long, long)> inCallback) override
+ {
+ return CONNECT(m_ChildMoved.connect(inCallback));
+ }
+
+ Graph::SGraphImpl<int, int> m_Graph;
+ std::shared_ptr<UICDM::ITransactionConsumer> m_Consumer;
+
+ signal<void(TIdentifier, TIdentifier, long)> m_ChildAddedSignal;
+ signal<void(TIdentifier, TIdentifier, long)> m_ChildRemoveSignal;
+ signal<void(TIdentifier, TIdentifier, long, long)> m_ChildMoved;
+};
+
+// Implementation of the transaction helpers.
+void SAddRemoveChildAction::AddChild()
+{
+ m_Graph->DoAddChild(m_Parent, m_Child, m_Index);
+}
+void SAddRemoveChildAction::RemoveChild()
+{
+ m_Graph->DoRemoveChild(m_Parent, m_Child, m_DeleteOnRemove);
+}
+void SReorderChildTransaction::Do()
+{
+ m_Graph->DoMove(m_Child, m_OldIndex, m_NewIndex);
+}
+void SReorderChildTransaction::Undo()
+{
+ m_Graph->DoMove(m_Child, m_NewIndex, m_OldIndex);
+}
+
+} // end anonymous namespace
+
+//==============================================================================
+/**
+ * CTOR
+ */
+CGraphIterator::CGraphIterator()
+{
+ Reset();
+}
+
+//==============================================================================
+/**
+ * CTOR
+ * Accepts a single criteria
+ */
+CGraphIterator::CGraphIterator(const SGraphableCriteria &inCriteria)
+{
+ m_Criterias.push_back(inCriteria);
+}
+
+//==============================================================================
+/**
+ * CTOR
+ * Accepts a list of criterias
+ */
+CGraphIterator::CGraphIterator(const TCriteriaList &inCriterias)
+ : m_Criterias(inCriterias)
+{
+}
+
+//==============================================================================
+/**
+ * SIterator override
+ * Returns true when iterator is at it's end
+ */
+bool CGraphIterator::IsDone()
+{
+ return m_Current == m_End;
+}
+
+//==============================================================================
+/**
+ * SIterator override
+ * Advance iterator
+ */
+void CGraphIterator::operator++()
+{
+ ++m_Current;
+}
+
+//==============================================================================
+/**
+ * SIterator override
+ * Advance iterator by a certain amount
+ */
+void CGraphIterator::operator+=(const long inNumToInc)
+{
+ m_Current += inNumToInc;
+}
+
+//==============================================================================
+/**
+ * SIterator override
+ * Returns current item
+ */
+TIdentifier CGraphIterator::GetCurrent()
+{
+ return *m_Current;
+}
+
+//==============================================================================
+/**
+ * Intializes iterator back to start state
+ */
+void CGraphIterator::Reset()
+{
+ m_Current = m_Results.begin();
+ m_End = m_Results.end();
+}
+
+//==============================================================================
+/**
+ * Clear the results
+ */
+void CGraphIterator::ClearResults()
+{
+ m_Results.clear();
+ Reset();
+}
+
+//==============================================================================
+/**
+ * Get the size of results
+ */
+size_t CGraphIterator::GetCount() const
+{
+ return m_Results.size();
+}
+
+//==============================================================================
+/**
+ * Get the result at certain index
+ */
+TIdentifier CGraphIterator::GetResult(size_t inIndex) const
+{
+ return m_Results[inIndex];
+}
+
+//==============================================================================
+/**
+ * Adds a set of criterias to the existing set
+ */
+void CGraphIterator::operator+=(const TCriteriaList &inCriterias)
+{
+ m_Criterias.insert(m_Criterias.end(), inCriterias.begin(), inCriterias.end());
+}
+
+//==============================================================================
+/**
+ * Adds a new criteria to the existing set
+ */
+void CGraphIterator::operator+=(const SGraphableCriteria &inCriteria)
+{
+ m_Criterias.push_back(inCriteria);
+}
+
+//==============================================================================
+/**
+ * Clears the current list of criterias
+ */
+void CGraphIterator::ClearCriterias()
+{
+ m_Criterias.clear();
+}
+
+//==============================================================================
+/**
+ * Evaluates an criterias for an iterator
+ */
+void CGraphIterator::ApplyCriterias()
+{
+ TCriteriaList::const_iterator theIter = m_Criterias.begin();
+ TCriteriaList::const_iterator theEnd = m_Criterias.end();
+
+ for (; theIter != theEnd; ++theIter) {
+ const SGraphableCriteria &theCriteria = *theIter;
+ switch (theCriteria.m_Type) {
+ case ECriteriaType_Sorter:
+ // use a lamda to workaround a clang + libstdc++ (from g++) bug
+ // https://bugs.llvm.org/show_bug.cgi?id=24115
+ // https://bugs.llvm.org/show_bug.cgi?id=31535
+ std::stable_sort(m_Results.begin(), m_Results.end(),
+ [&theCriteria](const auto &lhs, const auto &rhs) -> bool {
+ return theCriteria.m_SortFunc(lhs, rhs);
+ });
+ break;
+
+ case ECriteriaType_Filter:
+ TGraphableList::iterator theNewEnd;
+ theNewEnd =
+ std::remove_if(m_Results.begin(), m_Results.end(),
+ theCriteria.m_FilterFunc); // exclude those that satisfy the filter
+ m_Results.erase(theNewEnd, m_Results.end()); // clear away the junk
+ break;
+ }
+ }
+
+ // Get this iterator ready for use
+ Reset();
+}
+
+std::shared_ptr<CGraph> CGraph::CreateGraph(TIdentifier inRoot)
+{
+ return std::static_pointer_cast<CGraph>(std::make_shared<SGraphImpl>(inRoot));
+}
diff --git a/src/Authoring/Common/Code/Graph/Graph.h b/src/Authoring/Common/Code/Graph/Graph.h
new file mode 100644
index 00000000..86e3d7ca
--- /dev/null
+++ b/src/Authoring/Common/Code/Graph/Graph.h
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Include
+//==============================================================================
+#pragma once
+#include <vector>
+#include <map>
+#include "SIterator.h"
+
+namespace UICDM {
+class ITransactionConsumer;
+class ISignalConnection;
+}
+
+namespace Q3DStudio {
+
+typedef int TIdentifier;
+typedef std::vector<TIdentifier> TGraphableList;
+
+typedef enum _ECriteriaType {
+ ECriteriaType_Sorter, //< Sorts using a compare function
+ ECriteriaType_Filter, //< Filters using a boolean function
+ ECriteriaType_Unknown
+} ECriteriaType;
+
+typedef std::function<bool(const TIdentifier inFirst, const TIdentifier inSecond)> TSorter;
+typedef std::function<bool(const TIdentifier inGraphable)> TFilter;
+typedef bool (*TSorterFptr)(const TIdentifier inFirst, const TIdentifier inSecond);
+typedef bool (*TFilterFptr)(const TIdentifier inGraphable);
+
+typedef struct _SGraphableCriteria
+{
+ ECriteriaType m_Type; //< Criteria type
+ TSorter m_SortFunc; //< Sort function
+ TFilter m_FilterFunc; //< Filter function
+
+ _SGraphableCriteria(const TSorter &inFunction)
+ : m_Type(ECriteriaType_Sorter)
+ , m_SortFunc(inFunction)
+ , m_FilterFunc(NULL)
+ {
+ }
+
+ _SGraphableCriteria(const TFilter &inFunction)
+ : m_Type(ECriteriaType_Filter)
+ , m_SortFunc(NULL)
+ , m_FilterFunc(inFunction)
+ {
+ }
+
+ _SGraphableCriteria(const TSorterFptr inFunction)
+ : m_Type(ECriteriaType_Sorter)
+ , m_SortFunc(inFunction)
+ , m_FilterFunc(NULL)
+ {
+ }
+
+ _SGraphableCriteria(const TFilterFptr inFunction)
+ : m_Type(ECriteriaType_Filter)
+ , m_SortFunc(NULL)
+ , m_FilterFunc(inFunction)
+ {
+ }
+
+} SGraphableCriteria;
+
+typedef std::vector<SGraphableCriteria> TCriteriaList;
+
+//==============================================================================
+/**
+ * Generic iterator class that contains a list of criterias (sorters or filters).
+ * Criterias are applied in the order they are added.
+ * Results can then be obtained from the class.
+ */
+class CGraphIterator : public CSIterator<TIdentifier>
+{
+public:
+ CGraphIterator();
+ CGraphIterator(const SGraphableCriteria &inCriteria);
+ CGraphIterator(const TCriteriaList &inCriterias);
+
+ virtual ~CGraphIterator() {}
+
+ // Hide copy constructor
+ // Copying an iterator could be really heavy, consider if there are alternatives to copying if
+ // possible
+protected:
+ CGraphIterator &operator=(const CGraphIterator &) { return *this; };
+ CGraphIterator(const CGraphIterator &){};
+
+ // CSIterator overrides
+public:
+ bool IsDone() override;
+ void operator++() override;
+ void operator+=(const long inNumToInc) override;
+ TIdentifier GetCurrent() override;
+
+public:
+ size_t GetCount() const;
+ TIdentifier GetResult(size_t inIndex) const;
+ void Reset();
+ void ClearResults();
+ void AddResult(TIdentifier result) { m_Results.push_back(result); }
+
+ // Criteria management
+public:
+ void operator+=(const SGraphableCriteria &inCriteria);
+ void operator+=(const TCriteriaList &inCriterias);
+ void ClearCriterias();
+ void ApplyCriterias();
+
+protected:
+ friend class CGraph;
+ TGraphableList m_Results; //< Results list
+ TCriteriaList m_Criterias; //< Criterias list
+
+protected:
+ TGraphableList::iterator m_Current; //< Current std::iterator
+ TGraphableList::const_iterator m_End; //< End std::iterator
+};
+
+//==============================================================================
+/**
+ * Opaque implementation for storing node position for move/insert operations
+ */
+class COpaquePosition
+{
+public:
+ static const COpaquePosition FIRST;
+ static const COpaquePosition LAST;
+ static const long s_Invalid = -2;
+
+ COpaquePosition()
+ : m_Index(s_Invalid)
+ {
+ }
+ COpaquePosition(long inIndex)
+ : m_Index(inIndex)
+ {
+ }
+ bool operator==(const COpaquePosition &other) const { return m_Index == other.m_Index; }
+ long GetIndex() const { return m_Index; }
+ bool IsValid() const { return m_Index != s_Invalid; }
+
+private:
+ long m_Index;
+};
+//==============================================================================
+/**
+ * A CGraph is a directed graph with a set of roots nodes. Any node without a
+ * parent is assumed to be a root node. Removing nodes from the graph
+ * recursively removes children and the graph recycles their internal
+ * internal representation.
+ * Children of nodes are ordered as are root nodes.
+ */
+class CGraph
+{
+public:
+ virtual ~CGraph(){}
+ virtual void SetConsumer(std::shared_ptr<UICDM::ITransactionConsumer> inConsumer) = 0;
+
+ /**
+ * Add a new child to the graph. If inParent == NULL then it is added to the list of roots.
+ */
+ virtual void AddChild(const TIdentifier inParent, const TIdentifier inChild,
+ COpaquePosition inIndex = COpaquePosition::LAST) = 0;
+
+ /**
+ * If deleteNode is true, this recursively deletes all children also to avoid
+ * dangling pointers. If deleteNode is false, then the child is in limbo, neither with a
+ *parent
+ * Nor in the root list.
+ */
+ virtual void RemoveChild(const TIdentifier inChild, bool deleteNode) = 0;
+
+ /**
+ * Postcondition of remove node is that IsExist = false, recursively delete any attached
+ *children
+ */
+ void RemoveNode(const TIdentifier inChild) { RemoveChild(inChild, true); }
+ /**
+ * Move a child from oldIdx (which must be its existing index) to a new index
+ */
+ virtual void MoveChild(const TIdentifier inChild, const COpaquePosition &inOldIdx,
+ const COpaquePosition &inNewIdx) = 0;
+ /**
+ * Add a new root to the graph.
+ */
+ void AddRoot(const TIdentifier inRoot) { AddChild(0, inRoot); }
+
+ /**
+ * Graph mutators that can be described by the operations above.
+ *
+ */
+ virtual void ReParent(const TIdentifier inNode, const TIdentifier inNewParent) = 0;
+ /**
+ * Move requires the node to be in existance. InBefore or inAfter do not need
+ * to share a parent with inNode.
+ */
+ virtual void MoveBefore(const TIdentifier inNode, const TIdentifier inBefore) = 0;
+ virtual void MoveAfter(const TIdentifier inNode, const TIdentifier inAfter) = 0;
+ /**
+ * Insert will create the node before placing it in the correct spot.
+ * InBefore or inAfter do not need to share a parent with inNode.
+ */
+ virtual void InsertBefore(const TIdentifier inNode, const TIdentifier inBefore) = 0;
+ virtual void InsertAfter(const TIdentifier inNode, const TIdentifier inAfter) = 0;
+
+ /**
+ * Move a node to a different parent. This help you when you don't know the child sibling.
+ */
+ virtual void MoveTo(const TIdentifier inNode, const TIdentifier inNewParent,
+ const COpaquePosition &inPosition) = 0;
+ virtual void InsertTo(const TIdentifier inNode, const TIdentifier inNewParent,
+ const COpaquePosition &inPosition) = 0;
+
+ // Not an undoable operation!!
+ virtual void Clear() = 0;
+
+ // Simple graph queries
+ virtual TIdentifier GetParent(const TIdentifier inChild) const = 0;
+ virtual long GetChildCount(const TIdentifier inParent) const = 0;
+ virtual TIdentifier GetChild(const TIdentifier inParent, long inIndex) const = 0;
+ virtual TIdentifier GetRoot(long inIndex) const = 0;
+ virtual size_t GetRootsCount() const = 0;
+
+ /**
+ * Return the sibling of this node. Node may be a root node.
+ */
+ virtual TIdentifier GetSibling(const TIdentifier inNode, bool inAfter) const = 0;
+
+ virtual bool IsExist(const TIdentifier inGraphable) const = 0;
+ virtual COpaquePosition GetNodePosition(const TIdentifier inNode) const = 0;
+
+ // Iterators
+ virtual void GetRoots(CGraphIterator &outIterator) const = 0;
+ virtual void GetReverseRoots(CGraphIterator &outIterator) const = 0;
+ virtual void GetChildren(CGraphIterator &outIterator, const TIdentifier inParent) const = 0;
+ virtual void GetReverseChildren(CGraphIterator &outIterator,
+ const TIdentifier inParent) const = 0;
+ virtual void GetDepthFirst(CGraphIterator &outIterator, const TIdentifier inRoot) const = 0;
+
+ // Signals
+ // Always in the form of parent,child,childIdx
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ ConnectChildAdded(std::function<void(TIdentifier, TIdentifier, long)> inCallback) = 0;
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ ConnectChildRemoved(std::function<void(TIdentifier, TIdentifier, long)> inCallback) = 0;
+ // parent,child,oldpos,newpos
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ ConnectChildMoved(std::function<void(TIdentifier, TIdentifier, long, long)> inCallback) = 0;
+
+ static std::shared_ptr<CGraph> CreateGraph(TIdentifier inRoot = 0);
+};
+
+typedef std::shared_ptr<CGraph> TGraphPtr;
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Common/Code/Graph/GraphImpl.h b/src/Authoring/Common/Code/Graph/GraphImpl.h
new file mode 100644
index 00000000..5d279eb1
--- /dev/null
+++ b/src/Authoring/Common/Code/Graph/GraphImpl.h
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef GRAPHIMPLH
+#define GRAPHIMPLH
+#include <vector>
+#include <unordered_map>
+#include "GraphPosition.h"
+
+namespace Q3DStudio {
+namespace Graph {
+
+ using namespace std;
+
+ template <typename TKeyType, typename TValueType>
+ struct SGraphNode
+ {
+ typedef SGraphNode<TKeyType, TValueType> TThisType;
+ typedef vector<TThisType *> TNodeList;
+
+ SGraphNode(const TKeyType &inIdentifier, const TValueType &inNodeData = TValueType())
+ : m_GraphableID(inIdentifier)
+ , m_Data(inNodeData)
+ , m_Parent(NULL)
+ {
+ }
+
+ SGraphNode(const SGraphNode&) = delete;
+ SGraphNode& operator=(const SGraphNode&) = delete;
+
+ TNodeList &GetParentList(TNodeList &inRoots)
+ {
+ return m_Parent != NULL ? m_Parent->m_Children : inRoots;
+ }
+ const TNodeList &GetParentList(const TNodeList &inRoots) const
+ {
+ return m_Parent != NULL ? m_Parent->m_Children : inRoots;
+ }
+ TKeyType GetParentID() const { return m_Parent != NULL ? m_Parent->m_GraphableID : 0; }
+ TKeyType m_GraphableID; //< Opaque identifier
+ TValueType m_Data;
+ TThisType *m_Parent; //< Parent graphable
+ TNodeList m_Children; //< Children graphables
+ };
+
+ // You are free to define different traits for different key types.
+ template <typename TKeyType>
+ struct SGraphKeyTraits
+ {
+ bool IsValid(const TKeyType &inKey) { return inKey != 0; }
+ TKeyType Invalid() { return 0; }
+ };
+
+ template <typename TKeyType, typename TValueType>
+ struct SGraphImpl
+ {
+ Q_DISABLE_COPY(SGraphImpl)
+ SGraphImpl() = default;
+
+ public:
+ typedef SGraphNode<TKeyType, TValueType> TNodeType;
+ typedef TNodeType *TNodePtr;
+ typedef typename TNodeType::TNodeList TNodeList;
+ typedef std::unordered_map<TKeyType, TNodePtr> TLookupMap;
+
+ TNodeList m_Roots; //< Graph roots
+ TLookupMap m_LookupMap; //< Mapping between TKeyType and TNodeType
+
+ ~SGraphImpl() { ReleaseNodes(); }
+
+ // Graph node lifetime and manipulation helpers
+ void ReleaseNodes()
+ {
+ m_Roots.clear();
+ for (typename TLookupMap::iterator iter = m_LookupMap.begin(), end = m_LookupMap.end();
+ iter != end; ++iter) {
+ delete iter->second;
+ }
+ m_LookupMap.clear();
+ }
+
+ TNodePtr GetImpl(const TKeyType &inGraphable) const
+ {
+ if (SGraphKeyTraits<TKeyType>().IsValid(inGraphable)) {
+ typename TLookupMap::const_iterator theResult = m_LookupMap.find(inGraphable);
+ if (theResult != m_LookupMap.end())
+ return theResult->second;
+ }
+ return NULL;
+ }
+
+ pair<TNodePtr, bool> CreateImpl(const TKeyType &inGraphable,
+ const TValueType &inValue = TValueType())
+ {
+ if (SGraphKeyTraits<TKeyType>().IsValid(inGraphable)) {
+ TNodePtr theGraphableImpl = NULL;
+ std::pair<typename TLookupMap::iterator, bool> theResult =
+ m_LookupMap.insert(std::make_pair(inGraphable, theGraphableImpl));
+
+ if (theResult.second) {
+ theGraphableImpl = new TNodeType(inGraphable, inValue);
+ theResult.first->second = theGraphableImpl;
+ }
+ return make_pair(theResult.first->second, theResult.second);
+ }
+ assert(0);
+ return make_pair(TNodePtr(NULL), false);
+ }
+
+ void SetData(const TKeyType &inGraphable, const TValueType &inData)
+ {
+ pair<TNodePtr, bool> theNode = CreateImpl(inGraphable, inData);
+ if (theNode.second == false)
+ theNode.first->m_Data = inData;
+ }
+
+ void DeleteImpl(TNodePtr item)
+ {
+ if (item) {
+ m_LookupMap.erase(item->m_GraphableID);
+ delete item;
+ }
+ }
+
+ typename TNodeList::const_iterator FindNodeIter(const TNodePtr node,
+ const TNodePtr parent) const
+ {
+ if (node && parent) {
+ typename TNodeList::const_iterator find =
+ std::find(parent->m_Children.begin(), parent->m_Children.end(), node);
+ return find;
+ }
+ if (parent)
+ return parent->m_Children.end();
+ assert(0);
+ return TNodeList::const_iterator();
+ }
+
+ long FindNode(const TNodePtr node, const TNodeList &inList) const
+ {
+ typename TNodeList::const_iterator find = std::find(inList.begin(), inList.end(), node);
+ return (long)(find - inList.begin());
+ }
+
+ long FindNode(const TNodePtr node, const TNodePtr parent) const
+ {
+ if (node && parent)
+ return (long)(FindNodeIter(node, parent) - parent->m_Children.begin());
+ return 0;
+ }
+
+ long ResolveGraphPosition(TNodePtr theParent, SGraphPosition inPosition) const
+ {
+ const TNodeList &childList(theParent ? theParent->m_Children : m_Roots);
+ return min(inPosition.GetIndex(), (long)childList.size());
+ }
+
+ long ResolveGraphPosition(TKeyType theParent, SGraphPosition inPosition) const
+ {
+ return ResolveGraphPosition(GetImpl(theParent), inPosition);
+ }
+
+ // Add child to either the indicated parent or the graph's root
+ // list if no parent is indicated.
+ long AddChild(TKeyType inParent, TKeyType inChild, SGraphPosition inIndex)
+ {
+ TNodePtr theChild(CreateImpl(inChild).first);
+ assert(theChild->m_Parent == NULL);
+ if (inParent) {
+ TNodePtr theParent(GetImpl(inParent));
+ assert(theParent);
+ if (theParent == NULL)
+ return 0;
+ theChild->m_Parent = theParent;
+ }
+ long theIndex = ResolveGraphPosition(theChild->m_Parent, inIndex);
+
+ TNodeList &childList = theChild->GetParentList(m_Roots);
+
+ if (theIndex <= (long)childList.size()) {
+ childList.insert(childList.begin() + theIndex, theChild);
+ return theIndex;
+ } else {
+ childList.push_back(theChild);
+ return (long)childList.size() - 1;
+ }
+ return 0;
+ }
+
+ void AddRoot(const TKeyType inRoot) { AddChild(0, inRoot, SGraphPosition::SEnd()); }
+
+ // Remove this child from either the parent list or from the roots list
+ // if the parent is unspecified.
+ // Furthermore, delete the child if specified.
+ long RemoveChild(TKeyType inParent, TKeyType inChild, bool deleteChild)
+ {
+ TNodePtr theChild(GetImpl(inChild));
+
+ if (theChild == NULL || theChild->GetParentID() != inParent)
+ return 0;
+ if (deleteChild) {
+ while (theChild->m_Children.size())
+ RemoveChild(inChild, theChild->m_Children.back()->m_GraphableID, deleteChild);
+
+ assert(theChild->m_Children.size() == 0);
+ }
+
+ TNodeList &childList = theChild->GetParentList(m_Roots);
+ assert(theChild->m_Parent == GetImpl(inParent));
+ theChild->m_Parent = NULL;
+
+ long findIdx = FindNode(theChild, childList);
+ if (findIdx < (long)childList.size())
+ childList.erase(childList.begin() + findIdx);
+ if (deleteChild)
+ DeleteImpl(theChild);
+
+ return findIdx;
+ }
+
+ long RemoveChild(TKeyType inChild, bool deleteChild)
+ {
+ TNodePtr theChild(GetImpl(inChild));
+ if (theChild)
+ return RemoveChild(theChild->GetParentID(), theChild->m_GraphableID, deleteChild);
+ return 0;
+ }
+
+ void Move(const TKeyType inNode, long oldIdx, long newIdx)
+ {
+ TNodePtr node(GetImpl(inNode));
+ if (node) {
+ TNodeList &childList(node->GetParentList(m_Roots));
+ assert(oldIdx < (long)childList.size());
+ assert(newIdx < (long)childList.size());
+ assert(childList.at(oldIdx) == node);
+ childList.erase(childList.begin() + oldIdx);
+ childList.insert(childList.begin() + newIdx, node);
+ assert(childList.at(newIdx) == node);
+ }
+ }
+
+ void ReParent(const TKeyType inNode, const TKeyType inNewParent)
+ {
+ RemoveChild(inNode, false);
+ AddChild(inNewParent, inNode, SGraphPosition::SEnd());
+ }
+
+ void MoveChild(const TKeyType inChild, const SGraphPosition & /*inOldIdx*/,
+ const SGraphPosition &inNewIdx)
+ {
+ Move(inChild, inNewIdx);
+ }
+
+ void Move(const TKeyType inNode, SGraphPosition newIdx)
+ {
+ TNodePtr node(GetImpl(inNode));
+ if (node) {
+ SGraphPosition currentPos = GetNodePosition(inNode);
+ long requestIdx = ResolveGraphPosition(node->GetParentID(), newIdx);
+ Move(inNode, currentPos.GetIndex(), requestIdx);
+ }
+ }
+
+ void Move(const TKeyType inNode, const TKeyType inOther, bool inAfter)
+ {
+ if (inNode == inOther)
+ return;
+ TNodePtr node(GetImpl(inNode));
+ TNodePtr other(GetImpl(inOther));
+ if (node && other) {
+ long newPos = GetNodePosition(inOther).GetIndex();
+ long currentPos = GetNodePosition(inNode).GetIndex();
+ // We know we will do an erase followed by an insert.
+ if (node->GetParentID() == other->GetParentID()) {
+ if (newPos > currentPos) {
+ if (inAfter == false)
+ --newPos;
+ }
+
+ if (newPos < currentPos) {
+ if (inAfter == true)
+ ++newPos;
+ }
+ } else {
+ if (inAfter)
+ ++newPos;
+ }
+
+ if (node->m_Parent != other->m_Parent) {
+ RemoveChild(inNode, false);
+ TKeyType id = other->m_Parent ? other->m_Parent->m_GraphableID : 0;
+ AddChild(id, inNode, newPos);
+ } else {
+ Move(inNode, newPos);
+ }
+ return;
+ }
+ assert(0);
+ }
+
+ void MoveBefore(const TKeyType inNode, const TKeyType inOther)
+ {
+ Move(inNode, inOther, false);
+ }
+ void MoveAfter(const TKeyType inNode, const TKeyType inOther)
+ {
+ Move(inNode, inOther, true);
+ }
+
+ void Insert(const TKeyType inNode, const TKeyType inOther, bool after)
+ {
+ if (GetImpl(inNode) == NULL)
+ AddRoot(inNode);
+ Move(inNode, inOther, after);
+ }
+
+ void InsertBefore(const TKeyType inNode, const TKeyType inOther)
+ {
+ Insert(inNode, inOther, false);
+ }
+
+ void InsertAfter(const TKeyType inNode, const TKeyType inOther)
+ {
+ Insert(inNode, inOther, true);
+ }
+
+ void MoveTo(const TKeyType inNode, const TKeyType inNewParent,
+ const SGraphPosition &inPosition)
+ {
+ if (GetParent(inNode) != inNewParent
+ || !(GetNodePosition(inNode) == GetChildCount(inNewParent) - 1)) {
+ RemoveChild(inNode, false);
+ AddChild(inNewParent, inNode, inPosition);
+ }
+ }
+
+ void InsertTo(const TKeyType inNode, const TKeyType inNewParent,
+ const SGraphPosition &inPosition)
+ {
+ AddChild(inNewParent, inNode, inPosition);
+ }
+
+ TKeyType GetParent(const TKeyType inChild) const
+ {
+ TNodePtr node = GetImpl(inChild);
+ if (node && node->m_Parent)
+ return node->m_Parent->m_GraphableID;
+ return 0;
+ }
+
+ long GetChildCount(const TKeyType inParent) const
+ {
+ TNodePtr node = GetImpl(inParent);
+ if (node)
+ return (long)node->m_Children.size();
+ return 0;
+ }
+
+ TKeyType GetChild(const TKeyType inParent, long inIndex) const
+ {
+ TNodePtr node = GetImpl(inParent);
+ if (node && inIndex <= (long)node->m_Children.size())
+ return node->m_Children[inIndex]->m_GraphableID;
+ return 0;
+ }
+
+ TKeyType GetRoot(long inIndex) const
+ {
+ if (inIndex < (long)m_Roots.size())
+ return m_Roots[inIndex]->m_GraphableID;
+ return 0;
+ }
+
+ size_t GetRootsCount() const { return m_Roots.size(); }
+
+ TKeyType GetSibling(const TKeyType inNode, bool inAfter) const
+ {
+ TNodePtr theNode = GetImpl(inNode);
+ if (theNode) {
+ const TNodeList &childList(theNode->GetParentList(m_Roots));
+ typename TNodeList::const_iterator theChildPosition =
+ std::find(childList.begin(), childList.end(), theNode);
+ if (inAfter) {
+ if (theChildPosition != childList.end())
+ ++theChildPosition;
+ if (theChildPosition != childList.end())
+ return (*theChildPosition)->m_GraphableID;
+ } else {
+ if (theChildPosition != childList.begin()) {
+ --theChildPosition;
+ return (*theChildPosition)->m_GraphableID;
+ }
+ }
+ }
+ return SGraphKeyTraits<TKeyType>().Invalid();
+ }
+
+ bool IsExist(const TKeyType inGraphable) const
+ {
+ typename TLookupMap::const_iterator theFind = m_LookupMap.find(inGraphable);
+ return theFind != m_LookupMap.end();
+ }
+
+ SGraphPosition GetNodePosition(const TKeyType inNode) const
+ {
+ TNodePtr theNode(GetImpl(inNode));
+ if (theNode) {
+ const TNodeList &childList(theNode->GetParentList(m_Roots));
+ typename TNodeList::const_iterator thePos =
+ std::find(childList.begin(), childList.end(), theNode);
+ return (long)(thePos - childList.begin());
+ }
+ return SGraphPosition::SInvalid();
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/Graph/GraphPosition.h b/src/Authoring/Common/Code/Graph/GraphPosition.h
new file mode 100644
index 00000000..57addee8
--- /dev/null
+++ b/src/Authoring/Common/Code/Graph/GraphPosition.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef GRAPHPOSITIONH
+#define GRAPHPOSITIONH
+#include <boost/variant.hpp>
+#include <boost/operators.hpp>
+
+namespace Q3DStudio {
+namespace Graph {
+
+ using namespace boost;
+ using namespace std;
+
+ struct SGraphPosition : public equality_comparable<SGraphPosition>
+ {
+ struct SInvalid
+ {
+ SInvalid() {}
+ };
+ struct SBegin
+ {
+ SBegin() {}
+ };
+ struct SEnd
+ {
+ SEnd() {}
+ };
+ typedef boost::variant<SEnd, SBegin, long, SInvalid> TPositionType;
+
+ enum Enum {
+ Invalid,
+ Begin,
+ End,
+ Index,
+ };
+
+ struct SPosTypeVisitor : boost::static_visitor<Enum>
+ {
+ Enum operator()(SBegin) const { return Begin; }
+ Enum operator()(SEnd) const { return End; }
+ Enum operator()(SInvalid) const { return Invalid; }
+ Enum operator()(long) const { return Index; }
+ };
+
+ TPositionType m_Position;
+
+ SGraphPosition() {}
+ SGraphPosition(const SGraphPosition &inOther)
+ : m_Position(inOther.m_Position)
+ {
+ }
+ template <typename TDataType>
+ SGraphPosition(const TDataType &dtype)
+ : m_Position(dtype)
+ {
+ }
+
+ Enum GetType() const { return boost::apply_visitor(SPosTypeVisitor(), m_Position); }
+ bool operator==(const SGraphPosition &inOther)
+ {
+ if (GetType() != inOther.GetType())
+ return false;
+ if (GetType() == Index)
+ return get<long>(m_Position) == get<long>(inOther.m_Position);
+ return true;
+ }
+ long GetIndex() const
+ {
+ switch (GetType()) {
+ case Begin:
+ return 0;
+ case End:
+ return LONG_MAX;
+ case Index:
+ return get<long>(m_Position);
+ default:;
+ }
+ assert(0);
+ return 0;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/Graph/IGraphable.h b/src/Authoring/Common/Code/Graph/IGraphable.h
new file mode 100644
index 00000000..871a4247
--- /dev/null
+++ b/src/Authoring/Common/Code/Graph/IGraphable.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_IGRAPHABLE_H
+#define INCLUDED_IGRAPHABLE_H 1
+#pragma once
+
+//==============================================================================
+/**
+ * Arbitrary IGraphable interface
+ */
+class IGraphable
+{
+public:
+ virtual long GetGraphableType() const = 0; //< Override this to return RTTI type
+};
+
+typedef enum _EGraphableType { EGRAPHABLE_TYPE_NONE, EGRAPHABLE_TYPE_ASSET } EGraphableType;
+
+#endif // INCLUDED_IGRAPHABLE_H
diff --git a/src/Authoring/Common/Code/HiResTimer.cpp b/src/Authoring/Common/Code/HiResTimer.cpp
new file mode 100644
index 00000000..002bc683
--- /dev/null
+++ b/src/Authoring/Common/Code/HiResTimer.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#include "HiResTimer.h"
+
+//=============================================================================
+/**
+ * Construct a new HiRes Timer, the timer starts out stopped.
+ */
+CHiResTimer::CHiResTimer()
+ : m_IsRunning(false)
+{
+}
+
+CHiResTimer::~CHiResTimer()
+{
+}
+
+//=============================================================================
+/**
+ * Start the timer running, this will store the amount of time until Stop is called.
+ */
+void CHiResTimer::Start()
+{
+ if (!m_IsRunning) {
+ m_StartTime.start();
+ m_IsRunning = true;
+ }
+}
+
+//=============================================================================
+/**
+ * Stop the timer from running, this will store the elapsed time from when
+ * Start was called for later access.
+ */
+void CHiResTimer::Stop()
+{
+ if (m_IsRunning) {
+ m_elapsed = m_StartTime.nsecsElapsed();
+ m_IsRunning = false;
+ }
+}
+
+//=============================================================================
+/**
+ * Get the number of usecs elapsed since start was called.
+ * If the timer is running then this will return the time from when start was
+ * called. If the timer is stopped then this will return the amount of time
+ * between the start and last stop.
+ */
+TLarge CHiResTimer::ElapsedMicroSecs()
+{
+ if (m_IsRunning) {
+ return m_StartTime.nsecsElapsed() / 1000;
+ }
+ return m_elapsed / 1000;
+}
+
+//=============================================================================
+/**
+ * Get the number of msecs elapsed since start was called.
+ * If the timer is running then this will return the time from when start was
+ * called. If the timer is stopped then this will return the amount of time
+ * between the start and last stop.
+ */
+long CHiResTimer::ElapsedMilliSecs()
+{
+ if (m_IsRunning) {
+ return m_StartTime.nsecsElapsed() / 1000000;
+ }
+ return m_elapsed / 1000000;
+}
+
+void CHiResTimer::Reset()
+{
+ m_StartTime.restart();
+}
diff --git a/src/Authoring/Common/Code/HiResTimer.h b/src/Authoring/Common/Code/HiResTimer.h
new file mode 100644
index 00000000..5efaff08
--- /dev/null
+++ b/src/Authoring/Common/Code/HiResTimer.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_HI_RES_TIMER_H
+#define INCLUDED_HI_RES_TIMER_H 1
+
+#pragma once
+
+#include "UICLargeInteger.h"
+
+#include <QElapsedTimer>
+
+class CHiResTimer
+{
+public:
+ CHiResTimer();
+ virtual ~CHiResTimer();
+
+ void Start();
+ void Stop();
+ void Reset();
+
+ TLarge ElapsedMicroSecs();
+ long ElapsedMilliSecs();
+
+protected:
+ QElapsedTimer m_StartTime;
+ qint64 m_elapsed;
+
+ bool m_IsRunning;
+};
+#endif // INCLUDED_HI_RES_TIMER_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/IO/BufferedInputStream.cpp b/src/Authoring/Common/Code/IO/BufferedInputStream.cpp
new file mode 100644
index 00000000..81cb4452
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/BufferedInputStream.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BufferedInputStream.h"
+#include "IOLibraryException.h"
+#include <string.h>
+#include <sstream>
+
+CBufferedInputStream::CBufferedInputStream(CInputStream *inInputStream, long inBufferLength)
+ : m_InputStream(inInputStream)
+{
+ const long MAXBUFFERLENGTH = 33554432; // 32MB
+ if (inBufferLength > MAXBUFFERLENGTH)
+ m_BufferLength = MAXBUFFERLENGTH;
+ else
+ m_BufferLength = inBufferLength;
+
+ m_Buffer = new unsigned char[m_BufferLength];
+ m_BufferPosition = 0;
+ m_BufferUsedCount = 0;
+}
+
+CBufferedInputStream::~CBufferedInputStream()
+{
+ this->Close();
+ delete[] m_Buffer;
+}
+
+long CBufferedInputStream::Read(void *inBuffer, long inBufferLength)
+{
+ long nread = 1;
+ long theReadCount = 0;
+
+ // Loop around until the entire inBuffer has been filled (or an error occurs)
+ // This must be able to handle requests larger than this buffer.
+ // while the number of bytes read is less than the requested length...
+ while (theReadCount < inBufferLength) {
+ // If the amount of data left to read is greater than the amount currently in the buffer...
+ if ((inBufferLength - theReadCount) > (m_BufferUsedCount - m_BufferPosition)) {
+ char *theBuffer = reinterpret_cast<char *>(inBuffer);
+ // Copy what is in this buffer into the outgoing buffer
+ ::memcpy(&theBuffer[theReadCount], &m_Buffer[m_BufferPosition],
+ m_BufferUsedCount - m_BufferPosition);
+
+ // Adjust the number of bytes read
+ theReadCount += m_BufferUsedCount - m_BufferPosition;
+
+ // Fill up the buffer to continue reading
+ nread = FillBuffer();
+ if (nread == 0 || nread == (unsigned long)-1) {
+ break;
+ }
+ }
+ // The amount of data requested is less than the amount in the buffer,
+ // so the request comes completely from the buffer.
+ else {
+ char *theBuffer = reinterpret_cast<char *>(inBuffer);
+ ::memcpy(&theBuffer[theReadCount], &m_Buffer[m_BufferPosition],
+ inBufferLength - theReadCount);
+ m_BufferPosition += inBufferLength - theReadCount;
+ theReadCount += inBufferLength - theReadCount;
+ }
+ }
+ return theReadCount;
+}
+
+long CBufferedInputStream::Read(std::wstringstream &inStringStream)
+{
+ std::string theStreamData;
+ theStreamData.resize(m_BufferLength);
+ Read(&theStreamData[0], m_BufferLength);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ long theDataLength = ::MultiByteToWideChar(CP_UTF8, 0, theStreamData.c_str(), -1, 0, 0);
+ wchar_t *theWideBuffer = new wchar_t[theDataLength];
+ ::MultiByteToWideChar(CP_UTF8, 0, theStreamData.c_str(), -1, theWideBuffer, theDataLength);
+
+ inStringStream.write(&theWideBuffer[0], theDataLength);
+ delete[] theWideBuffer;
+
+ return m_BufferLength;
+#endif
+ return 0;
+}
+
+void CBufferedInputStream::Close()
+{
+ if (m_InputStream)
+ m_InputStream->Close();
+}
+
+bool CBufferedInputStream::IsValid()
+{
+ if (m_InputStream != NULL)
+ return m_InputStream->IsValid();
+ return false;
+}
+
+/** Fill up the internal buffer from the sub-inputstream.
+ * This just calls read on the stream and returns the amount that was read.
+ * @return the amount of data read.
+ */
+long CBufferedInputStream::FillBuffer()
+{
+ long theReadCount = m_InputStream->Read(m_Buffer, m_BufferLength);
+
+ if (theReadCount != (unsigned long)-1) {
+ m_BufferUsedCount = theReadCount;
+ m_BufferPosition = 0;
+ } else {
+ m_BufferUsedCount = 0;
+ m_BufferPosition = 0;
+ }
+
+ return theReadCount;
+}
+
+/** Insert the data into the buffer.
+ * This will put the data at the end of the data currently in the buffer, and is
+ * meant primarily for initializing the buffer with data. The amount of data
+ * cannot be larger than the amount of space left in the buffer.
+ * @param inData the data to be inserted.
+ * @param inDataLength the amount of data to be inserted.
+ * @return true if successful, false if not enough space.
+ */
+void CBufferedInputStream::InsertIntoBuffer(void *inData, long inDataLength)
+{
+ // Not enough space in the buffer for the data
+ if (inDataLength > m_BufferLength - m_BufferUsedCount)
+ throw CIOException();
+
+ // Copy the data into the buffer and adjust the buffer used count
+ ::memcpy(&m_Buffer[m_BufferUsedCount], inData, inDataLength);
+ m_BufferUsedCount += inDataLength;
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/IO/BufferedInputStream.h b/src/Authoring/Common/Code/IO/BufferedInputStream.h
new file mode 100644
index 00000000..3ff11d10
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/BufferedInputStream.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_BUFFERED_INPUT_STREAM_H
+#define INCLUDED_BUFFERED_INPUT_STREAM_H
+
+#include "InputStream.h"
+
+//==============================================================================
+/**
+ * @class CBufferedInputStream
+ * @brief Brief description goes here.
+ *
+ * This is where a complete desciption of the class belongs.
+ */
+class CBufferedInputStream : public CInputStream
+{
+ // Field Members
+
+protected:
+ CInputStream *m_InputStream;
+ unsigned char *m_Buffer;
+ long m_BufferLength;
+ long m_BufferPosition;
+ long m_BufferUsedCount;
+
+ // Construction
+
+public:
+ CBufferedInputStream(CInputStream *inInputStream, long inBufferLength = 65535);
+ virtual ~CBufferedInputStream();
+
+ long Read(void *inBuffer, long inBufferLength) override;
+ virtual long Read(std::wstringstream &inStringStream);
+ void Close() override;
+ bool IsValid() override;
+ virtual void InsertIntoBuffer(void *inData, long inDataLength);
+ Q3DStudio::CString GetMimeType() override { return L""; }
+ Q3DStudio::CString GetSource() override { return L""; }
+
+protected:
+ long FillBuffer();
+};
+
+#endif // INCLUDED_BUFFERED_INPUT_STREAM_H
diff --git a/src/Authoring/Common/Code/IO/BufferedOutputStream.cpp b/src/Authoring/Common/Code/IO/BufferedOutputStream.cpp
new file mode 100644
index 00000000..cab9f4b3
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/BufferedOutputStream.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <string.h>
+#include <sstream>
+#include "BufferedOutputStream.h"
+
+CBufferedOutputStream::CBufferedOutputStream(COutputStream *inOutputStream)
+ : m_OutputStream(inOutputStream)
+{
+ const long MAXBUFFERLENGTH = 33554432; // 32MB
+ m_BufferLength = MAXBUFFERLENGTH;
+ m_Buffer = new unsigned char[m_BufferLength];
+ m_BufferUsed = 0;
+}
+
+CBufferedOutputStream::~CBufferedOutputStream()
+{
+ Flush();
+ delete[] m_Buffer;
+}
+
+long CBufferedOutputStream::Write(const void *inBuffer, long inBufferLength)
+{
+ const char *theBuffer = reinterpret_cast<const char *>(inBuffer);
+
+ long theBufferLength = inBufferLength;
+ long theWroteCount = 0;
+
+ while (theBufferLength > m_BufferLength - m_BufferUsed) {
+ ::memcpy(&m_Buffer[m_BufferUsed], theBuffer, m_BufferLength - m_BufferUsed);
+
+ theWroteCount += m_BufferLength - m_BufferUsed;
+
+ theBufferLength -= (m_BufferLength - m_BufferUsed);
+ theBuffer += (m_BufferLength - m_BufferUsed);
+ m_BufferUsed = m_BufferLength;
+
+ Flush();
+ }
+
+ ::memcpy(&m_Buffer[m_BufferUsed], theBuffer, theBufferLength);
+ theWroteCount = inBufferLength;
+ m_BufferUsed += theBufferLength;
+
+ return theWroteCount;
+}
+
+bool CBufferedOutputStream::Write(std::wostringstream &inStringStream)
+{
+ // Writing out to file
+ long theDataLength = static_cast<long>(inStringStream.str().length()) * sizeof(wchar_t);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ std::string theMultiByteBuffer;
+ int theSize = ::WideCharToMultiByte(CP_UTF8, 0, inStringStream.str().c_str(), theDataLength / 2,
+ 0, 0, 0, 0);
+ if (theSize > 0) {
+ theMultiByteBuffer.resize(theSize);
+ ::WideCharToMultiByte(CP_UTF8, 0, inStringStream.str().c_str(), theDataLength / 2,
+ const_cast<char *>(theMultiByteBuffer.c_str()), theSize, 0, 0);
+ Write(theMultiByteBuffer.c_str(), theSize);
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+void CBufferedOutputStream::Close()
+{
+ this->Flush();
+ m_OutputStream->Close();
+}
+
+bool CBufferedOutputStream::IsValid()
+{
+ if (m_OutputStream != NULL)
+ return m_OutputStream->IsValid();
+ return false;
+}
+
+void CBufferedOutputStream::Flush()
+{
+ long theWroteCount = m_OutputStream->Write(m_Buffer, m_BufferUsed);
+
+ if (theWroteCount != m_BufferUsed) {
+ // Short write, move the unwritten data to the beginning of the buffer.
+ ::memmove(m_Buffer, &m_Buffer[theWroteCount], m_BufferUsed - theWroteCount);
+ m_BufferUsed -= theWroteCount;
+ } else {
+ m_BufferUsed = 0;
+ }
+}
+
+CBufferedSeekOutputStream::CBufferedSeekOutputStream(CSeekOutputStream *inStream,
+ long inBufferSize /*=1048576*/)
+ : m_OutputStream(inStream)
+ , m_BufferLength(inBufferSize)
+ , m_BufferUsed(0)
+ , m_BufferPosition(0)
+ , m_RunningCounter(0)
+{
+ m_Buffer = new unsigned char[inBufferSize];
+}
+
+CBufferedSeekOutputStream::~CBufferedSeekOutputStream()
+{
+ Close();
+ if (m_Buffer) {
+ delete[] m_Buffer;
+ }
+}
+
+long CBufferedSeekOutputStream::Write(const void *inBuffer, const long inBufferLength)
+{
+ long theDataRead = 0;
+ long theDataLeft = inBufferLength;
+ long theBufferSizeWritable = m_BufferLength - m_BufferPosition;
+ const char *theBuffer = static_cast<const char *>(inBuffer);
+
+ /* Early flushing?
+ if ( inBufferLength > m_BufferLength )
+ {
+ FlushBuffer( );
+ theDataRead = m_OutputStream->Write( theBuffer, inBufferLength );
+ return inBufferLength;
+ }
+ */
+
+ while (theDataLeft > theBufferSizeWritable) {
+ ::memcpy(&m_Buffer[m_BufferPosition], &theBuffer[theDataRead], theBufferSizeWritable);
+ m_BufferUsed += theBufferSizeWritable;
+ FlushBuffer();
+ theDataLeft -= theBufferSizeWritable;
+ theDataRead += theBufferSizeWritable;
+ theBufferSizeWritable = m_BufferLength;
+ }
+
+ ::memcpy(&m_Buffer[m_BufferPosition], &theBuffer[theDataRead], theDataLeft);
+ m_BufferPosition += theDataLeft;
+ m_BufferUsed = Q3DStudio::MAX(m_BufferUsed, m_BufferPosition);
+
+ return inBufferLength;
+}
+
+void CBufferedSeekOutputStream::FlushBuffer()
+{
+ long theFlushPoint = 0;
+ long theWroteCount = 0;
+ while (m_BufferUsed != 0) {
+ theWroteCount = m_OutputStream->Write(&m_Buffer[theFlushPoint], m_BufferUsed);
+ m_BufferUsed -= theWroteCount;
+ theFlushPoint += theWroteCount;
+ }
+
+ m_BufferPosition = 0;
+}
+
+void CBufferedSeekOutputStream::Flush()
+{
+ FlushBuffer();
+ m_OutputStream->Flush();
+}
+
+void CBufferedSeekOutputStream::Close()
+{
+ Flush();
+ m_OutputStream->Close();
+}
+
+bool CBufferedSeekOutputStream::IsValid()
+{
+ return m_OutputStream->IsValid();
+}
+
+// CSeekOutputStream
+long CBufferedSeekOutputStream::Seek(ESeekPosition inPosition, long inOffset)
+{
+ long theUnflushedPosition = m_OutputStream->GetCurrentPosition();
+
+ long theAbsolutePosition = -1;
+ switch (inPosition) {
+ case Q3DStudio::ISeekable::EBEGIN:
+ theAbsolutePosition = inOffset;
+ break;
+ case Q3DStudio::ISeekable::ECURRENT:
+ theAbsolutePosition = theUnflushedPosition + m_BufferPosition + inOffset;
+ break;
+ // case Q3DStudio::ISeekable::EEND: // This case need not be optimized
+ // break;
+ }
+
+ if (theAbsolutePosition >= theUnflushedPosition
+ && theAbsolutePosition <= theUnflushedPosition + m_BufferUsed) {
+ m_BufferPosition = theAbsolutePosition - theUnflushedPosition;
+ return m_BufferPosition;
+ } else {
+ FlushBuffer();
+ return m_OutputStream->Seek(inPosition, inOffset);
+ }
+}
+
+long CBufferedSeekOutputStream::GetCurrentPosition()
+{
+ return m_OutputStream->GetCurrentPosition() + m_BufferPosition;
+}
diff --git a/src/Authoring/Common/Code/IO/BufferedOutputStream.h b/src/Authoring/Common/Code/IO/BufferedOutputStream.h
new file mode 100644
index 00000000..f65a7979
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/BufferedOutputStream.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_BUFFERED_OUTPUT_STREAM_H
+#define INCLUDED_BUFFERED_OUTPUT_STREAM_H
+
+#include "OutputStream.h"
+
+//==============================================================================
+/**
+ * @class CBufferedOutputStream
+ * @brief Brief description goes here.
+ *
+ * This is where a complete desciption of the class belongs.
+ */
+class CBufferedOutputStream : public COutputStream
+{
+protected:
+ COutputStream *m_OutputStream;
+ unsigned char *m_Buffer;
+ long m_BufferLength;
+ long m_BufferUsed;
+
+public:
+ CBufferedOutputStream(COutputStream *inStream);
+ virtual ~CBufferedOutputStream();
+
+ // IBufferedOutputStream
+public:
+ long Write(const void *inBuffer, long inBufferLength) override;
+ virtual bool Write(std::wostringstream &inStringStream);
+ void Flush() override;
+ void Close() override;
+ bool IsValid() override;
+};
+
+class CBufferedSeekOutputStream : public CSeekOutputStream
+{
+protected:
+ CSeekOutputStream *m_OutputStream;
+ unsigned char *m_Buffer;
+ const long m_BufferLength;
+ long m_BufferUsed;
+ long m_BufferPosition;
+
+ unsigned long m_RunningCounter;
+
+public:
+ CBufferedSeekOutputStream(CSeekOutputStream *inStream, long inBufferSize = 1048576 /*1 meg*/);
+ virtual ~CBufferedSeekOutputStream();
+
+ // IBufferedOutputStream
+public:
+ long Write(const void *inBuffer, long inBufferLength) override;
+
+ virtual void FlushBuffer();
+
+ void Flush() override;
+
+ void Close() override;
+
+ bool IsValid() override;
+
+ // CSeekOutputStream
+ long Seek(ESeekPosition inPosition, long inOffset) override;
+ long GetCurrentPosition() override;
+};
+
+#endif //__BUFFEREDOUTPUTSTREAM_H_
diff --git a/src/Authoring/Common/Code/IO/ByteSwap.h b/src/Authoring/Common/Code/IO/ByteSwap.h
new file mode 100644
index 00000000..b4575e75
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/ByteSwap.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BYTESWAPH
+#define BYTESWAPH
+
+#define SWAP2BYTES(in, out) out = ((in & 0xff00) >> 8) | ((in & 0xff) << 8);
+
+#define SWAP4BYTES(in, out) \
+ out = ((in & 0xff000000) >> 24) | ((in & 0xFF0000) >> 8) | ((in & 0xFF00) << 8) \
+ | ((in & 0xFF) << 24);
+
+#define SWAP8BYTES(in, out) \
+ out = ((in & 0xFF00000000000000) >> 56) | ((in & 0xFF000000000000) >> 40) \
+ | ((in & 0xFF0000000000) >> 24) | ((in & 0xFF00000000) >> 8) | ((in & 0xFF000000) << 8) \
+ | ((in & 0xFF0000) << 24) | ((in & 0xFF00) << 40) | ((in & 0xFF) << 56);
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Common/Code/IO/FileInputStream.cpp b/src/Authoring/Common/Code/IO/FileInputStream.cpp
new file mode 100644
index 00000000..579c3448
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/FileInputStream.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FileInputStream.h"
+#include "IOLibraryException.h"
+
+CFileInputStream::CFileInputStream(const Q3DStudio::CString &inFilename)
+ : m_FileName(inFilename)
+ , m_ReadBytesFromCurrentBuffer(0)
+ , m_AvailableBytesInBuffer(0)
+ , m_File(inFilename.toQString())
+{
+ m_InternalBuffer[0] = '\0';
+ if (!m_File.open(QFile::ReadOnly))
+ throw CIOException();
+}
+
+CFileInputStream::~CFileInputStream()
+{
+ Close();
+}
+
+/**
+ * Seek to inOffset from inBegin. If the result is past either end of the
+ * file then the next byte read from the stream will either not exist or come
+ * from the beginning, ie the file position pointer will not be moved past
+ * the end or in front of the beginning of the file.
+ * @param inOffset The offset to seek to.
+ * @param inBegin where to seek from, i.e. current position, begin or end.
+ * @return success if this is a valid file handle.
+ */
+long CFileInputStream::Seek(Q3DStudio::ISeekable::ESeekPosition inBegin, long inOffset)
+{
+ if (!IsValid())
+ throw CIOException();
+ bool result = false;
+ switch (inBegin) {
+ case Q3DStudio::ISeekable::EBEGIN: {
+ result = m_File.seek(inOffset);
+ break;
+ }
+ case Q3DStudio::ISeekable::ECURRENT: {
+ inOffset -= m_AvailableBytesInBuffer;
+ result = m_File.seek(m_File.pos() + inOffset);
+ break;
+ }
+ case Q3DStudio::ISeekable::EEND: {
+ result = m_File.seek(m_File.size() + inOffset);
+ break;
+ }
+ default: {
+ throw CIOException();
+ break;
+ }
+ }
+
+ m_ReadBytesFromCurrentBuffer = 0;
+ m_AvailableBytesInBuffer = 0;
+
+ if (result == false)
+ throw CIOException();
+ return 0; // okay because we implement seeking
+}
+
+/**
+ * Read a chunk of the file into the inBuffer.
+ * This method will read as much as possible into the buffer. If not enough
+ * data exists in the file the outReadCount will reflect the amount of data
+ * successfully read. If the end of file has been reached the read count is
+ * 0. An error will set the read count to -1. This function will only fail if
+ * no data could be read (EOF or error).
+ * @param inBuffer destination for data being read in.
+ * @param inBufferLength the amount of data to be read.
+ * @param outReadCount the amount of data read.
+ * @return <HRESULT> S_OK if successful or if partial read succeeded.
+ */
+long CFileInputStream::Read(void *inBuffer, long inBufferLength)
+{
+ long theReadCount = 0;
+ char *theBufferPointer = static_cast<char *>(inBuffer);
+
+ // If reading more than the internal buffer, directly use the buffer supplied.
+ if (inBufferLength > INTERNAL_BUFFER_SIZE) {
+ long theActualReadCount = inBufferLength;
+ if (m_ReadBytesFromCurrentBuffer > 0) { // dump whatever that was previously read in first
+ ::memcpy(theBufferPointer, &m_InternalBuffer[m_ReadBytesFromCurrentBuffer],
+ m_AvailableBytesInBuffer);
+ theActualReadCount -= m_AvailableBytesInBuffer;
+ theBufferPointer += m_AvailableBytesInBuffer;
+ }
+ if ((theReadCount = m_File.read(theBufferPointer, theActualReadCount)) == -1)
+ throw CIOException();
+
+ // update and reset the counters
+ theReadCount += m_AvailableBytesInBuffer;
+ m_ReadBytesFromCurrentBuffer = m_AvailableBytesInBuffer = 0;
+ } else {
+ long theRequiredLength = inBufferLength;
+ while (true) {
+ BOOL theSuccess = TRUE;
+ if (m_ReadBytesFromCurrentBuffer
+ <= 0) { // If internal buffer is empty, read a chunk first
+ long theActualReadCount = m_File.read(m_InternalBuffer, INTERNAL_BUFFER_SIZE);
+ theSuccess = theActualReadCount > 0;
+ m_AvailableBytesInBuffer = theActualReadCount;
+ }
+ if (!theSuccess)
+ throw CIOException();
+ // End of file
+ if (m_AvailableBytesInBuffer <= 0)
+ break;
+
+ long theAvailableBytes = (m_AvailableBytesInBuffer < theRequiredLength)
+ ? m_AvailableBytesInBuffer
+ : theRequiredLength;
+ // copy the relevant portion over
+ ::memcpy(theBufferPointer, &m_InternalBuffer[m_ReadBytesFromCurrentBuffer],
+ theAvailableBytes);
+ // update the number of bytes 'read' so far
+ theReadCount += theAvailableBytes;
+ // if the required data is sufficient, we are done
+ if (theAvailableBytes >= theRequiredLength) {
+ m_ReadBytesFromCurrentBuffer +=
+ theAvailableBytes; // so the next read will start from here.
+ if (m_ReadBytesFromCurrentBuffer >= INTERNAL_BUFFER_SIZE)
+ m_ReadBytesFromCurrentBuffer = 0; // reset
+ m_AvailableBytesInBuffer -= theAvailableBytes;
+ break;
+ } else // loop back and read more data
+ {
+ m_ReadBytesFromCurrentBuffer = 0;
+ theBufferPointer += theAvailableBytes; // move the pointer too
+ theRequiredLength -= theAvailableBytes; // this much is still required
+ }
+ }
+ }
+ return theReadCount;
+}
+
+/**
+ * Close the file handle.
+ */
+void CFileInputStream::Close()
+{
+ m_File.close();
+ m_ReadBytesFromCurrentBuffer = m_AvailableBytesInBuffer = 0;
+}
+
+/**
+ * Returns true if the file is open and can be read.
+ * Does not check for EOF.
+ * @param outResult true if file is open.
+ */
+bool CFileInputStream::IsValid()
+{
+ return m_File.isOpen();
+}
+
+Q3DStudio::CString CFileInputStream::GetSource()
+{
+ return m_FileName;
+}
diff --git a/src/Authoring/Common/Code/IO/FileInputStream.h b/src/Authoring/Common/Code/IO/FileInputStream.h
new file mode 100644
index 00000000..b46697b6
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/FileInputStream.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_FILE_INPUT_STREAM_H
+#define INCLUDED_FILE_INPUT_STREAM_H
+
+#include <stdio.h>
+#include "InputStream.h"
+#include "UICString.h"
+
+#include <QFile>
+
+//==============================================================================
+/**
+ * @class CFileInputStream
+ * @brief Brief description goes here.
+ *
+ * This is where a complete desciption of the class belongs.
+ */
+class CFileInputStream : public CInputStream
+{
+protected:
+ static const long INTERNAL_BUFFER_SIZE =
+ 4096; ///< Size of internal buffer that is reading chunks from file
+
+ // Field Members
+protected:
+ Q3DStudio::CString m_FileName;
+
+ char m_InternalBuffer[INTERNAL_BUFFER_SIZE];
+ long m_ReadBytesFromCurrentBuffer;
+ long m_AvailableBytesInBuffer;
+ QFile m_File;
+
+ // Construction
+public:
+ CFileInputStream(const Q3DStudio::CString &inFileName);
+ virtual ~CFileInputStream();
+
+ // CInputStream
+public:
+ long Seek(Q3DStudio::ISeekable::ESeekPosition inSeekPosition, long inOffset) override;
+ long Read(void *inBuffer, long inBufferLength) override;
+ void Close() override;
+ bool IsValid() override;
+ Q3DStudio::CString GetMimeType() override { return L""; }
+ Q3DStudio::CString GetSource() override;
+};
+
+#endif // INCLUDED_FILEINPUTSTREAM_H
diff --git a/src/Authoring/Common/Code/IO/FileOutputStream.cpp b/src/Authoring/Common/Code/IO/FileOutputStream.cpp
new file mode 100644
index 00000000..8cfe45a8
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/FileOutputStream.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FileOutputStream.h"
+#include "IOLibraryException.h"
+
+#include <QByteArray>
+#include <QString>
+
+/* STL implementation
+CFileOutputStream::CFileOutputStream( const Q3DStudio::CString& inFilename, bool inAppend, long
+inBuffersize )
+{
+ m_Buffer = new char[inBuffersize];
+ m_FileStream = new std::ofstream( inFilename.GetMulti( ), inAppend ? ( std::ios_base::app |
+std::ios_base::binary ) : ( std::ios_base::out | std::ios_base::trunc | std::ios_base::binary ) );
+
+ m_FileStream->rdbuf( )->pubsetbuf( m_Buffer, inBuffersize );
+ m_FileStream->sync_with_stdio( false );
+
+ m_FileStream->unsetf( std::ios_base::unitbuf );
+ m_FileStream->tie( NULL );
+}
+
+CFileOutputStream::~CFileOutputStream( )
+{
+ Close( );
+ delete m_FileStream;
+ delete[] m_Buffer;
+}
+
+long CFileOutputStream::Write( const void* inBuffer, long inBufferLength )
+{
+ m_FileStream->write( static_cast<const char*>( inBuffer ), inBufferLength );
+ return inBufferLength;
+}
+
+void CFileOutputStream::Flush( )
+{
+ m_FileStream->flush( );
+}
+
+void CFileOutputStream::Close( )
+{
+ m_FileStream->close( );
+}
+
+bool CFileOutputStream::IsValid( )
+{
+ return m_FileStream->good( );
+}
+
+//CSeekOutputStream
+long CFileOutputStream::Seek( Q3DStudio::ISeekable::ESeekPosition inBegin, long inOffset )
+{
+ switch ( inBegin )
+ {
+ case Q3DStudio::ISeekable::EBEGIN:
+ m_FileStream->seekp( inOffset, std::ios_base::beg );
+ break;
+ case Q3DStudio::ISeekable::EEND:
+ m_FileStream->seekp( inOffset, std::ios_base::end );
+ break;
+ case Q3DStudio::ISeekable::ECURRENT:
+ m_FileStream->seekp( inOffset, std::ios_base::cur );
+ break;
+ }
+
+ return 0;
+}
+
+long CFileOutputStream::GetCurrentPosition( )
+{
+ return m_FileStream->tellp( );
+}
+*/
+
+CFileOutputStream::CFileOutputStream(const Q3DStudio::CString &inFilename, bool inAppend /* = false */)
+ : m_Position(0)
+ , m_Length(0)
+{
+#ifdef WIN32
+ m_File = ::CreateFile(inFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+ (inAppend) ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL);
+ if (m_File == INVALID_HANDLE_VALUE)
+ throw CIOException();
+ // In this case, set the file pointer to the end of the file
+ if (inAppend)
+ ::SetFilePointer(m_File, 0, NULL, FILE_END);
+#else
+ QByteArray theUTFBuffer = inFilename.toQString().toUtf8();
+ m_File = ::fopen(theUTFBuffer.constData(), (inAppend) ? "a" : "w");
+ if (m_File == NULL)
+ throw CIOException();
+#endif
+}
+
+CFileOutputStream::~CFileOutputStream()
+{
+ this->Close();
+}
+
+/** Write the specified buffer to this file.
+ * @param inBuffer the bytes to write to this file.
+ * @param inBufferLength the number of bytes to write.
+ * @param outWroteCount the number of bytes actually written.
+ */
+long CFileOutputStream::Write(const void *inBuffer, long inBufferLength)
+{
+ long theWroteCount = 0;
+#ifdef WIN32
+ ::WriteFile(m_File, inBuffer, inBufferLength, (DWORD *)&theWroteCount, NULL);
+ if (theWroteCount <= 0 && inBufferLength > 0)
+ throw CIOException();
+#else
+ theWroteCount = ::fwrite(inBuffer, 1, inBufferLength, m_File);
+ if (theWroteCount != inBufferLength)
+ throw CIOException();
+#endif
+ m_Position += theWroteCount;
+ if (m_Position > m_Length)
+ m_Length = m_Position;
+
+ return theWroteCount;
+}
+
+void CFileOutputStream::Flush()
+{
+#ifdef WIN32
+#else
+ ::fflush(m_File);
+#endif
+}
+
+/** Closes the file.
+ * This method should be called to eliminate handle leaks.
+ */
+void CFileOutputStream::Close()
+{
+#ifdef WIN32
+ if (m_File != INVALID_HANDLE_VALUE) {
+ ::CloseHandle(m_File);
+ m_File = INVALID_HANDLE_VALUE;
+ }
+#else
+ if (m_File != NULL) {
+ ::fflush(m_File);
+ ::fclose(m_File);
+ m_File = NULL;
+ }
+#endif
+}
+
+/** Check to see if thus stream is valid (opened successfully and still open).
+ */
+bool CFileOutputStream::IsValid()
+{
+#ifdef WIN32
+ return (m_File != INVALID_HANDLE_VALUE);
+#else
+ return (m_File != NULL);
+#endif
+}
+
+/** Seek to inOffset from inBegin. If the result is past either end of the
+ * file then the next byte read from the stream will either not exist or come
+ * from the beginning, ie the file position pointer will not be moved past
+ * the end or in front of the beginning of the file.
+ * @param inOffset The offset to seek to.
+ * @param inBegin where to seek from, i.e. current position, begin or end.
+ * @return success if this is a valid file handle.
+ */
+long CFileOutputStream::Seek(Q3DStudio::ISeekable::ESeekPosition inBegin, long inOffset)
+{
+ if (!IsValid())
+ throw CIOException();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ long theSeek = INVALID_SET_FILE_POINTER;
+ switch (inBegin) {
+ case Q3DStudio::ISeekable::EBEGIN: {
+ theSeek = ::SetFilePointer(m_File, inOffset, NULL, FILE_BEGIN);
+ m_Position = inOffset;
+ break;
+ }
+ case Q3DStudio::ISeekable::ECURRENT: {
+ theSeek = ::SetFilePointer(m_File, inOffset, NULL, FILE_CURRENT);
+ m_Position += inOffset;
+ break;
+ }
+ case Q3DStudio::ISeekable::EEND: {
+ theSeek = ::SetFilePointer(m_File, inOffset, NULL, FILE_END);
+ m_Position = m_Length + inOffset;
+ break;
+ }
+ default: {
+ throw CIOException();
+ break;
+ }
+ }
+ if (theSeek == INVALID_SET_FILE_POINTER)
+ throw CIOException();
+#endif
+ return 0; // okay because we implement seeking
+}
+
+long CFileOutputStream::GetCurrentPosition()
+{
+ return m_Position;
+}
diff --git a/src/Authoring/Common/Code/IO/FileOutputStream.h b/src/Authoring/Common/Code/IO/FileOutputStream.h
new file mode 100644
index 00000000..0594ef44
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/FileOutputStream.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_FILE_OUTPUT_STREAM_H
+#define INCLUDED_FILE_OUTPUT_STREAM_H
+
+#include "OutputStream.h"
+#include "UICString.h"
+#include <stdio.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+//==============================================================================
+/**
+ * @class CFileOutputStream
+ * @brief Brief description goes here.
+ * This is where a complete desciption of the class belongs.
+ */
+class CFileOutputStream : public CSeekOutputStream
+{
+protected:
+#ifdef WIN32
+ HANDLE m_File;
+#else
+ FILE *m_File;
+#endif
+ long m_Position; ///< Stores current write position
+ long m_Length; ///< Stores length of data written to file so far
+
+public:
+ // Construction
+ CFileOutputStream(const Q3DStudio::CString &inFilename, bool inAppend = false);
+ virtual ~CFileOutputStream();
+
+ long Write(const void *inBuffer, long inBufferLength) override;
+ void Flush() override;
+ void Close() override;
+ bool IsValid() override;
+
+ // CSeekOutputStream
+ long Seek(Q3DStudio::ISeekable::ESeekPosition inBegin, long inOffset) override;
+ long GetCurrentPosition() override;
+};
+
+/* STL implementation
+class CFileOutputStream : public CSeekOutputStream
+{
+ // Construction
+ protected:
+ std::ofstream* m_FileStream;
+ char* m_Buffer;
+
+ public:
+ CFileOutputStream( const Q3DStudio::CString& inFilename, bool inAppend = false ,
+long inBuffersize = 10485760 );
+
+ virtual ~CFileOutputStream( );
+
+ virtual long Write( const void* inBuffer, long inBufferLength );
+
+ virtual void Flush( );
+
+ virtual void Close( );
+
+ virtual bool IsValid( );
+
+ //CSeekOutputStream
+ virtual long Seek( Q3DStudio::ISeekable::ESeekPosition inBegin, long inOffset );
+
+ virtual long GetCurrentPosition( );
+
+};
+*/
+
+#endif // INCLUDED_FILE_OUTPUT_STREAM_H
diff --git a/src/Authoring/Common/Code/IO/IOLibraryException.h b/src/Authoring/Common/Code/IO/IOLibraryException.h
new file mode 100644
index 00000000..cf8982ad
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/IOLibraryException.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_IOLIBRARYEXCEPTION_H
+#define INCLUDED_IOLIBRARYEXCEPTION_H 1
+
+#pragma once
+
+#include "StudioException.h"
+
+// This string should never be displayed to user, just for brief description.
+static const wchar_t IOLIBRARY_EXCEPTION_DESCRIPTION[] = L"IOLibrary Exception";
+
+class CIOException : public CStudioException
+{
+public:
+ CIOException() {}
+ virtual ~CIOException() {}
+
+ const wchar_t *GetDescription() const override { return IOLIBRARY_EXCEPTION_DESCRIPTION; }
+};
+#endif // INCLUDED_IOLIBRARYEXCEPTION_H
diff --git a/src/Authoring/Common/Code/IO/IOStreams.cpp b/src/Authoring/Common/Code/IO/IOStreams.cpp
new file mode 100644
index 00000000..45c7fd50
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/IOStreams.cpp
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "IOStreams.h"
+#include "InputStream.h"
+#include "OutputStream.h"
+#include "IOLibraryException.h"
+
+#include <wctype.h>
+#include <ctype.h>
+#include <wchar.h>
+#include <limits>
+#include <stdlib.h>
+
+/** Create an input stream wrapper with no stream.
+ */
+CInStream::CInStream()
+ : m_Stream(NULL)
+{
+}
+
+/** Create an input stream wrapper for inStream.
+ * @param inStream the stream to be wrapped.
+ */
+CInStream::CInStream(CInputStream *inStream)
+{
+ m_Stream = inStream;
+}
+
+/** Create an input stream wrapper duplicating the old stream
+ * @param inOldStream the stream to be copied upon construction
+ */
+CInStream::CInStream(const CInStream &inStream)
+{
+ m_Stream = inStream.m_Stream;
+ m_URLString = inStream.m_URLString;
+}
+
+/**
+ * Destroy an input stream
+ */
+CInStream::~CInStream()
+{
+}
+
+/** Set the input stream this is wrapping.
+ * @param inStream theStream to be wrapped.
+ */
+void CInStream::SetInputStream(CInputStream *inStream)
+{
+ m_Stream = inStream;
+}
+
+/** Get the input stream this is wrapping.
+ * @param outStream theStream to being wrapped.
+ */
+CInputStream *CInStream::GetInputStream()
+{
+ return m_Stream;
+}
+
+void CInStream::SetURL(const wchar_t *inURLString)
+{
+ m_URLString = inURLString;
+}
+
+void CInStream::GetURL(wchar_t *ioURLString, const long &inSize)
+{
+ long theEndCount = m_URLString.Length();
+ wchar_t *theString;
+ theString = const_cast<wchar_t *>(static_cast<const wchar_t *>(m_URLString));
+
+ if (inSize >= m_URLString.Length()) {
+ // The swprintf just refused to work
+ // =================================
+ // POSSIBLE PROBLEM: the swprintf reads unsigned short (2 bytes) instead
+ // of wchar_t (4 bytes)
+ // as alphanumerics seldom exceeds 1 byte, the 3rd & 4th bytes of a wchar_t was usu
+ // a '\0'. swprintf ASSUMES EOS upon encountering '\0' and hence FAILURE
+ //
+ // A SLOPPY SOLUTION: blind copying theString to ioURLString, very amateurish, but it did
+ // the job...
+
+ // the stuff that dint work:
+ // theCharCount = _aswprintf( ioURLString, inSize, _UIC( "%s" ), theString );
+ // ... that's even when you call the swprintf directly...
+ // theCharCount = swprintf(ioURLString, inSize, _UIC( "%s" ), (unsigned short *)theString );
+
+ // the sloppy solution
+ for (long theCharCount = 0; theCharCount < theEndCount; ++theCharCount) {
+ ioURLString[theCharCount] = theString[theCharCount];
+ }
+
+ } else
+ throw CIOException();
+}
+
+CInStream *CInStream::Copy(CInputStream *inBase)
+{
+ return new CInStream(inBase);
+}
+
+CInStream *CInStream::Copy()
+{
+ return new CInStream();
+}
+//==============================================================================
+/**
+ * Read: Get the specified number of bytes from the stream.
+ * @param outBuffer void*. This buffer better be at least inByteCount in length.
+ * @param inByteCount long. This is the length of the buffer.
+ * @return The number of bytes read.
+ * In most cases the return value will be the same as the parameter inByteCount.
+ *However
+ * when the end of file comes before the specified number of bytes is read, the return
+ *value will
+ * will only contain the read.
+ * @see Write
+ */
+//==============================================================================
+long CInStream::Read(void *outBuffer, long inByteCount)
+{
+ return m_Stream->Read(outBuffer, inByteCount);
+}
+
+void CInStream::ReadData(void *inBuffer, long inBufferLength)
+{
+ long theLength = m_Stream->Read(inBuffer, inBufferLength);
+ if (theLength != inBufferLength) {
+ throw CIOException();
+ }
+}
+
+void CInStream::Close()
+{
+ m_Stream->Close();
+}
+
+bool CInStream::IsValid()
+{
+ return m_Stream->IsValid();
+}
+
+COutStream::COutStream()
+ : m_Stream(NULL)
+{
+}
+
+COutStream::COutStream(COutputStream *inStream)
+{
+ m_Stream = inStream;
+}
+
+void COutStream::SetOutputStream(COutputStream *inStream)
+{
+ m_Stream = inStream;
+}
+
+void COutStream::SetURL(const wchar_t *inURLString)
+{
+ m_URLString = inURLString;
+}
+
+void COutStream::GetURL(wchar_t *ioURLString, const long &inSize)
+{
+ if (inSize >= m_URLString.Length())
+#ifdef WIN32
+ _aswprintf(ioURLString, inSize, _UIC("%ls"), static_cast<const wchar_t *>(m_URLString));
+#else
+ swprintf(ioURLString, inSize, _UIC("%ls"), static_cast<const wchar_t *>(m_URLString));
+#endif
+ else
+ throw CIOException();
+}
+
+COutStream *COutStream::Copy(COutputStream *inBase)
+{
+ return new COutStream(inBase);
+}
+
+COutStream *COutStream::Copy()
+{
+ return new COutStream();
+}
+
+//==============================================================================
+/**
+ * Write: Puts the specified number of bytes out to the stream.
+ *
+ * @param inBuffer const void*.
+ * This is a pointer the chunk of data that will be written out
+ *the stream.
+ * It must be at least inByteCount in length. If the pointer is
+ *NULL, nothing will happen.
+ * If the pointer is dangling, the worst possible error will
+ *occur.
+ * @param inByteCount long. This is the number of bytes to be
+ *written.
+ *
+ * @return The number of bytes written.
+ * @see Read
+ */
+//==============================================================================
+long COutStream::Write(const void *inBuffer, long inByteCount)
+{
+ return m_Stream->Write(inBuffer, inByteCount);
+}
+
+void COutStream::WriteData(const void *inBuffer, long inByteCount)
+{
+ long theLength = m_Stream->Write(inBuffer, inByteCount);
+ if (theLength < inByteCount) {
+ throw CIOException();
+ }
+}
+
+void COutStream::Flush()
+{
+ m_Stream->Flush();
+}
+
+void COutStream::Close()
+{
+ m_Stream->Close();
+}
+
+bool COutStream::IsValid()
+{
+ return m_Stream->IsValid();
+}
+
+//==============================================================================
+/**
+ * operator << double: Writes a double to the stream.
+ * This operator will write either a textual representation of the
+ *inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to
+ *hold the type).
+ * @param inValue double
+ *
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(double inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << float: Writes a float to the stream.
+ * This operator will write either a textual representation of the
+ *inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to
+ *hold the type).
+ * @param inValue double
+ *
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(float inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << long: Writes a long to the stream.
+ * This operator will write either a textual representation of the
+ *inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to
+ *hold the type).
+ *
+ * @param inValue long
+ *
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(long inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << unsigned long: Writes a long to the stream.
+ * This operator will write either a textual representation of the inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to hold the type).
+ * @param inValue long
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(unsigned long inValue)
+{
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << short: Writes a short to the stream.
+ * This operator will write either a textual representation of the inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to hold the type).
+ * @param inValue short
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(short inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << char: Writes a char to the stream.
+ * This operator will write either a textual representation of the inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to hold the type).
+ * @param inValue char
+ * @return The reference to this object
+ */
+//==============================================================================
+
+COutStream &COutStream::operator<<(char inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << unsigned char: Writes a char to the stream.
+ * This operator will write either a textual representation of the
+ *inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to
+ *hold the type).
+ *
+ * @param inValue char
+ *
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(unsigned char inValue)
+{
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << wchar_t: Writes a character to the stream.
+ * This operator will write either a textual representation of the inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to hold the type).
+ * @param inValue wchar_t
+ * @return The reference to this object
+ */
+//==============================================================================
+COutStream &COutStream::operator<<(wchar_t inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator << unsigned short: Writes a character to the stream.
+ * This operator will write either a textual representation of the inValue, or just
+ * X number of bytes to the stream (X is the number of bytes used to hold the type).
+ * @param inValue wchar_t
+ * @return The reference to this object
+ */
+//==============================================================================
+
+#if _MSC_VER >= 1400 // VS2005
+COutStream &COutStream::operator<<(unsigned short inValue)
+{
+ // in binary mode we just copy the number value byte for byte
+ WriteData((unsigned char *)&inValue, sizeof(inValue));
+ return *this;
+}
+#endif
+
+//==============================================================================
+/**
+ * operator >> double& : Read a double from the stream.
+ *
+ * @param outValue double&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(double &outValue)
+{
+ // read the number of bytes and copy it directly to the outvalue
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> float& : Read a float from the stream.
+ * @param outValue float&
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(float &outValue)
+{
+ // read the number of bytes and copy it directly to the outvalue
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> long& : Read a long from the stream.
+ *
+ * @param outValue long&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(long &outValue)
+{
+ // determine how many digits necessary to hold the requested number
+ // read the number of bytes and copy it directly to the outvalue
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> unsigned long& : Read an unsigned long from the stream.
+ *
+ * @param outValue unsigned long&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(unsigned long &outValue)
+{
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> short& : Read a short from the stream.
+ * @param outValue short&
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(short &outValue)
+{
+ // read the number of bytes and copy it directly to the outvalue
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> char& : Read an unsigned char from the stream.
+ *
+ * @param outValue unsigned char&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(unsigned char &outValue)
+{
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> char& : Read a char from the stream.
+ *
+ * @param outValue char&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(char &outValue)
+{
+ // get one bytes worth of data
+ ReadData((unsigned char *)&outValue, sizeof(outValue));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> wchar_t& : Read a wchar_t from the stream.
+ *
+ * @param outValue wchar_t&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+CInStream &CInStream::operator>>(wchar_t &outValue)
+{
+ // do a byte for byte read
+ ReadData((unsigned char *)&outValue, sizeof(wchar_t));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * operator >> unsigned short& : Read a unsigned short from the stream.
+ *
+ * @param outValue wchar_t&
+ *
+ * @return The reference to this object
+ * @exception An exception it thrown if there is a mismatch between the
+ * the type read and the destination type. If the _USE_EXCEPTIONS
+ *flag
+ * not defined, the outValue will contain the quiet NaN value.
+ */
+//==============================================================================
+
+#if _MSC_VER >= 1400 // VS2005
+CInStream &CInStream::operator>>(unsigned short &outValue)
+{
+ // do a byte for byte read
+ ReadData((unsigned char *)&outValue, sizeof(unsigned short));
+ return *this;
+}
+#endif
diff --git a/src/Authoring/Common/Code/IO/IOStreams.h b/src/Authoring/Common/Code/IO/IOStreams.h
new file mode 100644
index 00000000..5f5c6680
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/IOStreams.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_IO_STREAMS_H
+#define INCLUDED_IO_STREAMS_H 1
+
+#include "UICString.h"
+#include "InputStream.h"
+#include "OutputStream.h"
+#include "IOLibraryException.h"
+
+// The base formatting streams simply write out data to the stream
+
+class CInStream : public CInputStream
+{
+public:
+ CInStream();
+ CInStream(CInputStream *inStream);
+ CInStream(const CInStream &inInStream);
+ virtual ~CInStream();
+
+ virtual void SetInputStream(CInputStream *inStream);
+ virtual CInputStream *GetInputStream();
+
+ virtual void SetURL(const wchar_t *inURLString);
+ virtual void GetURL(wchar_t *ioURLString, const long &inSize);
+
+ virtual CInStream *Copy(CInputStream *inBase);
+ virtual CInStream *Copy();
+
+ virtual CInStream &operator>>(double &outValue);
+ virtual CInStream &operator>>(float &outValue);
+ virtual CInStream &operator>>(long &outValue);
+ virtual CInStream &operator>>(unsigned long &outValue);
+ virtual CInStream &operator>>(short &outValue);
+ virtual CInStream &operator>>(char &outValue);
+ virtual CInStream &operator>>(unsigned char &outValue);
+ virtual CInStream &operator>>(wchar_t &outValue);
+
+#if _MSC_VER >= 1400 // VS2005
+ virtual CInStream &operator>>(unsigned short &outValue);
+#endif
+
+ // CInputStream functions
+ long Read(void *outBuffer, long inByteCount) override;
+ void Close() override;
+ bool IsValid() override;
+ Q3DStudio::CString GetMimeType() override { return L""; }
+ Q3DStudio::CString GetSource() override { return L""; }
+
+ // Ease of use function
+ virtual void ReadData(void *inBuffer, long inBufferLength);
+
+protected:
+ CInputStream *m_Stream;
+ Q3DStudio::CString m_URLString;
+};
+
+class COutStream : public COutputStream
+{
+public:
+ COutStream();
+ COutStream(COutputStream *inStream);
+ virtual ~COutStream() {}
+
+ virtual void SetOutputStream(COutputStream *inStream);
+
+ virtual void SetURL(const wchar_t *inURLString);
+ virtual void GetURL(wchar_t *ioURLString, const long &inSize);
+
+ virtual COutStream *Copy(COutputStream *inBase);
+ virtual COutStream *Copy();
+
+ virtual COutStream &operator<<(double inValue);
+ virtual COutStream &operator<<(float inValue);
+ virtual COutStream &operator<<(long inValue);
+ virtual COutStream &operator<<(unsigned long inValue);
+ virtual COutStream &operator<<(short inValue);
+ virtual COutStream &operator<<(char inValue);
+ virtual COutStream &operator<<(unsigned char inValue);
+ virtual COutStream &operator<<(wchar_t inValue);
+
+#if _MSC_VER >= 1400 // VS2005
+ virtual COutStream &operator<<(unsigned short inValue);
+#endif
+
+ // Output Stream functions
+ long Write(const void *inBuffer, long inBufferLength) override;
+ void Flush() override;
+ void Close() override;
+ bool IsValid() override;
+
+ // Ease of use function
+ virtual void WriteData(const void *inBuffer, long inBufferLength);
+
+protected:
+ COutputStream *m_Stream;
+ Q3DStudio::CString m_URLString;
+};
+
+#endif // _IO_STREAMS_H
diff --git a/src/Authoring/Common/Code/IO/InputStream.h b/src/Authoring/Common/Code/IO/InputStream.h
new file mode 100644
index 00000000..27f18e99
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/InputStream.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_INPUT_STREAM_H
+#define INCLUDED_INPUT_STREAM_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Seekable.h"
+#include "UICString.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * \class CInputStream
+ * \brief
+ */
+class CInputStream : public Q3DStudio::ISeekable
+{
+public:
+ virtual ~CInputStream() {}
+
+ virtual long Read(void *inBuffer, long inBufferLength) = 0;
+ virtual void Close() = 0;
+ virtual bool IsValid() = 0;
+ virtual Q3DStudio::CString GetMimeType() = 0;
+ virtual Q3DStudio::CString GetSource() = 0;
+};
+
+#endif // INCLUDED_INPUT_STREAM_H
diff --git a/src/Authoring/Common/Code/IO/LEndianStreams.cpp b/src/Authoring/Common/Code/IO/LEndianStreams.cpp
new file mode 100644
index 00000000..825cedca
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/LEndianStreams.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h" //Where the defines for big or little endian must lie
+#include "LEndianStreams.h"
+#include "IOLibraryException.h"
+#include "UICEndian.h"
+
+CLEndianInStream::CLEndianInStream()
+{
+}
+
+CLEndianInStream::CLEndianInStream(CInputStream *inStream)
+ : CInStream(inStream)
+{
+}
+
+CLEndianInStream::CLEndianInStream(const CInStream &inStream)
+ : CInStream(inStream)
+{
+}
+
+CLEndianInStream::~CLEndianInStream()
+{
+}
+
+CInStream *CLEndianInStream::Copy(CInputStream *inBase)
+{
+ return new CLEndianInStream(inBase);
+}
+
+CInStream *CLEndianInStream::Copy()
+{
+ return new CLEndianInStream();
+}
+
+CInStream &CLEndianInStream::operator>>(double &)
+{
+ throw CIOException();
+}
+
+CInStream &CLEndianInStream::operator>>(float &outValue)
+{
+ long theData;
+ ReadData(&theData, sizeof(theData));
+ long *theValue = reinterpret_cast<long *>(&outValue);
+ LTOH4(theData, *theValue);
+ return *this;
+}
+
+CInStream &CLEndianInStream::operator>>(long &outValue)
+{
+ long theData;
+ ReadData(&theData, sizeof(theData));
+ long *theValue = reinterpret_cast<long *>(&outValue);
+ LTOH4(theData, *theValue);
+ return *this;
+}
+
+CInStream &CLEndianInStream::operator>>(unsigned long &outValue)
+{
+ unsigned long theData;
+ ReadData(&theData, sizeof(theData));
+ unsigned long *theValue = reinterpret_cast<unsigned long *>(&outValue);
+ LTOH4(theData, *theValue);
+ return *this;
+}
+
+CInStream &CLEndianInStream::operator>>(short &outValue)
+{
+ short theTemp;
+ ReadData(&theTemp, sizeof(theTemp));
+ LTOH2(theTemp, outValue);
+ return *this;
+}
+
+CInStream &CLEndianInStream::operator>>(wchar_t &outValue)
+{
+ wchar_t theTemp;
+ ReadData(&theTemp, sizeof(theTemp));
+ LTOH2(theTemp, outValue);
+ return *this;
+}
+
+CLEndianOutStream::CLEndianOutStream()
+{
+}
+
+CLEndianOutStream::CLEndianOutStream(COutputStream *inStream)
+ : COutStream(inStream)
+{
+}
+
+CLEndianOutStream::~CLEndianOutStream()
+{
+}
+
+COutStream *CLEndianOutStream::Copy(COutputStream *inBase)
+{
+ return new CLEndianOutStream(inBase);
+}
+
+COutStream *CLEndianOutStream::Copy()
+{
+ return new CLEndianOutStream();
+}
+
+COutStream &CLEndianOutStream::operator<<(double)
+{
+ throw CIOException();
+}
+
+COutStream &CLEndianOutStream::operator<<(float inValue)
+{
+ long *theTemp = reinterpret_cast<long *>(&inValue);
+ long theWritten;
+ HTOL4(*theTemp, theWritten);
+ WriteData(&theWritten, sizeof(theWritten));
+ return *this;
+}
+COutStream &CLEndianOutStream::operator<<(long inValue)
+{
+ long *theTemp = reinterpret_cast<long *>(&inValue);
+ long theWritten;
+ HTOL4(*theTemp, theWritten);
+ WriteData(&theWritten, sizeof(theWritten));
+ return *this;
+}
+COutStream &CLEndianOutStream::operator<<(unsigned long inValue)
+{
+ long *theTemp = reinterpret_cast<long *>(&inValue);
+ long theWritten;
+ HTOL4(*theTemp, theWritten);
+ WriteData(&theWritten, sizeof(theWritten));
+ return *this;
+}
+COutStream &CLEndianOutStream::operator<<(short inValue)
+{
+ short *theTemp = reinterpret_cast<short *>(&inValue);
+ short theWritten;
+ HTOL2(*theTemp, theWritten);
+ WriteData(&theWritten, sizeof(theWritten));
+ return *this;
+}
+
+COutStream &CLEndianOutStream::operator<<(wchar_t inValue)
+{
+ short *theTemp = reinterpret_cast<short *>(&inValue);
+ short theWritten;
+ HTOL2(*theTemp, theWritten);
+ WriteData(&theWritten, sizeof(theWritten));
+ return *this;
+}
diff --git a/src/Authoring/Common/Code/IO/LEndianStreams.h b/src/Authoring/Common/Code/IO/LEndianStreams.h
new file mode 100644
index 00000000..179ab3c5
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/LEndianStreams.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef LENDIANSTREAMSH
+#define LENDIANSTREAMSH
+#include "IOStreams.h"
+
+class CLEndianInStream : public CInStream
+{
+public:
+ CLEndianInStream();
+ CLEndianInStream(CInputStream *inStream);
+ CLEndianInStream(const CInStream &inStream);
+ virtual ~CLEndianInStream();
+
+ CInStream *Copy(CInputStream *inBase) override;
+ CInStream *Copy() override;
+
+ CInStream &operator>>(double &outValue) override;
+ CInStream &operator>>(float &outValue) override;
+ CInStream &operator>>(long &outValue) override;
+ CInStream &operator>>(unsigned long &outValue) override;
+ CInStream &operator>>(short &outValue) override;
+ CInStream &operator>>(wchar_t &outValue) override;
+};
+
+class CLEndianOutStream : public COutStream
+{
+public:
+ CLEndianOutStream();
+ CLEndianOutStream(COutputStream *inStream);
+ virtual ~CLEndianOutStream();
+
+ COutStream *Copy(COutputStream *inBase) override;
+ COutStream *Copy() override;
+
+ COutStream &operator<<(double inValue) override;
+ COutStream &operator<<(float inValue) override;
+ COutStream &operator<<(long inValue) override;
+ COutStream &operator<<(unsigned long inValue) override;
+ COutStream &operator<<(short inValue) override;
+ COutStream &operator<<(wchar_t inValue) override;
+};
+
+#endif
diff --git a/src/Authoring/Common/Code/IO/MemBuf.cpp b/src/Authoring/Common/Code/IO/MemBuf.cpp
new file mode 100644
index 00000000..5b1a7d52
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MemBuf.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#include <string.h>
+#include "MemBuf.h"
+#include "IOLibraryException.h"
+
+using namespace Q3DStudio;
+
+/**
+ @brief Sets member variables to the uninitialized state.
+*/
+CMemBuf::CMemBuf()
+{
+ m_Buffer = NULL;
+ m_Dirty = 0;
+ m_BufSize = 0;
+}
+
+/**
+ @brief Does nothing.
+*/
+CMemBuf::~CMemBuf()
+{
+}
+
+/**
+ @brief Return the current buffer size.
+ @return The current buffer size.
+*/
+long CMemBuf::GetSize()
+{
+ return m_BufSize;
+}
+/**
+ @brief returns the memory buffer without releasing it from the object.
+ @return The actual memory buffer.
+*/
+unsigned char *CMemBuf::GetBuffer()
+{
+ return m_Buffer;
+}
+/**
+ @brief returns the memory buffer, releasing it from the object.
+*/
+unsigned char *CMemBuf::Detach()
+{
+ unsigned char *theTemp = m_Buffer;
+ m_Buffer = NULL;
+ m_Dirty = 0;
+ m_BufSize = 0;
+ return theTemp;
+}
+
+/**
+ @brief Set the amount of dirty memory in the buffer.
+ The buffer will copy over this amount of memory to a new buffer
+ on resize, so setting this is only important if you care for
+ data persistence.
+ @param dirty The amount of dirty memory.
+*/
+void CMemBuf::SetDirty(long theDirty)
+{
+ m_Dirty = theDirty;
+}
+
+/**
+ @brief Return the amount of dirty memory in buffer.
+ @return The amount of data that is dirty.
+*/
+long CMemBuf::GetDirty()
+{
+ return m_Dirty;
+}
+
+/**
+ @brief Does nothing.
+*/
+CDynamicMemBuf::CDynamicMemBuf()
+ : m_DisableMinFlag(false)
+{
+}
+
+/**
+ @brief Deletes buffer if allocated.
+*/
+CDynamicMemBuf::~CDynamicMemBuf()
+{
+ if (m_Buffer != NULL) {
+ delete[] m_Buffer;
+ }
+}
+
+/**
+ @brief Sets the flag to prevent SetSize from allocating a MIN buffer size
+*/
+void CDynamicMemBuf::DisableMinimumBuffer(bool inFlag)
+{
+ m_DisableMinFlag = inFlag;
+}
+
+/**
+ @brief Set the size of the buffer, causing resize if larger.
+*/
+void CDynamicMemBuf::SetSize(long theSize)
+{
+ if (theSize > m_BufSize) {
+ unsigned char *theTemp;
+
+ // adjust size to allocate accordingly, keeping to at least MIN_SIZE (to prevent excessive
+ // fragmentation)
+ if (theSize < MIN_SIZE && !m_DisableMinFlag)
+ theSize = MIN_SIZE;
+ else if (theSize > MIN_SIZE)
+ theSize += MIN_SIZE - (theSize % MIN_SIZE);
+
+ // chia: exception would be thrown here if new fails
+ try {
+ theTemp = new unsigned char[theSize];
+ } catch (...) {
+ throw CIOException();
+ }
+
+ if (m_Buffer != NULL) {
+ if (m_Dirty != 0) {
+ // copy old to new
+ memcpy(theTemp, m_Buffer, m_Dirty);
+ }
+ delete[] m_Buffer;
+ }
+
+ m_Buffer = theTemp;
+
+ if (m_Buffer == NULL) {
+ throw CIOException();
+ }
+
+ m_BufSize = theSize;
+ m_Dirty = 0;
+ }
+}
+
+/**
+ @brief Set the memory of the object, deleting old memory
+ and not copying over old memory no matter if dirty or not.
+*/
+void CDynamicMemBuf::SetMem(unsigned char *theMem, long theSize)
+{
+ if (m_Buffer != NULL) {
+ delete[] m_Buffer;
+ }
+ m_BufSize = theSize;
+ m_Buffer = theMem;
+ m_Dirty = 0;
+}
+
+/**
+ @brief Does nothing.
+*/
+CStaticMemBuf::CStaticMemBuf()
+{
+}
+
+/**
+ @brief Does nothing.
+*/
+CStaticMemBuf::~CStaticMemBuf()
+{
+}
+
+/**
+ @brief Sets the memory buffers, does not delete old buffer.
+ @param mem The memory to set.
+ @param size The size of that memory.
+*/
+void CStaticMemBuf::SetMem(unsigned char *theMem, long theSize)
+{
+ m_BufSize = theSize;
+ m_Buffer = theMem;
+ m_Dirty = 0;
+}
+
+/**
+ @brief Set the size of the buffer.
+ @param size The size of the buffer.
+*/
+void CStaticMemBuf::SetSize(long)
+{
+ throw CIOException();
+}
diff --git a/src/Authoring/Common/Code/IO/MemBuf.h b/src/Authoring/Common/Code/IO/MemBuf.h
new file mode 100644
index 00000000..dc980042
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MemBuf.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MEMBUFH
+#define MEMBUFH
+
+namespace Q3DStudio {
+/**
+ @class CMemBuf
+ @brief Memory buffer class to encapsulate the handling of memory.
+*/
+
+class CMemBuf
+{
+public:
+ CMemBuf();
+ virtual ~CMemBuf();
+ virtual long GetSize();
+ virtual unsigned char *GetBuffer();
+ virtual unsigned char *Detach();
+ virtual void SetDirty(long theDirty);
+ virtual long GetDirty();
+ virtual void SetSize(long theSize) = 0;
+
+protected:
+ unsigned char *m_Buffer;
+ long m_BufSize;
+ long m_Dirty;
+};
+
+// used for dynamic memory, will delete in some cases
+/**
+ @class CDynamicMemBuf
+ @brief Encapsulates dealing with dynamic memory.
+*/
+class CDynamicMemBuf : public CMemBuf
+{
+public:
+ CDynamicMemBuf();
+ virtual ~CDynamicMemBuf();
+ virtual void SetMem(unsigned char *theMemPtr, long theSize);
+ void SetSize(long theSize) override;
+ virtual void DisableMinimumBuffer(bool inFlag);
+
+protected:
+ static const long MIN_SIZE = 65535;
+ bool m_DisableMinFlag;
+};
+
+// used for static memory that does not need to be deleted
+/**
+ @class CStaticMemBuf
+ @brief Encapsulates dealing with static memory.
+*/
+class CStaticMemBuf : public CMemBuf
+{
+public:
+ CStaticMemBuf();
+ virtual ~CStaticMemBuf();
+ virtual void SetMem(unsigned char *theMemPtr, long theSize);
+ void SetSize(long theSize) override;
+};
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/IO/MemInputStream.cpp b/src/Authoring/Common/Code/IO/MemInputStream.cpp
new file mode 100644
index 00000000..0d4b8da9
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MemInputStream.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#include <string.h>
+#include "MemInputStream.h"
+#include "IOLibraryException.h"
+
+//==========================================================================
+/**
+ */
+CMemInputStream::CMemInputStream()
+ : m_BasePtr(NULL)
+ , m_Length(0)
+ , m_Position(0)
+{
+}
+
+//==========================================================================
+/**
+ *
+ */
+CMemInputStream::~CMemInputStream()
+{
+}
+
+long CMemInputStream::Read(void *inBuffer, long inBufferLength)
+{
+ size_t theRead;
+ size_t theNeeded = (size_t)inBufferLength;
+ Read((char *)inBuffer, theNeeded, theRead);
+ return (long)theRead;
+}
+void CMemInputStream::Close()
+{
+}
+
+bool CMemInputStream::IsValid()
+{
+ return true;
+}
+
+//==========================================================================
+/**
+ *
+ */
+void CMemInputStream::Read(char *ioBuffer, size_t inLength, size_t &outRead)
+{
+ if (m_Position > m_Length) {
+ throw CIOException();
+ }
+
+ size_t theResult = m_Position + inLength;
+ // Make sure we can't become overdrawn
+ if (theResult >= m_Length) {
+ // Set length to the amount we will grant
+ inLength = inLength - (theResult - m_Length);
+ }
+ if (inLength != 0) {
+ memcpy(ioBuffer, m_BasePtr + m_Position, inLength);
+ m_Position += inLength;
+ }
+ outRead = inLength;
+}
+
+//==========================================================================
+/**
+ *
+ */
+long CMemInputStream::Seek(Q3DStudio::ISeekable::ESeekPosition inPosition, long inOffset)
+{
+ switch (inPosition) {
+ case Q3DStudio::ISeekable::EBEGIN: {
+ m_Position = 0;
+ break;
+ }
+ case Q3DStudio::ISeekable::ECURRENT: {
+ break;
+ }
+ case Q3DStudio::ISeekable::EEND: {
+ m_Position = m_Length;
+ break;
+ }
+ default: {
+ throw CIOException();
+ break;
+ }
+ }
+ if (inOffset < 0) {
+ inOffset = -inOffset;
+ if (inOffset > (long)m_Position) {
+ m_Position = 0;
+ } else {
+ m_Position = m_Position - inOffset;
+ }
+ } else {
+ size_t theResult = m_Position + inOffset;
+ if (theResult > m_Length) {
+ m_Position = m_Length;
+ } else {
+ m_Position = theResult;
+ }
+ }
+ return 0; // okay because we do implement seek
+}
+
+//==========================================================================
+/**
+ *
+ */
+long CMemInputStream::GetCurrentPosition()
+{
+ return (long)m_Position;
+}
+
+long CMemInputStream::GetLength()
+{
+ return (long)m_Length;
+}
diff --git a/src/Authoring/Common/Code/IO/MemInputStream.h b/src/Authoring/Common/Code/IO/MemInputStream.h
new file mode 100644
index 00000000..158edf2d
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MemInputStream.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AMXMEMSOURCEH
+#define AMXMEMSOURCEH
+#ifdef WIN32
+#pragma warning(disable : 4505)
+#endif
+#include "InputStream.h"
+#include <stddef.h>
+
+class CMemInputStream : public CInputStream
+{
+public:
+ CMemInputStream();
+ virtual ~CMemInputStream() = 0;
+ long Read(void *inBuffer, long inBufferLength) override;
+ void Close() override;
+ bool IsValid() override;
+ Q3DStudio::CString GetMimeType() override { return L""; }
+ Q3DStudio::CString GetSource() override { return L""; }
+ //========================================================================
+ /**
+ * Returns amount read into buffer, which could be zero.
+ * @param ioBuffer The buffer to read into.
+ * @param inLength The length to attempt to read.
+ * @param outRead the amount actually read.
+ */
+ virtual void Read(char *ioBuffer, size_t inLength, size_t &outRead);
+ //==========================================================================
+ /**
+ * Seeks to offset from position.
+ * @param inPosition The position to seek from.
+ * @param inOffset The offset to seek to.
+ */
+ long Seek(Q3DStudio::ISeekable::ESeekPosition inPosition, long inOffset) override;
+ //==========================================================================
+ /**
+ * Returns the current offset of the input pointer from the beginning of the
+ * sink.
+ */
+ long GetCurrentPosition() override;
+
+ virtual long GetLength();
+
+ virtual void SetMem(unsigned char *inMem, size_t inLength) = 0;
+
+ virtual void Detach(unsigned char *&outMem, size_t &outLength) = 0;
+
+protected:
+ unsigned char *m_BasePtr;
+ size_t m_Length;
+ size_t m_Position;
+};
+
+template <class T>
+class CFullMemInputStream : public CMemInputStream
+{
+public:
+ CFullMemInputStream()
+ : CMemInputStream(){}
+ virtual ~CFullMemInputStream(){}
+
+ virtual void SetMem(unsigned char *inMem, size_t inLength)
+ {
+ m_Buffer.SetMem(inMem, (unsigned long)inLength);
+ m_Position = 0;
+ ResetBasePtr((long)inLength);
+ }
+ virtual void Detach(unsigned char *&outMem, size_t &outLength)
+ {
+ outLength = (unsigned long)m_Length;
+ outMem = m_Buffer.Detach();
+ ResetBasePtr(0);
+ }
+ virtual void ResetBasePtr(long inLength)
+ {
+ m_BasePtr = m_Buffer.GetBuffer();
+ m_Length = inLength;
+ }
+ T m_Buffer;
+};
+
+#endif
diff --git a/src/Authoring/Common/Code/IO/MemOutputStream.cpp b/src/Authoring/Common/Code/IO/MemOutputStream.cpp
new file mode 100644
index 00000000..a484010f
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MemOutputStream.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#include <string.h>
+
+#include "MemOutputStream.h"
+#include "IOLibraryException.h"
+
+//==========================================================================
+/**
+ *
+ */
+CMemOutputStream::CMemOutputStream()
+ : m_BasePtr(NULL)
+ , m_Length(0)
+ , m_Position(0)
+{
+}
+
+//==========================================================================
+/**
+ *
+ */
+CMemOutputStream::~CMemOutputStream()
+{
+}
+
+//==========================================================================
+/**
+ *
+ */
+void CMemOutputStream::Write(const char *inData, unsigned long inLength, unsigned long &outWritten)
+{
+ unsigned long theResult = inLength + m_Position;
+ if (theResult > m_Length) {
+ // lets not pre-allocate such a large size
+ Enlarge(static_cast<unsigned long>(1.5 * theResult));
+ }
+ memcpy(m_BasePtr + m_Position, inData, inLength);
+
+ m_Position += inLength;
+
+ outWritten = inLength;
+}
+
+long CMemOutputStream::Write(const void *inBuffer, long inBufferLength)
+{
+ unsigned long theRet;
+ Write((char *)inBuffer, inBufferLength, theRet);
+ return (long)theRet;
+}
+
+//==========================================================================
+/**
+ *
+ */
+void CMemOutputStream::Flush()
+{
+}
+
+//==========================================================================
+/**
+ *
+ */
+long CMemOutputStream::Seek(ISeekable::ESeekPosition inPosition, long inOffset)
+{
+ switch (inPosition) {
+ case ISeekable::EBEGIN: {
+ m_Position = 0;
+ break;
+ }
+ case ISeekable::ECURRENT: {
+ break;
+ }
+ case ISeekable::EEND: {
+ m_Position = m_Length;
+ break;
+ }
+ default: {
+ throw CIOException();
+ break;
+ }
+ }
+ if (inOffset < 0) {
+ inOffset = -inOffset;
+ if (inOffset > (long)m_Position) {
+ m_Position = 0;
+ } else {
+ m_Position = m_Position - inOffset;
+ }
+ } else {
+ unsigned long theResult = m_Position + inOffset;
+ if (theResult > m_Length) {
+ m_Position = m_Length;
+ } else {
+ m_Position = theResult;
+ }
+ }
+ return 0; // okay because we implement seeking
+}
+
+//==========================================================================
+/**
+ *
+ */
+long CMemOutputStream::GetCurrentPosition()
+{
+ return (long)m_Position;
+}
+
+void CMemOutputStream::GetMem(unsigned char *&outMem, unsigned long &outLength)
+{
+ outMem = m_BasePtr;
+ outLength = m_Position;
+}
diff --git a/src/Authoring/Common/Code/IO/MemOutputStream.h b/src/Authoring/Common/Code/IO/MemOutputStream.h
new file mode 100644
index 00000000..2195d203
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MemOutputStream.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AMXMEMSINKH
+#define AMXMEMSINKH
+#include "OutputStream.h"
+
+class CMemOutputStream : public CSeekOutputStream
+{
+public:
+ CMemOutputStream();
+ virtual ~CMemOutputStream();
+ virtual void Write(const char *inData, unsigned long inLength, unsigned long &outWritten);
+ long Write(const void *inBuffer, long inBufferLength) override;
+ void Close() override {}
+ bool IsValid() override { return m_Position == m_Length; }
+ void Flush() override;
+ long Seek(ESeekPosition inPosition, long inOffset) override;
+ long GetCurrentPosition() override;
+ virtual void SetMem(unsigned char *inMem, unsigned long inLength) = 0;
+ virtual void GetMem(unsigned char *&outMem, unsigned long &inLength);
+ virtual void Detach(unsigned char *&outMem, unsigned long &outLength) = 0;
+ virtual void Enlarge(unsigned long inNewSize) = 0;
+
+protected:
+ unsigned char *m_BasePtr;
+ unsigned long m_Length;
+ unsigned long m_Position;
+};
+
+template <class T>
+class CFullMemOutputStream : public CMemOutputStream
+{
+public:
+ CFullMemOutputStream(){}
+ virtual ~CFullMemOutputStream(){}
+ virtual void Write(const char *inData, unsigned long inLength, unsigned long &outWritten)
+ {
+ CMemOutputStream::Write(inData, inLength, outWritten);
+ m_Buffer.SetDirty((long)m_Position);
+ }
+ virtual long Write(const void *inBuffer, long inBufferLength)
+ {
+ return CMemOutputStream::Write(inBuffer, inBufferLength);
+ }
+ virtual void SetMem(unsigned char *inMem, unsigned long inLength)
+ {
+ m_Buffer.SetMem(inMem, (unsigned long)inLength);
+ m_Position = 0;
+ ResetBasePtr();
+ }
+ virtual void Enlarge(unsigned long inNewSize)
+ {
+ m_Buffer.SetDirty((unsigned long)m_Position);
+ m_Buffer.SetSize((unsigned long)inNewSize);
+ ResetBasePtr();
+ }
+ virtual void Detach(unsigned char *&outMem, unsigned long &outLength)
+ {
+ outLength = m_Position;
+ outMem = m_Buffer.Detach();
+ m_Position = 0;
+ ResetBasePtr();
+ }
+ virtual void ResetBasePtr()
+ {
+ m_BasePtr = m_Buffer.GetBuffer();
+ m_Length = m_Buffer.GetSize();
+ }
+
+ T m_Buffer;
+};
+
+#endif
diff --git a/src/Authoring/Common/Code/IO/MessageTypes.h b/src/Authoring/Common/Code/IO/MessageTypes.h
new file mode 100644
index 00000000..eb9e8e59
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/MessageTypes.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _MESSAGE_TYPES_H
+#define _MESSAGE_TYPES_H 1
+
+/** All of these need to be changed to defined numbers to avoid future versions changing
+ * the types and creating incompatibilities.
+ */
+
+/** The request types in StudioMessages.
+ */
+class CElementTypes
+{
+public:
+ enum EElementTypes {
+ SEND_FILE = 1,
+ CHUNKED_SEND_FILE = 2,
+ LAME_SEND_FILE = 3,
+ CACHED_SEND_FILE = 4,
+ LAME_CACHED_SEND_FILE = 5,
+ STATISTICS = 6,
+ FILE_STATISTICS_LIST = 7,
+ FILE_STATISTICS = 8,
+ };
+};
+
+/** The attributes types for the elements in StudioMessages.
+ */
+class CAttributeTypes
+{
+public:
+ enum EAttributeTypes {
+ FILENAME = 1,
+ ERROR_MESSAGE = 2,
+ FILE_START_LOCATION = 3,
+ FILE_END_LOCATION = 4,
+ CHUNK_SIZE = 5,
+ PRIORITY = 6,
+ URGENCY = 7,
+
+ // Statistics Attributes
+ CONNECTED_COUNT = 1000,
+ BITRATE = 1001,
+ STREAM_COUNT = 1002,
+ TOTAL_REQUEST_COUNT = 1003,
+
+ };
+};
+
+/** The urgencies of the incoming messages.
+ */
+class CMessageUrgencies
+{
+public:
+ enum EMessageUrgencies {
+ URGENT = 1,
+ NORMAL = 0,
+ };
+};
+
+class CMessagePriorities
+{
+public:
+ enum EMessagePriorities {
+ LOW_PRIORITY = 0,
+ MED_PRIORITY = 1,
+ HIGH_PRIORITY = 2,
+ ULTRA_PRIORITY = 3,
+ };
+};
+#endif
diff --git a/src/Authoring/Common/Code/IO/OutputStream.h b/src/Authoring/Common/Code/IO/OutputStream.h
new file mode 100644
index 00000000..ee349d41
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/OutputStream.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_OUTPUT_STREAM_H
+#define INCLUDED_OUTPUT_STREAM_H 1
+#include "Seekable.h"
+
+// we probably want to change this architecture to match CInputStream which no longer has a seekable
+// version - AES 12/26/02
+
+class COutputStream
+{
+public:
+ virtual ~COutputStream() {}
+ virtual long Write(const void *inBuffer, long inBufferLength) = 0;
+ virtual void Flush() = 0;
+ virtual void Close() = 0;
+ virtual bool IsValid() = 0;
+};
+
+class CSeekOutputStream : public COutputStream, public Q3DStudio::ISeekable
+{
+public:
+ virtual ~CSeekOutputStream() {}
+};
+#endif // INCLUDED_OUTPUT_STREAM_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/IO/Seekable.cpp b/src/Authoring/Common/Code/IO/Seekable.cpp
new file mode 100644
index 00000000..8a2afb5b
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/Seekable.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#include "Seekable.h"
+using namespace Q3DStudio;
+
+// very important note: these methods (not destructor) must be overridden
+// for seekable streams.
+long ISeekable::Seek(ESeekPosition inPosition, long inOffset)
+{
+ Q_UNUSED(inPosition); // getting rid of not used warnings
+ Q_UNUSED(inOffset);
+ return SEEKABLE_METHOD_NOT_IMPLEMENTED;
+}
+
+long ISeekable::GetCurrentPosition()
+{
+ return SEEKABLE_METHOD_NOT_IMPLEMENTED;
+}
+
+ISeekable::~ISeekable()
+{
+}
diff --git a/src/Authoring/Common/Code/IO/Seekable.h b/src/Authoring/Common/Code/IO/Seekable.h
new file mode 100644
index 00000000..00ec704e
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/Seekable.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef STUDIOSEEKABLEH
+#define STUDIOSEEKABLEH
+
+#define SEEKABLE_METHOD_NOT_IMPLEMENTED -1
+
+namespace Q3DStudio {
+//==========================================================================
+/**
+ * @class ISeekable
+ * Abstract class to represent the ability to seek in a medium
+ */
+class ISeekable
+{
+public:
+ enum ESeekPosition { EBEGIN = 1, ECURRENT = 2, EEND = 3 };
+ //==========================================================================
+ /**
+ * DTOR-does nothing.
+ */
+ virtual ~ISeekable() = 0;
+ //==========================================================================
+ /**
+ * Seeks to offset from position.
+ * @param inPosition The position to seek from.
+ * @param inOffset The offset to seek to.
+ */
+ virtual long Seek(ESeekPosition inPosition, long inOffset);
+ //==========================================================================
+ /**
+ * Returns the current offset of the input pointer from the beginning of the
+ * sink.
+ */
+ virtual long GetCurrentPosition();
+};
+}
+#endif
diff --git a/src/Authoring/Common/Code/IO/UICEndian.h b/src/Authoring/Common/Code/IO/UICEndian.h
new file mode 100644
index 00000000..b483ab32
--- /dev/null
+++ b/src/Authoring/Common/Code/IO/UICEndian.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef ENDIANH
+#define ENDIANH
+#include "ByteSwap.h"
+
+#include <QtEndian>
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+#define UIC_BIG_ENDIAN
+#else
+#define UIC_LITTLE_ENDIAN
+#endif
+
+#ifdef UIC_LITTLE_ENDIAN
+#define LTOH2(in, out) out = in;
+#define HTOL2(in, out) out = in;
+
+#define LTOH4(in, out) out = in;
+#define HTOL4(in, out) out = in;
+
+#define LTOH8(in, out) out = in;
+#define HTOL8(in, out) out = in;
+
+#define BTOH2(in, out) SWAP2BYTES(in, out)
+#define HTOB2(in, out) SWAP2BYTES(in, out)
+
+#define BTOH4(in, out) SWAP4BYTES(in, out)
+#define HTOB4(in, out) SWAP4BYTES(in, out)
+
+#define BTOH8(in, out) SWAP8BYTES(in, out)
+#define HTOB8(in, out) SWAP8BYTES(in, out)
+
+#endif
+#ifdef UIC_BIG_ENDIAN
+#undef LTOH2
+#define LTOH2(in, out) SWAP2BYTES(in, out)
+#undef HTOL2
+#define HTOL2(in, out) SWAP2BYTES(in, out)
+
+#undef LTOH4
+#define LTOH4(in, out) SWAP4BYTES(in, out)
+#undef HTOL4
+#define HTOL4(in, out) SWAP4BYTES(in, out)
+
+#undef LTOH8
+#define LTOH8(in, out) SWAP8BYTES(in, out)
+#undef HTOL8
+#define HTOL8(in, out) SWAP8BYTES(in, out)
+
+#undef BTOH2
+#define BTOH2(in, out) out = in;
+#undef HTOB2
+#define HTOB2(in, out) out = in;
+
+#undef BTOH4
+#define BTOH4(in, out) out = in;
+#undef HTOB4
+#define HTOB4(in, out) out = in;
+
+#undef BTOH8
+#define BTOH8(in, out) out = in;
+#undef HTOB8
+#define HTOB8(in, out) out = in;
+#endif // ENDIANH
+
+#if !defined(UIC_LITTLE_ENDIAN) && !defined(UIC_BIG_ENDIAN)
+#error You must define either UIC_LITTLE_ENDIAN or UIC_BIG_ENDIAN
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Common/Code/InfoDump/CoutSink.cpp b/src/Authoring/Common/Code/InfoDump/CoutSink.cpp
new file mode 100644
index 00000000..b5f423df
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/CoutSink.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#include "stdafx.h"
+#include "CoutSink.h"
+
+//==============================================================================
+/**
+* Ctor
+*/
+CCoutSink::CCoutSink(const long &inPriority)
+ : CInfoSink(inPriority)
+{
+}
+
+//==============================================================================
+/**
+* Dtor
+*/
+CCoutSink::~CCoutSink()
+{
+}
+
+//==============================================================================
+/**
+* Consume information passed into the sink
+* @param inStr == the info to consume
+*/
+void CCoutSink::Sink(const wchar_t *inStr)
+{
+ std::wcout << inStr << std::endl;
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/InfoDump/CoutSink.h b/src/Authoring/Common/Code/InfoDump/CoutSink.h
new file mode 100644
index 00000000..b1a09561
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/CoutSink.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef _COUTDUMP_H__
+#define _COUTDUMP_H__
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+
+#include "InfoSink.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+* @class CCoutSink
+* Takes in information from CInfoDump ( and implementations of ) and dumps
+* it to the standard output using std::cwout
+*/
+class CCoutSink : public CInfoSink
+{
+public:
+ CCoutSink(const long &inPriority = CInfoSink::EDONT_CARE);
+ virtual ~CCoutSink();
+
+public:
+ void Sink(const wchar_t *inStr) override;
+};
+
+#endif
diff --git a/src/Authoring/Common/Code/InfoDump/DumpFileSink.cpp b/src/Authoring/Common/Code/InfoDump/DumpFileSink.cpp
new file mode 100644
index 00000000..8068d50e
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/DumpFileSink.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#include "stdafx.h"
+#include "DumpFileSink.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <fstream>
+#include "StrUtilities.h"
+
+//==============================================================================
+// Ctor & Dtor
+//==============================================================================
+//==============================================================================
+/**
+* Ctor
+*/
+CDumpFileSink::CDumpFileSink(const wchar_t *inFilename, const long &inPriority)
+ : CInfoSink(inPriority)
+ , m_Filename(inFilename)
+{
+ std::string theWFilename = "";
+ theWFilename << inFilename;
+
+ std::wofstream theStream;
+ theStream.open(theWFilename.c_str(),
+ std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
+ if (theStream.is_open())
+ theStream.close();
+ else
+ throw std::logic_error("CDumpFileSink::CDumpFileSink - cannot open file");
+}
+
+//==============================================================================
+/**
+* Dtor
+*/
+CDumpFileSink::~CDumpFileSink()
+{
+}
+
+//==============================================================================
+// Interface
+//==============================================================================
+//==============================================================================
+/**
+* Writes to a file, throws on error
+* @param inStr == the string to write, whcar_t type
+*/
+void CDumpFileSink::Sink(const wchar_t *inStr)
+{
+ // CConvertStr< wchar_t, char > theConvert;
+ std::string theFilename = "";
+ theFilename << m_Filename;
+
+ std::wofstream theStream;
+
+ theStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+ theStream.open(theFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::app
+ | std::ios_base::binary);
+
+ if (theStream.is_open()) {
+ theStream.seekp(std::ios_base::end);
+ theStream << inStr << L"\n";
+ theStream.flush();
+ theStream.close();
+
+ } else {
+ throw std::logic_error("CDumpFileSink::Sink - cannot open file");
+ }
+}
diff --git a/src/Authoring/Common/Code/InfoDump/DumpFileSink.h b/src/Authoring/Common/Code/InfoDump/DumpFileSink.h
new file mode 100644
index 00000000..7bd9d6e3
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/DumpFileSink.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef _DUMPFILESINK_H_
+#define _DUMPFILESINK_H_
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include <string>
+#include "InfoSink.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CDumpFileSink
+ * This class inherits a CInfoSink, it can/will be called by CInfoDump to
+ * dump wchar_t passed to it into a designated file
+ */
+class CDumpFileSink : public CInfoSink
+{
+ //==============================================================================
+ // Internal Data
+ //==============================================================================
+private:
+ std::wstring m_Filename;
+
+ //==============================================================================
+ // Ctor Dtor
+ //==============================================================================
+public:
+ CDumpFileSink(const wchar_t *inFilename, const long &inPriority = CInfoSink::EDONT_CARE);
+ ~CDumpFileSink();
+
+ //==============================================================================
+ // Interface
+ //==============================================================================
+public:
+ void Sink(const wchar_t *inStr) override;
+};
+
+#endif
diff --git a/src/Authoring/Common/Code/InfoDump/InfoDump.cpp b/src/Authoring/Common/Code/InfoDump/InfoDump.cpp
new file mode 100644
index 00000000..ab055e3e
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/InfoDump.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "InfoDump.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "InfoSink.h"
+
+//==============================================================================
+// Ctors and Dtor
+//==============================================================================
+//==============================================================================
+/**
+* Ctor
+*/
+CInfoDump::CInfoDump()
+ : m_DebugON(true)
+{
+ m_Buffer[0] = '\0';
+ m_SinkList.clear();
+}
+
+//==============================================================================
+/**
+* Dtor
+*/
+CInfoDump::~CInfoDump()
+{
+ // for ( TSinkListItr theItr = m_SinkList.begin( ); theItr != m_SinkList.end( ); ++theItr )
+ //{
+ // delete *theItr;
+ //}
+ m_SinkList.clear();
+}
+
+//==============================================================================
+// Interface
+//==============================================================================
+//==============================================================================
+/**
+* Dumps out the string
+* Loops through the vec of CInfoSink, pushes out the string
+*/
+void CInfoDump::DumpStr(const wchar_t *inStr, const long &inPriority, bool inDumpCondition)
+{
+ if (m_DebugON ? inDumpCondition : true) {
+ for (TSinkListItr theItr = m_SinkList.begin(); theItr != m_SinkList.end(); ++theItr) {
+ if ((*theItr)->MatchPriority(inPriority))
+ (*theItr)->Sink(inStr);
+ }
+ }
+}
+
+void CInfoDump::DumpStrIndent(const wchar_t *inStr, const long inIndentCount,
+ const long &inPriority, bool inDumpCondition)
+{
+ std::wstring theCompoStr = L"";
+
+ for (long theIndex = 0; theIndex < inIndentCount; ++theIndex) {
+ theCompoStr += L" ";
+ }
+
+ theCompoStr += inStr;
+
+ DumpStr(theCompoStr.c_str(), inPriority, inDumpCondition);
+}
+
+#include <stdarg.h>
+#include "StrUtilities.h"
+void CInfoDump::DumpCStr(const char *inFormatString, ...) // printf style
+{
+ /*
+ code snippet adopted from:
+ http://www.newtek.com/products/lightwave/developer/75lwsdk/docs/commands.html
+ */
+
+ // pb - 5.14.2004 - removed POS super slow code.
+ if (inFormatString)
+
+ {
+
+#ifdef _DEBUG
+ // only for debug...?
+ static char theArg[1024];
+ va_list ap;
+ va_start(ap, inFormatString);
+ vsprintf(theArg, inFormatString, ap);
+ va_end(ap);
+
+ std::wstring theWString;
+ theWString << theArg;
+ DumpStr(theWString.c_str());
+#endif
+ }
+}
+
+////==============================================================================
+///**
+//* Sets the output destination(s) of the this class
+//* @param inSink a new output destination
+//*/
+// void CInfoDump::SetSink( CInfoSink& inSink )
+//{
+// m_SinkList.push_back( &inSink );
+//}
+
+//==============================================================================
+/**
+* Sets the output destination(s) of the this class
+* @param inSink a new output destination
+*/
+void CInfoDump::SetSink(CInfoSink *inSink)
+{
+ // no duplicates
+ TSinkListItr theItr = m_SinkList.begin();
+ for (; theItr != m_SinkList.end(); ++theItr) {
+ if (*theItr == inSink)
+ break;
+ }
+ if (theItr == m_SinkList.end()) {
+ m_SinkList.push_back(inSink);
+ }
+}
+
+//==============================================================================
+/**
+* Sets the output destination(s) of the this class
+* @param inSink a new output destination
+*/
+void CInfoDump::SetSink(const CInfoDump::TSinkList &inSinkList)
+{
+ m_SinkList = inSinkList;
+}
+
+//==============================================================================
+/**
+* Retrieve the Sinks ref that's set
+*/
+const CInfoDump::TSinkList &CInfoDump::GetSinks()
+{
+ return m_SinkList;
+}
+
+//==============================================================================
+/**
+* Sets the output destination(s) of the this class
+* @param inSink a new output destination
+*/
+void CInfoDump::RemoveSink(CInfoSink *inSink)
+{
+ for (TSinkListItr theItr = m_SinkList.begin(); theItr != m_SinkList.end(); ++theItr) {
+ if (*theItr == inSink) {
+ m_SinkList.erase(theItr);
+ break;
+ }
+ }
+}
+
+//==============================================================================
+/**
+* Sets the mode of the InfoDump to Debug
+*
+*/
+void CInfoDump::SetAsDebug()
+{
+ m_DebugON = true;
+}
+
+//==============================================================================
+/**
+* Sets the mode of the InfoDump to Debug
+*
+*/
+void CInfoDump::SetAsUnitTest()
+{
+ m_DebugON = false;
+}
+
+//==============================================================================
+/**
+* Checks the debug mode
+*
+*/
+bool CInfoDump::GetDebugMode()
+{
+ return m_DebugON;
+}
diff --git a/src/Authoring/Common/Code/InfoDump/InfoDump.h b/src/Authoring/Common/Code/InfoDump/InfoDump.h
new file mode 100644
index 00000000..8bee4d6f
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/InfoDump.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef INFODUMP_H
+#define INFODUMP_H
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <vector>
+#include "StrUtilities.h"
+#include "InfoSink.h"
+#include <string>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CInfoDump
+ *
+ * This concrete class that formats output strings, manages output sources
+ * derived from CInfoSink, and "dump" outputs to the Sinks
+ * Supports multiple output destination.
+ *
+ * This class is responsible to hold/release the pointer of the InfoSink classes
+ */
+class CInfoDump
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef std::vector<CInfoSink *> TSinkList;
+ typedef TSinkList::iterator TSinkListItr;
+
+protected:
+ TSinkList m_SinkList;
+ char m_Buffer[1024];
+ bool m_DebugON;
+
+ //==============================================================================
+ // Ctor & Dtor
+ //==============================================================================
+public:
+ CInfoDump();
+ virtual ~CInfoDump();
+
+ //==============================================================================
+ // Interface
+ //==============================================================================
+public:
+ template <typename T>
+ void DumpVal(const std::wstring &inPrefix, const T &inVal,
+ const long &inPriority = CInfoSink::ELOG, bool inDumpCondition = true)
+ {
+ std::wstring theStr = inPrefix;
+ theStr << inVal;
+
+ DumpStr(theStr.c_str(), inPriority, inDumpCondition);
+ }
+
+ virtual void DumpStr(const wchar_t *inStr, const long &inPriority = CInfoSink::ELOG,
+ bool inDumpCondition = true);
+ virtual void DumpStrIndent(const wchar_t *inStr, const long inIndentCount,
+ const long &inPriority = CInfoSink::ELOG,
+ bool inDumpCondition = true);
+
+ virtual void DumpCStr(const char *inFormatString, ...); // printf style
+
+ // void SetSink( CInfoSink& inSink );
+ virtual void SetSink(CInfoSink *inSink);
+ virtual void SetSink(const TSinkList &inSinkList);
+ virtual const TSinkList &GetSinks();
+ virtual void RemoveSink(CInfoSink *inSink);
+
+ virtual void SetAsDebug();
+ virtual void SetAsUnitTest();
+ virtual bool GetDebugMode();
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Common/Code/InfoDump/InfoSink.cpp b/src/Authoring/Common/Code/InfoDump/InfoSink.cpp
new file mode 100644
index 00000000..8f056447
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/InfoSink.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#include "stdafx.h"
+#include "InfoSink.h"
+
+CInfoSink::CInfoSink(const long &inPriorityBits)
+ : m_PriorityBits(inPriorityBits)
+{
+}
+
+//==============================================================================
+// InfoSink Native
+//==============================================================================
+//==============================================================================
+/**
+* Sets the priority bits
+*/
+void CInfoSink::SetPriorityBits(const long &inPBits)
+{
+ m_PriorityBits = (m_PriorityBits | inPBits);
+}
+
+//==============================================================================
+/**
+* Gets the priority bits
+*/
+bool CInfoSink::MatchPriority(const long &inPBits)
+{
+ return ((m_PriorityBits & inPBits) != 0);
+}
diff --git a/src/Authoring/Common/Code/InfoDump/InfoSink.h b/src/Authoring/Common/Code/InfoDump/InfoSink.h
new file mode 100644
index 00000000..df2be77d
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/InfoSink.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef INFOSINK_H
+#define INFOSINK_H
+
+#include <string>
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CInfoSink
+ *
+ * This base class that defines the destination of all output to the CInfoDump
+ * It is the responsibility of the the InfoSink class to insert a "\r\n" to the
+ * incoming string
+ */
+class CInfoSink
+{
+ //==============================================================================
+ // Enum
+ //==============================================================================
+public:
+ enum EPriorityBits { ELOG = 1, EERR = 2, EDONT_CARE = 3 };
+
+protected:
+ long m_PriorityBits;
+
+ //==============================================================================
+ // Ctor & Dtor
+ //==============================================================================
+public:
+ CInfoSink(const long &inPriorityBits);
+ virtual ~CInfoSink() {}
+
+ //==============================================================================
+ // Interface
+ //==============================================================================
+public:
+ virtual void Sink(const wchar_t *inStr) = 0;
+ void SetPriorityBits(const long &inPBits);
+ bool MatchPriority(const long &inPBits);
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Common/Code/InfoDump/StrVecSink.cpp b/src/Authoring/Common/Code/InfoDump/StrVecSink.cpp
new file mode 100644
index 00000000..75ca6814
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/StrVecSink.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#include "stdafx.h"
+#include "StrVecSink.h"
+
+#include <fstream>
+#include <algorithm>
+#include <functional>
+#include <stdexcept>
+#include "StrUtilities.h"
+#include "DumpFileSink.h"
+
+//==============================================================================
+// Local Funks
+//==============================================================================
+namespace StrVecSink {
+typedef std::wstring::const_iterator TWSItr;
+typedef std::wstring::reverse_iterator TRWSItr;
+
+//==============================================================================
+/**
+* Trims white spaces before and after the "valid string" which begins wif
+* a non whitespace
+* @param inStr == the string to trim
+* @param outStr == the resultant string
+*/
+void TrimWhiteSpace(const std::wstring &inStr, std::wstring &outStr)
+{
+ const std::wstring WHITECHARS = L" \t\n";
+
+ // Trim the front
+ // makes sure theTempStr have some valid values
+ std::wstring theTempStr = inStr;
+ TWSItr theStrItr;
+ for (inStr.begin(); theStrItr != inStr.end(); ++theStrItr) {
+ bool theFoundWhiteSpace = false;
+ for (TWSItr theWSItr = WHITECHARS.begin(); theWSItr != WHITECHARS.end(); ++theWSItr) {
+ if (*theStrItr == *theWSItr) {
+ // found whitespace for the front, break
+ theFoundWhiteSpace = true;
+ break;
+ }
+ }
+
+ if (!theFoundWhiteSpace) {
+ // indicates we have encountered the first NON whitespace,
+ // reassign theTempStr and break
+ theTempStr = inStr.substr(std::distance(inStr.begin(), theStrItr));
+ break;
+ }
+ }
+
+ if (theStrItr == inStr.end()) {
+ // this means there's no valid char in this string, all are white spaces
+ // assign a blank string to theTempStr
+ theTempStr = L"";
+ }
+
+ // now we have the head portion trimmed, trim the tail portion
+ // first make sure outStr has some valid values
+ outStr = theTempStr;
+ for (TRWSItr theRStrItr = theTempStr.rbegin(); theRStrItr != theTempStr.rend(); ++theRStrItr) {
+ bool theFoundWhiteSpace = false;
+ for (TWSItr theWSItr = WHITECHARS.begin(); theWSItr != WHITECHARS.end(); ++theWSItr) {
+ if (*theRStrItr == *theWSItr) {
+ // found whitespace for the back, break
+ theFoundWhiteSpace = true;
+ break;
+ }
+ }
+
+ if (!theFoundWhiteSpace) {
+ // indicates we have encountered the first NON whitespace,
+ // reassign outStr and break
+ std::wstring::iterator theStrItr = theRStrItr.base();
+ outStr = theTempStr.substr(0, std::distance(theTempStr.begin(), theStrItr));
+ break;
+ }
+ }
+}
+}
+
+//==============================================================================
+// Cotr & Dtor
+//==============================================================================
+//==============================================================================
+/**
+* Ctor
+*/
+CStrVecSink::CStrVecSink(const long &inPriorityBits)
+ : CInfoSink(inPriorityBits)
+{
+}
+
+//==============================================================================
+/**
+* Copy Ctor
+*/
+CStrVecSink::CStrVecSink(const CStrVecSink &inStrVecSink)
+ : CInfoSink(inStrVecSink.m_PriorityBits)
+{
+ m_StrVec = inStrVecSink.m_StrVec;
+}
+
+//==============================================================================
+/**
+* Dtor
+*/
+CStrVecSink::~CStrVecSink()
+{
+}
+
+//==============================================================================
+/**
+* assign operator
+*/
+CStrVecSink &CStrVecSink::operator=(const CStrVecSink &inStrVecSink)
+{
+ if (this != &inStrVecSink) {
+ m_StrVec = inStrVecSink.m_StrVec;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+// Interface
+//==============================================================================
+//==============================================================================
+/**
+* Stores incoming info into a multiset
+* @param inStr == the info to consume
+*/
+void CStrVecSink::Sink(const wchar_t *inStr)
+{
+ if (inStr != NULL) {
+ std::wstring theStr = inStr;
+ std::wstring theTrimmed;
+ // Trims white spaces
+ StrVecSink::TrimWhiteSpace(theStr, theTrimmed);
+ m_StrVec.insert(theTrimmed);
+ }
+}
+
+//==============================================================================
+/**
+* Loads XML file using incoming filename, this is one of the 2 ways to use this
+* class.
+* @param inXMLFile == the incoming filename
+*/
+void CStrVecSink::LoadXML(const std::wstring &inXMLFile)
+{
+ std::string theFilename = "";
+ theFilename << inXMLFile;
+
+ std::wifstream theStream;
+ theStream.open(theFilename.c_str(), std::ios_base::in | std::ios_base::binary);
+
+ if (theStream.is_open()) {
+ std::wstring theBuffer = L"";
+ wchar_t theChar[8];
+ // size_t theRead = 0;
+ bool theDone = false;
+ for (; theDone == false;) {
+ theStream.read(theChar, 1);
+ if (theStream.gcount() != 1) {
+ if (theStream.eof() == false) {
+ throw std::logic_error("CStrVecSink::LoadXML - error");
+ } else {
+ theDone = true;
+ break;
+ }
+ }
+
+ if (theChar[0] == '\n') {
+ Sink(theBuffer.c_str());
+ theBuffer = L"";
+ } else {
+ theChar[1] = 0;
+ theBuffer << theChar;
+ }
+ }
+
+ theStream.close();
+ }
+}
+
+//==============================================================================
+/**
+* The total lines collected
+* @return the number of lines collected
+*/
+long CStrVecSink::GetTotalLines()
+{
+ return static_cast<long>(m_StrVec.size());
+}
+
+//==============================================================================
+/**
+* Extracts a line from the str vec
+* @param inIndex == the line index
+* @param outStr == the holding string
+* @return true if success, false otherwise
+*/
+bool CStrVecSink::RetrieveLine(const long inIndex, std::wstring &outStr)
+{
+ bool theReturn = true;
+ if (inIndex >= static_cast<long>(m_StrVec.size()) || inIndex < 0)
+ theReturn = false;
+
+ TStrVec::iterator theItr = m_StrVec.begin();
+ std::advance(theItr, inIndex);
+ outStr = *theItr;
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+* Finds the line equivalent to the inStr
+* @param inStr == line to look for
+* @return -1 for failure, success otherwise
+*/
+long CStrVecSink::FindThisLine(const std::wstring &inStr)
+{
+ long theReturn = -1;
+
+ TStrVec::iterator theItr = m_StrVec.find(inStr);
+ if (theItr != m_StrVec.end()) {
+ // found the first one, it doesnt matter which
+ theReturn = static_cast<long>(std::distance(m_StrVec.begin(), theItr));
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+* Finds the line equivalent to the inStr and remove it
+* @param inStr == line to look for
+* @return true for success, false otherwise
+*/
+bool CStrVecSink::FindAndRemoveLine(const std::wstring &inStr)
+{
+ bool theReturn = true;
+ long theLineIndex = -1;
+
+ if ((theLineIndex = FindThisLine(inStr)) == -1)
+ theReturn = false;
+
+ if (theReturn) {
+ bool theIsDelingLastLine = (theLineIndex == (long)m_StrVec.size() - 1);
+
+ TStrVec::iterator theItr = m_StrVec.begin();
+ std::advance(theItr, theLineIndex);
+
+ m_StrVec.erase(theItr);
+
+ if (!theIsDelingLastLine && !m_StrVec.empty())
+ theReturn = false;
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+* Match differences between inCompareSink and this Sink, puts the result in outSet
+* @param inComapreSink == the sink to compare to
+* @param outSet == the set of differences found
+*/
+std::vector<std::wstring>::iterator
+CStrVecSink::RetrieveDifferenceSet(CStrVecSink &inCompareSink, std::vector<std::wstring> &outSet)
+{
+ outSet.resize(m_StrVec.size() > inCompareSink.m_StrVec.size() ? m_StrVec.size()
+ : inCompareSink.m_StrVec.size());
+ return std::set_difference(m_StrVec.begin(), m_StrVec.end(), inCompareSink.m_StrVec.begin(),
+ inCompareSink.m_StrVec.end(), outSet.begin());
+}
+
+//==============================================================================
+/**
+* Enable the stored data to be dumped to file
+*/
+void CStrVecSink::ToFile(const std::wstring &inFilename)
+{
+ CDumpFileSink theFileSink(inFilename.c_str(), CInfoSink::EDONT_CARE);
+ std::wstring theBuffer;
+
+ for (std::multiset<std::wstring>::iterator theItr = m_StrVec.begin(); theItr != m_StrVec.end();
+ ++theItr) {
+ theBuffer << *theItr << "\n";
+ }
+ theFileSink.Sink(theBuffer.c_str());
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/InfoDump/StrVecSink.h b/src/Authoring/Common/Code/InfoDump/StrVecSink.h
new file mode 100644
index 00000000..bee694e7
--- /dev/null
+++ b/src/Authoring/Common/Code/InfoDump/StrVecSink.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef _STRVECSINK_H_
+#define _STRVECSINK_H_
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include <set>
+#include <vector>
+#include <string>
+#include "InfoSink.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CStrVecSink
+ *
+ * This base class that collects all the info passed from:
+ * 1 ) the InfoDump
+ * 2 ) an XML file
+ * Stores them as multisets of strings, which can be processed by various
+ * classes.
+ */
+class CStrVecSink : public CInfoSink
+{
+public:
+ typedef std::multiset<std::wstring> TStrVec;
+
+protected:
+ TStrVec m_StrVec;
+ //==============================================================================
+ // Cotr & Dtor
+ //==============================================================================
+public:
+ CStrVecSink(const long &inPriority);
+ CStrVecSink(const CStrVecSink &inStrVecSink);
+ virtual ~CStrVecSink();
+
+ CStrVecSink &operator=(const CStrVecSink &inStrVecSink);
+
+ //==============================================================================
+ // Interface
+ //==============================================================================
+public:
+ void Sink(const wchar_t *inStr) override;
+ void LoadXML(const std::wstring &inXMLFile);
+ long GetTotalLines();
+ bool RetrieveLine(const long inIndex, std::wstring &outStr);
+ long FindThisLine(const std::wstring &inStr);
+ bool FindAndRemoveLine(const std::wstring &inStr);
+ std::vector<std::wstring>::iterator RetrieveDifferenceSet(CStrVecSink &inCompareSink,
+ std::vector<std::wstring> &outSet);
+
+ void ToFile(const std::wstring &inFilename);
+};
+
+#endif
diff --git a/src/Authoring/Common/Code/LICENSE_FOREACH.TXT b/src/Authoring/Common/Code/LICENSE_FOREACH.TXT
new file mode 100644
index 00000000..ae45f8f0
--- /dev/null
+++ b/src/Authoring/Common/Code/LICENSE_FOREACH.TXT
@@ -0,0 +1,7 @@
+Permission to use, copy, modify, distribute and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appears in all copies and
+that both the copyright notice and this permission notice appear in
+supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
diff --git a/src/Authoring/Common/Code/ListIterator.h b/src/Authoring/Common/Code/ListIterator.h
new file mode 100644
index 00000000..92faa340
--- /dev/null
+++ b/src/Authoring/Common/Code/ListIterator.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __LISTITERATOR_H__
+#define __LISTITERATOR_H__
+
+//==============================================================================
+// Class
+//==============================================================================
+/**
+ * @class CListIterator
+ */
+template <class Obj, class List>
+class CListIterator
+{
+ // Typedefs
+ // Field members
+protected:
+ typename List::iterator m_Begin;
+ typename List::iterator m_Pos;
+ typename List::iterator m_End;
+
+ // Construction/Destruction
+public:
+ CListIterator(typename List::iterator inBegin, typename List::iterator inEnd);
+ ~CListIterator();
+
+ // Access
+public:
+ bool HasNext();
+ Obj GetCurrent();
+ CListIterator<Obj, List> operator++();
+ CListIterator<Obj, List> operator--();
+ CListIterator<Obj, List> operator+=(const long &inNum);
+ CListIterator<Obj, List> operator-=(const long &inNum);
+ operator typename List::iterator();
+ CListIterator<Obj, List> &operator=(const typename List::iterator &inIterator);
+};
+
+/**
+ * Constructs a list iterator based given the begin and end iterators for the List.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List>::CListIterator(typename List::iterator inBegin,
+ typename List::iterator inEnd)
+ : m_Begin(inBegin)
+ , m_Pos(inBegin)
+ , m_End(inEnd)
+{
+}
+
+/**
+ * Destructor
+ */
+template <class Obj, class List>
+CListIterator<Obj, List>::~CListIterator()
+{
+}
+
+/**
+ * Returns true if there is another item in the list.
+ */
+template <class Obj, class List>
+bool CListIterator<Obj, List>::HasNext()
+{
+ return m_Pos != m_End;
+}
+
+/**
+ * Obtains the current object in the list.
+ */
+template <class Obj, class List>
+Obj CListIterator<Obj, List>::GetCurrent()
+{
+ if (m_Pos != m_End)
+ return *m_Pos;
+ return NULL;
+}
+
+/**
+ * Increments the iterator to point to the next object in the list.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List> CListIterator<Obj, List>::operator++()
+{
+ if (m_Pos != m_End)
+ ++m_Pos;
+ return *this;
+}
+
+/**
+ * Decrements the iterator to point to the previous object in the list.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List> CListIterator<Obj, List>::operator--()
+{
+ if (m_Pos != m_Begin)
+ --m_Pos;
+ return *this;
+}
+
+/**
+ * Increments the iterator to point to the an object later in the list.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List> CListIterator<Obj, List>::operator+=(const long &inNum)
+{
+ if ((m_Pos + inNum) >= m_Begin && (m_Pos + inNum) < m_End)
+ m_Pos += inNum;
+ return *this;
+}
+
+/**
+ * Decrements the iterator to point to the an object earlier in the list.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List> CListIterator<Obj, List>::operator-=(const long &inNum)
+{
+ if ((m_Pos - inNum) >= m_Begin && (m_Pos - inNum) < m_End)
+ m_Pos -= inNum;
+ return *this;
+}
+
+/**
+ * Implicit cast operator to obtain the actual iterator from the container.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List>::operator typename List::iterator()
+{
+ return m_Pos;
+}
+
+/**
+ * Assignment operator for taking in an iterator of the container type.
+ */
+template <class Obj, class List>
+CListIterator<Obj, List> &CListIterator<Obj, List>::
+operator=(const typename List::iterator &inIterator)
+{
+ if (m_Pos != inIterator)
+ m_Pos = inIterator;
+
+ return *this;
+}
+
+#endif // __LISTITERATOR_H__ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Literals.h b/src/Authoring/Common/Code/Literals.h
new file mode 100644
index 00000000..764a6639
--- /dev/null
+++ b/src/Authoring/Common/Code/Literals.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef LITERALS_H
+#define LITERALS_H
+
+#include <QLatin1String>
+
+inline
+#ifndef WIN32
+constexpr
+#endif
+QLatin1String operator"" _L1 (const char *str, std::size_t len)
+{
+ return QLatin1String(str, len);
+}
+
+inline
+#ifndef WIN32
+constexpr
+#endif
+QLatin1Char operator"" _L1 (const char ch)
+{
+ return QLatin1Char(ch);
+}
+
+#endif //LITERALS_H
diff --git a/src/Authoring/Common/Code/MapIterator.h b/src/Authoring/Common/Code/MapIterator.h
new file mode 100644
index 00000000..4bb1546e
--- /dev/null
+++ b/src/Authoring/Common/Code/MapIterator.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __MAPITERATOR_H__
+#define __MAPITERATOR_H__
+
+//==============================================================================
+// Class
+//==============================================================================
+/**
+ * @class CMapIterator
+ */
+template <class Obj, class Map>
+class CMapIterator
+{
+ // Typedefs
+public:
+ typedef typename Map::iterator TMapItr;
+
+ // Field members
+protected:
+ typename Map::iterator m_Begin;
+ typename Map::iterator m_Pos;
+ typename Map::iterator m_End;
+
+ // Construction/Destruction
+public:
+ CMapIterator(TMapItr inBegin, TMapItr inEnd);
+ ~CMapIterator();
+
+ // Access
+public:
+ bool HasNext();
+ Obj GetCurrent();
+ CMapIterator<Obj, Map> operator++();
+ CMapIterator<Obj, Map> operator--();
+ CMapIterator<Obj, Map> operator+=(const long &inNum);
+ CMapIterator<Obj, Map> operator-=(const long &inNum);
+ operator typename Map::iterator();
+ CMapIterator<Obj, Map> &operator=(const typename Map::iterator &inIterator);
+};
+
+/**
+ * Constructs a Map iterator based given the begin and end iterators for the Map.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map>::CMapIterator(typename Map::iterator inBegin, typename Map::iterator inEnd)
+ : m_Begin(inBegin)
+ , m_Pos(inBegin)
+ , m_End(inEnd)
+{
+}
+
+/**
+ * Destructor
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map>::~CMapIterator()
+{
+}
+
+/**
+ * Returns true if there is another item in the Map.
+ */
+template <class Obj, class Map>
+bool CMapIterator<Obj, Map>::HasNext()
+{
+ return m_Pos != m_End;
+}
+
+/**
+ * Obtains the current object in the Map.
+ */
+template <class Obj, class Map>
+Obj CMapIterator<Obj, Map>::GetCurrent()
+{
+ return m_Pos->second;
+}
+
+/**
+ * Increments the iterator to point to the next object in the Map.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map> CMapIterator<Obj, Map>::operator++()
+{
+ if (m_Pos != m_End)
+ ++m_Pos;
+ return *this;
+}
+
+/**
+ * Decrements the iterator to point to the previous object in the Map.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map> CMapIterator<Obj, Map>::operator--()
+{
+ if (m_Pos != m_Begin)
+ --m_Pos;
+ return *this;
+}
+
+/**
+ * Increments the iterator to point to the an object later in the Map.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map> CMapIterator<Obj, Map>::operator+=(const long &inNum)
+{
+ if ((m_Pos + inNum) >= m_Begin && (m_Pos + inNum) < m_End)
+ m_Pos += inNum;
+ return *this;
+}
+
+/**
+ * Decrements the iterator to point to the an object earlier in the Map.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map> CMapIterator<Obj, Map>::operator-=(const long &inNum)
+{
+ if ((m_Pos - inNum) >= m_Begin && (m_Pos - inNum) < m_End)
+ m_Pos -= inNum;
+ return *this;
+}
+
+/**
+ * Implicit cast operator to obtain the actual iterator from the container.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map>::operator typename Map::iterator()
+{
+ return m_Pos;
+}
+
+/**
+ * Assignment operator for taking in an iterator of the container type.
+ */
+template <class Obj, class Map>
+CMapIterator<Obj, Map> &CMapIterator<Obj, Map>::operator=(const typename Map::iterator &inIterator)
+{
+ if (m_Pos != inIterator)
+ m_Pos = inIterator;
+
+ return *this;
+}
+
+#endif // __MAPITERATOR_H__ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/MasterP.cpp b/src/Authoring/Common/Code/MasterP.cpp
new file mode 100644
index 00000000..d0232f81
--- /dev/null
+++ b/src/Authoring/Common/Code/MasterP.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#ifdef PERFORM_PROFILE
+
+#include "MasterP.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+ * Constructor, this shouldn't be necessary since this has a static GetInstance.
+ * Use GetInstance instead to use all the same one.
+ */
+CMasterProf::CMasterProf()
+{
+}
+
+CMasterProf::~CMasterProf()
+{
+}
+
+//==============================================================================
+/**
+ * Get the One profiler.
+ * This is the instance that all method profilers register themselves on.
+ */
+CMasterProf *CMasterProf::GetInstance()
+{
+ static CMasterProf theProf;
+ return &theProf;
+}
+
+//==============================================================================
+/**
+ * Add a meth prof to the list of available profilers.
+ * This should be auto-called by the CMethProf class.
+ */
+void CMasterProf::AddMethProf(CMethProf *inMethProf)
+{
+ m_Profs.push_back(inMethProf);
+}
+
+//==============================================================================
+/**
+ * Reset all the statistics.
+ * This will clear all call counts and call times for all the method profilers
+ * in the system.
+ */
+void CMasterProf::Clear()
+{
+ // delete all the meth profs in here.
+ std::vector<CMethProf *>::iterator thePos = m_Profs.begin();
+ for (; thePos != m_Profs.end(); ++thePos) {
+ (*thePos)->Clear();
+ }
+}
+
+//==============================================================================
+/**
+ * Get the number of profilers in the system, used for iterating through the profilers.
+ */
+long CMasterProf::GetProfilerCount()
+{
+ return static_cast<long>(m_Profs.size());
+}
+
+//==============================================================================
+/**
+ * Get a profiler at inIndex.
+ * @param inIndex must be less than GetProfilerCount.
+ */
+CMethProf *CMasterProf::GetProfiler(long inIndex)
+{
+ return m_Profs.at(inIndex);
+}
+
+#endif // #ifdef PERFORM_PROFILE \ No newline at end of file
diff --git a/src/Authoring/Common/Code/MasterP.h b/src/Authoring/Common/Code/MasterP.h
new file mode 100644
index 00000000..9ad0aef9
--- /dev/null
+++ b/src/Authoring/Common/Code/MasterP.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_MASTER_PROF_H
+#define INCLUDED_MASTER_PROF_H 1
+
+#ifdef PERFORM_PROFILE
+
+#include "MethProf.h"
+
+/**
+To use it just add to the start of the section you are looking to profile:
+ UICPROFILE( MethodName );
+
+UICPROFILE is defined in MasterP.h
+
+The profiler uses a stack variable to start and stop, so it will automatically stop when it gets
+destructed.
+To profile sub sections of a method you can do:
+{
+ UICPROFILE( MethodName_Subsection );
+ CodeToBeProfiled( );
+}
+
+The naming convention is to use MethodName when profiling a method and MethodName_Subsection when
+doing a certain
+area of a method. This way it keeps clear the location of the profiling code.
+
+Note- the profiling does not give very good statistics on recursive functions.
+
+In playback enable the Profiling window, then use F7 to display the profiling statistics and F8 to
+reset them. F8
+is useful if you only want timing of playback with no loading, or if you only want statistics of
+certain sections.
+To see the profiling window make sure you have the debug menu turned on in your preferences
+(shift-prefs from the
+web player).
+
+The symbols in the lines printed out have the following info:
+Cc- Call Count: the number of times the profiling section was hit.
+Tt- Total Time: the total amount of time spent in the profiling section.
+Mt- Max Time: the maximum time spent in a single pass of the profiling section.
+At- Avg Time: the average time spent in a single section.
+
+Average time is really good for profiling specific methods and seeing what differences code changes
+make.
+
+Total Time is good for seeing how much time a specific method takes up of larger loops, such as
+taking the total
+time of player::update and comparing it to the total time of GLRenderUICMB::Render to see the
+percentage of the
+entire update cycle that rendering models is taking up.
+
+Max Time is good for tracking down periodic hitches in the system where something may have a decent
+average time,
+but periodically take a long time.
+
+Call Count is useful for checking that things get called the proper number of times, such as for
+loading a
+presentation a method should only be invoked once, but it may be called multiple times.
+*/
+
+class CMasterProf
+{
+public:
+ CMasterProf();
+ virtual ~CMasterProf();
+
+ static CMasterProf *GetInstance();
+
+ void AddMethProf(CMethProf *inMethProf);
+
+ void Clear();
+
+ long GetProfilerCount();
+ CMethProf *GetProfiler(long inIndex);
+
+protected:
+ std::vector<CMethProf *> m_Profs;
+};
+
+class CProfiler
+{
+public:
+ CProfiler(CMethProf *inMethProf)
+ {
+ m_MethProf = inMethProf;
+ m_MethProf->Start();
+ }
+
+ virtual ~CProfiler() { m_MethProf->Stop(); }
+
+protected:
+ CMethProf *m_MethProf;
+};
+
+#endif // #ifdef PERFORM_PROFILE
+
+// Super ninja code:
+//
+// Make a static variable within the function using inName to name it. Pass a reference to the
+// static variable to the stack based start/stop CProfiler. The CProfiler will then use the
+// static variable for keeping the statistics.
+//
+// Every time the section is entered the same static variable is used but a new Profiler is created.
+// It's important to have the unique naming as well, this will allow multiple profilers per
+// function.
+
+#ifdef PERFORM_PROFILE
+#define UICPROFILE(inName) \
+ static CMethProf the##inName##StaticProf(Q3DStudio::CString(__FUNCTION__) \
+ + Q3DStudio::CString("::") \
+ + Q3DStudio::CString(#inName)); \
+ CProfiler the##inName##Prof(&the##inName##StaticProf)
+
+#else
+#define UICPROFILE(inName)
+#endif
+
+#endif // INCLUDED_MASTER_PROF_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Matrix.inl b/src/Authoring/Common/Code/Matrix.inl
new file mode 100644
index 00000000..a11f8385
--- /dev/null
+++ b/src/Authoring/Common/Code/Matrix.inl
@@ -0,0 +1,687 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// CONSTRUCTION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Empty constructor. Initializes this matrix to the identity matrix.
+ */
+
+CMatrix::CMatrix()
+{
+ ::memcpy(m, s_Identity, sizeof(m));
+}
+
+//==============================================================================
+/**
+ * Copy constructor.
+ * @param inMatrix is the source matrix to copy
+ */
+
+CMatrix::CMatrix(const CMatrix &inMatrix)
+{
+ ::memcpy(m, inMatrix.m, sizeof(m));
+}
+
+//==============================================================================
+/**
+ * Assignment constructor. Initializes the matrix from an array.
+ * @param inComponents is an array of 16 values
+ */
+
+CMatrix::CMatrix(const float inComponents[])
+
+{
+
+ ::memcpy(m, inComponents, sizeof(m));
+}
+
+//==============================================================================
+// INITIALIZATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Sets this matrix to a NULL matrix with all values at zero.
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Zero()
+{
+ ::memset(m, 0, sizeof(m));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the matrix to the identity matrix.
+ * @return reference to this matrix
+ */
+
+CMatrix &CMatrix::Identity()
+{
+ ::memcpy(m, s_Identity, sizeof(m));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Copies the elements from another matrix.
+ * @param inMatrix is the source matrix
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Set(const CMatrix &inMatrix)
+{
+ ::memcpy(m, inMatrix.m, sizeof(m));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Copies the given components to this matrix.
+ * @param inComponents is an array of 16 components
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Set(const float inComponents[])
+
+{
+ ::memcpy(m, inComponents, sizeof(m));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Heavily optimized assignment method. This has the same result as creating
+ * four full 4x4 matrices and multiplying them together.
+ * @param inTranslation translation coordinates
+ * @param inRotation euler angle rotations
+ * @param inScale scaling dimensions
+ * @param inPivot pivot offset vector
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Set(const CVector3 &inTranslation, const CEulerAngles &inRotation,
+ const CVector3 &inScale, const CVector3 &inPivot)
+{
+ // TODO: MF - Since we are bypassing quaternions we have to assert that these angles are Studio
+ // angles
+ // assert( CEulerAngles::YXZr == inRotation.m_Order );
+
+ // Precalculate the sins and cosins.
+ float theSinX = ::sin(inRotation.m_Angle.x);
+ float theSinY = ::sin(inRotation.m_Angle.y);
+ float theSinZ = ::sin(inRotation.m_Angle.z);
+ float theCosX = ::cos(inRotation.m_Angle.x);
+ float theCosY = ::cos(inRotation.m_Angle.y);
+ float theCosZ = ::cos(inRotation.m_Angle.z);
+
+ // Precalulate the scaled rotation 3x3 matrix and populate the rotation section of our 4x4
+ // matrix
+ float r1 = inScale.x * ((theCosZ * theCosY) + (theSinX * theSinY * theSinZ));
+ m[0][0] = r1;
+ float r4 = inScale.x * (theCosX * theSinZ);
+ m[0][1] = r4;
+ float r7 = -inScale.x * ((theSinY * theCosZ) + (theSinZ * theCosY * theSinX));
+ m[0][2] = r7;
+ m[0][3] = 0;
+
+ float r2 = -inScale.y * ((theSinZ * theCosY) + (theSinX * theSinY * theCosZ));
+ m[1][0] = r2;
+ float r5 = inScale.y * (theCosX * theCosZ);
+ m[1][1] = r5;
+ float r8 = inScale.y * ((theSinY * theSinZ) + (theSinX * theCosY * theCosZ));
+ m[1][2] = r8;
+ m[1][3] = 0;
+
+ float r3 = inScale.z * (theSinY * theCosX);
+ m[2][0] = r3;
+ float r6 = -inScale.z * (theSinX);
+ m[2][1] = r6;
+ float r9 = inScale.z * (theCosX * theCosY);
+ m[2][2] = r9;
+ m[2][3] = 0;
+
+ // Reuse the scaled rotation matrix in the translation/pivot section of out 4x4 matrix
+ m[3][0] = inTranslation.x - r1 * inPivot.x - r2 * inPivot.y - r3 * inPivot.z;
+ m[3][1] = inTranslation.y - r4 * inPivot.x - r5 * inPivot.y - r6 * inPivot.z;
+ m[3][2] = inTranslation.z - r7 * inPivot.x - r8 * inPivot.y - r9 * inPivot.z;
+ m[3][3] = 1.0f;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the translation portion of the matrix without affecting the rest.
+ * If you want a pure translation matrix you must make sure to start with
+ * the identity matrix.
+ * @param inTranslate a translation vector
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::SetTranslate(const CVector3 &inTranslate)
+{
+ m[3][0] = inTranslate.x;
+
+ m[3][1] = inTranslate.y;
+
+ m[3][2] = inTranslate.z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the rotation portion of the matrix without affecting the rest.
+ * FYI: The rotate and scale portions overlap. If you want a pure scale matrix
+ * you must make sure to start with the identity matrix.
+ * @param inRotation a quaternion describing the rotaion
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::SetRotate(const CQuaternion &inRotation)
+{
+ inRotation.ToMatrix(*this);
+ return *this;
+
+ /* // Precalculate the sin and cos.
+
+ float theSinX = (float) sin( inRotation.x );
+
+ float theSinY = (float) sin( inRotation.y );
+
+ float theSinZ = (float) sin( inRotation.z );
+
+ float theCosX = (float) cos( inRotation.x );
+
+ float theCosY = (float) cos( inRotation.y );
+
+ float theCosZ = (float) cos( inRotation.z );
+
+
+
+ // Fill out the matrix.
+
+ m[0][0] = ( theCosZ * theCosY ) + ( theSinX * theSinY * theSinZ );
+
+ m[0][1] = -theCosX * -theSinZ;
+
+ m[0][2] = - ( theSinY * theCosZ ) + ( theSinZ * theCosY * theSinX );
+
+
+
+ m[1][0] = - ( theSinZ * theCosY ) + ( theSinX * theSinY * theCosZ );
+
+ m[1][1] = theCosX * theCosZ;
+
+ m[1][2] = ( theSinY * theSinZ ) + ( theSinX * theCosY * theCosZ );
+
+
+
+ m[2][0] = theSinY * theCosX;
+
+ m[2][1] = - theSinX;
+
+ m[2][2] = theCosX * theCosY;
+
+
+
+ // Set tranlate portion of matrix.
+
+ m[ 3 ][ 0 ] = 0.0f;
+
+ m[ 3 ][ 1 ] = 0.0f;
+
+ m[ 3 ][ 2 ] = 0.0f;
+
+ m[ 3 ][ 3 ] = 1.0f;*/
+}
+
+//==============================================================================
+/**
+ * Sets the scale portion of the matrix without affecting the rest.
+ * FYI: The rotate and scale portions overlap. If you want a pure scale matrix
+ * you must make sure to start with the identity matrix.
+ * @param inTranslate a scale vector
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::SetScale(const CVector3 &inScale)
+{
+ m[0][0] = inScale.x;
+
+ m[1][1] = inScale.y;
+
+ m[2][2] = inScale.z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the current matrix to describe a perspective matrix that produces
+ * a perspective projection. This is a DX style 0..1 clipping projection matrix.
+ *
+ * n=near, f=far, l=left, r=right, t=top, b=bottom <br>
+ * A = (r+l)/(r-l) <br>
+ * B = (t+b)/(t-b) <br>
+ * C = f/(f-n) <br>
+ * D = -fn/(f-n) <p>
+ *
+ * 2n/(r-l) 0 0 0
+ * 0 2n/(t-b) 0 0
+ * A B C 1
+ * 0 0 D 0
+ *
+ * @param inOrthographic true if the matrix should be orthographic, false for
+ * @return reference to this modified matrix
+ */
+CMatrix &CMatrix::SetFrustum(const bool inOrthographic, const float inNear, const float inFar,
+ const float inLeft, const float inTop, const float inRight,
+ const float inBottom)
+{
+ float theWidth = inRight - inLeft;
+ float theHeight = inBottom - inTop;
+ float theClipDist = inFar - inNear;
+
+ if (theWidth > 0 && theHeight > 0 && theClipDist > 0) {
+ float theWidthRecip = 1.0f / theWidth;
+ float theHeightRecip = 1.0f / theHeight;
+ float theClipRecip = 1.0f / theClipDist;
+
+ Identity();
+ if (inOrthographic) {
+ m[0][0] = 2.0f * theWidthRecip;
+ m[1][1] = 2.0f * theHeightRecip;
+ m[2][2] = 1.0f * theClipRecip;
+
+ m[3][0] = -(inRight + inLeft) * theWidthRecip;
+ m[3][1] = -(inTop + inBottom) * theHeightRecip;
+ m[3][2] = (-inFar * theClipRecip) + 1.0f; //-(inFar+inNear) * theClipRecip;
+ m[3][3] = 1.0f;
+ } else {
+ m[0][0] = 2.0f * inNear * theWidthRecip;
+ m[1][1] = 2.0f * inNear * theHeightRecip;
+ m[2][0] = -(inRight + inLeft) * theWidthRecip;
+ m[2][1] = -(inBottom + inTop) * theHeightRecip;
+ m[2][2] = inFar * theClipRecip; // C
+ m[2][3] = 1.0f;
+ m[3][2] = (-inFar * inNear) * theClipRecip; // D
+ m[3][3] = 0.0f;
+ }
+ }
+
+ return *this;
+}
+
+//==============================================================================
+// FUNCTIONS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Check this matrix against the identity matrix.
+ * @return true if this matrix is equivalent to the identity matrix
+ */
+
+bool CMatrix::IsIdentity() const
+{
+ return *this == s_Identity;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is affine.
+ * An affine matrix has the last row being [ 0 0 0 1 ]
+ * @return true if the matrix is affine
+ */
+bool CMatrix::IsAffine() const
+{
+ return m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1.0f;
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include a translation. Equivalent to post-multiplying
+ * this matrix with a transformation matrix derived from the given vector.
+ * @param inVector is the transformation vector applied
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Translate(const CVector3 &inTranslation)
+{
+ m[3][0] += m[0][0] * inTranslation.x + m[1][0] * inTranslation.y + m[2][0] * inTranslation.z;
+ m[3][1] += m[0][1] * inTranslation.x + m[1][1] * inTranslation.y + m[2][1] * inTranslation.z;
+ m[3][2] += m[0][2] * inTranslation.x + m[1][2] * inTranslation.y + m[2][2] * inTranslation.z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include a rotation. Equivalent to post-multiplying
+ * this matrix with a rotation matrix derived from the given quaternion.
+ * @param inRotation is the rotation quaternion applied
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Rotate(const CQuaternion &inRotation)
+{
+ CMatrix theRotation;
+ return MultiplyAffine(inRotation.ToMatrix(theRotation));
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include scaling. Equivalent to post-multiplying
+ * this matrix with a scale matrix derived from the given vector.
+ * @param inVector is the scale vector applied
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Scale(const CVector3 &inScale)
+{
+ m[0][0] *= inScale.x;
+ m[0][1] *= inScale.x;
+ m[0][2] *= inScale.x;
+
+ m[1][0] *= inScale.y;
+ m[1][1] *= inScale.y;
+ m[1][2] *= inScale.y;
+
+ m[2][0] *= inScale.z;
+ m[2][1] *= inScale.z;
+ m[2][2] *= inScale.z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Flips the matrix elements around the identity diagonal.
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::Transpose()
+
+{
+ float theSwap = m[1][0];
+ m[1][0] = m[0][1];
+ m[0][1] = theSwap;
+
+ theSwap = m[2][0];
+ m[2][0] = m[0][2];
+ m[0][2] = theSwap;
+
+ theSwap = m[3][0];
+ m[3][0] = m[0][3];
+ m[0][3] = theSwap;
+
+ theSwap = m[2][1];
+ m[2][1] = m[1][2];
+ m[1][2] = theSwap;
+
+ theSwap = m[3][1];
+ m[3][1] = m[1][3];
+ m[1][3] = theSwap;
+
+ theSwap = m[3][2];
+ m[3][2] = m[2][3];
+ m[2][3] = theSwap;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Computes the inverse of a 3D affine matrix; i.e. a matrix with a dimen-
+ * sionality of 4 where the bottom row has the entries (0, 0, 0, 1).
+ *
+ * This procedure treats the 4 by 4 matrix as a block matrix and
+ * calculates the inverse of one submatrix for a significant performance
+ * improvement over a general procedure that can invert any non-singular matrix:
+ * (see code for correct formatting of matrix)
+ *
+ * | | -1 | -1 -1 | <br>
+ * | A C | | A -C A | <br>
+ * -1 | | | | <br>
+ * M = | | = | | <br>
+ * | 0 1 | | 0 1 | <br>
+ * | | | | <br>
+ *
+ * where M is a 4 by 4 matrix,
+ * A is the 3 by 3 upper left submatrix of M,
+ * C is the 3 by 1 upper right submatrix of M.
+ *
+ * @return the determinant of matrix
+ */
+float CMatrix::Invert()
+{
+ const float PRECISIONLIMIT(1.0e-07f);
+ float thePositiveDet(0.0f);
+ float theNegativeDet(0.0f);
+ float theTempDet;
+
+ // Calculate the determinant of submatrix A and determine if the
+ // the matrix is singular as limited by the float precision.
+ theTempDet = m[0][0] * m[1][1] * m[2][2];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m[0][1] * m[1][2] * m[2][0];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m[0][2] * m[1][0] * m[2][1];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m[0][2] * m[1][1] * m[2][0];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m[0][1] * m[1][0] * m[2][2];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m[0][0] * m[1][2] * m[2][1];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ // Is the submatrix A nonsingular? (i.e. there is an inverse?)
+ float theDeterminant = thePositiveDet + theNegativeDet;
+ if (theDeterminant != 0
+ || ::abs(theDeterminant / (thePositiveDet - theNegativeDet)) >= PRECISIONLIMIT) {
+ CMatrix theInverse;
+ float theInvDeterminant = 1.0f / theDeterminant;
+
+ // Calculate inverse(A) = adj(A) / det(A)
+ theInverse.m[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * theInvDeterminant;
+ theInverse.m[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * theInvDeterminant;
+ theInverse.m[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * theInvDeterminant;
+ theInverse.m[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) * theInvDeterminant;
+ theInverse.m[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * theInvDeterminant;
+ theInverse.m[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * theInvDeterminant;
+ theInverse.m[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * theInvDeterminant;
+ theInverse.m[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * theInvDeterminant;
+ theInverse.m[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * theInvDeterminant;
+
+ // Calculate -C * inverse(A)
+ theInverse.m[3][0] = -(m[3][0] * theInverse.m[0][0] + m[3][1] * theInverse.m[1][0]
+ + m[3][2] * theInverse.m[2][0]);
+ theInverse.m[3][1] = -(m[3][0] * theInverse.m[0][1] + m[3][1] * theInverse.m[1][1]
+ + m[3][2] * theInverse.m[2][1]);
+ theInverse.m[3][2] = -(m[3][0] * theInverse.m[0][2] + m[3][1] * theInverse.m[1][2]
+ + m[3][2] * theInverse.m[2][2]);
+
+ // Assing ourselves to the inverse
+ *this = theInverse;
+ }
+
+ return theDeterminant;
+}
+
+//==============================================================================
+/**
+ * Fast multiplication of two affine 4x4 matrices. No affine pre-check.
+ * TODO: MF - Convert to SSE Assembly Code
+ * @return reference to this modified matrix
+ */
+CMatrix &CMatrix::MultiplyAffine(const CMatrix &inMatrix)
+{
+ float theMult[4][4];
+
+ theMult[0][0] =
+ m[0][0] * inMatrix.m[0][0] + m[0][1] * inMatrix.m[1][0] + m[0][2] * inMatrix.m[2][0];
+ theMult[0][1] =
+ m[0][0] * inMatrix.m[0][1] + m[0][1] * inMatrix.m[1][1] + m[0][2] * inMatrix.m[2][1];
+ theMult[0][2] =
+ m[0][0] * inMatrix.m[0][2] + m[0][1] * inMatrix.m[1][2] + m[0][2] * inMatrix.m[2][2];
+ theMult[0][3] = 0;
+
+ theMult[1][0] =
+ m[1][0] * inMatrix.m[0][0] + m[1][1] * inMatrix.m[1][0] + m[1][2] * inMatrix.m[2][0];
+ theMult[1][1] =
+ m[1][0] * inMatrix.m[0][1] + m[1][1] * inMatrix.m[1][1] + m[1][2] * inMatrix.m[2][1];
+ theMult[1][2] =
+ m[1][0] * inMatrix.m[0][2] + m[1][1] * inMatrix.m[1][2] + m[1][2] * inMatrix.m[2][2];
+ theMult[1][3] = 0;
+
+ theMult[2][0] =
+ m[2][0] * inMatrix.m[0][0] + m[2][1] * inMatrix.m[1][0] + m[2][2] * inMatrix.m[2][0];
+ theMult[2][1] =
+ m[2][0] * inMatrix.m[0][1] + m[2][1] * inMatrix.m[1][1] + m[2][2] * inMatrix.m[2][1];
+ theMult[2][2] =
+ m[2][0] * inMatrix.m[0][2] + m[2][1] * inMatrix.m[1][2] + m[2][2] * inMatrix.m[2][2];
+ theMult[2][3] = 0;
+
+ theMult[3][0] = m[3][0] * inMatrix.m[0][0] + m[3][1] * inMatrix.m[1][0]
+ + m[3][2] * inMatrix.m[2][0] + inMatrix.m[3][0];
+ theMult[3][1] = m[3][0] * inMatrix.m[0][1] + m[3][1] * inMatrix.m[1][1]
+ + m[3][2] * inMatrix.m[2][1] + inMatrix.m[3][1];
+ theMult[3][2] = m[3][0] * inMatrix.m[0][2] + m[3][1] * inMatrix.m[1][2]
+ + m[3][2] * inMatrix.m[2][2] + inMatrix.m[3][2];
+ theMult[3][3] = 1.0f;
+
+ Set(&theMult[0][0]);
+ return *this;
+}
+
+//==============================================================================
+// OPERATORS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Simple assignment operator.
+ * @param inIndex
+ * @return reference to this modified matrix
+ */
+
+CMatrix &CMatrix::operator=(const CMatrix &inMatrix)
+{
+ ::memcpy(m, inMatrix.m, sizeof(m));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compares this matrix's elements with another matrix's and returns true
+ * if the matrices are equivalent.
+ * @param inMatrix is the matrix we are comparing against
+ * @return true if all elements are within EPSILON of each other.
+ */
+
+bool CMatrix::operator==(const CMatrix &inMatrix) const
+{
+ for (int iRow = 0; iRow < 4; ++iRow)
+ for (int iCol = 0; iCol < 4; ++iCol)
+ if (::abs(m[iRow][iCol] - inMatrix.m[iRow][iCol]) > EPSILON)
+ return false;
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * Compares this matrix's elements with another matrix's and returns true
+ * if the matrices are not equivalent.
+ * @param inMatrix is the matrix we are comparing against
+ * @return true if one or more elements are more than EPSILON from each other
+ */
+
+bool CMatrix::operator!=(const CMatrix &inMatrix) const
+{
+ for (int iRow = 0; iRow < 4; ++iRow)
+ for (int iCol = 0; iCol < 4; ++iCol)
+ if (::abs(m[iRow][iCol] - inMatrix.m[iRow][iCol]) <= EPSILON)
+ return false;
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * Allows direct access to the row. This allows fast direct access in the
+ * form of CMatrix[row][column].
+ * @param inRow is the row index, starting at zero
+ * @return a pointer to the first element
+ */
+
+float *CMatrix::operator[](int inRow)
+{
+ return &m[inRow][0];
+}
+
+//==============================================================================
+/**
+ * Allows const direct access to the row. This allows fast direct access in the
+ * form of CMatrix[row][column] from other const code.
+ * @param inRow is the row index, starting at zero
+ * @return a const pointer to the first element
+ */
+
+const float *CMatrix::operator[](int inRow) const
+{
+ return &m[inRow][0];
+}
diff --git a/src/Authoring/Common/Code/Memory/IMemoryObject.h b/src/Authoring/Common/Code/Memory/IMemoryObject.h
new file mode 100644
index 00000000..641a64b7
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/IMemoryObject.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __IMemoryObject_H_
+#define __IMemoryObject_H_
+
+namespace Q3DStudio {
+
+// Forwards
+class IMemoryObject;
+
+//==============================================================================
+/**
+ * This is an abstract interface for firing memeory object events.
+ */
+class IMemoryObjectListener
+{
+ // Interface
+public:
+ ///> Called when a new memory object is registered
+ virtual void OnMemoryObjectRegistered(IMemoryObject *inMemoryObject) = 0;
+ ///> Called when a memory object is removed
+ virtual void OnMemoryObjectUnRegistered(IMemoryObject *inMemoryObject) = 0;
+};
+
+//==============================================================================
+/**
+ * This is an abstract interface for traversing hierarchies of memeory objects.
+ *
+ * An IMemoryObject maintains information about the memory usage of the object
+ * and a list of child memory objects. Detailed information about object memory
+ * can be exposed by the detail object.
+ */
+class IMemoryObject
+{
+ // Typedefs
+public:
+ typedef std::vector<IMemoryObject *> TObjectList; ///< typedef for child memory objects
+ typedef TObjectList::const_iterator
+ TObjectListIt; ///< typedef for iterator of child memory objects
+
+ typedef std::pair<const char *, long> TDetailType; ///< typedef of the detail data
+ typedef std::vector<TDetailType> TDetailList; ///< typedef for details of memory object
+ typedef TDetailList::const_iterator
+ TDetailListIt; ///< typedef for iterator of details of memory object
+
+ // Interface
+public:
+ ///> Returns the name of the memory object
+ virtual const char *GetMemoryObjectName() const = 0;
+
+ ///> Return a description of the object
+ virtual const char *GetMemoryObjectDescription() const = 0;
+
+ ///> Returns the unique id of the memory object. This allows another thread (or a UI thread)
+ ///> to listen to object deletion events and handle the event in another thread without
+ ///> worrying that the pointer to the memory object will go out of scope before the other
+ ///> thread has a chance to handle the deletion.
+ virtual long GetMemoryObjectId() const = 0;
+ virtual IMemoryObject *FindMemoryObjectId(long inId) const = 0;
+
+ ///> Register a child memory object. These are objects that are "owned" by this object
+ virtual void RegisterMemoryObject(IMemoryObject *inMemoryObject) = 0;
+ virtual void UnregisterMemoryObject(IMemoryObject *inMemoryObject) = 0;
+
+ ///> Register a listener for memory change events
+ virtual void RegisterMemoryObjectListener(IMemoryObjectListener *inMemoryObjectListener) = 0;
+ virtual void UnregisterMemoryObjectListener(IMemoryObjectListener *inMemoryObjectListener) = 0;
+
+ ///> Returns the size of the base object (sizeof)
+ virtual long GetMemoryObjectBase() const = 0;
+
+ ///> Returns the size of the base object (sizeof) and any dynamic memory
+ virtual long GetMemoryObjectUsage() const = 0;
+
+ ///> Returns the size of the base object (sizeof), any dynamic memory and the total size of any
+ ///children
+ virtual long GetMemoryObjectTotal() const = 0;
+
+ ///> Iterate through child memory objects
+ virtual const TObjectListIt GetMemoryObjectBegin() const = 0;
+ virtual const TObjectListIt GetMemoryObjectEnd() const = 0;
+
+ ///> Iterate through the details of the memory objects dynamic memory
+ virtual const TDetailListIt GetMemoryObjectDetailBegin() const = 0;
+ virtual const TDetailListIt GetMemoryObjectDetailEnd() const = 0;
+
+ ///> Store the parent of the object so that it can be notified when the object is destroyed
+ virtual void SetMemoryObjectParent(IMemoryObject *inMemoryObject) = 0;
+};
+
+} // namespace Q3DStudio
+
+#endif //__IMemoryObject_H_
diff --git a/src/Authoring/Common/Code/Memory/MemoryObject.cpp b/src/Authoring/Common/Code/Memory/MemoryObject.cpp
new file mode 100644
index 00000000..d3c63101
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/MemoryObject.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MemoryObject.h"
+#include "UICString.h"
+#include "UICFunctor.h"
+#include "Multicaster.h"
+
+//==============================================================================
+// CMemoryObjectDetail
+//==============================================================================
+
+/**
+ * Constructor
+ */
+CMemoryObjectDetail::CMemoryObjectDetail()
+{
+ Clear();
+}
+
+/**
+ * Add some memory detail
+ */
+void CMemoryObjectDetail::Add(const char *inName, long inSize)
+{
+ m_DetailList.push_back(std::make_pair(inName, inSize));
+ m_TotalSize += inSize;
+}
+
+/**
+ * Clear the detail list
+ */
+void CMemoryObjectDetail::Clear()
+{
+ m_TotalSize = 0;
+ m_DetailList.clear();
+}
+
+//==============================================================================
+// CMemoryObject
+//==============================================================================
+
+long CMemoryObject::s_MemoryObjectID = 0; ///< static variable used for generating unique id's
+
+/**
+ * Constructor
+ */
+CMemoryObject::CMemoryObject(const char *inName, long inStaticSize,
+ Q3DStudio::IMemoryObject *inMemoryObject)
+ : m_ID(++s_MemoryObjectID)
+ , m_StaticSize(inStaticSize)
+ , m_Name(inName)
+ , m_MemoryObject(inMemoryObject)
+ , m_MemoryObjectParent(NULL)
+ , m_SizeFunctor(NULL)
+{
+}
+
+/**
+ * Copy Constructor
+ */
+CMemoryObject::CMemoryObject(const CMemoryObject &inSource,
+ Q3DStudio::IMemoryObject *inMemoryObject)
+ : m_ID(++s_MemoryObjectID)
+ , m_MemoryObjectParent(NULL)
+ , m_SizeFunctor(NULL)
+{
+ m_Name = inSource.m_Name;
+ m_StaticSize = inSource.m_StaticSize;
+ m_MemoryObject = inMemoryObject;
+}
+
+/**
+ * Destructor
+ */
+CMemoryObject::~CMemoryObject()
+{
+ if (m_MemoryObjectParent && m_MemoryObject)
+ m_MemoryObjectParent->UnregisterMemoryObject(m_MemoryObject);
+ else if (m_MemoryObject)
+ m_ChangeListener.FireEvent(&Q3DStudio::IMemoryObjectListener::OnMemoryObjectUnRegistered,
+ m_MemoryObject);
+
+ Q3DStudio::IMemoryObject::TObjectList::iterator theIterator = m_ObjectList.begin();
+ for (; theIterator < m_ObjectList.end(); ++theIterator)
+ (*theIterator)->SetMemoryObjectParent(NULL);
+}
+
+/**
+ * This functor is called to determine the size details of an object.
+ *
+ * This allows any class the uses CMemoryObject to set a functor to an
+ * arbitrary function like this:
+ *
+ * <pre>
+ * SetSizeFunctor( new CFunctorObjectParam1<CClass,CMemoryObjectDetail&>( this,
+ *CClass::GetMemoryUsage ) );
+ * </pre>
+ */
+void CMemoryObject::SetSizeFunctor(TSizeFunctor *inFunctor)
+{
+ m_SizeFunctor = inFunctor;
+}
+
+/**
+ * Call the size functor if it has been set for the object
+ */
+long CMemoryObject::CallSizeFunctor() const
+{
+ m_ObjectDetails.Clear();
+
+ // TODO: Calculate internal memory tracking usage
+
+ if (m_SizeFunctor)
+ m_SizeFunctor->Execute(m_ObjectDetails);
+
+ return m_ObjectDetails.m_TotalSize;
+}
+
+/**
+ * This functor is called to determine the description details of an object.
+ *
+ * This allows any class the uses CMemoryObject to set a functor to an
+ * arbitrary function like this:
+ *
+ * <pre>
+ * SetDescFunctor( new CFunctorObjectParam1<CClass,Q3DStudio::CString&>( this,
+ *CClass::GetMemeoryDescription ) );
+ * </pre>
+ */
+void CMemoryObject::SetDescFunctor(TDescFunctor *inFunctor)
+{
+ m_DescFunctor = inFunctor;
+}
+
+/**
+ * Call the desc functor if it has been set for the object
+ */
+Q3DStudio::CString CMemoryObject::CallDescFunctor() const
+{
+ Q3DStudio::CString theDesc;
+
+ if (m_DescFunctor)
+ m_DescFunctor->Execute(theDesc);
+
+ return theDesc;
+}
+
+//==============================================================================
+// IMemoryObject
+//==============================================================================
+
+/**
+ * Return the name of the memory object
+ */
+const char *CMemoryObject::GetMemoryObjectName() const
+{
+ return m_Name;
+}
+
+/**
+ * Return a description of the memory object
+ */
+const char *CMemoryObject::GetMemoryObjectDescription() const
+{
+ m_Desc = CallDescFunctor();
+ return (const char *)m_Desc.GetCharStar();
+}
+
+/**
+ * Return a unique identifier for the memory object
+ */
+long CMemoryObject::GetMemoryObjectId() const
+{
+ return m_ID;
+}
+
+/**
+ * Locate the specified unique identifier in the IMemoryObject hierarchy.
+ */
+Q3DStudio::IMemoryObject *CMemoryObject::FindMemoryObjectId(long inId) const
+{
+ Q3DStudio::IMemoryObject *theMemoryObject = NULL;
+ Q3DStudio::IMemoryObject::TObjectList::const_iterator theIterator = m_ObjectList.begin();
+ for (; theIterator < m_ObjectList.end(); ++theIterator) {
+ if ((*theIterator)->GetMemoryObjectId() == inId)
+ return *theIterator;
+
+ theMemoryObject = (*theIterator)->FindMemoryObjectId(inId);
+ if (theMemoryObject)
+ return theMemoryObject;
+ }
+
+ return NULL;
+}
+
+/**
+ * Register a child memory object that is "owned" by this object.
+ */
+void CMemoryObject::RegisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker)
+{
+ m_ObjectList.push_back(inMemoryTracker);
+
+ inMemoryTracker->SetMemoryObjectParent(m_MemoryObject);
+
+ m_ChangeListener.FireEvent(&Q3DStudio::IMemoryObjectListener::OnMemoryObjectRegistered,
+ inMemoryTracker);
+}
+
+/**
+ * Unregister a child memory object that is "owned" by this object.
+ */
+void CMemoryObject::UnregisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker)
+{
+ m_ChangeListener.FireEvent(&Q3DStudio::IMemoryObjectListener::OnMemoryObjectUnRegistered,
+ inMemoryTracker);
+
+ inMemoryTracker->SetMemoryObjectParent(NULL);
+
+ Q3DStudio::IMemoryObject::TObjectList::iterator theIterator = m_ObjectList.begin();
+ for (; theIterator < m_ObjectList.end(); ++theIterator) {
+ if (inMemoryTracker == *theIterator) {
+ m_ObjectList.erase(theIterator);
+ return;
+ }
+ }
+}
+
+/**
+ * Register a memory object listener to listen for change events.
+ */
+void CMemoryObject::RegisterMemoryObjectListener(
+ Q3DStudio::IMemoryObjectListener *inMemoryObjectListener)
+{
+ m_ChangeListener.AddListener(inMemoryObjectListener);
+}
+
+/**
+ * Unregister a memory object listener to listen for change events.
+ */
+void CMemoryObject::UnregisterMemoryObjectListener(
+ Q3DStudio::IMemoryObjectListener *inMemoryObjectListener)
+{
+ m_ChangeListener.RemoveListener(inMemoryObjectListener);
+}
+
+/**
+ * Returns the size of the base object (sizeof)
+ */
+long CMemoryObject::GetMemoryObjectBase() const
+{
+ return m_StaticSize;
+}
+
+/**
+ * Returns the size of the base object (sizeof) and any dynamic memory
+ */
+long CMemoryObject::GetMemoryObjectUsage() const
+{
+ long theMemoryUsage = GetMemoryObjectBase();
+ theMemoryUsage += CallSizeFunctor();
+ return theMemoryUsage;
+}
+
+/**
+ * Returns the size of the base object (sizeof), any dynamic memory and the total size of any
+ *children
+ */
+long CMemoryObject::GetMemoryObjectTotal() const
+{
+ long theMemoryUsage = m_StaticSize;
+
+ theMemoryUsage += CallSizeFunctor();
+
+ Q3DStudio::IMemoryObject::TObjectListIt theIterator = m_ObjectList.begin();
+ for (; theIterator != m_ObjectList.end(); ++theIterator) {
+ Q3DStudio::IMemoryObject *theMemoryObject = *theIterator;
+ theMemoryUsage += theMemoryObject->GetMemoryObjectTotal();
+ }
+
+ return theMemoryUsage;
+}
+
+/**
+ * Iterate through child memory objects
+ */
+const Q3DStudio::IMemoryObject::TObjectListIt CMemoryObject::GetMemoryObjectBegin() const
+{
+ return m_ObjectList.begin();
+}
+
+/**
+ * Iterate through child memory objects
+ */
+const Q3DStudio::IMemoryObject::TObjectListIt CMemoryObject::GetMemoryObjectEnd() const
+{
+ return m_ObjectList.end();
+}
+
+/**
+ * Iterate through the details of the memory objects dynamic memory
+ */
+const Q3DStudio::IMemoryObject::TDetailListIt CMemoryObject::GetMemoryObjectDetailBegin() const
+{
+ return m_ObjectDetails.m_DetailList.begin();
+}
+
+/**
+ * Iterate through the details of the memory objects dynamic memory
+ */
+const Q3DStudio::IMemoryObject::TDetailListIt CMemoryObject::GetMemoryObjectDetailEnd() const
+{
+ return m_ObjectDetails.m_DetailList.end();
+}
+
+/**
+ * Store the parent of the object so that it can be notified when the object is destroyed
+ */
+void CMemoryObject::SetMemoryObjectParent(Q3DStudio::IMemoryObject *inMemoryObject)
+{
+ m_MemoryObjectParent = inMemoryObject;
+}
diff --git a/src/Authoring/Common/Code/Memory/MemoryObject.h b/src/Authoring/Common/Code/Memory/MemoryObject.h
new file mode 100644
index 00000000..4afb3c42
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/MemoryObject.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "IMemoryObject.h"
+#include "UICFunctor.h"
+#include "Multicaster.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Classes
+//==============================================================================
+
+//==============================================================================
+/**
+ * This is a helper class for tracking memory detail on an object.
+ */
+class CMemoryObjectDetail
+{
+ // Typedefs
+public:
+ Q3DStudio::IMemoryObject::TDetailList m_DetailList; ///< the list of object details
+
+ // Field Variables
+ long m_TotalSize;
+
+ // Constructor
+public:
+ CMemoryObjectDetail();
+
+ // Implementation
+public:
+ void Add(const char *inName, long inSize);
+ void Clear();
+};
+
+//==============================================================================
+/**
+ * This is a helper class for tracking memory usage on an object.
+ *
+ * This class is a little odd, but here are the reasons it was implemented the
+ * way it is.
+ *
+ * Initially, this was a template class that derived from IMemoryObject, but
+ * this caused a problem with CAsset type objects, since the CAsset needed to
+ * derive from IMemoryObject, but the implementation was on the instance level,
+ * such as CCamera. This could be addressed, but then there were issues with
+ * classes such as CPropertyContainer, both of which needed to be IMemoryObject
+ * derived classes, but CPropertyContainer needed to stand alone.
+ *
+ * After a number of implementations, it was determined that the simplest and
+ * most maintainable version involved the MemoryObjectMacros that create a
+ * m_MemoryObject field variable on each class and and pseudo-interface that
+ * redirects call to the m_MemoryObject handler.
+ */
+class CMemoryObject
+{
+ // typedef
+public:
+ typedef Q3DStudio::CFunctorObjectParam1Base<CMemoryObjectDetail &>
+ TSizeFunctor; ///< Memory object details
+ typedef Q3DStudio::CFunctorObjectParam1Base<Q3DStudio::CString &>
+ TDescFunctor; ///< Memory object description
+
+ // Field Variables
+protected:
+ long m_ID; ///< unique id for the object
+ long m_StaticSize; ///< the size of the object, not including dynamic memory allocations
+ ///(usually calculated by using sizeof)
+ const char *m_Name; ///< pointer to the name of the object (not an Q3DStudio::CString because it
+ ///has issues sharing memory across DLL boundaries and the gumshoe plugin is
+ ///a DLL)
+ mutable Q3DStudio::CString m_Desc; ///< to provide persistance for the description data
+ Q3DStudio::IMemoryObject::TObjectList m_ObjectList; ///< the list of child memory objects
+ CMulticaster<Q3DStudio::IMemoryObjectListener *> m_ChangeListener; ///< the list of memory
+ ///change listeners (just for
+ ///adding and removing memory
+ ///objects)
+ Q3DStudio::IMemoryObject *m_MemoryObject; ///< a pointer to "this" memory object (for
+ ///auto-unregistering the object on deletion)
+ Q3DStudio::IMemoryObject *m_MemoryObjectParent; ///< a pointer to "this" memory objects parent
+ ///(for auto-unregistering the object on
+ ///deletion)
+ Q3DStudio::CAutoMemPtr<TSizeFunctor>
+ m_SizeFunctor; ///< the functor to call when dynamic memory usage needs to be calculated
+ Q3DStudio::CAutoMemPtr<TDescFunctor>
+ m_DescFunctor; ///< the functor to call to grab description information
+ mutable CMemoryObjectDetail m_ObjectDetails; ///< the detailed information about the object
+
+ // Static Variables
+protected:
+ static long s_MemoryObjectID; ///< static variable used for generating unique id's
+
+ // Constructor
+public:
+ CMemoryObject(const char *inName, long inStaticSize, Q3DStudio::IMemoryObject *inMemoryObject);
+ CMemoryObject(const CMemoryObject &inSource, Q3DStudio::IMemoryObject *inMemoryObject);
+ ~CMemoryObject();
+
+ void SetSizeFunctor(TSizeFunctor *inFunctor);
+ long CallSizeFunctor() const;
+
+ void SetDescFunctor(TDescFunctor *inFunctor);
+ Q3DStudio::CString CallDescFunctor() const;
+
+ // Accessors
+public:
+ // IMemoryObject
+public:
+ const char *GetMemoryObjectName() const;
+ const char *GetMemoryObjectDescription() const;
+ long GetMemoryObjectId() const;
+ Q3DStudio::IMemoryObject *FindMemoryObjectId(long inId) const;
+ void RegisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker);
+ void UnregisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker);
+ void RegisterMemoryObjectListener(Q3DStudio::IMemoryObjectListener *inMemoryObjectListener);
+ void UnregisterMemoryObjectListener(Q3DStudio::IMemoryObjectListener *inMemoryObjectListener);
+ long GetMemoryObjectBase() const;
+ long GetMemoryObjectUsage() const;
+ long GetMemoryObjectTotal() const;
+ const Q3DStudio::IMemoryObject::TObjectListIt GetMemoryObjectBegin() const;
+ const Q3DStudio::IMemoryObject::TObjectListIt GetMemoryObjectEnd() const;
+ const Q3DStudio::IMemoryObject::TDetailListIt GetMemoryObjectDetailBegin() const;
+ const Q3DStudio::IMemoryObject::TDetailListIt GetMemoryObjectDetailEnd() const;
+ void SetMemoryObjectParent(Q3DStudio::IMemoryObject *inMemoryObject);
+
+ // Static Methods
+public:
+ // Internal Methods
+protected:
+ // Operators
+private:
+ CMemoryObject &operator=(const CMemoryObject &inSrc);
+};
diff --git a/src/Authoring/Common/Code/Memory/MemoryObjectMacros.h b/src/Authoring/Common/Code/Memory/MemoryObjectMacros.h
new file mode 100644
index 00000000..fa86a6c0
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/MemoryObjectMacros.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MemoryObject.h"
+
+//==============================================================================
+// Defines
+//==============================================================================
+
+#define DEFINE_MEMORY_OBJECT(class, name) \
+protected: \
+ CMemoryObject m_MemoryObject; \
+ \
+public: \
+ virtual const char *GetMemoryObjectName() const; \
+ virtual const char *GetMemoryObjectDescription() const; \
+ virtual long GetMemoryObjectId() const; \
+ virtual Q3DStudio::IMemoryObject *FindMemoryObjectId(long inId) const; \
+ virtual void RegisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker); \
+ virtual void UnregisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker); \
+ virtual void RegisterMemoryObjectListener( \
+ Q3DStudio::IMemoryObjectListener *inMemoryObjectListener); \
+ virtual void UnregisterMemoryObjectListener( \
+ Q3DStudio::IMemoryObjectListener *inMemoryObjectListener); \
+ virtual long GetMemoryObjectBase() const; \
+ virtual long GetMemoryObjectUsage() const; \
+ virtual long GetMemoryObjectTotal() const; \
+ virtual const Q3DStudio::IMemoryObject::TObjectListIt GetMemoryObjectBegin() const; \
+ virtual const Q3DStudio::IMemoryObject::TObjectListIt GetMemoryObjectEnd() const; \
+ virtual const Q3DStudio::IMemoryObject::TDetailListIt GetMemoryObjectDetailBegin() const; \
+ virtual const Q3DStudio::IMemoryObject::TDetailListIt GetMemoryObjectDetailEnd() const; \
+ virtual void SetMemoryObjectParent(Q3DStudio::IMemoryObject *inMemoryObject); \
+ void SetSizeFunctor(CMemoryObject::TSizeFunctor *inFunctor); \
+ void SetDescFunctor(CMemoryObject::TDescFunctor *inFunctor);
+
+#define IMPLEMENT_MEMORY_OBJECT(class, name) \
+ const char *class ::GetMemoryObjectName() const \
+ { \
+ return m_MemoryObject.GetMemoryObjectName(); \
+ } \
+ const char *class ::GetMemoryObjectDescription() const \
+ { \
+ return m_MemoryObject.GetMemoryObjectDescription(); \
+ } \
+ long class ::GetMemoryObjectId() const { return m_MemoryObject.GetMemoryObjectId(); } \
+ Q3DStudio::IMemoryObject *class ::FindMemoryObjectId(long inId) const \
+ { \
+ return m_MemoryObject.FindMemoryObjectId(inId); \
+ } \
+ void class ::RegisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker) \
+ { \
+ return m_MemoryObject.RegisterMemoryObject(inMemoryTracker); \
+ } \
+ void class ::UnregisterMemoryObject(Q3DStudio::IMemoryObject *inMemoryTracker) \
+ { \
+ return m_MemoryObject.UnregisterMemoryObject(inMemoryTracker); \
+ } \
+ void class ::RegisterMemoryObjectListener( \
+ Q3DStudio::IMemoryObjectListener *inMemoryObjectListener) \
+ { \
+ return m_MemoryObject.RegisterMemoryObjectListener(inMemoryObjectListener); \
+ } \
+ void class ::UnregisterMemoryObjectListener( \
+ Q3DStudio::IMemoryObjectListener *inMemoryObjectListener) \
+ { \
+ return m_MemoryObject.UnregisterMemoryObjectListener(inMemoryObjectListener); \
+ } \
+ long class ::GetMemoryObjectBase() const { return m_MemoryObject.GetMemoryObjectBase(); } \
+ long class ::GetMemoryObjectUsage() const { return m_MemoryObject.GetMemoryObjectUsage(); } \
+ long class ::GetMemoryObjectTotal() const { return m_MemoryObject.GetMemoryObjectTotal(); } \
+ const Q3DStudio::IMemoryObject::TObjectListIt class ::GetMemoryObjectBegin() const \
+ { \
+ return m_MemoryObject.GetMemoryObjectBegin(); \
+ } \
+ const Q3DStudio::IMemoryObject::TObjectListIt class ::GetMemoryObjectEnd() const \
+ { \
+ return m_MemoryObject.GetMemoryObjectEnd(); \
+ } \
+ const Q3DStudio::IMemoryObject::TDetailListIt class ::GetMemoryObjectDetailBegin() const \
+ { \
+ return m_MemoryObject.GetMemoryObjectDetailBegin(); \
+ } \
+ const Q3DStudio::IMemoryObject::TDetailListIt class ::GetMemoryObjectDetailEnd() const \
+ { \
+ return m_MemoryObject.GetMemoryObjectDetailEnd(); \
+ } \
+ void class ::SetMemoryObjectParent(Q3DStudio::IMemoryObject *inMemoryObject) \
+ { \
+ return m_MemoryObject.SetMemoryObjectParent(inMemoryObject); \
+ } \
+ void class ::SetSizeFunctor(CMemoryObject::TSizeFunctor *inFunctor) \
+ { \
+ return m_MemoryObject.SetSizeFunctor(inFunctor); \
+ } \
+ void class ::SetDescFunctor(CMemoryObject::TDescFunctor *inFunctor) \
+ { \
+ return m_MemoryObject.SetDescFunctor(inFunctor); \
+ }
+
+#define CONSTRUCT_MEMORY_OBJECT(class, name) m_MemoryObject(#name, sizeof(class), this)
diff --git a/src/Authoring/Common/Code/Memory/MemoryObjectSize.h b/src/Authoring/Common/Code/Memory/MemoryObjectSize.h
new file mode 100644
index 00000000..70a95c40
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/MemoryObjectSize.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <map>
+#include <set>
+#include <list>
+#include <vector>
+
+/**
+ * Helper class to assist in calculating the sizes of well known objects.
+ */
+template <typename T1 = long, typename T2 = long, typename T3 = T1>
+class CMemoryObjectSize
+{
+public:
+ static long GetSize(std::vector<T1> &inValue) { return inValue.size() * sizeof(T3); }
+
+ static long GetSize(std::list<T1> &inValue) { return inValue.size() * sizeof(T3); }
+
+ static long GetSizeForEach(std::vector<T1> &inValue)
+ {
+ long theSize = 0;
+
+ // Calculate the size of each vector in the map
+ FOR_EACH(T1 & theItem, inValue) { theSize += sizeof(T1) + theItem.GetMemoryUsage(); }
+
+ return theSize;
+ }
+
+ static long GetSizeForEach(std::list<T1> &inValue)
+ {
+ long theSize = 0;
+
+ // Calculate the size of each vector in the map
+ FOR_EACH(T1 & theItem, inValue) { theSize += sizeof(T1) + theItem.GetMemoryUsage(); }
+
+ return theSize;
+ }
+
+ static long GetSizeForEach(std::map<T1, T2> &inValue)
+ {
+ long theSize = 0;
+
+ // Calculate the size of each vector in the map
+ typedef std::map<T1, T2> TRef;
+ FOR_EACH(TRef::const_reference thePair, inValue)
+ {
+ theSize += sizeof(T1) + sizeof(T2) + thePair.second->GetMemoryUsage();
+ }
+
+ return theSize;
+ }
+
+ static long GetSize(std::map<T1, std::vector<T2>> &inValue)
+ {
+ // Calculate the size of the map
+ long theSize = inValue.size() * (sizeof(T1) + sizeof(T2));
+
+ // Calculate the size of each vector in the map
+ typedef std::map<T1, std::vector<T2>> TRef;
+ FOR_EACH(TRef::const_reference thePair, inValue)
+ {
+ theSize += thePair.second.size() * sizeof(T2);
+ }
+
+ return theSize;
+ }
+
+ static long GetSize(std::map<T1, T2> &inValue)
+ {
+ return inValue.size() * (sizeof(T1) + sizeof(T3));
+ }
+
+ static long GetSize(std::multiset<T1, T2> &inValue)
+ {
+ return inValue.size() * (sizeof(T1) + sizeof(T2));
+ }
+
+ static long GetSize(Q3DStudio::CString &inValue)
+ {
+ long theLength = inValue.Length();
+ return (theLength * sizeof(wchar_t)) + // m_WideData
+ (theLength * sizeof(char)) + // m_CharData
+ (theLength * sizeof(char)) // m_MultiData
+ ;
+ }
+};
diff --git a/src/Authoring/Common/Code/Memory/UICMemoryLeak.cpp b/src/Authoring/Common/Code/Memory/UICMemoryLeak.cpp
new file mode 100644
index 00000000..82331bf4
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/UICMemoryLeak.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryLeak.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+using namespace Q3DStudio;
+
+//==============================================================================
+// From C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\crt\src\dbgint.h
+//==============================================================================
+
+#define nNoMansLandSize 4
+typedef struct _CrtMemBlockHeader
+{
+ struct _CrtMemBlockHeader *pBlockHeaderNext;
+ struct _CrtMemBlockHeader *pBlockHeaderPrev;
+ char *szFileName;
+ int nLine;
+#ifdef _WIN64
+ /* These items are reversed on Win64 to eliminate gaps in the struct
+ * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is
+ * maintained in the debug heap.
+ */
+ int nBlockUse;
+ size_t nDataSize;
+#else /* _WIN64 */
+ size_t nDataSize;
+ int nBlockUse;
+#endif /* _WIN64 */
+ long lRequest;
+ unsigned char gap[nNoMansLandSize];
+ /* followed by:
+ * unsigned char data[nDataSize];
+ * unsigned char anotherGap[nNoMansLandSize];
+ */
+} _CrtMemBlockHeader;
+
+#define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1))
+
+//==============================================================================
+// Global Variables
+//==============================================================================
+
+bool CMemoryLeak::s_ShowDialogOnExit = false;
+bool CMemoryLeak::s_DumpXMLOnExit = false;
+char CMemoryLeak::s_XMLFileName[_MAX_PATH] = "UICMemoryLeaks.xml";
+size_t CMemoryLeak::s_MaxDumpSize = 20;
+
+// The one and only object instance. This is placed in the "compiler"
+// initialization area, so that it gets constructed during C runtime
+// initialization and before any user global objects are constructed.
+// Also, disable the warning about us using the "compiler"
+// initialization area. Otherwise, this object doesn't get constructed
+// early enough to get a good spot in the "onexit" list and doesn't
+// accurately dump memeory leaks.
+#ifdef _DEBUG
+#ifdef WIN32
+#pragma warning(disable : 4074) // initializers put in compiler reserved initialization area
+#pragma init_seg(compiler)
+#endif
+static CMemoryLeak g_MemoryLeakGlobalVar;
+#endif
+
+//==============================================================================
+// Static Methods
+//==============================================================================
+
+/**
+ * Called on exit.
+ *
+ * NOTE: Be very careful with what you add to this method, it may be called
+ * AFTER facilities in the C runtime have been destroyed. This is close to the
+ * metal, be careful you don't get shocked!
+ */
+int CMemoryLeak::MemoryDumpCallback()
+{
+#ifdef _DEBUG
+
+ // Only dump memory leaks if there are in fact leaks
+#ifdef KDAB_TEMPORARILY_REMOVED
+ _CrtMemState msNow;
+ _CrtMemCheckpoint(&msNow);
+
+ // This is the only way I could figure out how to get hold of
+ // _pFirstBlock. This could change with other implementations
+ // of the C Runtime.
+ _CrtMemBlockHeader *_pFirstBlock = msNow.pBlockHeader;
+
+ size_t theMemoryLeakTotal = 0;
+ size_t theMemoryBytesTotal = 0;
+
+ // We're only interested in NORMAL blocks
+ if (msNow.lCounts[_NORMAL_BLOCK] != 0) {
+ FILE *theFilePtr(NULL);
+ XMLDumpInitialize(theFilePtr);
+
+ // Loop through all the blocks
+ for (_CrtMemBlockHeader *pHead = _pFirstBlock; pHead != NULL;
+ pHead = pHead->pBlockHeaderNext) {
+ if (pHead->nBlockUse == _NORMAL_BLOCK) {
+ ++theMemoryLeakTotal;
+ theMemoryBytesTotal += pHead->nDataSize;
+
+ XMLDumpLeak(theFilePtr, pHead);
+ }
+ }
+
+ XMLDumpClose(theFilePtr, theMemoryLeakTotal, theMemoryBytesTotal);
+
+ // Format the string
+ char theFormatString[_MAX_PATH];
+ _snprintf(theFormatString, sizeof(theFormatString),
+ "Detected %ld memory leak(s) for a total of %ld bytes leaked.\n",
+ theMemoryLeakTotal, theMemoryBytesTotal);
+
+ // Output to debugger
+ ::OutputDebugStringA("*** ");
+ ::OutputDebugStringA(theFormatString);
+
+ // Display dialog
+ if (s_ShowDialogOnExit)
+ ::MessageBoxA(NULL, theFormatString, "Memory Leak Warning", MB_OK);
+ }
+#endif
+
+#endif
+
+ return 0;
+}
+
+/**
+ * Set the flag that controls whether or not we display a dialog box
+ * when exiting the application with memory leaks.
+ */
+void CMemoryLeak::SetShowDialogOnExit(bool inValue)
+{
+ s_ShowDialogOnExit = inValue;
+}
+
+/**
+ * Set the flag that controls whether or not we dump an XML file
+ * when exiting the application with memory leaks.
+ */
+void CMemoryLeak::SetDumpXMLOnExit(bool inValue)
+{
+ s_DumpXMLOnExit = inValue;
+}
+
+/**
+ * Set the flag that controls whether or not we dump an XML file
+ * when exiting the application with memory leaks.
+ */
+void CMemoryLeak::SetXMLFileName(const char *inValue)
+{
+ strncpy(s_XMLFileName, inValue, sizeof(s_XMLFileName));
+ s_XMLFileName[sizeof(s_XMLFileName) - 1] = 0;
+}
+
+//==============================================================================
+// Internal Methods
+//==============================================================================
+
+/**
+ * Constructor
+ */
+CMemoryLeak::CMemoryLeak()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ ::_onexit(CMemoryLeak::MemoryDumpCallback);
+#endif
+}
+
+/**
+ * Opens and sets up the file ptr.
+ * Write some tags.
+ */
+void CMemoryLeak::XMLDumpInitialize(FILE *&outFilePtr)
+{
+ if (s_DumpXMLOnExit) {
+ outFilePtr = ::fopen(s_XMLFileName, "w");
+
+ if (outFilePtr) {
+ ::fprintf(outFilePtr, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
+ ::fprintf(outFilePtr, "<MemoryLeaks>\n");
+ ::fprintf(outFilePtr, "\t<Leaks>\n");
+ }
+ }
+}
+
+/**
+ * Dumps out first X bytes of the leak as a CDATA tag.
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+void CMemoryLeak::XMLDumpLeak(FILE *inFilePtr, _CrtMemBlockHeader *inBlockHdr)
+{
+ if (s_DumpXMLOnExit && inFilePtr) {
+ size_t theDumpSize(::MIN(s_MaxDumpSize, inBlockHdr->nDataSize));
+
+ ::fprintf(inFilePtr, "\t\t<Leak LeakSize = \"%d\" DumpSize = \"%d\">\n\t\t\t<![CDATA[",
+ inBlockHdr->nDataSize, theDumpSize);
+
+ ::fwrite(pbData(inBlockHdr), 1, theDumpSize, inFilePtr);
+
+ ::fprintf(inFilePtr, "]]>\n\t\t</Leak>\n");
+ }
+}
+#endif
+
+/**
+ * Write some tags. Flushes and closes the file.
+ */
+void CMemoryLeak::XMLDumpClose(FILE *inFilePtr, size_t inMemoryLeakTotal, size_t inMemoryBytesTotal)
+{
+ if (s_DumpXMLOnExit && inFilePtr) {
+ ::fprintf(inFilePtr, "\t</Leaks>\n\t<Summary\n ");
+ ::fprintf(inFilePtr, "\t\tTotalNumberOfLeaks = \"%lu\"\n", inMemoryLeakTotal);
+ ::fprintf(inFilePtr, "\t\tTotalBytesLeaked = \"%lu\"\n", inMemoryBytesTotal);
+ ::fprintf(inFilePtr, "\t/>\n</MemoryLeaks>");
+
+ ::fflush(inFilePtr);
+ ::fclose(inFilePtr);
+ }
+}
diff --git a/src/Authoring/Common/Code/Memory/UICMemoryLeak.h b/src/Authoring/Common/Code/Memory/UICMemoryLeak.h
new file mode 100644
index 00000000..ed6d691e
--- /dev/null
+++ b/src/Authoring/Common/Code/Memory/UICMemoryLeak.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Namespace
+//==============================================================================
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * \class CMemoryLeak
+ * \brief
+ */
+class CMemoryLeak
+{
+ // Static Field Variables
+protected:
+ static bool s_ShowDialogOnExit; ///<
+ static bool s_DumpXMLOnExit; ///<
+ static char s_XMLFileName[_MAX_PATH]; ///<
+ static size_t s_MaxDumpSize; ///< Maximium number of bytes to dump from a leak
+
+ // Constructor
+public:
+ CMemoryLeak();
+
+ // Static Methods
+public:
+ static void SetShowDialogOnExit(bool inValue);
+ static void SetDumpXMLOnExit(bool inValue);
+ static void SetXMLFileName(const char *inValue);
+ static int MemoryDumpCallback();
+
+ // XML file dumping
+protected:
+ static void XMLDumpInitialize(FILE *&outFilePtr);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ static void XMLDumpLeak(FILE *inFilePtr, _CrtMemBlockHeader *inBlockHdr);
+#endif
+ static void XMLDumpClose(FILE *inFilePtr, size_t inMemoryLeakTotal, size_t inMemoryBytesTotal);
+
+ // Operators
+private:
+ CMemoryLeak &operator=(const CMemoryLeak &inSrc);
+};
+
+}
diff --git a/src/Authoring/Common/Code/MethProf.cpp b/src/Authoring/Common/Code/MethProf.cpp
new file mode 100644
index 00000000..7df8763f
--- /dev/null
+++ b/src/Authoring/Common/Code/MethProf.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+#ifdef PERFORM_PROFILE
+
+#include "MethProf.h"
+#include "MasterP.h"
+#include "UICString.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+ * Create a profiler with inName as the identifying name.
+ * This will auto register itself on CMasterProf.
+ */
+CMethProf::CMethProf(const Q3DStudio::CString &inName)
+{
+ m_Name = inName;
+
+ this->Clear();
+
+ CMasterProf::GetInstance()->AddMethProf(this);
+}
+
+CMethProf::~CMethProf()
+{
+}
+
+//==============================================================================
+/**
+ * Clear the statistics for this profiler.
+ * This will cause all the timings to be reset.
+ */
+void CMethProf::Clear()
+{
+ m_TotalTime = 0;
+ m_MaxTime = 0;
+
+ m_CallCount = 0;
+ m_StackCount = 0;
+}
+
+//==============================================================================
+/**
+ * Start the profiler running.
+ * This will increment the call count and start the timer running.
+ */
+void CMethProf::Start()
+{
+ if (m_StackCount == 0) {
+ m_Timer.Start();
+ }
+ ++m_StackCount;
+}
+
+//==============================================================================
+/**
+ * Stop the profiler from running.
+ * This will log the amount of time taken from when Start was first called.
+ */
+void CMethProf::Stop()
+{
+ --m_StackCount;
+ ++m_CallCount;
+
+ if (m_StackCount == 0) {
+ m_Timer.Stop();
+ TLarge theElapsed = m_Timer.ElapsedMicroSecs();
+
+ if (theElapsed > m_MaxTime)
+ m_MaxTime = theElapsed;
+
+ m_TotalTime += theElapsed;
+ }
+}
+
+//==============================================================================
+/**
+ * Get the number of times that this profiler was started.
+ */
+unsigned long CMethProf::GetCount()
+{
+ return m_CallCount;
+}
+
+//==============================================================================
+/**
+ * Get the total amount of time in milliseconds that this profiler was running.
+ */
+unsigned long CMethProf::GetTotalMillis()
+{
+ return (unsigned long)(m_TotalTime / 1000);
+}
+
+//==============================================================================
+/**
+ * Get the average time in milliseconds that this profiler was running.
+ */
+float CMethProf::GetAverageMillis()
+{
+ if (m_CallCount > 0) {
+ float theTotal = (float)GetTotalMillis();
+ return theTotal / m_CallCount;
+ }
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Get the maximum time in milliseconds that this profiler was running.
+ */
+float CMethProf::GetMaxMillis()
+{
+ return ((float)m_MaxTime) / 1000.0f;
+}
+
+//==============================================================================
+/**
+ * Get a formatted string description of this profiler.
+ */
+Q3DStudio::CString CMethProf::GetDescription()
+{
+ Q3DStudio::CString theString;
+ theString.Format(_UIC("%ls cc: %d tt: %d mt: %8.2f at: %8.2f"),
+ (const wchar_t *)m_Name, m_CallCount, GetTotalMillis(), GetMaxMillis(),
+ GetAverageMillis());
+ return theString;
+}
+
+//==============================================================================
+/**
+ * Get the name of this profiler.
+ */
+Q3DStudio::CString CMethProf::GetName()
+{
+ return m_Name;
+}
+
+#endif // #ifdef PERFORM_PROFILE
diff --git a/src/Authoring/Common/Code/MethProf.h b/src/Authoring/Common/Code/MethProf.h
new file mode 100644
index 00000000..da0e7728
--- /dev/null
+++ b/src/Authoring/Common/Code/MethProf.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_METH_PROF_H
+#define INCLUDED_METH_PROF_H 1
+
+#pragma once
+
+#ifdef PERFORM_PROFILE
+
+#include "HiResTimer.h"
+#include "UICString.h"
+#include <vector>
+
+class CMethProf
+{
+public:
+ CMethProf(const Q3DStudio::CString &inName = "");
+ virtual ~CMethProf();
+
+ void Clear();
+
+ void Start();
+ void Stop();
+
+ unsigned long GetCount();
+ unsigned long GetTotalMillis();
+ float GetAverageMillis();
+ float GetMaxMillis();
+ Q3DStudio::CString GetDescription();
+ Q3DStudio::CString GetName();
+
+protected:
+ TLarge m_TotalTime;
+ TLarge m_MaxTime;
+ CHiResTimer m_Timer;
+
+ unsigned long m_CallCount;
+ long m_StackCount;
+
+ Q3DStudio::CString m_Name;
+};
+
+#endif // #ifdef PERFORM_PROFILE
+
+#endif // INCLUDED_METH_PROF_H
diff --git a/src/Authoring/Common/Code/Multicaster.h b/src/Authoring/Common/Code/Multicaster.h
new file mode 100644
index 00000000..0601e0e2
--- /dev/null
+++ b/src/Authoring/Common/Code/Multicaster.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDE_MULTICASTER_H
+#define INCLUDE_MULTICASTER_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "SafeArray.h"
+
+//==============================================================================
+/**
+ * Template class for maintaining a list of listeners and fire events off to them.
+ */
+template <class TObject>
+class CMulticaster
+{
+ typedef CSafeArray<TObject> TList;
+
+public:
+ CMulticaster() {}
+ virtual ~CMulticaster() {}
+
+ //==============================================================================
+ /**
+ * Adds a listener to the internally maintained list. First removes any
+ * previous instances of the listener before adding a new one.
+ *
+ * @param inListener The listener to be registered.
+ */
+ void AddListener(TObject inListener)
+ {
+ this->RemoveListener(inListener);
+ m_List.Add(inListener);
+ }
+
+ //==============================================================================
+ /**
+ * Removes all instances of the specified listener from the registration list.
+ *
+ * @param inListener The listener to be unregistered
+ */
+ void RemoveListener(TObject inListener)
+ {
+ typename TList::CIterator thePos = m_List.Begin();
+
+ for (; thePos.HasNext(); ++thePos) {
+ if (inListener == (*thePos)) {
+ m_List.Remove(thePos);
+ break;
+ }
+ }
+ }
+
+ //==============================================================================
+ /**
+ * Template methods for firing events with arbitrary numbers of params to
+ * listeners. If a source is specfied, then the source will not receive
+ * notifications that it kicked off itself.
+ */
+ template <typename TMethodType>
+ void FireEvent(TMethodType inMethod)
+ {
+ this->FireEventSource(inMethod, NULL);
+ }
+
+ template <typename TMethodType>
+ void FireEventSource(TMethodType inMethod, void *inSource)
+ {
+ typename TList::CIterator thePos = m_List.Begin();
+
+ for (; thePos.HasNext(); ++thePos) {
+ if (*thePos != inSource) {
+ ((*thePos)->*inMethod)();
+ }
+ }
+ }
+
+ template <typename TMethodType, typename TFirstArg>
+ void FireEvent(TMethodType inMethod, TFirstArg inFirstArg)
+ {
+ this->FireEventSource(inMethod, inFirstArg, NULL);
+ }
+
+ template <typename TMethodType, typename TFirstArg>
+ void FireEventSource(TMethodType inMethod, TFirstArg inFirstArg, void *inSource)
+ {
+ typename TList::CIterator thePos = m_List.Begin();
+
+ for (; thePos.HasNext(); ++thePos) {
+ if (*thePos != inSource) {
+ ((*thePos)->*inMethod)(inFirstArg);
+ }
+ }
+ }
+
+ template <typename TMethodType, typename TFirstArg, typename TSecondArg>
+ void FireEvent(TMethodType inMethod, TFirstArg inFirstArg, TSecondArg inSecondArg)
+ {
+ this->FireEventSource(inMethod, inFirstArg, inSecondArg, NULL);
+ }
+
+ template <typename TMethodType, typename TFirstArg, typename TSecondArg>
+ void FireEventSource(TMethodType inMethod, TFirstArg inFirstArg, TSecondArg inSecondArg,
+ void *inSource)
+ {
+ typename TList::CIterator thePos = m_List.Begin();
+
+ for (; thePos.HasNext(); ++thePos) {
+ if (*thePos != inSource) {
+ ((*thePos)->*inMethod)(inFirstArg, inSecondArg);
+ }
+ }
+ }
+
+ template <typename TMethodType, typename TFirstArg, typename TSecondArg, typename TThirdArg>
+ void FireEvent(TMethodType inMethod, TFirstArg inFirstArg, TSecondArg inSecondArg,
+ TThirdArg inThirdArg)
+ {
+ this->FireEventSource(inMethod, inFirstArg, inSecondArg, inThirdArg, NULL);
+ }
+
+ template <typename TMethodType, typename TFirstArg, typename TSecondArg, typename TThirdArg>
+ void FireEventSource(TMethodType inMethod, TFirstArg inFirstArg, TSecondArg inSecondArg,
+ TThirdArg inThirdArg, void *inSource)
+ {
+ typename TList::CIterator thePos = m_List.Begin();
+
+ for (; thePos.HasNext(); ++thePos) {
+ if (*thePos != inSource) {
+ ((*thePos)->*inMethod)(inFirstArg, inSecondArg, inThirdArg);
+ }
+ }
+ }
+
+ template <typename TMethodType, typename TFirstArg, typename TSecondArg, typename TThirdArg,
+ typename TFourthArg>
+ void FireEvent(TMethodType inMethod, TFirstArg inFirstArg, TSecondArg inSecondArg,
+ TThirdArg inThirdArg, TFourthArg inFourthArg)
+ {
+ this->FireEventSource(inMethod, inFirstArg, inSecondArg, inThirdArg, inFourthArg, NULL);
+ }
+
+ template <typename TMethodType, typename TFirstArg, typename TSecondArg, typename TThirdArg,
+ typename TFourthArg>
+ void FireEventSource(TMethodType inMethod, TFirstArg inFirstArg, TSecondArg inSecondArg,
+ TThirdArg inThirdArg, TFourthArg inFourthArg, void *inSource)
+ {
+ typename TList::CIterator thePos = m_List.Begin();
+
+ for (; thePos.HasNext(); ++thePos) {
+ if (*thePos != inSource) {
+ ((*thePos)->*inMethod)(inFirstArg, inSecondArg, inThirdArg, inFourthArg);
+ }
+ }
+ }
+
+ //=========================================================================
+ /**
+ * Get the number of listeners in this multicaster.
+ * @return the number of listeners in this multicaster.
+ */
+ long GetCount() { return m_List.GetCount(); }
+
+protected:
+ TList m_List; ///< List of objects to fire events to
+};
+
+#endif // INCLUDE_MULTICASTER_H
diff --git a/src/Authoring/Common/Code/Preferences.h b/src/Authoring/Common/Code/Preferences.h
new file mode 100644
index 00000000..cbbe118b
--- /dev/null
+++ b/src/Authoring/Common/Code/Preferences.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PREFERENCES_H
+#define INCLUDED_PREFERENCES_H 1
+
+#pragma once
+
+#include "CColor.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CPreferencesSerializer;
+
+class CPreferences
+{
+public:
+ CPreferences(const Q3DStudio::CString &inTagPath)
+ : m_TagPath(inTagPath)
+ {
+ }
+ virtual ~CPreferences();
+
+ CPreferences(const CPreferences &inPreferences);
+ CPreferences &operator=(const CPreferences &inRightHandSide);
+
+ static CPreferences GetUserPreferences();
+ static CPreferences GetUserPreferences(const Q3DStudio::CString &inSubKeyPath);
+
+ CPreferences GetPreferences(const Q3DStudio::CString &inPreferencesKey);
+
+ void SetStringValue(const Q3DStudio::CString &inKey, const Q3DStudio::CString &inValue);
+ Q3DStudio::CString GetStringValue(const Q3DStudio::CString &inKey,
+ const Q3DStudio::CString &inDefaultValue);
+
+ void SetLongValue(const Q3DStudio::CString &inKey, long inValue);
+ long GetLongValue(const Q3DStudio::CString &inKey, long inDefaultValue);
+
+ void SetValue(const Q3DStudio::CString &inKey, bool inValue);
+ bool GetValue(const Q3DStudio::CString &inKey, bool inDefaultValue);
+
+ void SetValue(const Q3DStudio::CString &inKey, double inValue);
+ double GetValue(const Q3DStudio::CString &inKey, double inDefaultValue);
+
+ void SetColorValue(const Q3DStudio::CString &inKey, ::CColor inValue);
+ ::CColor GetColorValue(const Q3DStudio::CString &inKey, ::CColor inDefaultValue);
+
+ void SetBinaryValue(const Q3DStudio::CString &inKey, const void *inData, long inLength);
+ bool GetBinaryValue(const Q3DStudio::CString &inKey, void *outData, long inLength);
+
+ void Clear();
+
+ long GetItemCount();
+
+ void Commit();
+
+ void RemoveKey(const Q3DStudio::CString &inKeyName);
+
+ bool Exists(const Q3DStudio::CString &inKeyName);
+
+ static void SetPreferencesFile(const Q3DStudio::CString &inFileName);
+
+private:
+ Q3DStudio::CString m_TagPath;
+ static CPreferencesSerializer s_PreferencesSerializer;
+};
+#endif // INCLUDED_PREFERENCES_H
diff --git a/src/Authoring/Common/Code/Pt.cpp b/src/Authoring/Common/Code/Pt.cpp
new file mode 100644
index 00000000..4baa85ba
--- /dev/null
+++ b/src/Authoring/Common/Code/Pt.cpp
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "Pt.h"
+
+// Code moved to header.
+CPt::CPt(const QPoint &qpoint)
+ : x(qpoint.x())
+ , y(qpoint.y())
+
+{
+}
diff --git a/src/Authoring/Common/Code/Pt.h b/src/Authoring/Common/Code/Pt.h
new file mode 100644
index 00000000..178210f9
--- /dev/null
+++ b/src/Authoring/Common/Code/Pt.h
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PT_H
+#define INCLUDED_PT_H 1
+
+#pragma once
+
+#include <QPoint>
+
+class CPt
+{
+public:
+ CPt();
+ CPt(long inX, long inY);
+ CPt(const CPt *inPt);
+ // CPt( const CPoint& inPt );
+
+ CPt(const QPoint& qpoint);
+
+ void Offset(const CPt inPt);
+ void operator+=(const CPt inPt);
+ void operator-=(const CPt inPt);
+ CPt operator+(const CPt inPt) const;
+ CPt operator-(const CPt inPt) const;
+ CPt operator-() const;
+
+ bool operator<(const CPt &inPt) const;
+ bool operator>(const CPt &inPt) const;
+ bool operator<=(const CPt &inPt) const;
+ bool operator>=(const CPt &inPt) const;
+ bool operator==(const CPt &inPt) const;
+ bool operator!=(const CPt &inPt) const;
+ operator QPoint() const;
+ // POINT operator POINT( ) const;
+
+ // sweetness- allows one variable to have 2 names, in here because of the integration of CPoint
+ // and CSize, plus it's slick and really annoys edwards.
+ // union
+ // {
+ long x;
+ // long cx;
+ // };
+
+ // union
+ // {
+ long y;
+ // long cy;
+ // };
+};
+
+//=============================================================================
+/**
+ * Constructor, initializes to 0, 0.
+ */
+inline CPt::CPt()
+ : x(0)
+ , y(0)
+{
+}
+
+//=============================================================================
+/**
+ * Constructor.
+ * @param inX the x value.
+ * @param inY the y value.
+ */
+inline CPt::CPt(long inX, long inY)
+ : x(inX)
+ , y(inY)
+{
+}
+
+//=============================================================================
+/**
+ * Constructor from another point object.
+ * Meant mainly to speed up the + and - operators.
+ * @param inPt the point to copy to this.
+ */
+inline CPt::CPt(const CPt *inPt)
+ : x(inPt->x)
+ , y(inPt->y)
+{
+}
+
+/*
+inline CPt::CPt( const CPoint& inPoint ): x( inPoint.x ), y( inPoint.y )
+{
+}
+*/
+
+//=============================================================================
+/**
+ * Offset this point by inPt.
+ * This just adds the x and y components of inPt to this.
+ * @param inPt the amount to offset this by.
+ */
+inline void CPt::Offset(const CPt inPt)
+{
+ x += inPt.x;
+ y += inPt.y;
+}
+
+//=============================================================================
+/**
+ * Add the values of inPt to this.
+ * This adds the x and y components of inPt to the x and y components of this.
+ * @param inPt the values to add to this.
+ */
+inline void CPt::operator+=(const CPt inPt)
+{
+ x += inPt.x;
+ y += inPt.y;
+}
+
+//=============================================================================
+/**
+ * Subtracts the values of inPt from this.
+ * This subtracts the x and y components of inPt from the x and y components of
+ * this.
+ * @param inPt the values to subtract from this.
+ */
+inline void CPt::operator-=(const CPt inPt)
+{
+ x -= inPt.x;
+ y -= inPt.y;
+}
+
+//=============================================================================
+/**
+ * Add this and the values of inPt together.
+ * This adds the x and y components of this and inPt together and returns the
+ * result.
+ * @param inPt the value to add to this.
+ * @return the result.
+ */
+inline CPt CPt::operator+(const CPt inPt) const
+{
+ CPt theRetVal(this);
+ theRetVal += inPt;
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Subtract the values of inPt from these values and return the result.
+ * This subtracts the x and y components of inPt from these values and returns
+ * the result.
+ * @param inPt the value to subtract from this.
+ * @return the result.
+ */
+inline CPt CPt::operator-(const CPt inPt) const
+{
+ CPt theRetVal(this);
+ theRetVal -= inPt;
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Comparator to see if one point is less than another.
+ * A point is considered to be smaller only if both it's x and y values are less
+ * than the others.
+ * @param inPt the point to compare this to.
+ * @return true if this is less than inPt.
+ */
+inline bool CPt::operator<(const CPt &inPt) const
+{
+ return (x < inPt.x && y < inPt.y);
+}
+
+//=============================================================================
+/**
+ * Comparator to see if one point is greater than another.
+ * A point is considered to be larger only if both it's x and y values are
+ * greater than the others.
+ * @param inPt the point to compare this to.
+ * @return true if this is less than inPt.
+ */
+inline bool CPt::operator>(const CPt &inPt) const
+{
+ return (x > inPt.x && y > inPt.y);
+}
+
+//=============================================================================
+/**
+ * Comparator to see if one point is less than or equal to another.
+ * @see operator <.
+ */
+inline bool CPt::operator<=(const CPt &inPt) const
+{
+ return (*this < inPt || (inPt.x == x && inPt.y == y));
+}
+
+//=============================================================================
+/**
+ * Comparator to see if one point is greater than or equal to another.
+ * @see operator >.
+ */
+inline bool CPt::operator>=(const CPt &inPt) const
+{
+ return (*this > inPt || (inPt.x == x && inPt.y == y));
+}
+
+//=============================================================================
+/**
+ * Comparator to see if two points are equal to each other.
+ */
+inline bool CPt::operator==(const CPt &inPt) const
+{
+ return (x == inPt.x && y == inPt.y);
+}
+
+//=============================================================================
+/**
+ * Comparator to see if two points are not equal to each other.
+ */
+inline bool CPt::operator!=(const CPt &inPt) const
+{
+ return (x != inPt.x || y != inPt.y);
+}
+
+inline CPt CPt::operator-() const
+{
+ return CPt(-x, -y);
+}
+
+inline CPt::operator QPoint() const
+{
+ return QPoint(x, y);
+}
+#endif // INCLUDED_PT_H
diff --git a/src/Authoring/Common/Code/PtrVector.h b/src/Authoring/Common/Code/PtrVector.h
new file mode 100644
index 00000000..646588b1
--- /dev/null
+++ b/src/Authoring/Common/Code/PtrVector.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef __PTRVECTOR_H__
+#define __PTRVECTOR_H__
+
+namespace Q3DStudio {
+
+/**
+ * @class CPtrVector: This is wrapper class for an std::vector of pointers.
+ * The reason for it's existance is because it will provide proper cleanup of
+ * stored pointers that an std::vector<CAutoMemPtrs> sometimes do not do properly.
+ */
+template <typename TPtr>
+class CPtrVector
+{
+public:
+ typedef std::vector<TPtr *> TPtrVector;
+ typedef typename TPtrVector::const_iterator
+ iterator; // protection against accidentally using non-const iterators
+ typedef typename TPtrVector::const_iterator const_iterator;
+ typedef typename TPtrVector::iterator TNonConstIterator;
+
+protected:
+ TPtrVector m_PtrVector;
+
+public:
+ CPtrVector(){}
+
+ ~CPtrVector() { clear(); }
+ long size() const { return static_cast<long>(m_PtrVector.size()); }
+
+ TPtr *at(long inIndex) const { return m_PtrVector.at(inIndex); }
+
+ TPtr *operator[](long inIndex) { return m_PtrVector.at(inIndex); }
+
+ void ReplaceAtIndex(long inIndex, TPtr *theNewPtr)
+ {
+ TPtr *theOldPtr = m_PtrVector.at(inIndex);
+ delete theOldPtr;
+ m_PtrVector.at(inIndex) = theNewPtr;
+ }
+
+ void DeleteAtIndex(long inIndex)
+ {
+ std::vector<TPtr *>::iterator theItr = m_PtrVector.begin() + inIndex;
+ TPtr *thePtr = theItr;
+ m_PtrVector.erase(theItr);
+ delete thePtr;
+ }
+
+ void pop_back()
+ {
+ delete m_PtrVector.back();
+ m_PtrVector.pop_back();
+ }
+
+ void push_back(TPtr *inNewPtr) { m_PtrVector.push_back(inNewPtr); }
+
+ void insert(TNonConstIterator inItr, TPtr *inNewPtr) { m_PtrVector.insert(inItr, inNewPtr); }
+
+ iterator begin() const { return m_PtrVector.begin(); }
+
+ TNonConstIterator NonConstBegin() { return m_PtrVector.begin(); }
+
+ iterator end() const { return m_PtrVector.end(); }
+
+ void erase(TNonConstIterator inItr, bool inDoDelete = true)
+ {
+ TPtr *thePtr = (*inItr);
+ m_PtrVector.erase(inItr);
+ if (inDoDelete)
+ delete thePtr;
+ }
+
+ void clear()
+ {
+ CPtrVector::iterator theItr = begin();
+ CPtrVector::iterator theEnd = end();
+
+ TPtr *thePtr = NULL;
+ for (; theItr != theEnd; ++theItr) {
+ thePtr = (*theItr);
+ delete thePtr;
+ }
+
+ m_PtrVector.clear();
+ }
+
+ bool empty() { return m_PtrVector.empty(); }
+
+ long IndexOf(const TPtr *inElement)
+ {
+ iterator theIter = m_PtrVector.begin();
+ const_iterator theEnd = m_PtrVector.end();
+ long theCount = 0;
+ bool theFound = false;
+
+ for (; theIter != theEnd; ++theIter) {
+ if (*theIter == inElement) {
+ theFound = true;
+ break;
+ }
+
+ ++theCount;
+ }
+
+ if (theFound)
+ return theCount;
+ else
+ return -1;
+ }
+};
+}
+
+#endif __PTRVECTOR_H__ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Quaternion.inl b/src/Authoring/Common/Code/Quaternion.inl
new file mode 100644
index 00000000..02500334
--- /dev/null
+++ b/src/Authoring/Common/Code/Quaternion.inl
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// CONSTRUCTION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Empty constructor. These default values represent the identity quaternion.
+ */
+
+CQuaternion::CQuaternion()
+ : qx(0.0f)
+ , qy(0.0f)
+ , qz(0.0f)
+ , qw(1.0f)
+{
+}
+
+//==============================================================================
+/**
+ * Simple constructor using arguments to initialize the quaternion.
+ * @param inX first component
+ * @param inY second component
+ * @param inZ third component
+ * @param inW fourth component
+ */
+
+CQuaternion::CQuaternion(const float inX, const float inY, const float inZ, const float inW)
+ : qx(inX)
+ , qy(inY)
+ , qz(inZ)
+ , qw(inW)
+{
+}
+
+//==============================================================================
+/**
+ * Copy constructor.
+ * @param inQuat the source quaternion
+ */
+
+CQuaternion::CQuaternion(const CQuaternion &inQuat)
+ : qx(inQuat.qx)
+ , qy(inQuat.qy)
+ , qz(inQuat.qz)
+ , qw(inQuat.qw)
+{
+}
+
+//==============================================================================
+/**
+ * Conversion constructor from a matrix. Expensive - caveat emptor.
+ * @param inMatrix a matrix with a rotation component to be extracted.
+ */
+
+CQuaternion::CQuaternion(const CMatrix &inMatrix)
+{
+ *this = inMatrix;
+}
+
+//==============================================================================
+/**
+ * Conversion constructor from an axis with an angle
+ * @param inAxisAngle the axis and angle the quaternion will represent.
+ */
+
+CQuaternion::CQuaternion(const CAxisAngle &inAxisAngle)
+{
+ *this = inAxisAngle;
+}
+
+//==============================================================================
+/**
+ * Conversion constructor from a set of euler angles.
+ * @param inAngles the angles the quaternion will represent.
+ */
+
+CQuaternion::CQuaternion(const CEulerAngles &inAngles)
+{
+ *this = inAngles;
+}
+
+//==============================================================================
+// INITIALIZATION
+//==============================================================================
+
+/**
+ * Explicit assignment method.
+ * @param inX first component
+ * @param inY second component
+ * @param inZ third component
+ * @param inW fourth component
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::Set(const float inX, const float inY, const float inZ, const float inW)
+
+{
+ qx = inX;
+ qy = inY;
+ qz = inZ;
+ qw = inW;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Resets this quaternion to the identity quaternion.
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::Reset()
+
+{
+ qx = 0;
+ qy = 0;
+ qz = 0;
+ qw = 1.0f;
+ return *this;
+}
+
+//==============================================================================
+// FUNCTIONS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Normalizes this quaternion. Most quaternion operations require it to
+ * be normalized.
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::Normalize()
+
+{
+
+ float theNorm = qx * qx + qy * qy + qz * qz + qw * qw;
+
+ if (theNorm < SQREPSILON) {
+ qx = 0;
+ qy = 0;
+ qz = 0;
+ qw = 1.0f;
+ } else if (::abs(theNorm - 1.0f) > SQREPSILON) {
+ float theScale = 1.0f / ::sqrt(theNorm);
+
+ qx *= theScale;
+ qy *= theScale;
+ qz *= theScale;
+ qw *= theScale;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Inverts this quaternion.
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::Invert()
+
+{
+
+ qx = -qx;
+ qy = -qy;
+ qz = -qz;
+ qw = -qw;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Gets the dotproduct between this and another quaternion.
+ * @return the dotproduct
+ */
+
+float CQuaternion::DotProduct(const CQuaternion &inQuat) const
+
+{
+
+ return qx * inQuat.qx + qy * inQuat.qy + qz * inQuat.qz + qw * inQuat.qw;
+}
+
+//==============================================================================
+/**
+ * Spherical Linear Interpolation. Rotate smoothly between two angles
+ * without the gimbal locks that plague Euler angle representations.
+ *
+ * TODO: MF - Code needs serious unit testing before release.
+ *
+ * @param inQuatA rotation we are interpolating from
+ * @param inQuatB rotation we are interpolating to
+ * @param inFactor interpolation amount: 1.0 turns this into inQuatB
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion CQuaternion::Slerp(const CQuaternion &inQuatA, const CQuaternion &inQuatB,
+ float inFactor)
+
+{
+
+ float theFlip = 1.0f;
+
+ float theCos = inQuatA.DotProduct(inQuatB); // This is cos of angle between A and B
+
+ if (theCos < 0)
+
+ {
+
+ theCos = -theCos;
+
+ theFlip = -theFlip;
+ }
+
+ float theAlpha = inFactor * theFlip;
+
+ float theBeta = 1.0f - inFactor;
+
+ // Plain linear interpolation only possible when the angle is very small, sin(x) ~= x
+
+ if ((1.0f - theCos) > FLT_EPSILON * 100.0f)
+
+ {
+
+ // Normal interpolation needed
+
+ float theTheta = ::acos(theCos);
+
+ float theSin = ::sin(theTheta);
+
+ theAlpha = ::sin(theAlpha * theTheta) / theSin;
+
+ theBeta = ::sin(theBeta * theTheta) / theSin;
+ }
+
+ return CQuaternion(inQuatA.qx * theBeta + inQuatB.qx * theAlpha,
+
+ inQuatA.qy * theBeta + inQuatB.qy * theAlpha,
+
+ inQuatA.qz * theBeta + inQuatB.qz * theAlpha,
+
+ inQuatA.qw * theBeta + inQuatB.qw * theAlpha);
+}
+
+//==============================================================================
+// CONVERTERS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Sets the rotation portion of the given matrix to equivalent of this quaternion.
+ * Be aware that only the uppe 3x3 portion is affected so be sure that the given
+ * matrix is an identity matrix unless you intend otherwise.
+ * @param outMatrix the matrix written to
+ * @return the modified matrix given as argument
+ */
+
+CMatrix &CQuaternion::ToMatrix(CMatrix &outMatrix) const
+
+{
+
+ float fTX = 2.0f * qx;
+ float fTY = 2.0f * qy;
+ float fTZ = 2.0f * qz;
+ float fTWX = fTX * qw;
+ float fTWY = fTY * qw;
+ float fTWZ = fTZ * qw;
+ float fTXX = fTX * qx;
+ float fTXY = fTY * qx;
+ float fTXZ = fTZ * qx;
+ float fTYY = fTY * qy;
+ float fTYZ = fTZ * qy;
+ float fTZZ = fTZ * qz;
+
+ float *pfMat = &outMatrix.m[0][0];
+
+ pfMat[0] = 1.0f - (fTYY + fTZZ);
+ pfMat[1] = fTXY - fTWZ;
+ pfMat[2] = fTXZ + fTWY;
+
+ pfMat[4] = fTXY + fTWZ;
+ pfMat[5] = 1.0f - (fTXX + fTZZ);
+ pfMat[6] = fTYZ - fTWX;
+
+ pfMat[8] = fTXZ - fTWY;
+ pfMat[9] = fTYZ + fTWX;
+ pfMat[10] = 1.0f - (fTXX + fTYY);
+
+ return outMatrix;
+}
+
+//==============================================================================
+/**
+ * Sets the given axis-angle to equivalent to this quaternion.
+ * @param outAxisAngle the axis-angle written to
+ * @return the modified axis-angle given as argument
+ */
+
+CAxisAngle &CQuaternion::ToAxisAngle(CAxisAngle &outAxisAngle) const
+
+{
+
+ float theSqrLength = qx * qx + qy * qy + qz * qz;
+
+ if (theSqrLength > 0) {
+ float theInvLength = 1.0f / ::log(theSqrLength);
+
+ outAxisAngle.m_Angle = 2.0f * ::acos(qw);
+ outAxisAngle.m_Axis.x = qx * theInvLength;
+ outAxisAngle.m_Axis.y = qy * theInvLength;
+ outAxisAngle.m_Axis.z = qz * theInvLength;
+ } else {
+ outAxisAngle.m_Angle = 0;
+ outAxisAngle.m_Axis.x = 1.0f;
+ outAxisAngle.m_Axis.y = 0;
+ outAxisAngle.m_Axis.z = 0;
+ }
+
+ return outAxisAngle;
+}
+
+//==============================================================================
+// OPERATORS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Simple assignment operator
+ * @param inQuat the quaternion being copied
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::operator=(const CQuaternion &inQuat)
+
+{
+ qx = inQuat.qx;
+ qy = inQuat.qy;
+ qz = inQuat.qz;
+ qw = inQuat.qw;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Assign from matrix - Extract rotation information from the given matrix.
+ * TODO: MF - Need to clean up this code after unit tests are in place.
+ * @param inMatrix the matrix containing rotation data
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::operator=(const CMatrix &inMatrix)
+
+{
+ CMatrix rkMatrix(inMatrix);
+ // Inspired by Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course
+ // article "Quaternion Calculus and Fast Animation".
+
+ float fTrace = rkMatrix[0][0] + rkMatrix[1][1] + rkMatrix[2][2];
+ float fRoot;
+
+ if (fTrace > 0.0f) {
+ fRoot = ::sqrt(fTrace + 1.0f);
+
+ qw = 0.5f * fRoot;
+
+ fRoot = 0.5f / fRoot;
+
+ qx = (rkMatrix[2][1] - rkMatrix[1][2]) * fRoot;
+ qy = (rkMatrix[0][2] - rkMatrix[2][0]) * fRoot;
+ qz = (rkMatrix[1][0] - rkMatrix[0][1]) * fRoot;
+ } else {
+ int iNext[3] = { 1, 2, 0 };
+
+ int i = 0;
+ if (rkMatrix[1][1] > rkMatrix[0][0])
+ i = 1;
+
+ if (rkMatrix[2][2] > rkMatrix[i][i])
+ i = 2;
+
+ int j = iNext[i];
+ int k = iNext[j];
+
+ fRoot = sqrtf(rkMatrix[i][i] - rkMatrix[j][j] - rkMatrix[k][k] + 1.0f);
+
+ float *apfQuat[3] = { &qx, &qy, &qz };
+
+ *(apfQuat[i]) = 0.5f * fRoot;
+
+ fRoot = 0.5f / fRoot;
+
+ qw = (rkMatrix[k][j] - rkMatrix[j][k]) * fRoot;
+
+ *(apfQuat[j]) = (rkMatrix[j][i] + rkMatrix[i][j]) * fRoot;
+ *(apfQuat[k]) = (rkMatrix[k][i] + rkMatrix[i][k]) * fRoot;
+ }
+
+ return Normalize();
+}
+
+//==============================================================================
+/**
+ * Assign from matrix - Extract rotation information from the given axis-angle.
+ * @param inAxisAngle the corresponding axis-angle
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::operator=(const CAxisAngle &inAxisAngle)
+
+{
+
+ float theHalfAngle = 0.5f * inAxisAngle.m_Angle;
+ float theSin = ::sin(theHalfAngle);
+
+ qx = theSin * inAxisAngle.m_Axis.x;
+ qy = theSin * inAxisAngle.m_Axis.y;
+ qz = theSin * inAxisAngle.m_Axis.z;
+ qw = ::cos(theHalfAngle);
+
+ return Normalize();
+}
+
+//==============================================================================
+/**
+ * Comparison operator.
+ * @param inQuat quaternion being copmpared to
+ * @return true if the quaternions are rougly the same
+ */
+
+bool CQuaternion::operator==(const CQuaternion &inQuat) const
+
+{
+
+ return (::abs(qx - inQuat.qx) < EPSILON) && (::abs(qy - inQuat.qy) < EPSILON)
+ && (::abs(qz - inQuat.qz) < EPSILON) && (::abs(qw - inQuat.qw) < EPSILON);
+}
+
+//==============================================================================
+/**
+ * Inequality operator.
+ * @para inQuat quaternion being compared to
+ * @return true if the quaternions are not even rougly the same
+ */
+
+bool CQuaternion::operator!=(const CQuaternion &inQuat) const
+
+{
+
+ return (::abs(qx - inQuat.qx) >= EPSILON) || (::abs(qy - inQuat.qy) >= EPSILON)
+ || (::abs(qz - inQuat.qz) >= EPSILON) || (::abs(qw - inQuat.qw) >= EPSILON);
+}
+
+//==============================================================================
+/**
+ * Adds this quaternion to another but does not modify this quaternion.
+ * @param inQuat the other quaternion
+ * @return a new summed quaternion
+ */
+
+CQuaternion CQuaternion::operator+(const CQuaternion &inQuat) const
+
+{
+
+ return CQuaternion(qx + inQuat.qx, qy + inQuat.qy, qz + inQuat.qz, qw + inQuat.qw);
+}
+
+//==============================================================================
+/**
+ * Adds another quaternion to this.
+ * @param inQuat the quaternion being added
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::operator+=(const CQuaternion &inQuat)
+
+{
+
+ qx += inQuat.qx;
+ qy += inQuat.qy;
+ qz += inQuat.qz;
+ qw += inQuat.qw;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Concatenates another quaternion with this without affecting this quaternion.
+ * This has the same effect as if you would multiply two rotation matrixes
+ * with each other. Alas, this operation is not commutative.
+ * @param inQuat the quaternion being concatenated.
+ * @return the new concatenated quaternion
+ */
+
+CQuaternion CQuaternion::operator*(const CQuaternion &inQuat) const
+
+{
+
+ CVector3 theVecOne(qx, qy, qz);
+ CVector3 theVecTwo(inQuat.qx, inQuat.qy, inQuat.qz);
+ CVector3 theVecResult = (theVecOne % theVecTwo) + theVecTwo * qw + theVecOne * inQuat.qw;
+
+ return CQuaternion(theVecResult.x, theVecResult.y, theVecResult.z,
+ qw * inQuat.qw - theVecOne * theVecTwo);
+}
+
+//==============================================================================
+/**
+ * Get a scaled copy of this quaternion.
+ * @param inFactor is the scaling factor
+ * @return a new scaled quaternion
+ */
+
+CQuaternion CQuaternion::operator*(float inFactor) const
+
+{
+
+ return CQuaternion(qx * inFactor, qy * inFactor, qz * inFactor, qw * inFactor);
+}
+
+//==============================================================================
+/**
+ * Concatenates this quaternion with another quaternion.
+ * This has the same effect as if you would multiply two rotation matrixes
+ * with each other. Alas, this operation is not commutative.
+ * @param inQuat the quaternion being concatenated
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::operator*=(const CQuaternion &inQuat)
+
+{
+
+ CVector3 theVecOne(qx, qy, qz);
+ CVector3 theVecTwo(inQuat.qx, inQuat.qy, inQuat.qz);
+ CVector3 theVecResult = (theVecOne % theVecTwo) + theVecTwo * qw + theVecOne * inQuat.qw;
+
+ return Set(theVecResult.x, theVecResult.y, theVecResult.z,
+ qw * inQuat.qw - theVecOne * theVecTwo);
+}
+
+//==============================================================================
+/**
+ * Scales this quaternion
+ * @param inFactor is the scaling factor
+ * @return a reference to this modified quaternion
+ */
+
+CQuaternion &CQuaternion::operator*=(float inScalar)
+
+{
+
+ qx *= inScalar;
+ qy *= inScalar;
+ qz *= inScalar;
+ qw *= inScalar;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Applies this rotation to a vector.
+ * @param inVector is the vector to be rotated.
+ * @return a new rotated vector
+ */
+
+CVector3 CQuaternion::operator*(const CVector3 &inVector) const
+
+{
+ CVector3 kVec0(qx, qy, qz);
+ CVector3 kVec1(kVec0 % inVector);
+
+ kVec1 += inVector * qw;
+
+ CVector3 kVec2 = kVec1 % kVec0;
+
+ kVec0 *= inVector * kVec0;
+ kVec0 += kVec1 * qw;
+
+ return CVector3(kVec0 - kVec2);
+}
diff --git a/src/Authoring/Common/Code/Rct.h b/src/Authoring/Common/Code/Rct.h
new file mode 100644
index 00000000..218a3454
--- /dev/null
+++ b/src/Authoring/Common/Code/Rct.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_RCT_H
+#define INCLUDED_RCT_H 1
+
+#pragma once
+
+#include "Pt.h"
+
+#include <QRect>
+
+#ifdef WIN32
+#include <Windows.h>
+#endif
+
+class CRct
+{
+public:
+ CRct();
+ CRct(long inX, long inY, long inWidth, long inHeight);
+ CRct(const CPt &inPos, const CPt &inSize);
+ CRct(const CPt &inSize);
+ CRct(const QRect &inRect);
+#ifdef WIN32
+ CRct(const RECT &inRect);
+ operator RECT() const;
+ CRct &operator=(const RECT &inRect);
+#endif
+
+ void Offset(const CPt &inOffset);
+
+ bool IsInRect(const CPt &inPoint);
+
+ void And(const CRct &inRect);
+ void Or(const CRct &inRect);
+
+ void Normalize();
+
+ static long LesserOfTwo(const long &inA, const long &inB);
+ static long GreaterOfTwo(const long &inA, const long &inB);
+
+ operator QRect() const;
+
+ CPt position;
+ CPt size;
+};
+
+//=============================================================================
+/**
+ * Constructs a rect of points 0,0,0,0.
+ */
+inline CRct::CRct()
+{
+}
+
+//=============================================================================
+/**
+ * Constructs a rect of the points.
+ * @param inX the X position of the top left of the rectangle.
+ * @param inY the Y position of the top left of the rectangle.
+ * @param inWidth the width of the rectangle.
+ * @param inHeight the height of the rectangle.
+ */
+inline CRct::CRct(long inX, long inY, long inWidth, long inHeight)
+ : position(inX, inY)
+ , size(inWidth, inHeight)
+{
+}
+
+//=============================================================================
+/**
+ * Constructs a rect of the position and size.
+ * @param inPos the position of the top left of the rectangle.
+ * @param inSize the width and height of the rectangle.
+ */
+inline CRct::CRct(const CPt &inPos, const CPt &inSize)
+ : position(inPos)
+ , size(inSize)
+{
+}
+
+//=============================================================================
+/**
+ * Constructs a rectangle at 0,0 with size inSize.
+ * @param inSize the width and height of the rectangle.
+ */
+inline CRct::CRct(const CPt &inSize)
+ : size(inSize)
+{
+}
+
+inline CRct::CRct(const QRect &inRect)
+ : position(inRect.x(), inRect.y())
+ , size(inRect.width(), inRect.height())
+{
+}
+
+#ifdef WIN32
+inline CRct::CRct(const RECT &inRect)
+ : position(inRect.left, inRect.top)
+ , size(inRect.right - inRect.left, inRect.bottom - inRect.top)
+{
+}
+
+inline CRct::operator RECT() const
+{
+ RECT theRect = { position.x, position.y, position.x + size.x, position.y + size.y };
+ return theRect;
+}
+
+inline CRct &CRct::operator=(const RECT &inRect)
+{
+ position.x = inRect.left;
+ position.y = inRect.top;
+ size.x = inRect.right - inRect.left;
+ size.y = inRect.bottom - inRect.top;
+
+ return *this;
+}
+#endif // _WIN32
+
+//=============================================================================
+/**
+ * Offset the rectangle.
+ */
+inline void CRct::Offset(const CPt &inOffset)
+{
+ position += inOffset;
+ // size += inOffset;
+}
+
+//=============================================================================
+/**
+ * @return true if the point is in this rectangle.
+ */
+inline bool CRct::IsInRect(const CPt &inPoint)
+{
+ if (inPoint.x >= position.x && inPoint.x < (position.x + size.x) && inPoint.y >= position.y
+ && inPoint.y < (position.y + size.y))
+ return true;
+ return false;
+}
+
+//=============================================================================
+/**
+ * Ease method to return the larger of the two numbers.
+ * @param inA the first number to check.
+ * @param inB the second number to check.
+ * @return the larger of the two numbers.
+ */
+inline long CRct::GreaterOfTwo(const long &inA, const long &inB)
+{
+ return (inA > inB) ? inA : inB;
+}
+
+//=============================================================================
+/**
+ * Ease method to return the smaller of the two numbers.
+ * @param inA the first number to check.
+ * @param inB the second number to check.
+ * @return the smaller of the two numbers.
+ */
+inline long CRct::LesserOfTwo(const long &inA, const long &inB)
+{
+ return (inA < inB) ? inA : inB;
+}
+
+//=============================================================================
+/**
+ * Combine inRect with this rect, setting this rect to the union of the two.
+ * This will modify this rect and make it only the area that exists in both
+ * rects.
+ * @param inRect the rect to merge with this one.
+ */
+inline void CRct::And(const CRct &inRect)
+{
+ long theXPos = GreaterOfTwo(position.x, inRect.position.x);
+ long theXSize = LesserOfTwo(position.x + size.x, inRect.position.x + inRect.size.x) - theXPos;
+ theXSize = GreaterOfTwo(0, theXSize);
+
+ long theYPos = GreaterOfTwo(position.y, inRect.position.y);
+ long theYSize = LesserOfTwo(position.y + size.y, inRect.position.y + inRect.size.y) - theYPos;
+ theYSize = GreaterOfTwo(0, theYSize);
+
+ position.x = theXPos;
+ position.y = theYPos;
+ size.x = theXSize;
+ size.y = theYSize;
+}
+
+//=============================================================================
+/**
+ * Combine inRect with this rect, making this the smallest rect containing both.
+ * This will modify this rect to make it the smallest possible rect that
+ * contains the entire area of both rects. If this rect's size is 0 then it
+ * this will be set only to inRect.
+ * @param inRect the rect to merge with this.
+ */
+inline void CRct::Or(const CRct &inRect)
+{
+ long theXPos;
+ long theXSize;
+ if (size.x == 0) {
+ theXPos = inRect.position.x;
+ theXSize = inRect.size.x;
+ } else {
+ theXPos = LesserOfTwo(position.x, inRect.position.x);
+ theXSize = GreaterOfTwo(position.x + size.x, inRect.position.x + inRect.size.x) - theXPos;
+ }
+
+ long theYPos;
+ long theYSize;
+ if (size.y == 0) {
+ theYPos = inRect.position.y;
+ theYSize = inRect.size.y;
+ } else {
+ theYPos = LesserOfTwo(position.y, inRect.position.y);
+ theYSize = GreaterOfTwo(position.y + size.y, inRect.position.y + inRect.size.y) - theYPos;
+ }
+
+ position.x = theXPos;
+ position.y = theYPos;
+ size.x = theXSize;
+ size.y = theYSize;
+}
+
+//=============================================================================
+/**
+ * Normalize this rectangle so that it's size is positive.
+ * If the size is negative in either direction then this will modify the
+ * position and the size so that the size becomes positive. The position will
+ * be modified so this will still cover the same area.
+ */
+inline void CRct::Normalize()
+{
+ if (size.x < 0) {
+ position.x += size.x;
+ size.x = -size.x;
+ }
+ if (size.y < 0) {
+ position.y += size.y;
+ size.y = -size.y;
+ }
+}
+
+inline CRct::operator QRect() const
+{
+ return QRect(position.x, position.y, size.x, size.y);
+}
+
+#endif // INCLUDED_RCT_H
diff --git a/src/Authoring/Common/Code/Report/CompConfig.cpp b/src/Authoring/Common/Code/Report/CompConfig.cpp
new file mode 100644
index 00000000..9be0554d
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/CompConfig.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifndef INCLUDED_COMP_CONFIG_H
+#include "CompConfig.h"
+#endif
+
+//==============================================================================
+/**
+ * Constructor:
+ */
+//==============================================================================
+CCompConfig::CCompConfig()
+{
+ m_TabCount = 0;
+}
+
+//==============================================================================
+/**
+ * Descructor: Destroys the object
+ */
+//==============================================================================
+CCompConfig::~CCompConfig()
+{
+}
+
+//==============================================================================
+/**
+ * SetTabCount: Sets the tab count for printing in XML format.
+ *
+ * @param <unsigned long> inTabCount The tab count
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CCompConfig::SetTabCount(unsigned long inTabCount)
+{
+ m_TabCount = inTabCount;
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Report/CompConfig.h b/src/Authoring/Common/Code/Report/CompConfig.h
new file mode 100644
index 00000000..a5f4830a
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/CompConfig.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_COMP_CONFIG_H
+#define INCLUDED_COMP_CONFIG_H 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <iostream>
+#include <string>
+#include "UICString.h"
+//#include <string>
+//#include <vector>
+//#include <Wbemidl.h>
+
+// using namespace std;
+//==============================================================================
+// Constants
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CCompConfig
+ *
+ */
+//==============================================================================
+class CCompConfig
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+protected:
+ unsigned long m_TabCount; ///< Number of tabs to print when writing to XML output
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Construction
+
+public:
+ CCompConfig();
+ virtual ~CCompConfig();
+
+ // Access
+
+public:
+ virtual void DetermineConfig() = 0;
+ void SetTabCount(unsigned long inTabCount);
+
+ virtual void WriteXML(std::ostream &inStream) = 0;
+};
+
+#endif // INCLUDED_COMP_CONFIG_H
diff --git a/src/Authoring/Common/Code/Report/CrashInfo.cpp b/src/Authoring/Common/Code/Report/CrashInfo.cpp
new file mode 100644
index 00000000..915178c9
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/CrashInfo.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#ifndef INCLUDED_CRASH_INFO_H
+#include "CrashInfo.h"
+#endif
+//#include "StudioInstance.h"
+#include "ProductInstance.h"
+
+#include <strstream>
+
+#include "Win32Config.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+//=============================================================================
+CCrashInfo::CCrashInfo()
+ : m_ProductInstance(NULL)
+{
+ // m_ProductInstance = CStudioInstance::GenerateProductInstance();
+ m_Config = new CWin32Config;
+
+ m_DeterminedConfig = false;
+}
+
+CCrashInfo::~CCrashInfo()
+{
+ delete m_Config;
+ delete m_ProductInstance;
+}
+//=============================================================================
+/**
+ * Setter for the product instance
+ * @param inProductInstance the product instance for this crash report
+ */
+void CCrashInfo::SetProductInstance(CProductInstance *inProductInstance)
+{
+ m_ProductInstance = inProductInstance;
+}
+
+//=============================================================================
+/**
+ * @param inEmailAddress the email address for the victim.
+ */
+//=============================================================================
+void CCrashInfo::SetEmailAddress(const Q3DStudio::CString &inEmailAddress)
+{
+ m_EmailAddress = inEmailAddress;
+}
+
+//=============================================================================
+/**
+ * @param inDescription the description of the crash.
+ */
+//=============================================================================
+void CCrashInfo::SetDescription(const Q3DStudio::CString &inDescription)
+{
+ m_Description = inDescription;
+}
+
+//=============================================================================
+/**
+ * @param inErrorString one line info on what the crash was.
+ */
+//=============================================================================
+void CCrashInfo::SetErrorString(const Q3DStudio::CString &inErrorString)
+{
+ m_ErrorString = inErrorString;
+}
+
+//=============================================================================
+/**
+ * Call this if the configuration is to be set, do not call it without the
+ * user's explicit permision.
+ */
+//=============================================================================
+void CCrashInfo::DetermineConfig()
+{
+ m_Config->DetermineConfig();
+ m_DeterminedConfig = true;
+}
+
+//=============================================================================
+/**
+ * @param the stack trace of the crash.
+ */
+//=============================================================================
+void CCrashInfo::SetStackTrace(const Q3DStudio::CString &inStackTrace)
+{
+ m_StackTrace = inStackTrace;
+}
+
+//=============================================================================
+/**
+ * Get all this info in XML format.
+ */
+//=============================================================================
+Q3DStudio::CString CCrashInfo::GetXMLifiedInfo()
+{
+ Q3DStudio::CString theInfo = "<crashreport>\n";
+
+ Q3DStudio::CString theEmailAddress;
+ theEmailAddress.Format(_UIC("\t<contact emailAddress=\"%ls\"/>\n"),
+ static_cast<const wchar_t *>(m_EmailAddress));
+
+ Q3DStudio::CString theDescription;
+ theDescription.Format(
+ _UIC("\t<description errorString=\"%ls\">\n\t\t<![CDATA[\n%ls\n\t\t]]>\n\t</description>\n"),
+ static_cast<const wchar_t *>(m_ErrorString), static_cast<const wchar_t *>(m_Description));
+
+ Q3DStudio::CString theProductInstance;
+ if (m_ProductInstance) {
+ std::ostrstream theProductStream;
+ m_ProductInstance->SetTabCount(1);
+
+ theProductStream << m_ProductInstance;
+ char *theProductString = theProductStream.str();
+ theProductString[theProductStream.pcount()] = 0;
+ theProductInstance = theProductString;
+ theProductInstance += "\n";
+ }
+
+ Q3DStudio::CString theConfiguration;
+ if (m_DeterminedConfig) {
+ std::ostrstream theStream;
+ m_Config->SetTabCount(1);
+ m_Config->WriteXML(theStream); // new way
+ // theStream << &m_Config; //old way
+ char *theConfigString = theStream.str();
+ theConfigString[theStream.pcount()] = 0;
+ theConfiguration = theConfigString;
+ theConfiguration += "\n";
+ }
+
+ Q3DStudio::CString theStackTrace;
+ theStackTrace.Format(_UIC("\t<stacktrace>\n\t\t<![CDATA[\n%ls\n\t\t]]>\n\t</stacktrace>\n"),
+ static_cast<const wchar_t *>(m_StackTrace));
+
+ theInfo += theEmailAddress;
+ theInfo += theDescription;
+ theInfo += theProductInstance;
+ theInfo += theConfiguration;
+ theInfo += theStackTrace;
+ theInfo += "</crashreport>";
+
+ return theInfo;
+}
diff --git a/src/Authoring/Common/Code/Report/CrashInfo.h b/src/Authoring/Common/Code/Report/CrashInfo.h
new file mode 100644
index 00000000..cc575e48
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/CrashInfo.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CRASH_INFO_H
+#define INCLUDED_CRASH_INFO_H 1
+
+#pragma once
+
+class CProductInstance;
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "CompConfig.h"
+
+class CCrashInfo
+{
+public:
+ CCrashInfo();
+ ~CCrashInfo();
+
+ void SetEmailAddress(const Q3DStudio::CString &inEmailAddress);
+ void SetDescription(const Q3DStudio::CString &inDescription);
+ void DetermineConfig();
+ void SetStackTrace(const Q3DStudio::CString &inStackTrace);
+ void SetErrorString(const Q3DStudio::CString &inErrorString);
+ void SetProductInstance(CProductInstance *inProductInstance);
+
+ Q3DStudio::CString GetXMLifiedInfo();
+
+protected:
+ Q3DStudio::CString m_EmailAddress;
+ Q3DStudio::CString m_Description;
+ Q3DStudio::CString m_StackTrace;
+ Q3DStudio::CString m_ErrorString;
+
+ CProductInstance *m_ProductInstance;
+ CCompConfig *m_Config;
+ bool m_DeterminedConfig;
+};
+
+#endif // INCLUDED_CRASH_INFO_H
diff --git a/src/Authoring/Common/Code/Report/ProductInfo.cpp b/src/Authoring/Common/Code/Report/ProductInfo.cpp
new file mode 100644
index 00000000..b73dd538
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/ProductInfo.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "ProductInfo.h"
+#ifdef WIN32
+#include "DLLVersion.h"
+#endif
+
+CProductInfo::CProductInfo(std::string inName, unsigned long inMajorNumber,
+ unsigned long inMinorNumber, unsigned long inIterationNumber,
+ unsigned long inBuildNumber)
+ : m_BuildNumber(inBuildNumber)
+ , m_MajorVersion(inMajorNumber)
+ , m_MinorVersion(inMinorNumber)
+ , m_IterationNumber(inIterationNumber)
+ , m_TabCount(0)
+{
+ m_Path = inName;
+ m_Name = NameFromPath(m_Path);
+ m_TabCount = 0;
+}
+
+#ifdef WIN32
+//=============================================================================
+/**
+ * Create a product info from a GUID.
+ * This looks up the GUID and finds the DLL associated with it then gets the
+ * DLLVersion for that DLL. The name of the product info is set as the location
+ * of the DLL.
+ * @param inGUID the GUID to query for.
+ */
+//=============================================================================
+CProductInfo::CProductInfo(Q3DStudio::CId inID)
+ : m_BuildNumber(0)
+ , m_MajorVersion(0)
+ , m_MinorVersion(0)
+ , m_IterationNumber(0)
+ , m_TabCount(0)
+{
+ Q3DStudio::CString theIDString(inID.ToString());
+ char theModuleLocation[512];
+ Q3DStudio::CString theRegKeyString("CLSID\\");
+ theRegKeyString += theIDString;
+ theRegKeyString += "\\InProcServer32";
+
+ HKEY theRegKey;
+
+ long theRegResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, theRegKeyString, 0, KEY_READ, &theRegKey);
+ if (theRegResult == ERROR_SUCCESS) {
+ DWORD theKeyType;
+ DWORD theModuleSize = sizeof(theModuleLocation);
+
+ // Query the default value
+ theRegResult =
+ RegQueryValueEx(theRegKey, NULL, NULL, &theKeyType,
+ reinterpret_cast<unsigned char *>(theModuleLocation), &theModuleSize);
+ if (theRegResult == ERROR_SUCCESS) {
+ CDLLVersion theVersion(theModuleLocation);
+
+ m_Path = theModuleLocation;
+ m_Name = NameFromPath(m_Path);
+
+ m_MajorVersion = theVersion.GetMajorVersion();
+ m_MinorVersion = theVersion.GetMinorVersion();
+ m_IterationNumber = theVersion.GetIterationNumber();
+ m_BuildNumber = theVersion.GetBuildNumber();
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Constructor from a module string.
+ * This will lookup the module, load it and attempt to query the version from
+ * it.
+ * @param inModulePath the path of the module to query.
+ */
+CProductInfo::CProductInfo(const char *inModulePath)
+ : m_BuildNumber(0)
+ , m_MajorVersion(0)
+ , m_MinorVersion(0)
+ , m_IterationNumber(0)
+ , m_TabCount(0)
+{
+ CDLLVersion theVersion(inModulePath);
+
+ m_Path = inModulePath;
+ m_Name = NameFromPath(m_Path);
+
+ m_MajorVersion = theVersion.GetMajorVersion();
+ m_MinorVersion = theVersion.GetMinorVersion();
+ m_IterationNumber = theVersion.GetIterationNumber();
+ m_BuildNumber = theVersion.GetBuildNumber();
+}
+#endif
diff --git a/src/Authoring/Common/Code/Report/ProductInfo.h b/src/Authoring/Common/Code/Report/ProductInfo.h
new file mode 100644
index 00000000..c54e9bbd
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/ProductInfo.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PRODUCT_INFO_H
+#define INCLUDED_PRODUCT_INFO_H 1
+
+#include <string>
+#include <ostream>
+#include "UICId.h"
+
+class CProductInfo
+{
+public:
+ CProductInfo(std::string inName, unsigned long inMajorNumber, unsigned long inMinorNumber,
+ unsigned long inIterationNumber, unsigned long inBuildNumber);
+
+#ifdef WIN32
+ CProductInfo(Q3DStudio::CId inID);
+ CProductInfo(const char *inModulePath);
+#endif
+
+ std::string GetName() { return m_Name; }
+
+ void SetTabCount(unsigned long inTabCount) { m_TabCount = inTabCount; }
+
+ unsigned long GetMajorVersion() { return m_MajorVersion; }
+
+ unsigned long GetMinorVersion() { return m_MinorVersion; }
+
+ unsigned long GetBuildNumber() { return m_BuildNumber; }
+
+ unsigned long GetIterationNumber() { return m_IterationNumber; }
+
+ friend std::ostream &operator<<(std::ostream &inStream, CProductInfo *inProduct)
+ {
+ for (unsigned long i = 0; i < inProduct->m_TabCount; ++i)
+ inStream << std::string("\t");
+
+ char theMajVer[10];
+ sprintf(theMajVer, "%lu", inProduct->m_MajorVersion);
+ char theMinVer[10];
+ sprintf(theMinVer, "%lu", inProduct->m_MinorVersion);
+ char theIterNum[10];
+ sprintf(theIterNum, "%lu", inProduct->m_IterationNumber);
+ char theBuildNum[10];
+ sprintf(theBuildNum, "%lu", inProduct->m_BuildNumber);
+
+ inStream << std::string("<Module moduleName=\"") << inProduct->m_Name;
+ inStream << std::string("\" moduleVersion=\"");
+ // put this next line back in if we ever have a module version
+ inStream /*<< std::string( "." )*/ << std::string(theMajVer);
+ inStream << std::string(".") << std::string(theMinVer);
+ inStream << std::string(".") << std::string(theIterNum);
+ inStream << std::string(".") << std::string(theBuildNum);
+ inStream << std::string("\"/>") << std::endl;
+ return inStream;
+ }
+
+ std::string NameFromPath(std::string &inPath)
+ {
+#ifdef WIN32
+ char theFileName[_MAX_FNAME];
+ char theExt[_MAX_EXT];
+ char theFullFileName[_MAX_PATH];
+
+ // Remove the file name and extension
+ _splitpath(inPath.c_str(), NULL, NULL, theFileName, theExt);
+ _makepath(theFullFileName, NULL, NULL, theFileName, theExt);
+
+ return std::string(theFullFileName);
+#else
+ return inPath;
+#endif
+ }
+
+protected:
+ std::string m_Name;
+ std::string m_Path;
+ unsigned long m_BuildNumber;
+ unsigned long m_MajorVersion;
+ unsigned long m_MinorVersion;
+ unsigned long m_IterationNumber;
+
+ unsigned long m_TabCount;
+};
+#endif //__PRODUCT_INFO_H_
diff --git a/src/Authoring/Common/Code/Report/ProductInstance.cpp b/src/Authoring/Common/Code/Report/ProductInstance.cpp
new file mode 100644
index 00000000..9f5e3dcf
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/ProductInstance.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#ifdef WIN32
+#include "DLLVersion.h"
+#endif
+#include "ProductInstance.h"
+
+CProductInstance::CProductInstance(std::string inName)
+{
+ m_Name = inName;
+ m_TabCount = 0;
+}
+
+CProductInstance::~CProductInstance()
+{
+ // Kill the List of Products.
+}
+
+void CProductInstance::AddInstance(CProductInstance *inChild)
+{
+ m_ChildInstances.push_back(inChild);
+}
+
+#ifdef WIN32
+void CProductInstance::AddProduct(const char *inModulePath)
+{
+
+ try {
+ CDLLVersion theVersion(inModulePath);
+ CProductInfo *theProduct = new CProductInfo(
+ inModulePath, theVersion.GetMajorVersion(), theVersion.GetMinorVersion(),
+ theVersion.GetIterationNumber(), theVersion.GetBuildNumber());
+ m_Modules.push_back(theProduct);
+ } catch (...) {
+ }
+}
+#endif
+
+void CProductInstance::AddProduct(const char *inModulePath, long inMajorVersion,
+ long inMinorVersion, long inIteration, long inBuild)
+{
+
+ try {
+ CProductInfo *theProduct =
+ new CProductInfo(inModulePath, inMajorVersion, inMinorVersion, inIteration, inBuild);
+ m_Modules.push_back(theProduct);
+ } catch (...) {
+ }
+}
+
+#ifdef WIN32
+void CProductInstance::AddProduct(Q3DStudio::CId inID)
+{
+
+ try {
+ CProductInfo *theProduct = new CProductInfo(inID);
+ m_Modules.push_back(theProduct);
+ } catch (...) {
+ }
+}
+#endif
+
+/*std::ostream& operator<<( std::ostream& inStream, CProductInstance* inProductInstance )
+{
+
+ unsigned long theCount = inProductInstance->m_Modules.size();
+ unsigned long theIndex;
+
+ for ( theIndex = 0; theIndex < inProductInstance->m_TabCount; ++theIndex )
+ inStream << "\t";
+
+
+ inStream << "<productInstance name=\"" << inProductInstance->m_Name.data() << "\">" <<
+std::endl;
+
+ for ( theIndex = 0; theIndex < theCount; theIndex++)
+ {
+ inProductInstance->m_Modules[theIndex]->SetTabCount(inProductInstance->m_TabCount +
+1);
+ inStream << (inProductInstance->m_Modules[theIndex]);
+ }
+
+ for ( theIndex = 0; theIndex < inProductInstance->m_TabCount; ++theIndex )
+ inStream << "\t";
+
+ inStream << "</productInstance >" << std::endl;
+
+ return inStream;
+}*/
diff --git a/src/Authoring/Common/Code/Report/ProductInstance.h b/src/Authoring/Common/Code/Report/ProductInstance.h
new file mode 100644
index 00000000..133d8797
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/ProductInstance.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PRODUCT_INSTANCE_H
+#define INCLUDED_PRODUCT_INSTANCE_H 1
+
+#ifndef INCLUDED_PRODUCT_INFO_H
+#include "ProductInfo.h"
+#endif
+
+#include <string>
+#include <iostream>
+#include <vector>
+
+class CProductInstance
+{
+ typedef std::vector<CProductInfo *> TProductInfo;
+ typedef std::vector<CProductInstance *> TProductInstance;
+
+protected:
+ TProductInfo m_Modules;
+ TProductInstance m_ChildInstances;
+ std::string m_Name;
+ unsigned long m_TabCount;
+
+public:
+ CProductInstance(std::string inName);
+ ~CProductInstance();
+ void AddInstance(CProductInstance *inChild);
+ void AddProduct(const char *inModulePath, long inMajorVersion, long inMinorVersion,
+ long inIteration, long inBuild);
+
+#ifdef WIN32
+ void AddProduct(Q3DStudio::CId inID);
+ void AddProduct(const char *inModulePath);
+#endif
+
+ void SetTabCount(unsigned long inTabCount) { m_TabCount = inTabCount; }
+
+ friend std::ostream &operator<<(std::ostream &inStream, CProductInstance *inProductInstance)
+ {
+
+ size_t theCount = inProductInstance->m_Modules.size();
+ size_t theIndex;
+
+ for (theIndex = 0; theIndex < inProductInstance->m_TabCount; ++theIndex)
+ inStream << "\t";
+
+ inStream << "<Instance name=\"" << inProductInstance->m_Name.data() << "\" ";
+#ifdef _DEBUG
+ inStream << "instanceType=\"Debug\">" << std::endl;
+#else
+ inStream << "instanceType=\"Release\">" << std::endl;
+#endif
+
+ for (theIndex = 0; theIndex < theCount; theIndex++) {
+ inProductInstance->m_Modules[theIndex]->SetTabCount(inProductInstance->m_TabCount + 1);
+ inStream << (inProductInstance->m_Modules[theIndex]);
+ }
+
+ for (theIndex = 0; theIndex < inProductInstance->m_TabCount; ++theIndex)
+ inStream << "\t";
+
+ for (theIndex = 0; theIndex < inProductInstance->m_ChildInstances.size(); theIndex++) {
+ inProductInstance->m_ChildInstances[theIndex]->SetTabCount(inProductInstance->m_TabCount
+ + 1);
+ inStream << inProductInstance->m_ChildInstances[theIndex];
+ }
+ inStream << "</Instance >" << std::endl;
+
+ return inStream;
+ };
+};
+#endif // INCLUDED_PRODUCT_INSTANCE_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Report/StackOps.cpp b/src/Authoring/Common/Code/Report/StackOps.cpp
new file mode 100644
index 00000000..cbcdcdc9
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/StackOps.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "StackOps.h"
+#include <stdio.h>
+
+#ifdef WIN32
+
+#include <comdef.h>
+
+typedef std::vector<size_t> ADDRVECTOR; ///< The address typedef.
+
+CrashProc CStackOps::g_CrashProc = NULL;
+void *CStackOps::g_UserData = NULL;
+
+//==============================================================================
+/**
+ * Registers the crash handler for all unhandled exceptions.
+ */
+//==============================================================================
+void CStackOps::RegisterCrashHandler()
+{
+ ::SetUnhandledExceptionFilter(&UnhandledCrashHandler);
+}
+
+//==============================================================================
+/**
+ * RunStackTrace: performs a stack trace
+ *
+ * @param ioBuffer buffer to put the stack trace in
+ * @param inBufferLength size of the buffer
+ */
+//==============================================================================
+void CStackOps::RunStackTrace(TCHAR *ioBuffer, DWORD inBufferLength)
+{
+ // TODO
+}
+
+//==============================================================================
+/**
+ * Generates a stack trace from a given CONTEXT.
+ * This is useful for getting stack traces within catch statements for where
+ * an exception was thrown.
+ *
+ * @param ioBuffer buffer to put the stack trace in.
+ * @param inBufferLength the size of the buffer.
+ * @param inContext the state of the thread for the exception, from GetExceptionInformation(
+ * )->ContextRecord.
+ */
+//==============================================================================
+void CStackOps::GetExceptionStackTrace(TCHAR *, DWORD, CONTEXT *, DWORD)
+{
+ // TODO
+}
+
+void CStackOps::SetCrashProc(CrashProc inCrashProc)
+{
+ g_CrashProc = inCrashProc;
+}
+//==============================================================================
+/**
+ * This gets called any time an unhandled exception is thrown anywhere in the
+ * application.
+ *
+ * @param pExPtrs a description of the exception.
+ * @return 0 if not handled, 1 if it was handled.
+ */
+//==============================================================================
+LONG __stdcall CStackOps::UnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs)
+{
+ if (g_CrashProc)
+ g_CrashProc(pExPtrs);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+//==============================================================================
+/**
+ * Get a somewhat useful short description of the exception.
+ *
+ * @param pExPtrs description of the exception, from GetExceptionInformation.
+ */
+//==============================================================================
+Q3DStudio::CString CStackOps::GetExceptionDescription(EXCEPTION_POINTERS *pExPtrs)
+{
+ Q3DStudio::CString theException;
+
+ switch (pExPtrs->ExceptionRecord->ExceptionCode) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ theException = "an Access Violation";
+ break;
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ theException = "an Array Bounds Exceeded";
+ break;
+ case EXCEPTION_BREAKPOINT:
+ theException = "a Breakpoint";
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ theException = "a DataType Misalignment";
+ break;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ theException = "a Float Denormal Operand";
+ break;
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ theException = "a Float Divide by Zero";
+ break;
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ theException = "a Float Inexact Result";
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ theException = "a Float Invalid Operation";
+ break;
+ case EXCEPTION_FLT_OVERFLOW:
+ theException = "a Float Overflow";
+ break;
+ case EXCEPTION_FLT_STACK_CHECK:
+ theException = "a Float Stack Check";
+ break;
+ case EXCEPTION_FLT_UNDERFLOW:
+ theException = "a Float Underflow";
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ theException = "an Illegal Instruction";
+ break;
+ case EXCEPTION_IN_PAGE_ERROR:
+ theException = "an In Page Error";
+ break;
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ theException = "an Integer Divide by Zero";
+ break;
+ case EXCEPTION_INT_OVERFLOW:
+ theException = "an Integer Overflow";
+ break;
+ case EXCEPTION_INVALID_DISPOSITION:
+ theException = "an Invalid Disposition";
+ break;
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ theException = "a Non-Continuable Exception";
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ theException = "a Private Instruction";
+ break;
+ case EXCEPTION_SINGLE_STEP:
+ theException = "a Single Step";
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ theException = "a Stack Overflow";
+ break;
+ default:
+ theException.Format(_UIC("an Error:0x%X"), pExPtrs->ExceptionRecord->ExceptionCode);
+ break;
+ }
+ return GetExceptionDescription(theException, pExPtrs);
+}
+
+//==============================================================================
+/**
+ * Get a somewhat useful short description of the exception.
+ *
+ * @param Q3DStudio::CString description of the exception
+ */
+//==============================================================================
+Q3DStudio::CString CStackOps::GetExceptionDescription(Q3DStudio::CString theException,
+ EXCEPTION_POINTERS *pExPtrs)
+{
+ Q3DStudio::CString theDescription;
+ char theBuffer[512];
+
+ theBuffer[::GetModuleFileNameA(NULL, theBuffer, sizeof(theBuffer))] = 0;
+
+ theDescription += theBuffer;
+ theDescription += " Caused ";
+ theDescription += theException;
+
+ theException.Format(_UIC(" at 0x%X"), pExPtrs->ExceptionRecord->ExceptionAddress);
+
+ theDescription += theException;
+
+ return theDescription;
+}
+
+#pragma warning(disable : 4748)
+#pragma warning(disable : 4740)
+
+#endif
+
+#if _MSC_VER >= 1300
+#include <rtcapi.h>
+#endif
+#ifndef _AddressOfReturnAddress
+// Taken from: http://msdn.microsoft.com/en-us/library/s975zw7k(VS.71).aspx
+#ifdef __cplusplus
+#define EXTERNC extern "C"
+#else
+#define EXTERNC
+#endif
+// _ReturnAddress and _AddressOfReturnAddress should be prototyped before use
+EXTERNC void *_AddressOfReturnAddress(void);
+EXTERNC void *_ReturnAddress(void);
+#endif
+// The following function retrieves exception info
+// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
+#ifdef KDAB_TEMPORARILY_REMOVED
+void CStackOps::GetExceptionPointers(DWORD dwExceptionCode,
+ EXCEPTION_POINTERS **ppExceptionPointers)
+{
+ // The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
+
+ EXCEPTION_RECORD ExceptionRecord;
+ CONTEXT ContextRecord;
+ memset(&ContextRecord, 0, sizeof(CONTEXT));
+
+#ifdef _X86_
+ __asm {
+ mov dword ptr [ContextRecord.Eax], eax
+ mov dword ptr [ContextRecord.Ecx], ecx
+ mov dword ptr [ContextRecord.Edx], edx
+ mov dword ptr [ContextRecord.Ebx], ebx
+ mov dword ptr [ContextRecord.Esi], esi
+ mov dword ptr [ContextRecord.Edi], edi
+ mov word ptr [ContextRecord.SegSs], ss
+ mov word ptr [ContextRecord.SegCs], cs
+ mov word ptr [ContextRecord.SegDs], ds
+ mov word ptr [ContextRecord.SegEs], es
+ mov word ptr [ContextRecord.SegFs], fs
+ mov word ptr [ContextRecord.SegGs], gs
+ pushfd
+ pop [ContextRecord.EFlags]
+ }
+ ContextRecord.ContextFlags = CONTEXT_CONTROL;
+#pragma warning(push)
+#pragma warning(disable : 4311)
+ ContextRecord.Eip = (ULONG)_ReturnAddress();
+ ContextRecord.Esp = (ULONG)_AddressOfReturnAddress();
+#pragma warning(pop)
+ ContextRecord.Ebp = *((ULONG *)_AddressOfReturnAddress() - 1);
+#elif defined(_IA64_) || defined(_AMD64_)
+ /* Need to fill up the Context in IA64 and AMD64. */
+ RtlCaptureContext(&ContextRecord);
+#else /* defined (_IA64_) || defined (_AMD64_) */
+ ZeroMemory(&ContextRecord, sizeof(ContextRecord));
+#endif /* defined (_IA64_) || defined (_AMD64_) */
+ ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
+ ExceptionRecord.ExceptionCode = dwExceptionCode;
+ ExceptionRecord.ExceptionAddress = _ReturnAddress();
+
+ EXCEPTION_RECORD *pExceptionRecord = new EXCEPTION_RECORD;
+ memcpy(pExceptionRecord, &ExceptionRecord, sizeof(EXCEPTION_RECORD));
+ CONTEXT *pContextRecord = new CONTEXT;
+ memcpy(pContextRecord, &ContextRecord, sizeof(CONTEXT));
+ *ppExceptionPointers = new EXCEPTION_POINTERS;
+ (*ppExceptionPointers)->ExceptionRecord = pExceptionRecord;
+ (*ppExceptionPointers)->ContextRecord = pContextRecord;
+}
+
+//==============================================================================
+/**
+ * EnableCrashingOnCrashes, allow exceptions to be thrown regardless due to the
+ * fact that on 64bit windows, it was not possible to unwind stack across kernel boundary
+ *
+ * hhttps://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/
+ * http://support.microsoft.com/kb/976038
+ *
+ */
+//==============================================================================
+
+void CStackOps::EnableCrashingOnCrashes()
+{
+ typedef BOOL(WINAPI * tGetPolicy)(LPDWORD lpFlags);
+ typedef BOOL(WINAPI * tSetPolicy)(DWORD dwFlags);
+ const DWORD EXCEPTION_SWALLOWING = 0x1;
+
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ tGetPolicy pGetPolicy =
+ (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
+ tSetPolicy pSetPolicy =
+ (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
+ if (pGetPolicy && pSetPolicy) {
+ DWORD dwFlags;
+ if (pGetPolicy(&dwFlags)) {
+ // Turn off the filter
+ pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
+ }
+ }
+}
+#endif
diff --git a/src/Authoring/Common/Code/Report/StackOps.h b/src/Authoring/Common/Code/Report/StackOps.h
new file mode 100644
index 00000000..8d8750f2
--- /dev/null
+++ b/src/Authoring/Common/Code/Report/StackOps.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STACK_OPS_H
+#define INCLUDED_STACK_OPS_H
+
+#pragma once
+
+#include "UICString.h"
+
+#ifdef WIN32
+typedef void (*CrashProc)(EXCEPTION_POINTERS *pExPtrs);
+#endif
+
+class CStackOps
+{
+public:
+#ifdef WIN32
+ static void RunStackTrace(TCHAR *inBuffer, DWORD inBufferLength);
+ static void GetExceptionStackTrace(TCHAR *inBuffer, DWORD inBufferLength, CONTEXT *stCtx,
+ DWORD dwNumSkip = 0);
+
+ static LONG __stdcall UnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs);
+ static void RegisterCrashHandler();
+ static void SetCrashProc(CrashProc inCrashProc);
+
+ static Q3DStudio::CString GetExceptionDescription(EXCEPTION_POINTERS *pExPtrs);
+ static Q3DStudio::CString GetExceptionDescription(Q3DStudio::CString theException,
+ EXCEPTION_POINTERS *pExPtrs);
+ static void GetExceptionPointers(DWORD dwExceptionCode,
+ EXCEPTION_POINTERS **ppExceptionPointers);
+ static void EnableCrashingOnCrashes();
+
+ // this should only be called from the place where the object is setting the call back
+ // otherwise we could end up with a nasty runtime error
+ static void SetUserData(void *inUserData) { g_UserData = inUserData; }
+ static void *GetUserData() { return g_UserData; }
+#else
+#endif
+
+protected:
+#ifdef WIN32
+ static CrashProc g_CrashProc;
+ static void *g_UserData;
+#endif
+};
+
+#endif // INCLUDED_STACK_OPS_H
+
+#ifdef WIN32
+#define TRY_REPORT __try
+#define CATCH_REPORT \
+ __except (CStackOps::UnhandledCrashHandler(GetExceptionInformation())) {}
+#else
+#define TRY_REPORT try
+#define CATCH_REPORT \
+ catch (...) { /** TODO: implement stacktrace*/}
+#endif
+
+//#ifdef WIN32
+//#define REPORT_CRASH CStackObject::StudioUnhandledCrashHandler( ::GetExceptionInformation( ) )
+//#else
+//#define REPORT_CRASH
+//#endif
+
+/*
+Sample code to activate the exception handler from a try/except
+__try
+{
+}
+__except( CStackOps::StudioUnhandledCrashHandler( GetExceptionInformation( ) ) )
+{
+}
+*/ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/SIterator.h b/src/Authoring/Common/Code/SIterator.h
new file mode 100644
index 00000000..9d8f82d1
--- /dev/null
+++ b/src/Authoring/Common/Code/SIterator.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SITERATOR_H
+#define INDLUDED_SITERATOR_H 1
+
+#pragma once
+
+template <class TObject>
+class CSIterator
+{
+public:
+ virtual bool IsDone() = 0;
+ virtual void operator++() = 0;
+ virtual void operator+=(const long inNumToInc) = 0;
+ virtual TObject GetCurrent() = 0;
+ virtual TObject operator->() { return GetCurrent(); }
+ virtual TObject operator*() { return GetCurrent(); }
+ virtual operator TObject() { return GetCurrent(); }
+protected:
+};
+
+#endif // INCLUDED_SITERATOR_H
diff --git a/src/Authoring/Common/Code/STLHelpers.h b/src/Authoring/Common/Code/STLHelpers.h
new file mode 100644
index 00000000..c8b022a0
--- /dev/null
+++ b/src/Authoring/Common/Code/STLHelpers.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef __STLHELPERS_H__
+#define __STLHELPERS_H__
+
+namespace Q3DStudio {
+
+/**
+ * @class CForEachDelete
+ * @brief Used in the std::for_each to delete object of type T.
+ */
+template <class T>
+class CForEachDelete
+{
+public: // Operators
+ void operator()(T *&inMember)
+ {
+ delete inMember;
+ inMember = NULL;
+ }
+};
+
+/**
+ * @class CForEachDeleteMapFirst
+ * @brief Used in the std::for_each to delete the Itr->first object from a std::map.
+ */
+template <class T1, class T2>
+class CForEachDeleteMapFirst
+{
+public: // Operators
+ void operator()(std::pair<T1, T2> inMember)
+ {
+ delete inMember.first;
+ inMember.first = NULL;
+ }
+};
+
+/**
+ * @class CForEachDeleteMapSecond
+ * @brief Used in the std::for_each to delete the Itr->second object from a std::map.
+ */
+template <class T1, class T2>
+class CForEachDeleteMapSecond
+{
+public: // Operators
+ void operator()(std::pair<T1, T2> inMember)
+ {
+ delete inMember.second;
+ inMember.second = NULL;
+ }
+};
+
+/**
+ * @class CForEachDeleteMapFirstAndSecond
+ * @brief Used in the std::for_each to delete the Itr->first and Itr->second object from a
+ *std::map.
+ */
+template <class T1, class T2>
+class CForEachDeleteMapFirstAndSecond
+{
+public: // Operators
+ void operator()(std::pair<T1, T2> inMember)
+ {
+ delete inMember.first;
+ inMember.first = NULL;
+
+ delete inMember.second;
+ inMember.second = NULL;
+ }
+};
+} // namespace Q3DStudio
+#endif // __STLHELPERS_H__ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/SafeArray.h b/src/Authoring/Common/Code/SafeArray.h
new file mode 100644
index 00000000..deea6e81
--- /dev/null
+++ b/src/Authoring/Common/Code/SafeArray.h
@@ -0,0 +1,695 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SAFE_ARRAY_H
+#define INCLUDED_SAFE_ARRAY_H 1
+
+#pragma once
+
+#include <vector>
+#include <assert.h>
+#include "SIterator.h"
+
+#ifndef ASSERT
+#ifdef _DEBUG
+#define ASSERT(a) assert(a)
+#else
+#define ASSERT(a)
+#endif
+#endif
+
+template <class TObject>
+class CSafeArray;
+
+template <class TObject>
+class CSafeArray
+{
+public:
+ class CSafeIterator;
+ class CIterator;
+ class CReverseIterator;
+
+ typedef std::vector<TObject> TVector;
+ typedef std::vector<CSafeIterator *> TIteratorList;
+
+ CSafeArray();
+ virtual ~CSafeArray();
+
+ void Add(const TObject &inObject);
+ void Add(const TObject &inObject, const CSafeIterator &inBeforePos);
+ void Remove(const CSafeIterator &inIterator);
+
+ TObject Get(long inIndex);
+
+ long GetCount();
+
+ // These functions were moved into the header to eliminate the CodeWarrior warnings that are
+ // produced
+ // when the functions are outside of the header file.
+ inline CIterator Begin() { return CIterator(this); }
+ CReverseIterator RBegin() { return CReverseIterator(this); }
+ //=============================================================================
+ /**
+ * Get a pointer iterating through this array forwards.
+ * @return an iterator iterating forwards through this array.
+ */
+ inline CIterator GetIterator() { return CIterator(this); }
+
+ //=============================================================================
+ /**
+ * Get a pointer iterating through this array backwards.
+ * @return an iterator iterating bakcwards through this array.
+ */
+ CReverseIterator GetReverseIterator() { return CReverseIterator(this); }
+
+ //=============================================================================
+ /**
+ * Register an iterator as being an iterator on this array.
+ * This will provide the iterator with access to the underlying vector.
+ * @param inIterator the iterator that is being registered.
+ * @return the underlying vector, for fast access.
+ */
+ TVector *Register(CSafeIterator *inIterator)
+ {
+ m_Iterators.push_back(inIterator);
+
+ return &m_Array;
+ }
+ void Deregister(CSafeIterator *inIterator);
+
+public:
+ class CSafeIterator : public CSIterator<TObject>
+ {
+ // friend CSafeArray<TObject>;
+ public:
+ CSafeIterator() {}
+ virtual ~CSafeIterator() {}
+
+ virtual void ArrayIndexAdded(long inIndex) = 0;
+ virtual void ArrayIndexRemoved(long inIndex) = 0;
+ virtual long GetArrayIndex() const = 0;
+ virtual typename std::vector<TObject>::iterator GetIterator() const = 0;
+ virtual void ArrayGoingAway() = 0;
+ };
+
+ //==========================================================================
+ /**
+ * Forward iterator class.
+ */
+ class CIterator : public CSafeIterator
+ {
+ typedef std::vector<TObject> TVector;
+
+ public:
+ //=======================================================================
+ /**
+ * Create a forward iterator iterating over inArray.
+ * @param inArray the array this is iterating over.
+ */
+ CIterator(CSafeArray<TObject> *inArray)
+ {
+ m_Array = inArray;
+ m_Vector = inArray->Register(this);
+ m_Position = m_Vector->begin();
+ m_Index = 0;
+ m_IsInvalid = false;
+ }
+
+ //=======================================================================
+ /**
+ * Copy constructor for a forward iterator.
+ * @param inIterator the iterator being copied.
+ */
+ CIterator(const CIterator &inIterator)
+ {
+ m_Array = inIterator.m_Array;
+ if (m_Array) {
+ m_Vector = m_Array->Register(this);
+
+ m_Position = inIterator.m_Position;
+ m_Index = inIterator.m_Index;
+ m_IsInvalid = inIterator.m_IsInvalid;
+ }
+ }
+
+ //=======================================================================
+ /**
+ * Destructor, cool eh?
+ */
+ virtual ~CIterator()
+ {
+ if (m_Array)
+ m_Array->Deregister(this);
+ }
+
+ //=======================================================================
+ /**
+ * Assignment operator, Copies inIterator.
+ * @param inIterator the iterator being copied.
+ */
+ CIterator &operator=(const CIterator &inIterator)
+ {
+ if (&inIterator == this)
+ return *this;
+
+ // Deregister from previous array
+ if (m_Array)
+ m_Array->Deregister(this);
+
+ m_Array = inIterator.m_Array;
+ if (m_Array) {
+ m_Position = inIterator.m_Position;
+ m_Index = inIterator.m_Index;
+ m_IsInvalid = inIterator.m_IsInvalid;
+
+ m_Vector = m_Array->Register(this);
+ }
+
+ return *this;
+ }
+
+ //=======================================================================
+ /**
+ * Increment the index of the object in the array.
+ * GetCurrent will now refer to the next object.
+ */
+ void operator++() override
+ {
+ if (m_Array) {
+ ++m_Index;
+
+ m_Position = m_Vector->begin();
+ if (m_Index > 0 && m_Index < (long)m_Vector->size())
+ m_Position += m_Index;
+
+ m_IsInvalid = false;
+ }
+ }
+
+ //=======================================================================
+ /**
+ * Increment the index of the object in the array.
+ * GetCurrent will now point to index + inNumToInc'th object.
+ * @param inNumToInc the amount to increment the index by.
+ */
+ void operator+=(const long inNumToInc) override
+ {
+ if (m_Array) {
+ m_Index += inNumToInc;
+
+ m_Position = m_Vector->begin();
+ if (m_Index > 0 && m_Index < (long)m_Vector->size())
+ m_Position += m_Index;
+
+ m_IsInvalid = false;
+ }
+ }
+
+ //=======================================================================
+ /**
+ * Checks to see if there's any more elements in the array.
+ * @return true if GetCurrent can be called again.
+ */
+ bool IsDone() override
+ {
+ if (m_Array)
+ return m_Index >= (long)m_Vector->size();
+ else
+ return true;
+ }
+
+ bool HasNext()
+ {
+ if (m_Array)
+ return m_Index < (long)m_Vector->size();
+ else
+ return false;
+ }
+
+ //=======================================================================
+ /**
+ * Get the element at the current index.
+ * @return the element at the current index.
+ */
+ TObject GetCurrent() override
+ {
+ if (m_Array) {
+ // assert( !m_IsInvalid );
+
+ return (*m_Position);
+ }
+ // assert( false );
+
+ return (*m_Position);
+ }
+
+ TObject operator*() override
+ {
+ if (m_Array) {
+ // assert( !m_IsInvalid );
+ return (*m_Position);
+ }
+ // assert( false );
+ return (*m_Position);
+ }
+
+ protected:
+ //=======================================================================
+ /**
+ * Notification from the Array that an item was removed.
+ * @param inIndex the index of the object that was removed.
+ */
+ void ArrayIndexRemoved(long inIndex) override
+ {
+ if (m_Array) {
+ if (inIndex <= m_Index)
+ --m_Index;
+
+ m_Position = m_Vector->begin();
+
+ if (m_Index > 0 && m_Index < (long)m_Vector->size())
+ m_Position += m_Index;
+
+ m_IsInvalid = true;
+ }
+ }
+
+ //=======================================================================
+ /**
+ * Notification from the array that an item was added.
+ * @param inIndex the index of the object that was added.
+ */
+ void ArrayIndexAdded(long inIndex) override
+ {
+ if (m_Array) {
+ if (inIndex <= m_Index)
+ ++m_Index;
+
+ m_Position = m_Vector->begin();
+
+ if (m_Index > 0 && m_Index < (long)m_Vector->size())
+ m_Position += m_Index;
+
+ m_IsInvalid = true;
+ }
+ }
+
+ //=======================================================================
+ /**
+ * Notification from the array that it is being deleted.
+ * This will cause all current iterating to end.
+ */
+ void ArrayGoingAway() override { m_Array = NULL; }
+
+ //=======================================================================
+ /**
+ * Get the index of the item that this is referring to.
+ * @return the index of the item this is referring to.
+ */
+ long GetArrayIndex() const override { return m_Index; }
+
+ //=======================================================================
+ /**
+ * Get the underlying control of this iterator.
+ * @return the underlying iterator.
+ */
+ typename TVector::iterator GetIterator() const override { return m_Position; }
+
+ CSafeArray<TObject> *m_Array;
+ TVector *m_Vector;
+ typename TVector::iterator m_Position;
+ long m_Index;
+ bool m_IsInvalid;
+ };
+
+ class CReverseIterator : public CSafeIterator
+ {
+ typedef std::vector<TObject> TVector;
+
+ public:
+ //=======================================================================
+ /**
+ * Creates a reverse iterator iterating over inArray.
+ * @param inArray the array this is iterating over.
+ */
+ CReverseIterator(CSafeArray<TObject> *inArray)
+ {
+ m_Array = inArray;
+ m_Vector = inArray->Register(this);
+ m_RPosition = m_Vector->rbegin();
+
+ m_Index = 0;
+ m_IsInvalid = false;
+ }
+
+ //=======================================================================
+ /**
+ * Copies a reverse iterator.
+ */
+ CReverseIterator(const CReverseIterator &inIterator)
+ {
+ m_Array = inIterator.m_Array;
+ if (m_Array) {
+ m_Vector = m_Array->Register(this);
+ m_RPosition = inIterator.m_RPosition;
+ m_Index = inIterator.m_Index;
+ m_IsInvalid = inIterator.m_IsInvalid;
+ }
+ }
+
+ virtual ~CReverseIterator()
+ {
+ // Remove this from the list of iterators in m_Array.
+ if (m_Array)
+ m_Array->Deregister(this);
+ }
+
+ //=======================================================================
+ /**
+ * Set this iterator equal to inIterator.
+ * @param inIterator the iterator being copied.
+ */
+ CReverseIterator &operator=(const CReverseIterator &inIterator)
+ {
+ if (&inIterator == this)
+ return *this;
+
+ // Remove registration from previous array
+ if (m_Array)
+ m_Array->Deregister(this);
+
+ m_Array = inIterator.m_Array;
+ m_RPosition = inIterator.m_RPosition;
+ m_Index = inIterator.m_Index;
+ m_IsInvalid = inIterator.m_IsInvalid;
+
+ // Add registration to new array.
+ if (m_Array)
+ m_Vector = m_Array->Register(this);
+
+ return *this;
+ }
+
+ //=======================================================================
+ /**
+ * Increment the location of this iterator.
+ * This will advance to the next object.
+ */
+ virtual void operator++()
+ {
+ if (m_Array) {
+ ++m_RPosition;
+ ++m_Index;
+ }
+
+ m_IsInvalid = false;
+ }
+
+ //=======================================================================
+ /**
+ * Increment the location of this iterator inNumToInc places.
+ * This will advance to the next inNumToInc object.
+ * @param inNumToInc the number of places to advance.
+ */
+ virtual void operator+=(const long inNumToInc)
+ {
+ if (m_Array) {
+ m_RPosition += inNumToInc;
+ m_Index += inNumToInc;
+ }
+ m_IsInvalid = false;
+ }
+
+ //=======================================================================
+ /**
+ * Checks to see if there are any more objects in this iterator.
+ * @return true if GetCurrent can be called.
+ */
+ virtual bool IsDone()
+ {
+ if (m_Array)
+ return m_RPosition == m_Vector->rend();
+ return true;
+ }
+
+ bool HasNext()
+ {
+ if (m_Array)
+ return m_RPosition != m_Vector->rend();
+ return false;
+ }
+
+ //=======================================================================
+ /**
+ * Get the current object in this iterator.
+ * @return the object at the current position this iterator is pointing to.
+ */
+ virtual TObject GetCurrent()
+ {
+ ASSERT(!m_IsInvalid);
+ ASSERT(m_Array);
+
+ return (*m_RPosition);
+ }
+
+ TObject operator*()
+ {
+ ASSERT(!m_IsInvalid);
+ ASSERT(m_Array);
+
+ return (*m_RPosition);
+ }
+
+ protected:
+ //=======================================================================
+ /**
+ * Notification from the Array that the item at inIndex was removed.
+ * @param inIndex the index of the object that was removed.
+ */
+ void ArrayIndexRemoved(long inIndex)
+ {
+ ASSERT(m_Array);
+
+ if ((long)(m_Vector->size() - inIndex) <= m_Index) {
+ --m_Index;
+ }
+
+ m_RPosition = m_Vector->rbegin();
+
+ if (m_Index > 0 && m_Index < (long)m_Vector->size())
+ m_RPosition += m_Index;
+
+ m_IsInvalid = true;
+ }
+
+ //=======================================================================
+ /**
+ * Notification from the Array that an item was added at inIndex.
+ * @param inIndex the index of the object that was added.
+ */
+ void ArrayIndexAdded(long inIndex)
+ {
+ ASSERT(m_Array);
+
+ if ((long)(m_Vector->size() - inIndex) <= m_Index) {
+ ++m_Index;
+ }
+ m_RPosition = m_Vector->rbegin();
+ if (m_Index > 0)
+ m_RPosition += m_Index;
+
+ m_IsInvalid = true;
+ }
+
+ //=======================================================================
+ /**
+ * Notification from the Array that it is being deleted.
+ * This will cause all iteration to end.
+ */
+ void ArrayGoingAway()
+ {
+ ASSERT(m_Array);
+
+ m_Array = NULL;
+ }
+
+ //=======================================================================
+ /**
+ * Get the index of the item that this array is pointing to.
+ * @return the index of the item that this array is pointing to.
+ */
+ long GetArrayIndex() const
+ {
+ ASSERT(m_Array);
+
+ return (long)m_Vector->size() - m_Index;
+ }
+
+ //=======================================================================
+ /**
+ * Get the underlying iterator that this is using.
+ * @return the underlying iterator that this is using.
+ */
+ typename TVector::iterator GetIterator() const
+ {
+ ASSERT(m_Array);
+
+ return m_RPosition.base();
+ }
+
+ CSafeArray<TObject> *m_Array; ///< The Array that this is iterating over.
+ TVector *m_Vector; ///< The fast-access vector of the array this is iterating over.
+ typename TVector::reverse_iterator
+ m_RPosition; ///< The position of this iterator, in terms of m_Vector.
+ long m_Index; ///< The index of this iterator in the vector.
+ bool m_IsInvalid; ///< True if the GetCurrent is invalid, the ++ operator must be called
+ ///first.
+ };
+
+protected:
+ TVector m_Array;
+ TIteratorList m_Iterators;
+};
+
+//=============================================================================
+/**
+ * Creates an empty SafeArray.
+ */
+template <typename T>
+inline CSafeArray<T>::CSafeArray()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor.
+ */
+template <typename T>
+inline CSafeArray<T>::~CSafeArray()
+{
+ typename TIteratorList::iterator theIterPos = m_Iterators.begin();
+ for (; theIterPos != m_Iterators.end(); ++theIterPos) {
+ (*theIterPos)->ArrayGoingAway();
+ }
+}
+
+//=============================================================================
+/**
+ * Add an element to the back of this array.
+ * @param inElement the element to be added.
+ */
+template <typename T>
+inline void CSafeArray<T>::Add(const T &inElement)
+{
+ long theIndex = long(m_Array.size());
+ m_Array.push_back(inElement);
+
+ typename TIteratorList::iterator theIterPos = m_Iterators.begin();
+ for (; theIterPos != m_Iterators.end(); ++theIterPos) {
+ (*theIterPos)->ArrayIndexAdded(theIndex);
+ }
+}
+
+//=============================================================================
+/**
+ * Add an element to this array at a specified index.
+ * @param inElement the element to be added to this array.
+ * @param inBeforePos the position this should be added in, pushing the existing
+ * element up one.
+ */
+template <typename T>
+inline void CSafeArray<T>::Add(const T &inElement,
+ const typename CSafeArray<T>::CSafeIterator &inBeforePos)
+{
+ long theIndex = inBeforePos.GetArrayIndex();
+ m_Array.insert(inBeforePos.GetIterator(), inElement);
+
+ typename TIteratorList::iterator theIterPos = m_Iterators.begin();
+ for (; theIterPos != m_Iterators.end(); ++theIterPos) {
+ (*theIterPos)->ArrayIndexAdded(theIndex);
+ }
+}
+
+//=============================================================================
+/**
+ * Remove an element from this array.
+ * @param inIterator the index of this item to be removed.
+ */
+template <typename T>
+inline void CSafeArray<T>::Remove(const typename CSafeArray<T>::CSafeIterator &inIterator)
+{
+ long theErasedIndex = 0;
+ theErasedIndex = inIterator.GetArrayIndex();
+ m_Array.erase(inIterator.GetIterator());
+
+ typename TIteratorList::iterator theIterPos = m_Iterators.begin();
+ for (; theIterPos != m_Iterators.end(); ++theIterPos) {
+ (*theIterPos)->ArrayIndexRemoved(theErasedIndex);
+ }
+}
+
+//=============================================================================
+/**
+ * Get the item at index inIndex.
+ * @param inIndex the index of the item to fetch.
+ * @return the item at index inIndex.
+ */
+template <typename T>
+inline T CSafeArray<T>::Get(long inIndex)
+{
+ return m_Array.at(inIndex);
+}
+
+//=============================================================================
+/**
+ * Get the number of elements in this array.
+ */
+template <typename T>
+inline long CSafeArray<T>::GetCount()
+{
+ return long(m_Array.size());
+}
+
+//=============================================================================
+/**
+ * Remove an iterator from the list of iterators iterating on this object.
+ * @param inIterator the location of the iterator to be removed.
+ */
+template <typename T>
+inline void CSafeArray<T>::Deregister(typename CSafeArray<T>::CSafeIterator *inIterator)
+{
+ typename TIteratorList::iterator thePos = m_Iterators.begin();
+ for (; thePos != m_Iterators.end(); ++thePos) {
+ if ((*thePos) == inIterator) {
+ m_Iterators.erase(thePos);
+ break;
+ }
+ }
+}
+#endif // INCLUDED_SAFE_ARRAY_H
diff --git a/src/Authoring/Common/Code/SafeQueue.h b/src/Authoring/Common/Code/SafeQueue.h
new file mode 100644
index 00000000..9a16b038
--- /dev/null
+++ b/src/Authoring/Common/Code/SafeQueue.h
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Mutex.h"
+#include "Guard.h"
+#include <queue>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CSafeQueue:
+ * @brief A thread safe, template class that wraps std::queue.
+ *
+ * This class uses the Bomb Ass Critical Section class to protect every queue
+ * method with a critical section. It is a template class.
+ *
+ */
+//==============================================================================
+template <class T>
+class CSafeQueue
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+private:
+ std::queue<T> m_Queue; ///< The std::queue that this class wraps.
+ CMutex m_Mutex; ///< The critical section
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Construction
+
+public:
+ CSafeQueue() {}
+ virtual ~CSafeQueue() {}
+
+ // Access
+
+public:
+ void Push(const T &inItem);
+ void Pop();
+ bool Empty();
+ size_t Size();
+ const T &Front() const;
+ T &Front();
+ const T &Back() const;
+ T &Back();
+};
+
+//==============================================================================
+/**
+ * Push: The member function inserts an element with value inItem at the end
+ * of the controlled sequence..
+ *
+ * @param inItem The item that is being inserted into the queue.
+ *
+ * @return void
+ */
+//==============================================================================
+template <class T>
+void CSafeQueue<T>::Push(const T &inItem)
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ m_Queue.push(inItem);
+}
+
+//==============================================================================
+/**
+ * Pop: The member function removes the last element of the controlled
+ * sequence, which must be non-empty.
+ *
+ * @return void
+ */
+//==============================================================================
+template <class T>
+void CSafeQueue<T>::Pop()
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ m_Queue.pop();
+}
+
+//==============================================================================
+/**
+ * Empty: The member function tells if the queue is empty or not.
+ *
+ * @return bool Returns true if the queue is empty, and false if it's not.
+ */
+//=============================================================================
+template <class T>
+bool CSafeQueue<T>::Empty()
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ return m_Queue.empty();
+}
+
+//==============================================================================
+/**
+ * Size: The member function returns the length of the controlled sequence.
+ *
+ * @return size_t The number of items in the queue.
+ */
+//=============================================================================
+template <class T>
+size_t CSafeQueue<T>::Size()
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ return m_Queue.size();
+}
+
+//==============================================================================
+/**
+ * Front: The member function returns a reference to the first element of the
+ * controlled sequence, which must be non-empty.
+ *
+ * @return T& A reference to the first element.
+ */
+//=============================================================================
+template <class T>
+T &CSafeQueue<T>::Front()
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ return m_Queue.front();
+}
+
+//==============================================================================
+/**
+ * Front: The member function returns a reference to the first element of the
+ * controlled sequence, which must be non-empty.
+ *
+ * @return const T& A reference to the first element.
+ */
+//=============================================================================
+template <class T>
+const T &CSafeQueue<T>::Front() const
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ return m_Queue.front();
+}
+
+//==============================================================================
+/**
+ * Back: The member function returns a reference to the last element of the
+ * controlled sequence, which must be non-empty.
+ *
+ * @return const T& A reference to the first element.
+ */
+//=============================================================================
+template <class T>
+T &CSafeQueue<T>::Back()
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ return m_Queue.back();
+}
+
+//==============================================================================
+/**
+ * Back: The member function returns a reference to the last element of the
+ * controlled sequence, which must be non-empty.
+ *
+ * @return const T& A reference to the first element.
+ */
+//=============================================================================
+template <class T>
+const T &CSafeQueue<T>::Back() const
+{
+ CGuard theThreadGuard(m_Mutex);
+
+ return m_Queue.back();
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Serialize/FormattedInputStream.cpp b/src/Authoring/Common/Code/Serialize/FormattedInputStream.cpp
new file mode 100644
index 00000000..6629930b
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/FormattedInputStream.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "FormattedInputStream.h"
+#include "UICEndian.h"
+#include "FileOutputStream.h"
+//#include "BufferedOutputStream.h"
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+CFormattedInputStream::CFormattedInputStream(CInputStream *inInputStream)
+ : m_InputStream(inInputStream)
+ , m_IsBigEndian(false)
+ , m_Count(0)
+{
+}
+
+CFormattedInputStream::~CFormattedInputStream()
+{
+}
+
+long CFormattedInputStream::Read(void *inData, long inLength)
+{
+ m_Count += inLength;
+
+ return m_InputStream->Read(inData, inLength);
+}
+
+void CFormattedInputStream::Close()
+{
+ m_InputStream->Close();
+}
+
+bool CFormattedInputStream::IsValid()
+{
+ return m_InputStream->IsValid();
+}
+
+CFormattedInputStream &CFormattedInputStream::operator>>(long &inLong)
+{
+ m_Count += sizeof(long);
+
+ m_InputStream->Read(&inLong, sizeof(long));
+ BTOH4(inLong, inLong);
+ SWAP4BYTES(inLong, inLong);
+ return *this;
+}
+
+CFormattedInputStream &CFormattedInputStream::operator>>(unsigned long &inLong)
+{
+ m_Count += sizeof(unsigned long);
+
+ m_InputStream->Read(&inLong, sizeof(unsigned long));
+ BTOH4(inLong, inLong);
+ SWAP4BYTES(inLong, inLong);
+ return *this;
+}
+
+CFormattedInputStream &CFormattedInputStream::operator>>(float &inFloat)
+{
+ m_Count += sizeof(float);
+
+ m_InputStream->Read(&inFloat, sizeof(float));
+ // BTOH4( inFloat, inFloat );
+
+ return *this;
+}
+
+CFormattedInputStream &CFormattedInputStream::operator>>(short &inShort)
+{
+ m_Count += sizeof(short);
+
+ m_InputStream->Read(&inShort, sizeof(short));
+ BTOH2(inShort, inShort);
+ SWAP2BYTES(inShort, inShort);
+ return *this;
+}
+
+CFormattedInputStream &CFormattedInputStream::operator>>(Q3DStudio::UICChar &inUICChar)
+{
+ m_Count += sizeof(Q3DStudio::UICChar);
+
+ m_InputStream->Read(&inUICChar, sizeof(Q3DStudio::UICChar));
+ BTOH2(inUICChar, inUICChar);
+ SWAP2BYTES(inUICChar, inUICChar);
+ return *this;
+}
+
+CFormattedInputStream &CFormattedInputStream::operator>>(bool &inBool)
+{
+ m_Count += sizeof(bool);
+
+ m_InputStream->Read(&inBool, sizeof(bool));
+
+ return *this;
+}
+
+unsigned char CFormattedInputStream::ReadUnsignedChar()
+{
+ m_Count += sizeof(unsigned char);
+
+ unsigned char theChar;
+ m_InputStream->Read(&theChar, sizeof(unsigned char));
+ return theChar;
+}
+
+unsigned short CFormattedInputStream::ReadUnsignedShort()
+{
+ m_Count += sizeof(unsigned short);
+
+ unsigned short theShort;
+ m_InputStream->Read(&theShort, sizeof(unsigned short));
+ BTOH2(theShort, theShort);
+ SWAP2BYTES(theShort, theShort);
+ return theShort;
+}
+
+void CFormattedInputStream::CopyToFile(const CUICFile &inFile, long inLength,
+ bool inCloseStream /*= true */)
+{
+ Q3DStudio::CString thePath = inFile.GetAbsolutePosixPath();
+
+ CFileOutputStream theFileStream(thePath);
+
+ unsigned long theLength = inLength;
+ unsigned long theBufferSize = 1024;
+ while (theBufferSize < theLength / 10 && theBufferSize < 1e6)
+ theBufferSize *= 2; // double until we have a buffer that is about %10 of file size
+ char *theBuffer = new char[theBufferSize];
+
+ unsigned long theReadCount = theBufferSize;
+ unsigned long theTotalReadCount = 0;
+
+ // Loop around reading from the archive and writing to the file.
+ while (theTotalReadCount < theLength) {
+ if (theLength - theTotalReadCount < theReadCount)
+ theReadCount = theLength - theTotalReadCount;
+
+ Read(theBuffer, theReadCount);
+ theFileStream.Write(theBuffer, theReadCount);
+
+ theTotalReadCount += theReadCount;
+ }
+
+ if (inCloseStream)
+ theFileStream.Close();
+ delete[] theBuffer;
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Serialize/FormattedInputStream.h b/src/Authoring/Common/Code/Serialize/FormattedInputStream.h
new file mode 100644
index 00000000..ef1b43a7
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/FormattedInputStream.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_FORMATTED_INPUT_STREAM_H
+#define INCLUDED_FORMATTED_INPUT_STREAM_H 1
+
+#pragma once
+
+#include "UICFile.h"
+#include "UICString.h"
+#include "InputStream.h"
+
+class CFormattedInputStream : public CInputStream
+{
+public:
+ CFormattedInputStream(CInputStream *inInputStream);
+ virtual ~CFormattedInputStream();
+
+ long Read(void *inData, long inLength) override;
+ void Close() override;
+ bool IsValid() override;
+ Q3DStudio::CString GetMimeType() override { return L""; }
+ Q3DStudio::CString GetSource() override { return L""; }
+
+ void SetBigEndian(bool inIsBigEndian);
+
+ CFormattedInputStream &operator>>(long &);
+ CFormattedInputStream &operator>>(unsigned long &);
+ CFormattedInputStream &operator>>(float &);
+ CFormattedInputStream &operator>>(short &);
+ CFormattedInputStream &operator>>(Q3DStudio::UICChar &);
+ CFormattedInputStream &operator>>(bool &);
+
+ unsigned char ReadUnsignedChar();
+ unsigned short ReadUnsignedShort();
+
+ void CopyToFile(const CUICFile &inFilename, long inLength, bool inCloseStream = true);
+
+protected:
+ CInputStream *m_InputStream;
+ bool m_IsBigEndian;
+ long m_Count;
+};
+#endif // INCLUDED_FORMATTED_INPUT_STREAM_H
diff --git a/src/Authoring/Common/Code/Serialize/FormattedOutputStream.cpp b/src/Authoring/Common/Code/Serialize/FormattedOutputStream.cpp
new file mode 100644
index 00000000..eef0865e
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/FormattedOutputStream.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICEndian.h"
+
+#include "FormattedOutputStream.h"
+
+CFormattedOutputStream::CFormattedOutputStream(CSeekOutputStream *inOutputStream)
+ : m_OutputStream(inOutputStream)
+{
+}
+
+CFormattedOutputStream::~CFormattedOutputStream()
+{
+}
+
+long CFormattedOutputStream::Write(const void *inData, long inLength)
+{
+ return m_OutputStream->Write(inData, inLength);
+}
+
+void CFormattedOutputStream::Close()
+{
+ m_OutputStream->Close();
+}
+
+void CFormattedOutputStream::Flush()
+{
+ m_OutputStream->Flush();
+}
+
+bool CFormattedOutputStream::IsValid()
+{
+ return m_OutputStream->IsValid();
+}
+
+CFormattedOutputStream &CFormattedOutputStream::operator<<(float inValue)
+{
+ m_OutputStream->Write(&inValue, sizeof(float));
+
+ return *this;
+}
+
+CFormattedOutputStream &CFormattedOutputStream::operator<<(long inValue)
+{
+#ifdef WIN32
+ m_OutputStream->Write(&inValue, sizeof(long));
+#else
+ SWAP4BYTES(inValue, inValue);
+ m_OutputStream->Write(&inValue, sizeof(long));
+#endif
+
+ return *this;
+}
+
+CFormattedOutputStream &CFormattedOutputStream::operator<<(short inValue)
+{
+#ifdef WIN32
+ m_OutputStream->Write(&inValue, sizeof(short));
+#else
+ SWAP2BYTES(inValue, inValue);
+ m_OutputStream->Write(&inValue, sizeof(short));
+#endif
+
+ return *this;
+}
+
+CFormattedOutputStream &CFormattedOutputStream::operator<<(Q3DStudio::UICChar inValue)
+{
+#ifdef WIN32
+ m_OutputStream->Write(&inValue, sizeof(Q3DStudio::UICChar));
+#else
+ SWAP2BYTES(inValue, inValue);
+ m_OutputStream->Write(&inValue, sizeof(Q3DStudio::UICChar));
+#endif
+
+ return *this;
+}
+
+CFormattedOutputStream &CFormattedOutputStream::operator<<(bool inValue)
+{
+ m_OutputStream->Write(&inValue, sizeof(bool));
+
+ return *this;
+}
diff --git a/src/Authoring/Common/Code/Serialize/FormattedOutputStream.h b/src/Authoring/Common/Code/Serialize/FormattedOutputStream.h
new file mode 100644
index 00000000..3b7a8212
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/FormattedOutputStream.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_FORMATTED_OUTPUT_STREAM_H
+#define INCLUDED_FORMATTED_OUTPUT_STREAM_H 1
+
+#pragma once
+
+#include "UICString.h"
+#include "OutputStream.h"
+
+class CFormattedOutputStream : public CSeekOutputStream
+{
+public:
+ CFormattedOutputStream(CSeekOutputStream *inOutputStream);
+ virtual ~CFormattedOutputStream();
+
+ long Write(const void *inData, long inLength) override;
+ void Close() override;
+ bool IsValid() override;
+ void Flush() override;
+
+ // CSeekOutputStream
+ long Seek(ESeekPosition inPosition, long inOffset) override
+ {
+ return m_OutputStream->Seek(inPosition, inOffset);
+ }
+ long GetCurrentPosition() override { return m_OutputStream->GetCurrentPosition(); }
+
+ CFormattedOutputStream &operator<<(float inValue);
+ CFormattedOutputStream &operator<<(long inValue);
+ CFormattedOutputStream &operator<<(bool inValue);
+ CFormattedOutputStream &operator<<(short inValue);
+ CFormattedOutputStream &operator<<(Q3DStudio::UICChar inValue);
+
+protected:
+ CSeekOutputStream *m_OutputStream;
+};
+#endif // INCLUDED_FORMATTED_OUTPUT_STREAM_H
diff --git a/src/Authoring/Common/Code/Serialize/PreferencesSerializer.cpp b/src/Authoring/Common/Code/Serialize/PreferencesSerializer.cpp
new file mode 100644
index 00000000..03fc4cab
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/PreferencesSerializer.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "PreferencesSerializer.h"
+
+#include <QDir>
+
+CPreferencesSerializer::CPreferencesSerializer()
+ : m_FileSet(false)
+ , m_PreferencesStrTable(IStringTable::CreateStringTable())
+ , m_PreferencesFactory(IDOMFactory::CreateDOMFactory(m_PreferencesStrTable))
+{
+}
+
+CPreferencesSerializer::~CPreferencesSerializer()
+{
+ Serialize();
+}
+
+void CPreferencesSerializer::SetPreferencesFile(const Q3DStudio::CString &theFile)
+{
+ Q3DStudio::CFilePath fPath = Q3DStudio::CFilePath::Normalize(theFile);
+
+ if (m_PreferencesFile.Compare(fPath, false))
+ return;
+
+ Serialize();
+
+ m_PreferencesFile = fPath;
+
+ SDOMElement *topElement = NULL;
+ if (m_PreferencesFile.IsFile()) {
+ qt3ds::foundation::CFileSeekableIOStream theInStream(m_PreferencesFile,
+ qt3ds::foundation::FileReadFlags());
+ if (theInStream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ m_FileSet = false;
+ return;
+ }
+
+ topElement = CDOMSerializer::Read(*m_PreferencesFactory, theInStream);
+ if (topElement == NULL) {
+ QT3DS_ASSERT(false);
+ m_FileSet = false;
+ return;
+ }
+ } else {
+ topElement = m_PreferencesFactory->NextElement(L"Settings");
+ }
+
+ m_PreferencesIO =
+ IDOMWriter::CreateDOMWriter(m_PreferencesFactory, *topElement, m_PreferencesStrTable);
+ m_FileSet = true;
+}
+
+void CPreferencesSerializer::Begin(const Q3DStudio::CString &inTag)
+{
+ if (!m_FileSet) {
+ return;
+ }
+ if (!inTag.IsEmpty()) {
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ CStringTokenizer theTokenizer(inTag, L"\\");
+ do {
+ Q3DStudio::CString theTag = theTokenizer.GetCurrentPartition();
+ if (!theReader->MoveToFirstChild(theTag.c_str())) {
+ std::shared_ptr<IDOMWriter> theWriter(m_PreferencesIO.first);
+ theWriter->Begin(theTag.c_str());
+ }
+ ++theTokenizer;
+ } while (theTokenizer.HasNextPartition());
+ }
+}
+
+bool CPreferencesSerializer::GetSubElemValue(const Q3DStudio::CString &inSubElem,
+ Q3DStudio::CString &outValue)
+{
+ if (!m_FileSet) {
+ return false;
+ }
+
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ IDOMReader::Scope _readerScoped(*theReader);
+ bool hasNext = true;
+
+ for (hasNext = theReader->MoveToFirstChild(); hasNext;
+ hasNext = theReader->MoveToNextSibling()) {
+ TWideXMLCharPtr strValue;
+ theReader->Att(L"name", strValue);
+ if (inSubElem.CompareNoCase(strValue)) {
+ theReader->Att(L"value", strValue);
+ outValue.assign(strValue);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CPreferencesSerializer::SetSubElemValue(const Q3DStudio::CString &inSubElem,
+ const Q3DStudio::CString &inValue)
+{
+ if (!m_FileSet) {
+ return;
+ }
+
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ theReader->PushScope();
+ bool hasNext = true, hasFind = false;
+ TWideXMLCharPtr strValue;
+ for (hasNext = theReader->MoveToFirstChild(); hasNext;
+ hasNext = theReader->MoveToNextSibling()) {
+
+ theReader->Att(L"name", strValue);
+ if (inSubElem.CompareNoCase(strValue)) {
+ hasFind = true;
+ break;
+ }
+ }
+ if (hasFind) {
+ std::shared_ptr<IDOMWriter> theWriter(m_PreferencesIO.first);
+ theWriter->Att(L"value", inValue.c_str());
+ theReader->PopScope();
+ } else {
+ theReader->PopScope();
+ std::shared_ptr<IDOMWriter> theWriter(m_PreferencesIO.first);
+ theWriter->Begin(L"Item");
+ theWriter->Att(L"Name", inSubElem.c_str());
+ theWriter->Att(L"value", inValue.c_str());
+ }
+}
+void CPreferencesSerializer::Revert()
+{
+ if (!m_FileSet) {
+ return;
+ }
+
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ theReader->SetScope(theReader->GetTopElement());
+}
+
+void CPreferencesSerializer::Remove(const Q3DStudio::CString &inTag)
+{
+ if (!m_FileSet) {
+ return;
+ }
+ if (!inTag.IsEmpty()) {
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ CStringTokenizer theTokenizer(inTag, L"\\");
+ Q3DStudio::CString theTag;
+ bool bBreak = true;
+ do {
+ theTag = theTokenizer.GetCurrentPartition();
+ bBreak = theReader->MoveToFirstChild(theTag.c_str());
+ if (!bBreak)
+ break;
+ ++theTokenizer;
+ } while (theTokenizer.HasNextPartition());
+ if (bBreak) {
+ std::shared_ptr<IDOMWriter> theWriter(m_PreferencesIO.first);
+ theWriter->RemoveCurrent();
+ }
+ } else {
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ while (theReader->CountChildren() > 0) {
+ theReader->MoveToFirstChild();
+ std::shared_ptr<IDOMWriter> theWriter(m_PreferencesIO.first);
+ theWriter->RemoveCurrent();
+ }
+ }
+}
+
+long CPreferencesSerializer::CountSubElems() const
+{
+ if (!m_FileSet) {
+ return 0;
+ }
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ return static_cast<long>(theReader->CountChildren());
+}
+
+void CPreferencesSerializer::RemoveSubElem(const Q3DStudio::CString &inSubElem)
+{
+ if (!m_FileSet) {
+ return;
+ }
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ IDOMReader::Scope _readerScoped(*theReader);
+ bool hasNext = true;
+ TWideXMLCharPtr strValue;
+ for (hasNext = theReader->MoveToFirstChild(); hasNext;
+ hasNext = theReader->MoveToNextSibling()) {
+ theReader->Att(L"name", strValue);
+ if (inSubElem.CompareNoCase(strValue)) {
+ std::shared_ptr<IDOMWriter> theWriter(m_PreferencesIO.first);
+ theWriter->RemoveCurrent();
+ break;
+ }
+ }
+}
+
+bool CPreferencesSerializer::ExistElem(const Q3DStudio::CString &inElemName)
+{
+ if (!m_FileSet) {
+ return false;
+ }
+ std::shared_ptr<IDOMReader> theReader(m_PreferencesIO.second);
+ IDOMReader::Scope _readerScoped(*theReader);
+ return theReader->MoveToFirstChild(inElemName.c_str());
+}
+
+void CPreferencesSerializer::Serialize()
+{
+ if (m_FileSet) {
+ QString preferencesDir = m_PreferencesFile.GetDirectory().toQString();
+ QDir dir(preferencesDir);
+ if (!dir.exists()) {
+ dir.mkpath(preferencesDir);
+ }
+
+ // Serialize the preferences in to the XML file
+ qt3ds::foundation::CFileSeekableIOStream stream(m_PreferencesFile,
+ qt3ds::foundation::FileWriteFlags());
+ stream.SetPosition(0, qt3ds::foundation::SeekPosition::Begin);
+ CDOMSerializer::WriteXMLHeader(stream);
+ CDOMSerializer::Write(*m_PreferencesIO.first->GetTopElement(), stream);
+ }
+}
diff --git a/src/Authoring/Common/Code/Serialize/PreferencesSerializer.h b/src/Authoring/Common/Code/Serialize/PreferencesSerializer.h
new file mode 100644
index 00000000..0a6f0d3f
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/PreferencesSerializer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PREFERENCES_SERIALIZER_H
+#define INCLUDED_PREFERENCES_SERIALIZER_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMXML.h"
+#include "StringTokenizer.h"
+#include "UICFileTools.h"
+
+using namespace UICDM;
+
+class CPreferencesSerializer
+{
+public: // construction
+ CPreferencesSerializer();
+ ~CPreferencesSerializer();
+
+public: // methods
+ void SetPreferencesFile(const Q3DStudio::CString &theFile);
+
+ void Begin(const Q3DStudio::CString &inTag);
+
+ bool GetSubElemValue(const Q3DStudio::CString &inSubElem, Q3DStudio::CString &outValue);
+
+ void Revert();
+
+ void Remove(const Q3DStudio::CString &inTag);
+
+ void SetSubElemValue(const Q3DStudio::CString &inSubElem, const Q3DStudio::CString &inValue);
+
+ long CountSubElems() const;
+
+ void RemoveSubElem(const Q3DStudio::CString &inSubElem);
+
+ bool ExistElem(const Q3DStudio::CString &inElemName);
+
+ bool IsFileSet() const { return m_FileSet; }
+
+private:
+ void Serialize();
+
+private:
+ bool m_FileSet;
+ Q3DStudio::CFilePath m_PreferencesFile;
+ TStringTablePtr m_PreferencesStrTable;
+ eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>> m_PreferencesIO;
+ std::shared_ptr<IDOMFactory> m_PreferencesFactory;
+};
+
+#endif // INCLUDED_PREFERENCES_SERIALIZER_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h b/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h
new file mode 100644
index 00000000..7cd66f93
--- /dev/null
+++ b/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROJECT_SETTINGS_SERIALIZER_H
+#define INCLUDED_PROJECT_SETTINGS_SERIALIZER_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioProjectSettings.h"
+#include "StudioProjectVariables.h"
+#include "UICDMXML.h"
+#include "UICDMWStrOpsImpl.h"
+
+#include <QtWidgets/qcolordialog.h>
+
+namespace UICDM {
+}
+
+class CProjectSettingsSerializer
+{
+ class CustomColorSerializer
+ {
+ public:
+ void Serialize(UICDM::IDOMWriter &ar)
+ {
+ using namespace UICDM;
+ ar.Att(L"count", static_cast<qt3ds::QT3DSI32>(QColorDialog::customCount()));
+ QString strColor;
+ for (int i = 0; i < QColorDialog::customCount(); ++i) {
+ if (i > 0)
+ strColor += QLatin1Char(' ');
+ QColor color = QColorDialog::customColor(i);
+ strColor += QVariant(color).toString();
+ }
+ QByteArray data = strColor.toLatin1();
+ ar.Value(data.data());
+ }
+ void Serialize(UICDM::IDOMReader &ar)
+ {
+ using namespace UICDM;
+ TCharStr countStr;
+ ar.Att(L"count", countStr);
+ int count = QString::fromWCharArray(countStr.wide_str()).toInt();
+ const wchar_t *value;
+ if (ar.Value(value)) {
+ QString strColor = QString::fromWCharArray(value);
+ QStringList strColors = strColor.split(" ");
+ if (count != strColors.size())
+ qWarning() << "Color count is invalid.";
+ for (int i = 0; i < strColors.size(); ++i) {
+ QColor color = QColor(strColors.at(i));
+ QColorDialog::setCustomColor(i, color);
+ }
+ }
+ }
+ };
+
+public:
+ CProjectSettingsSerializer(CStudioProjectSettings *inSettings)
+ : m_ProjectSettings(inSettings)
+ {
+ }
+ virtual ~CProjectSettingsSerializer() {}
+
+ void Serialize(UICDM::IDOMWriter &ar)
+ {
+ using namespace UICDM;
+ using namespace std;
+ CStudioProjectSettings *theProjectSettings = GetProjectSettings();
+ Q3DStudio::CString author =
+ Q3DStudio::CString::fromQString(theProjectSettings->GetAuthor());
+ TCharPtr theAuthor = author;
+ ar.Att(L"author", theAuthor);
+ Q3DStudio::CString company =
+ Q3DStudio::CString::fromQString(theProjectSettings->GetCompany());
+ TCharPtr theCompany = company;
+ ar.Att(L"company", theCompany);
+
+ CPt theSize = theProjectSettings->GetPresentationSize();
+ ar.Att(L"presentationWidth", static_cast<qt3ds::QT3DSI32>(theSize.x));
+ ar.Att(L"presentationHeight", static_cast<qt3ds::QT3DSI32>(theSize.y));
+
+ if (theProjectSettings->GetRotatePresentation()) {
+ ar.Att("presentationRotation", "90");
+ }
+
+ bool theMaintainAspect = theProjectSettings->GetMaintainAspect();
+ ar.Att(L"maintainAspect", theMaintainAspect);
+
+ if (QColorDialog::customCount() > 0) {
+ CustomColorSerializer ccs;
+ ar.Serialize(L"CustomColors", ccs);
+ }
+ }
+ void Serialize(UICDM::IDOMReader &ar)
+ {
+ using namespace UICDM;
+ using namespace std;
+ CStudioProjectSettings *theProjectSettings = GetProjectSettings();
+ theProjectSettings->Reset();
+
+ TCharStr theAuthor;
+ ar.Att(L"author", theAuthor);
+ Q3DStudio::CString theAuthorStr(theAuthor.wide_str());
+ theProjectSettings->SetAuthor(theAuthorStr.toQString());
+
+ TCharStr theCompany;
+ ar.Att(L"company", theCompany);
+ Q3DStudio::CString theCompanyStr(theCompany.wide_str());
+ theProjectSettings->SetCompany(theCompanyStr.toQString());
+
+ qt3ds::QT3DSI32 thePresentationWidth;
+ qt3ds::QT3DSI32 thePresentationHeight;
+ ar.Att("presentationWidth", thePresentationWidth);
+ ar.Att("presentationHeight", thePresentationHeight);
+ theProjectSettings->SetPresentationSize(CPt(thePresentationWidth, thePresentationHeight));
+
+ qt3ds::QT3DSI32 thePresentationRotate;
+ if (ar.Att("presentationRotation", thePresentationRotate) && thePresentationRotate == 90)
+ theProjectSettings->SetRotatePresentation(true);
+
+ bool theMaintainAspect;
+ ar.Att(L"maintainAspect", theMaintainAspect);
+ theProjectSettings->SetMaintainAspect(theMaintainAspect);
+
+ {
+ CustomColorSerializer ccs;
+ ar.Serialize(L"CustomColors", ccs);
+ }
+ }
+
+ CStudioProjectSettings *GetProjectSettings() { return m_ProjectSettings; }
+
+private:
+ CStudioProjectSettings *m_ProjectSettings;
+};
+
+template <typename Archive>
+void save(Archive &ar, const CProjectSettingsSerializer &inData, unsigned int)
+{
+ CStudioProjectSettings *theProjectSettings =
+ const_cast<CProjectSettingsSerializer &>(inData).GetProjectSettings();
+}
+
+template <typename Archive>
+void load(Archive &ar, CProjectSettingsSerializer &inData, unsigned int)
+{
+}
+
+#endif // INCLUDED_PROJECT_SETTINGS_SERIALIZER_H
diff --git a/src/Authoring/Common/Code/StackTokenizer.cpp b/src/Authoring/Common/Code/StackTokenizer.cpp
new file mode 100644
index 00000000..1143b7a1
--- /dev/null
+++ b/src/Authoring/Common/Code/StackTokenizer.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StackTokenizer.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+ * CTOR
+ * @param inString the string to tokenize
+ * @param inToken single char token
+ * @param inEscapeChar single char escape char
+ */
+CStackTokenizer::CStackTokenizer(const Q3DStudio::CString &inString, Q3DStudio::UICChar inDelimiter,
+ Q3DStudio::UICChar inEscapeChar)
+ : m_String(inString)
+ , m_Delimiter(inDelimiter)
+ , m_EscapeChar(inEscapeChar)
+ , m_Index(0)
+ , m_LastIndex(0)
+ , m_StringLength(inString.Length())
+{
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+CStackTokenizer::~CStackTokenizer()
+{
+}
+
+//==============================================================================
+/**
+ * Returns true if string contains another token that can be read.
+ * @return bool true of there is another token to be read
+ */
+bool CStackTokenizer::HasNextPartition()
+{
+ if (m_Index >= m_StringLength)
+ return false;
+ else
+ return true;
+}
+
+//==============================================================================
+/**
+ * Retrieve the current token within the string.
+ * @return Q3DStudio::CString the string value of the token
+ */
+
+Q3DStudio::CString CStackTokenizer::GetCurrentPartition()
+
+{
+ std::deque<Q3DStudio::UICChar> theStack;
+ bool theIgnoreEscapeChar = false;
+ bool theFoundToken = false;
+ long theCurrentIndex = m_Index;
+ Q3DStudio::CString theResult;
+
+ if (!m_String.IsEmpty()) {
+ while (!theFoundToken) {
+ // get the char at this index
+ Q3DStudio::UICChar theChar = m_String.GetAt(theCurrentIndex++);
+
+ if (theChar == m_Delimiter) {
+ if (theStack.size() != 0) {
+ if (theStack.front() == m_EscapeChar && !theIgnoreEscapeChar) {
+ theStack.pop_front(); // escape this delimiter
+ theStack.push_front(theChar);
+ } else
+ theFoundToken = true; // found a delimiter, time to stop
+ } else
+ theFoundToken = true; // this results in an empty token
+ } else if (theChar == m_EscapeChar) {
+ if (theStack.size() != 0) {
+ if (theStack.front() == m_EscapeChar && !theIgnoreEscapeChar) {
+ theIgnoreEscapeChar = true; //'escape' the escape char
+ } else {
+ theStack.push_front(theChar); // treat escape char as a normal
+ theIgnoreEscapeChar = false; // char.
+ }
+ } else
+ theStack.push_front(theChar); // wait for next character to determine
+ // what this should do.
+ } else
+ theStack.push_front(theChar); // any other characters
+
+ if (theCurrentIndex == m_StringLength) // case when we reach the end of the string
+ theFoundToken = true; // without encountering a delimiter.
+ }
+
+ m_LastIndex = theCurrentIndex; // update the last 'tokenized' position
+
+ while (theStack.size() != 0) {
+ theResult.Concat(theStack.back()); // put everything back into a string
+ theStack.pop_back();
+ }
+ }
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Advances to the next token within the string. Use HasNextPartition to
+ * determine when to stop advancing.
+ */
+void CStackTokenizer::operator++()
+{
+ if (m_LastIndex > m_Index)
+ m_Index = m_LastIndex;
+ else {
+ GetCurrentPartition();
+ this->operator++();
+ }
+}
diff --git a/src/Authoring/Common/Code/StackTokenizer.h b/src/Authoring/Common/Code/StackTokenizer.h
new file mode 100644
index 00000000..35cb5ffe
--- /dev/null
+++ b/src/Authoring/Common/Code/StackTokenizer.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STACKTOKENIZER_H_
+#define INCLUDED_STACKTOKENIZER_H_ 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CStackTokenizer seperates a string out using a delimiter; Difference
+ * between it and CStringTokenizer is that the
+ *delimiter
+ * is a single UICChar and there is an escape char as
+ *well.
+ */
+class CStackTokenizer
+{
+public:
+ CStackTokenizer(const Q3DStudio::CString &inString, Q3DStudio::UICChar inDelimiter,
+ Q3DStudio::UICChar inEscapeChar);
+ virtual ~CStackTokenizer();
+
+ bool HasNextPartition();
+ Q3DStudio::CString GetCurrentPartition();
+ void operator++();
+
+protected:
+ Q3DStudio::CString m_String; ///< contains the string to tokenize
+ Q3DStudio::UICChar m_Delimiter; ///< single char delimiter
+ Q3DStudio::UICChar m_EscapeChar; ///< single char escape char
+ long m_Index; ///< index to begin tokenizing the string from
+ long m_LastIndex; ///< index of the string since last tokenize operation
+ const long m_StringLength; ///< length of the string to tokenize
+};
+
+#endif // INCLUDED_STACKTOKENIZER_H_ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/StaticMaxSize.h b/src/Authoring/Common/Code/StaticMaxSize.h
new file mode 100644
index 00000000..8dcbe285
--- /dev/null
+++ b/src/Authoring/Common/Code/StaticMaxSize.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_STATIC_MAX_SIZE_H
+#define INCLUDED_STATIC_MAX_SIZE_H
+
+namespace Q3DStudio {
+
+template <class... Ts>
+struct StaticMaxSize;
+
+template <class T, class... Ts>
+struct StaticMaxSize<T, Ts...>
+{
+ static const size_t value = sizeof(T) > StaticMaxSize<Ts...>::value
+ ? sizeof(T) : StaticMaxSize<Ts...>::value;
+};
+
+template <class T>
+struct StaticMaxSize<T>
+{
+ static const size_t value = sizeof(T);
+};
+
+} // namespace Q3DStudio
+#endif // INCLUDED_STATIC_MAX_SIZE_H
diff --git a/src/Authoring/Common/Code/StopWatch.h b/src/Authoring/Common/Code/StopWatch.h
new file mode 100644
index 00000000..cbfc97eb
--- /dev/null
+++ b/src/Authoring/Common/Code/StopWatch.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "HiResTimer.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * @class CStopWatch
+ * @brief Stackbased timer class in microseonds.
+ * Times the lifespan of this obbject and sets the given argument accordingly.
+ */
+class CStopWatch
+{
+ CStopWatch(const CStopWatch &);
+ CStopWatch &operator=(const CStopWatch &);
+
+public:
+ CHiResTimer theTimer;
+ long &m_Result;
+
+ CStopWatch(long &inResult)
+ : m_Result(inResult)
+ {
+ theTimer.Start();
+ }
+
+ ~CStopWatch()
+ {
+ theTimer.Stop();
+ m_Result = static_cast<long>(theTimer.ElapsedMicroSecs());
+ }
+};
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/StrUtilities.cpp b/src/Authoring/Common/Code/StrUtilities.cpp
new file mode 100644
index 00000000..1c725952
--- /dev/null
+++ b/src/Authoring/Common/Code/StrUtilities.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#include "stdafx.h"
+#include "StrUtilities.h"
+#include <wchar.h>
+#include <stdio.h>
+//==============================================================================
+// Internal Helper
+//==============================================================================
+//==============================================================================
+/**
+ * @class CConvertStr
+ *
+ * Converts string from I type to O type
+ */
+template <typename I, typename O>
+class CConvertStr
+{
+private:
+ std::basic_string<O> m_OutStr;
+
+public:
+ CConvertStr() {}
+
+ ~CConvertStr() {}
+
+public:
+ //==============================================================================
+ /**
+ * The function. Takes in either const I* pointer or std::basic_string< I >
+ * @param inStr == the string to be converted
+ * @param inCount == the string length, in case, we do not hav a properly terminated
+ * I* pointer passed in
+ * @return the converted string
+ */
+ const O *operator()(const std::basic_string<I> &inStr, long inCount = 0)
+ {
+ m_OutStr.clear();
+ if (inCount == 0) {
+ for (typename std::basic_string<I>::const_iterator theIterator = inStr.begin();
+ theIterator != inStr.end(); ++theIterator) {
+ m_OutStr.push_back(static_cast<O>(*theIterator));
+ }
+ } else {
+ for (long theIndex = 0; theIndex < inCount; ++theIndex) {
+ m_OutStr.push_back(static_cast<O>(inStr[theIndex]));
+ }
+
+ m_OutStr.push_back(0);
+ }
+
+ return m_OutStr.c_str();
+ }
+};
+
+//==============================================================================
+// String Conversion Functions
+//==============================================================================
+
+std::wstring &operator<<(std::wstring &inStr, bool inBool)
+{
+ inStr += inBool ? L"true" : L"false";
+
+ return inStr;
+}
+
+std::wstring &operator<<(std::wstring &inStr, long inLong)
+{
+ // wchar_t theStr[ 64 ];
+
+ //#ifdef WIN32
+ // ::swprintf( theStr, L"%ld", inLong );
+ //#else
+ // ::swprintf( theStr, 32, L"%ld", inLong );
+ //#endif
+ // this should work across platforms
+ //::swprintf( theStr, 64, L"%ld", inLong );
+
+ char theStr[64];
+ sprintf(theStr, "%ld", inLong);
+
+ inStr << theStr;
+ return inStr;
+}
+
+std::wstring &operator<<(std::wstring &inStr, double inDouble)
+{
+ // wchar_t theStr[ 64 ];
+
+ //#ifdef _WIN32
+ // ::swprintf( theStr, L"%g", inDouble );
+ //#else
+ // ::swprintf( theStr, 32, L"%g", inDouble ) );
+ //#endif
+ // this should work across platforms
+ //::swprintf( theStr, 64, L"%g", inDouble );
+
+ char theStr[64];
+ sprintf(theStr, "%g", inDouble);
+
+ inStr << theStr;
+ return inStr;
+}
+
+std::wstring &operator<<(std::wstring &inStr, const char *inStr02)
+{
+ if (inStr02) {
+ CConvertStr<char, wchar_t> theConvert;
+ inStr += theConvert(inStr02);
+ }
+ return inStr;
+}
+
+std::wstring &operator<<(std::wstring &inStr, const wchar_t *inStr02)
+{
+ if (inStr02) {
+ inStr += inStr02;
+ }
+ return inStr;
+}
+
+std::wstring &operator<<(std::wstring &inStr, const std::string &inStr02)
+{
+ CConvertStr<char, wchar_t> theConvert;
+ inStr += theConvert(inStr02);
+ return inStr;
+}
+
+std::wstring &operator<<(std::wstring &inStr, const std::wstring &inStr02)
+{
+ inStr += inStr02;
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, bool inBool)
+{
+ char theStr[32];
+ ::sprintf(theStr, "%s", inBool ? "true" : "false");
+ inStr += theStr;
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, long inLong)
+{
+ char theStr[32];
+ ::sprintf(theStr, "%ld", inLong);
+ inStr += theStr;
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, double inDouble)
+{
+ char theStr[32];
+ ::sprintf(theStr, "%g", inDouble);
+ inStr += theStr;
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, const char *inStr02)
+{
+ if (inStr02) {
+ inStr += inStr02;
+ }
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, const wchar_t *inStr02)
+{
+ if (inStr02) {
+ CConvertStr<wchar_t, char> theConvert;
+ inStr += theConvert(inStr02);
+ }
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, const std::string &inStr02)
+{
+ inStr += inStr02;
+ return inStr;
+}
+
+std::string &operator<<(std::string &inStr, const std::wstring &inStr02)
+{
+ CConvertStr<wchar_t, char> theConvert;
+ inStr += theConvert(inStr02);
+ return inStr;
+}
diff --git a/src/Authoring/Common/Code/StrUtilities.h b/src/Authoring/Common/Code/StrUtilities.h
new file mode 100644
index 00000000..c56d4b25
--- /dev/null
+++ b/src/Authoring/Common/Code/StrUtilities.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefixes
+//==============================================================================
+#ifndef STRUTILITIES_H
+#define STRUTILITIES_H
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <string>
+#include <ctype.h>
+#include <stddef.h>
+
+//==============================================================================
+// String Conversion Functions
+//==============================================================================
+//==============================================================================
+/**
+ * @functions bunch of stream ins to facilitate putting various different
+ * types into std::string and std::wstring
+ *
+ */
+std::wstring &operator<<(std::wstring &inStr, bool inBool);
+std::wstring &operator<<(std::wstring &inStr, long inLong);
+std::wstring &operator<<(std::wstring &inStr, double inDouble);
+std::wstring &operator<<(std::wstring &inStr, const char *inStr02);
+std::wstring &operator<<(std::wstring &inStr, const wchar_t *inStr02);
+std::wstring &operator<<(std::wstring &inStr, const std::string &inStr02);
+std::wstring &operator<<(std::wstring &inStr, const std::wstring &inStr02);
+
+std::string &operator<<(std::string &inStr, bool inBool);
+std::string &operator<<(std::string &inStr, long inLong);
+std::string &operator<<(std::string &inStr, double inDouble);
+std::string &operator<<(std::string &inStr, const char *inStr02);
+std::string &operator<<(std::string &inStr, const wchar_t *inStr02);
+std::string &operator<<(std::string &inStr, const std::string &inStr02);
+std::string &operator<<(std::string &inStr, const std::wstring &inStr02);
+
+//==============================================================================
+/**
+ * Compares 2 strings in a case-insensitive way.
+ * operator== should be reserved for case sensitive compare,
+ * so this leaves us with this ugly function name to use.
+ *
+ * @param inString1 The first string to be compared
+ * @param inString2 The second string to be compared
+ *
+ * @return Returns true if both strings are equal, false otherwise
+ */
+template <class T, class U>
+bool CaseInsensitiveEqual(const std::basic_string<T> &inString1,
+ const std::basic_string<U> &inString2)
+{
+ bool theResult = true;
+
+ typename std::basic_string<T>::const_iterator theIterator1 = inString1.begin();
+ typename std::basic_string<U>::const_iterator theIterator2 = inString2.begin();
+
+ while (theIterator1 != inString1.end() && theIterator2 != inString2.end()) {
+ if (toupper(*theIterator1++) != toupper(*theIterator2++)) {
+ theResult = false;
+ theIterator1 = inString1.end(); // break
+ }
+ }
+
+ if (theIterator1 != inString1.end() || theIterator2 != inString2.end()) {
+ theResult = false;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Converts a string to upper-case.
+ *
+ * @param ioString The string
+ *
+ */
+template <class T>
+void ToUpperCase(std::basic_string<T> &ioString)
+{
+ typename std::basic_string<T>::iterator theIterator;
+ for (theIterator = ioString.begin(); theIterator != ioString.end(); ++theIterator) {
+ *theIterator = static_cast<T>(toupper(*theIterator));
+ }
+}
+
+//==============================================================================
+/**
+ * Finds a string in a case-insensitive way.
+ *
+ * @param inString1 The source string
+ * @param inString2 The string to find
+ *
+ * @return Returns the pos in inString1 where inString2 is found, npos if not found.
+ */
+template <class T, class U>
+size_t CaseInsensitiveFind(const std::basic_string<T> &inString1,
+ const std::basic_string<U> &inString2)
+{
+ size_t theResult = std::basic_string<T>::npos;
+
+ std::basic_string<T> theString1(inString1);
+ std::basic_string<T> theString2;
+ theString2 << inString2;
+
+ // convert both to upper-case
+ ToUpperCase<T>(theString1);
+ ToUpperCase<T>(theString2);
+
+ theResult = theString1.find(theString2);
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Returns the actual path of the string.
+ *
+ * @param inString the string to extract the path
+ * @param outString the string to gett the path
+ *
+ * @return the path, if there is one, '.' otherwise.
+ */
+template <class T, class U>
+void GetActualPath(const std::basic_string<T> &inString, std::basic_string<U> &outString)
+{
+ outString.clear();
+
+ size_t thePos = inString.find_last_of("/\\");
+ if (thePos != std::string::npos) {
+ for (std::string::const_iterator theIter = inString.begin();
+ theIter != inString.begin() + thePos; ++theIter) {
+ outString.push_back(*theIter);
+ }
+ } else {
+ outString.push_back('.');
+ }
+}
+
+//==============================================================================
+/**
+ * Search for tokens and replace them.
+ *
+ * @param inToBeReplaced the tokens to be replaced
+ * @param inToBeReplacedBy the tokens to be replaced with
+ * @param outString the string to be operated on
+ *
+ */
+template <class T>
+void ReplaceString(const std::basic_string<T> &inToBeReplaced,
+ const std::basic_string<T> &inToBeReplacedBy, std::basic_string<T> &outString)
+{
+ size_t thePos = outString.find_first_of(inToBeReplaced);
+ while (thePos != std::basic_string<T>::npos) {
+ outString.replace(outString.begin() + thePos, outString.begin() + thePos + 1,
+ inToBeReplacedBy.begin(), inToBeReplacedBy.end());
+ thePos = outString.find_first_of(inToBeReplaced, thePos);
+ }
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/StringTokenizer.cpp b/src/Authoring/Common/Code/StringTokenizer.cpp
new file mode 100644
index 00000000..a3b9520f
--- /dev/null
+++ b/src/Authoring/Common/Code/StringTokenizer.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StringTokenizer.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+ * formats inString so it is a correct delimited string using inToken
+ * @param inToken the token that delimets the string
+ * @param inString theString containing the delimited items yo
+ */
+CStringTokenizer::CStringTokenizer(Q3DStudio::CString inString, Q3DStudio::CString inToken)
+{
+ // If the first of the string is a token extract it off until there is no token at the first of
+ // the string
+ Q3DStudio::CString theTempString = inString.Extract(0, inToken.Length());
+ while (inToken.Length() && theTempString == inToken) {
+ inString = inString.Extract(inToken.Length());
+ theTempString = inString.Extract(0, inToken.Length());
+ }
+
+ // Do the same thing for the end part of the string
+ theTempString = inString.Extract(inString.Length() - 1 - inToken.Length());
+ while (theTempString == inToken) {
+ inString = inString.Extract(0, inString.Length() - inToken.Length());
+ theTempString = inString.Extract(inString.Length() - 1 - inToken.Length());
+ }
+
+ m_OriginalString = inString;
+ m_Token = inToken;
+ m_Index = 0;
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+CStringTokenizer::~CStringTokenizer()
+{
+}
+
+void CStringTokenizer::operator++()
+{
+ if (m_Index != Q3DStudio::CString::ENDOFSTRING) {
+ long theCurrentTokenIndex = m_OriginalString.Find(m_Token, m_Index);
+
+ // Case last partition after last token
+ if (theCurrentTokenIndex == Q3DStudio::CString::ENDOFSTRING) {
+ m_Index = Q3DStudio::CString::ENDOFSTRING;
+ }
+ // Somewhere in the middle or beginnign for the string
+ else {
+ m_Index = theCurrentTokenIndex + m_Token.Length();
+ if (m_Index > m_OriginalString.Length())
+ m_Index = Q3DStudio::CString::ENDOFSTRING;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Gets the next delimeted partition
+ */
+Q3DStudio::CString CStringTokenizer::GetCurrentPartition()
+{
+ Q3DStudio::CString theReturnString = "";
+ if (m_Index != Q3DStudio::CString::ENDOFSTRING) {
+ long theCurrentTokenIndex = m_OriginalString.Find(m_Token, m_Index);
+
+ // Case last partition after last token
+ if (theCurrentTokenIndex == Q3DStudio::CString::ENDOFSTRING) {
+ theReturnString = m_OriginalString.Extract(m_Index);
+ }
+ // Somewhere in the middle or beginnign for the string
+ else {
+ theReturnString = m_OriginalString.Extract(m_Index, theCurrentTokenIndex - m_Index);
+ }
+ }
+ return theReturnString;
+}
+
+//==============================================================================
+/**
+ * return true if there is more data to be extracted
+ */
+bool CStringTokenizer::HasNextPartition()
+{
+ return (m_Index != Q3DStudio::CString::ENDOFSTRING);
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/StringTokenizer.h b/src/Authoring/Common/Code/StringTokenizer.h
new file mode 100644
index 00000000..a71a814b
--- /dev/null
+++ b/src/Authoring/Common/Code/StringTokenizer.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STRINGTOKENIZER_H_
+#define INCLUDED_STRINGTOKENIZER_H_ 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CStringTokenizer seperates a string out using a token;
+ */
+class CStringTokenizer
+{
+public:
+ CStringTokenizer(Q3DStudio::CString inString, Q3DStudio::CString inToken);
+ ~CStringTokenizer();
+
+ Q3DStudio::CString GetCurrentPartition();
+ bool HasNextPartition();
+
+ void operator++();
+
+protected:
+ long m_Index;
+ Q3DStudio::CString m_Token;
+ Q3DStudio::CString m_OriginalString;
+};
+
+#endif // INCLUDED_STRINGTOKENIZER_H_ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Thread/Conditional.h b/src/Authoring/Common/Code/Thread/Conditional.h
new file mode 100644
index 00000000..9afed01e
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Conditional.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CONDITIONAL_H
+#define INCLUDED_CONDITIONAL_H
+
+#pragma once
+
+#include "ThreadException.h"
+
+#include <QMutex>
+#include <QWaitCondition>
+
+class CConditional
+{
+public:
+ CConditional();
+ ~CConditional();
+
+ void Wait();
+ bool Wait(unsigned long inTimeout);
+ void Notify();
+
+ static const unsigned long WAITINFINITE = ULONG_MAX;
+
+private:
+ CConditional(const CConditional &inConditional);
+ CConditional &operator=(const CConditional &inConditional);
+
+ QWaitCondition* m_Event;
+};
+
+//=============================================================================
+/**
+ * Create a new conditional.
+ * This will wait for the Mutex to become available then lock it when
+ * it becomes avaialable.
+ */
+inline CConditional::CConditional()
+{
+ m_Event = new QWaitCondition;
+}
+
+inline CConditional::~CConditional()
+{
+ delete m_Event;
+}
+
+//=============================================================================
+/**
+ * Wait for this conditional event to occur.
+ * The mutex should be locked entering this function and will be locked on
+ * exit. The thread is blocked until Notify is called by another thread. This
+ * is most commonly used for queues that need to block if no data is available.
+ * Intended useage:
+ * <code>
+ * mutex.Lock( );
+ * while( [condition] )
+ * conditional.Wait( mutex );
+ * [process condition]
+ * </code>
+ */
+inline void CConditional::Wait()
+{
+ QMutex m;
+ m.lock();
+ m_Event->wait(&m, WAITINFINITE);
+ m.unlock();
+}
+
+//=============================================================================
+/**
+ * Put the thread to sleep for inTimeout or until notified.
+ * This is used to provide interuptable sleeps.
+ * @param inTimeout the timeout for the wait, in milliseconds.
+ * @return true if the wait succeeded, false if timeout.
+ */
+inline bool CConditional::Wait(unsigned long inTimeout)
+{
+ QMutex m;
+ m.lock();
+ const bool result = m_Event->wait(&m, inTimeout);
+ m.unlock();
+ return result;
+}
+
+//=============================================================================
+/**
+ * Notify any threads waiting for this condition that it has occurred.
+ */
+inline void CConditional::Notify()
+{
+ m_Event->wakeAll();
+}
+#endif // INCLUDED_CONDITIONAL_H
diff --git a/src/Authoring/Common/Code/Thread/Guard.h b/src/Authoring/Common/Code/Thread/Guard.h
new file mode 100644
index 00000000..0b040de4
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Guard.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_GUARD_H
+#define INCLUDED_GUARD_H
+
+#pragma once
+
+#include "Mutex.h"
+class CGuard
+{
+public:
+ CGuard(CMutex *inMutex, bool inLockNow = true);
+ CGuard(CMutex &inMutex, bool inLockNow = true);
+ ~CGuard();
+
+ bool Lock();
+ void Unlock();
+
+private:
+ CGuard();
+ CMutex *m_Mutex;
+ long m_LockCount;
+};
+
+//=============================================================================
+/**
+ * Constructor, simple Mutex Guard creation.
+ * This will just lock the mutex on creation and unlock it on destruction.
+ */
+inline CGuard::CGuard(CMutex *inMutex, bool inLockNow)
+ : m_LockCount(0)
+{
+ m_Mutex = inMutex;
+
+ if (inLockNow)
+ Lock();
+}
+
+inline CGuard::CGuard(CMutex &inMutex, bool inLockNow)
+ : m_LockCount(0)
+{
+ m_Mutex = &inMutex;
+
+ if (inLockNow)
+ Lock();
+}
+
+inline CGuard::~CGuard()
+{
+ Unlock();
+}
+
+inline bool CGuard::Lock()
+{
+
+ m_Mutex->Lock();
+
+ m_LockCount++;
+
+ // Should return true if the lock was acquired
+ return true;
+}
+
+inline void CGuard::Unlock()
+{
+ if (m_LockCount > 0) {
+ m_LockCount--;
+ m_Mutex->Unlock();
+ }
+}
+
+#endif // INCLUDED_GUARD_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Thread/Mutex.cpp b/src/Authoring/Common/Code/Thread/Mutex.cpp
new file mode 100644
index 00000000..1130c5a9
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Mutex.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "Mutex.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//=============================================================================
+/** THIS IS BAD DUE TO CLOSING THE MUTEX ON DESTROY
+ */
+CMutex::CMutex(const CMutex &inMutex)
+{
+ m_Mutex = inMutex.m_Mutex;
+}
+
+//=============================================================================
+/** THIS IS BAD DUE TO CLOSING THE MUTEX ON DESTROY
+ */
+CMutex &CMutex::operator=(const CMutex &inMutex)
+{
+ if (&inMutex == this)
+ return *this;
+ m_Mutex = inMutex.m_Mutex;
+ return *this;
+}
+#endif
diff --git a/src/Authoring/Common/Code/Thread/Mutex.h b/src/Authoring/Common/Code/Thread/Mutex.h
new file mode 100644
index 00000000..85bfcc85
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Mutex.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MUTEX_H
+#define INCLUDED_MUTEX_H
+
+#pragma once
+
+#include "ThreadException.h"
+
+#include <QMutex>
+
+class CMutex
+{
+ typedef QMutex TMutex;
+
+public:
+ struct Scope
+ {
+ private:
+ Scope(const Scope &inOther);
+ Scope &operator=(const Scope &inOther);
+
+ public:
+ CMutex *m_Mutex;
+ Scope(CMutex *inMutex)
+ : m_Mutex(inMutex)
+ {
+ if (m_Mutex)
+ m_Mutex->Lock();
+ }
+ ~Scope()
+ {
+ if (m_Mutex)
+ m_Mutex->Unlock();
+ }
+ };
+ CMutex();
+ ~CMutex();
+
+ void Lock();
+ void Unlock();
+
+ TMutex *GetMutex();
+
+protected:
+ TMutex m_Mutex;
+
+private:
+ CMutex(const CMutex &inCMutex);
+ CMutex &operator=(const CMutex &inCMutex);
+};
+
+//=============================================================================
+/**
+ * Constructor for a new CMutex.
+ */
+inline CMutex::CMutex()
+ : m_Mutex(QMutex::Recursive)
+{
+}
+
+inline CMutex::~CMutex()
+{
+}
+
+//=============================================================================
+/**
+ * Lock this mutex.
+ */
+inline void CMutex::Lock()
+{
+ m_Mutex.lock();
+}
+
+//=============================================================================
+/**
+ * Unlock this mutex.
+ */
+inline void CMutex::Unlock()
+{
+ m_Mutex.unlock();
+}
+
+//=============================================================================
+/**
+ * Get the underlying platform object this is operating on.
+ */
+inline CMutex::TMutex *CMutex::GetMutex()
+{
+ return &m_Mutex;
+}
+#endif // INCLUDED_MUTEX_H
diff --git a/src/Authoring/Common/Code/Thread/Runnable.h b/src/Authoring/Common/Code/Thread/Runnable.h
new file mode 100644
index 00000000..a2b36046
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Runnable.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_RUNNABLE_H
+#define INCLUDED_RUNNABLE_H
+#pragma once
+
+//==============================================================================
+/**
+ * @class CRunnable
+ * @brief Abstract class providing an entry point for threads.
+ */
+class CRunnable
+{
+public:
+ virtual void Run(void *inParams) = 0;
+};
+#endif // INCLUDED_RUNNABLE_H \ No newline at end of file
diff --git a/src/Authoring/Common/Code/Thread/Thread.cpp b/src/Authoring/Common/Code/Thread/Thread.cpp
new file mode 100644
index 00000000..2c0e1b8f
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Thread.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "Thread.h"
+#include "ThreadException.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+class FunctionThread : public QThread
+{
+public:
+ FunctionThread(unsigned long (*function)(void* param), void* param)
+ : m_function(function),
+ m_param(param)
+ {
+ }
+
+protected:
+ void run() override
+ {
+ m_function(m_param);
+ }
+
+private:
+ unsigned long (*m_function)(void* param);
+ void* m_param;
+};
+
+//=============================================================================
+/**
+ * Windows thread entry.
+ */
+unsigned long ThreadRun(void *args)
+{
+ try {
+ CThread *theThread = (CThread *)args;
+ theThread->Run(NULL);
+ if (theThread->IsAutoDelete())
+ delete theThread;
+ return 0;
+ } catch (std::exception &) {
+ return 0xFFFFFFFF;
+ }
+}
+
+//=============================================================================
+/**
+ * Creates a new thread.
+ * @param inRunnable the class to be run.
+ * @param inArgs the arguments for the class to be run.
+ * @param inStartImmediately true if this is supposed to be started immediately.
+ */
+CThread::CThread(CRunnable *inRunnable, const Q3DStudio::CString &inThreadName, void *inArgs,
+ bool inStartImmediately)
+ : m_Thread(nullptr)
+ , m_Runnable(inRunnable)
+ , m_IsActive(false)
+ , m_DeleteOnDeath(false)
+ , m_Args(inArgs)
+ , m_ThreadID(0)
+ , m_ThreadName(inThreadName)
+{
+ if (inStartImmediately)
+ Start();
+}
+
+//=============================================================================
+/**
+ * Destructor, nothing special.
+ */
+CThread::~CThread()
+{
+ if (m_Thread != nullptr) {
+ delete m_Thread;
+ m_Thread = nullptr;
+ }
+ m_ThreadID = 0;
+}
+
+//=============================================================================
+/**
+ * If this is not started immediately (see constructor) then this will start the thread.
+ */
+unsigned long CThread::Start()
+{
+ // SDJ 2/15/2005 User Story
+ // Convert this to beginthreadex to prevent memory leaks from the c runtimes
+
+ m_Thread = new FunctionThread(&ThreadRun, this);
+ m_Thread->setObjectName(m_ThreadName.toQString());
+ m_Thread->start();
+
+ return m_ThreadID;
+}
+
+//=============================================================================
+/**
+ * Entry location for the executing thread.
+ * Calling this directly will result in synchronous execution.
+ */
+void CThread::Run(void *inArgs)
+{
+ Q_UNUSED(inArgs);
+
+ m_IsActive = true;
+ m_Runnable->Run(m_Args);
+ m_IsActive = false;
+}
+
+//=============================================================================
+/**
+ * Blocking call until this thread exits.
+ */
+void CThread::Join()
+{
+ // Only do this if run was called!!!
+ if (m_Thread != nullptr) {
+ bool nret = m_Thread->wait();
+ if (nret == false)
+ throw CThreadException("Thread.Join: join failed");
+ }
+}
+
+//=============================================================================
+/**
+ * Check to see if this thread is currently executing.
+ */
+bool CThread::IsActive()
+{
+ return m_IsActive;
+}
+
+//=============================================================================
+/**
+ * Get the platform specific thread descriptor.
+ */
+CThread::TThread CThread::GetThread()
+{
+ return m_Thread;
+}
+
+//=============================================================================
+/**
+ * Get the unique ID of the specified thread.
+ */
+unsigned long CThread::GetThreadID()
+{
+ return m_ThreadID;
+}
+
+//=============================================================================
+// Static Methods
+//=============================================================================
+
+//=============================================================================
+/**
+ * Cause the currently executing thread to pause for inTime.
+ * @param inTime the amount to pause for, in milliseconds.
+ */
+void CThread::Sleep(unsigned long inTime)
+{
+ QThread::msleep(inTime);
+}
+
+//=============================================================================
+/**
+ * Return the thread handle for the currently executing thread.
+ */
+CThread::TThread CThread::GetCurrentThread()
+{
+ return QThread::currentThread();
+}
+
+//=============================================================================
+/**
+ * Gets the unique ID of the current thread.
+ */
+unsigned long CThread::GetCurrentThreadID()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ return QThread::currentThreadId();
+#endif
+ return {};
+}
+
+//=============================================================================
+/**
+ * Gets the number of milliseconds spent in the current thread.
+ * This does not include sleeping or being interrupted by other threads.
+ * @note Only the Win32 portion is implemented and is only accurate to 10ms.
+ * @return CPU time spent in the thread in ms
+ */
+long CThread::GetUserTime()
+{
+ long theTime = 0;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ unsigned __int64 theBigUser;
+ unsigned __int64 theBigKernel;
+ FILETIME theStart;
+ FILETIME theStop;
+ FILETIME theKernel;
+ FILETIME theUser;
+ BOOL theOK;
+
+ // Win32 call to get the usertime
+ theOK = ::GetThreadTimes(::GetCurrentThread(), &theStart, &theStop, &theKernel, &theUser);
+
+ // Convert from FILETIME to 64bit integer
+ theBigUser = theUser.dwHighDateTime;
+ theBigUser <<= 32;
+ theBigUser |= theUser.dwLowDateTime;
+
+ theBigKernel = theKernel.dwHighDateTime;
+ theBigKernel <<= 32;
+ theBigKernel |= theKernel.dwLowDateTime;
+
+ // Convert from 100ns units to 1ms units
+ theTime = static_cast<long>((theBigUser + theBigKernel) / 10000);
+#endif
+
+ return theTime;
+}
diff --git a/src/Authoring/Common/Code/Thread/Thread.h b/src/Authoring/Common/Code/Thread/Thread.h
new file mode 100644
index 00000000..4cc578ec
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/Thread.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_THREAD_H
+#define INCLUDED_THREAD_H
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Runnable.h"
+#include "UICString.h"
+
+//==============================================================================
+// Platform dependent includes
+//==============================================================================
+#include <QThread>
+
+//==============================================================================
+/**
+ * @class CThread
+ * @brief Cross platform abstraction and implementation of threads.
+ */
+class CThread : public CRunnable
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef QThread* TThread; // Windows uses HANDLE
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ TThread m_Thread; ///< Platform dependent representation of thread
+ CRunnable *m_Runnable;
+ bool m_IsActive;
+ bool m_DeleteOnDeath;
+ void *m_Args;
+ unsigned long m_ThreadID;
+ Q3DStudio::CString m_ThreadName;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+protected: // Protected constructors
+ CThread(TThread &inThreadDesc);
+ CThread();
+ CThread(const CThread &inThread);
+
+public: // Construction
+ CThread(CRunnable *inRunnable, const Q3DStudio::CString &inThreadName, void *inArgs = NULL,
+ bool inStartImmediately = true);
+ virtual ~CThread();
+
+ void Run(void *inArgs = NULL) override;
+
+ unsigned long Start();
+ void Join();
+
+ bool IsActive();
+ bool IsAutoDelete() { return m_DeleteOnDeath; }
+ void SetAutoDelete(bool inAutoDelete) { m_DeleteOnDeath = inAutoDelete; }
+
+ TThread GetThread();
+ unsigned long GetThreadID();
+
+ //==============================================================================
+ // Statics
+ //==============================================================================
+public:
+ static void Sleep(unsigned long inTime);
+ static TThread GetCurrentThread();
+ static unsigned long GetCurrentThreadID();
+ static long GetUserTime();
+};
+#endif // __THREAD_H_
diff --git a/src/Authoring/Common/Code/Thread/ThreadException.h b/src/Authoring/Common/Code/Thread/ThreadException.h
new file mode 100644
index 00000000..44fc838f
--- /dev/null
+++ b/src/Authoring/Common/Code/Thread/ThreadException.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_THREAD_EXCEPTION_H
+#define INCLUDED_THREAD_EXCEPTION_H 1
+
+#pragma once
+
+#include "StudioException.h"
+#include "UICString.h"
+
+class CThreadException : public CStudioException
+{
+public:
+ CThreadException(Q3DStudio::CString inWhat) { m_What = inWhat; }
+
+ virtual ~CThreadException() {}
+
+ const wchar_t *GetDescription() const override { return m_What; }
+protected:
+ Q3DStudio::CString m_What;
+};
+#endif // INCLUDED_THREAD_EXCEPTION_H
diff --git a/src/Authoring/Common/Code/UICAtomic.cpp b/src/Authoring/Common/Code/UICAtomic.cpp
new file mode 100644
index 00000000..e39adeb2
--- /dev/null
+++ b/src/Authoring/Common/Code/UICAtomic.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#include "UICSynch.h"
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__I386__))
+#define GCC_i386
+#elif defined(_MSC_VER) && (defined(_M_IX86) && !defined(_AMD64_))
+#define MSC_i386
+#elif defined(_MSC_VER) && defined(_AMD64_)
+#define MSC_i686
+#elif defined(__BORLANDC__) && defined(_M_IX86)
+#define BCC_i386
+#endif
+
+#if defined(MSC_i386) || defined(BCC_i386)
+
+//
+// atomic operations for Microsoft C or Borland C on Windows
+//
+
+#if defined(_MSC_VER)
+#pragma warning(disable : 4035)
+#elif defined(__BORLANDC__)
+#pragma warn - rvl
+#endif
+
+// !!! NOTE
+// the following functions implement atomic exchange/inc/dec on
+// windows. they are dangerous in that they rely on the calling
+// conventions of MSVC and BCC. the first one passes the first
+// two arguments in ECX and EDX, and the second one - in EAX and
+// EDX.
+
+long __PFASTCALL pincrement(long *)
+{
+ __asm
+ {
+#ifdef BCC_i386
+.486
+ mov ecx,eax
+#endif
+ mov eax,1;
+ lock xadd [ecx],eax;
+ inc eax
+ }
+}
+
+long __PFASTCALL pdecrement(long *)
+{
+ __asm
+ {
+#ifdef BCC_i386
+.486
+ mov ecx,eax
+#endif
+ mov eax,-1;
+ lock xadd [ecx],eax;
+ dec eax
+ }
+}
+
+long __PFASTCALL pexchange(long *, long)
+{
+ __asm
+ {
+#ifdef BCC_i386
+.486
+ xchg eax,edx;
+ lock xchg eax,[edx];
+#else
+ mov eax,edx;
+ lock xchg eax,[ecx];
+#endif
+ }
+}
+
+void *__PFASTCALL pexchange(void **, void *)
+{
+ __asm
+ {
+#ifdef BCC_i386
+.486
+ xchg eax,edx;
+ lock xchg eax,[edx];
+#else
+ mov eax,edx;
+ lock xchg eax,[ecx];
+#endif
+ }
+}
+
+#elif defined(GCC_i386)
+
+//
+// GNU C compiler on any i386 platform (actually 486+ for xadd)
+//
+
+long pexchange(long *target, long value)
+{
+ __asm__ __volatile("lock ; xchgl (%1),%0" : "+r"(value) : "r"(target));
+ return value;
+}
+
+void *pexchange(void **target, void *value)
+{
+ __asm__ __volatile("lock ; xchgl (%1),%0" : "+r"(value) : "r"(target));
+ return value;
+}
+
+long pincrement(long *target)
+{
+ int temp = 1;
+ __asm__ __volatile("lock ; xaddl %0,(%1)" : "+r"(temp) : "r"(target));
+ return temp + 1;
+}
+
+long pdecrement(long *target)
+{
+ long temp = -1;
+ __asm__ __volatile("lock ; xaddl %0,(%1)" : "+r"(temp) : "r"(target));
+ return temp - 1;
+}
+
+#elif defined(MSC_i686)
+
+long __PFASTCALL pincrement(long *target)
+{
+ mutex mtx;
+ mtx.enter();
+ long r = ++(*target);
+ mtx.leave();
+ return r;
+}
+
+long __PFASTCALL pdecrement(long *target)
+{
+ mutex mtx;
+ mtx.enter();
+ long r = --(*target);
+ mtx.leave();
+ return r;
+}
+
+long pexchange(long *target, long value)
+{
+ mutex mtx;
+ mtx.enter();
+ long r = *target;
+ *target = value;
+ mtx.leave();
+ return r;
+}
+
+void *pexchange(void **target, void *value)
+{
+ mutex mtx;
+ mtx.enter();
+ void *r = *target;
+ *target = value;
+ mtx.leave();
+ return r;
+}
+
+#else
+
+//
+// other platforms: mutex locking
+//
+
+// we use a prime number for hashing
+const long MUTEX_HASH_SIZE = 17;
+
+#define MTX_INIT PTHREAD_MUTEX_INITIALIZER
+#define mtx_t pthread_mutex_t
+#define mtx_lock pthread_mutex_lock
+#define mtx_unlock pthread_mutex_unlock
+
+static mtx_t mutextbl[MUTEX_HASH_SIZE] = { MTX_INIT, MTX_INIT, MTX_INIT, MTX_INIT, MTX_INIT,
+ MTX_INIT, MTX_INIT, MTX_INIT, MTX_INIT, MTX_INIT,
+ MTX_INIT, MTX_INIT, MTX_INIT, MTX_INIT, MTX_INIT,
+ MTX_INIT, MTX_INIT };
+
+inline mtx_t *pgetmemlock(void *addr)
+{
+ return mutextbl + quint64(addr) % MUTEX_HASH_SIZE;
+}
+
+long pexchange(long *target, long value)
+{
+ mtx_t *m = pgetmemlock(target);
+ mtx_lock(m);
+ long r = *target;
+ *target = value;
+ mtx_unlock(m);
+ return r;
+}
+
+void *pexchange(void **target, void *value)
+{
+ mtx_t *m = pgetmemlock(target);
+ mtx_lock(m);
+ void *r = *target;
+ *target = value;
+ mtx_unlock(m);
+ return r;
+}
+
+long pincrement(long *target)
+{
+ mtx_t *m = pgetmemlock(target);
+ mtx_lock(m);
+ long r = ++(*target);
+ mtx_unlock(m);
+ return r;
+}
+
+long pdecrement(long *target)
+{
+ mtx_t *m = pgetmemlock(target);
+ mtx_lock(m);
+ long r = --(*target);
+ mtx_unlock(m);
+ return r;
+}
+
+#endif
diff --git a/src/Authoring/Common/Code/UICDESKey.h b/src/Authoring/Common/Code/UICDESKey.h
new file mode 100644
index 00000000..8cb7948f
--- /dev/null
+++ b/src/Authoring/Common/Code/UICDESKey.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2000 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+static __int64 g_DESKey(0xA9A425381A1EF126);
diff --git a/src/Authoring/Common/Code/UICFile.h b/src/Authoring/Common/Code/UICFile.h
new file mode 100644
index 00000000..7ad8d9c5
--- /dev/null
+++ b/src/Authoring/Common/Code/UICFile.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_UIC_FILE_H
+#define INCLUDED_UIC_FILE_H 1
+
+#pragma once
+
+#include "UICString.h"
+
+#include <set>
+#include "UICString.h"
+#include "FileIterator.h"
+#include "PlatformTypes.h"
+
+//=========================================================================================
+// Typedefs
+//=========================================================================================
+typedef std::set<Q3DStudio::CString> TFilePathList;
+typedef TFilePathList::iterator TFilePathListIterator;
+
+class CUICFile
+{
+
+public:
+ typedef void OSErr; // this may be better typedefed to HRESULT
+
+ static const Q3DStudio::CString CURRENT_DIR;
+ static const Q3DStudio::CString PARENT_DIR;
+
+ CUICFile(const Q3DStudio::CString &inPathName, bool inIsPosix = false, bool inAddBase = true);
+ CUICFile(const Q3DStudio::CString &inPathName, const Q3DStudio::CString &inName);
+ CUICFile(const CUICFile &inBasePath, const Q3DStudio::CString &inPathname,
+ bool inIsPosix = false);
+ CUICFile(const CUICFile &inFile);
+
+ CFileIterator GetSubItems() const;
+
+ ~CUICFile();
+
+ bool operator==(const CUICFile &inRHS) const;
+
+ bool CanRead() const;
+ bool CanWrite() const;
+ bool DeleteFile() const;
+ bool Exists() const;
+
+ Q3DStudio::CString GetAbsolutePath() const;
+ Q3DStudio::CString GetAbsolutePosixPath() const;
+
+ Q3DStudio::CString GetName() const;
+ Q3DStudio::CString GetExtension() const;
+ Q3DStudio::CString GetPath() const;
+
+ bool IsFile(bool inCheckForAlias = true) const;
+ bool IsHidden() const;
+ long Length() const;
+
+ OSErr MoveTo(const CUICFile &inDestination);
+ void CopyTo(const CUICFile &inDestination);
+
+ void Execute() const;
+
+ OSErr SetReadOnly(bool inReadOnlyFlag);
+
+ static CUICFile GetApplicationDirectory();
+ static CUICFile GetTemporaryFile(const Q3DStudio::CString &inExtension);
+ static CUICFile GetTemporaryFile();
+ static bool IsPathRelative(const Q3DStudio::CString &inPath);
+
+ QUrl GetURL() const;
+
+ static CUICFile Combine(const CUICFile &inFile, const Q3DStudio::CString &inRelPath);
+ HANDLE OpenFileReadHandle() const;
+ HANDLE OpenFileWriteHandle() const;
+ void RenameTo(const CUICFile &inDestination);
+ bool GetFileStat(struct _stat *inStat) const;
+
+ static void ClearCurrentTempCache();
+
+ static void AddTempFile(const Q3DStudio::CString &inFile);
+
+ // protected functions
+protected:
+ static TFilePathList s_TempFilePathList; ///< List of temporary files that gets created; this
+ ///should be cleared at end of program execution by
+ ///calling ClearTempCache
+ Q3DStudio::CString m_Path;
+};
+
+#endif // INCLUDED_UIC_FILE_H
diff --git a/src/Authoring/Common/Code/UICFileToolTypes.h b/src/Authoring/Common/Code/UICFileToolTypes.h
new file mode 100644
index 00000000..352bee25
--- /dev/null
+++ b/src/Authoring/Common/Code/UICFileToolTypes.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#pragma once
+#ifndef INCLUDED_UICFILETOOL_ENUMS_H
+#define INCLUDED_UICFILETOOL_ENUMS_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/IOStreams.h"
+
+namespace Q3DStudio {
+
+struct FileInfoFlagValues
+{
+ enum Enum {
+ Exists = 1,
+ IsDirectory = 1 << 1,
+ CanRead = 1 << 2,
+ CanWrite = 1 << 3,
+ IsHidden = 1 << 4,
+ };
+};
+
+using qt3ds::NVFlags;
+using qt3ds::QT3DSU32;
+using qt3ds::QT3DSU64;
+struct SFileInfoFlags : public NVFlags<FileInfoFlagValues::Enum, int>
+{
+ SFileInfoFlags(int value = 0)
+ : NVFlags(value)
+ {
+ }
+
+ bool Exists() const { return *this & FileInfoFlagValues::Exists; }
+ bool IsDirectory() const { return Exists() && (*this & FileInfoFlagValues::IsDirectory); }
+ bool IsFile() const
+ {
+ return Exists() && (QT3DSU32)((*this & FileInfoFlagValues::IsDirectory)) == 0;
+ }
+ bool CanRead() const { return Exists() && (*this & FileInfoFlagValues::CanRead); }
+ bool CanWrite() const { return Exists() && (*this & FileInfoFlagValues::CanWrite); }
+ bool IsHidden() const { return Exists() && (*this & FileInfoFlagValues::IsHidden); }
+};
+
+struct SFileData
+{
+ QT3DSU64 m_Length;
+ QT3DSU64 m_LastModTime;
+ QT3DSU64 m_CreateTime;
+ SFileData()
+ : m_Length(0)
+ , m_LastModTime(0)
+ , m_CreateTime(0)
+ {
+ }
+ SFileData(QT3DSU64 len, QT3DSU64 lastMod, QT3DSU64 create)
+ : m_Length(len)
+ , m_LastModTime(lastMod)
+ , m_CreateTime(create)
+ {
+ }
+};
+
+struct FileModificationType
+{
+ enum Enum {
+ Unknown = 0,
+ Created,
+ Modified, // file data changed
+ InfoChanged, // file info changed
+ Destroyed,
+ NoChange,
+ };
+};
+
+struct FileErrorCodes
+{
+ enum Enum {
+ NoError,
+ SourceNotExist,
+ SourceNotReadable,
+ DestNotWriteable,
+ };
+};
+}
+#endif
diff --git a/src/Authoring/Common/Code/UICFileTools.cpp b/src/Authoring/Common/Code/UICFileTools.cpp
new file mode 100644
index 00000000..9c47714d
--- /dev/null
+++ b/src/Authoring/Common/Code/UICFileTools.cpp
@@ -0,0 +1,1167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include <string>
+#include "UICFileTools.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "UICDMWStrOpsImpl.h"
+#include "foundation/Qt3DSMath.h"
+
+#include <QDateTime>
+#include <QDir>
+#include <QDirIterator>
+#include <QStandardPaths>
+#include <QCoreApplication>
+
+// #ifndef __ATLMISC_H__
+using qt3ds::NVMax;
+using qt3ds::QT3DSU8;
+
+namespace {
+const Q3DStudio::CString updirSearch = L"\\..\\";
+const Q3DStudio::CString curdirSearch = L"\\.\\";
+#ifdef _WIN32
+const Q3DStudio::CString updir = L"..\\";
+const Q3DStudio::CString curdir = L".\\";
+const wchar_t pathSep = '\\';
+const Q3DStudio::CString pathSepStr = L"\\";
+#else
+const Q3DStudio::CString updir = L"../";
+const Q3DStudio::CString curdir = L"./";
+const wchar_t pathSep = '/';
+const Q3DStudio::CString pathSepStr = L"/";
+#endif
+const Q3DStudio::CString UNCPathSepStr = L"\\\\";
+#ifdef _WIN32
+const wchar_t alternateSep = '/';
+#else
+const wchar_t alternateSep = '\\';
+#endif
+const Q3DStudio::CString fileUnsafeChars = L"\\/.:";
+const wchar_t identifierSep = '#';
+const Q3DStudio::CString veryLongPathPrefix = "\\\\?\\";
+
+long FindPreviousPathSep(const Q3DStudio::CString &path)
+{
+ long startOff = Q3DStudio::CString::npos;
+ // If the end of the path is a slash,
+ if (path.Length() && path[path.Length() - 1] == pathSep)
+ startOff = path.Length() - 2;
+ return path.rfind(pathSep, startOff);
+}
+
+bool RecurseCreateDirectory(const Q3DStudio::CFilePath &dirName)
+{
+ return QDir().mkpath(dirName.toQString());
+}
+}
+
+namespace Q3DStudio {
+
+const CString CFilePathTokenizer::s_DirectoryDelimiters = L"\\/";
+
+CFilePath::CFilePath(const CFilePath &str)
+ : CString(str)
+{
+}
+
+const CFilePath &CFilePath::operator=(const CFilePath &strSrc)
+{
+ CString::operator=(strSrc);
+ return *this;
+}
+
+void CFilePath::RemoveTrailingBackslash()
+{
+ if (GetAt(Length() - 1) == QDir::separator().toLatin1())
+ Assign(Extract(0, Length() - 1));
+}
+
+void CFilePath::AddTrailingBackslash()
+{
+ const auto separator = QDir::separator().toLatin1();
+ if (GetAt(Length()) != separator)
+ Concat(separator);
+}
+
+CString CFilePath::GetDrive() const
+{
+#ifdef _WIN32
+ Q3DStudio::CString theReturnString;
+ wchar_t theDrive[_MAX_DRIVE];
+
+ // Remove the file name and extension
+ _wsplitpath(GetPathWithoutIdentifier().c_str(), theDrive, NULL, NULL, NULL);
+
+ theReturnString = theDrive;
+
+ return theReturnString;
+#else
+ return CString();
+#endif
+}
+
+CFilePath CFilePath::GetDirectory() const
+{
+ const CFilePath &path(*this);
+ CFilePath::size_type pos = FindPreviousPathSep(path);
+ if (pos == CFilePath::npos)
+ return L"";
+ if (pos == 1 && path[0] == '.') {
+ if (path.size() > 2)
+ return L".\\";
+ return L"";
+ }
+ return path.substr(0, pos);
+}
+
+CString CFilePath::GetFileStem() const
+{
+ QFileInfo fi(QString::fromWCharArray(GetPathWithoutIdentifier().c_str()));
+ return fi.baseName().toLatin1().data();
+}
+
+CString CFilePath::GetFileName() const
+{
+ CFilePath path(GetPathWithoutIdentifier());
+ CFilePath::size_type pos = FindPreviousPathSep(path);
+ if (pos == CFilePath::npos)
+ return path;
+ return path.substr(pos + 1);
+}
+
+CString DoGetExtension(const CFilePath &inPath)
+{
+ const CFilePath &fullName(inPath);
+ CFilePath::size_type lastSlash = fullName.rfind(pathSep);
+ CFilePath::size_type period = fullName.rfind('.');
+ if (period != CFilePath::npos) {
+ if (lastSlash == CFilePath::npos || period > lastSlash) {
+ if (period != CFilePath::npos)
+ return fullName.substr(period + 1);
+ }
+ }
+ return L"";
+}
+
+CString CFilePath::GetExtension() const
+{
+ return DoGetExtension(GetPathWithoutIdentifier());
+}
+
+CString CFilePath::GetSuffix() const
+{
+ return DoGetExtension(*this);
+}
+
+// Get a file path you can give to systems that don't understand the identifier
+CFilePath CFilePath::GetPathWithoutIdentifier() const
+{
+ long pos = rfind(identifierSep);
+ if (pos != npos)
+ return substr(0, pos);
+ return *this;
+}
+
+// Set the identifer appended to the end of this file path.
+void CFilePath::SetIdentifier(const CString &inIdentifier)
+{
+ CFilePath theCanonicalPath(GetPathWithoutIdentifier());
+ if (inIdentifier.size()) {
+ theCanonicalPath.append(identifierSep);
+ theCanonicalPath.append(inIdentifier);
+ }
+ *this = theCanonicalPath;
+}
+
+// Get the identifier appended to the end of this file path.
+CString CFilePath::GetIdentifier() const
+{
+ long pos = rfind(identifierSep);
+ if (pos != npos)
+ return substr(pos + 1);
+ return Q3DStudio::CString();
+}
+
+unsigned long CFilePath::GetULIdentifier() const
+{
+ CString id(GetIdentifier());
+ if (id.size() == 0)
+ return 0;
+ QT3DSU32 retval;
+ WStrOps<QT3DSU32>().StrTo(id.GetCharStar(), retval);
+ return retval;
+}
+
+void CFilePath::SetIdentifier(unsigned long inIdentifier)
+{
+ QT3DSU32 id(inIdentifier);
+ wchar_t idBuf[16];
+ WStrOps<QT3DSU32>().ToStr(id, qt3ds::foundation::toDataRef(idBuf, 16));
+ SetIdentifier(idBuf);
+}
+
+bool CFilePath::GetTempDirectory()
+{
+ CString path = QDir::tempPath().toLatin1().data();
+ UICAssign(path);
+
+ return TRUE;
+}
+
+bool CFilePath::GetTemporaryFileName(const CString &inPrefix, const CString &inDirectory)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ wchar_t szPath[_MAX_PATH] = L"\0";
+ wchar_t szFile[_MAX_PATH] = L"\0";
+
+ if (inDirectory == NULL)
+ ::GetTempPathW(sizeof(szPath), szPath);
+ else
+ wcscpy(szPath, inDirectory);
+
+ ::GetTempFileNameW(szPath, inPrefix, 0, szFile);
+
+ *this = CString(szFile);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+bool CFilePath::GetModuleFilePath(/*HMODULE inModuleHandle*/)
+{
+ UICAssign(CString::fromQString(qApp->applicationFilePath()));
+ return true;
+}
+
+//==============================================================================
+/**
+* Obtiains the sourcepath of the module who's currently running. For example
+* the code currently exexuting might be within a DLL, but somebody may have
+* loaded that DLL, like Internet Explorer.
+*/
+bool CFilePath::GetContainerModuleFilePath()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TCHAR theModuleFileName[_MAX_PATH];
+
+ ::GetModuleFileName(NULL, theModuleFileName, sizeof(theModuleFileName));
+
+ *this = theModuleFileName;
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+//==============================================================================
+/**
+* Helper function to strip of "file" protocol so that this is just a system file path
+*/
+void CFilePath::EnsureNonFileURL(Q3DStudio::CString &ioFilePath)
+{
+ if (ioFilePath.Find(L"file://") != Q3DStudio::CString::ENDOFSTRING) {
+ ioFilePath.Delete(0, 7); // length of file protocol
+ }
+}
+
+//==============================================================================
+/**
+* Converts the absolute path this string represents into a relative path.
+* An absolute path is required as a base. If conversion is not sucessful, the
+* original absolute path is not changed.
+* @param inBaseAbsolute absolute path to base off from
+* @return bool to indicate successful conversion or not
+*/
+void CFilePath::ConvertToRelative(const CFilePath &inBasePath)
+{
+ if (inBasePath.IsEmpty()) // nothing to make relative to
+ return;
+
+ QT3DS_ASSERT(inBasePath.IsAbsolute());
+ QT3DS_ASSERT(IsAbsolute());
+
+ QDir basePathDir(inBasePath.toQString());
+ QString relPath = basePathDir.relativeFilePath(toQString());
+ *this = fromQString(relPath);
+}
+
+bool CFilePath::IsInSubDirectory(const CFilePath &inBasePath) const
+{
+ if (IsEmpty() || inBasePath.IsEmpty()) // nothing to compare
+ return false;
+
+ CFilePath thePath(GetPathWithoutIdentifier().c_str());
+
+ // Get base directory if it is a file
+ CFilePath theBaseDirectory(inBasePath.c_str());
+ if (inBasePath.IsFile())
+ theBaseDirectory = inBasePath.GetDirectory();
+
+ // Remove any trailing backslash so that we are comparing on the same ground
+ // just in case if we are comparing between same folder.
+ thePath.RemoveTrailingBackslash();
+ theBaseDirectory.RemoveTrailingBackslash();
+ if (thePath == theBaseDirectory)
+ return true;
+
+ // Add trailing backslash because we want to compare different folder
+ theBaseDirectory.AddTrailingBackslash();
+
+ // Check if the path is in the base directory
+ // Use caseless comparison because it's windows
+ return ((thePath.Length() >= theBaseDirectory.Length())
+ && theBaseDirectory.Compare(thePath.Extract(0, theBaseDirectory.Length()), false));
+}
+
+//==============================================================================
+/**
+* Retrieves the current directory for the current process.
+* @return TRUE always
+*/
+bool CFilePath::GetCurrentDir()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ wchar_t szPath[_MAX_PATH] = L"\0";
+ ::GetCurrentDirectoryW(sizeof(szPath) / sizeof(wchar_t), szPath);
+ UICAssign(szPath);
+#ifdef _WIN32
+ *this += L"\\";
+#else
+ *this += L"/";
+#endif //_WIN32
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+//==============================================================================
+/**
+* Resolves if this and inOtherPath are on the same drive.
+* @return true if this and inOtherPath are on the same drive.
+*/
+bool CFilePath::IsOnSameDrive(const CFilePath &inOtherPath) const
+{
+ CFilePath theOtherPath(inOtherPath);
+ return GetDrive().Compare(theOtherPath.GetDrive(), false);
+}
+
+void CFilePath::Normalize()
+{
+ CString &path(*this);
+ EnsureNonFileURL(path);
+ CFilePath retval;
+ retval.reserve(path.size());
+ bool lastSlash = false;
+ bool normalSep = false;
+ size_t index = 0;
+ for (CString::const_iterator iter = path.begin(), end = path.end(); iter != end;
+ ++iter, ++index) {
+ wchar_t current = *iter;
+ if (current == pathSep || current == alternateSep) {
+ if (lastSlash == false || (normalSep && (index < 2)))
+ retval.Concat(pathSep);
+ lastSlash = true;
+ normalSep = current == pathSep;
+ } else {
+ normalSep = false;
+ lastSlash = false;
+ retval.Concat(current);
+ }
+ }
+ // Resolve and remove ./ indicators that don't start at the beginning of the string
+ for (long curdirPos = retval.find(curdirSearch); curdirPos != CString::npos;
+ curdirPos = retval.find(curdirSearch, curdirPos))
+ retval = retval.erase(curdirPos, 2);
+
+ // Resolve updir indicators until we can't any more
+ for (long updirPos = retval.find(updirSearch); updirPos != CString::npos;
+ updirPos = retval.find(updirSearch, updirPos)) {
+ long lastSlash = CString::npos;
+ // catch ./../
+ if (updirPos < 2) {
+ retval = retval.erase(0, updirPos + 1);
+ break;
+ }
+ // for all other ../ conditions
+ else {
+ lastSlash = retval.rfind(pathSep, updirPos - 1);
+ if (lastSlash == CString::npos)
+ break;
+ retval = retval.erase(lastSlash, updirPos - lastSlash + 3);
+ updirPos = lastSlash;
+ }
+ }
+ *this = retval;
+}
+
+bool CFilePath::IsNormalized() const
+{
+ const CFilePath &path(*this);
+#ifdef _WIN32
+ if (path.find('/') != CFilePath::npos)
+#else
+ if (path.find('\\') != CFilePath::npos)
+#endif
+ return false;
+
+ CFilePath::size_type findResult = path.find(updir);
+ if (findResult != 0 && findResult != CFilePath::npos)
+ return false;
+
+ findResult = path.find(UNCPathSepStr);
+ if (findResult != 0 && findResult != CFilePath::npos)
+ return false;
+
+ return true;
+}
+
+bool CFilePath::IsAbsolute() const
+{
+ const CString &path(*this);
+ if (path.Length() > 1) {
+#ifdef _WIN32
+ if (path[1] == ':')
+ return true;
+ if (path[0] == path[1] && path[1] == pathSep)
+ return true;
+#else
+ if (path[0] == pathSep)
+ return true;
+#endif
+ }
+ return false;
+}
+void CFilePath::CombineBaseAndRelative(const CFilePath &basePath)
+{
+ QT3DS_ASSERT(basePath.IsAbsolute());
+ CFilePath &relativePath(*this);
+ if (relativePath.IsAbsolute())
+ return;
+ Q3DStudio::CFilePath retval;
+ retval.reserve(basePath.Length() + relativePath.Length());
+ retval.assign(basePath);
+ if (retval.Length() && retval[retval.Length() - 1] != '\\')
+ retval.append(pathSepStr);
+ retval.append(relativePath);
+ retval.Normalize();
+ *this = retval;
+}
+// If we are absolute, we are done.
+// If not, ConvertToAbsolute using getcwd.
+void CFilePath::ConvertToAbsolute()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (IsAbsolute())
+ return;
+ wchar_t pathBuf[1024];
+ _wgetcwd(pathBuf, 1024);
+ CombineBaseAndRelative(CString(pathBuf));
+#endif
+}
+// Make a save file stem from this string. Involves replacing characters
+// that are illegal (:,\\,//,etc).
+CString CFilePath::MakeSafeFileStem(const CString &name)
+{
+ CFilePath retval;
+ retval.reserve(name.Length());
+ for (Q3DStudio::CString::const_iterator iter = name.begin(), end = name.end(); iter != end;
+ ++iter) {
+ wchar_t strItem(*iter);
+ if (fileUnsafeChars.find_first_of(strItem) != Q3DStudio::CString::npos)
+ retval.append(L"_", 1);
+ else
+ retval.append(&strItem, 1);
+ }
+ return retval;
+}
+
+// Create this directory, recursively creating parent directories
+// if necessary.
+bool CFilePath::CreateDir(bool recurse) const
+{
+ QDir d(GetPathWithoutIdentifier().toQString());
+ if (d.exists())
+ return true;
+
+ if (recurse)
+ return RecurseCreateDirectory(CString(GetPathWithoutIdentifier().c_str()));
+ d.cdUp();
+ return d.mkdir(QFileInfo(GetPathWithoutIdentifier().toQString()).fileName());
+}
+// Returns true if exists and is directory
+bool CFilePath::IsDirectory() const
+{
+ return GetFileFlags().IsDirectory();
+}
+// returns true if exists and is a file
+bool CFilePath::IsFile() const
+{
+ return GetFileFlags().IsFile();
+}
+// If the file doesn't exist, create it.
+// If it does exist, update its modification time.
+void CFilePath::Touch() const
+{
+ QFile f(GetPathWithoutIdentifier().toQString());
+ f.open(QIODevice::ReadWrite);
+}
+// Returns true if this exists on the filesystem and is a directory or file.
+bool CFilePath::Exists() const
+{
+ return GetFileFlags().Exists();
+}
+
+// Delete this file from the filesystem
+bool CFilePath::DeleteThisFile()
+{
+ return QFile::remove(QString::fromWCharArray(GetPathWithoutIdentifier().c_str())) != 0;
+}
+// Delete this directory
+bool CFilePath::DeleteThisDirectory(bool recursive)
+{
+ bool retval = true;
+ if (recursive) {
+ std::vector<CFilePath> subFiles;
+ ListFilesAndDirectories(subFiles);
+ for (size_t idx = 0; idx < subFiles.size(); ++idx) {
+ if (subFiles[idx].IsFile())
+ retval = retval && subFiles[idx].DeleteThisFile();
+ else
+ retval = retval && subFiles[idx].DeleteThisDirectory(true);
+ }
+ }
+ QDir dir(QString::fromWCharArray(GetPathWithoutIdentifier().c_str()));
+ dir.cdUp();
+ retval = retval && dir.rmdir(QDir(QString::fromWCharArray(GetPathWithoutIdentifier().c_str())).dirName());
+ return retval;
+}
+
+void CFilePath::ListFilesAndDirectories(std::vector<CFilePath> &files) const
+{
+ if (!IsDirectory()) {
+ return;
+ }
+ CString findPath(GetPathWithoutIdentifier());
+ QDirIterator di(findPath.toQString(), QDir::NoDotAndDotDot | QDir::AllEntries);
+ while (di.hasNext())
+ files.push_back(CString::fromQString(di.next()));
+}
+
+bool CFilePath::FindLatestModifiedFileInDirectory(CFilePath &file) const
+{
+ if (!IsDirectory()) {
+ return false;
+ }
+
+ QDateTime theLatestFileTime;
+ bool foundFile = false;
+
+ CString findPath(GetPathWithoutIdentifier());
+ QDirIterator di(findPath.toQString(), QDir::NoDotAndDotDot | QDir::AllEntries);
+ while (di.hasNext()) {
+ auto ffd = di.fileInfo();
+ if (theLatestFileTime < ffd.lastModified()) {
+ theLatestFileTime = ffd.lastModified();
+ file = CString::fromQString(ffd.absoluteFilePath());
+ foundFile = true;
+ }
+ }
+
+ return foundFile;
+}
+
+void CFilePath::RecursivelyFindFilesOfType(const wchar_t **inExtensionList,
+ std::vector<CFilePath> &files, bool inMakeRelative,
+ bool inIncludeDirectories) const
+{
+ if (!IsDirectory()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ std::vector<CFilePath> directoryVector;
+ std::vector<CFilePath> nextDirectoryVector;
+ std::vector<CFilePath> resultsVector;
+
+ directoryVector.push_back(*this);
+ // breadth first search.
+ while (directoryVector.empty() == false && files.size() < 10000) {
+ for (size_t dirIdx = 0, dirEnd = directoryVector.size();
+ dirIdx < dirEnd && files.size() < 10000; ++dirIdx) {
+ resultsVector.clear();
+ directoryVector[dirIdx].ListFilesAndDirectories(resultsVector);
+ for (size_t resultIdx = 0, resultEnd = resultsVector.size(); resultIdx < resultEnd;
+ ++resultIdx) {
+ const CFilePath &result(resultsVector[resultIdx]);
+ if (result.IsDirectory()) {
+ nextDirectoryVector.push_back(result);
+ if (inIncludeDirectories)
+ files.push_back(result);
+ } else {
+ Q3DStudio::CString extension(result.GetExtension());
+ if (inExtensionList == NULL || *inExtensionList == NULL) {
+ files.push_back(result);
+ } else {
+ for (const wchar_t **specificExt = inExtensionList; *specificExt;
+ ++specificExt) {
+ if (extension == *specificExt) {
+ files.push_back(result);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ std::swap(directoryVector, nextDirectoryVector);
+ nextDirectoryVector.clear();
+ }
+ std::stable_sort(files.begin(), files.end());
+ if (inMakeRelative) {
+ for (size_t idx = 0, end = files.size(); idx < end; ++idx)
+ files[idx] = GetRelativePathFromBase(*this, files[idx]);
+ }
+}
+
+void CFilePath::FindDirectoryDifferences(
+ const std::vector<SFileModificationRecord> &inOldDifferences,
+ std::vector<SFileModificationRecord> &outNewDifferences, volatile bool *inCancel) const
+{
+ std::vector<SFileModificationRecord> theOutput;
+ std::vector<CFilePath> theFiles;
+
+ // Assume we will have about as many results as last time.
+ theFiles.reserve(inOldDifferences.size());
+ if (IsDirectory())
+ RecursivelyFindFilesOfType(NULL, theFiles, false, true);
+
+ // Else we have no files and the new file list should be empty
+ // This will send out destroyed messages for every file in the list
+ // once.
+
+ theOutput.reserve(NVMax(inOldDifferences.size(), theFiles.size()));
+ // Given that we know theFiles are sorted and inOldDifferences is sorted,
+ // run through inOldDifferences and theFiles exactly one, putting new values into theOutput.
+ // Algorithm below is O(max(inOldDifferences.size(), theFiles.size()) )
+
+ size_t numOldDifferences = inOldDifferences.size();
+ size_t numFiles = theFiles.size();
+ size_t oldDiffIdx = 0;
+ size_t fileIdx = 0;
+ volatile bool theLocalCancel = false;
+ if (inCancel == NULL)
+ inCancel = &theLocalCancel;
+
+ while (oldDiffIdx < numOldDifferences && fileIdx < numFiles && !*inCancel) {
+ const SFileModificationRecord &oldRecord = inOldDifferences[oldDiffIdx];
+ const CFilePath &theFile = theFiles[fileIdx];
+ if (oldRecord.m_File < theFile) {
+ // Stop recording destroyed files if the message has been sent once
+ if (oldRecord.m_ModificationType != FileModificationType::Destroyed)
+ theOutput.push_back(SFileModificationRecord(oldRecord.m_File, oldRecord.m_FileInfo,
+ oldRecord.m_FileData,
+ FileModificationType::Destroyed));
+
+ ++oldDiffIdx;
+ } else {
+ SFileData newData;
+ if (theFile.IsFile())
+ newData = theFile.GetFileData();
+
+ SFileInfoFlags theInfo = theFile.GetFileFlags();
+ FileModificationType::Enum theFileModType = FileModificationType::NoChange;
+ if (theFile < oldRecord.m_File) {
+ theFileModType = FileModificationType::Created;
+ ++fileIdx;
+ } else // We have matching files
+ {
+ if (oldRecord.m_ModificationType == FileModificationType::Destroyed)
+ theFileModType = FileModificationType::Created;
+ else if (newData.m_LastModTime != oldRecord.m_FileData.m_LastModTime)
+ theFileModType = FileModificationType::Modified;
+ else if (theInfo != oldRecord.m_FileInfo)
+ theFileModType = FileModificationType::InfoChanged;
+
+ ++fileIdx;
+ ++oldDiffIdx;
+ }
+ theOutput.push_back(SFileModificationRecord(theFile, theInfo, newData, theFileModType));
+ }
+ }
+ for (; oldDiffIdx < numOldDifferences && !*inCancel; ++oldDiffIdx) {
+ const SFileModificationRecord &oldRecord = inOldDifferences[oldDiffIdx];
+ if (oldRecord.m_ModificationType != FileModificationType::Destroyed)
+ theOutput.push_back(SFileModificationRecord(oldRecord.m_File, oldRecord.m_FileInfo,
+ oldRecord.m_FileData,
+ FileModificationType::Destroyed));
+ }
+ for (; fileIdx < numFiles && !*inCancel; ++fileIdx) {
+ const CFilePath &theFile = theFiles[fileIdx];
+ theOutput.push_back(SFileModificationRecord(
+ theFile, theFile.GetFileFlags(), theFile.GetFileData(), FileModificationType::Created));
+ }
+ std::swap(theOutput, outNewDifferences);
+}
+
+SFileInfoFlags CFilePath::GetFileFlags() const
+{
+ QFileInfo fi(GetPathWithoutIdentifier().toQString());
+ if (!fi.exists())
+ return 0; // doesn't exist
+ int atts = FileInfoFlagValues::Exists;
+ if (fi.isDir())
+ atts += FileInfoFlagValues::IsDirectory;
+ else {
+ atts += FileInfoFlagValues::CanRead;
+ if (fi.isWritable())
+ atts += FileInfoFlagValues::CanWrite;
+ }
+ if (fi.isHidden())
+ atts += FileInfoFlagValues::IsHidden;
+ return atts;
+}
+
+SFileData CFilePath::GetFileData() const
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ HANDLE file = CreateFileW(GetPathWithoutIdentifier().c_str(), GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ return SFileData();
+ StaticAssert<sizeof(FILETIME) == sizeof(QT3DSU64)>::valid_expression();
+ QT3DSU64 create;
+ QT3DSU64 lastWrite;
+ GetFileTime(file, reinterpret_cast<FILETIME *>(&create), NULL,
+ reinterpret_cast<FILETIME *>(&lastWrite));
+
+ // LE code alert
+ QT3DSU64 fileSize = 0;
+ DWORD *sizePtr(reinterpret_cast<DWORD *>(&fileSize));
+ sizePtr[0] = GetFileSize(file, sizePtr + 1);
+ CloseHandle(file);
+ return SFileData(fileSize, lastWrite, create);
+#else
+ return {};
+#endif
+}
+
+CFilePath CFilePath::GetUserApplicationDirectory()
+{
+ return CFilePath(CString::fromQString(QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation))));
+}
+
+SFile::SFile(const QSharedPointer<QFile> &of, const CFilePath &path)
+ : m_OpenFile(of)
+ , m_Path(path)
+{
+}
+SFile::~SFile()
+{
+ if (m_OpenFile)
+ Close(m_OpenFile);
+}
+QT3DSU32 SFile::Read(void *buffPtr, QT3DSU32 byteSize)
+{
+ return ReadData(m_OpenFile, buffPtr, byteSize);
+}
+QT3DSU32 SFile::Write(const void *buffPtr, QT3DSU32 byteSize)
+{
+ return WriteData(m_OpenFile, buffPtr, byteSize);
+}
+
+QSharedPointer<QFile> SFile::OpenForRead(const CFilePath &inPath)
+{
+ QSharedPointer<QFile> f(new QFile(inPath.toQString()));
+ if (!f->open(QFile::ReadOnly)) {
+ return nullptr;
+ }
+ return f;
+}
+
+QSharedPointer<QFile> SFile::OpenForWrite(const CFilePath &inFullPath, FileOpenFlags fileFlags)
+{
+ QFile::OpenMode mode = QIODevice::ReadWrite;
+ if (fileFlags & FileOpenFlagValues::Truncate)
+ mode |= QIODevice::Truncate;
+ bool truncate = (QT3DSU32)((fileFlags & FileOpenFlagValues::Truncate)) != 0;
+ bool open = (QT3DSU32)((fileFlags & FileOpenFlagValues::Open)) != 0;
+ bool create = (QT3DSU32)((fileFlags & FileOpenFlagValues::Create)) != 0;
+
+ QSharedPointer<QFile> file(new QFile(inFullPath.GetPathWithoutIdentifier().toQString()));
+ if (!create && !file->exists() || !file->open(mode)) {
+ return nullptr;
+ }
+ // If we aren't truncating, then we seek to the end to append.
+ if (truncate == false && open == true) {
+ file->seek(file->size());
+ }
+ return file;
+}
+
+// Copy src to dest, close both src and dest, and
+// return the number of bytes copied.
+QT3DSU64 SFile::Copy(const QSharedPointer<QFile> &destFile, const QSharedPointer<QFile> &srcFile)
+{
+ QT3DSU8 buffer[4096];
+ QT3DSU32 numBytes = 0;
+ QT3DSU64 total = 0;
+ do {
+ numBytes = ReadData(srcFile, buffer, 4096);
+ WriteData(destFile, buffer, numBytes);
+ total += numBytes;
+ } while (numBytes == 4096);
+ Close(srcFile);
+ Close(destFile);
+ return total;
+}
+
+// Attemt to write data, return the number of bytes written.
+QT3DSU32 SFile::WriteData(const QSharedPointer<QFile> &fileHandle, const void *data, QT3DSU32 byteSize)
+{
+ QT3DS_ASSERT(fileHandle);
+ if (byteSize && fileHandle) {
+ return fileHandle->write(reinterpret_cast<const char *>(data), byteSize);
+ }
+ return 0;
+}
+
+// Attempt to read data, return the number of byte read
+QT3DSU32 SFile::ReadData(const QSharedPointer<QFile> &fileHandle, void *data, QT3DSU32 byteSize)
+{
+ QT3DS_ASSERT(fileHandle);
+ if (byteSize && fileHandle) {
+ return fileHandle->read(reinterpret_cast<char *>(data), byteSize);
+ }
+ return 0;
+}
+
+DWORD SeekPosToMoveMethod(SeekPosition::Enum inEnum)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ switch (inEnum) {
+ case SeekPosition::Begin:
+ return FILE_BEGIN;
+ case SeekPosition::Current:
+ return FILE_CURRENT;
+ case SeekPosition::End:
+ return FILE_END;
+ }
+ QT3DS_ASSERT(false);
+ return FILE_BEGIN;
+#endif
+ return {};
+}
+
+QT3DSI64 SFile::GetPosition(const QSharedPointer<QFile> &fileHandle)
+{
+ QT3DS_ASSERT(fileHandle);
+ if (fileHandle) {
+ return fileHandle->pos();
+ }
+ return 0;
+}
+
+void SFile::SetPosition(const QSharedPointer<QFile> &fileHandle, QT3DSI64 inOffset, SeekPosition::Enum inSeekPos)
+{
+ QT3DS_ASSERT(fileHandle);
+ if (fileHandle) {
+ switch (inSeekPos) {
+ case SeekPosition::Begin:
+ fileHandle->seek(inOffset);
+ break;
+ case SeekPosition::Current:
+ fileHandle->seek(fileHandle->pos() + inOffset);
+ break;
+ case SeekPosition::End:
+ fileHandle->seek(fileHandle->size() + inOffset);
+ break;
+ }
+ }
+}
+
+void SFile::SetFileTimeToCurrentTime(const QSharedPointer<QFile> &fileHandle)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ FILETIME ft;
+ SYSTEMTIME st;
+
+ GetSystemTime(&st); // Gets the current system time
+ SystemTimeToFileTime(&st, &ft); // Converts the current system time to file time format
+ SetFileTime((HANDLE)fileHandle, // Sets last-write time of the file
+ (LPFILETIME)NULL, // to the converted current system time
+ (LPFILETIME)NULL, &ft);
+#endif
+}
+
+// Close the file handle.
+void SFile::Close(const QSharedPointer<QFile> &fileHandle)
+{
+ QT3DS_ASSERT(fileHandle);
+ fileHandle->close();
+}
+
+std::shared_ptr<SFile> SFile::Wrap(const QSharedPointer<QFile> &inFileHandle, const CFilePath &path)
+{
+ return std::make_shared<SFile>(inFileHandle, path);
+}
+
+// Open the file and return an os-specific handle.
+// in windows, this uses CreateFile and returns the file handle.
+// It returns the opened file because this eliminates a race condition where
+// this function returns the file name at the same time another process returns
+// the file name and then we have two objects thinking they own the file.
+// Function appends an index in betwee nthe file stem and the extension
+// in order to generate a possibly unique name.
+// params:
+// inDestDir -> points to destination directory (and is a directory)
+// fstem -> file stem to write to
+// inExt -> extension to use after stem + unique append apparatus.
+TFilePtr SFileTools::FindUniqueDestFile(const CFilePath &inDestDirectory, const CString &inFStem,
+ const CString &inExt)
+{
+ if (!inDestDirectory.Exists())
+ inDestDirectory.CreateDir(true);
+ if (!inDestDirectory.Exists())
+ return TFilePtr();
+ wchar_t period = '.';
+ Q3DStudio::CString stem;
+ stem.reserve(inDestDirectory.Length() + inFStem.Length() + 1);
+ stem.assign(inDestDirectory);
+ if (stem.Length() && stem[stem.Length() - 1] != '\\')
+ stem.append(&pathSep, 1);
+ stem.append(inFStem);
+
+ Q3DStudio::CString retval;
+ retval.reserve(stem.Length() + inExt.Length() + 10);
+ retval.assign(stem);
+
+ retval.append(&period, 1);
+ retval.append(inExt);
+
+ // Force creation of new file or failure.
+ auto handle = SFile::OpenForWrite(retval, FileOpenFlagValues::Create);
+ QT3DSU32 idx = 1;
+ while (handle == NULL && idx < 1000) {
+ wchar_t buffer[10];
+ QT3DSU32 numChars = swprintf(buffer, 10, L"_%03d", idx);
+ ++idx;
+
+#ifdef _WIN32
+ // On windows we need to limit the path
+ if (stem.size() > MAX_PATH) {
+ retval.assign(veryLongPathPrefix);
+ retval.append(stem, MAX_PATH - (inDestDirectory.Length() + 10));
+ } else
+#endif
+ retval.assign(stem);
+
+ retval.append(buffer, numChars);
+ retval.append(&period, 1);
+ retval.append(inExt);
+ handle = SFile::OpenForWrite(retval, FileOpenFlagValues::Create);
+ }
+ if (handle == NULL) {
+ retval.assign(inFStem);
+ retval.append(L"_999", 4);
+ return FindUniqueDestFile(inDestDirectory, retval, inExt);
+ }
+ return std::make_shared<SFile>(handle, retval);
+}
+
+QString SFileTools::FindUniqueDestFile(const QDir &inDestDirectory, const QString &inFStem,
+ const QString &inExt)
+{
+ if (!inDestDirectory.exists())
+ return {};
+
+ QString retval = QStringLiteral("%1.%2").arg(inFStem, inExt);
+ int idx = 1;
+ while (inDestDirectory.exists(retval) && idx < 1000) {
+ retval = QStringLiteral("%1_%2.%3").arg(inFStem).arg(idx, 3, 10, QLatin1Char('0')).arg(inExt);
+ ++idx;
+ }
+ if (inDestDirectory.exists(retval)) {
+ return FindUniqueDestFile(inDestDirectory, inFStem + QLatin1String("_999"), inExt);
+ }
+
+ return inDestDirectory.filePath(retval);
+}
+
+// Similar to above but takes care of finding the stem and extension from the full source CFilePath
+TFilePtr SFileTools::FindUniqueDestFile(const CFilePath &inDestDir,
+ const CFilePath &inSrcFullFilePath)
+{
+ return FindUniqueDestFile(inDestDir, inSrcFullFilePath.GetFileStem(),
+ inSrcFullFilePath.GetExtension());
+}
+
+QString SFileTools::FindUniqueDestFile(const QDir &inDestDir,
+ const QString &inSrcFullFilePath)
+{
+ QFileInfo fileInfo(inSrcFullFilePath);
+ return FindUniqueDestFile(inDestDir, fileInfo.completeBaseName(), fileInfo.suffix());
+}
+
+// Find a unique destination directory. This directory was guaranteed not to exist before this call
+// and we are guaranteeing that it was created for this call; i.e. there can't be a race condition
+// We expect dest dir and dir name to be normalized.
+// We also expect that inDestDirectory exists. Function results are L"" otherwise
+// If the function succeeds, it returns the absolute CFilePath of the new directory.
+// If it fails, it returns L"";
+CFilePath SFileTools::FindUniqueDestDirectory(const CFilePath &inDestDirectory,
+ const CString &inDirName)
+{
+ if (inDestDirectory.IsDirectory() == false) {
+ QT3DS_ASSERT(false);
+ return L"";
+ }
+
+ Q3DStudio::CString retval;
+ retval.reserve(inDestDirectory.Length() + inDirName.Length() + 2);
+ retval = CFilePath::CombineBaseAndRelative(inDestDirectory, inDirName);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ BOOL success = ::CreateDirectoryW(retval, NULL);
+ if (success)
+ return CFilePath::GetAbsolutePath(retval);
+ DWORD error = GetLastError();
+ if (error == ERROR_PATH_NOT_FOUND) {
+ QT3DS_ASSERT(false);
+ return L"";
+ }
+ QT3DSU32 idx = 0;
+ Q3DStudio::CString stem(retval);
+ // Eventually we will succeed
+ while (success == FALSE) {
+ ++idx;
+ retval = stem;
+ wchar_t buffer[10] = { 0 };
+ swprintf(buffer, 10, L"_%03d", idx);
+ retval.append(buffer);
+ success = ::CreateDirectoryW(retval, NULL);
+ }
+#endif
+ return CFilePath::GetAbsolutePath(retval);
+}
+
+QDir SFileTools::FindUniqueDestDirectory(const QDir &inDestDirectory,
+ const QString &inDirName)
+{
+ if (inDestDirectory.exists() == false) {
+ QT3DS_ASSERT(false);
+ return {};
+ }
+
+ QString retval = inDirName;
+
+ if (inDestDirectory.exists(retval) == true) {
+ int idx = 0;
+ // Eventually we will succeed
+ while (true) {
+ ++idx;
+ retval = QStringLiteral("%1_%2").arg(inDirName).arg(idx, 3, 10, QLatin1Char('0'));
+ if (inDestDirectory.exists(retval) == false)
+ break;
+ }
+ }
+
+ inDestDirectory.mkdir(retval);
+
+ return QDir(inDestDirectory.filePath(retval));
+}
+
+// Copy the full file FilePaths.
+// Same file flags as OpenFileForWrite
+SFileErrorCodeAndNumBytes SFileTools::Copy(const CFilePath &destFile, FileOpenFlags dstFileFlags,
+ const CFilePath &srcFile)
+{
+ QFileInfo srcInfo(srcFile.toQString());
+ if (!srcInfo.exists())
+ return FileErrorCodes::SourceNotExist;
+
+ if (!srcInfo.isReadable())
+ return FileErrorCodes::SourceNotReadable;
+
+ QString destFileString = destFile.toQString();
+ if (QFile::exists(destFileString)) {
+ bool ok = QFile::remove(destFileString);
+ if (!ok)
+ return FileErrorCodes::DestNotWriteable;
+ }
+
+ bool ok = QFile::copy(srcFile.toQString(), destFileString);
+ if (ok) {
+ QFileInfo destInfo(destFile.toQString());
+ return destInfo.size();
+ }
+
+ return FileErrorCodes::DestNotWriteable;
+}
+
+// Find a unique dest file based on the src file stem and extension but in the destination directory
+// then copy that file. Return the file name
+// this -> points to destination directory
+// srcFile -> src file to copy
+SFileErrorCodeFileNameAndNumBytes SFileTools::FindAndCopyDestFile(const CFilePath &inDestDir,
+ const CFilePath &inSrcFile)
+{
+ TFilePtr dest(FindUniqueDestFile(inDestDir, inSrcFile));
+ if (dest == NULL)
+ return SFileErrorCodeFileNameAndNumBytes(FileErrorCodes::DestNotWriteable);
+ auto srcFile = SFile::OpenForRead(inSrcFile);
+ if (srcFile == NULL)
+ return SFileErrorCodeFileNameAndNumBytes(FileErrorCodes::SourceNotReadable, 0,
+ dest->m_Path);
+ else {
+ QT3DSU64 nb = SFile::Copy(dest->m_OpenFile, srcFile);
+ dest->m_OpenFile = NULL;
+ return SFileErrorCodeFileNameAndNumBytes(FileErrorCodes::NoError, nb, dest->m_Path);
+ }
+}
+
+bool SFileTools::FindAndCopyDestFile(const QDir &inDestDir,
+ const QString &inSrcFile)
+{
+ QString dest = FindUniqueDestFile(inDestDir, inSrcFile);
+ if (dest.isEmpty())
+ return false;
+ return QFile::copy(inSrcFile, dest);
+}
+
+QDebug operator<<(QDebug stream, const CFilePath &s)
+{
+ stream << "CFilePath(" << s.toQString() << ")";
+ return stream;
+}
+
+}
diff --git a/src/Authoring/Common/Code/UICFileTools.h b/src/Authoring/Common/Code/UICFileTools.h
new file mode 100644
index 00000000..7ee95587
--- /dev/null
+++ b/src/Authoring/Common/Code/UICFileTools.h
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICFILETOOLS_H
+#define INCLUDED_UICFILETOOLS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSFlags.h"
+#include "UICFileToolTypes.h"
+#include "UICDMWStrOpsImpl.h"
+
+class QDir;
+
+namespace Q3DStudio {
+using qt3ds::QT3DSI64;
+using qt3ds::foundation::SeekPosition;
+using qt3ds::foundation::FileOpenFlags;
+using qt3ds::foundation::FileOpenFlagValues;
+using UICDM::WStrOps;
+
+class CFilePathTokenizer
+{
+protected:
+ CString m_FilePath;
+ long m_CurrPos;
+ long m_NextPos;
+
+public:
+ static const CString s_DirectoryDelimiters;
+
+ CFilePathTokenizer(const CString &inString)
+ : m_FilePath(static_cast<const wchar_t *>(inString))
+ , m_CurrPos(0)
+ , m_NextPos(CString::npos)
+ {
+ while (m_FilePath.find_first_of(s_DirectoryDelimiters, 0) == 0) {
+ m_FilePath.erase(0, 1);
+ }
+ }
+
+ CString GetNext()
+ {
+ long theTokenEnd = m_FilePath.find_first_of(s_DirectoryDelimiters, m_CurrPos);
+
+ if (theTokenEnd == CString::npos)
+ theTokenEnd = m_FilePath.size();
+
+ m_NextPos = theTokenEnd + 1;
+
+ return m_FilePath.substr(m_CurrPos, theTokenEnd - m_CurrPos);
+ }
+
+ bool HasNext()
+ {
+ if (m_CurrPos >= m_FilePath.size()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ CString GetRest()
+ {
+ if (HasNext())
+ return m_FilePath.substr(m_CurrPos);
+ else
+ return L"";
+ }
+
+ void operator++()
+ {
+ if (m_NextPos == CString::npos) {
+ GetNext();
+ }
+
+ m_CurrPos = m_NextPos;
+ m_NextPos = CString::npos;
+ }
+};
+
+struct SFileModificationRecord;
+
+/**
+ * SFile tools to abstract dealing with the filesystem. You should not be calling fstat
+ * or stat, fopen, CreateFile, CreateDirectory, etc. Those calls need to go through
+ * this object. File paths can also have identifiers trailing them.
+ * Anything after a # is interprented as an identifier. All file operations still work
+ * with the identifer included.
+ */
+class CFilePath : public CString
+{
+public:
+ //////Begin public API
+
+ CFilePath()
+ : CString(){}
+ CFilePath(const wchar_t *inPath)
+ : CString(inPath)
+ {
+ Normalize();
+ }
+ CFilePath(const char *inPath)
+ : CString(inPath)
+ {
+ Normalize();
+ }
+ CFilePath(const CString &szString, unsigned long inIdentifier)
+ : CString(szString)
+ {
+ Normalize();
+ SetIdentifier(inIdentifier);
+ }
+ CFilePath(const CString &szString, const CString &inIdentifier)
+ : CString(szString)
+ {
+ Normalize();
+ SetIdentifier(inIdentifier);
+ }
+ CFilePath(const CString &szString)
+ : CString(szString)
+ {
+ Normalize();
+ }
+ CFilePath(const QString &string)
+ : CString(string.toStdWString().c_str())
+ {
+
+ }
+
+ CFilePath(const CFilePath &szString);
+
+ const CFilePath &operator=(const CFilePath &strSrc);
+
+ void AddTrailingBackslash();
+ void RemoveTrailingBackslash();
+
+ CString GetDrive() const;
+ CFilePath GetDirectory() const;
+ CString GetFileName() const;
+ CString GetFileStem() const; // no extension, test.png -> test
+ CString GetExtension() const;
+ CString GetSuffix() const; // Return the extension +'#' + the identifier string, basically
+ // everything after the last .
+ // Get a file path you can give to systems that don't understand the identifier
+ CFilePath GetPathWithoutIdentifier() const;
+ // Set the identifer appended to the end of this file path.
+ void SetIdentifier(const CString &inIdentifier);
+ // Get the identifier appended to the end of this file path.
+ CString GetIdentifier() const;
+ // Returns 0 if no identifier was found
+ unsigned long GetULIdentifier() const;
+ void SetIdentifier(unsigned long inIdentifier);
+
+ bool GetTempDirectory();
+
+ static void EnsureNonFileURL(CString &ioFileFilePath);
+
+ bool GetTemporaryFileName(const CString &inPrefix, const CString &inDirectory = CString());
+ // NULL stands for the executable.
+// KDAB_TEMPORARILY_REMOVED
+ bool GetModuleFilePath(/*HMODULE inModuleHandle = NULL*/);
+
+ bool GetContainerModuleFilePath();
+ bool GetCurrentDir();
+
+ bool IsOnSameDrive(const CFilePath &inOtherFilePath) const;
+
+ /*
+ 1. All file:// or file:\ are stripped off
+ 2. All / are replaced with \
+ //3. duplicate forward slashes are removed.
+ 4. ..\ and .\ are resolved if possible.
+ This is done upon construction!!
+ */
+ void Normalize();
+
+ static CFilePath Normalize(const CString &inData) { return CFilePath(inData); }
+ static CFilePath Normalize(const CFilePath &inData) { return inData; }
+
+ // Ensure the above conditions are met.
+ bool IsNormalized() const;
+
+ void ConvertToRelative(const CFilePath &inBaseAbsolute);
+ static CFilePath GetRelativePathFromBase(const CFilePath &inBase, const CFilePath &inPath)
+ {
+ CFilePath retval(inPath);
+ retval.ConvertToRelative(inBase);
+ return retval;
+ }
+
+ /**
+ * Return true if this string is in subdirectory of inBasePath
+ * For example, basepath is C:\Folder\Project.uip
+ * This string is C:\Folder\Resources\Image.png
+ * The function should return true.
+ * @param inBasePath absolute path to base off from
+ * @return bool to indicate if is in subdirectory of inBasePath
+ */
+ bool IsInSubDirectory(const CFilePath &inBasePath) const;
+
+ void CombineBaseAndRelative(const CFilePath &inBase);
+
+ // Given a base CFilePath, convert it to an absolute CFilePath.
+ static CFilePath CombineBaseAndRelative(const CFilePath &inBase, const CFilePath &inRelative)
+ {
+ CFilePath retval(inRelative);
+ retval.CombineBaseAndRelative(inBase);
+ return retval;
+ }
+
+ bool IsAbsolute() const;
+ // If we are absolute, we are done.
+ // If not, CombineBaseAndRelative using getcwd.
+ void ConvertToAbsolute();
+ static CFilePath GetAbsolutePath(const CFilePath &inBaseFilePath)
+ {
+ CFilePath retval(inBaseFilePath);
+ retval.ConvertToAbsolute();
+ return retval;
+ }
+ // Make a save file stem from this string. Involves replacing characters
+ // that are illegal (:,\\,//,etc).
+ static CString MakeSafeFileStem(const CString &name);
+
+ // Create this directory, recursively creating parent directories
+ // if necessary.
+ bool CreateDir(bool recurse) const;
+ // Returns true if exists and is directory
+ bool IsDirectory() const;
+ // returns true if exists and is a file
+ bool IsFile() const;
+
+ // If the file doesn't exist, create an empty file at this location.
+ // If the file does exist, update its modification time to the current time.
+ void Touch() const;
+ // Returns true if this exists on the filesystem and is a directory or file.
+ bool Exists() const;
+ // Delete this file from the filesystem
+ bool DeleteThisFile();
+ // Delete this directory
+ bool DeleteThisDirectory(bool recursive);
+
+ // If this is a directory, list all contents.
+ // ignore special files ".\\" and "..\\"
+ // Returns absolute paths combined with this
+ // this.combineBaseAndRelative( result );
+ void ListFilesAndDirectories(std::vector<CFilePath> &files) const;
+ bool FindLatestModifiedFileInDirectory(CFilePath &file) const;
+
+ // Returns absolute paths
+ // This object has to be a directory
+ // extension list needs to be null terminated
+ // Returns results alphabetically sorted
+ // If makeRelative is true, returns paths relative to
+ // this directory.
+ // Else returns absolute paths.
+ // ExtensionList should not contain the "." in ".png" for example.
+ // It should just contain { L"png", NULL }
+ // An empty extension list means return all files.
+ void RecursivelyFindFilesOfType(const wchar_t **inExtensionList, std::vector<CFilePath> &files,
+ bool inMakeRelative, bool inIncludeDirectories = false) const;
+
+ // Given the list of differences from last time this function was called (which may be empty)
+ // and the list of new differences to put new results into, recursively diff this directory's
+ // contents with the last time this function was called.
+ // IF this is a file, the function asserts and immediately returns.
+ // All file paths are absolute paths!!
+ // Returns all files (and directories) recursively, sorted by name, for which either no record
+ // exists
+ // or for which the record entry has changed it's value since last time.
+ // inOldDifferences and outNewDifferences may point to the same location.
+ // We are expecting inOldDifferences to be sorted by filename; do not change the order of
+ // the return value *or* call std::stable_sort( ) on the vector before you call this
+ // method
+ // If at any point inCancel is true then this function will abort at that moment.
+ void FindDirectoryDifferences(const std::vector<SFileModificationRecord> &inOldDifferences,
+ std::vector<SFileModificationRecord> &outNewDifferences,
+ volatile bool *inCancel = NULL) const;
+
+ SFileInfoFlags GetFileFlags() const;
+ // Requires opening the file!!!
+ // Not valid for things that aren't files.
+ SFileData GetFileData() const;
+
+ // Get the directory where applications can write data.
+ static CFilePath GetUserApplicationDirectory();
+};
+
+struct SFileModificationRecord
+{
+ CFilePath m_File;
+ SFileInfoFlags m_FileInfo;
+ SFileData m_FileData;
+ FileModificationType::Enum m_ModificationType;
+
+ SFileModificationRecord()
+ : m_ModificationType(FileModificationType::Unknown)
+ {
+ }
+
+ SFileModificationRecord(const CFilePath &inFile, const SFileInfoFlags &inFileInfo,
+ const SFileData &inFileData, FileModificationType::Enum modType)
+ : m_File(inFile)
+ , m_FileInfo(inFileInfo)
+ , m_FileData(inFileData)
+ , m_ModificationType(modType)
+ {
+ }
+ // Order lexographically
+ bool operator<(const SFileModificationRecord &inOther) const { return m_File < inOther.m_File; }
+};
+
+typedef std::vector<SFileModificationRecord> TFileModificationList;
+
+struct SFile
+{
+ Q_DISABLE_COPY(SFile)
+
+ QSharedPointer<QFile> m_OpenFile;
+ CFilePath m_Path;
+
+ SFile(const QSharedPointer<QFile> &of, const CFilePath &path);
+ ~SFile();
+ QT3DSU32 Read(void *buffPtr, QT3DSU32 byteSize);
+ QT3DSU32 Write(const void *buffPtr, QT3DSU32 byteSize);
+
+ QT3DSI64 GetPosition() { return GetPosition(m_OpenFile); }
+ void SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inSeekPos)
+ {
+ SetPosition(m_OpenFile, inOffset, inSeekPos);
+ }
+
+ static QSharedPointer<QFile> OpenForRead(const CFilePath &inPath);
+
+ static QSharedPointer<QFile>
+ OpenForWrite(const CFilePath &inPath,
+ FileOpenFlags fileFlags = FileOpenFlags(FileOpenFlagValues::Open
+ | FileOpenFlagValues::Create
+ | FileOpenFlagValues::Truncate));
+
+ // Copy src to dest, close both src and dest, and
+ // return the number of bytes copied.
+ static QT3DSU64 Copy(const QSharedPointer<QFile> &destFile, const QSharedPointer<QFile> &srcFile);
+
+ // Attemt to write data, return the number of bytes written.
+ static QT3DSU32 WriteData(const QSharedPointer<QFile> &fileHandle, const void *data, QT3DSU32 byteSize);
+
+ // Attempt to read data, return the number of byte read
+ static QT3DSU32 ReadData(const QSharedPointer<QFile> &fileHandle, void *data, QT3DSU32 byteSize);
+
+ static QT3DSI64 GetPosition(const QSharedPointer<QFile> &fileHandle);
+
+ static void SetPosition(const QSharedPointer<QFile> &fileHandle, QT3DSI64 inOffset, SeekPosition::Enum inSeekPos);
+
+ // Close the file handle.
+ static void Close(const QSharedPointer<QFile> &fileHandle);
+
+ // Set file modification time to the current time.
+ static void SetFileTimeToCurrentTime(const QSharedPointer<QFile> &fileHandle);
+
+ static std::shared_ptr<SFile> Wrap(const QSharedPointer<QFile> &inFileHandle, const CFilePath &path);
+};
+
+typedef std::shared_ptr<SFile> TFilePtr;
+
+struct SFileErrorCodeAndNumBytes
+{
+ FileErrorCodes::Enum m_Error;
+ QT3DSU64 m_NumBytes;
+ SFileErrorCodeAndNumBytes(QT3DSU64 nb)
+ : m_Error(FileErrorCodes::NoError)
+ , m_NumBytes(nb)
+ {
+ }
+ SFileErrorCodeAndNumBytes(FileErrorCodes::Enum val)
+ : m_Error(val)
+ , m_NumBytes(0)
+ {
+ }
+};
+
+struct SFileErrorCodeFileNameAndNumBytes
+{
+ FileErrorCodes::Enum m_Error;
+ CFilePath m_DestFilename;
+ QT3DSU64 m_NumBytes;
+ SFileErrorCodeFileNameAndNumBytes(FileErrorCodes::Enum er, QT3DSU64 nb = 0,
+ const CString &dfn = CString())
+ : m_Error(er)
+ , m_DestFilename(dfn)
+ , m_NumBytes(nb)
+ {
+ }
+};
+
+struct SFileTools
+{
+ // Open the file and return an os-specific handle.
+ // in windows, this uses CreateFile and returns the file handle.
+ // It returns the opened file because this eliminates a race condition where
+ // this function returns the file name at the same time another process returns
+ // the file name and then we have two objects thinking they own the file.
+ // Function appends an index in betwee nthe file stem and the extension
+ // in order to generate a possibly unique name.
+ // params:
+ // inDestDir -> points to destination directory (and is a directory)
+ // fstem -> file stem to write to
+ // inExt -> extension to use after stem + unique append apparatus.
+ static TFilePtr FindUniqueDestFile(const CFilePath &inDestDir, const CString &inFStem,
+ const CString &inExt);
+ static QString FindUniqueDestFile(const QDir &inDestDir, const QString &inFStem,
+ const QString &inExt);
+ // Similar to above but takes care of finding the stem and extension from the full source
+ // CFilePath
+ static TFilePtr FindUniqueDestFile(const CFilePath &inDestDir,
+ const CFilePath &inSrcFullFilePath);
+ static QString FindUniqueDestFile(const QDir &inDestDir,
+ const QString &inSrcFullFilePath);
+
+ // Find a unique destination directory. This directory was guaranteed not to exist before this
+ // call
+ // and we are guaranteeing that it was created for this call; i.e. there can't be a race
+ // condition
+ // We expect dest dir and dir name to be normalized.
+ // We also expect that inDestDirectory exists. Function results are L"" otherwise
+ // If the function succeeds, it returns the absolute CFilePath of the new directory.
+ // If it fails, it returns L"";
+ static CFilePath FindUniqueDestDirectory(const CFilePath &inDestDir, const CString &inDirName);
+
+ static QDir FindUniqueDestDirectory(const QDir &inDestDir, const QString &inDirName);
+
+ // Copy the full file FilePaths.
+ // Same file flags as SFile::OpenForWrite
+ static SFileErrorCodeAndNumBytes Copy(const CFilePath &destFile, FileOpenFlags fileFlags,
+ const CFilePath &srcFile);
+
+ // Find a unique dest file based on the src file stem and extension but in the destination
+ // directory
+ // then copy that file. Return the file name
+ // this -> points to destination directory
+ // srcFile -> src file to copy
+ static SFileErrorCodeFileNameAndNumBytes FindAndCopyDestFile(const CFilePath &inDestDir,
+ const CFilePath &inSrcFile);
+ static bool FindAndCopyDestFile(const QDir &inDestDir,
+ const QString &inSrcFile);
+};
+
+}
+
+QDebug operator<<(QDebug stream, const Q3DStudio::CFilePath &s);
+
+#endif // INCLUDED_UICFILETOOLS_H
diff --git a/src/Authoring/Common/Code/UICFunctor.h b/src/Authoring/Common/Code/UICFunctor.h
new file mode 100644
index 00000000..f725607c
--- /dev/null
+++ b/src/Authoring/Common/Code/UICFunctor.h
@@ -0,0 +1,431 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// EngineeringTask (SDJ 08.09.05) This file is a huge mess!
+// It really should be cleaned up and consolidated to be a useful tool.
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICFUNCTOR
+#define INCLUDED_UICFUNCTOR
+
+#include <typeinfo>
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "SafeQueue.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==========================================================================
+/**
+ * @class CFunctorObjectBase
+ * Abstract base class, used as the base storage pointer for the
+ * Functor Queue.
+ */
+class CFunctorObjectBase
+{
+public:
+ const std::type_info *m_TypeInfo;
+
+public:
+ virtual bool Execute() { return false; }
+ virtual bool operator==(CFunctorObjectBase &) = 0;
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObjectBase
+ * Abstract base class, used as the base storage pointer for the
+ * Functor Queue.
+ */
+template <typename TFirstArg>
+class CFunctorObjectParam1Base
+{
+public:
+ virtual bool Execute(TFirstArg) { return false; }
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObjectReturnBase
+ */
+template <typename TReturnType>
+class CFunctorObjectReturnBase : public CFunctorObjectBase
+{
+public:
+ virtual TReturnType ExecuteReturn() = 0;
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObjectReturnBase1
+ */
+template <typename TReturnType, typename TFirstArg>
+class CFunctorObjectReturnBase1 : public CFunctorObjectBase
+{
+public:
+ virtual TReturnType ExecuteReturn(TFirstArg) = 0;
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObject0
+ * Template class that stores the data needed to execute a functor
+ * with a single parameter.
+ */
+template <typename TObjectType>
+class CFunctorObject0 : public CFunctorObjectBase
+{
+protected:
+ typedef void (TObjectType::*TMethod)();
+
+ TObjectType *m_Object; ///< The object on which to execute the methof
+ TMethod m_Method; ///< The single parameter method to execute
+
+public:
+ // Constructor
+ CFunctorObject0(TObjectType *inObject, TMethod inMethod)
+ : m_Object(inObject)
+ , m_Method(inMethod)
+ {
+ m_TypeInfo = &typeid(TObjectType);
+ }
+
+ //=======================================================================
+ /**
+ * Insert a functor object into the queue.
+ *
+ * @param inObjectBase
+ * The fucntor object to insert into the queue.
+ */
+ virtual bool Execute()
+ {
+ bool theReturn = true;
+
+ // Try / Catch the execution since param objects could go
+ // out of scope if not managed properly
+
+ try {
+ if (m_Object && m_Method) {
+ (m_Object->*(m_Method))();
+ }
+ } catch (...) {
+ theReturn = false;
+ }
+
+ return theReturn;
+ }
+
+ //=======================================================================
+ /**
+ * Compare the functors
+ *
+ * @param inFunctor
+ * The fucntor object to comapare.
+ */
+ virtual bool operator==(CFunctorObjectBase &inFunctor)
+ {
+ // Compare the Typinfo for the Callbacks. since we don't want to type cast just anything.
+ if (*m_TypeInfo == *inFunctor.m_TypeInfo) {
+ // This just does the type cast and the compare/
+ return Compare(static_cast<Q3DStudio::CFunctorObject0<TObjectType> *>(&inFunctor));
+ } else {
+ // return false if we are the wrong type.
+ return false;
+ }
+ }
+
+protected:
+ bool Compare(Q3DStudio::CFunctorObject0<TObjectType> *inFunctor)
+ {
+ // Don't compare the Args
+ return (m_Object == (*inFunctor).m_Object) && (m_Method == (*inFunctor).m_Method);
+ }
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObjectReturn0
+ */
+template <typename TReturnType, typename TObjectType>
+class CFunctorObjectReturn0 : public CFunctorObjectReturnBase<TReturnType>
+{
+protected:
+ typedef TReturnType (TObjectType::*TMethod)();
+
+ TObjectType *m_Object; ///< The object on which to execute the methof
+ TMethod m_Method; ///< The single parameter method to execute
+
+public:
+ // Constructor
+ CFunctorObjectReturn0(TObjectType *inObject, TMethod inMethod)
+ : m_Object(inObject)
+ , m_Method(inMethod)
+ {
+ CFunctorObjectReturnBase<TReturnType>::m_TypeInfo = &typeid(TObjectType);
+ }
+
+ //=======================================================================
+ /**
+ * Insert a functor object into the queue.
+ *
+ * @param inObjectBase
+ * The fucntor object to insert into the queue.
+ */
+ virtual TReturnType ExecuteReturn() { return (m_Object->*(m_Method))(); }
+
+ //=======================================================================
+ /**
+ * Compare the functors
+ *
+ * @param inFunctor
+ * The fucntor object to comapare.
+ */
+ virtual bool operator==(CFunctorObjectBase &inFunctor)
+ {
+ // Compare the Typinfo for the Callbacks. since we don't want to type cast just anything.
+ if (*CFunctorObjectReturnBase<TReturnType>::m_TypeInfo == *inFunctor.m_TypeInfo) {
+ // This just does the type cast and the compare/
+ return Compare(
+ static_cast<Q3DStudio::CFunctorObjectReturn0<TReturnType, TObjectType> *>(
+ &inFunctor));
+ } else {
+ // return false if we are the wrong type.
+ return false;
+ }
+ }
+
+protected:
+ bool Compare(Q3DStudio::CFunctorObjectReturn0<TReturnType, TObjectType> *inFunctor)
+ {
+ // Don't compare the Args
+ return (m_Object == (*inFunctor).m_Object) && (m_Method == (*inFunctor).m_Method);
+ }
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObjectReturn1
+ */
+template <typename TReturnType, typename TObjectType, typename TFirstArg>
+class CFunctorObjectReturn1 : public CFunctorObjectReturnBase1<TReturnType, TFirstArg>
+{
+protected:
+ typedef TReturnType (TObjectType::*TMethod)(TFirstArg);
+
+ TObjectType *m_Object; ///< The object on which to execute the method
+ TMethod m_Method; ///< The single parameter method to execute
+
+public:
+ // Constructor
+ CFunctorObjectReturn1(TObjectType *inObject, TMethod inMethod)
+ : m_Object(inObject)
+ , m_Method(inMethod)
+ {
+ CFunctorObjectReturnBase1<TReturnType, TFirstArg>::m_TypeInfo = &typeid(TObjectType);
+ }
+
+ //=======================================================================
+ /**
+ * Insert a functor object into the queue.
+ *
+ * @param inObjectBase
+ * The fucntor object to insert into the queue.
+ */
+ virtual TReturnType ExecuteReturn(TFirstArg inFirstArg)
+ {
+ return (m_Object->*(m_Method))(inFirstArg);
+ }
+
+ //=======================================================================
+ /**
+ * Compare the functors
+ *
+ * @param inFunctor
+ * The fucntor object to comapare.
+ */
+ virtual bool operator==(CFunctorObjectBase &inFunctor)
+ {
+ // Compare the Typinfo for the Callbacks. since we don't want to type cast just anything.
+ if (*CFunctorObjectReturnBase1<TReturnType, TFirstArg>::m_TypeInfo == *inFunctor.m_TypeInfo) {
+ // This just does the type cast and the compare/
+ return Compare(static_cast<Q3DStudio::CFunctorObjectReturn1<TReturnType, TObjectType,
+ TFirstArg> *>(&inFunctor));
+ } else {
+ // return false if we are the wrong type.
+ return false;
+ }
+ }
+
+protected:
+ bool Compare(Q3DStudio::CFunctorObjectReturn1<TReturnType, TObjectType, TFirstArg> *inFunctor)
+ {
+ // Don't compare the Args
+ return (m_Object == (*inFunctor).m_Object) && (m_Method == (*inFunctor).m_Method);
+ }
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObject1
+ * Template class that stores the data needed to execute a functor
+ * with a single parameter.
+ */
+template <typename TObjectType, typename TFirstArg>
+class CFunctorObjectParam1 : public CFunctorObjectParam1Base<TFirstArg>
+{
+protected:
+ typedef void (TObjectType::*TMethod)(TFirstArg);
+
+ TObjectType *m_Object; ///< The object on which to execute the method
+ TMethod m_Method; ///< The single parameter method to execute
+
+public:
+ // Constructor
+ CFunctorObjectParam1(TObjectType *inObject, TMethod inMethod)
+ : m_Object(inObject)
+ , m_Method(inMethod)
+ {
+ }
+
+ //=======================================================================
+ /**
+ * Insert a functor object into the queue.
+ *
+ * @param inObjectBase
+ * The fucntor object to insert into the queue.
+ */
+ virtual bool Execute(TFirstArg inFirstArg)
+ {
+ bool theReturn = true;
+
+ // Try / Catch the execution since param objects could go
+ // out of scope if not managed properly
+
+ try {
+ if (m_Object && m_Method) {
+ (m_Object->*(m_Method))(inFirstArg);
+ }
+ } catch (...) {
+ theReturn = false;
+ }
+
+ return theReturn;
+ }
+};
+
+//==========================================================================
+/**
+ * @class CFunctorObject1
+ * Template class that stores the data needed to execute a functor
+ * with a single parameter.
+ */
+template <typename TObjectType, typename TFirstArg>
+class CFunctorObject1 : public CFunctorObjectBase
+{
+protected:
+ typedef void (TObjectType::*TMethod)(TFirstArg);
+
+ TObjectType *m_Object; ///< The object on which to execute the methof
+ TMethod m_Method; ///< The single parameter method to execute
+ TFirstArg m_FirstArg; ///< The value of the single arguement
+
+public:
+ // Constructor
+ CFunctorObject1(TObjectType *inObject, TMethod inMethod, TFirstArg inFirstArg)
+ : m_Object(inObject)
+ , m_Method(inMethod)
+ , m_FirstArg(inFirstArg)
+ {
+ m_TypeInfo = &typeid(TObjectType);
+ }
+
+ //=======================================================================
+ /**
+ * Insert a functor object into the queue.
+ *
+ * @param inObjectBase
+ * The fucntor object to insert into the queue.
+ */
+ virtual bool Execute()
+ {
+ bool theReturn = true;
+
+ // Try / Catch the execution since param objects could go
+ // out of scope if not managed properly
+
+ try {
+ if (m_Object && m_Method) {
+ (m_Object->*(m_Method))(m_FirstArg);
+ }
+ } catch (...) {
+ theReturn = false;
+ }
+
+ return theReturn;
+ }
+
+ //=======================================================================
+ /**
+ * Compare the functors
+ *
+ * @param inFunctor
+ * The fucntor object to comapare.
+ */
+ virtual bool operator==(CFunctorObjectBase &inFunctor)
+ {
+ // Compare the Typinfo for the Callbacks. since we don't want to type cast just anything.
+ if (*m_TypeInfo == *inFunctor.m_TypeInfo) {
+ // This just does the type cast and the compare/
+ return Compare(
+ static_cast<Q3DStudio::CFunctorObject1<TObjectType, TFirstArg> *>(&inFunctor));
+ } else {
+ // return false if we are the wrong type.
+ return false;
+ }
+ }
+
+protected:
+ bool Compare(Q3DStudio::CFunctorObject1<TObjectType, TFirstArg> *inFunctor)
+ {
+ // Don't compare the Args
+ return (m_Object == (*inFunctor).m_Object) && (m_Method == (*inFunctor).m_Method);
+ }
+};
+} // namespace Q3DStudio
+
+#endif // __UICFunctor_H__ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/UICId.cpp b/src/Authoring/Common/Code/UICId.cpp
new file mode 100644
index 00000000..f95eac10
--- /dev/null
+++ b/src/Authoring/Common/Code/UICId.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "UICId.h"
+#include "UICTime.h"
+
+namespace Q3DStudio {
+
+//====================================================================
+/**
+ * Constructor .
+ * Initialize the GUID to Zero.
+ */
+CId::CId()
+ : m_Key(Q3DStudio::UUID_ZERO)
+{
+}
+
+//====================================================================
+/**
+ * Constructor. The local Key will get initialized to the Value represented by the string.
+ * @param inStringId is an ID in the form of a string.
+ *
+ */
+CId::CId(wchar_t *inStringId)
+{
+ Q3DStudio::CString theString = inStringId;
+ FromString(theString);
+}
+
+//====================================================================
+/**
+ * Constructor.
+ * @param inId is an ID to initialize from.
+ */
+CId::CId(const CId &inId)
+{
+ m_Key.GuidPacked.Data1 = inId.m_Key.GuidPacked.Data1;
+ m_Key.GuidPacked.Data2 = inId.m_Key.GuidPacked.Data2;
+ m_Key.GuidPacked.Data3 = inId.m_Key.GuidPacked.Data3;
+ m_Key.GuidPacked.Data4 = inId.m_Key.GuidPacked.Data4;
+}
+
+CId::CId(const GUID &inGUID)
+{
+ m_Key.GuidStd.Data1 = inGUID.Data1;
+ m_Key.GuidStd.Data2 = inGUID.Data2;
+ m_Key.GuidStd.Data3 = inGUID.Data3;
+ ::memcpy(m_Key.GuidStd.Data4, inGUID.Data4, sizeof(inGUID.Data4));
+}
+
+CId::CId(long in1, long in2, long in3, long in4)
+{
+ m_Key.GuidPacked.Data1 = in1;
+ m_Key.GuidPacked.Data2 = in2;
+ m_Key.GuidPacked.Data3 = in3;
+ m_Key.GuidPacked.Data4 = in4;
+}
+
+//====================================================================
+/**
+ * Generate a new Key
+ *
+ */
+void CId::Generate()
+{
+ // Generate unique UUID that works the same way on all platforms. We can't use QUuid as the
+ // generated UUID on non-Windows platforms many times fills the packed Data4 with 0,
+ // which is considered invalid by the rest of the application
+ static long s_LastMilliSecs = 0;
+ Q3DStudio::CTime theTime = Q3DStudio::CTime::Now( );
+ long theCurrentMilliSecs = theTime.GetMilliSecs( );
+
+ // Don't do this more than once in a 10ms period.
+ if ( s_LastMilliSecs != theCurrentMilliSecs )
+ {
+ s_LastMilliSecs = theCurrentMilliSecs;
+ ::srand( (unsigned)( theCurrentMilliSecs ) );
+ }
+
+ // ::rand is 16 bits, GUID is 128 bits, smear random bits over the whole GUID
+ m_Key.GuidPacked.Data1 = ::rand();
+ m_Key.GuidPacked.Data1 <<= 16;
+ m_Key.GuidPacked.Data1 |= ::rand();
+
+ m_Key.GuidPacked.Data2 = ::rand();
+ m_Key.GuidPacked.Data2 <<= 16;
+ m_Key.GuidPacked.Data2 |= ::rand();
+
+ m_Key.GuidPacked.Data3 = ::rand();
+ m_Key.GuidPacked.Data3 <<= 16;
+ m_Key.GuidPacked.Data3 |= ::rand();
+
+ m_Key.GuidPacked.Data4 = ::rand();
+ m_Key.GuidPacked.Data4 <<= 16;
+ m_Key.GuidPacked.Data4 |= ::rand();
+}
+
+//====================================================================
+/**
+ * Convert this CId to a GUID.
+ * @return a GUID struct.
+ */
+GUID CId::Convert() const
+{
+ GUID theThis;
+
+ theThis.Data1 = m_Key.GuidStd.Data1;
+ theThis.Data2 = m_Key.GuidStd.Data2;
+ theThis.Data3 = m_Key.GuidStd.Data3;
+ ::memcpy(theThis.Data4, m_Key.GuidStd.Data4, sizeof(m_Key.GuidStd.Data4));
+
+ return theThis;
+}
+
+//====================================================================
+/**
+ * Compare two CIds.
+ * @param inRVal is the Right side CId.
+ * @return True if they were equal.
+ */
+bool CId::operator==(const CId &inRVal) const
+{
+ bool theResult = ((m_Key.GuidPacked.Data1 == inRVal.m_Key.GuidPacked.Data1)
+ && (m_Key.GuidPacked.Data2 == inRVal.m_Key.GuidPacked.Data2)
+ && (m_Key.GuidPacked.Data3 == inRVal.m_Key.GuidPacked.Data3)
+ && (m_Key.GuidPacked.Data4 == inRVal.m_Key.GuidPacked.Data4));
+
+ return theResult;
+}
+
+//====================================================================
+/**
+ * Compare two CIds.
+ * @param inRVal is the Right side CId.
+ * @return True if they were equal.
+ */
+bool CId::operator==(const Q3DStudio::UUID &inRVal) const
+{
+ bool theResult = ((m_Key.GuidPacked.Data1 == inRVal.GuidPacked.Data1)
+ && (m_Key.GuidPacked.Data2 == inRVal.GuidPacked.Data2)
+ && (m_Key.GuidPacked.Data3 == inRVal.GuidPacked.Data3)
+ && (m_Key.GuidPacked.Data4 == inRVal.GuidPacked.Data4));
+
+ return theResult;
+}
+
+//====================================================================
+/**
+ * Compare two CIds for not equal.
+ * @param inRVal is the Right side CId.
+ * @return True if they were equal.
+ */
+bool CId::operator!=(const CId &inRVal) const
+{
+ return !(*this == inRVal);
+}
+
+//====================================================================
+/**
+ * Compare if this CId is less than the Right Size CId.
+ * @param inRVal is the Right side CId.
+ * @return True if this CId is Less than.
+ */
+bool CId::operator<(const CId &inRVal) const
+{
+ // const Q3DStudio::TGUIDPacked& theLVal = m_Key.GuidPacked;
+ // const Q3DStudio::TGUIDPacked& theRVal = inRVal.m_Key.GuidPacked;
+ // return !( theLVal.Data1 >= theRVal.Data1 &&
+ // theLVal.Data2 >= theRVal.Data2 &&
+ // theLVal.Data3 >= theRVal.Data3 &&
+ // theLVal.Data4 >= theRVal.Data4 );
+
+ bool theResult = false;
+
+ if (m_Key.GuidPacked.Data1 < inRVal.m_Key.GuidPacked.Data1) {
+ theResult = true;
+ }
+ // If it is equal then move on to the next element.
+ else if (m_Key.GuidPacked.Data1 == inRVal.m_Key.GuidPacked.Data1) {
+ if (m_Key.GuidPacked.Data2 < inRVal.m_Key.GuidPacked.Data2) {
+ theResult = true;
+ }
+ // If it is equal then move on to the next element.
+ else if (m_Key.GuidPacked.Data2 == inRVal.m_Key.GuidPacked.Data2) {
+ if (m_Key.GuidPacked.Data3 < inRVal.m_Key.GuidPacked.Data3) {
+ theResult = true;
+ } else if (m_Key.GuidPacked.Data3 == inRVal.m_Key.GuidPacked.Data3) {
+ if (m_Key.GuidPacked.Data4 < inRVal.m_Key.GuidPacked.Data4) {
+ theResult = true;
+ }
+ }
+ }
+ }
+ return theResult;
+}
+
+//====================================================================
+/**
+ * Set this Cid equal to the Right Side CId.
+ * @param inRVal is the Right side CId.
+ * @return this CId.
+ */
+CId &CId::operator=(const CId &inRVal)
+{
+ m_Key.GuidPacked.Data1 = inRVal.m_Key.GuidPacked.Data1;
+ m_Key.GuidPacked.Data2 = inRVal.m_Key.GuidPacked.Data2;
+ m_Key.GuidPacked.Data3 = inRVal.m_Key.GuidPacked.Data3;
+ m_Key.GuidPacked.Data4 = inRVal.m_Key.GuidPacked.Data4;
+
+ return *this;
+}
+//====================================================================
+/**
+ * Convert this CId into a String.
+ * @return The String version of this CId.
+ */
+Q3DStudio::CString CId::ToString() const
+{
+ Q3DStudio::CString theGuidStr;
+ theGuidStr.Format(_UIC("{%08X-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
+ m_Key.GuidStd.Data1, m_Key.GuidStd.Data2, m_Key.GuidStd.Data3,
+ m_Key.GuidStd.Data4[0], (unsigned long)m_Key.GuidStd.Data4[1],
+ (unsigned long)m_Key.GuidStd.Data4[2], (unsigned long)m_Key.GuidStd.Data4[3],
+ (unsigned long)m_Key.GuidStd.Data4[4], (unsigned long)m_Key.GuidStd.Data4[5],
+ (unsigned long)m_Key.GuidStd.Data4[6], (unsigned long)m_Key.GuidStd.Data4[7]);
+
+ return theGuidStr;
+}
+
+//====================================================================
+/**
+ * Convert this CId into the Incomming String.
+ * @param inStringId is a CId represented as a String.
+ * @return This CId.
+ */
+CId &CId::FromString(const Q3DStudio::CString &inStringId)
+{
+ unsigned long theData[8];
+ const wchar_t *theBuffer = (const wchar_t *)inStringId;
+
+ // All of the %02X formats get scaned into a 32bit long so we have to convert down below....
+ long theFields = ::swscanf(theBuffer, L"{%08x-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ &m_Key.GuidStd.Data1, &m_Key.GuidStd.Data2, &m_Key.GuidStd.Data3,
+ &theData[0], &theData[1], &theData[2], &theData[3], &theData[4],
+ &theData[5], &theData[6], &theData[7]);
+
+ if (theFields == 11) // magic number
+ {
+ // This is where we convert the 32 values into unsigned chars.
+ for (long theIndex = 0; theIndex < 8; ++theIndex) {
+ m_Key.GuidStd.Data4[theIndex] = static_cast<unsigned char>(theData[theIndex]);
+ }
+ } else {
+ // If we didn't read in all the fields, zero out the key
+ m_Key = Q3DStudio::UUID_ZERO;
+ }
+
+ return *this;
+}
+
+bool CId::IsZero() const
+{
+ return (*this == Q3DStudio::UUID_ZERO);
+}
+
+CId::operator GUID() const
+{
+ return Convert();
+}
+};
diff --git a/src/Authoring/Common/Code/UICId.h b/src/Authoring/Common/Code/UICId.h
new file mode 100644
index 00000000..a6b2eb63
--- /dev/null
+++ b/src/Authoring/Common/Code/UICId.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDEED_UICID
+#define INCLUDEED_UICID
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+
+#include "UICString.h"
+#include <map>
+#ifdef _WIN32
+#include <guiddef.h>
+#else
+#include "PlatformTypes.h"
+#endif
+
+namespace Q3DStudio {
+
+typedef struct _TGuidStd
+{
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+} TGUIDStd;
+
+typedef struct _TGuidPacked
+{
+ unsigned long Data1;
+ unsigned long Data2;
+ unsigned long Data3;
+ unsigned long Data4;
+} TGUIDPacked;
+
+union UUID {
+ // uuid_t leach;
+ TGUIDStd GuidStd;
+ TGUIDPacked GuidPacked;
+};
+
+// {E5D7768B-9111-45bc-98E6-9B0C44C0B1B6}
+static const UUID UUID_ZERO = {{ 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }};
+
+class CId
+{
+public:
+ CId();
+ CId(wchar_t *inStringId);
+ CId(const CId &inId);
+ CId(const GUID &inGUID);
+ CId(long in1, long in2, long in3, long in4);
+ void Generate();
+ GUID Convert() const;
+
+ bool operator==(const CId &inRVal) const;
+ bool operator==(const Q3DStudio::UUID &inRVal) const;
+ bool operator!=(const CId &inRVal) const;
+ CId &operator=(const CId &inRVal);
+ bool operator<(const CId &inRVal) const;
+ bool IsZero() const;
+ operator GUID() const;
+ // Not perfected yet!
+
+ Q3DStudio::CString ToString() const;
+ CId &FromString(const Q3DStudio::CString &inStringId);
+
+ operator TGUIDPacked &() { return m_Key.GuidPacked; }
+ operator const TGUIDPacked &() const { return m_Key.GuidPacked; }
+
+private:
+ UUID m_Key;
+};
+
+typedef std::map<Q3DStudio::CId, Q3DStudio::CId> TIDIDMap;
+
+} // End if namespace Q3DStudio
+#endif
diff --git a/src/Authoring/Common/Code/UICLargeInteger.h b/src/Authoring/Common/Code/UICLargeInteger.h
new file mode 100644
index 00000000..56d26a56
--- /dev/null
+++ b/src/Authoring/Common/Code/UICLargeInteger.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+// ================ PORTABLE 64-bit INTEGER ==================
+
+#ifdef _MSC_VER
+typedef __int64 TLarge; ///< 64-bit signed integer
+typedef unsigned __int64 TULarge; ///< 64-bit unsigned integer
+#else
+typedef long long TLarge; ///< 64-bit signed integer
+typedef unsigned long long TULarge; ///< 64-bit unsigned integer
+#endif
diff --git a/src/Authoring/Common/Code/UICMacros.h b/src/Authoring/Common/Code/UICMacros.h
new file mode 100644
index 00000000..fa97ca44
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMacros.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+#include <stddef.h>
+
+// ================ PLATFORM RECOGNITION ======================
+// Defines WIN32 when running on Windows
+#if defined(__WIN32__) && !defined(WIN32)
+#define WIN32
+#endif
+
+// ================ DEBUG DETECTION ======================
+#if defined(_DEBUG) && !defined(DEBUG)
+#define DEBUG
+#endif
+
+#ifdef DEBUG
+#define CHECK_BOUNDS // CHECK_BOUNDS affects the way an item is retrieved from container objects
+//# define USE_MEMORY_MANAGER // uses the fluid_studios memmgr.h
+#ifndef TRACK_OBJECT_COUNTS
+#define TRACK_OBJECT_COUNTS
+#endif
+#endif
+
+// Items to be removed before release
+#define PERFORM_PROFILE // include the profiler in the build
+
+// ====================== NULL ===========================
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+//==============================================================================
+// UICTODO Development Macro
+// Usage:
+//
+// "#pragma UICTODO(Message)" yields "__FILE__>(__LINE__) : To Do - <Message>"
+//
+// in the Build Pane of the Output Window
+//
+// For example:
+// #pragma UICTODO(SDJ, 11/12/00, Clean up this code) might result in
+// C:\Code\Project\File.cpp(20) : [ 11/12/00 ] SDJ - Clean up this code
+//
+// Double-clicking this line opens the specified file to the specified line in
+// the VC++ IDE.
+//
+// NOTE!!! Only use when you know you will fix it the next check-in. The
+// Last TODO macro was abused when people just left comments left and right.
+//
+//==============================================================================
+#define chSTR(x) #x
+#define chSTR2(x) chSTR(x)
+#define UICTODO(author, date, description) \
+ message(__FILE__ "(" chSTR2(__LINE__) "): [ " #date " ] " #author " - " #description)
+
+template <typename T, size_t N>
+char (&_ArraySizeHelper(T (&array)[N]))[N];
+#define _arraysize(array) (sizeof(_ArraySizeHelper(array)))
+
+// Old and disabled:
+#define TODO(author, date, description)
+
+//==============================================================================
+/**
+ * Lambda-type macro that simplifies iteration over collections.
+ * @param VAR theVariable iterating across the collection
+ * @param COL theCollection being iterated on
+ * @note Copyright (c) 2003 Eric Niebler
+ * @waring This macro forces us to turn off compiler warnings for:
+ * "warning C4706: assignment within conditional expression".
+ * This is unfortunate but the positive impact in readability
+ * makes this sacrifice worth it.
+ *
+ * For iterating over collections. Collections can be arrays, null-terminated
+ * strings, or STL containers including std::string. The loop variable can be
+ * a value or reference. For example: @code
+std::list<long> theLongList( stuff );
+FOR_EACH( long& theLong, theLongList )
+{
+ // *** loop body goes here ***
+ // theLong is a read-write reference to each long in theLongList
+} @endcode
+ * Alternately, you can declare the loop variable first, so you can access it
+ * after the loop finishes. Obviously, if you do it this way, then the loop
+ * variable cannot be a reference: @code
+long theLong;
+FOR_EACH( theLong, theLongList )
+{ ... } @endcode
+ */
+#define FOR_EACH(VAR, COL) \
+ if (::std::for_each::static_any_t _for_each_cur = ::std::for_each::begin(COL, 0)) { \
+ } else if (::std::for_each::static_any_t _for_each_end = ::std::for_each::end(COL, 0)) { \
+ } else \
+ for (bool _for_each_continue = true; \
+ _for_each_continue && !::std::for_each::done(_for_each_cur, _for_each_end, COL, 0); \
+ _for_each_continue ? ::std::for_each::next(_for_each_cur, COL, 0) : (void)&COL) \
+ if (_for_each_continue = false) { \
+ } else \
+ for (VAR = ::std::for_each::extract(_for_each_cur, COL, 0); !_for_each_continue; \
+ _for_each_continue = true)
+
+#ifdef _WIN32
+// See warning in method comment above, but not for Mac, Codewarrior fails the build process.
+#pragma warning(disable : 4706) // "assignment within conditional expression"
+#endif
diff --git a/src/Authoring/Common/Code/UICMath.cpp b/src/Authoring/Common/Code/UICMath.cpp
new file mode 100644
index 00000000..37d7e1f8
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMath.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMath.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const float PI = 3.1415926535897932384626433832795f;
+const float EPSILON = 0.0001f;
+const float SQREPSILON = 0.000001f;
+const float DTOR = PI / 180.0f;
+const float RTOD = 180.0f / PI;
+
+// EngineeringTask (MF 09/29/2004) AKMath source disabled until header is working
+
+#ifdef MATTIAS_OFF /////////////////////////////////////////////@#$%^&*(#$%^&*()#$%^&*()#$%&^*()_
+
+const float CMatrix::s_Identity[16] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
+
+//==============================================================================
+// EULER ANGLES
+//==============================================================================
+static inline unsigned int GetSafe(unsigned int uiOrder)
+{
+ static unsigned int aiSafe[] = { 0, 1, 2, 0 };
+ return (aiSafe[uiOrder & 0x3]);
+}
+
+static inline unsigned int GetNext(unsigned int uiOrder)
+{
+ static unsigned int aiNext[] = { 1, 2, 0, 1 };
+ return (aiNext[uiOrder & 0x3]);
+}
+
+static inline void GetOrderData(unsigned int uiOrder, int &i, int &j, int &k, int &h, int &n,
+ int &s, int &f)
+{
+ f = uiOrder & 0x1;
+ uiOrder >>= 1;
+ s = uiOrder & 0x1;
+ uiOrder >>= 1;
+ n = uiOrder & 0x1;
+ uiOrder >>= 1;
+ i = GetSafe(uiOrder & 0x3);
+ j = GetNext(i + n);
+ k = GetNext(i + 1 - n);
+ h = s ? k : i;
+}
+
+CQuaternion &CQuaternion::operator=(const CEulerAngles &inEulerAngles)
+{
+ // From Ken Shoemake in "Graphics Gems IV", Academic Press, 1994
+ float fAngle[3] = { inEulerAngles.m_Angle.x, inEulerAngles.m_Angle.y, inEulerAngles.m_Angle.z };
+ float a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+
+ GetOrderData(inEulerAngles.m_Order, i, j, k, h, n, s, f);
+
+ if (f == CEulerAngles::ROTATEFRAME) {
+ float t = fAngle[0];
+ fAngle[0] = fAngle[2];
+ fAngle[2] = t;
+ }
+
+ if (n == CEulerAngles::ODD) {
+ fAngle[1] = -fAngle[1];
+ }
+
+ ti = fAngle[0] * 0.5f;
+ tj = fAngle[1] * 0.5f;
+ th = fAngle[2] * 0.5f;
+
+ ci = ::cos(ti);
+ cj = ::cos(tj);
+ ch = ::cos(th);
+
+ si = ::sin(ti);
+ sj = ::sin(tj);
+ sh = ::sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == CEulerAngles::REPEAT) {
+ a[i] = cj * (cs + sc);
+ a[j] = sj * (cc + ss);
+ a[k] = sj * (cs - sc);
+ qw = cj * (cc - ss);
+ } else {
+ a[i] = cj * sc - sj * cs;
+ a[j] = cj * ss + sj * cc;
+ a[k] = cj * cs - sj * sc;
+ qw = cj * cc + sj * ss;
+ }
+
+ if (n == CEulerAngles::ODD)
+ a[j] = -a[j];
+
+ qx = a[CEulerAngles::X];
+ qy = a[CEulerAngles::Y];
+ qz = a[CEulerAngles::Z];
+
+ return Normalize();
+}
+
+CEulerAngles CQuaternion::ToEulerAngles(long inOrder) const
+{
+ // From Ken Shoemake in "Graphics Gems IV", Academic Press, 1994
+ CMatrix kM;
+ int i, j, k, h, n, s, f;
+ CVector3 kAngles;
+
+ kM.SetRotate(*this);
+ GetOrderData(inOrder, i, j, k, h, n, s, f);
+
+ if (s == CEulerAngles::REPEAT) {
+ float sy = ::sqrtf(kM[i][j] * kM[i][j] + kM[i][k] * kM[i][k]);
+
+ if (sy > EPSILON) {
+ kAngles.x = ::atan2(kM[i][j], kM[i][k]);
+ kAngles.y = ::atan2(sy, kM[i][i]);
+ kAngles.z = ::atan2(kM[j][i], -kM[k][i]);
+ } else {
+ kAngles.x = ::atan2(-kM[j][k], kM[j][j]);
+ kAngles.y = ::atan2(sy, kM[i][i]);
+ kAngles.z = 0.0f;
+ }
+ } else {
+ float cy = ::sqrt(kM[i][i] * kM[i][i] + kM[j][i] * kM[j][i]);
+
+ if (cy > EPSILON) {
+ kAngles.x = ::atan2f(kM[k][j], kM[k][k]);
+ kAngles.y = ::atan2f(-kM[k][i], cy);
+ kAngles.z = ::atan2f(kM[j][i], kM[i][i]);
+ } else {
+ kAngles.x = ::atan2f(-kM[j][k], kM[j][j]);
+ kAngles.y = ::atan2f(-kM[k][i], cy);
+ kAngles.z = 0.0f;
+ }
+ }
+
+ if (n == CEulerAngles::ODD) {
+ kAngles.x = -kAngles.x;
+ kAngles.y = -kAngles.y;
+ kAngles.z = -kAngles.z;
+ }
+ if (f == CEulerAngles::ROTATEFRAME) {
+ float t = kAngles.x;
+ kAngles.x = kAngles.z;
+ kAngles.z = t;
+ }
+
+ return CEulerAngles(kAngles, inOrder);
+}
+
+//==============================================================================
+// Stream operators for debugging
+//==============================================================================
+/*std::ostream &operator << ( std::ostream& inStream, const CVector3& inVector )
+{
+ inStream << "V( " << inVector.x << ", " << inVector.y << ", " << inVector.z << " )";
+ return inStream;
+}
+
+std::ostream &operator << ( std::ostream& inStream, const CQuaternion& inQuat )
+{
+ inStream << "Q( " << inQuat.qx << ", " << inQuat.qy << ", " << inQuat.qz << ", " <<
+inQuat.qw << " )";
+ return inStream;
+}
+
+std::ostream &operator << ( std::ostream& inStream, const CMatrix& inMatrix )
+{
+ inStream << "M( ( " << inMatrix.m[0][0] << ", " << inMatrix.m[0][1] << ", " <<
+inMatrix.m[0][2] << ", " << inMatrix.m[0][3] << " ),"
+ << " ( " << inMatrix.m[1][0] << ", " << inMatrix.m[1][1] << ", " <<
+inMatrix.m[1][2] << ", " << inMatrix.m[1][3] << " ),"
+ << " ( " << inMatrix.m[2][0] << ", " << inMatrix.m[2][1] << ", " <<
+inMatrix.m[2][2] << ", " << inMatrix.m[2][3] << " ),"
+ << " ( " << inMatrix.m[3][0] << ", " << inMatrix.m[3][1] << ", " <<
+inMatrix.m[3][2] << ", " << inMatrix.m[3][3] << " ) )";
+ return inStream;
+}*/
+
+#endif
+
+}; // namespace Q3DStudio
diff --git a/src/Authoring/Common/Code/UICMath.h b/src/Authoring/Common/Code/UICMath.h
new file mode 100644
index 00000000..3ff65173
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMath.h
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef __UICMATH_H__
+#define __UICMATH_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <math.h>
+#include <memory.h>
+
+#ifdef _WIN32
+// Generate these functions as inline code, not as function calls:
+#pragma intrinsic(sin, cos, sqrt, memcpy, memset, acos, fabs, abs)
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Template Macros
+//==============================================================================
+template <class T>
+inline const T &MIN(const T &inA, const T &inB)
+{
+ return inA < inB ? inA : inB;
+}
+template <class T>
+inline const T &MAX(const T &inA, const T &inB)
+{
+ return inA > inB ? inA : inB;
+}
+template <class T>
+inline const T &MIN3(const T &inA, const T &inB, const T &inC)
+{
+ return inA < inB ? MIN(inA, inC) : MIN(inB, inC);
+}
+template <class T>
+inline const T &MAX3(const T &inA, const T &inB, const T &inC)
+{
+ return inA > inB ? MAX(inA, inC) : MAX(inB, inC);
+}
+template <class T>
+inline const T CLAMP(const T &inVal, const T &inMin, const T &inMax)
+{
+ if (inVal <= inMin)
+ return inMin;
+ else if (inVal >= inMax)
+ return inMax;
+ return inVal;
+}
+template <class T>
+inline void MINMAX(const T &inA, const T &inB, T &outMin, T &outMax)
+{
+ if (inA < inB) {
+ outMin = inA;
+ outMax = inB;
+ } else {
+ outMin = inB;
+ outMax = inA;
+ }
+}
+
+//==============================================================================
+// Constants
+//==============================================================================
+extern const float PI; /// The venerable PI
+extern const float EPSILON; /// Maximum allowed error in float comparisons
+extern const float SQREPSILON; /// EPSILON squared is often used in distance computations
+extern const float
+ DTOR; /// Degrees to Radians - multiply with this factor to transform from "D to R"
+extern const float
+ RTOD; /// Radians to Degrees - multiply with this factor to transform from "R to D"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CVector3;
+class CEulerAngles;
+class CAxisAngle;
+class CQuaternion;
+class CMatrix;
+
+#ifdef MATTIAS_OFF
+//==============================================================================
+/**
+ * @class CVector3
+ * @brief Fast and minimal implementation of a 3D vector.
+ *
+ * This implementation of a 3D vector along with all the sibling and helper
+ * classes in the geometry section, try to strike a balance between clean code,
+ * ease-of-use and speed. Fields are public and most methods are inlined to
+ * give the impression of a very intelligent and capable structure. Heavier
+ * code such as intersections is encouraged to be added externally instead
+ * of here.
+ *
+ * The vector is a member of the geometry classes next to CMatrix, CRotation
+ * and CQuaternion.
+ * @see CMatrix
+ * @see CRotation
+ * @see CQuaternion
+ */
+class CVector3
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ float x; ///< X component of vector
+ float y; ///< Y component of vector
+ float z; ///< Z component of vector
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CVector3();
+ inline CVector3(const float inX, const float inY, const float inZ);
+ inline CVector3(const float inComponents[]);
+ inline CVector3(const CVector3 &inVector);
+
+public: // Initialization
+ inline CVector3 &Set(const float inX, const float inY, const float inZ);
+ inline CVector3 &Set(const float inComponents[]);
+ inline CVector3 &Set(const CVector3 &inVector);
+
+public: // Functions
+ inline float DistanceSquared(const CVector3 &inVector) const;
+ inline float Distance(const CVector3 &inVector) const;
+ inline float LengthSquared() const;
+ inline float Length() const;
+ inline float DotProduct(const CVector3 &inVector) const;
+ inline CVector3 CrossProduct(const CVector3 &inVector);
+ inline CVector3 &Normalize();
+ inline CVector3 &Minimize(const CVector3 &inVector);
+ inline CVector3 &Maximize(const CVector3 &inVector);
+ inline CVector3 &InterpolateLinear(const CVector3 &inDestVector, float inFactor);
+ inline CVector3 &Transform(const CMatrix &inMatrix, bool inTranslate = true);
+
+public: // Operators
+ inline bool operator==(const CVector3 &inVector) const;
+ inline bool operator!=(const CVector3 &inVector) const;
+ inline CVector3 operator+(const CVector3 &inVector) const;
+ inline CVector3 operator-(const CVector3 &inVector) const;
+ inline CVector3 operator*(float inFactor) const;
+ inline float operator*(const CVector3 &inVector) const;
+ inline CVector3 operator/(float inDivisor) const;
+ inline CVector3 operator%(const CVector3 &inVector) const;
+ inline CVector3 &operator=(const CVector3 &inVector);
+ inline CVector3 &operator+=(const CVector3 &inVector);
+ inline CVector3 &operator-=(const CVector3 &inVector);
+ inline CVector3 &operator*=(float inFactor);
+ inline CVector3 &operator/=(float inDivisor);
+ inline CVector3 &operator%=(const CVector3 &inVector);
+ inline CVector3 operator-() const;
+ inline float &operator[](int inIndex);
+ inline const float &operator[](int inIndex) const;
+};
+
+//==============================================================================
+/**
+ * @class CEulerAngles
+ * @brief Traditional yaw, pitch, roll representation of rotation.
+ * Quaternion can use this class to access and mutate it's state old-skool.
+ * All angles are in radians.
+ * @see CQuaternion
+ */
+class CEulerAngles
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ enum EEulerDefs {
+ X = 0, ///< Start with X axis
+ Y = 1, ///< Start with Y axis
+ Z = 2, ///< Start with Z axis
+
+ STATICFRAME = 0, ///< Keep axis globally oriented
+ ROTATEFRAME = 1, ///< Move axis with each operation
+
+ NOREPEAT = 0, ///< Use all three axis
+ REPEAT = 1, ///< Repeat first axis as last operation
+
+ EVEN = 0, ///< Normal XYZ or shifted (XYZ, YZX or ZXY)
+ ODD = 1, ///< Swap two last axis (XZY, YXZ or ZYX)
+ };
+
+#define GETEULERORDER(i, p, r, f) ((((((i << 1) + p) << 1) + r) << 1) + f)
+
+ enum EOrder {
+ XYZs = GETEULERORDER(X, EVEN, NOREPEAT, STATICFRAME),
+ XYXs = GETEULERORDER(X, EVEN, REPEAT, STATICFRAME),
+ XZYs = GETEULERORDER(X, ODD, NOREPEAT, STATICFRAME),
+ XZXs = GETEULERORDER(X, ODD, REPEAT, STATICFRAME),
+ YZXs = GETEULERORDER(Y, EVEN, NOREPEAT, STATICFRAME),
+ YZYs = GETEULERORDER(Y, EVEN, REPEAT, STATICFRAME),
+ YXZs = GETEULERORDER(Y, ODD, NOREPEAT, STATICFRAME),
+ YXYs = GETEULERORDER(Y, ODD, REPEAT, STATICFRAME),
+ ZXYs = GETEULERORDER(Z, EVEN, NOREPEAT, STATICFRAME),
+ ZXZs = GETEULERORDER(Z, EVEN, REPEAT, STATICFRAME),
+ ZYXs = GETEULERORDER(Z, ODD, NOREPEAT, STATICFRAME),
+ ZYZs = GETEULERORDER(Z, ODD, REPEAT, STATICFRAME),
+
+ ZYXr = GETEULERORDER(X, EVEN, NOREPEAT, ROTATEFRAME),
+ XYXr = GETEULERORDER(X, EVEN, REPEAT, ROTATEFRAME),
+ YZXr = GETEULERORDER(X, ODD, NOREPEAT, ROTATEFRAME),
+ XZXr = GETEULERORDER(X, ODD, REPEAT, ROTATEFRAME),
+ XZYr = GETEULERORDER(Y, EVEN, NOREPEAT, ROTATEFRAME),
+ YZYr = GETEULERORDER(Y, EVEN, REPEAT, ROTATEFRAME),
+ ZXYr = GETEULERORDER(Y, ODD, NOREPEAT, ROTATEFRAME),
+ YXYr = GETEULERORDER(Y, ODD, REPEAT, ROTATEFRAME),
+ YXZr = GETEULERORDER(Z, EVEN, NOREPEAT, ROTATEFRAME),
+ ZXZr = GETEULERORDER(Z, EVEN, REPEAT, ROTATEFRAME),
+ XYZr = GETEULERORDER(Z, ODD, NOREPEAT, ROTATEFRAME),
+ ZYZr = GETEULERORDER(Z, ODD, REPEAT, ROTATEFRAME)
+ };
+
+ CVector3 m_Angle;
+ long m_Order;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+ CEulerAngles(const CVector3 &inAngle, long inOrder = YXZr)
+ : m_Angle(inAngle)
+ , m_Order(inOrder)
+ {
+ }
+};
+
+//==============================================================================
+/**
+ * @class CAxisAngle
+ * @brief LookAt vector with roll component.
+ * Quaternion can use this class to access and mutate it's state. All angles
+ * are in radians.
+ * @see CQuaternion
+ */
+class CAxisAngle
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ CVector3 m_Axis; ///< The LookAt vector
+ float m_Angle; ///< Roll of LookAt vector in radians
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+ CAxisAngle(const CVector3 &inAxis, float inAngle)
+ : m_Axis(inAxis)
+ , m_Angle(inAngle)
+ {
+ }
+};
+
+//==============================================================================
+/**
+ * @class CQuaternion
+ * @brief Smart way to represent rotation in 3-space.
+ * @see CAxisAngle
+ * @see CEulerAngles
+*/
+class CQuaternion
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ float qx; ///< X portion of quaternion - Not related to x coordinate in any way
+ float qy; ///< Y portion of quaternion - Not related to y coordinate in any way
+ float qz; ///< Z portion of quaternion - Not related to z coordinate in any way
+ float qw; ///< W portion of quaternion
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CQuaternion();
+ inline CQuaternion(const float inX, const float inY, const float inZ, const float inW);
+ inline CQuaternion(const CQuaternion &inQuat);
+ inline CQuaternion(const CMatrix &inMatrix);
+ inline CQuaternion(const CAxisAngle &inAxisAngle);
+ inline CQuaternion(const CEulerAngles &inAngles);
+
+public: // Initialization
+ inline CQuaternion &Set(const float inX, const float inY, const float inZ, const float inW);
+ inline CQuaternion &Reset();
+
+public: // Functions
+ inline CQuaternion &Normalize();
+ inline CQuaternion &Invert();
+ inline float DotProduct(const CQuaternion &inQuat) const;
+ inline CQuaternion Slerp(const CQuaternion &inQuatA, const CQuaternion &inQuatB,
+ float inFactor);
+
+public: // Converters
+ inline CMatrix &ToMatrix(CMatrix &outMatrix) const;
+ inline CAxisAngle &ToAxisAngle(CAxisAngle &outAxisAngle) const;
+ CEulerAngles ToEulerAngles(long inOrder = CEulerAngles::XYZs) const;
+
+public: // Operators
+ inline CQuaternion &operator=(const CQuaternion &inQuat);
+ inline CQuaternion &operator=(const CMatrix &inMatrix);
+ inline CQuaternion &operator=(const CAxisAngle &inAxisAngle);
+ CQuaternion &operator=(const CEulerAngles &inEulerAngles);
+ inline bool operator==(const CQuaternion &inQuat) const;
+ inline bool operator!=(const CQuaternion &inQuat) const;
+ inline CQuaternion operator+(const CQuaternion &inQuat) const;
+ inline CQuaternion &operator+=(const CQuaternion &inQuat);
+ inline CQuaternion operator*(const CQuaternion &inQuat) const;
+ inline CQuaternion operator*(float inFactor) const;
+ inline CQuaternion &operator*=(const CQuaternion &inQuat);
+ inline CQuaternion &operator*=(float inFactor);
+
+ inline CVector3 operator*(const CVector3 &inVector) const;
+};
+
+//==============================================================================
+/**
+ * @class CMatrix
+ * @brief A row major matrix for 3D transformation.
+ * Matrix[row][column]
+ *<code>
+ *
+ * (see code for correct formatting of matrices)
+ * | 0 1 2 3 | or | 00 01 02 03 | or | Xx Xy Xz w | <br>
+ * | 4 5 6 7 | | 10 11 12 13 | | Yx Yy Yz w | <br>
+ * | 8 9 A B | | 20 21 22 23 | | Zx Zy Zz w | <br>
+ * | C D E F | | 30 31 32 33 | | Tx Ty Tz w | <br>
+ * </code>
+ * Rotations are concatenated in the the following order: YXZ
+ * All rotations are clockwise when viewed down the positive axis
+ * towards the origin.
+ */
+class CMatrix
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ float m[4][4]; ///< 16 elements in a 4 x 4
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CMatrix();
+ inline CMatrix(const CMatrix &inMatrix);
+ inline CMatrix(const float inComponents[]);
+
+public: // Initialization
+ inline CMatrix &Zero();
+ inline CMatrix &Identity();
+
+ inline CMatrix &Set(const CMatrix &inMatrix);
+ inline CMatrix &Set(const float inComponents[]);
+ inline CMatrix &Set(const CVector3 &inTranslation, const CEulerAngles &inRotation,
+ const CVector3 &inScale, const CVector3 &inPivot);
+
+ inline CMatrix &SetTranslate(const CVector3 &inTranslate);
+ inline CMatrix &SetRotate(const CQuaternion &inRotation);
+ inline CMatrix &SetScale(const CVector3 &inScale);
+ inline CMatrix &SetFrustum(const bool inOrthographic, const float inNear, const float inFar,
+ const float inLeft, const float inTop, const float inRight,
+ const float inBottom);
+
+public: // Functions
+ inline bool IsIdentity() const;
+ inline bool IsAffine() const;
+
+ inline CMatrix &Translate(const CVector3 &inTranslate);
+ inline CMatrix &Rotate(const CQuaternion &inRotation);
+ inline CMatrix &Scale(const CVector3 &inScale);
+ inline CMatrix &Transpose();
+ inline float Invert();
+ inline CMatrix &MultiplyAffine(const CMatrix &inMatrix);
+
+public: // Operators
+ inline CMatrix &operator=(const CMatrix &inMatrix);
+ inline bool operator==(const CMatrix &inMatrix) const;
+ inline bool operator!=(const CMatrix &inMatrix) const;
+ inline float *operator[](int inRow);
+ inline const float *operator[](int inRow) const;
+
+public: // Static common matrices
+ static const float s_Identity[16]; ///< Enabling fast initialization from static identity matrix
+};
+
+// Stream operators for easy debugging
+// std::ostream &operator<<( std::ostream& inStream, const CVector3& inVector );
+// std::ostream &operator<<( std::ostream& inStream, const CQuaternion& inQuat );
+// std::ostream &operator<<( std::ostream& inStream, const CMatrix& inMatrix );
+
+// Implementation
+#include "Vector3.inl"
+#include "Quaternion.inl"
+#include "Matrix.inl"
+
+#endif // MATTIAS_OFF
+
+} // namespace Q3DStudio
+
+#endif //__UICMATH_H_
diff --git a/src/Authoring/Common/Code/UICMemory.cpp b/src/Authoring/Common/Code/UICMemory.cpp
new file mode 100644
index 00000000..5de8bde6
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMemory.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+//#include <stdlib.h>
+#include "UICMemory.h"
+//#include "UICSynch.h"
+
+namespace Q3DStudio {
+
+long s_DebugMemoryTracker = 0;
+
+//====================================================================
+/**
+ * General error method that needs more work.
+ */
+void CMemory::Error()
+{
+ throw;
+}
+
+//====================================================================
+/**
+ * Allocation wrapper that performs some error checking.
+ * @param inSize is the requested amount of memory in bytes
+ * @return a pointer to allocated heap memory
+ */
+void *CMemory::Allocate(long inSize)
+{
+ if (0 == inSize) {
+ return 0;
+ } else {
+ void *theMemory = ::malloc(inSize);
+ if (0 == theMemory) {
+ Error();
+ }
+ return theMemory;
+ }
+}
+
+//====================================================================
+/**
+ * Reallocates memory previously allocated using CMemory.
+ * @param inMemory is the old allocated memory
+ * @param inSize is the new requested size in bytes
+ * @return a pointer to reallocated heap memory
+ */
+void *CMemory::Reallocate(void *inMemory, long inSize)
+{
+ if (0 == inSize) {
+ Free(inMemory);
+ return 0;
+ } else if (0 == inMemory) {
+ return Allocate(inSize);
+ } else {
+ inMemory = ::realloc(inMemory, inSize);
+ if (0 == inMemory) {
+ Error();
+ }
+ return inMemory;
+ }
+}
+
+//====================================================================
+/**
+ * Frees memory previously allocated using CMemory.
+ * @param inMemory is the old allocated memory
+ */
+void CMemory::Free(void *inMemory)
+{
+ if (0 != inMemory)
+ ::free(inMemory);
+}
+
+//====================================================================
+/**
+ * Prevents framentation and optimizes memory allocation.
+ * Method rounds up the value given to optimize memory usage.
+ * These are the ranges and return values: 0-15 = 16, 16-31 = 32
+ * 32 - 4095 = next 64 factor, 4096+ = next 4096 factor.
+ * @param inSpaceNeeded is the requested amount of memory in bytes
+ * @return optimal memory allocation amount in bytes
+ */
+long CSharedMemory::Quantize(long inSpaceNeeded)
+{
+ static long theBigQuant = 4096;
+ static long theBigMask = ~4095;
+ static long theSmallQuant = 64;
+ static long theSmallMask = ~63;
+
+ if (inSpaceNeeded < 16)
+ return 16;
+ if (inSpaceNeeded < 32)
+ return 32;
+ if (inSpaceNeeded < 2048)
+ return (inSpaceNeeded + theSmallQuant) & theSmallMask;
+ else
+ return (inSpaceNeeded + theBigQuant) & theBigMask;
+}
+
+//====================================================================
+/**
+ * Allocate memory with reference count and length.
+ * CSharedMemory allocates room for a header that allows tracking of
+ * reference count and size of the buffer. Memory allocated using
+ * this method MUST be deallocated using the corresponding Free call.
+ * The void pointer returned can be used directly as if returned
+ * by CMemory::Allocate or new char[inSize].
+ * @param inSize is the requested amount of memory in bytes
+ * @return a pointer to allocated heap memory
+ */
+void *CSharedMemory::Allocate(long inSize)
+{
+ if (inSize <= 0)
+ CMemory::Error();
+
+ long theQuantizedSize = Quantize(inSize);
+ SSharedHeader *theSharedMemory =
+ static_cast<SSharedHeader *>(CMemory::Allocate(theQuantizedSize + sizeof(SSharedHeader)));
+
+ theSharedMemory->m_Size = inSize;
+ theSharedMemory->m_RefCount = 1;
+#ifdef DEBUG
+ theSharedMemory->m_Signature = UICMEM_HEADERSIG;
+#endif
+
+ // NULL terminate manually. Quantization ensures there is space for it.
+ reinterpret_cast<char *>(theSharedMemory + 1)[inSize] = 0;
+
+#ifdef DEBUG
+ s_DebugMemoryTracker += theQuantizedSize;
+#endif
+
+ return reinterpret_cast<void *>(theSharedMemory + 1);
+}
+
+//====================================================================
+/**
+ * Reallocates memory previously allocated using CSharedMemory.
+ * CMemory and CSharedMemory pointers or NOT interchangable and
+ * great care must be taken to call the correct Reallocate method.
+ * @param inMemory is the old allocated memory
+ * @param inSize is the new requested size in bytes
+ * @return a pointer to reallocated heap memory
+ */
+void *CSharedMemory::Reallocate(void *inMemory, long inSize)
+{
+ SSharedHeader *theSharedMemory = Header(inMemory);
+
+ if (inSize <= 0)
+ CMemory::Error();
+
+ long theNewQuantizedSize = Quantize(inSize);
+ long theOldQuantizedSize = Quantize(theSharedMemory->m_Size);
+ if (theNewQuantizedSize != theOldQuantizedSize) {
+ theSharedMemory = reinterpret_cast<SSharedHeader *>(
+ CMemory::Reallocate(theSharedMemory, theNewQuantizedSize + sizeof(SSharedHeader)));
+ }
+ theSharedMemory->m_Size = inSize;
+
+ // NULL terminate manually. Quantization ensures there is space for it.
+ reinterpret_cast<char *>(theSharedMemory + 1)[inSize] = 0;
+
+#ifdef DEBUG
+ s_DebugMemoryTracker += theNewQuantizedSize - theOldQuantizedSize;
+#endif
+
+ return reinterpret_cast<void *>(theSharedMemory + 1);
+}
+
+//====================================================================
+/**
+ * Frees memory previously allocated using CSharedMemory.
+ * @param inMemory is the old allocated memory
+ */
+void CSharedMemory::Free(void *inMemory)
+{
+ SSharedHeader *theSharedMemory = Header(inMemory);
+
+#ifdef DEBUG
+ s_DebugMemoryTracker -= Quantize(theSharedMemory->m_Size);
+#endif
+
+ CMemory::Free(theSharedMemory);
+}
+
+long CSharedMemory::AddRef(void *inMemory)
+{
+ return ++(*(RefCountAddress(inMemory)));
+} // { return pincrement( RefCountAddress( inMemory ) );
+ //}
+long CSharedMemory::SubRef(void *inMemory)
+{
+ return --(*(RefCountAddress(inMemory)));
+} // { return pdecrement( RefCountAddress( inMemory ) );
+ //}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Common/Code/UICMemory.h b/src/Authoring/Common/Code/UICMemory.h
new file mode 100644
index 00000000..a6559af2
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMemory.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef __UICMEMORY_H__
+#define __UICMEMORY_H__
+
+#include "UICMacros.h"
+
+namespace Q3DStudio {
+#define UICMEM_HEADERSIG 0xF00D
+
+//==============================================================================
+/**
+ * @class CMemory
+ * @brief Small wrapper around memory allocation.
+ * @see CSharedMemory
+ * @see SSharedHeader
+ */
+class CMemory
+{
+public:
+ static void *Allocate(long inSize);
+ static void *Reallocate(void *inMemory, long inSize);
+ static void Free(void *inMemory);
+ static void Error();
+};
+
+//==============================================================================
+/**
+ * @struct SSharedHeader
+ * @brief Block of code at the beginning of memory enabling refcounting.
+ * @see CMemory
+ * @see CSharedMemory
+ */
+struct SSharedHeader
+{
+#ifdef DEBUG
+ long m_Signature;
+#endif
+ long m_RefCount;
+ long m_Size;
+};
+
+//==============================================================================
+/**
+ * @class CSharedMemory
+ * @brief Lowlevel memory class that hides extra header info enabling refcounting.
+ * @see CMemory
+ * @see SSharedHeader
+ */
+class CSharedMemory
+{
+protected:
+#ifdef DEBUG
+ static void Validate(void *inMemory)
+ {
+ if ((reinterpret_cast<SSharedHeader *>(inMemory) - 1)->m_Size < 0
+ || UICMEM_HEADERSIG != (reinterpret_cast<SSharedHeader *>(inMemory) - 1)->m_Signature)
+ CMemory::Error();
+ }
+ static SSharedHeader *Header(void *inMemory)
+ {
+ Validate(inMemory);
+ return reinterpret_cast<SSharedHeader *>(inMemory) - 1;
+ }
+#else
+ // inline static void Validate( void* /*inMemory*/ ) {}
+ inline static SSharedHeader *Header(void *inMemory)
+ {
+ return reinterpret_cast<SSharedHeader *>(inMemory) - 1;
+ }
+#endif
+
+public:
+ inline static long *RefCountAddress(void *inMemory) { return &(Header(inMemory)->m_RefCount); }
+ inline static long GetSize(void *inMemory) { return Header(inMemory)->m_Size; }
+
+ static long AddRef(void *inMemory);
+ static long SubRef(void *inMemory);
+
+ static long Quantize(long inSpaceNeeded);
+
+ static void *Allocate(long inSize);
+ static void *Reallocate(void *inMemory, long inSize);
+ static void Free(void *inMemory);
+};
+} // namespace Q3DStudio
+#endif // __UICMEMORY_H__
diff --git a/src/Authoring/Common/Code/UICMessageBox.cpp b/src/Authoring/Common/Code/UICMessageBox.cpp
new file mode 100644
index 00000000..2a5cca62
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMessageBox.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "UICMessageBox.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMessageBox.h"
+
+#include <QMessageBox>
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUICMessageBox::CUICMessageBox()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CUICMessageBox::~CUICMessageBox()
+{
+}
+
+//==============================================================================
+/**
+ * Displays the modal message box to the user.
+ * @param inTitle Title of the message box
+ * @param inText Text to be displayed on the message box
+ * @param inIcon Icon to be displayed on the message box
+ * @param inParentWindow window to attach this dialog to.
+ */
+CUICMessageBox::EMessageBoxReturn
+CUICMessageBox::Show(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText, EMessageBoxIcon inIcon,
+ bool inShowCancel /*false*/,
+ CUICMessageBox::TPlatformWindow inParentWindow /*NULL*/)
+{
+ QMessageBox box(inParentWindow);
+ box.setWindowTitle(inTitle.toQString());
+ box.setText(inText.toQString());
+
+ switch (inIcon) {
+ case ICON_ERROR:
+ box.setIcon(QMessageBox::Critical);
+ break;
+ case ICON_WARNING:
+ box.setIcon(QMessageBox::Warning);
+ break;
+ case ICON_INFO:
+ box.setIcon(QMessageBox::Information);
+ break;
+ default:
+ break;
+ }
+
+ QMessageBox::StandardButtons buttons = QMessageBox::Ok;
+ if (inShowCancel)
+ buttons |= QMessageBox::Cancel;
+ box.setStandardButtons(buttons);
+
+ auto theButtonPressed = box.exec();
+ return theButtonPressed == QMessageBox::Ok ? MSGBX_OK : MSGBX_CANCEL;
+}
diff --git a/src/Authoring/Common/Code/UICMessageBox.h b/src/Authoring/Common/Code/UICMessageBox.h
new file mode 100644
index 00000000..ad126c96
--- /dev/null
+++ b/src/Authoring/Common/Code/UICMessageBox.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UIC_MESSAGE_BOX_H
+#define INCLUDED_UIC_MESSAGE_BOX_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICString.h"
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+QT_END_NAMESPACE
+
+#ifndef _WIN32
+#define IDOK 1
+#define IDCANCEL 2
+#define IDYES 6
+#define IDNO 7
+#define MB_ICONERROR 0x00000010L
+#define MB_ICONWARNING 0x00000030L
+#define MB_ICONINFORMATION 0x00000040L
+#else
+#include <WinUser.h>
+#endif
+
+//==============================================================================
+/**
+ * Generic cross-platform class for showing message boxes with an Ok and Cancel
+ * button
+ */
+class CUICMessageBox
+{
+public:
+ /// Return codes from the message box
+ enum EMessageBoxReturn { MSGBX_ERROR = 0, MSGBX_OK = IDOK, MSGBX_CANCEL = IDCANCEL };
+
+ /// Icons to be displayed on the message box
+ enum EMessageBoxIcon {
+ ICON_NONE = 0,
+ ICON_ERROR = MB_ICONERROR,
+ ICON_WARNING = MB_ICONWARNING,
+ ICON_INFO = MB_ICONINFORMATION
+ };
+
+ typedef QWidget* TPlatformWindow;
+
+ CUICMessageBox();
+ virtual ~CUICMessageBox();
+ static EMessageBoxReturn Show(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText,
+ EMessageBoxIcon inIcon, bool inShowCancel = false,
+ TPlatformWindow inParentWindow = NULL);
+
+protected:
+};
+
+#endif // INCLUDED_UIC_MESSAGE_BOX_H
diff --git a/src/Authoring/Common/Code/UICObjectCounter.cpp b/src/Authoring/Common/Code/UICObjectCounter.cpp
new file mode 100644
index 00000000..fafebbd6
--- /dev/null
+++ b/src/Authoring/Common/Code/UICObjectCounter.cpp
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICObjectCounter.h"
+
+TObjectCounterTracker UICObjectCounter::s_ObjectVector;
diff --git a/src/Authoring/Common/Code/UICObjectCounter.h b/src/Authoring/Common/Code/UICObjectCounter.h
new file mode 100644
index 00000000..d36440bf
--- /dev/null
+++ b/src/Authoring/Common/Code/UICObjectCounter.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __UICOBJECTCOUNTER_H__
+#define __UICOBJECTCOUNTER_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <vector>
+#include <string.h>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class UICObjectCounter;
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef std::vector<UICObjectCounter *> TObjectCounterTracker;
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+// If defined, track the object counts
+#ifdef TRACK_OBJECT_COUNTS
+
+#define DEFINE_OBJECT_COUNTER(classname) static UICObjectCounter s_ObjectCounter##classname;
+
+#define IMPLEMENT_OBJECT_COUNTER(classname) \
+ UICObjectCounter classname::s_ObjectCounter##classname(#classname, sizeof(classname));
+
+#define ADDTO_OBJECT_COUNTER(classname) classname::s_ObjectCounter##classname.Add();
+
+#define REMOVEFROM_OBJECT_COUNTER(classname) classname::s_ObjectCounter##classname.Remove();
+
+#define GET_OBJECT_COUNTER_COUNT(classname) (classname::s_ObjectCounter##classname.m_ObjectCount)
+
+#define GET_OBJECT_COUNTER_SIZE(classname) (classname::s_ObjectCounter##classname.m_ObjectSize)
+
+#define DEFINE_OBJECT_COUNTER_TRACKER(tracktype) \
+ extern TObjectCounterTracker s_ObjectCounterTracker##tracktype;
+
+#define IMPLEMENT_OBJECT_COUNTER_TRACKER(tracktype) \
+ TObjectCounterTracker s_ObjectCounterTracker##tracktype;
+
+#define TRACK_OBJECT_COUNTER(tracktype, classname) \
+ s_ObjectCounterTracker##tracktype.push_back(&classname::s_ObjectCounter##classname);
+
+#define GET_TRACK_OBJECT_COUNTER(tracktype) s_ObjectCounterTracker##tracktype
+
+// If not defined, do nothing
+#else
+
+#define DEFINE_OBJECT_COUNTER(classname)
+#define IMPLEMENT_OBJECT_COUNTER(classname)
+#define ADDTO_OBJECT_COUNTER(classname)
+#define REMOVEFROM_OBJECT_COUNTER(classname)
+#define GET_OBJECT_COUNTER_COUNT(classname)
+#define DEFINE_OBJECT_COUNTER_TRACKER(tracktype)
+#define IMPLEMENT_OBJECT_COUNTER_TRACKER(tracktype)
+#define TRACK_OBJECT_COUNTER(tracktype, classname)
+#define GET_TRACK_OBJECT_COUNTER(tracktype)
+
+#endif
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class UICObjectCounter
+ * @brief This class is used to track that object have been released.
+ *
+ * Use the macros to make the feature easy.
+ * The macros define a static variable. Each time the object is constructed,
+ * the count on the static variable in incremented, and decremented when it
+ * is destructed. When the static variable is destroyed, object counts are
+ * dumped out to the debugger.
+ */
+class UICObjectCounter
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+public:
+ long m_ObjectCount;
+ char m_ObjectName[256];
+ long m_ObjectSize;
+
+private:
+ static TObjectCounterTracker s_ObjectVector;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+public:
+ UICObjectCounter(const char *inName, long inClassSize)
+ : m_ObjectCount(0)
+ , m_ObjectSize(inClassSize)
+ {
+ ::strncpy(m_ObjectName, inName, sizeof(m_ObjectName) - 1);
+ m_ObjectName[::strlen(inName)] = 0;
+
+ s_ObjectVector.push_back(this);
+ }
+
+ ~UICObjectCounter()
+ {
+ if (m_ObjectCount > 0) {
+#ifdef WIN32
+#ifdef ATLTRACE
+ ATLTRACE("\t. . . with %ld unreleased %s objects.\n", m_ObjectCount, m_ObjectName);
+#endif
+#endif
+ }
+
+ else if (m_ObjectCount < 0) {
+#ifdef WIN32
+#ifdef ATLTRACE
+ ATLTRACE("\t. . . object counting error for %s (%ld).\n", m_ObjectName, m_ObjectCount);
+#endif
+#endif
+ }
+ if (s_ObjectVector.size()) {
+ TObjectCounterTracker::iterator theBegin = s_ObjectVector.begin();
+ TObjectCounterTracker::iterator theEnd = s_ObjectVector.end();
+ for (; theBegin != theEnd; ++theBegin) {
+ if (this == *theBegin) {
+ s_ObjectVector.erase(theBegin);
+ break;
+ }
+ }
+ }
+ }
+ void Add() { m_ObjectCount++; }
+ void Remove() { m_ObjectCount--; };
+};
+
+#endif // #ifndef __UICOBJECTCOUNTER_H__
diff --git a/src/Authoring/Common/Code/UICPoint.h b/src/Authoring/Common/Code/UICPoint.h
new file mode 100644
index 00000000..2bee5ba2
--- /dev/null
+++ b/src/Authoring/Common/Code/UICPoint.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __UICPOINT_H__
+#define __UICPOINT_H__
+
+#ifndef __PLATFORMCONVERSION_H__
+#include "PlatformConversion.h"
+#endif
+
+#include "UICPointBase.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* @class CPoint
+* @brief This class contains a Point
+*/
+//==============================================================================
+class CPoint : public CPointBase
+{
+public:
+ // Constructors
+ CPoint();
+ CPoint(int initX, int initY);
+ CPoint(const CPoint &initPt);
+#ifndef __PLATFORMCONVERSION_H__
+ CPoint(const UICPoint &initPt);
+ CPoint(const UICPoint *initPt);
+#endif
+
+ // Operations
+ void Offset(int xOffset, int yOffset);
+ void Offset(CPoint &point);
+#ifndef __PLATFORMCONVERSION_H__
+ void operator=(const UICPoint &srcPt);
+#endif
+ bool operator==(CPoint &point) const;
+ bool operator!=(CPoint &point) const;
+ void operator+=(CPoint &point);
+ void operator-=(CPoint &point);
+ void SetPoint(int X, int Y);
+
+ // Operators returning CPoint values
+ CPoint operator-() const;
+ CPoint operator+(CPoint &point) const;
+};
+
+// CPoint
+inline CPoint::CPoint()
+{
+}
+inline CPoint::CPoint(int initX, int initY)
+{
+ x = initX;
+ y = initY;
+}
+inline CPoint::CPoint(const CPoint &initPt)
+{
+ *(CPoint *)this = initPt;
+}
+#ifndef __PLATFORMCONVERSION_H__
+inline CPoint::CPoint(const UICPoint &initPt)
+{
+ CPlatformConversion::UICPointToCPoint(initPt, *this);
+}
+inline CPoint::CPoint(const UICPoint *initPt)
+{
+ CPlatformConversion::UICPointToCPoint(*initPt, *this);
+}
+#endif
+inline void CPoint::Offset(int xOffset, int yOffset)
+{
+ x += xOffset;
+ y += yOffset;
+}
+inline void CPoint::Offset(CPoint &point)
+{
+ x += point.x;
+ y += point.y;
+}
+#ifndef __PLATFORMCONVERSION_H__
+inline void CPoint::operator=(const UICPoint &srcPt)
+{
+ CPlatformConversion::UICPointToCPoint(srcPt, *this);
+}
+#endif
+inline bool CPoint::operator==(CPoint &point) const
+{
+ return (x == point.x && y == point.y);
+}
+inline bool CPoint::operator!=(CPoint &point) const
+{
+ return (x != point.x || y != point.y);
+}
+inline void CPoint::operator+=(CPoint &point)
+{
+ x += point.x;
+ y += point.y;
+}
+inline void CPoint::operator-=(CPoint &point)
+{
+ x -= point.x;
+ y -= point.y;
+}
+inline void CPoint::SetPoint(int X, int Y)
+{
+ x = X;
+ y = Y;
+}
+inline CPoint CPoint::operator-() const
+{
+ return CPoint(-x, -y);
+}
+inline CPoint CPoint::operator+(CPoint &point) const
+{
+ return CPoint(x + point.x, y + point.y);
+}
+
+} // namespace Q3DStudio
+
+#endif // __UICPOINT_H__
diff --git a/src/Authoring/Common/Code/UICPointBase.h b/src/Authoring/Common/Code/UICPointBase.h
new file mode 100644
index 00000000..2d127a3a
--- /dev/null
+++ b/src/Authoring/Common/Code/UICPointBase.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __UICPOINTBASE_H__
+#define __UICPOINTBASE_H__
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* @class CPointBase
+* @brief This class contains the data for Q3DStudio::CPoint
+*/
+//==============================================================================
+class CPointBase
+{
+public:
+ CPointBase()
+ : x(0)
+ , y(0)
+ {
+ }
+
+ long x;
+ long y;
+};
+
+} // namespace Q3DStudio
+
+#endif // __UICPOINTBASE_H__
diff --git a/src/Authoring/Common/Code/UICRect.h b/src/Authoring/Common/Code/UICRect.h
new file mode 100644
index 00000000..2de39317
--- /dev/null
+++ b/src/Authoring/Common/Code/UICRect.h
@@ -0,0 +1,417 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __UICRECT_H__
+#define __UICRECT_H__
+
+#ifndef __PLATFORMCONVERSION_H__
+#include "PlatformConversion.h"
+#endif
+
+#include "UICPoint.h"
+#include "UICRectBase.h"
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* @class CRect
+* @brief This class contains a Rect
+*/
+//==============================================================================
+class CRect : public CRectBase
+{
+public:
+ // Constructors
+ CRect();
+ CRect(int l, int t, int r, int b);
+
+ CRect(const CRect &srcRect);
+ CRect(const CRect *lpSrcRect);
+#ifndef __PLATFORMCONVERSION_H__
+ CRect(const UICRect &inRect);
+ CRect(const UICRect *inRect);
+#endif
+ CRect(CPoint &topLeft, CPoint &bottomRight);
+
+ // Attributes (in addition to CRect members)
+ int Width() const;
+ int Height() const;
+ CPoint &TopLeft();
+ CPoint &BottomRight();
+ const CPoint &TopLeft() const;
+ const CPoint &BottomRight() const;
+ CPoint CenterPoint() const;
+
+ // convert between CRect and CRect*/const CRect* (no need for &)
+ operator CRect *();
+ operator const CRect *() const;
+
+ bool IsRectEmpty() const;
+ bool IsRectNull() const;
+ bool PtInRect(CPoint &point) const;
+
+ // Operations
+ void SetRect(int x1, int y1, int x2, int y2);
+ void SetRect(CPoint &topLeft, CPoint &bottomRight);
+ void SetRectEmpty();
+ void CopyRect(const CRect *lpSrcRect);
+ bool EqualRect(const CRect *lpRect) const;
+
+ void InflateRect(int x, int y);
+ void InflateRect(const CRect *lpRect);
+ void InflateRect(int l, int t, int r, int b);
+ void DeflateRect(int x, int y);
+ void DeflateRect(const CRect *lpRect);
+ void DeflateRect(int l, int t, int r, int b);
+
+ void OffsetRect(int x, int y);
+ void OffsetRect(CPoint &point);
+ void NormalizeRect();
+
+ // absolute position of rectangle
+ void MoveToY(int y);
+ void MoveToX(int x);
+ void MoveToXY(int x, int y);
+ void MoveToXY(CPoint &point);
+
+ // operations that fill '*this' with result
+ bool IntersectRect(const CRect *lpRect1, const CRect *lpRect2);
+ bool UnionRect(const CRect *lpRect1, const CRect *lpRect2);
+ bool SubtractRect(const CRect *lpRectSrc1, const CRect *lpRectSrc2);
+
+ // Additional Operations
+ void operator=(const CRect &srcRect);
+#ifndef __PLATFORMCONVERSION_H__
+ void operator=(const UICRect &srcRect);
+#endif
+ bool operator==(const CRect &rect) const;
+ bool operator!=(const CRect &rect) const;
+ void operator+=(CPoint &point);
+ void operator+=(const CRect *lpRect);
+ void operator-=(CPoint &point);
+ void operator-=(const CRect *lpRect);
+ void operator&=(const CRect &rect);
+ void operator|=(const CRect &rect);
+
+ // Operators returning CRect values
+ CRect operator+(CPoint &point) const;
+ CRect operator-(CPoint &point) const;
+ CRect operator+(const CRect *lpRect) const;
+ CRect operator-(const CRect *lpRect) const;
+ CRect operator&(const CRect &rect2) const;
+ CRect operator|(const CRect &rect2) const;
+};
+
+// CRect
+inline CRect::CRect()
+{
+}
+inline CRect::CRect(int l, int t, int r, int b)
+{
+ left = l;
+ top = t;
+ right = r;
+ bottom = b;
+}
+inline CRect::CRect(const CRect &srcRect)
+{
+ CopyRect(&srcRect);
+}
+inline CRect::CRect(const CRect *lpSrcRect)
+{
+ CopyRect(lpSrcRect);
+}
+#ifndef __PLATFORMCONVERSION_H__
+inline CRect::CRect(const UICRect &inRect)
+{
+ CPlatformConversion::UICRectToCRect(inRect, *this);
+}
+inline CRect::CRect(const UICRect *inRect)
+{
+ CPlatformConversion::UICRectToCRect(*inRect, *this);
+}
+#endif
+inline CRect::CRect(CPoint &topLeft, CPoint &bottomRight)
+{
+ left = topLeft.x;
+ top = topLeft.y;
+ right = bottomRight.x;
+ bottom = bottomRight.y;
+}
+inline int CRect::Width() const
+{
+ return right - left;
+}
+inline int CRect::Height() const
+{
+ return bottom - top;
+}
+inline CPoint &CRect::TopLeft()
+{
+ return *((CPoint *)this);
+}
+inline CPoint &CRect::BottomRight()
+{
+ return *((CPoint *)this + 1);
+}
+inline const CPoint &CRect::TopLeft() const
+{
+ return *((CPoint *)this);
+}
+inline const CPoint &CRect::BottomRight() const
+{
+ return *((CPoint *)this + 1);
+}
+inline CPoint CRect::CenterPoint() const
+{
+ return CPoint((left + right) / 2, (top + bottom) / 2);
+}
+inline CRect::operator CRect *()
+{
+ return this;
+}
+inline CRect::operator const CRect *() const
+{
+ return this;
+}
+inline bool CRect::IsRectEmpty() const
+{
+ return (Width() <= 0 && Height() <= 0);
+}
+inline bool CRect::IsRectNull() const
+{
+ return (left == 0 && right == 0 && top == 0 && bottom == 0);
+}
+inline bool CRect::PtInRect(CPoint &point) const
+{
+ return (point.x >= left && point.x <= right && point.y >= top && point.y <= bottom);
+}
+inline void CRect::SetRect(int x1, int y1, int x2, int y2)
+{
+ left = x1;
+ top = y1;
+ right = x2;
+ bottom = y2;
+}
+inline void CRect::SetRect(CPoint &topLeft, CPoint &bottomRight)
+{
+ left = topLeft.x;
+ top = topLeft.y;
+ right = bottomRight.x;
+ bottom = bottomRight.y;
+}
+inline void CRect::SetRectEmpty()
+{
+ left = 0;
+ top = 0;
+ right = 0;
+ bottom = 0;
+}
+inline void CRect::CopyRect(const CRect *lpSrcRect)
+{
+ left = lpSrcRect->left;
+ top = lpSrcRect->top;
+ right = lpSrcRect->right;
+ bottom = lpSrcRect->bottom;
+}
+inline bool CRect::EqualRect(const CRect *lpRect) const
+{
+ return (left == lpRect->left && top == lpRect->top && right == lpRect->right
+ && bottom == lpRect->bottom);
+}
+inline void CRect::InflateRect(int x, int y)
+{
+ InflateRect(x, y, x, y);
+}
+inline void CRect::DeflateRect(int x, int y)
+{
+ InflateRect(-x, -y, -x, -y);
+}
+inline void CRect::OffsetRect(int x, int y)
+{
+ left += x;
+ top += y;
+ right += x;
+ bottom += y;
+}
+inline void CRect::OffsetRect(CPoint &point)
+{
+ OffsetRect(point.x, point.y);
+}
+inline void CRect::operator=(const CRect &srcRect)
+{
+ CopyRect(&srcRect);
+}
+#ifndef __PLATFORMCONVERSION_H__
+inline void CRect::operator=(const UICRect &srcRect)
+{
+ CPlatformConversion::UICRectToCRect(srcRect, *this);
+}
+#endif
+inline bool CRect::operator==(const CRect &rect) const
+{
+ return EqualRect(&rect);
+}
+inline bool CRect::operator!=(const CRect &rect) const
+{
+ return !EqualRect(&rect);
+}
+inline void CRect::operator+=(CPoint &point)
+{
+ OffsetRect(point.x, point.y);
+}
+inline void CRect::operator+=(const CRect *lpRect)
+{
+ InflateRect(lpRect);
+}
+inline void CRect::operator-=(CPoint &point)
+{
+ OffsetRect(-point.x, -point.y);
+}
+inline void CRect::operator-=(const CRect *lpRect)
+{
+ DeflateRect(lpRect);
+}
+inline void CRect::operator&=(const CRect &rect)
+{
+ IntersectRect(this, &rect);
+}
+inline void CRect::operator|=(const CRect &rect)
+{
+ UnionRect(this, &rect);
+}
+inline CRect CRect::operator+(CPoint &pt) const
+{
+ CRect rect(*this);
+ rect.OffsetRect(pt.x, pt.y);
+ return rect;
+}
+inline CRect CRect::operator-(CPoint &pt) const
+{
+ CRect rect(*this);
+ rect.OffsetRect(-pt.x, -pt.y);
+ return rect;
+}
+inline CRect CRect::operator+(const CRect *lpRect) const
+{
+ CRect rect(this);
+ rect.InflateRect(lpRect);
+ return rect;
+}
+inline CRect CRect::operator-(const CRect *lpRect) const
+{
+ CRect rect(this);
+ rect.DeflateRect(lpRect);
+ return rect;
+}
+inline CRect CRect::operator&(const CRect &rect2) const
+{
+ CRect rect;
+ rect.IntersectRect(this, &rect2);
+ return rect;
+}
+inline CRect CRect::operator|(const CRect &rect2) const
+{
+ CRect rect;
+ rect.UnionRect(this, &rect2);
+ return rect;
+}
+
+inline void CRect::NormalizeRect()
+{
+ int nTemp;
+ if (left > right) {
+ nTemp = left;
+ left = right;
+ right = nTemp;
+ }
+ if (top > bottom) {
+ nTemp = top;
+ top = bottom;
+ bottom = nTemp;
+ }
+}
+
+inline void CRect::MoveToY(int y)
+{
+ bottom = Height() + y;
+ top = y;
+}
+inline void CRect::MoveToX(int x)
+{
+ right = Width() + x;
+ left = x;
+}
+inline void CRect::MoveToXY(int x, int y)
+{
+ MoveToX(x);
+ MoveToY(y);
+}
+inline void CRect::MoveToXY(CPoint &pt)
+{
+ MoveToX(pt.x);
+ MoveToY(pt.y);
+}
+
+inline void CRect::InflateRect(const CRect *lpRect)
+{
+ left -= lpRect->left;
+ top -= lpRect->top;
+ right += lpRect->right;
+ bottom += lpRect->bottom;
+}
+
+inline void CRect::InflateRect(int l, int t, int r, int b)
+{
+ left -= l;
+ top -= t;
+ right += r;
+ bottom += b;
+}
+
+inline void CRect::DeflateRect(const CRect *lpRect)
+{
+ left += lpRect->left;
+ top += lpRect->top;
+ right -= lpRect->right;
+ bottom -= lpRect->bottom;
+}
+
+inline void CRect::DeflateRect(int l, int t, int r, int b)
+{
+ left += l;
+ top += t;
+ right -= r;
+ bottom -= b;
+}
+
+} // namespace Q3DStudio
+
+#endif // __UICRECT_H__
diff --git a/src/Authoring/Common/Code/UICRectBase.h b/src/Authoring/Common/Code/UICRectBase.h
new file mode 100644
index 00000000..79b505ce
--- /dev/null
+++ b/src/Authoring/Common/Code/UICRectBase.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __UICRECTBASE_H__
+#define __UICRECTBASE_H__
+
+namespace Q3DStudio {
+//==============================================================================
+/**
+* @class CRectBase Base class that contains the data for a Q3DStudio::CRect.
+*/
+//==============================================================================
+class CRectBase
+{
+public:
+ CRectBase()
+ : left(0)
+ , top(0)
+ , right(0)
+ , bottom(0)
+ {
+ }
+
+ long left;
+ long top;
+ long right;
+ long bottom;
+};
+
+} // namespace Q3DStudio
+
+#endif // __UICRECTBASE_H__
diff --git a/src/Authoring/Common/Code/UICSharedPtr.h b/src/Authoring/Common/Code/UICSharedPtr.h
new file mode 100644
index 00000000..40ed7993
--- /dev/null
+++ b/src/Authoring/Common/Code/UICSharedPtr.h
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __UICSHAREDPTR_H__
+#define __UICSHAREDPTR_H__
+
+#pragma once
+
+#include "AutoPtr.h"
+#include "UICExceptions.h"
+//==============================================================================
+// Class
+//==============================================================================
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* @class CReferenceCount
+* @brief This class provides base reference counting for the CSharedPtr.
+*
+* This class simply maintains a reference count.
+*
+* @note No checking is performed for releasing the reference to many times.
+*/
+class CReferenceCount
+{
+protected:
+ long m_RefCount; ///< Referenced count variable
+
+ // Construction
+public:
+ CReferenceCount(long inStartRefCount = 0)
+ : m_RefCount(inStartRefCount)
+ {
+ }
+ virtual ~CReferenceCount()
+ {
+#ifdef _DEBUG
+ if (m_RefCount != 0)
+ throw;
+#endif
+ }
+
+ // Operations
+public:
+ // Add a reference
+ long Add() { return ++m_RefCount; }
+ // Release a reference
+ long Release() { return --m_RefCount; }
+
+ // Access
+public:
+ // Is this object referenced
+ bool IsReferenced() { return (m_RefCount > 0); }
+ // Is this the only reference on the object
+ bool IsUnique() { return (m_RefCount == 1); }
+ // Return the count of references on the object
+ long Count() { return m_RefCount; }
+};
+
+//==============================================================================
+/**
+* @class CSharedPtr
+* @brief This class provides ref counted sharing of any pointer.
+*/
+template <class T>
+class CSharedPtr
+{
+protected:
+ class SSharedObject
+ {
+ public:
+ SSharedObject(T *inPointer = NULL)
+ : m_Pointer(inPointer)
+ {
+ }
+
+ CAutoMemPtr<T> m_Pointer; ///< Pointer to the object type
+ CReferenceCount m_RefCount; ///< Referenced count object
+ private:
+ SSharedObject(const SSharedObject &inOther);
+ SSharedObject &operator=(const SSharedObject &inOther);
+ };
+
+ SSharedObject *m_Object;
+
+public:
+ // Constructor
+ // May use assignment to aquire a shared pointer object
+ CSharedPtr()
+ : m_Object(NULL)
+ {
+ }
+
+ // Copy constructor
+ // Starts ownership of the pointer
+ CSharedPtr(T *inPointer)
+ : m_Object(NULL)
+ {
+ if (inPointer) {
+ Assign(new SSharedObject(inPointer));
+ }
+ }
+
+ // Copy constructor
+ // Shares ownership of the pointer
+ CSharedPtr(const CSharedPtr<T> &inSource)
+ : m_Object(NULL)
+ {
+ Assign(inSource.m_Object);
+ }
+
+ // Destructor
+ // Deletes the pointer when the ref count is down to zero
+ ~CSharedPtr() { Release(); }
+
+ // Assignment operator
+ // Uses the same pointer and increments the ref count
+ CSharedPtr &operator=(const CSharedPtr<T> &inSource)
+ {
+ Assign(inSource.m_Object);
+ return *this;
+ }
+
+ // Assignment operator
+ // Starts ownership of the pointer
+ // Do not use this on a pointer that is already shared!!!!
+ CSharedPtr &operator=(T *inPointer)
+ {
+ if (inPointer != NULL) {
+ Assign(new SSharedObject(inPointer));
+ } else // inPointer == NULL
+ {
+ Release();
+ }
+
+ return *this;
+ }
+
+ /**
+ * DANGEROUS!!! This will simply change all of the ptrs that are shared
+ * from this one instance. Not recommended, as it changes an object's data from
+ * underneath the object without its knowledge...
+ * @param inNewPtr the new hotness.
+ * @param outOldPtr the old and busted.
+ */
+ /*
+ void ReplacePtr( T* inNewPtr, T*& outOldPtr )
+ {
+ UIC_THROWNULL( m_Object, E_FAIL );
+ outOldPtr = m_Object->m_Pointer;
+ m_Object->m_Pointer = inNewPtr;
+ //And the damage has been done...
+ }
+ */
+ void SwapPtr(CSharedPtr<T> &inSwapPtr)
+ {
+ UIC_THROWNULL(m_Object, E_FAIL);
+ UIC_THROWNULL(inSwapPtr.m_Object, E_FAIL);
+
+ // If the incoming ptr is not us
+ if (&inSwapPtr != this) {
+ CAutoMemPtr<T> theHoldPtr;
+
+ // Swap the pointers underneath.
+ theHoldPtr = m_Object->m_Pointer;
+ m_Object->m_Pointer = inSwapPtr.m_Object->m_Pointer;
+ inSwapPtr.m_Object->m_Pointer = theHoldPtr;
+ }
+ }
+
+ // Operator overloads
+ operator T *() const
+ {
+ if (m_Object) {
+ return m_Object->m_Pointer;
+ }
+ return NULL;
+ }
+
+ T *Get() const
+ {
+ if (m_Object) {
+ return m_Object->m_Pointer;
+ }
+ return NULL;
+ }
+
+ T *operator->() const
+ {
+ if (m_Object) {
+ return m_Object->m_Pointer;
+ }
+ return NULL;
+ }
+
+ // Comparison
+ bool operator==(const CSharedPtr<T> &inSource) const
+ {
+ if (m_Object != NULL && inSource.m_Object != NULL) {
+ return m_Object->m_Pointer == inSource.m_Object->m_Pointer;
+ }
+ return m_Object == inSource.m_Object;
+ }
+
+ // Comparison
+ bool operator==(T *inPointer) const
+ {
+ if (m_Object) {
+ return (m_Object->m_Pointer == inPointer);
+ }
+ return inPointer == NULL;
+ }
+
+ // Comparison
+ bool operator!=(const CSharedPtr<T> &inSource) const
+ {
+ if (m_Object != NULL && inSource.m_Object != NULL) {
+ return m_Object->m_Pointer != inSource.m_Object->m_Pointer;
+ }
+ return m_Object != inSource.m_Object;
+ }
+
+ // Comparison
+ bool operator!=(T *inPointer) const
+ {
+ if (m_Object) {
+ return (m_Object->m_Pointer != inPointer);
+ }
+ return inPointer != NULL;
+ }
+
+ //==============================================================================
+ /**
+ * Performs a deep copy of the contained pointer.
+ */
+ void Copy(const CSharedPtr<T> &inSource)
+ {
+ // Throw on NULL
+ UIC_THROWFALSE(m_Object != NULL && inSource.m_Object != NULL, E_FAIL);
+ if (m_Object != inSource.m_Object) {
+ *m_Object->m_Pointer = *inSource.m_Object->m_Pointer;
+ }
+ }
+
+ //==============================================================================
+ /**
+ * Performs a deep copy of the contained pointer.
+ *
+ * Assumes the pointer has a method named "Clone" that returns a newly
+ * allocated copy of the pointer to the class.
+ *
+ * @return The cloned pointer.
+ */
+ T *Clone()
+ {
+ T *theClone = NULL;
+ if (m_Object->m_Pointer)
+ theClone = m_Object->m_Pointer->Clone();
+ return theClone;
+ }
+
+ bool IsNull() { return (m_Object == NULL); }
+
+ // Reference count methods
+ bool IsReferenced() { return ((m_Object) ? (m_Object->m_RefCount.IsReferenced()) : false); }
+ bool IsUnique() { return ((m_Object) ? (m_Object->m_RefCount.IsUnique()) : true); }
+ long Count() { return ((m_Object) ? (m_Object->m_RefCount.Count()) : 0); }
+
+protected:
+ // Safe way to add references
+ void Add()
+ {
+ // Throw on NULL
+ if (m_Object)
+ m_Object->m_RefCount.Add();
+ }
+
+ // Safe way to release references
+ void Release()
+ {
+ // Throw on NULL
+ if (m_Object) {
+ long theRefCount = m_Object->m_RefCount.Release();
+ if (theRefCount <= 0) {
+ if (theRefCount < 0)
+ throw;
+
+ delete m_Object;
+ }
+ }
+ m_Object = NULL;
+ }
+
+ // Assigns the smart pointer and ref counts it
+ void Assign(SSharedObject *inObject)
+ {
+ if (m_Object != inObject) {
+ if (m_Object)
+ Release();
+ // Postcondition: m_Object is NULL
+
+ m_Object = inObject;
+
+ // Use the passed in ref count
+ if (m_Object) {
+ // Increment the reference count
+ Add();
+ }
+ }
+ }
+};
+
+} // namespace Q3DStudio
+
+#endif // __UICSHAREDPTR_H__
diff --git a/src/Authoring/Common/Code/UICString.cpp b/src/Authoring/Common/Code/UICString.cpp
new file mode 100644
index 00000000..1aa5c41e
--- /dev/null
+++ b/src/Authoring/Common/Code/UICString.cpp
@@ -0,0 +1,987 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICString.h"
+#include "UICMath.h"
+#include "UICMemory.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <QString>
+
+namespace Q3DStudio {
+
+#ifdef DEBUG
+SSharedHeader s_EmptyUICStringBuffer[2] = { { UICMEM_HEADERSIG, 0, sizeof(UICChar) }, { 0, 0, 0 } };
+#else
+SSharedHeader s_EmptyUICStringBuffer[2] = { { 0, sizeof(UICChar) }, { 0, 0 } };
+#endif
+
+UICChar *s_EmptyUICString = reinterpret_cast<UICChar *>(s_EmptyUICStringBuffer + 1);
+
+IMPLEMENT_OBJECT_COUNTER(CString)
+
+//====================================================================
+/**
+ * Memory allocator.
+ * @param inSize is the requested capacity of the string
+ */
+void CString::Allocate(long inLength)
+{
+ m_UICData =
+ reinterpret_cast<UICChar *>(CSharedMemory::Allocate((inLength + 1) * sizeof(UICChar)));
+
+ // NULL terminate string and dirty
+ m_UICData[inLength] = 0;
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Memory re-allocator.
+ * @param inSize is the new requested capacity of the string
+ */
+void CString::Reallocate(long inLength)
+{
+ m_UICData = reinterpret_cast<UICChar *>(
+ CSharedMemory::Reallocate(m_UICData, (inLength + 1) * sizeof(UICChar)));
+
+ // NULL terminate string and dirty
+ m_UICData[inLength] = 0;
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Memory releaser that resets the data pointer to the empty string.
+ */
+void CString::Free()
+{
+ if (m_UICData != s_EmptyUICString) {
+ CSharedMemory::Free(m_UICData);
+ m_UICData = s_EmptyUICString;
+ DirtyBuffers();
+ }
+}
+
+//====================================================================
+/**
+ * SyncCharBuffer.
+ */
+void CString::SyncCharBuffer() const
+{
+ // NULL buffers means it was never created or was dirtied
+ if (m_CharData == NULL) {
+ // Create new buffer equally as long but char based
+ m_CharData = CreateBuffer<char>();
+ }
+}
+
+//====================================================================
+/**
+ * SyncWideBuffer.
+ */
+void CString::SyncWideBuffer() const
+{
+ // NULL buffers means it was never created or was dirtied
+ if (m_WideData == NULL) {
+ // Create new buffer equally as long but char based
+ m_WideData = CreateBuffer<wchar_t>();
+ }
+}
+
+//====================================================================
+/**
+ * DirtyBuffers.
+ */
+void CString::DirtyBuffers()
+{
+ m_CharData = NULL;
+ m_WideData = NULL;
+#ifdef WIN32
+ m_MultiData = NULL;
+#endif
+}
+
+//====================================================================
+/**
+ * Construct a composite from two plain char strings.
+ * This is equivalent to make inString1 + inString2.
+ * @param inString1 is the first part of the string
+ * @param inLength1 is the length of the first string
+ * @param inString2 is the second part of the string
+ * @param inLength2 is the length of the second string
+ */
+CString::CString(const UICChar *inString1, long inLength1, const UICChar *inString2, long inLength2)
+ : m_UICData(s_EmptyUICString)
+{
+ ADDTO_OBJECT_COUNTER(CString)
+
+ if (inLength1 <= 0) {
+ Assign(inString2, inLength2);
+ } else if (inLength2 <= 0) {
+ Assign(inString1, inLength1);
+ } else {
+ Allocate(inLength1 + inLength2);
+ ::memcpy(m_UICData, inString1, inLength1 * sizeof(UICChar));
+ ::memcpy(m_UICData + inLength1, inString2, inLength2 * sizeof(UICChar));
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+* Insert an UICChar string into this string.
+* @param inPosition is the offset into this string where the char string should be inserted
+* @param inString is the string to be inserted
+* @param inLength is the length of the desired string
+*/
+void CString::UICInsert(long inPosition, const UICChar *inCharString, long inLength)
+{
+ if (ENDOFSTRING == inLength)
+ inLength = StrLen(inCharString);
+
+ long theCurrentLength = Length();
+ if (inLength > 0 && inPosition >= 0 && inPosition <= theCurrentLength) {
+ if (0 == theCurrentLength) {
+ Assign(inCharString, inLength);
+ } else {
+ SetLength(theCurrentLength + inLength);
+
+ long t = Length() - inPosition - inLength;
+ UICChar *p = m_UICData + inPosition;
+
+ if (t > 0)
+ ::memmove(p + inLength, p, t * sizeof(UICChar));
+ ::memmove(p, inCharString, inLength * sizeof(UICChar));
+ }
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Add the given UICChar string at the end of this string.
+ * @param inCharString is the pointer to the string to be added
+ * @param inLength is the length of the string to be added
+ */
+void CString::UICConcat(const UICChar *inCharString, long inLength)
+{
+ if (ENDOFSTRING == inLength)
+ inLength = StrLen(inCharString);
+
+ if (IsEmpty()) {
+ Assign(inCharString, inLength);
+ } else if (inLength > 0) {
+ long theOldLength = Length();
+
+ // We must check this before calling SetLength(), since
+ // the buffer pointer may be changed during reallocation
+ if (m_UICData == inCharString) {
+ SetLength(theOldLength + inLength);
+ ::memmove(m_UICData + theOldLength, m_UICData, inLength * sizeof(UICChar));
+ } else {
+ SetLength(theOldLength + inLength);
+ ::memmove(m_UICData + theOldLength, inCharString, inLength * sizeof(UICChar));
+ }
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Add the given string at the end of this string.
+ * @param inString is the string to be added
+ */
+void CString::Concat(const CString &inString)
+{
+ if (IsEmpty()) {
+ Assign(inString);
+ } else if (inString.Length() > 0) {
+ UICConcat(inString.m_UICData, inString.Length());
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Add the given char at the end of this string.
+ * @param inChar is the char to be added
+ */
+void CString::Concat(char inChar) // char = bad
+{
+ if (IsEmpty()) {
+ Assign(&inChar, 1);
+ } else {
+ SetLength(Length() + 1);
+ m_UICData[Length() - 1] = inChar;
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Add the given char at the end of this string.
+ * @param inChar is the char to be added
+ */
+void CString::Concat(UICChar inChar) // char = bad
+{
+ if (IsEmpty()) {
+ Assign(&inChar, 1);
+ } else {
+ SetLength(Length() + 1);
+ m_UICData[Length() - 1] = inChar;
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Make string a copy the given char string and release old buffer
+ * if needed. This looks similar to the Initialize line of methods
+ * but Assign takes care of detaching and releasing any previously
+ * used buffers.
+ * @see Initialize
+ * @param inCharString is the pointer to the string
+ * @param inLength is the length of the string
+ */
+void CString::UICAssign(const UICChar *inCharString, long inLength)
+{
+ if (ENDOFSTRING == inLength)
+ inLength = StrLen(inCharString);
+
+ if (!IsEmpty() && inLength > 0) {
+ if (CSharedMemory::RefCountAddress(m_UICData)[0] > 1) {
+ UICChar *theOldData = m_UICData;
+ Allocate(inLength);
+ ::memcpy(m_UICData, inCharString, inLength * sizeof(UICChar));
+ --(CSharedMemory::RefCountAddress(theOldData)[0]);
+ } else {
+ Reallocate(inLength);
+ ::memmove(m_UICData, inCharString, inLength * sizeof(UICChar));
+ }
+ } else {
+ Clear();
+ if (inLength != 0) {
+ Allocate(inLength);
+ ::memmove(m_UICData, inCharString, inLength * sizeof(UICChar));
+ }
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Make string a copy the given string and release old buffer if needed.
+ * @param inString is the string to be copied
+ */
+void CString::Assign(const CString &inString)
+{
+ if (m_UICData != inString.m_UICData) {
+ Clear();
+ if (inString.m_UICData != NULL) {
+ m_UICData = inString.m_UICData;
+ CSharedMemory::AddRef(m_UICData);
+ DirtyBuffers();
+ }
+ }
+}
+
+//====================================================================
+/**
+ * Make string a copy the given char string and release old buffer
+ * if needed. This looks similar to the Initialize line of methods
+ * but Assign takes care of detaching and releasing any previously
+ * used buffers.
+ * @see Initialize
+ * @param inCharString is the pointer to the string
+ * @param inLength is the length of the string
+ */
+bool CString::UICCompare(const UICChar *inCharString, long inLength, bool inCaseSensitive) const
+{
+ if (ENDOFSTRING == inLength)
+ inLength = StrLen(inCharString);
+
+ long theMinLength = MIN(inLength, Length());
+ long theIndex = 0;
+
+ // Two differently size strings are not equal no matter what
+ if (inLength != Length())
+ return false;
+
+ // Consider two zero length strings equal
+ if (0 == theMinLength)
+ return true;
+
+ if (inCaseSensitive) {
+ while (theIndex < theMinLength && inCharString[theIndex] == m_UICData[theIndex])
+ ++theIndex;
+ } else {
+ while (theIndex < theMinLength
+ && ToLower(inCharString[theIndex]) == ToLower(m_UICData[theIndex]))
+ ++theIndex;
+ }
+
+ // Equal if we scanned the whole string
+ return theIndex == theMinLength;
+}
+
+//====================================================================
+/**
+ * Copy constructor
+ * @param inString is the length of the string
+ */
+CString::CString(const CString &inString)
+ : m_UICData(s_EmptyUICString)
+{
+ ADDTO_OBJECT_COUNTER(CString)
+
+ Assign(inString);
+}
+
+//====================================================================
+/**
+ * Copy constructor
+ * @param inString is the length of the string
+ */
+CString::CString(char inChar)
+ : m_UICData(s_EmptyUICString)
+{
+ ADDTO_OBJECT_COUNTER(CString)
+
+ Assign(&inChar, 1);
+}
+
+//====================================================================
+/**
+ * Copy constructor
+ * @param inString is the length of the string
+ */
+CString::CString(UICChar inChar)
+ : m_UICData(s_EmptyUICString)
+{
+ ADDTO_OBJECT_COUNTER(CString)
+
+ Assign(&inChar, 1);
+}
+
+//====================================================================
+/**
+ * Compare the given char string to the buffer.
+ * MF: Needs more work to make consistent comparison of equal substrings.
+ */
+bool CString::operator<(const CString &inString) const
+{
+ long theMinLength = MIN(inString.Length(), Length());
+ return (::memcmp(m_UICData, inString.m_UICData, (theMinLength + 1) * sizeof(UICChar)) < 0);
+}
+
+#ifdef CHECK_BOUNDS
+//====================================================================
+/**
+ * Get the char at the indicated location.
+ * This will cause the buffer to split which may be an expensive operation.
+ * @param inIndex is the location of the desired char
+ * @return a char at the indecated index.
+ */
+UICChar &CString::operator[](long inIndex)
+{
+ Unique();
+ return m_UICData[inIndex];
+}
+#endif
+
+//====================================================================
+/**
+ * Detach from the buffer and release it if this string is the
+ * last reference.
+ */
+void CString::Clear()
+{
+ if (!IsEmpty() && 0 == CSharedMemory::SubRef(m_UICData))
+ Free();
+
+ m_UICData = s_EmptyUICString;
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Make a unique copy of the buffer and detach from the old buffer.
+ * Single-threaded version.
+ * @return a pointer to the new buffer
+ */
+UICChar *CString::Unique()
+{
+ if (!IsEmpty() && CSharedMemory::RefCountAddress(m_UICData)[0] > 1) {
+ UICChar *theOldData = m_UICData;
+ Allocate(Length());
+ ::memcpy(m_UICData, theOldData, Length() * sizeof(UICChar));
+ --(CSharedMemory::RefCountAddress(theOldData)[0]);
+ }
+
+ DirtyBuffers();
+ return m_UICData;
+}
+
+//====================================================================
+/**
+ * Set the length of the sting. The content is undefined past the
+ * length of the old string length if expanding.
+ * @param inNewLength is the new length of the string
+ */
+void CString::SetLength(long inNewLength)
+{
+ long theCurrentLength = Length();
+
+ if (inNewLength < 0)
+ return;
+
+ // If becoming empty
+ if (0 == inNewLength)
+ Clear();
+
+ // If otherwise was empty before
+ else if (0 == theCurrentLength)
+ Allocate(inNewLength);
+
+ // If length is not changing, return a unique string
+ else if (inNewLength == theCurrentLength)
+ Unique();
+
+ else {
+ if (CSharedMemory::RefCountAddress(m_UICData)[0] > 1) {
+ UICChar *theOldData = m_UICData;
+ Allocate(inNewLength);
+ ::memcpy(m_UICData, theOldData, MIN(theCurrentLength, inNewLength) * sizeof(UICChar));
+ --(CSharedMemory::RefCountAddress(theOldData)[0]);
+ } else {
+ Reallocate(inNewLength);
+ }
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * Return the length of the string.
+ * @return the length of the string
+ */
+long CString::Length() const
+{
+ return CSharedMemory::GetSize(m_UICData) / sizeof(UICChar) - 1;
+}
+
+//====================================================================
+/**
+ * Examine how many strings share the buffer of this string.
+ * @return how many strings share the buffer of this string
+ */
+long CString::RefCount() const
+{
+ return CSharedMemory::RefCountAddress(m_UICData)[0];
+}
+
+//====================================================================
+/**
+ * Extract a section of this string.
+ * @param inStart is the offset from the beginning of this string
+ * @param inLength is the length of the desired string
+ * @return a new string
+ */
+CString CString::Extract(long inStart, long inLength) const
+{
+ CString theReturn;
+
+ if (Length() > 0 && inStart >= 0 && inStart < Length()) {
+ long theMinLength = MIN(inLength, Length() - inStart);
+
+ if (inStart == 0 && theMinLength == Length()) {
+ theReturn = *this;
+ } else {
+ if (theMinLength == ENDOFSTRING)
+ theMinLength = Length() - inStart;
+
+ // Added to prevent memory leak - this class sucks
+ theReturn.Clear();
+ theReturn.SetLength(theMinLength);
+ // theReturn.Allocate( theMinLength );
+ ::memmove(theReturn.m_UICData, m_UICData + inStart, theMinLength * sizeof(UICChar));
+ // theReturn.m_UICData[ theMinLength ] = 0;
+ }
+ }
+ return theReturn;
+ ;
+}
+
+CString CString::Mid(int nFirst) const
+{
+ return Extract(nFirst);
+}
+
+CString CString::Mid(int nFirst, int nCount) const
+{
+ return Extract(nFirst, nCount);
+}
+
+CString CString::Left(int nCount) const
+{
+ return Extract(0, nCount);
+}
+
+CString CString::Right(int nCount) const
+{
+ return Extract(Length() - nCount);
+}
+
+//====================================================================
+/**
+ * Delete a section of this string.
+ * @param inStart is the offset from the beginning of this string
+ * @param inLength is the number of charachter to be deleted
+ */
+void CString::Delete(long inStart, long inLength)
+{
+ long theCurrentLength = Length();
+ if (inLength == ENDOFSTRING)
+ inLength = theCurrentLength - inStart;
+
+ if (inStart >= 0 && inStart < theCurrentLength && inLength > 0) {
+ if (inStart + inLength >= theCurrentLength)
+ inLength = theCurrentLength - inStart;
+
+ Unique();
+ ::memmove(m_UICData + inStart, m_UICData + inStart + inLength,
+ (theCurrentLength - inStart - inLength) * sizeof(UICChar));
+
+ SetLength(theCurrentLength - inLength);
+ }
+ DirtyBuffers();
+}
+
+//====================================================================
+/**
+ * ToUpper.
+ */
+CString &CString::ToUpper()
+{
+ Unique();
+
+ long theLength = Length();
+ for (long theScanner = 0; theScanner < theLength; ++theScanner)
+ if (m_UICData[theScanner] >= 'a' && m_UICData[theScanner] <= 'z')
+ m_UICData[theScanner] = static_cast<UICChar>(m_UICData[theScanner] + 'A' - 'a');
+ DirtyBuffers();
+ return *this;
+}
+
+//====================================================================
+/**
+ * ToLower.
+ */
+CString &CString::ToLower()
+{
+ Unique();
+
+ long theLength = Length();
+ for (long theScanner = 0; theScanner < theLength; ++theScanner)
+ if (m_UICData[theScanner] >= 'A' && m_UICData[theScanner] <= 'Z')
+ m_UICData[theScanner] = static_cast<UICChar>(m_UICData[theScanner] + 'a' - 'A');
+ DirtyBuffers();
+ return *this;
+}
+
+//====================================================================
+/**
+ * Trims all white-space characters from the right side of the string.
+ * White-space characters include newlines, tabs, spaces, and line
+ * feeds.
+ */
+void CString::TrimRight()
+{
+ const wchar_t *theString = *this;
+ long theLength = Length();
+ long theIndex = theLength - 1;
+
+ while ((theIndex > 0) && ((theString[theIndex] == '\t') || (theString[theIndex] == '\r')
+ || (theString[theIndex] == '\n') || (theString[theIndex] == ' '))) {
+ --theIndex;
+ }
+
+ if (theIndex > 0 && theIndex != ENDOFSTRING)
+ Delete(theIndex + 1, ENDOFSTRING);
+}
+
+//====================================================================
+/**
+ * Trims all white-space characters from the left side of the string.
+ * White-space characters include newlines, tabs, spaces, and line
+ * feeds.
+ */
+void CString::TrimLeft()
+{
+ const wchar_t *theString = *this;
+ long theIndex = 0;
+ long theLength = Length();
+
+ while ((theIndex < theLength)
+ && ((theString[theIndex] == '\t') || (theString[theIndex] == '\r')
+ || (theString[theIndex] == '\n') || (theString[theIndex] == ' '))) {
+ ++theIndex;
+ }
+
+ if (theIndex > 0 && theIndex != ENDOFSTRING)
+ Delete(0, theIndex);
+}
+
+//====================================================================
+/**
+ * Fetches the character located at the specified index into the
+ * string. Note that you must pass in a value greater than zero and
+ * less than the string's length or you will get an exception.
+ * @param inIndex index of the character to get
+ * @return the character located at inIndex
+ */
+UICChar CString::GetAt(long inIndex) const
+{
+ // Index must be positive
+ if (inIndex < 0)
+ throw;
+
+ // Index must not be longer than the number of chars in the string
+ if (inIndex > Length())
+ throw;
+
+ const wchar_t *theString = *this;
+ return theString[inIndex];
+}
+
+//====================================================================
+/**
+ * Find the first occurrance of the given string.
+ * @param inString is string we're looking for
+ * @return the offset in glyphs from the beginning of this string or ENDOFSTRING if not found.
+ */
+long CString::Find(const CString &inString) const
+{
+ UICChar *theSource = m_UICData;
+ long theSubLength = inString.Length() - 1;
+
+ // Finding an empty string is easy
+ if (0 != *inString.m_UICData) {
+ // Spin until the whole string matches
+ do {
+ // But first spin until first char matches
+ UICChar theSourceChar;
+ do {
+ theSourceChar = *theSource++;
+ if (0 == theSourceChar)
+ return ENDOFSTRING;
+
+ } while (theSourceChar != *inString.m_UICData);
+ } while (0 != StrNCmp(theSource, inString.m_UICData + 1, theSubLength));
+ --theSource;
+ }
+
+ return static_cast<long>(theSource - m_UICData);
+}
+
+//====================================================================
+/**
+ * Find the first occurrance of the given string after the start position.
+ * @param inString is string we're looking for
+ * @param inStart index to start the search from
+ * @return the offset in glyphs from the beginning of this string or ENDOFSTRING if not found.
+ */
+long CString::Find(const CString &inString, long inStart) const
+{
+ long theIndex = ENDOFSTRING;
+
+ // If the starting point is valid, extract the substring and just search it
+ if (inStart < Length() && inStart >= 0)
+ theIndex = Extract(inStart, ENDOFSTRING).Find(inString);
+
+ // If the value was found in the substring, calculate the correct index value
+ if (theIndex != ENDOFSTRING)
+ theIndex += inStart;
+
+ return theIndex;
+}
+
+//====================================================================
+/**
+ * Find the first occurrance of the given character.
+ * @param inChar is char we're looking for
+ * @return the offset in glyphs from the beginning of this string or NOTFOUND if not found.
+ */
+long CString::Find(char inChar) const // char = bad?
+{
+ long theLength = Length();
+ long theIndex;
+
+ for (theIndex = 0; theIndex < theLength && m_UICData[theIndex] != inChar; ++theIndex) {
+ // Empty
+ }
+
+ if (theIndex == theLength)
+ theIndex = ENDOFSTRING;
+
+ return theIndex;
+}
+
+long CString::find_first_of(const CString &inString, long inStart) const
+{
+ for (long idx = inStart, len = Length(); idx < len; ++idx) {
+ for (long strIdx = 0, strLen = inString.Length(); strIdx < strLen; ++strIdx) {
+ UICChar mine(m_UICData[idx]);
+ UICChar theirs(inString.m_UICData[strIdx]);
+ if (mine == theirs)
+ return idx;
+ }
+ }
+ return ENDOFSTRING;
+}
+
+//====================================================================
+/**
+ * Find the first occurrence of the given character after the start position.
+ * @param inChar is char we're looking for
+ * @param inStart
+ * @return the offset in glyphs from the beginning of this string or NOTFOUND if not found.
+ */
+long CString::Find(char inChar, long inStart) const
+{
+ long theIndex = ENDOFSTRING;
+
+ // If the starting point is valid, extract the substring and just search it
+ if (inStart < Length() && inStart >= 0)
+ theIndex = Extract(inStart, ENDOFSTRING).Find(inChar);
+
+ // If the value was found in the substring, calculate the correct index value
+ if (theIndex != ENDOFSTRING)
+ theIndex += inStart;
+
+ return theIndex;
+}
+
+//====================================================================
+/**
+ * Find the last occurrance of the given string.
+ * @param inString is string we're looking for
+ * @return the offset in glyphs from the beginning of this string or ENDOFSTRING if not found.
+ */
+long CString::ReverseFind(const CString &inString) const
+{
+ // This uses "lesser" calls, but does it recursively... I was hoping this could be a better
+ // approach...
+ long inLength = inString.Length();
+ long currStart = Length() - inLength;
+
+ // Extracts the last inString.Length() of strings...
+ CString currStr = Extract(currStart, inLength);
+
+ // If the inString is empty, no match
+ // If we have a 0 length string, the function fails. Return ENDOFSTRING
+ if (inString.Length() == 0 || Length() == 0)
+ return ENDOFSTRING;
+
+ // If we have found a match, we quit the search and return the values
+ if (currStr == inString)
+ return currStart;
+
+ // chop off the present string and try to find the inString in the chopped version
+ currStr = Extract(0, Length() - 1);
+ return currStr.ReverseFind(inString);
+}
+
+long CString::rfind(wchar_t inChar, long offset) const
+{
+ long length = offset == ENDOFSTRING ? Length() : MIN(Length(), offset + 1);
+ for (long idx = 0; idx < length; ++idx) {
+ long curIdx = length - idx - 1;
+ if (at(curIdx) == inChar)
+ return curIdx;
+ }
+ return ENDOFSTRING;
+}
+void CString::reserve(long numChars)
+{
+ long len = Length();
+ if (numChars > len) {
+ SetLength(numChars);
+ SetLength(len);
+ }
+}
+
+//====================================================================
+/**
+ * Find the last occurrance of the given character.
+ * @param inChar is char we're looking for
+ * @return the offset in glyphs from the beginning of this string or NOTFOUND if not found.
+ */
+long CString::ReverseFind(char inChar) const
+{
+ long theIndex;
+ for (theIndex = Length() - 1; theIndex >= 0 && m_UICData[theIndex] != inChar; --theIndex) {
+ // Empty
+ }
+
+ if (theIndex < 0)
+ theIndex = ENDOFSTRING;
+
+ return theIndex;
+}
+
+//=============================================================================
+/**
+ * Replaces all instances of inString with inReplacement.
+ * @return the number of instances that were replaced.
+ */
+long CString::Replace(const CString &inString, const CString &inReplacement)
+{
+ long theIndex = Find(inString);
+ long theFoundCount = 0;
+ while (theIndex != ENDOFSTRING) {
+ Delete(theIndex, inString.Length());
+ Insert(theIndex, inReplacement);
+
+ ++theFoundCount;
+ theIndex += inReplacement.Length();
+
+ theIndex = Find(inString, theIndex);
+ }
+
+ return theFoundCount;
+}
+
+//====================================================================
+/**
+ * Sets this string to a string specified via inFormat and parameters
+ * in sprintf style
+ * DO NOT PASS AN OBJECT INTO THE ...!! these old sprintf methods work
+ * via stack magic and the ... will suck up anything without casting it
+ *
+ * @param inFormat the format string, e.g. "Qt rocks the %ls"
+ * @param ... the parameters to sprint into the format string
+ */
+void CString::Format(const wchar_t *inFormat, ...)
+{
+ va_list theArgs;
+ va_start(theArgs, inFormat);
+
+ long theBufferSize = 512;
+
+ long theWrittenCount = -1;
+
+ while (-1 == theWrittenCount) {
+ // If using existing buffer failed, retry using progressively larger temp buffers
+ CAutoPtr<CArrayDeleteHandler<wchar_t>, wchar_t> theBuffer;
+ theBuffer = new wchar_t[theBufferSize];
+
+#ifdef WIN32
+ theWrittenCount = ::_vsnwprintf(theBuffer, theBufferSize, inFormat, theArgs);
+#else
+ theWrittenCount = vswprintf(theBuffer, theBufferSize, inFormat, theArgs);
+#endif
+
+ if (-1 == theWrittenCount) {
+ // Quadruple the buffer size every time we fail
+ theBufferSize *= 4;
+ } else {
+ // Copy the temp buffer to the main string buffer on success
+ Assign(static_cast<wchar_t *>(theBuffer), theWrittenCount);
+ }
+ }
+}
+
+//====================================================================
+/**
+ * Scan.
+ * @param inFormat is
+ */
+long CString::Scan(const char *inFormat, ...) const
+{
+ va_list theArgs;
+ va_start(theArgs, inFormat);
+
+ AssertChar(m_UICData); // ok?
+ SyncCharBuffer();
+ return 0; // Bastard Microsoft doesn't implement an sscanf with va_arg... will have to copy
+ // some code over.
+}
+
+//====================================================================
+/**
+ * Make sure that no characters are unicode.
+ */
+void CString::AssertChar(const UICChar *inString)
+{
+ while (*inString) {
+ if (*inString > 255)
+ throw;
+ ++inString;
+ }
+}
+
+void AppendString(eastl::string &str, const char *delim, const char *string)
+{
+ if (string && *string) {
+ str.append(delim);
+ str.append(string);
+ }
+}
+
+//====================================================================
+
+CString CString::fromQString(const QString& q)
+{
+ const int count = q.size();
+ wchar_t* tempBuf = reinterpret_cast<wchar_t*>(alloca(count * sizeof(wchar_t)));
+ const int actualLength = q.toWCharArray(tempBuf);
+ CString cs;
+ cs.Assign(tempBuf, actualLength);
+ return cs;
+}
+
+QString CString::toQString() const
+{
+ // ensure wide data is in sync
+ return QString::fromWCharArray(c_str());
+}
+
+QDebug operator<<(QDebug stream, const CString &s)
+{
+ stream << s.c_str();
+ return stream;
+}
+
+} // namespace Q3DStudio
+
diff --git a/src/Authoring/Common/Code/UICString.h b/src/Authoring/Common/Code/UICString.h
new file mode 100644
index 00000000..15441fdd
--- /dev/null
+++ b/src/Authoring/Common/Code/UICString.h
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef __UICSTRING_H__
+#define __UICSTRING_H__
+
+#ifdef _WIN32
+#pragma warning(push)
+#endif
+
+#include "AutoPtr.h"
+#include "UICMacros.h"
+#include "UICObjectCounter.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <EASTL/string.h>
+
+#include <QString>
+#include <QDebug>
+
+namespace Q3DStudio {
+#define _UIC(string) L##string
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1400 // VS2005 = 1400
+typedef wchar_t UICChar;
+#else
+typedef unsigned short UICChar;
+#endif
+
+extern UICChar *s_EmptyUICString;
+
+template <class T>
+long StrLen(const T *inChars);
+
+template <class T, class U>
+void StrToStr(const T *inChars, long inLength, U *outChars);
+
+// Stack based conversion from any array to UICChar*. Treat like a cast operator.
+// UICChar* memory valid for the duration of scope.
+class CUICStr
+{
+ UICChar *m_UICBuffer;
+ enum {
+ ENDOFSTRING = -2, /// End of String - used in extract and insert. Also returned as position
+ /// when the wanted string was not found
+ };
+
+public:
+ operator UICChar *() { return m_UICBuffer; }
+ ~CUICStr() { delete[] m_UICBuffer; }
+ template <class T>
+ CUICStr(const T *inString, long inLength = ENDOFSTRING)
+ : m_UICBuffer(NULL)
+ {
+ if (ENDOFSTRING == inLength)
+ inLength = StrLen(inString);
+
+ m_UICBuffer = new UICChar[inLength + 1];
+ m_UICBuffer[inLength] = 0;
+ StrToStr(inString, inLength, m_UICBuffer);
+ }
+};
+
+// The venerable string class
+class CString
+{
+public:
+ long Length() const;
+ long size() const { return Length(); }
+
+ enum {
+ ENDOFSTRING = -2, /// End of String - used in extract and insert. Also returned as position
+ /// when the wanted string was not found
+ npos = ENDOFSTRING, /// To make converting algorithms using std::wstring to CString easier.
+ };
+
+protected:
+ // Fields
+ UICChar *m_UICData;
+ mutable CAutoArrayPtr<wchar_t> m_WideData; ///< Mutable to allow const buffer access operators
+ mutable CAutoArrayPtr<char> m_CharData;
+#ifdef WIN32
+ /// Multibyte used on Windows only
+ mutable CAutoArrayPtr<char> m_MultiData;
+#endif
+
+ // Memory management
+ void Allocate(long inLength);
+ void Reallocate(long inLength);
+ void Free();
+
+ // Char buffer synchronization
+ void SyncCharBuffer() const;
+ void SyncWideBuffer() const;
+ void DirtyBuffers();
+
+ // Implementation of operators and templates
+ void UICInsert(long inPosition, const UICChar *inChars, long inLength = ENDOFSTRING);
+ void UICConcat(const UICChar *inChars, long inLength = ENDOFSTRING);
+ void UICAssign(const UICChar *inChars, long inLength = ENDOFSTRING);
+ bool UICCompare(const UICChar *inChars, long inLength = ENDOFSTRING,
+ bool inCaseSensitive = true) const;
+
+public:
+ typedef const wchar_t *const_iterator;
+ typedef long size_type;
+ const_iterator begin() const
+ {
+ if (Length())
+ return c_str();
+ return NULL;
+ }
+ const_iterator end() const { return begin() + Length(); }
+
+ // Tools
+ template <class T>
+ void Insert(long inPosition, const T *inChars, long inLength = ENDOFSTRING)
+ {
+ UICInsert(inPosition, CUICStr(inChars, inLength), inLength);
+ }
+ void Insert(long inPosition, const CString &inString)
+ {
+ UICInsert(inPosition, inString.m_UICData, inString.Length());
+ }
+
+ template <class T>
+ void Concat(const T *inChars, long inLength = ENDOFSTRING)
+ {
+ UICConcat(CUICStr(inChars, inLength), inLength);
+ }
+ void Concat(const CString &inString);
+ void Concat(char inChar);
+ void Concat(UICChar inChar);
+ void append(const CString &inString) { Concat(inString); }
+ void append(char inChar) { Concat(inChar); }
+ void append(UICChar inChar) { Concat(inChar); }
+ void append(const UICChar *inChars, long inLength) { Concat<UICChar>(inChars, inLength); }
+ void append(const CString &inString, long inOffset, long inLength)
+ {
+ append(inString.Extract(inOffset, inLength));
+ }
+
+ template <class T>
+ void Assign(const T *inChars, long inLength = ENDOFSTRING);
+ void assign(const wchar_t *inChars, long inLength = ENDOFSTRING) { Assign(inChars, inLength); }
+ void Assign(const CString &inString);
+ void assign(const CString &inString) { Assign(inString); }
+
+ template <class T>
+ bool Compare(const T *inChars, long inLength = ENDOFSTRING, bool inCaseSensitive = true) const
+ {
+ return UICCompare(CUICStr(inChars, inLength), inLength, inCaseSensitive);
+ }
+ bool Compare(const CString &inString, bool inCaseSensitive = true) const
+ {
+ return UICCompare(inString.m_UICData, inString.Length(), inCaseSensitive);
+ }
+
+private:
+ template <class T>
+ T *CreateBuffer() const;
+
+public:
+ DEFINE_OBJECT_COUNTER(CString)
+
+ // Construction
+ CString(char inChar);
+ CString(const CString &inString);
+ CString(UICChar inChar);
+ CString(void)
+ : m_UICData(s_EmptyUICString)
+ {
+ ADDTO_OBJECT_COUNTER(CString);
+ }
+ template <class T>
+ CString(const T *inChars, long inLength = ENDOFSTRING)
+ : m_UICData(s_EmptyUICString)
+ {
+ ADDTO_OBJECT_COUNTER(CString);
+ Assign(inChars, inLength);
+ }
+
+ ~CString()
+ {
+ REMOVEFROM_OBJECT_COUNTER(CString);
+ Clear();
+ }
+
+protected:
+ CString(const UICChar *inString1, long inLength1, const UICChar *inString2, long inLength2);
+
+public:
+ // Operators
+ CString &operator=(const CString &inString)
+ {
+ Assign(inString);
+ return *this;
+ }
+ CString &operator=(char inChar)
+ {
+ Assign(inChar);
+ return *this;
+ }
+ CString &operator=(const UICChar inChar)
+ {
+ Assign(inChar);
+ return *this;
+ }
+#ifdef WIN32
+ template <class T>
+ CString &operator=(const T *inChars)
+ {
+ Assign(inChars);
+ return *this;
+ }
+ template <class T>
+ CString &operator=(const T inChar)
+ {
+ Assign(inChar);
+ return *this;
+ }
+#endif
+
+ CString &operator+=(const CString &inString)
+ {
+ Concat(inString);
+ return *this;
+ }
+ CString &operator+=(char inChar)
+ {
+ Concat(inChar);
+ return *this;
+ }
+#ifdef WIN32
+ template <class T>
+ CString &operator+=(const T *inChars)
+ {
+ Concat(inChars);
+ return *this;
+ }
+ template <class T>
+ CString &operator+=(const T inChar)
+ {
+ Concat(inChar);
+ return *this;
+ }
+#endif
+
+ CString operator+(const CString &inString) const
+ {
+ return CString(m_UICData, Length(), inString.m_UICData, inString.Length());
+ }
+ CString operator+(char inChar) const
+ {
+ UICChar theChar = inChar;
+ return CString(m_UICData, Length(), &theChar, 1);
+ }
+ template <class T>
+ CString operator+(const T *inChars) const
+ {
+ return CString(m_UICData, Length(), CUICStr(inChars), StrLen(inChars));
+ }
+
+ bool operator==(const CString &inString) const { return Compare(inString); }
+ bool operator==(char inChar) const { return (1 == Length()) && (m_UICData[0] == inChar); }
+ template <class T>
+ bool operator==(const T *inChars) const
+ {
+ return UICCompare(CUICStr(inChars));
+ }
+
+ bool operator!=(const CString &inString) const { return !(*this == inString); }
+ bool operator!=(char inChar) const { return !(*this == inChar); }
+ template <class T>
+ bool operator!=(const T *inChars) const
+ {
+ return !(*this == inChars);
+ }
+
+ bool operator<(const CString &inString) const;
+
+ // this also covers wchar_t on 2 byte wchar_t systems (win)
+ operator const UICChar *() const { return m_UICData; }
+// operator long( ) const;
+
+#ifdef CHECK_BOUNDS
+ UICChar &operator[](long inIndex);
+#else
+ inline UICChar &operator[](long inIndex) { return Unique()[inIndex]; }
+#endif
+ inline UICChar &operator[](int inIndex) { return this->operator[]((long)inIndex); }
+
+ /// IMPORTANT NOTE! the char* cast operator is intentionally unimplemented.
+ /// this has been done so that the caller must explicitly call GetCharStar( ) (which flattens
+ /// unicode)
+ /// or GetMulti( ), which returns a multibyte character buffer windows can understand. using
+ /// wchar_ts
+ /// is preferred when possible to either of these options. questions? Ask Andy Skalet
+
+ // operator const char*( ) const
+
+ // replaces char* cast operator, which can be implicit (bad)
+ // should only be used if you know for sure 1 byte per character is ok for your need
+ char *GetCharStar() const
+ {
+ SyncCharBuffer();
+ return m_CharData;
+ }
+
+public:
+ // Utililty
+ void Clear();
+ UICChar *Unique();
+ void SetLength(long inLength);
+ long RefCount() const;
+ bool IsEmpty() const { return 0 == Length(); }
+ bool CompareNoCase(const CString &inString) const { return Compare(inString, false); }
+
+ // Explicit manipulation
+ CString Extract(long inStart, long inLength = ENDOFSTRING) const;
+ void Delete(long inStart, long inLength = ENDOFSTRING);
+ CString &ToUpper();
+ CString &ToLower();
+ void TrimRight();
+ void TrimLeft();
+ CString Mid(int nFirst) const;
+ CString Mid(int nFirst, int nCount) const;
+ CString Left(int nCount) const;
+ CString Right(int nCount) const;
+
+ // Searching
+ UICChar GetAt(long inIndex) const;
+ UICChar at(long inIndex) const { return GetAt(inIndex); }
+ long Find(const CString &inString) const;
+ long Find(const CString &inString, long inStart) const;
+ long Find(char inChar) const;
+ long Find(char inChar, long inStart) const;
+ long find(const CString &inString) const { return Find(inString); }
+ long find(const CString &inString, long inStart) const { return Find(inString, inStart); }
+ long find(char inChar) const { return Find(inChar); }
+ long find(char inChar, long inStart) const { return Find(inChar, inStart); }
+ long find_first_of(const CString &inString, long inStart = 0) const;
+
+ long ReverseFind(const CString &inString) const;
+ long ReverseFind(char inChar) const;
+ long rfind(const CString &str) const { return ReverseFind(str); }
+ long rfind(char inChar) const { return ReverseFind(inChar); }
+ long rfind(wchar_t inChar, long offset = ENDOFSTRING) const;
+ CString erase(long offset, long length) const
+ {
+ CString retval(*this);
+ retval.Delete(offset, length);
+ return retval;
+ }
+ CString substr(long offset, long length = ENDOFSTRING) const { return Extract(offset, length); }
+ void reserve(long numChars);
+
+ long Replace(const CString &inString, const CString &inReplacement);
+
+ const UICChar *c_str() const { return (const wchar_t *)*this; }
+
+ // Format and Scan
+ void Format(const wchar_t *inFormat, ...);
+ long Scan(const char *inFormat, ...) const;
+
+ // Static utilities
+ static void AssertChar(const UICChar *inString); ///< Throw if any UICChar is greater than 255
+ static UICChar ToLower(UICChar inChar)
+ {
+ return inChar >= 'A' && inChar <= 'Z' ? static_cast<UICChar>(inChar + 'a' - 'A') : inChar;
+ }
+
+ /// Everything below this line (within the same class) is handlers for os or library specific
+ /// types
+ /// If we want to run on Windows 9X, we need to use multibyte instead of unicode in system
+ /// calls.
+ /// These methods deal with multibyte
+
+ static CString fromQString(const QString& q);
+ QString toQString() const;
+
+public:
+#ifdef __AFX_H__
+ /// Methods and operators for MFC CStrings
+public:
+ CString(::CString inString)
+ : m_UICData(s_EmptyUICString)
+ {
+ ADDTO_OBJECT_COUNTER(CString);
+ Assign(inString.GetBuffer(0));
+ inString.ReleaseBuffer();
+ }
+
+ CString &operator=(::CString inString)
+ {
+ Assign(inString.GetBuffer(0));
+ inString.ReleaseBuffer();
+ return *this;
+ }
+
+ operator const ::CString() const
+ {
+ return ::CString(this->c_str());
+ } // compile error without "this->"
+#endif
+};
+
+/////// HELPER TEMPLATES ////////
+
+/// Get the length of any zero terminated array
+template <class T>
+long StrLen(const T *inChars)
+{
+ const T *theScanner = inChars;
+
+ if (theScanner)
+ while (*theScanner)
+ ++theScanner;
+
+ return static_cast<long>(theScanner - inChars);
+}
+
+// Convert from and to any array, statically converting every element
+template <class T, class U>
+void StrToStr(const T *inChars, long inLength, U *outChars)
+{
+ for (long theChar = 0; theChar < inLength; ++theChar)
+ outChars[theChar] = static_cast<U>(inChars[theChar]);
+ outChars[inLength] = 0;
+}
+
+// Compare memory pointed to by two null terminated pointers, up to inCount elements
+template <class T>
+long StrNCmp(const T *inChars1, const T *inChars2, long inCount)
+{
+ if (inCount <= 0)
+ return 0;
+
+ while (--inCount && *inChars1 && *inChars1 == *inChars2) {
+ ++inChars1;
+ ++inChars2;
+ }
+
+ return *inChars1 - *inChars2;
+}
+
+/////// CString TEMPLATE CODE ////////
+
+// Generic addition starting with any array type
+template <class T>
+CString operator+(const T *inLHS, const CString inRHS)
+{
+ return CString(inLHS) + inRHS;
+}
+
+// Generic assignment of any array
+template <class T>
+void CString::Assign(const T *inChars, long inLength)
+{
+ if (ENDOFSTRING == inLength)
+ inLength = StrLen(inChars);
+
+ if (reinterpret_cast<const UICChar *>(inChars) != m_UICData) {
+ SetLength(inLength);
+ StrToStr(inChars, inLength, m_UICData);
+ m_UICData[inLength] = 0;
+ }
+
+ DirtyBuffers();
+}
+
+// Generic creation of any array type trying to represent the buffer.
+// Caller assumes responibility for deleting array using delete [] operator.
+template <class T>
+T *CString::CreateBuffer() const
+{
+ long theLength = Length();
+ T *outBuffer = new T[theLength + 1];
+
+ outBuffer[theLength] = 0;
+ StrToStr(m_UICData, theLength, outBuffer);
+
+ return outBuffer;
+}
+
+};
+
+QDebug operator<<(QDebug stream, const Q3DStudio::CString &s);
+
+void AppendString(eastl::string &str, const char *delim, const char *string);
+
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+#endif // __UICSTRING_H__
diff --git a/src/Authoring/Common/Code/UICSynch.h b/src/Authoring/Common/Code/UICSynch.h
new file mode 100644
index 00000000..4903ac49
--- /dev/null
+++ b/src/Authoring/Common/Code/UICSynch.h
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+C++ Portable Types Library (PTypes)
+
+ Copyright (C) 2001-2007 Hovik Melikyan
+
+ http://www.melikyan.com/ptypes/
+
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#pragma once
+#ifndef __UICSYNC_H__
+#define __UICSYNC_H__
+
+#ifdef WIN32
+#define _WINSOCKAPI_ // prevent inclusion of winsock.h in windows.h
+#include <windows.h>
+#elif defined(__MACH__)
+#include <pthread.h>
+#else
+#include <semaphore.h>
+#endif
+
+//
+// Summary of implementation:
+//
+// atomic increment/decrement/exchange
+// Win32: internal, asm
+// GCC/i386: internal, asm
+// Other: internal, mutex hash table
+//
+// mutex
+// Win32: Critical section
+// Other: POSIX mutex
+//
+// trigger
+// Win32: Event
+// Other: internal, POSIX cond/mutex
+//
+// rwlock:
+// Win32: internal, Event/mutex
+// MacOS: internal, POSIX cond/mutex
+// Other: POSIX rwlock
+//
+// semaphore:
+// Win32: = tsemaphore
+// MacOS: = tsemaphore
+// Other: POSIX semaphore
+//
+// tsemaphore (with timed waiting):
+// Win32: Semaphore
+// Other: internal, POSIX mutex/cond
+//
+
+#ifdef WIN32
+typedef long pthread_id_t;
+typedef HANDLE pthread_t;
+#define __PFASTCALL __fastcall
+#elif defined(__MACH__)
+typedef pthread_t pthread_id_t;
+#define __PFASTCALL
+#else
+typedef long pthread_id_t;
+#define __PFASTCALL __attribute__((fastcall))
+#endif
+
+long __PFASTCALL pincrement(long *target);
+long __PFASTCALL pdecrement(long *target);
+long __PFASTCALL pexchange(long *target, long value);
+void *__PFASTCALL pexchange(void **target, void *value);
+
+void psleep(long milliseconds);
+bool pthrequal(pthread_id_t id); // note: this is NOT the thread handle, use thread::get_id()
+pthread_id_t pthrself(); // ... same
+
+// -------------------------------------------------------------------- //
+// --- mutex ---------------------------------------------------------- //
+// -------------------------------------------------------------------- //
+
+#ifdef WIN32
+
+struct mutex
+{
+protected:
+ CRITICAL_SECTION critsec;
+
+public:
+ mutex() { InitializeCriticalSection(&critsec); }
+ ~mutex() { DeleteCriticalSection(&critsec); }
+ void enter() { EnterCriticalSection(&critsec); }
+ void leave() { LeaveCriticalSection(&critsec); }
+ void lock() { enter(); }
+ void unlock() { leave(); }
+};
+
+#else
+
+struct mutex
+{
+protected:
+ pthread_mutex_t mtx;
+
+public:
+ mutex() { pthread_mutex_init(&mtx, 0); }
+ ~mutex() { pthread_mutex_destroy(&mtx); }
+ void enter() { pthread_mutex_lock(&mtx); }
+ void leave() { pthread_mutex_unlock(&mtx); }
+ void lock() { enter(); }
+ void unlock() { leave(); }
+};
+
+#endif
+
+// -------------------------------------------------------------------- //
+// --- trigger -------------------------------------------------------- //
+// -------------------------------------------------------------------- //
+
+#ifdef WIN32
+
+class trigger
+{
+protected:
+ HANDLE handle; // Event object
+public:
+ trigger(bool autoreset, bool state);
+ ~trigger() { CloseHandle(handle); }
+ void wait() { WaitForSingleObject(handle, INFINITE); }
+ void post() { SetEvent(handle); }
+ void signal() { post(); }
+ void reset() { ResetEvent(handle); }
+};
+
+#else
+
+class trigger
+{
+protected:
+ pthread_mutex_t mtx;
+ pthread_cond_t cond;
+ long state;
+ bool autoreset;
+
+public:
+ trigger(bool autoreset, bool state);
+ ~trigger();
+ void wait();
+ void post();
+ void signal() { post(); }
+ void reset();
+};
+
+#endif
+
+// -------------------------------------------------------------------- //
+// --- rwlock --------------------------------------------------------- //
+// -------------------------------------------------------------------- //
+
+#if defined(WIN32) || defined(__DARWIN__)
+#define __PTYPES_RWLOCK__
+#elif defined(linux)
+// on Linux rwlocks are included only with -D_GNU_SOURCE.
+// programs that don't use rwlocks, do not need to define
+// _GNU_SOURCE either.
+#if defined(_GNU_SOURCE) || defined(__USE_UNIX98)
+#define __POSIX_RWLOCK__
+#endif
+#else
+#define __POSIX_RWLOCK__
+#endif
+
+#ifdef __PTYPES_RWLOCK__
+
+struct rwlock : protected mutex
+{
+protected:
+#ifdef WIN32
+ HANDLE reading; // Event object
+ HANDLE finished; // Event object
+ long readcnt;
+ long writecnt;
+#else
+ pthread_mutex_t mtx;
+ pthread_cond_t readcond;
+ pthread_cond_t writecond;
+ long locks;
+ long writers;
+ long readers;
+#endif
+public:
+ rwlock();
+ ~rwlock();
+ void rdlock();
+ void wrlock();
+ void unlock();
+ void lock() { wrlock(); }
+};
+
+#elif defined(__POSIX_RWLOCK__)
+
+struct rwlock
+{
+protected:
+ pthread_rwlock_t rw;
+
+public:
+ rwlock();
+ ~rwlock() { pthread_rwlock_destroy(&rw); }
+ void rdlock() { pthread_rwlock_rdlock(&rw); }
+ void wrlock() { pthread_rwlock_wrlock(&rw); }
+ void unlock() { pthread_rwlock_unlock(&rw); }
+ void lock() { wrlock(); }
+};
+
+#endif
+
+// -------------------------------------------------------------------- //
+// --- semaphore ------------------------------------------------------ //
+// -------------------------------------------------------------------- //
+
+// use tsemaphore everywhere
+#define __SEM_TO_TIMEDSEM__
+
+#ifdef __SEM_TO_TIMEDSEM__
+
+// map ordinary semaphore to timed semaphore
+
+class tsemaphore;
+typedef tsemaphore semaphore;
+
+#else
+
+class semaphore
+{
+protected:
+ sem_t handle;
+
+public:
+ semaphore(long initvalue);
+ virtual ~semaphore();
+
+ void wait();
+ void post();
+ void signal() { post(); }
+};
+
+#endif
+
+class tsemaphore
+{
+protected:
+#ifdef WIN32
+ HANDLE handle;
+#else
+ long count;
+ pthread_mutex_t mtx;
+ pthread_cond_t cond;
+#endif
+public:
+ tsemaphore(long initvalue);
+ virtual ~tsemaphore();
+ bool wait(long msecs = -1);
+ void post();
+ void signal() { post(); }
+};
+
+// -------------------------------------------------------------------- //
+// --- thread --------------------------------------------------------- //
+// -------------------------------------------------------------------- //
+
+class thread
+{
+protected:
+#ifdef WIN32
+ long id;
+#endif
+ pthread_t handle;
+ bool autofree;
+ long running;
+ long signaled;
+ long freed;
+ bool finished;
+ tsemaphore relaxsem;
+
+ virtual void execute() = 0;
+ virtual void cleanup();
+
+ bool relax(long msecs) { return relaxsem.wait(msecs); }
+
+ friend void _threadepilog(thread *thr);
+
+#ifdef WIN32
+ friend long __stdcall _threadproc(void *arg);
+#else
+ friend void *_threadproc(void *arg);
+#endif
+
+public:
+ thread(bool iautofree);
+ virtual ~thread();
+
+#ifdef WIN32
+ pthread_id_t get_id() { return long(id); }
+#else
+ pthread_id_t get_id() { return handle; }
+#endif
+
+ bool get_running() { return running != 0; }
+ bool get_finished() { return finished; }
+ bool get_signaled() { return signaled != 0; }
+
+ void start();
+ void signal();
+ void waitfor();
+};
+
+// -------------------------------------------------------------------- //
+// --- msgqueue ------------------------------------------------------- //
+// -------------------------------------------------------------------- //
+
+const long MSG_USER = 0;
+const long MSG_USER_MAX = 0xBFFFF;
+const long MSG_LIB = 0xC0000;
+const long MSG_QUIT = MSG_LIB;
+
+class message
+{
+protected:
+ message *next; // next in the message chain, used internally
+ semaphore *sync; // used internally by msgqueue::send(), when called from a different thread
+ friend class msgqueue; // my friend, message queue...
+public:
+ long id;
+ long result;
+ long param;
+ message(long iid, long iparam = 0);
+ virtual ~message();
+};
+
+class msgqueue
+{
+private:
+ message *head; // queue head
+ message *tail; // queue tail
+ long qcount; // number of items in the queue
+ semaphore sem; // queue semaphore
+ mutex qlock; // critical sections in enqueue and dequeue
+ mutex thrlock; // lock for the queue processing
+ pthread_id_t owner; // thread ID of the queue processing thread
+
+ void enqueue(message *msg);
+ void push(message *msg);
+ message *dequeue(bool safe = true);
+
+ void purgequeue();
+ long finishmsg(message *msg);
+ void handlemsg(message *msg);
+ void takeownership();
+
+protected:
+ bool quit;
+
+ void defhandler(message &msg);
+ virtual void msghandler(message &msg) = 0;
+
+public:
+ msgqueue();
+ virtual ~msgqueue();
+
+ // functions calling from the owner thread:
+ long msgsavail() { return qcount; }
+ void processone(); // process one message, may hang if no msgs in the queue
+ void processmsgs(); // process all available messages and return
+ void run(); // process messages until MSG_QUIT
+
+ // functions calling from any thread:
+ void post(message *msg);
+ void post(long id, long param = 0);
+ void posturgent(message *msg);
+ void posturgent(long id, long param = 0);
+ long send(message *msg);
+ long send(long id, long param = 0);
+};
+
+#endif // __UICSYNC_H__
diff --git a/src/Authoring/Common/Code/UICTime.cpp b/src/Authoring/Common/Code/UICTime.cpp
new file mode 100644
index 00000000..84354f44
--- /dev/null
+++ b/src/Authoring/Common/Code/UICTime.cpp
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICTime.h"
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#elif defined(__MACH__)
+#include <sys/time.h>
+#endif
+
+namespace Q3DStudio {
+
+//====================================================================
+/**
+ * Sets this time object to reflect the current time.
+ * @param inUseUTC is true if we should use Coordinated Universal Time
+ * instead of local time zone.
+ */
+void CTime::SetNow(bool inUseUTC)
+{
+ m_Time = GetNow(inUseUTC);
+}
+
+//====================================================================
+/**
+ * Get the number of miliseconds since year 0.
+ * @param inUseUTC is true if we should use Coordinated Universal Time instead of local time zone.
+ * @return the number of miliseconds
+ */
+TLarge CTime::GetNow(bool inUseUTC)
+{
+#ifdef WIN32 // Windows
+
+ SYSTEMTIME t;
+
+ if (inUseUTC)
+ ::GetSystemTime(&t);
+ else
+ ::GetLocalTime(&t);
+
+ return Convert(t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
+
+#elif defined(__MACH__) // MACH-O
+ // we can't use localtime() and gmtime() here as they don't return
+ // milliseconds which are needed for our datetime format. instead,
+ // we call gettimeofday() which have microsecond precision, and then
+ // adjust the time according to timzone info returned by localtime()
+ // on BSD and Linux, and global variables altzone/timezone on SunOS.
+ // MacOS X: localtime() is always reentrant (?)
+
+ // NOTE: at the moment of passing the DST adjustment (twice a year)
+ // the local time value returned by now() may be incorrect.
+ // the application should call tzupdate() from time to time if it
+ // is supposed to be running infinitely, e.g. if it's a daemon.
+
+ // always rely on UTC time inside your application whenever possible.
+ timeval tv;
+ ::gettimeofday(&tv, NULL);
+
+ long theDays = tv.tv_sec / 86400 // days since Unix "Epoch", i.e. 01/01/1970
+ + 719162; // plus days between 01/01/0001 and Unix Epoch
+ long theSecs = tv.tv_sec % 86400; // the remainder, i.e. seconds since midnight
+ TLarge theMSecs =
+ static_cast<TLarge>(theDays) * msecsmax + (theSecs * 1000 + tv.tv_usec / 1000);
+
+ if (!inUseUTC) {
+ theMSecs += GetTimeZoneOffset() * 60 * 1000;
+ }
+ return theMSecs;
+#else
+ return 0;
+#endif
+}
+
+//====================================================================
+/**
+ * GetTimeZoneOffset.
+ * @return the number of miliseconds
+ */
+TLarge CTime::GetTimeZoneOffset()
+{
+ return 0;
+ /*
+#if defined(WIN32)
+ TIME_ZONE_INFORMATION tz;
+ GetTimeZoneInformation(&tz);
+ if (tz.DaylightDate.wMonth != 0)
+ return - (tz.Bias + tz.DaylightBias);
+ else
+ return - tz.Bias;
+
+#elif defined(__sun__)
+ if (timezone == 0)
+ tzset();
+ if (daylight != 0)
+ return - altzone / 60;
+ else
+ return - timezone / 60;
+
+#elif defined(__DARWIN__)
+ time_t u;
+ time(&u);
+ tm* t = localtime(&u);
+ return t->tm_gmtoff / 60;
+
+#else
+ time_t u;
+ time(&u);
+ tm t;
+ localtime_r(&u, &t);
+ return t.tm_gmtoff / 60;
+#endif*/
+}
+
+//====================================================================
+/**
+ * Get the difference in miliseconds between now and the time stored.
+ * @return the number of miliseconds
+ */
+long CTime::StopWatch()
+{
+ TLarge theDifference = GetNow() - m_Time;
+ return static_cast<long>(theDifference);
+}
+
+//====================================================================
+/**
+ * Validate the given representation of time.
+ * @param inTime is the time in question
+ * @return true if valid
+ */
+bool CTime::IsValid(TLarge inTime)
+{
+ return inTime >= 0 && inTime < datetimemax;
+}
+
+//====================================================================
+/**
+ * Examine if the given year is a leap year.
+ * @param inYear is the year in question
+ * @return true if leap year
+ */
+bool CTime::IsLeapYear(long inYear)
+{
+ return inYear > 0 && inYear % 4 == 0 && (inYear % 100 != 0 || inYear % 400 == 0);
+}
+
+//====================================================================
+/**
+ * Query the number of days in a month.
+ * @param inYear is the year in question
+ * @param inMonth is the month in question
+ * @return the days in the given month
+ */
+long CTime::DaysInMonth(long inYear, long inMonth)
+{
+ static const long sMonthDays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ long theDays = sMonthDays[inMonth - 1];
+
+ if (inMonth < 1 || inMonth > 12)
+ return 0;
+
+ if (inMonth == 2 && IsLeapYear(inYear)) {
+ ++theDays;
+ }
+
+ return theDays;
+}
+
+//====================================================================
+/**
+ * Query the number of days in a year up to and including a month.
+ * @param inYear is the year in question
+ * @param inMonth is the month in question
+ * @return the days in the given year
+ */
+long CTime::DaysInYear(long inYear, long inMonth)
+{
+ static const long sTotalMonthDays[12] = { 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334, 365 };
+ long theDays = sTotalMonthDays[inMonth - 1];
+
+ if (inMonth < 1 || inMonth > 12)
+ return 0;
+
+ if (inMonth > 1 && IsLeapYear(inYear)) {
+ ++theDays;
+ }
+
+ return theDays;
+}
+
+//====================================================================
+/**
+ * Validates the given date.
+ * @param inYear is the year in question
+ * @param inMonth is the month in question
+ * @param inDay is the day in question
+ * @return true if date is valid
+ */
+bool CTime::IsDateValid(long inYear, long inMonth, long inDay)
+{
+ return inYear >= 1 && inYear <= 9999 && inMonth >= 1 && inMonth <= 12 && inDay >= 1
+ && inDay <= DaysInMonth(inYear, inMonth);
+}
+
+//====================================================================
+/**
+ * Validates the given time.
+ * @param inHour is the hour in question
+ * @param inMin is the minute in question
+ * @param inSec is the second in question
+ * @param inMSec is the millisecond in question
+ * @return true if time is valid
+ */
+bool CTime::IsTimeValid(long inHour, long inMin, long inSec, long inMSec)
+{
+ return inHour >= 0 && inHour < 24 && inMin >= 0 && inMin < 60 && inSec >= 0 && inSec < 60
+ && inMSec >= 0 && inMSec < 1000;
+}
+
+//====================================================================
+/**
+ * Set the obejct time to the given date and time.
+ * @param inYear are the given years
+ * @param inMonth are the given minutes
+ * @param inDay are the given seconds
+ * @param inHour are the given hours
+ * @param inMin are the given minutes
+ * @param inSec are the given seconds
+ * @param inMSec are the given milliseconds
+ */
+void CTime::Encode(long inYear, long inMonth, long inDay, long inHour, long inMin, long inSec,
+ long inMSec)
+{
+ TLarge theTime = Convert(inYear, inMonth, inDay, inHour, inMin, inSec, inMSec);
+
+ if (IsValid(theTime)) {
+ m_Time = theTime;
+ }
+}
+
+//====================================================================
+/**
+ * Convert the given date and time to milliseconds.
+ * @param inYear are the given years
+ * @param inMonth are the given minutes
+ * @param inDay are the given seconds
+ * @param inHour are the given hours
+ * @param inMin are the given minutes
+ * @param inSec are the given seconds
+ * @param inMSec are the given milliseconds
+ * @return the total number of milliseonds since year 0
+ */
+TLarge CTime::Convert(long inYear, long inMonth, long inDay, long inHour, long inMin, long inSec,
+ long inMSec)
+{
+ TLarge theTime = static_cast<TLarge>(inHour) * 3600000 + static_cast<TLarge>(inMin) * 60000
+ + static_cast<TLarge>(inSec) * 1000 + inMSec;
+
+ long theYear = inYear - 1;
+ TLarge theDays = inDay // days in this month
+ + DaysInYear(inYear, inMonth - 1) // plus days since the beginning of the year
+ + theYear * 365 // plus "pure" days
+ + theYear / 4 - theYear / 100 + theYear / 400 // plus leap year correction
+ - 1; // ... minus one (guess why :)
+
+ theTime += static_cast<TLarge>(theDays) * msecsmax;
+
+ return theTime;
+}
+
+//====================================================================
+/**
+ * Decode the stored time into hours, minutes, seconds and milliseonds.
+ * @param outHour are the total hours
+ * @param outMin are the total minutes
+ * @param outSec are the total seconds
+ * @param outMSec are the total milliseconds
+ */
+void CTime::DecodeTime(long &outHour, long &outMin, long &outSec, long &outMSec)
+{
+ long theMSecs = GetMilliSecs();
+
+ outHour = theMSecs / 3600000;
+ theMSecs %= 3600000;
+ outMin = theMSecs / 60000;
+ theMSecs %= 60000;
+ outSec = theMSecs / 1000;
+ outMSec = theMSecs % 1000;
+}
+
+//====================================================================
+/**
+ * Decode the stored time into years, months and days.
+ * @param outYear are the total years
+ * @param outMonth are the total months
+ * @param outDay are the total days
+ */
+void CTime::DecodeDate(long &outYear, long &outMonth, long &outDay)
+{
+ long theDays = GetDays();
+ const long the1Year = 365; // number of days in 1 year
+ const long the4Years = the1Year * 4 + 1; // ... in 4 year period
+ const long the100Years = the4Years * 25 - 1; // ... in 100 year period
+ const long the400Years = the100Years * 4 + 1; // ... in 400 year period
+
+ outYear = (theDays / the400Years) * 400 + 1;
+ theDays %= the400Years;
+
+ long theCenturies = theDays / the100Years;
+ theDays %= the100Years;
+ if (4 == theCenturies) {
+ --theCenturies;
+ theDays += the100Years;
+ }
+ outYear += theCenturies * 100;
+
+ outYear += (theDays / the4Years) * 4;
+ theDays %= the4Years;
+
+ long theYears = theDays / the1Year;
+ theDays %= the1Year;
+ if (4 == theYears) {
+ --theYears;
+ theDays += the1Year;
+ }
+ outYear += theYears;
+
+ outMonth = theDays / 29; // approximate month no. (to avoid loops)
+ if (theDays < DaysInYear(outYear, outMonth)) // month no. correction
+ {
+ --outMonth;
+ }
+
+ outDay = theDays - DaysInYear(outYear, outMonth) + 1;
+ ++outMonth;
+}
+}
diff --git a/src/Authoring/Common/Code/UICTime.h b/src/Authoring/Common/Code/UICTime.h
new file mode 100644
index 00000000..8aac0d0d
--- /dev/null
+++ b/src/Authoring/Common/Code/UICTime.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef __UICTIME_H__
+#define __UICTIME_H__
+
+#include "UICLargeInteger.h"
+
+namespace Q3DStudio {
+const long msecsmax = 86400000; // number of milliseconds in one day
+const long daysmax = 3652059; // number of days between 01/01/0001 and 12/31/9999
+const TLarge datetimemax = TLarge(msecsmax) * daysmax; // max. allowed number for datetime type
+const TLarge invdatetime = TLarge(-1);
+
+class CTime
+{
+protected:
+ TLarge m_Time; // Datetime type: 64-bit, number of milliseconds since midnight 01/01/0001.
+
+public:
+ // Utilities
+ void SetNow(bool inUseUTC = true);
+ long StopWatch();
+
+ long GetMilliSecs() const { return static_cast<long>(m_Time % msecsmax); }
+ long GetDays() const { return static_cast<long>(m_Time / msecsmax); }
+ long DayOfWeek() const { return (GetDays() + 1) % 7; }
+
+ void Encode(long inYear, long inMonth, long inDay, long inHour, long inMin, long inSec,
+ long inMSec);
+ void DecodeTime(long &outHour, long &outMin, long &outSec, long &inMSec);
+ void DecodeDate(long &outYear, long &outMonth, long &outDay);
+
+ // Construction
+ CTime(bool inSetNow = false)
+ : m_Time(0)
+ {
+ if (inSetNow)
+ SetNow();
+ }
+ CTime(const CTime &inTime)
+ : m_Time(inTime.m_Time)
+ {
+ }
+
+ // Statics
+ static CTime Now() { return CTime(true); }
+ static bool IsLeapYear(long inYear);
+ static long DaysInMonth(long inYear, long inMonth);
+ static long DaysInYear(long inYear, long inMonth);
+ static bool IsDateValid(long inYear, long inMonth, long inDay);
+ static bool IsTimeValid(long inHour, long inMin, long inSec, long inMSec = 0);
+
+ // Operators
+ CTime &operator=(const CTime &inTime)
+ {
+ m_Time = inTime.m_Time;
+ return *this;
+ }
+ CTime &operator+=(const CTime &inTime)
+ {
+ m_Time += inTime.m_Time;
+ return *this;
+ }
+ CTime &operator-=(const CTime &inTime)
+ {
+ m_Time -= inTime.m_Time;
+ return *this;
+ }
+ CTime &operator/=(const CTime &inTime)
+ {
+ m_Time /= inTime.m_Time;
+ return *this;
+ }
+ CTime &operator*=(const CTime &inTime)
+ {
+ m_Time *= inTime.m_Time;
+ return *this;
+ }
+ CTime &operator%=(const CTime &inTime)
+ {
+ m_Time %= inTime.m_Time;
+ return *this;
+ }
+
+ CTime operator+(const CTime &inTime) const
+ {
+ CTime theTime(*this);
+ return theTime += inTime;
+ }
+ CTime operator-(const CTime &inTime) const
+ {
+ CTime theTime(*this);
+ return theTime -= inTime;
+ }
+ CTime operator*(const CTime &inTime) const
+ {
+ CTime theTime(*this);
+ return theTime *= inTime;
+ }
+ CTime operator/(const CTime &inTime) const
+ {
+ CTime theTime(*this);
+ return theTime /= inTime;
+ }
+ CTime operator%(const CTime &inTime) const
+ {
+ CTime theTime(*this);
+ return theTime %= inTime;
+ }
+
+ bool operator==(const CTime &inTime) const { return m_Time == inTime.m_Time; }
+ bool operator!=(const CTime &inTime) const { return m_Time != inTime.m_Time; }
+ bool operator>(const CTime &inTime) const { return m_Time > inTime.m_Time; }
+ bool operator<(const CTime &inTime) const { return m_Time < inTime.m_Time; }
+ bool operator>=(const CTime &inTime) const { return m_Time >= inTime.m_Time; }
+ bool operator<=(const CTime &inTime) const { return m_Time <= inTime.m_Time; }
+ operator const long() const { return GetMilliSecs(); }
+
+protected:
+ bool IsValid(TLarge inTime);
+ TLarge GetNow(bool inUseUTC = true);
+ TLarge Convert(long inYear, long inMonth, long inDay, long inHour, long inMin, long inSec,
+ long inMSec);
+ TLarge GetTimeZoneOffset();
+};
+}
+
+#endif // __UICTIME_H__
diff --git a/src/Authoring/Common/Code/Vector3.inl b/src/Authoring/Common/Code/Vector3.inl
new file mode 100644
index 00000000..e09a471a
--- /dev/null
+++ b/src/Authoring/Common/Code/Vector3.inl
@@ -0,0 +1,545 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// CONSTRUCTION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Simple constructor - creates a NULL vector.
+ */
+
+inline CVector3::CVector3()
+ : x(0.0f)
+ , y(0.0f)
+ , z(0.0f)
+{
+}
+
+//==============================================================================
+/**
+ * Construction from three coordinates.
+ * @param inX is the x coordinate
+ * @param inY is the y coordinate
+ * @param inZ is the z coordinate
+ */
+
+inline CVector3::CVector3(const float inX, const float inY, const float inZ)
+ : x(inX)
+ , y(inY)
+ , z(inZ)
+{
+}
+
+//==============================================================================
+/**
+ * Construction from three coordinates in an array.
+ * @param inComponents is an array with three coordinates
+ */
+
+inline CVector3::CVector3(const float inComponents[])
+ : x(inComponents[0])
+ , y(inComponents[1])
+ , z(inComponents[2])
+{
+}
+
+//==============================================================================
+/**
+ * Copy constructor
+ * @param inVector is the source vector
+ */
+
+inline CVector3::CVector3(const CVector3 &inVector)
+ : x(inVector.x)
+ , y(inVector.y)
+ , z(inVector.z)
+{
+}
+
+//==============================================================================
+// INITIALIZATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Assignment of coordinates.
+ * @param inX is the x coordinate
+ * @param inY is the y coordinate
+ * @param inZ is the z coordinate
+ * @return a reference to this modified vector
+ */
+
+inline CVector3 &CVector3::Set(const float inX, const float inY, const float inZ)
+{
+ x = inX;
+ y = inY;
+ z = inZ;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Assignment of coordinates using an array.
+ * @param inComponents is the coordinate array
+ * @return a reference to this modified vector
+ */
+
+inline CVector3 &CVector3::Set(const float inComponents[])
+{
+ x = inComponents[0];
+ y = inComponents[1];
+ z = inComponents[2];
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Assignment of coordinates using another vector.
+ * @param inVector is the vector to be copied.
+ * @return a reference to this modified vector
+ */
+
+inline CVector3 &CVector3::Set(const CVector3 &inVector)
+{
+ x = inVector.x;
+ y = inVector.y;
+ z = inVector.z;
+ return *this;
+}
+
+//==============================================================================
+// OPERATORS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Returns either the x,y or z value of the vector. Reference is read only.
+ * Fast implementation depends on the fields being packed next to each other.
+ * @param inIndex is the index of the value. X=0, Y=1, Z=2
+ * @return the requested coordinate
+ */
+inline const float &CVector3::operator[](int inIndex) const
+{
+ return *(&x + inIndex);
+}
+
+//==============================================================================
+/**
+ * Returns either the x,y or z value of the vector.
+ * Reference is read/write in contrast to the const method above and can
+ * thus be used for modification of values such as theVector[1] = 1.0f
+ * Fast implementation depends on the fields being packed next to each other.
+ * @param inIndex is the index of the value. X=0, Y=1, Z=2
+ * @return the value of the requested component
+*/
+inline float &CVector3::operator[](int inIndex)
+{
+ return *(&x + inIndex);
+}
+
+//==============================================================================
+/**
+ * Compare this vector with another. Exact match is not needed but instead
+ * an error of EPSILON is allowed.
+ * @param inVector is the vector we are compared with
+ * @return true if the vectors are close to identical
+ * @see EPSILON
+ */
+inline bool CVector3::operator==(const CVector3 &inVector) const
+{
+ return (::abs(x - inVector.x) < EPSILON) && (::abs(y - inVector.y) < EPSILON)
+ && (::abs(z - inVector.z) < EPSILON);
+}
+
+//==============================================================================
+/**
+ * Compare this vector with another. Exact match is not needed but instead
+ * an error of EPSILON is allowed.
+ * @param inVector is the vector we are compared with
+ * @return true if the vectors are not even close to identical
+ * @see EPSILON
+ */
+inline bool CVector3::operator!=(const CVector3 &inVector) const
+{
+ return (::abs(x - inVector.x) > EPSILON) || (::abs(y - inVector.y) > EPSILON)
+ || (::abs(z - inVector.z) > EPSILON);
+}
+
+//==============================================================================
+/**
+ * Add this vector with another but do not modify this vector.
+ * @param inVector is the second vector being added
+ * @return a new vector
+ */
+
+inline CVector3 CVector3::operator+(const CVector3 &inVector) const
+{
+ return CVector3(x + inVector.x, y + inVector.y, z + inVector.z);
+}
+
+//==============================================================================
+/**
+ * Add two vectors but do not modify this vector.
+ * @param inVector is vector being subtracted
+ * @return a new vector
+ */
+
+inline CVector3 CVector3::operator-(const CVector3 &inVector) const
+{
+ return CVector3(x - inVector.x, y - inVector.y, z - inVector.z);
+}
+
+//==============================================================================
+/**
+ * Get a scaled copy of this vector.
+ * @param inFactor is the factor that scales each coordinate
+ * @return a new scaled vector
+ */
+
+inline CVector3 CVector3::operator*(float inFactor) const
+{
+ return CVector3(x * inFactor, y * inFactor, z * inFactor);
+}
+
+//==============================================================================
+/**
+ * Perform a dot product.
+ * @param inVector is the second vector of the dot product
+ * @return the dot product
+ * @see DotProduct
+ */
+float CVector3::operator*(const CVector3 &inVector) const
+{
+ return x * inVector.x + y * inVector.y + z * inVector.z;
+}
+
+//==============================================================================
+/**
+ * Get a scaled copy of this vector.
+ * @param inDivisor is the divisor that scales each coordinate
+ * @return a new scaled vector
+ */
+inline CVector3 CVector3::operator/(float inDivisor) const
+{
+ return CVector3(x / inDivisor, y / inDivisor, z / inDivisor);
+}
+
+//==============================================================================
+/**
+ * Perform a cross product of two vectors.
+ * @param inVector is the second vector of the cross product
+ * @return the cross product vector
+ * @see CrossProduct
+ */
+CVector3 CVector3::operator%(const CVector3 &inVector) const
+{
+ return CVector3(y * inVector.z - z * inVector.y, z * inVector.x - x * inVector.z,
+ x * inVector.y - y * inVector.x);
+}
+
+//==============================================================================
+/**
+ * Invert the vector.
+ * @return the inverted copy of this vector
+ */
+inline CVector3 CVector3::operator-() const
+{
+ return CVector3(-x, -y, -z);
+}
+
+//==============================================================================
+/**
+ * Simple assignment.
+ * @param inVector
+ * @return a reference to this modified vector
+ */
+inline CVector3 &CVector3::operator=(const CVector3 &inVector)
+{
+ x = inVector.x;
+ y = inVector.y;
+ z = inVector.z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Increment this vector.
+ * @param inVector has the coordinates by which this textor will be incremented
+ * @return a reference to this modified vector
+ */
+inline CVector3 &CVector3::operator+=(const CVector3 &inVector)
+{
+ x += inVector.x;
+ y += inVector.y;
+ z += inVector.z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Decrement this vector.
+ * @param inVector has the coordinates by which this textor will be decremented
+ * @return a reference to this modified vector
+ */
+inline CVector3 &CVector3::operator-=(const CVector3 &inVector)
+{
+ x -= inVector.x;
+ y -= inVector.y;
+ z -= inVector.z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Scale this vector by a factor.
+ * @param inFactor is the scale factor
+ * @return a reference to this modified vector
+ */
+inline CVector3 &CVector3::operator*=(float inFactor)
+{
+ x *= inFactor;
+ y *= inFactor;
+ z *= inFactor;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Scale this vector by a divisor.
+ * @param inDivisor is the inverted scale factor
+ * @return a reference to this modified vector
+ */
+inline CVector3 &CVector3::operator/=(float inDivisor)
+{
+ x /= inDivisor;
+ y /= inDivisor;
+ z /= inDivisor;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Perform a cross product and immedately store the result in this vector.
+ * @param inVector is the second vector of the cross product
+ * @return a reference to this modified vector
+ * @see CrossProduct
+ */
+CVector3 &CVector3::operator%=(const CVector3 &inVector)
+{
+ float theX = y * inVector.z - z * inVector.y;
+ float theY = z * inVector.x - x * inVector.z;
+ float theZ = x * inVector.y - y * inVector.x;
+
+ x = theX;
+ y = theY;
+ z = theZ;
+ return *this;
+}
+
+//==============================================================================
+// FUNCTIONS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Calculates the squared distance between this vector and another.
+ * This is often used in sorting situations where the real distance isn't needed.
+ * @param inVector the vector to which the distance is being calculated
+ * @return the squared distance between vectors
+ */
+inline float CVector3::DistanceSquared(const CVector3 &inVector) const
+{
+ return (x - inVector.x) * (x - inVector.x) + (y - inVector.y) * (y - inVector.y)
+ + (z - inVector.z) * (z - inVector.z);
+}
+
+//==============================================================================
+/**
+ * Calculates the distance between this vector and another.
+ * @param inVector the vector to which the distance is being calculated
+ * @return the distance between vectors
+ */
+inline float CVector3::Distance(const CVector3 &inVector) const
+{
+ return ::sqrtf((x - inVector.x) * (x - inVector.x) + (y - inVector.y) * (y - inVector.y)
+ + (z - inVector.z) * (z - inVector.z));
+}
+
+//==============================================================================
+/**
+ * Calculates the squared length (squared magnitude) of the current vector.
+ * @return the squared length of this vector
+ */
+inline float CVector3::LengthSquared() const
+{
+ return x * x + y * y + z * z;
+}
+
+//==============================================================================
+/**
+ * Calculates the length (magnitude) of the current vector.
+ * @return the length of this vector
+ */
+inline float CVector3::Length() const
+{
+ return ::sqrt(x * x + y * y + z * z);
+}
+
+//==============================================================================
+/**
+ * Calculates the dot product of this vector and another.
+ * @param inVector3 is the other vector
+ * @return the dot product
+ * @see operator*
+ */
+inline float CVector3::DotProduct(const CVector3 &inVector) const
+{
+ return x * inVector.x + y * inVector.y + z * inVector.z;
+}
+
+//==============================================================================
+/**
+ * Calculates the cross product of this vector and another.
+ * @param inVector3 is the other vector
+ * @return the cross product vector
+ * @see operator%
+ * @see operator%=
+ */
+inline CVector3 CVector3::CrossProduct(const CVector3 &inVector)
+{
+ return CVector3(y * inVector.z - z * inVector.y, z * inVector.x - x * inVector.z,
+ x * inVector.y - y * inVector.x);
+}
+
+//==============================================================================
+/**
+ * Normalizes the current vector making it a unit vector.
+ * The normalized vector is defined to be: V_norm = V / Magnitude(V).
+ * @return this normalized vector
+*/
+inline CVector3 &CVector3::Normalize()
+{
+ float theLengthSquared = LengthSquared();
+ if ((theLengthSquared > SQREPSILON) && ::abs(theLengthSquared - 1.0f) > SQREPSILON) {
+ float theInvLength = 1.0f / ::sqrt(theLengthSquared);
+ x *= theInvLength;
+ y *= theInvLength;
+ z *= theInvLength;
+ }
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the minimum between
+ * this vector and another.
+ * @param inVector3 The vector that whose elements are tested against the
+ * current vector to build the minimum.
+ * @return this minimized vector
+*/
+inline CVector3 &CVector3::Minimize(const CVector3 &inVector)
+{
+ x = MIN<float>(x, inVector.x);
+ y = MIN<float>(y, inVector.y);
+ z = MIN<float>(z, inVector.z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the maximum between
+ * this vector and another.
+ * @param inVector3 The vector that whose elements are tested against the
+ * current vector to build the maximum.
+ * @return this maximized vector
+*/
+inline CVector3 &CVector3::Maximize(const CVector3 &inVector)
+{
+ x = MAX<float>(x, inVector.x);
+ y = MAX<float>(y, inVector.y);
+ z = MAX<float>(z, inVector.z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector by performing a linear interpolation between the
+ * current vector and the given vector. If inFactor is 0.0 then this vector
+ * remains unchanged. If inFactor is 1.0 then this vector becomes inDestVector.
+ * If inFactor is between 0.0-1.0 then this vector becomes a vector between
+ * this old vector and inDestVector proportionally interpolated based in inFactor.
+ * If inFactor is less than 0 or more than 1 then this vector is extrapolated.
+ *
+ * @param inDestVector Second vector for the interpolation
+ * @param inFactor Weight for the interpolation
+ * @return this interpolated vector
+ */
+inline CVector3 &CVector3::InterpolateLinear(const CVector3 &inDestVector, float inFactor)
+{
+ x += inFactor * (inDestVector.x - x);
+ y += inFactor * (inDestVector.y - y);
+ z += inFactor * (inDestVector.z - z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Transforms this vector by the given matrix.
+ *
+ * The matrix is row column of the form (Matrix[row][column]):
+ *<code> <p>
+ * | m0 m1 m2 w | <br>
+ * | m4 m5 m6 w | <br>
+ * | m8 m9 m10 w | <br>
+ * | tX tY tZ w | <br>
+ *</code>
+ * @param inMatrix transform matrix
+ * @param inTranslate false if you only want to rotate/scale the vector
+ * @return this transformed vector
+ */
+CVector3 &CVector3::Transform(const CMatrix &inMatrix, bool inTranslate)
+{
+ float theX = x;
+ float theY = y;
+ float theZ = z;
+
+ x = theX * inMatrix.m[0][0] + theY * inMatrix.m[1][0] + theZ * inMatrix.m[2][0];
+ y = theX * inMatrix.m[0][1] + theY * inMatrix.m[1][1] + theZ * inMatrix.m[2][1];
+ z = theX * inMatrix.m[0][2] + theY * inMatrix.m[1][2] + theZ * inMatrix.m[2][2];
+
+ if (inTranslate) {
+ x += inMatrix.m[3][0];
+ y += inMatrix.m[3][1];
+ z += inMatrix.m[3][2];
+ }
+
+ return *this;
+}
diff --git a/src/Authoring/Common/Code/_Qt/QtUICFile.cpp b/src/Authoring/Common/Code/_Qt/QtUICFile.cpp
new file mode 100644
index 00000000..8cb3502c
--- /dev/null
+++ b/src/Authoring/Common/Code/_Qt/QtUICFile.cpp
@@ -0,0 +1,455 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICFile.h"
+#include "UICFileTools.h"
+
+#include "IOLibraryException.h"
+
+#include <QFileInfo>
+#include <QDir>
+#include <QFile>
+#include <QCoreApplication>
+#include <QTemporaryFile>
+#include <QDesktopServices>
+#include <QUrl>
+
+//==============================================================================
+// Static variables
+//==============================================================================
+TFilePathList CUICFile::s_TempFilePathList;
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+const Q3DStudio::CString CUICFile::CURRENT_DIR(".\\");
+const Q3DStudio::CString CUICFile::PARENT_DIR("..\\");
+
+//=============================================================================
+/**
+ * Create a new file from the path.
+ * @param inIsPosix ignored.
+ * @param inAddBase ignored.
+ */
+CUICFile::CUICFile(const Q3DStudio::CString &inPathName, bool inIsPosix, bool inAddBase)
+{
+ Q_UNUSED(inIsPosix);
+ Q_UNUSED(inAddBase);
+
+ QString path = inPathName.toQString();
+#ifndef Q_OS_WIN
+ path.replace('\\', '/');
+#endif
+ m_Path = Q3DStudio::CString::fromQString(QDir::toNativeSeparators(path));
+}
+
+//=============================================================================
+/**
+ * Create a file by combining the two paths.
+ */
+CUICFile::CUICFile(const Q3DStudio::CString &inPathName, const Q3DStudio::CString &inName)
+{
+ CUICFile theBasePath(inPathName);
+ CUICFile theFile = Combine(theBasePath, inName);
+ m_Path = theFile.GetPath();
+}
+
+//=============================================================================
+/**
+ * Create a file by combining the base path with a relative path.
+ */
+CUICFile::CUICFile(const CUICFile &inBasePath, const Q3DStudio::CString &inPathname, bool inIsPosix)
+{
+ Q_UNUSED(inIsPosix);
+
+ CUICFile theFile(Combine(inBasePath, inPathname));
+ m_Path = theFile.GetPath();
+}
+
+CUICFile::CUICFile(const CUICFile &inFile)
+{
+ m_Path = inFile.m_Path;
+}
+
+//=============================================================================
+/**
+ * Get an iterator for all the sub-files of this directory.
+ */
+CFileIterator CUICFile::GetSubItems() const
+{
+ return CFileIterator(this);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CUICFile::~CUICFile()
+{
+}
+
+bool CUICFile::operator==(const CUICFile &inRHS) const
+{
+#ifdef _WIN32
+ return GetAbsolutePath().CompareNoCase(inRHS.GetAbsolutePath());
+#else
+ return GetAbsolutePath() == inRHS.GetAbsolutePath();
+#endif
+}
+
+//=============================================================================
+/**
+ * Returns true if this is a file and can be read.
+ */
+bool CUICFile::CanRead() const
+{
+ return IsFile();
+}
+
+//=============================================================================
+/**
+ * Returns true if this is a file and can be written to.
+ */
+bool CUICFile::CanWrite() const
+{
+ QFileInfo info(m_Path.toQString());
+ return info.isWritable();
+}
+
+//=============================================================================
+/**
+ * Delete this file from the file system. This will also perform a recursive
+ * delete on the sub folders and files if it is a folder
+ *
+ * @return true if the deletion of file/folder is successful, else false
+ */
+bool CUICFile::DeleteFile() const
+{
+ BOOL theFileDeleted = FALSE;
+
+ // check if AKFile to delete is a folder type, if it is, we want to recusively delete all its
+ // subfolder
+ if (!IsFile()) {
+ theFileDeleted = QDir(m_Path.toQString()).removeRecursively();
+ } else {
+ // delete the requested file or the main folder
+ theFileDeleted = QFile::remove(m_Path.toQString());
+ }
+
+ // erase it from this list
+ s_TempFilePathList.erase(m_Path);
+
+ return theFileDeleted == TRUE;
+}
+
+//=============================================================================
+/**
+ * Check to see if this file or directory exists.
+ */
+bool CUICFile::Exists() const
+{
+ QFileInfo info(m_Path.toQString());
+ return info.exists();
+}
+
+//=============================================================================
+/**
+ * Get the fully qualified absolute path.
+ * This should resolve all relative parts of the path.
+ */
+Q3DStudio::CString CUICFile::GetAbsolutePath() const
+{
+ const QFileInfo fi(m_Path.toQString());
+ if (fi.isDir())
+ return Q3DStudio::CString::fromQString(fi.absoluteFilePath() + QDir::separator());
+ return m_Path;
+}
+
+//=============================================================================
+/**
+ * @see GetAbsolutePath.
+ */
+Q3DStudio::CString CUICFile::GetAbsolutePosixPath() const
+{
+ return GetAbsolutePath();
+}
+
+//=============================================================================
+/**
+ * Get the filename section of this file, ignoring all drives and directories.
+ */
+Q3DStudio::CString CUICFile::GetName() const
+{
+ QFileInfo info(m_Path.toQString());
+ return Q3DStudio::CString::fromQString(info.fileName());
+}
+
+//=============================================================================
+/**
+ * Get the file extension, without the period.
+ */
+Q3DStudio::CString CUICFile::GetExtension() const
+{
+ QFileInfo info(m_Path.toQString());
+ return Q3DStudio::CString::fromQString(info.suffix());
+}
+
+//=============================================================================
+/**
+ * Get the underlying path for this file, this may include relativity.
+ */
+Q3DStudio::CString CUICFile::GetPath() const
+{
+ return m_Path;
+}
+
+//=============================================================================
+/**
+ * Returns true if this file exists and is not a directory.
+ * The param inCheckForAlias is not used in Windows
+ */
+bool CUICFile::IsFile(bool inCheckForAlias /*true*/) const
+{
+ Q_UNUSED(inCheckForAlias);
+ QFileInfo info(m_Path.toQString());
+ return info.isFile();
+}
+
+//=============================================================================
+/**
+ * Check to see if this file or directory is hidden.
+ */
+bool CUICFile::IsHidden() const
+{
+ QFileInfo info(m_Path.toQString());
+ return info.isHidden();
+}
+
+//=============================================================================
+/**
+ * Get the size of this file in bytes.
+ */
+long CUICFile::Length() const
+{
+ QFileInfo info(m_Path.toQString());
+ return info.size();
+}
+
+//=============================================================================
+/**
+ * Rename (or move) this file to the other file.
+ */
+void CUICFile::RenameTo(const CUICFile &inDestination)
+{
+ if (!QFile::rename(m_Path.toQString(), inDestination.GetAbsolutePath().toQString())) {
+ throw CIOException();
+ }
+}
+
+//=============================================================================
+/**
+ * Copy this file to the other file, leaving this file intact.
+ */
+void CUICFile::CopyTo(const CUICFile &inDestination)
+{
+ const QString destination(inDestination.GetAbsolutePath().toQString());
+ if (QFile::exists(destination))
+ QFile::remove(destination);
+ if (!QFile::copy(m_Path.toQString(), destination))
+ throw CIOException();
+}
+
+//=============================================================================
+/**
+ * Make this file read only. or unmark the read only
+ */
+void CUICFile::SetReadOnly(bool inReadOnlyFlag)
+{
+ const QString qpath(m_Path.toQString());
+ QFile::Permissions perm = QFile::permissions(qpath);
+ if (inReadOnlyFlag) {
+ perm &= ~QFile::WriteOwner;
+ } else {
+ perm |= QFile::WriteOwner;
+ }
+ QFile::setPermissions(qpath, perm);
+}
+
+//=============================================================================
+/**
+ * Get the location of where this application resides.
+ */
+CUICFile CUICFile::GetApplicationDirectory()
+{
+#ifdef Q_OS_MACOS
+ QDir appDir(qApp->applicationDirPath());
+ if (appDir.dirName() == "MacOS") {
+ appDir.cdUp();
+ appDir.cd("Resources");
+ }
+ return CUICFile(Q3DStudio::CString::fromQString(appDir.absolutePath()));
+#else
+ return CUICFile(Q3DStudio::CString::fromQString(qApp->applicationDirPath()));
+#endif
+}
+
+//=============================================================================
+/**
+ * Create a temporary file from where the system holds it's temp files.
+ * @param inExtension the file extension that should be used.
+ */
+CUICFile CUICFile::GetTemporaryFile(const Q3DStudio::CString &inExtension)
+{
+ QTemporaryFile tempFile(QDir::tempPath() + "/~uiXXXXXX" + inExtension.toQString());
+ tempFile.setAutoRemove(false);
+ tempFile.open(); // force creation of the actual file name
+ return CUICFile(Q3DStudio::CString::fromQString(tempFile.fileName()));
+}
+
+CUICFile CUICFile::GetTemporaryFile()
+{
+ QTemporaryFile tempFile(QDir::tempPath() + "/~uiXXXXXX");
+ tempFile.setAutoRemove(false);
+ tempFile.open(); // force creation of the actual file name
+ return CUICFile(Q3DStudio::CString::fromQString(tempFile.fileName()));
+}
+
+//=============================================================================
+/**
+ * Get the URL representing this file.
+ */
+QUrl CUICFile::GetURL() const
+{
+ return QUrl::fromLocalFile(m_Path.toQString());
+}
+
+//=============================================================================
+/**
+ * Request the filesystem to open this file in whatever manner it chooses with
+ * the associated application.
+ */
+void CUICFile::Execute() const
+{
+ Q3DStudio::CString sFile = GetAbsolutePath();
+ QUrl url = QUrl::fromLocalFile(sFile.toQString());
+ QDesktopServices::openUrl(url);
+}
+
+//=============================================================================
+/**
+ * Combine the file and relative path together into another file.
+ */
+CUICFile CUICFile::Combine(const CUICFile &inBasePath, const Q3DStudio::CString &inRelativePath)
+{
+ QDir basePath(inBasePath.GetAbsolutePath().toQString());
+ QString rel = basePath.absoluteFilePath(inRelativePath.toQString());
+ return CUICFile(Q3DStudio::CString::fromQString(rel));
+}
+
+//=============================================================================
+/**
+ * Get a file handle for this file that can be used for reading.
+ * The handle must be closed with CloseHandle when finished.
+ */
+HANDLE CUICFile::OpenFileReadHandle() const
+{
+ qFatal("implement me");
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Get a file handle for this file that can be used for writing.
+ * The handle must be closed with CloseHandle when finished.
+ */
+HANDLE CUICFile::OpenFileWriteHandle() const
+{
+ qFatal("implement me");
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Clear all temp files that have been created so far by calling the GetTemporaryFile methods.
+ * This would only clear the temp files that were created during the current program session,
+ * and not any previous files created by anything prior to this session.
+ */
+void CUICFile::ClearCurrentTempCache()
+{
+ if (!s_TempFilePathList.empty()) {
+ // Delete all temp files created so far
+ for (auto file : s_TempFilePathList) {
+ QFile::remove(file.toQString());
+ }
+
+ s_TempFilePathList.clear();
+ }
+}
+
+void CUICFile::AddTempFile(const Q3DStudio::CString &inFile)
+{
+ s_TempFilePathList.insert(inFile);
+}
+
+//=============================================================================
+/**
+ * Checks if a path is relative or not.
+ * Filename-only strings have no path separators and are considered relative.
+ * @param inPath path to check
+ * @return bool true to indicate this is a relative path
+ */
+bool CUICFile::IsPathRelative(const Q3DStudio::CString &inPath)
+{
+ QFileInfo info(inPath.toQString());
+ return info.isRelative();
+}
+
+//=============================================================================
+/**
+ * Retrieves the file 'stat' struct that contains useful information.
+ * @param inStat stat struct to fill
+ * @return true if file stats are successfully obtained
+ */
+bool CUICFile::GetFileStat(struct _stat *inStat) const
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ return ::_wstat(m_Path, inStat) == 0;
+#else
+ return false;
+#endif
+}
diff --git a/src/Authoring/Common/Code/_Win32/DLLVersion.cpp b/src/Authoring/Common/Code/_Win32/DLLVersion.cpp
new file mode 100644
index 00000000..db2992e9
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/DLLVersion.cpp
@@ -0,0 +1,417 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#ifndef INCLUDED_DLL_VERSION_H
+#include "DLLVersion.h"
+#endif
+
+//#include "Global.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <windows.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#define new DEBUG_NEW
+#endif
+
+/***************************************************************************
+
+ Function: GetDLLVersion
+
+ Purpose: Retrieves DLL major version, minor version and build numbers
+
+ Input: DLL file name
+ Reference to Major number
+ Reference to Minor number
+ Reference to Build number
+
+ Output: TRUE only if successful
+
+ Remarks: This function first tries to get the DLL version the nice way,
+ that is, call the DllGetVersion function in the DLL.
+
+ If this fails, it tries to located the DLL file in the file system,
+ read the file information block and retrieve the file version.
+
+****************************************************************************/
+BOOL CDLLVersion::GetDLLVersion(LPCSTR szDLLFileName, DWORD &dwMajor, DWORD &dwMinor,
+ DWORD &outIteration, DWORD &dwBuildNumber)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ HINSTANCE hDllInst; // Instance of loaded DLL
+ char szFileName[_MAX_PATH]; // Temp file name
+ BOOL bRes = TRUE; // Result
+
+ lstrcpyA(szFileName, szDLLFileName); // Save a file name copy for the loading
+
+ hDllInst = LoadLibraryA(szFileName); // load the DLL
+
+ if (hDllInst) // Could successfully load the DLL
+ {
+ DLLGETVERSIONPROC pDllGetVersion;
+ /*
+ You must get this function explicitly because earlier versions of the DLL
+ don't implement this function. That makes the lack of implementation of the
+ function a version marker in itself.
+ */
+ pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hDllInst, "DllGetVersion");
+
+ if (pDllGetVersion) // DLL supports version retrieval function
+ {
+ DLLVERSIONINFO dvi;
+
+ ZeroMemory(&dvi, sizeof(dvi));
+ dvi.cbSize = sizeof(dvi);
+ HRESULT hr = (*pDllGetVersion)(&dvi);
+
+ if (SUCCEEDED(hr)) // Finally, the version is at our hands
+ {
+ dwMajor = dvi.dwMajorVersion;
+ dwMinor = dvi.dwMinorVersion;
+ dwBuildNumber = dvi.dwBuildNumber;
+ outIteration = 0; //:(
+ } else
+ bRes = FALSE; // Failure
+ } else // GetProcAddress failed, the DLL cannot tell its version
+ bRes = FALSE; // Failure
+
+ FreeLibrary(hDllInst); // Release DLL
+ } else
+ bRes = FALSE; // DLL could not be loaded
+
+ if (!bRes) // Cannot read DLL version the nice way
+ {
+ for (int iDir = WIN_DIR; iDir <= NO_DIR; iDir++) // loop for each possible directory
+ {
+ lstrcpyA(szFileName, szDLLFileName); // Save a file name copy for the loading
+ bRes = this->CheckFileVersion(szFileName, iDir, dwMajor, dwMinor, outIteration,
+ dwBuildNumber); // Try the ugly way
+ if (bRes)
+ break;
+ };
+ return bRes;
+ } else
+ return TRUE;
+#endif
+ return FALSE;
+}
+
+/***************************************************************************
+
+ Function: CheckFileVersion
+
+ Purpose: Check the version information of a given file
+
+ Input: File name
+ File location (Windows dir, System dir, Current dir or none)
+ Reference to Major number
+ Reference to Minor number
+ Reference to Build number
+
+ Output: TRUE only if successful
+
+ Remarks: Trashes original file name
+
+****************************************************************************/
+BOOL CDLLVersion::CheckFileVersion(LPSTR szFileName, int FileLoc, DWORD &dwMajor, DWORD &dwMinor,
+ DWORD &outIteration, DWORD &dwBuildNumber)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ UNREFERENCED_PARAMETER(FileLoc);
+ LPSTR lpVersion; // String pointer to 'version' text
+ // UINT uVersionLen;
+ DWORD dwVerHnd = 0; // An 'ignored' parameter, always '0'
+ // VS_FIXEDFILEINFO vsFileInfo;
+
+ // FixFilePath (szFileName, FileLoc); // Add necessary path prefix to file name
+
+ DWORD dwVerInfoSize = GetFileVersionInfoSizeA(szFileName, &dwVerHnd);
+ if (!dwVerInfoSize) // Cannot reach the DLL file
+ return FALSE;
+
+ LPSTR lpstrVffInfo = (LPSTR)malloc(dwVerInfoSize); // Alloc memory for file info
+ if (lpstrVffInfo == NULL)
+ return FALSE; // Allocation failed
+
+ // Try to get the info
+ if (!GetFileVersionInfoA(szFileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo)) {
+ free(lpstrVffInfo);
+ return FALSE; // Cannot read the file information -
+ // wierd, since we could read the information size
+ }
+
+ /* The below 'hex' value looks a little confusing, but
+ essentially what it is, is the hexidecimal representation
+ of a couple different values that represent the language
+ and character set that we are wanting string values for.
+ 040904E4 is a very common one, because it means:
+ US English, Windows MultiLingual characterset
+ Or to pull it all apart:
+ 04------ = SUBLANG_ENGLISH_USA
+ --09---- = LANG_ENGLISH
+ ----04E4 = 1252 = Codepage for Windows:Multilingual
+ */
+ /*static char fileVersion[256];
+ LPVOID version=NULL;
+ DWORD vLen,langD;
+ BOOL retVal;
+
+ sprintf(fileVersion,"\\VarFileInfo\\Translation");
+ retVal = VerQueryValue ( lpstrVffInfo,
+ fileVersion, &version, (UINT *)&uVersionLen);
+ if (retVal && vLen==4)
+ {
+ memcpy(&langD,version,4);
+ sprintf(fileVersion, "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion",
+ (langD & 0xff00)>>8,langD & 0xff,(langD & 0xff000000)>>24,
+ (langD & 0xff0000)>>16);
+ }
+ else
+ sprintf(fileVersion,"\\StringFileInfo\\%04X04B0\\FileVersion",GetUserDefaultLangID());
+
+ if (!VerQueryValue ( lpstrVffInfo, fileVersion,
+ (LPVOID *)&lpVersion, (UINT *)&uVersionLen))
+ {
+ free (lpstrVffInfo);
+ return FALSE; // Query was unsuccessful
+ }
+ */
+ // Now we have a string that looks like this :
+ // "MajorVersion.MinorVersion.BuildNumber", so let's parse it
+ lpVersion = getVersion(szFileName);
+ m_stFullVersion = getVersion(szFileName);
+ BOOL bRes = ParseVersionString(lpVersion, dwMajor, dwMinor, outIteration, dwBuildNumber);
+ if (!bRes)
+ // Lets try for commas
+ bRes = ParseVersionString1(lpVersion, dwMajor, dwMinor, outIteration, dwBuildNumber);
+ free(lpstrVffInfo);
+ return bRes;
+#endif
+ return FALSE;
+}
+
+/***************************************************************************
+
+ Function: ParseVersionString
+
+ Purpose: Parse version information string into 3 different numbers
+
+ Input: The version string formatted as "MajorVersion.MinorVersion.BuildNumber"
+ Reference to Major number
+ Reference to Minor number
+ Reference to Build number
+
+ Output: TRUE only if successful
+
+ Remarks:
+
+****************************************************************************/
+BOOL CDLLVersion::ParseVersionString(LPSTR lpVersion, DWORD &dwMajor, DWORD &dwMinor,
+ DWORD &outIteration, DWORD &dwBuildNumber)
+{
+ // Get first token (Major version number)
+ LPSTR token = strtok(lpVersion, ".");
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ dwMajor = atoi(token);
+
+ token = strtok(NULL, "."); // Get second token (Minor version number)
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ dwMinor = atoi(token);
+
+ token = strtok(NULL, "."); // Get third token (Build number)
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ outIteration = atoi(token);
+
+ token = strtok(NULL, "."); // Get third token (Build number)
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ dwBuildNumber = atoi(token);
+
+ return TRUE;
+}
+
+/***************************************************************************
+
+ Function: FixFilePath
+
+ Purpose: Adds the correct path string to a file name according
+ to given file location
+
+ Input: Original file name
+ File location (Windows dir, System dir, Current dir or none)
+
+ Output: TRUE only if successful
+
+ Remarks: Trashes original file name
+
+****************************************************************************/
+BOOL CDLLVersion::FixFilePath(char *szFileName, int FileLoc)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ char szPathStr[_MAX_PATH]; // Holds path prefix
+
+ switch (FileLoc) {
+ case WIN_DIR:
+ // Get the name of the windows directory
+ if (GetWindowsDirectoryA(szPathStr, _MAX_PATH) == 0)
+ return FALSE; // Cannot get windows directory
+ break;
+
+ case SYS_DIR:
+ // Get the name of the windows SYSTEM directory
+ if (GetSystemDirectoryA(szPathStr, _MAX_PATH) == 0)
+ return FALSE; // Cannot get system directory
+ break;
+
+ case CUR_DIR:
+ // Get the name of the current directory
+ if (GetCurrentDirectoryA(_MAX_PATH, szPathStr) == 0)
+ return FALSE; // Cannot get current directory
+ break;
+
+ case NO_DIR:
+ lstrcpyA(szPathStr, "");
+ break;
+
+ default:
+ return FALSE;
+ }
+ lstrcatA(szPathStr, "\\");
+ lstrcatA(szPathStr, szFileName);
+ lstrcpyA(szFileName, szPathStr);
+ return TRUE;
+#endif
+ return FALSE;
+}
+
+/***************************************************************************
+ Function: ParseVersionString
+ Purpose: Parse version information string into 3 different numbers
+ Input: The version string formatted as "MajorVersion.MinorVersion.BuildNumber"
+ Reference to Major number
+ Reference to Minor number
+ Reference to Build number
+
+ Output: TRUE only if successful
+
+ Remarks:
+
+****************************************************************************/
+BOOL CDLLVersion::ParseVersionString1(LPSTR lpVersion, DWORD &dwMajor, DWORD &dwMinor,
+ DWORD &outIteration, DWORD &dwBuildNumber)
+{
+ // Get first token (Major version number)
+ LPSTR token = strtok(lpVersion, (","));
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ dwMajor = atoi(token);
+
+ token = strtok(NULL, (",")); // Get second token (Minor version number)
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ dwMinor = atoi(token);
+
+ token = strtok(NULL, (",")); // Get third token (Build number)
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ outIteration = atoi(token);
+
+ token = strtok(NULL, (",")); // Get third token (Build number)
+ if (token == NULL) // End of string
+ return FALSE; // String ended prematurely
+ dwBuildNumber = atoi(token);
+
+ return TRUE;
+}
+
+// a static buffer is used to hold the version, calling this function
+// a second time will erase previous information.
+// long paths may be used for this function.
+char *CDLLVersion::getVersion(char *fileName)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ DWORD vSize;
+ DWORD vLen, langD;
+ BOOL retVal;
+
+ LPVOID version = NULL;
+ LPVOID versionInfo = NULL;
+ static char fileVersion[256];
+ bool success = true;
+ vSize = GetFileVersionInfoSizeA(fileName, &vLen);
+ if (vSize) {
+ versionInfo = malloc(vSize + 1);
+ if (GetFileVersionInfoA(fileName, vLen, vSize, versionInfo)) {
+ sprintf(fileVersion, "\\VarFileInfo\\Translation");
+ retVal = VerQueryValueA(versionInfo, fileVersion, &version, (UINT *)&vLen);
+ if (retVal && vLen == 4) {
+ memcpy(&langD, version, 4);
+ sprintf(fileVersion, "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion",
+ (langD & 0xff00) >> 8, langD & 0xff, (langD & 0xff000000) >> 24,
+ (langD & 0xff0000) >> 16);
+ } else
+ sprintf(fileVersion, "\\StringFileInfo\\%04X04B0\\FileVersion",
+ GetUserDefaultLangID());
+ retVal = VerQueryValueA(versionInfo, fileVersion, &version, (UINT *)&vLen);
+ if (!retVal)
+ success = false;
+ } else
+ success = false;
+ } else
+ success = false;
+
+ if (success) {
+ if (vLen < 256)
+ strcpy(fileVersion, (char *)version);
+ else {
+ strncpy(fileVersion, (char *)version, 250);
+ fileVersion[250] = 0;
+ }
+ if (versionInfo)
+ free(versionInfo);
+ versionInfo = NULL;
+ return fileVersion;
+ } else {
+ if (versionInfo)
+ free(versionInfo);
+ versionInfo = NULL;
+ return NULL;
+ }
+#endif
+ return NULL;
+}
diff --git a/src/Authoring/Common/Code/_Win32/DLLVersion.h b/src/Authoring/Common/Code/_Win32/DLLVersion.h
new file mode 100644
index 00000000..092ebb3e
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/DLLVersion.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_DLL_VERSION_H
+#define INCLUDED_DLL_VERSION_H 1
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+/* For some odd reason, Microsoft published a sample code that uses shlwapi.h
+ (and shlwapi.lib)
+ to tinker file versions.
+
+ This header file could not be found anywhere !!!
+ Not in Visual C++ 4.2, Visual C++ 5.0 or MSDN versions up to July 97`.
+
+ So, I just took out the interesting structures from scraps I found
+ and re-defined them here.
+*/
+
+// Remember: You must link version.lib to the project for this class to work !!
+
+#include <string>
+/*
+#ifndef DLLVERSIONINFO
+typedef struct _DllVersionInfo
+{
+ DWORD cbSize;
+ DWORD dwMajorVersion;
+ DWORD dwMinorVersion;
+ DWORD dwBuildNumber;
+ DWORD dwPlatformID;
+}DLLVERSIONINFO;
+
+#endif
+*/
+/*
+#ifndef DLLGETVERSIONPROC
+typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
+#endif
+*/
+class CDLLVersion
+{
+ typedef enum {
+ WIN_DIR, // Windows directory (e.g.: "C:\Windows\")
+ SYS_DIR, // Windows system directory (e.g.: "C:\Windows\System")
+ CUR_DIR, // Current directory (e.g.: ".")
+ NO_DIR
+ } // No directory (path in file name)
+ FileLocationType; // Possible ways to add a path prefix to a file
+
+public:
+ CDLLVersion(LPCSTR szDLLFileName)
+ : m_dwMajor(0)
+ , m_dwMinor(0)
+ , m_dwIteration(0)
+ , m_dwBuild(0)
+ {
+ m_bValid = GetDLLVersion(szDLLFileName, m_dwMajor, m_dwMinor, m_dwIteration, m_dwBuild);
+ }
+
+ virtual ~CDLLVersion(){}
+
+ DWORD GetMajorVersion() { return m_dwMajor; }
+
+ DWORD GetMinorVersion() { return m_dwMinor; }
+
+ DWORD GetBuildNumber() { return m_dwBuild; }
+
+ DWORD GetIterationNumber() { return m_dwIteration; }
+
+ BOOL IsValid() { return m_bValid; }
+
+ std::string GetFullVersion() { return m_stFullVersion; }
+
+private:
+ char *getVersion(char *fileName);
+
+ BOOL GetDLLVersion(LPCSTR szDLLFileName, DWORD &dwMajor, DWORD &dwMinor, DWORD &outIteration,
+ DWORD &dwBuildNumber);
+ BOOL ParseVersionString(LPSTR lpVersion, DWORD &dwMajor, DWORD &dwMinor, DWORD &outIteration,
+ DWORD &dwBuildNumber);
+ BOOL ParseVersionString1(LPSTR lpVersion, DWORD &dwMajor, DWORD &dwMinor, DWORD &outIteration,
+ DWORD &dwBuildNumber);
+ BOOL CheckFileVersion(LPSTR szFileName, int FileLoc, DWORD &dwMajor, DWORD &dwMinor,
+ DWORD &outIteration, DWORD &dwBuildNumber);
+
+ BOOL FixFilePath(char *szFileName, int FileLoc);
+
+ DWORD m_dwMajor; // Major version number
+ DWORD m_dwMinor; // Minor version number
+ DWORD m_dwIteration;
+ DWORD m_dwBuild; // Build number
+ BOOL m_bValid; // Is the DLL version information valid ?
+ std::string m_stFullVersion;
+};
+
+#endif // INCLUDED_DLL_VERSION_H
diff --git a/src/Authoring/Common/Code/_Win32/FileIterator.cpp b/src/Authoring/Common/Code/_Win32/FileIterator.cpp
new file mode 100644
index 00000000..46824df2
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/FileIterator.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FileIterator.h"
+#include "UICFile.h"
+
+#include <QDirIterator>
+
+using namespace Q3DStudio;
+
+//=============================================================================
+/**
+ * Constructor: Takes a snapshot of the directory specified and all further
+ * iterations refer to this snapshot.
+ * @param inFile directory to iterate through
+ */
+CFileIterator::CFileIterator(const CUICFile *inFile)
+{
+ m_File = inFile->GetAbsolutePath();
+
+ QDirIterator it(m_File.toQString(), QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
+ while (it.hasNext()) {
+ it.next();
+ QFileInfo theFindFile = it.fileInfo();
+ Q3DStudio::CString theFullPath = Q3DStudio::CString::fromQString(QDir::toNativeSeparators(theFindFile.absoluteFilePath()));
+ m_FileNames.push_back(theFullPath);
+ }
+
+ m_Index = 0;
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CFileIterator::~CFileIterator()
+{
+ m_FileNames.clear();
+}
+
+//=============================================================================
+/**
+ * @return true if iteration has completed, otherwise false
+ */
+bool CFileIterator::IsDone()
+{
+ return (m_Index >= m_FileNames.size());
+}
+
+//=============================================================================
+/**
+ * Increments the file iterator forward to the next file.
+ */
+void CFileIterator::operator++()
+{
+ ++m_Index;
+}
+
+//=============================================================================
+/**
+ * Increments the file iterator forward by the specified amount.
+ * @param inNumToInc the number of files/directories to skip over
+ */
+void CFileIterator::operator+=(const long inNumToInc)
+{
+ m_Index += inNumToInc;
+ if (m_Index > m_FileNames.size())
+ m_Index = m_FileNames.size();
+}
+
+//=============================================================================
+/**
+ * @return the file or directory currently pointed to by this iterator
+ */
+CUICFile CFileIterator::GetCurrent()
+{
+ return CUICFile(m_FileNames[m_Index]);
+}
+
+//=============================================================================
+/**
+ * @return the number of files and directories in this iterator.
+ */
+size_t CFileIterator::GetTotal()
+{
+ return m_FileNames.size();
+}
diff --git a/src/Authoring/Common/Code/_Win32/Include/PlatformConversion.h b/src/Authoring/Common/Code/_Win32/Include/PlatformConversion.h
new file mode 100644
index 00000000..39a4db74
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Include/PlatformConversion.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef __PLATFORMCONVERSION_H__
+#define __PLATFORMCONVERSION_H__
+
+//==============================================================================
+// This is the WIN32 file for converting platform-specific types to
+// native Studio types and visa-versa.
+//==============================================================================
+
+#ifdef WIN32
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "UICRectBase.h"
+#include "UICPointBase.h"
+
+#ifndef __PLATFORMTYPES_H__
+#include "PlatformTypes.h"
+#endif
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CPlatformConversion
+ * This utility class handles conversions between platform specific data types.
+ */
+//==============================================================================
+class CPlatformConversion
+{
+public:
+ //==============================================================================
+ /**
+ * Convert an UICRect to a Q3DStudio::CRect
+ */
+ //==============================================================================
+ static void UICRectToCRect(const UICRect &inPlatform, Q3DStudio::CRectBase &outRect)
+ {
+ outRect.left = inPlatform.left;
+ outRect.top = inPlatform.top;
+ outRect.right = inPlatform.right;
+ outRect.bottom = inPlatform.bottom;
+ }
+
+ //==============================================================================
+ /**
+ * Convert a Q3DStudio::CRect to an UICRect
+ */
+ //==============================================================================
+ static void CRectToUICRect(const Q3DStudio::CRectBase &inRect, UICRect &outPlatform)
+ {
+ outPlatform.left = inRect.left;
+ outPlatform.top = inRect.top;
+ outPlatform.right = inRect.right;
+ outPlatform.bottom = inRect.bottom;
+ }
+
+ //==============================================================================
+ /**
+ * Convert an UICPoint to an Q3DStudio::CPoint
+ */
+ //==============================================================================
+ static void UICPointToCPoint(const UICPoint &inPlatform, Q3DStudio::CPointBase &outPoint)
+ {
+ outPoint.x = inPlatform.x;
+ outPoint.y = inPlatform.y;
+ }
+
+ //==============================================================================
+ /**
+ * Convert a Q3DStudio::CPoint to an UICPoint
+ */
+ //==============================================================================
+ static void CPointToUICPoint(const Q3DStudio::CPointBase &inPoint, UICPoint &outPlatform)
+ {
+ outPlatform.x = inPoint.x;
+ outPlatform.y = inPoint.y;
+ }
+};
+
+#endif // WIN32
+
+#endif // __PLATFORMCONVERSION_H__
diff --git a/src/Authoring/Common/Code/_Win32/Include/PlatformMacros.h b/src/Authoring/Common/Code/_Win32/Include/PlatformMacros.h
new file mode 100644
index 00000000..946bfb37
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Include/PlatformMacros.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef __PLATFORMMACROS_H__
+#define __PLATFORMMACROS_H__
+
+//==============================================================================
+// This is the WIN32 file for platform specific Macros.
+//==============================================================================
+#ifdef WIN32
+#define UICDEBUGSTRING(a) ::OutputDebugString((const char *)a);
+#endif // WIN32
+#endif // __PLATFORMMACROS_H__
diff --git a/src/Authoring/Common/Code/_Win32/Include/PlatformStrings.h b/src/Authoring/Common/Code/_Win32/Include/PlatformStrings.h
new file mode 100644
index 00000000..3b1317f6
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Include/PlatformStrings.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef __PLATFORMSTRINGS_H__
+#define __PLATFORMSTRINGS_H__
+
+//==============================================================================
+// This is the WIN32 file that maps string functions with dissimilar
+// cross-platform names (thanks Microsoft) to Studio specific names (_a).
+//==============================================================================
+
+#ifdef WIN32
+
+// ASCII string functions
+#define _asnprintf ::_snprintf
+#define _avsnprintf ::_vsnprintf
+
+// UNICODE string functions
+#define _aswprintf ::_snwprintf
+#define _avswprintf ::_vsnwprintf
+#define _awcstok(a, b, c) \
+ ::wcstok(a, b); \
+ c;
+
+#endif // WIN32
+
+#endif // __PLATFORMSTRINGS_H__
diff --git a/src/Authoring/Common/Code/_Win32/Include/PlatformTypes.h b/src/Authoring/Common/Code/_Win32/Include/PlatformTypes.h
new file mode 100644
index 00000000..b0c81c97
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Include/PlatformTypes.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef __PLATFORMTYPES_H__
+#define __PLATFORMTYPES_H__
+
+//==============================================================================
+// This is the WIN32 file that defines the cross-platform data types used
+// by Studio. Whereever possible, these types are mapped directly to existing
+// Windows types.
+//==============================================================================
+
+#include <QtGlobal>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+
+typedef RECT UICRect;
+typedef POINT UICPoint;
+typedef void *UICWindow;
+typedef HWND UICRenderDevice;
+typedef HCURSOR UICCursor;
+
+typedef unsigned __int64 __uint64;
+typedef unsigned long __uint32;
+typedef unsigned char __uint8;
+
+#else
+
+typedef bool BOOL;
+typedef int8_t BYTE;
+typedef int16_t WORD;
+typedef int32_t DWORD;
+typedef int32_t LONG;
+typedef int64_t __int64;
+typedef int64_t LONGLONG;
+typedef void* HANDLE;
+typedef void* HMODULE;
+typedef void* HRESULT;
+typedef const char* LPCTSTR;
+typedef char* LPCSTR;
+typedef char* LPSTR;
+#define UNREFERENCED_PARAMETER(s) Q_UNUSED(s)
+#define TRUE true
+#define FALSE false
+
+typedef DWORD COLORREF;
+typedef DWORD* LPCOLORREF;
+#define GetRValue(rgb) ((BYTE)(rgb & 0xFF))
+#define GetGValue(rgb) ((BYTE) ((rgb >> 8) & 0xFF ) )
+#define GetBValue(rgb) ((BYTE) ((rgb>>16) & 0xFF) )
+#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
+
+struct GUID
+{
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+};
+typedef const GUID& REFGUID;
+
+typedef void* UICWindow;
+typedef void* UICRenderDevice;
+
+typedef union _LARGE_INTEGER {
+ struct {
+ DWORD LowPart;
+ LONG HighPart;
+ };
+ struct {
+ DWORD LowPart;
+ LONG HighPart;
+ } u;
+ LONGLONG QuadPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+
+typedef struct tagPIXELFORMATDESCRIPTOR {
+ WORD nSize;
+ WORD nVersion;
+ DWORD dwFlags;
+ BYTE iPixelType;
+ BYTE cColorBits;
+ BYTE cRedBits;
+ BYTE cRedShift;
+ BYTE cGreenBits;
+ BYTE cGreenShift;
+ BYTE cBlueBits;
+ BYTE cBlueShift;
+ BYTE cAlphaBits;
+ BYTE cAlphaShift;
+ BYTE cAccumBits;
+ BYTE cAccumRedBits;
+ BYTE cAccumGreenBits;
+ BYTE cAccumBlueBits;
+ BYTE cAccumAlphaBits;
+ BYTE cDepthBits;
+ BYTE cStencilBits;
+ BYTE cAuxBuffers;
+ BYTE iLayerType;
+ BYTE bReserved;
+ DWORD dwLayerMask;
+ DWORD dwVisibleMask;
+ DWORD dwDamageMask;
+} PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR;
+
+#endif // WIN32
+
+#endif // __PLATFORMTYPES_H__
diff --git a/src/Authoring/Common/Code/_Win32/Preferences.cpp b/src/Authoring/Common/Code/_Win32/Preferences.cpp
new file mode 100644
index 00000000..9fe5bba9
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Preferences.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "Preferences.h"
+#include "PreferencesSerializer.h"
+#include "StringTokenizer.h"
+
+CPreferencesSerializer CPreferences::s_PreferencesSerializer;
+
+//=============================================================================
+/**
+ * Copy constructor.
+ */
+CPreferences::CPreferences(const CPreferences &inPrefs)
+{
+ m_TagPath = inPrefs.m_TagPath;
+}
+
+CPreferences::~CPreferences()
+{
+}
+
+CPreferences &CPreferences::operator=(const CPreferences &inPrefs)
+{
+ if (&inPrefs != this) {
+ m_TagPath = inPrefs.m_TagPath;
+ }
+ return *this;
+}
+
+//=============================================================================
+/**
+ * Sets the preferences serialization file
+ * This sets the applications base path for all preferences that are to be
+ * loaded. This should be called before any CPreferences are created.
+ * @param inFileName preferences serialization file.
+ */
+void CPreferences::SetPreferencesFile(const Q3DStudio::CString &inFileName)
+{
+ s_PreferencesSerializer.SetPreferencesFile(inFileName);
+}
+
+//=============================================================================
+/**
+ * Get the User Preferences for this application.
+ * This opens the Registry from HKEY_CURRENT_USER with key name set in
+ * SetRegistryRoot.
+ * Any values are in the user specific area of the registry.
+ * @return the user preferences.
+ */
+CPreferences CPreferences::GetUserPreferences()
+{
+ return CPreferences(L"");
+}
+
+//=============================================================================
+/**
+ * Get the User Preferences for this this application.
+ * This opens the Registry from HKEY_CURRENT_USER with the key as inLocation
+ * appended to the Registry Root.
+ * Any values are in the user specific area of the registry.
+ * @param inLocation appended to RegistryRoot to get the sub key location.
+ * @return the user preferences.
+ */
+CPreferences CPreferences::GetUserPreferences(const Q3DStudio::CString &inLocation)
+{
+ return CPreferences(inLocation);
+}
+
+//=============================================================================
+/**
+ * Set the value of inKey to inValue.
+ * @param inKey the name of the key to set.
+ * @param inValue the value for the key.
+ */
+void CPreferences::SetStringValue(const Q3DStudio::CString &inKey,
+ const Q3DStudio::CString &inValue)
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ s_PreferencesSerializer.SetSubElemValue(inKey, inValue);
+}
+
+//=============================================================================
+/**
+ * Get the value of inKey.
+ * @param inKey the name of the key to get.
+ * @param inDefaultValue the value to return if inKey's value cannot be gotten.
+ * @return the value of inKey or inDefaultValue if an error ocurred.
+ */
+Q3DStudio::CString CPreferences::GetStringValue(const Q3DStudio::CString &inKey,
+ const Q3DStudio::CString &inDefaultValue)
+{
+ Q3DStudio::CString theValue;
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ if (!s_PreferencesSerializer.GetSubElemValue(inKey, theValue)) {
+ theValue = inDefaultValue;
+ }
+
+ return theValue;
+}
+
+//=============================================================================
+/**
+ * Set the value of inKey to inValue.
+ * @param inKey the name of the key to set.
+ * @param inValue the value for the key.
+ */
+void CPreferences::SetLongValue(const Q3DStudio::CString &inKey, long inValue)
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ Q3DStudio::CString theStrValue;
+ theStrValue.Format(_UIC("%ld"), inValue);
+
+ s_PreferencesSerializer.SetSubElemValue(inKey, theStrValue);
+}
+
+//=============================================================================
+/**
+ * Get the value of inKey.
+ * @param inKey the name of the key to get.
+ * @param inDefaultValue the value to return if inKey's value cannot be gotten.
+ * @return the value of inKey or inDefaultValue if an error occurred.
+ */
+long CPreferences::GetLongValue(const Q3DStudio::CString &inKey, long inDefaultValue)
+{
+ long theValue;
+ Q3DStudio::CString theStrValue = GetStringValue(inKey, Q3DStudio::CString(""));
+ if (theStrValue == "") {
+ theValue = inDefaultValue;
+ } else {
+ theValue = atol(theStrValue.GetCharStar());
+ }
+
+ return theValue;
+}
+
+//=============================================================================
+/**
+ * Set the value of inKey to inValue.
+ * @param inKey the name of the key to set.
+ * @param inValue the value for the key.
+ */
+void CPreferences::SetValue(const Q3DStudio::CString &inKey, bool inValue)
+{
+ long theRegValue = inValue ? 1 : 0;
+
+ SetLongValue(inKey, theRegValue);
+}
+
+//=============================================================================
+/**
+ * Get the value of inKey.
+ * @param inKey the name of the key to get.
+ * @param inDefaultValue the value to return if inKey's value cannot be gotten.
+ * @return the value of inKey or inDefaultValue if an error occurred.
+ */
+bool CPreferences::GetValue(const Q3DStudio::CString &inKey, bool inDefaultValue)
+{
+ long theDefaultValue = inDefaultValue ? 1 : 0;
+ long theRegValue = GetLongValue(inKey, theDefaultValue);
+
+ return theRegValue ? true : false;
+}
+
+//=============================================================================
+/**
+ * Set the value of inKey to inValue.
+ * @param inKey the name of the key to set.
+ * @param inValue the value for the key.
+ */
+void CPreferences::SetValue(const Q3DStudio::CString &inKey, double inValue)
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ Q3DStudio::CString theStrValue;
+ theStrValue.Format(_UIC("%20.2f"), inValue);
+
+ s_PreferencesSerializer.SetSubElemValue(inKey, theStrValue);
+}
+
+//=============================================================================
+/**
+ * Get the value of inKey.
+ * @param inKey the name of the key to get.
+ * @param inDefaultValue the value to return if inKey's value cannot be gotten.
+ * @return the value of inKey or inDefaultValue if an error occurred.
+ */
+double CPreferences::GetValue(const Q3DStudio::CString &inKey, double inDefaultValue)
+{
+ double theValue;
+ Q3DStudio::CString theStrValue = GetStringValue(inKey, Q3DStudio::CString(""));
+ if (theStrValue == "") {
+ theValue = inDefaultValue;
+ } else {
+ theValue = atof(theStrValue.GetCharStar());
+ }
+
+ return theValue;
+}
+
+//=============================================================================
+/**
+ * Get the value of inKey as a color.
+ * @param inKey the name of the key to get.
+ * @param inDefaultColor the value to return if inKey's value cannot be gotten.
+ * @return the value of inKey or inDefaultColor if an error occurred.
+ */
+CColor CPreferences::GetColorValue(const Q3DStudio::CString &inKey, CColor inDefaultColor)
+{
+ CColor theRetColor = inDefaultColor;
+ Q3DStudio::CString theColorString = GetStringValue(inKey, "");
+ if (theColorString != "") {
+ CStringTokenizer theTokenizer(theColorString, " ");
+ Q3DStudio::CString theR = theTokenizer.GetCurrentPartition();
+ ++theTokenizer;
+ Q3DStudio::CString theG = theTokenizer.GetCurrentPartition();
+ ++theTokenizer;
+ Q3DStudio::CString theB = theTokenizer.GetCurrentPartition();
+
+ theRetColor =
+ ::CColor(atol(theR.GetCharStar()), atol(theG.GetCharStar()), atol(theB.GetCharStar()));
+ }
+ return theRetColor;
+}
+
+//=============================================================================
+/**
+ * Set the value of inKey to inValue.
+ * @param inKey the name of the key to set.
+ * @param inValue the value for the key.
+ */
+void CPreferences::SetColorValue(const Q3DStudio::CString &inKey, CColor inValue)
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ Q3DStudio::CString theStrValue;
+ theStrValue.Format(_UIC("%i %i %i"), inValue.GetRed(), inValue.GetGreen(), inValue.GetBlue());
+ s_PreferencesSerializer.SetSubElemValue(inKey, theStrValue);
+}
+
+void CPreferences::Clear()
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Remove(m_TagPath);
+}
+
+long CPreferences::GetItemCount()
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ return s_PreferencesSerializer.CountSubElems();
+}
+
+//====================================================================
+/**
+ * removes the specified sub element
+ * @param inKeyName the name of the sub element to be removed
+ */
+void CPreferences::RemoveKey(const Q3DStudio::CString &inKeyName)
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ s_PreferencesSerializer.RemoveSubElem(inKeyName);
+}
+
+//====================================================================
+/**
+ * Determines if the key exists
+ * @param inKeyName the name of the subkey
+ */
+bool CPreferences::Exists(const Q3DStudio::CString &inKeyName)
+{
+ s_PreferencesSerializer.Revert();
+ s_PreferencesSerializer.Begin(m_TagPath);
+ return s_PreferencesSerializer.ExistElem(inKeyName);
+} \ No newline at end of file
diff --git a/src/Authoring/Common/Code/_Win32/ProductInfo2.h b/src/Authoring/Common/Code/_Win32/ProductInfo2.h
new file mode 100644
index 00000000..2e52cf4d
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/ProductInfo2.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_PRODUCT_INFO2_H
+#define INCLUDED_PRODUCT_INFO2_H 1
+
+class CProductInfo2
+{
+public:
+ CProductInfo2(std::string inVersion)
+ {
+ TCHAR theModuleFilename[MAX_PATH];
+ ::GetModuleFileName(NULL, theModuleFilename, sizeof(theModuleFilename));
+
+ m_Description = theModuleFilename;
+
+ std::string::size_type thePos = m_Description.rfind("\\");
+ m_Description.erase(0, thePos + 1);
+
+ m_Version = inVersion;
+
+#ifdef _WIN32
+ m_Platform = "Windows";
+#elif _MAC
+ m_Platform = "Macintosh";
+#endif
+
+ m_TabCount = 0;
+ }
+
+ std::string GetDescription() { return m_Description; }
+
+ std::string GetVersion() { return m_Version; }
+
+ std::string GetPlatform() { return m_Platform; }
+
+ void SetTabCount(unsigned long inTabCount) { m_TabCount = inTabCount; }
+
+ friend std::ostream &operator<<(std::ostream &inStream, CProductInfo2 *inProduct)
+ {
+ for (unsigned long i = 0; i < inProduct->m_TabCount; ++i)
+ inStream << "\t";
+
+ inStream << "<Product Description=\"" << inProduct->m_Description.c_str() << "\" Version=\""
+ << inProduct->m_Version.c_str() << "\" Platform=\""
+ << inProduct->m_Platform.c_str() << "\"/>" << std::endl;
+
+ return inStream;
+ }
+
+protected:
+ std::string m_Description;
+ std::string m_Version;
+ std::string m_Platform;
+
+ unsigned long m_TabCount;
+};
+#endif //__PRODUCT_INFO_H2_ \ No newline at end of file
diff --git a/src/Authoring/Common/Code/_Win32/SystemInfo.cpp b/src/Authoring/Common/Code/_Win32/SystemInfo.cpp
new file mode 100644
index 00000000..c77f314b
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/SystemInfo.cpp
@@ -0,0 +1,862 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <atlbase.h>
+#include <objbase.h>
+#endif
+
+#ifndef INCLUDED_SYSTEM_INFO_H
+#include "SystemInfo.h"
+#endif
+
+// const GUID IID_IDirectDraw7 = { 0x15e65ec0, 0x3b9c, 0x11d2, { 0xb9, 0x2f, 0x00, 0x60, 0x97, 0x97,
+// 0xea, 0x5b } };
+
+extern const GUID IID_IDirectDraw7;
+// static const GUID GUID_SCENE2 = { 0xFFFFFFFF, 0xFFFF, 0xFFFF, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+// 0xFF, 0xFF, 0xFF } };
+
+//==============================================================================
+/**
+ * Constructor:
+ */
+//==============================================================================
+CSystemInfo::CSystemInfo()
+{
+ m_TabCount = 0;
+}
+
+//==============================================================================
+/**
+ * Descructor: Destroys the object
+ */
+//==============================================================================
+CSystemInfo::~CSystemInfo()
+{
+}
+
+//==============================================================================
+/**
+ * DetermineConfig: Obtains the overall computer information.
+ *
+ * Operating system, hardware configuration, etc...
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::DetermineConfig()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ HRESULT theResult;
+ CComPtr<IWbemLocator> theLocator;
+ CComPtr<IWbemServices> theServices;
+ CComBSTR theResource = "\\\\.\\root\\cimv2";
+
+ // Initialize COM
+ theResult = ::CoInitialize(NULL);
+ if (SUCCEEDED(theResult)) {
+ // Create WBEM Locator
+ theResult = ::CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_IWbemLocator,
+ (void **)&theLocator);
+ if (theResult == WBEM_S_NO_ERROR && theLocator) {
+ theResult = theLocator->ConnectServer(theResource, NULL, NULL, NULL, 0, NULL, NULL,
+ &theServices);
+ if (theResult == WBEM_S_NO_ERROR && theServices) {
+ // Switch the security level to IMPERSONATE so that provider(s)
+ // will grant access to system-level objects, and so that
+ // CALL authorization will be used.
+ ::CoSetProxyBlanket(theServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
+ RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL,
+ EOAC_NONE);
+
+ // Get the configuration name
+ this->GetConfigName(theServices);
+
+ // Get OS info
+ this->DetermineOS(theServices);
+
+ // Get processor info
+ this->DetermineProcessor(theServices);
+
+ // Get video controller info
+ // this->DetermineVideoController( theServices );
+
+ // Get application info
+ this->DetermineApps(theServices);
+ }
+ }
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * SetTabCount: Sets the tab count for printing in XML format.
+ *
+ * @param <unsigned long> inTabCount The tab count
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::SetTabCount(unsigned long inTabCount)
+{
+ m_TabCount = inTabCount;
+}
+
+//==============================================================================
+/**
+ * GetProcessorString: Formats the processor string. i.e. If more than 1 processor
+ * is present, it is separated by a ,
+ *
+ * @return the formatted string
+ */
+//==============================================================================
+std::string CSystemInfo::GetProcessorString()
+{
+ std::string theReturn;
+
+ unsigned long theI;
+
+ // Processor information
+ for (theI = 0; theI < m_Processors.size(); theI++) {
+ if (theI != 0)
+ theReturn += ", ";
+
+ theReturn += m_Processors[theI].Name + " " + m_Processors[theI].CurrentClockSpeed + "Mhz";
+ }
+
+ theReturn.erase(0, theReturn.find_first_not_of(" \n\r\t"));
+ theReturn.erase(theReturn.find_last_not_of(" \n\r\t") + 1);
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * operator <<: ostream operator used for printing out in XML format.
+ *
+ * @param <std::ostream> inStream The stream
+ *
+ * @param <CSystemInfo*> inConfig Pointer to a CSystemInfo class.
+ *
+ * @return <std::ostream&> Returns the modified stream
+ */
+//==============================================================================
+std::ostream &operator<<(std::ostream &inStream, CSystemInfo *inConfig)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ unsigned long theTabCounter;
+
+ if (::IsBadReadPtr(inConfig, sizeof(CSystemInfo)) == FALSE) {
+// Helper macros for writing XML to stream
+
+// Indent
+#define XML_INDENT \
+ for (theTabCounter = 0; theTabCounter < inConfig->m_TabCount; ++theTabCounter) { \
+ inStream << "\t"; \
+ }
+
+// Newline
+#define XML_NEW_LINE (inStream << std::endl)
+// Beginning tag
+#define XML_BEGIN_TAG(inTagName) (inStream << "<" << inTagName)
+// Name and value
+#define XML_ATTRIBUTE(inTagName, inValue) (inStream << " " << inTagName << "=\"" << inValue << "\"")
+// End tag
+#define XML_END_TAG(inTagName) (inStream << "</" << inTagName << ">")
+// Close tag
+#define XML_CLOSE_TAG (inStream << ">")
+
+ XML_INDENT;
+ XML_BEGIN_TAG("SystemInfo");
+ XML_ATTRIBUTE("MachineName", inConfig->GetMachineName().c_str());
+ XML_ATTRIBUTE("OS", inConfig->m_OS.Name.c_str());
+ std::string theProcessorString = inConfig->GetProcessorString();
+ XML_ATTRIBUTE("Processor", theProcessorString.c_str());
+ XML_ATTRIBUTE("Video", inConfig->m_VideoController.VideoProcessor.c_str());
+ XML_ATTRIBUTE("VideoDriverVersion", inConfig->m_VideoController.DriverVersion.c_str());
+ XML_ATTRIBUTE("DX", inConfig->m_Applications.DXVersion.c_str());
+ XML_CLOSE_TAG;
+ XML_END_TAG("SystemInfo");
+ XML_NEW_LINE;
+ }
+
+ /*
+ unsigned long theTabCounter;
+
+ if ( ::IsBadReadPtr( inConfig, sizeof (CSystemInfo) ) == FALSE )
+ {
+ // Helper macros for writing XML to stream
+
+ // Indent
+ #define XML_INDENT \
+ for ( theTabCounter = 0; theTabCounter < inConfig->m_TabCount; ++theTabCounter )
+ \
+ {
+ \
+ inStream << "\t";
+ \
+ }
+
+ // Newline
+ #define XML_NEW_LINE ( inStream << std::endl
+ )
+ // Beginning tag
+ #define XML_BEGIN_TAG(inTagName) ( inStream << "<" << inTagName
+ )
+ // Name and value
+ #define XML_ATTRIBUTE(inTagName,inValue) ( inStream << " " << inTagName <<
+ "=\"" << inValue << "\"" )
+ // End tag
+ #define XML_END_TAG(inTagName) ( inStream << "</" << inTagName <<
+ ">" )
+ // Close tag
+ #define XML_CLOSE_TAG ( inStream << ">" )
+
+
+ // Begin config tab
+ XML_NEW_LINE;
+ XML_BEGIN_TAG( "Config2" );
+ XML_ATTRIBUTE( "name", inConfig->m_ConfigName.c_str() );
+ XML_ATTRIBUTE( "VisibleMemory", inConfig->m_OS.TotalVisibleMemorySize.c_str() );
+ XML_CLOSE_TAG;
+ XML_NEW_LINE;
+ XML_INDENT;
+
+ // OS information
+ XML_BEGIN_TAG( "OS2" );
+ XML_ATTRIBUTE( "CountryCode", inConfig->m_OS.CountryCode.c_str() );
+ XML_ATTRIBUTE( "Locale", inConfig->m_OS.Locale.c_str() );
+ XML_ATTRIBUTE( "name", inConfig->m_OS.Name.c_str() );
+ XML_ATTRIBUTE( "ServicePacks", inConfig->m_OS.ServicePacks.c_str() );
+ XML_ATTRIBUTE( "Version", inConfig->m_OS.Version.c_str() );
+ XML_CLOSE_TAG;
+ XML_END_TAG( "OS2" );
+ XML_NEW_LINE;
+
+ XML_INDENT;
+
+
+ char theNumProcs[32];
+ itoa( inConfig->m_Processors.size(), theNumProcs, 32 );
+ XML_BEGIN_TAG( "ProcessorConfig" );
+ XML_ATTRIBUTE( "NumProcs", theNumProcs );
+ XML_CLOSE_TAG;
+ XML_NEW_LINE;
+ XML_INDENT;
+ unsigned long theI;
+ // Processor information
+ for( theI = 0; theI < inConfig->m_Processors.size(); theI++ )
+ {
+ XML_BEGIN_TAG( "Processor2" );
+ XML_ATTRIBUTE( "CurrentClockSpeed",
+ inConfig->m_Processors[theI].CurrentClockSpeed.c_str() );
+ XML_ATTRIBUTE( "Manufacturer", inConfig->m_Processors[theI].Manufacturer.c_str()
+ );
+ XML_ATTRIBUTE( "MaxClockSpeed",
+ inConfig->m_Processors[theI].MaxClockSpeed.c_str() );
+ XML_ATTRIBUTE( "name", inConfig->m_Processors[theI].Name.c_str() );
+ XML_ATTRIBUTE( "Version", inConfig->m_Processors[theI].Version.c_str() );
+ XML_CLOSE_TAG;
+ XML_END_TAG( "Processor2" );
+ XML_NEW_LINE;
+
+ XML_INDENT;
+ }
+ XML_END_TAG( "ProcessorConfig" );
+ XML_NEW_LINE;
+ XML_INDENT;
+
+ // Video Controller information
+ XML_BEGIN_TAG( "VideoConfig" );
+ XML_CLOSE_TAG;
+ XML_NEW_LINE;
+ XML_INDENT;
+ XML_BEGIN_TAG( "DisplayConfig" );
+
+ XML_ATTRIBUTE( "ColorDepth", inConfig->m_VideoController.CurrentBitsPerPixel.c_str() );
+ XML_ATTRIBUTE( "HResolution",
+ inConfig->m_VideoController.CurrentHorizontalResolution.c_str() );
+ XML_ATTRIBUTE( "RefreshRate", inConfig->m_VideoController.CurrentRefreshRate.c_str() );
+ XML_ATTRIBUTE( "VResolution",
+ inConfig->m_VideoController.CurrentVerticalResolution.c_str() );
+ XML_CLOSE_TAG;
+ XML_END_TAG( "DisplayConfig" );
+ XML_NEW_LINE;
+ XML_BEGIN_TAG( "VideoAdapter" );
+ XML_ATTRIBUTE( "AdapterRAM", inConfig->m_VideoController.AdapterRAM.c_str() );
+ XML_ATTRIBUTE( "MaxRefreshRate", inConfig->m_VideoController.MaxRefreshRate.c_str() );
+ XML_ATTRIBUTE( "MinRefreshRate", inConfig->m_VideoController.MinRefreshRate.c_str() );
+ XML_CLOSE_TAG;
+ XML_BEGIN_TAG( "VideoChipsets" );
+ XML_ATTRIBUTE( "DriverVersion", inConfig->m_VideoController.DriverVersion.c_str() );
+ XML_ATTRIBUTE( "VideoProcessor", inConfig->m_VideoController.VideoProcessor.c_str() );
+ XML_ATTRIBUTE( "DX7CapsKey", inConfig->m_VideoController.DX7CapsKey.c_str() );
+ XML_CLOSE_TAG;
+ XML_END_TAG( "VideoChipsets" );
+ XML_NEW_LINE;
+ XML_END_TAG( "VideoAdapter" );
+ XML_NEW_LINE;
+
+ XML_END_TAG( "VideoConfig" );
+ XML_NEW_LINE;
+
+ XML_INDENT;
+
+ // Applications information
+ XML_BEGIN_TAG( "Applications" );
+ XML_ATTRIBUTE( "DXVersion", inConfig->m_Applications.DXVersion.c_str() );
+ XML_ATTRIBUTE( "IEVersion", inConfig->m_Applications.IEVersion.c_str() );
+ XML_CLOSE_TAG;
+ XML_END_TAG( "Applications" );
+
+ // End config tag
+ XML_END_TAG( "Config2" );
+ XML_NEW_LINE;
+
+ // Begin config tab
+ XML_BEGIN_TAG( "Renderer" );
+ XML_ATTRIBUTE( "RendererID", inConfig->m_Renderer.c_str() );
+ XML_CLOSE_TAG;
+ XML_END_TAG( "Renderer" );
+ XML_NEW_LINE;
+ }
+ */
+#endif
+ return inStream;
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//==============================================================================
+/**
+ * DetermineOS: Obtains information about the operating system.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::DetermineOS(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_OperatingSystem";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ std::string theSPMajor;
+ std::string theSPMinor;
+
+ // Obtain neede values
+ this->GetObjValue(theObjInstance, CComBSTR("Caption"), m_OS.Name);
+ // this->GetObjValue( theObjInstance, CComBSTR( "name" ), m_OS.Name );
+ this->GetObjValue(theObjInstance, CComBSTR("CountryCode"), m_OS.CountryCode);
+ this->GetObjValue(theObjInstance, CComBSTR("Locale"), m_OS.Locale);
+ this->GetObjValue(theObjInstance, CComBSTR("Version"), m_OS.Version);
+ this->GetObjValue(theObjInstance, CComBSTR("TotalVisibleMemorySize"),
+ m_OS.TotalVisibleMemorySize);
+
+ // Obtain service pack major and minor version and put into string format
+ this->GetObjValue(theObjInstance, CComBSTR("ServicePackMajorVersion"), theSPMajor);
+ this->GetObjValue(theObjInstance, CComBSTR("ServicePackMinorVersion"), theSPMinor);
+ m_OS.ServicePacks = theSPMajor;
+ m_OS.ServicePacks += ".";
+ m_OS.ServicePacks += theSPMinor;
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * DetermineProcessor: Obtains information about the processor.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::DetermineProcessor(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_Processor";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ // Obtain needed values
+ SProcessor theProcessor;
+ this->GetObjValue(theObjInstance, CComBSTR("CurrentClockSpeed"),
+ theProcessor.CurrentClockSpeed);
+ this->GetObjValue(theObjInstance, CComBSTR("DeviceID"), theProcessor.DeviceID);
+ this->GetObjValue(theObjInstance, CComBSTR("Manufacturer"),
+ theProcessor.Manufacturer);
+ this->GetObjValue(theObjInstance, CComBSTR("MaxClockSpeed"),
+ theProcessor.MaxClockSpeed);
+ this->GetObjValue(theObjInstance, CComBSTR("name"), theProcessor.Name);
+ this->GetObjValue(theObjInstance, CComBSTR("Version"), theProcessor.Version);
+ m_Processors.push_back(theProcessor);
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * DetermineVideoController: Obtains information about the video controller.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::DetermineVideoController(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_VideoController";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ // Obtain needed values
+ this->GetObjValue(theObjInstance, CComBSTR("AdapterRAM"),
+ m_VideoController.AdapterRAM);
+ this->GetObjValue(theObjInstance, CComBSTR("CurrentBitsPerPixel"),
+ m_VideoController.CurrentBitsPerPixel);
+ this->GetObjValue(theObjInstance, CComBSTR("CurrentHorizontalResolution"),
+ m_VideoController.CurrentHorizontalResolution);
+ this->GetObjValue(theObjInstance, CComBSTR("CurrentRefreshRate"),
+ m_VideoController.CurrentRefreshRate);
+ this->GetObjValue(theObjInstance, CComBSTR("CurrentVerticalResolution"),
+ m_VideoController.CurrentVerticalResolution);
+ this->GetObjValue(theObjInstance, CComBSTR("DeviceID"), m_VideoController.DeviceID);
+ this->GetObjValue(theObjInstance, CComBSTR("DriverDate"),
+ m_VideoController.DriverDate);
+ this->GetObjValue(theObjInstance, CComBSTR("DriverVersion"),
+ m_VideoController.DriverVersion);
+ this->GetObjValue(theObjInstance, CComBSTR("InstalledDisplayDrivers"),
+ m_VideoController.InstalledDisplayDrivers);
+ this->GetObjValue(theObjInstance, CComBSTR("MaxRefreshRate"),
+ m_VideoController.MaxRefreshRate);
+ this->GetObjValue(theObjInstance, CComBSTR("MinRefreshRate"),
+ m_VideoController.MinRefreshRate);
+ this->GetObjValue(theObjInstance, CComBSTR("name"), m_VideoController.Name);
+ this->GetObjValue(theObjInstance, CComBSTR("VideoProcessor"),
+ m_VideoController.VideoProcessor);
+
+ // Determine video guid
+ this->GetVidGuid();
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * DetermineVideoController: Obtains information about the video controller.
+ *
+ * @param <IWbemServices> Not used yet...
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::DetermineApps(IWbemServices *)
+{
+ // Determine DirectX version
+ this->GetDXVersion();
+
+ // Obtain the Internet Explorer version
+ this->GetIEVersion();
+}
+
+//==============================================================================
+/**
+ * GetObjValue: Obtains the value of a certain property from a WMI object
+ *
+ * @param <IWbemClassObject> inObject Instance of object
+ *
+ * @param <BSTR> inPropName Name of property
+ *
+ * @param <std::string&> ioValue Reference to value
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::GetObjValue(IWbemClassObject *inObject, BSTR inPropName, std::string &ioValue)
+{
+ if (::IsBadReadPtr(inObject, sizeof(IWbemClassObject)) == FALSE) {
+ CComVariant theValue;
+ HRESULT theResult;
+
+ // Obtain property value
+ theResult = inObject->Get(inPropName, 0, &theValue, NULL, NULL);
+ if (SUCCEEDED(theResult)) {
+ // Make sure the variant is valid
+ if (theValue.vt != VT_NULL) {
+ // Change type to BSTR and copy over
+ USES_CONVERSION;
+ theValue.ChangeType(VT_BSTR);
+
+ if (theValue.vt == VT_BSTR) {
+ ioValue = OLE2A(theValue.bstrVal);
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * GetConfigName: Sets the configuration name.
+ *
+ * Queries WMI for the name of the computer and sets this to be the config name.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::GetConfigName(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_ComputerSystem";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ // Obtain the name of this computer system
+ this->GetObjValue(theObjInstance, CComBSTR("name"), m_ConfigName);
+ this->GetObjValue(theObjInstance, CComBSTR("UserName"), m_UserName);
+
+ std::string::size_type thePos = m_UserName.rfind("\\");
+ m_UserName.erase(0, thePos + 1);
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+#endif
+
+std::string CSystemInfo::GetMachineName()
+{
+ return m_ConfigName;
+}
+
+std::string CSystemInfo::GetUserName()
+{
+ return m_UserName;
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//==============================================================================
+/**
+ * GetDXVersion: Obtains the DirectX version.
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::GetDXVersion()
+{
+ CRegKey theRegistryKey;
+
+ m_Applications.DXVersion.erase();
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS
+ == theRegistryKey.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\DirectX",
+ KEY_QUERY_VALUE)) {
+ TCHAR theValueString[MAX_PATH];
+ DWORD theStringSize = sizeof(theValueString);
+
+// NOTE: TEMPORARY COMPILE FIX
+// Are we in VC6 (1200) or VC7 (1300)?
+#if _MSC_VER >= 1300
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryStringValue(_TEXT("Version"), theValueString, &theStringSize))
+#else
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryValue(theValueString, _TEXT("Version"), &theStringSize))
+#endif // _MSC_VER >= 1300
+ {
+ m_Applications.DXVersion = Q3DStudio::CString(theValueString).GetCharStar();
+ }
+
+ theRegistryKey.Close();
+ }
+}
+
+//==============================================================================
+/**
+ * GetIEVersion: Obtains the Internet Explorer version.
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::GetIEVersion()
+{
+ CRegKey theRegistryKey;
+
+ m_Applications.IEVersion.erase();
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS
+ == theRegistryKey.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Internet Explorer",
+ KEY_QUERY_VALUE)) {
+ TCHAR theValueString[MAX_PATH];
+ DWORD theStringSize = sizeof(theValueString);
+
+// NOTE: TEMPORARY COMPILE FIX
+// Are we in VC6 (1200) or VC7 (1300)?
+#if _MSC_VER >= 1300
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryStringValue(_TEXT("Version"), theValueString, &theStringSize))
+#else
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryValue(theValueString, _TEXT("Version"), &theStringSize))
+#endif // _MSC_VER >= 1300
+ {
+ m_Applications.IEVersion = Q3DStudio::CString(theValueString).GetCharStar();
+ }
+
+ theRegistryKey.Close();
+ }
+}
+
+//==============================================================================
+/**
+ * GetVidGuid: Obtains the Internet Explorer version.
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CSystemInfo::GetVidGuid()
+{
+ throw; // draw
+ // typedef HRESULT (WINAPI * DIRECTDRAWCREATEEX) (GUID FAR*, LPVOID *, REFIID, IUnknown FAR *);
+
+ // DIRECTDRAWCREATEEX theDDrawProcAddr;
+ // LPDIRECTDRAW7 theDDraw7Ptr;
+ // HRESULT theResult;
+ // HINSTANCE theDDrawDLL = NULL;
+ //
+
+ // // See if DDRAW.DLL even exists.
+ // theDDrawDLL = ::LoadLibrary( "DDRAW.DLL" );
+
+ //// Get the address of the exported DLL function, DirectDrawCreateEx
+ // theDDrawProcAddr = (DIRECTDRAWCREATEEX)::GetProcAddress( theDDrawDLL, "DirectDrawCreateEx" );
+
+ //// Try calling the exported DLL function, DirectDrawCreateEx
+ // theResult = (*theDDrawProcAddr) ( NULL, reinterpret_cast<void**>(&theDDraw7Ptr),
+ // IID_IDirectDraw7, NULL );
+ // if ( SUCCEEDED( theResult ) && theDDraw7Ptr )
+ //{
+ // WCHAR theDeviceGUID[ _MAX_PATH ];
+ // DDDEVICEIDENTIFIER2 theDevID;
+ // std::string theDriverVersion;
+ //
+ // // Get the video driver info
+ // theDDraw7Ptr->GetDeviceIdentifier( &theDevID, DDGDI_GETHOSTIDENTIFIER );
+
+ // // Convert guid to string
+ // if ( ::StringFromGUID2( theDevID.guidDeviceIdentifier, theDeviceGUID, _MAX_PATH ) )
+ // {
+ // USES_CONVERSION;
+ // m_VideoController.DX7CapsKey = OLE2A( theDeviceGUID );
+
+ // // Grab the version of the driver
+ // if ( GetComponentVersion( theDevID.szDriver, theDriverVersion ) )
+ // {
+ // m_VideoController.DX7CapsKey += ".";
+ // m_VideoController.DX7CapsKey += theDriverVersion;
+ // }
+ // }
+ // else
+ // {
+ // m_VideoController.DX7CapsKey.erase();
+ // }
+ //}
+
+ //// DDraw7 was created successfully. We must be at least DX7.0
+ // theDDraw7Ptr->Release();
+
+ //// Release the DDRAW.DLL
+ //::FreeLibrary( theDDrawDLL );
+}
+
+//==============================================================================
+/**
+ * GetComponentVersion: This method grabs the File Version given the path.
+ *
+ * Given a path, this method will construct a version in the following
+ * format: MajorVersion.MinorVersion.BuildNumber.PlatformID.
+ *
+ * @param inPath The path of the file to retrieve version information on.
+ * @param ioVersion The version of the given file in the format explained
+ * above.
+ *
+ * @return true if the version was determined, otherwise false
+ */
+//==============================================================================
+bool CSystemInfo::GetComponentVersion(LPTSTR inPath, std::string &ioVersion)
+{
+ DWORD theHandle;
+ DWORD theFileVersionSize;
+
+ // Get the file version information
+ if ((theFileVersionSize = ::GetFileVersionInfoSize(inPath, &theHandle)) == 0) {
+ ioVersion.erase();
+ }
+
+ else {
+ // Create a buffer to hold the file version information
+ TCHAR *theFileVersionBuffer = new TCHAR[theFileVersionSize];
+
+ // Get the file version information
+ if (::GetFileVersionInfo(inPath, theHandle, theFileVersionSize, theFileVersionBuffer)
+ == 0) {
+ // we failed getting the version information for some reason
+ ioVersion.erase();
+ }
+
+ else {
+ // Build a version structure
+ VS_FIXEDFILEINFO *theFileVersionStructure;
+ UINT theStructureSize;
+ LPTSTR theSearchString = TEXT("\\\0");
+
+ // Fille the version structure with the basic verison information
+ if (::VerQueryValue(theFileVersionBuffer, theSearchString,
+ reinterpret_cast<void **>(&theFileVersionStructure),
+ &theStructureSize)
+ == 0) {
+ // we failed on something
+ ioVersion.erase();
+ }
+
+ else {
+ // Get the major file version
+ WORD theMajorVer = HIWORD(theFileVersionStructure->dwFileVersionMS);
+ TCHAR theMajorString[_MAX_PATH];
+ ::_ltot(theMajorVer, theMajorString, 10);
+
+ // Get the minor file version
+ WORD theMinorVer = LOWORD(theFileVersionStructure->dwFileVersionMS);
+ TCHAR theMinorString[_MAX_PATH];
+ ::_ltot(theMinorVer, theMinorString, 10);
+
+ // Get the build number
+ WORD theBuildNum = HIWORD(theFileVersionStructure->dwFileVersionLS);
+ TCHAR theBuildNumString[_MAX_PATH];
+ ::_ltot(theBuildNum, theBuildNumString, 10);
+
+ // Get the platform ID
+ WORD thePlatformID = LOWORD(theFileVersionStructure->dwFileVersionLS);
+ TCHAR thePlatformIDString[_MAX_PATH];
+ ::_ltot(thePlatformID, thePlatformIDString, 10);
+
+ // Construct a string to represent the version number
+ Q3DStudio::CString theVersionString;
+ theVersionString = theMajorString;
+ theVersionString += _TEXT(".");
+ theVersionString += theMinorString;
+ theVersionString += _TEXT(".");
+ theVersionString += theBuildNumString;
+ theVersionString += _TEXT(".");
+ theVersionString += thePlatformIDString;
+
+ // We are golden.. copy the version out.
+ ioVersion = theVersionString.GetCharStar();
+ //_tcscpy( ioVersion, theVersionString );
+ }
+ }
+
+ // Delete our newed memory
+ delete[] theFileVersionBuffer;
+ }
+
+ return (!ioVersion.empty());
+}
+#endif
+
+// Get renderer info
+void CSystemInfo::DetermineRenderer(std::string inrenderer)
+{
+ m_Renderer = inrenderer;
+}
diff --git a/src/Authoring/Common/Code/_Win32/SystemInfo.h b/src/Authoring/Common/Code/_Win32/SystemInfo.h
new file mode 100644
index 00000000..18063737
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/SystemInfo.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SYSTEM_INFO_H
+#define INCLUDED_SYSTEM_INFO_H 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifdef WIN32
+#pragma warning(disable : 4819)
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <string>
+#include <vector>
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <Wbemidl.h>
+#endif
+
+using namespace std;
+//==============================================================================
+// Constants
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CSystemInfo
+ *
+ */
+//==============================================================================
+class CSystemInfo
+{
+ //==============================================================================
+ // Structures
+ //==============================================================================
+
+protected:
+ struct SOperatingSystem
+ {
+ std::string CountryCode;
+ std::string Locale;
+ std::string Name;
+ std::string ServicePacks;
+ std::string TotalVisibleMemorySize;
+ std::string Version;
+ };
+
+ struct SProcessor
+ {
+ std::string CurrentClockSpeed;
+ std::string DeviceID;
+ std::string Manufacturer;
+ std::string MaxClockSpeed;
+ std::string Name;
+ std::string Version;
+ };
+
+ struct SVideoController
+ {
+ std::string AdapterRAM;
+ std::string CurrentBitsPerPixel;
+ std::string CurrentHorizontalResolution;
+ std::string CurrentRefreshRate;
+ std::string CurrentVerticalResolution;
+ std::string DeviceID;
+ std::string DriverDate;
+ std::string DriverVersion;
+ std::string InstalledDisplayDrivers;
+ std::string MaxRefreshRate;
+ std::string MinRefreshRate;
+ std::string Name;
+ std::string VideoProcessor;
+ std::string DX7CapsKey;
+ };
+
+ struct SApplications
+ {
+ std::string DXVersion;
+ std::string IEVersion;
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+protected:
+ unsigned long m_TabCount; ///< Number of tabs to print when writing to XML output
+
+ std::string m_ConfigName; ///< The name of this specific configuration
+ std::string m_UserName; ///< User name for machine
+
+public:
+ SOperatingSystem m_OS; ///< Contains inforamtion about the operating system
+ vector<SProcessor> m_Processors; ///< Contains information about the system processor
+ SVideoController m_VideoController; ///< Contains information about the video controller
+ SApplications m_Applications; ///< Contians information about various applications installed
+ std::string m_Renderer;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Construction
+
+public:
+ CSystemInfo();
+ virtual ~CSystemInfo();
+
+ // Access
+
+public:
+ void DetermineConfig();
+ void SetTabCount(unsigned long inTabCount);
+ void DetermineRenderer(std::string inrenderer);
+
+ std::string GetMachineName();
+ std::string GetUserName();
+ std::string GetProcessorString();
+
+ friend std::ostream &operator<<(std::ostream &inStream, CSystemInfo *inConfig);
+
+ // Implementation
+
+protected:
+#ifdef KDAB_TEMPORARILY_REMOVED
+ void DetermineOS(IWbemServices *inServices);
+ void DetermineProcessor(IWbemServices *inServices);
+ void DetermineVideoController(IWbemServices *inServices);
+ void DetermineApps(IWbemServices *inServices);
+ void GetConfigName(IWbemServices *inServices);
+ void GetObjValue(IWbemClassObject *inObject, BSTR inPropName, std::string &ioValue);
+ void GetDXVersion();
+ void GetIEVersion();
+ void GetVidGuid();
+ bool GetComponentVersion(LPTSTR inPath, std::string &outVersion);
+#endif
+};
+
+#endif // INCLUDED_SYSTEM_INFO_H
diff --git a/src/Authoring/Common/Code/_Win32/UICFile.cpp b/src/Authoring/Common/Code/_Win32/UICFile.cpp
new file mode 100644
index 00000000..4cfa3dea
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/UICFile.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICFile.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <shellapi.h> // ShellExecute, etc.
+#include <Urlmon.h> // CoInternetCombineURL, etc.
+#endif
+#include "IOLibraryException.h"
+#include <sys/stat.h> // _stat
+
+// CUICFile originally uses ***W for file ops
+// but this only works for win2k and above (Bug2994)
+// if using plain version is giving too much problem, uncomment the line below
+//#define USE_WIDE_VERSION
+
+//==============================================================================
+// Static variables
+//==============================================================================
+TFilePathList CUICFile::s_TempFilePathList;
+
+//==============================================================================
+// Constants
+//==============================================================================
+#ifdef KDAB_TEMPORARILY_REMOVED
+const Q3DStudio::CString CUICFile::CURRENT_DIR(".\\");
+const Q3DStudio::CString CUICFile::PARENT_DIR("..\\");
+
+//=============================================================================
+/**
+ * Create a new file from the path.
+ * @param inIsPosix ignored.
+ * @param inAddBase ignored.
+ */
+CUICFile::CUICFile(const Q3DStudio::CString &inPathName, bool inIsPosix, bool inAddBase)
+{
+ Q_UNUSED(inIsPosix);
+ Q_UNUSED(inAddBase);
+
+ m_Path = inPathName;
+}
+
+//=============================================================================
+/**
+ * Create a file by combining the two paths.
+ */
+CUICFile::CUICFile(Q3DStudio::CString inPathName, Q3DStudio::CString inName)
+{
+ CUICFile theBasePath(inPathName);
+ CUICFile theFile = Combine(theBasePath, inName);
+ m_Path = theFile.GetPath();
+}
+
+//=============================================================================
+/**
+ * Create a file by combining the base path with a relative path.
+ */
+CUICFile::CUICFile(const CUICFile &inBasePath, const Q3DStudio::CString &inPathname, bool inIsPosix)
+{
+ Q_UNUSED(inIsPosix);
+
+ CUICFile theFile(Combine(inBasePath, inPathname));
+ m_Path = theFile.GetPath();
+}
+
+CUICFile::CUICFile(const CUICFile &inFile)
+{
+ m_Path = inFile.m_Path;
+}
+
+//=============================================================================
+/**
+ * Get an iterator for all the sub-files of this directory.
+ */
+CFileIterator CUICFile::GetSubItems() const
+{
+ return CFileIterator(this);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CUICFile::~CUICFile()
+{
+}
+
+bool CUICFile::operator==(const CUICFile &inRHS) const
+{
+#ifdef _WIN32
+ return GetAbsolutePath().CompareNoCase(inRHS.GetAbsolutePath());
+#else
+ return GetAbsolutePath() == inRHS.GetAbsolutePath();
+#endif
+}
+
+//=============================================================================
+/**
+ * Returns true if this is a file and can be read.
+ */
+bool CUICFile::CanRead() const
+{
+ return IsFile();
+}
+
+//=============================================================================
+/**
+ * Returns true if this is a file and can be written to.
+ */
+bool CUICFile::CanWrite() const
+{
+ long theAttributes = ::GetFileAttributesW(GetAbsolutePath());
+ return (theAttributes != INVALID_FILE_ATTRIBUTES) && !(theAttributes & FILE_ATTRIBUTE_READONLY);
+}
+
+//=============================================================================
+/**
+ * Delete this file from the file system. This will also perform a recursive
+ * delete on the sub folders and files if it is a folder
+ *
+ * @return true if the deletion of file/folder is successful, else false
+ */
+bool CUICFile::DeleteFile() const
+{
+ BOOL theFileDeleted = FALSE;
+
+ // check if AKFile to delete is a folder type, if it is, we want to recusively delete all its
+ // subfolder
+ if (!IsFile()) {
+ CFileIterator theIterator = GetSubItems();
+
+ for (; !theIterator.IsDone(); ++theIterator) {
+ CUICFile theFile = theIterator.GetCurrent();
+ theFile.DeleteFile();
+ }
+ theFileDeleted = ::RemoveDirectory(m_Path);
+ } else {
+ // delete the requested file or the main folder
+ theFileDeleted = ::DeleteFile(m_Path);
+ }
+
+ // erase it from this list
+ s_TempFilePathList.erase(m_Path);
+
+ return theFileDeleted == TRUE;
+}
+
+//=============================================================================
+/**
+ * Check to see if this file or directory exists.
+ */
+bool CUICFile::Exists() const
+{
+#ifdef USE_WIDE_VERSION
+ long theAttributes = ::GetFileAttributesW(GetAbsolutePath());
+#else
+ long theAttributes = ::GetFileAttributes(GetAbsolutePath());
+#endif
+ return theAttributes != INVALID_FILE_ATTRIBUTES;
+}
+
+//=============================================================================
+/**
+ * Get the fully qualified absolute path.
+ * This should resolve all relative parts of the path.
+ */
+Q3DStudio::CString CUICFile::GetAbsolutePath() const
+{
+ return m_Path;
+}
+
+//=============================================================================
+/**
+ * @see GetAbsolutePath.
+ */
+Q3DStudio::CString CUICFile::GetAbsolutePosixPath() const
+{
+ return GetAbsolutePath();
+}
+
+//=============================================================================
+/**
+ * Get the filename section of this file, ignoring all drives and directories.
+ */
+Q3DStudio::CString CUICFile::GetName() const
+{
+ // back/forward slashes counts in a file path (a badly formed, but still acceptable in win32)
+ // apparently, m_Path.ReverseFind( "\\/" ); doesnt work as required
+ // since no file name would consist of '/', a hack here is better than changing ReverseFind
+ // the ideal code would be:
+ //
+ // std::wstring theWString = m_Path.GetWidthString( ); // no luck...
+ // long theIdx = static_cast<long>( theWString.find_last_of( L"\\/" ) );
+ // if ( theIdx == std::wstring::npos )
+ // theIdx = -1;
+ // return m_Path.Extract( theIdx + 1 );
+
+ // so here's the little hack
+ long theIdx1 = m_Path.ReverseFind('\\');
+ long theIdx2 = m_Path.ReverseFind('/');
+ long theIdx = -1;
+ if (theIdx1 != Q3DStudio::CString::ENDOFSTRING) {
+ if (theIdx2 != Q3DStudio::CString::ENDOFSTRING) {
+ // both exist, so take the larger one
+ theIdx = (theIdx1 > theIdx2) ? theIdx1 : theIdx2;
+ } else {
+ theIdx = theIdx1;
+ }
+ } else {
+ if (theIdx2 != Q3DStudio::CString::ENDOFSTRING) {
+ theIdx = theIdx2;
+ } else {
+ theIdx = -1;
+ }
+ }
+ return m_Path.Extract(theIdx + 1);
+
+ // the original version
+ // long theIdx = m_Path.ReverseFind( '\\' );
+ // if ( theIdx != Q3DStudio::CString::ENDOFSTRING )
+ // return m_Path.Extract( theIdx + 1 );
+ // return m_Path;
+}
+
+//=============================================================================
+/**
+ * Get the file extension, without the period.
+ */
+Q3DStudio::CString CUICFile::GetExtension() const
+{
+ long theIdx = m_Path.ReverseFind('.');
+ if (theIdx != Q3DStudio::CString::ENDOFSTRING)
+ return m_Path.Extract(theIdx + 1);
+
+ return "";
+}
+
+//=============================================================================
+/**
+ * Get the underlying path for this file, this may include relativity.
+ */
+Q3DStudio::CString CUICFile::GetPath() const
+{
+ return m_Path;
+}
+
+//=============================================================================
+/**
+ * Returns true if this file exists and is not a directory.
+ * The param inCheckForAlias is not used in Windows
+ */
+bool CUICFile::IsFile(bool inCheckForAlias /*true*/) const
+{
+ Q_UNUSED(inCheckForAlias);
+#ifdef USE_WIDE_VERSION
+ long theAttributes = ::GetFileAttributesW(GetAbsolutePath());
+#else
+ long theAttributes = ::GetFileAttributes(GetAbsolutePath());
+#endif
+ return (theAttributes != INVALID_FILE_ATTRIBUTES)
+ && !(theAttributes & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+//=============================================================================
+/**
+ * Check to see if this file or directory is hidden.
+ */
+bool CUICFile::IsHidden() const
+{
+#ifdef USE_WIDE_VERSION
+ long theAttributes = ::GetFileAttributesW(GetAbsolutePath());
+#else
+ long theAttributes = ::GetFileAttributes(GetAbsolutePath());
+#endif
+ return (theAttributes != INVALID_FILE_ATTRIBUTES) && (theAttributes & FILE_ATTRIBUTE_HIDDEN);
+}
+
+//=============================================================================
+/**
+ * Get the size of this file in bytes.
+ */
+long CUICFile::Length() const
+{
+ HANDLE theFile = OpenFileReadHandle();
+ long theFilesize = ::GetFileSize(theFile, NULL);
+ ::CloseHandle(theFile);
+
+ return theFilesize;
+}
+
+//=============================================================================
+/**
+ * Rename (or move) this file to the other file.
+ */
+void CUICFile::RenameTo(const CUICFile &inDestination)
+{
+#ifdef USE_WIDE_VERSION
+
+ ::MoveFileW(GetAbsolutePath(), inDestination.GetAbsolutePath());
+
+#else
+ // note that destination file must NOT exist
+ if (!::MoveFile(GetAbsolutePath(), inDestination.GetAbsolutePath()))
+ throw CIOException();
+#endif
+}
+
+//=============================================================================
+/**
+ * Copy this file to the other file, leaving this file intact.
+ */
+void CUICFile::CopyTo(const CUICFile &inDestination)
+{
+#ifdef USE_WIDE_VERSION
+ if (!::CopyFileW(GetAbsolutePath(), inDestination.GetAbsolutePath(), FALSE))
+#else
+ if (!::CopyFile(GetAbsolutePath(), inDestination.GetAbsolutePath(), FALSE))
+#endif
+ throw CIOException();
+}
+
+//=============================================================================
+/**
+ * Make this file read only. or unmark the read only
+ */
+void CUICFile::SetReadOnly(bool inReadOnlyFlag)
+{
+#ifdef USE_WIDE_VERSION
+
+ DWORD theFileAttributes = ::GetFileAttributesW(GetAbsolutePath());
+ // If we are setting the file to be readonly
+ if (inReadOnlyFlag)
+ ::SetFileAttributesW(GetAbsolutePath(), theFileAttributes | FILE_ATTRIBUTE_READONLY);
+ else
+ ::SetFileAttributesW(GetAbsolutePath(), theFileAttributes & !FILE_ATTRIBUTE_READONLY);
+
+#else
+
+ DWORD theFileAttributes = ::GetFileAttributes(GetAbsolutePath());
+ // If we are setting the file to be readonly
+ if (inReadOnlyFlag)
+ ::SetFileAttributes(GetAbsolutePath(), theFileAttributes | FILE_ATTRIBUTE_READONLY);
+ else
+ ::SetFileAttributes(GetAbsolutePath(), theFileAttributes & !FILE_ATTRIBUTE_READONLY);
+
+#endif
+}
+
+//=============================================================================
+/**
+ * Get the location of where this application resides.
+ */
+CUICFile CUICFile::GetApplicationDirectory()
+{
+ Q3DStudio::CString theModuleDir;
+ wchar_t theModulePath[MAX_PATH] = { '\0' };
+ DWORD theRetVal = 0;
+
+ theRetVal = ::GetModuleFileNameW(NULL, theModulePath, MAX_PATH - 1);
+ theModulePath[theRetVal] = 0;
+
+ theModuleDir = theModulePath;
+ int theDirSeparatorIdx = theModuleDir.ReverseFind('\\');
+ if (theDirSeparatorIdx != Q3DStudio::CString::ENDOFSTRING)
+ theModuleDir = theModuleDir.Extract(0, theDirSeparatorIdx + 1);
+
+ return theModuleDir;
+}
+
+//=============================================================================
+/**
+ * Create a temporary file from where the system holds it's temp files.
+ * @param inExtension the file extension that should be used.
+ */
+CUICFile CUICFile::GetTemporaryFile(const Q3DStudio::CString &inExtension)
+{
+ wchar_t theTempPath[MAX_PATH] = { '\0' };
+ // char theTempFileName[MAX_PATH] = {'\0'};
+
+ // Get the temporary file directory name
+ ::GetTempPath(sizeof(theTempPath), theTempPath);
+
+ Q3DStudio::CString theTempFile(theTempPath);
+ theTempFile += L"Untitled." + inExtension;
+ /*
+ // Build a temporary filename
+ ::GetTempFileName( theTempPath, "~ui", 0, theTempFileName );
+
+ theTempFile = Q3DStudio::CString( theTempFileName );
+
+ theTempFile += ".";
+ theTempFile += inExtension;
+ */
+ // Ensure the file does not exist
+ ::DeleteFile(theTempFile);
+
+ s_TempFilePathList.insert(theTempFile);
+
+ return CUICFile(theTempFile);
+}
+
+CUICFile CUICFile::GetTemporaryFile()
+{
+ wchar_t theTempPath[MAX_PATH] = { '\0' };
+ wchar_t theTempFileName[MAX_PATH] = { '\0' };
+
+ // Get the temporary file directory name
+ ::GetTempPath(MAX_PATH, theTempPath);
+
+ // Build a temporary filename
+ if (::GetTempFileName(theTempPath, L"~ui", 0, theTempFileName) != 0) {
+ Q3DStudio::CString theTempFile(theTempFileName);
+ s_TempFilePathList.insert(theTempFile);
+ return CUICFile(theTempFile);
+ }
+ // return "" if the system fails us.
+ return CUICFile("");
+}
+
+//=============================================================================
+/**
+ * Get the URL representing this file.
+ */
+CURL CUICFile::GetURL() const
+{
+ Q3DStudio::CString thePath(m_Path);
+
+ // Return a fully qualified path if m_Path is relative.
+ if ((thePath.Find(CURRENT_DIR) == 0) || (thePath.Find(PARENT_DIR) == 0)) {
+ if (thePath.Find(CURRENT_DIR) == 0)
+ thePath.Delete(0, CURRENT_DIR.Length());
+
+ thePath.Insert(0, CUICFile::GetApplicationDirectory().GetAbsolutePosixPath());
+ }
+
+ return CURL(thePath);
+}
+
+//=============================================================================
+/**
+ * Request the filesystem to open this file in whatever manner it chooses with
+ * the associated application.
+ */
+void CUICFile::Execute() const
+{
+ Q3DStudio::CString sFile = GetAbsolutePath();
+
+ SHELLEXECUTEINFO sei;
+ ::ZeroMemory(&sei, sizeof(sei));
+ sei.cbSize = sizeof(sei);
+ sei.hwnd = ::GetActiveWindow();
+ sei.nShow = SW_SHOW;
+ sei.lpFile = sFile;
+ sei.fMask = SEE_MASK_INVOKEIDLIST;
+ ::ShellExecuteEx(&sei);
+}
+
+//=============================================================================
+/**
+ * Combine the file and relative path together into another file.
+ */
+CUICFile CUICFile::Combine(const CUICFile &inBasePath, const Q3DStudio::CString &inRelativePath)
+{
+ Q3DStudio::CString theFullPath;
+
+ const int MAX_BUFFER_SIZE = 512;
+
+ DWORD theBufferSize;
+ WCHAR theResultBuffer[MAX_BUFFER_SIZE];
+
+ wchar_t *theWorkingDir =
+ const_cast<wchar_t *>(static_cast<const wchar_t *>(inBasePath.GetAbsolutePath()));
+ wchar_t *theRelPath = const_cast<wchar_t *>(static_cast<const wchar_t *>(inRelativePath));
+
+ // This method is a bit of black magic, but seems to work well for client.
+ HRESULT theResult = CoInternetCombineUrl(theWorkingDir, theRelPath, 0, theResultBuffer,
+ MAX_BUFFER_SIZE, &theBufferSize, 0);
+ if (SUCCEEDED(theResult)) {
+ // I can find no reference to the flags parameter for CoInternetCombineUrl, maybe
+ // it does something, maybe not, anyway, to get rid of the %20 for spaces (and other
+ // special characters) that this function creates, we need to call the following function
+
+ theResult = CoInternetParseUrl(theResultBuffer, PARSE_UNESCAPE, 0, theResultBuffer,
+ MAX_BUFFER_SIZE, &theBufferSize, 0);
+ theResult = CoInternetParseUrl(theResultBuffer, PARSE_PATH_FROM_URL, 0, theResultBuffer,
+ MAX_BUFFER_SIZE, &theBufferSize, 0);
+
+ theFullPath = theResultBuffer;
+ }
+
+ return theFullPath;
+}
+
+//=============================================================================
+/**
+ * Get a file handle for this file that can be used for reading.
+ * The handle must be closed with CloseHandle when finished.
+ */
+HANDLE CUICFile::OpenFileReadHandle() const
+{
+#ifdef USE_WIDE_VERSION
+
+ return ::CreateFileW(GetAbsolutePath(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+#else
+
+ return ::CreateFile(GetAbsolutePath(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+#endif
+}
+
+//=============================================================================
+/**
+ * Get a file handle for this file that can be used for writing.
+ * The handle must be closed with CloseHandle when finished.
+ */
+HANDLE CUICFile::OpenFileWriteHandle() const
+{
+#ifdef USE_WIDE_VERSION
+
+ return ::CreateFileW(GetAbsolutePath(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+#else
+
+ return ::CreateFile(GetAbsolutePath(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+#endif
+}
+
+//=============================================================================
+/**
+ * Clear all temp files that have been created so far by calling the GetTemporaryFile methods.
+ * This would only clear the temp files that were created during the current program session,
+ * and not any previous files created by anything prior to this session.
+ */
+void CUICFile::ClearCurrentTempCache()
+{
+ TFilePathListIterator theTempFileIterator;
+
+ if (!s_TempFilePathList.empty()) {
+ // Delete all temp files created so far
+ for (theTempFileIterator = s_TempFilePathList.begin();
+ theTempFileIterator != s_TempFilePathList.end(); ++theTempFileIterator)
+ ::DeleteFile((*theTempFileIterator));
+
+ s_TempFilePathList.clear();
+ }
+}
+
+void CUICFile::AddTempFile(const Q3DStudio::CString &inFile)
+{
+ s_TempFilePathList.insert(inFile);
+}
+
+//=============================================================================
+/**
+ * Checks if a path is relative or not.
+ * Filename-only strings have no path separators and are considered relative.
+ * @param inPath path to check
+ * @return bool true to indicate this is a relative path
+ */
+bool CUICFile::IsPathRelative(const Q3DStudio::CString &inPath)
+{
+ bool theIsRelative = false;
+
+ if (!inPath.IsEmpty()) {
+ // relative paths start with a '.' or is just a filename entry
+ theIsRelative =
+ (inPath.GetAt(0) == L'.') || (inPath.Find('\\') == Q3DStudio::CString::ENDOFSTRING);
+ }
+
+ return theIsRelative;
+}
+
+//=============================================================================
+/**
+ * Retrieves the file 'stat' struct that contains useful information.
+ * @param inStat stat struct to fill
+ * @return true if file stats are successfully obtained
+ */
+bool CUICFile::GetFileStat(struct _stat *inStat) const
+{
+ return ::_wstat(m_Path, inStat) == 0;
+}
+#endif
diff --git a/src/Authoring/Common/Code/_Win32/UICRegistry.cpp b/src/Authoring/Common/Code/_Win32/UICRegistry.cpp
new file mode 100644
index 00000000..9cdf46f3
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/UICRegistry.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICRegistry.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CUICRegistry::CUICRegistry()
+{
+}
+
+CUICRegistry::~CUICRegistry()
+{
+}
+
+//==============================================================================
+/**
+ * GetValueKey: Query the specified value from the specified key.
+ *
+ * @param inKeyName
+ * The path and name of the key
+ *
+ * @param inValueName
+ * The value name
+ *
+ * @param outValueString
+ * Returns the value string
+ *
+ * @param inKeyRoot
+ * [ optional ] The registry root (defaults to HKEY_CURRENT_USER)
+ *
+ * @return HRESULT
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+//==============================================================================
+BOOL CUICRegistry::GetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName,
+ Q3DStudio::CString &outValueString, HKEY inKeyRoot)
+{
+ BOOL theResult = FALSE;
+ CRegKey theRegistryKey;
+
+ outValueString = "";
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS == theRegistryKey.Open(inKeyRoot, inKeyName.c_str(), KEY_QUERY_VALUE)) {
+ TCHAR theValueString[MAX_PATH];
+ DWORD theStringSize = sizeof(theValueString);
+
+ // if ( ERROR_SUCCESS == theRegistryKey.QueryValue( (LPTSTR) theValueString, inValueName,
+ // &theStringSize ) )
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryStringValue(inValueName.c_str(), (LPTSTR)theValueString,
+ &theStringSize)) {
+ outValueString = theValueString;
+ theResult = TRUE;
+ }
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * SetValueKey: Query the specified value from the specified key.
+ *
+ * @param inKeyName
+ * The path and name of the key
+ *
+ * @param inValueName
+ * The value name
+ *
+ * @param inValueString
+ * The value string to ser
+ *
+ * @param inKeyRoot
+ * [ optional ] The registry root (defaults to HKEY_CURRENT_USER)
+ *
+ * @return HRESULT
+ */
+//==============================================================================
+BOOL CUICRegistry::SetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName,
+ const Q3DStudio::CString &inValueString, HKEY inKeyRoot)
+{
+ BOOL theResult = FALSE;
+ CRegKey theRegistryKey;
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS == theRegistryKey.Create(inKeyRoot, inKeyName)) {
+ // if ( ERROR_SUCCESS == theRegistryKey.SetValue( inValueString, inValueName ) )
+ if (ERROR_SUCCESS == theRegistryKey.SetStringValue(inValueName, inValueString)) {
+ theResult = TRUE;
+ }
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * GetValueKey: Query the specified value from the specified key.
+ *
+ * @param inKeyName
+ * The path and name of the key
+ *
+ * @param inValueName
+ * The value name
+ *
+ * @param outValueString
+ * Returns the value string
+ *
+ * @param inKeyRoot
+ * [ optional ] The registry root (defaults to HKEY_CURRENT_USER)
+ *
+ * @return HRESULT
+ */
+//==============================================================================
+BOOL CUICRegistry::GetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName, long &outValue,
+ HKEY inKeyRoot)
+{
+ BOOL theResult = FALSE;
+ CRegKey theRegistryKey;
+
+ outValue = 0;
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS == theRegistryKey.Open(inKeyRoot, inKeyName, KEY_QUERY_VALUE)) {
+ // if ( ERROR_SUCCESS == theRegistryKey.QueryValue( (DWORD&) outValue, inValueName ) )
+ if (ERROR_SUCCESS == theRegistryKey.QueryDWORDValue(inValueName, (DWORD &)outValue)) {
+ theResult = TRUE;
+ }
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * SetValueKey: Query the specified value from the specified key.
+ *
+ * @param inKeyName
+ * The path and name of the key
+ *
+ * @param inValueName
+ * The value name
+ *
+ * @param inValueString
+ * The value string to set
+ *
+ * @param inKeyRoot
+ * [ optional ] The registry root (defaults to HKEY_CURRENT_USER)
+ *
+ * @return HRESULT
+ */
+//==============================================================================
+BOOL CUICRegistry::SetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName, long inValue, HKEY inKeyRoot)
+{
+ BOOL theResult = FALSE;
+ CRegKey theRegistryKey;
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS == theRegistryKey.Create(inKeyRoot, inKeyName)) {
+ // if ( ERROR_SUCCESS == theRegistryKey.SetValue( inValue, inValueName ) )
+ if (ERROR_SUCCESS == theRegistryKey.SetDWORDValue(inValueName, inValue)) {
+ theResult = TRUE;
+ }
+ }
+
+ return theResult;
+}
+#endif
diff --git a/src/Authoring/Common/Code/_Win32/UICRegistry.h b/src/Authoring/Common/Code/_Win32/UICRegistry.h
new file mode 100644
index 00000000..1750b966
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/UICRegistry.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_UICREGISTRY_H__9E9A6CBC_0465_457A_9EFC_40835D4A8CA6__INCLUDED_)
+#define AFX_UICREGISTRY_H__9E9A6CBC_0465_457A_9EFC_40835D4A8CA6__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "UICString.h"
+
+//==============================================================================
+/**
+ * @class CUICRegistry
+ * @brief Studio Client Registry Functions.
+ *
+ * Registry entries:
+ * - Stores the latest installed version.
+ */
+//==============================================================================
+class CUICRegistry
+{
+public:
+ CUICRegistry();
+ virtual ~CUICRegistry();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ static BOOL GetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName,
+ Q3DStudio::CString &outValueString, HKEY inKeyRoot = HKEY_CURRENT_USER);
+ static BOOL SetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName,
+ const Q3DStudio::CString &inValueString,
+ HKEY inKeyRoot = HKEY_CURRENT_USER);
+
+ static BOOL GetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName, long &outValue,
+ HKEY inKeyRoot = HKEY_CURRENT_USER);
+ static BOOL SetValueKey(const Q3DStudio::CString &inKeyName,
+ const Q3DStudio::CString &inValueName, long inValue,
+ HKEY inKeyRoot = HKEY_CURRENT_USER);
+#endif
+};
+
+#endif // !defined(AFX_UICREGISTRY_H__9E9A6CBC_0465_457A_9EFC_40835D4A8CA6__INCLUDED_)
diff --git a/src/Authoring/Common/Code/_Win32/Win32Config.cpp b/src/Authoring/Common/Code/_Win32/Win32Config.cpp
new file mode 100644
index 00000000..31cbdc18
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Win32Config.cpp
@@ -0,0 +1,720 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <objbase.h>
+#include <atlbase.h>
+#endif
+
+#ifndef INCLUDED_WIN32_CONFIG_H
+#include "Win32Config.h"
+#endif
+#ifdef _WIN32
+#pragma comment (lib,"version.lib")
+#endif
+
+//==============================================================================
+/**
+ * Constructor:
+ */
+//==============================================================================
+CWin32Config::CWin32Config()
+{
+}
+
+//==============================================================================
+/**
+ * Descructor: Destroys the object
+ */
+//==============================================================================
+CWin32Config::~CWin32Config()
+{
+}
+
+//==============================================================================
+/**
+ * DetermineConfig: Obtains the overall computer information.
+ *
+ * Operating system, hardware configuration, etc...
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::DetermineConfig()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ HRESULT theResult;
+ CComPtr<IWbemLocator> theLocator;
+ CComPtr<IWbemServices> theServices;
+ CComBSTR theResource = "\\\\.\\root\\cimv2";
+
+ // Initialize COM
+ theResult = ::CoInitialize(NULL);
+ if (SUCCEEDED(theResult)) {
+ // Create WBEM Locator
+ theResult = ::CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_IWbemLocator,
+ (void **)&theLocator);
+ if (theResult == WBEM_S_NO_ERROR && theLocator) {
+ theResult =
+ theLocator->ConnectServer(theResource, NULL, NULL, NULL,
+ WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &theServices);
+ if (theResult == WBEM_S_NO_ERROR && theServices) {
+ // Switch the security level to IMPERSONATE so that provider(s)
+ // will grant access to system-level objects, and so that
+ // CALL authorization will be used.
+ ::CoSetProxyBlanket(theServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
+ RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL,
+ EOAC_NONE);
+
+ // Get the configuration name
+ GetConfigName(theServices);
+
+ // Get OS info
+ DetermineOS(theServices);
+
+ // Get processor info
+ DetermineProcessor(theServices);
+
+ // Get video controller info
+ DetermineVideoController(theServices);
+
+ // Get application info
+ DetermineApps(theServices);
+ }
+ }
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * WriteXML: method used for printing out in XML format.
+ *
+ * @param <std::ostream> inStream The stream we are writing to
+ */
+//==============================================================================
+void CWin32Config::WriteXML(std::ostream &inStream)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ unsigned long theTabCounter;
+
+// Helper macros for writing XML to stream
+
+// Indent
+#define XML_INDENT \
+ for (theTabCounter = 0; theTabCounter < m_TabCount; ++theTabCounter) { \
+ inStream << "\t"; \
+ }
+
+// Newline
+#define XML_NEW_LINE (inStream << std::endl)
+// Beginning tag
+#define XML_BEGIN_TAG(inTagName) (inStream << "<" << inTagName)
+// Name and value
+#define XML_ATTRIBUTE(inTagName, inValue) (inStream << " " << inTagName << "=\"" << inValue << "\"")
+// End tag
+#define XML_END_TAG(inTagName) (inStream << "</" << inTagName << ">")
+// Close tag
+#define XML_CLOSE_TAG (inStream << ">")
+
+ // Begin config tab
+ XML_NEW_LINE;
+ XML_BEGIN_TAG("Config2");
+ XML_ATTRIBUTE("name", m_ConfigName.c_str());
+ XML_ATTRIBUTE("VisibleMemory", m_OS.TotalVisibleMemorySize.c_str());
+ XML_CLOSE_TAG;
+ XML_NEW_LINE;
+ XML_INDENT;
+
+ // OS information
+ XML_BEGIN_TAG("OS2");
+ XML_ATTRIBUTE("CountryCode", m_OS.CountryCode.c_str());
+ XML_ATTRIBUTE("Locale", m_OS.Locale.c_str());
+ XML_ATTRIBUTE("name", m_OS.Name.c_str());
+ XML_ATTRIBUTE("ServicePacks", m_OS.ServicePacks.c_str());
+ XML_ATTRIBUTE("Version", m_OS.Version.c_str());
+ XML_CLOSE_TAG;
+ XML_END_TAG("OS2");
+ XML_NEW_LINE;
+
+ XML_INDENT;
+
+ char theNumProcs[32];
+ _itoa((int)m_Processors.size(), theNumProcs, 32);
+ XML_BEGIN_TAG("ProcessorConfig");
+ XML_ATTRIBUTE("NumProcs", theNumProcs);
+ XML_CLOSE_TAG;
+ XML_NEW_LINE;
+ XML_INDENT;
+ unsigned long theI;
+ // Processor information
+ for (theI = 0; theI < m_Processors.size(); theI++) {
+ XML_BEGIN_TAG("Processor2");
+ XML_ATTRIBUTE("CurrentClockSpeed", m_Processors[theI].CurrentClockSpeed.c_str());
+ XML_ATTRIBUTE("Manufacturer", m_Processors[theI].Manufacturer.c_str());
+ XML_ATTRIBUTE("MaxClockSpeed", m_Processors[theI].MaxClockSpeed.c_str());
+ XML_ATTRIBUTE("name", m_Processors[theI].Name.c_str());
+ XML_ATTRIBUTE("Version", m_Processors[theI].Version.c_str());
+ XML_CLOSE_TAG;
+ XML_END_TAG("Processor2");
+ XML_NEW_LINE;
+
+ XML_INDENT;
+ }
+ XML_END_TAG("ProcessorConfig");
+ XML_NEW_LINE;
+ XML_INDENT;
+
+ // Video Controller information
+ XML_BEGIN_TAG("VideoConfig");
+ XML_CLOSE_TAG;
+ XML_NEW_LINE;
+ XML_INDENT;
+ XML_BEGIN_TAG("DisplayConfig");
+
+ XML_ATTRIBUTE("ColorDepth", m_VideoController.CurrentBitsPerPixel.c_str());
+ XML_ATTRIBUTE("HResolution", m_VideoController.CurrentHorizontalResolution.c_str());
+ XML_ATTRIBUTE("RefreshRate", m_VideoController.CurrentRefreshRate.c_str());
+ XML_ATTRIBUTE("VResolution", m_VideoController.CurrentVerticalResolution.c_str());
+ XML_CLOSE_TAG;
+ XML_END_TAG("DisplayConfig");
+ XML_NEW_LINE;
+ XML_BEGIN_TAG("VideoAdapter");
+ XML_ATTRIBUTE("AdapterRAM", m_VideoController.AdapterRAM.c_str());
+ XML_ATTRIBUTE("MaxRefreshRate", m_VideoController.MaxRefreshRate.c_str());
+ XML_ATTRIBUTE("MinRefreshRate", m_VideoController.MinRefreshRate.c_str());
+ XML_CLOSE_TAG;
+ XML_BEGIN_TAG("VideoChipsets");
+ XML_ATTRIBUTE("DriverVersion", m_VideoController.DriverVersion.c_str());
+ XML_ATTRIBUTE("VideoProcessor", m_VideoController.VideoProcessor.c_str());
+ XML_ATTRIBUTE("DX7CapsKey", m_VideoController.DX7CapsKey.c_str());
+ XML_CLOSE_TAG;
+ XML_END_TAG("VideoChipsets");
+ XML_NEW_LINE;
+ XML_END_TAG("VideoAdapter");
+ XML_NEW_LINE;
+
+ XML_END_TAG("VideoConfig");
+ XML_NEW_LINE;
+
+ XML_INDENT;
+
+ // Applications information
+ XML_BEGIN_TAG("Applications");
+ XML_ATTRIBUTE("DXVersion", m_Applications.DXVersion.c_str());
+ XML_ATTRIBUTE("IEVersion", m_Applications.IEVersion.c_str());
+ XML_CLOSE_TAG;
+ XML_END_TAG("Applications");
+
+ // End config tag
+ XML_END_TAG("Config2");
+ XML_NEW_LINE;
+#endif
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//==============================================================================
+/**
+ * DetermineOS: Obtains information about the operating system.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::DetermineOS(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_OperatingSystem";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ std::string theSPMajor;
+ std::string theSPMinor;
+
+ // Obtain neede values
+ GetObjValue(theObjInstance, CComBSTR("name"), m_OS.Name);
+ GetObjValue(theObjInstance, CComBSTR("CountryCode"), m_OS.CountryCode);
+ GetObjValue(theObjInstance, CComBSTR("Locale"), m_OS.Locale);
+ GetObjValue(theObjInstance, CComBSTR("Version"), m_OS.Version);
+ GetObjValue(theObjInstance, CComBSTR("TotalVisibleMemorySize"),
+ m_OS.TotalVisibleMemorySize);
+
+ // Obtain service pack major and minor version and put into string format
+ GetObjValue(theObjInstance, CComBSTR("ServicePackMajorVersion"), theSPMajor);
+ GetObjValue(theObjInstance, CComBSTR("ServicePackMinorVersion"), theSPMinor);
+ m_OS.ServicePacks = theSPMajor;
+ m_OS.ServicePacks += ".";
+ m_OS.ServicePacks += theSPMinor;
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * DetermineProcessor: Obtains information about the processor.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::DetermineProcessor(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_Processor";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ // Obtain needed values
+ SProcessor theProcessor;
+ GetObjValue(theObjInstance, CComBSTR("CurrentClockSpeed"),
+ theProcessor.CurrentClockSpeed);
+ GetObjValue(theObjInstance, CComBSTR("DeviceID"), theProcessor.DeviceID);
+ GetObjValue(theObjInstance, CComBSTR("Manufacturer"), theProcessor.Manufacturer);
+ GetObjValue(theObjInstance, CComBSTR("MaxClockSpeed"), theProcessor.MaxClockSpeed);
+ GetObjValue(theObjInstance, CComBSTR("name"), theProcessor.Name);
+ GetObjValue(theObjInstance, CComBSTR("Version"), theProcessor.Version);
+ m_Processors.push_back(theProcessor);
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * DetermineVideoController: Obtains information about the video controller.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::DetermineVideoController(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_VideoController";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ // Obtain needed values
+ GetObjValue(theObjInstance, CComBSTR("AdapterRAM"), m_VideoController.AdapterRAM);
+ GetObjValue(theObjInstance, CComBSTR("CurrentBitsPerPixel"),
+ m_VideoController.CurrentBitsPerPixel);
+ GetObjValue(theObjInstance, CComBSTR("CurrentHorizontalResolution"),
+ m_VideoController.CurrentHorizontalResolution);
+ GetObjValue(theObjInstance, CComBSTR("CurrentRefreshRate"),
+ m_VideoController.CurrentRefreshRate);
+ GetObjValue(theObjInstance, CComBSTR("CurrentVerticalResolution"),
+ m_VideoController.CurrentVerticalResolution);
+ GetObjValue(theObjInstance, CComBSTR("DeviceID"), m_VideoController.DeviceID);
+ GetObjValue(theObjInstance, CComBSTR("DriverDate"), m_VideoController.DriverDate);
+ GetObjValue(theObjInstance, CComBSTR("DriverVersion"),
+ m_VideoController.DriverVersion);
+ GetObjValue(theObjInstance, CComBSTR("InstalledDisplayDrivers"),
+ m_VideoController.InstalledDisplayDrivers);
+ GetObjValue(theObjInstance, CComBSTR("MaxRefreshRate"),
+ m_VideoController.MaxRefreshRate);
+ GetObjValue(theObjInstance, CComBSTR("MinRefreshRate"),
+ m_VideoController.MinRefreshRate);
+ GetObjValue(theObjInstance, CComBSTR("name"), m_VideoController.Name);
+ GetObjValue(theObjInstance, CComBSTR("VideoProcessor"),
+ m_VideoController.VideoProcessor);
+
+ // Determine video guid
+ GetVidGuid();
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * DetermineVideoController: Obtains information about the video controller.
+ *
+ * @param <IWbemServices> Not used yet...
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::DetermineApps(IWbemServices *)
+{
+ // Determine DirectX version
+ GetDXVersion();
+
+ // Obtain the Internet Explorer version
+ GetIEVersion();
+}
+
+//==============================================================================
+/**
+ * GetObjValue: Obtains the value of a certain property from a WMI object
+ *
+ * @param <IWbemClassObject> inObject Instance of object
+ *
+ * @param <BSTR> inPropName Name of property
+ *
+ * @param <std::string&> ioValue Reference to value
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::GetObjValue(IWbemClassObject *inObject, BSTR inPropName, std::string &ioValue)
+{
+ if (::IsBadReadPtr(inObject, sizeof(IWbemClassObject)) == FALSE) {
+ CComVariant theValue;
+ HRESULT theResult;
+
+ // Obtain property value
+ theResult = inObject->Get(inPropName, 0, &theValue, NULL, NULL);
+ if (SUCCEEDED(theResult)) {
+ // Make sure the variant is valid
+ if (theValue.vt != VT_NULL) {
+ // Change type to BSTR and copy over
+ USES_CONVERSION;
+ theValue.ChangeType(VT_BSTR);
+
+ if (theValue.vt == VT_BSTR) {
+ ioValue = OLE2A(theValue.bstrVal);
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * GetConfigName: Sets the configuration name.
+ *
+ * Queries WMI for the name of the computer and sets this to be the config name.
+ *
+ * @param <IWbemServices> inServices Used to access WMI services
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::GetConfigName(IWbemServices *inServices)
+{
+ HRESULT theResult;
+ CComPtr<IEnumWbemClassObject> theObjEnum;
+ CComPtr<IWbemClassObject> theObjInstance;
+ CComVariant theValue;
+ CComBSTR theObjectName = "Win32_ComputerSystem";
+ unsigned long theNumObjects;
+
+ if (::IsBadReadPtr(inServices, sizeof(IWbemServices)) == FALSE) {
+ // Create an Instance Enumerator
+ theResult =
+ inServices->CreateInstanceEnum(theObjectName, WBEM_FLAG_DEEP, NULL, &theObjEnum);
+ if (SUCCEEDED(theResult) && theObjEnum) {
+ while (WBEM_S_NO_ERROR == (theResult = theObjEnum->Next(INFINITE, 1, &theObjInstance,
+ &theNumObjects))) {
+ // Obtain the name of this computer system
+ GetObjValue(theObjInstance, CComBSTR("name"), m_ConfigName);
+
+ // Release the instance
+ theObjInstance = NULL;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * GetDXVersion: Obtains the DirectX version.
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::GetDXVersion()
+{
+ CRegKey theRegistryKey;
+
+ m_Applications.DXVersion.erase();
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS
+ == theRegistryKey.Open(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
+ KEY_QUERY_VALUE)) {
+ TCHAR theValueString[MAX_PATH];
+ DWORD theStringSize = sizeof(theValueString);
+
+// NOTE: TEMPORARY COMPILE FIX
+// Are we in VC6 (1200) or VC7 (1300)?
+#if _MSC_VER >= 1300
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryStringValue(_TEXT("Version"), theValueString, &theStringSize))
+#else
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryValue(theValueString, _TEXT("Version"), &theStringSize))
+#endif // _MSC_VER >= 1300
+ {
+ m_Applications.DXVersion = Q3DStudio::CString(theValueString).GetCharStar();
+ }
+
+ theRegistryKey.Close();
+ }
+}
+
+//==============================================================================
+/**
+ * GetIEVersion: Obtains the Internet Explorer version.
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::GetIEVersion()
+{
+ CRegKey theRegistryKey;
+
+ m_Applications.IEVersion.erase();
+
+ // If there is an error opening the key
+ if (ERROR_SUCCESS
+ == theRegistryKey.Open(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Internet Explorer"),
+ KEY_QUERY_VALUE)) {
+ TCHAR theValueString[MAX_PATH];
+ DWORD theStringSize = sizeof(theValueString);
+
+// NOTE: TEMPORARY COMPILE FIX
+// Are we in VC6 (1200) or VC7 (1300)?
+#if _MSC_VER >= 1300
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryStringValue(_TEXT("Version"), theValueString, &theStringSize))
+#else
+ if (ERROR_SUCCESS
+ == theRegistryKey.QueryValue(theValueString, _TEXT("Version"), &theStringSize))
+#endif // _MSC_VER >= 1300
+ {
+ m_Applications.IEVersion = Q3DStudio::CString(theValueString).GetCharStar();
+ }
+
+ theRegistryKey.Close();
+ }
+}
+
+//==============================================================================
+/**
+ * GetVidGuid: Obtains the Internet Explorer version.
+ *
+ * @return NONE
+ */
+//==============================================================================
+void CWin32Config::GetVidGuid()
+{
+ // throw; // really?
+ // typedef HRESULT (WINAPI * DIRECTDRAWCREATEEX) (GUID FAR*, LPVOID *, REFIID, IUnknown FAR *);
+
+ // DIRECTDRAWCREATEEX theDDrawProcAddr;
+ // LPDIRECTDRAW7 theDDraw7Ptr;
+ // HRESULT theResult;
+ // HINSTANCE theDDrawDLL = NULL;
+ //
+
+ // // See if DDRAW.DLL even exists.
+ // theDDrawDLL = ::LoadLibrary( "DDRAW.DLL" );
+
+ //// Get the address of the exported DLL function, DirectDrawCreateEx
+ // theDDrawProcAddr = (DIRECTDRAWCREATEEX)::GetProcAddress( theDDrawDLL, "DirectDrawCreateEx" );
+
+ //// Try calling the exported DLL function, DirectDrawCreateEx
+ // theResult = (*theDDrawProcAddr) ( NULL, reinterpret_cast<void**>(&theDDraw7Ptr),
+ // IID_IDirectDraw7, NULL );
+ // if ( SUCCEEDED( theResult ) && theDDraw7Ptr )
+ //{
+ // WCHAR theDeviceGUID[ _MAX_PATH ];
+ // DDDEVICEIDENTIFIER2 theDevID;
+ // std::string theDriverVersion;
+ //
+ // // Get the video driver info
+ // theDDraw7Ptr->GetDeviceIdentifier( &theDevID, DDGDI_GETHOSTIDENTIFIER );
+
+ // // Convert guid to string
+ // if ( ::StringFromGUID2( theDevID.guidDeviceIdentifier, theDeviceGUID, _MAX_PATH ) )
+ // {
+ // USES_CONVERSION;
+ // m_VideoController.DX7CapsKey = OLE2A( theDeviceGUID );
+
+ // // Grab the version of the driver
+ // if ( GetComponentVersion( theDevID.szDriver, theDriverVersion ) )
+ // {
+ // m_VideoController.DX7CapsKey += ".";
+ // m_VideoController.DX7CapsKey += theDriverVersion;
+ // }
+ // }
+ // else
+ // {
+ // m_VideoController.DX7CapsKey.erase();
+ // }
+ //}
+
+ //// DDraw7 was created successfully. We must be at least DX7.0
+ // theDDraw7Ptr->Release();
+
+ //// Release the DDRAW.DLL
+ //::FreeLibrary( theDDrawDLL );
+}
+
+//==============================================================================
+/**
+ * GetComponentVersion: This method grabs the File Version given the path.
+ *
+ * Given a path, this method will construct a version in the following
+ * format: MajorVersion.MinorVersion.BuildNumber.PlatformID.
+ *
+ * @param inPath The path of the file to retrieve version information on.
+ * @param ioVersion The version of the given file in the format explained
+ * above.
+ *
+ * @return true if the version was determined, otherwise false
+ */
+//==============================================================================
+bool CWin32Config::GetComponentVersion(LPTSTR inPath, std::string &ioVersion)
+{
+ DWORD theHandle;
+ DWORD theFileVersionSize;
+
+ // Get the file version information
+ if ((theFileVersionSize = ::GetFileVersionInfoSize(inPath, &theHandle)) == 0) {
+ ioVersion.erase();
+ }
+
+ else {
+ // Create a buffer to hold the file version information
+ TCHAR *theFileVersionBuffer = new TCHAR[theFileVersionSize];
+
+ // Get the file version information
+ if (::GetFileVersionInfo(inPath, theHandle, theFileVersionSize, theFileVersionBuffer)
+ == 0) {
+ // we failed getting the version information for some reason
+ ioVersion.erase();
+ }
+
+ else {
+ // Build a version structure
+ VS_FIXEDFILEINFO *theFileVersionStructure;
+ UINT theStructureSize;
+ LPTSTR theSearchString = TEXT("\\\0");
+
+ // Fille the version structure with the basic verison information
+ if (::VerQueryValue(theFileVersionBuffer, theSearchString,
+ reinterpret_cast<void **>(&theFileVersionStructure),
+ &theStructureSize)
+ == 0) {
+ // we failed on something
+ ioVersion.erase();
+ }
+
+ else {
+ // Get the major file version
+ WORD theMajorVer = HIWORD(theFileVersionStructure->dwFileVersionMS);
+ TCHAR theMajorString[_MAX_PATH];
+ ::_ltot(theMajorVer, theMajorString, 10);
+
+ // Get the minor file version
+ WORD theMinorVer = LOWORD(theFileVersionStructure->dwFileVersionMS);
+ TCHAR theMinorString[_MAX_PATH];
+ ::_ltot(theMinorVer, theMinorString, 10);
+
+ // Get the build number
+ WORD theBuildNum = HIWORD(theFileVersionStructure->dwFileVersionLS);
+ TCHAR theBuildNumString[_MAX_PATH];
+ ::_ltot(theBuildNum, theBuildNumString, 10);
+
+ // Get the platform ID
+ WORD thePlatformID = LOWORD(theFileVersionStructure->dwFileVersionLS);
+ TCHAR thePlatformIDString[_MAX_PATH];
+ ::_ltot(thePlatformID, thePlatformIDString, 10);
+
+ // Construct a string to represent the version number
+ Q3DStudio::CString theVersionString;
+ theVersionString = theMajorString;
+ theVersionString += _TEXT(".");
+ theVersionString += theMinorString;
+ theVersionString += _TEXT(".");
+ theVersionString += theBuildNumString;
+ theVersionString += _TEXT(".");
+ theVersionString += thePlatformIDString;
+
+ // We are golden.. copy the version out.
+ ioVersion = theVersionString.GetCharStar();
+ //_tcscpy( ioVersion, theVersionString );
+ }
+ }
+
+ // Delete our newed memory
+ delete[] theFileVersionBuffer;
+ }
+
+ return (!ioVersion.empty());
+}
+#endif
diff --git a/src/Authoring/Common/Code/_Win32/Win32Config.h b/src/Authoring/Common/Code/_Win32/Win32Config.h
new file mode 100644
index 00000000..fa5669f0
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/Win32Config.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_WIN32_CONFIG_H
+#define INCLUDED_WIN32_CONFIG_H 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <string>
+#include <vector>
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <Wbemidl.h>
+#endif
+#include "CompConfig.h"
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+//==============================================================================
+/**
+ * @class CWin32Config
+ *
+ */
+//==============================================================================
+class CWin32Config : public CCompConfig
+{
+ //==============================================================================
+ // Structures
+ //==============================================================================
+
+protected:
+ struct SOperatingSystem
+ {
+ std::string CountryCode;
+ std::string Locale;
+ std::string Name;
+ std::string ServicePacks;
+ std::string TotalVisibleMemorySize;
+ std::string Version;
+ };
+
+ struct SProcessor
+ {
+ std::string CurrentClockSpeed;
+ std::string DeviceID;
+ std::string Manufacturer;
+ std::string MaxClockSpeed;
+ std::string Name;
+ std::string Version;
+ };
+
+ struct SVideoController
+ {
+ std::string AdapterRAM;
+ std::string CurrentBitsPerPixel;
+ std::string CurrentHorizontalResolution;
+ std::string CurrentRefreshRate;
+ std::string CurrentVerticalResolution;
+ std::string DeviceID;
+ std::string DriverDate;
+ std::string DriverVersion;
+ std::string InstalledDisplayDrivers;
+ std::string MaxRefreshRate;
+ std::string MinRefreshRate;
+ std::string Name;
+ std::string VideoProcessor;
+ std::string DX7CapsKey;
+ };
+
+ struct SApplications
+ {
+ std::string DXVersion;
+ std::string IEVersion;
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+protected:
+ std::string m_ConfigName; ///< The name of this specific configuration
+
+ SOperatingSystem m_OS; ///< Contains inforamtion about the operating system
+ std::vector<SProcessor> m_Processors; ///< Contains information about the system processor
+ SVideoController m_VideoController; ///< Contains information about the video controller
+ SApplications m_Applications; ///< Contians information about various applications installed
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Construction
+
+public:
+ CWin32Config();
+ virtual ~CWin32Config();
+
+ // Access
+
+public:
+ void DetermineConfig() override;
+ void WriteXML(std::ostream &inStream) override;
+
+ // Implementation
+
+protected:
+#ifdef KDAB_TEMPORARILY_REMOVED
+ void DetermineOS(IWbemServices *inServices);
+ void DetermineProcessor(IWbemServices *inServices);
+ void DetermineVideoController(IWbemServices *inServices);
+ void DetermineApps(IWbemServices *inServices);
+ void GetConfigName(IWbemServices *inServices);
+ void GetObjValue(IWbemClassObject *inObject, BSTR inPropName, std::string &ioValue);
+ void GetDXVersion();
+ void GetIEVersion();
+ void GetVidGuid();
+ bool GetComponentVersion(LPTSTR inPath, std::string &outVersion);
+#endif
+};
+
+#endif // INCLUDED_WIN32_CONFIG_H
diff --git a/src/Authoring/Common/Code/_Win32/stdafx.cpp b/src/Authoring/Common/Code/_Win32/stdafx.cpp
new file mode 100644
index 00000000..9db65ab7
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/stdafx.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// CommonLibProject.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/Authoring/Common/Code/_Win32/stdafx.h b/src/Authoring/Common/Code/_Win32/stdafx.h
new file mode 100644
index 00000000..32f792a9
--- /dev/null
+++ b/src/Authoring/Common/Code/_Win32/stdafx.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// CommonLib Precompiled Header
+//==============================================================================
+#ifdef __cplusplus
+#pragma once
+#include "UICMacros.h"
+
+#ifdef WIN32
+//==============================================================================
+// Disable certain warnings since warnings are errors
+#pragma warning(disable : 4702) // Unreachable code
+#pragma warning(disable : 4290) // C++ Exception Specification ignored
+#pragma warning(disable : 4514) // unreferenced inline function
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4819)
+#endif
+
+//==============================================================================
+// Common Includes
+#include <stdio.h> // Standard includes MUST come first
+#include <stdlib.h>
+#include <wchar.h>
+
+//==============================================================================
+// STL Includes
+#ifdef WIN32
+#pragma warning(push, 3) // Temporarily pop to warning level 3 while including standard headers
+#pragma warning(disable : 4018) // Disable mismatched < STL warning
+#endif
+
+#include <vector>
+#include <map>
+#include <deque>
+#include <string>
+#include <stack>
+#include <set>
+#include <list>
+#include <utility>
+#include <algorithm>
+#include <stdexcept>
+#include <limits>
+#ifdef WIN32
+#pragma warning(pop) // Pop out to previous warning level (probably level 4)
+#endif
+
+//==============================================================================
+// Common Player Includes
+#include "PlatformTypes.h"
+#include "PlatformStrings.h"
+#include "UICMath.h"
+#include "UICExceptions.h"
+#include "UICObjectCounter.h"
+#include "UICString.h"
+#include "STLHelpers.h"
+
+#include <QtGlobal>
+#endif
diff --git a/src/Authoring/Common/Code/qt_attribution.json b/src/Authoring/Common/Code/qt_attribution.json
new file mode 100644
index 00000000..5ccf78cb
--- /dev/null
+++ b/src/Authoring/Common/Code/qt_attribution.json
@@ -0,0 +1,24 @@
+[
+ {
+ "Id": "foreach",
+ "Name": "Foreach",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio, Studio component.",
+
+ "Description": "Foreach loop used by UICMacros.",
+ "License": "MIT Old style",
+ "LicenseFile": "LICENSE_FOREACH.TXT",
+ "Copyright": "Copyright (c) 2003 Eric Niebler"
+ },
+ {
+ "Id": "ptypes",
+ "Name": "PTypes",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio, Studio component.",
+
+ "Description": "C++ Portable Types Library (PTypes).",
+ "License": "Zlib license",
+ "LicenseId": "Zlib",
+ "Copyright": "Copyright (C) 2001-2007 Hovik Melikyan"
+ }
+]
diff --git a/src/Authoring/CommonLib.pri b/src/Authoring/CommonLib.pri
new file mode 100644
index 00000000..58069121
--- /dev/null
+++ b/src/Authoring/CommonLib.pri
@@ -0,0 +1,63 @@
+SOURCES += \
+ ../3rdparty/color/CColor.cpp \
+ Common/Code/HiResTimer.cpp \
+ Common/Code/MasterP.cpp \
+ Common/Code/MethProf.cpp \
+ Common/Code/Pt.cpp \
+ Common/Code/StackTokenizer.cpp \
+ Common/Code/StringTokenizer.cpp \
+ Common/Code/StrUtilities.cpp \
+ Common/Code/UICAtomic.cpp \
+ Common/Code/UICFileTools.cpp \
+ Common/Code/UICId.cpp \
+ Common/Code/UICMath.cpp \
+ Common/Code/UICMemory.cpp \
+ Common/Code/UICMessageBox.cpp \
+ Common/Code/UICObjectCounter.cpp \
+ Common/Code/UICString.cpp \
+ Common/Code/UICTime.cpp \
+ Common/Code/Thread/Mutex.cpp \
+ Common/Code/Thread/Thread.cpp \
+ Common/Code/Exceptions/UICExceptionClass.cpp \
+ Common/Code/Exceptions/XMLException.cpp \
+ Common/Code/_Win32/DLLVersion.cpp \
+ Common/Code/_Win32/FileIterator.cpp \
+ Common/Code/_Win32/Preferences.cpp \
+ Common/Code/_Win32/stdafx.cpp \
+ Common/Code/_Win32/SystemInfo.cpp \
+ # Common/Code/_Win32/UICFile.cpp \
+ Common/Code/_Win32/UICRegistry.cpp \
+ Common/Code/_Win32/Win32Config.cpp \
+ Common/Code/Graph/Graph.cpp \
+ Common/Code/InfoDump/CoutSink.cpp \
+ Common/Code/InfoDump/DumpFileSink.cpp \
+ Common/Code/InfoDump/InfoDump.cpp \
+ Common/Code/InfoDump/InfoSink.cpp \
+ Common/Code/InfoDump/StrVecSink.cpp \
+ Common/Code/IO/BufferedInputStream.cpp \
+ Common/Code/IO/BufferedOutputStream.cpp \
+ Common/Code/IO/FileInputStream.cpp \
+ Common/Code/IO/FileOutputStream.cpp \
+ Common/Code/IO/IOStreams.cpp \
+ Common/Code/IO/LEndianStreams.cpp \
+ Common/Code/IO/MemBuf.cpp \
+ Common/Code/IO/MemInputStream.cpp \
+ Common/Code/IO/MemOutputStream.cpp \
+ Common/Code/IO/Seekable.cpp \
+ Common/Code/Report/CompConfig.cpp \
+ Common/Code/Report/CrashInfo.cpp \
+ Common/Code/Report/ProductInfo.cpp \
+ Common/Code/Report/ProductInstance.cpp \
+ Common/Code/Report/StackOps.cpp \
+ Common/Code/EulerAngles/EulerAngles.cpp \
+ Common/Code/Memory/MemoryObject.cpp \
+ Common/Code/Memory/UICMemoryLeak.cpp \
+ Common/Code/Serialize/FormattedInputStream.cpp \
+ Common/Code/Serialize/FormattedOutputStream.cpp \
+ Common/Code/Serialize/PreferencesSerializer.cpp \
+
+
+SOURCES += \
+ Common/Code/_Qt/QtUICFile.cpp \
+
+HEADERS = Common/Code/Literals.h
diff --git a/src/Authoring/CommonLib.pro b/src/Authoring/CommonLib.pro
new file mode 100644
index 00000000..0f2769c7
--- /dev/null
+++ b/src/Authoring/CommonLib.pro
@@ -0,0 +1,28 @@
+TEMPLATE = lib
+TARGET = CommonLib
+CONFIG += staticlib nostrictstrings
+include($$PWD/commoninclude.pri)
+
+QT += widgets
+
+DEFINES += _UNICODE UIC_AUTHORING _AFXDLL \
+ PCRE_STATIC BOOST_SIGNALS_NO_DEPRECATION_WARNING _AMD64_ _WINSOCK_DEPRECATED_NO_WARNINGS
+
+INCLUDEPATH += \
+ Common/Code/_Win32 \
+ Common/Code/Thread \
+ Common/Code/IO \
+ Common/Code \
+ Common/Code/Exceptions \
+ Common/Code/_Win32/Include \
+ Common/Code/Report \
+ Common/Code/Serialize \
+ UICDM \
+ UICDM/Systems \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ ../3rdparty/EASTL/UnknownVersion/include \
+ ../3rdparty/color
+
+PRECOMPILED_HEADER += Common/Code/_Win32/stdafx.h
+
+include(CommonLib.pri)
diff --git a/src/Authoring/CoreLib.pri b/src/Authoring/CoreLib.pri
new file mode 100644
index 00000000..0727cf51
--- /dev/null
+++ b/src/Authoring/CoreLib.pri
@@ -0,0 +1,67 @@
+SOURCES += \
+ Client/Code/Core/StdAfx.cpp \
+ Client/Code/Core/Q3DStudioNVFoundation.cpp \
+ Client/Code/Core/Types/BoundingBox.cpp \
+ Client/Code/Core/Types/CachedMatrix.cpp \
+ Client/Code/Core/Types/Frustum.cpp \
+ Client/Code/Core/Types/Matrix.cpp \
+ Client/Code/Core/Types/Pixel.cpp \
+ Client/Code/Core/Types/Plane.cpp \
+ Client/Code/Core/Types/Rotation3.cpp \
+ Client/Code/Core/Types/UICColor.cpp \
+ Client/Code/Core/Types/Vector2.cpp \
+ Client/Code/Core/Types/Vector3.cpp \
+ Client/Code/Core/Utility/BuildConfigParser.cpp \
+ Client/Code/Core/Utility/ColorConversion.cpp \
+ Client/Code/Core/Utility/CoreUtils.cpp \
+ Client/Code/Core/Utility/cpuid.cpp \
+ Client/Code/Core/Utility/DataModelObjectReferenceHelper.cpp \
+ Client/Code/Core/Utility/HotKeys.cpp \
+ Client/Code/Core/Utility/OptimizedArithmetic.cpp \
+ Client/Code/Core/Utility/PathConstructionHelper.cpp \
+ Client/Code/Core/Utility/StudioClipboard.cpp \
+ Client/Code/Core/Utility/StudioObjectTypes.cpp \
+ Client/Code/Core/Utility/StudioPreferences.cpp \
+ Client/Code/Core/Utility/StudioProjectVariables.cpp \
+ Client/Code/Core/Utility/TestCmdUtils.cpp \
+ Client/Code/Core/Commands/Cmd.cpp \
+ Client/Code/Core/Commands/CmdActivateSlide.cpp \
+ Client/Code/Core/Commands/CmdBatch.cpp \
+ Client/Code/Core/Commands/CmdDataModel.cpp \
+ Client/Code/Core/Commands/CmdLocateReference.cpp \
+ Client/Code/Core/Commands/CmdStack.cpp \
+ Client/Code/Core/Core/Core.cpp \
+ Client/Code/Core/Core/Dispatch.cpp \
+ Client/Code/Core/Doc/ComposerEditorInterface.cpp \
+ Client/Code/Core/Doc/Doc.cpp \
+ Client/Code/Core/Doc/DocumentBufferCache.cpp \
+ Client/Code/Core/Doc/DocumentEditor.cpp \
+ Client/Code/Core/Doc/DynamicLua.cpp \
+ Client/Code/Core/Doc/GraphUtils.cpp \
+ Client/Code/Core/Doc/IComposerSerializer.cpp \
+ Client/Code/Core/Doc/PathImportTranslator.cpp \
+ Client/Code/Core/Doc/RelativePathTools.cpp \
+ Client/Code/Core/Doc/StudioProjectSettings.cpp \
+ Client/Code/Core/Doc/UICDMStudioSystem.cpp \
+ Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp \
+ Client/Code/Core/Timer/Timer.cpp \
+ Client/Code/Core/VirtualAssets/PlaybackClock.cpp \
+ Client/Code/Core/VirtualAssets/VClockPolicy.cpp \
+ Client/Code/Shared/Log/LogHelper.cpp \
+ UICIMP/UICImportLib/UICImport.cpp \
+ UICIMP/UICImportLib/UICImportComposerTypes.cpp \
+ UICIMP/UICImportLib/UICImportLibPrecompile.cpp \
+ UICIMP/UICImportLib/UICImportMesh.cpp \
+ UICIMP/UICImportLib/UICImportMeshBuilder.cpp \
+ UICIMP/UICImportLib/UICImportMeshStudioOnly.cpp \
+ UICIMP/UICImportLib/UICImportPath.cpp \
+ UICIMP/UICImportLib/UICImportPerformImport.cpp \
+ UICIMP/UICImportSGTranslation/UICImportColladaSGTranslation.cpp \
+ UICIMP/UICImportSGTranslation/UICImportFbxSGTranslation.cpp \
+ UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.cpp \
+ $$PWD/Client/Code/Core/Utility/q3dsdirsystem.cpp \
+ $$PWD/Client/Code/Core/Utility/q3dsdirwatcher.cpp
+
+HEADERS += \
+ $$PWD/Client/Code/Core/Utility/q3dsdirsystem.h \
+ $$PWD/Client/Code/Core/Utility/q3dsdirwatcher.h
diff --git a/src/Authoring/CoreLib.pro b/src/Authoring/CoreLib.pro
new file mode 100644
index 00000000..24ffb845
--- /dev/null
+++ b/src/Authoring/CoreLib.pro
@@ -0,0 +1,63 @@
+TEMPLATE = lib
+TARGET = CoreLib
+CONFIG += staticlib nostrictstrings
+include($$PWD/commoninclude.pri)
+include($$OUT_PWD/qtAuthoring-config.pri)
+DEFINES += _UNICODE UIC_AUTHORING _AFXDLL \
+ PCRE_STATIC BOOST_SIGNALS_NO_DEPRECATION_WARNING DRIVE_DESIGN_STUDIO \
+ DISABLE_MESH_OPTIMIZATION DOM_INCLUDE_TINYXML NO_ZAE COLLADA_DOM_SUPPORT141 BOOST_ALL_NO_LIB \
+ _AMD64_
+
+QT += widgets
+
+macos:DEFINES += WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T UIC_LITTLE_ENDIAN
+
+linux: DEFINES += WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+
+INCLUDEPATH += \
+ Client/Code/Core \
+ Client/Code/Core/Utility \
+ Client/Code/Core/Types \
+ Client/Code/Core/Commands \
+ Client/Code/Core/Core \
+ Client/Code/Core/Doc \
+ Client/Code/Core/Doc/ClientDataModelBridge \
+ Client/Code/Shared \
+ Client/Code/Shared/Log \
+ Client/Code/Core/Timer \
+ Client/Code/Core/VirtualAssets \
+ UICIMP/UICImportLib \
+ UICDM/Systems \
+ UICDM/Systems/Cores \
+ UICIMP/UICImportSGTranslation \
+ Studio/DragAndDrop \
+ Studio/Render \
+ Studio/Workspace \
+ Studio/_Win/DragNDrop \
+ Studio/Utils \
+ Build \
+ Common/Code/Thread \
+ Common/Code/IO \
+ Common/Code \
+ Common/Code/Exceptions \
+ Common/Code/_Win32/Include \
+ Common/Code/Graph \
+ Common/Code/EulerAngles \
+ Common/Code/Serialize \
+ $$PWD/../Runtime/Source/RuntimeUICDM/Include \
+ $$PWD/../Runtime/Source/Qt3DSRender/Include \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ $$PWD/../Runtime/Source/UICRender/Include \
+ $$PWD/../Runtime/Source/UICRender/GraphObjects \
+ $$PWD/../Runtime/Source/UICRender/ResourceManager \
+ $$PWD/../Runtime/Source/UICState/Application \
+ ../3rdparty/Lua/UnknownVersion/src \
+ ../3rdparty/EASTL/UnknownVersion/include \
+ $$QMAKE_INCDIR_FBX \
+ ../3rdparty/ColladaDOM/1.4.0/dom/include \
+ ../3rdparty/ColladaDOM/1.4.0/dom/include/1.4 \
+ ../3rdparty/color
+
+PRECOMPILED_HEADER = Client/Code/Core/StdAfx.h
+
+include(CoreLib.pri)
diff --git a/src/Authoring/FBXLineExporter.pri b/src/Authoring/FBXLineExporter.pri
new file mode 100644
index 00000000..9a5d6dc8
--- /dev/null
+++ b/src/Authoring/FBXLineExporter.pri
@@ -0,0 +1 @@
+SOURCES += FBXLineExporter/FBXLineExporter.cpp
diff --git a/src/Authoring/FBXLineExporter.pro b/src/Authoring/FBXLineExporter.pro
new file mode 100644
index 00000000..c81df949
--- /dev/null
+++ b/src/Authoring/FBXLineExporter.pro
@@ -0,0 +1,35 @@
+TEMPLATE = app
+TARGET = FBXLineExporter
+include($$PWD/commoninclude.pri)
+include($$OUT_PWD/qtAuthoring-config.pri)
+CONFIG += console
+QT -= gui
+DEFINES += _UNICODE UIC_AUTHORING _AFXDLL PCRE_STATIC
+
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ $$QMAKE_INCDIR_FBX \
+ ../3rdparty/EASTL/UnknownVersion/include
+
+LIBS += \
+ -L"$$BOOSTDIR" \
+ $$QMAKE_LIBS_FBX \
+ -lws2_32 \
+ -lLua$$qtPlatformTargetSuffix() \
+ -lEASTL$$qtPlatformTargetSuffix() \
+ -lRpcrt4 \
+ -lGdiplus \
+ -lUser32 \
+ -lUserenv \
+ -lWbemuuid \
+ -lWinmm \
+ -l$$BOOSTSIGNALLIB \
+ -l$$BOOSTSYSTEMLIB \
+ -l$$BOOSTFILESYSTEMLIB \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix()
+
+include(FBXLineExporter.pri)
+
+load(qt_tool)
+
+INSTALLS -= target
diff --git a/src/Authoring/FBXLineExporter/FBXLineExporter.cpp b/src/Authoring/FBXLineExporter/FBXLineExporter.cpp
new file mode 100644
index 00000000..ac54f3d6
--- /dev/null
+++ b/src/Authoring/FBXLineExporter/FBXLineExporter.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+#include "qtAuthoring-config.h"
+#ifdef QT_3DSTUDIO_FBX
+#include <fbxsdk.h>
+#include "eastl/string.h"
+#include "foundation/FileTools.h"
+#include "foundation/IOStreams.h"
+
+using namespace eastl;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+
+namespace {
+struct SLineExporter
+{
+ FbxManager *m_FbxManager;
+ FbxScene *m_FbxScene;
+ IOutStream *m_OutStream;
+ SLineExporter()
+ : m_FbxManager(FbxManager::Create())
+ , m_FbxScene(NULL)
+ , m_OutStream(NULL)
+ {
+ FbxIOSettings *theIOSettings = FbxIOSettings::Create(m_FbxManager, IOSROOT);
+ m_FbxManager->SetIOSettings(theIOSettings);
+ m_FbxScene = FbxScene::Create(m_FbxManager, "");
+ }
+
+ bool OpenFile(const char *inFilePath)
+ {
+ FbxImporter *theImporter = FbxImporter::Create(m_FbxManager, "");
+ if (!theImporter->Initialize(inFilePath, -1, m_FbxManager->GetIOSettings())) {
+ theImporter->Destroy();
+ return false;
+ }
+ int major = 0, minor = 0, revision = 0;
+ theImporter->GetFileVersion(major, minor, revision);
+
+ if (theImporter->IsFBX()) {
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_MATERIAL, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_TEXTURE, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_LINK, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_SHAPE, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_GOBO, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_ANIMATION, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, true);
+ }
+ bool theStatus = theImporter->Import(m_FbxScene);
+ theImporter->Destroy();
+ return theStatus;
+ }
+
+ ~SLineExporter()
+ {
+ if (m_FbxScene != NULL)
+ m_FbxScene->Destroy();
+ if (m_FbxManager != NULL)
+ m_FbxManager->Destroy();
+ }
+
+ void Write(const char *data)
+ {
+ if (isTrivial(data))
+ return;
+ m_OutStream->Write(data, (QT3DSU32)strlen(data));
+ }
+
+ void ProcessNodeChildren(FbxNode *inFbxNode)
+ {
+
+ for (int i = 0, end = inFbxNode->GetChildCount(); i < end; ++i) {
+ ProcessNode(inFbxNode->GetChild(i));
+ }
+ }
+
+ static bool AreEqual(QT3DSF64 lhs, QT3DSF64 rhs) { return abs((long)lhs - (long)rhs) < .0001; }
+
+ void ProcessNode(FbxNode *inNode)
+ {
+ if (inNode == NULL)
+ return;
+ if (inNode->GetNodeAttribute() != NULL
+ && inNode->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eLine
+ && !isTrivial(inNode->GetName())) {
+ const char *nodeName = inNode->GetName();
+ FbxLine *theLine = inNode->GetLine();
+ (void)theLine;
+ // Only support translating the point set, not anything else.
+ FbxDouble3 theTranslation = inNode->LclTranslation.Get();
+ fprintf(stdout, "Exporting line %s\n", nodeName);
+ Write("local ");
+ Write(nodeName);
+ Write("Data = {\n");
+ char buffer[1024];
+ FbxDouble2 theLastPoint;
+ for (int idx = 0, end = theLine->GetIndexArraySize(); idx < end; ++idx) {
+ int pointIndex = theLine->GetPointIndexAt(idx);
+ FbxDouble4 thePoint = theLine->GetControlPointAt(pointIndex);
+ thePoint[0] += theTranslation[0];
+ thePoint[1] += theTranslation[1];
+ bool writeData = true;
+ if (idx) {
+ writeData = !(AreEqual(thePoint[0], theLastPoint[0])
+ && AreEqual(thePoint[1], theLastPoint[1]));
+ }
+
+ // Do a simple de-dup; identical points in the list present problems.
+ if (writeData) {
+ sprintf(buffer, "\t{%g, %g},\n", thePoint[0], thePoint[1]);
+ Write(buffer);
+ }
+ theLastPoint[0] = thePoint[0];
+ theLastPoint[1] = thePoint[1];
+ }
+ Write("}\n");
+
+ Write("allLines[\"");
+ Write(nodeName);
+ Write("\"] = ");
+ Write(nodeName);
+ Write("Data\n\n");
+ }
+ ProcessNodeChildren(inNode);
+ }
+
+ void ExportLines(IOutStream &outStream)
+ {
+ m_OutStream = &outStream;
+ Write("local allLines = {}\n\n");
+ ProcessNode(m_FbxScene->GetRootNode());
+ Write("\n\nreturn allLines\n");
+ }
+};
+}
+
+int main(int c, char **v)
+{
+ if (c == 1) {
+ fprintf(stderr, "No input file given\n");
+ return 1;
+ }
+ string fullPath(v[1]);
+ if (fullPath.find('\"') == 0) {
+ fullPath.resize(fullPath.size() - 1);
+ fullPath.erase(fullPath.begin(), fullPath.begin() + 1);
+ }
+
+ SLineExporter theExporter;
+ if (!theExporter.OpenFile(fullPath.c_str())) {
+ fprintf(stderr, "Failed to open input file: \"%s\"\n", fullPath.c_str());
+ }
+
+ string dirname, filename, extension;
+ CFileTools::Split(fullPath.c_str(), dirname, filename, extension);
+ string outputFileName(filename);
+ outputFileName.append(".lua");
+ string outputFilePath;
+ CFileTools::CombineBaseAndRelative(dirname.c_str(), outputFileName.c_str(), outputFilePath);
+ CFileSeekableIOStream theOutputStream(outputFilePath.c_str(), FileWriteFlags());
+ if (theOutputStream.IsOpen() == false) {
+ fprintf(stderr, "Failed to open output file: \"%s\"\n", outputFilePath.c_str());
+ return 1;
+ }
+ theExporter.ExportLines(theOutputStream);
+}
+#else
+int main(int, char **)
+{
+ qCritical("FBX SDK not available!");
+ return 1;
+}
+#endif
diff --git a/src/Authoring/MeshOptimizer/Source/MeshOptimizer.cpp b/src/Authoring/MeshOptimizer/Source/MeshOptimizer.cpp
new file mode 100644
index 00000000..134441cd
--- /dev/null
+++ b/src/Authoring/MeshOptimizer/Source/MeshOptimizer.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <winsock2.h>
+#include <Windows.h>
+#include <stdio.h>
+#include "UICFileTools.h"
+#include "StandardExtensions.h"
+#include <map>
+#include "UICImportMesh.h"
+#include "UICDMXML.h"
+#include "UICDMStringTable.h"
+#include "foundation/IOStreams.h"
+#include "render/NvRenderBaseTypes.h"
+#include "foundation/TrackingAllocator.h"
+#include "StandardExtensions.h"
+#include "foundation/Qt3DSLogging.h"
+
+using namespace Q3DStudio;
+using namespace std;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::render;
+
+const CString uipExtension = "uip";
+const CString meshExtension = "mesh";
+
+bool IsNotUIPFile(const CFilePath &inFile)
+{
+ if (inFile.GetExtension().CompareNoCase(uipExtension) == false)
+ return true;
+ return false;
+}
+
+using namespace UICDM;
+typedef map<Q3DStudio::CFilePath, vector<QT3DSU32>> TMeshFileToIdMap;
+
+void ScanChildrenForSourcepath(UICDM::IDOMReader &inReader, TMeshFileToIdMap &inMap,
+ const CFilePath &inProjectDirectory)
+{
+ UICDM::IDOMReader::Scope elemScope(inReader);
+ const wchar_t *sourcePathAtt = NULL;
+ if (inReader.UnregisteredAtt(L"sourcepath", sourcePathAtt)) {
+ if (sourcePathAtt && *sourcePathAtt) {
+ if (sourcePathAtt[0] != '#') {
+ CFilePath theFullPath(
+ CFilePath::CombineBaseAndRelative(inProjectDirectory, sourcePathAtt));
+ if (theFullPath.GetExtension().CompareNoCase(meshExtension)) {
+ if (theFullPath.IsFile()) {
+ QT3DSU32 theMeshId = theFullPath.GetULIdentifier();
+ pair<TMeshFileToIdMap::iterator, bool> insertResult = inMap.insert(
+ make_pair(theFullPath.GetPathWithoutIdentifier(), vector<QT3DSU32>()));
+ insert_unique(insertResult.first->second, theMeshId);
+ } else {
+ qCWarning(qt3ds::WARNING) << "Failed to find mesh: "
+ << CString(sourcePathAtt).GetMulti();
+ // go on, ignore it
+ }
+ }
+ }
+ }
+ }
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling())
+ ScanChildrenForSourcepath(inReader, inMap, inProjectDirectory);
+}
+
+void FindMeshFiles(const CFilePath &inUIPPath, TMeshFileToIdMap &inMeshMap,
+ const CFilePath &inProjectDirectory)
+{
+ qCInfo(qt3ds::TRACE_INFO) << "Scanning file " << inUIPPath.GetCharStar() << " for mesh files";
+ std::shared_ptr<UICDM::IStringTable> theTable(UICDM::IStringTable::CreateStringTable());
+ std::shared_ptr<UICDM::IDOMFactory> theFactory(
+ UICDM::IDOMFactory::CreateDOMFactory(theTable));
+ CFileSeekableIOStream theStream(inUIPPath, FileOpenFlagValues::Open);
+ if (!theStream.IsOpen()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ UICDM::SDOMElement *theElement = CDOMSerializer::Read(*theFactory, theStream);
+ if (!theElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ std::shared_ptr<UICDM::IDOMReader> theReader(
+ UICDM::IDOMReader::CreateDOMReader(*theElement, theTable, theFactory));
+ if (!theReader->MoveToFirstChild(L"Project")) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ {
+ UICDM::IDOMReader::Scope projectScope(*theReader);
+ if (!theReader->MoveToFirstChild(L"Graph")) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ ScanChildrenForSourcepath(*theReader, inMeshMap, inProjectDirectory);
+ }
+ {
+ UICDM::IDOMReader::Scope projectScope(*theReader);
+ if (theReader->MoveToFirstChild(L"Logic"))
+ ScanChildrenForSourcepath(*theReader, inMeshMap, inProjectDirectory);
+ }
+}
+
+struct SMeshScope
+{
+ UICIMP::Mesh *m_Mesh;
+ SMeshScope(UICIMP::Mesh *mesh)
+ : m_Mesh(mesh)
+ {
+ }
+ ~SMeshScope()
+ {
+ if (m_Mesh)
+ free(m_Mesh);
+ }
+};
+
+int main(int c, char **v)
+{
+ CFilePath theProjectDirectory;
+ if (c > 1)
+ theProjectDirectory = v[1];
+ else
+ theProjectDirectory.GetCurrentDir();
+
+ if (theProjectDirectory.size() == 0)
+ return -1;
+ if (theProjectDirectory[0] == '"')
+ theProjectDirectory.erase(0, 1);
+
+ if (theProjectDirectory.size() == 0)
+ return -1;
+
+ if (theProjectDirectory[theProjectDirectory.size() - 1] == '"')
+ theProjectDirectory.erase(theProjectDirectory.size() - 1, 1);
+
+ vector<CFilePath> theDirectoryFiles;
+
+ theProjectDirectory.ListFilesAndDirectories(theDirectoryFiles);
+ erase_if(theDirectoryFiles, IsNotUIPFile);
+
+ if (theDirectoryFiles.size() == 0) {
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Directory: " << theProjectDirectory.GetMulti()
+ << " doesn't appear to contain UIP files";
+ return -1;
+ }
+ TMeshFileToIdMap theMeshMap;
+ for (size_t idx = 0, end = theDirectoryFiles.size(); idx < end; ++idx)
+ FindMeshFiles(theDirectoryFiles[idx], theMeshMap, theProjectDirectory);
+
+ qCInfo(qt3ds::TRACE_INFO) << "Found " << theMeshMap.size() << " mesh files";
+
+ UICIMP::MeshBuilder &theBuilder = UICIMP::MeshBuilder::CreateMeshBuilder();
+ vector<QT3DSU16> theIndexes;
+ MallocAllocator theAllocator;
+ QT3DSU32 theFileIndex = 1;
+ QT3DSU32 theFileCount = theMeshMap.size();
+ for (TMeshFileToIdMap::iterator theIter = theMeshMap.begin(), theEnd = theMeshMap.end();
+ theIter != theEnd; ++theIter, ++theFileIndex) {
+ qCInfo(qt3ds::TRACE_INFO) << "Optimizing mesh " << theFileIndex << " of " << theFileCount;
+ const vector<QT3DSU32> &theIdList(theIter->second);
+ CFilePath theTempFile(theIter->first);
+ theTempFile.append(L".temp");
+ qCInfo(qt3ds::TRACE_INFO) << "Optimizing mesh file: " << theIter->first.GetMulti();
+ for (size_t meshIdx = 0, meshEnd = theIdList.size(); meshIdx < meshEnd; ++meshIdx) {
+ theBuilder.Reset();
+ QT3DSU32 theMeshId(theIdList[meshIdx]);
+ qCInfo(qt3ds::TRACE_INFO) << "Optimizing mesh: " << theMeshId;
+ UICIMP::Mesh *theMesh = UICIMP::Mesh::LoadMulti(theIter->first.GetMulti(), theMeshId);
+ if (!theMesh) {
+ qCWarning(qt3ds::WARNING) << "Failed to load mesh";
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ SMeshScope theMeshScope(theMesh);
+ theBuilder.SetVertexBuffer(theMesh->m_VertexBuffer.m_Entries,
+ theMesh->m_VertexBuffer.m_Stride,
+ theMesh->m_VertexBuffer.m_Data);
+
+ theBuilder.SetIndexBuffer(NVConstDataRef<QT3DSU8>(theMesh->m_IndexBuffer.m_Data.begin(),
+ theMesh->m_IndexBuffer.m_Data.size()),
+ theMesh->m_IndexBuffer.m_ComponentType);
+
+ for (QT3DSU32 jointIdx = 0, jointEnd = theMesh->m_Joints.size(); jointIdx < jointEnd;
+ ++jointIdx) {
+ const UICIMP::Joint &theJoint = theMesh->m_Joints[jointIdx];
+ theBuilder.AddJoint(theJoint.m_JointID, theJoint.m_ParentID, theJoint.m_invBindPose,
+ theJoint.m_localToGlobalBoneSpace);
+ }
+
+ for (QT3DSU32 subsetIdx = 0; subsetIdx < theMesh->m_Subsets.size(); ++subsetIdx) {
+ theBuilder.AddMeshSubset(theMesh->m_Subsets[subsetIdx].m_Name.begin(),
+ theMesh->m_Subsets[subsetIdx].m_Count,
+ theMesh->m_Subsets[subsetIdx].m_Offset,
+ theMesh->m_Subsets[subsetIdx].m_Bounds);
+ }
+ theBuilder.SetDrawParameters(theMesh->m_DrawMode, theMesh->m_Winding);
+ theBuilder.OptimizeMesh();
+ UICIMP::Mesh theOptimizedMesh(theBuilder.GetMesh());
+ FileOpenFlags theFlags = FileWriteFlags();
+ if (meshIdx)
+ theFlags = FileAppendFlags();
+ CFileSeekableIOStream theIOStream(theTempFile.GetMulti(), theFlags);
+ if (!theIOStream.IsOpen()) {
+ qCWarning(qt3ds::WARNING) << "Failed to open temp mesh file";
+ QT3DS_ASSERT(false);
+ } else
+ theOptimizedMesh.SaveMulti(theAllocator, theIOStream, theMeshId);
+ }
+
+ CFilePath theSrcFile(theIter->first);
+ qCInfo(qt3ds::TRACE_INFO) << "Overwriting source file";
+ BOOL success = ::CopyFileExW(theTempFile, theIter->first, NULL, NULL, NULL, 0);
+ if (!success)
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to write to file: " << theSrcFile.GetMulti()
+ << ", is this file locked by source control?";
+ else
+ qCInfo(qt3ds::TRACE_INFO) << "Successfully overwritten original mesh file!";
+ theTempFile.DeleteThisFile();
+ }
+
+ theBuilder.Release();
+
+ return 0;
+}
diff --git a/src/Authoring/MorphLines.pri b/src/Authoring/MorphLines.pri
new file mode 100644
index 00000000..80f48dd0
--- /dev/null
+++ b/src/Authoring/MorphLines.pri
@@ -0,0 +1 @@
+SOURCES += MorphLinesExporter/MorphLines.cpp
diff --git a/src/Authoring/MorphLines.pro b/src/Authoring/MorphLines.pro
new file mode 100644
index 00000000..79e709a9
--- /dev/null
+++ b/src/Authoring/MorphLines.pro
@@ -0,0 +1,38 @@
+TEMPLATE = app
+TARGET = MorphLines
+include($$PWD/commoninclude.pri)
+include($$OUT_PWD/qtAuthoring-config.pri)
+CONFIG += console nostrictstrings
+QT -= gui
+DEFINES += _UNICODE UIC_AUTHORING _AFXDLL PCRE_STATIC
+
+INCLUDEPATH += \
+ UICIMP/UICImportLib \
+ $$PWD/../Runtime/Source/Qt3DSRender/Include \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ ../3rdparty/EASTL/UnknownVersion/include
+
+LIBS += \
+ -L"$$BOOSTDIR" \
+ $$QMAKE_LIBS_FBX \
+ -lws2_32 \
+ -lLua$$qtPlatformTargetSuffix() \
+ -lEASTL$$qtPlatformTargetSuffix() \
+ -lRpcrt4 \
+ -lGdiplus \
+ -lUser32 \
+ -lUserenv \
+ -lWbemuuid \
+ -lWinmm \
+ -l$$BOOSTSIGNALLIB \
+ -l$$BOOSTSYSTEMLIB \
+ -l$$BOOSTFILESYSTEMLIB \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix() \
+ -lCoreLib$$qtPlatformTargetSuffix() \
+ -lCommonLib$$qtPlatformTargetSuffix()
+
+include(MorphLines.pri)
+
+load(qt_tool)
+
+INSTALLS -= target
diff --git a/src/Authoring/MorphLinesExporter/MorphLines.cpp b/src/Authoring/MorphLinesExporter/MorphLines.cpp
new file mode 100644
index 00000000..6a8012a5
--- /dev/null
+++ b/src/Authoring/MorphLinesExporter/MorphLines.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdio.h>
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/IOStreams.h"
+#include "foundation/StringConversionImpl.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSVec3.h"
+#include "UICImportMesh.h"
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+
+namespace {
+
+eastl::string ReadStream(IInStream &inStream)
+{
+ eastl::string retval;
+ bool good = true;
+ do {
+ char buffer[1024] = { 0 };
+ NVDataRef<QT3DSU8> readData(reinterpret_cast<QT3DSU8 *>(buffer), 1024);
+ QT3DSU32 amountRead = inStream.Read(readData);
+ if (amountRead == 0)
+ good = false;
+ else
+ retval.append(buffer, buffer + amountRead);
+
+ } while (good);
+
+ return retval;
+}
+
+eastl::vector<QT3DSVec3> ParsePoints(eastl::string &data)
+{
+ eastl::vector<QT3DSVec3> retval;
+ while (data.size()) {
+ uint32_t pos = data.find("\n");
+ if (pos == eastl::string::npos)
+ pos = data.size() - 1;
+ size_t retvalSize = retval.size();
+ (void)retvalSize;
+
+ eastl::string temp = data.substr(2, pos - 2);
+ data.erase(data.begin(), data.begin() + pos + 1);
+ QT3DSVec3 parseData;
+ char *parsePtr = const_cast<char *>(temp.c_str());
+ char *nextPtr = NULL;
+ parseData[0] = static_cast<float>(strtod(parsePtr, &nextPtr));
+ parsePtr = nextPtr;
+ parseData[1] = static_cast<float>(strtod(parsePtr, &nextPtr));
+ parsePtr = nextPtr;
+ parseData[2] = static_cast<float>(strtod(parsePtr, &nextPtr));
+ parsePtr = nextPtr;
+ retval.push_back(parseData);
+ }
+ return retval;
+}
+}
+
+int main(int c, char **v)
+{
+ if (c < 3)
+ return 1;
+ const char *startFileName = v[1];
+ const char *endFileName = v[2];
+
+ CFileSeekableIOStream startFile(startFileName, FileReadFlags());
+ CFileSeekableIOStream endFile(endFileName, FileReadFlags());
+ if (!(startFile.IsOpen() && endFile.IsOpen())) {
+ puts("failed to open source files");
+ return 1;
+ }
+
+ eastl::string startDataString = ReadStream(startFile);
+ eastl::string endDataString = ReadStream(endFile);
+
+ eastl::vector<QT3DSVec3> startData = ParsePoints(startDataString);
+ eastl::vector<QT3DSVec3> endData = ParsePoints(endDataString);
+
+ QT3DS_ASSERT(!startData.empty());
+ QT3DS_ASSERT(!endData.empty());
+ QT3DS_ASSERT(startData.size() == endData.size());
+
+ UICIMP::MeshBuilder &theBuilder = UICIMP::MeshBuilder::CreateMeshBuilder();
+ eastl::vector<QT3DSVec3> meshBuffer;
+
+ NVBounds3 theBounds(NVBounds3::empty());
+ for (uint32_t idx = 0, end = startData.size(); idx < end; ++idx) {
+ meshBuffer.push_back(startData[idx]);
+ theBounds.include(meshBuffer.back());
+ meshBuffer.push_back(endData[idx]);
+ theBounds.include(meshBuffer.back());
+ }
+ theBuilder.SetDrawParameters(qt3ds::render::NVRenderDrawMode::Lines,
+ qt3ds::render::NVRenderWinding::CounterClockwise);
+ NVDataRef<QT3DSU8> theData = qt3ds::foundation::toU8DataRef(meshBuffer.data(), meshBuffer.size());
+ UICIMP::MeshBuilderVBufEntry theBuilderEntry("attr_pos", theData,
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3);
+ theBuilder.SetVertexBuffer(toConstDataRef(theBuilderEntry));
+ theBuilder.AddMeshSubset(L"points", (QT3DSU32)meshBuffer.size(), 0,
+ theBounds);
+ UICIMP::Mesh &theMesh(theBuilder.GetMesh());
+ theMesh.SaveMulti(v[3]);
+ return 0;
+}
diff --git a/src/Authoring/PresentationCompiler.pro b/src/Authoring/PresentationCompiler.pro
new file mode 100644
index 00000000..f80afbdc
--- /dev/null
+++ b/src/Authoring/PresentationCompiler.pro
@@ -0,0 +1,50 @@
+TEMPLATE = app
+TARGET = Qt3DCompiler
+include($$PWD/../Runtime/commoninclude.pri)
+CONFIG += console
+
+SOURCES += \
+ $$PWD/../Runtime/Source/UICCompiler/Source/UICCompilerMain.cpp
+
+linux {
+ BEGIN_ARCHIVE = -Wl,--whole-archive
+ END_ARCHIVE = -Wl,--no-whole-archive
+}
+
+STATICRUNTIME = \
+ $$BEGIN_ARCHIVE \
+ -lEASTL$$qtPlatformTargetSuffix() \
+ -lLua$$qtPlatformTargetSuffix() \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix() \
+ $$END_ARCHIVE
+
+# On non-windows systems link the whole static archives and do not put them
+# in the prl file to prevent them being linked again by targets that depend
+# upon this shared library
+!win32 {
+ QMAKE_LFLAGS += $$STATICRUNTIME
+ LIBS += -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+} else {
+ LIBS += \
+ $$STATICRUNTIME \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+}
+
+win32 {
+ LIBS += \
+ -lws2_32
+}
+
+linux {
+ LIBS += \
+ -ldl \
+ -lEGL
+}
+
+PREDEPS_LIBS = qt3dsruntimestatic
+
+include($$PWD/../utils.pri)
+PRE_TARGETDEPS += $$fixLibPredeps($$LIBDIR, PREDEPS_LIBS)
+
+load(qt_tool)
+CONFIG -= relative_qt_rpath
diff --git a/src/Authoring/Q3DStudio.pri b/src/Authoring/Q3DStudio.pri
new file mode 100644
index 00000000..d73e6064
--- /dev/null
+++ b/src/Authoring/Q3DStudio.pri
@@ -0,0 +1,310 @@
+
+HEADERS += \
+ Studio/MainFrm.h \
+ Studio/_Win/Application/AboutDlg.h \
+ Studio/_Win/UI/EditCameraBar.h \
+ Studio/_Win/UI/InterpolationDlg.h \
+ Studio/_Win/UI/StartupDlg.h \
+ Studio/_Win/UI/RecentItems.h \
+ Studio/_Win/UI/PlayerWnd.h \
+ Studio/_Win/UI/PlayerContainerWnd.h \
+ Studio/_Win/UI/SceneView.h \
+ Studio/Controls/WidgetControl.h \
+ Studio/_Win/UI/StudioAppPrefsPage.h \
+ Studio/_Win/UI/StudioPreferencesPropSheet.h \
+ Studio/_Win/UI/StudioProjectSettingsPage.h \
+ Studio/_Win/DragNDrop/DropProxy.h \
+ Studio/Palettes/Inspector/ObjectListModel.h \
+ Studio/Palettes/Inspector/ObjectBrowserView.h \
+ $$PWD/Studio/_Win/Application/SubPresentationsDlg.h
+
+FORMS += \
+ Studio/_Win/UI/timeeditdlg.ui \
+ Studio/_Win/UI/StudioAppPrefsPage.ui \
+ Studio/_Win/UI/StudioPreferencesPropSheet.ui \
+ Studio/_Win/UI/StudioProjectSettingsPage.ui \
+ Studio/_Win/UI/InterpolationDlg.ui \
+ Studio/Application/StudioTutorialWidget.ui
+
+SOURCES += \
+ Studio/MainFrm.cpp \
+ Studio/PreviewHelper.cpp \
+ Studio/remoteproject.cpp \
+ Studio/_Win/Application/AboutDlg.cpp \
+ #Studio/_Win/Application/BaseLink.cpp \
+ Studio/_Win/Application/MsgRouter.cpp \
+ Studio/_Win/Application/StudioApp.cpp \
+ #Studio/_Win/Application/TextLink.cpp \
+ #Studio/_Win/Application/WebLink.cpp \
+ Studio/_Win/Controls/AppFonts.cpp \
+ Studio/_Win/Controls/BufferedRenderer.cpp \
+ #Studio/_Win/Controls/MFCEditControl.cpp \
+ Studio/_Win/Controls/OffscreenRenderer.cpp \
+ #Studio/_Win/Controls/PlatformEditControl.cpp \
+ #Studio/_Win/Controls/PlatformStaticControl.cpp \
+ #Studio/_Win/Controls/PlatformWindowControl.cpp \
+ Studio/_Win/Controls/WinRenderer.cpp \
+ #Studio/_Win/Controls/WndControl.cpp \
+ Studio/_Win/DragNDrop/DropProxy.cpp \
+ #Studio/_Win/DragNDrop/WinDnd.cpp \
+ Studio/_Win/Palettes/PaletteManager.cpp \
+ #Studio/_Win/Palettes/Progress/ProgressPalette.cpp \
+ #Studio/_Win/Palettes/Progress/ProgressView.cpp \
+ #Studio/_Win/Palettes/Splash/SplashPalette.cpp \
+ Studio/_Win/Palettes/Splash/SplashView.cpp \
+ #Studio/_Win/Studio/stdafx.cpp \
+ #Studio/_Win/UI/ContextMenu.cpp \
+ #Studio/_Win/UI/ControlButton.cpp \
+ #Studio/_Win/UI/CrashDlg.cpp \
+ Studio/_Win/UI/EditCameraBar.cpp \
+ Studio/_Win/UI/EditorPane.cpp \
+ #Studio/_Win/UI/FileDialogEX.cpp \
+ #Studio/_Win/UI/GLVersionDlg.cpp \
+ Studio/_Win/UI/InterpolationDlg.cpp \
+ #Studio/_Win/UI/MemoryDC.cpp \
+ #Studio/_Win/UI/MenuEdit.cpp \
+ #Studio/_Win/UI/MenuItem.cpp \
+ #Studio/_Win/UI/NumericEdit.cpp \
+ Studio/_Win/UI/PlayerContainerWnd.cpp \
+ Studio/_Win/UI/PlayerWnd.cpp \
+ #Studio/_Win/UI/PopupWnd.cpp \
+ #Studio/_Win/UI/PreviewOutputDlg.cpp \
+ Studio/_Win/UI/RecentItems.cpp \
+ #Studio/_Win/UI/ReportDlg.cpp \
+ #Studio/_Win/UI/ResetKeyframeValuesDlg.cpp \
+ Studio/_Win/UI/SceneView.cpp \
+ Studio/_Win/UI/StartupDlg.cpp \
+ Studio/_Win/UI/StudioAppPrefsPage.cpp \
+ #Studio/_Win/UI/StudioPaletteBar.cpp \
+ Studio/_Win/UI/StudioPreferencesPropSheet.cpp \
+ Studio/_Win/UI/StudioProjectSettingsPage.cpp \
+ Studio/_Win/UI/TimeEditDlg.cpp \
+ Studio/_Win/Utils/MouseCursor.cpp \
+ #Studio/_Win/Utils/ResImage.cpp \
+ #Studio/_Win/Utils/WinUtils.cpp \
+ Studio/_Win/Workspace/Dialogs.cpp \
+ Studio/_Win/Workspace/Views.cpp \
+ Studio/Application/StudioInstance.cpp \
+ Studio/Application/StudioTutorialWidget.cpp \
+ Studio/Controls/BaseMeasure.cpp \
+ Studio/Controls/BlankControl.cpp \
+ Studio/Controls/BreadCrumbControl.cpp \
+ Studio/Controls/ButtonControl.cpp \
+ Studio/Controls/Control.cpp \
+ Studio/Controls/ControlData.cpp \
+ Studio/Controls/ControlGraph.cpp \
+ Studio/Controls/FloatEdit.cpp \
+ Studio/Controls/FlowLayout.cpp \
+ Studio/Controls/InsertionLine.cpp \
+ Studio/Controls/InsertionOverlay.cpp \
+ Studio/Controls/LazyFlow.cpp \
+ Studio/Controls/ListBoxItem.cpp \
+ Studio/Controls/ListBoxStringItem.cpp \
+ Studio/Controls/ListLayout.cpp \
+ Studio/Controls/NameEdit.cpp \
+ Studio/Controls/OverlayControl.cpp \
+ Studio/Controls/Renderer.cpp \
+ Studio/Controls/ScrollController.cpp \
+ Studio/Controls/Scroller.cpp \
+ Studio/Controls/ScrollerBackground.cpp \
+ Studio/Controls/ScrollerBar.cpp \
+ Studio/Controls/ScrollerButtonControl.cpp \
+ Studio/Controls/ScrollerThumb.cpp \
+ Studio/Controls/SIcon.cpp \
+ Studio/Controls/SplashControl.cpp \
+ Studio/Controls/SplitBar.cpp \
+ Studio/Controls/Splitter.cpp \
+ Studio/Controls/StringEdit.cpp \
+ Studio/Controls/TextEdit.cpp \
+ Studio/Controls/TextEditContextMenu.cpp \
+ Studio/Controls/TextEditInPlace.cpp \
+ Studio/Controls/TimeEdit.cpp \
+ Studio/Controls/ToggleButton.cpp \
+ Studio/Controls/TreeControl.cpp \
+ Studio/Controls/TreeItem.cpp \
+ Studio/DragAndDrop/BasicObjectDropSource.cpp \
+ Studio/DragAndDrop/DropContainer.cpp \
+ Studio/DragAndDrop/DropSource.cpp \
+ Studio/DragAndDrop/DropTarget.cpp \
+ Studio/DragAndDrop/ExplorerFileDropSource.cpp \
+ Studio/DragAndDrop/FileDropSource.cpp \
+ Studio/DragAndDrop/ListBoxDropSource.cpp \
+ Studio/DragAndDrop/ListBoxDropTarget.cpp \
+ Studio/DragAndDrop/ProjectDropTarget.cpp \
+ Studio/DragAndDrop/SceneDropTarget.cpp \
+ Studio/DragAndDrop/TimelineDropSource.cpp \
+ Studio/DragAndDrop/TimelineDropTarget.cpp \
+ Studio/Palettes/Action/ActionModel.cpp \
+ Studio/Palettes/Action/ActionView.cpp \
+ Studio/Palettes/Action/ActionContextMenu.cpp \
+ Studio/Palettes/Action/EventsModel.cpp \
+ Studio/Palettes/Action/EventsBrowserView.cpp \
+ Studio/Palettes/Action/PropertyModel.cpp \
+ Studio/Palettes/BasicObjects/BasicObjectsModel.cpp \
+ Studio/Palettes/BasicObjects/BasicObjectsView.cpp \
+ Studio/Palettes/Inspector/ChooserModelBase.cpp \
+ Studio/Palettes/Inspector/EasyInspectorGroup.cpp \
+ Studio/Palettes/Inspector/GuideInspectable.cpp \
+ Studio/Palettes/Inspector/InspectableBase.cpp \
+ Studio/Palettes/Inspector/InspectorGroup.cpp \
+ Studio/Palettes/Inspector/ImageChooserView.cpp \
+ Studio/Palettes/Inspector/FileChooserView.cpp \
+ Studio/Palettes/Inspector/FileChooserModel.cpp \
+ Studio/Palettes/Inspector/ImageChooserModel.cpp \
+ Studio/Palettes/Inspector/MeshChooserModel.cpp \
+ Studio/Palettes/Inspector/MeshChooserView.cpp \
+ Studio/Palettes/Inspector/TextureChooserView.cpp \
+ Studio/Palettes/Inspector/UICDMInspectable.cpp \
+ Studio/Palettes/Inspector/UICDMInspectorGroup.cpp \
+ Studio/Palettes/Inspector/UICDMInspectorRow.cpp \
+ Studio/Palettes/Inspector/UICDMMaterialInspectable.cpp \
+ Studio/Palettes/Inspector/UICDMSceneInspectable.cpp \
+ Studio/Palettes/Inspector/InspectorControlView.cpp \
+ Studio/Palettes/Inspector/InspectorControlModel.cpp \
+ Studio/Palettes/Inspector/ObjectListModel.cpp \
+ Studio/Palettes/Inspector/ObjectBrowserView.cpp \
+ Studio/Palettes/Inspector/ObjectReferenceModel.cpp \
+ Studio/Palettes/Inspector/ObjectReferenceView.cpp \
+ Studio/Palettes/Inspector/TabOrderHandler.cpp \
+ #Studio/Palettes/Master/MasterControl.cpp \
+ #Studio/Palettes/Master/MasterView.cpp \
+ #Studio/Palettes/Progress/ProgressControl.cpp \
+ Studio/Palettes/Project/ProjectView.cpp \
+ Studio/Palettes/Project/ProjectFileSystemModel.cpp \
+ Studio/Palettes/Project/ProjectContextMenu.cpp \
+ Studio/Palettes/Slide/SlideModel.cpp \
+ Studio/Palettes/Slide/SlideView.cpp \
+ Studio/Palettes/Slide/SlideContextMenu.cpp \
+ Studio/Palettes/Timeline/AreaBoundingRect.cpp \
+ Studio/Palettes/Timeline/AssetTimelineKeyframe.cpp \
+ Studio/Palettes/Timeline/BaseStateRow.cpp \
+ Studio/Palettes/Timeline/BaseTimebarlessRow.cpp \
+ Studio/Palettes/Timeline/BaseTimelineTreeControl.cpp \
+ Studio/Palettes/Timeline/BlankToggleControl.cpp \
+ Studio/Palettes/Timeline/ColorBlankControl.cpp \
+ Studio/Palettes/Timeline/ColorControl.cpp \
+ Studio/Palettes/Timeline/CommentEdit.cpp \
+ Studio/Palettes/Timeline/ComponentContextMenu.cpp \
+ Studio/Palettes/Timeline/FilterToolbar.cpp \
+ Studio/Palettes/Timeline/KeyframeContextMenu.cpp \
+ #Studio/Palettes/Timeline/MultiSelectAspect.cpp \
+ Studio/Palettes/Timeline/Playhead.cpp \
+ Studio/Palettes/Timeline/PropertyColorControl.cpp \
+ Studio/Palettes/Timeline/PropertyGraphKeyframe.cpp \
+ Studio/Palettes/Timeline/PropertyRow.cpp \
+ Studio/Palettes/Timeline/PropertyTimebarGraph.cpp \
+ Studio/Palettes/Timeline/PropertyTimebarRow.cpp \
+ Studio/Palettes/Timeline/PropertyTimelineKeyframe.cpp \
+ Studio/Palettes/Timeline/PropertyToggleControl.cpp \
+ Studio/Palettes/Timeline/PropertyTreeControl.cpp \
+ Studio/Palettes/Timeline/ScalableScroller.cpp \
+ Studio/Palettes/Timeline/ScalableScrollerBar.cpp \
+ Studio/Palettes/Timeline/SlideRow.cpp \
+ Studio/Palettes/Timeline/SlideTimebarRow.cpp \
+ Studio/Palettes/Timeline/Snapper.cpp \
+ Studio/Palettes/Timeline/StateRow.cpp \
+ Studio/Palettes/Timeline/StateRowFactory.cpp \
+ Studio/Palettes/Timeline/StateTimebarlessRow.cpp \
+ Studio/Palettes/Timeline/StateTimebarRow.cpp \
+ Studio/Palettes/Timeline/TimebarControl.cpp \
+ Studio/Palettes/Timeline/TimebarTip.cpp \
+ #Studio/Palettes/Timeline/TimeEditAspect.cpp \
+ Studio/Palettes/Timeline/TimelineControl.cpp \
+ Studio/Palettes/Timeline/TimelineFilter.cpp \
+ Studio/Palettes/Timeline/TimelineKeyframe.cpp \
+ Studio/Palettes/Timeline/TimelineRow.cpp \
+ Studio/Palettes/Timeline/TimelineSplitter.cpp \
+ Studio/Palettes/Timeline/TimelineTimelineLayout.cpp \
+ Studio/Palettes/Timeline/TimelineTreeLayout.cpp \
+ Studio/Palettes/Timeline/TimeMeasure.cpp \
+ Studio/Palettes/Timeline/TimeToolbar.cpp \
+ Studio/Palettes/Timeline/ToggleBlankControl.cpp \
+ Studio/Palettes/Timeline/ToggleControl.cpp \
+ Studio/Palettes/Timeline/ToggleToolbar.cpp \
+ Studio/Palettes/Timeline/TreeBlankControl.cpp \
+ Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.cpp \
+ Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/KeyframesManager.cpp \
+ Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.cpp \
+ Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.cpp \
+ Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp \
+ Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.cpp \
+ Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.cpp \
+ Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.cpp \
+ Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.cpp \
+ Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.cpp \
+ Studio/Render/PathWidget.cpp \
+ Studio/Render/StudioRenderer.cpp \
+ Studio/Render/StudioRendererTranslation.cpp \
+ Studio/Render/StudioRotationWidget.cpp \
+ Studio/Render/StudioScaleWidget.cpp \
+ Studio/Render/StudioTranslationWidget.cpp \
+ Studio/Render/StudioWidget.cpp \
+ Studio/Render/WGLRenderContext.cpp \
+ #Studio/UI/CustomReBar.cpp \
+ #Studio/UI/PaletteState.cpp \
+ Studio/Utils/CmdLineParser.cpp \
+ Studio/Utils/ImportUtils.cpp \
+ Studio/Utils/ResourceCache.cpp \
+ Studio/Utils/StringLoader.cpp \
+ Studio/Utils/StudioUtils.cpp \
+ Studio/Utils/SystemPreferences.cpp \
+ Studio/Utils/TickTock.cpp \
+ Studio/Controls/ClickableLabel.cpp \
+ Studio/Controls/WidgetControl.cpp \
+ $$PWD/Studio/_Win/Application/SubPresentationsDlg.cpp
+
+HEADERS += \
+ Studio/_Win/UI/TimeEditDlg.h \
+ Studio/Controls/TextEditContextMenu.h \
+ Studio/Palettes/Action/ActionModel.h \
+ Studio/Palettes/Action/ActionContextMenu.h \
+ Studio/Palettes/Action/ActionView.h \
+ Studio/Palettes/Action/EventsModel.h \
+ Studio/Palettes/Action/EventsBrowserView.h \
+ Studio/Palettes/Action/PropertyModel.h \
+ Studio/Palettes/BasicObjects/BasicObjectsModel.h \
+ Studio/Palettes/BasicObjects/BasicObjectsView.h \
+ Studio/Palettes/Inspector/InspectorControlView.h \
+ Studio/Palettes/Inspector/InspectorControlModel.h \
+# Studio/Palettes/Project/ProjectBrokenLinkMenu.h \
+# Studio/Palettes/Project/ProjectContextMenu.h \
+ Studio/Palettes/Slide/SlideModel.h \
+ Studio/Palettes/Slide/SlideView.h \
+ Studio/Palettes/Timeline/ComponentContextMenu.h \
+ Studio/Palettes/Timeline/KeyframeContextMenu.h \
+ Studio/Palettes/Timeline/Bindings/IKeyframeSelector.h \
+ Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h \
+ Studio/Palettes/Timeline/Bindings/ITimelineItem.h \
+ Studio/Palettes/Timeline/Bindings/ITimelineItemProperty.h \
+ Studio/Palettes/Timeline/Bindings/ITimelineKeyframesManager.h \
+ Studio/Palettes/Timeline/Bindings/ITimelineTimebar.h \
+ Studio/Palettes/Slide/SlideView.h \
+ Studio/Palettes/Slide/SlideContextMenu.h \
+ Studio/Controls/ClickableLabel.h \
+ Studio/_Win/UI/SceneView.h \
+ Studio/PreviewHelper.h \
+ Studio/remoteproject.h \
+ Studio/Application/StudioTutorialWidget.h \
+ Studio/Palettes/Inspector/ChooserModelBase.h \
+ Studio/Palettes/Inspector/ImageChooserView.h \
+ Studio/Palettes/Inspector/ImageChooserModel.h \
+ Studio/Palettes/Inspector/MeshChooserModel.h \
+ Studio/Palettes/Inspector/MeshChooserView.h \
+ Studio/Palettes/Inspector/ObjectReferenceModel.h \
+ Studio/Palettes/Inspector/ObjectReferenceView.h \
+ Studio/Palettes/Inspector/FileChooserView.h \
+ Studio/Palettes/Inspector/FileChooserModel.h \
+ Studio/Palettes/Inspector/TextureChooserView.h \
+ Studio/Palettes/Inspector/TabOrderHandler.h \
+ Studio/Palettes/Project/ProjectView.h \
+ Studio/Palettes/Project/ProjectFileSystemModel.h \
+ Studio/Palettes/Project/ProjectContextMenu.h \
+
diff --git a/src/Authoring/Q3DStudio.pro b/src/Authoring/Q3DStudio.pro
new file mode 100644
index 00000000..1b2bc266
--- /dev/null
+++ b/src/Authoring/Q3DStudio.pro
@@ -0,0 +1,225 @@
+TEMPLATE = app
+TARGET = Qt3DStudio
+include($$PWD/commoninclude.pri)
+include($$OUT_PWD/qtAuthoring-config.pri)
+CONFIG += nostrictstrings
+DEFINES += _UNICODE UNICODE UIC_AUTHORING _AFXDLL \
+ PCRE_STATIC BOOST_SIGNALS_NO_DEPRECATION_WARNING EASTL_MINMAX_ENABLED=0 \
+ EASTL_NOMINMAX=0 DOM_DYNAMIC DRIVE_DESIGN_STUDIO
+
+win: QMAKE_LFLAGS += /MANIFEST /ENTRY:"wWinMainCRTStartup"
+
+QT += core gui openglextensions
+QT += qml quick widgets quickwidgets network
+
+INCLUDEPATH += \
+ Studio/_Win/Include \
+ Studio/_Win/Application \
+ Studio/_Win/Controls \
+ Studio/_Win/DragNDrop \
+ Studio/_Win/Palettes \
+ Studio/_Win/Palettes/Progress \
+ Studio/_Win/Palettes/Splash \
+ Studio/_Win/UI \
+ Studio/_Win/Utils \
+ Studio/Application \
+ Studio/Controls \
+ Studio/DragAndDrop \
+ Studio/Palettes \
+ Studio/Palettes/Action \
+ Studio/Palettes/Action/ActionParamRow \
+ Studio/Palettes/BasicObjects \
+ Studio/Palettes/Inspector \
+ Studio/Palettes/Master \
+ Studio/Palettes/Progress \
+ Studio/Palettes/Project \
+ Studio/Palettes/Slide \
+ Studio/Palettes/Timeline \
+ Studio/Render \
+ Studio/UI \
+ Studio/Utils \
+ Studio/Workspace \
+ Studio/Workspace/Views \
+ Studio \
+ Studio/English.lproj/Strings \
+ UICIMP/UICImportLib \
+ UICIMP/UICImportSGTranslation \
+ UICDM/Systems \
+ Common/Code/Thread \
+ Common/Code/IO \
+ Common/Code \
+ Common/Code/Exceptions \
+ Common/Code/_Win32/Include \
+ Common/Code/_Win32 \
+ Common/Code/Graph \
+ Common/Code/Report \
+ Common/Code/Memory \
+ Client/Code/Core/Utility \
+ Client/Code/Core/Types \
+ Client/Code/Core/Commands \
+ Client/Code/Core/Core \
+ Client/Code/Core \
+ Client/Code/Core/Doc \
+ Client/Code/Core/Doc/ClientDataModelBridge \
+ Client/Code/Shared \
+ Client/Code/Shared/Log \
+ $$PWD/../Runtime/Source/Qt3DSRender/Include \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ $$PWD/../Runtime/Source/UICRender/Include \
+ $$PWD/../Runtime/Source/UICRender/GraphObjects \
+ $$PWD/../Runtime/Source/UICRender/ResourceManager \
+ $$PWD/../Runtime/Source/UICState/Application \
+ ../3rdparty/EASTL/UnknownVersion/include \
+ ../3rdparty/color
+
+
+LIBS += \
+ -L"$$BOOSTDIR"
+
+linux {
+ BEGIN_ARCHIVE = -Wl,--whole-archive
+ END_ARCHIVE = -Wl,--no-whole-archive
+}
+
+STATICRUNTIME = \
+ $$BEGIN_ARCHIVE \
+ -lLua$$qtPlatformTargetSuffix() \
+ -lEASTL$$qtPlatformTargetSuffix() \
+ -lpcre$$qtPlatformTargetSuffix() \
+ -lTinyXML$$qtPlatformTargetSuffix() \
+ -lColladaDOM$$qtPlatformTargetSuffix() \
+ -lUICDM$$qtPlatformTargetSuffix() \
+ -lCommonLib$$qtPlatformTargetSuffix() \
+ -lCoreLib$$qtPlatformTargetSuffix() \
+ $$END_ARCHIVE
+
+# On non-windows systems link the whole static archives and do not put them
+# in the prl file to prevent them being linked again by targets that depend
+# upon this shared library
+!win32 {
+ QMAKE_LFLAGS += $$STATICRUNTIME
+} else {
+ DEFINES += WIN32_LEAN_AND_MEAN
+ LIBS += $$STATICRUNTIME
+ QMAKE_LFLAGS += /NODEFAULTLIB:tinyxml.lib
+}
+
+LIBS += \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix() \
+ -l$$BOOSTSIGNALLIB \
+ -l$$BOOSTSYSTEMLIB \
+ -l$$BOOSTFILESYSTEMLIB \
+ $$QMAKE_LIBS_FBX
+
+linux {
+ LIBS += \
+ -ldl \
+ -lEGL
+}
+
+win: PRECOMPILED_HEADER = Studio/_Win/Studio/stdafx.h
+
+include(Q3DStudio.pri)
+
+
+DISTFILES += \
+ Studio/Palettes/BasicObjects/BasicObjectsView.qml \
+ Studio/Palettes/BasicObjects/SlideView.qml
+
+FORMS += \
+ Studio/MainFrm.ui \
+ Studio/_Win/Application/AboutDlg.ui \
+ Studio/_Win/UI/StartupDlg.ui \
+ Studio/_Win/Application/SubPresentationsDlg.ui
+
+RESOURCES += \
+ Studio/MainFrm.qrc \
+ qml.qrc \
+ Studio/images.qrc
+
+PREDEPS_LIBS += \
+ qt3dsruntimestatic \
+ UICDM \
+ CommonLib \
+ CoreLib
+
+
+# Optional license handler
+isEmpty(TQTC_LICENSE_MANAGING): TQTC_LICENSE_MANAGING=$$(TQTC_LICENSE_MANAGING)
+!isEmpty(TQTC_LICENSE_MANAGING) {
+ DEFINES += USE_LICENSE_HANDLER LICENSE_HANDLER_AS_DLL
+ LIBS += -llicensehandler$$qtPlatformTargetSuffix()
+ INCLUDEPATH += $$TQTC_LICENSE_MANAGING/studio3d
+}
+
+include($$PWD/../utils.pri)
+PRE_TARGETDEPS += $$fixLibPredeps($$LIBDIR, PREDEPS_LIBS)
+
+# Copy necessary resources
+
+ABS_PRJ_ROOT = $$absolute_path($$PWD/../..)
+macos:ABS_DEST_DIR = $$absolute_path($$BINDIR)/$${TARGET}.app/Contents
+!macos:ABS_DEST_DIR = $$absolute_path($$BINDIR)
+macos:RES = "Resources"
+!macos:RES = "res"
+
+defineReplace(doReplaceResCopy_copy1) {
+ filePath = $$absolute_path($$1)
+ filePath = $$replace(filePath, $$ABS_PRJ_ROOT/Studio, $$ABS_DEST_DIR)
+ PRE_TARGETDEPS += $$filePath
+ export(PRE_TARGETDEPS)
+ return($$system_path($$filePath))
+}
+defineReplace(doReplaceResCopy_copy2) {
+ filePath = $$absolute_path($$1)
+ macos:filePath = $$replace(filePath, $$ABS_PRJ_ROOT/Studio, $$ABS_DEST_DIR/$$RES)
+ !macos:filePath = $$replace(filePath, $$ABS_PRJ_ROOT/Studio, $$ABS_DEST_DIR)
+ PRE_TARGETDEPS += $$filePath
+ export(PRE_TARGETDEPS)
+ return($$system_path($$filePath))
+}
+
+defineReplace(addFilesToResources) {
+ # Remove directories from results
+ input_files = $$files($$2, true)
+ for(input_file, input_files) {
+ last_part = $$split(input_file, /)
+ last_part = $$last(last_part)
+ last_split = $$split(last_part, .)
+ split_size = $$size(last_split)
+ equals(split_size, 2): $${1}.input_files += $$input_file
+ }
+ $${1}.input = $${1}.input_files
+ $${1}.commands = $(COPY_FILE) "${QMAKE_FILE_IN}" "${QMAKE_FILE_OUT}"
+ $${1}.CONFIG = no_link
+ $${1}.name = $$1
+ $${1}.output_function = doReplaceResCopy_$${1}
+
+ export($${1}.input_files)
+ export($${1}.input)
+ export($${1}.output_function)
+ export($${1}.commands)
+ export($${1}.CONFIG)
+ export($${1}.name)
+
+ $${1}_install.files = $$2
+ $${1}_install.path = $$[QT_INSTALL_BINS]/$$3
+ INSTALLS += $${1}_install
+ export($${1}_install.files)
+ export($${1}_install.path)
+ export(INSTALLS)
+
+ return($$1)
+}
+
+QMAKE_EXTRA_COMPILERS += $$addFilesToResources("copy1", $$PWD/../../Studio/Content/*, Content)
+QMAKE_EXTRA_COMPILERS += $$addFilesToResources("copy2", "$$PWD/../../Studio/Build Configurations/*", "Build Configurations")
+
+CONFIG += exceptions
+DISTFILES +=
+
+RESOURCES += \
+ Studio/qt3dstudio.qrc
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/src/Authoring/Qt3DSState.pri b/src/Authoring/Qt3DSState.pri
new file mode 100644
index 00000000..0e8d1a14
--- /dev/null
+++ b/src/Authoring/Qt3DSState.pri
@@ -0,0 +1,5 @@
+SOURCES += \
+ $$PWD/../Runtime/Source/Qt3DSState/Source/Qt3DSStateEngine.cpp \
+ $$PWD/../Runtime/Source/Qt3DSState/Source/Qt3DSStateFactory.cpp \
+ $$PWD/../Runtime/Source/Qt3DSState/Source/Qt3DSStateInputStreamFactory.cpp \
+ $$PWD/../Runtime/Source/Qt3DSState/Source/Qt3DSStateLuaEngine.cpp
diff --git a/src/Authoring/Qt3DSState.pro b/src/Authoring/Qt3DSState.pro
new file mode 100644
index 00000000..60abe959
--- /dev/null
+++ b/src/Authoring/Qt3DSState.pro
@@ -0,0 +1,21 @@
+TEMPLATE = lib
+TARGET = qt3dsstate
+CONFIG += staticlib console
+include($$PWD/commoninclude.pri)
+DEFINES += QT3DS_STATE_EXPORTS
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ $$PWD/../Runtime/Source/Runtime/Include \
+ $$PWD/../Runtime/Source/System/Include \
+ $$PWD/../Runtime/Source/Qt3DSRender/Include \
+ $$PWD/../Runtime/Source/UICState/Include \
+ $$PWD/../Runtime/Source/UICState/Editor \
+ $$PWD/../Runtime/Source/UICState/Debugger \
+ $$PWD/../Runtime/Source/Qt3DSState/Include \
+ $$PWD/../Runtime/Source/Qt3DSState/InternalInclude \
+ $$PWD/../Runtime/Source/UICEvent/Include \
+ $$PWD/../Runtime/Source/UICEvent/InternalInclude \
+ ../3rdparty/EASTL/UnknownVersion/include \
+ ../3rdparty/Lua/UnknownVersion/src
+
+include(Qt3DSState.pri)
diff --git a/src/Authoring/Studio/Application/MsgRouter.h b/src/Authoring/Studio/Application/MsgRouter.h
new file mode 100644
index 00000000..78dbf4f6
--- /dev/null
+++ b/src/Authoring/Studio/Application/MsgRouter.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_MSG_ROUTER_H
+#define INCLUDED_MSG_ROUTER_H 1
+#pragma once
+
+//==============================================================================
+// Defines
+//==============================================================================
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioConst.h"
+
+#include <QEvent>
+#include <QObject>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CCmd;
+class CCore;
+
+class CRoutedMessageBase
+{
+public:
+ CRoutedMessageBase() {}
+ virtual ~CRoutedMessageBase() {}
+
+ virtual void Notify() = 0;
+};
+
+template <typename TObject, typename TData>
+class CRoutedMessageImpl : public CRoutedMessageBase
+{
+protected:
+ typedef void (TObject::*TMethod)(const TData &);
+
+public:
+ TObject *m_Object;
+ TMethod m_Method;
+ TData m_Data;
+
+ CRoutedMessageImpl(TObject *inObject, TMethod inMethod, const TData &inData)
+ : m_Object(inObject)
+ , m_Method(inMethod)
+ , m_Data(inData)
+ {
+ }
+
+ virtual void Notify() { (m_Object->*m_Method)(m_Data); }
+};
+
+//==============================================================================
+/**
+ * Routes user-defined messages between different threads of an application.
+ */
+class CMsgRouter : public QObject
+{
+protected:
+ class SMessageData;
+
+public:
+ typedef void (CMsgRouter::*TMainThreadMethod)(SMessageData *inMessageData);
+
+public:
+ static CMsgRouter *GetInstance();
+ virtual ~CMsgRouter();
+
+ void SendCommand(CCmd *inCommand, CCore *inCore);
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+ CMsgRouter(); ///< This is a singleton so the constructor is not public (call GetInstance)
+
+ class SMessageData : public QEvent
+ {
+ public:
+ SMessageData(int eventType);
+
+ TMainThreadMethod Method;
+ void *Data;
+ void *Data2;
+ };
+
+ void OnAsyncNotification(SMessageData *inMessageData);
+ void OnCommand(SMessageData *inMessageData);
+
+private:
+ int m_eventType;
+};
+
+#endif // INCLUDED_MSG_ROUTER_H
diff --git a/src/Authoring/Studio/Application/StudioConst.h b/src/Authoring/Studio/Application/StudioConst.h
new file mode 100644
index 00000000..6463cb7d
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioConst.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+// User Windows messages
+#ifndef WM_APP
+#define WM_APP 0x8000
+#endif
+#define WM_STUDIO_INITIALIZE_PALETTES (WM_APP + 1)
+#define WM_STUDIO_DUPLICATE_SERIAL (WM_APP + 2)
+#define WM_STUDIO_SHOWCOMPRESSION (WM_APP + 3)
+#define WM_STUDIO_LOADPROGRESS (WM_APP + 4)
+#define WM_STUDIO_NOTIFYLOADCOMPLETE (WM_APP + 5)
+#define WM_STUDIO_TIMER (WM_APP + 6)
+#define WM_STUDIO_MESSAGE_ROUTER (WM_APP + 7)
+#define WM_STUDIO_OPEN_RECENT_MIN (WM_APP + 9)
+#define WM_STUDIO_OPEN_RECENT_MAX (WM_APP + 19)
+#define WM_STUDIO_QUICKSTART_MIN (WM_APP + 31)
+#define WM_STUDIO_QUICKSTART_MAX (WM_APP + 44)
+#define WM_CUSTOMIZE_TOOLBAR (WM_APP + 45)
+
+enum EPreviewApplication { INTERNET_EXPLORER = 0, UIC_MEDIA_PLAYER, WINDOWS_MEDIA_PLAYER };
+
+// property pages
+const long PAGE_STUDIOAPPPREFERENCES = 0;
+const long PAGE_STUDIOPROJECTSETTINGS = 1;
+
+// Playhead moving with keyboard:
+const long SHIFT_PLAYHEAD_SMALL_TICK = 0;
+const long SHIFT_PLAYHEAD_LARGE_TICK = 1;
+
+// Used to reset default preferences
+const long PREFS_RESET_DEFAULTS = 999;
+
+// Message values
+#define STUDIO_PLAYHEADUPDATEONLY -1
+#define STUDIO_PLAYHEADSYNCPRESENTATION -2
+
+const unsigned long PARAMINDEX_RED = 0;
+const unsigned long PARAMINDEX_GREEN = 1;
+const unsigned long PARAMINDEX_BLUE = 2;
+const unsigned long PARAMINDEX_ALPHA = 3;
+
+const unsigned long PARAMINDEX_X = 0;
+const unsigned long PARAMINDEX_Y = 1;
+const unsigned long PARAMINDEX_Z = 2;
+
+// These are the new operation update masks
+namespace FILTERMASK {
+const long FILTER_MODELS = 0x02; // Mask for filtering out Models
+const long FILTER_IMAGES = 0x20; // Mask for filtering out Images
+const long FILTER_ALL = 0xff; // Used for adding all files back to display mode
+}
+
+// Used for timebar display - should we display Comments or Time Start/End/Duration information?
+const long TIMEBAR_COMMENTS = 1;
+const long TIMEBAR_TIMEINFO = 2;
+
+// Used to set the number of decimal places in the float dialog boxes.
+const long FLOAT_NUM_DECIMAL_PLACES = 3;
+
+// Default palette positions
+const long DEFAULT_MAINFRM_STARTWIDTH = 25;
+const long DEFAULT_MAINFRM_WIDTH = 50;
+const long DEFAULT_MAINFRM_STARTHEIGHT = 0;
+const long DEFAULT_MAINFRM_HEIGHT = 50;
+
+const long DEFAULT_INSPECTOR_STARTHEIGHT = 50;
+const long DEFAULT_INSPECTOR_HEIGHT = 50;
+const long DEFAULT_INSPECTOR_STARTWIDTH = 0;
+const long DEFAULT_INSPECTOR_WIDTH = 25;
+
+const long DEFAULT_LIBRARY_STARTHEIGHT = 0;
+const long DEFAULT_LIBRARY_HEIGHT = 50;
+const long DEFAULT_LIBRARY_STARTWIDTH = 0;
+const long DEFAULT_LIBRARY_WIDTH = 25;
+
+const long DEFAULT_TIMELINE_STARTHEIGHT = 50;
+const long DEFAULT_TIMELINE_HEIGHT = 50;
+const long DEFAULT_TIMELINE_STARTWIDTH = 25;
+const long DEFAULT_TIMELINE_WIDTH = 75;
+
+const long DEFAULT_HISTORY_STARTHEIGHT = 0;
+const long DEFAULT_HISTORY_HEIGHT = 50;
+const long DEFAULT_HISTORY_STARTWIDTH = 75;
+const long DEFAULT_HISTORY_WIDTH = 25;
+
+const long DEFAULT_STORAGE_STARTHEIGHT = 0;
+const long DEFAULT_STORAGE_HEIGHT = 50;
+const long DEFAULT_STORAGE_STARTWIDTH = 75;
+const long DEFAULT_STORAGE_WIDTH = 25;
+
+const long DEFAULT_HELP_STARTHEIGHT = 25;
+const long DEFAULT_HELP_HEIGHT = 50;
+const long DEFAULT_HELP_STARTWIDTH = 25;
+const long DEFAULT_HELP_WIDTH = 50;
+
+// Port number for serial number verification on the LAN
+const long SERIAL_NUMBER_PORT = 3133;
+const long SERIAL_NUMBER_BASE = 10;
+const long NUMBER_SERIAL_DIGITS_CHECK = 12;
+
+// Constants for AKTRACE statements
+// These are bitmasks - must be sequential and not overlap.
+const long TRACE_STUDIO_OBJECT = 0x0001;
+const long TRACE_TIMELINE = 0x0002;
+const long TRACE_KEYFRAMEDATA = 0x0004;
+const long TRACE_ANIMTRACKS = 0x0008;
+const long TRACE_UNDOREDO = 0x0010;
+const long TRACE_LIBRARY = 0x0020;
+const long TRACE_MSGHANDLER = 0x0040;
+const long TRACE_SNAPPING = 0x0080;
+const long TRACE_INSPECTOR = 0x0100;
+const long TRACE_CLIENT = 0x0200;
+const long TRACE_STORAGE = 0x0400;
+const long TRACE_TESTING = 0x0800;
+const long TRACE_HELPVIEW = 0x1000;
+const long TRACE_STUDIODOC = 0x2000;
+const long TRACE_MAINFRAME = 0x4000;
+const long TRACE_ALL = 0xffff;
+
+const char CLIENT_CORE_DLL_NAME[] = "AKCore.dll";
+
+// Timeline icon dimensions
+const long TREEICON_WIDTH = 14;
+const long TREEICON_HEIGHT = 14;
+const long TIMER_DRAGHOVEREXPAND = 2;
+const long TIMER_DRAGDROPSCROLL = 1;
+const long DRAGSCROLL_DIRECTION_UP = 1;
+const long DRAGSCROLL_DIRECTION_DOWN = 2;
+const long TIMER_DRAGDROPSCROLL_DELAY = 20;
+const long TIMER_DRAGHOVEREXPAND_DELAY = 1500; // 2000; // 3-second delay
diff --git a/src/Authoring/Studio/Application/StudioDefs.h b/src/Authoring/Studio/Application/StudioDefs.h
new file mode 100644
index 00000000..16465427
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioDefs.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef STUDIO_DEFINITIONS_H
+#define STUDIO_DEFINITIONS_H 1
+// NOTE: no #pragma once otherwise Mac will not compile
+
+//==============================================================================
+// Definitions
+//==============================================================================
+
+// Copyright date (year only) used through out the Studio program; must be a quoted string.
+#define STUDIO_COPYRIGHT_YEAR "2017"
+
+#endif // STUDIO_DEFINITIONS_H
diff --git a/src/Authoring/Studio/Application/StudioInstance.cpp b/src/Authoring/Studio/Application/StudioInstance.cpp
new file mode 100644
index 00000000..177e82c0
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioInstance.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "StudioInstance.h"
+#include "StudioPreferences.h"
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+CProductInstance *CStudioInstance::GenerateProductInstance()
+{
+ CProductInstance *theRetVal = new CProductInstance("UIComposer Studio");
+ // CProductInstance* theClient = new CProductInstance( "Client" );
+
+ // theRetVal->AddProduct( "AKPluWAV.dll" );
+ // theRetVal->AddProduct( "AKPluIMG.dll" );
+ // theRetVal->AddProduct( "AKPlu3DS.dll" );
+ // This section will soon be a call into the client dll
+ /*
+ theClient->AddProduct( "AKCore.dll" );
+ theClient->AddProduct( "AKCorENU.dll" );
+ theClient->AddProduct( "AKProENU.dll" );
+ theRetVal->AddInstance( theClient );
+ */
+
+ long theMajorVersion = 0;
+ long theMinorVersion = 0;
+ long theIterationNumber = 0;
+ long theBuildNumber = 0;
+ Q3DStudio::CString theUnparsedNumber;
+ Q3DStudio::CString theStudioVersion = CStudioPreferences::GetVersionString();
+
+ int theIndex = theStudioVersion.Find('.');
+ if (theIndex != Q3DStudio::CString::ENDOFSTRING) {
+ theUnparsedNumber = theStudioVersion.Extract(0, theIndex);
+ theMajorVersion = atoi(theUnparsedNumber.GetCharStar());
+ theStudioVersion = theStudioVersion.Extract(theIndex + 1);
+ }
+
+ theIndex = theStudioVersion.Find('.');
+ if (theIndex != Q3DStudio::CString::ENDOFSTRING) {
+ theUnparsedNumber = theStudioVersion.Extract(0, theIndex);
+ theMinorVersion = atoi(theUnparsedNumber.GetCharStar());
+ theStudioVersion = theStudioVersion.Extract(theIndex + 1);
+ }
+
+ theIndex = theStudioVersion.Find('.');
+ if (theIndex != Q3DStudio::CString::ENDOFSTRING) {
+ theUnparsedNumber = theStudioVersion.Extract(0, theIndex);
+ theIterationNumber = atoi(theUnparsedNumber.GetCharStar());
+ theStudioVersion = theStudioVersion.Extract(theIndex + 1);
+ }
+
+ theBuildNumber = atoi(theStudioVersion.GetCharStar());
+
+ theRetVal->AddProduct("Studio.exe", theMajorVersion, theMinorVersion, theIterationNumber,
+ theBuildNumber);
+ return theRetVal;
+}
diff --git a/src/Authoring/Studio/Application/StudioInstance.h b/src/Authoring/Studio/Application/StudioInstance.h
new file mode 100644
index 00000000..d2df3e24
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioInstance.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_INSTANCE_H
+#define INCLUDED_STUDIO_INSTANCE_H 1
+
+#pragma once
+#include "ProductInstance.h"
+
+//==============================================================================
+/**
+ * @class CStudioInstance
+ * @brief Generates a product instance for studio.
+ * The product instance is essentially a set of modules and a name, and could have
+ * one or more product instances inside of it.
+ */
+class CStudioInstance
+{
+public:
+ static CProductInstance *GenerateProductInstance();
+};
+
+#endif // INCLUDED_STUDIO_INSTANCE_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Application/StudioTutorialWidget.cpp b/src/Authoring/Studio/Application/StudioTutorialWidget.cpp
new file mode 100644
index 00000000..d354d731
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioTutorialWidget.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "StudioTutorialWidget.h"
+#include "ui_StudioTutorialWidget.h"
+#include "StudioUtils.h"
+
+StudioTutorialWidget::StudioTutorialWidget(bool goToFileDialog) :
+ m_ui(new Ui::StudioTutorialWidget),
+ m_welcomeImages(0),
+ m_imgIter(0),
+ m_palette(0),
+ m_displayScale(1.0)
+{
+ m_ui->setupUi(this);
+
+ connect(m_ui->studioTutorialBack, &QPushButton::released, this,
+ &StudioTutorialWidget::handleBack);
+ connect(m_ui->studioTutorialForward, &QPushButton::released, this,
+ &StudioTutorialWidget::handleFwd);
+ connect(m_ui->studioTutorialShowAgain, &QCheckBox::stateChanged, this,
+ &StudioTutorialWidget::handleDoNotShowAgainChange);
+ connect(m_ui->studioTutorialNew, &QPushButton::released, this,
+ &StudioTutorialWidget::handleCreateNew);
+ connect(m_ui->studioTutorialOpen, &QPushButton::released, this,
+ &StudioTutorialWidget::handleOpenSample);
+
+ OnInitDialog(goToFileDialog);
+}
+
+StudioTutorialWidget::~StudioTutorialWidget()
+{
+ delete m_ui;
+ delete m_welcomeImages;
+ delete m_palette;
+}
+
+void StudioTutorialWidget::OnInitDialog(bool goToFileDialog)
+{
+ m_welcomeImages = new QList<QString>();
+
+ // populate welcome screen images
+ getImageList();
+ m_imgIter = m_welcomeImages->begin();
+
+ // do we go straight to last page with file dialog buttons?
+ int page = goToFileDialog ? m_welcomeImages->size() - 1 : 0;
+ // based on first PNG, get the scale that we need to fit welcome
+ // screen and buttons comfortably on display
+ m_displayScale = getDisplayScalingForImage(m_imgIter);
+
+ if (!m_welcomeImages->isEmpty()) {
+ for (int i = 0; i < page && m_imgIter != m_welcomeImages->end(); ++i)
+ m_imgIter++;
+
+ m_ui->studioTutorialShowAgain->setVisible(false);
+ if (*m_imgIter == m_welcomeImages->last() || m_imgIter == m_welcomeImages->end()) {
+ if (m_imgIter == m_welcomeImages->end())
+ m_imgIter--;
+ m_ui->studioTutorialForward->setVisible(false);
+ m_ui->studioTutorialOpen->setVisible(true);
+ m_ui->studioTutorialNew->setVisible(true);
+ } else {
+ if (m_imgIter == m_welcomeImages->begin()) {
+ m_ui->studioTutorialBack->setVisible(false);
+ m_ui->studioTutorialShowAgain->setVisible(true);
+ }
+ m_ui->studioTutorialOpen->setVisible(false);
+ m_ui->studioTutorialNew->setVisible(false);
+ }
+ }
+
+ QSettings settings;
+ m_ui->studioTutorialShowAgain->setChecked(!settings.value("showWelcomeScreen").toBool());
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+}
+
+void StudioTutorialWidget::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event)
+ if (m_palette)
+ return;
+
+ m_palette = new QPalette;
+ QPixmap pic = getScaledPic(m_imgIter);
+ m_palette->setBrush(QPalette::Window, pic);
+ setPalette(*m_palette);
+
+ // assume all welcome screen images are sized the same
+ resize(pic.size());
+ setFixedSize(size());
+}
+
+void StudioTutorialWidget::handleFwd()
+{
+ if (*m_imgIter != m_welcomeImages->last()) {
+ QPixmap pic = getNextScaledPic();
+ m_palette->setBrush(QPalette::Window, pic);
+ setPalette(*m_palette);
+
+ m_ui->studioTutorialBack->setVisible(true);
+ m_ui->studioTutorialShowAgain->setVisible(false);
+ }
+
+ if (*m_imgIter == m_welcomeImages->last()) {
+ m_ui->studioTutorialForward->setVisible(false);
+ m_ui->studioTutorialOpen->setVisible(true);
+ m_ui->studioTutorialNew->setVisible(true);
+ }
+}
+
+void StudioTutorialWidget::handleBack()
+{
+ if (*m_imgIter != m_welcomeImages->first()) {
+ QPixmap pic = getPrevScaledPic();
+ m_palette->setBrush(QPalette::Window, pic);
+ setPalette(*m_palette);
+
+ m_ui->studioTutorialForward->setVisible(true);
+ m_ui->studioTutorialShowAgain->setVisible(false);
+
+ m_ui->studioTutorialOpen->setVisible(false);
+ m_ui->studioTutorialNew->setVisible(false);
+ }
+
+ if (*m_imgIter == m_welcomeImages->first()) {
+ m_ui->studioTutorialBack->setVisible(false);
+ m_ui->studioTutorialShowAgain->setVisible(true);
+ }
+}
+
+void StudioTutorialWidget::handleDoNotShowAgainChange(int state)
+{
+ QSettings settings;
+ const bool show = !(state == Qt::Checked);
+ settings.setValue("showWelcomeScreen", show);
+}
+
+void StudioTutorialWidget::handleOpenSample()
+{
+ this->done(StudioTutorialWidget::openSampleResult);
+}
+
+void StudioTutorialWidget::handleCreateNew()
+{
+ this->done(StudioTutorialWidget::createNewResult);
+}
+
+void StudioTutorialWidget::getImageList()
+{
+ QDirIterator *it = new QDirIterator(":/res/Tutorial/screens/",
+ QDirIterator::NoIteratorFlags);
+
+ while (it->hasNext())
+ m_welcomeImages->append(it->next());
+}
+
+int StudioTutorialWidget::page() const
+{
+ int i = 0;
+ QList<QString>::iterator iter = m_welcomeImages->begin();
+ while (iter != m_imgIter) { ++i; iter++; }
+ return i;
+}
+
+QPixmap StudioTutorialWidget::getNextScaledPic()
+{
+ return getScaledPic(++m_imgIter);
+}
+
+QPixmap StudioTutorialWidget::getPrevScaledPic()
+{
+ return getScaledPic(--m_imgIter);
+}
+
+QPixmap StudioTutorialWidget::getScaledPic(QList<QString>::iterator iter)
+{
+ QPixmap picOrig = QPixmap(*iter);
+ QPixmap pic = picOrig.scaledToHeight(m_displayScale * picOrig.height(),
+ Qt::SmoothTransformation);
+
+ pic.setDevicePixelRatio(devicePixelRatio());
+ return pic;
+}
+
+qreal StudioTutorialWidget::getDisplayScalingForImage(QList<QString>::iterator iter)
+{
+ QPixmap picOrig = QPixmap(*iter);
+
+ // Set the splash screen to 80% of display size.
+ // Note that high DPI scaling has an effect on the display
+ // resolution returned by GetAvailableDisplaySize().
+ // DPI scaling factor is integer and taken from the primary screen.
+ // When running studio on secondary monitor with different DPI,
+ // or running it on primary with non-integer scaling, we might
+ // get different dialog size than intended.
+ QSize displaySize = GetAvailableDisplaySize(getWidgetScreen(this)) * 0.8;
+
+ // scale down if images do not fit on screen, otherwise use
+ // 1:1 PNGs to avoid scaling artifacts
+ if (picOrig.height() > displaySize.height() ||
+ picOrig.width() > displaySize.width()) {
+ QSize picScaledSize = picOrig.size();
+ picScaledSize.scale(displaySize, Qt::KeepAspectRatio);
+ m_displayScale = qMin((qreal)picScaledSize.height() / (qreal)picOrig.height(),
+ (qreal)picScaledSize.width() / (qreal)picOrig.width());
+ return m_displayScale;
+ } else {
+ return 1.0;
+ }
+}
diff --git a/src/Authoring/Studio/Application/StudioTutorialWidget.h b/src/Authoring/Studio/Application/StudioTutorialWidget.h
new file mode 100644
index 00000000..3fa69489
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioTutorialWidget.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef STUDIOTUTORIALWIDGET_H
+#define STUDIOTUTORIALWIDGET_H
+
+#include <QtCore/qdiriterator.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qsettings.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qpalette.h>
+#include <QtWidgets/qdialog.h>
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class StudioTutorialWidget;
+}
+QT_END_NAMESPACE
+
+class StudioTutorialWidget : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit StudioTutorialWidget(bool goToFileDialog);
+
+ ~StudioTutorialWidget();
+
+ enum result {
+ acceptResult = QDialog::Accepted,
+ rejectResult = QDialog::Rejected,
+ openSampleResult,
+ createNewResult
+ };
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+ void OnInitDialog(bool goToFileDialog);
+
+public:
+ void handleFwd();
+ void handleBack();
+ void handleDoNotShowAgainChange(int state);
+ void handleOpenSample();
+ void handleCreateNew();
+ int page() const;
+
+private:
+ Ui::StudioTutorialWidget *m_ui;
+
+ QList<QString> *m_welcomeImages;
+ QList<QString>::iterator m_imgIter;
+
+ QPalette *m_palette;
+
+ qreal m_displayScale;
+
+ void getImageList();
+
+ QPixmap getScaledPic(QList<QString>::iterator iter);
+ QPixmap getPrevScaledPic();
+ QPixmap getNextScaledPic();
+ qreal getDisplayScalingForImage(QList<QString>::iterator iter);
+};
+
+#endif // STUDIOTUTORIALWIDGET_H
diff --git a/src/Authoring/Studio/Application/StudioTutorialWidget.ui b/src/Authoring/Studio/Application/StudioTutorialWidget.ui
new file mode 100644
index 00000000..cb83a5ce
--- /dev/null
+++ b/src/Authoring/Studio/Application/StudioTutorialWidget.ui
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioTutorialWidget</class>
+ <widget class="QDialog" name="StudioTutorialWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1440</width>
+ <height>900</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Welcome to Qt 3D Studio</string>
+ </property>
+ <property name="accessibleName">
+ <string>StudioTutorialWidget</string>
+ </property>
+ <widget class="QCheckBox" name="studioTutorialShowAgain">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>701</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="accessibleName">
+ <string>studioTutorialShowAgain</string>
+ </property>
+ <property name="text">
+ <string>Do Not Show This Again</string>
+ </property>
+ </widget>
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>820</y>
+ <width>1421</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="bottomBar">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="buttons">
+ <item>
+ <widget class="QPushButton" name="studioTutorialOpen">
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="accessibleName">
+ <string>studioTutorialOpen</string>
+ </property>
+ <property name="text">
+ <string>Open Sample Project</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="studioTutorialNew">
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="accessibleName">
+ <string>studioTutorialNew</string>
+ </property>
+ <property name="text">
+ <string>Create New</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="horizontalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>40</y>
+ <width>1441</width>
+ <height>51</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="topBar">
+ <item>
+ <widget class="QPushButton" name="studioTutorialBack">
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>90</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="accessibleName">
+ <string>studioTutorialBack</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../qt3dstudio.qrc">
+ <normaloff>:/res/Tutorial/button_back.png</normaloff>:/res/Tutorial/button_back.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>39</width>
+ <height>39</height>
+ </size>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="studioTutorialForward">
+ <property name="maximumSize">
+ <size>
+ <width>90</width>
+ <height>90</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="accessibleName">
+ <string>StudioTutorialWidget</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../qt3dstudio.qrc">
+ <normaloff>:/res/Tutorial/button_next.png</normaloff>:/res/Tutorial/button_next.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>39</width>
+ <height>39</height>
+ </size>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources>
+ <include location="../qt3dstudio.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/Controls/BaseMeasure.cpp b/src/Authoring/Studio/Controls/BaseMeasure.cpp
new file mode 100644
index 00000000..25d5c204
--- /dev/null
+++ b/src/Authoring/Studio/Controls/BaseMeasure.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "BaseMeasure.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Create a new measure.
+ * @param inRatio the current ratio.
+ * @param inFillBackground true if the background of this control is to be drawn.
+ */
+CBaseMeasure::CBaseMeasure(double inRatio, bool inFillBackground /*= true */)
+ : m_SmallHashInterval(0)
+ , m_MediumHashInterval(0)
+ , m_LargeHashInterval(0)
+ , m_Ratio(inRatio)
+ , m_Offset(0)
+ , m_EdgeMargin(0)
+ , m_LargeHashOffset(0)
+ , m_MediumHashOffset(6)
+ , m_SmallHashOffset(3)
+ , m_FillBackground(inFillBackground)
+{
+ m_BackgroundColor = CStudioPreferences::GetBaseColor();
+}
+
+CBaseMeasure::~CBaseMeasure()
+{
+}
+
+//=============================================================================
+/**
+ * Overrides the control to set up clipping rects.
+ * @param inRenderer the renderer to be rendered to.
+ * @param inDirtyRect the resulting dirty rect.
+ * @param inIgnoreValidation true if everything needs to be drawn.
+ */
+void CBaseMeasure::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation)
+{
+ inRenderer->PushClippingRect(CRct(GetSize()));
+
+ CControl::OnDraw(inRenderer, inDirtyRect, inIgnoreValidation);
+
+ inRenderer->PopClippingRect();
+}
+
+//=============================================================================
+/**
+ * Draw the measure.
+ * @param inRenderer the renderer to draw to.
+ */
+void CBaseMeasure::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+
+ if (m_FillBackground)
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+
+ long theLength = GetDisplayLength();
+ long theHeight = GetDisplayHeight();
+
+ double theTotalMeasure = theLength / m_Ratio;
+ long thePos;
+
+ long theNumLargeHashes = (long)(theTotalMeasure / m_LargeHashInterval) + 1;
+
+ inRenderer->PushPen(CStudioPreferences::GetRulerTickColor());
+
+ long theOffset = m_Offset - (m_Offset % ::dtol(m_LargeHashInterval));
+
+ for (long i = 0; i < theNumLargeHashes + 1; ++i) {
+ double theMeasure = m_LargeHashInterval * i + theOffset;
+
+ thePos = CalculatePos(theMeasure - m_Offset);
+
+ if (thePos > 0)
+ DrawLine(inRenderer, thePos, theHeight, theHeight - m_LargeHashOffset);
+
+ DrawMeasureText(inRenderer, thePos, long(theMeasure));
+
+ // sanity check
+ if (m_MediumHashInterval > 0) {
+ // in cases where the medium and small hashes must be filled up to the right of the
+ // first Large hash
+ if (m_Offset < 0 && i == 0) {
+ thePos = CalculatePos(theMeasure - m_Offset - m_MediumHashInterval);
+ if (thePos > 0)
+ DrawLine(inRenderer, thePos, theHeight, theHeight - m_MediumHashOffset);
+
+ for (double theSmallInterval = 0; theSmallInterval < m_LargeHashInterval;
+ theSmallInterval += m_SmallHashInterval) {
+ thePos = CalculatePos(theMeasure - m_Offset - theSmallInterval);
+ if (thePos > 0)
+ DrawLine(inRenderer, thePos, theHeight, theHeight - m_SmallHashOffset);
+ }
+ }
+
+ thePos = CalculatePos(theMeasure - m_Offset + m_MediumHashInterval);
+ if (thePos > 0)
+ DrawLine(inRenderer, thePos, theHeight, theHeight - m_MediumHashOffset);
+
+ for (double theSmallInterval = 0; theSmallInterval < m_LargeHashInterval;
+ theSmallInterval += m_SmallHashInterval) {
+ thePos = CalculatePos(theMeasure - m_Offset + theSmallInterval);
+
+ if (thePos > 0)
+ DrawLine(inRenderer, thePos, theHeight, theHeight - m_SmallHashOffset);
+ }
+ } // if medium is valid
+ }
+ // Draws the top outline
+ DrawOutline(inRenderer, theHeight, 0, theLength);
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ // Draws the bottom outline
+ DrawOutline(inRenderer, theHeight + 1, 0, theLength);
+ inRenderer->PopPen();
+
+ // Dark line at left and right ends of the measure
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ DrawLine(inRenderer, theRect.size.x - 1, 0, theRect.size.y - 1);
+
+ // Dark line across the top of the measure
+ DrawOutline(inRenderer, 0, 0, theRect.size.x - 1);
+ inRenderer->PopPen();
+
+ // pop for the first PushPen
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Return the display length, by default, this is horizontal and returns the x
+ */
+long CBaseMeasure::GetDisplayLength()
+{
+ return GetSize().x;
+}
+
+//=============================================================================
+/**
+ * Return the display height, by default, this is horizontal and returns the y
+ */
+long CBaseMeasure::GetDisplayHeight()
+{
+ return GetSize().y - m_EdgeMargin;
+}
+
+//=============================================================================
+/**
+ * By default, this draws a vertical line.
+ * A subclass can override this and draw a horizontal one, if its orientation requires so.
+ * @parma inRenderer the renderer
+ * @param inPos the position that in the x-coordinate
+ * @param inStart start position of the line
+ * @param inEnd end position of the line
+ */
+void CBaseMeasure::DrawLine(CRenderer *inRenderer, long inPos, long inStart, long inEnd)
+{
+ inRenderer->MoveTo(CPt(inPos, inStart));
+ inRenderer->LineTo(CPt(inPos, inEnd));
+}
+
+//=============================================================================
+/**
+ * This draws a horizontal outline
+ * A subclass can override this and draw a vertical one, if its orientation requires so.
+ * @parma inRenderer the renderer
+ * @param inPos the position that in the x-coordinate
+ * @param inStart start position of the line
+ * @param inEnd end position of the line
+ */
+void CBaseMeasure::DrawOutline(CRenderer *inRenderer, long inPos, long inStart, long inEnd)
+{
+ inRenderer->MoveTo(CPt(inStart, inPos));
+ inRenderer->LineTo(CPt(inEnd, inPos));
+}
diff --git a/src/Authoring/Studio/Controls/BaseMeasure.h b/src/Authoring/Studio/Controls/BaseMeasure.h
new file mode 100644
index 00000000..25916198
--- /dev/null
+++ b/src/Authoring/Studio/Controls/BaseMeasure.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BASE_MEASURE_H
+#define INCLUDED_BASE_MEASURE_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+#include "CoreUtils.h"
+#include <vector>
+
+class CBaseMarker;
+class CSnapper;
+
+class CBaseMeasure : public CControl
+{
+public:
+ CBaseMeasure(double inRatio, bool inFillBackground = true);
+ virtual ~CBaseMeasure();
+
+ virtual void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation = false);
+
+ virtual void Draw(CRenderer *inRenderer);
+
+ // inline these
+ long GetLargeHashInterval() const { return ::dtol(m_LargeHashInterval); }
+ long GetMediumHashInterval() const { return ::dtol(m_MediumHashInterval); }
+ long GetSmallHashInterval() const { return ::dtol(m_SmallHashInterval); }
+
+protected:
+ virtual void DrawMeasureText(CRenderer *inRenderer, long inPosition, long inMeasure) = 0;
+ virtual long CalculatePos(double inNewValue) = 0;
+ virtual long GetDisplayLength();
+ virtual long GetDisplayHeight();
+ virtual void DrawLine(CRenderer *inRenderer, long inPos, long inStart, long inEnd);
+ virtual void DrawOutline(CRenderer *inRenderer, long inPos, long inStart, long inEnd);
+
+ double m_SmallHashInterval; ///< the measurement represented by a small hash
+ double m_MediumHashInterval; ///< the measurement represented by a medium hash
+ double m_LargeHashInterval; ///< the measurement represented by a large hash
+ double m_Ratio; ///< Ratio that is used to calculate the size of the large hash
+ long m_Offset; ///< Offset of the point 0 from left or top
+ ::CColor m_BackgroundColor; ///< Background of this control
+
+ // Tickmarks
+ long m_EdgeMargin; ///< Margin from the edge, so that no line draws all the way through
+ long m_LargeHashOffset; ///< Offset from the margin for the large hash
+ long m_MediumHashOffset; ///< Offset from the margin for the medium hash
+ long m_SmallHashOffset; ///< Offset from the margin for the small hash
+
+ bool m_FillBackground; ///< true to fill the background (i.e. its not transparent)
+};
+#endif // INCLUDED_BASE_MEASURE_H
diff --git a/src/Authoring/Studio/Controls/BlankControl.cpp b/src/Authoring/Studio/Controls/BlankControl.cpp
new file mode 100644
index 00000000..492bc630
--- /dev/null
+++ b/src/Authoring/Studio/Controls/BlankControl.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BlankControl.h"
+#include "Renderer.h"
+#include "SystemPreferences.h"
+
+//=============================================================================
+/**
+ * constructor
+ */
+CBlankControl::CBlankControl(CColor inColor)
+ : m_DrawBorder(false)
+ , m_FillBackground(true)
+{
+ SetColor(inColor);
+}
+
+//=============================================================================
+/**
+ * destructor
+ */
+CBlankControl::~CBlankControl()
+{
+}
+
+//=============================================================================
+/**
+ * Draws this control
+ */
+void CBlankControl::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+
+ if (m_FillBackground)
+ inRenderer->FillSolidRect(theRect, m_Color);
+
+ if (m_DrawBorder) {
+ // Get the normal colors for the 3D border
+ CColor theShadowColor = CStudioPreferences::GetButtonShadowColor();
+ CColor theHiliteColor = CStudioPreferences::GetButtonHighlightColor();
+
+ // Draw a frame around the button
+ inRenderer->Draw3dRect(
+ CRct(theRect.position.x + 1, theRect.position.y, theRect.size.x, theRect.size.y),
+ theHiliteColor, theShadowColor);
+ inRenderer->PushPen(theShadowColor);
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theRect.size.y));
+ inRenderer->PopPen();
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the color for this control
+ */
+void CBlankControl::SetColor(CColor inColor)
+{
+ if (m_Color == inColor)
+ return;
+
+ m_Color = inColor;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * @param inDrawBorder true if we should draw the border
+ */
+void CBlankControl::SetDrawBorder(bool inDrawBorder)
+{
+ m_DrawBorder = inDrawBorder;
+}
+
+//=============================================================================
+/**
+ * @param inFillBackground true if we should draw the background
+ */
+void CBlankControl::SetFillBackground(bool inFillBackground)
+{
+ m_FillBackground = inFillBackground;
+}
diff --git a/src/Authoring/Studio/Controls/BlankControl.h b/src/Authoring/Studio/Controls/BlankControl.h
new file mode 100644
index 00000000..b04337b0
--- /dev/null
+++ b/src/Authoring/Studio/Controls/BlankControl.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BLANKCONTROL_H
+#define INCLUDED_BLANKCONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "StudioPreferences.h"
+
+class CBlankControl : public CControl
+{
+public:
+ CBlankControl(::CColor inColor = CStudioPreferences::GetBaseColor());
+ virtual ~CBlankControl();
+ void Draw(CRenderer *inRenderer) override;
+ void SetColor(::CColor inColor);
+ void SetDrawBorder(bool inDrawBorder);
+ void SetFillBackground(bool inFillBackground);
+
+protected:
+ ::CColor m_Color;
+ bool m_DrawBorder;
+ bool m_FillBackground;
+};
+
+#endif // INCLUDED_BLANKCONTROL_H
diff --git a/src/Authoring/Studio/Controls/BreadCrumbControl.cpp b/src/Authoring/Studio/Controls/BreadCrumbControl.cpp
new file mode 100644
index 00000000..5ccae438
--- /dev/null
+++ b/src/Authoring/Studio/Controls/BreadCrumbControl.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BreadCrumbControl.h"
+#include "StudioPreferences.h"
+#include "IBreadCrumbProvider.h"
+//#include "Cmd.h"
+#include <boost/bind.hpp>
+
+#include <QPixmap>
+
+IMPLEMENT_OBJECT_COUNTER(CBreadCrumbControl)
+
+//==============================================================================
+// Internal Classes
+//==============================================================================
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CBreadCrumbControl::CBreadCrumbControl()
+ : m_BreadCrumbProvider(nullptr)
+{
+ ADDTO_OBJECT_COUNTER(CBreadCrumbControl)
+
+ SetName("BreadCrumbControl");
+ SetAutoMin(false);
+ SetFlowDirection(FLOW_HORIZONTAL);
+ SetAlignment(ALIGN_TOP, ALIGN_LEFT);
+ SetTopMargin(0);
+ SetBottomMargin(0);
+ SetLeftMargin(0);
+ SetRightMargin(0);
+ SetGapBetweenChildren(0);
+
+ long theHeaderHeight = CStudioPreferences::GetHeaderHeight();
+ SetMaximumSize(CPt(LONG_MAX, theHeaderHeight));
+ SetMinimumSize(CPt(0, theHeaderHeight));
+ SetSize(CPt(LONG_MAX, theHeaderHeight));
+ SetPosition(CPt(0, 0));
+}
+
+//=============================================================================
+/**
+ * destructor
+ */
+CBreadCrumbControl::~CBreadCrumbControl()
+{
+ RemoveAllButtons();
+ REMOVEFROM_OBJECT_COUNTER(CBreadCrumbControl)
+}
+
+//=============================================================================
+/**
+ * Helper class to create the colon separator button
+ */
+static inline CBreadCrumbControl::TSeparatorButtonType *CreateSeparatorButton(const QPixmap &inImage)
+{
+ CBreadCrumbControl::TSeparatorButtonType *theButton =
+ new CBreadCrumbControl::TSeparatorButtonType;
+ theButton->SetAutoSize(true);
+ theButton->SetUpImage(inImage);
+ theButton->SetSize(CPt(12, 21));
+ theButton->SetMinimumSize(CPt(12, 21));
+ theButton->SetMaximumSize(CPt(12, 21));
+ return theButton;
+}
+
+//=============================================================================
+/**
+ * Helper function to create a new button to be placed on the breadcrumb bar
+ * @param inButtonName Name of the button to be displayed and stored
+ * inImageName The specific .png file to load in for the button
+ * @return TButtonType returns the newly created button
+ */
+static inline CBreadCrumbControl::TButtonType *CreateButton(const QPixmap &inImage)
+{
+ CBreadCrumbControl::TButtonType *theButton = new CBreadCrumbControl::TButtonType();
+ theButton->SetAutoSize(true);
+ theButton->SetUpImage(inImage);
+ CBreadCrumbControl::TButtonType::SBorderOptions theBorderOptions(false, false, false, false);
+ theButton->SetBorderVisibilityAll(theBorderOptions);
+ theButton->SetFillStyleUp(CBreadCrumbControl::TButtonType::EFILLSTYLE_FLOOD);
+ theButton->SetFillStyleOver(CBreadCrumbControl::TButtonType::EFILLSTYLE_FLOOD);
+ theButton->SetFillColorUp(CStudioPreferences::GetBaseColor());
+ theButton->SetFillColorDown(CStudioPreferences::GetBaseColor());
+ theButton->SetFillColorOver(CStudioPreferences::GetMouseOverHighlightColor());
+ theButton->SetMinimumSize(CPt(16, 21));
+ theButton->SetMaximumSize(CPt(125, 21));
+ return theButton;
+}
+
+//=============================================================================
+/**
+ * Generate/Reset the text appearing on the breadcrumb which is currently
+ * appending the slide name as well.
+ * @param inBreadCrumb containing color/text info for display
+ * @param inButton The button to be modified
+ */
+void CBreadCrumbControl::GenerateButtonText(const SBreadCrumb &inBreadCrumb, TButtonType *inButton)
+{
+ Q3DStudio::CString theDisplayName(Q3DStudio::CString::fromQString(inBreadCrumb.m_String));
+ inButton->SetTextColorUp(CStudioPreferences::GetNormalColor());
+ inButton->SetTextColorDown(CStudioPreferences::GetNormalColor());
+ inButton->SetText(theDisplayName);
+ inButton->SetTooltipText(theDisplayName);
+ inButton->SetName(theDisplayName);
+}
+
+//=============================================================================
+/**
+ * Draws this control
+ */
+void CBreadCrumbControl::Draw(CRenderer *inRenderer)
+{
+ const auto size = GetSize();
+
+ // Fill in the background
+ inRenderer->FillSolidRect(QRect(0, 0, size.x, size.y), CStudioPreferences::GetBaseColor());
+
+ // Outline the control
+ CColor theOutlineColor = CStudioPreferences::GetButtonShadowColor();
+ inRenderer->DrawRectOutline(QRect(0, 0, size.x, size.y -1), theOutlineColor, theOutlineColor,
+ theOutlineColor, theOutlineColor);
+
+ // Draw the highlight at the bottom
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(QPoint(0, size.y - 1));
+ inRenderer->LineTo(QPoint(size.x - 1, size.y - 1));
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Update the entire bread crumb trail. This will 'reuse' created controls, creating more if
+ *trail is longer than previous, and deleting extra if shorter.
+ */
+void CBreadCrumbControl::RefreshTrail(IBreadCrumbProvider *inBreadCrumbProvider)
+{
+ bool theChangedProvider = m_BreadCrumbProvider != inBreadCrumbProvider;
+ if (theChangedProvider && m_BreadCrumbProvider)
+ m_BreadCrumbProvider->SigBreadCrumbUpdate.disconnect(boost::bind(&CBreadCrumbControl::OnUpdateBreadCrumb, this));
+
+ m_BreadCrumbProvider = inBreadCrumbProvider;
+
+ SuspendRecalcLayout(true);
+ size_t theIndex = 0;
+
+ if (m_BreadCrumbProvider) {
+ // listen for single breadcrumb update (i.e. name changes)
+ if (theChangedProvider)
+ m_BreadCrumbProvider->SigBreadCrumbUpdate.connect(boost::bind(&CBreadCrumbControl::OnUpdateBreadCrumb, this));
+
+ const IBreadCrumbProvider::TTrailList &theList = m_BreadCrumbProvider->GetTrail();
+ // By design, if this is only 1 item in the list, nothing is shown.
+ if (theList.size() > 1) {
+ for (; theIndex < theList.size(); ++theIndex) {
+ TButtonType *theButton = nullptr;
+ if (theIndex < m_BreadCrumbList.size())
+ theButton = m_BreadCrumbList[theIndex].m_BreadCrumb;
+ else // create new
+ {
+ theButton =
+ CreateButton((theIndex == 0) ? m_BreadCrumbProvider->GetRootImage()
+ : m_BreadCrumbProvider->GetBreadCrumbImage());
+ theButton->SigToggle.connect(boost::bind(&CBreadCrumbControl::OnButtonToggled, this, _1, _2));
+
+ TSeparatorButtonType *theSeparator =
+ CreateSeparatorButton(m_BreadCrumbProvider->GetSeparatorImage());
+
+ // the ":" is always added as a pair
+ m_BreadCrumbList.push_back(SBreadCrumbItem(theButton, theSeparator));
+ AddChild(theButton);
+ AddChild(theSeparator);
+ }
+ // Update text and color
+ GenerateButtonText(theList[theIndex], theButton);
+
+ // Refresh all properties that might be outdated since buttons are reused
+ QPixmap theImage;
+ bool theEnabled = true;
+ if (theIndex
+ == theList.size()
+ - 1) { // The last button is displayed differently (grayed-out)
+ theButton->SetTextColorUp(CColor(94, 91, 85));
+ theButton->SetTextColorDown(CColor(94, 91, 85));
+ theImage = m_BreadCrumbProvider->GetActiveBreadCrumbImage();
+
+ theEnabled = false; // the last item being the 'active' is disabled.
+ } else if (theIndex > 0)
+ theImage = m_BreadCrumbProvider->GetBreadCrumbImage();
+
+ if (!theImage.isNull())
+ theButton->SetUpImage(theImage);
+
+ theButton->SetToggleState(!theEnabled);
+ theButton->SetEnabled(theEnabled);
+ // the separator is hidden for the last one
+ m_BreadCrumbList[theIndex].m_Separator->SetVisible(theEnabled);
+
+ theButton->Invalidate();
+ }
+ }
+ }
+ // Discard 'extras' OR if this is no provider, this will remove all breadcrumbs
+ while (m_BreadCrumbList.size() > theIndex) {
+ RemoveButton(m_BreadCrumbList.back());
+ m_BreadCrumbList.pop_back();
+ }
+ SuspendRecalcLayout(false);
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Check for changes in the existing list and update.
+ */
+void CBreadCrumbControl::OnUpdateBreadCrumb()
+{
+ ASSERT(m_BreadCrumbProvider);
+ bool theUpdated = false;
+
+ const IBreadCrumbProvider::TTrailList &theList = m_BreadCrumbProvider->GetTrail(false);
+ ASSERT(m_BreadCrumbList.size() == theList.size()
+ || (m_BreadCrumbList.size() == 0
+ && theList.size()
+ == 1)); // By design, if this is only 1 item in the list, nothing is shown.
+
+ for (size_t theIndex = 0; theIndex < m_BreadCrumbList.size(); ++theIndex) {
+ TButtonType *theButton = m_BreadCrumbList[theIndex].m_BreadCrumb;
+ if (theButton->GetText().toQString() != theList[theIndex].m_String
+ || theButton->GetTextColorUp().getQColor() != theList[theIndex].m_Color) {
+ GenerateButtonText(theList[theIndex], theButton);
+ theUpdated = true;
+ }
+ }
+
+ if (theUpdated) // Make sure that this entire BreadCrumbControl has room for extraneous length
+ // buttons
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Removes and clean up button
+ */
+void CBreadCrumbControl::RemoveButton(SBreadCrumbItem &inBreadCrumb)
+{
+ inBreadCrumb.m_BreadCrumb->SigToggle.disconnect(boost::bind(&CBreadCrumbControl::OnButtonToggled, this, _1, _2));
+ RemoveChild(inBreadCrumb.m_BreadCrumb);
+ RemoveChild(inBreadCrumb.m_Separator);
+ delete inBreadCrumb.m_BreadCrumb;
+ delete inBreadCrumb.m_Separator;
+}
+
+//=============================================================================
+/**
+ * Removes all buttons (trail and separators)
+ */
+void CBreadCrumbControl::RemoveAllButtons()
+{
+ while (!m_BreadCrumbList.empty()) {
+ RemoveButton(m_BreadCrumbList.back());
+ m_BreadCrumbList.pop_back();
+ }
+}
+
+//=============================================================================
+/**
+ * Handles turning a filter on or off in response to a button being pressed.
+ * @param inButton button that generated the event
+ * @param inState new state of the button after being toggled
+ */
+void CBreadCrumbControl::OnButtonToggled(CToggleButton *inButton,
+ CButtonControl::EButtonState inState)
+{
+ Q_UNUSED(inState);
+
+ ASSERT(m_BreadCrumbProvider);
+
+ // Find the index into the trail list
+ size_t theIndex = 0;
+ for (; theIndex < m_BreadCrumbList.size(); ++theIndex) {
+ if (m_BreadCrumbList[theIndex].m_BreadCrumb == inButton)
+ break;
+ }
+ ASSERT(theIndex < m_BreadCrumbList.size()); // sanity check
+
+ m_BreadCrumbProvider->OnBreadCrumbClicked((long)theIndex);
+}
diff --git a/src/Authoring/Studio/Controls/BreadCrumbControl.h b/src/Authoring/Studio/Controls/BreadCrumbControl.h
new file mode 100644
index 00000000..c8fc519a
--- /dev/null
+++ b/src/Authoring/Studio/Controls/BreadCrumbControl.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2004 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BREADCRUMBCONTROL_H
+#define INCLUDED_BREADCRUMBCONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FlowLayout.h"
+#include "ProceduralButton.h"
+#include "ToggleButton.h"
+#include "TextButton.h"
+#include "IBreadCrumbProvider.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IDoc;
+class CRenderer;
+
+class CBreadCrumbControl : public CFlowLayout
+{
+public:
+ typedef CProceduralButton<CTextButton<CToggleButton>> TButtonType;
+ typedef CTextButton<CButtonControl> TSeparatorButtonType;
+ struct SBreadCrumbItem
+ {
+ TButtonType *m_BreadCrumb;
+ TSeparatorButtonType *m_Separator;
+
+ SBreadCrumbItem(TButtonType *inBreadCrumb, TSeparatorButtonType *inSeparator)
+ {
+ m_BreadCrumb = inBreadCrumb;
+ m_Separator = inSeparator;
+ }
+ };
+ typedef std::vector<SBreadCrumbItem> TBreadCrumbList;
+
+ // Construction
+public:
+ CBreadCrumbControl();
+ virtual ~CBreadCrumbControl();
+
+ DEFINE_OBJECT_COUNTER(CBreadCrumbControl)
+
+ // CControl
+public:
+ virtual void Draw(CRenderer *inRenderer);
+
+ void RefreshTrail(IBreadCrumbProvider *inBreadCrumbProvider);
+ void OnUpdateBreadCrumb();
+
+ // Implementation
+protected:
+ void GenerateButtonText(const SBreadCrumb &inBreadCrumb, TButtonType *inButton);
+ void OnButtonToggled(CToggleButton *inButton, CButtonControl::EButtonState inState);
+ void RemoveButton(SBreadCrumbItem &inBreadCrumb);
+ void RemoveAllButtons();
+
+protected:
+ IBreadCrumbProvider *m_BreadCrumbProvider;
+ TBreadCrumbList m_BreadCrumbList;
+};
+
+#endif // INCLUDED_BREADCRUMBCONTROL_H
diff --git a/src/Authoring/Studio/Controls/ButtonControl.cpp b/src/Authoring/Studio/Controls/ButtonControl.cpp
new file mode 100644
index 00000000..c242915a
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ButtonControl.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ButtonControl.h"
+#include "Renderer.h"
+#include "ResourceCache.h"
+
+//=============================================================================
+/**
+ * Constructor
+ *
+ * @param inToggleButton true if this is suppose to be a toggle button. Toggle
+ * buttons stay pressed when clicked on and have to be clicked again in order
+ * to release. Normal buttons return to the up state when the button is released.
+ */
+CButtonControl::CButtonControl()
+ : m_State(EBUTTONSTATE_UP)
+ , m_AutoSize(true)
+ , m_MouseEnter(true)
+ , m_IsMouseDown(false)
+ , m_VCenterImage(false)
+ , m_HCenterImage(false)
+ , m_Margin(0)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CButtonControl::~CButtonControl()
+{
+}
+
+//=============================================================================
+/**
+ * Returns the current state of the button. A button can be "up", "down", or
+ * "indeterminate". The up state is the normal state of the button. The down
+ * state is when the mouse is pressing the button. The indeterminate state is
+ * provided for subclasses and not used here.
+ * @return the button's current state
+ */
+CButtonControl::EButtonState CButtonControl::GetButtonState() const
+{
+ return m_State;
+}
+
+//=============================================================================
+/**
+ * Sets the current state of the button. No listeners are notified.
+ * @param inState new state of the button
+ */
+void CButtonControl::SetButtonState(EButtonState inState)
+{
+ if (m_State == inState)
+ return;
+
+ m_State = inState;
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button is in the up state. A button is "up"
+ * if it is not disabled, not depressed, and the mouse is not over it.
+ * @param inImage image to be loaded when this button is up
+ */
+void CButtonControl::SetUpImage(const QPixmap &inImage)
+{
+ m_ImageUp = inImage;
+ Resize();
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button is in the up state. A button is "up"
+ * if it is not disabled, not depressed, and the mouse is not over it.
+ * @param inImageName name of the image to be loaded when this button is up
+ */
+void CButtonControl::SetUpImage(const QString &inImageName)
+{
+ QPixmap theImage ;
+ if (!inImageName.isEmpty())
+ theImage = CResourceCache::GetInstance()->GetBitmap(inImageName);
+ SetUpImage(theImage);
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button is in the down state.
+ * @param inImage image to be loaded when this button is down
+ */
+void CButtonControl::SetDownImage(const QPixmap &inImage)
+{
+ m_ImageDown = inImage;
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button is in the down state.
+ * @param inImageName name of the image to be loaded when this button is down
+ */
+void CButtonControl::SetDownImage(const QString &inImageName)
+{
+ QPixmap theImage;
+ if (!inImageName.isEmpty())
+ theImage = CResourceCache::GetInstance()->GetBitmap(inImageName);
+ SetDownImage(theImage);
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button the mouse is over the button. To
+ * leave the button displaying the "up" state, pass NULL to this function.
+ * @param inImage image to be loaded when the mouse is over this button
+ */
+void CButtonControl::SetOverImage(const QPixmap &inImage)
+{
+ m_ImageOver = inImage;
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button the mouse is over the button. To
+ * leave the button displaying the "up" state, pass an empty string to this function.
+ * @param inImageName name of the image to be loaded when the mouse is over this button
+ */
+void CButtonControl::SetOverImage(const QString &inImageName)
+{
+ QPixmap theImage;
+ if (!inImageName.isEmpty())
+ theImage = CResourceCache::GetInstance()->GetBitmap(inImageName);
+ SetOverImage(theImage);
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button is disabled, when the button is in a DOWN state
+ * @param inImage image to be loaded when this button is disabled
+ */
+void CButtonControl::SetDisabledImage(const QPixmap &inImage)
+{
+ m_ImageDownDisabled = inImage;
+}
+
+//=============================================================================
+/**
+ * Sets the image to use when this button is in the disabled state.
+ * @param inImageName name of the image to be loaded when this button is disabled
+ */
+void CButtonControl::SetDisabledImage(const QString &inImageName)
+{
+ QPixmap theImage;
+ if (!inImageName.isEmpty())
+ theImage = CResourceCache::GetInstance()->GetBitmap(inImageName);
+ SetDisabledImage(theImage);
+}
+
+//=============================================================================
+/**
+ * In cases, where there is a different (disabled) image for button UP state
+ */
+void CButtonControl::SetUpDisabledImage(const QString &inImageName)
+{
+ if (!inImageName.isEmpty())
+ m_ImageUpDisabled = CResourceCache::GetInstance()->GetBitmap(inImageName);
+}
+
+//=============================================================================
+/**
+ * Allows you to enable or disable auto sizing for this button. Auto sizing
+ * causes the button's size to change whenever the "Up" image is changed for
+ * this button. Button size does NOT change as the button state changes.
+ * @return true if this button is currently in Auto Size mode
+ */
+void CButtonControl::SetAutoSize(bool inEnableAutoSize)
+{
+ m_AutoSize = inEnableAutoSize;
+ Resize();
+}
+
+//=============================================================================
+/**
+ * Determines if this button will auto size or not. Auto sizing causes the
+ * button's size to change whenever the "Up" image is changed for this button.
+ * Button size does NOT change as the button state changes.
+ * @return true if this button is currently in Auto Size mode
+ */
+bool CButtonControl::GetAutoSize()
+{
+ return m_AutoSize;
+}
+
+void CButtonControl::SetCenterImage(bool inVCenter, bool inHCenter)
+{
+ if (m_VCenterImage == inVCenter && m_HCenterImage == inHCenter)
+ return;
+ m_VCenterImage = inVCenter;
+ m_HCenterImage = inHCenter;
+ Invalidate();
+}
+
+void CButtonControl::SetMarginImage(long inMargin)
+{
+ m_Margin = inMargin;
+}
+
+//=============================================================================
+/**
+ * Draws the button based on the current state
+ */
+void CButtonControl::Draw(CRenderer *inRenderer)
+{
+ Render(inRenderer);
+}
+
+//=============================================================================
+/**
+ * Handles mouse down on the button. Flags the button as down which results
+ * in some possible drawing changes.
+ */
+bool CButtonControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_IsMouseDown = true;
+ SetButtonState(EBUTTONSTATE_DOWN);
+ SigButtonDown(this);
+ Invalidate();
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handles mouse up on the button. Sets the button to the "up" state and fires
+ * an event to interested listeners.
+ * @param inPoint location of the mouse when the event occurred
+ * @param inFlags state of the modifier keys when this event occurred
+ */
+void CButtonControl::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ SetButtonState(EBUTTONSTATE_UP);
+
+ if (IsMouseOver()) {
+ SigButtonUp(this);
+ if (m_IsMouseDown)
+ SigClicked(this);
+ }
+ m_IsMouseDown = false;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * This function is called when the mouse passes over this button. The button
+ * is invalidated so that any custom drawing for when the mouse is over the
+ * button can occurr.
+ * @param inPoint location of the mouse when the event occurred
+ * @param inFlags state of the modifier keys when this event occurred
+ */
+void CButtonControl::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ // Only invalidate the first time the mouse enters this control
+ if (m_MouseEnter) {
+ Invalidate();
+ m_MouseEnter = false;
+ }
+}
+
+//=============================================================================
+/**
+ * This function is called when the mouse exits the bounds of this button. The
+ * button is invalidated so that any custom drawing caused by the OnMouseOver
+ * event can be undone.
+ * @param inPoint location of the mouse when the event occurred
+ * @param inFlags state of the modifier keys when this event occurred
+ */
+void CButtonControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+ Invalidate();
+ // Change the flag so that next time we get a mouse over event, we know to invalidate this
+ // button
+ m_MouseEnter = true;
+}
+
+//=============================================================================
+/**
+ * Gets the current bitmap depending on the state of the button, postion of the
+ * mouse, etc. Returns the image for the up state by default.
+ * @return the currently displayed image or NULL if there is no image on this button
+ */
+QPixmap CButtonControl::GetCurrentImage() const
+{
+ // Default to the up state
+ auto theImage = m_ImageUp;
+
+ EButtonState theState = GetButtonState();
+
+ // If the mouse is over the button, switch to the mouse over image
+ if (IsMouseOver() && !m_ImageOver.isNull())
+ theImage = m_ImageOver;
+
+ // If the button is currently pressed, this cancels the up and over states, so return the down
+ // image
+ if (theState == EBUTTONSTATE_DOWN && !m_ImageDown.isNull())
+ theImage = m_ImageDown;
+
+ // If this button is disabled just return the disabled image (overrides any other states)
+ if (!IsEnabled()) { // use the specified butuon UP disabled if specified, otherwise fall back on
+ // the DOWN ( that's how the legacy system does it )
+ if (theState == EBUTTONSTATE_UP && !m_ImageUpDisabled.isNull())
+ theImage = m_ImageUpDisabled;
+ else if (!m_ImageDownDisabled.isNull())
+ theImage = m_ImageDownDisabled;
+ }
+ return theImage;
+}
+
+//=============================================================================
+/**
+ * Get the size of the image that this control is currently using.
+ * @return the size of the ImageUp image.
+ */
+QSize CButtonControl::GetImageSize() const
+{
+ // Get the image map.
+ QPixmap theImage = GetCurrentImage();
+
+ return theImage.size();
+}
+
+//=============================================================================
+/**
+ * Override of invalidate to invalidate the parent as well.
+ * @param inIsInvalidated true if this is to be invalidated.
+ */
+void CButtonControl::Invalidate(bool inIsInvalidated /* = true */)
+{
+ // Since the button is transparent the parent needs to be drawn as well.
+ if (inIsInvalidated && GetParent() != nullptr)
+ GetParent()->Invalidate();
+
+ CControl::Invalidate(inIsInvalidated);
+}
+
+//=============================================================================
+/**
+ * Draws the appropriate image for the current button state to the renderer.
+ * @param inRenderer the renderer to draw to
+ */
+void CButtonControl::Render(CRenderer *inRenderer)
+{
+ CPt thePos(0, 0);
+ const auto theImage = GetCurrentImage();
+
+ if (m_VCenterImage || m_HCenterImage) {
+ const auto theSize = theImage.size();
+
+ if (m_HCenterImage)
+ thePos.x = (GetSize().x / 2) - (theSize.width() / 2);
+
+ if (m_VCenterImage)
+ thePos.y = (GetSize().y / 2) - (theSize.height() / 2);
+ }
+
+ thePos.x += m_Margin;
+
+ if (!theImage.isNull())
+ inRenderer->DrawBitmap(thePos, theImage);
+}
+
+//=============================================================================
+/**
+ * If auto sizing is enabled, this function resizes the button to be the same
+ * size as the image that it contains. Note: it does not set the Min/Max sizes.
+ */
+void CButtonControl::Resize()
+{
+ if (m_AutoSize) {
+ auto theSize = m_ImageUp.size();
+
+ SetSize(CPt(theSize.width(), theSize.height()));
+ }
+}
diff --git a/src/Authoring/Studio/Controls/ButtonControl.h b/src/Authoring/Studio/Controls/ButtonControl.h
new file mode 100644
index 00000000..4baf71dc
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ButtonControl.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_BUTTON_CONTROL_H
+#define INCLUDED_BUTTON_CONTROL_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "Multicaster.h"
+
+#include <QPixmap>
+
+#include <boost/signals.hpp>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//=============================================================================
+/**
+ * Base class for creating button controls.
+ */
+class CButtonControl : public CControl
+{
+public:
+ /// States for procedural buttons that might result in drawing changes
+ enum EButtonState {
+ EBUTTONSTATE_UP, ///< Indicates that the button is currently in the up position
+ EBUTTONSTATE_DOWN, ///< Indicates that the button is currently in the up position
+ EBUTTONSTATE_INDETERMINATE ///< Not used yet; provided for sub-classes to implement a
+ ///tri-state functionality
+ };
+
+protected:
+ EButtonState m_State; ///< Specifies what state the button is currently in; state changes as the
+ ///button is clicked on
+ QPixmap m_ImageUp; ///< The image for the button in its normal state
+ QPixmap m_ImageDown; ///< The image for the button while it is being clicked
+ QPixmap m_ImageOver; ///< The image for the button while the mouse is over
+ QPixmap m_ImageUpDisabled; ///< The image for the button when it is disabled and unavailable
+ ///to the user
+ QPixmap m_ImageDownDisabled; ///< The image for the button when it is disabled and unavailable
+ ///to the user
+ bool m_AutoSize; ///< true if the button will automatically resize itself
+ bool m_MouseEnter; ///< Flag for determining mouse enter/exit status so that the number of
+ ///invalidations is minimized. See OnMouseOver and OnMouseOut.
+ bool m_IsMouseDown;
+ bool m_VCenterImage;
+ bool m_HCenterImage;
+ long m_Margin;
+
+public:
+ CButtonControl();
+ virtual ~CButtonControl();
+
+ EButtonState GetButtonState() const;
+ virtual void SetButtonState(EButtonState inState);
+
+ void SetUpImage(const QPixmap &inImage);
+ void SetUpImage(const QString &inImageName);
+ void SetDownImage(const QPixmap &inImage);
+ void SetDownImage(const QString &inImageName);
+ void SetOverImage(const QPixmap &inImage);
+ void SetOverImage(const QString &inImageName);
+ void SetDisabledImage(const QPixmap &inImage);
+ void SetDisabledImage(const QString &inImageName);
+ void SetUpDisabledImage(const QString &inImageName);
+ QSize GetImageSize() const;
+
+ void SetAutoSize(bool inEnableAutoSize);
+ bool GetAutoSize();
+
+ void SetCenterImage(bool inVCenter, bool inHCenter);
+ void SetMarginImage(long inMargin);
+
+ void Draw(CRenderer *inRenderer) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void Invalidate(bool inIsInvalidated = true) override;
+
+ boost::signal1<void, CControl *> SigButtonDown;
+ boost::signal1<void, CControl *> SigButtonUp;
+ boost::signal1<void, CControl *> SigClicked;
+
+protected:
+ virtual void Render(CRenderer *inRenderer);
+ virtual QPixmap GetCurrentImage() const;
+ virtual void Resize();
+};
+
+#endif // INCLUDED_BUTTON_CONTROL_H
diff --git a/src/Authoring/Studio/Controls/ClickableLabel.cpp b/src/Authoring/Studio/Controls/ClickableLabel.cpp
new file mode 100644
index 00000000..73995fcf
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ClickableLabel.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ClickableLabel.h"
+
+#include <QMouseEvent>
+
+ClickableLabel::ClickableLabel(QWidget *pr) :
+ QLabel(pr)
+{
+
+}
+
+void ClickableLabel::mousePressEvent(QMouseEvent *event)
+{
+ if (rect().contains(event->pos()))
+ event->accept();
+}
+
+void ClickableLabel::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (rect().contains(event->pos())) {
+ event->accept();
+ Q_EMIT clicked();
+ }
+}
diff --git a/src/Authoring/Studio/Controls/ClickableLabel.h b/src/Authoring/Studio/Controls/ClickableLabel.h
new file mode 100644
index 00000000..591baa9a
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ClickableLabel.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLICKABLELABEL_H
+#define CLICKABLELABEL_H
+
+#include <QLabel>
+
+class ClickableLabel : public QLabel
+{
+ Q_OBJECT
+public:
+ ClickableLabel(QWidget *pr = nullptr);
+
+Q_SIGNALS:
+ void clicked();
+
+protected:
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+};
+
+#endif // CLICKABLELABEL_H
diff --git a/src/Authoring/Studio/Controls/ComboTextBox.h b/src/Authoring/Studio/Controls/ComboTextBox.h
new file mode 100644
index 00000000..dbb3f199
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ComboTextBox.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_COMBO_TEXT_BOX_H
+#define INCLUDED_COMBO_TEXT_BOX_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StringEdit.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//==============================================================================
+/**
+ * @class CComboTextBox extends CTextEdit to handle custom drawing, etc.
+ */
+class CComboTextBox : public CStringEdit
+{
+public:
+ CComboTextBox();
+ virtual ~CComboTextBox();
+ void Draw(CRenderer *inRenderer) override;
+ bool OnMouseDown(CPt inLocation, Qt::KeyboardModifiers inFlags) override;
+ bool CanAcceptChar(const Q3DStudio::CString &inCheckString, unsigned int inChar,
+ unsigned int inPosition) override;
+
+protected:
+};
+
+#endif // INCLUDED_COMBO_TEXT_BOX_H
diff --git a/src/Authoring/Studio/Controls/Control.cpp b/src/Authoring/Studio/Controls/Control.cpp
new file mode 100644
index 00000000..dbf06690
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Control.cpp
@@ -0,0 +1,1806 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "Control.h"
+#include "Renderer.h"
+#include "MasterP.h"
+#include "StudioUtils.h"
+#include "HotKeys.h"
+#include "ControlGraph.h"
+#include "ControlData.h"
+#include "ResourceCache.h"
+#include "MouseCursor.h"
+
+#include <QtWidgets/qapplication.h>
+
+using namespace Q3DStudio::Control;
+
+IMPLEMENT_OBJECT_COUNTER(CControl)
+
+//=============================================================================
+/**
+ * Constructor, creates a control with all default values.
+ */
+CControl::CControl()
+ : m_cursorSet(-1)
+{
+ m_ControlData = CControlData::CreateControlData(*this);
+ ADDTO_OBJECT_COUNTER(CControl)
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CControl::~CControl()
+{
+ REMOVEFROM_OBJECT_COUNTER(CControl)
+ m_ControlData->ReleaseControl();
+}
+
+//=============================================================================
+/**
+ * Draw this control and all children below it.
+ * This can be overriden by controls to draw themselves but should still be
+ * called if sub controls are to be drawn.
+ * This will call Draw if this control is actually supposed to be drawn. It will
+ * be drawn if it is invalidated or if anything above it in it's heirarchy has
+ * been invalidated.
+ * @param inRenderer the renderer to draw this control out to.
+ */
+void CControl::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect,
+ bool inIgnoreValidation /* = false */)
+{
+ EnsureLayout();
+ bool isInvalidated = IsInvalidated();
+
+ // inRenderer->PushClippingRect( GetSize( ) );
+
+ CRct theBoundingBox = inRenderer->GetClippingRect();
+
+ if (isInvalidated) {
+ CRct theRect(GetSize());
+ theRect.And(theBoundingBox);
+ theRect.Offset(inRenderer->GetTranslation());
+ inDirtyRect.Or(theRect);
+ }
+
+ if (isInvalidated || inIgnoreValidation) {
+ Draw(inRenderer);
+ }
+
+ // Notify the children in the reverse order that they are drawn.
+ ControlGraph::SReverseIterator theRPos = ControlGraph::GetRChildren(*this);
+ for (; !theRPos.IsDone(); ++theRPos) {
+ (*theRPos)->EnsureLayout();
+ (*theRPos)->BeginDrawChildren(inRenderer);
+ }
+
+ // Go through all the children and draw them in the correct order. By keeping
+ // this order there is a semblance of depth.
+ ControlGraph::SIterator thePos = ControlGraph::GetChildren(*this);
+ for (; !thePos.IsDone(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsVisible()) //&& ( theChild->IsChildInvalidated( ) || inIgnoreValidation ||
+ //isInvalidated ) )
+ {
+ CPt thePosition = theChild->GetPosition();
+ inRenderer->PushTranslation(thePosition);
+
+ // Clipping of non-visible objects.
+ if (theChild->IsInRect(theBoundingBox)) {
+ theChild->OnDraw(inRenderer, inDirtyRect, inIgnoreValidation || isInvalidated);
+ } else {
+ theChild->NotifyNotInClipRect();
+ }
+ inRenderer->PopTranslation();
+ }
+ }
+
+ // inRenderer->PopClippingRect( );
+
+ // Set this as not being invalidated.
+ Invalidate(false);
+}
+
+//=============================================================================
+/**
+ * Performs the drawing for this control.
+ * Does nothing by default.
+ * @param inRenderer the renderer to draw to.
+ */
+void CControl::Draw(CRenderer *inRenderer)
+{
+ Q_UNUSED(inRenderer);
+}
+
+//=============================================================================
+/**
+ * Notification that this control is not in the clipping rect and hence will
+ * not be drawn.
+ * By default, tell inform its children
+ */
+void CControl::NotifyNotInClipRect()
+{
+ ControlGraph::SIterator thePos = ControlGraph::GetChildren(*this);
+ for (; !thePos.IsDone(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ theChild->NotifyNotInClipRect();
+ }
+}
+
+//=============================================================================
+/**
+ * Get the position of this control.
+ * The position of this control is relative to it's parent's 0,0 coordinate.
+ * @return the position relative to it's parent's position.
+ */
+CPt CControl::GetPosition() const
+{
+ return m_ControlData->m_Position;
+}
+
+//=============================================================================
+/**
+ * Set the position of this control.
+ * The position of this control is relative to it's parent's 0,0 coordinate.
+ * @return the position relative to it's parent's position.
+ */
+void CControl::SetPosition(CPt inPosition)
+{
+ if (inPosition != m_ControlData->m_Position) {
+ MarkChildrenNeedLayout();
+ m_ControlData->m_Position = inPosition;
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Overload of SetPosition to allow it to take 2 parameters.
+ * This will call SetPosition( CPt ) so there is no need to extend this
+ * method.
+ * @param inX the X position to set.
+ * @param inY the Y position to set.
+ */
+void CControl::SetPosition(long inX, long inY)
+{
+ SetPosition(CPt(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Get the size of the control.
+ * The size is the width and height of the control from it's position.
+ * @return the size of this control.
+ */
+CPt CControl::GetSize() const
+{
+ return m_ControlData->m_Size;
+}
+
+//=============================================================================
+/**
+ * Set the size of this control.
+ * The size is the width and height of the control from it's position.
+ * @param inSize the new size of the control.
+ */
+void CControl::SetSize(CPt inSize)
+{
+ if (GetSize() != inSize) {
+ m_ControlData->m_Size = inSize;
+ if (GetParent() != nullptr)
+ GetParent()->OnChildSizeChanged(this); // this callback needs to die
+ OnSizeChanged(inSize);
+ }
+}
+
+void CControl::OnSizeChanged(CPt /*inSize*/)
+{
+ MarkChildrenNeedLayout();
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Overload of SetSize to allow it to take 2 parameters.
+ * This will call SetSize( CPt ) so there is no need to extend this method.
+ * @param inWidth the new width of this control.
+ * @param inHeight the new height of this control.
+ */
+void CControl::SetSize(long inX, long inY)
+{
+ SetSize(CPt(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Get the minimum allowable size of this control.
+ * This is used by layout managers to get the minimum size that a control is
+ * allowed to be when it is resizing the control. This defaults to 0,0.
+ * @return the minimum size that this control is allowed to be.
+ */
+CPt CControl::GetMinimumSize()
+{
+ return m_ControlData->m_MinSize;
+}
+
+//=============================================================================
+/**
+ * Set the minimum allowable size of this control.
+ * This is used by layout managers to get the minimum size that a control is
+ * allowed to be when it is resizing the control. This defaults to 0,0.
+ * param inSize the minimum size that this control is allowed to be.
+ */
+void CControl::SetMinimumSize(CPt inSize)
+{
+ if (inSize != m_ControlData->m_MinSize) {
+ NotifyParentNeedsLayout();
+ m_ControlData->m_MinSize = inSize;
+ if (inSize.x > m_ControlData->m_MaxSize.x)
+ m_ControlData->m_MaxSize.x = inSize.x;
+ if (inSize.y > m_ControlData->m_MaxSize.y)
+ m_ControlData->m_MaxSize.y = inSize.y;
+ }
+}
+
+//=============================================================================
+/**
+ * Get the maximum allowable size of this control.
+ * This is used by layout managers to get the maximum size that a control is
+ * allowed to be when it is resizing the control. This defaults to LONG_MAX,LONG_MAX.
+ * @return the maximum size that this control is allowed to be.
+ */
+CPt CControl::GetMaximumSize()
+{
+ return m_ControlData->m_MaxSize;
+}
+
+//=============================================================================
+/**
+ * Set the maximum allowable size of this control.
+ * This is used by layout managers to get the maximum size that a control is
+ * allowed to be when it is resizing the control. This defaults to LONG_MAX,LONG_MAX.
+ * @param inSize the maximum size that this control is allowed to be.
+ */
+void CControl::SetMaximumSize(CPt inSize)
+{
+ if (inSize != m_ControlData->m_MaxSize) {
+ NotifyParentNeedsLayout();
+ m_ControlData->m_MaxSize = inSize;
+ }
+}
+
+//=============================================================================
+/**
+ * Get the preferred size of this control.
+ * This is used by layout managers to get the preferred size of the control.
+ * The preferred size is often used for relative scaling of sibling controls.
+ * @return the preferred size of this control.
+ */
+CPt CControl::GetPreferredSize()
+{
+ return m_ControlData->m_PrefSize;
+}
+
+//=============================================================================
+/**
+ * Set the preferred size of this control.
+ * This is used by layout managers to get the preferred size of the control.
+ * The preferred size is often used for relative scaling of sibling controls.
+ * @param the preferred size of this control.
+ */
+void CControl::SetPreferredSize(CPt inSize)
+{
+ if (inSize != m_ControlData->m_PrefSize) {
+ NotifyParentNeedsLayout();
+ Invalidate();
+ m_ControlData->m_PrefSize = inSize;
+ }
+}
+
+void CControl::SetAbsoluteSize(CPt inSize)
+{
+ SetMinimumSize(inSize);
+ SetMaximumSize(inSize);
+ SetPreferredSize(inSize);
+ SetSize(inSize);
+}
+
+//=============================================================================
+/**
+ * Event called when the mouse is moving.
+ * This event will be called when the mouse is over this control or when this
+ * control has the focus. This can be extended by controls but should be called
+ * if the event is to be propagated down to child controls.
+ * @param inPoint the location of the mouse relative to this control.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ */
+void CControl::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theHitFlag = false;
+ // Go through all the children notifying them of mouse moves.
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If a child has not already gotten the move (higher level child covering a lower level
+ // one)
+ // then check the hit test.
+ if (!theHitFlag && theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ // This is the first child to be hit, do not allow the message to go onto another
+ // sibling under this one.
+ theHitFlag = true;
+
+ // Do not fire events to non-enabled children.
+ if (theChild->IsEnabled()) {
+ // If this is the first time the mouse is over this then fire a mouse over
+ if (!theChild->IsMouseOver()) {
+ theChild->OnMouseOver(theChildPoint, inFlags);
+ }
+ // Fire a mouse move as well, this will also propagate the mouse over to
+ // grand-children etc.
+ theChild->OnMouseMove(theChildPoint, inFlags);
+ }
+ }
+ // Check all the children and if they think the mouse is over them then notify them of a
+ // mouse out.
+ else if (theChild->IsMouseOver()) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ theChild->OnMouseOut(theChildPoint, inFlags);
+ }
+ }
+
+ // If there is a child with focus and the mouse is not over it then still notify it of the mouse
+ // move
+ // If the mouse is over it then it would have gotten the move from the above loop.
+ if (m_ControlData->m_MouseFocus && !m_ControlData->m_MouseFocus->IsMouseOver()) {
+ CPt theChildPoint = inPoint - m_ControlData->m_MouseFocus->GetPosition();
+ m_ControlData->m_MouseFocus->OnMouseMove(theChildPoint, inFlags);
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse is over this control.
+ * This is only called once when the mouse enters the control, and does not get
+ * called until the mouse leaves then re-enters the control.
+ * @param inPoint where the mouse is, relative to this control.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ */
+void CControl::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+ m_ControlData->m_IsMouseOver = true;
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse left this control.
+ * This is only called once when the mouse leaves the control and does not get
+ * called until the mouse enters then re-leaves the control.
+ * This also notifies all children that the mouse is over that it is no longer
+ * over.
+ * @param inPoint where the mouse is, relative to this control.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ */
+void CControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_ControlData->m_IsMouseOver = false;
+
+ GetWindowListener()->HideTooltips();
+ // Go through all the children looking for ones that think the mouse is over.
+ // If it is then notify it of a mouse out.
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsMouseOver()) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ theChild->OnMouseOut(inPoint, inFlags);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the left mouse button was clicked on this control.
+ * This handles the mouse hits and sets the focus to the control that was
+ * clicked on.
+ * @param inPoint where the mouse was clicked, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ * @return true if the mouse event is processed.
+ */
+bool CControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+ bool theChildGotHit = false;
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If the child was hit then notify it of the mouse down, and set the focus to
+ // be it.
+ if (theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ theChildGotHit = true;
+ // Only send the event if the child is enabled.
+ if (theChild->IsEnabled()) {
+ theRetVal = theChild->OnMouseDown(theChildPoint, inFlags);
+
+ if (m_ControlData->m_Focus != theChild) {
+ if (m_ControlData->m_Focus)
+ m_ControlData->m_Focus->OnLoseFocus();
+ if (theChild->CanGainFocus()) {
+ m_ControlData->m_Focus = theChild;
+ m_ControlData->m_Focus->OnGainFocus();
+ } else
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ }
+ m_ControlData->m_MouseFocus = theChild;
+ } else {
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ }
+
+ // only want OnMouseDown to be called on the first child under the point.
+ break;
+ }
+ }
+ if (!theChildGotHit && m_ControlData->m_Focus) {
+ m_ControlData->m_Focus->OnLoseFocus();
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ }
+ m_ControlData->SetMouseDown(!theRetVal);
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Notification that the right mouse button was clicked on this control.
+ * This handles the mouse hits and sets the focus to the control that was
+ * clicked on.
+ * @param inPoint where the mouse was clicked, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ * @return true if the mouse event is processed.
+ */
+bool CControl::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If the child was hit then notify it of the mouse down, and set the focus to
+ // be it.
+ if (theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+
+ // Only send the event if the child is enabled.
+ if (theChild->IsEnabled()) {
+ if (m_ControlData->m_Focus != theChild) {
+ if (m_ControlData->m_Focus)
+ m_ControlData->m_Focus->OnLoseFocus();
+ if (theChild->CanGainFocus()) {
+ m_ControlData->m_Focus = theChild;
+ m_ControlData->m_Focus->OnGainFocus();
+ } else
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ }
+ m_ControlData->m_MouseFocus = theChild;
+ theRetVal = theChild->OnMouseRDown(theChildPoint, inFlags);
+ } else {
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ }
+
+ // only want OnMouseDown to be called on the first child under the point.
+ break;
+ }
+ }
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Notification thatthe mouse was double clicked on this control.
+ * This handled the mouse hits and passes it down to all the children.
+ * @param inPoint where the mouse was clicked, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ * @return true if the mouse event is processed.
+ */
+bool CControl::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If the child was hit then notify it of the mouse down, and set the focus to
+ // be it.
+ if (theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ // Only send the event if the child is enabled.
+ if (theChild->IsEnabled()) {
+ theRetVal = theChild->OnMouseDoubleClick(theChildPoint, inFlags);
+ }
+
+ // only want OnMouseDown to be called on the first child under the point.
+ break;
+ }
+ }
+
+ return theRetVal;
+}
+
+bool CControl::OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+
+ // try letting the focus getting the wheel first
+ if (m_ControlData->m_Focus) {
+ CPt theChildPoint = inPoint - m_ControlData->m_Focus->GetPosition();
+ theRetVal = m_ControlData->m_Focus->OnMouseWheel(theChildPoint, inAmount, inFlags);
+ }
+
+ // if the focus does not want the wheel then let the mouse pos do it.
+ if (!theRetVal) {
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->GetMouseWheelEventState() == ControlEventState::Listening
+ && theChild->IsEnabled() && theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ theRetVal = theChild->OnMouseWheel(theChildPoint, inAmount, inFlags);
+ break;
+ }
+ }
+ }
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse is hovering over this control.
+ * This handles the mouse hover and passes it down to all the children.
+ * @param inPoint where the mouse is located, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ * @return true if the mouse event is processed.
+ */
+bool CControl::OnMouseHover(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If the child was hit then notify it of the mouse down, and set the focus to
+ // be it.
+ if (theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ // Only send the event if the child is enabled.
+ if (theChild->IsEnabled()) {
+ theRetVal = theChild->OnMouseHover(theChildPoint, inFlags);
+ }
+
+ // only want OnMouseHover to be called on the first child under the point.
+ break;
+ }
+ }
+
+ // If the mouseover was not handled
+ if (!theRetVal) {
+ // If the tooltip text is not empty
+ Q3DStudio::CString theTooltipText = GetTooltipText();
+ if (!theTooltipText.IsEmpty()) {
+ // Show the tooltip, and return true so that parents don't cover this tooltip with their
+ // own
+ // Note that we are offsetting the point so that it appears below the mouse cursor
+ GetWindowListener()->ShowTooltips(GetGlobalPosition(CPt(inPoint.x, inPoint.y + 32)),
+ GetTooltipText());
+ theRetVal = true;
+ }
+ }
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Notification that the left mouse button was released.
+ * This is only called on the control that has focus, not on the control under
+ * the mouse.
+ * @param inPoint where the mouse was released, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ */
+void CControl::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_ControlData->m_MouseFocus) {
+ CPt theChildPoint = inPoint - m_ControlData->m_MouseFocus->GetPosition();
+ m_ControlData->m_MouseFocus->OnMouseUp(theChildPoint, inFlags);
+ }
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If the child was hit then notify it of the mouse down, and set the focus to
+ // be it.
+ if (theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ // Only send the event if the child is enabled.
+ if (theChild->IsEnabled() && theChild != m_ControlData->m_MouseFocus
+ && theChild != m_ControlData->m_Focus) {
+ theChild->OnMouseUp(theChildPoint, inFlags);
+ }
+
+ // only want OnMouseUp to be called on the first child under the point.
+ break;
+ }
+ }
+ m_ControlData->m_MouseFocus = std::shared_ptr<CControlData>();
+
+ if (m_ControlData->m_IsMouseDown) {
+ OnMouseClick(inPoint, inFlags);
+ m_ControlData->SetMouseDown(false);
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the right mouse button was released.
+ * This is only called on the control that has focus, not on the control under
+ * the mouse.
+ * @param inPoint where the mouse was released, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ */
+void CControl::OnMouseRUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_ControlData->m_MouseFocus) {
+ CPt theChildPoint = inPoint - m_ControlData->m_MouseFocus->GetPosition();
+ m_ControlData->m_MouseFocus->OnMouseRUp(theChildPoint, inFlags);
+ }
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ // If the child was hit then notify it of the mouse down, and set the focus to
+ // be it.
+ if (theChild->HitTest(inPoint)) {
+ CPt theChildPoint = inPoint - theChild->GetPosition();
+ // Only send the event if the child is enabled.
+ if (theChild->IsEnabled() && theChild != m_ControlData->m_MouseFocus
+ && theChild != m_ControlData->m_Focus) {
+ theChild->OnMouseRUp(theChildPoint, inFlags);
+ }
+
+ // only want OnMouseUp to be called on the first child under the point.
+ break;
+ }
+ }
+ m_ControlData->m_MouseFocus = std::shared_ptr<CControlData>();
+}
+
+//=============================================================================
+/**
+ * Handles character input from the keyboard.
+ *
+ * @param inChar Character that was pressed
+ * @return true if the character was handled, false if this control does not
+ * care about the character that was pressed
+ */
+bool CControl::OnChar(const QString &inChar, Qt::KeyboardModifiers inModifiers)
+{
+ if (m_ControlData->m_Focus)
+ return m_ControlData->m_Focus->OnChar(inChar, inModifiers);
+ else
+ return false;
+}
+
+//=============================================================================
+/**
+ * Handles a key down message from the keyboard.
+ *
+ * @param inChar Character that was pressed
+ * @return true if the character was handled, false if this control does not
+ * care about the character that was pressed
+ */
+bool CControl::OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inModifiers)
+{
+ bool theRetVal = false;
+
+ if (m_ControlData->m_Focus)
+ theRetVal = m_ControlData->m_Focus->OnKeyDown(inChar, inModifiers);
+
+ if (!theRetVal) {
+ if (inChar == Qt::Key_Tab) {
+ if (inModifiers & Qt::ShiftModifier) {
+ OnReverseTab();
+ } else {
+ OnTab();
+ }
+ theRetVal = true;
+ }
+ }
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Handles a key up from the keyboard.
+ *
+ * @param inChar Character that was pressed
+ * @return true if the character was handled, false if this control does not
+ * care about the character that was pressed
+ */
+bool CControl::OnKeyUp(unsigned int inChar, Qt::KeyboardModifiers)
+{
+ Q_UNUSED(inChar);
+ return false;
+}
+
+//=============================================================================
+/**
+ * Find the first child (descendant) control that has a valid drop target.
+ */
+CDropTarget *CControl::FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags)
+{
+ CDropTarget *theDropTarget = NULL;
+
+ // Go through all the children looking for the first one that was clicked on
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsMouseOver() && theChild->IsEnabled()) {
+ // Put the point into this childs coords.
+ CPt theChildPoint = inMousePoint - theChild->GetPosition();
+
+ // Allow the child the opportunity to respond
+ theDropTarget = theChild->FindDropCandidate(theChildPoint, inFlags);
+
+ if (theDropTarget)
+ break;
+ }
+ }
+ return theDropTarget;
+}
+
+//=============================================================================
+/**
+ * Add a child control to this control.
+ * This will make the child behave as a child of this, get set up for drawing
+ * and events. The inInsertBefore control is used to determine Z-depth, or
+ * manually insert a control into a specific location.
+ * The child cannot already be a child of another control.
+ * @param inControl the control to be added.
+ * @param inInsertBefore the control to be inserted before, or std::shared_ptr<CControlData>() to
+ * be at the back.\
+ */
+void CControl::AddChild(CControl *inControl,
+ CControl *inInsertBefore /*=std::shared_ptr<CControlData>()*/)
+{
+ NotifyParentNeedsLayout();
+ ControlGraph::AddChild(*this, *inControl, inInsertBefore);
+}
+
+//=============================================================================
+/**
+ * Remove a child control from this control.
+ * This will remove it from drawing and getting any events.
+ * @param inControl the control to be removed.
+ */
+void CControl::RemoveChild(CControl *inControl)
+{
+ if (inControl) {
+ ControlGraph::RemoveChild(*this, *inControl);
+
+ if (m_ControlData->m_Focus == inControl->m_ControlData) {
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ }
+ if (m_ControlData->m_MouseFocus == inControl->m_ControlData) {
+ m_ControlData->m_MouseFocus = std::shared_ptr<CControlData>();
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Remove all child controls from this control.
+ * This will remove it from drawing and getting any events.
+ *
+ * This is not recursive
+ */
+void CControl::RemoveAllChildren()
+{
+ NotifyParentNeedsLayout();
+ ControlGraph::RemoveAllChildren(*this);
+
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ m_ControlData->m_MouseFocus = std::shared_ptr<CControlData>();
+}
+
+//=============================================================================
+/**
+ * Retrieve the index of a child control. The index will return the zero based position.
+ * @param inChildControl the control that is a direct child of this control
+ * @return the zero-based index of this control we will return -1 if we don't find the control
+ */
+long CControl::GetChildIndex(CControl *inChildControl)
+{
+ return ControlGraph::GetChildIndex(*this, *inChildControl);
+}
+
+static inline CControl *ToControl(std::shared_ptr<CControlData> inPtr)
+{
+ if (inPtr)
+ return inPtr->GetControl();
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Finds a child control by its name
+ * @return the child if found, std::shared_ptr<CControlData>() otherwise
+ */
+CControl *CControl::FindChildByName(const Q3DStudio::CString &inName)
+{
+ std::shared_ptr<CControlData> theResult = std::shared_ptr<CControlData>();
+
+ ControlGraph::SIterator theChildIter = GetChildren();
+ for (; !theChildIter.IsDone(); ++theChildIter) {
+ if (theChildIter.GetCurrent()->GetName() == inName) {
+ theResult = theChildIter.GetCurrent();
+ break;
+ }
+ }
+
+ return ToControl(theResult);
+}
+
+CControl *CControl::FocusedChild()
+{
+ CControl *theResult = nullptr;
+
+ ControlGraph::SIterator theChildIter = GetChildren();
+ for (; !theChildIter.IsDone(); ++theChildIter) {
+ auto current = ToControl(theChildIter.GetCurrent());
+ auto hasFocus = HasFocus(current);
+ if (hasFocus) {
+ if (current->GetFirstChild())
+ theResult = current->FocusedChild();
+ else
+ theResult = current;
+ break;
+ }
+ }
+
+ return theResult;
+}
+
+//=============================================================================
+/**
+ * Check to see if the mouse is over this control or not.
+ * @return true if the mouse is over this control.
+ */
+bool CControl::IsMouseOver() const
+{
+ return m_ControlData->m_IsMouseOver;
+}
+
+//=============================================================================
+/**
+ * Check to see if inPoint is over this control or not.
+ * This is used for mouse hits and can be extended for non-standard control
+ * shapes. Non-visible controls always return false.
+ * @param inPoint the location of the mouse in local coordinates.
+ */
+bool CControl::HitTest(const CPt &inPoint) const
+{
+ CPt thePoint = inPoint - GetPosition();
+ CPt theSize = GetSize();
+ // Basic check to see if it's in the size.
+ if (IsVisible() && thePoint.x >= 0 && thePoint.y >= 0 && thePoint.x < theSize.x
+ && thePoint.y < theSize.y)
+ return true;
+ return false;
+}
+
+//=============================================================================
+/**
+ * Checks to see if any part of this control is in the rect.
+ * This is used for drawing and ignoring objects that do not need to be
+ * redrawn or need to be drawn.
+ * @param inRect the rect to check to see if this is in.
+ * @return true if this is in the rect.
+ */
+bool CControl::IsInRect(const CRct &inRect) const
+{
+ CRct myRect(GetPosition(), GetSize());
+
+ if (myRect.position <= inRect.size + inRect.position) {
+ if (myRect.size + myRect.position >= inRect.position) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Invalidate this control and cause it to be redrawn.
+ * @param inInvalidate true if this is to be invalidated.
+ */
+void CControl::Invalidate(bool inInvalidate /*= true*/)
+{
+ m_ControlData->m_IsInvalidated = inInvalidate;
+ if (inInvalidate && GetParent() != nullptr) {
+ GetParent()->OnChildInvalidated();
+ }
+ if (!inInvalidate) {
+ m_ControlData->m_IsChildInvalidated = false;
+ }
+}
+
+//=============================================================================
+/**
+ * Invalidate this object and all children within inRect.
+ * @param inRect the rect in which to invalidate all children.
+ */
+void CControl::InvalidateRect(const CRct &inRect)
+{
+ Invalidate();
+
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsInRect(inRect)) {
+ CRct theChildRect = inRect;
+ theChildRect.Offset(theChild->GetPosition());
+
+ theChild->InvalidateRect(inRect);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Check to see if this control is invalidated or not.
+ * @return true if this control is invalidated.
+ */
+bool CControl::IsInvalidated() const
+{
+ return m_ControlData->IsInvalidated();
+}
+
+//=============================================================================
+/**
+ * Notifies this control that a child of it has been invalidated.
+ */
+void CControl::OnChildInvalidated()
+{
+ // Only do it if we haven't already, avoid multiple traversals up the tree.
+ if (!m_ControlData->m_IsChildInvalidated) {
+ if (GetParent() != nullptr)
+ GetParent()->OnChildInvalidated();
+ else if (m_ControlData->m_WindowListener != nullptr)
+ m_ControlData->m_WindowListener->OnControlInvalidated();
+
+ m_ControlData->m_IsChildInvalidated = true;
+ }
+}
+
+//=============================================================================
+/**
+ * Checks to see if a child of this control is invalidated.
+ */
+bool CControl::IsChildInvalidated() const
+{
+ return m_ControlData->m_IsChildInvalidated || m_ControlData->m_IsInvalidated;
+}
+
+void CControl::SetWindowListener(CControlWindowListener *inListener)
+{
+ m_ControlData->m_WindowListener = inListener;
+}
+
+//=============================================================================
+/**
+ * Retrieves the topmost window of this control. The window listener is the
+ * bridge between the OS and the cross-platform custom control code below.
+ * This function was added specifically to support drag-and-drop by providing
+ * a way of setting the drag state on the outermost window.
+ * @return pointer to the control window listener or std::shared_ptr<CControlData>() if there is
+ * not one
+ */
+CControlWindowListener *CControl::GetWindowListener()
+{
+ CControlWindowListener *theWindowListener = nullptr;
+ if (GetParent() != nullptr)
+ theWindowListener = GetParent()->GetWindowListener();
+ else
+ theWindowListener = m_ControlData->m_WindowListener;
+ return theWindowListener;
+}
+
+//=============================================================================
+/**
+ * Set this control as being visible or not.
+ * If the control is not visible then it will not be drawn and will not
+ * get mouse clicks.
+ * @param inIsVisible true if this control is to be visible.
+ */
+void CControl::SetVisible(bool inIsVisible)
+{
+ if (inIsVisible != m_ControlData->m_IsVisible) {
+ m_ControlData->m_IsVisible = inIsVisible;
+ NotifyParentNeedsLayout();
+
+ if (GetParent() != nullptr)
+ GetParent()->OnChildSizeChanged(this);
+
+ OnVisibleStateChange(inIsVisible);
+ OnParentVisibleStateChanged(inIsVisible);
+
+ this->Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the visible state of a control has changed
+ */
+void CControl::OnVisibleStateChange(bool inIsVisible)
+{
+ Q_UNUSED(inIsVisible);
+}
+
+void CControl::OnParentVisibleStateChanged(bool inIsVisible)
+{
+ NotifyParentNeedsLayout();
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ theChild->OnParentVisibleStateChanged(inIsVisible);
+ }
+}
+
+//=============================================================================
+/**
+ * Checks to see if this control is visible or not.
+ * If the control is not visible then it will not be drawn and will not
+ * get mouse clicks.
+ * @return true if this control is visible.
+ */
+bool CControl::IsVisible() const
+{
+ return m_ControlData->m_IsVisible;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not this control is enabled.
+ * If the control is not enabled then it is still drawn and still intercepts
+ * mouse clicks, but it will not actually process them.
+ * @param inIsEnabled true if this control is to be enabled.
+ */
+void CControl::SetEnabled(bool inIsEnabled)
+{
+ if (inIsEnabled != m_ControlData->m_IsEnabled) {
+ NotifyParentNeedsLayout();
+ m_ControlData->m_IsEnabled = inIsEnabled;
+
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ theChild->SetParentEnabled(inIsEnabled);
+ }
+ Invalidate();
+ }
+}
+
+void CControl::SetParentEnabled(bool inParentEnabled)
+{
+ NotifyParentNeedsLayout();
+ m_ControlData->m_IsParentEnabled = inParentEnabled;
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ theChild->SetParentEnabled(inParentEnabled);
+ }
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Gets whether or not this control is enabled.
+ * If the control is not enabled then it is still drawn and still intercepts
+ * mouse clicks, but it will not actually process them.
+ * @param inIsEnabled true if this control is to be enabled.
+ */
+bool CControl::IsEnabled() const
+{
+ return m_ControlData->IsEnabled();
+}
+
+//=============================================================================
+/**
+ * Gets teh value of the enabled flag without its parent's flag
+ */
+bool CControl::GetEnabledFlag()
+{
+ return m_ControlData->GetEnabledFlag();
+}
+
+//=============================================================================
+/**
+ * Sets the enabled flag...this is used when a control wants to override the
+ * SetEnabled function and does not necessarily want to pass enabled messages
+ * to its children no matter what
+ */
+void CControl::SetEnabledFlag(bool inIsEnabled)
+{
+ m_ControlData->SetEnabledFlag(inIsEnabled);
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Notification that the size of a child has changed.
+ * @param inControl the control that has changed size.
+ */
+void CControl::OnChildSizeChanged(CControl *inControl)
+{
+ Q_UNUSED(inControl);
+}
+
+void CControl::SetName(const Q3DStudio::CString &inName)
+{
+ m_ControlData->SetName(inName);
+}
+
+Q3DStudio::CString CControl::GetName()
+{
+ return m_ControlData->GetName();
+}
+
+void CControl::BeginDrawChildren(CRenderer *inRenderer)
+{
+ Q_UNUSED(inRenderer);
+}
+
+long CControl::DoPopup(QMenu *inMenu, CPt inLocation)
+{
+ inLocation.Offset(GetPosition());
+ CControl *theParent(GetParent());
+ if (theParent) {
+ return theParent->DoPopup(inMenu, inLocation);
+ } else {
+ return m_ControlData->m_WindowListener->DoPopup(inMenu, inLocation);
+ }
+}
+
+//=============================================================================
+/**
+ * Called when a control acquires focus
+ */
+void CControl::OnGainFocus()
+{
+}
+
+//=============================================================================
+/**
+ * Causes focus to be lost.
+ */
+void CControl::OnLoseFocus()
+{
+ if (m_ControlData->m_Focus) {
+ m_ControlData->m_Focus->OnLoseFocus();
+ }
+ FireFocusEvent(false);
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+}
+
+//=============================================================================
+/**
+ * @return the parent control of this class
+ */
+CControl *CControl::GetParent()
+{
+ return m_ControlData->GetParent();
+}
+
+const CControl *CControl::GetParent() const
+{
+ return m_ControlData->GetParent();
+}
+
+//=============================================================================
+/**
+ * Removes a control from the top level control
+ */
+void CControl::RemoveUberControl(CControl *inControl)
+{
+ if (GetParent() != nullptr) {
+ GetParent()->RemoveUberControl(inControl);
+ } else {
+ RemoveChild(inControl);
+ }
+ Invalidate();
+}
+
+long CControl::GetChildCount()
+{
+ return ControlGraph::GetNumChildren(*this);
+}
+
+Q3DStudio::Control::ControlGraph::SIterator CControl::GetChildren()
+{
+ return ControlGraph::GetChildren(*this);
+}
+
+Q3DStudio::Control::ControlGraph::SReverseIterator CControl::GetReverseChildren()
+{
+ return ControlGraph::GetRChildren(*this);
+}
+
+//=============================================================================
+/**
+ * Gets the global position of the point in regards to the top level control
+ */
+CPt CControl::GetGlobalPosition(CPt inChildPoint) const
+{
+ CPt thePosition(GetPosition());
+ CPt thePoint = CPt(inChildPoint.x + thePosition.x, inChildPoint.y + thePosition.y);
+ if (GetParent())
+ return GetParent()->GetGlobalPosition(thePoint);
+ else
+ return thePoint;
+}
+
+//=============================================================================
+/**
+ * Query the platform specific render device (window)
+ */
+UICRenderDevice CControl::GetPlatformDevice()
+{
+ if (GetParent())
+ return GetParent()->GetPlatformDevice();
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Does self or child use this render device?
+ * @see CWndControl::OnKillFocus
+ */
+bool CControl::IsChildPlatformDevice(UICRenderDevice inDevice)
+{
+ if (GetPlatformDevice() == inDevice)
+ return true;
+
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsChildPlatformDevice(inDevice))
+ return true;
+ }
+
+ return false;
+}
+
+//=============================================================================
+/**
+ * Shows the window's moveable window with text
+ *
+ * @param inLocation the postion of hte center point of the window
+ * @param inText the text the window will display
+ */
+void CControl::ShowMoveableWindow(CPt inLocation, const Q3DStudio::CString &inText, CRct inBoundingRct)
+{
+ CPt thePosition(GetPosition());
+ CPt thePoint = CPt(inLocation.x + thePosition.x, inLocation.y + thePosition.y);
+
+ if (GetParent())
+ GetParent()->ShowMoveableWindow(thePoint, inText, inBoundingRct);
+ else if (m_ControlData->m_WindowListener) {
+ m_ControlData->m_WindowListener->ShowMoveableWindow(thePoint, inText, inBoundingRct);
+ }
+}
+
+//=============================================================================
+/**
+ * Hides the window's moveable window
+ */
+void CControl::HideMoveableWindow()
+{
+ if (GetParent() != nullptr)
+ GetParent()->HideMoveableWindow();
+ else if (m_ControlData->m_WindowListener)
+ m_ControlData->m_WindowListener->HideMoveableWindow();
+}
+
+//=============================================================================
+/**
+ * Offsets the position of this control... this is useful if you don't want to calculate
+ * the global position every time
+ */
+void CControl::OffsetPosition(CPt inOffset)
+{
+ CPt thePosition(GetPosition());
+ thePosition.Offset(inOffset);
+ SetPosition(thePosition);
+}
+
+//=============================================================================
+/**
+ * Gets the first child of this control
+ */
+CControl *CControl::GetFirstChild()
+{
+ std::shared_ptr<CControlData> theChild = std::shared_ptr<CControlData>();
+ ControlGraph::SIterator thePos = ControlGraph::GetChildren(*this);
+ if (!thePos.IsDone()) {
+ theChild = (*thePos);
+ }
+ return ToControl(theChild);
+}
+
+//=============================================================================
+/**
+ * @return true if this control has focus
+ */
+bool CControl::HasFocus(CControl *inControl)
+{
+ return (ToControl(m_ControlData->m_Focus) == inControl);
+}
+
+//=============================================================================
+/**
+ * default is true for controls... override if the control cannot have focus
+ */
+bool CControl::CanGainFocus()
+{
+ if (IsVisible())
+ for (ControlGraph::SIterator thePos = ControlGraph::GetChildren(*this); !thePos.IsDone();
+ ++thePos)
+ if ((*thePos)->CanGainFocus())
+ return true;
+
+ return false;
+}
+
+//=============================================================================
+/**
+ * Returns true if this CControl is in focus.
+ * @return True if this CControl is in focus.
+ */
+bool CControl::IsInFocus()
+{
+ if (GetParent())
+ return GetParent()->HasFocus(this);
+
+ return false;
+}
+
+//=============================================================================
+/**
+ * Handles the tab button in controls
+ */
+void CControl::OnTab()
+{
+ // Go through the children... if there is a focus, then get the next control
+ ControlGraph::SIterator thePos = ControlGraph::GetChildren(*this);
+ bool theFoundFlag = false;
+ if (m_ControlData->m_Focus) {
+ while (!thePos.IsDone() && !theFoundFlag) {
+ std::shared_ptr<CControlData> theCurrentControl = (*thePos);
+ if (theCurrentControl == m_ControlData->m_Focus) {
+ ++thePos;
+ while (!thePos.IsDone() && !theFoundFlag) {
+ std::shared_ptr<CControlData> theNextFocusCanidate = (*thePos);
+ if (theNextFocusCanidate->CanGainFocus()) {
+ m_ControlData->m_Focus->OnLoseFocus();
+ theFoundFlag = true;
+ m_ControlData->m_Focus = theNextFocusCanidate;
+ m_ControlData->m_Focus->SetFocusToFirstAvailable();
+ } else {
+ ++thePos;
+ }
+ }
+ } else {
+ ++thePos;
+ }
+ }
+ // If we didn't find it and we have a parent, then allow the parent to decide
+ if (!theFoundFlag) {
+ m_ControlData->m_Focus->OnLoseFocus();
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ if (GetParent())
+ GetParent()->OnTab();
+ else
+ SetFocusToFirstAvailable();
+ }
+ }
+ // If no focus, then go to first available control
+ else {
+ SetFocusToFirstAvailable();
+ }
+}
+
+//=============================================================================
+/**
+ * Handles the shift tab button in controls
+ */
+void CControl::OnReverseTab()
+{
+ // Go through the children in reverse order... if there is a focus, then get the next control
+ ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ bool theFoundFlag = false;
+ if (m_ControlData->m_Focus) {
+ while (!thePos.IsDone() && !theFoundFlag) {
+ std::shared_ptr<CControlData> theCurrentControl = (*thePos);
+ if (theCurrentControl == m_ControlData->m_Focus) {
+ ++thePos;
+ while (!thePos.IsDone() && !theFoundFlag) {
+ std::shared_ptr<CControlData> theNextFocusCanidate = (*thePos);
+ if (theNextFocusCanidate->CanGainFocus()) {
+ m_ControlData->m_Focus->OnLoseFocus();
+ theFoundFlag = true;
+ m_ControlData->m_Focus = theNextFocusCanidate;
+ m_ControlData->m_Focus->SetFocusToLastAvailable();
+ } else {
+ ++thePos;
+ }
+ }
+ } else {
+ ++thePos;
+ }
+ }
+ // If we didn't find it and we have a parent, then allow the parent to decide
+ if (!theFoundFlag) {
+ m_ControlData->m_Focus->OnLoseFocus();
+ m_ControlData->m_Focus = std::shared_ptr<CControlData>();
+ if (GetParent())
+ GetParent()->OnReverseTab();
+ else
+ SetFocusToLastAvailable();
+ }
+ }
+
+ // If no focus, then go to last available control
+ else {
+ SetFocusToLastAvailable();
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the focus to the first available child control
+ */
+void CControl::SetFocusToFirstAvailable()
+{
+ bool theFlag = false;
+ OnGainFocus();
+
+ // if there are any child controls, then go through them
+ for (ControlGraph::SIterator thePos = ControlGraph::GetChildren(*this);
+ !thePos.IsDone() && !theFlag; ++thePos) {
+ std::shared_ptr<CControlData> theControl = (*thePos);
+ if (theControl->CanGainFocus()) {
+ m_ControlData->m_Focus = theControl;
+ m_ControlData->m_Focus->SetFocusToFirstAvailable();
+ theFlag = true;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the focus to the last available child control
+ */
+void CControl::SetFocusToLastAvailable()
+{
+ bool theFlag = false;
+ OnGainFocus();
+
+ // if there are any child controls, then go through them
+ for (ControlGraph::SReverseIterator thePos = ControlGraph::GetRChildren(*this);
+ !thePos.IsDone() && !theFlag; ++thePos) {
+ std::shared_ptr<CControlData> theControl = (*thePos);
+ if (theControl->CanGainFocus()) {
+ m_ControlData->m_Focus = theControl;
+ m_ControlData->m_Focus->SetFocusToLastAvailable();
+ theFlag = true;
+ }
+ }
+}
+
+//===============================================================================
+/**
+* Coverts the given point from local coordinates into global coordinates.
+* @param inPoint the point in local coordinates to be converted
+* @return The point translated to global coordinates
+*/
+CPt CControl::ClientToScreen(CPt inPoint)
+{
+ CPt theFinalPt = inPoint + m_ControlData->m_Position;
+
+ if (GetParent())
+ theFinalPt = GetParent()->ClientToScreen(theFinalPt);
+ else if (m_ControlData->m_WindowListener)
+ theFinalPt = m_ControlData->m_WindowListener->ClientToScreen(theFinalPt);
+
+ return theFinalPt;
+}
+
+//===============================================================================
+/**
+* Coverts the given point from screen coordinates into local space.
+* @param inPoint the point in screen coordinates to be converted
+* @return The point translated to local, client coordinates
+*/
+CPt CControl::ScreenToClient(CPt inPoint)
+{
+ CPt theFinalPt = inPoint - m_ControlData->m_Position;
+
+ if (GetParent())
+ theFinalPt = GetParent()->ScreenToClient(theFinalPt);
+ else if (m_ControlData->m_WindowListener)
+ theFinalPt = m_ControlData->m_WindowListener->ScreenToClient(theFinalPt);
+
+ return theFinalPt;
+}
+
+//===============================================================================
+/**
+* Adds a focus listener to this control
+*/
+void CControl::AddFocusListener(CChildFocusListener *inListener)
+{
+ m_ControlData->m_FocusListeners.AddListener(inListener);
+}
+
+//===============================================================================
+/**
+* Removes a focus listener to this control
+*/
+void CControl::RemoveFocusListener(CChildFocusListener *inListener)
+{
+ m_ControlData->m_FocusListeners.RemoveListener(inListener);
+}
+
+//===============================================================================
+/**
+* tells anyone listeneing that the focus of this control has changed
+*/
+void CControl::FireFocusEvent(bool inStatus)
+{
+ m_ControlData->m_FocusListeners.FireEvent(&CChildFocusListener::OnChildFocusChange, inStatus);
+}
+
+//===============================================================================
+/**
+ * Get the platform specific view that this is embedded into.
+ * Used for when platform dependent controls have to be embedded or used.
+ */
+TPlatformView CControl::GetPlatformView()
+{
+ if (GetParent())
+ return GetParent()->GetPlatformView();
+ else if (m_ControlData->m_WindowListener)
+ return m_ControlData->m_WindowListener->GetPlatformView();
+ return nullptr;
+}
+
+bool CControl::IsMouseDown()
+{
+ return m_ControlData->m_IsMouseDown;
+}
+
+void CControl::OnMouseClick(CPt, Qt::KeyboardModifiers)
+{
+}
+
+//===============================================================================
+/**
+ * Sets the text of the tooltip for this control. If the string is empty, no
+ * tooltip will be shown.
+ * @param inText text of the tooltip
+ */
+void CControl::SetTooltipText(const Q3DStudio::CString &inText)
+{
+ m_ControlData->SetTooltipText(inText);
+}
+
+//===============================================================================
+/**
+ * @return the current tooltip text for this control
+ */
+Q3DStudio::CString CControl::GetTooltipText()
+{
+ return m_ControlData->GetTooltipText();
+}
+
+void CControl::GrabFocus(CControl *inControl)
+{
+ if (GetParent())
+ GetParent()->GrabFocus(this);
+
+ std::shared_ptr<CControlData> theNewFocus;
+ if (inControl)
+ theNewFocus = inControl->m_ControlData;
+
+ if (m_ControlData->m_Focus != theNewFocus) {
+ if (m_ControlData->m_Focus)
+ m_ControlData->m_Focus->OnLoseFocus();
+ m_ControlData->m_Focus = theNewFocus;
+ if (m_ControlData->m_Focus)
+ m_ControlData->m_Focus->OnGainFocus();
+ }
+}
+
+//===============================================================================
+/**
+ * Used to notify scrolling views that something should be visible.
+ */
+void CControl::EnsureVisible(CRct inRect)
+{
+ if (GetParent()) {
+ inRect.Offset(GetPosition());
+ GetParent()->EnsureVisible(inRect);
+ }
+}
+
+//===============================================================================
+/**
+ * Call to make this control visible.
+ */
+void CControl::EnsureVisible()
+{
+ CRct theRect(CPt(0, 0), GetSize());
+ EnsureVisible(theRect);
+}
+
+void CControl::OnParentChanged(CControl * /*inNewParent*/)
+{
+}
+
+void CControl::MarkChildrenNeedLayout()
+{
+ if (m_ControlData->m_ChildrenNeedLayout == false) {
+ for (ControlGraph::SIterator theIter = GetChildren(); theIter.IsDone() == false; ++theIter)
+ (*theIter)->MarkNeedsLayout();
+ m_ControlData->m_ChildrenNeedLayout = true;
+ }
+}
+
+void CControl::NotifyParentNeedsLayout()
+{
+ CControl *theParent(GetParent());
+ if (theParent)
+ theParent->MarkChildrenNeedLayout();
+}
+
+void CControl::MarkNeedsLayout()
+{
+ m_ControlData->m_NeedsLayout = true;
+}
+// Tell this control that one of its children need to be layed out.
+void CControl::SetLayout(CPt inSize, CPt inPosition)
+{
+ SetSize(inSize);
+ SetPosition(inPosition);
+ m_ControlData->m_NeedsLayout = false;
+}
+
+void CControl::LayoutChildren()
+{
+ for (ControlGraph::SIterator theIter = GetChildren(); theIter.IsDone() == false; ++theIter) {
+ std::shared_ptr<CControlData> theChild(*theIter);
+ // By default the children get the exact same layout that I do.
+ theChild->SetLayout(theChild->m_Size, theChild->m_Position);
+ }
+ m_ControlData->m_ChildrenNeedLayout = false;
+}
+
+void CControl::EnsureLayout()
+{
+ if (m_ControlData->m_NeedsLayout) {
+ if (IsVisible()) {
+ CControl *parent = GetParent();
+ if (parent)
+ parent->LayoutChildren();
+ }
+ m_ControlData->m_NeedsLayout = false;
+ }
+ if (m_ControlData->m_ChildrenNeedLayout) {
+ LayoutChildren();
+ m_ControlData->m_ChildrenNeedLayout = false;
+ }
+}
+
+void CControl::ChildrenChanged()
+{
+ MarkChildrenNeedLayout();
+ Invalidate();
+ m_ControlData->OnHierarchyChanged();
+}
+
+void CControl::setCursorIfNotSet(long cursor)
+{
+ if (cursor != m_cursorSet) {
+ if (m_cursorSet != -1)
+ qApp->restoreOverrideCursor();
+ m_cursorSet = cursor;
+ qApp->setOverrideCursor(CResourceCache::GetInstance()->GetCursor(cursor));
+ }
+}
+
+void CControl::resetCursor()
+{
+ if (m_cursorSet != -1) {
+ qApp->restoreOverrideCursor();
+ m_cursorSet = -1;
+ }
+}
+
+QCursor CControl::getCursor() const
+{
+ if (m_cursorSet != -1)
+ return CResourceCache::GetInstance()->GetCursor(m_cursorSet);
+ return QCursor();
+}
diff --git a/src/Authoring/Studio/Controls/Control.h b/src/Authoring/Studio/Controls/Control.h
new file mode 100644
index 00000000..0d2ea79e
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Control.h
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_CONTROL_H
+#define INCLUDED_CONTROL_H 1
+
+#pragma once
+
+#include "Pt.h"
+#include "Rct.h"
+#include "SafeArray.h"
+#include "GenericFunctor.h"
+#include "PlatformTypes.h"
+
+#include "DropTarget.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/signals/trackable.hpp>
+#include "ControlGraphIterators.h"
+
+class CRenderer;
+class CContextMenu;
+class CUICFile;
+class IDragable;
+class CAsset;
+class CStudioApp;
+
+class QMenu;
+
+namespace Q3DStudio {
+namespace Control {
+ class CControlData;
+ using std::pair;
+ using std::make_pair;
+ using std::vector;
+}
+}
+
+// this functor is used to tell when a child loses focus the boolean should be true if the child
+// gains focus
+GENERIC_FUNCTOR_1(CChildFocusListener, OnChildFocusChange, bool)
+
+#ifdef _WIN32
+typedef HWND TPlatformView;
+#else
+typedef void *TPlatformView;
+#endif
+
+class CControlWindowListener
+{
+public:
+ virtual void OnControlInvalidated() = 0;
+ virtual long DoPopup(QMenu *inMenu, CPt inLocation) = 0;
+ virtual CPt ClientToScreen(CPt inPoint) = 0;
+ virtual CPt ScreenToClient(CPt inPoint) = 0;
+ virtual TPlatformView GetPlatformView() = 0;
+ virtual void SetIsDragging(bool inIsDragging) = 0;
+ virtual void ShowTooltips(CPt inLocation, const Q3DStudio::CString &inText) = 0;
+ virtual void HideTooltips() = 0;
+ virtual void DoStartDrag(IDragable *inDragable) = 0;
+ virtual void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileList) = 0;
+ virtual void ShowMoveableWindow(CPt inLocation, const Q3DStudio::CString &inText,
+ CRct inBoundingRct) = 0;
+ virtual void HideMoveableWindow() = 0;
+};
+
+namespace Q3DStudio {
+namespace Control {
+ class CControlData;
+}
+}
+
+class CControl : public boost::BOOST_SIGNALS_NAMESPACE::trackable
+{
+
+ CControl(CControl &inOther);
+ CControl &operator=(CControl &inOther);
+
+public:
+ CControl();
+ virtual ~CControl();
+
+ DEFINE_OBJECT_COUNTER(CControl)
+
+ CControl *GetParent();
+ const CControl *GetParent() const;
+
+ virtual void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation = false);
+ virtual void Draw(CRenderer *inRenderer);
+ virtual void NotifyNotInClipRect();
+
+ virtual CPt GetPosition() const;
+ virtual void SetPosition(CPt inPosition);
+ void SetPosition(long inX, long inY);
+
+ virtual CPt GetSize() const;
+ virtual void SetSize(CPt inSize);
+ void SetSize(long inWidth, long inHeight);
+ virtual void OnSizeChanged(CPt inSize);
+
+ virtual CPt GetMinimumSize();
+ virtual void SetMinimumSize(CPt inSize);
+
+ virtual CPt GetMaximumSize();
+ virtual void SetMaximumSize(CPt inSize);
+
+ virtual CPt GetPreferredSize();
+ virtual void SetPreferredSize(CPt inSize);
+
+ virtual void SetAbsoluteSize(CPt inSize);
+
+ virtual void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseRUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual bool OnMouseHover(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ /**
+ Note that just overriding this isn't enough, you need to call
+ m_ControlData->SetMouseWheelEnabled( true )
+ in order to receive mouse wheel events
+ */
+ virtual bool OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags);
+ virtual bool OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags);
+ virtual bool OnKeyUp(unsigned int inChar, Qt::KeyboardModifiers inFlags);
+ virtual bool OnChar(const QString &inChar, Qt::KeyboardModifiers inFlags);
+ virtual void OnLoseFocus();
+ virtual void OnGainFocus();
+ virtual bool CanGainFocus();
+ virtual bool IsInFocus();
+ void OnTab();
+ void OnReverseTab();
+ void SetFocusToFirstAvailable();
+ void SetFocusToLastAvailable();
+
+ virtual CDropTarget *FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags);
+
+ virtual void AddChild(CControl *inControl, CControl *inInsertBefore = NULL);
+ virtual void RemoveChild(CControl *inControl);
+ virtual void RemoveAllChildren();
+ virtual long GetChildIndex(CControl *inChildControl);
+ virtual CControl *FindChildByName(const Q3DStudio::CString &inName);
+ CControl *FocusedChild();
+
+ virtual bool IsMouseOver() const;
+
+ virtual bool HitTest(const CPt &inPoint) const;
+ virtual bool IsInRect(const CRct &inRect) const;
+
+ virtual void Invalidate(bool inInvalidate = true);
+ virtual void InvalidateRect(const CRct &inRect);
+ virtual bool IsInvalidated() const;
+
+ virtual void OnChildInvalidated();
+ virtual bool IsChildInvalidated() const;
+
+ virtual void SetVisible(bool inIsVisible);
+ virtual bool IsVisible() const;
+ virtual void OnVisibleStateChange(bool inIsVisible);
+ virtual void OnParentVisibleStateChanged(bool inIsVisible);
+
+ virtual void SetParentEnabled(bool inParentEnabled);
+ virtual void SetEnabled(bool inIsEnabled);
+ virtual bool IsEnabled() const;
+ bool GetEnabledFlag();
+ void SetEnabledFlag(bool inIsEnabled);
+
+ void SetWindowListener(CControlWindowListener *inListener);
+ CControlWindowListener *GetWindowListener();
+
+ virtual void OnChildSizeChanged(CControl *inChild);
+ virtual void ResetMinMaxPref(){}
+
+ void SetName(const Q3DStudio::CString &inName);
+ Q3DStudio::CString GetName();
+
+ virtual void BeginDrawChildren(CRenderer *inRenderer);
+
+ virtual long DoPopup(QMenu *inContextMenu, CPt inPoint);
+ virtual void RemoveUberControl(CControl *inControl);
+ virtual void OffsetPosition(CPt inOffset);
+
+ virtual CPt GetGlobalPosition(CPt inChildPoint) const;
+ virtual UICRenderDevice GetPlatformDevice();
+ bool IsChildPlatformDevice(UICRenderDevice inDevice);
+ virtual void ShowMoveableWindow(CPt inLocation, const Q3DStudio::CString &inText, CRct inBoundingRct);
+ virtual void HideMoveableWindow();
+ CControl *GetFirstChild();
+ bool HasFocus(CControl *inControl);
+ virtual void GrabFocus(CControl *inControl);
+
+ virtual CPt ClientToScreen(CPt inPoint);
+ virtual CPt ScreenToClient(CPt inPoint);
+
+ void AddFocusListener(CChildFocusListener *inListener);
+ void RemoveFocusListener(CChildFocusListener *inListener);
+ void FireFocusEvent(bool inStatus);
+
+ void SetTooltipText(const Q3DStudio::CString &inText);
+ Q3DStudio::CString GetTooltipText();
+
+ virtual void EnsureVisible(CRct inRect);
+ void EnsureVisible();
+
+ virtual void OnParentChanged(CControl *inNewParent);
+
+ virtual void MarkChildrenNeedLayout();
+ virtual void MarkNeedsLayout();
+ // Tell our parent that we (and all our siblings) need to be
+ // laid out.
+ virtual void NotifyParentNeedsLayout();
+ // Tell this control that one of its children need to be layed out.
+ virtual void SetLayout(CPt inSize, CPt inPosition);
+ virtual void LayoutChildren();
+ virtual void EnsureLayout();
+
+ virtual void ChildrenChanged();
+
+ Q3DStudio::Control::ControlGraph::SIterator GetChildren();
+ Q3DStudio::Control::ControlGraph::SReverseIterator GetReverseChildren();
+
+protected: ///< Current size of this control
+ // Member Functions
+
+ long GetChildCount();
+ TPlatformView GetPlatformView();
+ bool IsMouseDown();
+ void setCursorIfNotSet(long cursor);
+ void resetCursor();
+ QCursor getCursor() const;
+
+ std::shared_ptr<Q3DStudio::Control::CControlData> m_ControlData;
+ long m_cursorSet;
+};
+#endif // INCLUDED_CONTROL_H
diff --git a/src/Authoring/Studio/Controls/ControlData.cpp b/src/Authoring/Studio/Controls/ControlData.cpp
new file mode 100644
index 00000000..65122537
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ControlData.cpp
@@ -0,0 +1,763 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "ControlData.h"
+#include "ControlGraph.h"
+#include "Control.h"
+
+#include <QMenu>
+
+using namespace Q3DStudio::Control;
+using Q3DStudio::CString;
+
+CControlData::CControlData(CControl &inControl)
+ : m_Control(&inControl)
+ , m_MinSize(0, 0)
+ , m_MaxSize(LONG_MAX, LONG_MAX)
+ , m_PrefSize(10, 10)
+ , m_IsMouseOver(false)
+ , m_IsInvalidated(true)
+ , m_IsChildInvalidated(false)
+ , m_IsVisible(true)
+ , m_IsEnabled(true)
+ , m_IsParentEnabled(true)
+ , m_HasFocus(false)
+ , m_IsMouseDown(false)
+ , m_ShowTooltips(false)
+ , m_NeedsLayout(true)
+ , m_ChildrenNeedLayout(true)
+ , m_WindowListener(NULL)
+{
+}
+
+CControlData::~CControlData()
+{
+}
+
+void CControlData::ReleaseControl()
+{
+ if (m_Control) {
+ ControlGraph::RemoveNode(*m_Control);
+ m_Control = nullptr;
+ }
+}
+
+std::shared_ptr<CControlData> CControlData::CreateControlData(CControl &inControl)
+{
+ std::shared_ptr<CControlData> retval =
+ std::make_shared<CControlData>(std::ref(inControl));
+ ControlGraph::AddNode(retval);
+ return retval;
+}
+
+CControl *CControlData::GetControl()
+{
+ return m_Control;
+}
+
+CControl *CControlData::GetParent()
+{
+
+ if (m_Control) {
+ std::shared_ptr<CControlData> theParent(ControlGraph::GetParent(*m_Control));
+ if (theParent)
+ return theParent->GetControl();
+ }
+ return nullptr;
+}
+
+void CControlData::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation)
+{
+ if (m_Control)
+ m_Control->OnDraw(inRenderer, inDirtyRect, inIgnoreValidation);
+}
+
+void CControlData::Draw(CRenderer *inRenderer)
+{
+ if (m_Control)
+ m_Control->Draw(inRenderer);
+}
+
+void CControlData::NotifyNotInClipRect()
+{
+ if (m_Control)
+ m_Control->NotifyNotInClipRect();
+}
+
+CPt CControlData::GetPosition() const
+{
+ if (m_Control)
+ return m_Control->GetPosition();
+ return CPt();
+}
+void CControlData::SetPosition(CPt inPosition)
+{
+ if (m_Control)
+ m_Control->SetPosition(inPosition);
+}
+void CControlData::SetPosition(long inX, long inY)
+{
+ SetPosition(CPt(inX, inY));
+}
+
+CPt CControlData::GetSize() const
+{
+ if (m_Control)
+ return m_Control->GetSize();
+ return CPt();
+}
+void CControlData::SetSize(CPt inSize)
+{
+ if (m_Control)
+ m_Control->SetSize(inSize);
+}
+void CControlData::SetSize(long inWidth, long inHeight)
+{
+ SetSize(CPt(inWidth, inHeight));
+}
+
+CPt CControlData::GetMinimumSize()
+{
+ if (m_Control)
+ return m_Control->GetMinimumSize();
+ return CPt();
+}
+void CControlData::SetMinimumSize(CPt inSize)
+{
+ if (m_Control)
+ m_Control->SetMinimumSize(inSize);
+}
+
+CPt CControlData::GetMaximumSize()
+{
+ if (m_Control)
+ return m_Control->GetMaximumSize();
+ return CPt();
+}
+void CControlData::SetMaximumSize(CPt inSize)
+{
+ if (m_Control)
+ m_Control->SetMaximumSize(inSize);
+}
+
+CPt CControlData::GetPreferredSize()
+{
+ if (m_Control)
+ return m_Control->GetPreferredSize();
+ return CPt();
+}
+void CControlData::SetPreferredSize(CPt inSize)
+{
+ if (m_Control)
+ return m_Control->SetPreferredSize(inSize);
+}
+
+void CControlData::SetAbsoluteSize(CPt inSize)
+{
+ if (m_Control)
+ m_Control->SetAbsoluteSize(inSize);
+}
+void CControlData::SetMouseDown(bool inMouseDown)
+{
+ m_IsMouseDown = inMouseDown;
+}
+
+void CControlData::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ m_Control->OnMouseMove(inPoint, inFlags);
+}
+void CControlData::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ m_Control->OnMouseOver(inPoint, inFlags);
+}
+void CControlData::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ m_Control->OnMouseOut(inPoint, inFlags);
+}
+bool CControlData::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnMouseDown(inPoint, inFlags);
+ return false;
+}
+bool CControlData::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnMouseRDown(inPoint, inFlags);
+ return false;
+}
+void CControlData::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ m_Control->OnMouseUp(inPoint, inFlags);
+}
+void CControlData::OnMouseRUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ m_Control->OnMouseRUp(inPoint, inFlags);
+}
+void CControlData::OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ m_Control->OnMouseClick(inPoint, inFlags);
+}
+bool CControlData::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnMouseDoubleClick(inPoint, inFlags);
+ return false;
+}
+bool CControlData::OnMouseHover(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnMouseHover(inPoint, inFlags);
+ return false;
+}
+bool CControlData::OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnMouseWheel(inPoint, inAmount, inFlags);
+ return false;
+}
+bool CControlData::OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnKeyDown(inChar, inFlags);
+ return false;
+}
+bool CControlData::OnKeyUp(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnKeyUp(inChar, inFlags);
+ return false;
+}
+bool CControlData::OnChar(const QString &inChar, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control)
+ return m_Control->OnChar(inChar, inFlags);
+ return false;
+}
+void CControlData::OnLoseFocus()
+{
+ if (m_Control) {
+ m_Control->OnLoseFocus();
+ }
+}
+void CControlData::OnGainFocus()
+{
+ if (m_Control) {
+ m_Control->OnGainFocus();
+ }
+}
+bool CControlData::CanGainFocus()
+{
+ if (m_Control) {
+ return m_Control->CanGainFocus();
+ }
+ return false;
+}
+bool CControlData::IsInFocus()
+{
+ if (m_Control) {
+ return m_Control->IsInFocus();
+ }
+ return false;
+}
+void CControlData::OnTab()
+{
+ if (m_Control) {
+ m_Control->OnTab();
+ }
+}
+void CControlData::OnReverseTab()
+{
+ if (m_Control) {
+ m_Control->OnReverseTab();
+ }
+}
+void CControlData::SetFocusToFirstAvailable()
+{
+ if (m_Control) {
+ m_Control->SetFocusToFirstAvailable();
+ }
+}
+void CControlData::SetFocusToLastAvailable()
+{
+ if (m_Control) {
+ m_Control->SetFocusToLastAvailable();
+ }
+}
+void CControlData::ChildrenChanged()
+{
+ if (m_Control)
+ m_Control->ChildrenChanged();
+}
+
+void CControlData::SetMouseWheelEnabled(bool inEnabled)
+{
+ if (m_Control == nullptr)
+ return;
+
+ if (m_MouseWheelState.m_Enabled != inEnabled) {
+ m_MouseWheelState.m_Enabled = inEnabled;
+ ControlEventState::Enum theNewState;
+ if (m_MouseWheelState.m_Enabled == false)
+ theNewState = ControlEventState::Unknown;
+ else
+ theNewState = ControlEventState::Listening;
+ SetMouseWheelEventState(theNewState);
+ }
+}
+
+void CControlData::OnHierarchyChanged()
+{
+ ControlEventState::Enum theNewState;
+ if (m_MouseWheelState.m_Enabled)
+ theNewState = ControlEventState::Listening;
+ else
+ theNewState = ControlEventState::Unknown;
+ SetMouseWheelEventState(theNewState);
+}
+
+/**
+ Look at hierarchy information to figure out which events should
+ trickle down the tree to here (or deeper). Recursive call that
+ may take some time to complete.
+*/
+void CControlData::UpdateMouseWheelEventState()
+{
+ if (m_Control == nullptr)
+ return;
+ ControlEventState::Enum theNewState(ControlEventState::Ignoring);
+ if (m_MouseWheelState.m_Enabled == true)
+ theNewState = ControlEventState::Listening;
+ else if (m_MouseWheelState.m_EventState == ControlEventState::Unknown && m_Control != nullptr) {
+ for (ControlGraph::SIterator theIter(ControlGraph::GetChildren(*m_Control));
+ theIter.IsDone() == false; ++theIter) {
+ if (theIter->GetMouseWheelEventState() == ControlEventState::Listening) {
+ theNewState = ControlEventState::Listening;
+ break;
+ }
+ }
+ }
+ SetMouseWheelEventState(theNewState);
+}
+
+/**
+ Update our mouse wheel state and notify our parent if necessary. Note that we
+ can't set our event state to ignoring without checking all of our children
+ so the result of this function is that our event state is either listening
+ or unknown.
+*/
+void CControlData::SetMouseWheelEventState(ControlEventState::Enum inNewState)
+{
+ if (m_MouseWheelState.m_EventState != inNewState) {
+ m_MouseWheelState.m_EventState = inNewState;
+ std::shared_ptr<CControlData> theParent = ControlGraph::GetParent(*m_Control);
+ if (theParent)
+ theParent->ChildMouseWheelEventStateChanged(m_MouseWheelState.m_EventState);
+ }
+}
+
+/**
+ When a given child notifies us that its event state has changed then we can update
+ our state. We can't set the state to ignoring unless we *know* all of our
+ children are ignoring mouse wheel.
+ */
+void CControlData::ChildMouseWheelEventStateChanged(ControlEventState::Enum inNewState)
+{
+ ControlEventState::Enum theNewState;
+ if (inNewState == ControlEventState::Listening || m_MouseWheelState.m_Enabled == true)
+ theNewState = ControlEventState::Listening;
+ else
+ theNewState = ControlEventState::Unknown;
+
+ SetMouseWheelEventState(theNewState);
+}
+
+ControlEventState::Enum CControlData::GetMouseWheelEventState()
+{
+ if (m_MouseWheelState.m_EventState == ControlEventState::Unknown)
+ UpdateMouseWheelEventState();
+ assert(m_MouseWheelState.m_EventState != ControlEventState::Unknown);
+ return m_MouseWheelState.m_EventState;
+}
+
+CDropTarget *CControlData::FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_Control) {
+ return m_Control->FindDropCandidate(inMousePoint, inFlags);
+ }
+ return nullptr;
+}
+
+void CControlData::AddChild(CControl *inControl, CControl *inInsertBefore)
+{
+ if (m_Control)
+ m_Control->AddChild(inControl, inInsertBefore);
+}
+
+void CControlData::RemoveChild(CControl *inControl)
+{
+ if (m_Control)
+ m_Control->RemoveChild(inControl);
+}
+void CControlData::RemoveAllChildren()
+{
+ if (m_Control)
+ m_Control->RemoveAllChildren();
+}
+long CControlData::GetChildIndex(CControl *inChildControl)
+{
+ if (m_Control)
+ return m_Control->GetChildIndex(inChildControl);
+ return 0;
+}
+CControl *CControlData::FindChildByName(const Q3DStudio::CString &inName)
+{
+ if (m_Control) {
+ m_Control->FindChildByName(inName);
+ }
+ return nullptr;
+}
+
+bool CControlData::IsMouseOver() const
+{
+ if (m_Control) {
+ return m_Control->IsMouseOver();
+ }
+ return false;
+}
+
+bool CControlData::HitTest(const CPt &inPoint) const
+{
+ if (m_Control) {
+ return m_Control->HitTest(inPoint);
+ }
+ return false;
+}
+bool CControlData::IsInRect(const CRct &inRect) const
+{
+ if (m_Control) {
+ return m_Control->IsInRect(inRect);
+ }
+ return false;
+}
+
+void CControlData::Invalidate(bool inInvalidate)
+{
+ if (m_Control) {
+ m_Control->Invalidate(inInvalidate);
+ }
+}
+void CControlData::InvalidateRect(const CRct &inRect)
+{
+ if (m_Control) {
+ m_Control->InvalidateRect(inRect);
+ }
+}
+bool CControlData::IsInvalidated() const
+{
+ return m_IsInvalidated;
+}
+
+void CControlData::OnChildInvalidated()
+{
+ if (m_Control) {
+ m_Control->OnChildInvalidated();
+ }
+}
+bool CControlData::IsChildInvalidated() const
+{
+ if (m_Control) {
+ return m_Control->IsChildInvalidated();
+ }
+ return false;
+}
+
+void CControlData::SetVisible(bool inIsVisible)
+{
+ if (m_Control) {
+ m_Control->SetVisible(inIsVisible);
+ }
+}
+bool CControlData::IsVisible() const
+{
+ if (m_Control) {
+ return m_Control->IsVisible();
+ }
+ return false;
+}
+void CControlData::OnVisibleStateChange(bool inIsVisible)
+{
+ if (m_Control) {
+ m_Control->OnVisibleStateChange(inIsVisible);
+ }
+}
+void CControlData::OnParentVisibleStateChanged(bool inIsVisible)
+{
+ if (m_Control) {
+ m_Control->OnParentVisibleStateChanged(inIsVisible);
+ }
+}
+
+void CControlData::SetParentEnabled(bool inParentEnabled)
+{
+ if (m_Control) {
+ m_Control->SetParentEnabled(inParentEnabled);
+ }
+}
+void CControlData::SetEnabled(bool inIsEnabled)
+{
+ if (m_Control) {
+ m_Control->SetEnabled(inIsEnabled);
+ }
+}
+
+bool CControlData::IsEnabled() const
+{
+ return m_IsEnabled && m_IsParentEnabled;
+}
+bool CControlData::GetEnabledFlag()
+{
+ return m_IsEnabled;
+}
+void CControlData::SetEnabledFlag(bool inIsEnabled)
+{
+ m_IsEnabled = inIsEnabled;
+}
+
+void CControlData::SetWindowListener(CControlWindowListener *inListener)
+{
+ m_WindowListener = inListener;
+}
+CControlWindowListener *CControlData::GetWindowListener()
+{
+ return m_WindowListener;
+}
+
+void CControlData::OnChildSizeChanged(CControl *inChild)
+{
+ if (m_Control) {
+ m_Control->OnChildSizeChanged(inChild);
+ }
+}
+void CControlData::ResetMinMaxPref()
+{
+ if (m_Control) {
+ m_Control->ResetMinMaxPref();
+ }
+}
+
+void CControlData::SetName(CString inName)
+{
+ m_ControlName = inName;
+}
+CString CControlData::GetName()
+{
+ return m_ControlName;
+}
+
+void CControlData::BeginDrawChildren(CRenderer *inRenderer)
+{
+ if (m_Control) {
+ m_Control->BeginDrawChildren(inRenderer);
+ }
+}
+
+long CControlData::DoPopup(QMenu *inContextMenu, CPt inPoint)
+{
+ if (m_Control) {
+ return m_Control->DoPopup(inContextMenu, inPoint);
+ }
+ return 0;
+}
+void CControlData::RemoveUberControl(CControl *inControl)
+{
+ if (m_Control) {
+ m_Control->RemoveUberControl(inControl);
+ }
+}
+void CControlData::OffsetPosition(CPt inOffset)
+{
+ if (m_Control) {
+ m_Control->OffsetPosition(inOffset);
+ }
+}
+
+CPt CControlData::GetGlobalPosition(CPt inChildPoint) const
+{
+ if (m_Control) {
+ return m_Control->GetGlobalPosition(inChildPoint);
+ }
+ return CPt();
+}
+UICRenderDevice CControlData::GetPlatformDevice()
+{
+ if (m_Control) {
+ return m_Control->GetPlatformDevice();
+ }
+ return nullptr;
+}
+bool CControlData::IsChildPlatformDevice(UICRenderDevice inDevice)
+{
+ if (m_Control) {
+ return m_Control->IsChildPlatformDevice(inDevice);
+ }
+ return false;
+}
+void CControlData::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct)
+{
+ if (m_Control) {
+ m_Control->ShowMoveableWindow(inLocation, inText, inBoundingRct);
+ }
+}
+void CControlData::HideMoveableWindow()
+{
+ if (m_Control) {
+ m_Control->HideMoveableWindow();
+ }
+}
+CControl *CControlData::GetFirstChild()
+{
+ if (m_Control) {
+ m_Control->GetFirstChild();
+ }
+ return nullptr;
+}
+bool CControlData::HasFocus(CControl *inControl)
+{
+ if (m_Control) {
+ return m_Control->HasFocus(inControl);
+ }
+ return false;
+}
+void CControlData::GrabFocus(CControl *inControl)
+{
+ if (m_Control) {
+ m_Control->GrabFocus(inControl);
+ }
+}
+
+CPt CControlData::ClientToScreen(CPt inPoint)
+{
+ if (m_Control) {
+ return m_Control->ClientToScreen(inPoint);
+ }
+ return CPt();
+}
+CPt CControlData::ScreenToClient(CPt inPoint)
+{
+ if (m_Control) {
+ return m_Control->ScreenToClient(inPoint);
+ }
+ return CPt();
+}
+
+void CControlData::AddFocusListener(CChildFocusListener *inListener)
+{
+ if (m_Control) {
+ m_Control->AddFocusListener(inListener);
+ }
+}
+void CControlData::RemoveFocusListener(CChildFocusListener *inListener)
+{
+ if (m_Control) {
+ m_Control->RemoveFocusListener(inListener);
+ }
+}
+void CControlData::FireFocusEvent(bool inStatus)
+{
+ if (m_Control) {
+ m_Control->FireFocusEvent(inStatus);
+ }
+}
+
+void CControlData::SetTooltipText(const Q3DStudio::CString &inText)
+{
+ m_TooltipText = inText;
+}
+CString CControlData::GetTooltipText()
+{
+ return m_TooltipText;
+}
+
+void CControlData::EnsureVisible(CRct inRect)
+{
+ if (m_Control) {
+ m_Control->EnsureVisible(inRect);
+ }
+}
+void CControlData::EnsureVisible()
+{
+ if (m_Control) {
+ m_Control->EnsureVisible();
+ }
+}
+
+void CControlData::OnParentChanged(CControl *inControl)
+{
+ if (m_Control)
+ m_Control->OnParentChanged(inControl);
+}
+
+void CControlData::NotifyParentNeedsLayout()
+{
+ if (m_Control)
+ m_Control->NotifyParentNeedsLayout();
+}
+void CControlData::MarkChildrenNeedLayout()
+{
+ if (m_Control)
+ m_Control->MarkChildrenNeedLayout();
+}
+void CControlData::MarkNeedsLayout()
+{
+ if (m_Control)
+ m_Control->MarkNeedsLayout();
+}
+// Tell this control that one of its children need to be layed out.
+void CControlData::SetLayout(CPt inSize, CPt inPosition)
+{
+ if (m_Control)
+ m_Control->SetLayout(inSize, inPosition);
+}
+void CControlData::LayoutChildren()
+{
+ if (m_Control)
+ m_Control->LayoutChildren();
+}
+void CControlData::EnsureLayout()
+{
+ if (m_Control)
+ m_Control->EnsureLayout();
+}
diff --git a/src/Authoring/Studio/Controls/ControlData.h b/src/Authoring/Studio/Controls/ControlData.h
new file mode 100644
index 00000000..83ebaf7d
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ControlData.h
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef CONTROLDATAH
+#define CONTROLDATAH
+
+#include "DropTarget.h"
+#include "Pt.h"
+#include "Rct.h"
+#include "Multicaster.h"
+#include "UICString.h"
+
+class CControl;
+class CControlWindowListener;
+class CChildFocusListener;
+class CRenderer;
+
+class QMenu;
+
+namespace Q3DStudio {
+namespace Control {
+
+ using namespace std;
+
+ struct ControlEventState
+ {
+ enum Enum {
+ Unknown = 0,
+ Listening,
+ Ignoring,
+ };
+ };
+
+ struct SControlEventData
+ {
+ bool m_Enabled;
+ ControlEventState::Enum m_EventState;
+ SControlEventData()
+ : m_Enabled(false)
+ , m_EventState(ControlEventState::Ignoring)
+ {
+ }
+ };
+
+ // Smart pointer object that referees access to a control.
+ class CControlData
+ {
+ Q_DISABLE_COPY(CControlData)
+ public:
+ friend class ::CControl;
+ friend class std::shared_ptr<CControlData>;
+
+ private:
+ // The physical address of the control is the key in the graph
+ // that points to this data item.
+ CControl *m_Control;
+
+ CPt m_Size; ///< Current size of this control
+
+ CPt m_Position; ///< Position of this control, relative to the parent
+ CPt m_MinSize; ///< Minimum allowed size of this control
+ CPt m_MaxSize; ///< Maximum allowed size of this contrl
+ CPt m_PrefSize; ///< Preferred size of this control
+
+ bool m_IsMouseOver; ///< True if the mouse is over this control
+ bool m_IsInvalidated; ///< True if this control needs to be redrawn
+ bool m_IsChildInvalidated; ///< True if a child of this control is invalidated.
+ bool m_IsVisible; ///< True if this control is to be visible
+ bool m_IsEnabled; ///< True if this control is enabled.
+ bool m_IsParentEnabled;
+ bool m_HasFocus;
+ bool m_IsMouseDown;
+ bool m_ShowTooltips; ///< Specifies whether or not tooltips should be shown
+ bool m_NeedsLayout; ///< True if this control needs to be layed out.
+ bool m_ChildrenNeedLayout; ///< True if my children need layout
+ SControlEventData
+ m_MouseWheelState; ///< Tracks whether this object cares about mouse wheel.
+
+ Q3DStudio::CString m_TooltipText; ///< Text to be displayed for tooltips
+
+ std::shared_ptr<CControlData> m_Focus; ///< Child control that has the focus.
+ std::shared_ptr<CControlData> m_MouseFocus; ///< Child control that got the mouse down.
+ CControlWindowListener
+ *m_WindowListener; ///< External listener for when this control is invalidated.
+
+ Q3DStudio::CString m_ControlName;
+ CMulticaster<CChildFocusListener *> m_FocusListeners; ///< Used for focus changes
+
+ public:
+ CControlData(CControl &inControl);
+ ~CControlData();
+
+ CControl *GetControl();
+
+ CControl *GetParent();
+
+ void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation = false);
+ void Draw(CRenderer *inRenderer);
+ void NotifyNotInClipRect();
+
+ CPt GetPosition() const;
+ void SetPosition(CPt inPosition);
+ void SetPosition(long inX, long inY);
+
+ CPt GetSize() const;
+ void SetSize(CPt inSize);
+ void SetSize(long inWidth, long inHeight);
+
+ CPt GetMinimumSize();
+ void SetMinimumSize(CPt inSize);
+
+ CPt GetMaximumSize();
+ void SetMaximumSize(CPt inSize);
+
+ CPt GetPreferredSize();
+ void SetPreferredSize(CPt inSize);
+
+ void SetAbsoluteSize(CPt inSize);
+
+ void SetMouseDown(bool inMouseDown);
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ void OnMouseRUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ void OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ bool OnMouseHover(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ bool OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags);
+ bool OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags);
+ bool OnKeyUp(unsigned int inChar, Qt::KeyboardModifiers inFlags);
+ bool OnChar(const QString &inChar, Qt::KeyboardModifiers inFlags);
+ void OnLoseFocus();
+ void OnGainFocus();
+ bool CanGainFocus();
+ bool IsInFocus();
+ void OnTab();
+ void OnReverseTab();
+ void SetFocusToFirstAvailable();
+ void SetFocusToLastAvailable();
+ void ChildrenChanged();
+
+ // Mouse wheel event state.
+ void SetMouseWheelEnabled(bool inEnabled);
+ /**
+ Callback so we can update any event states to unknown
+ from ignoring forcing a refresh of hierarchy event information
+ the next time the event state is queried.
+ */
+ void OnHierarchyChanged();
+ /**
+ If our event state is unknown, force resolution by asking children what their
+ event state is. Else return our event state.
+ */
+ ControlEventState::Enum GetMouseWheelEventState();
+
+ protected:
+ void UpdateMouseWheelEventState();
+ void ChildMouseWheelEventStateChanged(ControlEventState::Enum inNewState);
+ void SetMouseWheelEventState(ControlEventState::Enum inNewState);
+
+ public:
+ CDropTarget *FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags);
+
+ void AddChild(CControl *inControl, CControl *inInsertBefore = NULL);
+ void RemoveChild(CControl *inControl);
+ void RemoveAllChildren();
+ long GetChildIndex(CControl *inChildControl);
+ CControl *FindChildByName(const Q3DStudio::CString &inName);
+
+ bool IsMouseOver() const;
+
+ bool HitTest(const CPt &inPoint) const;
+ bool IsInRect(const CRct &inRect) const;
+
+ void Invalidate(bool inInvalidate = true);
+ void InvalidateRect(const CRct &inRect);
+ bool IsInvalidated() const;
+
+ void OnChildInvalidated();
+ bool IsChildInvalidated() const;
+
+ void SetVisible(bool inIsVisible);
+ bool IsVisible() const;
+ void OnVisibleStateChange(bool inIsVisible);
+ void OnParentVisibleStateChanged(bool inIsVisible);
+
+ void SetParentEnabled(bool inParentEnabled);
+ void SetEnabled(bool inIsEnabled);
+ bool IsEnabled() const;
+ bool GetEnabledFlag();
+ void SetEnabledFlag(bool inIsEnabled);
+
+ void SetWindowListener(CControlWindowListener *inListener);
+ CControlWindowListener *GetWindowListener();
+
+ void OnChildSizeChanged(CControl *inChild);
+ void ResetMinMaxPref();
+
+ void SetName(Q3DStudio::CString inName);
+ Q3DStudio::CString GetName();
+
+ void BeginDrawChildren(CRenderer *inRenderer);
+
+ long DoPopup(QMenu *inContextMenu, CPt inPoint);
+ void RemoveUberControl(CControl *inControl);
+ void OffsetPosition(CPt inOffset);
+
+ CPt GetGlobalPosition(CPt inChildPoint) const;
+ UICRenderDevice GetPlatformDevice();
+ bool IsChildPlatformDevice(UICRenderDevice inDevice);
+ void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct);
+ void HideMoveableWindow();
+ CControl *GetFirstChild();
+ bool HasFocus(CControl *inControl);
+ void GrabFocus(CControl *inControl);
+
+ CPt ClientToScreen(CPt inPoint);
+ CPt ScreenToClient(CPt inPoint);
+
+ void AddFocusListener(CChildFocusListener *inListener);
+ void RemoveFocusListener(CChildFocusListener *inListener);
+ void FireFocusEvent(bool inStatus);
+
+ void SetTooltipText(const Q3DStudio::CString &inText);
+ Q3DStudio::CString GetTooltipText();
+
+ void EnsureVisible(CRct inRect);
+ void EnsureVisible();
+
+ void OnParentChanged(CControl *inControl);
+
+ void NotifyParentNeedsLayout();
+ void MarkChildrenNeedLayout();
+ void MarkNeedsLayout();
+ // Tell this control that one of its children need to be layed out.
+ void SetLayout(CPt inSize, CPt inPosition);
+ void LayoutChildren();
+ void EnsureLayout();
+
+ private:
+ static std::shared_ptr<CControlData> CreateControlData(CControl &inControl);
+ void ReleaseControl(); // set the control to null, remove our graph representation
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Controls/ControlGraph.cpp b/src/Authoring/Studio/Controls/ControlGraph.cpp
new file mode 100644
index 00000000..912bd1a0
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ControlGraph.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "ControlGraph.h"
+#include "GraphImpl.h"
+#include "foundation/Qt3DSAssert.h"
+#include "Control.h"
+#include "ControlData.h"
+
+using namespace std;
+using namespace Q3DStudio;
+using namespace Q3DStudio::Graph;
+using namespace Q3DStudio::Control;
+using Q3DStudio::CString;
+
+namespace {
+typedef SGraphImpl<CControl *, std::shared_ptr<CControlData>> TGraphType;
+
+TGraphType g_ControlGraph;
+}
+
+namespace Q3DStudio {
+namespace Control {
+ namespace ControlGraph {
+
+ void AddNode(std::shared_ptr<CControlData> inData)
+ {
+ g_ControlGraph.AddRoot(inData->GetControl());
+ g_ControlGraph.SetData(inData->GetControl(), inData);
+ }
+
+ void RemoveNode(CControl &inData) { g_ControlGraph.RemoveChild(&inData, true); }
+
+ void AddChild(CControl &inParent, CControl &inChild, CControl *inNextSibling)
+ {
+ std::shared_ptr<CControlData> oldParent = GetParent(inChild);
+ TGraphType::TNodePtr theParent(g_ControlGraph.GetImpl(&inParent));
+
+ // It actually happens that sometimes inChild gets added with a sibling
+ // but the sibling hasn't actually been added yet.
+ if (inNextSibling != nullptr) {
+ TGraphType::TNodePtr theSibling(g_ControlGraph.GetImpl(inNextSibling));
+ if (theSibling->m_Parent == theParent)
+ g_ControlGraph.MoveBefore(&inChild, inNextSibling);
+ else
+ g_ControlGraph.AddChild(&inParent, &inChild, SGraphPosition::SEnd());
+ } else
+ g_ControlGraph.AddChild(&inParent, &inChild, SGraphPosition::SEnd());
+
+ if (!oldParent || oldParent->GetControl() != &inParent) {
+ inChild.OnParentChanged(&inParent);
+ if (oldParent)
+ oldParent->ChildrenChanged();
+ }
+ inChild.Invalidate();
+ inParent.ChildrenChanged();
+ }
+ // inParent is supplied for error checking purposes.
+ void RemoveChild(CControl &inParent, CControl &inChild)
+ {
+ inChild.OnParentChanged(nullptr);
+ g_ControlGraph.RemoveChild(&inParent, &inChild, false);
+ inChild.Invalidate();
+ inParent.ChildrenChanged();
+ }
+ void RemoveAllChildren(CControl &inParent)
+ {
+ TGraphType::TNodePtr theNode(g_ControlGraph.GetImpl(&inParent));
+ if (theNode == nullptr)
+ return;
+ while (theNode->m_Children.empty() == false) {
+ theNode->m_Children.back()->m_Data->OnParentChanged(nullptr);
+ theNode->m_Children.back()->m_Data->NotifyParentNeedsLayout();
+ g_ControlGraph.RemoveChild(&inParent, theNode->m_Children.back()->m_GraphableID,
+ false);
+ }
+ inParent.ChildrenChanged();
+ }
+ void MoveTo(CControl &inParent, CControl &inChild, const Graph::SGraphPosition &inPosition)
+ {
+ std::shared_ptr<CControlData> theOldParent(GetParent(inChild));
+ g_ControlGraph.MoveTo(&inParent, &inChild, inPosition);
+ if (!theOldParent || theOldParent->GetControl() != &inParent)
+ inChild.OnParentChanged(&inParent);
+ inChild.NotifyParentNeedsLayout();
+ inParent.MarkChildrenNeedLayout();
+ if (theOldParent) {
+ theOldParent->ChildrenChanged();
+ }
+ inParent.ChildrenChanged();
+ inChild.Invalidate();
+ }
+ long GetNumChildren(CControl &inControl)
+ {
+ return g_ControlGraph.GetChildCount(&inControl);
+ }
+
+ long GetChildIndex(CControl &inParent, CControl &inChild)
+ {
+ QT3DS_ASSERT(GetParent(inChild)->GetControl() == &inParent);
+
+ SGraphPosition thePos = g_ControlGraph.GetNodePosition(&inChild);
+ return thePos.GetIndex();
+ }
+
+ std::shared_ptr<CControlData> GetChild(CControl &inParent, long inIndex)
+ {
+ TGraphType::TNodePtr theNode(g_ControlGraph.GetImpl(&inParent));
+ if (theNode && inIndex < (long)theNode->m_Children.size() && inIndex > -1)
+ return theNode->m_Children[inIndex]->m_Data;
+ return std::shared_ptr<CControlData>();
+ }
+
+ std::shared_ptr<CControlData> GetParent(CControl &inControl)
+ {
+ TGraphType::TNodePtr theNode(g_ControlGraph.GetImpl(&inControl));
+ if (theNode && theNode->m_Parent)
+ return theNode->m_Parent->m_Data;
+ return std::shared_ptr<CControlData>();
+ }
+
+ // Dummy struct to hide graph implementation
+ struct SDummyGraphNode : public TGraphType::TNodeType
+ {
+ SDummyGraphNode(CControl *const &inIdentifier,
+ const std::shared_ptr<CControlData> &inNodeData =
+ std::shared_ptr<CControlData>())
+ : TGraphType::TNodeType(inIdentifier, inNodeData)
+ {
+ }
+ };
+
+ std::shared_ptr<CControlData> SIteratorBase::GetCurrent()
+ {
+ if (m_Children && m_Index < (long)m_Children->size())
+ return (*m_Children)[m_Index]->m_Data;
+
+ QT3DS_ASSERT(false);
+ return std::shared_ptr<CControlData>();
+ }
+
+ SReverseIterator GetRChildren(CControl &inControl)
+ {
+ TGraphType::TNodePtr theNode(g_ControlGraph.GetImpl(&inControl));
+ if (theNode)
+ return SReverseIterator(
+ theNode->m_Data,
+ reinterpret_cast<vector<SDummyGraphNode *> &>(theNode->m_Children));
+ return SReverseIterator();
+ }
+
+ SIterator GetChildren(CControl &inControl)
+ {
+ TGraphType::TNodePtr theNode(g_ControlGraph.GetImpl(&inControl));
+ if (theNode)
+ return SIterator(theNode->m_Data, reinterpret_cast<vector<SDummyGraphNode *> &>(
+ theNode->m_Children));
+ return SIterator();
+ }
+ }
+}
+}
diff --git a/src/Authoring/Studio/Controls/ControlGraph.h b/src/Authoring/Studio/Controls/ControlGraph.h
new file mode 100644
index 00000000..0dfe2b30
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ControlGraph.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef CONTROLGRAPHH
+#define CONTROLGRAPHH
+#include "Multicaster.h"
+#include "ControlGraphIterators.h"
+
+class CControl;
+class CControlWindowListener;
+class CChildFocusListener;
+class CRenderer;
+
+namespace Q3DStudio {
+namespace Graph {
+
+ struct SGraphPosition; // GraphPosition.h"
+}
+
+namespace Control {
+ class ControlData;
+
+ namespace ControlGraph {
+ void AddNode(std::shared_ptr<CControlData> inData);
+ void RemoveNode(CControl &inData);
+ void AddChild(CControl &inParent, CControl &inChild, CControl *inNextSibling);
+ // inParent is supplied for error checking purposes.
+ void RemoveChild(CControl &inParent, CControl &inChild);
+ void RemoveAllChildren(CControl &inParent);
+ void MoveTo(CControl &inParent, CControl &inChild, const Graph::SGraphPosition &inPosition);
+ long GetNumChildren(CControl &inControl);
+ long GetChildIndex(CControl &inParent, CControl &inChild);
+ std::shared_ptr<CControlData> GetChild(CControl &inParent, long inIndex);
+ std::shared_ptr<CControlData> GetParent(CControl &inControl);
+
+ SReverseIterator GetRChildren(CControl &inControl);
+ SIterator GetChildren(CControl &inControl);
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Controls/ControlGraphIterators.h b/src/Authoring/Studio/Controls/ControlGraphIterators.h
new file mode 100644
index 00000000..ae2ffcf6
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ControlGraphIterators.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef CONTROLGRAPHITERATORSH
+#define CONTROLGRAPHITERATORSH
+#include <vector>
+
+namespace Q3DStudio {
+namespace Control {
+ class CControlData;
+ using std::vector;
+
+ namespace ControlGraph {
+ struct SDummyGraphNode;
+
+ struct SIteratorBase
+ {
+ protected:
+ std::shared_ptr<CControlData> m_ControlData;
+ vector<SDummyGraphNode *> *m_Children;
+ long m_Index;
+
+ public:
+ SIteratorBase()
+ : m_Children(nullptr)
+ , m_Index(0)
+ {
+ }
+
+ SIteratorBase(std::shared_ptr<CControlData> data,
+ vector<SDummyGraphNode *> &inChildren)
+ : m_ControlData(data)
+ , m_Children(&inChildren)
+ , m_Index(0)
+ {
+ }
+
+ SIteratorBase(const SIteratorBase &inOther)
+ : m_ControlData(inOther.m_ControlData)
+ , m_Children(inOther.m_Children)
+ , m_Index(inOther.m_Index)
+ {
+ }
+
+ SIteratorBase &operator=(const SIteratorBase &inOther)
+ {
+ if (this != &inOther) {
+ m_ControlData = inOther.m_ControlData;
+ m_Children = inOther.m_Children;
+ m_Index = inOther.m_Index;
+ }
+ return *this;
+ }
+
+ bool operator==(const SIteratorBase &other) { return m_Index == other.m_Index; }
+ bool operator!=(const SIteratorBase &other) { return m_Index != other.m_Index; }
+
+ std::shared_ptr<CControlData> GetCurrent();
+
+ std::shared_ptr<CControlData> operator->() { return GetCurrent(); }
+ std::shared_ptr<CControlData> operator*() { return GetCurrent(); }
+ };
+
+ struct SReverseIterator : SIteratorBase
+ {
+ SReverseIterator() {}
+ SReverseIterator(std::shared_ptr<CControlData> data,
+ vector<SDummyGraphNode *> &inChildren)
+ : SIteratorBase(data, inChildren)
+ {
+ m_Index = (long)inChildren.size() - 1;
+ }
+ SReverseIterator(const SReverseIterator &inOther)
+ : SIteratorBase(inOther)
+ {
+ }
+ SReverseIterator &operator=(const SReverseIterator &inOther)
+ {
+ SIteratorBase::operator=(inOther);
+ return *this;
+ }
+
+ bool IsDone() { return m_Children == nullptr || m_Index < 0; }
+ bool HasNext() { return m_Children && m_Index > -1; }
+ SReverseIterator &operator++()
+ {
+ --m_Index;
+ return *this;
+ }
+ SReverseIterator &operator+=(long inAmount)
+ {
+ m_Index -= inAmount;
+ return *this;
+ }
+ };
+
+ struct SIterator : SIteratorBase
+ {
+ SIterator() {}
+ SIterator(std::shared_ptr<CControlData> data, vector<SDummyGraphNode *> &inChildren)
+ : SIteratorBase(data, inChildren)
+ {
+ }
+ SIterator(const SReverseIterator &inOther)
+ : SIteratorBase(inOther)
+ {
+ }
+ SIterator &operator=(const SIterator &inOther)
+ {
+ SIteratorBase::operator=(inOther);
+ return *this;
+ }
+
+ bool IsDone() { return m_Children == nullptr || m_Index >= (long)m_Children->size(); }
+ bool HasNext() { return m_Children && m_Index < (long)m_Children->size(); }
+ SIterator operator++()
+ {
+ ++m_Index;
+ return *this;
+ }
+ SIterator &operator+=(long inAmount)
+ {
+ m_Index += inAmount;
+ return *this;
+ }
+ };
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/EditInPlace.h b/src/Authoring/Studio/Controls/EditInPlace.h
new file mode 100644
index 00000000..f4497210
--- /dev/null
+++ b/src/Authoring/Studio/Controls/EditInPlace.h
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_EDIT_IN_PLACE_H
+#define INCLUDED_EDIT_IN_PLACE_H 1
+
+#pragma once
+
+#include "Renderer.h"
+#include "Pt.h"
+#include "StudioPreferences.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+template <class T>
+class CEditInPlace : public T
+{
+public:
+ CEditInPlace();
+ virtual ~CEditInPlace();
+
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnLoseFocus() override;
+ void OnGainFocus() override;
+ void Draw(CRenderer *inRenderer) override;
+ void SetEditable(bool inIsEditable);
+ void SetEditMode(bool inEditMode);
+ void EnterText(bool inHighlight) override;
+ void Invalidate(bool inInvalidate = true) override;
+ bool GetEditMode();
+ static long GetRightBuffer();
+
+protected:
+ bool m_IsInEditMode; ///< If in edit mode, the user is currently editing the control
+ bool m_IsEditable; ///< Can only enter edit mode when the control is editable
+
+private:
+ static const long s_RightBuffer = 6;
+};
+
+template <class T>
+CEditInPlace<T>::CEditInPlace()
+ : T()
+ , m_IsInEditMode(false)
+ , m_IsEditable(true)
+{
+ T::SetReadOnly(true);
+ T::SetFillBackground(false);
+}
+
+template <class T>
+CEditInPlace<T>::~CEditInPlace()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the mouse double-click event. Enters the text into edit mode so that
+ * the user can change its value.
+ * @param inPoint location of the mouse
+ * @param inFlags modifier flags for the mouse
+ * @return true if this message should not be passed to any other children, otherwise false
+ */
+template <class T>
+bool CEditInPlace<T>::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_IsEditable && CStudioPreferences::IsSudoMode()) {
+ SetEditMode(true);
+ this->SetSelection(0, T::GetString().Length());
+ return true;
+ }
+ return T::OnMouseDoubleClick(inPoint, inFlags);
+}
+
+template <class T>
+bool CEditInPlace<T>::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (T::GetParent()->HasFocus(this) && !(inFlags & CHotKeys::MOUSE_RBUTTON))
+ SetEditMode(true);
+ return T::OnMouseDown(inPoint, inFlags);
+}
+
+//==============================================================================
+/**
+ * Called when this control loses focus. Turns off edit mode and redraws the
+ * control.
+ */
+template <class T>
+void CEditInPlace<T>::OnLoseFocus()
+{
+ T::OnLoseFocus();
+ SetEditMode(false);
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Handles most of the drawing, with some help from the parent class.
+ * @param inRenderer Renderer to draw to
+ */
+template <class T>
+void CEditInPlace<T>::Draw(CRenderer *inRenderer)
+{
+ CRct theRect = CRct(T::GetSize()); // CRct( CPt( 0, 0 ), CPt( CalculateCharWidths( inRenderer ) +
+ // s_RightBuffer, GetSize( ).y ) );
+ CColor theOutlineColor = CColor(0, 0, 0);
+
+ T::SetAbsoluteSize(theRect.size);
+
+ bool theFillFlag = T::m_FillBackground;
+
+ if (theFillFlag && !m_IsInEditMode) {
+ T::SetFillBackground(false);
+ inRenderer->FillSolidRect(theRect, T::m_BackgroundColorNoFocus);
+ }
+
+ if (m_IsInEditMode)
+ T::SetTextColor(CColor(0, 0, 0));
+
+ inRenderer->PushClippingRect(theRect);
+ T::Draw(inRenderer);
+ inRenderer->PopClippingRect();
+
+ if (!m_IsInEditMode)
+ T::SetFillBackground(theFillFlag);
+
+ if (m_IsInEditMode)
+ inRenderer->DrawRectOutline(theRect, theOutlineColor, theOutlineColor, theOutlineColor,
+ theOutlineColor);
+}
+
+//==============================================================================
+/**
+ * Enables or disables this control from being able to enter "Edit Mode" when
+ * SetEditMode() is called.
+ * @param inIsEditable true if you want the control to be editable when double-clicked, otherwise
+ * false
+ */
+template <class T>
+void CEditInPlace<T>::SetEditable(bool inIsEditable)
+{
+ m_IsEditable = inIsEditable;
+
+ if (!m_IsEditable && m_IsInEditMode)
+ SetEditMode(false);
+}
+
+//==============================================================================
+/**
+ * Starts or stops "Edit Mode". While in Edit Mode, the user can change the
+ * text, move the caret, and highlight the text. An edit box is also drawn
+ * around the text.
+ * @param inEditMode true to turn on Edit Mode, false to turn off Edit Mode
+ */
+template <class T>
+void CEditInPlace<T>::SetEditMode(bool inEditMode)
+{
+ if (m_IsEditable) {
+ m_IsInEditMode = inEditMode;
+ T::SetFillBackground(!m_IsInEditMode);
+ T::SetReadOnly(!m_IsInEditMode);
+ if (!m_IsInEditMode)
+ T::FireCommitEvent();
+ }
+}
+
+//==============================================================================
+/**
+ * Overriden from the parent to cause this control to lose focus when the Enter
+ * button is pressed on the keyboard.
+ * @param inHighlight true to highlight all of the text, false to just change the string
+ */
+template <class T>
+void CEditInPlace<T>::EnterText(bool inHighlight)
+{
+ T::EnterText(inHighlight);
+ OnLoseFocus();
+}
+
+//==============================================================================
+/**
+ * Overriden to also invalidate/validate the parent.
+ * @param inInvalidate true to invalidate this control and the parent control
+ */
+/*
+template<class T>
+void CEditInPlace<T>::Invalidate( bool inInvalidate )
+{
+ if ( inInvalidate && GetParent() )
+ GetParent()->Invalidate( inInvalidate );
+
+ CControl::Invalidate( inInvalidate );
+}*/
+
+//==============================================================================
+/**
+ * Override to avoid selecting all the text unless in edit mode.
+ */
+template <class T>
+void CEditInPlace<T>::OnGainFocus()
+{
+ if (m_IsInEditMode && m_IsEditable)
+ T::OnGainFocus();
+}
+
+template <class T>
+bool CEditInPlace<T>::GetEditMode()
+{
+ return m_IsInEditMode;
+}
+
+template <class T>
+long CEditInPlace<T>::GetRightBuffer()
+{
+ return s_RightBuffer;
+}
+
+template <class T>
+bool CEditInPlace<T>::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers)
+{
+ bool theReturn = false;
+
+ if (m_IsInEditMode) {
+ T::DisplayContextMenu(inPoint);
+ theReturn = true;
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * Overriden to also invalidate/validate the parent.
+ * @param inInvalidate true to invalidate this control and the parent control
+ */
+template <class T>
+void CEditInPlace<T>::Invalidate(bool inInvalidate)
+{
+ if (inInvalidate && T::GetParent())
+ T::GetParent()->Invalidate(inInvalidate);
+
+ T::Invalidate(inInvalidate);
+}
+
+#endif // INCLUDED_EDIT_IN_PLACE_H
diff --git a/src/Authoring/Studio/Controls/FloatEdit.cpp b/src/Authoring/Studio/Controls/FloatEdit.cpp
new file mode 100644
index 00000000..e3dc9c2f
--- /dev/null
+++ b/src/Authoring/Studio/Controls/FloatEdit.cpp
@@ -0,0 +1,524 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+#include "StringTokenizer.h"
+#include "StringLoader.h"
+//==============================================================================
+// Include
+//==============================================================================
+#include "FloatEdit.h"
+#include "MouseCursor.h"
+#include "ResourceCache.h"
+#include "StudioClipboard.h"
+#include "ControlData.h"
+#include "UICMath.h"
+
+#include <QApplication>
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CFloatEdit::CFloatEdit()
+ : m_NumDecimalPlaces(3)
+ , m_FixedPlaces(-1)
+ , m_IsMouseDown(false)
+ , m_Min(-FLT_MAX)
+ , m_Max(FLT_MAX)
+ , m_EditMode(false)
+ , m_RevertListener(NULL)
+{
+ m_ControlData->SetMouseWheelEnabled(true);
+ // Set the default string
+ SetData(0.0f, false);
+
+ SetReadOnly(true);
+ SetName("FloatEdit");
+
+ // TODO: Used only for timeline palette timebar. It is not editable, we do not need
+ // to register any events. Registering minus here will prevent it from working for zooming
+ // out in the timeline.
+ // TODO: This whole class will most likely be removed when timeline is converted to Qt.
+// m_CommandHandler.RegisterKeyEvent(
+// new CDynHotKeyConsumer<CFloatEdit>(this, &CFloatEdit::AddCharNegative), 0, '-');
+// m_CommandHandler.RegisterKeyEvent(
+// new CDynHotKeyConsumer<CFloatEdit>(this, &CFloatEdit::AddCharPeriod), 0, '.');
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CFloatEdit::~CFloatEdit()
+{
+}
+
+void CFloatEdit::AddCharNegative()
+{
+ Q3DStudio::CString theMinusString = ::LoadResourceString(IDS_CONTROLS_FLOAT_MINUS);
+ unsigned int theMinus = theMinusString[0];
+
+ InsertChar(theMinus);
+}
+
+void CFloatEdit::AddCharPeriod()
+{
+ Q3DStudio::CString thePeriodString = ::LoadResourceString(IDS_CONTROLS_FLOAT_PERIOD);
+ unsigned int thePeriod = thePeriodString[0];
+
+ InsertChar(thePeriod);
+}
+
+void CFloatEdit::FormatString()
+{
+ Q3DStudio::CString theFormatString;
+ if (m_FixedPlaces == -1)
+ theFormatString.Format(_UIC("%%.%df"), m_NumDecimalPlaces);
+ else
+ theFormatString.Format(_UIC("%%0%d.%df"), m_FixedPlaces, m_NumDecimalPlaces);
+
+ m_ValueString.Format(theFormatString, m_Value);
+}
+
+//==============================================================================
+/**
+ * Converts the internal (float) data of this control into a string that can be
+ * displayed. The parent class (CTextEdit) calls this function when it needs
+ * to redraw the control and the text within it.
+ *
+ * @return the string to be displayed.
+ */
+Q3DStudio::CString CFloatEdit::GetString()
+{
+ return m_ValueString;
+}
+
+//==============================================================================
+/**
+ * Sets the internal data of this control the specified value and marks the
+ * control as dirty so that it gets redrawn during the next free cycle.
+ *
+ * @param inValue the new value for this control
+ * @param inFireEvent true to fire a property change event
+ */
+void CFloatEdit::SetData(float inValue, bool inFireEvent /* = true */)
+{
+ m_Value = inValue;
+
+ FormatString();
+ SetDisplayString(GetString(), inFireEvent);
+ if (inFireEvent)
+ SetDirty(true);
+}
+
+//==============================================================================
+/**
+ * Attempts to set the internal data of this control to the specified string.
+ *
+ * @param inData a string containing the new data
+ */
+void CFloatEdit::SetData(const Q3DStudio::CString &inData, bool inFireEvent /*= true*/)
+{
+ m_Value = static_cast<float>(::atof(inData.GetCharStar()));
+
+ FormatString();
+ // The string needs to be set precisely here, otherwise
+ // we end up truncating - and . from the floats
+ SetDisplayString(inData, inFireEvent);
+ SetDirty(true);
+}
+
+//==============================================================================
+/**
+ * Determines if the specified character can be inserted into the string. This
+ * control only accepts numbers, decimals, and minus signs. Further, a minus
+ * sign may only be inserted at the front of the string if there is not already
+ * one in the string and a decimal may only be inserted if there is not one in
+ * the string already.
+ *
+ * @param inCheckString the string that is to be checked (in case a lenght requirement is exceeded)
+ * @param inChar the character that was pressed
+ * @param inPosition character index where we are attempting to insert inChar into inCheckString
+ * @return true if this control can accept the character into the string, otherwise false
+ */
+bool CFloatEdit::CanAcceptChar(const Q3DStudio::CString &inCheckString, unsigned int inChar,
+ unsigned int inPosition)
+{
+ bool theRetVal = false;
+ Q3DStudio::CString thePeriodString = ::LoadResourceString(IDS_CONTROLS_FLOAT_PERIOD);
+ Q3DStudio::CString theMinusString = ::LoadResourceString(IDS_CONTROLS_FLOAT_MINUS);
+
+ unsigned int thePeriod = thePeriodString[0];
+ unsigned int theMinus = theMinusString[0];
+
+ if ((CTextEdit::CanAcceptChar(inCheckString, inChar, inPosition) && inCheckString.Length() < 10)
+ || inChar == thePeriod || inChar == theMinus) {
+ if (inChar >= '0' && inChar <= '9')
+ theRetVal = true;
+ if (!theRetVal) {
+ if (thePeriod == inChar) {
+ if (inCheckString.Find(char(thePeriod)) == Q3DStudio::CString::ENDOFSTRING)
+ theRetVal = true;
+ else {
+ theRetVal = false;
+ }
+ } else if (theMinus == inChar) {
+ if ((inCheckString.Find(char(theMinus)) == Q3DStudio::CString::ENDOFSTRING)
+ && (inPosition == 0))
+ theRetVal = true;
+ }
+ }
+ }
+ return theRetVal;
+}
+
+bool CFloatEdit::HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ bool isLargeStep = inFlags & CHotKeys::MODIFIER_SHIFT ? true : false;
+ bool isSmallStep = inFlags & CHotKeys::MODIFIER_CONTROL ? true : false;
+
+ bool wasHandled = false;
+ switch (inChar) {
+ case Qt::Key_Up:
+ if (isLargeStep)
+ SetFloatValue(m_Value + 10.0f);
+ else if (isSmallStep)
+ SetFloatValue(static_cast<float>(m_Value + 0.1f));
+ else
+ SetFloatValue(static_cast<float>(m_Value + 1.0f));
+ wasHandled = true;
+ break;
+
+ case Qt::Key_Down:
+ if (isLargeStep)
+ SetFloatValue(static_cast<float>(m_Value - 10.0f));
+ else if (isSmallStep)
+ SetFloatValue(static_cast<float>(m_Value - 0.1f));
+ else
+ SetFloatValue(m_Value - 1.0f);
+ wasHandled = true;
+ break;
+
+ case Qt::Key_Enter:
+ ExitEditMode();
+ wasHandled = true;
+ CTextEdit::OnLoseFocus();
+ break;
+
+ case Qt::Key_Escape:
+ if (m_RevertListener)
+ m_RevertListener->OnDiscardChanges(this);
+ ExitEditMode();
+ wasHandled = true;
+ CTextEdit::OnLoseFocus();
+ break;
+
+ /*
+ case CHotKeys::KEY_SUBTRACT:
+ case CHotKeys::KEY_SUBTRACT_OEM:
+ case CHotKeys::KEY_PERIOD_OEM:
+ wasHandled = true;
+ break;
+ */
+ }
+
+ if (!wasHandled)
+ wasHandled = CTextEdit::HandleSpecialChar(inChar, inFlags);
+
+ return wasHandled;
+}
+
+float CFloatEdit::GetData()
+{
+ return m_Value;
+}
+
+float CFloatEdit::GetDisplayData()
+{
+ float theFloat = static_cast<float>(::atof(GetDisplayString().GetCharStar()));
+ return theFloat;
+}
+
+void CFloatEdit::OnLoseFocus()
+{
+ ExitEditMode();
+ CTextEdit::OnLoseFocus();
+}
+
+void CFloatEdit::OnGainFocus()
+{
+ if (!m_IsMouseDown && IsEnabled())
+ SetReadOnly(false);
+ CTextEdit::OnGainFocus();
+}
+
+bool CFloatEdit::CanGainFocus()
+{
+ return true;
+}
+
+void CFloatEdit::ExitEditMode()
+{
+ m_EditMode = false;
+ SetReadOnly(true);
+}
+
+void CFloatEdit::EnterEditMode()
+{
+ m_EditMode = true;
+ SetReadOnly(false);
+}
+
+//==============================================================================
+/**
+ * Handles the dynamic dragging of float values.
+ */
+void CFloatEdit::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_IsMouseDown && !m_EditMode) {
+ // If we haven't started handling selecting or dragging figure out which one to do
+ if (!m_Trapping) {
+ // If moved outside of the safety zone start dragging the value.
+ if (::labs(inPoint.y - m_MouseStartPos.y) > 2) {
+ m_Trapping = true;
+// In Mac there's no infinite mouse, so don't hide it.
+ setCursorIfNotSet(CMouseCursor::CURSOR_BLANK);
+ }
+ }
+ // If in trapping mode then do the value drag processing.
+ if (m_Trapping) {
+ float theDiff = static_cast<float>(m_MouseStartPos.y - inPoint.y);
+
+ if (inFlags & CHotKeys::MODIFIER_CONTROL)
+ theDiff *= 0.1f;
+ else if (inFlags & CHotKeys::MODIFIER_SHIFT)
+ theDiff *= 10.0f;
+
+ SetFloatValue(theDiff + m_StartDragVal);
+
+ CPt theMouseLoc = CControl::ClientToScreen(m_MouseStartPos);
+ getCursor().setPos(theMouseLoc.x, theMouseLoc.y);
+
+ m_StartDragVal = GetData();
+ }
+ } else
+ CTextEdit::OnMouseMove(inPoint, inFlags);
+}
+
+void CFloatEdit::SetFloatValue(float inValue)
+{
+ // If the min and max are both zero, special case, don't bother capping the value to the
+ // min/max.
+ if (m_Min != 0 || m_Max != 0) {
+ if (inValue > m_Max)
+ inValue = m_Max;
+ else if (inValue < m_Min)
+ inValue = m_Min;
+ }
+
+ SetData(inValue);
+ ReloadData();
+ Q3DStudio::CString theNewValue = GetString();
+ SetData(theNewValue);
+}
+
+//==============================================================================
+/**
+ * Handler to start mouse dragging actions on this.
+ */
+bool CFloatEdit::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (IsEnabled()) {
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ if (m_EditMode)
+ CTextEdit::OnMouseDown(inPoint, inFlags);
+
+ m_IsMouseDown = true;
+ m_Trapping = false;
+ m_StartDragVal = GetData();
+
+ m_MouseStartPos = inPoint;
+ }
+ }
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * Handler to finish the mouse dragging actions.
+ */
+void CFloatEdit::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_IsMouseDown && !m_Trapping && m_IsReadOnly) {
+ SetReadOnly(false);
+ SelectAllText();
+ EnterEditMode();
+ }
+
+ CTextEdit::OnMouseUp(inPoint, inFlags);
+
+ resetCursor();
+ m_IsMouseDown = false;
+
+ if (m_Trapping)
+ FireFocusEvent(true);
+}
+
+//==============================================================================
+/**
+ * Set the minimum value allowed in this edit field.
+ */
+void CFloatEdit::SetMin(float inMin)
+{
+ m_Min = inMin;
+}
+
+//==============================================================================
+/**
+ * Set the maximum value allowed in this field.
+ */
+void CFloatEdit::SetMax(float inMax)
+{
+ m_Max = inMax;
+}
+
+//==============================================================================
+/**
+ * Handle mouse wheel messages to allow scrolling of the values.
+ */
+bool CFloatEdit::OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ bool theRet = false;
+ if (GetParent() && GetParent()->HasFocus(this)) {
+ float theDiff = 1.0f;
+ if (inFlags & CHotKeys::MODIFIER_CONTROL)
+ theDiff = 0.1f;
+ else if (inFlags & CHotKeys::MODIFIER_SHIFT)
+ theDiff = 10.0f;
+
+ if (inAmount < 0)
+ theDiff *= -1.0f;
+
+ SetFloatValue(GetData() + theDiff);
+
+ theRet = true;
+ }
+ return theRet;
+}
+
+//==============================================================================
+/**
+ * Set the number of decimal places to be displayed in this.
+ */
+void CFloatEdit::SetNumDecimalPlaces(short inNumDecimalPlaces)
+{
+ m_NumDecimalPlaces = inNumDecimalPlaces;
+ FormatString();
+}
+
+//==============================================================================
+/**
+ * Set the number of fill places before the start of the number to fill if the number
+ * is too short. This defaults to -1 which means none.
+ */
+void CFloatEdit::SetFixedPlaces(short inFixedPlaces)
+{
+ m_FixedPlaces = inFixedPlaces;
+}
+
+//==============================================================================
+/**
+ * Ensure that the text from clipboard can be pasted into this control
+ */
+bool CFloatEdit::CanPaste()
+{
+ bool theValid = false;
+
+ const auto text = Q3DStudio::CString::fromQString(CStudioClipboard::GetTextFromClipboard());
+ if (m_Caret.show) {
+ Q3DStudio::CString theNewString(m_DisplayString);
+ long theCaret = m_Caret.position;
+
+ if (HasSelectedText()) {
+ theNewString.Delete(GetSelectionLeft(), GetSelectionRight() - GetSelectionLeft());
+ theCaret = Q3DStudio::MIN(GetSelectionLeft(), GetSelectionRight());
+ }
+ theNewString.Insert(theCaret, text);
+ theValid = Validate(theNewString);
+ } else {
+ theValid = Validate(text);
+ }
+
+ return theValid;
+}
+
+//==============================================================================
+/**
+ * Returns true if the given string can be pasted into the control
+ */
+bool CFloatEdit::Validate(const Q3DStudio::CString &inString)
+{
+ Q3DStudio::CString theCheckString("");
+ Q3DStudio::CString theTemp;
+ bool theRetVal = true;
+ long theIter;
+
+ for (theIter = 0; theIter < inString.Length(); ++theIter) {
+ theTemp = inString.Extract(theIter, 1);
+
+ if (!CanAcceptChar(theCheckString, theTemp[0], theIter)) {
+ theRetVal = false;
+ break;
+ } else
+ theCheckString += inString.Extract(theIter, 1);
+ }
+
+ return theRetVal;
+}
+
+//==============================================================================
+/**
+ * Refreshes the display string from the internal data
+ */
+void CFloatEdit::RefreshDisplayFromData()
+{
+ SetDisplayString(GetString());
+ Invalidate();
+}
diff --git a/src/Authoring/Studio/Controls/FloatEdit.h b/src/Authoring/Studio/Controls/FloatEdit.h
new file mode 100644
index 00000000..4e29283b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/FloatEdit.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_FLOAT_EDIT_H
+#define INCLUDED_FLOAT_EDIT_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TextEdit.h"
+
+#include <QCursor>
+
+GENERIC_FUNCTOR_1(CRevertListener, OnDiscardChanges, CControl *);
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CMouseCursor;
+
+class CFloatEdit : public CTextEdit
+{
+protected:
+ float m_Value; ///<
+ short m_NumDecimalPlaces; ///<
+ short m_FixedPlaces; ///<
+ bool m_IsMouseDown; ///<
+ bool m_Trapping; ///<
+ float m_StartDragVal; ///<
+ float m_Min; ///<
+ float m_Max; ///<
+ bool m_EditMode; ///<
+ Q3DStudio::CString m_ValueString; ///<
+ CPt m_MouseStartPos; ///< Used to reset the mouse pos when dragging values.
+ CRevertListener *m_RevertListener; ///< Used when user presses escape.
+
+public:
+ CFloatEdit();
+ virtual ~CFloatEdit();
+
+ Q3DStudio::CString GetString() override;
+ virtual void SetData(float inValue, bool inFireEvent = true);
+ void SetData(const Q3DStudio::CString &inData, bool inFireEvent = true) override;
+ bool CanAcceptChar(const Q3DStudio::CString &inCheckString, unsigned int inChar,
+ unsigned int inPosition) override;
+ bool CanPaste() override;
+
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags) override;
+
+ virtual void SetMin(float inMin);
+ virtual void SetMax(float inMax);
+
+ void OnLoseFocus() override;
+ void OnGainFocus() override;
+ bool CanGainFocus() override;
+
+ float GetData();
+ float GetDisplayData();
+
+ void SetNumDecimalPlaces(short inNumDecimalPlaces);
+ void SetFixedPlaces(short inFixedPlaces);
+ void RefreshDisplayFromData() override;
+
+ virtual void SetRevertListener(CRevertListener *inListener) { m_RevertListener = inListener; }
+
+protected:
+ bool HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags) override;
+
+ void SetFloatValue(float inValue);
+ bool Validate(const Q3DStudio::CString &inString);
+
+ void EnterEditMode();
+ void ExitEditMode();
+
+ void FormatString();
+
+ void AddCharNegative();
+ void AddCharPeriod();
+};
+
+#endif // INCLUDED_FLOAT_EDIT_H
diff --git a/src/Authoring/Studio/Controls/FlowLayout.cpp b/src/Authoring/Studio/Controls/FlowLayout.cpp
new file mode 100644
index 00000000..9864321d
--- /dev/null
+++ b/src/Authoring/Studio/Controls/FlowLayout.cpp
@@ -0,0 +1,1009 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FlowLayout.h"
+#include "Renderer.h"
+#include "MasterP.h"
+#include "ControlData.h"
+#include "CoreUtils.h"
+#include "UICMath.h"
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+using namespace Q3DStudio::Control;
+
+//=============================================================================
+/**
+ * Checks to see if this has hit it's max X
+ */
+bool CanBeExpandedX(CControl *inControl)
+{
+ bool theRetVal = false;
+ CPt theSize = inControl->GetSize();
+ CPt theMaxSize = inControl->GetMaximumSize();
+ if (theSize.x < theMaxSize.x) {
+ theRetVal = true;
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Checks to see if this has hit it's max Y
+ */
+bool CanBeExpandedY(CControl *inControl)
+{
+ bool theRetVal = false;
+ CPt theSize = inControl->GetSize();
+ CPt theMaxSize = inControl->GetMaximumSize();
+ if (theSize.y < theMaxSize.y) {
+ theRetVal = true;
+ }
+ return theRetVal;
+}
+
+IMPLEMENT_OBJECT_COUNTER(CFlowLayout)
+
+//=============================================================================
+/**
+ * Constructs a new FlowLayout flowing vertically (down).
+ */
+CFlowLayout::CFlowLayout(CControl *inControl, bool inUseControl)
+ : m_FlowDirection(FLOW_VERTICAL)
+ , m_VerticalAlignment(ALIGN_TOP)
+ , m_HorizontalAlignment(ALIGN_LEFT)
+ , m_ResizingChildren(false)
+ , m_LeftMargin(0)
+ , m_RightMargin(0)
+ , m_TopMargin(0)
+ , m_BottomMargin(0)
+ , m_ChildGap(0)
+ , m_DebugFlag(false)
+ , m_AutoMin(true)
+ , m_SuspendRecalcLayout(false)
+{
+ ADDTO_OBJECT_COUNTER(CFlowLayout)
+
+ m_BlankDisable = false;
+ m_HasUnusedSpace = false;
+
+ if (inControl != nullptr) {
+ m_BlankControl = inControl;
+ } else if (inUseControl) {
+ m_BlankControl = new CBlankControl();
+ } else {
+ m_BlankControl = nullptr;
+ }
+
+ SetMaximumSize(CPt(LONG_MAX, LONG_MAX));
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CFlowLayout::~CFlowLayout()
+{
+ delete m_BlankControl;
+
+ REMOVEFROM_OBJECT_COUNTER(CFlowLayout)
+}
+
+//=============================================================================
+/**
+ * The left margin is the gap on the left side of the flow layout where no
+ * controls are drawn. The default left margin of a flow layout is zero. If
+ * you have a horizontal flow layout with left alignment, you can use the margin
+ * to push all the child controls over by a fixed amount.
+ * @param inMargin Width in pixels of the left margin
+ * @return the previous width of the left margin
+ */
+long CFlowLayout::SetLeftMargin(long inMargin)
+{
+ long theOldMargin = m_LeftMargin;
+ m_LeftMargin = inMargin;
+ ResetMinMaxPref();
+ RecalcLayout();
+ return theOldMargin;
+}
+
+//=============================================================================
+/**
+ * The left margin is the gap on the left side of the flow layout where no
+ * controls are drawn. The default left margin of a flow layout is zero. Only
+ * valid with a horizontal flow layout with left alignment.
+ * @return the gap on the left side of this flow, in pixels
+ */
+long CFlowLayout::GetLeftMargin() const
+{
+ return m_LeftMargin;
+}
+
+long CFlowLayout::GetRightMargin() const
+{
+ return m_RightMargin;
+}
+
+long CFlowLayout::GetTopMargin() const
+{
+ return m_TopMargin;
+}
+
+long CFlowLayout::GetBottomMargin() const
+{
+ return m_BottomMargin;
+}
+
+//=============================================================================
+/**
+ * Disables the drawing of blank rectangles in blank areas on the screen
+ * @param NONE
+ * @return NONE
+ */
+void CFlowLayout::DisableBlank()
+{
+ m_BlankDisable = true;
+}
+
+//=============================================================================
+/**
+ * The right margin is the gap on the rgiht side of the flow layout where no
+ * controls are drawn. The default right margin of a flow layout is zero. If
+ * you have a horizontal flow layout with right alignment, you can use the margin
+ * to push all the child controls over by a fixed amount.
+ * @param inMargin Width in pixels of the right margin
+ * @return the previous width of the right margin
+ */
+long CFlowLayout::SetRightMargin(long inMargin)
+{
+ long theOldMargin = m_RightMargin;
+ m_RightMargin = inMargin;
+ ResetMinMaxPref();
+ RecalcLayout();
+ return theOldMargin;
+}
+
+//=============================================================================
+/**
+ * The top margin is the gap on the top of the flow layout where no controls
+ * are drawn. The default top margin of a flow layout is zero. If you have
+ * a vertical flow layout with top alignment, you can use the margin to push
+ * all the child controls down by a fixed amount.
+ * @param inMargin Height in pixels of the top margin
+ * @return the previous height of the top margin
+ */
+long CFlowLayout::SetTopMargin(long inMargin)
+{
+ long theOldMargin = m_TopMargin;
+ m_TopMargin = inMargin;
+ ResetMinMaxPref();
+ RecalcLayout();
+ return theOldMargin;
+}
+
+//=============================================================================
+/**
+ * The bottom margin is the gap on the bottom of the flow layout where no
+ * controls are drawn. The default bottom margin of a flow layout is zero. If
+ * you have a vertical flow layout with bottom alignment, you can use the margin
+ * to push all the child controls up by a fixed amount.
+ * @param inMargin Height in pixels of the bottom margin
+ * @return the previous height of the bottom margin
+ */
+long CFlowLayout::SetBottomMargin(long inMargin)
+{
+ long theOldMargin = m_BottomMargin;
+ m_BottomMargin = inMargin;
+ ResetMinMaxPref();
+ RecalcLayout();
+ return theOldMargin;
+}
+
+//=============================================================================
+/**
+ * This functions sets a fixed gap between children of the flow layout.
+ * @param inGap pixel gap between each child of the flow layout
+ * @return the previous pixel gap between children
+ */
+long CFlowLayout::SetGapBetweenChildren(long inGap)
+{
+ long theOldGap = m_ChildGap;
+ m_ChildGap = inGap;
+ ResetMinMaxPref();
+ RecalcLayout();
+ return theOldGap;
+}
+
+//=============================================================================
+/**
+ * Get the preferred size of this control.
+ * The preferred size is the sum of all the preferred sizes of all the children.
+ * @return the preferred size of this control.
+ */
+// CPt CFlowLayout::GetPreferredSize( )
+//{
+// return m_PreferredSize;
+//}
+
+//=============================================================================
+/**
+ * Get the minimum size of this control.
+ * The minimum size is the sum of all the minimum sizes of all the children in
+ * the flow direction, and the largest minimum size in the non-flow direction.
+ * @return the minimum size of this control.
+ */
+// CPt CFlowLayout::GetMinimumSize( )
+//{
+// return m_MinimumSize;
+//}
+
+//=============================================================================
+/**
+ * Get the maximum size of this control.
+ * The maximum size is the sum of all the maximum sizes of all the children in
+ * the flow direction, and the smallest maximum size in the non-flow direction.
+ * @return the maximum size of this control.
+ */
+// CPt CFlowLayout::GetMaximumSize( )
+//{
+// return m_MaximumSize;
+//}
+
+//=============================================================================
+/**
+ * Set the direction the components are flowing.
+ * Vertical means the components will be positioned one on top of the other,
+ * starting at the top and flowing down.
+ * Horizontal means the components will be positions side by side, starting on
+ * the left and flowing right.
+ * @param inFlowDirection the new flow direction.
+ */
+void CFlowLayout::SetFlowDirection(EFlowDirection inFlowDirection)
+{
+ if (inFlowDirection != m_FlowDirection) {
+ m_FlowDirection = inFlowDirection;
+
+ RecalcLayout();
+ }
+}
+
+//=============================================================================
+/**
+ * Add a child control to this control.
+ * This adds the child control to this and includes it in the layout.
+ * @param inControl the control to be added.
+ * @param inInsertBefore the location to insert the control, nullptr = end.
+ */
+void CFlowLayout::AddChild(CControl *inControl, CControl *inInsertBefore /*= nullptr*/)
+{
+ CControl::AddChild(inControl, inInsertBefore);
+
+ if (GetParent() != nullptr) {
+ ResetMinMaxPref();
+ GetParent()->OnChildSizeChanged(this);
+ }
+
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Remove a child from this control.
+ * @param inControl the control to be removed.
+ */
+void CFlowLayout::RemoveChild(CControl *inControl)
+{
+ CControl::RemoveChild(inControl);
+
+ if (GetParent() != nullptr) {
+ ResetMinMaxPref();
+ GetParent()->OnChildSizeChanged(this);
+ }
+
+ RecalcLayout();
+}
+
+/**
+ * Sets the flag on whether to suspend the recalculation of the layout.
+ * Recalc is expensive, especially when there are many children.
+ * if you need to add lots of children items to this control, do this:
+ * SuspendRecalcLayout( true ); AddLotsOFItems( ); SuspendRecalcLayout( false );
+ * DoSomethingThatWillTriggerRecalcLayout( );
+ * @param inSuspendFlag true would suspend recalc
+ * @see RecalcLayout
+ * @see CListBoxControl
+*/
+void CFlowLayout::SuspendRecalcLayout(bool inSuspendFlag)
+{
+ m_SuspendRecalcLayout = inSuspendFlag;
+}
+
+//=============================================================================
+/**
+ * Recalculate the positions of all the child controls of this control.
+ * This does the work of all the layout of the children and figures out where
+ * everything belongs.
+ */
+void CFlowLayout::RecalcLayout()
+{
+ UICPROFILE(RecalcLayout);
+
+ // if you need to add lots of children items to this control, do this:
+ // SuspendRecalcLayout( true ); AddLotsOFItems( ); SuspendRecalcLayout( false );
+ // DoSomethingThatWillTriggerRecalcLayout( );
+ if (m_SuspendRecalcLayout)
+ return;
+
+ m_ResizingChildren = true;
+
+ CPt thePosition(0, 0);
+ CPt theCurSize = GetSize();
+ long theNumExpandableY = 0;
+ long theNumExpandableX = 0;
+ m_HasUnusedSpace = false;
+
+ if ((m_FlowDirection == FLOW_HORIZONTAL && m_HorizontalAlignment != ALIGN_RIGHT)
+ || (m_FlowDirection == FLOW_VERTICAL && m_VerticalAlignment != ALIGN_BOTTOM)) {
+ thePosition.x = m_LeftMargin;
+ thePosition.y = m_TopMargin;
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = *thePos;
+ RecalcChild(theChild->GetControl(), thePosition, theNumExpandableX, theNumExpandableY);
+
+ if (m_FlowDirection == FLOW_HORIZONTAL)
+ thePosition += CPt(m_ChildGap, 0);
+ else
+ thePosition += CPt(0, m_ChildGap);
+ }
+ } else {
+ // thePosition.x = m_RightMargin;
+ // thePosition.y = m_BottomMargin;
+ ControlGraph::SReverseIterator thePos = GetReverseChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = *thePos;
+ RecalcChild(theChild->GetControl(), thePosition, theNumExpandableX, theNumExpandableY);
+
+ if (m_FlowDirection == FLOW_HORIZONTAL)
+ thePosition -= CPt(m_ChildGap, 0);
+ else
+ thePosition -= CPt(0, m_ChildGap);
+ }
+ }
+
+ // If there is extra space and there are items able to expand still
+ if (thePosition.y < theCurSize.y && m_FlowDirection == FLOW_VERTICAL) {
+ if (theNumExpandableY > 0)
+ ResizeExpandableControlsY((theCurSize.y - thePosition.y), theNumExpandableY);
+ else
+ m_HasUnusedSpace = true;
+
+ // SDJ: See below
+ // ResetChildPositions( );
+ } else if (thePosition.x < theCurSize.x && m_FlowDirection == FLOW_HORIZONTAL) {
+ if (theNumExpandableX > 0)
+ ResizeExpandableControlsX((theCurSize.x - thePosition.x), theNumExpandableX);
+ else
+ m_HasUnusedSpace = true;
+
+ // SDJ: See below
+ // ResetChildPositions( );
+ }
+
+ // SDJ: There is a case where the top margin is not properly calculated when
+ // neither of the above conditions is met. Calling ResetChildPositions fixes
+ // this, but might be ineffiecient. If you attempt to fix this, replace the
+ // commented out calls to ResetChildPositions above.
+ ResetChildPositions();
+
+ m_ResizingChildren = false;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * XXX
+ */
+void CFlowLayout::RecalcChild(CControl *inChild, CPt &ioPosition, long &ioNumExpandableX,
+ long &ioNumExpandableY)
+{
+ CPt theTotalPrefSizes = GetTotalPreferredSizes();
+ CPt theCurSize = GetSize();
+ CPt theChildSize = theCurSize;
+
+ theCurSize.x -= m_RightMargin;
+ theCurSize.y -= m_BottomMargin;
+
+ if (inChild->IsVisible()) {
+ inChild->ResetMinMaxPref();
+ CPt thePrefSize = inChild->GetPreferredSize();
+ CPt theMinSize = inChild->GetMinimumSize();
+ CPt theMaxSize = inChild->GetMaximumSize();
+
+ if (theMaxSize.x > theCurSize.x - ioPosition.x)
+ theMaxSize.x = theCurSize.x - ioPosition.x;
+ if (theMaxSize.x < 0)
+ theMaxSize.x = 0;
+ if (theMaxSize.y > theCurSize.y - ioPosition.y)
+ theMaxSize.y = theCurSize.y - ioPosition.y;
+ if (theMaxSize.y < 0)
+ theMaxSize.y = 0;
+
+ if (m_FlowDirection == FLOW_VERTICAL) {
+ CPt theChildPosition;
+ theChildPosition.y = ioPosition.y;
+ theChildPosition.x = 0;
+ theChildSize.x = theCurSize.x;
+ ///*
+ // SDJ; Why is this commented out?
+ switch (m_HorizontalAlignment) {
+ case ALIGN_LEFT:
+ theChildPosition.x = 0;
+ break;
+
+ case ALIGN_RIGHT:
+ theChildPosition.x =
+ (GetSize().x - (m_LeftMargin + m_RightMargin)) - inChild->GetSize().x;
+ break;
+
+ case ALIGN_MIDDLE:
+ theChildPosition.x = (GetSize().x / 2) - (inChild->GetSize().x / 2);
+ break;
+
+ case ALIGN_HORIZ_NEITHER:
+ // NO BREAK
+ default:
+ theChildPosition.x = inChild->GetPosition().x;
+ break;
+ }
+ //*/
+
+ inChild->SetPosition(theChildPosition);
+
+ if (theTotalPrefSizes.y) {
+ float theModifier = ((float)thePrefSize.y) / ((float)theTotalPrefSizes.y);
+ // Check to see if they have hit their min or max
+ if (theMinSize.y > ::dtol(theCurSize.y * theModifier)) {
+ theChildSize.y = theMinSize.y;
+ ++ioNumExpandableY;
+
+ } else if (theMaxSize.y < ::dtol(theCurSize.y * theModifier)) {
+ theChildSize.y = theMaxSize.y;
+ } else {
+ // This item can be expanded
+ ++ioNumExpandableY;
+ theChildSize.y = inChild->GetSize().y;
+ }
+ }
+
+ // If the child cannot be expanded, maintain its current width
+ // if ( !CanBeExpandedX( inChild ) )
+ // theChildSize.x = inChild->GetSize( ).x;
+
+ theChildSize.x = Q3DStudio::MAX(theChildSize.x, theMinSize.x);
+ theChildSize.y = Q3DStudio::MAX(theChildSize.y, theMinSize.y);
+
+ theChildSize.x = Q3DStudio::MIN(theChildSize.x, theMaxSize.x);
+ theChildSize.y = Q3DStudio::MIN(theChildSize.y, theMaxSize.y);
+
+ inChild->SetSize(theChildSize);
+ ioPosition.y += theChildSize.y;
+ } else {
+ CPt theChildPosition;
+ theChildPosition.x = ioPosition.x;
+
+ switch (m_VerticalAlignment) {
+ case ALIGN_TOP:
+ theChildPosition.y = m_TopMargin;
+ break;
+
+ case ALIGN_BOTTOM:
+ theChildPosition.y = GetSize().y - inChild->GetSize().y;
+ break;
+
+ case ALIGN_CENTER:
+ theChildPosition.y = (GetSize().y / 2) - (inChild->GetSize().y / 2);
+ break;
+
+ case ALIGN_VERT_NEITHER:
+ // NO BREAK
+ default:
+ theChildPosition.y = inChild->GetPosition().y;
+ break;
+ }
+
+ inChild->SetPosition(theChildPosition);
+
+ if (theTotalPrefSizes.x) {
+ float theModifier = ((float)thePrefSize.x) / ((float)theTotalPrefSizes.x);
+ // Check to see if they have hit their min or max
+ if (theMinSize.x > ::dtol(theCurSize.x * theModifier)) {
+ theChildSize.x = theMinSize.x;
+ ++ioNumExpandableX;
+
+ } else if (theMaxSize.x < ::dtol(theCurSize.x * theModifier)) {
+ theChildSize.x = theMaxSize.x;
+ } else {
+ // This item can be expanded
+ theChildSize.x = ::dtol((theCurSize.x * theModifier));
+ ++ioNumExpandableX;
+ }
+ }
+
+ // If the child cannot by expanded, maintain the same height
+ if (!CanBeExpandedY(inChild))
+ theChildSize.y = inChild->GetSize().y;
+
+ theChildSize.x = Q3DStudio::MAX(theChildSize.x, theMinSize.x);
+ theChildSize.y = Q3DStudio::MAX(theChildSize.y, theMinSize.y);
+
+ theChildSize.x = Q3DStudio::MIN(theChildSize.x, theMaxSize.x);
+ theChildSize.y = Q3DStudio::MIN(theChildSize.y, theMaxSize.y);
+
+ inChild->SetSize(theChildSize);
+ ioPosition.x += theChildSize.x;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Resets all child positions accd to their size
+ */
+void CFlowLayout::ResetChildPositions()
+{
+ if ((m_FlowDirection == FLOW_HORIZONTAL && m_HorizontalAlignment != ALIGN_RIGHT)
+ || (m_FlowDirection == FLOW_VERTICAL && m_VerticalAlignment != ALIGN_BOTTOM)) {
+ CPt thePosition(m_LeftMargin, m_TopMargin);
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsVisible()) {
+ CPt theChildSize = theChild->GetSize();
+ if (m_FlowDirection == FLOW_VERTICAL) {
+ thePosition.x = theChild->GetPosition().x + m_LeftMargin;
+ theChild->SetPosition(thePosition);
+ thePosition.y = thePosition.y + theChildSize.y + m_ChildGap;
+ } else {
+ thePosition.y = theChild->GetPosition().y + m_TopMargin;
+ theChild->SetPosition(thePosition);
+ thePosition.x = thePosition.x + theChildSize.x + m_ChildGap;
+ }
+ }
+ }
+
+ if (m_HasUnusedSpace && m_BlankControl) {
+ CPt theBlankPosition;
+ if (m_FlowDirection == FLOW_HORIZONTAL) {
+ theBlankPosition.x = thePosition.x;
+ theBlankPosition.y = 0;
+ } else {
+ theBlankPosition.x = 0;
+ theBlankPosition.y = thePosition.y;
+ }
+ m_BlankControl->SetPosition(theBlankPosition);
+ m_BlankControl->SetSize(GetSize() - theBlankPosition);
+ }
+ } else {
+ CPt thePosition(GetSize() - CPt(m_RightMargin, m_BottomMargin));
+ ControlGraph::SReverseIterator thePos = GetReverseChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsVisible()) {
+ CPt theChildSize = theChild->GetSize();
+ if (m_FlowDirection == FLOW_VERTICAL) {
+ thePosition.x = theChild->GetPosition().x - m_RightMargin;
+ thePosition.y = thePosition.y - theChildSize.y - m_ChildGap;
+ theChild->SetPosition(thePosition);
+ } else {
+ thePosition.y = theChild->GetPosition().y - m_BottomMargin;
+ thePosition.x = thePosition.x - theChildSize.x - m_ChildGap;
+ theChild->SetPosition(thePosition);
+ }
+ }
+ }
+
+ if (m_HasUnusedSpace && m_BlankControl) {
+ CPt theBlankSize;
+ if (m_FlowDirection == FLOW_HORIZONTAL) {
+ theBlankSize.x = thePosition.x;
+ theBlankSize.y = GetSize().y;
+ } else {
+ theBlankSize.x = GetSize().x;
+ theBlankSize.y = thePosition.y;
+ }
+ m_BlankControl->SetPosition(CPt(0, 0));
+ m_BlankControl->SetSize(theBlankSize);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Resizes any expandable Controls in the Y Dir
+ *
+ * @param inExtraSpace the Amount left
+ * @param inNumExpandable used to calc percentages
+ */
+void CFlowLayout::ResizeExpandableControlsY(long inExtraSpace, long inNumExpandable)
+{
+ m_HasUnusedSpace = false;
+ long theSpaceDistributed = 0;
+ if (inExtraSpace / inNumExpandable < 1) {
+ this->DistributeRemaining(inExtraSpace);
+ } else {
+ ControlGraph::SIterator thePos = GetChildren();
+ long theNumExpandable = 0;
+
+ // Loop through teh children for items that can expand
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+
+ // If this item can be expanded then expand accd to new percent
+ if (CanBeExpandedY(theChild->GetControl()) && theChild->IsVisible()) {
+ CPt theMaxSize = theChild->GetMaximumSize();
+ CPt theChildSize = theChild->GetSize();
+ float theModifier = (float)1 / inNumExpandable;
+ if (theMaxSize.y < ::dtol((inExtraSpace * theModifier) + theChildSize.y)) {
+ theSpaceDistributed += theMaxSize.y - theChildSize.y;
+ theChildSize.y = theMaxSize.y;
+ } else {
+ theSpaceDistributed += ::dtol((inExtraSpace * theModifier));
+ theChildSize.y += ::dtol((inExtraSpace * theModifier));
+ ++theNumExpandable;
+ }
+
+ theChild->SetSize(theChildSize);
+ }
+ }
+
+ // If there is extra space and there are items able to expand still
+ if ((inExtraSpace - theSpaceDistributed) > 0) {
+ if (theNumExpandable > 0) {
+ this->ResizeExpandableControlsY((inExtraSpace - theSpaceDistributed),
+ theNumExpandable);
+ } else {
+ m_HasUnusedSpace = true;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Resizes any expandable Controls in the X Dir
+ *
+ * @param inExtraSpace the Amount left
+ * @param inNumExpandable used to calc percentages
+ */
+void CFlowLayout::ResizeExpandableControlsX(long inExtraSpace, long inNumExpandable)
+{
+ m_HasUnusedSpace = false;
+ long theSpaceDistributed = 0;
+ if (inExtraSpace / inNumExpandable < 1) {
+ this->DistributeRemaining(inExtraSpace);
+ } else {
+ long theNumExpandable = 0;
+ ControlGraph::SIterator thePos = GetChildren();
+ // Loop through teh children for items that can expand
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+
+ // If this item can be expanded then expand accd to new percent
+ if (CanBeExpandedX(theChild->GetControl()) && theChild->IsVisible()) {
+ CPt theMaxSize = theChild->GetMaximumSize();
+ CPt theChildSize = theChild->GetSize();
+ float theModifier = (float)1 / inNumExpandable;
+ if (theMaxSize.x < ::dtol((inExtraSpace * theModifier) + theChildSize.x)) {
+ theSpaceDistributed += theMaxSize.x - theChildSize.x;
+ theChildSize.x = theMaxSize.x;
+ } else {
+ theSpaceDistributed += ::dtol((inExtraSpace * theModifier));
+ theChildSize.x += ::dtol((inExtraSpace * theModifier));
+ ++theNumExpandable;
+ }
+
+ theChild->SetSize(theChildSize);
+ }
+ }
+
+ // If there is extra space and there are items able to expand still
+ if ((inExtraSpace - theSpaceDistributed) > 0) {
+ if (theNumExpandable > 0) {
+ this->ResizeExpandableControlsX((inExtraSpace - theSpaceDistributed),
+ theNumExpandable);
+ } else {
+ m_HasUnusedSpace = true;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Distributes remaining size to items that can be expanded.
+ * this should only be called when theNumExpandable items > the extra space
+ */
+void CFlowLayout::DistributeRemaining(long inExtraSpace)
+{
+ long theNumToDistribute = inExtraSpace;
+ if (m_FlowDirection == FLOW_VERTICAL) {
+ ControlGraph::SIterator thePos = GetChildren();
+ // Loop through teh children for items that can expand
+ for (; thePos.HasNext() && theNumToDistribute > 0; ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+
+ // If this item can be expanded then expand accd to new percent
+ if (CanBeExpandedY(theChild->GetControl()) && theChild->IsVisible()) {
+ CPt theChildSize = theChild->GetSize();
+ theChildSize.y++;
+ theChild->SetSize(theChildSize.x, theChildSize.y);
+ theNumToDistribute--;
+ }
+ }
+ } else {
+ ControlGraph::SIterator thePos = GetChildren();
+ // Loop through teh children for items that can expand
+ for (; thePos.HasNext() && theNumToDistribute > 0; ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+
+ // If this item can be expanded then expand accd to new percent
+ if (CanBeExpandedX(theChild->GetControl()) && theChild->IsVisible()) {
+ CPt theChildSize = theChild->GetSize();
+ theChildSize.x++;
+ theChild->SetSize(theChildSize.x, theChildSize.y);
+ theNumToDistribute--;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Gets the total prefered sizes of the children
+ */
+CPt CFlowLayout::GetTotalPreferredSizes()
+{
+ CPt theTotalPrefSizes(0, 0);
+
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsVisible()) {
+ theTotalPrefSizes += theChild->GetPreferredSize();
+ }
+ }
+
+ return theTotalPrefSizes;
+}
+
+//==============================================================================
+/**
+ * sets the size and does a recalc
+ */
+void CFlowLayout::SetSize(CPt inSize)
+{
+ if (inSize != GetSize()) {
+ CControl::SetSize(inSize);
+
+ RecalcLayout();
+ }
+}
+
+void CFlowLayout::SetLayout(CPt inSize, CPt inPosition)
+{
+ CControl::SetLayout(inSize, inPosition);
+
+ RecalcLayout();
+}
+//==============================================================================
+/**
+ * override to force a recalc when the parent is changed
+ */
+void CFlowLayout::OnParentChanged(CControl *inParent)
+{
+ CControl::OnParentChanged(inParent);
+ RecalcLayout();
+}
+
+//==============================================================================
+/**
+ * Sets this object's alignment
+ */
+void CFlowLayout::SetAlignment(EVerticalAlignment inVertical, EHorizontalAlignment inHorizontal)
+{
+ m_VerticalAlignment = inVertical;
+ m_HorizontalAlignment = inHorizontal;
+
+ RecalcLayout();
+}
+
+//==============================================================================
+/**
+ * Overloaded draw function. Draws the extra control if it is needed
+ */
+void CFlowLayout::Draw(CRenderer *inRenderer)
+{
+ // If there is unused space in this control, then use the blank control
+ if (m_HasUnusedSpace && m_BlankControl) {
+ if (m_BlankControl->IsVisible()) {
+ inRenderer->PushTranslation(m_BlankControl->GetPosition());
+ if (!m_BlankDisable)
+ m_BlankControl->Draw(inRenderer);
+ inRenderer->PopTranslation();
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * called when a child's size changes
+ */
+void CFlowLayout::OnChildSizeChanged(CControl *inChild)
+{
+ Q_UNUSED(inChild);
+
+ if (!m_ResizingChildren) {
+ ResetMinMaxPref();
+
+ if (GetParent() != nullptr)
+ GetParent()->OnChildSizeChanged(this);
+
+ RecalcLayout();
+ }
+}
+
+//==============================================================================
+/**
+ * Called to calc the min/max/and pre size of this layout. NOTE: this function
+ * no longer adjusts the max size of the flow layout. The max size is not dictated
+ * by the size of the children, so it can be set independently with a call to
+ * SetMaximumSize().
+ */
+void CFlowLayout::ResetMinMaxPref()
+{
+ if (m_AutoMin) {
+ CPt thePreferredSize(0, 0);
+ CPt theMinimumSize(0, 0);
+
+ thePreferredSize = theMinimumSize;
+
+ // Keep track of the largest, minimum size of all the children for use later
+ CPt theBiggestChildMinSize(0, 0);
+
+ // Go through all the children and find their maximum sizes.
+ ControlGraph::SIterator thePos = GetChildren();
+
+ for (; thePos.HasNext(); ++thePos) {
+ std::shared_ptr<CControlData> theChild = (*thePos);
+ if (theChild->IsVisible()) {
+ theChild->ResetMinMaxPref();
+ CPt theChildPrefSize = theChild->GetPreferredSize();
+ CPt theChildMinSize = theChild->GetMinimumSize();
+
+ // use the sum of the children in the flow direction and the smallest size
+ // in the non-flow direction.
+ if (m_FlowDirection == FLOW_VERTICAL) {
+ thePreferredSize.y += theChildPrefSize.y;
+
+ theMinimumSize.y += theChildMinSize.y;
+
+ if (theChildMinSize.x > theBiggestChildMinSize.x)
+ theBiggestChildMinSize = theChildMinSize;
+ } else {
+ thePreferredSize.x += theChildPrefSize.x;
+
+ theMinimumSize.x += theChildMinSize.x;
+
+ if (theChildMinSize.y > theBiggestChildMinSize.y)
+ theBiggestChildMinSize = theChildMinSize;
+ }
+ }
+ }
+
+ // If this is a vertical flow
+ if (m_FlowDirection == FLOW_VERTICAL) {
+ // The width is determined by minimum size of the largest child
+ theMinimumSize.x = theBiggestChildMinSize.x;
+
+ // If the flow is aligned to top, the top margin must be added to the minimum height
+ if (m_VerticalAlignment == ALIGN_TOP)
+ theMinimumSize.y += m_TopMargin;
+ // If the flow is aligned to bottom, the bottom margin must be added to the minimum
+ // height
+ else if (m_VerticalAlignment == ALIGN_BOTTOM)
+ theMinimumSize.y += m_BottomMargin;
+
+ theMinimumSize.y += (m_ChildGap * GetChildCount());
+ }
+ // If this is a horzontal flow
+ else {
+ // The height is determined by minimum size of the largest child
+ theMinimumSize.y = theBiggestChildMinSize.y;
+
+ // If the flow is left aligned, the left margin must be added to the minimum width
+ if (m_HorizontalAlignment == ALIGN_LEFT)
+ theMinimumSize.x += m_LeftMargin;
+ // If the flow is right aligned, the right margin must be added to the minimum width
+ else if (m_HorizontalAlignment == ALIGN_RIGHT)
+ theMinimumSize.x += m_RightMargin;
+
+ theMinimumSize.x += (m_ChildGap * GetChildCount());
+ }
+
+ thePreferredSize.x = max(thePreferredSize.x, theMinimumSize.x);
+ thePreferredSize.y = max(thePreferredSize.y, theMinimumSize.y);
+
+ SetMinimumSize(theMinimumSize);
+ SetPreferredSize(thePreferredSize);
+ }
+}
+
+//=============================================================================
+/**
+ * Override the default in case the blank control was hit
+ * @param inPoint where the mouse was clicked, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * @return true if the mouse event is processed.
+ */
+bool CFlowLayout::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = CControl::OnMouseDown(inPoint, inFlags);
+ if (!theRetVal) {
+ if (m_BlankControl && m_BlankControl->HitTest(inPoint))
+ GrabFocus(nullptr);
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Override the default in case the blank control was hit
+ * @param inPoint where the mouse was clicked, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * @return true if the mouse event is processed.
+ */
+bool CFlowLayout::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = CControl::OnMouseRDown(inPoint, inFlags);
+ if (!theRetVal) {
+ if (m_BlankControl && m_BlankControl->HitTest(inPoint))
+ GrabFocus(nullptr);
+ }
+ return theRetVal;
+}
diff --git a/src/Authoring/Studio/Controls/FlowLayout.h b/src/Authoring/Studio/Controls/FlowLayout.h
new file mode 100644
index 00000000..1f7523a1
--- /dev/null
+++ b/src/Authoring/Studio/Controls/FlowLayout.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_FLOW_LAYOUT_H
+#define INCLUDED_FLOW_LAYOUT_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "BlankControl.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+
+//==============================================================================
+/**
+* @class CFlowLayout
+* @brief CHRIS.EDWARDS needs to enter a brief description here.
+*
+* CHRIS.EDWARDS needs to enter a long description here.
+*/
+class CFlowLayout : public CControl
+{
+public:
+ enum EFlowDirection {
+ FLOW_VERTICAL,
+ FLOW_HORIZONTAL,
+ };
+
+ enum EVerticalAlignment {
+ ALIGN_TOP,
+ ALIGN_BOTTOM,
+ ALIGN_CENTER,
+ ALIGN_VERT_NEITHER,
+ };
+
+ enum EHorizontalAlignment {
+ ALIGN_LEFT,
+ ALIGN_RIGHT,
+ ALIGN_MIDDLE,
+ ALIGN_HORIZ_NEITHER,
+ };
+
+ CFlowLayout(CControl *inControl = nullptr, bool inUseControl = true);
+ virtual ~CFlowLayout();
+
+ DEFINE_OBJECT_COUNTER(CFlowLayout)
+
+ void SetSize(CPt inSize) override;
+ void SetLayout(CPt inSize, CPt inPosition) override;
+ void OnParentChanged(CControl *inParent) override;
+
+ void SetAlignment(EVerticalAlignment inVertical, EHorizontalAlignment inHorizontal);
+ long SetLeftMargin(long inMargin);
+ long GetLeftMargin() const;
+ long SetRightMargin(long inMargin);
+ long GetRightMargin() const;
+ long SetTopMargin(long inMargin);
+ long GetTopMargin() const;
+ long SetBottomMargin(long inMargin);
+ long GetBottomMargin() const;
+ long SetGapBetweenChildren(long inGap);
+ void SetDebug(bool inFlag) { m_DebugFlag = inFlag; }
+ void SetAutoMin(bool inFlag) { m_AutoMin = inFlag; }
+
+ virtual void SetFlowDirection(EFlowDirection inFlowDirection);
+ void AddChild(CControl *inControl, CControl *inInsertBefore = nullptr) override;
+ void RemoveChild(CControl *inControl) override;
+ void Draw(CRenderer *inRenderer) override;
+ virtual void DisableBlank();
+ void OnChildSizeChanged(CControl *inControl) override;
+
+ virtual void RecalcLayout();
+ void SuspendRecalcLayout(bool inSuspendFlag);
+ void ResetMinMaxPref() override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+protected:
+ CPt GetTotalPreferredSizes();
+ void ResizeExpandableControlsY(long inExtraSpace, long inNumExpandable);
+ void ResizeExpandableControlsX(long inExtraSpace, long inNumExpandable);
+ void ResetChildPositions();
+ void DistributeRemaining(long inExtraSpace);
+ void RecalcChild(CControl *inChild, CPt &ioPosition, long &ioNumExpandableX,
+ long &ioNumExpandableY);
+
+ bool m_HasUnusedSpace;
+ bool m_BlankDisable;
+ EFlowDirection m_FlowDirection;
+ EVerticalAlignment m_VerticalAlignment;
+ EHorizontalAlignment m_HorizontalAlignment;
+ bool m_ResizingChildren;
+ long m_LeftMargin; ///< gap at left of this control
+ long m_RightMargin; ///< gap at right of this control
+ long m_TopMargin; ///< gap at top of this control
+ long m_BottomMargin; ///< gap at bottom of this control
+ long m_ChildGap; ///< gap between each child control when laying out everything
+ bool m_DebugFlag;
+ bool m_AutoMin;
+
+ bool m_SuspendRecalcLayout; ///< flag to suspend recalculation of the layout; slow down is
+ ///noticeable if this control has many children
+
+private:
+ CControl *m_BlankControl; ///< used when all items are at their max and there si still space
+};
+
+#endif // INCLUDED_FLOW_LAYOUT_H
diff --git a/src/Authoring/Studio/Controls/GenericComboDropDown.h b/src/Authoring/Studio/Controls/GenericComboDropDown.h
new file mode 100644
index 00000000..cd95b3a2
--- /dev/null
+++ b/src/Authoring/Studio/Controls/GenericComboDropDown.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_GENERIC_COMBO_DROP_DOWN_H
+#define INCLUDED_GENERIC_COMBO_DROP_DOWN_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "GenericEdit.h"
+#include "ComboTextBox.h"
+
+#include <QMenu>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CButtonControl;
+class CButtonUpListener;
+
+//==============================================================================
+/**
+ * Combo-box GUI element. Allows user to choose from a list of strings, and the
+ * selected string is displayed in a box.
+ */
+class CGenericComboDropDown : public CGenericEdit, public IChangeDataListener
+{
+public:
+ CGenericComboDropDown(const bool inUseFloat = false);
+ virtual ~CGenericComboDropDown();
+
+ void OnDropDownSelect();
+ void OnButtonUp(CControl *inButton);
+ bool CanGainFocus() override;
+ void AddItem(const Q3DStudio::CString &inString, bool inEnable = true);
+ void RemoveAllItems();
+ void SelectItem(long inIndex, bool inFireChangeEvent = true);
+ long GetSelectedItem();
+ long GetItemCount();
+ Q3DStudio::CString GetItemText(long inIndex);
+ Q3DStudio::CString GetCurrentText();
+
+ virtual long DoDropDownMenu();
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags) override;
+ bool OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags) override;
+ void LayoutChildren() override { CGenericEdit::LayoutChildren(); }
+
+ // IChangeDataListener
+ void OnChangeData(const Q3DStudio::CString &inOldString,
+ const Q3DStudio::CString &inNewString) override;
+
+protected:
+ virtual void ChangeSelection(long inNewSelection);
+ virtual void OffsetSelection(long inAmount);
+ void SetDisplayText(const Q3DStudio::CString &inString, bool inFireChangeEvent = true);
+ void UpdateReadOnly(bool inReadOnlyFlag);
+
+ long m_SelectedItem;
+ Q3DStudio::CString m_CurrentText;
+ CComboTextBox *m_TextBox; ///< ComboTextBox (StringEdit derivative) that processes text data
+ CButtonControl *m_Button;
+ QMenu m_DropDownMenu; ///< Context menu used to display a list of options for the control
+ QActionGroup m_actionGroup;
+ bool m_ReverseOffset; ///< True if we want the mousewheel to scroll the other direction in the
+ ///list;useful for numerical lists like
+};
+
+#endif // INCLUDED_GENERIC_COMBO_DROP_DOWN_H
diff --git a/src/Authoring/Studio/Controls/GenericEdit.h b/src/Authoring/Studio/Controls/GenericEdit.h
new file mode 100644
index 00000000..5af96a6b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/GenericEdit.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_GENERIC_EDIT_H
+#define INCLUDED_GENERIC_EDIT_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "LazyFlow.h"
+#include "Multicaster.h"
+#include "CColor.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//==============================================================================
+// Functors
+//==============================================================================
+/// Function to be called when the edit control changes
+GENERIC_FUNCTOR(CGenericEditCommitListener, OnCommitData);
+GENERIC_FUNCTOR(CGenericEditChangeListener, OnChangeData);
+GENERIC_FUNCTOR(CGenericEditRevertListener, OnRevertData);
+
+//==============================================================================
+/**
+ * Base class for most edit controls. Provides functions for adding/removing/
+ * notifying listeners when the control's value changes. Implements some
+ * common functionality across all edit controls.
+ */
+class CGenericEdit : public Q3DStudio::Control::CRuntimeLazyFlow
+{
+public:
+ CGenericEdit();
+ virtual ~CGenericEdit();
+
+ void AddCommitListener(CGenericEditCommitListener *inListener);
+ void RemoveCommitListener(CGenericEditCommitListener *inListener);
+ void FireCommitDataEvent();
+
+ void AddChangeListener(CGenericEditChangeListener *inListener);
+ void RemoveChangeListener(CGenericEditChangeListener *inListener);
+ void FireChangeDataEvent();
+
+ void AddRevertListener(CGenericEditRevertListener *inListener);
+ void RemoveRevertListener(CGenericEditRevertListener *inListener);
+ void FireRevertDataEvent();
+
+ void SetFillBackground(bool inFill);
+ void SetBackgroundColor(const ::CColor &inColor);
+
+ // CControl
+ void Draw(CRenderer *inRenderer);
+
+protected:
+ CMulticaster<CGenericEditCommitListener *> m_CommitListeners;
+ CMulticaster<CGenericEditChangeListener *> m_ChangeListeners;
+ CMulticaster<CGenericEditRevertListener *> m_RevertListeners;
+ bool m_FillBackground;
+ ::CColor m_BackgroundColor;
+};
+
+#endif // INCLUDED_GENERIC_EDIT_H
diff --git a/src/Authoring/Studio/Controls/InsertionLine.cpp b/src/Authoring/Studio/Controls/InsertionLine.cpp
new file mode 100644
index 00000000..5edbcd93
--- /dev/null
+++ b/src/Authoring/Studio/Controls/InsertionLine.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "InsertionLine.h"
+#include "Renderer.h"
+#include "ResourceCache.h"
+#include "StudioUtils.h"
+#include "CColor.h"
+#include "CoreUtils.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CInsertionLine::CInsertionLine()
+ : m_LineWidth(0)
+ , m_LineHeight(2)
+ , m_LineColor(CColor(0, 0, 0))
+{
+ SetVisible(false);
+
+ m_InsertLeftImage = CResourceCache::GetInstance()->GetBitmap("Insert-Rearrange-Left.png");
+ m_InsertRightImage = CResourceCache::GetInstance()->GetBitmap("Insert-Rearrange-Right.png");
+
+ const auto theLeftSize = m_InsertLeftImage.size();
+ const auto theRightSize = m_InsertRightImage.size();
+
+ if (theLeftSize.height() >= theRightSize.width()) {
+ SetSize(CPt(theLeftSize.width() + theRightSize.width(), theLeftSize.height()));
+ SetMaximumSize(CPt(LONG_MAX, theLeftSize.height()));
+ } else {
+ SetSize(CPt(theLeftSize.width() + theRightSize.width(), theRightSize.height()));
+ SetMaximumSize(CPt(LONG_MAX, theLeftSize.height()));
+ }
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CInsertionLine::~CInsertionLine()
+{
+}
+
+//=============================================================================
+/**
+ * Sets the position of the line. Overridden since the line is technically
+ * drawn in the middle of the area specified as the size of this control, so
+ * we have to adjust the point accordingly. If you specify that the line should
+ * be drawn at inPoint = ( 100, 100 ), the line will be drawn there, but the
+ * actual control will be positioned at y = 100 - m_LineHeight.
+ * @param inPoint starting point of the line to be drawn
+ */
+void CInsertionLine::SetPosition(CPt inPoint)
+{
+ inPoint.y -= m_LineHeight;
+ COverlayControl::SetPosition(inPoint);
+}
+
+//=============================================================================
+/**
+ * Sets the width of the horizontal line. The arrows on the ends will
+ * automatically overlap this line. Thus the control will be exactly as wide
+ * as you specify here. You should call this method instead of SetSize.
+ * @param inWidth The new width of the line
+ */
+void CInsertionLine::SetLineWidth(long inWidth)
+{
+ m_LineWidth = inWidth;
+
+ SetSize(CPt(m_LineWidth, GetSize().y));
+}
+
+//=============================================================================
+/**
+ * Draws the insertion line at the current position.
+ * @param inRenderer Renderer to draw to
+ */
+void CInsertionLine::Draw(CRenderer *inRenderer)
+{
+ // Actual insertion line
+ CPt theTotalSize = GetSize();
+ inRenderer->FillSolidRect(
+ CRct(CPt(0, ::dtol(theTotalSize.y / 2.0f) - ::dtol(m_LineHeight / 2.0f)),
+ CPt(m_LineWidth, m_LineHeight)),
+ m_LineColor);
+
+ // Left arrow (draws on top of the left side of the line)
+ inRenderer->DrawBitmap(QPoint(0, 0), m_InsertLeftImage);
+
+ // Right arrow (draws on top of the right side of the line)
+ const auto theRightSize = m_InsertRightImage.size();
+ inRenderer->DrawBitmap(QPoint(theTotalSize.x - theRightSize.width(), 0), m_InsertRightImage);
+}
+
+//=============================================================================
+/**
+ * Check to see if inPoint is over this control or not. Overridden so that
+ * this overlay control does not interfere with drag-and-drop.
+ * @param inPoint not used
+ * @return false
+ */
+bool CInsertionLine::HitTest(const CPt &inPoint) const
+{
+ Q_UNUSED(inPoint);
+
+ return false;
+}
diff --git a/src/Authoring/Studio/Controls/InsertionLine.h b/src/Authoring/Studio/Controls/InsertionLine.h
new file mode 100644
index 00000000..60ec01bf
--- /dev/null
+++ b/src/Authoring/Studio/Controls/InsertionLine.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_INSERTION_LINE_H
+#define INCLUDED_INSERTION_LINE_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "OverlayControl.h"
+#include "CColor.h"
+
+#include <QPixmap>
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//=============================================================================
+/**
+ * Class for drawing a horizontal insertion line on top of other controls.
+ * Useful for indicating drag-and-drop locations. Example usage: Item is
+ * being inserted between Item1 and Item2.
+ * Item1
+ * >----<
+ * Item2
+ */
+class CInsertionLine : public COverlayControl
+{
+public:
+ CInsertionLine();
+ virtual ~CInsertionLine();
+ virtual void SetPosition(CPt inPoint);
+ void SetLineWidth(long inWidth);
+ virtual void Draw(CRenderer *inRenderer);
+ virtual bool HitTest(const CPt &inPoint) const;
+
+protected:
+ long m_LineWidth;
+ long m_LineHeight;
+ CColor m_LineColor;
+ QPixmap m_InsertLeftImage;
+ QPixmap m_InsertRightImage;
+};
+#endif // INCLUDED_INSERTION_LINE_H
diff --git a/src/Authoring/Studio/Controls/InsertionOverlay.cpp b/src/Authoring/Studio/Controls/InsertionOverlay.cpp
new file mode 100644
index 00000000..fc26f68c
--- /dev/null
+++ b/src/Authoring/Studio/Controls/InsertionOverlay.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "InsertionOverlay.h"
+#include "Renderer.h"
+#include "ResourceCache.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CInsertionOverlay::CInsertionOverlay()
+ : m_Width(0)
+{
+ SetVisible(false);
+
+ m_InsertLeftImage = CResourceCache::GetInstance()->GetBitmap("Insert-Left.png");
+ m_InsertRightImage = CResourceCache::GetInstance()->GetBitmap("Insert-Right.png");
+
+ const auto theLeftSize = m_InsertLeftImage.size();
+ const auto theRightSize = m_InsertRightImage.size();
+
+ if (theLeftSize.height() >= theRightSize.height())
+ SetSize(CPt(theLeftSize.width() + theRightSize.width(), theLeftSize.height()));
+ else
+ SetSize(CPt(theLeftSize.width() + theRightSize.width(), theRightSize.height()));
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CInsertionOverlay::~CInsertionOverlay()
+{
+}
+
+//=============================================================================
+/**
+ * Sets the width of the control. The arrows are always drawn at the left
+ * and right side of the control, as defined by this width.
+ * @param inWidth total width of the control
+ */
+void CInsertionOverlay::SetWidth(long inWidth)
+{
+ m_Width = inWidth;
+
+ SetSize(CPt(m_Width, GetSize().y));
+}
+
+//=============================================================================
+/**
+ * Draws the insertion markers.
+ * Draws arrows at the left and right sides of the control, as defined by m_Width.
+ * @param inRenderer Renderer to draw to
+ */
+void CInsertionOverlay::Draw(CRenderer *inRenderer)
+{
+ // Left arrow
+ inRenderer->DrawBitmap(CPt(0, 0), m_InsertLeftImage);
+
+ // Right arrow
+ const auto theRightSize = m_InsertRightImage.size();
+ inRenderer->DrawBitmap(QPoint(m_Width - theRightSize.width(), 0), m_InsertRightImage);
+}
+
+//=============================================================================
+/**
+ * Check to see if inPoint is over this control or not. Overridden so that
+ * this overlay control does not interfere with drag-and-drop.
+ * @param inPoint not used
+ * @return false
+ */
+bool CInsertionOverlay::HitTest(const CPt &inPoint) const
+{
+ Q_UNUSED(inPoint);
+
+ return false;
+}
diff --git a/src/Authoring/Studio/Controls/InsertionOverlay.h b/src/Authoring/Studio/Controls/InsertionOverlay.h
new file mode 100644
index 00000000..0e43af3b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/InsertionOverlay.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_INSERTION_OVERLAY_H
+#define INCLUDED_INSERTION_OVERLAY_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "OverlayControl.h"
+
+#include <QPixmap>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+
+//=============================================================================
+/**
+ * In drag-and-drop operations it's often desirable to indicate when you are
+ * dropping an item onto another item. This control gives that visual
+ * representation by drawing an arrow at either side. Example: Item2 is selected.
+ * + Item1
+ * > + Item2 <
+ * + Item3
+ */
+class CInsertionOverlay : public COverlayControl
+{
+public:
+ CInsertionOverlay();
+ virtual ~CInsertionOverlay();
+ void SetWidth(long inWidth);
+ virtual void Draw(CRenderer *inRenderer);
+ virtual bool HitTest(const CPt &inPoint) const;
+
+protected:
+ long m_Width;
+ QPixmap m_InsertLeftImage;
+ QPixmap m_InsertRightImage;
+};
+#endif // INCLUDED_INSERTION_OVERLAY_H
diff --git a/src/Authoring/Studio/Controls/LazyFlow.cpp b/src/Authoring/Studio/Controls/LazyFlow.cpp
new file mode 100644
index 00000000..8b8e74fe
--- /dev/null
+++ b/src/Authoring/Studio/Controls/LazyFlow.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "LazyFlow.h"
+#include "ControlData.h"
+
+using namespace Q3DStudio::Control;
+
+template <typename TIteratorType>
+struct SVisibleFilteredIterator
+{
+ TIteratorType m_BaseIterator;
+ SVisibleFilteredIterator(TIteratorType inIter)
+ : m_BaseIterator(inIter)
+ {
+ FindNextValidItem();
+ }
+ void FindNextValidItem()
+ {
+ while (m_BaseIterator.IsDone() == false
+ && m_BaseIterator.GetCurrent()->IsVisible() == false)
+ ++m_BaseIterator;
+ }
+
+ SVisibleFilteredIterator<TIteratorType> &operator++()
+ {
+ ++m_BaseIterator;
+ FindNextValidItem();
+ return *this;
+ }
+ std::shared_ptr<CControlData> operator*() { return *m_BaseIterator; }
+ bool IsDone() { return m_BaseIterator.IsDone(); }
+};
+
+struct SaneMinMaxPref : public SSizeGroup
+{
+ SaneMinMaxPref(const SSizeGroup &inData)
+ : SSizeGroup(inData)
+ {
+ // ensure max and pref are greater than or equal to minimum
+ m_Pref.x = max(m_Pref.x, m_Min.x);
+ m_Pref.y = max(m_Pref.y, m_Min.y);
+ m_Max.x = max(m_Max.x, m_Min.x);
+ m_Max.y = max(m_Max.y, m_Min.y);
+
+ // Ensure the maximum has valid information
+ if (m_Max.x == 0)
+ m_Max.x = m_Pref.x;
+ if (m_Max.y == 0)
+ m_Max.y = m_Pref.y;
+
+ // Ensure preference is no greater than the maximum
+ m_Pref.x = min(m_Pref.x, m_Max.x);
+ m_Pref.y = min(m_Pref.y, m_Max.y);
+ }
+};
+
+CPt CLazyFlowBase::GetMinimumSize()
+{
+ MaybeRecalcMinMaxPerf();
+ return CControl::GetMinimumSize();
+}
+CPt CLazyFlowBase::GetPreferredSize()
+{
+ MaybeRecalcMinMaxPerf();
+ return CControl::GetPreferredSize();
+}
+CPt CLazyFlowBase::GetMaximumSize()
+{
+ MaybeRecalcMinMaxPerf();
+ return CControl::GetMaximumSize();
+}
+
+void CLazyFlowBase::LayoutChildren()
+{
+ TControlSizeList theSizeList;
+ DistributeChildSizes(theSizeList);
+ PerformLayout(theSizeList);
+ Invalidate();
+}
+
+void CLazyFlowBase::MarkChildrenNeedLayout()
+{
+ m_MinMaxPreferredDirty = true;
+ CControl::MarkChildrenNeedLayout();
+}
+
+void CLazyFlowBase::NotifyParentNeedsLayout()
+{
+ if (m_CalculatingMinMaxPref == false)
+ CControl::NotifyParentNeedsLayout();
+}
+
+void CLazyFlowBase::SetLayout(CPt inSize, CPt inPosition)
+{
+ bool wasDirty = m_MinMaxPreferredDirty;
+ CControl::SetLayout(inSize, inPosition);
+ m_MinMaxPreferredDirty = wasDirty;
+}
+
+long CLazyFlowBase::GetGapTotal()
+{
+ long theNumVisibleChildren = 0;
+
+ // Ensure we don't count any gaps for children that are invisible
+ for (SVisibleFilteredIterator<ControlGraph::SIterator> theIter = GetChildren();
+ theIter.IsDone() == false; ++theIter, ++theNumVisibleChildren) {
+ }
+
+ if (theNumVisibleChildren > 0)
+ return m_ChildGap * theNumVisibleChildren;
+
+ return 0;
+}
+
+void CLazyFlowBase::DistributeChildSizes(TControlSizeList &ioList)
+{
+ ILazyFlowLayoutSpecializer &theSpecializer(GetSpecializer());
+ SSizeGroup theChildSizes(CalcChildrenMinMaxPref());
+ CPt theMin(theChildSizes.m_Min);
+ CPt thePref(theChildSizes.m_Pref);
+
+ CPt theSize = GetSize();
+ long &theSizeSum(theSpecializer.GetSummedVariable(theSize));
+ long &theSizeMax = theSpecializer.GetMaxedVariable(theSize);
+
+ long theTotalInlineMargin =
+ ILazyFlowLayoutSpecializer::SafeSum(GetBeginMargin(), GetEndMargin());
+ // long theTotalBesideMargin = ILazyFlowLayoutSpecializer::SafeSum( GetBeforeRowMargin(),
+ // GetAfterRowMargin() );
+ long theGapTotal(GetGapTotal());
+ // Remove child independent size information.
+ theSizeSum = theSizeSum - theGapTotal - theTotalInlineMargin;
+ theSizeMax = theSizeMax - GetBeforeRowMargin() - GetAfterRowMargin();
+
+ // sanitize the size after we remove the child indepedent size information
+ theSize.x = max(theMin.x, theSize.x);
+ theSize.y = max(theMin.y, theSize.y);
+
+ // If we have more space than we can use.
+ if (theSizeSum >= theSpecializer.GetSummedVariable(thePref)) {
+ vector<long> theResizeableChildren;
+ long theIndex = 0;
+ CPt theLayoutRect;
+ for (SVisibleFilteredIterator<ControlGraph::SIterator> theIter = GetChildren();
+ theIter.IsDone() == false; ++theIter, ++theIndex) {
+ std::shared_ptr<CControlData> theChildControl(*theIter);
+ SaneMinMaxPref saneSizes(GetChildSizes(*theIter));
+ long theSaneMax(theSpecializer.GetMaxedVariable(saneSizes.m_Max));
+ CPt newSize(theSpecializer.ToPoint(theSpecializer.GetSummedVariable(saneSizes.m_Pref),
+ min(theSizeMax, theSaneMax)));
+ theLayoutRect = theSpecializer.SumMax(theLayoutRect, newSize);
+ ioList.push_back(make_pair(theChildControl, newSize));
+ if (theSpecializer.GetSummedVariable(saneSizes.m_Max) == LONG_MAX)
+ theResizeableChildren.push_back(theIndex);
+ }
+
+ long theRectSum = theSpecializer.GetSummedVariable(theLayoutRect);
+ if (theResizeableChildren.size() && theSizeSum > theRectSum) {
+ long extra = (theSizeSum - theRectSum) / (long)theResizeableChildren.size();
+ for (vector<long>::iterator theIter = theResizeableChildren.begin(),
+ theEnd = theResizeableChildren.end();
+ theIter != theEnd; ++theIter) {
+ pair<std::shared_ptr<CControlData>, CPt> &theChildAndSize(ioList[*theIter]);
+ CPt theNewSize = theChildAndSize.second;
+ theNewSize =
+ theSpecializer.ToPoint(theSpecializer.GetSummedVariable(theNewSize) + extra,
+ theSpecializer.GetMaxedVariable(theNewSize));
+ theChildAndSize.second = theNewSize;
+ }
+ }
+ } else {
+ long theMinSum = theSpecializer.GetSummedVariable(theMin);
+ long thePrefSum = theSpecializer.GetSummedVariable(thePref);
+ long minSizeX = max(theMinSum, theSizeSum);
+ // We know that we got less than the pref size.
+ long requestRange = thePrefSum - theMinSum;
+ long actualRange = minSizeX - theMinSum;
+ float ratio = 0.0f;
+ if (requestRange != 0)
+ ratio = (float)actualRange / (float)requestRange;
+
+ // so we distribute the remaining to each object based on the ratio between
+ // its preferred size to its minimums size, thus reducing each object equally
+ // but on terms of the ratio between it's preferred size and minimum size.
+ for (SVisibleFilteredIterator<ControlGraph::SIterator> theIter = GetChildren();
+ theIter.IsDone() == false; ++theIter) {
+ SaneMinMaxPref saneSizes(GetChildSizes(*theIter));
+ std::shared_ptr<CControlData> theChildControl(*theIter);
+ CPt childPref(saneSizes.m_Pref);
+ CPt childMin(saneSizes.m_Min);
+ long range = theSpecializer.GetSummedVariable(childPref)
+ - theSpecializer.GetSummedVariable(childMin);
+ long newRange = (long)((float)range * ratio + .5f);
+ long newMin = theSpecializer.GetSummedVariable(childMin);
+ CPt newSize = theSpecializer.ToPoint(newMin + newRange, theSizeMax);
+ ioList.push_back(make_pair(theChildControl, newSize));
+ }
+ }
+}
+
+void CLazyFlowBase::PerformLayout(TControlSizeList &ioList)
+{
+ ILazyFlowLayoutSpecializer &theSpecializer(GetSpecializer());
+ CPt thePos(theSpecializer.ToPoint(GetBeginMargin(), GetBeforeRowMargin()));
+ long &theSummedVar = theSpecializer.GetSummedVariable(thePos);
+
+ for (TControlSizeList::iterator iter = ioList.begin(), end = ioList.end(); iter != end;
+ ++iter) {
+ iter->first->SetLayout(iter->second, thePos);
+ // Bump the position out to the next object
+ theSummedVar += theSpecializer.GetSummedVariable(iter->second) + m_ChildGap;
+ }
+}
+
+// Ignoring margins, calculate the min,max, and preferred sizes of the aggregate of our children
+SSizeGroup CLazyFlowBase::CalcChildrenMinMaxPref()
+{
+ ILazyFlowLayoutSpecializer &theSpecializer(GetSpecializer());
+ SSizeGroup retval;
+ for (SVisibleFilteredIterator<ControlGraph::SIterator> theIter = GetChildren();
+ theIter.IsDone() == false; ++theIter) {
+ SaneMinMaxPref saneSizes(GetChildSizes(*theIter));
+ retval.m_Min = theSpecializer.SumMax(retval.m_Min, saneSizes.m_Min);
+ retval.m_Max = theSpecializer.SumMax(retval.m_Max, saneSizes.m_Max);
+ retval.m_Pref = theSpecializer.SumMax(retval.m_Pref, saneSizes.m_Pref);
+ }
+ return retval;
+}
+
+void CLazyFlowBase::RecalcMinMaxPref()
+{
+ ILazyFlowLayoutSpecializer &theSpecializer(GetSpecializer());
+ // Vertical means that we take the max of the x widths
+ // and sum the y heights;
+ // ensuring that LONG_MAX always sums to LONG_MAX
+ long theRowMargin =
+ ILazyFlowLayoutSpecializer::SafeSum(GetBeforeRowMargin(), GetAfterRowMargin());
+ CPt theMin(theSpecializer.ToPoint(GetBeginMargin() + GetEndMargin(), theRowMargin));
+ CPt theMax(theMin);
+ CPt thePref(theMin);
+ SSizeGroup theChildSizes(CalcChildrenMinMaxPref());
+ theMin = theSpecializer.SumMax(theChildSizes.m_Min, theMin);
+ theMax = theSpecializer.SumMax(theChildSizes.m_Max, theMax);
+ thePref = theSpecializer.SumMax(theChildSizes.m_Pref, thePref);
+
+ long theGapTotal(GetGapTotal());
+ theMin = theSpecializer.ToPoint(
+ ILazyFlowLayoutSpecializer::SafeSum(theSpecializer.GetSummedVariable(theMin), theGapTotal),
+ ILazyFlowLayoutSpecializer::SafeSum(theSpecializer.GetMaxedVariable(theMin), theRowMargin));
+
+ thePref = theSpecializer.ToPoint(
+ ILazyFlowLayoutSpecializer::SafeSum(theSpecializer.GetSummedVariable(thePref), theGapTotal),
+ ILazyFlowLayoutSpecializer::SafeSum(theSpecializer.GetMaxedVariable(thePref),
+ theRowMargin));
+
+ theMax = theSpecializer.ToPoint(
+ ILazyFlowLayoutSpecializer::SafeSum(theSpecializer.GetSummedVariable(theMax), theGapTotal),
+ ILazyFlowLayoutSpecializer::SafeSum(theSpecializer.GetMaxedVariable(theMax), theRowMargin));
+
+ // Let's ensure we keep sane min,max,etc.
+ thePref.x = max(thePref.x, theMin.x);
+ thePref.y = max(thePref.y, theMin.y);
+ theMax.x = max(theMax.x, theMin.x);
+ theMax.y = max(theMax.y, theMin.y);
+
+ SetMinimumSize(theMin);
+ SetPreferredSize(thePref);
+ SetMaximumSize(theMax);
+}
+
+void CLazyFlowBase::MaybeRecalcMinMaxPerf() const
+{
+ if (m_MinMaxPreferredDirty) {
+ m_MinMaxPreferredDirty = false;
+ if (m_AutoMinMaxPref) {
+ m_CalculatingMinMaxPref = true;
+ CLazyFlowBase &flow(const_cast<CLazyFlowBase &>(*this));
+ flow.RecalcMinMaxPref();
+ m_CalculatingMinMaxPref = false;
+ }
+ }
+}
+
+SSizeGroup CLazyFlowBase::GetChildSizes(std::shared_ptr<CControlData> inControl)
+{
+ SSizeGroup theGroup;
+ theGroup.m_Min = inControl->GetMinimumSize();
+ theGroup.m_Max = inControl->GetMaximumSize();
+ theGroup.m_Pref = inControl->GetPreferredSize();
+ return theGroup;
+}
diff --git a/src/Authoring/Studio/Controls/LazyFlow.h b/src/Authoring/Studio/Controls/LazyFlow.h
new file mode 100644
index 00000000..c5fb7fd3
--- /dev/null
+++ b/src/Authoring/Studio/Controls/LazyFlow.h
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef LAZYFLOWH
+#define LAZYFLOWH
+#include "Control.h"
+
+#ifdef WIN32
+#include <minmax.h>
+#endif
+
+namespace Q3DStudio {
+namespace Control {
+
+ // Specializers used to specialize the layout algorithm in the X or Y direction.
+ // You could, in fact, specialzie the algorithm in any arbitrary direction including
+ // 3d where components are sumed in the chosen direction and maxed in any other
+ // orthogonal non-chosen directions.
+
+ // Specializes the general layout algorithm in the x or y direction.
+ struct ILazyFlowLayoutSpecializer
+ {
+ protected:
+ virtual ~ILazyFlowLayoutSpecializer() {}
+
+ public:
+ static inline long SafeSum(long lhs, long rhs)
+ {
+ if (lhs == LONG_MAX || rhs == LONG_MAX)
+ return LONG_MAX;
+ return lhs + rhs;
+ }
+ // These functions allow us to apply the lazy flow layout algorithm to
+ // either horizontal or vertical layouts.
+ // Sum the variable in the direction we are going, and max any other variables
+ CPt SumMax(const CPt &inCurrentSum, const CPt &inOther)
+ {
+ long curSum = GetSummedVariable(inCurrentSum);
+ long nextSum = GetSummedVariable(inOther);
+ long resultSum = SafeSum(curSum, nextSum);
+#ifdef WIN32
+ // windows.h redefines max
+ long resultMax = max(GetMaxedVariable(inCurrentSum), GetMaxedVariable(inOther));
+#else
+ long resultMax = std::max(GetMaxedVariable(inCurrentSum), GetMaxedVariable(inOther));
+#endif
+ return ToPoint(resultSum, resultMax);
+ }
+ // Return the summed variable
+ virtual long &GetSummedVariable(CPt &inPt) = 0;
+ const long &GetSummedVariable(const CPt &inPt)
+ {
+ return GetSummedVariable(const_cast<CPt &>(inPt));
+ }
+ // return the maxed variable
+ virtual long &GetMaxedVariable(CPt &inPt) = 0;
+ const long &GetMaxedVariable(const CPt &inPt)
+ {
+ return GetMaxedVariable(const_cast<CPt &>(inPt));
+ }
+ // Create a new point from the combination of a summed variable and a maxed variable.
+ virtual CPt ToPoint(long inSummedVariable, long inMaxedVariable) = 0;
+ };
+
+ struct SVerticalLayoutSpecializer : public ILazyFlowLayoutSpecializer
+ {
+ long &GetSummedVariable(CPt &inPt) override { return inPt.y; }
+ long &GetMaxedVariable(CPt &inPt) override { return inPt.x; }
+ CPt ToPoint(long inSummedVariable, long inMaxedVariable) override
+ {
+ return CPt(inMaxedVariable, inSummedVariable);
+ }
+ };
+
+ struct SHorizontalLayoutSpecializer : public ILazyFlowLayoutSpecializer
+ {
+ long &GetSummedVariable(CPt &inPt) override { return inPt.x; }
+ long &GetMaxedVariable(CPt &inPt) override { return inPt.y; }
+ CPt ToPoint(long inSummedVariable, long inMaxedVariable) override
+ {
+ return CPt(inSummedVariable, inMaxedVariable);
+ }
+ };
+
+ struct SSizeGroup
+ {
+ CPt m_Min;
+ CPt m_Max;
+ CPt m_Pref;
+ };
+
+ class CLazyFlowBase : public CControl
+ {
+ mutable bool m_MinMaxPreferredDirty;
+ mutable bool m_CalculatingMinMaxPref;
+ bool m_AutoMinMaxPref;
+ CPt m_BeginMargin;
+ CPt m_EndMargin;
+
+ public:
+ typedef vector<pair<std::shared_ptr<CControlData>, CPt>> TControlSizeList;
+
+ CLazyFlowBase()
+ : m_MinMaxPreferredDirty(true)
+ , m_CalculatingMinMaxPref(false)
+ , m_AutoMinMaxPref(true)
+ , m_ChildGap(0)
+ {
+ }
+
+ CPt GetMinimumSize() override;
+ CPt GetPreferredSize() override;
+ CPt GetMaximumSize() override;
+
+ virtual void SetGapBetweenChildren(long inGap)
+ {
+ m_ChildGap = inGap;
+ MarkChildrenNeedLayout();
+ }
+ virtual long GetGapBetweenChildren() const { return m_ChildGap; }
+
+ // Also sets min max preferred dirty.
+ void LayoutChildren() override;
+ void MarkChildrenNeedLayout() override;
+ void NotifyParentNeedsLayout() override;
+ void SetLayout(CPt inSize, CPt inPosition) override;
+
+ virtual void SetAutoMinMaxPref(bool inAuto) { m_AutoMinMaxPref = inAuto; }
+ bool GetAutoMinMaxPref() const { return m_AutoMinMaxPref; }
+
+ // Legacy with FlowLayout.
+ virtual void SetAutoMin(bool inAuto) { m_AutoMinMaxPref = inAuto; }
+
+ virtual void SetTopMargin(long inPixels)
+ {
+ m_BeginMargin.y = inPixels;
+ MarkChildrenNeedLayout();
+ }
+ virtual long GetTopMargin() const { return m_BeginMargin.y; }
+
+ virtual void SetLeftMargin(long inPixels)
+ {
+ m_BeginMargin.x = inPixels;
+ MarkChildrenNeedLayout();
+ }
+ virtual long GetLeftMargin() const { return m_BeginMargin.x; }
+
+ virtual void SetBottomMargin(long inPixels)
+ {
+ m_EndMargin.y = inPixels;
+ MarkChildrenNeedLayout();
+ }
+ virtual long GetBottomMargin() const { return m_EndMargin.y; }
+
+ virtual void SetRightMargin(long inPixels)
+ {
+ m_EndMargin.x = inPixels;
+ MarkChildrenNeedLayout();
+ }
+ virtual long GetRightMargin() const { return m_EndMargin.x; }
+
+ protected:
+ void SetMinMaxPrefDirty() { m_MinMaxPreferredDirty = true; }
+ virtual ILazyFlowLayoutSpecializer &GetSpecializer() = 0;
+
+ long m_ChildGap;
+ long GetGapTotal();
+ // Margins are begin/end meaning before any children, after any children
+ long GetBeginMargin() { return GetSpecializer().GetSummedVariable(m_BeginMargin); }
+ long GetEndMargin() { return GetSpecializer().GetSummedVariable(m_EndMargin); }
+ // And then margines that are beside the row of children, either before the row or after it.
+ long GetBeforeRowMargin() { return GetSpecializer().GetMaxedVariable(m_BeginMargin); }
+ long GetAfterRowMargin() { return GetSpecializer().GetMaxedVariable(m_EndMargin); }
+
+ // I only implement these algorithms once, and I use a specializer to make them apply
+ // to either a left-to-right or a top-to-bottom layout.
+ void DistributeChildSizes(TControlSizeList &ioList);
+ void PerformLayout(TControlSizeList &ioList);
+ SSizeGroup CalcChildrenMinMaxPref();
+
+ virtual SSizeGroup GetChildSizes(std::shared_ptr<CControlData> inControl);
+
+ void RecalcMinMaxPref();
+ void MaybeRecalcMinMaxPerf() const;
+ };
+
+ template <typename TSpecializerType>
+ class TLazyFlowBase : public CLazyFlowBase
+ {
+ TSpecializerType m_Specializer;
+
+ public:
+ ILazyFlowLayoutSpecializer &GetSpecializer() override { return m_Specializer; }
+ };
+
+ struct SVerticalLazyFlow : public TLazyFlowBase<SVerticalLayoutSpecializer>
+ {
+ };
+
+ struct SHorizontalLazyFlow : public TLazyFlowBase<SHorizontalLayoutSpecializer>
+ {
+ };
+
+ class CRuntimeLazyFlow : public CLazyFlowBase
+ {
+ public:
+ enum EFlowDirection {
+ FLOW_VERTICAL,
+ FLOW_HORIZONTAL,
+ };
+
+ private:
+ SHorizontalLayoutSpecializer m_HorizontalSpecifier;
+ SVerticalLayoutSpecializer m_VerticalSpecifier;
+ EFlowDirection m_FlowDirection;
+
+ public:
+ CRuntimeLazyFlow()
+ : m_FlowDirection(FLOW_VERTICAL)
+ {
+ }
+
+ virtual void SetFlowDirection(EFlowDirection inFlowDirection)
+ {
+ m_FlowDirection = inFlowDirection;
+ MarkChildrenNeedLayout();
+ }
+
+ protected:
+ ILazyFlowLayoutSpecializer &GetSpecializer() override
+ {
+ if (m_FlowDirection == FLOW_VERTICAL)
+ return m_VerticalSpecifier;
+ return m_HorizontalSpecifier;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Controls/ListBoxItem.cpp b/src/Authoring/Studio/Controls/ListBoxItem.cpp
new file mode 100644
index 00000000..885d8f87
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ListBoxItem.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ListBoxItem.h"
+#include "Renderer.h"
+#include "HotKeys.h"
+#include "SystemPreferences.h"
+#include "StudioPreferences.h"
+
+IMPLEMENT_OBJECT_COUNTER(CListBoxItem)
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CListBoxItem::CListBoxItem()
+ : m_Selected(false)
+ , m_BorderColor(CStudioPreferences::GetControlRectSideLineColor())
+ , m_BackgroundColorSelected(CSystemPreferences::GetSelectedItemColor())
+ , m_BackgroundColorUnselected(CColor(255, 255, 255))
+{
+ ADDTO_OBJECT_COUNTER(CListBoxItem)
+
+ // this reserves the minimum height for the ListBoxItem in the ListBox first
+ SetAbsoluteSize(CPt(0, CStudioPreferences::GetDefaultTextEditSize()));
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CListBoxItem::~CListBoxItem()
+{
+ REMOVEFROM_OBJECT_COUNTER(CListBoxItem)
+}
+
+//==============================================================================
+/**
+ * Draws the bounding rectangle and white edit box for the List Box Item class.
+ *
+ * @param inRenderer The renderer that is responsible for drawing this Item.
+ */
+void CListBoxItem::Draw(CRenderer *inRenderer)
+{
+ const auto rect = QRect(QPoint(0, 0), GetSize());
+ inRenderer->PushClippingRect(rect);
+
+ // Fill the interior of the ListBoxItem
+ CColor theFillColor = m_BackgroundColorUnselected;
+
+ // If this ListBox is selected
+ if (m_Selected)
+ theFillColor = m_BackgroundColorSelected;
+
+ inRenderer->FillSolidRect(rect, theFillColor);
+
+ /*
+ CRct theRect = GetSize();
+ CPt theLowerRight( theRect.position.x + theRect.size.x - 1, theRect.position.y + theRect.size.y
+ - 1 );
+ CPt theLowerLeft( theRect.position.x, theLowerRight.y );
+
+ // draw the bottom line for this item;
+ // the top will be drawn by the prev item, otherwise it's the bounding box for the ListBox
+ inRenderer->PushPen( m_BorderColor, 1 );
+ inRenderer->MoveTo( theLowerLeft );
+ inRenderer->LineTo( theLowerRight );
+ inRenderer->PopPen();
+ */
+
+ inRenderer->PopClippingRect();
+}
+
+//=============================================================================
+/**
+ * Handles Mouse down events on this CListBoxItem. When a Mouse Click occurs
+ * on this ListBoxItem, fire off a SelectionEvent, to let the parent
+ * CListBoxControl know that this is selected, and to perform neccesary selection
+ * actions, e.g. Single Selection, or Multiple Selection.
+ *
+ * @param inPoint where the mouse was clicked, in local coordinates.
+ * @param inFlags Modifier keys that are down at time of event. Can be any
+ * combination of the following: MODIFIER_CONTROL | MODIFIER_SHIFT |
+ * MODIFIER_ALT | MOUSE_LBUTTON | MOUSE_RBUTTON | MOUSE_MBUTTON
+ */
+bool CListBoxItem::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theIsHandled = CControl::OnMouseDown(inPoint, inFlags);
+ m_SelectionListeners.FireEvent(&CListBoxSelectionListener::OnSelectItem, this, inFlags);
+ return theIsHandled;
+}
+
+//==============================================================================
+/**
+ * Overridden to help recalc the minimum size of the item
+ */
+void CListBoxItem::OnParentChanged(CControl *inParent)
+{
+ CControl::OnParentChanged(inParent);
+ RecalcMinimumSize();
+}
+
+//==============================================================================
+/**
+ * Overridden to help recalc the minimum size of the item
+ */
+void CListBoxItem::SetMinimumSize(CPt inSize)
+{
+ CControl::SetMinimumSize(inSize);
+ RecalcMinimumSize();
+}
+
+//==============================================================================
+/**
+ * Set the minimum width of the item based on the size of the parent
+ */
+void CListBoxItem::RecalcMinimumSize()
+{
+ if (GetParent()) {
+ CPt theSize = CControl::GetMinimumSize();
+ CPt theParentSize = GetParent()->GetSize();
+
+ // If the minimum width of the item is less than the
+ // current width of the parent, set the size to be the
+ // width of the parent
+ if (theParentSize.x > (theSize.x - GetPosition().x))
+ theSize.x = theParentSize.x - GetPosition().x;
+
+ CControl::SetMinimumSize(theSize);
+ }
+}
+
+//==============================================================================
+/**
+ * Sets this ListBoxItem to be selected or unselected.
+ *
+ * @param inSelected True if this CListBoxItem is selected.
+ */
+void CListBoxItem::SetSelectedState(bool inSelected)
+{
+ m_Selected = inSelected;
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Returns true if this ListBoxItem is selected.
+ *
+ * @return true if this CListBoxItem is selected.
+ */
+bool CListBoxItem::IsSelected() const
+{
+ return m_Selected;
+}
+
+//==============================================================================
+/**
+ * Sets the color of this control's border. Defines the color of the bounding
+ * rectangle.
+ *
+ * @param inColor the Color of this control's border.
+ */
+void CListBoxItem::SetBorderColor(const CColor &inColor)
+{
+ m_BorderColor = inColor;
+}
+
+//==============================================================================
+/**
+ * Returns the color of this control's border.
+ *
+ * @return the color of the border of this control.
+ */
+CColor CListBoxItem::GetBorderColor() const
+{
+ return m_BorderColor;
+}
+
+//==============================================================================
+/**
+ * Sets the background color for the ListBoxItem when it is selected.
+ *
+ * @param inColor the background color for the ListBoxItem when it is selected.
+ */
+void CListBoxItem::SetBGColorSelected(const CColor &inColor)
+{
+ m_BackgroundColorSelected = inColor;
+}
+
+//==============================================================================
+/**
+ * Returns the background color for the ListBoxItem when it is selected.
+ *
+ * @return the background color for the ListBoxItem when it is selected.
+ */
+CColor CListBoxItem::GetBGColorSelected() const
+{
+ return m_BackgroundColorSelected;
+}
+
+//==============================================================================
+/**
+ * Sets the background color for the ListBoxItem when it is not selected.
+ *
+ * @param inColor the background color for the ListBoxItem when it is not selected.
+ */
+void CListBoxItem::SetBGColorUnselected(const CColor &inColor)
+{
+ m_BackgroundColorUnselected = inColor;
+}
+
+//==============================================================================
+/**
+ * Returns the background color for the ListBoxItem when it is not selected.
+ *
+ * @return the background color for the ListBoxItem when it is not selected.
+ */
+CColor CListBoxItem::GetBGColorUnselected() const
+{
+ return m_BackgroundColorUnselected;
+}
+
+//==============================================================================
+/**
+ * Add a SelectionListener to this control's list of SelectionListeners.
+ *
+ * @param inListener The SelectionListener to add to the list of SelectionListeners
+ */
+void CListBoxItem::AddSelectionListener(CListBoxSelectionListener *inListener)
+{
+ m_SelectionListeners.AddListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Remove a SelectionListener from this control's list of SelectionListeners.
+ *
+ * @param inListener The SelectionListener to remove from the list of SelectionListeners
+ */
+void CListBoxItem::RemoveSelectionListener(CListBoxSelectionListener *inListener)
+{
+ m_SelectionListeners.RemoveListener(inListener);
+}
diff --git a/src/Authoring/Studio/Controls/ListBoxItem.h b/src/Authoring/Studio/Controls/ListBoxItem.h
new file mode 100644
index 00000000..26e1ecb9
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ListBoxItem.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_LIST_BOX_ITEM_H
+#define INCLUDED_LIST_BOX_ITEM_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "FlowLayout.h"
+#include "Multicaster.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class CListBoxItem;
+
+//==============================================================================
+// Functor
+//==============================================================================
+GENERIC_FUNCTOR_2(CListBoxSelectionListener, OnSelectItem, CListBoxItem *, long);
+
+//==============================================================================
+/**
+ * abstract CListBoxItem base class that all other ListBoxItem classes
+ * must inherit from. e.g. CListBoxStringItem, CActionListBoxItem
+ */
+class CListBoxItem : public CControl
+{
+public:
+ CListBoxItem();
+ virtual ~CListBoxItem();
+
+ DEFINE_OBJECT_COUNTER(CListBoxItem)
+
+ virtual Q3DStudio::CString GetString() = 0; ///< returns the string representation of this item
+
+ void Draw(CRenderer *inRenderer) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnParentChanged(CControl *inParent) override;
+ void SetMinimumSize(CPt inSize) override;
+
+ virtual void SetSelectedState(bool inSelected);
+ virtual void RecalcMinimumSize();
+ bool IsSelected() const;
+
+ // Color Accessors / Mutators
+ void SetBorderColor(const CColor &inColor);
+ CColor GetBorderColor() const;
+ void SetBGColorSelected(const CColor &inColor);
+ CColor GetBGColorSelected() const;
+ void SetBGColorUnselected(const CColor &inColor);
+ CColor GetBGColorUnselected() const;
+
+ // SelectionListener methods
+ void AddSelectionListener(CListBoxSelectionListener *inListener);
+ void RemoveSelectionListener(CListBoxSelectionListener *inListener);
+
+protected:
+ bool m_Selected;
+ CColor m_BorderColor;
+ QColor m_BackgroundColorSelected;
+ CColor m_BackgroundColorUnselected;
+ CMulticaster<CListBoxSelectionListener *>
+ m_SelectionListeners; ///< Usually only just the ListBoxControl owning this item
+};
+
+#endif // INCLUDED_LIST_BOX_ITEM_H
diff --git a/src/Authoring/Studio/Controls/ListBoxStringItem.cpp b/src/Authoring/Studio/Controls/ListBoxStringItem.cpp
new file mode 100644
index 00000000..d8efe02b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ListBoxStringItem.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "ListBoxStringItem.h"
+#include "Renderer.h"
+#include "SystemPreferences.h"
+
+//==============================================================================
+/**
+ * Constructor
+ *
+ * A ListBoxStringItem contains an immutable StringEdit, extending the base
+ * class ListBoxItem to give basic String display and containing funtionality.
+ * TODO: Need to implement some way to set the alignment of the text.
+ * Right now, setting the alignment makes the drawing of the control
+ * all dirty. That's why it's taken out, for now.
+ *
+ * @param inString the String which this ListBoxStringItem is to hold
+ */
+CListBoxStringItem::CListBoxStringItem()
+ : m_TextColor(0, 0, 0)
+ , m_SelectedTextColor(CSystemPreferences::GetSelectedTextColor())
+{
+ m_StringEdit.SetReadOnly(true);
+ m_StringEdit.AllowAutoSize(true);
+ m_StringEdit.SetAlignment(CTextEdit::LEFT);
+ m_StringEdit.SetFillBackground(false);
+ m_StringEdit.SetTextColor(m_TextColor);
+ AddChild(&m_StringEdit);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CListBoxStringItem::~CListBoxStringItem()
+{
+}
+
+//==============================================================================
+/**
+ * @return the String that this ListBoxStringItem contains
+ */
+void CListBoxStringItem::SetString(const Q3DStudio::CString &inString)
+{
+ m_StringEdit.SetData(inString, false);
+
+ SetMinimumSize(m_StringEdit.GetSize());
+ SetSize(m_StringEdit.GetSize());
+}
+
+//==============================================================================
+/**
+ * @return the String that this ListBoxStringItem contains
+ */
+Q3DStudio::CString CListBoxStringItem::GetString()
+{
+ return m_StringEdit.GetString();
+}
+
+//=============================================================================
+/**
+ * Overridden so that we can change the color of the text based upon selection.
+ * @param inSelected true to select this item, false to deselect it
+ */
+void CListBoxStringItem::SetSelectedState(bool inSelected)
+{
+ CListBoxItem::SetSelectedState(inSelected);
+
+ if (inSelected)
+ m_StringEdit.SetTextColor(m_SelectedTextColor);
+ else
+ m_StringEdit.SetTextColor(m_TextColor);
+}
diff --git a/src/Authoring/Studio/Controls/ListBoxStringItem.h b/src/Authoring/Studio/Controls/ListBoxStringItem.h
new file mode 100644
index 00000000..e950d494
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ListBoxStringItem.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_LIST_BOX_STRING_ITEM_H
+#define INCLUDED_LIST_BOX_STRING_ITEM_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "ListBoxItem.h"
+#include "StringEdit.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * CListBoxStringItem contains an immutable StringEdit, extending the base
+ * class ListBoxItem to give basic String displaying and storage.
+ */
+class CListBoxStringItem : public CListBoxItem
+{
+public:
+ CListBoxStringItem();
+ virtual ~CListBoxStringItem();
+
+ virtual void SetString(const Q3DStudio::CString &inString);
+ virtual Q3DStudio::CString GetString(); ///< returns the string representation of this item
+
+ virtual void SetSelectedState(bool inSelected); ///< Overridden so that we can change the color
+ ///of the text based upon selection
+
+protected:
+ CStringEdit m_StringEdit;
+ CColor m_TextColor;
+ CColor m_SelectedTextColor;
+};
+
+#endif // INCLUDED_LIST_BOX_STRING_ITEM_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/ListLayout.cpp b/src/Authoring/Studio/Controls/ListLayout.cpp
new file mode 100644
index 00000000..912cec13
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ListLayout.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "ListLayout.h"
+#include "MasterP.h"
+#include "ControlData.h"
+
+using namespace Q3DStudio;
+using namespace Q3DStudio::Control;
+
+CListLayout::CListLayout(bool inAlignChildrenLength /*= false */)
+ : m_IsResizing(false)
+ , m_AlignChildrenLength(inAlignChildrenLength)
+{
+}
+
+CListLayout::~CListLayout()
+{
+}
+
+//=============================================================================
+/**
+ * Add a child to this control.
+ * Overrides to make the layout get recalculated as well.
+ * @param inChild the child to be added.
+ * @param inInsertBefore the location to be added.
+ * @see CControl::AddChild.
+ */
+void CListLayout::AddChild(CControl *inChild, CControl *inInsertBefore /*= nullptr*/)
+{
+ CControl::AddChild(inChild, inInsertBefore);
+
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Remove a child from this control.
+ * Overrides to make the layout get recalculated as well.
+ * @param inChild the child to be removed.
+ * @see CControl::RemoveChild.
+ */
+void CListLayout::RemoveChild(CControl *inChild)
+{
+ CControl::RemoveChild(inChild);
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Set the size of this control.
+ * Overrides CControl::SetSize to propagate down to children too.
+ * @param inSize the new size.
+ */
+void CListLayout::SetSize(CPt inSize)
+{
+ if (inSize.x != GetSize().x) {
+ m_IsResizing = true;
+
+ // Go through all the children and set their sizes too
+ ControlGraph::SIterator theChildren = GetChildren();
+ for (; theChildren.HasNext(); ++theChildren) {
+ std::shared_ptr<CControlData> theChild = (*theChildren);
+ if (theChild->IsVisible()) {
+ // Only care about the width, keep the height the same.
+ theChild->SetSize(inSize.x, theChild->GetSize().y);
+ }
+ }
+ m_IsResizing = false;
+ }
+
+ CControl::SetSize(inSize);
+}
+
+//=============================================================================
+/**
+ * Recalculate the layout of all the sub controls.
+ * This will resize this control appropriately and reposition all the children.
+ */
+void CListLayout::RecalcLayout()
+{
+ m_IsResizing = true;
+
+ long theHeight = 0;
+ CPt theCurrentPos(0, 0);
+ long theMinLen = 0;
+
+ ControlGraph::SIterator theChildren = GetChildren();
+ if (m_AlignChildrenLength) {
+ // Go through the first time to determine what is the minimum length for the children
+ for (; theChildren.HasNext(); ++theChildren) {
+ std::shared_ptr<CControlData> theChild = (*theChildren);
+ // Only handle visible children
+ if (theChild->IsVisible()) {
+ CPt theMinimumSize(theChild->GetMinimumSize());
+ if (theMinimumSize.x > theMinLen)
+ theMinLen = theMinimumSize.x;
+ }
+ }
+ // reset this
+ theChildren = GetChildren();
+ }
+
+ // Go through all the children and set their position, as well as the minimum length if required
+ // to
+ for (; theChildren.HasNext(); ++theChildren) {
+ std::shared_ptr<CControlData> theChild = (*theChildren);
+ // Only handle visible children
+ if (theChild->IsVisible()) {
+ CPt theChildSize = theChild->GetSize();
+ theHeight += theChildSize.y;
+
+ if (m_AlignChildrenLength)
+ theChild->SetSize(CPt(theMinLen, theChildSize.y));
+ else { // this would be the only loop to get the minimum length
+ CPt theMinimumSize(theChild->GetMinimumSize());
+ if (theMinimumSize.x > theMinLen)
+ theMinLen = theMinimumSize.x;
+ }
+
+ // Update the position
+ theChild->SetPosition(theCurrentPos);
+ theCurrentPos.y += theChildSize.y;
+ }
+ }
+
+ SetMinimumSize(CPt(theMinLen, theHeight));
+ SetMaximumSize(CPt(LONG_MAX, theHeight));
+
+ SetSize(CPt(theMinLen, theHeight));
+
+ m_IsResizing = false;
+}
+
+//=============================================================================
+/**
+ * Notification to this control that one of the child controls has changed size.
+ * @param inControl the control that changed size.
+ */
+void CListLayout::OnChildSizeChanged(CControl *inControl)
+{
+ Q_UNUSED(inControl);
+
+ // If we are not actively resizing then redo the layout.
+ if (!m_IsResizing) {
+ UICPROFILE(OnChildSizeChanged);
+
+ RecalcLayout();
+ }
+}
+
+#ifdef _DEBUG
+bool CListLayout::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ return CControl::OnMouseDown(inPoint, inFlags);
+}
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/ListLayout.h b/src/Authoring/Studio/Controls/ListLayout.h
new file mode 100644
index 00000000..3b1d7768
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ListLayout.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_LIST_LAYOUT_H
+#define INCLUDED_LIST_LAYOUT_H 1
+
+#pragma once
+
+#include "Control.h"
+
+class CListLayout : public CControl
+{
+public:
+ CListLayout(bool inAlignChildrenLength = false);
+ virtual ~CListLayout();
+
+ void SetSize(CPt inSize) override;
+
+ void AddChild(CControl *inChild, CControl *inInsertBefore = nullptr) override;
+ void RemoveChild(CControl *inChild) override;
+
+ void OnChildSizeChanged(CControl *inControl) override;
+
+ void RecalcLayout();
+
+#ifdef _DEBUG
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+#endif
+
+protected:
+ bool m_IsResizing;
+ bool m_AlignChildrenLength; ///< True when all children in this list should align up
+};
+#endif // INCLUDED_LIST_LAYOUT_H
diff --git a/src/Authoring/Studio/Controls/NameEdit.cpp b/src/Authoring/Studio/Controls/NameEdit.cpp
new file mode 100644
index 00000000..b8cface6
--- /dev/null
+++ b/src/Authoring/Studio/Controls/NameEdit.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "NameEdit.h"
+#include "INamable.h"
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inPropertyProvider interface that will provide properties by name
+ * (such as a CAsset object). Can be nullptr.
+ */
+CNameEdit::CNameEdit(INamable *inNamable)
+ : m_Namable(inNamable)
+ , m_IsSettingData(false)
+ , m_LastMoustDown(0, 0)
+ , m_LastFocused(true)
+ , m_CanEdit(false)
+{
+ ASSERT(m_Namable); // if you don't have a namable, use CTextEditInPlace instead.
+
+ SetData(m_Namable->GetName(), false);
+ AddCommitListener(this);
+ AllowAutoSize(true);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CNameEdit::~CNameEdit()
+{
+ RemoveCommitListener(this);
+}
+
+//=============================================================================
+/**
+ * Called when a CTextEdit control's data is changed. In this case, the name
+ * field is being changed, so the new value is pushed down to Client.
+ * @param inControl the control that had it's data changed
+ */
+void CNameEdit::OnSetData(CControl *inControl)
+{
+ if (!m_IsSettingData && inControl == this && m_Namable) {
+ if (m_Namable->GetName() != GetString()) {
+ m_IsSettingData = true;
+ m_Namable->SetName(GetString());
+ m_IsSettingData = false;
+
+ // Refresh what it is in m_Nameable, because the UI data is already changed and the
+ // underlying data model may not agree ( ie not accepting empty or renaming isn't
+ // allowed )
+ // Ideally UI shouldn't change, it should informing the data model through some kind of
+ // transaction (like how blackfish does it)
+ SetData(m_Namable->GetName(), false);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Called when something on an asset changes, making it dirty. Resets the name
+ * displayed by this control, in case it was the name that changed on the asset.
+ */
+void CNameEdit::OnDirty()
+{
+ SetData(m_Namable->GetName());
+ RefreshDisplayFromData();
+}
+
+bool CNameEdit::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_LastMoustDown = inPoint;
+ m_CanEdit = !m_LastFocused;
+
+ return CTextEditInPlace::OnMouseDown(inPoint, inFlags);
+}
+
+void CNameEdit::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (IsInFocus() && !m_IsInEditMode && !(inFlags & CHotKeys::MOUSE_RBUTTON)) {
+ if (m_CanEdit && m_LastMoustDown == inPoint) {
+ SetEditMode(true);
+ SelectAllText();
+ }
+ } else {
+ CTextEditInPlace::OnMouseUp(inPoint, inFlags);
+ }
+
+ m_CanEdit = false;
+}
+
+void CNameEdit::OnGainFocus()
+{
+ CTextEditInPlace::OnGainFocus();
+ m_LastFocused = false;
+}
+
+void CNameEdit::OnLoseFocus()
+{
+ m_LastFocused = true;
+ CTextEditInPlace::OnLoseFocus();
+}
diff --git a/src/Authoring/Studio/Controls/NameEdit.h b/src/Authoring/Studio/Controls/NameEdit.h
new file mode 100644
index 00000000..cf54bb35
--- /dev/null
+++ b/src/Authoring/Studio/Controls/NameEdit.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_NAME_EDIT
+#define INCLUDED_NAME_EDIT 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TextEditInPlace.h"
+
+class INamable;
+
+//=============================================================================
+/**
+ * @class CNameEdit Edit control for statically displaying a "name" property.
+ * Double-clicking on the text enables you to edit it. Changes to the underlying
+ * name property are automatically handled by this control.
+ */
+class CNameEdit : public CTextEditInPlace, public CCommitDataListener
+{
+public:
+ CNameEdit(INamable *inNamable);
+ virtual ~CNameEdit();
+ void OnSetData(CControl *inControl) override;
+ virtual void OnDirty();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnGainFocus() override;
+ void OnLoseFocus() override;
+
+protected:
+ INamable *m_Namable;
+ bool m_IsSettingData;
+
+ CPt m_LastMoustDown;
+ bool m_LastFocused;
+ bool m_CanEdit;
+};
+
+#endif // INCLUDED_NAME_EDIT
diff --git a/src/Authoring/Studio/Controls/OverlayControl.cpp b/src/Authoring/Studio/Controls/OverlayControl.cpp
new file mode 100644
index 00000000..cca9b402
--- /dev/null
+++ b/src/Authoring/Studio/Controls/OverlayControl.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+#include "OverlayControl.h"
+#include "Renderer.h"
+
+IMPLEMENT_OBJECT_COUNTER(COverlayControl)
+
+//=============================================================================
+/**
+ * Create a new OverlayControl.
+ */
+COverlayControl::COverlayControl()
+ : m_HasSizeChanged(false)
+ , m_WasVisible(false)
+ , m_Alpha(255)
+{
+ ADDTO_OBJECT_COUNTER(COverlayControl)
+}
+
+COverlayControl::~COverlayControl()
+{
+ REMOVEFROM_OBJECT_COUNTER(COverlayControl)
+}
+
+//=============================================================================
+/**
+ * Notification from the parent control that it is going to begin drawing children.
+ * This is used to erase this component before the children are drawn.
+ * @param inRenderer the renderer that is being drawn to.
+ */
+void COverlayControl::BeginDrawChildren(CRenderer *inRenderer)
+{
+ const auto size = GetParent()->GetSize();
+ QRect theClippingRect(0, 0, size.x, size.y);
+
+// doing this = lockup on MacX.
+// not doing this = playhead redraw errors on Windows
+#ifdef WIN32
+ inRenderer->PushClippingRect(theClippingRect);
+#endif
+ // If we don't have a renderer then create one.
+ if (IsVisible() && m_BufferedRenderer == NULL) {
+ m_BufferedRenderer = new CBufferedRenderer(QSize(size.x, size.y));
+ }
+
+ else if (m_HasSizeChanged && m_BufferedRenderer != NULL) {
+ CRct theRect(m_PreviousSize);
+ theRect.Offset(-m_PositionOffset + GetPosition());
+
+ // Overwrite the current contents, clearing this object's drawing.
+ inRenderer->BitBltFrom(theRect, m_BufferedRenderer, 0, 0);
+
+ m_HasSizeChanged = false;
+
+ m_BufferedRenderer = new CBufferedRenderer(QSize(size.x, size.y));
+ }
+
+ else {
+ if ((IsVisible() || m_WasVisible) && m_BufferedRenderer != NULL) {
+ // If this moved since the last begin draw then take in that offset too.
+ CRct theRect(GetSize());
+ theRect.Offset(-m_PositionOffset + GetPosition());
+
+ // Overwrite the current contents, clearing this object's drawing.
+ inRenderer->BitBltFrom(theRect, m_BufferedRenderer, 0, 0);
+
+ if (m_WasVisible)
+ m_BufferedRenderer = nullptr;
+
+ m_WasVisible = false;
+ }
+ }
+
+ m_PositionOffset.x = 0;
+ m_PositionOffset.y = 0;
+
+#ifdef WIN32
+ inRenderer->PopClippingRect();
+#endif
+}
+
+//=============================================================================
+/**
+ * Overrides OnDraw to perform custom drawing logic.
+ * This basically needs to draw all the time regardless of invalidation.
+ * The dirty rect will be properly updated if this is dirty.
+ * @param inRenderer the renderer to draw to.
+ * @param inDirtyRect the resulting dirty rect from drawing.
+ * @param inIgnoreValidation true if this should draw everything.
+ */
+void COverlayControl::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation)
+{
+ CRct theClippingRect(-GetPosition(), GetParent()->GetSize());
+ inRenderer->PushClippingRect(theClippingRect);
+
+ if (IsVisible() && m_BufferedRenderer != nullptr) {
+ // Copy the current contents of the background.
+ m_BufferedRenderer->BitBltFrom(CRct(GetSize()), inRenderer, 0, 0);
+
+ bool isInvalidated = IsInvalidated();
+
+ if (isInvalidated || inIgnoreValidation) {
+ // If this is invalidated then update the dirty rect appropriately
+ CRct theBoundingBox = inRenderer->GetClippingRect();
+
+ CRct theRect(GetSize());
+ theRect.And(theBoundingBox);
+ theRect.Offset(inRenderer->GetTranslation());
+ inDirtyRect.Or(theRect);
+ }
+
+ // if ( m_Alpha != 255 )
+ //{
+ // DrawAlpha( inRenderer );
+ //}
+ // else
+ {
+ // Always draw this component to the renderer, regardless of whether it's dirty or not.
+ Draw(inRenderer);
+ }
+
+ Invalidate(false);
+ }
+ CControl::OnDraw(inRenderer, inDirtyRect, inIgnoreValidation);
+
+ inRenderer->PopClippingRect();
+}
+
+//=============================================================================
+/**
+ * Handles drawing this control as being transparent.
+ * @param inRenderer the renderer to draw to.
+ */
+void COverlayControl::DrawAlpha(CRenderer * /*inRenderer*/)
+{
+ /* // Copy the contents of the current background, this will make it so only the areas
+ // that are drawn to are actually blended
+ BUFFEREDRENDERERTYPE theIntermediate( m_BufferedRenderer,
+ m_BufferedRenderer->GetClippingRect() );
+ Draw( &theIntermediate );
+
+ // Do the transparent draw.
+ theIntermediate.TransparentBltTo( inRenderer, m_Alpha );*/
+}
+
+//=============================================================================
+/**
+ * Logs the changes in position so that it can properly reset the background.
+ * @param inPosition the new position.
+ */
+void COverlayControl::SetPosition(CPt inPosition)
+{
+ if (inPosition != GetPosition()) {
+ // Offset the position, make it relative just in case multiple changes occur per cycle.
+ m_PositionOffset += inPosition - GetPosition();
+
+ CControl::SetPosition(inPosition);
+ }
+}
+
+//=============================================================================
+/**
+ * Override of SetSize so that the renderer can be ditched.
+ * @param inSize the new size of this control.
+ */
+void COverlayControl::SetSize(CPt inSize)
+{
+ if (inSize != GetSize()) {
+ // Record how big this was so the previous drawing can be erased.
+ if (!m_HasSizeChanged && m_BufferedRenderer != nullptr) {
+ m_HasSizeChanged = true;
+ m_PreviousSize = GetSize();
+ }
+
+ CControl::SetSize(inSize);
+ }
+}
+
+//=============================================================================
+/**
+ * Set whether or not this control is visible.
+ * Override to handle final clearing of this control when not visible.
+ * @param inIsVisible true if this is to be visible.
+ */
+void COverlayControl::SetVisible(bool inIsVisible)
+{
+ if (!inIsVisible && IsVisible()) {
+ m_WasVisible = true;
+ }
+ CControl::SetVisible(inIsVisible);
+}
+
+//=============================================================================
+/**
+ * Set the alpha blend of this control.
+ * This defaults to 255 which is opaque, if it is anything other than 255 then
+ * this control will be drawn with transparency.
+ * @param inAlpha the new opacity, 255 = opaque, 0 = transparent.
+ */
+void COverlayControl::SetAlpha(short inAlpha)
+{
+ m_Alpha = inAlpha;
+}
+
+bool COverlayControl::IsChildInvalidated() const
+{
+ return true;
+}
diff --git a/src/Authoring/Studio/Controls/OverlayControl.h b/src/Authoring/Studio/Controls/OverlayControl.h
new file mode 100644
index 00000000..9ad622f8
--- /dev/null
+++ b/src/Authoring/Studio/Controls/OverlayControl.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef INCLUDED_OVERLAY_CONTROL_H
+#define INCLUDED_OVERLAY_CONTROL_H 1
+
+#pragma once
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "Control.h"
+
+//=============================================================================
+// Forwards
+//=============================================================================
+
+#include "BufferedRenderer.h"
+#include "UICObjectCounter.h"
+
+//=============================================================================
+/**
+ * Overlay control provides a way to a control on top of another and move it
+ * around. The drawing is handled so that you do not need to invalidate the
+ * bottom control and you don't get trails to forming on the bottom control.
+ * This is accomplished through the use of a buffered renderer.
+ */
+class COverlayControl : public CControl
+{
+public:
+ COverlayControl();
+ virtual ~COverlayControl();
+
+ DEFINE_OBJECT_COUNTER(COverlayControl)
+
+ virtual void SetSize(CPt inSize);
+ virtual void SetPosition(CPt inPosition);
+ virtual void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation = false);
+ virtual void BeginDrawChildren(CRenderer *inRenderer);
+ virtual void SetVisible(bool inIsVisible);
+ void SetAlpha(short inAlpha);
+ virtual bool IsChildInvalidated() const;
+
+protected:
+ void DrawAlpha(CRenderer *inRenderer);
+
+ CPt m_PositionOffset;
+ Q3DStudio::CAutoMemPtr<CBufferedRenderer> m_BufferedRenderer;
+ bool m_HasSizeChanged;
+ CPt m_PreviousSize;
+ bool m_WasVisible;
+ short m_Alpha;
+};
+#endif // INCLUDED_OVERLAY_CONTROL_H
diff --git a/src/Authoring/Studio/Controls/ProceduralButton.h b/src/Authoring/Studio/Controls/ProceduralButton.h
new file mode 100644
index 00000000..47b39046
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ProceduralButton.h
@@ -0,0 +1,569 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROCEDURAL_BUTTON_H
+#define INCLUDED_PROCEDURAL_BUTTON_H 1
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Renderer.h"
+#include "ButtonControl.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Template class for making procedural buttons. A procedural button has
+ * additional drawing options compared to a normal button. You must specify
+ * a derivative of CButtonControl as the class for the procedural button to
+ * extend.
+ */
+template <typename TButton>
+class CProceduralButton : public TButton
+{
+public:
+ /// Fill color styles for procedurally drawn buttons
+ enum EFillStyle {
+ EFILLSTYLE_GRADIENT, ///< Button background is filled using a gradient
+ EFILLSTYLE_FLOOD, ///< Button background is filled in a solid color
+ EFILLSTYLE_NONE ///< Button background is not filled at all
+ };
+
+ /// Struct enabling you to specify whether or not to draw each border of the button individually
+ struct SBorderOptions
+ {
+ bool m_DrawLeft; ///< If true, you want the left border to be drawn
+ bool m_DrawTop; ///< If true, you want the top border to be drawn
+ bool m_DrawRight; ///< If true, you want the right border to be drawn
+ bool m_DrawBottom; ///< If true, you want the bottom border to be drawn
+
+ /// Default Constructor - makes all borders be drawn
+ SBorderOptions()
+ {
+ m_DrawLeft = true;
+ m_DrawTop = true;
+ m_DrawRight = true;
+ m_DrawBottom = true;
+ }
+
+ /// Constructor to initialize each member of the struct individually
+ SBorderOptions(bool inLeft, bool inTop, bool inRight, bool inBottom)
+ {
+ m_DrawLeft = inLeft;
+ m_DrawTop = inTop;
+ m_DrawRight = inRight;
+ m_DrawBottom = inBottom;
+ }
+ };
+
+public:
+ CProceduralButton();
+ virtual ~CProceduralButton();
+
+ void SetFillStyleUp(EFillStyle inStyle);
+ void SetFillStyleDown(EFillStyle inStyle);
+ void SetFillStyleDisabled(EFillStyle inStyle);
+ void SetFillStyleOver(EFillStyle inStyle);
+ void SetFillStyleAll(EFillStyle inStyle);
+ void SetFillColorUp(const CColor &inColor);
+ void SetFillColorDown(const CColor &inColor);
+ void SetFillColorDisabled(const CColor &inColor);
+ void SetFillColorOver(const CColor &inColor);
+
+ void SetBorderVisibilityAll(const SBorderOptions &inBorderOptions);
+ void SetBorderVisiblityUp(const SBorderOptions &inBorderOptions);
+ void SetBorderVisiblityDown(const SBorderOptions &inBorderOptions);
+ void SetBorderVisiblityDisabled(const SBorderOptions &inBorderOptions);
+ void SetBorderVisiblityOver(const SBorderOptions &inBorderOptions);
+
+ void SetLeftBorderColor(const CColor &inColor);
+ void SetTopBorderColor(const CColor &inColor);
+ void SetRightBorderColor(const CColor &inColor);
+ void SetBottomBorderColor(const CColor &inColor);
+
+protected:
+ virtual void Render(CRenderer *inRenderer);
+ void DrawBackground(CRenderer *inRenderer);
+ void DrawBorder(CRenderer *inRenderer);
+ EFillStyle GetCurrentFillStyle();
+ CColor GetCurrentBackgroundColor();
+ SBorderOptions GetCurrentBorderOptions();
+
+protected:
+ EFillStyle m_UpFillStyle;
+ EFillStyle m_DownFillStyle;
+ EFillStyle m_DisabledFillStyle;
+ EFillStyle m_OverFillStyle;
+ CColor m_UpColor;
+ CColor m_DownColor;
+ CColor m_DisabledColor;
+ CColor m_OverColor;
+ CColor m_LeftBorderColor;
+ CColor m_TopBorderColor;
+ CColor m_RightBorderColor;
+ CColor m_BottomBorderColor;
+ SBorderOptions m_UpBorders;
+ SBorderOptions m_DownBorders;
+ SBorderOptions m_DisabledBorders;
+ SBorderOptions m_OverBorders;
+};
+
+//==============================================================================
+// Template implemenations
+//==============================================================================
+
+//=============================================================================
+/**
+ * Constructor
+ */
+template <typename TButton>
+CProceduralButton<TButton>::CProceduralButton()
+ : TButton()
+ , m_UpFillStyle(EFILLSTYLE_GRADIENT)
+ , m_DownFillStyle(EFILLSTYLE_GRADIENT)
+ , m_DisabledFillStyle(EFILLSTYLE_NONE)
+ , m_OverFillStyle(EFILLSTYLE_GRADIENT)
+ , m_UpColor(CStudioPreferences::GetBaseColor())
+ , m_DownColor(CStudioPreferences::GetButtonDownColor())
+ , m_DisabledColor(CStudioPreferences::GetBaseColor())
+ , m_OverColor(CStudioPreferences::GetBaseColor())
+ , m_LeftBorderColor(CStudioPreferences::GetButtonShadowColor())
+ , m_TopBorderColor(CStudioPreferences::GetButtonShadowColor())
+ , m_RightBorderColor(CStudioPreferences::GetButtonShadowColor())
+ , m_BottomBorderColor(CStudioPreferences::GetButtonShadowColor())
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+template <typename TButton>
+CProceduralButton<TButton>::~CProceduralButton()
+{
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillStyleUp(EFillStyle inStyle)
+{
+ if (m_UpFillStyle != inStyle) {
+ m_UpFillStyle = inStyle;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillStyleDown(EFillStyle inStyle)
+{
+ if (m_DownFillStyle != inStyle) {
+ m_DownFillStyle = inStyle;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillStyleDisabled(EFillStyle inStyle)
+{
+ if (m_DisabledFillStyle != inStyle) {
+ m_DisabledFillStyle = inStyle;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillStyleOver(EFillStyle inStyle)
+{
+ if (m_OverFillStyle != inStyle) {
+ m_OverFillStyle = inStyle;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillStyleAll(EFillStyle inStyle)
+{
+ SetFillStyleUp(inStyle);
+ SetFillStyleDown(inStyle);
+ SetFillStyleDisabled(inStyle);
+ SetFillStyleOver(inStyle);
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillColorUp(const CColor &inColor)
+{
+ if (m_UpColor != inColor) {
+ m_UpColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillColorDown(const CColor &inColor)
+{
+ if (m_DownColor != inColor) {
+ m_DownColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillColorDisabled(const CColor &inColor)
+{
+ if (m_DisabledColor != inColor) {
+ m_DisabledColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetFillColorOver(const CColor &inColor)
+{
+ if (m_OverColor != inColor) {
+ m_OverColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+template <typename TButton>
+void CProceduralButton<TButton>::SetBorderVisibilityAll(const SBorderOptions &inBorderOptions)
+{
+ SetBorderVisiblityUp(inBorderOptions);
+ SetBorderVisiblityDown(inBorderOptions);
+ SetBorderVisiblityDisabled(inBorderOptions);
+ SetBorderVisiblityOver(inBorderOptions);
+}
+
+template <typename TButton>
+void CProceduralButton<TButton>::SetBorderVisiblityUp(const SBorderOptions &inBorderOptions)
+{
+ m_UpBorders = inBorderOptions;
+}
+
+template <typename TButton>
+void CProceduralButton<TButton>::SetBorderVisiblityDown(const SBorderOptions &inBorderOptions)
+{
+ m_DownBorders = inBorderOptions;
+}
+
+template <typename TButton>
+void CProceduralButton<TButton>::SetBorderVisiblityDisabled(const SBorderOptions &inBorderOptions)
+{
+ m_DisabledBorders = inBorderOptions;
+}
+
+template <typename TButton>
+void CProceduralButton<TButton>::SetBorderVisiblityOver(const SBorderOptions &inBorderOptions)
+{
+ m_OverBorders = inBorderOptions;
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetLeftBorderColor(const CColor &inColor)
+{
+ if (m_LeftBorderColor != inColor) {
+ m_LeftBorderColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetTopBorderColor(const CColor &inColor)
+{
+ if (m_TopBorderColor != inColor) {
+ m_TopBorderColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetRightBorderColor(const CColor &inColor)
+{
+ if (m_RightBorderColor != inColor) {
+ m_RightBorderColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::SetBottomBorderColor(const CColor &inColor)
+{
+ if (m_BottomBorderColor != inColor) {
+ m_BottomBorderColor = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::Render(CRenderer *inRenderer)
+{
+ // Fill the background if desired
+ DrawBackground(inRenderer);
+
+ // Draw the button icon
+ TButton::Render(inRenderer);
+
+ // Draw the border
+ DrawBorder(inRenderer);
+}
+
+//=============================================================================
+/**
+ * Fills the background of this button with the appropriate color and style.
+ * The style is specified by calling "GetCurrentFillStyle" which may indicate
+ * not to fill the background at all.
+ * @param inRenderer the renderer to draw to
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::DrawBackground(CRenderer *inRenderer)
+{
+ CPt theSize = TButton::GetSize();
+
+ // Fill in the background color if necessary
+ EFillStyle theFillStyle = GetCurrentFillStyle();
+
+ switch (theFillStyle) {
+ // Perform a gradient fill (block of color that varies slightly along the y-axis)
+ case EFILLSTYLE_GRADIENT: {
+ // The gradient inverts if the button is currently in the down state
+ bool theInvertGradientFlag = (TButton::GetButtonState() == TButton::EBUTTONSTATE_DOWN) ? true : false;
+ inRenderer->DrawGradientBitmap(QRect(0, 0, theSize.x, theSize.y), GetCurrentBackgroundColor(), theInvertGradientFlag,
+ 0.75);
+ } break;
+
+ // Fill the whole area with a block of solid color
+ case EFILLSTYLE_FLOOD:
+ inRenderer->FillSolidRect(QRect(0, 0, theSize.x, theSize.y), GetCurrentBackgroundColor());
+ break;
+
+ // Do not fill the background at all
+ case EFILLSTYLE_NONE:
+ // No break
+ default:
+ // No filling in of the background
+ break;
+ }
+}
+
+//=============================================================================
+/**
+ * Draws the borders around this button as specified in the border options for
+ * the current state of the button. You can turn border drawing on and off
+ * per side of the button, and you can also specify different colors for each
+ * side of the button.
+ * @param inRenderer renderer to draw to
+ */
+template <typename TButton>
+void CProceduralButton<TButton>::DrawBorder(CRenderer *inRenderer)
+{
+ CPt theSize = TButton::GetSize();
+ SBorderOptions theBorders = CProceduralButton::GetCurrentBorderOptions();
+
+ if (theBorders.m_DrawLeft) {
+ inRenderer->PushPen(m_LeftBorderColor);
+ inRenderer->MoveTo(CPt(0, theSize.y - 1));
+ inRenderer->LineTo(CPt(0, 0));
+ inRenderer->PopPen();
+ }
+
+ if (theBorders.m_DrawTop) {
+ inRenderer->PushPen(m_TopBorderColor);
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(theSize.x - 1, 0));
+ inRenderer->PopPen();
+ }
+
+ if (theBorders.m_DrawRight) {
+ inRenderer->PushPen(m_RightBorderColor);
+ if (!theBorders.m_DrawTop)
+ inRenderer->MoveTo(CPt(theSize.x - 1, 0));
+ else
+ inRenderer->MoveTo(CPt(theSize.x - 1, 1));
+ inRenderer->LineTo(CPt(theSize.x - 1, theSize.y - 1));
+ inRenderer->PopPen();
+ }
+
+ if (theBorders.m_DrawBottom) {
+ inRenderer->PushPen(m_BottomBorderColor);
+ inRenderer->MoveTo(CPt(theSize.x - 1, theSize.y - 1));
+ if (!theBorders.m_DrawLeft)
+ inRenderer->LineTo(CPt(0, theSize.y - 1));
+ else
+ inRenderer->LineTo(CPt(1, theSize.y - 1));
+ inRenderer->PopPen();
+ }
+}
+
+//=============================================================================
+/**
+ * @return the current fill style based upon state (up, down, mouse over, disabled) of the button
+ */
+template <typename TButton>
+typename CProceduralButton<TButton>::EFillStyle
+CProceduralButton<TButton>::GetCurrentFillStyle()
+{
+ // Default to the up state
+ EFillStyle theFillStyle = m_UpFillStyle;
+
+ typename TButton::EButtonState theState = TButton::GetButtonState();
+
+ // If the mouse is over the button, switch to the mouse over style
+ if (TButton::IsMouseOver())
+ theFillStyle = m_OverFillStyle;
+
+ // If the button is currently pressed, this cancels the up and over states, so return the down
+ // style
+ if (theState == TButton::EBUTTONSTATE_DOWN)
+ theFillStyle = m_DownFillStyle;
+
+ // If this button is disabled just return the disabled style (overrides any other states)
+ if (!TButton::IsEnabled())
+ theFillStyle = m_DisabledFillStyle;
+
+ return theFillStyle;
+}
+
+//=============================================================================
+/**
+ * @return the current background color based upon state (up, down, mouse over, disabled) of the
+ * button
+ */
+template <typename TButton>
+::CColor CProceduralButton<TButton>::GetCurrentBackgroundColor()
+{
+ // Default to the up color
+ ::CColor theColor = m_UpColor;
+
+ typename TButton::EButtonState theState = TButton::GetButtonState();
+
+ // If the mouse is over the button, switch to the mouse over color
+ if (TButton::IsMouseOver())
+ theColor = m_OverColor;
+
+ // If the button is currently pressed, this cancels the up and over states, so return the down
+ // color
+ if (theState == TButton::EBUTTONSTATE_DOWN)
+ theColor = m_DownColor;
+
+ // If this button is disabled just return the disabled color (overrides any other states)
+ if (!TButton::IsEnabled())
+ theColor = m_DisabledColor;
+
+ return theColor;
+}
+
+//=============================================================================
+/**
+ * @return the current border drawing options based upon state (up, down, mouse over, disabled) of
+ * the button
+ */
+template <typename TButton>
+typename CProceduralButton<TButton>::SBorderOptions
+CProceduralButton<TButton>::GetCurrentBorderOptions()
+{
+ SBorderOptions theOptions = m_UpBorders;
+ typename TButton::EButtonState theState = TButton::GetButtonState();
+
+ // If the mouse is over the button, switch to the mouse over border options
+ if (TButton::IsMouseOver())
+ theOptions = m_OverBorders;
+
+ // If the button is currently pressed, this cancels the up and over states, so return the over
+ // border options
+ if (theState == TButton::EBUTTONSTATE_DOWN)
+ theOptions = m_DownBorders;
+
+ // If this button is disabled just return the disabled border options (overrides any other
+ // states)
+ if (!TButton::IsEnabled())
+ theOptions = m_DisabledBorders;
+
+ return theOptions;
+}
+
+#endif // INCLUDED_PROCEDURAL_BUTTON_H
diff --git a/src/Authoring/Studio/Controls/Renderer.cpp b/src/Authoring/Studio/Controls/Renderer.cpp
new file mode 100644
index 00000000..1a750196
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Renderer.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "Renderer.h"
+
+#include <QPoint>
+#include <QRect>
+
+/**
+ * Draws the outline of a rectangle in the specified colors.
+ *
+ * @param inRect Rectangle to be outlined
+ * @param inTop Color of the top line
+ * @param inRight Color of the line on the right side
+ * @param inBottom Color of the line on the bottom
+ * @param inLeft Color of the line on the left side
+ */
+void CRenderer::DrawRectOutline(const QRect &inRect, const QColor &inTop, const QColor &inRight,
+ const QColor &inBottom, const QColor &inLeft)
+{
+ QPoint theUpperLeft(inRect.topLeft());
+ QPoint theUpperRight(inRect.topRight());
+ QPoint theLowerRight(inRect.bottomRight());
+ QPoint theLowerLeft(inRect.bottomLeft());
+
+ // Top
+ PushPen(inTop, 1);
+ MoveTo(theUpperLeft.x(), theUpperLeft.y());
+ LineTo(theUpperRight.x(), theUpperRight.y());
+ PopPen();
+
+ // Right
+ PushPen(inRight, 1);
+ LineTo(theLowerRight.x(), theLowerRight.y());
+ PopPen();
+
+ // Bottom
+ PushPen(inBottom, 1);
+ LineTo(theLowerLeft.x(), theLowerLeft.y());
+ PopPen();
+
+ // Left
+ PushPen(inLeft, 1);
+ LineTo(theUpperLeft.x(), theUpperLeft.y());
+ PopPen();
+}
diff --git a/src/Authoring/Studio/Controls/Renderer.h b/src/Authoring/Studio/Controls/Renderer.h
new file mode 100644
index 00000000..6feca4ed
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Renderer.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_RENDERER_H
+#define INCLUDED_RENDERER_H 1
+
+#pragma once
+
+#include <QColor>
+#include <QPoint>
+
+#include "CColor.h"
+
+QT_BEGIN_NAMESPACE
+class QPainter;
+class QPixmap;
+class QRect;
+class QSize;
+class QString;
+QT_END_NAMESPACE
+
+class CRenderer
+{
+ typedef std::vector<QPoint> TTranslationList;
+
+public:
+ virtual ~CRenderer() {}
+
+ virtual QPainter* GetPainter() = 0;
+ virtual void FillSolidRect(const QRect &inCoordinates, const QColor &inColor) = 0;
+ virtual void MoveTo(const QPoint &inPoint) = 0;
+ virtual void MoveTo(long inX, long inY) = 0;
+ virtual void LineTo(const QPoint &inPoint) = 0;
+ virtual void LineTo(long inX, long inY) = 0;
+
+ virtual void PushPen(const QColor &inColor,
+ int inWidth = 1) = 0; //, UINT inStyle = PS_SOLID );
+ virtual void PopPen() = 0;
+ virtual void BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc) = 0;
+
+ virtual void DrawText(float inX, float inY, const QString &inText) = 0;
+ virtual void DrawText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingRect, const QColor &inColor = Qt::black) = 0;
+ virtual void DrawBoldText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingRect, const QColor &inColor = Qt::black) = 0;
+
+ virtual QSize GetTextSize(const QString &inText) = 0;
+
+ virtual void DrawBitmap(const QPoint &inPos, const QPixmap &inImage) = 0;
+ virtual void Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor,
+ const QColor &inBottomRightColor) = 0;
+ virtual void DrawRectOutline(const QRect &inRect, const QColor &inTop, const QColor &inRight,
+ const QColor &inBottom, const QColor &inLeft);
+ virtual void DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted,
+ double inScalingFactor = .99) = 0;
+
+ virtual void DrawGradient(const QRect &inRect, const QColor &inBeginColor,
+ const QColor &inEndColor) = 0;
+
+ virtual void PushTranslation(const QPoint &inTranslation) = 0;
+ virtual void PopTranslation() = 0;
+ virtual QPoint GetTranslation() = 0;
+
+ virtual QRect GetClippingRect() = 0;
+ virtual void PushClippingRect(const QRect &inRect) = 0;
+ virtual void PushAbsoluteClippingRect(const QRect &inRect) = 0;
+ virtual void PopClippingRect() = 0;
+
+ virtual QRect Scroll(const QPoint &inAmount, const QRect &inVisibleSize) = 0;
+
+ virtual void FillHashed(const QRect &inRect, const QColor &inForeGroundColor) = 0;
+
+ virtual QPixmap pixmap() const = 0;
+
+protected:
+ QPoint m_Translation;
+ TTranslationList m_Translations;
+};
+#endif // INCLUDED_RENDERER_H
diff --git a/src/Authoring/Studio/Controls/SIcon.cpp b/src/Authoring/Studio/Controls/SIcon.cpp
new file mode 100644
index 00000000..5df99717
--- /dev/null
+++ b/src/Authoring/Studio/Controls/SIcon.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SIcon.h"
+#include "Renderer.h"
+#include "MasterP.h"
+#include "ResourceCache.h"
+
+//=============================================================================
+/**
+ * Create a new Icon with no image.
+ */
+CSIcon::CSIcon()
+{
+ SetAbsoluteSize(CPt(0, 0));
+ SetImage(QPixmap());
+}
+
+//=============================================================================
+/**
+ * Create a new Icon with the specified images loaded from the resource cache.
+ * @param inResName Name of the image to be loaded for the normal icon
+ * @param inDisabledResName Name of the image to be loaded for the icon when it's disabled
+ */
+CSIcon::CSIcon(const QString &inResName, const QString &inDisabledResName /*= ""*/)
+{
+ SetAbsoluteSize(CPt(0, 0));
+ CResourceCache *theCache = CResourceCache::GetInstance();
+ m_EnabledImage = theCache->GetBitmap(inResName);
+ m_DisabledImage = theCache->GetBitmap(inDisabledResName);
+ SetImage(m_EnabledImage);
+}
+
+//=============================================================================
+/**
+ * Create a new Icon with the specified image.
+ * Any pixels in the image with the transparent color will not be drawn.
+ * The size of this control will be set to the size of the image.
+ * @param inResource string specifying what image to draw.
+ * @param inDisabledResource string specifying what disabled image to draw
+ */
+CSIcon::CSIcon(const QPixmap &inResource, const QPixmap &inDisabledResource /*=NULL*/)
+ : m_DisabledImage(inDisabledResource)
+ , m_EnabledImage(inResource)
+{
+ SetAbsoluteSize(CPt(0, 0));
+ SetImage(m_EnabledImage);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSIcon::~CSIcon()
+{
+}
+
+//=============================================================================
+/**
+ * Set the image that this icon is drawing as.
+ * Any pixels in the image with the transparent color will not be drawn.
+ * The size of this control will be set to the size of the image.
+ * @param inResource the resource ID if the new image to draw.
+ * @param inPreserveSize false to check and set size ( setting to true can reduce flickering in some
+ * cases )
+ */
+void CSIcon::SetImage(const QPixmap &inResource, bool inPreserveSize)
+{
+ m_Image = inResource;
+
+ if (!inPreserveSize) {
+ // If we successfully loaded the new image then modify the size.
+ if (!m_Image.isNull())
+ SetAbsoluteSize(CPt(GetImageSize().width(), GetImageSize().height()));
+ else
+ SetAbsoluteSize(CPt(0, 0));
+ }
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Set image to the one specified
+ * @param inResName Name of the image to be loaded for the normal icon
+ * @param inPreserveSize false to check and set size ( setting to true can reduce flickering in some
+ * cases )
+ */
+void CSIcon::SetImage(const QString &inResName, bool inPreserveSize)
+{
+ CResourceCache *theCache = CResourceCache::GetInstance();
+ SetImage(theCache->GetBitmap(inResName), inPreserveSize);
+}
+
+//=============================================================================
+/**
+ * Draw this image.
+ * @param inRenderer the renderer to draw to.
+ */
+void CSIcon::Draw(CRenderer *inRenderer)
+{
+ inRenderer->PushClippingRect(QRect(QPoint(0,0), GetSize()));
+ if (!m_Image.isNull()) {
+ inRenderer->DrawBitmap(CPt(0, 0), m_Image);
+ }
+ inRenderer->PopClippingRect();
+}
+
+//=============================================================================
+/**
+ * Get the size of this image.
+ */
+QSize CSIcon::GetImageSize()
+{
+ return m_Image.size();
+}
+
+//=============================================================================
+/**
+ * Enables or disables the parent and switches the image to be displayed for
+ * this icon to a disabled or enabled image.
+ */
+void CSIcon::SetParentEnabled(bool inIsEnabled)
+{
+ CControl::SetParentEnabled(inIsEnabled);
+ if (!IsEnabled()) {
+ SetImage(m_DisabledImage);
+ } else {
+ SetImage(m_EnabledImage);
+ }
+ Invalidate();
+}
diff --git a/src/Authoring/Studio/Controls/SIcon.h b/src/Authoring/Studio/Controls/SIcon.h
new file mode 100644
index 00000000..53201e01
--- /dev/null
+++ b/src/Authoring/Studio/Controls/SIcon.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_ICON_H
+#define INCLUDED_ICON_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+
+#include <QPixmap>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//=============================================================================
+/**
+ * Class for drawing bitmapped icon controls to the renderer.
+ */
+class CSIcon : public CControl
+{
+public:
+ CSIcon();
+ CSIcon(const QString &inResName, const QString &inDisabledResName = QString());
+ CSIcon(const QPixmap &inResource, const QPixmap &inDisabledResource = {});
+
+ virtual ~CSIcon();
+
+ void SetImage(const QPixmap &inResource, bool inPreserveSize = false);
+ void SetImage(const QString &inResName, bool inPreserveSize = false);
+ QSize GetImageSize();
+ void SetParentEnabled(bool inParentEnabled) override;
+
+ void Draw(CRenderer *inRenderer) override;
+
+protected:
+ QPixmap m_Image;
+ QPixmap m_DisabledImage;
+ QPixmap m_EnabledImage;
+};
+#endif // INCLUDED_ICON_H
diff --git a/src/Authoring/Studio/Controls/ScrollController.cpp b/src/Authoring/Studio/Controls/ScrollController.cpp
new file mode 100644
index 00000000..8b1dd72f
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollController.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ScrollController.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "Scroller.h"
+#include "Control.h"
+
+using namespace Q3DStudio;
+
+const long CScrollController::DEFAULT_SCROLL_AMOUNT = 20;
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CScrollController::CScrollController()
+ : m_Orientation(IScrollerBar::VERTICAL)
+ , m_ScrollerBar(NULL)
+ , m_Control(NULL)
+ , m_ScrollingForward(false)
+ , m_ScrollingBackward(false)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CScrollController::~CScrollController()
+{
+}
+
+//=============================================================================
+/**
+ * Sets the control. Used to get the check if the mouse is over the control.
+ */
+void CScrollController::SetControl(CControl *inControl)
+{
+ m_Control = inControl;
+}
+
+//=============================================================================
+/**
+ * Sets the scroller bar for this control. Used to get the thumb position in
+ * OnMouseDown.
+ */
+void CScrollController::SetScrollerBar(IScrollerBar *inScrollerBar)
+{
+ m_ScrollerBar = inScrollerBar;
+}
+
+//=============================================================================
+/**
+ * Tells this control which way to draw itself.
+ * @param inOrientation Direction of the scroller that is using this control
+ */
+void CScrollController::SetOrientation(IScrollerBar::EOrientation inOrientation)
+{
+ m_Orientation = inOrientation;
+}
+
+//=============================================================================
+/**
+ * Returns the amount to scroll
+ */
+long CScrollController::DetermineScrollAmount()
+{
+ return DEFAULT_SCROLL_AMOUNT;
+}
+
+//=============================================================================
+/**
+ * Call to scroll forwards.
+ * Forwards is right/down depending on orientation.
+ */
+void CScrollController::OnScrollForward(CControl *inButton)
+{
+ if (!m_ScrollingForward && inButton) {
+ m_ScrollingForward = true;
+
+ Q3DStudio::CString theName = "CScrollController::OnScrollForward";
+ if (m_Control) {
+ theName += "::%s";
+ theName.Format(theName, static_cast<const wchar_t *>(m_Control->GetName()));
+ }
+
+ m_TimerConnection = ITickTock::GetInstance().AddTimer(
+ 100, true, std::bind(&CScrollController::OnTimer, this), theName);
+ }
+
+ Q_UNUSED(inButton);
+ CPt theScrollDistance(0, 0);
+ long theScrollAmount = DetermineScrollAmount();
+
+ if (m_ScrollerBar->GetOrientation() == IScrollerBar::VERTICAL) {
+ theScrollDistance.y = theScrollAmount;
+ } else {
+ theScrollDistance.x = theScrollAmount;
+ }
+
+ m_ScrollerBar->GetScroller()->SetVisiblePosition(
+ m_ScrollerBar->GetScroller()->GetVisiblePosition() + theScrollDistance);
+ m_ScrollerBar->RepositionThumb();
+}
+
+//=============================================================================
+/**
+ * Call to scroll backwards.
+ * Backwards is left/up depending on orientation.
+ */
+void CScrollController::OnScrollBackward(CControl *inButton)
+{
+ if (!m_ScrollingBackward && inButton) {
+ m_ScrollingBackward = true;
+
+ Q3DStudio::CString theName = "CScrollController::OnScrollBackward";
+ if (m_Control) {
+ theName += "::%s";
+ theName.Format(theName, static_cast<const wchar_t *>(m_Control->GetName()));
+ }
+
+ m_TimerConnection = ITickTock::GetInstance().AddTimer(
+ 100, true, std::bind(&CScrollController::OnTimer, this), theName);
+ }
+
+ Q_UNUSED(inButton);
+ CPt theScrollDistance(0, 0);
+ long theScrollAmount = DetermineScrollAmount();
+
+ if (m_ScrollerBar->GetOrientation() == IScrollerBar::VERTICAL) {
+ theScrollDistance.y = theScrollAmount;
+ } else {
+ theScrollDistance.x = theScrollAmount;
+ }
+
+ m_ScrollerBar->GetScroller()->SetVisiblePosition(
+ m_ScrollerBar->GetScroller()->GetVisiblePosition() - theScrollDistance);
+ m_ScrollerBar->RepositionThumb();
+}
+
+//=============================================================================
+/**
+ * Cancels the scrolling. Removes the timer.
+ */
+void CScrollController::OnCancelScrolling(CControl *inButton)
+{
+ Q_UNUSED(inButton);
+
+ m_ScrollingForward = false;
+ m_ScrollingBackward = false;
+
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+}
+
+//=============================================================================
+/**
+ * Overwritten TickTockProc thats called everytime the timer is activated.
+ */
+void CScrollController::OnTimer()
+{
+ if (m_ScrollingForward) {
+ // We want it to scroll only if the mouse is over the control
+ if (m_Control->IsMouseOver()) {
+ OnScrollForward(nullptr);
+ }
+ } else if (m_ScrollingBackward) {
+ // We want it to scroll only if the mouse is over the control
+ if (m_Control->IsMouseOver()) {
+ OnScrollBackward(nullptr);
+ }
+ } else // The timer should not be called if we are not scrolling forward nor backwards
+ {
+ ASSERT(false);
+ }
+}
diff --git a/src/Authoring/Studio/Controls/ScrollController.h b/src/Authoring/Studio/Controls/ScrollController.h
new file mode 100644
index 00000000..9c9cdf41
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollController.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SCROLL_CONTROLLER_H
+#define INCLUDED_SCROLL_CONTROLLER_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BlankControl.h"
+#include "StudioPreferences.h"
+#include "ITickTock.h"
+#include "ScrollerBar.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class CControl;
+
+//=============================================================================
+/**
+ * Extends the blank control to draw items specific to the scroller control.
+ */
+class CScrollController
+{
+public:
+ static const long DEFAULT_SCROLL_AMOUNT;
+
+ CScrollController();
+ virtual ~CScrollController();
+ void SetControl(CControl *inControl);
+ void SetScrollerBar(IScrollerBar *inScrollerBar);
+ void SetOrientation(IScrollerBar::EOrientation inOrientation);
+
+ virtual void OnScrollForward(CControl *inControl = nullptr);
+ virtual void OnScrollBackward(CControl *inControl = nullptr);
+ virtual void OnCancelScrolling(CControl *inControl = nullptr);
+
+protected:
+ void OnTimer();
+
+ std::shared_ptr<UICDM::ISignalConnection> m_TimerConnection;
+ IScrollerBar::EOrientation m_Orientation;
+ IScrollerBar *m_ScrollerBar;
+ CControl *m_Control;
+
+ bool m_ScrollingForward;
+ bool m_ScrollingBackward;
+
+ virtual long DetermineScrollAmount();
+};
+
+#endif // INCLUDED_SCROLL_CONTROLLER_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/Scroller.cpp b/src/Authoring/Studio/Controls/Scroller.cpp
new file mode 100644
index 00000000..9dd3d006
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Scroller.cpp
@@ -0,0 +1,829 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Scroller.h"
+#include "Renderer.h"
+#include "ButtonControl.h"
+#include "MasterP.h"
+#include "UICDMSignals.h"
+#include "ControlData.h"
+
+#include <QDateTime>
+
+using namespace Q3DStudio;
+const unsigned long ORIGINAL_DELAY_TIME = 200;
+const unsigned long ORIGINAL_OFFSET_AMMOUNT = 205;
+//=============================================================================
+/**
+ * Creates a scroller.
+ * @param inCreateImmediately used by subclasses, true if using base class of CScroller
+ */
+CScroller::CScroller(bool inCreateImmediately /* = true */)
+ : m_VisibleSize(0, 0)
+ , m_VisiblePosition(0, 0)
+ , m_VerticalScrollMode(AS_NEEDED)
+ , m_HorizontalScrollMode(AS_NEEDED)
+ , m_ResizingChildren(false)
+ , m_IsMouseDown(false)
+ , m_OffsetAmmount(ORIGINAL_OFFSET_AMMOUNT)
+ , m_DelayTime(ORIGINAL_DELAY_TIME)
+{
+ if (inCreateImmediately)
+ Initialize();
+ m_ControlData->SetMouseWheelEnabled(true);
+
+ SetName("Scroller");
+}
+
+CScroller::~CScroller()
+{
+ delete m_VerticalBar;
+ delete m_HorizontalBar;
+}
+
+//=============================================================================
+/**
+ * Performed once and only once!
+ * Do not call if CScroller was called with the createImmediately flag as true.
+ */
+void CScroller::Initialize()
+{
+ m_VerticalBar = CreateVerticalBar();
+ m_HorizontalBar = CreateHorizontalBar();
+
+ AddChild(m_VerticalBar);
+ AddChild(m_HorizontalBar);
+}
+
+//=============================================================================
+/**
+ * Virtual function to get the vertical scroll bar.
+ * This allows overriding so subclasses can subclass the ScrollerBar as well.
+ * The created bar will be deleted on the destruction of this class.
+ * @return the created scrollerbar.
+ */
+CScrollerBar *CScroller::CreateVerticalBar()
+{
+ CScrollerBar *theBar = new CScrollerBar(this);
+ theBar->SetOrientation(CScrollerBar::VERTICAL);
+
+ return theBar;
+}
+
+//=============================================================================
+/**
+ * Virtual function to get the horizontal scroll bar.
+ * This allows overriding so subclasses can subclass the ScrollerBar as well.
+ * The created bar will be deleted on the destruction of this class.
+ * @return the created scrollerbar.
+ */
+CScrollerBar *CScroller::CreateHorizontalBar()
+{
+ CScrollerBar *theBar = new CScrollerBar(this);
+ theBar->SetOrientation(CScrollerBar::HORIZONTAL);
+
+ return theBar;
+}
+
+void CScroller::OnSizeChanged(CPt /*inSize*/)
+{
+ CPt theMaxPoint = GetMaxVisiblePosition();
+ CPt theVisPoint = GetVisiblePosition();
+ if (theVisPoint.x > theMaxPoint.x)
+ theVisPoint.x = theMaxPoint.x;
+ if (theVisPoint.y > theMaxPoint.y)
+ theVisPoint.y = theMaxPoint.y;
+
+ SetVisiblePosition(theVisPoint);
+ RecalcLayout();
+}
+//=============================================================================
+/**
+ * Sets the size of the scroller.
+ * @param inSize the new size for this scroller.
+ */
+void CScroller::SetSize(CPt inSize)
+{
+ if (inSize != GetSize()) {
+ CControl::SetSize(inSize);
+ OnSizeChanged(inSize);
+ }
+}
+
+void CScroller::SetLayout(CPt inSize, CPt inPosition)
+{
+ CControl::SetLayout(inSize, inPosition);
+ OnSizeChanged(inSize);
+}
+
+//=============================================================================
+/**
+ * Gets the minimum size that this scroller is allowed to be.
+ * This is calculated from the minimum size of the child control and the
+ * needed size of the scroll bars.
+ * @return the minimum size of this object.
+ */
+CPt CScroller::GetMinimumSize()
+{
+ CPt theSize(0, 0);
+ CControl *theChildControl = GetControl();
+ if (theChildControl != nullptr) {
+ CPt theChildMin = theChildControl->GetMinimumSize();
+ // If at zero the scroll bars are up then include them in the size.
+ if (theChildMin.x != 0) {
+ theSize += m_HorizontalBar->GetMinimumSize();
+ }
+ if (theChildMin.y != 0) {
+ theSize += m_VerticalBar->GetMinimumSize();
+ }
+ }
+
+ return theSize;
+}
+
+//=============================================================================
+/**
+ * Get the maximum size of this scroller.
+ * This is just the maximum size of the child window, since the scroll bars
+ * will not be up when at max size.
+ * @return the maximum size of this control.
+ */
+CPt CScroller::GetMaximumSize()
+{
+ CPt theMaxSize;
+ CControl *theChildControl = GetControl();
+ if (theChildControl != nullptr)
+ theMaxSize = theChildControl->GetMaximumSize();
+ else
+ theMaxSize = CControl::GetMaximumSize();
+
+ return theMaxSize;
+}
+
+//=============================================================================
+/**
+ * Add a child control to this control.
+ * This is used to add a new child to this control. If there is already a
+ * component in the scrolling window then inControl will take the place of the
+ * previous control and the previous will be removed as a child of this.
+ * @param inControl the control to be added.
+ * @param inInsertBefore not used.
+ */
+void CScroller::AddChild(CControl *inControl, CControl *inInsertBefore /*= nullptr*/)
+{
+ Q_UNUSED(inInsertBefore);
+
+ if (GetChildCount() > 3)
+ RemoveChild(GetChildren().GetCurrent()->GetControl());
+
+ if (GetChildCount() > 0)
+ CControl::AddChild(inControl, GetChildren().GetCurrent()->GetControl());
+ else
+ CControl::AddChild(inControl);
+
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Recalculate the layout of this object.
+ * This is used anytime this is changing size or needs to figure out where the
+ * controls go. This does all the work of setting the scrollerbar positions and
+ * the child window positions.
+ */
+void CScroller::RecalcLayout()
+{
+ UICPROFILE(RecalcLayout);
+
+ m_ResizingChildren = true;
+
+ CPt mySize = GetSize();
+ m_VisibleSize = mySize;
+
+ // If the side bar should be visible
+ if (IsVerticalVisible()) {
+ // Make sure the side bar is visible.
+ m_VerticalBar->SetVisible(true);
+
+ // Set the side bars position
+ m_VerticalBar->SetPosition(CPt(mySize.x - m_VerticalBar->GetMinimumSize().x, 0));
+ // the width of the vertical bar is subtracted from the visible area.
+ m_VisibleSize.x -= m_VerticalBar->GetMinimumSize().x;
+
+ if (!IsVerticalScrolling())
+ m_VerticalBar->SetEnabled(false);
+ else
+ m_VerticalBar->SetEnabled(true);
+ } else
+ m_VerticalBar->SetVisible(false);
+
+ if (IsHorizontalVisible()) {
+ // Make sure the bottom bar is visible.
+ m_HorizontalBar->SetVisible(true);
+
+ // Set the bottom bar's position.
+ m_HorizontalBar->SetPosition(CPt(0, mySize.y - m_HorizontalBar->GetMinimumSize().y));
+ // the height of the horizontal bar is subtracted from the visible area.
+ m_VisibleSize.y -= m_HorizontalBar->GetMinimumSize().y;
+
+ if (!IsHorizontalScrolling())
+ m_HorizontalBar->SetEnabled(false);
+ else
+ m_HorizontalBar->SetEnabled(true);
+ } else
+ m_HorizontalBar->SetVisible(false);
+
+ SetVisibleSize(m_VisibleSize);
+ SetVisiblePosition(GetVisiblePosition());
+
+ if (IsVerticalVisible())
+ m_VerticalBar->SetSize(CPt(m_VerticalBar->GetMinimumSize().x, m_VisibleSize.y));
+ if (IsHorizontalVisible())
+ m_HorizontalBar->SetSize(CPt(m_VisibleSize.x, m_HorizontalBar->GetMinimumSize().y));
+
+ m_ResizingChildren = false;
+}
+
+//=============================================================================
+/**
+ * Set the size of the inner control that is visible.
+ * @param inSize the size of the inner control that is to be visible.
+ */
+void CScroller::SetVisibleSize(CPt inSize)
+{
+ m_VisibleSize = inSize;
+
+ // If we have a child then set all of it's properties up.
+ CControl *theChild = GetControl();
+ if (theChild) {
+ CPt theChildSize = m_VisibleSize;
+ CPt theMinSize = theChild->GetMinimumSize();
+
+ if (theMinSize.x < theChildSize.x)
+ theMinSize.x = theChildSize.x;
+ if (theMinSize.y < theChildSize.y)
+ theMinSize.y = theChildSize.y;
+
+ // Set the sizes of the child to be either the size of the control or it's minimum size
+ if (theMinSize.x > theChildSize.x)
+ theChildSize.x = theMinSize.x;
+ if (theMinSize.y > theChildSize.y)
+ theChildSize.y = theMinSize.y;
+
+ theChild->SetSize(theChildSize);
+ }
+}
+
+//=============================================================================
+/**
+ * Check to see is the vertical bar should be visible or not.
+ * @return true if the vertical bar should be visible.
+ */
+bool CScroller::IsVerticalVisible()
+{
+ if (m_VerticalScrollMode != NEVER) {
+ if (m_VerticalScrollMode == ALWAYS || IsVerticalScrolling()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Check to see if the horizontal bar should be visible or not.
+ * @return true if the horizontal bar should be visible.
+ */
+bool CScroller::IsHorizontalVisible()
+{
+ if (m_HorizontalScrollMode != NEVER) {
+ if (m_HorizontalScrollMode == ALWAYS || IsHorizontalScrolling()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Checks to see if the client view should be scrolled vertically or not.
+ * This does not mean that the scroll bar is visible or not, just that the client
+ * view can be scrolled vertically.
+ * @return true if the client min height larger than this height.
+ */
+bool CScroller::IsVerticalScrolling()
+{
+ CControl *theChild = GetControl();
+ if (theChild != nullptr) {
+ CPt mySize = GetSize();
+ if (m_HorizontalScrollMode == ALWAYS)
+ mySize.y -= m_HorizontalBar->GetSize().y;
+
+ CPt theChildSize = theChild->GetMinimumSize();
+
+ if (theChildSize.y > mySize.y)
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Checks to see if the client view should be scrolled horizontally or not.
+ * This does not mean that the scroll bar is visible or not, just that the
+ * client view can be scrolled horizontally.
+ * @return true if the client min width is larget than this width.
+ */
+bool CScroller::IsHorizontalScrolling()
+{
+ CControl *theChild = GetControl();
+ if (theChild != nullptr) {
+ CPt mySize = GetSize();
+ if (m_VerticalScrollMode == ALWAYS)
+ mySize.x -= m_VerticalBar->GetSize().x;
+
+ CPt theChildSize = theChild->GetMinimumSize();
+
+ if (theChildSize.x > mySize.x)
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Get the child control that this is wrapping.
+ * @return the child control, or nullptr if there is not one.
+ */
+CControl *CScroller::GetControl()
+{
+ if (GetChildCount() > 2)
+ return GetChildren().GetCurrent()->GetControl();
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Get the size of this control that the Client is actually visible in.
+ * This is not the size of the client, but the size of the area that the client
+ * is being drawn to.
+ * @return the visible area of the child control.
+ */
+CPt CScroller::GetVisibleSize()
+{
+ return m_VisibleSize;
+}
+
+//=============================================================================
+/**
+ * Get the size of the actual child control.
+ * This is the total size of the child, and is always at least the size of
+ * the visible size.
+ * @return the size of the child control.
+ */
+CPt CScroller::GetContaineeSize()
+{
+ UICPROFILE(GetContaineeSize);
+
+ CControl *theControl = GetControl();
+ CPt theSize;
+ if (theControl != nullptr)
+ theSize = theControl->GetSize();
+ else
+ theSize = GetSize();
+
+ return theSize;
+}
+
+//=============================================================================
+/**
+ * Get the offset of the child control inside of this control.
+ * @return the offset location of the child.
+ */
+CPt CScroller::GetVisiblePosition()
+{
+ return m_VisiblePosition;
+}
+
+//=============================================================================
+/**
+ * Set the visible position of the child control.
+ * @param inVisiblePosition the visible position of the child control.
+ */
+void CScroller::SetVisiblePosition(CPt inVisiblePosition)
+{
+ if (inVisiblePosition.x < 0)
+ inVisiblePosition.x = 0;
+
+ if (inVisiblePosition.y < 0)
+ inVisiblePosition.y = 0;
+
+ CPt theMaxVisiblePosition = GetMaxVisiblePosition();
+
+ if (inVisiblePosition.x > theMaxVisiblePosition.x)
+ inVisiblePosition.x = theMaxVisiblePosition.x;
+
+ if (inVisiblePosition.y > theMaxVisiblePosition.y)
+ inVisiblePosition.y = theMaxVisiblePosition.y;
+
+ if (inVisiblePosition != m_VisiblePosition) {
+ CPt theScrolledAmount = m_VisiblePosition - inVisiblePosition;
+ m_ScrolledAmount += theScrolledAmount;
+
+ m_VisiblePosition = inVisiblePosition;
+
+ if (IsVerticalScrolling())
+ m_VerticalBar->RepositionThumb();
+ if (IsHorizontalScrolling())
+ m_HorizontalBar->RepositionThumb();
+
+ m_ScrollListeners.FireEvent(&CScrollListener::OnScroll, this, theScrolledAmount);
+ }
+
+ CControl *theChild = GetControl();
+ if (theChild != nullptr) {
+ theChild->SetPosition(-m_VisiblePosition);
+ }
+}
+
+//=============================================================================
+/**
+ * Get the maximum allowable offset of the child control.
+ * This is where the child would be offset to if the scroll bars were at their
+ * far ends.
+ * @return the maximum visible position allowed.
+ */
+CPt CScroller::GetMaxVisiblePosition()
+{
+ CPt theMaxPoint(0, 0);
+ CPt mySize = GetSize();
+ CControl *theChild = GetControl();
+
+ mySize.x -= IsVerticalVisible() ? m_VerticalBar->GetSize().x : 0;
+ mySize.y -= IsHorizontalVisible() ? m_HorizontalBar->GetSize().y : 0;
+
+ if (theChild != nullptr) {
+ CPt theChildSize = theChild->GetSize();
+
+ if (theChildSize.x > mySize.x)
+ theMaxPoint.x = theChildSize.x - mySize.x;
+
+ if (theChildSize.y > mySize.y)
+ theMaxPoint.y = theChildSize.y - mySize.y;
+ }
+
+ return theMaxPoint;
+}
+
+void CScroller::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation)
+{
+ UICPROFILE(OnDraw);
+
+ CRct theDirtyRect;
+ bool isInvalidated = IsInvalidated();
+
+ if (isInvalidated || inIgnoreValidation || m_VerticalBar->IsChildInvalidated()
+ || m_HorizontalBar->IsChildInvalidated()) {
+ if (isInvalidated || inIgnoreValidation)
+ DrawBackground(inRenderer);
+ Draw(inRenderer);
+ theDirtyRect.Or(CRct(GetSize()));
+ }
+
+ CControl *theChild = GetControl();
+ if (theChild != nullptr) {
+ // Create an off screen buffer to draw the child to, this makes it so the child will draw
+ // it's
+ // entire self to the offscreen section, then we'll only draw the visible part to the actual
+ // renderer
+ CRct theClippingRect = m_VisibleSize;
+ if (m_AddtlClippingRect.size.x != 0 && m_AddtlClippingRect.size.y != 0)
+ theClippingRect.And(m_AddtlClippingRect);
+
+ inRenderer->PushClippingRect(theClippingRect);
+ inRenderer->PushTranslation(-m_VisiblePosition);
+ theChild->OnDraw(inRenderer, theDirtyRect, isInvalidated || inIgnoreValidation);
+ inRenderer->PopTranslation();
+ inRenderer->PopClippingRect();
+
+ m_ScrolledAmount = CPt(0, 0);
+ }
+
+ Invalidate(false);
+
+ CRct theBoundingBox = inRenderer->GetClippingRect();
+ theDirtyRect.And(theBoundingBox);
+ theDirtyRect.Offset(inRenderer->GetTranslation());
+ inDirtyRect.Or(theDirtyRect);
+}
+
+//=============================================================================
+/**
+ * Overrides CControl::Draw to handle custom child buffering.
+ * This just allows the child to be drawn offset without actually letting it
+ * know that it's offset.
+ * @param inRenderer the renderer to draw to.
+ */
+void CScroller::Draw(CRenderer *inRenderer)
+{
+ UICPROFILE(Draw);
+
+ CRct theDirtyRct;
+ // Only draw the side bar if it's visible
+ if (m_VerticalBar->IsVisible()) {
+ inRenderer->PushTranslation(m_VerticalBar->GetPosition());
+ m_VerticalBar->OnDraw(inRenderer, theDirtyRct, true);
+ inRenderer->PopTranslation();
+ }
+
+ // only draw the bottom bar if it's visible
+ if (m_HorizontalBar->IsVisible()) {
+ inRenderer->PushTranslation(m_HorizontalBar->GetPosition());
+ m_HorizontalBar->OnDraw(inRenderer, theDirtyRct, true);
+ inRenderer->PopTranslation();
+ }
+}
+
+//=============================================================================
+/**
+ * Gets the horizontal scroll bar of this scroller.
+ * @return the horizontal scroll bar of this scroller.
+ */
+CScrollerBar *CScroller::GetHorizontalBar()
+{
+ return m_HorizontalBar;
+}
+
+//=============================================================================
+/**
+ * Gets the vertical scroll bar of this scroller.
+ * @return the vertical scroll bar of this scroller.
+ */
+CScrollerBar *CScroller::GetVerticalBar()
+{
+ return m_VerticalBar;
+}
+
+//=============================================================================
+/**
+ * Sets the vertical scroll mode of this scroller.
+ * This controls when the scroll bars will be visible and when thes will not be
+ * visible.
+ * @param inScrollMode the vertical scroll mode.
+ */
+void CScroller::SetVerticalScrollMode(EScrollMode inScrollMode)
+{
+ m_VerticalScrollMode = inScrollMode;
+}
+
+//=============================================================================
+/**
+ * Gets the vertical scroll mode of this scroller.
+ * This controls when the scroll bars will be visible and when they will not be
+ * visible.
+ * @return the vertical scroll mode.
+ */
+CScroller::EScrollMode CScroller::GetVerticalScrollMode()
+{
+ return m_VerticalScrollMode;
+}
+
+//=============================================================================
+/**
+ * Sets the horizontal scroll mode of this scroller.
+ * This controls when the scroll bars will be visible and when they will not be
+ * visible.
+ * @param inScrollMode the vertical scroll mode.
+ */
+void CScroller::SetHorizontalScrollMode(EScrollMode inScrollMode)
+{
+ m_HorizontalScrollMode = inScrollMode;
+}
+
+//=============================================================================
+/**
+ * Gets the horizontal scroll mode of this scroller.
+ * This controls when the scroll bars will be visible and when they will not be
+ * visible.
+ * @return the horizontal scroll mode.
+ */
+CScroller::EScrollMode CScroller::GetHorizontalScrollMode()
+{
+ return m_HorizontalScrollMode;
+}
+
+void CScroller::OnChildSizeChanged(CControl *inControl)
+{
+ UICPROFILE(OnChildSizeChanged);
+
+ CControl *theChild = GetControl();
+
+ if (inControl == theChild) {
+ CPt theChildSize = theChild->GetSize();
+ CPt theMinSize = GetVisibleSize();
+ if (theChildSize.x < theMinSize.x) {
+ theChild->SetMinimumSize(CPt(theMinSize.x, theChild->GetMinimumSize().y));
+ theChildSize.x = theMinSize.x;
+ }
+ if (theChildSize.y < theMinSize.y) {
+ theChild->SetMinimumSize(CPt(theChild->GetMinimumSize().x, theMinSize.y));
+ theChildSize.y = theMinSize.y;
+ }
+
+ if (theChildSize != theChild->GetSize())
+ theChild->SetSize(theChildSize);
+ else if (!m_ResizingChildren) {
+ RecalcLayout();
+ Invalidate();
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Add a listener to get notified when this control scrolls.
+ * @param inListener the listener to be notified when this scrolls.
+ */
+void CScroller::AddScrollListener(CScrollListener *inListener)
+{
+ m_ScrollListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Remove a listener from the list of listeners to be notified when this scrolls.
+ * @param inListener the listener to be removed from the list of listeners.
+ */
+void CScroller::RemoveScrollListener(CScrollListener *inListener)
+{
+ m_ScrollListeners.RemoveListener(inListener);
+}
+
+void CScroller::SetAdditionalClippingRect(CRct inAddtlClippingRect)
+{
+ m_AddtlClippingRect = inAddtlClippingRect;
+}
+
+bool CScroller::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CPt theVertPoint = inPoint - m_VerticalBar->GetPosition();
+ if (!m_VerticalBar->HitTest(inPoint) && !m_HorizontalBar->HitTest(inPoint)) {
+ m_IsMouseDown = true;
+ }
+
+ return CControl::OnMouseDown(inPoint, inFlags);
+}
+
+void CScroller::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_IsMouseDown) {
+ m_CurrentTickTock = std::shared_ptr<UICDM::ISignalConnection>();
+
+ CPt theOffset;
+ if ((inPoint.x < 0))
+ theOffset.x = inPoint.x;
+ else if (inPoint.x > m_VisibleSize.x)
+ theOffset.x = inPoint.x - m_VisibleSize.x;
+
+ // if ( ( inPoint.y < 0 && inPoint.y < m_PrevMousePoint.y ) || ( inPoint.y >
+ //m_VisibleSize.y && inPoint.y > m_PrevMousePoint.y ) )
+ // theOffset.y = inPoint.y - m_PrevMousePoint.y;
+
+ SetVisiblePosition(m_VisiblePosition + theOffset);
+
+ if (theOffset.x != 0) {
+ m_ScrollingDir = theOffset;
+ m_MousePos = inPoint;
+ m_MouseFlags = inFlags;
+ m_CurrentTickTock = ITickTock::GetInstance().AddTimer(
+ m_DelayTime, true, std::bind(&CScroller::OnTimer, this),
+ "CScroller::OnMouseMove::" + GetName());
+ // OnTimer( );
+ }
+ }
+
+ CControl::OnMouseMove(inPoint, inFlags);
+}
+
+void CScroller::OnTimer()
+{
+ CPt theOffset;
+ const auto theBeginCurrentTime = QDateTime::currentMSecsSinceEpoch();
+ if (m_ScrollingDir.x > 0)
+ theOffset.x = m_OffsetAmmount;
+ else if (m_ScrollingDir.x < 0)
+ theOffset.x = -m_OffsetAmmount;
+
+ SetVisiblePosition(m_VisiblePosition + theOffset);
+ CControl::OnMouseMove(m_MousePos, m_MouseFlags);
+ const auto theEndCurrentTime = QDateTime::currentMSecsSinceEpoch();
+ AdjustDelayTimeAccordingToOnTimerTime(theEndCurrentTime - theBeginCurrentTime);
+}
+
+//=============================================================================
+/**
+ * This function will adjust the delay time of the auto scroller depending on how long the timer
+ * took
+ * the numbers in here are pretty arbitrary and this should be redone at some point.
+ * @param inTime the amount of time that the timer took
+ */
+void CScroller::AdjustDelayTimeAccordingToOnTimerTime(unsigned long inTime)
+{
+ for (long theIndex = 2; theIndex < 6; theIndex++) {
+ if ((inTime)*theIndex > m_DelayTime) {
+ m_DelayTime = static_cast<unsigned long>(m_DelayTime * 10 / theIndex);
+ m_OffsetAmmount = static_cast<unsigned long>(m_OffsetAmmount * 10 / theIndex);
+ m_CurrentTickTock = ITickTock::GetInstance().AddTimer(
+ m_DelayTime, true, std::bind(&CScroller::OnTimer, this),
+ "CScroller::AdjustDelayTimeAccordingToOnTimerTime");
+ break;
+ }
+ }
+}
+
+void CScroller::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_IsMouseDown = false;
+
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ m_CurrentTickTock = std::shared_ptr<UICDM::ISignalConnection>();
+}
+
+void CScroller::OnLoseFocus()
+{
+ m_IsMouseDown = false;
+ m_CurrentTickTock = std::shared_ptr<UICDM::ISignalConnection>();
+ CControl::OnLoseFocus();
+}
+
+//=============================================================================
+/**
+ * Handles mouse wheel messages to scroll the view.
+ */
+bool CScroller::OnMouseWheel(CPt inPoint, long inScrollAmount, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseWheel(inPoint, inScrollAmount, inFlags)) {
+ if (inScrollAmount < 0)
+ SetVisiblePosition(CPt(GetVisiblePosition().x, GetVisiblePosition().y + 60));
+ else
+ SetVisiblePosition(CPt(GetVisiblePosition().x, GetVisiblePosition().y - 60));
+ }
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handles messages from children to scroll the view to appropriate loc.
+ */
+void CScroller::EnsureVisible(CRct inRect)
+{
+ CControl *theChild = GetControl();
+ inRect.position -= theChild->GetPosition();
+
+ CPt theVisSize = GetVisibleSize();
+ CPt theVisPos = GetVisiblePosition();
+
+ // Check to see if the top is off the top.
+ if (inRect.position.y < theVisPos.y)
+ theVisPos.y = inRect.position.y;
+ // Check to see if the bottom is off the bottom.
+ else if (inRect.position.y + inRect.size.y > theVisPos.y + theVisSize.y)
+ theVisPos.y = inRect.position.y + inRect.size.y - theVisSize.y;
+
+ SetVisiblePosition(theVisPos);
+}
diff --git a/src/Authoring/Studio/Controls/Scroller.h b/src/Authoring/Studio/Controls/Scroller.h
new file mode 100644
index 00000000..9cb39962
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Scroller.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SCROLLER_H
+#define INCLUDED_SCROLLER_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "ScrollerBar.h"
+#include "FlowLayout.h"
+#include "GenericFunctor.h"
+#include "Multicaster.h"
+#include "ITickTock.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CButtonControl;
+
+GENERIC_FUNCTOR_2(CScrollListener, OnScroll, CScroller *, CPt);
+
+class IScroller
+{
+protected:
+ virtual ~IScroller() {}
+public:
+ virtual void SetVisiblePosition(CPt inVisiblePosition) = 0;
+ virtual CPt GetVisiblePosition() = 0;
+};
+
+//=============================================================================
+/**
+ * Class for creating a scroller.
+ */
+class CScroller : public CControl, public IScroller
+{
+public:
+ enum EScrollMode {
+ NEVER,
+ AS_NEEDED,
+ ALWAYS,
+ };
+
+ CScroller(bool inCreateImmediately = true);
+ virtual ~CScroller();
+
+ void Initialize();
+
+ void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect,
+ bool inIgnoreValidation /* = false */) override;
+ virtual void DrawBackground(CRenderer *) {}
+ void Draw(CRenderer *inRenderer) override;
+
+ void SetSize(CPt inSize) override;
+ void SetLayout(CPt inSize, CPt inPosition) override;
+ CPt GetMinimumSize() override;
+ CPt GetMaximumSize() override;
+
+ void AddChild(CControl *inControl, CControl *inInsertBefore = nullptr) override;
+
+ CPt GetVisibleSize();
+ CPt GetContaineeSize();
+
+ CPt GetVisiblePosition() override;
+ void SetVisiblePosition(CPt inVisiblePosition) override;
+ CPt GetMaxVisiblePosition();
+
+ CScrollerBar *GetHorizontalBar();
+ CScrollerBar *GetVerticalBar();
+
+ void SetVerticalScrollMode(EScrollMode inScrollMode);
+ EScrollMode GetVerticalScrollMode();
+
+ void SetHorizontalScrollMode(EScrollMode inScrollMode);
+ EScrollMode GetHorizontalScrollMode();
+
+ virtual void RecalcLayout();
+ void OnChildSizeChanged(CControl *inChild) override;
+
+ void AddScrollListener(CScrollListener *inScrollListener);
+ void RemoveScrollListener(CScrollListener *inScrollListener);
+
+ void SetAdditionalClippingRect(CRct inClippingRect);
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseWheel(CPt inPoint, long inScrollAmount, Qt::KeyboardModifiers inFlags) override;
+ void EnsureVisible(CRct inRect) override;
+
+ virtual void OnTimer();
+ void OnLoseFocus() override;
+ void AdjustDelayTimeAccordingToOnTimerTime(unsigned long inTime);
+
+protected:
+ void OnSizeChanged(CPt inSize) override;
+ virtual bool IsVerticalVisible();
+ virtual bool IsHorizontalVisible();
+ virtual bool IsVerticalScrolling();
+ virtual bool IsHorizontalScrolling();
+
+ virtual CScrollerBar *CreateVerticalBar();
+ virtual CScrollerBar *CreateHorizontalBar();
+
+ virtual void SetVisibleSize(CPt inSize);
+
+ virtual CControl *GetControl();
+
+ CScrollerBar *m_VerticalBar;
+ CScrollerBar *m_HorizontalBar;
+
+ CPt m_VisibleSize;
+ CPt m_VisiblePosition;
+ CPt m_MaxVisiblePosition;
+
+ CPt m_ScrolledAmount;
+ CPt m_ChildOffset;
+
+ CRct m_AddtlClippingRect;
+ CPt m_ScrollingDir;
+ CPt m_MousePos;
+ Qt::KeyboardModifiers m_MouseFlags;
+
+ EScrollMode m_VerticalScrollMode;
+ EScrollMode m_HorizontalScrollMode;
+
+ bool m_ResizingChildren;
+
+ CMulticaster<CScrollListener *> m_ScrollListeners;
+
+ bool m_IsMouseDown;
+ CPt m_PrevMousePoint;
+
+ long m_OffsetAmmount;
+ unsigned long m_DelayTime;
+ std::shared_ptr<UICDM::ISignalConnection> m_CurrentTickTock;
+};
+#endif // INCLUDED_SCROLLER_H
diff --git a/src/Authoring/Studio/Controls/ScrollerBackground.cpp b/src/Authoring/Studio/Controls/ScrollerBackground.cpp
new file mode 100644
index 00000000..fcfa5e7f
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerBackground.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ScrollerBackground.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "Scroller.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CScrollerBackground::CScrollerBackground(CColor inColor)
+ : CBlankControl(inColor)
+{
+ m_Orientation = CScrollerBar::HORIZONTAL;
+ m_ScrollerBar = nullptr;
+ m_Control = this;
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CScrollerBackground::~CScrollerBackground()
+{
+}
+
+//=============================================================================
+/**
+ * Overrides CBlankControl::Draw to handle scroller-specific drawing.
+ */
+void CScrollerBackground::Draw(CRenderer *inRenderer)
+{
+ CBlankControl::Draw(inRenderer);
+
+ if (CScrollerBar::HORIZONTAL == m_Orientation) {
+ // Horizontal lines
+ inRenderer->PushPen(CStudioPreferences::GetScrollBGOutlineColor(), 1);
+ inRenderer->MoveTo(0, 0);
+ inRenderer->LineTo(GetSize().x, 0);
+ inRenderer->PopPen();
+ inRenderer->PushPen(CStudioPreferences::GetScrollBGOutlineColor(), 1);
+ inRenderer->MoveTo(0, GetSize().y - 1);
+ inRenderer->LineTo(GetSize().x, GetSize().y - 1);
+ inRenderer->PopPen();
+ } else {
+ // Vertical lines
+ inRenderer->PushPen(CStudioPreferences::GetScrollBGOutlineColor(), 1);
+ inRenderer->MoveTo(0, 0);
+ inRenderer->LineTo(0, GetSize().y - 1);
+ inRenderer->MoveTo(GetSize().x - 1, 0);
+ inRenderer->LineTo(GetSize().x - 1, GetSize().y - 1);
+ inRenderer->PopPen();
+ }
+}
+
+//=============================================================================
+/**
+ * Handles mouse down events. Scrolls the thumb to the clicked position.
+ * @param inPoint location of the mouse click
+ * @param inFlags mouse event flags
+ */
+bool CScrollerBackground::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theHandledFlag = CBlankControl::OnMouseDown(inPoint, inFlags);
+
+ if (!theHandledFlag && m_ScrollerBar) {
+ CPt theThumbPosition = m_ScrollerBar->GetThumb()->GetPosition();
+ bool theScrollForwardFlag = false;
+
+ if (CScrollerBar::HORIZONTAL == m_Orientation) {
+ if (inPoint.x > theThumbPosition.x)
+ theScrollForwardFlag = true;
+ } else {
+ if (inPoint.y > theThumbPosition.y)
+ theScrollForwardFlag = true;
+ }
+
+ m_MousePos = inPoint;
+
+ if (theScrollForwardFlag)
+ OnScrollForward(this);
+ else
+ OnScrollBackward(this);
+
+ theHandledFlag = true;
+ }
+
+ return theHandledFlag;
+}
+
+//=============================================================================
+/**
+ * Handles mouse up events
+ */
+void CScrollerBackground::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CBlankControl::OnMouseUp(inPoint, inFlags);
+
+ OnCancelScrolling();
+}
+
+//=============================================================================
+/**
+ * Returns the amount to scroll
+ */
+long CScrollerBackground::DetermineScrollAmount()
+{
+ long theDistance = 0;
+ CPt theThumbPosition = m_ScrollerBar->GetThumb()->GetPosition();
+ CPt theThumbSize = m_ScrollerBar->GetThumb()->GetSize();
+
+ if (CScrollerBar::VERTICAL == m_Orientation) {
+ if ((m_ScrollingForward && (m_MousePos.y > theThumbPosition.y + theThumbSize.y))
+ || (m_ScrollingBackward && (m_MousePos.y < theThumbPosition.y))) {
+ theDistance = theThumbSize.y;
+ }
+ } else // HORIZONTAL
+ {
+ if ((m_ScrollingForward && (m_MousePos.x > theThumbPosition.x + theThumbSize.x))
+ || (m_ScrollingBackward && (m_MousePos.x < theThumbPosition.x))) {
+ theDistance = theThumbSize.x;
+ }
+ }
+
+ return theDistance;
+}
+
+//=============================================================================
+/**
+ * Overwrite the MouseMove function. We want to take care of the scenario where
+ * it is in a scrolling state, then determine whether to scroll forwards or backwards
+ * depending on the mouse position relative to the scroller thumb.
+ */
+void CScrollerBackground::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Call the default mouseMove function
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ // We only want to do stuff if it is currently scrolling
+ if (m_ScrollingForward || m_ScrollingBackward) {
+ // save the mouse position
+ m_MousePos = inPoint;
+
+ CPt theThumbPosition = m_ScrollerBar->GetThumb()->GetPosition();
+ CPt theThumbSize = m_ScrollerBar->GetThumb()->GetSize();
+
+ if (CScrollerBar::VERTICAL == m_Orientation) {
+ if (m_MousePos.y > (theThumbPosition.y + theThumbSize.y)) {
+ m_ScrollingForward = true;
+ m_ScrollingBackward = false;
+ } else {
+ m_ScrollingForward = false;
+ m_ScrollingBackward = true;
+ }
+ } else // HORIZONTAL
+ {
+ if (m_MousePos.x > (theThumbPosition.x + theThumbSize.x)) {
+ m_ScrollingForward = true;
+ m_ScrollingBackward = false;
+ } else {
+ m_ScrollingForward = false;
+ m_ScrollingBackward = true;
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Controls/ScrollerBackground.h b/src/Authoring/Studio/Controls/ScrollerBackground.h
new file mode 100644
index 00000000..885d1c88
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerBackground.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SCROLLER_BACKGROUND_H
+#define INCLUDED_SCROLLER_BACKGROUND_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BlankControl.h"
+#include "StudioPreferences.h"
+#include "ScrollerBar.h"
+#include "ScrollController.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//=============================================================================
+/**
+ * Extends the blank control to draw items specific to the scroller control.
+ */
+class CScrollerBackground : public CBlankControl, public CScrollController
+{
+protected:
+ CPt m_MousePos;
+
+public:
+ CScrollerBackground(CColor inColor = CStudioPreferences::GetScrollBGColor());
+ virtual ~CScrollerBackground();
+ virtual void Draw(CRenderer *inRenderer);
+ virtual bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags);
+
+protected:
+ virtual long DetermineScrollAmount();
+};
+
+#endif // INCLUDED_SCROLLER_BACKGROUND_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/ScrollerBar.cpp b/src/Authoring/Studio/Controls/ScrollerBar.cpp
new file mode 100644
index 00000000..b054fb6e
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerBar.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ScrollerBar.h"
+#include "Scroller.h"
+#include "Renderer.h"
+#include "ButtonControl.h"
+#include "CoreUtils.h"
+#include "ScrollerBackground.h"
+#include "ScrollerThumb.h"
+#include "StudioPreferences.h"
+#include "Renderer.h"
+#include "SystemPreferences.h"
+#include "StudioUtils.h"
+#include "ScrollerButtonControl.h"
+#include "MasterP.h"
+
+//==============================================================================
+// Static variables
+//==============================================================================
+const long CScrollerBar::DEFAULT_WIDTH = 16;
+const CColor CScrollerBar::DEFAULT_COLOR = CColor(196, 194, 189);
+const CColor CScrollerBar::SCROLLER_TOP = CColor(165, 162, 161);
+
+IMPLEMENT_OBJECT_COUNTER(CScrollerBar)
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inScroller the scroller on which this is operating.
+ * @param inCreateImmediately false for lazy construction, only for subclasses.
+ */
+CScrollerBar::CScrollerBar(CScroller *inScroller, bool inCreateImmediately /* = true */)
+{
+ ADDTO_OBJECT_COUNTER(CScrollerBar)
+
+ m_Scroller = inScroller;
+ SetFlowDirection(FLOW_HORIZONTAL);
+
+ if (inCreateImmediately)
+ Initialize();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CScrollerBar::~CScrollerBar()
+{
+ REMOVEFROM_OBJECT_COUNTER(CScrollerBar)
+}
+
+//=============================================================================
+/**
+ * Initialize this scroller bar.
+ * This is used for lazy construction of this object by subclasses. If a subclass
+ * specifies lazy construction in the constructor of this class then it must call
+ * this to put it into a valid state.
+ */
+void CScrollerBar::Initialize()
+{
+ m_ScrollerThumb = CreateThumb();
+
+ // First button
+ m_ButtonBackward = new CScrollerButtonControl(this, CScrollerButtonControl::BACKWARD);
+
+ // Background
+ m_Background = new CScrollerBackground(CStudioPreferences::GetScrollBGColor());
+ m_Background->SetScrollerBar(this);
+ m_Background->AddChild(m_ScrollerThumb);
+
+ m_ScrollerThumb->SetPosition(CPt(0, 0));
+
+ // Second button (either right or bottom)
+ m_ButtonForward = new CScrollerButtonControl(this, CScrollerButtonControl::FORWARD);
+
+ // Determine the placement of the scroll bar arrows based on the system preference
+ if (CSystemPreferences::AreScrollArrowsAdjacent()) {
+ // Scroll arrows go together at one end of the bar
+ AddChild(m_Background);
+ AddChild(m_ButtonBackward);
+ AddChild(m_ButtonForward);
+ } else {
+ // Scroll arrows go on each end of the scroll bar
+ AddChild(m_ButtonBackward);
+ AddChild(m_Background);
+ AddChild(m_ButtonForward);
+ }
+}
+
+//=============================================================================
+/**
+ * Virtual class to create the thumb class.
+ * This is used to allow sub-classes to specialize the scroller thumb that they
+ * are using.
+ * @return the thumb that was created.
+ */
+CControl *CScrollerBar::CreateThumb()
+{
+ return new CScrollerThumb(this);
+}
+
+//=============================================================================
+/**
+ * Set the orientation of this scroller bar.
+ * This determines which way this is scrolling.
+ */
+void CScrollerBar::SetOrientation(EOrientation inOrientation)
+{
+ m_Orientation = inOrientation;
+ m_Background->SetOrientation(inOrientation);
+
+ if (m_Orientation == VERTICAL) {
+ // Vertical buttons
+ SetFlowDirection(FLOW_VERTICAL);
+ m_ButtonBackward->SetUpImage("scrollbar-arrows-up-normal.png");
+ m_ButtonBackward->SetDownImage("scrollbar-arrows-up-depressed.png");
+ m_ButtonBackward->SetDisabledImage("scrollbar-arrows-up-disabled.png");
+ m_ButtonForward->SetUpImage("scrollbar-arrows-down-normal.png");
+ m_ButtonForward->SetDownImage("scrollbar-arrows-down-depressed.png");
+ m_ButtonForward->SetDisabledImage("scrollbar-arrows-down-disabled.png");
+ } else {
+ // Horizontal buttons
+ SetFlowDirection(FLOW_HORIZONTAL);
+ m_ButtonBackward->SetUpImage("scrollbar-arrows-left-normal.png");
+ m_ButtonBackward->SetDownImage("scrollbar-arrows-left-depressed.png");
+ m_ButtonBackward->SetDisabledImage("scrollbar-arrows-left-disabled.png");
+ m_ButtonForward->SetUpImage("scrollbar-arrows-right-normal.png");
+ m_ButtonForward->SetDownImage("scrollbar-arrows-right-depressed.png");
+ m_ButtonForward->SetDisabledImage("scrollbar-arrows-right-disabled.png");
+ }
+}
+
+//=============================================================================
+/**
+ * Get the orientation of this scroller bar.
+ */
+CScrollerBar::EOrientation CScrollerBar::GetOrientation()
+{
+ return m_Orientation;
+}
+
+//=============================================================================
+/**
+ * Get the minimum size of this scroller bar.
+ * The minumum size is the width or height of both of it's buttons (depending
+ * on orientation.
+ * @return the minimum allowable size of this bar.
+ */
+CPt CScrollerBar::GetMinimumSize()
+{
+ if (GetOrientation() == VERTICAL) {
+ return CPt(DEFAULT_WIDTH, DEFAULT_WIDTH * 2);
+ } else {
+ return CPt(DEFAULT_WIDTH * 2, DEFAULT_WIDTH);
+ }
+}
+
+//=============================================================================
+/**
+ * Set the size of this scroller bar.
+ */
+void CScrollerBar::SetSize(CPt inSize)
+{
+ CFlowLayout::SetSize(inSize);
+
+ RepositionThumb();
+}
+
+//=============================================================================
+/**
+ * Recalculate the size and position of the thumb control.
+ */
+void CScrollerBar::RepositionThumb()
+{
+ long theBarLen;
+
+ if (GetOrientation() == VERTICAL) {
+ float thePercentage =
+ (float)m_Scroller->GetVisibleSize().y / (float)m_Scroller->GetContaineeSize().y;
+ theBarLen = (long)(thePercentage * ((float)m_Background->GetSize().y));
+
+ if (theBarLen < CScrollerThumb::MIN_LENGTH)
+ theBarLen = CScrollerThumb::MIN_LENGTH;
+
+ CPt theSize(GetMinimumSize().x, theBarLen);
+
+ m_ScrollerThumb->SetSize(theSize);
+
+ float theVisPosY = (float)(m_Scroller->GetVisiblePosition().y);
+ float theMaxPosY = (float)(m_Scroller->GetMaxVisiblePosition().y);
+ long thePosY = 0;
+ if (theMaxPosY != 0)
+ thePosY = ::dtol((theVisPosY / theMaxPosY)
+ * (m_Background->GetSize().y - m_ScrollerThumb->GetSize().y));
+
+ m_ScrollerThumb->SetPosition(CPt(0, thePosY));
+ } else {
+ float thePercentage =
+ (float)m_Scroller->GetVisibleSize().x / (float)m_Scroller->GetContaineeSize().x;
+ theBarLen = ::dtol(thePercentage * ((float)m_Background->GetSize().x));
+ if (theBarLen < CScrollerThumb::MIN_LENGTH)
+ theBarLen = CScrollerThumb::MIN_LENGTH;
+
+ CPt theSize(theBarLen, GetMinimumSize().y);
+
+ m_ScrollerThumb->SetSize(theSize);
+
+ float theVisPosX = (float)(m_Scroller->GetVisiblePosition().x);
+ float theMaxPosX = (float)(m_Scroller->GetMaxVisiblePosition().x);
+ long thePosX = 0;
+ if (theMaxPosX != 0)
+ thePosX = ::dtol((theVisPosX / theMaxPosX)
+ * (m_Background->GetSize().x - m_ScrollerThumb->GetSize().x));
+
+ m_ScrollerThumb->SetPosition(CPt(thePosX, 0));
+ }
+
+ Invalidate();
+}
+
+IScroller *CScrollerBar::GetScroller()
+{
+ return m_Scroller;
+};
+
+//=============================================================================
+/**
+ * Called by the ScrollerThumb to reposition itself.
+ * This is used to reposition the thumb, the positions here are used to derive
+ * the position of the visible window, so that this provides absolute positioning
+ * of the thumb.
+ * @param inPosition the new position of the thumb.
+ */
+void CScrollerBar::SetBarPosition(long inPosition)
+{
+ long theAvailableSpace;
+ if (GetOrientation() == HORIZONTAL) {
+ theAvailableSpace = m_Background->GetSize().x - m_ScrollerThumb->GetSize().x;
+ } else {
+ theAvailableSpace = m_Background->GetSize().y - m_ScrollerThumb->GetSize().y;
+ }
+
+ if (inPosition > theAvailableSpace)
+ inPosition = theAvailableSpace;
+ if (inPosition < 0)
+ inPosition = 0;
+
+ CPt theVisPos = m_Scroller->GetVisiblePosition();
+ if (GetOrientation() == HORIZONTAL) {
+ m_ScrollerThumb->SetPosition(CPt(inPosition, 0));
+ double theMaxPosX = (double)(m_Scroller->GetMaxVisiblePosition().x);
+ double theScrollDiff = (double)(m_Background->GetSize().x - m_ScrollerThumb->GetSize().x);
+ theVisPos.x = ::dtol((double)inPosition / theScrollDiff * theMaxPosX);
+ } else {
+ m_ScrollerThumb->SetPosition(CPt(0, inPosition));
+ double theMaxPosY = (double)(m_Scroller->GetMaxVisiblePosition().y);
+ double theScrollDiff = (double)(m_Background->GetSize().y - m_ScrollerThumb->GetSize().y);
+ theVisPos.y = ::dtol((double)inPosition / theScrollDiff * theMaxPosY);
+ }
+ m_Scroller->SetVisiblePosition(theVisPos);
+
+ RepositionThumb();
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Get the current position of the thumb.
+ * @return the current position of the thumb.
+ */
+long CScrollerBar::GetBarPosition()
+{
+ if (GetOrientation() == HORIZONTAL)
+ return m_ScrollerThumb->GetPosition().x;
+ else
+ return m_ScrollerThumb->GetPosition().y;
+}
+
+//=============================================================================
+/**
+ * Get the ScrollerThumb.
+ * @return the scroller thumb.
+ */
+CControl *CScrollerBar::GetThumb()
+{
+ return m_ScrollerThumb;
+}
+
+//=============================================================================
+/**
+ * Get the background of the thumb.
+ * @return the background of the thumb.
+ */
+CControl *CScrollerBar::GetThumbBackground()
+{
+ return m_Background;
+}
diff --git a/src/Authoring/Studio/Controls/ScrollerBar.h b/src/Authoring/Studio/Controls/ScrollerBar.h
new file mode 100644
index 00000000..3a8527ef
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerBar.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SCROLLER_BAR_H
+#define INCLUDED_SCROLLER_BAR_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "Control.h"
+#include "FlowLayout.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+class CScroller;
+class CScrollerBar;
+class CScrollerBackground;
+class CRenderer;
+class CScrollerButtonControl;
+
+class IScroller;
+
+class IScrollerBar
+{
+protected:
+ virtual ~IScrollerBar() {}
+public:
+ enum EOrientation {
+ VERTICAL,
+ HORIZONTAL,
+ };
+ virtual EOrientation GetOrientation() = 0;
+ virtual void RepositionThumb() = 0;
+ virtual IScroller *GetScroller() = 0;
+ virtual void SetBarPosition(long inPosition) = 0;
+ virtual long GetBarPosition() = 0;
+ virtual CControl *GetThumb() = 0;
+};
+
+//=============================================================================
+/**
+ * Class for creating a scrollerbar (contains a CScrollerThumb).
+ */
+class CScrollerBar : public CFlowLayout, public IScrollerBar
+{
+public:
+ static const long DEFAULT_WIDTH;
+ static const ::CColor DEFAULT_COLOR;
+ static const ::CColor SCROLLER_TOP;
+
+ CScrollerBar(CScroller *inScroller, bool inCreateImmediately = true);
+ virtual ~CScrollerBar();
+
+ DEFINE_OBJECT_COUNTER(CScrollerBar)
+
+ void SetOrientation(EOrientation inOrientation);
+ EOrientation GetOrientation() override;
+
+ CPt GetMinimumSize() override;
+
+ void SetScrollerThumbPosition(long inPosition);
+ long GetScrollerThumbPosition();
+
+ void SetSize(CPt inSize) override;
+
+ void SetBarPosition(long inPosition) override;
+ long GetBarPosition() override;
+
+ CControl *GetThumb() override;
+ virtual CControl *GetThumbBackground();
+ void RepositionThumb() override;
+ IScroller *GetScroller() override;
+
+protected:
+ virtual CControl *CreateThumb();
+ void Initialize();
+ Q3DStudio::CAutoMemPtr<CScrollerButtonControl> m_ButtonBackward;
+ Q3DStudio::CAutoMemPtr<CScrollerButtonControl> m_ButtonForward;
+ Q3DStudio::CAutoMemPtr<CControl> m_ScrollerThumb;
+ Q3DStudio::CAutoMemPtr<CScrollerBackground> m_Background;
+
+ EOrientation m_Orientation;
+ CScroller *m_Scroller;
+};
+
+#endif // INCLUDED_SCROLLER_BAR_H
diff --git a/src/Authoring/Studio/Controls/ScrollerButtonControl.cpp b/src/Authoring/Studio/Controls/ScrollerButtonControl.cpp
new file mode 100644
index 00000000..a04b8ff8
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerButtonControl.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ScrollerButtonControl.h"
+#include "Scroller.h"
+
+//=============================================================================
+/**
+ * Constructor
+ *
+ * @param inToggleButton true if this is suppose to be a toggle button. Toggle
+ * buttons stay pressed when clicked on and have to be clicked again in order
+ * to release. Normal buttons return to the up state when the button is released.
+ */
+CScrollerButtonControl::CScrollerButtonControl(IScrollerBar *inScrollerBar, EDirection inDirection)
+ : m_Direction(inDirection)
+{
+ SetAbsoluteSize(CPt(CScrollerBar::DEFAULT_WIDTH, CScrollerBar::DEFAULT_WIDTH));
+ SetScrollerBar(inScrollerBar);
+ m_Control = this;
+
+ Initialize();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CScrollerButtonControl::~CScrollerButtonControl()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+void CScrollerButtonControl::Initialize() {
+ // Add the button down listeners
+ if (m_Direction == FORWARD) {
+ SigButtonDown.connect(std::bind(&CScrollerButtonControl::OnScrollForward,
+ static_cast<CScrollController *>(this), std::placeholders::_1));
+ } else {
+ SigButtonDown.connect(std::bind(&CScrollerButtonControl::OnScrollBackward,
+ static_cast<CScrollController *>(this), std::placeholders::_1));
+ }
+ SigClicked.connect(std::bind(&CScrollerButtonControl::OnCancelScrolling,
+ static_cast<CScrollController *>(this), std::placeholders::_1));
+}
+
+//=============================================================================
+/**
+ * Handles mouse up on the button.
+ */
+void CScrollerButtonControl::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CButtonControl::OnMouseUp(inPoint, inFlags);
+
+ // If the mouse is not over this button, the base class will not fire an up event.
+ // However, we want to fire this event anyway so that the timer stops (otherwise,
+ // the next time you move your mouse over the button, it will start scrolling again).
+ if (!IsMouseOver())
+ SigButtonUp(this);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/ScrollerButtonControl.h b/src/Authoring/Studio/Controls/ScrollerButtonControl.h
new file mode 100644
index 00000000..a7763d8b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerButtonControl.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_SCROLLER_BUTTON_CONTROL_H
+#define INCLUDED_SCROLLER_BUTTON_CONTROL_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "ButtonControl.h"
+#include "ScrollerBar.h"
+#include "ScrollController.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//=============================================================================
+/**
+ * Subclassed button control that controls the scroller
+ */
+class CScrollerButtonControl : public CButtonControl, public CScrollController
+{
+public:
+ enum EDirection {
+ FORWARD,
+ BACKWARD,
+ };
+
+protected:
+ EDirection m_Direction;
+
+public:
+ CScrollerButtonControl(IScrollerBar *inScrollerBar, EDirection inDirection);
+ virtual ~CScrollerButtonControl();
+
+ virtual void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+
+ EDirection GetDirection() { return m_Direction; };
+
+protected:
+ void Initialize();
+};
+
+#endif // INCLUDED_SCROLLER_BUTTON_CONTROL_H
diff --git a/src/Authoring/Studio/Controls/ScrollerThumb.cpp b/src/Authoring/Studio/Controls/ScrollerThumb.cpp
new file mode 100644
index 00000000..a7fedbca
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerThumb.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ScrollerThumb.h"
+#include "ScrollerBar.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+
+//==============================================================================
+// Static variables
+//==============================================================================
+const long CScrollerThumb::MIN_LENGTH = 32;
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inScrollerBar the scroller bar this is operating on.
+ */
+CScrollerThumb::CScrollerThumb(IScrollerBar *inScrollerBar)
+ : m_MouseDown(false)
+{
+ m_ScrollerBar = inScrollerBar;
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CScrollerThumb::~CScrollerThumb()
+{
+}
+
+//=============================================================================
+/**
+ * Draw this scroller bar.
+ * @param inRenderer the renderer this is to draw to.
+ */
+void CScrollerThumb::Draw(CRenderer *inRenderer)
+{
+ if (IsEnabled()) {
+ CPt theSize = GetSize();
+ CRct theRect(theSize);
+
+ // Draw the thumb
+ inRenderer->FillSolidRect(theRect, CStudioPreferences::GetScrollThumbBGColor());
+ // Draw the highlight
+ inRenderer->Draw3dRect(CRct(theRect.position.x + 1, theRect.position.y + 1,
+ theRect.size.x - 1, theRect.size.y - 1),
+ CStudioPreferences::GetScrollThumbHighlightColor(),
+ CStudioPreferences::GetScrollThumbBGColor());
+ // Draw the black border
+ inRenderer->Draw3dRect(theRect, CStudioPreferences::GetScrollThumbShadowColor(),
+ CStudioPreferences::GetScrollThumbShadowColor());
+
+ // Draw the 3 lines in the middle of the control, depending on orientation
+ if (m_ScrollerBar->GetOrientation() == CScrollerBar::VERTICAL) {
+ // Draw the light lines
+ inRenderer->PushPen(CStudioPreferences::GetScrollThumbGripHighlightColor());
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 3, theSize.y / 2 - 5));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 2, theSize.y / 2 - 5));
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 3, theSize.y / 2 - 2));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 2, theSize.y / 2 - 2));
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 3, theSize.y / 2 + 1));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 2, theSize.y / 2 + 1));
+ inRenderer->PopPen();
+ // Draw the dark lines
+ inRenderer->PushPen(CStudioPreferences::GetScrollThumbGripShadowColor());
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 2, theSize.y / 2 - 4));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 3, theSize.y / 2 - 4));
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 2, theSize.y / 2 - 1));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 3, theSize.y / 2 - 1));
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 2, theSize.y / 2 + 2));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 3, theSize.y / 2 + 2));
+ inRenderer->PopPen();
+ } else {
+ // Draw the light lines
+ inRenderer->PushPen(CStudioPreferences::GetScrollThumbGripHighlightColor());
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 4, theSize.y / 2 - 3));
+ inRenderer->LineTo(CPt(theSize.x / 2 - 4, theSize.y / 2 + 2));
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 1, theSize.y / 2 - 3));
+ inRenderer->LineTo(CPt(theSize.x / 2 - 1, theSize.y / 2 + 2));
+ inRenderer->MoveTo(CPt(theSize.x / 2 + 2, theSize.y / 2 - 3));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 2, theSize.y / 2 + 2));
+ inRenderer->PopPen();
+
+ // Draw the dark lines
+ inRenderer->PushPen(CStudioPreferences::GetScrollThumbGripShadowColor());
+ inRenderer->MoveTo(CPt(theSize.x / 2 - 3, theSize.y / 2 - 2));
+ inRenderer->LineTo(CPt(theSize.x / 2 - 3, theSize.y / 2 + 3));
+ inRenderer->MoveTo(CPt(theSize.x / 2, theSize.y / 2 - 2));
+ inRenderer->LineTo(CPt(theSize.x / 2, theSize.y / 2 + 3));
+ inRenderer->MoveTo(CPt(theSize.x / 2 + 3, theSize.y / 2 - 2));
+ inRenderer->LineTo(CPt(theSize.x / 2 + 3, theSize.y / 2 + 3));
+ inRenderer->PopPen();
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Listener for the OnMouseDown to allow dragging.
+ * Begins dragging of the control.
+ */
+bool CScrollerThumb::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_MouseDown = true;
+ m_MouseDownPoint = inPoint;
+
+ Invalidate();
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Ends dragging of the control.
+ */
+void CScrollerThumb::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+ m_MouseDown = false;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Used for dragging the control.
+ */
+void CScrollerThumb::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ // Only care if the mouse is down.
+ if (m_MouseDown) {
+ long theBarPos = m_ScrollerBar->GetBarPosition();
+
+ // Adjust the position based on which way we are being dragged.
+ if (m_ScrollerBar->GetOrientation() == CScrollerBar::VERTICAL) {
+ theBarPos += inPoint.y - m_MouseDownPoint.y;
+ } else {
+ theBarPos += inPoint.x - m_MouseDownPoint.x;
+ }
+
+ // Update the position.
+ m_ScrollerBar->SetBarPosition(theBarPos);
+ }
+}
+
+//=============================================================================
+/**
+ * Get the minimum size that this scroller thumb is allowed to be.
+ * @return the minimum size that this scroller thumb is allowed to be.
+ */
+CPt CScrollerThumb::GetMinimumSize()
+{
+ if (m_ScrollerBar->GetOrientation() == CScrollerBar::HORIZONTAL)
+ return CPt(MIN_LENGTH, 0);
+ else
+ return CPt(0, MIN_LENGTH);
+}
diff --git a/src/Authoring/Studio/Controls/ScrollerThumb.h b/src/Authoring/Studio/Controls/ScrollerThumb.h
new file mode 100644
index 00000000..c699c910
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ScrollerThumb.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SCROLLER_THUMB_H
+#define INCLUDED_SCROLLER_THUMB_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "FlowLayout.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IScrollerBar;
+class CRenderer;
+
+//=============================================================================
+/**
+ * Class for creating the thumb portion of a scroller.
+ */
+class CScrollerThumb : public CControl
+{
+public:
+ static const long MIN_LENGTH;
+
+ CScrollerThumb(IScrollerBar *inScroller);
+ virtual ~CScrollerThumb();
+
+ virtual void Draw(CRenderer *inRenderer);
+
+ virtual bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags);
+
+ virtual CPt GetMinimumSize();
+
+protected:
+ IScrollerBar *m_ScrollerBar;
+ bool m_MouseDown;
+ CPt m_MouseDownPoint;
+};
+
+#endif // INCLUDED_SCROLLER_THUMB_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/SplashControl.cpp b/src/Authoring/Studio/Controls/SplashControl.cpp
new file mode 100644
index 00000000..ea23f168
--- /dev/null
+++ b/src/Authoring/Studio/Controls/SplashControl.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SplashControl.h"
+#include "Renderer.h"
+#include "ResourceCache.h"
+#include "StudioPreferences.h"
+#include "OffscreenRenderer.h"
+#include "StringLoader.h"
+#include "StudioDefs.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CSplashControl::CSplashControl()
+{
+ // Image
+ m_Image = CResourceCache::GetInstance()->GetBitmap("obsolete_placeholder.png");
+ SetAbsoluteSize(m_Image.rect().bottomRight());
+
+ // First line of the copyright statement
+ m_CopyrightLine1.Format(
+ ::LoadResourceString(IDS_SPLASH_COPYRIGHT1),
+ static_cast<const wchar_t *>(Q3DStudio::CString(STUDIO_COPYRIGHT_YEAR)));
+
+ // Second line of the copyright statement
+ m_CopyrightLine2 = ::LoadResourceString(IDS_SPLASH_COPYRIGHT2);
+
+ // Version text
+ m_VersionInfo.Format((::LoadResourceString(IDS_UIC_STUDIO_VERSION)),
+ static_cast<const wchar_t *>(CStudioPreferences::GetVersionString()));
+
+ // Calculate the number of pixels between each line of text
+ COffscreenRenderer theOffscreenRenderer(CRct(0, 0, 1, 1));
+ auto size = theOffscreenRenderer.GetTextSize(m_CopyrightLine1.toQString());
+ m_SpaceBetweenLines = size.height();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSplashControl::~CSplashControl()
+{
+}
+
+//=============================================================================
+/**
+ * Draws the splash screen.
+ * @param inRenderer Renderer to draw to
+ */
+void CSplashControl::Draw(CRenderer *inRenderer)
+{
+ CRct theBounds(GetSize());
+ CColor theTextColor(50, 50, 50);
+ long theVertOffset = GetSize().y / 2 - 14; ///< Last line of the copyright starts here
+
+ // Splash screen bitmap
+ inRenderer->DrawBitmap(CPt(0, 0), m_Image);
+
+ // Print the copyright text, starting at the last line and going up to the first line (just to
+ // make sure that we didn't move where the text ends)
+ inRenderer->DrawText(14, static_cast<float>(theVertOffset), m_VersionInfo.toQString(), theBounds,
+ theTextColor);
+ theVertOffset -= m_SpaceBetweenLines;
+ inRenderer->DrawText(14, static_cast<float>(theVertOffset), m_CopyrightLine2.toQString(), theBounds,
+ theTextColor);
+ theVertOffset -= m_SpaceBetweenLines;
+ inRenderer->DrawText(14, static_cast<float>(theVertOffset), m_CopyrightLine1.toQString(), theBounds,
+ theTextColor);
+}
diff --git a/src/Authoring/Studio/Controls/SplashControl.h b/src/Authoring/Studio/Controls/SplashControl.h
new file mode 100644
index 00000000..dbce104c
--- /dev/null
+++ b/src/Authoring/Studio/Controls/SplashControl.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SPLASH_CONTROL_H
+#define INCLUDED_SPLASH_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+
+
+#include <QPixmap>
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//=============================================================================
+/**
+ * Class responsible for drawing contents of a splash screen at program start-up.
+ */
+class CSplashControl : public CControl
+{
+public:
+ CSplashControl();
+ virtual ~CSplashControl();
+
+ void Draw(CRenderer *inRenderer) override;
+
+protected:
+ QPixmap m_Image;
+ Q3DStudio::CString m_CopyrightLine1;
+ Q3DStudio::CString m_CopyrightLine2;
+ Q3DStudio::CString m_VersionInfo;
+ long m_SpaceBetweenLines; ///< number of pixels between subsequent lines of the copyright
+ ///statement (calculated automatically)
+};
+
+#endif // INCLUDED_SPLASH_CONTROL_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/SplitBar.cpp b/src/Authoring/Studio/Controls/SplitBar.cpp
new file mode 100644
index 00000000..b37f60e9
--- /dev/null
+++ b/src/Authoring/Studio/Controls/SplitBar.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "SplitBar.h"
+#include "Renderer.h"
+#include "ResourceCache.h"
+#include "MouseCursor.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+
+#include <QApplication>
+//=============================================================================
+// Static Variables
+//=============================================================================
+const long CSplitBar::DEFAULT_WIDTH = 5;
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CSplitBar::CSplitBar(CSplitterBase *inSplitter, const long inWidth /*=DEFAULT_WIDTH*/)
+ : m_Splitter(inSplitter)
+ , m_Width(inWidth)
+ , m_MouseDown(false)
+{
+
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSplitBar::~CSplitBar()
+{
+}
+
+//=============================================================================
+/**
+ * Handles mouse down events, starts the dragging.
+ * @param inPoint where the mouse was clicked.
+ * @param inFlags the state of the mouse.
+ */
+bool CSplitBar::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseDown(inPoint, inFlags);
+
+ m_MouseDown = true;
+ m_MouseDownPoint = inPoint;
+
+ Invalidate();
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handles mouse up events, stops the dragging.
+ * @param inPoint where the mouse was let up.
+ * @param inFlags the state of the mouse.
+ */
+void CSplitBar::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ m_MouseDown = false;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Do the drawing of this splitter.
+ * @param inRenderer the renderer to draw to.
+ */
+void CSplitBar::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(CPt(0, 0), GetSize());
+ CRct theHighlightRect;
+ CRct theShadowRect;
+
+ if (m_Splitter->GetSplitDirection() == CSplitterBase::SPLIT_HORIZONTAL) {
+ theHighlightRect.position = CPt(0, 0);
+ theHighlightRect.size = CPt(GetSize().x, 1);
+ theShadowRect.position = CPt(0, theRect.size.y - 1);
+ theShadowRect.size = CPt(theRect.size.x, 1);
+ } else {
+ theHighlightRect.position = CPt(0, 0);
+ theHighlightRect.size = CPt(1, GetSize().y);
+ theShadowRect.position = CPt(theRect.size.x - 1, 0);
+ theShadowRect.size = CPt(1, theRect.size.y);
+ }
+
+ inRenderer->FillSolidRect(theRect, CStudioPreferences::GetBaseColor());
+ inRenderer->FillSolidRect(theHighlightRect, CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->FillSolidRect(theShadowRect, CStudioPreferences::GetButtonShadowColor());
+}
+
+//=============================================================================
+/**
+ * Get the width of this splitter bar.
+ */
+long CSplitBar::GetWidth()
+{
+ return m_Width;
+}
+
+//=============================================================================
+/**
+ * Set the width of this splitter bar.
+ */
+void CSplitBar::SetWidth(long inWidth)
+{
+ m_Width = inWidth;
+}
+
+//=============================================================================
+/**
+ * Processes the dragging of the split bar.
+ * @param inPoint the position of the mouse.
+ * @param inFlags the state of the mouse buttons.
+ */
+void CSplitBar::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ const Qt::MouseButtons buttons = QApplication::mouseButtons();
+
+ // Don't show the cursor if the mouse is down from someone else.
+ if (!(buttons & Qt::LeftButton) && !(buttons & Qt::RightButton)) {
+ // If the buttons are not down and the mouse is over this control
+ if (HitTest(inPoint + GetPosition())) {
+ // Show the appropriate resize cursor
+ setCursorIfNotSet(m_Splitter->GetSplitDirection() == CSplitterBase::SPLIT_HORIZONTAL
+ ? CMouseCursor::CURSOR_RESIZE_UPDOWN
+ : CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
+ } else {
+ resetCursor();
+ }
+ }
+
+ // Only care if the mouse is down
+ if (m_MouseDown) {
+ // When calculating the offsets remember that this object is moving with the mouse
+ // and the inPoint is relative to this position, so inPoint's relative position is
+ // changing on every drag.
+ long theSplitPos = m_Splitter->GetSplitLocation();
+
+ if (m_Splitter->GetSplitDirection() == CSplitterBase::SPLIT_HORIZONTAL) {
+ theSplitPos += inPoint.y - m_MouseDownPoint.y;
+ } else {
+ theSplitPos += inPoint.x - m_MouseDownPoint.x;
+ }
+
+ m_Splitter->SetSplitLocation(theSplitPos);
+ }
+}
+
+//=============================================================================
+/**
+ * Processes the mouse out event. Changes the cursor if necessary back to normal.
+ * @param inPoint the position of the mouse.
+ * @param inFlags the state of the mouse buttons.
+ */
+void CSplitBar::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ const Qt::MouseButtons buttons = QApplication::mouseButtons();
+ // Don't change the cursor if the mouse is down (from someone else or from ourselves)
+ if (!m_MouseDown && !(buttons & Qt::LeftButton) && !(buttons & Qt::RightButton))
+ resetCursor();
+ CControl::OnMouseOut(inPoint, inFlags);
+}
diff --git a/src/Authoring/Studio/Controls/SplitBar.h b/src/Authoring/Studio/Controls/SplitBar.h
new file mode 100644
index 00000000..f70b4469
--- /dev/null
+++ b/src/Authoring/Studio/Controls/SplitBar.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef INCLUDED_SPLIT_BAR_H
+#define INCLUDED_SPLIT_BAR_H 1
+
+#pragma once
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "Control.h"
+
+#include <QCursor>
+
+//=============================================================================
+// Forwards
+//=============================================================================
+
+//=============================================================================
+/**
+ * Abstract class for implementing a splitter control
+ */
+class CSplitterBase
+{
+public:
+ enum ESplitDirection {
+ SPLIT_VERTICAL,
+ SPLIT_HORIZONTAL,
+ };
+
+ virtual void SetSplitLocation(long inPixels) = 0;
+ virtual long GetSplitLocation() const = 0;
+ virtual ESplitDirection GetSplitDirection() const = 0;
+};
+
+//=============================================================================
+/**
+ * Defines the bar used in a splitter control. Handles drawing and cursors for
+ * the bar.
+ */
+class CSplitBar : public CControl
+{
+public:
+ static const long DEFAULT_WIDTH;
+
+ CSplitBar(CSplitterBase *inSplitter, long inWidth = DEFAULT_WIDTH);
+ virtual ~CSplitBar();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void Draw(CRenderer *inRenderer) override;
+
+ virtual long GetWidth();
+ virtual void SetWidth(long inWidth);
+
+protected:
+ CSplitterBase *m_Splitter;
+ long m_Width;
+
+ bool m_MouseDown;
+ CPt m_MouseDownPoint;
+};
+
+#endif // INCLUDED_SPLIT_BAR_H
diff --git a/src/Authoring/Studio/Controls/Splitter.cpp b/src/Authoring/Studio/Controls/Splitter.cpp
new file mode 100644
index 00000000..b0ae0eb0
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Splitter.cpp
@@ -0,0 +1,419 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "Splitter.h"
+#include "ControlData.h"
+
+using namespace Q3DStudio;
+using namespace Q3DStudio::Control;
+//=============================================================================
+/**
+ * Constructor, creates a Splitter.
+ */
+CSplitter::CSplitter()
+ : m_SplitDirection(SPLIT_VERTICAL)
+ , m_SplitLocation(0)
+ , m_InRecalcLayoutFlag(false)
+{
+ m_SplitMinMargin = 10;
+ m_SplitMaxMargin = 10;
+ m_SplitBar = new CSplitBar(this);
+ AddChild(m_SplitBar);
+}
+
+CSplitter::~CSplitter()
+{
+ RemoveChild(m_SplitBar);
+ delete m_SplitBar;
+}
+
+//=============================================================================
+/**
+ * Set the size of this splitter.
+ * @param inSize the size of this splitter.
+ */
+void CSplitter::SetSize(CPt inSize)
+{
+ if (inSize != GetSize()) {
+ CControl::SetSize(inSize);
+
+ RecalcLayout();
+ }
+}
+
+void CSplitter::SetLayout(CPt inSize, CPt inPosition)
+{
+ CControl::SetLayout(inSize, inPosition);
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Get the preferred size of this splitter.
+ * The preferred size is the sum of both the panes.
+ * @return the preferred size of this splitter.
+ */
+CPt CSplitter::GetPreferredSize()
+{
+ CPt theSize = CControl::GetPreferredSize();
+
+ if (m_SplitDirection == SPLIT_VERTICAL) {
+ theSize.x = m_SplitBar->GetWidth();
+
+ // If vertical then sum up x's
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ CPt thePrefSize = (*thePos)->GetPreferredSize();
+ theSize.x += thePrefSize.x;
+ }
+ } else {
+ theSize.y = m_SplitBar->GetWidth();
+
+ // If horizontal then sum up y's
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ CPt thePrefSize = (*thePos)->GetPreferredSize();
+ theSize.y += thePrefSize.y;
+ }
+ }
+
+ return theSize;
+}
+
+//=============================================================================
+/**
+ * Get the minimum allowable size of this splitter.
+ * The minimum size is the sum of both the minimum sizes in the split direciton
+ * and the largest minimum in the non-split direction.
+ * @return the minimum size of this control.
+ */
+CPt CSplitter::GetMinimumSize()
+{
+ CPt theSize(0, 0);
+
+ if (m_SplitDirection == SPLIT_VERTICAL) {
+ theSize.x += m_SplitBar->GetWidth();
+
+ // Sum up in the split direction and take max min size in non-split direction
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ CPt theMinSize = (*thePos)->GetMinimumSize();
+ theSize.x += theMinSize.x;
+
+ if (theSize.y < theMinSize.y) {
+ theSize.y = theMinSize.y;
+ }
+ }
+ } else {
+ theSize.y += m_SplitBar->GetWidth();
+
+ // Sum up in the split direction and take max min size in non-split direction.
+ ControlGraph::SIterator thePos = GetChildren();
+ for (; thePos.HasNext(); ++thePos) {
+ CPt theMinSize = (*thePos)->GetMinimumSize();
+ theSize.y += theMinSize.y;
+
+ if (theSize.x > theMinSize.x) {
+ theSize.x = theMinSize.x;
+ }
+ }
+ }
+
+ return theSize;
+}
+
+//=============================================================================
+/**
+ * Get the maximum size that this control should be.
+ * The maximum size is the sum of both the maximum sizes in the split direction
+ * and the smalled maximum size in the non-split direction.
+ * @return the maximum size of this control.
+ */
+CPt CSplitter::GetMaximumSize()
+{
+ CPt theSize(0, 0);
+
+ if (m_SplitDirection == SPLIT_VERTICAL) {
+ theSize.x += m_SplitBar->GetWidth();
+ theSize.y = LONG_MAX;
+
+ // Sum up the split direction and take min max size in non-split direction.
+ ControlGraph::SIterator thePos = GetChildren();
+ // Skip the separator
+ ++thePos;
+ for (; thePos.HasNext(); ++thePos) {
+ CPt theMaxSize = (*thePos)->GetMaximumSize();
+ theSize.x += theMaxSize.x;
+
+ if (theSize.y > theMaxSize.y) {
+ theSize.y = theMaxSize.y;
+ }
+ }
+ } else {
+ theSize.y += m_SplitBar->GetWidth();
+ theSize.x = LONG_MAX;
+
+ // Sum up the split direction and take min max size in the non-split direction.
+ ControlGraph::SIterator thePos = GetChildren();
+ // Skip the separator.
+ ++thePos;
+ for (; thePos.HasNext(); ++thePos) {
+ CPt theMaxSize = (*thePos)->GetMaximumSize();
+ theSize.y += theMaxSize.y;
+
+ if (theSize.x > theMaxSize.x) {
+ theSize.x = theMaxSize.x;
+ }
+ }
+ }
+
+ return theSize;
+}
+
+//=============================================================================
+/**
+ * Set the location of the splitter bar.
+ * @param inSplitLocation the location of the splitter bar, in pixels from the right/top.
+ */
+void CSplitter::SetSplitLocation(long inSplitLocation)
+{
+ ControlGraph::SIterator theChildren = GetChildren();
+
+ std::shared_ptr<CControlData> theControl1;
+ std::shared_ptr<CControlData> theControl2;
+ ++theChildren;
+ if (theChildren.HasNext()) {
+ theControl1 = *theChildren;
+
+ ++theChildren;
+ if (theChildren.HasNext()) {
+ theControl2 = *theChildren;
+ }
+ }
+ if (m_SplitDirection == SPLIT_VERTICAL && theControl1) {
+ CPt theControl1Min = theControl1->GetMinimumSize();
+ if (theControl1Min.x > inSplitLocation)
+ inSplitLocation = theControl1Min.x;
+ } else if (theControl2) {
+ CPt theControl1Min = theControl1->GetMinimumSize();
+ if (theControl1Min.y > inSplitLocation && theControl2)
+ inSplitLocation = theControl1Min.y;
+ }
+ m_SplitLocation = inSplitLocation;
+
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Get the location of the splitter bar.
+ * @return the location of the splitter bar, in pixels from the right/top.
+ */
+long CSplitter::GetSplitLocation() const
+{
+ long theSplitLocation = m_SplitLocation;
+
+ // Enforce the max margin and then the min margin (in that order)
+ // this is done on the get so that internally we maintain
+ // the correct location of the splitter
+ if (m_SplitDirection == SPLIT_VERTICAL) {
+ if (m_SplitLocation > GetSize().x - m_SplitMaxMargin /*- m_SplitBar->GetWidth( )*/)
+ theSplitLocation = GetSize().x - m_SplitMaxMargin /*- m_SplitBar->GetWidth( )*/;
+ } else {
+ if (m_SplitLocation > GetSize().y - m_SplitMaxMargin)
+ theSplitLocation = GetSize().y - m_SplitMaxMargin;
+ }
+
+ if (m_SplitLocation < m_SplitMinMargin)
+ theSplitLocation = m_SplitMinMargin;
+
+ return theSplitLocation;
+}
+
+//=============================================================================
+/**
+ * Set the minimum and maximum split location. This will limit the splitter
+ * left and right or up and down.
+ * @param inSplitMinMargin the number of pixels from the left/top of the pane
+ * @param inSplitMaxMargin the number of pixels from the right/bottom of the pane.
+ */
+void CSplitter::SetSplitLimits(long inSplitMinMargin, long inSplitMaxMargin)
+{
+ m_SplitMinMargin = inSplitMinMargin;
+ m_SplitMaxMargin = inSplitMaxMargin;
+}
+
+//=============================================================================
+/**
+ * Set the direction that this is being split in.
+ * @param inSplitDirection the direction that this is being split in.
+ */
+void CSplitter::SetSplitDirection(CSplitterBase::ESplitDirection inSplitDirection)
+{
+ m_SplitDirection = inSplitDirection;
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Get the direction that this is being split in.
+ * @return the direction that this is being split in.
+ */
+CSplitterBase::ESplitDirection CSplitter::GetSplitDirection() const
+{
+ return m_SplitDirection;
+}
+
+//=============================================================================
+/**
+ * Add a child to this splitter.
+ * If more than 2 children are added then this will pop off the last one to be
+ * added before inControl.
+ * @param inControl the control to add to this.
+ * @param inInsertAfter the position to inster the control.
+ */
+void CSplitter::AddChild(CControl *inControl, CControl *inInsertAfter /*=nullptr*/)
+{
+ CControl::AddChild(inControl, inInsertAfter);
+
+ // If there are more than 3 objects then ditch the last one, allows the insert after to still
+ // work.
+ if (GetChildCount() > 3)
+ RemoveChild(GetReverseChildren().GetCurrent()->GetControl());
+
+ RecalcLayout();
+}
+
+void CSplitter::RecalcLayout()
+{
+ CPt thePoint(0, 0);
+ CPt theSize = GetSize();
+
+ std::shared_ptr<CControlData> theControl1;
+ std::shared_ptr<CControlData> theControl2;
+
+ long theSplitLocation = GetSplitLocation();
+
+ ControlGraph::SIterator theChildren = GetChildren();
+ ++theChildren;
+ if (theChildren.HasNext()) {
+ theControl1 = *theChildren;
+
+ ++theChildren;
+ if (theChildren.HasNext()) {
+ theControl2 = *theChildren;
+ }
+ }
+
+ // Prevent OnChildSizeChanged from screwing with us
+ m_InRecalcLayoutFlag = true;
+
+ if (theControl2 != nullptr) {
+ CPt theControl1Max = theControl1->GetMaximumSize();
+ CPt theControl2Max = theControl2->GetMaximumSize();
+
+ if (m_SplitDirection == SPLIT_VERTICAL) {
+ CPt theControl1Min = theControl1->GetMinimumSize();
+ if (theControl1Min.x > theSplitLocation) {
+ theSplitLocation = theControl1Min.x;
+ }
+ theControl1->SetPosition(CPt(0, 0));
+ theControl1->SetSize(CPt(theSplitLocation, min(theSize.y, theControl1Max.y)));
+
+ m_SplitBar->SetPosition(CPt(theSplitLocation, 0));
+ m_SplitBar->SetSize(CPt(m_SplitBar->GetWidth(), theSize.y));
+
+ theControl2->SetPosition(CPt(theSplitLocation + m_SplitBar->GetWidth(), 0));
+ theControl2->SetSize(CPt(theSize.x - (theSplitLocation + m_SplitBar->GetWidth()),
+ min(theSize.y, theControl2Max.y)));
+ } else {
+ CPt theControl1Min = theControl1->GetMinimumSize();
+ if (theControl1Min.y > theSplitLocation) {
+ theSplitLocation = theControl1Min.y;
+ }
+ theControl1->SetPosition(CPt(0, 0));
+ theControl1->SetSize(CPt(min(theSize.x, theControl1Max.x), theSplitLocation));
+
+ m_SplitBar->SetPosition(CPt(0, theSplitLocation));
+ m_SplitBar->SetSize(CPt(theSize.x, m_SplitBar->GetWidth()));
+
+ theControl2->SetPosition(CPt(0, theSplitLocation + m_SplitBar->GetWidth()));
+ theControl2->SetSize(CPt(min(theSize.x, theControl2Max.x),
+ theSize.y - (theSplitLocation + m_SplitBar->GetWidth())));
+ }
+ }
+
+ m_InRecalcLayoutFlag = false;
+
+ Invalidate();
+}
+
+void CSplitter::OnChildSizeChanged(CControl *)
+{
+ if (m_InRecalcLayoutFlag == false) {
+ std::shared_ptr<CControlData> theControl1;
+ std::shared_ptr<CControlData> theControl2;
+
+ ControlGraph::SIterator theChildren = GetChildren();
+ ++theChildren;
+ if (theChildren.HasNext()) {
+ theControl1 = *theChildren;
+
+ ++theChildren;
+ if (theChildren.HasNext()) {
+ theControl2 = *theChildren;
+ }
+ }
+
+ CPt theSize = GetSize();
+ if (theControl2 != nullptr) {
+ CPt theSize1 = theControl1->GetSize();
+ CPt theSize2 = theControl2->GetSize();
+ if (m_SplitDirection == SPLIT_VERTICAL)
+ theSize.y = max(theSize1.y, theSize2.y);
+ else
+ theSize.x = max(theSize1.x, theSize2.x);
+ }
+
+ SetSize(theSize);
+ SetMaximumSize(theSize);
+
+ RecalcLayout();
+ }
+
+ // Notify the folks
+ if (GetParent() != nullptr)
+ GetParent()->OnChildSizeChanged(this);
+}
+
+void CSplitter::SetSplitBarWidth(const long inWidth)
+{
+ m_SplitBar->SetWidth(inWidth);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/Splitter.h b/src/Authoring/Studio/Controls/Splitter.h
new file mode 100644
index 00000000..94c70781
--- /dev/null
+++ b/src/Authoring/Studio/Controls/Splitter.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SPLIT_AGENT_H
+#define INCLUDED_SPLIT_AGENT_H 1
+
+#pragma once
+
+#include "SplitBar.h"
+
+class CSplitter : public CControl, public CSplitterBase
+{
+public:
+ CSplitter();
+ virtual ~CSplitter();
+
+ virtual void SetSize(CPt inSize);
+ virtual void SetLayout(CPt inSize, CPt inPosition);
+ virtual CPt GetPreferredSize();
+ virtual CPt GetMinimumSize();
+ virtual CPt GetMaximumSize();
+
+ // CSplitterBase
+ virtual void SetSplitLocation(long inPixels);
+ virtual long GetSplitLocation() const;
+ virtual ESplitDirection GetSplitDirection() const;
+
+ virtual void SetSplitLimits(long inSplitMinMargin, long inSplitMaxMargin);
+ virtual void SetSplitDirection(CSplitterBase::ESplitDirection inSplitDirection);
+
+ virtual void AddChild(CControl *inControl, CControl *inInsertBefore = nullptr);
+
+ virtual void OnChildSizeChanged(CControl *inChild);
+
+ virtual void SetSplitBarWidth(const long inWidth);
+
+protected:
+ void RecalcLayout();
+
+ ESplitDirection m_SplitDirection;
+ long m_SplitLocation;
+ long m_SplitMinMargin;
+ long m_SplitMaxMargin;
+ CSplitBar *m_SplitBar;
+ bool m_InRecalcLayoutFlag;
+};
+
+#endif // INCLUDED_SPLIT_AGENT_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Controls/StringEdit.cpp b/src/Authoring/Studio/Controls/StringEdit.cpp
new file mode 100644
index 00000000..34b5f521
--- /dev/null
+++ b/src/Authoring/Studio/Controls/StringEdit.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "StringEdit.h"
+#include "OffscreenRenderer.h"
+#include "CoreUtils.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CStringEdit::CStringEdit()
+ : m_AutoSize(false)
+{
+ // StringEdit is going to have to handle its own RevertText.
+ // This can't be done in TextEdit because FloatEdit ( VectorEdit, etc ) are using the command
+ // stack for undo/redo
+ // StringEdit doesn't have command stack set until you hit enter or lose focus.
+ // We can't make CTextEdit::RegisterCommands a virtual function since its being called in the
+ // constructor,
+ // therefore this is a pretty lame way to register for a hotkey.
+ m_CommandHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStringEdit>(this, &CStringEdit::RevertText),
+ Qt::ControlModifier, Qt::Key_Z);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CStringEdit::~CStringEdit()
+{
+}
+
+//==============================================================================
+/**
+ * Returns the string value of the control.
+ */
+Q3DStudio::CString CStringEdit::GetString()
+{
+ return m_Value;
+}
+
+//==============================================================================
+/**
+ * Sets the string value of the control.
+ */
+void CStringEdit::SetData(const Q3DStudio::CString &inValue, bool inFireEvent /*= true*/)
+{
+ if (m_Value != inValue) {
+ m_Value = inValue;
+ SetDisplayString(inValue, inFireEvent);
+
+ if (inFireEvent)
+ SetDirty(true);
+ }
+}
+
+//==============================================================================
+/**
+ * Commits changes to the value of this control when the control loses focus.
+ */
+void CStringEdit::OnLoseFocus()
+{
+ CTextEdit::OnLoseFocus();
+ FireCommitEvent();
+}
+
+//==============================================================================
+/**
+ * Commits changes to the value of this control when the Enter button is pressed.
+ * @param inHighlight true to highlight the text after committing it
+ */
+void CStringEdit::EnterText(bool inHighlight)
+{
+ CTextEdit::EnterText(inHighlight);
+ FireCommitEvent();
+}
+
+void CStringEdit::RefreshDisplayFromData()
+{
+ SetDisplayString(GetString());
+ Invalidate();
+}
+
+bool CStringEdit::CanPaste()
+{
+ return true;
+}
+
+//==============================================================================
+/**
+ * Enables or disables auto-sizing of this control. If auto-sizing is enabled
+ * the size of this control will be automatically set to fit the text that it
+ * contains.
+ * @param inAllow true to enable auto-sizing, false to disable auto-sizing
+ */
+void CStringEdit::AllowAutoSize(bool inAllow)
+{
+ m_AutoSize = inAllow;
+}
+
+//==============================================================================
+/**
+ * @return true if auto-resizing is enabled, otherwise false
+ */
+bool CStringEdit::GetAllowAutoSize()
+{
+ return m_AutoSize;
+}
+
+//==============================================================================
+/**
+ * If auto-resizing is enabled, this function will resize this control so that
+ * it is the same size as the text that it is displaying. Text size is calculated
+ * with an offscreen buffer, so this can be done outside of a draw operation.
+ */
+void CStringEdit::ResetSize()
+{
+ // If auto-resizing of the text field is enabled
+ if (m_AutoSize) {
+ // Resize the control to fit the text, plus the buffer gap
+ COffscreenRenderer theRenderer(CRct(0, 0, 100, 16));
+ CPt theSize;
+ const auto textSize = theRenderer.GetTextSize(GetDisplayString().toQString());
+ theSize.x = textSize.width() + GetBufferLength() * 3;
+ theSize.y = textSize.height() + 1;
+ SetMinimumSize(theSize);
+ SetPreferredSize(theSize);
+ SetMaximumSize(theSize);
+ }
+}
+
+//==============================================================================
+/**
+ * Primarily delegates up to the parent class, but responds by recalculating
+ * size of the text box for auto-sized strings.
+ *
+ * @param inDirty true to mark this control as dirty, which causes the string to be redrawn
+ * false to mark the control as not needing to reevaluate its text during next draw cycle
+ */
+void CStringEdit::SetDirty(bool inDirty)
+{
+ // Allow the parent to handle this situation
+ CTextEdit::SetDirty(inDirty);
+
+ ResetSize();
+}
+
+//==============================================================================
+/**
+ * Reverts the displayed text to the previous text.
+ */
+void CStringEdit::RevertText()
+{
+ SetData(m_PreviousValue);
+ SetDisplayString(m_PreviousValue);
+
+ FireCommitEvent();
+ SelectAllText();
+}
+
+//==============================================================================
+/**
+ * Handles any non-character keys that were pressed and need to be handled.
+ *
+ * @param inChar The key that was pressed
+ * @param inFlags Indicates which modifier keys were down when event occurred
+ * @return true if this function handled the character, otherwise false
+ */
+bool CStringEdit::HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ bool theMessageWasHandled = false;
+
+ switch (inChar) {
+ // Escape and Ctrl+Z both do basically the same thing for StringEdits,
+ // They are special cased in TextEditInPlace though.
+ case Qt::Key_Escape:
+ RevertText();
+ theMessageWasHandled = true;
+ break;
+
+ default:
+ theMessageWasHandled = CTextEdit::HandleSpecialChar(inChar, inFlags);
+ }
+
+ return theMessageWasHandled;
+}
+
+//==============================================================================
+/**
+ * Called when this control gains focus. Shows the caret, clears the current
+ * selection and invalidates the control so that it will get redrawn.
+ */
+void CStringEdit::OnGainFocus()
+{
+ CTextEdit::OnGainFocus();
+ m_PreviousValue = GetString();
+}
+
+//=============================================================================
+/**
+ * Handles character input from the keyboard.
+ *
+ * @param inChar Character that was pressed
+ * @return true if the character was handled, false if this control does not
+ * care about the character that was pressed
+ */
+bool CStringEdit::OnChar(const QString &inChar, Qt::KeyboardModifiers inFlags)
+{
+ return CTextEdit::OnChar(inChar, inFlags);
+}
diff --git a/src/Authoring/Studio/Controls/StringEdit.h b/src/Authoring/Studio/Controls/StringEdit.h
new file mode 100644
index 00000000..8f3c34b1
--- /dev/null
+++ b/src/Authoring/Studio/Controls/StringEdit.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STRING_EDIT_H
+#define INCLUDED_STRING_EDIT_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TextEdit.h"
+
+class CStringEdit : public CTextEdit
+{
+public:
+ CStringEdit();
+ virtual ~CStringEdit();
+ Q3DStudio::CString GetString() override;
+ void SetData(const Q3DStudio::CString &inValue, bool inFireEvent = true) override;
+ void OnLoseFocus() override;
+ void EnterText(bool inHighlight) override;
+ void RefreshDisplayFromData() override;
+ bool CanPaste() override;
+ virtual void ResetSize();
+ void AllowAutoSize(bool inAllow);
+ bool GetAllowAutoSize();
+
+ // overload functions
+ bool HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags) override;
+ void OnGainFocus() override;
+ bool OnChar(const QString &inChar, Qt::KeyboardModifiers inFlags) override;
+
+protected:
+ Q3DStudio::CString m_Value;
+ Q3DStudio::CString m_PreviousValue;
+ bool m_AutoSize;
+
+ virtual void RevertText();
+ void SetDirty(bool inDirty) override;
+};
+
+#endif // INCLUDED_STRING_EDIT_H
diff --git a/src/Authoring/Studio/Controls/TextButton.h b/src/Authoring/Studio/Controls/TextButton.h
new file mode 100644
index 00000000..2593a1d1
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextButton.h
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TEXT_BUTTON_H
+#define INCLUDED_TEXT_BUTTON_H 1
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Renderer.h"
+#include "OffscreenRenderer.h"
+#include "CoreUtils.h"
+#include "StudioPreferences.h"
+#include "ButtonControl.h"
+#include "CColor.h"
+
+#include <QSize>
+
+const long MARGIN_X = 12;
+const long MARGIN_Y = 6;
+
+//=============================================================================
+/**
+ * Template class for making buttons that have text on them. The text can be
+ * displayed with or without the button's icon. In order to use this class,
+ * you must instantiate it with some sort of CButtonControl to act as the base
+ * class.
+ */
+template <class TButton>
+class CTextButton : public TButton
+{
+ // Enumerations
+public:
+ enum EAlignment {
+ ALIGNMENT_LEFT,
+ ALIGNMENT_CENTER,
+ ALIGNMENT_RIGHT,
+ ALIGNMENT_VCENTER ///< Only align center vertically
+ };
+
+ // Constuction/Destruction
+public:
+ CTextButton();
+ virtual ~CTextButton();
+ // Access
+public:
+ void SetText(const Q3DStudio::CString &inText);
+ void SetBoldText(const Q3DStudio::CString &inText);
+ Q3DStudio::CString GetText();
+ void SetTextColorUp(const CColor &inColor);
+ void SetTextColorDown(const CColor &inColor);
+ CColor GetTextColorUp();
+ CColor GetTextColorDown();
+ void SetTextAlignment(EAlignment inAlignment);
+ long GetTextAlignment();
+
+ // Implementation
+protected:
+ virtual void Render(CRenderer *inRenderer);
+ virtual void Resize();
+ void SizeToFitTextLen();
+
+ // Field members
+protected:
+ Q3DStudio::CString m_Text; ///< Text
+ CColor m_TextColorUp; ///< Color of text
+ CColor m_TextColorDown; ///< Color of text
+ CPt m_TextPos; ///< Position of text
+ EAlignment m_TextAlign; ///< Alignment of text
+ BOOL m_BoldText;
+};
+
+//==============================================================================
+// Template implemenations
+//==============================================================================
+
+//=============================================================================
+/**
+ * Constructor
+ */
+template <class TButton>
+CTextButton<TButton>::CTextButton()
+ : TButton()
+ , m_TextColorUp(CStudioPreferences::GetNormalColor())
+ , m_TextColorDown(CStudioPreferences::GetNormalColor())
+ , m_TextPos(MARGIN_X, MARGIN_Y / 2)
+ , m_TextAlign(ALIGNMENT_LEFT)
+ , m_BoldText(FALSE)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+template <class TButton>
+CTextButton<TButton>::~CTextButton()
+{
+}
+
+//=============================================================================
+/**
+ * Sets the text displayed on this button to the specified string.
+ * @param inText new text to be displayed on this button
+ */
+template <class TButton>
+void CTextButton<TButton>::SetText(const Q3DStudio::CString &inText)
+{
+ if (m_Text != inText) {
+ m_Text = inText;
+ SizeToFitTextLen();
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the text bold to be displayed on this button to the specified string.
+ * @param inText new text to be displayed on this button
+ */
+template <class TButton>
+void CTextButton<TButton>::SetBoldText(const Q3DStudio::CString &inText)
+{
+ m_Text = inText;
+ m_BoldText = TRUE;
+ SizeToFitTextLen();
+ TButton::Invalidate();
+}
+
+//=============================================================================
+/**
+ * @return the text currently displayed on this button
+ */
+template <class TButton>
+Q3DStudio::CString CTextButton<TButton>::GetText()
+{
+ return m_Text;
+}
+
+//=============================================================================
+/**
+ * Sets the color of the text displayed on this button in the up state
+ * @param inColor new text color
+ */
+template <class TButton>
+void CTextButton<TButton>::SetTextColorUp(const CColor &inColor)
+{
+ if (m_TextColorUp != inColor) {
+ m_TextColorUp = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the color of the text displayed on this button in the down state
+ * @param inColor new text color
+ */
+template <class TButton>
+void CTextButton<TButton>::SetTextColorDown(const CColor &inColor)
+{
+ if (m_TextColorDown != inColor) {
+ m_TextColorDown = inColor;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * @return the color of the text displayed on this button in the up state
+ */
+template <class TButton>
+CColor CTextButton<TButton>::GetTextColorUp()
+{
+ return m_TextColorUp;
+}
+
+//=============================================================================
+/**
+ * @return the color of the text displayed on this button in the down state
+ */
+template <class TButton>
+CColor CTextButton<TButton>::GetTextColorDown()
+{
+ return m_TextColorDown;
+}
+
+//=============================================================================
+/**
+ * Set the alignment of the text.
+ */
+template <class TButton>
+void CTextButton<TButton>::SetTextAlignment(EAlignment inAlignment)
+{
+ if (inAlignment != m_TextAlign) {
+ m_TextAlign = inAlignment;
+ TButton::Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * @return the alignment of the text displayed on this button
+ */
+template <class TButton>
+long CTextButton<TButton>::GetTextAlignment()
+{
+ return m_TextAlign;
+}
+
+//=============================================================================
+/**
+ * Draws the button, then draws the specified text onto the button.
+ * @param inRenderer the renderer to draw to
+ */
+template <class TButton>
+void CTextButton<TButton>::Render(CRenderer *inRenderer)
+{
+ // Draw the button icon
+ TButton::Render(inRenderer);
+
+ // Detertmine position of text based off horizontal alignment
+ float theTextPosX(static_cast<float>(m_TextPos.x));
+ float theTextPosY(static_cast<float>(m_TextPos.y));
+
+ long theImageX = 0;
+ long theImageY = 0;
+ if (!TButton::GetCurrentImage().isNull()) {
+ theImageX += TButton::GetCurrentImage().size().width();
+ theImageY += TButton::GetCurrentImage().size().height();
+ }
+
+ switch (m_TextAlign) {
+ case ALIGNMENT_CENTER: {
+ const auto textSize = inRenderer->GetTextSize(m_Text.toQString());
+ theTextPosX = (TButton::GetSize().x - textSize.width() + theImageX) / 2;
+ theTextPosY = static_cast<float>(m_TextPos.y);
+ } break;
+
+ case ALIGNMENT_RIGHT: {
+ const auto textSize = inRenderer->GetTextSize(m_Text.toQString());
+ theTextPosX = TButton::GetSize().x - textSize.width();
+ theTextPosY = static_cast<float>(m_TextPos.y);
+ } break;
+
+ case ALIGNMENT_VCENTER: {
+ const auto textSize = inRenderer->GetTextSize(m_Text.toQString());
+ theTextPosY = (TButton::GetSize().y - textSize.height() + theImageY) / 2;
+ theTextPosX = static_cast<float>(m_TextPos.x);
+ }
+ // Default is LEFT justification
+ default:
+ case ALIGNMENT_LEFT:
+ theTextPosX += theImageX;
+ break;
+ }
+
+ typename TButton::EButtonState theState = TButton::GetButtonState();
+ ::CColor theTextColor = m_TextColorUp;
+ if (theState == CButtonControl::EBUTTONSTATE_DOWN)
+ theTextColor = m_TextColorDown;
+ if (TButton::IsEnabled() == false)
+ theTextColor = CStudioPreferences::GetDisabledTextColor();
+
+ inRenderer->PushPen(theTextColor);
+
+ // Draw the text
+ const auto buttonSize = TButton::GetSize();
+ const QRect rect(0, 0, buttonSize.x, buttonSize.y);
+ if (m_BoldText && !m_Text.IsEmpty()) {
+ inRenderer->DrawBoldText(theTextPosX, theTextPosY, m_Text.toQString(), rect, theTextColor);
+ } else {
+ if (!m_Text.IsEmpty())
+ inRenderer->DrawText(theTextPosX, theTextPosY, m_Text.toQString(), rect, theTextColor);
+ }
+
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * this function calculates the text length in the button control and sets the size of the
+ *button
+ */
+template <class TButton>
+void CTextButton<TButton>::Resize()
+{
+ TButton::Resize();
+ SizeToFitTextLen();
+}
+
+//=============================================================================
+/**
+ * this function calculates the text length in the button control and sets the size of the
+ *button
+ */
+template <class TButton>
+void CTextButton<TButton>::SizeToFitTextLen()
+{
+ // If auto-resizing of the text field is enabled
+ if (TButton::m_AutoSize) {
+ // Resize the control to fit the text, plus the buffer gap
+ COffscreenRenderer theRenderer(CRct(0, 0, 1, 1));
+ CPt theSize;
+ const auto textSize = theRenderer.GetTextSize(m_Text.toQString());
+ int theX = textSize.width();
+ int theY = textSize.height();
+
+ if (!TButton::GetCurrentImage().isNull())
+ theX += TButton::GetCurrentImage().size().width();
+
+ // MARGIN_LEN * 2 is just to add some space between the text and the button
+ theSize.x = ::dtol(theX) + (MARGIN_X * 2);
+ theSize.y = static_cast<long>(theY + (MARGIN_Y * 2));
+ TButton::SetSize(theSize);
+ TButton::SetMaximumSize(theSize);
+ TButton::Invalidate();
+ }
+}
+#endif // INCLUDED_TEXT_BUTTON_H
diff --git a/src/Authoring/Studio/Controls/TextEdit.cpp b/src/Authoring/Studio/Controls/TextEdit.cpp
new file mode 100644
index 00000000..76f925e1
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextEdit.cpp
@@ -0,0 +1,1478 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TextEdit.h"
+#include "Renderer.h"
+#include "SystemPreferences.h"
+#include "HotKeys.h"
+#include "TextEditContextMenu.h"
+#include "StudioClipboard.h"
+#include "CoreUtils.h"
+#include "UICMath.h"
+#include "UICDMSignals.h"
+#include "MouseCursor.h"
+#include "StudioApp.h"
+#include "Core.h"
+
+#include <QApplication>
+
+using namespace Q3DStudio;
+
+//==============================================================================
+// Constants
+//==============================================================================
+const long BLINKSPEED =
+ 700; ///< Speed of the blinking cursor while editing, measured in milliseconds
+
+IMPLEMENT_OBJECT_COUNTER(CTextEdit)
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CTextEdit::CTextEdit()
+ : m_IsStringDirty(true)
+ , m_NeedsCommit(false)
+ , m_Alignment(RIGHT)
+ , m_TotalCharWidth(0)
+ , m_BufferLength(2)
+ , m_MaxLength(QT3DS_MAX_I32)
+ , m_IsReadOnly(false)
+ , m_MouseIsDown(false)
+ , m_FillBackground(true)
+ , m_TextColor(0, 0, 0)
+ , m_UseBGColorReadOnly(false)
+ , m_BackgroundColorNoFocus(CStudioPreferences::GetTextBoxBGColorNoFocus())
+ , m_BackgroundColorFocus(CStudioPreferences::GetTextBoxBGColorWithFocus())
+ , m_BoldText(false)
+ , m_ScrollAmount(0, 0)
+ , m_CommandHandler(g_StudioApp.GetCore()->GetHotKeys())
+{
+ ADDTO_OBJECT_COUNTER(CTextEdit)
+
+ m_Caret.color = ::CColor(0, 0, 0);
+ m_Caret.position = 0;
+ m_Caret.show = false;
+
+ m_StartDragPt = CPt(0, 0);
+ m_SelectionStart = 0;
+ m_SelectionEnd = 0;
+
+ m_TextColor = CStudioPreferences::GetRulerTickColor();
+
+ RegisterCommands();
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CTextEdit::~CTextEdit()
+{
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+
+ REMOVEFROM_OBJECT_COUNTER(CTextEdit)
+
+ // Added to help debug freeing memory allocated from inside a DLL
+ m_DisplayString.Clear();
+}
+
+//==============================================================================
+/**
+ * Sets text justification to left, right, or center.
+ *
+ * @param inAlignment Enumeration describing the t3xt justification
+ */
+void CTextEdit::SetAlignment(EAlignment inAlignment)
+{
+ m_Alignment = inAlignment;
+}
+
+//==============================================================================
+/**
+ * Draws the bounding rectangle and white edit box for the text edit class. Also
+ * draws the actual text in the box by calling GetString(), which should be
+ * implemented by any class that extends CTextEdit.
+ */
+void CTextEdit::Draw(CRenderer *inRenderer)
+{
+ inRenderer->PushClippingRect(QRect(0, 0, GetSize().x, GetSize().y));
+
+ // If the string has changed since we last drew it, cache the character widths
+ if (m_IsStringDirty) {
+ CalculateCharWidths(inRenderer);
+ SetDirty(false);
+ }
+
+ DoFillBackground(inRenderer);
+
+ // Draw the actual text
+ DrawText(inRenderer);
+
+ // Draw the caret last
+ DrawCaret(inRenderer);
+
+ inRenderer->PopClippingRect();
+}
+
+//==============================================================================
+/**
+ * Determines the bounding rectangle for the text based on the text justification
+ * setting.
+ *
+ * @return the bounding rectangle for the text being displayed.
+ */
+CRct CTextEdit::GetTextRect()
+{
+ CRct theTextRect;
+
+ switch (m_Alignment) {
+ case LEFT:
+ theTextRect = CRct(CPt(m_BufferLength, 0), CPt(::dtol(m_TotalCharWidth), GetSize().y));
+ break;
+
+ case CENTER:
+ theTextRect = CRct(CPt(GetSize().x / 2 - ::dtol(m_TotalCharWidth / 2), 0),
+ CPt(::dtol(m_TotalCharWidth), GetSize().y));
+ break;
+
+ case RIGHT:
+ // NO BREAK
+ default: {
+ theTextRect = CRct(CPt(GetSize().x - ::dtol(m_TotalCharWidth + m_BufferLength), 0),
+ CPt(::dtol(m_TotalCharWidth), GetSize().y));
+ } break;
+ }
+
+ return theTextRect;
+}
+
+//==============================================================================
+/**
+ * Draws the text out to the screen. If any selection is occurring, the
+ * appropriate text is rendered out to the screen using the system preferences
+ * for selection color.
+ *
+ * @param inRenderer Renderer to draw the text out to
+ */
+void CTextEdit::DrawText(CRenderer *inRenderer)
+{
+ Q3DStudio::CString theCompleteString = GetDisplayString();
+ Q3DStudio::CString theFirstPart = theCompleteString;
+ Q3DStudio::CString theHighlightedString;
+ Q3DStudio::CString theLastPart;
+
+ float theTextSizeX;
+ float theTextSizeY;
+
+ if (HasSelectedText()) {
+ theFirstPart = theCompleteString.Extract(0, GetSelectionLeft());
+ theHighlightedString =
+ theCompleteString.Extract(GetSelectionLeft(), GetSelectionRight() - GetSelectionLeft());
+ theLastPart = theCompleteString.Extract(GetSelectionRight(),
+ theCompleteString.Length() - GetSelectionRight());
+ }
+
+ // Calculate where the upper left corner where text begins (we'll move this point for each part
+ // of the text)
+ float theUpperLeftX = static_cast<float>(GetTextRect().position.x + m_ScrollAmount.x);
+ float theUpperLeftY = static_cast<float>(GetTextRect().position.y + m_ScrollAmount.y);
+
+ const QRect sizeRect(0, 0, GetSize().x, GetSize().y);
+ CRct theSelectionRect(0, 0, 0, 0);
+
+ if (theFirstPart.Length() > 0) {
+ if (!m_BoldText) {
+ inRenderer->DrawText(theUpperLeftX, theUpperLeftY, theFirstPart.toQString(),
+ CRct(GetSize()), m_TextColor);
+ } else {
+ inRenderer->DrawBoldText(theUpperLeftX, theUpperLeftY, theFirstPart.toQString(),
+ CRct(GetSize()), m_TextColor);
+ }
+
+ // Move the upper left corner
+ const auto textSize = inRenderer->GetTextSize(theFirstPart.toQString());
+ theTextSizeX = textSize.width();
+ theTextSizeY = textSize.height();
+ theUpperLeftX += theTextSizeX;
+ }
+
+ if (theHighlightedString.Length() > 0) {
+ // Draw the selection rectangle
+ const auto textSize = inRenderer->GetTextSize(theHighlightedString.toQString());
+ theTextSizeX = textSize.width();
+ theTextSizeY = textSize.height();
+ theSelectionRect.position.x = ::dtol(theUpperLeftX);
+ theSelectionRect.size = CPt(::dtol(theTextSizeX), ::dtol(theTextSizeY) + 2);
+
+ // If the caret is at the far right of the selection, shrink the highlight rect by one
+ // pixel. This is so that you can actually see the blinking cursor on the right edge.
+ if (static_cast<long>(m_Caret.position) == GetSelectionRight())
+ --theSelectionRect.size.x;
+
+ inRenderer->FillSolidRect(theSelectionRect, CSystemPreferences::GetSelectedItemColor());
+
+ // Draw the actual text in the highlight color
+ if (!m_BoldText) {
+ inRenderer->DrawText(theUpperLeftX, theUpperLeftY, theHighlightedString.toQString(),
+ sizeRect, CSystemPreferences::GetSelectedTextColor());
+ } else {
+ inRenderer->DrawBoldText(theUpperLeftX, theUpperLeftY, theHighlightedString.toQString(),
+ sizeRect, CSystemPreferences::GetSelectedTextColor());
+ }
+
+ // Move the upper left corner
+ theUpperLeftX += theTextSizeX;
+ }
+
+ if (theLastPart.Length() > 0) {
+ if (!m_BoldText) {
+ inRenderer->DrawText(theUpperLeftX, theUpperLeftY, theLastPart.toQString(), sizeRect,
+ m_TextColor);
+ } else {
+ inRenderer->DrawBoldText(theUpperLeftX, theUpperLeftY, theLastPart.toQString(), sizeRect,
+ m_TextColor);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Draws the caret out to the screen.
+ *
+ * @param inRenderer Renderer to draw the text out to
+ */
+void CTextEdit::DrawCaret(CRenderer *inRenderer)
+{
+ if (m_Caret.show && m_Caret.visible) {
+ CRct theTextRect = GetTextRect();
+ CPt theCaretPosition(theTextRect.position.x, 0);
+
+ float theSizeX;
+ float theSizeY;
+
+ const auto textSize = inRenderer->GetTextSize(GetDisplayString().
+ Extract(0, m_Caret.position).toQString());
+ theSizeX = textSize.width();
+ theSizeY = textSize.height();
+
+ theCaretPosition.x = ::dtol(theSizeX) + theTextRect.position.x;
+
+ // Adjust the caret postion so that it draws just before the current character, instead of
+ // on the current character
+ theCaretPosition.x--;
+
+ theCaretPosition += m_ScrollAmount;
+
+ inRenderer->PushPen(::CColor(m_Caret.color));
+ theCaretPosition.y = theCaretPosition.y;
+ inRenderer->MoveTo(theCaretPosition);
+ inRenderer->LineTo(theCaretPosition.x, GetSize().y - 1);
+ inRenderer->PopPen();
+ }
+}
+
+//=============================================================================
+/**
+ * Inserts the specified character into the control
+ */
+bool CTextEdit::InsertChar(unsigned int inChar)
+{
+ bool theReturnValue = false;
+ Q3DStudio::CString theTempString = m_DisplayString;
+
+ if (!m_Caret.show)
+ SelectAllText();
+
+ long theLeftSelection = GetSelectionLeft();
+ long theRightSelection = GetSelectionRight();
+ long thePosition = m_Caret.position;
+
+ if (theLeftSelection != theRightSelection) {
+ Q3DStudio::CString theDisplayString = m_DisplayString;
+
+ theTempString = "";
+ theTempString = theDisplayString.Extract(0, theLeftSelection);
+ theTempString += theDisplayString.Extract(theRightSelection,
+ theDisplayString.Length() - theRightSelection);
+ thePosition = theLeftSelection;
+ }
+
+ if (CanAcceptChar(theTempString, inChar, thePosition)
+ && theTempString.Length() < GetMaxLength()) {
+ DeleteCurrentSelection(false);
+
+ Q3DStudio::CString theChar = static_cast<wchar_t>(inChar);
+ theTempString.Insert(m_Caret.position, theChar);
+ SetData(theTempString);
+
+ // Advance the caret past the character that we just typed
+ MoveCaretTo(m_Caret.position + 1);
+
+ ResetBlinkingCursor();
+ theReturnValue = true;
+ }
+
+ return theReturnValue;
+}
+
+//=============================================================================
+/**
+ * Handles character input from the keyboard.
+ *
+ * @param inChar Character that was pressed
+ * @return true if the character was handled, false if this control does not
+ * care about the character that was pressed
+ */
+bool CTextEdit::OnChar(const QString &inChar, Qt::KeyboardModifiers inFlags)
+{
+ // 0x7F is a character generated by the delete key
+ if (inChar.size() == 0 || inChar[0].unicode() == 0x7F)
+ return false;
+
+ bool theReturnValue = false;
+
+ if (!m_CommandHandler->OnChar(QKeySequence::fromString(inChar)[0], 1, inFlags)) {
+ // Do not process the character if control is down, this will allow
+ // app's hotkey to process application hotkeys.
+ if (!(inFlags & Qt::ControlModifier)) {
+ // Always return true whenever it captures focus and tries insert character.
+ // Though InsertChar fails, this is still getting the focus and have processed the
+ // event, return true so that no other controls will handle it
+ // Refer to Bug 897
+ InsertChar(inChar[0].unicode());
+ theReturnValue = true;
+ }
+ } else
+ theReturnValue = true;
+
+ return theReturnValue;
+}
+
+//=============================================================================
+/**
+ * Virtual function that determines if a key recieved via OnChar can actually be
+ * processed. Sub-classes should override this implementation and provide their
+ * own function for determining what characters they accept.
+ *
+ * @param inCheckString the string that is to be checked (in case a lenght requirement is exceeded)
+ * @param inChar the character that was pressed
+ * @param inPosition character index where we are attempting to insert inChar into inCheckString
+ * @return true if this control can accept the character into the string, otherwise false
+ */
+bool CTextEdit::CanAcceptChar(const Q3DStudio::CString &inCheckString, unsigned int inChar,
+ unsigned int inPosition)
+{
+ Q_UNUSED(inCheckString);
+ Q_UNUSED(inPosition);
+
+ bool theAcceptFlag = false;
+
+ if (inChar >= 32 && inChar <= 255 && !m_IsReadOnly)
+ theAcceptFlag = true;
+
+ return theAcceptFlag;
+}
+
+//=============================================================================
+/**
+ * Handles key presses. OnKeyDown events pass in non-printable characters
+ * such as the arrow keys or Enter. Some of these keys will be handled by this
+ * control.
+ *
+ * @param inChar the character that was pressed
+ * @return true if the character was consumed by this control, otherwise false
+ */
+bool CTextEdit::OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ bool theHandledFlag = false;
+ if (!m_IsReadOnly) {
+ if (!m_CommandHandler->OnChar(inChar, 1, inFlags)) {
+ theHandledFlag = HandleSpecialChar(inChar, inFlags);
+
+ // Enter key commits the last change
+ if (inChar == Qt::Key_Enter)
+ FireCommitEvent();
+
+ ResetBlinkingCursor();
+ Invalidate();
+ } else {
+ theHandledFlag = true;
+ }
+ }
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * Handles any non-character keys that were pressed and need to be handled.
+ *
+ * @param inChar The key that was pressed
+ * @param inFlags Indicates which modifier keys were down when event occurred
+ * @return true if this function handled the character, otherwise false
+ */
+bool CTextEdit::HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ bool theHandledFlag = true;
+ bool isShiftDown = inFlags & CHotKeys::MODIFIER_SHIFT ? true : false;
+ // bool isControlDown = inFlags & CHotKeys::MODIFIER_CONTROL ? true : false;
+
+ switch (inChar) {
+ case Qt::Key_Left:
+ // If we are cancelling selection, then we need to change how the caret moves
+ if (HasSelectedText() && !isShiftDown)
+ MoveCaretTo(GetSelectionLeft(), isShiftDown);
+ // Otherwise, just move the caret left by one character
+ else
+ MoveCaretTo(m_Caret.position - 1, isShiftDown);
+ break;
+
+ case Qt::Key_Right:
+ // If we are cancelling selection, then we need to change how the caret moves
+ if (HasSelectedText() && !isShiftDown)
+ MoveCaretTo(GetSelectionRight(), isShiftDown);
+ // Otherwise, just move the caret right by one character
+ else
+ MoveCaretTo(m_Caret.position + 1, isShiftDown);
+ break;
+
+ case Qt::Key_Home:
+ MoveCaretTo(0, isShiftDown);
+ break;
+
+ case Qt::Key_End:
+ MoveCaretTo((long)m_CharWidths.size(), isShiftDown);
+ break;
+
+ case Qt::Key_Backspace:
+ if (HasSelectedText())
+ DeleteCurrentSelection();
+ else
+ DeleteCharacter(false);
+ break;
+
+ case Qt::Key_Delete: {
+ if (HasSelectedText())
+ DeleteCurrentSelection();
+ else
+ DeleteCharacter(true);
+ } break;
+ case Qt::Key_Return:
+ EnterText(true);
+ break;
+
+ default:
+ theHandledFlag = false;
+ break;
+ }
+
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * Handles mouse down events. Places the caret in the appropriate place based
+ * upon the mouse position.
+ *
+ * @param inLocation Location of the mouse at the time the click occurred
+ * @param inFlags Flags indicating various key states (not used)
+ * @return true (this control always handles mouse down events)
+ */
+void CTextEdit::OnMouseOver(CPt inLocation, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inLocation, inFlags);
+
+ if (!m_IsReadOnly)
+ setCursorIfNotSet(CMouseCursor::CURSOR_IBEAM);
+}
+
+//==============================================================================
+/**
+ * Handles mouse down events. Places the caret in the appropriate place based
+ * upon the mouse position.
+ *
+ * @param inLocation Location of the mouse at the time the click occurred
+ * @param inFlags Flags indicating various key states (not used)
+ * @return true (this control always handles mouse down events)
+ */
+bool CTextEdit::OnMouseDown(CPt inLocation, Qt::KeyboardModifiers inFlags)
+{
+ bool theReturnValue = CControl::OnMouseDown(inLocation, inFlags);
+
+ if (!m_IsReadOnly) {
+ // If the text is scrolled, we'll need to adjust for that
+ inLocation -= m_ScrollAmount;
+
+ m_StartDragPt = inLocation;
+ m_MouseIsDown = true;
+
+ ClearSelection();
+
+ MoveCaretTo(ConvertPositionToIndex(inLocation), false, false);
+
+ // Turn the caret on
+ m_Caret.show = true;
+ m_Caret.visible = true;
+
+ ResetBlinkingCursor();
+
+ m_TimerConnection =
+ ITickTock::GetInstance().AddTimer(1000, true, std::bind(&CTextEdit::OnTimer, this),
+ "CTextEdit::OnMouseDown::" + GetDisplayString());
+
+ theReturnValue = true;
+ }
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Called when the mouse button is released. Disables any dragging that may
+ * have been occurring.
+ *
+ * @param inPoint location of the mouse when the event occurred
+ * @param inFlags various flags about other key states
+ */
+void CTextEdit::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_MouseIsDown = false;
+ m_StartDragPt = CPt(0, 0);
+ CControl::OnMouseUp(inPoint, inFlags);
+}
+
+//==============================================================================
+/**
+ * Handles mouse movement. If the left mouse button is down and the user is
+ * dragging the mouse over the text in the edit box, the appropriate text is
+ * selected.
+ *
+ * @param inPoint location of the mouse.
+ * @param inFlags not used
+ */
+void CTextEdit::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inFlags);
+
+ if (!m_IsReadOnly)
+ setCursorIfNotSet(CMouseCursor::CURSOR_IBEAM);
+
+ if (m_MouseIsDown && !m_IsReadOnly) {
+ // The point was scrolled in OnMouseDown, so we have to scroll it when we drag as well so
+ // that it lines up
+ inPoint -= m_ScrollAmount;
+
+ // Figure out what character index inPoint.x translates to
+ long theCharOffset = ConvertPositionToIndex(inPoint);
+
+ MoveCaretTo(theCharOffset, true);
+ }
+}
+
+//==============================================================================
+/**
+ * Converts a given pixel position on the screen into an index into the display
+ * string.
+ *
+ * @param inPosition the point to be converted
+ * @return the character index derived from inPostion
+ */
+long CTextEdit::ConvertPositionToIndex(CPt inPosition)
+{
+ CRct theTextRect = GetTextRect();
+ long theIndex = 0;
+ long theTotalPixels = theTextRect.position.x;
+
+ // NOTE: We technically only care about the x-position of the point, so just ignore
+ // inPosition.y if it is not within the text area. This may need to be changed in
+ // the future (perhaps if vertical alignment is implemented).
+ CPt thePositionNoY = CPt(inPosition.x, theTextRect.position.y);
+
+ // If the point is within the text area
+ if (theTextRect.IsInRect(thePositionNoY)) {
+ // Figure out which characters it falls in between
+ for (TCharLengths::iterator thePos = m_CharWidths.begin(); thePos != m_CharWidths.end();
+ ++thePos) {
+ theTotalPixels += ::dtol(*thePos);
+ if (inPosition.x < theTotalPixels)
+ break;
+ theIndex++;
+ }
+ }
+ // If the point is to the left of the text, default the index to the beginning of the text
+ else if (theTextRect.position.x > thePositionNoY.x) {
+ theIndex = 0;
+ }
+ // Otherwise, the point must be to the right of the text, so move the index to the end of the
+ // text
+ else {
+ theIndex = (long)m_CharWidths.size();
+ }
+
+ return theIndex;
+}
+
+//==============================================================================
+/**
+ * Converts a given character index into a pixel postion on the screen. This
+ * function is the inverse of ConvertPositionToIndex.
+ * @param inIndex the character index to be converted
+ * @return the x-position (in pixels) of character at inIndex
+ */
+long CTextEdit::ConvertIndexToPosition(long inIndex)
+{
+ long theXPixelOffset = GetTextRect().position.x;
+ long theCurrentIndex = 0;
+
+ for (TCharLengths::iterator thePos = m_CharWidths.begin(); thePos != m_CharWidths.end();
+ ++thePos) {
+ theCurrentIndex++;
+
+ if (theCurrentIndex > inIndex) {
+ break;
+ }
+
+ theXPixelOffset += ::dtol(*thePos);
+ }
+
+ return theXPixelOffset;
+}
+
+//==============================================================================
+/**
+ * Handles double clicks on the control. Highlights all the text in the control.
+ *
+ * @param inPoint Not used
+ * @param inFlags Not used
+ * @return true (this control always handles double clicks)
+ */
+bool CTextEdit::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theHandledFlag = false;
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+ if (!m_IsReadOnly) {
+ SelectAllText();
+
+ if (GetParent())
+ GetParent()->GrabFocus(this);
+
+ theHandledFlag = true;
+ }
+
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * Selects all the text in the display string
+ */
+void CTextEdit::SelectAllText()
+{
+ if (!m_IsReadOnly) {
+ MoveCaretTo(GetDisplayString().Length());
+ SetSelection(0, GetDisplayString().Length());
+ // Turn the caret on
+ m_Caret.show = true;
+ }
+}
+
+//==============================================================================
+/**
+ * Marks the string contained by this control as dirty so that it is reevaluated
+ * the next time that the control draws itself. Also clears out any selection
+ * that may have been present, resetting the selection to the caret position.
+ *
+ * @param inDirty true to mark this control as dirty, which causes the string to be redrawn
+ * false to mark the control as not needing to reevaluate its text during next draw cycle
+ */
+void CTextEdit::SetDirty(bool inDirty)
+{
+ m_IsStringDirty = inDirty;
+ if (m_IsStringDirty) {
+ m_NeedsCommit = true;
+ ClearSelection();
+ Invalidate();
+ }
+}
+
+//==============================================================================
+/**
+ * @return true if the string is currently dirty and needs to be reevalutated.
+ */
+bool CTextEdit::IsDirty() const
+{
+ return m_IsStringDirty;
+}
+
+//==============================================================================
+/**
+ * Determines the width in pixels of each letter in the display string.
+ *
+ * @param inRenderer The current renderer being drawn to (since only the renderer
+ * knows how to calculate the pixel width of the text in the current font).
+ * @return The total width in pixels of the entire display string
+ */
+float CTextEdit::CalculateCharWidths(CRenderer *inRenderer)
+{
+ Q3DStudio::CString theString = GetDisplayString();
+
+ m_CharWidths.clear();
+ m_TotalCharWidth = 0;
+
+ for (long theCharIndex = 0; theCharIndex < theString.Length(); ++theCharIndex) {
+ const auto textSize = inRenderer->GetTextSize(theString.Extract(theCharIndex, 1).toQString());
+ m_CharWidths.push_back(textSize.width());
+ m_TotalCharWidth += textSize.width();
+ }
+
+ return m_TotalCharWidth;
+}
+
+//==============================================================================
+/**
+ * Sets the number of pixels worth of buffer space to place at the left and
+ * right ends of the edit box.
+ */
+void CTextEdit::SetBufferLength(long inLength)
+{
+ m_BufferLength = inLength;
+}
+
+//==============================================================================
+/**
+ * Sets the maximum length of text
+ */
+void CTextEdit::SetMaxLength(long inLength)
+{
+ m_MaxLength = inLength;
+}
+
+//==============================================================================
+/**
+ * Allows you to turn the background fill on and off.
+ * @param inFillBackground true to fill the background color when drawing, false to turn it off
+ */
+void CTextEdit::SetFillBackground(bool inFillBackground)
+{
+ if (m_FillBackground == inFillBackground)
+ return;
+ m_FillBackground = inFillBackground;
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Called when this control loses focus. Hides the caret, clears the current
+ * selection and invalidates the control so that it will get redrawn.
+ */
+void CTextEdit::OnLoseFocus()
+{
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+ m_Caret.show = false;
+ m_ScrollAmount.x = 0;
+ ClearSelection();
+ m_IsStringDirty = true;
+ FireCommitEvent();
+ resetCursor();
+ CControl::OnLoseFocus();
+}
+
+//==============================================================================
+/**
+ * Called when this control gains focus. Shows the caret, clears the current
+ * selection and invalidates the control so that it will get redrawn.
+ */
+void CTextEdit::OnGainFocus()
+{
+ if (!m_MouseIsDown) {
+ m_Caret.position = 0;
+ m_Caret.show = !m_IsReadOnly;
+ if (!m_IsReadOnly)
+ SelectAllText();
+
+ if (m_Caret.show) {
+ ResetBlinkingCursor();
+ m_TimerConnection = ITickTock::GetInstance().AddTimer(
+ 1000, true, std::bind(&CTextEdit::OnTimer, this),
+ "CTextEdit::OnGainFocus::" + GetDisplayString());
+ }
+ }
+
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Override to set whether or not this can gain focus.
+ */
+bool CTextEdit::CanGainFocus()
+{
+ return !m_IsReadOnly;
+}
+
+//==============================================================================
+/**
+ * If this control has focus, it's display may have a different string then the
+ * actual underlying string. This enables us to revert back to the original
+ * string if the user presses the Escape while editing the text. So this function
+ * should be used to obtain the proper string to work with. If this control has
+ * focus, the internally stored string is returned, otherwise the CTextEdit asks
+ * its child class to reevaluate the string.
+ *
+ * @return the string being displayed in the edit box
+ */
+Q3DStudio::CString CTextEdit::GetDisplayString()
+{
+ // If this control does not have focus, we should just reevaluate the string
+ if (GetParent()) {
+ if (!GetParent()->HasFocus(this))
+ SetDisplayString(GetString(), false);
+ }
+
+ // If the edit box is read only, then add the pre and postfix,
+ // otherwise, just the display string is drawn while editing
+ Q3DStudio::CString theCompleteString = m_DisplayString;
+ if (m_IsReadOnly) {
+ theCompleteString = m_Prefix + m_DisplayString + m_Postfix;
+ }
+
+ return theCompleteString;
+}
+
+//==============================================================================
+/**
+ * Invokied in a Draw call. Derived class can override to do their own background fill
+ */
+void CTextEdit::DoFillBackground(CRenderer *inRenderer)
+{
+ if ((m_FillBackground && m_UseBGColorReadOnly) || !m_IsReadOnly) {
+ // Fill the interior of the edit box
+ ::CColor theFillColor = m_BackgroundColorNoFocus;
+ // If this control has focus
+ if (GetParent()) {
+ // Lighten the fill color
+ if (GetParent()->HasFocus(this))
+ theFillColor = m_BackgroundColorFocus;
+ }
+ inRenderer->FillSolidRect(QRect(0, 0, GetSize().x, GetSize().y), theFillColor);
+ }
+}
+
+//==============================================================================
+/**
+ * Selects the specified text within the edit box. If inFirstIndex == inLastIndex
+ * no text is selected. If the indices specified do not fall within the size of
+ * the actual text, no selection occurs.
+ *
+ * @param inFirstIndex Index of the first letter to be selected
+ * @param inLastIndex Index of the last letter to be selected
+ */
+void CTextEdit::SetSelection(long inFirstIndex, long inLastIndex)
+{
+ if (inFirstIndex < 0 || inLastIndex > GetDisplayString().Length()) {
+ ClearSelection();
+ } else {
+ if (m_SelectionStart != inFirstIndex || m_SelectionEnd != inLastIndex)
+ Invalidate();
+
+ m_SelectionStart = inFirstIndex;
+ m_SelectionEnd = inLastIndex;
+ }
+
+ m_Caret.position = m_SelectionEnd;
+}
+
+//==============================================================================
+/**
+ * Sets this CTextEdit as either read-only or read/write. When a CTextEdit
+ * control is set to read-only, users cannot input data via the keyboard,
+ * and the text cannot be selected.
+ *
+ * @param inReadOnly true to specify static, non-editable, non-selectable text
+ */
+void CTextEdit::SetReadOnly(bool inReadOnly)
+{
+ if (inReadOnly != m_IsReadOnly)
+ Invalidate();
+
+ m_IsReadOnly = inReadOnly;
+}
+
+//==============================================================================
+/**
+ * @return true if this control should not allow the string to be edited
+ */
+bool CTextEdit::IsReadOnly()
+{
+ return m_IsReadOnly;
+}
+
+//==============================================================================
+/**
+ * Sets the color of the text dispalyed by this control.
+ * @param inColor Color of the text to be displayed
+ */
+void CTextEdit::SetTextColor(::CColor inColor)
+{
+ if (m_TextColor == inColor)
+ return;
+
+ m_TextColor = inColor;
+ m_Caret.color = inColor;
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * @return The current text color
+ */
+::CColor CTextEdit::GetTextColor()
+{
+ return m_TextColor;
+}
+
+//==============================================================================
+/**
+ * Sets the flag that says whether or not to use the m_BackgroundColorFocus
+ * and m_BackgroundColorNoFocus user colors to draw the background color
+ * of the text box.
+ */
+void CTextEdit::SetUseBGColorReadOnly(bool inUseBGColorReadOnly)
+{
+ m_UseBGColorReadOnly = inUseBGColorReadOnly;
+}
+
+//==============================================================================
+/**
+ * Sets the color of the background of this control when it does not have focus.
+ * Note that this color only has an effect when SetFillBackground has been
+ * called with true.
+ * @param inColor Color of the background when the control does not have focus
+ * @return The previous background color
+ */
+::CColor CTextEdit::SetBGColorNoFocus(::CColor inColor)
+{
+ ::CColor theOldColor = m_BackgroundColorNoFocus;
+ m_BackgroundColorNoFocus = inColor;
+ return theOldColor;
+}
+
+//==============================================================================
+/**
+ * Sets the color of the background of this control when it has focus.
+ * Note that this color only has an effect when SetFillBackground has been
+ * called with true.
+ * @param inColor Color of the background when the control has focus
+ * @return The previous background color
+ */
+::CColor CTextEdit::SetBGColorFocus(::CColor inColor)
+{
+ ::CColor theOldColor = m_BackgroundColorFocus;
+ m_BackgroundColorFocus = inColor;
+ return theOldColor;
+}
+
+void CTextEdit::AddCommitListener(CCommitDataListener *inListener)
+{
+ m_CommitListeners.AddListener(inListener);
+}
+
+void CTextEdit::RemoveCommitListener(CCommitDataListener *inListener)
+{
+ m_CommitListeners.RemoveListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Fires commit events on Listeners. Only fires a commit event if it has not
+ * been fired previously.
+ */
+void CTextEdit::FireCommitEvent()
+{
+ // If we are not currently processing a command to fire commit events to listeners
+ if (m_NeedsCommit) {
+ // Fire the event and undirty the text
+ m_CommitListeners.FireEvent(&CCommitDataListener::OnSetData, this);
+ m_NeedsCommit = false;
+ }
+}
+
+void CTextEdit::AddChangeListener(IChangeDataListener *inListener)
+{
+ m_ChangeListeners.AddListener(inListener);
+}
+
+void CTextEdit::RemoveChangeListener(IChangeDataListener *inListener)
+{
+ m_ChangeListeners.RemoveListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Fires change events on Listeners.
+ */
+void CTextEdit::FireChangeEvent(const Q3DStudio::CString &inOldString,
+ const Q3DStudio::CString &inNewString)
+{
+ m_ChangeListeners.FireEvent(&IChangeDataListener::OnChangeData, inOldString, inNewString);
+}
+
+void CTextEdit::AddEnterListener(ITextEditEnterListener *inListener)
+{
+ m_EnterListeners.AddListener(inListener);
+}
+
+void CTextEdit::RemoveEnterListener(ITextEditEnterListener *inListener)
+{
+ m_EnterListeners.RemoveListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Fires enter events on listeners.
+ */
+void CTextEdit::FireEnterEvent()
+{
+ m_EnterListeners.FireEvent(&ITextEditEnterListener::OnEnter, this);
+}
+
+//==============================================================================
+/**
+ * Delete any text that is currently selected.
+ * If there is no text selected this will do nothing.
+ */
+void CTextEdit::DeleteCurrentSelection(bool inFireEvent /*=true*/)
+{
+ if (HasSelectedText()) {
+ Q3DStudio::CString theTempString = m_DisplayString;
+ theTempString.Delete(GetSelectionLeft(), GetSelectionRight() - GetSelectionLeft());
+
+ m_Caret.position = GetSelectionLeft();
+
+ ClearSelection();
+
+ // @see DeleteCharacter( )
+ SetData(theTempString, inFireEvent);
+ SetDisplayString(theTempString, inFireEvent);
+ SetDirty(true);
+ }
+}
+
+//==============================================================================
+/**
+ * Delete a character to the left or right of the cursor.
+ * This will delete a single character on the specified side of the cursor.
+ * @param inOnRight true if the character to be deleted is on the right of the cursor.
+ */
+void CTextEdit::DeleteCharacter(bool inOnRight)
+{
+ if (!inOnRight) {
+ if (m_Caret.position == 0)
+ return;
+ else
+ m_Caret.position--;
+ }
+
+ Q3DStudio::CString theTempString = m_DisplayString;
+ theTempString.Delete(m_Caret.position, 1);
+ // Since SetData is overloaded by other types of text edit controls,
+ // it has to be called first so that subclasses have a chance to set their internal values
+ // before calling SetDisplayString, which fires a DataChanged event.
+ // @see DeleteCurrentSelection( ). EnterText got it right.
+ SetData(theTempString);
+ SetDisplayString(theTempString);
+ SetDirty(true);
+}
+
+//==============================================================================
+/**
+ * Move the caret to the specified position in the string.
+ * If inSelect then this will select the text from the selection start position
+ * to the new position. If there is no current selection start then this will
+ * select from the old position to the new position. If select is false and there
+ * is selected text the selection will be cleared.
+ * @param inPosition the position to move to in the string.
+ * @param inSelect true if the selection should be changed when moving.
+ * @param inScroll true if moving the caret should allow the text to scroll within the box
+ */
+void CTextEdit::MoveCaretTo(long inPosition, bool inSelect /*=false*/, bool inScroll /*=true*/)
+{
+ if (inPosition < 0)
+ inPosition = 0;
+ if (inPosition > GetDisplayString().Length())
+ inPosition = GetDisplayString().Length();
+
+ // Only perform the operation if the caret is actually going to move, or the selection is going
+ // to change
+ if ((static_cast<unsigned long>(inPosition) != m_Caret.position)
+ || (HasSelectedText() && !inSelect)) {
+ if (inSelect) {
+ if (!HasSelectedText())
+ m_SelectionStart = m_Caret.position;
+ m_SelectionEnd = inPosition;
+ } else
+ ClearSelection();
+
+ m_Caret.position = inPosition;
+
+ // Scroll if necessary
+ if (inScroll) {
+ long theCaretPixelPos = ConvertIndexToPosition(m_Caret.position);
+ if (theCaretPixelPos + m_ScrollAmount.x <= 0)
+ Scroll(m_ScrollAmount.x - (theCaretPixelPos + m_ScrollAmount.x) + m_BufferLength);
+ else if (theCaretPixelPos + m_ScrollAmount.x > GetSize().x)
+ Scroll(-(theCaretPixelPos - GetSize().x + m_BufferLength));
+ }
+
+ Invalidate();
+ }
+}
+
+//==============================================================================
+/**
+ * Effectively scrolls the text in this edit box.
+ * Enables you to set the number of pixels to offset the text and caret by when
+ * they are drawn to the screen. If inPixel = 0, no scrolling takes place. If
+ * inPixel < 0, text is scrolled to the left. If inPixel > 0, text is scrolled
+ * to the right.
+ * @param inPixel specifies the horizontal scroll in pixels
+ */
+void CTextEdit::Scroll(long inPixel)
+{
+ m_ScrollAmount.x = inPixel;
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Pushes the display string back down to the control and optionally highlights
+ * the entire string. Called when the user clicks the enter button in an edit
+ * box.
+ * @param inHighlight true to highlight the string
+ */
+void CTextEdit::EnterText(bool inHighlight)
+{
+ SetData(m_DisplayString);
+ SetDisplayString(GetString());
+
+ if (inHighlight)
+ SetSelection(0, m_DisplayString.Length());
+
+ Invalidate();
+
+ FireEnterEvent();
+}
+
+//==============================================================================
+/**
+ * Check to see if there is any text selected.
+ * @return true if there is any text selected.
+ */
+bool CTextEdit::HasSelectedText()
+{
+ return m_SelectionStart != m_SelectionEnd;
+}
+
+//==============================================================================
+/**
+ * Get the index of the leftmost selected character.
+ * @return the index, invalid if no text is selected.
+ */
+long CTextEdit::GetSelectionLeft()
+{
+ return m_SelectionStart < m_SelectionEnd ? m_SelectionStart : m_SelectionEnd;
+}
+
+//==============================================================================
+/**
+ * Get the index of the rightmost selected character.
+ * @return the index, invalid if no text is selected.
+ */
+long CTextEdit::GetSelectionRight()
+{
+ return m_SelectionStart > m_SelectionEnd ? m_SelectionStart : m_SelectionEnd;
+}
+
+//==============================================================================
+/**
+ * Clear any text from being selected, this will not delete the text, only deselect it.
+ */
+void CTextEdit::ClearSelection()
+{
+ m_SelectionStart = 0;
+ m_SelectionEnd = 0;
+
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Re-get the display string.
+ */
+void CTextEdit::ReloadData()
+{
+ SetDisplayString(GetString());
+}
+
+//==============================================================================
+/**
+ * Supply a prefix to be displayed when the string is not being edited (e.g. "#").
+ */
+void CTextEdit::SetPrefix(const Q3DStudio::CString &inPrefix)
+{
+ m_Prefix = inPrefix;
+}
+
+//==============================================================================
+/**
+ * Supply a postfix to be displayed when the string is not being edited (e.g. " inches").
+ */
+void CTextEdit::SetPostfix(const Q3DStudio::CString &inPostfix)
+{
+ m_Postfix = inPostfix;
+}
+
+//==============================================================================
+/**
+ * Handles the hotkey commands
+ */
+
+void CTextEdit::RegisterCommands()
+{
+ m_CommandHandler->RegisterKeyEvent(new CDynHotKeyConsumer<CTextEdit>(this, &CTextEdit::CopyText),
+ Qt::ControlModifier, Qt::Key_C);
+ m_CommandHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CTextEdit>(this, &CTextEdit::PasteText), Qt::ControlModifier,
+ Qt::Key_V);
+ m_CommandHandler->RegisterKeyEvent(new CDynHotKeyConsumer<CTextEdit>(this, &CTextEdit::CutText),
+ Qt::ControlModifier, Qt::Key_X);
+ m_CommandHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CTextEdit>(this, &CTextEdit::SelectAllText),
+ Qt::ControlModifier, Qt::Key_A);
+}
+
+//==============================================================================
+/**
+ * Copies selected text to clipboard. If nothing is selected, everything is copied.
+ * @return true if text was copied
+ */
+bool CTextEdit::CopyText()
+{
+ if (!m_IsReadOnly) {
+ if (HasSelectedText())
+ CStudioClipboard::CopyTextToClipboard(m_DisplayString.Extract(
+ GetSelectionLeft(), GetSelectionRight() - GetSelectionLeft()).toQString());
+ else
+ CStudioClipboard::CopyTextToClipboard(m_DisplayString.toQString());
+ }
+ return !m_IsReadOnly;
+}
+
+//==============================================================================
+/**
+ * Pastes text to clipboard
+ */
+
+bool CTextEdit::PasteText()
+{
+ Q3DStudio::CString theText = Q3DStudio::CString
+ ::fromQString(CStudioClipboard::GetTextFromClipboard());
+ bool theHandledFlag = !m_IsReadOnly && CanPaste() && !theText.IsEmpty();
+
+ theHandledFlag &= theText.Length() <= GetMaxLength();
+ if (HasSelectedText()) {
+ theHandledFlag &=
+ m_DisplayString.Length() - (GetSelectionRight() - GetSelectionLeft()) + theText.Length()
+ <= GetMaxLength();
+ } else {
+ theHandledFlag &= m_DisplayString.Length() + theText.Length() <= GetMaxLength();
+ }
+
+ if (theHandledFlag) {
+ if (!m_Caret.show) {
+ SetData(theText);
+ } else {
+ Q3DStudio::CString theNewString(m_DisplayString);
+
+ if (HasSelectedText()) {
+ theNewString.Delete(GetSelectionLeft(), GetSelectionRight() - GetSelectionLeft());
+ m_Caret.position = Q3DStudio::MIN(GetSelectionLeft(), GetSelectionRight());
+ }
+ theNewString.Insert(m_Caret.position, theText);
+
+ SetData(theNewString);
+ m_Caret.position += theText.Length();
+ }
+ SetDirty(true);
+ }
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * Cuts text to clipboard
+ */
+
+bool CTextEdit::CutText()
+{
+ bool theReturn = false;
+
+ if (CopyText()) {
+ DeleteCurrentSelection();
+ theReturn = true;
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * Reloads the display string with the given string
+ * @param inString The string to be set
+ */
+void CTextEdit::SetDisplayString(const Q3DStudio::CString &inString, bool inFireEvent /*= true*/)
+{
+ if (m_DisplayString != inString) {
+ Q3DStudio::CString theOldString = m_DisplayString;
+ m_DisplayString = inString;
+
+ if (inFireEvent)
+ FireChangeEvent(theOldString, m_DisplayString);
+
+ m_IsStringDirty = true;
+ }
+}
+
+//==============================================================================
+/**
+ * The buffer length is the number of pixels between where the control starts
+ * and where the text begins drawing (in the case of left alignment). In the
+ * case of right alignment it's the number of pixels on the right side of the
+ * control where the text ends before the actual edge of the control. Provided
+ * for sub classes.
+ */
+long CTextEdit::GetBufferLength()
+{
+ return m_BufferLength;
+}
+
+//==============================================================================
+/**
+ * The maximum allowed length of text
+ */
+long CTextEdit::GetMaxLength()
+{
+ return m_MaxLength;
+}
+
+//==============================================================================
+/**
+ * Displays the Copy/Cut/Paste context menu on right mouse down
+ */
+void CTextEdit::DisplayContextMenu(CPt inPt)
+{
+ CTextEditContextMenu theMenu(this);
+ DoPopup(&theMenu, inPt);
+}
+
+//==============================================================================
+/**
+ * Handles the Right mouse down event. Displays a cut/copy/paste context menu.
+ * @param inPoint location of the mouse at time of the event (context menu's upper left corner will
+ * be here)
+ * @param inFlags state of the modifier keys at the time of the event
+ * @return true - this control always consumes the event
+ */
+bool CTextEdit::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Give children the chance to handle the event, otherwise display the context menu
+ if (!CControl::OnMouseRDown(inPoint, inFlags)) {
+ if (!IsReadOnly()) {
+ DisplayContextMenu(CPt(inPoint.x, GetSize().y));
+ return true;
+ }
+ }
+ return false;
+}
+
+//==============================================================================
+/**
+ * Periodic callback to make the caret blink.
+ */
+void CTextEdit::OnTimer()
+{
+ m_Caret.visible = !m_Caret.visible;
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Cancels the current timer and adds a new timer so that the cursor continues
+ * to blink. If the cursor is not currently visible, it is made visible.
+ */
+void CTextEdit::ResetBlinkingCursor()
+{
+ // Cancel the current timer
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+
+ // If the cursor is not visible, make it visible
+ if (!m_Caret.visible) {
+ m_Caret.visible = true;
+ Invalidate();
+ }
+
+ // Add the timer so that the cursor will blink back off after BLINKSPEED amount of time
+ m_TimerConnection =
+ ITickTock::GetInstance().AddTimer(BLINKSPEED, true, std::bind(&CTextEdit::OnTimer, this),
+ "CTextEdit::ResetBlinkingCursor::" + m_DisplayString);
+}
+
+//==============================================================================
+/**
+ * Set to true to indicate text should be drawn bold.
+ * @param inBold true to set text to bold
+ */
+void CTextEdit::SetBoldText(bool inBold)
+{
+ m_BoldText = inBold;
+}
diff --git a/src/Authoring/Studio/Controls/TextEdit.h b/src/Authoring/Studio/Controls/TextEdit.h
new file mode 100644
index 00000000..b34dd75b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextEdit.h
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TEXT_EDIT_H
+#define INCLUDED_TEXT_EDIT_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "Control.h"
+#include "HotKeys.h"
+#include "StudioPreferences.h"
+#include "ITickTock.h"
+#include "Multicaster.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+class CRenderer;
+
+//==============================================================================
+/**
+ * @class CTextEdit Base class for textual edit fields in Studio (timeline, inspector).
+ */
+
+// Functors
+GENERIC_FUNCTOR_1(CCommitDataListener, OnSetData, CControl *);
+GENERIC_FUNCTOR_1(ITextEditEnterListener, OnEnter, CControl *);
+GENERIC_FUNCTOR_2(IChangeDataListener, OnChangeData, const Q3DStudio::CString &,
+ const Q3DStudio::CString &);
+
+class CTextEdit : public CControl
+{
+ struct SCaret
+ {
+ unsigned long position; ///< index of the character that the cursor is currently in front of
+ ///(zero is first character)
+ ::CColor color; ///< color of the cursor
+ bool show; ///< must be true in order for the cursor to show up (outside of blink state)
+ bool visible; ///< blinking state of the cursor (true if currently visible)
+ };
+
+ typedef std::vector<float> TCharLengths;
+
+public:
+ enum EAlignment { LEFT = 0, CENTER, RIGHT };
+
+ CTextEdit();
+ virtual ~CTextEdit();
+
+ DEFINE_OBJECT_COUNTER(CTextEdit)
+
+ virtual Q3DStudio::CString
+ GetString() = 0; ///< Returns the string to be displayed in the edit box
+
+ void Draw(CRenderer *inRenderer) override;
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inLocation, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnChar(const QString &inChar, Qt::KeyboardModifiers inModifiers) override;
+ bool OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inModifiers) override;
+ void OnGainFocus() override;
+ void OnLoseFocus() override;
+ bool CanGainFocus() override;
+ virtual bool CanAcceptChar(const Q3DStudio::CString &inCheckString, unsigned int inChar,
+ unsigned int inPosition);
+ void SetAlignment(EAlignment inAlignment);
+ void SetBufferLength(long inLength);
+ void SetMaxLength(long inLength);
+ void SetFillBackground(bool inFillBackground);
+ void SelectAllText();
+ void DisplayContextMenu(CPt inPt);
+ virtual bool CanPaste() = 0;
+
+ virtual void SetData(const Q3DStudio::CString &inData, bool inFireEvent = true) = 0;
+ virtual void ReloadData();
+ virtual void SetPrefix(const Q3DStudio::CString &inPrefix);
+ virtual void SetPostfix(const Q3DStudio::CString &inPostfix);
+
+ void SetReadOnly(bool inReadOnly);
+ bool IsReadOnly();
+ void SetTextColor(::CColor inColor);
+ ::CColor GetTextColor();
+ void SetUseBGColorReadOnly(bool inUseBGColorReadOnly);
+ ::CColor SetBGColorNoFocus(::CColor inColor);
+ ::CColor SetBGColorFocus(::CColor inColor);
+ void SetBoldText(bool inBold);
+
+ void AddCommitListener(CCommitDataListener *inListener);
+ void RemoveCommitListener(CCommitDataListener *inListener);
+ void FireCommitEvent();
+
+ void AddChangeListener(IChangeDataListener *inListener);
+ void RemoveChangeListener(IChangeDataListener *inListener);
+ void FireChangeEvent(const Q3DStudio::CString &inOldString,
+ const Q3DStudio::CString &inNewString);
+
+ void AddEnterListener(ITextEditEnterListener *inListener);
+ void RemoveEnterListener(ITextEditEnterListener *inListener);
+ void FireEnterEvent();
+
+ bool HasSelectedText();
+ long GetSelectionLeft();
+ long GetSelectionRight();
+ void ClearSelection();
+ virtual void SetSelection(long inFirstIndex, long inLastIndex);
+
+ void MoveCaretTo(long inPosition, bool inSelect = false, bool inScroll = true);
+ void Scroll(long inPixel);
+ virtual void EnterText(bool inHighlight);
+
+ virtual void RefreshDisplayFromData() = 0;
+
+ bool CopyText();
+ bool PasteText();
+ bool CutText();
+ bool IsDirty() const;
+
+ virtual void OnTimer();
+
+ // Public so that derived objects can query the value on change events
+ Q3DStudio::CString GetDisplayString();
+
+protected:
+ virtual void DoFillBackground(CRenderer *inRenderer);
+
+protected:
+ bool m_IsStringDirty;
+ bool m_NeedsCommit;
+ TCharLengths m_CharWidths;
+ EAlignment m_Alignment;
+ float m_TotalCharWidth;
+ SCaret m_Caret;
+ long m_BufferLength;
+ long m_MaxLength;
+ bool m_IsReadOnly;
+ bool m_MouseIsDown;
+ CPt m_StartDragPt;
+ CHotKeys *m_CommandHandler;
+ bool m_FillBackground;
+ ::CColor m_TextColor;
+ bool m_UseBGColorReadOnly; ///< Flag indicating that we should use the background colors in read
+ ///only boxes as well as read/write
+ ::CColor m_BackgroundColorNoFocus;
+ ::CColor m_BackgroundColorFocus;
+ Q3DStudio::CString m_DisplayString;
+ Q3DStudio::CString m_Prefix;
+ Q3DStudio::CString m_Postfix;
+ bool m_BoldText;
+
+ virtual void DeleteCurrentSelection(bool inFireEvent = true);
+ virtual void DeleteCharacter(bool inIsOnRight = false);
+ void RegisterCommands();
+ virtual void SetDirty(bool inDirty);
+ float CalculateCharWidths(CRenderer *inRenderer);
+ virtual bool HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags);
+ void DrawText(CRenderer *inRenderer);
+ void DrawCaret(CRenderer *inRenderer);
+ CRct GetTextRect();
+ long ConvertIndexToPosition(long inIndex);
+ long ConvertPositionToIndex(CPt inPosition);
+ void SetDisplayString(const Q3DStudio::CString &inString, bool inFireEvent = true);
+ long GetBufferLength();
+ long GetMaxLength();
+ void ResetBlinkingCursor();
+ bool InsertChar(unsigned int inChar);
+
+private:
+ CMulticaster<CCommitDataListener *> m_CommitListeners;
+ CMulticaster<IChangeDataListener *> m_ChangeListeners;
+ CMulticaster<ITextEditEnterListener *> m_EnterListeners;
+ long m_SelectionStart;
+ long m_SelectionEnd;
+ CPt m_ScrollAmount; ///< Pixel offset to scroll the text and caret by
+ std::shared_ptr<UICDM::ISignalConnection> m_TimerConnection;
+};
+
+#endif // INCLUDED_TEXT_EDIT_H
diff --git a/src/Authoring/Studio/Controls/TextEditContextMenu.cpp b/src/Authoring/Studio/Controls/TextEditContextMenu.cpp
new file mode 100644
index 00000000..12d6ede9
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextEditContextMenu.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TextEditContextMenu.h"
+#include "TextEdit.h"
+#include "StudioClipboard.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+
+CTextEditContextMenu::CTextEditContextMenu(CTextEdit *inEditControl, QWidget *parent) : QMenu(parent)
+{
+ m_TextEditControl = inEditControl;
+
+ m_cutAction = new QAction(tr("Cut"), this);
+ connect(m_cutAction, &QAction::triggered, this, &CTextEditContextMenu::CutText);
+ addAction(m_cutAction);
+
+ m_copyAction = new QAction(tr("Copy"), this);
+ connect(m_copyAction, &QAction::triggered, this, &CTextEditContextMenu::CopyText);
+ addAction(m_copyAction);
+
+ m_pasteAction = new QAction(tr("Paste"), this);
+ connect(m_pasteAction, &QAction::triggered, this, &CTextEditContextMenu::PasteText);
+ addAction(m_pasteAction);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+
+CTextEditContextMenu::~CTextEditContextMenu()
+{
+}
+
+//==============================================================================
+/**
+ * returns true if 'cut' can be applied to the control
+ */
+bool CTextEditContextMenu::CanCutText()
+{
+ return true;
+}
+
+//==============================================================================
+/**
+ * Returns true if you can copy the text in the control
+ */
+bool CTextEditContextMenu::CanCopyText()
+{
+ return true;
+}
+
+//==============================================================================
+/**
+ * Returns true if you may paste text from the clipboard into the control
+ */
+bool CTextEditContextMenu::CanPasteText()
+{
+ return CStudioClipboard::CanPasteText();
+}
+
+//==============================================================================
+/**
+ * Calls the controls cuttext function
+ */
+void CTextEditContextMenu::CutText()
+{
+ m_TextEditControl->CutText();
+}
+
+//==============================================================================
+/**
+ * Calls the controls copy text function
+ */
+void CTextEditContextMenu::CopyText()
+{
+ m_TextEditControl->CopyText();
+}
+
+//==============================================================================
+/**
+ * Calls the controls paste text function
+ */
+void CTextEditContextMenu::PasteText()
+{
+ m_TextEditControl->PasteText();
+}
+
+void CTextEditContextMenu::showEvent(QShowEvent *event)
+{
+ m_cutAction->setEnabled(CanCutText());
+ m_copyAction->setEnabled(CanCopyText());
+ m_pasteAction->setEnabled(CanPasteText());
+
+ QMenu::showEvent(event);
+}
diff --git a/src/Authoring/Studio/Controls/TextEditContextMenu.h b/src/Authoring/Studio/Controls/TextEditContextMenu.h
new file mode 100644
index 00000000..981253be
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextEditContextMenu.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TEXTEDITCONTEXTMENU_H
+#define INCLUDED_TEXTEDITCONTEXTMENU_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <QMenu>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTextEdit;
+
+//==============================================================================
+/**
+ * @class CTextEditContextMenu
+ */
+
+class CTextEditContextMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ CTextEditContextMenu(CTextEdit *inEditControl, QWidget *parent = nullptr);
+ ~CTextEditContextMenu();
+
+protected Q_SLOTS:
+ void CutText();
+ void CopyText();
+ void PasteText();
+
+protected:
+ void showEvent(QShowEvent *event) override;
+
+ bool CanCutText();
+ bool CanPasteText();
+ bool CanCopyText();
+
+ CTextEdit *m_TextEditControl;
+ QAction *m_cutAction;
+ QAction *m_copyAction;
+ QAction *m_pasteAction;
+};
+
+#endif // INCLUDED_TEXTEDITCONTEXTMENU_H
diff --git a/src/Authoring/Studio/Controls/TextEditInPlace.cpp b/src/Authoring/Studio/Controls/TextEditInPlace.cpp
new file mode 100644
index 00000000..145df140
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextEditInPlace.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TextEditInPlace.h"
+#include "Renderer.h"
+
+//==============================================================================
+// Static class constants
+//==============================================================================
+const long CTextEditInPlace::s_RightBuffer =
+ 6; ///< Extra space allotted on the right side of the text
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CTextEditInPlace::CTextEditInPlace()
+ : CStringEdit()
+ , m_IsInEditMode(false)
+ , m_IsEditable(true)
+ , m_AllowSingleClickEdit(true)
+{
+ SetAlignment(LEFT);
+ SetReadOnly(true);
+ SetFillBackground(false);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CTextEditInPlace::~CTextEditInPlace()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the mouse double-click event. Enters the text into edit mode so that
+ * the user can change its value.
+ * @param inPoint location of the mouse
+ * @param inFlags modifier flags for the mouse
+ * @return true if this message should not be passed to any other children, otherwise false
+ */
+bool CTextEditInPlace::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theMessageWasHandled = false;
+ if (m_IsEditable) {
+ SetEditMode(true);
+ SetSelection(0, GetString().Length());
+ m_Caret.show = true;
+ theMessageWasHandled = true;
+ } else
+ theMessageWasHandled = CStringEdit::OnMouseDoubleClick(inPoint, inFlags);
+ return theMessageWasHandled;
+}
+
+void CTextEditInPlace::OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CStringEdit::OnMouseClick(inPoint, inFlags);
+ if (IsInFocus() && !(inFlags & CHotKeys::MOUSE_RBUTTON) && !m_IsInEditMode && m_IsEditable
+ && m_AllowSingleClickEdit) {
+ SetEditMode(true);
+ SelectAllText();
+ }
+}
+
+//==============================================================================
+/**
+ * Called when this control loses focus. Turns off edit mode and redraws the
+ * control.
+ */
+void CTextEditInPlace::OnLoseFocus()
+{
+ SetEditMode(false);
+ CStringEdit::OnLoseFocus();
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Handles most of the drawing, with some help from the parent class.
+ * @param inRenderer Renderer to draw to
+ */
+void CTextEditInPlace::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize()); // CRct( CPt( ::dtol( CalculateCharWidths( inRenderer ) + s_RightBuffer
+ // ), GetSize( ).y ) );
+
+ inRenderer->PushClippingRect(theRect);
+ CStringEdit::Draw(inRenderer);
+ inRenderer->PopClippingRect();
+}
+
+//==============================================================================
+/**
+ * Enables or disables this control from being able to enter "Edit Mode" when
+ * SetEditMode() is called.
+ * @param inIsEditable true if you want the control to be editable when double-clicked, otherwise
+ * false
+ */
+void CTextEditInPlace::SetEditable(bool inIsEditable)
+{
+ m_IsEditable = inIsEditable;
+
+ if (!m_IsEditable && m_IsInEditMode)
+ SetEditMode(false);
+}
+
+//==============================================================================
+/**
+ * Starts or stops "Edit Mode". While in Edit Mode, the user can change the
+ * text, move the caret, and highlight the text. An edit box is also drawn
+ * around the text.
+ * @param inEditMode true to turn on Edit Mode, false to turn off Edit Mode
+ */
+void CTextEditInPlace::SetEditMode(bool inEditMode)
+{
+ if (m_IsEditable && (inEditMode != m_IsInEditMode)) {
+ m_IsInEditMode = inEditMode;
+ SetReadOnly(!m_IsInEditMode);
+
+ // If we are in edit mode
+ if (m_IsInEditMode) {
+ m_PreviousValue = GetString();
+ }
+ // If we are not in edit mode
+ else {
+ // Restore the text color and commit the changes
+ FireCommitEvent();
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Overriden from the parent to cause this control to lose focus when the Enter
+ * button is pressed on the keyboard.
+ * @param inHighlight true to highlight all of the text, false to just change the string
+ */
+void CTextEditInPlace::EnterText(bool inHighlight)
+{
+ CStringEdit::EnterText(inHighlight);
+ OnLoseFocus();
+}
+
+//==============================================================================
+/**
+ * Overriden to also invalidate/validate the parent.
+ * @param inInvalidate true to invalidate this control and the parent control
+ */
+void CTextEditInPlace::Invalidate(bool inInvalidate)
+{
+ if (inInvalidate && GetParent())
+ GetParent()->Invalidate(inInvalidate);
+
+ CStringEdit::Invalidate(inInvalidate);
+}
+
+//==============================================================================
+/**
+ * Override to avoid selecting all the text unless in edit mode.
+ */
+void CTextEditInPlace::OnGainFocus()
+{
+ if (m_IsInEditMode && m_IsEditable)
+ CStringEdit::OnGainFocus();
+}
+
+bool CTextEditInPlace::CanGainFocus()
+{
+ return true;
+}
+
+//==============================================================================
+/**
+ * Returns the edit mode.
+ * @return true if the control is currently in edit mode meaning that the user
+ * can enter text into it, otherwise false
+ */
+bool CTextEditInPlace::GetEditMode()
+{
+ return m_IsInEditMode;
+}
+
+long CTextEditInPlace::GetRightBuffer()
+{
+ return s_RightBuffer;
+}
+
+//==============================================================================
+/**
+ * Handles the Right mouse button down command. Only shows the cut/copy/paste
+ * context menu if the control is currently being edited. You can't change a
+ * string that's not currently being edited
+ * @param inPoint The mouse position at the time of the event
+ * @param inFlags The state of the modifier keys at the time of the event
+ * @return true if this function handled the character, otherwise false
+ */
+
+bool CTextEditInPlace::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theMessageWasHandled = false;
+
+ // The base class shows the cut/copy/paste menu, so only do it if we are in edit mode
+ if (m_IsInEditMode)
+ theMessageWasHandled = CStringEdit::OnMouseRDown(inPoint, inFlags);
+
+ return theMessageWasHandled;
+}
+
+//=============================================================================
+/**
+ * Handles character input from the keyboard.
+ *
+ * @param inChar Character that was pressed
+ * @return true if the character was handled, false if this control does not
+ * care about the character that was pressed
+ */
+bool CTextEditInPlace::OnChar(const QString &inChar, Qt::KeyboardModifiers inModifiers)
+{
+ bool theMessageWasHandled = false;
+ if (GetEditMode())
+ theMessageWasHandled = CStringEdit::OnChar(inChar, inModifiers);
+ return theMessageWasHandled;
+}
+
+//==============================================================================
+/**
+ * By default, clicking on a CTextEditInPlace control that already has focus, will
+ * cause the control to enter edit mode (if SetEditable( true ) has been called).
+ * This is referred to as single-click editing. This function allows you to
+ * enable or disable this functionality. Even if single-click editing is
+ * disabled, the user can still edit the text control by double-clicking on it.
+ * @param inAllow true to enable single-click editing, false to prevent it
+ */
+void CTextEditInPlace::SetSingleClickEdit(bool inAllow)
+{
+ m_AllowSingleClickEdit = inAllow;
+}
+
+//==============================================================================
+/**
+ * Reverts the displayed text to the previous text.
+ */
+void CTextEditInPlace::RevertText()
+{
+ if (m_IsInEditMode)
+ CStringEdit::RevertText();
+}
+
+//==============================================================================
+/**
+ * Override the base class's version
+ */
+void CTextEditInPlace::DoFillBackground(CRenderer *inRenderer)
+{
+ if (m_FillBackground && !m_IsInEditMode)
+ inRenderer->FillSolidRect(QRect(0, 0, GetSize().x, GetSize().y), m_BackgroundColorNoFocus);
+}
+
+//==============================================================================
+/**
+ * Handles any non-character keys that were pressed and need to be handled.
+ *
+ * @param inChar The key that was pressed
+ * @param inFlags Indicates which modifier keys were down when event occurred
+ * @return true if this function handled the character, otherwise false
+ */
+bool CTextEditInPlace::HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ bool theMessageWasHandled = false;
+
+ switch (inChar) {
+ // We're overwriting the Escape hotkey sequence from StringEdit because we need to lose focus
+ // in TextEditInPlace, StringEdit basically does the same thing for Escape and Ctrl + Z.
+ case Qt::Key_Escape:
+ RevertText();
+ OnLoseFocus();
+ theMessageWasHandled = true;
+ break;
+
+ default:
+ theMessageWasHandled = CStringEdit::HandleSpecialChar(inChar, inFlags);
+ }
+
+ return theMessageWasHandled;
+}
diff --git a/src/Authoring/Studio/Controls/TextEditInPlace.h b/src/Authoring/Studio/Controls/TextEditInPlace.h
new file mode 100644
index 00000000..7239e6fc
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TextEditInPlace.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TEXT_EDIT_IN_PLACE_H
+#define INCLUDED_TEXT_EDIT_IN_PLACE_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StringEdit.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//==============================================================================
+/**
+ * @class CTextEditInPlace
+ */
+class CTextEditInPlace : public CStringEdit
+{
+public:
+ CTextEditInPlace();
+ virtual ~CTextEditInPlace();
+
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnLoseFocus() override;
+ void OnGainFocus() override;
+ bool CanGainFocus() override;
+ void Draw(CRenderer *inRenderer) override;
+ void SetEditable(bool inIsEditable);
+ void SetEditMode(bool inEditMode);
+ void EnterText(bool inHighlight) override;
+ void Invalidate(bool inInvalidate = true) override;
+ bool GetEditMode();
+ static long GetRightBuffer();
+ bool OnChar(const QString &inChar, Qt::KeyboardModifiers inModifiers) override;
+ bool HandleSpecialChar(unsigned int inChar, Qt::KeyboardModifiers inFlags) override;
+ virtual void SetSingleClickEdit(bool inAllow);
+
+protected:
+ void DoFillBackground(CRenderer *inRenderer) override;
+
+protected:
+ bool m_IsInEditMode; ///< If in edit mode, the user is currently editing the control
+ bool m_IsEditable; ///< Can only enter edit mode when the control is editable
+ bool m_AllowSingleClickEdit; ///< True if clicking on the control while it has focus should
+ ///cause it to enter edit mode. False to force a double-click for
+ ///entering edit mode.
+
+ void RevertText() override;
+
+private:
+ static const long s_RightBuffer;
+};
+
+#endif // INCLUDED_TEXT_EDIT_IN_PLACE_H
diff --git a/src/Authoring/Studio/Controls/TimeEdit.cpp b/src/Authoring/Studio/Controls/TimeEdit.cpp
new file mode 100644
index 00000000..3859721f
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TimeEdit.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "CoreUtils.h"
+#include "TimeEdit.h"
+#include "Renderer.h"
+#include "IDoc.h"
+#include "TimeEditDlg.h"
+
+long DELIMITER_SIZE = 2;
+long MINUTES_SIZE = 28;
+long SECONDS_SIZE = 20;
+long MILLIS_SIZE = 28;
+
+CTimeEdit::CTimeEdit(IDoc *inDoc)
+ : m_Time(0)
+ , m_MinimumTime(0)
+ , m_MaximumTime(LONG_MAX)
+{
+ AddChild(&m_Minutes);
+ AddChild(&m_Seconds);
+ AddChild(&m_Millis);
+ m_Doc = inDoc;
+}
+
+CTimeEdit::~CTimeEdit()
+{
+}
+long CTimeEdit::GetTime()
+{
+ return m_Time;
+}
+
+//=============================================================================
+/**
+ * OnMouseDown: Displays a time edit dialog, when the user clicks on the time edit box.
+ * @param inPoint stores the point clicked
+ * @param inFlags stores the control keys pressed
+ */
+bool CTimeEdit::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.ShowDialog(m_Time, 0, m_Doc, PLAYHEAD);
+ return true;
+}
+
+void CTimeEdit::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+
+ inSize.x -= DELIMITER_SIZE * 2;
+
+ m_Minutes.SetPosition(CPt(0, 0));
+ m_Minutes.SetAbsoluteSize(CPt(MINUTES_SIZE, inSize.y));
+ m_Minutes.SetAlignment(CTextEdit::RIGHT);
+ m_Minutes.SetNumDecimalPlaces(0);
+ m_Minutes.AddCommitListener(this);
+ m_Minutes.SetMin(0);
+
+ m_Seconds.SetPosition(CPt(MINUTES_SIZE + DELIMITER_SIZE, 0));
+ m_Seconds.SetAbsoluteSize(CPt(SECONDS_SIZE, inSize.y));
+ m_Seconds.SetAlignment(CTextEdit::LEFT);
+ m_Seconds.SetFixedPlaces(2);
+ m_Seconds.SetNumDecimalPlaces(0);
+ m_Seconds.AddCommitListener(this);
+ m_Seconds.SetMin(0);
+
+ m_Millis.SetPosition(CPt(MINUTES_SIZE + SECONDS_SIZE + DELIMITER_SIZE * 2, 0));
+ m_Millis.SetAbsoluteSize(CPt(MILLIS_SIZE, inSize.y));
+ m_Millis.SetAlignment(CTextEdit::LEFT);
+ m_Millis.SetFixedPlaces(3);
+ m_Millis.SetNumDecimalPlaces(0);
+ m_Millis.AddCommitListener(this);
+ m_Millis.SetMin(0);
+}
+
+//=============================================================================
+/**
+ * Draw this time.
+ * @param inRenderer the renderer to draw to.
+ */
+
+void CTimeEdit::Draw(CRenderer *inRenderer)
+{
+ // Fill in the background, otherwise we'll have junk left over from before
+ CRct theRect(GetSize());
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+ const float yPos = GetSize().y - 3;
+ inRenderer->PushPen(CStudioPreferences::GetRulerTickColor());
+ inRenderer->DrawText(static_cast<float>(m_Seconds.GetPosition().x - DELIMITER_SIZE - 1), yPos,
+ ":");
+ inRenderer->DrawText(static_cast<float>(m_Millis.GetPosition().x - DELIMITER_SIZE - 1), yPos,
+ ".");
+}
+
+//=============================================================================
+/**
+ * Set the text background color for this component.
+ * @param inColor the background color for this.
+ */
+void CTimeEdit::SetBackgroundColor(const CColor &inColor)
+{
+ m_BackgroundColor = inColor;
+
+ m_Minutes.SetBGColorNoFocus(inColor);
+ m_Seconds.SetBGColorNoFocus(inColor);
+ m_Millis.SetBGColorNoFocus(inColor);
+}
+
+//=============================================================================
+/**
+ * Lame, yes. Basically gets the estimated width of this control.
+ */
+long CTimeEdit::GetWidth()
+{
+ return MINUTES_SIZE + SECONDS_SIZE + MILLIS_SIZE + DELIMITER_SIZE * 2;
+}
+
+//=============================================================================
+/**
+ * Set the time displayed by this control.
+ * This will make sure the time is in the proper ranges then set it to the
+ * value.
+ * @param inTime the new time value for this control.
+ */
+void CTimeEdit::SetTime(long inTime)
+{
+ m_Time = inTime;
+
+ m_Minutes.SetData((float)(m_Time / (1000 * 60)));
+ m_Seconds.SetData((float)((m_Time / 1000) % 60));
+ m_Millis.SetData((float)(m_Time % 1000));
+ Invalidate();
+}
+
+void CTimeEdit::OnSetData(CControl *inControl)
+{
+ Q_UNUSED(inControl);
+
+ long theTime = ::dtol(m_Millis.GetData()) + ::dtol(m_Seconds.GetData() * 1000)
+ + ::dtol(m_Minutes.GetData() * 60 * 1000);
+
+ m_TimeListeners.FireEvent(&CTimeEditChangeListener::OnTimeChanged, theTime);
+}
+
+//=============================================================================
+/**
+ * Add a listener to this control for when the time changes.
+ * @param inListener the listener to be added to this control.
+ */
+void CTimeEdit::AddTimeChangeListener(CTimeEditChangeListener *inListener)
+{
+ m_TimeListeners.AddListener(inListener);
+}
+
+//=============================================================================
+/**
+ * Remove a time change listener from this control.
+ * @param inListener the listener to be removed from this control.
+ */
+void CTimeEdit::RemoveTimeChangeListener(CTimeEditChangeListener *inListener)
+{
+ m_TimeListeners.RemoveListener(inListener);
+}
diff --git a/src/Authoring/Studio/Controls/TimeEdit.h b/src/Authoring/Studio/Controls/TimeEdit.h
new file mode 100644
index 00000000..39c8cd3b
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TimeEdit.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIME_EDIT_H
+#define INCLUDED_TIME_EDIT_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "GenericFunctor.h"
+#include "Multicaster.h"
+#include "FloatEdit.h"
+#include "EditInPlace.h"
+#include "StringEdit.h"
+
+#include "IDoc.h"
+
+GENERIC_FUNCTOR_1(CTimeEditChangeListener, OnTimeChanged, long);
+
+class CTimeEdit : public CControl, public CCommitDataListener
+{
+public:
+ CTimeEdit(IDoc *inDoc);
+ virtual ~CTimeEdit();
+
+ void SetMinimumTime(long inMinimumTime);
+ void SetMaximumTime(long inMaximumTime);
+ void SetBackgroundColor(const CColor &inColor);
+ void SetTime(long inTime);
+ virtual void Draw(CRenderer *inRenderer);
+ long GetWidth();
+ void AddTimeChangeListener(CTimeEditChangeListener *inListener);
+ void RemoveTimeChangeListener(CTimeEditChangeListener *inListener);
+
+ virtual void SetSize(CPt inSize);
+
+ virtual void OnSetData(CControl *inControl);
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ long GetTime();
+
+protected:
+ long m_Time;
+ IDoc *m_Doc;
+ CEditInPlace<CFloatEdit> m_Minutes;
+ CEditInPlace<CFloatEdit> m_Seconds;
+ CEditInPlace<CFloatEdit> m_Millis;
+
+ CColor m_BackgroundColor;
+
+ long m_MinimumTime;
+ long m_MaximumTime;
+
+ CMulticaster<CTimeEditChangeListener *> m_TimeListeners;
+};
+#endif // INCLUDED_TIME_EDIT_H
diff --git a/src/Authoring/Studio/Controls/ToggleButton.cpp b/src/Authoring/Studio/Controls/ToggleButton.cpp
new file mode 100644
index 00000000..3271a949
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ToggleButton.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ToggleButton.h"
+
+IMPLEMENT_OBJECT_COUNTER(CToggleButton)
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CToggleButton::CToggleButton()
+ : m_IsToggleDown(false)
+{
+ ADDTO_OBJECT_COUNTER(CToggleButton)
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CToggleButton::~CToggleButton()
+{
+ REMOVEFROM_OBJECT_COUNTER(CToggleButton)
+}
+
+//=============================================================================
+/**
+ * Handles mouse click events (full mouse down and mouse up combo). Causes the
+ * button to change states.
+ * @param inListener toggle listener to be removed
+ */
+void CToggleButton::OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CButtonControl::OnMouseClick(inPoint, inFlags);
+ Toggle();
+}
+
+//=============================================================================
+/**
+ * Handles mouse down on the button. Allows a button down event to be fired
+ * by the base class, but then returns the button to the proper state, meaning
+ * that toggle buttons should not actually change states on mouse down messages
+ * even though that's what the base class does.
+ * @param inPoint location of the mouse when this event occurred
+ * @param inFlags state of modifier keys at the time that this event occurred
+ */
+bool CToggleButton::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theReturn = CButtonControl::OnMouseDown(inPoint, inFlags);
+
+ if (m_IsToggleDown)
+ SetButtonState(EBUTTONSTATE_DOWN);
+ else
+ SetButtonState(EBUTTONSTATE_UP);
+ Invalidate();
+
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Handles mouse up on the button. Fires a mouse up event, but not a toggle
+ * event, as this is handled by OnMouseClick. Button state is maintained for
+ * the toggle button instead of changing immediately like on the base class.
+ * @param inPoint location of the mouse when this event occurred
+ * @param inFlags state of modifier keys at the time that this event occurred
+ */
+void CToggleButton::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CButtonControl::OnMouseUp(inPoint, inFlags);
+
+ if (m_IsToggleDown)
+ SetButtonState(EBUTTONSTATE_DOWN);
+ else
+ SetButtonState(EBUTTONSTATE_UP);
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Changes the state of the button. If the button is currently down, it will
+ * be changed to up and vice versa. An event is fired to notify interested
+ * listeners that the button was toggled.
+ */
+void CToggleButton::Toggle()
+{
+ m_IsToggleDown = !m_IsToggleDown;
+ if (m_IsToggleDown)
+ SetButtonState(EBUTTONSTATE_DOWN);
+ else
+ SetButtonState(EBUTTONSTATE_UP);
+
+ SigToggle(this, GetButtonState());
+
+ Invalidate();
+}
+
+void CToggleButton::SetToggleState(bool inIsDown)
+{
+ if (inIsDown != m_IsToggleDown) {
+ m_IsToggleDown = inIsDown;
+ SetButtonState(inIsDown ? EBUTTONSTATE_DOWN : EBUTTONSTATE_UP);
+ }
+}
diff --git a/src/Authoring/Studio/Controls/ToggleButton.h b/src/Authoring/Studio/Controls/ToggleButton.h
new file mode 100644
index 00000000..59feafb5
--- /dev/null
+++ b/src/Authoring/Studio/Controls/ToggleButton.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TOGGLE_BUTTON_H
+#define INCLUDED_TOGGLE_BUTTON_H 1
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ButtonControl.h"
+
+//==============================================================================
+// Functors
+//==============================================================================
+
+//=============================================================================
+/**
+ * Class for making toggle buttons. A toggle button changes state each time a
+ * full mouse click is received. When you click the mouse on a toggle button,
+ * it will enter the "down" state. When you click it again, the toggle button
+ * will enter the "up" state. This differs from a regular button, which only
+ * enters the "down" state while the mouse is being held down, then immediately
+ * returns to the "up" state when the mouse is released.
+ */
+class CToggleButton : public CButtonControl
+{
+public:
+ CToggleButton();
+ virtual ~CToggleButton();
+
+ DEFINE_OBJECT_COUNTER(CToggleButton)
+
+ void OnMouseClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ virtual void Toggle();
+
+ virtual void SetToggleState(bool inIsDown);
+ bool GetToggleState() const { return m_IsToggleDown; }
+
+ //=============================================================================
+ /**
+ * Functor for handling button toggle messages. The message will be fired to
+ * interested listeners when a full button click occurs on this button. If you
+ * want to be a listener for button toggle events, you must define an
+ * OnButtonToggle function with the following parameters.
+ * @param CToggleButton* pointer to the button that generated the event
+ * @param EButtonState the state of the button as a result of this event
+ */
+ boost::signal2<void, CToggleButton *, CButtonControl::EButtonState> SigToggle;
+
+protected:
+ // protected to make fools use SetToggleState instead.
+ void SetButtonState(EButtonState inState) override { CButtonControl::SetButtonState(inState); }
+
+ bool m_IsToggleDown;
+};
+
+#endif // INCLUDED_TOGGLE_BUTTON_H
diff --git a/src/Authoring/Studio/Controls/TreeControl.cpp b/src/Authoring/Studio/Controls/TreeControl.cpp
new file mode 100644
index 00000000..892c2086
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TreeControl.cpp
@@ -0,0 +1,749 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TreeControl.h"
+#include "Renderer.h"
+#include "HotKeys.h"
+#include "MasterP.h"
+#include "StudioPreferences.h"
+#include "StudioErrorIDs.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTreeControl::CTreeControl()
+ : m_AllowMultipleSelection(false)
+ , m_Refresh(true)
+ , m_SortFlag(false)
+{
+
+ m_BGColor = CStudioPreferences::GetBaseColor();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTreeControl::~CTreeControl()
+{
+ // Just clear out our lists, deletion is handled by whoever created the items.
+ m_ItemList.clear();
+ m_SelectedItemList.clear();
+}
+
+//=============================================================================
+/**
+ * Sets the background color of this control.
+ * @param inColor new background color
+ */
+void CTreeControl::SetBackgroundColor(const CColor &inColor)
+{
+ m_BGColor = inColor;
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Draws the control.
+ */
+void CTreeControl::Draw(CRenderer *inRenderer)
+{
+ inRenderer->FillSolidRect(QRect(QPoint(0, 0), GetSize()), m_BGColor);
+}
+
+//=============================================================================
+/**
+ * Find the item that this item should be added after to maintian sort order.
+ */
+CTreeItem *CTreeControl::FindPrevSortSibling(CTreeItem *, CTreeItem *)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ UIC_THROW(E_FAIL); // this is ass
+#endif
+ return NULL;
+}
+
+//=============================================================================
+/**
+ * Find the item that this item should be before after to maintian sort order.
+ */
+CTreeItem *CTreeControl::FindNextSortSibling(CTreeItem *inParent, CTreeItem *inChild)
+{
+ CTreeItem *theSortItem = nullptr;
+
+ if (inParent) {
+ theSortItem = inParent->FindNextSortSibling(inChild);
+ } else {
+ // No items in the list - return nullptr (because we don't care)
+ if (m_ItemList.size()) {
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ // Item in the list
+ theSortItem = *thePos;
+ if (IsItemLess(inChild, theSortItem))
+ break;
+ }
+
+ // Last item in the list
+ if (thePos == m_ItemList.end())
+ theSortItem = nullptr;
+ }
+ }
+
+ return theSortItem;
+}
+
+//=============================================================================
+/**
+ * Adds a tree item to the tree control. The child is automatically added to
+ * the end of the list under the specified parent. Once you add a tree item,
+ * to this tree control. You must call the remove functions to take it out of
+ * the tree control, after which point, it is safe for you to delete it.
+ * @param inParent parent of the tree item or nullptr if the item is to be a root
+ * @param inChild the child item to be added
+ */
+void CTreeControl::AddItem(CTreeItem *inParent, CTreeItem *inChild)
+{
+ CTreeItem *theBeforeItem = nullptr;
+
+ if (IsSorting())
+ theBeforeItem = FindNextSortSibling(inParent, inChild);
+
+ AddItemBefore(inParent, inChild, theBeforeItem);
+}
+
+//=============================================================================
+/**
+ * Same as AddItem( ), except that you can specify where to put the child in relation
+ * to its siblings.
+ * @param inParent parent of the new item, or nullptr if adding a root level item
+ * @param inChild new child to be added
+ * @param inBefore should be a child of inParent, in which case, inChild is added before it;
+ * can be nullptr to indicate that inChild needs to go at the end of the inParent's children.
+ */
+void CTreeControl::AddItemBefore(CTreeItem *inParent, CTreeItem *inChild, CTreeItem *inBefore)
+{
+ if (inParent)
+ inParent->AddItem(inChild, inBefore);
+ else
+ AddToRootItemList(inChild, inBefore);
+
+ CTreeItem *theControlBefore = inBefore;
+ if (inParent && !inBefore)
+ theControlBefore = RecurseGetControlAfter(inParent);
+
+ AddToHierarchy(inChild, theControlBefore, true);
+}
+
+//=============================================================================
+/**
+ * Same as AddItem( ), except that you can specify where to put the child in relation
+ * to its siblings.
+ * @param inParent parent of the new item, or nullptr if adding a root level item
+ * @param inChild new child to be added
+ * @param inAfter should be a child of inParent, in which case, inChild is added after it
+ */
+void CTreeControl::AddItemAfter(CTreeItem *inParent, CTreeItem *inChild, CTreeItem *inAfter)
+{
+ CTreeItem *theItemBefore = nullptr;
+ CTreeItem *theControlBefore = nullptr;
+
+ theItemBefore = GetSiblingAfter(inAfter);
+ theControlBefore = RecurseGetControlAfter(inAfter);
+
+ if (inParent)
+ inParent->AddItem(inChild, theItemBefore);
+ else
+ AddToRootItemList(inChild, theItemBefore);
+
+ AddToHierarchy(inChild, theControlBefore, true);
+}
+
+//=============================================================================
+/**
+ * Simply detaches inItem from the tree. Provided so that subclasses can
+ * override this function to actually perform item deletion if necessary.
+ * @param inItem Item to be removed
+ */
+void CTreeControl::RemoveItem(CTreeItem *inItem)
+{
+ Detach(inItem);
+}
+
+//=============================================================================
+/**
+ * Removes all currently selected items.
+ * @param inItem Item to be removed
+ */
+void CTreeControl::RemoveSelectedItems()
+{
+ // Iterate through the selected items, removing each one
+ CTreeItem::TItemList::iterator thePos = m_SelectedItemList.begin();
+ for (; thePos != m_SelectedItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ RemoveItem(theItem);
+ }
+ m_SelectedItemList.clear();
+}
+
+//=============================================================================
+/**
+ * Removes all currently selected items.
+ * @param inItem Item to be removed
+ */
+void CTreeControl::RemoveAllItems()
+{
+ // Iterate through the selected items, removing each one
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+
+ while (thePos != m_ItemList.end()) {
+ CTreeItem *theItem = *thePos;
+ RemoveItem(theItem);
+ thePos = m_ItemList.begin();
+ }
+ ASSERT(m_ItemList.empty() == true);
+}
+
+//=============================================================================
+/**
+ * Creates a break in the tree. The item being detached is disconnected from
+ * it's parent (or from the tree control itself if it has no parent). The
+ * releations between branches below inItem are maintained internally by
+ * each child item. However, inItem and all of it's children are removed
+ * from the control hierarchy (they won't be drawn). This is useful if you
+ * want to move sections of the tree around without deleting anything.
+ * @param inItem item to detach
+ */
+void CTreeControl::Detach(CTreeItem *inItem)
+{
+ inItem->Detach();
+
+ if (inItem->IsRootItem())
+ RemoveFromRootItemList(inItem);
+
+ RemoveFromHierarchy(inItem, true);
+}
+
+//=============================================================================
+/**
+ * Allows you to enable or disable multiple selection for this tree control.
+ * @param inAllow true to allow multiple selection, false to only allow single selection
+ */
+void CTreeControl::SetAllowMultipleSelection(bool inAllow)
+{
+ m_AllowMultipleSelection = inAllow;
+}
+
+//=============================================================================
+/**
+ * @return true if multiple selection is enabled, false if only single
+ * selection is enabled.
+ */
+bool CTreeControl::GetAllowMultipleSelection()
+{
+ return m_AllowMultipleSelection;
+}
+
+//=============================================================================
+/**
+ * @return the number of items at the root level of this tree control
+ */
+long CTreeControl::GetNumRootItems()
+{
+ return (long)m_ItemList.size();
+}
+
+//=============================================================================
+/**
+ * Get the root item at the specified index
+ */
+CTreeItem *CTreeControl::GetRootItem(long inIndex)
+{
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+ std::advance(thePos, inIndex);
+
+ if (thePos != m_ItemList.end())
+ return (*thePos);
+
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Gets iterators for traversing the list of selected tree items.
+ * @param outListBegin returns an iterator to the beginning of the selected item list
+ * @param outListEnd returns an iterator to the end of the selected item list
+ */
+void CTreeControl::GetSelectionIterators(CTreeItem::TItemList::iterator &outListBegin,
+ CTreeItem::TItemList::iterator &outListEnd)
+{
+ outListBegin = m_SelectedItemList.begin();
+ outListEnd = m_SelectedItemList.end();
+}
+
+//=============================================================================
+/**
+ * @return number of selected items in this tree control
+ */
+long CTreeControl::GetNumSelectedItems()
+{
+ return (long)m_SelectedItemList.size();
+}
+
+//=============================================================================
+/**
+ * @return the first selected item in the tree control
+ */
+CTreeItem *CTreeControl::GetFirstSelectedItem()
+{
+ CTreeItem::TItemList::iterator theBegin = m_SelectedItemList.begin();
+ if (theBegin != m_SelectedItemList.end())
+ return (*theBegin);
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Selects the specified tree item and adds the item to the selection list.
+ * Multiple selection is handled via inKeyModifiers and setting of the multiple
+ * selection flag on this class.
+ * @param inItem item to be selected
+ * @param inKeyModifiers optionally indicates the state of shift, ctrl, etc. for multiple selection
+ */
+void CTreeControl::Select(CTreeItem *inItem, long inKeyModifiers /*=0*/)
+{
+ ASSERT(inItem != nullptr);
+
+ bool theCtrlKeyIsDown =
+ (inKeyModifiers & CHotKeys::MODIFIER_CONTROL) == CHotKeys::MODIFIER_CONTROL;
+ bool theShiftKeyIsDown =
+ (inKeyModifiers & CHotKeys::MODIFIER_SHIFT) == CHotKeys::MODIFIER_SHIFT;
+
+ // clears all existing selection if multiple selection is not allowed
+ // If multiple selection is not enabled or neither control nor shift is down
+ if (!m_AllowMultipleSelection || (!theCtrlKeyIsDown && !theShiftKeyIsDown)) {
+ CTreeItem::TItemList::iterator thePos = m_SelectedItemList.begin();
+ // Iterate through all the selected items and deselect them
+ for (; thePos != m_SelectedItemList.end();) {
+ CTreeItem *theItem = *thePos;
+ if (theItem->IsSelected() && inItem != theItem) {
+ theItem->SetSelected(false);
+ thePos = m_SelectedItemList.erase(thePos); // remove unselected item from list
+ } else
+ ++thePos;
+ }
+ }
+
+ // Don't bother selecting the item if it is already selected
+ if (!inItem->IsSelected()) {
+ inItem->SetSelected(true);
+ m_SelectedItemList.push_back(inItem);
+
+ // Tell all TreeItemSelectionListeners that the item was selected
+ FireItemSelected(inItem);
+ }
+
+ if (theShiftKeyIsDown) {
+ // TODO: advanced selection
+ }
+}
+
+//=============================================================================
+/**
+ * Deselects the specified item, if it is selected.
+ * @param inItem item to be deselected
+ */
+void CTreeControl::Deselect(CTreeItem *inItem)
+{
+ // Run through the list and look for the specified item
+ bool theItemWasFound = false;
+ CTreeItem::TItemList::iterator thePos = m_SelectedItemList.begin();
+ CTreeItem::TItemList::iterator theEnd = m_SelectedItemList.end();
+ for (; thePos != theEnd; ++thePos) {
+ CTreeItem *theItem = *thePos;
+ if (theItem == inItem) {
+ theItemWasFound = true;
+ break;
+ }
+ }
+
+ // If the item was found, remove it from the selected item list
+ if (theItemWasFound) {
+ m_SelectedItemList.erase(thePos);
+ // Tell the item it is no longer selected
+ inItem->SetSelected(false);
+ }
+}
+
+//=============================================================================
+/**
+ * Deselects all currently selected items.
+ */
+void CTreeControl::DeselectAll()
+{
+ CTreeItem::TItemList::iterator thePos = m_SelectedItemList.begin();
+ CTreeItem::TItemList::iterator theEnd = m_SelectedItemList.end();
+ for (; thePos != theEnd; ++thePos) {
+ CTreeItem *theItem = *thePos;
+ theItem->SetSelected(false);
+ }
+ m_SelectedItemList.clear();
+}
+
+//=============================================================================
+/**
+ * Expand all nodes to the specified item.
+ */
+void CTreeControl::ExpandTo(CTreeItem *inItem)
+{
+ // Turn off tree refreshing
+ bool theAllowRefresh = GetAllowRefresh();
+ SetAllowRefresh(false);
+
+ // Expand the specified item
+ inItem->Expand();
+
+ // Expand the parents
+ CTreeItem *theParent = inItem->GetParentItem();
+ if (theParent)
+ ExpandTo(theParent);
+
+ // Restore tree refreshing
+ SetAllowRefresh(theAllowRefresh);
+}
+
+//=============================================================================
+/**
+ * Expand all nodes from this item onwards.
+ */
+void CTreeControl::ExpandFrom(CTreeItem *inItem)
+{
+ // Turn off tree refreshing
+ bool theAllowRefresh = GetAllowRefresh();
+ SetAllowRefresh(false);
+
+ // Expand the item's immediate children
+ inItem->Expand();
+
+ CTreeItem::TItemList::iterator theBegin;
+ CTreeItem::TItemList::iterator theEnd;
+
+ inItem->GetItemIterator(theBegin, theEnd);
+
+ // Expand all children
+ std::for_each(theBegin, theEnd, std::bind1st(std::mem_fun(&CTreeControl::ExpandFrom), this));
+
+ // Restore refresh state
+ SetAllowRefresh(theAllowRefresh);
+}
+
+//=============================================================================
+/**
+ * Collapse all items in the tree.
+ */
+void CTreeControl::CollapseAll()
+{
+ // Not implemented
+ UIC_THROW(STUDIO_E_FAIL);
+}
+
+//=============================================================================
+/**
+ * Allows or disallows calls to RecalcLayout. This is useful if you are adding
+ * a bulk amount of items to the tree control at once. You can simply call
+ * this function with false, add your items, the call this function again with
+ * true. In this way, you don't incur a call to RecalcLayout for each item
+ * added, just one call at the end when all the items are added.
+ * @param inAllowRefresh true to allow RecalcLayout calls, false to prevent them
+ * from doing anything.
+ */
+void CTreeControl::SetAllowRefresh(bool inAllowRefresh)
+{
+ m_Refresh = inAllowRefresh;
+}
+
+//=============================================================================
+/**
+ * Tells you whether or not a call to RecalcLayout will actually result in
+ * resizing and repositioning the items in the tree.
+ * @return true if the tree control is currently allowing recalc layout calls
+ * to process, otherwise false.
+ */
+bool CTreeControl::GetAllowRefresh()
+{
+ return m_Refresh;
+}
+
+//=============================================================================
+/**
+ * Helper function for finding the tree item that is the next sibling after
+ * the specified item. If inItem has a parent, the parent's list is searched,
+ * otherwise, we just search the root item list. If there is no sibling, this
+ * function recurses on the parent (if there is one) all the way up the tree
+ * until we reach the top. If there is not a control after the specified one,
+ * this function returns nullptr.
+ * @param inItem Item whose sibling we are searching for
+ * @return the sibling that occurs after inItem in the tree hierarchy
+ */
+CTreeItem *CTreeControl::GetSiblingAfter(CTreeItem *inItem)
+{
+ UICPROFILE(GetSiblingAfter);
+
+ ASSERT(inItem);
+
+ CTreeItem *theSibling = nullptr;
+ CTreeItem *theParent = inItem->GetParentItem();
+
+ // Declare the iterators, then use them on either list
+ CTreeItem::TItemList::reverse_iterator thePos;
+ CTreeItem::TItemList::reverse_iterator theListEnd;
+
+ // If we have a parent, get the iterators from the parent
+ if (theParent) {
+ theParent->GetReverseItemIterator(thePos, theListEnd);
+ }
+ // If we don't have a parent, we must be searching for a root-level item, so search the tree
+ // control's list
+ else {
+ thePos = m_ItemList.rbegin();
+ theListEnd = m_ItemList.rend();
+ }
+
+ // Iterate through the list
+ bool theItemWasFound = false;
+ CTreeItem *thePreviousItem = nullptr;
+ for (; thePos != theListEnd; ++thePos) {
+ CTreeItem *theCurrentItem = *thePos;
+
+ // If we found the item we are looking for, break out of the loop
+ if (theCurrentItem == inItem) {
+ theItemWasFound = true;
+ break;
+ }
+
+ thePreviousItem = theCurrentItem;
+ }
+
+ // If the item we were looking for was found, the sibling is probably contained in
+ // thePreviousItem
+ if (theItemWasFound)
+ theSibling = thePreviousItem;
+
+ return theSibling;
+}
+
+//=============================================================================
+/**
+ * Helper function for fetching the control after inItem. If inItem has siblings,
+ * those are searched to determine if there is a sibling after inItem. If no
+ * sibling is found, this function recurses, this time searching for a sibling
+ * of inItem->GetParentItem( ); assuming that inItem has a parent. In this
+ * way, we determine the control that occurs after inItem in the Control
+ * hierarchy.
+ * @param inItem we are searching for the item after this one
+ * @return the item after inItem in the control hierarchy or nullptr if there is no item after inItem.
+ */
+CTreeItem *CTreeControl::RecurseGetControlAfter(CTreeItem *inItem)
+{
+ UICPROFILE(RecurseGetControlAfter);
+
+ ASSERT(inItem);
+
+ CTreeItem *theControlAfter = GetSiblingAfter(inItem);
+ CTreeItem *theParent = inItem->GetParentItem();
+
+ // If we still haven't found a sibling, and we have a valid parent, recursively search for a
+ // sibling of the parent
+ if (!theControlAfter && theParent)
+ theControlAfter = RecurseGetControlAfter(theParent);
+
+ return theControlAfter;
+}
+
+//=============================================================================
+/**
+ * Protected function for adding items to the root level of this control.
+ * @param inItem new item to be added
+ * @param inInsertBefore item to insert inItem before in the list, or
+ * nullptr to insert the item at the end of the list
+ */
+void CTreeControl::AddToRootItemList(CTreeItem *inItem, CTreeItem *inInsertBefore)
+{
+ // If an item to insert before is specified
+ if (inInsertBefore) {
+ // Go through the list and insert inItem before inInsertBefore
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theCurrentItem = *thePos;
+ if (theCurrentItem == inInsertBefore) {
+ m_ItemList.insert(thePos, inItem);
+ break;
+ }
+ }
+ }
+ // If no item is specified for inserting before, add inItem to the end of the list
+ else {
+ m_ItemList.push_back(inItem);
+ }
+}
+
+//=============================================================================
+/**
+ * Protected function for removing items from the root level of this control.
+ * The item is not deleted and nothing is done to the children of the item.
+ * @param inItem item to be removed from the list
+ */
+void CTreeControl::RemoveFromRootItemList(CTreeItem *inItem)
+{
+ bool theItemWasFound = false;
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ if (theItem == inItem) {
+ theItemWasFound = true;
+ break;
+ }
+ }
+
+ if (theItemWasFound) {
+ m_ItemList.erase(thePos);
+ }
+}
+
+//=============================================================================
+/**
+ * Protected function for adding items to the root level of this control. No
+ * lists are updated, this is merely for updating the control hierarchy.
+ * @param inItem item to be added to the control hierarchy
+ * @param inBefore item to insert inItem before in the control hierarchy or nullptr
+ * to insert at the end of the control hierarchy.
+ * @param inIsRecursive true to recursively add all children of inItem to hierarchy
+ */
+void CTreeControl::AddToHierarchy(CTreeItem *inItem, CTreeItem *inBefore, bool inIsRecursive)
+{
+ AddChild(inItem, inBefore);
+
+ if (inIsRecursive) {
+ bool theAllowRefresh = GetAllowRefresh();
+ SetAllowRefresh(false);
+
+ if (inItem->IsContainer()) {
+ CTreeItem::TItemList::iterator thePos;
+ CTreeItem::TItemList::iterator theEnd;
+ inItem->GetItemIterator(thePos, theEnd);
+ for (; thePos != theEnd; ++thePos) {
+ CTreeItem *theChild = *thePos;
+ AddToHierarchy(theChild, inBefore, inIsRecursive);
+ }
+ }
+
+ SetAllowRefresh(theAllowRefresh);
+ }
+}
+
+//=============================================================================
+/**
+ * Protected function for removing an item from the control hierarchy. The
+ * item is not deleted, but it will no longer be drawn.
+ * @param inItem Item to remove
+ * @param inIsRecursive true to recursively call this function on all of the item's children
+ */
+void CTreeControl::RemoveFromHierarchy(CTreeItem *inItem, bool inIsRecursive)
+{
+ if (inIsRecursive) {
+ bool theAllowRefresh = GetAllowRefresh();
+ SetAllowRefresh(false);
+
+ if (inItem->IsContainer()) {
+ CTreeItem::TItemList::iterator thePos;
+ CTreeItem::TItemList::iterator theEnd;
+ inItem->GetItemIterator(thePos, theEnd);
+ for (; thePos != theEnd; ++thePos) {
+ CTreeItem *theChild = *thePos;
+ RemoveFromHierarchy(theChild, inIsRecursive);
+ }
+ }
+
+ SetAllowRefresh(theAllowRefresh);
+ }
+
+ Deselect(inItem);
+ RemoveChild(inItem);
+}
+
+//=============================================================================
+/**
+ * Private function for adding children to the Control hierarchy. Only this
+ * class should call this function. Everyone else needs to go through AddItem( ).
+ * @param inControl new control to be added
+ * @param inInsertBefore control to insert the new one before in the hierarchy
+ */
+void CTreeControl::AddChild(CControl *inControl, CControl *inInsertBefore)
+{
+ Q3DStudio::Control::SVerticalLazyFlow::AddChild(inControl, inInsertBefore);
+}
+
+//==============================================================================
+/**
+ * Add a CTreeItemSelectionListener to this control's list of
+ * CTreeItemSelectionListeners.
+ *
+ * @param inListener CTreeItemSelectionListener to add to m_SelectionListeners
+ */
+void CTreeControl::AddSelectionListener(CTreeItemSelectionListener *inListener)
+{
+ m_SelectionListeners.AddListener(inListener);
+}
+
+//==============================================================================
+/**
+ * Remove a CTreeItemSelectionListener from this control's list of
+ * CTreeItemSelectionListeners.
+ *
+ * @param inListener CTreeItemSelectionListener to remove from m_SelectionListeners
+ */
+void CTreeControl::RemoveSelectionListener(CTreeItemSelectionListener *inListener)
+{
+ m_SelectionListeners.RemoveListener(inListener);
+}
+
+void CTreeControl::FireItemSelected(CTreeItem *inItem)
+{
+ OnTreeItemSelected(inItem);
+ m_SelectionListeners.FireEvent(&CTreeItemSelectionListener::OnTreeItemSelected, inItem);
+}
diff --git a/src/Authoring/Studio/Controls/TreeControl.h b/src/Authoring/Studio/Controls/TreeControl.h
new file mode 100644
index 00000000..e9958322
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TreeControl.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TREE_CONTROL_H
+#define INCLUDED_TREE_CONTROL_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "LazyFlow.h"
+#include "TreeItem.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class CTest_TreeControl;
+
+//==============================================================================
+// Functor
+//==============================================================================
+/// This means that any class that wants be informed when TreeItems are selected
+/// needs to implement the CTreeItemSelectionListener interface, and the
+/// void OnTreeItemSelected( CTreeItem* ) method
+/// The CTreeItem is the item that was selected
+GENERIC_FUNCTOR_1(CTreeItemSelectionListener, OnTreeItemSelected, CTreeItem *);
+
+//=============================================================================
+/**
+ * Custom tree control class. You need to call one of the AddItem*( ) functions
+ * to add tree items to this control. Multiple selection can be enabled using
+ * the provided functions. The tree control maintains a list of all the root
+ * level items. It is also responsible for managing the separate "Control
+ * hierarchy."
+ */
+class CTreeControl : public Q3DStudio::Control::SVerticalLazyFlow
+{
+public:
+ CTreeControl();
+ virtual ~CTreeControl();
+ void SetBackgroundColor(const ::CColor &inColor);
+ void Draw(CRenderer *inRenderer) override;
+ virtual void AddItem(CTreeItem *inParent, CTreeItem *inChild);
+ virtual void AddItemBefore(CTreeItem *inParent, CTreeItem *inChild, CTreeItem *inBefore);
+ virtual void AddItemAfter(CTreeItem *inParent, CTreeItem *inChild, CTreeItem *inAfter);
+ virtual void RemoveItem(CTreeItem *inItem);
+ virtual void RemoveSelectedItems();
+ virtual void RemoveAllItems();
+ virtual void Detach(CTreeItem *inItem);
+ void SetAllowMultipleSelection(bool inAllow);
+ bool GetAllowMultipleSelection();
+ void GetSelectionIterators(CTreeItem::TItemList::iterator &outListBegin,
+ CTreeItem::TItemList::iterator &outListEnd);
+ long GetNumSelectedItems();
+ CTreeItem *GetFirstSelectedItem();
+ virtual void Select(CTreeItem *inItem, long inKeyModifiers = 0);
+ virtual void Deselect(CTreeItem *inItem);
+ virtual void DeselectAll();
+ void SetAllowRefresh(bool inAllowRefresh);
+ bool GetAllowRefresh();
+ long GetNumRootItems();
+ CTreeItem *GetRootItem(long inIndex);
+ virtual void ExpandTo(CTreeItem *inItem);
+ virtual void ExpandFrom(CTreeItem *inItem);
+ virtual void CollapseAll();
+ virtual void SetSorting(bool inSort) { m_SortFlag = inSort; }
+ virtual bool IsSorting() { return m_SortFlag; }
+
+ virtual bool IsItemGreater(CTreeItem *, CTreeItem *) { return true; }
+ virtual bool IsItemLess(CTreeItem *, CTreeItem *) { return false; }
+
+ // SelectionListener methods
+ void AddSelectionListener(CTreeItemSelectionListener *inListener);
+ void RemoveSelectionListener(CTreeItemSelectionListener *inListener);
+ void FireItemSelected(CTreeItem *inItem);
+
+ // Override to hear select
+ virtual void OnTreeItemSelected(CTreeItem *) {}
+ virtual void OnItemExpanding(CTreeItem *) {}
+ virtual void OnItemExpanded(CTreeItem *) { NotifyParentNeedsLayout(); }
+ virtual void OnItemCollapsing(CTreeItem *) {}
+ virtual void OnItemCollapsed(CTreeItem *) { NotifyParentNeedsLayout(); }
+
+protected:
+ // Member Vars
+ ::CColor m_BGColor; ///< Specifies the background color of this control
+ bool m_AllowMultipleSelection; ///< If true, multiple selection is enabled for this control
+ CTreeItem::TItemList m_ItemList; ///< List of all root level tree items
+ CTreeItem::TItemList m_SelectedItemList; ///< List of all selected tree items, regardless of
+ ///whether or not they are root level
+ bool m_Refresh;
+ bool m_SortFlag;
+
+ // Member Functions
+ CTreeItem *GetSiblingAfter(CTreeItem *inItem);
+ CTreeItem *RecurseGetControlAfter(CTreeItem *inItem);
+ CTreeItem *FindPrevSortSibling(CTreeItem *inParent, CTreeItem *inChild);
+ CTreeItem *FindNextSortSibling(CTreeItem *inParent, CTreeItem *inChild);
+ void AddToRootItemList(CTreeItem *inItem, CTreeItem *inInsertBefore);
+ void RemoveFromRootItemList(CTreeItem *inItem);
+ void AddToHierarchy(CTreeItem *inItem, CTreeItem *inBefore, bool inIsRecursive);
+ void RemoveFromHierarchy(CTreeItem *inItem, bool inIsRecursive);
+
+private:
+ /// Private because you can only add CTreeItems to this control with AddItem( ).
+ void AddChild(CControl *inControl, CControl *inInsertBefore = nullptr) override;
+
+ CMulticaster<CTreeItemSelectionListener *>
+ m_SelectionListeners; ///< List of listeners who want to know when a TreeItem is selected
+};
+#endif // INCLUDED_TREE_CONTROL_H
diff --git a/src/Authoring/Studio/Controls/TreeItem.cpp b/src/Authoring/Studio/Controls/TreeItem.cpp
new file mode 100644
index 00000000..03a41530
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TreeItem.cpp
@@ -0,0 +1,939 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TreeItem.h"
+#include "TreeControl.h"
+#include "Renderer.h"
+#include "SIcon.h"
+#include "ResourceCache.h"
+#include "HotKeys.h"
+#include "MasterP.h"
+#include "StudioPreferences.h"
+
+IMPLEMENT_OBJECT_COUNTER(CTreeItem)
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inTreeControl the tree control that this item will belong to
+ */
+CTreeItem::CTreeItem(CTreeControl *inTreeControl)
+ : m_TreeControl(inTreeControl)
+ , m_Parent(NULL)
+ , m_Toggle(NULL)
+ , m_Name(NULL)
+ , m_Icon(NULL)
+ , m_ControlGap(2)
+ , m_IndentLevel(0)
+ , m_IndentSize(0)
+ , m_IsExpanded(false)
+ , m_IsSelected(false)
+ , m_ShowVisibleSelection(true)
+ , m_Color(CStudioPreferences::GetBaseColor())
+ , m_TextColor(CStudioPreferences::GetNormalColor())
+{
+ ADDTO_OBJECT_COUNTER(CTreeItem)
+
+ // Set up some of our flow layout properties
+ SetFlowDirection(FLOW_HORIZONTAL);
+ SetAlignment(ALIGN_VERT_NEITHER, ALIGN_LEFT);
+ SetGapBetweenChildren(m_ControlGap);
+ SetMaximumSize(CPt(LONG_MAX, CStudioPreferences::GetDefaultTextEditSize()));
+ SetMinimumSize(CPt(0, CStudioPreferences::GetDefaultTextEditSize()));
+
+ // Create the toggle
+ CreateToggle();
+
+ // Icon control
+ m_Icon = new CSIcon();
+
+ // Name control
+ m_Name = new CTextEditInPlace();
+ m_Name->SetAlignment(CTextEditInPlace::LEFT);
+ m_Name->SetTextColor(m_TextColor);
+ m_Name->SetBGColorNoFocus(CStudioPreferences::GetSelectColor());
+ m_Name->SetFillBackground(false);
+ m_Name->AllowAutoSize(true);
+
+ // Name change listener
+ m_NameChangeListener =
+ new CSpecificCCommitDataListener<CTreeItem>(this, &CTreeItem::OnNameChanged);
+ m_Name->AddCommitListener(m_NameChangeListener);
+
+ // Toggle listener
+ m_Toggle->SigToggle.connect(std::bind(&CTreeItem::OnToggleExpansion, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ // Add all the controls to the flow
+ AddChild(m_Toggle);
+ AddChild(m_Icon);
+ AddChild(m_Name);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTreeItem::~CTreeItem()
+{
+ m_Name->RemoveCommitListener(m_NameChangeListener);
+ delete m_NameChangeListener;
+
+ // Clear out our list of subitems, but don't delete anything (whoever called new should do the
+ // delete)
+ m_ItemList.clear();
+ delete m_Toggle;
+ delete m_Icon;
+ delete m_Name;
+
+ REMOVEFROM_OBJECT_COUNTER(CTreeItem)
+}
+
+//=============================================================================
+/**
+ * Fills in the background color of this control.
+ * @param inRenderer renderer to draw to
+ */
+void CTreeItem::Draw(CRenderer *inRenderer)
+{
+ inRenderer->FillSolidRect(QRect({}, GetSize()), m_Color);
+}
+
+//=============================================================================
+/**
+ * Allows you to set the background color of this control.
+ * @param inColor new background color for this control
+ */
+void CTreeItem::SetBackgroundColor(const CColor &inColor)
+{
+ m_Color = inColor;
+ Invalidate();
+}
+
+void CTreeItem::SetTextColor(const CColor &inColor)
+{
+ m_Name->SetTextColor(inColor);
+ m_TextColor = inColor;
+ Invalidate();
+}
+
+void CTreeItem::SetTextBGFocusColor(const ::CColor &inColor)
+{
+ m_Name->SetBGColorNoFocus(inColor);
+ Invalidate();
+}
+//=============================================================================
+/**
+ * @return the current background color of this control
+ */
+CColor CTreeItem::GetBackgroundColor()
+{
+ return m_Color;
+}
+
+//=============================================================================
+/**
+ * Sets the parent of this tree item. The parent is the tree item that can
+ * be toggled to hide or show this item. You can set this value to nullptr to
+ * specify that this item is a root item, thus making it always be visible.
+ * @param inParent parent of this item
+ */
+void CTreeItem::SetParentItem(CTreeItem *inParent)
+{
+ m_Parent = inParent;
+}
+
+//=============================================================================
+/**
+ * Allows you to access the parent of this tree item. Note that this parent is
+ * not the same as parenting in the Control hierarchy. The parent is the tree
+ * item that can be toggled to hide or show this item.
+ * @return the parent of this tree item, or nullptr if this is a root level item.
+ */
+CTreeItem *CTreeItem::GetParentItem()
+{
+ return m_Parent;
+}
+
+//=============================================================================
+/**
+ * Allows you to change the icon associated with this tree item.
+ * @param inIcon name of the icon in normal state
+ * @param inSelectedIcon name of the icon to be displayed when this item is selected
+ */
+void CTreeItem::SetIcon(const QString &inIcon, const QString &inSelectedIcon)
+{
+ SetIcon(CResourceCache::GetInstance()->GetBitmap(inIcon),
+ CResourceCache::GetInstance()->GetBitmap(inSelectedIcon));
+}
+
+//=============================================================================
+/**
+ * Allows you to change the icon associated with this tree item.
+ */
+void CTreeItem::SetIcon(const QPixmap &inNormalIcon, const QPixmap &inSelectedIcon)
+{
+ m_NormalIcon = inNormalIcon;
+ m_SelectedIcon = inSelectedIcon;
+
+ m_Icon->SetImage(m_NormalIcon);
+}
+
+//=============================================================================
+/**
+ * Allows you to specifiy whether or not the name of this tree item can be edited.
+ * If set to true, the user can edit an item's name by double-clicking on it.
+ * @param inIsEditable true to specify that the user is allowed to edit this
+ * item, otherwise false to prevent double-click editing.
+ */
+void CTreeItem::SetIsNameEditable(bool inIsEditable)
+{
+ m_Name->SetEditable(inIsEditable);
+}
+
+//=============================================================================
+/**
+ * Sets the text displayed by this tree item. This does not trigger a name
+ * change event.
+ * @param inText text to be displayed
+ */
+void CTreeItem::SetText(const Q3DStudio::CString &inText)
+{
+ m_Name->SetData(inText);
+}
+
+//=============================================================================
+/**
+ * Gets the text displayed by this tree item.
+ * @return the text that is displayed.
+ */
+Q3DStudio::CString CTreeItem::GetText()
+{
+ return m_Name->GetString();
+}
+
+//=============================================================================
+/**
+ * Called when the name of the tree item is changed. Notifies any interested
+ * listeners. This is only for when the name control is edited directly. If
+ * you call SetText directly or change the text by other means, no listeners
+ * are notified.
+ * @param inControl control that generated the name change message (not used)
+ */
+void CTreeItem::OnNameChanged(CControl *inControl)
+{
+ Q_UNUSED(inControl);
+
+ // Maintain the color scheme based upon whether or not this item is selected
+ if (m_ShowVisibleSelection) {
+ if (m_IsSelected) {
+ m_Name->SetFillBackground(true);
+ m_Name->SetTextColor(CColor(255, 255, 255));
+ } else {
+ m_Name->SetFillBackground(false);
+ m_Name->SetTextColor(m_TextColor);
+ }
+ }
+
+ // TODO: notify listeners
+}
+
+//=============================================================================
+/**
+ * Allows you to specify the indent level of this tree item. Generally, this
+ * is called automatically when adding a child item. An item at level 0 is a
+ * root item, an item at level 1 is a child of a root item, and so on. The
+ * indent level is multiplied by a fixed amount to cause the control to appear
+ * indented.
+ * @param inAmount number indicating how many children deep this item is
+ * @param inIsRecursive set to true to recursively set the indent level of all
+ * children in addition to this item. Each child is set at one more indent
+ * level than its parent.
+ */
+void CTreeItem::SetIndent(long inAmount, bool inIsRecursive)
+{
+ m_IndentLevel = inAmount;
+
+ SetLeftMargin((m_IndentLevel * m_IndentSize) + m_ControlGap);
+
+ if (inIsRecursive) {
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theChild = *thePos;
+ theChild->SetIndent(m_IndentLevel + 1, inIsRecursive);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Handles clicking on this item and selects or deselects it appropriately.
+ * @param inPoint location of the mouse
+ * @param inFlags key modifier states at time of mouse event
+ */
+bool CTreeItem::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CFlowLayout::OnMouseDown(inPoint, inFlags)) {
+ // If the name is being edited, but was not clicked on, force it to lose focus
+ if (m_Name->GetEditMode() && !m_Name->HitTest(inPoint))
+ m_Name->OnLoseFocus();
+
+ // The item needs to see if the control key is down, because that might mean that it needs
+ // to deselect itself
+ bool theControlKeyIsDown =
+ (inFlags & CHotKeys::MODIFIER_CONTROL) == CHotKeys::MODIFIER_CONTROL;
+
+ // If the control key is down and we are currently selected, deselect ourselves
+ if (theControlKeyIsDown && IsSelected())
+ m_TreeControl->Deselect(this);
+ // Otherwise, go ahead and perform a normal select command
+ else
+ m_TreeControl->Select(this, inFlags);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * If this item is a container, double-click will expand it or collapse it.
+ * @param inPoint location of mouse at time of event
+ * @param inFlags modifier flags at time of event
+ */
+bool CTreeItem::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Let the children have the chance to handle the message
+ bool theMessageWasHandled = CFlowLayout::OnMouseDoubleClick(inPoint, inFlags);
+
+ // If no one else handled it, we'll just go ahead and expand
+ if (!theMessageWasHandled) {
+ // If this item is a container, toggle whether or not it's expanded
+ if (IsContainer())
+ ToggleExpansion();
+ }
+
+ return theMessageWasHandled;
+}
+
+//=============================================================================
+/**
+ * Handles right clicking on this item and selects or deselects it appropriately.
+ * @param inPoint location of the mouse
+ * @param inFlags key modifier states at time of mouse event
+ * @return true if the event was consumed, false if it should continue to propagate
+ */
+bool CTreeItem::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theMessageWasHandled = CFlowLayout::OnMouseRDown(inPoint, inFlags);
+ if (!theMessageWasHandled) {
+ // If the name is being edited, but was not clicked on, force it to lose focus
+ if (m_Name->GetEditMode() && !m_Name->HitTest(inPoint))
+ m_Name->OnLoseFocus();
+
+ // If this item is not already selected
+ if (!IsSelected()) {
+ // Select this tree item
+ m_TreeControl->Select(this, inFlags);
+ }
+ }
+
+ return theMessageWasHandled;
+}
+
+//=============================================================================
+/**
+ * @return true if this row is currently expanded (showing it's children).
+ */
+bool CTreeItem::IsExpanded()
+{
+ return m_IsExpanded;
+}
+
+//=============================================================================
+/**
+ * If the row is currently expanded, this call will collapse it, or vice-versa.
+ */
+void CTreeItem::ToggleExpansion()
+{
+ if (IsExpanded())
+ Collapse();
+ else
+ Expand();
+}
+
+//=============================================================================
+/**
+ * Expands this item to reveal all of its children.
+ */
+void CTreeItem::Expand()
+{
+ UICPROFILE(Expand);
+
+ if (!m_IsExpanded) {
+ m_TreeControl->OnItemExpanding(this);
+
+ bool theAllowRefresh = m_TreeControl->GetAllowRefresh();
+ m_TreeControl->SetAllowRefresh(false);
+
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ theItem->ShowChildItems();
+ }
+
+ m_IsExpanded = true;
+
+ m_TreeControl->SetAllowRefresh(theAllowRefresh);
+
+ // Expand/collapse might come from somewhere other than the button itself (see
+ // CTreeItem::OnMouseDoubleClick),
+ // so make sure we toggle it just in case
+ m_Toggle->SetToggleState(true);
+
+ m_TreeControl->OnItemExpanded(this);
+ }
+}
+
+//=============================================================================
+/**
+ * Collapses this row, hiding all of its children
+ */
+void CTreeItem::Collapse()
+{
+ if (m_IsExpanded) {
+ m_TreeControl->OnItemCollapsing(this);
+
+ bool theAllowRefresh = m_TreeControl->GetAllowRefresh();
+ m_TreeControl->SetAllowRefresh(false);
+
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ theItem->HideChildItems();
+ }
+
+ m_IsExpanded = false;
+
+ // Deselect all children if they are being hidden and see if any children were in fact
+ // selected
+ // If there were children that were selected, we need to add this item to the selection
+ // list, without
+ // interfering with the selection state of other items
+ if (DeselectChildren()) {
+ long theFlags = 0;
+
+ // If multiple selection is enabled, we need to make sure that we don't disrupt any
+ // other selection,
+ // so we simulate a control click on this item (selects this item in addition to
+ // whatever is already
+ // selected).
+ if (m_TreeControl->GetAllowMultipleSelection())
+ theFlags = CHotKeys::MODIFIER_CONTROL;
+
+ m_TreeControl->Select(this, theFlags);
+ }
+
+ m_TreeControl->SetAllowRefresh(theAllowRefresh);
+
+ // Expand/collapse might come from somewhere other than the button itself (see
+ // CTreeItem::OnMouseDoubleClick),
+ // so make sure we toggle it just in case
+ m_Toggle->SetToggleState(false);
+
+ m_TreeControl->OnItemCollapsed(this);
+ }
+}
+
+//=============================================================================
+/**
+ * Adds a tree item as a child of this one.
+ * @param inItem the new item to be added.
+ * @param inInsertBefore the item to insert the new one before, or nullptr to
+ * insert at the end of the list
+ */
+void CTreeItem::AddItem(CTreeItem *inItem, CTreeItem *inInsertBefore /*=nullptr*/)
+{
+ inItem->SetIndent(m_IndentLevel + 1, true);
+
+ inItem->SetVisible(IsExpanded());
+
+ if (!inInsertBefore) {
+ m_ItemList.push_back(inItem);
+ } else {
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ if (theItem == inInsertBefore) {
+ m_ItemList.insert(thePos, inItem);
+ break;
+ }
+ }
+ }
+
+ inItem->SetParentItem(this);
+
+ UpdateToggle();
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * The number of children this item has. Note that this is different than
+ * the GetChildCount( ) function on the base class CControl. The "children"
+ * counted by this function are the ones that have been added to this control
+ * to form a tree by calls to AddItem.
+ * @return the number of items added a "child tree items" to this one.
+ */
+long CTreeItem::GetNumChildItems()
+{
+ return (long)m_ItemList.size();
+}
+
+//=============================================================================
+/**
+ * Retrieve the child tree item based on it's position within m_ItemList
+ * @param inIndex position of the child tree item
+ * @return CTreeItem* ptr to child tree item or nullptr if inIndex is invalid.
+ */
+CTreeItem *CTreeItem::GetChildItem(long inIndex)
+{
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+ std::advance(thePos, inIndex);
+
+ if (thePos != m_ItemList.end())
+ return (*thePos);
+
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Retrieve the index of a child tree item based on it's position within
+ * m_ItemList.
+ * @param inChildItem ptr to the child tree item
+ * @return long index to the child tree item or -1 if inChildItem is invalid.
+ */
+long CTreeItem::GetChildTreeItemIndex(const CTreeItem *inChildItem) const
+{
+ TItemList::const_iterator thePos = m_ItemList.begin();
+ TItemList::const_iterator theEnd = m_ItemList.end();
+
+ long theItemIndex(-1);
+ bool theIsFound(false);
+ for (; thePos != theEnd && !theIsFound; ++thePos) {
+ ++theItemIndex;
+
+ if ((*thePos) == inChildItem)
+ theIsFound = true;
+ }
+
+ if (theIsFound)
+ return theItemIndex;
+ else
+ return -1;
+}
+
+//=============================================================================
+/**
+ * Retrieves the necessary iterators for searching through this item's list
+ * of children. You should not need to access this directly. This is provided
+ * for use by the CTreeControl class.
+ * @param outListBegin returns an iterator pointing to the first element in the list
+ * @param outListEnd returns an iterator pointing to the last element
+ */
+void CTreeItem::GetItemIterator(TItemList::iterator &outListBegin, TItemList::iterator &outListEnd)
+{
+ outListBegin = m_ItemList.begin();
+ outListEnd = m_ItemList.end();
+}
+
+//=============================================================================
+/**
+ * Retrieves the necessary iterators for searching through this item's list
+ * of children (in reverse order). You should not need to access this directly.
+ * This is provided for use by the CTreeControl class.
+ * @param outListBegin returns a reverse iterator pointing to the last element in the list
+ * @param outListEnd returns a reverse iterator pointing to the first element
+ */
+void CTreeItem::GetReverseItemIterator(TItemList::reverse_iterator &outListBegin,
+ TItemList::reverse_iterator &outListEnd)
+{
+ outListBegin = m_ItemList.rbegin();
+ outListEnd = m_ItemList.rend();
+}
+
+//=============================================================================
+/**
+ * An item that is a container has a visible toggle that can be clicked to
+ * hide or show its children.
+ * @return true if this item is a parent and has children, otherwise false
+ */
+bool CTreeItem::IsContainer()
+{
+ return m_ItemList.size() > 0;
+}
+
+//=============================================================================
+/**
+ * @return true if this item is a root level item, false if it has a parent
+ */
+bool CTreeItem::IsRootItem()
+{
+ return (!m_Parent);
+}
+
+//=============================================================================
+/**
+ * Removes this tree item and all its children from the tree control. Recursively
+ * goes through all children and asks them to detach themselves as children of
+ * the tree control. No items are actually deleted, as this is deferred to
+ * the class that created the items.
+ */
+void CTreeItem::RemoveItem()
+{
+ // Enable or disable the toggle on the parent accordingly
+ if (m_Parent)
+ m_Parent->UpdateToggle();
+
+ // Recursively remove all children
+ RemoveChildren();
+
+ // If this item has a parent, ask the parent to remove us from it's list of children
+ if (m_Parent)
+ m_Parent->RemoveFromList(this);
+
+ // Remove this item from the control hierarchy
+ m_TreeControl->RemoveChild(this);
+}
+
+//=============================================================================
+/**
+ * Updates the visibility of the expand toggle. If the the item is a container,
+ * the toggle is shown, otherwise it is hidden.
+ */
+void CTreeItem::UpdateToggle()
+{
+ UICPROFILE(UpdateToggle);
+
+ bool theEnableToggle = IsContainer();
+ bool theToggleIsEnabled = m_Toggle->IsEnabled();
+
+ if (theEnableToggle != theToggleIsEnabled) {
+ m_Toggle->SetEnabled(theEnableToggle);
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Recursively removes all children from the child list and from the control
+ * hierarchy maintained by the tree control.
+ */
+void CTreeItem::RemoveChildren()
+{
+ // If this item has children
+ if (IsContainer()) {
+ // Iterate through each child
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ // And recursively remove the child's children
+ CTreeItem *theItem = *thePos;
+ theItem->RemoveChildren();
+
+ // Ask the tree control to remove this child from the control hierarchy
+ m_TreeControl->RemoveChild(theItem);
+ }
+
+ // Clear the child list since we deleted all the children
+ m_ItemList.clear();
+ }
+}
+
+//=============================================================================
+/**
+ * Helper function for item removal. Goes through the list of child items that
+ * belongs to this control and removes the specified item from the list.
+ * @param inItem item to be removed from list
+ */
+void CTreeItem::RemoveFromList(CTreeItem *inItem)
+{
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ if (theItem == inItem) {
+ m_ItemList.erase(thePos);
+ break;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Detaches this item from its parent.
+ */
+void CTreeItem::Detach()
+{
+ if (m_Parent)
+ m_Parent->RemoveFromList(this);
+}
+
+//=============================================================================
+/**
+ * @return true if this item is currently selected, otherwise false.
+ */
+bool CTreeItem::IsSelected()
+{
+ return m_IsSelected;
+}
+
+//=============================================================================
+/**
+ * Selects or deselects this row. Color of the selected item changes, as well
+ * as the item's icon.
+ * @param inIsSelected true to select this item, false to deselect it
+ */
+void CTreeItem::SetSelected(bool inIsSelected)
+{
+ // If this command is actually resulting in a change of state
+ if (m_IsSelected != inIsSelected) {
+ m_IsSelected = inIsSelected;
+
+ if (m_ShowVisibleSelection) {
+ // If the item is to be selected
+ if (m_IsSelected) {
+ // Change to the selection color
+ m_Name->SetFillBackground(true);
+
+ if (!m_SelectedIcon.isNull())
+ m_Icon->SetImage(m_SelectedIcon);
+ }
+ // Otherwise, the item is to be deselected
+ else {
+ // Change to the normal color scheme
+ m_Name->SetFillBackground(false);
+ m_Name->SetTextColor(m_TextColor);
+
+ if (!m_NormalIcon.isNull())
+ m_Icon->SetImage(m_NormalIcon);
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Deselects all children, grandchildren, and so on who are currently selected.
+ * @return true if there were any selected children who were deselected
+ */
+bool CTreeItem::DeselectChildren()
+{
+ bool theChildSelection = false;
+
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theChild = *thePos;
+
+ if (theChild->IsContainer()) {
+ bool theRecursiveCheck = theChild->DeselectChildren();
+ if (!theChildSelection)
+ theChildSelection = theRecursiveCheck;
+ }
+
+ if (theChild->IsSelected()) {
+ m_TreeControl->Deselect(theChild);
+ theChildSelection = true;
+ }
+ }
+
+ return theChildSelection;
+}
+
+//=============================================================================
+/**
+ * Creates the toggle control used by this tree item.
+ */
+void CTreeItem::CreateToggle()
+{
+ m_Toggle = new CToggleButton();
+
+ // Make sure these sizes are accurate
+ QSize theImageSize = CResourceCache::GetInstance()->GetBitmap("arrow.png").size();
+ m_Toggle->SetUpImage("arrow.png");
+
+ m_Toggle->SetDownImage("arrow_down.png");
+ m_Toggle->SetDisabledImage("empty-pixel.png");
+ m_Toggle->SetAbsoluteSize({theImageSize.width(), theImageSize.height()});
+ m_Toggle->SetEnabled(false);
+
+ // This is to get around a problem in SetIndent when the parent control is 0
+ m_IndentSize = theImageSize.width();
+}
+
+//=============================================================================
+/**
+ * Called when the toggle button for this item is clicked on. Expands the item
+ * if is currently collapsed, otherwise, collapses the row.
+ * @param inButton button that generated this event
+ * @param inState state of the button after the toggle event
+ */
+void CTreeItem::OnToggleExpansion(CToggleButton *inButton, CButtonControl::EButtonState inState)
+{
+ Q_UNUSED(inState);
+
+ if (inButton == m_Toggle)
+ ToggleExpansion();
+}
+
+//=============================================================================
+/**
+ * Recursive function to help change the visiblity of all children of this item.
+ */
+void CTreeItem::HideChildItems()
+{
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ theItem->HideChildItems();
+ }
+
+ SetVisible(false);
+}
+
+//=============================================================================
+/**
+ * Recursive function to help change the visiblity of all children of this item.
+ * If a child is expanded, this function is called recursively to reveal all of
+ * the grandchildren, and so on.
+ */
+void CTreeItem::ShowChildItems()
+{
+ if (m_Parent)
+ SetVisible(m_Parent->IsVisible());
+ else
+ SetVisible(true);
+
+ TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ CTreeItem *theItem = *thePos;
+ if (IsExpanded())
+ theItem->ShowChildItems();
+ }
+}
+
+//=============================================================================
+/**
+ * Private function for adding children to this control. The only children
+ * should be a toggle, an icon, and a text control for the name. If you
+ * need to add another tree item as a "child" of this one, you should use
+ * AddItem( ).
+ * @param inControl Control to be added as a child to this one
+ * @param inInsertBefore Control to insert before in the hierarchy or nullptr to
+ * insert at the end of the list.
+ */
+void CTreeItem::AddChild(CControl *inControl, CControl *inInsertBefore /*= nullptr*/)
+{
+ CFlowLayout::AddChild(inControl, inInsertBefore);
+}
+
+//=============================================================================
+/**
+ * Find the item that this item should be added after to maintian sort order.
+ */
+CTreeItem *CTreeItem::FindPrevSortSibling(CTreeItem *)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ UIC_THROW(E_FAIL);
+#endif
+ return NULL;
+}
+
+//=============================================================================
+/**
+ * Find the item that this item should be added before to maintian sort order.
+ */
+CTreeItem *CTreeItem::FindNextSortSibling(CTreeItem *inChild)
+{
+ CTreeItem *theSortItem = nullptr;
+
+ // No items in the list - return nullptr (because we don't care)
+ if (m_ItemList.size()) {
+ CTreeItem::TItemList::iterator thePos = m_ItemList.begin();
+ for (; thePos != m_ItemList.end(); ++thePos) {
+ // Item in the list
+ theSortItem = *thePos;
+ if (m_TreeControl->IsItemLess(inChild, theSortItem))
+ break;
+ }
+
+ // Last item in the list
+ if (thePos == m_ItemList.end())
+ theSortItem = nullptr;
+ }
+
+ return theSortItem;
+}
+
+/**
+ * Retrieve the edit state of the text edit control associated with this tree item
+ */
+bool CTreeItem::GetEditMode()
+{
+ if (m_Name) {
+ return m_Name->GetEditMode();
+ }
+
+ return false;
+}
+
+//=============================================================================
+/**
+ * Sets whether item is 'visibly' selected
+ */
+void CTreeItem::SetVisibleSelection(bool inValue)
+{
+ m_ShowVisibleSelection = inValue;
+}
+
+//=============================================================================
+/**
+ * Gets whether item is 'visibly' selected
+ */
+bool CTreeItem::GetVisibleSelection() const
+{
+ return m_ShowVisibleSelection;
+}
diff --git a/src/Authoring/Studio/Controls/TreeItem.h b/src/Authoring/Studio/Controls/TreeItem.h
new file mode 100644
index 00000000..78cb54bb
--- /dev/null
+++ b/src/Authoring/Studio/Controls/TreeItem.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TREE_ITEM_H
+#define INCLUDED_TREE_ITEM_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FlowLayout.h"
+#include "ToggleButton.h"
+#include "TextEditInPlace.h"
+
+#include <QPixmap>
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTreeControl;
+class CRenderer;
+class CSIcon;
+class CTreeItem;
+class CTest_TreeControl;
+
+//=============================================================================
+/**
+ * Class encapsulating a single row in a tree control. Manages the toggle, the
+ * icon, and the name of the tree item. When you create a tree item you must
+ * associate it with a tree control. Then you can specify it's parent when you
+ * call AddItem( ).
+ */
+class CTreeItem : public CFlowLayout
+{
+public:
+ typedef std::vector<CTreeItem *> TItemList;
+
+public:
+ CTreeItem(CTreeControl *inTreeControl);
+ virtual ~CTreeItem();
+
+ DEFINE_OBJECT_COUNTER(CTreeItem)
+
+ void Draw(CRenderer *inRenderer) override;
+
+ void SetBackgroundColor(const ::CColor &inColor);
+ ::CColor GetBackgroundColor();
+ void SetTextColor(const ::CColor &inColor);
+ void SetTextBGFocusColor(const ::CColor &inColor);
+
+ void SetParentItem(CTreeItem *inParent);
+ CTreeItem *GetParentItem();
+ bool GetEditMode();
+
+ virtual void SetIcon(const QString &inIcon,
+ const QString &inSelectedIcon);
+ virtual void SetIcon(const QPixmap &inNormalIcon, const QPixmap &inSelectedIcon);
+ void SetIsNameEditable(bool inIsEditable);
+ virtual void SetText(const Q3DStudio::CString &inText);
+ virtual Q3DStudio::CString GetText();
+ virtual void OnNameChanged(CControl *inControl);
+ void SetIndent(long inAmount, bool inIsRecursive);
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ bool IsExpanded();
+ virtual void ToggleExpansion();
+ virtual void Expand();
+ virtual void Collapse();
+
+ virtual void AddItem(CTreeItem *inItem, CTreeItem *inInsertBefore = nullptr);
+ long GetNumChildItems();
+ CTreeItem *GetChildItem(long inIndex);
+ long GetChildTreeItemIndex(const CTreeItem *inChildItem) const;
+ void GetItemIterator(TItemList::iterator &outListBegin, TItemList::iterator &outListEnd);
+ void GetReverseItemIterator(TItemList::reverse_iterator &outListBegin,
+ TItemList::reverse_iterator &outListEnd);
+ virtual bool IsContainer();
+ bool IsRootItem();
+ virtual void RemoveItem();
+ void UpdateToggle();
+ virtual void RemoveChildren();
+ void RemoveFromList(CTreeItem *inItem);
+ virtual void Detach();
+ virtual CTreeItem *FindPrevSortSibling(CTreeItem *inChild);
+ virtual CTreeItem *FindNextSortSibling(CTreeItem *inChild);
+
+ bool IsSelected();
+ virtual void SetSelected(bool inIsSelected);
+ bool DeselectChildren();
+
+ void SetVisibleSelection(bool inValue);
+ bool GetVisibleSelection() const;
+
+ boost::signal1<void, CControl *> SigToggle;
+
+protected:
+ // Member Vars
+ CTreeControl *m_TreeControl;
+ CTreeItem *m_Parent;
+ CToggleButton *m_Toggle;
+ CTextEditInPlace *m_Name;
+ CCommitDataListener *m_NameChangeListener;
+ CSIcon *m_Icon;
+ QPixmap m_NormalIcon;
+ QPixmap m_SelectedIcon;
+ TItemList m_ItemList;
+ long m_ControlGap;
+ long m_IndentLevel;
+ long m_IndentSize;
+ bool m_IsExpanded;
+ bool m_IsSelected;
+ bool m_ShowVisibleSelection;
+ ::CColor m_Color;
+ ::CColor m_TextColor;
+
+ // Member Functions
+ void CreateToggle();
+ void OnToggleExpansion(CToggleButton *inButton, CButtonControl::EButtonState inState);
+ void HideChildItems();
+ void ShowChildItems();
+
+private:
+ /// Private because no one outside this class should be calling it; use AddItem( ) instead.
+ void AddChild(CControl *inControl, CControl *inInsertBefore = nullptr) override;
+};
+#endif // INCLUDED_TREE_ITEM_H
diff --git a/src/Authoring/Studio/Controls/WidgetControl.cpp b/src/Authoring/Studio/Controls/WidgetControl.cpp
new file mode 100644
index 00000000..ae45468a
--- /dev/null
+++ b/src/Authoring/Studio/Controls/WidgetControl.cpp
@@ -0,0 +1,439 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "WidgetControl.h"
+
+#include "Control.h"
+#include "DropSource.h"
+#include "IDragable.h"
+#include "OffscreenRenderer.h"
+#include "Pt.h"
+#include "Rct.h"
+#include "UICFile.h"
+
+#include <QDrag>
+#include <QFocusEvent>
+#include <QKeyEvent>
+#include <QMenu>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QPaintEvent>
+#include <QShowEvent>
+#include <QWheelEvent>
+
+WidgetControl::WidgetControl(CControl *control, QWidget *parent)
+ : QWidget(parent)
+ , m_control(control)
+ , m_controlListener(this)
+{
+ Q_ASSERT(control);
+ control->SetWindowListener(&m_controlListener);
+ setControlSize(sizeHint());
+}
+
+bool WidgetControl::event(QEvent *event)
+{
+ if (event->type() == QEvent::ShortcutOverride) {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ m_control->OnKeyDown(ke->key(), ke->modifiers());
+ }
+ return QWidget::event(event);
+}
+
+void WidgetControl::showEvent(QShowEvent *event)
+{
+ QWidget::showEvent(event);
+}
+
+void WidgetControl::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(this);
+ const auto boundRect = QRect(QPoint(0,0), size());
+ CWinRenderer renderer(&painter, boundRect);
+ CRct rect(event->rect());
+ m_control->OnDraw(&renderer, rect, true);
+
+ QWidget::paintEvent(event);
+}
+
+void WidgetControl::resizeEvent(QResizeEvent *event)
+{
+ setControlSize(event->size());
+ QWidget::resizeEvent(event);
+}
+
+void WidgetControl::keyPressEvent(QKeyEvent *event)
+{
+ m_control->OnKeyDown(event->key(), event->modifiers());
+ m_control->OnChar(event->text(), event->modifiers());
+ QWidget::keyPressEvent(event);
+}
+
+void WidgetControl::keyReleaseEvent(QKeyEvent *event)
+{
+ m_control->OnKeyUp(event->key(), event->modifiers());
+ QWidget::keyReleaseEvent(event);
+}
+
+void WidgetControl::mousePressEvent(QMouseEvent *event)
+{
+ const auto pos = CPt(event->pos());
+ if (m_isLeftMouseDown)
+ m_control->OnMouseUp(pos, event->modifiers());
+
+ m_isLeftMouseDown = (event->button() == Qt::LeftButton);
+ if (m_isLeftMouseDown)
+ m_control->OnMouseDown(pos, event->modifiers());
+ else
+ m_control->OnMouseRDown(pos, event->modifiers());
+
+ setFocus();
+ QWidget::mousePressEvent(event);
+}
+
+void WidgetControl::mouseReleaseEvent(QMouseEvent *event)
+{
+ const auto pos = CPt(event->pos());
+ if (event->button() == Qt::LeftButton) {
+ m_isLeftMouseDown = false;
+ m_control->OnMouseUp(pos, event->modifiers());
+ } else {
+ m_control->OnMouseRUp(pos, event->modifiers());
+ }
+
+ QWidget::mouseReleaseEvent(event);
+}
+
+void WidgetControl::mouseMoveEvent(QMouseEvent *event)
+{
+ m_control->OnMouseMove(event->pos(), event->modifiers());
+ QWidget::mouseMoveEvent(event);
+}
+
+void WidgetControl::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ // call QWidget handler first to not deliver OnMouseDown after OnMouseDoubleClick
+ QWidget::mouseDoubleClickEvent(event);
+ m_control->OnMouseDoubleClick(event->pos(), event->modifiers());
+}
+
+void WidgetControl::wheelEvent(QWheelEvent *event)
+{
+ m_control->OnMouseWheel(event->pos(), event->angleDelta().y(), event->modifiers());
+ QWidget::wheelEvent(event);
+}
+
+void WidgetControl::enterEvent(QEvent *event)
+{
+ setMouseTracking(true);
+ m_control->OnMouseHover(mapFromGlobal(QCursor::pos()), {});
+ QWidget::enterEvent(event);
+}
+
+void WidgetControl::leaveEvent(QEvent *event)
+{
+ setMouseTracking(false);
+ m_control->OnMouseOut(mapFromGlobal(QCursor::pos()), {});
+ QWidget::leaveEvent(event);
+}
+
+void WidgetControl::focusInEvent(QFocusEvent *event)
+{
+ m_control->OnGainFocus();
+ QWidget::focusInEvent(event);
+}
+
+void WidgetControl::focusOutEvent(QFocusEvent *event)
+{
+ if (!m_isContextMenuShown)
+ m_control->OnLoseFocus();
+ QWidget::focusOutEvent(event);
+}
+
+QSize WidgetControl::sizeHint() const
+{
+ const auto preferredSize = m_control->GetPreferredSize();
+ return QSize(preferredSize.x, preferredSize.y);
+}
+
+/*
+ * CPaletteManager::GetTimelineControl() needs a way of accessing
+ * the CControl inside the widget
+ */
+CControl *WidgetControl::getControl() const
+{
+ return m_control;
+}
+
+void WidgetControl::setControlSize(const QSize &size)
+{
+ m_control->SetSize(size.width(), size.height());
+}
+
+void WidgetControl::DoStartDrag(IDragable *inDragable)
+{
+ if (m_isDragging || !m_isLeftMouseDown)
+ return;
+
+ QDrag drag(this);
+ m_isDragging = true;
+
+ drag.setMimeData(CDropSourceFactory::Create(inDragable->GetFlavor(), inDragable));
+ drag.exec();
+ m_isLeftMouseDown = false;
+
+ m_isDragging = false;
+}
+
+void WidgetControl::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList)
+{
+ if (m_isDragging || !m_isLeftMouseDown)
+ return;
+
+ QDrag drag(this);
+ m_isDragging = true;
+
+ try {
+ auto thePos = inDragFileNameList.begin();
+ auto theEndPos = inDragFileNameList.end();
+
+ Q3DStudio::CAutoMemPtr<CUICFile> theDragFile;
+ for (; thePos != theEndPos; ++thePos) {
+ Q3DStudio::CString theDragFileName = *thePos;
+ if (theDragFileName.Length() > 0) {
+ theDragFile = new CUICFile(theDragFileName);
+ CDropSource *theDropSource = CDropSourceFactory::Create(
+ EUIC_FLAVOR_ASSET_UICFILE, (void *)theDragFile, sizeof(theDragFile));
+ // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls.
+ drag.setMimeData(theDropSource);
+ break;
+ }
+ }
+ drag.exec();
+ m_isLeftMouseDown = false;
+ } catch (...) { // if there are any errors that throws an exception, there
+ // there will be no more drag and drop, since the flag will not be reset.
+ }
+
+ m_isDragging = false;
+}
+
+bool WidgetControl::OnDragWithin(CDropSource &inSource)
+{
+ bool theReturn = false;
+ CPt thePoint = inSource.GetCurrentPoint();
+ Qt::KeyboardModifiers theFlags = inSource.GetCurrentFlags();
+ CDropTarget *theDropTarget = m_control->FindDropCandidate(thePoint, theFlags);
+
+ if (theDropTarget) {
+ theReturn = theDropTarget->Accept(inSource);
+ delete theDropTarget;
+ }
+ return theReturn;
+}
+
+bool WidgetControl::OnDragReceive(CDropSource &inSource)
+{
+ bool theReturn = false;
+ CPt thePoint = inSource.GetCurrentPoint();
+ Qt::KeyboardModifiers theFlags = inSource.GetCurrentFlags();
+
+ CDropTarget *theDropTarget = m_control->FindDropCandidate(thePoint, theFlags);
+
+ if (theDropTarget) {
+ theReturn = theDropTarget->Drop(inSource);
+ delete theDropTarget;
+ }
+ return theReturn;
+}
+
+void WidgetControl::OnDragLeave()
+{
+ m_control->OnMouseMove(CPt(-1, -1), 0);
+}
+
+void WidgetControl::OnReflectMouse(CPt &inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Notify the control that the mouse moved
+ m_control->OnMouseMove(inPoint, inFlags /*CHotKeys::GetCurrentKeyModifiers( )*/);
+
+ // If the control invalidated because of a mouse event then we want to do an immediate redraw.
+ // this ensures consistent visible feedback.
+ if (m_control->IsChildInvalidated())
+ repaint();
+}
+
+//=============================================================================
+/**
+ * Creates the pass thru class for the wnd control.
+ */
+WidgetControlControlListener::WidgetControlControlListener(WidgetControl *inParent)
+{
+ m_Parent = inParent;
+}
+
+WidgetControlControlListener::~WidgetControlControlListener()
+{
+}
+
+//=============================================================================
+/**
+ * Notification from the control that the window was invalidated.
+ */
+void WidgetControlControlListener::OnControlInvalidated()
+{
+ m_Parent->update();
+}
+
+//=============================================================================
+/**
+ * Notification from the control to do a popup at the specified location.
+ */
+long WidgetControlControlListener::DoPopup(QMenu *inMenu, CPt inPoint)
+{
+ long selectedIndex = -1;
+ if (inMenu) {
+ m_Parent->setContextMenuShown(true);
+ auto action = inMenu->exec(m_Parent->mapToGlobal(inPoint));
+ m_Parent->setContextMenuShown(false);
+ if (action)
+ selectedIndex = inMenu->actions().indexOf(action);
+ }
+
+ return selectedIndex;
+}
+
+//=============================================================================
+/**
+ * Get the location of the point in Screen coordinates.
+ */
+CPt WidgetControlControlListener::ClientToScreen(CPt inPoint)
+{
+ return m_Parent->mapToGlobal(inPoint);
+}
+
+//=============================================================================
+/**
+ * Get the location of the point into client coordinates.
+ */
+CPt WidgetControlControlListener::ScreenToClient(CPt inPoint)
+{
+ return m_Parent->mapFromGlobal(inPoint);
+}
+
+//=============================================================================
+/**
+ * Get the platform dependent view that this is embedding.
+ * Used when platform dependent controls need to be embedded into the Controls.
+ */
+TPlatformView WidgetControlControlListener::GetPlatformView()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ return m_Parent->m_hWnd;
+#else
+ return nullptr;
+#endif
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's SetIsDragging function.
+ * @param inIsDragging true to specify that a drag is occurring or false to cancel a drag
+ */
+void WidgetControlControlListener::SetIsDragging(bool inIsDragging)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ m_Parent->SetIsDragging(inIsDragging);
+#endif
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's ShowTooltips function.
+ * @param inLocation mid-point of the tooltip in global coordinates
+ * @param inText text to display as a tooltip
+ */
+void WidgetControlControlListener::ShowTooltips(CPt inLocation, const Q3DStudio::CString &inText)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ m_Parent->ShowTooltips(inLocation, inText);
+#endif
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's HideTooltips function.
+ */
+void WidgetControlControlListener::HideTooltips()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ m_Parent->HideTooltips();
+#endif
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's ShowMoveableTooltips function.
+ * @param inLocation mid-point of the tooltip in global coordinates
+ * @param inText text to display as a tooltip
+ */
+void WidgetControlControlListener::ShowMoveableWindow(CPt inLocation, const Q3DStudio::CString &inText,
+ CRct inBoundingRct)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ m_Parent->ShowMoveableWindow(inLocation, inText, inBoundingRct);
+#endif
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's HideMoveableTooltips function.
+ */
+void WidgetControlControlListener::HideMoveableWindow()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ m_Parent->HideMoveableWindow();
+#endif
+}
+
+void WidgetControlControlListener::DoStartDrag(IDragable *inDragable)
+{
+ m_Parent->DoStartDrag(inDragable);
+}
+
+//===============================================================================
+/**
+* performs a drag operation on a file
+*/
+void WidgetControlControlListener::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList)
+{
+ m_Parent->DoStartDrag(inDragFileNameList);
+}
+
+
+
diff --git a/src/Authoring/Studio/Controls/WidgetControl.h b/src/Authoring/Studio/Controls/WidgetControl.h
new file mode 100644
index 00000000..8c30f1bb
--- /dev/null
+++ b/src/Authoring/Studio/Controls/WidgetControl.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETCONTROL_H
+#define WIDGETCONTROL_H
+
+#include <QWidget>
+
+#include "Control.h"
+#include "DropContainer.h"
+
+class CRenderer;
+class WidgetControl;
+
+class WidgetControlControlListener : public CControlWindowListener
+{
+public:
+ WidgetControlControlListener(WidgetControl *inParent);
+ virtual ~WidgetControlControlListener();
+
+ void OnControlInvalidated() override;
+ long DoPopup(QMenu *inMenu, CPt inLocation) override;
+ CPt ClientToScreen(CPt inPoint) override;
+ CPt ScreenToClient(CPt inPoint) override;
+ TPlatformView GetPlatformView() override;
+ void SetIsDragging(bool inIsDragging) override;
+ void ShowTooltips(CPt inLocation, const Q3DStudio::CString &inText) override;
+ void HideTooltips() override;
+ void DoStartDrag(IDragable *inDragable) override;
+ void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList) override;
+ void ShowMoveableWindow(CPt inLocation, const Q3DStudio::CString &inText, CRct inBoundingRct) override;
+ void HideMoveableWindow() override;
+
+protected:
+ WidgetControl *m_Parent;
+};
+class WidgetControl : public QWidget, public CWinDropContainer
+{
+ Q_OBJECT
+ friend class ::WidgetControlControlListener;
+public:
+ explicit WidgetControl(CControl *control, QWidget *parent = nullptr);
+ void setContextMenuShown(bool shown) { m_isContextMenuShown = shown; }
+
+protected:
+ bool event(QEvent *event) override;
+ void showEvent(QShowEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+ void wheelEvent(QWheelEvent *event) override;
+ void enterEvent(QEvent *event) override;
+ void leaveEvent(QEvent *event) override;
+ void focusInEvent(QFocusEvent *event) override;
+ void focusOutEvent(QFocusEvent *event) override;
+
+public:
+ QSize sizeHint() const override;
+ CControl *getControl() const;
+
+protected:
+ void DoStartDrag(IDragable *inDragable);
+ void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList);
+
+ bool OnDragWithin(CDropSource &inSource) override;
+ bool OnDragReceive(CDropSource &inSource) override;
+ void OnDragLeave() override;
+ void OnReflectMouse(CPt &inPoint, Qt::KeyboardModifiers inFlags) override;
+
+private:
+ void setControlSize(const QSize &size);
+
+ CControl *m_control;
+ bool m_isLeftMouseDown = false;
+ bool m_isDragging = false;
+ bool m_isContextMenuShown = false;
+ WidgetControlControlListener m_controlListener;
+};
+
+#endif // WIDGETCONTROL_H
diff --git a/src/Authoring/Studio/Docs/CmdLineOptions.txt b/src/Authoring/Studio/Docs/CmdLineOptions.txt
new file mode 100644
index 00000000..42610e8a
--- /dev/null
+++ b/src/Authoring/Studio/Docs/CmdLineOptions.txt
@@ -0,0 +1,27 @@
+-t, -test <Test Path> - Runs the specified Unit Test(s) (TEST_CMD_LINE)
+-n <File Name> - Normal operation (NORMAL)
+-replay - Replay File
+-export - Export the file. Usage: Studio.exe -export AMWFilename AMCFilename DOMPath [ slide index(optional and defaults to 1) ]
+-silent - Run silent run deep
+-refresh - Refresh resources
+
+Unused:
+-u, -xml <File Name> - TEST_XML
+-i, -testInfo - TEST_INFO
+
+It is possible to stack command line options, with left to right operation precedence. With the exception of
+-test and -silent which take effect regardless of ordering. Any failed operations would result in the
+aborting of subsequent operations, and a -1 (failure) value will be returned.
+
+Example 1:
+StudioC -silent -refresh myFile.uip -export myOutput.amc Scene.Layer.Component
+Refreshes the myFile.uip, then exports to myOutput.amc the component found at the indicated DOM path. No dialogs are
+displayed. Error messages are piped to stdout.
+
+Example 2:
+Studio -refresh myFile.uip myOutput.xgf -export
+Refreshes myFile.uip then exports to myOutput.xgf using the XGF exporter.
+
+Example 3:
+StudioC -silent -export myFile.uip -refresh myOutput.avi
+Exports myFile.uip to myOutput.avi THEN refreshes myFile.uip. Error messages are piped to stdout. \ No newline at end of file
diff --git a/src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.cpp b/src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.cpp
new file mode 100644
index 00000000..089a9c97
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BasicObjectDropSource.h"
+#include "Doc.h"
+#include "DropTarget.h"
+
+#include "Dialogs.h"
+#include "Dispatch.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMDataCore.h"
+#include "IDocumentEditor.h"
+#include "ImportUtils.h"
+#include "BasicObjectsModel.h"
+#include "IDragable.h"
+#include "IDocSceneGraph.h"
+#include "UICTextRenderer.h"
+#include "HotKeys.h"
+#include "StudioUtils.h"
+
+#include <QDir>
+
+//===============================================================================
+/**
+ *
+ */
+CBasicObjectDropSource::CBasicObjectDropSource(long inFlavor, IDragable *inDragable)
+ : CDropSource(inFlavor, 0)
+ , m_IsIndependent(false)
+{
+ auto item = dynamic_cast<BasicObjectItem *>(inDragable);
+ if (item) {
+ m_ObjectType = item->objectType();
+ m_PrimitiveType = item->primitiveType();
+ }
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CBasicObjectDropSource::ValidateTarget(CDropTarget *inTarget)
+{
+ using namespace Q3DStudio;
+
+ EStudioObjectType targetType = (EStudioObjectType)inTarget->GetObjectType();
+ bool theValidTarget = false;
+
+ // the only thing we want to do from here is check the type.
+ theValidTarget =
+ CStudioObjectTypes::AcceptableParent((EStudioObjectType)m_ObjectType, targetType);
+
+ if (!theValidTarget) {
+ SetHasValidTarget(theValidTarget);
+ return theValidTarget;
+ } else {
+ if (CHotKeys::IsKeyDown(Qt::AltModifier) && targetType != OBJTYPE_SCENE
+ && targetType != OBJTYPE_COMPONENT) {
+ UICDM::CUICDMInstanceHandle theTarget = inTarget->GetInstance();
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ IDocumentReader &theReader(theDoc->GetDocumentReader());
+ UICDM::CUICDMSlideHandle toSlide = theReader.GetAssociatedSlide(theTarget);
+ ;
+
+ if (!theReader.IsMasterSlide(toSlide))
+ theValidTarget = false;
+ }
+
+ SetHasValidTarget(theValidTarget);
+ return theValidTarget;
+ }
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CBasicObjectDropSource::CanMove()
+{
+ return true;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CBasicObjectDropSource::CanCopy()
+{
+ return true;
+}
+
+CCmd *CBasicObjectDropSource::GenerateAssetCommand(UICDM::CUICDMInstanceHandle inTarget,
+ EDROPDESTINATION inDestType,
+ UICDM::CUICDMSlideHandle inSlide)
+{
+ using namespace Q3DStudio;
+ using UICDM::ComposerObjectTypes;
+ using namespace std;
+
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ CPt thePoint;
+ // if ( CHotKeys::IsKeyDown( CHotKeys::KEY_MENU ) )
+ // thePoint = GetCurrentPoint();
+
+ long theStartTime = -1;
+ if (CHotKeys::IsKeyDown(Qt::ControlModifier))
+ theStartTime = theDoc->GetCurrentViewTime();
+
+ DocumentEditorInsertType::Enum theInsertType(ImportUtils::GetInsertTypeForDropType(inDestType));
+ ComposerObjectTypes::Enum theComposerType;
+ switch (m_ObjectType) {
+ case OBJTYPE_SCENE:
+ theComposerType = ComposerObjectTypes::Scene;
+ break;
+ case OBJTYPE_LAYER:
+ theComposerType = ComposerObjectTypes::Layer;
+ break;
+ case OBJTYPE_BEHAVIOR:
+ theComposerType = ComposerObjectTypes::Behavior;
+ break;
+ case OBJTYPE_MATERIAL:
+ theComposerType = ComposerObjectTypes::Material;
+ break;
+ case OBJTYPE_CAMERA:
+ theComposerType = ComposerObjectTypes::Camera;
+ break;
+ case OBJTYPE_LIGHT:
+ theComposerType = ComposerObjectTypes::Light;
+ break;
+ case OBJTYPE_MODEL:
+ theComposerType = ComposerObjectTypes::Model;
+ break;
+ case OBJTYPE_GROUP:
+ theComposerType = ComposerObjectTypes::Group;
+ break;
+ case OBJTYPE_IMAGE:
+ theComposerType = ComposerObjectTypes::Image;
+ break;
+ case OBJTYPE_TEXT:
+ theComposerType = ComposerObjectTypes::Text;
+ break;
+ case OBJTYPE_COMPONENT:
+ theComposerType = ComposerObjectTypes::Component;
+ break;
+ case OBJTYPE_ALIAS:
+ theComposerType = ComposerObjectTypes::Alias;
+ break;
+ case OBJTYPE_PATH:
+ theComposerType = ComposerObjectTypes::Path;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ theComposerType = ComposerObjectTypes::Unknown;
+ break;
+ }
+ if (theComposerType != ComposerObjectTypes::Unknown) {
+ if (theComposerType == ComposerObjectTypes::Text) {
+ // For Text, we need to check if user already has font file inside fonts folder
+ CFilePath theFontFile;
+ CFilePath theFontDir = CFilePath::CombineBaseAndRelative(theDoc->GetDocumentDirectory(),
+ CFilePath(L"fonts"));
+ if (!theFontDir.Exists()) {
+ // Create font dir if necessary
+ theFontDir.CreateDir(true);
+ } else {
+ // Recursively find the first font file in font dir
+ vector<CFilePath> theFiles;
+ theFontDir.RecursivelyFindFilesOfType(nullptr, theFiles, false);
+ for (size_t i = 0; i < theFiles.size(); ++i) {
+ if (CDialogs::IsFontFileExtension(theFiles[i].GetExtension())) {
+ // Reuse the font in fonts subdirectory
+ theFontFile = theFiles[i];
+ break;
+ }
+ }
+ }
+
+ if (theFontFile == L"") {
+ // If user doesn't have any font file, copy the default font file from Studio's res
+ // folder
+
+ CFilePath theResFontFile;
+
+ QDir theResFontDir(resourcePath() + "/Font");
+ Q_FOREACH (QFileInfo fontFile, theResFontDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot)) {
+ CString ext = CString::fromQString(fontFile.suffix());
+ if (CDialogs::IsFontFileExtension(ext)) {
+ theResFontFile = CString::fromQString(fontFile.absoluteFilePath());
+ theFontFile = CFilePath::CombineBaseAndRelative(theFontDir, CString::fromQString(fontFile.fileName()));
+ break;
+ }
+ }
+
+ if (theResFontFile == L"") {
+ QT3DS_ASSERT(false);
+ std::shared_ptr<IImportFailedHandler> theHandler(
+ theDoc->GetImportFailedHandler());
+ if (theHandler)
+ theHandler->DisplayImportFailed(
+ theResFontDir.absolutePath(),
+ QObject::tr("Default Font File Doesn't Exist in the Directory"),
+ false);
+ return nullptr;
+ }
+
+ // Copy the file to project's fonts folder
+ SFileTools::Copy(theFontFile,
+ Q3DStudio::FileOpenFlags(Q3DStudio::FileOpenFlagValues::Create),
+ theResFontFile);
+ // Force the text renderer to refresh
+ if (theDoc->GetSceneGraph() && theDoc->GetSceneGraph()->GetTextRenderer())
+ theDoc->GetSceneGraph()->GetTextRenderer()->ReloadFonts();
+ }
+
+ // Lastly, we use the font file to create the Text object. This is similar to drag-drop
+ // the font file from Project Palette to Scene.
+ SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Add Text"))
+ ->ImportFile(DocumentEditorFileType::Font, theFontFile, inTarget, inSlide,
+ CDialogs::GetImportFileExtension(),
+ Q3DStudio::ImportUtils::GetInsertTypeForDropType(inDestType), thePoint,
+ theStartTime);
+ } else {
+ SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Add Instance"))
+ ->CreateSceneGraphInstance(theComposerType, inTarget, inSlide, theInsertType,
+ thePoint, (EPrimitiveType)m_PrimitiveType, theStartTime);
+ }
+ }
+ return nullptr;
+}
diff --git a/src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.h b/src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.h
new file mode 100644
index 00000000..454fce9e
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/BasicObjectDropSource.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __BasicObjectDropSource_H__
+#define __BasicObjectDropSource_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropSource.h"
+#include "StudioObjectTypes.h"
+
+class CStudioApp;
+class CDropTarget;
+
+class CBasicObjectDropSource : public CDropSource
+{
+public:
+ CBasicObjectDropSource(long inFlavor, IDragable *inDragable);
+
+ // CDropSource
+ bool CanMove() override;
+ bool CanCopy() override;
+ bool ValidateTarget(CDropTarget *inTarget) override;
+
+ CCmd *GenerateAssetCommand(UICDM::CUICDMInstanceHandle inTarget,
+ EDROPDESTINATION inDestType,
+ UICDM::CUICDMSlideHandle inSlide) override;
+
+protected:
+ EPrimitiveType m_PrimitiveType;
+ bool m_IsIndependent;
+};
+
+#endif // #ifndef __BasicObjectDropSource_H__
diff --git a/src/Authoring/Studio/DragAndDrop/DropContainer.cpp b/src/Authoring/Studio/DragAndDrop/DropContainer.cpp
new file mode 100644
index 00000000..b1ed7a6c
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/DropContainer.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "StudioApp.h"
+#include "DropContainer.h"
+#include "HotKeys.h"
+#include "MouseCursor.h"
+#include "FileDropSource.h"
+#include "ResourceCache.h"
+
+//===============================================================================
+/**
+ * A derived object will call this to subscribe to Drop Flavors.
+ * @param inMainFlavor the Flavor to add.
+ * @see CDropSource.h
+ */
+void CDropContainer::AddMainFlavor(long inMainFlavor)
+{
+ m_Flavors.push_back(inMainFlavor);
+}
+
+//===============================================================================
+/**
+ * This an accessor to get the begining of the iterator.
+ * @return the Iterator
+ */
+CDropContainer::TFlavorItr CDropContainer::GetFlavorBegin()
+{
+ return m_Flavors.begin();
+}
+
+//===============================================================================
+/**
+ * This is an iterator to the end.
+ * @return the Iterator
+ */
+CDropContainer::TFlavorItr CDropContainer::GetFlavorEnd()
+{
+ return m_Flavors.end();
+}
+
+//===============================================================================
+/**
+ * Constructor to build the container.
+ * This also sets up the DropProxy.
+ * @see CDropProxy
+ */
+CWinDropContainer::CWinDropContainer()
+ : m_DropProxy(this)
+{
+}
+//===============================================================================
+/**
+ * Destructor
+ */
+CWinDropContainer::~CWinDropContainer()
+{
+}
+
+//===============================================================================
+/**
+ * This is so the Window that is derived from CWinContainer can receive drags.
+ * @param inWindow the outer to drag.
+ */
+void CWinDropContainer::RegiserForDnd(QWidget *inWindow)
+{
+ // This passes the inWindow down to the COLEDropSource.
+ m_DropProxy.Register(inWindow);
+}
diff --git a/src/Authoring/Studio/DragAndDrop/DropContainer.h b/src/Authoring/Studio/DragAndDrop/DropContainer.h
new file mode 100644
index 00000000..808a5bf4
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/DropContainer.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_DROPCONTAINER
+#define INCLUDED_DROPCONTAINER
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropProxy.h"
+#include "DropSource.h"
+#include <vector>
+
+class CStudioApp;
+
+class CDropContainer
+{
+public:
+ typedef std::vector<long> TFlavor;
+ typedef TFlavor::iterator TFlavorItr;
+
+protected:
+ TFlavor m_Flavors; ///< This is a list of flavors handled by this container.
+
+public:
+ CDropContainer() {}
+ virtual ~CDropContainer() {}
+
+ CDropContainer::TFlavorItr GetFlavorBegin();
+ CDropContainer::TFlavorItr GetFlavorEnd();
+
+ void AddMainFlavor(long inMainFlavor);
+
+ // These need to get implemented by the Cross platform Container.
+ virtual bool OnDragWithin(CDropSource &inSource) = 0;
+ virtual bool OnDragReceive(CDropSource &inSource) = 0;
+ virtual void OnDragLeave() = 0;
+ virtual void OnReflectMouse(CPt &inPoint, Qt::KeyboardModifiers inFlags) = 0;
+};
+
+class CWinDropContainer : public CDropContainer
+{
+public:
+ CWinDropContainer();
+ virtual ~CWinDropContainer();
+
+ void RegiserForDnd(QWidget *inWindow);
+ long ReflectMouse(long inX, long inY);
+
+protected:
+ // These are utility functions.
+ CDropProxy m_DropProxy; ///< The COLEDropSource pass through.
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/DragAndDrop/DropSource.cpp b/src/Authoring/Studio/DragAndDrop/DropSource.cpp
new file mode 100644
index 00000000..06a3fc8a
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/DropSource.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "DropTarget.h"
+#include "StudioObjectTypes.h"
+#include "HotKeys.h"
+#include "Doc.h"
+#include "IDragable.h"
+#include "FileDropSource.h"
+#include "ExplorerFileDropSource.h"
+#include "TimelineDropSource.h"
+#include "BasicObjectDropSource.h"
+#include "ListBoxDropSource.h"
+
+CDropSource::CDropSource(long inFlavor, unsigned long inSize)
+ : m_Flavor(inFlavor)
+ , m_Size(inSize)
+ , m_ObjectType(0)
+ , m_HasValidTarget(false)
+ , m_CurrentFlags(0)
+{
+}
+
+CDropSource::~CDropSource()
+{
+}
+
+CDropSource *CDropSourceFactory::Create(long inFlavor, void *inData, unsigned long inSize)
+{
+ CDropSource *theDropSource(nullptr);
+ switch (inFlavor) {
+
+ case EUIC_FLAVOR_FILE: {
+ theDropSource = new CExplorerFileDropSource(inFlavor, inData, inSize);
+ } break;
+ case EUIC_FLAVOR_TEXT:
+ // Don't do anythiing for this
+ break;
+
+ case EUIC_FLAVOR_ASSET_UICFILE:
+ // make an Aset out of this.
+ theDropSource = new CFileDropSource(inFlavor, inData, inSize);
+ break;
+ }
+
+ return theDropSource;
+}
+
+CDropSource *CDropSourceFactory::Create(long inFlavor, IDragable *inDragable)
+{
+ CDropSource *theDropSource(nullptr);
+ switch (inFlavor) {
+ case EUIC_FLAVOR_LISTBOX:
+ theDropSource = new CListBoxDropSource(inFlavor, inDragable);
+ break;
+
+ case EUIC_FLAVOR_BASIC_OBJECTS:
+ theDropSource = new CBasicObjectDropSource(inFlavor, inDragable);
+ break;
+
+ case EUIC_FLAVOR_ASSET_TL:
+ theDropSource = new CTimeLineDropSource(inFlavor, inDragable);
+ break;
+
+ default:
+ theDropSource = Create(inFlavor, reinterpret_cast<void *>(inDragable), sizeof(inDragable));
+ }
+
+ return theDropSource;
+}
+
+CDropSource *CDropSourceFactory::Extract(long inFlavor, void *inData, unsigned long /*inSize*/)
+{
+ CDropSource *theDropSource(nullptr);
+ switch (inFlavor) {
+ // For all of the Studio Flavors we just need to extract the dropsource out of it.
+ case EUIC_FLAVOR_LISTBOX:
+ // make an Aset out of this.
+ theDropSource = static_cast<CListBoxDropSource *>(inData);
+ break;
+
+ case EUIC_FLAVOR_BASIC_OBJECTS:
+ // make an Aset out of this.
+ theDropSource = static_cast<CBasicObjectDropSource *>(inData);
+ break;
+
+ case EUIC_FLAVOR_ASSET_TL:
+ // cast it to the right type just so we don't loose the virtual table.
+ theDropSource = static_cast<CTimeLineDropSource *>(inData);
+ break;
+
+ case EUIC_FLAVOR_ASSET_UICFILE:
+ theDropSource = static_cast<CFileDropSource *>(inData);
+
+ break;
+ default:
+ theDropSource = nullptr;
+ }
+
+ return theDropSource;
+}
diff --git a/src/Authoring/Studio/DragAndDrop/DropSource.h b/src/Authoring/Studio/DragAndDrop/DropSource.h
new file mode 100644
index 00000000..542b14ac
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/DropSource.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifndef INCLUDED_DROPSOURCE
+#define INCLUDED_DROPSOURCE
+
+#include "UICDMHandles.h"
+#include "Pt.h"
+#include "Cmd.h"
+
+#include <QMimeData>
+
+typedef enum _EDROPDESTINATION {
+ EDROPDESTINATION_ON, ///< drop occurs on the target asset
+ EDROPDESTINATION_ABOVE, ///< drop occurs above the target asset
+ EDROPDESTINATION_BELOW ///< drop occurs below the target asset
+} EDROPDESTINATION;
+
+class CDropTarget;
+class IDragable;
+class CStudioApp;
+
+class CDropSource : public QMimeData
+{
+protected:
+ long m_Flavor;
+ unsigned long m_Size;
+
+ UICDM::TInstanceHandleList m_Instances;
+ long m_ObjectType;
+ bool m_HasValidTarget;
+ CPt m_CurrentPoint;
+ Qt::KeyboardModifiers m_CurrentFlags;
+
+public:
+ CDropSource(long inFlavor, unsigned long inSize);
+ virtual ~CDropSource();
+
+ virtual bool CanMove() = 0;
+ virtual bool CanCopy() = 0;
+ long GetObjectType() const { return m_ObjectType; }
+ long GetFlavor() const { return m_Flavor; }
+ virtual bool ValidateTarget(CDropTarget *) = 0;
+
+ virtual bool GetHasValidTarget() const { return m_HasValidTarget; }
+ virtual void SetHasValidTarget(bool inValid) { m_HasValidTarget = inValid; }
+ virtual void InterpretKeyFlags(long) {}
+
+ virtual void SetCurrentPoint(CPt &inPoint) { m_CurrentPoint = inPoint; }
+ virtual CPt GetCurrentPoint() const { return m_CurrentPoint; }
+
+ virtual void SetCurrentFlags(Qt::KeyboardModifiers inFlags) { m_CurrentFlags = inFlags; }
+ virtual Qt::KeyboardModifiers GetCurrentFlags() const { return m_CurrentFlags; }
+
+ virtual CCmd *GenerateAssetCommand(UICDM::CUICDMInstanceHandle, EDROPDESTINATION,
+ UICDM::CUICDMSlideHandle)
+ {
+ return nullptr;
+ }
+ virtual CCmd *GenerateSlideCommand(long) { return nullptr; }
+};
+
+class CDropSourceFactory
+{
+public:
+ static CDropSource *Create(long inFlavor, IDragable *inDragable);
+ static CDropSource *Create(long inFlavor, void *inData, unsigned long inSize);
+ static CDropSource *Extract(long inFlavor, void *inData, unsigned long inSize);
+};
+
+#endif
diff --git a/src/Authoring/Studio/DragAndDrop/DropTarget.cpp b/src/Authoring/Studio/DragAndDrop/DropTarget.cpp
new file mode 100644
index 00000000..2ca783e5
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/DropTarget.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+#include "DropTarget.h"
+
+CDropTarget::CDropTarget()
+ : m_Instance(0)
+ , m_ObjectType(OBJTYPE_UNKNOWN)
+{
+}
+
+bool CDropTarget::CanAddToMaster()
+{
+ long theTargetObjectType = GetObjectType();
+ if (theTargetObjectType == OBJTYPE_SCENE || theTargetObjectType == OBJTYPE_COMPONENT)
+ return true;
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ UICDM::ISlideSystem *theSlideSystem = theDoc->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theTargetSlide = theSlideSystem->GetAssociatedSlide(GetInstance());
+ return theTargetSlide && theSlideSystem->IsMasterSlide(theTargetSlide);
+}
diff --git a/src/Authoring/Studio/DragAndDrop/DropTarget.h b/src/Authoring/Studio/DragAndDrop/DropTarget.h
new file mode 100644
index 00000000..7bbec133
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/DropTarget.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_DROPTARGET
+#define INCLUDED_DROPTARGET
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioObjectTypes.h"
+#include "UICDMHandles.h"
+
+class CDropSource;
+class CStudioApp;
+
+class CDropTarget
+{
+protected:
+ UICDM::CUICDMInstanceHandle m_Instance;
+ long m_ObjectType;
+
+public:
+ CDropTarget();
+ virtual ~CDropTarget() {}
+
+ virtual bool Accept(CDropSource &inSource) = 0;
+ virtual bool Drop(CDropSource &inSource) = 0;
+ virtual long GetObjectType() = 0;
+
+ virtual void SetInstance(UICDM::CUICDMInstanceHandle inInstance) { m_Instance = inInstance; }
+ virtual UICDM::CUICDMInstanceHandle GetInstance() { return m_Instance; }
+
+ virtual bool IsRelative(UICDM::CUICDMInstanceHandle) { return false; }
+ virtual bool IsSelf(UICDM::CUICDMInstanceHandle) { return false; }
+ virtual bool IsMaster() { return false; }
+ virtual bool CanAddToMaster();
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.cpp b/src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.cpp
new file mode 100644
index 00000000..f32cbe9b
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "ExplorerFileDropSource.h"
+#include "Dialogs.h"
+#include "DropTarget.h"
+#include "StudioObjectTypes.h"
+#include "IDragable.h"
+#include "UICFileTools.h"
+#include "ImportUtils.h"
+
+bool CExplorerFileDropSource::s_FileHasValidTarget = false;
+
+//===============================================================================
+/**
+ *
+ */
+bool CExplorerFileDropSource::ValidateTarget(CDropTarget *inTarget)
+{
+ // Check the type is valid and if target can accept
+ bool theValidTarget =
+ ((m_ObjectType != OBJTYPE_UNKNOWN) && (inTarget->GetObjectType() == EUIC_FLAVOR_FILE));
+ SetHasValidTarget(theValidTarget);
+
+ return theValidTarget;
+}
+
+//===============================================================================
+/**
+ *
+ */
+CExplorerFileDropSource::CExplorerFileDropSource(long inFlavor, void *inData, unsigned long inSize)
+ : CDropSource(inFlavor, inSize)
+ , m_File("")
+{
+ // Pull out all of the SDropItemData and build a file.
+ m_File = *(CUICFile *)inData;
+ Q3DStudio::CFilePath thePath(m_File.GetAbsolutePath());
+ m_ObjectType = Q3DStudio::ImportUtils::GetObjectFileTypeForFile(thePath).m_IconType;
+ // Fix because DAE files are the *only* thing you can drop onto the project
+ if (thePath.GetExtension().Compare(CDialogs::GetWideDAEFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)) {
+ m_ObjectType = OBJTYPE_GROUP;
+ }
+#ifdef QT_3DSTUDIO_FBX
+ else if (thePath.GetExtension().Compare(CDialogs::GetWideFbxFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)) {
+ m_ObjectType = OBJTYPE_GROUP;
+ }
+#endif
+}
+
+//===============================================================================
+/**
+ *
+ */
+void CExplorerFileDropSource::SetHasValidTarget(bool inValid)
+{
+ m_HasValidTarget = inValid;
+ CExplorerFileDropSource::s_FileHasValidTarget = inValid;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CExplorerFileDropSource::GetHasValidTarget()
+{
+ return CExplorerFileDropSource::s_FileHasValidTarget;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CExplorerFileDropSource::CanMove()
+{
+ return false;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CExplorerFileDropSource::CanCopy()
+{
+ return true;
+}
diff --git a/src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.h b/src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.h
new file mode 100644
index 00000000..03269aaf
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ExplorerFileDropSource.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __EXPLORERFILEDROPSOURCE_H__
+#define __EXPLORERFILEDROPSOURCE_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropSource.h"
+#include "UICFile.h"
+
+class CStudioApp;
+class CDropTarget;
+
+//==============================================================================
+/**
+ * @class CExplorerFileDropSource
+ * @brief Drop Source for EUIC_FLAVOR_UICFILE
+ *
+ * This class is meant to handle drag and drop for EUIC_FLAVOR_UICFILE,
+ * for example when user drags a file from Explorer Window (outside Studio).
+ */
+class CExplorerFileDropSource : public CDropSource
+{
+protected:
+ CUICFile m_File;
+ static bool s_FileHasValidTarget;
+
+public:
+ CExplorerFileDropSource(long inFlavor, void *inData, unsigned long inSize);
+
+ bool CanMove() override;
+ bool CanCopy() override;
+ bool ValidateTarget(CDropTarget *inTarget) override;
+ bool GetHasValidTarget();
+ void SetHasValidTarget(bool inValid) override;
+ CUICFile GetFile() const { return m_File; }
+};
+
+#endif // #ifndef __EXPLORERFILEDROPSOURCE_H__
diff --git a/src/Authoring/Studio/DragAndDrop/FileDropSource.cpp b/src/Authoring/Studio/DragAndDrop/FileDropSource.cpp
new file mode 100644
index 00000000..a4164e02
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/FileDropSource.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "Dialogs.h"
+#include "FileDropSource.h"
+#include "DropTarget.h"
+#include "StudioObjectTypes.h"
+#include "HotKeys.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "IDocumentEditor.h"
+#include "UICFileTools.h"
+#include "ImportUtils.h"
+
+bool CFileDropSource::s_FileHasValidTarget = false;
+
+//===============================================================================
+/**
+ *
+ */
+bool CFileDropSource::ValidateTarget(CDropTarget *inTarget)
+{
+ using namespace Q3DStudio;
+
+ EStudioObjectType targetType = (EStudioObjectType)inTarget->GetObjectType();
+ bool theValidTarget = false;
+
+ // the only thing we want to do from here is check the type.
+ theValidTarget = CStudioObjectTypes::AcceptableParent(
+ (EStudioObjectType)m_ObjectType, (EStudioObjectType)inTarget->GetObjectType());
+
+ if (!theValidTarget) {
+ SetHasValidTarget(theValidTarget);
+ return theValidTarget;
+ } else {
+ if (CHotKeys::IsKeyDown(Qt::AltModifier) && targetType != OBJTYPE_SCENE
+ && targetType != OBJTYPE_COMPONENT) {
+ UICDM::CUICDMInstanceHandle theTarget = inTarget->GetInstance();
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ IDocumentReader &theReader(theDoc->GetDocumentReader());
+ UICDM::CUICDMSlideHandle toSlide = theReader.GetAssociatedSlide(theTarget);
+ ;
+
+ if (!theReader.IsMasterSlide(toSlide))
+ theValidTarget = false;
+ }
+
+ SetHasValidTarget(theValidTarget);
+ return theValidTarget;
+ }
+}
+
+//===============================================================================
+/**
+ *
+ */
+CFileDropSource::CFileDropSource(long inFlavor, void *inData, unsigned long inSize)
+ : CDropSource(inFlavor, inSize)
+ , m_File("")
+{
+ // Pull out all of the SDropItemData and build a file.
+ m_File = *(CUICFile *)inData;
+ m_ObjectType =
+ Q3DStudio::ImportUtils::GetObjectFileTypeForFile(m_File.GetAbsolutePath()).m_ObjectType;
+}
+
+//===============================================================================
+/**
+ *
+ */
+void CFileDropSource::SetHasValidTarget(bool inValid)
+{
+ m_HasValidTarget = inValid;
+ CFileDropSource::s_FileHasValidTarget = inValid;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CFileDropSource::GetHasValidTarget()
+{
+ return CFileDropSource::s_FileHasValidTarget;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CFileDropSource::CanMove()
+{
+ return false;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CFileDropSource::CanCopy()
+{
+ return true;
+}
+
+CCmd *CFileDropSource::GenerateAssetCommand(UICDM::CUICDMInstanceHandle inTarget,
+ EDROPDESTINATION inDestType,
+ UICDM::CUICDMSlideHandle inSlide)
+{
+ UICDM::CUICDMInstanceHandle theTarget = inTarget;
+
+ CDoc &theDoc(*g_StudioApp.GetCore()->GetDoc());
+ Q3DStudio::CFilePath theFilePath(m_File.GetAbsolutePath());
+ CPt thePoint;
+ // if ( CHotKeys::IsKeyDown( Qt::AltModifier ) )
+ // thePoint = GetCurrentPoint();
+
+ long theStartTime = -1;
+ if (CHotKeys::IsKeyDown(Qt::ControlModifier))
+ theStartTime = theDoc.GetCurrentViewTime();
+
+ if (theFilePath.IsFile()) {
+ Q3DStudio::DocumentEditorFileType::Enum theDocType(
+ Q3DStudio::ImportUtils::GetObjectFileTypeForFile(theFilePath).m_FileType);
+ QString theCommandName;
+ // TODO: internationalize
+ switch (theDocType) {
+ case Q3DStudio::DocumentEditorFileType::DAE:
+ theCommandName = QObject::tr("File Drop DAE File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Import:
+ theCommandName = QObject::tr("File Drop Import File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Image:
+ theCommandName = QObject::tr("File Drop Image File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Behavior:
+ theCommandName = QObject::tr("File Drop Behavior File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Mesh:
+ theCommandName = QObject::tr("File Drop Mesh File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Font:
+ theCommandName = QObject::tr("File Drop Font File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Effect:
+ theCommandName = QObject::tr("File Drop Effect File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Material:
+ theCommandName = QObject::tr("File Drop Material File");
+ break;
+ case Q3DStudio::DocumentEditorFileType::Path:
+ theCommandName = QObject::tr("File Drop Path File");
+ break;
+ }
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(theDoc, theCommandName)
+ ->ImportFile(theDocType, theFilePath, theTarget, inSlide,
+ CDialogs::GetImportFileExtension(),
+ Q3DStudio::ImportUtils::GetInsertTypeForDropType(inDestType), thePoint,
+ theStartTime);
+ }
+ return nullptr;
+}
diff --git a/src/Authoring/Studio/DragAndDrop/FileDropSource.h b/src/Authoring/Studio/DragAndDrop/FileDropSource.h
new file mode 100644
index 00000000..57127b0d
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/FileDropSource.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __FILEDROPSOURCE_H__
+#define __FILEDROPSOURCE_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+// This should go into its own FileDropSourceFile.
+#include "DropSource.h"
+#include "UICFile.h"
+
+class CStudioApp;
+class CDropTarget;
+
+//==============================================================================
+/**
+ * @class CFileDropSource
+ * @brief Drop Source for EUIC_FLAVOR_ASSET_UICFILE
+ *
+ * This class is meant to handle drag and drop for EUIC_FLAVOR_ASSET_UICFILE,
+ * for example when user drags a file from within Studio.
+ */
+class CFileDropSource : public CDropSource
+{
+protected:
+ CUICFile m_File;
+ static bool s_FileHasValidTarget;
+
+public:
+ CFileDropSource(long inFlavor, void *inData, unsigned long inSize);
+
+ bool CanMove() override;
+ bool CanCopy() override;
+ bool ValidateTarget(CDropTarget *inTarget) override;
+ bool GetHasValidTarget();
+ void SetHasValidTarget(bool inValid) override;
+
+ CCmd *GenerateAssetCommand(UICDM::CUICDMInstanceHandle inTarget,
+ EDROPDESTINATION inDestType,
+ UICDM::CUICDMSlideHandle inSlide) override;
+};
+
+#endif // #ifndef __FILEDROPSOURCE_H__
diff --git a/src/Authoring/Studio/DragAndDrop/ListBoxDropSource.cpp b/src/Authoring/Studio/DragAndDrop/ListBoxDropSource.cpp
new file mode 100644
index 00000000..da602679
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ListBoxDropSource.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ListBoxDropSource.h"
+#include "DropTarget.h"
+#include "ListBoxItem.h"
+#include "IDragable.h"
+
+//===============================================================================
+/**
+ * Constructor
+ */
+CListBoxDropSource::CListBoxDropSource(long inFlavor, IDragable *inDragable)
+ : CDropSource(inFlavor, 0)
+{
+ m_Item = reinterpret_cast<CListBoxItem *>(inDragable);
+}
+
+//===============================================================================
+/**
+ * Validate that the drop target is EUIC_FLAVOR_LISTBOX type.
+ * @param inTarget Drop target for validation
+ * @return true if inTarget is EUIC_FLAVOR_LISTBOX; false if otherwise
+ */
+bool CListBoxDropSource::ValidateTarget(CDropTarget *inTarget)
+{
+ bool theValidTarget = (inTarget->GetObjectType() == EUIC_FLAVOR_LISTBOX);
+ SetHasValidTarget(theValidTarget);
+
+ return theValidTarget;
+}
+
+//===============================================================================
+/**
+ * @return true
+ */
+bool CListBoxDropSource::CanMove()
+{
+ return true;
+}
+
+//===============================================================================
+/**
+ * @return true
+ */
+bool CListBoxDropSource::CanCopy()
+{
+ return true;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/DragAndDrop/ListBoxDropSource.h b/src/Authoring/Studio/DragAndDrop/ListBoxDropSource.h
new file mode 100644
index 00000000..a28678d4
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ListBoxDropSource.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __ListBoxDropSource_H__
+#define __ListBoxDropSource_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropSource.h"
+
+class CStudioApp;
+class CDropTarget;
+class CListBoxItem;
+
+class CListBoxDropSource : public CDropSource
+{
+protected:
+ CListBoxItem *m_Item;
+
+public:
+ CListBoxDropSource(long inFlavor, IDragable *inDragable);
+
+ bool CanMove() override;
+ bool CanCopy() override;
+ bool ValidateTarget(CDropTarget *inTarget) override;
+
+ CListBoxItem *GetItem() { return m_Item; }
+};
+
+#endif // #ifndef __ListBoxDropSource_H__
diff --git a/src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.cpp b/src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.cpp
new file mode 100644
index 00000000..752cc430
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ListBoxDropTarget.h"
+#include "ListBoxDropSource.h"
+#include "IDragable.h"
+
+//===============================================================================
+/**
+ * Constructor
+ */
+CListBoxDropTarget::CListBoxDropTarget()
+ : m_Item(nullptr)
+{
+}
+
+//===============================================================================
+/**
+ * This get called on every DragWithin.
+ * Note: the source will validate the target instead of the otherway around.
+ * This is because the DropSource knows how to get information from itself without
+ * creating an asset. This is mainly for DropSources that have a lazy creation idiom.
+ * like files.
+ * @param the DropSource in question.
+ * @return true if the DropSource likes the DropTarget.
+ */
+bool CListBoxDropTarget::Accept(CDropSource &inSource)
+{
+ return inSource.ValidateTarget(this);
+}
+
+//===============================================================================
+/**
+ * This is where is actually happens.
+ * Note: At this point everything should be verified, and setup in the dropsource.
+ * The only thing left to do is to get the Assets and move/copy or connect them.
+ * @param inSource the Object in question.
+ * @return true if the drop was successful .
+ */
+bool CListBoxDropTarget::Drop(CDropSource &inSource)
+{
+ if (m_Item) {
+ inSource;
+ /*
+ CSlideDropSource* theSlideDropSource = static_cast< CSlideDropSource* >(
+ &inSource );
+ CSlideControl* theSlideControl = theSlideDropSource->GetSlide( );
+ CTimeContext* theTimeContext = theSlideControl->GetTimeContext( );
+
+ // Reorder this slide to the position held by this drop target.
+ CCmdRearrangeTimeContext* theCommand = new CCmdRearrangeTimeContext( theTimeContext,
+ m_SlideInsert->GetInsertIndex( ) );
+ if ( theCommand )
+ {
+ theTimeContext->GetAsset( )->ExecuteCommand( theCommand, false );
+ }
+ */
+ }
+
+ // we are always successful
+ return true;
+}
+
+//===============================================================================
+/**
+ * This will get the objec ttype from the Asset.
+ * Note: The asset can change all of the time, so i always ask the asset for its type.
+ * @return the Studio object type.
+ */
+long CListBoxDropTarget::GetObjectType()
+{
+ return EUIC_FLAVOR_LISTBOX;
+}
+
+//===============================================================================
+/**
+ * Set the SlideInsertionControl that is the drop target
+ */
+void CListBoxDropTarget::SetItem(CListBoxItem *inItem)
+{
+ m_Item = inItem;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.h b/src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.h
new file mode 100644
index 00000000..44199092
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ListBoxDropTarget.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __ListBoxDropTarget_H__
+#define __ListBoxDropTarget_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropTarget.h"
+
+class CDropSource;
+class CListBoxItem;
+
+//==============================================================================
+/**
+ * @class
+ * @brief justin.ebert needs to enter a brief description here.
+ *
+ * justin.ebert needs to enter a long description here.
+ */
+class CListBoxDropTarget : public CDropTarget
+{
+protected:
+ CListBoxItem *m_Item; ///< The list item that we can drop on
+
+public:
+ CListBoxDropTarget();
+ bool Accept(CDropSource &inSource) override;
+ bool Drop(CDropSource &inSource) override;
+ long GetObjectType() override;
+
+ void SetItem(CListBoxItem *inItem);
+};
+
+#endif // #ifndef __ListBoxDropTarget_H__
diff --git a/src/Authoring/Studio/DragAndDrop/ProjectDropTarget.cpp b/src/Authoring/Studio/DragAndDrop/ProjectDropTarget.cpp
new file mode 100644
index 00000000..5344d459
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ProjectDropTarget.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "ProjectDropTarget.h"
+#include "DropSource.h"
+#include "ExplorerFileDropSource.h"
+#include "IDragable.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "Dialogs.h"
+#include "Doc.h"
+#include "UICFile.h"
+#include "UICFileTools.h"
+#include "UICImportPerformImport.h"
+#include "UICImportTranslation.h"
+#include "IDocumentEditor.h"
+#include "PathImportTranslator.h"
+
+//===============================================================================
+/**
+ * Constructor
+ */
+CProjectDropTarget::CProjectDropTarget(const Q3DStudio::CFilePath &inTargetDir)
+ : m_TargetDir(inTargetDir)
+{
+}
+
+//===============================================================================
+/**
+ * This get called on every DragWithin.
+ * Note: the source will validate the target instead of the otherway around.
+ * This is because the DropSource knows how to get information from itself without
+ * creating an asset. This is mainly for DropSources that have a lazy creation idiom.
+ * like files.
+ * @param the DropSource in question.
+ * @return true if the DropSource likes the DropTarget.
+ */
+bool CProjectDropTarget::Accept(CDropSource &inSource)
+{
+ return inSource.ValidateTarget(this);
+}
+
+//===============================================================================
+/**
+ * This is where is actually happens.
+ * Note: At this point everything should be verified, and setup in the dropsource.
+ * The only thing left to do is to get the Assets and move/copy or connect them.
+ * @param inSource the Object in question.
+ * @return true if the drop was successful .
+ */
+bool CProjectDropTarget::Drop(CDropSource &inSource)
+{
+ using namespace Q3DStudio;
+ using namespace UICIMP;
+ // Drag and Drop - From Explorer window to Project Palette
+ // For all valid Project File Types:
+ // - This performs a file copy from the source Explorer location to the selected Project Palette
+ // Folder
+ // - The destination copy must NOT be read-only even if the source is read-only
+ // For DAE, it will import the file.
+ if (inSource.GetFlavor() == EUIC_FLAVOR_FILE) {
+ // Create target directory if it doesn't exist
+ if (!m_TargetDir.Exists())
+ m_TargetDir.CreateDir(true);
+ // also make sure that target directory is a directory, not a file
+ else if (m_TargetDir.IsFile())
+ m_TargetDir = m_TargetDir.GetDirectory();
+
+ // Sanity check
+ ASSERT(m_TargetDir.IsDirectory());
+
+ // Get the Source file to be copied
+ CExplorerFileDropSource *theFileDropSource =
+ static_cast<CExplorerFileDropSource *>(&inSource);
+ CFilePath theSourceFile(theFileDropSource->GetFile().GetAbsolutePath());
+
+ if (theSourceFile.IsFile() && m_TargetDir.IsDirectory()) {
+ // Get the file extension
+ Q3DStudio::CString theExtension(theSourceFile.GetExtension());
+
+ Q3DStudio::CString theFileStem = theSourceFile.GetFileStem();
+ Q3DStudio::CString outputFileName(theFileStem + L"."
+ + CDialogs::GetImportFileExtension());
+
+ if (theExtension.Compare(CDialogs::GetWideDAEFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)) {
+ SColladaTranslator theTranslator(theSourceFile.toQString());
+
+ CFilePath theOutputDir =
+ SFileTools::FindUniqueDestDirectory(m_TargetDir, theFileStem);
+ CFilePath theFullOutputFile(
+ CFilePath::CombineBaseAndRelative(theOutputDir, outputFileName));
+ SImportResult theImportResult =
+ CPerformImport::TranslateToImportFile(theTranslator, theFullOutputFile);
+ bool forceError = theFullOutputFile.IsFile() == false;
+ IDocumentEditor::DisplayImportErrors(
+ theSourceFile.toQString(), theImportResult.m_Error,
+ g_StudioApp.GetCore()->GetDoc()->GetImportFailedHandler(),
+ theTranslator.m_TranslationLog, forceError);
+#ifdef QT_3DSTUDIO_FBX
+ } else if (theExtension.Compare(CDialogs::GetWideFbxFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)) {
+ SFbxTranslator theTranslator(theSourceFile.toQString());
+
+ CFilePath theOutputDir =
+ SFileTools::FindUniqueDestDirectory(m_TargetDir, theFileStem);
+ CFilePath theFullOutputFile(
+ CFilePath::CombineBaseAndRelative(theOutputDir, outputFileName));
+ SImportResult theImportResult =
+ CPerformImport::TranslateToImportFile(theTranslator, theFullOutputFile);
+ bool forceError = theFullOutputFile.IsFile() == false;
+ IDocumentEditor::DisplayImportErrors(
+ theSourceFile.toQString(), theImportResult.m_Error,
+ g_StudioApp.GetCore()->GetDoc()->GetImportFailedHandler(),
+ theTranslator.m_TranslationLog, forceError);
+#endif
+ } else if (theExtension.Compare(L"svg", Q3DStudio::CString::ENDOFSTRING, false)) {
+ IDocumentReader &theReader(g_StudioApp.GetCore()->GetDoc()->GetDocumentReader());
+ SPathImportTranslator theTranslator(theSourceFile.toQString(), *theReader.GetLuaContext(),
+ theReader.GetFoundation());
+ CFilePath theOutputDir =
+ SFileTools::FindUniqueDestDirectory(m_TargetDir, theFileStem);
+ CFilePath theFullOutputFile(
+ CFilePath::CombineBaseAndRelative(theOutputDir, outputFileName));
+ SImportResult theImportResult =
+ CPerformImport::TranslateToImportFile(theTranslator, theFullOutputFile);
+ bool forceError = theFullOutputFile.IsFile() == false;
+ IDocumentEditor::DisplayImportErrors(
+ theSourceFile.toQString(), theImportResult.m_Error,
+ g_StudioApp.GetCore()->GetDoc()->GetImportFailedHandler(),
+ theTranslator.m_TranslationLog, forceError);
+ } else {
+ // Copy the file to target directory
+ // FindAndCopyDestFile will make sure the file name is unique and make sure it is
+ // not read only.
+ SFileErrorCodeFileNameAndNumBytes theCopyResult = SFileTools::FindAndCopyDestFile(
+ m_TargetDir, CFilePath::GetAbsolutePath(theSourceFile));
+
+ // Sanity check
+ ASSERT(theCopyResult.m_Error == Q3DStudio::FileErrorCodes::NoError);
+ ASSERT(theCopyResult.m_DestFilename.Exists());
+
+ // For effect and custom material files, automatically copy related resources
+ if (CDialogs::IsEffectFileExtension(theExtension)
+ || CDialogs::IsMaterialFileExtension(theExtension)) {
+ std::shared_ptr<IImportFailedHandler> theHandler(
+ g_StudioApp.GetCore()->GetDoc()->GetImportFailedHandler());
+ CFilePath theShaderFile(theSourceFile);
+
+ if (theShaderFile.GetExtension() != "effect"
+ && theShaderFile.GetExtension() != "material") {
+ ASSERT(false); // what file is this?
+ } else {
+ }
+
+ std::vector<Q3DStudio::CString> theEffectFileSourcePaths;
+ g_StudioApp.GetCore()
+ ->GetDoc()
+ ->GetDocumentReader()
+ .ParseSourcePathsOutOfEffectFile(
+ Q3DStudio::CFilePath::GetAbsolutePath(theSourceFile),
+ theEffectFileSourcePaths);
+
+ CFilePath theFileDir(
+ Q3DStudio::CFilePath::GetAbsolutePath(theSourceFile).GetDirectory());
+ CFilePath theDocumentDir(
+ g_StudioApp.GetCore()->GetDoc()->GetDocumentDirectory());
+ for (size_t idx = 0; idx < theEffectFileSourcePaths.size(); ++idx) {
+ CFilePath theSourcePath = CFilePath::CombineBaseAndRelative(
+ theFileDir, theEffectFileSourcePaths[idx]);
+ CFilePath theResultPath = CFilePath::CombineBaseAndRelative(
+ theDocumentDir, theEffectFileSourcePaths[idx]);
+ CFilePath theResultDir(theResultPath.GetDirectory());
+ theResultDir.CreateDir(true);
+ // If the file already exists, these file flags will ensure it won't get
+ // overwritten.
+ SFileTools::Copy(theResultPath,
+ qt3ds::foundation::FileOpenFlags(
+ qt3ds::foundation::FileOpenFlagValues::Create
+ | qt3ds::foundation::FileOpenFlagValues::Write),
+ theSourcePath);
+ }
+ }
+ }
+ }
+ }
+
+ // we are always successful
+ return true;
+}
+
+//===============================================================================
+/**
+ * This will get the objec ttype from the Asset.
+ * Note: The asset can change all of the time, so i always ask the asset for its type.
+ * @return the Studio object type.
+ */
+long CProjectDropTarget::GetObjectType()
+{
+ return EUIC_FLAVOR_FILE;
+}
diff --git a/src/Authoring/Studio/DragAndDrop/ProjectDropTarget.h b/src/Authoring/Studio/DragAndDrop/ProjectDropTarget.h
new file mode 100644
index 00000000..234c30ed
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/ProjectDropTarget.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __PROJECTDROPTARGET_H__
+#define __PROJECTDROPTARGET_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropTarget.h"
+#include "UICFileTools.h"
+
+class CDropSource;
+
+//==============================================================================
+/**
+ * @class CProjectDropTarget
+ * @brief Drop Target for Project Palette
+ */
+class CProjectDropTarget : public CDropTarget
+{
+public:
+ CProjectDropTarget(const Q3DStudio::CFilePath &inTargetDir);
+
+ bool Accept(CDropSource &inSource) override;
+ bool Drop(CDropSource &inSource) override;
+ long GetObjectType() override;
+
+protected:
+ Q3DStudio::CFilePath m_TargetDir; ///< The target directory to copy file to.
+};
+
+#endif // #ifndef __PROJECTDROPTARGET_H__
diff --git a/src/Authoring/Studio/DragAndDrop/SceneDropTarget.cpp b/src/Authoring/Studio/DragAndDrop/SceneDropTarget.cpp
new file mode 100644
index 00000000..47850e80
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/SceneDropTarget.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SceneDropTarget.h"
+#include "DropTarget.h"
+#include "DropSource.h"
+
+#include "StudioApp.h"
+#include "Doc.h"
+
+#include "HotKeys.h"
+#include "IDropTargetHelper.h"
+#include "Core.h"
+#include "GraphUtils.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMDataCore.h"
+#include "UICDMSlides.h"
+
+// Sceneview stuff
+//===============================================================================
+/**
+ * Constructor.
+ */
+CSceneViewDropTarget::CSceneViewDropTarget()
+ : m_DropTime(-1)
+{
+ m_ObjectType = OBJTYPE_LAYER;
+ m_DropSourceObjectType = OBJTYPE_UNKNOWN;
+}
+
+//===============================================================================
+/**
+ * This will get the objec ttype from the Asset.
+ * Note: The asset can change all of the time, so i always ask the asset for its type.
+ * @return the Studio object type.
+ */
+long CSceneViewDropTarget::GetObjectType()
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+
+ if (theInstance.Valid()) {
+ CClientDataModelBridge *theBridge =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+ m_ObjectType = theBridge->GetObjectType(theInstance);
+ return m_ObjectType;
+ }
+ return OBJTYPE_UNKNOWN;
+}
+
+//===============================================================================
+/**
+ * This get called on every DragWithin.
+ * Note: the source will validate the target instead of the otherway around.
+ * This is because the DropSource knows how to get information from itself without
+ * creating an asset. This is mainly for DropSources that have a lazy creation idiom.
+ * like files.
+ * Dropping into "locked" layers are not allowed.
+ * @param inSource the DropSource in question.
+ * @return true if the DropSource likes the DropTarget.
+ */
+bool CSceneViewDropTarget::Accept(CDropSource &inSource)
+{
+ CClientDataModelBridge *theBridge =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+
+ // We have to set this so we can adjust the Target to accept this source.
+ SetDropSourceObjectType(inSource.GetObjectType());
+
+ bool theAcceptable = false;
+
+ // We don't want to generate an asset right now so let the DropSource ask us if it can drop.
+ theAcceptable = inSource.ValidateTarget(this);
+
+ // The DropSource already generated the asset for this in the above.
+ if (theAcceptable && m_Instance.Valid()) {
+ theAcceptable = !theBridge->IsLockedAtAll(m_Instance);
+ }
+
+ return theAcceptable;
+}
+
+//===============================================================================
+/**
+ * This is so the questioned object type can be cached so we can get the correct asset.
+ * @param inObjType the object type of the Questioned object.
+ */
+void CSceneViewDropTarget::SetDropSourceObjectType(long inObjType)
+{
+ m_DropSourceObjectType = inObjType;
+}
+
+//===============================================================================
+/**
+ * This is where is actually happens.
+ * Note: At this point either everything should be verified, and setup in the dropsource.
+ * Then the only thing left to do is to get the Assets and move/copy or connect them.
+ * Or the dropsource needs the target to perform the actual drop.
+ * Note that if the Control key is depressed, the start time follows the current view time(
+ *i.e. playhead position )
+ * And if the Alt key (KEY_MENU) is depressed, the object is dropped at the mouse location.
+ *
+ * @param inSource the Object in question.
+ * @return true if the drop was successful .
+ */
+bool CSceneViewDropTarget::Drop(CDropSource &inSource)
+{
+ // The Parent is a tree control item, so iwe know it can be converted to an Asset.
+
+ // We have to set this so we can adjust the Target to accept this source.
+ SetDropSourceObjectType(inSource.GetObjectType());
+
+ UICDM::CUICDMInstanceHandle theTargetInstance = GetInstance();
+ if (theTargetInstance.Valid()) {
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ UICDM::ISlideSystem *theSlideSystem = theDoc->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlide = theDoc->GetActiveSlide();
+ if (!theSlideSystem->IsMasterSlide(theSlide)
+ && (inSource.GetCurrentFlags() & CHotKeys::MODIFIER_ALT)) {
+ if (CanAddToMaster()) {
+ UICDM::CUICDMSlideHandle theMasterSlideHandle =
+ theSlideSystem->GetMasterSlide(theSlide);
+ if (theMasterSlideHandle.Valid())
+ theSlide = theMasterSlideHandle;
+ }
+ }
+ CCmd *command =
+ inSource.GenerateAssetCommand(theTargetInstance, EDROPDESTINATION_ON, theSlide);
+ if (command != nullptr)
+ theDoc->GetCore()->ExecuteCommand(command);
+ }
+
+ return true;
+}
+
+//===============================================================================
+/**
+ * @return the Asset that we would like the DropSource to drop on to.
+ */
+UICDM::CUICDMInstanceHandle CSceneViewDropTarget::GetInstance()
+{
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ UICDM::CUICDMInstanceHandle theRootObject = theDoc->GetActiveRootInstance();
+ EStudioObjectType theRootObjType =
+ theDoc->GetStudioSystem()->GetClientDataModelBridge()->GetObjectType(theRootObject);
+
+ // Check if the inObjectType can just go ahead and drop onto the Root object.
+ if (CStudioObjectTypes::AcceptableParent((EStudioObjectType)m_DropSourceObjectType,
+ theRootObjType)) {
+ m_Instance = theRootObject;
+ } else if (theRootObject == theDoc->GetSceneInstance()
+ && CStudioObjectTypes::AcceptableParent((EStudioObjectType)m_DropSourceObjectType,
+ OBJTYPE_LAYER)) {
+ m_Instance = theDoc->GetActiveLayer();
+ }
+
+ return m_Instance;
+}
+
+//===============================================================================
+/**
+ * Check to see if the Asset is a relative of our asset.
+ * @return true if the inAsset is a parent grandparent...etc. of this asset.
+ */
+bool CSceneViewDropTarget::IsRelative(UICDM::CUICDMInstanceHandle inInstance)
+{
+ bool theReturn = false;
+
+ UICDM::CUICDMInstanceHandle theThisInstance = GetInstance();
+ // This will check to see if the inAsset is already a parent, grandparent....etc.
+ if (theThisInstance.Valid())
+ theReturn = IsAscendant(theThisInstance, inInstance,
+ g_StudioApp.GetCore()->GetDoc()->GetAssetGraph());
+ return theReturn;
+}
+
+//===============================================================================
+/**
+ * Check to see if the inAsset is our asset.
+ * @param inAsset The Asset to check.
+ * @return true if we are the same.
+ */
+bool CSceneViewDropTarget::IsSelf(UICDM::CUICDMInstanceHandle inInstance)
+{
+ UICDM::CUICDMInstanceHandle theThisInstance = GetInstance();
+ return (theThisInstance == inInstance);
+}
+
+//===============================================================================
+/**
+ * Set the Drop time for all sources.
+ * @param inDropTime The time to drop the source.
+ */
+void CSceneViewDropTarget::SetDropTime(long inDropTime)
+{
+ m_DropTime = inDropTime;
+}
+
+//===============================================================================
+/**
+ * @return The time that all sources will be droped.
+ */
+long CSceneViewDropTarget::GetDropTime()
+{
+ return m_DropTime;
+}
+
+// Last Sceneview related stuff.
diff --git a/src/Authoring/Studio/DragAndDrop/SceneDropTarget.h b/src/Authoring/Studio/DragAndDrop/SceneDropTarget.h
new file mode 100644
index 00000000..cdcb7afc
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/SceneDropTarget.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __SCENEDROPTARGET_H__
+#define __SCENEDROPTARGET_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropTarget.h"
+
+//==============================================================================
+/**
+ * @class
+ * @brief LEONARD.PONCE needs to enter a brief description here.
+ *
+ * LEONARD.PONCE needs to enter a long description here.
+ */
+class CSceneViewDropTarget : public CDropTarget
+{
+protected:
+ long m_DropTime; ///< The Time to drop any thing.
+ long m_DropSourceObjectType;
+
+public:
+ CSceneViewDropTarget();
+ bool Accept(CDropSource &inSource) override;
+ bool Drop(CDropSource &inSource) override;
+ UICDM::CUICDMInstanceHandle GetInstance() override;
+
+ bool IsRelative(UICDM::CUICDMInstanceHandle inInstance) override;
+ bool IsSelf(UICDM::CUICDMInstanceHandle inInstance) override;
+ long GetObjectType() override;
+ void SetDropSourceObjectType(long inObjType);
+ void SetDropTime(long inDropTime);
+ long GetDropTime();
+};
+#endif // #ifndef __SCENEDROPTARGET_H__
diff --git a/src/Authoring/Studio/DragAndDrop/TimelineDropSource.cpp b/src/Authoring/Studio/DragAndDrop/TimelineDropSource.cpp
new file mode 100644
index 00000000..cf664825
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/TimelineDropSource.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TimelineDropSource.h"
+#include "FileDropSource.h"
+#include "Dispatch.h"
+#include "DropTarget.h"
+#include "StudioObjectTypes.h"
+#include "HotKeys.h"
+#include "Core.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+#include "Bindings/UICDMTimelineItemBinding.h"
+#include "IDocumentEditor.h"
+#include "ImportUtils.h"
+
+#pragma warning(disable : 4100)
+
+using namespace Q3DStudio;
+
+//===============================================================================
+/**
+ *
+ */
+CTimeLineDropSource::CTimeLineDropSource(long inFlavor, IDragable *inDraggable)
+ : CDropSource(inFlavor, sizeof(inDraggable))
+{
+ m_Copy = true;
+
+ m_Instances = g_StudioApp.GetCore()->GetDoc()->GetSelectedValue().GetSelectedInstances();
+ if (m_Instances.size())
+ m_ObjectType = g_StudioApp.GetCore()
+ ->GetDoc()
+ ->GetStudioSystem()
+ ->GetClientDataModelBridge()
+ ->GetObjectType(m_Instances[0]);
+ else
+ m_ObjectType = OBJTYPE_UNKNOWN;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CTimeLineDropSource::CanMove()
+{
+ return !m_Copy;
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CTimeLineDropSource::CanCopy()
+{
+ bool theReturn = false;
+ // This is here because some Assets can not be copied ( scene, material )
+ theReturn = m_Copy && g_StudioApp.GetCore()->GetDoc()->CanCopyObject(m_Instances);
+
+ return theReturn;
+}
+
+//===============================================================================
+/**
+ *
+ */
+void CTimeLineDropSource::InterpretKeyFlags(long inModifyerKeys)
+{
+ m_Copy = ((inModifyerKeys & CHotKeys::MODIFIER_CONTROL) != 0);
+}
+
+//===============================================================================
+/**
+ *
+ */
+bool CTimeLineDropSource::ValidateTarget(CDropTarget *inTarget)
+{
+ // the only thing we want to do from here is check the type.
+ bool theValidTarget = CStudioObjectTypes::AcceptableParent(
+ (EStudioObjectType)GetObjectType(), (EStudioObjectType)inTarget->GetObjectType());
+
+ for (size_t idx = 0, end = m_Instances.size(); idx < end && theValidTarget; ++idx) {
+ UICDM::CUICDMInstanceHandle theHandle(m_Instances[idx]);
+
+ if (theValidTarget && theHandle.Valid()) {
+ theValidTarget &= (!inTarget->IsSelf(theHandle) && !inTarget->IsRelative(theHandle));
+ UICDM::ISlideSystem *theSlideSystem =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetAssociatedSlide(theHandle);
+ bool theIsMaster = theSlideSystem->IsMasterSlide(theSlide);
+
+ theValidTarget &= !(theIsMaster && !inTarget->IsMaster());
+ }
+ }
+
+ SetHasValidTarget(theValidTarget);
+
+ return theValidTarget;
+}
+
+using namespace UICDM;
+using namespace Q3DStudio;
+
+inline void Rearrange(CDoc &inDoc, const UICDM::TInstanceHandleList &inInstances,
+ CUICDMInstanceHandle inTarget, DocumentEditorInsertType::Enum inInsertType)
+{
+ SCOPED_DOCUMENT_EDITOR(inDoc, QObject::tr("Rearrange Object"))
+ ->RearrangeObjects(inInstances, inTarget, inInsertType);
+}
+
+CCmd *CTimeLineDropSource::GenerateAssetCommand(UICDM::CUICDMInstanceHandle inTarget,
+ EDROPDESTINATION inDestType,
+ UICDM::CUICDMSlideHandle inSlide)
+{
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ CClientDataModelBridge *theBridge = theDoc->GetStudioSystem()->GetClientDataModelBridge();
+
+ if (CanCopy()) {
+ SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Duplicate Object"))
+ ->DuplicateInstances(m_Instances, inTarget,
+ ImportUtils::GetInsertTypeForDropType(inDestType));
+ } else {
+ // We can't do the rearrange inline because it deletes a timeline item.
+ // So we will effectively postmessage and do it out of line.
+ theDoc->GetCore()->GetDispatch()->FireOnAsynchronousCommand(
+ std::bind(Rearrange, std::ref(*theDoc), m_Instances, inTarget,
+ ImportUtils::GetInsertTypeForDropType(inDestType)));
+ }
+
+ return nullptr;
+}
diff --git a/src/Authoring/Studio/DragAndDrop/TimelineDropSource.h b/src/Authoring/Studio/DragAndDrop/TimelineDropSource.h
new file mode 100644
index 00000000..3a385518
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/TimelineDropSource.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __TIMELINEDROPSOURCE_H__
+#define __TIMELINEDROPSOURCE_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioApp.h"
+#include "DropSource.h"
+
+//==============================================================================
+// Forward
+//==============================================================================
+class CDropTarget;
+class IDragable;
+
+class CTimeLineDropSource : public CDropSource
+{
+protected:
+ bool m_Copy;
+
+public:
+ CTimeLineDropSource(long inFlavor, IDragable *inDraggable);
+
+ bool CanMove() override;
+ bool CanCopy() override;
+ bool ValidateTarget(CDropTarget *inTarget) override;
+ void InterpretKeyFlags(long inModifyerKeys) override;
+
+ CCmd *GenerateAssetCommand(UICDM::CUICDMInstanceHandle inTarget,
+ EDROPDESTINATION inDestType,
+ UICDM::CUICDMSlideHandle inSlide) override;
+};
+
+#endif // #ifndef __TIMELINEDROPSOURCE_H__
diff --git a/src/Authoring/Studio/DragAndDrop/TimelineDropTarget.cpp b/src/Authoring/Studio/DragAndDrop/TimelineDropTarget.cpp
new file mode 100644
index 00000000..25a1352b
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/TimelineDropTarget.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "TimelineDropTarget.h"
+#include "StudioApp.h"
+#include "DropSource.h"
+#include "HotKeys.h"
+#include "Core.h"
+#include "Doc.h"
+#include "IDropTargetHelper.h"
+#include "GraphUtils.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+
+// Timeline stuff
+
+//===============================================================================
+/**
+ * This get called on every DragWithin.
+ * Note: the source will validate the target instead of the otherway around.
+ * This is because the DropSource knows how to get information from itself without
+ * creating an asset. This is mainly for DropSources that have a lazy creation idiom.
+ * like files.
+ * @param the DropSource in question.
+ * @return true if the DropSource likes the DropTarget.
+ */
+bool CTimeLineDropTarget::Accept(CDropSource &inSource)
+{
+ bool theDropFlag = inSource.ValidateTarget(this);
+ return theDropFlag;
+}
+
+//===============================================================================
+/**
+ * This is where is actually happens.
+ * Note: At this point either everything should be verified, and setup in the dropsource.
+ * Then the only thing left to do is to get the Assets and move/copy or connect them.
+ * Or the dropsource needs the target to perform the actual drop.
+ * Note that if the Control key is depressed, the start time follows the current view time(
+ *i.e. playhead position )
+ *
+ * @param inSource the Object in question.
+ * @return true if the drop was successful .
+ */
+bool CTimeLineDropTarget::Drop(CDropSource &inSource)
+{
+ UICDM::CUICDMInstanceHandle theTargetInstance = GetInstance();
+
+ if (theTargetInstance.Valid()) {
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ UICDM::ISlideSystem *theSlideSystem = theDoc->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlide = theDoc->GetActiveSlide();
+ if (!theSlideSystem->IsMasterSlide(theSlide)
+ && (inSource.GetCurrentFlags() & CHotKeys::MODIFIER_ALT)) {
+ if (CanAddToMaster()) {
+ UICDM::CUICDMSlideHandle theMasterSlideHandle =
+ theSlideSystem->GetMasterSlide(theSlide);
+ if (theMasterSlideHandle.Valid())
+ theSlide = theMasterSlideHandle;
+ }
+ }
+ CCmd *theCmd = inSource.GenerateAssetCommand(theTargetInstance, m_Destination, theSlide);
+ if (theCmd)
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ }
+
+ return true;
+}
+
+//===============================================================================
+/**
+ * This will get the objec ttype from the Asset.
+ * Note: The asset can change all of the time, so i always ask the asset for its type.
+ * @return the Studio object type.
+ */
+long CTimeLineDropTarget::GetObjectType()
+{
+ UICDM::CUICDMInstanceHandle theTargetInstance = GetTargetInstance();
+ if (theTargetInstance.Valid()) {
+ CClientDataModelBridge *theBridge =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+ return theBridge->GetObjectType(theTargetInstance);
+ }
+
+ return m_ObjectType;
+}
+
+//===============================================================================
+/**
+ * Check to see if the Asset is a relative of our asset.
+ * @return true if the inAsset is a parent grandparent...etc. of this asset.
+ */
+bool CTimeLineDropTarget::IsRelative(UICDM::CUICDMInstanceHandle inInstance)
+{
+ bool theReturn = false; ///< Default return value.
+ UICDM::CUICDMInstanceHandle theThisInstance = GetInstance();
+
+ // This will check to see if the inAsset is already some sort of parent grandparent....etc.
+ if (theThisInstance.Valid())
+ theReturn = IsAscendant(theThisInstance, inInstance,
+ g_StudioApp.GetCore()->GetDoc()->GetAssetGraph());
+
+ return theReturn;
+}
+
+//===============================================================================
+/**
+ * Check to see if the inAsset is our asset.
+ * @param inAsset The Asset to check.
+ * @return true if we are the same.
+ */
+bool CTimeLineDropTarget::IsSelf(UICDM::CUICDMInstanceHandle inInstance)
+{
+ UICDM::CUICDMInstanceHandle theThisInstance = GetInstance();
+ // true if self.....
+ return (theThisInstance == inInstance);
+}
+
+//===============================================================================
+/**
+ * This method is used to detirmine validity for dropping on Master items.
+ * We do not allow Master items to be dropped on non-master targets because
+ * it does not make any hierarchical sense. Also checks for NULL and Scene object.
+ * (The scene object reports as a master object so that we can re-arrange layers (On the master
+ *slide).)
+ * Changed checking for scene to checking for root object, which may be a component. This
+ * would allow for the root component (as in edit component) to re-arrange its children, even if
+ *either
+ * party is not a master.
+ * @param inAsset The Asset to check.
+ * @return true if we are the same.
+ */
+bool CTimeLineDropTarget::IsMaster()
+{
+ if (!m_Instance.Valid())
+ return true;
+ else if (m_Instance == g_StudioApp.GetCore()->GetDoc()->GetActiveRootInstance())
+ return true;
+ else {
+ UICDM::ISlideSystem *theSlideSystem =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetAssociatedSlide(m_Instance);
+ return theSlideSystem->IsMasterSlide(theSlide);
+ }
+}
+
+void CTimeLineDropTarget::SetDestination(EDROPDESTINATION inDestination)
+{
+ m_Destination = inDestination;
+}
+
+EDROPDESTINATION CTimeLineDropTarget::GetDestination() const
+{
+ return m_Destination;
+}
+
+//===============================================================================
+/**
+ * Figure out the destination (parent) asset that the drop is to occur.
+ * In the case that the drop occurs ON this asset, then the to-be-dropped asset becomes a child
+ *of m_Asset
+ * Otherwise, this m_Asset ends up being a sibling
+ */
+UICDM::CUICDMInstanceHandle CTimeLineDropTarget::GetTargetInstance()
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ if (!theInstance.Valid())
+ return 0;
+
+ CClientDataModelBridge *theBridge =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+ bool theIsActiveComponent = false;
+ bool theIsComponent = (theBridge->GetObjectType(theInstance) == OBJTYPE_COMPONENT);
+ if (theIsComponent)
+ theIsActiveComponent = theBridge->IsActiveComponent(theInstance);
+
+ // If the drop destination is ON, it will be valid if this is not a component or it's in the
+ // component timeline
+ if (m_Destination == EDROPDESTINATION_ON) {
+ if (!theIsComponent || theIsActiveComponent)
+ return theInstance;
+ else
+ return 0;
+ }
+
+ // if target is a component, and we want to insert it above/below, and we are viewing this
+ // component, then it's an invalid operation
+ // thus set the target to 0.
+ if (theIsActiveComponent)
+ return 0;
+
+ return theBridge->GetParentInstance(theInstance);
+}
+
+// LASTTIMELINE RELATED CODE \ No newline at end of file
diff --git a/src/Authoring/Studio/DragAndDrop/TimelineDropTarget.h b/src/Authoring/Studio/DragAndDrop/TimelineDropTarget.h
new file mode 100644
index 00000000..29133afd
--- /dev/null
+++ b/src/Authoring/Studio/DragAndDrop/TimelineDropTarget.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __TIMELINEDROPTARGET_H__
+#define __TIMELINEDROPTARGET_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropTarget.h"
+#include "DropSource.h"
+
+class CControl;
+class CDropSource;
+
+//==============================================================================
+/**
+ * @class
+ * @brief LEONARD.PONCE needs to enter a brief description here.
+ *
+ * LEONARD.PONCE needs to enter a long description here.
+ */
+class CTimeLineDropTarget : public CDropTarget
+{
+
+public:
+ CTimeLineDropTarget()
+ : m_Destination(EDROPDESTINATION_ON)
+ , m_InsertionMarkedRow(nullptr)
+ , m_InsertionMarkedIndent(0)
+ {
+ }
+ bool Accept(CDropSource &inSource) override;
+ bool Drop(CDropSource &inSource) override;
+ long GetObjectType() override;
+
+ bool IsRelative(UICDM::CUICDMInstanceHandle inInstance) override;
+ bool IsSelf(UICDM::CUICDMInstanceHandle inInstance) override;
+ bool IsMaster() override;
+
+ void SetDestination(EDROPDESTINATION inDestination);
+ EDROPDESTINATION GetDestination() const;
+
+ // Return info where the insertion markers is supposed to be drawn at.
+ CControl *GetInsertionMarkerRow() const { return m_InsertionMarkedRow; }
+ void SetInsertionMarkerRow(CControl *inControl) { m_InsertionMarkedRow = inControl; }
+ long GetInsertionMarkerIndent() const { return m_InsertionMarkedIndent; }
+ void SetInsertionMarkerIndent(long inIndent) { m_InsertionMarkedIndent = inIndent; }
+
+protected:
+ UICDM::CUICDMInstanceHandle GetTargetInstance();
+
+protected:
+ EDROPDESTINATION m_Destination;
+ CControl *m_InsertionMarkedRow;
+ long m_InsertionMarkedIndent;
+};
+
+#endif // #ifndef __TIMELINEDROPTARGET_H__
diff --git a/src/Authoring/Studio/English.lproj/Strings/Static.stri b/src/Authoring/Studio/English.lproj/Strings/Static.stri
new file mode 100644
index 00000000..d65e7fa7
--- /dev/null
+++ b/src/Authoring/Studio/English.lproj/Strings/Static.stri
Binary files differ
diff --git a/src/Authoring/Studio/English.lproj/Strings/Static.stro b/src/Authoring/Studio/English.lproj/Strings/Static.stro
new file mode 100644
index 00000000..0b3577f6
--- /dev/null
+++ b/src/Authoring/Studio/English.lproj/Strings/Static.stro
Binary files differ
diff --git a/src/Authoring/Studio/English.lproj/Strings/Strings.h b/src/Authoring/Studio/English.lproj/Strings/Strings.h
new file mode 100644
index 00000000..ef70db6e
--- /dev/null
+++ b/src/Authoring/Studio/English.lproj/Strings/Strings.h
@@ -0,0 +1,301 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//===============================================================================================================================
+// CODEGEN -- FILE CREATED BY STUDIO CODE GENERATION SYSTEM
+//
+// Do not modify the contents of this file. Your changes will be destroyed by
+// code generation.
+//
+// Please see the CodeGen folder for more information or to make changes.
+// StringsReadme.htm
+//===============================================================================================================================
+//{{AFX_INSERT_LOCATION}}
+
+#ifndef STUDIOSTRINGSH
+#define STUDIOSTRINGSH
+
+#define STRING_RESOURCE_COUNT 254
+#define IDS_PREFS_PRESENTATIONWIDTH 1
+#define IDS_PREFS_PRESENTATIONHEIGHT 2
+#define IDS_PREFS_PRESENTATIONASPECTRATIO 3
+#define IDS_PREFS_AUTHORNAME 4
+#define IDS_PREFS_COMPANYNAME 5
+#define IDS_PREFS_NUDGEAMOUNT 6
+#define IDS_PREFS_SNAPRANGE 7
+#define IDS_PREFS_INTERPOLATIONDEFAULT 8
+#define IDS_PREFS_TIMELINEGRIDSNAPPING 9
+#define IDS_PREFS_TIMELINEGRIDRESOLUTION 10
+#define IDS_PREFS_RESTOREDEFAULTS 11
+#define IDS_PREFS_REFERENCECONTROLS 12
+#define IDS_WEBSITELINK 13
+#define IDS_SUPPORTEMAIL_TEXT 14
+#define IDS_SUPPORTEMAIL 15
+#define IDS_PALETTE_TIMELINE 16
+#define IDS_PALETTE_INSPECTOR 17
+#define IDS_PALETTE_SLIDE 18
+#define IDS_PALETTE_ACTION 19
+#define IDS_PALETTE_BASIC_OBJECTS 20
+#define IDS_PALETTE_PROJECT 21
+#define IDS_OBJTYPE_MASTER 22
+#define IDS_SLIDE_EDIT_MASTER 23
+#define IDS_SLIDE_LEAVE_MASTER 24
+#define IDS_SLIDE_DEFAULT_TITLE 25
+#define IDS_HELP_FILE_NAME 26
+#define IDS_PREF_RESTOREDEFAULT_TITLE 27
+#define IDS_PREF_RESTOREDEFAULT_TEXT 28
+#define IDS_PREF_INTERPOLATION_1 29
+#define IDS_PREF_INTERPOLATION_2 30
+#define IDS_PREF_SNAPRANGE_1 31
+#define IDS_PREF_SNAPRANGE_2 32
+#define IDS_PREF_SNAPRANGE_3 33
+#define IDS_ERROR_REFRESHRESOURCETEXT 34
+#define IDS_ERROR_REFRESHRESOURCETITLE 35
+#define IDS_ERROR_IMPORTRESOURCETEXT 36
+#define IDS_ERROR_IMPORTRESOURCETEXT_CHECKFILE 37
+#define IDS_ERROR_IMPORTRESOURCETEXT_REASON 38
+#define IDS_ERROR_IMPORTRESOURCETEXT_COMPLETEWITHWARNING 39
+#define IDS_ERROR_IMPORTRESOURCETEXT_FAILED 40
+#define IDS_ERROR_IMPORTRESOURCETITLE 41
+#define IDS_ERROR_IMPORTRESOURCETITLE_ERROR 42
+#define IDS_ERROR_IMPORTRESOURCETITLE_WARNING 43
+#define IDS_ERROR_IMPORTLUARESOURCETEXT 44
+#define IDS_ERROR_LOADPRESENTATION 45
+#define IDS_ERROR_LOADFILENOTEXIST 46
+#define IDS_ERROR_LOADPRESENTATION_TITLE 47
+#define IDS_ERROR_EXPORTPRESENTATION 48
+#define IDS_ERROR_MISSING_RESOURCES 49
+#define IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT 50
+#define IDS_ERROR_MSGTITLE 51
+#define IDS_ERROR_CLIENTSAVE 52
+#define IDS_ERROR_PROJECT_VARIABLES_TITLE 53
+#define IDS_ERROR_PROJECT_VARIABLES_MSG 54
+#define IDS_ERROR_OBJECT_RENAME_TITLE 55
+#define IDS_ERROR_OBJECT_RENAME_EMPTY_STRING 56
+#define IDS_ERROR_OBJECT_RENAME_DUPLICATED_STRING 57
+#define IDS_ERROR_PATHOLOGICAL_PASTE_TITLE 58
+#define IDS_ERROR_PATHOLOGICAL_PASTE_MESSAGE 59
+#define IDS_ERROR_MSGPASSING 60
+#define IDS_WARNING_IMPORTLUARESOURCETEXT 61
+#define IDS_WARNING_MSGTITLE 62
+#define IDS_TITLE_WARNING 63
+#define IDS_FILE_DESC_UIP 64
+#define IDS_FILE_EXT_UIP 65
+#define IDS_LIBRARYIMPORT_MODEL 66
+#define IDS_LIBRARYIMPORT_IMAGE 67
+#define IDS_LIBRARYIMPORT_BEHAVIOR 68
+#define IDS_LIBRARYIMPORT_MESH 69
+#define IDS_LIBRARYIMPORT_IMPORT 70
+#define IDS_LIBRARYIMPORT_EFFECT 71
+#define IDS_PROJNAME 72
+#define IDS_REPORTDLG_INFO 73
+#define IDS_REPORTDLG_DESCHEADER 74
+#define IDS_REPORTDLG_EMAILHEADER 75
+#define IDS_REPORTDLG_SYSINFOHEADER 76
+#define IDS_COMMAND_COPYACTION 77
+#define IDS_COMMAND_PASTEACTION 78
+#define IDS_COMMAND_CUTACTION 79
+#define IDS_COMMAND_DELETEACTION 80
+#define IDS_HELP_BEHAVIORREFERENCE 81
+#define IDS_SAVE_READONLY_WARNING 82
+#define IDS_COMMENT_SUGGESTION_TOADDR 83
+#define IDS_COMMENT_BUG_TOADDR 84
+#define IDS_COMMENT_TYPE_SUGGESTION 85
+#define IDS_COMMENT_TYPE_BUG 86
+#define IDS_CM_RENAME_OBJECT 87
+#define IDS_CM_DUPLICATE_OBJECT 88
+#define IDS_CM_DELETE_OBJECT 89
+#define IDS_CM_MAKE_COMPONENT 90
+#define IDS_CM_COPY_OBJECT_PATH 91
+#define IDS_CM_EXTERNALIZE_OBJECT_BUFFER 92
+#define IDS_CM_INTERNALIZE_OBJECT_BUFFER 93
+#define IDS_CM_INSPECT_COMPONENT 94
+#define IDS_TEXTEDIT_CONTEXT_MENU_CUT 95
+#define IDS_TEXTEDIT_CONTEXT_MENU_COPY 96
+#define IDS_TEXTEDIT_CONTEXT_MENU_PASTE 97
+#define IDS_UIC_STUDIO_VERSION 98
+#define IDS_CRASH_REPORT_TOADDR 99
+#define IDS_CRASH_REPORT_FROMADDR 100
+#define IDS_CRASH_REPORT_SERVERADDR 101
+#define IDS_UICOMPOSER_PALETTE_SETTINGS_REGISTRY_KEY 102
+#define IDS_COPYPASTE_FORMAT_NAME 103
+#define IDS_STUDIOFONT_SIZE 104
+#define IDS_STUDIOPREFSTITLE 105
+#define IDS_NOOBJECTSELECTED 106
+#define IDS_CONTEXTKEY_SETINTERPOLATION 107
+#define IDS_CONTEXTKEY_DELETESELECTED 108
+#define IDS_CONTEXTKEY_CUTSELECTED 109
+#define IDS_CONTEXTKEY_COPYSELECTED 110
+#define IDS_CONTEXTKEY_PASTE 111
+#define IDS_CONTEXTKEY_INSERTKEY 112
+#define IDS_CONTEXTKEY_SETKEYFRAMETIME 113
+#define IDS_CONTEXTKEY_DELETECHANNEL 114
+#define IDS_CONTEXTKEY_BARCOLOR 115
+#define IDS_CONTEXTKEY_BARTEXT 116
+#define IDS_CONTEXTKEY_SHOWTIMEBARHANDLES 117
+#define IDS_CONTEXTKEY_HIDETIMEBARHANDLES 118
+#define IDS_CONTEXTKEY_SETTIMEBARTIME 119
+#define IDS_CONTEXTKEY_MAKE_ANIMATION_DYNAMIC 120
+#define IDS_CONTEXTKEY_MAKE_ANIMATION_STATIC 121
+#define IDS_CONTEXTKEY_MAKE_ANIMATIONS_DYNAMIC 122
+#define IDS_CONTEXTKEY_MAKE_ANIMATIONS_STATIC 123
+#define IDS_CONTEXT_SLIDE_NEW 124
+#define IDS_CONTEXT_SLIDE_DELETE 125
+#define IDS_CONTEXT_SLIDE_DUPLICATE 126
+#define IDS_CONTEXT_LINK_STATEWISE 127
+#define IDS_CONTEXT_UNLINK_STATEWISE 128
+#define IDS_HK_CMD 129
+#define IDS_HK_ALPHALOCK 130
+#define IDS_CONTROLS_FLOAT_MINUS 131
+#define IDS_CONTROLS_FLOAT_PERIOD 132
+#define IDS_PROJECT_BEHAVIORLIB_PATH 133
+#define IDS_PROJECT_EFFECTLIB_PATH 134
+#define IDS_PROJECT_FONTLIB_PATH 135
+#define IDS_PROJECT_IMAGELIB_PATH 136
+#define IDS_PROJECT_MATERIALLIB_PATH 137
+#define IDS_PROJECT_MODELLIB_PATH 138
+#define IDS_PROJECT_BUTTON_BEHAVIOR 139
+#define IDS_PROJECT_BUTTON_EFFECT 140
+#define IDS_PROJECT_BUTTON_FONT 141
+#define IDS_PROJECT_BUTTON_IMAGE 142
+#define IDS_PROJECT_BUTTON_MATERIAL 143
+#define IDS_PROJECT_BUTTON_MODEL 144
+#define IDS_PROJECT_CM_SHOW_IN_EXPLORER 145
+#define IDS_PROJECT_CM_COPY_PATH 146
+#define IDS_PROJECT_CM_COPY_FULL_PATH 147
+#define IDS_PROJECT_CM_LOCATE_FOLDER 148
+#define IDS_PROJECT_CM_LOCATE_FILE 149
+#define IDS_PROJECT_FILE_NOT_IN_DOCUMENT_SUBDIR 150
+#define IDS_UNTITLED_DOCUMENT_TITLE 151
+#define IDS_CREATE_NEW_DOCUMENT_TITLE 152
+#define IDS_MENU_WIN_UNDO_FORMAT 153
+#define IDS_MENU_WIN_REDO_FORMAT 154
+#define IDS_MENU_WIN_COPY_FORMAT 155
+#define IDS_MENU_WIN_PASTE_FORMAT 156
+#define IDS_MENU_WIN_CUT_FORMAT 157
+#define IDS_MENU_COPYPASTE_TYPE_ACTION 158
+#define IDS_MENU_COPYPASTE_TYPE_KEYFRAMES 159
+#define IDS_MENU_COPYPASTE_TYPE_OBJECT 160
+#define IDS_PROMPT_FOR_SAVE 161
+#define IDS_PROMPT_FOR_REVERT 162
+#define IDS_WAIT_LOADING 163
+#define IDS_HELP_VISIT_QT 164
+#define IDS_FLTR_TOOLTIP_BEHAVIOR1 165
+#define IDS_FLTR_TOOLTIP_BEHAVIOR2 166
+#define IDS_FLTR_TOOLTIP_PROPERTIES1 167
+#define IDS_FLTR_TOOLTIP_PROPERTIES2 168
+#define IDS_FLTR_TOOLTIP_MATERIALS1 169
+#define IDS_FLTR_TOOLTIP_MATERIALS2 170
+#define IDS_FLTR_TOOLTIP_SHY1 171
+#define IDS_FLTR_TOOLTIP_SHY2 172
+#define IDS_FLTR_TOOLTIP_VISIBLE1 173
+#define IDS_FLTR_TOOLTIP_VISIBLE2 174
+#define IDS_FLTR_TOOLTIP_LOCK1 175
+#define IDS_FLTR_TOOLTIP_LOCK2 176
+#define IDS_TOOLTIP_ANIMATE_TOGGLE 177
+#define IDS_TIME_EDIT_DLG_GO_TO_TIME 178
+#define IDS_TIME_EDIT_DLG_SET_KEYFRAME_TIME 179
+#define IDS_TIME_EDIT_DLG_SET_TIMEBAR_TIME 180
+#define IDS_TIME_EDIT_DLG_START_TIME 181
+#define IDS_TIME_EDIT_DLG_END_TIME 182
+#define IDS_TIME_EDIT_DLG_MIN_SEC_MSEC 183
+#define IDS_REFRESH_IMPORT 184
+#define IDS_COLORCHOOSER_AUTO 185
+#define IDS_COLORCHOOSER_MORE 186
+#define IDS_SPLASH_COPYRIGHT1 187
+#define IDS_SPLASH_COPYRIGHT2 188
+#define IDS_ABOUT_COPYRIGHT 189
+#define IDS_ABOUT_PAINTLIB_CREDIT 190
+#define IDS_ABOUT_FBX_CREDIT 191
+#define IDS_DEFAULT_PALETTE_LAYOUT 192
+#define IDS_BASIC_OBJ_PALETTE_LAYER 193
+#define IDS_BASIC_OBJ_PALETTE_CAMERA 194
+#define IDS_BASIC_OBJ_PALETTE_LIGHT 195
+#define IDS_BASIC_OBJ_PALETTE_GROUP 196
+#define IDS_BASIC_OBJ_PALETTE_CUBE 197
+#define IDS_BASIC_OBJ_PALETTE_CYLINDER 198
+#define IDS_BASIC_OBJ_PALETTE_CONE 199
+#define IDS_BASIC_OBJ_PALETTE_RECTANGLE 200
+#define IDS_BASIC_OBJ_PALETTE_SPHERE 201
+#define IDS_BASIC_OBJ_PALETTE_TEXT 202
+#define IDS_BASIC_OBJ_PALETTE_COMPONENT 203
+#define IDS_BASIC_OBJ_PALETTE_ALIAS 204
+#define IDS_CREATE_NEW_PALETTE 205
+#define IDS_MOVE_PALETTE 206
+#define IDS_GROUP_EXPAND_TOGGLE_TOOLTIP 207
+#define IDS_GROUP_MOVE_UP_TOOLTIP 208
+#define IDS_GROUP_MOVE_DOWN_TOOLTIP 209
+#define IDS_ACTION_DELETE_TOOLTIP 210
+#define IDS_HANDLER_CONTROL_NAME 211
+#define IDS_EVENT_CONTROL_NAME 212
+#define IDS_EVENT_TARGET_OBJ 213
+#define IDS_EVENT_TRIGGER_OBJ 214
+#define IDS_ACTION_LISTEN_FOR_STRING 215
+#define IDS_ACTION_LISTEN_FOR_TELL_STRING 216
+#define IDS_ACTION_LISTEN_TO_FOR_STRING 217
+#define IDS_ACTION_LISTEN_TO_FOR_TELL_STRING 218
+#define IDS_ACTION_NEW 219
+#define IDS_DELETE_ACTION 220
+#define IDS_PROPERTIES_BASIC 221
+#define IDS_PROPERTIES_SHARED 222
+#define IDS_OBJ_REF_PATH 223
+#define IDS_OBJ_REF_PATH_TYPE 224
+#define IDS_OBJ_REF_PATH_ABSOLUTE 225
+#define IDS_OBJ_REF_PATH_RELATIVE 226
+#define IDS_PROP_UNKNOWN_SOURCE 227
+#define IDS_PROP_UNKNOWN_TARGET 228
+#define IDS_PROP_UNKNOWN_PROP 229
+#define IDS_PROP_UNKNOWN_HANDLER 230
+#define IDS_ACTION_ENABLE_STATE 231
+#define IDS_ASSET_NAME_UNKNOWN 232
+#define IDS_DELETE_OBJ_CONFIRM_TITLE 233
+#define IDS_DELETE_OBJ_CONFIRM_MSG 234
+#define IDS_SCENE_CAMERA_VIEW 235
+#define IDS_PROJECT_VARIABLES_FORMAT 236
+#define IDS_CONFIG_EXPORT_PREVIEW 237
+#define IDS_CONFIG_EXPORT_DEPLOY 238
+#define IDS_CONFIG_PREVIEW_TITLE 239
+#define IDS_CONFIG_PREVIEW_ERROR_TITLE 240
+#define IDS_CONFIG_PREVIEW_ERROR_MSG 241
+#define IDS_CONFIG_PREVIEW_ERROR_TEXT 242
+#define IDS_CONFIG_PREVIEW_REDIRECT_ERROR 243
+#define IDS_CONFIG_PREVIEW_INPUT 244
+#define IDS_CONFIG_PREVIEW_OUTPUT 245
+#define IDS_RENAME_OBJ_CONFIRM_TITLE 246
+#define IDS_RENAME_OBJ_CONFIRM_MSG 247
+#define IDS_BUILDCONFIGS_ERROR_TITLE 248
+#define IDS_MISSINGSLIDE 249
+#define IDS_SAVE_UNKNOWN_ERROR 250
+#define IDS_GL_VERSION_ERROR 251
+#define IDS_GL_VERSION_WARNING 252
+#define IDS_PRESENTATION_MODIFIED_EXTERNALLY 253
+#ifdef KDAB_TEMPORARILY_REMOVED
+#define placeholder 254
+#endif
+
+#endif //STUDIOSTRINGSH \ No newline at end of file
diff --git a/src/Authoring/Studio/English.lproj/Strings/StringsReadme.htm b/src/Authoring/Studio/English.lproj/Strings/StringsReadme.htm
new file mode 100644
index 00000000..78dec4f1
--- /dev/null
+++ b/src/Authoring/Studio/English.lproj/Strings/StringsReadme.htm
@@ -0,0 +1,124 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>Studio String Files</title>
+</head>
+
+<body>
+
+<h2>Studio String Files</h2>
+<p>The directory Studio\English.lproj\Strings contain files that help manage the
+following ideas:</p>
+<ul>
+ <li>the text strings displayed in Studio's user interface and how they are
+ mapped onto integer-based identifiers in the C++ source code</li>
+ <li>the process of internationalization (or localization) of the GUI and the
+ strings that are displayed in non-English versions of Studio</li>
+</ul>
+<p>This document provides an overview of the various files and how they are
+used.</p>
+<address align="right">
+ Paul Tweedlie, January 27 2005</address>
+<h3>Compile.py</h3>
+<p>The Python script 'compile.py' takes the 2 input files (stri) and generates
+the 2 output files (stro) and a C++ header file 'Strings.h'. The 2 stri input
+files are ASCII-based and are typically edited by code developers while adding
+new GUI and functionality. The 2 stro files generated by the script are 16-bit
+Unicode-based files that are designed to be language-independent, see
+<a href="http://www.unicode.org/">http://www.unicode.org/</a>. The 2 stro files
+form part of the Studio release and are loaded by Studio.exe on start-up. They
+are installed on a user's machine in the directory:</p>
+<p>&nbsp;&nbsp;&nbsp; C:\Program Files\Qt 3D Studio\res\Strings</p>
+<p>The stro files may be edited at the end of a development cycle to localize
+Studio's GUI from English to another language that may use a different script,
+e.g. Japanese.</p>
+<p>To run the compile.py script, you need a Python interpreter installed on your
+machine, get one from <a href="http://www.python.org/">http://www.python.org/</a>.
+The typical steps for a code developer are:</p>
+<ol>
+ <li>Check out the input files <i>and</i> the output files before running the
+ script. It's easiest to just check out the entire Strings directory using
+ Perforce.</li>
+ <li>Make your text changes to the stri file(s)</li>
+ <li>Run the compile.py script</li>
+ <li>Build Studio and verify your changes</li>
+ <li>Go to Perforce and revert unchanged files in the Strings directory</li>
+ <li>Check in the Strings directory back into Perforce</li>
+</ol>
+<h3>Strings.h</h3>
+<p>The C++ header file 'Strings.h' is auto-generated and should never be hand
+edited. The file contains a bunch of #define statements that set up constant
+identifiers where each identifier is assigned a unique integer. For example,</p>
+<p>&nbsp;&nbsp;&nbsp; #define IDS_CONTEXT_SLIDE_NEW 570</p>
+<h3>Stri: ASCII Input Files</h3>
+<div align="center">
+ <center>
+ <table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="90%" id="AutoNumber1">
+ <tr>
+ <td width="15%">Static.stri</td>
+ <td width="85%">An ASCII text file that specifies the strings that are
+ displayed in Studio's user interface such as buttons and tooltips. The
+ file is organized as a mapping of pairs <b>from</b> integer-based
+ identifiers that are referenced in the C++ source code<b> to</b> text
+ strings. For example, the mapping for the 'New Slide' button appears as:<p>&nbsp;&nbsp;&nbsp;
+ &lt;string name=&quot;IDS_CONTEXT_SLIDE_NEW&quot; value=&quot;New Slide&quot; /&gt;</p>
+ <p>where the integer identifier 'IDS_CONTEXT_SLIDE_NEW' is used in the
+ source file SlideContextMenu.cpp and 'New Slide' is the text that appears
+ in the list of options when the user right-clicks in the Slide palette.
+ </p>
+ <p>Developers should edit this file when writing new GUI code, e.g. adding
+ new buttons.</td>
+ </tr>
+ </table>
+ </center>
+</div>
+<h3>Stro: Unicode Output Files</h3>
+<div align="center">
+ <center>
+ <table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="90%" id="AutoNumber1">
+ <tr>
+ <td width="15%">Static.stro</td>
+ <td width="85%">A Unicode file that specifies the strings that are
+ displayed in Studio's user interface such as buttons and tooltips. The
+ file is organized into a list of triples: an identifier, a numeric value,
+ and a Unicode string. For example, the triple representing the 'New Slide'
+ button appears as:<p>&nbsp;&nbsp;&nbsp; &lt;string name=&quot;IDS_CONTEXT_SLIDE_NEW&quot;
+ ID=&quot;570&quot; value=&quot;New Slide&quot;/&gt;. </p>
+ <p>Language translators should edit the 'value' strings in this file. For
+ example, the above triple may be translated as follows:</p>
+ <p>&nbsp;&nbsp; &lt;string name=&quot;IDS_CONTEXT_SLIDE_NEW&quot; ID=&quot;570&quot;
+ value=&quot;Nouveau Slide&quot;/&gt;. </td>
+ </tr>
+ </table>
+ </center>
+</div>
+<h3>Localization</h3>
+<p>Studio's user interface uses the Arial font by default and a point side of
+13pt. If you want to change the GUI's font and/or the point size, you should
+search in the Static.stro file for the following identifiers:</p>
+<p>&nbsp;&nbsp; &lt;string name=&quot;IDS_STUDIOFONT_FACE&quot; ID=&quot;548&quot; value=&quot;Arial&quot;/&gt;</p>
+<p>&nbsp;&nbsp; &lt;string name=&quot;IDS_STUDIOFONT_SIZE&quot; ID=&quot;547&quot; value=&quot;13&quot;</p>
+<p>If you want to use a font that supports non-English characters, for instance
+Japanese symbols, you should first change the 'Arial' font to something like
+'Arial Unicode MS'. For example,</p>
+<p>&nbsp;&nbsp; &lt;string name=&quot;IDS_STUDIOFONT_FACE&quot; ID=&quot;548&quot; value=&quot;Arial Unicode
+MS&quot;/&gt;</p>
+<p>Next you substitute all the English strings in the stro files for their
+Japanese-translated counterparts. You will need to use an editor such as Notepad
+or Wordpad that supports the Unicode format. For example, perhaps the 'New
+Slide' option is translated so:</p>
+<p>&nbsp;&nbsp; &lt;string name=&quot;IDS_CONTEXT_SLIDE_NEW&quot; ID=&quot;570&quot; value=&quot;&#12461;&#12515;&#12483;&#12471;&#12531;&quot;/&gt;.
+</p>
+<p>Note from Gim Guan Chua: To see the Japanese symbols in Studio, you may have
+to set your machine to Japanese settings (in Control Panel-&gt;Regional and
+Language Settings-&gt;Advance). Studio is considered a &quot;non-Unicode&quot; program in
+contrast to Notepad and Wordpad which are Unicode-aware in XP.</p>
+<p>&nbsp;</p>
+
+</body>
+
+</html>
diff --git a/src/Authoring/Studio/English.lproj/Strings/compile.py b/src/Authoring/Studio/English.lproj/Strings/compile.py
new file mode 100644
index 00000000..255d1f45
--- /dev/null
+++ b/src/Authoring/Studio/English.lproj/Strings/compile.py
@@ -0,0 +1,245 @@
+'''
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+'''
+
+'''Compile the string input (stri) into string output (stro) + Strings.h'''
+import os, os.path, re
+import xml.sax.handler, xml.sax, codecs
+
+
+class CGenericXMLFactory:
+ '''Generic factory for xml generation'''
+ def __init__( self ):
+ self.m_Elements = {}
+
+ def AddTagElement( self, inName, inFunction ):
+ self.m_Elements[inName] = inFunction
+
+ def CreateObject( self, inName, inAttrs, inParent ):
+ theElement = self.m_Elements[inName](inName, inAttrs, inParent )
+ return theElement
+
+
+class CBaseXMLHandler( xml.sax.handler.ContentHandler ):
+ """Base xml parsing class. Can be used to form a dom system"""
+ def __init__( self, inFactory ):
+ self.m_Objects = [] #stack of objects used for parsing (targets require the latest project)
+ self.m_Factory = inFactory
+ self.m_CurrentObject = None
+ self.m_CharacterHandler = None
+ self.m_TopObject = None
+
+ def startElement( self, name, attrs ):
+ theParent = None
+ if( not len(self.m_Objects) == 0 ):
+ theParent = self.m_Objects[-1]
+ self.m_CurrentObject = self.m_Factory.CreateObject( name, attrs, theParent )
+ try:
+ self.m_CurrentObject.startElement( self )
+ except AttributeError:
+ pass #Don't care if the object does not support the method call
+ self.OnObjectCreated( self.m_CurrentObject )
+
+ def endElement( self, name ):
+ theElement = self.m_Objects.pop()
+ try:
+ theElement.endElement( self )
+ except AttributeError:
+ pass #Don't care if the object does not support the method call
+
+ if( len( self.m_Objects ) != 0 ):
+ self.m_CurrentObject = self.m_Objects[-1]
+
+ def characters( self, content ):
+ if( self.m_CharacterHandler ):
+ self.m_CharacterHandler( self.m_CurrentObject, content )
+
+ def SetCharacterHandler( self, inHandler ):
+ self.m_CharacterHandler = inHandler
+
+ def OnObjectCreated( self, theObject ):
+ '''Callback every time a factory returns an object'''
+ self.m_Objects.append( theObject )
+ if( len( self.m_Objects ) == 1 ):
+ self.m_TopObject = self.m_CurrentObject
+
+ def SetFactory( self, inFactory ):
+ self.m_Factory = inFactory
+
+ def Parse( self, inFilename ):
+ '''Parse the file, grabbing the extension'''
+ theDirectory = os.path.dirname( inFilename )
+ theFile = os.path.basename( inFilename )
+ self.m_BasePath = theDirectory
+ theReturn = None
+ theExcept = None
+ self.m_TopObject = None
+ self.m_CurrentObject = None
+ self.m_Objects = []
+ theParse = xml.sax.parse( inFilename, self )
+ return self.m_TopObject
+
+
+class CStringObject:
+ '''Basic string object'''
+ def __init__( self ):
+ self.m_Name = ''
+ self.m_Value = ''
+
+ def SetName( self, inName ):
+ self.m_Name = inName
+
+ def GetName( self ):
+ return self.m_Name
+
+ def SetValue( self, inValue ):
+ self.m_Value = inValue
+
+ def GetValue( self ):
+ return self.m_Value
+
+def XMLStringObjectInit( inName, inAttrs, inParent ):
+ '''Create a string object from xml'''
+ theObject = CStringObject( )
+ try:
+ theObject.SetName( inAttrs['name'] )
+ theObject.SetValue( inAttrs['value'] )
+ except KeyError:
+ print 'Failed to parse string object'
+ inParent.AddObject( theObject )
+ return theObject
+
+
+class CStringObjectList:
+ '''Create a list of string objects'''
+ def __init__( self ):
+ self.m_StringObjects = []
+
+ def AddObject( self, inStringObject ):
+ self.m_StringObjects.append( inStringObject )
+
+ def GetObjects( self ):
+ return self.m_StringObjects
+
+def XMLStringObjectListInit( inName, inAttrs, inParent ):
+ '''Create a list from xml'''
+ theStringList = CStringObjectList()
+ return theStringList
+
+def ExportObjects( inFactory ):
+ inFactory.AddTagElement( 'stringresourceinput', XMLStringObjectListInit )
+ inFactory.AddTagElement( 'string', XMLStringObjectInit )
+
+
+
+
+###Main Code Below###########################################
+theLists = []
+#parse into a named group the matches anything up to the period and an ending of stri
+theSourceRegex = re.compile( r'(?P<stem>.*)\.stri$' ) # $ means end of line/input
+theTotalFiles = os.listdir( '.' ) #List files in the current working directory
+
+
+#Create xml parsing context
+theFactory = CGenericXMLFactory()
+theHandler = CBaseXMLHandler( theFactory )
+ExportObjects( theFactory ) #Export the dom objects we would like to use
+
+theStringCount = 0
+
+for theFile in theTotalFiles:
+ theMatch = theSourceRegex.match( theFile )
+ if( theMatch ):
+ theList = None
+ try:
+ print 'parsing %s' % ( theFile )
+ theList = theHandler.Parse( theFile )
+ theLists.append( ( theMatch.group( 'stem' ), theList ) ) #append a touple of the source name
+ theStringCount += len( theList.GetObjects() )
+ except Exception, e:
+ print 'Failed to parse %s: %s' % ( theFile, e )
+ #salvage anything possible
+ theList = theHandler.m_TopObject
+ if( theList ):
+ theLists.append( ( theMatch.group( 'stem' ), theList ) ) #append a touple of the source name
+ theStringCount += len( theList.GetObjects() )
+
+theIndex = 1
+theHeaderName = 'Strings.h'
+theHeaderFile = open( 'Strings.h', 'w' )
+
+theHeaderLine = '''
+//===============================================================================================================================
+// CODEGEN -- FILE CREATED BY STUDIO CODE GENERATION SYSTEM
+//
+// Do not modify the contents of this file. Your changes will be destroyed by
+// code generation.
+//
+// Please see the CodeGen folder for more information or to make changes.
+// C:\NVIDIA\p4sw\sw\contenttools\UIComposer\ViewComposer\Main\Studio\English.lproj\Strings\StringsReadme.htm\StringsReadme.htm
+//===============================================================================================================================
+//{{AFX_INSERT_LOCATION}}
+
+#ifndef STUDIOSTRINGSH
+#define STUDIOSTRINGSH
+
+#define STRING_RESOURCE_COUNT %s
+''' % ( theStringCount )
+
+theResultLine = '''
+<!-- ============================================================================================================================== -->
+<!-- CODEGEN - FILE CREATED BY STUDIO CODE GENERATION SYSTEM -->
+<!-- -->
+<!-- Do not modify the contents of this file. Your changes will be destroyed -->
+<!-- by code generation. -->
+<!-- -->
+<!-- Please see the CodeGen folder for more information or to make changes. -->
+<!-- C:\NVIDIA\p4sw\sw\contenttools\UIComposer\ViewComposer\Main\Studio\English.lproj\Strings\StringsReadme.htm\StringsReadme.htm -->
+<!-- ============================================================================================================================== -->
+
+<stringresourceinput>
+'''
+
+theHeaderFile.write( theHeaderLine )
+for theName, theList in theLists:
+ theFileName = theName + '.stro'
+ print 'write file %s' % ( theFileName )
+ theResultFile = codecs.open( theFileName, 'w', 'utf-16' )
+ theResultFile.write( theResultLine )
+ for theObject in theList.GetObjects():
+ theName = theObject.GetName()
+ theValue = theObject.GetValue()
+ theResultFile.write( '\t<string name="%s" ID="%s" value="%s"/>\n' % ( theName, theIndex, theValue ) )
+ theHeaderFile.write( '#define %s %s\n' % ( theName, theIndex ) )
+ theIndex+= 1
+ theResultFile.write( '</stringresourceinput>' )
+ theResultFile.close()
+
+theHeaderFile.write( '\n#endif //STUDIOSTRINGSH' )
+theHeaderFile.close()
diff --git a/src/Authoring/Studio/English.lproj/Strings/compile32.py b/src/Authoring/Studio/English.lproj/Strings/compile32.py
new file mode 100644
index 00000000..a1be6cab
--- /dev/null
+++ b/src/Authoring/Studio/English.lproj/Strings/compile32.py
@@ -0,0 +1,272 @@
+'''
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+'''
+'''Compile the string input (stri) into string output (stro) + Strings.h'''
+import os, os.path, re
+import xml.sax.handler, xml.sax, codecs
+
+
+class CGenericXMLFactory:
+ '''Generic factory for xml generation'''
+ def __init__( self ):
+ self.m_Elements = {}
+
+ def AddTagElement( self, inName, inFunction ):
+ self.m_Elements[inName] = inFunction
+
+ def CreateObject( self, inName, inAttrs, inParent ):
+ theElement = self.m_Elements[inName](inName, inAttrs, inParent )
+ return theElement
+
+
+class CBaseXMLHandler( xml.sax.handler.ContentHandler ):
+ """Base xml parsing class. Can be used to form a dom system"""
+ def __init__( self, inFactory ):
+ self.m_Objects = [] #stack of objects used for parsing (targets require the latest project)
+ self.m_Factory = inFactory
+ self.m_CurrentObject = None
+ self.m_CharacterHandler = None
+ self.m_TopObject = None
+
+ def startElement( self, name, attrs ):
+ theParent = None
+ if( not len(self.m_Objects) == 0 ):
+ theParent = self.m_Objects[-1]
+ self.m_CurrentObject = self.m_Factory.CreateObject( name, attrs, theParent )
+ try:
+ self.m_CurrentObject.startElement( self )
+ except AttributeError:
+ pass #Don't care if the object does not support the method call
+ self.OnObjectCreated( self.m_CurrentObject )
+
+ def endElement( self, name ):
+ theElement = self.m_Objects.pop()
+ try:
+ theElement.endElement( self )
+ except AttributeError:
+ pass #Don't care if the object does not support the method call
+
+ if( len( self.m_Objects ) != 0 ):
+ self.m_CurrentObject = self.m_Objects[-1]
+
+ def characters( self, content ):
+ if( self.m_CharacterHandler ):
+ self.m_CharacterHandler( self.m_CurrentObject, content )
+
+ def SetCharacterHandler( self, inHandler ):
+ self.m_CharacterHandler = inHandler
+
+ def OnObjectCreated( self, theObject ):
+ '''Callback every time a factory returns an object'''
+ self.m_Objects.append( theObject )
+ if( len( self.m_Objects ) == 1 ):
+ self.m_TopObject = self.m_CurrentObject
+
+ def SetFactory( self, inFactory ):
+ self.m_Factory = inFactory
+
+ def Parse( self, inFilename ):
+ '''Parse the file, grabbing the extension'''
+ theDirectory = os.path.dirname( inFilename )
+ theFile = os.path.basename( inFilename )
+ self.m_BasePath = theDirectory
+ theReturn = None
+ theExcept = None
+ self.m_TopObject = None
+ self.m_CurrentObject = None
+ self.m_Objects = []
+ theParse = xml.sax.parse( inFilename, self )
+ return self.m_TopObject
+
+
+class CStringObject:
+ '''Basic string object'''
+ def __init__( self ):
+ self.m_Name = ''
+ self.m_Value = ''
+
+ def SetName( self, inName ):
+ self.m_Name = inName
+
+ def GetName( self ):
+ return self.m_Name
+
+ def SetValue( self, inValue ):
+ self.m_Value = inValue
+
+ def GetValue( self ):
+ return self.m_Value
+
+def XMLStringObjectInit( inName, inAttrs, inParent ):
+ '''Create a string object from xml'''
+ theObject = CStringObject( )
+ try:
+ theObject.SetName( inAttrs['name'] )
+ theObject.SetValue( inAttrs['value'] )
+ except KeyError:
+ print("Failed to parse string object")
+
+ inParent.AddObject( theObject )
+ return theObject
+
+
+class CStringObjectList:
+ '''Create a list of string objects'''
+ def __init__( self ):
+ self.m_StringObjects = []
+
+ def AddObject( self, inStringObject ):
+ self.m_StringObjects.append( inStringObject )
+
+ def GetObjects( self ):
+ return self.m_StringObjects
+
+def XMLStringObjectListInit( inName, inAttrs, inParent ):
+ '''Create a list from xml'''
+ theStringList = CStringObjectList()
+ return theStringList
+
+def ExportObjects( inFactory ):
+ inFactory.AddTagElement( 'stringresourceinput', XMLStringObjectListInit )
+ inFactory.AddTagElement( 'string', XMLStringObjectInit )
+
+
+
+
+###Main Code Below###########################################
+theLists = []
+#parse into a named group the matches anything up to the period and an ending of stri
+theSourceRegex = re.compile( r'(?P<stem>.*)\.stri$' ) # $ means end of line/input
+theTotalFiles = os.listdir( '.' ) #List files in the current working directory
+
+
+#Create xml parsing context
+theFactory = CGenericXMLFactory()
+theHandler = CBaseXMLHandler( theFactory )
+ExportObjects( theFactory ) #Export the dom objects we would like to use
+
+theStringCount = 0
+
+for theFile in theTotalFiles:
+ theMatch = theSourceRegex.match( theFile )
+ if( theMatch ):
+ theList = None
+ try:
+ print( 'parsing %s' % ( theFile ) )
+ theList = theHandler.Parse( theFile )
+ theLists.append( ( theMatch.group( 'stem' ), theList ) ) #append a touple of the source name
+ theStringCount += len( theList.GetObjects() )
+ except Exception as e:
+ print( 'Failed to parse %s: %s' % ( theFile, e ) )
+ #salvage anything possible
+ theList = theHandler.m_TopObject
+ if( theList ):
+ theLists.append( ( theMatch.group( 'stem' ), theList ) ) #append a touple of the source name
+ theStringCount += len( theList.GetObjects() )
+
+theIndex = 1
+theHeaderName = 'Strings.h'
+theHeaderFile = open( 'Strings.h', 'w' )
+
+theHeaderLine = r'''
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//===============================================================================================================================
+// CODEGEN -- FILE CREATED BY STUDIO CODE GENERATION SYSTEM
+//
+// Do not modify the contents of this file. Your changes will be destroyed by
+// code generation.
+//
+// Please see the CodeGen folder for more information or to make changes.
+// StringsReadme.htm
+//===============================================================================================================================
+//{{AFX_INSERT_LOCATION}}
+
+#ifndef STUDIOSTRINGSH
+#define STUDIOSTRINGSH
+
+#define STRING_RESOURCE_COUNT %s
+''' % ( theStringCount )
+
+theResultLine = r'''
+<!-- ============================================================================================================================== -->
+<!-- CODEGEN - FILE CREATED BY STUDIO CODE GENERATION SYSTEM -->
+<!-- -->
+<!-- Do not modify the contents of this file. Your changes will be destroyed -->
+<!-- by code generation. -->
+<!-- -->
+<!-- Please see the CodeGen folder for more information or to make changes. -->
+<!-- StringsReadme.htm -->
+<!-- ============================================================================================================================== -->
+
+<stringresourceinput>
+'''
+
+theHeaderFile.write( theHeaderLine )
+for theName, theList in theLists:
+ theFileName = theName + '.stro'
+ print('write file %s' % ( theFileName ))
+ theResultFile = codecs.open( theFileName, 'w', 'utf-16' )
+ theResultFile.write( theResultLine )
+ for theObject in theList.GetObjects():
+ theName = theObject.GetName()
+ theValue = theObject.GetValue()
+ theResultFile.write( '\t<string name="%s" ID="%s" value="%s"/>\n' % ( theName, theIndex, theValue ) )
+ theHeaderFile.write( '#define %s %s\n' % ( theName, theIndex ) )
+ theIndex+= 1
+ theResultFile.write( '</stringresourceinput>' )
+ theResultFile.close()
+
+theHeaderFile.write( '\n#endif //STUDIOSTRINGSH' )
+theHeaderFile.close()
diff --git a/src/Authoring/Studio/MainFrm.cpp b/src/Authoring/Studio/MainFrm.cpp
new file mode 100644
index 00000000..9db47a65
--- /dev/null
+++ b/src/Authoring/Studio/MainFrm.cpp
@@ -0,0 +1,2049 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "MainFrm.h"
+#include "ui_MainFrm.h"
+
+#include "StudioConst.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Bindings/TimelineTranslationManager.h"
+#include "Bindings/UICDMTimelineItemBinding.h"
+#include "Bindings/ITimelineTimebar.h"
+#include "SceneView.h"
+#include "Strings.h"
+#include "StringLoader.h"
+#include "StudioApp.h"
+#include "TimelineControl.h"
+#include "UICOptions.h"
+#include "UICColor.h"
+
+#include "Doc.h"
+#include "IKeyframesManager.h"
+#include "Dispatch.h"
+#include "Dialogs.h"
+#include "StudioPreferencesPropSheet.h"
+#include "StudioProjectSettings.h"
+#include "StudioPreferences.h"
+#include "Views.h"
+#include "HotKeys.h"
+#include "RecentItems.h"
+#include "PaletteManager.h"
+#include "Core.h"
+#include "ITickTock.h"
+#include "IStudioRenderer.h"
+#include "SubPresentationsDlg.h"
+#include "StudioTutorialWidget.h"
+#include "remoteproject.h"
+
+#include "InspectorControlView.h"
+
+#include <QtGui/qevent.h>
+#include <QtGui/qdesktopservices.h>
+#include <QtWidgets/qdockwidget.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+
+// Constants
+const long PLAYBACK_TIMER_TIMEOUT = 10; // 10 milliseconds
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ON_MESSAGE(WM_STUDIO_MESSAGE_ROUTER, OnMsgRouterMsg)
+#endif
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CMainFrame::CMainFrame()
+ : m_ui(new Ui::MainFrame)
+{
+ m_ui->setupUi(this);
+
+ OnCreate();
+
+ g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
+ g_StudioApp.GetCore()->GetDispatch()->AddFileOpenListener(this);
+ g_StudioApp.GetCore()->GetDispatch()->AddClientPlayChangeListener(this);
+ g_StudioApp.SetupTimer(WM_STUDIO_TIMER, this);
+
+ m_remoteProject = new RemoteProject(this);
+
+ // File Menu
+ connect(m_ui->action_Open, &QAction::triggered, this, &CMainFrame::OnFileOpen);
+ connect(m_ui->action_Save, &QAction::triggered, this, &CMainFrame::OnFileSave);
+ connect(m_ui->action_New, &QAction::triggered, this, &CMainFrame::OnFileNew);
+ connect(m_ui->actionSave_As, &QAction::triggered, this, &CMainFrame::OnFileSaveAs);
+ connect(m_ui->actionSave_a_Copy, &QAction::triggered, this, &CMainFrame::OnFileSaveCopy);
+ connect(m_ui->action_Revert, &QAction::triggered, this, &CMainFrame::OnFileRevert);
+ connect(m_ui->action_Connect_to_Device, &QAction::triggered, this,
+ &CMainFrame::OnFileConnectToDevice);
+ connect(m_remoteProject, &RemoteProject::connectionChanged,
+ m_ui->action_Connect_to_Device, &QAction::setChecked);
+ connect(m_ui->action_Exit, &QAction::triggered, this, &CMainFrame::close);
+
+ m_RecentItems = new CRecentItems(m_ui->menuRecent_Projects, 0);
+ connect(m_RecentItems, &CRecentItems::openRecent, this, &CMainFrame::OnFileOpenRecent);
+ //ON_COMMAND_RANGE(WM_STUDIO_OPEN_RECENT_MIN, WM_STUDIO_OPEN_RECENT_MAX, OnFileOpenRecent)
+
+ // Edit Menu
+ connect(m_ui->action_Undo, &QAction::triggered, this, &CMainFrame::OnEditUndo);
+ connect(m_ui->action_Redo, &QAction::triggered, this, &CMainFrame::OnEditRedo);
+ connect(m_ui->action_Copy, &QAction::triggered, this, &CMainFrame::OnEditCopy);
+ connect(m_ui->action_Cut, &QAction::triggered, this, &CMainFrame::OnEditCut);
+ connect(m_ui->actionAutoset_Keyframes, &QAction::triggered, this, &CMainFrame::OnToolAutosetkeys);
+ connect(m_ui->action_Paste, &QAction::triggered, this, &CMainFrame::OnEditPaste);
+ connect(m_ui->actionStudio_Preferences, &QAction::triggered, this, &CMainFrame::OnEditApplicationPreferences);
+ connect(m_ui->actionPresentation_Settings, &QAction::triggered, this, &CMainFrame::OnEditPresentationPreferences);
+ connect(m_ui->actionSubpresentations, &QAction::triggered, this,
+ &CMainFrame::OnEditSubPresentations);
+ connect(m_ui->action_Duplicate_Object, &QAction::triggered, this, &CMainFrame::OnEditDuplicate);
+
+ // Timeline Menu
+ connect(m_ui->actionDelete_Selected_Keyframe_s, &QAction::triggered, this, &CMainFrame::OnTimelineDeleteSelectedKeyframes);
+ connect(m_ui->actionSet_Interpolation, &QAction::triggered, this, &CMainFrame::OnTimelineSetInterpolation);
+ connect(m_ui->actionChange_Time_Bar_Color, &QAction::triggered, this, &CMainFrame::OnTimelineSetTimeBarColor);
+ connect(m_ui->actionSet_Changed_Keyframes, &QAction::triggered, this, &CMainFrame::OnTimelineSetChangedKeyframe);
+
+ // View Menu
+ connect(m_ui->actionBounding_Boxes, &QAction::triggered, this, &CMainFrame::OnViewBoundingBoxes);
+ connect(m_ui->actionPivot_Point, &QAction::triggered, this, &CMainFrame::OnViewPivotPoint);
+ connect(m_ui->actionWireframe, &QAction::triggered, this, &CMainFrame::OnViewWireframe);
+ connect(m_ui->actionTooltips, &QAction::triggered, this, &CMainFrame::OnViewTooltips);
+
+ // Tools Menu
+ connect(m_ui->actionTimeline, &QAction::triggered, this, &CMainFrame::OnViewTimeline);
+ connect(m_ui->actionAction, &QAction::triggered, this, &CMainFrame::OnViewAction);
+ connect(m_ui->actionBasic_Objects, &QAction::triggered, this, &CMainFrame::OnViewBasicObjects);
+ connect(m_ui->actionProject, &QAction::triggered, this, &CMainFrame::OnViewProject);
+ connect(m_ui->actionSlide, &QAction::triggered, this, &CMainFrame::OnViewSlide);
+ connect(m_ui->actionInspector, &QAction::triggered, this, &CMainFrame::OnViewInspector);
+
+ // Help Menu
+ connect(m_ui->action_Reference_Manual, &QAction::triggered, this, &CMainFrame::OnHelpIndex);
+ connect(m_ui->action_Visit_Qt_Web_Site, &QAction::triggered, this, &CMainFrame::OnHelpVisitQt);
+ connect(m_ui->action_About_Qt_3D_Studio, &QAction::triggered, []() { g_StudioApp.OnAppAbout(); });
+ connect(m_ui->action_Open_Tutorial, &QAction::triggered, this, &CMainFrame::OnHelpOpenTutorial);
+
+
+ connect(m_ui->actionItem_Select_Tool, &QAction::triggered, m_SceneView, &CSceneView::OnToolItemSelection);
+ connect(m_ui->actionGroup_Select_Tool, &QAction::triggered, m_SceneView, &CSceneView::OnToolGroupSelection);
+
+ // Playback toolbar
+ connect(m_ui->actionPlay, &QAction::triggered, this, &CMainFrame::OnPlaybackPlay);
+ connect(m_ui->actionRewind, &QAction::triggered, this, &CMainFrame::OnPlaybackRewind);
+ connect(m_ui->actionStop, &QAction::triggered, this, &CMainFrame::OnPlaybackStop);
+ connect(m_ui->actionPreview, &QAction::triggered, this, &CMainFrame::OnPlaybackPreview);
+
+ // Tool mode toolbar
+ connect(m_ui->actionPosition_Tool, &QAction::triggered, this, &CMainFrame::OnToolMove);
+ connect(m_ui->actionRotation_Tool, &QAction::triggered, this, &CMainFrame::OnToolRotate);
+ connect(m_ui->actionScale_Tool, &QAction::triggered, this, &CMainFrame::OnToolScale);
+ connect(m_ui->actionLocal_Global_Manipulators, &QAction::triggered, this, &CMainFrame::OnToolGlobalManipulators);
+
+ // Edit Camera toolbar
+ connect(m_ui->actionFit_Selected, &QAction::triggered, this, &CMainFrame::OnEditCameraZoomExtent);
+ connect(m_ui->actionPan_Tool, &QAction::triggered, this, &CMainFrame::OnEditCameraPan);
+ connect(m_ui->actionOrbit_Tool, &QAction::triggered, this, &CMainFrame::OnEditCameraRotate);
+ connect(m_ui->actionZoom_Tool, &QAction::triggered, this, &CMainFrame::OnEditCameraZoom);
+ connect(m_ui->actionShading_Mode, &QAction::triggered, this, &CMainFrame::OnEditViewFillMode);
+ connect(m_ui->actionRulers_Guides, &QAction::triggered, this, &CMainFrame::OnViewGuidesRulers);
+ connect(m_ui->actionClear_Guides, &QAction::triggered, this, &CMainFrame::OnClearGuides);
+ connect(m_ui->actionLock_Guides, &QAction::triggered, this, &CMainFrame::OnLockGuides);
+
+ // TODO: better solution?
+ QTimer* updateUITimer = new QTimer;
+ updateUITimer->start(500);
+ connect(updateUITimer, &QTimer::timeout, [&]() {
+ if (QApplication::activeWindow() != this)
+ return;
+
+ OnUpdateFileSave();
+ OnUpdateEditUndo();
+ OnUpdateEditRedo();
+ OnUpdateEditCopy();
+ OnUpdateEditCut();
+ OnUpdateToolAutosetkeys();
+ OnUpdateEditPaste();
+ OnUpdateEditDuplicate();
+ OnUpdateTimelineDeleteSelectedKeyframes();
+ OnUpdateTimelineSetInterpolation();
+ OnUpdateTimelineSetTimeBarColor();
+ OnUpdateViewBoundingBoxes();
+ OnUpdateViewPivotPoint();
+ OnUpdateViewWireframe();
+ OnUpdateViewTooltips();
+ OnUpdateViewTimeline();
+ OnUpdateViewInspector();
+ OnUpdateViewAction();
+ OnUpdateViewBasicObjects();
+ OnUpdateViewProject();
+ OnUpdateViewSlide();
+ OnUpdateHelpIndex();
+ OnUpdatePlaybackPlay();
+ OnUpdatePlaybackRewind();
+ OnUpdatePlaybackStop();
+ OnUpdatePlaybackPreview();
+ OnUpdateToolMove();
+ OnUpdateToolRotate();
+ OnUpdateToolScale();
+ OnUpdateToolGlobalManipulators();
+ OnUpdateToolGroupSelection();
+ OnUpdateToolItemSelection();
+ OnUpdateCameraZoomExtentAndAuthorZoom();
+ OnUpdateEditCameraPan();
+ OnUpdateEditCameraRotate();
+ OnUpdateEditCameraZoom();
+ OnUpdateEditViewFillMode();
+ OnUpdateViewGuidesRulers();
+ OnUpdateClearGuides();
+ OnUpdateLockGuides();
+ });
+
+ m_playbackTimer.setInterval(PLAYBACK_TIMER_TIMEOUT);
+ connect(&m_playbackTimer, &QTimer::timeout, this, &CMainFrame::onPlaybackTimeout);
+ qApp->installEventFilter(this);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMainFrame::~CMainFrame()
+{
+}
+
+//==============================================================================
+/**
+ * Timer callback
+ */
+void CMainFrame::onPlaybackTimeout()
+{
+ // Timer callback that drives playback
+ Q_ASSERT(&g_StudioApp);
+ g_StudioApp.GetCore()->GetDoc()->ClientStep();
+}
+
+//==============================================================================
+
+void CMainFrame::showEvent(QShowEvent *event)
+{
+ QMainWindow::showEvent(event);
+
+ QSettings settings;
+ restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
+ restoreState(settings.value("mainWindowState").toByteArray());
+}
+
+/**
+ * Called when the main frame is actually created. Sets up tool bars and default
+ * views.
+ */
+int CMainFrame::OnCreate()
+{
+ m_SceneView = new CSceneView(&g_StudioApp, this);
+ connect(m_SceneView, &CSceneView::toolChanged, this, &CMainFrame::OnUpdateToolChange);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // tell the edit camera bar about this scene view
+ m_ui->m_EditCamerasBar->SetSceneView(m_SceneView);
+#endif
+
+ // Newly launched, the file dialog for open and import should default to more recent
+ // opened/imported
+ CDialogs *theDialogs = g_StudioApp.GetDialogs();
+ // this must NOT be in 'command line' mode
+ if (theDialogs) {
+ Q3DStudio::CString theMostRecentOpen;
+ if (m_RecentItems && m_RecentItems->GetItemCount() > 0)
+ theMostRecentOpen = m_RecentItems->GetItem(0).GetPath();
+ if (theMostRecentOpen.IsEmpty()) // default to exe
+ theMostRecentOpen = CUICFile::GetApplicationDirectory().GetPath();
+
+ theDialogs->ResetSettings(theMostRecentOpen);
+ }
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Change the background color for the menu bar
+ if (IsMenu(theMenu)) {
+ MENUINFO theMenuInfo = { 0 };
+ theMenuInfo.cbSize = sizeof(MENUINFO);
+ theMenuInfo.fMask = MIM_BACKGROUND;
+
+ CBrush *theNewBrush = new CBrush();
+ CColor theBaseColor(CStudioPreferences::GetMenuBarBaseColor());
+ theNewBrush->CreateSolidBrush(
+ RGB(theBaseColor.GetRed(), theBaseColor.GetGreen(), theBaseColor.GetBlue()));
+ theMenuInfo.hbrBack = *theNewBrush; // Brush you want to draw
+
+ SetMenuInfo(theMenu, &theMenuInfo);
+ }
+ #endif
+
+ // Create the view manager
+ m_PaletteManager = new CPaletteManager(this);
+
+ // Remove basic toolbar (open, save, undo/redo, etc.)
+ // Kept in ui form in case it is going to be added back later on.
+ delete m_ui->toolBar;
+
+ setCentralWidget(m_SceneView);
+ return 0;
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+// If we want things to look good then on the *first* paint we want to actually
+// paint over the background. I don't know why, but if you were to paint
+// the entire background on every message you would get some flashing.
+void CMainFrame::OnPaint()
+{
+ static bool needsPaint = true;
+ if (needsPaint) {
+ needsPaint = false;
+ RECT theRect;
+ ::GetClientRect(GetSafeHwnd(), &theRect);
+ CBrush theBrush;
+ ::CColor theColor = CStudioPreferences::GetBaseColor();
+ DWORD theColorRef = RGB(theColor.GetRed(), theColor.GetGreen(), theColor.GetBlue());
+ theBrush.CreateSolidBrush(theColor);
+ CPaintDC dc(this);
+ dc.FillRect(&theRect, &theBrush);
+ }
+ CFrameWnd::OnPaint();
+}
+//==============================================================================
+void CMainFrame::OnInitMenu(CMenu *inMenu)
+{
+ ReleaseFocus();
+ // Emulate a Control ModifierUp on the Sceneview to "unstick" the Alt-Key/Scale Tool
+ m_SceneView->HandleModifierUp(CHotKeys::KEY_MENU, 0, 0);
+ CFrameWnd::OnInitMenu(inMenu);
+}
+
+::CString CMainFrame::m_WindowClass;
+
+::CString CMainFrame::GetWindowClass()
+{
+ if (m_WindowClass.GetLength() == 0) {
+ ::CColor theColor = CStudioPreferences::GetBaseColor();
+ DWORD theRefColor = RGB(theColor.GetRed(), theColor.GetGreen(), theColor.GetBlue());
+ HBRUSH theBrush = ::CreateSolidBrush(theRefColor);
+ m_WindowClass = AfxRegisterWndClass(0, 0, theBrush, 0);
+ }
+ return m_WindowClass;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &cs)
+{
+ if (!CFrameWnd::PreCreateWindow(cs))
+ return FALSE;
+
+ // TODO: Modify the Window class or styles here by modifying
+ cs.lpszClass = GetWindowClass();
+ return TRUE;
+}
+
+BOOL CMainFrame::DestroyWindow()
+{
+ // Save before we destroy anything
+ SaveLayout();
+
+ SAFE_DELETE(m_PaletteManager);
+
+ g_StudioApp.GetCore()->GetDispatch()->RemovePresentationChangeListener(this);
+ g_StudioApp.GetCore()->GetDispatch()->RemoveFileOpenListener(this);
+ g_StudioApp.GetCore()->GetDispatch()->RemoveClientPlayChangeListener(this);
+
+ SAFE_DELETE(m_RecentItems);
+
+ // In order to help debug why image lists sometimes crash on shutdown
+ // This will help identify whcih cone is causing the problem
+ m_ClientToolsImageList.DeleteImageList();
+ m_ClientToolsImageListHot.DeleteImageList();
+ m_ClientToolsImageListDisabled.DeleteImageList();
+ m_PlaybackImageList.DeleteImageList();
+ m_PlaybackImageListHot.DeleteImageList();
+ m_PlaybackImageListDisabled.DeleteImageList();
+ m_EditCameraToolsImageList.DeleteImageList();
+ m_EditCameraToolsImageListHot.DeleteImageList();
+ m_EditCameraToolsImageListDisabled.DeleteImageList();
+
+ return CFrameWnd::DestroyWindow();
+}
+#endif
+
+//==============================================================================
+/**
+ * Called when a new presenation is created. We have to wait to associate the
+ * scene object with the scene view until this point, because the scene object
+ * does not exist until this function gets called.
+ */
+void CMainFrame::OnNewPresentation()
+{
+ // TODO - CN needs to fix this
+ // Associate the scene object with the scene view
+ m_ui->m_EditCamerasBar->SetupCameras();
+}
+
+//==============================================================================
+/**
+ * Called when the current presentation is being closed.
+ * This will close all the editor windows that are open.
+ */
+void CMainFrame::OnClosingPresentation()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the Timeline | Set Interpolation menu item
+ * This is a temporary method that will display the Set Interpolation dialog.
+ */
+void CMainFrame::OnTimelineSetInterpolation()
+{
+ g_StudioApp.GetCore()->GetDoc()->SetKeyframeInterpolation();
+}
+
+//==============================================================================
+/**
+ * Store all the information regarding the layout of the main frame and its palettes.
+ * This is used to save the current position, so when the app is restarted the
+ * window will come back to it's previous location.
+ * On one hand, there is the main frame which continues to use the original
+ * CPaletteState scheme. Now there is also the control bars/palettes that dock.
+ * These all now use the MFC path for serialization to the registry.
+ * This operation used to occur every time there was a change to any window, now
+ * the final state is only saved when the app is closed.
+ */
+void CMainFrame::SaveLayout()
+{
+ if (m_PaletteManager)
+ m_PaletteManager->Save();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Only save the window position if we're not minimized
+ if (!IsIconic()) {
+ CPaletteState theState("MainWindow");
+
+ theState.SetMaximized(IsZoomed() == TRUE);
+ if (!IsZoomed()) {
+ /*
+ SDJ: 12/17/03 - From MSDN
+ The coordinates used in a WINDOWPLACEMENT structure should be used only by the
+ GetWindowPlacement and SetWindowPlacement functions. Passing coordinates
+ to functions which expect screen coordinates (such as SetWindowPos) will result
+ in the window appearing in the wrong location. For example, if the taskbar is at
+ the top of the screen, saving window coordinates using GetWindowPlacement and
+ restoring them using SetWindowPos causes the window to appear to "creep" up the screen.
+
+ We were using GetWindowPlacement with MoveWindow (in SetLayout) which was causing
+ "creep" when the taskbar was at the top of the screen. Replaced GetWindowPlacement
+ with the following GetWindowRect call.
+ */
+
+ CRect theRect;
+ GetWindowRect(&theRect);
+
+ theState.SetPosition(CPt(theRect.left, theRect.top));
+ theState.SetSize(CPt(theRect.right - theRect.left, theRect.bottom - theRect.top));
+ }
+ theState.SetVisible(IsWindowVisible() ? true : false);
+
+ theState.SaveState();
+
+ // Force a recalc of the layout to ensure that everything is correct with the docking
+ RecalcLayout(TRUE);
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Restore all the information regarding the layout of the main frame and its palettes.
+ * This will make the window be located at the last stored location.
+ * On one hand, there is the main frame which continues to use the original
+ * CPaletteState scheme. Now there is also the control bars/palettes that dock.
+ * These all now use the MFC path for serialization to the registry. This happens
+ * on startup.
+ */
+void CMainFrame::RestoreLayout()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CPaletteState theState("MainWindow");
+ theState.LoadState();
+
+ SetLayout(theState);
+
+ if (!m_PaletteManager->Load())
+ m_PaletteManager->RestoreDefaults(true);
+
+ // Force a recalc for the layout for the docking palettes to work
+ RecalcLayout(TRUE);
+#endif
+}
+
+//==============================================================================
+/**
+ * Set the state of this window to the specified state.
+ */
+void CMainFrame::SetLayout(const CPaletteState &inState)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CPt thePosition = inState.GetPosition();
+ CPt theSize = inState.GetSize();
+ bool isVisible = inState.IsVisible();
+
+ CRect theWindowRect(thePosition.x, thePosition.y, thePosition.x + theSize.x,
+ thePosition.y + theSize.y);
+
+ // Relocate the window to the new location
+ MoveWindow(theWindowRect);
+
+ if (inState.IsMaximized())
+ ::AfxGetApp()->m_nCmdShow = SW_SHOWMAXIMIZED;
+ ShowWindow(::AfxGetApp()->m_nCmdShow);
+ ShowWindow((isVisible ? SW_SHOW : SW_HIDE));
+#endif
+ // UpdateWindow();
+}
+
+//==============================================================================
+/**
+ * OnEditRedo: calls handleRedoOperation
+ */
+//==============================================================================
+void CMainFrame::OnEditRedo()
+{
+ g_StudioApp.GetCore()->GetCmdStack()->Redo();
+}
+
+//==============================================================================
+/**
+ * OnEditUndo: calls HandleUndoOperation
+ */
+//==============================================================================
+void CMainFrame::OnEditUndo()
+{
+ g_StudioApp.GetCore()->GetCmdStack()->Undo();
+}
+
+//==============================================================================
+/**
+ * OnUpdateEditUndo: Handler for ID_EDIT_UNDO message
+ *
+ * @param pCmndUI The UI element that generated the message
+ */
+void CMainFrame::OnUpdateEditUndo()
+{
+ const QString undoDescription = QObject::tr("Undo %1\tCtrl+Z").arg(g_StudioApp.GetCore()->GetCmdStack()->GetUndoDescription());
+ m_ui->action_Undo->setEnabled(g_StudioApp.CanUndo());
+ m_ui->action_Undo->setText(undoDescription);
+}
+
+//==============================================================================
+/**
+ * OnUpdateEditRedo: handles the message ID_EDIT_REDO
+ *
+ * @param pCmndUI The UI element that generated the message
+ */
+void CMainFrame::OnUpdateEditRedo()
+{
+ const QString redoDescription = QObject::tr("Redo %1\tCtrl+Y").arg(g_StudioApp.GetCore()->GetCmdStack()->GetRedoDescription());
+ m_ui->action_Redo->setEnabled(g_StudioApp.CanRedo());
+ m_ui->action_Redo->setText(redoDescription);
+}
+
+//==============================================================================
+/**
+ * OnEditCopy: Handles the Copy message
+ *
+ * Tells the doc to copy the selected keyframes.
+ */
+void CMainFrame::OnEditCopy()
+{
+ g_StudioApp.OnCopy();
+}
+
+//==============================================================================
+/**
+ * OnUpdateEditCopy: Handle the update UI command for the copy button and menu item
+ *
+ * If there are keyframes selected, the button is enabled, otherwise, it is
+ * disabled.
+ *
+ * @param pCmndUI The UI element that generated the message
+ */
+void CMainFrame::OnUpdateEditCopy()
+{
+ if (g_StudioApp.CanCopy()) {
+ Q3DStudio::CString theDescription;
+ theDescription.Format(::LoadResourceString(IDS_MENU_WIN_COPY_FORMAT),
+ static_cast<const wchar_t *>(g_StudioApp.GetCopyType()));
+
+ m_ui->action_Copy->setText(theDescription.toQString());
+ m_ui->action_Copy->setEnabled(true);
+ } else {
+ m_ui->action_Copy->setEnabled(false);
+ }
+}
+
+//==============================================================================
+/**
+ * OnEditCut: Handles the Cut message
+ *
+ * Tells the doc to cut the selected keyframes.
+ */
+void CMainFrame::OnEditCut()
+{
+ g_StudioApp.OnCut();
+}
+
+//==============================================================================
+/**
+ * OnUpdateEditCut: Handle the update UI command for the cut button and menu item
+ *
+ * If there are keyframes selected, the button is enabled, otherwise, it is
+ * disabled.
+ *
+ * @param pCmndUI The UI element that generated the message
+ */
+void CMainFrame::OnUpdateEditCut()
+{
+ if (g_StudioApp.CanCut()) {
+ Q3DStudio::CString theDescription;
+ theDescription.Format(::LoadResourceString(IDS_MENU_WIN_CUT_FORMAT),
+ static_cast<const wchar_t *>(g_StudioApp.GetCopyType()));
+
+ m_ui->action_Cut->setText(theDescription.toQString());
+ m_ui->action_Cut->setEnabled(true);
+ } else {
+ m_ui->action_Cut->setEnabled(false);
+ }
+}
+
+//==============================================================================
+/**
+ * OnEditPaste: Handles the Paste command
+ *
+ * Tells the doc to paste the copied keyframes at the current playhead time, on
+ * the currently selected object.
+ */
+void CMainFrame::OnEditPaste()
+{
+ g_StudioApp.OnPaste();
+}
+
+//==============================================================================
+/**
+ * OnUpdateEditPaste: Handle the update UI command for the paste button and menu item
+ *
+ * If there we can perform a keyframe paste, the button is enabled, otherwise, it is
+ * disabled.
+ *
+ * @param pCmndUI The UI element that generated the message
+ */
+void CMainFrame::OnUpdateEditPaste()
+{
+ if (g_StudioApp.CanPaste()) {
+ Q3DStudio::CString theUndoDescription;
+ theUndoDescription.Format(::LoadResourceString(IDS_MENU_WIN_PASTE_FORMAT),
+ static_cast<const wchar_t *>(g_StudioApp.GetPasteType()));
+
+ m_ui->action_Paste->setText(theUndoDescription.toQString());
+
+ m_ui->action_Paste->setEnabled(true);
+ } else {
+ m_ui->action_Paste->setEnabled(false);
+ }
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//=============================================================================
+/**
+ * Router for forwarding messages onto the MsgRouter.
+ * This is used for posting messages between threads.
+ */
+LRESULT CMainFrame::OnMsgRouterMsg(WPARAM inWParam, LPARAM inLParam)
+{
+ CMsgRouter::GetInstance()->HandleMessage(inWParam, inLParam);
+
+ return TRUE;
+}
+#endif
+
+//=============================================================================
+/**
+ * Called when a tool mode changes from a modifier key
+ */
+void CMainFrame::OnUpdateToolChange()
+{
+ long theSelectMode = g_StudioApp.GetSelectMode();
+ m_ui->actionGroup_Select_Tool->setChecked(theSelectMode == STUDIO_SELECTMODE_GROUP);
+ m_ui->actionItem_Select_Tool->setChecked(theSelectMode == STUDIO_SELECTMODE_ENTITY);
+
+ // See what tool mode we are in and change checks accordingly
+ long theToolMode = g_StudioApp.GetToolMode();
+ m_ui->actionPosition_Tool->setChecked(theToolMode == STUDIO_TOOLMODE_MOVE);
+ m_ui->actionRotation_Tool->setChecked(theToolMode == STUDIO_TOOLMODE_ROTATE);
+ m_ui->actionScale_Tool->setChecked(theToolMode == STUDIO_TOOLMODE_SCALE);
+ m_ui->actionLocal_Global_Manipulators->setChecked(g_StudioApp.GetMinpulationMode()
+ == StudioManipulationModes::Global);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ m_ui->actionPan_Tool->setChecked(theToolMode == STUDIO_TOOLMODE_CAMERA_PAN);
+ m_ui->actionOrbit_Tool->setChecked(theToolMode == STUDIO_TOOLMODE_CAMERA_ROTATE);
+ m_ui->actionZoom_Tool->setChecked(theToolMode == STUDIO_TOOLMODE_CAMERA_ZOOM);
+
+/*CEditCameraContainer* theEditCameras = g_StudioApp.GetCore()->GetDoc()->GetEditCameraContainer( );
+CSEditCamera* theActiveEditCamera = theEditCameras->GetActiveEditCamera( );
+bool theIsEditView = !m_SceneView->IsDeploymentView( );
+m_EditCamerasBar.GetToolBarCtrl( ).EnableButton( ID_TOOL_EDITCAMERA_ROTATE, ( theActiveEditCamera &&
+theActiveEditCamera->Is3D( ) ) );
+m_EditCamerasBar.GetToolBarCtrl( ).EnableButton( ID_TOOL_EDITCAMERA_PAN, theIsEditView );
+m_EditCamerasBar.GetToolBarCtrl( ).EnableButton( ID_TOOL_EDITCAMERA_ZOOM, theIsEditView );
+m_EditCamerasBar.GetToolBarCtrl( ).EnableButton( ID_EDITCAMERA_ZOOMEXTENT, theIsEditView );
+
+m_EditCamerasBar.GetToolBarCtrl( ).EnableButton( ID_TOOL_EDITVIEW_FILLMODE, theIsEditView );
+m_EditCamerasBar.GetToolBarCtrl( ).CheckButton( ID_TOOL_EDITVIEW_FILLMODE, theIsEditView &&
+theEditCameras->GetEditViewFillMode( ) );
+*/
+#endif
+}
+
+//==============================================================================
+/**
+ * OnTimelineSettimebarcolor: Handles the ID_TIMELINE_SETTIMEBARCOLOR message.
+ *
+ * Called when the user clicks on Timeline->Change Time Bar Color. Changes
+ * the currently selected timebar's color.
+ */
+void CMainFrame::OnTimelineSetTimeBarColor()
+{
+ ITimelineTimebar *theTimelineTimebar = GetSelectedTimelineTimebar();
+ if (theTimelineTimebar != NULL) {
+ CColor theColor = theTimelineTimebar->GetTimebarColor();
+
+ if (g_StudioApp.GetDialogs()->PromptObjectTimebarColor(theColor))
+ theTimelineTimebar->SetTimebarColor(theColor);
+ }
+}
+
+//==============================================================================
+/**
+ * OnUpdateTimelineSetTimeBarColor: Handles the update UI message for the
+ * "Change Time Bar Color" menu item.
+ *
+ * If the currently selected object is an item in the timeline and it has a
+ * time bar, this menu item is enabled. Otherwise, the menu item is disabled.
+ *
+ * @param pCmndUI Pointer to the ui object that generated this update message.
+ */
+void CMainFrame::OnUpdateTimelineSetTimeBarColor()
+{
+ m_ui->actionChange_Time_Bar_Color->setEnabled(g_StudioApp.CanChangeTimebarColor());
+}
+
+//==============================================================================
+/**
+ * OnTimelineSetChangedKeyframe: Handles the ID_TIMELINE_SETCHANGEDKEYFRAME message.
+ *
+ * Calls the StudioDoc handler to insert keyframes for animatable properties that
+ * have changed.
+ */
+void CMainFrame::OnTimelineSetChangedKeyframe()
+{
+ g_StudioApp.HandleSetChangedKeys();
+}
+
+//==============================================================================
+/**
+ * OnTimelineDeleteSelectedKeyframes: Handles the ID_TIMELINE_DELETESELECTEDKEYFRAMES
+ * message.
+ *
+ * Deletes all currently selected keyframes.
+ */
+void CMainFrame::OnTimelineDeleteSelectedKeyframes()
+{
+ g_StudioApp.DeleteSelectedKeys();
+}
+
+//==============================================================================
+/**
+ * OnUpdateTimelineDeleteSelectedKeyframes: Handles the update UI message for
+ * the "Delete Selected Keyframe(s)" message.
+ *
+ * If there are currently keyframes selected, the menu item is enabled. Otherwise,
+ * the menu item is disabled.
+ *
+ * @param pCmdUI The UI element that generated this message
+ */
+void CMainFrame::OnUpdateTimelineDeleteSelectedKeyframes()
+{
+ m_ui->actionDelete_Selected_Keyframe_s->setEnabled(g_StudioApp.CanCopy());
+}
+
+//==============================================================================
+/**
+ * OnUpdateTimelineSetInterpolation: Handles the update UI message for
+ * the "Set Interpolation" message.
+ *
+ * If there are currently keyframes selected, this menu item is enabled, otherwise
+ * it is disabled.
+ *
+ * @param pCmdUI The UI element that generated this message
+ */
+void CMainFrame::OnUpdateTimelineSetInterpolation()
+{
+ m_ui->actionSet_Interpolation->setEnabled(g_StudioApp.GetCore()->GetDoc()->GetKeyframesManager()->HasSelectedKeyframes());
+}
+
+//==============================================================================
+/**
+ * OnEditDuplicate: Handles the ID_EDIT_DUPLICATE message.
+ *
+ * Pass through to the doc.
+ */
+void CMainFrame::OnEditDuplicate()
+{
+ g_StudioApp.HandleDuplicateCommand();
+}
+
+//==============================================================================
+/**
+ * OnUpdateEditDuplicate: Handles the UPDATE COMMAND UI message for this menu item.
+ *
+ * If the currently selected object is not null, and it is not in the library,
+ * then the user can duplicate the object and the menu item is enabled. Otherwise,
+ * it is disabled.
+ */
+void CMainFrame::OnUpdateEditDuplicate()
+{
+ m_ui->action_Duplicate_Object->setEnabled(g_StudioApp.CanDuplicateObject());
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Open menu and toolbar options.
+ * This will save the file, if the file has not been saved before this will
+ * do a save as operation.
+ */
+void CMainFrame::OnFileOpen()
+{
+ g_StudioApp.OnFileOpen();
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Save menu and toolbar options.
+ * This will save the file, if the file has not been saved before this will
+ * do a save as operation.
+ */
+void CMainFrame::OnFileSave()
+{
+ g_StudioApp.OnSave();
+}
+
+void CMainFrame::OnUpdateFileSave()
+{
+ m_ui->action_Save->setEnabled(g_StudioApp.GetCore()->GetDoc()->IsModified());
+}
+//=============================================================================
+/**
+ * Command handler for the File Save As menu option.
+ * This will prompt the user for a location to save the file out to then
+ * will perform the save.
+ */
+void CMainFrame::OnFileSaveAs()
+{
+ g_StudioApp.OnSaveAs();
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Save a Copy menu option.
+ * This will prompt the user for a location to save the file out to then
+ * save a copy, leaving the original file open in the editor.
+ */
+void CMainFrame::OnFileSaveCopy()
+{
+ g_StudioApp.OnSaveCopy();
+}
+
+//=============================================================================
+/**
+ * Command handler for the New Document menu option.
+ * This will create a new default document.
+ */
+void CMainFrame::OnFileNew()
+{
+ g_StudioApp.OnFileNew();
+}
+
+
+//==============================================================================
+/**
+ * Overrides the close method to prompt if the document is modified.
+ */
+void CMainFrame::closeEvent(QCloseEvent *event)
+{
+ QSettings settings;
+ settings.setValue("mainWindowGeometry", saveGeometry());
+ settings.setValue("mainWindowState", saveState());
+ QMainWindow::closeEvent(event);
+
+ if (g_StudioApp.GetCore()->GetDoc()->IsModified()) {
+ CDialogs::ESavePromptResult theResult = g_StudioApp.GetDialogs()->PromptForSave();
+ if (theResult == CDialogs::SAVE_FIRST) {
+ // If the save was canceled or failed then do not exit.
+ if (!g_StudioApp.OnSave())
+ return;
+ }
+ // On cancel ditch out of here and abort exit. Abort! Abort!
+ else if (theResult == CDialogs::CANCEL_OPERATION) {
+ event->ignore();
+ return;
+ }
+ }
+
+ // Tell the app to shutdown, do it here so it does not rely on static destructor.
+ g_StudioApp.PerformShutdown();
+}
+
+//==============================================================================
+/**
+ * Displays the preferences dialog and can change program settings.
+ */
+void CMainFrame::OnEditApplicationPreferences()
+{
+ EditPreferences(PAGE_STUDIOAPPPREFERENCES);
+}
+
+//==============================================================================
+/**
+ * Displays the preferences dialog and can change program settings.
+ */
+void CMainFrame::OnEditPresentationPreferences()
+{
+ EditPreferences(PAGE_STUDIOPROJECTSETTINGS);
+}
+
+//==============================================================================
+/**
+ * Displays the preferences dialog and can change subpresentation settings.
+ */
+void CMainFrame::OnEditSubPresentations()
+{
+ QString dir = g_StudioApp.GetCore()->GetDoc()->GetDocumentDirectory().toQString();
+
+ CSubPresentationsDlg dlg(QDir::toNativeSeparators(dir),
+ g_StudioApp.m_subpresentations);
+ dlg.exec();
+ if (dlg.result() == QDialog::Accepted) {
+ g_StudioApp.m_subpresentations = dlg.subpresentations();
+ g_StudioApp.SaveUIAFile();
+ }
+}
+
+//==============================================================================
+/**
+ * EditPreferences: Displays the presentation settings property sheet with
+ * the specified active page.
+ *
+ * Used for editing the application and project settings.
+ *
+ * @param inPageIndex The page index to select when displayed.
+ */
+void CMainFrame::EditPreferences(short inPageIndex)
+{
+ // Set the active page based on the inPageIndex
+ CStudioPreferencesPropSheet thePropSheet(::LoadResourceString(IDS_STUDIOPREFSTITLE).toQString(),
+ this, inPageIndex);
+
+ // CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings();
+
+ // Q3DStudio::CString theAuthorName theAuthorName = theProjectSettings->GetAuthor();
+ // Q3DStudio::CString theCompanyName theCompanyName = theProjectSettings->GetCompany();
+
+ // Display the CStudioPreferencesPropSheet
+ int thePrefsReturn = thePropSheet.exec();
+
+ // Ugly hack to fix some bug
+ m_SceneView->OnEditCameraChanged();
+
+ if (thePrefsReturn == PREFS_RESET_DEFAULTS) {
+ // Restore default values
+ g_StudioApp.SetAutosetKeyframes(true);
+ CStudioPreferences::SetBoundingBoxesOn(true);
+ CStudioPreferences::SetTimebarDisplayTime(true);
+ g_StudioApp.GetCore()->GetDoc()->SetDefaultKeyframeInterpolation(true);
+ CStudioPreferences::SetNudgeAmount(10.0f);
+ CStudioPreferences::SetSnapRange(10);
+ CStudioPreferences::SetTimelineSnappingGridActive(true);
+ CStudioPreferences::SetTimelineSnappingGridResolution(SNAPGRID_SECONDS);
+// Edit Cameras
+#ifdef INCLUDE_EDIT_CAMERA
+ CColor theDefaultBgColor(CStudioPreferences::EDITVIEW_DEFAULTBGCOLOR);
+ CStudioPreferences::SetEditViewBackgroundColor(theDefaultBgColor);
+ // g_StudioApp.GetCore()->GetDoc()->SetEditViewBackgroundColor( theDefaultBgColor );
+ CStudioPreferences::SetPreferredStartupView(
+ CStudioPreferences::PREFERREDSTARTUP_DEFAULTINDEX);
+#endif
+
+ if (m_PaletteManager)
+ m_PaletteManager->RestoreDefaults();
+
+ RecheckSizingMode();
+
+ // Remove keys related to the ObjRef and PropRef Pickers
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("ObjectReferenceWidth");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("ObjectReferenceHeight");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("ObjectReferenceXPos");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("ObjectReferenceYPos");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("PropertyReferenceWidth");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("PropertyReferenceHeight");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("PropertyReferenceXPos");
+ CPreferences::GetUserPreferences(::LoadResourceString(IDS_PREFS_REFERENCECONTROLS))
+ .RemoveKey("PropertyReferenceYPos");
+
+ // Also clear out the viewer's settings file
+ Q3DStudio::CFilePath theFilePath(Q3DStudio::CFilePath::CombineBaseAndRelative(
+ Q3DStudio::CFilePath::GetUserApplicationDirectory(),
+ "UIComposer\\UICViewerSettings.txt"));
+ theFilePath.DeleteThisFile();
+ }
+}
+
+//==============================================================================
+/**
+ * OnToolAutosetkeys: Called when the Autoset Keyframe button is pressed.
+ * Calls the doc to turn off or on the Autoset Keyframe preference.
+ */
+void CMainFrame::OnToolAutosetkeys()
+{
+ // Toggle autoset keyframes to the opposite of what it's currently set as
+ g_StudioApp.SetAutosetKeyframes(!CStudioPreferences::IsAutosetKeyframesOn());
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolAutosetkeys: Updates the UI associated with this button.
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+void CMainFrame::OnUpdateToolAutosetkeys()
+{
+ // If autoset keyframes is on
+ m_ui->actionAutoset_Keyframes->setChecked(CStudioPreferences::IsAutosetKeyframesOn());
+}
+
+//==========================================================================
+/**
+ * Called when the presentation is being played in Studio. Updates the play
+ * button on the main frame.
+ */
+void CMainFrame::OnPlayStart()
+{
+ // Update the play button since this doesn't always happen automatically
+ m_ui->actionPlay->setChecked(true);
+
+ if (m_PlaybackFlag == false) {
+ m_PlaybackFlag = true;
+
+ // g_StudioApp.GetCore()->GetDoc()->SetPlayMode( PLAYMODE_PLAY );
+
+ m_playbackTimer.start();
+ }
+}
+
+//==========================================================================
+/**
+ * Called when the presentation stops being played in Studio. Updates the play
+ * button on the main frame.
+ */
+void CMainFrame::OnPlayStop()
+{
+ // Update the play button since this doesn't always happen automatically
+ m_ui->actionPlay->setChecked(false);
+
+ if (m_PlaybackFlag == true) {
+ m_PlaybackFlag = false;
+ m_playbackTimer.stop();
+ // g_StudioApp.GetCore()->GetDoc()->SetPlayMode( PLAYMODE_STOP );
+ }
+}
+
+//==========================================================================
+/**
+ * Called when the presentation time changes. Not handled by this class,
+ * but included because the base class requires it to be implemented.
+ */
+void CMainFrame::OnTimeChanged(long inTime)
+{
+ Q_UNUSED(inTime);
+ // Do nothing
+}
+
+//==============================================================================
+/**
+ * Handles pressing the play button.
+ */
+void CMainFrame::OnPlaybackPlay()
+{
+ g_StudioApp.PlaybackPlay();
+}
+
+//==============================================================================
+/**
+ * Handles pressing of the stop button.
+ */
+void CMainFrame::OnPlaybackStop()
+{
+ g_StudioApp.PlaybackStopNoRestore();
+}
+
+//==============================================================================
+/**
+ * Handles pressing the preview button.
+ */
+void CMainFrame::OnPlaybackPreview()
+{
+ if (m_remoteProject->isConnected())
+ CPreviewHelper::OnDeploy(*m_remoteProject);
+ else
+ CPreviewHelper::OnPreview();
+}
+
+//==============================================================================
+/**
+ * Handles the update ui message for the preview button.
+ * Adding more UI updating here would just be redundant.
+ * @param inCmdUI Pointer to the UI element that needs updating
+ */
+void CMainFrame::OnUpdatePlaybackPreview()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the update ui message for the play button. Does nothing because the
+ * button state is being updated manually in OnPlayStart() and OnPlayStop.
+ * Adding more UI updating here would just be redundant.
+ * @param inCmdUI Pointer to the UI element that needs updating
+ */
+void CMainFrame::OnUpdatePlaybackPlay()
+{
+}
+
+//==============================================================================
+/**
+ * Handles pressing the rewind button.
+ */
+void CMainFrame::OnPlaybackRewind()
+{
+ g_StudioApp.PlaybackRewind();
+}
+
+//==============================================================================
+/**
+ * Handles the update ui message for the rewind button. Does nothing because
+ * no additional ui handling is necessary for this button.
+ * @param inCmdUI Pointer to the UI element that needs updating
+ */
+void CMainFrame::OnUpdatePlaybackRewind()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the update ui message for the stop button. Doesn't do anything
+ * because no special ui handling is necessary for the stop button.
+ * @param inCmdUI Pointer to the UI element that needs updating
+ */
+void CMainFrame::OnUpdatePlaybackStop()
+{
+}
+
+//==============================================================================
+/**
+ * Registers all the keys it will need for shortcuts, also telsl children to register theirs
+ * @param inHotKeys the hotkeys to with which to register
+ */
+void CMainFrame::RegisterGlobalKeyboardShortcuts(CHotKeys *inHotKeys)
+{
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnToolMove),
+ 0, Qt::Key_W);
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnToolRotate),
+ 0, Qt::Key_R);
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnToolScale),
+ 0, Qt::Key_E);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnViewBoundingBoxes),
+ Qt::ControlModifier, Qt::Key_B);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnViewPivotPoint),
+ Qt::ControlModifier | Qt::AltModifier, Qt::Key_P);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnEditPresentationPreferences),
+ Qt::ControlModifier, Qt::Key_P);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnOpenMostRecentlyUsedDocument),
+ Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier, Qt::Key_P);
+
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnShowAction),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_A);
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnShowBasic),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_B);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnShowInspector),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_I);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnShowProject),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_P);
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnShowSlide),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_D);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnShowTimeline),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_T);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnViewGuidesRulers),
+ Qt::ControlModifier, Qt::Key_Semicolon);
+ inHotKeys->RegisterKeyEvent(new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnLockGuides),
+ Qt::ControlModifier | Qt::AltModifier, Qt::Key_Semicolon);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ inHotKeys->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::HandleEditViewFillModeKey), 0,
+ Qt::Key_F3);
+ inHotKeys->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::HandleEditCameraZoomExtent), 0, Qt::Key_F);
+#endif
+
+ inHotKeys->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CMainFrame>(this, &CMainFrame::OnPlaybackPreview), 0,
+ Qt::Key_F5);
+
+ m_SceneView->RegisterGlobalKeyboardShortcuts(inHotKeys);
+
+ CTimelineControl *theTimelineControl = GetTimelineControl();
+ if (theTimelineControl)
+ theTimelineControl->RegisterGlobalKeyboardShortcuts(inHotKeys);
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolMove: Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+//==============================================================================
+void CMainFrame::OnUpdateToolMove()
+{
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+
+ // If the current tool mode matches this button
+ // If the button is currently enabled
+ m_ui->actionPosition_Tool->setChecked(theCurrentToolSettings == STUDIO_TOOLMODE_MOVE && m_ui->actionPosition_Tool->isEnabled());
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolRotate: Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+void CMainFrame::OnUpdateToolRotate()
+{
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+
+ // If the current tool mode matches this button
+ // If the button is currently enabled
+ m_ui->actionRotation_Tool->setChecked(theCurrentToolSettings == STUDIO_TOOLMODE_ROTATE && m_ui->actionRotation_Tool->isEnabled());
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolScale: Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+void CMainFrame::OnUpdateToolScale()
+{
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+
+ // If the current tool mode matches this button
+ // If the button is currently enabled
+ m_ui->actionScale_Tool->setChecked(theCurrentToolSettings == STUDIO_TOOLMODE_SCALE && m_ui->actionScale_Tool->isEnabled());
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolScale: Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+void CMainFrame::OnUpdateToolGlobalManipulators()
+{
+ StudioManipulationModes::Enum theMode = g_StudioApp.GetMinpulationMode();
+
+ // If the current tool mode matches this button
+ // If the button is currently enabled
+ m_ui->actionLocal_Global_Manipulators->setChecked(theMode == StudioManipulationModes::Global && m_ui->actionLocal_Global_Manipulators->isEnabled());
+}
+
+//==============================================================================
+/**
+ * OnToolMove: Called when the Move button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CMainFrame::OnToolMove()
+{
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_MOVE);
+}
+
+//==============================================================================
+/**
+ * OnToolRotate: Called when the Rotate button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CMainFrame::OnToolRotate()
+{
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_ROTATE);
+}
+
+//==============================================================================
+/**
+ * OnToolScale: Called when the Scale button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CMainFrame::OnToolScale()
+{
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_SCALE);
+}
+
+void CMainFrame::OnToolGlobalManipulators()
+{
+ if (m_ui->actionLocal_Global_Manipulators->isChecked())
+ g_StudioApp.SetMinpulationMode(StudioManipulationModes::Global);
+ else
+ g_StudioApp.SetMinpulationMode(StudioManipulationModes::Local);
+
+ g_StudioApp.GetRenderer().RequestRender();
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolGroupSelection: Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+void CMainFrame::OnUpdateToolGroupSelection()
+{
+ long theCurrentSelectSettings = g_StudioApp.GetSelectMode();
+
+ // If the current tool mode matches this button
+ // If the button is currently enabled
+ m_ui->actionGroup_Select_Tool->setChecked(theCurrentSelectSettings == STUDIO_SELECTMODE_GROUP && m_ui->actionGroup_Select_Tool->isEnabled());
+}
+
+//==============================================================================
+/**
+ * OnUpdateToolItemSelection: Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * tool mode, and whether or not the button is enabled.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+void CMainFrame::OnUpdateToolItemSelection()
+{
+ long theCurrentSelectSettings = g_StudioApp.GetSelectMode();
+
+ // If the current tool mode matches this button
+ // If the button is currently enabled
+ m_ui->actionItem_Select_Tool->setChecked(theCurrentSelectSettings == STUDIO_SELECTMODE_ENTITY && m_ui->actionItem_Select_Tool->isEnabled());
+}
+
+//==============================================================================
+/**
+ * Called when the edit camera Zoom Extent button is pressed.
+ * Inform the current active edit camera to toggle itself.
+ */
+void CMainFrame::OnEditCameraZoomExtent()
+{
+ if (g_StudioApp.GetRenderer().GetEditCamera() >= 0)
+ g_StudioApp.GetRenderer().EditCameraZoomToFit();
+ else
+ g_StudioApp.SetAuthorZoom(!g_StudioApp.IsAuthorZoom());
+}
+
+//==============================================================================
+/**
+ * Called when the "Zoom Extent" keyboard shortcut is pressed.
+ * Inform the current active edit camera to toggle itself.
+ */
+//==============================================================================
+void CMainFrame::HandleEditCameraZoomExtent()
+{
+ OnEditCameraZoomExtent();
+}
+
+//==============================================================================
+/**
+ * Called when the Pan Edit Camera button is pressed.
+ * Inform the current active edit camera on their tool mode.
+ */
+void CMainFrame::OnEditCameraPan()
+{
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+}
+
+//==============================================================================
+/**
+ * Called when the Rotate Edit Camera button is pressed.
+ * Inform the current active edit camera on their tool mode.
+ */
+void CMainFrame::OnEditCameraRotate()
+{
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+}
+
+//==============================================================================
+/**
+ * Called when the Zoom Edit Camera button is pressed.
+ * Inform the current active edit camera on their tool mode.
+ */
+void CMainFrame::OnEditCameraZoom()
+{
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+}
+
+//==============================================================================
+/**
+ * Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * settings of the current edit camera tool.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+//==============================================================================
+void CMainFrame::OnUpdateCameraZoomExtentAndAuthorZoom()
+{
+ if (m_SceneView == GetActiveView() && !m_SceneView->IsDeploymentView()) {
+ m_ui->actionFit_Selected->setChecked(false);
+ } else {
+ m_ui->actionFit_Selected->setChecked(g_StudioApp.IsAuthorZoom());
+ }
+}
+
+//==============================================================================
+/**
+ * Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * settings of the current edit camera tool.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+//==============================================================================
+void CMainFrame::OnUpdateEditCameraPan()
+{
+ if (m_SceneView == GetActiveView() && !m_SceneView->IsDeploymentView()) {
+ m_ui->actionPan_Tool->setEnabled(true);
+
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ m_ui->actionPan_Tool->setChecked(theCurrentToolSettings == STUDIO_TOOLMODE_CAMERA_PAN);
+ } else {
+ m_ui->actionPan_Tool->setEnabled(false);
+ m_ui->actionPan_Tool->setChecked(false);
+ }
+}
+
+//==============================================================================
+/**
+ * Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * settings of the current edit camera tool.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+//==============================================================================
+void CMainFrame::OnUpdateEditCameraRotate()
+{
+ if (m_SceneView == GetActiveView() && !m_SceneView->IsDeploymentView()
+ && g_StudioApp.GetRenderer().DoesEditCameraSupportRotation(
+ g_StudioApp.GetRenderer().GetEditCamera())) {
+ m_ui->actionOrbit_Tool->setEnabled(true);
+
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ m_ui->actionOrbit_Tool->setChecked(theCurrentToolSettings == STUDIO_TOOLMODE_CAMERA_ROTATE);
+ } else {
+ m_ui->actionOrbit_Tool->setEnabled(false);
+ m_ui->actionOrbit_Tool->setChecked(false);
+ }
+}
+
+//==============================================================================
+/**
+ * Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * settings of the current edit camera tool.
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+//==============================================================================
+void CMainFrame::OnUpdateEditCameraZoom()
+{
+ if (m_SceneView == GetActiveView() && !m_SceneView->IsDeploymentView()) {
+ m_ui->actionZoom_Tool->setEnabled(true);
+
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ m_ui->actionZoom_Tool->setChecked(theCurrentToolSettings == STUDIO_TOOLMODE_CAMERA_ZOOM);
+ } else {
+ m_ui->actionZoom_Tool->setEnabled(false);
+ m_ui->actionZoom_Tool->setChecked(false);
+ }
+}
+
+//==============================================================================
+/**
+ * Called when the "Render geometry as solid/wireframe in edit view" button is pressed.
+ * Toggle the mode and update the studio preferences, also cache it in EditCameraContainer
+ */
+//==============================================================================
+void CMainFrame::HandleEditViewFillModeKey()
+{
+ if (m_SceneView == GetActiveView() && !m_SceneView->IsDeploymentView()) {
+ OnEditViewFillMode();
+ bool theEditViewFillMode = g_StudioApp.GetRenderer().IsEditLightEnabled();
+ m_ui->actionShading_Mode->setChecked(theEditViewFillMode);
+ }
+}
+
+//==============================================================================
+/**
+ * Called when the "Render geometry as solid/wireframe in edit view" button is pressed.
+ * Toggle the mode and update the studio preferences, also cache it in EditCameraContainer
+ */
+//==============================================================================
+void CMainFrame::OnEditViewFillMode()
+{
+ bool theEditViewFillMode = !g_StudioApp.GetRenderer().IsEditLightEnabled();
+ g_StudioApp.GetRenderer().SetEnableEditLight(theEditViewFillMode);
+}
+
+//==============================================================================
+/**
+ * Updates the UI associated with this button.
+ *
+ * Checks or unchecks this button on the toolbar, depending on the current
+ * settings of the "Render geometry as solid/wireframe in edit view".
+ *
+ * @param pCmdUI Pointer to the button that generated the message.
+ */
+//==============================================================================
+void CMainFrame::OnUpdateEditViewFillMode()
+{
+ if (m_SceneView == GetActiveView() && !m_SceneView->IsDeploymentView()) {
+ m_ui->actionShading_Mode->setEnabled(true);
+ m_ui->actionShading_Mode->setChecked(g_StudioApp.GetRenderer().IsEditLightEnabled());
+ } else {
+ m_ui->actionShading_Mode->setEnabled(false);
+ m_ui->actionShading_Mode->setChecked(false);
+ }
+}
+
+void CMainFrame::OnViewGuidesRulers()
+{
+ g_StudioApp.GetRenderer().SetGuidesEnabled(!g_StudioApp.GetRenderer().AreGuidesEnabled());
+ g_StudioApp.GetCore()->GetDispatch()->FireAuthorZoomChanged();
+ m_SceneView->OnRulerGuideToggled();
+}
+
+void CMainFrame::OnUpdateViewGuidesRulers()
+{
+ m_ui->actionRulers_Guides->setEnabled(m_SceneView->IsDeploymentView());
+ m_ui->actionRulers_Guides->setChecked(g_StudioApp.GetRenderer().AreGuidesEnabled());
+}
+
+void CMainFrame::OnClearGuides()
+{
+ g_StudioApp.ClearGuides();
+}
+
+void CMainFrame::OnUpdateClearGuides()
+{
+ bool enable = g_StudioApp.GetRenderer().AreGuidesEnabled()
+ && g_StudioApp.GetRenderer().AreGuidesEditable() && m_SceneView->IsDeploymentView();
+
+ m_ui->actionClear_Guides->setEnabled(enable);
+}
+
+void CMainFrame::OnLockGuides()
+{
+ g_StudioApp.GetRenderer().SetGuidesEditable(!g_StudioApp.GetRenderer().AreGuidesEditable());
+}
+
+void CMainFrame::OnUpdateLockGuides()
+{
+ bool enable = g_StudioApp.GetRenderer().AreGuidesEnabled() && m_SceneView->IsDeploymentView();
+ m_ui->actionLock_Guides->setEnabled(enable);
+ // Set to the inverse of guides editable.
+ m_ui->actionLock_Guides->setChecked(!g_StudioApp.GetRenderer().AreGuidesEditable());
+}
+
+void CMainFrame::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == WM_STUDIO_TIMER)
+ g_StudioApp.GetTickTock().ProcessMessages();
+ QMainWindow::timerEvent(event);
+}
+
+void CMainFrame::OnViewAction()
+{
+ m_PaletteManager->ToggleControl(CPaletteManager::CONTROLTYPE_ACTION);
+ SaveLayout();
+}
+
+void CMainFrame::OnUpdateViewAction()
+{
+ m_ui->actionAction->setChecked(
+ m_PaletteManager->IsControlVisible(CPaletteManager::CONTROLTYPE_ACTION));
+}
+
+void CMainFrame::OnViewBasicObjects()
+{
+ m_PaletteManager->ToggleControl(CPaletteManager::CONTROLTYPE_BASICOBJECTS);
+ SaveLayout();
+}
+
+void CMainFrame::OnUpdateViewBasicObjects()
+{
+ m_ui->actionBasic_Objects->setChecked(m_PaletteManager->IsControlVisible(CPaletteManager::CONTROLTYPE_BASICOBJECTS));
+}
+
+void CMainFrame::OnViewInspector()
+{
+ m_PaletteManager->ToggleControl(CPaletteManager::CONTROLTYPE_INSPECTOR);
+ SaveLayout();
+}
+
+void CMainFrame::OnUpdateViewInspector()
+{
+ m_ui->actionInspector->setChecked(
+ m_PaletteManager->IsControlVisible(CPaletteManager::CONTROLTYPE_INSPECTOR));
+}
+
+void CMainFrame::OnViewProject()
+{
+ m_PaletteManager->ToggleControl(CPaletteManager::CONTROLTYPE_PROJECT);
+ SaveLayout();
+}
+
+void CMainFrame::OnUpdateViewProject()
+{
+ m_ui->actionProject->setChecked(
+ m_PaletteManager->IsControlVisible(CPaletteManager::CONTROLTYPE_PROJECT));
+}
+
+void CMainFrame::OnViewSlide()
+{
+ m_PaletteManager->ToggleControl(CPaletteManager::CONTROLTYPE_SLIDE);
+ SaveLayout();
+}
+
+void CMainFrame::OnUpdateViewSlide()
+{
+ m_ui->actionSlide->setChecked(
+ m_PaletteManager->IsControlVisible(CPaletteManager::CONTROLTYPE_SLIDE) ? TRUE : FALSE);
+}
+
+//==============================================================================
+/**
+ * Called when the View Inspector Palette menu item is chosen.
+ */
+void CMainFrame::OnViewTimeline()
+{
+ m_PaletteManager->ToggleControl(CPaletteManager::CONTROLTYPE_TIMELINE);
+ SaveLayout();
+}
+
+//==============================================================================
+/**
+ * Checks or unchecks the menu item depending on if the view is available or not.
+ * @param pCmdUI Pointer to the UI element that generated the message.
+ */
+void CMainFrame::OnUpdateViewTimeline()
+{
+ m_ui->actionTimeline->setChecked(
+ m_PaletteManager->IsControlVisible(CPaletteManager::CONTROLTYPE_TIMELINE));
+}
+
+//==============================================================================
+/**
+ * Called when the View Inspector Palette menu item is chosen.
+ */
+void CMainFrame::OnViewBoundingBoxes()
+{
+ CStudioPreferences::SetBoundingBoxesOn(!CStudioPreferences::IsBoundingBoxesOn());
+ g_StudioApp.GetRenderer().RequestRender();
+}
+
+//==============================================================================
+/**
+ * Checks or unchecks the menu item depending on if the view is available or not.
+ * @param pCmdUI Pointer to the UI element that generated the message.
+ */
+void CMainFrame::OnUpdateViewBoundingBoxes()
+{
+ m_ui->actionBounding_Boxes->setChecked(CStudioPreferences::IsBoundingBoxesOn());
+}
+
+//==============================================================================
+/**
+ * Called when the View Pivot Point menu item is chosen.
+ */
+void CMainFrame::OnViewPivotPoint()
+{
+ CStudioPreferences::SetDisplayPivotPoint(!CStudioPreferences::ShouldDisplayPivotPoint());
+ g_StudioApp.GetRenderer().RequestRender();
+}
+
+//==============================================================================
+/**
+ * Checks or unchecks the menu item depending on if the view is available or not.
+ * @param pCmdUI Pointer to the UI element that generated the message.
+ */
+void CMainFrame::OnUpdateViewPivotPoint()
+{
+ m_ui->actionPivot_Point->setChecked(CStudioPreferences::ShouldDisplayPivotPoint());
+}
+
+//==============================================================================
+/**
+ * Called when the View Wireframe menu item is chosen.
+ */
+void CMainFrame::OnViewWireframe()
+{
+ CStudioPreferences::SetWireframeModeOn(!CStudioPreferences::IsWireframeModeOn());
+ g_StudioApp.GetRenderer().RequestRender();
+}
+
+//==============================================================================
+/**
+ * Checks or unchecks the menu item depending on if the view is available or not.
+ * @param pCmdUI Pointer to the UI element that generated the message.
+ */
+void CMainFrame::OnUpdateViewWireframe()
+{
+ m_ui->actionWireframe->setChecked(CStudioPreferences::IsWireframeModeOn());
+}
+
+//==============================================================================
+/**
+ * Checks or unchecks the menu item depending whether tooltips should be shown
+ * or not.
+ * @param inCmdUI Pointer to the UI element that generated the message.
+ */
+void CMainFrame::OnUpdateViewTooltips()
+{
+ m_ui->actionTooltips->setChecked(CStudioPreferences::ShouldShowTooltips());
+}
+
+//==============================================================================
+/**
+ * Called when the "View->Tooltips" menu item is chosen. Toggles tooltips on
+ * and off for custom controls.
+ */
+void CMainFrame::OnViewTooltips()
+{
+ CStudioPreferences::SetShowTooltips(!CStudioPreferences::ShouldShowTooltips());
+}
+
+//==============================================================================
+/**
+ * Called when the update message occurs for the Help->Help Topics menu item.
+ * If the help file exists, the menu item is enabled, otherwise it's disabled.
+ * @param inCmdUI UI element that generated the message
+ */
+void CMainFrame::OnUpdateHelpIndex()
+{
+ CUICFile theFile(g_StudioApp.m_pszHelpFilePath);
+ m_ui->action_Reference_Manual->setEnabled(theFile.Exists());
+}
+
+//==============================================================================
+/**
+ * Handles the ID_HELP_INDEX command. Opens the online help for Studio.
+ */
+void CMainFrame::OnHelpIndex()
+{
+ CUICFile theFile(g_StudioApp.m_pszHelpFilePath);
+ if (theFile.Exists())
+ QDesktopServices::openUrl(QUrl::fromLocalFile(theFile.GetAbsolutePath().toQString()));
+}
+
+//==============================================================================
+/**
+ * Handles the ID_HELP_VISIT_QT command. Opens the Qt Web site.
+ */
+void CMainFrame::OnHelpVisitQt()
+{
+ Q3DStudio::CString theWebSite(::LoadResourceString(IDS_HELP_VISIT_QT));
+ QDesktopServices::openUrl(QUrl(theWebSite.toQString()));
+}
+
+//==============================================================================
+/**
+ * Opens the tutorial.
+ */
+void CMainFrame::OnHelpOpenTutorial()
+{
+ StudioTutorialWidget tutorial(false);
+ tutorial.exec();
+}
+
+//==============================================================================
+/**
+ * OnHelpBehaviorReference: Handles the ID_HELP_BEHAVIORREFERENCE message.
+ * Called when the Behavior Reference menu item is chosen inside the Help menu.
+ * Opens the HTML file to display the Behavior help.
+ */
+void CMainFrame::OnHelpBehaviorReference()
+{
+ CUICFile theFile(CUICFile::GetApplicationDirectory(),
+ ::LoadResourceString(IDS_HELP_BEHAVIORREFERENCE));
+ if (theFile.Exists()) {
+ g_StudioApp.GetCore()->GetDispatch()->FireOnNavigate(
+ Q3DStudio::CString::fromQString(theFile.GetURL().path()), true);
+ SaveLayout();
+ }
+}
+
+//==============================================================================
+/**
+ * Handle the file revert menu option.
+ */
+void CMainFrame::OnFileRevert()
+{
+ g_StudioApp.OnRevert();
+}
+
+void CMainFrame::OnFileConnectToDevice()
+{
+ if (m_remoteProject->isConnected())
+ m_remoteProject->disconnect();
+ else
+ m_remoteProject->connect();
+}
+
+//==============================================================================
+/**
+ * Handles the recent list.
+ */
+void CMainFrame::OnFileOpenRecent(int nID)
+{
+ g_StudioApp.OnFileOpenRecent(m_RecentItems->GetItem(nID));
+}
+
+//==============================================================================
+/**
+ * Tells the scene view to recheck its sizing mode and tells client to update
+ */
+void CMainFrame::RecheckSizingMode()
+{
+ m_SceneView->RecheckSizingMode();
+}
+
+//==============================================================================
+/**
+ * Callback when a Core is opened or fails to open.
+ */
+void CMainFrame::OnOpenDocument(const CUICFile &inFilename, bool inSucceeded)
+{
+ if (inSucceeded)
+ m_RecentItems->AddRecentItem(inFilename);
+ else
+ m_RecentItems->RemoveRecentItem(inFilename);
+}
+
+//==============================================================================
+/**
+ * Callback when a Core is saved or fails to save.
+ */
+void CMainFrame::OnSaveDocument(const CUICFile &inFilename, bool inSucceeded, bool inSaveCopy)
+{
+ if (!inSaveCopy)
+ OnOpenDocument(inFilename, inSucceeded);
+}
+
+//==============================================================================
+/**
+ * Callback for when a the doc gets a new path
+ */
+void CMainFrame::OnDocumentPathChanged(const CUICFile &inNewPath)
+{
+ QString theTitle = inNewPath.GetName().toQString();
+ if (theTitle.isEmpty())
+ theTitle = QObject::tr("Untitled");
+
+ theTitle = theTitle + " - " + QObject::tr("Qt 3D Studio");
+
+ // TODO: Move this whole pile to the studio app
+ setWindowTitle(theTitle);
+
+ if (inNewPath.Exists())
+ m_RecentItems->AddRecentItem(inNewPath);
+}
+
+//==============================================================================
+/**
+ * Secret hot-key compatibility with Aftereffects muscle memory
+ */
+void CMainFrame::OnOpenMostRecentlyUsedDocument()
+{
+ CUICFile theDocument = m_RecentItems->GetItem(0);
+ if (theDocument.Exists())
+ g_StudioApp.OnLoadDocument(theDocument);
+}
+
+void CMainFrame::OnShowSlide()
+{
+ m_PaletteManager->ShowControl(CPaletteManager::CONTROLTYPE_SLIDE);
+}
+
+void CMainFrame::OnShowTimeline()
+{
+ m_PaletteManager->ShowControl(CPaletteManager::CONTROLTYPE_TIMELINE);
+}
+
+void CMainFrame::OnShowBasic()
+{
+ m_PaletteManager->ShowControl(CPaletteManager::CONTROLTYPE_BASICOBJECTS);
+}
+
+void CMainFrame::OnShowProject()
+{
+ m_PaletteManager->ShowControl(CPaletteManager::CONTROLTYPE_PROJECT);
+}
+
+void CMainFrame::OnShowAction()
+{
+ m_PaletteManager->ShowControl(CPaletteManager::CONTROLTYPE_ACTION);
+}
+
+void CMainFrame::OnShowInspector()
+{
+ m_PaletteManager->ShowControl(CPaletteManager::CONTROLTYPE_INSPECTOR);
+}
+
+CTimelineControl *CMainFrame::GetTimelineControl()
+{
+ return m_PaletteManager->GetTimelineControl();
+}
+
+ITimelineTimebar *CMainFrame::GetSelectedTimelineTimebar()
+{
+ CUICDMTimelineItemBinding *theTimelineItemBinding =
+ GetTimelineControl()->GetTranslationManager()->GetSelectedBinding();
+ if (theTimelineItemBinding == NULL)
+ return NULL;
+
+ return theTimelineItemBinding->GetTimelineItem()->GetTimebar();
+}
+
+CRecentItems *CMainFrame::GetRecentItems()
+{
+ return m_RecentItems;
+}
+
+QWidget *CMainFrame::GetActiveView()
+{
+ return centralWidget();
+}
+
+bool CMainFrame::eventFilter(QObject *obj, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::KeyPress: {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ if (ke->key() == Qt::Key_Tab) {
+ if (m_PaletteManager->tabNavigateFocusedWidget(true))
+ return true;
+ } else if (ke->key() == Qt::Key_Backtab) {
+ if (m_PaletteManager->tabNavigateFocusedWidget(false))
+ return true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return QMainWindow::eventFilter(obj, event);
+}
diff --git a/src/Authoring/Studio/MainFrm.h b/src/Authoring/Studio/MainFrm.h
new file mode 100644
index 00000000..56373498
--- /dev/null
+++ b/src/Authoring/Studio/MainFrm.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_MAIN_FRAME
+#define INCLUDED_MAIN_FRAME 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PreviewHelper.h"
+#include "DispatchListeners.h"
+
+#include <QMainWindow>
+#include <QTimer>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CHotKeys;
+class CPaletteManager;
+class CPaletteState;
+class CRecentItems;
+class CSceneView;
+class CStudioApp;
+class CTimelineControl;
+class ITimelineTimebar;
+class RemoteProject;
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui
+{
+ class MainFrame;
+}
+QT_END_NAMESPACE
+
+class CMainFrame : public QMainWindow,
+ public CPresentationChangeListener,
+ public CFileOpenListener,
+ public CClientPlayChangeListener
+{
+ Q_OBJECT
+public:
+ CMainFrame();
+ virtual ~CMainFrame();
+
+ void OnNewPresentation() override;
+ void OnClosingPresentation() override;
+
+ // CFileOpenListener
+ void OnOpenDocument(const CUICFile &inFilename, bool inSucceeded) override;
+ void OnSaveDocument(const CUICFile &inFilename, bool inSucceeded, bool inSaveCopy) override;
+ void OnDocumentPathChanged(const CUICFile &inNewPath) override;
+
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+ void RecheckSizingMode();
+
+ void SaveLayout();
+ void RestoreLayout();
+ void SetLayout(const CPaletteState &inState);
+
+ // CClientPlayChangeListener
+ void OnPlayStart() override;
+ void OnPlayStop() override;
+ void OnTimeChanged(long inTime) override;
+
+ CRecentItems *GetRecentItems();
+
+ int OnCreate();
+
+ void onPlaybackTimeout();
+
+ void OnFileOpen();
+ void OnFileSave();
+ void OnUpdateFileSave();
+ void OnFileSaveAs();
+ void OnFileSaveCopy();
+ void OnFileNew();
+ void OnFileRevert();
+ void OnFileConnectToDevice();
+ void OnFileOpenRecent(int nID);
+
+ void OnEditRedo();
+ void OnEditUndo();
+ void OnUpdateEditUndo();
+ void OnUpdateEditRedo();
+ void OnEditCopy();
+ void OnUpdateEditCopy();
+ void OnEditCut();
+ void OnUpdateEditCut();
+ void OnEditPaste();
+ void OnUpdateEditPaste();
+ void OnEditDuplicate();
+ void OnUpdateEditDuplicate();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ afx_msg LRESULT OnMsgRouterMsg(WPARAM inWParam, LPARAM inLParam);
+#endif
+ void timerEvent(QTimerEvent *event) override;
+ void showEvent(QShowEvent *event) override;
+
+ void OnUpdateTimelineSetTimeBarColor();
+ void OnTimelineSetTimeBarColor();
+ void OnTimelineSetChangedKeyframe();
+ void OnTimelineDeleteSelectedKeyframes();
+ void OnUpdateTimelineDeleteSelectedKeyframes();
+ void OnTimelineSetTimeBarText();
+ void OnUpdateTimelineSetTimeBarText();
+ void OnUpdateTimelineSetInterpolation();
+ void OnTimelineSetInterpolation();
+ void closeEvent(QCloseEvent *event) override;
+ void OnToolAutosetkeys();
+ void OnUpdateToolAutosetkeys();
+ void OnEditApplicationPreferences();
+ void OnEditPresentationPreferences();
+ void OnEditSubPresentations();
+ void OnPlaybackPlay();
+ void OnUpdatePlaybackPlay();
+ void OnPlaybackRewind();
+ void OnUpdatePlaybackRewind();
+ void OnPlaybackStop();
+ void OnUpdatePlaybackStop();
+ void OnPlaybackPreview();
+ void OnUpdatePlaybackPreview();
+ void OnUpdateToolMove();
+ void OnUpdateToolRotate();
+ void OnUpdateToolScale();
+ void OnUpdateToolGlobalManipulators();
+ void OnToolMove();
+ void OnToolRotate();
+ void OnToolScale();
+ void OnToolGlobalManipulators();
+ void OnUpdateToolChange();
+ void OnUpdateToolGroupSelection();
+ void OnUpdateToolItemSelection();
+
+ void OnViewBoundingBoxes();
+ void OnUpdateViewBoundingBoxes();
+ void OnViewPivotPoint();
+ void OnUpdateViewPivotPoint();
+ void OnViewWireframe();
+ void OnUpdateViewWireframe();
+ void OnViewHelpPalette();
+ void OnUpdateViewHelpPalette();
+ void OnUpdateViewTooltips();
+ void OnViewTooltips();
+ void OnUpdateHelpIndex();
+ void OnHelpIndex();
+ void OnHelpVisitQt();
+ void OnHelpOpenTutorial();
+ void OnHelpBehaviorReference();
+ void OnOpenMostRecentlyUsedDocument();
+
+ void OnViewAction();
+ void OnUpdateViewAction();
+ void OnViewBasicObjects();
+ void OnUpdateViewBasicObjects();
+ void OnViewInspector();
+ void OnUpdateViewInspector();
+ void OnViewProject();
+ void OnUpdateViewProject();
+ void OnViewSlide();
+ void OnUpdateViewSlide();
+ void OnViewTimeline();
+ void OnUpdateViewTimeline();
+
+ void OnEditCameraZoomExtent();
+ void OnEditCameraPan();
+ void OnEditCameraRotate();
+ void OnEditCameraZoom();
+ void OnUpdateCameraZoomExtentAndAuthorZoom();
+ void OnUpdateEditCameraPan();
+ void OnUpdateEditCameraRotate();
+ void OnUpdateEditCameraZoom();
+ void OnEditViewFillMode();
+ void OnUpdateEditViewFillMode();
+
+ void OnViewGuidesRulers();
+ void OnUpdateViewGuidesRulers();
+ void OnClearGuides();
+ void OnUpdateClearGuides();
+ void OnLockGuides();
+ void OnUpdateLockGuides();
+
+ void OnShowSlide();
+ void OnShowTimeline();
+ void OnShowBasic();
+ void OnShowProject();
+ void OnShowAction();
+ void OnShowInspector();
+
+ CTimelineControl *GetTimelineControl();
+ ITimelineTimebar *GetSelectedTimelineTimebar();
+
+ void EditPreferences(short inPageIndex);
+
+ void HandleEditViewFillModeKey();
+ void HandleEditCameraZoomExtent();
+
+ QWidget *GetActiveView();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+ RemoteProject *m_remoteProject = nullptr;
+ CSceneView *m_SceneView = nullptr;
+ CRecentItems *m_RecentItems = nullptr;
+ CPaletteManager *m_PaletteManager = nullptr;
+ bool m_PlaybackFlag = false;
+
+ QScopedPointer<Ui::MainFrame> m_ui;
+ QTimer m_playbackTimer;
+};
+
+#endif // INCLUDED_MAIN_FRAME
diff --git a/src/Authoring/Studio/MainFrm.qrc b/src/Authoring/Studio/MainFrm.qrc
new file mode 100644
index 00000000..cb91ad47
--- /dev/null
+++ b/src/Authoring/Studio/MainFrm.qrc
@@ -0,0 +1,83 @@
+<RCC>
+ <qresource prefix="/">
+ <file>res/prefstab-00.png</file>
+ <file>res/prefstab-01.png</file>
+ <file>res/client_tools_hi_color-00.png</file>
+ <file>res/client_tools_hi_color-01.png</file>
+ <file>res/client_tools_hi_color-02.png</file>
+ <file>res/client_tools_hi_color-03.png</file>
+ <file>res/client_tools_hi_color-04.png</file>
+ <file>res/client_tools_hi_color-05.png</file>
+ <file>res/client_tools_hi_color-06.png</file>
+ <file>res/editcamera_tools_hi-00.png</file>
+ <file>res/editcamera_tools_hi-01.png</file>
+ <file>res/editcamera_tools_hi-02.png</file>
+ <file>res/editcamera_tools_hi-03.png</file>
+ <file>res/editcamera_tools_hi-04.png</file>
+ <file>res/editcamera_tools_hi-05.png</file>
+ <file>res/playback_tools_low-00.png</file>
+ <file>res/playback_tools_low-01.png</file>
+ <file>res/playback_tools_low-02.png</file>
+ <file>res/playback_tools_low-03.png</file>
+ <file>res/Toolbar-00.png</file>
+ <file>res/Toolbar-01.png</file>
+ <file>res/Toolbar-02.png</file>
+ <file>res/Toolbar-03.png</file>
+ <file>res/Toolbar-04.png</file>
+ <file>res/Toolbar-05.png</file>
+ <file>res/Toolbar-06.png</file>
+ <file>res/Toolbar-07.png</file>
+ <file>res/About Icon.bmp</file>
+ <file>res/Studio.png</file>
+ <file>style.qss</file>
+ <file>res/separator.png</file>
+ <file>res/editcamera_tools_hi-00_disabled.png</file>
+ <file>res/editcamera_tools_hi-01_disabled.png</file>
+ <file>res/editcamera_tools_hi-02_disabled.png</file>
+ <file>res/editcamera_tools_hi-03_disabled.png</file>
+ <file>res/editcamera_tools_hi-04_disabled.png</file>
+ <file>res/editcamera_tools_hi-05_disabled.png</file>
+ <file>res/editcamera_tools_hi-00@2x.png</file>
+ <file>res/editcamera_tools_hi-00_disabled@2x.png</file>
+ <file>res/editcamera_tools_hi-01@2x.png</file>
+ <file>res/editcamera_tools_hi-01_disabled@2x.png</file>
+ <file>res/editcamera_tools_hi-02@2x.png</file>
+ <file>res/editcamera_tools_hi-02_disabled@2x.png</file>
+ <file>res/editcamera_tools_hi-03@2x.png</file>
+ <file>res/editcamera_tools_hi-03_disabled@2x.png</file>
+ <file>res/editcamera_tools_hi-04@2x.png</file>
+ <file>res/editcamera_tools_hi-04_disabled@2x.png</file>
+ <file>res/editcamera_tools_hi-05@2x.png</file>
+ <file>res/editcamera_tools_hi-05_disabled@2x.png</file>
+ <file>res/playback_tools_low-00@2x.png</file>
+ <file>res/playback_tools_low-01@2x.png</file>
+ <file>res/playback_tools_low-02@2x.png</file>
+ <file>res/prefstab-01@2x.png</file>
+ <file>res/separator@2x.png</file>
+ <file>res/client_tools_hi_color-00@2x.png</file>
+ <file>res/client_tools_hi_color-01@2x.png</file>
+ <file>res/client_tools_hi_color-02@2x.png</file>
+ <file>res/client_tools_hi_color-03@2x.png</file>
+ <file>res/client_tools_hi_color-04@2x.png</file>
+ <file>res/client_tools_hi_color-05@2x.png</file>
+ <file>res/client_tools_hi_color-06@2x.png</file>
+ <file>res/prefstab-00@2x.png</file>
+ <file>res/arrow_down.png</file>
+ <file>res/arrow_down@2x.png</file>
+ <file>res/playback_tools_low-03@2x.png</file>
+ </qresource>
+ <qresource prefix="/startup">
+ <file alias="open_dialog.png">res/open_dialog.png</file>
+ </qresource>
+ <qresource prefix="/cursors">
+ <file alias="edit_camera_rot.png">res/edit_camera_rot.png</file>
+ <file alias="edit_camera_pan.png">res/edit_camera_pan.png</file>
+ <file alias="edit_camera_zoom.png">res/edit_camera_zoom.png</file>
+ <file alias="group_move.png">res/group_move.png</file>
+ <file alias="group_rotate.png">res/group_rotate.png</file>
+ <file alias="group_scale.png">res/group_scale.png</file>
+ <file alias="item_move.png">res/item_move.png</file>
+ <file alias="item_rotate.png">res/item_rotate.png</file>
+ <file alias="item_scale.png">res/item_scale.png</file>
+ </qresource>
+</RCC>
diff --git a/src/Authoring/Studio/MainFrm.ui b/src/Authoring/Studio/MainFrm.ui
new file mode 100644
index 00000000..3f626236
--- /dev/null
+++ b/src/Authoring/Studio/MainFrm.ui
@@ -0,0 +1,799 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainFrame</class>
+ <widget class="QMainWindow" name="MainFrame">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>973</width>
+ <height>617</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qt 3D Studio</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Studio.png</normaloff>:/res/Studio.png</iconset>
+ </property>
+ <widget class="QWidget" name="centralwidget"/>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>973</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menu_File">
+ <property name="title">
+ <string>&amp;File</string>
+ </property>
+ <widget class="QMenu" name="menuRecent_Projects">
+ <property name="title">
+ <string>Recent Projects</string>
+ </property>
+ <addaction name="actionSomething"/>
+ </widget>
+ <addaction name="action_New"/>
+ <addaction name="action_Open"/>
+ <addaction name="action_Save"/>
+ <addaction name="actionSave_As"/>
+ <addaction name="actionSave_a_Copy"/>
+ <addaction name="action_Revert"/>
+ <addaction name="action_Connect_to_Device"/>
+ <addaction name="separator"/>
+ <addaction name="menuRecent_Projects"/>
+ <addaction name="separator"/>
+ <addaction name="action_Exit"/>
+ </widget>
+ <widget class="QMenu" name="menu_Edit">
+ <property name="title">
+ <string>&amp;Edit</string>
+ </property>
+ <addaction name="action_Undo"/>
+ <addaction name="action_Redo"/>
+ <addaction name="separator"/>
+ <addaction name="action_Cut"/>
+ <addaction name="action_Copy"/>
+ <addaction name="action_Paste"/>
+ <addaction name="action_Duplicate_Object"/>
+ <addaction name="separator"/>
+ <addaction name="actionStudio_Preferences"/>
+ <addaction name="actionPresentation_Settings"/>
+ <addaction name="actionSubpresentations"/>
+ </widget>
+ <widget class="QMenu" name="menu_View">
+ <property name="title">
+ <string>&amp;View</string>
+ </property>
+ <addaction name="actionAction"/>
+ <addaction name="actionBasic_Objects"/>
+ <addaction name="actionInspector"/>
+ <addaction name="actionProject"/>
+ <addaction name="actionSlide"/>
+ <addaction name="actionTimeline"/>
+ <addaction name="separator"/>
+ <addaction name="actionBounding_Boxes"/>
+ <addaction name="actionPivot_Point"/>
+ <addaction name="actionWireframe"/>
+ <addaction name="actionTooltips"/>
+ <addaction name="actionRulers_Guides"/>
+ <addaction name="actionLock_Guides"/>
+ <addaction name="actionClear_Guides"/>
+ </widget>
+ <widget class="QMenu" name="menu_Timeline">
+ <property name="title">
+ <string>&amp;Timeline</string>
+ </property>
+ <addaction name="actionSet_Changed_Keyframes"/>
+ <addaction name="actionDelete_Selected_Keyframe_s"/>
+ <addaction name="actionSet_Interpolation"/>
+ <addaction name="actionChange_Time_Bar_Color"/>
+ <addaction name="separator"/>
+ <addaction name="actionAutoset_Keyframes"/>
+ </widget>
+ <widget class="QMenu" name="menu_Help">
+ <property name="title">
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="action_Reference_Manual"/>
+ <addaction name="action_Visit_Qt_Web_Site"/>
+ <addaction name="action_About_Qt_3D_Studio"/>
+ <addaction name="action_Open_Tutorial"/>
+ </widget>
+ <addaction name="menu_File"/>
+ <addaction name="menu_Edit"/>
+ <addaction name="menu_View"/>
+ <addaction name="menu_Timeline"/>
+ <addaction name="menu_Help"/>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ <widget class="QToolBar" name="toolBar">
+ <property name="windowTitle">
+ <string>Tool Bar</string>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>15</height>
+ </size>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="action_New"/>
+ <addaction name="action_Open"/>
+ <addaction name="action_Save"/>
+ <addaction name="separator"/>
+ <addaction name="action_Cut"/>
+ <addaction name="action_Copy"/>
+ <addaction name="action_Paste"/>
+ <addaction name="separator"/>
+ <addaction name="action_Undo"/>
+ <addaction name="action_Redo"/>
+ </widget>
+ <widget class="QToolBar" name="m_ClientToolsBar">
+ <property name="windowTitle">
+ <string>Client Tools</string>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>true</bool>
+ </attribute>
+ <addaction name="actionGroup_Select_Tool"/>
+ <addaction name="actionItem_Select_Tool"/>
+ <addaction name="separator"/>
+ <addaction name="actionPosition_Tool"/>
+ <addaction name="actionScale_Tool"/>
+ <addaction name="actionRotation_Tool"/>
+ <addaction name="actionLocal_Global_Manipulators"/>
+ <addaction name="separator"/>
+ <addaction name="actionAutoset_Keyframes"/>
+ </widget>
+ <widget class="CEditCameraBar" name="m_EditCamerasBar">
+ <property name="windowTitle">
+ <string>Edit Cameras</string>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="separator"/>
+ <addaction name="actionFit_Selected"/>
+ <addaction name="actionPan_Tool"/>
+ <addaction name="actionZoom_Tool"/>
+ <addaction name="actionOrbit_Tool"/>
+ <addaction name="separator"/>
+ <addaction name="actionShading_Mode"/>
+ <addaction name="actionWireframe"/>
+ </widget>
+ <widget class="QToolBar" name="m_PlaybackToolbar">
+ <property name="windowTitle">
+ <string>Playback</string>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="actionRewind"/>
+ <addaction name="actionStop"/>
+ <addaction name="actionPlay"/>
+ <addaction name="separator"/>
+ <addaction name="actionPreview"/>
+ </widget>
+ <action name="action_Reference_Manual">
+ <property name="text">
+ <string>&amp;Reference Manual...</string>
+ </property>
+ </action>
+ <action name="action_Visit_Qt_Web_Site">
+ <property name="text">
+ <string>&amp;Visit Qt Web site...</string>
+ </property>
+ </action>
+ <action name="action_About_Qt_3D_Studio">
+ <property name="text">
+ <string>&amp;About Qt 3D Studio...</string>
+ </property>
+ </action>
+ <action name="action_Open_Tutorial">
+ <property name="text">
+ <string>&amp;Open Tutorial...</string>
+ </property>
+ </action>
+ <action name="actionSet_Changed_Keyframes">
+ <property name="text">
+ <string>Set Changed Keyframes</string>
+ </property>
+ <property name="shortcut">
+ <string>F6</string>
+ </property>
+ </action>
+ <action name="actionDelete_Selected_Keyframe_s">
+ <property name="text">
+ <string>Delete Selected Keyframe(s)</string>
+ </property>
+ </action>
+ <action name="actionSet_Interpolation">
+ <property name="text">
+ <string>Set Interpolation...</string>
+ </property>
+ </action>
+ <action name="actionChange_Time_Bar_Color">
+ <property name="text">
+ <string>Change Time Bar Color...</string>
+ </property>
+ </action>
+ <action name="actionAutoset_Keyframes">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-06.png</normaloff>:/res/client_tools_hi_color-06.png</iconset>
+ </property>
+ <property name="text">
+ <string>Autoset Keyframes</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle autoset keyframes</string>
+ </property>
+ </action>
+ <action name="actionAction">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Action</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+A</string>
+ </property>
+ </action>
+ <action name="actionBasic_Objects">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Basic Objects</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+B</string>
+ </property>
+ </action>
+ <action name="actionInspector">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Inspector</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+I</string>
+ </property>
+ </action>
+ <action name="actionProject">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Project</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+P</string>
+ </property>
+ </action>
+ <action name="actionSlide">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Slide</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+D</string>
+ </property>
+ </action>
+ <action name="actionTimeline">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Timeline</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+T</string>
+ </property>
+ </action>
+ <action name="actionBounding_Boxes">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Bounding Boxes</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+B</string>
+ </property>
+ </action>
+ <action name="actionPivot_Point">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Pivot Point</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Alt+P</string>
+ </property>
+ </action>
+ <action name="actionWireframe">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/editcamera_tools_hi-05.png</normaloff>
+ <disabledoff>:/res/editcamera_tools_hi-05_disabled.png</disabledoff>:/res/editcamera_tools_hi-05.png</iconset>
+ </property>
+ <property name="text">
+ <string>Wireframe</string>
+ </property>
+ <property name="toolTip">
+ <string>Show or Hide Wireframe</string>
+ </property>
+ </action>
+ <action name="actionTooltips">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Tooltips</string>
+ </property>
+ </action>
+ <action name="actionRulers_Guides">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Rulers &amp;&amp; Guides</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+;</string>
+ </property>
+ </action>
+ <action name="actionLock_Guides">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Lock Guides</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Alt+;</string>
+ </property>
+ </action>
+ <action name="actionClear_Guides">
+ <property name="text">
+ <string>Clear Guides</string>
+ </property>
+ </action>
+ <action name="action_Undo">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-06.png</normaloff>:/res/Toolbar-06.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Undo</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Z</string>
+ </property>
+ </action>
+ <action name="action_Redo">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-07.png</normaloff>:/res/Toolbar-07.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Redo</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Y</string>
+ </property>
+ </action>
+ <action name="action_Cut">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-03.png</normaloff>:/res/Toolbar-03.png</iconset>
+ </property>
+ <property name="text">
+ <string>Cu&amp;t</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+X</string>
+ </property>
+ </action>
+ <action name="action_Copy">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-04.png</normaloff>:/res/Toolbar-04.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Copy</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+C</string>
+ </property>
+ </action>
+ <action name="action_Paste">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-05.png</normaloff>:/res/Toolbar-05.png</iconset>
+ </property>
+ <property name="text">
+ <string>P&amp;aste</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+V</string>
+ </property>
+ </action>
+ <action name="action_Duplicate_Object">
+ <property name="text">
+ <string>&amp;Duplicate Object</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="actionStudio_Preferences">
+ <property name="text">
+ <string>Studio &amp;Preferences...</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::PreferencesRole</enum>
+ </property>
+ </action>
+ <action name="actionPresentation_Settings">
+ <property name="text">
+ <string>Presentation &amp;Settings...</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+P</string>
+ </property>
+ </action>
+ <action name="action_New">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-00.png</normaloff>:/res/Toolbar-00.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;New</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <action name="action_Open">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-01.png</normaloff>:/res/Toolbar-01.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Open</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="action_Save">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/Toolbar-02.png</normaloff>:/res/Toolbar-02.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Save</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+S</string>
+ </property>
+ </action>
+ <action name="actionSave_As">
+ <property name="text">
+ <string>Save &amp;As...</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+S</string>
+ </property>
+ </action>
+ <action name="actionSave_a_Copy">
+ <property name="text">
+ <string>Save a Copy...</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Alt+S</string>
+ </property>
+ </action>
+ <action name="action_Revert">
+ <property name="text">
+ <string>&amp;Revert...</string>
+ </property>
+ </action>
+ <action name="action_Connect_to_Device">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Connect to Device</string>
+ </property>
+ </action>
+ <action name="action_Exit">
+ <property name="text">
+ <string>E&amp;xit</string>
+ </property>
+ </action>
+ <action name="actionSomething">
+ <property name="text">
+ <string>Something</string>
+ </property>
+ </action>
+ <action name="actionGroup_Select_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-00.png</normaloff>:/res/client_tools_hi_color-00.png</iconset>
+ </property>
+ <property name="text">
+ <string>Group Select Tool</string>
+ </property>
+ <property name="toolTip">
+ <string>Group Select</string>
+ </property>
+ </action>
+ <action name="actionItem_Select_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-01.png</normaloff>:/res/client_tools_hi_color-01.png</iconset>
+ </property>
+ <property name="text">
+ <string>Item Select Tool</string>
+ </property>
+ <property name="toolTip">
+ <string>Select Item</string>
+ </property>
+ </action>
+ <action name="actionRotation_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-04.png</normaloff>:/res/client_tools_hi_color-04.png</iconset>
+ </property>
+ <property name="text">
+ <string>Rotation Tool</string>
+ </property>
+ <property name="toolTip">
+ <string>Rotate current selection</string>
+ </property>
+ </action>
+ <action name="actionPosition_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-02.png</normaloff>:/res/client_tools_hi_color-02.png</iconset>
+ </property>
+ <property name="text">
+ <string>Position Tool</string>
+ </property>
+ <property name="toolTip">
+ <string>Move current selection</string>
+ </property>
+ </action>
+ <action name="actionScale_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-03.png</normaloff>:/res/client_tools_hi_color-03.png</iconset>
+ </property>
+ <property name="text">
+ <string>Scale Tool</string>
+ </property>
+ <property name="toolTip">
+ <string>Scale current selection</string>
+ </property>
+ </action>
+ <action name="actionLocal_Global_Manipulators">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/client_tools_hi_color-05.png</normaloff>:/res/client_tools_hi_color-05.png</iconset>
+ </property>
+ <property name="text">
+ <string>Local/Global Manipulators</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle Manipulators to work in global/local space</string>
+ </property>
+ </action>
+ <action name="actionFit_Selected">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/editcamera_tools_hi-00.png</normaloff>
+ <disabledoff>:/res/editcamera_tools_hi-00_disabled.png</disabledoff>:/res/editcamera_tools_hi-00.png</iconset>
+ </property>
+ <property name="text">
+ <string>Fit Selected (F)</string>
+ </property>
+ <property name="toolTip">
+ <string>Fit Selected</string>
+ </property>
+ </action>
+ <action name="actionPan_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/editcamera_tools_hi-01.png</normaloff>
+ <disabledoff>:/res/editcamera_tools_hi-01_disabled.png</disabledoff>:/res/editcamera_tools_hi-01.png</iconset>
+ </property>
+ <property name="text">
+ <string>Pan Tool (Middle Mouse Drag)</string>
+ </property>
+ <property name="toolTip">
+ <string>Pan current edit camera</string>
+ </property>
+ </action>
+ <action name="actionZoom_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/editcamera_tools_hi-02.png</normaloff>
+ <disabledoff>:/res/editcamera_tools_hi-02_disabled.png</disabledoff>:/res/editcamera_tools_hi-02.png</iconset>
+ </property>
+ <property name="text">
+ <string>Zoom Tool (Mouse Wheel)</string>
+ </property>
+ <property name="toolTip">
+ <string>Zoom current edit camera</string>
+ </property>
+ </action>
+ <action name="actionOrbit_Tool">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/editcamera_tools_hi-03.png</normaloff>
+ <disabledoff>:/res/editcamera_tools_hi-03_disabled.png</disabledoff>:/res/editcamera_tools_hi-03.png</iconset>
+ </property>
+ <property name="text">
+ <string>Orbit Tool (Alt+Middle Mouse Drag)</string>
+ </property>
+ <property name="toolTip">
+ <string>Orbit current edit camera</string>
+ </property>
+ </action>
+ <action name="actionShading_Mode">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/editcamera_tools_hi-04.png</normaloff>
+ <disabledoff>:/res/editcamera_tools_hi-04_disabled.png</disabledoff>:/res/editcamera_tools_hi-04.png</iconset>
+ </property>
+ <property name="text">
+ <string>Shading Mode (F3)</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle Shading Mode</string>
+ </property>
+ <property name="shortcut">
+ <string>F3</string>
+ </property>
+ </action>
+ <action name="actionRewind">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/playback_tools_low-00.png</normaloff>:/res/playback_tools_low-00.png</iconset>
+ </property>
+ <property name="text">
+ <string>Rewind</string>
+ </property>
+ </action>
+ <action name="actionStop">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/playback_tools_low-01.png</normaloff>:/res/playback_tools_low-01.png</iconset>
+ </property>
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </action>
+ <action name="actionPlay">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/playback_tools_low-02.png</normaloff>:/res/playback_tools_low-02.png</iconset>
+ </property>
+ <property name="text">
+ <string>Play</string>
+ </property>
+ </action>
+ <action name="actionPreview">
+ <property name="icon">
+ <iconset resource="MainFrm.qrc">
+ <normaloff>:/res/playback_tools_low-03.png</normaloff>:/res/playback_tools_low-03.png</iconset>
+ </property>
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </action>
+ <action name="actionSubpresentations">
+ <property name="text">
+ <string>Sub-presentations...</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CEditCameraBar</class>
+ <extends>QToolBar</extends>
+ <header>Studio/_Win/UI/EditCameraBar.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="MainFrm.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/Palettes/Action/ActionContextMenu.cpp b/src/Authoring/Studio/Palettes/Action/ActionContextMenu.cpp
new file mode 100644
index 00000000..d2957e8b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionContextMenu.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ActionContextMenu.h"
+#include "StudioClipboard.h"
+
+//==============================================================================
+/**
+ * Constructor
+ *
+ * @param inActionControl Owner Action Control (commonly known as the Action Palette)
+ *that will handle all cut/copy/paste/delete of Actions.
+ */
+CActionContextMenu::CActionContextMenu(QWidget *parent)
+ : QMenu(parent)
+{
+ QAction *action = new QAction(tr("Copy Action"));
+ connect(action, &QAction::triggered, this, &CActionContextMenu::copyAction);
+ addAction(action);
+
+ action = new QAction(tr("Paste Action"));
+ action->setEnabled(CStudioClipboard::CanPasteAction());
+ connect(action, &QAction::triggered, this, &CActionContextMenu::pasteAction);
+ addAction(action);
+
+ action = new QAction(tr("Cut Action"));
+ connect(action, &QAction::triggered, this, &CActionContextMenu::cutAction);
+ addAction(action);
+
+ action = new QAction(tr("Delete Action"));
+ connect(action, &QAction::triggered, this, &CActionContextMenu::deleteAction);
+ addAction(action);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CActionContextMenu::~CActionContextMenu()
+{
+}
diff --git a/src/Authoring/Studio/Palettes/Action/ActionContextMenu.h b/src/Authoring/Studio/Palettes/Action/ActionContextMenu.h
new file mode 100644
index 00000000..f413232d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionContextMenu.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2005 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_ACTION_CONTEXT_MENU_H
+#define INCLUDED_ACTION_CONTEXT_MENU_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <QMenu>
+
+//==============================================================================
+/**
+ * Context menu that springs up on right mouseclick in the Action Palette.
+ */
+class CActionContextMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ explicit CActionContextMenu(QWidget *parent = nullptr);
+ virtual ~CActionContextMenu();
+
+Q_SIGNALS:
+ void cutAction();
+ void copyAction();
+ void pasteAction();
+ void deleteAction();
+};
+#endif // INCLUDED_ACTION_CONTEXT_MENU_H
diff --git a/src/Authoring/Studio/Palettes/Action/ActionModel.cpp b/src/Authoring/Studio/Palettes/Action/ActionModel.cpp
new file mode 100644
index 00000000..249aa636
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionModel.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ActionModel.h"
+
+#include "stdafx.h"
+#include "ClientDataModelBridge.h"
+#include "CmdDataModelActionSetValue.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "UICDMActionSystem.h"
+#include "UICDMStudioSystem.h"
+
+ActionModel::ActionModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+void ActionModel::setInstanceHandle(const UICDM::CUICDMInstanceHandle &handle)
+{
+ beginResetModel();
+ m_handle = handle;
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ m_actions.clear();
+ doc->GetStudioSystem()->GetActionSystem()->GetActions(doc->GetActiveSlide(),
+ handle, m_actions);
+
+ endResetModel();
+}
+
+QHash<int, QByteArray> ActionModel::roleNames() const
+{
+ auto names = QAbstractItemModel::roleNames();
+ names.insert(DescriptionRole, "description");
+ names.insert(VisibleRole, "visible");
+
+ return names;
+}
+
+
+int ActionModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_actions.size();
+}
+
+QVariant ActionModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ return {};
+
+ const auto action = m_actions.at(index.row());
+ switch (role)
+ {
+ case DescriptionRole:
+ return actionString(action);
+ case VisibleRole:
+ return actionSystem()->GetActionEyeballValue(activeSlide(), action);
+ default:
+ return {};
+ }
+
+ return {};
+}
+
+bool ActionModel::setData(const QModelIndex &index, const QVariant &data, int role)
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ return false;
+
+ const auto action = m_actions.at(index.row());
+
+ if (role == VisibleRole) {
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ CCmd *theCmd = new CCmdDataModelActionSetEyeball(doc, activeSlide(), action, data.toBool());
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ Q_EMIT dataChanged(index, index, {VisibleRole});
+ }
+
+
+ return false;
+}
+
+void ActionModel::addAction(const CUICDMActionHandle &action)
+{
+ if (std::find(m_actions.begin(), m_actions.end(), action) == m_actions.end()) {
+ const auto count = rowCount();
+ beginInsertRows({}, count, count);
+ m_actions.push_back(action);
+ endInsertRows();
+ }
+}
+
+void ActionModel::removeAction(const CUICDMActionHandle &action)
+{
+ // KDAB_FIXME use beginRemoveRows
+ beginResetModel();
+ m_actions.erase(std::remove(m_actions.begin(), m_actions.end(), action), m_actions.end());
+ endResetModel();
+}
+
+void ActionModel::updateAction(const CUICDMActionHandle &action)
+{
+ for (unsigned i = 0; i < m_actions.size(); i++) {
+ if (m_actions[i] == action) {
+ auto idx = index(i, 0);
+ Q_EMIT dataChanged(idx, idx, {});
+ }
+ }
+}
+
+const CUICDMActionHandle ActionModel::actionAt(int row)
+{
+ if (row >= 0 && static_cast<unsigned>(row) < m_actions.size())
+ return m_actions[row];
+
+ return {};
+}
+
+const SActionInfo ActionModel::actionInfoAt(int row)
+{
+ const auto action = actionAt(row);
+ if (!action.Valid())
+ return {};
+ auto actionCore = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetActionCore();
+ return actionCore->GetActionInfo(action);
+}
+
+UICDM::IActionSystem *ActionModel::actionSystem() const
+{
+ return g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetActionSystem();
+}
+
+UICDM::CUICDMSlideHandle ActionModel::activeSlide() const
+{
+ return g_StudioApp.GetCore()->GetDoc()->GetActiveSlide();
+}
+
+QString ActionModel::actionString(const CUICDMActionHandle &action) const
+{
+ QString result;
+ if (action.Valid()) {
+ auto core = g_StudioApp.GetCore();
+ auto doc = core->GetDoc();
+ auto actionCore = doc->GetStudioSystem()->GetActionCore();
+ auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+
+ const SActionInfo &actionInfo = actionCore->GetActionInfo(action);
+
+ // Query the event name
+ QString eventFormalName(tr("[Unknown Event]"));
+ CUICDMEventHandle eventHandle = bridge->ResolveEvent(actionInfo);
+ if (eventHandle.Valid())
+ eventFormalName =
+ QString::fromWCharArray(bridge->GetEventInfo(eventHandle).m_FormalName.wide_str());
+
+ // Query the asset name
+ QString assetName = tr("[Unknown]");
+ assetName = bridge->GetName(actionInfo.m_Owner).toQString();
+
+ const auto sourceInstance =
+ bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TriggerObject);
+ const auto targetInstance =
+ bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+ QString sourceName = sourceInstance.Valid()
+ ? bridge->GetName(sourceInstance).toQString()
+ : tr("[Unknown Source]");
+ QString targetName = targetInstance.Valid()
+ ? bridge->GetName(targetInstance).toQString()
+ : tr("[Unknown Target]");
+
+ // Query the action name
+ QString handlerFormalName(tr("[Unknown Handler]"));
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+ if (handlerHandle.Valid())
+ handlerFormalName = QString::fromWCharArray(bridge->GetHandlerInfo(handlerHandle).m_FormalName.wide_str());
+
+ // Format the strings
+ if (actionInfo.m_Owner == sourceInstance) {
+ if (sourceInstance == targetInstance) {
+ result = tr("Listen for '%1', '%2'").arg(eventFormalName, handlerFormalName);
+ } else {
+ result = tr("Listen for '%1', tell %2 to '%3'").arg(eventFormalName, targetName,
+ handlerFormalName);
+ }
+ } else if (actionInfo.m_Owner == targetInstance) {
+ result = tr("Listen to '%1' for '%2', '%3'").arg(sourceName, eventFormalName,
+ handlerFormalName);
+ } else {
+ result = tr("Listen to '%1' for '%2', tell %3 to '%4'").arg(sourceName,
+ eventFormalName,
+ targetName,
+ handlerFormalName);
+ }
+ }
+ return result;
+}
diff --git a/src/Authoring/Studio/Palettes/Action/ActionModel.h b/src/Authoring/Studio/Palettes/Action/ActionModel.h
new file mode 100644
index 00000000..89a4586d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionModel.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIONMODEL_H
+#define ACTIONMODEL_H
+
+#include <QAbstractListModel>
+
+#include "UICDMActionInfo.h"
+#include "UICDMHandles.h"
+
+namespace UICDM {
+ class IActionSystem;
+}
+
+class ActionModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit ActionModel(QObject *parent = nullptr);
+
+ void setInstanceHandle(const UICDM::CUICDMInstanceHandle &handle);
+
+ enum Roles {
+ DescriptionRole = Qt::DisplayRole,
+ VisibleRole = Qt::UserRole + 1,
+
+ };
+
+ QHash<int, QByteArray> roleNames() const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &data, int role = Qt::EditRole) override;
+
+ void addAction(const UICDM::CUICDMActionHandle &action);
+ void removeAction(const UICDM::CUICDMActionHandle &action);
+ void updateAction(const UICDM::CUICDMActionHandle &action);
+ const UICDM::CUICDMActionHandle actionAt(int row);
+ const UICDM::SActionInfo actionInfoAt(int row);
+
+private:
+ UICDM::IActionSystem *actionSystem() const;
+ UICDM::CUICDMSlideHandle activeSlide() const;
+ QString actionString(const UICDM::CUICDMActionHandle &action) const;
+
+ UICDM::CUICDMInstanceHandle m_handle;
+ UICDM::TActionHandleList m_actions;
+};
+
+#endif // ACTIONMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Action/ActionView.cpp b/src/Authoring/Studio/Palettes/Action/ActionView.cpp
new file mode 100644
index 00000000..4aace20a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionView.cpp
@@ -0,0 +1,848 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ActionView.h"
+#include "ActionContextMenu.h"
+#include "ActionModel.h"
+#include "CmdDataModelActionSetValue.h"
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "Doc.h"
+#include "IDocumentEditor.h"
+#include "IDocumentReader.h"
+#include "IObjectReferenceHelper.h"
+#include "Literals.h"
+#include "ObjectListModel.h"
+#include "StudioUtils.h"
+#include "StudioApp.h"
+#include "StudioClipboard.h"
+#include "StudioObjectTypes.h"
+#include "StudioPreferences.h"
+#include "UICFileTools.h"
+#include "UICDMActionCore.h"
+#include "UICDMDataTypes.h"
+#include "UICDMSlides.h"
+
+#include <QCoreApplication>
+#include <QQmlContext>
+#include <QQmlEngine>
+#include <QTimer>
+
+ActionView::ActionView(QWidget *parent)
+ : QQuickWidget(parent)
+ , TabNavigable()
+ , m_actionsModel(new ActionModel(this))
+{
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ActionView::initialize);
+
+ g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
+
+ connect(this, &ActionView::actionChanged, this, [this] {
+ if (!m_propertyModel)
+ m_propertyModel = new PropertyModel(this);
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler == L"Set Property") {
+ m_currentPropertyNameHandle = actionInfo.m_HandlerArgs.at(0);
+ m_currentPropertyValueHandle = actionInfo.m_HandlerArgs.at(1);
+ m_propertyModel->setAction(m_actionsModel->actionAt(m_currentActionIndex));
+ m_propertyModel->setNameHandle(m_currentPropertyNameHandle);
+ m_propertyModel->setValueHandle(m_currentPropertyValueHandle);
+
+ Q_EMIT propertyModelChanged();
+ }
+
+ });
+
+ m_actionChangedCompressionTimer.setInterval(500);
+ m_actionChangedCompressionTimer.setSingleShot(true);
+ connect(&m_actionChangedCompressionTimer, &QTimer::timeout, this, [this] {
+ updateHandlerArguments();
+ updateFiredEvent();
+ Q_EMIT actionChanged();
+ });
+}
+
+ActionView::~ActionView()
+{
+ m_connections.clear();
+}
+
+QSize ActionView::sizeHint() const
+{
+ return {500, 500};
+}
+
+void ActionView::setItem(const UICDM::CUICDMInstanceHandle &handle)
+{
+ m_objRefHelper = GetDoc()->GetDataModelObjectReferenceHelper();
+ m_itemHandle = handle;
+ m_actionsModel->setInstanceHandle(handle);
+ emitActionChanged();
+ Q_EMIT itemChanged();
+}
+
+QString ActionView::itemIcon() const
+{
+ if (!m_itemHandle.Valid())
+ return {};
+
+ auto info = m_objRefHelper->GetInfo(m_itemHandle);
+ return CStudioObjectTypes::GetNormalIconName(info.m_Type);
+}
+
+QString ActionView::itemText() const
+{
+ if (!m_itemHandle.Valid())
+ return tr("No Object Selected");
+
+ const auto data = m_objRefHelper->GetInfo(m_itemHandle);
+ return data.m_Name.toQString();
+}
+
+QColor ActionView::itemColor() const
+{
+ if (!m_itemHandle.Valid())
+ return Qt::white;
+
+ auto info = m_objRefHelper->GetInfo(m_itemHandle);
+ if (info.m_Master)
+ return CStudioPreferences::masterColor();
+ else
+ return CStudioPreferences::textColor();
+}
+
+QAbstractItemModel *ActionView::actionsModel() const
+{
+ return m_actionsModel;
+}
+
+QAbstractItemModel *ActionView::propertyModel() const
+{
+ return m_propertyModel;
+}
+
+QString ActionView::targetObjectName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+
+ const auto targetInstance =
+ GetBridge()->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+
+ QString targetName = targetInstance.Valid()
+ ? GetBridge()->GetName(targetInstance).toQString()
+ : tr("[Unknown Target]");
+
+ return targetName;
+}
+
+QString ActionView::triggerObjectName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+
+ const auto sourceInstance =
+ GetBridge()->GetInstance(actionInfo.m_Owner, actionInfo.m_TriggerObject);
+
+ QString sourceName = sourceInstance.Valid()
+ ? GetBridge()->GetName(sourceInstance).toQString()
+ : tr("[Unknown Source]");
+
+ return sourceName;
+}
+
+QString ActionView::eventName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto eventHandle = bridge->ResolveEvent(actionInfo);
+ const auto eventInfo = bridge->GetEventInfo(eventHandle);
+
+ const QString formalName = QString::fromWCharArray(eventInfo.m_FormalName.wide_str());
+ return formalName.isEmpty() ? tr("[Unknown Event]") : formalName;
+}
+
+QString ActionView::handlerName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+
+ if (handlerHandle.Valid()) {
+ const auto handlerInfo = bridge->GetHandlerInfo(handlerHandle);
+ return QString::fromWCharArray(handlerInfo.m_FormalName.wide_str());
+ }
+
+ return tr("[Unknown Handler]");
+}
+
+QVariantList ActionView::handlerArguments() const
+{
+ return m_handlerArguments;
+}
+
+PropertyInfo ActionView::property() const
+{
+ if (!m_propertyModel)
+ return {};
+ return m_propertyModel->property(m_currentPropertyIndex);
+}
+
+void ActionView::setCurrentActionIndex(int index)
+{
+ if (index == m_currentActionIndex)
+ return;
+
+ m_currentActionIndex = index;
+ emitActionChanged();
+}
+
+void ActionView::setCurrentPropertyIndex(int handle, int index)
+{
+ if (index == m_currentPropertyIndex)
+ return;
+
+ m_currentPropertyValueHandle = 0;
+ m_currentPropertyNameHandle = handle;
+ for (int i = 0; i < m_handlerArguments.size(); ++i) {
+ auto handlerArg = m_handlerArguments[i].value<HandlerArgument>();
+ if (handlerArg.m_handle.GetHandleValue() == handle && i < m_handlerArguments.size() - 1) {
+ m_currentPropertyValueHandle = m_handlerArguments[i + 1].value<HandlerArgument>().m_handle;
+ if (m_propertyModel) {
+ m_propertyModel->setNameHandle(m_currentPropertyNameHandle);
+ m_propertyModel->setValueHandle(m_currentPropertyValueHandle);
+ }
+ }
+ }
+
+ m_currentPropertyIndex = index;
+
+ // set the property for the handler
+ if (m_propertyModel && handle != 0) {
+ UICDM::SValue sValue(QVariant(m_propertyModel->property(index).m_nameId));
+ UICDM::SValue oldValue;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, oldValue);
+
+ if (!Equals(oldValue, sValue)) {
+ CCmd *theCmd =
+ new CCmdDataModelActionSetArgumentValue(GetDoc(), handle, sValue);
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ }
+ }
+
+ Q_EMIT propertyChanged();
+}
+
+void ActionView::addAction()
+{
+ if (m_itemHandle.Valid()) {
+ // Query data model bridge to see the applicable events and actions for this instance.
+ CClientDataModelBridge *theBridge = GetBridge();
+
+ std::wstring theEventName = theBridge->GetDefaultEvent(m_itemHandle);
+ std::wstring theHandlerName = theBridge->GetDefaultHandler(m_itemHandle);
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Add Action"))
+ ->AddAction(GetDoc()->GetActiveSlide(), m_itemHandle, theEventName,
+ theHandlerName);
+ }
+}
+
+void ActionView::deleteAction(int index)
+{
+ const auto action = m_actionsModel->actionAt(index);
+ if (action.Valid()) {
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Delete Action"))->DeleteAction(action);
+ }
+}
+
+QObject *ActionView::showTriggerObjectBrowser(const QPoint &point)
+{
+ if (!m_objectsModel) {
+ m_objectsModel = new ObjectListModel(g_StudioApp.GetCore(),
+ GetDoc()->GetActiveRootInstance(), this);
+ }
+
+ if (!m_triggerObjectBrowser)
+ m_triggerObjectBrowser = new ObjectBrowserView(this);
+
+ m_triggerObjectBrowser->setModel(m_objectsModel);
+
+ showBrowser(m_triggerObjectBrowser, point);
+
+ connect(m_triggerObjectBrowser, &ObjectBrowserView::selectionChanged,
+ this, [this] {
+ auto selectedItem = m_triggerObjectBrowser->selectedHandle();
+ setTriggerObject(m_objRefHelper->GetAssetRefValue(selectedItem,
+ m_itemHandle,
+ (CRelativePathTools::EPathType)(m_triggerObjectBrowser->pathType())));
+ });
+
+ return m_triggerObjectBrowser;
+}
+
+QObject *ActionView::showTargetObjectBrowser(const QPoint &point)
+{
+ if (!m_objectsModel) {
+ m_objectsModel = new ObjectListModel(g_StudioApp.GetCore(),
+ GetDoc()->GetActiveRootInstance(), this);
+ }
+
+ if (!m_targetObjectBrowser)
+ m_targetObjectBrowser = new ObjectBrowserView(this);
+
+ m_targetObjectBrowser->setModel(m_objectsModel);
+
+ showBrowser(m_targetObjectBrowser, point);
+
+ connect(m_targetObjectBrowser, &ObjectBrowserView::selectionChanged,
+ this, [this] {
+ auto selectedItem = m_targetObjectBrowser->selectedHandle();
+ setTargetObject(m_objRefHelper->GetAssetRefValue(selectedItem,
+ m_itemHandle,
+ (CRelativePathTools::EPathType)(m_targetObjectBrowser->pathType())));
+ resetFiredEvent();
+ });
+
+ return m_targetObjectBrowser;
+}
+
+void ActionView::showContextMenu(int x, int y)
+{
+ CActionContextMenu contextMenu(this);
+
+ connect(&contextMenu, &CActionContextMenu::copyAction, this, &ActionView::copyAction);
+ connect(&contextMenu, &CActionContextMenu::pasteAction, this, &ActionView::pasteAction);
+ connect(&contextMenu, &CActionContextMenu::cutAction, this, &ActionView::cutAction);
+ connect(&contextMenu, &CActionContextMenu::deleteAction, this, [this] {
+ deleteAction(m_currentActionIndex);
+ });
+
+ contextMenu.exec(mapToGlobal({x, y}));
+}
+
+QObject *ActionView::showEventBrowser(const QPoint &point)
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TriggerObject);
+
+ if (!instanceHandle.Valid())
+ return nullptr;
+
+ if (!m_eventsModel) {
+ m_eventsModel = new EventsModel(this);
+ }
+
+ UICDM::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ m_eventsModel->setEventList(eventList);
+
+ if (!m_eventsBrowser)
+ m_eventsBrowser = new EventsBrowserView(this);
+
+ m_eventsBrowser->setModel(m_eventsModel);
+
+ showBrowser(m_eventsBrowser, point);
+
+ connect(m_eventsBrowser, &EventsBrowserView::selectionChanged,
+ this, [this] {
+ setEvent(UICDM::CUICDMEventHandle(m_eventsBrowser->selectedHandle()));
+ });
+
+ return m_eventsBrowser;
+}
+
+QObject *ActionView::showHandlerBrowser(const QPoint &point)
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+
+ if (!instanceHandle.Valid())
+ return nullptr;
+
+ if (!m_handlersModel) {
+ m_handlersModel = new EventsModel(this);
+ }
+
+ UICDM::THandlerHandleList handlerList;
+ bridge->GetHandlers(instanceHandle, handlerList);
+ m_handlersModel->setHandlerList(handlerList);
+
+ if (!m_handlerBrowser)
+ m_handlerBrowser = new EventsBrowserView(this);
+
+ m_handlerBrowser->setModel(m_handlersModel);
+
+ showBrowser(m_handlerBrowser, point);
+
+ connect(m_handlerBrowser, &EventsBrowserView::selectionChanged,
+ this, [this] {
+ setHandler(UICDM::CUICDMHandlerHandle(m_handlerBrowser->selectedHandle()));
+ });
+
+ return m_handlerBrowser;
+}
+
+QObject *ActionView::showEventBrowserForArgument(int handle, const QPoint &point)
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+
+ if (!instanceHandle.Valid())
+ return nullptr;
+
+ if (!m_fireEventsModel) {
+ m_fireEventsModel = new EventsModel(this);
+ }
+
+ UICDM::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ m_fireEventsModel->setEventList(eventList);
+
+ if (!m_fireEventsBrowser)
+ m_fireEventsBrowser = new EventsBrowserView(this);
+
+ m_fireEventsBrowser->setModel(m_fireEventsModel);
+
+ showBrowser(m_fireEventsBrowser, point);
+
+ connect(m_fireEventsBrowser, &EventsBrowserView::selectionChanged,
+ this, [this, handle] {
+ setArgumentValue(handle, UICDM::CUICDMEventHandle(m_fireEventsBrowser->selectedHandle()).GetHandleValue());
+ });
+
+ return m_fireEventsBrowser;
+}
+
+void ActionView::showBrowser(QQuickWidget *browser, const QPoint &point)
+{
+ QSize popupSize = CStudioPreferences::browserPopupSize();
+ browser->disconnect();
+ browser->resize(popupSize);
+ browser->move(point - QPoint(popupSize.width(), popupSize.height()));
+
+ // Show asynchronously to avoid flashing blank window on first show
+ QTimer::singleShot(0, this, [browser] {
+ browser->show();
+ browser->activateWindow();
+ browser->setFocus();
+ });
+}
+
+void ActionView::updateFiredEvent()
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler != L"Fire Event") {
+ m_firedEvent = tr("[Unknown event]");
+ return;
+ }
+
+ const auto doc = GetDoc();
+ if (!doc->IsValid())
+ return;
+
+ const auto bridge = GetBridge();
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+ IActionCore *actionCore = doc->GetStudioSystem()->GetActionCore();
+
+ if (handlerHandle.Valid()) {
+ for (const auto &argHandle: actionInfo.m_HandlerArgs) {
+ const auto &argumentInfo = actionCore->GetHandlerArgumentInfo(argHandle);
+ DataModelDataType::Value theArgType(GetValueType(argumentInfo.m_Value));
+ SValue theArgValue(argumentInfo.m_Value);
+ if (argumentInfo.m_ArgType == HandlerArgumentType::Event) {
+ theArgType = DataModelDataType::String;
+ auto theEventHandle = get<qt3ds::QT3DSI32>(argumentInfo.m_Value);
+ theArgValue = SValue(std::make_shared<CDataStr>(
+ bridge->GetEventInfo(theEventHandle).m_Name.wide_str()));
+ m_firedEvent = theArgValue.toQVariant().toString();
+ Q_EMIT firedEventChanged();
+ }
+ }
+ }
+}
+
+void ActionView::updateFiredEventFromHandle(int handle)
+{
+ m_firedEvent = QString::fromWCharArray(GetBridge()->GetEventInfo(handle).m_FormalName.wide_str());
+ Q_EMIT firedEventChanged();
+}
+
+void ActionView::resetFiredEvent()
+{
+ m_firedEvent = tr("[Unknown Event]");
+ Q_EMIT firedEventChanged();
+}
+
+void ActionView::OnNewPresentation()
+{
+ // Register callback
+ UICDM::IStudioFullSystemSignalProvider *theSignalProvider =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+ m_connections.push_back(theSignalProvider->ConnectActionCreated(
+ std::bind(&ActionView::OnActionAdded, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_connections.push_back(theSignalProvider->ConnectActionDeleted(
+ std::bind(&ActionView::OnActionDeleted, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_connections.push_back(theSignalProvider->ConnectTriggerObjectSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectTargetObjectSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectEventSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectHandlerSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectHandlerArgumentValueSet(
+ std::bind(&ActionView::OnHandlerArgumentModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectInstancePropertyValue(
+ std::bind(&ActionView::OnInstancePropertyValueChanged, this, std::placeholders::_1,
+ std::placeholders::_2)));
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ m_connections.push_back(theDispatch->ConnectSelectionChange(
+ std::bind(&ActionView::OnSelectionSet, this,
+ std::placeholders::_1)));
+}
+
+void ActionView::OnSelectionSet(Q3DStudio::SSelectedValue inSelectable)
+{
+ UICDM::CUICDMInstanceHandle theInstance;
+ std::vector<UICDM::CUICDMInstanceHandle> instances;
+
+ switch (inSelectable.getType()) {
+ case Q3DStudio::SelectedValueTypes::Instance:
+ theInstance = inSelectable.getData<UICDM::CUICDMInstanceHandle>();
+ break;
+ case Q3DStudio::SelectedValueTypes::MultipleInstances:
+ instances = inSelectable.getData<std::vector<UICDM::CUICDMInstanceHandle>>();
+ // handling only if we have one selected element.
+ if (instances.size() == 1)
+ theInstance = instances[0];
+ break;
+ case Q3DStudio::SelectedValueTypes::Slide: {
+ UICDM::CUICDMSlideHandle theSlideHandle =
+ inSelectable.getData<Q3DStudio::SSlideInstanceWrapper>().m_Slide;
+ // Get the owning component instance
+ CClientDataModelBridge *theBridge = GetBridge();
+ UICDM::SLong4 theComponentGuid = theBridge->GetComponentGuid(theSlideHandle);
+ Q_ASSERT(GuidValid(theComponentGuid));
+ theInstance = theBridge->GetInstanceByGUID(theComponentGuid);
+ Q_ASSERT(theInstance.Valid());
+ } break;
+ };
+
+ setItem(theInstance);
+}
+
+void ActionView::OnActionAdded(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide, UICDM::CUICDMInstanceHandle inOwner)
+{
+ CDoc *theDoc = GetDoc();
+ UICDM::CStudioSystem *theStudioSystem = theDoc->GetStudioSystem();
+
+ UICDM::CUICDMSlideHandle theCurrentSlide = theDoc->GetActiveSlide();
+ UICDM::CUICDMSlideHandle theMasterSlideOfAction =
+ theStudioSystem->GetSlideSystem()->GetMasterSlide(inSlide);
+ UICDM::CUICDMSlideHandle theMasterOfCurrentSlide =
+ theStudioSystem->GetSlideSystem()->GetMasterSlide(theCurrentSlide);
+
+ if (inOwner == m_itemHandle && // the action is added to current viewed instance
+ (theCurrentSlide == inSlide || // and is added to the current viewed slide
+ (theMasterSlideOfAction == inSlide
+ && theMasterOfCurrentSlide == theMasterSlideOfAction))) // or it is added to the master of
+ // the current viewed slide
+ {
+ m_actionsModel->addAction(inAction);
+// KDAB_TODO SortActions();
+ }
+}
+
+void ActionView::OnActionDeleted(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide, UICDM::CUICDMInstanceHandle inOwner)
+{
+ Q_UNUSED(inSlide);
+ Q_UNUSED(inOwner);
+ m_actionsModel->removeAction(inAction);
+}
+
+void ActionView::OnActionModified(UICDM::CUICDMActionHandle inAction)
+{
+ if (GetDoc()->GetStudioSystem()->GetActionCore()->HandleValid(inAction)) {
+ m_actionsModel->updateAction(inAction);
+ emitActionChanged();
+ }
+}
+
+void ActionView::OnHandlerArgumentModified(UICDM::CUICDMHandlerArgHandle inHandlerArgument)
+{
+ emitActionChanged();
+}
+
+void ActionView::OnInstancePropertyValueChanged(UICDM::CUICDMInstanceHandle inInstance, UICDM::CUICDMPropertyHandle inProperty)
+{
+ emitActionChanged();
+}
+
+void ActionView::copyAction()
+{
+ auto theTempAPFile =
+ GetDoc()->GetDocumentReader().CopyAction(m_actionsModel->actionAt(m_currentActionIndex),
+ GetDoc()->GetActiveSlide());
+ CUICFile theFile(theTempAPFile);
+ CStudioClipboard::CopyActionToClipboard(theFile);
+}
+
+void ActionView::cutAction()
+{
+ copyAction();
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Cut Action"))->DeleteAction(action);
+}
+
+void ActionView::pasteAction()
+{
+ CUICFile theTempAPFile = CStudioClipboard::GetActionFromClipboard();
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Paste Action"))
+ ->PasteAction(theTempAPFile.GetAbsolutePath(), m_itemHandle);
+}
+
+void ActionView::setTriggerObject(const UICDM::SObjectRefType &object)
+{
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ if (!action.Valid())
+ return;
+
+ auto core = g_StudioApp.GetCore();
+ auto theBridge = GetBridge();
+
+ auto theCmd = new CCmdDataModelActionSetTriggerObject(GetDoc(), action, object);
+ const SActionInfo &theActionInfo = GetDoc()->GetStudioSystem()->GetActionCore()->GetActionInfo(action);
+
+ CUICDMInstanceHandle theBaseInstance = theActionInfo.m_Owner;
+ CUICDMInstanceHandle theObjectInstance = theBridge->GetInstance(theBaseInstance, object);
+ CUICDMInstanceHandle theOldInstance = theBridge->GetInstance(theBaseInstance, theActionInfo.m_TargetObject);
+ // old instance and object instance could be the same, for example if user changes the type
+ // from Absolute to Path. In this case we don't need to reset handler or event.
+ if (theOldInstance != theObjectInstance)
+ theCmd->ResetEvent(
+ theBridge->GetDefaultEvent(theObjectInstance, theActionInfo.m_Event));
+
+ core->ExecuteCommand(theCmd);
+ emitActionChanged();
+}
+
+void ActionView::setTargetObject(const UICDM::SObjectRefType &object)
+{
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ if (!action.Valid())
+ return;
+
+ auto core = g_StudioApp.GetCore();
+ auto doc = GetDoc();
+ auto theBridge = GetBridge();
+
+ auto theCmd = new CCmdDataModelActionSetTargetObject(doc, action, object);
+ const SActionInfo &theActionInfo = doc->GetStudioSystem()->GetActionCore()->GetActionInfo(action);
+
+ CUICDMInstanceHandle theBaseInstance = theActionInfo.m_Owner;
+ CUICDMInstanceHandle theObjectInstance = theBridge->GetInstance(theBaseInstance, object);
+ CUICDMInstanceHandle theOldInstance = theBridge->GetInstance(theBaseInstance, theActionInfo.m_TargetObject);
+ // old instance and object instance could be the same, for example if user changes the type
+ // from Absolute to Path. In this case we don't need to reset handler or event.
+ if (theOldInstance != theObjectInstance)
+ theCmd->ResetHandler(
+ theBridge->GetDefaultHandler(theObjectInstance, theActionInfo.m_Handler));
+
+ core->ExecuteCommand(theCmd);
+ emitActionChanged();
+}
+
+void ActionView::setEvent(const CUICDMEventHandle &event)
+{
+ if (!event.Valid())
+ return;
+
+ auto doc = GetDoc();
+ const auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ CCmd *theCmd = new CCmdDataModelActionSetEvent(doc, action,
+ doc->GetStudioSystem()
+ ->GetActionMetaData()
+ ->GetEventInfo(event)
+ ->m_Name.wide_str());
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+}
+
+void ActionView::setHandler(const CUICDMHandlerHandle &handler)
+{
+ if (!handler.Valid())
+ return;
+
+ auto doc = GetDoc();
+ const auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ wstring handlerName(doc->GetStudioSystem()->GetActionMetaData()->GetHandlerInfo(handler)
+ ->m_Name.wide_str());
+ CCmdDataModelActionSetHandler *theCmd =
+ new CCmdDataModelActionSetHandler(doc, action, handlerName);
+ theCmd->ResetHandler(handlerName); // reset the handler args
+
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+}
+
+QVariant ActionView::handlerArgumentValue(int handle) const
+{
+ UICDM::SValue value;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, value);
+ return value.toQVariant();
+}
+
+void ActionView::updateHandlerArguments()
+{
+ m_currentPropertyValueHandle = 0;
+ m_currentPropertyNameHandle = 0;
+ m_handlerArguments.clear();
+ const auto doc = GetDoc();
+ if (!doc->IsValid())
+ return;
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+ IActionCore *actionCore = doc->GetStudioSystem()->GetActionCore();
+
+ if (handlerHandle.Valid()) {
+ auto newMetaData = doc->GetStudioSystem()->GetActionMetaData();
+
+ for (const auto &argHandle: actionInfo.m_HandlerArgs) {
+ const auto &argumentInfo = actionCore->GetHandlerArgumentInfo(argHandle);
+ Option<SMetaDataHandlerArgumentInfo> argMetaData(
+ newMetaData->FindHandlerArgumentByName(handlerHandle, argumentInfo.m_Name));
+
+
+ HandlerArgument argument;
+ argument.m_handle = argHandle;
+ argument.m_type = argMetaData->m_ArgType;
+ argument.m_name = QString::fromWCharArray(argumentInfo.m_Name.wide_str());
+ argument.m_value = argumentInfo.m_Value.toQVariant();
+ argument.m_completeType = argMetaData->m_CompleteType;
+ m_handlerArguments.append(QVariant::fromValue(argument));
+ }
+ }
+}
+
+void ActionView::emitActionChanged()
+{
+ m_actionChangedCompressionTimer.start();
+}
+
+void ActionView::setArgumentValue(int handle, const QVariant &value)
+{
+ if (handle == 0)
+ return;
+
+ UICDM::SValue sValue(value);
+ UICDM::SValue oldValue;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, oldValue);
+
+ if (!Equals(oldValue, sValue)) {
+ CCmd *theCmd =
+ new CCmdDataModelActionSetArgumentValue(GetDoc(), handle, sValue);
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ }
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler == L"Fire Event") {
+ if (value.toInt())
+ updateFiredEventFromHandle(value.toInt());
+ }
+}
+
+CDoc *ActionView::GetDoc()
+{
+ return g_StudioApp.GetCore()->GetDoc();
+}
+
+CClientDataModelBridge *ActionView::GetBridge()
+{
+ return GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+}
+
+void ActionView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_actionView"_L1, this);
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+ rootContext()->setContextProperty("_tabOrderHandler"_L1, tabOrderHandler());
+ qmlRegisterUncreatableType<UICDM::HandlerArgumentType>("Qt3DStudio", 1, 0, "HandlerArgumentType",
+ "HandlerArgumentType is an enum container"_L1);
+ qmlRegisterUncreatableType<UICDM::DataModelDataType>("Qt3DStudio", 1, 0, "DataModelDataType",
+ "DataModelDataType is an enum container"_L1);
+ qmlRegisterUncreatableType<UICDM::AdditionalMetaDataType>("Qt3DStudio", 1, 0, "AdditionalMetaDataType",
+ "AdditionalMetaDataType is an enum container"_L1);
+ qmlRegisterUncreatableType<PropertyInfo>("Qt3DStudio", 1, 0, "PropertyInfo",
+ "PropertyInfo is anot creatable in QML"_L1);
+ qmlRegisterUncreatableType<UICDM::CompleteMetaDataType>("Qt3DStudio", 1, 0, "CompleteMetaDataType",
+ "CompleteMetaDataType is an enum container"_L1);
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Action/ActionView.qml"_L1));
+}
+
+QStringList ActionView::slideNames()
+{
+ std::list<Q3DStudio::CString> outSlideNames;
+ QStringList slideNames;
+ CClientDataModelBridge *theBridge = GetBridge();
+ const auto action = m_actionsModel->actionAt(m_currentActionIndex);
+
+ theBridge->GetSlideNamesOfAction(action, outSlideNames);
+
+ for (auto slideName : outSlideNames) {
+ slideNames.append(slideName.toQString());
+ }
+
+ return slideNames;
+}
+
+int ActionView::slideNameToIndex(const QString &name)
+{
+ const auto slides = slideNames(); // KDAB_TODO cache it
+ return slides.indexOf(name);
+}
diff --git a/src/Authoring/Studio/Palettes/Action/ActionView.h b/src/Authoring/Studio/Palettes/Action/ActionView.h
new file mode 100644
index 00000000..dec7b078
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionView.h
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIONVIEW_H
+#define ACTIONVIEW_H
+
+#include <QQuickWidget>
+#include <QColor>
+#include <QPointer>
+#include <QTimer>
+
+#include "stdafx.h"
+#include "DispatchListeners.h"
+#include "EventsBrowserView.h"
+#include "EventsModel.h"
+#include "ObjectBrowserView.h"
+#include "ObjectListModel.h"
+#include "PropertyModel.h"
+#include "SelectedValueImpl.h"
+#include "UICDMHandles.h"
+#include "UICDMSignals.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMMetaDataTypes.h"
+#include "TabOrderHandler.h"
+
+class ActionModel;
+class CClientDataModelBridge;
+class CCore;
+class CDoc;
+class IObjectReferenceHelper;
+
+class QAbstractItemModel;
+
+struct HandlerArgument {
+ Q_PROPERTY(UICDM::HandlerArgumentType::Value type MEMBER m_type FINAL)
+ Q_PROPERTY(QString name MEMBER m_name FINAL)
+ Q_PROPERTY(int handle MEMBER m_handle FINAL)
+ Q_PROPERTY(QVariant value MEMBER m_value FINAL)
+ Q_PROPERTY(UICDM::CompleteMetaDataType::Enum completeType MEMBER m_completeType FINAL)
+
+ UICDM::CUICDMHandlerArgHandle m_handle;
+ UICDM::HandlerArgumentType::Value m_type;
+ UICDM::CompleteMetaDataType::Enum m_completeType;
+ QString m_name;
+ QVariant m_value;
+
+ Q_GADGET
+};
+
+Q_DECLARE_METATYPE(HandlerArgument)
+
+class ActionView : public QQuickWidget,
+ public CPresentationChangeListener,
+ public TabNavigable
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QAbstractItemModel *actionsModel READ actionsModel NOTIFY itemChanged FINAL)
+ Q_PROPERTY(QAbstractItemModel *propertyModel READ propertyModel NOTIFY propertyModelChanged FINAL)
+ Q_PROPERTY(QString itemIcon READ itemIcon NOTIFY itemChanged FINAL)
+ Q_PROPERTY(QString itemText READ itemText NOTIFY itemChanged FINAL)
+ Q_PROPERTY(QColor itemColor READ itemColor NOTIFY itemChanged FINAL)
+ Q_PROPERTY(QString triggerObjectName READ triggerObjectName NOTIFY actionChanged FINAL)
+ Q_PROPERTY(QString targetObjectName READ targetObjectName NOTIFY actionChanged FINAL)
+ Q_PROPERTY(QString eventName READ eventName NOTIFY actionChanged FINAL)
+ Q_PROPERTY(QString handlerName READ handlerName NOTIFY actionChanged FINAL)
+ Q_PROPERTY(QVariantList handlerArguments READ handlerArguments NOTIFY actionChanged FINAL)
+ Q_PROPERTY(PropertyInfo property READ property NOTIFY propertyChanged FINAL)
+ Q_PROPERTY(QString firedEvent MEMBER m_firedEvent NOTIFY firedEventChanged FINAL)
+
+public:
+ ActionView(QWidget *parent = nullptr);
+ ~ActionView();
+
+ QSize sizeHint() const override;
+
+ void setItem(const UICDM::CUICDMInstanceHandle &handle);
+ QString itemIcon() const;
+ QString itemText() const;
+ QColor itemColor() const;
+ QAbstractItemModel *actionsModel() const;
+ QAbstractItemModel *propertyModel() const;
+ QString targetObjectName() const;
+ QString triggerObjectName() const;
+ QString eventName() const;
+ QString handlerName() const;
+ QVariantList handlerArguments() const;
+ PropertyInfo property() const;
+
+ Q_INVOKABLE void setCurrentActionIndex(int index);
+ Q_INVOKABLE void setCurrentPropertyIndex(int handle, int index);
+ Q_INVOKABLE void addAction();
+ Q_INVOKABLE void deleteAction(int index);
+ Q_INVOKABLE QObject *showTriggerObjectBrowser(const QPoint &point);
+ Q_INVOKABLE QObject *showTargetObjectBrowser(const QPoint &point);
+ Q_INVOKABLE void showContextMenu(int x, int y);
+ Q_INVOKABLE QObject *showEventBrowser(const QPoint &point);
+ Q_INVOKABLE QObject *showHandlerBrowser(const QPoint &point);
+ Q_INVOKABLE QObject *showEventBrowserForArgument(int handle, const QPoint &point);
+ Q_INVOKABLE void setArgumentValue(int handle, const QVariant &value);
+ Q_INVOKABLE QStringList slideNames();
+ Q_INVOKABLE int slideNameToIndex(const QString &name);
+
+
+ // CPresentationChangeListener
+ void OnNewPresentation() override;
+
+ // ISelectionChangeListener
+ void OnSelectionSet(Q3DStudio::SSelectedValue inSelectable);
+
+ // Action callback
+ void OnActionAdded(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMInstanceHandle inOwner);
+ void OnActionDeleted(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMInstanceHandle inOwner);
+ void OnActionModified(UICDM::CUICDMActionHandle inAction);
+ void OnHandlerArgumentModified(UICDM::CUICDMHandlerArgHandle inHandlerArgument);
+ void OnInstancePropertyValueChanged(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+
+Q_SIGNALS:
+ void itemChanged();
+ void actionChanged();
+ void propertyModelChanged();
+ void propertyChanged();
+ void firedEventChanged();
+
+private Q_SLOTS:
+ void copyAction();
+ void cutAction();
+ void pasteAction();
+
+private:
+ void setTriggerObject(const UICDM::SObjectRefType &object);
+ void setTargetObject(const UICDM::SObjectRefType &object);
+ void setEvent(const UICDM::CUICDMEventHandle &event);
+ void setHandler(const UICDM::CUICDMHandlerHandle &handler);
+ QVariant handlerArgumentValue(int handle) const;
+ void updateHandlerArguments();
+ void emitActionChanged();
+ void updateFiredEvent();
+ void resetFiredEvent();
+ void updateFiredEventFromHandle(int handle);
+ void showBrowser(QQuickWidget *browser, const QPoint &point);
+
+ static CDoc *GetDoc();
+ static CClientDataModelBridge *GetBridge();
+
+ void initialize();
+ QColor m_baseColor = QColor::fromRgb(75, 75, 75);
+ QColor m_selectColor = Qt::transparent;
+ UICDM::CUICDMInstanceHandle m_itemHandle;
+ IObjectReferenceHelper *m_objRefHelper = nullptr;
+ ActionModel *m_actionsModel = nullptr;
+ PropertyModel *m_propertyModel = nullptr;
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>>
+ m_connections; /// connections to the UICDM
+ QPointer<ObjectListModel> m_objectsModel;
+ QPointer<ObjectBrowserView> m_triggerObjectBrowser;
+ QPointer<ObjectBrowserView> m_targetObjectBrowser;
+ QPointer<EventsModel> m_eventsModel;
+ QPointer<EventsModel> m_handlersModel;
+ QPointer<EventsModel> m_fireEventsModel;
+ QPointer<EventsBrowserView> m_eventsBrowser;
+ QPointer<EventsBrowserView> m_handlerBrowser;
+ QPointer<EventsBrowserView> m_fireEventsBrowser;
+ int m_currentActionIndex = -1;
+ int m_currentPropertyIndex = -1;
+ UICDM::CUICDMHandlerArgHandle m_currentPropertyNameHandle;
+ UICDM::CUICDMHandlerArgHandle m_currentPropertyValueHandle;
+ QVariantList m_handlerArguments;
+ QTimer m_actionChangedCompressionTimer;
+ QString m_firedEvent;
+};
+
+#endif // ACTIONVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Action/ActionView.qml b/src/Authoring/Studio/Palettes/Action/ActionView.qml
new file mode 100644
index 00000000..c1debc3a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionView.qml
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import Qt3DStudio 1.0
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+
+ Flickable {
+ id: actionFlickable
+ ScrollBar.vertical: ScrollBar {
+ id: scrollBar
+ visible: size < 1.0
+ }
+
+ anchors.fill: parent
+ contentHeight: contentColumn.height
+
+ property bool scrollToBottom: false
+
+ onContentHeightChanged: {
+ if (scrollToBottom) {
+ scrollToBottom = false;
+ if (contentHeight > height)
+ contentY = contentHeight - height;
+ }
+ }
+
+ Column {
+ id: contentColumn
+ width: parent.width
+ spacing: 4
+
+ RowLayout {
+ height: _controlBaseHeight + anchors.margins * 2
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: 4
+ anchors.rightMargin: 12
+
+ Image {
+ id: headerImage
+ source: _actionView.itemIcon !== "" ? _resDir + _actionView.itemIcon : ""
+ }
+
+ StyledLabel {
+ Layout.fillWidth: true
+ text: _actionView.itemText
+ color: _actionView.itemColor
+ }
+
+ StyledToolButton {
+ enabled: actionsList.currentIndex !== -1
+ enabledImage: "Action-Trash-Normal.png"
+ disabledImage: "Action-Trash-Disabled.png"
+ toolTipText: qsTr("Delete selected action")
+
+ onClicked: _actionView.deleteAction(actionsList.currentIndex)
+ }
+
+ StyledToolButton {
+ enabledImage: "add.png"
+ toolTipText: qsTr("Add new action")
+
+ onClicked: _actionView.addAction()
+ }
+ }
+ ListView {
+ id: actionsList
+ width: parent.width
+ height: count * _controlBaseHeight
+ clip: true
+
+ boundsBehavior: Flickable.StopAtBounds
+ model: _actionView.actionsModel
+
+ delegate: Rectangle {
+ id: delegateItem
+
+ width: actionsList.width
+ height: _controlBaseHeight
+ color: model.index === actionsList.currentIndex ? _selectionColor
+ : "transparent"
+
+ Row {
+ x: 10
+ y: 5
+ height: parent.height
+ width: parent.width - x
+ spacing: 4
+
+ Image {
+ id: visibilityIcon
+
+ source: model.visible ? _resDir + "Toggle-HideShow.png"
+ : _resDir + "Toggle-HideShow-disabled.png"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: model.visible = !model.visible
+ }
+ }
+
+ StyledLabel {
+ text: model.description
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+
+ onClicked: {
+ actionFlickable.scrollToBottom = false;
+ actionsList.currentIndex = model.index;
+ _actionView.setCurrentActionIndex(model.index);
+ if (mouse.button == Qt.LeftButton && mouse.x < visibilityIcon.width + 10)
+ model.visible = !model.visible;
+
+ if (mouse.button == Qt.RightButton) {
+ var updateMousePosition = mapToItem(actionsList, mouse.x, mouse.y)
+ _actionView.showContextMenu(updateMousePosition.x, updateMousePosition.y);
+ }
+ }
+ onDoubleClicked: {
+ actionFlickable.scrollToBottom = false;
+ if (mouse.button == Qt.LeftButton && mouse.x > visibilityIcon.width + 10) {
+ // Scroll down to bottom to show properties on double click
+ if (actionFlickable.contentHeight > actionFlickable.height) {
+ actionFlickable.contentY = (actionFlickable.contentHeight
+ - actionFlickable.height)
+ }
+ // Since loading new property fields takes a moment, we want
+ // to keep the view scrolled to bottom
+ // when the content height changes the next time.
+ actionFlickable.scrollToBottom = true;
+ }
+ }
+ }
+ }
+
+ onCountChanged: {
+ if (currentIndex >= count)
+ currentIndex = count - 1;
+ }
+
+ onCurrentIndexChanged: _actionView.setCurrentActionIndex(currentIndex);
+ }
+
+ StyledMenuSeparator {
+ leftPadding: 12
+ rightPadding: 12
+ }
+
+ Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: childrenRect.height
+ visible: actionsList.currentIndex !== -1
+ spacing: 4
+
+ RowLayout {
+ x: 12
+ StyledLabel {
+ text: qsTr("Trigger Object")
+ }
+ BrowserCombo {
+ value: _actionView.triggerObjectName
+ onShowBrowser: activeBrowser = _actionView.showTriggerObjectBrowser(
+ mapToGlobal(width, 0));
+ }
+ }
+
+ RowLayout {
+ x: 12
+ StyledLabel {
+ text: qsTr("Event")
+ }
+ BrowserCombo {
+ value: _actionView.eventName
+ onShowBrowser: activeBrowser = _actionView.showEventBrowser(
+ mapToGlobal(width, 0))
+ }
+ }
+ }
+
+ StyledMenuSeparator {
+ visible: actionsList.currentIndex !== -1
+ leftPadding: 12
+ rightPadding: 12
+ }
+
+ Column {
+ visible: actionsList.currentIndex !== -1
+ width: parent.width
+ height: childrenRect.height
+ spacing: 4
+
+ RowLayout {
+ x: 12
+ StyledLabel {
+ text: qsTr("Target Object")
+ }
+
+ BrowserCombo {
+ value: _actionView.targetObjectName
+ onShowBrowser: activeBrowser = _actionView.showTargetObjectBrowser(
+ mapToGlobal(width, 0))
+ }
+ }
+
+ RowLayout {
+ x: 12
+ StyledLabel {
+ text: qsTr("Handler")
+ }
+
+ BrowserCombo {
+ value: _actionView.handlerName
+ onShowBrowser: activeBrowser = _actionView.showHandlerBrowser(
+ mapToGlobal(width, 0))
+ }
+ }
+
+ Component {
+ id: genericHandlerComponent
+
+ HandlerGenericText {
+ label: parent && parent.argument.name ? parent.argument.name : ""
+ value: parent && parent.argument.value ? parent.argument.value : ""
+
+ onEditingFinished: {
+ if (parent)
+ _actionView.setArgumentValue(parent.argument.handle, value)
+ }
+ }
+ }
+
+ Component {
+ id: floatHandlerComponent
+
+ HandlerGenericText {
+ label: parent && parent.argument.name ? parent.argument.name : ""
+ value: parent && parent.argument.value ? parent.argument.value : 0.0
+ validator: DoubleValidator {
+ decimals: 3
+ notation: DoubleValidator.StandardNotation
+ }
+
+ onEditingFinished: {
+ if (parent)
+ _actionView.setArgumentValue(parent.argument.handle, value)
+ }
+ }
+ }
+
+ Component {
+ id: signalHandlerComponent
+
+ HandlerGenericText {
+ label: parent && parent.argument.name ? parent.argument.name : ""
+ value: parent && parent.argument.value ? parent.argument.value : ""
+
+ onEditingFinished: {
+ if (parent)
+ _actionView.setArgumentValue(parent.argument.handle, value);
+ }
+ }
+ }
+
+ Component {
+ id: eventHandlerComponent
+
+ HandlerFireEvent {
+ label: parent && parent.argument.name ? parent.argument.name : ""
+ value: _actionView.firedEvent === "" ? qsTr("[Unknown Event]")
+ : _actionView.firedEvent
+
+ onShowBrowser: {
+ if (parent && parent.argument.handle) {
+ activeBrowser = _actionView.showEventBrowserForArgument(
+ parent.argument.handle, mapToGlobal(width, 0))
+ }
+ }
+ }
+ }
+
+ Component {
+ id: slideHandlerComponent
+
+ HandlerGoToSlide {
+ slideModel: _actionView.slideNames()
+ defaultSlideIndex: parent && parent.argument.value ? _actionView.slideNameToIndex(parent.argument.value)
+ : 0
+
+ onIndexChanged: {
+ if (parent && parent.argument.handle && currentSlide)
+ _actionView.setArgumentValue(parent.argument.handle, currentSlide)
+ }
+ }
+ }
+
+ Component {
+ id: checkboxHandlerComponent
+
+ HandlerGenericCheckbox {
+ label: parent && parent.argument.name ? parent.argument.name : ""
+ checked: parent && parent.argument.value ? parent.argument.value : false
+
+ onClicked: {
+ if (parent && parent.argument.handle)
+ _actionView.setArgumentValue(parent.argument.handle, !checked)
+ }
+ }
+ }
+
+ Component {
+ id: propertyHandlerComponent
+
+ HandlerProperty {
+ propertyModel: _actionView.propertyModel
+ defaultPropertyIndex: propertyModel ? propertyModel.defaultPropertyIndex : 0
+
+ onPropertySelected: {
+ if (parent && parent.argument.handle)
+ _actionView.setCurrentPropertyIndex(parent.argument.handle, index);
+ }
+ }
+ }
+
+ Repeater {
+ model: _actionView.handlerArguments.length
+
+ Loader {
+ x: 12
+
+ readonly property var argument:_actionView.handlerArguments[model.index]
+
+ onLoaded: {
+ // HandlerProperty does its own tab order handling
+ if (argument.type !== HandlerArgumentType.Property) {
+ // Dynamic actions use group 0.
+ // We assume there is always just one tabbable argument per action,
+ // and the rest are dependent types.
+ _tabOrderHandler.clear();
+ if (item.tabItem1 !== undefined) {
+ _tabOrderHandler.addItem(0, item.tabItem1)
+ if (item.tabItem2 !== undefined) {
+ _tabOrderHandler.addItem(0, item.tabItem2)
+ if (item.tabItem3 !== undefined)
+ _tabOrderHandler.addItem(0, item.tabItem3)
+ }
+ }
+ }
+ }
+
+ sourceComponent: {
+ const handlerType = argument.type;
+ switch (handlerType) {
+ case HandlerArgumentType.None:
+ switch (argument.completeType) {
+ case CompleteMetaDataType.Boolean:
+ return checkboxHandlerComponent;
+ case CompleteMetaDataType.Float:
+ return floatHandlerComponent;
+ default:
+ return genericHandlerComponent;
+ }
+ case HandlerArgumentType.Event:
+ return eventHandlerComponent;
+ case HandlerArgumentType.Property:
+ return propertyHandlerComponent;
+ case HandlerArgumentType.Dependent:
+ return null; // no UI for Dependent type, they are the value for a property
+ case HandlerArgumentType.Signal:
+ return signalHandlerComponent;
+ case HandlerArgumentType.Slide:
+ return slideHandlerComponent
+ default: console.warn("KDAB_TODO implement handler for type: ", handlerType)
+ }
+ return null;
+ }
+ }
+ }
+ }
+
+ StyledMenuSeparator {
+ visible: actionsList.count > 0 && actionsList.currentIndex !== -1
+ leftPadding: 12
+ rightPadding: 12
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/EventsBrowser.qml b/src/Authoring/Studio/Palettes/Action/EventsBrowser.qml
new file mode 100644
index 00000000..63973ec7
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/EventsBrowser.qml
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+ border.color: _studioColor3
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ ListView {
+ id: eventsList
+
+ Layout.margins: 10
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.minimumHeight: 80
+ Layout.preferredHeight: count * 20
+ Layout.preferredWidth: root.width
+
+ ScrollBar.vertical: ScrollBar {}
+
+ boundsBehavior: Flickable.StopAtBounds
+ clip: true
+
+ model: _eventsBrowserView.model
+
+ delegate: Item {
+ id: delegateItem
+
+ readonly property bool isCategory: model.isCategory
+
+ x: isCategory ? 0 : 50
+ width: parent.width
+ height: model.parentExpanded ? 30 : 0
+ visible: height > 0
+
+ Behavior on height {
+ NumberAnimation {
+ duration: 100
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ Row {
+ id: row
+
+ height: categoryIcon.height
+ spacing: 5
+
+ Image {
+ source: {
+ if (!delegateItem.isCategory)
+ return "";
+ model.expanded ? _resDir + "arrow_down.png"
+ : _resDir + "arrow.png";
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: model.expanded = !model.expanded
+ }
+ }
+
+ Rectangle {
+ height: name.height
+ width: categoryIcon.width + name.width + 10
+
+ color: model.index === eventsList.currentIndex ? _selectionColor
+ : "transparent"
+
+ Row {
+ id: textRow
+
+ spacing: 10
+ Image {
+ id: categoryIcon
+
+ source: model.icon
+ }
+
+ StyledLabel {
+ id: name
+ anchors.verticalCenter: textRow.verticalCenter
+ text: model.name
+ }
+ }
+
+ MouseArea {
+ id: delegateArea
+
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: eventsList.currentIndex = model.index
+ onEntered: itemDescription.text = model.description
+ onExited: itemDescription.text = ""
+ onDoubleClicked: {
+ eventsList.currentIndex = model.index;
+ _eventsBrowserView.close();
+ }
+ }
+ }
+ }
+
+ }
+ onCurrentIndexChanged: _eventsBrowserView.selection = currentIndex
+ }
+
+ StyledMenuSeparator {
+ bottomPadding: 0
+ }
+
+ Item {
+ Layout.fillWidth: true
+ Layout.preferredHeight: _controlBaseHeight + 4
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 2
+
+ color: _backgroundColor
+
+ StyledLabel {
+ id: itemDescription
+ leftPadding: 6
+ anchors.fill: parent
+ }
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/EventsBrowserView.cpp b/src/Authoring/Studio/Palettes/Action/EventsBrowserView.cpp
new file mode 100644
index 00000000..047a7b82
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/EventsBrowserView.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "EventsBrowserView.h"
+
+#include "CColor.h"
+#include "EventsModel.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "StudioPreferences.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+EventsBrowserView::EventsBrowserView(QWidget *parent) : QQuickWidget(parent)
+{
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &EventsBrowserView::initialize);
+}
+
+QAbstractItemModel *EventsBrowserView::model() const
+{
+ return m_model;
+}
+
+void EventsBrowserView::setModel(EventsModel *model)
+{
+ if (m_model != model) {
+ m_model = model;
+ Q_EMIT modelChanged();
+ }
+}
+
+QSize EventsBrowserView::sizeHint() const
+{
+ return {500, 500};
+}
+
+UICDM::CDataModelHandle EventsBrowserView::selectedHandle() const
+{
+ const auto handleId = m_model->handleForRow(m_selection);
+ return handleId;
+}
+
+void EventsBrowserView::setSelection(int index)
+{
+ auto handleId = m_model->handleForRow(index);
+ if (!handleId.Valid()) {
+ m_selection = -1;
+ Q_EMIT selectionChanged();
+ } else if (m_selection != index) {
+ m_selection = index;
+ Q_EMIT selectionChanged();
+ }
+}
+
+void EventsBrowserView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ QTimer::singleShot(0, this, &EventsBrowserView::close);
+}
+
+void EventsBrowserView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_eventsBrowserView"_L1, this);
+ rootContext()->setContextProperty("_resDir"_L1,
+ resourceImageUrl());
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Action/EventsBrowser.qml"_L1));
+}
+
diff --git a/src/Authoring/Studio/Palettes/Action/EventsBrowserView.h b/src/Authoring/Studio/Palettes/Action/EventsBrowserView.h
new file mode 100644
index 00000000..3902ca12
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/EventsBrowserView.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef EVENTSBROWSERVIEW_H
+#define EVENTSBROWSERVIEW_H
+
+#include <QQuickWidget>
+
+#include "UICDMHandles.h"
+
+class EventsModel;
+
+class QAbstractItemModel;
+
+class EventsBrowserView : public QQuickWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractItemModel *model READ model NOTIFY modelChanged FINAL)
+ Q_PROPERTY(int selection READ selection WRITE setSelection NOTIFY selectionChanged FINAL)
+public:
+ explicit EventsBrowserView(QWidget *parent = nullptr);
+
+ QAbstractItemModel *model() const;
+ void setModel(EventsModel *model);
+ QSize sizeHint() const override;
+ UICDM::CDataModelHandle selectedHandle() const;
+
+ int selection() const { return m_selection; }
+ void setSelection(int index);
+
+Q_SIGNALS:
+ void modelChanged();
+ void selectionChanged();
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+private:
+ void initialize();
+ EventsModel *m_model = nullptr;
+ QColor m_baseColor = QColor::fromRgb(75, 75, 75);
+ QColor m_selectColor;
+ int m_selection = -1;
+};
+
+#endif // EVENTSBROWSERVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Action/EventsModel.cpp b/src/Authoring/Studio/Palettes/Action/EventsModel.cpp
new file mode 100644
index 00000000..aa14ad81
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/EventsModel.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EventsModel.h"
+
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioUtils.h"
+#include "StudioApp.h"
+#include "UICDMStudioSystem.h"
+
+EventsModel::EventsModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+void EventsModel::setEventList(const UICDM::TEventHandleList &eventList)
+{
+ beginResetModel();
+
+ m_rowCount = 0;
+ m_events.clear();
+ m_categories.clear();
+
+ auto studioSystem = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+ auto theBridge = studioSystem->GetClientDataModelBridge();
+ auto thePos = eventList.begin();
+ for (; thePos != eventList.end(); ++thePos) {
+ UICDM::SEventInfo theEvent = theBridge->GetEventInfo(*thePos);
+
+ CategoryInfo category;
+ category.name = QString::fromWCharArray(theEvent.m_Category.wide_str());
+ if (!m_events.contains(category.name)) {
+ UICDM::SCategoryInfo theCategoryMetaData = studioSystem->GetActionMetaData()
+ ->GetEventCategory(theEvent.m_Category);
+ category.icon = QString::fromWCharArray(theCategoryMetaData.m_Icon.wide_str());
+ category.highlightIcon = QString::fromWCharArray(theCategoryMetaData.m_HighlightIcon.wide_str());
+ category.description = QString::fromWCharArray(theCategoryMetaData.m_Description.wide_str());
+ m_categories.append(category);
+ m_rowCount++;
+ }
+
+ EventInfo eventInfo;
+ // Use the formal name to display, but if the formal name is not set, use the name instead
+ eventInfo.name = QString::fromWCharArray(theEvent.m_FormalName.wide_str());
+ if (eventInfo.name.isEmpty())
+ eventInfo.name = QString::fromWCharArray(theEvent.m_Name.wide_str());
+ eventInfo.handle = *thePos;
+
+ eventInfo.description = QString::fromWCharArray(theEvent.m_Description.wide_str());
+ m_events[category.name].append(eventInfo);
+ m_rowCount++;
+
+ //KDAB_TODO set the selection to the current event
+ }
+
+ endResetModel();
+}
+
+void EventsModel::setHandlerList(const UICDM::THandlerHandleList &handlerList)
+{
+ beginResetModel();
+ m_rowCount = 0;
+ m_events.clear();
+ m_categories.clear();
+
+ auto studioSystem = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+ auto theBridge = studioSystem->GetClientDataModelBridge();
+ auto thePos = handlerList.begin();
+ for (; thePos != handlerList.end(); ++thePos) {
+ UICDM::SHandlerInfo handlerInfo = theBridge->GetHandlerInfo(*thePos);
+
+ CategoryInfo category;
+ category.name = QString::fromWCharArray(handlerInfo.m_Category.wide_str());
+ if (!m_events.contains(category.name)) {
+ UICDM::SCategoryInfo theCategoryMetaData = studioSystem->GetActionMetaData()
+ ->GetHandlerCategory(handlerInfo.m_Category);
+ category.icon = QString::fromWCharArray(theCategoryMetaData.m_Icon.wide_str());
+ category.highlightIcon = QString::fromWCharArray(theCategoryMetaData.m_HighlightIcon.wide_str());
+ category.description = QString::fromWCharArray(theCategoryMetaData.m_Description.wide_str());
+ m_categories.append(category);
+ m_rowCount++;
+ }
+
+ EventInfo eventInfo;
+ // Use the formal name to display, but if the formal name is not set, use the name instead
+ eventInfo.name = QString::fromWCharArray(handlerInfo.m_FormalName.wide_str());
+ if (eventInfo.name.isEmpty())
+ eventInfo.name = QString::fromWCharArray(handlerInfo.m_Name.wide_str());
+ eventInfo.handle = *thePos;
+
+ eventInfo.description = QString::fromWCharArray(handlerInfo.m_Description.wide_str());
+ m_events[category.name].append(eventInfo);
+ m_rowCount++;
+
+ //KDAB_TODO set the selection to the current event
+ }
+
+ endResetModel();
+}
+
+int EventsModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_rowCount;
+}
+
+QVariant EventsModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ return {};
+
+ const auto row = index.row();
+ auto category = categoryForRow(row);
+
+ bool isCategory = category.isValid();
+ EventInfo event;
+ if (!isCategory)
+ event = eventForRow(row);
+
+ switch (role) {
+ case NameRole:
+ return isCategory ? category.name : event.name;
+ case DescriptionRole:
+ return isCategory ? category.description: event.description;
+ case IconRole:
+ return isCategory ? resourceImageUrl() + category.icon : "";
+ case HighlightedIconRole:
+ return isCategory ? resourceImageUrl() + category.highlightIcon : "";
+ case ExpandedRole:
+ return isCategory ? category.expanded : false;
+ case ParentExpandedRole: {
+ if (isCategory)
+ return true;
+ for (int i = row - 1; i >= 0; i--) {
+ auto parentCategory = categoryForRow(i);
+ if (parentCategory.isValid())
+ return parentCategory.expanded;
+ }
+ return false;
+ }
+ case IsCategoryRole:
+ return isCategory;
+ }
+
+ return QVariant();
+}
+
+bool EventsModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (role == ExpandedRole) {
+ int catRow = categoryRowForRow(index.row());
+ if (catRow != -1) {
+ auto category = &m_categories[catRow];
+ category->expanded = value.toBool();
+ Q_EMIT dataChanged(this->index(0, 0), this->index(rowCount() - 1, 0), {});
+ return true;
+ }
+ }
+ return false;
+}
+
+QHash<int, QByteArray> EventsModel::roleNames() const
+{
+ auto names = QAbstractItemModel::roleNames();
+ names.insert(NameRole, "name");
+ names.insert(DescriptionRole, "description");
+ names.insert(IconRole, "icon");
+ names.insert(HighlightedIconRole, "highlightedIcon");
+ names.insert(IsCategoryRole, "isCategory");
+ names.insert(ExpandedRole, "expanded");
+ names.insert(ParentExpandedRole, "parentExpanded");
+
+ return names;
+}
+
+UICDM::CDataModelHandle EventsModel::handleForRow(int row) const
+{
+ if (row < 0 || row >= m_rowCount)
+ return {};
+
+ auto event = eventForRow(row);
+ if (event.isValid())
+ return event.handle;
+
+ return {};
+}
+
+EventsModel::CategoryInfo EventsModel::categoryForRow(int row) const
+{
+ int i = 0;
+ for (const auto &category: m_categories) {
+ if (i == row)
+ return category;
+ i += m_events[category.name].size();
+ i++;
+ }
+
+ return {};
+}
+
+int EventsModel::categoryRowForRow(int row) const
+{
+ int i = 0;
+ int catRow = 0;
+ for (const auto &category: m_categories) {
+ if (i == row)
+ return catRow;
+ i += m_events[category.name].size();
+ i++;
+ catRow++;
+ }
+
+ return -1;
+}
+
+EventsModel::EventInfo EventsModel::eventForRow(int row) const
+{
+ if (row == 0) // first line is not an event, but a category
+ return {};
+
+ int i = 0;
+ for (const auto &category: m_categories) {
+ i++;
+ const auto events = m_events[category.name];
+ const int index = (row - i);
+ if (row < i + events.size() && (index >= 0) ) {
+ return events[index];
+ }
+ i += events.size();
+ }
+
+ return {};
+}
diff --git a/src/Authoring/Studio/Palettes/Action/EventsModel.h b/src/Authoring/Studio/Palettes/Action/EventsModel.h
new file mode 100644
index 00000000..ef458877
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/EventsModel.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EVENTSMODEL_H
+#define EVENTSMODEL_H
+
+#include <QAbstractListModel>
+
+#include "UICDMHandles.h"
+
+/** Model for both action events and action handlers */
+class EventsModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit EventsModel(QObject *parent = nullptr);
+
+ void setEventList(const UICDM::TEventHandleList &eventList);
+ void setHandlerList(const UICDM::THandlerHandleList &handlerList);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role = Qt::EditRole) override;
+
+ enum Roles {
+ NameRole = Qt::DisplayRole,
+ DescriptionRole = Qt::UserRole + 1,
+ IconRole,
+ HighlightedIconRole,
+ ExpandedRole,
+ ParentExpandedRole,
+ IsCategoryRole
+ };
+
+ QHash<int, QByteArray> roleNames() const override;
+
+ UICDM::CDataModelHandle handleForRow(int row) const;
+
+private:
+ struct EventInfo {
+ UICDM::CDataModelHandle handle;
+ QString name;
+ QString description;
+
+ bool isValid() const { return handle.Valid(); }
+ };
+
+ struct CategoryInfo {
+ QString name;
+ QString icon;
+ QString description;
+ QString highlightIcon;
+ bool expanded = true;
+
+ bool isValid() const { return !name.isEmpty(); }
+ };
+
+ CategoryInfo categoryForRow(int row) const;
+ int categoryRowForRow(int row) const;
+ EventInfo eventForRow(int row) const;
+
+ QHash<QString, QVector<EventInfo> > m_events;
+ QVector<CategoryInfo> m_categories;
+ int m_rowCount = 0;
+};
+
+#endif // EVENTSMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerEmitSignal.qml b/src/Authoring/Studio/Palettes/Action/HandlerEmitSignal.qml
new file mode 100644
index 00000000..5917a9bd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerEmitSignal.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias value: textField.text
+ property Item tabItem1: textfield
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("Signal Name")
+ }
+
+ StyledTextField {
+ id: textField
+ Layout.preferredWidth: _valueWidth
+ }
+}
+
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerFireEvent.qml b/src/Authoring/Studio/Palettes/Action/HandlerFireEvent.qml
new file mode 100644
index 00000000..e92d2265
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerFireEvent.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias value: comboField.value
+ property alias activeBrowser: comboField.activeBrowser
+
+ signal showBrowser
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("Event")
+ }
+
+ BrowserCombo {
+ id: comboField
+ Layout.preferredWidth: _valueWidth
+ value: qsTr("[Unknown Event]")
+ onShowBrowser: root.showBrowser()
+ }
+}
+
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerGenericBaseColor.qml b/src/Authoring/Studio/Palettes/Action/HandlerGenericBaseColor.qml
new file mode 100644
index 00000000..dbe097cb
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerGenericBaseColor.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Dialogs 1.2
+import QtQuick.Layouts 1.3
+
+RowLayout {
+ id: root
+
+ property alias color: rect.color
+ property alias selectedColor: colorDialog.color
+
+ signal colorSelected()
+
+ Rectangle {
+ id: rect
+
+ width: _valueWidth / 4
+ height: _controlBaseHeight
+
+ border {
+ width: 1
+ color: _studioColor2
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ onClicked: colorDialog.open()
+ }
+
+ Image {
+ id: img
+ x: parent.width - sourceSize.width - 3
+ y: (parent.height - sourceSize.height) / 2
+ source: _resDir + "arrow_down.png"
+ }
+ }
+
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ ColorDialog {
+ id: colorDialog
+
+ color: rect.color
+
+ onAccepted: root.colorSelected()
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerGenericCheckbox.qml b/src/Authoring/Studio/Palettes/Action/HandlerGenericCheckbox.qml
new file mode 100644
index 00000000..4b3b0ba4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerGenericCheckbox.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property bool checked: false
+ property alias label: labelField.text
+
+ signal clicked()
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("Pause")
+ }
+
+ Image {
+ source: _resDir + (checked ? "checkbox-checked.png" : "checkbox-unchecked.png")
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.clicked()
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerGenericColor.qml b/src/Authoring/Studio/Palettes/Action/HandlerGenericColor.qml
new file mode 100644
index 00000000..378aa7b0
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerGenericColor.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias color: handlerGenericColor.color
+ property alias selectedColor: handlerGenericColor.selectedColor
+
+ signal colorSelected()
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("New Value")
+ }
+
+ HandlerGenericBaseColor {
+ id: handlerGenericColor
+
+ onColorSelected: root.colorSelected();
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerGenericText.qml b/src/Authoring/Studio/Palettes/Action/HandlerGenericText.qml
new file mode 100644
index 00000000..e33e170f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerGenericText.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias value: textField.text
+ property alias validator: textField.validator
+ property Item tabItem1: textField
+
+ signal editingFinished()
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("Argument")
+ }
+
+ StyledTextField {
+ id: textField
+ onEditingFinished: root.editingFinished()
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerGoToSlide.qml b/src/Authoring/Studio/Palettes/Action/HandlerGoToSlide.qml
new file mode 100644
index 00000000..ef76dfcb
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerGoToSlide.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias slideModel: comboSlide.model
+ property string currentSlide
+ property int defaultSlideIndex: 0
+
+ signal indexChanged()
+
+ onDefaultSlideIndexChanged: comboSlide.currentIndex = defaultSlideIndex
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("Slide")
+ }
+
+ StyledComboBox {
+ id: comboSlide
+ Layout.preferredWidth: _valueWidth
+ model: slideModel
+
+ onCurrentIndexChanged: {
+ currentSlide = comboSlide.textAt(currentIndex);
+ indexChanged();
+ }
+ }
+}
+
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerMultilineText.qml b/src/Authoring/Studio/Palettes/Action/HandlerMultilineText.qml
new file mode 100644
index 00000000..2c7704a4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerMultilineText.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias value: textArea.text
+ property Item tabItem1: textArea
+
+ signal editingFinished()
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("Argument")
+ }
+
+ Flickable {
+ Layout.preferredWidth: _valueWidth
+ Layout.preferredHeight: textArea.height
+
+ ScrollBar.vertical: ScrollBar {}
+
+ TextArea.flickable: TextArea {
+ id: textArea
+
+ horizontalAlignment: TextInput.AlignLeft
+ verticalAlignment: TextInput.AlignVCenter
+ implicitWidth: _valueWidth
+ font.pixelSize: _fontSize
+ color: _textColor
+
+ topPadding: 6
+ bottomPadding: 6
+ rightPadding: 6
+
+ wrapMode: TextArea.Wrap
+ background: Rectangle {
+ color: textArea.enabled ? _studioColor2 : "transparent"
+ border.width: textArea.activeFocus ? 1 : 0
+ border.color: textArea.activeFocus ? _selectionColor : _disabledColor
+ }
+
+ onEditingFinished: root.editingFinished()
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ onPressed: parent.forceActiveFocus()
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerProperty.qml b/src/Authoring/Studio/Palettes/Action/HandlerProperty.qml
new file mode 100644
index 00000000..52d6265a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerProperty.qml
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.2
+import QtQuick.Layouts 1.3
+import Qt3DStudio 1.0
+import "../controls"
+
+ColumnLayout {
+ id: root
+
+ property alias propertyModel: propertyCombo.model
+ property int defaultPropertyIndex: 0
+
+ signal propertySelected(int index)
+
+ onDefaultPropertyIndexChanged: propertyCombo.currentIndex = defaultPropertyIndex
+
+ RowLayout {
+
+ Layout.fillWidth: true
+
+ StyledLabel {
+ text: qsTr("Property")
+ }
+
+ StyledComboBox {
+ id: propertyCombo
+ textRole: "name"
+ onCurrentIndexChanged: root.propertySelected(currentIndex)
+ onModelChanged: currentIndex = root.defaultPropertyIndex
+ }
+ }
+
+ Component {
+ id: multiLineComponent
+
+ HandlerMultilineText {
+ readonly property var actionProperty: parent ? _actionView.property : null
+
+ label: parent ? parent.label : ""
+ value: propertyModel && actionProperty && actionProperty.type === DataModelDataType.String
+ ? propertyModel.value : ""
+ onEditingFinished: _actionView.setArgumentValue(propertyModel.valueHandle, value)
+ }
+ }
+
+ Component {
+ id: fontSizeComponent
+
+ HandlerPropertyCombo {
+ readonly property var actionProperty: parent ? _actionView.property : null
+
+ label: parent ? parent.label : ""
+ comboModel: ["8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "72", "96", "120"];
+
+ onValueChanged: _actionView.setArgumentValue(propertyModel.valueHandle, value)
+ }
+ }
+
+ Component {
+ id: xyzPropertyComponent
+
+ HandlerPropertyXYZ {
+ readonly property var propValue: propertyModel && propertyModel.value.x ?
+ propertyModel.value
+ : undefined
+ label: parent ? parent.label : ""
+ valueX: propValue !== undefined ? propValue.x : 0
+ valueY: propValue !== undefined ? propValue.y : 0
+ valueZ: propValue !== undefined ? propValue.z : 0
+
+ onEditingFinished: _actionView.setArgumentValue(propertyModel.valueHandle,
+ Qt.vector3d(valueX, valueY, valueZ))
+ }
+ }
+
+ Component {
+ id: sliderPropertyComponent
+
+ HandlerPropertySlider {
+ readonly property var actionProperty: parent ? _actionView.property : null
+
+ sliderMin: actionProperty ? actionProperty.min : 0
+ sliderMax: actionProperty ? actionProperty.max : 100
+ intSlider: actionProperty ? actionProperty.type === DataModelDataType.Long : false
+ value: propertyModel ? propertyModel.value : 0
+
+ label: parent ? parent.label : ""
+
+ onValueChanged: _actionView.setArgumentValue(propertyModel.valueHandle, value)
+ }
+ }
+
+ Component {
+ id: comboPropertyComponent
+
+ HandlerPropertyCombo {
+ readonly property var actionProperty: parent ? _actionView.property : null
+
+ label: parent ? parent.label : ""
+ comboModel: actionProperty ? actionProperty.possibleValues : null
+
+ onValueChanged: _actionView.setArgumentValue(propertyModel.valueHandle, value)
+
+ }
+ }
+
+ Component {
+ id: booleanComponent
+
+ HandlerGenericCheckbox {
+ label: parent ? parent.label : ""
+ checked: propertyModel ? propertyModel.value : false
+
+ onClicked: {
+ _actionView.setArgumentValue(propertyModel.valueHandle, !checked)
+ }
+ }
+ }
+
+ Component {
+ id: colorBox
+
+ HandlerGenericColor {
+ readonly property var propValue: propertyModel ? propertyModel.value : undefined
+
+ label: parent ? parent.label : ""
+ color: propValue ? Qt.rgba(propValue.x, propValue.y, propValue.z, 1) : "black"
+ onColorSelected: {
+ _actionView.setArgumentValue(propertyModel.valueHandle, selectedColor)
+ }
+ }
+ }
+
+ Component {
+ id: genericTextComponent
+
+ HandlerGenericText {
+ label: parent ? parent.label : ""
+ value: propertyModel ? propertyModel.value : ""
+ onEditingFinished: _actionView.setArgumentValue(propertyModel.valueHandle, value)
+ }
+ }
+
+ Component {
+ id: floatPropertyComponent
+
+ HandlerGenericText {
+ label: parent ? parent.label : ""
+ value: propertyModel ? propertyModel.value : ""
+ validator: DoubleValidator {
+ decimals: 3
+ notation: DoubleValidator.StandardNotation
+ }
+
+ onEditingFinished: _actionView.setArgumentValue(propertyModel.valueHandle, value)
+ }
+ }
+
+ Loader {
+ readonly property string label: qsTr("New Value")
+ readonly property var actionProperty: _actionView.property
+
+ Layout.fillWidth: true
+
+ onLoaded: {
+ _tabOrderHandler.clear();
+ if (item.tabItem1 !== undefined) {
+ _tabOrderHandler.addItem(0, item.tabItem1)
+ if (item.tabItem2 !== undefined) {
+ _tabOrderHandler.addItem(0, item.tabItem2)
+ if (item.tabItem3 !== undefined)
+ _tabOrderHandler.addItem(0, item.tabItem3)
+ }
+ }
+ }
+
+ sourceComponent: {
+ // KDAB_TODO Handle additionaltype
+ switch (actionProperty.type) {
+ case DataModelDataType.Float:
+ switch (actionProperty.additionalType) {
+ case AdditionalMetaDataType.FontSize:
+ return fontSizeComponent;
+ case AdditionalMetaDataType.Range:
+ return sliderPropertyComponent;
+ default:
+ return floatPropertyComponent;
+ }
+ case DataModelDataType.Long:
+ return sliderPropertyComponent;
+ case DataModelDataType.Float3:
+ switch (actionProperty.additionalType) {
+ case AdditionalMetaDataType.None:
+ case AdditionalMetaDataType.Rotation:
+ return xyzPropertyComponent;
+ case AdditionalMetaDataType.Color:
+ return colorBox;
+ default:
+ console.warn("KDAB_TODO implement property handler for additional typeDataModelDataType.Float3: ", actionProperty.additionalType);
+ return xyzPropertyComponent;
+ }
+ case DataModelDataType.String:
+ switch (actionProperty.additionalType) {
+ case AdditionalMetaDataType.StringList:
+ return comboPropertyComponent;
+ case AdditionalMetaDataType.MultiLine:
+ return multiLineComponent;
+ case AdditionalMetaDataType.Font:
+ return comboPropertyComponent;
+ case AdditionalMetaDataType.Import:
+ case AdditionalMetaDataType.Renderable:
+ return genericTextComponent;
+ default:
+ console.warn("KDAB_TODO implement property handler for additional type: ", actionProperty.additionalType)
+ return null;
+ }
+ case DataModelDataType.Bool:
+ return booleanComponent;
+ case DataModelDataType.None:
+ return null;
+ default: console.warn("KDAB_TODO implement property handler for type: ", actionProperty.type)
+
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseSlider.qml b/src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseSlider.qml
new file mode 100644
index 00000000..8fcf3511
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseSlider.qml
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+/*
+* Use for: Opacity, Edge Tesselation Value, Inner Tesselation Value ...
+* For the latter two set sliderMax to 64
+*/
+
+Row {
+ id: root
+
+ property alias value: slider.value
+ property int intValue: slider.value
+ property alias sliderMin: slider.from
+ property alias sliderMax: slider.to
+ property bool intSlider: false
+ property int decimalSlider: 3
+ property Item tabItem1: textField
+
+ signal editingFinished
+ signal sliderMoved
+ signal editingStarted
+
+ spacing: 5
+ width: _valueWidth
+
+ Slider {
+ id: slider
+
+ leftPadding: 0
+
+ background: Rectangle {
+ x: slider.leftPadding
+ y: slider.topPadding + slider.availableHeight / 2 - height / 2
+ implicitWidth: _valueWidth / 2 - 5
+ implicitHeight: 6
+ height: implicitHeight
+ radius: 2
+ color: _studioColor2
+ }
+ handle: Rectangle {
+ x: slider.leftPadding + slider.visualPosition * slider.availableWidth
+ y: slider.topPadding + slider.availableHeight / 2 - height / 2
+ implicitWidth: 6
+ implicitHeight: 12
+ color: _studioColor3
+ radius: 2
+ }
+
+ from: 0
+ to: 100
+ stepSize: 2
+
+ onMoved: {
+ if (!rateLimiter.running) {
+ rateLimiter.start();
+ }
+ }
+
+ onPressedChanged: {
+ if (pressed)
+ root.editingStarted();
+ else
+ root.editingFinished();
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton
+
+ onWheel: {
+ var delta = (wheel.angleDelta.x != 0) ? wheel.angleDelta.x
+ : wheel.angleDelta.y;
+
+ if (delta > 0) {
+ slider.increase();
+ } else {
+ slider.decrease();
+ }
+ if (!rateLimiter.running) {
+ rateLimiter.start();
+ }
+ }
+ }
+ }
+
+ Timer {
+ id: rateLimiter
+ interval: 50
+ onTriggered: {
+ root.sliderMoved();
+ }
+ }
+
+ DoubleValidator {
+ id: doubleValidator
+
+ decimals: decimalSlider
+ bottom: slider.from
+ top: slider.to
+ locale: "C"
+ }
+
+ IntValidator {
+ id: intValidator
+
+ bottom: slider.from
+ top: slider.to
+ }
+
+ StyledTextField {
+ id: textField
+
+ height: _controlBaseHeight
+ width: _valueWidth / 2
+ text: intSlider ? slider.value.toFixed(0) : slider.value.toFixed(decimalSlider)
+
+ validator: intSlider ? intValidator : doubleValidator
+
+ onActiveFocusChanged: {
+ if (activeFocus)
+ root.editingStarted();
+ }
+
+ onEditingFinished: {
+ if (textField.text > sliderMax)
+ textField.text = sliderMax
+ else if (textField.text < sliderMin)
+ textField.text = sliderMin
+ slider.value = textField.text
+ root.editingFinished()
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseXYZ.qml b/src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseXYZ.qml
new file mode 100644
index 00000000..fcabf271
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerPropertyBaseXYZ.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+/* Use for: Position, Rotation, Scale, Pivot ... */
+
+GridLayout {
+ id: root
+
+ property alias valueX: textFieldX.text
+ property alias valueY: textFieldY.text
+ property alias valueZ: textFieldZ.text
+ property int numberOfDecimal: 3
+ property Item tabItem1: textFieldX
+ property Item tabItem2: textFieldY
+ property Item tabItem3: textFieldZ
+
+ columns: 2
+ rowSpacing: 1
+
+ signal editingFinished
+
+ StyledLabel {
+ Layout.preferredWidth: 10
+ text: qsTr("X")
+ }
+
+ FloatTextField {
+ id: textFieldX
+
+ decimalValue: numberOfDecimal
+ onEditingFinished: root.editingFinished()
+ onWheelEventFinished: root.editingFinished()
+ }
+
+ StyledLabel {
+ Layout.preferredWidth: 10
+ text: qsTr("Y")
+ }
+
+ FloatTextField {
+ id: textFieldY
+
+ decimalValue: numberOfDecimal
+ onEditingFinished: root.editingFinished()
+ onWheelEventFinished: root.editingFinished()
+ }
+
+ StyledLabel {
+ Layout.preferredWidth: 10
+ text: qsTr("Z")
+ }
+
+ FloatTextField {
+ id: textFieldZ
+
+ decimalValue: numberOfDecimal
+ onEditingFinished: root.editingFinished()
+ onWheelEventFinished: root.editingFinished()
+ }
+}
+
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerPropertyCombo.qml b/src/Authoring/Studio/Palettes/Action/HandlerPropertyCombo.qml
new file mode 100644
index 00000000..1e60cf44
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerPropertyCombo.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+/* Use for Tesselation mode, Horizontal alignment, Vertical alignment ... */
+
+RowLayout {
+ id: root
+
+ property alias label: labelField.text
+ property alias comboModel : comboBox.model
+ property alias comboTextRole: comboBox.textRole
+ property string value
+
+ StyledLabel {
+ id: labelField
+ text: qsTr("New Value")
+ }
+
+ StyledComboBox {
+ id: comboBox
+
+ Layout.fillWidth: true
+ onCurrentIndexChanged: value = comboBox.textAt(currentIndex)
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerPropertySlider.qml b/src/Authoring/Studio/Palettes/Action/HandlerPropertySlider.qml
new file mode 100644
index 00000000..aecdcfd4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerPropertySlider.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+/*
+* Use for: Opacity, Edge Tesselation Value, Inner Tesselation Value ...
+* For the latter two set sliderMax to 64
+*/
+
+GridLayout {
+ id: root
+
+ property alias value: propertySlider.value
+ property alias sliderMin: propertySlider.sliderMin
+ property alias sliderMax: propertySlider.sliderMax
+ property alias label: labelItem.text
+ property bool intSlider: propertySlider.intSlider
+ property int decimalSlider: propertySlider.decimalSlider
+ property alias tabItem1: propertySlider.tabItem1
+
+ signal editingFinished
+
+ columns: 3
+
+ StyledLabel {
+ id: labelItem
+ text: label
+ }
+
+ HandlerPropertyBaseSlider {
+ id: propertySlider
+ // proxy the signal upwards
+ onEditingFinished: root.editingFinished()
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/HandlerPropertyXYZ.qml b/src/Authoring/Studio/Palettes/Action/HandlerPropertyXYZ.qml
new file mode 100644
index 00000000..eef611ce
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/HandlerPropertyXYZ.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+/* Use for: Position, Rotation, Scale, Pivot ... */
+
+RowLayout {
+ id: root
+
+ property alias valueX: propertyXYZ.valueX
+ property alias valueY: propertyXYZ.valueY
+ property alias valueZ: propertyXYZ.valueZ
+ property alias label: labelItem.text
+ property alias tabItem1: propertyXYZ.tabItem1
+ property alias tabItem2: propertyXYZ.tabItem2
+ property alias tabItem3: propertyXYZ.tabItem3
+
+ signal editingFinished
+
+ StyledLabel {
+ id: labelItem
+ Layout.alignment: Qt.AlignTop | Qt.AlignLeft
+ text: qsTr("New Value")
+ }
+
+ HandlerPropertyBaseXYZ {
+ id: propertyXYZ
+ Layout.alignment: Qt.AlignRight
+
+ onEditingFinished: {
+ root.editingFinished();
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/PropertyModel.cpp b/src/Authoring/Studio/Palettes/Action/PropertyModel.cpp
new file mode 100644
index 00000000..5ee896c8
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/PropertyModel.cpp
@@ -0,0 +1,219 @@
+#include "PropertyModel.h"
+
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+
+#include "UICDMActionCore.h"
+#include "UICDMActionInfo.h"
+#include "UICDMDataCore.h"
+#include "UICDMMetaData.h"
+#include "UICDMStudioSystem.h"
+
+
+PropertyModel::PropertyModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+void PropertyModel::setAction(const UICDM::CUICDMActionHandle &action)
+{
+ beginResetModel();
+ m_action = action;
+ m_valueHandle = 0;
+ m_nameHandle = 0;
+ m_properties.clear();
+
+ if (action.Valid()) {
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ auto studioSystem = doc->GetStudioSystem();
+ auto propertySystem = studioSystem->GetPropertySystem();
+ auto bridge = studioSystem->GetClientDataModelBridge();
+
+ auto actionInfo = studioSystem->GetActionCore()->GetActionInfo(action);
+
+ UICDM::IMetaData &metaData(*studioSystem->GetActionMetaData());
+ UICDM::TMetaDataPropertyHandleList metaProperties;
+ const auto instance = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+ metaData.GetMetaDataProperties(instance, metaProperties);
+
+ for (const auto &metaProperty: metaProperties) {
+ auto propertyMetaInfo = metaData.GetMetaDataPropertyInfo(metaProperty);
+ if (propertyMetaInfo->m_IsHidden == false) {
+ PropertyInfo property;
+ property.m_handle = propertyMetaInfo->m_Property;
+ property.m_name = QString::fromWCharArray(propertySystem->GetFormalName(instance, property.m_handle).wide_str());
+ property.m_nameId = QString::fromWCharArray(propertySystem->GetName(property.m_handle).wide_str());
+ property.m_type = propertyMetaInfo->GetDataType();
+ property.m_additionalType = propertyMetaInfo->GetAdditionalType();
+
+ const auto additionalMetaDataType = propertySystem->GetAdditionalMetaDataType(instance, property.m_handle);
+ switch (additionalMetaDataType) {
+ case UICDM::AdditionalMetaDataType::Range: {
+ const UICDM::TMetaDataData &metaDataData =
+ propertySystem->GetAdditionalMetaDataData(instance, property.m_handle);
+ UICDM::SMetaDataRange minMax = UICDM::get<UICDM::SMetaDataRange>(metaDataData);
+ property.m_min = minMax.m_Min;
+ property.m_max = minMax.m_Max;
+ break;
+ }
+ case UICDM::AdditionalMetaDataType::StringList: {
+ const UICDM::TMetaDataData &metaDataData =
+ propertySystem->GetAdditionalMetaDataData(instance, property.m_handle);
+ auto values = UICDM::get<UICDM::TMetaDataStringList>(metaDataData);
+ QStringList possibleValues;
+ for (const auto &value: values) {
+ possibleValues.append(QString::fromWCharArray(value.wide_str()));
+ }
+ property.m_possibleValues = possibleValues;
+ break;
+ }
+ case UICDM::AdditionalMetaDataType::Font: {
+ std::vector<Q3DStudio::CString> fontNames;
+ doc->GetProjectFonts(fontNames);
+ QStringList possibleValues;
+ for (const auto &fontName: fontNames) {
+ possibleValues.append(fontName.toQString());
+ }
+ property.m_possibleValues = possibleValues;
+ break;
+ }
+ default:;
+ }
+ m_properties.append(property);
+ }
+ }
+ }
+ endResetModel();
+
+ Q_EMIT valueHandleChanged();
+}
+
+void PropertyModel::setNameHandle(const UICDM::CUICDMHandlerArgHandle &handle)
+{
+ m_nameHandle = handle;
+}
+
+void PropertyModel::setValueHandle(const UICDM::CUICDMHandlerArgHandle &handle)
+{
+ m_valueHandle = handle;
+
+ updateDefaultPropertyIndex();
+ updateValue();
+ if (m_valueHandle != handle)
+ Q_EMIT valueHandleChanged();
+}
+
+int PropertyModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_properties.size();
+}
+
+
+QVariant PropertyModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ return {};
+
+ const auto property = m_properties.at(index.row());
+
+ switch (role)
+ {
+ case NameRole:
+ return property.m_name;
+ case HandleRole:
+ return property.m_handle.GetHandleValue();
+
+ default:
+ return {};
+ }
+
+ return QVariant();
+}
+
+QHash<int, QByteArray> PropertyModel::roleNames() const
+{
+ auto names = QAbstractItemModel::roleNames();
+ names.insert(NameRole, "name");
+ names.insert(HandleRole, "handle");
+
+ return names;
+}
+
+PropertyInfo PropertyModel::property(int index) const
+{
+ if (index < 0 || index >= m_properties.size() )
+ return {};
+ return m_properties[index];
+}
+
+int PropertyModel::valueHandle() const
+{
+ return m_valueHandle;
+}
+
+QVariant PropertyModel::value() const
+{
+ return m_value;
+}
+
+void PropertyModel::updateDefaultPropertyIndex()
+{
+ if (!m_nameHandle.Valid()) {
+ m_defaultPropertyIndex = -1;
+ Q_EMIT defaultPropertyIndexChanged();
+ return;
+ }
+
+ UICDM::SValue sValue;
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ auto studioSystem = doc->GetStudioSystem();
+ studioSystem->GetActionCore()->GetHandlerArgumentValue(m_nameHandle, sValue);
+
+ if (sValue.getType() != UICDM::DataModelDataType::String) {
+ m_defaultPropertyIndex = -1;
+ Q_EMIT defaultPropertyIndexChanged();
+ return;
+ }
+
+ auto propertyName = UICDM::get<QString>(sValue);
+ auto iter = std::find_if(m_properties.constBegin(), m_properties.constEnd(),
+ [&propertyName](const PropertyInfo &info)
+ {
+ return (info.m_nameId == propertyName);
+ });
+
+ auto index = std::distance(m_properties.constBegin(), iter);
+
+ if (m_defaultPropertyIndex != index) {
+ m_defaultPropertyIndex = index;
+ Q_EMIT defaultPropertyIndexChanged();
+ }
+}
+
+int PropertyModel::defaultPropertyIndex() const
+{
+ return m_defaultPropertyIndex;
+}
+
+void PropertyModel::updateValue()
+{
+ const auto oldValue = m_value;
+ if (!m_valueHandle.Valid()) {
+ m_value.clear();
+ } else {
+ UICDM::SValue sValue;
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ auto studioSystem = doc->GetStudioSystem();
+ studioSystem->GetActionCore()->GetHandlerArgumentValue(m_valueHandle, sValue);
+ m_value = sValue.toQVariant();
+ }
+ if (oldValue != m_value) {
+
+ Q_EMIT valueChanged();
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Action/PropertyModel.h b/src/Authoring/Studio/Palettes/Action/PropertyModel.h
new file mode 100644
index 00000000..293e682e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/PropertyModel.h
@@ -0,0 +1,80 @@
+#ifndef PROPERTYMODEL_H
+#define PROPERTYMODEL_H
+
+#include <QAbstractListModel>
+
+#include "UICDMHandles.h"
+#include "UICDMDataTypes.h"
+#include "UICDMMetaDataTypes.h"
+
+struct PropertyInfo {
+ Q_PROPERTY(QString name MEMBER m_name CONSTANT FINAL)
+ Q_PROPERTY(float min MEMBER m_min CONSTANT FINAL)
+ Q_PROPERTY(float max MEMBER m_max CONSTANT FINAL)
+ Q_PROPERTY(UICDM::DataModelDataType::Value type MEMBER m_type CONSTANT FINAL)
+ Q_PROPERTY(UICDM::AdditionalMetaDataType::Value additionalType MEMBER m_additionalType CONSTANT FINAL)
+ Q_PROPERTY(QStringList possibleValues MEMBER m_possibleValues CONSTANT FINAL)
+
+ UICDM::CUICDMPropertyHandle m_handle;
+ QString m_name;
+ QString m_nameId;
+ UICDM::DataModelDataType::Value m_type;
+ UICDM::AdditionalMetaDataType::Value m_additionalType;
+ QStringList m_possibleValues;
+ float m_min = 0.0f;
+ float m_max = 0.0f;
+
+ Q_GADGET
+};
+
+class PropertyModel : public QAbstractListModel
+{
+ Q_PROPERTY(int valueHandle READ valueHandle NOTIFY valueHandleChanged FINAL)
+ Q_PROPERTY(QVariant value READ value NOTIFY valueChanged FINAL)
+ Q_PROPERTY(int defaultPropertyIndex READ defaultPropertyIndex NOTIFY defaultPropertyIndexChanged FINAL)
+ Q_OBJECT
+
+public:
+ explicit PropertyModel(QObject *parent = nullptr);
+
+ enum Roles {
+ NameRole = Qt::DisplayRole,
+ HandleRole = Qt::UserRole + 1
+ };
+
+ void setAction(const UICDM::CUICDMActionHandle &action);
+ void setNameHandle(const UICDM::CUICDMHandlerArgHandle &valueHandle);
+ void setValueHandle(const UICDM::CUICDMHandlerArgHandle &valueHandle);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ PropertyInfo property(int index) const;
+ UICDM::CUICDMActionHandle action() const { return m_action; }
+ int valueHandle() const;
+
+ QVariant value() const;
+ int defaultPropertyIndex() const;
+
+Q_SIGNALS:
+ void valueHandleChanged();
+ void valueChanged();
+ void defaultPropertyIndexChanged();
+
+private:
+ void updateValue();
+ void updateDefaultPropertyIndex();
+
+ QVector<PropertyInfo> m_properties;
+ UICDM::CUICDMActionHandle m_action;
+ UICDM::CUICDMHandlerArgHandle m_nameHandle;
+ UICDM::CUICDMHandlerArgHandle m_valueHandle;
+ int m_defaultPropertyIndex = -1;
+ QVariant m_value;
+};
+
+Q_DECLARE_METATYPE(PropertyInfo)
+
+#endif // PROPERTYMODEL_H
diff --git a/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.cpp b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.cpp
new file mode 100644
index 00000000..9ceee2d2
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "BasicObjectsModel.h"
+#include "DropSource.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+
+#include <QCoreApplication>
+#include <QDataStream>
+#include <QMimeData>
+
+BasicObjectsModel::BasicObjectsModel(QObject *parent) : QAbstractListModel(parent)
+{
+ initialize();
+}
+
+void BasicObjectsModel::initialize()
+{
+ m_ObjectItems = {
+ {tr("Rectangle"), "Asset-Rectangle-Normal.png"_L1, OBJTYPE_MODEL, PRIMITIVETYPE_RECT},
+ {tr("Sphere"), "Asset-Sphere-Normal.png"_L1, OBJTYPE_MODEL, PRIMITIVETYPE_SPHERE},
+ {tr("Cube"), "Asset-Cube-Normal.png"_L1, OBJTYPE_MODEL, PRIMITIVETYPE_BOX},
+ {tr("Cylinder"), "Asset-Cylinder-Normal.png"_L1, OBJTYPE_MODEL, PRIMITIVETYPE_CYLINDER},
+ {tr("Cone"), "Asset-Cone-Normal.png"_L1, OBJTYPE_MODEL, PRIMITIVETYPE_CONE},
+ {tr("Component"), "Asset-Component-Normal.png"_L1, OBJTYPE_COMPONENT, PRIMITIVETYPE_UNKNOWN},
+ {tr("Group"), "Asset-Group-Normal.png"_L1, OBJTYPE_GROUP, PRIMITIVETYPE_UNKNOWN},
+ {tr("Text"), "Asset-Text-Normal.png"_L1, OBJTYPE_TEXT, PRIMITIVETYPE_UNKNOWN},
+ {tr("Layer"), "Asset-Layer-Normal.png"_L1, OBJTYPE_LAYER, PRIMITIVETYPE_UNKNOWN},
+ {tr("Camera"), "Asset-Camera-Normal.png"_L1, OBJTYPE_CAMERA, PRIMITIVETYPE_UNKNOWN},
+ {tr("Light"), "Asset-Light-Normal.png"_L1, OBJTYPE_LIGHT, PRIMITIVETYPE_UNKNOWN},
+ {tr("Alias"), "Asset-Alias-Normal.png"_L1, OBJTYPE_ALIAS, PRIMITIVETYPE_UNKNOWN}
+ };
+}
+
+QVariant BasicObjectsModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(),index.parent()))
+ return {};
+
+ const auto row = index.row();
+
+ switch (role) {
+ case NameRole: return m_ObjectItems.at(row).name();
+ case IconRole: return resourceImageUrl() +
+ m_ObjectItems.at(row).icon();
+ case ObjectTypeRole: return m_ObjectItems.at(row).objectType();
+ case PrimitiveTypeRole: return m_ObjectItems.at(row).primitiveType();
+ }
+
+ return {};
+}
+
+int BasicObjectsModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return m_ObjectItems.count();
+}
+
+QHash<int, QByteArray> BasicObjectsModel::roleNames() const
+{
+ auto names = QAbstractListModel::roleNames();
+ names.insert(NameRole, "name");
+ names.insert(IconRole, "icon");
+
+ return names;
+}
+
+Qt::ItemFlags BasicObjectsModel::flags(const QModelIndex &index) const {
+ if (index.isValid())
+ return Qt::ItemIsDragEnabled;
+
+ return QAbstractListModel::flags(index);
+}
+
+QStringList BasicObjectsModel::mimeTypes() const
+{
+ return { m_MimeType };
+}
+
+QMimeData *BasicObjectsModel::mimeData(const QModelIndexList &indexes) const
+{
+
+ const auto row = indexes.first().row(); // we support only one item for D&D
+ auto object = m_ObjectItems.at(row);
+
+ auto *data = CDropSourceFactory::Create(object.GetFlavor(), &object);
+ return data;
+}
+
+BasicObjectItem::~BasicObjectItem()
+{
+}
diff --git a/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.h b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.h
new file mode 100644
index 00000000..ccaf07d6
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsModel.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BASICOBJECTSMODEL_H
+#define BASICOBJECTSMODEL_H
+
+#include <QAbstractListModel>
+
+#include "IDragable.h"
+#include "StudioObjectTypes.h"
+
+class BasicObjectItem : public IDragable {
+
+public:
+ BasicObjectItem() {}
+ BasicObjectItem(const QString &name, const QString &icon,
+ EStudioObjectType objectType, EPrimitiveType primitiveType)
+ : m_name(name), m_icon(icon)
+ , m_objectType(objectType), m_primitiveType(primitiveType)
+ { }
+
+ virtual ~BasicObjectItem();
+
+ QString name() const { return m_name; }
+ QString icon() const { return m_icon; }
+
+ EStudioObjectType objectType() const { return m_objectType; }
+ EPrimitiveType primitiveType() const { return m_primitiveType; }
+
+ void setName(const QString &name) { m_name = name; }
+ void setIcon(const QString &icon) { m_icon = icon; }
+ void setObjectType(EStudioObjectType type) { m_objectType = type; }
+ void setPrimitveType(EPrimitiveType type) { m_primitiveType = type; }
+
+ long GetFlavor() const override {return EUIC_FLAVOR_BASIC_OBJECTS;}
+
+private:
+ QString m_name;
+ QString m_icon;
+ EStudioObjectType m_objectType;
+ EPrimitiveType m_primitiveType;
+};
+
+class BasicObjectsModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ BasicObjectsModel(QObject *parent = nullptr);
+
+ enum Roles {
+ NameRole = Qt::DisplayRole,
+ IconRole = Qt::DecorationRole,
+ ObjectTypeRole = Qt::UserRole + 1,
+ PrimitiveTypeRole
+ };
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ QStringList mimeTypes() const override;
+ QMimeData *mimeData(const QModelIndexList &indexes) const override;
+
+private:
+ void initialize();
+
+ QVector<BasicObjectItem> m_ObjectItems;
+
+ const QString m_MimeType = QLatin1String("application/x-basic-object");
+};
+
+#endif // BASICOBJECTSMODEL_H
diff --git a/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.cpp b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.cpp
new file mode 100644
index 00000000..6834352a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "BasicObjectsView.h"
+#include "BasicObjectsModel.h"
+#include "CColor.h"
+#include "Literals.h"
+#include "StudioPreferences.h"
+#include "StudioUtils.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qtimer.h>
+#include <QtGui/qdrag.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+BasicObjectsView::BasicObjectsView(QWidget *parent) : QQuickWidget(parent)
+ , m_ObjectsModel(new BasicObjectsModel(this))
+
+{
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &BasicObjectsView::initialize);
+}
+
+QSize BasicObjectsView::sizeHint() const
+{
+ return {120, 600};
+}
+
+void BasicObjectsView::startDrag(int row)
+{
+ const auto index = m_ObjectsModel->index(row);
+
+ QDrag drag(this);
+ drag.setMimeData(m_ObjectsModel->mimeData({index}));
+ drag.setPixmap(QPixmap(index.data(BasicObjectsModel::IconRole).toUrl().toLocalFile()));
+ drag.exec(Qt::CopyAction);
+}
+
+void BasicObjectsView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_basicObjectsModel"_L1, m_ObjectsModel);
+ rootContext()->setContextProperty("_basicObjectsView"_L1, this);
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/BasicObjects/BasicObjectsView.qml"_L1));
+}
diff --git a/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.h b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.h
new file mode 100644
index 00000000..9317fc8f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BASICOBJECTSVIEW_H
+#define BASICOBJECTSVIEW_H
+
+#include <QQuickWidget>
+
+class BasicObjectsModel;
+
+class BasicObjectsView : public QQuickWidget
+{
+ Q_OBJECT
+public:
+ explicit BasicObjectsView(QWidget *parent = nullptr);
+
+ QSize sizeHint() const override;
+
+ Q_INVOKABLE void startDrag(int row);
+private:
+ void initialize();
+
+ BasicObjectsModel *m_ObjectsModel = nullptr;
+ QColor m_BaseColor = QColor::fromRgb(75, 75, 75);
+};
+
+#endif // BASICOBJECTSVIEW_H
diff --git a/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.qml b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.qml
new file mode 100644
index 00000000..ec2a0f6e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/BasicObjects/BasicObjectsView.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import "../controls"
+
+Rectangle {
+
+ color: _backgroundColor
+
+ ListView {
+ anchors {
+ fill: parent
+ leftMargin: 8
+ }
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: _basicObjectsModel
+ spacing: 2
+
+ ScrollBar.vertical: ScrollBar {}
+
+ delegate: Item {
+ height: contentRow.height
+ width: contentRow.width
+ Item {
+ id: dragItem
+ anchors.fill: parent
+
+ Drag.active: dragArea.drag.active
+ Drag.hotSpot.x: width / 2
+ Drag.hotSpot.y: height / 2
+ Drag.dragType: Drag.Automatic
+ Drag.supportedActions: Qt.CopyAction
+
+ MouseArea {
+ id: dragArea
+ property bool dragging: false
+ anchors.fill: parent
+ drag.target: dragItem
+ }
+
+ Drag.onDragStarted: _basicObjectsView.startDrag(model.index)
+ }
+ Row {
+ id: contentRow
+ spacing: 4
+ Image {
+ id: assetIcon
+ width: 24
+ height: 24
+ fillMode: Image.Pad
+ source: model.icon
+ }
+ StyledLabel {
+ y: (assetIcon.height - height) / 2
+ text: model.name
+ }
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ChooserDelegate.qml b/src/Authoring/Studio/Palettes/Inspector/ChooserDelegate.qml
new file mode 100644
index 00000000..6ee4445c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ChooserDelegate.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: item
+
+ signal clicked(string filePath)
+ signal doubleClicked(string filePath)
+
+ width: parent.width
+ height: 20
+ color: isCurrentFile ? _selectionColor : "transparent"
+
+ Row {
+ x: depth*28
+ anchors.verticalCenter: item.verticalCenter
+
+ Image {
+ source: _resDir + (expanded ? "arrow_down.png" : "arrow.png")
+ opacity: isExpandable ? 1 : 0
+
+ MouseArea {
+ visible: isExpandable
+ anchors.fill: parent
+ onClicked: {
+ if (expanded)
+ listView.model.collapse(index)
+ else
+ listView.model.expand(index)
+ }
+ }
+ }
+
+ Image {
+ source: fileIcon
+ }
+
+ StyledLabel {
+ text: fileName
+ color: _textColor
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton
+ visible: isSelectable
+ onClicked: item.clicked(filePath)
+ onDoubleClicked: item.doubleClicked(filePath)
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.cpp b/src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.cpp
new file mode 100644
index 00000000..87df1b45
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QSet>
+
+#include "stdafx.h"
+
+#include "ChooserModelBase.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "Doc.h"
+#include "StudioUtils.h"
+#include "UICFileTools.h"
+#include "ImportUtils.h"
+#include "StudioApp.h"
+
+ChooserModelBase::ChooserModelBase(QObject *parent) : QAbstractListModel(parent)
+ , m_model(new QFileSystemModel(this))
+{
+ connect(m_model, &QAbstractItemModel::rowsInserted, this, &ChooserModelBase::modelRowsInserted);
+ connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ChooserModelBase::modelRowsRemoved);
+ connect(m_model, &QAbstractItemModel::layoutChanged, this, &ChooserModelBase::modelLayoutChanged);
+
+ g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
+
+ rebuild();
+}
+
+ChooserModelBase::~ChooserModelBase()
+{
+ g_StudioApp.GetCore()->GetDispatch()->RemovePresentationChangeListener(this);
+}
+
+QHash<int, QByteArray> ChooserModelBase::roleNames() const
+{
+ auto modelRoleNames = m_model->roleNames();
+ modelRoleNames.insert(IsExpandableRole, "isExpandable");
+ modelRoleNames.insert(DepthRole, "depth");
+ modelRoleNames.insert(ExpandedRole, "expanded");
+ modelRoleNames.insert(IsSelectableRole, "isSelectable");
+ modelRoleNames.insert(IsCurrentFile, "isCurrentFile");
+ return modelRoleNames;
+}
+
+int ChooserModelBase::rowCount(const QModelIndex &) const
+{
+ return getFixedItems().count() + m_items.count();
+}
+
+QVariant ChooserModelBase::data(const QModelIndex &index, int role) const
+{
+ const int row = index.row();
+
+ const auto fixedItems = getFixedItems();
+ const int fixedItemCount = fixedItems.count();
+
+ if (row < fixedItemCount) {
+ const auto &item = fixedItems.at(row);
+
+ switch (role) {
+ case Qt::DecorationRole:
+ return resourceImageUrl() + CStudioObjectTypes::GetNormalIconName(item.iconType);
+
+ case IsExpandableRole:
+ return false;
+
+ case DepthRole:
+ return 0;
+
+ case ExpandedRole:
+ return false;
+
+ case IsSelectableRole:
+ return true;
+
+ case IsCurrentFile:
+ return item.name == m_currentFile;
+
+ default:
+ return item.name;
+ }
+ } else {
+ const auto &item = m_items.at(row - fixedItemCount);
+
+ switch (role) {
+ case Qt::DecorationRole: {
+ QString path = item.index.data(QFileSystemModel::FilePathRole).toString();
+ return resourceImageUrl() + getIconName(path);
+ }
+
+ case IsExpandableRole: {
+ QFileInfo fileInfo(item.index.data(QFileSystemModel::FilePathRole).toString());
+ return fileInfo.isDir();
+ }
+
+ case DepthRole:
+ return item.depth;
+
+ case ExpandedRole:
+ return item.expanded;
+
+ case IsSelectableRole: {
+ QFileInfo fileInfo(item.index.data(QFileSystemModel::FilePathRole).toString());
+ return fileInfo.isFile();
+ }
+
+ case IsCurrentFile: {
+ QString path = item.index.data(QFileSystemModel::FilePathRole).toString();
+ return path == m_currentFile;
+ }
+
+ default:
+ return m_model->data(item.index, role);
+ }
+ }
+}
+
+void ChooserModelBase::setCurrentFile(const QString &path)
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const QDir documentDir(doc->GetDocumentDirectory().toQString());
+ const QString fullPath = QDir::cleanPath(documentDir.filePath(path));
+
+ if (fullPath != m_currentFile) {
+ const auto fixedItems = getFixedItems();
+
+ const auto fileRow = [this, &fixedItems](const QString &path)
+ {
+ const int fixedItemCount = fixedItems.count();
+
+ for (int i = 0; i < fixedItemCount; ++i) {
+ const auto &item = fixedItems.at(i);
+
+ if (item.name == path)
+ return i;
+ }
+
+ const int itemCount = m_items.count();
+
+ for (int i = 0; i < itemCount; ++i) {
+ const auto &item = m_items.at(i);
+
+ if (item.index.data(QFileSystemModel::FilePathRole).toString() == path)
+ return fixedItemCount + i;
+ }
+
+ return -1;
+ };
+
+ int previousRow = fileRow(m_currentFile);
+ int currentRow = fileRow(fullPath);
+
+ m_currentFile = fullPath;
+
+ const int fixedItemCount = fixedItems.count();
+
+ if (previousRow != -1)
+ Q_EMIT dataChanged(index(previousRow), index(previousRow));
+
+ if (currentRow != -1)
+ Q_EMIT dataChanged(index(currentRow), index(currentRow));
+ }
+
+ // expand parent folder if current file is hidden
+ auto matched = m_model->match(m_rootIndex, QFileSystemModel::FilePathRole, path, 1,
+ Qt::MatchExactly|Qt::MatchRecursive);
+ if (!matched.isEmpty()) {
+ auto modelIndex = matched.first();
+ if (modelIndexRow(modelIndex) == -1)
+ expand(m_model->parent(modelIndex));
+ }
+}
+
+void ChooserModelBase::expand(const QModelIndex &modelIndex)
+{
+ if (modelIndex == m_rootIndex)
+ return;
+
+ int row = modelIndexRow(modelIndex);
+ if (row == -1) {
+ QModelIndex parentIndex = m_model->parent(modelIndex);
+ expand(parentIndex);
+
+ row = modelIndexRow(modelIndex);
+ Q_ASSERT(row != -1);
+ }
+
+ if (!m_items.at(row).expanded)
+ expand(row + getFixedItems().count());
+}
+
+void ChooserModelBase::setRootPath(const QString &path)
+{
+ setRootIndex(m_model->setRootPath(path));
+}
+
+void ChooserModelBase::setRootIndex(const QModelIndex &rootIndex)
+{
+ if (rootIndex != m_rootIndex) {
+ clearModelData();
+ m_rootIndex = rootIndex;
+ showModelTopLevelItems();
+ }
+}
+
+void ChooserModelBase::clearModelData()
+{
+ if (!m_items.isEmpty()) {
+ const auto fixedItemCount = getFixedItems().count();
+ beginRemoveRows({}, fixedItemCount, fixedItemCount + m_items.count() - 1);
+ m_items.clear();
+ endRemoveRows();
+ }
+}
+
+void ChooserModelBase::showModelTopLevelItems()
+{
+ int rowCount = m_model->rowCount(m_rootIndex);
+
+ if (rowCount == 0) {
+ if (m_model->hasChildren(m_rootIndex) && m_model->canFetchMore(m_rootIndex))
+ m_model->fetchMore(m_rootIndex);
+ } else {
+ showModelChildItems(m_rootIndex, 0, rowCount - 1);
+
+ for (int i = 0; i < rowCount; ++i) {
+ const auto &childIndex = m_model->index(i, 0, m_rootIndex);
+ if (m_model->hasChildren(childIndex) && m_model->canFetchMore(childIndex))
+ m_model->fetchMore(childIndex);
+ }
+ }
+}
+
+void ChooserModelBase::showModelChildItems(const QModelIndex &parentIndex, int start, int end)
+{
+ QVector<QModelIndex> rowsToInsert;
+ for (int i = start; i <= end; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ if (isVisible(childIndex))
+ rowsToInsert.append(childIndex);
+ }
+
+ const int insertCount = rowsToInsert.count();
+
+ if (insertCount != 0) {
+ TreeItem *parent;
+ int depth, startRow;
+
+ if (parentIndex == m_rootIndex) {
+ parent = nullptr;
+ depth = 0;
+ startRow = 0;
+ } else {
+ const int parentRow = modelIndexRow(parentIndex);
+ Q_ASSERT(parentRow != -1 && isVisible(parentIndex));
+ parent = &m_items[parentRow];
+ depth = parent->depth + 1;
+ startRow = parentRow + parent->childCount + 1;
+ }
+
+ const int fixedItemCount = getFixedItems().count();
+ beginInsertRows({}, startRow + fixedItemCount, startRow + fixedItemCount + insertCount - 1);
+
+ for (auto it = rowsToInsert.rbegin(); it != rowsToInsert.rend(); ++it)
+ m_items.insert(startRow, { *it, depth, false, parent, 0 });
+
+ for (; parent != nullptr; parent = parent->parent)
+ parent->childCount += insertCount;
+
+ endInsertRows();
+ }
+}
+
+void ChooserModelBase::expand(int row)
+{
+ const int fixedItemCount = getFixedItems().count();
+ Q_ASSERT(row >= fixedItemCount && row < fixedItemCount + m_items.count());
+
+ auto &item = m_items[row - fixedItemCount];
+ Q_ASSERT(item.expanded == false);
+
+ const auto &modelIndex = item.index;
+
+ const int rowCount = m_model->rowCount(modelIndex);
+ if (rowCount == 0) {
+ if (m_model->hasChildren(modelIndex) && m_model->canFetchMore(modelIndex))
+ m_model->fetchMore(modelIndex);
+ } else {
+ showModelChildItems(modelIndex, 0, rowCount - 1);
+ }
+
+ item.expanded = true;
+ Q_EMIT dataChanged(index(row), index(row));
+}
+
+void ChooserModelBase::collapse(int row)
+{
+ const int fixedItemCount = getFixedItems().count();
+ Q_ASSERT(row >= fixedItemCount && row < fixedItemCount + m_items.count());
+
+ auto &item = m_items[row - fixedItemCount];
+ Q_ASSERT(item.expanded == true);
+
+ const int childCount = item.childCount;
+
+ if (childCount > 0) {
+ beginRemoveRows({}, row + 1, row + childCount);
+
+ auto first = std::begin(m_items) + row - fixedItemCount + 1;
+ m_items.erase(first, first + childCount);
+
+ for (auto parent = &item; parent != nullptr; parent = parent->parent)
+ parent->childCount -= childCount;
+
+ endRemoveRows();
+ }
+
+ item.expanded = false;
+ Q_EMIT dataChanged(index(row), index(row));
+}
+
+void ChooserModelBase::OnNewPresentation()
+{
+ rebuild();
+}
+
+int ChooserModelBase::modelIndexRow(const QModelIndex &modelIndex) const
+{
+ auto it = std::find_if(std::begin(m_items), std::end(m_items),
+ [&modelIndex](const TreeItem &item)
+ {
+ return item.index == modelIndex;
+ });
+
+ return it != std::end(m_items) ? std::distance(std::begin(m_items), it) : -1;
+}
+
+bool ChooserModelBase::isExpanded(const QModelIndex &modelIndex) const
+{
+ if (modelIndex == m_rootIndex) {
+ return true;
+ } else {
+ const int row = modelIndexRow(modelIndex);
+ return row != -1 && m_items.at(row).expanded;
+ }
+}
+
+EStudioObjectType ChooserModelBase::getIconType(const QString &path) const
+{
+ return Q3DStudio::ImportUtils::GetObjectFileTypeForFile(Q3DStudio::CFilePath::fromQString(path)).m_IconType;
+}
+
+QString ChooserModelBase::getIconName(const QString &path) const
+{
+ QString iconName;
+
+ QFileInfo fileInfo(path);
+ if (fileInfo.isFile()) {
+ EStudioObjectType type = getIconType(path);
+ if (type != OBJTYPE_UNKNOWN)
+ iconName = CStudioObjectTypes::GetNormalIconName(type);
+ else
+ iconName = QStringLiteral("Objects-Layer-Normal.png");
+ } else {
+ iconName = QStringLiteral("Objects-Folder-Normal.png");
+ }
+
+ return iconName;
+}
+
+bool ChooserModelBase::isVisible(const QModelIndex &modelIndex) const
+{
+ QString path = modelIndex.data(QFileSystemModel::FilePathRole).toString();
+ QFileInfo fileInfo(path);
+
+ if (fileInfo.isFile()) {
+ return isVisible(path);
+ } else {
+ return hasVisibleChildren(modelIndex);
+ }
+}
+
+bool ChooserModelBase::hasVisibleChildren(const QModelIndex &modelIndex) const
+{
+ int rowCount = m_model->rowCount(modelIndex);
+
+ for (int i = 0; i < rowCount; ++i) {
+ const auto &childIndex = m_model->index(i, 0, modelIndex);
+
+ if (m_model->hasChildren(childIndex)) {
+ if (hasVisibleChildren(childIndex))
+ return true;
+ } else {
+ QString path = childIndex.data(QFileSystemModel::FilePathRole).toString();
+ QFileInfo fileInfo(path);
+ if (fileInfo.isFile() && isVisible(path))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ChooserModelBase::modelRowsInserted(const QModelIndex &parentIndex, int start, int end)
+{
+ if (!m_rootIndex.isValid())
+ return;
+
+ if (isExpanded(parentIndex)) {
+ showModelChildItems(parentIndex, start, end);
+ } else {
+ if (modelIndexRow(parentIndex) == -1) {
+ // parent wasn't inserted in model yet, check if any of the new rows is visible
+
+ bool visible = false;
+
+ for (int i = start; i <= end; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ QString path = childIndex.data(QFileSystemModel::FilePathRole).toString();
+ QFileInfo fileInfo(path);
+ if (fileInfo.isFile() && isVisible(path)) {
+ visible = true;
+ break;
+ }
+ }
+
+ // if any of the new rows is visible, insert parent folder index into model
+
+ if (visible) {
+ QModelIndex index = parentIndex, parent = m_model->parent(parentIndex);
+
+ while (parent != m_rootIndex && modelIndexRow(parent) == -1) {
+ index = parent;
+ parent = m_model->parent(parent);
+ }
+
+ if (isExpanded(parent) && modelIndexRow(index) == -1) {
+ const int row = index.row();
+ showModelChildItems(parent, row, row);
+ }
+ }
+ }
+
+ // if one of the new rows is the current file expand parent folder
+
+ bool containsCurrent = false;
+
+ for (int i = start; i <= end; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ if (childIndex.data(QFileSystemModel::FilePathRole).toString() == m_currentFile) {
+ containsCurrent = true;
+ break;
+ }
+ }
+
+ if (containsCurrent)
+ expand(parentIndex);
+ }
+
+ // fetch children so we're notified when files are added or removed
+
+ for (int i = start; i <= end; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ if (m_model->hasChildren(childIndex) && m_model->canFetchMore(childIndex))
+ m_model->fetchMore(childIndex);
+ }
+}
+
+void ChooserModelBase::modelRowsRemoved(const QModelIndex &parentIndex, int start, int end)
+{
+ if (!m_rootIndex.isValid())
+ return;
+
+ if (isExpanded(parentIndex)) {
+ const auto fixedItems = getFixedItems();
+
+ const auto removeRow = [this, &fixedItems](int row)
+ {
+ const auto &item = m_items.at(row);
+
+ const int fixedItemCount = fixedItems.count();
+ beginRemoveRows({}, row + fixedItemCount, row + fixedItemCount + item.childCount);
+
+ for (auto parent = item.parent; parent != nullptr; parent = parent->parent)
+ parent->childCount -= 1 + item.childCount;
+
+ m_items.erase(std::begin(m_items) + row, std::begin(m_items) + row + item.childCount + 1);
+
+ endRemoveRows();
+ };
+
+ // remove rows
+
+ for (int i = start; i <= end; ++i) {
+ const int row = modelIndexRow(m_model->index(i, 0, parentIndex));
+ if (row != -1)
+ removeRow(row);
+ }
+
+ // also remove folder row if there are no more visible children
+
+ QModelIndex index = parentIndex;
+
+ while (index != m_rootIndex && !hasVisibleChildren(index)) {
+ const int row = modelIndexRow(index);
+ Q_ASSERT(row != -1);
+ removeRow(row);
+ index = m_model->parent(index);
+ }
+ }
+}
+
+void ChooserModelBase::modelLayoutChanged()
+{
+ if (!m_rootIndex.isValid())
+ return;
+
+ QSet<QPersistentModelIndex> expandedItems;
+ for (const auto &item : m_items) {
+ if (item.expanded)
+ expandedItems.insert(item.index);
+ }
+
+ const std::function<int(const QModelIndex &, TreeItem *)> insertChildren =
+ [this, &expandedItems, &insertChildren](const QModelIndex &parentIndex, TreeItem *parent)
+ {
+ Q_ASSERT(parentIndex == m_rootIndex || isVisible(parentIndex));
+
+ const int rowCount = m_model->rowCount(parentIndex);
+ const int depth = parent == nullptr ? 0 : parent->depth + 1;
+
+ int childCount = 0;
+
+ for (int i = 0; i < rowCount; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ if (isVisible(childIndex)) {
+ const bool expanded = expandedItems.contains(childIndex);
+ m_items.append({ childIndex, depth, expanded, parent, 0 });
+ auto &item = m_items.last();
+ if (expanded) {
+ item.childCount = insertChildren(childIndex, &item);
+ childCount += item.childCount;
+ }
+ ++childCount;
+ }
+ }
+
+ return childCount;
+ };
+
+ const int itemCount = m_items.count();
+
+ m_items.clear();
+ m_items.reserve(itemCount);
+
+ insertChildren(m_rootIndex, nullptr);
+ Q_ASSERT(m_items.count() == itemCount);
+
+ const int fixedItemCount = getFixedItems().count();
+ Q_EMIT dataChanged(index(fixedItemCount), index(fixedItemCount + itemCount - 1));
+}
+
+void ChooserModelBase::rebuild()
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const Q3DStudio::CFilePath path(doc->GetDocumentPath().GetAbsolutePath());
+ setRootPath(path.GetDirectory().toQString());
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.h b/src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.h
new file mode 100644
index 00000000..547822ea
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ChooserModelBase.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef CHOOSERMODELBASE_H
+#define CHOOSERMODELBASE_H
+
+#include "DispatchListeners.h"
+#include "StudioObjectTypes.h"
+
+#include <QFileSystemModel>
+#include <QAbstractListModel>
+#include <QList>
+#include <QVector>
+
+class QFileSystemModel;
+
+class ChooserModelBase : public QAbstractListModel, public CPresentationChangeListener
+{
+ Q_OBJECT
+
+public:
+ explicit ChooserModelBase(QObject *parent = nullptr);
+ ~ChooserModelBase();
+
+ enum {
+ IsExpandableRole = QFileSystemModel::FilePermissions + 1,
+ DepthRole,
+ ExpandedRole,
+ IsSelectableRole,
+ IsCurrentFile
+ };
+
+ QHash<int, QByteArray> roleNames() const override;
+ int rowCount(const QModelIndex &parent = {}) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+
+ Q_INVOKABLE void expand(int row);
+ Q_INVOKABLE void collapse(int row);
+
+ void setCurrentFile(const QString &path);
+
+ // CPresentationChangeListener
+ void OnNewPresentation() override;
+
+Q_SIGNALS:
+ void modelChanged(QAbstractItemModel *model);
+
+protected:
+ EStudioObjectType getIconType(const QString &path) const;
+
+ virtual bool isVisible(const QString &path) const = 0;
+
+ struct FixedItem
+ {
+ EStudioObjectType iconType;
+ QString name;
+ };
+
+ virtual const QVector<FixedItem> getFixedItems() const = 0;
+
+private:
+ void setRootPath(const QString &path);
+ void setRootIndex(const QModelIndex &rootIndex);
+ void clearModelData();
+ void showModelTopLevelItems();
+ void showModelChildItems(const QModelIndex &parentItem, int start, int end);
+ int modelIndexRow(const QModelIndex &modelIndex) const;
+ bool isExpanded(const QModelIndex &modelIndex) const;
+ QString getIconName(const QString &path) const;
+ bool isVisible(const QModelIndex &modelIndex) const;
+ bool hasVisibleChildren(const QModelIndex &modelIndex) const;
+ void expand(const QModelIndex &modelIndex);
+
+ void modelRowsInserted(const QModelIndex &parent, int start, int end);
+ void modelRowsRemoved(const QModelIndex &parent, int start, int end);
+ void modelRowsMoved(const QModelIndex &parent, int start, int end);
+ void modelLayoutChanged();
+
+ void rebuild();
+
+ struct TreeItem {
+ QPersistentModelIndex index;
+ int depth;
+ bool expanded;
+ TreeItem *parent;
+ int childCount;
+ };
+
+ QFileSystemModel *m_model;
+ QPersistentModelIndex m_rootIndex;
+ QList<TreeItem> m_items;
+ QString m_currentFile;
+};
+
+#endif // CHOOSERMODELBASE_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.cpp b/src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.cpp
new file mode 100644
index 00000000..44b89904
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EasyInspectorGroup.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CEasyInspectorGroup::CEasyInspectorGroup(const QString &inName)
+ : CInspectorGroup()
+{
+ SetName(inName);
+}
+
+//==============================================================================
+/**
+ *
+ */
+CEasyInspectorGroup::~CEasyInspectorGroup()
+{
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.h b/src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.h
new file mode 100644
index 00000000..62cc35a5
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/EasyInspectorGroup.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_EASYINSPECTORGROUP_H
+#define INCLUDED_EASYINSPECTORGROUP_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "InspectorGroup.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * Simplest possible inspector group
+ */
+class CEasyInspectorGroup : public CInspectorGroup
+{
+public: // Construction
+ CEasyInspectorGroup(const QString &inName);
+ ~CEasyInspectorGroup();
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Inspector/FileChooser.qml b/src/Authoring/Studio/Palettes/Inspector/FileChooser.qml
new file mode 100644
index 00000000..2762af3a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/FileChooser.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+ border.color: _studioColor3
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ spacing: 10
+ ListView {
+ id: listView
+
+ anchors {
+ fill: parent
+ leftMargin: 8
+ }
+
+ boundsBehavior: Flickable.StopAtBounds
+ spacing: 4
+ clip: true
+
+ ScrollBar.vertical: ScrollBar {}
+
+ model: _fileChooserModel
+
+ delegate: ChooserDelegate {
+ onClicked: _fileChooserView.fileSelected(_fileChooserView.handle, _fileChooserView.instance, filePath)
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/FileChooserModel.cpp b/src/Authoring/Studio/Palettes/Inspector/FileChooserModel.cpp
new file mode 100644
index 00000000..6c57635b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/FileChooserModel.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "FileChooserModel.h"
+
+FileChooserModel::FileChooserModel(QObject *parent)
+ : ChooserModelBase(parent)
+{
+
+}
+
+FileChooserModel::~FileChooserModel()
+{
+}
+
+bool FileChooserModel::isVisible(const QString &path) const
+{
+ return getIconType(path) == OBJTYPE_GROUP;
+}
+
+const QVector<ChooserModelBase::FixedItem> FileChooserModel::getFixedItems() const
+{
+ static const QVector<FixedItem> items = { { OBJTYPE_GROUP, tr("[None]") } };
+ return items;
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/FileChooserModel.h b/src/Authoring/Studio/Palettes/Inspector/FileChooserModel.h
new file mode 100644
index 00000000..c019c4a1
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/FileChooserModel.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILECHOOSERMODEL_H
+#define FILECHOOSERMODEL_H
+
+#include "ChooserModelBase.h"
+
+class FileChooserModel : public ChooserModelBase
+{
+ Q_OBJECT
+
+public:
+ explicit FileChooserModel(QObject *parent = nullptr);
+ virtual ~FileChooserModel();
+private:
+ bool isVisible(const QString &path) const override;
+ const QVector<FixedItem> getFixedItems() const override;
+};
+
+#endif // IMAGECHOOSERMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/FileChooserView.cpp b/src/Authoring/Studio/Palettes/Inspector/FileChooserView.cpp
new file mode 100644
index 00000000..d5951e7c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/FileChooserView.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "FileChooserView.h"
+#include "FileChooserModel.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "IDocumentEditor.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMValue.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "StudioPreferences.h"
+
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+#include <QtCore/qtimer.h>
+
+FileChooserView::FileChooserView(QWidget *parent)
+ : QQuickWidget(parent)
+ , m_model(new FileChooserModel(this))
+{
+ setWindowTitle(tr("Imports"));
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &FileChooserView::initialize);
+}
+
+void FileChooserView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_resDir"_L1,
+ resourceImageUrl());
+ rootContext()->setContextProperty("_fileChooserView"_L1, this);
+ rootContext()->setContextProperty("_fileChooserModel"_L1, m_model);
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/FileChooser.qml"_L1));
+}
+
+QSize FileChooserView::sizeHint() const
+{
+ return {500, 500};
+}
+
+void FileChooserView::setHandle(int handle)
+{
+ m_handle = handle;
+}
+
+int FileChooserView::handle() const
+{
+ return m_handle;
+}
+
+void FileChooserView::setInstance(int instance)
+{
+ m_instance = instance;
+}
+
+int FileChooserView::instance() const
+{
+ return m_instance;
+}
+
+void FileChooserView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ QTimer::singleShot(0, this, &FileChooserView::close);
+}
+
+void FileChooserView::showEvent(QShowEvent *event)
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+
+ UICDM::SValue value;
+ propertySystem->GetInstancePropertyValue(m_instance, m_handle, value);
+
+ m_model->setCurrentFile(UICDM::get<QString>(value));
+
+ QQuickWidget::showEvent(event);
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/FileChooserView.h b/src/Authoring/Studio/Palettes/Inspector/FileChooserView.h
new file mode 100644
index 00000000..400f9f1e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/FileChooserView.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILECHOOSERVIEW_H
+#define FILECHOOSERVIEW_H
+
+#include <QtQuickWidgets/qquickwidget.h>
+
+class FileChooserModel;
+
+class FileChooserView : public QQuickWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int instance READ instance)
+ Q_PROPERTY(int handle READ handle)
+
+public:
+ explicit FileChooserView(QWidget *parent = nullptr);
+
+ QSize sizeHint() const override;
+
+ void setHandle(int handle);
+ int handle() const;
+
+ void setInstance(int instance);
+ int instance() const;
+
+Q_SIGNALS:
+ void fileSelected(int handle, int instance, const QString &name);
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+private:
+ void showEvent(QShowEvent *event) override;
+ void initialize();
+ int m_handle = -1;
+ int m_instance = -1;
+ FileChooserModel *m_model = nullptr;
+};
+
+#endif // IMAGECHOOSERVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/GuideInspectable.cpp b/src/Authoring/Studio/Palettes/Inspector/GuideInspectable.cpp
new file mode 100644
index 00000000..f840d92f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/GuideInspectable.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "GuideInspectable.h"
+#include "InspectableBase.h"
+#include "Core.h"
+#include "Doc.h"
+#include "UICDMGuides.h"
+#include "EasyInspectorGroup.h"
+#include "IDocumentEditor.h"
+#include "UICDMDataTypes.h"
+#include "IInspectableItem.h"
+#include "UICDMValue.h"
+
+typedef std::function<UICDM::SValue()> TGetterFunc;
+typedef std::function<void(UICDM::SValue)> TSetterFunc;
+typedef std::function<void()> TCommitFunc;
+typedef std::function<void()> TCancelFunc;
+
+struct SInspectableDataInfo
+{
+ Q3DStudio::CString m_Name;
+ Q3DStudio::CString m_FormalName;
+ Q3DStudio::CString m_Description;
+ TGetterFunc m_Getter;
+ TSetterFunc m_Setter;
+ TCommitFunc m_Commit;
+ TCancelFunc m_Cancel;
+
+ SInspectableDataInfo(const Q3DStudio::CString &name, const Q3DStudio::CString &formalName,
+ const Q3DStudio::CString &description, TGetterFunc getter, TSetterFunc setter,
+ TCommitFunc commit, TCancelFunc inCancel)
+ : m_Name(name)
+ , m_FormalName(formalName)
+ , m_Description(description)
+ , m_Getter(getter)
+ , m_Setter(setter)
+ , m_Commit(commit)
+ , m_Cancel(inCancel)
+ {
+ }
+};
+
+struct SComboAttItem : public IInspectableAttributeItem
+{
+ SInspectableDataInfo m_BaseInspectableInfo;
+ UICDM::TMetaDataStringList m_MetaDataTypes;
+ SComboAttItem(const SInspectableDataInfo &inInfo, const UICDM::TMetaDataStringList &inTypes)
+ : m_BaseInspectableInfo(inInfo)
+ , m_MetaDataTypes(inTypes)
+ {
+ }
+ UICDM::HandlerArgumentType::Value GetInspectableSubType() const override
+ {
+ return UICDM::HandlerArgumentType::Property;
+ }
+ Q3DStudio::CString GetInspectableName() const override { return m_BaseInspectableInfo.m_Name; }
+ Q3DStudio::CString GetInspectableFormalName() const override
+ {
+ return m_BaseInspectableInfo.m_FormalName;
+ }
+ Q3DStudio::CString GetInspectableDescription() const override
+ {
+ return m_BaseInspectableInfo.m_Description;
+ }
+
+ UICDM::SValue GetInspectableData() const override { return m_BaseInspectableInfo.m_Getter(); }
+ void SetInspectableData(const UICDM::SValue &inValue) override
+ {
+ m_BaseInspectableInfo.m_Setter(inValue);
+ m_BaseInspectableInfo.m_Commit();
+ }
+
+ float GetInspectableMin() const override { return 0; }
+ float GetInspectableMax() const override { return 0; }
+ UICDM::TMetaDataStringList GetInspectableList() const override { return m_MetaDataTypes; }
+ UICDM::DataModelDataType::Value GetInspectableType() const override
+ {
+ return UICDM::DataModelDataType::String;
+ }
+ UICDM::AdditionalMetaDataType::Value GetInspectableAdditionalType() const override
+ {
+ return UICDM::AdditionalMetaDataType::StringList;
+ }
+};
+
+struct SFloatIntItem : public IInspectableAttributeItem
+{
+ SInspectableDataInfo m_BaseInspectableInfo;
+ UICDM::DataModelDataType::Value m_DataType;
+ float m_Min;
+ float m_Max;
+ SFloatIntItem(const SInspectableDataInfo &inInfo, UICDM::DataModelDataType::Value inType,
+ float inMin = 0, float inMax = 0)
+ : m_BaseInspectableInfo(inInfo)
+ , m_DataType(inType)
+ , m_Min(inMin)
+ , m_Max(inMax)
+ {
+ }
+ UICDM::HandlerArgumentType::Value GetInspectableSubType() const override
+ {
+ return UICDM::HandlerArgumentType::Property;
+ }
+ Q3DStudio::CString GetInspectableName() const override { return m_BaseInspectableInfo.m_Name; }
+ Q3DStudio::CString GetInspectableFormalName() const override
+ {
+ return m_BaseInspectableInfo.m_FormalName;
+ }
+ Q3DStudio::CString GetInspectableDescription() const override
+ {
+ return m_BaseInspectableInfo.m_Description;
+ }
+
+ UICDM::SValue GetInspectableData() const override { return m_BaseInspectableInfo.m_Getter(); }
+ void SetInspectableData(const UICDM::SValue &inValue) override
+ {
+ m_BaseInspectableInfo.m_Setter(inValue);
+ m_BaseInspectableInfo.m_Commit();
+ }
+
+ void ChangeInspectableData(const UICDM::SValue &inValue) override
+ {
+ m_BaseInspectableInfo.m_Setter(inValue);
+ }
+ void CancelInspectableData() override { m_BaseInspectableInfo.m_Cancel(); }
+
+ float GetInspectableMin() const override { return m_Min; }
+ float GetInspectableMax() const override { return m_Max; }
+ UICDM::TMetaDataStringList GetInspectableList() const override
+ {
+ return UICDM::TMetaDataStringList();
+ }
+ UICDM::DataModelDataType::Value GetInspectableType() const override { return m_DataType; }
+ UICDM::AdditionalMetaDataType::Value GetInspectableAdditionalType() const override
+ {
+ return UICDM::AdditionalMetaDataType::None;
+ }
+};
+
+
+CInspectableBase *CGuideInspectable::CreateInspectable(CCore &inCore,
+ UICDM::CUICDMGuideHandle inGuide)
+{
+ return new SGuideInspectableImpl(inCore, inGuide);
+}
+
+SGuideInspectableImpl::SGuideInspectableImpl(CCore &inCore, UICDM::CUICDMGuideHandle inGuide)
+ : CInspectableBase(&inCore)
+ , m_Guide(inGuide)
+ , m_Editor(*inCore.GetDoc())
+{
+}
+
+Q3DStudio::IDocumentReader &SGuideInspectableImpl::Reader() const
+{
+ return m_Core->GetDoc()->GetDocumentReader();
+}
+
+EStudioObjectType SGuideInspectableImpl::GetObjectType()
+{
+ return OBJTYPE_GUIDE;
+}
+
+Q3DStudio::CString SGuideInspectableImpl::GetName()
+{
+ return L"Guide";
+}
+
+long SGuideInspectableImpl::GetGroupCount()
+{
+ return 1;
+}
+
+CInspectorGroup *SGuideInspectableImpl::GetGroup(long)
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ TCommitFunc theCommiter = std::bind(&SGuideInspectableImpl::Commit, this);
+ TCancelFunc theCanceler = std::bind(&SGuideInspectableImpl::Rollback, this);
+ m_Properties.push_back(std::make_shared<SFloatIntItem>(
+ SInspectableDataInfo("Position", "Position", "Position of the guide",
+ std::bind(&SGuideInspectableImpl::GetPosition, this),
+ std::bind(&SGuideInspectableImpl::SetPosition, this,
+ std::placeholders::_1),
+ theCommiter, theCanceler),
+ UICDM::DataModelDataType::Float));
+ UICDM::TMetaDataStringList theComboItems;
+ theComboItems.push_back(L"Horizontal");
+ theComboItems.push_back(L"Vertical");
+
+ m_Properties.push_back(std::make_shared<SComboAttItem>(
+ SInspectableDataInfo("Direction", "Direction", "Direction of the guide",
+ std::bind(&SGuideInspectableImpl::GetDirection, this),
+ std::bind(&SGuideInspectableImpl::SetDirection, this,
+ std::placeholders::_1),
+ theCommiter, theCanceler),
+ theComboItems));
+
+ m_Properties.push_back(std::make_shared<SFloatIntItem>(
+ SInspectableDataInfo("Width", "Width", "Width of the guide",
+ std::bind(&SGuideInspectableImpl::GetWidth, this),
+ std::bind(&SGuideInspectableImpl::SetWidth, this, std::placeholders::_1),
+ theCommiter, theCanceler),
+ UICDM::DataModelDataType::Long, 1.0f, 50.0f));
+
+ CEasyInspectorGroup *theNewGroup = new CEasyInspectorGroup(QObject::tr("Basic"));
+ return theNewGroup;
+}
+
+bool SGuideInspectableImpl::IsValid() const
+{
+ return Reader().IsGuideValid(m_Guide);
+}
+
+bool SGuideInspectableImpl::IsMaster()
+{
+ return true;
+}
+
+void SGuideInspectableImpl::SetDirection(const UICDM::SValue &inValue)
+{
+ UICDM::TDataStrPtr theData = inValue.getData<UICDM::TDataStrPtr>();
+ UICDM::SGuideInfo theSetter(Reader().GetGuideInfo(m_Guide));
+ if (theData) {
+ if (UICDM::AreEqual(theData->GetData(), L"Horizontal"))
+ theSetter.m_Direction = UICDM::GuideDirections::Horizontal;
+ else if (UICDM::AreEqual(theData->GetData(), L"Vertical"))
+ theSetter.m_Direction = UICDM::GuideDirections::Vertical;
+ }
+ Editor().UpdateGuide(m_Guide, theSetter);
+ FireRefresh();
+}
+
+UICDM::SValue SGuideInspectableImpl::GetDirection()
+{
+ switch (Reader().GetGuideInfo(m_Guide).m_Direction) {
+ case UICDM::GuideDirections::Horizontal:
+ return std::make_shared<UICDM::CDataStr>(L"Horizontal");
+ case UICDM::GuideDirections::Vertical:
+ return std::make_shared<UICDM::CDataStr>(L"Vertical");
+ default:
+ return std::make_shared<UICDM::CDataStr>(L"");
+ }
+}
+
+void SGuideInspectableImpl::SetPosition(const UICDM::SValue &inValue)
+{
+ float thePos = inValue.getData<float>();
+ UICDM::SGuideInfo theSetter(Reader().GetGuideInfo(m_Guide));
+ theSetter.m_Position = thePos;
+ Editor().UpdateGuide(m_Guide, theSetter);
+ FireRefresh();
+}
+
+UICDM::SValue SGuideInspectableImpl::GetPosition()
+{
+ UICDM::SGuideInfo theSetter(Reader().GetGuideInfo(m_Guide));
+ return theSetter.m_Position;
+}
+
+void SGuideInspectableImpl::SetWidth(const UICDM::SValue &inValue)
+{
+ auto theData = inValue.getData<qt3ds::QT3DSI32>();
+
+ UICDM::SGuideInfo theSetter(Reader().GetGuideInfo(m_Guide));
+ theSetter.m_Width = theData;
+ Editor().UpdateGuide(m_Guide, theSetter);
+ FireRefresh();
+
+}
+
+UICDM::SValue SGuideInspectableImpl::GetWidth()
+{
+ UICDM::SGuideInfo theSetter(Reader().GetGuideInfo(m_Guide));
+ return theSetter.m_Width;
+}
+
+Q3DStudio::IDocumentEditor &SGuideInspectableImpl::Editor()
+{
+ return m_Editor.EnsureEditor(L"Set Property", __FILE__, __LINE__);
+}
+
+void SGuideInspectableImpl::Commit()
+{
+ m_Editor.CommitEditor();
+}
+
+void SGuideInspectableImpl::Rollback()
+{
+ m_Editor.RollbackEditor();
+}
+
+void SGuideInspectableImpl::FireRefresh()
+{
+ m_Editor.FireImmediateRefresh(UICDM::CUICDMInstanceHandle());
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/GuideInspectable.h b/src/Authoring/Studio/Palettes/Inspector/GuideInspectable.h
new file mode 100644
index 00000000..77ff7a62
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/GuideInspectable.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef __GUIDEINSPECTABLE_H__
+#define __GUIDEINSPECTABLE_H__
+#include "UICDMHandles.h"
+#include "Core.h"
+#include "InspectableBase.h"
+#include "Doc.h"
+#include "IDocumentEditor.h"
+#include "IInspectableItem.h"
+
+class CInspectableBase;
+
+class CGuideInspectable
+{
+public:
+ static CInspectableBase *CreateInspectable(CCore &inCore, UICDM::CUICDMGuideHandle inGuide);
+};
+
+class SGuideInspectableImpl : public CInspectableBase
+{
+public:
+ SGuideInspectableImpl(CCore &inCore, UICDM::CUICDMGuideHandle inGuide);
+
+ Q3DStudio::IDocumentReader &Reader() const;
+ // Interface
+ EStudioObjectType GetObjectType() override;
+ Q3DStudio::CString GetName() override;
+ long GetGroupCount() override;
+ CInspectorGroup *GetGroup(long) override;
+ bool IsValid() const override;
+ bool IsMaster() override;
+
+ // Implementation to get/set properties
+
+ void SetDirection(const UICDM::SValue &inValue);
+
+ UICDM::SValue GetDirection();
+
+ void SetPosition(const UICDM::SValue &inValue);
+
+ UICDM::SValue GetPosition();
+
+ void SetWidth(const UICDM::SValue &inValue);
+
+ UICDM::SValue GetWidth();
+
+ Q3DStudio::IDocumentEditor &Editor();
+ void Commit();
+ void Rollback();
+ void FireRefresh();
+private:
+ UICDM::CUICDMGuideHandle m_Guide;
+ Q3DStudio::CUpdateableDocumentEditor m_Editor;
+ std::vector<std::shared_ptr<IInspectableAttributeItem>> m_Properties;
+};
+
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Inspector/HandlerFilesChooser.qml b/src/Authoring/Studio/Palettes/Inspector/HandlerFilesChooser.qml
new file mode 100644
index 00000000..65e0d6be
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/HandlerFilesChooser.qml
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.1
+import "../controls"
+
+RowLayout {
+ id: root
+
+ signal showBrowser
+ property string value: ""
+ property alias activeBrowser: browser.activeBrowser
+
+ BrowserCombo {
+ id: browser
+ Layout.preferredWidth: _valueWidth
+ Layout.fillWidth: true
+ value: root.value === "" ? qsTr("Select...") : root.value
+ onShowBrowser: root.showBrowser()
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/HandlerGenericChooser.qml b/src/Authoring/Studio/Palettes/Inspector/HandlerGenericChooser.qml
new file mode 100644
index 00000000..9a8f1688
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/HandlerGenericChooser.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.1
+import "../controls"
+
+RowLayout {
+ id: root
+
+ signal showBrowser
+ property alias value: browser.value
+ property alias activeBrowser: browser.activeBrowser
+
+ BrowserCombo {
+ id: browser
+ Layout.preferredWidth: _valueWidth
+ Layout.fillWidth: true
+ onShowBrowser: root.showBrowser()
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/IEasyInspectorRowListener.h b/src/Authoring/Studio/Palettes/Inspector/IEasyInspectorRowListener.h
new file mode 100644
index 00000000..ced2099b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/IEasyInspectorRowListener.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#include "ToggleButton.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Interface for getting callbacks from the EasyInspectorRow
+ */
+class IEasyInspectorRowListener
+{
+public: // IEasyInspectorRowListener
+ virtual void OnAnimateToggle(CToggleButton::EButtonState inState) = 0;
+ virtual void OnLinkToggle() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Studio/Palettes/Inspector/IInspectableItem.h b/src/Authoring/Studio/Palettes/Inspector/IInspectableItem.h
new file mode 100644
index 00000000..341e46f0
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/IInspectableItem.h
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __IINSPECTABLEITEM_H__
+#define __IINSPECTABLEITEM_H__
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMDataTypes.h"
+#include "UICDMHandles.h"
+#include "UICDMActionInfo.h"
+#include "UICDMMetaData.h"
+#include "UICString.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+class IInspectableItem;
+
+//==============================================================================
+// Abstract Base Classes
+//==============================================================================
+
+enum EInspectableItemTypes {
+ INSPECTABLEITEMTYPE_VANILLA = 1,
+ INSPECTABLEITEMTYPE_PROPERTY,
+ INSPECTABLEITEMTYPE_DEPENDENT,
+ INSPECTABLEITEMTYPE_SLIDE,
+ INSPECTABLEITEMTYPE_OBJECTREFERENCE,
+ INSPECTABLEITEMTYPE_EVENTSOURCE,
+ INSPECTABLEITEMTYPE_ACTION,
+ INSPECTABLEITEMTYPE_CONDITIONS,
+};
+
+//==============================================================================
+/**
+ * @class IInspectableItemChangeListener
+ * @brief Listener class for inspectable item changes.
+ */
+class IInspectableItemChangeListener
+{
+public:
+ virtual void OnInspectablePropertyChanged(IInspectableItem *inProperty) = 0;
+};
+
+class IInspectableObject
+{
+public:
+ virtual UICDM::CUICDMInstanceHandle GetInspectableBaseInstance() = 0;
+ virtual void SetInspectableObject(const UICDM::SObjectRefType &) = 0;
+ virtual UICDM::SObjectRefType GetInspectableObject() = 0;
+};
+
+class IInspectableEvent
+{
+public:
+ virtual UICDM::CUICDMInstanceHandle GetInspectableInstance() = 0;
+ virtual UICDM::CUICDMEventHandle GetInspectableEvent() = 0;
+ virtual void SetInspectableEvent(const UICDM::CUICDMEventHandle &inEventHandle) = 0;
+};
+
+class IInspectableTargetSection : public IInspectableObject
+{
+public:
+ virtual UICDM::CUICDMActionHandle GetInspectableAction() const = 0;
+};
+
+class IInspectableEventSection : public IInspectableObject, public IInspectableEvent
+{
+public:
+ virtual UICDM::CUICDMActionHandle GetInspectableAction() const = 0;
+};
+
+class IInspectableHandlerSection
+{
+public:
+ virtual UICDM::CUICDMActionHandle GetInspectableAction() const = 0;
+ virtual UICDM::CUICDMHandlerHandle GetInspectableHandler() = 0;
+ virtual void SetInspectableHandler(const UICDM::CUICDMHandlerHandle &inHandlerHandle) = 0;
+
+ virtual UICDM::THandlerHandleList GetInspectableHandlerList() = 0;
+ virtual long GetArgumentCount() = 0;
+ virtual IInspectableItem *GetArgument(long inIndex) = 0;
+ virtual Q3DStudio::CString GetInspectableDescription() = 0;
+};
+
+//==============================================================================
+/**
+ * @class IInspectableItem
+ * @brief Abstract base class for inspectable items.
+ */
+class IInspectableItem
+{
+public:
+ virtual ~IInspectableItem() {}
+ virtual EInspectableItemTypes GetInspectableKind() { return INSPECTABLEITEMTYPE_VANILLA; }
+
+ virtual UICDM::HandlerArgumentType::Value
+ GetInspectableSubType() const = 0; // TODO : Make this method name correct
+ virtual Q3DStudio::CString GetInspectableName() const = 0;
+ virtual Q3DStudio::CString GetInspectableFormalName() const = 0;
+ virtual Q3DStudio::CString GetInspectableDescription() const = 0;
+
+ virtual UICDM::SValue GetInspectableData() const = 0;
+ virtual void SetInspectableData(const UICDM::SValue &) = 0;
+
+ // TODO: Remove from here onwards after cleaning up the rest of the UI classes
+ // This is the non-commital version of SetInspectableData, which must be called
+ // after ChangeInspectableData to commit the action.
+ virtual bool GetInspectableReadOnly() const { return false; }
+
+ virtual void ChangeInspectableData(const UICDM::SValue & /*inAttr*/){};
+ virtual void CancelInspectableData(){}
+
+ virtual void AddInspectableChangeListener(IInspectableItemChangeListener * /*inListener*/){};
+ virtual void RemoveInspectableChangeListener(IInspectableItemChangeListener * /*inListener*/){};
+};
+
+//==============================================================================
+/**
+ * Property specialization
+ */
+class IInspectablePropertyItem : public IInspectableItem
+{
+public:
+ EInspectableItemTypes GetInspectableKind() override { return INSPECTABLEITEMTYPE_PROPERTY; }
+ virtual void GetInspectablePropertyList(UICDM::TPropertyHandleList &outList) = 0;
+ virtual UICDM::CUICDMInstanceHandle GetInspectableInstance() = 0;
+};
+
+//==============================================================================
+/**
+ * Attribute specialization
+ */
+class IInspectableAttributeItem : public IInspectableItem
+{
+public:
+ EInspectableItemTypes GetInspectableKind() override { return INSPECTABLEITEMTYPE_DEPENDENT; }
+ virtual float GetInspectableMin() const = 0;
+ virtual float GetInspectableMax() const = 0;
+ virtual UICDM::TMetaDataStringList GetInspectableList() const = 0;
+ virtual UICDM::DataModelDataType::Value GetInspectableType() const = 0;
+ virtual UICDM::AdditionalMetaDataType::Value GetInspectableAdditionalType() const = 0;
+};
+
+//==============================================================================
+/**
+ * Slide specialization
+ */
+class IInspectableSlideItem : public IInspectableItem
+{
+public:
+ EInspectableItemTypes GetInspectableKind() override { return INSPECTABLEITEMTYPE_SLIDE; }
+ virtual void GetSlideNames(std::list<Q3DStudio::CString> &outSlideNames) = 0;
+};
+
+//==============================================================================
+/**
+ * ObjectReference specialiaztion
+ */
+class IInspectableObjectRefItem : public IInspectableObject, public IInspectableItem
+{
+public:
+ EInspectableItemTypes GetInspectableKind() override
+ {
+ return INSPECTABLEITEMTYPE_OBJECTREFERENCE;
+ }
+};
+
+//==============================================================================
+/**
+ * Event specialization
+ */
+class IInspectableEventItem : public IInspectableEvent, public IInspectableItem
+{
+public:
+ EInspectableItemTypes GetInspectableKind() override { return INSPECTABLEITEMTYPE_EVENTSOURCE; }
+};
+
+#endif // #ifndef __IINSPECTABLEITEM_H__
diff --git a/src/Authoring/Studio/Palettes/Inspector/ImageChooser.qml b/src/Authoring/Studio/Palettes/Inspector/ImageChooser.qml
new file mode 100644
index 00000000..7621c5ef
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ImageChooser.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+ border.color: _studioColor3
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ spacing: 10
+ ListView {
+ id: listView
+
+ anchors {
+ fill: parent
+ leftMargin: 8
+ }
+
+ boundsBehavior: Flickable.StopAtBounds
+ spacing: 4
+ clip: true
+
+ ScrollBar.vertical: ScrollBar {}
+
+ model: _imageChooserModel
+
+ delegate: ChooserDelegate {
+ onClicked: _imageChooserView.imageSelected(_imageChooserView.handle, _imageChooserView.instance, filePath);
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.cpp b/src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.cpp
new file mode 100644
index 00000000..98732f74
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ImageChooserModel.h"
+
+ImageChooserModel::ImageChooserModel(QObject *parent)
+ : ChooserModelBase(parent)
+{
+}
+
+ImageChooserModel::~ImageChooserModel()
+{
+}
+
+bool ImageChooserModel::isVisible(const QString &path) const
+{
+ return getIconType(path) == OBJTYPE_IMAGE;
+}
+
+const QVector<ChooserModelBase::FixedItem> ImageChooserModel::getFixedItems() const
+{
+ static const QVector<FixedItem> items = { { OBJTYPE_IMAGE, tr("[None]") } };
+ return items;
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.h b/src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.h
new file mode 100644
index 00000000..288846fd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ImageChooserModel.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef IMAGECHOOSERMODEL_H
+#define IMAGECHOOSERMODEL_H
+
+#include "ChooserModelBase.h"
+
+class ImageChooserModel : public ChooserModelBase
+{
+ Q_OBJECT
+
+public:
+ explicit ImageChooserModel(QObject *parent = nullptr);
+ virtual ~ImageChooserModel();
+
+private:
+ bool isVisible(const QString &path) const override;
+ const QVector<FixedItem> getFixedItems() const override;
+};
+
+#endif // IMAGECHOOSERMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/ImageChooserView.cpp b/src/Authoring/Studio/Palettes/Inspector/ImageChooserView.cpp
new file mode 100644
index 00000000..a3a35217
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ImageChooserView.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ImageChooserView.h"
+#include "ImageChooserModel.h"
+#include "StudioPreferences.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "IDocumentEditor.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMValue.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "StudioPreferences.h"
+
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+ImageChooserView::ImageChooserView(QWidget *parent)
+ : QQuickWidget(parent)
+ , m_model(new ImageChooserModel(this))
+{
+ setWindowTitle(tr("Images"));
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ImageChooserView::initialize);
+}
+
+void ImageChooserView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_resDir"_L1,
+ resourceImageUrl());
+ rootContext()->setContextProperty("_imageChooserView"_L1, this);
+ rootContext()->setContextProperty("_imageChooserModel"_L1, m_model);
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/ImageChooser.qml"_L1));
+}
+
+QSize ImageChooserView::sizeHint() const
+{
+ return {500, 500};
+}
+
+void ImageChooserView::setHandle(int handle)
+{
+ m_handle = handle;
+}
+
+int ImageChooserView::handle() const
+{
+ return m_handle;
+}
+
+void ImageChooserView::setInstance(int instance)
+{
+ m_instance = instance;
+}
+
+int ImageChooserView::instance() const
+{
+ return m_instance;
+}
+
+void ImageChooserView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ QTimer::singleShot(0, this, &ImageChooserView::close);
+}
+
+void ImageChooserView::showEvent(QShowEvent *event)
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+
+ UICDM::SValue value;
+ propertySystem->GetInstancePropertyValue(m_instance, m_handle, value);
+
+ const auto guid = UICDM::get<UICDM::SLong4>(value);
+
+ const auto imageInstance = doc->GetDocumentReader().GetInstanceForGuid(guid);
+ if (imageInstance.Valid()) {
+ const QString path = doc->GetDocumentReader().GetSourcePath(imageInstance).toQString();
+ m_model->setCurrentFile(path);
+ } else {
+ m_model->setCurrentFile(tr("[None]"));
+ }
+
+ QQuickWidget::showEvent(event);
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ImageChooserView.h b/src/Authoring/Studio/Palettes/Inspector/ImageChooserView.h
new file mode 100644
index 00000000..f1738aa9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ImageChooserView.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef IMAGECHOOSERVIEW_H
+#define IMAGECHOOSERVIEW_H
+
+#include <QQuickWidget>
+
+class ImageChooserModel;
+
+class ImageChooserView : public QQuickWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int instance READ instance)
+ Q_PROPERTY(int handle READ handle)
+
+public:
+ explicit ImageChooserView(QWidget *parent = nullptr);
+
+ QSize sizeHint() const override;
+
+ void setHandle(int handle);
+ int handle() const;
+
+ void setInstance(int instance);
+ int instance() const;
+
+Q_SIGNALS:
+ void imageSelected(int handle, int instance, const QString &name);
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+private:
+ void showEvent(QShowEvent *event) override;
+ void initialize();
+ int m_handle = -1;
+ int m_instance = -1;
+ ImageChooserModel *m_model = nullptr;
+};
+
+#endif // IMAGECHOOSERVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectableBase.cpp b/src/Authoring/Studio/Palettes/Inspector/InspectableBase.cpp
new file mode 100644
index 00000000..1c33eb23
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectableBase.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "InspectableBase.h"
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectableBase.h b/src/Authoring/Studio/Palettes/Inspector/InspectableBase.h
new file mode 100644
index 00000000..34973393
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectableBase.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef __INSPECTABLEBASE_H__
+#define __INSPECTABLEBASE_H__
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CInspectorGroup;
+
+#include "Core.h"
+#include "StudioObjectTypes.h"
+
+//==============================================================================
+/**
+ * Parent class of Inspectable types that will appear in the Inspector Palette.
+ */
+class CInspectableBase
+{
+protected:
+ CCore *m_Core; ///<
+
+public:
+ CInspectableBase(CCore *inCore)
+ : m_Core(inCore)
+ {
+ }
+ virtual ~CInspectableBase() {}
+
+ // Interface
+ virtual EStudioObjectType GetObjectType() = 0;
+ // virtual std::wstring GetTypeString() const { return L""; }
+ virtual Q3DStudio::CString GetName() = 0;
+ virtual long GetGroupCount() = 0;
+ virtual CInspectorGroup *GetGroup(long inIndex) = 0;
+ virtual bool IsValid() const = 0;
+ virtual bool IsMaster() = 0;
+};
+
+#endif // #ifndef __INSPECTABLEBASE_H__
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp
new file mode 100644
index 00000000..474fc3e4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.cpp
@@ -0,0 +1,862 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QFileInfo>
+
+#include <functional>
+
+#include "InspectorControlModel.h"
+#include "Core.h"
+#include "Doc.h"
+#include "ControlGraphIterators.h"
+#include "InspectorGroup.h"
+#include "UICDMInspectorGroup.h"
+#include "UICDMInspectorRow.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMInspectable.h"
+#include "UICDMDataCore.h"
+#include "StudioApp.h"
+#include "IDocumentEditor.h"
+#include "Control.h"
+#include "ControlData.h"
+#include "UICDMMetaData.h"
+#include "UICDMSignals.h"
+#include "CmdDataModelDeanimate.h"
+#include "GuideInspectable.h"
+#include "UICDMDataTypes.h"
+#include "IObjectReferenceHelper.h"
+#include "UICDMXML.h"
+#include "UICDMStringTable.h"
+#include "UICFileTools.h"
+#include "UICDMSlideCore.h"
+#include "SlideSystem.h"
+#include "UICDMMaterialInspectable.h"
+#include "ClientDataModelBridge.h"
+#include "IDocumentReader.h"
+#include "IStudioRenderer.h"
+
+static QStringList renderableItems()
+{
+ QStringList renderables;
+ renderables.push_back(QObject::tr("No renderable item"));
+ const CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ Q3DStudio::CString docDir = doc->GetDocumentDirectory();
+ Q3DStudio::CFilePath fullDocPath = doc->GetDocumentPath().GetAbsolutePath();
+ Q3DStudio::CString docFilename = fullDocPath.GetFileName();
+ // First step, find uia file, parse and pull out renderable asset id's but ignoring the
+ // current presentation.
+ std::vector<Q3DStudio::CFilePath> dirFiles;
+ Q3DStudio::CFilePath thePath(docDir);
+ thePath.ListFilesAndDirectories(dirFiles);
+ for (size_t idx = 0, end = dirFiles.size(); idx < end; ++idx) {
+ if (!dirFiles[idx].IsFile())
+ continue;
+
+ Q3DStudio::CString ext = dirFiles[idx].GetExtension();
+ if (!ext.CompareNoCase("uia"))
+ continue;
+
+ UICDM::TStringTablePtr theStringTable
+ = UICDM::IStringTable::CreateStringTable();
+ std::shared_ptr<UICDM::IDOMFactory> theDomFact =
+ UICDM::IDOMFactory::CreateDOMFactory(theStringTable);
+ Q3DStudio::CString fullFile = dirFiles[idx];
+ qt3ds::foundation::CFileSeekableIOStream theStream(
+ fullFile, qt3ds::foundation::FileReadFlags());
+
+ UICDM::SDOMElement *theElem
+ = UICDM::CDOMSerializer::Read(*theDomFact, theStream);
+ if (theElem) {
+ std::shared_ptr<UICDM::IDOMReader> theReader =
+ UICDM::IDOMReader::CreateDOMReader(*theElem, theStringTable,
+ theDomFact);
+ if (theReader->MoveToFirstChild("assets")) {
+ for (bool success = theReader->MoveToFirstChild(); success;
+ success = theReader->MoveToNextSibling()) {
+ if (UICDM::AreEqual(theReader->GetElementName(), L"presentation") ||
+ UICDM::AreEqual(theReader->GetElementName(), L"presentation-qml")) {
+ UICDM::TXMLStr src = nullptr;
+ UICDM::TXMLStr id = nullptr;
+ theReader->Att("src", src);
+ theReader->Att("id", id);
+ if (docFilename != src.c_str())
+ renderables.push_back(QString::fromLatin1(id.c_str()));
+ } else if (UICDM::AreEqual(theReader->GetElementName(),
+ L"renderplugin")) {
+ const wchar_t *id = nullptr;
+ theReader->UnregisteredAtt(L"id", id);
+ renderables.push_back(QString::fromWCharArray(id));
+ }
+ }
+ }
+ }
+ }
+ // second step, find the renderable plugins.
+ {
+ Q3DStudio::CFilePath pluginDir
+ = Q3DStudio::CFilePath::CombineBaseAndRelative(docDir, "plugins");
+ if (pluginDir.Exists() && pluginDir.IsDirectory()) {
+ std::vector<Q3DStudio::CFilePath> dirFiles;
+ pluginDir.ListFilesAndDirectories(dirFiles);
+ for (size_t idx = 0, end = dirFiles.size(); idx < end; ++idx) {
+ if (dirFiles[idx].IsFile()) {
+ Q3DStudio::CFilePath relPath =
+ Q3DStudio::CFilePath::GetRelativePathFromBase(docDir, dirFiles[idx]);
+ renderables.push_back(relPath.toQString());
+ }
+ }
+ }
+ }
+ std::sort(renderables.begin() + 1, renderables.end());
+ return renderables;
+}
+
+static std::pair<bool, bool> getSlideCharacteristics(UICDM::CUICDMInstanceHandle instance,
+ const UICDM::ISlideCore &slideCore,
+ const UICDM::ISlideSystem &slideSystem)
+{
+ // Get the slide from the instance.
+ UICDM::CUICDMSlideHandle slide = slideCore.GetSlideByInstance(instance);
+ UICDM::CUICDMSlideHandle master = slideSystem.GetMasterSlide(slide);
+ int index = (int)slideSystem.GetSlideIndex(slide);
+ int count = (int)slideSystem.GetSlideCount(master);
+ bool hasNextSlide = index > 0 && index < count - 1;
+ bool hasPreviousSlide = index > 1;
+ return std::make_pair(hasNextSlide, hasPreviousSlide);
+}
+
+InspectorControlModel::InspectorControlModel(QObject *parent)
+ : QAbstractListModel(parent)
+ , m_UpdatableEditor(*g_StudioApp.GetCore()->GetDoc())
+{
+}
+
+void InspectorControlModel::setInspectable(CInspectableBase *inInspectable)
+{
+ const auto signalProvider
+ = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+
+ if (m_notifier.get() == nullptr) {
+ m_notifier = signalProvider->ConnectInstancePropertyValue(
+ std::bind(&InspectorControlModel::notifyInstancePropertyValue,
+ this, std::placeholders::_1, std::placeholders::_2));
+ }
+ if (m_slideNotifier.get() == nullptr) {
+ m_slideNotifier = signalProvider->ConnectSlideRearranged(
+ std::bind(&InspectorControlModel::onSlideRearranged, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ }
+
+ if (m_inspectableBase != inInspectable) {
+ m_inspectableBase = inInspectable;
+ rebuildTree();
+ }
+}
+
+void InspectorControlModel::notifyInstancePropertyValue(UICDM::CUICDMInstanceHandle inHandle,
+ UICDM::CUICDMPropertyHandle inProperty)
+{
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ bool changed = false;
+ for (int row = 0; row < m_groupElements.count(); ++row) {
+ auto group = m_groupElements[row];
+ for (int p = 0; p < group.controlElements.count(); ++p) {
+ QVariant& element = group.controlElements[p];
+ InspectorControlBase *property = element.value<InspectorControlBase *>();
+ UICDM::CUICDMInstanceHandle imageInstance;
+ if (property->m_dataType == UICDM::DataModelDataType::Long4
+ && property->m_property.Valid()) {
+ imageInstance = doc->GetDocumentReader().GetImageInstanceForProperty(
+ property->m_instance, property->m_property);
+ }
+ if (property->m_property == inProperty || imageInstance == inHandle) {
+ updatePropertyValue(property);
+ changed = true;
+ }
+ }
+ }
+ if (changed)
+ Q_EMIT dataChanged(index(0), index(rowCount() - 1));
+}
+
+QVariant InspectorControlModel::getPropertyValue(long instance, int handle)
+{
+ for (int row = 0; row < m_groupElements.count(); ++row) {
+ auto group = m_groupElements[row];
+ for (int p = 0; p < group.controlElements.count(); ++p) {
+ QVariant& element = group.controlElements[p];
+ InspectorControlBase *property = element.value<InspectorControlBase *>();
+ if (property->m_property == UICDM::CDataModelHandle(handle))
+ return property->m_value;
+ }
+ }
+ return {};
+}
+
+void InspectorControlModel::setMaterials(std::vector<Q3DStudio::CFilePath> &materials)
+{
+ m_materials.clear();
+ const Q3DStudio::CString base = g_StudioApp.GetCore()->GetDoc()->GetDocumentDirectory();
+
+ for (Q3DStudio::CFilePath path : materials) {
+
+ const QString relativePath = path.toQString();
+ const Q3DStudio::CFilePath absolutePath
+ = Q3DStudio::CFilePath::CombineBaseAndRelative(base, path);
+
+ const QString name = g_StudioApp.GetCore()->GetDoc()->GetDocumentReader()
+ .GetCustomMaterialName(absolutePath).toQString();
+
+ m_materials.push_back({name, relativePath});
+ }
+}
+
+InspectorControlBase* InspectorControlModel::createMaterialItem(CUICDMInspectable *inspectable,
+ int groupIndex)
+{
+ const auto studio = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+ InspectorControlBase *item = new InspectorControlBase;
+ item->m_instance = inspectable->GetGroupInstance(groupIndex);
+
+ item->m_title = tr("Material Type");
+
+ CClientDataModelBridge *theBridge = studio->GetClientDataModelBridge();
+ EStudioObjectType theType = theBridge->GetObjectType(item->m_instance);
+ item->m_dataType = UICDM::DataModelDataType::StringRef;
+ item->m_propertyType = UICDM::AdditionalMetaDataType::None;
+ item->m_tooltip = tr("Type of material being used or custom material");
+
+ item->m_animatable = false;
+
+ QStringList values;
+ values.push_back(tr("Standard Material"));
+ values.push_back(tr("Referenced Material"));
+
+ const QString sourcePath = theBridge->GetSourcePath(item->m_instance).toQString();
+
+ switch (theType) {
+
+ case OBJTYPE_MATERIAL:
+ item->m_value = tr("Standard Material");
+ break;
+
+ case OBJTYPE_REFERENCEDMATERIAL:
+ item->m_value = tr("Referenced Material");
+ break;
+ }
+
+ for (size_t matIdx = 0, end = m_materials.size(); matIdx < end; ++matIdx) {
+ values.push_back(m_materials[matIdx].m_name);
+ if (m_materials[matIdx].m_relativePath == sourcePath)
+ item->m_value = values.last();
+ }
+
+ item->m_values = values;
+
+ return item;
+}
+
+InspectorControlBase* InspectorControlModel::createItem(CUICDMInspectable *inspectable,
+ Q3DStudio::CUICDMInspectorRow *row,
+ int groupIndex)
+{
+ return createItem(inspectable, row->GetMetaDataPropertyInfo(), groupIndex);
+}
+
+InspectorControlBase* InspectorControlModel::createItem(CUICDMInspectable *inspectable,
+ const UICDM::SMetaDataPropertyInfo &metaProperty,
+ int groupIndex)
+{
+ const auto studio = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+ if (metaProperty.m_IsHidden)
+ return nullptr;
+
+ InspectorControlBase *item = new InspectorControlBase;
+ item->m_property = metaProperty.m_Property;
+ item->m_instance = inspectable->GetGroupInstance(groupIndex);
+
+ Q3DStudio::CString title;
+ title.Assign(metaProperty.m_FormalName.c_str());
+ if (title.IsEmpty())
+ title.Assign(metaProperty.m_Name.c_str());
+ item->m_title = title.toQString();
+
+ const auto propertySystem = studio->GetPropertySystem();
+ item->m_dataType = propertySystem->GetDataType(metaProperty.m_Property);
+ item->m_propertyType = static_cast<UICDM::AdditionalMetaDataType::Value>
+ (propertySystem->GetAdditionalMetaDataType(item->m_instance, metaProperty.m_Property));
+ item->m_tooltip = Q3DStudio::CString(metaProperty.m_Description.c_str()).toQString();
+
+ item->m_animatable = metaProperty.m_Animatable &&
+ studio->GetAnimationSystem()->IsPropertyAnimatable(item->m_instance,
+ metaProperty.m_Property);
+ if (item->m_animatable) {
+ item->m_animated = studio->GetAnimationSystem()->IsPropertyAnimated(item->m_instance,
+ metaProperty.m_Property);
+
+ // Update the Animate Toggle on undo/redo
+ auto signalProvider = studio->GetFullSystemSignalProvider();
+ item->m_connections.push_back(signalProvider->ConnectAnimationCreated(
+ std::bind(&InspectorControlModel::updateAnimateToggleState,
+ this, item)));
+
+ item->m_connections.push_back(signalProvider->ConnectAnimationDeleted(
+ std::bind(&InspectorControlModel::updateAnimateToggleState,
+ this, item)));
+ }
+
+ // synchronize the value itself
+ updatePropertyValue(item);
+ return item;
+}
+
+UICDM::SValue InspectorControlModel::currentPropertyValue(long instance, int handle)
+{
+ UICDM::SValue value;
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ auto studioSystem = doc->GetStudioSystem();
+ const auto propertySystem = studioSystem->GetPropertySystem();
+ propertySystem->GetInstancePropertyValue(instance, handle, value);
+
+ return value;
+}
+
+void InspectorControlModel::updateAnimateToggleState(InspectorControlBase* inItem)
+{
+ const auto studio = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+ bool animated = studio->GetAnimationSystem()->IsPropertyAnimated(inItem->m_instance,
+ inItem->m_property);
+ if (animated != inItem->m_animated) {
+ inItem->m_animated = animated;
+ Q_EMIT inItem->animatedChanged();
+ }
+}
+
+bool InspectorControlModel::isTreeRebuildRequired(CInspectableBase* inspectBase) const
+{
+ if (inspectBase != m_inspectableBase)
+ return true;
+
+ long theCount = m_inspectableBase->GetGroupCount();
+ if (m_groupElements.size() != theCount)
+ return true;
+
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ const CInspectorGroup *theInspectorGroup = m_inspectableBase->GetGroup(theIndex);
+ if (m_groupElements.at(theIndex).groupTitle != theInspectorGroup->GetName())
+ return true;
+ }
+
+ return false;
+}
+
+bool InspectorControlModel::isGroupRebuildRequired(CInspectableBase* inspectable, int theIndex) const
+{
+ Q_ASSERT(theIndex < m_groupElements.size());
+ const CInspectorGroup *theInspectorGroup = inspectable->GetGroup(theIndex);
+ const auto existingGroup = m_groupElements.at(theIndex);
+ if (existingGroup.groupTitle != theInspectorGroup->GetName())
+ return true;
+
+ if (const auto cdmInspectable = dynamic_cast<CUICDMInspectable *>(inspectable)) {
+ int existingIndex = 0;
+ if (const auto group = dynamic_cast<const CUICDMInspectorGroup *>(theInspectorGroup)) {
+ const auto materialGroup
+ = dynamic_cast<const UICDMMaterialInspectorGroup *>(group);
+ if (materialGroup && materialGroup->isMaterialGroup()) {
+ auto i = existingGroup.controlElements.at(existingIndex++).value<InspectorControlBase*>();
+ if (i->m_instance != cdmInspectable->GetGroupInstance(theIndex))
+ return true;
+ }
+
+ if ((existingGroup.controlElements.size() - existingIndex) != group->GetRows().size())
+ return true;
+
+ for (const auto row : group->GetRows()) {
+ auto i = existingGroup.controlElements.at(existingIndex++).value<InspectorControlBase*>();
+ if (i->m_instance != cdmInspectable->GetGroupInstance(theIndex))
+ return true;
+
+ if (i->m_property != row->GetMetaDataPropertyInfo().m_Property)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+auto InspectorControlModel::computeTree(CInspectableBase* inspectBase)
+ -> QVector<GroupInspectorControl>
+{
+ QVector<GroupInspectorControl> result;
+
+ if (inspectBase) {
+ long theCount = inspectBase->GetGroupCount();
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ result.append(computeGroup(inspectBase, theIndex));
+ }
+ }
+
+ return result;
+}
+
+auto InspectorControlModel::computeGroup(CInspectableBase* inspectable,
+ int theIndex)
+ -> GroupInspectorControl
+{
+ CInspectorGroup* theInspectorGroup = inspectable->GetGroup(theIndex);
+ GroupInspectorControl result;
+ result.groupTitle = theInspectorGroup->GetName();
+
+ if (const auto cdmInspectable = dynamic_cast<CUICDMInspectable *>(inspectable)) {
+ if (const auto group = dynamic_cast<CUICDMInspectorGroup *>(theInspectorGroup)) {
+ const auto materialGroup
+ = dynamic_cast<UICDMMaterialInspectorGroup *>(group);
+ if (materialGroup && materialGroup->isMaterialGroup()) {
+ InspectorControlBase *item = createMaterialItem(cdmInspectable, theIndex);
+ if (item) {
+ result.controlElements.push_back(QVariant::fromValue(item));
+ }
+ }
+ for (const auto row : group->GetRows()) {
+ InspectorControlBase *item = createItem(cdmInspectable, row, theIndex);
+ if (!item)
+ continue;
+
+ result.controlElements.push_back(QVariant::fromValue(item));
+ }
+ }
+ } else if (dynamic_cast<SGuideInspectableImpl *>(inspectable)) {
+ //KDAB_FIXME: load row element (How ?)
+ }
+
+ return result;
+}
+
+void InspectorControlModel::rebuildTree()
+{
+ beginResetModel();
+ m_groupElements = computeTree(m_inspectableBase);
+ endResetModel();
+}
+
+int InspectorControlModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_groupElements.count();
+}
+
+void InspectorControlModel::updatePropertyValue(InspectorControlBase *element) const
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ auto studioSystem = doc->GetStudioSystem();
+ const auto propertySystem = studioSystem->GetPropertySystem();
+ UICDM::SValue value;
+ const auto instance = element->m_instance;
+ propertySystem->GetInstancePropertyValue(instance, element->m_property, value);
+
+ const auto metaDataProvider = doc->GetStudioSystem()->GetActionMetaData();
+ const auto info = metaDataProvider->GetMetaDataPropertyInfo(
+ metaDataProvider->GetMetaDataProperty(instance, element->m_property));
+ switch (element->m_dataType) {
+ case UICDM::DataModelDataType::String:
+ element->m_value = UICDM::get<QString>(value);
+ //intentional fall-through
+ case UICDM::DataModelDataType::StringOrInt:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::StringList) {
+ QStringList stringlist = UICDM::get<QStringList>(info->m_MetaDataData);
+ auto slideSystem = studioSystem->GetSlideSystem();
+
+ if (element->m_title == QStringLiteral("Play Mode")) {
+ std::pair<bool, bool> slideData(
+ getSlideCharacteristics(element->m_instance, *studioSystem->GetSlideCore(),
+ *slideSystem));
+ bool hasNextSlide(slideData.first);
+ bool hasPreviousSlide(slideData.second);
+ if (!hasNextSlide && !hasPreviousSlide)
+ stringlist.removeAll("Play Through To...");
+ } else if (element->m_title == QStringLiteral("Play Through To")) {
+ // the code duplication is intentional as we may ask for slide characteristics
+ // only if the property refers to slides
+ std::pair<bool, bool> slideData(
+ getSlideCharacteristics(element->m_instance, *studioSystem->GetSlideCore(),
+ *slideSystem));
+ bool hasNextSlide(slideData.first);
+ bool hasPreviousSlide(slideData.second);
+ if (!hasNextSlide)
+ stringlist.removeAll("Next");
+ if (!hasPreviousSlide)
+ stringlist.removeAll("Previous");
+
+ auto itemCount = stringlist.count();
+ QString listOpt;
+ int selectedSlideHandle = 0;
+ int selectedIndex = -1;
+ UICDM::SStringOrInt stringOrInt = UICDM::get<UICDM::SStringOrInt>(value);
+ if (stringOrInt.GetType() == UICDM::SStringOrIntTypes::String)
+ listOpt = QString::fromWCharArray(UICDM::get<UICDM::TDataStrPtr>
+ (stringOrInt.m_Value)->GetData());
+ else
+ selectedSlideHandle = UICDM::get<long>(stringOrInt.m_Value);
+
+ selectedIndex = stringlist.indexOf(listOpt);
+ // Add the slide names (exclude the master slide)
+ auto bridge = studioSystem->GetClientDataModelBridge();
+ auto slideHandle = slideSystem->GetSlideByInstance(instance);
+ auto masterSlide = slideSystem->GetMasterSlide(slideHandle);
+ long slideCount = (long)slideSystem->GetSlideCount(masterSlide);
+ for (long slideIndex = 1; slideIndex < slideCount; ++slideIndex) {
+ auto currentSlide = slideSystem->GetSlideByIndex(masterSlide, slideIndex);
+ auto currentInstance = slideSystem->GetSlideInstance(currentSlide);
+
+ QString slideName = bridge->GetName(currentInstance).toQString();
+ //hack to add a separator before the item
+ if (slideIndex == 1 && itemCount > 0)
+ slideName += "|separator";
+ stringlist.append(slideName);
+
+ if (currentSlide.GetHandleValue() == selectedSlideHandle)
+ selectedIndex = slideIndex + itemCount - 1;
+ }
+
+ element->m_value = QString(selectedIndex > 0 ? stringlist[selectedIndex]
+ : stringlist.first()).replace("|separator", "");
+ }
+ element->m_values = stringlist;
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Import) {
+ QStringList stringlist = UICDM::get<QStringList>(info->m_MetaDataData);
+ element->m_values = stringlist;
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Renderable) {
+ element->m_values = renderableItems();
+ if (element->m_value.toString().isEmpty())
+ element->m_value = element->m_values.toStringList().at(0);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::MultiLine) {
+ element->m_value = UICDM::get<QString>(value);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Font) {
+ std::vector<Q3DStudio::CString> fontNames;
+ g_StudioApp.GetCore()->GetDoc()->GetProjectFonts(fontNames);
+ QStringList possibleValues;
+ for (const auto &fontName: fontNames)
+ possibleValues.append(fontName.toQString());
+ element->m_values = possibleValues;
+ element->m_value = UICDM::get<QString>(value);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Mesh) {
+ QString meshValue = UICDM::get<QString>(value);
+ Q3DStudio::CFilePath theSelectionItem(Q3DStudio::CString::fromQString(meshValue));
+ Q3DStudio::CFilePath theSelectionWithoutId(theSelectionItem.GetPathWithoutIdentifier());
+ if (theSelectionWithoutId.size())
+ element->m_value = theSelectionWithoutId.GetFileName().toQString();
+ else
+ element->m_value = theSelectionItem.GetIdentifier().toQString();
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Texture) {
+ QFileInfo fileInfo(UICDM::get<QString>(value));
+ element->m_value = fileInfo.fileName();
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::PathBuffer) {
+ element->m_value = UICDM::get<QString>(value);
+ } else {
+ qWarning() << "KDAB_TODO: InspectorControlModel::updatePropertyValue: need to implement:"
+ << element->m_dataType << " element->m_propertyType : "
+ << element->m_propertyType;
+ }
+ break;
+ case UICDM::DataModelDataType::StringRef:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::None) {
+ element->m_value = UICDM::get<QString>(value);
+ }
+ break;
+ case UICDM::DataModelDataType::Bool:
+ element->m_value = UICDM::get<bool>(value);
+ break;
+ case UICDM::DataModelDataType::Long4:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::Image) {
+ UICDM::Option<UICDM::SLong4> guid = UICDM::get<UICDM::SLong4>(value);
+ UICDM::CUICDMInstanceHandle imageInstance = doc->GetDocumentReader()
+ .GetInstanceForGuid(guid);
+ if (imageInstance.Valid()) {
+ Q3DStudio::CString path = doc->GetDocumentReader().GetSourcePath(imageInstance);
+ Q3DStudio::CFilePath relPath(path);
+ element->m_value = QVariant(relPath.GetFileName().toQString());
+ } else {
+ element->m_value = QVariant(QString(""));
+ }
+ } else {
+ qWarning() << "KDAB_TODO: InspectorControlModel::updatePropertyValue: need to implement:"
+ << element->m_dataType << " " << element->m_title;
+ }
+ break;
+ case UICDM::DataModelDataType::Long:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::Range) {
+ element->m_value = UICDM::get<int>(value);
+ const UICDM::SMetaDataRange ranges = UICDM::get<UICDM::SMetaDataRange>(info->m_MetaDataData);
+ const QList<double> rangesValues{ranges.m_Min, ranges.m_Max};
+ element->m_values = QVariant::fromValue<QList<double> >(rangesValues);
+ }
+ else if (element->m_propertyType == UICDM::AdditionalMetaDataType::ShadowMapResolution) {
+ element->m_value = UICDM::get<int>(value);
+ } else {
+ qWarning() << "KDAB_TODO: InspectorControlModel::updatePropertyValue: need to implement:"
+ << element->m_dataType;
+ }
+ break;
+ case UICDM::DataModelDataType::Float3:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::Color) {
+ element->m_value = UICDM::get<QColor>(value);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Rotation) {
+ const QVector3D theFloat3 = UICDM::get<QVector3D>(value);
+ const QList<double> float3Values{theFloat3.x(), theFloat3.y(), theFloat3.z()};
+ element->m_values = QVariant::fromValue<QList<double> >(float3Values);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::None) {
+ const QVector3D theFloat3 = UICDM::get<QVector3D>(value);
+ const QList<double> float3Values{theFloat3.x(), theFloat3.y(), theFloat3.z()};
+ element->m_values = QVariant::fromValue<QList<double> >(float3Values);
+ }
+ break;
+ case UICDM::DataModelDataType::Float:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::None) {
+ element->m_value = UICDM::get<float>(value);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::Range) {
+ element->m_value = UICDM::get<float>(value);
+ const UICDM::SMetaDataRange ranges = UICDM::get<UICDM::SMetaDataRange>(info->m_MetaDataData);
+ const QList<double> rangesValues{ranges.m_Min, ranges.m_Max};
+ element->m_values = QVariant::fromValue<QList<double> >(rangesValues);
+ } else if (element->m_propertyType == UICDM::AdditionalMetaDataType::FontSize) {
+ element->m_value = UICDM::get<float>(value);
+ }
+ break;
+ case UICDM::DataModelDataType::ObjectRef:
+ if (element->m_propertyType == UICDM::AdditionalMetaDataType::ObjectRef) {
+ IObjectReferenceHelper *objRefHelper = doc->GetDataModelObjectReferenceHelper();
+ if (objRefHelper) {
+ UICDM::CUICDMInstanceHandle refInstance = objRefHelper->Resolve(value, instance);
+ element->m_value = objRefHelper->LookupObjectFormalName(refInstance).toQString();
+ }
+ }
+ break;
+ default:
+ qWarning() << "TODO: InspectorControlModel::updatePropertyValue: I've no idea how to handle this datatype"
+ << element->m_dataType;
+ break;
+ }
+ Q_EMIT element->valueChanged();
+ Q_EMIT element->valuesChanged();
+}
+
+void InspectorControlModel::refreshRenderables()
+{
+ for (int row = 0; row < m_groupElements.count(); ++row) {
+ auto group = m_groupElements[row];
+ for (int p = 0; p < group.controlElements.count(); ++p) {
+ QVariant& element = group.controlElements[p];
+ InspectorControlBase *property = element.value<InspectorControlBase *>();
+ if (property->m_propertyType == UICDM::AdditionalMetaDataType::Renderable)
+ updatePropertyValue(property);
+ }
+ }
+}
+
+void InspectorControlModel::refresh()
+{
+ for (int row = 0; row < m_groupElements.count(); ++row) {
+ auto group = m_groupElements[row];
+ for (int p = 0; p < group.controlElements.count(); ++p) {
+ QVariant& element = group.controlElements[p];
+ InspectorControlBase *property = element.value<InspectorControlBase *>();
+ if (property->m_property.Valid())
+ updatePropertyValue(property);
+ }
+ }
+ Q_EMIT dataChanged(index(0), index(rowCount() - 1));
+}
+
+void InspectorControlModel::setMaterialTypeValue(long instance, int handle, const QVariant &value)
+{
+ Q_UNUSED(handle);
+ const QString typeValue = value.toString();
+ Q3DStudio::CString v;
+
+ if (typeValue == tr("Standard Material")) {
+ v = Q3DStudio::CString("Standard Material");
+ } else if (typeValue == tr("Referenced Material")) {
+ v = Q3DStudio::CString("Referenced Material");
+ } else {
+ for (size_t matIdx = 0, end = m_materials.size(); matIdx < end; ++matIdx) {
+ if (m_materials[matIdx].m_name == typeValue) {
+ v = Q3DStudio::CString::fromQString(m_materials[matIdx].m_relativePath);
+ break;
+ }
+ }
+ }
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(),
+ QObject::tr("Set Property"))->SetMaterialType(instance, v);
+}
+
+void InspectorControlModel::setRenderableValue(long instance, int handle, const QVariant &value)
+{
+ UICDM::SValue oldValue = currentPropertyValue(instance, handle);
+
+ QString v = value.toString();
+ if (v == QObject::tr("No renderable item"))
+ v = QString();
+
+ if (v == UICDM::get<QString>(oldValue))
+ return;
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), QObject::tr("Set Property"))
+ ->SetInstancePropertyValueAsRenderable(instance, handle,
+ Q3DStudio::CString::fromQString(v));
+}
+
+void InspectorControlModel::setPropertyValue(long instance, int handle, const QVariant &value, bool commit)
+{
+ UICDM::SValue oldValue = currentPropertyValue(instance, handle);
+ UICDM::SValue v = value;
+
+ if (v == oldValue)
+ return;
+
+ // some properties may initialize OpenGL resources (e.g. loading meshes will
+ // initialize vertex buffers), so the renderer's OpenGL context must be current
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ theRenderer.MakeContextCurrent();
+
+ m_UpdatableEditor.EnsureEditor(L"Set Property", __FILE__, __LINE__)
+ .SetInstancePropertyValue(instance, handle, v);
+
+ theRenderer.ReleaseContext();
+
+ m_UpdatableEditor.FireImmediateRefresh(instance);
+
+ if (commit) {
+ m_UpdatableEditor.CommitEditor();
+
+ if (isTreeRebuildRequired(m_inspectableBase)) {
+ rebuildTree();
+ } else {
+ // group strucutre is intact, let's walk to see which rows changed
+ long theCount = m_inspectableBase->GetGroupCount();
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ if (isGroupRebuildRequired(m_inspectableBase, theIndex)) {
+ m_groupElements[theIndex] = computeGroup(m_inspectableBase, theIndex);
+ Q_EMIT dataChanged(index(theIndex), index(theIndex));
+ }
+ }
+ }
+
+ } // of commit
+}
+
+void InspectorControlModel::setSlideSelection(long instance, int handle, int index,
+ const QStringList &list)
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ auto studioSystem = doc->GetStudioSystem();
+ const auto metaDataProvider = doc->GetStudioSystem()->GetActionMetaData();
+ const auto info = metaDataProvider->GetMetaDataPropertyInfo(
+ metaDataProvider->GetMetaDataProperty(instance, handle));
+ QStringList stringlist = UICDM::get<QStringList>(info->m_MetaDataData);
+
+ auto slideSystem = studioSystem->GetSlideSystem();
+ std::pair<bool, bool> slideData(
+ getSlideCharacteristics(instance, *studioSystem->GetSlideCore(),
+ *slideSystem));
+ bool hasNextSlide(slideData.first);
+ bool hasPreviousSlide(slideData.second);
+ UICDM::SStringOrInt newSelectedData;
+ if (!hasNextSlide)
+ stringlist.removeAll("Next");
+ if (!hasPreviousSlide)
+ stringlist.removeAll("Previous");
+
+ auto itemCount = stringlist.count();
+ if (index < itemCount) {
+ newSelectedData = UICDM::SStringOrInt(std::make_shared<UICDM::CDataStr>
+ (Q3DStudio::CString::fromQString(list[index]).c_str()));
+ } else {
+ auto slideHandle = slideSystem->GetSlideByInstance(instance);
+ auto masterSlide = slideSystem->GetMasterSlide(slideHandle);
+ long slideIndex = index - itemCount + 1;
+ auto newSelectedSlide = slideSystem->GetSlideByIndex(masterSlide, slideIndex);
+ newSelectedData = UICDM::SStringOrInt((long)newSelectedSlide);
+ }
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), QObject::tr("Set Property"))
+ ->SetInstancePropertyValue(instance, handle, newSelectedData);
+}
+
+void InspectorControlModel::setPropertyAnimated(long instance, int handle, bool animated)
+{
+ CCmd* cmd = nullptr;
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ if (animated)
+ cmd = new CCmdDataModelAnimate(doc, instance, handle);
+ else
+ cmd = new CCmdDataModelDeanimate(doc, instance, handle);
+
+ g_StudioApp.GetCore()->ExecuteCommand(cmd);
+}
+
+void InspectorControlModel::onSlideRearranged(const UICDM::CUICDMSlideHandle &inMaster,
+ int inOldIndex, int inNewIndex)
+{
+ Q_UNUSED(inMaster);
+ Q_UNUSED(inOldIndex);
+ Q_UNUSED(inNewIndex);
+ rebuildTree();
+}
+
+QVariant InspectorControlModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(),index.parent()))
+ return {};
+
+ const auto row = index.row();
+
+ switch (role) {
+ case GroupValuesRole:
+ return m_groupElements.at(row).controlElements;
+ case GroupTitleRole:
+ return m_groupElements.at(row).groupTitle;
+ }
+ return {};
+}
+
+QHash<int, QByteArray> InspectorControlModel::roleNames() const
+{
+ auto names = QAbstractListModel::roleNames();
+ names.insert(GroupValuesRole, "values");
+ names.insert(GroupTitleRole, "title");
+ return names;
+}
+
+InspectorControlBase::~InspectorControlBase()
+{
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h
new file mode 100644
index 00000000..20718039
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlModel.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INSPECTORCONTROLMODEL_H
+#define INSPECTORCONTROLMODEL_H
+
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qvector.h>
+
+#include "UICDMValue.h"
+#include "UICDMMetaDataValue.h"
+#include "UICDMMetaDataTypes.h"
+#include "UICFileTools.h"
+
+#include "IDocumentEditor.h"
+
+class CInspectableBase;
+class CUICDMInspectable;
+class SGuideInspectableImpl;
+
+namespace UICDM {
+class ISignalConnection;
+typedef std::shared_ptr<ISignalConnection> TSignalConnectionPtr;
+}
+
+namespace Q3DStudio
+{
+class CUICDMInspectorRow;
+}
+
+class InspectorControlBase : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(UICDM::DataModelDataType::Value dataType MEMBER m_dataType CONSTANT)
+ Q_PROPERTY(UICDM::AdditionalMetaDataType::Value propertyType MEMBER m_propertyType CONSTANT)
+ Q_PROPERTY(QVariant value MEMBER m_value NOTIFY valueChanged)
+ Q_PROPERTY(QVariant values MEMBER m_values NOTIFY valuesChanged)
+ Q_PROPERTY(QString title MEMBER m_title CONSTANT)
+ Q_PROPERTY(QString toolTip MEMBER m_tooltip CONSTANT)
+ Q_PROPERTY(int instance MEMBER m_instance CONSTANT)
+ Q_PROPERTY(int handle MEMBER m_property CONSTANT)
+
+ Q_PROPERTY(bool animatable MEMBER m_animatable CONSTANT)
+ Q_PROPERTY(bool animated MEMBER m_animated NOTIFY animatedChanged)
+
+public:
+ virtual ~InspectorControlBase();
+
+Q_SIGNALS:
+ void valueChanged();
+ void valuesChanged();
+ void animatedChanged();
+
+public:
+ UICDM::DataModelDataType::Value m_dataType;
+ UICDM::AdditionalMetaDataType::Value m_propertyType;
+ QVariant m_value;
+ QVariant m_values;
+ QString m_title;
+ QString m_tooltip;
+
+ UICDM::CUICDMInstanceHandle m_instance;
+ UICDM::CUICDMPropertyHandle m_property;
+
+ bool m_animatable = false;
+ bool m_animated = false;
+
+ std::vector<UICDM::TSignalConnectionPtr> m_connections;
+};
+
+class InspectorControlModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ explicit InspectorControlModel(QObject *parent);
+ ~InspectorControlModel() = default;
+
+ enum Roles {
+ GroupValuesRole = Qt::UserRole + 1,
+ GroupTitleRole
+ };
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+
+ QHash<int, QByteArray> roleNames() const override;
+
+ void setInspectable(CInspectableBase *inInspectable);
+ void setMaterials(std::vector<Q3DStudio::CFilePath> &materials);
+ void refreshRenderables();
+ void refresh();
+
+ QVariant getPropertyValue(long instance, int handle);
+
+ Q_INVOKABLE void setMaterialTypeValue(long instance, int handle, const QVariant &value);
+ Q_INVOKABLE void setRenderableValue(long instance, int handle, const QVariant &value);
+ Q_INVOKABLE void setPropertyValue(long instance, int handle, const QVariant &value, bool commit = true);
+ Q_INVOKABLE void setSlideSelection(long instance, int handle, int index,
+ const QStringList &list);
+ Q_INVOKABLE void setPropertyAnimated(long instance, int handle, bool animated);
+
+private:
+ void onSlideRearranged(const UICDM::CUICDMSlideHandle &inMaster, int inOldIndex,
+ int inNewIndex);
+
+
+ struct GroupInspectorControl {
+ QString groupTitle;
+ QVariantList controlElements;
+
+ ~GroupInspectorControl() {
+ //for (auto element : controlElements)
+ // element.value<QObject *>()->deleteLater();
+ }
+ };
+
+ mutable QVector<GroupInspectorControl> m_groupElements;
+ CInspectableBase *m_inspectableBase = nullptr;
+
+ struct MaterialEntry
+ {
+ QString m_name;
+ QString m_relativePath;
+ };
+
+ std::vector<MaterialEntry> m_materials;
+
+ Q3DStudio::CUpdateableDocumentEditor m_UpdatableEditor;
+
+ void updatePropertyValue(InspectorControlBase *element) const;
+ void rebuildTree();
+ void notifyInstancePropertyValue(UICDM::CUICDMInstanceHandle, UICDM::CUICDMPropertyHandle inProperty);
+ void updateAnimateToggleState(InspectorControlBase* inItem);
+
+ std::shared_ptr<UICDM::ISignalConnection> m_notifier;
+ std::shared_ptr<UICDM::ISignalConnection> m_slideNotifier;
+
+ InspectorControlBase *createMaterialItem(CUICDMInspectable *inspectable, int groupIndex);
+ InspectorControlBase *createItem(CUICDMInspectable *inspectable,
+ Q3DStudio::CUICDMInspectorRow *row, int groupIndex);
+ InspectorControlBase *createItem(CUICDMInspectable *inspectable,
+ const UICDM::SMetaDataPropertyInfo &metaProperty,
+ int groupIndex);
+
+ UICDM::SValue currentPropertyValue(long instance, int handle);
+
+ QVector<GroupInspectorControl> computeTree(CInspectableBase *inspectBase);
+ bool isTreeRebuildRequired(CInspectableBase *inspectBase) const;
+
+ GroupInspectorControl computeGroup(CInspectableBase* inspectBase, int theIndex);
+ bool isGroupRebuildRequired(CInspectableBase *inspectable, int theIndex) const;
+
+};
+
+#endif // INSPECTORCONTROLMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp
new file mode 100644
index 00000000..3079c02a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.cpp
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "InspectorControlView.h"
+#include "Literals.h"
+#include "CColor.h"
+#include "UICDMValue.h"
+#include "StudioUtils.h"
+#include "InspectorControlModel.h"
+#include "StudioPreferences.h"
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+#include <QtWidgets/qmenu.h>
+#include "Core.h"
+#include "Doc.h"
+#include "IDocumentEditor.h"
+#include "ImageChooserModel.h"
+#include "ImageChooserView.h"
+#include "MeshChooserView.h"
+#include "TextureChooserView.h"
+#include "InspectableBase.h"
+#include "StudioApp.h"
+#include "ObjectListModel.h"
+#include "ObjectBrowserView.h"
+#include "IDirectoryWatchingSystem.h"
+#include "StandardExtensions.h"
+#include "FileChooserView.h"
+#include "IObjectReferenceHelper.h"
+#include "UICDMStudioSystem.h"
+#include "StudioFullSystem.h"
+
+InspectorControlView::InspectorControlView(QWidget *parent)
+ : QQuickWidget(parent),
+ TabNavigable(),
+ m_inspectorControlModel(new InspectorControlModel(this)),
+ m_instance(0),
+ m_handle(0)
+{
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &InspectorControlView::initialize);
+ auto dispatch = g_StudioApp.GetCore()->GetDispatch();
+ dispatch->AddPresentationChangeListener(this);
+ dispatch->AddDataModelListener(this);
+
+ m_selectionChangedConnection = g_StudioApp.GetCore()->GetDispatch()->ConnectSelectionChange(
+ std::bind(&InspectorControlView::OnSelectionSet, this, std::placeholders::_1));
+}
+
+const wchar_t **AllSupportedExtensionsList()
+{
+ static const wchar_t *extensions[] = {
+ L"png", L"jpg", L"jpeg", L"dds", L"hdr",
+ L"mesh", L"import", L"path",
+ L"material",
+ nullptr
+ };
+ return extensions;
+}
+
+static bool isInList(const wchar_t **list, const Q3DStudio::CString &inStr)
+{
+ for (const wchar_t **item = list; item && *item; ++item) {
+ if (inStr.Compare(*item, Q3DStudio::CString::ENDOFSTRING, false))
+ return true;
+ }
+ return false;
+}
+
+void InspectorControlView::filterMaterials(std::vector<Q3DStudio::CFilePath> &materials)
+{
+ static const wchar_t *extensions[] = {
+ L"material",
+ nullptr
+ };
+ for (size_t i = 0; i < m_fileList.size(); ++i) {
+ if (isInList(extensions, m_fileList[i].GetExtension()))
+ materials.push_back(m_fileList[i]);
+ }
+}
+
+void InspectorControlView::OnNewPresentation()
+{
+ m_DirectoryConnection = g_StudioApp.GetDirectoryWatchingSystem().AddDirectory(
+ g_StudioApp.GetCore()->GetDoc()->GetDocumentDirectory().toQString(),
+ std::bind(&InspectorControlView::onFilesChanged, this, std::placeholders::_1));
+}
+
+void InspectorControlView::OnClosingPresentation()
+{
+ m_fileList.clear();
+}
+
+void InspectorControlView::OnLoadedSubPresentation()
+{
+ m_DirectoryConnection = g_StudioApp.GetDirectoryWatchingSystem().AddDirectory(
+ g_StudioApp.GetCore()->GetDoc()->GetDocumentDirectory().toQString(),
+ std::bind(&InspectorControlView::onFilesChanged, this, std::placeholders::_1));
+}
+
+void InspectorControlView::onFilesChanged(
+ const Q3DStudio::TFileModificationList &inFileModificationList)
+{
+ const wchar_t **extensions = AllSupportedExtensionsList();
+ for (size_t idx = 0, end = inFileModificationList.size(); idx < end; ++idx) {
+ const Q3DStudio::SFileModificationRecord &record(inFileModificationList[idx]);
+ if (record.m_FileInfo.IsFile()
+ && isInList(extensions, record.m_File.GetExtension())) {
+ Q3DStudio::CFilePath relativePath(
+ Q3DStudio::CFilePath::GetRelativePathFromBase(
+ g_StudioApp.GetCore()->GetDoc()->GetDocumentDirectory(),
+ record.m_File));
+
+ if (record.m_ModificationType == Q3DStudio::FileModificationType::Created)
+ UICDM::binary_sort_insert_unique(m_fileList, relativePath);
+ else if (record.m_ModificationType == Q3DStudio::FileModificationType::Destroyed)
+ UICDM::binary_sort_erase(m_fileList, relativePath);
+ }
+ if (record.m_FileInfo.IsFile()
+ && record.m_ModificationType == Q3DStudio::FileModificationType::Modified) {
+ if (record.m_File.toQString() == g_StudioApp.GetCore()->GetDoc()
+ ->GetDocumentUIAFile()) {
+ m_inspectorControlModel->refreshRenderables();
+ }
+ }
+ }
+ std::vector<Q3DStudio::CFilePath> materials;
+ filterMaterials(materials);
+ m_inspectorControlModel->setMaterials(materials);
+}
+
+InspectorControlView::~InspectorControlView()
+{
+ g_StudioApp.GetCore()->GetDispatch()->RemovePresentationChangeListener(this);
+}
+
+QSize InspectorControlView::sizeHint() const
+{
+ return {120, 600};
+}
+
+void InspectorControlView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_inspectorView"_L1, this);
+ rootContext()->setContextProperty("_inspectorModel"_L1, m_inspectorControlModel);
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+ rootContext()->setContextProperty("_tabOrderHandler"_L1, tabOrderHandler());
+ qmlRegisterUncreatableType<UICDM::DataModelDataType>("Qt3DStudio", 1, 0, "DataModelDataType",
+ "DataModelDataType is an enum container");
+ qmlRegisterUncreatableType<UICDM::AdditionalMetaDataType>(
+ "Qt3DStudio", 1, 0, "AdditionalMetaDataType",
+ "AdditionalMetaDataType is an enum container");
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/InspectorControlView.qml"_L1));
+}
+
+QAbstractItemModel *InspectorControlView::inspectorControlModel() const
+{
+ return m_inspectorControlModel;
+}
+
+QString InspectorControlView::titleText() const
+{
+ if (m_inspectableBase) {
+ Q3DStudio::CString theName = m_inspectableBase->GetName();
+ if (theName == L"PathAnchorPoint")
+ return tr("Anchor Point");
+ else
+ return theName.toQString();
+ }
+ return tr("No Object Selected");
+}
+
+QColor InspectorControlView::titleColor(int instance, int handle) const
+{
+ if (instance != 0 && handle != 0) {
+ if (g_StudioApp.GetCore()->GetDoc()->GetDocumentReader().IsPropertyLinked(instance, handle))
+ return CStudioPreferences::masterColor();
+ else
+ return CStudioPreferences::textColor();
+ } else {
+ return CStudioPreferences::textColor();
+ }
+}
+
+QString InspectorControlView::titleIcon() const
+{
+ if (m_inspectableBase)
+ return CStudioObjectTypes::GetNormalIconName(m_inspectableBase->GetObjectType());
+ return {};
+}
+
+void InspectorControlView::OnSelectionSet(Q3DStudio::SSelectedValue inSelectable)
+{
+ updateInspectable(g_StudioApp.GetInspectableFromSelectable(inSelectable));
+}
+
+void InspectorControlView::updateInspectable(CInspectableBase *inInspectable)
+{
+ if (inInspectable != nullptr) {
+ if (inInspectable->IsValid() == false)
+ inInspectable = nullptr;
+ }
+ setInspectable(inInspectable);
+}
+
+void InspectorControlView::setInspectable(CInspectableBase *inInspectable)
+{
+ if (m_inspectableBase != inInspectable) {
+ m_inspectableBase = inInspectable;
+ m_inspectorControlModel->setInspectable(inInspectable);
+ Q_EMIT titleChanged();
+ auto sp = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystem()->GetSignalProvider();
+ m_PropertyChangeConnection = sp->ConnectInstancePropertyValue(
+ std::bind(&InspectorControlView::titleChanged, this));
+ }
+}
+
+void InspectorControlView::showContextMenu(int x, int y, int handle, int instance)
+{
+ m_instance = instance;
+ m_handle = handle;
+
+ QMenu theContextMenu;
+
+ auto doc = g_StudioApp.GetCore()->GetDoc();
+ bool isLinkedFlag = doc->GetDocumentReader().IsPropertyLinked(instance, handle);
+ bool canBeLinkedFlag = doc->GetDocumentReader().CanPropertyBeLinked(instance, handle);
+ if (isLinkedFlag) {
+ auto action = theContextMenu.addAction(QObject::tr("Unlink Property from Master Slide"));
+ action->setEnabled(canBeLinkedFlag);
+ connect(action, &QAction::triggered, this, &InspectorControlView::toggleMasterLink);
+ } else {
+ auto action = theContextMenu.addAction(QObject::tr("Link Property from Master Slide"));
+ action->setEnabled(canBeLinkedFlag);
+ connect(action, &QAction::triggered, this, &InspectorControlView::toggleMasterLink);
+ }
+ theContextMenu.exec(mapToGlobal({x, y}));
+
+ m_instance = 0;
+ m_handle = 0;
+}
+
+void InspectorControlView::toggleMasterLink()
+{
+ Q3DStudio::ScopedDocumentEditor editor(*g_StudioApp.GetCore()->GetDoc(),
+ L"Link Property", __FILE__, __LINE__);
+ bool wasLinked = editor->IsPropertyLinked(m_instance, m_handle);
+
+ if (wasLinked)
+ editor->UnlinkProperty(m_instance, m_handle);
+ else
+ editor->LinkProperty(m_instance, m_handle);
+}
+
+void InspectorControlView::setPropertyValueFromFilename(long instance, int handle,
+ const QString &name)
+{
+ if (m_inspectorControlModel) {
+ QString value;
+ if (name != tr("[None]"))
+ value = name;
+ m_inspectorControlModel->setPropertyValue(instance, handle, value);
+ }
+}
+
+QObject *InspectorControlView::showImageChooser(int handle, int instance, const QPoint &point)
+{
+ if (!m_imageChooserView) {
+ m_imageChooserView = new ImageChooserView(this);
+ connect(m_imageChooserView, &ImageChooserView::imageSelected, this,
+ [this] (int handle, int instance, const QString &imageName){
+ setPropertyValueFromFilename(instance, handle, imageName);
+ m_imageChooserView->hide();
+ });
+ }
+
+ m_imageChooserView->setHandle(handle);
+ m_imageChooserView->setInstance(instance);
+
+ showBrowser(m_imageChooserView, point);
+
+ return m_imageChooserView;
+}
+
+QObject *InspectorControlView::showFilesChooser(int handle, int instance, const QPoint &point)
+{
+ if (!m_fileChooserView) {
+ m_fileChooserView = new FileChooserView(this);
+ connect(m_fileChooserView, &FileChooserView::fileSelected, this,
+ [this] (int handle, int instance, const QString &fileName){
+ setPropertyValueFromFilename(instance, handle, fileName);
+ m_fileChooserView->hide();
+ });
+ }
+
+ m_fileChooserView->setHandle(handle);
+ m_fileChooserView->setInstance(instance);
+
+ showBrowser(m_fileChooserView, point);
+
+ return m_fileChooserView;
+}
+
+QObject *InspectorControlView::showMeshChooser(int handle, int instance, const QPoint &point)
+{
+ if (!m_meshChooserView) {
+ m_meshChooserView = new MeshChooserView(this);
+ connect(m_meshChooserView, &MeshChooserView::meshSelected, this,
+ [this] (int handle, int instance, const QString &name){
+ if (m_inspectorControlModel)
+ m_inspectorControlModel->setPropertyValue(instance, handle, name);
+ });
+ }
+
+ m_meshChooserView->setHandle(handle);
+ m_meshChooserView->setInstance(instance);
+
+ showBrowser(m_meshChooserView, point);
+
+ return m_meshChooserView;
+}
+
+QObject *InspectorControlView::showTextureChooser(int handle, int instance, const QPoint &point)
+{
+ if (!m_textureChooserView) {
+ m_textureChooserView = new TextureChooserView(this);
+ connect(m_textureChooserView, &TextureChooserView::textureSelected, this,
+ [this] (int handle, int instance, const QString &fileName){
+ setPropertyValueFromFilename(instance, handle, fileName);
+ m_textureChooserView->hide();
+ });
+ }
+
+ m_textureChooserView->setHandle(handle);
+ m_textureChooserView->setInstance(instance);
+
+ showBrowser(m_textureChooserView, point);
+
+ return m_textureChooserView;
+}
+
+QObject *InspectorControlView::showObjectReference(int handle, int instance, const QPoint &point)
+{
+ CDoc *doc = g_StudioApp.GetCore()->GetDoc();
+ if (!m_objectReferenceModel) {
+ m_objectReferenceModel
+ = new ObjectListModel(g_StudioApp.GetCore(), doc->GetActiveRootInstance(), this);
+ }
+ if (!m_objectReferenceView)
+ m_objectReferenceView = new ObjectBrowserView(this);
+ m_objectReferenceView->setModel(m_objectReferenceModel);
+
+ disconnect(m_objectReferenceView);
+
+ showBrowser(m_objectReferenceView, point);
+
+ connect(m_objectReferenceView, &ObjectBrowserView::selectionChanged,
+ this, [this, doc, handle, instance] {
+ auto selectedItem = m_objectReferenceView->selectedHandle();
+ UICDM::SObjectRefType objRef = doc->GetDataModelObjectReferenceHelper()->GetAssetRefValue(
+ selectedItem, handle,
+ (CRelativePathTools::EPathType)(m_objectReferenceView->pathType()));
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*doc, QObject::tr("Set Property"))
+ ->SetInstancePropertyValue(instance, handle, objRef);
+ });
+
+ return m_objectReferenceView;
+}
+
+void InspectorControlView::showBrowser(QQuickWidget *browser, const QPoint &point)
+{
+ QSize popupSize = CStudioPreferences::browserPopupSize();
+ browser->resize(popupSize);
+ browser->move(point - QPoint(popupSize.width(), popupSize.height()));
+
+ // Show asynchronously to avoid flashing blank window on first show
+ QTimer::singleShot(0, this, [browser] {
+ browser->show();
+ browser->activateWindow();
+ browser->setFocus();
+ });
+}
+
+void InspectorControlView::OnBeginDataModelNotifications()
+{
+
+}
+
+void InspectorControlView::OnEndDataModelNotifications()
+{
+ m_inspectorControlModel->refresh();
+}
+
+void InspectorControlView::OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance)
+{
+ m_inspectorControlModel->refresh();
+}
+
+void InspectorControlView::OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance, long inInstanceCount)
+{
+ m_inspectorControlModel->refresh();
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h
new file mode 100644
index 00000000..e5815e6c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INSPECTORCONTROLVIEW_H
+#define INSPECTORCONTROLVIEW_H
+
+#include <QtQuickWidgets/qquickwidget.h>
+#include <QtCore/qpointer.h>
+#include "DispatchListeners.h"
+#include "Dispatch.h"
+#include "UICFileTools.h"
+#include "TabOrderHandler.h"
+
+class InspectorControlModel;
+class QAbstractItemModel;
+class CInspectableBase;
+class ImageChooserView;
+class ImageChooserModel;
+class MeshChooserView;
+class ObjectBrowserView;
+class ObjectListModel;
+class FileChooserView;
+class TextureChooserView;
+
+class InspectorControlView : public QQuickWidget,
+ public CPresentationChangeListener,
+ public IDataModelListener,
+ public TabNavigable
+{
+ Q_OBJECT
+ Q_PROPERTY(QString titleText READ titleText NOTIFY titleChanged FINAL)
+ Q_PROPERTY(QString titleIcon READ titleIcon NOTIFY titleChanged FINAL)
+public:
+ explicit InspectorControlView(QWidget *parent = nullptr);
+ ~InspectorControlView();
+
+ void OnSelectionSet(Q3DStudio::SSelectedValue inValue);
+ QAbstractItemModel *inspectorControlModel() const;
+
+ QString titleText() const;
+ Q_INVOKABLE QColor titleColor(int instance = 0, int handle = 0) const;
+ QString titleIcon() const;
+
+ Q_INVOKABLE void showContextMenu(int x, int y, int handle, int instance);
+ Q_INVOKABLE QObject *showImageChooser(int handle, int instance, const QPoint &point);
+ Q_INVOKABLE QObject *showFilesChooser(int handle, int instance, const QPoint &point);
+ Q_INVOKABLE QObject *showMeshChooser(int handle, int instance, const QPoint &point);
+ Q_INVOKABLE QObject *showObjectReference(int handle, int instance, const QPoint &point);
+ Q_INVOKABLE QObject *showTextureChooser(int handle, int instance, const QPoint &point);
+
+ // IDataModelListener
+ void OnBeginDataModelNotifications() override;
+ void OnEndDataModelNotifications() override;
+ void OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance) override;
+ void OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance,
+ long inInstanceCount) override;
+
+
+Q_SIGNALS:
+ void titleChanged();
+ void controlsChanged();
+ void imageSelected(const QString &name);
+
+public Q_SLOTS:
+ void toggleMasterLink();
+
+protected:
+ QSize sizeHint() const override;
+
+private:
+ void setInspectable(CInspectableBase *inInspectable);
+ void updateInspectable(CInspectableBase *inInspectable);
+ void initialize();
+ void onFilesChanged(const Q3DStudio::TFileModificationList &inFileModificationList);
+ void OnNewPresentation() override;
+ void OnClosingPresentation() override;
+ void OnLoadedSubPresentation() override;
+ void filterMaterials(std::vector<Q3DStudio::CFilePath> &materials);
+ void setPropertyValueFromFilename(long instance, int handle, const QString &name);
+ void showBrowser(QQuickWidget *browser, const QPoint &point);
+
+ std::shared_ptr<UICDM::ISignalConnection> m_selectionChangedConnection;
+ std::shared_ptr<UICDM::ISignalConnection> m_DirectoryConnection;
+ std::shared_ptr<UICDM::ISignalConnection> m_PropertyChangeConnection;
+ QColor m_backgroundColor;
+ InspectorControlModel *m_inspectorControlModel = nullptr;
+ CInspectableBase *m_inspectableBase = nullptr;
+ QPointer<ImageChooserView> m_imageChooserView;
+ QPointer<MeshChooserView> m_meshChooserView;
+ QPointer<FileChooserView> m_fileChooserView;
+ QPointer<TextureChooserView> m_textureChooserView;
+ QPointer<ObjectBrowserView> m_objectReferenceView;
+ QPointer<ObjectListModel> m_objectReferenceModel;
+ std::vector<Q3DStudio::CFilePath> m_fileList;
+
+ int m_instance;
+ int m_handle;
+};
+
+#endif // INSPECTORCONTROLVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml
new file mode 100644
index 00000000..9e838d4c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml
@@ -0,0 +1,771 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.8
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.2
+
+import Qt3DStudio 1.0
+import "../controls"
+import "../Action"
+
+Rectangle {
+ id: root
+ color: _backgroundColor
+
+ Connections {
+ target: _inspectorModel
+ onModelAboutToBeReset: {
+ _tabOrderHandler.clear();
+ }
+ }
+
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.topMargin: 4
+ spacing: 8
+
+ RowLayout {
+ height: _controlBaseHeight + anchors.margins * 2
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: 4
+
+ Image {
+ id: headerImage
+ source: _inspectorView.titleIcon !== "" ? _resDir + _inspectorView.titleIcon : ""
+ }
+
+ StyledLabel {
+ text: _inspectorView.titleText
+ color: _inspectorView.titleColor()
+ }
+ }
+
+ ListView {
+ id: groupElements
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ spacing: 4
+
+ clip: true
+
+ ScrollBar.vertical: ScrollBar {
+ visible: size < 1.0
+ }
+
+ model: _inspectorModel
+ delegate: Rectangle {
+ id: delegateItem
+
+ property int indexOfThisDelegate: index
+
+ width: parent.width
+ height: items.height
+ color: "transparent";
+
+ readonly property var values: model.values
+
+ Column {
+ id: items
+
+ x: 10
+ width: parent.width - x
+ spacing: 4
+
+ StyledLabel {
+ text: model.title
+ }
+
+ Column {
+ spacing: 4
+
+ Repeater {
+ model: delegateItem.values
+
+ onItemAdded: {
+ if (index === 0)
+ _tabOrderHandler.clearGroup(indexOfThisDelegate);
+ if (item.loadedItem.tabItem1 !== undefined) {
+ _tabOrderHandler.addItem(indexOfThisDelegate,
+ item.loadedItem.tabItem1)
+ if (item.loadedItem.tabItem2 !== undefined) {
+ _tabOrderHandler.addItem(
+ indexOfThisDelegate,
+ item.loadedItem.tabItem2)
+ if (item.loadedItem.tabItem3 !== undefined) {
+ _tabOrderHandler.addItem(
+ indexOfThisDelegate,
+ item.loadedItem.tabItem3)
+ }
+ }
+ }
+ }
+
+ RowLayout {
+ id: groupDelegateItem
+ spacing: 0
+
+ property alias loadedItem: loader.item
+
+ function showContextMenu(coords) {
+ _inspectorView.showContextMenu(
+ coords.x, coords.y,
+ model.modelData.handle,
+ model.modelData.instance);
+ // Refresh text; title color is wrong after this
+ propertyRow.color = _inspectorView.titleColor(
+ modelData.instance, modelData.handle);
+ }
+
+ Item {
+ Layout.alignment: Qt.AlignTop
+ width: animatedPropertyButton.sourceSize.width
+ height: _controlBaseHeight
+ visible: model.modelData.animatable
+ Image {
+ id: animatedPropertyButton
+
+ property bool animated: model.modelData.animated
+
+ anchors.fill: parent
+ fillMode: Image.Pad
+
+ source: {
+ _resDir + (animated
+ ? "Inspector-AnimateToggle-Active.png"
+ : "Inspector-AnimateToggle-Normal.png")
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton | Qt.LeftButton
+ onClicked: {
+ if (mouse.button === Qt.LeftButton) {
+ _inspectorModel.setPropertyAnimated(
+ model.modelData.instance,
+ model.modelData.handle,
+ !model.modelData.animated)
+ } else {
+ const coords = mapToItem(root, mouse.x, mouse.y);
+ groupDelegateItem.showContextMenu(coords);
+ }
+ }
+ }
+ }
+ }
+
+
+ Item {
+ // Spacer item
+ width: model.modelData.animatable
+ ? 4 : animatedPropertyButton.width + 4
+ height: loadedItem.height + 4 // Add little space between items
+ }
+
+ StyledLabel {
+ id: propertyRow
+
+ readonly property var modelData: model.modelData
+ text: model.modelData.title
+ color: _inspectorView.titleColor(modelData.instance,
+ modelData.handle)
+
+ Layout.alignment: Qt.AlignTop
+
+ MouseArea {
+ id: mouse
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton
+ hoverEnabled: true
+ onClicked: {
+ const coords = mapToItem(root, mouse.x, mouse.y);
+ groupDelegateItem.showContextMenu(coords);
+ }
+ }
+
+ StyledTooltip {
+ text: modelData.toolTip
+ visible: mouse.containsMouse
+ }
+ }
+
+ Loader {
+ id: loader
+ readonly property var modelData: propertyRow.modelData
+ sourceComponent: {
+ const dataType = modelData.dataType;
+ console.warn("KDAB_TODO: DEBUG for type", dataType,
+ "property", modelData.propertyType,
+ "text ", model.modelData.title);
+ switch (dataType) {
+ case DataModelDataType.Long:
+ if (modelData.propertyType ===
+ AdditionalMetaDataType.ShadowMapResolution) {
+ return shadowResolutionComponent;
+ }
+ if (modelData.propertyType === AdditionalMetaDataType.Range) {
+ return intSliderComponent;
+ }
+ console.warn("KDAB_TODO: implement handler for type \"Long\", property:",
+ modelData.propertyType);
+ return null;
+ case DataModelDataType.Long4:
+ if (modelData.propertyType === AdditionalMetaDataType.Image) {
+ return imageChooser;
+ }
+ console.warn("KDAB_TODO: implement handler for type \"long4\" property:",
+ modelData.propertyType);
+ return null;
+ case DataModelDataType.ObjectRef:
+ if (modelData.propertyType === AdditionalMetaDataType.ObjectRef)
+ return objectReference;
+ console.warn("KDAB_TODO: implement handler for type: \"objectref\" property:",
+ modelData.propertyType);
+ return null;
+ case DataModelDataType.StringOrInt:
+ //TODO: Maybe do some further check if the right combo is used
+ if (modelData.propertyType === AdditionalMetaDataType.StringList)
+ return slideSelectionDropDown;
+ console.warn("KDAB_TODO: (String) implement handler for type \"stringOrInt\" property:",
+ modelData.propertyType);
+ return null;
+ case DataModelDataType.String:
+ if (modelData.propertyType === AdditionalMetaDataType.Import)
+ return fileChooser;
+ if (modelData.propertyType === AdditionalMetaDataType.StringList)
+ return comboDropDown;
+ if (modelData.propertyType === AdditionalMetaDataType.Renderable)
+ return renderableDropDown;
+ if (modelData.propertyType === AdditionalMetaDataType.Mesh)
+ return meshChooser;
+ if (modelData.propertyType === AdditionalMetaDataType.MultiLine)
+ return multiLine;
+ if (modelData.propertyType === AdditionalMetaDataType.Font)
+ return comboDropDown;
+ if (modelData.propertyType === AdditionalMetaDataType.Texture)
+ return textureChooser;
+ console.warn("KDAB_TODO: (String) implement handler for type \"string\" property:",
+ modelData.propertyType);
+ return null;
+ case DataModelDataType.Bool:
+ return checkBox;
+ case DataModelDataType.Float:
+ if (modelData.propertyType === AdditionalMetaDataType.None)
+ return valueComponent;
+ if (modelData.propertyType === AdditionalMetaDataType.Range)
+ return sliderComponent;
+ if (modelData.propertyType === AdditionalMetaDataType.FontSize)
+ return fontSizeComponent;
+ console.warn("KDAB_TODO: implement handler for type\"float\" property:",
+ modelData.propertyType);
+ return null;
+ case DataModelDataType.Float3:
+ if (modelData.propertyType === AdditionalMetaDataType.Color)
+ return colorBox;
+ if (modelData.propertyType === AdditionalMetaDataType.Rotation)
+ return xyzPropertyComponent;
+ if (modelData.propertyType === AdditionalMetaDataType.None)
+ return xyzPropertyComponent;
+ console.warn("KDAB_TODO: implement handler for type:\"float3\" property:",
+ modelData.propertyType, "text ",
+ model.modelData.title);
+ return null;
+ case DataModelDataType.StringRef:
+ if (modelData.propertyType === AdditionalMetaDataType.None)
+ return materialDropDown;
+ console.warn("KDAB_TODO: implement handler for type:\"StringRef\" text ",
+ model.modelData.title);
+ return null;
+ default:
+ console.warn("KDAB_TODO: implement handler for type",
+ dataType, "property",
+ modelData.propertyType, "text ",
+ model.modelData.title);
+ }
+ return null;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Component {
+ id: multiLine
+
+ ScrollView {
+ id: scrollView
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant value: parent.modelData.value
+ property Item tabItem1: textArea
+
+ width: _valueWidth
+ height: _controlBaseHeight * 3
+ clip: true
+
+ ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
+ ScrollBar.vertical.policy: ScrollBar.AsNeeded
+
+ TextArea {
+ id: textArea
+
+ text: scrollView.value
+ horizontalAlignment: TextInput.AlignLeft
+ verticalAlignment: TextInput.AlignTop
+ font.pixelSize: _fontSize
+ color: _textColor
+ wrapMode: TextEdit.WordWrap
+ selectionColor: _selectionColor
+ selectedTextColor: _textColor
+
+ topPadding: 6
+ bottomPadding: 6
+ rightPadding: 6
+
+ background: Rectangle {
+ color: textArea.enabled ? _studioColor2 : "transparent"
+ border.width: textArea.activeFocus ? 1 : 0
+ border.color: textArea.activeFocus ? _selectionColor : _disabledColor
+ }
+
+ MouseArea {
+ id: mouseAreaX
+ anchors.fill: parent
+ property int clickedPos
+ preventStealing: true
+
+ onPressed: {
+ textArea.forceActiveFocus()
+ clickedPos = textArea.positionAt(mouse.x, mouse.y)
+ textArea.cursorPosition = clickedPos
+ }
+ onDoubleClicked: textArea.selectAll()
+ onPositionChanged: {
+ textArea.cursorPosition = textArea.positionAt(mouse.x, mouse.y)
+ textArea.select(clickedPos, textArea.cursorPosition)
+ }
+ }
+
+ onTextChanged: {
+ _inspectorModel.setPropertyValue(scrollView.instance, scrollView.handle,
+ text, false)
+ }
+
+ onEditingFinished: {
+ _inspectorModel.setPropertyValue(scrollView.instance, scrollView.handle,
+ text, true)
+ }
+ }
+ }
+ }
+
+ Component {
+ id: meshChooser
+ HandlerFilesChooser {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ value: parent.modelData.value
+ onShowBrowser: {
+ activeBrowser = _inspectorView.showMeshChooser(handle, instance,
+ mapToGlobal(width, 0))
+ }
+ }
+ }
+
+ Component {
+ id: imageChooser
+ HandlerFilesChooser {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ value: parent.modelData.value
+ onShowBrowser: {
+ activeBrowser = _inspectorView.showImageChooser(handle, instance,
+ mapToGlobal(width, 0))
+ }
+ }
+ }
+
+ Component {
+ id: fileChooser
+ HandlerFilesChooser {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ value: parent.modelData.value === "" ? qsTr("[None]") : parent.modelData.value
+ onShowBrowser: {
+ activeBrowser = _inspectorView.showFilesChooser(handle, instance,
+ mapToGlobal(width, 0))
+ }
+ }
+ }
+
+ Component {
+ id: textureChooser
+ HandlerFilesChooser {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ value: parent.modelData.value
+ onShowBrowser: {
+ activeBrowser = _inspectorView.showTextureChooser(handle, instance,
+ mapToGlobal(width, 0))
+ }
+ }
+ }
+
+ Component {
+ id: xyzPropertyComponent
+
+ RowLayout {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ property alias tabItem1: xyzHandler.tabItem1
+ property alias tabItem2: xyzHandler.tabItem2
+ property alias tabItem3: xyzHandler.tabItem3
+ spacing: 0
+ Item {
+ width: _valueWidth - xyzHandler.width
+ }
+ HandlerPropertyBaseXYZ {
+ id: xyzHandler
+ valueX: Number(values[0]).toFixed(3)
+ valueY: Number(values[1]).toFixed(3)
+ valueZ: Number(values[2]).toFixed(3)
+ onEditingFinished: {
+ _inspectorModel.setPropertyValue(parent.instance, parent.handle,
+ Qt.vector3d(valueX, valueY, valueZ))
+ }
+ }
+ }
+ }
+
+ Component {
+ id: valueComponent
+
+ RowLayout {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property real value: Number(parent.modelData.value).toFixed(3)
+ property Item tabItem1: floatField
+ spacing: 0
+ Item {
+ width: _valueWidth - floatField.width
+ }
+ FloatTextField {
+ id: floatField
+ text: parent.value
+ implicitHeight: _controlBaseHeight
+ implicitWidth: _valueWidth / 2
+
+ onWheelEventFinished: {
+ _inspectorModel.setPropertyValue(parent.instance, parent.handle, Number(text));
+ }
+
+ onEditingFinished: {
+ _inspectorModel.setPropertyValue(parent.instance, parent.handle, Number(text));
+ }
+ }
+ }
+ }
+
+ Component {
+ id: sliderComponent
+
+ HandlerPropertyBaseSlider {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ property real oldValue: 0.0
+
+ value: parent.modelData.value
+ sliderMin: values[0]
+ sliderMax: values[1]
+
+ onEditingStarted: {
+ oldValue = value
+ }
+ onEditingFinished: {
+ // make sure the undo step is created, therefore resetting it to the old value
+ var val = value
+ _inspectorModel.setPropertyValue(instance, handle, oldValue, false)
+ _inspectorModel.setPropertyValue(instance, handle, val, true)
+ }
+ onSliderMoved: {
+ _inspectorModel.setPropertyValue(instance, handle, value, false)
+ }
+ }
+ }
+
+ Component {
+ id: comboDropDown
+
+ StyledComboBox {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property var values: parent.modelData.values
+ property var value: parent.modelData.value
+
+ model: values
+
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+
+ Component.onCompleted: {
+ currentIndex = find(value)
+ }
+ onCurrentIndexChanged: {
+ var newValue = textAt(currentIndex)
+ if (value !== newValue && currentIndex !== -1)
+ _inspectorModel.setPropertyValue(instance, handle, newValue)
+ }
+ onValueChanged: {
+ currentIndex = find(value)
+ }
+ }
+ }
+
+ Component {
+ id: slideSelectionDropDown
+
+ StyledComboBox {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property var values: parent.modelData.values
+ property var value: parent.modelData.value
+
+ model: values
+
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+
+ Component.onCompleted: {
+ var newIndex = find(value)
+ if (newIndex === -1)
+ newIndex = find(value + "|separator")
+ currentIndex = newIndex
+ }
+ onCurrentIndexChanged: {
+ var newValue = textAt(currentIndex).replace("|separator", "")
+ if (value !== newValue && currentIndex !== -1) {
+ _inspectorModel.setSlideSelection(instance, handle,
+ currentIndex, values)
+ }
+ }
+ onValueChanged: {
+ var newIndex = find(value)
+ if (newIndex === -1)
+ newIndex = find(value + "|separator")
+ currentIndex = newIndex
+ }
+ }
+ }
+
+ Component {
+ id: materialDropDown
+
+ StyledComboBox {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property var values: parent.modelData.values
+ property var value: parent.modelData.value
+
+ model: values
+
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+
+ Component.onCompleted: {
+ currentIndex = find(value)
+ }
+ onCurrentIndexChanged: {
+ var newValue = textAt(currentIndex)
+ if (value !== newValue && currentIndex !== -1)
+ _inspectorModel.setMaterialTypeValue(instance, handle, newValue)
+ }
+ onValueChanged: {
+ currentIndex = find(value)
+ }
+ }
+ }
+
+ Component {
+ id: renderableDropDown
+
+ StyledComboBox {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property var values: parent.modelData.values
+ property var value: parent.modelData.value
+ model: values
+
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+
+ Component.onCompleted: {
+ currentIndex = find(value)
+ }
+
+ onCurrentIndexChanged: {
+ var newValue = textAt(currentIndex)
+ if (value !== newValue && currentIndex !== -1)
+ _inspectorModel.setRenderableValue(instance, handle, newValue)
+ }
+ onValueChanged: {
+ currentIndex = find(value)
+ }
+ }
+ }
+
+ Component {
+ id: checkBox
+
+ Image {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property bool checked: parent.modelData.value
+
+ source: (_resDir + (checked ? "checkbox-checked.png" : "checkbox-unchecked.png"))
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: _inspectorModel.setPropertyValue(instance, handle, !checked)
+ }
+ }
+ }
+
+ Component {
+ id: colorBox
+
+ HandlerGenericBaseColor {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+
+ color: parent.modelData.value
+ onColorSelected: _inspectorModel.setPropertyValue(instance, handle, selectedColor)
+ }
+ }
+
+ Component {
+ id: objectReference
+
+ HandlerGenericChooser {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ value: parent.modelData.value
+ onShowBrowser: {
+ activeBrowser = _inspectorView.showObjectReference(handle, instance,
+ mapToGlobal(width, 0))
+ }
+ }
+ }
+
+ Component {
+ id: intSliderComponent
+
+ HandlerPropertyBaseSlider {
+ intSlider: true;
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property variant values: parent.modelData.values
+ intValue: parent.modelData.value
+ sliderMin: values[0]
+ sliderMax: values[1]
+
+ onEditingFinished: {
+ _inspectorModel.setPropertyValue(instance, handle, intValue)
+ }
+ }
+ }
+
+ Component {
+ id: fontSizeComponent
+
+ StyledComboBox {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property real value: parent.modelData.value
+
+ model: ["8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "72", "96", "120"]
+
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+
+ Component.onCompleted: {
+ currentIndex = find(value)
+ }
+
+ onCurrentIndexChanged: {
+ var newvalue = parseInt(textAt(currentIndex))
+ _inspectorModel.setPropertyValue(instance, handle, newvalue)
+ }
+
+ onValueChanged: {
+ currentIndex = find(value)
+ }
+ }
+ }
+
+ Component {
+ id: shadowResolutionComponent
+
+ StyledComboBox {
+ property int instance: parent.modelData.instance
+ property int handle: parent.modelData.handle
+ property var value: parent.modelData.value
+ property int newValue
+
+ model: ["8", "9", "10", "11"]
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+
+ Component.onCompleted: {
+ currentIndex = find(value)
+ }
+
+ onCurrentIndexChanged: {
+ newValue = parseInt(textAt(currentIndex))
+ if (value !== newValue && currentIndex !== -1)
+ _inspectorModel.setPropertyValue(instance, handle, newValue)
+ }
+
+ onValueChanged: {
+ currentIndex = find(value)
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorGroup.cpp b/src/Authoring/Studio/Palettes/Inspector/InspectorGroup.cpp
new file mode 100644
index 00000000..c3ea86cb
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorGroup.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "InspectorGroup.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CInspectorGroup::CInspectorGroup()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CInspectorGroup::~CInspectorGroup()
+{
+}
+
+//==============================================================================
+/**
+ * Set the name to show up in the title bar
+ */
+void CInspectorGroup::SetName(const QString &inName)
+{
+ m_name = inName;
+}
+
+QString CInspectorGroup::GetName() const
+{
+ return m_name;
+}
+
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorGroup.h b/src/Authoring/Studio/Palettes/Inspector/InspectorGroup.h
new file mode 100644
index 00000000..98ac824d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorGroup.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_INSPECTOR_GROUP_H
+#define INCLUDED_INSPECTOR_GROUP_H 1
+
+#pragma once
+
+#include <QString>
+
+//==============================================================================
+/**
+ * @class CInspectorGroup
+ * @brief This is the base class for inspector groups.
+ *
+ * Derive from this class in order to create a new group for the inspector
+ * palette.
+ */
+class CInspectorGroup
+{
+public:
+ enum EGroupCommand {
+ EGroupCommandNone = 0,
+ EGroupCommandToggle,
+ };
+
+public:
+ CInspectorGroup();
+ virtual ~CInspectorGroup();
+
+ void SetName(const QString &inName);
+ QString GetName() const;
+
+protected:
+ QString m_name;
+};
+
+#endif // INCLUDED_INSPECTOR_GROUP_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/MeshChooser.qml b/src/Authoring/Studio/Palettes/Inspector/MeshChooser.qml
new file mode 100644
index 00000000..229c4c8c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/MeshChooser.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+ border.color: _studioColor3
+
+ ColumnLayout {
+ anchors.fill: parent
+ ListView {
+ id: listView
+
+ anchors {
+ fill: parent
+ leftMargin: 8
+ }
+
+ boundsBehavior: Flickable.StopAtBounds
+ spacing: 4
+ clip: true
+
+ ScrollBar.vertical: ScrollBar {}
+
+ model: _meshChooserModel
+
+ delegate: ChooserDelegate {
+ onClicked: _meshChooserView.setSelectedMeshName(filePath)
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.cpp b/src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.cpp
new file mode 100644
index 00000000..e1b61bbf
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "MeshChooserModel.h"
+#include "Core.h"
+#include "Doc.h"
+#include "IDocumentBufferCache.h"
+#include "StudioApp.h"
+
+MeshChooserModel::MeshChooserModel(QObject *parent)
+ : ChooserModelBase(parent)
+{
+}
+
+MeshChooserModel::~MeshChooserModel()
+{
+
+}
+
+bool MeshChooserModel::isVisible(const QString &path) const
+{
+ return getIconType(path) == OBJTYPE_MODEL;
+}
+
+const QVector<ChooserModelBase::FixedItem> MeshChooserModel::getFixedItems() const
+{
+ static QVector<FixedItem> items;
+
+ if (items.isEmpty()) {
+ auto primitiveNames = g_StudioApp.GetCore()->GetDoc()->GetBufferCache().GetPrimitiveNames();
+ for (auto item = primitiveNames; *item; ++item) {
+ auto itemName = *item;
+ if (itemName[0] == L'#')
+ items.append({ OBJTYPE_MODEL, QString::fromWCharArray(itemName + 1) });
+ }
+ }
+
+ return items;
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.h b/src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.h
new file mode 100644
index 00000000..5aea88a8
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/MeshChooserModel.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESHCHOOSERMODEL_H
+#define MESHCHOOSERMODEL_H
+
+#include "ChooserModelBase.h"
+
+class MeshChooserModel : public ChooserModelBase
+{
+ Q_OBJECT
+
+public:
+ explicit MeshChooserModel(QObject *parent = nullptr);
+ virtual ~MeshChooserModel();
+
+private:
+ bool isVisible(const QString &path) const override;
+ const QVector<FixedItem> getFixedItems() const override;
+};
+
+#endif // MESHCHOOSERMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/MeshChooserView.cpp b/src/Authoring/Studio/Palettes/Inspector/MeshChooserView.cpp
new file mode 100644
index 00000000..86f7c75b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/MeshChooserView.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "MeshChooserView.h"
+#include "MeshChooserModel.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "StudioPreferences.h"
+#include "IDocumentEditor.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMValue.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "IDocumentBufferCache.h"
+
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+MeshChooserView::MeshChooserView(QWidget *parent)
+ : QQuickWidget(parent)
+ , m_model(new MeshChooserModel(this))
+{
+ setWindowTitle(tr("Meshes"));
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &MeshChooserView::initialize);
+}
+
+void MeshChooserView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_resDir"_L1,
+ resourceImageUrl());
+ rootContext()->setContextProperty("_meshChooserView"_L1, this);
+ rootContext()->setContextProperty("_meshChooserModel"_L1, m_model);
+
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/MeshChooser.qml"_L1));
+}
+
+QSize MeshChooserView::sizeHint() const
+{
+ return {500, 500};
+}
+
+void MeshChooserView::setSelectedMeshName(const QString &name)
+{
+ hide();
+ bool resourceName = false;
+ QString meshName = QLatin1Char('#') + name;
+ const wchar_t **files = g_StudioApp.GetCore()->GetDoc()->GetBufferCache().GetPrimitiveNames();
+ for (const wchar_t **item = files; item && *item; ++item) {
+ QString primitive = QString::fromWCharArray(*item);
+ if (primitive == meshName) {
+ resourceName = true;
+ break;
+ }
+ }
+ if (!resourceName)
+ meshName = name;
+
+ Q_EMIT meshSelected(m_handle, m_instance, meshName);
+}
+
+void MeshChooserView::setHandle(int handle)
+{
+ m_handle = handle;
+}
+
+void MeshChooserView::setInstance(int instance)
+{
+ m_instance = instance;
+}
+
+void MeshChooserView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ QTimer::singleShot(0, this, &MeshChooserView::close);
+}
+
+void MeshChooserView::showEvent(QShowEvent *event)
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+
+ UICDM::SValue value;
+ propertySystem->GetInstancePropertyValue(m_instance, m_handle, value);
+
+ const QString meshValue = UICDM::get<QString>(value);
+ const Q3DStudio::CFilePath selectionItem = Q3DStudio::CFilePath::fromQString(meshValue);
+ const Q3DStudio::CFilePath selectionWithoutId = selectionItem.GetPathWithoutIdentifier();
+
+ QString currentFile;
+
+ if (selectionWithoutId.size()) {
+ currentFile = selectionWithoutId.toQString();
+ } else {
+ currentFile = selectionItem.GetIdentifier().toQString();
+ }
+
+ m_model->setCurrentFile(currentFile);
+
+ QQuickWidget::showEvent(event);
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/MeshChooserView.h b/src/Authoring/Studio/Palettes/Inspector/MeshChooserView.h
new file mode 100644
index 00000000..b47770d9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/MeshChooserView.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESHCHOOSERVIEW_H
+#define MESHCHOOSERVIEW_H
+
+#include <QQuickWidget>
+
+namespace Q3DStudio {
+class CFilePath;
+class CString;
+}
+
+class QAbstractItemModel;
+class MeshChooserModel;
+class MeshChooserView : public QQuickWidget
+{
+ Q_OBJECT
+public:
+ explicit MeshChooserView(QWidget *parent = nullptr);
+
+ QSize sizeHint() const override;
+
+ Q_INVOKABLE void setSelectedMeshName(const QString &name);
+
+ void setHandle(int handle);
+ void setInstance(int instance);
+
+Q_SIGNALS:
+ void meshSelected(int handle, int instance, const QString &name);
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+private:
+ void showEvent(QShowEvent *event) override;
+ void initialize();
+ int m_handle = -1;
+ int m_instance = -1;
+ MeshChooserModel *m_model = nullptr;
+};
+
+#endif // MESHCHOOSERVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectBrowser.qml b/src/Authoring/Studio/Palettes/Inspector/ObjectBrowser.qml
new file mode 100644
index 00000000..d0ece17a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectBrowser.qml
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import Qt3DStudio 1.0
+import "../controls"
+
+Rectangle {
+ id: root
+
+ property alias selectedText: selectionText.text
+
+ color: _backgroundColor
+ border.color: _studioColor3
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ spacing: 10
+
+ ListView {
+ id: browserList
+
+ Layout.margins: 10
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.minimumHeight: 80
+ Layout.preferredHeight: count * 20
+ Layout.preferredWidth: root.width
+
+ ScrollBar.vertical: ScrollBar {}
+
+ model: _objectBrowserView.model
+ boundsBehavior: Flickable.StopAtBounds
+ clip: true
+
+ delegate: Item {
+ id: delegateItem
+
+ x: model.depth * 20
+ width: parent.width
+ height: model.parentExpanded ? typeIcon.height + 10 : 0
+
+ visible: height > 0
+
+ Behavior on height {
+ NumberAnimation {
+ duration: 100
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ Row {
+ id: row
+
+ height: typeIcon.height
+ spacing: 5
+
+ Image {
+ source: {
+ if (!model.hasChildren)
+ return "";
+ model.expanded ? _resDir + "arrow_down.png"
+ : _resDir + "arrow.png";
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: model.expanded = !model.expanded
+ }
+ }
+
+ Rectangle {
+ height: typeIcon.height
+ width: typeIcon.width + name.width + 10
+
+ color: model.index === browserList.currentIndex ? _selectionColor
+ : "transparent"
+
+ Row {
+ spacing: 10
+ Image {
+ id: typeIcon
+
+ source: model.icon
+ }
+
+ StyledLabel {
+ id: name
+ anchors.verticalCenter: typeIcon.verticalCenter
+ color: model.textColor
+ text: model.name
+ }
+ }
+
+ MouseArea {
+ id: delegateArea
+
+ anchors.fill: parent
+ onClicked: browserList.currentIndex = model.index
+ onDoubleClicked: {
+ browserList.currentIndex = model.index;
+ _objectBrowserView.close();
+ }
+ }
+ }
+ }
+ }
+
+ onCurrentIndexChanged: _objectBrowserView.selection = currentIndex
+ }
+
+ StyledMenuSeparator {}
+
+ GridLayout {
+ columns: 2
+ Layout.margins: 10
+
+ StyledLabel {
+ text: qsTr("Type")
+ }
+
+ StyledComboBox {
+ id: pathCombo
+ model: [qsTr("Absolute Reference"), qsTr("Path Reference")]
+
+ onActivated: {
+ if (index === 0)
+ _objectBrowserView.pathType = ObjectBrowserView.Name;
+ else if (index === 1)
+ _objectBrowserView.pathType = ObjectBrowserView.Relative;
+ }
+ }
+
+ StyledLabel {
+ text: qsTr("Path")
+ }
+
+ StyledLabel {
+ id: selectionText
+ Layout.preferredWidth: _valueWidth
+ text: pathCombo.currentIndex === 0 ? _objectBrowserView.name(browserList.currentIndex)
+ : _objectBrowserView.path(browserList.currentIndex)
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.cpp b/src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.cpp
new file mode 100644
index 00000000..86067722
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "ObjectBrowserView.h"
+
+#include "CColor.h"
+#include "Literals.h"
+#include "ObjectListModel.h"
+#include "StudioPreferences.h"
+#include "StudioUtils.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+ObjectBrowserView::ObjectBrowserView(QWidget *parent)
+ : QQuickWidget(parent)
+{
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ObjectBrowserView::initialize);
+}
+
+QAbstractItemModel *ObjectBrowserView::model() const
+{
+ return m_model;
+}
+
+void ObjectBrowserView::setModel(ObjectListModel *model)
+{
+ if (!m_model) {
+ m_model = new FlatObjectListModel(model, this);
+ }
+ m_model->setSourceModel(model);
+
+ Q_EMIT modelChanged();
+}
+
+
+QSize ObjectBrowserView::sizeHint() const
+{
+ return {500, 500};
+}
+
+QString ObjectBrowserView::name(int index) const
+{
+ return m_model->index(index, 0).data(ObjectListModel::NameRole).toString();
+}
+
+QString ObjectBrowserView::path(int index) const
+{
+ return m_model->index(index, 0).data(ObjectListModel::PathReferenceRole).toString();
+}
+
+void ObjectBrowserView::setSelection(int index)
+{
+ if (m_selection != index) {
+ m_selection = index;
+ Q_EMIT selectionChanged();
+ }
+}
+
+void ObjectBrowserView::setPathType(ObjectBrowserView::PathType type)
+{
+ if (type != m_pathType) {
+ m_pathType = type;
+ Q_EMIT pathTypeChanged();
+ }
+}
+
+UICDM::CUICDMInstanceHandle ObjectBrowserView::selectedHandle() const
+{
+ auto handleId = m_model->index(m_selection, 0).data(ObjectListModel::HandleRole).toInt();
+ return UICDM::CUICDMInstanceHandle(handleId);
+}
+
+void ObjectBrowserView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ QTimer::singleShot(0, this, &ObjectBrowserView::close);
+}
+
+void ObjectBrowserView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_objectBrowserView"_L1, this);
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+ qmlRegisterUncreatableType<ObjectBrowserView>("Qt3DStudio", 1, 0, "ObjectBrowserView"
+ , tr("Creation of ObjectBrowserView not allowed from QML"));
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/ObjectBrowser.qml"_L1));
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.h b/src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.h
new file mode 100644
index 00000000..8a4ed1eb
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectBrowserView.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef OBJECTBROWSERVIEW_H
+#define OBJECTBROWSERVIEW_H
+
+#include <QQuickWidget>
+
+#include "RelativePathTools.h"
+#include "UICDMHandles.h"
+
+#include <QColor>
+
+class ObjectListModel;
+class FlatObjectListModel;
+
+class QAbstractItemModel;
+
+class ObjectBrowserView : public QQuickWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractItemModel *model READ model NOTIFY modelChanged FINAL)
+ Q_PROPERTY(int selection READ selection WRITE setSelection NOTIFY selectionChanged FINAL)
+ Q_PROPERTY(PathType pathType READ pathType WRITE setPathType NOTIFY pathTypeChanged FINAL)
+
+public:
+ ObjectBrowserView(QWidget *parent = nullptr);
+
+
+ enum PathType {
+ Name = CRelativePathTools::EPATHTYPE_GUID,
+ Relative = CRelativePathTools::EPATHTYPE_RELATIVE,
+ };
+ Q_ENUM(PathType)
+
+ QAbstractItemModel *model() const;
+ void setModel(ObjectListModel *model);
+ QSize sizeHint() const override;
+
+ Q_INVOKABLE QString name(int index) const;
+ Q_INVOKABLE QString path(int index) const;
+
+ int selection() const { return m_selection; }
+ void setSelection(int index);
+
+ PathType pathType() const {return m_pathType;}
+ void setPathType(PathType type);
+
+ UICDM::CUICDMInstanceHandle selectedHandle() const;
+
+Q_SIGNALS:
+ void modelChanged();
+ void pathTypeChanged();
+ void selectionChanged();
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+private:
+ void initialize();
+
+ FlatObjectListModel *m_model = nullptr;
+ QHash<int, ObjectListModel *> m_subModels;
+ QColor m_baseColor = QColor::fromRgb(75, 75, 75);
+ QColor m_selectColor;
+ int m_selection = -1;
+ PathType m_pathType = Name;
+};
+
+#endif // OBJECTBROWSERVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectListModel.cpp b/src/Authoring/Studio/Palettes/Inspector/ObjectListModel.cpp
new file mode 100644
index 00000000..ad1d752f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectListModel.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ObjectListModel.h"
+
+#include "Core.h"
+#include "Doc.h"
+#include "GraphUtils.h"
+#include "IObjectReferenceHelper.h"
+#include "StudioUtils.h"
+#include "SlideSystem.h"
+#include "StudioObjectTypes.h"
+#include "StudioPreferences.h"
+#include "UICDMStudioSystem.h"
+
+#include <QCoreApplication>
+#include <QColor>
+
+ObjectListModel::ObjectListModel(CCore *core,
+ const UICDM::CUICDMInstanceHandle &baseHandle, QObject *parent)
+ : QAbstractItemModel(parent)
+ , m_core(core)
+ , m_baseHandle(baseHandle)
+{
+ auto doc = m_core->GetDoc();
+ m_objRefHelper = doc->GetDataModelObjectReferenceHelper();
+ m_slideHandle = m_objRefHelper->GetSlideList(m_baseHandle)[0];
+}
+
+QHash<int, QByteArray> ObjectListModel::roleNames() const
+{
+ auto names = QAbstractItemModel::roleNames();
+ names.insert(NameRole, "name");
+ names.insert(HandleRole, "handle");
+ names.insert(IconRole, "icon");
+ names.insert(TextColorRole, "textColor");
+ names.insert(AbsolutePathRole, "absolutePath");
+ names.insert(PathReferenceRole, "referencePath");
+
+ return names;
+}
+
+int ObjectListModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return 1;
+
+ const auto handle = handleForIndex(parent);
+ const auto children = childrenList(m_slideHandle, handle);
+ return children.size();
+}
+
+int ObjectListModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return 1;
+}
+
+QVariant ObjectListModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(), index.parent()))
+ return {};
+
+ switch (role) {
+ case NameRole: {
+ return nameForHandle(handleForIndex(index));
+ }
+ case PathReferenceRole: {
+ Q3DStudio::CString data(m_objRefHelper->GetObjectReferenceString(
+ m_baseHandle, CRelativePathTools::EPATHTYPE_RELATIVE, handleForIndex(index)));
+ return data.toQString();
+ }
+ case AbsolutePathRole: {
+ Q3DStudio::CString data(m_objRefHelper->GetObjectReferenceString(
+ m_baseHandle, CRelativePathTools::EPATHTYPE_GUID, handleForIndex(index)));
+ return data.toQString();
+ }
+ case HandleRole: {
+ return (int)handleForIndex(index);
+ }
+ case IconRole: {
+ auto info = m_objRefHelper->GetInfo(handleForIndex(index));
+ return resourceImageUrl() + CStudioObjectTypes::GetNormalIconName(info.m_Type);
+ }
+ case TextColorRole: {
+ auto info = m_objRefHelper->GetInfo(handleForIndex(index));
+ if (info.m_Master)
+ return QVariant::fromValue(CStudioPreferences::masterColor());
+ else
+ return QVariant::fromValue(CStudioPreferences::textColor());
+ }
+ default:
+ return {};
+ }
+
+ return {};
+}
+
+QModelIndex ObjectListModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return createIndex(row, column, (quintptr)(m_baseHandle));
+
+ const auto handle = handleForIndex(parent);
+ const auto children = childrenList(m_slideHandle, handle);
+ if (row >= children.size())
+ return {};
+
+ auto childHandle = children[row];
+ return createIndex(row, column, (quintptr)(childHandle));
+}
+
+QModelIndex ObjectListModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return {};
+
+ const auto handle = handleForIndex(index);
+ UICDM::CUICDMInstanceHandle parentHandle = m_core->GetDoc()->GetAssetGraph()->GetParent(handle);
+ if (!parentHandle.Valid())
+ return {};
+
+ int row = 0;
+ UICDM::CUICDMInstanceHandle grandParentHandle = m_core->GetDoc()->GetAssetGraph()
+ ->GetParent(handle);
+ const auto children = childrenList(m_slideHandle, grandParentHandle);
+ const auto it = std::find(children.begin(), children.end(), parentHandle);
+ if (it != children.end())
+ row = it - children.begin();
+
+ return createIndex(row, 0, (quintptr)(parentHandle));
+}
+
+UICDM::CUICDMInstanceHandle ObjectListModel::handleForIndex(const QModelIndex &index) const
+{
+ return static_cast<UICDM::CUICDMInstanceHandle>(index.internalId());
+}
+
+UICDM::TInstanceHandleList ObjectListModel::childrenList(const UICDM::CUICDMSlideHandle &slideHandle, const UICDM::CUICDMInstanceHandle &handle) const
+{
+ auto slideSystem = m_core->GetDoc()->GetStudioSystem()->GetSlideSystem();
+ auto currentMaster = slideSystem->GetMasterSlide(slideHandle);
+
+ UICDM::TInstanceHandleList children;
+ m_objRefHelper->GetChildInstanceList(handle, children, slideHandle, m_baseHandle);
+ children.erase(
+ std::remove_if(children.begin(), children.end(),
+ [&slideHandle, slideSystem, &currentMaster](const UICDM::CUICDMInstanceHandle &h) {
+ const auto childSlide = slideSystem->GetAssociatedSlide(h);
+ if (!childSlide.Valid())
+ return true;
+ const auto childMaster = slideSystem->GetMasterSlide(childSlide);
+ if (childMaster == currentMaster) {
+ return childSlide != childMaster && childSlide != slideHandle;
+ } else {
+ return childSlide != childMaster;
+ }
+ }), children.end());
+ return children;
+}
+
+QString ObjectListModel::nameForHandle(const UICDM::CUICDMInstanceHandle &handle) const
+{
+ const auto data = m_objRefHelper->GetInfo(handle);
+ return data.m_Name.toQString();
+}
+
+QModelIndex ObjectListModel::indexForHandle(const UICDM::CUICDMInstanceHandle &handle,
+ const QModelIndex &startIndex) const
+{
+ if (handle == m_baseHandle)
+ return index(0, 0, {});
+
+ for (int i = 0; i < rowCount(startIndex); i++) {
+ auto idx = index(i, 0, startIndex);
+ if (static_cast<UICDM::CUICDMInstanceHandle>(idx.internalId()) == handle)
+ return idx;
+ if (rowCount(idx) > 0)
+ return indexForHandle(handle, idx);
+ }
+ return {};
+}
+
+
+FlatObjectListModel::FlatObjectListModel(ObjectListModel *sourceModel, QObject *parent)
+ : QAbstractListModel(parent)
+ , m_sourceModel(sourceModel)
+
+{
+ Q_ASSERT(sourceModel);
+ m_sourceInfo = collectSourceIndexes({}, 0);
+}
+
+QVector<FlatObjectListModel::SourceInfo> FlatObjectListModel::collectSourceIndexes(
+ const QModelIndex &sourceIndex, int depth) const
+{
+ QVector<SourceInfo> sourceInfo;
+
+ for (int i = 0; i < m_sourceModel->rowCount(sourceIndex); i++) {
+ auto idx = m_sourceModel->index(i, 0, sourceIndex);
+ SourceInfo info;
+ info.depth = depth;
+ info.index = idx;
+ sourceInfo.append(info);
+ if (m_sourceModel->rowCount(idx) > 0) {
+ sourceInfo += collectSourceIndexes(idx, depth + 1);
+ }
+ }
+
+ return sourceInfo;
+}
+
+QHash<int, QByteArray> FlatObjectListModel::roleNames() const
+{
+ auto roles = m_sourceModel->roleNames();
+ roles.insert(DepthRole, "depth");
+ roles.insert(ExpandedRole, "expanded");
+ roles.insert(ParentExpandedRole, "parentExpanded");
+ roles.insert(HasChildrenRole, "hasChildren");
+ return roles;
+}
+
+QModelIndex FlatObjectListModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ int row = proxyIndex.row();
+ if (row < 0 || row >= m_sourceInfo.count())
+ return {};
+ return m_sourceInfo[row].index;
+}
+
+QVariant FlatObjectListModel::data(const QModelIndex &index, int role) const
+{
+ const auto row = index.row();
+ if (row < 0 || row >= m_sourceInfo.count())
+ return {};
+
+ switch (role) {
+ case DepthRole: {
+ auto info = m_sourceInfo[row];
+ return info.depth;
+ }
+ case ExpandedRole: {
+ auto info = m_sourceInfo[row];
+ return info.expanded;
+ }
+ case ParentExpandedRole: {
+ auto info = m_sourceInfo[row];
+ if (info.depth == 0)
+ return true;
+
+ int depth = info.depth;
+ for (int i = row - 1; i >= 0; i--) {
+ const auto prevInfo = m_sourceInfo[i];
+ if (prevInfo.depth < depth) {
+ if (!prevInfo.expanded) {
+ return false;
+ } else {
+ depth = prevInfo.depth;
+ }
+ }
+ }
+ return true;
+ }
+ case HasChildrenRole: {
+ if (row == m_sourceInfo.count() - 1)
+ return false;
+ auto info = m_sourceInfo[row];
+ auto nextInfo = m_sourceInfo[row + 1];
+ return (nextInfo.depth > info.depth);
+ }
+ }
+
+ QModelIndex sourceIndex = mapToSource(index);
+ return m_sourceModel->data(sourceIndex, role);
+}
+
+bool FlatObjectListModel::setData(const QModelIndex &index, const QVariant &data, int role)
+{
+ const auto row = index.row();
+ if (row < 0 || row >= m_sourceInfo.count())
+ return {};
+
+ switch (role) {
+ case ExpandedRole: {
+ auto info = &m_sourceInfo[index.row()];
+ info->expanded = data.toBool();
+ Q_EMIT dataChanged(this->index(0, 0), this->index(rowCount() - 1, 0), {});
+ return true;
+ }
+ }
+
+ QModelIndex sourceIndex = mapToSource(index);
+ return m_sourceModel->setData(sourceIndex, data, role);
+}
+
+int FlatObjectListModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_sourceInfo.count();
+}
+
+void FlatObjectListModel::setSourceModel(ObjectListModel *sourceModel)
+{
+ beginResetModel();
+ m_sourceModel = sourceModel;
+ m_sourceInfo = collectSourceIndexes({}, 0);
+ endResetModel();
+}
+
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectListModel.h b/src/Authoring/Studio/Palettes/Inspector/ObjectListModel.h
new file mode 100644
index 00000000..fbff3537
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectListModel.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJECTLISTMODEL_H
+#define OBJECTLISTMODEL_H
+
+#include <QAbstractItemModel>
+#include <QAbstractListModel>
+
+#include "UICDMHandles.h"
+
+class IObjectReferenceHelper;
+class CCore;
+
+class ObjectListModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ ObjectListModel(CCore *core, const UICDM::CUICDMInstanceHandle &baseHandle, QObject *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex &index) const override;
+
+ enum Roles {
+ NameRole = Qt::DisplayRole,
+ AbsolutePathRole = Qt::UserRole + 1,
+ PathReferenceRole,
+ IconRole,
+ TextColorRole,
+ HandleRole,
+ LastRole = HandleRole
+ };
+
+ QHash<int, QByteArray> roleNames() const override;
+
+ UICDM::CUICDMInstanceHandle baseHandle() const {return m_baseHandle;}
+
+private:
+ UICDM::CUICDMInstanceHandle handleForIndex(const QModelIndex &index) const;
+
+ UICDM::TInstanceHandleList childrenList(const UICDM::CUICDMSlideHandle &slideHandle,
+ const UICDM::CUICDMInstanceHandle &handle) const;
+
+ QString nameForHandle(const UICDM::CUICDMInstanceHandle &handle) const;
+
+ QModelIndex indexForHandle(const UICDM::CUICDMInstanceHandle &handle, const QModelIndex &startIndex = {}) const;
+
+ CCore *m_core;
+ UICDM::CUICDMSlideHandle m_slideHandle;
+ UICDM::CUICDMInstanceHandle m_baseHandle;
+ IObjectReferenceHelper *m_objRefHelper;
+};
+
+class FlatObjectListModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ FlatObjectListModel(ObjectListModel *sourceModel, QObject *parent = nullptr);
+
+ enum Roles {
+ DepthRole = ObjectListModel::LastRole + 1,
+ ExpandedRole,
+ ParentExpandedRole,
+ HasChildrenRole
+ };
+
+ QHash<int, QByteArray> roleNames() const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &data, int role = Qt::EditRole) override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ void setSourceModel(ObjectListModel *sourceModel);
+ ObjectListModel *sourceModel() const {return m_sourceModel;}
+
+private:
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+
+ struct SourceInfo {
+ bool expanded = false;
+ int depth = 0;
+ QPersistentModelIndex index;
+ };
+
+ QVector<SourceInfo> collectSourceIndexes(const QModelIndex &sourceIndex, int depth) const;
+
+ QVector<SourceInfo> m_sourceInfo;
+ ObjectListModel *m_sourceModel;
+};
+
+
+#endif // OBJECTLISTMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectReference.qml b/src/Authoring/Studio/Palettes/Inspector/ObjectReference.qml
new file mode 100644
index 00000000..3e456067
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectReference.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+ ColumnLayout {
+ anchors.fill: parent
+ //KDAB_FIXME implement object chooser
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.cpp b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.cpp
new file mode 100644
index 00000000..40dc91e1
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ObjectReferenceModel.h"
+
+ObjectReferenceModel::ObjectReferenceModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ //KDAB_FIXME: Understand how it must be filled
+}
+
+ObjectReferenceModel::~ObjectReferenceModel()
+{
+
+}
+
+
+int ObjectReferenceModel::rowCount(const QModelIndex &parent) const
+{
+ //KDAB_FIXME
+ return 0;
+}
+
+QVariant ObjectReferenceModel::data(const QModelIndex &index, int role) const
+{
+ //KDAB_FIXME
+ return {};
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.h b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.h
new file mode 100644
index 00000000..29932442
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceModel.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJECTREFERENCEMODEL_H
+#define OBJECTREFERENCEMODEL_H
+
+#include <QAbstractListModel>
+
+class ObjectReferenceModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ explicit ObjectReferenceModel(QObject *parent = nullptr);
+ ~ObjectReferenceModel();
+
+ int rowCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+};
+
+#endif // OBJECTREFERENCEMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.cpp b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.cpp
new file mode 100644
index 00000000..eab0b0aa
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ObjectReferenceView.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "StudioPreferences.h"
+#include "IDocumentEditor.h"
+#include "UICDMValue.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+ObjectReferenceView::ObjectReferenceView(QWidget *parent) : QQuickWidget(parent)
+{
+ setWindowTitle(tr("Object Reference"));
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ObjectReferenceView::initialize);
+}
+
+void ObjectReferenceView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_resDir"_L1,
+ resourceImageUrl());
+ rootContext()->setContextProperty("_objectReferenceView"_L1, this);
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/ObjectReference.qml"_L1));
+}
+
+QSize ObjectReferenceView::sizeHint() const
+{
+ return {500, 500};
+}
+
+QAbstractItemModel *ObjectReferenceView::model() const
+{
+ return m_model;
+}
+
+void ObjectReferenceView::setModel(QAbstractItemModel *model)
+{
+ if (m_model != model) {
+ m_model = model;
+ Q_EMIT modelChanged();
+ }
+}
+
+void ObjectReferenceView::setHandle(int handle)
+{
+ m_handle = handle;
+}
+
+void ObjectReferenceView::setInstance(int instance)
+{
+ m_instance = instance;
+}
+
+void ObjectReferenceView::setSelectedReference(const QString &name)
+{
+ UICDM::SValue v = QVariant(name);
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), QObject::tr("Set Property"))
+ ->SetInstancePropertyValue(m_instance, m_handle, v);
+}
+
+void ObjectReferenceView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ close();
+}
+
diff --git a/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.h b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.h
new file mode 100644
index 00000000..5634fd97
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/ObjectReferenceView.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJECTREFERENCEVIEW_H
+#define OBJECTREFERENCEVIEW_H
+
+#include <QQuickWidget>
+class QAbstractItemModel;
+
+class ObjectReferenceView : public QQuickWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractItemModel *model READ model NOTIFY modelChanged FINAL)
+public:
+ explicit ObjectReferenceView(QWidget *parent = nullptr);
+
+ QSize sizeHint() const override;
+ QAbstractItemModel *model() const;
+ void setModel(QAbstractItemModel *model);
+
+ void setHandle(int handle);
+ void setInstance(int instance);
+
+ Q_INVOKABLE void setSelectedReference(const QString &name);
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+Q_SIGNALS:
+ void modelChanged();
+
+private:
+ void initialize();
+ int m_handle = -1;
+ int m_instance = -1;
+ QColor m_baseColor = QColor::fromRgb(75, 75, 75);
+ QAbstractItemModel *m_model = nullptr;
+};
+
+#endif // OBJECTREFERENCEVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.cpp b/src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.cpp
new file mode 100644
index 00000000..415b1877
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "TabOrderHandler.h"
+
+TabOrderHandler::TabOrderHandler(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+TabOrderHandler::~TabOrderHandler()
+{
+
+}
+
+void TabOrderHandler::addItem(int group, QQuickItem *item)
+{
+ m_itemMap[group].append(item);
+}
+
+void TabOrderHandler::clear()
+{
+ m_itemMap.clear();
+}
+
+void TabOrderHandler::clearGroup(int group)
+{
+ m_itemMap[group].clear();
+}
+
+void TabOrderHandler::tabNavigate(bool tabForward)
+{
+ // Find the currently focused control
+ for (int i = 0; i < m_itemMap.size(); i++) {
+ const QList<QQuickItem *> items = m_itemMap[i];
+ for (int j = 0; j < items.size(); j++) {
+ if (items[j]->hasActiveFocus()) {
+ if (tabForward)
+ nextItem(i, j)->forceActiveFocus();
+ else
+ previousItem(i, j)->forceActiveFocus();
+ return;
+ }
+ }
+ }
+ // Activate the first item if could not find currently focused item
+ for (int i = 0; i < m_itemMap.size(); i++) {
+ if (m_itemMap[i].size() > 0)
+ m_itemMap[i][0]->forceActiveFocus();
+ }
+}
+
+QQuickItem *TabOrderHandler::nextItem(int group, int index)
+{
+ if (m_itemMap[group].size() > index + 1) {
+ // Try next item in group
+ index++;
+ } else {
+ // Get item in next available group
+ int nextGroup = group + 1;
+ while (nextGroup != group) {
+ if (m_itemMap.size() >= nextGroup)
+ nextGroup = 0;
+ if (m_itemMap[nextGroup].size() == 0)
+ nextGroup++;
+ else
+ group = nextGroup;
+ }
+ index = 0;
+ }
+ return m_itemMap[group][index];
+}
+
+QQuickItem *TabOrderHandler::previousItem(int group, int index)
+{
+ if (index - 1 >= 0) {
+ // Try previous item in group
+ index--;
+ } else {
+ // Get last item in previous available group
+ int nextGroup = group - 1;
+ while (nextGroup != group) {
+ if (nextGroup < 0)
+ nextGroup = m_itemMap.size() - 1;
+ if (m_itemMap[nextGroup].size() == 0)
+ nextGroup--;
+ else
+ group = nextGroup;
+ }
+ index = m_itemMap[group].size() - 1;
+ }
+ return m_itemMap[group][index];
+}
+
diff --git a/src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.h b/src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.h
new file mode 100644
index 00000000..10c1d400
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/TabOrderHandler.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TABORDERHANDLER_H
+#define TABORDERHANDLER_H
+
+#include <QtCore/qobject.h>
+#include <QtQuick/qquickitem.h>
+
+class TabOrderHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit TabOrderHandler(QObject *parent = nullptr);
+ ~TabOrderHandler();
+
+ Q_INVOKABLE void addItem(int group, QQuickItem *item);
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void clearGroup(int group);
+
+ void tabNavigate(bool tabForward);
+
+private:
+ QQuickItem *nextItem(int group, int index);
+ QQuickItem *previousItem(int group, int index);
+
+ QHash<int, QList<QQuickItem *> > m_itemMap;
+};
+
+class TabNavigable {
+public:
+ TabNavigable() : m_tabOrderHandler(new TabOrderHandler) {}
+ virtual ~TabNavigable() { delete m_tabOrderHandler; }
+ TabOrderHandler *tabOrderHandler() const { return m_tabOrderHandler; }
+
+private:
+ TabOrderHandler *m_tabOrderHandler;
+};
+
+#endif // TABORDERHANDLER_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/TextureChooser.qml b/src/Authoring/Studio/Palettes/Inspector/TextureChooser.qml
new file mode 100644
index 00000000..4f90640e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/TextureChooser.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+ border.color: _studioColor3
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ spacing: 10
+ ListView {
+ id: listView
+
+ anchors {
+ fill: parent
+ leftMargin: 8
+ }
+
+ boundsBehavior: Flickable.StopAtBounds
+ spacing: 4
+ clip: true
+
+ ScrollBar.vertical: ScrollBar {}
+
+ model: _textureChooserModel
+
+ delegate: ChooserDelegate {
+ onClicked: {
+ _textureChooserView.textureSelected(
+ _textureChooserView.handle,
+ _textureChooserView.instance,
+ filePath);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/TextureChooserView.cpp b/src/Authoring/Studio/Palettes/Inspector/TextureChooserView.cpp
new file mode 100644
index 00000000..78084b06
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/TextureChooserView.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "TextureChooserView.h"
+#include "ImageChooserModel.h"
+#include "StudioPreferences.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "IDocumentEditor.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMValue.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "StudioPreferences.h"
+
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+TextureChooserView::TextureChooserView(QWidget *parent)
+ : QQuickWidget(parent)
+ , m_model(new ImageChooserModel(this))
+{
+ setWindowTitle(tr("Texture"));
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &TextureChooserView::initialize);
+}
+
+void TextureChooserView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_textureChooserView"_L1, this);
+ rootContext()->setContextProperty("_textureChooserModel"_L1, m_model);
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Inspector/TextureChooser.qml"_L1));
+}
+
+QSize TextureChooserView::sizeHint() const
+{
+ return {500, 500};
+}
+
+void TextureChooserView::setHandle(int handle)
+{
+ m_handle = handle;
+}
+
+int TextureChooserView::handle() const
+{
+ return m_handle;
+}
+
+void TextureChooserView::setInstance(int instance)
+{
+ m_instance = instance;
+}
+
+int TextureChooserView::instance() const
+{
+ return m_instance;
+}
+
+void TextureChooserView::focusOutEvent(QFocusEvent *event)
+{
+ QQuickWidget::focusOutEvent(event);
+ QTimer::singleShot(0, this, &TextureChooserView::close);
+}
+
+void TextureChooserView::showEvent(QShowEvent *event)
+{
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+
+ UICDM::SValue value;
+ propertySystem->GetInstancePropertyValue(m_instance, m_handle, value);
+
+ m_model->setCurrentFile(UICDM::get<QString>(value));
+
+ QQuickWidget::showEvent(event);
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/TextureChooserView.h b/src/Authoring/Studio/Palettes/Inspector/TextureChooserView.h
new file mode 100644
index 00000000..5bd51367
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/TextureChooserView.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTURECHOOSERVIEW_H
+#define TEXTURECHOOSERVIEW_H
+
+#include <QQuickWidget>
+
+class ImageChooserModel;
+
+class TextureChooserView : public QQuickWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int instance READ instance)
+ Q_PROPERTY(int handle READ handle)
+
+public:
+ explicit TextureChooserView(QWidget *parent = nullptr);
+
+ QSize sizeHint() const override;
+
+ void setHandle(int handle);
+ int handle() const;
+
+ void setInstance(int instance);
+ int instance() const;
+
+Q_SIGNALS:
+ void textureSelected(int handle, int instance, const QString &name);
+
+protected:
+ void focusOutEvent(QFocusEvent *event) override;
+
+private:
+ void showEvent(QShowEvent *event) override;
+ void initialize();
+ int m_handle = -1;
+ int m_instance = -1;
+ ImageChooserModel *m_model = nullptr;
+};
+
+#endif // TEXTURECHOOSERVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.cpp b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.cpp
new file mode 100644
index 00000000..1d009b4c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.cpp
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMInspectable.h"
+#include "UICDMInspectorGroup.h"
+#include "UICDMInspectorRow.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMDataCore.h"
+#include "UICDMPropertyDefinition.h"
+#include "Core.h"
+#include "StudioFullSystem.h"
+#include "StudioCoreSystem.h"
+#include "UICDMMetaData.h"
+#include "UICDMSlides.h"
+#include "IDocumentReader.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+using namespace UICDM;
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUICDMInspectable::CUICDMInspectable(CStudioApp &inApp, CCore *inCore,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inDualPersonalityInstance /*= 0*/)
+ : CInspectableBase(inCore)
+ , m_Instance(inInstance)
+ , m_DualPersonalityInstance((inDualPersonalityInstance != 0) ? inDualPersonalityInstance
+ : inInstance)
+ , m_App(inApp)
+{
+ QT3DS_ASSERT(inCore->GetDoc()->GetDocumentReader().IsInstance(m_Instance));
+}
+
+//==============================================================================
+/**
+ * Query the name of the inspectable item
+ */
+Q3DStudio::CString CUICDMInspectable::GetName()
+{
+ CClientDataModelBridge *theBridge =
+ m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+
+ if (m_Instance == m_DualPersonalityInstance)
+ return theBridge->GetName(m_Instance);
+
+ Q3DStudio::CString theName = theBridge->GetName(m_Instance);
+ theName += " (";
+ theName += theBridge->GetName(m_DualPersonalityInstance);
+ theName += ")";
+
+ return theName;
+}
+
+//==============================================================================
+/**
+ * Query the number of groups to display
+ */
+long CUICDMInspectable::GetGroupCount()
+{
+ // If you have a dual personality inspectable then you may overwrite
+ QT3DS_ASSERT(
+ m_Instance == m_DualPersonalityInstance
+ || m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsComponentInstance(
+ m_Instance));
+ IMetaData &theMetaData = *m_Core->GetDoc()->GetStudioSystem()->GetActionMetaData();
+ long count = (long)theMetaData.GetGroupCountForInstance(m_Instance);
+ return count;
+}
+
+//==============================================================================
+/**
+ * Return the property group for display
+ */
+CInspectorGroup *CUICDMInspectable::GetGroup(long inIndex)
+{
+ CUICDMInspectorGroup *theGroup =
+ new CUICDMInspectorGroup(m_App, GetGroupName(inIndex).toQString(), *this, inIndex);
+
+ TMetaDataPropertyHandleList theProperties = GetGroupProperties(inIndex);
+
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount; ++thePropertyIndex)
+ theGroup->CreateRow(m_Core->GetDoc(), theProperties[thePropertyIndex]);
+
+ return theGroup;
+}
+
+//==============================================================================
+/**
+ * Return the property handles for display, given the group index
+ */
+TMetaDataPropertyHandleList CUICDMInspectable::GetGroupProperties(long inIndex)
+{
+ TMetaDataPropertyHandleList retval;
+ IMetaData &theMetaData = *m_Core->GetDoc()->GetStudioSystem()->GetActionMetaData();
+ theMetaData.GetMetaDataProperties(GetGroupInstance(inIndex), retval);
+ UICDM::IPropertySystem &thePropertySystem(
+ *m_Core->GetDoc()->GetStudioSystem()->GetPropertySystem());
+ // get name of the current group fofr filtering
+ Option<UICDM::TCharStr> theGroupFilterName =
+ theMetaData.GetGroupFilterNameForInstance(GetGroupInstance(inIndex), inIndex);
+ long theGroupCount = GetGroupCount();
+
+ // end is explicitly required
+ for (size_t idx = 0; idx < retval.size(); ++idx) {
+ if (theMetaData.GetMetaDataPropertyInfo(retval[idx])->m_IsHidden) {
+ retval.erase(retval.begin() + idx);
+ --idx;
+ } else if (theGroupCount > 1 && theGroupFilterName.hasValue()
+ && theMetaData.GetMetaDataPropertyInfo(retval[idx])->m_GroupName
+ != theGroupFilterName) {
+ retval.erase(retval.begin() + idx);
+ --idx;
+ } else {
+ qt3ds::foundation::NVConstDataRef<SPropertyFilterInfo> theFilters(
+ theMetaData.GetMetaDataPropertyFilters(retval[idx]));
+ if (theFilters.size()) {
+ Option<bool> keepProperty;
+ // The tests are done in an ambiguous way. Really, show if equal should take
+ // multiple conditions
+ // as should hide if equal. They do not, so we need to rigorously define exactly
+ // how those two interact.
+ for (QT3DSU32 propIdx = 0, propEnd = theFilters.size(); propIdx < propEnd; ++propIdx) {
+ const SPropertyFilterInfo &theFilter(theFilters[propIdx]);
+
+ QT3DS_ASSERT(theFilter.m_FilterType == PropertyFilterTypes::ShowIfEqual
+ || theFilter.m_FilterType == PropertyFilterTypes::HideIfEqual);
+
+ SValue theValue;
+ thePropertySystem.GetInstancePropertyValue(
+ GetGroupInstance(inIndex), theFilter.m_FilterProperty, theValue);
+ bool resultIfTrue =
+ theFilter.m_FilterType == PropertyFilterTypes::ShowIfEqual ? true : false;
+ if (Equals(theValue.toOldSkool(), theFilter.m_Value.toOldSkool())) {
+ keepProperty = resultIfTrue;
+ break;
+ } else {
+ keepProperty = !resultIfTrue;
+ }
+ }
+ if (keepProperty.hasValue() && *keepProperty == false) {
+ retval.erase(retval.begin() + idx);
+ --idx;
+ }
+ }
+ }
+ }
+ return retval;
+}
+
+//==============================================================================
+/**
+ * Return the Resource String ID for the Group Name, given the group index
+ */
+Q3DStudio::CString CUICDMInspectable::GetGroupName(long inGroupIndex)
+{
+ std::vector<TCharStr> theGroupNames;
+ IMetaData &theMetaData = *m_Core->GetDoc()->GetStudioSystem()->GetActionMetaData();
+ theMetaData.GetGroupNamesForInstance(GetGroupInstance(inGroupIndex), theGroupNames);
+
+ size_t theIndex = inGroupIndex;
+
+ if (theGroupNames.size() > theIndex) {
+ Q3DStudio::CString theName = theGroupNames[inGroupIndex].wide_str();
+ return theName;
+ } else
+ return ::LoadResourceString(IDS_PROPERTIES_BASIC);
+}
+
+//==============================================================================
+/**
+ * Return the Inspectable Instance Handle for the Group, given the group index
+ */
+CUICDMInstanceHandle CUICDMInspectable::GetGroupInstance(long inGroupIndex)
+{
+ Q_UNUSED(inGroupIndex);
+ return m_DualPersonalityInstance;
+}
+
+EStudioObjectType CUICDMInspectable::GetObjectType()
+{
+ IMetaData &theMetaData = *m_Core->GetDoc()->GetStudioSystem()->GetActionMetaData();
+ Option<UICDM::TCharStr> theObjTypeName = theMetaData.GetTypeForInstance(m_Instance);
+ if (theObjTypeName.hasValue()) {
+ ComposerObjectTypes::Enum theType =
+ ComposerObjectTypes::Convert(theObjTypeName->wide_str());
+ switch (theType) {
+ case ComposerObjectTypes::Slide: {
+ CDoc *theDoc = m_Core->GetDoc();
+ CClientDataModelBridge *theBridge =
+ theDoc->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::CUICDMInstanceHandle theInstance =
+ theBridge->GetOwningComponentInstance(theDoc->GetActiveSlide());
+ Option<TCharStr> theObjTypeName = theMetaData.GetTypeForInstance(theInstance);
+ if (theObjTypeName.hasValue()) {
+ ComposerObjectTypes::Enum theType =
+ ComposerObjectTypes::Convert(theObjTypeName->wide_str());
+ if (theType == ComposerObjectTypes::Scene)
+ return OBJTYPE_SCENE;
+ else
+ return OBJTYPE_COMPONENT;
+ }
+ return OBJTYPE_UNKNOWN;
+ }
+ case ComposerObjectTypes::Scene:
+ return OBJTYPE_SCENE;
+ case ComposerObjectTypes::Layer:
+ return OBJTYPE_LAYER;
+ case ComposerObjectTypes::Behavior:
+ return OBJTYPE_BEHAVIOR;
+ case ComposerObjectTypes::Material:
+ return OBJTYPE_MATERIAL;
+ case ComposerObjectTypes::Camera:
+ return OBJTYPE_CAMERA;
+ case ComposerObjectTypes::Light:
+ return OBJTYPE_LIGHT;
+ case ComposerObjectTypes::Model:
+ return OBJTYPE_MODEL;
+ case ComposerObjectTypes::Group:
+ return OBJTYPE_GROUP;
+ case ComposerObjectTypes::Image:
+ return OBJTYPE_IMAGE;
+ case ComposerObjectTypes::Text:
+ return OBJTYPE_TEXT;
+ case ComposerObjectTypes::Component:
+ return OBJTYPE_COMPONENT;
+ case ComposerObjectTypes::Effect:
+ return OBJTYPE_EFFECT;
+ case ComposerObjectTypes::CustomMaterial:
+ return OBJTYPE_CUSTOMMATERIAL;
+ case ComposerObjectTypes::ReferencedMaterial:
+ return OBJTYPE_REFERENCEDMATERIAL;
+ case ComposerObjectTypes::Path:
+ return OBJTYPE_PATH;
+ case ComposerObjectTypes::SubPath:
+ return OBJTYPE_SUBPATH;
+ case ComposerObjectTypes::PathAnchorPoint:
+ return OBJTYPE_PATHANCHORPOINT;
+ case ComposerObjectTypes::Lightmaps:
+ return OBJTYPE_LIGHTMAPS;
+ }
+ }
+ return OBJTYPE_UNKNOWN;
+}
+
+bool CUICDMInspectable::IsValid() const
+{
+ return m_Core->GetDoc()->GetStudioSystem()->IsInstance(m_Instance)
+ && m_Core->GetDoc()->GetStudioSystem()->IsInstance(m_DualPersonalityInstance);
+}
+
+bool CUICDMInspectable::IsMaster()
+{
+ ISlideSystem *theSlideSystem = m_Core->GetDoc()->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMSlideHandle theSlideHandle = theSlideSystem->GetAssociatedSlide(m_Instance);
+ if (theSlideHandle.Valid())
+ return theSlideSystem->IsMasterSlide(theSlideHandle);
+ // Slide handle may not be valid if we are selecting the Scene or if we are inside Component and
+ // we select the Component root.
+ return false;
+}
+
+// std::wstring CUICDMInspectable::GetTypeString( ) const
+//{
+// std::wstring theReturn(L"");
+// try
+// {
+// IPropertySystem* thePropertySystem = m_Core->GetDoc( )->GetStudioSystem(
+//)->GetPropertySystem( );
+// CUICDMPropertyHandle theProperty =
+//thePropertySystem->GetAggregateInstancePropertyByName( m_Instance, L"type" );
+// SValue theTypeValue;
+// if ( theProperty && thePropertySystem->GetInstancePropertyValue( m_Instance,
+//theProperty, theTypeValue ) )
+// {
+// theReturn.assign( UICDM::get<TDataStrPtr>( theTypeValue )->GetData() );
+// }
+// }
+// catch( ... )
+// {
+// theReturn.assign(L"");
+// }
+//
+// return theReturn;
+//}
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.h b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.h
new file mode 100644
index 00000000..f497d4f9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectable.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICDM_INSPECTABLE_H
+#define INCLUDED_UICDM_INSPECTABLE_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "InspectableBase.h"
+#include "UICDMHandles.h"
+#include "StudioApp.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+* For inspecting data model instances
+*/
+class CUICDMInspectable : public CInspectableBase
+{
+protected: // Fields
+ UICDM::CUICDMInstanceHandle m_Instance;
+ UICDM::CUICDMInstanceHandle m_DualPersonalityInstance;
+ CStudioApp &m_App;
+
+public: // Constructor
+ CUICDMInspectable(CStudioApp &inApp, CCore *inCore, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inDualPersonalityInstance = 0);
+
+public: // CInspectableBase
+ Q3DStudio::CString GetName() override;
+ long GetGroupCount() override;
+ CInspectorGroup *GetGroup(long) override;
+ EStudioObjectType GetObjectType() override;
+ // virtual std::wstring GetTypeString( ) const;
+ bool IsValid() const override;
+ bool IsMaster() override;
+ virtual UICDM::TMetaDataPropertyHandleList GetGroupProperties(long inGroupIndex);
+ virtual UICDM::CUICDMInstanceHandle GetGroupInstance(long inGroupIndex);
+
+protected:
+ virtual Q3DStudio::CString GetGroupName(long inGroupIndex);
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.cpp b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.cpp
new file mode 100644
index 00000000..86f62847
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMInspectorGroup.h"
+#include "UICDMInspectorRow.h"
+#include "UICDMInspectable.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "UICDMMetaData.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUICDMInspectorGroup::CUICDMInspectorGroup(CStudioApp &inApp, const QString &inName,
+ CUICDMInspectable &inInspectable, long inIndex)
+ : CEasyInspectorGroup(inName)
+ , m_App(inApp)
+ , m_Inspectable(inInspectable)
+ , m_Index(inIndex)
+{
+}
+
+//==============================================================================
+/**
+ * clean up
+ */
+CUICDMInspectorGroup::~CUICDMInspectorGroup()
+{
+ std::vector<Q3DStudio::CUICDMInspectorRow *>::iterator theIterator =
+ m_UICDMInspectorRows.begin();
+ for (; theIterator != m_UICDMInspectorRows.end(); ++theIterator)
+ delete (*theIterator);
+}
+
+//==============================================================================
+/**
+ * Method to create a new InspectorRowBase.
+ */
+void CUICDMInspectorGroup::CreateRow(CDoc *inDoc, UICDM::CUICDMMetaDataPropertyHandle inProperty)
+{
+ Q3DStudio::CUICDMInspectorRow *theUICDMRow =
+ new Q3DStudio::CUICDMInspectorRow(inDoc, inProperty);
+ m_UICDMInspectorRows.push_back(
+ theUICDMRow); // this CUICDMInspectorRow is now owned by this class
+
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.h b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.h
new file mode 100644
index 00000000..3d811364
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorGroup.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICDM_INSPECTORGROUP_H
+#define INCLUDED_UICDM_INSPECTORGROUP_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EasyInspectorGroup.h"
+#include "UICDMHandles.h"
+#include "StudioApp.h"
+
+class CDoc;
+namespace Q3DStudio {
+class CUICDMInspectorRow;
+};
+
+class CUICDMInspectable;
+
+//==============================================================================
+/**
+ *
+ */
+class CUICDMInspectorGroup: public CEasyInspectorGroup
+{
+protected: // Members
+ CStudioApp &m_App;
+ std::vector<Q3DStudio::CUICDMInspectorRow *> m_UICDMInspectorRows;
+ CUICDMInspectable &m_Inspectable;
+ long m_Index;
+
+public: // Construction
+ CUICDMInspectorGroup(CStudioApp &inApp, const QString &inName,
+ CUICDMInspectable &inInspectable, long inIndex);
+ ~CUICDMInspectorGroup();
+
+ const std::vector<Q3DStudio::CUICDMInspectorRow *> &GetRows() const
+ {
+ return m_UICDMInspectorRows;
+ }
+
+public: // Use
+ void CreateRow(CDoc *inDoc, UICDM::CUICDMMetaDataPropertyHandle inProperty);
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.cpp b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.cpp
new file mode 100644
index 00000000..d92ef10a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMInspectorRow.h"
+#include "UICDMMetaData.h"
+#include "Doc.h"
+#include "StudioApp.h"
+#include "UICDMSlides.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMAnimation.h"
+#include "UICDMSignals.h"
+#include "CmdDataModelDeanimate.h"
+#include "UICDMDataCore.h"
+#include "Core.h"
+#include "ClientDataModelBridge.h"
+#include "IDocumentEditor.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+using namespace UICDM;
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUICDMInspectorRow::CUICDMInspectorRow(CDoc *inDoc,
+ CUICDMMetaDataPropertyHandle inProperty)
+ : m_MetaProperty(inProperty)
+{
+ IMetaData *theMetaData = inDoc->GetStudioSystem()->GetActionMetaData();
+ SMetaDataPropertyInfo theInfo(theMetaData->GetMetaDataPropertyInfo(inProperty));
+ m_MetaDataPropertyInfo = theInfo;
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CUICDMInspectorRow::~CUICDMInspectorRow()
+{
+}
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.h b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.h
new file mode 100644
index 00000000..ff2155bc
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMInspectorRow.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMHandles.h"
+#include "IEasyInspectorRowListener.h"
+#include "IDataDrivenChangeListener.h"
+#include "DispatchListeners.h"
+#include "UICDMMetaDataTypes.h"
+#include "CmdBatch.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CDoc;
+class CEasyInspectorRow;
+
+// UICDM
+namespace UICDM {
+class ISignalConnection;
+}
+
+class CGenericEdit;
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * This is a binding between a DataModelInspectable and an EasyInspectorRow
+ */
+class CUICDMInspectorRow
+{
+ //==============================================================================
+ // Members
+ //==============================================================================
+protected:
+ UICDM::CUICDMMetaDataPropertyHandle m_MetaProperty;
+ UICDM::SMetaDataPropertyInfo m_MetaDataPropertyInfo;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CUICDMInspectorRow(CDoc *inDoc, UICDM::CUICDMMetaDataPropertyHandle inProperty);
+ virtual ~CUICDMInspectorRow();
+
+private: // Disabled parameterless construction
+ CUICDMInspectorRow();
+
+public: // Use
+ UICDM::CUICDMMetaDataPropertyHandle GetMetaDataProperty() const
+ {
+ return m_MetaProperty;
+ }
+ const UICDM::SMetaDataPropertyInfo &GetMetaDataPropertyInfo() const
+ {
+ return m_MetaDataPropertyInfo;
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.cpp b/src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.cpp
new file mode 100644
index 00000000..70b204e5
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "UICDMMaterialInspectable.h"
+#include "UICDMInspectorGroup.h"
+#include "UICDMInspectorRow.h"
+#include "Core.h"
+#include "IDocumentEditor.h"
+#include "GenericComboDropDown.h"
+#include "UICDMHandles.h"
+#include "Doc.h"
+#include "GenericFunctor.h"
+#include "StudioApp.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "IDocumentReader.h"
+#include "Dispatch.h"
+#include "IDirectoryWatchingSystem.h"
+#include "UICDMSignals.h"
+#include "UICString.h"
+
+using namespace UICDM;
+
+struct SMaterialTypeDropDown : public CGenericComboDropDown
+{
+ struct SMaterialEntry
+ {
+ Q3DStudio::CString m_Name;
+ Q3DStudio::CString m_RelativePath;
+ bool operator<(const SMaterialEntry &inOther) const { return m_Name < inOther.m_Name; }
+ };
+ CUICDMInstanceHandle m_Instance;
+ Q3DStudio::CAutoMemPtr<CGenericEditCommitListener> m_CommitListener;
+ vector<SMaterialEntry> m_Materials;
+ CDoc &m_Doc;
+ TSignalConnectionPtr m_FileListPtr;
+
+ SMaterialTypeDropDown(CDoc &inDoc, CUICDMInstanceHandle inInstance)
+ : m_Instance(inInstance)
+ , m_Doc(inDoc)
+ {
+ using Q3DStudio::CString;
+ using Q3DStudio::CFilePath;
+ m_CommitListener =
+ CREATE_LISTENER(CGenericEditCommitListener, SMaterialTypeDropDown, OnDataCommit);
+ AddCommitListener(m_CommitListener);
+ m_FileListPtr = m_Doc.GetDirectoryWatchingSystem()->AddDirectory(
+ m_Doc.GetDocumentDirectory().toQString(),
+ std::bind(&SMaterialTypeDropDown::OnFilesChanged, this, std::placeholders::_1));
+ }
+
+ vector<SMaterialEntry>::iterator GetMaterialEntry(const Q3DStudio::CString &inRelativePath)
+ {
+ for (size_t idx = 0, end = m_Materials.size(); idx < end; ++idx)
+ if (m_Materials[idx].m_RelativePath == inRelativePath)
+ return m_Materials.begin() + idx;
+ return m_Materials.end();
+ }
+
+ vector<SMaterialEntry>::iterator
+ GetOrCreateMaterialEntry(const Q3DStudio::CString &inRelativePath)
+ {
+ vector<SMaterialEntry>::iterator retval = GetMaterialEntry(inRelativePath);
+ if (retval == m_Materials.end()) {
+ m_Materials.push_back(SMaterialEntry());
+ m_Materials.back().m_RelativePath = inRelativePath;
+ return m_Materials.begin() + m_Materials.size() - 1;
+ } else
+ return retval;
+ }
+
+ void OnFilesChanged(const Q3DStudio::TFileModificationList &inFileModificationList)
+ {
+ for (size_t idx = 0, end = inFileModificationList.size(); idx < end; ++idx) {
+ const Q3DStudio::SFileModificationRecord &theRecord = inFileModificationList[idx];
+ Q3DStudio::CFilePath relativePath(Q3DStudio::CFilePath::GetRelativePathFromBase(
+ m_Doc.GetDocumentDirectory(), theRecord.m_File));
+ Q3DStudio::CString extension = relativePath.GetExtension();
+ if (extension.CompareNoCase("material")) {
+ switch (theRecord.m_ModificationType) {
+ case Q3DStudio::FileModificationType::Created:
+ case Q3DStudio::FileModificationType::Modified: {
+ SMaterialEntry &theEntry =
+ *GetOrCreateMaterialEntry(Q3DStudio::CString(relativePath));
+ theEntry.m_Name =
+ m_Doc.GetDocumentReader().GetCustomMaterialName(theRecord.m_File);
+ } break;
+ case Q3DStudio::FileModificationType::Destroyed: {
+ vector<SMaterialEntry>::iterator theEntry = GetMaterialEntry(relativePath);
+ if (theEntry != m_Materials.end())
+ m_Materials.erase(theEntry);
+ } break;
+
+ default: // don't care.
+ break;
+ }
+ }
+ }
+
+ std::sort(m_Materials.begin(), m_Materials.end());
+
+ RefreshAllItems();
+ }
+
+ void RefreshAllItems()
+ {
+ RemoveAllItems();
+ AddItem("Standard Material");
+ AddItem("Referenced Material");
+ CClientDataModelBridge *theBridge = m_Doc.GetStudioSystem()->GetClientDataModelBridge();
+ long selectIdx = 0;
+ EStudioObjectType theType = theBridge->GetObjectType(m_Instance);
+
+ if (theType == OBJTYPE_REFERENCEDMATERIAL)
+ selectIdx = 1;
+
+ Q3DStudio::CString sourcePath = theBridge->GetSourcePath(m_Instance);
+
+ for (size_t matIdx = 0, end = m_Materials.size(); matIdx < end; ++matIdx) {
+ AddItem(m_Materials[matIdx].m_Name);
+ if (m_Materials[matIdx].m_RelativePath.Compare(sourcePath))
+ selectIdx = (long)matIdx + 2;
+ }
+
+ SelectItem(selectIdx, false);
+ }
+
+ // Note that the this object is probably deleted when this happens or will be during its
+ // execution.
+ static void DoChangeObjectType(CDoc *inDoc, const Q3DStudio::CString &inNewType,
+ CUICDMInstanceHandle instance)
+ {
+ using namespace Q3DStudio;
+ SCOPED_DOCUMENT_EDITOR(*inDoc, QObject::tr("Set Property"))->SetMaterialType(instance, inNewType);
+ }
+
+ void OnDataCommit()
+ {
+ using Q3DStudio::CString;
+ size_t item = this->GetSelectedItem();
+ if (item >= 0) {
+ CString selectedType = this->GetItemText(this->GetSelectedItem());
+ if (item > 1) {
+ size_t matIdx = item - 2;
+ if (matIdx < m_Materials.size())
+ selectedType = m_Materials[matIdx].m_RelativePath;
+ }
+ // Fire a command to do this later because we will get screwed if we don't as we will be
+ // deleted
+ // during this process.
+ g_StudioApp.GetCore()->GetDispatch()->FireOnAsynchronousCommand(
+ std::bind(&DoChangeObjectType, &m_Doc, selectedType, m_Instance));
+ }
+ }
+};
+
+UICDMMaterialInspectorGroup::UICDMMaterialInspectorGroup(
+ CStudioApp &inApp,
+ const Q3DStudio::CString &inName,
+ CUICDMInspectable &inInspectable,
+ long inIndex)
+ : CUICDMInspectorGroup(inApp, inName.toQString(), inInspectable, inIndex)
+{
+}
+
+struct SUICDMMaterialInspectorGroup : public UICDMMaterialInspectorGroup
+{
+ SUICDMMaterialInspectorGroup(CStudioApp &inApp, const Q3DStudio::CString &inName,
+ CUICDMInspectable &inInspectable, long inIndex)
+ : UICDMMaterialInspectorGroup(inApp, inName, inInspectable, inIndex)
+ {
+ Q3DStudio::CString theMaterialGroupName = L"Material";
+ m_isMaterialGroup = (inName == theMaterialGroupName);
+ }
+
+ bool isMaterialGroup() const override
+ {
+ return m_isMaterialGroup;
+ }
+
+private:
+ bool m_isMaterialGroup;
+};
+
+CInspectorGroup *CUICDMMaterialInspectable::GetGroup(long inIndex)
+{
+ Q3DStudio::CString theGroupName = GetGroupName(inIndex);
+ Q3DStudio::CString theMaterialGroupName = L"Material";
+
+ CUICDMInspectorGroup *theGroup =
+ new SUICDMMaterialInspectorGroup(m_App, theGroupName, *this, inIndex);
+
+ TMetaDataPropertyHandleList theProperties = GetGroupProperties(inIndex);
+ size_t thePropertyCount = theProperties.size();
+
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount; ++thePropertyIndex)
+ theGroup->CreateRow(m_Core->GetDoc(), theProperties[thePropertyIndex]);
+
+ return theGroup;
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.h b/src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.h
new file mode 100644
index 00000000..20bb4365
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMMaterialInspectable.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICDM_MATERIAL_INSPECTABLE_H
+#define INCLUDED_UICDM_MATERIAL_INSPECTABLE_H 1
+
+#include "UICDMInspectable.h"
+#include "UICDMInspectorGroup.h"
+
+class UICDMMaterialInspectorGroup : public CUICDMInspectorGroup
+{
+public:
+ UICDMMaterialInspectorGroup(CStudioApp &inApp, const Q3DStudio::CString &inName,
+ CUICDMInspectable &inInspectable, long inIndex);
+
+ virtual bool isMaterialGroup() const = 0;
+};
+
+class CUICDMMaterialInspectable : public CUICDMInspectable
+{
+public:
+ CUICDMMaterialInspectable(CStudioApp &inApp, CCore *inCore,
+ UICDM::CUICDMInstanceHandle inInstance)
+ : CUICDMInspectable(inApp, inCore, inInstance)
+ {
+ }
+
+ CInspectorGroup *GetGroup(long) override;
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.cpp b/src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.cpp
new file mode 100644
index 00000000..85f9b60c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMSceneInspectable.h"
+#include "Core.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+
+CUICDMSceneInspectable::CUICDMSceneInspectable(
+ CStudioApp &inApp, CCore *inCore, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inCurrentActiveSlideInstance)
+ : CUICDMInspectable(inApp, inCore, inInstance)
+ , m_CurrentActiveSlideInstance(inCurrentActiveSlideInstance)
+{
+}
+
+bool CUICDMSceneInspectable::IsValid() const
+{
+ return CUICDMInspectable::IsValid()
+ && m_Core->GetDoc()->GetStudioSystem()->IsInstance(m_CurrentActiveSlideInstance);
+}
+
+long CUICDMSceneInspectable::GetGroupCount()
+{
+ return 2; // hard-coded to basic and shared
+}
+
+//==============================================================================
+/**
+ * Return the Resource String ID for the Group Name, given the group index
+ */
+Q3DStudio::CString CUICDMSceneInspectable::GetGroupName(long inGroupIndex)
+{
+ return (inGroupIndex == 0) ? ::LoadResourceString(IDS_PROPERTIES_BASIC)
+ : ::LoadResourceString(IDS_PROPERTIES_SHARED);
+}
+
+UICDM::CUICDMInstanceHandle CUICDMSceneInspectable::GetGroupInstance(long inGroupIndex)
+{
+ return (inGroupIndex == 0) ? m_CurrentActiveSlideInstance : m_Instance;
+}
diff --git a/src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.h b/src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.h
new file mode 100644
index 00000000..f30693b9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Inspector/UICDMSceneInspectable.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICDM_SCENE_INSPECTABLE_H
+#define INCLUDED_UICDM_SCENE_INSPECTABLE_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMInspectable.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+* For inspecting scene data model instances
+*/
+class CUICDMSceneInspectable : public CUICDMInspectable
+{
+public:
+ CUICDMSceneInspectable(CStudioApp &inApp, CCore *inCore, UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inCurrentActiveSlideInstance);
+
+ bool IsValid() const override;
+ // CUICDMInspectable
+ long GetGroupCount() override;
+
+protected:
+ inline Q3DStudio::CString GetGroupName(long inGroupIndex) override;
+ inline UICDM::CUICDMInstanceHandle GetGroupInstance(long inGroupIndex) override;
+
+ UICDM::CUICDMInstanceHandle m_CurrentActiveSlideInstance;
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Master/MasterControl.cpp b/src/Authoring/Studio/Palettes/Master/MasterControl.cpp
new file mode 100644
index 00000000..922b6d02
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Master/MasterControl.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MasterControl.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "InspectorControl.h"
+#include "ActionControl.h"
+#include "GenericTabControl.h"
+
+//===============================================================================
+/**
+ * Constructor
+ * @param inStudioApp
+ */
+CMasterControl::CMasterControl(IMasterControlProvider *inProvider)
+ : m_Provider(inProvider)
+ , m_TabMenu(nullptr)
+ , m_RenderDevice(nullptr)
+{
+ // Create the tab control
+ m_TabControl = new CGenericTabControl();
+ AddChild(m_TabControl);
+ m_TabControl->SigTabSelected.connect(std::bind(&CMasterControl::OnTabSelected, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ // Add the drop-down menu
+ m_MenuButton = new CProceduralButton<CButtonControl>();
+ m_MenuButton->SetUpImage("Storage-Dropdown-Normal.png");
+ m_MenuButton->SetDisabledImage("Tab-Menu-Disabled.png");
+ m_MenuButton->SetAbsoluteSize(m_MenuButton->GetImageSize());
+ m_MenuButton->SetFillColorUp(CStudioPreferences::GetDarkBaseColor());
+ m_MenuButton->SetFillColorDown(CStudioPreferences::GetDarkBaseColor());
+ m_MenuButton->SetFillColorOver(CStudioPreferences::GetDarkBaseColor());
+ m_MenuButton->SetFillColorDisabled(CStudioPreferences::GetDarkBaseColor());
+ m_MenuButton->SetFillStyleAll(CProceduralButton<CButtonControl>::EFILLSTYLE_FLOOD);
+ CProceduralButton<CButtonControl>::SBorderOptions theBorders(false, false, false, false);
+ m_MenuButton->SetBorderVisibilityAll(theBorders);
+ m_MenuButton->SigButtonDown.connect(std::bind(&CMasterControl::OnMenuButtonDown, this,
+ std::placeholders::_1));
+ m_TabControl->SetTabBarSibling(m_MenuButton);
+}
+
+//===============================================================================
+/**
+ * Destructor
+ */
+CMasterControl::~CMasterControl()
+{
+ RemoveChild(m_TabControl);
+}
+
+//===============================================================================
+/**
+ * Display the context menu for this control
+ */
+void CMasterControl::DisplayContextMenu(CPt inPosition)
+{
+ ASSERT(m_Provider != nullptr);
+ m_Provider->OnContextMenu(this, inPosition, m_TabMenu);
+}
+
+//=============================================================================
+/**
+ * Callback when the menu button is selected
+ */
+void CMasterControl::AddControl(const Q3DStudio::CString &inName, long inType, CControl *inControl)
+{
+ inControl->SetName(inName);
+ m_ControlList.insert(std::make_pair(inControl, inType));
+ m_TabControl->AddTab(inName, inControl);
+}
+
+//=============================================================================
+/**
+ * Callback when the menu button is selected
+ */
+void CMasterControl::RemoveControl(CControl *inControl)
+{
+ TControlMap::iterator theIterator = m_ControlList.begin();
+ TControlMap::iterator theEndIterator = m_ControlList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (inControl == theIterator->first) {
+ m_ControlList.erase(theIterator);
+ break;
+ }
+ }
+
+ if (m_ControlList.size())
+ m_TabControl->SelectTab((long)0);
+
+ m_TabControl->RemoveTab(inControl);
+}
+
+//=============================================================================
+/**
+ * Callback when the menu button is selected
+ */
+void CMasterControl::SelectControl(long inIndex)
+{
+ m_TabControl->SelectTab(inIndex);
+}
+
+//=============================================================================
+/**
+ * Callback when the menu button is selected
+ */
+void CMasterControl::SelectControl(CControl *inControl)
+{
+ m_TabControl->SelectTab(inControl);
+}
+
+//=============================================================================
+/**
+ * Return the number of controls
+ */
+long CMasterControl::GetControlCount()
+{
+ return m_TabControl->GetTabCount();
+}
+
+//=============================================================================
+/**
+ * Return the control for the specified type
+ */
+CControl *CMasterControl::FindControl(long inType)
+{
+ CControl *theControl = nullptr;
+ TControlMap::iterator theIterator = m_ControlList.begin();
+ TControlMap::iterator theEndIterator = m_ControlList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (inType == theIterator->second) {
+ theControl = theIterator->first;
+ break;
+ }
+ }
+ return theControl;
+}
+
+//=============================================================================
+/**
+ * Return the active control
+ */
+CControl *CMasterControl::GetActiveControl()
+{
+ return m_TabControl->GetSelectedTab();
+}
+
+//=============================================================================
+/**
+ * Return the index of the active tab
+ */
+long CMasterControl::GetActiveIndex()
+{
+ return m_TabControl->GetSelectedTabIndex();
+}
+
+//=============================================================================
+/**
+ * Return the active type
+ */
+long CMasterControl::GetActiveType()
+{
+ return m_ControlList[GetActiveControl()];
+}
+
+//=============================================================================
+/**
+ * Callback when the menu button is selected
+ */
+void CMasterControl::OnMenuButtonDown(CControl *)
+{
+ CPt thePosition(GetSize().x, GetPosition().y + m_MenuButton->GetSize().y);
+ DisplayContextMenu(thePosition);
+}
+
+//=============================================================================
+/**
+ * Callback when a tab changes
+ */
+void CMasterControl::OnTabSelected(CControl *, CControl *inNewControl)
+{
+ // Notify the provider that the selection changed
+ m_Provider->OnControlSelected(this, inNewControl, m_ControlList[inNewControl]);
+
+ // Set the enabled state of the menu item
+ m_MenuButton->SetEnabled((m_TabControl->GetTabCount() != 0));
+}
+
+//==============================================================================
+// CControl
+//==============================================================================
+
+Q3DStudio::CString CMasterControl::GetName()
+{
+ CControl *theActiveControl = GetActiveControl();
+ if (theActiveControl)
+ return theActiveControl->GetName();
+ return L"< Empty >";
+}
+
+//=============================================================================
+/**
+ * Fills the whole control with the base (gray) color, then other controls will
+ * draw on top of that.
+ * @param inRenderer renderer to draw to
+ */
+void CMasterControl::Draw(CRenderer *inRenderer)
+{
+ inRenderer->FillSolidRect(GetSize(), CStudioPreferences::GetDarkBaseColor());
+}
+
+//=============================================================================
+/**
+ * Set the size of the tree control
+ */
+void CMasterControl::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+ m_TabControl->SetSize(inSize);
+}
+
+//=============================================================================
+/**
+ * Check to see if the right mouse down occurred on the tab control
+ */
+bool CMasterControl::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (m_TabControl->IsInTabBar(inPoint)) {
+ DisplayContextMenu(inPoint);
+ return true;
+ }
+
+ return CControl::OnMouseRDown(inPoint, inFlags); // not handled
+}
+
+//=============================================================================
+/**
+ * Return the window handle to the master view
+ */
+UICRenderDevice CMasterControl::GetPlatformDevice()
+{
+ return m_RenderDevice;
+}
+
+//=============================================================================
+/**
+ * Overriden from CControl. Since this control's parent is the CWnd, ensure
+ * that it gets the keyboard focus if this function is called.
+ * @see CControl::SetFocus
+ */
+void CMasterControl::GrabFocus(CControl *inControl)
+{
+ if (m_RenderDevice) {
+ ::SetFocus(m_RenderDevice);
+ }
+
+ CControl::GrabFocus(inControl);
+}
diff --git a/src/Authoring/Studio/Palettes/Master/MasterControl.h b/src/Authoring/Studio/Palettes/Master/MasterControl.h
new file mode 100644
index 00000000..40a347a4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Master/MasterControl.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_MASTER_CONTROL_H
+#define INCLUDED_MASTER_CONTROL_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "ProceduralButton.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+class CRenderer;
+class CAssetControl;
+class CGenericTabControl;
+class CMasterControl;
+
+//==============================================================================
+/**
+ * @class IMasterControlProvider
+ */
+class IMasterControlProvider
+{
+public:
+ virtual void OnControlRemoved(CMasterControl *inControl) = 0;
+ virtual void OnContextMenu(CMasterControl *inControl, const CPt &inPosition,
+ CContextMenu *inMyMenu) = 0;
+ virtual void OnControlSelected(CMasterControl *inMaster, CControl *inControl, long inType) = 0;
+};
+
+//==============================================================================
+/**
+ * @class CMasterControl
+ * @brief Class wrapping up all controls that appear in the Inspector Palette.
+ */
+class CMasterControl : public CControl
+{
+protected:
+ typedef std::map<CControl *, long> TControlMap;
+
+public:
+ CMasterControl(IMasterControlProvider *inProvider);
+ ~CMasterControl();
+
+ void SetRenderDevice(UICRenderDevice inDevice) { m_RenderDevice = inDevice; }
+
+ void AddControl(const Q3DStudio::CString &inName, long inType, CControl *inControl);
+ void RemoveControl(CControl *inControl);
+ void SelectControl(long inIndex);
+ void SelectControl(CControl *inControl);
+ long GetControlCount();
+ CControl *FindControl(long inType);
+
+ long GetActiveType();
+ long GetActiveIndex();
+ CControl *GetActiveControl();
+
+ // CControl
+ virtual Q3DStudio::CString GetName();
+ void Draw(CRenderer *inRenderer) override;
+ void SetSize(CPt inSize) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ UICRenderDevice GetPlatformDevice() override;
+ void GrabFocus(CControl *inControl) override;
+
+protected:
+ void DisplayContextMenu(CPt inPosition);
+ void OnTabSelected(CControl *inOldControl, CControl *inNewControl);
+ void OnMenuButtonDown(CControl *);
+
+protected:
+ IMasterControlProvider *m_Provider; ///<
+ CContextMenu *m_TabMenu; ///<
+ Q3DStudio::CAutoMemPtr<CGenericTabControl> m_TabControl; ///<
+ Q3DStudio::CAutoMemPtr<CProceduralButton<CButtonControl>>
+ m_MenuButton; ///< menu button for the storage palette
+ TControlMap m_ControlList; ///< the list of controls to display
+ UICRenderDevice m_RenderDevice; ///<
+};
+
+#endif //#ifndef INCLUDED_MASTER_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Master/MasterView.cpp b/src/Authoring/Studio/Palettes/Master/MasterView.cpp
new file mode 100644
index 00000000..8a4a9bd5
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Master/MasterView.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MasterView.h"
+#include "WndControl.h"
+#include "StudioApp.h"
+#include "MasterControl.h"
+#include "IDragable.h"
+
+//==============================================================================
+// Message Maps, etc.
+//==============================================================================
+IMPLEMENT_DYNCREATE(CMasterView, CView)
+
+BEGIN_MESSAGE_MAP(CMasterView, CView)
+//{{AFX_MSG_MAP(CMasterView)
+ON_WM_SIZE()
+ON_WM_ERASEBKGND()
+ON_WM_MOUSEACTIVATE()
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_STUDIO_INITIALIZE_PALETTES, OnInitializePalettes)
+END_MESSAGE_MAP()
+
+int CMasterView::OnMouseActivate(CWnd *, UINT, UINT)
+{
+ return MA_NOACTIVATE;
+}
+
+//=============================================================================
+/**
+ * Constructor: Protected because the view is always created dynamically.
+ * You must call Initialize() before trying to use this class.
+ */
+CMasterView::CMasterView()
+ : m_WndControl(nullptr)
+ , m_Provider(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CMasterView::~CMasterView()
+{
+ m_WndControl->DestroyWindow();
+ m_WndControl = nullptr;
+
+ m_MasterControl = nullptr;
+}
+
+//==============================================================================
+/**
+ * Handles the WM_INITIALUPDATE message. Responsible for preparing the view
+ * before it is displayed for the first time.
+ */
+LRESULT CMasterView::OnInitializePalettes(WPARAM inwParam, LPARAM)
+{
+ if (!m_WndControl) {
+ CStudioApp *theStudioApp = reinterpret_cast<CStudioApp *>(inwParam);
+
+ m_MasterControl = new CMasterControl(m_Provider);
+ m_WndControl = new CWndControl(m_MasterControl);
+
+ m_WndControl->RegiserForDnd(this);
+
+ m_WndControl->AddMainFlavor(EUIC_FLAVOR_LISTBOX);
+ m_WndControl->AddMainFlavor(EUIC_FLAVOR_FILE);
+ m_WndControl->AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE);
+ m_WndControl->AddMainFlavor(EUIC_FLAVOR_ASSET_LIB);
+ m_WndControl->AddMainFlavor(EUIC_FLAVOR_ASSET_TL);
+ m_WndControl->AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS);
+
+ CRect theClientRect;
+ GetClientRect(&theClientRect);
+
+ m_WndControl->CreateEx(
+ WS_EX_NOPARENTNOTIFY, AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(nullptr, IDC_ARROW),
+ (HBRUSH)GetStockObject(BLACK_BRUSH)),
+ L"MasterViewWndCtrl", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ theClientRect, this, 100);
+ m_MasterControl->SetRenderDevice(m_WndControl->GetSafeHwnd());
+ }
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Required by base class but does nothing since all drawing is handled by the
+ * child control.
+ */
+void CMasterView::OnDraw(CDC *inDC)
+{
+ Q_UNUSED(inDC);
+}
+
+//=============================================================================
+/**
+ * Resizes the wnd control to fill the whole view.
+ */
+void CMasterView::OnSize(UINT inType, int inX, int inY)
+{
+ CView::OnSize(inType, inX, inY);
+ if (::IsWindow(m_WndControl->GetSafeHwnd()))
+ m_WndControl->MoveWindow(0, 0, inX, inY);
+}
+
+//==============================================================================
+/**
+ * Tells the Inspector to erase before redrawing. Overridden because we erasing
+ * before each draw produces a flashing effect.
+ * @param inDC the DC to erase on.
+ * @return FALSE.
+ */
+BOOL CMasterView::OnEraseBkgnd(CDC *inDC)
+{
+ Q_UNUSED(inDC);
+ return FALSE;
+}
diff --git a/src/Authoring/Studio/Palettes/Master/MasterView.h b/src/Authoring/Studio/Palettes/Master/MasterView.h
new file mode 100644
index 00000000..008d748f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Master/MasterView.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_MASTER_VIEW_H
+#define INCLUDED_MASTER_VIEW_H 1
+
+#pragma once
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+class CWndControl;
+class CMasterControl;
+class IMasterControlProvider;
+
+//=============================================================================
+/**
+ * Windows view encapsulating the inspector palette.
+ */
+class CMasterView : public CView
+{
+protected:
+ CMasterView();
+ DECLARE_DYNCREATE(CMasterView)
+ virtual ~CMasterView();
+
+ afx_msg void OnSize(UINT inType, int inX, int inY);
+ afx_msg BOOL OnEraseBkgnd(CDC *inDC);
+ afx_msg int OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message);
+ DECLARE_MESSAGE_MAP()
+
+public:
+ virtual void OnDraw(CDC *inDC);
+ virtual LRESULT OnInitializePalettes(WPARAM inwParam, LPARAM inlParam);
+
+ void SetProvider(IMasterControlProvider *inProvider) { m_Provider = inProvider; }
+ CMasterControl *GetMasterControl() const { return m_MasterControl; }
+
+protected:
+ IMasterControlProvider *m_Provider; ///<
+ CWndControl *m_WndControl; ///<
+ Q3DStudio::CAutoMemPtr<CMasterControl> m_MasterControl; ///<
+};
+
+#endif // INCLUDED_MASTER_VIEW_H
diff --git a/src/Authoring/Studio/Palettes/Progress/ProgressCallback.h b/src/Authoring/Studio/Palettes/Progress/ProgressCallback.h
new file mode 100644
index 00000000..eeff02b8
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Progress/ProgressCallback.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROGRESS_CALLBACK_H
+#define INCLUDED_PROGRESS_CALLBACK_H 1
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * Callback interface to progress update window
+ */
+class IProgressCallback
+{
+public:
+ virtual void SetProgress(long inPercent) = 0;
+
+ virtual void SetActionText(const Q3DStudio::CString &inText) = 0;
+};
+
+#endif // INCLUDED_PROGRESS_CALLBACK_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Progress/ProgressControl.cpp b/src/Authoring/Studio/Palettes/Progress/ProgressControl.cpp
new file mode 100644
index 00000000..2a69bf44
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Progress/ProgressControl.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ProgressControl.h"
+#include "Renderer.h"
+#include "ResourceCache.h"
+#include "ResImage.h"
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CProgressControl::CProgressControl()
+ : m_Percent(0)
+{
+ // Load the image
+ m_Image = CResourceCache::GetInstance()->GetBitmap("progress-screen.png");
+
+ // Load the default string for the window for now
+ m_ActionText = ::LoadResourceString(IDS_WAIT_LOADING);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CProgressControl::~CProgressControl()
+{
+}
+
+//==============================================================================
+/**
+ * The size of this control is equal to the size of the image that we display.
+ * @return the size (in pixels) of this control.
+ */
+CPt CProgressControl::GetSize() const
+{
+ return m_Image->GetSize();
+}
+
+//==============================================================================
+/**
+ * Draws this control.
+ * @param inRenderer renderer to draw to.
+ */
+void CProgressControl::Draw(CRenderer *inRenderer)
+{
+ // Draw the image over the whole window
+ inRenderer->DrawBitmap(CPt(0, 0), m_Image);
+
+ // Show "Loading..."
+ inRenderer->DrawText(105, 20, m_ActionText, GetSize(), CColor(255, 255, 255));
+
+ // Show the file name
+ if (!m_FileName.IsEmpty())
+ inRenderer->DrawText(105, 35, m_FileName, GetSize(), CColor(255, 255, 255));
+
+ // Show the percentage
+ inRenderer->DrawText(105, 50, m_PercentString, GetSize(), CColor(255, 255, 255));
+}
+
+//==============================================================================
+/**
+ * Sets the text displayed above the file name. For instance: "Loading..."
+ * @param inText text to be shown above the file name
+ */
+void CProgressControl::SetActionText(const Q3DStudio::CString &inText)
+{
+ m_ActionText = inText;
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Changes the percentage complete displayed by this control.
+ * @param inPercent new percentage complete.
+ */
+void CProgressControl::SetProgress(long inPercent)
+{
+ m_Percent = inPercent;
+ char theBuffer[256] = { 0 };
+ _ltoa(m_Percent, theBuffer, 10);
+ m_PercentString = theBuffer;
+ m_PercentString += " %";
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Sets the name of the file that is being opened. This is displayed on the
+ * control.
+ * @param inFileName File name to display in the middle of this control
+ */
+void CProgressControl::SetFileName(const Q3DStudio::CString &inFileName)
+{
+ m_FileName = inFileName;
+ Invalidate();
+}
diff --git a/src/Authoring/Studio/Palettes/Progress/ProgressControl.h b/src/Authoring/Studio/Palettes/Progress/ProgressControl.h
new file mode 100644
index 00000000..1d596c0c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Progress/ProgressControl.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROGRESS_CONTROL_H
+#define INCLUDED_PROGRESS_CONTROL_H 1
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class CResImage;
+
+//==============================================================================
+/**
+ * Top-level control of a loading progress window.
+ */
+class CProgressControl : public CControl
+{
+public:
+ CProgressControl();
+ virtual ~CProgressControl();
+
+ virtual CPt GetSize() const;
+ virtual void Draw(CRenderer *inRenderer);
+ virtual void SetActionText(const Q3DStudio::CString &inText);
+ virtual void SetProgress(long inPercent);
+ void SetFileName(const Q3DStudio::CString &inFileName);
+
+protected:
+ long m_Percent;
+ Q3DStudio::CString m_ActionText;
+ Q3DStudio::CString m_PercentString;
+ Q3DStudio::CString m_FileName;
+ CResImage *m_Image;
+};
+
+#endif // INCLUDED_PROGRESS_CONTROL_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectContextMenu.cpp b/src/Authoring/Studio/Palettes/Project/ProjectContextMenu.cpp
new file mode 100644
index 00000000..edcafbf1
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectContextMenu.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ProjectContextMenu.h"
+#include "ProjectView.h"
+
+ProjectContextMenu::ProjectContextMenu(ProjectView *parent, int index)
+ : QMenu(parent)
+ , m_view(parent)
+ , m_index(index)
+{
+ QAction *action = new QAction(tr("Show in Explorer"));
+ connect(action, &QAction::triggered, this, &ProjectContextMenu::handleShowInExplorer);
+ addAction(action);
+
+ addSeparator();
+
+ action = new QAction(tr("Copy Path"));
+ connect(action, &QAction::triggered, this, &ProjectContextMenu::handleCopyPath);
+ addAction(action);
+
+ action = new QAction(tr("Copy Full Path"));
+ connect(action, &QAction::triggered, this, &ProjectContextMenu::handleCopyFullPath);
+ addAction(action);
+
+ if (m_view->isGroup(m_index)) {
+ addSeparator();
+ action = new QAction(tr("Refresh Import..."));
+ connect(action, &QAction::triggered, this, &ProjectContextMenu::handleRefreshImport);
+ addAction(action);
+ }
+}
+
+ProjectContextMenu::~ProjectContextMenu()
+{
+}
+
+void ProjectContextMenu::handleShowInExplorer()
+{
+ m_view->showInExplorer(m_index);
+}
+
+void ProjectContextMenu::handleCopyPath()
+{
+ m_view->copyPath(m_index);
+}
+
+void ProjectContextMenu::handleCopyFullPath()
+{
+ m_view->copyFullPath(m_index);
+}
+
+void ProjectContextMenu::handleRefreshImport()
+{
+ m_view->refreshImport(m_index);
+}
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectContextMenu.h b/src/Authoring/Studio/Palettes/Project/ProjectContextMenu.h
new file mode 100644
index 00000000..51dc8c5d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectContextMenu.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROJECT_CONTEXT_MENU_H
+#define PROJECT_CONTEXT_MENU_H
+
+#include <QtWidgets/qmenu.h>
+
+class ProjectView;
+
+class ProjectContextMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ explicit ProjectContextMenu(ProjectView *parent, int index);
+ virtual ~ProjectContextMenu();
+
+private Q_SLOTS:
+ void handleShowInExplorer();
+ void handleCopyPath();
+ void handleCopyFullPath();
+ void handleRefreshImport();
+
+private:
+ ProjectView *m_view;
+ int m_index;
+};
+#endif // PROJECT_CONTEXT_MENU_H
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp
new file mode 100644
index 00000000..07ddd3d4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp
@@ -0,0 +1,587 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qtAuthoring-config.h"
+#include <QtCore/qset.h>
+
+#include "stdafx.h"
+#include "ProjectFileSystemModel.h"
+#include "StudioUtils.h"
+#include "StudioApp.h"
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "Doc.h"
+#include "UICFileTools.h"
+#include "ImportUtils.h"
+#include "Dialogs.h"
+#include "UICDMStudioSystem.h"
+#include "UICImportTranslation.h"
+#include "IDocumentEditor.h"
+#include "PathImportTranslator.h"
+#include "IDragable.h"
+
+ProjectFileSystemModel::ProjectFileSystemModel(QObject *parent) : QAbstractListModel(parent)
+ , m_model(new QFileSystemModel(this))
+{
+ connect(m_model, &QAbstractItemModel::rowsInserted, this, &ProjectFileSystemModel::modelRowsInserted);
+ connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ProjectFileSystemModel::modelRowsRemoved);
+ connect(m_model, &QAbstractItemModel::layoutChanged, this, &ProjectFileSystemModel::modelLayoutChanged);
+}
+
+QHash<int, QByteArray> ProjectFileSystemModel::roleNames() const
+{
+ auto modelRoleNames = m_model->roleNames();
+ modelRoleNames.insert(IsExpandableRole, "_isExpandable");
+ modelRoleNames.insert(IsDraggableRole, "_isDraggable");
+ modelRoleNames.insert(IsReferencedRole, "_isReferenced");
+ modelRoleNames.insert(DepthRole, "_depth");
+ modelRoleNames.insert(ExpandedRole, "_expanded");
+ return modelRoleNames;
+}
+
+int ProjectFileSystemModel::rowCount(const QModelIndex &) const
+{
+ return m_items.count();
+}
+
+QVariant ProjectFileSystemModel::data(const QModelIndex &index, int role) const
+{
+ const auto &item = m_items.at(index.row());
+
+ switch (role) {
+ case Qt::DecorationRole: {
+ QString path = item.index.data(QFileSystemModel::FilePathRole).toString();
+ return resourceImageUrl() + getIconName(path);
+ }
+
+ case IsExpandableRole: {
+ if (item.index == m_rootIndex) {
+ return false;
+ } else {
+ return hasVisibleChildren(item.index);
+ }
+ }
+
+ case IsDraggableRole:
+ return QFileInfo(item.index.data(QFileSystemModel::FilePathRole).toString()).isFile();
+
+ case IsReferencedRole: {
+ const QString path = item.index.data(QFileSystemModel::FilePathRole).toString();
+ return m_references.contains(path);
+ }
+
+ case DepthRole:
+ return item.depth;
+
+ case ExpandedRole:
+ return item.expanded;
+
+ default:
+ return m_model->data(item.index, role);
+ }
+}
+
+QMimeData *ProjectFileSystemModel::mimeData(const QModelIndexList &indexes) const
+{
+ const auto path = filePath(indexes.first().row()); // can only drag one item
+ CUICFile dragFile(Q3DStudio::CString::fromQString(path));
+ return CDropSourceFactory::Create(EUIC_FLAVOR_ASSET_UICFILE,
+ reinterpret_cast<void *>(&dragFile),
+ sizeof(dragFile));
+}
+
+QString ProjectFileSystemModel::filePath(int row) const
+{
+ if (row < 0 || row >= m_items.size())
+ return QString();
+ const auto &item = m_items.at(row);
+ return item.index.data(QFileSystemModel::FilePathRole).toString();
+}
+
+void ProjectFileSystemModel::updateReferences(bool emitDataChanged)
+{
+ m_references.clear();
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+ const auto sourcePathList = bridge->GetSourcePathList();
+ const auto fontFileList = bridge->GetFontFileList();
+ const auto effectTextureList = bridge->GetDynamicObjectTextureList();
+
+ auto addFileReferences = [this, doc](const Q3DStudio::CString &str) {
+ auto path = doc->GetResolvedPathToDoc(str).toQString();
+ path = QDir::cleanPath(path);
+ m_references.append(path);
+ QString rootPath = QDir::cleanPath(doc->GetDocumentDirectory().toQString());
+ QString parentPath = QFileInfo(path).path();
+ do {
+ if (!m_references.contains(parentPath))
+ m_references.append(parentPath);
+ path = parentPath;
+ parentPath = QFileInfo(path).path();
+ } while (rootPath != path && parentPath != path);
+ };
+
+ std::for_each(sourcePathList.begin(), sourcePathList.end(), addFileReferences);
+ std::for_each(fontFileList.begin(), fontFileList.end(), addFileReferences);
+ std::for_each(effectTextureList.begin(), effectTextureList.end(), addFileReferences);
+
+ if (emitDataChanged)
+ Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {IsReferencedRole});
+}
+
+void ProjectFileSystemModel::setRootPath(const QString &path)
+{
+ setRootIndex(m_model->setRootPath(path));
+}
+
+void ProjectFileSystemModel::setRootIndex(const QModelIndex &rootIndex)
+{
+ if (rootIndex == m_rootIndex)
+ return;
+
+ clearModelData();
+ updateReferences(false);
+
+ m_rootIndex = rootIndex;
+
+ beginInsertRows({}, 0, 0);
+ m_items.append({ m_rootIndex, 0, true, nullptr, 0 });
+ endInsertRows();
+
+ showModelTopLevelItems();
+}
+
+void ProjectFileSystemModel::clearModelData()
+{
+ beginResetModel();
+ m_items.clear();
+ endResetModel();
+}
+
+void ProjectFileSystemModel::showModelTopLevelItems()
+{
+ int rowCount = m_model->rowCount(m_rootIndex);
+
+ if (rowCount == 0) {
+ if (m_model->hasChildren(m_rootIndex) && m_model->canFetchMore(m_rootIndex))
+ m_model->fetchMore(m_rootIndex);
+ } else {
+ showModelChildItems(m_rootIndex, 0, rowCount - 1);
+ }
+}
+
+void ProjectFileSystemModel::showModelChildItems(const QModelIndex &parentIndex, int start, int end)
+{
+ const int parentRow = modelIndexRow(parentIndex);
+ if (parentRow == -1)
+ return;
+
+ Q_ASSERT(isVisible(parentIndex));
+
+ QVector<QModelIndex> rowsToInsert;
+ for (int i = start; i <= end; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ if (isVisible(childIndex))
+ rowsToInsert.append(childIndex);
+ }
+
+ const int insertCount = rowsToInsert.count();
+ if (insertCount == 0)
+ return;
+
+ auto parent = &m_items[parentRow];
+
+ const int depth = parent->depth + 1;
+ const int startRow = parentRow + parent->childCount + 1;
+
+ beginInsertRows({}, startRow, startRow + insertCount - 1);
+
+ for (auto it = rowsToInsert.rbegin(); it != rowsToInsert.rend(); ++it)
+ m_items.insert(startRow, { *it, depth, false, parent, 0 });
+
+ for (; parent != nullptr; parent = parent->parent)
+ parent->childCount += insertCount;
+
+ endInsertRows();
+
+ // also fetch children so we're notified when files are added or removed in immediate subdirs
+ for (const auto &childIndex : rowsToInsert) {
+ if (m_model->hasChildren(childIndex) && m_model->canFetchMore(childIndex))
+ m_model->fetchMore(childIndex);
+ }
+}
+
+void ProjectFileSystemModel::expand(int row)
+{
+ Q_ASSERT(row >= 0 && row < m_items.size());
+
+ auto &item = m_items[row];
+ Q_ASSERT(item.expanded == false);
+
+ const auto &modelIndex = item.index;
+
+ const int rowCount = m_model->rowCount(modelIndex);
+ if (rowCount == 0) {
+ if (m_model->hasChildren(modelIndex) && m_model->canFetchMore(modelIndex))
+ m_model->fetchMore(modelIndex);
+ } else {
+ showModelChildItems(modelIndex, 0, rowCount - 1);
+ }
+
+ item.expanded = true;
+ Q_EMIT dataChanged(index(row), index(row));
+}
+
+bool ProjectFileSystemModel::hasValidUrlsForDropping(const QList<QUrl> &urls) const
+{
+ for (const auto &url : urls) {
+ if (url.isLocalFile()) {
+ const QString path = url.toLocalFile();
+ const QFileInfo fileInfo(path);
+ if (fileInfo.isFile()) {
+ const QString extension = fileInfo.suffix();
+ return extension.compare(QLatin1String(CDialogs::GetDAEFileExtension()),
+ Qt::CaseInsensitive) == 0
+#ifdef QT_3DSTUDIO_FBX
+ || extension.compare(QLatin1String(CDialogs::GetFbxFileExtension()),
+ Qt::CaseInsensitive) == 0
+#endif
+ || getIconType(path) != OBJTYPE_UNKNOWN;
+ }
+ }
+ }
+
+ return false;
+}
+
+void ProjectFileSystemModel::dropUrls(const QList<QUrl> &urls, int row)
+{
+ Q_ASSERT(row >= 0 && row < m_items.size());
+
+ const auto &item = m_items.at(row);
+ const QString targetPath = item.index.data(QFileSystemModel::FilePathRole).toString();
+ const QDir targetDir(targetPath);
+
+ if (targetDir.exists()) {
+ for (const auto& url : urls)
+ dropUrl(targetPath, url);
+
+ if (!item.expanded)
+ expand(row);
+ }
+}
+
+void ProjectFileSystemModel::dropUrl(const QDir &targetDir, const QUrl &url) const
+{
+ using namespace Q3DStudio;
+ using namespace UICIMP;
+ // Drag and Drop - From Explorer window to Project Palette
+ // For all valid Project File Types:
+ // - This performs a file copy from the source Explorer location to the selected Project Palette
+ // Folder
+ // - The destination copy must NOT be read-only even if the source is read-only
+ // For DAE, it will import the file.
+
+ if (!url.isLocalFile())
+ return;
+
+ const QString sourceFile = url.toLocalFile();
+
+ const QFileInfo fileInfo(sourceFile);
+ if (!fileInfo.isFile())
+ return;
+
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+
+ const QString extension = fileInfo.suffix();
+ const QString fileStem = fileInfo.baseName();
+ const QString outputFileName = QStringLiteral("%1.%2").arg(fileStem).arg(CDialogs::GetImportFileExtension());
+
+ if (extension.compare(QLatin1String(CDialogs::GetDAEFileExtension()), Qt::CaseInsensitive) == 0) {
+ SColladaTranslator translator(sourceFile);
+ const QDir outputDir = SFileTools::FindUniqueDestDirectory(targetDir, fileStem);
+ const QString fullOutputFile = outputDir.filePath(outputFileName);
+ const SImportResult importResult =
+ CPerformImport::TranslateToImportFile(translator, CFilePath::fromQString(fullOutputFile));
+ bool forceError = QFileInfo(fullOutputFile).isFile() == false;
+ IDocumentEditor::DisplayImportErrors(
+ sourceFile, importResult.m_Error, doc->GetImportFailedHandler(),
+ translator.m_TranslationLog, forceError);
+#ifdef QT_3DSTUDIO_FBX
+ } else if (extension.compare(QLatin1String(CDialogs::GetFbxFileExtension()), Qt::CaseInsensitive) == 0) {
+ SFbxTranslator translator(sourceFile);
+ const QDir outputDir = SFileTools::FindUniqueDestDirectory(targetDir, fileStem);
+ const QString fullOutputFile = outputDir.filePath(outputFileName);
+ const SImportResult importResult =
+ CPerformImport::TranslateToImportFile(translator, CFilePath::fromQString(fullOutputFile));
+ bool forceError = QFileInfo(fullOutputFile).isFile() == false;
+ IDocumentEditor::DisplayImportErrors(
+ sourceFile, importResult.m_Error, doc->GetImportFailedHandler(),
+ translator.m_TranslationLog, forceError);
+#endif
+ } else if (extension.compare(QLatin1String("svg"), Qt::CaseInsensitive) == 0) {
+ IDocumentReader &reader(doc->GetDocumentReader());
+ SPathImportTranslator translator(sourceFile, *reader.GetLuaContext(), reader.GetFoundation());
+ const QDir outputDir = SFileTools::FindUniqueDestDirectory(targetDir, fileStem);
+ const QString fullOutputFile = outputDir.filePath(outputFileName);
+ const SImportResult importResult =
+ CPerformImport::TranslateToImportFile(translator, CFilePath::fromQString(fullOutputFile));
+ bool forceError = QFileInfo(fullOutputFile).isFile() == false;
+ IDocumentEditor::DisplayImportErrors(
+ sourceFile, importResult.m_Error,
+ doc->GetImportFailedHandler(),
+ translator.m_TranslationLog, forceError);
+ } else {
+ // Copy the file to target directory
+ // FindAndCopyDestFile will make sure the file name is unique and make sure it is
+ // not read only.
+ bool copyResult = SFileTools::FindAndCopyDestFile(targetDir, sourceFile);
+ ASSERT(copyResult);
+
+ // For effect and custom material files, automatically copy related resources
+ if (CDialogs::IsEffectFileExtension(extension.toLatin1().data())
+ || CDialogs::IsMaterialFileExtension(extension.toLatin1().data())) {
+ std::vector<Q3DStudio::CString> effectFileSourcePaths;
+ doc->GetDocumentReader().ParseSourcePathsOutOfEffectFile(
+ Q3DStudio::CFilePath::GetAbsolutePath(CFilePath::fromQString(sourceFile)),
+ effectFileSourcePaths);
+
+ const QDir fileDir = QFileInfo(sourceFile).dir();
+ const QDir documentDir(doc->GetDocumentDirectory().toQString());
+
+ for (const auto &effectFile : effectFileSourcePaths) {
+ const QString sourcePath = fileDir.filePath(effectFile.toQString());
+ const QString resultPath = documentDir.filePath(effectFile.toQString());
+
+ const QFileInfo resultFileInfo(resultPath);
+ if (!resultFileInfo.exists()) {
+ resultFileInfo.dir().mkpath(".");
+ QFile::copy(sourcePath, resultPath);
+ }
+ }
+ }
+ }
+}
+
+void ProjectFileSystemModel::collapse(int row)
+{
+ Q_ASSERT(row >= 0 && row < m_items.size());
+
+ auto &item = m_items[row];
+ Q_ASSERT(item.expanded == true);
+
+ const int childCount = item.childCount;
+
+ if (childCount > 0) {
+ beginRemoveRows({}, row + 1, row + childCount);
+
+ m_items.erase(std::begin(m_items) + row + 1, std::begin(m_items) + row + 1 + childCount);
+
+ for (auto parent = &item; parent != nullptr; parent = parent->parent)
+ parent->childCount -= childCount;
+
+ endRemoveRows();
+ }
+
+ item.expanded = false;
+ Q_EMIT dataChanged(index(row), index(row));
+}
+
+int ProjectFileSystemModel::modelIndexRow(const QModelIndex &modelIndex) const
+{
+ auto it = std::find_if(
+ std::begin(m_items),
+ std::end(m_items),
+ [&modelIndex](const TreeItem &item)
+ {
+ return item.index == modelIndex;
+ });
+
+ return it != std::end(m_items) ? std::distance(std::begin(m_items), it) : -1;
+}
+
+bool ProjectFileSystemModel::isExpanded(const QModelIndex &modelIndex) const
+{
+ if (modelIndex == m_rootIndex)
+ return true;
+ const int row = modelIndexRow(modelIndex);
+ return row != -1 && m_items.at(row).expanded;
+}
+
+EStudioObjectType ProjectFileSystemModel::getIconType(const QString &path) const
+{
+ Q3DStudio::CFilePath filePath(Q3DStudio::CString::fromQString(path));
+ return Q3DStudio::ImportUtils::GetObjectFileTypeForFile(filePath).m_IconType;
+}
+
+QString ProjectFileSystemModel::getIconName(const QString &path) const
+{
+ QString iconName;
+
+ QFileInfo fileInfo(path);
+ if (fileInfo.isFile()) {
+ EStudioObjectType type = getIconType(path);
+ if (type != OBJTYPE_UNKNOWN)
+ iconName = CStudioObjectTypes::GetNormalIconName(type);
+ else
+ iconName = QStringLiteral("Objects-Layer-Normal.png");
+ } else {
+ iconName = QStringLiteral("Objects-Folder-Normal.png");
+ }
+
+ return iconName;
+}
+
+bool ProjectFileSystemModel::hasVisibleChildren(const QModelIndex &modelIndex) const
+{
+ const QDir dir(modelIndex.data(QFileSystemModel::FilePathRole).toString());
+ if (!dir.exists() || dir.isEmpty())
+ return false;
+
+ const auto fileInfoList = dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot);
+ for (const auto &fileInfo : fileInfoList) {
+ if (fileInfo.isDir() || getIconType(fileInfo.filePath()) != OBJTYPE_UNKNOWN)
+ return true;
+ }
+
+ return false;
+}
+
+bool ProjectFileSystemModel::isVisible(const QModelIndex &modelIndex) const
+{
+ bool result = false;
+
+ if (modelIndex == m_rootIndex) {
+ result = true;
+ } else {
+ QString path = modelIndex.data(QFileSystemModel::FilePathRole).toString();
+ QFileInfo fileInfo(path);
+ if (fileInfo.isFile()) {
+ result = getIconType(path) != OBJTYPE_UNKNOWN;
+ } else {
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+void ProjectFileSystemModel::modelRowsInserted(const QModelIndex &parent, int start, int end)
+{
+ if (!m_rootIndex.isValid())
+ return;
+
+ if (isExpanded(parent)) {
+ showModelChildItems(parent, start, end);
+ } else {
+ if (hasVisibleChildren(parent)) {
+ // show expand arrow
+ const int row = modelIndexRow(parent);
+ Q_EMIT dataChanged(index(row), index(row));
+ }
+ }
+}
+
+void ProjectFileSystemModel::modelRowsRemoved(const QModelIndex &parent, int start, int end)
+{
+ if (!m_rootIndex.isValid())
+ return;
+
+ if (isExpanded(parent)) {
+ for (int i = start; i <= end; ++i) {
+ const int row = modelIndexRow(m_model->index(i, 0, parent));
+
+ if (row != -1) {
+ const auto &item = m_items.at(row);
+
+ beginRemoveRows({}, row, row + item.childCount);
+
+ for (auto parent = item.parent; parent != nullptr; parent = parent->parent)
+ parent->childCount -= 1 + item.childCount;
+
+ m_items.erase(std::begin(m_items) + row, std::begin(m_items) + row + item.childCount + 1);
+
+ endRemoveRows();
+ }
+ }
+ }
+
+ if (!hasVisibleChildren(parent)) {
+ // hide expand arrow
+ const int row = modelIndexRow(parent);
+ m_items[row].expanded = false;
+ Q_EMIT dataChanged(index(row), index(row));
+ }
+}
+
+void ProjectFileSystemModel::modelLayoutChanged()
+{
+ if (!m_rootIndex.isValid())
+ return;
+
+ QSet<QPersistentModelIndex> expandedItems;
+ for (const auto &item : m_items) {
+ if (item.expanded)
+ expandedItems.insert(item.index);
+ }
+
+ const std::function<int(const QModelIndex &, TreeItem *)> insertChildren = [this, &expandedItems, &insertChildren](const QModelIndex &parentIndex, TreeItem *parent)
+ {
+ Q_ASSERT(isVisible(parentIndex));
+
+ const int rowCount = m_model->rowCount(parentIndex);
+ const int depth = parent->depth + 1;
+
+ int childCount = 0;
+
+ for (int i = 0; i < rowCount; ++i) {
+ const auto &childIndex = m_model->index(i, 0, parentIndex);
+ if (isVisible(childIndex)) {
+ const bool expanded = expandedItems.contains(childIndex);
+ m_items.append({ childIndex, depth, expanded, parent, 0 });
+ auto &item = m_items.last();
+ if (expanded) {
+ item.childCount = insertChildren(childIndex, &item);
+ childCount += item.childCount;
+ }
+ ++childCount;
+ }
+ }
+
+ return childCount;
+ };
+
+ const int itemCount = m_items.count();
+
+ m_items.erase(std::begin(m_items) + 1, std::end(m_items));
+ m_items.reserve(itemCount);
+ insertChildren(m_rootIndex, &m_items.first());
+
+ Q_ASSERT(m_items.count() == itemCount);
+
+ Q_EMIT dataChanged(index(0), index(itemCount - 1));
+}
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h
new file mode 100644
index 00000000..c9ef1b27
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TREEVIEWADAPTOR_H
+#define TREEVIEWADAPTOR_H
+
+#include "StudioObjectTypes.h"
+
+#include <QFileSystemModel>
+#include <QAbstractListModel>
+#include <QList>
+#include <QUrl>
+
+class QFileSystemModel;
+
+class ProjectFileSystemModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit ProjectFileSystemModel(QObject *parent = nullptr);
+
+ enum {
+ IsExpandableRole = QFileSystemModel::FilePermissions + 1,
+ IsDraggableRole,
+ IsReferencedRole,
+ DepthRole,
+ ExpandedRole,
+ };
+
+ void setRootPath(const QString &path);
+
+ QHash<int, QByteArray> roleNames() const override;
+ int rowCount(const QModelIndex &parent = {}) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ QMimeData *mimeData(const QModelIndexList &indexes) const override;
+
+ QString filePath(int row) const;
+
+ void updateReferences(bool emitDataChanged);
+
+ Q_INVOKABLE void expand(int row);
+ Q_INVOKABLE void collapse(int row);
+
+ Q_INVOKABLE void dropUrls(const QList<QUrl> &urls, int row);
+ Q_INVOKABLE bool hasValidUrlsForDropping(const QList<QUrl> &urls) const;
+
+Q_SIGNALS:
+ void modelChanged(QAbstractItemModel *model);
+
+private:
+ void setRootIndex(const QModelIndex &rootIndex);
+ void clearModelData();
+ void showModelTopLevelItems();
+ void showModelChildItems(const QModelIndex &parentItem, int start, int end);
+ int modelIndexRow(const QModelIndex &modelIndex) const;
+ bool isExpanded(const QModelIndex &modelIndex) const;
+ QString getIconName(const QString &path) const;
+ EStudioObjectType getIconType(const QString &path) const;
+ bool isVisible(const QModelIndex& modelIndex) const;
+ bool hasVisibleChildren(const QModelIndex &modelIndex) const;
+ void dropUrl(const QDir &targetDir, const QUrl &url) const;
+
+ void modelRowsInserted(const QModelIndex &parent, int start, int end);
+ void modelRowsRemoved(const QModelIndex &parent, int start, int end);
+ void modelRowsMoved(const QModelIndex &parent, int start, int end);
+ void modelLayoutChanged();
+
+ struct TreeItem {
+ QPersistentModelIndex index;
+ int depth;
+ bool expanded;
+ TreeItem *parent;
+ int childCount;
+ };
+
+ QFileSystemModel *m_model = nullptr;
+ QPersistentModelIndex m_rootIndex;
+ QList<TreeItem> m_items;
+ QStringList m_references;
+};
+
+#endif // TREEVIEWADAPTOR_H
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectView.cpp b/src/Authoring/Studio/Palettes/Project/ProjectView.cpp
new file mode 100644
index 00000000..0bdc69a6
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectView.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "ProjectView.h"
+#include "ProjectFileSystemModel.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "Doc.h"
+#include "Literals.h"
+#include "StudioUtils.h"
+#include "ImportUtils.h"
+#include "StudioApp.h"
+#include "StudioClipboard.h"
+#include "StudioPreferences.h"
+#include "UICImport.h"
+#include "Dialogs.h"
+#include "IDocumentEditor.h"
+#include "ProjectContextMenu.h"
+
+#include <QtCore/qprocess.h>
+#include <QtCore/qtimer.h>
+#include <QtGui/qdrag.h>
+#include <QtGui/qdesktopservices.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+ProjectView::ProjectView(QWidget *parent) : QQuickWidget(parent)
+ , m_ProjectModel(new ProjectFileSystemModel(this))
+{
+ const QString theApplicationPath =
+ CUICFile::GetApplicationDirectory().GetAbsolutePath().toQString();
+
+ m_BehaviorDir = CUICFile(
+ Q3DStudio::CString::fromQString(theApplicationPath
+ + QLatin1String("/Content/Behavior Library")));
+ m_EffectDir = CUICFile(
+ Q3DStudio::CString::fromQString(theApplicationPath
+ + QLatin1String("/Content/Effect Library")));
+ m_FontDir = CUICFile(
+ Q3DStudio::CString::fromQString(theApplicationPath
+ + QLatin1String("/Content/Font Library")));
+ m_ImageDir = CUICFile(
+ Q3DStudio::CString::fromQString(theApplicationPath
+ + QLatin1String("/Content/Maps Library")));
+ m_MaterialDir = CUICFile(
+ Q3DStudio::CString::fromQString(theApplicationPath
+ + QLatin1String("/Content/Material Library")));
+ m_ModelDir = CUICFile(
+ Q3DStudio::CString::fromQString(theApplicationPath
+ + QLatin1String("/Content/Models Library")));
+
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ProjectView::initialize);
+
+ auto dispatch = g_StudioApp.GetCore()->GetDispatch();
+ dispatch->AddPresentationChangeListener(this);
+ dispatch->AddDataModelListener(this);
+}
+
+ProjectView::~ProjectView()
+{
+}
+
+QAbstractItemModel *ProjectView::projectModel() const
+{
+ return m_ProjectModel;
+}
+
+QSize ProjectView::sizeHint() const
+{
+ return {500,500};
+}
+
+void ProjectView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+ rootContext()->setContextProperty("_projectView"_L1, this);
+
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Project/ProjectView.qml"_L1));
+}
+
+void ProjectView::effectAction()
+{
+ m_EffectDir.Execute();
+}
+
+void ProjectView::fontAction()
+{
+ m_FontDir.Execute();
+}
+
+void ProjectView::imageAction()
+{
+ m_ImageDir.Execute();
+}
+
+void ProjectView::materialAction()
+{
+ m_MaterialDir.Execute();
+}
+
+void ProjectView::modelAction()
+{
+ m_ModelDir.Execute();
+}
+
+void ProjectView::behaviorAction()
+{
+ m_BehaviorDir.Execute();
+}
+
+void ProjectView::OnNewPresentation()
+{
+ rebuild();
+}
+
+void ProjectView::OnBeginDataModelNotifications()
+{
+}
+
+void ProjectView::OnEndDataModelNotifications()
+{
+ m_ProjectModel->updateReferences(true);
+}
+
+void ProjectView::OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance)
+{
+ Q_UNUSED(inInstance);
+}
+
+void ProjectView::OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance, long inInstanceCount)
+{
+ Q_UNUSED(inInstance);
+ Q_UNUSED(inInstanceCount);
+}
+
+void ProjectView::startDrag(int row)
+{
+ const auto index = m_ProjectModel->index(row);
+
+ QDrag drag(this);
+ drag.setMimeData(m_ProjectModel->mimeData({index}));
+ drag.exec(Qt::CopyAction);
+}
+
+void ProjectView::showInExplorer(int row) const
+{
+ if (row == -1)
+ return;
+ const auto path = m_ProjectModel->filePath(row);
+#if defined(Q_OS_WIN)
+ QProcess::startDetached("explorer", {"/select", path});
+#elif defined(Q_OS_MACOS)
+ QProcess::startDetached("/usr/bin/osascript", {"-e",
+ QStringLiteral("tell application \"Finder\" to reveal POSIX file \"%1\"").arg(path)});
+ QProcess::startDetached("/usr/bin/osascript", {"-e",
+ QStringLiteral("tell application \"Finder\" to activate")});
+#else
+ // we cannot select a file here, because no file browser really supports it...
+ QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(path).absolutePath()));
+#endif
+}
+
+void ProjectView::copyPath(int row) const
+{
+ if (row == -1)
+ return;
+ const auto path = m_ProjectModel->filePath(row);
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ const auto relativePath = doc->GetRelativePathToDoc(
+ Q3DStudio::CFilePath(Q3DStudio::CString::fromQString(path)));
+ CStudioClipboard::CopyTextToClipboard(relativePath.toQString());
+}
+
+void ProjectView::copyFullPath(int row) const
+{
+ if (row == -1)
+ return;
+ const auto path = m_ProjectModel->filePath(row);
+ CStudioClipboard::CopyTextToClipboard(path);
+}
+
+bool ProjectView::isGroup(int row) const
+{
+ if (row == -1)
+ return false;
+ Q3DStudio::CFilePath path(Q3DStudio::CString::fromQString(m_ProjectModel->filePath(row)));
+ return Q3DStudio::ImportUtils::GetObjectFileTypeForFile(path).m_ObjectType == OBJTYPE_GROUP;
+}
+
+void ProjectView::showContextMenu(int x, int y, int index)
+{
+ ProjectContextMenu contextMenu(this, index);
+ contextMenu.exec(mapToGlobal({x, y}));
+}
+
+void ProjectView::refreshImport(int row) const
+{
+ if (row == -1)
+ return;
+ using namespace Q3DStudio;
+ const auto path = m_ProjectModel->filePath(row);
+ UICIMP::ImportPtrOrError importPtr = UICIMP::Import::Load(path.toStdWString().c_str());
+ if (importPtr.m_Value) {
+ const auto destDir = QString::fromWCharArray(importPtr.m_Value->GetDestDir());
+ const auto srcFile = QString::fromWCharArray(importPtr.m_Value->GetSrcFile());
+ const QString fullSrcPath(QDir(destDir).filePath(srcFile));
+ const QFileInfo newFile(g_StudioApp.GetDialogs()->ConfirmRefreshModelFile(fullSrcPath));
+ if (newFile.exists() && newFile.isFile()){
+ const auto doc = g_StudioApp.GetCore()->GetDoc();
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*doc, tr("Refresh Import..."))
+ ->RefreshImport(fullSrcPath, CString::fromQString(newFile.filePath()));
+ }
+ }
+}
+
+void ProjectView::rebuild()
+{
+ const auto theDoc = g_StudioApp.GetCore()->GetDoc();
+ const Q3DStudio::CFilePath thePath(theDoc->GetDocumentPath().GetAbsolutePath());
+ const Q3DStudio::CFilePath theRootDirPath = thePath.GetDirectory();
+
+ m_ProjectModel->setRootPath(theRootDirPath.toQString());
+}
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectView.h b/src/Authoring/Studio/Palettes/Project/ProjectView.h
new file mode 100644
index 00000000..f46aa976
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectView.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PROJECTVIEW_H
+#define PROJECTVIEW_H
+
+#include "DispatchListeners.h"
+#include "UICFile.h"
+
+#include <QQuickWidget>
+#include <QModelIndex>
+
+class ProjectFileSystemModel;
+
+class ProjectView : public QQuickWidget,
+ public CPresentationChangeListener,
+ public IDataModelListener
+
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QAbstractItemModel *projectModel READ projectModel NOTIFY projectChanged FINAL)
+
+public:
+ explicit ProjectView(QWidget *parent = nullptr);
+ ~ProjectView();
+
+ QSize sizeHint() const override;
+
+ QAbstractItemModel *projectModel() const;
+
+ Q_INVOKABLE void effectAction();
+ Q_INVOKABLE void fontAction();
+ Q_INVOKABLE void imageAction();
+ Q_INVOKABLE void materialAction();
+ Q_INVOKABLE void modelAction();
+ Q_INVOKABLE void behaviorAction();
+
+ Q_INVOKABLE void startDrag(int row);
+
+ Q_INVOKABLE void showInExplorer(int row) const;
+ Q_INVOKABLE void copyPath(int row) const;
+ Q_INVOKABLE void copyFullPath(int row) const;
+ Q_INVOKABLE void refreshImport(int row) const;
+
+ Q_INVOKABLE bool isGroup(int row) const;
+ Q_INVOKABLE void showContextMenu(int x, int y, int index);
+
+ // CPresentationChangeListener
+ void OnNewPresentation() override;
+ // IDataModelListener
+ void OnBeginDataModelNotifications() override;
+ void OnEndDataModelNotifications() override;
+ // These are used during drag operations or during operations which
+ // require immediate user feedback. So they are unimplemented, effectively,
+ // we ignore them.
+ void OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance) override;
+ void OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance,
+ long inInstanceCount) override;
+
+Q_SIGNALS:
+ void projectChanged();
+
+private:
+ void initialize();
+ void rebuild();
+
+ ProjectFileSystemModel *m_ProjectModel = nullptr;
+ QColor m_BaseColor = QColor::fromRgb(75, 75, 75);
+ CUICFile m_BehaviorDir{""};
+ CUICFile m_EffectDir{""};
+ CUICFile m_FontDir{""};
+ CUICFile m_ImageDir{""};
+ CUICFile m_MaterialDir{""};
+ CUICFile m_ModelDir{""};
+};
+
+#endif // PROJECTVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectView.qml b/src/Authoring/Studio/Palettes/Project/ProjectView.qml
new file mode 100644
index 00000000..88ff608f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Project/ProjectView.qml
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import "../controls"
+
+Rectangle {
+ id: root
+
+ color: _backgroundColor
+
+ ColumnLayout {
+ anchors.fill: parent
+ spacing: 4
+
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton
+ onClicked: {
+ _projectView.showContextMenu(mouse.x, mouse.y, projectTree.currentIndex);
+ }
+ }
+
+ ListView {
+ id: projectTree
+
+ anchors.fill: parent
+
+ ScrollBar.vertical: ScrollBar {}
+
+ model: _projectView.projectModel
+
+ delegate: Rectangle {
+ id: delegateItem
+
+ width: parent.width
+ height: 20
+ color: index == projectTree.currentIndex ? _selectionColor : "transparent"
+
+ Row {
+ x: _depth*28
+ anchors.verticalCenter: delegateItem.verticalCenter
+
+ Image {
+ source: _resDir + (_expanded ? "arrow_down.png" : "arrow.png")
+ opacity: _isExpandable ? 1 : 0
+
+ MouseArea {
+ visible: _isExpandable
+ anchors.fill: parent
+ onClicked: {
+ if (_expanded)
+ projectTree.model.collapse(index)
+ else
+ projectTree.model.expand(index)
+ delegateMouseArea.clickPending = false
+ }
+ }
+ }
+
+ Image {
+ source: fileIcon
+ }
+
+ StyledLabel {
+ text: fileName
+ color: _isReferenced ? _textColor : _disabledColor
+ leftPadding: 2
+
+ Item {
+ id: dragItem
+
+ visible: _isDraggable
+ anchors.fill: parent
+
+ Drag.active: dragArea.drag.active
+ Drag.hotSpot.x: width / 2
+ Drag.hotSpot.y: height / 2
+ Drag.dragType: Drag.Automatic
+ Drag.supportedActions: Qt.CopyAction
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ drag.target: dragItem
+ }
+
+ Drag.onDragStarted: _projectView.startDrag(index)
+ }
+ }
+ }
+
+ DropArea {
+ id: dropArea
+
+ anchors.fill: parent
+
+ onEntered: {
+ if (drag.hasUrls && projectTree.model.hasValidUrlsForDropping(drag.urls)) {
+ drag.accept(Qt.CopyAction)
+ } else {
+ drag.accepted = false;
+ }
+ }
+
+ onDropped: {
+ if (drop.hasUrls) {
+ projectTree.model.dropUrls(drop.urls, index)
+ }
+ }
+ }
+
+ MouseArea {
+ id: delegateMouseArea
+ property bool clickPending: false
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton|Qt.LeftButton
+ propagateComposedEvents: true
+ onPressed: {
+ projectTree.currentIndex = model.index;
+
+ // Presses must be ignored by this handler in order for dragging to work
+ mouse.accepted = false;
+
+ // Since ignoring presses means we don't get doubleClicked events,
+ // detect doubleclick using custom timer.
+ if (clickPending) {
+ if (_isExpandable) {
+ if (_expanded)
+ projectTree.model.collapse(index);
+ else
+ projectTree.model.expand(index);
+ }
+ clickPending = false;
+ } else {
+ clickPending = true;
+ doubleClickTimer.restart();
+ }
+ }
+ Timer {
+ id: doubleClickTimer
+ repeat: false
+ triggeredOnStart: false
+ interval: 500
+ onTriggered: parent.clickPending = false;
+ }
+ }
+ }
+ }
+ }
+
+ StyledMenuSeparator {}
+
+ RowLayout {
+ width: parent.width
+ Layout.margins: 4
+ Layout.rightMargin: 12
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ StyledToolButton {
+ enabledImage: "Objects-Effect-Normal.png";
+ onClicked: _projectView.effectAction()
+ toolTipText: qsTr("Open Effect Library directory")
+ }
+
+ StyledToolButton {
+ enabledImage: "Objects-Text-Normal.png";
+ onClicked: _projectView.fontAction()
+ toolTipText: qsTr("Open Font Library directory")
+ }
+
+ StyledToolButton {
+ enabledImage: "Objects-Image-Normal.png";
+ onClicked: _projectView.imageAction()
+ toolTipText: qsTr("Open Maps Library directory")
+ }
+
+ StyledToolButton {
+ enabledImage: "Objects-Material-Normal.png";
+ onClicked: _projectView.materialAction()
+ toolTipText: qsTr("Open Material Library directory")
+ }
+
+ StyledToolButton {
+ enabledImage: "Objects-Model-Normal.png";
+ onClicked: _projectView.modelAction()
+ toolTipText: qsTr("Open Models Library directory")
+ }
+
+ StyledToolButton {
+ enabledImage: "Objects-Behavior-Normal.png";
+ onClicked: _projectView.behaviorAction()
+ toolTipText: qsTr("Open Behavior Library directory")
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideContextMenu.cpp b/src/Authoring/Studio/Palettes/Slide/SlideContextMenu.cpp
new file mode 100644
index 00000000..9af46cb1
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideContextMenu.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SlideContextMenu.h"
+#include "SlideView.h"
+
+SlideContextMenu::SlideContextMenu(SlideView *parent, int row, int rowCount, bool master)
+ : QMenu(parent)
+ , m_view(parent)
+ , m_row(row)
+ , m_rowCount(rowCount)
+{
+ QAction *action = new QAction(tr("New Slide"));
+ action->setEnabled(!master);
+ connect(action, &QAction::triggered, this, &SlideContextMenu::handleAddNewSlide);
+ addAction(action);
+
+ action = new QAction(tr("Delete Slide"));
+ action->setEnabled(!master && m_row != -1);
+ connect(action, &QAction::triggered, this, &SlideContextMenu::handleRemoveSlide);
+ addAction(action);
+
+ action = new QAction(tr("Duplicate Slide"));
+ action->setEnabled(!master && m_row != -1);
+ connect(action, &QAction::triggered, this, &SlideContextMenu::handleDuplicateSlide);
+ addAction(action);
+}
+
+SlideContextMenu::~SlideContextMenu()
+{
+}
+
+void SlideContextMenu::handleAddNewSlide()
+{
+ m_view->addNewSlide(m_row == -1 ? m_rowCount : m_row + 1);
+}
+
+void SlideContextMenu::handleRemoveSlide()
+{
+ m_view->removeSlide(m_row);
+}
+
+void SlideContextMenu::handleDuplicateSlide()
+{
+ m_view->duplicateSlide(m_row);
+}
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideContextMenu.h b/src/Authoring/Studio/Palettes/Slide/SlideContextMenu.h
new file mode 100644
index 00000000..bb4bb864
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideContextMenu.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SLIDE_CONTEXT_MENU_H
+#define SLIDE_CONTEXT_MENU_H
+
+#include <QtWidgets/qmenu.h>
+
+class SlideView;
+
+class SlideContextMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ explicit SlideContextMenu(SlideView *parent, int row, int rowCount, bool master);
+ virtual ~SlideContextMenu();
+
+private Q_SLOTS:
+ void handleAddNewSlide();
+ void handleRemoveSlide();
+ void handleDuplicateSlide();
+
+private:
+ SlideView *m_view;
+ int m_row;
+ int m_rowCount;
+};
+#endif // SLIDE_CONTEXT_MENU_H
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp b/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp
new file mode 100644
index 00000000..d2ef842c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SlideModel.h"
+
+#include "CmdActivateSlide.h"
+#include "Core.h"
+#include "Doc.h"
+#include "StudioApp.h"
+
+#include "IDocumentEditor.h"
+
+#include "ClientDataModelBridge.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+
+SlideModel::SlideModel(int slideCount, QObject *parent) : QAbstractListModel(parent)
+ , m_slides(slideCount)
+{
+
+}
+
+QVariant SlideModel::data(const QModelIndex &index, int role) const
+{
+ if (!hasIndex(index.row(), index.column(),index.parent()))
+ return {};
+
+ const auto row = index.row();
+
+ switch (role) {
+ case NameRole:
+ return slideName(m_slides[row]);
+ case SelectedRole:
+ return row == m_selectedRow;
+ }
+
+ return {};
+}
+
+bool SlideModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!hasIndex(index.row(), index.column(),index.parent()))
+ return false;
+
+ auto &slideHandle = m_slides[index.row()];
+
+ switch (role) {
+ case NameRole: {
+ setSlideName(slideHandle, value.toString());
+ Q_EMIT dataChanged(index, index, {role});
+ break;
+ }
+ case HandleRole: {
+ slideHandle = value.value<UICDM::CUICDMSlideHandle>();
+ Q_EMIT dataChanged(index, index, {HandleRole, NameRole});
+ break;
+ }
+ case SelectedRole: {
+ m_selectedRow = value.toBool() ? index.row() : -1;
+
+ if (m_selectedRow != -1) {
+ CCmdActivateSlide *theCmd = new CCmdActivateSlide(GetDoc(), m_slides[m_selectedRow]);
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ }
+
+ Q_EMIT dataChanged(this->index(0, 0), this->index(rowCount() - 1, 0), {role});
+ return true;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+int SlideModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_slides.count();
+}
+
+QHash<int, QByteArray> SlideModel::roleNames() const
+{
+ auto names = QAbstractListModel::roleNames();
+ names.insert(NameRole, "name");
+ names.insert(SelectedRole, "selected");
+
+ return names;
+}
+
+bool SlideModel::insertRows(int row, int count, const QModelIndex &parent)
+{
+ if (row > m_slides.count())
+ return false;
+
+ beginInsertRows(parent, row, row + count - 1);
+ for (int i = 0; i < count; i++)
+ m_slides.insert(row, {});
+ endInsertRows();
+
+ setData(index(row + count - 1), true, SelectedRole);
+ return true;
+}
+
+bool SlideModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (row + count > m_slides.count())
+ return false;
+
+ bool selectionRemoved = false;
+ beginRemoveRows(parent, row, row + count - 1);
+ for (int i = 0; i < count; i++) {
+ if (m_selectedRow == row)
+ selectionRemoved = true;
+ m_slides.removeAt(row);
+ }
+ endRemoveRows();
+
+ auto newSelectedRow = -1;
+ if (selectionRemoved) {
+ if (row > 0)
+ newSelectedRow = row - 1;
+ else
+ newSelectedRow = row + count - 1;
+ } else if (m_selectedRow >= m_slides.count()) {
+ newSelectedRow = m_slides.count() - 1;
+ }
+ if (newSelectedRow != -1)
+ setData(index(newSelectedRow), true, SelectedRole);
+
+ return true;
+}
+
+void SlideModel::duplicateRow(int row)
+{
+ const auto handle = m_slides[row];
+
+ beginInsertRows({}, row, row);
+ m_slides.insert(row + 1, Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(),
+ QObject::tr("Duplicate Slide"))
+ ->DuplicateSlide(handle));
+ endInsertRows();
+ setData(index(row + 1), true, SelectedRole);
+
+ Q_EMIT dataChanged(index(row, 0), index(row + 1, 0), {});
+}
+
+void SlideModel::move(int fromRow, int toRow)
+{
+ if (fromRow == toRow)
+ return;
+
+ auto handle = m_slides[fromRow];
+ // toRow + 1 as DocumentEditor uses 1 based indexes for slides
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Rearrange Slide"))
+ ->RearrangeSlide(handle, toRow + 1);
+
+ if (fromRow > toRow)
+ beginMoveRows({}, fromRow, fromRow, {}, toRow);
+ else
+ beginMoveRows({}, fromRow, fromRow, {}, toRow + 1);
+ m_slides.move(fromRow, toRow);
+ endMoveRows();
+}
+
+void SlideModel::clear()
+{
+ beginResetModel();
+ m_slides.clear();
+ endResetModel();
+}
+
+void SlideModel::addNewSlide(int row)
+{
+ const auto handle = (row < m_slides.size()) ? m_slides[row] : m_slides.last();
+
+ const auto instanceHandle = GetBridge()->GetOwningComponentInstance(handle);
+ UICDM::CUICDMSlideHandle theMasterSlide = GetBridge()->GetComponentSlide(instanceHandle, 0);
+
+ beginInsertRows({}, row, row);
+ m_slides.insert(row, Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(),
+ QObject::tr("Create Slide"))
+ ->AddSlide(theMasterSlide, row + 1));
+ endInsertRows();
+
+ setData(index(row), true, SelectedRole);
+}
+
+void SlideModel::removeSlide(int row)
+{
+ const auto handle = m_slides[row];
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Delete Slide"))->DeleteSlide(handle);
+ removeRows(row, 1);
+}
+
+bool SlideModel::hasSlideWithName(const QString &name) const
+{
+ for (const auto &slide: m_slides) {
+ if (slideName(slide) == name)
+ return true;
+ }
+ return false;
+}
+
+QString SlideModel::slideName(const UICDM::CUICDMSlideHandle &handle) const
+{
+ auto doc = GetDoc();
+ if (!doc->IsValid())
+ return {};
+ const auto instanceHandle = doc->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(handle);
+ return GetBridge()->GetName(instanceHandle).toQString();
+}
+
+void SlideModel::setSlideName(const UICDM::CUICDMSlideHandle &handle, const QString &name)
+{
+ const auto oldName = slideName(handle);
+ if (oldName != name && !name.trimmed().isEmpty()) {
+ using namespace UICDM;
+ CDoc *theDoc = GetDoc();
+ CClientDataModelBridge *theBridge = GetBridge();
+ if (!theBridge)
+ return;
+ const auto instanceHandle = GetDoc()->GetStudioSystem()->
+ GetSlideSystem()->GetSlideInstance(handle);
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Set Slide Name"))
+ ->SetSlideName(instanceHandle, theBridge->GetNameProperty(),
+ Q3DStudio::CString::fromQString(oldName),
+ Q3DStudio::CString::fromQString(name));
+ }
+}
+
+CDoc *SlideModel::GetDoc() const
+{
+ return g_StudioApp.GetCore()->GetDoc();
+}
+
+CClientDataModelBridge *SlideModel::GetBridge() const
+{
+ auto doc = GetDoc();
+ if (!doc->IsValid())
+ return nullptr;
+ return doc->GetStudioSystem()->GetClientDataModelBridge();
+}
+
+
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideModel.h b/src/Authoring/Studio/Palettes/Slide/SlideModel.h
new file mode 100644
index 00000000..659fc548
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideModel.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SLIDEMODEL_H
+#define SLIDEMODEL_H
+
+#include <QAbstractListModel>
+
+#include "UICDMHandles.h"
+
+class CClientDataModelBridge;
+class CDoc;
+
+class SlideModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum Roles {
+ NameRole = Qt::DisplayRole,
+ HandleRole = Qt::UserRole + 1,
+ SelectedRole
+ };
+
+ SlideModel(int slideCount, QObject *parent = nullptr);
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role = Qt::DisplayRole) override;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ bool insertRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) override;
+ bool removeRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) override;
+ void duplicateRow(int row);
+ void move(int fromRow, int toRow);
+
+ void clear();
+ void addNewSlide(int row);
+ void removeSlide(int row);
+
+private:
+ bool hasSlideWithName(const QString &name) const;
+ QString slideName(const UICDM::CUICDMSlideHandle &handle) const;
+ void setSlideName(const UICDM::CUICDMSlideHandle &handle, const QString &name);
+ inline CDoc *GetDoc() const;
+ inline CClientDataModelBridge *GetBridge() const;
+
+ QVector<UICDM::CUICDMSlideHandle> m_slides;
+ int m_selectedRow = -1;
+};
+
+
+#endif // SLIDEMODEL_H
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideView.cpp b/src/Authoring/Studio/Palettes/Slide/SlideView.cpp
new file mode 100644
index 00000000..08b38a2c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideView.cpp
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SlideView.h"
+#include "CColor.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "Doc.h"
+#include "Literals.h"
+#include "StudioPreferences.h"
+#include "SlideModel.h"
+#include "StudioApp.h"
+#include "StudioUtils.h"
+#include "SlideContextMenu.h"
+
+#include "ClientDataModelBridge.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qtimer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+
+SlideView::SlideView(QWidget *parent) : QQuickWidget(parent)
+ , m_MasterSlideModel(new SlideModel(1, this))
+ , m_SlidesModel(new SlideModel(0, this))
+ , m_ActiveRoot(0)
+{
+ g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ m_CurrentModel = m_SlidesModel;
+ QTimer::singleShot(0, this, &SlideView::initialize);
+}
+
+SlideView::~SlideView()
+{
+ clearSlideList();
+ g_StudioApp.GetCore()->GetDispatch()->RemovePresentationChangeListener(this);
+}
+
+bool SlideView::showMasterSlide() const
+{
+ return m_CurrentModel == m_MasterSlideModel;
+}
+
+void SlideView::setShowMasterSlide(bool show)
+{
+ const bool currentIsMaster = m_CurrentModel == m_MasterSlideModel;
+ if (show == currentIsMaster)
+ return;
+
+ if (show)
+ m_CurrentModel = m_MasterSlideModel;
+ else
+ m_CurrentModel = m_SlidesModel;
+
+ // We need to get the first slide in the correct master mode
+ CDoc *theDoc = GetDoc();
+ UICDM::CUICDMInstanceHandle theRoot = theDoc->GetActiveRootInstance();
+ CClientDataModelBridge *theBridge = GetBridge();
+ UICDM::CUICDMSlideHandle theNewActiveSlide =
+ theBridge->GetOrCreateGraphRoot(theRoot); // this will return the master slide
+ UICDM::ISlideSystem *theSlideSystem = theDoc->GetStudioSystem()->GetSlideSystem();
+ if (m_CurrentModel != m_MasterSlideModel) {
+ const auto theFind = m_MasterSlideReturnPointers.find(theNewActiveSlide);
+ size_t theSlideIndex = 1;
+ size_t theNumSlides = theSlideSystem->GetSlideCount(theNewActiveSlide);
+ if (theFind != m_MasterSlideReturnPointers.end() && theFind->second < theNumSlides)
+ theSlideIndex = theFind->second;
+
+ theNewActiveSlide = theSlideSystem->GetSlideByIndex(
+ theNewActiveSlide, theSlideIndex); // activate the first slide
+ } else {
+ int theIndex = theSlideSystem->GetActiveSlideIndex(theNewActiveSlide);
+ m_MasterSlideReturnPointers[theNewActiveSlide] = theIndex;
+ }
+
+ // We have forced a mode change, and so we need to set the current active TC
+ // to be in the correct mode so our slide palette will show the correct information
+ if (theNewActiveSlide.Valid()) {
+ theDoc->NotifyActiveSlideChanged(theNewActiveSlide);
+ }
+
+ Q_EMIT showMasterSlideChanged();
+ Q_EMIT currentModelChanged();
+}
+
+QSize SlideView::sizeHint() const
+{
+ return {150, 200};
+}
+
+void SlideView::deselectAll()
+{
+ g_StudioApp.GetCore()->GetDoc()->DeselectAllItems();
+}
+
+void SlideView::addNewSlide(int row)
+{
+ m_SlidesModel->addNewSlide(row);
+}
+
+void SlideView::removeSlide(int row)
+{
+ m_SlidesModel->removeSlide(row);
+}
+
+void SlideView::duplicateSlide(int row)
+{
+ m_SlidesModel->duplicateRow(row);
+}
+
+void SlideView::moveSlide(int from, int to)
+{
+ m_SlidesModel->move(from, to);
+}
+
+void SlideView::showContextMenu(int x, int y, int row)
+{
+ SlideContextMenu contextMenu(this, row, m_SlidesModel->rowCount(),
+ m_CurrentModel == m_MasterSlideModel);
+ contextMenu.exec(mapToGlobal({x, y}));
+}
+
+void SlideView::OnNewPresentation()
+{
+ // Register callbacks
+ UICDM::IStudioFullSystemSignalProvider *theSignalProvider =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+ m_MasterSlideReturnPointers.clear();
+
+ m_Connections.push_back(theSignalProvider->ConnectActiveSlide(
+ std::bind(&SlideView::OnActiveSlide, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+
+ // KDAB_TODO We most probably don't need to listen to the below signals,
+ // as the functionality is done in the model already. Remove after it is confirmed
+ // it works as desired when the rendering works.
+ m_Connections.push_back(theSignalProvider->ConnectSlideCreated(
+ std::bind(&SlideView::OnNewSlide, this, std::placeholders::_1)));
+ m_Connections.push_back(theSignalProvider->ConnectSlideDeleted(
+ std::bind(&SlideView::OnDeleteSlide, this, std::placeholders::_1)));
+ m_Connections.push_back(theSignalProvider->ConnectSlideRearranged(
+ std::bind(&SlideView::OnSlideRearranged, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+}
+
+void SlideView::OnClosingPresentation()
+{
+ m_Connections.clear();
+ clearSlideList();
+}
+
+void SlideView::OnActiveSlide(const UICDM::CUICDMSlideHandle &inMaster, int inIndex,
+ const UICDM::CUICDMSlideHandle &inSlide)
+{
+ // When the active slide changes, we need to update our button and mode
+ if (inMaster.Valid()) {
+ // if inIndex is 0, it means that we are activating master slide
+ setShowMasterSlide(inIndex == 0);
+ setActiveSlide(inSlide);
+ }
+}
+
+void SlideView::OnNewSlide(const UICDM::CUICDMSlideHandle &inSlide)
+{
+
+}
+
+void SlideView::OnDeleteSlide(const UICDM::CUICDMSlideHandle &inSlide)
+{
+
+}
+
+void SlideView::OnSlideRearranged(const UICDM::CUICDMSlideHandle &inMaster, int inOldIndex, int inNewIndex)
+{
+}
+
+void SlideView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_slideView"_L1, this);
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Slide/SlideView.qml"_L1));
+}
+
+void SlideView::clearSlideList()
+{
+ m_ActiveRoot = 0;
+ m_SlidesModel->clear();
+}
+
+void SlideView::setActiveSlide(const UICDM::CUICDMSlideHandle &inActiveSlideHandle)
+{
+ // Make sure we are in the correct master mode based on the inActiveSlideHandle
+ // If we changed mode, then we need to force a rebuild
+ bool theRebuildFlag = isMaster(inActiveSlideHandle) && (m_CurrentModel != m_MasterSlideModel);
+
+ // Check to see if the incoming slide is a sibling of the current active slide
+ // If it is, then we may be able to update without rebuilding everything
+ if (!theRebuildFlag
+ && m_ActiveRoot == GetBridge()->GetOwningComponentInstance(inActiveSlideHandle)) {
+ // If this is a new active slide, but the same root parent
+ if (m_ActiveSlideHandle != inActiveSlideHandle) {
+ m_ActiveSlideHandle = inActiveSlideHandle;
+ }
+ } else {
+ // We have a new parent or a new slide that makes us rebuild the entire list
+ rebuildSlideList(inActiveSlideHandle);
+ }
+}
+
+void SlideView::rebuildSlideList(const UICDM::CUICDMSlideHandle &inActiveSlideHandle)
+{
+ // Clear out the existing slides
+ clearSlideList();
+
+ // Add new slide controls as required
+ if (inActiveSlideHandle.Valid()) {
+ m_ActiveSlideHandle = inActiveSlideHandle;
+ m_ActiveRoot = GetBridge()->GetOwningComponentInstance(inActiveSlideHandle);
+
+ // Get the Master Slide handle and the slide count
+ UICDM::ISlideSystem *theSlideSystem = GetSlideSystem();
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlide(inActiveSlideHandle);
+
+ // update handle for master slide
+ UICDM::CUICDMSlideHandle theMasterSlideHandle =
+ theSlideSystem->GetSlideByIndex(theMasterSlide, 0);
+ m_MasterSlideModel->setData(m_MasterSlideModel->index(0, 0),
+ QVariant::fromValue(theMasterSlideHandle),
+ SlideModel::HandleRole);
+
+ long theSlideCount = (long)theSlideSystem->GetSlideCount(theMasterSlide);
+
+ // Iterate through, creating the new slide controls
+ m_SlidesModel->clear();
+ m_SlidesModel->insertRows(0, theSlideCount - 1, {});
+ int row = 0;
+ for (long theSlideIndex = 1; theSlideIndex < theSlideCount; ++theSlideIndex) {
+ UICDM::CUICDMSlideHandle theSlideHandle =
+ theSlideSystem->GetSlideByIndex(theMasterSlide, theSlideIndex);
+ auto index = m_SlidesModel->index(row, 0);
+ m_SlidesModel->setData(index,
+ QVariant::fromValue(theSlideHandle),
+ SlideModel::HandleRole);
+ const auto instanceHandle =
+ GetDoc()->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(theSlideHandle);
+ m_SlidesModel->setData(index,
+ GetBridge()->GetName(instanceHandle).toQString(),
+ SlideModel::NameRole);
+ // This slide is the active slide
+ if (theSlideHandle == m_ActiveSlideHandle) {
+ m_SlidesModel->setData(index, true, SlideModel::SelectedRole);
+ }
+ row++;
+ }
+ }
+}
+
+CDoc *SlideView::GetDoc()
+{
+ return g_StudioApp.GetCore()->GetDoc();
+}
+
+CClientDataModelBridge *SlideView::GetBridge()
+{
+ return GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+}
+
+UICDM::ISlideSystem *SlideView::GetSlideSystem()
+{
+ return GetDoc()->GetStudioSystem()->GetSlideSystem();
+}
+
+long SlideView::GetSlideIndex(const UICDM::CUICDMSlideHandle &inSlideHandle)
+{
+ return GetSlideSystem()->GetSlideIndex(inSlideHandle);
+}
+
+bool SlideView::isMaster(const UICDM::CUICDMSlideHandle &inSlideHandle)
+{
+ return (0 == GetSlideIndex(inSlideHandle));
+}
+
+
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideView.h b/src/Authoring/Studio/Palettes/Slide/SlideView.h
new file mode 100644
index 00000000..a4347ddd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideView.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SLIDEVIEW_H
+#define SLIDEVIEW_H
+
+#include <QQuickWidget>
+
+#include "DispatchListeners.h"
+#include "SlideModel.h"
+
+#include "UICDMHandles.h"
+#include "UICDMSignals.h"
+#include <unordered_map>
+class CClientDataModelBridge;
+class CDoc;
+
+namespace UICDM {
+class ISlideSystem;
+}
+
+class SlideView : public QQuickWidget, public CPresentationChangeListener
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractItemModel *currentModel READ currentModel NOTIFY currentModelChanged FINAL)
+ Q_PROPERTY(bool showMasterSlide READ showMasterSlide WRITE setShowMasterSlide NOTIFY showMasterSlideChanged FINAL)
+public:
+ SlideView(QWidget *parent = nullptr);
+ ~SlideView();
+
+ bool showMasterSlide() const;
+ void setShowMasterSlide(bool show);
+ QAbstractItemModel *currentModel() { return m_CurrentModel; }
+ QSize sizeHint() const override;
+
+ Q_INVOKABLE void deselectAll();
+ Q_INVOKABLE void addNewSlide(int row);
+ Q_INVOKABLE void removeSlide(int row);
+ Q_INVOKABLE void duplicateSlide(int row);
+ Q_INVOKABLE void moveSlide(int from, int to);
+ Q_INVOKABLE void showContextMenu(int x, int y, int row);
+
+ // Presentation Change Listener
+ void OnNewPresentation() override;
+ void OnClosingPresentation() override;
+
+Q_SIGNALS:
+ void currentModelChanged();
+ void showMasterSlideChanged();
+
+
+protected:
+ // UICDM callbacks
+ virtual void OnActiveSlide(const UICDM::CUICDMSlideHandle &inMaster, int inIndex,
+ const UICDM::CUICDMSlideHandle &inSlide);
+ virtual void OnNewSlide(const UICDM::CUICDMSlideHandle &inSlide);
+ virtual void OnDeleteSlide(const UICDM::CUICDMSlideHandle &inSlide);
+ virtual void OnSlideRearranged(const UICDM::CUICDMSlideHandle &inMaster, int inOldIndex,
+ int inNewIndex);
+
+private:
+ void initialize();
+ void clearSlideList();
+ void setActiveSlide(const UICDM::CUICDMSlideHandle &inActiveSlideHandle);
+ inline CDoc *GetDoc();
+ inline CClientDataModelBridge *GetBridge();
+ inline UICDM::ISlideSystem *GetSlideSystem();
+ long GetSlideIndex(const UICDM::CUICDMSlideHandle &inSlideHandle);
+ bool isMaster(const UICDM::CUICDMSlideHandle &inSlideHandle);
+ void rebuildSlideList(const UICDM::CUICDMSlideHandle &inActiveSlideHandle);
+
+ SlideModel *m_CurrentModel = nullptr;
+ SlideModel *m_MasterSlideModel = nullptr;
+ SlideModel *m_SlidesModel = nullptr;
+ QColor m_BaseColor = QColor::fromRgb(75, 75, 75);
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>>
+ m_Connections; /// connections to the UICDM
+ typedef std::unordered_map<int, int> TIntIntMap;
+ // We need to remember which slide we were on when we entered the master slide.
+ // Then, when the users leave the master slide we can go back to roughly the same
+ // state.
+ TIntIntMap m_MasterSlideReturnPointers;
+
+ UICDM::CUICDMInstanceHandle m_ActiveRoot; ///< the object containing the slides to be inspected.
+ UICDM::CUICDMSlideHandle m_ActiveSlideHandle; ///< the active slide handle
+};
+
+#endif // SLIDEVIEW_H
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideView.qml b/src/Authoring/Studio/Palettes/Slide/SlideView.qml
new file mode 100644
index 00000000..7bffcad3
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Slide/SlideView.qml
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import "../controls"
+
+Rectangle {
+
+ id: root
+
+ readonly property bool masterSlide: _slideView.showMasterSlide
+
+ color: _backgroundColor
+
+ MouseArea {
+ id: mainMouseArea
+
+ propagateComposedEvents: true
+ anchors.fill: parent
+ acceptedButtons: Qt.AllButtons
+ onClicked: {
+ if (mouse.button === Qt.RightButton) {
+ _slideView.showContextMenu(mouse.x, mouse.y, -1);
+ } else {
+ root.focus = true;
+ //Unselect All element when we click outside slider item in listView.
+ //It worked as it in old version.
+ _slideView.deselectAll();
+ mouse.accepted = false
+ }
+ }
+ }
+
+ Column {
+ anchors {
+ top: parent.top
+ topMargin: 5
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ spacing: 5
+
+ Column {
+ id: masterButtonColumn
+ spacing: -4
+ anchors.horizontalCenter: parent.horizontalCenter
+ Button {
+ id: masterEditButton
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ onClicked: _slideView.showMasterSlide = !_slideView.showMasterSlide
+
+ background: Rectangle {
+ color: "transparent"
+ }
+ contentItem: Image {
+ source: _resDir + "Slide-Master-Active.png"
+ }
+ }
+ StyledLabel {
+ id: masterEditLabel
+ text: _slideView.showMasterSlide ? qsTr("Leave Master") : qsTr("Edit Master")
+ font.pixelSize: _fontSize
+ color: _masterColor
+ verticalAlignment: Text.AlignVCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+
+ StyledMenuSeparator {
+ id: separator
+ leftPadding: 12
+ rightPadding: 12
+ }
+
+ ListView {
+ id: slideList
+
+ ScrollBar.vertical: ScrollBar {}
+
+ width: root.width
+ height: root.height - masterButtonColumn.height
+ - separator.height - parent.spacing * 2 - 10
+ anchors.horizontalCenter: parent.horizontalCenter
+ boundsBehavior: Flickable.StopAtBounds
+ clip: true
+
+ model: _slideView.currentModel
+ spacing: 10
+
+
+ delegate: MouseArea {
+ id: delegateArea
+
+ property int dragIndex
+ property bool held : false
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: delegateItem.height
+ width: parent.width
+
+ acceptedButtons: Qt.RightButton | Qt.LeftButton
+ drag.target: held ? delegateItem : null
+ drag.axis: Drag.YAxis
+
+
+ onPressed: {
+ dragIndex = model.index;
+ if (mouse.x > delegateItem.x && mouse.x < delegateItem.x + delegateItem.width)
+ held = true;
+ }
+ onReleased: held = false
+
+
+ onClicked: {
+ _slideView.deselectAll();
+ if (mouse.button === Qt.LeftButton) {
+ root.focus = true;
+ model.selected = true;
+ }
+ if (mouse.button === Qt.RightButton) {
+ const coords = mapToItem(root, mouse.x, mouse.y);
+ _slideView.showContextMenu(coords.x, coords.y, model.index);
+ }
+ }
+
+ Item {
+ id: delegateItem
+
+ anchors.centerIn: parent
+ height: column.implicitHeight
+ width: 100
+
+ Drag.keys: "application/x-slide"
+ Drag.active: delegateArea.held
+ Drag.hotSpot.x: width / 2
+ Drag.hotSpot.y: height / 2
+ Drag.source: delegateArea
+
+ Column {
+ id: column
+ spacing: 2
+ anchors.fill: parent
+ Image {
+ id: slideImage
+
+ source: {
+ if (masterSlide)
+ return _resDir + "Slide-Master-Active.png"
+ return model.selected ? _resDir + "Slide-Active.png"
+ : _resDir + "Slide-Normal.png";
+ }
+ }
+
+ Item {
+ anchors.horizontalCenter: slideImage.horizontalCenter
+
+ height: childrenRect.height
+ width: childrenRect.width
+ Row {
+ StyledLabel {
+ visible: !masterSlide
+ text: model.index + 1 + ": "
+ }
+
+ TextInput {
+ id: slideName
+
+ readOnly: masterSlide
+ selectByMouse: !readOnly
+ color: _textColor
+ text: model.name
+ font.pixelSize: _fontSize
+
+ onFocusChanged: {
+ if (focus && !readOnly)
+ selectAll();
+ }
+
+ onEditingFinished: {
+ model.name = text;
+ slideName.focus = false;
+ }
+
+ Keys.onEscapePressed: {
+ slideName.undo();
+ slideName.focus = false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DropArea {
+ anchors.fill: parent
+ keys: "application/x-slide"
+ onEntered: {
+ var oldIndex = drag.source.dragIndex
+ var newIndex = model.index
+ _slideView.moveSlide(oldIndex, newIndex)
+ drag.source.dragIndex = newIndex
+ }
+ }
+
+ states: State {
+ when: held
+
+ ParentChange {
+ target: delegateItem
+ parent: slideList
+ }
+
+ PropertyChanges {
+ target: delegateItem
+ anchors.centerIn: null
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.cpp b/src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.cpp
new file mode 100644
index 00000000..48fe8993
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "AreaBoundingRect.h"
+#include "Renderer.h"
+#include "CColor.h"
+
+//=============================================================================
+/**
+ * Draws the rectangle.
+ */
+void CAreaBoundingRect::Draw(CRenderer *inRenderer)
+{
+ CPt theSize = GetSize();
+ inRenderer->PushPen(CColor(89, 120, 223));
+
+ // Removed because alpha doesn't work on Mac
+ // CColor theOverlayColor( 184, 198, 246 );
+ // inRenderer->FillSolidRect( CPt( theSize.x - 1, theSize.y - 1 ) ), theOverlayColor );
+
+ // Draw the rectangle outline
+ if (theSize.y > 1 && theSize.x > 1) {
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theSize.y - 1));
+ inRenderer->LineTo(CPt(theSize.x - 1, theSize.y - 1));
+ inRenderer->LineTo(CPt(theSize.x - 1, 0));
+ inRenderer->LineTo(CPt(0, 0));
+ }
+ inRenderer->PopPen();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.h b/src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.h
new file mode 100644
index 00000000..1ec98c55
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/AreaBoundingRect.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_AREA_BOUNDING_RECT
+#define INCLUDED_AREA_BOUNDING_RECT 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "OverlayControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+class CAreaBoundingRect : public COverlayControl
+{
+public:
+ virtual ~CAreaBoundingRect(){}
+ void Draw(CRenderer *inRenderer) override;
+
+protected:
+};
+#endif // INCLUDED_AREA_BOUNDING_RECT
diff --git a/src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.cpp b/src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.cpp
new file mode 100644
index 00000000..c0541fac
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "AssetTimelineKeyframe.h"
+#include "StateTimebarlessRow.h"
+#include "Renderer.h"
+#include "MasterP.h"
+#include "StateRow.h"
+#include "KeyframeContextMenu.h"
+#include "HotKeys.h"
+#include "ResourceCache.h"
+#include "ITimelineControl.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "StudioUtils.h"
+#include "TimeEditDlg.h"
+
+CAssetTimelineKeyframe::CAssetTimelineKeyframe(CStateTimebarlessRow *inParentRow,
+ double inTimeRatio)
+ : m_Selected(false)
+ , m_ParentRow(inParentRow)
+ , m_IsMouseDown(false)
+ , m_IsDragging(false)
+ , m_TimeRatio(inTimeRatio)
+{
+ CResourceCache *theCache = CResourceCache::GetInstance();
+ m_Icon = theCache->GetBitmap("Keyframe-Master-Normal.png");
+ m_DisabledIcon = theCache->GetBitmap("Keyframe-Master-Disabled.png");
+ m_SelectedIcon = theCache->GetBitmap("Keyframe-Master-Selected.png");
+ m_DynamicIcon = theCache->GetBitmap("Keyframe-MasterDynamic-Normal.png");
+ m_DynamicSelectedIcon = theCache->GetBitmap("Keyframe-MasterDynamic-Selected.png");
+
+ m_RightIcon = theCache->GetBitmap("Keyframe-MasterRight-Normal.png");
+ m_RightDisabledIcon = theCache->GetBitmap("Keyframe-MasterRight-disabled.png");
+ m_RightSelectedIcon = theCache->GetBitmap("Keyframe-MasterRight-Selected.png");
+ m_RightDynamicIcon = theCache->GetBitmap("Keyframe-MasterRightDynamic-Normal.png");
+ m_RightDynamicSelectedIcon = theCache->GetBitmap("Keyframe-MasterRightDynamic-Selected.png");
+
+ m_LeftIcon = theCache->GetBitmap("Keyframe-MasterLeft-Normal.png");
+ m_LeftDisabledIcon = theCache->GetBitmap("Keyframe-MasterLeft-disabled.png");
+ m_LeftSelectedIcon = theCache->GetBitmap("Keyframe-MasterLeft-Selected.png");
+ m_LeftDynamicIcon = theCache->GetBitmap("Keyframe-MasterLeftDynamic-Normal.png");
+ m_LeftDynamicSelectedIcon = theCache->GetBitmap("Keyframe-MasterLeftDynamic-Selected.png");
+
+ m_RectOverHandled = false;
+ m_PreviousSelectState = false;
+}
+
+CAssetTimelineKeyframe::~CAssetTimelineKeyframe()
+{
+}
+
+//=============================================================================
+/**
+ * SetRectOverHandled: Sets if mouse rectangle has been handled
+ * param@ inState indicates if the rectangle over has been handled.
+ * return@ NONE
+ */
+
+void CAssetTimelineKeyframe::SetRectOverHandled(bool inState)
+{
+ m_RectOverHandled = inState;
+}
+
+//=============================================================================
+/**
+ * GetRectOverHandled: GetRectOverHandled
+ * param@ NONE
+ * return@ m_RectOverHandled, which indicates if the rectangle over has been handled
+ */
+bool CAssetTimelineKeyframe::GetRectOverHandled()
+{
+ return m_RectOverHandled;
+}
+
+//=============================================================================
+/**
+ * SetPreviousSelectState: Sets if the current keyframe was previously selected
+ * param@ inState is used to set m_PreviousSelectState.
+ * return@ NONE
+ */
+void CAssetTimelineKeyframe::SetPreviousSelectState(bool inState)
+{
+ m_PreviousSelectState = inState;
+}
+
+//=============================================================================
+/**
+ * GetPreviousSelectState: Returns the keyframe's previous select state
+ * param@ NONE
+ * return@ m_PreviousSelectState that stores the select state for the keyframe
+ */
+bool CAssetTimelineKeyframe::GetPreviousSelectState()
+{
+ return m_PreviousSelectState;
+}
+
+//=============================================================================
+/**
+* Updates the ToolTip and moves it to the correct place on screen.
+* @param inPoint the point that the tooltip is supposed to be placed.
+*/
+void CAssetTimelineKeyframe::RefreshToolTip(CPt inPoint)
+{
+ Q3DStudio::CString theCommentText;
+ CStateRow *theStateRow = m_ParentRow->GetStateRow();
+ CRct theTimelineBounds(theStateRow->GetTopControl()->GetBounds());
+
+ // format label
+ theCommentText = " " + ::FormatTimeString(GetTime());
+
+ inPoint.y = GetPosition().y - GetSize().y;
+ inPoint.x = GetSize().x / 2;
+ ShowMoveableWindow(inPoint, theCommentText, theTimelineBounds);
+}
+
+//=============================================================================
+/**
+ * Gets the correct image and draws
+ */
+void CAssetTimelineKeyframe::Draw(CRenderer *inRenderer)
+{
+ inRenderer->DrawBitmap(CPt(0, 0), GetImage());
+}
+
+//=============================================================================
+/**
+ * Gets the name of the current bitmap depending on the state of the button,
+ * postion of the mouse, etc. Returns name of the image for the up state by
+ * default.
+ * @return name of the image representing current state of the button
+ */
+QPixmap CAssetTimelineKeyframe::GetImage() const
+{
+ QPixmap theImage = m_Icon;
+ long theStartTime = m_ParentRow->GetStateRow()->GetStartTime();
+ long theEndTime = m_ParentRow->GetStateRow()->GetEndTime();
+
+ if (theStartTime == m_Time) {
+ theImage = m_LeftIcon;
+ if (!IsEnabled())
+ theImage = m_LeftDisabledIcon;
+ else if (m_IsDynamic) {
+ if (m_Selected)
+ return m_LeftDynamicSelectedIcon;
+ else
+ return m_LeftDynamicIcon;
+ } else if (m_Selected)
+ theImage = m_LeftSelectedIcon;
+ } else if (theEndTime == m_Time) {
+ theImage = m_RightIcon;
+ if (!IsEnabled())
+ theImage = m_RightDisabledIcon;
+ else if (m_IsDynamic) {
+ if (m_Selected)
+ return m_RightDynamicSelectedIcon;
+ else
+ return m_RightDynamicIcon;
+ } else if (m_Selected)
+ theImage = m_RightSelectedIcon;
+ } else {
+ if (!IsEnabled())
+ theImage = m_DisabledIcon;
+ else if (m_IsDynamic) {
+ if (m_Selected)
+ return m_DynamicSelectedIcon;
+ else
+ return m_DynamicIcon;
+ } else if (m_Selected)
+ theImage = m_SelectedIcon;
+ }
+ return theImage;
+}
+
+//=============================================================================
+/**
+ * @return true if the mouse is over the keyframe
+ * @param inPoint the point where the mouse is
+ */
+bool CAssetTimelineKeyframe::HitTest(const CPt &inPoint) const
+{
+ bool theRetVal = false;
+ // If not over the control then don't bother with specific checks
+ if (CControl::HitTest(inPoint)) {
+ // If the key is at the beginning or end of the timebar then calculate the test differently
+ long theStartTime = m_ParentRow->GetStateRow()->GetStartTime();
+ long theEndTime = m_ParentRow->GetStateRow()->GetEndTime();
+ CPt thePoint = inPoint - GetPosition();
+ if (theStartTime == m_Time)
+ theRetVal = (thePoint.x > 7);
+ else if (theEndTime == m_Time)
+ theRetVal = (thePoint.x < 9);
+ else {
+ if (m_Selected)
+ theRetVal = (thePoint.x > 1 && thePoint.x < 15);
+ else
+ theRetVal = (thePoint.x > 3 && thePoint.x < 13);
+ }
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Handler for left mouse down events.
+ * @param inPoint the point where the mouse is
+ * @param inFlags indicates modifier keys that were down at time of the event
+ */
+bool CAssetTimelineKeyframe::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Store the mouse down location in screen coordinates so that we can check the dragging buffer
+ // in OnMouseMove
+ m_MouseDownLoc = inPoint;
+
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ bool theClearPreviouslySelectedKeys = false;
+ bool theSelectedFlag = false;
+ // If the control key is down then we change state, otherwise
+ if (!((CHotKeys::MODIFIER_CONTROL & inFlags) == CHotKeys::MODIFIER_CONTROL)) {
+ theClearPreviouslySelectedKeys = !m_Selected; // clear if not multi-selecting
+ theSelectedFlag = true;
+ } else {
+ theSelectedFlag = !m_Selected;
+ }
+ m_ParentRow->OnKeySelected(m_Time, theSelectedFlag, theClearPreviouslySelectedKeys);
+ m_Selected = theSelectedFlag; // set this after OnKeySelected, because the function may
+ // clear out all previously selected keys including this
+ // TODO : sk - 1-1 mapping of seemingly useless calls in
+ // CPropertyTimelineKeyframe::OnMouseDown, see my comments there.
+ // m_StudioDoc->UpdateClientScene( true );
+ // m_ParentRow->GetStateRow( )->GetState( )->FireAnimatedPropertiesChanged( );
+
+ m_IsMouseDown = true;
+ CStateRow *theStateRow = m_ParentRow->GetStateRow();
+ long theStartTime = theStateRow->GetStartTime();
+ long theEndTime = theStateRow->GetEndTime();
+ m_Snapper.SetStartEndTime(theStartTime, theEndTime);
+ m_Snapper.SetSource(this);
+ m_Snapper.SetKeyFrameClicked(true);
+ m_Snapper.SetSnappingSelectedKeyframes(false);
+
+ theStateRow->GetTimebar()->GetSnappingListProvider().PopulateSnappingList(&m_Snapper);
+ m_Snapper.BeginDrag(inPoint.x);
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handler for right mouse down events.
+ * @param inPoint the point where the mouse is
+ * @param inFlags indicates modifier keys that were down at time of the event
+ */
+bool CAssetTimelineKeyframe::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseRDown(inPoint, inFlags)) {
+ if (!m_Selected) {
+ m_Selected = true;
+ m_ParentRow->OnKeySelected(m_Time, m_Selected, true);
+ }
+ ITimelineItemProperty *iProperty = nullptr;
+ if (GetTimelineItemBinding()->GetPropertyCount() > 0) {
+ iProperty = GetTimelineItemBinding()->GetProperty(0);
+ }
+ CKeyframeContextMenu theMenu(GetTimelineItemBinding()->GetKeyframesManager(), iProperty);
+ theMenu.SetTime(GetTime());
+ DoPopup(&theMenu, inPoint);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * called when this key is selected
+ *
+ * @param inState the state this key is selected to
+ */
+void CAssetTimelineKeyframe::Select(bool inState)
+{
+ if (m_Selected != inState) {
+ m_Selected = inState;
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * handler for the mouse up event
+ * @param inFlags the state of things when the mouse button was released
+ * @param inPoint the point where the mouse is
+ */
+void CAssetTimelineKeyframe::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+ m_IsMouseDown = false;
+ m_IsDragging = false;
+
+ GetTimelineItemBinding()->CommitChangedKeyframes();
+
+ HideMoveableWindow();
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * handler for the onMouse Move event. Offsets selected keys.
+ * Displays the StudioToolTip for the keyframe, showing the time it is at.
+ *
+ * @param inFlags the state of things when the mouse was moved
+ * @param inPoint the point where the mouse is
+ */
+void CAssetTimelineKeyframe::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+ UICPROFILE(OnMouseMove);
+ // If the mouse is down and this is slected, then offst the keys
+ if (m_IsMouseDown && m_Selected) {
+ // If we are not yet dragging the keyframe
+ if (!m_IsDragging) {
+ long theDiff = ::abs(inPoint.x) - m_MouseDownLoc.x;
+ // Figure out if the mouse has moved far enough to start the drag, and readjust the drag
+ // postion on the snapper
+ m_IsDragging = (::abs(theDiff) > DRAGBUFFER);
+ if (m_IsDragging && (::abs(theDiff) - DRAGBUFFER) > 2) {
+ m_Snapper.BeginDrag(m_MouseDownLoc.x);
+ } else
+ m_Snapper.BeginDrag(inPoint.x);
+ }
+
+ // If we are now dragging, procceed as normal
+ if (m_IsDragging) {
+ long theNewTime = m_Snapper.ProcessDrag(m_Time, inPoint.x, inFlags);
+ long theDiffTime = theNewTime - m_Time;
+
+ if (theDiffTime != 0) {
+ // theDiffTime can get updated if its invalid.
+ theDiffTime = GetTimelineItemBinding()->OffsetSelectedKeyframes(theDiffTime);
+ // Set this key's time so it won't be recalced in Refresh keyframes in the row
+ SetTime(m_Time + theDiffTime);
+
+ Invalidate();
+ }
+ }
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the time ratio
+ *
+ * @param inTimeRatio the new ratio
+ */
+void CAssetTimelineKeyframe::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+ CPt theSize = GetSize();
+ SetPosition(::TimeToPos(GetTime(), m_TimeRatio) - (theSize.x / 2), 0);
+}
+
+//=============================================================================
+/**
+ * Pass the double click notification on to the row and have it process it.
+ * The row will do object-specific actions on doubleclicks.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ * @return true stating that the event was processed.
+ */
+bool CAssetTimelineKeyframe::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+
+ GetTimelineItemBinding()->OnEditKeyframeTime(m_Time, ASSETKEYFRAME);
+ m_IsMouseDown = false;
+ m_IsDragging = false;
+ return true;
+}
+
+//=============================================================================
+/**
+ * @return true if selected
+ */
+bool CAssetTimelineKeyframe::IsSelected()
+{
+ return m_Selected;
+}
+
+void CAssetTimelineKeyframe::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+}
+
+//=============================================================================
+/**
+ *
+ */
+ITimelineItemBinding *CAssetTimelineKeyframe::GetTimelineItemBinding() const
+{
+ return m_ParentRow->GetStateRow()->GetTimelineItemBinding();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.h b/src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.h
new file mode 100644
index 00000000..54a8b501
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/AssetTimelineKeyframe.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_ASSET_TIMELINE_KEYFRAME
+#define INCLUDED_ASSET_TIMELINE_KEYFRAME 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "TimelineKeyframe.h"
+#include "Snapper.h"
+
+#include <QPixmap>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class CStateTimebarlessRow;
+class ITimelineItemBinding;
+
+class CAssetTimelineKeyframe : public CControl, public CTimelineKeyframe
+{
+
+public:
+ CAssetTimelineKeyframe(CStateTimebarlessRow *inParentRow, double inTimeRatio);
+ ~CAssetTimelineKeyframe();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void Select(bool inState);
+ void SetTimeRatio(double inTimeRatio);
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool IsSelected();
+ void SetSize(CPt inSize) override;
+ bool HitTest(const CPt &inPoint) const override;
+ void SetRectOverHandled(bool inState);
+ bool GetRectOverHandled();
+ void SetPreviousSelectState(bool inState);
+ bool GetPreviousSelectState();
+
+protected:
+ void RefreshToolTip(CPt inPoint);
+ QPixmap GetImage() const;
+ ITimelineItemBinding *GetTimelineItemBinding() const;
+
+protected:
+ bool m_RectOverHandled; ///< Indicates if the mouse rect over has been handled.
+ bool m_PreviousSelectState; ///< Stores the previous select state for the keyframe.
+ bool m_Selected;
+ CStateTimebarlessRow *m_ParentRow;
+ bool m_IsMouseDown;
+ CPt m_MouseDownLoc; ///< Location of the mouse after an OnMouseDownEvent, in client coordinates
+ bool m_IsDragging; ///< Indicates whether or not the keyframe is currently being dragged,
+ ///determined by the pixel buffer
+ double m_TimeRatio;
+
+ CSnapper m_Snapper;
+ QPixmap m_Icon;
+ QPixmap m_DisabledIcon;
+ QPixmap m_SelectedIcon;
+ QPixmap m_DynamicIcon;
+ QPixmap m_DynamicSelectedIcon;
+ QPixmap m_LeftIcon;
+ QPixmap m_LeftDisabledIcon;
+ QPixmap m_LeftSelectedIcon;
+ QPixmap m_LeftDynamicIcon;
+ QPixmap m_LeftDynamicSelectedIcon;
+ QPixmap m_RightIcon;
+ QPixmap m_RightDisabledIcon;
+ QPixmap m_RightSelectedIcon;
+ QPixmap m_RightDynamicIcon;
+ QPixmap m_RightDynamicSelectedIcon;
+};
+
+#endif // INCLUDED_ASSET_TIMELINE_KEYFRAME
diff --git a/src/Authoring/Studio/Palettes/Timeline/BaseStateRow.cpp b/src/Authoring/Studio/Palettes/Timeline/BaseStateRow.cpp
new file mode 100644
index 00000000..7960ed96
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BaseStateRow.cpp
@@ -0,0 +1,1139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "BaseStateRow.h"
+#include "PropertyRow.h"
+#include "BaseTimelineTreeControl.h"
+#include "ToggleControl.h"
+#include "BaseTimebarlessRow.h"
+#include "ColorControl.h"
+#include "StateRowFactory.h"
+#include "TimelineTimelineLayout.h"
+#include "ComponentContextMenu.h"
+#include "ITimelineControl.h"
+#include "ResourceCache.h"
+#include "StudioUtils.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "Bindings/ITimelineTimebar.h"
+
+const long CBaseStateRow::DEFAULT_TOGGLE_LENGTH = 57;
+
+CBaseStateRow::CBaseStateRow()
+ : m_TimeRatio(0.0f)
+ , m_TreeList(true)// true to align the children in the timeline.
+ , m_TreeControl(nullptr)
+ , m_ColorControl(nullptr)
+ , m_ToggleControl(nullptr)
+ , m_TimebarControl(nullptr)
+ , m_Loaded(false)
+ , m_IsExpanded(false)
+ , m_Highlighted(false)
+ , m_Dirty(false)
+ , m_Selected(false)
+ , m_TimelineItemBinding(nullptr)
+ , m_ActiveStart(0)
+ , m_ActiveEnd(0)
+{
+}
+
+CBaseStateRow::~CBaseStateRow()
+{
+ delete m_TreeControl;
+ delete m_ColorControl;
+ delete m_ToggleControl;
+ delete m_TimebarControl;
+
+ // Go through all the state rows and delete them, this control owns all child controls.
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos)
+ (*thePos)->Dispose();
+
+ // Go through all the properties and delete them, this control owns all child controls.
+ TPropertyRowList::iterator thePropertyPos = m_PropertyRows.begin();
+ for (; thePropertyPos != m_PropertyRows.end(); ++thePropertyPos) {
+ CPropertyRow *theRow = (*thePropertyPos);
+ delete theRow;
+ }
+}
+
+void CBaseStateRow::Initialize(ITimelineItemBinding *inTimelineItemBinding)
+{
+ m_Dirty = true;
+ ASSERT(inTimelineItemBinding);
+ m_TimelineItemBinding = inTimelineItemBinding;
+
+ m_TreeControl = new CBaseTimelineTreeControl(this, GetTimelineItem()->IsMaster());
+ m_ColorControl = new CColorControl(this);
+ m_ToggleControl = CreateToggleControl();
+ m_TimebarControl = CreateTimebarRow();
+
+ long theTimebarHeight = CStudioPreferences::GetRowSize();
+ m_TreeControl->SetSize(CPt(500, theTimebarHeight));
+ m_ColorControl->SetAbsoluteSize(CPt(theTimebarHeight, theTimebarHeight));
+ m_ToggleControl->SetAbsoluteSize(CPt(DEFAULT_TOGGLE_LENGTH, theTimebarHeight));
+ m_TimebarControl->SetSize(CPt(800, theTimebarHeight));
+
+ ::CColor theColor = GetTimebarBackgroundColor(GetObjectType());
+ m_TreeControl->SetBackgroundColor(theColor);
+ m_ToggleControl->SetBackgroundColor(theColor);
+ m_TimebarControl->SetBackgroundColor(theColor);
+
+ m_ColorList.AddChild(m_ColorControl);
+ m_TreeList.AddChild(m_TreeControl);
+ m_ToggleList.AddChild(m_ToggleControl);
+ m_TimebarList.AddChild(m_TimebarControl);
+
+ // sk - I think setting controls' names is only useful for debugging.
+ /*Q3DStudio::CString theAssetName( m_Asset->GetName( ) );
+ m_TreeControl->SetName( theAssetName + "TreeControl" );
+ m_TreeList.SetName( theAssetName + "TreeList" );
+ m_ColorControl->SetName( theAssetName + "ColorControl" );
+ m_ColorList.SetName( theAssetName + "ColorList" );
+ m_ToggleControl->SetName( theAssetName + "ToggleControl" );
+ m_ToggleList.SetName( theAssetName + "ToggleList" );
+ m_TimebarControl->SetName( theAssetName + "TimebarControl" );
+ m_TimebarList.SetName( theAssetName + "TimebarList" );*/
+
+ // Bind after all the UI is setup.
+ m_TimelineItemBinding->Bind(this); // see Dispose where it properly unbinds.
+
+ ClearDirty();
+}
+
+//=============================================================================
+/**
+ * Expand this node of the tree control.
+ * This will display all children the fit the filter.
+ */
+void CBaseStateRow::Expand(bool inExpandAll /*= false*/, bool inExpandUp)
+{
+ if (!m_IsExpanded) {
+ m_Filter.SetExpanded(true);
+
+ // Expand/Collapse is done by adding and removing the children, add all the
+ // properties first so they are at the top of the list.
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow)
+ thePropRow->Filter(m_Filter, false);
+ }
+ // Add all the State rows after the properties.
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ CStateRow *theRow = (*thePos);
+ theRow->Filter(m_Filter, false);
+ }
+
+ m_TreeControl->SetExpanded(true);
+ m_IsExpanded = true;
+ m_ColorControl->UpdateIconStatus();
+ }
+
+ if (inExpandAll) {
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos)
+ (*thePos)->Expand(inExpandAll);
+ }
+
+ if (inExpandUp && m_ParentRow)
+ m_ParentRow->Expand(false, inExpandUp);
+}
+
+//=============================================================================
+/**
+ * Collapse this node of the tree control.
+ * This will hide all children of this control.
+ */
+void CBaseStateRow::Collapse(bool inCollapseAll /* = false */)
+{
+ if (m_IsExpanded) {
+ CFilter theFilter = m_Filter;
+ theFilter.SetExpanded(false);
+
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow)
+ thePropRow->Filter(theFilter);
+ }
+
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ CStateRow *theRow = (*thePos);
+ theRow->Filter(theFilter);
+ }
+
+ m_TimelineItemBinding->OnCollapsed();
+
+ m_TreeControl->SetExpanded(false);
+ m_IsExpanded = false;
+ m_ColorControl->UpdateIconStatus();
+ }
+
+ if (inCollapseAll) {
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ (*thePos)->Collapse(inCollapseAll);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Toggle the expansion state of this control.
+ * This will expand the control if it is closed, or collapse it if it is
+ * open.
+ */
+void CBaseStateRow::ToggleExpansion(CToggleButton *, CButtonControl::EButtonState inButtonState)
+{
+ if (inButtonState == CButtonControl::EBUTTONSTATE_UP)
+ Collapse();
+ else
+ Expand();
+}
+
+//=============================================================================
+/**
+ * Shows or hides rows for all children, based on the filter.
+ * @param inFilter Object specifying the filters currently applied to the timeline.
+ * @param inFilterChildren true if the filter should go recursively to children.
+ */
+void CBaseStateRow::Filter(const CFilter &inFilter, bool inFilterChildren /*= true*/)
+{
+ m_Filter = inFilter;
+
+ // For each child object
+ if (inFilterChildren) {
+ CFilter theChildFilter = inFilter;
+ theChildFilter.SetExpanded(m_IsExpanded);
+
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ // Apply the filter
+ CStateRow *theRow = (*thePos);
+ theRow->Filter(theChildFilter);
+ }
+ }
+
+ // This flag determines whether or not the controls on this row should be shown, based on the
+ // filter
+ bool theVisibleFlag = PerformFilter(m_Filter);
+
+ m_IsViewable = theVisibleFlag;
+
+ theVisibleFlag &= inFilter.IsExpanded();
+
+ // Show or hide the controls on this row before we iterate through the properties
+ m_ColorList.SetVisible(theVisibleFlag);
+ m_TreeList.SetVisible(theVisibleFlag);
+ m_ToggleList.SetVisible(theVisibleFlag);
+ m_TimebarList.SetVisible(theVisibleFlag);
+
+ if (inFilterChildren) {
+ CFilter theChildFilter = inFilter;
+ theChildFilter.SetExpanded(m_IsExpanded);
+
+ // For each property on this object
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ // Apply the filter
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow)
+ thePropRow->Filter(theChildFilter);
+ }
+ }
+
+ m_TreeControl->SetToggleVisible(this->HasVisibleChildren());
+}
+
+//=============================================================================
+/**
+ * Get the color control for this row.
+ * @return the color control for this row.
+ */
+CControl *CBaseStateRow::GetColorControl()
+{
+ return &m_ColorList;
+}
+
+//=============================================================================
+/**
+ * Get the tree control for this row.
+ * @return the tree control for this row.
+ */
+CControl *CBaseStateRow::GetTreeControl()
+{
+ return &m_TreeList;
+}
+
+//=============================================================================
+/**
+ * Get the toggle control for this row.
+ * @return the toggle control for this row.
+ */
+CControl *CBaseStateRow::GetToggleControl()
+{
+ return &m_ToggleList;
+}
+
+//=============================================================================
+/**
+ * Get the timebar control for this row.
+ * @return the timebar control for this row.
+ */
+CControl *CBaseStateRow::GetTimebarControl()
+{
+ return &m_TimebarList;
+}
+
+//=============================================================================
+/**
+ * Remove a row from this control.
+ * @param inState the state of the row to be removed.
+ */
+void CBaseStateRow::RemoveRow(CStateRow *inRow)
+{
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ CStateRow *theRow = (*thePos);
+ if (theRow == inRow) {
+ DeleteRow(theRow);
+ m_StateRows.erase(thePos);
+ break;
+ }
+ }
+ m_TreeControl->SetToggleVisible(this->HasVisibleChildren());
+}
+
+//=============================================================================
+/**
+ * Helper function to remove all controls of this property row and dispose of it.
+ */
+void CBaseStateRow::DeletePropertyRow(CPropertyRow *inPropertyRow)
+{
+ if (!inPropertyRow)
+ return;
+
+ m_ColorList.RemoveChild(inPropertyRow->GetColorControl());
+ m_TreeList.RemoveChild(inPropertyRow->GetTreeControl());
+ m_ToggleList.RemoveChild(inPropertyRow->GetToggleControl());
+ m_TimebarList.RemoveChild(inPropertyRow->GetTimebarControl());
+ delete inPropertyRow;
+}
+
+//=============================================================================
+/**
+ * By default, we don't show shy/eye/lock toggles
+ */
+CBlankToggleControl *CBaseStateRow::CreateToggleControl()
+{
+ return new CBlankToggleControl(this);
+}
+
+//=============================================================================
+/**
+ * Get the StateRow that is representing this child timeline item.
+ * @param inTimelineItem child timeline item
+ * @return the StateRow for inState.
+ */
+CStateRow *CBaseStateRow::GetRow(ITimelineItem *inTimelineItem)
+{
+ if (inTimelineItem) {
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ if ((*thePos)->GetTimelineItem() == inTimelineItem)
+ return (*thePos);
+ }
+ }
+ return nullptr;
+}
+
+//=============================================================================
+/**
+ * Called when a row is to be completely removed from the UI
+ */
+void CBaseStateRow::DeleteRow(CStateRow *inRow)
+{
+ m_ColorList.RemoveChild(inRow->GetColorControl());
+ m_TreeList.RemoveChild(inRow->GetTreeControl());
+ m_ToggleList.RemoveChild(inRow->GetToggleControl());
+ m_TimebarList.RemoveChild(inRow->GetTimebarControl());
+
+ inRow->Dispose();
+}
+
+//=============================================================================
+/**
+ * Call from the child controls that the mouse is over one of the children.
+ * This is used to highlight the entire row on mouse over.
+ */
+void CBaseStateRow::OnMouseOver()
+{
+ if (!m_Highlighted) {
+ try {
+ // TODO: Added the try/catch block to prevent crashing when the instance handle is not
+ // found
+ // this will happen sometimes when delete the object from the timeline
+ // need to really fix this at the root.
+ ::CColor theColor = GetTimebarHighlightBackgroundColor(GetObjectType());
+ m_TreeControl->SetBackgroundColor(theColor);
+ m_ToggleControl->SetBackgroundColor(theColor);
+ m_TimebarControl->SetBackgroundColor(theColor);
+
+ m_Highlighted = true;
+ } catch (...) {
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Call from the child controls that the mouse is no longer over one of the children.
+ * This is used to highlight the entire row on mouse over.
+ */
+void CBaseStateRow::OnMouseOut()
+{
+ if (m_Highlighted) {
+ try {
+ // TODO: Added the try/catch block to prevent crashing when the instance handle is not
+ // found
+ // this will happen sometimes when delete the object from the timeline
+ // need to really fix this at the root.
+ ::CColor theColor = GetTimebarBackgroundColor(GetObjectType());
+ m_TreeControl->SetBackgroundColor(theColor);
+ m_ToggleControl->SetBackgroundColor(theColor);
+ m_TimebarControl->SetBackgroundColor(theColor);
+
+ m_Highlighted = false;
+ } catch (...) {
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Tells this that the Asset data has changed and it needs to be updated.
+ * Someone should call ClearDirty afterwards.
+ */
+void CBaseStateRow::OnDirty()
+{
+ m_Dirty = true;
+}
+
+void CBaseStateRow::ClearDirty()
+{
+ if (m_Dirty) {
+ m_TreeControl->Refresh(m_TimelineItemBinding->GetTimelineItem());
+ m_ToggleControl->Refresh();
+ m_ColorControl->Invalidate();
+ m_TimebarControl->RefreshRowMetaData();
+ m_Dirty = false;
+ }
+}
+
+//=============================================================================
+/**
+ * Recursively load the children of this control, used by derived classes
+ * This will load all the properties and states, and create controls for them.
+ */
+void CBaseStateRow::LoadChildren()
+{
+ if (!m_Loaded) {
+ m_Loaded = true;
+
+ LoadProperties();
+
+ CTimelineItemOrderedIterator theChildIter(m_TimelineItemBinding);
+ // Go through all the children and load them too.
+ for (; !theChildIter.IsDone(); ++theChildIter)
+ CreateChildRow(*theChildIter, nullptr);
+
+ GetTopControl()->OnLayoutChanged();
+ }
+}
+
+//=============================================================================
+/**
+ * Add a row that represents this child timeline item
+ * @param inNextItem indicates row to follow behind the row for inTimeLineItem, nullptr to append inRow
+ * to the end of the current list.
+ */
+void CBaseStateRow::AddChildRow(ITimelineItemBinding *inTimeLineItem,
+ ITimelineItemBinding *inNextItem)
+{
+ if (!inTimeLineItem)
+ return;
+
+ // only add if loaded, else it will get added twice.
+ if (m_Loaded) {
+ CStateRow *theStateRow = CreateChildRow(
+ inTimeLineItem, inNextItem ? GetRow(inNextItem->GetTimelineItem()) : nullptr);
+ if (theStateRow)
+ theStateRow->LoadChildren();
+ }
+ Expand(false, true);
+
+ CBaseStateRow *theRow = GetRow(inTimeLineItem->GetTimelineItem());
+ if (theRow) {
+ CControl *theTreeControl = theRow->GetTreeControl();
+ if (theTreeControl)
+ theTreeControl->EnsureVisible();
+ }
+}
+
+void CBaseStateRow::RemoveChildRow(ITimelineItemBinding *inTimelineItem)
+{
+ CStateRow *theChildRow = GetRow(inTimelineItem->GetTimelineItem());
+ inTimelineItem->SetParent(nullptr);
+ if (theChildRow) {
+ RemoveRow(theChildRow);
+ // preserving legacy behavior.
+ GetTopControl()->HideTimelineMoveableTooltip();
+ }
+}
+
+//=============================================================================
+/**
+ * Removes all child rows from this row. Called prior to a load. The load call is responsible for
+ * updating the UI.
+ */
+void CBaseStateRow::RemoveAllChildren()
+{
+ RemoveAllProperties();
+
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos)
+ DeleteRow(*thePos);
+
+ m_StateRows.clear();
+}
+
+//=============================================================================
+/**
+ * Remove all the properties from this object. Called prior to a load. The load call is responsible
+ * for updating the UI.
+ */
+void CBaseStateRow::RemoveAllProperties()
+{
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos)
+ DeletePropertyRow(*thePropPos);
+
+ m_PropertyRows.clear();
+}
+
+//=============================================================================
+/**
+ * Set this row to selected
+ */
+void CBaseStateRow::Select(SBaseStateRowSelectionKeyState inState,
+ bool inCheckKeySelection /*= true */)
+{
+ bool alreadySelected = m_Selected;
+ m_TimelineItemBinding->SetSelected(inState.IsControlDown());
+ if (inCheckKeySelection) {
+ if (inState.IsShiftDown())
+ m_TimebarControl->SelectAllKeys();
+ else if (!alreadySelected)
+ m_TimelineItemBinding->ClearKeySelection();
+ }
+}
+
+//=============================================================================
+/**
+ * Change the selection state of the row.
+ */
+void CBaseStateRow::OnSelected(bool inSelection)
+{
+ if (inSelection == m_Selected)
+ return;
+
+ m_Selected = inSelection;
+ if (inSelection) {
+ if (m_ParentRow)
+ m_ParentRow->Expand(false, true);
+
+ m_TreeControl->EnsureVisible();
+
+ m_TreeControl->OnSelect();
+ m_ToggleControl->OnSelect();
+ m_ColorControl->OnSelect();
+ m_TimebarControl->OnSelect();
+ } else {
+ m_TreeControl->OnDeselect();
+ m_ToggleControl->OnDeselect();
+ m_ColorControl->OnDeselect();
+ m_TimebarControl->OnDeselect();
+ }
+}
+
+//=============================================================================
+/**
+ * Call to add a property row as a child of this control.
+ * @param inRow the row to be added.
+ */
+void CBaseStateRow::AddPropertyRow(CPropertyRow *inRow, CTimelineRow *inNextRow /*= nullptr */)
+{
+ m_PropertyRows.push_back(inRow);
+ InitializePropertyRow(inRow, inNextRow);
+ // For snapping timebars/keyframes
+ inRow->SetSnappingListProvider(GetSnappingListProvider());
+
+ m_TimebarControl->SetDirty(true);
+}
+
+//=============================================================================
+/**
+ * Remove the property row.
+ */
+void CBaseStateRow::RemovePropertyRow(const CPropertyRow *inRow)
+{
+ if (!inRow)
+ return;
+
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *theRow = *thePropPos;
+ if (theRow == inRow) {
+ DeletePropertyRow(theRow);
+ m_PropertyRows.erase(thePropPos);
+
+ // Update flippy
+ OnChildVisibilityChanged();
+ break;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Helper function to initialize a new property row
+ * @param inRow the row to be added.
+ * @param inNextRow if specified, row that should be after inRow after
+ * insertion.
+ */
+void CBaseStateRow::InitializePropertyRow(CPropertyRow *inRow, CTimelineRow *inNextRow /*= nullptr */)
+{
+ CFilter theFilter = m_Filter;
+ theFilter.SetExpanded(m_IsExpanded);
+
+ if (!inNextRow) { // not provided, this property row would be inserted before the first
+ // non-property row.
+ CTimelineItemOrderedIterator theIterator(m_TimelineItemBinding);
+ if (!theIterator.IsDone())
+ inNextRow = GetRow(theIterator.GetCurrent()->GetTimelineItem());
+ }
+ AddRowToUILists(inRow, inNextRow, theFilter);
+}
+
+void CBaseStateRow::AddRowToUILists(CTimelineRow *inRow, CTimelineRow *inNextRow, CFilter &inFilter)
+{
+ // Default the insert locations to the end of the list.
+ CControl *theNextColorControl = nullptr;
+ CControl *theNextTreeControl = nullptr;
+ CControl *theNextToggleControl = nullptr;
+ CControl *theNextTimebarControl = nullptr;
+ if (inNextRow) {
+ theNextColorControl = inNextRow->GetColorControl();
+ theNextTreeControl = inNextRow->GetTreeControl();
+ theNextToggleControl = inNextRow->GetToggleControl();
+ theNextTimebarControl = inNextRow->GetTimebarControl();
+ }
+ inRow->SetIndent(m_Indent + CTimelineRow::TREE_INDENT);
+ inRow->SetParent(this);
+ inRow->Filter(inFilter);
+ inRow->SetTimeRatio(m_TimeRatio);
+
+ CControl *theColorControl = inRow->GetColorControl();
+ CControl *theTreeControl = inRow->GetTreeControl();
+ CControl *theToggleControl = inRow->GetToggleControl();
+ CControl *theTimebarControl = inRow->GetTimebarControl();
+
+ // If not expanded then hide the controls.
+ if (!m_IsExpanded) {
+ theColorControl->SetVisible(false);
+ theTreeControl->SetVisible(false);
+ theToggleControl->SetVisible(false);
+ theTimebarControl->SetVisible(false);
+ }
+
+ // Add the controls to the lists in the prioritized order
+ m_ColorList.AddChild(theColorControl, theNextColorControl);
+ m_TreeList.AddChild(theTreeControl, theNextTreeControl);
+ m_ToggleList.AddChild(theToggleControl, theNextToggleControl);
+ m_TimebarList.AddChild(theTimebarControl, theNextTimebarControl);
+
+ m_TreeControl->SetToggleVisible(this->HasVisibleChildren());
+}
+
+CStateRow *CBaseStateRow::CreateChildRow(ITimelineItemBinding *inChildBinding, CStateRow *inNextRow)
+{
+ CStateRow *theRow =
+ CStateRowFactory::CreateStateRow(inChildBinding, this, GetSnappingListProvider());
+ if (theRow) { // add by appending to the list
+ AddStateRow(theRow, inNextRow);
+ }
+ inChildBinding->SetParent(m_TimelineItemBinding);
+ return theRow;
+}
+
+long CBaseStateRow::GetNumNonPropertyRows() const
+{
+ return static_cast<long>(m_StateRows.size());
+}
+
+CBaseStateRow *CBaseStateRow::GetNonPropertyRow(long inIndex) const
+{
+ return m_StateRows.at(inIndex);
+}
+
+long CBaseStateRow::GetNumPropertyRows() const
+{
+ return static_cast<long>(m_PropertyRows.size());
+}
+CPropertyRow *CBaseStateRow::GetPropertyRow(long inIndex) const
+{
+ return m_PropertyRows.at(inIndex);
+}
+
+//=============================================================================
+/**
+ * Call to add a state row as a child of this control.
+ * @param inRow the row to be added.
+ * @param inNextRow row to follow behind the row that would be added, nullptr to append inRow to the
+ * end of the current list.
+ */
+void CBaseStateRow::AddStateRow(CStateRow *inRow, CStateRow *inNextRow)
+{
+ if (inNextRow != nullptr) {
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ while (thePos != m_StateRows.end()) {
+ if ((*thePos) == inNextRow) {
+ m_StateRows.insert(thePos, inRow);
+ thePos = m_StateRows.end();
+ } else
+ ++thePos;
+ }
+ } else {
+ m_StateRows.push_back(inRow);
+ }
+
+ AddRowToUILists(inRow, inNextRow, m_Filter);
+}
+
+//=============================================================================
+/**
+ * Checks to see if there are any visible children of this row.
+ * This is used for figuring out whether the expand button should be displayed
+ * or not.
+ */
+bool CBaseStateRow::HasVisibleChildren()
+{
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ // Apply the filter
+ if ((*thePos)->IsViewable())
+ return true;
+ }
+
+ // For each property on this object
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ // Apply the filter
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow && thePropRow->IsViewable())
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Set the amount of time that is represented by a pixel.
+ * This modifies the length of this control.
+ * @param inTimePerPixel the time per pixel.
+ */
+void CBaseStateRow::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+ m_TimebarControl->SetTimeRatio(inTimeRatio);
+
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ (*thePos)->SetTimeRatio(inTimeRatio);
+ }
+
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow)
+ thePropRow->SetTimeRatio(inTimeRatio);
+ }
+}
+
+//=============================================================================
+/**
+ * Called when a child becomes visible/invisible.
+ */
+void CBaseStateRow::OnChildVisibilityChanged()
+{
+ m_TreeControl->SetToggleVisible(this->HasVisibleChildren());
+}
+
+//=============================================================================
+/**
+ * Called when the mouse is double clicked.
+ * @param inPoint location of the mouse at time of event
+ * @param inFlags modifier key states at time of event
+ */
+void CBaseStateRow::OnMouseDoubleClick(CPt, Qt::KeyboardModifiers inFlags)
+{
+ // Do nothing by default. Let subclasses define what to do.
+ Q_UNUSED(inFlags);
+}
+
+//=============================================================================
+/**
+ * Show context menu for this row
+ */
+void CBaseStateRow::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inFlags);
+
+ Select(SBaseStateRowSelectionKeyState()); // ensure this is selected, but doesn't affect any key
+ // selections, because this can be triggered from a
+ // key being selected
+ CComponentContextMenu theMenu(m_TreeControl, m_TimelineItemBinding);
+ m_TreeControl->DoPopup(&theMenu, inPoint);
+}
+
+//=============================================================================
+/**
+ * Selects keys in a given rect
+ * @param inRect the rect to use for selection
+ */
+void CBaseStateRow::SelectKeysInRect(CRct inRect, bool inModifierKeyDown,
+ bool inGlobalCommitSelectionFlag)
+{
+ CRct theOffsetRect = inRect;
+ theOffsetRect.Offset(-m_TimebarList.GetPosition());
+
+ // Commits the keyframe selection by setting the keyframes' previous state to its current state,
+ // when the user releases the mouse button.
+ // This will help the keyframes to retain their original states even though they are
+ // not in the mouse select region.
+ if (inGlobalCommitSelectionFlag) {
+ m_TimebarControl->CommitSelections();
+
+ // iterates through every property row and commits the selection states of properties
+ // keyframes
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow && thePropRow->IsViewable())
+ thePropRow->CommitSelections();
+ }
+ }
+
+ if (m_IsExpanded) {
+ // Iterates each property row and select the keys that are in the rectangle
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow && thePropRow->IsViewable())
+ thePropRow->SelectKeysInRect(theOffsetRect, inModifierKeyDown);
+ }
+
+ // Recurse the each state row (or master row) and selects the property keyframes in them
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos)
+ (*thePos)->SelectKeysInRect(theOffsetRect, inModifierKeyDown,
+ inGlobalCommitSelectionFlag);
+
+ } else {
+ // Selects all the master key frames in the rect
+ m_TimebarControl->SelectKeysInRect(theOffsetRect, inModifierKeyDown);
+ }
+}
+
+//=============================================================================
+/**
+ * Deletes all the keys for the asset that was chosen by the user
+ * @param inBatch the batch used to batch all the deletes together
+ */
+void CBaseStateRow::DeleteAllKeys()
+{
+ // Iterate through all the property rows and delete all their keys
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow)
+ thePropRow->DeleteAllKeys();
+ }
+}
+
+//=============================================================================
+/**
+ * Add snapping points to inSnappingList.
+ * This will add the snapping points for any visible objects to inSnappingList.
+ * @param inSnappingList the list to add the snapping points to.
+ */
+void CBaseStateRow::PopulateSnappingList(CSnapper *inSnappingList)
+{
+ inSnappingList->PushOffset(-m_TimebarList.GetPosition().y);
+ m_TimebarControl->PopulateSnappingList(inSnappingList);
+
+ if (IsExpanded()) {
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ (*thePos)->PopulateSnappingList(inSnappingList);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Sets all the child control enable states
+ * @param inEnabled the state to set the controls to
+ */
+void CBaseStateRow::SetEnabled(bool inEnabled)
+{
+ m_TreeControl->SetEnabled(inEnabled);
+ m_ToggleControl->SetEnabled(inEnabled);
+ m_ColorControl->SetEnabled(inEnabled);
+ m_TimebarControl->SetEnabled(inEnabled);
+}
+
+//=============================================================================
+/**
+ * Begin dragging.
+ * sk - potential spot for refactoring the Drag&Drop implementation.
+ * Right now, each IDragable is implicitly assumed to be a asset implementation. See
+ * *DropSource.cpp: each IDragable is dynamically cast to its implementation.
+ */
+void CBaseStateRow::DoStartDrag(CControlWindowListener *inWndListener)
+{
+ m_TimelineItemBinding->DoStartDrag(inWndListener);
+}
+
+void CBaseStateRow::AcceptDropAfter(bool inAccept)
+{
+ m_TreeControl->AcceptDropAfter(inAccept);
+}
+
+void CBaseStateRow::AcceptDropBefore(bool inAccept)
+{
+ m_TreeControl->AcceptDropBefore(inAccept);
+}
+
+//=============================================================================
+/**
+ * Pass through to the binding to set up the target aset for a drag&drop action on this
+ *control.
+ */
+void CBaseStateRow::SetDropTarget(CDropTarget *inDropTarget)
+{
+ m_TimelineItemBinding->SetDropTarget(inDropTarget);
+}
+
+void CBaseStateRow::SetTimelineLatestTime(long inTime)
+{
+ long theLength = ::TimeToPos(inTime, m_TimeRatio) + CTimelineTimelineLayout::END_BUFFER_SIZE;
+ m_TimebarControl->SetAbsoluteSize(CPt(theLength, m_TimebarControl->GetSize().y));
+
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos)
+ (*thePos)->SetTimelineLatestTime(inTime);
+}
+
+//=============================================================================
+/**
+ * Determines whether or not a row is expanded. A row can be expanded even if
+ * it is not visible.
+ * @return true if the row is currently expanded, otherwise false
+ */
+bool CBaseStateRow::IsExpanded()
+{
+ return m_IsExpanded;
+}
+
+//=============================================================================
+/**
+ * Determines whether or not a row is loaded. The rows are delayed loaded, i.e.
+ * it will be loaded when it's visible for the first time. Before it's loaded, any
+ * updates to the structure, say, adding dynamic properties does not need to update the
+ * timeline.
+ * @return true if the row is currently loaded, otherwise false
+ */
+bool CBaseStateRow::IsLoaded()
+{
+ return m_Loaded;
+}
+
+long CBaseStateRow::GetStartTime()
+{
+ ITimelineTimebar *theTimebar = m_TimelineItemBinding->GetTimelineItem()->GetTimebar();
+ if (theTimebar)
+ return theTimebar->GetStartTime();
+ return 0;
+}
+
+long CBaseStateRow::GetEndTime()
+{
+ ITimelineTimebar *theTimebar = m_TimelineItemBinding->GetTimelineItem()->GetTimebar();
+ if (theTimebar)
+ return theTimebar->GetEndTime();
+ return 0;
+}
+
+long CBaseStateRow::GetActiveStart()
+{
+ return m_ActiveStart;
+}
+long CBaseStateRow::GetActiveEnd()
+{
+ return m_ActiveEnd;
+}
+
+//=============================================================================
+/**
+ * Get the start time of this row, which is accumulative of all its descendants.
+ */
+long CBaseStateRow::GetEarliestStartTime()
+{
+ long theEarliestStartTime = 0;
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ CStateRow *theRow = (*thePos);
+ long theStartTime = theRow->GetEarliestStartTime();
+ if (theStartTime < theEarliestStartTime)
+ theEarliestStartTime = theStartTime;
+ }
+ return theEarliestStartTime;
+}
+
+//=============================================================================
+/**
+ * Get the end time of this row, which is accumulative of all its descendants.
+ */
+long CBaseStateRow::GetLatestEndTime()
+{
+ long theLatestTime = 0;
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos) {
+ CStateRow *theRow = (*thePos);
+ long theEndTime = theRow->GetLatestEndTime();
+ if (theEndTime > theLatestTime)
+ theLatestTime = theEndTime;
+ }
+ return theLatestTime;
+}
+
+//=============================================================================
+/**
+ * Lame switch to get the normal state object specific icon.
+ * @return the icon to be used in the 'normal' state.
+ */
+QPixmap CBaseStateRow::GetIcon()
+{
+ return CResourceCache::GetInstance()->GetBitmap(
+ CStudioObjectTypes::GetNormalIconName(GetObjectType()));
+}
+
+//=============================================================================
+/**
+ * Lame switch to get the disabled state object specific icon.
+ * @return the icon to be used in the disabled state.
+ */
+QPixmap CBaseStateRow::GetDisabledIcon()
+{
+ return CResourceCache::GetInstance()->GetBitmap(
+ CStudioObjectTypes::GetDisabledIconName(GetObjectType()));
+}
+
+//=============================================================================
+/**
+ * @return the studio type of the object represented by this row
+ */
+EStudioObjectType CBaseStateRow::GetObjectType() const
+{
+ return GetTimelineItem()->GetObjectType();
+}
+
+ITimelineItemBinding *CBaseStateRow::GetTimelineItemBinding() const
+{
+ return m_TimelineItemBinding;
+}
+
+ITimelineItem *CBaseStateRow::GetTimelineItem() const
+{
+ return m_TimelineItemBinding->GetTimelineItem();
+}
+
+//=============================================================================
+/**
+ * When this row is no longer useful, clean up.
+ */
+void CBaseStateRow::Dispose()
+{
+ // Disconnection point
+ if (m_TimelineItemBinding)
+ m_TimelineItemBinding->Release();
+
+ CTimelineRow::Dispose();
+}
+
+void CBaseStateRow::UpdateActionStatus()
+{
+ m_ColorControl->UpdateIconStatus();
+}
+
+//=============================================================================
+/**
+ * Restores the focus state of this row.
+ */
+void CBaseStateRow::SetFocus()
+{
+ CControl *theParent = m_TreeControl->GetParent();
+ if (theParent)
+ theParent->GrabFocus(m_TreeControl);
+}
+
+CBaseTimebarlessRow *CBaseStateRow::GetTimebar() const
+{
+ return m_TimebarControl;
+}
+
+void CBaseStateRow::SetNameReadOnly(bool inReadOnly)
+{
+ m_TreeControl->SetNameReadOnly(inReadOnly);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/BaseStateRow.h b/src/Authoring/Studio/Palettes/Timeline/BaseStateRow.h
new file mode 100644
index 00000000..5a62dfc0
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BaseStateRow.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BASE_STATE_ROW_H
+#define INCLUDED_BASE_STATE_ROW_H 1
+
+#pragma once
+
+#include "TimelineRow.h"
+#include "ListLayout.h"
+#include "ToggleButton.h"
+#include "DispatchListeners.h"
+
+class CPropertyRow;
+class CBaseTimelineTreeControl;
+class CColorControl;
+class CBlankToggleControl;
+class CBaseTimebarlessRow;
+class CStateRow;
+class CCmdBatch;
+class ITimelineItem;
+class ITimelineItemBinding;
+
+struct SBaseStateRowSelectionKeyState
+{
+ enum Enum {
+ NoKeyDown = 0,
+ ShiftKey = 1 << 0,
+ ControlKey = 1 << 1,
+ };
+ qt3ds::QT3DSU32 m_KeyState;
+ SBaseStateRowSelectionKeyState()
+ : m_KeyState(0)
+ {
+ }
+ void SetShiftDown() { m_KeyState = m_KeyState | ShiftKey; }
+ void SetControlDown() { m_KeyState = m_KeyState | ControlKey; }
+ bool IsShiftDown() const { return (m_KeyState & ShiftKey) != 0; }
+ bool IsControlDown() const { return (m_KeyState & ControlKey) != 0; }
+};
+
+class CBaseStateRow : public CTimelineRow
+{
+public:
+ typedef std::vector<CPropertyRow *> TPropertyRowList;
+ typedef std::vector<CStateRow *> TStateRowList;
+ static const long DEFAULT_TOGGLE_LENGTH;
+
+public:
+ CBaseStateRow();
+ virtual ~CBaseStateRow();
+
+ virtual void Initialize(ITimelineItemBinding *inTimelineItemBinding);
+
+ bool IsExpanded();
+ bool IsLoaded();
+ virtual void Expand(bool inExpandAll = false, bool inExpandUp = false);
+ virtual void Collapse(bool inCollapseAll = false);
+ void ToggleExpansion(CToggleButton *, CButtonControl::EButtonState);
+
+ void SetTimeRatio(double inTimePerPixel) override;
+
+ CControl *GetColorControl() override;
+ CControl *GetTreeControl() override;
+ CControl *GetToggleControl() override;
+ CControl *GetTimebarControl() override;
+
+ void Select(SBaseStateRowSelectionKeyState inKeyState, bool inCheckKeySelection = true);
+ void SelectKeysInRect(CRct inRect, bool inModifierKeyDown, bool inGlobalCommitSelectionFlag);
+ void DeleteAllKeys();
+
+ virtual void OnMouseOver();
+ virtual void OnMouseOut();
+ virtual void OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ virtual void OnDirty();
+ virtual void OnSelected(bool inSelected);
+
+ void LoadChildren();
+ void AddChildRow(ITimelineItemBinding *inTimeLineItem, ITimelineItemBinding *inNextItem);
+ void RemoveChildRow(ITimelineItemBinding *inTimeLineItem);
+
+ void RemoveRow(CStateRow *inRow);
+ void AddStateRow(CStateRow *inRow, CStateRow *inNextRow);
+ void AddPropertyRow(CPropertyRow *inRow, CTimelineRow *inNextRow = nullptr);
+ void RemovePropertyRow(const CPropertyRow *inRow);
+ void RemoveAllChildren();
+ void RemoveAllProperties();
+
+ long GetNumNonPropertyRows() const;
+ CBaseStateRow *GetNonPropertyRow(long inIndex) const;
+ long GetNumPropertyRows() const;
+ CPropertyRow *GetPropertyRow(long inIndex) const;
+
+ void Filter(const CFilter &inFilter, bool inFilterChildren = true) override;
+ CFilter *GetFilter() { return &m_Filter; }
+ void OnChildVisibilityChanged() override;
+
+ virtual bool HasVisibleChildren();
+
+ void PopulateSnappingList(CSnapper *inSnappingList) override;
+
+ virtual void SetEnabled(bool inEnabled);
+
+ void DoStartDrag(CControlWindowListener *inWndListener);
+ void AcceptDropAfter(bool inAccept);
+ void AcceptDropBefore(bool inAccept);
+ void SetDropTarget(CDropTarget *inDropTarget);
+
+ // CTimelineRow
+ virtual long GetEarliestStartTime();
+ long GetLatestEndTime() override;
+
+ long GetStartTime();
+ long GetEndTime();
+ long GetActiveStart();
+ long GetActiveEnd();
+ virtual bool CalculateActiveStartTime() = 0;
+ virtual bool CalculateActiveEndTime() = 0;
+ void Dispose() override;
+
+ virtual QPixmap GetIcon();
+ virtual QPixmap GetDisabledIcon();
+
+ EStudioObjectType GetObjectType() const;
+ ITimelineItemBinding *GetTimelineItemBinding() const;
+ ITimelineItem *GetTimelineItem() const;
+
+ void UpdateActionStatus();
+ void SetFocus();
+
+ CBaseTimebarlessRow *GetTimebar() const;
+
+ void SetNameReadOnly(bool inReadOnly);
+
+ void ClearDirty();
+
+protected:
+ void DeletePropertyRow(CPropertyRow *inPropertyRow);
+ virtual CBlankToggleControl *CreateToggleControl();
+ virtual CBaseTimebarlessRow *CreateTimebarRow() = 0;
+ virtual bool PerformFilter(const CFilter &inFilter) = 0;
+ CStateRow *GetRow(ITimelineItem *inTimelineItem);
+ void DeleteRow(CStateRow *inRow);
+ void SetTimelineLatestTime(long inLength);
+
+ virtual void LoadProperties() {}
+ void InitializePropertyRow(CPropertyRow *inRow, CTimelineRow *inNextRow = nullptr);
+
+ void AddRowToUILists(CTimelineRow *inRow, CTimelineRow *inNextRow, CFilter &inFilter);
+ CStateRow *CreateChildRow(ITimelineItemBinding *inChildBinding, CStateRow *inNextRow);
+
+ double m_TimeRatio;
+ CFilter m_Filter;
+ CListLayout m_ColorList;
+ CListLayout m_TreeList;
+ CListLayout m_ToggleList;
+ CListLayout m_TimebarList;
+
+ CBaseTimelineTreeControl *m_TreeControl;
+ CColorControl *m_ColorControl;
+ CBlankToggleControl *m_ToggleControl;
+ CBaseTimebarlessRow *m_TimebarControl;
+
+ TStateRowList m_StateRows;
+ TPropertyRowList m_PropertyRows;
+
+ bool m_Loaded;
+ bool m_IsExpanded;
+ bool m_Highlighted;
+ bool m_Dirty;
+ bool m_Selected;
+
+ ITimelineItemBinding *m_TimelineItemBinding;
+
+ long m_ActiveStart;
+ long m_ActiveEnd;
+};
+#endif // INCLUDED_BASE_STATE_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.cpp b/src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.cpp
new file mode 100644
index 00000000..4ded07dd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "BaseTimebarlessRow.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "BaseStateRow.h"
+
+CBaseTimebarlessRow::CBaseTimebarlessRow()
+ : m_Selected(false)
+ , m_DirtyFlag(true)
+ , m_TimeRatio(0.0f)
+{
+}
+
+CBaseTimebarlessRow::~CBaseTimebarlessRow()
+{
+}
+
+void CBaseTimebarlessRow::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+
+ // Fill in the background
+ if (!m_Selected)
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+ else
+ inRenderer->FillSolidRect(theRect, CStudioPreferences::GetTimelineSelectColor());
+
+ // Draw the line at the bottom of this control and the one on the side
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Set this control to being highlighted or not.
+ * @param inIsHighlighted true if this is to be highlighted.
+ */
+void CBaseTimebarlessRow::SetBackgroundColor(::CColor inBackgroundColor)
+{
+ if (m_BackgroundColor != inBackgroundColor) {
+ m_BackgroundColor = inBackgroundColor;
+ Invalidate();
+ }
+}
+
+void CBaseTimebarlessRow::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+}
+
+//=============================================================================
+/**
+ * Notification that the object that this row is representing has been selected.
+ */
+void CBaseTimebarlessRow::OnSelect()
+{
+ m_Selected = true;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Notification that the object that this row is representing has been deselected.
+ */
+void CBaseTimebarlessRow::OnDeselect()
+{
+ m_Selected = false;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * called when meta data for this row is changed... should be overridden by the
+ * timebar row
+ */
+void CBaseTimebarlessRow::RefreshRowMetaData()
+{
+}
+
+//=============================================================================
+/**
+ * called when a child changes and the keyframes need to be refreshed
+ * @param inDirtyFlag true if this object is now dirty
+ */
+void CBaseTimebarlessRow::SetDirty(bool inDirtyFlag)
+{
+ if (m_DirtyFlag == inDirtyFlag)
+ return;
+
+ m_DirtyFlag = inDirtyFlag;
+ Invalidate();
+}
+
+void CBaseTimebarlessRow::UpdateTime(long inStartTime, long inEndTime)
+{
+ Q_UNUSED(inStartTime);
+ Q_UNUSED(inEndTime);
+}
+
+//=============================================================================
+/**
+ * OnMouseOver event, handles the highlighting of the row.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+void CBaseTimebarlessRow::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ GetBaseStateRow()->OnMouseOver();
+}
+
+//=============================================================================
+/**
+ * OnMouseOut event, handles the de-highlighting of this row.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+void CBaseTimebarlessRow::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ GetBaseStateRow()->OnMouseOut();
+}
+
+//=============================================================================
+/**
+ * OnMouseDown event, handles the selecting of this object.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+bool CBaseTimebarlessRow::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ return CControl::OnMouseDown(inPoint, inFlags);
+#if 0
+ // this addition is causing 4085: Cannot do rubber band selection from sections of timeline that don't contain timebars anymore
+ bool theReturn = CControl::OnMouseDown( inPoint, inFlags );
+ if ( !theReturn )
+ {
+ // Tests if the user has pressed the modifier key, where the intention is to multi-select keyframes.
+ if ( !(inFlags & CHotKeys::MODIFIER_CONTROL ) )
+ {
+ // SK - I changed this to select the row when this is clicked, because I think its a nice feature. ie don't always have to click on the timebar (esp for those e.g. scene without one)
+ // when the modifier key is pressed.
+ GetBaseStateRow( )->Select( false );
+
+ theReturn = true;
+ }
+ }
+ return theReturn;
+#endif
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.h b/src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.h
new file mode 100644
index 00000000..9c2fbea4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BaseTimebarlessRow.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BASE_TIMEBARLESS_ROW_H
+#define INCLUDED_BASE_TIMEBARLESS_ROW_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+
+class CSnapper;
+class CBaseStateRow;
+class ISnappingListProvider;
+
+class CBaseTimebarlessRow : public CControl
+{
+public:
+ CBaseTimebarlessRow();
+ virtual ~CBaseTimebarlessRow();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ virtual void SetBackgroundColor(::CColor inColor);
+ virtual void SetTimeRatio(double inTimeRatio);
+
+ virtual void RefreshRowMetaData();
+
+ virtual void OnSelect();
+ virtual void OnDeselect();
+
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ virtual void SetDirty(bool inIsDirty);
+ virtual void UpdateTime(long inStartTime, long inEndTime);
+
+ virtual void CommitSelections() = 0;
+ virtual void SelectKeysInRect(CRct inRect, bool inModifierKeyDown) = 0;
+ virtual void SelectAllKeys() = 0;
+ virtual void SelectKeysByTime(long inTime, bool inSelected) = 0;
+ virtual void PopulateSnappingList(CSnapper *inSnappingList) = 0;
+ virtual ISnappingListProvider &GetSnappingListProvider() const = 0;
+
+protected:
+ virtual CBaseStateRow *GetBaseStateRow() const = 0;
+
+ ::CColor m_BackgroundColor;
+ bool m_Selected;
+ bool m_DirtyFlag;
+ double m_TimeRatio;
+};
+#endif // INCLUDED_BASE_TIMEBARLESS_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.cpp b/src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.cpp
new file mode 100644
index 00000000..3221f6a1
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.cpp
@@ -0,0 +1,685 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "Renderer.h"
+#include "ToggleButton.h"
+#include "BaseStateRow.h"
+#include "StudioPreferences.h"
+#include "TimelineDropTarget.h"
+#include "BaseTimelineTreeControl.h"
+#include "NameEdit.h"
+#include "Bindings/ITimelineItem.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Create a new tree control for the specified state row.
+ * This control contains the toggle button and item name controls.
+ * @param inStateRow the state row of which this belongs to.
+ */
+CBaseTimelineTreeControl::CBaseTimelineTreeControl(CBaseStateRow *inStateRow, bool inMaster)
+ : m_Selected(false)
+ , m_MouseDown(false)
+{
+ m_StateRow = inStateRow;
+
+ m_BackgroundColor = m_StateRow->GetTimebarBackgroundColor(m_StateRow->GetObjectType());
+
+ // Create the expand/collapse button.
+ m_ExpandButton = new CToggleButton();
+ m_ExpandButton->SetUpImage("arrow.png");
+ m_ExpandButton->SetDownImage("arrow_down.png");
+
+ // Add the button and initialize all the listeners for the events on it.
+ AddChild(m_ExpandButton);
+ m_ExpandButton->SigToggle.connect(std::bind(&CBaseStateRow::ToggleExpansion, m_StateRow,
+ std::placeholders::_1, std::placeholders::_2));
+ m_ExpandButton->SetVisible(false);
+
+ m_Icon = new CSIcon(m_StateRow->GetIcon(), m_StateRow->GetDisabledIcon());
+ AddChild(m_Icon);
+
+ // Create and add the name label.
+ m_Text = nullptr; // withdrawn from constructor to delay creation of text object
+
+ // Initialize all the component's positions to 0.
+ SetIndent(CStudioPreferences::GetRowSize());
+
+ SetMinimumSize(CPt(CBaseStateRow::DEFAULT_TOGGLE_LENGTH + m_Icon->GetPosition().x
+ + m_Icon->GetSize().x + 5,
+ CStudioPreferences::GetRowSize()));
+
+ m_TrackingPoint.x = 0;
+ m_TrackingPoint.y = 0;
+ m_DrawAcceptBefore = false;
+ m_DrawAcceptAfter = false;
+
+ // Set up default text colors
+ m_NormalTextColor = CStudioPreferences::GetNormalColor();
+ m_SelectedTextColor = CStudioPreferences::GetNormalColor();
+ if (inMaster) {
+ m_NormalTextColor = CStudioPreferences::GetMasterColor();
+ m_SelectedTextColor = CStudioPreferences::GetMasterColor();
+ }
+ m_LockedTextColor = CStudioPreferences::GetLockedTextColor();
+}
+
+CBaseTimelineTreeControl::~CBaseTimelineTreeControl()
+{
+ delete m_Icon;
+ delete m_ExpandButton;
+ delete m_Text;
+}
+
+//=============================================================================
+/**
+ * Create a new text object. For performance reasons we delay
+ * creating this object until it is needed, i.e. until the row is exposed
+ * by the user and the Draw method is called
+ */
+void CBaseTimelineTreeControl::CreateText()
+{
+ if (!m_Text) {
+ ITimelineItem *theTimelineItem = m_StateRow->GetTimelineItem();
+
+ m_Text = new CNameEdit(theTimelineItem);
+
+ m_Text->SetSize(
+ CPt(CStudioPreferences::GetTimelineNameSize(),
+ CStudioPreferences::GetRowSize() - 3)); /* m_ExpandButton->GetSize( ).y - 3*/
+ // m_Text->SetBGColorNoFocus( CStudioPreferences::GetNormalColor( ) );
+ // if ( theTimelineItem->IsMaster( ) )
+ // m_Text->SetBGColorNoFocus( CStudioPreferences::GetMasterColor( ) );
+ // m_Text->SetFillBackground( false );
+ m_Text->SetBoldText(false);
+
+ // If the object is the scene, you can't edit it's name
+ m_Text->SetEditable(m_StateRow->GetObjectType() != OBJTYPE_SCENE);
+ AddChild(m_Text);
+ m_Text->SetPosition(CPt(m_Icon->GetPosition().x + m_Icon->GetSize().x + 5, 1));
+
+ // This was disabled before Text was created.
+ if (!IsEnabled()) {
+ m_Text->SetEnabled(false);
+ m_Text->SetParentEnabled(false);
+ m_Text->SetTextColor(m_LockedTextColor);
+ } else // since we do delay-creation, "sync" with the parent's selection state
+ UpdateTextSelection();
+
+ // This is so that make the timeline scrollbar scrolls correctly
+ // ( i.e. to the end of the asset name )
+ CPt theSize(GetSize());
+ theSize.x =
+ CBaseStateRow::DEFAULT_TOGGLE_LENGTH + m_Text->GetPosition().x + m_Text->GetSize().x;
+ SetAbsoluteSize(theSize);
+ }
+}
+
+void CBaseTimelineTreeControl::UpdateTextSelection()
+{
+ // since we do delay-creation for the Text only when we have to draw it.. this checks if it is
+ // created first
+ if (m_Text) {
+ if (!IsEnabled())
+ m_Text->SetTextColor(m_LockedTextColor);
+ else
+ m_Text->SetTextColor(m_Selected ? m_SelectedTextColor : m_NormalTextColor);
+ // m_Text->SetFillBackground( m_Selected );
+ // m_Text->SetBoldText( m_Selected );
+ }
+}
+
+//=============================================================================
+/**
+ * Perform the drawing of this control.
+ * @param inRenderer the renderer to draw to.
+ */
+void CBaseTimelineTreeControl::Draw(CRenderer *inRenderer)
+{
+ CreateText(); // the row is now exposed and we can't delay creating the text object any longer
+
+ CRct theRect(GetSize());
+ // Fill in the background
+ if (!m_Selected)
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+ else
+ inRenderer->FillSolidRect(theRect, CStudioPreferences::GetTimelineSelectColor());
+
+ // if ( m_Text )
+ // m_Text->SetBoldText( m_Selected );
+ // m_Text->SetFillBackground( m_Selected );
+
+ // Draw the line at the bottom of this control
+ inRenderer->PushPen(CStudioPreferences::GetTreeFloorColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Override for the set parent enabled function which tells children the state of the parent
+ */
+void CBaseTimelineTreeControl::SetEnabled(bool inIsEnabled)
+{
+ CControl::SetEnabled(inIsEnabled);
+ if (m_Text) {
+ m_Text->SetEnabled(inIsEnabled);
+ if (!inIsEnabled)
+ m_Text->SetTextColor(m_LockedTextColor);
+ else
+ m_Text->SetTextColor(m_Selected ? m_SelectedTextColor : m_NormalTextColor);
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that something has changed on the asset that this
+ * represents, update it.
+ */
+void CBaseTimelineTreeControl::Refresh(ITimelineItem *inTimelineItem)
+{
+ bool theEnabled = !inTimelineItem->IsLocked();
+ if (m_Text) {
+ // Make sure the color is correct depending on if its is a master object
+ if (m_NormalTextColor != CStudioPreferences::GetMasterColor()
+ && inTimelineItem->IsMaster()) {
+ m_NormalTextColor = CStudioPreferences::GetMasterColor();
+ m_Text->SetBGColorNoFocus(CStudioPreferences::GetMasterColor());
+ if (!m_Selected)
+ m_Text->SetTextColor(m_NormalTextColor);
+ }
+
+ m_Text->SetData(inTimelineItem->GetName());
+ }
+ m_Icon->SetImage((theEnabled) ? m_StateRow->GetIcon() : m_StateRow->GetDisabledIcon());
+ SetEnabled(theEnabled);
+}
+
+//=============================================================================
+/**
+ * Set the indent of this control.
+ * The indent gives the semblance of a tree control, and causes the toggle
+ * name and icon to be pushed in some.
+ * @param inIndent the indent for this control.
+ */
+void CBaseTimelineTreeControl::SetIndent(long inIndent)
+{
+ m_Indent = inIndent;
+
+ // Set the new position for all the children.
+ m_ExpandButton->SetPosition(CPt(inIndent, 0));
+
+ m_Icon->SetPosition(CPt(m_ExpandButton->GetPosition().x + m_ExpandButton->GetSize().x, 0));
+ if (m_Text)
+ m_Text->SetPosition(CPt(m_Icon->GetPosition().x + m_Icon->GetSize().x + 5, 1));
+}
+
+//=============================================================================
+/**
+ * Get the current indent of this control.
+ */
+long CBaseTimelineTreeControl::GetIndent()
+{
+ return m_Indent;
+}
+
+//=============================================================================
+/**
+ * Set whether or not to have the toggle control visible.
+ * The toggle is turned off by the state row when there are no visible children.
+ * @param inIsToggleVisible false if the toggle is not to be visible.
+ */
+void CBaseTimelineTreeControl::SetToggleVisible(bool inIsToggleVisible)
+{
+ m_ExpandButton->SetVisible(inIsToggleVisible);
+}
+
+//=============================================================================
+/**
+ * Set whether or not this control is expanded.
+ * This is used to set the state of the expand button.
+ */
+void CBaseTimelineTreeControl::SetExpanded(bool inIsExpanded)
+{
+ m_ExpandButton->SetToggleState(inIsExpanded);
+}
+
+//=============================================================================
+/**
+ * Set the current background color for this control.
+ * The background color changes when the control gets a mouse over/mouse out.
+ */
+void CBaseTimelineTreeControl::SetBackgroundColor(CColor inColor)
+{
+ if (m_BackgroundColor == inColor)
+ return;
+
+ m_BackgroundColor = inColor;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Notify the row that a mouse out occurred.
+ * The row will in turn turn off the highlighting.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CBaseTimelineTreeControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_DrawAcceptAfter = false;
+ m_DrawAcceptBefore = false;
+
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ m_StateRow->OnMouseOut();
+
+ if (m_TimerHandler) {
+
+ // nullptr out our handle so we can create a new one.
+ m_TimerHandler = std::shared_ptr<UICDM::ISignalConnection>();
+ }
+
+ AcceptDropAfter(false);
+ AcceptDropBefore(false);
+}
+
+//=============================================================================
+/**
+ * Notify the row that a mouse over occurred.
+ * The row will in turn turn on the highlighting.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CBaseTimelineTreeControl::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ m_StateRow->OnMouseOver();
+}
+
+//=============================================================================
+/**
+ * Pass the double click notification on to the row and have it process it.
+ * The row will do object-specific actions on doubleclicks.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ * @return true stating that the event was processed.
+ */
+bool CBaseTimelineTreeControl::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDoubleClick(inPoint, inFlags)) {
+ m_StateRow->OnMouseDoubleClick(inPoint, inFlags);
+ GrabFocus(nullptr);
+ }
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handles mouse down on the this control. Flags the button as down which results
+ * in some possible drawing changes.
+ * @param inPoint location of the mouse when event occurred
+ * @param inFlags state of modifier keys when event occurred
+ * @return true
+ */
+bool CBaseTimelineTreeControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ SBaseStateRowSelectionKeyState theKeyState;
+ if ((CHotKeys::MODIFIER_SHIFT & inFlags) == CHotKeys::MODIFIER_SHIFT)
+ theKeyState.SetShiftDown();
+ if ((CHotKeys::MODIFIER_CONTROL & inFlags) == CHotKeys::MODIFIER_CONTROL)
+ theKeyState.SetControlDown();
+ m_StateRow->Select(theKeyState);
+
+ // Always track where the mouse is.
+ m_MouseDown = true;
+
+ Invalidate();
+ }
+
+ return true;
+}
+
+bool CBaseTimelineTreeControl::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseRDown(inPoint, inFlags))
+ m_StateRow->OnMouseRDown(inPoint, inFlags);
+
+ return true;
+}
+
+void CBaseTimelineTreeControl::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_MouseDown = false;
+
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ AcceptDropAfter(false);
+ AcceptDropBefore(false);
+}
+
+//=============================================================================
+/**
+ * This method handles the keydown event for a StateTreeControl. It calls
+ * CControl::OnKeyDown method to make sure that the keydown event is handled
+ * by its children. If the keydown event is not handled and F2 is down, it
+ * enables text edit mode.
+ * @param inChar is the char pressed
+ * @param inFlags state of modifier keys when event occurred
+ * @return if the key was handled
+ */
+bool CBaseTimelineTreeControl::OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags)
+{
+ bool theKeyWasHandled = CControl::OnKeyDown(inChar, inFlags);
+
+ if (!theKeyWasHandled && (inChar == Qt::Key_F2)) {
+ DoRename();
+ theKeyWasHandled = true;
+ }
+
+ return theKeyWasHandled;
+}
+
+//=============================================================================
+/**
+ * This is so the Gesture can this object to get something ready to Drag.
+ */
+void CBaseTimelineTreeControl::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ if (m_MouseDown /*&& inFlags & MOUSE_LBUTTON*/) {
+ long theDeltaX = inPoint.x - m_TrackingPoint.x;
+ long theDeltaY = inPoint.y - m_TrackingPoint.y;
+
+ if (::abs(theDeltaX) > 3 || ::abs(theDeltaY) > 3) {
+ m_TrackingPoint = inPoint;
+
+ m_StateRow->DoStartDrag(GetWindowListener());
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the state that this is displaying has been selected.
+ */
+void CBaseTimelineTreeControl::OnSelect()
+{
+ m_Selected = true;
+
+ UpdateTextSelection();
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Notification that the state that this is displaying has been deselected.
+ */
+void CBaseTimelineTreeControl::OnDeselect()
+{
+ m_Selected = false;
+
+ UpdateTextSelection();
+ Invalidate();
+}
+
+void CBaseTimelineTreeControl::GrabTextFocus()
+{
+ GrabFocus(m_Text);
+}
+
+//=============================================================================
+/**
+ * To enable F2 editing.
+ */
+void CBaseTimelineTreeControl::OnGainFocus()
+{
+ CControl::OnGainFocus();
+ GrabFocus(m_Text);
+}
+
+//=============================================================================
+/**
+ * Called when this control loses focus. Overridden because we need to set the
+ * text color depending on whether or not the asset for this row is still
+ * selected.
+ */
+void CBaseTimelineTreeControl::OnLoseFocus()
+{
+ CControl::OnLoseFocus();
+
+ if (m_Text) {
+ if (m_Selected) {
+ m_Text->SetTextColor(m_SelectedTextColor);
+ } else // If this asset is no longer selected
+ {
+ // If the row is enabled, use the normal text color
+ if (m_Text->IsEnabled()) {
+ m_Text->SetTextColor(m_NormalTextColor);
+ }
+ // Otherwise use the locked text color
+ else {
+ m_Text->SetTextColor(m_LockedTextColor);
+ }
+ }
+ }
+
+ AcceptDropAfter(false);
+ AcceptDropBefore(false);
+}
+
+//=============================================================================
+/**
+ * If the name is changed, the size has to be adjusted accordingly.
+ */
+void CBaseTimelineTreeControl::OnChildSizeChanged(CControl *inChild)
+{
+ CControl::OnChildSizeChanged(inChild);
+
+ if (inChild == m_Text) { // This is so that make the timeline scrollbar scrolls correctly
+ // ( i.e. to the end of the asset name )
+ CPt theSize(GetSize());
+ theSize.x =
+ CBaseStateRow::DEFAULT_TOGGLE_LENGTH + m_Text->GetPosition().x + m_Text->GetSize().x;
+ SetAbsoluteSize(theSize);
+ }
+}
+
+//=============================================================================
+/**
+ * This will do a vertical hit test on this control.
+ * This need to figure out if the point is toward teh top or toward the bottom, or on this
+ *control.
+ * @param inMousePoint the point where the dropp wants to occure.
+ * @return An enumeration representing the location of the potential drop.
+ */
+CBaseTimelineTreeControl::ECONTROLREGION CBaseTimelineTreeControl::FindHitRegion(CPt &inMousePoint)
+{
+ // Default Region is "on"
+ CBaseTimelineTreeControl::ECONTROLREGION theDropRegion =
+ CBaseTimelineTreeControl::ECONTROLREGION_ON;
+
+ CPt theSize = GetSize();
+ long theTop = 0;
+ long theBottom = theSize.y - 1;
+ long thePointY = inMousePoint.y;
+
+ // check if we are in the upper part of the control
+ if ((thePointY >= theTop) && (thePointY <= (theTop + 3))) {
+ theDropRegion = CBaseTimelineTreeControl::ECONTROLREGION_ABOVE;
+ }
+ // check if we are in the lower part of the control
+ else if ((thePointY <= (theBottom)) && (thePointY >= (theBottom - 3))) {
+ theDropRegion = CBaseTimelineTreeControl::ECONTROLREGION_BELOW;
+ }
+
+ return theDropRegion;
+}
+
+//=============================================================================
+/**
+ * Find an object under the point.
+ * If tht point is close to the top or the bottom of the control,
+ * then the Asset to use would be the parent of the current asset.
+ * @param inMousePoint the point where the Drop wants to occure.
+ */
+CDropTarget *CBaseTimelineTreeControl::BuildDropTarget(CPt &inMousePoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inFlags);
+
+ // This will do the hit testing to see where we are with the point.
+ ECONTROLREGION theRegion = FindHitRegion(inMousePoint);
+
+ // Make a new DropTarget to return.
+ CTimeLineDropTarget *theTarget = new CTimeLineDropTarget();
+
+ EDROPDESTINATION theDropDest = EDROPDESTINATION_ON;
+
+ switch (theRegion) {
+ case ECONTROLREGION_BELOW:
+ theDropDest = EDROPDESTINATION_BELOW;
+
+ AcceptDropAfter(true);
+ AcceptDropBefore(false);
+ break;
+
+ case ECONTROLREGION_ABOVE:
+ theDropDest = EDROPDESTINATION_ABOVE;
+
+ AcceptDropAfter(false);
+ AcceptDropBefore(true);
+ break;
+
+ case ECONTROLREGION_ON:
+
+ AcceptDropAfter(false);
+ AcceptDropBefore(false);
+ break;
+ }
+ theTarget->SetDestination(theDropDest);
+ // For insertion markers
+ theTarget->SetInsertionMarkerRow(this);
+ theTarget->SetInsertionMarkerIndent(m_Icon->GetPosition().x);
+
+ // connect the data portion of the drag&drop action
+ m_StateRow->SetDropTarget(theTarget);
+
+ return theTarget;
+}
+
+//=============================================================================
+/**
+ * This function is overriden from the CControl class.
+ * It will find an Asset that can be dropped upon. Also it will
+ * figureout if the DropTarget should contain this Asset or the parent
+ * of this Asset.
+ * @param inMousePoint the coords [in local space] of the drop action.
+ * @param inFlags the Modifier flags for the keyboard state.
+ * @return the found DropTarget or null if not found.
+ */
+CDropTarget *CBaseTimelineTreeControl::FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags)
+{
+ // Make sure the Mouse Highlighting happens.
+ m_StateRow->OnMouseOver();
+
+ // This will do all of the work.
+ CDropTarget *theReturnTarget = BuildDropTarget(inMousePoint, inFlags);
+
+ // Expand the object [ once again ask CE for an explaination of this ]
+ if (!m_TimerHandler && m_ExpandButton->IsVisible() && m_ExpandButton->IsEnabled()) {
+ if (!m_DrawAcceptBefore && !m_DrawAcceptAfter)
+ m_TimerHandler = Q3DStudio::ITickTock::GetInstance().AddTimer(
+ 1000, false, std::bind(&CBaseTimelineTreeControl::OnTimer, this),
+ "CStateTreeControl::FindDropCandidate::" + GetName());
+ }
+
+ // we always return true, since we should be the only one to handle it.
+ return theReturnTarget;
+}
+
+//=============================================================================
+/**
+ * Notification that the Hover Time has expired,
+ */
+void CBaseTimelineTreeControl::OnTimer()
+{
+ // Expand the Row to show the children.
+ m_StateRow->Expand();
+}
+
+//=============================================================================
+/**
+ * This will set the Flag so we can Draw the Bottom Line.
+ * @param inAccept true to draw the line false otherwise.
+ */
+void CBaseTimelineTreeControl::AcceptDropAfter(bool inAccept)
+{
+ if (inAccept != m_DrawAcceptAfter) {
+ m_DrawAcceptAfter = inAccept;
+ }
+}
+
+//=============================================================================
+/**
+ * This will set the Flag so we can Draw the Top Line.
+ * @param inAccept true to draw the line false otherwise.
+ */
+void CBaseTimelineTreeControl::AcceptDropBefore(bool inAccept)
+{
+ if (inAccept != m_DrawAcceptBefore) {
+ m_DrawAcceptBefore = inAccept;
+ }
+}
+
+//=============================================================================
+/**
+ * Called by the state context menu to do the renaming portion of the menu
+ */
+void CBaseTimelineTreeControl::DoRename()
+{
+ CreateText();
+ m_Text->SetEditMode(true);
+ GrabFocus(m_Text);
+ m_Text->SelectAllText();
+}
+
+void CBaseTimelineTreeControl::SetNameReadOnly(bool inReadOnly)
+{
+ CreateText(); // Create the text if it's not ready.
+ m_Text->SetEditable(!inReadOnly);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.h b/src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.h
new file mode 100644
index 00000000..e348cccf
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BaseTimelineTreeControl.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BASE_TIMELINE_TREE_CONTROL_H
+#define INCLUDED_BASE_TIMELINE_TREE_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "SIcon.h"
+#include "ToggleButton.h"
+#include "ITickTock.h"
+
+class CButtonControl;
+class CBaseStateRow;
+class CDropTarget;
+class CNameEdit;
+class CTickTockProc;
+struct STickTockHandle;
+class CPt;
+class CToggleButton;
+class ITimelineItem;
+
+class CBaseTimelineTreeControl : public CControl
+{
+
+public:
+ enum ECONTROLREGION { ECONTROLREGION_ON, ECONTROLREGION_ABOVE, ECONTROLREGION_BELOW };
+
+ CBaseTimelineTreeControl(CBaseStateRow *inStateRow, bool inMaster);
+ virtual ~CBaseTimelineTreeControl();
+
+ void Draw(CRenderer *inRenderer) override;
+ void OnChildSizeChanged(CControl *inChild) override;
+
+ void SetIndent(long inIndent);
+ long GetIndent();
+
+ void SetExpanded(bool inIsExpanded);
+
+ void SetToggleVisible(bool inIsToggleVisible);
+ void OnSelect();
+ void OnDeselect();
+ void GrabTextFocus();
+ void OnGainFocus() override;
+ void OnLoseFocus() override;
+ void SetBackgroundColor(::CColor inBackgroundColor);
+
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnKeyDown(unsigned int inChar, Qt::KeyboardModifiers inFlags) override;
+
+ void OnTimer();
+
+ void Refresh(ITimelineItem *inTimelineItem);
+
+ void SetEnabled(bool inIsEnabled) override;
+
+ CDropTarget *BuildDropTarget(CPt &inMousePoint, Qt::KeyboardModifiers inFlags);
+ CDropTarget *FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags) override;
+ void AcceptDropAfter(bool inAccept);
+ void AcceptDropBefore(bool inAccept);
+ void DoRename();
+
+ void SetNameReadOnly(bool inReadOnly);
+
+protected:
+ ECONTROLREGION FindHitRegion(CPt &inMousePoint);
+ void CreateText(); // delay text creation until row is exposed
+ void UpdateTextSelection();
+
+ long m_Indent;
+
+ CBaseStateRow *m_StateRow;
+
+ CToggleButton *m_ExpandButton;
+ CNameEdit *m_Text;
+
+ CSIcon *m_Icon;
+ bool m_Selected;
+
+ ::CColor m_BackgroundColor;
+
+ CPt m_TrackingPoint;
+ CPt m_MouseMovePoint;
+ bool m_MouseDown;
+ bool m_DrawAcceptBefore;
+ bool m_DrawAcceptAfter;
+ std::shared_ptr<UICDM::ISignalConnection> m_TimerHandler;
+ ::CColor m_NormalTextColor;
+ ::CColor m_SelectedTextColor;
+ ::CColor m_LockedTextColor;
+};
+#endif // INCLUDED_BASE_TIMELINE_TREE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.cpp
new file mode 100644
index 00000000..196d345d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BehaviorTimelineItemBinding.h"
+#include "TimelineTranslationManager.h"
+#include "StudioApp.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "Doc.h"
+
+using namespace UICDM;
+
+CBehaviorTimelineItemBinding::CBehaviorTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+{
+}
+
+EStudioObjectType CBehaviorTimelineItemBinding::GetObjectType() const
+{
+ return OBJTYPE_BEHAVIOR;
+}
+
+//=============================================================================
+/**
+ * Open the associated item as though it was double-clicked in explorer
+ */
+bool CBehaviorTimelineItemBinding::OpenAssociatedEditor()
+{
+ return OpenSourcePathFile();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.h
new file mode 100644
index 00000000..b75d100c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/BehaviorTimelineItemBinding.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_BEHAVIOR_TIMELINEITEM_BINDING_H
+#define INCLUDED_BEHAVIOR_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CTimelineTranslationManager;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Behavior type
+ */
+class CBehaviorTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public:
+ CBehaviorTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ ~CBehaviorTimelineItemBinding() {}
+
+ // CUICDMTimelineItemBinding
+ EStudioObjectType GetObjectType() const override;
+ bool OpenAssociatedEditor() override;
+};
+
+#endif // INCLUDED_BEHAVIOR_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.cpp
new file mode 100644
index 00000000..7534fa73
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EmptyTimelineTimebar.h"
+#include "StudioPreferences.h"
+
+CEmptyTimelineTimebar::CEmptyTimelineTimebar()
+{
+}
+
+CEmptyTimelineTimebar::~CEmptyTimelineTimebar()
+{
+}
+
+long CEmptyTimelineTimebar::GetStartTime() const
+{
+ return 0;
+}
+
+long CEmptyTimelineTimebar::GetEndTime() const
+{
+ return 0;
+}
+
+long CEmptyTimelineTimebar::GetDuration() const
+{
+ return 0;
+}
+
+bool CEmptyTimelineTimebar::ShowHandleBars() const
+{ // makes no sense to show handle bars, when this does not have start/end times.
+ return false;
+}
+
+void CEmptyTimelineTimebar::OnBeginDrag()
+{
+}
+
+void CEmptyTimelineTimebar::OffsetTime(long inDiff)
+{
+ Q_UNUSED(inDiff);
+}
+
+void CEmptyTimelineTimebar::ChangeTime(long inTime, bool inSetStart)
+{
+ Q_UNUSED(inTime);
+ Q_UNUSED(inSetStart);
+}
+
+void CEmptyTimelineTimebar::CommitTimeChange()
+{
+}
+
+void CEmptyTimelineTimebar::RollbackTimeChange()
+{
+}
+
+::CColor CEmptyTimelineTimebar::GetTimebarColor()
+{
+ return CStudioPreferences::GetObjectTimebarColor();
+}
+
+void CEmptyTimelineTimebar::SetTimebarColor(const ::CColor &inColor)
+{
+ Q_UNUSED(inColor);
+}
+
+Q3DStudio::CString CEmptyTimelineTimebar::GetTimebarComment()
+{
+ return "";
+}
+
+void CEmptyTimelineTimebar::SetTimebarComment(const Q3DStudio::CString &inComment)
+{
+ Q_UNUSED(inComment);
+}
+
+void CEmptyTimelineTimebar::SetTimebarTime(ITimeChangeCallback *inCallback /*= nullptr*/)
+{
+ Q_UNUSED(inCallback);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.h
new file mode 100644
index 00000000..9aacb524
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/EmptyTimelineTimebar.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#pragma once
+
+#include "ITimelineTimebar.h"
+
+//=============================================================================
+/**
+ * The current timeline UI design is such that even when no timebar shows up ( with the exception of
+ * the top row, ie the time context )
+ * there is a timebar control to store the keyframes for the animated properties.
+ * Hence, instead of return nullptr for GetTimebar for ITimelineItem, this class will ensure the UI
+ * classes still work.
+ */
+class CEmptyTimelineTimebar : public ITimelineTimebar
+{
+public:
+ CEmptyTimelineTimebar();
+ virtual ~CEmptyTimelineTimebar();
+
+ // ITimelineTimebar
+ long GetStartTime() const override;
+ long GetEndTime() const override;
+ long GetDuration() const override;
+ bool ShowHandleBars() const override;
+ void OnBeginDrag() override;
+ void OffsetTime(long inDiff) override;
+ void ChangeTime(long inTime, bool inSetStart) override;
+ void CommitTimeChange() override;
+ void RollbackTimeChange() override;
+ ::CColor GetTimebarColor() override;
+ void SetTimebarColor(const ::CColor &inColor) override;
+ Q3DStudio::CString GetTimebarComment() override;
+ void SetTimebarComment(const Q3DStudio::CString &inComment) override;
+ void SetTimebarTime(ITimeChangeCallback *inCallback = nullptr) override;
+};
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.cpp
new file mode 100644
index 00000000..322cbd33
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "GroupTimelineItemBinding.h"
+#include "BaseStateRow.h"
+#include "TimelineTranslationManager.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "Dialogs.h"
+
+// Data model specific
+#include "Doc.h"
+#include "CmdGeneric.h"
+
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+#include "UICDMDataCore.h"
+#include "UICFileTools.h"
+
+using namespace UICDM;
+
+CGroupTimelineItemBinding::CGroupTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+{
+}
+
+//=============================================================================
+/**
+ * Ideally we like to be able to edit the component in a different editor ( we've been hoping for
+ * that feature ) BUT we don't have that,
+ * and it has always been we 'dive' into the component within Studio.
+ */
+bool CGroupTimelineItemBinding::OpenAssociatedEditor()
+{
+ if (GetObjectType() == OBJTYPE_COMPONENT) {
+ ISlideSystem *theSlideSystem = m_StudioSystem->GetSlideSystem();
+
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ Q3DStudio::CId theId = m_StudioSystem->GetClientDataModelBridge()->GetGUID(theInstance);
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theId));
+
+ if (theMasterSlide.Valid()) {
+ CUICDMSlideHandle theActiveSlide = theSlideSystem->GetActiveSlide(theMasterSlide);
+
+ CCmd *theCmd = new CCmdGeneric<CDoc, CUICDMSlideHandle>(
+ m_TransMgr->GetDoc(), &CDoc::NotifyActiveSlideChanged,
+ &CDoc::NotifyActiveSlideChanged, theActiveSlide, NULL, "");
+ theCmd->SetUndoable(false);
+ theCmd->SetModifiedFlag(false);
+ m_TransMgr->GetDoc()->GetCore()->ExecuteCommand(theCmd, false);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool CGroupTimelineItemBinding::IsImported() const
+{
+
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetDoc()->GetStudioSystem()->GetPropertySystem();
+ UICDM::SValue theValue;
+ if (thePropertySystem->GetInstancePropertyValue(theInstance, m_TransMgr->GetDoc()
+ ->GetStudioSystem()
+ ->GetClientDataModelBridge()
+ ->GetSourcePathProperty(),
+ theValue)) {
+ UICDM::TDataStrPtr theSrcPath(UICDM::get<UICDM::TDataStrPtr>(theValue));
+ Q3DStudio::CFilePath theFilePath(theSrcPath->GetData());
+ if (theFilePath.GetExtension() == CDialogs::GetWideImportFileExtension())
+ return true;
+ }
+ // If it is, check to be sure that
+ // we can get to the import file.
+ // If we can, then we are imported.
+ return false;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.h
new file mode 100644
index 00000000..a9462c1c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/GroupTimelineItemBinding.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_GROUP_TIMELINEITEM_BINDING_H
+#define INCLUDED_GROUP_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class ITimelineItem;
+class CTimelineTranslationManager;
+class CBaseStateRow;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Group type
+ */
+class CGroupTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public:
+ CGroupTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ ~CGroupTimelineItemBinding() {}
+
+ // CUICDMTimelineItemBinding
+ bool OpenAssociatedEditor() override;
+ bool IsImported() const override;
+};
+
+#endif // INCLUDED_GROUP_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/IKeyframeSelector.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/IKeyframeSelector.h
new file mode 100644
index 00000000..db8b551f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/IKeyframeSelector.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_IKEYFRAME_SELECTOR_H
+#define INCLUDED_IKEYFRAME_SELECTOR_H 1
+
+#pragma once
+
+//=============================================================================
+/**
+ * Interface that performs keyframe selection.
+ */
+//=============================================================================
+class IKeyframeSelector
+{
+public:
+ virtual ~IKeyframeSelector() {}
+
+ //=============================================================================
+ /**
+ * @param inTime -1 to selected (or deselect) ALL keyframes, otherwise only by time.
+ */
+ virtual void SelectKeyframes(bool inSelected, long inTime = -1) = 0;
+};
+
+#endif // INCLUDED_IKEYFRAME_SELECTOR_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItem.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItem.h
new file mode 100644
index 00000000..e5af8671
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItem.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_ITIMELINE_ITEM_H
+#define INCLUDED_ITIMELINE_ITEM_H 1
+
+#pragma once
+
+#include "INamable.h"
+#include "StudioObjectTypes.h"
+
+class ITimelineTimebar;
+
+//=============================================================================
+/**
+ * Abstraction of a data model item in the Scene. This might end up deriving from a more generic
+ * interface, so that common
+ * functions can be generalized for items in the different palettes.
+ */
+//=============================================================================
+class ITimelineItem : public INamable
+{
+public:
+ virtual ~ITimelineItem() {}
+
+ virtual EStudioObjectType GetObjectType() const = 0;
+ virtual bool IsMaster() const = 0;
+
+ virtual bool IsShy() const = 0;
+ virtual void SetShy(bool) = 0;
+ virtual bool IsLocked() const = 0;
+ virtual void SetLocked(bool) = 0;
+ virtual bool IsVisible() const = 0;
+ virtual void SetVisible(bool) = 0;
+ virtual bool IsExpanded() const = 0;
+ virtual void SetExpanded(bool) = 0;
+ virtual bool IsImported() const { return false; }
+
+ // Actions
+ virtual bool HasAction(bool inMaster) = 0;
+ virtual bool ChildrenHasAction(bool inMaster) = 0;
+ virtual bool ComponentHasAction(bool inMaster) = 0;
+
+ virtual ITimelineTimebar *GetTimebar() = 0;
+};
+
+#endif // INCLUDED_ITIMELINE_ITEM_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h
new file mode 100644
index 00000000..d251f530
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_ITIMELINE_ITEM_BINDINGS_H
+#define INCLUDED_ITIMELINE_ITEM_BINDINGS_H 1
+
+#pragma once
+
+#include "ITimelineItem.h"
+#include "ITimelineItemProperty.h"
+#include "IKeyframeSelector.h"
+#include "SIterator.h"
+
+class CBaseStateRow;
+class CControlWindowListener;
+class ITimelineKeyframesManager;
+
+// Data model specific ??
+class CDropTarget;
+
+class ITimelineItemKeyframesHolder
+{
+public:
+ virtual ~ITimelineItemKeyframesHolder() {}
+
+ virtual void InsertKeyframe() = 0;
+ virtual void DeleteAllChannelKeyframes() = 0;
+ virtual long GetKeyframeCount() const = 0;
+ virtual IKeyframe *GetKeyframeByTime(long inTime) const = 0;
+ virtual IKeyframe *GetKeyframeByIndex(long inIndex) const = 0;
+ virtual long OffsetSelectedKeyframes(long inOffset) = 0;
+ virtual void CommitChangedKeyframes() = 0;
+ virtual void OnEditKeyframeTime(long inCurrentTime, long inObjectAssociation) = 0;
+};
+
+//=============================================================================
+/**
+ * Interface to encapsulate data model specific functions, that Timeline UI objects can talk to.
+ */
+//=============================================================================
+class ITimelineItemBinding : public ITimelineItemKeyframesHolder, public IKeyframeSelector
+{
+public:
+ // List of possible transactions that requires querying the data model if they are valid
+ enum EUserTransaction {
+ EUserTransaction_None,
+ EUserTransaction_Rename,
+ EUserTransaction_Duplicate,
+ EUserTransaction_Cut,
+ EUserTransaction_Copy,
+ EUserTransaction_Paste,
+ EUserTransaction_Delete,
+ EUserTransaction_MakeComponent,
+ EUserTransaction_EditComponent,
+ };
+
+public:
+ virtual ~ITimelineItemBinding() {}
+
+ virtual ITimelineItem *GetTimelineItem() = 0;
+ virtual CBaseStateRow *GetRow() = 0;
+
+ // Events
+ virtual void SetSelected(bool multiSelect) = 0;
+ virtual void OnCollapsed() = 0;
+ virtual void ClearKeySelection() = 0;
+ virtual bool OpenAssociatedEditor() = 0;
+ virtual void DoStartDrag(CControlWindowListener *inWndListener) = 0;
+ virtual void SetDropTarget(CDropTarget *inTarget) = 0;
+
+ // Hierarchy
+ virtual long GetChildrenCount() = 0;
+ virtual ITimelineItemBinding *GetChild(long inIndex) = 0;
+ virtual ITimelineItemBinding *GetParent() = 0;
+ virtual void SetParent(ITimelineItemBinding *parent) = 0;
+ // Properties
+ virtual long GetPropertyCount() = 0;
+ virtual ITimelineItemProperty *GetProperty(long inIndex) = 0;
+
+ // Eye/Lock toggles
+ virtual bool ShowToggleControls() const = 0;
+ virtual bool IsLockedEnabled() const = 0;
+ virtual bool IsVisibleEnabled() const = 0;
+
+ // Init/Cleanup
+ virtual void Bind(CBaseStateRow *inRow) = 0;
+ virtual void Release() = 0;
+
+ // ContextMenu
+ virtual bool IsValidTransaction(EUserTransaction inTransaction) = 0;
+ virtual void PerformTransaction(EUserTransaction inTransaction) = 0;
+ virtual Q3DStudio::CString GetObjectPath() = 0;
+
+ virtual bool IsExternalizeable() { return false; }
+ virtual void Externalize() {}
+ virtual bool IsInternalizeable() { return false; }
+ virtual void Internalize() {}
+
+ // Selected keyframes
+ virtual ITimelineKeyframesManager *GetKeyframesManager() const = 0;
+
+ // Properties
+ virtual void RemoveProperty(ITimelineItemProperty *inProperty) = 0;
+ virtual void LoadProperties() = 0;
+};
+
+//=============================================================================
+/**
+ * Helper iterator class that iterates over a ITimeline's children in a ordered (priority) list.
+ */
+//=============================================================================
+class CTimelineItemOrderedIterator : public CSIterator<ITimelineItemBinding *>
+{
+public:
+ CTimelineItemOrderedIterator(ITimelineItemBinding *inRootTimelineItem)
+ {
+ m_RootTimelineItem = inRootTimelineItem;
+ Reset();
+ }
+ bool IsDone() override { return (m_Index >= m_Total); }
+ void operator++() override { m_Index++; }
+ void operator+=(const long inNumToInc) override { m_Index += inNumToInc; }
+ ITimelineItemBinding *GetCurrent() override { return m_RootTimelineItem->GetChild(m_Index); }
+ virtual void Reset()
+ {
+ m_Index = 0;
+ m_Total = m_RootTimelineItem->GetChildrenCount();
+ }
+
+protected:
+ ITimelineItemBinding *m_RootTimelineItem;
+ long m_Index;
+ long m_Total;
+};
+
+//=============================================================================
+/**
+ * Helper iterator class that iterates over a ITimeline's properties
+ */
+//=============================================================================
+class CTimelineItemPropertyIterator : public CSIterator<ITimelineItemProperty *>
+{
+public:
+ CTimelineItemPropertyIterator(ITimelineItemBinding *inTimelineItem)
+ {
+ m_TimelineItem = inTimelineItem;
+ Reset();
+ }
+ bool IsDone() override { return (m_Index >= m_Total); }
+ void operator++() override { m_Index++; }
+ void operator+=(const long inNumToInc) override { m_Index += inNumToInc; }
+ ITimelineItemProperty *GetCurrent() override { return m_TimelineItem->GetProperty(m_Index); }
+ virtual void Reset()
+ {
+ m_Index = 0;
+ m_Total = m_TimelineItem->GetPropertyCount();
+ }
+
+protected:
+ ITimelineItemBinding *m_TimelineItem;
+ long m_Index;
+ long m_Total;
+};
+
+#endif // INCLUDED_ITIMELINE_ITEM_BINDINGS_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemProperty.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemProperty.h
new file mode 100644
index 00000000..c241ebfa
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemProperty.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_ITIMELINE_ITEM_PROPERTY_H
+#define INCLUDED_ITIMELINE_ITEM_PROPERTY_H 1
+
+#pragma once
+
+#include "IKeyframeSelector.h"
+#include "UICDMMetaData.h"
+#include "UICString.h"
+
+class CPropertyRow;
+class IKeyframe;
+class ITimelineKeyframesManager;
+
+//=============================================================================
+/**
+ * Abstraction of a data model item's property that is displayed in the Timeline.
+ */
+//=============================================================================
+class ITimelineItemProperty : public IKeyframeSelector
+{
+public:
+ virtual ~ITimelineItemProperty() {}
+
+ virtual Q3DStudio::CString GetName() const = 0;
+ virtual bool IsMaster() const = 0;
+ virtual UICDM::TDataTypePair GetType() const = 0;
+ virtual float GetMaximumValue() const = 0;
+ virtual float GetMinimumValue() const = 0;
+
+ virtual void SetSelected() = 0;
+ virtual void ClearKeySelection() = 0;
+ virtual void DeleteAllKeys() = 0;
+
+ virtual void Bind(CPropertyRow *inRow) = 0;
+ virtual void Release() = 0;
+ virtual CPropertyRow *GetRow() = 0;
+
+ // Keyframes
+ virtual ITimelineKeyframesManager *GetKeyframesManager() const = 0;
+ virtual IKeyframe *GetKeyframeByTime(long inTime) const = 0;
+ virtual IKeyframe *GetKeyframeByIndex(long inIndex) const = 0;
+ virtual long GetKeyframeCount() const = 0;
+ virtual long GetChannelCount() const = 0;
+ virtual float GetChannelValueAtTime(long inChannelIndex, long inTime) = 0;
+ virtual void SetChannelValueAtTime(long inChannelIndex, long inTime, float inValue) = 0;
+ virtual long OffsetSelectedKeyframes(long inOffset) = 0;
+ virtual void CommitChangedKeyframes() = 0;
+ virtual void OnEditKeyframeTime(long inCurrentTime, long inObjectAssociation) = 0;
+ virtual bool IsDynamicAnimation() = 0;
+};
+
+#endif // INCLUDED_ITIMELINE_ITEM_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineKeyframesManager.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineKeyframesManager.h
new file mode 100644
index 00000000..e1a6914f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineKeyframesManager.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_ITIMELINE_KEYFRAMES_MANAGER_H
+#define INCLUDED_ITIMELINE_KEYFRAMES_MANAGER_H 1
+
+#pragma once
+
+#include "IKeyframesManager.h"
+
+//=============================================================================
+/**
+ * Interface to manage keyframes related actions in the Timeline
+ */
+//=============================================================================
+class ITimelineKeyframesManager : public IKeyframesManager
+{
+public:
+ virtual ~ITimelineKeyframesManager() {}
+
+ virtual void SetKeyframeTime(long inTime) = 0;
+ virtual void SetKeyframesDynamic(bool inDynamic) = 0;
+ virtual long OffsetSelectedKeyframes(long inOffset) = 0;
+ virtual bool CanMakeSelectedKeyframesDynamic() = 0;
+ virtual void CommitChangedKeyframes() = 0;
+ virtual void RollbackChangedKeyframes() = 0;
+};
+
+#endif // INCLUDED_IKEYFRAMES_MANAGER_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineTimebar.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineTimebar.h
new file mode 100644
index 00000000..dbeefb85
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineTimebar.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_ITIMELINE_TIMEBAR_H
+#define INCLUDED_ITIMELINE_TIMEBAR_H 1
+
+#pragma once
+
+#include "UICString.h"
+
+class ITimeChangeCallback;
+
+class CColor;
+
+//=============================================================================
+/**
+ * Interface for a Timebar
+ */
+//=============================================================================
+class ITimelineTimebar
+{
+public:
+ virtual ~ITimelineTimebar() {}
+
+ virtual long GetStartTime() const = 0;
+ virtual long GetEndTime() const = 0;
+ virtual long GetDuration() const = 0;
+ virtual bool ShowHandleBars() const = 0;
+ //=============================================================================
+ /**
+ * TODO: consider refactor. drag&drop specfics should not be in the Data Model.
+ */
+ virtual void OnBeginDrag() = 0;
+ //
+ virtual void OffsetTime(long inDiff) = 0;
+ // Change the start time or the end time of the timebar. inTime: time to change to, inSetStart:
+ // true to set start time, false to set end time.
+ virtual void ChangeTime(long inTime, bool inSetStart) = 0;
+ virtual void CommitTimeChange() = 0;
+ virtual void RollbackTimeChange() = 0;
+ //
+ virtual CColor GetTimebarColor() = 0;
+ virtual void SetTimebarColor(const CColor &inColor) = 0;
+ virtual Q3DStudio::CString GetTimebarComment() = 0;
+ virtual void SetTimebarComment(const Q3DStudio::CString &inComment) = 0;
+ virtual void SetTimebarTime(ITimeChangeCallback *inCallback = nullptr) = 0;
+};
+
+#endif // INCLUDED_ITIMELINE_TIMEBAR_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.cpp
new file mode 100644
index 00000000..bf41f00d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ImageTimelineItemBinding.h"
+#include "TimelineTranslationManager.h"
+#include "UICDMHandles.h"
+#include "BaseStateRow.h"
+#include "Doc.h"
+#include "IObjectReferenceHelper.h"
+#include "EmptyTimelineTimebar.h"
+
+using namespace UICDM;
+
+CImageTimelineItemBinding::CImageTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+{
+}
+
+CImageTimelineItemBinding::~CImageTimelineItemBinding()
+{
+}
+
+ITimelineTimebar *CImageTimelineItemBinding::GetTimebar()
+{ // No timebars on images
+ return new CEmptyTimelineTimebar();
+}
+
+Q3DStudio::CString CImageTimelineItemBinding::GetName() const
+{
+ return m_Name;
+}
+
+void CImageTimelineItemBinding::SetName(const Q3DStudio::CString &inName)
+{
+ m_Name = inName;
+}
+
+EStudioObjectType CImageTimelineItemBinding::GetObjectType() const
+{
+ return OBJTYPE_IMAGE;
+}
+
+bool CImageTimelineItemBinding::ShowToggleControls() const
+{
+ // no toggle controls, by design
+ return false;
+}
+
+void CImageTimelineItemBinding::Bind(CBaseStateRow *inRow)
+{
+ CUICDMTimelineItemBinding::Bind(inRow);
+ GetRow()->SetNameReadOnly(true);
+}
+
+//=============================================================================
+/**
+ * Open the associated item as though it was double-clicked in explorer
+ */
+bool CImageTimelineItemBinding::OpenAssociatedEditor()
+{
+ return OpenSourcePathFile();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.h
new file mode 100644
index 00000000..2c27dd2d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ImageTimelineItemBinding.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_IMAGE_TIMELINEITEM_BINDING_H
+#define INCLUDED_IMAGE_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CTimelineTranslationManager;
+class CBaseStateRow;
+class ITimelineTimebar;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Image type
+ */
+class CImageTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public:
+ CImageTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ virtual ~CImageTimelineItemBinding();
+
+ // CUICDMTimelineItemBinding
+ ITimelineTimebar *GetTimebar() override;
+ Q3DStudio::CString GetName() const override;
+ void SetName(const Q3DStudio::CString &inName) override;
+ EStudioObjectType GetObjectType() const override;
+ bool ShowToggleControls() const override;
+ void Bind(CBaseStateRow *inRow) override;
+ bool OpenAssociatedEditor() override;
+
+ void SetPropertyHandle(UICDM::CUICDMPropertyHandle inProperty)
+ {
+ m_PropertyHandle = inProperty;
+ }
+ UICDM::CUICDMPropertyHandle GetPropertyHandle() const { return m_PropertyHandle; }
+
+protected:
+ Q3DStudio::CString m_Name;
+ UICDM::CUICDMPropertyHandle m_PropertyHandle;
+};
+
+#endif // INCLUDED_IMAGE_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.cpp
new file mode 100644
index 00000000..a4adefbc
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.cpp
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+#include "KeyframesManager.h"
+#include "IDoc.h"
+#include "TimeEditDlg.h"
+#include "TimelineTranslationManager.h"
+#include "UICDMTimelineKeyframe.h"
+#include "UICDMTimelineItemBinding.h"
+#include "CmdDataModelRemoveKeyframe.h"
+#include "CmdDataModelInsertKeyframe.h"
+#include "CmdDataModelChangeKeyframe.h"
+#include "UICDMAnimation.h"
+#include "ClientDataModelBridge.h"
+#include "PasteKeyframesCommandHelper.h"
+#include "IDocumentEditor.h"
+#include "IKeyframe.h"
+#include "Dispatch.h"
+#include "StudioPreferences.h"
+
+#include "StudioApp.h" //for CommitCurrentCommand
+#include "Core.h"
+#include "Dialogs.h"
+
+using namespace UICDM;
+
+bool SortKeyframeInstancePairByTime(const CKeyframesManager::SKeyframeInstancePair &inLHS,
+ const CKeyframesManager::SKeyframeInstancePair &inRHS)
+{
+ return inLHS.m_Keyframe->GetTime() < inRHS.m_Keyframe->GetTime();
+}
+
+//==============================================================================
+// Keyframe specific.
+// UICDM selection is handled by CTimelineTranslationManager.
+//==============================================================================
+CKeyframesManager::CKeyframesManager(CTimelineTranslationManager *inTransMgr)
+ : m_TransMgr(inTransMgr)
+ , m_OffsetKeyframeCommandHelper(*(g_StudioApp.GetCore()->GetDoc()))
+ , m_PasteKeyframeCommandHelper(nullptr)
+{
+ g_StudioApp.GetCore()->GetDoc()->SetKeyframesManager(this);
+}
+
+CKeyframesManager::~CKeyframesManager()
+{
+ delete m_PasteKeyframeCommandHelper;
+}
+
+bool CKeyframesManager::HasSelectedKeyframes(bool inOnlyDynamic /*= false */)
+{
+ // specifically only to know if there are any selected keyframes that are dynamic
+ if (inOnlyDynamic) {
+ for (size_t theIndex = 0; theIndex < m_SelectedKeyframes.size(); ++theIndex)
+ if (m_SelectedKeyframes[theIndex].m_Keyframe->IsDynamic())
+ return true;
+
+ return false;
+ }
+
+ bool theRetVal = !m_SelectedKeyframes.empty();
+
+ return theRetVal;
+}
+
+bool CKeyframesManager::CanPerformKeyframeCopy()
+{
+ bool theCanCopyNewData = false;
+ // Legacy system actually prevents copy/pasting between different instances, so let's preserve
+ // that
+ if (!m_SelectedKeyframes.empty()) {
+ theCanCopyNewData = true;
+ if (m_SelectedKeyframes.size() > 1) {
+ CUICDMTimelineItemBinding *theInstance = m_SelectedKeyframes[0].m_Instance;
+ TSelectedKeyframeList::iterator theIter = m_SelectedKeyframes.begin();
+ ++theIter;
+ for (; theIter != m_SelectedKeyframes.end() && theCanCopyNewData; ++theIter) {
+ if (theIter->m_Instance != theInstance) // fail!
+ theCanCopyNewData = false;
+ }
+ }
+ }
+ return theCanCopyNewData;
+}
+
+bool CKeyframesManager::CanPerformKeyframePaste()
+{
+ if (m_PasteKeyframeCommandHelper && m_PasteKeyframeCommandHelper->HasCopiedKeyframes()) {
+ UICDM::CUICDMInstanceHandle theSelectedInstance =
+ g_StudioApp.GetCore()->GetDoc()->GetSelectedInstance();
+ if (theSelectedInstance.Valid()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void CKeyframesManager::CopyKeyframes()
+{
+ CopySelectedKeyframes();
+}
+
+// legacy stuff that we have to support for animation tracks in the old data model to work
+inline void PostExecuteCommand(IDoc *inDoc)
+{
+ CDoc *theDoc = dynamic_cast<CDoc *>(inDoc);
+ theDoc->GetCore()->CommitCurrentCommand();
+ // fire render event.
+ // theDoc->UpdateClientScene( true );
+}
+
+//@param inPerformCopy true if that is a copy/cut command. false if this is a delete.
+// Note: Keyframes are never explicitly copied to the clipboard (only as part of a asset copy),
+// hence that means that the keyframes (only) are never copied across different instances of studio.
+bool CKeyframesManager::RemoveKeyframes(bool inPerformCopy)
+{
+ bool theRetVal = HasSelectedKeyframes();
+
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+
+ if (inPerformCopy) // copy prior to removing the keyframes
+ CopySelectedKeyframes();
+
+ CCmdDataModelRemoveKeyframe *theCmd = nullptr;
+ if (!m_SelectedKeyframes.empty()) {
+ TSelectedKeyframeList::iterator theKeyIter = m_SelectedKeyframes.begin();
+ for (; theKeyIter != m_SelectedKeyframes.end(); ++theKeyIter) {
+ CUICDMTimelineKeyframe::TKeyframeHandleList theKeyframeHandles;
+ theKeyIter->m_Keyframe->GetKeyframeHandles(theKeyframeHandles);
+ ASSERT(!theKeyframeHandles.empty());
+ CUICDMTimelineKeyframe::TKeyframeHandleList::iterator theIter =
+ theKeyframeHandles.begin();
+ if (!theCmd) {
+ theCmd = new CCmdDataModelRemoveKeyframe(theDoc, *theIter);
+ ++theIter;
+ }
+ for (; theIter != theKeyframeHandles.end(); ++theIter)
+ theCmd->AddKeyframeHandle(*theIter);
+ }
+ }
+
+ if (theCmd) {
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ PostExecuteCommand(theDoc);
+ }
+ return theRetVal;
+}
+
+// note: we can't paste data from old data model system to the new one, and vice versa. so either
+// the old Or the new system succeeds in pasting, never both.
+void CKeyframesManager::PasteKeyframes()
+{
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+
+ if (m_PasteKeyframeCommandHelper && m_PasteKeyframeCommandHelper->HasCopiedKeyframes()) {
+ UICDM::CUICDMInstanceHandle theSelectedInstance = theDoc->GetSelectedInstance();
+ if (theSelectedInstance.Valid()) {
+ long theCurrentViewTimeInMilliseconds = theDoc->GetCurrentViewTime();
+ CCmdDataModelInsertKeyframe *theInsertKeyframesCommand =
+ m_PasteKeyframeCommandHelper->GetCommand(theDoc, theCurrentViewTimeInMilliseconds,
+ theSelectedInstance);
+ if (theInsertKeyframesCommand)
+ g_StudioApp.GetCore()->ExecuteCommand(theInsertKeyframesCommand);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Sets interpolation values of all selected keyframes to the values specified
+ * by the user. Pops up a dialog prompting the user to choose new ease in and
+ * ease out values. Values in the dialog are initialized to the left-most
+ * selected keyframe's interpolation values.
+ */
+void CKeyframesManager::SetKeyframeInterpolation()
+{
+ if (!HasSelectedKeyframes())
+ return;
+
+ float theEaseIn = 0;
+ float theEaseOut = 0;
+ if (CStudioPreferences::GetInterpolation())
+ theEaseIn = theEaseOut = 100;
+
+ IAnimationCore *theAnimationCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+
+ if (!m_SelectedKeyframes.empty()) // this is a sorted list, so we only need to grab tge ease
+ // in/out values from the first item in this list.
+ {
+ CUICDMTimelineKeyframe *theTimelineKeyframe = m_SelectedKeyframes.front().m_Keyframe;
+ CUICDMTimelineKeyframe::TKeyframeHandleList theKeyframeHandles;
+ theTimelineKeyframe->GetKeyframeHandles(theKeyframeHandles);
+ TKeyframe theKeyframeData = theAnimationCore->GetKeyframeData(theKeyframeHandles[0]);
+ GetEaseInOutValues(theKeyframeData, theEaseIn, theEaseOut);
+ }
+
+ if (g_StudioApp.GetDialogs()->PromptForKeyframeInterpolation(theEaseIn, theEaseOut)) {
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ Q3DStudio::ScopedDocumentEditor editor(*theDoc, L"Set Keyframe Interpolation", __FILE__,
+ __LINE__);
+ TSelectedKeyframeList::iterator theKeyIter = m_SelectedKeyframes.begin();
+ for (; theKeyIter != m_SelectedKeyframes.end(); ++theKeyIter) {
+ CUICDMTimelineKeyframe *theTimelineKeyframe = theKeyIter->m_Keyframe;
+ CUICDMTimelineKeyframe::TKeyframeHandleList theKeyframeHandles;
+ theTimelineKeyframe->GetKeyframeHandles(theKeyframeHandles);
+ for (size_t i = 0; i < theKeyframeHandles.size(); ++i) {
+ TKeyframe theKeyframeData =
+ theAnimationCore->GetKeyframeData(theKeyframeHandles[i]);
+ SetEaseInOutValues(theKeyframeData, theEaseIn, theEaseOut);
+ theAnimationCore->SetKeyframeData(theKeyframeHandles[i], theKeyframeData);
+ }
+ }
+ }
+}
+
+bool CKeyframesManager::HasDynamicKeyframes()
+{
+ CUICDMTimelineItemBinding *theBinding = m_TransMgr->GetSelectedBinding();
+ if (theBinding) {
+ return theBinding->HasDynamicKeyframes(-1);
+ }
+ return false;
+}
+
+void CKeyframesManager::SelectAllKeyframes()
+{
+ ITimelineItemBinding *theBinding = m_TransMgr->GetSelectedBinding();
+ if (theBinding)
+ theBinding->SelectKeyframes(true);
+}
+
+void CKeyframesManager::DeselectAllKeyframes()
+{
+ m_TransMgr->ClearBindingsKeyframeSelection();
+ m_SelectedKeyframes.clear();
+}
+
+//==============================================================================
+/**
+ * Sets keyframes on all the changed properties of the selected object.
+ * Also known as autoset keyframes, but it only applies to one object, and is
+ * the result of an F6 key press. Tells the TimelineCtrl to autoset keyframes.
+ */
+void CKeyframesManager::SetChangedKeyframes()
+{
+
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ UICDM::CUICDMInstanceHandle theSelectedInstance = theDoc->GetSelectedInstance();
+ if (theSelectedInstance.Valid()) {
+ using namespace Q3DStudio;
+ Q3DStudio::ScopedDocumentEditor editor(*theDoc, L"Set Changed Keyframes", __FILE__,
+ __LINE__);
+ CStudioSystem *theStudioSystem = theDoc->GetStudioSystem();
+ // Get all animated properties.
+ TPropertyHandleList theProperties;
+ theStudioSystem->GetPropertySystem()->GetAggregateInstanceProperties(theSelectedInstance,
+ theProperties);
+ for (size_t thePropertyIndex = 0; thePropertyIndex < theProperties.size();
+ ++thePropertyIndex) {
+ if (theStudioSystem->GetAnimationSystem()->IsPropertyAnimated(
+ theSelectedInstance, theProperties[thePropertyIndex]))
+ editor->KeyframeProperty(theSelectedInstance, theProperties[thePropertyIndex],
+ true);
+ }
+ }
+}
+
+void CKeyframesManager::SetKeyframeTime(long inTime)
+{
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.SetKeyframesManager(this);
+ theTimeEditDlg.ShowDialog(inTime, 0, g_StudioApp.GetCore()->GetDoc(), ASSETKEYFRAME);
+}
+
+void CKeyframesManager::SetKeyframeDynamic(CUICDMTimelineKeyframe *inKeyframe, bool inDynamic)
+{
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ UICDM::TKeyframeHandleList theKeyframeHandle;
+ CCmdDataModelChangeDynamicKeyframe *theCmd = nullptr;
+
+ if (inKeyframe != nullptr)
+ inKeyframe->GetKeyframeHandles(theKeyframeHandle);
+
+ UICDM::IAnimationCore *theAnimationCore = theDoc->GetStudioSystem()->GetAnimationCore();
+ for (size_t theKeyframe = 0; theKeyframe < theKeyframeHandle.size(); ++theKeyframe) {
+ UICDM::CUICDMAnimationHandle theAnimation(
+ theAnimationCore->GetAnimationForKeyframe(theKeyframeHandle.at(theKeyframe)));
+ if (!theCmd)
+ theCmd = new CCmdDataModelChangeDynamicKeyframe(theDoc, theAnimation, inDynamic);
+ else
+ theCmd->AddHandle(theAnimation);
+ }
+
+ if (theCmd)
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+}
+
+void CKeyframesManager::SetKeyframesDynamic(bool inDynamic)
+{
+
+ CUICDMTimelineKeyframe *theKeyframe;
+
+ if (m_SelectedKeyframes.size() == 0) {
+ CUICDMTimelineItemBinding *theBinding = m_TransMgr->GetSelectedBinding();
+ IKeyframe *key = theBinding->GetKeyframeByIndex(0);
+ theKeyframe = dynamic_cast<CUICDMTimelineKeyframe *>(key);
+ SetKeyframeDynamic(theKeyframe, inDynamic);
+ } else {
+ for (int i = 0; i < (int)m_SelectedKeyframes.size(); ++i) {
+ theKeyframe = m_SelectedKeyframes[i].m_Keyframe;
+ SetKeyframeDynamic(theKeyframe, inDynamic);
+ }
+ }
+}
+
+long CKeyframesManager::OffsetSelectedKeyframes(long inOffset)
+{
+ m_InstanceSet.clear();
+ m_InstanceList.clear();
+ std::set<CUICDMTimelineItemBinding *> &theInstances(m_InstanceSet);
+
+ TSelectedKeyframeList::iterator theKeyIter = m_SelectedKeyframes.begin();
+ for (; theKeyIter != m_SelectedKeyframes.end(); ++theKeyIter) {
+ // since this list is sorted by time and we are iterating from the first in the list
+ long theKeyframeTime = theKeyIter->m_Keyframe->GetTime();
+ if (inOffset < 0 && theKeyframeTime + inOffset < 0)
+ inOffset = -theKeyframeTime;
+
+ theKeyIter->m_Keyframe->UpdateKeyframesTime(&m_OffsetKeyframeCommandHelper,
+ theKeyframeTime + inOffset);
+
+ // this contains unique instancs, i.e. mulitple keyframe can map to the same instances
+ if (theInstances.insert(theKeyIter->m_Instance).second)
+ m_InstanceList.push_back(theKeyIter->m_Instance->GetInstance());
+ }
+
+ // UI update, explicitly because this doesn't generate any events till action is committed
+ std::set<CUICDMTimelineItemBinding *>::iterator theInstanceIter = theInstances.begin();
+ for (; theInstanceIter != theInstances.end(); ++theInstanceIter)
+ (*theInstanceIter)->UIRefreshPropertyKeyframe(inOffset);
+
+ if (m_InstanceList.size())
+ m_TransMgr->GetDoc()->GetCore()->GetDispatch()->FireImmediateRefreshInstance(
+ &m_InstanceList[0], (long)m_InstanceList.size());
+
+ // by contract, this functions returns the "legal" offset, ie time cannot be offset to negative.
+ return inOffset;
+}
+
+void CKeyframesManager::CommitChangedKeyframes()
+{
+ m_OffsetKeyframeCommandHelper.Finalize();
+}
+
+void CKeyframesManager::RollbackChangedKeyframes()
+{
+ m_OffsetKeyframeCommandHelper.Rollback();
+}
+
+bool CKeyframesManager::CanMakeSelectedKeyframesDynamic()
+{
+ using namespace UICDM;
+ TKeyframeHandleList theKeyframes;
+ TKeyframeHandleList allTheKeyframes;
+ IAnimationCore &theAnimationCore(
+ *g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetAnimationCore());
+ // Ensure that all keyframes selected are the first keyframes from the animation track.
+ for (size_t idx = 0, end = m_SelectedKeyframes.size(); idx < end; ++idx) {
+ theKeyframes.clear();
+ m_SelectedKeyframes.at(idx).m_Keyframe->GetKeyframeHandles(theKeyframes);
+ for (size_t specificKeyframeIdx = 0, specificKeyframeEnd = theKeyframes.size();
+ specificKeyframeIdx < specificKeyframeEnd; ++specificKeyframeIdx) {
+ CUICDMKeyframeHandle theKeyframe = theKeyframes[specificKeyframeIdx];
+ CUICDMAnimationHandle theAnimation =
+ theAnimationCore.GetAnimationForKeyframe(theKeyframe);
+ allTheKeyframes.clear();
+ theAnimationCore.GetKeyframes(theAnimation, allTheKeyframes);
+ if (allTheKeyframes[0] != theKeyframe)
+ return false;
+ }
+ }
+ return true;
+}
+
+// keeps track of selected keyframes so that we don't have to iterate through the entire hierarchy
+// to find them
+void CKeyframesManager::SetKeyframeSelected(CUICDMTimelineKeyframe *inKeyframe, bool inSelected,
+ CUICDMTimelineItemBinding *inOwningInstance /*= nullptr */)
+{
+ TSelectedKeyframeList::iterator theKeyIter = m_SelectedKeyframes.begin();
+ for (; theKeyIter != m_SelectedKeyframes.end(); ++theKeyIter) {
+ if (theKeyIter->m_Keyframe == inKeyframe)
+ break;
+ }
+ if (inSelected) {
+ ASSERT(inOwningInstance);
+ if (theKeyIter == m_SelectedKeyframes.end()) { // only this is not already selected
+ m_SelectedKeyframes.push_back(SKeyframeInstancePair(inKeyframe, inOwningInstance));
+ std::sort(m_SelectedKeyframes.begin(), m_SelectedKeyframes.end(),
+ SortKeyframeInstancePairByTime);
+ }
+ } else if (theKeyIter != m_SelectedKeyframes.end()) {
+ m_SelectedKeyframes.erase(theKeyIter);
+ }
+}
+
+UICDM::SGetOrSetKeyframeInfo SetupKeyframeInfo(UICDM::CUICDMKeyframeHandle inKeyframe,
+ UICDM::IAnimationCore &inCore)
+{
+ TKeyframe theKeyframeData = inCore.GetKeyframeData(inKeyframe);
+ SEaseInEaseOutKeyframe theKeyframe = UICDM::get<SEaseInEaseOutKeyframe>(theKeyframeData);
+ // Is this the first keyframe?
+ bool isDynamic = false;
+ if (inCore.IsFirstKeyframe(inKeyframe))
+ isDynamic = inCore.GetAnimationInfo(inCore.GetAnimationForKeyframe(inKeyframe))
+ .m_DynamicFirstKeyframe;
+
+ return SGetOrSetKeyframeInfo(theKeyframe.m_KeyframeValue, theKeyframe.m_EaseIn,
+ theKeyframe.m_EaseOut, isDynamic);
+}
+
+// only deal with this manager's selected keyframes
+void CKeyframesManager::CopySelectedKeyframes()
+{
+ if (!m_SelectedKeyframes.empty()) {
+ if (m_PasteKeyframeCommandHelper)
+ m_PasteKeyframeCommandHelper->Clear(); // clear out previously copied data
+ else
+ m_PasteKeyframeCommandHelper = new CPasteKeyframeCommandHelper();
+
+ // note: m_SelectedKeyframes is already sorted by time
+ float theEarliestKeyframeTimeInSecs =
+ CUICDMTimelineKeyframe::GetTimeInSecs(m_SelectedKeyframes[0].m_Keyframe->GetTime());
+
+ IAnimationCore *theAnimationCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+ TSelectedKeyframeList::iterator theIter = m_SelectedKeyframes.begin();
+ for (; theIter != m_SelectedKeyframes.end(); ++theIter) {
+ CUICDMTimelineKeyframe *theKeyframe = (*theIter).m_Keyframe;
+ CUICDMTimelineKeyframe::TKeyframeHandleList theKeyframeHandles;
+ theKeyframe->GetKeyframeHandles(theKeyframeHandles);
+ UICDM::SGetOrSetKeyframeInfo theInfos[3];
+ size_t theValidInfos = 0;
+ if (!theKeyframeHandles.empty()) {
+ // TODO: need to figure out a good way to convert from individual keyframes back to
+ // SValue
+ SValue theValue;
+ switch (theKeyframeHandles.size()) {
+ case 1: {
+ theInfos[0] = SetupKeyframeInfo(theKeyframeHandles[0], *theAnimationCore);
+ theValidInfos = 1;
+
+ } break;
+ case 3: {
+ theInfos[0] = SetupKeyframeInfo(theKeyframeHandles[0], *theAnimationCore);
+ theInfos[1] = SetupKeyframeInfo(theKeyframeHandles[1], *theAnimationCore);
+ theInfos[2] = SetupKeyframeInfo(theKeyframeHandles[2], *theAnimationCore);
+ theValidInfos = 3;
+ } break;
+ default: // not handled
+ break;
+ }
+ // time is relative to the earliest keyframe time.
+ float theRelativeTimeInSecs =
+ CUICDMTimelineKeyframe::GetTimeInSecs(theKeyframe->GetTime())
+ - theEarliestKeyframeTimeInSecs;
+
+ CUICDMAnimationHandle theAnimation =
+ theAnimationCore->GetAnimationForKeyframe(theKeyframeHandles[0]);
+ m_PasteKeyframeCommandHelper->AddKeyframeData(
+ theAnimationCore->GetAnimationInfo(theAnimation).m_Property,
+ theRelativeTimeInSecs, theInfos, theValidInfos);
+ }
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.h
new file mode 100644
index 00000000..61ac2740
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/KeyframesManager.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_KEYFRAMES_MANAGER_H
+#define INCLUDED_KEYFRAMES_MANAGER_H 1
+
+#pragma once
+
+#include "ITimelineKeyframesManager.h"
+#include "OffsetKeyframesCommandHelper.h"
+
+class CTimelineTranslationManager;
+class CUICDMTimelineKeyframe;
+class CUICDMTimelineItemBinding;
+class CPasteKeyframeCommandHelper;
+
+//=============================================================================
+/**
+ * Abstraction layer to the class that manages both selected keyframes.
+ */
+//=============================================================================
+class CKeyframesManager : public ITimelineKeyframesManager
+{
+public:
+ CKeyframesManager(CTimelineTranslationManager *inTransMgr);
+ virtual ~CKeyframesManager();
+
+ // IKeyframesManager
+ bool HasSelectedKeyframes(bool inOnlyDynamic = false) override;
+ bool HasDynamicKeyframes() override;
+ bool CanPerformKeyframeCopy() override;
+ bool CanPerformKeyframePaste() override;
+ void CopyKeyframes() override;
+ bool RemoveKeyframes(bool inPerformCopy) override;
+ void PasteKeyframes() override;
+ void SetKeyframeInterpolation() override;
+ void DeselectAllKeyframes() override;
+ void SelectAllKeyframes() override;
+ void SetChangedKeyframes() override;
+ // ITimelineKeyframesManager
+ void SetKeyframeTime(long inTime) override;
+ void SetKeyframesDynamic(bool inDynamic) override;
+ bool CanMakeSelectedKeyframesDynamic() override;
+ long OffsetSelectedKeyframes(long inOffset) override;
+ void CommitChangedKeyframes() override;
+ void RollbackChangedKeyframes() override;
+
+ void SetKeyframeSelected(CUICDMTimelineKeyframe *inKeyframe, bool inSelected,
+ CUICDMTimelineItemBinding *inOwningInstance = nullptr);
+
+protected:
+ void SetKeyframeDynamic(CUICDMTimelineKeyframe *inKeyframe, bool inDynamic);
+ void CopySelectedKeyframes();
+
+public:
+ struct SKeyframeInstancePair
+ {
+ CUICDMTimelineKeyframe *m_Keyframe;
+ CUICDMTimelineItemBinding *m_Instance;
+
+ SKeyframeInstancePair(CUICDMTimelineKeyframe *inKeyframe,
+ CUICDMTimelineItemBinding *inInstance)
+ {
+ m_Keyframe = inKeyframe;
+ m_Instance = inInstance;
+ }
+ };
+
+protected:
+ typedef std::vector<SKeyframeInstancePair> TSelectedKeyframeList; ///< handle multiple keyframes
+ ///manipulation, e.g.
+ ///offsetting by dragging
+
+ CTimelineTranslationManager *m_TransMgr;
+ TSelectedKeyframeList m_SelectedKeyframes;
+ COffsetKeyframesCommandHelper m_OffsetKeyframeCommandHelper; // so that we can commit on mouseup
+ CPasteKeyframeCommandHelper *m_PasteKeyframeCommandHelper;
+ std::set<CUICDMTimelineItemBinding *> m_InstanceSet;
+ std::vector<UICDM::CUICDMInstanceHandle> m_InstanceList;
+};
+
+#endif // INCLUDED_IKEYFRAMES_MANAGER_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.cpp
new file mode 100644
index 00000000..73d5d5d2
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "LayerTimelineItemBinding.h"
+#include "TimelineTranslationManager.h"
+#include "BaseStateRow.h"
+#include "ImageTimelineItemBinding.h"
+#include "EmptyTimelineTimebar.h"
+
+// Data model specific
+#include "IDoc.h"
+#include "ClientDataModelBridge.h"
+#include "DropSource.h"
+#include "Doc.h"
+
+#include "UICDMHandles.h"
+#include "UICDMStudioSystem.h"
+
+#include "UICDMMetaData.h"
+#include "UICDMDataCore.h"
+#include "StudioFullSystem.h"
+#include "StudioCoreSystem.h"
+#include "UICDMSlides.h"
+
+using namespace UICDM;
+
+namespace {
+
+bool ImageSlotIsFilled(UICDM::IPropertySystem *inPropertySystem, CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr)
+{
+ CUICDMPropertyHandle theProperty =
+ inPropertySystem->GetAggregateInstancePropertyByName(inInstance, inStr);
+ SValue theValue;
+ inPropertySystem->GetInstancePropertyValue(inInstance, theProperty, theValue);
+
+ SLong4 theLong4 = UICDM::get<SLong4>(theValue);
+ bool theReturn = theLong4.m_Longs[0] != 0 || theLong4.m_Longs[1] != 0
+ || theLong4.m_Longs[2] != 0 || theLong4.m_Longs[3] != 0;
+
+ return theReturn;
+}
+
+// helper function to find the image binding class that 'represents' this property
+inline CImageTimelineItemBinding *FindImageBindingByProperty(CBaseStateRow *inRow,
+ CUICDMPropertyHandle inProperty)
+{
+ if (!inRow || !inProperty.Valid())
+ return nullptr;
+
+ CImageTimelineItemBinding *theInvalidImageBinding = nullptr;
+ for (long theIndex = 0; theIndex < inRow->GetNumNonPropertyRows(); ++theIndex) {
+ CImageTimelineItemBinding *theImageBinding = dynamic_cast<CImageTimelineItemBinding *>(
+ inRow->GetNonPropertyRow(theIndex)->GetTimelineItemBinding());
+ if (theImageBinding && theImageBinding->GetPropertyHandle() == inProperty) {
+ theInvalidImageBinding = theImageBinding;
+ break;
+ }
+ }
+ return theInvalidImageBinding;
+}
+}
+
+CLayerTimelineItemBinding::CLayerTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+{
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(inDataHandle, theProperties);
+
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(inDataHandle, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ TCharStr theName(thePropertySystem->GetName(theProperty));
+ TCharStr theFormalName(thePropertySystem->GetFormalName(inDataHandle, theProperty));
+ TNameFormalNamePair thePair =
+ std::make_tuple(theName, theFormalName, theProperty);
+ m_ImageNameFormalNamePairs.push_back(thePair);
+ }
+ }
+}
+
+CLayerTimelineItemBinding::~CLayerTimelineItemBinding()
+{
+}
+
+EStudioObjectType CLayerTimelineItemBinding::GetObjectType() const
+{
+ return OBJTYPE_LAYER;
+}
+
+ITimelineItemBinding *CLayerTimelineItemBinding::GetChild(long inIndex)
+{
+ static const TCharStr theLayerPrefix(L"Layer_");
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ if (theInstance.Valid()) {
+ Q3DStudio::CGraphIterator theChildren;
+ CUICDMSlideHandle theActiveSlide = m_TransMgr->GetDoc()->GetActiveSlide();
+ GetAssetChildrenInTimeParent(theInstance, m_TransMgr->GetDoc(), AmITimeParent(),
+ theChildren, theActiveSlide);
+ theChildren += inIndex;
+
+ UICDM::CUICDMInstanceHandle theChildInstance = theChildren.GetCurrent();
+ if (theChildInstance.Valid()) {
+ std::shared_ptr<IDataCore> theDataCore =
+ m_TransMgr->GetStudioSystem()->GetFullSystem()->GetCoreSystem()->GetDataCore();
+ ISlideSystem *theSlideSystem = m_TransMgr->GetStudioSystem()->GetSlideSystem();
+ ISlideCore *theSlideCore = m_TransMgr->GetStudioSystem()->GetSlideCore();
+
+ size_t theSlotCursor = (size_t)-1;
+ {
+
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ UICDM::SLong4 theGuid;
+ {
+ CUICDMPropertyHandle theTypeProperty =
+ thePropertySystem->GetAggregateInstancePropertyByName(theChildInstance,
+ L"id");
+ SValue theIdValue;
+ thePropertySystem->GetInstancePropertyValue(theChildInstance, theTypeProperty,
+ theIdValue);
+ theGuid = UICDM::get<UICDM::SLong4>(theIdValue);
+ }
+ for (size_t theSlotIndex = 0, theSlotCount = m_ImageNameFormalNamePairs.size();
+ theSlotIndex < theSlotCount; ++theSlotIndex) {
+ bool theIsMatch = false;
+ UICDM::CUICDMPropertyHandle theProperty =
+ std::get<2>(m_ImageNameFormalNamePairs[theSlotIndex]);
+ SValue theValue;
+ const SUICDMPropertyDefinition &theDefinition(
+ theDataCore->GetProperty(theProperty));
+ if (theDefinition.m_Type == DataModelDataType::Long4) {
+ SValue theDCValue;
+ if (theDataCore->GetInstancePropertyValue(theInstance, theProperty,
+ theDCValue)) {
+ SLong4 thePropGuid = get<SLong4>(theDCValue);
+ if (thePropGuid == theGuid)
+ theIsMatch = true;
+ }
+ CUICDMSlideHandle theSlide =
+ theSlideSystem->GetAssociatedSlide(theChildInstance);
+ CUICDMSlideHandle theMasterSlide = theSlideSystem->GetMasterSlide(theSlide);
+ if (theIsMatch == false && theSlide.Valid()
+ && theSlideCore->GetSpecificInstancePropertyValue(
+ theSlide, theInstance, theProperty, theValue)) {
+ SLong4 thePropGuid = get<SLong4>(theValue);
+ if (thePropGuid == theGuid)
+ theIsMatch = true;
+ }
+ }
+ if (theIsMatch) {
+ theSlotCursor = theSlotIndex;
+ break;
+ }
+ }
+ }
+ if (theSlotCursor != (size_t)-1) {
+ CUICDMPropertyHandle theImageProperty =
+ thePropertySystem->GetAggregateInstancePropertyByName(
+ m_DataHandle, std::get<0>(m_ImageNameFormalNamePairs[theSlotCursor]));
+ return GetOrCreateImageBinding(
+ theImageProperty,
+ std::get<1>(m_ImageNameFormalNamePairs[theSlotCursor]).wide_str());
+ } else
+ return m_TransMgr->GetOrCreate(theChildInstance);
+ }
+ }
+ return nullptr;
+}
+
+void CLayerTimelineItemBinding::OnAddChild(UICDM::CUICDMInstanceHandle inInstance)
+{
+ using namespace UICDM;
+ CClientDataModelBridge *theBridge = m_TransMgr->GetStudioSystem()->GetClientDataModelBridge();
+ // This is handled via the OnPropertyChanged call below
+ if (theBridge->IsImageInstance(inInstance))
+ return;
+ else
+ CUICDMTimelineItemBinding::OnAddChild(inInstance);
+}
+
+void CLayerTimelineItemBinding::OnPropertyChanged(CUICDMPropertyHandle inPropertyHandle)
+{
+ bool theHandled = false;
+ if (m_Row) {
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *theBridge =
+ m_TransMgr->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::TCharStr thePropertyName = thePropertySystem->GetName(inPropertyHandle);
+ size_t theSlotCount = m_ImageNameFormalNamePairs.size();
+ for (size_t theSlotIndex = 0; theSlotIndex < theSlotCount; ++theSlotIndex) {
+ UICDM::TCharStr thePropName = std::get<0>(m_ImageNameFormalNamePairs[theSlotIndex]);
+ if (thePropertyName == thePropName) {
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle, thePropName)) {
+ // already created, bail!
+ if (m_TransMgr->GetBinding(GetImage(inPropertyHandle)))
+ return;
+
+ // Image property was changed from one non-zero guid value to another, delete
+ // the old and and create a new one
+ CImageTimelineItemBinding *theReplacedImageBinding =
+ FindImageBindingByProperty(m_Row, inPropertyHandle);
+ if (theReplacedImageBinding)
+ m_Row->RemoveChildRow(theReplacedImageBinding);
+
+ ITimelineItemBinding *theNextImageBinding = nullptr;
+ // Determine if this is inserted somewhere in the existing list.
+ for (size_t theNextImage = theSlotIndex + 1; theNextImage < theSlotCount;
+ ++theNextImage) {
+ UICDM::TCharStr theTempName =
+ std::get<0>(m_ImageNameFormalNamePairs[theNextImage]);
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle, theTempName)) {
+ CUICDMPropertyHandle theNextImageProperty =
+ theBridge->GetAggregateInstancePropertyByName(m_DataHandle,
+ theTempName);
+ theNextImageBinding =
+ m_TransMgr->GetBinding(GetImage(theNextImageProperty));
+ break;
+ }
+ }
+ m_Row->AddChildRow(
+ GetOrCreateImageBinding(
+ inPropertyHandle,
+ std::get<1>(m_ImageNameFormalNamePairs[theSlotIndex]).wide_str()),
+ theNextImageBinding);
+ } else // check for delete
+ {
+ // GetImage will not return anything valid since the value is nuked.
+ // From the UI end, there is no way we can tell which image is associated with
+ // this property, since that is "encapsulated" in the property value.
+ CImageTimelineItemBinding *theInvalidImageBinding =
+ FindImageBindingByProperty(m_Row, inPropertyHandle);
+ if (theInvalidImageBinding)
+ m_Row->RemoveChildRow(theInvalidImageBinding);
+ }
+ theHandled = true;
+ break;
+ }
+ }
+ }
+ if (!theHandled)
+ CUICDMTimelineItemBinding::OnPropertyChanged(inPropertyHandle);
+}
+
+UICDM::CUICDMInstanceHandle
+CLayerTimelineItemBinding::GetImage(UICDM::CUICDMPropertyHandle inPropertyHandle)
+{
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ SValue theImageValue;
+ thePropertySystem->GetInstancePropertyValue(m_DataHandle, inPropertyHandle, theImageValue);
+ SLong4 theImageLong4 = UICDM::get<SLong4>(theImageValue);
+ return m_TransMgr->GetStudioSystem()->GetClientDataModelBridge()->GetImageInstanceByGUID(
+ theImageLong4);
+}
+
+ITimelineItemBinding *
+CLayerTimelineItemBinding::GetOrCreateImageBinding(UICDM::CUICDMPropertyHandle inPropertyHandle,
+ const wchar_t *inName)
+{
+ UICDM::CUICDMInstanceHandle theImageInstance = GetImage(inPropertyHandle);
+ ITimelineItemBinding *theImageTimelineRow = m_TransMgr->GetBinding(theImageInstance);
+ if (!theImageTimelineRow) // create
+ {
+ theImageTimelineRow = m_TransMgr->GetOrCreate(theImageInstance);
+ // Set the name, by spec: the nice name.
+ theImageTimelineRow->GetTimelineItem()->SetName(inName);
+ CImageTimelineItemBinding *theImageBinding =
+ dynamic_cast<CImageTimelineItemBinding *>(theImageTimelineRow);
+ if (theImageBinding)
+ theImageBinding->SetPropertyHandle(inPropertyHandle);
+ }
+ return theImageTimelineRow;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.h
new file mode 100644
index 00000000..d4826f2f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/LayerTimelineItemBinding.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_LAYER_TIMELINEITEM_BINDING_H
+#define INCLUDED_LAYER_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+
+namespace UICDM {
+class CStudioSystem;
+}
+
+//=============================================================================
+/**
+ * Binding to generic UICDM object
+ */
+class CLayerTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public: // Types
+ typedef std::tuple<UICDM::TCharStr, UICDM::TCharStr, UICDM::CUICDMPropertyHandle>
+ TNameFormalNamePair;
+ typedef std::vector<TNameFormalNamePair> TNameFormalNamePairList;
+
+protected: // Members
+ TNameFormalNamePairList m_ImageNameFormalNamePairs;
+
+public: // Construction
+ CLayerTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ virtual ~CLayerTimelineItemBinding();
+
+public: // CUICDMTimelineItemBinding
+ EStudioObjectType GetObjectType() const override;
+ // Hierarchy
+ ITimelineItemBinding *GetChild(long inIndex) override;
+ void OnAddChild(UICDM::CUICDMInstanceHandle inInstance) override;
+ // Event callback
+ void OnPropertyChanged(UICDM::CUICDMPropertyHandle inPropertyHandle) override;
+
+protected:
+ UICDM::CUICDMInstanceHandle GetImage(UICDM::CUICDMPropertyHandle inPropertyHandle);
+ ITimelineItemBinding *GetOrCreateImageBinding(UICDM::CUICDMPropertyHandle inPropertyHandle,
+ const wchar_t *inName);
+};
+
+#endif // INCLUDED_LAYER_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp
new file mode 100644
index 00000000..eb91714e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MaterialTimelineItemBinding.h"
+#include "TimelineTranslationManager.h"
+#include "BaseStateRow.h"
+#include "ImageTimelineItemBinding.h"
+#include "EmptyTimelineTimebar.h"
+
+// Data model specific
+#include "IDoc.h"
+#include "ClientDataModelBridge.h"
+#include "DropSource.h"
+
+#include "UICDMHandles.h"
+#include "UICDMStudioSystem.h"
+
+#include "UICDMMetaData.h"
+#include "UICDMDataCore.h"
+#include "StudioFullSystem.h"
+#include "StudioCoreSystem.h"
+
+using namespace UICDM;
+
+CMaterialTimelineItemBinding::CMaterialTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+{
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ TPropertyHandleList theProperties;
+ thePropertySystem->GetAggregateInstanceProperties(inDataHandle, theProperties);
+
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ CUICDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(inDataHandle, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ TCharStr theName(thePropertySystem->GetName(theProperty));
+ TCharStr theFormalName(thePropertySystem->GetFormalName(inDataHandle, theProperty));
+ TNameFormalNamePair thePair = std::make_tuple(theName, theFormalName);
+ m_ImageNameFormalNamePairs.push_back(thePair);
+ }
+ }
+}
+
+CMaterialTimelineItemBinding::~CMaterialTimelineItemBinding()
+{
+}
+
+ITimelineTimebar *CMaterialTimelineItemBinding::GetTimebar()
+{ // No timebars on materials
+ return new CEmptyTimelineTimebar();
+}
+
+EStudioObjectType CMaterialTimelineItemBinding::GetObjectType() const
+{
+ return OBJTYPE_MATERIAL;
+}
+
+bool CMaterialTimelineItemBinding::ShowToggleControls() const
+{
+ // Materials have no toggle controls, by design
+ return false;
+}
+
+bool ImageSlotIsFilled(UICDM::IPropertySystem *inPropertySystem, CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr)
+{
+ CUICDMPropertyHandle theProperty =
+ inPropertySystem->GetAggregateInstancePropertyByName(inInstance, inStr);
+ SValue theValue;
+ inPropertySystem->GetInstancePropertyValue(inInstance, theProperty, theValue);
+
+ // Prevent assertion down the path when changing from edited standard material to reference material
+ if (UICDM::GetValueType(theValue) == DataModelDataType::None)
+ return false;
+
+ SLong4 theLong4 = UICDM::get<SLong4>(theValue);
+ bool theReturn = theLong4.m_Longs[0] != 0 || theLong4.m_Longs[1] != 0
+ || theLong4.m_Longs[2] != 0 || theLong4.m_Longs[3] != 0;
+
+ return theReturn;
+}
+
+long CMaterialTimelineItemBinding::GetChildrenCount()
+{
+ long theReturnCount = 0;
+ if (m_TransMgr->GetStudioSystem()->IsInstance(m_DataHandle)) {
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ size_t theSlotCount = m_ImageNameFormalNamePairs.size();
+ for (size_t theSlotIndex = 0; theSlotIndex < theSlotCount; ++theSlotIndex) {
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle,
+ std::get<0>(m_ImageNameFormalNamePairs[theSlotIndex]))) {
+ ++theReturnCount;
+ }
+ }
+ }
+
+ return theReturnCount;
+}
+
+ITimelineItemBinding *CMaterialTimelineItemBinding::GetChild(long inIndex)
+{
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+
+ size_t theSlotCursor = 0;
+ size_t theSlotCount = m_ImageNameFormalNamePairs.size();
+ for (size_t theSlotIndex = 0; theSlotIndex < theSlotCount; ++theSlotIndex) {
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle,
+ std::get<0>(m_ImageNameFormalNamePairs[theSlotIndex]))) {
+ inIndex--;
+
+ if (inIndex < 0) {
+ theSlotCursor = theSlotIndex;
+ break;
+ }
+ }
+ }
+ CUICDMPropertyHandle theImageProperty = thePropertySystem->GetAggregateInstancePropertyByName(
+ m_DataHandle, std::get<0>(m_ImageNameFormalNamePairs[theSlotCursor]));
+ return GetOrCreateImageBinding(
+ theImageProperty, std::get<1>(m_ImageNameFormalNamePairs[theSlotCursor]).wide_str());
+}
+
+void CMaterialTimelineItemBinding::OnAddChild(UICDM::CUICDMInstanceHandle inInstance)
+{
+ using namespace UICDM;
+ CClientDataModelBridge *theBridge = m_TransMgr->GetStudioSystem()->GetClientDataModelBridge();
+ // This is handled via the OnPropertyChanged call below
+ if (theBridge->IsImageInstance(inInstance))
+ return;
+ else
+ CUICDMTimelineItemBinding::OnAddChild(inInstance);
+}
+
+// helper function to find the image binding class that 'represents' this property
+inline CImageTimelineItemBinding *FindImageBindingByProperty(CBaseStateRow *inRow,
+ CUICDMPropertyHandle inProperty)
+{
+ if (!inRow || !inProperty.Valid())
+ return nullptr;
+
+ CImageTimelineItemBinding *theInvalidImageBinding = nullptr;
+ for (long theIndex = 0; theIndex < inRow->GetNumNonPropertyRows(); ++theIndex) {
+ CImageTimelineItemBinding *theImageBinding = dynamic_cast<CImageTimelineItemBinding *>(
+ inRow->GetNonPropertyRow(theIndex)->GetTimelineItemBinding());
+ if (theImageBinding && theImageBinding->GetPropertyHandle() == inProperty) {
+ theInvalidImageBinding = theImageBinding;
+ break;
+ }
+ }
+ return theInvalidImageBinding;
+}
+
+void CMaterialTimelineItemBinding::OnPropertyChanged(CUICDMPropertyHandle inPropertyHandle)
+{
+ bool theHandled = false;
+ if (m_Row) {
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *theBridge =
+ m_TransMgr->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::TCharStr thePropertyName = thePropertySystem->GetName(inPropertyHandle);
+ size_t theSlotCount = m_ImageNameFormalNamePairs.size();
+ for (size_t theSlotIndex = 0; theSlotIndex < theSlotCount; ++theSlotIndex) {
+ UICDM::TCharStr thePropName = std::get<0>(m_ImageNameFormalNamePairs[theSlotIndex]);
+ if (thePropertyName == thePropName) {
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle, thePropName)) {
+ // already created, bail!
+ if (m_TransMgr->GetBinding(GetImage(inPropertyHandle)))
+ return;
+
+ // Image property was changed from one non-zero guid value to another, delete
+ // the old and and create a new one
+ CImageTimelineItemBinding *theReplacedImageBinding =
+ FindImageBindingByProperty(m_Row, inPropertyHandle);
+ if (theReplacedImageBinding)
+ m_Row->RemoveChildRow(theReplacedImageBinding);
+
+ ITimelineItemBinding *theNextImageBinding = nullptr;
+ // Determine if this is inserted somewhere in the existing list.
+ for (size_t theNextImage = theSlotIndex + 1; theNextImage < theSlotCount;
+ ++theNextImage) {
+ UICDM::TCharStr theTempName =
+ std::get<0>(m_ImageNameFormalNamePairs[theNextImage]);
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle, theTempName)) {
+ CUICDMPropertyHandle theNextImageProperty =
+ theBridge->GetAggregateInstancePropertyByName(m_DataHandle,
+ theTempName);
+ theNextImageBinding =
+ m_TransMgr->GetBinding(GetImage(theNextImageProperty));
+ break;
+ }
+ }
+ m_Row->AddChildRow(
+ GetOrCreateImageBinding(
+ inPropertyHandle,
+ std::get<1>(m_ImageNameFormalNamePairs[theSlotIndex]).wide_str()),
+ theNextImageBinding);
+ } else // check for delete
+ {
+ // GetImage will not return anything valid since the value is nuked.
+ // From the UI end, there is no way we can tell which image is associated with
+ // this property, since that is "encapsulated" in the property value.
+ CImageTimelineItemBinding *theInvalidImageBinding =
+ FindImageBindingByProperty(m_Row, inPropertyHandle);
+ if (theInvalidImageBinding)
+ m_Row->RemoveChildRow(theInvalidImageBinding);
+ }
+ theHandled = true;
+ break;
+ }
+ }
+ }
+ if (!theHandled)
+ CUICDMTimelineItemBinding::OnPropertyChanged(inPropertyHandle);
+}
+
+void CMaterialTimelineItemBinding::OnPropertyLinked(CUICDMPropertyHandle inPropertyHandle)
+{
+ bool theHandled = false;
+ if (m_Row) {
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *theBridge =
+ m_TransMgr->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::TCharStr thePropertyName = thePropertySystem->GetName(inPropertyHandle);
+ size_t theSlotCount = m_ImageNameFormalNamePairs.size();
+ for (size_t theSlotIndex = 0; theSlotIndex < theSlotCount; ++theSlotIndex) {
+ UICDM::TCharStr thePropName = std::get<0>(m_ImageNameFormalNamePairs[theSlotIndex]);
+ if (thePropertyName == thePropName) {
+ // Refresh image child row by delete and recreate
+ CImageTimelineItemBinding *theInvalidImageBinding =
+ FindImageBindingByProperty(m_Row, inPropertyHandle);
+ if (theInvalidImageBinding)
+ m_Row->RemoveChildRow(theInvalidImageBinding);
+
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle, thePropName)) {
+ ITimelineItemBinding *theNextImageBinding = nullptr;
+ // Determine if this is inserted somewhere in the existing list.
+ for (size_t theNextImage = theSlotIndex + 1; theNextImage < theSlotCount;
+ ++theNextImage) {
+ UICDM::TCharStr theTempName =
+ std::get<0>(m_ImageNameFormalNamePairs[theNextImage]);
+ if (ImageSlotIsFilled(thePropertySystem, m_DataHandle, theTempName)) {
+ CUICDMPropertyHandle theNextImageProperty =
+ theBridge->GetAggregateInstancePropertyByName(m_DataHandle,
+ theTempName);
+ theNextImageBinding =
+ m_TransMgr->GetBinding(GetImage(theNextImageProperty));
+ break;
+ }
+ }
+ m_Row->AddChildRow(
+ GetOrCreateImageBinding(
+ inPropertyHandle,
+ std::get<1>(m_ImageNameFormalNamePairs[theSlotIndex]).wide_str()),
+ theNextImageBinding);
+ }
+
+ theHandled = true;
+ break;
+ }
+ }
+ }
+ if (!theHandled)
+ CUICDMTimelineItemBinding::OnPropertyLinked(inPropertyHandle);
+}
+
+UICDM::CUICDMInstanceHandle
+CMaterialTimelineItemBinding::GetImage(UICDM::CUICDMPropertyHandle inPropertyHandle)
+{
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ SValue theImageValue;
+ thePropertySystem->GetInstancePropertyValue(m_DataHandle, inPropertyHandle, theImageValue);
+ SLong4 theImageLong4 = UICDM::get<SLong4>(theImageValue);
+ return m_TransMgr->GetStudioSystem()->GetClientDataModelBridge()->GetImageInstanceByGUID(
+ theImageLong4);
+}
+
+ITimelineItemBinding *
+CMaterialTimelineItemBinding::GetOrCreateImageBinding(UICDM::CUICDMPropertyHandle inPropertyHandle,
+ const wchar_t *inName)
+{
+ UICDM::CUICDMInstanceHandle theImageInstance = GetImage(inPropertyHandle);
+ ITimelineItemBinding *theImageTimelineRow = m_TransMgr->GetBinding(theImageInstance);
+ if (!theImageTimelineRow) // create
+ {
+ theImageTimelineRow = m_TransMgr->GetOrCreate(theImageInstance);
+ // Set the name, by spec: the nice name.
+ theImageTimelineRow->GetTimelineItem()->SetName(inName);
+ CImageTimelineItemBinding *theImageBinding =
+ dynamic_cast<CImageTimelineItemBinding *>(theImageTimelineRow);
+ if (theImageBinding)
+ theImageBinding->SetPropertyHandle(inPropertyHandle);
+ }
+ return theImageTimelineRow;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h
new file mode 100644
index 00000000..e1c2188d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_MATERIAL_TIMELINEITEM_BINDING_H
+#define INCLUDED_MATERIAL_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+#include "UICDMDataTypes.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CTimelineTranslationManager;
+class CBaseStateRow;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Material type
+ */
+class CMaterialTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public: // Types
+ typedef std::tuple<UICDM::TCharStr, UICDM::TCharStr> TNameFormalNamePair;
+ typedef std::vector<TNameFormalNamePair> TNameFormalNamePairList;
+
+protected: // Members
+ TNameFormalNamePairList m_ImageNameFormalNamePairs;
+
+public: // Construction
+ CMaterialTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ virtual ~CMaterialTimelineItemBinding();
+
+public: // CUICDMTimelineItemBinding
+ ITimelineTimebar *GetTimebar() override;
+ EStudioObjectType GetObjectType() const override;
+ bool ShowToggleControls() const override;
+ // Hierarchy
+ long GetChildrenCount() override;
+ ITimelineItemBinding *GetChild(long inIndex) override;
+ void OnAddChild(UICDM::CUICDMInstanceHandle inInstance) override;
+ // Event callback
+ void OnPropertyChanged(UICDM::CUICDMPropertyHandle inPropertyHandle) override;
+ void OnPropertyLinked(UICDM::CUICDMPropertyHandle inPropertyHandle) override;
+
+protected:
+ UICDM::CUICDMInstanceHandle GetImage(UICDM::CUICDMPropertyHandle inPropertyHandle);
+ ITimelineItemBinding *GetOrCreateImageBinding(UICDM::CUICDMPropertyHandle inPropertyHandle,
+ const wchar_t *inName);
+};
+
+#endif // INCLUDED_MATERIAL_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.cpp
new file mode 100644
index 00000000..374c123b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "OffsetKeyframesCommandHelper.h"
+#include "Core.h"
+
+// Data model specific
+#include "IDoc.h"
+#include "CmdDataModelChangeKeyframe.h"
+#include "IDocumentEditor.h"
+
+#include "UICDMTimelineKeyframe.h" //TODO: remove once we resolve the precision issue
+
+using namespace UICDM;
+
+COffsetKeyframesCommandHelper::COffsetKeyframesCommandHelper(CDoc &inDoc)
+ : Q3DStudio::CUpdateableDocumentEditor(inDoc)
+ , m_Doc(inDoc)
+{
+}
+
+COffsetKeyframesCommandHelper::~COffsetKeyframesCommandHelper()
+{
+ Finalize();
+}
+
+//@param inTime time in millisecs
+void COffsetKeyframesCommandHelper::SetCommandTime(UICDM::CUICDMKeyframeHandle inKeyframe,
+ long inTime)
+{
+ // The UICDM system will take care of merging these under the hood.
+ ENSURE_EDITOR(L"Set Keyframe Time").SetKeyframeTime(inKeyframe, inTime);
+}
+
+// equivalent to commit (onmouseup)
+void COffsetKeyframesCommandHelper::Finalize()
+{
+ CommitEditor();
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.h
new file mode 100644
index 00000000..3a58e672
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/OffsetKeyframesCommandHelper.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_OFFSET_KEYFRAMES_COMMAND_HELPER_H
+#define INCLUDED_OFFSET_KEYFRAMES_COMMAND_HELPER_H 1
+
+#pragma once
+
+// Data model
+#include "UICDMHandles.h"
+#include "IDocumentEditor.h"
+
+namespace Q3DStudio {
+class IDocumentEditor;
+}
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CCmdDataModelSetKeyframeTime;
+
+class COffsetKeyframesCommandHelper : public Q3DStudio::CUpdateableDocumentEditor
+{
+protected:
+ CDoc &m_Doc;
+
+public:
+ COffsetKeyframesCommandHelper(CDoc &inDoc);
+ ~COffsetKeyframesCommandHelper();
+
+ void SetCommandTime(UICDM::CUICDMKeyframeHandle inKeyframe, long inTime);
+ void Finalize();
+ void Rollback() { RollbackEditor(); }
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h
new file mode 100644
index 00000000..130f6d20
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/PasteKeyframesCommandHelper.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PASTE_KEYFRAME_COMMAND_HELPER_H
+#define INCLUDED_PASTE_KEYFRAME_COMMAND_HELPER_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "CmdDataModelInsertKeyframe.h"
+#include "UICDMPropertyDefinition.h"
+#include "UICDMDataCore.h"
+
+// This caches all copied keyframes' time and data, for a paste action.
+// This has to deal with the actual data and not keyframe handles, because a prior Cut can
+// invalidate those handles.
+class CPasteKeyframeCommandHelper
+{
+protected:
+ typedef std::vector<CCmdDataModelInsertKeyframe::STimeKeyframeData> TCopiedKeyframeList;
+ TCopiedKeyframeList m_CopiedKeyframeList;
+
+public: // Construction
+ CPasteKeyframeCommandHelper() {}
+ ~CPasteKeyframeCommandHelper() {}
+
+ // inTime should be relative to the earliest keyframe time in this list
+ void AddKeyframeData(UICDM::CUICDMPropertyHandle inProperty, float inKeyframeTime,
+ UICDM::SGetOrSetKeyframeInfo *inInfos, size_t inInfoCount)
+ {
+ m_CopiedKeyframeList.push_back(CCmdDataModelInsertKeyframe::STimeKeyframeData(
+ inProperty, inKeyframeTime, inInfos, inInfoCount));
+ }
+
+ bool HasCopiedKeyframes() const { return !m_CopiedKeyframeList.empty(); }
+
+ // Triggered by a "Paste Keyframe" action
+ // Note: The logic is based on what the Animation Manager in the old system used to do.
+ // 1. The condition for paste to occur is that the property name matches.
+ // The old data model has a limitation that if the destination property is a linked property,
+ // the source has to come from the same instance, most likely a easy way out than to deal with
+ // with having to 'sync' all linked animation tracks.
+ // but that is not an issue in the new data model.
+ //
+ // 2. The first pasted keyframe is at current view time and the rest are offset accordingly.
+ CCmdDataModelInsertKeyframe *GetCommand(CDoc *inDoc, long inTimeOffsetInMilliseconds,
+ UICDM::CUICDMInstanceHandle inTargetInstance)
+ {
+ using namespace UICDM;
+
+ CCmdDataModelInsertKeyframe *theInsertKeyframesCommand = nullptr;
+ TCopiedKeyframeList::iterator theIter = m_CopiedKeyframeList.begin();
+ UICDM::IPropertySystem *thePropertySystem = inDoc->GetStudioSystem()->GetPropertySystem();
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+
+ for (; theIter != m_CopiedKeyframeList.end(); ++theIter) {
+ TCharStr thePropertyName = thePropertySystem->GetName(theIter->m_Property);
+ DataModelDataType::Value thePropertyType =
+ thePropertySystem->GetDataType(theIter->m_Property);
+ CUICDMPropertyHandle theTargetPropertyHandle =
+ theBridge->GetAggregateInstancePropertyByName(inTargetInstance, thePropertyName);
+ if (theTargetPropertyHandle.Valid()) // property exists on target
+ {
+ // sanity check for type match
+ DataModelDataType::Value theTargetPropertyType =
+ thePropertySystem->GetDataType(theTargetPropertyHandle);
+ if (theTargetPropertyType == thePropertyType) {
+ // 2. Offset keyframe time by current view time
+ double milliseconds = theIter->m_KeyframeTime * 1000.0;
+ double theTimeInMilliseconds = milliseconds + inTimeOffsetInMilliseconds;
+ float theTimeInSeconds = static_cast<float>(theTimeInMilliseconds / 1000.0);
+
+ if (!theInsertKeyframesCommand)
+ theInsertKeyframesCommand = new CCmdDataModelInsertKeyframe(
+ inDoc, inTargetInstance, theTargetPropertyHandle, theTimeInSeconds,
+ theIter->m_Infos, theIter->m_ValidInfoCount);
+ else
+ theInsertKeyframesCommand->AddKeyframeData(
+ theTargetPropertyHandle, theTimeInSeconds, theIter->m_Infos,
+ theIter->m_ValidInfoCount);
+ }
+ }
+ }
+ return theInsertKeyframesCommand;
+ }
+
+ void Clear() { m_CopiedKeyframeList.clear(); }
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.cpp
new file mode 100644
index 00000000..286a899f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "PathAnchorPointTimelineItemBinding.h"
+#include "EmptyTimelineTimebar.h"
+
+using namespace UICDM;
+
+CPathAnchorPointTimelineItemBinding::CPathAnchorPointTimelineItemBinding(
+ CTimelineTranslationManager *inMgr, CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+{
+}
+
+ITimelineTimebar *CPathAnchorPointTimelineItemBinding::GetTimebar()
+{
+ return new CEmptyTimelineTimebar();
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.h
new file mode 100644
index 00000000..2bc3f8d6
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathAnchorPointTimelineItemBinding.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef PATH_ANCHOR_POINT_TIMELINE_ITEM_BINDING
+#define PATH_ANCHOR_POINT_TIMELINE_ITEM_BINDING
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+#include "UICDMDataTypes.h"
+#include <boost/tuple/tuple.hpp>
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CTimelineTranslationManager;
+class CBaseStateRow;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Material type
+ */
+class CPathAnchorPointTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public: // Construction
+ CPathAnchorPointTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+
+ bool ShowToggleControls() const override { return false; }
+ bool IsVisible() const override { return true; }
+ void SetVisible(bool) override {}
+ ITimelineTimebar *GetTimebar() override;
+ bool IsLocked() const override { return false; }
+ void SetLocked(bool) override {}
+ bool IsShy() const override { return false; }
+ void SetShy(bool) override {}
+ Q3DStudio::CString GetName() const override { return L"Anchor Point"; }
+ void SetName(const Q3DStudio::CString &) override {}
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.cpp
new file mode 100644
index 00000000..3fbed168
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "PathTimelineItemBinding.h"
+#include "TimelineTranslationManager.h"
+#include "Doc.h"
+
+bool CPathTimelineItemBinding::IsExternalizeable()
+{
+ // If this path has subpath children, then it is externalizeable.
+ return m_TransMgr->GetDoc()->GetDocumentReader().IsPathExternalizeable(GetInstance());
+}
+
+void CPathTimelineItemBinding::Externalize()
+{
+ Q3DStudio::ScopedDocumentEditor(*m_TransMgr->GetDoc(), L"Externalize Path Buffer", __FILE__,
+ __LINE__)
+ ->ExternalizePath(GetInstance());
+}
+
+bool CPathTimelineItemBinding::IsInternalizeable()
+{
+ // If this path has a sourcepath, then it might be internalizeable
+ return m_TransMgr->GetDoc()->GetDocumentReader().IsPathInternalizeable(GetInstance());
+}
+
+void CPathTimelineItemBinding::Internalize()
+{
+ Q3DStudio::ScopedDocumentEditor(*m_TransMgr->GetDoc(), L"Internalize Path Buffer", __FILE__,
+ __LINE__)
+ ->InternalizePath(GetInstance());
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.h
new file mode 100644
index 00000000..1be4b2e1
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/PathTimelineItemBinding.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef PATH_TIMELINE_ITEM_BINDING
+#define PATH_TIMELINE_ITEM_BINDING
+#pragma once
+#include "UICDMTimelineItemBinding.h"
+#include "UICDMDataTypes.h"
+#include <boost/tuple/tuple.hpp>
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CTimelineTranslationManager;
+class CBaseStateRow;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Material type
+ */
+class CPathTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public: // Construction
+ CPathTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr, inDataHandle)
+ {
+ }
+
+ bool IsExternalizeable() override;
+ void Externalize() override;
+ bool IsInternalizeable() override;
+ void Internalize() override;
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.cpp
new file mode 100644
index 00000000..ce381f44
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SlideTimelineItemBinding.h"
+#include "BaseStateRow.h"
+
+// Data model specific
+#include "Doc.h"
+#include "CmdGeneric.h"
+#include "EmptyTimelineTimebar.h"
+
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+#include "ClientDataModelBridge.h"
+
+using namespace UICDM;
+
+CSlideTimelineItemBinding::CSlideTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ CUICDMInstanceHandle inDataHandle)
+ : CUICDMTimelineItemBinding(inMgr)
+{
+ UICDM::CUICDMSlideHandle theSlideHandle =
+ m_StudioSystem->GetSlideSystem()->GetSlideByInstance(inDataHandle);
+
+ // Get the owning component of m_SlideHandle.
+ // This should return CAsset OBJTYPE_SCENE or OBJTYPE_COMPONENT.
+ UICDM::CUICDMInstanceHandle theInstance =
+ m_StudioSystem->GetClientDataModelBridge()->GetOwningComponentInstance(theSlideHandle);
+ SetInstanceHandle(theInstance);
+
+ // Listen to change on Asset name
+ IStudioFullSystemSignalProvider *theEngine = m_StudioSystem->GetFullSystemSignalProvider();
+ std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle)> theSetter(
+ std::bind(&CSlideTimelineItemBinding::OnPropertyChanged, this, std::placeholders::_2));
+ m_Connection = theEngine->ConnectInstancePropertyValue(
+ std::bind(UICDM::MaybackCallbackInstancePropertyValue<std::function<void(
+ CUICDMInstanceHandle, CUICDMPropertyHandle)>>,
+ std::placeholders::_1, std::placeholders::_2, theInstance,
+ m_StudioSystem->GetClientDataModelBridge()->GetNameProperty(), theSetter));
+}
+
+ITimelineTimebar *CSlideTimelineItemBinding::GetTimebar()
+{ // No timebars on slides
+ return new CEmptyTimelineTimebar();
+}
+
+void CSlideTimelineItemBinding::SetName(const Q3DStudio::CString & /*inName*/)
+{
+ // Do nothing because name is read only
+}
+
+void CSlideTimelineItemBinding::Bind(CBaseStateRow *inRow)
+{
+ CUICDMTimelineItemBinding::Bind(inRow);
+ GetRow()->SetNameReadOnly(true);
+}
+
+bool CSlideTimelineItemBinding::IsValidTransaction(EUserTransaction inTransaction)
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ switch (inTransaction) {
+ // Disable the following context menus
+ case EUserTransaction_Rename:
+ case EUserTransaction_MakeComponent:
+ case EUserTransaction_EditComponent:
+ return false;
+ }
+
+ return CUICDMTimelineItemBinding::IsValidTransaction(inTransaction);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.h
new file mode 100644
index 00000000..759fdfb9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/SlideTimelineItemBinding.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SLIDE_TIMELINEITEM_BINDING_H
+#define INCLUDED_SLIDE_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "UICDMTimelineItemBinding.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class ITimelineItem;
+class CTimelineTranslationManager;
+class CBaseStateRow;
+
+//=============================================================================
+/**
+ * Binding to a UICDM object of Slide type
+ */
+class CSlideTimelineItemBinding : public CUICDMTimelineItemBinding
+{
+public:
+ CSlideTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ ~CSlideTimelineItemBinding() {}
+
+ // CUICDMTimelineItemBinding
+ ITimelineTimebar *GetTimebar() override;
+ void SetName(const Q3DStudio::CString &inName) override;
+ void Bind(CBaseStateRow *inRow) override;
+ bool IsValidTransaction(EUserTransaction inTransaction) override;
+
+ // No properties
+ long GetPropertyCount() override { return 0; }
+ ITimelineItemProperty *GetProperty(long) override { return nullptr; }
+ void LoadProperties() override {}
+
+ // Eye/Lock toggles are not applicable
+ bool ShowToggleControls() const override { return false; }
+ bool IsLockedEnabled() const override { return false; }
+ bool IsVisibleEnabled() const override { return false; }
+
+ // Shy, Locked, Visible are not applicable
+ bool IsShy() const override { return false; }
+ void SetShy(bool) override {}
+ bool IsLocked() const override { return false; }
+ void SetLocked(bool) override {}
+ bool IsVisible() const override { return true; }
+ void SetVisible(bool) override {}
+
+ // Keyframes, not applicable to a Slide
+ void InsertKeyframe() override {}
+ void DeleteAllChannelKeyframes() override {}
+ long GetKeyframeCount() const override { return 0; }
+ IKeyframe *GetKeyframeByTime(long) const override { return nullptr; }
+ IKeyframe *GetKeyframeByIndex(long) const override { return nullptr; }
+ long OffsetSelectedKeyframes(long) override { return 0; }
+ void CommitChangedKeyframes() override {}
+ void OnEditKeyframeTime(long, long) override {}
+ // IKeyframeSelector
+ void SelectKeyframes(bool, long inTime = -1) override { Q_UNUSED(inTime); }
+
+ // Keyframe manipulation, not applicable
+ void UIRefreshPropertyKeyframe(long inOffset) override { Q_UNUSED(inOffset); }
+ bool HasDynamicKeyframes(long inTime) override
+ {
+ Q_UNUSED(inTime);
+ return false;
+ }
+ void SetDynamicKeyframes(long inTime, bool inDynamic) override
+ {
+ Q_UNUSED(inTime);
+ Q_UNUSED(inDynamic);
+ }
+ void DoSelectKeyframes(bool inSelected, long inTime, bool inUpdateUI) override
+ {
+ Q_UNUSED(inSelected);
+ Q_UNUSED(inTime);
+ Q_UNUSED(inUpdateUI);
+ }
+ void OnPropertySelection(long inTime) override { Q_UNUSED(inTime); }
+
+protected:
+ std::shared_ptr<UICDM::ISignalConnection>
+ m_Connection; // Callback when the Asset name changes
+
+ bool AmITimeParent() const override { return true; }
+};
+
+#endif // INCLUDED_SLIDE_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.cpp
new file mode 100644
index 00000000..4bd1fc01
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "TimelineBreadCrumbProvider.h"
+#include "Core.h"
+
+// Link to data model
+#include "Doc.h"
+#include "StudioApp.h"
+#include "Cmd.h"
+#include "ResourceCache.h"
+#include "Strings.h"
+#include "StringLoader.h"
+#include "CColor.h"
+
+#include "ClientDataModelBridge.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+#include "CmdActivateSlide.h"
+
+using namespace UICDM;
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimelineBreadCrumbProvider::CTimelineBreadCrumbProvider(CDoc *inDoc)
+ : m_Doc(inDoc)
+{
+}
+
+//=============================================================================
+/**
+ */
+CTimelineBreadCrumbProvider::~CTimelineBreadCrumbProvider()
+{
+}
+
+//=============================================================================
+/**
+ * determine the color and text string for this breadcrumb
+ */
+static inline void FillBreadCrumb(SBreadCrumb &outBreadCrumb,
+ UICDM::CUICDMInstanceHandle inInstance, CDoc *inDoc)
+{
+ // Get the MasterSlide Handle associated with inAsset
+ CClientDataModelBridge *theBridge = inDoc->GetStudioSystem()->GetClientDataModelBridge();
+ ISlideSystem *theSlideSystem = inDoc->GetStudioSystem()->GetSlideSystem();
+ Q3DStudio::CId theId = theBridge->GetGUID(inInstance);
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theId));
+ ASSERT(theMasterSlide.Valid()); // it should be valid because inAsset should be OBJTYPE_SCENE or
+ // non-library OBJTYPE_COMPONENT
+
+ // Get the active slide index of the master slide. Master Slide always has index 0
+ long theActiveIndex = theSlideSystem->GetActiveSlideIndex(theMasterSlide);
+ bool theIsMaster = (theActiveIndex == 0);
+
+ // Determine the color
+ outBreadCrumb.m_Color =
+ theIsMaster ? CColor(0, 0, 255) : CColor(0, 0, 0); // blue for master, black otherwise
+
+ // Determine the text string
+ outBreadCrumb.m_String = theBridge->GetName(inInstance).toQString();
+ outBreadCrumb.m_String += " (";
+ if (theIsMaster)
+ outBreadCrumb.m_String += ::LoadResourceString(IDS_OBJTYPE_MASTER).toQString();
+ else {
+ CUICDMSlideHandle theActiveSlide =
+ theSlideSystem->GetSlideByIndex(theMasterSlide, theActiveIndex);
+ CUICDMInstanceHandle theInstanceHandle = theSlideSystem->GetSlideInstance(theActiveSlide);
+ ASSERT(theInstanceHandle.Valid());
+ outBreadCrumb.m_String += theBridge->GetName(theInstanceHandle).toQString();
+ }
+ outBreadCrumb.m_String += ")";
+}
+
+//=============================================================================
+/**
+ * return the trail of breadcrumb.
+ * This constructs a list of the "time context tree" from Scene down to the current active time
+ * context.
+ * @param inRefresh true to refresh the list, false to get existing.
+ */
+CTimelineBreadCrumbProvider::TTrailList
+CTimelineBreadCrumbProvider::GetTrail(bool inRefresh /*= true */)
+{
+ if (inRefresh)
+ RefreshSlideList();
+
+ TTrailList theList;
+ for (size_t theIndex = 0; theIndex < m_BreadCrumbList.size(); ++theIndex) {
+ SBreadCrumb theBreadCrumb;
+ FillBreadCrumb(theBreadCrumb, m_BreadCrumbList[theIndex], m_Doc);
+ theList.push_back(theBreadCrumb);
+ }
+ return theList;
+}
+
+//=============================================================================
+/**
+ * switch current time context to the one 'represented' by the breadcrumbs.
+ * @param inTrailIndex index into the trail list
+ */
+void CTimelineBreadCrumbProvider::OnBreadCrumbClicked(long inTrailIndex)
+{
+ if (inTrailIndex >= 0 && inTrailIndex < (long)m_BreadCrumbList.size()) {
+ CCmdActivateSlide *theCmd = new CCmdActivateSlide(m_Doc, m_BreadCrumbList[inTrailIndex]);
+ theCmd->SetForceRefresh(false);
+ m_Doc->GetCore()->ExecuteCommand(theCmd, false);
+ }
+}
+
+QPixmap CTimelineBreadCrumbProvider::GetRootImage() const
+{
+ return CResourceCache::GetInstance()->GetBitmap("breadcrumb_component_scene.png");
+}
+
+QPixmap CTimelineBreadCrumbProvider::GetBreadCrumbImage() const
+{
+ return CResourceCache::GetInstance()->GetBitmap("breadcrumb_component_button.png");
+}
+
+QPixmap CTimelineBreadCrumbProvider::GetSeparatorImage() const
+{
+ return CResourceCache::GetInstance()->GetBitmap("breadcrumb_component_colon_button.png");
+}
+
+QPixmap CTimelineBreadCrumbProvider::GetActiveBreadCrumbImage() const
+{
+ return CResourceCache::GetInstance()->GetBitmap("breadcrumb_component_grey_button.png");
+}
+
+//=============================================================================
+/**
+ * Called when active time context is changed.
+ */
+void CTimelineBreadCrumbProvider::RefreshSlideList()
+{
+ ClearSlideList();
+
+ UICDM::CUICDMInstanceHandle theActiveRoot = m_Doc->GetActiveRootInstance();
+ if (!theActiveRoot.Valid())
+ return;
+ FillSlideList(theActiveRoot);
+}
+
+//=============================================================================
+/**
+ * Callback that inAsset has its name changed, fire off a signal to the UI control.
+ * All the assets' signals are connected to this object and we'll let the UI control check iterate
+ * through the list for changes and refresh.
+ * Alternative we can set up additional classes that listens to specific assets and only the asset
+ * affected refreshed. the former is easier for now.
+ */
+void CTimelineBreadCrumbProvider::OnNameDirty()
+{
+ SigBreadCrumbUpdate();
+}
+
+void CTimelineBreadCrumbProvider::ClearSlideList()
+{
+ m_Connections.clear();
+ m_BreadCrumbList.clear();
+}
+
+//=============================================================================
+/**
+ * This will recurse up the time context tree, so that we can fill the list in a top-down (i.e
+ * Scene) first manner
+ */
+void CTimelineBreadCrumbProvider::FillSlideList(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (!inInstance.Valid())
+ return;
+
+ CClientDataModelBridge *theBridge = m_Doc->GetStudioSystem()->GetClientDataModelBridge();
+ ISlideSystem *theSlideSystem = m_Doc->GetStudioSystem()->GetSlideSystem();
+ Q3DStudio::CId theId = theBridge->GetGUID(inInstance);
+
+ // Recurse
+ FillSlideList(theBridge->GetParentComponent(inInstance));
+
+ m_BreadCrumbList.push_back(inInstance);
+
+ CUICDMPropertyHandle theNameProp =
+ m_Doc->GetStudioSystem()->GetClientDataModelBridge()->GetNameProperty();
+ IStudioFullSystemSignalProvider *theEngine =
+ m_Doc->GetStudioSystem()->GetFullSystemSignalProvider();
+ std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle)> theSetter(
+ std::bind(&CTimelineBreadCrumbProvider::OnNameDirty, this));
+
+ // Listen to name changes on the Asset
+ m_Connections.push_back(theEngine->ConnectInstancePropertyValue(
+ std::bind(UICDM::MaybackCallbackInstancePropertyValue<std::function<void(
+ CUICDMInstanceHandle, CUICDMPropertyHandle)>>,
+ std::placeholders::_1, std::placeholders::_2, inInstance, theNameProp, theSetter)));
+
+ // Listen to name changes on the non-master Slides
+ UICDM::CUICDMSlideHandle theMasterSlide =
+ theSlideSystem->GetMasterSlideByComponentGuid(GuidtoSLong4(theId));
+ long theSlideCount = (long)theSlideSystem->GetSlideCount(theMasterSlide);
+
+ for (long theIndex = 1; theIndex < theSlideCount; ++theIndex) {
+ CUICDMSlideHandle theSlide = theSlideSystem->GetSlideByIndex(theMasterSlide, theIndex);
+ CUICDMInstanceHandle theSlideInstance = theSlideSystem->GetSlideInstance(theSlide);
+ m_Connections.push_back(theEngine->ConnectInstancePropertyValue(
+ std::bind(UICDM::MaybackCallbackInstancePropertyValue<std::function<void(
+ CUICDMInstanceHandle, CUICDMPropertyHandle)>>,
+ std::placeholders::_1, std::placeholders::_2, theSlideInstance, theNameProp, theSetter)));
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.h
new file mode 100644
index 00000000..d71b57b9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineBreadCrumbProvider.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BREADCRUMBPROVIDER_H
+#define INCLUDED_BREADCRUMBPROVIDER_H 1
+
+#pragma once
+
+#include "IBreadCrumbProvider.h"
+#include "UICDMSignals.h"
+
+// Link to data model
+class CDoc;
+class CTimelineBreadCrumbProvider;
+
+//=============================================================================
+/**
+ * Bread crumb provider for displaying a trail of time contexts
+ */
+class CTimelineBreadCrumbProvider : public IBreadCrumbProvider
+{
+public:
+ CTimelineBreadCrumbProvider(CDoc *inDoc);
+ virtual ~CTimelineBreadCrumbProvider();
+
+ TTrailList GetTrail(bool inRefresh = true) override;
+ void OnBreadCrumbClicked(long inTrailIndex) override;
+
+ QPixmap GetRootImage() const override;
+ QPixmap GetBreadCrumbImage() const override;
+ QPixmap GetSeparatorImage() const override;
+ QPixmap GetActiveBreadCrumbImage() const override;
+
+ void RefreshSlideList();
+ void OnNameDirty();
+
+protected:
+ void ClearSlideList();
+ void FillSlideList(UICDM::CUICDMInstanceHandle inInstance);
+
+protected:
+ std::vector<UICDM::CUICDMInstanceHandle> m_BreadCrumbList;
+ CDoc *m_Doc;
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>>
+ m_Connections; /// connections to the UICDM
+};
+
+#endif // INCLUDED_BREADCRUMBPROVIDER_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp
new file mode 100644
index 00000000..cc28b0cc
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp
@@ -0,0 +1,599 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TimelineTranslationManager.h"
+#include "SlideTimelineItemBinding.h"
+#include "GroupTimelineItemBinding.h"
+#include "BehaviorTimelineItemBinding.h"
+#include "MaterialTimelineItemBinding.h"
+#include "ImageTimelineItemBinding.h"
+#include "PathAnchorPointTimelineItemBinding.h"
+#include "PathTimelineItemBinding.h"
+#include "LayerTimelineItemBinding.h"
+#include "KeyframesManager.h"
+#include "TimelineBreadCrumbProvider.h"
+#include "BaseStateRow.h"
+#include "PropertyRow.h"
+#include "IDoc.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+#include "UICDMSignals.h"
+
+// Link to Data model
+#include "ClientDataModelBridge.h"
+#include "UICDMDataCore.h"
+#include "Doc.h" //Because we need to access Client Data Model Bridge
+#include "StudioApp.h"
+#include "Core.h"
+
+using namespace UICDM;
+
+CTimelineTranslationManager::CTimelineTranslationManager()
+{
+ m_KeyframesManager = new CKeyframesManager(this);
+ m_BreadCrumbProvider = new CTimelineBreadCrumbProvider(g_StudioApp.GetCore()->GetDoc());
+}
+
+CTimelineTranslationManager::~CTimelineTranslationManager()
+{
+ // clean up all bindings
+ Clear();
+ m_Connections.clear();
+ delete m_KeyframesManager;
+ delete m_BreadCrumbProvider;
+}
+
+ITimelineItemBinding *CTimelineTranslationManager::GetOrCreate(CUICDMInstanceHandle inInstance)
+{
+ ITimelineItemBinding *theBinding = GetBinding(inInstance);
+ if (!theBinding) {
+ CUICDMTimelineItemBinding *theReturn = nullptr;
+ UICDM::IPropertySystem *thePropertySystem = GetStudioSystem()->GetPropertySystem();
+ CUICDMPropertyHandle theTypeProperty =
+ thePropertySystem->GetAggregateInstancePropertyByName(inInstance, L"type");
+
+ SValue theTypeValue;
+ thePropertySystem->GetInstancePropertyValue(inInstance, theTypeProperty, theTypeValue);
+
+ std::wstring theWideTypeString(UICDM::get<TDataStrPtr>(theTypeValue)->GetData());
+
+ if (theWideTypeString == L"Material" || theWideTypeString == L"CustomMaterial"
+ || theWideTypeString == L"ReferencedMaterial")
+ theReturn = new CMaterialTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Image")
+ theReturn = new CImageTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Group" || theWideTypeString == L"Component")
+ theReturn = new CGroupTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Behavior")
+ theReturn = new CBehaviorTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Slide")
+ theReturn = new CSlideTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"PathAnchorPoint")
+ theReturn = new CPathAnchorPointTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Path")
+ theReturn = new CPathTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Layer")
+ theReturn = new CLayerTimelineItemBinding(this, inInstance);
+ else if (theWideTypeString == L"Model" || theWideTypeString == L"Text"
+ || theWideTypeString == L"Camera" || theWideTypeString == L"Effect"
+ || theWideTypeString == L"Light" || theWideTypeString == L"RenderPlugin"
+ || theWideTypeString == L"Alias" || theWideTypeString == L"SubPath")
+ theReturn = new CUICDMTimelineItemBinding(this, inInstance);
+ else {
+ // Add support for additional UICDM types here.
+ ASSERT(0);
+ }
+
+ m_InstanceHandleBindingMap.insert(
+ std::make_pair(theReturn->GetInstanceHandle(), theReturn));
+ m_InstanceHandleExpandedMap.insert(std::make_pair(theReturn->GetInstanceHandle(), false));
+ theBinding = theReturn;
+ }
+
+ return theBinding;
+}
+
+//==============================================================================
+/**
+ * Create a new CPropertyRow that maps to this ITimelineItemProperty.
+ * The caller is assumed to have ensured that this is only called once per property binding.
+ */
+void CTimelineTranslationManager::CreateNewPropertyRow(
+ ITimelineItemProperty *inTimelineItemPropertyBinding, CBaseStateRow *inParentRow,
+ CPropertyRow *inNextRow)
+{
+ if (!inParentRow || !inTimelineItemPropertyBinding)
+ return;
+
+ CPropertyRow *theNewRow = new CPropertyRow(inTimelineItemPropertyBinding);
+ inParentRow->AddPropertyRow(theNewRow, inNextRow);
+ inTimelineItemPropertyBinding->Bind(theNewRow);
+}
+
+//==============================================================================
+/**
+ * Does the reverse of CreateNewPropertyRow, when a property has been de-animated.
+ */
+void CTimelineTranslationManager::RemovePropertyRow(
+ ITimelineItemProperty *inTimelineItemPropertyBinding)
+{
+ CPropertyRow *theRow = nullptr;
+ if (!inTimelineItemPropertyBinding
+ || (theRow = inTimelineItemPropertyBinding->GetRow()) == nullptr)
+ return;
+
+ CBaseStateRow *theParentRow = theRow->GetParentRow();
+ if (theParentRow) {
+ inTimelineItemPropertyBinding->Release();
+ theParentRow->RemovePropertyRow(theRow); // this implicitly delete the row
+ }
+}
+
+//==============================================================================
+/**
+ * Clear all bindings, typically when a presentation is closed.
+ */
+void CTimelineTranslationManager::Clear()
+{
+ // clean up all bindings
+ m_InstanceHandleBindingMap.clear();
+}
+
+//==============================================================================
+/**
+ * Called when the associated UI is no longer valid.
+ */
+void CTimelineTranslationManager::Unregister(ITimelineItemBinding *inTimelineItem)
+{
+ // UICDM
+ bool theDeselectItem = false;
+ TInstanceHandleBindingMap::iterator theInstanceIter = m_InstanceHandleBindingMap.begin();
+ for (; theInstanceIter != m_InstanceHandleBindingMap.end(); ++theInstanceIter) {
+ if (theInstanceIter->second == inTimelineItem) {
+ // If this is the currently selected object and make sure that is cleared.
+ UICDM::CUICDMInstanceHandle theSelectedInstance =
+ g_StudioApp.GetCore()->GetDoc()->GetSelectedInstance();
+ if (theSelectedInstance.Valid() && theSelectedInstance == theInstanceIter->first)
+ theDeselectItem = true;
+
+ m_InstanceHandleBindingMap.erase(theInstanceIter);
+ break;
+ }
+ }
+
+ delete inTimelineItem;
+}
+
+CKeyframesManager *CTimelineTranslationManager::GetKeyframesManager() const
+{
+ return m_KeyframesManager;
+}
+
+IBreadCrumbProvider *CTimelineTranslationManager::GetBreadCrumbProvider() const
+{
+ return m_BreadCrumbProvider;
+}
+
+CBaseStateRow *CTimelineTranslationManager::GetSelectedRow() const
+{
+ ITimelineItemBinding *theBinding = GetSelectedBinding();
+ if (theBinding)
+ return theBinding->GetRow();
+ return nullptr;
+}
+
+long CTimelineTranslationManager::GetCurrentViewTime() const
+{
+ return g_StudioApp.GetCore()->GetDoc()->GetCurrentViewTime();
+}
+
+//==============================================================================
+/**
+ * @return the Binding object that corresponds to this instance.
+ */
+CUICDMTimelineItemBinding *
+CTimelineTranslationManager::GetBinding(CUICDMInstanceHandle inHandle) const
+{
+ TInstanceHandleBindingMap::const_iterator theIter = m_InstanceHandleBindingMap.find(inHandle);
+ if (theIter != m_InstanceHandleBindingMap.end())
+ return theIter->second;
+ return nullptr;
+}
+
+CUICDMTimelineItemBinding *CTimelineTranslationManager::GetSelectedBinding() const
+{
+ UICDM::CUICDMInstanceHandle theSelectedInstance =
+ g_StudioApp.GetCore()->GetDoc()->GetSelectedInstance();
+ if (theSelectedInstance.Valid()) {
+ CUICDMTimelineItemBinding *theBinding = GetBinding(theSelectedInstance);
+ return theBinding;
+ }
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Triggered from individual binding classes, to clear all keyframe selection
+ */
+void CTimelineTranslationManager::ClearKeyframeSelection()
+{
+ m_KeyframesManager->DeselectAllKeyframes();
+}
+
+//==============================================================================
+/**
+ * Set up callbacks for animation changes
+ */
+void CTimelineTranslationManager::OnNewPresentation()
+{
+ m_Connections.clear();
+ m_InstanceHandleExpandedMap.clear();
+
+ IStudioFullSystemSignalProvider *theSignalProvider =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+ m_Connections.push_back(theSignalProvider->ConnectAnimationCreated(
+ std::bind(&CTimelineTranslationManager::OnAnimationCreated, this,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theSignalProvider->ConnectAnimationDeleted(
+ std::bind(&CTimelineTranslationManager::OnAnimationDeleted, this,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theSignalProvider->ConnectPropertyLinked(
+ std::bind(&CTimelineTranslationManager::OnPropertyLinked, this,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theSignalProvider->ConnectPropertyUnlinked(
+ std::bind(&CTimelineTranslationManager::OnPropertyUnlinked, this,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theSignalProvider->ConnectKeyframeInserted(
+ std::bind(&CTimelineTranslationManager::OnKeyframeInserted, this,
+ std::placeholders::_1, std::placeholders::_2)));
+ m_Connections.push_back(theSignalProvider->ConnectKeyframeErased(
+ std::bind(&CTimelineTranslationManager::OnKeyframeDeleted, this,
+ std::placeholders::_1, std::placeholders::_2)));
+ m_Connections.push_back(theSignalProvider->ConnectKeyframeUpdated(
+ std::bind(&CTimelineTranslationManager::OnKeyframeUpdated, this, std::placeholders::_1)));
+ m_Connections.push_back(theSignalProvider->ConnectInstancePropertyValue(
+ std::bind(&CTimelineTranslationManager::OnPropertyChanged, this,
+ std::placeholders::_1, std::placeholders::_2)));
+ m_Connections.push_back(theSignalProvider->ConnectFirstKeyframeDynamicSet(
+ std::bind(&CTimelineTranslationManager::OnDynamicKeyframeChanged, this,
+ std::placeholders::_1, std::placeholders::_2)));
+
+ m_Connections.push_back(theSignalProvider->ConnectInstanceCreated(
+ std::bind(&CTimelineTranslationManager::OnAssetCreated, this, std::placeholders::_1)));
+ m_Connections.push_back(theSignalProvider->ConnectInstanceDeleted(
+ std::bind(&CTimelineTranslationManager::OnAssetDeleted, this, std::placeholders::_1)));
+
+ m_Connections.push_back(theSignalProvider->ConnectActionCreated(
+ std::bind(&CTimelineTranslationManager::OnActionEvent, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theSignalProvider->ConnectActionDeleted(
+ std::bind(&CTimelineTranslationManager::OnActionEvent, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+
+ Q3DStudio::CGraph &theGraph(*g_StudioApp.GetCore()->GetDoc()->GetAssetGraph());
+ m_Connections.push_back(theGraph.ConnectChildAdded(
+ std::bind(&CTimelineTranslationManager::OnChildAdded, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theGraph.ConnectChildRemoved(
+ std::bind(&CTimelineTranslationManager::OnChildRemoved, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theGraph.ConnectChildMoved(
+ std::bind(&CTimelineTranslationManager::OnChildMoved, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)));
+}
+
+//==============================================================================
+/**
+ * Selection events on the old data model was triggered via signals on the actual objects.
+ * For the new data model, it would be via this OnSelectionChange event.
+ */
+void CTimelineTranslationManager::OnSelectionChange(Q3DStudio::SSelectedValue inNewSelectable)
+{
+ // Deselect all items
+ TInstanceHandleBindingMap::const_iterator theIter = m_InstanceHandleBindingMap.begin();
+ for (; theIter != m_InstanceHandleBindingMap.end(); ++theIter) {
+ ITimelineItemBinding *theBinding = theIter->second;
+ CBaseStateRow *theRow = theBinding->GetRow();
+ if (theRow)
+ theRow->OnSelected(false);
+ }
+
+ // Select new
+ if (inNewSelectable)
+ SetSelected(inNewSelectable, true);
+}
+
+CDoc *CTimelineTranslationManager::GetDoc() const
+{
+ return dynamic_cast<CDoc *>(g_StudioApp.GetCore()->GetDoc());
+}
+
+CStudioSystem *CTimelineTranslationManager::GetStudioSystem() const
+{
+ // TODO: figure if we can just deal with IDoc instead of CDoc
+ return g_StudioApp.GetCore()->GetDoc()->GetStudioSystem();
+}
+
+void CTimelineTranslationManager::OnAnimationCreated(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ CUICDMTimelineItemBinding *theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(inInstance));
+ if (theTimelineBinding)
+ theTimelineBinding->AddPropertyRow(inProperty);
+}
+
+void CTimelineTranslationManager::OnAnimationDeleted(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ CUICDMTimelineItemBinding *theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(inInstance));
+ if (theTimelineBinding)
+ theTimelineBinding->RemovePropertyRow(inProperty);
+}
+
+void CTimelineTranslationManager::OnPropertyLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ CUICDMTimelineItemBinding *theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(inInstance));
+ if (theTimelineBinding)
+ theTimelineBinding->OnPropertyLinked(inProperty);
+}
+
+void CTimelineTranslationManager::OnPropertyUnlinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ OnPropertyLinked(inInstance, inProperty);
+}
+
+void CTimelineTranslationManager::RefreshKeyframe(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe,
+ ETimelineKeyframeTransaction inTransaction)
+{
+ CUICDMTimelineItemBinding *theTimelineBinding = nullptr;
+ if (GetStudioSystem()->GetAnimationCore()->AnimationValid(inAnimation)) {
+ SAnimationInfo theAnimationInfo =
+ GetStudioSystem()->GetAnimationCore()->GetAnimationInfo(inAnimation);
+ theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(theAnimationInfo.m_Instance));
+
+ if (theTimelineBinding)
+ theTimelineBinding->RefreshPropertyKeyframe(theAnimationInfo.m_Property, inKeyframe,
+ inTransaction);
+ }
+ // else, animation has been nuked, ignore this event, we'll get a AnimationDelete
+}
+
+void CTimelineTranslationManager::OnKeyframeInserted(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe)
+{
+ RefreshKeyframe(inAnimation, inKeyframe, ETimelineKeyframeTransaction_Add);
+}
+
+void CTimelineTranslationManager::OnKeyframeDeleted(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe)
+{
+ RefreshKeyframe(inAnimation, inKeyframe, ETimelineKeyframeTransaction_Delete);
+}
+
+void CTimelineTranslationManager::OnKeyframeUpdated(CUICDMKeyframeHandle inKeyframe)
+{
+ IAnimationCore *theAnimationCore = GetStudioSystem()->GetAnimationCore();
+ if (theAnimationCore->KeyframeValid(inKeyframe)) {
+ CUICDMAnimationHandle theAnimationHandle =
+ theAnimationCore->GetAnimationForKeyframe(inKeyframe);
+ RefreshKeyframe(theAnimationHandle, inKeyframe, ETimelineKeyframeTransaction_Update);
+ }
+ // else, keyframe has been nuked, ignore this event, we'll get a KeyframeDeleted
+}
+
+void CTimelineTranslationManager::OnPropertyChanged(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty)
+{
+ CUICDMTimelineItemBinding *theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(inInstance));
+ if (theTimelineBinding)
+ theTimelineBinding->OnPropertyChanged(inProperty);
+}
+
+void CTimelineTranslationManager::OnDynamicKeyframeChanged(UICDM::CUICDMAnimationHandle inAnimation,
+ bool inDynamic)
+{
+ Q_UNUSED(inDynamic);
+
+ CUICDMTimelineItemBinding *theTimelineBinding = nullptr;
+ if (GetStudioSystem()->GetAnimationCore()->AnimationValid(inAnimation)) {
+ SAnimationInfo theAnimationInfo =
+ GetStudioSystem()->GetAnimationCore()->GetAnimationInfo(inAnimation);
+ theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(theAnimationInfo.m_Instance));
+ if (theTimelineBinding)
+ theTimelineBinding->RefreshPropertyKeyframe(
+ theAnimationInfo.m_Property, 0, ETimelineKeyframeTransaction_DynamicChanged);
+ }
+}
+
+void CTimelineTranslationManager::OnAssetCreated(UICDM::CUICDMInstanceHandle inInstance)
+{
+ CClientDataModelBridge *theDataModelBridge = GetStudioSystem()->GetClientDataModelBridge();
+
+ if (theDataModelBridge->IsSceneGraphInstance(inInstance))
+ EnsureLoaded(inInstance);
+}
+
+void CTimelineTranslationManager::OnAssetDeleted(UICDM::CUICDMInstanceHandle inInstance)
+{
+ // You can't assume the instance is valid. Someone may have deleted a large number of items
+ // from the model and then decided to send notifications after the fact.
+ // if the created asset is library asset, do nothing
+ // start to add the scene asset to the timeline
+ CUICDMTimelineItemBinding *theItemBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(inInstance));
+ if (theItemBinding) {
+ CUICDMTimelineItemBinding *theParentBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(theItemBinding->GetParent());
+ if (theParentBinding)
+ theParentBinding->OnDeleteChild(inInstance);
+ }
+}
+
+void CTimelineTranslationManager::OnChildAdded(int /*inParent*/, int inChild, long /*inIndex*/)
+{
+ OnAssetCreated(inChild);
+}
+void CTimelineTranslationManager::OnChildRemoved(int /*inParent*/, int inChild, long /*inIndex*/)
+{
+ OnAssetDeleted(inChild);
+}
+void CTimelineTranslationManager::OnChildMoved(int /*inParent*/, int inChild, long /*inOldIndex*/,
+ long /*inNewIndex*/)
+{
+ OnAssetDeleted(inChild);
+ OnAssetCreated(inChild);
+}
+
+//==============================================================================
+/**
+ * Callback method whenever an action is either created or removed.
+ * Basically, it tells the owner of the action to update its timeline control to
+ * update the icon that shows action association status
+ */
+void CTimelineTranslationManager::OnActionEvent(UICDM::CUICDMActionHandle inAction,
+ UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMInstanceHandle inOwner)
+{
+ Q_UNUSED(inAction);
+
+ // the slide that action is added to is the current slide or
+ // is added to the master slide of the current slide
+ CUICDMTimelineItemBinding *theTimelineBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetBinding(inOwner));
+ if (theTimelineBinding)
+ theTimelineBinding->UpdateActionStatus();
+}
+
+//==============================================================================
+/**
+ * Helper functions to go through ALL binding and clear any keyframes selection.
+ */
+void CTimelineTranslationManager::ClearBindingsKeyframeSelection()
+{
+ // UICDM bindings handle their own selections
+ TInstanceHandleBindingMap::const_iterator theIter = m_InstanceHandleBindingMap.begin();
+ for (; theIter != m_InstanceHandleBindingMap.end(); ++theIter)
+ theIter->second->DoSelectKeyframes(false, -1, true);
+}
+
+//==============================================================================
+/**
+ * Helper function to find the binding that corresponds to inSelectable and set its selection state
+ */
+void CTimelineTranslationManager::SetSelected(Q3DStudio::SSelectedValue inSelectable,
+ bool inSelected)
+{
+ UICDM::TInstanceHandleList theInstances = inSelectable.GetSelectedInstances();
+ for (size_t idx = 0, end = theInstances.size(); idx < end; ++idx) {
+ CUICDMInstanceHandle theInstance(theInstances[idx]);
+ if (GetStudioSystem()->IsInstance(theInstance)) {
+ ITimelineItemBinding *theBinding = EnsureLoaded(theInstance);
+ if (theBinding) {
+ CBaseStateRow *theRow = theBinding->GetRow();
+ if (theRow)
+ theRow->OnSelected(inSelected);
+ }
+ }
+ }
+}
+
+ITimelineItemBinding *CTimelineTranslationManager::EnsureLoaded(CUICDMInstanceHandle inHandle)
+{
+ ITimelineItemBinding *theBinding = GetBinding(inHandle);
+ bool rowLoaded = theBinding != nullptr && theBinding->GetRow() != nullptr;
+ if (rowLoaded == false) {
+ // tell my parent to load me
+ CClientDataModelBridge *theDataModelBridge = GetStudioSystem()->GetClientDataModelBridge();
+ CUICDMInstanceHandle theParent = theDataModelBridge->GetParentInstance(inHandle);
+ if (theParent.Valid()) {
+ ITimelineItemBinding *theParentBinding = EnsureLoaded(theParent);
+ if (theParentBinding)
+ theParentBinding->GetRow()->LoadChildren();
+
+ // The LoadChildren has an optimzation such that if it's already loaded, it won't
+ // recreate again
+ // So, if we still can't get the binding after LoadChildren, it very likely means that
+ // this is newly added
+ // so call OnAddChild to let it just add this.
+ theBinding = GetBinding(inHandle);
+ bool rowLoaded = theBinding != nullptr && theBinding->GetRow() != nullptr;
+ if (theParentBinding && rowLoaded == false) {
+ // start to add the scene asset to the timeline
+ CUICDMTimelineItemBinding *theUICDMBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(theParentBinding);
+ theUICDMBinding->OnAddChild(inHandle);
+ theBinding = GetBinding(inHandle);
+ }
+ }
+ }
+ return theBinding;
+}
+
+//==============================================================================
+/**
+ * remember the expanded state for the current presentation
+ */
+bool CTimelineTranslationManager::IsExpanded(CUICDMInstanceHandle inInstance) const
+{
+ TInstanceHandleExpandedMap::const_iterator theIter =
+ m_InstanceHandleExpandedMap.find(inInstance);
+ if (theIter != m_InstanceHandleExpandedMap.end()) {
+ return theIter->second;
+ }
+ return false;
+}
+
+//==============================================================================
+/**
+ * remember the expanded state for the current presentation
+ */
+void CTimelineTranslationManager::SetExpanded(CUICDMInstanceHandle inInstance, bool inExpanded)
+{
+ TInstanceHandleExpandedMap::iterator theIter = m_InstanceHandleExpandedMap.find(inInstance);
+ if (theIter != m_InstanceHandleExpandedMap.end()) {
+ theIter->second = inExpanded;
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.h
new file mode 100644
index 00000000..48f7bebe
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/TimelineTranslationManager.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TIMELINE_TRANSLATIONMANAGER_H
+#define INCLUDED_TIMELINE_TRANSLATIONMANAGER_H 1
+
+#pragma once
+
+#include "UICDMHandles.h"
+#include "UICDMTimeline.h"
+
+#include "Doc.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class ITimelineItemBinding;
+class ITimelineItemProperty;
+class CUICDMTimelineItemBinding;
+class CBaseStateRow;
+class CPropertyRow;
+class CKeyframesManager;
+class IBreadCrumbProvider;
+
+// Link to data model
+class CAsset;
+class IUICDMSelectable;
+class CClientDataModelBridge;
+
+// UICDM
+namespace UICDM {
+class CStudioSystem;
+class ISignalConnection;
+}
+
+class CDoc;
+
+//=============================================================================
+/**
+ * There is a TranslationManager per presentation (project)
+ */
+class CTimelineTranslationManager
+{
+protected: // Typedefs
+ // UICDM support
+ typedef std::map<UICDM::CUICDMInstanceHandle, CUICDMTimelineItemBinding *>
+ TInstanceHandleBindingMap;
+
+ // Store expanded state
+ typedef std::map<UICDM::CUICDMInstanceHandle, bool> TInstanceHandleExpandedMap; // UICDM support
+
+protected: // Properties
+ // UICDM support
+ TInstanceHandleBindingMap m_InstanceHandleBindingMap;
+
+ CKeyframesManager *m_KeyframesManager;
+ IBreadCrumbProvider *m_BreadCrumbProvider;
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>>
+ m_Connections; /// connections to the UICDM
+
+ TInstanceHandleExpandedMap m_InstanceHandleExpandedMap;
+
+public:
+ CTimelineTranslationManager();
+ ~CTimelineTranslationManager();
+
+public:
+ ITimelineItemBinding *GetOrCreate(UICDM::CUICDMInstanceHandle inInstance);
+ void CreateNewPropertyRow(ITimelineItemProperty *inTimelineItemPropertyBinding,
+ CBaseStateRow *inParentRow, CPropertyRow *inNextRow);
+ void RemovePropertyRow(ITimelineItemProperty *inTimelineItemPropertyBinding);
+
+ void Clear();
+ void Unregister(ITimelineItemBinding *inTimelineItem);
+
+ CKeyframesManager *GetKeyframesManager() const;
+ IBreadCrumbProvider *GetBreadCrumbProvider() const;
+ CBaseStateRow *GetSelectedRow() const;
+ long GetCurrentViewTime() const;
+ CUICDMTimelineItemBinding *GetBinding(UICDM::CUICDMInstanceHandle inHandle) const;
+ CUICDMTimelineItemBinding *GetSelectedBinding() const;
+
+ void ClearKeyframeSelection();
+ void OnNewPresentation();
+ void OnSelectionChange(Q3DStudio::SSelectedValue inNewSelectable);
+
+ UICDM::CStudioSystem *GetStudioSystem() const;
+
+ // UICDM callback
+ void OnAnimationCreated(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ void OnAnimationDeleted(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ void OnPropertyLinked(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ void OnPropertyUnlinked(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ void RefreshKeyframe(UICDM::CUICDMAnimationHandle inAnimation,
+ UICDM::CUICDMKeyframeHandle inKeyframe,
+ ETimelineKeyframeTransaction inTransaction);
+ void OnKeyframeInserted(UICDM::CUICDMAnimationHandle inAnimation,
+ UICDM::CUICDMKeyframeHandle inKeyframe);
+ void OnKeyframeDeleted(UICDM::CUICDMAnimationHandle inAnimation,
+ UICDM::CUICDMKeyframeHandle inKeyframe);
+ void OnKeyframeUpdated(UICDM::CUICDMKeyframeHandle inKeyframe);
+ void OnPropertyChanged(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ void OnDynamicKeyframeChanged(UICDM::CUICDMAnimationHandle inAnimation, bool inDynamic);
+
+ void OnAssetCreated(UICDM::CUICDMInstanceHandle inInstance);
+ void OnAssetDeleted(UICDM::CUICDMInstanceHandle inInstance);
+ void OnChildAdded(int inParent, int inChild, long inIndex);
+ void OnChildRemoved(int inParent, int inChild, long inIndex);
+ void OnChildMoved(int inParent, int inChild, long inOldIndex, long inNewIndex);
+
+ void OnActionEvent(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMInstanceHandle inOwner);
+
+ // Helper function to iterate over all bindings
+ void ClearBindingsKeyframeSelection();
+ CDoc *GetDoc() const;
+
+ // Store expanded state
+ bool IsExpanded(UICDM::CUICDMInstanceHandle inInstance) const;
+ void SetExpanded(UICDM::CUICDMInstanceHandle inInstance, bool inExpanded);
+
+protected:
+ void SetSelected(Q3DStudio::SSelectedValue inSelectable, bool inSelected);
+ ITimelineItemBinding *EnsureLoaded(UICDM::CUICDMInstanceHandle inHandle);
+};
+
+#endif // INCLUDED_TIMELINE_TRANSLATIONMANAGER_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.cpp
new file mode 100644
index 00000000..4eb0f906
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICDMAssetTimelineKeyframe.h"
+#include "UICDMTimelineItemBinding.h"
+
+using namespace UICDM;
+
+CUICDMAssetTimelineKeyframe::CUICDMAssetTimelineKeyframe(CUICDMTimelineItemBinding *inOwningBinding,
+ long inTime)
+ : m_OwningBinding(inOwningBinding)
+ , m_Time(inTime)
+ , m_Selected(false)
+{
+}
+
+CUICDMAssetTimelineKeyframe::~CUICDMAssetTimelineKeyframe()
+{
+}
+
+bool CUICDMAssetTimelineKeyframe::IsSelected() const
+{
+ return m_Selected;
+}
+
+long CUICDMAssetTimelineKeyframe::GetTime() const
+{
+ return m_Time;
+}
+
+void CUICDMAssetTimelineKeyframe::SetTime(const long inNewTime)
+{
+ Q_UNUSED(inNewTime);
+ // note: this is not used. because setting time is currently only done through offsetting by
+ // moving keyframes OR using the edit time dialog.
+ ASSERT(0);
+}
+
+void CUICDMAssetTimelineKeyframe::SetDynamic(bool inIsDynamic)
+{
+ m_OwningBinding->SetDynamicKeyframes(m_Time, inIsDynamic);
+}
+
+bool CUICDMAssetTimelineKeyframe::IsDynamic() const
+{
+ // return true if any of its property keyframes is dynamic
+ return m_OwningBinding->HasDynamicKeyframes(m_Time);
+}
+
+void CUICDMAssetTimelineKeyframe::SetSelected(bool inSelected)
+{
+ m_Selected = inSelected;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.h
new file mode 100644
index 00000000..e8cf6870
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMAssetTimelineKeyframe.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_UICDMASSETKEYFRAME_H
+#define INCLUDED_UICDMASSETKEYFRAME_H 1
+
+#pragma once
+
+#include "IKeyframe.h"
+
+// Data model specific
+#include "UICDMHandles.h"
+
+class CUICDMTimelineItemBinding;
+
+//==============================================================================
+/**
+ * Represents a keyframe displayed for a Asset( e.g. material ), for all keyframes (of the
+ *animated properties) at time t.
+ */
+//==============================================================================
+class CUICDMAssetTimelineKeyframe : public IKeyframe
+{
+protected:
+ CUICDMTimelineItemBinding *m_OwningBinding;
+ long m_Time;
+ bool m_Selected;
+
+public:
+ CUICDMAssetTimelineKeyframe(CUICDMTimelineItemBinding *inOwningBinding, long inTime);
+ virtual ~CUICDMAssetTimelineKeyframe();
+
+ // IKeyframe
+ bool IsSelected() const override;
+ long GetTime() const override;
+ void SetTime(const long inNewTime) override;
+ void SetDynamic(bool inIsDynamic) override;
+ bool IsDynamic() const override;
+
+ void SetSelected(bool inSelected);
+ void UpdateTime(const long inTime) { m_Time = inTime; }
+};
+
+#endif // INCLUDED_UICDMKEYFRAME_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimeline.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimeline.h
new file mode 100644
index 00000000..7989956f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimeline.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_UICDMTIMELINE_H
+#define INCLUDED_UICDMTIMELINE_H 1
+
+#pragma once
+
+enum ETimelineKeyframeTransaction {
+ ETimelineKeyframeTransaction_Add,
+ ETimelineKeyframeTransaction_Delete,
+ ETimelineKeyframeTransaction_Update,
+ ETimelineKeyframeTransaction_DynamicChanged,
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.cpp
new file mode 100644
index 00000000..b6dd94d9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.cpp
@@ -0,0 +1,1260 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMTimelineItemBinding.h"
+#include "TimelineTranslationManager.h"
+#include "TimeEditDlg.h"
+#include "EmptyTimelineTimebar.h"
+#include "UICDMTimelineTimebar.h"
+#include "BaseStateRow.h"
+#include "BaseTimebarlessRow.h"
+#include "PropertyTimebarRow.h"
+#include "PropertyRow.h"
+#include "KeyframesManager.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "Dialogs.h"
+#include "GraphUtils.h"
+#include "UICDMDataCore.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+// Data model specific
+#include "IDoc.h"
+#include "ClientDataModelBridge.h"
+#include "Dispatch.h"
+#include "DropSource.h"
+#include "UICDMTimelineItemProperty.h"
+#include "UICDMSlides.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlideGraphCore.h"
+#include "UICDMActionCore.h"
+#include "UICDMAnimation.h"
+#include "CmdDataModelChangeKeyframe.h"
+#include "RelativePathTools.h"
+#include "IDocumentEditor.h"
+#include "UICFileTools.h"
+#include "ImportUtils.h"
+
+#include <QMessageBox>
+
+using namespace UICDM;
+
+CUICDMTimelineItemBinding::CUICDMTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ CUICDMInstanceHandle inDataHandle)
+ : m_Row(nullptr)
+ , m_TransMgr(inMgr)
+ , m_DataHandle(inDataHandle)
+ , m_Parent(nullptr)
+ , m_TimelineTimebar(nullptr)
+
+{
+ m_StudioSystem = m_TransMgr->GetStudioSystem();
+ m_TransMgr->GetDoc()->GetCore()->GetDispatch()->AddDataModelListener(this);
+}
+
+CUICDMTimelineItemBinding::CUICDMTimelineItemBinding(CTimelineTranslationManager *inMgr)
+ : m_Row(nullptr)
+ , m_TransMgr(inMgr)
+ , m_DataHandle(0)
+ , m_Parent(nullptr)
+ , m_TimelineTimebar(nullptr)
+{
+ m_StudioSystem = m_TransMgr->GetStudioSystem();
+ m_TransMgr->GetDoc()->GetCore()->GetDispatch()->AddDataModelListener(this);
+}
+
+CUICDMTimelineItemBinding::~CUICDMTimelineItemBinding()
+{
+ RemoveAllPropertyBindings();
+ delete m_TimelineTimebar;
+ m_TransMgr->GetDoc()->GetCore()->GetDispatch()->RemoveDataModelListener(this);
+}
+
+// helpers
+bool CUICDMTimelineItemBinding::UICDMGetBoolean(UICDM::CUICDMPropertyHandle inProperty) const
+{
+ UICDM::IPropertySystem *thePropertySystem = m_StudioSystem->GetPropertySystem();
+ SValue theValue;
+ thePropertySystem->GetInstancePropertyValue(m_DataHandle, inProperty, theValue);
+ return UICDM::get<bool>(theValue);
+}
+
+void CUICDMTimelineItemBinding::UICDMSetBoolean(UICDM::CUICDMPropertyHandle inProperty,
+ bool inValue, const QString &inNiceText) const
+{
+ CDoc *theDoc = dynamic_cast<CDoc *>(g_StudioApp.GetCore()->GetDoc());
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*theDoc, inNiceText)
+ ->SetInstancePropertyValue(m_DataHandle, inProperty, inValue);
+}
+
+void CUICDMTimelineItemBinding::SetInstanceHandle(UICDM::CUICDMInstanceHandle inDataHandle)
+{
+ m_DataHandle = inDataHandle;
+}
+
+EStudioObjectType CUICDMTimelineItemBinding::GetObjectType() const
+{
+ return m_StudioSystem->GetClientDataModelBridge()->GetObjectType(m_DataHandle);
+}
+
+bool CUICDMTimelineItemBinding::IsMaster() const
+{
+ CDoc *theDoc = dynamic_cast<CDoc *>(g_StudioApp.GetCore()->GetDoc());
+ Q3DStudio::IDocumentReader &theReader(theDoc->GetDocumentReader());
+ if (GetObjectType() == OBJTYPE_IMAGE) {
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ CUICDMInstanceHandle theParent;
+ CUICDMPropertyHandle theProperty;
+ bool isPropertyLinked;
+
+ theBridge->GetMaterialFromImageInstance(GetInstance(), theParent, theProperty);
+ isPropertyLinked = theReader.IsPropertyLinked(theParent, theProperty);
+
+ // Also check light probe
+ if (!isPropertyLinked) {
+ theBridge->GetLayerFromImageProbeInstance(GetInstance(), theParent, theProperty);
+ isPropertyLinked = theReader.IsPropertyLinked(theParent, theProperty);
+ }
+
+ return isPropertyLinked;
+ }
+ CUICDMInstanceHandle theQueryHandle(m_DataHandle);
+ if (GetObjectType() == OBJTYPE_PATHANCHORPOINT)
+ theQueryHandle = theReader.GetParent(m_DataHandle);
+
+ // logic: you can't unlink name, so if name is linked then, this is master.
+ CUICDMPropertyHandle theNamePropHandle =
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstancePropertyByName(theQueryHandle,
+ L"name");
+ return theReader.IsPropertyLinked(theQueryHandle, theNamePropHandle);
+}
+
+bool CUICDMTimelineItemBinding::IsShy() const
+{
+ return UICDMGetBoolean(m_StudioSystem->GetClientDataModelBridge()->GetSceneAsset().m_Shy);
+}
+void CUICDMTimelineItemBinding::SetShy(bool inShy)
+{
+ UICDMSetBoolean(m_StudioSystem->GetClientDataModelBridge()->GetSceneAsset().m_Shy, inShy,
+ QObject::tr("Shy Toggle"));
+}
+bool CUICDMTimelineItemBinding::IsLocked() const
+{
+ return UICDMGetBoolean(m_StudioSystem->GetClientDataModelBridge()->GetSceneAsset().m_Locked);
+}
+
+void ToggleChildrenLock(Q3DStudio::ScopedDocumentEditor &scopedDocEditor,
+ CUICDMTimelineItemBinding *inTimelineItemBinding,
+ SDataModelSceneAsset inSceneAsset, bool inLocked)
+{
+ scopedDocEditor->SetInstancePropertyValue(inTimelineItemBinding->GetInstanceHandle(),
+ inSceneAsset.m_Locked, inLocked);
+ long childrenCount = inTimelineItemBinding->GetChildrenCount();
+ if (childrenCount == 0)
+ return;
+ for (long i = 0; i < childrenCount; ++i) {
+ CUICDMTimelineItemBinding *child =
+ static_cast<CUICDMTimelineItemBinding *>(inTimelineItemBinding->GetChild(i));
+ ToggleChildrenLock(scopedDocEditor, child, inSceneAsset, inLocked);
+ }
+}
+
+void CUICDMTimelineItemBinding::SetLocked(bool inLocked)
+{
+ CDoc *theDoc = dynamic_cast<CDoc *>(g_StudioApp.GetCore()->GetDoc());
+ Q3DStudio::ScopedDocumentEditor scopedDocEditor(*theDoc, L"SetLock", __FILE__, __LINE__);
+
+ SDataModelSceneAsset sceneAsset = m_StudioSystem->GetClientDataModelBridge()->GetSceneAsset();
+ ToggleChildrenLock(scopedDocEditor, this, sceneAsset, inLocked);
+
+ if (inLocked)
+ g_StudioApp.GetCore()->GetDoc()->NotifySelectionChanged();
+}
+
+bool CUICDMTimelineItemBinding::IsVisible() const
+{
+ return UICDMGetBoolean(m_StudioSystem->GetClientDataModelBridge()->GetSceneAsset().m_Eyeball);
+}
+
+void CUICDMTimelineItemBinding::SetVisible(bool inVisible)
+{
+ UICDMSetBoolean(m_StudioSystem->GetClientDataModelBridge()->GetSceneAsset().m_Eyeball,
+ inVisible, QObject::tr("Visibility Toggle"));
+}
+
+// remember the expanded state for the current presentation
+bool CUICDMTimelineItemBinding::IsExpanded() const
+{
+ return m_TransMgr->IsExpanded(m_DataHandle);
+}
+// remember the expanded state for the current presentation
+void CUICDMTimelineItemBinding::SetExpanded(bool inExpanded)
+{
+ m_TransMgr->SetExpanded(m_DataHandle, inExpanded);
+}
+
+bool CUICDMTimelineItemBinding::HasAction(bool inMaster)
+{
+ TActionHandleList theActions;
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+
+ CUICDMSlideHandle theSlide = theDoc->GetActiveSlide();
+ UICDM::ISlideCore &theSlideCore(*m_StudioSystem->GetSlideCore());
+ if (theSlideCore.IsSlide(theSlide)) {
+ if (inMaster)
+ theSlide =
+ m_StudioSystem->GetSlideSystem()->GetMasterSlide(theSlide); // use the master slide
+
+ m_StudioSystem->GetActionCore()->GetActions(theSlide, m_DataHandle, theActions);
+ }
+ return theActions.size() > 0;
+}
+
+bool CUICDMTimelineItemBinding::ChildrenHasAction(bool inMaster)
+{
+ // Get all the instances in this slidegraph
+ // check whehter it's an action instance and is in the slide of interst
+ // check also it's owner is a descendent of the viewed instances
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ IActionCore *theActionCore(m_StudioSystem->GetActionCore());
+ CClientDataModelBridge *theBridge(m_StudioSystem->GetClientDataModelBridge());
+
+ CUICDMSlideHandle theSlide = theDoc->GetActiveSlide();
+ UICDM::ISlideCore &theSlideCore(*m_StudioSystem->GetSlideCore());
+ if (theSlideCore.IsSlide(theSlide)) {
+ if (inMaster)
+ theSlide =
+ m_StudioSystem->GetSlideSystem()->GetMasterSlide(theSlide); // use the master slide
+
+ TSlideInstancePairList theGraphInstances;
+ m_StudioSystem->GetSlideSystem()->GetAssociatedInstances(theSlide, theGraphInstances);
+
+ UICDM::CUICDMInstanceHandle theObservedInstance = GetInstance();
+ if (theObservedInstance.Valid()) {
+ for (TSlideInstancePairList::const_iterator theIter = theGraphInstances.begin();
+ theIter != theGraphInstances.end(); ++theIter) {
+ if (theIter->first == theSlide && theBridge->IsActionInstance(theIter->second)) {
+ CUICDMActionHandle theAction =
+ theActionCore->GetActionByInstance(theIter->second);
+ SActionInfo theActionInfo = theActionCore->GetActionInfo(theAction);
+ CUICDMInstanceHandle theAcionOwner = theActionInfo.m_Owner;
+ if (theAcionOwner.Valid()
+ && IsAscendant(theAcionOwner, theObservedInstance, theDoc->GetAssetGraph()))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CUICDMTimelineItemBinding::ComponentHasAction(bool inMaster)
+{
+ // Get all the instances in this component slidegraph
+ // check whether the instance is an action instance
+ // if inMaster is true, we only interest with those that are in the master slide, else we want
+ // those that are not in the master slide
+ CClientDataModelBridge *theBridge(m_StudioSystem->GetClientDataModelBridge());
+ if (!theBridge->IsComponentInstance(m_DataHandle))
+ return false;
+
+ Q3DStudio::CId theAssetId = theBridge->GetGUID(m_DataHandle);
+ CUICDMSlideHandle theMasterSlide =
+ m_StudioSystem->GetSlideSystem()->GetMasterSlideByComponentGuid(GuidtoSLong4(theAssetId));
+
+ TSlideInstancePairList theGraphInstances;
+ m_StudioSystem->GetSlideSystem()->GetAssociatedInstances(theMasterSlide, theGraphInstances);
+
+ for (TSlideInstancePairList::const_iterator theIter = theGraphInstances.begin();
+ theIter != theGraphInstances.end(); ++theIter) {
+ if (((inMaster && theIter->first == theMasterSlide)
+ || (!inMaster && theIter->first != theMasterSlide))
+ && theBridge->IsActionInstance(theIter->second))
+ return true;
+ }
+ return false;
+}
+
+ITimelineTimebar *CUICDMTimelineItemBinding::GetTimebar()
+{
+ if (!m_TimelineTimebar)
+ m_TimelineTimebar = CreateTimelineTimebar();
+ return m_TimelineTimebar;
+}
+
+Q3DStudio::CString CUICDMTimelineItemBinding::GetName() const
+{
+ if (m_StudioSystem->IsInstance(m_DataHandle) == false)
+ return L"";
+ CUICDMPropertyHandle theNamePropHandle =
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstancePropertyByName(m_DataHandle,
+ L"name");
+ SValue theNameValue;
+ m_StudioSystem->GetPropertySystem()->GetInstancePropertyValue(m_DataHandle, theNamePropHandle,
+ theNameValue);
+ TDataStrPtr theName = UICDM::get<TDataStrPtr>(theNameValue);
+
+ return (theName) ? Q3DStudio::CString(theName->GetData()) : "";
+}
+
+void CUICDMTimelineItemBinding::SetName(const Q3DStudio::CString &inName)
+{
+ // Display warning dialog if user tried to enter an empty string
+ if (inName.IsEmpty()) {
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_OBJECT_RENAME_TITLE));
+ Q3DStudio::CString theString(::LoadResourceString(IDS_ERROR_OBJECT_RENAME_EMPTY_STRING));
+ g_StudioApp.GetDialogs()->DisplayMessageBox(theTitle, theString, CUICMessageBox::ICON_ERROR,
+ false);
+
+ return;
+ }
+
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ if (!theBridge->CheckNameUnique(m_DataHandle, inName)) {
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_OBJECT_RENAME_TITLE));
+ Q3DStudio::CString theString(
+ ::LoadResourceString(IDS_ERROR_OBJECT_RENAME_DUPLICATED_STRING));
+ int theUserChoice = g_StudioApp.GetDialogs()->DisplayChoiceBox(
+ theTitle, theString, CUICMessageBox::ICON_WARNING);
+ if (theUserChoice == QMessageBox::Yes) {
+ // Set with the unique name
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*m_TransMgr->GetDoc(), QObject::tr("Set Name"))
+ ->SetName(m_DataHandle, inName, true);
+ return;
+ }
+ }
+ // Set the name no matter it's unique or not
+ CUICDMPropertyHandle theNamePropHandle =
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstancePropertyByName(m_DataHandle,
+ L"name");
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*m_TransMgr->GetDoc(), QObject::tr("Set Name"))
+ ->SetInstancePropertyValue(m_DataHandle, theNamePropHandle,
+ std::make_shared<CDataStr>(inName));
+}
+
+ITimelineItem *CUICDMTimelineItemBinding::GetTimelineItem()
+{
+ return this;
+}
+
+CBaseStateRow *CUICDMTimelineItemBinding::GetRow()
+{
+ return m_Row;
+}
+
+void CUICDMTimelineItemBinding::SetSelected(bool inMultiSelect)
+{
+ if (!inMultiSelect)
+ g_StudioApp.GetCore()->GetDoc()->SelectUICDMObject(m_DataHandle);
+ else
+ g_StudioApp.GetCore()->GetDoc()->ToggleUICDMObjectToSelection(m_DataHandle);
+}
+
+void CUICDMTimelineItemBinding::OnCollapsed()
+{
+ // Preserves legacy behavior where collapsing a tree will select that root, if any of its
+ // descendant was selected
+ // TODO: This won't work for Image (because Image is Material's property, not child)
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ if (theInstance.Valid()) {
+ CDoc *theDoc = m_TransMgr->GetDoc();
+ UICDM::CUICDMInstanceHandle theSelectedInstance = theDoc->GetSelectedInstance();
+ if (theSelectedInstance.Valid()
+ && IsAscendant(theSelectedInstance, theInstance, theDoc->GetAssetGraph()))
+ SetSelected(false);
+ }
+}
+
+void CUICDMTimelineItemBinding::ClearKeySelection()
+{
+ m_TransMgr->ClearKeyframeSelection();
+}
+
+bool CUICDMTimelineItemBinding::OpenAssociatedEditor()
+{
+ return false; // nothing to do by default
+}
+
+void CUICDMTimelineItemBinding::DoStartDrag(CControlWindowListener *inWndListener)
+{
+ inWndListener->DoStartDrag(this);
+}
+
+inline UICDM::CUICDMInstanceHandle CUICDMTimelineItemBinding::GetInstance() const
+{
+ return m_DataHandle;
+}
+
+void CUICDMTimelineItemBinding::SetDropTarget(CDropTarget *inTarget)
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ inTarget->SetInstance(theInstance);
+}
+
+long CUICDMTimelineItemBinding::GetChildrenCount()
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ if (theInstance.Valid()) {
+ Q3DStudio::CGraphIterator theChildren;
+ CUICDMSlideHandle theActiveSlide = m_TransMgr->GetDoc()->GetActiveSlide();
+ GetAssetChildrenInTimeParent(theInstance, m_TransMgr->GetDoc(), AmITimeParent(),
+ theChildren, theActiveSlide);
+ return (long)theChildren.GetCount();
+ }
+ return 0;
+}
+
+ITimelineItemBinding *CUICDMTimelineItemBinding::GetChild(long inIndex)
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ if (theInstance.Valid()) {
+ Q3DStudio::CGraphIterator theChildren;
+ CUICDMSlideHandle theActiveSlide = m_TransMgr->GetDoc()->GetActiveSlide();
+ GetAssetChildrenInTimeParent(theInstance, m_TransMgr->GetDoc(), AmITimeParent(),
+ theChildren, theActiveSlide);
+ theChildren += inIndex;
+
+ UICDM::CUICDMInstanceHandle theChildInstance = theChildren.GetCurrent();
+ if (theChildInstance.Valid())
+ return m_TransMgr->GetOrCreate(theChildInstance);
+ }
+ return nullptr;
+}
+
+ITimelineItemBinding *CUICDMTimelineItemBinding::GetParent()
+{
+ return m_Parent;
+}
+void CUICDMTimelineItemBinding::SetParent(ITimelineItemBinding *parent)
+{
+ if (parent != m_Parent) {
+ ASSERT(parent == nullptr || m_Parent == nullptr);
+ m_Parent = parent;
+ }
+}
+
+long CUICDMTimelineItemBinding::GetPropertyCount()
+{
+ long theCount = 0;
+ if (m_StudioSystem->IsInstance(m_DataHandle)) {
+ TPropertyHandleList theProperties;
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstanceProperties(m_DataHandle,
+ theProperties);
+ for (size_t thePropertyIndex = 0; thePropertyIndex < theProperties.size();
+ ++thePropertyIndex) {
+ if (m_StudioSystem->GetAnimationSystem()->IsPropertyAnimated(
+ m_DataHandle, theProperties[thePropertyIndex]))
+ ++theCount;
+ }
+ }
+ return theCount;
+}
+
+ITimelineItemProperty *CUICDMTimelineItemBinding::GetProperty(long inIndex)
+{
+ TPropertyHandleList theProperties;
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstanceProperties(m_DataHandle,
+ theProperties);
+ long theIndex = -1;
+ size_t thePropertyIndex = 0;
+ for (; thePropertyIndex < theProperties.size(); ++thePropertyIndex) {
+ if (m_StudioSystem->GetAnimationSystem()->IsPropertyAnimated(
+ m_DataHandle, theProperties[thePropertyIndex])) {
+ ++theIndex;
+ if (theIndex == inIndex)
+ break;
+ }
+ }
+ ASSERT(thePropertyIndex < theProperties.size()); // no reason why this would be out of range!!
+ return GetOrCreatePropertyBinding(theProperties[thePropertyIndex]);
+}
+
+bool CUICDMTimelineItemBinding::ShowToggleControls() const
+{
+ return true;
+}
+bool CUICDMTimelineItemBinding::IsLockedEnabled() const
+{
+ return IsLocked();
+}
+bool CUICDMTimelineItemBinding::IsVisibleEnabled() const
+{
+ // You can only toggle visible if you aren't on the master slide.
+ return m_StudioSystem->GetSlideSystem()->GetSlideIndex(m_TransMgr->GetDoc()->GetActiveSlide())
+ != 0;
+}
+
+void CUICDMTimelineItemBinding::Bind(CBaseStateRow *inRow)
+{
+ ASSERT(!m_Row);
+ m_Row = inRow;
+
+ // Because children(properties included) may only be loaded later, check if there are any
+ // keyframes without having to have the UI created.
+ TPropertyHandleList theProperties;
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstanceProperties(m_DataHandle,
+ theProperties);
+ for (size_t thePropertyIndex = 0; thePropertyIndex < theProperties.size(); ++thePropertyIndex) {
+ if (m_StudioSystem->GetAnimationSystem()->IsPropertyAnimated(
+ m_DataHandle, theProperties[thePropertyIndex]))
+ AddKeyframes(GetOrCreatePropertyBinding(theProperties[thePropertyIndex]));
+ }
+
+ // Set selection status
+ CUICDMInstanceHandle theSelectedInstance = m_TransMgr->GetDoc()->GetSelectedInstance();
+ m_Row->OnSelected(m_DataHandle == theSelectedInstance);
+}
+
+void CUICDMTimelineItemBinding::Release()
+{
+ m_Row = nullptr;
+ RemoveAllPropertyBindings();
+ m_TransMgr->Unregister(this);
+}
+
+bool CUICDMTimelineItemBinding::IsValidTransaction(EUserTransaction inTransaction)
+{
+ UICDM::CUICDMInstanceHandle theInstance = GetInstance();
+ switch (inTransaction) {
+ case EUserTransaction_Rename:
+ return (GetObjectType() != OBJTYPE_SCENE && GetObjectType() != OBJTYPE_IMAGE);
+
+ case EUserTransaction_Duplicate:
+ if (theInstance.Valid())
+ return m_StudioSystem->GetClientDataModelBridge()->IsDuplicateable(theInstance);
+ break;
+
+ case EUserTransaction_Cut:
+ return g_StudioApp.CanCut();
+
+ case EUserTransaction_Copy:
+ return g_StudioApp.CanCopy();
+
+ case EUserTransaction_Paste:
+ return m_TransMgr->GetDoc()->CanPasteObject();
+
+ case EUserTransaction_Delete:
+ if (theInstance.Valid())
+ return m_StudioSystem->GetClientDataModelBridge()->CanDelete(theInstance);
+ break;
+
+ case EUserTransaction_MakeComponent: {
+ bool theCanMakeFlag = false;
+ if (theInstance.Valid()) {
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ EStudioObjectType theObjectType = theBridge->GetObjectType(theInstance);
+
+ if (!IsLocked()) {
+ // Any assets that are attached to the Scene directly must not be wrapped in a
+ // component.
+ // This may include behavior assets which may be directly attached to the Scene.
+ // This is because by principal, components cannot exist on the Scene directly.
+ UICDM::CUICDMInstanceHandle theParentInstance =
+ theBridge->GetParentInstance(theInstance);
+ if (theObjectType != OBJTYPE_LAYER && theObjectType != OBJTYPE_SCENE
+ && theObjectType != OBJTYPE_MATERIAL && theObjectType != OBJTYPE_IMAGE
+ && theObjectType != OBJTYPE_EFFECT
+ && (theParentInstance.Valid()
+ && theBridge->GetObjectType(theParentInstance)
+ != OBJTYPE_SCENE)) // This checks if the object is
+ // AttachedToSceneDirectly
+ {
+ theCanMakeFlag = true;
+ }
+ }
+ }
+ return theCanMakeFlag;
+ }
+
+ case EUserTransaction_EditComponent:
+ return (GetObjectType() == OBJTYPE_COMPONENT);
+
+ default: // not handled
+ break;
+ }
+
+ return false;
+}
+
+using namespace Q3DStudio;
+
+inline void DoCut(CDoc &inDoc, const UICDM::TInstanceHandleList &inInstances)
+{
+ inDoc.DeselectAllKeyframes();
+ inDoc.CutObject(inInstances);
+}
+
+inline void DoDelete(CDoc &inDoc, const UICDM::TInstanceHandleList &inInstances)
+{
+ inDoc.DeselectAllKeyframes();
+ inDoc.DeleteObject(inInstances);
+}
+
+inline void DoMakeComponent(CDoc &inDoc, const UICDM::TInstanceHandleList &inInstances)
+{
+ SCOPED_DOCUMENT_EDITOR(inDoc, QObject::tr("Make Component"))->MakeComponent(inInstances);
+}
+
+void CUICDMTimelineItemBinding::PerformTransaction(EUserTransaction inTransaction)
+{
+ CDoc *theDoc = m_TransMgr->GetDoc();
+ UICDM::TInstanceHandleList theInstances = theDoc->GetSelectedValue().GetSelectedInstances();
+ if (theInstances.empty())
+ return;
+ CDispatch &theDispatch(*theDoc->GetCore()->GetDispatch());
+
+ // Transactions that could result in *this* object being deleted need to be executed
+ // via postmessage, not in this context because it could result in the currently
+ // active timeline row being deleted while in its own mouse handler.
+ switch (inTransaction) {
+ case EUserTransaction_Duplicate: {
+ theDoc->DeselectAllKeyframes();
+ SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Duplicate Object"))->DuplicateInstances(theInstances);
+ } break;
+ case EUserTransaction_Cut: {
+ theDispatch.FireOnAsynchronousCommand(
+ std::bind(DoCut, std::ref(*theDoc), theInstances));
+ } break;
+ case EUserTransaction_Copy: {
+ theDoc->DeselectAllKeyframes();
+ theDoc->CopyObject(theInstances);
+ } break;
+ case EUserTransaction_Paste: {
+ theDoc->DeselectAllKeyframes();
+ theDoc->PasteObject(GetInstance());
+ } break;
+ case EUserTransaction_Delete: {
+ theDispatch.FireOnAsynchronousCommand(
+ std::bind(DoDelete, std::ref(*theDoc), theInstances));
+ } break;
+ case EUserTransaction_MakeComponent: {
+ theDispatch.FireOnAsynchronousCommand(
+ std::bind(DoMakeComponent, std::ref(*theDoc), theInstances));
+ }
+ default: // not handled
+ break;
+ }
+}
+
+Q3DStudio::CString CUICDMTimelineItemBinding::GetObjectPath()
+{
+ CDoc *theDoc = m_TransMgr->GetDoc();
+ // Because we are getting absolute path, the base id doesn't matter.
+ return CRelativePathTools::BuildAbsoluteReferenceString(m_DataHandle, theDoc);
+}
+
+ITimelineKeyframesManager *CUICDMTimelineItemBinding::GetKeyframesManager() const
+{
+ return m_TransMgr->GetKeyframesManager();
+}
+
+void CUICDMTimelineItemBinding::RemoveProperty(ITimelineItemProperty *inProperty)
+{
+ Q_UNUSED(inProperty);
+ // TODO: This function has no use in UICDM world. This is replaced by RemovePropertyRow(
+ // CUICDMPropertyHandle inPropertyHandle ).
+ // Decide if this function should be removed from ITimelineItemBinding.
+}
+
+void CUICDMTimelineItemBinding::LoadProperties()
+{
+ TPropertyHandleList theProperties;
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstanceProperties(m_DataHandle,
+ theProperties);
+ for (size_t thePropertyIndex = 0; thePropertyIndex < theProperties.size(); ++thePropertyIndex) {
+ if (m_StudioSystem->GetAnimationSystem()->IsPropertyAnimated(
+ m_DataHandle, theProperties[thePropertyIndex]))
+ AddPropertyRow(theProperties[thePropertyIndex], true);
+ }
+}
+
+void CUICDMTimelineItemBinding::InsertKeyframe()
+{
+ if (m_PropertyBindingMap.empty())
+ return;
+
+ TPropertyBindingMap::const_iterator theIter = m_PropertyBindingMap.begin();
+ ScopedDocumentEditor editor(*g_StudioApp.GetCore()->GetDoc(), L"Insert Keyframe", __FILE__,
+ __LINE__);
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter)
+ editor->KeyframeProperty(m_DataHandle, theIter->first, false);
+}
+
+void CUICDMTimelineItemBinding::DeleteAllChannelKeyframes()
+{
+ if (m_PropertyBindingMap.empty())
+ return;
+
+ CDoc *theDoc = m_TransMgr->GetDoc();
+ Q3DStudio::ScopedDocumentEditor editor(*theDoc, L"Delete Channel Keyframes", __FILE__,
+ __LINE__);
+ for (TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.begin(),
+ theEnd = m_PropertyBindingMap.end();
+ theIter != theEnd; ++theIter)
+ theIter->second->DeleteAllKeys();
+}
+
+long CUICDMTimelineItemBinding::GetKeyframeCount() const
+{
+ // This list is updated when properties are loaded and when keyframes are added & deleted.
+ return (long)m_Keyframes.size();
+}
+
+IKeyframe *CUICDMTimelineItemBinding::GetKeyframeByTime(long inTime) const
+{
+ TAssetKeyframeList::const_iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ if ((*theIter).GetTime() == inTime)
+ return const_cast<CUICDMAssetTimelineKeyframe *>(&(*theIter));
+ }
+ return nullptr;
+}
+
+IKeyframe *CUICDMTimelineItemBinding::GetKeyframeByIndex(long inIndex) const
+{
+ if (inIndex >= 0 && inIndex < (long)m_Keyframes.size())
+ return const_cast<CUICDMAssetTimelineKeyframe *>(&m_Keyframes[inIndex]);
+
+ ASSERT(0); // should not happen
+ return nullptr;
+}
+
+long CUICDMTimelineItemBinding::OffsetSelectedKeyframes(long inOffset)
+{
+ return m_TransMgr->GetKeyframesManager()->OffsetSelectedKeyframes(inOffset);
+}
+
+void CUICDMTimelineItemBinding::CommitChangedKeyframes()
+{
+ m_TransMgr->GetKeyframesManager()->CommitChangedKeyframes();
+}
+
+void CUICDMTimelineItemBinding::OnEditKeyframeTime(long inCurrentTime, long inObjectAssociation)
+{
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.SetKeyframesManager(m_TransMgr->GetKeyframesManager());
+ theTimeEditDlg.ShowDialog(inCurrentTime, 0, g_StudioApp.GetCore()->GetDoc(),
+ inObjectAssociation);
+}
+
+void CUICDMTimelineItemBinding::SelectKeyframes(bool inSelected, long inTime /*= -1 */)
+{
+ // Callback from UI, hence skip the UI update
+ DoSelectKeyframes(inSelected, inTime, false);
+}
+
+CUICDMInstanceHandle CUICDMTimelineItemBinding::GetInstanceHandle() const
+{
+ return m_DataHandle;
+}
+
+long CUICDMTimelineItemBinding::GetFlavor() const
+{
+ return EUIC_FLAVOR_ASSET_TL;
+}
+
+void CUICDMTimelineItemBinding::OnBeginDataModelNotifications()
+{
+}
+void CUICDMTimelineItemBinding::OnEndDataModelNotifications()
+{
+ RefreshStateRow();
+}
+void CUICDMTimelineItemBinding::OnImmediateRefreshInstanceSingle(
+ UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (inInstance == m_DataHandle)
+ RefreshStateRow(true);
+}
+void CUICDMTimelineItemBinding::OnImmediateRefreshInstanceMultiple(
+ UICDM::CUICDMInstanceHandle *inInstance, long inInstanceCount)
+{
+ for (long idx = 0; idx < inInstanceCount; ++idx)
+ if (inInstance[idx] == m_DataHandle) {
+ RefreshStateRow();
+ break;
+ }
+}
+
+void CUICDMTimelineItemBinding::RefreshStateRow(bool inRefreshChildren)
+{
+ CStateRow *theRow = dynamic_cast<CStateRow *>(m_Row);
+ if (theRow) {
+ theRow->OnTimeChange();
+ theRow->ClearDirty();
+ if (inRefreshChildren) {
+ long theChildrenCount = GetChildrenCount();
+ for (long theIndex = 0; theIndex < theChildrenCount; ++theIndex) {
+ ITimelineItemBinding *theChild = GetChild(theIndex);
+ CUICDMTimelineItemBinding *theBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(theChild);
+ if (theBinding)
+ theBinding->RefreshStateRow(inRefreshChildren);
+ }
+ }
+ }
+}
+
+ITimelineTimebar *CUICDMTimelineItemBinding::CreateTimelineTimebar()
+{
+ return new CUICDMTimelineTimebar(m_TransMgr, m_DataHandle);
+}
+
+ITimelineItemProperty *
+CUICDMTimelineItemBinding::GetPropertyBinding(CUICDMPropertyHandle inPropertyHandle)
+{
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.find(inPropertyHandle);
+ // check if it already exists
+ if (theIter != m_PropertyBindingMap.end())
+ return theIter->second;
+ return nullptr;
+}
+
+ITimelineItemProperty *
+CUICDMTimelineItemBinding::GetOrCreatePropertyBinding(CUICDMPropertyHandle inPropertyHandle)
+{
+ ITimelineItemProperty *theProperty = GetPropertyBinding(inPropertyHandle);
+ // check if it already exists
+ if (theProperty)
+ return theProperty;
+
+ // Create
+ CUICDMTimelineItemProperty *theTimelineProperty =
+ new CUICDMTimelineItemProperty(m_TransMgr, inPropertyHandle, m_DataHandle);
+ m_PropertyBindingMap.insert(std::make_pair(inPropertyHandle, theTimelineProperty));
+
+ return theTimelineProperty;
+}
+
+//=============================================================================
+/**
+ * Add a new property row for this property.
+ * @param inAppend true to skip the check to find where to insert. ( true if this is a
+ * loading/initializing step, where the call is already done in order )
+ */
+void CUICDMTimelineItemBinding::AddPropertyRow(CUICDMPropertyHandle inPropertyHandle,
+ bool inAppend /*= false */)
+{
+ ITimelineItemProperty *theTimelineProperty = GetPropertyBinding(inPropertyHandle);
+ if (theTimelineProperty && theTimelineProperty->GetRow()) // if created, bail
+ return;
+
+ if (!theTimelineProperty)
+ theTimelineProperty = GetOrCreatePropertyBinding(inPropertyHandle);
+
+ // Find the row to insert this new property, if any, this preserves the order the property rows
+ // is displayed in the timeline.
+ ITimelineItemProperty *theNextProperty = nullptr;
+ if (!inAppend) {
+ TPropertyHandleList theProperties;
+ m_StudioSystem->GetPropertySystem()->GetAggregateInstanceProperties(m_DataHandle,
+ theProperties);
+ size_t thePropertyIndex = 0;
+ size_t thePropertyCount = theProperties.size();
+ for (; thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ if (theProperties[thePropertyIndex] == inPropertyHandle) {
+ ++thePropertyIndex;
+ break;
+ }
+ }
+ // Not all properties are displayed, so another loop to search for the first one that maps
+ // to a existing propertyrow
+ for (; thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ TPropertyBindingMap::iterator theNextPropIter =
+ m_PropertyBindingMap.find(theProperties[thePropertyIndex]);
+ if (theNextPropIter != m_PropertyBindingMap.end()) {
+ theNextProperty = theNextPropIter->second;
+ break;
+ }
+ }
+ }
+ // Create a new property row
+ m_TransMgr->CreateNewPropertyRow(theTimelineProperty, m_Row,
+ theNextProperty ? theNextProperty->GetRow() : nullptr);
+
+ // Update keyframes
+ AddKeyframes(theTimelineProperty);
+}
+
+void CUICDMTimelineItemBinding::RemovePropertyRow(CUICDMPropertyHandle inPropertyHandle)
+{
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.find(inPropertyHandle);
+ if (theIter != m_PropertyBindingMap.end()) {
+ ITimelineItemProperty *thePropertyBinding = theIter->second;
+
+ bool theUpdateUI = DeleteAssetKeyframesWhereApplicable(thePropertyBinding);
+
+ m_TransMgr->RemovePropertyRow(thePropertyBinding);
+ m_PropertyBindingMap.erase(theIter);
+
+ // UI must update
+ if (m_Row && theUpdateUI) {
+ m_Row->OnChildVisibilityChanged();
+ m_Row->GetTimebar()->SetDirty(true);
+ }
+ }
+}
+
+// called when a keyframe is inserted, deleted or updated in the data model
+void CUICDMTimelineItemBinding::RefreshPropertyKeyframe(
+ UICDM::CUICDMPropertyHandle inPropertyHandle, UICDM::CUICDMKeyframeHandle inKeyframe,
+ ETimelineKeyframeTransaction inTransaction)
+{
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.find(inPropertyHandle);
+ if (theIter != m_PropertyBindingMap.end()) {
+ CUICDMTimelineItemProperty *theProperty = theIter->second;
+ if (theProperty) {
+ if (theProperty->RefreshKeyframe(inKeyframe, inTransaction)) {
+ // Update asset keyframes
+ UpdateKeyframe(theProperty->GetKeyframeByHandle(inKeyframe), inTransaction);
+ if (m_Row) // UI update
+ m_Row->GetTimebar()->SetDirty(true);
+ }
+ }
+ }
+}
+
+// called when the keyframes are updated in the UI and data model hasn't committed the change, ie no
+// event callback from UICDM
+void CUICDMTimelineItemBinding::UIRefreshPropertyKeyframe(long inOffset)
+{
+ if (!m_Row)
+ return;
+
+ // TODO: figure out a better way to sync m_Keyframes
+ TAssetKeyframeList::iterator theKeyIter = m_Keyframes.begin();
+ for (; theKeyIter != m_Keyframes.end(); ++theKeyIter) {
+ if (theKeyIter->IsSelected())
+ theKeyIter->UpdateTime(theKeyIter->GetTime() + inOffset);
+ }
+ // If a asset keyframe was "shared" by several properties' keyframes
+ // we need to 'break' this sharing and create for the remaining unmoved keyframes.
+ TPropertyBindingMap::const_iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter) {
+ (*theIter).second->RefreshKeyFrames();
+
+ for (long i = 0; i < theIter->second->GetKeyframeCount(); ++i) {
+ IKeyframe *theKeyframe = theIter->second->GetKeyframeByIndex(i);
+ UpdateKeyframe(theKeyframe, ETimelineKeyframeTransaction_Add);
+
+ // Unfortunately, this is the way we can propagate UI updates to ALL selected keyframes
+ if (theKeyframe->IsSelected()) {
+ CPropertyRow *thePropertyRow = theIter->second->GetRow();
+ if (thePropertyRow)
+ thePropertyRow->GetTimebar()->SetDirty(true);
+ }
+ }
+ }
+ m_Row->GetTimebar()->SetDirty(true);
+}
+
+void CUICDMTimelineItemBinding::OnPropertyChanged(CUICDMPropertyHandle inPropertyHandle)
+{ // Refresh UI
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ if (m_Row && (inPropertyHandle == theBridge->GetNameProperty()
+ || inPropertyHandle == theBridge->GetSceneAsset().m_Eyeball
+ || inPropertyHandle == theBridge->GetSceneAsset().m_Locked
+ || inPropertyHandle == theBridge->GetSceneAsset().m_Shy
+ || inPropertyHandle == theBridge->GetSceneAsset().m_StartTime
+ || inPropertyHandle == theBridge->GetSceneAsset().m_EndTime))
+ m_Row->OnDirty();
+}
+
+void CUICDMTimelineItemBinding::OnPropertyLinked(CUICDMPropertyHandle inPropertyHandle)
+{
+ if (m_StudioSystem->GetAnimationSystem()->IsPropertyAnimated(m_DataHandle, inPropertyHandle)) {
+ // Refresh property row by delete and recreate
+ RemovePropertyRow(inPropertyHandle);
+ AddPropertyRow(inPropertyHandle);
+ }
+}
+
+bool CUICDMTimelineItemBinding::HasDynamicKeyframes(long inTime)
+{
+ if (inTime == -1) {
+ if (GetPropertyCount() == 0)
+ return false;
+
+ for (long i = 0; i < GetPropertyCount(); ++i) {
+ ITimelineItemProperty *theTimelineItemProperty = GetProperty(i);
+ if (!theTimelineItemProperty->IsDynamicAnimation())
+ return false;
+ }
+ return true;
+ } else {
+ TPropertyBindingMap::const_iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter) {
+ IKeyframe *theKeyframe = theIter->second->GetKeyframeByTime(inTime);
+ if (theKeyframe && theKeyframe->IsDynamic())
+ return true;
+ }
+ }
+ return false;
+}
+
+void CUICDMTimelineItemBinding::SetDynamicKeyframes(long inTime, bool inDynamic)
+{
+ TPropertyBindingMap::const_iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter) {
+ IKeyframe *theKeyframe = theIter->second->GetKeyframeByTime(inTime);
+ if (theKeyframe)
+ theKeyframe->SetDynamic(inDynamic); // TODO: we want this in 1 batch command
+ }
+}
+
+// Update UI on the selection state of all keyframes on this row and all its properties' keyframes.
+void CUICDMTimelineItemBinding::DoSelectKeyframes(bool inSelected, long inTime, bool inUpdateUI)
+{
+ if (inTime == -1) // all keyframes
+ {
+ TAssetKeyframeList::iterator theKeyIter = m_Keyframes.begin();
+ for (; theKeyIter != m_Keyframes.end(); ++theKeyIter)
+ theKeyIter->SetSelected(inSelected);
+ } else {
+ CUICDMAssetTimelineKeyframe *theKeyframe =
+ dynamic_cast<CUICDMAssetTimelineKeyframe *>(GetKeyframeByTime(inTime));
+ if (theKeyframe)
+ theKeyframe->SetSelected(inSelected);
+ }
+ if (inUpdateUI && m_Row)
+ m_Row->GetTimebar()->SelectKeysByTime(-1, inSelected);
+
+ // legacy feature: all properties with keyframes at inTime or all if inTime is -1 are selected
+ // as well.
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter)
+ theIter->second->DoSelectKeyframes(inSelected, inTime, true, this);
+}
+
+// When selecting by mouse-drag, if all properties are selected, select the asset keyframe. And if
+// one gets de-selected, de-select. Legacy feature.
+// Note that if only 1 property has a keyframe at time t, the asset keyframe gets selected
+// automatically when that keyframe is selected. Its odd to me but
+// that's how it has always behaved.
+void CUICDMTimelineItemBinding::OnPropertySelection(long inTime)
+{
+ IKeyframe *theAssetKeyframe = GetKeyframeByTime(inTime);
+ if (theAssetKeyframe) {
+ bool theAllSelectedFlag = true;
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter) {
+ IKeyframe *theKeyframe = theIter->second->GetKeyframeByTime(inTime);
+ if (theKeyframe && !theKeyframe->IsSelected()) // done, i.e selection remain unchanged.
+ {
+ theAllSelectedFlag = false;
+ break;
+ }
+ }
+ if (theAssetKeyframe->IsSelected() != theAllSelectedFlag) {
+ dynamic_cast<CUICDMAssetTimelineKeyframe *>(theAssetKeyframe)
+ ->SetSelected(theAllSelectedFlag);
+ // Update UI
+ if (m_Row)
+ m_Row->GetTimebar()->SelectKeysByTime(inTime, theAllSelectedFlag);
+ }
+ }
+}
+
+Q3DStudio::CId CUICDMTimelineItemBinding::GetGuid() const
+{
+ CClientDataModelBridge *theClientBridge = m_StudioSystem->GetClientDataModelBridge();
+ UICDM::IPropertySystem *thePropertySystem = m_StudioSystem->GetPropertySystem();
+ SValue theValue;
+ if (thePropertySystem->GetInstancePropertyValue(m_DataHandle, theClientBridge->GetIdProperty(),
+ theValue)) {
+ SLong4 theLong4 = UICDM::get<SLong4>(theValue);
+ return Q3DStudio::CId(theLong4.m_Longs[0], theLong4.m_Longs[1], theLong4.m_Longs[2],
+ theLong4.m_Longs[3]);
+ }
+ return Q3DStudio::CId();
+}
+
+// Delete asset keyframes at time t if no property keyframes exist at time t
+//@param inSkipPropertyBinding property that to skip, e.g. in cases where property is deleted
+//@return true if there are asset keyframes deleted.
+bool CUICDMTimelineItemBinding::DeleteAssetKeyframesWhereApplicable(
+ ITimelineItemProperty *inSkipPropertyBinding /*= nullptr */)
+{
+ // iterate through m_Keyframes because we cannot obtain time information from the Animation
+ // keyframes anymore, since they are deleted.
+ std::vector<long> theDeleteIndicesList;
+ for (size_t theIndex = 0; theIndex < m_Keyframes.size(); ++theIndex) {
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter) {
+ if ((!inSkipPropertyBinding || theIter->second != inSkipPropertyBinding)
+ && theIter->second->GetKeyframeByTime(m_Keyframes[theIndex].GetTime())) // done!
+ break;
+ }
+ if (theIter == m_PropertyBindingMap.end())
+ theDeleteIndicesList.push_back((long)theIndex);
+ }
+ // start with the last item, so that the indices remain valid.
+ for (long i = (long)theDeleteIndicesList.size() - 1; i >= 0; --i) {
+ TAssetKeyframeList::iterator theKeyIter = m_Keyframes.begin();
+ std::advance(theKeyIter, theDeleteIndicesList[i]);
+ m_Keyframes.erase(theKeyIter);
+ }
+
+ return !theDeleteIndicesList.empty();
+}
+
+void CUICDMTimelineItemBinding::RemoveAllPropertyBindings()
+{
+ TPropertyBindingMap::iterator theIter = m_PropertyBindingMap.begin();
+ for (; theIter != m_PropertyBindingMap.end(); ++theIter)
+ delete theIter->second;
+ m_PropertyBindingMap.clear();
+}
+
+void CUICDMTimelineItemBinding::AddKeyframes(ITimelineItemProperty *inPropertyBinding)
+{
+ for (long i = 0; i < inPropertyBinding->GetKeyframeCount(); ++i)
+ UpdateKeyframe(inPropertyBinding->GetKeyframeByIndex(i), ETimelineKeyframeTransaction_Add);
+}
+
+// Update the asset keyframes based on the properties' keyframes.
+void CUICDMTimelineItemBinding::UpdateKeyframe(IKeyframe *inKeyframe,
+ ETimelineKeyframeTransaction inTransaction)
+{
+ bool theDoAddFlag = (inTransaction == ETimelineKeyframeTransaction_Add);
+ bool theDoDeleteFlag = (inTransaction == ETimelineKeyframeTransaction_Delete);
+
+ // For update, if there isn't already a asset keyframe at the associated time, create one
+ if (inTransaction == ETimelineKeyframeTransaction_Update) {
+ theDoAddFlag = inKeyframe && !GetKeyframeByTime(inKeyframe->GetTime());
+ theDoDeleteFlag = true; // plus, since we don't keep track of indiviual property keyframes
+ // here, iterate and make sure list is correct.
+ }
+
+ if (theDoDeleteFlag)
+ DeleteAssetKeyframesWhereApplicable();
+
+ // Add when a new keyframe is added or MAYBE when a keyframe is moved
+ if (theDoAddFlag && inKeyframe) {
+ long theKeyframeTime = inKeyframe->GetTime();
+ if (theKeyframeTime >= 0) {
+ bool theAppend = true;
+ // insert this in the order that it should be. and we trust the
+ TAssetKeyframeList::iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ long theTime = (*theIter).GetTime();
+ if (theTime == theKeyframeTime) {
+ theAppend = false;
+ break; // already exists, we are done. Because we only need 1 to represent ALL
+ // properties
+ }
+ }
+ if (theAppend)
+ m_Keyframes.push_back(CUICDMAssetTimelineKeyframe(this, theKeyframeTime));
+ }
+ }
+ if (m_Row && (theDoAddFlag
+ || inTransaction == ETimelineKeyframeTransaction_DynamicChanged)) // dynamic =>
+ // only UI needs
+ // to refresh
+ m_Row->GetTimebar()->SetDirty(true);
+}
+
+void CUICDMTimelineItemBinding::OnAddChild(CUICDMInstanceHandle inInstance)
+{
+ CDoc *theDoc = m_TransMgr->GetDoc();
+ CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
+ ISlideSystem *theSlideSystem = m_StudioSystem->GetSlideSystem();
+
+ UICDM::CUICDMSlideHandle theSlide = theSlideSystem->GetAssociatedSlide(inInstance);
+ if (theBridge->IsInActiveComponent(inInstance)
+ && (theSlideSystem->IsMasterSlide(theSlide) || theSlide == theDoc->GetActiveSlide())) {
+ // Only add if the asset is in the current active component, and it's a master asset or in
+ // the current slide
+ ITimelineItemBinding *theNextItem = nullptr;
+ UICDM::CUICDMInstanceHandle theParentInstance = GetInstance();
+ // Figure out where to insert this row, if applicable.
+ // CAsset has a list of children, and not necessarily all are active in this slide (e.g.
+ // non-master children)
+ Q3DStudio::TIdentifier theNextChild = 0;
+ if (theParentInstance.Valid()) {
+ // Get the next prioritized child in the same slide
+ Q3DStudio::CGraphIterator theChildren;
+ GetAssetChildrenInSlide(theDoc, theParentInstance, theDoc->GetActiveSlide(),
+ theChildren);
+ theNextChild = GetSibling(inInstance, true, theChildren);
+ }
+
+ if (theNextChild != 0)
+ theNextItem = m_TransMgr->GetOrCreate(theNextChild);
+
+ m_Row->AddChildRow(m_TransMgr->GetOrCreate(inInstance), theNextItem);
+ }
+}
+
+void CUICDMTimelineItemBinding::OnDeleteChild(CUICDMInstanceHandle inInstance)
+{
+ ITimelineItemBinding *theChild = m_TransMgr->GetOrCreate(inInstance);
+ if (theChild) {
+ m_Row->RemoveChildRow(theChild);
+ }
+}
+
+void CUICDMTimelineItemBinding::UpdateActionStatus()
+{
+ if (m_Row)
+ m_Row->UpdateActionStatus();
+}
+
+//=============================================================================
+/**
+ * Open the associated item as though it was double-clicked in explorer
+ * Respective subclasses (for example Image and Behavior) can call this function
+ */
+bool CUICDMTimelineItemBinding::OpenSourcePathFile()
+{
+ // Get source path property value
+ CClientDataModelBridge *theClientBridge = m_StudioSystem->GetClientDataModelBridge();
+ UICDM::IPropertySystem *thePropertySystem = m_StudioSystem->GetPropertySystem();
+ SValue theValue;
+ if (thePropertySystem->GetInstancePropertyValue(
+ m_DataHandle, theClientBridge->GetSourcePathProperty(), theValue)) {
+ // Open the respective file
+ Q3DStudio::CFilePath theSourcePath(UICDM::get<UICDM::TDataStrPtr>(theValue)->GetData());
+ CUICFile theFile(m_TransMgr->GetDoc()->GetResolvedPathToDoc(theSourcePath));
+ theFile.Execute();
+ return true;
+ }
+ return false;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.h
new file mode 100644
index 00000000..2866d698
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemBinding.h
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_UICDM_TIMELINEITEM_BINDING_H
+#define INCLUDED_UICDM_TIMELINEITEM_BINDING_H 1
+
+#pragma once
+
+#include "ITimelineItemBinding.h"
+#include "ITimelineItem.h"
+
+// Data model
+#include "UICDMHandles.h"
+#include "IDragable.h"
+#include "UICDMAssetTimelineKeyframe.h"
+#include "OffsetKeyframesCommandHelper.h"
+#include "UICDMTimeline.h"
+#include "UICDMSignals.h"
+#include "DispatchListeners.h"
+
+//==============================================================================
+// Classes
+//==============================================================================
+class CTimelineTranslationManager;
+class CBaseStateRow;
+class CUICDMTimelineItemProperty;
+class CCmdDataModelSetKeyframeTime;
+
+namespace UICDM {
+class CStudioSystem;
+}
+
+//=============================================================================
+/**
+ * Binding to generic UICDM object
+ */
+class CUICDMTimelineItemBinding : public ITimelineItemBinding,
+ public ITimelineItem,
+ public IDragable,
+ public IDataModelListener
+
+{
+protected: // Typedef
+ typedef std::map<UICDM::CUICDMPropertyHandle, CUICDMTimelineItemProperty *> TPropertyBindingMap;
+ typedef std::vector<CUICDMAssetTimelineKeyframe> TAssetKeyframeList;
+
+protected:
+ CBaseStateRow *m_Row;
+ CTimelineTranslationManager *m_TransMgr;
+ UICDM::CUICDMInstanceHandle m_DataHandle;
+ ITimelineItemBinding *m_Parent;
+ ITimelineTimebar *m_TimelineTimebar;
+ TPropertyBindingMap m_PropertyBindingMap;
+ TAssetKeyframeList m_Keyframes; /// Sorted (by time) list of keyframes
+ UICDM::CStudioSystem *m_StudioSystem;
+
+ UICDM::TSignalConnectionPtr m_StartTimeConnection;
+ UICDM::TSignalConnectionPtr m_EndTimeConnection;
+
+public:
+ CUICDMTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ CUICDMTimelineItemBinding(CTimelineTranslationManager *inMgr);
+ virtual ~CUICDMTimelineItemBinding();
+
+protected:
+ bool UICDMGetBoolean(UICDM::CUICDMPropertyHandle inProperty) const;
+ void UICDMSetBoolean(UICDM::CUICDMPropertyHandle inProperty, bool inValue,
+ const QString &inNiceText) const;
+ void SetInstanceHandle(UICDM::CUICDMInstanceHandle inDataHandle);
+
+public:
+ // ITimelineItem
+ EStudioObjectType GetObjectType() const override;
+ bool IsMaster() const override;
+ bool IsShy() const override;
+ void SetShy(bool) override;
+ bool IsLocked() const override;
+ void SetLocked(bool) override;
+ bool IsVisible() const override;
+ void SetVisible(bool) override;
+ bool IsExpanded() const override;
+ void SetExpanded(bool inExpanded) override;
+ bool HasAction(bool inMaster) override;
+ bool ChildrenHasAction(bool inMaster) override;
+ bool ComponentHasAction(bool inMaster) override;
+ ITimelineTimebar *GetTimebar() override;
+
+ // INamable
+ Q3DStudio::CString GetName() const override;
+ void SetName(const Q3DStudio::CString &inName) override;
+
+ // ITimelineItemBinding
+ ITimelineItem *GetTimelineItem() override;
+ CBaseStateRow *GetRow() override;
+ void SetSelected(bool inMultiSelect) override;
+ void OnCollapsed() override;
+ void ClearKeySelection() override;
+ bool OpenAssociatedEditor() override;
+ void DoStartDrag(CControlWindowListener *inWndListener) override;
+ void SetDropTarget(CDropTarget *inTarget) override;
+ // Hierarchy
+ long GetChildrenCount() override;
+ ITimelineItemBinding *GetChild(long inIndex) override;
+ ITimelineItemBinding *GetParent() override;
+ void SetParent(ITimelineItemBinding *parent) override;
+ // Properties
+ long GetPropertyCount() override;
+ ITimelineItemProperty *GetProperty(long inIndex) override;
+ // Eye/Lock toggles
+ bool ShowToggleControls() const override;
+ bool IsLockedEnabled() const override;
+ bool IsVisibleEnabled() const override;
+ // Init/Cleanup
+ void Bind(CBaseStateRow *inRow) override;
+ void Release() override;
+ // ContextMenu
+ bool IsValidTransaction(EUserTransaction inTransaction) override;
+ void PerformTransaction(EUserTransaction inTransaction) override;
+ Q3DStudio::CString GetObjectPath() override;
+ // Selected keyframes
+ ITimelineKeyframesManager *GetKeyframesManager() const override;
+ // Properties
+ void RemoveProperty(ITimelineItemProperty *inProperty) override;
+ void LoadProperties() override;
+
+ // ITimelineItemKeyframesHolder
+ void InsertKeyframe() override;
+ void DeleteAllChannelKeyframes() override;
+ long GetKeyframeCount() const override;
+ IKeyframe *GetKeyframeByTime(long inTime) const override;
+ IKeyframe *GetKeyframeByIndex(long inIndex) const override;
+ long OffsetSelectedKeyframes(long inOffset) override;
+ void CommitChangedKeyframes() override;
+ void OnEditKeyframeTime(long inCurrentTime, long inObjectAssociation) override;
+
+ // IKeyframeSelector
+ void SelectKeyframes(bool inSelected, long inTime = -1) override;
+
+ // IUICDMSelectable
+ virtual UICDM::CUICDMInstanceHandle GetInstanceHandle() const;
+
+ // IDragable
+ long GetFlavor() const override;
+
+ void OnBeginDataModelNotifications() override;
+ void OnEndDataModelNotifications() override;
+ void OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance) override;
+ void OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance,
+ long inInstanceCount) override;
+ void RefreshStateRow(bool inRefreshChildren = false);
+
+ virtual void AddPropertyRow(UICDM::CUICDMPropertyHandle inPropertyHandle,
+ bool inAppend = false);
+ virtual void RemovePropertyRow(UICDM::CUICDMPropertyHandle inPropertyHandle);
+ virtual void RefreshPropertyKeyframe(UICDM::CUICDMPropertyHandle inPropertyHandle,
+ UICDM::CUICDMKeyframeHandle,
+ ETimelineKeyframeTransaction inTransaction);
+ virtual void OnPropertyChanged(UICDM::CUICDMPropertyHandle inPropertyHandle);
+ virtual void OnPropertyLinked(UICDM::CUICDMPropertyHandle inPropertyHandle);
+
+ virtual void UIRefreshPropertyKeyframe(long inOffset);
+ // Keyframe manipulation
+ virtual bool HasDynamicKeyframes(long inTime);
+ virtual void SetDynamicKeyframes(long inTime, bool inDynamic);
+ virtual void DoSelectKeyframes(bool inSelected, long inTime, bool inUpdateUI);
+ virtual void OnPropertySelection(long inTime);
+
+ virtual void OnAddChild(UICDM::CUICDMInstanceHandle inInstance);
+ virtual void OnDeleteChild(UICDM::CUICDMInstanceHandle inInstance);
+
+ void UpdateActionStatus();
+
+ Q3DStudio::CId GetGuid() const;
+
+ // Bridge between asset & UICDM. Ideally we should be fully UICDM
+ virtual UICDM::CUICDMInstanceHandle GetInstance() const;
+
+protected:
+ virtual ITimelineTimebar *CreateTimelineTimebar();
+ ITimelineItemProperty *GetPropertyBinding(UICDM::CUICDMPropertyHandle inPropertyHandle);
+ ITimelineItemProperty *GetOrCreatePropertyBinding(UICDM::CUICDMPropertyHandle inPropertyHandle);
+ void RemoveAllPropertyBindings();
+ void AddKeyframes(ITimelineItemProperty *inPropertyBinding);
+ bool
+ DeleteAssetKeyframesWhereApplicable(ITimelineItemProperty *inTriggerPropertyBinding = nullptr);
+ void UpdateKeyframe(IKeyframe *inKeyframe, ETimelineKeyframeTransaction inTransaction);
+
+ // For iterating through children
+ virtual bool AmITimeParent() const { return false; }
+
+ // subclasses can call this method to open referenced files
+ virtual bool OpenSourcePathFile();
+};
+
+#endif // INCLUDED_UICDM_TIMELINEITEM_BINDING_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.cpp
new file mode 100644
index 00000000..c09fca25
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.cpp
@@ -0,0 +1,579 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMTimelineItemProperty.h"
+#include "PropertyRow.h"
+#include "TimelineTranslationManager.h"
+#include "ITimelineItemBinding.h"
+#include "PropertyTimebarRow.h"
+#include "UICDMTimelineItemBinding.h"
+#include "UICDMTimelineKeyframe.h"
+#include "KeyframesManager.h"
+#include "CmdDataModelChangeKeyframe.h"
+#include "CmdDataModelRemoveKeyframe.h"
+#include "StudioApp.h"
+#include "Core.h"
+
+// Link to data model
+#include "TimeEditDlg.h"
+#include "ClientDataModelBridge.h"
+#include "UICDMSlides.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMAnimation.h"
+#include "UICDMMetaData.h"
+#include "UICDMPropertyDefinition.h"
+#include "UICDMDataCore.h"
+#include "StudioFullSystem.h"
+#include <boost/bind.hpp>
+using namespace UICDM;
+
+bool SortKeyframeByTime(const CUICDMTimelineKeyframe *inLHS, const CUICDMTimelineKeyframe *inRHS)
+{
+ return inLHS->GetTime() < inRHS->GetTime();
+}
+
+// UICDM stores it from 0..1, UI expects 0..255
+inline float UICDMToColor(float inValue)
+{
+ return inValue * 255;
+}
+
+CUICDMTimelineItemProperty::CUICDMTimelineItemProperty(CTimelineTranslationManager *inTransMgr,
+ CUICDMPropertyHandle inPropertyHandle,
+ CUICDMInstanceHandle inInstance)
+ : m_Row(nullptr)
+ , m_InstanceHandle(inInstance)
+ , m_PropertyHandle(inPropertyHandle)
+ , m_TransMgr(inTransMgr)
+ , m_SetKeyframeValueCommand(nullptr)
+{
+ // Cache all the animation handles because we need them for any keyframes manipulation.
+ // the assumption is that all associated handles are created all at once (i.e. we do not need to
+ // add or delete from this list )
+ CreateKeyframes();
+ InitializeCachedVariables(inInstance);
+ m_Signals.push_back(
+ m_TransMgr->GetStudioSystem()->GetFullSystem()->GetSignalProvider()->ConnectPropertyLinked(
+ boost::bind(&CUICDMTimelineItemProperty::OnPropertyLinkStatusChanged, this, _1, _2,
+ _3)));
+
+ m_Signals.push_back(
+ m_TransMgr->GetStudioSystem()
+ ->GetFullSystem()
+ ->GetSignalProvider()
+ ->ConnectPropertyUnlinked(boost::bind(
+ &CUICDMTimelineItemProperty::OnPropertyLinkStatusChanged, this, _1, _2, _3)));
+}
+
+CUICDMTimelineItemProperty::~CUICDMTimelineItemProperty()
+{
+ ReleaseKeyframes();
+ Release();
+}
+
+void CUICDMTimelineItemProperty::CreateKeyframes()
+{
+ // Cache all the animation handles because we need them for any keyframes manipulation.
+ // the assumption is that all associated handles are created all at once (i.e. we do not need to
+ // add or delete from this list )
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ DataModelDataType::Value theDataType = thePropertySystem->GetDataType(m_PropertyHandle);
+ IStudioAnimationSystem *theAnimationSystem =
+ m_TransMgr->GetStudioSystem()->GetAnimationSystem();
+ std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType);
+ for (size_t i = 0; i < std::get<1>(theArity); ++i) {
+ CUICDMAnimationHandle theAnimationHandle =
+ theAnimationSystem->GetControllingAnimation(m_InstanceHandle, m_PropertyHandle, i);
+ if (theAnimationHandle.Valid())
+ m_AnimationHandles.push_back(theAnimationHandle);
+ }
+ if (!m_AnimationHandles.empty()) { // update wrappers for keyframes
+ IAnimationCore *theAnimationCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+ TKeyframeHandleList theKeyframes;
+ // all channels have keyframes at the same time
+ theAnimationCore->GetKeyframes(m_AnimationHandles[0], theKeyframes);
+ for (size_t i = 0; i < theKeyframes.size(); ++i)
+ CreateKeyframeIfNonExistent(theKeyframes[i], m_AnimationHandles[0]);
+ }
+}
+
+void CUICDMTimelineItemProperty::ReleaseKeyframes()
+{
+ // clear any selection from m_TransMgr
+ TKeyframeList::iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ m_TransMgr->GetKeyframesManager()->SetKeyframeSelected(*theIter, false);
+
+ SAFE_DELETE(*theIter);
+ }
+ m_Keyframes.clear();
+ m_AnimationHandles.clear();
+}
+
+// Type doesn't change and due to the logic required to figure this out, cache it.
+void CUICDMTimelineItemProperty::InitializeCachedVariables(UICDM::CUICDMInstanceHandle inInstance)
+{
+ using namespace Q3DStudio;
+ UICDM::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
+
+ m_Type.first = thePropertySystem->GetDataType(m_PropertyHandle);
+ m_Type.second = thePropertySystem->GetAdditionalMetaDataType(inInstance, m_PropertyHandle);
+
+ // Name doesn't change either.
+ TCharStr theFormalName = thePropertySystem->GetFormalName(inInstance, m_PropertyHandle);
+
+ if (theFormalName.empty()) // fallback on property name
+ theFormalName = thePropertySystem->GetName(m_PropertyHandle);
+ m_Name = theFormalName.c_str();
+}
+
+Q3DStudio::CString CUICDMTimelineItemProperty::GetName() const
+{
+ return m_Name;
+}
+
+// Helper function to retrieve the parent binding class.
+inline ITimelineItemBinding *GetParentBinding(CPropertyRow *inRow)
+{
+ ITimelineItemBinding *theParentBinding = nullptr;
+ if (inRow) {
+ CBaseStateRow *theParentRow = inRow->GetParentRow();
+ if (theParentRow) {
+ theParentBinding = theParentRow->GetTimelineItemBinding();
+ ASSERT(theParentBinding); // TimelineItemBinding should be set properly during
+ // CBaseStateRow::Initialize
+ }
+ }
+ return theParentBinding;
+}
+
+bool CUICDMTimelineItemProperty::IsMaster() const
+{
+ if (m_Row) {
+ if (CUICDMTimelineItemBinding *theParentBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetParentBinding(m_Row)))
+ return m_TransMgr->GetDoc()->GetDocumentReader().IsPropertyLinked(
+ theParentBinding->GetInstanceHandle(), m_PropertyHandle);
+ }
+ return false;
+}
+
+UICDM::TDataTypePair CUICDMTimelineItemProperty::GetType() const
+{
+ return m_Type;
+}
+
+void CompareAndSet(const CUICDMTimelineKeyframe *inKeyframe, float &outRetValue, bool inGreaterThan)
+{
+ float theValue = (inGreaterThan) ? inKeyframe->GetMaxValue() : inKeyframe->GetMinValue();
+ if ((inGreaterThan && theValue > outRetValue) || (!inGreaterThan && theValue < outRetValue))
+ outRetValue = theValue;
+}
+
+// return the max value of the current set of keyframes
+float CUICDMTimelineItemProperty::GetMaximumValue() const
+{
+ float theRetVal = FLT_MIN;
+ do_all(m_Keyframes, boost::bind(CompareAndSet, _1, boost::ref(theRetVal), true));
+ if (m_Type.first == DataModelDataType::Float3 && m_Type.second == AdditionalMetaDataType::Color)
+ theRetVal = UICDMToColor(theRetVal);
+ return theRetVal;
+}
+
+// return the min value of the current set of keyframes
+float CUICDMTimelineItemProperty::GetMinimumValue() const
+{
+ float theRetVal = FLT_MAX;
+ do_all(m_Keyframes, boost::bind(CompareAndSet, _1, boost::ref(theRetVal), false));
+ if (m_Type.first == DataModelDataType::Float3 && m_Type.second == AdditionalMetaDataType::Color)
+ theRetVal = UICDMToColor(theRetVal);
+ return theRetVal;
+}
+
+void CUICDMTimelineItemProperty::Bind(CPropertyRow *inRow)
+{
+ ASSERT(!m_Row);
+
+ m_Row = inRow;
+}
+
+void CUICDMTimelineItemProperty::Release()
+{
+ m_Row = nullptr;
+}
+
+// Ensures the object that owns this property is selected.
+void CUICDMTimelineItemProperty::SetSelected()
+{
+ if (m_Row) {
+ ITimelineItemBinding *theParentBinding = GetParentBinding(m_Row);
+ if (theParentBinding)
+ theParentBinding->SetSelected(false);
+ }
+}
+
+void CUICDMTimelineItemProperty::ClearKeySelection()
+{
+ m_TransMgr->ClearKeyframeSelection();
+}
+
+void CUICDMTimelineItemProperty::DeleteAllKeys()
+{
+ if (m_Keyframes.empty())
+ return;
+
+ using namespace Q3DStudio;
+
+ ScopedDocumentEditor editor(*m_TransMgr->GetDoc(), L"Delete All Keyframes", __FILE__, __LINE__);
+ for (size_t idx = 0, end = m_AnimationHandles.size(); idx < end; ++idx)
+ editor->DeleteAllKeyframes(m_AnimationHandles[idx]);
+}
+
+ITimelineKeyframesManager *CUICDMTimelineItemProperty::GetKeyframesManager() const
+{
+ return m_TransMgr->GetKeyframesManager();
+}
+
+IKeyframe *CUICDMTimelineItemProperty::GetKeyframeByTime(long inTime) const
+{
+ std::vector<long> theTest;
+ TKeyframeList::const_iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ if ((*theIter)->GetTime() == inTime)
+ return (*theIter);
+
+ theTest.push_back((*theIter)->GetTime());
+ }
+ // if key had been deleted, this returns nullptr
+ return nullptr;
+}
+
+IKeyframe *CUICDMTimelineItemProperty::GetKeyframeByIndex(long inIndex) const
+{
+ if (inIndex >= 0 && inIndex < (long)m_Keyframes.size())
+ return m_Keyframes[inIndex];
+
+ ASSERT(0); // should not happen
+ return nullptr;
+}
+
+long CUICDMTimelineItemProperty::GetKeyframeCount() const
+{
+ // this list is updated in constructor and when keyframes are added or deleted.
+ return (long)m_Keyframes.size();
+}
+
+long CUICDMTimelineItemProperty::GetChannelCount() const
+{
+ return (long)m_AnimationHandles.size();
+}
+
+float CUICDMTimelineItemProperty::GetChannelValueAtTime(long inChannelIndex, long inTime)
+{
+ // if no keyframes, get current property value.
+ if (m_Keyframes.empty()) {
+ CUICDMTimelineItemBinding *theParentBinding =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetParentBinding(m_Row));
+ if (theParentBinding) {
+
+ SValue theValue;
+ UICDM::IPropertySystem *thePropertySystem =
+ m_TransMgr->GetStudioSystem()->GetPropertySystem();
+ thePropertySystem->GetInstancePropertyValue(theParentBinding->GetInstanceHandle(),
+ m_PropertyHandle, theValue);
+ switch (m_Type.first) {
+ case DataModelDataType::Float3: {
+ if (m_Type.second == AdditionalMetaDataType::Color) {
+ SFloat3 theFloat3 = UICDM::get<SFloat3>(theValue);
+ if (inChannelIndex >= 0 && inChannelIndex < 3)
+ return UICDMToColor(theFloat3[inChannelIndex]);
+ } else {
+ SFloat3 theFloat3 = UICDM::get<SFloat3>(theValue);
+ if (inChannelIndex >= 0 && inChannelIndex < 3)
+ return theFloat3[inChannelIndex];
+ }
+ break;
+ }
+ case DataModelDataType::Float2: {
+ SFloat2 theFloat2 = UICDM::get<SFloat2>(theValue);
+ if (inChannelIndex >= 0 && inChannelIndex < 2)
+ return theFloat2[inChannelIndex];
+ break;
+ }
+ case DataModelDataType::Float:
+ return UICDM::get<float>(theValue);
+ break;
+ default: // TODO: handle other types
+ break;
+ }
+ }
+ }
+ IAnimationCore *theAnimationCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+ if (!m_AnimationHandles.empty() && inChannelIndex >= 0
+ && inChannelIndex < (long)m_AnimationHandles.size()) {
+ float theValue = theAnimationCore->EvaluateAnimation(
+ m_AnimationHandles[inChannelIndex], CUICDMTimelineKeyframe::GetTimeInSecs(inTime));
+ if (m_Type.first == DataModelDataType::Float3
+ && m_Type.second == AdditionalMetaDataType::Color)
+ theValue = UICDMToColor(theValue);
+
+ return theValue;
+ }
+ return 0.f;
+}
+
+void CUICDMTimelineItemProperty::SetChannelValueAtTime(long inChannelIndex, long inTime,
+ float inValue)
+{
+ using namespace boost;
+ CUICDMTimelineKeyframe *theKeyframeWrapper =
+ dynamic_cast<CUICDMTimelineKeyframe *>(GetKeyframeByTime(inTime));
+ if (theKeyframeWrapper) {
+ CUICDMTimelineKeyframe::TKeyframeHandleList theKeyframes;
+ theKeyframeWrapper->GetKeyframeHandles(theKeyframes);
+ if (!theKeyframes.empty() && inChannelIndex < (long)theKeyframes.size()) {
+ inValue /= 255;
+ if (!m_SetKeyframeValueCommand)
+ m_SetKeyframeValueCommand = new CCmdDataModelSetKeyframeValue(
+ g_StudioApp.GetCore()->GetDoc(), theKeyframes[inChannelIndex], inValue);
+ m_SetKeyframeValueCommand->Update(inValue);
+ }
+ }
+}
+
+long CUICDMTimelineItemProperty::OffsetSelectedKeyframes(long inOffset)
+{
+ long theRetVal = m_TransMgr->GetKeyframesManager()->OffsetSelectedKeyframes(inOffset);
+ if (m_Row) // UI update, since the data model sends no event while the change isn't commited.
+ {
+ m_Row->Refresh();
+ }
+ return theRetVal;
+}
+
+void CUICDMTimelineItemProperty::CommitChangedKeyframes()
+{
+ if (m_SetKeyframeValueCommand) { // if this is moving a keyframe value
+ g_StudioApp.GetCore()->ExecuteCommand(m_SetKeyframeValueCommand, false);
+ m_SetKeyframeValueCommand = nullptr;
+ } else // otherwise its changing keyframe times
+ m_TransMgr->GetKeyframesManager()->CommitChangedKeyframes();
+}
+
+void CUICDMTimelineItemProperty::OnEditKeyframeTime(long inCurrentTime, long inObjectAssociation)
+{
+ (void)inObjectAssociation;
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.SetKeyframesManager(m_TransMgr->GetKeyframesManager());
+ theTimeEditDlg.ShowDialog(inCurrentTime, 0, g_StudioApp.GetCore()->GetDoc(), ASSETKEYFRAME);
+}
+
+void CUICDMTimelineItemProperty::SelectKeyframes(bool inSelected, long inTime /*= -1 */)
+{
+ CUICDMTimelineItemBinding *theParent =
+ dynamic_cast<CUICDMTimelineItemBinding *>(GetParentBinding(m_Row));
+ DoSelectKeyframes(inSelected, inTime, false, theParent);
+}
+
+CPropertyRow *CUICDMTimelineItemProperty::GetRow()
+{
+ return m_Row;
+}
+
+bool CUICDMTimelineItemProperty::IsDynamicAnimation()
+{
+ return m_Keyframes.size() > 0 && m_Keyframes[0]->IsDynamic();
+}
+
+//=============================================================================
+/**
+ * For updating the UI when keyframes are added/updated/deleted.
+ */
+bool CUICDMTimelineItemProperty::RefreshKeyframe(UICDM::CUICDMKeyframeHandle inKeyframe,
+ ETimelineKeyframeTransaction inTransaction)
+{
+ bool theHandled = false;
+ switch (inTransaction) {
+ case ETimelineKeyframeTransaction_Delete: {
+ TKeyframeList::iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ CUICDMTimelineKeyframe *theKeyframe = *theIter;
+ if (theKeyframe->HasKeyframeHandle(inKeyframe)) { // clear selection
+ m_TransMgr->GetKeyframesManager()->SetKeyframeSelected(theKeyframe, false);
+ m_Keyframes.erase(theIter);
+
+ theHandled = true;
+ break;
+ }
+ }
+ } break;
+ case ETimelineKeyframeTransaction_Add: {
+ ASSERT(!m_AnimationHandles.empty());
+ IAnimationCore *theAnimationCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+ CUICDMAnimationHandle theAnimationHandle =
+ theAnimationCore->GetAnimationForKeyframe(inKeyframe);
+ // only create for the first animation handle.
+ if (theAnimationHandle == m_AnimationHandles[0]) { // for undo/redo, the keyframes can be
+ // added in reverse, hence the need to
+ // sort
+ if (CreateKeyframeIfNonExistent(inKeyframe, theAnimationHandle))
+ std::stable_sort(m_Keyframes.begin(), m_Keyframes.end(), SortKeyframeByTime);
+ theHandled = true;
+ }
+ } break;
+ case ETimelineKeyframeTransaction_Update:
+ case ETimelineKeyframeTransaction_DynamicChanged:
+ theHandled = true;
+ break;
+ default:
+ return false;
+ }
+ if (theHandled && m_Row)
+ m_Row->Refresh();
+
+ return theHandled;
+}
+
+IKeyframe *CUICDMTimelineItemProperty::GetKeyframeByHandle(UICDM::CUICDMKeyframeHandle inKeyframe)
+{
+ TKeyframeList::iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ CUICDMTimelineKeyframe *theKeyframe = *theIter;
+ if (theKeyframe->HasKeyframeHandle(inKeyframe))
+ return *theIter;
+ }
+ return nullptr;
+}
+
+// This is either triggered from this property's keyframe selection OR from a parent's keyframe
+// selection.
+void CUICDMTimelineItemProperty::DoSelectKeyframes(bool inSelected, long inTime,
+ bool inParentTriggered,
+ CUICDMTimelineItemBinding *inParent)
+{
+ // this is what it used to do before the refactor. selecting a keyframe always selects the
+ // asset.
+ if (inSelected)
+ SetSelected();
+
+ if (!inParent)
+ return;
+
+ if (inTime == -1) // all keyframes
+ {
+ TKeyframeList::iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ (*theIter)->SetSelected(inSelected);
+ m_TransMgr->GetKeyframesManager()->SetKeyframeSelected(*theIter, inSelected, inParent);
+ }
+ } else {
+ CUICDMTimelineKeyframe *theKeyframe =
+ dynamic_cast<CUICDMTimelineKeyframe *>(GetKeyframeByTime(inTime));
+ if (theKeyframe) {
+ theKeyframe->SetSelected(inSelected);
+ m_TransMgr->GetKeyframesManager()->SetKeyframeSelected(theKeyframe, inSelected,
+ inParent);
+ }
+ }
+ // Requires UI to be updated explicitly
+ if (inParentTriggered && m_Row)
+ m_Row->GetTimebar()->SelectKeysByTime(inTime, inSelected);
+
+ // Support existing feature, selection by mouse-drag a rect, when all property keyframes are
+ // selected, the asset keyframe is automatically selected as well.
+ // and the mouse drags 'outside' a keyframe and de-selecting it, the asset keyframe has to be
+ // deselected as well.
+ if (!inParentTriggered && inTime != -1)
+ inParent->OnPropertySelection(inTime);
+}
+
+//=============================================================================
+/**
+ * Create a wrapper for this keyframe if doesn't exists.
+ * @return true if created, false if already exists.
+ */
+bool CUICDMTimelineItemProperty::CreateKeyframeIfNonExistent(
+ UICDM::CUICDMKeyframeHandle inKeyframeHandle, CUICDMAnimationHandle inOwningAnimation)
+{
+ TKeyframeList::iterator theIter = m_Keyframes.begin();
+ for (; theIter != m_Keyframes.end(); ++theIter) {
+ CUICDMTimelineKeyframe *theKeyframe = *theIter;
+ if (theKeyframe->HasKeyframeHandle(inKeyframeHandle))
+ return false;
+ }
+ // check for multiple channels => only create 1 CUICDMTimelineKeyframe
+ CUICDMTimelineKeyframe *theNewKeyframe =
+ new CUICDMTimelineKeyframe(g_StudioApp.GetCore()->GetDoc());
+ theNewKeyframe->AddKeyframeHandle(inKeyframeHandle);
+ if (m_AnimationHandles.size()
+ > 1) { // assert assumption that is only called for the first handle
+ ASSERT(m_AnimationHandles[0] == inOwningAnimation);
+ IAnimationCore *theAnimationCore = m_TransMgr->GetStudioSystem()->GetAnimationCore();
+ float theKeyframeTime = KeyframeTime(theAnimationCore->GetKeyframeData(inKeyframeHandle));
+ for (size_t i = 1; i < m_AnimationHandles.size(); ++i) {
+ TKeyframeHandleList theKeyframes;
+ theAnimationCore->GetKeyframes(m_AnimationHandles[i], theKeyframes);
+ // the data model ensures that there is only 1 keyframe created for a given time
+ for (size_t theKeyIndex = 0; theKeyIndex < theKeyframes.size(); ++theKeyIndex) {
+ float theValue =
+ KeyframeTime(theAnimationCore->GetKeyframeData(theKeyframes[theKeyIndex]));
+ if (theValue == theKeyframeTime) {
+ theNewKeyframe->AddKeyframeHandle(theKeyframes[theKeyIndex]);
+ break;
+ }
+ }
+ }
+ }
+ m_Keyframes.push_back(theNewKeyframe);
+ return true;
+}
+
+void CUICDMTimelineItemProperty::OnPropertyLinkStatusChanged(UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty)
+{
+ if (inInstance == m_InstanceHandle && inProperty == m_PropertyHandle) {
+ // Re-bind to keyframes because the ones we should be pointing to will have changed.
+ ReleaseKeyframes();
+ CreateKeyframes();
+ }
+}
+
+void CUICDMTimelineItemProperty::RefreshKeyFrames(void)
+{
+ std::stable_sort(m_Keyframes.begin(), m_Keyframes.end(), SortKeyframeByTime);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.h
new file mode 100644
index 00000000..ddd4b647
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineItemProperty.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_UICDMTIMELINE_ITEM_PROPERTY_H
+#define INCLUDED_UICDMTIMELINE_ITEM_PROPERTY_H 1
+
+#pragma once
+
+#include "ITimelineItemProperty.h"
+#include "UICDMTimelineKeyframe.h"
+#include "UICDMTimeline.h"
+#include "UICDMPropertyDefinition.h"
+
+class CTimelineTranslationManager;
+class CCmdDataModelSetKeyframeValue;
+class CUICDMTimelineItemBinding;
+
+//=============================================================================
+/**
+ * A data model item's property.
+ * Typically only animated properties show up in the Timeline.
+ */
+//=============================================================================
+class CUICDMTimelineItemProperty : public ITimelineItemProperty
+{
+public:
+ CUICDMTimelineItemProperty(CTimelineTranslationManager *inTransMgr,
+ UICDM::CUICDMPropertyHandle inPropertyHandle,
+ UICDM::CUICDMInstanceHandle inInstance);
+ virtual ~CUICDMTimelineItemProperty();
+
+ // ITimelineProperty
+ Q3DStudio::CString GetName() const override;
+ bool IsMaster() const override;
+ UICDM::TDataTypePair GetType() const override;
+ float GetMaximumValue() const override;
+ float GetMinimumValue() const override;
+ void SetSelected() override;
+ void ClearKeySelection() override;
+ void DeleteAllKeys() override;
+ ITimelineKeyframesManager *GetKeyframesManager() const override;
+ IKeyframe *GetKeyframeByTime(long inTime) const override;
+ IKeyframe *GetKeyframeByIndex(long inIndex) const override;
+ long GetKeyframeCount() const override;
+ long GetChannelCount() const override;
+ float GetChannelValueAtTime(long inChannelIndex, long inTime) override;
+ void SetChannelValueAtTime(long inChannelIndex, long inTime, float inValue) override;
+ long OffsetSelectedKeyframes(long inOffset) override;
+ void CommitChangedKeyframes() override;
+ void OnEditKeyframeTime(long inCurrentTime, long inObjectAssociation) override;
+ bool IsDynamicAnimation() override;
+ // IKeyframeSelector
+ void SelectKeyframes(bool inSelected, long inTime = -1) override;
+
+ void Bind(CPropertyRow *inRow) override;
+ void Release() override;
+ CPropertyRow *GetRow() override;
+
+ bool RefreshKeyframe(UICDM::CUICDMKeyframeHandle inKeyframe,
+ ETimelineKeyframeTransaction inTransaction);
+ IKeyframe *GetKeyframeByHandle(UICDM::CUICDMKeyframeHandle inKeyframe);
+ void DoSelectKeyframes(bool inSelected, long inTime, bool inParentTriggered,
+ CUICDMTimelineItemBinding *inParent);
+
+ void RefreshKeyFrames(void);
+
+protected:
+ void InitializeCachedVariables(UICDM::CUICDMInstanceHandle inInstance);
+ bool CreateKeyframeIfNonExistent(UICDM::CUICDMKeyframeHandle inKeyframe,
+ UICDM::CUICDMAnimationHandle inOwningAnimation);
+ void OnPropertyLinkStatusChanged(UICDM::CUICDMSlideHandle inSlide,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+ void CreateKeyframes();
+ void ReleaseKeyframes();
+
+protected:
+ typedef std::vector<CUICDMTimelineKeyframe *> TKeyframeList;
+
+ CPropertyRow *m_Row;
+ UICDM::CUICDMInstanceHandle m_InstanceHandle;
+ UICDM::CUICDMPropertyHandle m_PropertyHandle;
+ CTimelineTranslationManager *m_TransMgr;
+ std::vector<UICDM::CUICDMAnimationHandle> m_AnimationHandles;
+ TKeyframeList m_Keyframes;
+ CCmdDataModelSetKeyframeValue
+ *m_SetKeyframeValueCommand; // for merging modifying keyframe values via graph
+ UICDM::TDataTypePair m_Type;
+ Q3DStudio::CString m_Name;
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>> m_Signals;
+};
+
+#endif // INCLUDED_UICDMTIMELINE_ITEM_PROPERTY_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.cpp
new file mode 100644
index 00000000..c29062a2
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "UICDMTimelineKeyframe.h"
+#include "UICDMAnimation.h"
+#include "CmdDataModelChangeKeyframe.h"
+#include "CmdBatch.h"
+#include "UICDMStudioSystem.h"
+#include "OffsetKeyframesCommandHelper.h"
+
+#include "Doc.h"
+#include "StudioApp.h"
+#include "Core.h"
+
+using namespace UICDM;
+
+// TODO: figure out if we can just use IDoc instead of CDoc
+CUICDMTimelineKeyframe::CUICDMTimelineKeyframe(IDoc *inDoc)
+ : m_Doc(dynamic_cast<CDoc *>(inDoc))
+ , m_Selected(false)
+{
+}
+
+CUICDMTimelineKeyframe::~CUICDMTimelineKeyframe()
+{
+}
+
+bool CUICDMTimelineKeyframe::IsSelected() const
+{
+ return m_Selected;
+}
+
+float my_roundf(float r)
+{
+ return (r > 0.0f) ? floorf(r + 0.5f) : ceilf(r - 0.5f);
+}
+
+long CUICDMTimelineKeyframe::GetTime() const
+{
+ if (!m_KeyframeHandles.empty()) {
+ IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ CUICDMKeyframeHandle theKeyframeHandle = *m_KeyframeHandles.begin();
+ if (theAnimationCore->KeyframeValid(theKeyframeHandle)) {
+ float theTimeinSecs =
+ KeyframeTime(theAnimationCore->GetKeyframeData(theKeyframeHandle));
+ // We always convert back and forth between between long and float.
+ // This causes especially issues when we do comparisons
+ return (long)my_roundf(theTimeinSecs * 1000);
+ }
+ }
+ return -1; // keyframe was deleted, and data cannot be retrieved.
+}
+
+float CUICDMTimelineKeyframe::GetTimeInSecs(long inTime)
+{
+ float theTimeinSecs = static_cast<float>(inTime) / 1000.f;
+ // round off to 4 decimal place to workaround precision issues
+ // TODO: fix this, either all talk float OR long. choose one.
+ theTimeinSecs = (float)(((theTimeinSecs + 0.00005) * 10000.0) / 10000.0f);
+ return theTimeinSecs;
+}
+
+void CUICDMTimelineKeyframe::SetTime(const long inNewTime)
+{
+ float theTimeinSecs = GetTimeInSecs(inNewTime);
+ CCmd *theCmd = nullptr;
+ if (m_KeyframeHandles.size() == 1) {
+ theCmd = new CCmdDataModelSetKeyframeTime(m_Doc, m_KeyframeHandles.front(), theTimeinSecs);
+ } else { // more than 1 channel
+ CCmdBatch *theBatch = new CCmdBatch(m_Doc);
+ TKeyframeHandleList::iterator theIter = m_KeyframeHandles.begin();
+ for (; theIter != m_KeyframeHandles.end(); ++theIter)
+ theBatch->AddCommand(new CCmdDataModelSetKeyframeTime(m_Doc, *theIter, theTimeinSecs));
+ theCmd = theBatch;
+ }
+ if (theCmd)
+ m_Doc->GetCore()->ExecuteCommand(theCmd);
+
+#ifdef _DEBUG
+ // we have a precision issue from converting from long to float..
+ IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ long theTest = static_cast<long>(
+ KeyframeTime(theAnimationCore->GetKeyframeData(*m_KeyframeHandles.begin())) * 1000);
+ ASSERT(inNewTime == theTest);
+#endif
+}
+
+inline CUICDMAnimationHandle GetAnimationHandle(UICDM::IAnimationCore *inAnimationCore,
+ const TKeyframeHandleList &inKeyframes)
+{
+ if (!inKeyframes.empty())
+ return inAnimationCore->GetAnimationForKeyframe(inKeyframes[0]);
+ return 0;
+}
+
+void CUICDMTimelineKeyframe::SetDynamic(bool inIsDynamic)
+{
+ if (!m_KeyframeHandles.empty()) {
+ CUICDMAnimationHandle theAnimation =
+ GetAnimationHandle(m_Doc->GetStudioSystem()->GetAnimationCore(), m_KeyframeHandles);
+ if (theAnimation.Valid())
+ m_Doc->GetCore()->ExecuteCommand(
+ new CCmdDataModelChangeDynamicKeyframe(m_Doc, theAnimation, inIsDynamic));
+ }
+}
+
+// Only the first key of a track can be dynamic.
+bool CUICDMTimelineKeyframe::IsDynamic() const
+{
+ UICDM::IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ CUICDMAnimationHandle theAnimation = GetAnimationHandle(theAnimationCore, m_KeyframeHandles);
+ if (theAnimation.Valid()) {
+ SAnimationInfo theInfo = theAnimationCore->GetAnimationInfo(theAnimation);
+ if (theInfo.m_DynamicFirstKeyframe) {
+ TKeyframeHandleList theKeyframes;
+ theAnimationCore->GetKeyframes(theAnimation, theKeyframes);
+ if (!theKeyframes.empty()) // only true if track is dynamic and this is the first
+ // keyframe. Might have to optimize because this is so
+ // clunky.
+ return (theKeyframes[0] == m_KeyframeHandles[0]);
+ }
+ }
+ return false;
+}
+
+void CUICDMTimelineKeyframe::AddKeyframeHandle(UICDM::CUICDMKeyframeHandle inHandle)
+{
+ m_KeyframeHandles.push_back(inHandle);
+}
+
+bool CUICDMTimelineKeyframe::HasKeyframeHandle(UICDM::CUICDMKeyframeHandle inHandle) const
+{
+ TKeyframeHandleList::const_iterator theIter = m_KeyframeHandles.begin();
+ for (; theIter != m_KeyframeHandles.end(); ++theIter) {
+ if (*theIter == inHandle)
+ return true;
+ }
+ return false;
+}
+
+void CUICDMTimelineKeyframe::SetSelected(bool inSelected)
+{
+ m_Selected = inSelected;
+}
+
+// For colors, there would be 3 keyframe handles
+void CUICDMTimelineKeyframe::UpdateKeyframesTime(COffsetKeyframesCommandHelper *inCommandHelper,
+ long inTime)
+{
+ for (size_t i = 0; i < m_KeyframeHandles.size(); ++i)
+ inCommandHelper->SetCommandTime(m_KeyframeHandles[i], inTime);
+}
+
+void CUICDMTimelineKeyframe::GetKeyframeHandles(TKeyframeHandleList &outList) const
+{
+ outList = m_KeyframeHandles;
+}
+
+void CompareAndSet(CUICDMKeyframeHandle inKeyframe, IAnimationCore *inAnimationCore,
+ float &outRetValue, bool inGreaterThan)
+{
+ TKeyframe theKeyframeData = inAnimationCore->GetKeyframeData(inKeyframe);
+ float theValue = KeyframeValueValue(theKeyframeData);
+ if ((inGreaterThan && theValue > outRetValue) || (!inGreaterThan && theValue < outRetValue))
+ outRetValue = theValue;
+}
+
+float CUICDMTimelineKeyframe::GetMaxValue() const
+{
+ IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ float theRetVal = FLT_MIN;
+ do_all(m_KeyframeHandles,
+ std::bind(CompareAndSet, std::placeholders::_1, theAnimationCore,
+ std::ref(theRetVal), true));
+ return theRetVal;
+}
+
+float CUICDMTimelineKeyframe::GetMinValue() const
+{
+ IAnimationCore *theAnimationCore = m_Doc->GetStudioSystem()->GetAnimationCore();
+ float theRetVal = FLT_MAX;
+ do_all(m_KeyframeHandles,
+ std::bind(CompareAndSet, std::placeholders::_1, theAnimationCore,
+ std::ref(theRetVal), false));
+ return theRetVal;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.h
new file mode 100644
index 00000000..bb615202
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineKeyframe.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef INCLUDED_UICDMKEYFRAME_H
+#define INCLUDED_UICDMKEYFRAME_H 1
+
+#pragma once
+
+#include "IKeyframe.h"
+
+// Data model specific
+#include "UICDMHandles.h"
+
+class IDoc;
+class CDoc;
+class CCmdBatch;
+class COffsetKeyframesCommandHelper;
+
+//==============================================================================
+/**
+ * Wrapper for a keyframe in UICDM.
+ */
+//==============================================================================
+class CUICDMTimelineKeyframe : public IKeyframe
+{
+public:
+ typedef std::vector<UICDM::CUICDMKeyframeHandle> TKeyframeHandleList;
+
+protected:
+ TKeyframeHandleList
+ m_KeyframeHandles; ///< no. corresponds to the channels the animated property has.
+ CDoc *m_Doc;
+ bool m_Selected;
+
+public:
+ CUICDMTimelineKeyframe(IDoc *inDoc);
+ virtual ~CUICDMTimelineKeyframe();
+
+ // IKeyframe
+ bool IsSelected() const override;
+ long GetTime() const override;
+ void SetTime(const long inNewTime) override;
+ void SetDynamic(bool inIsDynamic) override;
+ bool IsDynamic() const override;
+
+ void AddKeyframeHandle(UICDM::CUICDMKeyframeHandle inHandle);
+ bool HasKeyframeHandle(UICDM::CUICDMKeyframeHandle inHandle) const;
+ void SetSelected(bool inSelected);
+ void UpdateKeyframesTime(COffsetKeyframesCommandHelper *inCommandHelper, long inTime);
+ void GetKeyframeHandles(TKeyframeHandleList &outList) const;
+
+ // support drawing graphs
+ float GetMaxValue() const;
+ float GetMinValue() const;
+
+ static float GetTimeInSecs(long inTime);
+};
+
+#endif // INCLUDED_UICDMKEYFRAME_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.cpp
new file mode 100644
index 00000000..2c44e438
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMTimelineTimebar.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMDataCore.h"
+#include "UICDMDataTypes.h"
+#include "ClientDataModelBridge.h"
+#include "TimelineTranslationManager.h"
+#include "Doc.h"
+#include "Dispatch.h"
+#include "Core.h"
+#include "TimeEditDlg.h"
+#include "IDocumentEditor.h"
+#include "BaseStateRow.h"
+#include "BaseTimebarlessRow.h"
+#include "StudioFullSystem.h"
+#include "StudioPreferences.h"
+#include "ITimelineItemBinding.h"
+
+CUICDMTimelineTimebar::CUICDMTimelineTimebar(
+ CTimelineTranslationManager *inTimelineTranslationManager,
+ UICDM::CUICDMInstanceHandle inDataHandle)
+ : Q3DStudio::CUpdateableDocumentEditor(*inTimelineTranslationManager->GetDoc())
+ , m_TimelineTranslationManager(inTimelineTranslationManager)
+ , m_PropertySystem(inTimelineTranslationManager->GetStudioSystem()->GetPropertySystem())
+ , m_DataHandle(inDataHandle)
+{
+ CClientDataModelBridge *theClientDataModelBridge =
+ inTimelineTranslationManager->GetStudioSystem()->GetClientDataModelBridge();
+ m_StartTime = theClientDataModelBridge->GetSceneAsset().m_StartTime;
+ m_EndTime = theClientDataModelBridge->GetSceneAsset().m_EndTime;
+ UICDM::SValue theValue;
+ if (m_PropertySystem->GetInstancePropertyValue(
+ m_DataHandle, theClientDataModelBridge->GetSceneAsset().m_TimebarColor, theValue)) {
+ UICDM::SFloat3 theTimebarColor = UICDM::get<UICDM::SFloat3>(theValue);
+
+ m_Color.SetRGB(static_cast<int>(theTimebarColor.m_Floats[0] * 255.0f),
+ static_cast<int>(theTimebarColor.m_Floats[1] * 255.0f),
+ static_cast<int>(theTimebarColor.m_Floats[2] * 255.0f));
+ }
+ UICDM::IStudioFullSystemSignalProvider *theProvider =
+ inTimelineTranslationManager->GetStudioSystem()->GetFullSystem()->GetSignalProvider();
+ m_PropertyChangedSignal = theProvider->ConnectInstancePropertyValue(
+ std::bind(&CUICDMTimelineTimebar::OnPropertyChanged, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ OnPropertyChanged(m_DataHandle, theClientDataModelBridge->GetSceneAsset().m_TimebarColor);
+ OnPropertyChanged(m_DataHandle, theClientDataModelBridge->GetSceneAsset().m_TimebarText);
+}
+
+void CUICDMTimelineTimebar::OnPropertyChanged(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty)
+{
+ if (m_DataHandle == inInstance) {
+ bool needsInvalidate = false;
+ UICDM::SValue theValue;
+ CClientDataModelBridge *theClientDataModelBridge =
+ m_TimelineTranslationManager->GetStudioSystem()->GetClientDataModelBridge();
+ if (inProperty == theClientDataModelBridge->GetSceneAsset().m_TimebarColor) {
+
+ if (m_PropertySystem->GetInstancePropertyValue(
+ m_DataHandle, theClientDataModelBridge->GetSceneAsset().m_TimebarColor,
+ theValue)) {
+ UICDM::SFloat3 theTimebarColor = UICDM::get<UICDM::SFloat3>(theValue);
+
+ m_Color.SetRGB(static_cast<int>(theTimebarColor.m_Floats[0] * 255.0f),
+ static_cast<int>(theTimebarColor.m_Floats[1] * 255.0f),
+ static_cast<int>(theTimebarColor.m_Floats[2] * 255.0f));
+ } else {
+ switch (theClientDataModelBridge->GetObjectType(inInstance)) {
+ case OBJTYPE_LAYER:
+ m_Color = CStudioPreferences::GetLayerTimebarColor();
+ break;
+ case OBJTYPE_BEHAVIOR:
+ m_Color = CStudioPreferences::GetBehaviorTimebarColor();
+ break;
+ case OBJTYPE_CAMERA:
+ m_Color = CStudioPreferences::GetCameraTimebarColor();
+ break;
+ case OBJTYPE_LIGHT:
+ m_Color = CStudioPreferences::GetLightTimebarColor();
+ break;
+ case OBJTYPE_MODEL:
+ m_Color = CStudioPreferences::GetModelTimebarColor();
+ break;
+ case OBJTYPE_GROUP:
+ m_Color = CStudioPreferences::GetGroupTimebarColor();
+ break;
+ case OBJTYPE_COMPONENT:
+ m_Color = CStudioPreferences::GetComponentTimebarColor();
+ break;
+ case OBJTYPE_EFFECT:
+ m_Color = CStudioPreferences::GetEffectTimebarColor();
+ break;
+ default:
+ m_Color = CStudioPreferences::GetObjectTimebarColor();
+ break;
+ }
+ }
+ needsInvalidate = true;
+ } else if (inProperty == theClientDataModelBridge->GetSceneAsset().m_TimebarText) {
+ if (m_PropertySystem->GetInstancePropertyValue(
+ m_DataHandle, theClientDataModelBridge->GetSceneAsset().m_TimebarText,
+ theValue)) {
+ UICDM::SStringRef theTimebarComment = UICDM::get<UICDM::SStringRef>(theValue);
+ m_Comment.Assign(static_cast<const wchar_t *>(theTimebarComment));
+ } else {
+ m_Comment.Assign(L"");
+ }
+ needsInvalidate = true;
+ }
+ if (needsInvalidate) {
+ ITimelineItemBinding *theBinding =
+ m_TimelineTranslationManager->GetOrCreate(inInstance);
+ if (theBinding) {
+ CBaseStateRow *theRow = theBinding->GetRow();
+ if (theRow) {
+ CBaseTimebarlessRow *theTimebar = theRow->GetTimebar();
+ theTimebar->RefreshRowMetaData();
+ }
+ }
+ }
+ }
+}
+
+CUICDMTimelineTimebar::~CUICDMTimelineTimebar()
+{
+}
+
+// TODO: Can we put this on IInstancePropertyCore?
+template <typename T>
+T GetInstancePropertyValue(UICDM::IPropertySystem *inPropertySystem,
+ UICDM::CUICDMInstanceHandle inInstanceHandle,
+ UICDM::CUICDMPropertyHandle inProperty)
+{
+ UICDM::SValue theValue;
+ inPropertySystem->GetInstancePropertyValue(inInstanceHandle, inProperty, theValue);
+ return UICDM::get<T>(theValue);
+}
+
+long CUICDMTimelineTimebar::GetStartTime() const
+{
+ return GetInstancePropertyValue<qt3ds::QT3DSI32>(m_PropertySystem, m_DataHandle, m_StartTime);
+}
+
+long CUICDMTimelineTimebar::GetEndTime() const
+{
+ return GetInstancePropertyValue<qt3ds::QT3DSI32>(m_PropertySystem, m_DataHandle, m_EndTime);
+}
+
+long CUICDMTimelineTimebar::GetDuration() const
+{
+ auto theStartTime = GetInstancePropertyValue<qt3ds::QT3DSI32>(m_PropertySystem, m_DataHandle, m_StartTime);
+ auto theEndTime = GetInstancePropertyValue<qt3ds::QT3DSI32>(m_PropertySystem, m_DataHandle, m_EndTime);
+
+ return theEndTime - theStartTime;
+}
+
+bool CUICDMTimelineTimebar::ShowHandleBars() const
+{
+ return true;
+}
+
+void CUICDMTimelineTimebar::OnBeginDrag()
+{ // Really? TODO: Figure out why this is here.
+ // ASSERT(0);
+}
+
+void CUICDMTimelineTimebar::OffsetTime(long inDiff)
+{
+ if (m_DataHandle.Valid()) {
+ ENSURE_EDITOR(L"Time Bar Move").OffsetTimeRange(m_DataHandle, inDiff);
+ m_TimelineTranslationManager->GetDoc()
+ ->GetCore()
+ ->GetDispatch()
+ ->FireImmediateRefreshInstance(m_DataHandle);
+ }
+}
+
+void CUICDMTimelineTimebar::ChangeTime(long inTime, bool inSetStart)
+{
+ if (m_DataHandle.Valid()) {
+ ENSURE_EDITOR(L"Time Bar Resize").ResizeTimeRange(m_DataHandle, inTime, inSetStart);
+ m_TimelineTranslationManager->GetDoc()
+ ->GetCore()
+ ->GetDispatch()
+ ->FireImmediateRefreshInstance(m_DataHandle);
+ }
+}
+
+void CUICDMTimelineTimebar::CommitTimeChange()
+{
+ CommitEditor();
+}
+
+void CUICDMTimelineTimebar::RollbackTimeChange()
+{
+ RollbackEditor();
+}
+
+void CUICDMTimelineTimebar::SetTimebarColor(const ::CColor &inColor)
+{
+ using namespace Q3DStudio;
+ if (inColor != m_Color) {
+ UICDM::CUICDMInstanceHandle theHandle = m_DataHandle;
+ SCOPED_DOCUMENT_EDITOR(*m_TimelineTranslationManager->GetDoc(), QObject::tr("Set Timebar Color"))
+ ->SetTimebarColor(theHandle, inColor);
+ }
+}
+
+void CUICDMTimelineTimebar::SetTimebarComment(const Q3DStudio::CString &inComment)
+{
+ using namespace Q3DStudio;
+ if (inComment != m_Comment) {
+ UICDM::CUICDMInstanceHandle theHandle = m_DataHandle;
+ SCOPED_DOCUMENT_EDITOR(*m_TimelineTranslationManager->GetDoc(), QObject::tr("Set Timebar Text"))
+ ->SetTimebarText(theHandle, inComment);
+ }
+}
+
+void CUICDMTimelineTimebar::SetTimebarTime(ITimeChangeCallback *inCallback /*= nullptr*/)
+{
+ long theStartTime = GetStartTime();
+ long theEndTime = GetEndTime();
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.ShowDialog(theStartTime, theEndTime, m_TimelineTranslationManager->GetDoc(),
+ TIMEBAR, inCallback);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.h
new file mode 100644
index 00000000..d1441039
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/UICDMTimelineTimebar.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+///////////////////////////////////////////////////////////////////////////////
+// Includes
+#include "ITimelineTimebar.h"
+#include "UICDMHandles.h"
+#include "IDocumentEditor.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Forwards
+class CTimelineTranslationManager;
+
+namespace Q3DStudio {
+class IDocumentEditor;
+}
+
+namespace UICDM {
+class IPropertySystem;
+class ISignalConnection;
+}
+
+//=============================================================================
+/**
+ * General timebar implementation for UICDM objects
+ */
+class CUICDMTimelineTimebar : public ITimelineTimebar, public Q3DStudio::CUpdateableDocumentEditor
+{
+public:
+ CUICDMTimelineTimebar(CTimelineTranslationManager *inTimelineTranslationManager,
+ UICDM::CUICDMInstanceHandle inDataHandle);
+ virtual ~CUICDMTimelineTimebar();
+
+protected:
+ CTimelineTranslationManager *m_TimelineTranslationManager;
+ UICDM::IPropertySystem *m_PropertySystem;
+ UICDM::CUICDMInstanceHandle m_DataHandle; // The Instance Handle for this Timeline Timeber.
+ UICDM::CUICDMPropertyHandle m_StartTime;
+ UICDM::CUICDMPropertyHandle m_EndTime;
+ ::CColor m_Color; // Timebar color
+ Q3DStudio::CString m_Comment; // Timebar comment text
+ std::shared_ptr<UICDM::ISignalConnection> m_PropertyChangedSignal;
+ void OnPropertyChanged(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty);
+
+public:
+ // ITimelineTimebar
+ long GetStartTime() const override;
+ long GetEndTime() const override;
+ long GetDuration() const override;
+ bool ShowHandleBars() const override;
+ void OnBeginDrag() override;
+ void OffsetTime(long inDiff) override;
+ void ChangeTime(long inTime, bool inSetStart) override;
+ void CommitTimeChange() override;
+ void RollbackTimeChange() override;
+ ::CColor GetTimebarColor() override { return m_Color; }
+ void SetTimebarColor(const ::CColor &inColor) override;
+ Q3DStudio::CString GetTimebarComment() override { return m_Comment; }
+ void SetTimebarComment(const Q3DStudio::CString &inComment) override;
+ void SetTimebarTime(ITimeChangeCallback *inCallback = nullptr) override;
+};
diff --git a/src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.cpp b/src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.cpp
new file mode 100644
index 00000000..fb25559a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "BlankToggleControl.h"
+#include "Renderer.h"
+#include "BaseStateRow.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+
+CBlankToggleControl::CBlankToggleControl(CBaseStateRow *inBaseStateRow)
+ : m_StateRow(inBaseStateRow)
+ , m_Selected(false)
+{
+ m_BackgroundColor = m_StateRow->GetTimebarBackgroundColor(inBaseStateRow->GetObjectType());
+}
+
+CBlankToggleControl::~CBlankToggleControl()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the drawing fo rthe toggle control
+ */
+void CBlankToggleControl::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+
+ // Fill in the background
+ if (!m_Selected)
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+ else
+ inRenderer->FillSolidRect(theRect, CStudioPreferences::GetTimelineSelectColor());
+
+ // Draw the line at the bottom of this control
+ inRenderer->PushPen(CStudioPreferences::GetTreeFloorColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+ inRenderer->PopPen();
+
+ // Draw the line on the left side of this control
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theRect.size.y - 1));
+ inRenderer->PopPen();
+
+ // Draw the highlight
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(1, 0));
+ inRenderer->LineTo(CPt(1, theRect.size.y - 1));
+ inRenderer->PopPen();
+
+ // Draw the line on the right side of this control
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ inRenderer->MoveTo(CPt(theRect.size.x - 1, 0));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Notification that the object that this row is representing has been selected.
+ */
+void CBlankToggleControl::OnSelect()
+{
+ m_Selected = true;
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Notification that the object that this row is representing has been deselected.
+ */
+void CBlankToggleControl::OnDeselect()
+{
+ m_Selected = false;
+
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Handler for the OnMouseDown event
+ *
+ * @param inPoint the point where this event takes place
+ * @param inFlags the state when this event takes place.
+ */
+bool CBlankToggleControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_StateRow->Select(SBaseStateRowSelectionKeyState());
+ }
+ return true;
+}
+
+//==============================================================================
+/**
+ * Sets the background color of this toggle control
+ */
+void CBlankToggleControl::SetBackgroundColor(::CColor inBackgroundColor)
+{
+ if (m_BackgroundColor == inBackgroundColor)
+ return;
+
+ m_BackgroundColor = inBackgroundColor;
+
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Handler for the OnMouseOver event
+ *
+ * @param inPoint the point where this event takes place
+ * @param inFlags the state when this event takes place.
+ */
+void CBlankToggleControl::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ m_StateRow->OnMouseOver();
+}
+
+//==============================================================================
+/**
+ * Handler for the OnMouseOut event
+ *
+ * @param inPoint the point where this event takes place
+ * @param inFlags the state when this event takes place.
+ */
+void CBlankToggleControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ m_StateRow->OnMouseOut();
+}
+
+void CBlankToggleControl::Refresh()
+{
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.h b/src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.h
new file mode 100644
index 00000000..2fe4ce28
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/BlankToggleControl.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BLANK_TOGGLE_CONTROL_H
+#define INCLUDED_BLANK_TOGGLE_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+
+class CBaseStateRow;
+
+class CBlankToggleControl : public CControl
+{
+public:
+ CBlankToggleControl(CBaseStateRow *inStateRow);
+ virtual ~CBlankToggleControl();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ void OnSelect();
+ void OnDeselect();
+
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void SetBackgroundColor(::CColor inBackgroundColor);
+
+ virtual void Refresh();
+
+protected:
+ CBaseStateRow *m_StateRow;
+ bool m_Selected;
+
+ ::CColor m_BackgroundColor;
+};
+#endif // INCLUDED_BLANK_TOGGLE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.cpp b/src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.cpp
new file mode 100644
index 00000000..2564d087
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ColorBlankControl.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CColorBlankControl::CColorBlankControl(CColor inColor)
+ : CBlankControl(inColor)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CColorBlankControl::~CColorBlankControl()
+{
+}
+
+//=============================================================================
+/**
+ * Handles custom drawing of the blank control underneath the tree control
+ * on the timeline palette.
+ */
+void CColorBlankControl::Draw(CRenderer *inRenderer)
+{
+ CBlankControl::Draw(inRenderer);
+
+ // Draw the line on the right side of this control
+ CPt theSize = GetSize();
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ inRenderer->MoveTo(theSize.x - 1, 0);
+ inRenderer->LineTo(theSize.x - 1, theSize.y - 1);
+ inRenderer->PopPen();
+
+ // Draw the line on the left side of this control
+ inRenderer->PushPen(CStudioPreferences::GetRowTopColor());
+ inRenderer->MoveTo(0, 0);
+ inRenderer->LineTo(0, theSize.y - 1);
+ inRenderer->PopPen();
+
+ // Draw the highlight on the left side of this control
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(1, 0));
+ inRenderer->LineTo(CPt(1, theSize.y - 1));
+ inRenderer->PopPen();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.h b/src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.h
new file mode 100644
index 00000000..bb85b2aa
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ColorBlankControl.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_COLOR_BLANK_CONTROL_H
+#define INCLUDED_COLOR_BLANK_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BlankControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//=============================================================================
+/**
+ * Extends the blank control to draw items specific to the tree view side of the
+ * timeline palette.
+ */
+class CColorBlankControl : public CBlankControl
+{
+public:
+ CColorBlankControl(CColor inColor = CStudioPreferences::GetBaseColor());
+ virtual ~CColorBlankControl();
+ void Draw(CRenderer *inRenderer) override;
+
+protected:
+};
+
+#endif // INCLUDED_COLOR_BLANK_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ColorControl.cpp b/src/Authoring/Studio/Palettes/Timeline/ColorControl.cpp
new file mode 100644
index 00000000..71d1c392
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ColorControl.cpp
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "CColor.h"
+#include "ColorControl.h"
+#include "CoreUtils.h"
+#include "BaseStateRow.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+#include "Dispatch.h"
+#include "ResourceCache.h"
+#include "Bindings/ITimelineItem.h"
+
+//==============================================================================
+/**
+ * The control (of each row) to the left of the tree view, where it indicates if there are
+ *actions associated with this row.
+ */
+CColorControl::CColorControl(CBaseStateRow *inRow)
+ : m_Shaded(true)
+ , m_Selected(false)
+ , m_HasAction(false)
+ , m_HasMasterAction(false)
+ , m_ChildHasAction(false)
+ , m_ChildHasMasterAction(false)
+ , m_ComponentHasAction(false)
+ , m_ComponentHasMasterAction(false)
+{
+ m_ParentRow = inRow;
+ m_BackgroundColor = m_ParentRow->GetTimebarBackgroundColor(m_ParentRow->GetObjectType());
+
+ UpdateIconStatus();
+}
+
+CColorControl::~CColorControl()
+{
+}
+
+void CColorControl::SetShaded(bool inIsShaded)
+{
+ m_Shaded = inIsShaded;
+}
+
+//==============================================================================
+/**
+ * Draw
+ *
+ * draws this object
+ *
+ * @param inRenderer a renderer object
+ */
+void CColorControl::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+ //
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ // bottom
+ inRenderer->MoveTo(CPt(1, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y - 1));
+ // left
+ inRenderer->MoveTo(CPt(0, 1));
+ inRenderer->LineTo(CPt(0, theRect.size.y - 1));
+ // right
+ inRenderer->MoveTo(CPt(theRect.size.x - 1, 1));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y - 1));
+ //
+ inRenderer->PopPen();
+
+ CPt thePos(0, 0);
+ if (m_HasMasterAction) {
+ if (m_ActionImages[IMAGETYPE_MASTERACTION].isNull())
+ m_ActionImages[IMAGETYPE_MASTERACTION] =
+ CResourceCache::GetInstance()->GetBitmap("Action-MasterAction.png");
+
+ inRenderer->DrawBitmap(thePos, m_ActionImages[IMAGETYPE_MASTERACTION]);
+ } else if (m_HasAction) {
+ if (m_ActionImages[IMAGETYPE_ACTION].isNull())
+ m_ActionImages[IMAGETYPE_ACTION] =
+ CResourceCache::GetInstance()->GetBitmap("Action-Action.png");
+
+ inRenderer->DrawBitmap(thePos, m_ActionImages[IMAGETYPE_ACTION]);
+ }
+ if (m_ChildHasMasterAction) {
+ if (m_ActionImages[IMAGETYPE_CHILDMASTERACTION].isNull())
+ m_ActionImages[IMAGETYPE_CHILDMASTERACTION] =
+ CResourceCache::GetInstance()->GetBitmap("Action-ChildMasterAction.png");
+
+ inRenderer->DrawBitmap(thePos, m_ActionImages[IMAGETYPE_CHILDMASTERACTION]);
+ } else if (m_ChildHasAction) {
+ if (m_ActionImages[IMAGETYPE_CHILDACTION].isNull())
+ m_ActionImages[IMAGETYPE_CHILDACTION] =
+ CResourceCache::GetInstance()->GetBitmap("Action-ChildAction.png");
+
+ inRenderer->DrawBitmap(thePos, m_ActionImages[IMAGETYPE_CHILDACTION]);
+ }
+ if (m_ComponentHasMasterAction) {
+ if (m_ActionImages[IMAGETYPE_COMPONENTMASTERACTION].isNull())
+ m_ActionImages[IMAGETYPE_COMPONENTMASTERACTION] =
+ CResourceCache::GetInstance()->GetBitmap("Action-ComponentMasterAction.png");
+
+ inRenderer->DrawBitmap(thePos, m_ActionImages[IMAGETYPE_COMPONENTMASTERACTION]);
+ } else if (m_ComponentHasAction) {
+ if (m_ActionImages[IMAGETYPE_COMPONENTACTION].isNull())
+ m_ActionImages[IMAGETYPE_COMPONENTACTION] =
+ CResourceCache::GetInstance()->GetBitmap("Action-ComponentAction.png");
+
+ inRenderer->DrawBitmap(thePos, m_ActionImages[IMAGETYPE_COMPONENTACTION]);
+ }
+
+ // the old code with selection
+
+ // inRenderer->DrawGradientBitmap( theRect, m_ParentRow->GetAsset( )->GetTimebarColor( ), false
+ // );
+ // if ( m_Selected )
+ //{
+ // long theXSize = theRect.size.x / 2;
+ // long theYSize = theRect.size.y / 2;
+ // inRenderer->FillSolidRect( CRct( CPt( theXSize / 2, theYSize / 2 ), CPt( theXSize, theYSize)
+ //), CalculateSelectedColor( m_ParentRow->GetAsset( )->GetTimebarColor( ) ) );
+ //}
+
+ // if this is selected then do something special
+ // if ( m_Shaded )
+ //{
+ // // This is used for the left line of the color control
+ // CColor theNonGradiantHighlight = m_ParentRow->GetAsset( )->GetTimebarColor( );
+ // float theLuminance = theNonGradiantHighlight.GetLuminance( );
+ // theLuminance = theLuminance * (float)1.15;
+ // if ( theLuminance > 1.0 )
+ // {
+ // theLuminance = (float)1.0;
+ // }
+ //
+ // // Highlight on left edge
+ // theNonGradiantHighlight.SetLuminance( theLuminance );
+ // inRenderer->PushPen( theNonGradiantHighlight );
+ // inRenderer->MoveTo( CPt( 1, 0 ) );
+ // inRenderer->LineTo( CPt( 1, theRect.size.y - 1 ) );
+ // inRenderer->PopPen( );
+
+ // // Dark line on far left edge
+ // inRenderer->PushPen( CStudioPreferences::GetRowTopColor( ) );
+ // inRenderer->MoveTo( CPt( 0, 0 ) );
+ // inRenderer->LineTo( CPt( 0, theRect.size.y - 1 ) );
+ // inRenderer->PopPen( );
+ //
+ // inRenderer->PushPen( CStudioPreferences::GetRowTopColor( ) );
+ // inRenderer->MoveTo( CPt( 0,theRect.size.y - 1 ) );
+ // inRenderer->LineTo( CPt( theRect.size.x, theRect.size.y - 1 ) );
+ // inRenderer->MoveTo( CPt( theRect.size.x - 1, 0 ) );
+ // inRenderer->LineTo( CPt( theRect.size.x - 1, theRect.size.y - 1 ) );
+ // inRenderer->PopPen( );
+ //}
+
+ // inRenderer->Draw3dRect( CRct( theRect.position, CPt( theRect.size.x, theRect.size.y + 1 ) ),
+ // CColor( 0, 255, 0 ), CColor( 0, 255, 0 ) );
+}
+
+//==============================================================================
+/**
+ * CalculateNonGradiantHighlight
+ *
+ * calculates the highlight for this color
+ *
+ * @param inColor color to multiply
+ */
+CColor CColorControl::CalculateNonGradiantHighlight(CColor inColor)
+{
+ double theNonGradiantHighlightR = inColor.GetRed() * 1.15;
+ double theNonGradiantHighlightG = inColor.GetGreen() * 1.15;
+ double theNonGradiantHighlightB = inColor.GetBlue() * 1.15;
+ if (theNonGradiantHighlightR > 255) {
+ theNonGradiantHighlightR = 255;
+ }
+ if (theNonGradiantHighlightG > 255) {
+ theNonGradiantHighlightG = 255;
+ }
+ if (theNonGradiantHighlightB > 255) {
+ theNonGradiantHighlightB = 255;
+ }
+ return CColor(::dtol(theNonGradiantHighlightR), ::dtol(theNonGradiantHighlightG),
+ ::dtol(theNonGradiantHighlightB));
+}
+
+//==============================================================================
+/**
+ * CalculateNonGradiantHighlight
+ *
+ * calculates the highlight for this color
+ *
+ * @param inColor color to multiply
+ */
+CColor CColorControl::CalculateSelectedColor(CColor inColor)
+{
+ double theNonGradiantHighlightR = inColor.GetRed() * 0.65;
+ double theNonGradiantHighlightG = inColor.GetGreen() * 0.65;
+ double theNonGradiantHighlightB = inColor.GetBlue() * 0.65;
+ if (theNonGradiantHighlightR > 255) {
+ theNonGradiantHighlightR = 255;
+ }
+ if (theNonGradiantHighlightG > 255) {
+ theNonGradiantHighlightG = 255;
+ }
+ if (theNonGradiantHighlightB > 255) {
+ theNonGradiantHighlightB = 255;
+ }
+ return CColor(::dtol(theNonGradiantHighlightR), ::dtol(theNonGradiantHighlightG),
+ ::dtol(theNonGradiantHighlightB));
+}
+
+//==============================================================================
+/**
+ * Handles the OnMouseDownEvent
+ */
+bool CColorControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+ return true;
+}
+
+//==============================================================================
+/**
+ * Called when this row becomes selected
+ */
+void CColorControl::OnSelect()
+{
+ m_Selected = true;
+ this->Invalidate();
+}
+
+//==============================================================================
+/**
+ * Called when this row becomes deselected
+ */
+void CColorControl::OnDeselect()
+{
+ m_Selected = false;
+ this->Invalidate();
+}
+
+//==============================================================================
+/**
+ * Updates the icon used for display based on the following logic:
+ * 1. Self has actions
+ * 2. Descendents have actions
+ * Results in 4 states.
+ */
+void CColorControl::UpdateIconStatus()
+{
+ ITimelineItem *theTimelineItem = m_ParentRow->GetTimelineItem();
+
+ if (!theTimelineItem)
+ return;
+
+ // Master 'supersede' non-master
+ m_HasMasterAction = theTimelineItem->HasAction(true);
+ if (!m_HasMasterAction)
+ m_HasAction = theTimelineItem->HasAction(false);
+
+ // no descendent info if current row is expanded
+ if (!m_ParentRow->IsExpanded()) {
+ m_ChildHasMasterAction = theTimelineItem->ChildrenHasAction(true);
+ if (!m_ChildHasMasterAction)
+ m_ChildHasAction = theTimelineItem->ChildrenHasAction(false);
+ } else {
+ m_ChildHasMasterAction = false;
+ m_ChildHasAction = false;
+ }
+
+ m_ComponentHasMasterAction = theTimelineItem->ComponentHasAction(true);
+ if (!m_ComponentHasMasterAction)
+ m_ComponentHasAction = theTimelineItem->ComponentHasAction(false);
+
+ this->Invalidate();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ColorControl.h b/src/Authoring/Studio/Palettes/Timeline/ColorControl.h
new file mode 100644
index 00000000..ec5b156d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ColorControl.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_COLOR_CONTROL_H
+#define INCLUDED_COLOR_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+#include "CmdStack.h"
+
+#include <QPixmap>
+
+class CBaseStateRow;
+
+//==============================================================================
+/**
+ * The control at the left side of the TimeContextRow.
+ * It is currently being used to indicate if the Asset or its descendents have any Action.
+ */
+class CColorControl : public CControl
+{
+protected:
+ enum EImageType {
+ IMAGETYPE_ACTION = 0, ///< Types of action image
+ IMAGETYPE_MASTERACTION,
+ IMAGETYPE_CHILDACTION,
+ IMAGETYPE_CHILDMASTERACTION,
+ IMAGETYPE_COMPONENTACTION,
+ IMAGETYPE_COMPONENTMASTERACTION,
+ IMAGETYPE_MAXCOUNT
+ };
+
+public:
+ CColorControl(CBaseStateRow *inRow);
+ virtual ~CColorControl();
+
+ void SetColor(::CColor inColor);
+
+ void SetShaded(bool inIsShaded);
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void Draw(CRenderer *inRenderer) override;
+ ::CColor CalculateNonGradiantHighlight(::CColor inColor);
+
+ void OnSelect();
+ void OnDeselect();
+
+ static ::CColor CalculateSelectedColor(::CColor inCOLOR);
+
+ void UpdateIconStatus();
+
+protected:
+ ::CColor m_BackgroundColor;
+ bool m_Shaded;
+ bool m_Selected;
+ CBaseStateRow *m_ParentRow;
+
+ ///////////////////////////////////////////////////
+ // Action icons
+ // Action status
+ bool m_HasAction;
+ bool m_HasMasterAction;
+ bool m_ChildHasAction;
+ bool m_ChildHasMasterAction;
+ bool m_ComponentHasAction;
+ bool m_ComponentHasMasterAction;
+ // Action images
+ QPixmap m_ActionImages[IMAGETYPE_MAXCOUNT];
+};
+#endif // INCLUDED_COLOR_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/CommentEdit.cpp b/src/Authoring/Studio/Palettes/Timeline/CommentEdit.cpp
new file mode 100644
index 00000000..d0d5325f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/CommentEdit.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CommentEdit.h"
+#include "Renderer.h"
+#include "ColorControl.h"
+#include "Bindings/ITimelineTimebar.h"
+#include "CoreUtils.h"
+//=============================================================================
+/**
+ * Constructor
+ */
+CCommentEdit::CCommentEdit(ITimelineTimebar *inTimelineItemTimebar)
+ : m_TimelineItemTimebar(inTimelineItemTimebar)
+ , m_IsSelected(false)
+{
+ AddCommitListener(this);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CCommentEdit::~CCommentEdit()
+{
+ RemoveCommitListener(this);
+}
+
+//=============================================================================
+/**
+ * Called when a property changes.
+ * @param inProperty the property that was changed
+ * @param inIsVisibleChange true if this is a change that effects the property's visibility in the
+ * Timeline
+ */
+void CCommentEdit::OnSetData(CControl *inControl)
+{
+ if (inControl == this && m_TimelineItemTimebar) {
+ m_TimelineItemTimebar->SetTimebarComment(GetString());
+ }
+}
+
+//=============================================================================
+/**
+ * Called when this control receives a double click, edit the comment.
+ *
+ * @param inPoint the point where the double click occured
+ * @param inFlags the flags at the time of the click
+ */
+bool CCommentEdit::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+
+ if (GetDisplayString().Length() > 0) {
+ DoChangeComment();
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Edit the Comment
+ *
+ */
+void CCommentEdit::DoChangeComment()
+{
+ SetEditMode(true);
+ SelectAllText();
+}
+
+//=============================================================================
+/**
+ * Called when this control receives a mouse down, don't do anything unless we're in edit mode
+ *
+ * @param inPoint the point where the click occured
+ * @param inFlags the flags at the time of the click
+ */
+bool CCommentEdit::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+ if (GetEditMode()) {
+ theRetVal = CTextEditInPlace::OnMouseDown(inPoint, inFlags);
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Called when this control loses focus
+ */
+void CCommentEdit::OnLoseFocus()
+{
+ CStringEdit::OnLoseFocus();
+ SetEditMode(false);
+}
+
+//=============================================================================
+/**
+ * Called when this control gains focus, don't do anytihng
+ */
+void CCommentEdit::OnGainFocus()
+{
+}
+
+//=============================================================================
+/**
+ * Override for the draw, don't set the size of this control here since we are in
+ * a comment and wouldn't want the size changing
+ */
+void CCommentEdit::Draw(CRenderer *inRenderer)
+{
+ CPt theRectPoint = CPt(::dtol(CalculateCharWidths(inRenderer) + GetRightBuffer()), GetSize().y);
+ CPt theSize = GetSize();
+ if (theSize.x < theRectPoint.x)
+ theRectPoint.x = theSize.x;
+ CRct theRect = CRct(theRectPoint);
+ ::CColor theOutlineColor = ::CColor(0, 0, 0);
+ bool theFillFlag = m_FillBackground;
+
+ if (theFillFlag && !GetEditMode())
+ SetFillBackground(false);
+
+ if (GetEditMode())
+ SetTextColor(::CColor(0, 0, 0));
+
+ inRenderer->PushClippingRect(theRect);
+ CStringEdit::Draw(inRenderer);
+ inRenderer->PopClippingRect();
+
+ if (!GetEditMode())
+ SetFillBackground(theFillFlag);
+
+ if (GetEditMode())
+ inRenderer->DrawRectOutline(theRect, theOutlineColor, theOutlineColor, theOutlineColor,
+ theOutlineColor);
+}
+
+//=============================================================================
+/**
+ * Called when the timebar comment or the time bar color changes on an asset
+ */
+void CCommentEdit::RefreshMetaData()
+{
+ m_Color = ::CColor(m_TimelineItemTimebar->GetTimebarColor());
+ CalculateTextColor();
+ SetData(m_TimelineItemTimebar->GetTimebarComment());
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Calculates the text color based on whether the object is selected or not
+ */
+void CCommentEdit::CalculateTextColor()
+{
+ ::CColor theColor = m_Color;
+ float theLuminance = theColor.GetLuminance();
+ if (m_IsSelected) {
+ theLuminance = theLuminance * 0.8f;
+ }
+ // Duplicated Code to check luminance when the timebar changes color
+
+ if (theLuminance < 0.5) {
+ SetTextColor(::CColor(255, 255, 255));
+ } else {
+ SetTextColor(::CColor(0, 0, 0));
+ }
+}
+
+//=============================================================================
+/**
+ * Sets this object as selected
+ * @param inPoint the point to check
+ */
+void CCommentEdit::SetSelected(bool inState)
+{
+ m_IsSelected = inState;
+ CalculateTextColor();
+}
+
+//=============================================================================
+/**
+ * Overrides the hit test for the case when the click occurs in the object, but outside the text
+ * @param inPoint the point to check
+ */
+bool CCommentEdit::HitTest(const CPt &inPoint) const
+{
+ // rp this seems wrong but apparently it magically works
+ bool theRetVal = false;
+ if (inPoint.x
+ < m_TotalCharWidth + GetRightBuffer() + 2 * CStudioPreferences::GetTimebarTipSize())
+ theRetVal = CTextEditInPlace::HitTest(inPoint);
+ return theRetVal;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/CommentEdit.h b/src/Authoring/Studio/Palettes/Timeline/CommentEdit.h
new file mode 100644
index 00000000..8ae37ad9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/CommentEdit.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_COMMENT_EDIT
+#define INCLUDED_COMMENT_EDIT 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TextEditInPlace.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class ITimelineTimebar;
+
+//=============================================================================
+/**
+ * @class CCommentEdit this class handles changing the comments for a timebar in
+ * the timeline. This class seems necessary only to change the color of the text
+ * depending on the timebar color
+ */
+class CCommentEdit : public CTextEditInPlace, public CCommitDataListener
+{
+public:
+ CCommentEdit(ITimelineTimebar *inTimelineItemTimebar);
+ virtual ~CCommentEdit();
+ void OnSetData(CControl *inControl) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void Draw(CRenderer *inRenderer) override;
+ void RefreshMetaData();
+ void CalculateTextColor();
+ bool HitTest(const CPt &inPoint) const override;
+ void SetSelected(bool inState);
+
+ void OnLoseFocus() override;
+ void OnGainFocus() override;
+
+ void DoChangeComment();
+
+protected:
+ ITimelineTimebar *m_TimelineItemTimebar;
+ ::CColor m_Color;
+ bool m_IsSelected;
+};
+
+#endif // INCLUDED_COMMENT_EDIT
diff --git a/src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.cpp b/src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.cpp
new file mode 100644
index 00000000..8909ab7e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.cpp
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ComponentContextMenu.h"
+#include "TimelineControl.h"
+#include "StudioUtils.h"
+#include "StudioClipboard.h"
+#include "Dialogs.h"
+#include "BaseTimelineTreeControl.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "RelativePathTools.h"
+
+CComponentContextMenu::CComponentContextMenu(CBaseTimelineTreeControl *inTreeControl,
+ ITimelineItemBinding *inTimelineItemBinding,
+ QWidget *parent)
+ : QMenu(parent)
+ , m_TreeControl(inTreeControl)
+ , m_TimelineItemBinding(inTimelineItemBinding)
+{
+ Initialize();
+}
+
+void CComponentContextMenu::Initialize()
+{
+ m_renameAction = new QAction(tr("Rename Object"), this);
+ connect(m_renameAction, &QAction::triggered, this, &CComponentContextMenu::RenameObject);
+ addAction(m_renameAction);
+
+ m_duplicateAction = new QAction(tr("Duplicate Object"), this);
+ connect(m_duplicateAction, &QAction::triggered, this, &CComponentContextMenu::DuplicateObject);
+ addAction(m_duplicateAction);
+
+ m_deleteAction = new QAction(tr("Delete Object"), this);
+ connect(m_deleteAction, &QAction::triggered, this, &CComponentContextMenu::DeleteObject);
+ addAction(m_deleteAction);
+
+ addSeparator();
+
+ m_copyAction = new QAction(tr("Copy"), this);
+ connect(m_copyAction, &QAction::triggered, this, &CComponentContextMenu::CopyObject);
+ addAction(m_copyAction);
+
+ m_pasteAction = new QAction(tr("Paste"), this);
+ connect(m_pasteAction, &QAction::triggered, this, &CComponentContextMenu::PasteObject);
+ addAction(m_pasteAction);
+
+ m_cutAction = new QAction(tr("Cut"), this);
+ connect(m_cutAction, &QAction::triggered, this, &CComponentContextMenu::CutObject);
+ addAction(m_cutAction);
+ addSeparator();
+
+ m_makeAction = new QAction(tr("Make Component"), this);
+ connect(m_makeAction, &QAction::triggered, this, &CComponentContextMenu::MakeComponent);
+ addAction(m_makeAction);
+
+ if (CanInspectComponent()) {
+ m_inspectAction = new QAction(tr("Edit Component"), this);
+ connect(m_inspectAction, &QAction::triggered, this, &CComponentContextMenu::InspectComponent);
+ addAction(m_inspectAction);
+ }
+
+ if (m_TimelineItemBinding->IsExternalizeable()) {
+ addSeparator();
+ m_externalizeAction = new QAction(tr("Externalize Buffer"), this);
+ connect(m_externalizeAction, &QAction::triggered, this, &CComponentContextMenu::Externalize);
+ addAction(m_externalizeAction);
+ } else if (m_TimelineItemBinding->IsInternalizeable()) {
+ addSeparator();
+ m_internalizeAction = new QAction(tr("Internalize Buffer"), this);
+ connect(m_internalizeAction, &QAction::triggered, this, &CComponentContextMenu::Internalize);
+ addAction(m_internalizeAction);
+ }
+
+ addSeparator();
+
+ m_copyPathAction = new QAction(tr("Copy Object Path"), this);
+ connect(m_copyPathAction, &QAction::triggered, this, &CComponentContextMenu::CopyObjectPath);
+ addAction(m_copyPathAction);
+}
+
+void CComponentContextMenu::showEvent(QShowEvent *event)
+{
+ m_renameAction->setEnabled(CanRenameObject());
+ m_duplicateAction->setEnabled(CanDuplicateObject());
+ m_deleteAction->setEnabled(CanDeleteObject());
+
+ m_cutAction->setEnabled(CanCutObject());
+ m_copyAction->setEnabled(CanCopyObject());
+ m_pasteAction->setEnabled(CanPasteObject());
+
+ m_makeAction->setEnabled(CanMakeComponent());
+
+ QMenu::showEvent(event);
+}
+
+
+CComponentContextMenu::~CComponentContextMenu()
+{
+ // This will result in a double deletion.
+ // DeletePerformers( );
+}
+
+//=============================================================================
+/**
+ * Checks to see if the object can be renamed.
+ * @return true if the object can be renamed.
+ */
+bool CComponentContextMenu::CanRenameObject()
+{
+ return m_TimelineItemBinding->IsValidTransaction(ITimelineItemBinding::EUserTransaction_Rename);
+}
+
+//=============================================================================
+/**
+ * Rename the object.
+ */
+void CComponentContextMenu::RenameObject()
+{
+ m_TreeControl->DoRename();
+}
+
+//=============================================================================
+/**
+ * Checks to see if the object can be duplicated.
+ * @return true if the object can be duplicated.
+ */
+bool CComponentContextMenu::CanDuplicateObject()
+{
+ return m_TimelineItemBinding->IsValidTransaction(
+ ITimelineItemBinding::EUserTransaction_Duplicate);
+}
+
+//=============================================================================
+/**
+ * Duplicate the object.
+ */
+void CComponentContextMenu::DuplicateObject()
+{
+ m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Duplicate);
+}
+
+//=============================================================================
+/**
+ * Checks to see if the object can be deleted.
+ * @return true if the object can be deleted.
+ */
+bool CComponentContextMenu::CanDeleteObject()
+{
+ return m_TimelineItemBinding->IsValidTransaction(ITimelineItemBinding::EUserTransaction_Delete);
+}
+
+//=============================================================================
+/**
+ * Deletes the object from the scene graph.
+ */
+void CComponentContextMenu::DeleteObject()
+{
+ m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Delete);
+}
+
+//=============================================================================
+/**
+ * Checks to see if the State is a component and can be inspected.
+ * @return true is the state is a component and can be inspected.
+ */
+bool CComponentContextMenu::CanInspectComponent()
+{
+ return m_TimelineItemBinding->IsValidTransaction(
+ ITimelineItemBinding::EUserTransaction_EditComponent);
+}
+
+//=============================================================================
+/**
+ * Inspect the State (Component).
+ * This will make the component the top level item of the timelineview.
+ */
+void CComponentContextMenu::InspectComponent()
+{
+ m_TimelineItemBinding->OpenAssociatedEditor();
+}
+
+//=============================================================================
+/**
+ * Checks to see if the object can be wrapped in a component.
+ * @return true if the object is allowed to be wrapped in a component.
+ */
+bool CComponentContextMenu::CanMakeComponent()
+{
+ return m_TimelineItemBinding->IsValidTransaction(
+ ITimelineItemBinding::EUserTransaction_MakeComponent);
+}
+
+//=============================================================================
+/**
+ * Wraps the specified asset hierarchy under a component.
+ */
+void CComponentContextMenu::MakeComponent()
+{
+ m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_MakeComponent);
+}
+
+//=============================================================================
+/**
+ * Get the full Scripting path of the object and copy it to the clipboard.
+ * This will figure out the proper way to address the object via scripting
+ * and put that path into the clipboard.
+ */
+void CComponentContextMenu::CopyObjectPath()
+{
+ CStudioClipboard::CopyTextToClipboard(m_TimelineItemBinding->GetObjectPath().toQString());
+}
+
+//=============================================================================
+/**
+ * Checks to see if the object can be copied
+ * @return true if the object can be copied
+ */
+bool CComponentContextMenu::CanCopyObject()
+{
+ return m_TimelineItemBinding->IsValidTransaction(ITimelineItemBinding::EUserTransaction_Copy);
+}
+
+//=============================================================================
+/**
+ * Copy the object.
+ */
+void CComponentContextMenu::CopyObject()
+{
+ m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Copy);
+}
+
+bool CComponentContextMenu::CanCutObject()
+{
+ return m_TimelineItemBinding->IsValidTransaction(ITimelineItemBinding::EUserTransaction_Cut);
+}
+
+void CComponentContextMenu::CutObject()
+{
+ m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Cut);
+}
+
+//=============================================================================
+/**
+ * Checks to see if the object can be pasted
+ * @return true if the object can be pasted
+ */
+bool CComponentContextMenu::CanPasteObject()
+{
+ return m_TimelineItemBinding->IsValidTransaction(ITimelineItemBinding::EUserTransaction_Paste);
+}
+
+//=============================================================================
+/**
+ * Paste the object.
+ */
+void CComponentContextMenu::PasteObject()
+{
+ m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Paste);
+}
+
+ITimelineItem *CComponentContextMenu::GetTimelineItem() const
+{
+ return m_TimelineItemBinding->GetTimelineItem();
+}
+
+void CComponentContextMenu::Externalize()
+{
+ m_TimelineItemBinding->Externalize();
+}
+
+void CComponentContextMenu::Internalize()
+{
+ m_TimelineItemBinding->Internalize();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.h b/src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.h
new file mode 100644
index 00000000..cf1573e6
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ComponentContextMenu.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_COMPONENT_CONTEXT_MENU_H
+#define INCLUDED_COMPONENT_CONTEXT_MENU_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <QMenu>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CBaseTimelineTreeControl;
+class ITimelineItem;
+class ITimelineItemBinding;
+
+class CComponentContextMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ CComponentContextMenu(CBaseTimelineTreeControl *inTreeControl,
+ ITimelineItemBinding *inTimelineItemBinding,
+ QWidget *parent = nullptr);
+ virtual ~CComponentContextMenu();
+
+protected Q_SLOTS:
+ void RenameObject();
+ void DuplicateObject();
+ void DeleteObject();
+ void InspectComponent();
+ void MakeComponent();
+ void CopyObjectPath();
+ void CopyObject();
+ void PasteObject();
+ void CutObject();
+ void Externalize();
+ void Internalize();
+
+protected:
+ void showEvent(QShowEvent *event) override;
+
+ bool CanRenameObject();
+ bool CanDuplicateObject();
+ bool CanDeleteObject();
+ bool CanInspectComponent();
+ bool CanMakeComponent();
+ bool CanCopyObject();
+ bool CanPasteObject();
+ bool CanCutObject();
+ void Import();
+ void RefreshImport();
+ bool CanImport();
+ bool CanRefreshImport();
+ bool CanExportComponent();
+
+ void Initialize();
+
+ ITimelineItem *GetTimelineItem() const;
+
+ CBaseTimelineTreeControl *m_TreeControl;
+ ITimelineItemBinding *m_TimelineItemBinding;
+ QAction *m_renameAction;
+ QAction *m_duplicateAction;
+ QAction *m_deleteAction;
+ QAction *m_inspectAction;
+ QAction *m_makeAction;
+ QAction *m_copyPathAction;
+ QAction *m_cutAction;
+ QAction *m_copyAction;
+ QAction *m_pasteAction;
+ QAction *m_externalizeAction;
+ QAction *m_internalizeAction;
+};
+#endif // INCLDUED_STATE_CONTEXT_MENU_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/FilterToolbar.cpp b/src/Authoring/Studio/Palettes/Timeline/FilterToolbar.cpp
new file mode 100644
index 00000000..ce2b296c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/FilterToolbar.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FilterToolbar.h"
+#include "ButtonControl.h"
+#include "SystemPreferences.h"
+#include "Renderer.h"
+#include "TimelineTreeLayout.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CFilterToolbar::CFilterToolbar(CTimelineTreeLayout *inTreeLayout)
+ : CFlowLayout(nullptr, false)
+{
+ m_TreeLayout = inTreeLayout;
+
+ SetFlowDirection(FLOW_HORIZONTAL);
+ SetAlignment(ALIGN_TOP, ALIGN_LEFT);
+ SetLeftMargin(1);
+
+ // Create the buttons
+ m_FltrBehaviorsBtn = new CProceduralButton<CToggleButton>();
+ m_FltrPropertiesBtn = new CProceduralButton<CToggleButton>();
+ m_FltrMaterialsBtn = new CProceduralButton<CToggleButton>();
+ m_FltrShyBtn = new CProceduralButton<CToggleButton>();
+ m_FltrVisibleBtn = new CProceduralButton<CToggleButton>();
+
+ // Load the bitmaps
+ m_FltrBehaviorsBtn->SetUpImage("obsolete_placeholder.png");
+ m_FltrBehaviorsBtn->SetDownImage("obsolete_placeholder.png");
+
+ m_FltrPropertiesBtn->SetUpImage("obsolete_placeholder.png");
+ m_FltrPropertiesBtn->SetDownImage("obsolete_placeholder.png");
+
+ m_FltrMaterialsBtn->SetUpImage("obsolete_placeholder.png");
+ m_FltrMaterialsBtn->SetDownImage("obsolete_placeholder.png");
+
+ m_FltrShyBtn->SetUpImage("Toggle-Shy.png");
+ m_FltrShyBtn->SetDownImage("Toggle-Shy.png");
+
+ m_FltrVisibleBtn->SetUpImage("Toggle-HideShow.png");
+ m_FltrVisibleBtn->SetDownImage("Toggle-HideShow.png");
+
+ // Turn off the left border of each button since they are all next to each other, otherwise,
+ // you'll get a double line effect
+ CProceduralButton<CToggleButton>::SBorderOptions theBorderOptions(false, true, true, true);
+ m_FltrBehaviorsBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrPropertiesBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrMaterialsBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrShyBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrVisibleBtn->SetBorderVisibilityAll(theBorderOptions);
+ CProceduralButton<CButtonControl>::SBorderOptions theBorderOptions2(false, true, true, true);
+
+ // Set the max sizes for the buttons
+ m_FltrBehaviorsBtn->SetAbsoluteSize(m_FltrBehaviorsBtn->GetSize());
+ m_FltrPropertiesBtn->SetAbsoluteSize(m_FltrPropertiesBtn->GetSize());
+ m_FltrMaterialsBtn->SetAbsoluteSize(m_FltrMaterialsBtn->GetSize());
+ m_FltrShyBtn->SetAbsoluteSize(m_FltrShyBtn->GetSize());
+ m_FltrVisibleBtn->SetAbsoluteSize(m_FltrShyBtn->GetSize());
+
+ // Tooltips
+ m_FltrBehaviorsBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_BEHAVIOR2));
+ m_FltrPropertiesBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_PROPERTIES2));
+ m_FltrMaterialsBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_MATERIALS2));
+ m_FltrShyBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_SHY2));
+ m_FltrVisibleBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_VISIBLE2));
+
+ // Callback for one of the Filter buttons being clicked on
+ m_FltrBehaviorsBtn->SigToggle.connect(std::bind(&CFilterToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_FltrPropertiesBtn->SigToggle.connect(std::bind(&CFilterToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_FltrMaterialsBtn->SigToggle.connect(std::bind(&CFilterToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_FltrShyBtn->SigToggle.connect(std::bind(&CFilterToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_FltrVisibleBtn->SigToggle.connect(std::bind(&CFilterToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ // Add the buttons to this layout
+ AddChild(m_FltrMaterialsBtn);
+ AddChild(m_FltrPropertiesBtn);
+ AddChild(m_FltrBehaviorsBtn);
+ AddChild(m_FltrShyBtn);
+ AddChild(m_FltrVisibleBtn);
+
+ m_FltrBehaviorsBtn->SetToggleState(false);
+ m_FltrPropertiesBtn->SetToggleState(false);
+ m_FltrMaterialsBtn->SetToggleState(false);
+ m_FltrShyBtn->SetToggleState(false);
+ m_FltrVisibleBtn->SetToggleState(false);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CFilterToolbar::~CFilterToolbar()
+{
+ delete m_FltrBehaviorsBtn;
+ delete m_FltrPropertiesBtn;
+ delete m_FltrMaterialsBtn;
+ delete m_FltrShyBtn;
+ delete m_FltrVisibleBtn;
+}
+
+//=============================================================================
+/**
+ * Overriden to draw some highlighting.
+ */
+void CFilterToolbar::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+ // Draw the highlight at the bottom
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+ inRenderer->PopPen();
+
+ // Draw the line on the left side
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ inRenderer->MoveTo(0, 0);
+ inRenderer->LineTo(0, theRect.size.y - 1);
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for behavior objects in the timeline.
+ * @param inFilter true to filter behaviors out of the timeline, false to show
+ * behaviors in the timeline.
+ */
+void CFilterToolbar::FilterBehaviors(bool inFilter)
+{
+ if (inFilter)
+ m_FltrBehaviorsBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_BEHAVIOR1));
+ else
+ m_FltrBehaviorsBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_BEHAVIOR2));
+
+ m_TreeLayout->GetFilter()->SetBehaviors(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for properties on objects in the timeline.
+ * @param inFilter true to filter properties out of the timeline, false to show
+ * properties in the timeline.
+ */
+void CFilterToolbar::FilterProperties(bool inFilter)
+{
+ if (inFilter)
+ m_FltrPropertiesBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_PROPERTIES1));
+ else
+ m_FltrPropertiesBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_PROPERTIES2));
+
+ m_TreeLayout->GetFilter()->SetProperties(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for material objects.
+ * @param inFilter true to filter material objects out of the timeline, false to show
+ * material objects in the timeline.
+ */
+void CFilterToolbar::FilterMaterials(bool inFilter)
+{
+ if (inFilter)
+ m_FltrMaterialsBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_MATERIALS1));
+ else
+ m_FltrMaterialsBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_MATERIALS2));
+
+ m_TreeLayout->GetFilter()->SetMaterials(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for shy objects.
+ * @param inFilter true to filter shy objects out of the timeline, false to show
+ * shy objects in the timeline.
+ */
+void CFilterToolbar::FilterShy(bool inFilter)
+{
+ if (inFilter)
+ m_FltrShyBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_SHY1));
+ else
+ m_FltrShyBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_SHY2));
+
+ m_TreeLayout->GetFilter()->SetShy(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for visible objects.
+ * @param inFilter true to filter visible objects out of the timeline, false to show
+ * shy objects in the timeline.
+ */
+void CFilterToolbar::FilterVisible(bool inFilter)
+{
+ if (inFilter)
+ m_FltrVisibleBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_VISIBLE1));
+ else
+ m_FltrVisibleBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_VISIBLE2));
+
+ m_TreeLayout->GetFilter()->SetVisible(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Handles turning a filter on or off in response to a button being pressed.
+ * @param inButton button that generated the event
+ * @param inState new state of the button after being toggled
+ */
+void CFilterToolbar::OnButtonToggled(CToggleButton *inButton, CButtonControl::EButtonState inState)
+{
+ bool theFilterNeedsApplied = (inState == CButtonControl::EBUTTONSTATE_UP);
+
+ if (inButton == m_FltrBehaviorsBtn)
+ FilterBehaviors(theFilterNeedsApplied);
+ else if (inButton == m_FltrPropertiesBtn)
+ FilterProperties(theFilterNeedsApplied);
+ else if (inButton == m_FltrMaterialsBtn)
+ FilterMaterials(theFilterNeedsApplied);
+ else if (inButton == m_FltrShyBtn)
+ FilterShy(theFilterNeedsApplied);
+ else if (inButton == m_FltrVisibleBtn)
+ FilterVisible(theFilterNeedsApplied);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/FilterToolbar.h b/src/Authoring/Studio/Palettes/Timeline/FilterToolbar.h
new file mode 100644
index 00000000..8148fff3
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/FilterToolbar.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_FILTER_TOOLBAR_H
+#define INCLUDED_FILTER_TOOLBAR_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "FlowLayout.h"
+#include "ProceduralButton.h"
+#include "ToggleButton.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CButtonControl;
+class CRenderer;
+class CTimelineTreeLayout;
+
+//=============================================================================
+/**
+ * Control at the top of the timeline containing filter buttons.
+ */
+class CFilterToolbar : public CFlowLayout
+{
+public:
+ CFilterToolbar(CTimelineTreeLayout *inTreeLayout);
+ virtual ~CFilterToolbar();
+ void Draw(CRenderer *inRenderer) override;
+
+ void FilterBehaviors(bool inFilter);
+ void FilterProperties(bool inFilter);
+ void FilterMaterials(bool inFilter);
+ void FilterShy(bool inFilter);
+ void FilterVisible(bool inFilter);
+
+ void OnButtonToggled(CToggleButton *inButton, CToggleButton::EButtonState inState);
+
+protected:
+ CProceduralButton<CToggleButton> *m_FltrBehaviorsBtn;
+ CProceduralButton<CToggleButton> *m_FltrPropertiesBtn;
+ CProceduralButton<CToggleButton> *m_FltrMaterialsBtn;
+ CProceduralButton<CToggleButton> *m_FltrShyBtn;
+ CProceduralButton<CToggleButton> *m_FltrVisibleBtn;
+ CTimelineTreeLayout *m_TreeLayout;
+};
+
+#endif // INCLUDED_FILTER_TOOLBAR_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/IBreadCrumbProvider.h b/src/Authoring/Studio/Palettes/Timeline/IBreadCrumbProvider.h
new file mode 100644
index 00000000..18aa31ac
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/IBreadCrumbProvider.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_IBREADCRUMBPROVIDER_H
+#define INCLUDED_IBREADCRUMBPROVIDER_H 1
+
+#pragma once
+
+#include <QColor>
+#include <QString>
+
+#include <boost/signals.hpp>
+
+class QPixmap;
+
+struct SBreadCrumb
+{
+ QColor m_Color; /// Color for text of the bread crumb
+ QString m_String; /// Text to be displayed for the bread crumb
+};
+
+//=============================================================================
+/**
+ * A interface class for the breadcrumb control, to walk down the breadcrumb trail, without having
+ * to know any underlying implementations.
+ */
+class IBreadCrumbProvider
+{
+public:
+ typedef std::vector<SBreadCrumb> TTrailList;
+
+public:
+ virtual ~IBreadCrumbProvider() {}
+
+ virtual TTrailList GetTrail(bool inRefresh = true) = 0;
+ virtual void OnBreadCrumbClicked(long inTrailIndex) = 0;
+
+ virtual QPixmap GetRootImage() const = 0;
+ virtual QPixmap GetBreadCrumbImage() const = 0;
+ virtual QPixmap GetSeparatorImage() const = 0;
+ virtual QPixmap GetActiveBreadCrumbImage() const = 0;
+
+ boost::signal0<void> SigBreadCrumbUpdate;
+};
+
+#endif // INCLUDED_IBREADCRUMBPROVIDER_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ITimelineControl.h b/src/Authoring/Studio/Palettes/Timeline/ITimelineControl.h
new file mode 100644
index 00000000..05af776e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ITimelineControl.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_ITIMELINE_CONTROL_H
+#define INCLUDED_ITIMELINE_CONTROL_H 1
+
+#pragma once
+
+#include "Rct.h"
+
+class ISnappingListProvider;
+
+class ITimelineControl
+{
+public:
+ virtual ~ITimelineControl() {}
+
+ virtual void OnLayoutChanged() = 0;
+ virtual CRct GetBounds() const = 0;
+ virtual void HideTimelineMoveableTooltip() = 0;
+ virtual ISnappingListProvider *GetSnappingListProvider() const = 0;
+};
+
+#endif // INCLUDED_TIMELINE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.cpp b/src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.cpp
new file mode 100644
index 00000000..78a2e4cb
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "KeyframeContextMenu.h"
+#include "IDoc.h"
+#include "CColor.h"
+#include "Preferences.h"
+#include "Dialogs.h"
+#include "TimebarControl.h"
+#include "Bindings/ITimelineTimebar.h"
+#include "Bindings/ITimelineKeyframesManager.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "IKeyframe.h"
+
+#include <QColorDialog>
+
+#define IDC_KEYFRAME_COLOR_BOX 1002
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CBaseKeyframeContextMenu::CBaseKeyframeContextMenu(QWidget *parent)
+ : QMenu(parent)
+ , m_HasDynamicSelectedKeyframes(false)
+ , m_KeyframesManager(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CBaseKeyframeContextMenu::~CBaseKeyframeContextMenu()
+{
+}
+
+void CBaseKeyframeContextMenu::Initialize(ITimelineKeyframesManager *inKeyframesManager)
+{
+ m_KeyframesManager = inKeyframesManager;
+ ASSERT(m_KeyframesManager);
+
+ //"Insert Keyframe"
+ ITimelineItemKeyframesHolder *theKeyframesHolder = GetKeyframesHolder();
+ if (theKeyframesHolder) {
+ m_insertAction = new QAction(tr("Insert Keyframe"));
+ connect(m_insertAction, &QAction::triggered, this, &CBaseKeyframeContextMenu::InsertKeyframe);
+ addAction(m_insertAction);
+ }
+
+ bool theHasKeysSelected = m_KeyframesManager->HasSelectedKeyframes();
+ bool theCanCopyKeys = m_KeyframesManager->CanPerformKeyframeCopy();
+ bool theCanPasteKeys = m_KeyframesManager->CanPerformKeyframePaste();
+
+ m_cutAction = new QAction(tr("Cut Selected Keyframes"));
+ connect(m_cutAction, &QAction::triggered, this, &CBaseKeyframeContextMenu::CutSelectedKeys);
+ m_cutAction->setEnabled(theCanCopyKeys);
+ addAction(m_cutAction);
+
+ m_copyAction = new QAction(tr("Copy Selected Keyframes"));
+ connect(m_copyAction, &QAction::triggered, this, &CBaseKeyframeContextMenu::CopySelectedKeys);
+ m_copyAction->setEnabled(theCanCopyKeys);
+ addAction(m_copyAction);
+
+ m_pasteAction = new QAction(tr("Paste Keyframes"));
+ connect(m_pasteAction, &QAction::triggered, this, &CBaseKeyframeContextMenu::PasteSelectedKeys);
+ m_pasteAction->setEnabled(theCanPasteKeys);
+ addAction(m_pasteAction);
+
+ m_deleteSelectedAction = new QAction(tr("Delete Selected Keyframes"));
+ connect(m_deleteSelectedAction, &QAction::triggered, this, &CBaseKeyframeContextMenu::DeleteSelectedKeys);
+ m_deleteSelectedAction->setEnabled(theHasKeysSelected);
+ addAction(m_deleteSelectedAction);
+
+ //"Delete All Channel Keyframes"
+ if (theKeyframesHolder) {
+ m_deleteChannelKeysAction = new QAction(tr("Delete All Channel Keyframes"));
+ connect(m_deleteChannelKeysAction, &QAction::triggered, this, &CBaseKeyframeContextMenu::DeleteChannelKeys);
+ addAction(m_deleteChannelKeysAction);
+ }
+}
+
+//=============================================================================
+/**
+ * Called when the cut selected keys option is chosen by the user. Makes a call
+ * to the doc to handle the request
+ */
+void CBaseKeyframeContextMenu::InsertKeyframe()
+{
+ GetKeyframesHolder()->InsertKeyframe();
+}
+
+//=============================================================================
+/**
+ * Called when the cut selected keys option is chosen by the user. Makes a call
+ * to the doc to handle the request
+ */
+void CBaseKeyframeContextMenu::DeleteChannelKeys()
+{
+ GetKeyframesHolder()->DeleteAllChannelKeyframes();
+}
+
+//=============================================================================
+/**
+ * Called when the cut selected keys option is chosen by the user. Makes a call
+ * to the doc to handle the request
+ */
+void CBaseKeyframeContextMenu::CutSelectedKeys()
+{
+ m_KeyframesManager->RemoveKeyframes(true);
+}
+
+//=============================================================================
+/**
+ * Called when the copy selected keys option is chosen by the user. Makes a call
+ * to the doc to handle the request
+ */
+void CBaseKeyframeContextMenu::CopySelectedKeys()
+{
+ m_KeyframesManager->CopyKeyframes();
+}
+
+//=============================================================================
+/**
+ * Called when the paste selected keys option is chosen by the user. Makes a call
+ * to the doc to handle the request
+ */
+void CBaseKeyframeContextMenu::PasteSelectedKeys()
+{
+ m_KeyframesManager->PasteKeyframes();
+}
+
+//=============================================================================
+/**
+ * Called when the delete selected keys option is chosen by the user. Makes a call
+ * to the doc to handle the request
+ */
+void CBaseKeyframeContextMenu::DeleteSelectedKeys()
+{
+ m_KeyframesManager->RemoveKeyframes(false);
+}
+
+//=============================================================================
+/**
+ * Toggle if the selected keyframe(s) is dynamic
+ */
+void CBaseKeyframeContextMenu::MakeDynamic()
+{
+ m_KeyframesManager->SetKeyframesDynamic(!m_HasDynamicSelectedKeyframes); // toggle
+}
+
+//==============================================================================
+// CTimebarKeyframeContextMenu
+//==============================================================================
+CTimebarKeyframeContextMenu::CTimebarKeyframeContextMenu(ITimebarControl *inTimebarControl, ITimelineKeyframesManager *inKeyframesManager,
+ bool inShowTimebarPropertiesOptions /*= true */, QWidget *parent)
+ : CBaseKeyframeContextMenu(parent)
+ , m_TimebarControl(inTimebarControl)
+ , m_ShowTimebarPropertiesOptions(inShowTimebarPropertiesOptions)
+{
+ Initialize(inKeyframesManager);
+}
+
+CTimebarKeyframeContextMenu::~CTimebarKeyframeContextMenu()
+{
+}
+
+void CTimebarKeyframeContextMenu::Initialize(ITimelineKeyframesManager *inKeyframesManager)
+{
+ CBaseKeyframeContextMenu::Initialize(inKeyframesManager);
+
+ // Dynamic keyframes ( the way it was set up before was, this option is still shown, but grayed
+ // out even if this context menu isn't triggered from right-clicking on a timebar )
+ QString theMakeDynamicOption = tr("Make Animations Static");
+
+ if (m_TimebarControl->GetKeyframesHolder()->GetKeyframeCount() > 0) {
+ m_HasDynamicSelectedKeyframes = m_KeyframesManager->HasDynamicKeyframes();
+
+ if (!m_HasDynamicSelectedKeyframes) {
+ theMakeDynamicOption = tr("Make Animations Dynamic");
+ }
+
+ m_makeDynamicAction = new QAction(theMakeDynamicOption);
+ connect(m_makeDynamicAction, &QAction::triggered, this, &CTimebarKeyframeContextMenu::MakeDynamic);
+ addAction(m_makeDynamicAction);
+ }
+
+ if (m_ShowTimebarPropertiesOptions) {
+ // Timebar specific actions
+ addSeparator();
+ m_timeBarColorAction = new QAction(tr("Change Time Bar Color"));
+ connect(m_timeBarColorAction, &QAction::triggered, this, &CTimebarKeyframeContextMenu::ChangeTimebarColor);
+
+ m_timeBarTextAction = new QAction(tr("Change Time Bar Text"));
+ connect(m_timeBarTextAction, &QAction::triggered, this, &CTimebarKeyframeContextMenu::ChangeTimebarText);
+
+ // Change the text for the timebar option depending on whether they are currently being
+ // shown or not
+ QString theTimebarHandleTextID = tr("Show Time Bar Handles");
+ if (CPreferences::GetUserPreferences("Timeline").GetValue("ShowTimebarHandles", false))
+ theTimebarHandleTextID = tr("Hide Time Bar Handles");
+
+ m_timeBarHandlesAction = new QAction(theTimebarHandleTextID);
+ connect(m_timeBarHandlesAction, &QAction::triggered, this, &CTimebarKeyframeContextMenu::ToggleTimebarHandles);
+
+ m_timeBarTimeAction = new QAction(tr("Set Timebar Time"));
+ connect(m_timeBarTimeAction, &QAction::triggered, this, &CTimebarKeyframeContextMenu::SetTimebarTime);
+ }
+}
+
+void CTimebarKeyframeContextMenu::MakeDynamic()
+{
+ m_KeyframesManager->SelectAllKeyframes();
+ CBaseKeyframeContextMenu::MakeDynamic();
+}
+
+//=============================================================================
+/**
+ * To show "Insert Keyframe" and "Delete All Channel Keyframes"
+ */
+ITimelineItemKeyframesHolder *CTimebarKeyframeContextMenu::GetKeyframesHolder()
+{
+ return m_TimebarControl->GetKeyframesHolder();
+}
+
+//=============================================================================
+/**
+ * Called when the copy selected keys option is chosen by the user.
+ */
+void CTimebarKeyframeContextMenu::ChangeTimebarColor()
+{
+ const auto color = QColorDialog::getColor(m_TimebarControl->GetTimebarColor());
+ if (color.isValid())
+ m_TimebarControl->SetTimebarColor(color);
+}
+
+//=============================================================================
+/**
+ * Called when the copy selected keys option is chosen by the user.
+ */
+void CTimebarKeyframeContextMenu::ChangeTimebarText()
+{
+ m_TimebarControl->OnEditTimeComment();
+}
+
+//=============================================================================
+/**
+ * Shows or hides timebar handles in the timeline. If timebar handles are
+ * currently being shown, they are hidden, and the preference is stored. If
+ * timebar handles are being hidden, they are shown.
+ */
+void CTimebarKeyframeContextMenu::ToggleTimebarHandles()
+{
+ // Get the current timebar handle preference
+ bool theHandlesAreShowing =
+ CPreferences::GetUserPreferences("Timeline").GetValue("ShowTimebarHandles", false);
+ // Switch the preference.
+ CPreferences::GetUserPreferences("Timeline")
+ .SetValue("ShowTimebarHandles", !theHandlesAreShowing);
+ if (m_TimebarControl)
+ m_TimebarControl->OnToggleTimebarHandles();
+}
+
+//=============================================================================
+/**
+ * SetTimebarTime: This is the event handler that will be called when the user
+ * chooses set timebar time from a pop up menu. This pop up
+ *menu
+ * is triggered when the user right click on the selected
+ *timebar.
+ * It displays a time edit dialog to allow the user to set the
+ * start and end time of the timebar time.
+ * @param NONE
+ * @return NONE
+ */
+void CTimebarKeyframeContextMenu::SetTimebarTime()
+{
+ m_TimebarControl->SetTimebarTime();
+}
+
+//==============================================================================
+// CKeyframeContextMenu
+//==============================================================================
+CKeyframeContextMenu::CKeyframeContextMenu(ITimelineKeyframesManager *inKeyframesManager,
+ ITimelineItemProperty *inTimelineItemProperty, QWidget *parent)
+ : CBaseKeyframeContextMenu(parent)
+ , m_TimelineItemProperty(inTimelineItemProperty)
+{
+ Initialize(inKeyframesManager);
+}
+
+CKeyframeContextMenu::~CKeyframeContextMenu()
+{
+}
+
+void CKeyframeContextMenu::Initialize(ITimelineKeyframesManager *inKeyframesManager)
+{
+ CBaseKeyframeContextMenu::Initialize(inKeyframesManager);
+
+ // Dynamic keyframes ( the way it was set up before was, this option is still shown, but grayed
+ // out even if this context menu isn't triggered from right-clicking on a timebar )
+ QString theMakeDynamicOption = tr("Make Animations Static");
+ m_HasDynamicSelectedKeyframes =
+ m_TimelineItemProperty && m_TimelineItemProperty->IsDynamicAnimation();
+
+ if (!m_HasDynamicSelectedKeyframes) {
+ theMakeDynamicOption = tr("Make Animations Dynamic");
+ }
+
+ m_makeDynamicAction = new QAction(theMakeDynamicOption);
+ connect(m_makeDynamicAction, &QAction::triggered, this, &CKeyframeContextMenu::MakeDynamic);
+ addAction(m_makeDynamicAction);
+
+ addSeparator();
+ bool theHasKeysSelected = m_KeyframesManager->HasSelectedKeyframes();
+ m_setInterpolationAction = new QAction(tr("Set Interpolation"));
+ connect(m_setInterpolationAction, &QAction::triggered, this, &CKeyframeContextMenu::SetInterpolation);
+ addAction(m_setInterpolationAction);
+
+ m_setKeyframeTimeAction = new QAction(tr("Set Keyframe Time"));
+ connect(m_setKeyframeTimeAction, &QAction::triggered, this, &CKeyframeContextMenu::SetKeyframeTime);
+ m_setKeyframeTimeAction->setEnabled(theHasKeysSelected);
+ addAction(m_setKeyframeTimeAction);
+}
+
+void CKeyframeContextMenu::MakeDynamic()
+{
+ if (m_TimelineItemProperty != nullptr && m_TimelineItemProperty->GetKeyframeCount() > 0) {
+ m_TimelineItemProperty->SelectKeyframes(
+ true, m_TimelineItemProperty->GetKeyframeByIndex(0)->GetTime());
+ }
+
+ CBaseKeyframeContextMenu::MakeDynamic();
+}
+
+//=============================================================================
+/**
+ * SetTime: Saves the keyframe time
+ * @param inTime is the keyframe time
+ */
+void CKeyframeContextMenu::SetTime(long inTime)
+{
+ m_Time = inTime;
+}
+
+//=============================================================================
+/**
+ * Called when the set interpolation option is taken by the user. Uses the left most
+ * selected key for the base interpolation in the dialog box. User can then set the interpolation
+ * and it is propagated to all teh keys
+ */
+void CKeyframeContextMenu::SetInterpolation()
+{
+ m_KeyframesManager->SetKeyframeInterpolation();
+}
+
+//=============================================================================
+/**
+ * SetKeyframeTime: This is the event handler that will be called when the user
+ * chooses set keyframe time from a pop up menu. This pop up
+ *menu
+ * is triggered when the user right click on the selected
+ *keyframe.
+ * It displays a time edit dialog to allow the user to set the
+ * keyframe time.
+ * @param NONE
+ * @return NONE
+ */
+void CKeyframeContextMenu::SetKeyframeTime()
+{
+ m_KeyframesManager->SetKeyframeTime(m_Time);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.h b/src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.h
new file mode 100644
index 00000000..b11ccb2f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/KeyframeContextMenu.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_KEYFRAME_CONTEXT_MENU
+#define INCLUDED_KEYFRAME_CONTEXT_MENU 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <QMenu>
+
+class ITimelineKeyframesManager;
+class ITimelineItemProperty;
+class ITimelineTimebar;
+class ITimeChangeCallback;
+class ITimelineItemKeyframesHolder;
+class ITimebarControl;
+
+class QAction;
+
+//=============================================================================
+/**
+ * Abstract class that contain the common items for the keyframes-related context menu.
+ */
+class CBaseKeyframeContextMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ CBaseKeyframeContextMenu(QWidget *parent = nullptr);
+ virtual ~CBaseKeyframeContextMenu();
+
+protected:
+ virtual void Initialize(ITimelineKeyframesManager *inKeyframesManager);
+ virtual void MakeDynamic();
+ virtual ITimelineItemKeyframesHolder *GetKeyframesHolder() { return nullptr; }
+
+protected Q_SLOTS:
+ void CutSelectedKeys();
+ void CopySelectedKeys();
+ void PasteSelectedKeys();
+ void DeleteSelectedKeys();
+ void InsertKeyframe();
+ void DeleteChannelKeys();
+
+protected:
+ bool m_HasDynamicSelectedKeyframes;
+ ITimelineKeyframesManager *m_KeyframesManager;
+ QAction *m_insertAction;
+ QAction *m_cutAction;
+ QAction *m_copyAction;
+ QAction *m_pasteAction;
+ QAction *m_deleteSelectedAction;
+ QAction *m_deleteChannelKeysAction;
+};
+
+//=============================================================================
+/**
+ * Context menu right-clicking on a timebar,
+ */
+class CTimebarKeyframeContextMenu : public CBaseKeyframeContextMenu
+{
+ Q_OBJECT
+public:
+ CTimebarKeyframeContextMenu(ITimebarControl *inTimebarControl,
+ ITimelineKeyframesManager *inKeyframesManager,
+ bool inShowTimebarPropertiesOptions = true,
+ QWidget *parent = nullptr);
+ ~CTimebarKeyframeContextMenu();
+
+protected:
+ void Initialize(ITimelineKeyframesManager *inKeyframesManager) override;
+ ITimelineItemKeyframesHolder *GetKeyframesHolder() override;
+ void MakeDynamic() override;
+
+ void ChangeTimebarColor();
+ void ChangeTimebarText();
+ void ToggleTimebarHandles();
+ void SetTimebarTime();
+
+protected:
+ ITimebarControl *m_TimebarControl;
+ bool m_ShowTimebarPropertiesOptions;
+
+ QAction *m_makeDynamicAction;
+ QAction *m_timeBarColorAction;
+ QAction *m_timeBarTextAction;
+ QAction *m_timeBarHandlesAction;
+ QAction *m_timeBarTimeAction;
+};
+
+//=============================================================================
+/**
+ * Context menu for right-clicking on selected keyframe(s)
+ * so even though the assoicated action isn't limited to the keyframe that was right-clicked on,
+ * this is still a different one from right-clicking on outside the keyframe.
+ * This is how the old system used to be.
+ */
+class CKeyframeContextMenu : public CBaseKeyframeContextMenu
+{
+ Q_OBJECT
+public:
+ CKeyframeContextMenu(ITimelineKeyframesManager *inKeyframesManager,
+ ITimelineItemProperty *inTimelineItemProperty = nullptr,
+ QWidget *parent = nullptr);
+ ~CKeyframeContextMenu();
+
+ void SetTime(long inTime);
+
+protected:
+ void Initialize(ITimelineKeyframesManager *inKeyframesManager) override;
+ void MakeDynamic() override;
+
+protected Q_SLOTS:
+ void SetInterpolation();
+ void SetKeyframeTime();
+
+protected:
+ long m_Time;
+
+private:
+ ITimelineItemProperty *m_TimelineItemProperty;
+ QAction *m_makeDynamicAction;
+ QAction *m_setKeyframeTimeAction;
+ QAction *m_setInterpolationAction;
+};
+#endif // INCLUDED_KEYFRAME_CONTEXT_MENU
diff --git a/src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.cpp b/src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.cpp
new file mode 100644
index 00000000..676a5d2d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "MultiSelectAspect.h"
diff --git a/src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.h b/src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.h
new file mode 100644
index 00000000..0c19b2b2
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/MultiSelectAspect.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MULTISELECT_ASPECT_H
+#define INCLUDED_MULTISELECT_ASPECT_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StateRow.h"
+#include "TimelineTimelineLayout.h"
+#include "Bindings/IKeyframeSelector.h"
+
+//==============================================================================
+/**
+ * This class handles the multi selection aspect for keyframes in the timeline.
+ * It toggles each keyframe's select state on or off, depending on whether the
+ * mouse rectangle is over them and if the modifier key is down.
+ */
+template <typename TSTLKeyFrameList>
+class CMultiSelectAspect
+{
+
+public:
+ typedef typename TSTLKeyFrameList::iterator TSTLKeyframesItr;
+
+protected:
+ TSTLKeyFrameList &m_STLKeyframes; ///< stores list of keyframes in a vector (STL)
+ IKeyframeSelector *m_KeyframeSelector; ///< the interface that performs the keyframes selection
+
+public:
+ //=============================================================================
+ /**
+ * Constructor
+ * @param inSTLKeyframes stores a list of keyframes in a vector
+ * @param inDoc stores the studio document
+ */
+ CMultiSelectAspect(TSTLKeyFrameList &inSTLKeyframes, IKeyframeSelector *inKeyframeSelector)
+ : m_STLKeyframes(inSTLKeyframes)
+ , m_KeyframeSelector(inKeyframeSelector)
+ {
+ }
+
+ //=============================================================================
+ /**
+ * Destructor
+ */
+ ~CMultiSelectAspect() {}
+
+ //=============================================================================
+ /**
+ * CommitSelections: Overwrites all previous keyframe states with the current keyframe states.
+ * This will prevent the keyframes in the current selection
+*from
+* switching states as we select other keyframes.
+ */
+ void CommitSelections()
+ {
+ // Iterates each keyframe and set the previous state to the current one.
+ TSTLKeyframesItr thePos = m_STLKeyframes.begin();
+ for (; thePos != m_STLKeyframes.end(); ++thePos) {
+ (*thePos)->SetPreviousSelectState((*thePos)->IsSelected());
+ }
+ }
+
+ //=============================================================================
+ /**
+ * MultiSelect: Handles the selection of keyframes in a given rect.
+ * @param inRect stores the rectangle that will be used to select the keyframes within it.
+ * @param inModifierKeyDown indicates if thte modifier key is pressed.
+ */
+ void MultiSelect(CRct inRect, bool inModifierKeyDown)
+ {
+ // Iterates through the keyframes and checks if the keys are in the rect and
+ // perform the necessary selection operations on each keyframe.
+ TSTLKeyframesItr thePos = m_STLKeyframes.begin();
+ for (; thePos != m_STLKeyframes.end(); ++thePos) {
+ bool isInRect = (*thePos)->IsInRect(inRect);
+ if ((*thePos)->IsEnabled()) {
+ if (inModifierKeyDown) {
+ if (isInRect) {
+ if (!(*thePos)->GetRectOverHandled()) {
+ bool theSelectState = (*thePos)->IsSelected();
+
+ // Update the previous select state
+ (*thePos)->SetPreviousSelectState(theSelectState);
+ // Negate the keyframe state when it is in the rectangle
+ theSelectState = !theSelectState;
+ (*thePos)->Select(theSelectState);
+ m_KeyframeSelector->SelectKeyframes(theSelectState,
+ (*thePos)->GetTime());
+
+ // Set the RectOverFlag to true, so that we will not repeat the negation
+ // in indefinitely.
+ (*thePos)->SetRectOverHandled(true);
+ }
+ } else {
+ // When the rectangle is not over the current keyframe, revert its state to
+ // the previous one
+ if ((*thePos)->IsSelected() != (*thePos)->GetPreviousSelectState()) {
+ (*thePos)->Select((*thePos)->GetPreviousSelectState());
+ m_KeyframeSelector->SelectKeyframes((*thePos)->GetPreviousSelectState(),
+ (*thePos)->GetTime());
+ }
+ (*thePos)->SetRectOverHandled(false);
+ }
+ } else {
+ // When modifier is not pressed we will just select the keyframes if it is over
+ // in the rectangle and deselect it when it isn't.
+ if ((*thePos)->IsSelected() != isInRect) {
+ (*thePos)->SetPreviousSelectState((*thePos)->IsSelected());
+ m_KeyframeSelector->SelectKeyframes(isInRect, (*thePos)->GetTime());
+ (*thePos)->Select(isInRect);
+ }
+ (*thePos)->SetRectOverHandled(false);
+ }
+ }
+ }
+ }
+};
+#endif // INCLUDED_MULTISELECT_ASPECT_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Playhead.cpp b/src/Authoring/Studio/Palettes/Timeline/Playhead.cpp
new file mode 100644
index 00000000..c010a854
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Playhead.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "Playhead.h"
+#include "Renderer.h"
+#include "TimelineTimelineLayout.h"
+#include "IDoc.h"
+#include "HotKeys.h"
+#include "ResourceCache.h"
+#include "TimeEditDlg.h"
+#include "TimeMeasure.h"
+
+//=============================================================================
+/**
+ * Create a new Playhead.
+ * The timeline is used for notifying of time changes and for scrolling.
+ * @param inTimeline the timeline that this is a part of.
+ */
+CPlayhead::CPlayhead(CTimelineTimelineLayout *inTimeline, IDoc *inDoc)
+ : m_IsMouseDown(false)
+ , m_MinimumPosition(0)
+ , m_MaximumPosition(LONG_MAX)
+ , m_InitialOffset(0)
+ , m_Doc(inDoc)
+{
+ m_Timeline = inTimeline;
+
+ m_PlayheadImage = CResourceCache::GetInstance()->GetBitmap("PlaybackHead.png");
+ SetName("Playhead");
+
+ // Set the line to the middle of this.
+ m_LinePos = GetSize().x / 2;
+ SetAlpha(128);
+}
+
+CPlayhead::~CPlayhead()
+{
+}
+
+//=============================================================================
+/**
+ * Call from the OverlayControl to perform the draw.
+ * Wish this didn't have to be a special function but...
+ * @param inRenderer the renderer to draw to.
+ */
+void CPlayhead::Draw(CRenderer *inRenderer)
+{
+ // If this goes before position then clip it at 0.
+ if (GetPosition().x < 0) {
+ CRct theClipRect(GetSize());
+ theClipRect.Offset(CPt(-GetPosition().x, 0));
+ inRenderer->PushClippingRect(theClipRect);
+ }
+
+ // Draw the playhead
+ inRenderer->DrawBitmap(CPt(0, 2), m_PlayheadImage);
+
+ // Draw the line
+ inRenderer->PushPen(CColor(255, 0, 0));
+ inRenderer->MoveTo(m_LinePos, 20);
+ inRenderer->LineTo(m_LinePos, GetSize().y - 1);
+ inRenderer->PopPen();
+
+ // If we added an extra clipping rect then remove it.
+ if (GetPosition().x < 0) {
+ inRenderer->PopClippingRect();
+ }
+}
+
+//=============================================================================
+/**
+ * Handles mouse down messages.
+ * @param inPoint where the mouse was clicked.
+ * @param inFlags the state of the mouse.
+ */
+bool CPlayhead::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // If no one else processed it then process the command.
+ if (!COverlayControl::OnMouseDown(inPoint, inFlags)) {
+ m_Snapper.Clear();
+ m_Snapper.SetSource(this);
+ m_Timeline->PopulateSnappingList(&m_Snapper);
+
+ // m_Snapper.SetTimeOffset( m_Timeline->GetViewTimeOffset( ) );
+ m_Snapper.SetSnappingKeyframes(true);
+ m_Snapper.BeginDrag(inPoint.x, GetSize().x / 2);
+
+ m_InitialOffset = inPoint.x;
+ m_IsMouseDown = true;
+
+ m_Timeline->RecalcTime((inFlags & CHotKeys::MODIFIER_CONTROL) == 0, 0);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handles mouse double click messages. Pops up a time edit dialog box for
+ * modifying playhead time.
+ * @param inPoint the location of the mouse in local coordinates.
+ * @param inFlags the state of the mouse.
+ */
+bool CPlayhead::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.ShowDialog(GetCurrentTime(), 0, m_Doc, PLAYHEAD);
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handles mouse move messages.
+ * @param inPoint the location of the mouse in local coordinates.
+ * @param inFlags the state of the mouse.
+ */
+void CPlayhead::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ COverlayControl::OnMouseMove(inPoint, inFlags);
+
+ // If we are down then move the playhead
+ if (m_IsMouseDown) {
+ long theTime = m_Snapper.ProcessDrag(GetCurrentTime(), inPoint.x, inFlags);
+ bool theUpdateClientTimeFlag = (inFlags & CHotKeys::MODIFIER_CONTROL) == 0;
+
+ UpdateTime(theTime, theUpdateClientTimeFlag);
+ }
+}
+
+//=============================================================================
+/**
+ * Updates the time of the active context
+ * @param inTime the new time
+ * @param inUpdateClient true if scene is to be redrawn
+ */
+void CPlayhead::UpdateTime(long inTime, bool /*inUpdateClient*/)
+{
+ // true to "check bounds" to ensure playhead is within valid range.
+ m_Doc->NotifyTimeChanged(inTime);
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse was let go.
+ * @param inPoint the location of the mouse in local coordinates.
+ * @param inFlags the state of the mouse.
+ */
+void CPlayhead::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ COverlayControl::OnMouseUp(inPoint, inFlags);
+
+ m_IsMouseDown = false;
+}
+
+//=============================================================================
+/**
+ * Set the size of this control.
+ * @param inSize the size to be set.
+ */
+void CPlayhead::SetSize(CPt inSize)
+{
+ COverlayControl::SetSize(inSize);
+ // Update the line position.
+ m_LinePos = inSize.x / 2;
+}
+
+//=============================================================================
+/**
+ * Set the minimum and maximum allowed positions of the line.
+ * @param inMinimumPosition the minimum allowed position.
+ * @param inMaximumPosition the maximum allowed position.
+ */
+void CPlayhead::SetMinMaxPosition(long inMinimumPosition, long inMaximumPosition)
+{
+ m_MinimumPosition = inMinimumPosition;
+ m_MaximumPosition = inMaximumPosition;
+}
+
+long CPlayhead::GetCurrentTime()
+{
+ return m_Doc->GetCurrentViewTime();
+}
+
+//=============================================================================
+/**
+ * Check to see if inPoint is over this control or not.
+ * This overrides COverlayControl::HitTest so that the playhead line can be
+ * exempt from mouse hits.
+ * @param inPoint the location of the mouse in local coordinates.
+ */
+bool CPlayhead::HitTest(const CPt &inPoint) const
+{
+ if (inPoint.y < m_PlayheadImage.height()) {
+ return COverlayControl::HitTest(inPoint);
+ }
+ return false;
+}
+
+void CPlayhead::StepRightSmall()
+{
+ long theInterval = m_Timeline->GetTimeMeasure()->GetSmallHashInterval();
+
+ long theCurrentTime = GetCurrentTime();
+ long theTime = theCurrentTime / theInterval * theInterval + theInterval;
+ UpdateTime(theTime, true);
+}
+
+void CPlayhead::StepRightLarge()
+{
+ long theInterval = m_Timeline->GetTimeMeasure()->GetLargeHashInterval();
+
+ long theCurrentTime = GetCurrentTime();
+ long theTime = theCurrentTime / theInterval * theInterval + theInterval;
+ UpdateTime(theTime, true);
+}
+
+void CPlayhead::StepLeftSmall()
+{
+ long theInterval = m_Timeline->GetTimeMeasure()->GetSmallHashInterval();
+
+ long theCurrentTime = GetCurrentTime();
+ long theTime = theCurrentTime / theInterval * theInterval - theInterval;
+
+ UpdateTime(theTime, true);
+}
+
+void CPlayhead::StepLeftLarge()
+{
+ long theInterval = m_Timeline->GetTimeMeasure()->GetLargeHashInterval();
+
+ long theCurrentTime = GetCurrentTime();
+ long theTime = theCurrentTime / theInterval * theInterval - theInterval;
+
+ UpdateTime(theTime, true);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Playhead.h b/src/Authoring/Studio/Palettes/Timeline/Playhead.h
new file mode 100644
index 00000000..21d21041
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Playhead.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PLAYHEAD_H
+#define INCLUDED_PLAYHEAD_H 1
+
+#pragma once
+
+#include "OverlayControl.h"
+#include "Snapper.h"
+
+#include <QPixmap>
+
+class CTimelineTimelineLayout;
+class IDoc;
+
+class CPlayhead : public COverlayControl
+{
+public:
+ CPlayhead(CTimelineTimelineLayout *inTimeline, IDoc *inDoc);
+ virtual ~CPlayhead();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void SetSize(CPt inSize) override;
+ void Draw(CRenderer *inRenderer) override;
+ void SetMinMaxPosition(long inMinimumPosition, long inMaximumPosition);
+ long GetCurrentTime();
+ bool HitTest(const CPt &inPoint) const override;
+ void StepRightSmall();
+ void StepRightLarge();
+ void StepLeftSmall();
+ void StepLeftLarge();
+
+ long GetCenterOffset() const { return m_LinePos; }
+ bool IsMouseDown() const { return m_IsMouseDown; }
+
+ void UpdateTime(long inTime, bool inUpdateClient);
+
+protected:
+ QPixmap m_PlayheadImage;
+ bool m_IsMouseDown;
+ long m_InitialOffset;
+
+ long m_MinimumPosition;
+ long m_MaximumPosition;
+ long m_LinePos;
+
+ CTimelineTimelineLayout *m_Timeline;
+
+ CSnapper m_Snapper;
+ IDoc *m_Doc;
+};
+#endif // INCLUDED_PLAYHEAD_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.cpp
new file mode 100644
index 00000000..3cffd417
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "PropertyColorControl.h"
+#include "Renderer.h"
+#include "PropertyRow.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+
+CPropertyColorControl::CPropertyColorControl(CPropertyRow *inPropertyRow)
+{
+ m_ParentRow = inPropertyRow;
+}
+
+CPropertyColorControl::~CPropertyColorControl()
+{
+}
+
+//==============================================================================
+/**
+ * Draw
+ *
+ * draws this object
+ *
+ * @param inRenderer a renderer object
+ */
+void CPropertyColorControl::Draw(CRenderer *inRenderer)
+{
+ // Fill the control with the solid color
+ CRct theRect(GetSize());
+ CColor theBgColor(CStudioPreferences::GetPropertyBackgroundColor());
+ inRenderer->FillSolidRect(theRect, theBgColor);
+
+ // Define the colors for the side and bottom outline
+ CColor theBorderColor(CStudioPreferences::GetPropertyFloorColor());
+
+ // Right
+ inRenderer->PushPen(theBorderColor);
+ inRenderer->MoveTo(CPt(theRect.size.x - 1, 0));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y - 1));
+
+ // Left
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theRect.size.y - 1));
+
+ // Bottom
+ inRenderer->MoveTo(CPt(1, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x - 2, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+//==============================================================================
+/**
+ * Handles the OnMouseDownEvent
+ */
+bool CPropertyColorControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ m_ParentRow->Select((CHotKeys::MODIFIER_SHIFT & inFlags) == CHotKeys::MODIFIER_SHIFT);
+ return true;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.h b/src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.h
new file mode 100644
index 00000000..cc3263b8
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyColorControl.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTYCOLOR_CONTROL_H
+#define INCLUDED_PROPERTYCOLOR_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+
+class CRenderer;
+class CPropertyRow;
+
+class CPropertyColorControl : public CControl
+{
+public:
+ CPropertyColorControl(CPropertyRow *inPropertyRow);
+ virtual ~CPropertyColorControl();
+
+ void SetColor(::CColor inColor);
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void Draw(CRenderer *inRenderer) override;
+
+protected:
+ CPropertyRow *m_ParentRow;
+};
+#endif // INCLUDED_
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.cpp
new file mode 100644
index 00000000..fd7585ac
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "PropertyGraphKeyframe.h"
+#include "Renderer.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "StudioUtils.h"
+#include "CColor.h"
+
+CPropertyGraphKeyframe::CPropertyGraphKeyframe(ITimelineItemProperty *inProperty,
+ long inChannelIndex, long inKeyframeTime,
+ double inTimeRatio, long inMinY, long inMaxY,
+ float inMinVal, float inMaxVal)
+ : m_Property(inProperty)
+ , m_ChannelIndex(inChannelIndex)
+ , m_KeyframeTime(inKeyframeTime)
+ , m_TimeRatio(inTimeRatio)
+ , m_MinVal(inMinVal)
+ , m_MaxVal(inMaxVal)
+ , m_MinY(inMinY)
+ , m_MaxY(inMaxY)
+ , m_IsMouseDown(false)
+{
+ SetSize(CPt(4, 4));
+ PositionKeyframe();
+}
+
+CPropertyGraphKeyframe::~CPropertyGraphKeyframe()
+{
+}
+
+long CPropertyGraphKeyframe::GetTime()
+{
+ return m_KeyframeTime;
+}
+
+long CPropertyGraphKeyframe::GetChannelIndex() const
+{
+ return m_ChannelIndex;
+}
+
+void CPropertyGraphKeyframe::PositionKeyframe()
+{
+ long theXPos = ::TimeToPos(m_KeyframeTime, m_TimeRatio);
+ float theValue = GetKeyframeValue();
+ long theYPos = (long)((1.0 - (theValue - m_MinVal) / (m_MaxVal - m_MinVal)) * (m_MaxY - m_MinY)
+ + m_MinY - GetSize().y / 2 + .5);
+
+ if (theYPos < m_MinY)
+ theYPos = m_MinY;
+ else if (theYPos > m_MaxY)
+ theYPos = m_MaxY;
+
+ SetPosition(CPt(theXPos, theYPos));
+}
+
+void CPropertyGraphKeyframe::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+ PositionKeyframe();
+}
+
+float CPropertyGraphKeyframe::GetKeyframeValue()
+{
+ return m_Property->GetChannelValueAtTime(m_ChannelIndex, m_KeyframeTime);
+}
+
+void CPropertyGraphKeyframe::SetKeyframeValue(float inValue)
+{
+ m_Property->SetChannelValueAtTime(m_ChannelIndex, m_KeyframeTime, inValue);
+}
+
+void CPropertyGraphKeyframe::Draw(CRenderer *inRenderer)
+{
+ CPt mySize = GetSize();
+ inRenderer->MoveTo(0, 0);
+ inRenderer->LineTo(mySize.x, 0);
+ inRenderer->LineTo(mySize.x, mySize.y);
+ inRenderer->LineTo(0, mySize.y);
+ inRenderer->LineTo(0, 0);
+
+ if (m_IsMouseDown) {
+ inRenderer->FillSolidRect(CRct(GetSize()), CColor::black);
+ }
+}
+
+bool CPropertyGraphKeyframe::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_IsMouseDown = true;
+ m_MouseDownLoc = inPoint;
+ }
+ return true;
+}
+
+void CPropertyGraphKeyframe::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+ m_IsMouseDown = false;
+ m_Property->CommitChangedKeyframes();
+ GetParent()->Invalidate();
+}
+
+void CPropertyGraphKeyframe::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ if (m_IsMouseDown) {
+ long theDiff = inPoint.y - m_MouseDownLoc.y;
+ long theYPos = GetPosition().y + theDiff;
+ if (theYPos < m_MinY)
+ theYPos = m_MinY;
+ if (theYPos > m_MaxY)
+ theYPos = m_MaxY;
+ SetPosition(GetPosition().x, theYPos);
+
+ float theValue = (m_MaxVal - m_MinVal)
+ * (((m_MaxY + m_MinY) - theYPos - GetSize().y / 2) - m_MinY) / (m_MaxY - m_MinY)
+ + m_MinVal;
+ SetKeyframeValue(theValue);
+
+ GetParent()->Invalidate();
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.h b/src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.h
new file mode 100644
index 00000000..daffc8ab
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyGraphKeyframe.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_GRAPH_KEYFRAME_H
+#define INCLUDED_PROPERTY_GRAPH_KEYFRAME_H 1
+
+#pragma once
+
+#include "Control.h"
+
+class ITimelineItemProperty;
+
+class CPropertyGraphKeyframe : public CControl
+{
+public:
+ CPropertyGraphKeyframe(ITimelineItemProperty *inProperty, long inChannelIndex,
+ long inKeyframeTime, double inTimeRatio, long inHeight, long inOffset,
+ float inMinVal, float inMaxVal);
+ virtual ~CPropertyGraphKeyframe();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ long GetTime();
+ long GetChannelIndex() const;
+ void SetTimeRatio(double inTimeRatio);
+ void PositionKeyframe();
+
+protected:
+ float GetKeyframeValue();
+ void SetKeyframeValue(float inValue);
+
+ ITimelineItemProperty *m_Property;
+ long m_ChannelIndex; // index that identifies the channel for a animated property
+ long m_KeyframeTime;
+ double m_TimeRatio;
+ float m_MinVal;
+ float m_MaxVal;
+ long m_MinY;
+ long m_MaxY;
+ CPt m_MouseDownLoc;
+ bool m_IsMouseDown;
+};
+#endif // INCLUDED_PROPERTY_GRAPH_KEYFRAME_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyRow.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyRow.cpp
new file mode 100644
index 00000000..986d8326
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyRow.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PropertyRow.h"
+#include "TimelineControl.h"
+#include "PropertyColorControl.h"
+#include "PropertyToggleControl.h"
+#include "PropertyTreeControl.h"
+#include "PropertyTimebarRow.h"
+#include "BlankControl.h"
+#include "StudioPreferences.h"
+#include "StateRow.h"
+#include "Bindings/ITimelineItemProperty.h"
+
+//=============================================================================
+/**
+ * Create a property row for inProperty.
+ * @param inProperty the property that this is displaying.
+ */
+CPropertyRow::CPropertyRow(ITimelineItemProperty *inProperty)
+ : m_Highlighted(false)
+ , m_DetailedView(false)
+ , m_TimeRatio(0.0f)
+ , m_Property(inProperty)
+{
+ m_IsViewable = true;
+
+ m_TreeControl = new CPropertyTreeControl(this);
+ m_ToggleControl = new CPropertyToggleControl(this);
+ m_TimebarRow = new CPropertyTimebarRow(this);
+
+ m_PropertyColorControl = new CPropertyColorControl(this);
+ long theTimebarHeight = CStudioPreferences::GetRowSize();
+
+ // do not set absolute size because it messes up the timeline
+ m_TreeControl->SetSize(CPt(500, theTimebarHeight));
+ m_PropertyColorControl->SetAbsoluteSize(CPt(theTimebarHeight, theTimebarHeight));
+ m_ToggleControl->SetAbsoluteSize(CPt(57, theTimebarHeight));
+ m_TimebarRow->SetSize(CPt(0, theTimebarHeight));
+
+ // sk: setting controls names' seem to be only useful for debugging.
+ // Q3DStudio::CString thePropName( inProperty->GetName( ) );
+ // m_TreeControl->SetName( thePropName );
+ // m_TimebarRow->SetName( thePropName + "TimebarRow" );
+}
+
+CPropertyRow::~CPropertyRow()
+{
+ delete m_TreeControl;
+ delete m_ToggleControl;
+ delete m_PropertyColorControl;
+ delete m_TimebarRow;
+}
+
+//=============================================================================
+/**
+ * Get the left hand color control for this row.
+ * @return the color control for this row.
+ */
+CControl *CPropertyRow::GetColorControl()
+{
+ return m_PropertyColorControl;
+}
+
+//=============================================================================
+/**
+ * Get the tree control object for this row.
+ * @return the tree control object for this row.
+ */
+CControl *CPropertyRow::GetTreeControl()
+{
+ return m_TreeControl;
+}
+
+//=============================================================================
+/**
+ * Get the toggle control object for this row.
+ * @return the toggle control object for this row.
+ */
+CControl *CPropertyRow::GetToggleControl()
+{
+ return m_ToggleControl;
+}
+
+//=============================================================================
+/**
+ * Get the timebar control for this row.
+ * @return the timebar control for this row.
+ */
+CControl *CPropertyRow::GetTimebarControl()
+{
+ return m_TimebarRow;
+}
+
+//=============================================================================
+/**
+ * Set the amount that this row is indented.
+ * This handles the tree indenting.
+ * @param inIndent the amount of indent for this row.
+ */
+void CPropertyRow::SetIndent(long inIndent)
+{
+ m_TreeControl->SetIndent(inIndent);
+}
+
+//=============================================================================
+/**
+ * Notification from one of the child controls that the mouse just entered.
+ * This is used to handle the highlighting of the entire row.
+ */
+void CPropertyRow::OnMouseOver()
+{
+ // Only change if change is needed
+ if (!m_Highlighted) {
+ m_TreeControl->SetHighlighted(true);
+ m_ToggleControl->SetHighlighted(true);
+ m_TimebarRow->SetHighlighted(true);
+
+ m_Highlighted = true;
+ }
+}
+
+//=============================================================================
+/**
+ * Notification from one of the child controls that the mouse just left.
+ * This is used to handle the highlighting of the entire row.
+ */
+void CPropertyRow::OnMouseOut()
+{
+ // Only change is change is needed.
+ if (m_Highlighted) {
+ m_TreeControl->SetHighlighted(false);
+ m_ToggleControl->SetHighlighted(false);
+ m_TimebarRow->SetHighlighted(false);
+
+ m_Highlighted = false;
+ }
+}
+
+//=============================================================================
+/**
+ * Double click handler for the property row
+ */
+void CPropertyRow::OnMouseDoubleClick()
+{
+ SetDetailedView(!m_DetailedView);
+}
+
+//=============================================================================
+/**
+ * Expands the row out so a more detailed view of the animation tracks can be seen
+ *
+ * @param inIsInDetailedView true if we are switching to a detailed view
+ */
+void CPropertyRow::SetDetailedView(bool inIsDetailedView)
+{
+ m_DetailedView = inIsDetailedView;
+
+ if (m_DetailedView) {
+ long theHeight = 100;
+ m_PropertyColorControl->SetAbsoluteSize(
+ CPt(m_PropertyColorControl->GetSize().x, theHeight));
+ m_TreeControl->SetSize(CPt(m_TreeControl->GetSize().x, theHeight));
+ m_ToggleControl->SetAbsoluteSize(CPt(m_ToggleControl->GetSize().x, theHeight));
+ m_TimebarRow->SetAbsoluteSize(CPt(m_TimebarRow->GetSize().x, theHeight));
+
+ m_TimebarRow->SetDetailedView(true);
+ } else {
+ long theDefaultHeight = CStudioPreferences::GetRowSize();
+
+ m_PropertyColorControl->SetAbsoluteSize(
+ CPt(m_PropertyColorControl->GetSize().x, theDefaultHeight));
+ m_TreeControl->SetSize(CPt(m_TreeControl->GetSize().x, theDefaultHeight));
+ m_ToggleControl->SetAbsoluteSize(CPt(m_ToggleControl->GetSize().x, theDefaultHeight));
+ m_TimebarRow->SetAbsoluteSize(CPt(m_TimebarRow->GetSize().x, theDefaultHeight));
+
+ m_TimebarRow->SetDetailedView(false);
+ }
+
+ GetTopControl()->OnLayoutChanged();
+}
+
+//=============================================================================
+/**
+ * Filter this property.
+ * This controls whether or not this row should be displayed. The filter will
+ * be stored and used for future operations that may change whether or not
+ * this should be visible.
+ * @param inFilter the filter to filter on.
+ * @param inFilterChildren true if the call is recursive.
+ */
+void CPropertyRow::Filter(const CFilter &inFilter, bool inFilterChildren /*= true*/)
+{
+ Q_UNUSED(inFilterChildren);
+
+ m_Filter = inFilter;
+
+ bool theVisibleFlag = inFilter.Filter(m_Property);
+ m_TreeControl->SetVisible(theVisibleFlag);
+ m_TimebarRow->SetVisible(theVisibleFlag);
+ m_ToggleControl->SetVisible(theVisibleFlag);
+ m_PropertyColorControl->SetVisible(theVisibleFlag);
+ m_IsViewable = theVisibleFlag;
+}
+
+//=============================================================================
+/**
+ * @return true if this property is animated and is not currently being filtered out
+ */
+bool CPropertyRow::IsViewable() const
+{
+ return m_Filter.GetProperties();
+}
+
+//=============================================================================
+/**
+ * Call from one of the child controls to select this object.
+ * Currently this just causes the Asset to be selected.
+ */
+void CPropertyRow::Select(bool inIsShiftKeyPressed /*= false */)
+{
+ m_Property->SetSelected();
+
+ if (inIsShiftKeyPressed)
+ m_TimebarRow->SelectAllKeys();
+ else
+ m_Property->ClearKeySelection();
+}
+
+ISnappingListProvider *CPropertyRow::GetSnappingListProvider() const
+{
+ return &m_TimebarRow->GetSnappingListProvider();
+}
+
+void CPropertyRow::SetSnappingListProvider(ISnappingListProvider *inProvider)
+{
+ m_TimebarRow->SetSnappingListProvider(inProvider);
+}
+
+//=============================================================================
+/**
+ * Retrieves the background color for the row based upon the type of asset
+ * passed in. Overridden so that properties can have a different background
+ * color than their parent asset does.
+ * @return background color to use for this row
+ */
+::CColor CPropertyRow::GetTimebarBackgroundColor()
+{
+ return CStudioPreferences::GetPropertyBackgroundColor();
+}
+
+//=============================================================================
+/**
+ * Retrieves the background color for the row when the mouse is over the row
+ * based upon the type of asset passed in. Overridden so that properties can
+ * have a different highlight background color than their parent asset does.
+ * @return background color to use for this row when the mouse is over it
+ */
+::CColor CPropertyRow::GetTimebarHighlightBackgroundColor()
+{
+ return CStudioPreferences::GetPropertyMouseOverColor();
+}
+
+//=============================================================================
+/**
+ * Set the amount of time that is represented by a pixel.
+ * This modifies the length of this control.
+ * @param inTimePerPixel the time per pixel.
+ */
+void CPropertyRow::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+ m_TimebarRow->SetTimeRatio(inTimeRatio);
+}
+
+//=============================================================================
+/**
+ * Selects all keyframes of this property that are inside inRect
+ *
+ * @param inRect theRect to check
+ */
+void CPropertyRow::SelectKeysInRect(CRct inRect, bool inModifierKeyDown)
+{
+ CRct theOffsetRect = inRect;
+ CRct myRect(CPt(0, 0), m_TimebarRow->GetSize());
+ theOffsetRect.Offset(-m_TimebarRow->GetPosition());
+ m_TimebarRow->SelectKeysInRect(theOffsetRect, inModifierKeyDown);
+}
+
+//=============================================================================
+/**
+ * CommitSelections: commits all the property keyframe selections by setting their
+ * previous selection state to the current selection state.
+ * This will prevent the keyframes in the current selection
+ *from
+ * switching states as we select other keyframes.
+ *
+ * @param NONE
+ * @return NONE
+ */
+void CPropertyRow::CommitSelections()
+{
+ m_TimebarRow->CommitSelections();
+}
+
+//=============================================================================
+/**
+ * Selects all keyframes
+ */
+void CPropertyRow::SelectAllKeys()
+{
+ m_TimebarRow->SelectAllKeys();
+}
+
+//=============================================================================
+/**
+ * Deletes keyframes on this property row
+ */
+void CPropertyRow::DeleteAllKeys()
+{
+ m_Property->DeleteAllKeys();
+ m_TimebarRow->Invalidate();
+}
+
+//=============================================================================
+/**
+ * Sets all the child control enable states
+ * @param inEnabled the state to set the controls to
+ */
+void CPropertyRow::SetEnabled(bool inEnabled)
+{
+ m_TreeControl->SetEnabled(inEnabled);
+ m_ToggleControl->SetEnabled(inEnabled);
+ m_PropertyColorControl->SetEnabled(inEnabled);
+ m_TimebarRow->SetEnabled(inEnabled);
+}
+
+//=============================================================================
+/**
+ * Callback from the ITimelineProperty.
+ */
+void CPropertyRow::Refresh()
+{
+ if (m_TimebarRow->IsVisible())
+ m_TimebarRow->SetDirty(true);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyRow.h b/src/Authoring/Studio/Palettes/Timeline/PropertyRow.h
new file mode 100644
index 00000000..49ca60a7
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyRow.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_ROW_H
+#define INCLUDED_PROPERTY_ROW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TimelineRow.h"
+#include "StateRow.h"
+#include "Rct.h"
+#include <vector>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CPropertyColorControl;
+class CBlankControl;
+class CPropertyTreeControl;
+class CPropertyToggleControl;
+class CPropertyTimebarRow;
+class ITimelineItemProperty;
+
+class CPropertyRow : public CTimelineRow
+{
+public:
+ CPropertyRow(ITimelineItemProperty *inProperty);
+ virtual ~CPropertyRow();
+ CControl *GetColorControl() override;
+ CControl *GetTreeControl() override;
+ CControl *GetToggleControl() override;
+ CControl *GetTimebarControl() override;
+
+ void SetTimeRatio(double inTimePerPixel) override;
+ void SetIndent(long inIndent) override;
+ void Filter(const CFilter &inFilter, bool inFilterChildren = true) override;
+ void OnMouseOver();
+ void OnMouseOut();
+ void OnMouseDoubleClick();
+ void Select(bool inIsShiftKeyPressed = false);
+ void SetDetailedView(bool inIsInDetailedView);
+ void CommitSelections();
+ void SelectKeysInRect(CRct inRect, bool inModifierKeyDown);
+ void SelectAllKeys();
+ void DeleteAllKeys();
+ bool IsViewable() const override;
+ void SetEnabled(bool inEnabled);
+
+ ISnappingListProvider *GetSnappingListProvider() const override;
+ void SetSnappingListProvider(ISnappingListProvider *inProvider) override;
+ using CTimelineRow::GetTimebarBackgroundColor;
+ virtual ::CColor GetTimebarBackgroundColor();
+ using CTimelineRow::GetTimebarHighlightBackgroundColor;
+ virtual ::CColor GetTimebarHighlightBackgroundColor();
+
+ void Refresh();
+ ITimelineItemProperty *GetProperty() const { return m_Property; }
+
+ CPropertyTimebarRow *GetTimebar() { return m_TimebarRow; }
+
+protected:
+ CPropertyTreeControl *m_TreeControl;
+ CPropertyToggleControl *m_ToggleControl;
+ CPropertyColorControl *m_PropertyColorControl;
+ CPropertyTimebarRow *m_TimebarRow;
+ bool m_Highlighted;
+ bool m_DetailedView;
+ double m_TimeRatio;
+ CFilter m_Filter;
+ ITimelineItemProperty *m_Property;
+};
+#endif // INCLUDED_PROPERTY_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.cpp
new file mode 100644
index 00000000..ecd3b5df
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "PropertyTimebarGraph.h"
+#include "IKeyframe.h"
+#include "Renderer.h"
+#include "PropertyGraphKeyframe.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "StudioUtils.h"
+
+//=============================================================================
+/**
+ * Create a graph for the specified property.
+ * @param inProperty the property this is graphing.
+ */
+CPropertyTimebarGraph::CPropertyTimebarGraph(ITimelineItemProperty *inProperty)
+ : m_Property(inProperty)
+ , m_TimeRatio(0.0f)
+ , m_MaxVal(0.0f)
+ , m_MinVal(0.0f)
+ , m_MinY(0)
+ , m_MaxY(0)
+{
+}
+
+CPropertyTimebarGraph::~CPropertyTimebarGraph()
+{
+ TKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos)
+ delete (*thePos);
+}
+
+//=============================================================================
+/**
+ * Toggle whether this is visible or not.
+ * Overrides CControl::SetVisible. If this is not visible then it removes
+ * a bunch of the refresh logic to speed stuff up.
+ * @param inIsVisible true if this control is to be visible.
+ */
+void CPropertyTimebarGraph::SetVisible(bool inIsVisible)
+{
+ CControl::SetVisible(inIsVisible);
+
+ // If this is visible then add the appropriate keyframes and listeners.
+ if (inIsVisible) {
+ m_MaxVal = m_Property->GetMaximumValue();
+ m_MinVal = m_Property->GetMinimumValue();
+
+ m_MinY = 10;
+ m_MaxY = GetSize().y - m_MinY;
+
+ RefreshKeyframes();
+ } else
+ RemoveKeyframes();
+}
+
+//=============================================================================
+/**
+ * Set the time ratio for this display.
+ * The time ratio controls how much time is displayed in how much space.
+ * @param inTimeRatio the time ratio.
+ */
+void CPropertyTimebarGraph::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+}
+
+//=============================================================================
+/**
+ * Draw this to the specified renderer.
+ * This will perform the graphing of all the channels on the property.
+ * @param inRenderer the renderer to draw to.
+ */
+void CPropertyTimebarGraph::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(CPt(0, 0), GetSize());
+ inRenderer->PushClippingRect(theRect);
+
+ // the available line colors, tried to use Rainbow.bvs code to do it dynamically but didn't
+ // quite work.
+ ::CColor theColors[6] = { ::CColor(255, 0, 0), ::CColor(0, 255, 0), ::CColor(0, 0, 255),
+ ::CColor(255, 255, 0), ::CColor(255, 0, 255), ::CColor(0, 255, 255) };
+
+ long theChannelCount = m_Property->GetChannelCount();
+ // Don't want to overflow the color array
+ if (theChannelCount <= 6) {
+ // For each channel graph it.
+ for (long theIndex = 0; theIndex < theChannelCount; ++theIndex)
+ DrawDetailedChannel(inRenderer, theIndex, theColors[theIndex]);
+ }
+
+ inRenderer->PopClippingRect();
+}
+
+void CPropertyTimebarGraph::DrawDetailedChannel(CRenderer *inRenderer, long inChannelIndex,
+ ::CColor inColor)
+{
+ inRenderer->PushPen(inColor, 2);
+
+ CRct theClipRect = inRenderer->GetClippingRect();
+ float theValue = m_Property->GetChannelValueAtTime(inChannelIndex, 0);
+ long theYPos = (long)((1.0 - (theValue - m_MinVal) / (m_MaxVal - m_MinVal)) * (m_MaxY - m_MinY)
+ + m_MinY + .5);
+
+ inRenderer->MoveTo(CPt(0, theYPos));
+
+ long theInterval = 5;
+ long theSize = theClipRect.position.x + theClipRect.size.x + theInterval;
+
+ for (long thePixel = theClipRect.position.x; thePixel < theSize; thePixel += theInterval) {
+ long theTime = ::PosToTime(thePixel, m_TimeRatio); //(long)( thePixel / m_TimeRatio + .5 );
+ theValue = m_Property->GetChannelValueAtTime(inChannelIndex, theTime);
+ theYPos = (long)((1.0 - (theValue - m_MinVal) / (m_MaxVal - m_MinVal)) * (m_MaxY - m_MinY)
+ + m_MinY + .5);
+
+ inRenderer->LineTo(CPt(thePixel, theYPos));
+ }
+
+ inRenderer->PopPen();
+}
+
+void CPropertyTimebarGraph::AddKeyframes()
+{
+ long theChannelCount = m_Property->GetChannelCount();
+ long theKeyframeCount =
+ m_Property->GetKeyframeCount(); // the way it works now (and hence the assumption is), the
+ // number of keyframes for all the channels is the same.
+ for (long theIndex = 0; theIndex < theChannelCount; ++theIndex) {
+ for (long theKeyIndex = 0; theKeyIndex < theKeyframeCount; ++theKeyIndex) {
+ CPropertyGraphKeyframe *theGraphKeyframe = new CPropertyGraphKeyframe(
+ m_Property, theIndex, m_Property->GetKeyframeByIndex(theKeyIndex)->GetTime(),
+ m_TimeRatio, m_MinY, m_MaxY, m_MinVal, m_MaxVal);
+ AddChild(theGraphKeyframe);
+ m_Keyframes.push_back(theGraphKeyframe);
+ }
+ }
+}
+
+void CPropertyTimebarGraph::Invalidate(bool inIsInvalidated)
+{
+ CControl::Invalidate(inIsInvalidated);
+
+ if (inIsInvalidated && GetParent() != nullptr) {
+ GetParent()->Invalidate(inIsInvalidated);
+ }
+}
+
+void CPropertyTimebarGraph::RemoveKeyframes()
+{
+ TKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ CPropertyGraphKeyframe *theKeyframe = (*thePos);
+ RemoveChild(theKeyframe);
+ delete theKeyframe;
+ }
+ m_Keyframes.clear();
+}
+
+void CPropertyTimebarGraph::RefreshKeyframes()
+{
+ TKeyframeList::iterator thePos = m_Keyframes.begin();
+ while (thePos != m_Keyframes.end()) {
+ CPropertyGraphKeyframe *theKeyframe = (*thePos);
+ if (m_Property->GetKeyframeByTime(theKeyframe->GetTime())) {
+ theKeyframe->PositionKeyframe();
+ ++thePos;
+ } else {
+ RemoveChild(theKeyframe);
+ delete theKeyframe;
+ thePos = m_Keyframes.erase(thePos);
+ }
+ }
+ long theChannelCount = m_Property->GetChannelCount();
+ long theKeyframeCount =
+ m_Property->GetKeyframeCount(); // the way it works now (and hence the assumption is), the
+ // number of keyframes for all the channels is the same.
+ for (long theIndex = 0; theIndex < theChannelCount; ++theIndex) {
+ for (long theKeyIndex = 0; theKeyIndex < theKeyframeCount; ++theKeyIndex) {
+ IKeyframe *theKeyframe = m_Property->GetKeyframeByIndex(theKeyIndex);
+ CPropertyGraphKeyframe *theExistingKeyframe =
+ GetKeyframe(theKeyframe->GetTime(), theIndex);
+ if (!theExistingKeyframe) {
+ CPropertyGraphKeyframe *theGraphKeyframe =
+ new CPropertyGraphKeyframe(m_Property, theIndex, theKeyframe->GetTime(),
+ m_TimeRatio, m_MinY, m_MaxY, m_MinVal, m_MaxVal);
+ AddChild(theGraphKeyframe);
+
+ m_Keyframes.push_back(theGraphKeyframe);
+ }
+ }
+ }
+
+ Invalidate();
+}
+
+CPropertyGraphKeyframe *CPropertyTimebarGraph::GetKeyframe(long inTime, long inChannelIndex)
+{
+ TKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ CPropertyGraphKeyframe *theKeyframe = (*thePos);
+ if (theKeyframe->GetChannelIndex() == inChannelIndex && theKeyframe->GetTime() == inTime) {
+ return theKeyframe;
+ }
+ }
+ return nullptr;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.h b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.h
new file mode 100644
index 00000000..76379bcd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarGraph.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_TIMEBAR_GRAPH_H
+#define INCLUDED_PROPERTY_TIMEBAR_GRAPH_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+
+class CPropertyGraphKeyframe;
+class ITimelineItemProperty;
+
+class CPropertyTimebarGraph : public CControl
+{
+ typedef std::vector<CPropertyGraphKeyframe *> TKeyframeList;
+
+public:
+ CPropertyTimebarGraph(ITimelineItemProperty *inProperty);
+ virtual ~CPropertyTimebarGraph();
+ void SetVisible(bool inIsVisible) override;
+ void Draw(CRenderer *inRenderer) override;
+ void SetTimeRatio(double inTimeRatio);
+ void Invalidate(bool inIsInvalidated = true) override;
+ void RefreshKeyframes();
+
+protected:
+ void DrawDetailedChannel(CRenderer *inRenderer, long inChannelIndex, ::CColor inColor);
+ void AddKeyframes();
+ void RemoveKeyframes();
+
+ CPropertyGraphKeyframe *GetKeyframe(long inTime, long inChannelIndex);
+
+protected:
+ ITimelineItemProperty *m_Property;
+ double m_TimeRatio;
+ TKeyframeList m_Keyframes;
+ float m_MaxVal;
+ float m_MinVal;
+ long m_MinY;
+ long m_MaxY;
+};
+#endif // INCLUDED_PROPERTY_TIMEBAR_GRAPH_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.cpp
new file mode 100644
index 00000000..428777a8
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.cpp
@@ -0,0 +1,508 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PropertyTimebarRow.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "StudioUtils.h"
+#include "PropertyRow.h"
+#include "MasterP.h"
+#include "KeyframeContextMenu.h"
+#include "PropertyTimelineKeyframe.h"
+#include "HotKeys.h"
+#include "MultiSelectAspect.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "IKeyframe.h"
+#include "CoreUtils.h"
+
+//=============================================================================
+/**
+ */
+CPropertyTimebarRow::CPropertyTimebarRow(CPropertyRow *inPropertyRow)
+ : m_PropertyRow(inPropertyRow)
+ , m_DetailedView(inPropertyRow->GetProperty())
+ , m_DirtyFlag(false)
+ , m_Refreshing(false)
+ , m_SnappingListProvider(nullptr)
+{
+ m_DetailedView.SetVisible(false);
+
+ m_BackgroundColor = m_PropertyRow->GetTimebarBackgroundColor();
+
+ AddChild(&m_DetailedView);
+ m_Refreshing = false;
+ RefreshKeyframes();
+}
+
+CPropertyTimebarRow::~CPropertyTimebarRow()
+{
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ CPropertyTimelineKeyframe *theDeletedKey = (*thePos);
+ RemoveChild(theDeletedKey);
+ delete theDeletedKey;
+ }
+}
+
+//=============================================================================
+/**
+ * Draws the this row background.
+ * @param inRenderer the renderer to draw to.
+ */
+void CPropertyTimebarRow::Draw(CRenderer *inRenderer)
+{
+ if (m_DirtyFlag) {
+ RefreshKeyframes();
+ m_DirtyFlag = false;
+ }
+
+ CRct theRect(GetSize());
+ UICDM::TDataTypePair theType = m_PropertyRow->GetProperty()->GetType();
+ if (theType.first == UICDM::DataModelDataType::Float3
+ && theType.second == UICDM::AdditionalMetaDataType::Color) {
+ inRenderer->FillSolidRect(CRct(0, 0, theRect.size.x, theRect.size.y - 1),
+ m_BackgroundColor);
+ DrawColor(inRenderer);
+ } else {
+ inRenderer->FillSolidRect(CRct(0, 0, theRect.size.x, theRect.size.y - 1),
+ m_BackgroundColor);
+ }
+
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Draw a colorized background for this property row.
+ * If this is a color object then this will draw the background of this control
+ * as the color that the property is. This will draw a gradient between the
+ * colors over time to show somewhat what the colors look like.
+ * @param inRenderer the renderer to draw to.
+ */
+void CPropertyTimebarRow::DrawColor(CRenderer *inRenderer)
+{
+ UICPROFILE(DrawColor);
+
+ ITimelineItemProperty *theProperty = m_PropertyRow->GetProperty();
+ ASSERT(theProperty->GetChannelCount() == 3); // sanity check
+
+ CColor thePreviousColor;
+ thePreviousColor.SetRed(::dtol(theProperty->GetChannelValueAtTime(0, 0)));
+ thePreviousColor.SetGreen(::dtol(theProperty->GetChannelValueAtTime(1, 0)));
+ thePreviousColor.SetBlue(::dtol(theProperty->GetChannelValueAtTime(2, 0)));
+
+ long thePreviousTime = 0;
+ long theLastPosition = 0;
+ CColor theCurrentColor;
+
+ long theKeyframeCount = theProperty->GetKeyframeCount();
+
+ // Go through all the keyframes and draw a gradient from the previous key to the current key.
+ // Only use the first channel for the keyframes, assume they are all at the same time.
+ for (long theIndex = 0; theIndex < theKeyframeCount; ++theIndex) {
+ long theCurrentTime = theProperty->GetKeyframeByIndex(theIndex)->GetTime();
+ // Get the color at the specified time.
+ theCurrentColor.SetRed(::dtol(theProperty->GetChannelValueAtTime(0, theCurrentTime)));
+ theCurrentColor.SetGreen(::dtol(theProperty->GetChannelValueAtTime(1, theCurrentTime)));
+ theCurrentColor.SetBlue(::dtol(theProperty->GetChannelValueAtTime(2, theCurrentTime)));
+
+ long thePreviousPixel = ::TimeToPos(thePreviousTime, m_TimeRatio);
+ long theCurrentPixel = ::TimeToPos(theCurrentTime, m_TimeRatio);
+
+ // Draw a gradient from the previous keyframe position to the current one.
+ inRenderer->DrawGradient(
+ CRct(thePreviousPixel, 0, theCurrentPixel - thePreviousPixel, GetSize().y),
+ thePreviousColor, theCurrentColor);
+ thePreviousTime = theCurrentTime;
+ thePreviousColor = theCurrentColor;
+ theLastPosition = theCurrentPixel;
+ }
+ // Fill in from the last keyframe to the end of the bar.
+ inRenderer->DrawGradient(CRct(theLastPosition, 0, GetSize().x - theLastPosition, GetSize().y),
+ thePreviousColor, thePreviousColor);
+}
+
+//=============================================================================
+/**
+ * OnMouseOver event, handles the highlighting of the row.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+void CPropertyTimebarRow::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ m_PropertyRow->OnMouseOver();
+}
+
+//=============================================================================
+/**
+ * OnMouseOut event, handles the de-highlighting of this row.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+void CPropertyTimebarRow::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ m_PropertyRow->OnMouseOut();
+}
+
+//=============================================================================
+/**
+ * OnMouseRDown event, pops up a context menu
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the modifier key states (shift, alt, and ctrl).
+ */
+bool CPropertyTimebarRow::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Only do it if a child has not handled the mouse down.
+ bool theRetVal = CControl::OnMouseRDown(inPoint, inFlags);
+ if (!theRetVal) {
+ m_PropertyRow->Select();
+ CKeyframeContextMenu theMenu(m_PropertyRow->GetProperty()->GetKeyframesManager(),
+ m_PropertyRow->GetProperty());
+ DoPopup(&theMenu, inPoint);
+ theRetVal = true;
+ }
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * OnMouseOut event, handles the de-highlighting of this row.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+void CPropertyTimebarRow::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ UICPROFILE(OnMouseMove);
+ CControl::OnMouseMove(inPoint, inFlags);
+}
+//=============================================================================
+/**
+ * Set this control to being highlighted or not.
+ * @param inIsHighlighted true if this is to be highlighted.
+ */
+void CPropertyTimebarRow::SetHighlighted(bool inIsHighlighted)
+{
+ if (inIsHighlighted)
+ m_BackgroundColor = m_PropertyRow->GetTimebarHighlightBackgroundColor();
+ else
+ m_BackgroundColor = m_PropertyRow->GetTimebarBackgroundColor();
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Get the state row that this belongs to.
+ */
+CPropertyRow *CPropertyTimebarRow::GetPropertyRow()
+{
+ return m_PropertyRow;
+}
+
+//=============================================================================
+/**
+ * Sets teh time ratio
+ *
+ * @param inTimeRatio the new ratio
+ */
+void CPropertyTimebarRow::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ (*thePos)->SetTimeRatio(inTimeRatio);
+ }
+ m_DetailedView.SetTimeRatio(inTimeRatio);
+
+ Invalidate();
+}
+
+void CPropertyTimebarRow::SetDetailedView(bool inDetailedView)
+{
+ m_DetailedView.SetVisible(inDetailedView);
+}
+
+//=============================================================================
+/**
+ * Sets teh size of this control.
+ * @param inSize size to set the row
+ */
+void CPropertyTimebarRow::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+
+ m_DetailedView.SetSize(inSize);
+}
+
+//=============================================================================
+/**
+ * called when keyframes need to be updated, this funciton has two loops:
+ * the first loops through and deletes any keys no longer in the sskf list. the
+ * second adds any keys in the sskf list that are not already in the list
+ *
+ */
+void CPropertyTimebarRow::RefreshKeyframes()
+{
+ m_Refreshing = true;
+ UICPROFILE(RefreshKeyframes);
+
+ // First Loop clears any keys that do not correlate to a supersetkey
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+ while (thePos != m_Keyframes.end()) {
+ CPropertyTimelineKeyframe *theTimelineKey = (*thePos);
+ CPt theSize = theTimelineKey->GetSize();
+ IKeyframe *theTempKey = nullptr;
+ theTempKey = m_PropertyRow->GetProperty()->GetKeyframeByTime(theTimelineKey->GetTime());
+
+ // If we find a key at this time, then the timeline key doesn't need to be deleted
+ if (!theTempKey) {
+ RemoveChild(theTimelineKey);
+ delete theTimelineKey;
+ thePos = m_Keyframes.erase(thePos);
+ } else if (theTempKey->IsDynamic() != theTimelineKey->IsDynamic()) {
+ theTimelineKey->SetDynamic(theTempKey->IsDynamic());
+ } else {
+ // Set the position
+ theTimelineKey->SetPosition(
+ ::TimeToPos(theTempKey->GetTime(), m_TimeRatio) - (theSize.x / 2), 0);
+ ++thePos;
+ }
+ }
+
+ // Second Loop adds teh remaining keys
+ long theKeyframeCount = m_PropertyRow->GetProperty()->GetKeyframeCount();
+ for (long theKey = 0; theKey < theKeyframeCount; ++theKey) {
+ bool theFoundFlag = false;
+ IKeyframe *theTempKey = m_PropertyRow->GetProperty()->GetKeyframeByIndex(theKey);
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+
+ long theKeyframeTime = theTempKey->GetTime();
+ // each key needs to be compared to all the keys in the sskf list to see if it has to be
+ // added.
+ for (; thePos != m_Keyframes.end() && !theFoundFlag; ++thePos) {
+ CPropertyTimelineKeyframe *theCurrentKey = (*thePos);
+ if (theCurrentKey->GetTime() == theKeyframeTime) {
+ theFoundFlag = true;
+ }
+ }
+ if (!theFoundFlag) {
+ // If we don't have a timeline key, then we have to make a new one
+ CPropertyTimelineKeyframe *thePropertyTimelineKey =
+ new CPropertyTimelineKeyframe(this, m_TimeRatio);
+ thePropertyTimelineKey->SetTime(theKeyframeTime);
+ thePropertyTimelineKey->Select(theTempKey->IsSelected());
+ thePropertyTimelineKey->SetDynamic(theTempKey->IsDynamic());
+ thePropertyTimelineKey->SetSize(CPt(15, 16));
+ CPt theSize = thePropertyTimelineKey->GetSize();
+ long theXPosition = ::TimeToPos(theKeyframeTime, m_TimeRatio) - (theSize.x / 2);
+ thePropertyTimelineKey->SetPosition(theXPosition, 0);
+ AddChild(thePropertyTimelineKey);
+ m_Keyframes.push_back(thePropertyTimelineKey);
+ }
+ }
+
+ if (m_DetailedView.IsVisible())
+ m_DetailedView.RefreshKeyframes();
+
+ m_Refreshing = false;
+}
+
+void CPropertyTimebarRow::Invalidate(bool inInvalidate)
+{
+ if (!m_Refreshing) {
+ CControl::Invalidate(inInvalidate);
+ }
+}
+
+//=============================================================================
+/**
+ * Handler for when a child key is selected
+ *
+ * @param inTime time of the key
+ */
+void CPropertyTimebarRow::OnKeySelected(long inTime, bool inSelected)
+{
+ if (inTime >= 0) {
+ m_PropertyRow->GetProperty()->SelectKeyframes(inSelected, inTime);
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Deselects all keyframes
+ */
+void CPropertyTimebarRow::DeselectAllKeyframes()
+{
+ m_PropertyRow->GetProperty()->SelectKeyframes(false);
+}
+
+//=============================================================================
+/**
+ * called when a child changes and the keyframes need to be refreshed
+ *
+ * @param inDirtyFlag true if this object is now dirty
+ *
+ */
+void CPropertyTimebarRow::SetDirty(bool inDirtyFlag)
+{
+ if (m_DirtyFlag == inDirtyFlag)
+ return;
+
+ m_DirtyFlag = inDirtyFlag;
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * SelectKeysInRect: selects any keyframes inside the rect
+ *
+ * @param inRect is used to select keyframes
+ * @param inModifierKeyDown indicates if the control modifier is down
+ */
+void CPropertyTimebarRow::SelectKeysInRect(CRct inRect, bool inModifierKeyDown)
+{
+ CMultiSelectAspect<TTimelineKeyframeList> theMultiSelectAspect(m_Keyframes,
+ m_PropertyRow->GetProperty());
+ theMultiSelectAspect.MultiSelect(inRect, inModifierKeyDown);
+}
+
+//=============================================================================
+/**
+ * CommitSelections: commits all the master keyframe selections by setting their
+ * previous selection state to the current selection state.
+ * This will prevent the keyframes in the current selection
+ *from
+ * switching states as we select other keyframes.
+ *
+ * @param NONE
+ * @return NONE
+ */
+
+void CPropertyTimebarRow::CommitSelections()
+{
+ CMultiSelectAspect<TTimelineKeyframeList> theMultiSelectAspect(m_Keyframes,
+ m_PropertyRow->GetProperty());
+ theMultiSelectAspect.CommitSelections();
+}
+
+//=============================================================================
+/**
+ * true if there are selected keys on this object
+ */
+bool CPropertyTimebarRow::HasSelectedKeys()
+{
+ bool theRetVal = false;
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end() && !theRetVal; ++thePos) {
+ if ((*thePos)->IsSelected()) {
+ theRetVal = true;
+ }
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * selects all keys for this timebar row
+ */
+void CPropertyTimebarRow::SelectAllKeys()
+{
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ m_PropertyRow->GetProperty()->SelectKeyframes(true, (*thePos)->GetTime());
+ (*thePos)->Select(true);
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Set this control as being visible or not.
+ * If the control is not visible then it will not be drawn and will not
+ * get mouse clicks.
+ * @param inIsVisible true if this control is to be visible.
+ */
+void CPropertyTimebarRow::SetVisible(bool inIsVisible)
+{
+ if (inIsVisible != IsVisible()) {
+ CControl::SetVisible(inIsVisible);
+ SetDirty(true);
+ }
+}
+
+bool CPropertyTimebarRow::HasKeyframe(long inTime) const
+{
+ return m_PropertyRow->GetProperty()->GetKeyframeByTime(inTime) != nullptr;
+}
+
+//=============================================================================
+/**
+ * @param inTime -1 for all keyframes
+ */
+void CPropertyTimebarRow::SelectKeysByTime(long inTime, bool inSelected)
+{
+ TTimelineKeyframeList::iterator thePos = m_Keyframes.begin();
+ bool theFoundFlag = false;
+ for (; thePos != m_Keyframes.end() && !theFoundFlag; ++thePos) {
+ CPropertyTimelineKeyframe *theKey = (*thePos);
+ if (inTime == -1 || theKey->GetTime() == inTime) {
+ theKey->Select(inSelected);
+ theFoundFlag = (inTime != -1);
+ }
+ }
+ Invalidate();
+}
+
+void CPropertyTimebarRow::SetSnappingListProvider(ISnappingListProvider *inProvider)
+{
+ m_SnappingListProvider = inProvider;
+}
+
+ISnappingListProvider &CPropertyTimebarRow::GetSnappingListProvider() const
+{
+ // sk - If you hit this, it means the setup is incorrect. e.g. the parent row (which is most
+ // probably a staterow) isn't pass 'down' this info.
+ ASSERT(m_SnappingListProvider);
+ return *m_SnappingListProvider;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.h b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.h
new file mode 100644
index 00000000..a07118f9
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTimebarRow.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_TIMEBAR_ROW_H
+#define INCLUDED_PROPERTY_TIMEBAR_ROW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "PropertyTimebarGraph.h"
+#include "StateRow.h"
+
+//==============================================================================
+// forwards
+//==============================================================================
+class CPropertyRow;
+class CPropertyTimelineKeyframe;
+class ISnappingListProvider;
+
+class CPropertyTimebarRow : public CControl
+{
+ typedef std::vector<CPropertyTimelineKeyframe *> TTimelineKeyframeList;
+
+public:
+ CPropertyTimebarRow(CPropertyRow *inPropertyRow);
+ virtual ~CPropertyTimebarRow();
+
+ void Draw(CRenderer *inRenderer) override;
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void SetHighlighted(bool inIsHighlighted);
+ void RefreshKeyframes();
+
+ void SetSize(CPt inSize) override;
+
+ CPropertyRow *GetPropertyRow();
+
+ void SetTimeRatio(double inTimeRatio);
+
+ void SetDetailedView(bool inDetailedView);
+ void OnKeySelected(long inTime, bool inSelected);
+ void DeselectAllKeyframes();
+ void SetDirty(bool inDirtyFlag);
+ void CommitSelections();
+ void SelectKeysInRect(CRct inRect, bool inModifierKeyDown);
+ void SelectAllKeys();
+ bool HasSelectedKeys();
+ void Invalidate(bool inInvalidate = true) override;
+ void SetVisible(bool inIsVisible) override;
+
+ bool HasKeyframe(long inTime) const;
+ void SelectKeysByTime(long inTime, bool inSelected);
+
+ void SetSnappingListProvider(ISnappingListProvider *inProvider);
+ ISnappingListProvider &GetSnappingListProvider() const;
+
+protected:
+ void DrawColor(CRenderer *inRenderer);
+
+protected:
+ TTimelineKeyframeList m_Keyframes; ///< Properties Keyframe List (STL)
+ CPropertyRow *m_PropertyRow;
+ CPropertyTimebarGraph m_DetailedView;
+ ::CColor m_BackgroundColor;
+ double m_TimeRatio;
+
+ bool m_DirtyFlag;
+ bool m_Refreshing;
+ ISnappingListProvider *m_SnappingListProvider;
+};
+#endif // INCLUDED_STATE_TIMEBAR_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.cpp
new file mode 100644
index 00000000..c3a83e09
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.cpp
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Dialogs.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PropertyTimelineKeyframe.h"
+#include "PropertyTimebarRow.h"
+#include "Renderer.h"
+#include "PropertyRow.h"
+#include "KeyframeContextMenu.h"
+#include "HotKeys.h"
+#include "ResourceCache.h"
+#include "TimelineControl.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "StudioUtils.h"
+#include "TimeEditDlg.h"
+
+CPropertyTimelineKeyframe::CPropertyTimelineKeyframe(CPropertyTimebarRow *inParentRow,
+ double inTimeRatio)
+ : m_Selected(false)
+ , m_IsMouseDown(false)
+ , m_IsDragging(false)
+{
+ m_ParentRow = inParentRow;
+ m_TimeRatio = inTimeRatio;
+ CResourceCache *theCache = CResourceCache::GetInstance();
+ m_Icon = theCache->GetBitmap("Keyframe-Property-Normal.png");
+ m_DisabledIcon = theCache->GetBitmap("Keyframe-Property-Disabled.png");
+ m_SelectedIcon = theCache->GetBitmap("Keyframe-Property-Selected.png");
+ m_DynamicIcon = theCache->GetBitmap("Keyframe-PropertyDynamic-Normal.png");
+ m_DynamicSelectedIcon = theCache->GetBitmap("Keyframe-PropertyDynamic-Selected.png");
+ m_RectOverHandled = false;
+ m_PreviousSelectState = false;
+}
+
+CPropertyTimelineKeyframe::~CPropertyTimelineKeyframe()
+{
+}
+
+//=============================================================================
+/**
+ * SetRectOverHandled: Sets if mouse rectangle has been handled
+ * param@ inState indicates if the rectangle over has been handled.
+ * return@ NONE
+ */
+void CPropertyTimelineKeyframe::SetRectOverHandled(bool inState)
+{
+ m_RectOverHandled = inState;
+}
+
+//=============================================================================
+/**
+ * GetRectOverHandled: GetRectOverHandled
+ * param@ NONE
+ * return@ m_RectOverHandled, which indicates if the rectangle over has been handled
+ */
+bool CPropertyTimelineKeyframe::GetRectOverHandled()
+{
+ return m_RectOverHandled;
+}
+
+//=============================================================================
+/**
+ * SetPreviousSelectState: Sets if the current keyframe was previously selected
+ * param@ inState is used to set m_PreviousSelectState.
+ * return@ NONE
+ */
+void CPropertyTimelineKeyframe::SetPreviousSelectState(bool inState)
+{
+ m_PreviousSelectState = inState;
+}
+
+//=============================================================================
+/**
+ * GetPreviousSelectState: Returns the keyframe's previous select state
+ * param@ NONE
+ * return@ m_PreviousSelectState that stores the select state for the keyframe
+ */
+bool CPropertyTimelineKeyframe::GetPreviousSelectState()
+{
+ return m_PreviousSelectState;
+}
+
+//=============================================================================
+/**
+ * Gets teh correct image and draws
+ */
+void CPropertyTimelineKeyframe::Draw(CRenderer *inRenderer)
+{
+ if (m_Selected) {
+ inRenderer->DrawBitmap(CPt(0, 0), GetImage());
+ } else {
+ inRenderer->DrawBitmap(CPt(2, 0), GetImage());
+ }
+}
+
+//=============================================================================
+/**
+ * Gets the current bitmap depending on the state of the button, postion of the
+ * mouse, etc. Returns the image for the up state by default.
+ */
+QPixmap CPropertyTimelineKeyframe::GetImage()
+{
+ if (!IsEnabled())
+ return m_DisabledIcon;
+ else if (m_IsDynamic) {
+ if (m_Selected)
+ return m_DynamicSelectedIcon;
+ else
+ return m_DynamicIcon;
+ } else if (m_Selected)
+ return m_SelectedIcon;
+ else
+ return m_Icon;
+}
+
+//=============================================================================
+/**
+ * Handler for left-click events. Allows keyframe dragging. Children are
+ * allowed to handle this event before the parent does.
+ * @param inPoint the point where the mouse is
+ * @param inFlags the state of modifier keys when the event occurred
+ * @return true
+ */
+bool CPropertyTimelineKeyframe::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // Store the mouse down location in screen coordinates so that we can check the dragging buffer
+ // in OnMouseMove
+ m_MouseDownLoc = inPoint;
+
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ // If the control key is down then we change state, otherwise
+ if (!((CHotKeys::MODIFIER_CONTROL & inFlags) == CHotKeys::MODIFIER_CONTROL)) {
+ if (!m_Selected)
+ GetProperty()->ClearKeySelection();
+
+ m_Selected = true;
+ } else {
+ m_Selected = !m_Selected;
+ }
+ m_ParentRow->OnKeySelected(m_Time, m_Selected);
+ // TODO : sk - Remove this when we are clear on the fact that UpdateClientScene &
+ // FireChangeEvent do nothing useful here.
+ // This call makes no sense. However, if you run into some wierd
+ //behavior related to mouse down events, this might be a clue.
+ // I am leaving this just in case this speeds up debugging for anyone
+ //else looking at this.
+ // CAssetTimelineKeyframe::OnMouseDown does similar things.
+ // m_Doc->UpdateClientScene( true );
+ // m_ParentRow->GetPropertyRow()->GetProperty()->FireChangeEvent( false );
+ m_IsMouseDown = true;
+
+ m_Snapper.Clear();
+ m_Snapper.SetSource(this);
+ m_Snapper.SetSnappingSelectedKeyframes(false);
+ m_ParentRow->GetSnappingListProvider().PopulateSnappingList(&m_Snapper);
+ m_Snapper.BeginDrag(inPoint.x);
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Handler for right-click events. Pops up a context menu. Children are
+ * allowed to handle this event before the parent does.
+ * @param inPoint the point where the mouse is
+ * @param inFlags the state of modifier keys when the event occurred
+ * @return true
+ */
+bool CPropertyTimelineKeyframe::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseRDown(inPoint, inFlags)) {
+ if (!m_Selected) {
+ GetProperty()->ClearKeySelection();
+ m_Selected = true;
+ m_ParentRow->OnKeySelected(m_Time, m_Selected);
+ }
+
+ CKeyframeContextMenu theMenu(GetProperty()->GetKeyframesManager(), GetProperty());
+ theMenu.SetTime(GetTime());
+ DoPopup(&theMenu, inPoint);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * called when this key is selected
+ * @param inState the state this key is selected to
+ */
+void CPropertyTimelineKeyframe::Select(bool inState)
+{
+ if (m_Selected != inState) {
+ m_Selected = inState;
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * handler for the mouse up event
+ * @param inFlags the state of things when the mouse button was released
+ * @param inPoint the point where the mouse is
+ */
+void CPropertyTimelineKeyframe::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ // If this key is selected, then we need to make sure that it moved all the way to the
+ // mouse up location
+ if (m_Selected && m_IsMouseDown && m_IsDragging) {
+ long theNewTime = m_Snapper.ProcessDrag(m_Time, inPoint.x, inFlags);
+ long theDiffTime = theNewTime - m_Time;
+
+ // theDiffTime can get updated if its invalid.
+ theDiffTime = GetProperty()->OffsetSelectedKeyframes(theDiffTime);
+ // Set this key's time so it won't be recalced in Refresh keyframes in the row
+ SetTime(m_Time + theDiffTime);
+ }
+
+ m_IsMouseDown = false;
+ m_IsDragging = false;
+
+ GetProperty()->CommitChangedKeyframes();
+ HideMoveableWindow();
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * handler for the onMouse Move event. Offsets selected keys.
+ *
+ * @param inFlags the state of things when the mouse was moved
+ * @param inPoint the point where the mouse is
+ */
+void CPropertyTimelineKeyframe::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ // If the mouse is down and this is slected, then offst the keys
+ if (m_IsMouseDown && m_Selected) {
+ // If we are not yet dragging the keyframe
+ if (!m_IsDragging) {
+ long theDiff = ::abs(inPoint.x) - m_MouseDownLoc.x;
+ // Figure out if the mouse has moved far enough to start the drag, and readjust the drag
+ // postion on the snapper
+ m_IsDragging = (::abs(theDiff) > DRAGBUFFER);
+ if (m_IsDragging && (::abs(theDiff) - DRAGBUFFER) > 2) {
+ m_Snapper.BeginDrag(m_MouseDownLoc.x);
+ } else
+ m_Snapper.BeginDrag(inPoint.x);
+ }
+
+ // If we are already dragging the keyframe, procceed as normal
+ if (m_IsDragging) {
+ long theNewTime = m_Snapper.ProcessDrag(m_Time, inPoint.x, inFlags);
+ long theDiffTime = theNewTime - m_Time;
+
+ if (theDiffTime != 0) {
+ // theDiffTime can get updated if its invalid.
+ theDiffTime = GetProperty()->OffsetSelectedKeyframes(theDiffTime);
+ // Set this key's time so it won't be recalced in Refresh keyframes in the row
+ SetTime(m_Time + theDiffTime);
+ Invalidate();
+ }
+ }
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+}
+
+//=============================================================================
+/**
+ * Sets teh time ratio
+ *
+ * @param inTimeRatio the new ratio
+ */
+void CPropertyTimelineKeyframe::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+ CPt theSize = GetSize();
+ SetPosition(::TimeToPos(GetTime(), m_TimeRatio) - (theSize.x / 2), 0);
+}
+
+//=============================================================================
+/**
+ * Pass the double click notification on to the row and have it process it.
+ * The row will do object-specific actions on doubleclicks.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ * @return true stating that the event was processed.
+ */
+bool CPropertyTimelineKeyframe::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+
+ GetProperty()->OnEditKeyframeTime(m_Time, ASSETKEYFRAME);
+ return true;
+}
+
+//=============================================================================
+/**
+ * @return true if selected
+ */
+bool CPropertyTimelineKeyframe::IsSelected()
+{
+ return m_Selected;
+}
+
+//=============================================================================
+/**
+* Updates the ToolTip and moves it to the correct place on screen.
+* @param inPoint the point that the tooltip is supposed to be placed.
+*/
+void CPropertyTimelineKeyframe::RefreshToolTip(CPt inPoint)
+{
+ CRct theTimelineBounds(m_ParentRow->GetPropertyRow()->GetTopControl()->GetBounds());
+
+ // format label
+ Q3DStudio::CString theCommentText = " " + ::FormatTimeString(GetTime());
+
+ inPoint.y = GetPosition().y - GetSize().y;
+ inPoint.x = GetSize().x / 2;
+ ShowMoveableWindow(inPoint, theCommentText, theTimelineBounds);
+}
+
+//=============================================================================
+/**
+* Helper function to retrieve the ITimelineItemProperty
+*/
+ITimelineItemProperty *CPropertyTimelineKeyframe::GetProperty() const
+{
+ return m_ParentRow->GetPropertyRow()->GetProperty();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.h b/src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.h
new file mode 100644
index 00000000..40c7f05b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTimelineKeyframe.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_TIMELINE_KEYFRAME
+#define INCLUDED_PROPERTY_TIMELINE_KEYFRAME 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "TimelineKeyframe.h"
+#include "Snapper.h"
+
+#include <QPixmap>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class CPropertyTimebarRow;
+class ITimelineItemProperty;
+
+class CPropertyTimelineKeyframe : public CControl, public CTimelineKeyframe
+{
+
+public:
+ CPropertyTimelineKeyframe(CPropertyTimebarRow *inParentRow, double inTimeRatio);
+ ~CPropertyTimelineKeyframe();
+ void Draw(CRenderer *inRenderer) override;
+ QPixmap GetImage();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void Select(bool inState);
+ void SetTimeRatio(double inTimeRatio);
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool IsSelected();
+ void SetRectOverHandled(bool inState);
+ bool GetRectOverHandled();
+ void SetPreviousSelectState(bool inState);
+ bool GetPreviousSelectState();
+
+protected:
+ void RefreshToolTip(CPt inPoint);
+ ITimelineItemProperty *GetProperty() const;
+
+protected:
+ bool m_Selected;
+ bool m_RectOverHandled; ///< Indicates if the mouse rect over has been handled.
+ bool m_PreviousSelectState; ///< Stores the previous select state for the keyframe.
+ CPropertyTimebarRow *m_ParentRow;
+ bool m_IsMouseDown;
+ CPt m_MouseDownLoc; ///< Location of the mouse after an OnMouseDownEvent, in client coordinates
+ bool m_IsDragging; ///< Indicates whether or not the keyframe is currently being dragged,
+ ///determined by the pixel buffer
+ double m_TimeRatio;
+ CSnapper m_Snapper;
+ QPixmap m_Icon;
+ QPixmap m_DisabledIcon;
+ QPixmap m_SelectedIcon;
+ QPixmap m_DynamicIcon;
+ QPixmap m_DynamicSelectedIcon;
+};
+
+#endif // INCLUDED_PROPERTY_TIMELINE_KEYFRAME
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.cpp
new file mode 100644
index 00000000..994ba2fe
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "PropertyToggleControl.h"
+#include "TimelineRow.h"
+#include "PropertyRow.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+
+CPropertyToggleControl::CPropertyToggleControl(CPropertyRow *inPropertyRow)
+ : m_PropertyRow(inPropertyRow)
+{
+ m_BackgroundColor = m_PropertyRow->GetTimebarBackgroundColor();
+}
+
+CPropertyToggleControl::~CPropertyToggleControl()
+{
+}
+
+void CPropertyToggleControl::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+ inRenderer->FillSolidRect(QRect(0, 0, theRect.size.x + 1, theRect.size.y), m_BackgroundColor);
+
+ // Draw the line at the bottom of this control
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+
+ // Draw the line on the left side of this control
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theRect.size.y - 1));
+
+ // Draw the highlight
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(1, 0));
+ inRenderer->LineTo(CPt(1, theRect.size.y - 1));
+ inRenderer->PopPen();
+
+ // Draw the line on the right side of this control
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ inRenderer->MoveTo(CPt(theRect.size.x - 1, 0));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+void CPropertyToggleControl::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ m_PropertyRow->OnMouseOver();
+}
+
+void CPropertyToggleControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ m_PropertyRow->OnMouseOut();
+}
+
+void CPropertyToggleControl::SetHighlighted(bool inIsHighlighted)
+{
+ if (inIsHighlighted)
+ m_BackgroundColor = m_PropertyRow->GetTimebarHighlightBackgroundColor();
+ else
+ m_BackgroundColor = m_PropertyRow->GetTimebarBackgroundColor();
+
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * Handles the OnMouseDownEvent
+ */
+bool CPropertyToggleControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags))
+ m_PropertyRow->Select((CHotKeys::MODIFIER_SHIFT & inFlags) == CHotKeys::MODIFIER_SHIFT);
+
+ return true;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.h b/src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.h
new file mode 100644
index 00000000..81435cc6
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyToggleControl.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_TOGGLE_CONTROL_H
+#define INCLUDED_PROPERTY_TOGGLE_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "CColor.h"
+
+class CPropertyRow;
+
+class CPropertyToggleControl : public CControl
+{
+public:
+ CPropertyToggleControl(CPropertyRow *inPropertyRow);
+ virtual ~CPropertyToggleControl();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void SetHighlighted(bool inIsHightlighted);
+
+protected:
+ CPropertyRow *m_PropertyRow;
+ ::CColor m_BackgroundColor;
+};
+#endif // INCLUDED_PROPERTY_TOGGLE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.cpp b/src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.cpp
new file mode 100644
index 00000000..813f04f3
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PropertyTreeControl.h"
+#include "PropertyRow.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "StudioUtils.h"
+#include "HotKeys.h"
+#include "ResourceCache.h"
+#include "BaseTimelineTreeControl.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "CoreUtils.h"
+
+CPropertyTreeControl::CPropertyTreeControl(CPropertyRow *inPropRow)
+ : m_Icon(CResourceCache::GetInstance()->GetBitmap("Objects-Property-Normal.png"),
+ CResourceCache::GetInstance()->GetBitmap("Objects-Property-Disabled.png"))
+{
+ m_PropRow = inPropRow;
+
+ CBaseStateRow *theParentRow = m_PropRow->GetParentRow();
+ if (theParentRow) // property row typically should never exists on its own, but to be safe.
+ m_BackgroundColor = m_PropRow->GetTimebarBackgroundColor();
+ else
+ m_BackgroundColor = CStudioPreferences::GetPropertyBackgroundColor();
+
+ AddChild(&m_Icon);
+
+ m_Text.SetData(inPropRow->GetProperty()->GetName());
+ m_Text.SetAlignment(CTextEdit::LEFT);
+ m_Text.SetReadOnly(true);
+
+ AddChild(&m_Text);
+
+ SetIndent(0);
+}
+
+CPropertyTreeControl::~CPropertyTreeControl()
+{
+}
+
+void CPropertyTreeControl::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(GetSize());
+
+ inRenderer->FillSolidRect(theRect, m_BackgroundColor);
+
+ // Draw the line at the bottom of this control
+ CColor theShadowColor = CStudioPreferences::GetPropertyFloorColor();
+ inRenderer->PushPen(theShadowColor);
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+ inRenderer->PopPen();
+
+ ::CColor theTextColor = CStudioPreferences::GetNormalColor();
+ if (m_PropRow->GetProperty()->IsMaster())
+ theTextColor = CStudioPreferences::GetMasterColor();
+ m_Text.SetTextColor(theTextColor);
+}
+
+void CPropertyTreeControl::SetIndent(long inIndent)
+{
+ m_Indent = inIndent;
+
+ // place it it's size x2 to the right since we don't have a toggle.
+ m_Icon.SetPosition(CPt(m_Indent + m_Icon.GetSize().x, 0));
+
+ m_Text.SetPosition(CPt(m_Icon.GetPosition().x + m_Icon.GetSize().x + 5, 0));
+ m_Text.SetSize(CPt(200, m_Icon.GetSize().y - 1));
+}
+
+long CPropertyTreeControl::GetIndent()
+{
+ return m_Indent;
+}
+
+void CPropertyTreeControl::SetHighlighted(bool inIsHighlighted)
+{
+ CBaseStateRow *theParentRow = m_PropRow->GetParentRow();
+ if (theParentRow) // property row typically should never exists on its own, but to be safe.
+ m_BackgroundColor = (inIsHighlighted) ? m_PropRow->GetTimebarHighlightBackgroundColor()
+ : m_PropRow->GetTimebarBackgroundColor();
+ else
+ m_BackgroundColor = (inIsHighlighted) ? CStudioPreferences::GetPropertyMouseOverColor()
+ : CStudioPreferences::GetPropertyBackgroundColor();
+
+ Invalidate();
+}
+
+//==============================================================================
+/**
+ * HACK: Trying to scroll the timeline during a drag and drop operation.
+ *
+ * The Property Tree Control will never have a drop candidate, so this function
+ * returns nullptr. However, we still need to scroll the timeline in case we are
+ * at the top or bottom of the window. This is hackish for two reasons. 1) It
+ * points out that CPropertyTreeControl and CStateTreeControl should have a
+ * common base class that handles similar code. 2) The TreeControls should not
+ * have to scroll the timeline automatically. It should be handled through a
+ * timer on the scroller when the mouse is being dragged and hovering near the
+ * border of the scroller. But all of that will be saved for another day.
+ * @param inMousePoint location of the mouse
+ * @param inFlags not used (modifier key flags)
+ * @return nullptr (no drop candidate is ever found)
+ */
+CDropTarget *CPropertyTreeControl::FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inFlags);
+
+ CPt theSize(GetSize());
+
+ // If the mouse is towards the top of this row, make sure that this row and the
+ // one above it are visible (scroll upwards)
+ if (inMousePoint.y <= ::dtol(theSize.y / 2.0f))
+ EnsureVisible(CRct(CPt(0, -theSize.y), theSize));
+ // Otherwise, the mouse is towards the bottom of this row, so make sure this row
+ // and the one below it are visible (scroll downwards)
+ else
+ EnsureVisible(CRct(CPt(theSize.x, theSize.y * 2)));
+
+ return nullptr;
+}
+
+void CPropertyTreeControl::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ m_PropRow->OnMouseOver();
+}
+
+void CPropertyTreeControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ m_PropRow->OnMouseOut();
+}
+
+//==============================================================================
+/**
+ * Handles the OnMouseDownEvent
+ */
+bool CPropertyTreeControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags))
+ m_PropRow->Select((CHotKeys::MODIFIER_SHIFT & inFlags) == CHotKeys::MODIFIER_SHIFT);
+
+ return true;
+}
+
+bool CPropertyTreeControl::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDoubleClick(inPoint, inFlags)) {
+ m_PropRow->OnMouseDoubleClick();
+ }
+ return true;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.h b/src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.h
new file mode 100644
index 00000000..5bc61c23
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/PropertyTreeControl.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PROPERTY_TREE_CONTROL_H
+#define INCLUDED_PROPERTY_TREE_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "SIcon.h"
+#include "StringEdit.h"
+
+class CPropertyRow;
+
+class CPropertyTreeControl : public CControl
+{
+public:
+ CPropertyTreeControl(CPropertyRow *inPropRow);
+ virtual ~CPropertyTreeControl();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ void SetIndent(long inIndent);
+ long GetIndent();
+
+ void SetHighlighted(bool inIsHighlighted);
+
+ CDropTarget *FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags) override;
+
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+protected:
+ long m_Indent;
+ CPropertyRow *m_PropRow;
+ CSIcon m_Icon;
+ CStringEdit m_Text;
+ ::CColor m_BackgroundColor;
+};
+#endif // INCLUDED_PROPERTY_TREE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ScalableScroller.cpp b/src/Authoring/Studio/Palettes/Timeline/ScalableScroller.cpp
new file mode 100644
index 00000000..b445db83
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ScalableScroller.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "ScalableScroller.h"
+#include "ScalableScrollerBar.h"
+
+CScalableScroller::CScalableScroller()
+ : CScroller(false)
+ , m_ScalableBar(nullptr)
+ , m_ScalingListener(nullptr)
+{
+ Initialize();
+}
+
+CScalableScroller::~CScalableScroller()
+{
+}
+
+CScrollerBar *CScalableScroller::CreateHorizontalBar()
+{
+ if (m_ScalableBar == nullptr) {
+ m_ScalableBar = new CScalableBar(this);
+ m_ScalableBar->SetOrientation(CScrollerBar::HORIZONTAL);
+ m_ScalableBar->SetScalingListener(m_ScalingListener);
+ }
+ return m_ScalableBar;
+}
+
+void CScalableScroller::SetScalingListener(CScalingListener *inListener)
+{
+ m_ScalingListener = inListener;
+
+ if (m_ScalableBar != nullptr) {
+ m_ScalableBar->SetScalingListener(inListener);
+ }
+}
+
+//====================================================================
+/**
+ * Protected function for seting the display size of the scroller.
+ * Overridden because the scaleable scroller thumb at the bottom of
+ * the timeline was getting messed up. Yes, it's a hack, but I couldn't
+ * fix it any other way.
+ */
+void CScalableScroller::SetVisibleSize(CPt inSize)
+{
+ m_VisibleSize = inSize;
+
+ // Don't call the base class because it messes things up
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ScalableScroller.h b/src/Authoring/Studio/Palettes/Timeline/ScalableScroller.h
new file mode 100644
index 00000000..9fd6df3b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ScalableScroller.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SCALABLE_SCROLLER_H
+#define INCLUDED_SCALABLE_SCROLLER_H 1
+
+#pragma once
+
+#include "Scroller.h"
+
+class CScalingListener;
+class CScalableBar;
+
+class CScalableScroller : public CScroller
+{
+public:
+ CScalableScroller();
+ virtual ~CScalableScroller();
+
+ void SetScalingListener(CScalingListener *inScalingListener);
+
+ void SetVisibleSize(CPt inSize) override;
+
+protected:
+ CScrollerBar *CreateHorizontalBar() override;
+
+ CScalableBar *m_ScalableBar;
+
+ CScalingListener *m_ScalingListener;
+};
+#endif // INCLUDED_SCALABLE_SCROLLER_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.cpp b/src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.cpp
new file mode 100644
index 00000000..77c63292
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "ScrollerBackground.h"
+#include "ScalableScrollerBar.h"
+#include "ScalableScroller.h"
+#include "Renderer.h"
+#include "MouseCursor.h"
+#include "ResourceCache.h"
+
+#include <QApplication>
+
+//=============================================================================
+/**
+ * Creates a new ThumbTab (the scalable ends of the thumb).
+ * @param inThumb the thumb this belongs to.
+ * @param inIsRight true if this is the right side, false for left.
+ * @param inBar the ScalableBar this belongs to.
+ */
+CScalableThumbTab::CScalableThumbTab(CScalableThumb *inThumb, bool inIsRightTab,
+ CScalableBar *inBar)
+ : m_Bar(inBar)
+ , m_IsMouseDown(false)
+ , m_IsRightTab(inIsRightTab)
+{
+ m_Thumb = inThumb;
+}
+
+CScalableThumbTab::~CScalableThumbTab()
+{
+}
+
+//=============================================================================
+/**
+ * MouseOver handler, modifies the cursor.
+ * @param inPoint the mouse location.
+ * @param inFlags the mouse state.
+ */
+void CScalableThumbTab::OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOver(inPoint, inFlags);
+
+ setCursorIfNotSet(CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Mouse out handler, invalidates the control to clear the mouse over drawing.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CScalableThumbTab::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ if (!m_IsMouseDown)
+ resetCursor();
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Mouse move handlers, if this was clicked on then drags the control.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CScalableThumbTab::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ // Only drag if this was clicked on
+ if (m_IsMouseDown) {
+ long theDiff = inPoint.x - m_MouseDownLoc.x;
+ // Fire the scaling event for the delta size.
+ if (m_IsRightTab)
+ m_Bar->OnScalingRight(theDiff);
+ else
+ m_Bar->OnScalingLeft(theDiff);
+ }
+
+ CRct theRect(GetSize());
+ if (theRect.IsInRect(inPoint))
+ setCursorIfNotSet(CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
+}
+
+//=============================================================================
+/**
+ * Mouse click handler, starts resizing the control.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+bool CScalableThumbTab::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseDown(inPoint, inFlags);
+
+ setCursorIfNotSet(CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
+ m_IsMouseDown = true;
+ m_MouseDownLoc = inPoint;
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Mouse up handler, ends resizing this control.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CScalableThumbTab::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ resetCursor();
+
+ m_IsMouseDown = false;
+}
+
+//=============================================================================
+/**
+ * Draw this control.
+ * @param inRenderer the renderer to draw to.
+ */
+void CScalableThumbTab::Draw(CRenderer *inRenderer)
+{
+ CPt theSize = GetSize();
+ CRct theRect(theSize);
+
+ inRenderer->FillSolidRect(theRect, CStudioPreferences::GetScrollThumbBGColor());
+
+ // Draw the light colored highlight
+ inRenderer->PushPen(CStudioPreferences::GetScrollThumbHighlightColor());
+ inRenderer->MoveTo(CPt(1, theSize.y - 1));
+ inRenderer->LineTo(CPt(1, 1));
+ inRenderer->LineTo(CPt(theSize.x - 1, 1));
+ inRenderer->PopPen();
+
+ // Draw the dark bounding rectangle
+ CColor theGripBoundColor = CStudioPreferences::GetScrollThumbShadowColor();
+ inRenderer->Draw3dRect(theRect, theGripBoundColor, theGripBoundColor);
+}
+
+//=============================================================================
+/**
+ * Create a scalable thumb, this is the dragging component of the bar.
+ * @param inScrollerBar the bar this belongs to.
+ */
+CScalableThumb::CScalableThumb(CScalableBar *inScrollerBar)
+ : CScrollerThumb(inScrollerBar)
+ , m_LeftTab(this, false, inScrollerBar)
+ , m_RightTab(this, true, inScrollerBar)
+{
+ m_ScrollerBar = inScrollerBar;
+
+ m_LeftTab.SetPosition(CPt(0, 0));
+
+ AddChild(&m_LeftTab);
+ AddChild(&m_RightTab);
+}
+
+CScalableThumb::~CScalableThumb()
+{
+}
+
+//=============================================================================
+/**
+ * Set the size of this component, overrides to update the location of the tabs.
+ * @param inSize the new size of this control.
+ */
+void CScalableThumb::SetSize(CPt inSize)
+{
+ CScrollerThumb::SetSize(inSize);
+ m_LeftTab.SetSize(CPt(7, inSize.y));
+ m_RightTab.SetSize(CPt(7, inSize.y));
+ m_RightTab.SetPosition(CPt(inSize.x - m_RightTab.GetSize().x, 0));
+}
+
+//=============================================================================
+/**
+ * On double click this sends off a reset scaling notification.
+ * @param inPoint the mouse location.
+ * @param inFlags the state of the mouse.
+ */
+bool CScalableThumb::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDoubleClick(inPoint, inFlags))
+ m_ScrollerBar->OnScalingReset();
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Creates a new scalable scroller bar.
+ * This object can only be used for horizontal scrolling.
+ * @param inScroller the scalable scroller this is operating on.
+ */
+CScalableBar::CScalableBar(CScalableScroller *inScroller)
+ : CScrollerBar(inScroller, false)
+ , m_ScalableScroller(inScroller)
+ , m_Listener(nullptr)
+ , m_Thumb(nullptr)
+{
+ Initialize();
+}
+
+CScalableBar::~CScalableBar()
+{
+}
+
+//=============================================================================
+/**
+ * Create a new thumb control.
+ * This method is here so the ScalableBar can override it and return the Scalable
+ * Thumb instead of a normal thumb.
+ */
+CControl *CScalableBar::CreateThumb()
+{
+ if (m_Thumb == nullptr)
+ m_Thumb = new CScalableThumb(this);
+ return m_Thumb;
+}
+
+//=============================================================================
+/**
+ * This control is not allowed to become disabled (it should always allow scaling).
+ * @param inIsEnabled ignored.
+ */
+void CScalableBar::SetEnabled(bool inIsEnabled)
+{
+ Q_UNUSED(inIsEnabled);
+ CControl::SetEnabled(true);
+}
+
+//=============================================================================
+/**
+ * Set the single scaling listener that is to carry out the actual scaling work.
+ * @param inListener the scaling listener, there is only one.
+ */
+void CScalableBar::SetScalingListener(CScalingListener *inListener)
+{
+ m_Listener = inListener;
+}
+
+//=============================================================================
+/**
+ * Event from the left ThumbTab that it is scaling.
+ * @param inAmount the amount that the left ThumbTab is being scaled by.
+ */
+void CScalableBar::OnScalingLeft(long inAmount)
+{
+ CPt theLoc = m_Thumb->GetPosition();
+ CPt theSize = m_Thumb->GetSize();
+
+ // Don't let the loc go before the end of the control.
+ if (theLoc.x + inAmount < 0)
+ inAmount = -theLoc.x;
+
+ // Anchors the scroller position when its size reaches the minimum size
+ // The algorithm does not modify the inAmount as the scale can be further reduced,
+ // when the scroller reaches the minimum size.
+
+ CPt thePreviousPosition;
+ bool theAnchor = false;
+ if (theSize.x - inAmount < m_Thumb->GetMinimumSize().x) {
+ thePreviousPosition = m_Thumb->GetPosition();
+ theAnchor = true;
+ }
+
+ // Tell the listener of the scaling, it's the listener that will do the actual scaling work.
+ if (m_Listener != nullptr)
+ m_Listener->OnScalingLeft(theSize.x - inAmount, m_Background->GetSize().x,
+ m_Thumb->GetPosition().x + inAmount);
+
+ // When the Anchor flag is true (i.e. when the scroller has reach its minimum size), stop the
+ // scroller
+ // from moving by restoring its previous position.
+ if (theAnchor) {
+ m_Thumb->SetPosition(thePreviousPosition);
+ }
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Event from the right ThumbTab that it is scaling.
+ * @param inAmount the amount that the left ThumbTab is being scaled by.
+ */
+void CScalableBar::OnScalingRight(long inAmount)
+{
+ CPt theLoc = m_Thumb->GetPosition();
+ CPt theSize = m_Thumb->GetSize();
+ // Don't let the loc go after the end of the control.
+ if (theLoc.x + theSize.x + inAmount > m_Background->GetSize().x)
+ inAmount = m_Background->GetSize().x - (theLoc.x + theSize.x);
+
+ // Anchors the scroller position when its size reaches the minimum size
+ // The algorithm does not modify the inAmount as the scale can be further reduced,
+ // when the scroller reaches the minimum size.
+
+ CPt thePreviousPosition;
+ bool theAnchor = false;
+ if (theSize.x + inAmount < m_Thumb->GetMinimumSize().x) {
+ thePreviousPosition = m_Thumb->GetPosition();
+ theAnchor = true;
+ }
+
+ // Tell the listener of the scaling, it's the listener that will do the actual scaling work.
+ if (m_Listener != nullptr)
+ m_Listener->OnScalingRight(theSize.x + inAmount, m_Background->GetSize().x,
+ m_Thumb->GetPosition().x);
+
+ // When the Anchor flag is true (i.e. when the scroller has reach its minimum size), stop the
+ // scroller
+ // from moving by restoring its previous position.
+ if (theAnchor) {
+ m_Thumb->SetPosition(thePreviousPosition);
+ }
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Handles scaling reset messages commands, just routes them to the listener.
+ */
+void CScalableBar::OnScalingReset()
+{
+ m_Listener->OnScalingReset();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.h b/src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.h
new file mode 100644
index 00000000..afc0ef1e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ScalableScrollerBar.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SCALABLE_SCROLLER_BAR_H
+#define INCLUDED_SCALABLE_SCROLLER_BAR_H 1
+
+#pragma once
+
+#include "ScrollerThumb.h"
+#include "ScrollerBar.h"
+
+#include <QCursor>
+
+class CScalableBar;
+class CScalableScroller;
+class CScalableThumb;
+
+class CScalingListener
+{
+public:
+ virtual void OnScalingLeft(long inLength, long inTotalLength, long inOffset) = 0;
+ virtual void OnScalingRight(long inLength, long inTotalLength, long inOffset) = 0;
+ virtual void OnScalingReset() = 0;
+};
+
+class CScalableThumbTab : public CControl
+{
+public:
+ CScalableThumbTab(CScalableThumb *inThumb, bool inIsRightTab, CScalableBar *inBar);
+ virtual ~CScalableThumbTab();
+
+ void Draw(CRenderer *inRenderer) override;
+
+ void OnMouseOver(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+protected:
+ CScalableThumb *m_Thumb;
+ CScalableBar *m_Bar;
+ bool m_IsMouseDown;
+ bool m_IsRightTab;
+ CPt m_MouseDownLoc;
+};
+
+class CScalableThumb : public CScrollerThumb
+{
+public:
+ CScalableThumb(CScalableBar *inScrollerBar);
+ virtual ~CScalableThumb();
+
+ void SetSize(CPt inSize) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+protected:
+ CScalableBar *m_ScrollerBar;
+ CScalableThumbTab m_LeftTab;
+ CScalableThumbTab m_RightTab;
+};
+
+class CScalableBar : public CScrollerBar
+{
+public:
+ CScalableBar(CScalableScroller *inScroller);
+ virtual ~CScalableBar();
+
+ void SetEnabled(bool inIsEnabled) override;
+
+ void SetScalingListener(CScalingListener *inListener);
+
+ void OnScalingRight(long inAmount);
+ void OnScalingLeft(long inAmount);
+ void OnScalingReset();
+
+protected:
+ CControl *CreateThumb() override;
+
+ CScalableScroller *m_ScalableScroller;
+
+ CScalingListener *m_Listener;
+ CScalableThumb *m_Thumb;
+};
+
+#endif // INCLUDED_SCALABLE_SCROLLER_BAR_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/SlideRow.cpp b/src/Authoring/Studio/Palettes/Timeline/SlideRow.cpp
new file mode 100644
index 00000000..ac14bee2
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/SlideRow.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "SlideRow.h"
+#include "BlankToggleControl.h"
+#include "ColorControl.h"
+#include "SlideTimebarRow.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "ITimelineControl.h"
+
+CSlideRow::CSlideRow(ITimelineItemBinding *inTimelineItem)
+ : m_TimelineControl(nullptr)
+{
+ Initialize(inTimelineItem);
+}
+
+CSlideRow::~CSlideRow()
+{
+}
+
+void CSlideRow::SetTimelineControl(ITimelineControl *inTimelineControl)
+{
+ m_TimelineControl = inTimelineControl;
+}
+
+//=============================================================================
+/**
+ * Expand this node of the tree control.
+ * This will display all children the fit the filter.
+ */
+void CSlideRow::Expand(bool inExpandAll /*= false*/, bool inExpandUp)
+{
+ if (!m_Loaded) {
+ m_Loaded = true;
+ LoadChildren();
+ }
+
+ CBaseStateRow::Expand(inExpandAll, inExpandUp);
+}
+
+//=============================================================================
+/**
+ * This do not 'contribute' to its child's active start time
+ */
+bool CSlideRow::CalculateActiveStartTime()
+{
+ return false;
+}
+//=============================================================================
+/**
+ * This do not 'contribute' to its child's active end time
+ */
+bool CSlideRow::CalculateActiveEndTime()
+{
+ return false;
+}
+
+ISnappingListProvider *CSlideRow::GetSnappingListProvider() const
+{
+ ASSERT(m_TimelineControl);
+ return m_TimelineControl->GetSnappingListProvider();
+}
+
+void CSlideRow::SetSnappingListProvider(ISnappingListProvider *inProvider)
+{
+ // does nothing
+ Q_UNUSED(inProvider);
+}
+
+//=============================================================================
+/**
+ * See CBaseStateRow::GetTopControl comments.
+ * This being to "top" row will have the actual pointer
+ */
+ITimelineControl *CSlideRow::GetTopControl() const
+{
+ return m_TimelineControl;
+}
+
+//=============================================================================
+/**
+ * Create a new CStateTimebarRow.
+ * This is virtual and used for objects to return their type specific
+ * timebar rows if they want to.
+ * @return the created timebar row.
+ */
+CBaseTimebarlessRow *CSlideRow::CreateTimebarRow()
+{
+ return new CSlideTimebarRow(this);
+}
+
+bool CSlideRow::PerformFilter(const CFilter &inFilter)
+{
+ Q_UNUSED(inFilter);
+ return true;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/SlideRow.h b/src/Authoring/Studio/Palettes/Timeline/SlideRow.h
new file mode 100644
index 00000000..d978f11e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/SlideRow.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIME_CONTEXT_ROW_H
+#define INCLUDED_TIME_CONTEXT_ROW_H 1
+
+#pragma once
+
+#include "BaseStateRow.h"
+
+class ISnappingListProvider;
+class ITimelineControl;
+
+class CSlideRow : public CBaseStateRow
+{
+public:
+ CSlideRow(ITimelineItemBinding *inTimelineItem);
+ virtual ~CSlideRow();
+
+ void SetTimelineControl(ITimelineControl *inTimelineControl);
+
+ // BaseStateRow
+ void Expand(bool inExpandAll = false, bool inExpandUp = false) override;
+ bool CalculateActiveStartTime() override;
+ bool CalculateActiveEndTime() override;
+ ISnappingListProvider *GetSnappingListProvider() const override;
+ void SetSnappingListProvider(ISnappingListProvider *inProvider) override;
+ ITimelineControl *GetTopControl() const override;
+
+protected:
+ // CBaseStateRow
+ CBaseTimebarlessRow *CreateTimebarRow() override;
+ bool PerformFilter(const CFilter &inFilter) override;
+
+ ITimelineControl *m_TimelineControl;
+};
+#endif // INCLUDED_TIME_CONTEXT_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.cpp b/src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.cpp
new file mode 100644
index 00000000..49ce261f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "SlideTimebarRow.h"
+#include "SlideRow.h"
+
+CSlideTimebarRow::CSlideTimebarRow(CSlideRow *inSlideRow)
+ : m_SlideRow(inSlideRow)
+{
+}
+
+CSlideTimebarRow::~CSlideTimebarRow()
+{
+}
+
+void CSlideTimebarRow::CommitSelections()
+{
+}
+
+void CSlideTimebarRow::SelectKeysInRect(CRct inRect, bool inModifierKeyDown)
+{
+ Q_UNUSED(inRect);
+ Q_UNUSED(inModifierKeyDown);
+}
+
+void CSlideTimebarRow::SelectKeysByTime(long inTime, bool inSelected)
+{
+ Q_UNUSED(inTime);
+ Q_UNUSED(inSelected);
+}
+
+void CSlideTimebarRow::SelectAllKeys()
+{
+}
+
+void CSlideTimebarRow::PopulateSnappingList(CSnapper *inSnapper)
+{
+ Q_UNUSED(inSnapper);
+}
+
+CBaseStateRow *CSlideTimebarRow::GetBaseStateRow() const
+{
+ return m_SlideRow;
+}
+
+// This is not applicable to a SlideTimebarRow!!
+ISnappingListProvider &CSlideTimebarRow::GetSnappingListProvider() const
+{
+ throw;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.h b/src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.h
new file mode 100644
index 00000000..a2f63e33
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/SlideTimebarRow.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIME_CONTEXT_TIMEBAR_ROW_H
+#define INCLUDED_TIME_CONTEXT_TIMEBAR_ROW_H 1
+
+#pragma once
+
+#include "BaseTimebarlessRow.h"
+
+class CSlideRow;
+
+class CSlideTimebarRow : public CBaseTimebarlessRow
+{
+public:
+ CSlideTimebarRow(CSlideRow *inSlideRow);
+ virtual ~CSlideTimebarRow();
+
+ void CommitSelections() override;
+
+ void SelectKeysInRect(CRct inRect, bool inModifierKeyDown) override;
+ void SelectKeysByTime(long inTime, bool inSelected) override;
+ void SelectAllKeys() override;
+
+ void PopulateSnappingList(CSnapper *inSnappingList) override;
+ ISnappingListProvider &GetSnappingListProvider() const override;
+
+protected:
+ CBaseStateRow *GetBaseStateRow() const override;
+
+protected:
+ CSlideRow *m_SlideRow;
+};
+#endif // INCLUDED_TIME_CONTEXT_TIMEBAR_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/Snapper.cpp b/src/Authoring/Studio/Palettes/Timeline/Snapper.cpp
new file mode 100644
index 00000000..2b405e70
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Snapper.cpp
@@ -0,0 +1,455 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "Snapper.h"
+#include "StudioPreferences.h"
+#include "Control.h"
+#include "CoreUtils.h"
+#include "StudioUtils.h"
+#include "HotKeys.h"
+
+//=============================================================================
+/**
+ * Create a new snapper object.
+ * @param inTimeRatio the default time ratio.
+ */
+CSnapper::CSnapper(double inTimeRatio)
+ : m_theStartTime(0)
+ , m_theEndTime(0)
+ , m_TimeRatio(inTimeRatio)
+ , m_IsSnappingKeyframes(false)
+ , m_IsSnappingSelectedKeyframes(true)
+ , m_Offset(0)
+ , m_StartHeight(0)
+ , m_EndHeight(0)
+ , m_PeriodicInterval(LONG_MAX)
+ , m_InitialOffset(0)
+ , m_ObjectTimeOffset(0)
+ , m_TimeOffset(0)
+ , m_KeyFrameClicked(false)
+ , m_Source(nullptr)
+{
+ SetSnappingDistance(CStudioPreferences::GetSnapRange());
+}
+
+CSnapper::~CSnapper()
+{
+}
+//=============================================================================
+/**
+ * Set if keyframe is clicked
+ * @param inKeyFrameClicked toggles snapping to end handles at 1 pixel range,
+ * if true.
+ */
+void CSnapper::SetKeyFrameClicked(bool inKeyFrameClicked)
+{
+ m_KeyFrameClicked = inKeyFrameClicked;
+}
+//=============================================================================
+/**
+ * Clear all the snapping points from this.
+ * This effectively erases this object.
+ */
+void CSnapper::Clear()
+{
+ m_PeriodicInterval = LONG_MAX;
+ m_Times.clear();
+ m_KeyFrameClicked = false;
+ SetSnappingDistance(CStudioPreferences::GetSnapRange());
+}
+
+//=============================================================================
+/**
+ * Add a snapping point at the specified time.
+ * @param inTime the time to add the point at.
+ */
+void CSnapper::AddTime(long inTime)
+{
+ m_Times.insert(inTime);
+}
+
+//=============================================================================
+/**
+ * Add a snapping point at the specified pixel location.
+ * @param inPosition the position of the snapping point to add.
+ */
+void CSnapper::AddPixelLocation(long inPosition)
+{
+ AddTime(::PosToTime(inPosition, m_TimeRatio));
+}
+
+//=============================================================================
+/**
+ * Set whether or not keyframes should be added as snapping points.
+ * @param true if keyframes should be added as snapping points.
+ */
+void CSnapper::SetSnappingKeyframes(bool inIsSnappingKeyframes)
+{
+ m_IsSnappingKeyframes = inIsSnappingKeyframes;
+}
+
+//=============================================================================
+/**
+ * Checks whether or not keyframes are being snapped to.
+ * @return true if keyframes should be snapped to.
+ */
+bool CSnapper::IsSnappingKeyframes()
+{
+ return m_IsSnappingKeyframes;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not selected keyframes are being snapped to.
+ * This is used to ignore all selected keyframes when keyframes are being
+ * dragged.
+ * @param inIsSnappingSelectedKeyframes true if selected keys should be snapped.
+ */
+void CSnapper::SetSnappingSelectedKeyframes(bool inIsSnappingSelectedKeyframes)
+{
+ m_IsSnappingSelectedKeyframes = inIsSnappingSelectedKeyframes;
+}
+
+//=============================================================================
+/**
+ * Checks whether or not selected keyframes are being snapped to.
+ * This is used to ignore all selected keyframes when keyframes are being
+ * dragged.
+ * @return true if selected keyframes should be snapping points.
+ */
+bool CSnapper::IsSnappingSelectedKeyframes()
+{
+ return m_IsSnappingKeyframes && m_IsSnappingSelectedKeyframes;
+}
+
+//=============================================================================
+/**
+ * Set the current time ratio.
+ * This will effect all time based positions as well as the intervals. It is
+ * suggested that this is called on an empty snapper when possible for speed.
+ * @param inTimeRatio the new time ratio.
+ */
+void CSnapper::SetTimeRatio(double inTimeRatio)
+{
+ m_SnapDistance = ::dtol(m_SnapDistance * m_TimeRatio / inTimeRatio);
+ m_TimeRatio = inTimeRatio;
+}
+
+//=============================================================================
+/**
+ * Set the visible area of this snapper.
+ * This is used to limit snapping to visible areas only. The visibility limit
+ * is only on vertical because the user can scroll horizontally and expose
+ * previously non visible objects. The heights are relative to the initial
+ * offset and
+ * @param inStartHeight the minimum height for visibility.
+ * @param inEndHeight the maximum height for visibility.
+ */
+void CSnapper::SetVisibleArea(long inStartHeight, long inEndHeight)
+{
+ m_StartHeight = inStartHeight;
+ m_EndHeight = inEndHeight;
+}
+
+//=============================================================================
+/**
+ * Push an offset into this for calculating later visibilities.
+ * This is accumulated with previous offsets.
+ * @param inHeight the amount to modify the offset by.
+ */
+void CSnapper::PushOffset(long inHeight)
+{
+ m_Offsets.push_back(inHeight);
+ m_Offset += inHeight;
+}
+
+//=============================================================================
+/**
+ * Remove an offset that was pushed on.
+ * This will update the current offset to be what it was before the push.
+ */
+void CSnapper::PopOffset()
+{
+ m_Offset -= m_Offsets.back();
+ m_Offsets.pop_back();
+}
+
+//=============================================================================
+/**
+ * Checks to see if an object at inPosition of height inHeight is visible.
+ * This uses the current offset with the visible area to check visibility.
+ * @param inPosition the position of the object to be checked.
+ * @param inHeight the height of the object to be checked.
+ */
+bool CSnapper::IsVisible(long inPosition, long inHeight)
+{
+ return (inPosition + m_Offset < m_EndHeight
+ && inPosition + m_Offset + inHeight > m_StartHeight);
+}
+
+//=============================================================================
+/**
+ * Add a periodic interval to the snapping points.
+ * This will make snapping points at every multiple of inInterval. The interval
+ * starts at time 0.
+ * @param inInterval time in millis for the periodic points.
+ */
+void CSnapper::SetPeriodicInterval(long inInterval)
+{
+ m_PeriodicInterval = inInterval;
+}
+
+//=============================================================================
+/**
+ * Interpret the given position into a snapped/nonsnapped position.
+ * This will use the inFlags to determine whether or not this should be snapping
+ * and uses inPosition to figure out the closest snapping position. If the
+ * closest position is not within the tolerances then inPosition will be
+ * returned.
+ * @param inPosition to position to check for snapping.
+ * @param inFlags the mouse state flags, to determine whether or not snapping.
+ */
+bool CSnapper::InterpretTimeEx(long &ioTime, long inFlags)
+{
+ // Only snap if shift key is down.
+ if (inFlags & CHotKeys::MODIFIER_SHIFT)
+ return GetSnapTime(ioTime, true);
+ else
+ return GetSnapTime(ioTime, false);
+}
+
+//=============================================================================
+/**
+ * Interpret the given position into a snapped/nonsnapped position.
+ * This will use the inFlags to determine whether or not this should be snapping
+ * and uses inPosition to figure out the closest snapping position. If the
+ * closest position is not within the tolerances then inPosition will be
+ * returned.
+ * @param inPosition to position to check for snapping.
+ * @param inFlags the mouse state flags, to determine whether or not snapping.
+ */
+long CSnapper::InterpretTime(long inTime, long inFlags)
+{
+ if (inFlags & CHotKeys::MODIFIER_SHIFT) {
+ GetSnapTime(inTime, true);
+ return inTime;
+ }
+ GetSnapTime(inTime, false);
+ return inTime;
+}
+
+//=============================================================================
+/**
+ * Set the maximum distance that snapping will occur at.
+ * This sets the maximum tolerances for a position to be away from a snapping
+ * point and still get snapped to it.
+ * @param inSnapDistance the snap distance, in pixels.
+ */
+void CSnapper::SetSnappingDistance(long inSnapDistance)
+{
+ m_SnapDistance = ::dtol(inSnapDistance / m_TimeRatio);
+}
+
+//=============================================================================
+/**
+ * Helper method to find the closer of two values to a third.
+ * If both values are the same distance then the first value will be returned.
+ * @param inFirst the first value to check the distance to inBase.
+ * @param inSecond the second value to check the distance to inBase.
+ * @param inBase the value the others are being compared to.
+ * @return the value, either first or second, that is closest to inBase.
+ */
+long GetClosestValue(long inFirst, long inSecond, long inBase)
+{
+ return (::labs(inFirst - inBase) <= ::labs(inSecond - inBase)) ? inFirst : inSecond;
+}
+
+//=============================================================================
+/**
+ * Given the current time, it is adjusted if necessary to snap.
+ * @param ioTime the current time on input; on output the adjusted time
+ * @param inShiftKeyDown true if the shift key was down, otherwise false
+ * @return true if a snap occurred, otherwise false
+ */
+bool CSnapper::GetSnapTime(long &ioTime, bool inShiftKeyDown)
+{
+ bool theReturnValue = false;
+
+ if (inShiftKeyDown) // If user hits the shift key (i.e. snapping is toggled on)
+ {
+ long thePreviousTime = 0;
+ long theNextTime = 0;
+
+ // Go through all the snapping positions finding the positions on either
+ // side of ioPosition. Bsically just loop through until a snap position
+ // is larger than in position and use that with the previous value to get
+ // the closest snapping location.
+ TTimeList::iterator thePos = m_Times.begin();
+ for (; thePos != m_Times.end(); ++thePos) {
+ thePreviousTime = theNextTime;
+ theNextTime = (*thePos);
+
+ // Don't need to go any further because we've hit the first point larget than
+ // ioPosition.
+ if (theNextTime >= ioTime) {
+ break;
+ }
+ }
+
+ // Use the last snap position less than ioPosition and the first snap position greater than
+ // ioPosition
+ // to find the closest of the two.
+ long theClosestTime = GetClosestValue(thePreviousTime, theNextTime, ioTime);
+ long theClosestInterval = GetClosestPeriodicInterval(ioTime);
+
+ // Get the closest snapping position between the periodic interval and the position
+ theClosestTime = GetClosestValue(theClosestTime, theClosestInterval, ioTime);
+
+ // If the closest position is within tolerances then use it, otherwise return the original
+ // value.
+ if (::labs(theClosestTime - ioTime) <= m_SnapDistance) {
+ ioTime = theClosestTime;
+ theReturnValue = true;
+ }
+ } else // If user does not hit the shift key (i.e. snapping is toggled off)
+ {
+ // Snap to end handles at 1 pixel range if the current object dragged
+ // is a keyframe
+ if (m_KeyFrameClicked) {
+ // Returns if the startTime or the endTime of a Time Bar is closer to the dragged
+ // keyframe
+ long theClosestTime = GetClosestValue(m_theStartTime, m_theEndTime, ioTime);
+
+ // Set snapping range to 1 pixel and converts it to time.
+ // The snapping range of 1 pixel applies for keyframes that are dragged really
+ // close to the end handles.
+ long thePixel = 1;
+ long theTime = ::dtol(thePixel / m_TimeRatio);
+
+ // Determines if the closest time is within 1 pixel range
+ // If so returns the closest time, which is the snapping time, and true indicating
+ // that snapping occurs.
+ if (::labs(theClosestTime - ioTime) <= theTime) {
+ ioTime = theClosestTime;
+ theReturnValue = true;
+ }
+ }
+ }
+
+ return theReturnValue;
+}
+//=============================================================================
+/**
+ * Get the closest periodic interval to inPosition.
+ * Since it is too expensive to store every possible periodic interval in the
+ * snapping list, this just dynamically figures out the closest periodic
+ * interval.
+ */
+void CSnapper::SetStartEndTime(long theStartTime, long theEndTime)
+{
+ m_theStartTime = theStartTime;
+ m_theEndTime = theEndTime;
+}
+//=============================================================================
+/**
+ * Get the closest periodic interval to inPosition.
+ * Since it is too expensive to store every possible periodic interval in the
+ * snapping list, this just dynamically figures out the closest periodic
+ * interval.
+ */
+long CSnapper::GetClosestPeriodicInterval(long inTime)
+{
+ long theIntervalLow = inTime / m_PeriodicInterval * m_PeriodicInterval;
+ long theIntervalHigh = (inTime / m_PeriodicInterval + 1) * m_PeriodicInterval;
+
+ return GetClosestValue(theIntervalLow, theIntervalHigh, inTime);
+}
+
+//=============================================================================
+/**
+ * Used to pass off snapping logic to this for objects being dragged.
+ * This does all the work of an object when the object itself is being dragged
+ * and it's position is being modified by the drag, but it needs to be snapped
+ * as well. It is not necessary to call this unless ProcessDrag is being
+ * used.
+ * @param inClickPosition the mouse click location, usually just inPoint.x.
+ * @param inCenterOffset the center of the object where it should be snapped to.
+ */
+void CSnapper::BeginDrag(long inClickLocation, long inCenterTimeOffset)
+{
+ m_InitialOffset = inClickLocation;
+ m_ObjectTimeOffset = inCenterTimeOffset;
+}
+
+//=============================================================================
+/**
+ * Process an object's drag event and figure out where the object should be.
+ * This does all the work of figuring out where the object should be snapped
+ * to. It is not necessary to call this, but it may make implementing snapping
+ * much easier. BeginDrag needs to be called on OnMouseDown to use this.
+ * @param inPosition the position of the mouse, GetPosition( ).x + inPoint.x.
+ * @param inFlags the mouse state flags, used to determine snapping state.
+ */
+long CSnapper::ProcessDrag(long inTime, long inOffset, long inFlags)
+{
+ long theModPos = inTime + m_TimeOffset + ::dtol((inOffset - m_InitialOffset) / m_TimeRatio);
+ InterpretTimeEx(theModPos, inFlags);
+ theModPos -= m_TimeOffset;
+
+ return theModPos;
+}
+
+//=============================================================================
+/**
+ * Set the source for this Snapper object.
+ * This is so that objects may choose to no add themselves to snapping lists
+ * that they originated. This is only meant for comparison with the 'this' ptr.
+ * @param inSource the source object for this snapping list.
+ */
+void CSnapper::SetSource(void *inSource)
+{
+ m_Source = inSource;
+}
+
+//=============================================================================
+/**
+ * Get the source for this snapper object.
+ * @return the source of the snapping.
+ */
+void *CSnapper::GetSource()
+{
+ return m_Source;
+}
+
+void CSnapper::SetTimeOffset(long inTimeOffset)
+{
+ m_TimeOffset = inTimeOffset;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/Snapper.h b/src/Authoring/Studio/Palettes/Timeline/Snapper.h
new file mode 100644
index 00000000..ea230bc0
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/Snapper.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SNAPPER_H
+#define INCLUDED_SNAPPER_H 1
+
+#pragma once
+
+#include <set>
+#include <vector>
+
+class CSnapper
+{
+ typedef std::set<long> TTimeList;
+ typedef std::vector<long> TOffsetList;
+
+public:
+ CSnapper(double inTimeRatio = .1);
+ virtual ~CSnapper();
+
+ void AddTime(long inTime);
+ void AddPixelLocation(long inPixelLoc);
+
+ void SetSnappingKeyframes(bool inIsSnappingKeyframes);
+ bool IsSnappingKeyframes();
+ void SetSnappingSelectedKeyframes(bool inIsSnappingSelectedKeyframes);
+ bool IsSnappingSelectedKeyframes();
+
+ void Clear();
+
+ void SetVisibleArea(long inStartHeight, long inEndHeight);
+ void PushOffset(long inHeight);
+ void PopOffset();
+ bool IsVisible(long inPosition, long inHeight);
+
+ void SetTimeRatio(double inTimeRatio);
+
+ void SetPeriodicInterval(long inInterval);
+
+ bool InterpretTimeEx(long &ioTime, long inFlags);
+ long InterpretTime(long inTime, long inFlags);
+
+ void SetSnappingDistance(long inSnapDistance);
+
+ void BeginDrag(long inPosition, long inOffset = 0);
+ long ProcessDrag(long inTime, long inPosition, long inFlags);
+
+ void SetSource(void *inSource);
+ void *GetSource();
+
+ void SetTimeOffset(long inTimeOffset);
+ void SetStartEndTime(long theStartTime, long theEndTime);
+ void SetKeyFrameClicked(bool inKeyFrameClicked);
+
+protected:
+ bool GetSnapTime(long &inTime, bool inShiftKeyDown);
+ long GetClosestPeriodicInterval(long inTime);
+
+ long m_theStartTime;
+ long m_theEndTime;
+
+ TTimeList m_Times;
+ TOffsetList m_Offsets;
+
+ double m_TimeRatio;
+
+ bool m_IsSnappingKeyframes;
+ bool m_IsSnappingSelectedKeyframes;
+ long m_Offset;
+ long m_StartHeight;
+ long m_EndHeight;
+ long m_SnapDistance;
+
+ long m_PeriodicInterval;
+
+ long m_InitialOffset;
+ long m_ObjectTimeOffset;
+ long m_TimeOffset;
+ bool m_KeyFrameClicked;
+ void *m_Source;
+};
+
+// Interface that will provider the info for snapping logic in the timebars and keyframes
+class ISnappingListProvider
+{
+public:
+ virtual ~ISnappingListProvider() {}
+
+ virtual void PopulateSnappingList(CSnapper *inSnappingList) = 0;
+};
+
+#endif // INCLUDED_SNAPPER_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateRow.cpp b/src/Authoring/Studio/Palettes/Timeline/StateRow.cpp
new file mode 100644
index 00000000..bdc07a11
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateRow.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StateRow.h"
+#include "TimelineControl.h"
+#include "TimelineTimelineLayout.h"
+#include "ColorControl.h"
+#include "ToggleControl.h"
+#include "PropertyRow.h"
+#include "StateTimebarRow.h"
+#include "BaseTimebarlessRow.h"
+#include "BaseTimelineTreeControl.h"
+#include "Bindings/ITimelineItemBinding.h"
+
+//=============================================================================
+/**
+ * Creates a new CStateRow for the Asset.
+ * @param inParentRow the parent of this row.
+ */
+CStateRow::CStateRow(CBaseStateRow *inParentRow)
+{
+ m_ParentRow = inParentRow;
+}
+
+CStateRow::~CStateRow()
+{
+}
+
+CBlankToggleControl *CStateRow::CreateToggleControl()
+{
+ return (m_TimelineItemBinding->ShowToggleControls())
+ ? new CToggleControl(this, m_TimelineItemBinding)
+ : CBaseStateRow::CreateToggleControl();
+}
+
+//=============================================================================
+/**
+ * Create a new CStateTimebarRow.
+ * This is virtual and used for objects to return their type specific
+ * timebar rows if they want to.
+ * @return the created timebar row.
+ */
+CBaseTimebarlessRow *CStateRow::CreateTimebarRow()
+{
+ return new CStateTimebarRow(this);
+}
+
+//=============================================================================
+/**
+ * Initialize this object.
+ * This must be called after construction and may only be called once.
+ */
+void CStateRow::Initialize(ITimelineItemBinding *inTimelineItemBinding,
+ ISnappingListProvider *inProvider)
+{
+ CBaseStateRow::Initialize(inTimelineItemBinding);
+
+ // cache these numbers. I believe caching these numbers is to avoid having to incur expensive
+ // recursive calculations on ever draw.
+ CalculateActiveStartTime();
+ CalculateActiveEndTime();
+
+ SetSnappingListProvider(inProvider);
+
+ if (GetTimelineItem()->IsExpanded()) // this is stored for the current opened presentation and
+ // conveniently help you remember the last view before you
+ // switch slides.
+ Expand();
+ // sk - Delay loading till this is expanded. I think it makes more sense to not have to incur
+ // work till the UI needs to be displayed
+ // Plus it would not work now since the parent always needs to be 'fully' initialized for the
+ //SnappingListProvider, prior to any child creation.
+ // else
+ // LoadChildren( );
+}
+
+//=============================================================================
+/**
+ * Expand this node of the tree control.
+ * This will display all children the fit the filter.
+ */
+void CStateRow::Expand(bool inExpandAll /*= false*/, bool inExpandUp)
+{
+ // Only RecalcLayout if loaded children or expanded.
+ bool theDoRecalLayout = !m_Loaded;
+
+ if (!m_Loaded)
+ LoadChildren();
+
+ bool theWasExpanded = m_IsExpanded;
+ CBaseStateRow::Expand(inExpandAll, inExpandUp);
+ // Check if this is expanded
+ theDoRecalLayout |= (theWasExpanded != m_IsExpanded);
+ GetTimelineItem()->SetExpanded(
+ m_IsExpanded); // remember this setting so that it persist when this row is recreated
+
+ if (theDoRecalLayout)
+ DoTimelineRecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Collapse this node of the tree control.
+ * This will hide all children of this control.
+ */
+void CStateRow::Collapse(bool inCollapseAll /* = false */)
+{
+ bool theWasExpanded = m_IsExpanded;
+ CBaseStateRow::Collapse(inCollapseAll);
+
+ GetTimelineItem()->SetExpanded(
+ m_IsExpanded); // remember this setting so that it persist when this row is recreated
+ // only RecalcLayout if this is collapsed
+ if (theWasExpanded != m_IsExpanded)
+ DoTimelineRecalcLayout();
+}
+
+bool CStateRow::PerformFilter(const CFilter &inFilter)
+{
+ return inFilter.Filter(m_TimelineItemBinding->GetTimelineItem());
+}
+
+//=============================================================================
+/**
+ * Set the indent of this control.
+ * This controls how far to the right the toggle and text display on this
+ * control. The indent should be increased for every level of sub-controls.
+ * @param inIndent how much this control should be indented.
+ */
+void CStateRow::SetIndent(long inIndent)
+{
+ CTimelineRow::SetIndent(inIndent);
+
+ m_TreeControl->SetIndent(inIndent);
+
+ TStateRowList::iterator thePos = m_StateRows.begin();
+ for (; thePos != m_StateRows.end(); ++thePos)
+ (*thePos)->SetIndent(inIndent + CTimelineRow::TREE_INDENT);
+
+ // For each property on this object
+ TPropertyRowList::iterator thePropPos = m_PropertyRows.begin();
+ for (; thePropPos != m_PropertyRows.end(); ++thePropPos) {
+ CPropertyRow *thePropRow = (*thePropPos);
+ if (thePropRow)
+ thePropRow->SetIndent(inIndent + CTimelineRow::TREE_INDENT);
+ }
+}
+
+bool CStateRow::HasVisibleChildren()
+{
+ if (!m_Loaded) {
+ CTimelineItemOrderedIterator theChildren(m_TimelineItemBinding);
+ // Return true if has children but do not load the children.
+ if (!theChildren.IsDone()) {
+ return true;
+ }
+ CTimelineItemPropertyIterator theProperties(m_TimelineItemBinding);
+ if (!theProperties.IsDone()) {
+ return true;
+ }
+ }
+ return CBaseStateRow::HasVisibleChildren();
+}
+
+ISnappingListProvider *CStateRow::GetSnappingListProvider() const
+{
+ CStateTimebarRow *theTimebarControl = dynamic_cast<CStateTimebarRow *>(m_TimebarControl);
+ return (theTimebarControl) ? &theTimebarControl->GetSnappingListProvider() : nullptr;
+}
+
+void CStateRow::SetSnappingListProvider(ISnappingListProvider *inProvider)
+{
+ CStateTimebarRow *theTimebarControl = dynamic_cast<CStateTimebarRow *>(m_TimebarControl);
+ if (theTimebarControl)
+ theTimebarControl->SetSnappingListProvider(inProvider);
+}
+
+//=============================================================================
+/**
+ * Trigger any external applications where applicable.
+ */
+void CStateRow::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inPoint);
+ Q_UNUSED(inFlags);
+
+ if (!m_TimelineItemBinding
+ ->OpenAssociatedEditor()) // if not handled, fall backon the base class
+ CBaseStateRow::OnMouseDoubleClick(inPoint, inFlags);
+}
+
+void CStateRow::OnTimeChange()
+{
+ CalculateActiveStartTime();
+ CalculateActiveEndTime();
+
+ // sk - I don't see the need to DoTimelineRecalcLayout here, because that is usually when height
+ // of the control change
+ // this should just change width.. but maybe I am missing something, so I am leaving this
+ //here for 'easy' debugging
+ // DoTimelineRecalcLayout( );
+
+ m_TimebarControl->UpdateTime(GetStartTime(), GetEndTime());
+
+ GetTopControl()->OnLayoutChanged();
+}
+
+//=============================================================================
+/**
+ * calculate the active start time... this function set the active start to its
+ * parent's start time if it comes after the objects start time
+ */
+bool CStateRow::CalculateActiveStartTime()
+{
+ long theRetVal = GetStartTime();
+
+ if (m_ParentRow) {
+ if (m_ParentRow->CalculateActiveStartTime()) {
+ long theParentActiveStart = m_ParentRow->GetActiveStart();
+ if (theParentActiveStart > theRetVal)
+ theRetVal = theParentActiveStart;
+ }
+ }
+ m_ActiveStart = theRetVal;
+ return true;
+}
+
+//=============================================================================
+/**
+ * calculate the active end time... this function set the active end to its
+ * parent's end time if it comes before the objects end time
+ */
+bool CStateRow::CalculateActiveEndTime()
+{
+ long theRetVal = GetEndTime();
+ if (m_ParentRow) {
+ if (m_ParentRow->CalculateActiveEndTime()) {
+ long theParentActiveEnd = m_ParentRow->GetActiveEnd();
+ if (theParentActiveEnd < theRetVal)
+ theRetVal = theParentActiveEnd;
+ }
+ }
+ m_ActiveEnd = theRetVal;
+ return true;
+}
+
+//==============================================================================
+/**
+ *
+ */
+long CStateRow::GetLatestEndTime()
+{
+ if (m_IsExpanded) // if its children are not visible, they do not have any affect
+ return CBaseStateRow::GetLatestEndTime();
+
+ return GetActiveEnd();
+}
+
+//=============================================================================
+/**
+ * Load all the properties on this object.
+ */
+void CStateRow::LoadProperties()
+{
+ m_TimelineItemBinding->LoadProperties();
+}
+
+//==============================================================================
+/**
+ * Tells the timeline timeline layout to recalc its layout. Should only be called
+ * from this class, that's why it's protected.
+ */
+void CStateRow::DoTimelineRecalcLayout()
+{
+ GetTopControl()->OnLayoutChanged();
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateRow.h b/src/Authoring/Studio/Palettes/Timeline/StateRow.h
new file mode 100644
index 00000000..f03682e3
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateRow.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STATE_ROW_H
+#define INCLUDED_STATE_ROW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BaseStateRow.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CButtonControl;
+class CButtonDownListener;
+class CColorControl;
+class CStateTreeControl;
+class CToggleControl;
+class CStateTimebarlessRow;
+class CPropertyRow;
+class CCmdBatch;
+class CSnapper;
+class CResImage;
+
+class CStateRow : public CBaseStateRow
+{
+public:
+ CStateRow(CBaseStateRow *inParentRow);
+ virtual ~CStateRow();
+
+ using CBaseStateRow::Initialize;
+ virtual void Initialize(ITimelineItemBinding *inTimelineItemBinding,
+ ISnappingListProvider *inProvider);
+
+ void Expand(bool inExpandAll = false, bool inExpandUp = false) override;
+ void Collapse(bool inCollapseAll = false) override;
+ void SetIndent(long inIndent) override;
+ virtual void OnTimeChange();
+
+ long GetLatestEndTime() override;
+ bool CalculateActiveStartTime() override;
+ bool CalculateActiveEndTime() override;
+ bool HasVisibleChildren() override;
+ ISnappingListProvider *GetSnappingListProvider() const override;
+ void SetSnappingListProvider(ISnappingListProvider *inProvider) override;
+
+ // CControl
+ void OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+protected:
+ CBlankToggleControl *CreateToggleControl() override;
+ CBaseTimebarlessRow *CreateTimebarRow() override;
+
+ bool PerformFilter(const CFilter &inFilter) override;
+ void LoadProperties() override;
+ void DoTimelineRecalcLayout();
+};
+#endif // INCLUDED_STATE_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateRowFactory.cpp b/src/Authoring/Studio/Palettes/Timeline/StateRowFactory.cpp
new file mode 100644
index 00000000..921b4b04
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateRowFactory.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "StateRowFactory.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "StateRow.h"
+
+//=============================================================================
+/**
+ * Create the type specific StateRow for the Asset.
+ * Different asset use different derivations of StateRow, and this will
+ * return the proper state row for the asset.
+ * @param inTimelineItem the timeline item to create the state row for.
+ * @param inParentRow the parent row of the state row being created.
+ * @param inSnappingListProvider For keyframe/timebar snapping
+ * @return CStateRow the row that represents the state, or nullptr if it should not show up.
+ */
+CStateRow *CStateRowFactory::CreateStateRow(ITimelineItemBinding *inTimelineItem,
+ CBaseStateRow *inParentRow,
+ ISnappingListProvider *inSnappingListProvider)
+{
+ CStateRow *theRow = nullptr;
+ if (inTimelineItem) {
+ theRow = new CStateRow(inParentRow);
+
+ if (theRow != nullptr) {
+ theRow->Initialize(inTimelineItem, inSnappingListProvider);
+ }
+ }
+
+ return theRow;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateRowFactory.h b/src/Authoring/Studio/Palettes/Timeline/StateRowFactory.h
new file mode 100644
index 00000000..d818f4cd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateRowFactory.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STATE_ROW_FACTORY_H
+#define INCLUDED_STATE_ROW_FACTORY_H 1
+
+#pragma once
+
+class ITimelineItemBinding;
+class CStateRow;
+class CBaseStateRow;
+class ISnappingListProvider;
+
+class CStateRowFactory
+{
+protected:
+ CStateRowFactory();
+ virtual ~CStateRowFactory();
+
+public:
+ static CStateRow *CreateStateRow(ITimelineItemBinding *inTimelineItem, CBaseStateRow *inParent,
+ ISnappingListProvider *inSnappingListProvider);
+};
+#endif // INCLUDED_STATE_ROW_FACTORY_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.cpp b/src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.cpp
new file mode 100644
index 00000000..0a0ba258
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "StateTimebarRow.h"
+#include "Renderer.h"
+#include "StateRow.h"
+#include "StudioPreferences.h"
+#include "TimebarControl.h"
+#include "MasterP.h"
+#include "Snapper.h"
+#include "Bindings/ITimelineItemBinding.h"
+
+//=============================================================================
+/**
+ * Creates a new CStateTimebarRow for the StateRow.
+ * @param inStateRow the State Row that this is on.
+ * @param inCreateTimebar true if the constructor is responsible for creating a timebar, otherwise
+ * the derived class will take care of the construction.
+ *
+ */
+CStateTimebarRow::CStateTimebarRow(CStateRow *inStateRow, bool inCreateTimebar /*=true*/)
+ : CStateTimebarlessRow(inStateRow)
+ , m_Timebar(nullptr)
+{
+ if (inCreateTimebar) {
+ m_Timebar = new CTimebarControl(this, inStateRow->GetTimelineItemBinding());
+ m_Timebar->SetMinimumSize(CPt(0, CStudioPreferences::GetRowSize()));
+
+ AddChild(m_Timebar);
+ }
+}
+
+CStateTimebarRow::~CStateTimebarRow()
+{
+ delete m_Timebar;
+}
+
+//=============================================================================
+/**
+ * OnMouseRDown event, handles context menus for this object.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+bool CStateTimebarRow::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CStateTimebarlessRow::OnMouseRDown(inPoint, inFlags)) {
+ CPt theTimebarPoint = inPoint - m_Timebar->GetPosition();
+ m_Timebar->ShowContextMenu(theTimebarPoint, false);
+ }
+ return true;
+}
+
+//=============================================================================
+/**
+ * Set the amount of time that is being represented per pixel.
+ * @param inTimerPerPixel the amound of time being represented per pixel.
+ */
+void CStateTimebarRow::SetTimeRatio(double inTimeRatio)
+{
+ CStateTimebarlessRow::SetTimeRatio(inTimeRatio);
+
+ m_Timebar->SetTimeRatio(inTimeRatio);
+}
+
+//=============================================================================
+/**
+ * Notification that the object that this row is representing has been selected.
+ */
+void CStateTimebarRow::OnSelect()
+{
+ CStateTimebarlessRow::OnSelect();
+
+ m_Timebar->SetSelected(true);
+}
+
+//=============================================================================
+/**
+ * Notification that the object that this row is representing has been deselected.
+ */
+void CStateTimebarRow::OnDeselect()
+{
+ CStateTimebarlessRow::OnDeselect();
+
+ m_Timebar->SetSelected(false);
+}
+
+//=============================================================================
+/**
+ * Notification from the Asset that it's time has changed.
+ * @param inStartTime the new start time.
+ * @param inEndTime the new end time.
+ */
+void CStateTimebarRow::UpdateTime(long inStartTime, long inEndTime)
+{
+ m_Timebar->Refresh(inStartTime, inEndTime);
+ Invalidate();
+}
+
+void CStateTimebarRow::PopulateSnappingList(CSnapper *inSnappingList)
+{
+ if (inSnappingList->GetSource() != m_Timebar) {
+ inSnappingList->AddTime(m_Timebar->GetStartTime());
+ inSnappingList->AddTime(m_Timebar->GetEndTime());
+ }
+ m_Timebar->PopulateSnappingList(inSnappingList);
+ CStateTimebarlessRow::PopulateSnappingList(inSnappingList);
+}
+
+//=============================================================================
+/**
+ * called when meta data for this row is changed... should be overridden by the
+ * timebar row
+ */
+void CStateTimebarRow::RefreshRowMetaData()
+{
+ Invalidate();
+ m_Timebar->RefreshMetaData();
+}
+
+void CStateTimebarRow::SetSnappingListProvider(ISnappingListProvider *inProvider)
+{
+ m_Timebar->SetSnappingListProvider(inProvider);
+}
+
+ISnappingListProvider &CStateTimebarRow::GetSnappingListProvider() const
+{
+ return m_Timebar->GetSnappingListProvider();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.h b/src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.h
new file mode 100644
index 00000000..7b62e3fd
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateTimebarRow.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STATE_TIMEBAR_ROW_H
+#define INCLUDED_STATE_TIMEBAR_ROW_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "StateTimebarlessRow.h"
+
+class CStateRow;
+class CTimebarControl;
+class CSnapper;
+class ITimelineItemBinding;
+
+class CStateTimebarRow : public CStateTimebarlessRow
+{
+public:
+ CStateTimebarRow(CStateRow *inStateRow, bool inCreateTimebar = true);
+ virtual ~CStateTimebarRow();
+
+ // CControl
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void SetTimeRatio(double inTimeRatio) override;
+
+ void OnSelect() override;
+ void OnDeselect() override;
+ void UpdateTime(long inStartTime, long inEndTime) override;
+
+ void PopulateSnappingList(CSnapper *inSnappingList) override;
+ void RefreshRowMetaData() override;
+
+ void SetSnappingListProvider(ISnappingListProvider *inProvider);
+ ISnappingListProvider &GetSnappingListProvider() const override;
+
+protected:
+ CTimebarControl *m_Timebar;
+};
+#endif // INCLUDED_STATE_TIMEBAR_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.cpp b/src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.cpp
new file mode 100644
index 00000000..6eebd0c4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.cpp
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StateTimebarlessRow.h"
+#include "IKeyframe.h"
+#include "Renderer.h"
+#include "StateRow.h"
+#include "MasterP.h"
+#include "KeyframeContextMenu.h"
+#include "Snapper.h"
+#include "MultiSelectAspect.h"
+#include "PropertyTimebarRow.h"
+#include "PropertyRow.h"
+#include "AssetTimelineKeyframe.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "StudioUtils.h"
+
+//=============================================================================
+/**
+ * Creates a new CStateTimebarRow for the StateRow.
+ * @param inStateRow the State Row that this is on.
+ */
+CStateTimebarlessRow::CStateTimebarlessRow(CStateRow *inStateRow)
+ : m_StateRow(inStateRow)
+ , m_Selected(false)
+ , m_Refreshing(false)
+{
+ m_BackgroundColor = m_StateRow->GetTimebarBackgroundColor(m_StateRow->GetObjectType());
+}
+
+CStateTimebarlessRow::~CStateTimebarlessRow()
+{
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ CAssetTimelineKeyframe *theDeletedKey = (*thePos);
+ RemoveChild(theDeletedKey);
+ delete theDeletedKey;
+ }
+}
+
+void CStateTimebarlessRow::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation)
+{
+ CControl::OnDraw(inRenderer, inDirtyRect, inIgnoreValidation);
+}
+
+//=============================================================================
+/**
+ * Draws the this row background.
+ * @param inRenderer the renderer to draw to.
+ */
+void CStateTimebarlessRow::Draw(CRenderer *inRenderer)
+{
+ UICPROFILE(Draw);
+
+ if (m_DirtyFlag) {
+ RefreshKeyframes();
+ m_DirtyFlag = false;
+ }
+
+ CBaseTimebarlessRow::Draw(inRenderer);
+}
+
+//=============================================================================
+/**
+ * OnMouseRDown event, handles context menus for this object.
+ * @param inPoint the location of the mouse over this control.
+ * @param inFlags the mouse state flags.
+ */
+bool CStateTimebarlessRow::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_StateRow->Select(SBaseStateRowSelectionKeyState()); // ensure this is selected, but doesn't
+ // affect any key selections, because this
+ // can be triggered from a key being
+ // selected
+ return CControl::OnMouseRDown(inPoint, inFlags);
+}
+
+//=============================================================================
+/**
+ * Set the amount of time that is being represented per pixel.
+ * @param inTimerPerPixel the amound of time being represented per pixel.
+ */
+void CStateTimebarlessRow::SetTimeRatio(double inTimeRatio)
+{
+ CBaseTimebarlessRow::SetTimeRatio(inTimeRatio);
+
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ (*thePos)->SetTimeRatio(inTimeRatio);
+ }
+}
+
+//=============================================================================
+/**
+ * Get the state row that this belongs to.
+ */
+CStateRow *CStateTimebarlessRow::GetStateRow()
+{
+ return m_StateRow;
+}
+
+//=============================================================================
+/**
+ * Handler for when a child key is selected
+ *
+ * @param inTime time of the key
+ */
+void CStateTimebarlessRow::OnKeySelected(long inTime, bool inSelected,
+ bool inClearPreviouslySelectedKeys)
+{
+ ITimelineItemBinding *theTimelineItemBinding = m_StateRow->GetTimelineItemBinding();
+ if (inSelected)
+ theTimelineItemBinding->SetSelected(false);
+
+ if (inClearPreviouslySelectedKeys)
+ theTimelineItemBinding->ClearKeySelection();
+
+ theTimelineItemBinding->SelectKeyframes(inSelected, inTime);
+ RefreshKeyframes();
+ Invalidate();
+}
+
+CBaseStateRow *CStateTimebarlessRow::GetBaseStateRow() const
+{
+ return m_StateRow;
+}
+
+//=============================================================================
+/**
+ * Checks the data binding, instead of the property rows since they may not be created
+ * (delayed-loading) if this is not expanded.
+ */
+bool CStateTimebarlessRow::PropertiesHaveKeyframe(long inTime)
+{
+ bool theResult = false;
+
+ ITimelineItemBinding *theTimelineItemBinding = m_StateRow->GetTimelineItemBinding();
+ long theNumProps = theTimelineItemBinding->GetPropertyCount();
+ for (long theIndex = 0; theIndex < theNumProps; ++theIndex) {
+ ITimelineItemProperty *theProp = theTimelineItemBinding->GetProperty(theIndex);
+ if (theProp && theProp->GetKeyframeByTime(inTime)) {
+ theResult = true;
+ break;
+ }
+ }
+ return theResult;
+}
+
+//=============================================================================
+/**
+ * called when keyframes need to be updated, this funciton has two loops:
+ * the first loops through and deletes any keys no longer in the sskf list. the
+ * second adds any keys in the sskf list that are not already in the list
+ *
+ */
+void CStateTimebarlessRow::RefreshKeyframes()
+{
+ UICPROFILE(RefreshKeyframes);
+
+ m_Refreshing = true;
+
+ ITimelineItemBinding *theTimelineItemBinding = m_StateRow->GetTimelineItemBinding();
+ long theKeyframeCount = theTimelineItemBinding->GetKeyframeCount();
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+
+ // First Loop clears any keys that do not correlate to a supersetkey
+ while (thePos != m_Keyframes.end()) {
+ CAssetTimelineKeyframe *theTimelineKey = (*thePos);
+ IKeyframe *theTempKey = nullptr;
+ theTempKey = theTimelineItemBinding->GetKeyframeByTime(theTimelineKey->GetTime());
+
+ // If we find a key at this time, then the timeline key doesn't need to be deleted
+ if (!theTempKey || !PropertiesHaveKeyframe(theTimelineKey->GetTime())) {
+ RemoveChild(theTimelineKey);
+ delete theTimelineKey;
+ thePos = m_Keyframes.erase(thePos);
+ } else if (theTempKey->IsDynamic() != theTimelineKey->IsDynamic()) {
+ theTimelineKey->SetDynamic(theTempKey->IsDynamic());
+ } else {
+ // Set the position
+ theTimelineKey->SetPosition(::TimeToPos(theTempKey->GetTime(), m_TimeRatio)
+ - (theTimelineKey->GetSize().x / 2),
+ 0);
+ ++thePos;
+ }
+ }
+
+ // Second Loop adds the remaining keys
+ for (long theKey = 0; theKey < theKeyframeCount; ++theKey) {
+ bool theFoundFlag = false;
+ IKeyframe *theTempKey = theTimelineItemBinding->GetKeyframeByIndex(theKey);
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+
+ // each key needs to be compared to all the keys in the sskf list to see if it has to be
+ // added.
+ for (; thePos != m_Keyframes.end() && !theFoundFlag; ++thePos) {
+ CAssetTimelineKeyframe *theCurrentKey = (*thePos);
+ if (theCurrentKey->GetTime() == theTempKey->GetTime()) {
+ theFoundFlag = true;
+ }
+ }
+ if (!theFoundFlag && PropertiesHaveKeyframe(theTempKey->GetTime())) {
+ // If we don't have a timeline key, then we have to make a new one
+ CAssetTimelineKeyframe *theAssetTimelineKey =
+ new CAssetTimelineKeyframe(this, m_TimeRatio);
+ theAssetTimelineKey->SetTime(theTempKey->GetTime());
+ theAssetTimelineKey->Select(theTempKey->IsSelected());
+ theAssetTimelineKey->SetDynamic(theTempKey->IsDynamic());
+ theAssetTimelineKey->SetSize(CPt(17, 16));
+ theAssetTimelineKey->SetPosition(::TimeToPos(theTempKey->GetTime(), m_TimeRatio)
+ - (theAssetTimelineKey->GetSize().x / 2),
+ 0);
+ AddChild(theAssetTimelineKey);
+ m_Keyframes.push_back(theAssetTimelineKey);
+ }
+ }
+ m_Refreshing = false;
+}
+
+void CStateTimebarlessRow::Invalidate(bool inInvalidate)
+{
+ if (!m_Refreshing) {
+ CControl::Invalidate(inInvalidate);
+ }
+}
+
+//=============================================================================
+/**
+ * called when a list has a member change selection
+ * @param inTime -1 to affect all keyframes.
+ *
+ */
+void CStateTimebarlessRow::SelectKeysByTime(long inTime, bool inSelected)
+{
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+ bool theFoundFlag = false;
+ for (; thePos != m_Keyframes.end() && !theFoundFlag; ++thePos) {
+ CAssetTimelineKeyframe *theKey = (*thePos);
+ if (inTime == -1 || theKey->GetTime() == inTime) {
+ theKey->Select(inSelected);
+ theFoundFlag = (inTime != -1);
+ }
+ }
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * SelectKeysInRect: selects any keyframes inside the rect
+ *
+ * @param inRect the Rect to select the keyframes in
+ * @return NONE.
+ */
+void CStateTimebarlessRow::SelectKeysInRect(CRct inRect, bool inModifierKeyDown)
+{
+ CMultiSelectAspect<TTimelineAssetKeyframeList> theMultiSelectAspect(
+ m_Keyframes, m_StateRow->GetTimelineItemBinding());
+ theMultiSelectAspect.MultiSelect(inRect, inModifierKeyDown);
+}
+
+//=============================================================================
+/**
+ * CommitSelections: commits all the master keyframe selections by setting their
+ * previous selection state to the current selection state.
+ * This will prevent the current keyframe states from
+ *changing.
+ *
+ * @param NONE
+ * @return NONE
+ */
+
+void CStateTimebarlessRow::CommitSelections()
+{
+ CMultiSelectAspect<TTimelineAssetKeyframeList> theMultiSelectAspect(
+ m_Keyframes, m_StateRow->GetTimelineItemBinding());
+ theMultiSelectAspect.CommitSelections();
+}
+
+//=============================================================================
+/**
+ * true if there are selected keys on this object
+ */
+bool CStateTimebarlessRow::HasSelectedKeys()
+{
+ bool theRetVal = false;
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end() && !theRetVal; ++thePos) {
+ if ((*thePos)->IsSelected()) {
+ theRetVal = true;
+ }
+ }
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * selects all keys for this timebar row
+ */
+void CStateTimebarlessRow::SelectAllKeys()
+{
+ m_StateRow->GetTimelineItemBinding()->SelectKeyframes(true, -1);
+
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos)
+ (*thePos)->Select(true);
+
+ Invalidate();
+}
+
+//=============================================================================
+/**
+ * Populates the snapping list with any snapping points that may be on this.
+ * This will add the timebar ends, master keyframes to the snapping list, and
+ * time labels to the snapping list.
+ * @param inSnapper the snapper to add the points to.
+ */
+void CStateTimebarlessRow::PopulateSnappingList(CSnapper *inSnapper)
+{
+ // Only add points if this is not the object originating the snapping.
+ if (inSnapper->GetSource() != this) {
+ // Add Keyframes
+ TTimelineAssetKeyframeList::iterator thePos = m_Keyframes.begin();
+ for (; thePos != m_Keyframes.end(); ++thePos) {
+ if (inSnapper->IsSnappingSelectedKeyframes())
+ inSnapper->AddTime((*thePos)->GetTime());
+ else if (!(*thePos)->IsSelected())
+ inSnapper->AddTime((*thePos)->GetTime());
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.h b/src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.h
new file mode 100644
index 00000000..1812e365
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/StateTimebarlessRow.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STATE_TIMEBARLESS_ROW_H
+#define INCLUDED_STATE_TIMEBARLESS_ROW_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BaseTimebarlessRow.h"
+#include "DispatchListeners.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStateRow;
+class CSnapper;
+class CAssetTimelineKeyframe;
+class ITimelineItemBinding;
+
+class CStateTimebarlessRow : public CBaseTimebarlessRow
+{
+ typedef std::vector<CAssetTimelineKeyframe *> TTimelineAssetKeyframeList;
+
+public:
+ CStateTimebarlessRow(CStateRow *inStateRow);
+ virtual ~CStateTimebarlessRow();
+
+ void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation = false) override;
+ void Draw(CRenderer *inRenderer) override;
+
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void OnKeySelected(long inTime, bool inState, bool inClearPreviouslySelectedKeys);
+
+ void SetTimeRatio(double inTimeRatio) override;
+
+ virtual void RefreshKeyframes();
+ void Invalidate(bool inInvalidate = true) override;
+ void CommitSelections() override;
+ void SelectKeysInRect(CRct inRect, bool inModifierKeyDown) override;
+ void SelectAllKeys() override;
+ void SelectKeysByTime(long inTime, bool inSelected) override;
+ bool HasSelectedKeys();
+ CStateRow *GetStateRow();
+ void PopulateSnappingList(CSnapper *inSnapper) override;
+
+protected:
+ CBaseStateRow *GetBaseStateRow() const override;
+ bool PropertiesHaveKeyframe(long inTime);
+
+protected:
+ CStateRow *m_StateRow;
+ bool m_Selected;
+ TTimelineAssetKeyframeList m_Keyframes; ///<Master Keyframe list ( STL )
+ bool m_Refreshing;
+};
+#endif // INCLUDED_STATE_TIMEBARLESS_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.cpp b/src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.cpp
new file mode 100644
index 00000000..5ef32619
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "TimeEditAspect.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimeEditAspect::CTimeEditAspect()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimeEditAspect::~CTimeEditAspect()
+{
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.h b/src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.h
new file mode 100644
index 00000000..f8cf0599
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimeEditAspect.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIME_EDIT_ASPECT_H
+#define INCLUDED_TIME_EDIT_ASPECT_H 1
+
+#pragma once
+//==============================================================================
+// Prefix
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CTimeEditAspect: It contains cross-platform codes that handles the Time Edit
+ * processing for the the time edit dialog box in Mac and Win
+ */
+//==============================================================================
+class CTimeEditAspect
+{
+protected:
+public:
+ CTimeEditAspect();
+ ~CTimeEditAspect();
+};
+#endif // INCLUDED_TIME_EDIT_ASPECT_H \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimeMeasure.cpp b/src/Authoring/Studio/Palettes/Timeline/TimeMeasure.cpp
new file mode 100644
index 00000000..9735499a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimeMeasure.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "TimeMeasure.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "StudioUtils.h"
+#include "TimelineTimelineLayout.h"
+#include "Snapper.h"
+#include "UICDMSignals.h"
+
+const long AUTO_TICK_AMNT = 60;
+using namespace Q3DStudio;
+
+//=============================================================================
+/**
+ * Create a new time measure.
+ * @param inLayout the layout this is representing, used for modifying time.
+ * @param inTimeRatio the current time ratio.
+ * @param inIsTransparent true if the background of this control should not be drawn.
+ */
+CTimeMeasure::CTimeMeasure(CTimelineTimelineLayout *inLayout, double inTimeRatio,
+ bool inFillBackground /*= true */)
+ : CBaseMeasure(inTimeRatio, inFillBackground)
+ , m_ScrollDir(0)
+ , m_TimePerPixel(0)
+ , m_IsMouseDown(false)
+ , m_TimelineLayout(inLayout)
+{
+ SetTimeRatio(inTimeRatio);
+ SetName("TimeMeasure");
+
+ m_EdgeMargin = 2;
+ // the large tickmark is shorter than the medium to leave room for the text
+ m_LargeHashOffset = 5;
+}
+
+CTimeMeasure::~CTimeMeasure()
+{
+}
+
+//=============================================================================
+/**
+ * Set the amount of time that is represented for each pixel.
+ * @param inTimePerPixel the amount of time represented for each pixel.
+ */
+void CTimeMeasure::SetTimeRatio(double inTimeRatio)
+{
+ m_Ratio = inTimeRatio;
+
+ double theTimePerPixel = (double)(1 / inTimeRatio);
+
+ // Only go through this if it has actually changed
+ if (theTimePerPixel != m_TimePerPixel) {
+ m_TimePerPixel = theTimePerPixel;
+
+ // Go through the possible hash settings and find the one that best suits the
+ // time per pixel.
+ double theMillisPerLargeHash = theTimePerPixel * 50;
+ if (theMillisPerLargeHash <= 100) // 100ms
+ theMillisPerLargeHash = 100;
+ else if (theMillisPerLargeHash <= 200) // 200ms
+ theMillisPerLargeHash = 200;
+ else if (theMillisPerLargeHash <= 500) // .5s
+ theMillisPerLargeHash = 500;
+ else if (theMillisPerLargeHash <= 1000) // 1s
+ theMillisPerLargeHash = 1000;
+ else if (theMillisPerLargeHash <= 2000) // 2s
+ theMillisPerLargeHash = 2000;
+ else if (theMillisPerLargeHash <= 5000) // 5s
+ theMillisPerLargeHash = 5000;
+ else if (theMillisPerLargeHash <= 10000) // 10s
+ theMillisPerLargeHash = 10000;
+ else if (theMillisPerLargeHash <= 20000) // 20s
+ theMillisPerLargeHash = 20000;
+ else if (theMillisPerLargeHash <= 30000) // 30s
+ theMillisPerLargeHash = 30000;
+ else if (theMillisPerLargeHash <= 60000) // 1m
+ theMillisPerLargeHash = 60000;
+ else if (theMillisPerLargeHash <= 120000) // 2m
+ theMillisPerLargeHash = 120000;
+ else if (theMillisPerLargeHash <= 300000) // 5m
+ theMillisPerLargeHash = 300000;
+ else if (theMillisPerLargeHash <= 600000) // 10m
+ theMillisPerLargeHash = 600000;
+ else if (theMillisPerLargeHash <= 1200000) // 20m
+ theMillisPerLargeHash = 1200000;
+ else if (theMillisPerLargeHash <= 1800000) // 30m
+ theMillisPerLargeHash = 1800000;
+ else if (theMillisPerLargeHash <= 3600000) // 1h
+ theMillisPerLargeHash = 3600000;
+ else
+ theMillisPerLargeHash = 7200000; // 2h
+
+ // Set the distances between the hashes
+ m_LargeHashInterval = theMillisPerLargeHash;
+ m_MediumHashInterval = theMillisPerLargeHash / 2;
+ m_SmallHashInterval = theMillisPerLargeHash / 10;
+
+ // update to StudioPreferences so that the ',' '.' and '<' '>' keys would respond
+ // accordingly
+ CStudioPreferences::SetTimeAdvanceAmount(static_cast<long>(m_SmallHashInterval));
+ CStudioPreferences::SetBigTimeAdvanceAmount(static_cast<long>(m_MediumHashInterval));
+
+ Invalidate();
+ }
+}
+//=============================================================================
+/**
+ * Get the time formatted as a string.
+ * This will figure out the best way to display the time and return it as a
+ * string.
+ * @param inTime the time to display in milliseconds.
+ * @return the time formatted in a string.
+ */
+Q3DStudio::CString CTimeMeasure::FormatTime(long inTime)
+{
+ long theHours = inTime / 3600000;
+ long theMinutes = inTime % 3600000 / 60000;
+ long theSeconds = inTime % 60000 / 1000;
+ long theMillis = inTime % 1000;
+
+ bool theHoursOnlyFlag = theHours != 0 && theMinutes == 0 && theSeconds == 0 && theMillis == 0;
+ bool theMinutesOnlyFlag =
+ !theHoursOnlyFlag && theMinutes != 0 && theSeconds == 0 && theMillis == 0;
+ bool theSecondsOnlyFlag = !theMinutesOnlyFlag && theMillis == 0;
+
+ Q3DStudio::CString theTime;
+ // If only hours are being displayed then format it as hours.
+ if (theHoursOnlyFlag) {
+ theTime.Format(_UIC("%dh"), theHours);
+ }
+ // If only minutes are being displayed then format it as minutes.
+ else if (theMinutesOnlyFlag) {
+ theTime.Format(_UIC("%dm"), theMinutes);
+ }
+ // If only seconds are being displayed then format as seconds
+ else if (theSecondsOnlyFlag) {
+ theTime.Format(_UIC("%ds"), theSeconds);
+ }
+ // If the intervals are correct then this should only be tenths of seconds, so do that.
+ else {
+ theTime.Format(_UIC("0.%ds"), theMillis / 100);
+ }
+
+ return theTime;
+}
+
+//=============================================================================
+/**
+ * Set the amount of time that this time measure is offset by.
+ * @param inTimeOffset the offset time in milliseconds.
+ */
+void CTimeMeasure::SetTimeOffset(long inTimeOffset)
+{
+ if (inTimeOffset != m_Offset) {
+ m_Offset = inTimeOffset;
+
+ Invalidate();
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the left mouse button was clicked.
+ * This tells the timeline to move the playhead to the current loc.
+ * @param inPoint the location where the mouse was clicked.
+ * @param inFlags the state of the mouse.
+ */
+bool CTimeMeasure::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_IsMouseDown = true;
+
+ m_TimelineLayout->OnTimeMeasureMouseDown(inPoint, inFlags);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse is moving over this control.
+ * If the mouse was clicked on this control this will drag the playhead.
+ * @param inPoint the location where the mouse was clicked.
+ * @param inFlags the state of the mouse.
+ */
+void CTimeMeasure::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+
+ // subtract out the button width since the playhead is never allowed into that area on the right
+ // side
+ // of the timeline and use it for the initial autoscrolling place
+ if (inPoint.x > 0 && inPoint.x <= GetSize().x - CStudioPreferences::GetDefaultButtonWidth()) {
+ CControl::OnMouseMove(inPoint, inFlags);
+ if (m_IsMouseDown)
+ m_TimelineLayout->OnTimeMeasureMouseDown(inPoint, inFlags);
+ m_ScrollDir = 0;
+ } else if (m_IsMouseDown) {
+ if (inPoint.x < 0)
+ m_ScrollDir = -1;
+ else if (inPoint.x > GetSize().x - CStudioPreferences::GetDefaultButtonWidth())
+ m_ScrollDir = 1;
+ m_TimerConnection = ITickTock::GetInstance().AddTimer(
+ 150, true, std::bind(&CTimeMeasure::OnTimer, this), "CTimeMeasure::OnMouseMove");
+ OnTimer();
+ }
+}
+
+//=============================================================================
+/**
+ * Call back for the timer that was set in on mouse move
+ */
+void CTimeMeasure::OnTimer()
+{
+ CPt theOffset;
+ if (m_ScrollDir > 0)
+ theOffset.x =
+ GetSize().x - 2 * CStudioPreferences::GetDefaultButtonWidth() + AUTO_TICK_AMNT;
+ else if (m_ScrollDir < 0)
+ theOffset.x = -AUTO_TICK_AMNT;
+ m_TimelineLayout->OnTimeMeasureMouseDown(theOffset, 0);
+ ;
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse was unclicked.
+ * This stops dragging of the playhead if it was dragging it.
+ * @param inPoint the location where the mouse was unclicked.
+ * @param inFlags the state of the mouse.
+ */
+void CTimeMeasure::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+ m_IsMouseDown = false;
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse was unclicked.
+ * This stops dragging of the playhead if it was dragging it.
+ * @param inPoint the location where the mouse was unclicked.
+ * @param inFlags the state of the mouse.
+ */
+void CTimeMeasure::OnMouseRUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+ m_IsMouseDown = false;
+}
+
+//=============================================================================
+/**
+ * Add the tick marks to the snapping list.
+ * This uses the user preference for the tick marks and adds them.
+ */
+void CTimeMeasure::PopulateSnappingList(CSnapper *inSnapper)
+{
+ // Only if this is supposed to snap to time markers.
+ if (CStudioPreferences::IsTimelineSnappingGridActive()) {
+ // Check the resolution to snap to
+ ESnapGridResolution theResolution = CStudioPreferences::GetTimelineSnappingGridResolution();
+ double thePeriodicInterval;
+ if (theResolution == SNAPGRID_TICKMARKS) {
+ thePeriodicInterval = m_SmallHashInterval;
+ } else if (theResolution == SNAPGRID_HALFSECONDS) {
+ thePeriodicInterval = m_MediumHashInterval;
+ } else {
+ thePeriodicInterval = m_LargeHashInterval;
+ }
+
+ // Set a periodic interval for snapping
+ inSnapper->SetPeriodicInterval(::dtol(thePeriodicInterval));
+ }
+}
+
+void CTimeMeasure::OnLoseFocus()
+{
+ m_TimerConnection = std::shared_ptr<UICDM::ISignalConnection>();
+ m_IsMouseDown = false;
+}
+
+//=============================================================================
+/**
+ * Draw the time at the specified position.
+ * @param inRenderer the renderer to draw to.
+ * @param inPosition the position to draw the time to, the time will be centered here.
+ * @param inTime the time to draw.
+ */
+void CTimeMeasure::DrawMeasureText(CRenderer *inRenderer, long inPosition, long inMeasure)
+{
+ Q3DStudio::CString theTimeFormat(FormatTime(inMeasure));
+ // Offset the position by half the text size to center it over the hash.
+ const auto textSize = inRenderer->GetTextSize(theTimeFormat.toQString());
+ inPosition -= ::dtol(textSize.width() / 2);
+
+ inRenderer->DrawText((float)inPosition, -3, theTimeFormat.toQString(),
+ QRect(0, 0, GetSize().x, GetSize().y),
+ CStudioPreferences::GetRulerTickColor().getQColor());
+}
+
+//=============================================================================
+/**
+ * Calculate the position of a time value on the time measure
+ */
+long CTimeMeasure::CalculatePos(double inNewValue)
+{
+ return ::TimeToPos(inNewValue, m_Ratio);
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimeMeasure.h b/src/Authoring/Studio/Palettes/Timeline/TimeMeasure.h
new file mode 100644
index 00000000..7e72a52c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimeMeasure.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIME_MEASURE_H
+#define INCLUDED_TIME_MEASURE_H 1
+
+#pragma once
+
+#include "BaseMeasure.h"
+#include "ITickTock.h"
+
+class CTimelineTimelineLayout;
+class CSnapper;
+
+class CTimeMeasure : public CBaseMeasure
+{
+public:
+ CTimeMeasure(CTimelineTimelineLayout *inLayout, double inTimeRatio,
+ bool inFillBackground = true);
+ virtual ~CTimeMeasure();
+
+ void SetTimeRatio(double inTimeRatio);
+ void SetTimeOffset(long inTimeOffset);
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseRUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ void PopulateSnappingList(CSnapper *inSnapper);
+
+ virtual void OnTimer();
+ void OnLoseFocus() override;
+
+protected:
+ // CBaseMeasure
+ void DrawMeasureText(CRenderer *inRenderer, long inPosition, long inMeasure) override;
+ long CalculatePos(double inNewValue) override;
+
+ Q3DStudio::CString FormatTime(long inTime);
+
+ long m_ScrollDir;
+ double m_TimePerPixel;
+ bool m_IsMouseDown;
+ CTimelineTimelineLayout *m_TimelineLayout;
+ std::shared_ptr<UICDM::ISignalConnection> m_TimerConnection;
+};
+#endif // INCLUDED_TIME_MEASURE_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimeToolbar.cpp b/src/Authoring/Studio/Palettes/Timeline/TimeToolbar.cpp
new file mode 100644
index 00000000..639e61d2
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimeToolbar.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TimeToolbar.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "BlankControl.h"
+#include "IDoc.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimeToolbar::CTimeToolbar(IDoc *inDoc)
+{
+ m_Doc = inDoc;
+ m_TimeEdit = new CTimeEdit(inDoc);
+ m_Color = CStudioPreferences::GetBaseColor();
+ m_TimeEdit->SetBackgroundColor(m_Color);
+ AddChild(m_TimeEdit);
+
+ m_TimeEdit->AddTimeChangeListener(this);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimeToolbar::~CTimeToolbar()
+{
+ delete m_TimeEdit;
+}
+
+//=============================================================================
+/**
+ * Fills in the background color for this layout.
+ */
+void CTimeToolbar::Draw(CRenderer *inRenderer)
+{
+ // Fill in the background color and draw the child controls
+
+ // Draw the shadow lines at the top and bottom of the layout
+ CRct theRect(GetSize());
+ inRenderer->FillSolidRect(theRect, m_Color);
+
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(theRect.size.x, 0));
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theRect.size.y - 2));
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 2));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 2));
+ inRenderer->PopPen();
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y - 1));
+ inRenderer->LineTo(CPt(theRect.size.x, theRect.size.y - 1));
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * Override of Control's set size to reposition the TimeEdit.
+ * @param inSize the new size.
+ */
+void CTimeToolbar::SetSize(CPt inSize)
+{
+ m_TimeEdit->SetSize(CPt(m_TimeEdit->GetWidth(), inSize.y - 4));
+ m_TimeEdit->SetPosition(inSize.x - m_TimeEdit->GetWidth(), 2);
+
+ CControl::SetSize(inSize);
+}
+
+//=============================================================================
+/**
+ * Call from the TimelineView (or thereabouts) that the scene time changed.
+ * @param inTime the new time.
+ */
+void CTimeToolbar::SetTime(long inTime)
+{
+ m_TimeEdit->SetTime(inTime);
+}
+//=============================================================================
+/**
+ * Returns the playhead time
+ */
+long CTimeToolbar::GetTime()
+{
+ return m_TimeEdit->GetTime();
+}
+
+//=============================================================================
+/**
+ * Callback from the TimeEdit that it's time was manually changed.
+ * @param inNewTime the new time.
+ */
+void CTimeToolbar::OnTimeChanged(long inNewTime)
+{
+ m_Doc->NotifyTimeChanged(inNewTime);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimeToolbar.h b/src/Authoring/Studio/Palettes/Timeline/TimeToolbar.h
new file mode 100644
index 00000000..c1ed948d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimeToolbar.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TIME_TOOLBAR_H
+#define INCLUDED_TIME_TOOLBAR_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TimeEdit.h"
+#include "Control.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+class IDoc;
+
+//=============================================================================
+/**
+ * Control at the top of the time display and a header for the toggle column.
+ */
+class CTimeToolbar : public CControl, public CTimeEditChangeListener
+{
+public:
+ CTimeToolbar(IDoc *inDoc);
+ virtual ~CTimeToolbar();
+ void Draw(CRenderer *inRenderer) override;
+
+ void SetSize(CPt inSize) override;
+ void SetTime(long inTime);
+ virtual long GetTime();
+
+ void OnTimeChanged(long inNewTime) override;
+
+protected:
+ CTimeEdit *m_TimeEdit;
+ IDoc *m_Doc;
+ CColor m_Color;
+};
+
+#endif // INCLUDED_TIME_TOOLBAR_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimebarControl.cpp b/src/Authoring/Studio/Palettes/Timeline/TimebarControl.cpp
new file mode 100644
index 00000000..af0084aa
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimebarControl.cpp
@@ -0,0 +1,690 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "TimebarControl.h"
+#include "StateTimebarRow.h"
+#include "StateRow.h"
+#include "Renderer.h"
+#include "ColorControl.h"
+#include "StudioPreferences.h"
+#include "Views.h"
+#include "TimelineControl.h"
+#include "TimelineTimelineLayout.h"
+#include "ResourceCache.h"
+#include "HotKeys.h"
+#include "Preferences.h"
+#include "Bindings/ITimelineItemBinding.h"
+#include "Bindings/ITimelineTimebar.h"
+#include "StudioApp.h"
+#include "Core.h"
+#include "Doc.h"
+#include "CoreUtils.h"
+#include "StudioUtils.h"
+#include "MasterP.h"
+
+const float SCALING_FACTOR = 0.50;
+
+//=============================================================================
+/**
+ * Create a timebar control on the specified state timebar row.
+ * Attaches a new ToolTip to it that displays the time range this timebar control
+ * encompasses.
+ * @param inRow the row on which this timebar is attached.
+ */
+CTimebarControl::CTimebarControl(CStateTimebarRow *inRow,
+ ITimelineItemBinding *inTimelineItemBinding)
+ : m_IsSelected(false)
+ , m_IsMouseDown(false)
+ , m_MaybeDragStart(false)
+ , m_LeftLeftTip(this, true)
+ , m_LeftTip(this, true)
+ , m_RightTip(this, false)
+ , m_RightRightTip(this, false)
+ , m_SnappingListProvider(nullptr)
+{
+ m_TimebarRow = inRow;
+ m_TimelineItemBinding = inTimelineItemBinding;
+ // Start/End times
+ ITimelineTimebar *theTimelineTimebar = GetTimebar();
+ m_StartTime = theTimelineTimebar->GetStartTime();
+ m_EndTime = theTimelineTimebar->GetEndTime();
+ bool theShowHandleBars = theTimelineTimebar->ShowHandleBars();
+ m_LeftLeftTip.ShowHandles(theShowHandleBars);
+ m_RightRightTip.ShowHandles(theShowHandleBars);
+
+ m_LeftLeftTip.SetSize(CStudioPreferences::GetTimebarTipSize(),
+ CStudioPreferences::GetRowSize());
+ m_LeftTip.SetPosition(CPt(0, 0));
+ m_LeftTip.SetSize(CStudioPreferences::GetTimebarInnerTipSize(),
+ CStudioPreferences::GetRowSize());
+ m_LeftTip.SetPosition(CPt(m_LeftLeftTip.GetSize().x, 0));
+
+ m_RightTip.SetSize(CStudioPreferences::GetTimebarInnerTipSize(),
+ CStudioPreferences::GetRowSize());
+ m_RightRightTip.SetSize(CStudioPreferences::GetTimebarTipSize(),
+ CStudioPreferences::GetRowSize());
+
+ m_EditControl = new CCommentEdit(theTimelineTimebar);
+ m_EditControl->SetPosition(CStudioPreferences::GetTimebarTipSize() * 2, 1);
+ m_EditControl->SetSize(CPt(100, 15));
+ m_EditControl->SetFillBackground(false);
+ AddChild(m_EditControl);
+ AddChild(&m_LeftTip);
+ AddChild(&m_RightTip);
+ AddChild(&m_RightRightTip);
+ AddChild(&m_LeftLeftTip);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimebarControl::~CTimebarControl()
+{
+ delete m_EditControl;
+}
+
+//=============================================================================
+/**
+ * Draw this timebar control to the renderer.
+ * @param inRenderer the renderer to draw to.
+ */
+void CTimebarControl::Draw(CRenderer *inRenderer)
+{
+ CStateRow *theRow = m_TimebarRow->GetStateRow();
+ CRct theRect(GetSize());
+
+ ::CColor theNormalColor = GetTimebar()->GetTimebarColor();
+ ::CColor theSelectedColor = CColorControl::CalculateSelectedColor(theNormalColor);
+
+ ::CColor theBorderColor = CStudioPreferences::GetTimeBarBorderColor();
+ ::CColor theDarkExtendedColor = CStudioPreferences::GetExtendedObjectDarkColor();
+ ::CColor theLightExtendedColor = CStudioPreferences::GetExtendedObjectLightColor();
+
+ long theTipOffset = CStudioPreferences::GetTimebarTipSize();
+
+ if (!IsEnabled()) {
+ theNormalColor = CStudioPreferences::GetLockedTimebarColor();
+ theBorderColor = CStudioPreferences::GetLockedBorderColor();
+ theDarkExtendedColor = CStudioPreferences::GetExtendedLockedDarkColor();
+ theLightExtendedColor = CStudioPreferences::GetExtendedLockedLightColor();
+ }
+
+ // Calculate the start/end/activestart
+ long theObjectLifeStart = ::TimeToPos(m_StartTime, m_TimeRatio);
+ long theStartPos = ::TimeToPos(theRow->GetActiveStart(), m_TimeRatio) - theObjectLifeStart;
+ long theEndPos = ::TimeToPos(theRow->GetActiveEnd(), m_TimeRatio) - theObjectLifeStart;
+ long theObjectLifeEnd = ::TimeToPos(m_EndTime, m_TimeRatio) - theObjectLifeStart;
+
+ CRct theGradientRct(theStartPos + theTipOffset, 0, theEndPos - theStartPos, theRect.size.y - 1);
+
+ if (theEndPos > theStartPos) {
+ inRenderer->DrawGradientBitmap(theGradientRct, theNormalColor, 0, SCALING_FACTOR);
+ // Calculate the gradient rect a bit differently depending on selection
+ if (m_IsSelected) {
+ CRct theSelectedRct(CPt(theGradientRct.position.x, theGradientRct.position.y + 3),
+ CPt(theGradientRct.size.x, theGradientRct.size.y - 7));
+ inRenderer->FillSolidRect(theSelectedRct, theSelectedColor);
+ }
+ }
+
+ inRenderer->PushPen(theBorderColor);
+ // Check to see if we need some hashes at the end
+ if (theObjectLifeEnd > theEndPos) {
+ long theUpdatedStartTime = theEndPos;
+ if (theStartPos > theUpdatedStartTime)
+ theUpdatedStartTime = theStartPos;
+ else {
+ inRenderer->MoveTo(theEndPos + theTipOffset, 0);
+ inRenderer->LineTo(theEndPos + theTipOffset, theRect.size.y - 1);
+ }
+ CRct theClippingRect(CPt(theUpdatedStartTime + theTipOffset + 1, 0),
+ CPt(theObjectLifeEnd - theUpdatedStartTime - 1, theRect.size.y - 1));
+ inRenderer->PushClippingRect(theClippingRect);
+
+ // Draw the hashed background
+ DrawHashedBackgroundX(inRenderer, theDarkExtendedColor, theLightExtendedColor,
+ theClippingRect);
+ inRenderer->PopClippingRect();
+ }
+
+ // Check to see if we need some hashes at the beginning
+ if (theStartPos > 0) {
+ long theUpdatedEndTime = theStartPos;
+ if (theObjectLifeEnd < theUpdatedEndTime)
+ theUpdatedEndTime = theObjectLifeEnd;
+ else {
+ inRenderer->MoveTo(theStartPos + theTipOffset, 0);
+ inRenderer->LineTo(theStartPos + theTipOffset, theRect.size.y - 1);
+ }
+ CRct theClippingRect(CPt(theTipOffset, 0), CPt(theUpdatedEndTime, theRect.size.y - 1));
+ inRenderer->PushClippingRect(theClippingRect);
+
+ // Draw the hashed background
+ DrawHashedBackgroundX(inRenderer, theDarkExtendedColor, theLightExtendedColor,
+ theClippingRect);
+ inRenderer->PopClippingRect();
+ }
+
+ // Draw the border stuff
+ inRenderer->MoveTo(CPt(theTipOffset, 0));
+ inRenderer->LineTo(CPt(theTipOffset, theRect.size.y - 1));
+ inRenderer->MoveTo(CPt(theObjectLifeEnd + theTipOffset, 0));
+ inRenderer->LineTo(CPt(theObjectLifeEnd + theTipOffset, theRect.size.y - 1));
+
+ inRenderer->PopPen();
+ // Setting the position with the active time
+ m_EditControl->SetPosition(CStudioPreferences::GetTimebarTipSize() * 2, 1);
+}
+
+//=============================================================================
+/**
+ * Draws a hashed background in a given clipping rect
+ *
+ * @param inStartX the x position to start from
+ * @param inSizeY the y size the you want the lines to range from
+ * @param inEndX one after the last place where lines can be drawn from
+ * @inRenderer the renderer to draw to
+ * @param inFirstColor the first hash color
+ * @param inSecondColor the second hash color
+ * @para inRect the clipping rect
+ */
+void CTimebarControl::DrawHashedBackgroundX(CRenderer *inRenderer, ::CColor inFirstColor,
+ ::CColor inSecondColor, CRct inRect)
+{
+ inRenderer->FillSolidRect(inRect, inFirstColor);
+ if (m_IsSelected) {
+ CRct theSelectedRct(CPt(inRect.position.x, inRect.position.y + 4),
+ CPt(inRect.size.x, inRect.size.y - 8));
+ inRenderer->FillSolidRect(
+ theSelectedRct, CColorControl::CalculateSelectedColor(GetTimebar()->GetTimebarColor()));
+ }
+
+ inRenderer->FillHashed(inRect, inSecondColor);
+}
+
+//=============================================================================
+/**
+ * Set the current time ratio.
+ * The time ratio controls the length of this control and is the ratio of
+ * pixels to milliseconds.
+ * @param inTimeRatio the new time ratio.
+ */
+void CTimebarControl::SetTimeRatio(double inTimeRatio)
+{
+ m_TimeRatio = inTimeRatio;
+
+ Refresh();
+}
+
+//=============================================================================
+/**
+ * Set the size of this control.
+ * @param inSize the new size of this control.
+ */
+void CTimebarControl::SetSize(CPt inSize)
+{
+ CControl::SetSize(CPt(inSize.x, inSize.y));
+
+ CStateRow *theRow = m_TimebarRow->GetStateRow();
+ long theTipSize =
+ CStudioPreferences::GetTimebarTipSize() + CStudioPreferences::GetTimebarInnerTipSize();
+ long theCommentSize = CStudioPreferences::GetDefaultCommentSize();
+ if (inSize.x < theCommentSize)
+ theCommentSize = inSize.x;
+
+ // Recalculate the comment size depending on where the timebar is and how large it is
+ long theDiff = ::dtol((theRow->GetActiveEnd() - theRow->GetActiveStart()) * m_TimeRatio);
+ if (theDiff < theCommentSize) {
+ theCommentSize = theDiff - theTipSize;
+ if (theCommentSize < 0)
+ theCommentSize = 0;
+ }
+
+ m_EditControl->SetSize(CPt(theCommentSize, 15));
+
+ // Set the two right tips depending on where the right side is
+ m_RightTip.SetPosition(CPt(inSize.x - theTipSize, 0));
+ m_RightRightTip.SetPosition(CPt(inSize.x - m_RightRightTip.GetSize().x + 1, 0));
+}
+
+//=============================================================================
+/**
+ * Set whether this control is selected or not.
+ * If this is selected then it will modify how this control looks.
+ * @param inIsSelected true if this control is to be selected.
+ */
+void CTimebarControl::SetSelected(bool inIsSelected)
+{
+ if (inIsSelected != m_IsSelected) {
+ m_IsSelected = inIsSelected;
+ m_EditControl->SetSelected(m_IsSelected);
+ Invalidate();
+ }
+}
+
+void CTimebarControl::RefreshMetaData()
+{
+ m_EditControl->RefreshMetaData();
+}
+
+//=============================================================================
+/**
+ * Request for this control to refresh it's properties.
+ * This checks the size of the asset and adjusts it's size the the asset's
+ * length. Called when the time ratio or properties have changed.
+ * If the time has changed then Refresh( long, long ) must be called with the
+ * new times.
+ */
+void CTimebarControl::Refresh()
+{
+ Refresh(m_StartTime, m_EndTime);
+}
+
+//=============================================================================
+/**
+ * Request for this control to refresh it's properties.
+ * This updates all the properties of this control and resize it as necessary.
+ * Called when the time changes on the asset, the time ratio changes or any
+ * properties that this displays change.
+ * @param inStartTime the asset's start time.
+ * @param inEndTime the asset's end time.
+ */
+void CTimebarControl::Refresh(long inStartTime, long inEndTime)
+{
+ m_StartTime = inStartTime;
+ m_EndTime = inEndTime;
+
+ long thePosition = ::TimeToPos(inStartTime, m_TimeRatio);
+ long theSize = ::dtol((inEndTime - inStartTime) * m_TimeRatio);
+
+ SetPosition(thePosition - CStudioPreferences::GetTimebarTipSize(), GetPosition().y);
+
+ SetSize(CPt(theSize + 2 * CStudioPreferences::GetTimebarTipSize(), GetMinimumSize().y));
+ if (IsInvalidated())
+ m_TimebarRow->Invalidate();
+}
+
+//=============================================================================
+/**
+ * Get the interface to the timebar item in the data model
+ */
+ITimelineTimebar *CTimebarControl::GetTimebar()
+{
+ return m_TimelineItemBinding->GetTimelineItem()->GetTimebar();
+}
+
+//=============================================================================
+/**
+* Updates the ToolTip and moves it to the correct place on screen.
+* @param inPoint the point that the tooltip is supposed to be placed.
+*/
+void CTimebarControl::RefreshToolTip(CPt inPoint)
+{
+ Q3DStudio::CString theCommentText;
+ CStateRow *theRow = m_TimebarRow->GetStateRow();
+
+ CRct theTimelineBounds(GetTopControlBounds());
+ // format label as: startTime - endTime (timeDifference)
+ theCommentText = " " + FormatTimeString(theRow->GetStartTime()) + " - "
+ + FormatTimeString(theRow->GetEndTime()) + " ("
+ + FormatTimeString(theRow->GetEndTime() - theRow->GetStartTime()) + ")";
+ inPoint.y = GetPosition().y - GetSize().y;
+ ShowMoveableWindow(inPoint, theCommentText, theTimelineBounds);
+}
+
+//=============================================================================
+/**
+ * OnMouseDoubleClick: Pop up a dialog box for the editing of the timebar start
+ * and end time.
+ */
+bool CTimebarControl::OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDoubleClick(inPoint, inFlags)
+ && !m_TimelineItemBinding->IsLockedEnabled()) {
+ CTimeEditDlg theTimeEditDlg;
+ theTimeEditDlg.ShowDialog(m_StartTime, m_EndTime, g_StudioApp.GetCore()->GetDoc(), TIMEBAR,
+ this);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Allows this timebar control to add any times it wishes to the snapper list
+ * @param inSnapper the Snapper that is handling the snapping functions for this timebar
+ */
+void CTimebarControl::PopulateSnappingList(CSnapper *inSnapper)
+{
+ Q_UNUSED(inSnapper);
+}
+
+//=============================================================================
+/**
+ * Start drag handler, puts this control into drag mode.
+ * @param inPoint the point where the mouse was clicked.
+ * @param inFlags the mouse state.
+ */
+bool CTimebarControl::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_IsMouseDown = true;
+ m_MaybeDragStart = true;
+ m_MouseDownLoc = inPoint;
+
+ OnBeginDrag();
+
+ m_TimebarRow->GetStateRow()->Select(SBaseStateRowSelectionKeyState());
+
+ m_Snapper.Clear();
+ m_Snapper.SetSource(this);
+
+ GetSnappingListProvider().PopulateSnappingList(&m_Snapper);
+ m_Snapper.BeginDrag(inPoint.x);
+
+ if (HasFocus(m_EditControl) && !m_EditControl->HitTest(inPoint)) {
+ m_EditControl->OnLoseFocus();
+ }
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+ return true;
+}
+
+//=============================================================================
+/**
+ * Puts up the context menu.
+ * @param inPoint the point where the mouse was clicked.
+ * @param inFlags the mouse state.
+ */
+bool CTimebarControl::OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseRDown(inPoint, inFlags)) {
+ if (m_IsMouseDown) {
+ m_IsMouseDown = false;
+ CommitTimeChange();
+ HideMoveableWindow();
+ }
+ // only right-clicking ON the timebar will show the timebar (text and color) properties'
+ // options
+ ShowContextMenu(inPoint, true);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Notification that the drag has finished.
+ * @param inPoint the point where the mouse was let go.
+ * @param inFlags the state of the mouse.
+ */
+void CTimebarControl::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // try to prevent stuck mousetips on exceptions
+ try {
+ CControl::OnMouseUp(inPoint, inFlags);
+ CommitTimeChange();
+ } catch (...) {
+ }
+ m_IsMouseDown = false;
+ m_MaybeDragStart = false;
+ HideMoveableWindow();
+}
+
+//=============================================================================
+/**
+ * Handler for the mouse move messages.
+ * If the mouse is down then this will drag the control and offset the timebar.
+ * @param inPoint the current location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CTimebarControl::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ bool theCommentEditMode = m_EditControl->GetEditMode();
+
+ // If we are in edit Comment mode or locked, then we do not drag the timebar.
+ if (!theCommentEditMode && m_IsMouseDown && !m_TimelineItemBinding->IsLockedEnabled()) {
+ UICPROFILE(OnMouseMove);
+
+ if (m_MaybeDragStart) {
+ // Dragging in the first 5 pixels will be ignored to avoid unconsciously accidental
+ // moves
+ CPt theDragDistance = inPoint - m_MouseDownLoc;
+ if (theDragDistance.x * theDragDistance.x + theDragDistance.y * theDragDistance.y <= 25)
+ return;
+
+ m_MaybeDragStart = false;
+ }
+
+ long theNewTime = m_Snapper.ProcessDrag(m_StartTime, inPoint.x, inFlags);
+ if (theNewTime < 0)
+ theNewTime = 0;
+ long theDiffTime = theNewTime - m_StartTime;
+
+ if (theDiffTime) {
+ GetTimebar()->OffsetTime(theDiffTime);
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Call from the left TimebarTab to resize the control.
+ * @param inTime the time to set the start time to.
+ */
+void CTimebarControl::ResizeTimebarLeftTo(long inTime)
+{
+ // TOOD: sk - Figure out what this does
+ // if ( inTime != 0 )
+ {
+ // The whole idea is to not do anything additional once times passes 0 (negatively)
+ // unless it is valid that time is negative on the timebar
+ if (inTime < 0 && m_StartTime > 0)
+ inTime = -m_StartTime; // so that it decrements to 0
+
+ if (m_StartTime > 0 || (m_StartTime == 0 && inTime > 0))
+ GetTimebar()->ChangeTime(inTime, true);
+ }
+}
+
+//=============================================================================
+/**
+ * Call from the right TimebarTab to resize the control.
+ * @param inTime the time to set the start time to.
+ */
+void CTimebarControl::ResizeTimebarRightTo(long inTime)
+{
+ GetTimebar()->ChangeTime(inTime, false);
+}
+
+//=============================================================================
+/**
+ * Sets the Actual string of text
+ * @param inText the text to set the comment text to
+ */
+void CTimebarControl::SetText(const Q3DStudio::CString &inText)
+{
+ m_EditControl->SetData(inText);
+}
+
+//=============================================================================
+/**
+ * Sets the Text Color on the edit control
+ * @param inColor the color
+ */
+void CTimebarControl::SetTextColor(::CColor inColor)
+{
+ m_EditControl->SetTextColor(inColor);
+}
+
+long CTimebarControl::GetStartTime()
+{
+ return m_StartTime;
+}
+
+long CTimebarControl::GetEndTime()
+{
+ return m_EndTime;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not this control is enabled.
+ * If the control is not enabled then it is still drawn and still intercepts
+ * mouse clicks, but it will not actually process them.
+ * @param inIsEnabled true if this control is to be enabled.
+ */
+void CTimebarControl::SetEnabled(bool inIsEnabled)
+{
+ CControl::SetEnabled(inIsEnabled);
+}
+
+//=============================================================================
+/**
+ * COMMENT!!!!!!!!!!!!!!!!!!!!!!
+ */
+void CTimebarControl::OnLoseFocus()
+{
+ if (m_IsMouseDown) {
+ m_IsMouseDown = false;
+ CommitTimeChange();
+ HideMoveableWindow();
+ }
+ CControl::OnLoseFocus();
+}
+
+//=============================================================================
+/**
+ * Setup prior to dragging.
+ */
+void CTimebarControl::OnBeginDrag()
+{
+ GetTimebar()->OnBeginDrag();
+}
+
+void CTimebarControl::ChangeStartTime(long inTime)
+{
+ ResizeTimebarLeftTo(inTime);
+}
+
+void CTimebarControl::ChangeEndTime(long inTime)
+{
+ ResizeTimebarRightTo(inTime);
+}
+
+void CTimebarControl::Commit()
+{
+ GetTimebar()->CommitTimeChange();
+}
+void CTimebarControl::Rollback()
+{
+ GetTimebar()->RollbackTimeChange();
+}
+
+void CTimebarControl::ShowContextMenu(CPt inPoint, bool inShowTimebarPropertiesOptions)
+{
+ CTimebarKeyframeContextMenu theMenu(this, m_TimelineItemBinding->GetKeyframesManager(),
+ inShowTimebarPropertiesOptions);
+ DoPopup(&theMenu, inPoint);
+}
+
+void CTimebarControl::CommitTimeChange()
+{
+ GetTimebar()->CommitTimeChange();
+}
+
+//=============================================================================
+/**
+ * The binding is a keyframes holder
+ */
+ITimelineItemKeyframesHolder *CTimebarControl::GetKeyframesHolder()
+{
+ return m_TimelineItemBinding;
+}
+
+//=============================================================================
+/**
+ * Start editing the timebar comment
+ */
+void CTimebarControl::OnEditTimeComment()
+{
+ GrabFocus(m_EditControl);
+ m_EditControl->DoChangeComment();
+}
+
+//=============================================================================
+/**
+ * Need to invalidate all timebars to redraw
+ */
+void CTimebarControl::OnToggleTimebarHandles()
+{
+ Invalidate();
+}
+
+void CTimebarControl::SetTimebarTime()
+{
+ GetTimebar()->SetTimebarTime(this);
+}
+
+::CColor CTimebarControl::GetTimebarColor()
+{
+ return GetTimebar()->GetTimebarColor();
+}
+
+void CTimebarControl::SetTimebarColor(const ::CColor &inColor)
+{
+ GetTimebar()->SetTimebarColor(inColor);
+}
+
+void CTimebarControl::SetSnappingListProvider(ISnappingListProvider *inProvider)
+{
+ m_SnappingListProvider = inProvider;
+}
+
+ISnappingListProvider &CTimebarControl::GetSnappingListProvider() const
+{
+ // sk - If you hit this, it means the setup order is incorrect. e.g. loading children is done
+ // depth first, ie your child's children is loaded before parent, doesn't work that way.
+ ASSERT(m_SnappingListProvider);
+ return *m_SnappingListProvider;
+}
+
+CRct CTimebarControl::GetTopControlBounds() const
+{
+ return m_TimebarRow->GetStateRow()->GetTopControl()->GetBounds();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimebarControl.h b/src/Authoring/Studio/Palettes/Timeline/TimebarControl.h
new file mode 100644
index 00000000..ec37d134
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimebarControl.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIMEBAR_CONTROL_H
+#define INCLUDED_TIMEBAR_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "Snapper.h"
+#include "CommentEdit.h"
+#include "TimebarTip.h"
+#include "TimeEditDlg.h"
+#include "KeyframeContextMenu.h"
+
+class CStateTimebarRow;
+class ITimelineItemBinding;
+class ISnappingListProvider;
+
+//=============================================================================
+/**
+ * Interface to a timebar control
+ */
+class ITimebarControl
+{
+public:
+ virtual ~ITimebarControl() {}
+
+ virtual ITimelineItemKeyframesHolder *GetKeyframesHolder() = 0;
+ virtual void OnEditTimeComment() = 0;
+ virtual void OnToggleTimebarHandles() = 0;
+ virtual void SetTimebarTime() = 0;
+ virtual ::CColor GetTimebarColor() = 0;
+ virtual void SetTimebarColor(const ::CColor &inColor) = 0;
+};
+
+class CTimebarControl : public CControl, public ITimeChangeCallback, public ITimebarControl
+{
+public:
+ CTimebarControl(CStateTimebarRow *inRow, ITimelineItemBinding *inTimelineItemBinding);
+ virtual ~CTimebarControl();
+ void Draw(CRenderer *inRenderer) override;
+ void SetSize(CPt inSize) override;
+ void SetSelected(bool inIsSelected);
+ void SetTimeRatio(double inTimeRatio);
+ void Refresh();
+ void Refresh(long inStartTime, long inEndTime);
+ void RefreshMetaData();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseRDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseDoubleClick(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void ResizeTimebarLeftTo(long inTime);
+ void ResizeTimebarRightTo(long inTime);
+ void SetText(const Q3DStudio::CString &inText);
+ void SetTextColor(::CColor inColor = ::CColor(0, 0, 0));
+ void SetEnabled(bool inIsEnabled) override;
+
+ long GetStartTime();
+ long GetEndTime();
+
+ virtual void PopulateSnappingList(CSnapper *inSnapper);
+ void OnLoseFocus() override;
+
+ void OnBeginDrag();
+
+ // ITimeChangeCallback
+ void ChangeStartTime(long) override;
+ void ChangeEndTime(long) override;
+ void Commit() override;
+ void Rollback() override;
+
+ void ShowContextMenu(CPt inPoint, bool inShowTimebarPropertiesOptions);
+ void CommitTimeChange();
+
+ // ITimebarControl
+ ITimelineItemKeyframesHolder *GetKeyframesHolder() override;
+ void OnEditTimeComment() override;
+ void OnToggleTimebarHandles() override;
+ void SetTimebarTime() override;
+ ::CColor GetTimebarColor() override;
+ void SetTimebarColor(const ::CColor &inColor) override;
+
+ void SetSnappingListProvider(ISnappingListProvider *inProvider);
+ ISnappingListProvider &GetSnappingListProvider() const;
+
+ CRct GetTopControlBounds() const;
+
+protected:
+ ITimelineTimebar *GetTimebar();
+
+ void RefreshToolTip(CPt inPoint);
+ void DrawHashedBackgroundX(CRenderer *inRenderer, ::CColor inFirstColor, ::CColor inSecondColor,
+ CRct inRect);
+
+ CStateTimebarRow *m_TimebarRow;
+ bool m_IsSelected;
+ double m_TimeRatio;
+ bool m_IsMouseDown;
+ bool m_MaybeDragStart;
+ CPt m_MouseDownLoc;
+ long m_StartTime;
+ long m_EndTime;
+
+ CTimebarTip m_LeftLeftTip;
+ CTimebarTip m_LeftTip;
+
+ CTimebarTip m_RightTip;
+ CTimebarTip m_RightRightTip;
+ CCommentEdit *m_EditControl;
+ CSnapper m_Snapper;
+
+ ITimelineItemBinding *m_TimelineItemBinding;
+ ISnappingListProvider *m_SnappingListProvider;
+};
+#endif // INCLUDED_TIMEBAR_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimebarTip.cpp b/src/Authoring/Studio/Palettes/Timeline/TimebarTip.cpp
new file mode 100644
index 00000000..9968a838
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimebarTip.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TimebarTip.h"
+#include "TimebarControl.h"
+#include "MouseCursor.h"
+#include "TimelineControl.h"
+#include "ResourceCache.h"
+#include "Renderer.h"
+#include "StudioUtils.h"
+
+#include <QApplication>
+
+//=============================================================================
+/**
+ * Create a timebar tip for the timebar.
+ * This handles displaying the resize cursor and processing the mouse commands.
+ * @param inTimebar the timebar on which this tip is attached.
+ * @param inIsLeft true if this is the left timebar tip.
+ */
+CTimebarTip::CTimebarTip(CTimebarControl *inTimebar, bool inIsLeft, bool inHasHandle /*=false*/)
+ : m_IsMouseDown(false)
+ , m_MaybeDragStart(false)
+ , m_HasHandle(false)
+{
+ m_Timebar = inTimebar;
+ m_IsLeft = inIsLeft;
+
+ ShowHandles(inHasHandle);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimebarTip::~CTimebarTip()
+{
+}
+
+//=============================================================================
+/**
+* Updates the ToolTip and moves it to the correct place on screen.
+* @param inPoint the point that the tooltip is supposed to be placed.
+*/
+void CTimebarTip::RefreshToolTip(CPt inPoint)
+{
+ Q3DStudio::CString theCommentText;
+
+ // format label as: startTime - endTime (timeDifference)
+ theCommentText = " " + FormatTimeString(m_Timebar->GetStartTime()) + " - "
+ + FormatTimeString(m_Timebar->GetEndTime()) + " ("
+ + FormatTimeString(m_Timebar->GetEndTime() - m_Timebar->GetStartTime()) + ")";
+
+ CRct theTimelineBounds(m_Timebar->GetTopControlBounds());
+ inPoint.y = GetPosition().y - GetSize().y;
+ ShowMoveableWindow(inPoint, theCommentText, theTimelineBounds);
+}
+
+//=============================================================================
+/**
+ * Starts the dragging of the timebar tip.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+bool CTimebarTip::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseDown(inPoint, inFlags);
+
+ m_Timebar->OnBeginDrag();
+
+ m_Snapper.Clear();
+ m_Snapper.SetSource(m_Timebar);
+ m_Timebar->GetSnappingListProvider().PopulateSnappingList(&m_Snapper);
+ m_Snapper.BeginDrag(inPoint.x);
+
+ m_IsMouseDown = true;
+ m_MaybeDragStart = true;
+ m_MouseDownLoc = inPoint;
+
+ setCursorIfNotSet(CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+
+ return true;
+}
+
+//=============================================================================
+/**
+ * Ends the dragging of the tip and commits the commands.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CTimebarTip::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // try to prevent stuck mousetips on exceptions
+ try {
+ CControl::OnMouseUp(inPoint, inFlags);
+
+ // Commit the current command so it will not be merged with drag commands if this gets
+ // dragged again.
+ m_Timebar->CommitTimeChange();
+ } catch (...) {
+ }
+
+ m_IsMouseDown = false;
+ m_MaybeDragStart = false;
+ HideMoveableWindow();
+ resetCursor();
+}
+
+//=============================================================================
+/**
+ * If the mouse is down then this handles the resizing of the timebar.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse.
+ */
+void CTimebarTip::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ // Don't show the cursor if the mouse is down from someone else.
+ if (!(inFlags & CHotKeys::MOUSE_RBUTTON) && !(inFlags & CHotKeys::MOUSE_LBUTTON))
+ setCursorIfNotSet(CMouseCursor::CURSOR_RESIZE_LEFTRIGHT);
+
+ if (m_IsMouseDown) {
+ if (m_MaybeDragStart) {
+ // Dragging in the first 5 pixels will be ignored to avoid unconsciously accidental
+ // moves
+ CPt theDragDistance = inPoint - m_MouseDownLoc;
+ if (theDragDistance.x * theDragDistance.x + theDragDistance.y * theDragDistance.y <= 25)
+ return;
+
+ m_MaybeDragStart = false;
+ }
+
+ // Figure out which method to call based on which tip we are.
+ if (m_IsLeft) {
+ long theNewTime = m_Snapper.ProcessDrag(m_Timebar->GetStartTime(), inPoint.x, inFlags);
+ m_Timebar->ResizeTimebarLeftTo(theNewTime);
+ } else {
+ long theNewTime = m_Snapper.ProcessDrag(m_Timebar->GetEndTime(), inPoint.x, inFlags);
+ m_Timebar->ResizeTimebarRightTo(theNewTime);
+ }
+
+ // display the time range tooltip
+ RefreshToolTip(inPoint);
+ }
+}
+
+//=============================================================================
+/**
+ * Resets the cursor back to normal.
+ * @param inPoint the location of the mouse.
+ * @param inFlags the state of the mouse/modifier buttons.
+ */
+void CTimebarTip::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+
+ resetCursor();
+}
+
+//=============================================================================
+/**
+ * Draws timebar handles if necessary.
+ */
+void CTimebarTip::Draw(CRenderer *inRenderer)
+{
+ if (m_HasHandle) { // to show or not is based on Studio preferences
+ bool theShowHandle =
+ CPreferences::GetUserPreferences("Timeline").GetValue("ShowTimebarHandles", false);
+ if (theShowHandle) {
+ if (IsEnabled())
+ inRenderer->DrawBitmap(CPt(0, 0), m_HandleImage);
+ else
+ inRenderer->DrawBitmap(CPt(0, 0), m_HandleDisabledImage);
+ }
+ }
+}
+
+void CTimebarTip::ShowHandles(bool inShowHandles)
+{
+ m_HasHandle = inShowHandles;
+
+ // If this tip can have a handle
+ if (m_HasHandle) {
+ if (!m_HandleImage) {
+ // If this is a tip on the left side, load the images for the left side
+ const char *theBitMap =
+ (m_IsLeft) ? "timebarhandle-left.png" : "timebarhandle-right.png";
+ m_HandleImage = CResourceCache::GetInstance()->GetBitmap(theBitMap);
+ }
+
+ if (!m_HandleDisabledImage) {
+ const char *theBitMap =
+ (m_IsLeft) ? "timebarhandle-disabled-left.png" : "timebarhandle-disabled-right.png";
+ m_HandleDisabledImage = CResourceCache::GetInstance()->GetBitmap(theBitMap);
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimebarTip.h b/src/Authoring/Studio/Palettes/Timeline/TimebarTip.h
new file mode 100644
index 00000000..4aca03a7
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimebarTip.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TIMEBAR_TIP
+#define INCLUDED_TIMEBAR_TIP 1
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "Snapper.h"
+
+#include <QCursor>
+#include <QPixmap>
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTimebarControl;
+class CRenderer;
+
+//==============================================================================
+/**
+ * Class for the tips of timebar controls. Allows the user to resize timebars
+ * by grabbing the tips.
+ */
+class CTimebarTip : public CControl
+{
+public:
+ CTimebarTip(CTimebarControl *inTimebarControl, bool inIsLeft, bool inHasHandle = false);
+ virtual ~CTimebarTip();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void Draw(CRenderer *inRenderer) override;
+
+ void ShowHandles(bool inShowHandles);
+
+protected:
+ void RefreshToolTip(CPt inPoint);
+
+ CTimebarControl *m_Timebar;
+ bool m_IsMouseDown;
+ bool m_MaybeDragStart;
+ CPt m_MouseDownLoc;
+ bool m_IsLeft;
+ bool m_HasHandle;
+ QPixmap m_HandleImage;
+ QPixmap m_HandleDisabledImage;
+ CSnapper m_Snapper;
+};
+
+#endif // INCLUDED_TIMEBAR_TIP
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineControl.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineControl.cpp
new file mode 100644
index 00000000..9e0f4303
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineControl.cpp
@@ -0,0 +1,587 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TimelineControl.h"
+#include "TimelineSplitter.h"
+#include "StudioApp.h"
+#include "Dispatch.h"
+#include "TimelineTreeLayout.h"
+#include "TimelineTimelineLayout.h"
+#include "SlideRow.h"
+#include "IDoc.h"
+#include "InsertionLine.h"
+#include "InsertionOverlay.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "BreadCrumbControl.h"
+#include "BaseTimelineTreeControl.h"
+#include "Bindings/TimelineTranslationManager.h"
+#include "Doc.h"
+#include "Core.h"
+#include "MasterP.h"
+
+// Data model specific
+#include "TimelineDropTarget.h"
+
+#include "ClientDataModelBridge.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMSlides.h"
+
+IMPLEMENT_OBJECT_COUNTER(CTimelineControl)
+
+CTimelineControl::CTimelineControl()
+ : m_SuspendRecalcLayout(false)
+ , m_TranslationManager(nullptr)
+{
+ ADDTO_OBJECT_COUNTER(CTimelineControl)
+
+ m_TranslationManager = new CTimelineTranslationManager();
+
+ m_Splitter = new CTimelineSplitter();
+ AddChild(m_Splitter);
+
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+ m_TreeLayout = new CTimelineTreeLayout(this, theDoc);
+ m_Splitter->AddChild(m_TreeLayout);
+
+ m_TimelineLayout = new CTimelineTimelineLayout(this, theDoc);
+ m_Splitter->AddChild(m_TimelineLayout);
+
+ m_Splitter->SetSplitDirection(CSplitter::SPLIT_VERTICAL);
+ m_Splitter->SetSplitLocation(CStudioPreferences::GetTimelineSplitterLocation());
+
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ theDispatch->AddPresentationChangeListener(this);
+ theDispatch->AddClientPlayChangeListener(this);
+
+ // Insertion line
+ m_InsertionLine = new CInsertionLine();
+ m_InsertionLine->SetName("TimelineInsertionLine");
+ AddChild(m_InsertionLine);
+
+ // Insertion overlay marker
+ m_InsertionOverlay = new CInsertionOverlay();
+ m_InsertionOverlay->SetName("TimelineInsertionOverlay");
+ AddChild(m_InsertionOverlay);
+
+ m_Splitter->SetPosition(CPt(0, CStudioPreferences::GetHeaderHeight()));
+
+ m_BreadCrumbToolbar = new CBreadCrumbControl();
+ AddChild(m_BreadCrumbToolbar);
+
+ SetPreferredSize(CPt(400, 200));
+}
+
+CTimelineControl::~CTimelineControl()
+{
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ theDispatch->RemovePresentationChangeListener(this);
+ theDispatch->RemoveClientPlayChangeListener(this);
+
+ delete m_InsertionOverlay;
+ delete m_InsertionLine;
+ delete m_TimelineLayout;
+ delete m_TreeLayout;
+ delete m_Splitter;
+ delete m_BreadCrumbToolbar;
+
+ REMOVEFROM_OBJECT_COUNTER(CTimelineControl)
+}
+
+//=============================================================================
+/**
+ * Returns the playhead time
+ */
+long CTimelineControl::GetTime()
+{
+ return m_TreeLayout->GetTime();
+}
+
+//=============================================================================
+/**
+ * Clear the contents of this view.
+ * This will empty out this view and leave it ready for inspecting other objects.
+ */
+void CTimelineControl::ClearView()
+{
+ m_TimelineLayout->ClearRows();
+ m_TreeLayout->ClearRows();
+ m_ActiveSlide = 0;
+
+ // clean out all previous translations, because the bindings are not guaranteed to be valid when
+ // switching from one slide to another.
+ m_TranslationManager->Clear();
+}
+
+//=============================================================================
+/**
+ * Populates this view with the provided state.
+ * This will set the state as being the root object on this view. ClearView
+ * should be called before this is called.
+ * The object will become the root object of this and will become the active
+ * root of the doc.
+ * @param inState the state to be viewed as the root asset.
+ */
+void CTimelineControl::ViewSlide(UICDM::CUICDMSlideHandle inSlide)
+{
+ m_ActiveSlide = inSlide;
+
+ UICDM::ISlideSystem *theSlideSystem = GetDoc()->GetStudioSystem()->GetSlideSystem();
+ UICDM::CUICDMInstanceHandle theSlideInstance = theSlideSystem->GetSlideInstance(inSlide);
+ CSlideRow *theSlideRow = new CSlideRow(m_TranslationManager->GetOrCreate(theSlideInstance));
+ theSlideRow->SetTimelineControl(this);
+
+ m_TreeLayout->AddRow(theSlideRow);
+ m_TimelineLayout->AddRow(theSlideRow);
+
+ // Since this would be loading the entire context's assets, fire the OnTimelineLayoutChange
+ // event just once.
+ SuspendLayoutChanges(true);
+ try {
+ theSlideRow->LoadChildren();
+ theSlideRow->Expand();
+ } catch (...) { // restore the 'states' before passing the exception up
+ SuspendLayoutChanges(false);
+ throw;
+ }
+ // Update breadcrumbs
+ m_BreadCrumbToolbar->RefreshTrail(m_TranslationManager->GetBreadCrumbProvider());
+
+ SuspendLayoutChanges(false);
+ OnLayoutChanged();
+}
+
+//=============================================================================
+/**
+ * Notification from the StudioFullSystem signal provider that a we have a new active slide.
+ * This will populate this view with the new context.
+ */
+void CTimelineControl::OnActiveSlide(UICDM::CUICDMSlideHandle inSlide)
+{
+ ClearView();
+ ViewSlide(inSlide);
+
+ double theStoredRatio = m_TimelineLayout->GetTimelineRatio(inSlide);
+ if (theStoredRatio != -1)
+ m_TimelineLayout->SetTimeRatio(theStoredRatio);
+ else
+ m_TimelineLayout->OnScalingReset();
+
+ m_TimelineLayout->RecalcLayout();
+}
+
+void CTimelineControl::OnNewPresentation()
+{
+ m_TranslationManager->OnNewPresentation();
+
+ // Register callback
+ UICDM::IStudioFullSystemSignalProvider *theSignalProvider =
+ GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+ m_Connections.push_back(theSignalProvider->ConnectActiveSlide(
+ std::bind(&CTimelineControl::OnActiveSlide, this, std::placeholders::_3)));
+ m_Connections.push_back(theSignalProvider->ConnectSlideDeleted(
+ std::bind(&CTimelineControl::OnDeleteSlide, this, std::placeholders::_1)));
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ m_Connections.push_back(theDispatch->ConnectSelectionChange(
+ std::bind(&CTimelineControl::OnSelectionChange, this, std::placeholders::_1)));
+}
+
+//=============================================================================
+/**
+ * Notification from the dispatch that the presentation is being closed.
+ * This will clear all the objects from this presentation.
+ */
+void CTimelineControl::OnClosingPresentation()
+{
+ ClearView();
+ m_TimelineLayout->ClearAllTimeRatios();
+ m_BreadCrumbToolbar->RefreshTrail(nullptr);
+
+ m_Connections.clear();
+}
+
+//=============================================================================
+/**
+ * Accessor for the root object being displayed in this view.
+ */
+UICDM::CUICDMSlideHandle CTimelineControl::GetActiveSlide()
+{
+ return m_ActiveSlide;
+}
+
+//=============================================================================
+/**
+ * Gets the timeline layout which is the portion of the timeline to the right
+ * of the splitter. The timeline layout contains the timebars.
+ */
+CTimelineTimelineLayout *CTimelineControl::GetTimelineLayout()
+{
+ return m_TimelineLayout;
+}
+
+//=============================================================================
+/**
+ * Gets the tree layout which is the portion of the timeline to the left
+ * of the splitter. The tree layout contains the tree controls for expanding
+ * rows in the timeline.
+ */
+CTimelineTreeLayout *CTimelineControl::GetTreeLayout()
+{
+ return m_TreeLayout;
+}
+
+//=============================================================================
+/**
+ * Notification from the dispatch that the presentation is going into play mode.
+ */
+void CTimelineControl::OnPlayStart()
+{
+}
+
+//=============================================================================
+/**
+ * Notification from the dispatch that the presentation is exiting play state.
+ */
+void CTimelineControl::OnPlayStop()
+{
+}
+
+//=============================================================================
+/**
+ * Notification from the dispatch that the time has changed.
+ * This is used to update the playhead location and view time.
+ * @param inNewTime the new time that this should display.
+ */
+void CTimelineControl::OnTimeChanged(long inNewTime)
+{
+ SetTime(inNewTime);
+}
+
+//==============================================================================
+// CSelectionChangeListener
+//==============================================================================
+void CTimelineControl::OnSelectionChange(Q3DStudio::SSelectedValue inNewSelectable)
+{
+ // testing for nullptr selection OR if the selected is not displayed in the timeline
+ bool theLoseFocus = !inNewSelectable.empty();
+ if (!theLoseFocus) {
+ Q3DStudio::SelectedValueTypes::Enum theSelectionType = inNewSelectable.getType();
+ // for now, its just UICDM objects
+ theLoseFocus = theSelectionType != Q3DStudio::SelectedValueTypes::Instance; // UICDM objects
+ }
+ if (theLoseFocus)
+ m_TreeLayout->OnLoseFocus();
+
+ GetTranslationManager()->OnSelectionChange(inNewSelectable);
+
+ // The drag&drop doesn't have any sort of callback after a drop
+ // so for now, this acts as a "event-trigger" after a drop ( because new items are always
+ // selcted after a drop )
+ HideInsertionMarkers();
+}
+
+//=============================================================================
+/**
+ * Callback when individual rows has affected the layout, such that the treelayout needs to be
+ * synchronized with the timelinelayout or vice versa.
+ */
+void CTimelineControl::OnLayoutChanged()
+{
+ if (m_SuspendRecalcLayout) // optimization where this is explicitly shutoff.
+ return;
+
+ m_TreeLayout->RecalcLayout();
+ m_TimelineLayout->OnTimelineLayoutChanged();
+}
+
+//=============================================================================
+/**
+ * typically for displaying tooltip
+ */
+CRct CTimelineControl::GetBounds() const
+{
+ return CRct(GetGlobalPosition(CPt(0, 0)), GetSize());
+}
+
+void CTimelineControl::HideTimelineMoveableTooltip()
+{
+ HideMoveableWindow();
+}
+
+//=============================================================================
+/**
+ * For snapping timebars/keyframes
+ */
+ISnappingListProvider *CTimelineControl::GetSnappingListProvider() const
+{
+ return m_TimelineLayout;
+}
+
+//=============================================================================
+/**
+ * Sets the current time as seen in this palette.
+ * This will update the Playhead time and the time view time.
+ * @param inNewTime the time to set on this.
+ */
+void CTimelineControl::SetTime(long inNewTime)
+{
+ m_TimelineLayout->SetTime(inNewTime);
+ m_TreeLayout->SetTime(inNewTime);
+}
+
+void CTimelineControl::HideInsertionMarkers()
+{
+ bool theInvalidate = false;
+ if (m_InsertionOverlay->IsVisible()) {
+ m_InsertionOverlay->SetVisible(false);
+ theInvalidate = true;
+ }
+ if (m_InsertionLine->IsVisible()) {
+ m_InsertionLine->SetVisible(false);
+ theInvalidate = true;
+ }
+ if (theInvalidate) {
+ m_TreeLayout->Invalidate();
+ Invalidate();
+ }
+}
+
+void CTimelineControl::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+
+ m_Splitter->SetSize(CPt(inSize.x, inSize.y));
+}
+
+//=============================================================================
+/**
+ * Scrolls both sides of the timeline along the y-axis so that they stay synced.
+ * @param inSource Scroller that generated the scroll messsage
+ * @param inPositionY New vertical scroll bar position
+ */
+void CTimelineControl::SetScrollPositionY(CScroller *inSource, long inPositionY)
+{
+ m_TreeLayout->SetScrollPositionY(inSource, inPositionY);
+ m_TimelineLayout->SetScrollPositionY(inSource, inPositionY);
+}
+
+//=============================================================================
+/**
+ * Override OnDraw to provide Timeline only draw profiling stats.
+ */
+void CTimelineControl::OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation)
+{
+ UICPROFILE(OnDraw);
+ CControl::OnDraw(inRenderer, inDirtyRect, inIgnoreValidation);
+}
+
+//=============================================================================
+/**
+ * Fills the whole control with the base (gray) color, then other controls will
+ * draw on top of that.
+ * @param inRenderer renderer to draw to
+ */
+void CTimelineControl::Draw(CRenderer *inRenderer)
+{
+ const auto size = GetSize();
+ inRenderer->FillSolidRect(QRect(0, 0, size.x, size.y), CStudioPreferences::GetBaseColor());
+}
+
+//=============================================================================
+/**
+ * Overriden from CControl. We want to propagate keydown (specifically F2)
+ * messages to the selected row regardless if the control has focus or not.
+ */
+void CTimelineControl::OnGainFocus()
+{
+ CControl::OnGainFocus();
+
+ CBaseStateRow *theRow = m_TranslationManager->GetSelectedRow();
+ if (theRow)
+ theRow->SetFocus();
+}
+
+//=============================================================================
+/**
+ * Overridden to draw insertion lines
+ */
+CDropTarget *CTimelineControl::FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags)
+{
+ CDropTarget *theDropTarget = CControl::FindDropCandidate(inMousePoint, inFlags);
+
+ bool theHideInsertionMarkers = true;
+ CTimeLineDropTarget *theTimelineDropTarget = nullptr;
+ if (theDropTarget
+ && (theTimelineDropTarget = dynamic_cast<CTimeLineDropTarget *>(theDropTarget))) {
+ CControl *theInsertionOverControl = theTimelineDropTarget->GetInsertionMarkerRow();
+ if (theInsertionOverControl) {
+ CRct theTreeRect = GetVisibleTreeLayoutArea();
+ EDROPDESTINATION theDropDest = theTimelineDropTarget->GetDestination();
+ switch (theDropDest) {
+ case EDROPDESTINATION_ABOVE:
+ case EDROPDESTINATION_BELOW: {
+ // the insertion line starts from the indent to the end of the row
+ long theIndent = theTimelineDropTarget->GetInsertionMarkerIndent();
+ if (theDropDest == EDROPDESTINATION_ABOVE)
+ m_InsertionLine->SetPosition(theInsertionOverControl->GetGlobalPosition(
+ CPt(theIndent, -GetPosition().y)));
+ else
+ m_InsertionLine->SetPosition(theInsertionOverControl->GetGlobalPosition(CPt(
+ theIndent, theInsertionOverControl->GetSize().y - 1 - GetPosition().y)));
+
+ long theWidth =
+ theTreeRect.size.x + theTreeRect.position.x - m_InsertionLine->GetPosition().x;
+ m_InsertionLine->SetLineWidth(theWidth);
+ m_InsertionLine->SetVisible(true);
+ m_InsertionOverlay->SetVisible(false);
+ } break;
+ case EDROPDESTINATION_ON: {
+ // insertion overlay spans the width of the row
+ m_InsertionOverlay->SetPosition(theInsertionOverControl->GetGlobalPosition(
+ CPt(theTreeRect.position.x, -GetPosition().y)));
+
+ long theWidth = theTreeRect.size.x + theTreeRect.position.x
+ - m_InsertionOverlay->GetPosition().x;
+ m_InsertionOverlay->SetWidth(theWidth);
+ m_InsertionOverlay->SetVisible(true);
+ m_InsertionLine->SetVisible(false);
+ } break;
+ }
+ theHideInsertionMarkers = false;
+ }
+ }
+ // not drawn
+ if (theHideInsertionMarkers)
+ HideInsertionMarkers();
+
+ return theDropTarget;
+}
+
+void CTimelineControl::OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseOut(inPoint, inFlags);
+ HideInsertionMarkers();
+}
+
+void CTimelineControl::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+ HideInsertionMarkers();
+}
+
+//=============================================================================
+/**
+ * Gets the insertion line for the timeline. The insertion line should be used
+ * to indicate when you can drag-and-drop and item between two other items.
+ * Call SetVisible on this control to show/hide it.
+ * @return the insertion line control
+ */
+CInsertionLine *CTimelineControl::GetInsertionLine()
+{
+ return m_InsertionLine;
+}
+
+//=============================================================================
+/**
+ * Gets the insertion overlay marker for the timeline. This control should be
+ * used to indicate that you can drag-and-drop and object onto another item in
+ * the timeline. Call SetVisible on this control to show/hide it.
+ * @return the insertion overlay marker for the timeline
+ */
+CInsertionOverlay *CTimelineControl::GetInsertionOverlay()
+{
+ return m_InsertionOverlay;
+}
+
+//=============================================================================
+/**
+ * Fetches the bounding rect for the CTimelineTreeLayout section of the
+ * timeline. This is the section that contains toggles and text names of items
+ * in the timeline. The actual tree layout might be bigger than this rect
+ * specifies. This is because portions of the tree layout might be overlapped
+ * by other controls.
+ * @return rectangle describing visible area of the tree control
+ */
+CRct CTimelineControl::GetVisibleTreeLayoutArea()
+{
+ return m_TreeLayout->GetVisibleArea();
+}
+
+void CTimelineControl::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ m_TimelineLayout->RegisterGlobalKeyboardShortcuts(inShortcutHandler);
+}
+
+//=============================================================================
+/**
+ * event that takes place just before a save or export, on lose focus will commit changes
+ * in text boxes
+ */
+void CTimelineControl::OnSavingPresentation(const CUICFile *inNewPresentationFile)
+{
+ Q_UNUSED(inNewPresentationFile);
+ OnLoseFocus();
+}
+
+//=============================================================================
+/**
+ * Notification from the StudioFullSystem signal provider that a slide has been deleted.
+ */
+void CTimelineControl::OnDeleteSlide(UICDM::CUICDMSlideHandle inSlide)
+{
+ m_TimelineLayout->DeleteTimelineRatio(inSlide);
+}
+
+//==============================================================================
+/**
+ * When caller knows that there are 'batch' changes to the timeline layout,
+ * to prevent unnecessary calls to recalclayout
+ */
+void CTimelineControl::SuspendLayoutChanges(bool inSuspend)
+{
+ m_SuspendRecalcLayout = inSuspend;
+}
+
+CDoc *CTimelineControl::GetDoc()
+{
+ return g_StudioApp.GetCore()->GetDoc();
+}
+
+CClientDataModelBridge *CTimelineControl::GetBridge()
+{
+ return GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineControl.h b/src/Authoring/Studio/Palettes/Timeline/TimelineControl.h
new file mode 100644
index 00000000..470a10a5
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineControl.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_TIMELINE_CONTROL_H
+#define INCLUDED_TIMELINE_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Control.h"
+#include "DispatchListeners.h"
+#include "TimelineRow.h"
+#include "ITimelineControl.h"
+
+#include "UICDMHandles.h"
+#include "UICDMSignals.h"
+#include "SelectedValueImpl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CDoc;
+class CDropTarget;
+class CTimelineSplitter;
+class CTimelineTreeLayout;
+class CTimelineTimelineLayout;
+class CScroller;
+class CInsertionLine;
+class CInsertionOverlay;
+class CRenderer;
+class CHotKeys;
+class CBreadCrumbControl;
+class CTimelineTranslationManager;
+class CClientDataModelBridge;
+
+//==============================================================================
+// Classes
+//==============================================================================
+
+class CTimelineControl : public CControl,
+ public CPresentationChangeListener,
+ public CClientPlayChangeListener,
+ public ITimelineControl
+{
+public:
+ CTimelineControl();
+ ~CTimelineControl();
+
+ DEFINE_OBJECT_COUNTER(CTimelineControl)
+
+ // CControl
+ void OnDraw(CRenderer *inRenderer, CRct &inDirtyRect, bool inIgnoreValidation = false) override;
+ void Draw(CRenderer *inRenderer) override;
+ void OnGainFocus() override;
+ CDropTarget *FindDropCandidate(CPt &inMousePoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseOut(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+
+ // Presentation Change Listener
+ void OnNewPresentation() override;
+ void OnClosingPresentation() override;
+ void OnSavingPresentation(const CUICFile *inNewPresentationFile) override;
+
+ // ClientPlayChangeListener
+ void OnPlayStart() override;
+ void OnPlayStop() override;
+ void OnTimeChanged(long inNewTime) override;
+
+ // CSelectionChangeListener,
+ virtual void OnSelectionChange(Q3DStudio::SSelectedValue inNewSelectable);
+
+ // ITimelineControl
+ void OnLayoutChanged() override;
+ CRct GetBounds() const override;
+ void HideTimelineMoveableTooltip() override;
+ ISnappingListProvider *GetSnappingListProvider() const override;
+
+ void ClearView();
+ void ViewSlide(UICDM::CUICDMSlideHandle inSlide);
+ UICDM::CUICDMSlideHandle GetActiveSlide();
+
+ CTimelineTimelineLayout *GetTimelineLayout();
+ CTimelineTreeLayout *GetTreeLayout();
+
+ void SetSize(CPt inSize) override;
+ long GetTime();
+ void SetScrollPositionY(CScroller *inSource, long inPositionY);
+
+ CInsertionLine *GetInsertionLine();
+ CInsertionOverlay *GetInsertionOverlay();
+ CRct GetVisibleTreeLayoutArea();
+
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+
+ CTimelineTranslationManager *GetTranslationManager() const { return m_TranslationManager; }
+
+protected:
+ void SuspendLayoutChanges(bool inSuspend);
+ void SetTime(long inNewTime);
+
+ void HideInsertionMarkers();
+
+ // UICDM callbacks
+ void OnActiveSlide(UICDM::CUICDMSlideHandle inSlide);
+ void OnDeleteSlide(UICDM::CUICDMSlideHandle inSlide);
+
+ // Helper functions
+ inline CDoc *GetDoc();
+ inline CClientDataModelBridge *GetBridge();
+
+ CTimelineSplitter *m_Splitter;
+ CTimelineTreeLayout *m_TreeLayout;
+ CTimelineTimelineLayout *m_TimelineLayout;
+ UICDM::CUICDMSlideHandle m_ActiveSlide;
+ CInsertionLine
+ *m_InsertionLine; ///< Drag-and-drop insertion line for dropping between timeline items
+ CInsertionOverlay
+ *m_InsertionOverlay; ///< Drag-and-drop insertion marker for dropping on a timeline item
+ CBreadCrumbControl *m_BreadCrumbToolbar;
+ bool m_SuspendRecalcLayout;
+
+ CTimelineTranslationManager *m_TranslationManager;
+
+ std::vector<std::shared_ptr<UICDM::ISignalConnection>>
+ m_Connections; /// connections to the UICDM
+};
+#endif // INCLUDED_TIMELINE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineFilter.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineFilter.cpp
new file mode 100644
index 00000000..5ef25911
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineFilter.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TimelineFilter.h"
+#include "Bindings/ITimelineItemProperty.h"
+#include "Bindings/ITimelineItem.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CFilter::CFilter()
+ : m_ShowBehaviors(true)
+ , m_ShowMaterials(true)
+ , m_ShowProperties(true)
+ , m_ShowShy(true)
+ , m_ShowLocked(true)
+ , m_ShowVisible(true)
+ , m_IsExpanded(true)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CFilter::~CFilter()
+{
+}
+
+//=============================================================================
+/**
+ * @return true if behaviors should be shown, false if they should be hidden
+ */
+bool CFilter::GetBehaviors() const
+{
+ return m_ShowBehaviors;
+}
+
+//=============================================================================
+/**
+ * @return true if materials should be shown, false if they should be hidden
+ */
+bool CFilter::GetMaterials() const
+{
+ return m_ShowMaterials;
+}
+
+//=============================================================================
+/**
+ * @return true if properties should be shown, false if they should be hidden
+ */
+bool CFilter::GetProperties() const
+{
+ return m_ShowProperties;
+}
+
+//=============================================================================
+/**
+ * @return true if shy objects should still be shown, false if they should be hidden
+ */
+bool CFilter::GetShy() const
+{
+ return m_ShowShy;
+}
+
+//=============================================================================
+/**
+ * @return true if locked objects should still be shown, false if they should be hidden
+ */
+bool CFilter::GetLocked() const
+{
+ return m_ShowLocked;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not to show behaviors on objects.
+ * @param inShow true to show behaviors, false to hide behaviors
+ */
+void CFilter::SetBehaviors(bool inShow /*= true*/)
+{
+ m_ShowBehaviors = inShow;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not to show materials on objects.
+ * @param inShow true to show materials, false to hide materials
+ */
+void CFilter::SetMaterials(bool inShow /*= true*/)
+{
+ m_ShowMaterials = inShow;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not to show properties on objects.
+ * @param inShow true to show properties, false to hide properties
+ */
+void CFilter::SetProperties(bool inShow /*= true*/)
+{
+ m_ShowProperties = inShow;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not to show objects with the shy flag.
+ * @param inShow true to show shy objects, false to hide shy objects
+ */
+void CFilter::SetShy(bool inShow /*= true*/)
+{
+ m_ShowShy = inShow;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not to show objects with the locked flag.
+ * @param inShow true to show locked objects, false to hide locked objects
+ */
+void CFilter::SetLocked(bool inShow /*= true*/)
+{
+ m_ShowLocked = inShow;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not the parent object is expanded.
+ * If the parent is not expanded then nothing should be visible.
+ */
+void CFilter::SetExpanded(bool inIsExpanded /*= true*/)
+{
+ m_IsExpanded = inIsExpanded;
+}
+
+//=============================================================================
+/**
+ * Sets whether or not to show objects that are not visible.
+ * @param inIsVisible true to show non-visible objects, false to hide them.
+ */
+void CFilter::SetVisible(bool inIsVisible /*= true*/)
+{
+ m_ShowVisible = inIsVisible;
+}
+
+//=============================================================================
+/**
+ * Gets whether or not non-visible objects should be displayed.
+ * @return true if non-visible objects should be displayed.
+ */
+bool CFilter::GetVisible() const
+{
+ return m_ShowVisible;
+}
+
+//=============================================================================
+/**
+ * Gets whether or not the parent object is expanded.
+ * If the parent is not expanded then nothing should be visible.
+ */
+bool CFilter::IsExpanded() const
+{
+ return m_IsExpanded;
+}
+
+//=============================================================================
+/**
+ * Checks to see if the specified property should be displayed or not.
+ * @return true if the property should be visible.
+ */
+bool CFilter::Filter(ITimelineItemProperty *inTimelineItemProperty) const
+{
+ Q_UNUSED(inTimelineItemProperty);
+
+ bool theVisibleFlag = GetProperties();
+ theVisibleFlag &= IsExpanded();
+
+ return theVisibleFlag;
+}
+
+//=============================================================================
+/**
+ * Checks to see if the specified state should be displayed or not.
+ * @return true if the state should be visible.
+ */
+bool CFilter::Filter(ITimelineItem *inTimelineItem) const
+{
+ bool theVisibleFlag = true;
+
+ // If this row is shy, we need to check the filter for shy objects
+ if (inTimelineItem->IsShy())
+ theVisibleFlag &= GetShy();
+
+ // If this row is locked, we need to check the filter for locked objects
+ if (inTimelineItem->IsLocked())
+ theVisibleFlag &= GetLocked();
+
+ // This is for hiding visible eye toggle objects
+ if (!inTimelineItem->IsVisible())
+ theVisibleFlag &= GetVisible();
+
+ // If this row is a behavior, we need to check the filter for behaviors
+ if (inTimelineItem->GetObjectType() == OBJTYPE_BEHAVIOR)
+ theVisibleFlag &= GetBehaviors();
+
+ // If this row is a material, we need to check the filter for materials
+ if (inTimelineItem->GetObjectType() == OBJTYPE_MATERIAL)
+ theVisibleFlag &= GetMaterials();
+
+ return theVisibleFlag;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineFilter.h b/src/Authoring/Studio/Palettes/Timeline/TimelineFilter.h
new file mode 100644
index 00000000..e956b4da
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineFilter.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_FILTER_H
+#define INCLUDED_FILTER_H 1
+
+#pragma once
+
+//==============================================================================
+// Forward
+//==============================================================================
+class ITimelineItem;
+class ITimelineItemProperty;
+
+//=============================================================================
+/**
+ * Filter class for determining what objects to show in the timeline.
+ */
+class CFilter
+{
+public:
+ CFilter();
+ virtual ~CFilter();
+
+ bool GetBehaviors() const;
+ bool GetMaterials() const;
+ bool GetProperties() const;
+ bool GetShy() const;
+ bool GetLocked() const;
+ bool GetVisible() const;
+ void SetBehaviors(bool inShow = true);
+ void SetMaterials(bool inShow = true);
+ void SetProperties(bool inShow = true);
+ void SetShy(bool inShow = true);
+ void SetLocked(bool inShow = true);
+ void SetVisible(bool inShow = true);
+
+ void SetExpanded(bool inExpanded = true);
+ bool IsExpanded() const;
+
+ bool Filter(ITimelineItemProperty *inTimelineItemProperty) const;
+ bool Filter(ITimelineItem *inTimelineItem) const;
+
+protected:
+ bool m_ShowBehaviors;
+ bool m_ShowMaterials;
+ bool m_ShowProperties;
+ bool m_ShowShy;
+ bool m_ShowLocked;
+ bool m_ShowVisible;
+ bool m_IsExpanded;
+};
+
+#endif // INCLUDED_FILTER_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.cpp
new file mode 100644
index 00000000..36946432
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "TimelineKeyframe.h"
+#include "Renderer.h"
+
+CTimelineKeyframe::CTimelineKeyframe()
+ : m_Time(0)
+ , m_IsDynamic(false)
+{
+}
+
+CTimelineKeyframe::~CTimelineKeyframe()
+{
+}
+
+void CTimelineKeyframe::SetTime(long inTime)
+{
+ m_Time = inTime;
+}
+
+long CTimelineKeyframe::GetTime()
+{
+ return m_Time;
+}
+
+//=============================================================================
+/**
+ * called when this key is made dynamic
+ * @param inIsDynamic true if the keyframe is dynamic
+ */
+void CTimelineKeyframe::SetDynamic(bool inIsDynamic)
+{
+ if (m_IsDynamic != inIsDynamic) {
+ m_IsDynamic = inIsDynamic;
+ // Invalidate( );
+ }
+}
+
+//=============================================================================
+/**
+ * @return true if dynamic
+ */
+bool CTimelineKeyframe::IsDynamic()
+{
+ return m_IsDynamic;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.h b/src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.h
new file mode 100644
index 00000000..a08f553c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineKeyframe.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIMELINE_KEYFRAME
+#define INCLUDED_TIMELINE_KEYFRAME 1
+
+#pragma once
+class CRenderer;
+
+class CTimelineKeyframe
+{
+public:
+ CTimelineKeyframe();
+ ~CTimelineKeyframe();
+ virtual void Draw(CRenderer *inRenderer) = 0;
+
+ virtual void SetTime(long inTime);
+ virtual long GetTime();
+
+ void SetDynamic(bool inIsDynamic);
+ bool IsDynamic();
+
+ static const long DRAGBUFFER =
+ 3; // Specifies how many pixels a keframe should be dragged before it actually moves
+
+protected:
+ long m_Time;
+ bool m_IsDynamic;
+};
+
+#endif // INCLUDED_TIMELINE_KEYFRAME \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineRow.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineRow.cpp
new file mode 100644
index 00000000..c465575c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineRow.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "TimelineRow.h"
+#include "StudioPreferences.h"
+#include "StudioObjectTypes.h"
+#include "BaseStateRow.h"
+
+const long CTimelineRow::TREE_INDENT = CStudioPreferences::GetRowSize();
+
+CTimelineRow::CTimelineRow()
+ : m_ParentRow(nullptr)
+ , m_IsViewable(false)
+ , m_Indent(0)
+{
+}
+
+CTimelineRow::~CTimelineRow()
+{
+}
+void CTimelineRow::SetIndent(long inIndent)
+{
+ m_Indent = inIndent;
+}
+
+long CTimelineRow::GetIndent()
+{
+ return m_Indent;
+}
+
+void CTimelineRow::SetParent(CBaseStateRow *inParent)
+{
+ m_ParentRow = inParent;
+}
+
+//=============================================================================
+/**
+ * Gets the Parent Row
+ */
+CBaseStateRow *CTimelineRow::GetParentRow() const
+{
+ return m_ParentRow;
+}
+
+void CTimelineRow::SetTimeRatio(double inTimeRatio)
+{
+ Q_UNUSED(inTimeRatio);
+}
+
+void CTimelineRow::OnChildVisibilityChanged()
+{
+}
+
+bool CTimelineRow::IsViewable() const
+{
+ return m_IsViewable;
+}
+
+void CTimelineRow::PopulateSnappingList(CSnapper *inSnapper)
+{
+ Q_UNUSED(inSnapper);
+}
+
+//=============================================================================
+/**
+ * By default, this will recurse up its parent, for an answer.
+ * If this proves to a performance hit, we can cache a ITimelineControl pointer at EVERY row.
+ */
+ITimelineControl *CTimelineRow::GetTopControl() const
+{
+ ITimelineControl *theControl = (m_ParentRow) ? m_ParentRow->GetTopControl() : nullptr;
+ ASSERT(theControl);
+ return theControl;
+}
+
+//=============================================================================
+/**
+ * Retrieves the background color for the row based upon the type of asset
+ * passed in.
+ * @param inType specifies which asset type you want the color for
+ * @return background color to use for this row
+ */
+::CColor CTimelineRow::GetTimebarBackgroundColor(EStudioObjectType inType)
+{
+ ::CColor theColor;
+
+ switch (inType) {
+ case OBJTYPE_LAYER:
+ theColor = CStudioPreferences::GetLayerBackgroundColor();
+ break;
+
+ case OBJTYPE_GROUP:
+ case OBJTYPE_COMPONENT:
+ theColor = CStudioPreferences::GetGroupBackgroundColor();
+ break;
+
+ default:
+ theColor = CStudioPreferences::GetObjectBackgroundColor();
+ break;
+ }
+
+ return theColor;
+}
+
+//=============================================================================
+/**
+ * Retrieves the background color for the row when the mouse is over the row,
+ * based upon the type of asset passed in.
+ * @param inType specifies which asset type you want the color for
+ * @return background color to use for this row when the mouse is over the row
+ */
+::CColor CTimelineRow::GetTimebarHighlightBackgroundColor(EStudioObjectType inType)
+{
+ ::CColor theColor;
+
+ switch (inType) {
+ case OBJTYPE_LAYER:
+ theColor = CStudioPreferences::GetMouseOverHighlightColor();
+ break;
+
+ case OBJTYPE_GROUP:
+ case OBJTYPE_COMPONENT:
+ theColor = CStudioPreferences::GetMouseOverHighlightColor();
+ break;
+
+ default:
+ theColor = CStudioPreferences::GetMouseOverHighlightColor();
+ break;
+ }
+
+ return theColor;
+}
+
+long CTimelineRow::GetLatestEndTime()
+{
+ return 0;
+}
+
+void CTimelineRow::Dispose()
+{
+ delete this;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineRow.h b/src/Authoring/Studio/Palettes/Timeline/TimelineRow.h
new file mode 100644
index 00000000..c18d438b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineRow.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TIMELINE_ROW_H
+#define INCLUDED_TIMELINE_ROW_H 1
+
+#pragma once
+
+#include "TimelineFilter.h"
+#include "CColor.h"
+#include "StudioObjectTypes.h"
+
+#include <vector>
+
+class CSnapper;
+class CControl;
+class CBaseStateRow;
+class ISnappingListProvider;
+class ITimelineControl;
+
+class CTimelineRow
+{
+public:
+ static const long TREE_INDENT;
+
+ CTimelineRow();
+ virtual ~CTimelineRow();
+
+ virtual CControl *GetColorControl() = 0;
+ virtual CControl *GetTreeControl() = 0;
+ virtual CControl *GetToggleControl() = 0;
+ virtual CControl *GetTimebarControl() = 0;
+
+ virtual void SetIndent(long inIndent);
+ long GetIndent();
+
+ virtual void Filter(const CFilter &inFilter, bool inFilterChildren = true) = 0;
+
+ void SetParent(CBaseStateRow *inParent);
+ CBaseStateRow *GetParentRow() const;
+ virtual void SetTimeRatio(double inTimeRatio);
+ virtual void OnChildVisibilityChanged();
+ virtual bool IsViewable() const;
+ virtual void PopulateSnappingList(CSnapper *inSnappingList);
+ virtual ISnappingListProvider *GetSnappingListProvider() const = 0;
+ virtual void SetSnappingListProvider(ISnappingListProvider *inProvider) = 0;
+ virtual ITimelineControl *GetTopControl() const;
+
+ virtual ::CColor GetTimebarBackgroundColor(EStudioObjectType inType);
+ virtual ::CColor GetTimebarHighlightBackgroundColor(EStudioObjectType inType);
+
+ virtual long GetLatestEndTime();
+
+ virtual void Dispose();
+
+protected:
+ CBaseStateRow *m_ParentRow;
+ bool m_IsViewable;
+ long m_Indent;
+};
+#endif // INCLUDED_TIMELINE_ROW_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.cpp
new file mode 100644
index 00000000..fe072db6
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "TimelineSplitter.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimelineSplitter::CTimelineSplitter()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimelineSplitter::~CTimelineSplitter()
+{
+}
+
+//=============================================================================
+/**
+ * Set the location of the splitter bar. Overridden so that this location can
+ * be stored in the user's preferences.
+ * @param inSplitLocation the location of the splitter bar, in pixels from the right/top.
+ */
+void CTimelineSplitter::SetSplitLocation(long inPixels)
+{
+ CSplitter::SetSplitLocation(inPixels);
+ CStudioPreferences::SetTimelineSplitterLocation(inPixels);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.h b/src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.h
new file mode 100644
index 00000000..f9ba681a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineSplitter.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef TIMELINE_SPLITTER_INCLUDED
+#define TIMELINE_SPLITTER_INCLUDED 1
+
+#pragma once
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "Splitter.h"
+
+//=============================================================================
+/**
+ * Overridden splitter, specific to the timeline, which stores the split location
+ * so that it can be retrieved between program sessions.
+ */
+class CTimelineSplitter : public CSplitter
+{
+public:
+ CTimelineSplitter();
+ virtual ~CTimelineSplitter();
+ void SetSplitLocation(long inPixels) override;
+};
+
+#endif
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.cpp
new file mode 100644
index 00000000..ead5251d
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.cpp
@@ -0,0 +1,713 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "TimelineTimelineLayout.h"
+#include "TimeMeasure.h"
+#include "ScalableScroller.h"
+#include "StudioUtils.h"
+#include "TimelineRow.h"
+#include "TimelineControl.h"
+#include "StateRow.h"
+#include "Snapper.h"
+#include "Bindings/TimelineTranslationManager.h"
+#include "ControlData.h"
+#include "HotKeys.h"
+#include "foundation/Qt3DSLogging.h"
+
+//=============================================================================
+// Defines
+//=============================================================================
+// For Win the modifier key for keyframe multi selection is the control key.
+#define MODIFIER_KEY CHotKeys::MODIFIER_CONTROL
+
+//=============================================================================
+// Class constants
+//=============================================================================
+const double DEFAULT_TIME_RATIO = .05;
+const double CTimelineTimelineLayout::SCALING_PERCENTAGE_INC = 1.1;
+const double CTimelineTimelineLayout::SCALING_PERCENTAGE_DEC = 0.9;
+const double CTimelineTimelineLayout::MAX_ZOOM_OUT = 7e-005;
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimelineTimelineLayout::CTimelineTimelineLayout(CTimelineControl *inTimelineControl, IDoc *inDoc)
+ : m_Playhead(this, inDoc)
+ , m_IsLayoutChanged(false)
+ , m_IsMouseDown(false)
+{
+ m_ControlData->SetMouseWheelEnabled(true);
+ m_TimelineControl = inTimelineControl;
+
+ m_TimeRatio = DEFAULT_TIME_RATIO + .01;
+ m_TimeMeasure = new CTimeMeasure(this, m_TimeRatio);
+ m_Scroller = new CScalableScroller();
+
+ m_Scroller->SetVerticalScrollMode(CScroller::ALWAYS);
+ m_Scroller->SetHorizontalScrollMode(CScroller::ALWAYS);
+ m_Scroller->AddScrollListener(this);
+ m_BoundingRect = new CAreaBoundingRect();
+ m_BoundingRect->SetName("TimelineAreaBoundingRect");
+ m_BoundingRect->SetVisible(false);
+ m_BoundingRect->SetAlpha(128);
+
+ AddChild(m_TimeMeasure);
+ AddChild(m_Scroller);
+ AddChild(&m_Playhead);
+ AddChild(m_BoundingRect);
+
+ // Blank control filling in the bottom of the timeline, under the rows
+ CBlankControl *theTimelineBlankControl = new CBlankControl();
+ m_TimebarList = new CFlowLayout(theTimelineBlankControl);
+
+ m_Scroller->AddChild(m_TimebarList);
+ m_Scroller->SetScalingListener(this);
+ m_TimebarList->SetName("TimelineTimelineLayoutList");
+
+ // Initializing flags for keyframe multi select to work.
+ m_CommitKeyframeSelection = false;
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimelineTimelineLayout::~CTimelineTimelineLayout()
+{
+ delete m_TimeMeasure;
+ delete m_Scroller;
+ delete m_TimebarList;
+ delete m_BoundingRect;
+}
+
+//=============================================================================
+/**
+ * Clear all the StateRows out of the top-level list.
+ * This is used when the current presentation is being cleared out.
+ */
+void CTimelineTimelineLayout::ClearRows()
+{
+ TTimelineRowList::iterator thePos = m_Rows.begin();
+ for (; thePos != m_Rows.end(); ++thePos) {
+ CTimelineRow *theRow = (*thePos);
+ m_TimebarList->RemoveChild(theRow->GetTimebarControl());
+ }
+
+ m_Rows.clear();
+}
+
+//=============================================================================
+/**
+ * Set the size of this control.
+ * Overrrides CControl::SetSize so that this can redo the layout of all inner
+ * controls.
+ * @param inSize the new size of this control.
+ */
+void CTimelineTimelineLayout::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+
+ RecalcLayout();
+}
+
+//=============================================================================
+/**
+ * Recalculate the positioning of all the child components.
+ */
+void CTimelineTimelineLayout::RecalcLayout()
+{
+ CPt mySize = GetSize();
+ // Put the time measure on top taking 21 pixels high.
+ m_TimeMeasure->SetSize(CPt(mySize.x, 21));
+ m_TimeMeasure->SetPosition(CPt(0, 0));
+
+ // Make the scroller take up the rest of the space.
+ m_Scroller->SetSize(CPt(mySize.x, mySize.y - 42));
+ m_Scroller->SetPosition(CPt(0, 21));
+
+ // Make it the full length of the view, minus the bottom scroll bar.
+ m_Playhead.SetSize(CPt(13, GetSize().y - m_Scroller->GetHorizontalBar()->GetSize().y - 21));
+
+ long theMinTime = -(m_Playhead.GetCenterOffset());
+
+ if (!m_Rows.empty()) {
+ long theLatestTime = 0;
+ TTimelineRowList::iterator thePos = m_Rows.begin();
+ for (; thePos != m_Rows.end(); ++thePos) {
+ CTimelineRow *theRow = (*thePos);
+ long theRowLatestTime = theRow->GetLatestEndTime();
+ if (theRowLatestTime > theLatestTime)
+ theLatestTime = theRowLatestTime;
+ }
+
+ long theMinWidth = ::TimeToPos(theLatestTime, m_TimeRatio) + END_BUFFER_SIZE;
+ long theMinHeight = m_TimebarList->GetMinimumSize().y;
+
+ CPt theVisSize = m_Scroller->GetVisibleSize();
+
+ if (theMinHeight < theVisSize.y)
+ theMinHeight = theVisSize.y;
+ if (theMinWidth < theVisSize.x)
+ theMinWidth = theVisSize.x;
+
+ m_TimebarList->ResetMinMaxPref();
+ m_TimebarList->SetAbsoluteSize(CPt(theMinWidth, theMinHeight));
+ }
+
+ // Set up the limits.
+ m_Playhead.SetMinMaxPosition(theMinTime, mySize.x - m_Scroller->GetVerticalBar()->GetSize().x);
+
+ // Set playhead to time 0.
+ SetTime(m_TimelineControl->GetTranslationManager()->GetCurrentViewTime(), true);
+
+ // Reset! so that this isn't unnecessarily run
+ m_IsLayoutChanged = false;
+}
+
+//=============================================================================
+/**
+ * Add a timeline row to this object.
+ * This will add the row as a top level object.
+ * @param inRow the row to be added.
+ */
+void CTimelineTimelineLayout::AddRow(CTimelineRow *inRow)
+{
+ m_Rows.push_back(inRow);
+
+ m_TimebarList->AddChild(inRow->GetTimebarControl());
+
+ inRow->SetTimeRatio(m_TimeRatio);
+ // For keyframe/timebar snapping.
+ inRow->SetSnappingListProvider(this);
+}
+
+//=============================================================================
+/**
+ * Call from the ScalableScroller that it is scaling the right side of the timebar.
+ * @param inLength the length that the thumb wants to be.
+ * @param inTotalLength the maximum length that the thumb can be.
+ * @param inOffset the offset of the thumb position.
+ */
+void CTimelineTimelineLayout::OnScalingRight(long inLength, long inTotalLength, long inOffset)
+{
+ double theViewSize = m_Scroller->GetVisibleSize().x;
+ double theClientSize = m_Scroller->GetContaineeSize().x;
+ double theLength = inLength;
+ double theTotalLength = inTotalLength;
+
+ double theTimeRatio =
+ (theViewSize * theTotalLength) / (theClientSize * theLength) * m_TimeRatio;
+
+ // This means the bar was dragged to the far end, just prevent it for getting wacky.
+ if (theTimeRatio > 0) {
+ // This will set the time ratio, but will cap it at 1 or MAX_ZOOM_OUT so if the Time ratio
+ // less than max, don't need to move the timeline
+ SetTimeRatio(theTimeRatio);
+ if (theTimeRatio < 1) {
+ double theMaxVisPos = m_Scroller->GetMaxVisiblePosition().x;
+ long theVisiblePosition = ::dtol(theMaxVisPos * inOffset / (inTotalLength - inLength));
+ m_Scroller->SetVisiblePosition(
+ CPt(theVisiblePosition, m_Scroller->GetVisiblePosition().y));
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Under construction.
+ */
+void CTimelineTimelineLayout::OnScalingLeft(long inLength, long inTotalLength, long inOffset)
+{
+ // Hey- look at that, doesn't matter which side you're scaling.
+ // Hey, nice comment especially the function header
+ OnScalingRight(inLength, inTotalLength, inOffset);
+}
+
+void CTimelineTimelineLayout::OnScalingReset()
+{
+ SetTimeRatio(DEFAULT_TIME_RATIO);
+}
+
+//=============================================================================
+/**
+ * Set the TimeRatio to be used.
+ * This will propagate the time ratio down to all the child items.
+ * @param inTimeRatio the time ratio to be set.
+ */
+void CTimelineTimelineLayout::SetTimeRatio(double inTimeRatio)
+{
+ if (inTimeRatio != m_TimeRatio) {
+ if (inTimeRatio > 1)
+ inTimeRatio = 1;
+ // if ( inTimeRatio < MAX_ZOOM_OUT )
+ // inTimeRatio = MAX_ZOOM_OUT;
+
+ m_TimeRatio = inTimeRatio;
+ m_TimeMeasure->SetTimeRatio(inTimeRatio);
+
+ TTimelineRowList::iterator thePos = m_Rows.begin();
+ for (; thePos != m_Rows.end(); ++thePos) {
+ CTimelineRow *theRow = (*thePos);
+ theRow->SetTimeRatio(inTimeRatio);
+ }
+
+ RecalcLayout();
+
+ // store the timeline ratio
+ SetTimelineRatio(m_TimelineControl->GetActiveSlide(), m_TimeRatio);
+ qCInfo(qt3ds::TRACE_INFO) << "Set time ratio: " << inTimeRatio;
+ }
+}
+
+//==============================================================================
+/**
+ * When timeline layout has changed. RecalcLayout should be called to adjust the scrollbars if
+ * a asset is expanded/collapsed in the timeline.
+ */
+void CTimelineTimelineLayout::OnTimelineLayoutChanged()
+{
+ RecalcLayout();
+
+ // In addition, this has to be 'marked' for if SetScrollerPositionY is called due to
+ // new assets being added, RecalcLayout has to be called again.
+ m_IsLayoutChanged = true;
+}
+
+/**
+ * Deletes the time zoom ratio for a particular slide.
+ * @param inContext the time context of that slide to delete
+ */
+void CTimelineTimelineLayout::DeleteTimelineRatio(UICDM::CUICDMSlideHandle inSlide)
+{
+ m_TimelineRatio.erase(inSlide);
+}
+
+/**
+ * Clear all entries
+ */
+void CTimelineTimelineLayout::ClearAllTimeRatios()
+{
+ m_TimelineRatio.clear();
+}
+
+/**
+ * Retrieves the time zoom ratio for a particular slide
+ * @param inContext the time context of that slide to retrieve zoom ratio
+ * @return the zoom ratio, or -1 if it's not found
+ */
+double CTimelineTimelineLayout::GetTimelineRatio(UICDM::CUICDMSlideHandle inSlide)
+{
+ TSlideRatioMap::iterator theResult = m_TimelineRatio.find(inSlide);
+ if (theResult != m_TimelineRatio.end())
+ return theResult->second;
+ else
+ return -1;
+}
+
+/**
+ * Sets the time zoom ratio for a particular slide
+ * @param inContext the time context of that slide
+ * @param inRatio the zoom factor
+ */
+void CTimelineTimelineLayout::SetTimelineRatio(UICDM::CUICDMSlideHandle inSlide, double inRatio)
+{
+ m_TimelineRatio[inSlide] = inRatio;
+}
+
+//=============================================================================
+/**
+ * For testing purposes.
+ */
+long CTimelineTimelineLayout::GetMaximumTimebarTime()
+{
+ return 30000;
+}
+
+//=============================================================================
+/**
+ * Call from the TimelineView to notifiy this that some of its objects got filtered.
+ * This was used for redoing the layout but is no longer necessary.
+ */
+void CTimelineTimelineLayout::Filter()
+{
+}
+
+//=============================================================================
+/**
+ * Notification from the CScroller that it is scrolling.
+ * This will update the other views with the verticall scrolling and update
+ * the TimeMeasure with the horizontal scroll amount.
+ * @param inScrollAmount the amount that was scrolled by.
+ */
+void CTimelineTimelineLayout::OnScroll(CScroller *inSource, CPt inScrollAmount)
+{
+ Q_UNUSED(inSource);
+
+ m_TimelineControl->SetScrollPositionY(m_Scroller, m_Scroller->GetVisiblePosition().y);
+
+ long theTimeOffset = GetViewTimeOffset();
+ m_TimeMeasure->SetTimeOffset(theTimeOffset);
+
+ long thePlayheadPos =
+ ::TimeToPos(m_TimelineControl->GetTranslationManager()->GetCurrentViewTime()
+ - theTimeOffset,
+ m_TimeRatio)
+ - m_Playhead.GetCenterOffset();
+
+ m_Playhead.SetPosition(CPt(thePlayheadPos, 0));
+
+ m_DragBeginPoint += inScrollAmount;
+}
+
+void CTimelineTimelineLayout::SetScrollPositionY(CScroller *inSource, long inPositionY,
+ bool inAbsolute)
+{
+ Q_UNUSED(inSource);
+
+ CPt theVisPos = m_Scroller->GetVisiblePosition();
+
+ if (!inAbsolute) {
+ CPt theMaxSize = m_Scroller->GetMaxVisiblePosition();
+
+ CRct theVisibleRect(CPt(theVisPos.x, theMaxSize.y - theVisPos.y),
+ m_Scroller->GetVisibleSize());
+ CPt thePoint(theVisPos.x, inPositionY);
+ if (!theVisibleRect.IsInRect(thePoint))
+ m_Scroller->SetVisiblePosition(CPt(theVisPos.x, inPositionY));
+ } else {
+ // For new assets added, RecalcLayout needs be called here if there was a layout changed
+ // because
+ // m_TimebarList->GetMinimumSize( ).y is only updated at this point, otherwise the tree and
+ // layout will
+ // go out of sync.
+ if (m_IsLayoutChanged)
+ RecalcLayout();
+
+ m_Scroller->SetVisiblePosition(CPt(theVisPos.x, inPositionY));
+ }
+}
+
+//=============================================================================
+/**
+ * Get the scroller control this is using.
+ * Meant for testing purposes.
+ * @return the scroller this is using.
+ */
+CScalableScroller *CTimelineTimelineLayout::GetScroller()
+{
+ return m_Scroller;
+}
+
+//=============================================================================
+/**
+ * Get the playhead control this is using.
+ * Meant for testing purposes.
+ * @return the playhead this is using.
+ */
+CPlayhead *CTimelineTimelineLayout::GetPlayhead()
+{
+ return &m_Playhead;
+}
+
+//=============================================================================
+/**
+ * Scroll the contents of the timeline horizontally.
+ * This is used mainly by the playhead to scroll the view when it gets to the
+ * edge.
+ * @param inAmount the amount to scroll the view by.
+ * @return the amount actually scrolled, limited by min/max values.
+ */
+long CTimelineTimelineLayout::ScrollLayout(long inAmount)
+{
+ // Log the current position for returning
+ CPt thePosition = m_Scroller->GetVisiblePosition();
+
+ m_Scroller->SetVisiblePosition(CPt(thePosition.x + inAmount, thePosition.y));
+
+ // Return how much was actually scrolled, let the scroller handle min/max scroll amounts.
+ return m_Scroller->GetVisiblePosition().x - thePosition.x;
+}
+
+//=============================================================================
+/**
+ * Recalculate what the time is based on the location of the playhead.
+ * This will call SetTime on the TimelineView with the new time.
+ * @param inUpdateClient true if the client time should be updated.
+ */
+void CTimelineTimelineLayout::RecalcTime(bool inUpdateClient, long inFlags)
+{
+ long theOffset = m_Playhead.GetPosition().x + m_Playhead.GetCenterOffset()
+ + m_Scroller->GetVisiblePosition().x;
+
+ long theTime = ::PosToTime(theOffset, m_TimeRatio);
+ m_Snapper.InterpretTimeEx(theTime, inFlags);
+
+ // Update the time
+ m_Playhead.UpdateTime(theTime, inUpdateClient);
+}
+
+//=============================================================================
+/**
+ * Call from the timeline view that the time is changing.
+ * @param inNewTime the new time.
+ * @param inIsSecondary lame flag to prevent infinite recursion.
+ */
+void CTimelineTimelineLayout::SetTime(long inNewTime, bool inIsSecondary)
+{
+ long theOffset = ::TimeToPos(inNewTime, m_TimeRatio);
+ theOffset -= m_Scroller->GetVisiblePosition().x + m_Playhead.GetCenterOffset();
+
+ long theViewSize = m_Scroller->GetVisibleSize().x;
+
+ if (!inIsSecondary) {
+ if (theOffset < -m_Playhead.GetCenterOffset()) {
+ long thePos = ::TimeToPos(inNewTime, m_TimeRatio) - m_Playhead.GetCenterOffset();
+ m_Scroller->SetVisiblePosition(CPt(thePos, m_Scroller->GetVisiblePosition().y));
+ } else if (theOffset > (theViewSize - (m_Playhead.GetCenterOffset() + 20))) {
+ long thePos = ::TimeToPos(inNewTime, m_TimeRatio) + 20;
+ thePos -= theViewSize;
+ m_Scroller->SetVisiblePosition(CPt(thePos, m_Scroller->GetVisiblePosition().y));
+ }
+ SetTime(inNewTime, true);
+ } else {
+ m_Playhead.SetPosition(CPt(theOffset, m_Playhead.GetPosition().y));
+ }
+}
+
+//=============================================================================
+/**
+ * Notification that the TimeMeasure was clicked on.
+ * This is used to reposition the playhead wherever the mouse was clicked.
+ * @param inPoint the location of the mouse local to the time measure.
+ */
+void CTimelineTimelineLayout::OnTimeMeasureMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ Q_UNUSED(inFlags);
+
+ m_Snapper.Clear();
+ m_Snapper.SetSource(&m_Playhead);
+ PopulateSnappingList(&m_Snapper);
+ m_Snapper.SetSnappingKeyframes(true);
+
+ m_Playhead.SetPosition(
+ CPt(inPoint.x - m_Playhead.GetCenterOffset(), m_Playhead.GetPosition().y));
+ RecalcTime(true, inFlags);
+}
+
+//=============================================================================
+/**
+ * Handles left-clicks. Starts a drag operation if a child does not handle the
+ * message.
+ * @param inPoint location of the mouse when event occurred
+ * @param inFlags state of modifier keys when event occurred
+ */
+bool CTimelineTimelineLayout::OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ if (!CControl::OnMouseDown(inPoint, inFlags)) {
+ m_BoundingRect->SetSize(CPt(0, 0));
+ m_BoundingRect->SetVisible(true);
+
+ // Do not deselect all keyframes as the user intends to select more keyframes,
+ // when the modifier key is pressed.
+ if (!(inFlags & MODIFIER_KEY))
+ m_TimelineControl->GetTranslationManager()->ClearKeyframeSelection();
+
+ m_IsMouseDown = true;
+ m_DragBeginPoint = inPoint;
+ }
+ return true;
+}
+
+void CTimelineTimelineLayout::OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseMove(inPoint, inFlags);
+
+ if (m_IsMouseDown) {
+ CPt theSize;
+ CRct theRect;
+
+ // Tests if the user has pressed the modifier key, while moving the mouse.
+ bool theModifierKeyDown;
+ if (inFlags & MODIFIER_KEY)
+ theModifierKeyDown = true;
+ else
+ theModifierKeyDown = false;
+
+ // Calculate the rect for the bounding box
+ theSize = CPt(inPoint.x - m_DragBeginPoint.x, inPoint.y - m_DragBeginPoint.y);
+ theRect = CRct(m_DragBeginPoint, theSize);
+ theRect.Normalize();
+ m_BoundingRect->SetPosition(theRect.position);
+ m_BoundingRect->SetSize(theRect.size);
+ theRect.Offset(-m_Scroller->GetPosition());
+ theRect.Offset(m_Scroller->GetVisiblePosition());
+
+ // Select all keys inside the rect
+
+ TTimelineRowList::iterator thePos = m_Rows.begin();
+
+ for (; thePos != m_Rows.end(); ++thePos) {
+ CStateRow *theRow = reinterpret_cast<CStateRow *>(*thePos);
+ theRow->SelectKeysInRect(theRect, theModifierKeyDown, m_CommitKeyframeSelection);
+ }
+ m_CommitKeyframeSelection = false;
+ }
+}
+
+void CTimelineTimelineLayout::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ // try to prevent stuck mousetips on exceptions
+ try {
+ CControl::OnMouseUp(inPoint, inFlags);
+ m_BoundingRect->SetVisible(false);
+ } catch (...) {
+ }
+
+ m_IsMouseDown = false;
+
+ // Commits the key frame selection. This finalises the keyframes selection
+ // in the rect. When the mouse is down again, we would be able to append
+ // the commited keyframes with the new batch of keyframes.
+ m_CommitKeyframeSelection = true;
+}
+
+void CTimelineTimelineLayout::PopulateSnappingList(CSnapper *inSnappingList)
+{
+ CRct theArea(m_Scroller->GetVisibleSize());
+ theArea.Offset(-m_Scroller->GetPosition());
+ theArea.Offset(m_Scroller->GetVisiblePosition());
+
+ inSnappingList->SetVisibleArea(theArea.position.y, theArea.size.y);
+
+ inSnappingList->SetTimeRatio(m_TimeRatio);
+ if (inSnappingList->GetSource() != &m_Playhead)
+ inSnappingList->AddTime(m_Playhead.GetCurrentTime());
+
+ m_TimeMeasure->PopulateSnappingList(inSnappingList);
+
+ TTimelineRowList::iterator theRowIter = m_Rows.begin();
+ for (; theRowIter != m_Rows.end(); ++theRowIter) {
+ (*theRowIter)->PopulateSnappingList(inSnappingList);
+ }
+}
+
+long CTimelineTimelineLayout::GetViewTimeOffset()
+{
+ return ::dtol(m_Scroller->GetVisiblePosition().x / m_TimeRatio);
+}
+
+CTimeMeasure *CTimelineTimelineLayout::GetTimeMeasure()
+{
+ return m_TimeMeasure;
+}
+
+//=============================================================================
+/**
+ * Register all the events for hotkeys that are active for the entire application.
+ * Hotkeys for the entire application are ones that are not view specific in
+ * scope.
+ * @param inShortcutHandler the global shortcut handler.
+ */
+void CTimelineTimelineLayout::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CTimelineTimelineLayout>(
+ this, &CTimelineTimelineLayout::OnScalingZoomIn),
+ 0, Qt::Key_Plus);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CTimelineTimelineLayout>(
+ this, &CTimelineTimelineLayout::OnScalingZoomOut),
+ 0, Qt::Key_Minus);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CTimelineTimelineLayout>(
+ this, &CTimelineTimelineLayout::OnScalingZoomIn),
+ Qt::KeypadModifier, Qt::Key_Plus);
+ inShortcutHandler->RegisterKeyDownEvent(new CDynHotKeyConsumer<CTimelineTimelineLayout>(
+ this, &CTimelineTimelineLayout::OnScalingZoomOut),
+ Qt::KeypadModifier, Qt::Key_Minus);
+}
+
+//=============================================================================
+/**
+ * Call from the Hotkey that it is zooming in the timebar.
+ */
+
+void CTimelineTimelineLayout::OnScalingZoomIn()
+{
+ double theTimeRatio = m_TimeRatio * SCALING_PERCENTAGE_INC;
+
+ SetTimeRatio(theTimeRatio);
+ CenterToPlayhead();
+}
+
+//=============================================================================
+/**
+ * Call from the Hotkey that it is zooming out of the timebar.
+ */
+
+void CTimelineTimelineLayout::OnScalingZoomOut()
+{
+ double theTimeRatio = m_TimeRatio * SCALING_PERCENTAGE_DEC;
+
+ SetTimeRatio(theTimeRatio);
+ CenterToPlayhead();
+}
+
+void CTimelineTimelineLayout::CenterToPlayhead()
+{
+ long theTime = m_Playhead.GetCurrentTime();
+ long thePos = ::TimeToPos(theTime, m_TimeRatio);
+ long theNewPosX = thePos - (m_Scroller->GetSize().x / 2);
+
+ m_Scroller->SetVisiblePosition(CPt(theNewPosX, m_Scroller->GetVisiblePosition().y));
+}
+
+//==============================================================================
+/**
+ * Handle mouse wheel messages to allow zooming
+ */
+bool CTimelineTimelineLayout::OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags)
+{
+ bool theRetVal = false;
+ if (inFlags & CHotKeys::MODIFIER_CONTROL) {
+ if (inAmount > 0)
+ OnScalingZoomIn();
+ else
+ OnScalingZoomOut();
+ theRetVal = true;
+ } else
+ theRetVal = CControl::OnMouseWheel(inPoint, inAmount, inFlags);
+ return theRetVal;
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.h b/src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.h
new file mode 100644
index 00000000..35524d5b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineTimelineLayout.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef INCLUDED_TIMELINE_TIMELINE_LAYOUT_H
+#define INCLUDED_TIMELINE_TIMELINE_LAYOUT_H 1
+
+#pragma once
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "Control.h"
+#include <vector>
+#include "ScalableScrollerBar.h"
+#include "Scroller.h"
+#include "Pt.h"
+#include "Snapper.h"
+#include "AreaBoundingRect.h"
+#include "Playhead.h"
+#include "UICDMHandles.h"
+
+//=============================================================================
+// Forwards
+//=============================================================================
+class CScalableScroller;
+class CTimelineRow;
+class CFlowLayout;
+class CTimelineControl;
+class CSnapper;
+class IDoc;
+class CHotKeys;
+class CTimeMeasure;
+class CPlayhead;
+
+//=============================================================================
+/**
+ * Right-hand pane of the Timeline containing timebars, keyframes, etc.
+ */
+class CTimelineTimelineLayout : public CControl,
+ public CScalingListener,
+ public CScrollListener,
+ public ISnappingListProvider
+{
+ typedef std::vector<CTimelineRow *> TTimelineRowList;
+ typedef std::map<UICDM::CUICDMSlideHandle, double> TSlideRatioMap;
+
+public:
+ static const long END_BUFFER_SIZE = 20;
+ static const double SCALING_PERCENTAGE_INC;
+ static const double SCALING_PERCENTAGE_DEC;
+ static const double MAX_ZOOM_OUT;
+
+ CTimelineTimelineLayout(CTimelineControl *inView, IDoc *inDoc);
+ virtual ~CTimelineTimelineLayout();
+
+ void SetSize(CPt inSize) override;
+
+ void AddRow(CTimelineRow *inRow);
+
+ void OnScalingRight(long inLength, long inTotalLength, long inOffset) override;
+ void OnScalingLeft(long inLength, long inTotalLength, long inOffset) override;
+ void OnScalingReset() override;
+
+ long ScrollLayout(long inAmount);
+
+ void Filter();
+
+ void OnScroll(CScroller *inScroller, CPt inScrollAmount) override;
+ void SetScrollPositionY(CScroller *inSource, long inPositionY, bool inAbsolute = true);
+
+ void ClearRows();
+
+ bool OnMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseMove(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ bool OnMouseWheel(CPt inPoint, long inAmount, Qt::KeyboardModifiers inFlags) override;
+
+ CScalableScroller *GetScroller();
+ CPlayhead *GetPlayhead();
+ CTimeMeasure *GetTimeMeasure();
+ void RecalcTime(bool inUpdateClient, long inFlags);
+ void SetTime(long inTime, bool inIsSecondary = false);
+ void OnTimeMeasureMouseDown(CPt inPoint, Qt::KeyboardModifiers inFlags);
+ long GetViewTimeOffset();
+ void RecalcLayout();
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+ void SetTimeRatio(double inTimeRatio);
+ void OnTimelineLayoutChanged();
+
+ void DeleteTimelineRatio(UICDM::CUICDMSlideHandle inSlide);
+ void ClearAllTimeRatios();
+ double GetTimelineRatio(UICDM::CUICDMSlideHandle inSlide);
+
+ // ISnappingListProvider
+ void PopulateSnappingList(CSnapper *inSnappingList) override;
+
+protected:
+ void SetTimelineRatio(UICDM::CUICDMSlideHandle inSlide, double inRatio);
+
+ long GetMaximumTimebarTime();
+ void OnScalingZoomIn();
+ void OnScalingZoomOut();
+ void CenterToPlayhead();
+
+ bool m_CommitKeyframeSelection; ///< flag for saving previous keyframe selection when the mouse
+ ///is released.
+ CTimelineControl *m_TimelineControl;
+ CTimeMeasure *m_TimeMeasure;
+ CScalableScroller *m_Scroller;
+ CFlowLayout *m_TimebarList;
+ double m_TimeRatio;
+
+ TTimelineRowList m_Rows;
+ CPlayhead m_Playhead;
+ CSnapper m_Snapper;
+ bool m_IsLayoutChanged; ///< flag to keep track of a need for a delayed RecalcLayout
+
+ bool m_IsMouseDown;
+ CPt m_DragBeginPoint;
+ CAreaBoundingRect *m_BoundingRect;
+
+ TSlideRatioMap m_TimelineRatio; ///< stores the time zooming ratios for each slide
+};
+#endif // INCLUDED_TIMELINE_TIMELINE_LAYOUT_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.cpp b/src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.cpp
new file mode 100644
index 00000000..1229b88b
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "TimelineTreeLayout.h"
+#include "FlowLayout.h"
+#include "Scroller.h"
+#include "StateRow.h"
+#include "FilterToolbar.h"
+#include "ToggleToolbar.h"
+#include "TimeToolbar.h"
+#include "StudioPreferences.h"
+#include "TimelineControl.h"
+#include "Renderer.h"
+#include "ToggleBlankControl.h"
+#include "ColorBlankControl.h"
+#include "TreeBlankControl.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimelineTreeLayout::CTimelineTreeLayout(CTimelineControl *inTimelineControl, IDoc *inDoc)
+ : m_IsScrolling(false)
+{
+ m_TimelineControl = inTimelineControl;
+
+ m_ColorScroller = new CScroller();
+ m_ColorScroller->SetHorizontalScrollMode(CScroller::NEVER);
+ m_ColorScroller->SetVerticalScrollMode(CScroller::NEVER);
+ m_ColorScroller->AddScrollListener(this);
+
+ m_ColorBlankControl = new CColorBlankControl();
+ m_ColorList = new CFlowLayout(m_ColorBlankControl);
+ m_ColorScroller->AddChild(m_ColorList);
+
+ m_ToggleScroller = new CScroller();
+ m_ToggleScroller->SetHorizontalScrollMode(CScroller::NEVER);
+ m_ToggleScroller->SetVerticalScrollMode(CScroller::NEVER);
+
+ m_ToggleBlankControl = new CToggleBlankControl();
+ m_ToggleList = new CFlowLayout(m_ToggleBlankControl);
+ m_ToggleScroller->AddChild(m_ToggleList);
+ m_ToggleScroller->AddScrollListener(this);
+
+ m_TreeScroller = new CScroller();
+ m_TreeScroller->SetVerticalScrollMode(CScroller::NEVER);
+ m_TreeScroller->SetHorizontalScrollMode(CScroller::ALWAYS);
+ m_TreeScroller->AddScrollListener(this);
+
+ m_TreeBlankControl = new CTreeBlankControl();
+ m_TreeList = new CFlowLayout(m_TreeBlankControl);
+ m_TreeScroller->AddChild(m_TreeList);
+
+ m_FilterToolbar = new CFilterToolbar(this);
+ m_TimeToolbar = new CTimeToolbar(inDoc);
+ m_ToggleToolbar = new CToggleToolbar(this);
+
+ AddChild(m_TreeScroller);
+ AddChild(m_ToggleScroller);
+ AddChild(m_TimeToolbar);
+ AddChild(m_ToggleToolbar);
+ AddChild(m_ColorScroller);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimelineTreeLayout::~CTimelineTreeLayout()
+{
+ m_ColorScroller->RemoveChild(m_ColorList);
+ m_ToggleScroller->RemoveChild(m_ToggleList);
+ m_TreeScroller->RemoveChild(m_TreeList);
+
+ RemoveChild(m_TreeScroller);
+ RemoveChild(m_ToggleScroller);
+ RemoveChild(m_TimeToolbar);
+ RemoveChild(m_FilterToolbar);
+ RemoveChild(m_ToggleToolbar);
+ RemoveChild(m_ColorScroller);
+ // RemoveChild( m_BreadCrumbToolbar );
+
+ delete m_FilterToolbar;
+ delete m_TimeToolbar;
+ delete m_ToggleToolbar;
+ delete m_ColorScroller;
+ delete m_ColorList;
+ delete m_ToggleScroller;
+ delete m_ToggleList;
+ delete m_TreeList;
+ delete m_TreeScroller;
+ // delete m_BreadCrumbToolbar;
+
+ // Delete all the rows, this control is responsible for the rows, maybe it should not
+ // be but currently it is.
+ TTimelineRowList::iterator thePos = m_Rows.begin();
+ for (; thePos != m_Rows.end(); ++thePos) {
+ CTimelineRow *theRow = (*thePos);
+ theRow->Dispose(); // Dispose will delete the row as well
+ }
+}
+
+//=============================================================================
+/**
+ * Clear out all the contents of this tree layout.
+ * This will also delete all the rows, so make sure it is called after the
+ * TimelineTimelineLayout::ClearRows is called.
+ */
+void CTimelineTreeLayout::ClearRows()
+{
+ TTimelineRowList::iterator thePos = m_Rows.begin();
+ for (; thePos != m_Rows.end(); ++thePos) {
+ CTimelineRow *theRow = (*thePos);
+ m_ColorList->RemoveChild(theRow->GetColorControl());
+ m_TreeList->RemoveChild(theRow->GetTreeControl());
+ m_ToggleList->RemoveChild(theRow->GetToggleControl());
+
+ theRow->Dispose();
+ }
+
+ m_Rows.clear();
+}
+
+//=============================================================================
+/**
+ * Set the filter back to it's default state.
+ */
+void CTimelineTreeLayout::ResetFilter()
+{
+ m_FilterToolbar->FilterBehaviors(false);
+ m_FilterToolbar->FilterProperties(false);
+ m_FilterToolbar->FilterMaterials(false);
+ m_FilterToolbar->FilterShy(false);
+}
+
+//=============================================================================
+/**
+ * Set the size of this control.
+ * Overrides CControl::SetSize so that RecalcLayout can be called.
+ */
+void CTimelineTreeLayout::SetSize(CPt inSize)
+{
+ if (inSize != GetSize()) {
+ CControl::SetSize(inSize);
+
+ RecalcLayout();
+ }
+}
+
+//=============================================================================
+/**
+ * Recalculate the layout of all the child components.
+ * Called when this changes size and all the children need to be repositioned.
+ */
+void CTimelineTreeLayout::RecalcLayout()
+{
+ CPt mySize = GetSize();
+ long theHeaderHeight = CStudioPreferences::GetHeaderHeight();
+
+ m_FilterToolbar->SetSize(CPt(120, theHeaderHeight));
+ m_FilterToolbar->SetPosition(0, 0);
+
+ m_ToggleToolbar->SetSize(CPt(61, theHeaderHeight));
+ m_ToggleToolbar->SetPosition(mySize.x - m_ToggleToolbar->GetSize().x, 0);
+
+ m_TimeToolbar->SetSize(CPt(mySize.x - m_ToggleToolbar->GetSize().x, theHeaderHeight));
+ m_TimeToolbar->SetPosition(0, 0);
+
+ m_ColorScroller->SetSize(CPt(CStudioPreferences::GetRowSize(), mySize.y - theHeaderHeight
+ - m_TreeScroller->GetHorizontalBar()->GetMinimumSize().y
+ - theHeaderHeight));
+ m_ColorScroller->SetPosition(0, theHeaderHeight);
+
+ m_ToggleScroller->SetSize(CPt(m_ToggleToolbar->GetSize().x, mySize.y - theHeaderHeight
+ - m_TreeScroller->GetHorizontalBar()->GetMinimumSize().y
+ - theHeaderHeight));
+ m_ToggleScroller->SetPosition(mySize.x - m_ToggleScroller->GetSize().x, theHeaderHeight);
+
+ m_TreeScroller->SetSize(
+ CPt(mySize.x, mySize.y - m_FilterToolbar->GetSize().y - theHeaderHeight));
+ m_TreeScroller->SetPosition(0, theHeaderHeight);
+
+ m_TreeScroller->SetAdditionalClippingRect(
+ CRct(m_ColorScroller->GetSize().x, 0,
+ m_ToggleScroller->GetPosition().x - m_ColorScroller->GetSize().x,
+ m_TreeScroller->GetSize().y));
+}
+
+//=============================================================================
+/**
+ * Add another top level item to the left side of the timeline.
+ * If there is already a top level item then this one will be appended to the
+ * list.
+ * @param inRow the row to be added.
+ */
+void CTimelineTreeLayout::AddRow(CTimelineRow *inRow)
+{
+ m_ColorList->AddChild(inRow->GetColorControl());
+ m_TreeList->AddChild(inRow->GetTreeControl());
+ m_ToggleList->AddChild(inRow->GetToggleControl());
+
+ m_Rows.push_back(inRow);
+
+ inRow->SetIndent(20);
+
+ inRow->Filter(m_Filter);
+}
+
+//=============================================================================
+/**
+ * Applies the current filter settings to the timeline. Although the filter
+ * preferences can be set independently, they are not actually applied until
+ * this function is called.
+ */
+void CTimelineTreeLayout::Filter()
+{
+ for (TTimelineRowList::iterator thePos = m_Rows.begin(); thePos != m_Rows.end(); ++thePos) {
+ CTimelineRow *theRow = *thePos;
+ theRow->Filter(m_Filter);
+ }
+
+ // TODO: sk - it is unclear to me what this is trying to do.. I am leavint this here till it
+ // becomes obvious it is totally redundant OR someone finds a related bug
+ /*
+ // Call OnSelect( ) on the selected object (if there is one) to get the timeline to scroll down.
+ CAsset* theSelectedObject = dynamic_cast<CAsset*>( m_Doc->GetSelectedObject( ) );
+ if ( theSelectedObject )
+ theSelectedObject->OnSelect( );
+
+ m_TimelineControl->GetTimelineLayout( )->RecalcLayout( );
+ */
+}
+
+void CTimelineTreeLayout::OnScroll(CScroller *inSource, CPt inScrollAmount)
+{
+ Q_UNUSED(inScrollAmount);
+
+ // SetScrollPositionY triggers another onScroll event and potentially causes the position
+ // to be set incorrectly.
+ if (!m_IsScrolling) {
+ m_IsScrolling = true;
+ m_TreeBlankControl->SetVisiblePositionX(inSource->GetVisiblePosition().x);
+ m_TimelineControl->SetScrollPositionY(inSource, inSource->GetVisiblePosition().y);
+ m_IsScrolling = false;
+ }
+}
+
+//=============================================================================
+/**
+ * Set the vertical position of all the scrollers in this view.
+ * This is used to sync up the positions with the timebar scroller view.
+ * @param inScrollPositionY the position of the scroller.
+ */
+void CTimelineTreeLayout::SetScrollPositionY(CScroller *inSource, long inScrollPositionY,
+ bool inAbsolute)
+{
+ Q_UNUSED(inSource);
+
+ if (!inAbsolute) {
+ CRct theVisibleRect(m_ColorScroller->GetVisiblePosition(),
+ m_ColorScroller->GetVisibleSize());
+ CPt thePoint(m_ColorScroller->GetVisiblePosition().x, inScrollPositionY);
+ if (!theVisibleRect.IsInRect(thePoint)) {
+ m_ColorScroller->SetVisiblePosition(
+ CPt(m_ColorScroller->GetVisiblePosition().x, inScrollPositionY));
+ m_TreeScroller->SetVisiblePosition(
+ CPt(m_TreeScroller->GetVisiblePosition().x, inScrollPositionY));
+ m_ToggleScroller->SetVisiblePosition(
+ CPt(m_ToggleScroller->GetVisiblePosition().x, inScrollPositionY));
+ }
+ } else {
+ m_ColorScroller->SetVisiblePosition(
+ CPt(m_ColorScroller->GetVisiblePosition().x, inScrollPositionY));
+ m_TreeScroller->SetVisiblePosition(
+ CPt(m_TreeScroller->GetVisiblePosition().x, inScrollPositionY));
+ m_ToggleScroller->SetVisiblePosition(
+ CPt(m_ToggleScroller->GetVisiblePosition().x, inScrollPositionY));
+ }
+}
+
+//=============================================================================
+/**
+ * Sets the time on the Time header display time.
+ * @param inTime the new time.
+ */
+void CTimelineTreeLayout::SetTime(long inTime)
+{
+ m_TimeToolbar->SetTime(inTime);
+}
+
+//=============================================================================
+/**
+ * This is overridden so the Gesture can Notify Drop Listeners that its time to Drop.
+ * If the gesture is dragging something then wee will drop.
+ */
+void CTimelineTreeLayout::OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags)
+{
+ CControl::OnMouseUp(inPoint, inFlags);
+}
+
+//=============================================================================
+/**
+ * Returns the playhead time
+ */
+long CTimelineTreeLayout::GetTime()
+{
+ return m_TimeToolbar->GetTime();
+}
+
+//=============================================================================
+/**
+ * @return rectangle describing the visible area of the tree control
+ */
+CRct CTimelineTreeLayout::GetVisibleArea()
+{
+ CPt theUpperLeftCorner;
+ CPt theSize;
+
+ theUpperLeftCorner.x = m_ColorScroller->GetSize().x;
+ theUpperLeftCorner.y = CStudioPreferences::GetHeaderHeight();
+ theSize.x = m_ToggleScroller->GetPosition().x - theUpperLeftCorner.x;
+ theSize.y = ::abs(m_ToggleScroller->GetPosition().y - m_ToggleScroller->GetSize().y)
+ - theUpperLeftCorner.y;
+
+ return CRct(theUpperLeftCorner, theSize);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.h b/src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.h
new file mode 100644
index 00000000..004bf3b7
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TimelineTreeLayout.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef INCLUDED_TIMELINE_TREE_LAYOUT_H
+#define INCLUDED_TIMELINE_TREE_LAYOUT_H 1
+
+#pragma once
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "Control.h"
+#include "TimelineFilter.h"
+#include "Scroller.h"
+#include <vector>
+
+//=============================================================================
+// Forwards
+//=============================================================================
+class CFlowLayout;
+class CScroller;
+class CFilterToolbar;
+class CTimelineRow;
+class CToggleToolbar;
+class CTimeToolbar;
+class CTimelineControl;
+class IDoc;
+class CRenderer;
+class CToggleBlankControl;
+class CColorBlankControl;
+class CTreeBlankControl;
+
+//=============================================================================
+/**
+ * Class for tree control on the timeline palette.
+ */
+class CTimelineTreeLayout : public CControl, public CScrollListener
+{
+ typedef std::vector<CTimelineRow *> TTimelineRowList;
+
+public:
+ CTimelineTreeLayout(CTimelineControl *inTimelineControl, IDoc *inDoc);
+ virtual ~CTimelineTreeLayout();
+
+ // CControl
+ void OnMouseUp(CPt inPoint, Qt::KeyboardModifiers inFlags) override;
+ void SetSize(CPt inSize) override;
+
+ virtual void AddRow(CTimelineRow *inRow);
+
+ /// Returns a filter object so that filter preferences can be set. You must call Filter() in
+ /// order to apply the filters once you make your changes.
+ CFilter *GetFilter() { return &m_Filter; }
+ void Filter();
+
+ void OnScroll(CScroller *inScroller, CPt inScrollAmount) override;
+ void SetScrollPositionY(CScroller *inSource, long inPositionY, bool inAbsolute = true);
+
+ void ClearRows();
+
+ void SetTime(long inTime);
+ long GetTime();
+ void ResetFilter();
+ CRct GetVisibleArea();
+ void RecalcLayout();
+
+protected:
+ CFilter m_Filter;
+ CFilterToolbar
+ *m_FilterToolbar; ///< Control at the top of the timeline containing filter buttons.
+ CTimeToolbar *m_TimeToolbar; ///< Control at the top containing the time display
+ CToggleToolbar
+ *m_ToggleToolbar; ///< Control at the top containing a header for the toggle column.
+
+ CScroller *m_ColorScroller;
+ CFlowLayout *m_ColorList;
+ CColorBlankControl *m_ColorBlankControl;
+
+ CScroller *m_ToggleScroller;
+ CFlowLayout *m_ToggleList;
+ CToggleBlankControl *m_ToggleBlankControl;
+
+ CScroller *m_TreeScroller;
+ CFlowLayout *m_TreeList;
+ CTreeBlankControl *m_TreeBlankControl;
+
+ TTimelineRowList m_Rows;
+ CTimelineControl *m_TimelineControl; ///< Parent control of this control
+
+ bool
+ m_IsScrolling; ///< Flag to not process onScroll that was triggered from a previous onScroll
+};
+#endif // INCLUDED_TIMELINE_TREE_LAYOUT_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.cpp b/src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.cpp
new file mode 100644
index 00000000..c9ffff8e
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ToggleBlankControl.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CToggleBlankControl::CToggleBlankControl(CColor inColor)
+ : CBlankControl(inColor)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CToggleBlankControl::~CToggleBlankControl()
+{
+}
+
+//=============================================================================
+/**
+ * Handles custom drawing of the blank control underneath the tree control
+ * on the timeline palette.
+ */
+void CToggleBlankControl::Draw(CRenderer *inRenderer)
+{
+ CBlankControl::Draw(inRenderer);
+
+ // Draw the line on the right side of this control
+ CPt theSize = GetSize();
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ inRenderer->MoveTo(theSize.x - 1, 0);
+ inRenderer->LineTo(theSize.x - 1, theSize.y - 1);
+ inRenderer->PopPen();
+
+ // Draw the line on the left side of this control
+ inRenderer->PushPen(CStudioPreferences::GetPropertyFloorColor());
+ inRenderer->MoveTo(CPt(0, 0));
+ inRenderer->LineTo(CPt(0, theSize.y - 1));
+ inRenderer->PopPen();
+
+ // Draw the highlight
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(1, 0));
+ inRenderer->LineTo(CPt(1, theSize.y - 1));
+ inRenderer->PopPen();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.h b/src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.h
new file mode 100644
index 00000000..ac07f7db
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ToggleBlankControl.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TOGGLE_BLANK_CONTROL_H
+#define INCLUDED_TOGGLE_BLANK_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BlankControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//=============================================================================
+/**
+ * Extends the blank control to draw items specific to the tree view side of the
+ * timeline palette.
+ */
+class CToggleBlankControl : public CBlankControl
+{
+public:
+ CToggleBlankControl(CColor inColor = CStudioPreferences::GetBaseColor());
+ virtual ~CToggleBlankControl();
+ void Draw(CRenderer *inRenderer) override;
+
+protected:
+};
+
+#endif // INCLUDED_TOGGLE_BLANK_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ToggleControl.cpp b/src/Authoring/Studio/Palettes/Timeline/ToggleControl.cpp
new file mode 100644
index 00000000..7abc00d4
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ToggleControl.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "ToggleControl.h"
+#include "Renderer.h"
+#include "StateRow.h"
+#include "BlankControl.h"
+#include "HotKeys.h"
+#include "Bindings/ITimelineItemBinding.h"
+
+CToggleControl::CToggleControl(CStateRow *inStateRow, ITimelineItemBinding *inTimelineItemBinding)
+ : CBlankToggleControl(inStateRow)
+ , m_TimelineItemBinding(inTimelineItemBinding)
+{
+ m_StateRow = inStateRow;
+ long theLeftOffset = 4;
+
+ m_Shy = new CToggleButton();
+ m_Shy->SetName("ShyToggle");
+ m_Shy->SetUpImage("Toggle-Empty.png");
+ m_Shy->SetDownImage("Toggle-Shy.png");
+ m_Shy->SetPosition(CPt(theLeftOffset, 0));
+ CPt theShySize = m_Shy->GetSize();
+
+ m_Visible = new CToggleButton();
+ m_Visible->SetName("VisibilityToggle");
+ m_Visible->SetUpImage("Toggle-Empty.png");
+ m_Visible->SetDownImage("Toggle-HideShow.png");
+ m_Visible->SetUpDisabledImage("Toggle-Empty.png"); // show empty if disabled
+ m_Visible->SetDisabledImage("Toggle-HideShow-disabled.png");
+ m_Visible->SetPosition(CPt(theShySize.x + 7, 0));
+ CPt theVisibleSize = m_Visible->GetSize();
+
+ m_Locked = new CToggleButton();
+ m_Locked->SetName("LockToggle");
+ m_Locked->SetUpImage("Toggle-Empty.png");
+ m_Locked->SetDownImage("Toggle-Lock.png");
+ m_Locked->SetPosition(CPt(theVisibleSize.x + theShySize.x + 10, 0));
+ CPt theLockedSize = m_Locked->GetSize();
+
+ AddChild(m_Shy);
+ AddChild(m_Visible);
+ AddChild(m_Locked);
+
+ SetAbsoluteSize(CPt(theShySize.x + theVisibleSize.x + theLockedSize.x + 1, theShySize.y));
+
+ // Button down listeners
+ m_Shy->SigToggle.connect(std::bind(&CToggleControl::OnShyClicked, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_Visible->SigToggle.connect(std::bind(&CToggleControl::OnVisibleClicked, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_Locked->SigToggle.connect(std::bind(&CToggleControl::OnLockClicked, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ ITimelineItem *theTimelineItem = m_TimelineItemBinding->GetTimelineItem();
+ // Initial toggle state of the eye visibility button
+ // Note GetViewToggleOff==FALSE means visible
+ m_Visible->SetToggleState(theTimelineItem->IsVisible());
+
+ // Initial toggle state of the button
+ m_Locked->SetToggleState(theTimelineItem->IsLocked());
+
+ // Initial toggle state of the button
+ m_Shy->SetToggleState(theTimelineItem->IsShy());
+
+ // sk - if anything, this should be checked in the data model level, not here.
+ // The tri-state (on, off, dim) of visibility depends on two bools:
+ // GetViewToggleOff and IsEnabled. Ensure that any bogus 4th permutation
+ // is detected ASAP
+ // ASSERT( !inStateRow->GetState( )->GetViewToggleOff( ) ||
+ // !inStateRow->GetState( )->IsEnabled( ) );
+}
+
+CToggleControl::~CToggleControl()
+{
+ delete m_Shy;
+ delete m_Visible;
+ delete m_Locked;
+}
+
+//==============================================================================
+/**
+ * Handles clicking on the Shy button. Toggles the shy state on the asset. Shy
+ * objects can be filtered out of the timeline.
+ */
+void CToggleControl::OnShyClicked(CToggleButton *, CToggleButton::EButtonState inButtonState)
+{
+ m_TimelineItemBinding->GetTimelineItem()->SetShy(inButtonState
+ == CToggleButton::EBUTTONSTATE_DOWN);
+
+ m_StateRow->Filter(*m_StateRow->GetFilter());
+ CBaseStateRow *theParentRow = m_StateRow->GetParentRow();
+ if (theParentRow != nullptr)
+ theParentRow->OnChildVisibilityChanged();
+}
+
+//==============================================================================
+/**
+ * Handles clicking on the Visible button. Toggles the Visible state on the asset.
+ */
+void CToggleControl::OnVisibleClicked(CToggleButton *inButton,
+ CToggleButton::EButtonState inButtonState)
+{
+ Q_UNUSED(inButton);
+
+ m_TimelineItemBinding->GetTimelineItem()->SetVisible(inButtonState
+ == CToggleButton::EBUTTONSTATE_DOWN);
+ m_StateRow->Filter(*m_StateRow->GetFilter());
+}
+
+//==============================================================================
+/**
+ * Handles clicking on the Lock button. Toggles the Lock state on the asset.
+ */
+void CToggleControl::OnLockClicked(CToggleButton *inButton,
+ CToggleButton::EButtonState inButtonState)
+{
+ Q_UNUSED(inButton);
+
+ m_TimelineItemBinding->GetTimelineItem()->SetLocked(inButtonState
+ == CToggleButton::EBUTTONSTATE_DOWN);
+ m_StateRow->Filter(*m_StateRow->GetFilter());
+}
+
+//==============================================================================
+/**
+ * Refreshes the state of this control accd to the asset state
+ */
+void CToggleControl::Refresh()
+{
+ CBlankToggleControl::Refresh();
+
+ ITimelineItem *theTimelineItem = m_TimelineItemBinding->GetTimelineItem();
+ m_Shy->SetToggleState(theTimelineItem->IsShy());
+ m_Locked->SetToggleState(theTimelineItem->IsLocked());
+
+ bool theEnabled = m_TimelineItemBinding->IsVisibleEnabled();
+ m_Visible->SetEnabled(theEnabled);
+ if (theEnabled) // only valid to update this if the enabled flag is true.
+ m_Visible->SetToggleState(theTimelineItem->IsVisible());
+
+ this->Invalidate();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ToggleControl.h b/src/Authoring/Studio/Palettes/Timeline/ToggleControl.h
new file mode 100644
index 00000000..49caaff8
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ToggleControl.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TOGGLE_CONTROL_H
+#define INCLUDED_TOGGLE_CONTROL_H 1
+
+#pragma once
+
+#include "BlankToggleControl.h"
+#include "ToggleButton.h"
+
+class CStateRow;
+class CBlankControl;
+class ITimelineItemBinding;
+
+class CToggleControl : public CBlankToggleControl
+{
+public:
+ CToggleControl(CStateRow *inStateRow, ITimelineItemBinding *inTimelineItemBinding);
+ virtual ~CToggleControl();
+
+ void OnShyClicked(CToggleButton *inButton, CToggleButton::EButtonState inState);
+ void OnVisibleClicked(CToggleButton *inButton, CToggleButton::EButtonState inState);
+ void OnLockClicked(CToggleButton *inButton, CToggleButton::EButtonState inState);
+
+ void Refresh() override;
+
+protected:
+ CStateRow *m_StateRow;
+
+ CToggleButton *m_Shy;
+ CToggleButton *m_Visible;
+ CToggleButton *m_Locked;
+
+ ITimelineItemBinding *m_TimelineItemBinding;
+};
+#endif // INCLUDED_TOGGLE_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.cpp b/src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.cpp
new file mode 100644
index 00000000..7dadde19
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "ToggleToolbar.h"
+#include "SIcon.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+#include "TimelineTreeLayout.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CToggleToolbar::CToggleToolbar(CTimelineTreeLayout *inTreeLayout)
+ : CFlowLayout(new CBlankControl(CStudioPreferences::GetTopRowColor()))
+{
+ m_TreeLayout = inTreeLayout;
+
+ m_Color = CStudioPreferences::GetBaseColor();
+
+ SetFlowDirection(FLOW_HORIZONTAL);
+ SetAlignment(ALIGN_TOP, ALIGN_LEFT);
+ SetLeftMargin(1);
+
+ CProceduralButton<CToggleButton>::SBorderOptions theBorderOptions(false, true, true, true);
+
+ m_FltrShyBtn = new CProceduralButton<CToggleButton>();
+ m_FltrShyBtn->SetUpImage("Toggle-Shy.png");
+ m_FltrShyBtn->SetDownImage("Toggle-Shy.png");
+ m_FltrShyBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrShyBtn->SetAbsoluteSize(m_FltrShyBtn->GetSize());
+ m_FltrShyBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_SHY2));
+ m_FltrShyBtn->SigToggle.connect(std::bind(&CToggleToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ AddChild(m_FltrShyBtn);
+ m_FltrShyBtn->SetToggleState(false);
+
+ m_FltrVisibleBtn = new CProceduralButton<CToggleButton>();
+ m_FltrVisibleBtn->SetUpImage("filter-toggle-eye-up.png");
+ m_FltrVisibleBtn->SetDownImage("filter-toggle-eye-down.png");
+ m_FltrVisibleBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrVisibleBtn->SetAbsoluteSize(m_FltrVisibleBtn->GetSize());
+ m_FltrVisibleBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_VISIBLE2));
+ m_FltrVisibleBtn->SigToggle.connect(std::bind(&CToggleToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ AddChild(m_FltrVisibleBtn);
+ m_FltrVisibleBtn->SetToggleState(false);
+
+ m_FltrLockBtn = new CProceduralButton<CToggleButton>();
+ m_FltrLockBtn->SetUpImage("Toggle-Lock.png");
+ m_FltrLockBtn->SetDownImage("Toggle-Lock.png");
+ m_FltrLockBtn->SetBorderVisibilityAll(theBorderOptions);
+ m_FltrLockBtn->SetAbsoluteSize(m_FltrLockBtn->GetSize());
+ m_FltrLockBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_LOCK2));
+ m_FltrLockBtn->SigToggle.connect(std::bind(&CToggleToolbar::OnButtonToggled, this,
+ std::placeholders::_1, std::placeholders::_2));
+ AddChild(m_FltrLockBtn);
+ m_FltrLockBtn->SetToggleState(false);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CToggleToolbar::~CToggleToolbar()
+{
+ delete m_FltrShyBtn;
+ delete m_FltrVisibleBtn;
+ delete m_FltrLockBtn;
+}
+
+//=============================================================================
+/**
+ * Fills in the background color and highlighting for this control.
+ */
+void CToggleToolbar::Draw(CRenderer *inRenderer)
+{
+ CRct theRect(0, 0, GetSize().x, GetSize().y - 1);
+ inRenderer->FillSolidRect(theRect, m_Color);
+ CFlowLayout::Draw(inRenderer);
+ inRenderer->Draw3dRect(theRect, CStudioPreferences::GetButtonShadowColor(),
+ CStudioPreferences::GetButtonShadowColor());
+
+ // Draw the highlight at the bottom
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CPt(0, theRect.size.y));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y));
+ inRenderer->PopPen();
+
+ // Draw the one pixel on the end of the highlight that has to be dark
+ // Apparently there's some problems trying to draw one pixel, so clip the excess
+ inRenderer->PushClippingRect(QRect(0, 0, GetSize().x, GetSize().y));
+ inRenderer->PushPen(CStudioPreferences::GetButtonShadowColor());
+ inRenderer->MoveTo(CPt(theRect.size.x, theRect.size.y));
+ inRenderer->LineTo(CPt(theRect.size.x - 1, theRect.size.y));
+ inRenderer->PopPen();
+ inRenderer->PopClippingRect();
+}
+
+//=============================================================================
+/**
+ * Handles turning a filter on or off in response to a button being pressed.
+ * @param inButton button that generated the event
+ * @param inState new state of the button after being toggled
+ */
+void CToggleToolbar::OnButtonToggled(CToggleButton *inButton, CButtonControl::EButtonState inState)
+{
+ bool theFilterNeedsApplied = (inState == CButtonControl::EBUTTONSTATE_UP);
+
+ if (inButton == m_FltrShyBtn)
+ FilterShy(theFilterNeedsApplied);
+ else if (inButton == m_FltrVisibleBtn)
+ FilterVisible(theFilterNeedsApplied);
+ else if (inButton == m_FltrLockBtn)
+ FilterLocked(theFilterNeedsApplied);
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for shy objects.
+ * @param inFilter true to filter shy objects out of the timeline, false to show
+ * shy objects in the timeline.
+ */
+void CToggleToolbar::FilterShy(bool inFilter)
+{
+ if (inFilter)
+ m_FltrShyBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_SHY2));
+ else
+ m_FltrShyBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_SHY1));
+
+ m_TreeLayout->GetFilter()->SetShy(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for visible objects.
+ * @param inFilter true to filter visible objects out of the timeline, false to show
+ * visible objects in the timeline.
+ */
+void CToggleToolbar::FilterVisible(bool inFilter)
+{
+ if (inFilter)
+ m_FltrVisibleBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_VISIBLE2));
+ else
+ m_FltrVisibleBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_VISIBLE1));
+
+ m_TreeLayout->GetFilter()->SetVisible(inFilter);
+ m_TreeLayout->Filter();
+}
+
+//=============================================================================
+/**
+ * Turns filtering on and off for locked objects.
+ * @param inFilter true to filter locked objects out of the timeline, false to show
+ * locked objects in the timeline.
+ */
+void CToggleToolbar::FilterLocked(bool inFilter)
+{
+ if (inFilter)
+ m_FltrLockBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_LOCK2));
+ else
+ m_FltrLockBtn->SetTooltipText(::LoadResourceString(IDS_FLTR_TOOLTIP_LOCK1));
+
+ m_TreeLayout->GetFilter()->SetLocked(inFilter);
+ m_TreeLayout->Filter();
+}
diff --git a/src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.h b/src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.h
new file mode 100644
index 00000000..a0f95e62
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/ToggleToolbar.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TOGGLE_TOOLBAR_H
+#define INCLUDED_TOGGLE_TOOLBAR_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "FlowLayout.h"
+#include "ProceduralButton.h"
+#include "ToggleButton.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+class CRenderer;
+class CTimelineTreeLayout;
+// class CSIcon;
+
+//=============================================================================
+/**
+ * Control at the top of the time display and a header for the toggle column.
+ */
+class CToggleToolbar : public CFlowLayout
+{
+public:
+ CToggleToolbar(CTimelineTreeLayout *inTreeLayout);
+ virtual ~CToggleToolbar();
+ void Draw(CRenderer *inRenderer) override;
+
+ void FilterShy(bool inFilter);
+ void FilterVisible(bool inFilter);
+ void FilterLocked(bool inFilter);
+ void OnButtonToggled(CToggleButton *inButton, CToggleButton::EButtonState inState);
+
+protected:
+ // CSIcon* m_ShyIcon;
+ // CSIcon* m_VisibilityIcon;
+ // CSIcon* m_LockIcon;
+ CProceduralButton<CToggleButton> *m_FltrShyBtn;
+ CProceduralButton<CToggleButton> *m_FltrVisibleBtn;
+ CProceduralButton<CToggleButton> *m_FltrLockBtn;
+ CTimelineTreeLayout *m_TreeLayout;
+ CColor m_Color;
+};
+
+#endif // INCLUDED_TOGGLE_TOOLBAR_H
diff --git a/src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.cpp b/src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.cpp
new file mode 100644
index 00000000..b49eabb5
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TreeBlankControl.h"
+#include "Renderer.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTreeBlankControl::CTreeBlankControl(CColor inColor)
+ : CBlankControl(inColor)
+ , m_LeftEdgeOffset(0)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTreeBlankControl::~CTreeBlankControl()
+{
+}
+
+//=============================================================================
+/**
+ * Handles custom drawing of the blank control underneath the tree control
+ * on the timeline palette.
+ */
+void CTreeBlankControl::Draw(CRenderer *inRenderer)
+{
+ CBlankControl::Draw(inRenderer);
+
+ // Draw the highlight on the left side of this control
+ CPt theSize = GetSize();
+ inRenderer->PushPen(CStudioPreferences::GetButtonHighlightColor());
+ inRenderer->MoveTo(CStudioPreferences::GetRowSize() + m_LeftEdgeOffset, 0);
+ inRenderer->LineTo(CStudioPreferences::GetRowSize() + m_LeftEdgeOffset, theSize.y - 1);
+ inRenderer->PopPen();
+}
+
+//=============================================================================
+/**
+ * xxx
+ */
+void CTreeBlankControl::SetVisiblePositionX(long inPosition)
+{
+ m_LeftEdgeOffset = inPosition;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.h b/src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.h
new file mode 100644
index 00000000..0d0df3ab
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Timeline/TreeBlankControl.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_TREE_BLANK_CONTROL_H
+#define INCLUDED_TREE_BLANK_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BlankControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRenderer;
+
+//=============================================================================
+/**
+ * Extends the blank control to draw items specific to the tree view side of the
+ * timeline palette.
+ */
+class CTreeBlankControl : public CBlankControl
+{
+public:
+ CTreeBlankControl(CColor inColor = CStudioPreferences::GetBaseColor());
+ virtual ~CTreeBlankControl();
+ void Draw(CRenderer *inRenderer) override;
+ void SetVisiblePositionX(long inPosition);
+
+protected:
+ long m_LeftEdgeOffset; ///< Visibility offset of the left edge in case timeline is scrolled
+ ///horizontally
+};
+
+#endif // INCLUDED_TREE_BLANK_CONTROL_H
diff --git a/src/Authoring/Studio/Palettes/controls/BrowserCombo.qml b/src/Authoring/Studio/Palettes/controls/BrowserCombo.qml
new file mode 100644
index 00000000..0e8bcb55
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/BrowserCombo.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+
+MouseArea {
+ id: root
+
+ property alias value: value.text
+ property var activeBrowser
+ property bool blockShow: false
+
+ signal showBrowser
+
+ Layout.minimumHeight: _controlBaseHeight
+ Layout.preferredWidth: _valueWidth
+
+ onPressed: {
+ // Block showBrowser event on the mouse press that makes the browser lose focus
+ if (activeBrowser && activeBrowser.visible) {
+ activeBrowser = null;
+ blockShow = true
+ } else {
+ blockShow = false
+ }
+ }
+
+ onClicked: {
+ if (!blockShow)
+ root.showBrowser()
+ }
+
+ Rectangle {
+ anchors.fill: parent
+
+ color: _studioColor2
+
+ StyledLabel {
+ id: value
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignLeft
+ rightPadding: 6 + img.width
+ leftPadding: 6
+ }
+ Image {
+ id: img
+ x: parent.width - sourceSize.width - 2
+ y: (parent.height - sourceSize.height) / 2
+ source: _resDir + "arrow_down.png"
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/FloatTextField.qml b/src/Authoring/Studio/Palettes/controls/FloatTextField.qml
new file mode 100644
index 00000000..bea65443
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/FloatTextField.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+
+/* Use for: Position, Rotation, Scale, Pivot ... */
+
+TextField {
+ id: floatTextFieldId
+ property alias decimalValue: validator.decimals
+
+ signal wheelEventFinished
+
+ selectByMouse: true
+ text: "0.000"
+ Layout.preferredWidth: _valueWidth / 2
+ Layout.preferredHeight: _controlBaseHeight
+
+ topPadding: 0
+ bottomPadding: 0
+ rightPadding: 6
+
+ horizontalAlignment: TextInput.AlignRight
+ verticalAlignment: TextInput.AlignVCenter
+ validator: DoubleValidator {
+ id: validator
+ decimals: 3
+ locale: "C"
+ }
+
+ selectionColor: _selectionColor
+ selectedTextColor: _textColor
+ font.pixelSize: _fontSize
+ color: _textColor
+ background: Rectangle {
+ color: floatTextFieldId.enabled ? _studioColor2 : "transparent"
+ border.width: floatTextFieldId.activeFocus ? 1 : 0
+ border.color: floatTextFieldId.activeFocus ? _selectionColor : _disabledColor
+ }
+
+ MouseArea {
+ property int _clickedPos
+ id: mouseAreaBaseId
+
+ anchors.fill: parent
+ onPressed: {
+ parent.forceActiveFocus()
+ _clickedPos = parent.positionAt(mouse.x, mouse.y)
+ parent.cursorPosition = _clickedPos
+ }
+ onDoubleClicked: parent.selectAll()
+ onPositionChanged: {
+ parent.cursorPosition = parent.positionAt(mouse.x, mouse.y)
+ parent.select(_clickedPos, parent.cursorPosition)
+ }
+
+ onWheel: {
+ if (!floatTextFieldId.activeFocus) {
+ wheel.accepted = false
+ return
+ }
+ if (wheel.angleDelta.y > 0) {
+ floatTextFieldId.text++
+ } else {
+ floatTextFieldId.text--
+ }
+ wheel.accepted=true
+ floatTextFieldId.wheelEventFinished();
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledComboBox.qml b/src/Authoring/Studio/Palettes/controls/StyledComboBox.qml
new file mode 100644
index 00000000..ff079f41
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledComboBox.qml
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.2
+import QtQuick.Layouts 1.3
+import QtQuick.Window 2.2
+
+ComboBox {
+ id: control
+ Layout.preferredHeight: _controlBaseHeight
+ Layout.preferredWidth: _valueWidth
+ topPadding: 0
+ bottomPadding: 0
+
+ delegate: ItemDelegate {
+ id: itemDelegate
+
+ property bool hasSeparator: itemDelegate.text.endsWith("|separator")
+
+ width: parent.width
+ height: hasSeparator ? _controlBaseHeight + 6 : _controlBaseHeight
+ padding: 0
+ spacing: 0
+ text: {
+ control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole]
+ : model[control.textRole])
+ : modelData
+ }
+ highlighted: control.highlightedIndex === index
+ hoverEnabled: control.hoverEnabled
+ contentItem: ColumnLayout {
+ anchors.fill: itemDelegate
+ spacing: 0
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1
+ color: _studioColor3
+ visible: itemDelegate.hasSeparator
+ }
+ StyledLabel {
+ Layout.fillWidth: true
+ rightPadding: control.indicator.width + 6
+ leftPadding: 6
+ text: {
+ hasSeparator ? itemDelegate.text.replace("|separator", "")
+ : itemDelegate.text
+ }
+ visible: itemDelegate.text
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ background: Rectangle {
+ anchors.fill: itemDelegate
+ color: hovered ? _selectionColor : _studioColor2
+ }
+ }
+
+ indicator: Image {
+ x: control.width - width - 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ source: _resDir + "arrow_down.png"
+ sourceSize.width: width
+ sourceSize.height: height
+ }
+
+ contentItem: StyledTextField {
+ text: {
+ var newText = control.editable ? control.editText : control.displayText;
+ var hasSeparator = newText.endsWith("|separator");
+ hasSeparator ? newText.replace("|separator", "") : newText;
+ }
+
+ enabled: control.editable
+ autoScroll: control.editable
+ readOnly: control.popup.visible
+ inputMethodHints: control.inputMethodHints
+ validator: control.validator
+ opacity: 1
+ leftPadding: 6
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ background: Rectangle {
+ color: control.enabled ? _studioColor2 : "transparent"
+ border.width: 0
+ }
+
+ popup: Popup {
+ y: control.height
+ width: control.width
+ height: Math.min(contentItem.implicitHeight,
+ control.Window.height - topMargin - bottomMargin)
+ topMargin: 6
+ bottomMargin: 6
+ padding: 0
+
+ contentItem: ListView {
+ clip: true
+ implicitHeight: contentHeight
+ model: control.popup.visible ? control.delegateModel : null
+ currentIndex: control.highlightedIndex
+ highlightRangeMode: ListView.ApplyRange
+ highlightMoveDuration: 0
+ ScrollIndicator.vertical: ScrollIndicator {
+ id: scrollIndicator
+ contentItem: Rectangle {
+ id: indicator
+
+ implicitWidth: 2
+ implicitHeight: 2
+
+ color: _studioColor3
+ visible: scrollIndicator.size < 1.0
+ opacity: 0.75
+ }
+ }
+ Rectangle {
+ z: 10
+ anchors.fill: parent
+ color: "transparent"
+ border.color: _studioColor3
+ }
+ }
+
+ background: Rectangle {
+ color: _studioColor2
+ }
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledLabel.qml b/src/Authoring/Studio/Palettes/controls/StyledLabel.qml
new file mode 100644
index 00000000..02016069
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledLabel.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+
+Label {
+ id: styledLabelId
+ font.pixelSize: _fontSize
+ color: _textColor
+ Layout.preferredHeight: _controlBaseHeight
+ Layout.preferredWidth: _idWidth
+ verticalAlignment: Text.AlignVCenter
+ clip: true
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledMenuItem.qml b/src/Authoring/Studio/Palettes/controls/StyledMenuItem.qml
new file mode 100644
index 00000000..361d5876
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledMenuItem.qml
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+
+MenuItem {
+ id: control
+ hoverEnabled: true
+
+ contentItem: StyledLabel {
+ text: control.text
+ visible: control.text
+ horizontalAlignment: Text.AlignLeft
+ color: control.enabled ? _textColor : _disabledColor
+ }
+ background: Rectangle {
+ implicitWidth: _valueWidth
+ implicitHeight: _controlBaseHeight
+ color: control.hovered ? _selectionColor : _studioColor1
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledMenuSeparator.qml b/src/Authoring/Studio/Palettes/controls/StyledMenuSeparator.qml
new file mode 100644
index 00000000..532fee2c
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledMenuSeparator.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+
+MenuSeparator {
+ id: control
+ padding: 0
+ topPadding: 4
+ bottomPadding: 4
+ leftPadding: 0
+ rightPadding: 0
+ contentItem: Rectangle {
+ width: control.width
+ implicitWidth: control.parent.width - control.leftPadding - control.rightPadding
+ implicitHeight: 1
+ color: _studioColor3
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledTextField.qml b/src/Authoring/Studio/Palettes/controls/StyledTextField.qml
new file mode 100644
index 00000000..da621314
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledTextField.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+
+TextField {
+ id: styledTextFieldId
+
+ property alias backgroundColor: textBackground.color
+
+ Layout.preferredWidth: _valueWidth
+ Layout.preferredHeight: _controlBaseHeight
+ horizontalAlignment: TextInput.AlignRight
+ verticalAlignment: TextInput.AlignVCenter
+
+ topPadding: 0
+ bottomPadding: 0
+ rightPadding: 6
+
+ selectByMouse: true
+ selectionColor: _selectionColor
+ selectedTextColor: _textColor
+
+ font.pixelSize: _fontSize
+ color: _textColor
+ background: Rectangle {
+ id: textBackground
+ color: styledTextFieldId.enabled ? _studioColor2 : "transparent"
+ border.width: styledTextFieldId.activeFocus ? 1 : 0
+ border.color: styledTextFieldId.activeFocus ? _selectionColor : _disabledColor
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledToolButton.qml b/src/Authoring/Studio/Palettes/controls/StyledToolButton.qml
new file mode 100644
index 00000000..51654331
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledToolButton.qml
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+
+ToolButton {
+ id: control
+
+ property string enabledImage
+ property string disabledImage
+ property alias toolTipText: toolTip.text
+
+ hoverEnabled: true
+
+ StyledTooltip {
+ id: toolTip
+ visible: control.hovered
+ }
+
+ background: Rectangle {
+ color: control.pressed ? _selectionColor : (hovered ? _studioColor1 : "transparent")
+ border.color: _studioColor1
+ }
+
+ contentItem: Image {
+ source: control.enabled ? _resDir + enabledImage : _resDir + disabledImage
+ }
+}
diff --git a/src/Authoring/Studio/Palettes/controls/StyledTooltip.qml b/src/Authoring/Studio/Palettes/controls/StyledTooltip.qml
new file mode 100644
index 00000000..cae9c59f
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/controls/StyledTooltip.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.1
+
+ToolTip {
+ id: control
+ delay: 500
+ contentItem: StyledLabel {
+ text: control.text
+ }
+
+ background: Rectangle {
+ border.color: _studioColor3
+ color: _studioColor2
+ radius: 2
+ }
+}
diff --git a/src/Authoring/Studio/PreviewHelper.cpp b/src/Authoring/Studio/PreviewHelper.cpp
new file mode 100644
index 00000000..271daf4d
--- /dev/null
+++ b/src/Authoring/Studio/PreviewHelper.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PreviewHelper.h"
+#include "StudioApp.h"
+#include "Dialogs.h"
+#include "Dispatch.h"
+#include "Doc.h"
+#include "StudioPreferences.h"
+#include "StudioProjectSettings.h"
+#include "StudioProjectVariables.h"
+#include "Core.h"
+#include "UICFileTools.h"
+
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QProcess>
+
+#include "remoteproject.h"
+
+//=============================================================================
+/**
+ * PKC : Yes, we're duplicating functionality found in UICStateApplication
+ * but we want to eliminate as many dependencies on UICState as possible in Studio.
+ */
+
+Q3DStudio::CString CPreviewHelper::GetLaunchFile(const Q3DStudio::CString &inUipPath)
+{
+ Q3DStudio::CFilePath theUipPath(inUipPath);
+
+ Q3DStudio::CString theDir = theUipPath.GetDirectory();
+ Q3DStudio::CString theStem = theUipPath.GetFileStem();
+
+ // Check if a corresponding .UIA file actually exists
+ theDir.append('/');
+ Q3DStudio::CString idealPath = theDir + theStem + Q3DStudio::CString(".uia");
+
+ Q3DStudio::CFilePath theUiaPath(idealPath);
+
+ return (theUiaPath.IsFile()) ? idealPath : inUipPath;
+}
+
+//=============================================================================
+/**
+ * Callback for previewing a presentation.
+ */
+void CPreviewHelper::OnPreview()
+{
+ Q3DStudio::CBuildConfigurations &theConfigurations =
+ g_StudioApp.GetCore()->GetBuildConfigurations();
+ Q3DStudio::CBuildConfiguration *theBuildConfiguration =
+ theConfigurations.GetConfiguration(CStudioPreferences::GetPreviewConfig());
+ if (theBuildConfiguration)
+ PreviewViaConfig(theBuildConfiguration, EXECMODE_PREVIEW);
+}
+
+//=============================================================================
+/**
+ * Callback for deploying a presentation.
+ */
+void CPreviewHelper::OnDeploy(RemoteProject &project)
+{
+ Q3DStudio::CBuildConfigurations &theConfigurations =
+ g_StudioApp.GetCore()->GetBuildConfigurations();
+ Q3DStudio::CBuildConfiguration *theBuildConfiguration =
+ theConfigurations.GetConfiguration(CStudioPreferences::GetPreviewConfig());
+ if (theBuildConfiguration) {
+ // ItemDataPtr != nullptr ==> Build configurations specified NANT pipeline exporter
+ PreviewViaConfig(theBuildConfiguration, EXECMODE_DEPLOY, &project);
+ }
+}
+
+//=============================================================================
+/**
+ * Previewing a presentation using the build configurations loaded.
+ * This involves 2 steps:
+ * 1 Export the presentation using the specified exporter.
+ * 2 Viewing the exported content following the command specified in the configuration.
+ */
+void CPreviewHelper::PreviewViaConfig(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ EExecMode inMode, RemoteProject *project)
+{
+ bool theUsingTempFile;
+ CUICFile theDocument = GetDocumentFile(theUsingTempFile);
+ CCore *theCore = g_StudioApp.GetCore();
+ try {
+ if (theCore->GetDoc()->IsModified()) {
+ theCore->OnSaveDocument(theDocument);
+ }
+
+ DoPreviewViaConfig(inSelectedConfig, theDocument.GetAbsolutePath(),
+ inMode, project);
+ } catch (...) {
+ theCore->GetDispatch()->FireOnProgressEnd();
+ g_StudioApp.GetDialogs()->DisplaySaveReadOnlyFailed(theDocument);
+ }
+}
+
+//=============================================================================
+/**
+ * Launch a viewing app to preview a file.
+ * @param inDocumentFile File to be previewed
+ */
+void CPreviewHelper::DoPreviewViaConfig(Q3DStudio::CBuildConfiguration * /*inSelectedConfig*/,
+ const Q3DStudio::CString &inDocumentFile,
+ EExecMode inMode,
+ RemoteProject *project)
+{
+ using namespace Q3DStudio;
+ Q3DStudio::CString theCommandStr;
+
+ if (inMode == EXECMODE_DEPLOY) {
+ Q_ASSERT(project);
+ project->streamProject(inDocumentFile.GetCharStar());
+ } else if (inMode == EXECMODE_PREVIEW
+ && CStudioPreferences::GetPreviewProperty("PLATFORM") == "PC") {
+ // Quick Preview on PC without going via NANT
+ CFilePath theCurrentPath(CUICFile::GetApplicationDirectory().GetAbsolutePath());
+ CFilePath theViewerDir = CFilePath::fromQString(QApplication::applicationDirPath());
+ if (!theViewerDir.IsDirectory()) {
+ // theMainDir = theCurrentPath.GetDirectory().GetDirectory();
+ // theViewerDir = CFilePath::CombineBaseAndRelative( theMainDir, CFilePath(
+ // L"Runtime/Build/Bin/Win32" ) );
+ theViewerDir = theCurrentPath.GetDirectory(); // Developing directory
+ }
+
+ Q3DStudio::CString theDocumentFile = CPreviewHelper::GetLaunchFile(inDocumentFile);
+#ifdef Q_OS_WIN
+ Q3DStudio::CString theViewerFile = "Qt3DViewer.exe";
+ theCommandStr = theViewerDir + "\\" + theViewerFile;
+#else
+#ifdef Q_OS_MACOS
+ Q3DStudio::CString theViewerFile = "../../../Qt3DViewer.app/Contents/MacOS/Qt3DViewer";
+#else
+ Q3DStudio::CString theViewerFile = "Qt3DViewer";
+#endif
+ theCommandStr = theViewerDir + "/" + theViewerFile;
+#endif
+
+ QProcess *p = new QProcess;
+ auto finished = static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished);
+ QObject::connect(p, finished, p, &QObject::deleteLater);
+ p->start(theCommandStr.toQString(), { theDocumentFile.toQString() });
+
+ if (!p->waitForStarted()) {
+ QMessageBox::critical(nullptr, QObject::tr("Error Launching Viewer"), QObject::tr("%1 failed with error: %2")
+ .arg(theViewerFile.toQString()).arg(p->errorString()));
+ delete p;
+ return;
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Interpret the string by resolving the variables.
+ * @param inSourceString String to be interpreted
+ */
+Q3DStudio::CString CPreviewHelper::InterpretString(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ const Q3DStudio::CString &inDocumentFile,
+ const Q3DStudio::CString &inSourceString)
+{
+ Q3DStudio::CString theReturnString;
+ long theStart = 0; // start index of string
+ long theBeginIndex = 0; // index of '%'
+ long theEndIndex = 0; // index of '%'
+ while (Q3DStudio::CString::ENDOFSTRING != theEndIndex) {
+ theBeginIndex = inSourceString.Find('%', theStart);
+ if (Q3DStudio::CString::ENDOFSTRING != theBeginIndex) {
+ theReturnString += inSourceString.Extract(theStart, theBeginIndex - theStart);
+ // find the corresponding '%'
+ theEndIndex = inSourceString.Find('%', theBeginIndex + 1);
+ if (Q3DStudio::CString::ENDOFSTRING != theEndIndex) {
+ // first, resolve the variable by the toolbar selection
+ Q3DStudio::CString theVariable =
+ inSourceString.Extract(theBeginIndex + 1, theEndIndex - theBeginIndex - 1);
+ Q3DStudio::CString theResolvedVariable;
+ bool theHasResolved = ResolveVariable(inSelectedConfig, inDocumentFile, theVariable,
+ theResolvedVariable);
+
+ if (theHasResolved) {
+ theReturnString += theResolvedVariable;
+ } else {
+ theReturnString += "_NULL_";
+ }
+ theStart = theEndIndex + 1;
+ } else
+ theReturnString += inSourceString.Extract(theBeginIndex);
+ } else {
+ theEndIndex = theBeginIndex;
+ theReturnString += inSourceString.Extract(theStart);
+ }
+ }
+
+ return theReturnString;
+}
+
+//==============================================================================
+/**
+ * Resolves the passed in variable and write out the resolved value if it exists
+ * in the current selected build configuration.
+ * @param inVariable the environment to be resolved
+ * @param outValue the string to receive the resolved value
+ * @return true if the variable exists, else false
+ */
+//==============================================================================
+bool CPreviewHelper::ResolveVariable(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ const Q3DStudio::CString &inDocumentFile,
+ const Q3DStudio::CString &inVariable,
+ Q3DStudio::CString &outValue)
+{
+ Q3DStudio::CString theReturnStr;
+ bool theHasResolved = false;
+
+ // Handle special variable
+ if (inVariable == "BUILDFILE") {
+ if (inSelectedConfig) {
+ theReturnStr = inSelectedConfig->GetPath();
+ theHasResolved = true;
+ }
+ } else if (inVariable == "UIPFILE") {
+ theReturnStr = inDocumentFile;
+ theHasResolved = true;
+ }
+
+ if (!theHasResolved) {
+ Q3DStudio::CString theValue = CStudioPreferences::GetPreviewProperty(inVariable);
+ if (theValue != "") {
+ theReturnStr = theValue;
+ theHasResolved = true;
+ }
+ }
+
+ if (theHasResolved)
+ outValue = InterpretString(inSelectedConfig, inDocumentFile, theReturnStr);
+
+ return theHasResolved;
+}
+
+//=============================================================================
+/**
+ * Gets a file to be previewed or conditioned based on the current document.
+ * If the document has not been saved yet (and thus does not have a name), a temp file is used.
+ * If the document has been saved but it's dirty, a temp file based on the current document is
+ *used (same path but different extension).
+ * @param outUsingTempFile if temp file if used
+ * @return the document file to be previewed or conditioned
+ */
+CUICFile CPreviewHelper::GetDocumentFile(bool &outUsingTempFile)
+{
+ CUICFile theDocument = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath();
+ CUICFile theResult("");
+ theResult = theDocument;
+ outUsingTempFile = false;
+ return theResult;
+}
diff --git a/src/Authoring/Studio/PreviewHelper.h b/src/Authoring/Studio/PreviewHelper.h
new file mode 100644
index 00000000..e68e51d9
--- /dev/null
+++ b/src/Authoring/Studio/PreviewHelper.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PREVIEW_HELPER
+#define INCLUDED_PREVIEW_HELPER 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICFile.h"
+#include "UICString.h"
+#include "remoteproject.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CHotKeys;
+
+namespace Q3DStudio {
+class CBuildConfiguration;
+}
+
+//==============================================================================
+/**
+ * @class CPreviewHelper
+ */
+class CPreviewHelper
+{
+public:
+ enum EExecMode {
+ EXECMODE_PREVIEW, ///< Preview
+ EXECMODE_DEPLOY, ///< Deploy
+ };
+
+public:
+ static void OnPreview();
+ static void OnDeploy(RemoteProject &project);
+ static void PreviewViaConfig(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ EExecMode inMode, RemoteProject *project = 0);
+ static void DoPreviewViaConfig(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ const Q3DStudio::CString &inDocumentFile,
+ EExecMode inMode,
+ RemoteProject *project = 0);
+
+protected:
+ static Q3DStudio::CString InterpretString(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ const Q3DStudio::CString &inDocumentFile,
+ const Q3DStudio::CString &inSourceString);
+ static bool ResolveVariable(Q3DStudio::CBuildConfiguration *inSelectedConfig,
+ const Q3DStudio::CString &inDocumentFile,
+ const Q3DStudio::CString &inVariable, Q3DStudio::CString &outValue);
+ static CUICFile GetDocumentFile(bool &outUsingTempFile);
+ static Q3DStudio::CString GetLaunchFile(const Q3DStudio::CString &inDocFile);
+};
+
+#endif
diff --git a/src/Authoring/Studio/Render/IStudioRenderer.h b/src/Authoring/Studio/Render/IStudioRenderer.h
new file mode 100644
index 00000000..2dabbd08
--- /dev/null
+++ b/src/Authoring/Studio/Render/IStudioRenderer.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_RENDERER
+#define UIC_STUDIO_RENDERER
+#pragma once
+
+#include "IDocSceneGraph.h"
+#include <EASTL/vector.h>
+#include <EASTL/string.h>
+
+#include <QRect>
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+QT_END_NAMESPACE
+
+namespace Q3DStudio {
+using qt3ds::QT3DSI32;
+class IStudioRenderer : public IDocSceneGraph
+{
+protected:
+ virtual ~IStudioRenderer() {}
+
+public:
+ friend class std::shared_ptr<IStudioRenderer>;
+
+ virtual bool IsInitialized() = 0;
+
+ virtual void Initialize(QWidget *inWindow) = 0;
+
+ virtual void SetViewRect(const QRect &inRect) = 0;
+
+ virtual void GetEditCameraList(QStringList &outCameras) = 0;
+ virtual void SetEnableEditLight(bool inEnableLight) = 0;
+ virtual bool IsEditLightEnabled() const = 0;
+ virtual bool DoesEditCameraSupportRotation(QT3DSI32 inIndex) = 0;
+ virtual bool AreGuidesEnabled() const = 0;
+ virtual void SetGuidesEnabled(bool val) = 0;
+ virtual bool AreGuidesEditable() const = 0;
+ virtual void SetGuidesEditable(bool val) = 0;
+ // Setting the camera to -1 disables the edit cameras
+ // So setting the camera to 0- (numcameras - 1) will set change the active
+ // edit camera.
+ virtual void SetEditCamera(QT3DSI32 inIndex) = 0;
+ virtual QT3DSI32 GetEditCamera() const = 0;
+ virtual void EditCameraZoomToFit() = 0;
+
+ // This must be safe to call from multiple places
+ virtual void Close() = 0;
+
+ // synchronously render the content
+ virtual void RenderNow() = 0;
+
+ virtual void MakeContextCurrent() = 0;
+ virtual void ReleaseContext() = 0;
+
+ // Uses the global studio app to get the doc and dispatch.
+ static std::shared_ptr<IStudioRenderer> CreateStudioRenderer();
+};
+};
+
+#endif
diff --git a/src/Authoring/Studio/Render/PathWidget.cpp b/src/Authoring/Studio/Render/PathWidget.cpp
new file mode 100644
index 00000000..49fea1ef
--- /dev/null
+++ b/src/Authoring/Studio/Render/PathWidget.cpp
@@ -0,0 +1,512 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "PathWidget.h"
+#include "UICRenderWidgets.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderInputAssembler.h"
+#include "UICRenderPath.h"
+#include "UICRenderPathSubPath.h"
+#include "UICRenderPathManager.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+
+using namespace uic::widgets;
+
+namespace {
+
+QT3DSVec3 toVec3(QT3DSVec2 inPoint)
+{
+ return QT3DSVec3(inPoint.x, inPoint.y, 0.0f);
+}
+QT3DSVec3 toVec3(QT3DSVec2 inPoint, float z)
+{
+ return QT3DSVec3(inPoint.x, inPoint.y, z);
+}
+
+struct SPointEntry
+{
+ QT3DSVec2 m_Position;
+ QT3DSVec3 m_Color;
+ QT3DSF32 m_ObjectId;
+ SPointEntry(QT3DSVec2 pos, QT3DSVec3 color, size_t objId)
+ : m_Position(pos)
+ , m_Color(color)
+ , m_ObjectId((QT3DSF32)objId)
+ {
+ }
+ SPointEntry() {}
+};
+
+struct SPathWidget : public IPathWidget
+{
+ typedef nvvector<eastl::pair<QT3DSU32, uic::studio::SPathPick::EAnchorProperty>>
+ TReverseAnchorBuffer;
+
+ NVAllocatorCallback &m_Allocator;
+ IUICRenderContext &m_UICContext;
+
+ NVScopedRefCounted<NVRenderVertexBuffer> m_PointVertexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> m_PointAssembler;
+ NVScopedRefCounted<NVRenderShaderProgram> m_PointShader;
+ NVScopedRefCounted<NVRenderShaderProgram> m_PointPickShader;
+
+ NVScopedRefCounted<NVRenderVertexBuffer> m_LineVertexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> m_LineAssembler;
+ NVScopedRefCounted<NVRenderShaderProgram> m_LineShader;
+
+ nvvector<eastl::pair<QT3DSVec2, QT3DSVec2>> m_LineBuffer;
+ nvvector<SPointEntry> m_PointBuffer;
+ TReverseAnchorBuffer m_AnchorIndexBuffer;
+ SWidgetRenderSetupResult m_RenderSetup;
+ QT3DSVec2 m_PointViewportDimensions;
+ QT3DSMat44 m_PointMVP;
+
+ QT3DSI32 m_RefCount;
+ SPathWidget(NVAllocatorCallback &inAlloc, IUICRenderContext &inRc)
+ : m_Allocator(inAlloc)
+ , m_UICContext(inRc)
+ , m_LineBuffer(inAlloc, "m_LineBuffer")
+ , m_PointBuffer(inAlloc, "m_PointBuffer")
+ , m_AnchorIndexBuffer(inAlloc, "m_AnchorIndexBuffer")
+ , m_LineShader(nullptr)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { ++m_RefCount; }
+ void release() override
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Allocator);
+ NVDelete(alloc, this);
+ }
+ }
+
+ void SetNode(SNode &inNode) override { m_Node = &inNode; }
+
+ QT3DSVec3 ToGlobalSpace(QT3DSVec3 inPoint) { return m_Node->m_GlobalTransform.transform(inPoint); }
+
+ QT3DSVec3 ToCameraSpace(QT3DSVec3 inPoint)
+ {
+ QT3DSVec3 theGlobalPos = m_Node->m_GlobalTransform.transform(inPoint);
+ return m_RenderSetup.m_WidgetInfo.m_CameraGlobalInverse.transform(theGlobalPos);
+ }
+
+ QT3DSVec3 ToCameraSpace(QT3DSVec2 inPoint)
+ {
+ return ToCameraSpace(QT3DSVec3(inPoint.x, inPoint.y, 0.0f));
+ }
+
+ void GeneratePointVertexGeometrySections(IShaderProgramGenerator &inProgramGenerator)
+ {
+ IShaderStageGenerator &vertex(*inProgramGenerator.GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &geometry(
+ *inProgramGenerator.GetStage(ShaderGeneratorStages::Geometry));
+ vertex.AddIncoming("attr_pos", "vec2");
+ vertex.AddIncoming("attr_color", "vec3");
+ vertex.AddIncoming("attr_objid", "float");
+ vertex.AddOutgoing("point_color", "vec3");
+ vertex.AddOutgoing("object_id", "float");
+ vertex.AddUniform("model_view_projection", "mat4");
+ vertex << "void main()" << Endl << "{" << Endl
+ << "\tgl_Position = model_view_projection * vec4( attr_pos.xy, 0.0, 1.0 );" << Endl
+ << "\tpoint_color = attr_color;" << Endl << "\tobject_id = uint(attr_objid);" << Endl
+ << "}" << Endl;
+
+ geometry.AddUniform("viewport_dimensions", "vec2");
+ geometry.AddUniform("pointsize", "float");
+ geometry.AddIncoming("point_color", "vec3");
+ geometry.AddIncoming("object_id", "float");
+ geometry.AddOutgoing("point_colorGE", "vec3");
+ geometry.AddOutgoing("object_idGE", "float");
+ geometry.AddOutgoing("uv_coords", "vec2");
+ geometry.Append("layout (points) in;");
+ geometry.Append("layout (triangle_strip, max_vertices = 4) out;");
+ geometry.Append(
+ "void main() {"
+ "// project points to screen space\n"
+ "\tvec2 p0 = vec2(gl_in[0].gl_Position.xy) / gl_in[0].gl_Position.w;\n"
+ "\tvec2 increments = (pointsize / viewport_dimensions) / 2.0;\n"
+ "\tgl_Position = vec4( p0.x - increments.x, p0.y + increments.y, 0.0, 1.0 );\n"
+ "\tpoint_colorGE = point_color[0];\n"
+ "\tuv_coords = vec2(0.0, 0.0);\n"
+ "\tobject_idGE = object_id[0];\n"
+ "\tEmitVertex();\n"
+ "\tgl_Position = vec4( p0.x + increments.x, p0.y + increments.y, 0.0, 1.0 );\n"
+ "\tpoint_colorGE = point_color[0];\n"
+ "\tuv_coords = vec2(1.0, 0.0);\n"
+ "\tobject_idGE = object_id[0];\n"
+ "\tEmitVertex();\n"
+ "\tgl_Position = vec4( p0.x - increments.x, p0.y - increments.y, 0.0, 1.0 );\n"
+ "\tpoint_colorGE = point_color[0];\n"
+ "\tuv_coords = vec2(0.0, 1.0);\n"
+ "\tobject_idGE = object_id[0];\n"
+ "\tEmitVertex();\n"
+ "\tgl_Position = vec4( p0.x + increments.x, p0.y - increments.y, 0.0, 1.0 );\n"
+ "\tpoint_colorGE = point_color[0];\n"
+ "\tuv_coords = vec2(1.0, 1.0);\n"
+ "\tobject_idGE = object_id[0];\n"
+ "\tEmitVertex();\n"
+ "\tEndPrimitive();\n"
+ "}\n");
+ }
+
+ NVRenderShaderProgram *GetPointShader(IShaderProgramGenerator &inProgramGenerator)
+ {
+ if (m_PointShader)
+ return m_PointShader.mPtr;
+ inProgramGenerator.BeginProgram(IShaderProgramGenerator::DefaultFlags()
+ | ShaderGeneratorStages::Geometry);
+ GeneratePointVertexGeometrySections(inProgramGenerator);
+
+ IShaderStageGenerator &fragment(
+ *inProgramGenerator.GetStage(ShaderGeneratorStages::Fragment));
+ fragment.AddIncoming("point_colorGE", "vec3");
+ fragment.AddIncoming("uv_coords", "vec2");
+ fragment.Append("void main()\n"
+ "{\n"
+ "\tvec2 coords = uv_coords - vec2(.5, .5);\n"
+ "\tfloat coordLen = length( coords );\n"
+ "\tfloat margin = .4;\n"
+ "\tfloat leftover = min( 1.0, (coordLen - margin)/.1 );\n"
+ "\tfloat alpha = coordLen < margin ? 1.0 : mix( 1.0, 0.0, leftover );\n"
+ "\tfragOutput = vec4(point_colorGE, alpha);\n"
+ "}\n");
+
+ m_PointShader = inProgramGenerator.CompileGeneratedShader("path widget point shader");
+ return m_PointShader.mPtr;
+ }
+
+ NVRenderShaderProgram *GetPointPickShader(IShaderProgramGenerator &inProgramGenerator)
+ {
+ if (m_PointPickShader)
+ return m_PointPickShader.mPtr;
+ inProgramGenerator.BeginProgram(IShaderProgramGenerator::DefaultFlags()
+ | ShaderGeneratorStages::Geometry);
+ GeneratePointVertexGeometrySections(inProgramGenerator);
+
+ IShaderStageGenerator &fragment(
+ *inProgramGenerator.GetStage(ShaderGeneratorStages::Fragment));
+ fragment.AddIncoming("object_idGE", "float");
+ fragment.AddIncoming("uv_coords", "vec2");
+ fragment.Append("void main()\n"
+ "{\n"
+ "\tvec2 coords = uv_coords - vec2(.5, .5);\n"
+ "\tfloat coordLen = length( coords );\n"
+ "\tfloat margin = .4;\n"
+ "\tuint object_id = coordLen < margin ? uint(object_idGE + 1) : uint(0);\n"
+ "\tfragOutput.r = float(object_id % 256)/255.0;\n"
+ "\tfragOutput.g = float(object_id / 256)/255.0;\n"
+ //"\tfragOutput.g = float(object_id) / 10.0;\n"
+ "\tfragOutput.b = 0.0;\n"
+ "\tfragOutput.a = 1.0;\n"
+ "}\n");
+ m_PointPickShader =
+ inProgramGenerator.CompileGeneratedShader("path widget point pick shader");
+ return m_PointPickShader.mPtr;
+ }
+
+ NVRenderShaderProgram *GetLineShader(IShaderProgramGenerator &inProgramGenerator)
+ {
+ if (m_LineShader)
+ return m_LineShader.mPtr;
+
+ inProgramGenerator.BeginProgram(IShaderProgramGenerator::DefaultFlags()
+ | ShaderGeneratorStages::Geometry);
+
+ IShaderStageGenerator &vertex(*inProgramGenerator.GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &geometry(
+ *inProgramGenerator.GetStage(ShaderGeneratorStages::Geometry));
+ IShaderStageGenerator &fragment(
+ *inProgramGenerator.GetStage(ShaderGeneratorStages::Fragment));
+
+ vertex.AddIncoming("attr_pos", "vec2");
+ vertex.AddUniform("model_view_projection", "mat4");
+ vertex << "void main()" << Endl << "{" << Endl
+ << "\tgl_Position = model_view_projection * vec4( attr_pos.xy, 0.0, 1.0 );" << Endl
+ << "}" << Endl;
+
+ geometry.AddUniform("viewport_dimensions", "vec2");
+ geometry.AddUniform("linewidth", "float");
+ geometry.AddOutgoing("uv_coords", "vec2");
+ geometry.Append(
+ "layout (lines) in;\n"
+ "layout (triangle_strip, max_vertices = 4) out;\n"
+ "void main()\n"
+ "{\n"
+ "\tvec2 p0 = vec2(gl_in[0].gl_Position.xy) / gl_in[0].gl_Position.w;\n"
+ "\tvec2 p1 = vec2(gl_in[1].gl_Position.xy) / gl_in[1].gl_Position.w;\n"
+ "\tvec2 slope = normalize( p1 - p0 );\n"
+ "\tvec2 tangent = vec2(slope.y, -slope.x);\n"
+ "\tvec2 increments = (linewidth / viewport_dimensions) / 2.0;\n"
+ "\tvec2 tangentVec = vec2( tangent.x * increments.x, tangent.y * increments.y );\n"
+ "\tgl_Position = vec4( p0 - tangentVec, 0.0, 1.0);\n"
+ "\tuv_coords = vec2(0.0, 0.0);\n"
+ "\tEmitVertex();\n"
+ "\tgl_Position = vec4( p0 + tangentVec, 0.0, 1.0);\n"
+ "\tuv_coords = vec2(1.0, 0.0);\n"
+ "\tEmitVertex();\n"
+ "\tgl_Position = vec4( p1 - tangentVec, 0.0, 1.0);\n"
+ "\tuv_coords = vec2(0.0, 1.0);\n"
+ "\tEmitVertex();\n"
+ "\tgl_Position = vec4( p1 + tangentVec, 0.0, 1.0);\n"
+ "\tuv_coords = vec2(1.0, 1.0);\n"
+ "\tEmitVertex();\n"
+ "\tEndPrimitive();\n"
+ "}\n");
+
+ fragment.AddUniform("line_color", "vec3");
+ fragment.AddIncoming("uv_coords", "vec2");
+ fragment.Append("void main()\n"
+ "{\n"
+ "\tvec2 coords = uv_coords - vec2(.5, .5);\n"
+ "\tfloat coordLen = abs(coords.x);\n"
+ "\tfloat margin = .1;\n"
+ "\tfloat leftover = min( 1.0, (coordLen - margin)/.3 );\n"
+ "\tleftover = leftover * leftover;\n"
+ "\tfloat alpha = coordLen < margin ? 1.0 : mix( 1.0, 0.0, leftover );\n"
+ "\tfragOutput = vec4(line_color, alpha);\n"
+ "}\n");
+
+ m_LineShader = inProgramGenerator.CompileGeneratedShader("path widget line shader");
+ return m_LineShader.mPtr;
+ }
+
+ void RenderPointBuffer(NVRenderShaderProgram &inProgram, const QT3DSMat44 &inMVP,
+ NVRenderContext &inRenderContext)
+ {
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetDepthTestEnabled(false);
+ inRenderContext.SetDepthWriteEnabled(false);
+ inRenderContext.SetStencilTestEnabled(false);
+ inRenderContext.SetBlendingEnabled(true);
+ inRenderContext.SetBlendFunction(qt3ds::render::NVRenderBlendFunctionArgument(
+ qt3ds::render::NVRenderSrcBlendFunc::SrcAlpha,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ qt3ds::render::NVRenderSrcBlendFunc::One,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha));
+ inRenderContext.SetBlendEquation(qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add));
+ inRenderContext.SetActiveShader(&inProgram);
+ inProgram.SetPropertyValue("model_view_projection", inMVP);
+ inProgram.SetPropertyValue("pointsize", (QT3DSF32)15.0f);
+ inProgram.SetPropertyValue("viewport_dimensions", m_PointViewportDimensions);
+ inRenderContext.SetInputAssembler(m_PointAssembler);
+ inRenderContext.Draw(NVRenderDrawMode::Points, m_PointBuffer.size(), 0);
+ }
+
+ void PushPoint(const SPointEntry &inEntry, QT3DSU32 inAnchorIndex,
+ uic::studio::SPathPick::EAnchorProperty inProperty)
+ {
+ QT3DSU32 anchorIndex = (QT3DSU32)m_PointBuffer.size();
+ m_PointBuffer.push_back(inEntry);
+ m_AnchorIndexBuffer.push_back(eastl::make_pair(inAnchorIndex, inProperty));
+ }
+
+ void Render(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext) override
+ {
+ if (!m_Node)
+ return;
+ SPath &thePath = static_cast<SPath &>(*m_Node);
+ IPathManager &theManager = m_UICContext.GetPathManager();
+
+ QT3DSVec3 anchorColor(0, 1, 0);
+ QT3DSVec3 controlColor(0, 0, 1);
+ m_LineBuffer.clear();
+ m_PointBuffer.clear();
+ // point index -> anchor index
+ m_AnchorIndexBuffer.clear();
+ QT3DSU32 anchorIndex = 0;
+
+ for (SPathSubPath *theSubPath = thePath.m_FirstSubPath; theSubPath;
+ theSubPath = theSubPath->m_NextSubPath) {
+ NVDataRef<uic::render::SPathAnchorPoint> thePathBuffer(
+ theManager.GetPathSubPathBuffer(*theSubPath));
+ if (thePathBuffer.size() == 0)
+ return;
+
+ QT3DSU32 numAnchors = thePathBuffer.size();
+ for (QT3DSU32 idx = 0, end = numAnchors; idx < end; ++idx) {
+ const uic::render::SPathAnchorPoint &theAnchorPoint(thePathBuffer[idx]);
+ if (idx > 0) {
+ QT3DSVec2 incoming(uic::render::IPathManagerCore::GetControlPointFromAngleDistance(
+ theAnchorPoint.m_Position, theAnchorPoint.m_IncomingAngle,
+ theAnchorPoint.m_IncomingDistance));
+ PushPoint(SPointEntry(incoming, controlColor, m_PointBuffer.size()),
+ anchorIndex, uic::studio::SPathPick::IncomingControl);
+ m_LineBuffer.push_back(eastl::make_pair(theAnchorPoint.m_Position, incoming));
+ }
+ PushPoint(SPointEntry(theAnchorPoint.m_Position, anchorColor, m_PointBuffer.size()),
+ anchorIndex, uic::studio::SPathPick::Anchor);
+ if (idx < (numAnchors - 1)) {
+ QT3DSVec2 outgoing(uic::render::IPathManagerCore::GetControlPointFromAngleDistance(
+ theAnchorPoint.m_Position, theAnchorPoint.m_OutgoingAngle,
+ theAnchorPoint.m_OutgoingDistance));
+ PushPoint(SPointEntry(outgoing, controlColor, m_PointBuffer.size()),
+ anchorIndex, uic::studio::SPathPick::OutgoingControl);
+ m_LineBuffer.push_back(eastl::make_pair(theAnchorPoint.m_Position, outgoing));
+ }
+ ++anchorIndex;
+ }
+ }
+
+ m_RenderSetup = SWidgetRenderSetupResult(inWidgetContext, *m_Node,
+ uic::render::RenderWidgetModes::Local);
+
+ m_PointMVP = m_RenderSetup.m_WidgetInfo.m_LayerProjection
+ * m_RenderSetup.m_WidgetInfo.m_CameraGlobalInverse * m_Node->m_GlobalTransform;
+
+ NVRenderRect theViewport = inRenderContext.GetViewport();
+ m_PointViewportDimensions = QT3DSVec2((QT3DSF32)theViewport.m_Width, (QT3DSF32)theViewport.m_Height);
+
+ if (!m_LineBuffer.empty()) {
+ QT3DSU32 vertItemSize = sizeof(QT3DSVec2);
+ QT3DSU32 vertBufSize = m_LineBuffer.size() * vertItemSize * 2;
+ if ((!m_LineVertexBuffer) || m_LineVertexBuffer->Size() < vertBufSize) {
+ m_LineVertexBuffer = inRenderContext.CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Dynamic, vertBufSize, vertItemSize,
+ qt3ds::foundation::toU8DataRef(m_LineBuffer.data(), (QT3DSU32)m_LineBuffer.size()));
+ m_LineAssembler = nullptr;
+ } else
+ m_LineVertexBuffer->UpdateBuffer(
+ qt3ds::foundation::toU8DataRef(m_LineBuffer.data(), (QT3DSU32)m_LineBuffer.size()));
+
+ if (m_LineAssembler == nullptr) {
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 0),
+ };
+ NVRenderAttribLayout *theAttribLayout =
+ &inWidgetContext.CreateAttributeLayout(toConstDataRef(theEntries, 1));
+ m_LineAssembler = inRenderContext.CreateInputAssembler(
+ theAttribLayout, toConstDataRef(&m_LineVertexBuffer.mPtr, 1), nullptr,
+ toConstDataRef(vertItemSize), toConstDataRef((QT3DSU32)0));
+ }
+ inRenderContext.SetInputAssembler(m_LineAssembler);
+ NVRenderShaderProgram *lineShader =
+ GetLineShader(inWidgetContext.GetProgramGenerator());
+ if (lineShader) {
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetDepthTestEnabled(false);
+ inRenderContext.SetDepthWriteEnabled(false);
+ inRenderContext.SetStencilTestEnabled(false);
+ inRenderContext.SetBlendingEnabled(true);
+ inRenderContext.SetBlendFunction(qt3ds::render::NVRenderBlendFunctionArgument(
+ qt3ds::render::NVRenderSrcBlendFunc::SrcAlpha,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ qt3ds::render::NVRenderSrcBlendFunc::One,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha));
+ inRenderContext.SetBlendEquation(qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add));
+ inRenderContext.SetActiveShader(lineShader);
+ lineShader->SetPropertyValue("model_view_projection", m_PointMVP);
+ lineShader->SetPropertyValue("line_color", QT3DSVec3(1.0, 1.0, 0.0));
+ // Note the line needs to be wide enough to account for anti-aliasing.
+ lineShader->SetPropertyValue("linewidth", 3.0f);
+ lineShader->SetPropertyValue("viewport_dimensions", m_PointViewportDimensions);
+ inRenderContext.Draw(NVRenderDrawMode::Lines, m_LineBuffer.size() * 2, 0);
+ }
+ }
+ {
+ QT3DSU32 vertItemSize = (sizeof(SPointEntry));
+ QT3DSU32 vertBufSize = m_PointBuffer.size() * vertItemSize;
+ if ((!m_PointVertexBuffer) || m_PointVertexBuffer->Size() < vertBufSize) {
+ m_PointVertexBuffer = inRenderContext.CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Dynamic, vertBufSize, vertItemSize,
+ qt3ds::foundation::toU8DataRef(m_PointBuffer.data(), (QT3DSU32)m_PointBuffer.size()));
+ m_PointAssembler = nullptr;
+ } else
+ m_PointVertexBuffer->UpdateBuffer(
+ qt3ds::foundation::toU8DataRef(m_PointBuffer.data(), (QT3DSU32)m_PointBuffer.size()));
+ if (m_PointAssembler == nullptr) {
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 0),
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_color", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3, 8),
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_objid", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 1, 20),
+ };
+ NVRenderAttribLayout *theAttribLayout =
+ &inWidgetContext.CreateAttributeLayout(toConstDataRef(theEntries, 3));
+ m_PointAssembler = inRenderContext.CreateInputAssembler(
+ theAttribLayout, toConstDataRef(&m_PointVertexBuffer.mPtr, 1), nullptr,
+ toConstDataRef(vertItemSize), toConstDataRef((QT3DSU32)0));
+ }
+ NVRenderShaderProgram *thePointShader =
+ GetPointShader(inWidgetContext.GetProgramGenerator());
+ GetPointPickShader(inWidgetContext.GetProgramGenerator());
+
+ if (thePointShader) {
+ m_PointMVP = m_RenderSetup.m_WidgetInfo.m_LayerProjection
+ * m_RenderSetup.m_WidgetInfo.m_CameraGlobalInverse * m_Node->m_GlobalTransform;
+
+ RenderPointBuffer(*m_PointShader, m_PointMVP, inRenderContext);
+ }
+ }
+ }
+
+ void RenderPick(const QT3DSMat44 &inProjPreMult, NVRenderContext &inRenderContext,
+ uic::render::SWindowDimensions inWinDimensions) override
+ {
+ if (m_PointAssembler == nullptr || m_PointPickShader == nullptr)
+ return;
+ // The projection premultiplication step moves the viewport around till
+ // it is centered over the mouse and scales everything *post* rendering (to keep appropriate
+ // aspect).
+ QT3DSMat44 theMVP = inProjPreMult * m_PointMVP;
+ m_PointViewportDimensions =
+ QT3DSVec2((QT3DSF32)inWinDimensions.m_Width, (QT3DSF32)inWinDimensions.m_Height);
+
+ RenderPointBuffer(*m_PointPickShader, theMVP, inRenderContext);
+ }
+
+ uic::studio::SStudioPickValue PickIndexToPickValue(QT3DSU32 inPickIndex) override
+ {
+ inPickIndex -= 1;
+
+ if (inPickIndex < m_AnchorIndexBuffer.size())
+ return uic::studio::SPathPick(m_AnchorIndexBuffer[inPickIndex].first,
+ m_AnchorIndexBuffer[inPickIndex].second);
+ else {
+ QT3DS_ASSERT(false);
+ return uic::studio::SPathPick();
+ }
+ }
+};
+}
+
+IPathWidget &IPathWidget::CreatePathWidget(NVAllocatorCallback &inCallback, IUICRenderContext &inRc)
+{
+ return *QT3DS_NEW(inCallback, SPathWidget)(inCallback, inRc);
+}
diff --git a/src/Authoring/Studio/Render/PathWidget.h b/src/Authoring/Studio/Render/PathWidget.h
new file mode 100644
index 00000000..cde1a84a
--- /dev/null
+++ b/src/Authoring/Studio/Render/PathWidget.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_PATH_WIDGET_H
+#define UIC_STUDIO_PATH_WIDGET_H
+#pragma once
+#include "StudioWidget.h"
+#include "UICDMHandles.h"
+#include "StudioPickValues.h"
+
+namespace uic {
+namespace widgets {
+
+ class IPathWidget : public IStudioWidgetBase
+ {
+ public:
+ uic::studio::SStudioPickValue PickIndexToPickValue(QT3DSU32 inPickIndex) override = 0;
+ static IPathWidget &CreatePathWidget(NVAllocatorCallback &inAlloc,
+ IUICRenderContext &inRenderContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Render/StudioPickValues.h b/src/Authoring/Studio/Render/StudioPickValues.h
new file mode 100644
index 00000000..cc811073
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioPickValues.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_PICK_VALUES_H
+#define UIC_STUDIO_PICK_VALUES_H
+#pragma once
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "foundation/Qt3DSUnionCast.h"
+#include "UICDMHandles.h"
+#include "StaticMaxSize.h"
+
+namespace uic {
+namespace studio {
+ using UICDM::CUICDMInstanceHandle;
+ using UICDM::CUICDMGuideHandle;
+
+ struct StudioPickValueTypes
+ {
+ enum Enum {
+ UnknownValueType = 0,
+ Instance,
+ Widget,
+ Guide,
+ Path,
+ };
+ };
+
+ struct SWidgetPick
+ {
+ qt3ds::QT3DSI32 m_WidgetId;
+ SWidgetPick(qt3ds::QT3DSI32 id = 0)
+ : m_WidgetId(id)
+ {
+ }
+ };
+
+ struct SPathPick
+ {
+ enum EAnchorProperty {
+ Anchor = 0,
+ IncomingControl,
+ OutgoingControl,
+ };
+
+ qt3ds::QT3DSU32 m_AnchorIndex;
+ EAnchorProperty m_Property;
+
+ SPathPick()
+ : m_AnchorIndex(0)
+ , m_Property(Anchor)
+ {
+ }
+
+ SPathPick(qt3ds::QT3DSU32 ai, EAnchorProperty p)
+ : m_AnchorIndex(ai)
+ , m_Property(p)
+ {
+ }
+ };
+
+ template <typename TDataType>
+ struct SStudioPickValueTypeMap
+ {
+ };
+
+ template <>
+ struct SStudioPickValueTypeMap<CUICDMInstanceHandle>
+ {
+ static StudioPickValueTypes::Enum GetType() { return StudioPickValueTypes::Instance; }
+ };
+
+ template <>
+ struct SStudioPickValueTypeMap<SWidgetPick>
+ {
+ static StudioPickValueTypes::Enum GetType() { return StudioPickValueTypes::Widget; }
+ };
+
+ template <>
+ struct SStudioPickValueTypeMap<CUICDMGuideHandle>
+ {
+ static StudioPickValueTypes::Enum GetType() { return StudioPickValueTypes::Guide; }
+ };
+
+ template <>
+ struct SStudioPickValueTypeMap<SPathPick>
+ {
+ static StudioPickValueTypes::Enum GetType() { return StudioPickValueTypes::Path; }
+ };
+
+ struct SStudioPickValueTraits
+ {
+ typedef StudioPickValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = Q3DStudio::StaticMaxSize<UICDM::CUICDMInstanceHandle,
+ SWidgetPick,
+ UICDM::CUICDMGuideHandle,
+ SPathPick>::value
+ };
+
+ static TIdType getNoDataId() { return StudioPickValueTypes::UnknownValueType; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SStudioPickValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case StudioPickValueTypes::Instance:
+ return inVisitor(*qt3ds::NVUnionCast<UICDM::CUICDMInstanceHandle *>(inData));
+ case StudioPickValueTypes::Widget:
+ return inVisitor(*qt3ds::NVUnionCast<SWidgetPick *>(inData));
+ case StudioPickValueTypes::Guide:
+ return inVisitor(*qt3ds::NVUnionCast<UICDM::CUICDMGuideHandle *>(inData));
+ case StudioPickValueTypes::Path:
+ return inVisitor(*qt3ds::NVUnionCast<SPathPick *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case StudioPickValueTypes::UnknownValueType:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case StudioPickValueTypes::Instance:
+ return inVisitor(*qt3ds::NVUnionCast<const UICDM::CUICDMInstanceHandle *>(inData));
+ case StudioPickValueTypes::Widget:
+ return inVisitor(*qt3ds::NVUnionCast<const SWidgetPick *>(inData));
+ case StudioPickValueTypes::Guide:
+ return inVisitor(*qt3ds::NVUnionCast<const UICDM::CUICDMGuideHandle *>(inData));
+ case StudioPickValueTypes::Path:
+ return inVisitor(*qt3ds::NVUnionCast<const SPathPick *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case StudioPickValueTypes::UnknownValueType:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SStudioPickValueTraits,
+ SStudioPickValueTraits::TBufferSize>,
+ SStudioPickValueTraits::TBufferSize>
+ TStudioPickValueType;
+
+ struct SStudioPickValue : public TStudioPickValueType
+ {
+ SStudioPickValue() {}
+ SStudioPickValue(CUICDMInstanceHandle inst)
+ : TStudioPickValueType(inst)
+ {
+ }
+ SStudioPickValue(SWidgetPick inst)
+ : TStudioPickValueType(inst)
+ {
+ }
+ SStudioPickValue(CUICDMGuideHandle inst)
+ : TStudioPickValueType(inst)
+ {
+ }
+ SStudioPickValue(SPathPick inst)
+ : TStudioPickValueType(inst)
+ {
+ }
+ SStudioPickValue(const SStudioPickValue &other)
+ : TStudioPickValueType(static_cast<const TStudioPickValueType &>(other))
+ {
+ }
+ SStudioPickValue &operator=(const SStudioPickValue &other)
+ {
+ TStudioPickValueType::operator=(static_cast<const TStudioPickValueType &>(other));
+ return *this;
+ }
+ int GetWidgetId() const
+ {
+ if (getType() == StudioPickValueTypes::Widget)
+ return getData<SWidgetPick>().m_WidgetId;
+ return 0;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Render/StudioRenderer.cpp b/src/Authoring/Studio/Render/StudioRenderer.cpp
new file mode 100644
index 00000000..960cc1b6
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioRenderer.cpp
@@ -0,0 +1,883 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "StudioRendererImpl.h"
+#include "StudioRendererTranslation.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+#include "StudioUtils.h"
+
+#include <QDebug>
+
+#ifdef _WIN32
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+#endif
+using namespace uic::studio;
+
+namespace {
+
+const QT3DSU32 g_WheelFactor = 10; // the wheel zoom factor
+
+struct SEditCameraDefinition
+{
+ EditCameraTypes::Enum m_Type;
+ // Directional cameras have a direction they point
+ QT3DSVec3 m_Direction; // not normalized
+ QString m_Name;
+};
+
+SEditCameraDefinition g_EditCameraDefinitions[] = {
+ { EditCameraTypes::Perspective, QT3DSVec3(1, -1, -1), QObject::tr("Perspective View") },
+ { EditCameraTypes::Orthographic, QT3DSVec3(1, -1, -1), QObject::tr("Orthographic View") },
+ { EditCameraTypes::Directional, QT3DSVec3(0, -1, 0), QObject::tr("Top View") },
+ { EditCameraTypes::Directional, QT3DSVec3(0, 1, 0), QObject::tr("Bottom View") },
+ { EditCameraTypes::Directional, QT3DSVec3(1, 0, 0), QObject::tr("Left View") },
+ { EditCameraTypes::Directional, QT3DSVec3(-1, 0, 0), QObject::tr("Right View") },
+ { EditCameraTypes::Directional, QT3DSVec3(0, 0, -1), QObject::tr("Front View") },
+ { EditCameraTypes::Directional, QT3DSVec3(0, 0, 1), QObject::tr("Back View") },
+};
+QT3DSU32 g_NumEditCameras = sizeof(g_EditCameraDefinitions) / sizeof(*g_EditCameraDefinitions);
+
+struct SRendererImpl : public IStudioRenderer,
+ public IDataModelListener,
+ public IReloadListener,
+ public CPresentationChangeListener,
+ public CSceneDragListener,
+ public CToolbarChangeListener
+{
+ typedef eastl::vector<Option<SEditCameraPersistentInformation>> TEditCameraInfoList;
+ std::shared_ptr<CWGLRenderContext> m_RenderContext;
+ NVScopedRefCounted<IUICRenderContext> m_UICContext;
+ QRect m_Rect;
+ CDispatch &m_Dispatch;
+ CDoc &m_Doc;
+ std::shared_ptr<STranslation> m_Translation;
+ CPt m_MouseDownPoint;
+ CPt m_PreviousMousePoint;
+ bool m_HasPresentation;
+ bool m_Closed;
+ CUpdateableDocumentEditor m_UpdatableEditor;
+ MovementTypes::Enum m_LastDragToolMode;
+ bool m_MaybeDragStart;
+ TEditCameraInfoList m_EditCameraInformation;
+ QT3DSI32 m_EditCameraIndex;
+ SEditCameraPersistentInformation m_MouseDownCameraInformation;
+ SStudioPickValue m_PickResult;
+ bool m_RenderRequested;
+ int m_LastToolMode;
+ bool m_GuidesEnabled;
+ UICDM::TSignalConnectionPtr m_SelectionSignal;
+
+ SRendererImpl()
+ : m_Dispatch(*g_StudioApp.GetCore()->GetDispatch())
+ , m_Doc(*g_StudioApp.GetCore()->GetDoc())
+ , m_HasPresentation(false)
+ , m_Closed(false)
+ , m_UpdatableEditor(m_Doc)
+ , m_LastDragToolMode(MovementTypes::Unknown)
+ , m_MaybeDragStart(false)
+ , m_EditCameraIndex(-1)
+ , m_RenderRequested(false)
+ , m_LastToolMode(0)
+ , m_GuidesEnabled(true)
+ {
+ m_Dispatch.AddReloadListener(this);
+ m_Dispatch.AddDataModelListener(this);
+ m_Dispatch.AddPresentationChangeListener(this);
+ m_SelectionSignal =
+ m_Dispatch.ConnectSelectionChange(std::bind(&SRendererImpl::OnSelectionChange, this));
+ m_Dispatch.AddSceneDragListener(this);
+ m_Dispatch.AddToolbarChangeListener(this);
+ }
+ ~SRendererImpl()
+ {
+ Close();
+ m_Dispatch.RemoveDataModelListener(this);
+ m_Dispatch.RemovePresentationChangeListener(this);
+ m_Dispatch.RemoveSceneDragListener(this);
+ m_Dispatch.RemoveToolbarChangeListener(this);
+ }
+
+ // IDocSceneGraph
+ QT3DSVec3 GetIntendedPosition(UICDM::CUICDMInstanceHandle inHandle, CPt inPoint) override
+ {
+ if (m_Translation)
+ return m_Translation->GetIntendedPosition(inHandle, inPoint);
+
+ return QT3DSVec3(0, 0, 0);
+ }
+
+ ITextRenderer *GetTextRenderer() override
+ {
+ if (m_UICContext.mPtr)
+ return m_UICContext->GetTextRenderer();
+ return NULL;
+ }
+ // The buffer manager may not be available
+ IBufferManager *GetBufferManager() override
+ {
+ if (m_UICContext.mPtr)
+ return &m_UICContext->GetBufferManager();
+ return NULL;
+ }
+
+ IPathManager *GetPathManager() override
+ {
+ if (m_UICContext.mPtr)
+ return &m_UICContext->GetPathManager();
+ return NULL;
+ }
+
+ qt3ds::foundation::IStringTable *GetRenderStringTable() override
+ {
+ if (m_UICContext.mPtr)
+ return &m_UICContext->GetStringTable();
+ return NULL;
+ }
+
+ bool IsInitialized() override { return m_UICContext.mPtr != NULL; }
+
+ void Initialize(QWidget *inWindow) override
+ {
+ if (m_Closed)
+ return;
+ QT3DS_ASSERT(!m_RenderContext);
+ QT3DS_ASSERT(m_UICContext.mPtr == NULL);
+ try {
+ m_RenderContext = std::make_shared<CWGLRenderContext>(inWindow);
+
+ Q3DStudio::CString theResourcePath = Q3DStudio::CString::fromQString(resourcePath());
+ NVScopedRefCounted<uic::render::IUICRenderContextCore> theCore =
+ uic::render::IUICRenderContextCore::Create(
+ m_RenderContext->GetRenderContext().GetFoundation(),
+ m_RenderContext->GetRenderContext().GetStringTable());
+
+ // Create text renderer
+ uic::render::ITextRendererCore &theTextRenderer(
+ uic::render::ITextRendererCore::CreateQtTextRenderer(
+ m_RenderContext->GetRenderContext().GetFoundation(),
+ m_RenderContext->GetRenderContext().GetStringTable()));
+ theCore->SetTextRendererCore(theTextRenderer);
+
+ m_UICContext = theCore->CreateRenderContext(
+ m_RenderContext->GetRenderContext(),
+ m_RenderContext->GetRenderContext().GetStringTable().RegisterStr(
+ theResourcePath.c_str()));
+
+ // Allow the artist to interact with the top level objects alone.
+ m_UICContext->GetRenderer().PickRenderPlugins(false);
+
+ SetupTextRenderer();
+
+ m_UICContext->SetAuthoringMode(true);
+
+ InitializePointerTags(m_UICContext->GetStringTable());
+ SetViewRect(m_Rect);
+#ifdef KDAB_TEMPORARILY_REMOVE
+ // KDAB_TODO the below call asserts on windows
+ m_RenderContext->GetRenderContext().SetClearColor(QT3DSVec4(0, 0, 0, 1));
+#endif
+ if (m_HasPresentation)
+ CreateTranslator();
+
+ // Notify that renderer has been initialized
+ m_Dispatch.FireOnRendererInitialized();
+ } catch (...) {
+ m_UICContext = nullptr;
+ m_RenderContext = std::shared_ptr<CWGLRenderContext>();
+ throw;
+ }
+ }
+
+ void SetViewRect(const QRect &inRect) override
+ {
+ if (m_RenderContext)
+ m_RenderContext->resized();
+
+ m_Rect = inRect;
+ if (IsInitialized()) {
+ m_RenderContext->BeginRender();
+ NVRenderContext &theContext = m_RenderContext->GetRenderContext();
+ theContext.SetViewport(qt3ds::render::NVRenderRect(0, 0, inRect.width(),
+ inRect.height()));
+ SetTranslationViewport();
+ m_RenderContext->EndRender();
+ }
+ }
+ // Request that this object renders. May be ignored if a transaction
+ // is ongoing so we don't get multiple rendering per transaction.
+ void RequestRender() override
+ {
+ if (m_RenderContext)
+ m_RenderContext->requestRender();
+ }
+
+ void RenderRequestedRender()
+ {
+ if (m_RenderRequested) {
+ m_RenderContext->requestRender();
+ }
+ }
+
+ void RenderNow() override
+ {
+ Render();
+ }
+
+ void MakeContextCurrent() override
+ {
+ m_RenderContext->BeginRender();
+ }
+
+ void ReleaseContext()
+ {
+ m_RenderContext->EndRender();
+ }
+
+ void Render()
+ {
+ m_RenderRequested = false;
+ if (!m_Closed && IsInitialized()) {
+ m_RenderContext->BeginRender();
+ if (m_Translation)
+ m_Translation->PreRender();
+ NVRenderContext &theContext = m_RenderContext->GetRenderContext();
+ theContext.SetDepthWriteEnabled(true);
+ theContext.Clear(qt3ds::render::NVRenderClearFlags(
+ qt3ds::render::NVRenderClearValues::Color | qt3ds::render::NVRenderClearValues::Depth));
+ if (m_Translation) {
+ m_Translation->Render(m_PickResult.GetWidgetId(), m_GuidesEnabled);
+ }
+ m_RenderContext->EndRender();
+ }
+ }
+ void GetEditCameraList(QStringList &outCameras) override
+ {
+ outCameras.clear();
+ for (QT3DSU32 idx = 0; idx < g_NumEditCameras; ++idx)
+ outCameras.push_back(g_EditCameraDefinitions[idx].m_Name);
+ }
+ void SetEnableEditLight(bool inEnableLight) override
+ {
+ CStudioPreferences::SetEditViewFillMode(inEnableLight);
+ if (m_Translation)
+ m_Translation->m_EditLightEnabled = inEnableLight;
+ RequestRender();
+ }
+
+ bool DoesEditCameraSupportRotation(QT3DSI32 inIndex) override
+ {
+ if (inIndex >= 0 && inIndex < (QT3DSI32)g_NumEditCameras)
+ return g_EditCameraDefinitions[inIndex].m_Type != EditCameraTypes::Directional;
+ return false;
+ }
+
+ bool AreGuidesEnabled() const override { return m_GuidesEnabled; }
+
+ void SetGuidesEnabled(bool val) override { m_GuidesEnabled = val; }
+
+ bool AreGuidesEditable() const override { return m_Doc.IsValid() ? m_Doc.GetDocumentReader().AreGuidesEditable() : false; }
+
+ void SetGuidesEditable(bool val) override { if (m_Doc.IsValid()) m_Doc.GetDocumentReader().SetGuidesEditable(val); }
+
+ // Setting the camera to -1 disables the edit cameras
+ // So setting the camera to 0- (numcameras - 1) will set change the active
+ // edit camera.
+ void SetEditCamera(QT3DSI32 inIndex) override
+ {
+ QT3DSI32 oldIndex = m_EditCameraIndex;
+ m_EditCameraIndex = NVMin(inIndex, (QT3DSI32)g_NumEditCameras);
+ // save the old edit camera information
+ if (oldIndex != m_EditCameraIndex && m_Translation && m_Translation->m_EditCameraEnabled) {
+ while (m_EditCameraInformation.size() <= (QT3DSU32)oldIndex)
+ m_EditCameraInformation.push_back(Empty());
+
+ m_EditCameraInformation[oldIndex] = m_Translation->m_EditCameraInfo;
+ }
+
+ ApplyEditCameraIndex();
+ RequestRender();
+ }
+
+ QT3DSI32 GetEditCamera() const override
+ {
+ if (m_EditCameraIndex >= 0 && m_EditCameraIndex < (QT3DSI32)g_NumEditCameras)
+ return m_EditCameraIndex;
+ return -1;
+ }
+
+ bool IsEditLightEnabled() const override
+ {
+ return GetEditCamera() >= 0 && CStudioPreferences::GetEditViewFillMode();
+ }
+
+ void EditCameraZoomToFit() override
+ {
+ UICDM::CUICDMInstanceHandle theInstance = m_Doc.GetSelectedInstance();
+ if (!m_Translation || m_Translation->m_EditCameraEnabled == false)
+ return;
+ // If we aren't pointed at a node then bounce up the asset graph till we are.
+ while (theInstance.Valid() && m_Translation->GetOrCreateTranslator(theInstance)
+ && GraphObjectTypes::IsNodeType(
+ m_Translation->GetOrCreateTranslator(theInstance)->GetGraphObject().m_Type)
+ == false) {
+ theInstance = m_Translation->m_AssetGraph.GetParent(theInstance);
+ }
+ // If we still aren't pointed at a node then use the active layer.
+ if (theInstance.Valid() == false
+ || m_Translation->GetOrCreateTranslator(theInstance) == nullptr
+ || GraphObjectTypes::IsNodeType(
+ m_Translation->GetOrCreateTranslator(theInstance)->GetGraphObject().m_Type)
+ == false)
+ theInstance = m_Doc.GetActiveLayer();
+
+ // If we *still* aren't pointed at a node then bail.
+ if (m_Translation->GetOrCreateTranslator(theInstance) == nullptr
+ || GraphObjectTypes::IsNodeType(
+ m_Translation->GetOrCreateTranslator(theInstance)->GetGraphObject().m_Type)
+ == false)
+ return;
+
+ SNode &theNode = static_cast<SNode &>(
+ m_Translation->GetOrCreateTranslator(theInstance)->GetGraphObject());
+ qt3ds::NVBounds3 theBounds;
+ theBounds.setEmpty();
+ if (theNode.m_Type == GraphObjectTypes::Layer) {
+ SNode *theEditLayer = m_Translation->GetEditCameraLayer();
+ if (theEditLayer) {
+ for (SNode *theChild = theEditLayer->m_FirstChild; theChild;
+ theChild = theChild->m_NextSibling) {
+ qt3ds::NVBounds3 childBounds = theChild->GetBounds(
+ m_UICContext->GetBufferManager(), m_UICContext->GetPathManager());
+ if (childBounds.isEmpty() == false) {
+ childBounds.transform(theChild->m_GlobalTransform);
+ theBounds.include(childBounds);
+ }
+ }
+ }
+ } else
+ theBounds =
+ theNode.GetBounds(m_UICContext->GetBufferManager(), m_UICContext->GetPathManager());
+ QT3DSVec3 theCenter = theNode.m_GlobalTransform.transform(theBounds.getCenter());
+ // Center the edit camera so that it points directly at the bounds center point
+ m_Translation->m_EditCameraInfo.m_Position = theCenter;
+ // Now we need to adjust the camera's zoom such that the view frustum contains the bounding
+ // box.
+ // But to do that I need to figure out what the view frustum is at -600 units from the near
+ // clip plane
+
+ QT3DSVec3 theExtents = theBounds.getExtents();
+ // get the largest extent and then some addition so things fit nicely in the viewport.
+ QT3DSF32 theMaxPossibleRadius = theExtents.magnitude();
+ // easiest case, the viewport dimensions map directly to the
+ m_Translation->m_EditCameraInfo.m_ViewRadius = theMaxPossibleRadius;
+ RequestRender();
+ }
+
+ // This must be safe to call from multiple places
+ void Close() override
+ {
+ m_Closed = true;
+ m_Translation = std::shared_ptr<STranslation>();
+ m_UICContext = nullptr;
+ m_RenderContext = std::shared_ptr<CWGLRenderContext>();
+ }
+
+ // Data model listener
+
+ // Fired before a large group of notifications come out so views can
+ // only refresh their view once.
+ void OnBeginDataModelNotifications() override {}
+ // Fired after a large gruop of notifications (onInstancePropertyChanged, etc) come out
+ // so views can be careful about refreshing their data and there view
+ void OnEndDataModelNotifications() override { Render(); }
+
+ // Fired during 3d drag or mouse move events (or keyframe drag) or likewise
+ // events so that views that need to update based on the new data can.
+ void OnImmediateRefreshInstanceSingle(UICDM::CUICDMInstanceHandle inInstance) override
+ {
+ if (m_Translation) {
+ m_Translation->MarkDirty(inInstance);
+ // Pass to translation system
+ Render();
+ }
+ }
+ // Same thing, but fired when more than one instance is being refreshed.
+ void OnImmediateRefreshInstanceMultiple(UICDM::CUICDMInstanceHandle *inInstance,
+ long inInstanceCount) override
+ {
+ // Pass to translation system
+ if (m_Translation) {
+ m_Translation->MarkDirty(inInstance, inInstanceCount);
+ // Pass to translation system
+ Render();
+ }
+ Render();
+ }
+
+ void OnReloadEffectInstance(UICDM::CUICDMInstanceHandle inInstance) override
+ {
+ if (m_Translation)
+ m_Translation->ReleaseEffect(inInstance);
+ }
+
+ void ApplyEditCameraIndex()
+ {
+ if (!m_Translation)
+ return;
+ if (m_EditCameraIndex < 0 || m_EditCameraIndex >= (QT3DSI32)g_NumEditCameras)
+ m_Translation->m_EditCameraEnabled = false;
+ else {
+ const SEditCameraDefinition &theDefinition(g_EditCameraDefinitions[m_EditCameraIndex]);
+
+ while ((size_t)m_EditCameraIndex >= m_EditCameraInformation.size())
+ m_EditCameraInformation.push_back(Empty());
+
+ Option<SEditCameraPersistentInformation> &theCameraInfo =
+ m_EditCameraInformation[m_EditCameraIndex];
+
+ if (!theCameraInfo.hasValue()) {
+ theCameraInfo = SEditCameraPersistentInformation();
+ // TODO - consider resizing clip planes to scene so we use the depth buffer more
+ // accurately
+ // or consider requesting a larger depth buffer from the windowing system.
+ // Setup the camera
+ theCameraInfo->m_Direction = theDefinition.m_Direction;
+ theCameraInfo->m_CameraType = theDefinition.m_Type;
+ }
+
+ m_Translation->m_EditCameraEnabled = true;
+ m_Translation->m_EditCameraInfo = theCameraInfo;
+ }
+ }
+
+ void SetTranslationViewport()
+ {
+ if (m_Translation) {
+ m_Translation->SetViewport(QT3DSF32(m_Rect.right() - m_Rect.left()),
+ QT3DSF32(m_Rect.bottom() - m_Rect.top()));
+ }
+ }
+
+ void CreateTranslator()
+ {
+ if (!m_Translation) {
+ if (m_UICContext.mPtr) {
+ m_Translation = std::make_shared<STranslation>(std::ref(*this),
+ std::ref(*m_UICContext.mPtr));
+ m_Translation->m_EditLightEnabled = CStudioPreferences::GetEditViewFillMode();
+ ApplyEditCameraIndex();
+ SetTranslationViewport();
+ }
+ }
+ }
+
+ void SetupTextRenderer()
+ {
+ if (m_UICContext.mPtr && m_UICContext->GetTextRenderer()) {
+ m_UICContext->GetTextRenderer()->ClearProjectFontDirectories();
+ Q3DStudio::CString theDocDir = m_Doc.GetDocumentDirectory();
+ if (theDocDir.Length()) {
+ // Add the installed font folders from the res dir.
+ Q3DStudio::CString thePath(Q3DStudio::CString::fromQString(
+ resourcePath() + QStringLiteral("/Font")));
+ m_UICContext->GetTextRenderer()->AddSystemFontDirectory(
+ m_UICContext->GetStringTable().RegisterStr(thePath.c_str()));
+ m_UICContext->GetTextRenderer()->AddProjectFontDirectory(
+ m_UICContext->GetStringTable().RegisterStr(theDocDir.c_str()));
+ }
+ }
+ }
+
+ //==========================================================================
+ /**
+ * New presentation is being created.
+ */
+ void OnNewPresentation() override
+ {
+ OnClosingPresentation();
+ m_HasPresentation = true;
+ // Reset edit camera information.
+ m_EditCameraInformation.clear();
+ // Rebuild translation
+ CreateTranslator();
+ SetupTextRenderer();
+ RequestRender();
+ }
+
+ //==========================================================================
+ /**
+ * The current presentation is being closed.
+ */
+ void OnClosingPresentation() override
+ {
+ // Destroy translation
+ m_Translation = std::shared_ptr<STranslation>();
+ m_HasPresentation = false;
+ }
+
+ void OnSelectionChange() { RequestRender(); }
+
+ UICDM::CUICDMInstanceHandle GetAnchorPointFromPick(SPathPick &inPick)
+ {
+ return m_Translation->GetAnchorPoint(inPick);
+ }
+
+ //==========================================================================
+ // CSceneDragListener
+ //==========================================================================
+ void OnSceneMouseDown(SceneDragSenderType::Enum inSenderType, QPoint inPoint, int) override
+ {
+ if (m_Translation == NULL)
+ return;
+
+ inPoint.setX(inPoint.x() * devicePixelRatio());
+ inPoint.setY(inPoint.y() * devicePixelRatio());
+
+ m_PickResult = SStudioPickValue();
+ TranslationSelectMode::Enum theSelectMode = TranslationSelectMode::Group;
+ switch (g_StudioApp.GetSelectMode()) {
+ case STUDIO_SELECTMODE_ENTITY:
+ theSelectMode = TranslationSelectMode::Single;
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ theSelectMode = TranslationSelectMode::Group;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ if (inSenderType == SceneDragSenderType::SceneWindow
+ && m_Translation->GetPickArea(inPoint) == PickTargetAreas::Presentation) {
+ m_RenderContext->BeginRender();
+ m_PickResult = m_Translation->Pick(inPoint, theSelectMode);
+ m_RenderContext->EndRender();
+ // If we definitely did not pick a widget.
+ if (m_PickResult.getType() == StudioPickValueTypes::Instance) {
+ UICDM::CUICDMInstanceHandle theHandle(m_PickResult.getData<CUICDMInstanceHandle>());
+
+ if (theHandle != m_Doc.GetSelectedInstance())
+ m_Doc.SelectUICDMObject(theHandle);
+ } else if (m_PickResult.getType() == StudioPickValueTypes::Guide)
+ m_Doc.NotifySelectionChanged(m_PickResult.getData<UICDM::CUICDMGuideHandle>());
+ else if (m_PickResult.getType() == StudioPickValueTypes::Path) {
+ SPathPick thePick = m_PickResult.getData<SPathPick>();
+ UICDM::CUICDMInstanceHandle theAnchorHandle =
+ m_Translation->GetAnchorPoint(thePick);
+ if (theAnchorHandle.Valid() && theAnchorHandle != m_Doc.GetSelectedInstance()) {
+ m_Doc.SelectUICDMObject(theAnchorHandle);
+ }
+ }
+ RequestRender();
+ } else {
+ qt3ds::foundation::Option<UICDM::SGuideInfo> pickResult =
+ m_Translation->PickRulers(inPoint);
+ if (pickResult.hasValue() == false)
+ m_Translation->PrepareForDrag();
+ else {
+ Q3DStudio::IDocumentEditor &docEditor(
+ m_UpdatableEditor.EnsureEditor(L"Create Guide", __FILE__, __LINE__));
+ CUICDMGuideHandle newGuide = docEditor.CreateGuide(*pickResult);
+ m_PickResult = SStudioPickValue(newGuide);
+ m_Doc.NotifySelectionChanged(newGuide);
+ }
+ }
+ m_LastDragToolMode = MovementTypes::Unknown;
+ m_MaybeDragStart = true;
+ m_MouseDownPoint = inPoint;
+ m_PreviousMousePoint = inPoint;
+ m_MouseDownCameraInformation = m_Translation->m_EditCameraInfo;
+ m_LastToolMode = g_StudioApp.GetToolMode();
+ }
+
+ void OnSceneMouseDrag(SceneDragSenderType::Enum, QPoint inPoint, int inToolMode,
+ int inFlags) override
+ {
+ if (m_Translation == NULL)
+ return;
+
+ inPoint.setX(inPoint.x() * devicePixelRatio());
+ inPoint.setY(inPoint.y() * devicePixelRatio());
+
+ if (m_MaybeDragStart) {
+ // Dragging in the first 5 pixels will be ignored to avoid unconsciously accidental
+ // moves
+ CPt theDragDistance = inPoint - m_MouseDownPoint;
+ if (m_PickResult.getType() == StudioPickValueTypes::Widget
+ || inToolMode != STUDIO_TOOLMODE_SCALE) {
+ if (theDragDistance.x * theDragDistance.x + theDragDistance.y * theDragDistance.y
+ <= 25)
+ return;
+ } else {
+ if (abs(theDragDistance.y) <= 5)
+ return;
+ }
+ }
+
+ m_MaybeDragStart = false;
+
+ // If the tool mode changes then we throw out the last widget pick if there was one.
+ if (m_LastToolMode != inToolMode)
+ m_PickResult = SStudioPickValue();
+ m_LastToolMode = inToolMode;
+
+ // General dragging
+ if (m_PickResult.getType() == StudioPickValueTypes::Instance
+ || m_PickResult.getType()
+ == StudioPickValueTypes::UnknownValueType) // matte drag and widget drag
+ {
+ // Not sure what right-click drag does in the scene.
+ bool isEditCamera = m_Translation->m_EditCameraEnabled;
+ int theCameraToolMode = isEditCamera ? (inToolMode & (STUDIO_CAMERATOOL_MASK)) : 0;
+ bool rightClick = (inFlags & CHotKeys::MOUSE_RBUTTON) != 0;
+
+ if (theCameraToolMode == 0) {
+ if (m_Doc.GetDocumentReader().IsInstance(m_Doc.GetSelectedInstance())) {
+ bool rightClick = (inFlags & CHotKeys::MOUSE_RBUTTON) != 0;
+ MovementTypes::Enum theMovement(MovementTypes::Unknown);
+
+ switch (inToolMode) {
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ case STUDIO_TOOLMODE_MOVE:
+ if (rightClick)
+ theMovement = MovementTypes::TranslateAlongCameraDirection;
+ else
+ theMovement = MovementTypes::Translate;
+ break;
+ case STUDIO_TOOLMODE_SCALE:
+ if (rightClick)
+ theMovement = MovementTypes::ScaleZ;
+ else
+ theMovement = MovementTypes::Scale;
+ break;
+ case STUDIO_TOOLMODE_ROTATE:
+ if (rightClick)
+ theMovement = MovementTypes::RotationAboutCameraDirection;
+ else
+ theMovement = MovementTypes::Rotation;
+ break;
+ }
+
+ if (theMovement != MovementTypes::Unknown) {
+ bool theLockToAxis = (inFlags & CHotKeys::MODIFIER_SHIFT) != 0;
+
+ if (m_LastDragToolMode != MovementTypes::Unknown
+ && theMovement != m_LastDragToolMode) {
+ m_UpdatableEditor.RollbackEditor();
+ m_MouseDownPoint = inPoint;
+ }
+
+ m_LastDragToolMode = theMovement;
+
+ switch (theMovement) {
+ case MovementTypes::TranslateAlongCameraDirection:
+ m_Translation->TranslateSelectedInstanceAlongCameraDirection(
+ m_MouseDownPoint, inPoint, m_UpdatableEditor);
+ break;
+ case MovementTypes::Translate:
+ m_Translation->TranslateSelectedInstance(
+ m_MouseDownPoint, inPoint, m_UpdatableEditor, theLockToAxis);
+ break;
+ case MovementTypes::ScaleZ:
+ m_Translation->ScaleSelectedInstanceZ(m_MouseDownPoint, inPoint,
+ m_UpdatableEditor);
+ break;
+ case MovementTypes::Scale:
+ m_Translation->ScaleSelectedInstance(m_MouseDownPoint, inPoint,
+ m_UpdatableEditor);
+ break;
+ case MovementTypes::Rotation:
+ m_Translation->RotateSelectedInstance(m_MouseDownPoint,
+ m_PreviousMousePoint, inPoint,
+ m_UpdatableEditor, theLockToAxis);
+ break;
+ case MovementTypes::RotationAboutCameraDirection:
+ m_Translation->RotateSelectedInstanceAboutCameraDirectionVector(
+ m_PreviousMousePoint, inPoint, m_UpdatableEditor);
+ break;
+ }
+ }
+ }
+ } else {
+ QT3DSF32 theXDistance = static_cast<QT3DSF32>(inPoint.x() - m_MouseDownPoint.x);
+ QT3DSF32 theYDistance = static_cast<QT3DSF32>(inPoint.y() - m_MouseDownPoint.y);
+ QT3DSF32 theSubsetXDistance = static_cast<QT3DSF32>(inPoint.x() - m_PreviousMousePoint.x);
+ QT3DSF32 theSubsetYDistance = static_cast<QT3DSF32>(inPoint.y() - m_PreviousMousePoint.y);
+
+ // Edit cameras are not implemented.
+ switch (theCameraToolMode) {
+ case STUDIO_TOOLMODE_CAMERA_PAN: {
+ QT3DSVec3 theXAxis =
+ m_Translation->m_EditCamera.m_GlobalTransform.column0.getXYZ();
+ QT3DSVec3 theYAxis =
+ m_Translation->m_EditCamera.m_GlobalTransform.column1.getXYZ();
+ QT3DSVec3 theXChange = -1.0f * theXAxis * theXDistance;
+ QT3DSVec3 theYChange = theYAxis * theYDistance;
+ QT3DSVec3 theDiff = theXChange + theYChange;
+ m_Translation->m_EditCameraInfo.m_Position =
+ m_MouseDownCameraInformation.m_Position + theDiff;
+ RequestRender();
+ } break;
+ case STUDIO_TOOLMODE_CAMERA_ZOOM: {
+ QT3DSF32 theMultiplier = 1.0f + theSubsetYDistance / 40.0f;
+ m_Translation->m_EditCameraInfo.m_ViewRadius =
+ NVMax(.0001f, m_Translation->m_EditCameraInfo.m_ViewRadius * theMultiplier);
+ RequestRender();
+ } break;
+ case STUDIO_TOOLMODE_CAMERA_ROTATE: {
+ if (m_Translation->m_EditCameraInfo.SupportsRotation()) {
+ if (rightClick == false) {
+ QT3DSVec3 theXAxis = QT3DSVec3(1, 0, 0);
+ QT3DSVec3 theYAxis = QT3DSVec3(0, 1, 0);
+ // Rotate about the center; we will just rotation the direction vector.
+ QT3DSQuat theXRotation(-1.0f * theSubsetXDistance * g_RotationScaleFactor
+ / 20.0f,
+ theYAxis);
+ QT3DSQuat theYRotation(-1.0f * theSubsetYDistance * g_RotationScaleFactor
+ / 20.0f,
+ theXAxis);
+ m_Translation->m_EditCameraInfo.m_Rotation =
+ m_MouseDownCameraInformation.m_Rotation
+ * (theXRotation * theYRotation);
+ } else {
+ QT3DSVec3 theZAxis = QT3DSVec3(0, 0, 1);
+ QT3DSQuat theZRotation(
+ -1.0f * theYDistance * g_RotationScaleFactor / 20.0f, theZAxis);
+ m_Translation->m_EditCameraInfo.m_Rotation =
+ m_MouseDownCameraInformation.m_Rotation * theZRotation;
+ }
+ // Rotations need to be incremental and relative else things don't rotate
+ // intuitively.
+ m_MouseDownCameraInformation.m_Rotation =
+ m_Translation->m_EditCameraInfo.m_Rotation;
+ RequestRender();
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ } // if ( m_PickResult.m_WidgetId.hasValue() == false )
+
+ // We need to do widget-specific dragging.
+ else if (m_PickResult.getType() == StudioPickValueTypes::Widget) {
+ m_Translation->PerformWidgetDrag(m_PickResult.GetWidgetId(), m_MouseDownPoint,
+ m_PreviousMousePoint, inPoint, m_UpdatableEditor);
+ } else if (m_PickResult.getType() == StudioPickValueTypes::Guide) {
+ m_Translation->PerformGuideDrag(m_PickResult.getData<CUICDMGuideHandle>(), inPoint,
+ m_UpdatableEditor);
+ } else if (m_PickResult.getType() == StudioPickValueTypes::Path) {
+ SPathPick thePick = m_PickResult.getData<SPathPick>();
+ m_Translation->PerformPathDrag(thePick, m_MouseDownPoint, m_PreviousMousePoint, inPoint,
+ m_UpdatableEditor);
+ }
+ m_PreviousMousePoint = inPoint;
+ }
+
+ void OnSceneMouseUp(SceneDragSenderType::Enum) override
+ {
+ m_MaybeDragStart = false;
+ CUICDMGuideHandle theSelectedGuide;
+ if (m_PickResult.getType() == StudioPickValueTypes::Guide) {
+ theSelectedGuide = m_PickResult.getData<CUICDMGuideHandle>();
+ m_Translation->CheckGuideInPresentationRect(theSelectedGuide, m_UpdatableEditor);
+ }
+ m_UpdatableEditor.CommitEditor();
+ m_PickResult = SStudioPickValue();
+ if (m_Translation)
+ m_Translation->EndDrag();
+ if (theSelectedGuide.GetHandleValue()) {
+ // Get rid of selection if things aren't editable.
+ if (m_Doc.GetDocumentReader().AreGuidesEditable())
+ m_Doc.NotifySelectionChanged(theSelectedGuide);
+ else
+ m_Doc.NotifySelectionChanged();
+ }
+ RequestRender();
+ }
+
+ void OnSceneMouseDblClick(SceneDragSenderType::Enum inSenderType, QPoint inPoint) override
+ {
+ if (inSenderType == SceneDragSenderType::SceneWindow && m_Translation) {
+ inPoint.setX(inPoint.x() * devicePixelRatio());
+ inPoint.setY(inPoint.y() * devicePixelRatio());
+ m_RenderContext->BeginRender();
+ SStudioPickValue theResult(
+ m_Translation->Pick(inPoint, TranslationSelectMode::NestedComponentSingle));
+ m_RenderContext->EndRender();
+
+ if (theResult.getType() == StudioPickValueTypes::Instance)
+ m_Doc.SelectAndNavigateToUICDMObject(theResult.getData<CUICDMInstanceHandle>());
+ else if (theResult.getType() == StudioPickValueTypes::Path) {
+ SPathPick thePickValue = theResult.getData<SPathPick>();
+ UICDM::CUICDMInstanceHandle theAnchorHandle =
+ m_Translation->GetAnchorPoint(thePickValue);
+ if (theAnchorHandle.Valid() && theAnchorHandle != m_Doc.GetSelectedInstance()) {
+ m_Doc.SelectUICDMObject(theAnchorHandle);
+ }
+ }
+ }
+ }
+
+ void OnSceneMouseWheel(SceneDragSenderType::Enum inSenderType, short inDelta,
+ int inToolMode) override
+ {
+ ASSERT(inSenderType == SceneDragSenderType::Matte);
+ if (inToolMode == STUDIO_TOOLMODE_CAMERA_ZOOM && m_Translation) {
+ QT3DSF32 theMultiplier = 1.0f - inDelta / static_cast<QT3DSF32>(120 * g_WheelFactor);
+ m_Translation->m_EditCameraInfo.m_ViewRadius =
+ NVMax(.0001f, m_Translation->m_EditCameraInfo.m_ViewRadius * theMultiplier);
+ RequestRender();
+ }
+ }
+
+ void OnNudge(ENudgeDirection inNudgeDirection, int inToolMode, int inFlags) override
+ {
+ if (m_Translation)
+ m_Translation->OnNudge(inNudgeDirection, inToolMode, inFlags, m_UpdatableEditor);
+ }
+
+ void OnNudgeDone() override
+ {
+ if (m_Translation)
+ m_Translation->OnNudgeFinished();
+ m_UpdatableEditor.CommitEditor();
+ }
+
+ void OnToolbarChange() override { RequestRender(); }
+};
+}
+
+std::shared_ptr<IStudioRenderer> IStudioRenderer::CreateStudioRenderer()
+{
+ return std::make_shared<SRendererImpl>();
+}
diff --git a/src/Authoring/Studio/Render/StudioRendererImpl.h b/src/Authoring/Studio/Render/StudioRendererImpl.h
new file mode 100644
index 00000000..86ce4f0b
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioRendererImpl.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_RENDERER_IMPL_H
+#define UIC_STUDIO_RENDERER_IMPL_H
+#pragma once
+#include "IStudioRenderer.h"
+#include "WGLRenderContext.h"
+#include "UICDMDataTypes.h"
+#include "UICDMSignals.h"
+#include "UICRenderContext.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "IDocumentReader.h"
+#include "UICFileTools.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSVec4.h"
+#include "DispatchListeners.h"
+#include "Dispatch.h"
+#include "Core.h"
+#include "foundation/Qt3DSInvasiveSet.h"
+#include "UICRenderer.h"
+#include "UICRenderScene.h"
+#include "UICRenderNode.h"
+#include "UICRenderLayer.h"
+#include "UICRenderModel.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderLight.h"
+#include "UICRenderCamera.h"
+#include "UICRenderImage.h"
+#include "UICRenderPresentation.h"
+#include "StudioProjectSettings.h"
+#include "UICRenderUIPSharedTranslation.h"
+#include "UICRenderBufferManager.h"
+#include "StudioFullSystem.h"
+#include "UICDMSignals.h"
+#include "CoreConst.h"
+#include "IDocumentEditor.h"
+#include "foundation/Qt3DSPlane.h"
+#include "foundation/Qt3DSQuat.h"
+#include "UICTextRenderer.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSMathUtils.h"
+#include "UICRenderEffect.h"
+#include "UICRenderPath.h"
+#include "UICRenderPathSubPath.h"
+
+namespace uic {
+namespace studio {
+ using Q3DStudio::IDocumentReader;
+ using Q3DStudio::CUpdateableDocumentEditor;
+ using Q3DStudio::TIdentifier;
+ using Q3DStudio::IStudioRenderer;
+ using qt3ds::foundation::NVScopedRefCounted;
+ using qt3ds::QT3DSVec3;
+ using qt3ds::QT3DSQuat;
+ using qt3ds::QT3DSF32;
+ using qt3ds::QT3DSMat44;
+ using qt3ds::QT3DSMat33;
+ using qt3ds::QT3DSI32;
+ using qt3ds::QT3DSVec2;
+ using qt3ds::QT3DSVec4;
+ using qt3ds::NVMax;
+ using qt3ds::NVMin;
+ using qt3ds::QT3DSU32;
+ using qt3ds::foundation::Empty;
+ using qt3ds::foundation::InvasiveSet;
+ using qt3ds::foundation::nvhash_map;
+ using qt3ds::foundation::nvvector;
+ using qt3ds::foundation::rotationArc;
+ using qt3ds::foundation::Option;
+ using qt3ds::foundation::Empty;
+ using uic::render::IUICRenderContext;
+ using uic::render::SScene;
+ using uic::render::SLayer;
+ using uic::render::SNode;
+ using uic::render::SGraphObject;
+ using uic::render::SLight;
+ using uic::render::SCamera;
+ using uic::render::SDefaultMaterial;
+ using uic::render::SImage;
+ using uic::render::SModel;
+ using uic::render::SText;
+ using uic::render::GraphObjectTypes;
+ using uic::render::SRay;
+ using uic::render::ITextRenderer;
+ using uic::render::SEffect;
+ using uic::render::IEffectSystem;
+ using uic::render::SDynamicObject;
+ using uic::render::SCustomMaterial;
+ using uic::render::IDynamicObjectSystem;
+ using uic::render::ICustomMaterialSystem;
+ using uic::render::IBufferManager;
+ using uic::render::IPathManager;
+ using uic::render::SPath;
+ using uic::render::SPathSubPath;
+ using uic::render::SReferencedMaterial;
+ using qt3ds::render::CRegisteredString;
+ using qt3ds::render::IStringTable;
+ using UICDM::SFloat3;
+ using UICDM::SLong4;
+ using UICDM::SComposerObjectDefinitions;
+ using UICDM::CUICDMInstanceHandle;
+ using UICDM::CUICDMPropertyHandle;
+}
+}
+#endif
diff --git a/src/Authoring/Studio/Render/StudioRendererTranslation.cpp b/src/Authoring/Studio/Render/StudioRendererTranslation.cpp
new file mode 100644
index 00000000..7efca4a4
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioRendererTranslation.cpp
@@ -0,0 +1,3827 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "StudioRendererImpl.h"
+#include "StudioRendererTranslation.h"
+#include "UICRenderEffectSystem.h"
+#include "foundation/StrConvertUTF.h"
+#include "UICFileTools.h"
+#include "UICRenderUIPLoader.h"
+#include "UICRenderWidgets.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "UICRenderResourceManager.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "UICRenderCamera.h"
+#include "foundation/Qt3DSPlane.h"
+#include "UICRenderRotationHelper.h"
+#include "UICRenderPluginGraphObject.h"
+#include "UICRenderPlugin.h"
+#include "StudioCoreSystem.h"
+#include "UICDMDataCore.h"
+#include "UICRenderPluginPropertyValue.h"
+#include "UICRenderEffectSystem.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderMaterialHelpers.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderReferencedMaterial.h"
+#include "UICRenderPixelGraphicsTypes.h"
+#include "UICRenderPixelGraphicsRenderer.h"
+#include "UICRenderPathManager.h"
+#include "PathWidget.h"
+#include "UICRenderLightmaps.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+#include <boost/bind.hpp>
+
+#pragma warning(disable : 4100) // unreferenced formal parameter
+
+using namespace uic::studio;
+QT3DSU32 uic::studio::g_GraphObjectTranslatorTag;
+using uic::render::SPGGraphObject;
+using uic::render::SPGRect;
+using uic::render::SPGVertLine;
+using uic::render::SPGHorzLine;
+using qt3ds::render::NVRenderRectF;
+using qt3ds::render::NVRenderRect;
+
+namespace {
+using namespace UICDM;
+struct STranslatorUICDMParser
+{
+ STranslation &m_Context;
+ CUICDMInstanceHandle m_InstanceHandle;
+ STranslatorUICDMParser(STranslation &inContext, CUICDMInstanceHandle inInstance)
+ : m_Context(inContext)
+ , m_InstanceHandle(inInstance)
+ {
+ }
+ CUICDMInstanceHandle GetInstanceHandle() { return m_InstanceHandle; }
+
+ template <typename TDataType>
+ inline Option<TDataType> GetPropertyValue(UICDM::CUICDMPropertyHandle inProperty)
+ {
+ Option<SValue> theValue =
+ m_Context.m_Reader.GetRawInstancePropertyValue(GetInstanceHandle(), inProperty);
+ if (theValue.hasValue())
+ return UICDM::get<TDataType>(*theValue);
+ return Empty();
+ }
+
+ bool ParseProperty(CUICDMPropertyHandle inProperty, QT3DSF32 &outValue)
+ {
+ Option<float> theValue = GetPropertyValue<float>(inProperty);
+ if (theValue.hasValue()) {
+ outValue = theValue.getValue();
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseProperty(CUICDMPropertyHandle inProperty, QT3DSU32 &outValue)
+ {
+ auto theValue = GetPropertyValue<qt3ds::QT3DSI32>(inProperty);
+ if (theValue.hasValue()) {
+ outValue = NVMax(theValue.getValue(), 0);
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseProperty(CUICDMPropertyHandle inProperty, QT3DSI32 &outValue)
+ {
+ auto theValue = GetPropertyValue<qt3ds::QT3DSI32>(inProperty);
+ if (theValue.hasValue()) {
+ outValue = *theValue;
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseRadianProperty(CUICDMPropertyHandle inProperty, QT3DSF32 &outValue)
+ {
+ if (ParseProperty(inProperty, outValue)) {
+ TORAD(outValue);
+ return true;
+ }
+ return false;
+ }
+ bool ParseRadianProperty(CUICDMPropertyHandle inProperty, QT3DSVec3 &outValue)
+ {
+ if (ParseProperty(inProperty, outValue)) {
+ TORAD(outValue.x);
+ TORAD(outValue.y);
+ TORAD(outValue.z);
+ return true;
+ }
+ return false;
+ }
+ bool ParseOpacityProperty(CUICDMPropertyHandle inProperty, QT3DSF32 &outValue)
+ {
+ if (ParseProperty(inProperty, outValue)) {
+ outValue = (1.0f / 100.0f) * outValue;
+ return true;
+ }
+ return false;
+ }
+ bool ParseRotationOrder(CUICDMPropertyHandle inProperty, QT3DSU32 &outValue)
+ {
+ qt3ds::render::CRegisteredString temp;
+ if (ParseProperty(inProperty, temp)) {
+ outValue = uic::render::MapRotationOrder(temp);
+ return true;
+ }
+ return false;
+ }
+ bool ParseOrientation(CUICDMPropertyHandle inProperty, uic::render::NodeFlags &outValue)
+ {
+ qt3ds::render::CRegisteredString temp;
+ if (ParseProperty(inProperty, temp)) {
+ bool isLeftHanded = strcmp(temp.c_str(), "Left Handed") == 0;
+ outValue.SetLeftHanded(isLeftHanded);
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseProperty(CUICDMPropertyHandle inProperty, bool &outValue)
+ {
+ Option<bool> theValue = GetPropertyValue<bool>(inProperty);
+ if (theValue.hasValue()) {
+ outValue = theValue.getValue();
+ return true;
+ }
+ return false;
+ }
+ bool ParseProperty(CUICDMPropertyHandle inProperty, QT3DSVec2 &outValue)
+ {
+ Option<UICDM::SFloat2> theValue = GetPropertyValue<UICDM::SFloat2>(inProperty);
+ if (theValue.hasValue()) {
+ outValue = QT3DSVec2(theValue->m_Floats[0], theValue->m_Floats[1]);
+ return true;
+ }
+ return false;
+ }
+ bool ParseProperty(CUICDMPropertyHandle inProperty, QT3DSVec3 &outValue)
+ {
+ Option<SFloat3> theValue = GetPropertyValue<SFloat3>(inProperty);
+ if (theValue.hasValue()) {
+ outValue = QT3DSVec3(theValue->m_Floats[0], theValue->m_Floats[1], theValue->m_Floats[2]);
+ return true;
+ }
+ return false;
+ }
+ bool ParseProperty(CUICDMPropertyHandle inProperty, qt3ds::render::CRegisteredString &outValue)
+ {
+ Option<UICDM::TDataStrPtr> theValue = GetPropertyValue<UICDM::TDataStrPtr>(inProperty);
+ if (theValue.hasValue() && *theValue) {
+ qt3ds::render::IStringTable &theStrTable(m_Context.m_UICContext.GetStringTable());
+ outValue = theStrTable.RegisterStr((*theValue)->GetData());
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseAndResolveSourcePath(UICDM::CUICDMPropertyHandle inProperty,
+ qt3ds::render::CRegisteredString &outValue)
+ {
+ if (ParseProperty(inProperty, outValue)) {
+ if (outValue.IsValid() && outValue.c_str()[0] != '#') {
+ Q3DStudio::CFilePath theDirectory = m_Context.m_Doc.GetDocumentDirectory();
+ Q3DStudio::CFilePath theResolvedPath =
+ Q3DStudio::CFilePath::CombineBaseAndRelative(theDirectory, outValue.c_str());
+ outValue =
+ m_Context.m_UICContext.GetStringTable().RegisterStr(theResolvedPath.c_str());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ template <typename TEnumType>
+ bool ParseEnumProperty(UICDM::CUICDMPropertyHandle inProperty, TEnumType &ioValue)
+ {
+ qt3ds::render::CRegisteredString temp;
+ if (ParseProperty(inProperty, temp)) {
+ uic::render::SEnumNameMap *theNameMap(uic::render::SEnumParseMap<TEnumType>::GetMap());
+ for (uic::render::SEnumNameMap *theIter = theNameMap;
+ theIter->m_Name && *theIter->m_Name; ++theIter) {
+ // hack to match advanced overlay types, whose name start with a '*'
+ const char8_t *p = temp;
+ if (*p == '*')
+ ++p;
+ if (strcmp(p, theIter->m_Name) == 0) {
+ ioValue = (TEnumType)theIter->m_Enum;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool ParseNodeFlagsProperty(UICDM::CUICDMPropertyHandle inProperty,
+ uic::render::NodeFlags &outValue,
+ uic::render::NodeFlagValues::Enum theFlag)
+ {
+ bool temp = false;
+ if (ParseProperty(inProperty, temp)) {
+ outValue.ClearOrSet(temp, theFlag);
+ return true;
+ }
+ return false;
+ }
+ bool ParseNodeFlagsInverseProperty(UICDM::CUICDMPropertyHandle inProperty,
+ uic::render::NodeFlags &outValue,
+ uic::render::NodeFlagValues::Enum theFlag)
+ {
+ bool temp = false;
+ if (ParseProperty(inProperty, temp)) {
+ outValue.ClearOrSet(!temp, theFlag);
+ return true;
+ }
+ return false;
+ }
+ bool ParseProperty(CUICDMPropertyHandle inProperty, uic::render::SImage *&ioImage)
+ {
+ Option<SLong4> theData = GetPropertyValue<SLong4>(inProperty);
+ if (theData.hasValue()) {
+ UICDM::CUICDMInstanceHandle theInstance(
+ m_Context.m_Reader.GetInstanceForGuid(*theData));
+ SGraphObjectTranslator *imageTranslator = m_Context.GetOrCreateTranslator(theInstance);
+ if (imageTranslator
+ && imageTranslator->GetGraphObject().m_Type
+ == uic::render::GraphObjectTypes::Image) {
+ SImage *theNewImage = static_cast<SImage *>(&imageTranslator->GetGraphObject());
+ ioImage = theNewImage;
+ } else
+ ioImage = nullptr;
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseProperty(CUICDMPropertyHandle inProperty, uic::render::SGraphObject *&ioObjRef)
+ {
+ Option<SObjectRefType> theData = GetPropertyValue<SObjectRefType>(inProperty);
+ if (theData.hasValue()) {
+ UICDM::CUICDMInstanceHandle theInstance(
+ m_Context.m_Reader.GetInstanceForObjectRef(m_InstanceHandle, *theData));
+ SGraphObjectTranslator *theItemTranslator =
+ m_Context.GetOrCreateTranslator(theInstance);
+ if (theItemTranslator)
+ ioObjRef = &theItemTranslator->GetGraphObject();
+ }
+ return true;
+ }
+
+ bool ParseProperty(CUICDMPropertyHandle inProperty, uic::render::SNode *&ioNodePtr)
+ {
+ Option<SObjectRefType> theData = GetPropertyValue<SObjectRefType>(inProperty);
+ SNode *theNewNodePtr = nullptr;
+ if (theData.hasValue()) {
+ UICDM::CUICDMInstanceHandle theInstance(
+ m_Context.m_Reader.GetInstanceForObjectRef(m_InstanceHandle, *theData));
+ SGraphObjectTranslator *theItemTranslator =
+ m_Context.GetOrCreateTranslator(theInstance);
+ if (theItemTranslator) {
+ SGraphObject &theObject = theItemTranslator->GetGraphObject();
+ if (GraphObjectTypes::IsNodeType(theObject.m_Type))
+ theNewNodePtr = &static_cast<SNode &>(theObject);
+ }
+ }
+ ioNodePtr = theNewNodePtr;
+ return true;
+ }
+};
+
+// Define parse tables
+#define Scene_ClearColor m_Scene.m_BackgroundColor
+#define Scene_UseClearColor m_Scene.m_BgColorEnable
+#define Node_Rotation m_Node.m_Rotation
+#define Node_Position m_Node.m_Position
+#define Node_Scale m_Node.m_Scale
+#define Node_Pivot m_Node.m_Pivot
+#define Node_LocalOpacity m_Node.m_Opacity
+#define Node_RotationOrder m_Node.m_RotationOrder
+#define Node_LeftHanded m_Node.m_Orientation
+#define Layer_TemporalAAEnabled m_Layer.m_TemporalAA
+#define Layer_LayerEnableDepthTest m_Layer.m_DisableDepthTest
+#define Layer_LayerEnableDepthPrePass m_Layer.m_DisableDepthPrepass
+#define Layer_ClearColor m_Layer.m_BackgroundColor
+#define Layer_Background m_Layer.m_Background
+#define Layer_BlendType m_Layer.m_BlendType
+#define Layer_Size m_Layer.m_Size
+#define Layer_Location m_Layer.m_Location
+#define Layer_ProgressiveAAMode m_Layer.m_ProgressiveAA
+#define Layer_MultisampleAAMode m_Layer.m_MultisampleAA
+#define Layer_HorizontalFieldValues m_Layer.m_HorizontalFieldValues
+#define Layer_Left m_Layer.m_Left
+#define Layer_LeftUnits m_Layer.m_LeftUnits
+#define Layer_Width m_Layer.m_Width
+#define Layer_WidthUnits m_Layer.m_WidthUnits
+#define Layer_Right m_Layer.m_Right
+#define Layer_RightUnits m_Layer.m_RightUnits
+#define Layer_VerticalFieldValues m_Layer.m_VerticalFieldValues
+#define Layer_Top m_Layer.m_Top
+#define Layer_TopUnits m_Layer.m_TopUnits
+#define Layer_Height m_Layer.m_Height
+#define Layer_HeightUnits m_Layer.m_HeightUnits
+#define Layer_Bottom m_Layer.m_Bottom
+#define Layer_BottomUnits m_Layer.m_BottomUnits
+#define Layer_AoStrength m_Layer.m_AoStrength
+#define Layer_AoDistance m_Layer.m_AoDistance
+#define Layer_AoSoftness m_Layer.m_AoSoftness
+#define Layer_AoBias m_Layer.m_AoBias
+#define Layer_AoSamplerate m_Layer.m_AoSamplerate
+#define Layer_AoDither m_Layer.m_AoDither
+#define Layer_ShadowStrength m_Layer.m_ShadowStrength
+#define Layer_ShadowDist m_Layer.m_ShadowDist
+#define Layer_ShadowSoftness m_Layer.m_ShadowSoftness
+#define Layer_ShadowBias m_Layer.m_ShadowBias
+#define Layer_LightProbe m_Layer.m_LightProbe
+#define Layer_ProbeBright m_Layer.m_ProbeBright
+#define Layer_FastIbl m_Layer.m_FastIbl
+#define Layer_ProbeHorizon m_Layer.m_ProbeHorizon
+#define Layer_ProbeFov m_Layer.m_ProbeFov
+#define Layer_LightProbe2 m_Layer.m_LightProbe2
+#define Layer_Probe2Fade m_Layer.m_Probe2Fade
+#define Layer_Probe2Window m_Layer.m_Probe2Window
+#define Layer_Probe2Pos m_Layer.m_Probe2Pos
+#define Layer_TexturePath m_Asset.m_SourcePath
+#define Camera_ClipNear m_Camera.m_ClipNear
+#define Camera_ClipFar m_Camera.m_ClipFar
+#define Camera_FOV m_Camera.m_Fov
+#define Camera_Orthographic m_Camera.m_Orthographic
+#define Camera_ScaleMode m_Camera.m_ScaleMode
+#define Camera_ScaleAnchor m_Camera.m_ScaleAnchor
+#define Light_LightType m_Light.m_LightType
+#define Light_Scope m_Light.m_Scope
+#define Light_DiffuseColor m_Light.m_LightColor
+#define Light_SpecularColor m_Light.m_SpecularColor
+#define Light_AmbientColor m_Light.m_AmbientColor
+#define Light_Brightness m_Light.m_Brightness
+#define Light_LinearFade m_Light.m_LinearFade
+#define Light_ExponentialFade m_Light.m_ExpFade
+#define Light_AreaWidth m_Light.m_AreaWidth
+#define Light_AreaHeight m_Light.m_AreaHeight
+#define Light_CastShadow m_Light.m_CastShadow
+#define Light_ShadowBias m_Light.m_ShadowBias
+#define Light_ShadowFactor m_Light.m_ShadowFactor
+#define Light_ShadowMapRes m_Light.m_ShadowMapRes
+#define Light_ShadowMapFar m_Light.m_ShadowMapFar
+#define Light_ShadowFilter m_Light.m_ShadowFilter
+#define Model_MeshPath m_Asset.m_SourcePath
+#define Model_TessellationMode m_Model.m_Tessellation
+#define Model_EdgeTess m_Model.m_EdgeTess
+#define Model_InnerTess m_Model.m_InnerTess
+#define Lightmaps_LightmapIndirect m_Lightmaps.m_LightmapIndirect
+#define Lightmaps_LightmapRadiosity m_Lightmaps.m_LightmapRadiosity
+#define Lightmaps_LightmapShadow m_Lightmaps.m_LightmapShadow
+#define MaterialBase_IblProbe m_MaterialBase.m_IblProbe
+#define Material_Lighting m_Material.m_ShaderLighting
+#define Material_BlendMode m_Material.m_BlendMode
+#define Material_DiffuseColor m_Material.m_DiffuseColor
+#define Material_DiffuseMaps_0 m_Material.m_DiffuseMap1
+#define Material_DiffuseMaps_1 m_Material.m_DiffuseMap2
+#define Material_DiffuseMaps_2 m_Material.m_DiffuseMap3
+#define Material_EmissivePower m_Material.m_EmissivePower
+#define Material_EmissiveColor m_Material.m_EmissiveColor
+#define Material_EmissiveMap m_Material.m_EmissiveMap
+#define Material_EmissiveMap2 m_Material.m_EmissiveMap2
+#define Material_SpecularReflection m_Material.m_SpecularReflection
+#define Material_SpecularMap m_Material.m_SpecularMap
+#define Material_SpecularModel m_Material.m_SpecularModel
+#define Material_SpecularTint m_Material.m_SpecularTint
+#define Material_IOR m_Material.m_IOR
+#define Material_FresnelPower m_Material.m_FresnelPower
+#define Material_SpecularAmount m_Material.m_SpecularAmount
+#define Material_SpecularRoughness m_Material.m_SpecularRoughness
+#define Material_Opacity m_Material.m_Opacity
+#define Material_OpacityMap m_Material.m_OpacityMap
+#define Material_BumpMap m_Material.m_BumpMap
+#define Material_BumpAmount m_Material.m_BumpAmount
+#define Material_NormalMap m_Material.m_NormalMap
+#define Material_DisplacementMap m_Material.m_DisplacementMap
+#define Material_DisplaceAmount m_Material.m_DisplaceAmount
+#define Material_TranslucencyMap m_Material.m_TranslucencyMap
+#define Material_TranslucentFalloff m_Material.m_TranslucentFalloff
+#define Material_DiffuseLightWrap m_Material.m_DiffuseLightWrap
+#define Material_ReferencedMaterial m_ReferencedMaterial.m_ReferencedMaterial
+#define Image_ImagePath m_Asset.m_SourcePath
+#define Image_OffscreenRendererId m_Image.m_SubPresentation
+#define Image_Scale_X m_Image.m_RepeatU
+#define Image_Scale_Y m_Image.m_RepeatV
+#define Image_Pivot_X m_Image.m_PivotU
+#define Image_Pivot_Y m_Image.m_PivotV
+#define Image_Rotation m_Image.m_RotationUV
+#define Image_Position_X m_Image.m_PositionU
+#define Image_Position_Y m_Image.m_PositionV
+#define Image_MappingMode m_Image.m_TextureMapping
+#define Image_HorizontalTilingMode m_Image.m_TilingU
+#define Image_VerticalTilingMode m_Image.m_TilingV
+#define Text_Text m_Text.m_TextString
+#define Text_Font m_Text.m_Font
+#define Text_FontSize m_Text.m_Size
+#define Text_HorizontalAlignment m_Text.m_HorzAlign
+#define Text_VerticalAlignment m_Text.m_VertAlign
+#define Text_Leading m_Text.m_Leading
+#define Text_Tracking m_Text.m_Tracking
+#define Text_TextColor m_Text.m_TextColor
+#define Text_EnableAcceleratedFont m_Text.m_EnableAcceleratedFont
+#define Path_Width m_Path.m_Width
+#define Path_LinearError m_Path.m_LinearError
+#define Path_InnerTessAmount m_Path.m_InnerTessAmount
+#define Path_EdgeTessAmount m_Path.m_EdgeTessAmount
+#define Path_Opacity m_Path.m_Opacity
+#define Path_BeginCapping m_Path.m_BeginCap
+#define Path_BeginCapOffset m_Path.m_BeginCapOffset
+#define Path_BeginCapOpacity m_Path.m_BeginCapOpacity
+#define Path_BeginCapWidth m_Path.m_BeginCapWidth
+#define Path_EndCapping m_Path.m_EndCap
+#define Path_EndCapOffset m_Path.m_EndCapOffset
+#define Path_EndCapOpacity m_Path.m_EndCapOpacity
+#define Path_EndCapWidth m_Path.m_EndCapWidth
+#define Path_PathType m_Path.m_PathType
+#define Path_PaintStyle m_Path.m_PaintStyle
+#define Path_PathBuffer m_Asset.m_SourcePath
+#define SubPath_Closed m_SubPath.m_Closed
+
+// Fill in implementations for the actual parse tables.
+#define HANDLE_UIC_RENDER_PROPERTY(type, name, dirty) \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_VEC3_PROPERTY(type, name, dirty) \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_REAL_VEC2_PROPERTY(type, name, dirty) \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_COLOR_PROPERTY(type, name, dirty) \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_RADIAN_PROPERTY(type, name, dirty) \
+ theParser.ParseRadianProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_VEC3_RADIAN_PROPERTY(type, name, dirty) \
+ theParser.ParseRadianProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_OPACITY_PROPERTY(type, name, dirty) \
+ theParser.ParseOpacityProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_ROTATION_ORDER_PROPERTY(type, name, dirty) \
+ theParser.ParseRotationOrder(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_NODE_ORIENTATION_PROPERTY(type, name, dirty) \
+ theParser.ParseOrientation(inContext.m_ObjectDefinitions.type##_##name, theItem.m_Flags);
+#define HANDLE_UIC_RENDER_DEPTH_TEST_PROPERTY(type, name, dirty) \
+ if (theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name)) \
+ theItem.m_##name = !theItem.m_##name;
+#define HANDLE_UIC_NODE_FLAGS_PROPERTY(type, name, dirty) \
+ theParser.ParseNodeFlagsProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_Flags, \
+ uic::render::NodeFlagValues::name);
+#define HANDLE_UIC_NODE_FLAGS_INVERSE_PROPERTY(type, name, dirty) \
+ theParser.ParseNodeFlagsInverseProperty(inContext.m_ObjectDefinitions.type##_##name, \
+ theItem.m_Flags, uic::render::NodeFlagValues::name);
+#define HANDLE_UIC_RENDER_ENUM_PROPERTY(type, name, dirty) \
+ theParser.ParseEnumProperty(inContext.m_ObjectDefinitions.type##_##name, theItem.m_##name);
+#define HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(type, name, dirty) \
+ theParser.ParseAndResolveSourcePath(inContext.m_ObjectDefinitions.type##_##name, \
+ theItem.m_##name);
+#define HANDLE_UIC_RENDER_ARRAY_PROPERTY(type, name, index, dirty) \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name##_##index, \
+ theItem.m_##name[index]);
+#define HANDLE_UIC_RENDER_VEC2_PROPERTY(type, name, dirty) \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name##_##X, \
+ theItem.m_##name.x); \
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.type##_##name##_##Y, theItem.m_##name.y);
+#define HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY( \
+ type, name, dirty) // noop by intention already handled by HANDLE_UIC_RENDER_COLOR_PROPERTY
+#define HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY( \
+ type, name, dirty) // noop by intention already handled by HANDLE_UIC_RENDER_VEC3_PROPERTY
+
+struct SSceneTranslator : public SGraphObjectTranslator
+{
+ SSceneTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SScene)())
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SScene &theItem = static_cast<SScene &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_SCENE_PROPERTIES
+ SLayer *theCurrentLayer = nullptr;
+ theItem.m_FirstChild = nullptr;
+ for (long idx = 0, end = inContext.m_AssetGraph.GetChildCount(GetInstanceHandle());
+ idx < end; ++idx) {
+ SGraphObjectTranslator::PushTranslation(inContext);
+ UICDM::CUICDMInstanceHandle theLayer =
+ inContext.m_AssetGraph.GetChild(GetInstanceHandle(), idx);
+ SGraphObjectTranslator *theTranslator = inContext.GetOrCreateTranslator(theLayer);
+ if (theTranslator
+ && theTranslator->GetGraphObject().m_Type == uic::render::GraphObjectTypes::Layer) {
+ SLayer *theLayerObj = static_cast<SLayer *>(&theTranslator->GetGraphObject());
+ theLayerObj->m_NextSibling = nullptr;
+ if (theItem.m_FirstChild == nullptr)
+ theItem.m_FirstChild = theLayerObj;
+ else
+ theCurrentLayer->m_NextSibling = theLayerObj;
+ theCurrentLayer = theLayerObj;
+ }
+ }
+ }
+ void ClearChildren() override
+ {
+ SScene &theItem = static_cast<SScene &>(GetGraphObject());
+ SLayer *theLastChild = nullptr;
+ for (SLayer *theChild = theItem.m_FirstChild; theChild;
+ theChild = static_cast<SLayer *>(theChild->m_NextSibling)) {
+ if (theLastChild)
+ theLastChild->m_NextSibling = nullptr;
+ theChild->m_Parent = nullptr;
+ theLastChild = theChild;
+ }
+ theItem.m_FirstChild = nullptr;
+ }
+ void AppendChild(SGraphObject &inChild) override
+ {
+ if (inChild.m_Type != GraphObjectTypes::Layer) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SScene &theItem = static_cast<SScene &>(GetGraphObject());
+ SLayer &theLayer = static_cast<SLayer &>(inChild);
+ theItem.AddChild(theLayer);
+ }
+ void SetActive(bool /*inActive*/) override
+ {
+ // How could we not be active?
+ }
+};
+
+struct SNodeTranslator : public SGraphObjectTranslator
+{
+ SNodeTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SNode)())
+ {
+ Initialize();
+ }
+ SNodeTranslator(UICDM::CUICDMInstanceHandle inInstance, SNode &inNode)
+ : SGraphObjectTranslator(inInstance, inNode)
+ {
+ Initialize();
+ }
+ void Initialize()
+ {
+ SNode &theNode = static_cast<SNode &>(GetGraphObject());
+ // Ensure the global transform is valid because we use this before we render sometimes.
+ theNode.m_GlobalTransform = QT3DSMat44::createIdentity();
+ }
+ static inline bool IsNodeType(uic::render::GraphObjectTypes::Enum inType)
+ {
+ return uic::render::GraphObjectTypes::IsNodeType(inType);
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ SGraphObjectTranslator::PushTranslation(inContext);
+ SNode &theItem = static_cast<SNode &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_NODE_PROPERTIES
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Node.m_BoneId,
+ theItem.m_SkeletonId);
+ bool ignoresParent = false;
+ if (theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Node.m_IgnoresParent,
+ ignoresParent))
+ theItem.m_Flags.SetIgnoreParentTransform(ignoresParent);
+ }
+ void AppendChild(SGraphObject &inChild) override
+ {
+ if (GraphObjectTypes::IsNodeType(inChild.m_Type) == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ SNode &theItem = static_cast<SNode &>(GetGraphObject());
+ SNode &theChild = static_cast<SNode &>(inChild);
+ theItem.AddChild(theChild);
+ theItem.MarkDirty(uic::render::NodeTransformDirtyFlag::TransformIsDirty);
+ theChild.MarkDirty(uic::render::NodeTransformDirtyFlag::TransformIsDirty);
+ }
+ void ClearChildren() override
+ {
+ SNode &theItem = static_cast<SNode &>(GetGraphObject());
+ SNode *theLastChild = nullptr;
+ for (SNode *theChild = theItem.m_FirstChild; theChild; theChild = theChild->m_NextSibling) {
+ if (theLastChild)
+ theLastChild->m_NextSibling = nullptr;
+ theLastChild = theChild;
+ theChild->m_Parent = nullptr;
+ }
+ theItem.m_FirstChild = nullptr;
+ }
+
+ void SetActive(bool inActive) override
+ {
+ SNode &theNode = static_cast<SNode &>(GetGraphObject());
+ if (inActive != theNode.m_Flags.IsActive()) {
+ theNode.m_Flags.SetActive(inActive);
+ theNode.MarkDirty(uic::render::NodeTransformDirtyFlag::TransformIsDirty);
+ }
+ }
+};
+
+struct SLayerTranslator : public SNodeTranslator
+{
+ SLayerTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SNodeTranslator(inInstance, *QT3DS_NEW(inAlloc, SLayer)())
+ {
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ SNodeTranslator::PushTranslation(inContext);
+ SLayer &theItem = static_cast<SLayer &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_LAYER_PROPERTIES
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Layer.m_AoSamplerate,
+ theItem.m_AoSamplerate);
+ }
+ void AppendChild(SGraphObject &inChild) override
+ {
+ if (GraphObjectTypes::IsNodeType(inChild.m_Type)) {
+ SNodeTranslator::AppendChild(inChild);
+ } else if (inChild.m_Type == GraphObjectTypes::Effect) {
+ SLayer &theItem = static_cast<SLayer &>(GetGraphObject());
+ theItem.AddEffect(static_cast<SEffect &>(inChild));
+ } else if (inChild.m_Type == GraphObjectTypes::RenderPlugin) {
+ SLayer &theItem = static_cast<SLayer &>(GetGraphObject());
+ theItem.m_RenderPlugin = &static_cast<uic::render::SRenderPlugin &>(inChild);
+ }
+ }
+ void ClearChildren() override
+ {
+ SNodeTranslator::ClearChildren();
+ SLayer &theItem = static_cast<SLayer &>(GetGraphObject());
+ SEffect *theLastChild = nullptr;
+ for (SEffect *theChild = theItem.m_FirstEffect; theChild;
+ theChild = theChild->m_NextEffect) {
+ if (theLastChild)
+ theLastChild->m_NextEffect = nullptr;
+ theLastChild = theChild;
+ theChild->m_Layer = nullptr;
+ }
+ theItem.m_FirstEffect = nullptr;
+ theItem.m_RenderPlugin = nullptr;
+ // Don't clear the light probe properties because those are added/removed as part of the
+ // normal
+ // property scan, they aren't added as generic children.
+ }
+};
+struct SLightTranslator : public SNodeTranslator
+{
+ SLightTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SNodeTranslator(inInstance, *QT3DS_NEW(inAlloc, SLight)())
+ {
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ SNodeTranslator::PushTranslation(inContext);
+ SLight &theItem = static_cast<SLight &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_LIGHT_PROPERTIES
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Light.m_ShadowMapRes,
+ theItem.m_ShadowMapRes);
+ }
+ void AppendChild(SGraphObject &inChild) override { SNodeTranslator::AppendChild(inChild); }
+ void ClearChildren() override { SNodeTranslator::ClearChildren(); }
+};
+struct SCameraTranslator : public SNodeTranslator
+{
+ SCameraTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SNodeTranslator(inInstance, *QT3DS_NEW(inAlloc, SCamera)())
+ {
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ SNodeTranslator::PushTranslation(inContext);
+ SCamera &theItem = static_cast<SCamera &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_CAMERA_PROPERTIES
+ }
+};
+struct SModelTranslator : public SNodeTranslator
+{
+ SModelTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SNodeTranslator(inInstance, *QT3DS_NEW(inAlloc, SModel)())
+ {
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ SNodeTranslator::PushTranslation(inContext);
+ SModel &theItem = static_cast<SModel &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_MODEL_PROPERTIES
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Model.m_PoseRoot,
+ theItem.m_SkeletonRoot);
+
+ theItem.m_FirstMaterial = nullptr;
+ for (long idx = 0, end = inContext.m_AssetGraph.GetChildCount(GetInstanceHandle());
+ idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theItemHandle =
+ inContext.m_AssetGraph.GetChild(GetInstanceHandle(), idx);
+ SGraphObjectTranslator *theTranslator = inContext.GetOrCreateTranslator(theItemHandle);
+ if (theTranslator && IsMaterial(theTranslator->GetGraphObject())) {
+ SGraphObject *theMaterial = &theTranslator->GetGraphObject();
+ SetNextMaterialSibling(*theMaterial, nullptr);
+ theItem.AddMaterial(*theMaterial);
+ }
+ }
+ }
+ void AppendChild(SGraphObject &inChild) override
+ {
+ if (GraphObjectTypes::IsNodeType(inChild.m_Type)) {
+ SNodeTranslator::AppendChild(inChild);
+ } else if (IsMaterial(inChild)) {
+ SModel &theItem = static_cast<SModel &>(GetGraphObject());
+ theItem.AddMaterial(inChild);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ void ClearChildren() override
+ {
+ SModel &theItem = static_cast<SModel &>(GetGraphObject());
+ SNodeTranslator::ClearChildren();
+
+ SGraphObject *theLastMaterial = nullptr;
+ for (SGraphObject *theMaterial = theItem.m_FirstMaterial; theMaterial;
+ theMaterial = uic::render::GetNextMaterialSibling(theMaterial)) {
+ if (theLastMaterial)
+ uic::render::SetNextMaterialSibling(*theLastMaterial, nullptr);
+ theLastMaterial = theMaterial;
+ }
+ theItem.m_FirstMaterial = nullptr;
+ }
+};
+
+static SFloat2 ToFloat2(const Option<SValue> &inValue)
+{
+ if (inValue.hasValue())
+ return inValue->getData<SFloat2>();
+ return SFloat2();
+}
+
+static float ToFloat(const Option<SValue> &inValue)
+{
+ if (inValue.hasValue())
+ return inValue->getData<QT3DSF32>();
+ return 0.0f;
+}
+
+struct SPathSubPathTranslator : public SGraphObjectTranslator
+{
+ eastl::vector<uic::render::SPathAnchorPoint> m_PathBuffer;
+ SPathSubPathTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SPathSubPath)())
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SPathSubPath &theItem = static_cast<SPathSubPath &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_PATH_SUBPATH_PROPERTIES
+ m_PathBuffer.clear();
+ Q3DStudio::IDocumentReader &theReader(inContext.m_Doc.GetDocumentReader());
+ QT3DSU32 anchorCount = 0;
+ for (QT3DSI32 idx = 0, end = inContext.m_AssetGraph.GetChildCount(GetInstanceHandle());
+ idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theAnchor =
+ inContext.m_AssetGraph.GetChild(GetInstanceHandle(), idx);
+ if (theReader.GetObjectTypeName(theAnchor) == L"PathAnchorPoint")
+ ++anchorCount;
+ }
+ QT3DSU32 anchorIdx = 0;
+ for (QT3DSI32 idx = 0, end = inContext.m_AssetGraph.GetChildCount(GetInstanceHandle());
+ idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theAnchor =
+ inContext.m_AssetGraph.GetChild(GetInstanceHandle(), idx);
+ if (theReader.GetObjectTypeName(theAnchor) == L"PathAnchorPoint") {
+ SFloat2 theAnchorPos = ToFloat2(theReader.GetInstancePropertyValue(
+ theAnchor,
+ inContext.m_ObjectDefinitions.m_PathAnchorPoint.m_Position.m_Property));
+ float theIncomingAngle = ToFloat(theReader.GetInstancePropertyValue(
+ theAnchor,
+ inContext.m_ObjectDefinitions.m_PathAnchorPoint.m_IncomingAngle.m_Property));
+ float theIncomingDistance = ToFloat(theReader.GetInstancePropertyValue(
+ theAnchor,
+ inContext.m_ObjectDefinitions.m_PathAnchorPoint.m_IncomingDistance.m_Property));
+ float theOutgoingDistance = ToFloat(theReader.GetInstancePropertyValue(
+ theAnchor,
+ inContext.m_ObjectDefinitions.m_PathAnchorPoint.m_OutgoingDistance.m_Property));
+ uic::render::SPathAnchorPoint thePoint(QT3DSVec2(theAnchorPos[0], theAnchorPos[1]),
+ theIncomingAngle, theIncomingAngle + 180.0f,
+ theIncomingDistance, theOutgoingDistance);
+ m_PathBuffer.push_back(thePoint);
+ ++anchorIdx;
+ }
+ }
+ inContext.m_UICContext.GetPathManager().SetPathSubPathData(
+ theItem,
+ qt3ds::foundation::toConstDataRef(m_PathBuffer.begin(), (QT3DSU32)m_PathBuffer.size()));
+ }
+
+ void AppendChild(SGraphObject &) override {}
+
+ void ClearChildren() override {}
+
+ void SetActive(bool /*inActive*/) override {}
+};
+
+struct SPathTranslator : public SNodeTranslator
+{
+ SPathTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SNodeTranslator(inInstance, *QT3DS_NEW(inAlloc, SPath)())
+ {
+ }
+ void AppendChild(SGraphObject &inChild) override
+ {
+ if (GraphObjectTypes::IsMaterialType(inChild.m_Type)) {
+ SPath &theItem = static_cast<SPath &>(GetGraphObject());
+ theItem.AddMaterial(&inChild);
+ theItem.m_Flags.SetDirty(true);
+ } else if (inChild.m_Type == GraphObjectTypes::PathSubPath) {
+ SPath &theItem = static_cast<SPath &>(GetGraphObject());
+ theItem.AddSubPath(static_cast<SPathSubPath &>(inChild));
+ theItem.m_Flags.SetDirty(true);
+ } else {
+ SNodeTranslator::AppendChild(inChild);
+ }
+ }
+
+ void ClearChildren() override
+ {
+ SNodeTranslator::ClearChildren();
+ SPath &theItem = static_cast<SPath &>(GetGraphObject());
+ theItem.ClearMaterials();
+ theItem.ClearSubPaths();
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SNodeTranslator::PushTranslation(inContext);
+ SPath &theItem = static_cast<SPath &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_PATH_PROPERTIES
+ }
+};
+
+struct SDefaultMaterialTranslator : public SGraphObjectTranslator
+{
+ SDefaultMaterialTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SDefaultMaterial)())
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SGraphObjectTranslator::PushTranslation(inContext);
+ SDefaultMaterial &theItem = static_cast<SDefaultMaterial &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_MATERIAL_PROPERTIES
+
+ // UICDM::CUICDMInstanceHandle parent = inContext.m_AssetGraph.GetParent(
+ // GetInstanceHandle() );
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapIndirect,
+ theItem.m_Lightmaps.m_LightmapIndirect);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapRadiosity,
+ theItem.m_Lightmaps.m_LightmapRadiosity);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapShadow,
+ theItem.m_Lightmaps.m_LightmapShadow);
+ }
+
+ void AppendChild(SGraphObject &) override {}
+ void ClearChildren() override {}
+
+ void SetActive(bool /*inActive*/) override {}
+};
+
+struct SImageTranslator : public SGraphObjectTranslator
+{
+ SImageTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SImage)())
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SGraphObjectTranslator::PushTranslation(inContext);
+ SImage &theItem = static_cast<SImage &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_IMAGE_PROPERTIES
+
+ theItem.m_Flags.SetDirty(true);
+ theItem.m_Flags.SetTransformDirty(true);
+ }
+ void AppendChild(SGraphObject &child) override
+ {
+ SImage &theItem = static_cast<SImage &>(GetGraphObject());
+ if (child.m_Type == GraphObjectTypes::RenderPlugin)
+ theItem.m_RenderPlugin = &static_cast<uic::render::SRenderPlugin &>(child);
+ }
+ void ClearChildren() override
+ {
+ SImage &theItem = static_cast<SImage &>(GetGraphObject());
+ theItem.m_RenderPlugin = nullptr;
+ }
+
+ void SetActive(bool /*inActive*/) override {}
+};
+
+struct STextTranslator : public SNodeTranslator
+{
+ STextTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SNodeTranslator(inInstance, *QT3DS_NEW(inAlloc, SText)())
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SNodeTranslator::PushTranslation(inContext);
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ SText &theItem = static_cast<SText &>(GetGraphObject());
+ ITERATE_UIC_RENDER_TEXT_PROPERTIES
+ theItem.m_Flags.SetTextDirty(true);
+ }
+};
+
+inline qt3ds::QT3DSVec2 ToRenderType(const UICDM::SFloat2 &inType)
+{
+ return qt3ds::QT3DSVec2(inType.m_Floats[0], inType.m_Floats[1]);
+}
+inline qt3ds::QT3DSVec3 ToRenderType(const UICDM::SFloat3 &inType)
+{
+ return qt3ds::QT3DSVec3(inType.m_Floats[0], inType.m_Floats[1], inType.m_Floats[2]);
+}
+
+struct SDynamicObjectTranslator : public SGraphObjectTranslator
+{
+ typedef eastl::vector<eastl::pair<QT3DSU32, int>> TIdxToPropertyMap;
+ eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> m_ConvertStr;
+ TIdxToPropertyMap m_PropertyMap;
+
+ SDynamicObjectTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &,
+ SDynamicObject &inObject)
+ : SGraphObjectTranslator(inInstance, inObject)
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SDynamicObject &theItem = static_cast<SDynamicObject &>(GetGraphObject());
+ IDynamicObjectSystem &theSystem = inContext.m_UICContext.GetDynamicObjectSystem();
+ using namespace uic::render::dynamic;
+ using qt3ds::foundation::NVConstDataRef;
+ NVConstDataRef<SPropertyDefinition> theProperties =
+ theSystem.GetProperties(theItem.m_ClassName);
+ if (m_PropertyMap.size() == 0) {
+ for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(theProperties[idx]);
+ qt3ds::foundation::ConvertUTF(theDefinition.m_Name.c_str(), 0, m_ConvertStr);
+ const wchar_t *thePropName =
+ reinterpret_cast<const wchar_t *>(m_ConvertStr.c_str());
+ UICDM::CUICDMPropertyHandle theProperty =
+ inContext.m_Reader.FindProperty(GetInstanceHandle(), thePropName);
+ if (theProperty.Valid())
+ m_PropertyMap.push_back(eastl::make_pair(idx, theProperty.GetHandleValue()));
+ }
+ }
+ for (TIdxToPropertyMap::iterator theIter = m_PropertyMap.begin(), end = m_PropertyMap.end();
+ theIter != end; ++theIter) {
+ const SPropertyDefinition &theDefinition(theProperties[theIter->first]);
+ UICDM::CUICDMPropertyHandle theProperty = theIter->second;
+ Option<UICDM::SValue> theValueOpt =
+ inContext.m_Reader.GetInstancePropertyValue(GetInstanceHandle(), theProperty);
+ if (theValueOpt.hasValue()) {
+ UICDM::SValue &theValue(*theValueOpt);
+ switch (UICDM::GetValueType(theValue)) {
+ case UICDM::DataModelDataType::Long:
+ if (theDefinition.m_DataType == qt3ds::render::NVRenderShaderDataTypes::QT3DSI32)
+ theItem.SetPropertyValue(theDefinition, UICDM::get<qt3ds::QT3DSI32>(theValue));
+ else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case UICDM::DataModelDataType::Bool:
+ if (theDefinition.m_DataType
+ == qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool)
+ theItem.SetPropertyValue(theDefinition, UICDM::get<bool>(theValue));
+ else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case UICDM::DataModelDataType::Float:
+ if (theDefinition.m_DataType == qt3ds::render::NVRenderShaderDataTypes::QT3DSF32)
+ theItem.SetPropertyValue(theDefinition, UICDM::get<float>(theValue));
+ else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case UICDM::DataModelDataType::Float2:
+ if (theDefinition.m_DataType == qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2)
+ theItem.SetPropertyValue(
+ theDefinition, ToRenderType(UICDM::get<UICDM::SFloat2>(theValue)));
+ else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case UICDM::DataModelDataType::Float3:
+ if (theDefinition.m_DataType == qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3)
+ theItem.SetPropertyValue(
+ theDefinition, ToRenderType(UICDM::get<UICDM::SFloat3>(theValue)));
+ else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ // Could be either an enum or a texture.
+ case UICDM::DataModelDataType::String: {
+ UICDM::TDataStrPtr theData = UICDM::get<UICDM::TDataStrPtr>(theValue);
+ if (theData) {
+ eastl::string theStr;
+ qt3ds::render::ConvertWideUTF(theData->GetData(), 0, theStr);
+ eastl::string theWorkspace;
+ theItem.SetPropertyValue(
+ theDefinition, theStr.c_str(),
+ inContext.m_Doc.GetDocumentDirectory().GetCharStar(), theWorkspace,
+ inContext.m_UICContext.GetStringTable());
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+
+ void AppendChild(SGraphObject &) override {}
+ void ClearChildren() override {}
+};
+
+struct SEffectTranslator : public SDynamicObjectTranslator
+{
+ // TODO - move this map to inContext and have it looked up by name.
+ IEffectSystem *m_EffectSystem;
+
+ SEffectTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc,
+ SEffect &inEffect)
+ : SDynamicObjectTranslator(inInstance, inAlloc, inEffect)
+ , m_EffectSystem(nullptr)
+ {
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ m_EffectSystem = &inContext.m_UICContext.GetEffectSystem();
+ SDynamicObjectTranslator::PushTranslation(inContext);
+ }
+
+ void SetActive(bool inActive) override
+ {
+ SEffect &theItem = static_cast<SEffect &>(GetGraphObject());
+ if (m_EffectSystem)
+ theItem.SetActive(inActive, *m_EffectSystem);
+ else
+ theItem.m_Flags.SetActive(inActive);
+ }
+};
+struct SCustomMaterialTranslator : public SDynamicObjectTranslator
+{
+ ICustomMaterialSystem *m_MaterialSystem;
+
+ SCustomMaterialTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ qt3ds::NVAllocatorCallback &inAlloc, SCustomMaterial &inMaterial)
+ : SDynamicObjectTranslator(inInstance, inAlloc, inMaterial)
+ , m_MaterialSystem(nullptr)
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SDynamicObjectTranslator::PushTranslation(inContext);
+ SCustomMaterial &theItem = static_cast<SCustomMaterial &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_CUSTOM_MATERIAL_PROPERTIES
+
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapIndirect,
+ theItem.m_Lightmaps.m_LightmapIndirect);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapRadiosity,
+ theItem.m_Lightmaps.m_LightmapRadiosity);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapShadow,
+ theItem.m_Lightmaps.m_LightmapShadow);
+ }
+
+ void SetActive(bool inActive) override
+ {
+ if (m_MaterialSystem) {
+ SCustomMaterial &theItem = static_cast<SCustomMaterial &>(GetGraphObject());
+ if (inActive != theItem.m_Flags.IsActive()) {
+ theItem.m_Flags.SetActive(inActive);
+ m_MaterialSystem->OnMaterialActivationChange(theItem, inActive);
+ }
+ }
+ }
+};
+struct SReferencedMaterialTranslator : public SGraphObjectTranslator
+{
+ SReferencedMaterialTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SReferencedMaterial)())
+ {
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ SGraphObjectTranslator::PushTranslation(inContext);
+ SReferencedMaterial &theItem = static_cast<SReferencedMaterial &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ ITERATE_UIC_RENDER_REFERENCED_MATERIAL_PROPERTIES
+
+ theItem.m_Dirty.SetDirty();
+ if (theItem.m_ReferencedMaterial == &theItem) {
+ qCCritical(qt3ds::INVALID_OPERATION,
+ "Referenced material is referencing itself.");
+ } else if (theItem.m_ReferencedMaterial
+ && theItem.m_ReferencedMaterial->m_Type == GraphObjectTypes::DefaultMaterial) {
+ SDefaultMaterial *theDefaultItem =
+ static_cast<SDefaultMaterial *>(theItem.m_ReferencedMaterial);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapIndirect,
+ theDefaultItem->m_Lightmaps.m_LightmapIndirect);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapRadiosity,
+ theDefaultItem->m_Lightmaps.m_LightmapRadiosity);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapShadow,
+ theDefaultItem->m_Lightmaps.m_LightmapShadow);
+ } else if (theItem.m_ReferencedMaterial
+ && theItem.m_ReferencedMaterial->m_Type == GraphObjectTypes::CustomMaterial) {
+ SCustomMaterial *theDefaultItem =
+ static_cast<SCustomMaterial *>(theItem.m_ReferencedMaterial);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapIndirect,
+ theDefaultItem->m_Lightmaps.m_LightmapIndirect);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapRadiosity,
+ theDefaultItem->m_Lightmaps.m_LightmapRadiosity);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Lightmaps.m_LightmapShadow,
+ theDefaultItem->m_Lightmaps.m_LightmapShadow);
+ }
+ }
+
+ void AppendChild(SGraphObject &) override {}
+
+ void ClearChildren() override {}
+
+ void SetActive(bool /*inActive*/) override {}
+};
+using uic::render::SRenderPlugin;
+using uic::render::SRenderPropertyValueUpdate;
+using uic::render::IRenderPluginClass;
+using uic::render::SRenderPluginPropertyDeclaration;
+struct SRenderPluginPropertyUpdateFactory
+{
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates, float value,
+ const SRenderPluginPropertyDeclaration &theDec, IRenderPluginClass &)
+ {
+ ioUpdates.push_back(SRenderPropertyValueUpdate(theDec.m_Name, value));
+ }
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates, qt3ds::QT3DSI32 value,
+ const SRenderPluginPropertyDeclaration &theDec, IRenderPluginClass &)
+ {
+ ioUpdates.push_back(SRenderPropertyValueUpdate(theDec.m_Name, value));
+ }
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates, bool value,
+ const SRenderPluginPropertyDeclaration &theDec, IRenderPluginClass &)
+ {
+ ioUpdates.push_back(SRenderPropertyValueUpdate(theDec.m_Name, value));
+ }
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates, UICDM::TDataStrPtr value,
+ const SRenderPluginPropertyDeclaration &theDec, IRenderPluginClass &,
+ qt3ds::foundation::IStringTable &strTable)
+ {
+ if (value) {
+ ioUpdates.push_back(
+ SRenderPropertyValueUpdate(theDec.m_Name, strTable.RegisterStr(value->GetData())));
+ }
+ }
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates, UICDM::SStringRef value,
+ const SRenderPluginPropertyDeclaration &theDec, IRenderPluginClass &,
+ qt3ds::foundation::IStringTable &strTable)
+ {
+ ioUpdates.push_back(
+ SRenderPropertyValueUpdate(theDec.m_Name, strTable.RegisterStr(value.m_Id)));
+ }
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates,
+ const UICDM::SFloat2 &value, const SRenderPluginPropertyDeclaration &theDec,
+ IRenderPluginClass &inClass)
+ {
+ ioUpdates.push_back(SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(theDec.m_StartOffset).first, value.m_Floats[0]));
+ ioUpdates.push_back(SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(theDec.m_StartOffset + 1).first, value.m_Floats[1]));
+ }
+
+ static void Add(eastl::vector<SRenderPropertyValueUpdate> &ioUpdates,
+ const UICDM::SFloat3 &value, const SRenderPluginPropertyDeclaration &theDec,
+ IRenderPluginClass &inClass)
+ {
+ ioUpdates.push_back(SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(theDec.m_StartOffset).first, value.m_Floats[0]));
+ ioUpdates.push_back(SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(theDec.m_StartOffset + 1).first, value.m_Floats[1]));
+ ioUpdates.push_back(SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(theDec.m_StartOffset + 2).first, value.m_Floats[2]));
+ }
+};
+struct SRenderPluginTranslator : public SGraphObjectTranslator
+{
+ eastl::vector<SRenderPropertyValueUpdate> m_PropertyUpdates;
+
+ SRenderPluginTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SRenderPlugin)())
+ {
+ }
+
+ void PushTranslation(STranslation &inContext) override
+ {
+ SRenderPlugin &theItem = static_cast<SRenderPlugin &>(GetGraphObject());
+ // First, get the instance via resolving the source path.
+ CUICDMPropertyHandle sourcepath =
+ inContext.m_Reader.FindProperty(GetInstanceHandle(), L"sourcepath");
+ Option<SValue> theSourcePath =
+ inContext.m_Reader.GetInstancePropertyValue(GetInstanceHandle(), sourcepath);
+ UICDM::TDataStrPtr theData = theSourcePath->getData<UICDM::TDataStrPtr>();
+ if (!theData)
+ return;
+
+ Q3DStudio::CFilePath theFullPath = inContext.m_Doc.GetResolvedPathToDoc(theData->GetData());
+ qt3ds::foundation::IStringTable &theStrTable = inContext.m_UICContext.GetStringTable();
+ theItem.m_PluginPath = theStrTable.RegisterStr(theFullPath);
+ uic::render::IRenderPluginInstance *theInstance =
+ inContext.m_UICContext.GetRenderPluginManager().GetOrCreateRenderPluginInstance(
+ theItem.m_PluginPath, &theItem);
+
+ // Couldn't load the instance, so we can't render the instance.
+ if (theInstance == nullptr)
+ return;
+ // Grab the instance's parent and get the properties that are specific to just that
+ // instance.
+ TInstanceHandleList derivationParents;
+ std::shared_ptr<IDataCore> theDataCore =
+ inContext.m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetDataCore();
+ theDataCore->GetInstanceParents(GetInstanceHandle(), derivationParents);
+ if (derivationParents.size() == 0)
+ return;
+ TPropertyHandleList theSpecificProperties;
+ theDataCore->GetInstanceProperties(derivationParents[0], theSpecificProperties);
+ eastl::string propStem;
+ eastl::string propname;
+ m_PropertyUpdates.clear();
+ uic::render::IRenderPluginClass &theClass = theInstance->GetPluginClass();
+ using uic::render::SRenderPluginPropertyDeclaration;
+ if (theClass.GetRegisteredProperties().size() == 0) {
+ for (size_t idx = 0, end = theSpecificProperties.size(); idx < end; ++idx) {
+ SUICDMPropertyDefinition theProperty =
+ theDataCore->GetProperty(theSpecificProperties[idx]);
+ UICDM::AdditionalMetaDataType::Value theMetaType =
+ inContext.m_StudioSystem.GetActionMetaData()->GetAdditionalMetaDataType(
+ GetInstanceHandle(), theSpecificProperties[idx]);
+ CRegisteredString thePropName(theStrTable.RegisterStr(theProperty.m_Name.c_str()));
+ switch (theProperty.m_Type) {
+ case DataModelDataType::Float:
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::Float));
+ break;
+ case DataModelDataType::Float2:
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::Vector2));
+ break;
+ case DataModelDataType::Float3:
+ if (theMetaType != AdditionalMetaDataType::Color) {
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::Vector3));
+ } else {
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::Color));
+ }
+ break;
+ case DataModelDataType::Long:
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::Long));
+ break;
+ case DataModelDataType::String:
+ case DataModelDataType::StringRef:
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::String));
+ break;
+ case DataModelDataType::Bool:
+ theClass.RegisterProperty(SRenderPluginPropertyDeclaration(
+ thePropName, uic::render::SRenderPluginPropertyTypes::Boolean));
+ break;
+ default:
+ // Unsupported plugin property.
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+ for (size_t idx = 0, end = theSpecificProperties.size(); idx < end; ++idx) {
+ Option<SValue> thePropValueOpt = inContext.m_Reader.GetInstancePropertyValue(
+ GetInstanceHandle(), theSpecificProperties[idx]);
+ if (thePropValueOpt.hasValue()) {
+ SValue &thePropValue = thePropValueOpt.getValue();
+ SUICDMPropertyDefinition theProperty =
+ theDataCore->GetProperty(theSpecificProperties[idx]);
+ SRenderPluginPropertyDeclaration theDeclaration(theClass.GetPropertyDeclaration(
+ theStrTable.RegisterStr(theProperty.m_Name.c_str())));
+
+ switch (thePropValue.getType()) {
+ case DataModelDataType::None:
+ QT3DS_ASSERT(false);
+ break;
+ case DataModelDataType::Float:
+ SRenderPluginPropertyUpdateFactory::Add(
+ m_PropertyUpdates, thePropValue.getData<float>(), theDeclaration, theClass);
+ break;
+ case DataModelDataType::Float2:
+ SRenderPluginPropertyUpdateFactory::Add(m_PropertyUpdates,
+ thePropValue.getData<SFloat2>(),
+ theDeclaration, theClass);
+ break;
+ case DataModelDataType::Float3:
+ SRenderPluginPropertyUpdateFactory::Add(m_PropertyUpdates,
+ thePropValue.getData<SFloat3>(),
+ theDeclaration, theClass);
+ break;
+ case DataModelDataType::Long:
+ SRenderPluginPropertyUpdateFactory::Add(
+ m_PropertyUpdates, thePropValue.getData<qt3ds::QT3DSI32>(), theDeclaration, theClass);
+ break;
+ case DataModelDataType::String:
+ SRenderPluginPropertyUpdateFactory::Add(m_PropertyUpdates,
+ thePropValue.getData<TDataStrPtr>(),
+ theDeclaration, theClass, theStrTable);
+ break;
+ case DataModelDataType::Bool:
+ SRenderPluginPropertyUpdateFactory::Add(
+ m_PropertyUpdates, thePropValue.getData<bool>(), theDeclaration, theClass);
+ break;
+ case DataModelDataType::StringRef:
+ SRenderPluginPropertyUpdateFactory::Add(m_PropertyUpdates,
+ thePropValue.getData<SStringRef>(),
+ theDeclaration, theClass, theStrTable);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+ theInstance->Update(NVConstDataRef<SRenderPropertyValueUpdate>(m_PropertyUpdates.data(),
+ m_PropertyUpdates.size()));
+ }
+ void AppendChild(SGraphObject &) override {}
+ void ClearChildren() override {}
+ void SetActive(bool inActive) override
+ {
+ SRenderPlugin &theItem = static_cast<SRenderPlugin &>(GetGraphObject());
+ theItem.m_Flags.SetActive(inActive);
+ }
+};
+
+struct SAliasTranslator : public SGraphObjectTranslator
+{
+ SGraphObjectTranslator *m_ReferenceTree;
+ CUICDMInstanceHandle m_ReferencedInstance;
+ SAliasTranslator(UICDM::CUICDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &inAlloc)
+ : SGraphObjectTranslator(inInstance, *QT3DS_NEW(inAlloc, SNode)())
+ , m_ReferenceTree(nullptr)
+ {
+ }
+ void RecurseAndCreateTranslators(STranslation &inContext,
+ UICDM::CUICDMInstanceHandle inInstance)
+ {
+ for (QT3DSI32 idx = 0, end = inContext.m_AssetGraph.GetChildCount(inInstance); idx < end;
+ ++idx) {
+ UICDM::CUICDMInstanceHandle theChild = inContext.m_AssetGraph.GetChild(inInstance, idx);
+ inContext.GetOrCreateTranslator(theChild, m_InstanceHandle);
+ RecurseAndCreateTranslators(inContext, theChild);
+ }
+ }
+ void PushTranslation(STranslation &inContext) override
+ {
+ STranslatorUICDMParser theParser(inContext, GetInstanceHandle());
+ Option<SObjectRefType> theData = theParser.GetPropertyValue<SObjectRefType>(
+ inContext.m_ObjectDefinitions.m_Alias.m_ReferencedNode);
+ m_ReferencedInstance = CUICDMInstanceHandle();
+ m_ReferenceTree = nullptr;
+ ((SNode *)m_GraphObject)->m_Flags.SetDirty(true);
+ if (theData.hasValue()) {
+ m_ReferencedInstance =
+ inContext.m_Reader.GetInstanceForObjectRef(GetInstanceHandle(), *theData);
+ if (inContext.m_Reader.IsInstance(m_ReferencedInstance)) {
+ m_ReferenceTree =
+ inContext.GetOrCreateTranslator(m_ReferencedInstance, m_InstanceHandle);
+ if (m_ReferenceTree
+ && !GraphObjectTypes::IsNodeType(m_ReferenceTree->GetGraphObject().m_Type)) {
+ QT3DS_ASSERT(false);
+ m_ReferenceTree = nullptr;
+ m_ReferencedInstance = CUICDMInstanceHandle();
+ } else {
+ RecurseAndCreateTranslators(inContext, m_ReferencedInstance);
+ }
+ }
+ }
+ }
+
+ void AfterRenderGraphIsBuilt(STranslation &inContext) override
+ {
+ SNode &theItem = static_cast<SNode &>(GetGraphObject());
+ STranslatorUICDMParser theParser(inContext, m_InstanceHandle);
+ ITERATE_UIC_RENDER_NODE_PROPERTIES
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Node.m_BoneId,
+ theItem.m_SkeletonId);
+ bool ignoresParent = false;
+ if (theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Node.m_IgnoresParent,
+ ignoresParent))
+ theItem.m_Flags.SetIgnoreParentTransform(ignoresParent);
+ theItem.m_Flags.SetDirty(true);
+ }
+ void AppendChild(SGraphObject &inObject) override
+ {
+ if (m_ReferenceTree)
+ m_ReferenceTree->AppendChild(inObject);
+ }
+ void ClearChildren() override
+ {
+ if (m_ReferenceTree)
+ m_ReferenceTree->ClearChildren();
+ }
+ void SetActive(bool inActive) override
+ {
+ SNode &theItem = static_cast<SNode &>(GetGraphObject());
+ theItem.m_Flags.SetActive(inActive);
+ }
+ SGraphObject &GetGraphObject() override
+ {
+ if (m_ReferenceTree)
+ return *m_ReferenceTree->m_GraphObject;
+ return *m_GraphObject;
+ }
+ UICDM::CUICDMInstanceHandle GetSceneGraphInstanceHandle() override
+ {
+ if (m_ReferencedInstance.Valid())
+ return m_ReferencedInstance;
+ return m_InstanceHandle;
+ }
+ CUICDMInstanceHandle GetInstanceHandle() override { return m_InstanceHandle; }
+
+ SGraphObject &GetNonAliasedGraphObject() override { return *m_GraphObject; }
+};
+}
+
+void SGraphObjectTranslator::PushTranslation(STranslation &inTranslatorContext)
+{
+ Q3DStudio::CString theId = inTranslatorContext.m_Reader.GetFileId(GetInstanceHandle());
+ if (theId.size())
+ GetGraphObject().m_Id =
+ inTranslatorContext.m_UICContext.GetStringTable().RegisterStr(theId.c_str());
+}
+
+bool STranslation::IncludeNode(const SNode &inNode)
+{
+ SGraphObjectTranslator *theTranslator = inNode.m_UserData.DynamicCast<SGraphObjectTranslator>();
+ if (theTranslator
+ && m_Doc.GetDocumentReader().IsCurrentlyActive(theTranslator->GetInstanceHandle()))
+ return true;
+ return false;
+}
+
+void STranslation::ReleaseEffect(UICDM::CUICDMInstanceHandle inInstance)
+{
+ if (m_Reader.IsInstance(inInstance) == false)
+ return;
+
+ UICDM::ComposerObjectTypes::Enum theType = m_ObjectDefinitions.GetType(inInstance);
+ UICDM::CUICDMInstanceHandle theParentClass = m_Reader.GetFirstBaseClass(inInstance);
+
+ if (theType == NULL && theParentClass.Valid())
+ theType = m_ObjectDefinitions.GetType(theParentClass);
+
+ if (theType == UICDM::ComposerObjectTypes::Effect) {
+ IEffectSystem &theSystem = m_UICContext.GetEffectSystem();
+ if (theParentClass.Valid()) {
+ Q3DStudio::CString theInstanceName = m_Reader.GetName(theParentClass);
+ CRegisteredString theNameStr =
+ m_UICContext.GetStringTable().RegisterStr(theInstanceName);
+
+ if (theSystem.IsEffectRegistered(theNameStr)) {
+ TInstanceToTranslatorMap::iterator theTranslatorList =
+ m_TranslatorMap.find(inInstance);
+ if (theTranslatorList != m_TranslatorMap.end())
+ m_TranslatorMap.erase(theTranslatorList);
+ theSystem.SetEffectRequiresCompilation(theNameStr, true);
+ }
+ }
+ }
+}
+
+SGraphObjectTranslator *STranslation::CreateTranslator(UICDM::CUICDMInstanceHandle inInstance)
+{
+ SGraphObjectTranslator *theNewTranslator = nullptr;
+ UICDM::ComposerObjectTypes::Enum theType = m_ObjectDefinitions.GetType(inInstance);
+ UICDM::CUICDMInstanceHandle theParentClass = m_Reader.GetFirstBaseClass(inInstance);
+ if (theType == NULL && theParentClass.Valid())
+ theType = m_ObjectDefinitions.GetType(theParentClass);
+
+ // For the subset of possible instances, pick out the valid translators.
+ switch (theType) {
+ case UICDM::ComposerObjectTypes::Group:
+ case UICDM::ComposerObjectTypes::Component:
+ case UICDM::ComposerObjectTypes::Node:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SNodeTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Scene:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SSceneTranslator)(inInstance, m_Allocator);
+ m_Scene = static_cast<SScene *>(&theNewTranslator->GetGraphObject());
+ m_Scene->m_Presentation = &m_Presentation;
+ break;
+ case UICDM::ComposerObjectTypes::Layer:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SLayerTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Light:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SLightTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Camera:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SCameraTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Model:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SModelTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Image:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SImageTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Text:
+ theNewTranslator = QT3DS_NEW(m_Allocator, STextTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Material:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SDefaultMaterialTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::ReferencedMaterial:
+ theNewTranslator =
+ QT3DS_NEW(m_Allocator, SReferencedMaterialTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Alias:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SAliasTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Path:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SPathTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::SubPath:
+ theNewTranslator = QT3DS_NEW(m_Allocator, SPathSubPathTranslator)(inInstance, m_Allocator);
+ break;
+ case UICDM::ComposerObjectTypes::Effect: {
+ IEffectSystem &theSystem = m_UICContext.GetEffectSystem();
+ if (theParentClass.Valid()) {
+ Q3DStudio::CString theInstanceName = m_Reader.GetName(theParentClass);
+ CRegisteredString theNameStr =
+ m_UICContext.GetStringTable().RegisterStr(theInstanceName);
+
+ if (theSystem.IsEffectRegistered(theNameStr)
+ && theSystem.DoesEffectRequireCompilation(theNameStr)) {
+ theSystem.UnregisterEffect(theNameStr);
+ }
+
+ if (!theSystem.IsEffectRegistered(theNameStr)) {
+ // We assume the effect has already been registered and such.
+ UICDM::IMetaData &theMetaData(*m_StudioSystem.GetActionMetaData());
+ Q3DStudio::CString theInstancePath = m_Reader.GetSourcePath(theParentClass);
+ Option<UICDM::SMetaDataEffect> theMetaEffect =
+ theMetaData.GetEffectBySourcePath(
+ m_UICContext.GetStringTable().GetNarrowStr(theInstancePath));
+ if (theMetaEffect.hasValue()) {
+ uic::render::IUIPLoader::CreateEffectClassFromMetaEffect(
+ theNameStr, m_UICContext.GetFoundation(), theSystem, theMetaEffect,
+ m_UICContext.GetStringTable());
+ theSystem.SetEffectRequiresCompilation(theNameStr, true);
+ }
+ }
+
+ if (theSystem.IsEffectRegistered(theNameStr)) {
+ theNewTranslator = QT3DS_NEW(m_Allocator, SEffectTranslator)(
+ inInstance, m_Allocator,
+ *theSystem.CreateEffectInstance(theNameStr, m_Allocator));
+ }
+ }
+ } break;
+ case UICDM::ComposerObjectTypes::CustomMaterial: {
+ ICustomMaterialSystem &theSystem = m_UICContext.GetCustomMaterialSystem();
+ if (theParentClass.Valid()) {
+ Q3DStudio::CString theInstanceName = m_Reader.GetName(theParentClass);
+ CRegisteredString theNameStr =
+ m_UICContext.GetStringTable().RegisterStr(theInstanceName);
+ if (!theSystem.IsMaterialRegistered(theNameStr)) {
+ // We assume the effect has already been registered and such.
+ UICDM::IMetaData &theMetaData(*m_StudioSystem.GetActionMetaData());
+ Q3DStudio::CString theInstancePath = m_Reader.GetSourcePath(theParentClass);
+ Option<UICDM::SMetaDataCustomMaterial> theMaterialData =
+ theMetaData.GetMaterialBySourcePath(
+ m_UICContext.GetStringTable().GetNarrowStr(theInstancePath));
+ if (theMaterialData.hasValue()) {
+ uic::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ theNameStr, m_UICContext.GetFoundation(), theSystem, theMaterialData,
+ m_UICContext.GetStringTable());
+ }
+ }
+ if (theSystem.IsMaterialRegistered(theNameStr)) {
+ theNewTranslator = QT3DS_NEW(m_Allocator, SCustomMaterialTranslator)(
+ inInstance, m_Allocator,
+ *theSystem.CreateCustomMaterial(theNameStr, m_Allocator));
+ static_cast<SCustomMaterialTranslator *>(theNewTranslator)->m_MaterialSystem =
+ &theSystem;
+ }
+ }
+ } break;
+ case UICDM::ComposerObjectTypes::RenderPlugin: {
+ theNewTranslator = QT3DS_NEW(m_Allocator, SRenderPluginTranslator)(inInstance, m_Allocator);
+ } break;
+ }
+ return theNewTranslator;
+}
+
+bool CompareTranslator(const STranslation::THandleTranslatorPair &first,
+ const STranslation::THandleTranslatorPair &second)
+{
+ return first.first == second.first;
+}
+
+struct STranslatorPredicate
+{
+ CUICDMInstanceHandle m_Instance;
+ STranslatorPredicate(CUICDMInstanceHandle &ins)
+ : m_Instance(ins)
+ {
+ }
+ bool operator()(const STranslation::THandleTranslatorPair &first) const
+ {
+ return first.first == m_Instance;
+ }
+};
+
+Option<STranslation::THandleTranslatorPair>
+FindTranslator(STranslation::THandleTranslatorPairList &inList,
+ CUICDMInstanceHandle inInstance = CUICDMInstanceHandle())
+{
+ STranslation::THandleTranslatorPairList::iterator iter =
+ eastl::find_if(inList.begin(), inList.end(), STranslatorPredicate(inInstance));
+ if (iter != inList.end())
+ return *iter;
+ return Empty();
+}
+
+SGraphObjectTranslator *STranslation::GetOrCreateTranslator(UICDM::CUICDMInstanceHandle inInstance)
+{
+ return GetOrCreateTranslator(inInstance, CUICDMInstanceHandle());
+}
+
+SGraphObjectTranslator *
+STranslation::GetOrCreateTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inAliasInstance)
+{
+ TInstanceToTranslatorMap::iterator theTranslatorList =
+ m_TranslatorMap.insert(eastl::make_pair(inInstance, THandleTranslatorPairList())).first;
+ THandleTranslatorPairList &theList = theTranslatorList->second;
+ Option<STranslation::THandleTranslatorPair> theExistingTranslator =
+ FindTranslator(theList, inAliasInstance);
+
+ if (theExistingTranslator.hasValue()) {
+ return theExistingTranslator->second;
+ }
+ if (m_Reader.IsInstance(inInstance) == false)
+ return nullptr;
+
+ SGraphObjectTranslator *theNewTranslator = CreateTranslator(inInstance);
+ if (theNewTranslator != nullptr) {
+ theNewTranslator->m_AliasInstanceHandle = inAliasInstance;
+ m_DirtySet.insert(*theNewTranslator);
+ theList.push_back(THandleTranslatorPair(inAliasInstance, theNewTranslator));
+ }
+
+ return theNewTranslator;
+}
+
+STranslation::THandleTranslatorPairList &
+STranslation::GetTranslatorsForInstance(UICDM::CUICDMInstanceHandle inInstance)
+{
+ return m_TranslatorMap.insert(eastl::make_pair(inInstance, THandleTranslatorPairList()))
+ .first->second;
+}
+
+UICDM::CUICDMInstanceHandle STranslation::GetAnchorPoint(QT3DSU32 inAnchorIndex)
+{
+ SGraphObjectTranslator *thePathTranslator =
+ static_cast<SGraphObjectTranslator *>(m_PathWidget->GetNode().m_UserData.m_UserData);
+ if (thePathTranslator == nullptr)
+ return UICDM::CUICDMInstanceHandle();
+ UICDM::CUICDMInstanceHandle thePathHandle = thePathTranslator->GetInstanceHandle();
+ QT3DSU32 theAnchorIndex = 0;
+ for (QT3DSI32 idx = 0, end = m_AssetGraph.GetChildCount(thePathHandle); idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theChildInstance = m_AssetGraph.GetChild(thePathHandle, idx);
+ if (m_Doc.GetDocumentReader().GetObjectTypeName(theChildInstance) == L"SubPath") {
+ QT3DSI32 numAnchors = m_AssetGraph.GetChildCount(theChildInstance);
+ QT3DSU32 endIndex = theAnchorIndex + (QT3DSU32)numAnchors;
+ if (endIndex > inAnchorIndex) {
+ return m_AssetGraph.GetChild(theChildInstance, inAnchorIndex - theAnchorIndex);
+ } else
+ theAnchorIndex = endIndex;
+ }
+ }
+ return UICDM::CUICDMInstanceHandle();
+}
+
+UICDM::CUICDMInstanceHandle STranslation::GetAnchorPoint(SPathPick &inPick)
+{
+ return GetAnchorPoint(inPick.m_AnchorIndex);
+}
+
+namespace uic {
+namespace studio {
+ struct SEditCameraLayerTranslator : public SLayerTranslator
+ {
+ SEditCameraLayerTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ qt3ds::NVAllocatorCallback &inAlloc)
+ : SLayerTranslator(inInstance, inAlloc)
+ {
+ }
+ void PushTranslation(STranslation &) override
+ {
+ SLayer &theItem = static_cast<SLayer &>(GetGraphObject());
+ theItem.m_Flags.SetActive(true);
+ }
+ void AppendChild(SGraphObject &inChild) override
+ {
+ if (GraphObjectTypes::IsNodeType(inChild.m_Type)) {
+ SNodeTranslator::AppendChild(inChild);
+ }
+ }
+ };
+}
+}
+
+STranslation::STranslation(IStudioRenderer &inRenderer, IUICRenderContext &inContext)
+ : m_Renderer(inRenderer)
+ , m_UICContext(inContext)
+ , m_Doc(*g_StudioApp.GetCore()->GetDoc())
+ , m_Reader(m_Doc.GetDocumentReader())
+ , m_ObjectDefinitions(
+ m_Doc.GetStudioSystem()->GetClientDataModelBridge()->GetObjectDefinitions())
+ , m_StudioSystem(*m_Doc.GetStudioSystem())
+ , m_FullSystem(*m_Doc.GetStudioSystem()->GetFullSystem())
+ , m_AssetGraph(*m_Doc.GetAssetGraph())
+ , m_Allocator(inContext.GetRenderContext().GetFoundation())
+ , m_TranslatorMap(inContext.GetAllocator(), "STranslation::m_TranslatorMap")
+ , m_DirtySet(inContext.GetAllocator(), "STranslation::m_DirtySet")
+ , m_Scene(nullptr)
+ , m_SignalConnections(inContext.GetAllocator(), "STranslation::m_SignalConnections")
+ , m_ComponentSecondsDepth(0)
+ , m_KeyRepeat(0)
+ , m_EditCameraEnabled(false)
+ , m_EditLightEnabled(false)
+ , m_Viewport(0, 0)
+ , m_EditCameraLayerTranslator(nullptr)
+ , m_PixelBuffer(inContext.GetAllocator(), "STranslation::m_PixelBuffer")
+ , m_GuideAllocator(inContext.GetAllocator(), "STranslation::m_GuideAllocator")
+{
+ m_EditCamera.m_Flags.SetActive(true);
+ m_EditLight.m_Flags.SetActive(true);
+ UICDM::CUICDMInstanceHandle theScene = m_AssetGraph.GetRoot(0);
+ m_GraphIterator.ClearResults();
+ m_AssetGraph.GetDepthFirst(m_GraphIterator, theScene);
+ for (; !m_GraphIterator.IsDone(); ++m_GraphIterator) {
+ UICDM::CUICDMInstanceHandle theInstance(m_GraphIterator.GetCurrent());
+ GetOrCreateTranslator(theInstance);
+ }
+ UICDM::IStudioFullSystemSignalProvider *theProvider = m_FullSystem.GetSignalProvider();
+ m_SignalConnections.push_back(
+ theProvider->ConnectInstanceCreated(boost::bind(&STranslation::MarkDirty, this, _1)));
+ m_SignalConnections.push_back(theProvider->ConnectInstanceDeleted(
+ boost::bind(&STranslation::ReleaseTranslation, this, _1)));
+ m_SignalConnections.push_back(
+ theProvider->ConnectInstancePropertyValue(boost::bind(&STranslation::MarkDirty, this, _1)));
+ m_SignalConnections.push_back(m_AssetGraph.ConnectChildAdded(
+ boost::bind(&STranslation::MarkGraphInstanceDirty, this, _1, _2)));
+ m_SignalConnections.push_back(m_AssetGraph.ConnectChildMoved(
+ boost::bind(&STranslation::MarkGraphInstanceDirty, this, _1, _2)));
+ m_SignalConnections.push_back(m_AssetGraph.ConnectChildRemoved(
+ boost::bind(&STranslation::MarkGraphInstanceDirty, this, _1, _2)));
+ m_SignalConnections.push_back(theProvider->ConnectBeginComponentSeconds(
+ boost::bind(&STranslation::MarkBeginComponentSeconds, this, _1)));
+ m_SignalConnections.push_back(theProvider->ConnectComponentSeconds(
+ boost::bind(&STranslation::MarkComponentSeconds, this, _1)));
+
+ ::CColor color = CStudioPreferences::GetRulerBackgroundColor(); // Rectangles under tick marks
+ m_rectColor = QT3DSVec4(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f,
+ 1.f);
+ color = CStudioPreferences::GetRulerTickColor(); // Tick marks
+ m_lineColor = QT3DSVec4(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f,
+ 1.f);
+ color = CStudioPreferences::GetGuideColor();
+ m_guideColor = QT3DSVec4(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f,
+ 1.f);
+ color = CStudioPreferences::GetGuideSelectedColor();
+ m_selectedGuideColor = QT3DSVec4(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f,
+ 1.f);
+ color = CStudioPreferences::GetGuideFillColor(); // Not sure what this is used for
+ m_guideFillColor = QT3DSVec4(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f,
+ 1.f);
+ color = CStudioPreferences::GetGuideFillSelectedColor(); // Not sure what this is used for
+ m_selectedGuideFillColor = QT3DSVec4(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f,
+ 1.f);
+}
+
+void STranslation::BuildRenderGraph(SGraphObjectTranslator &inParent,
+ CUICDMInstanceHandle inAliasHandle)
+{
+ SGraphObjectTranslator &theParentTranslator(inParent);
+ theParentTranslator.ClearChildren();
+ if (m_EditCameraEnabled
+ && theParentTranslator.GetGraphObject().m_Type == GraphObjectTypes::Layer) {
+ theParentTranslator.AppendChild(m_EditCamera);
+ if (m_EditLightEnabled) {
+ m_EditLight.m_Parent = &m_EditCamera;
+ m_EditCamera.m_FirstChild = &m_EditLight;
+ } else {
+ m_EditCamera.m_FirstChild = nullptr;
+ m_EditLight.m_Parent = nullptr;
+ }
+ }
+ // Alias handles propagate down the scene graph.
+ if (inParent.GetInstanceHandle() != inParent.GetSceneGraphInstanceHandle())
+ inAliasHandle = inParent.GetInstanceHandle();
+ for (long idx = 0, end = m_AssetGraph.GetChildCount(inParent.GetSceneGraphInstanceHandle());
+ idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theChild(
+ m_AssetGraph.GetChild(inParent.GetSceneGraphInstanceHandle(), idx));
+ SGraphObjectTranslator *theTranslator = GetOrCreateTranslator(theChild, inAliasHandle);
+ if (theTranslator == nullptr)
+ continue;
+
+ // We we have edit cameras active, we only render the active layer and we remove any cameras
+ // in the active layer. Furthermore if our edit light is active, then we also remove any
+ // active lights in the layer.
+ if (m_EditCameraEnabled) {
+ if (theTranslator->GetGraphObject().m_Type == GraphObjectTypes::Layer) {
+ if (theChild == m_Doc.GetActiveLayer()) {
+ if (m_EditCameraLayerTranslator == nullptr)
+ m_EditCameraLayerTranslator =
+ QT3DS_NEW(m_Allocator, SEditCameraLayerTranslator)(theChild, m_Allocator);
+ else
+ m_EditCameraLayerTranslator->GetInstanceHandle() = theChild;
+ theTranslator = m_EditCameraLayerTranslator;
+ theParentTranslator.AppendChild(theTranslator->GetGraphObject());
+ BuildRenderGraph(*m_EditCameraLayerTranslator);
+ }
+ } else {
+ theParentTranslator.AppendChild(theTranslator->GetGraphObject());
+ BuildRenderGraph(theChild, inAliasHandle);
+
+ if (theTranslator->GetGraphObject().m_Type == GraphObjectTypes::Effect)
+ theTranslator->SetActive(false);
+ else if (theTranslator->GetGraphObject().m_Type == GraphObjectTypes::Camera)
+ theTranslator->SetActive(false);
+ else if (theTranslator->GetGraphObject().m_Type == GraphObjectTypes::Light
+ && m_EditLightEnabled == true)
+ theTranslator->SetActive(false);
+ else
+ theTranslator->SetActive(m_Reader.IsCurrentlyActive(theChild));
+ }
+ } else // Else build the graph and it will be an exact copy of the asset graph.
+ {
+ theParentTranslator.AppendChild(theTranslator->GetGraphObject());
+ if (m_Reader.IsCurrentlyActive(theChild)) {
+ BuildRenderGraph(theChild, inAliasHandle);
+ theTranslator->SetActive(true);
+ } else {
+ theTranslator->SetActive(false);
+ DeactivateScan(*theTranslator, inAliasHandle);
+ }
+ }
+ }
+ if (GraphObjectTypes::Layer == theParentTranslator.GetGraphObject().m_Type)
+ m_UICContext.GetRenderer().ChildrenUpdated(
+ static_cast<SLayer &>(theParentTranslator.GetGraphObject()));
+
+ // Allow certain nodes to override their children.
+ theParentTranslator.AfterRenderGraphIsBuilt(*this);
+}
+
+void STranslation::DeactivateScan(SGraphObjectTranslator &inParent,
+ CUICDMInstanceHandle inAliasHandle)
+{
+ SGraphObjectTranslator &theParentTranslator(inParent);
+ // Alias handles propagate down the scene graph.
+ if (inParent.GetInstanceHandle() != inParent.GetSceneGraphInstanceHandle())
+ inAliasHandle = inParent.GetInstanceHandle();
+ for (long idx = 0, end = m_AssetGraph.GetChildCount(inParent.GetSceneGraphInstanceHandle());
+ idx < end; ++idx) {
+ UICDM::CUICDMInstanceHandle theChild(
+ m_AssetGraph.GetChild(inParent.GetSceneGraphInstanceHandle(), idx));
+ SGraphObjectTranslator *theTranslator = GetOrCreateTranslator(theChild, inAliasHandle);
+ if (theTranslator == nullptr)
+ continue;
+ theTranslator->SetActive(false);
+ DeactivateScan(*theTranslator, inAliasHandle);
+ }
+}
+
+// We build the render graph every time we render. This may seem wasteful
+void STranslation::BuildRenderGraph(UICDM::CUICDMInstanceHandle inParent,
+ CUICDMInstanceHandle inAliasHandle)
+{
+ SGraphObjectTranslator *theParentTranslator = GetOrCreateTranslator(inParent, inAliasHandle);
+ if (theParentTranslator == nullptr)
+ return;
+ if (m_Reader.IsCurrentlyActive(inParent) == false) {
+ theParentTranslator->SetActive(false);
+ return;
+ }
+ BuildRenderGraph(*theParentTranslator, inAliasHandle);
+}
+
+void STranslation::ReleaseTranslation(Q3DStudio::TIdentifier inInstance)
+{
+ m_TranslatorMap.erase(inInstance);
+}
+
+void STranslation::MarkDirty(UICDM::CUICDMInstanceHandle inInstance)
+{
+ // Anchor points are not handled individually.
+ if (m_Reader.GetObjectTypeName(inInstance) == L"PathAnchorPoint")
+ inInstance = m_AssetGraph.GetParent(inInstance);
+ GetOrCreateTranslator(inInstance);
+
+ THandleTranslatorPairList &theTranslators = GetTranslatorsForInstance(inInstance);
+ for (size_t idx = 0, end = theTranslators.size(); idx < end; ++idx) {
+ m_DirtySet.insert(*theTranslators[(eastl::allocator::size_type)idx].second);
+ }
+ RequestRender();
+}
+
+void STranslation::PreRender()
+{
+ // Run through the entire asset graph and mark active or inactive if we have an
+ // associated render representation.
+ // If we cache all the components and some of their state then we don't have to do this
+ // but for now it is more stable to run through the graph.
+ // There is always one root, the scene.
+ TIdentifier theRoot = m_AssetGraph.GetRoot(0);
+ ClearDirtySet();
+ BuildRenderGraph(theRoot);
+ m_UICContext.SetScaleMode(uic::render::ScaleModes::ExactSize);
+ m_UICContext.SetMatteColor(QT3DSVec4(.13f, .13f, .13f, 1.0f));
+ QT3DSVec2 theViewportDims(GetViewportDimensions());
+ // Ensure the camera points where it should
+ if (m_EditCameraEnabled) {
+ m_EditCameraInfo.ApplyToCamera(m_EditCamera, GetViewportDimensions());
+ m_EditLight.MarkDirty(uic::render::NodeTransformDirtyFlag::TransformIsDirty);
+ }
+
+ if (m_Scene) {
+ CStudioProjectSettings *theSettings = m_Doc.GetCore()->GetStudioProjectSettings();
+ CPt thePresSize = theSettings->GetPresentationSize();
+ // The presentation sizes are used for when we have to render a layer offscreen. If their
+ // width and height
+ // isn't set, then they use the presentation dimensions.
+ m_Presentation.m_PresentationDimensions =
+ QT3DSVec2((QT3DSF32)thePresSize.x, (QT3DSF32)thePresSize.y);
+ QT3DSVec2 theViewportDims(GetViewportDimensions());
+ m_UICContext.SetWindowDimensions(
+ uic::render::SWindowDimensions((QT3DSU32)theViewportDims.x, (QT3DSU32)theViewportDims.y));
+ m_UICContext.SetPresentationDimensions(
+ uic::render::SWindowDimensions((QT3DSU32)m_Presentation.m_PresentationDimensions.x,
+ (QT3DSU32)m_Presentation.m_PresentationDimensions.y));
+
+ // set if we draw geometry in wireframe mode
+ m_UICContext.SetWireframeMode(CStudioPreferences::IsWireframeModeOn());
+
+ if (m_EditCameraEnabled) {
+ m_Presentation.m_PresentationDimensions = theViewportDims;
+ m_UICContext.SetPresentationDimensions(
+ uic::render::SWindowDimensions((QT3DSU32)theViewportDims.x, (QT3DSU32)theViewportDims.y));
+ ::CColor theEditCameraBackground = CStudioPreferences::GetEditViewBackgroundColor();
+ m_UICContext.SetSceneColor(QT3DSVec4(theEditCameraBackground.GetRed() / 255.0f,
+ theEditCameraBackground.GetGreen() / 255.0f,
+ theEditCameraBackground.GetBlue() / 255.0f, 1.0f));
+ } else {
+
+ TIdentifier theRoot = m_AssetGraph.GetRoot(0);
+ SGraphObjectTranslator *theSceneTranslator = GetOrCreateTranslator(theRoot);
+ if (theSceneTranslator) {
+ SScene &theScene = static_cast<SScene &>(theSceneTranslator->GetGraphObject());
+ if (theScene.m_UseClearColor)
+ m_UICContext.SetSceneColor(QT3DSVec4(theScene.m_ClearColor, 1.0f));
+ else
+ m_UICContext.SetSceneColor(QT3DSVec4(QT3DSVec3(0.0f), 1.0f));
+ }
+ }
+ }
+ if (m_EditCameraEnabled == false && g_StudioApp.IsAuthorZoom()) {
+ if (m_Presentation.m_PresentationDimensions.x > theViewportDims.x
+ || m_Presentation.m_PresentationDimensions.y > theViewportDims.y) {
+ m_UICContext.SetScaleMode(uic::render::ScaleModes::FitSelected);
+ }
+ }
+}
+
+static void CreatePixelRect(STranslation &inTranslation, QT3DSF32 left, QT3DSF32 right, QT3DSF32 bottom,
+ QT3DSF32 top, QT3DSVec4 color)
+{
+ SPGRect *theRect = QT3DS_NEW(inTranslation.m_GuideAllocator, SPGRect)();
+ theRect->m_Left = left;
+ theRect->m_Right = right;
+ theRect->m_Top = top;
+ theRect->m_Bottom = bottom;
+ theRect->m_FillColor = color;
+ inTranslation.m_GuideContainer.push_back(theRect);
+}
+
+static void CreatePixelVertLine(STranslation &inTranslation, QT3DSF32 inXPos, QT3DSF32 inBottom,
+ QT3DSF32 inTop, QT3DSVec4 color)
+{
+ SPGVertLine *theLine = QT3DS_NEW(inTranslation.m_GuideAllocator, SPGVertLine)();
+ theLine->m_X = inXPos;
+ theLine->m_Bottom = inBottom;
+ theLine->m_Top = inTop;
+ theLine->m_LineColor = color;
+ inTranslation.m_GuideContainer.push_back(theLine);
+}
+
+static void CreatePixelHorzLine(STranslation &inTranslation, QT3DSF32 inYPos, QT3DSF32 inLeft,
+ QT3DSF32 inRight, QT3DSVec4 color)
+{
+ SPGHorzLine *theLine = QT3DS_NEW(inTranslation.m_GuideAllocator, SPGHorzLine)();
+ theLine->m_Y = inYPos;
+ theLine->m_Left = inLeft;
+ theLine->m_Right = inRight;
+ theLine->m_LineColor = color;
+ inTranslation.m_GuideContainer.push_back(theLine);
+}
+
+static void CreateTopBottomTickMarks(STranslation &inTranslation, QT3DSF32 posX, QT3DSF32 innerBottom,
+ QT3DSF32 innerTop, QT3DSF32 outerBottom, QT3DSF32 outerTop,
+ QT3DSF32 lineHeight, QT3DSVec4 lineColor)
+{
+ CreatePixelVertLine(inTranslation, posX, innerBottom - lineHeight, innerBottom, lineColor);
+ CreatePixelVertLine(inTranslation, posX, innerTop, innerTop + lineHeight, lineColor);
+}
+
+static void DrawTickMarksOnHorizontalRects(STranslation &inTranslation, QT3DSF32 innerLeft,
+ QT3DSF32 innerRight, QT3DSF32 innerBottom, QT3DSF32 innerTop,
+ QT3DSF32 outerBottom, QT3DSF32 outerTop, QT3DSVec4 lineColor)
+{
+ QT3DSF32 centerPosX = floor(innerLeft + (innerRight - innerLeft) / 2.0f + .5f);
+ CreateTopBottomTickMarks(inTranslation, centerPosX, innerBottom, innerTop, outerBottom,
+ outerTop, 15, lineColor);
+ for (QT3DSU32 incrementor = 10;
+ (centerPosX + incrementor) < innerRight && (centerPosX - incrementor) > innerLeft;
+ incrementor += 10) {
+ QT3DSF32 rightEdge = centerPosX + incrementor;
+ QT3DSF32 leftEdge = centerPosX - incrementor;
+ QT3DSF32 lineHeight = 0;
+ if (incrementor % 100 == 0)
+ lineHeight = 11;
+ else if (incrementor % 20)
+ lineHeight = 4;
+ else
+ lineHeight = 2;
+
+ if (rightEdge < innerRight)
+ CreateTopBottomTickMarks(inTranslation, rightEdge, innerBottom, innerTop, outerBottom,
+ outerTop, lineHeight, lineColor);
+ if (leftEdge > innerLeft)
+ CreateTopBottomTickMarks(inTranslation, leftEdge, innerBottom, innerTop, outerBottom,
+ outerTop, lineHeight, lineColor);
+ }
+}
+
+static void CreateLeftRightTickMarks(STranslation &inTranslation, QT3DSF32 inYPos, QT3DSF32 innerLeft,
+ QT3DSF32 innerRight, QT3DSF32 outerLeft, QT3DSF32 outerRight,
+ QT3DSF32 lineLength, QT3DSVec4 lineColor)
+{
+ CreatePixelHorzLine(inTranslation, inYPos, innerLeft - lineLength, innerLeft, lineColor);
+ CreatePixelHorzLine(inTranslation, inYPos, innerRight, innerRight + lineLength, lineColor);
+}
+
+static void DrawTickMarksOnVerticalRects(STranslation &inTranslation, QT3DSF32 innerLeft,
+ QT3DSF32 innerRight, QT3DSF32 innerBottom, QT3DSF32 innerTop,
+ QT3DSF32 outerLeft, QT3DSF32 outerRight, QT3DSVec4 lineColor)
+{
+ QT3DSF32 centerPosY = floor(innerBottom + (innerTop - innerBottom) / 2.0f + .5f);
+ CreateLeftRightTickMarks(inTranslation, centerPosY, innerLeft, innerRight, outerLeft,
+ outerRight, 15, lineColor);
+ for (QT3DSU32 incrementor = 10;
+ (centerPosY + incrementor) < innerTop && (centerPosY - incrementor) > innerBottom;
+ incrementor += 10) {
+ QT3DSF32 topEdge = centerPosY + incrementor;
+ QT3DSF32 bottomEdge = centerPosY - incrementor;
+ QT3DSF32 lineHeight = 0;
+ if (incrementor % 100 == 0)
+ lineHeight = 11;
+ else if (incrementor % 20)
+ lineHeight = 4;
+ else
+ lineHeight = 2;
+
+ if (topEdge < innerTop)
+ CreateLeftRightTickMarks(inTranslation, topEdge, innerLeft, innerRight, outerLeft,
+ outerRight, lineHeight, lineColor);
+ if (bottomEdge > innerBottom)
+ CreateLeftRightTickMarks(inTranslation, bottomEdge, innerLeft, innerRight, outerLeft,
+ outerRight, lineHeight, lineColor);
+ }
+}
+
+class IGuideElementFactory
+{
+protected:
+ virtual ~IGuideElementFactory() {}
+public:
+ virtual void CreateLine(QT3DSF32 inPos) = 0;
+ virtual void CreateRect(QT3DSF32 inPosMin, QT3DSF32 inPosMax) = 0;
+};
+
+static void CreateGuide(IGuideElementFactory &inFactory, QT3DSF32 inPos, QT3DSF32 inWidth)
+{
+ QT3DSF32 halfWidth = inWidth / 2.0f;
+ QT3DSF32 leftLine = floor(inPos + 1.0f - halfWidth);
+ inFactory.CreateLine(leftLine);
+ // Then we are done if not enough width
+ if (inWidth < 2.0f)
+ return;
+
+ QT3DSF32 rightLine = leftLine + inWidth - 1;
+ inFactory.CreateLine(rightLine);
+
+ if (inWidth < 3.0f)
+ return;
+ QT3DSF32 rectStart = leftLine + 1;
+ QT3DSF32 rectStop = rectStart + inWidth - 2.0f;
+ inFactory.CreateRect(rectStart, rectStop);
+}
+
+struct SHorizontalGuideFactory : public IGuideElementFactory
+{
+ STranslation &m_Translation;
+ QT3DSF32 m_Start;
+ QT3DSF32 m_Stop;
+ QT3DSVec4 m_LineColor;
+ QT3DSVec4 m_FillColor;
+ SHorizontalGuideFactory(STranslation &trans, QT3DSF32 start, QT3DSF32 stop, QT3DSVec4 lineColor,
+ QT3DSVec4 fillColor)
+ : m_Translation(trans)
+ , m_Start(start)
+ , m_Stop(stop)
+ , m_LineColor(lineColor)
+ , m_FillColor(fillColor)
+ {
+ }
+ void CreateLine(QT3DSF32 inPos) override
+ {
+ CreatePixelHorzLine(m_Translation, inPos, m_Start, m_Stop, m_LineColor);
+ }
+
+ void CreateRect(QT3DSF32 inPosMin, QT3DSF32 inPosMax) override
+ {
+ CreatePixelRect(m_Translation, m_Start, m_Stop, inPosMin, inPosMax, m_FillColor);
+ }
+};
+
+struct SVerticalGuideFactory : public IGuideElementFactory
+{
+ STranslation &m_Translation;
+ QT3DSF32 m_Start;
+ QT3DSF32 m_Stop;
+ QT3DSVec4 m_LineColor;
+ QT3DSVec4 m_FillColor;
+ SVerticalGuideFactory(STranslation &trans, QT3DSF32 start, QT3DSF32 stop, QT3DSVec4 lineColor,
+ QT3DSVec4 fillColor)
+ : m_Translation(trans)
+ , m_Start(start)
+ , m_Stop(stop)
+ , m_LineColor(lineColor)
+ , m_FillColor(fillColor)
+ {
+ }
+ void CreateLine(QT3DSF32 inPos) override
+ {
+ CreatePixelVertLine(m_Translation, inPos, m_Start, m_Stop, m_LineColor);
+ }
+
+ void CreateRect(QT3DSF32 inPosMin, QT3DSF32 inPosMax) override
+ {
+ CreatePixelRect(m_Translation, inPosMin, inPosMax, m_Start, m_Stop, m_FillColor);
+ }
+};
+
+void STranslation::Render(int inWidgetId, bool inDrawGuides)
+{
+ // For now, we just render.
+ // Next step will be to get the bounding boxes and such setup.
+ // but we will want a custom renderer to do that.
+ if (m_Scene) {
+ // Note that begin frame is called before we allocate the bounding box and axis widgets so
+ // that we can take advantage of the renderer's per-frame-allocator.
+ m_UICContext.BeginFrame();
+ // Render the bounding boxes and extra widgets.
+ // This is called *before* the render because these sort of appendages need to be added
+ // to the layer renderables.
+ UICDM::TInstanceHandleList theHandles = m_Doc.GetSelectedValue().GetSelectedInstances();
+
+ // Don't show the bounding box or pivot for the component we are *in* the component
+ SGraphObjectTranslator *theTranslator = nullptr;
+ long theToolMode = g_StudioApp.GetToolMode();
+ bool isEditCamera = m_EditCameraEnabled;
+ int theCameraToolMode = isEditCamera ? (theToolMode & (STUDIO_CAMERATOOL_MASK)) : 0;
+ long theModifiers = CHotKeys::GetCurrentKeyModifiers();
+ bool shouldDisplayWidget = false;
+ if (theCameraToolMode == 0) {
+ switch (theToolMode) {
+ default:
+ break;
+ case STUDIO_TOOLMODE_MOVE:
+ case STUDIO_TOOLMODE_ROTATE:
+ case STUDIO_TOOLMODE_SCALE:
+ shouldDisplayWidget = true;
+ break;
+ };
+ }
+
+ SDisableUseClearColor color(*this, isEditCamera);
+ bool selectedPath = false;
+
+ for (size_t selectedIdx = 0, selectedEnd = theHandles.size(); selectedIdx < selectedEnd;
+ ++selectedIdx) {
+ UICDM::CUICDMInstanceHandle theInstance = theHandles[selectedIdx];
+ if (theInstance
+ != m_Doc.GetDocumentReader().GetComponentForSlide(m_Doc.GetActiveSlide())) {
+ if (m_Doc.GetDocumentReader().GetObjectTypeName(theInstance)
+ == L"PathAnchorPoint") {
+ theInstance = m_AssetGraph.GetParent(m_AssetGraph.GetParent(theInstance));
+ shouldDisplayWidget = false;
+ }
+ theTranslator = GetOrCreateTranslator(theInstance);
+ // Get the tool mode right now.
+ if (theTranslator) {
+ GraphObjectTypes::Enum theType(theTranslator->GetGraphObject().m_Type);
+ if (CStudioPreferences::IsBoundingBoxesOn()) {
+ switch (theType) {
+ case GraphObjectTypes::Node:
+ DrawGroupBoundingBoxes(*theTranslator);
+ break;
+ case GraphObjectTypes::Text:
+ case GraphObjectTypes::Model:
+ case GraphObjectTypes::Layer:
+ case GraphObjectTypes::Light:
+ case GraphObjectTypes::Path:
+ DrawNonGroupBoundingBoxes(*theTranslator);
+ break;
+ }
+ }
+ // Don't draw the axis if there is a widget.
+ if (CStudioPreferences::ShouldDisplayPivotPoint()
+ && shouldDisplayWidget == false) {
+ switch (theTranslator->GetGraphObject().m_Type) {
+ case GraphObjectTypes::Node:
+ case GraphObjectTypes::Text:
+ case GraphObjectTypes::Model:
+ DrawAxis(*theTranslator);
+ break;
+ }
+ }
+ if (theType == GraphObjectTypes::Path && selectedPath == false) {
+ selectedPath = true;
+ if (!m_PathWidget)
+ m_PathWidget = uic::widgets::IPathWidget::CreatePathWidget(
+ m_UICContext.GetAllocator(), m_UICContext);
+ m_PathWidget->SetNode(
+ static_cast<SNode &>(theTranslator->GetGraphObject()));
+ m_UICContext.GetRenderer().AddRenderWidget(*m_PathWidget);
+ }
+ }
+ }
+ }
+
+ if (theHandles.size() > 1)
+ theTranslator = nullptr;
+
+ uic::widgets::IStudioWidget *theNextWidget(nullptr);
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetGraphObject().m_Type)
+ && theTranslator->GetGraphObject().m_Type != GraphObjectTypes::Layer) {
+
+ uic::render::SNode &theNode(
+ static_cast<uic::render::SNode &>(theTranslator->GetGraphObject()));
+ SCamera *theRenderCamera = m_UICContext.GetRenderer().GetCameraForNode(theNode);
+ bool isActiveCamera = theRenderCamera == (static_cast<SCamera *>(&theNode));
+ if (shouldDisplayWidget && isActiveCamera == false) {
+ switch (theToolMode) {
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ case STUDIO_TOOLMODE_MOVE:
+ // Render translation widget
+ if (!m_TranslationWidget)
+ m_TranslationWidget = uic::widgets::IStudioWidget::CreateTranslationWidget(
+ m_UICContext.GetAllocator());
+ theNextWidget = m_TranslationWidget.mPtr;
+ break;
+ case STUDIO_TOOLMODE_ROTATE:
+ if (!m_RotationWidget)
+ m_RotationWidget = uic::widgets::IStudioWidget::CreateRotationWidget(
+ m_UICContext.GetAllocator());
+ theNextWidget = m_RotationWidget.mPtr;
+ break;
+
+ case STUDIO_TOOLMODE_SCALE:
+ if (!m_ScaleWidget)
+ m_ScaleWidget = uic::widgets::IStudioWidget::CreateScaleWidget(
+ m_UICContext.GetAllocator());
+ theNextWidget = m_ScaleWidget.mPtr;
+ break;
+ }
+ if (theNextWidget) {
+ theNextWidget->SetNode(static_cast<SNode &>(theTranslator->GetGraphObject()));
+ m_UICContext.GetRenderer().AddRenderWidget(*theNextWidget);
+ }
+ }
+ }
+ if (m_LastRenderedWidget.mPtr && m_LastRenderedWidget.mPtr != theNextWidget)
+ ResetWidgets();
+
+ m_LastRenderedWidget = theNextWidget;
+ if (m_LastRenderedWidget) {
+ m_LastRenderedWidget->SetSubComponentId(inWidgetId);
+ switch (g_StudioApp.GetMinpulationMode()) {
+ case StudioManipulationModes::Local:
+ m_LastRenderedWidget->SetRenderWidgetMode(uic::render::RenderWidgetModes::Local);
+ break;
+ case StudioManipulationModes::Global:
+ m_LastRenderedWidget->SetRenderWidgetMode(uic::render::RenderWidgetModes::Global);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ m_Scene->PrepareForRender(GetViewportDimensions(), m_UICContext);
+
+ m_UICContext.RunRenderTasks();
+
+ m_Scene->Render(GetViewportDimensions(), m_UICContext, SScene::DoNotClear);
+
+ if (inDrawGuides && m_EditCameraEnabled == false && g_StudioApp.IsAuthorZoom() == false) {
+ m_GuideContainer.clear();
+ // Figure out the matte area.
+ NVRenderRect theContextViewport = m_UICContext.GetContextViewport();
+ NVRenderRect thePresentationViewport = m_UICContext.GetPresentationViewport();
+ m_UICContext.GetRenderContext().SetViewport(theContextViewport);
+ QT3DSI32 innerLeft = thePresentationViewport.m_X;
+ QT3DSI32 innerRight = thePresentationViewport.m_X + thePresentationViewport.m_Width;
+ QT3DSI32 innerBottom = thePresentationViewport.m_Y;
+ QT3DSI32 innerTop = thePresentationViewport.m_Y + thePresentationViewport.m_Height;
+
+ QT3DSI32 outerLeft = innerLeft - 16;
+ QT3DSI32 outerRight = innerRight + 16;
+ QT3DSI32 outerBottom = innerBottom - 16;
+ QT3DSI32 outerTop = innerTop + 16;
+ // Retain the rects for picking purposes.
+ m_InnerRect = SRulerRect(innerLeft, innerTop, innerRight, innerBottom);
+ m_OuterRect = SRulerRect(outerLeft, outerTop, outerRight, outerBottom);
+
+ // Draw tick marks around the presentation
+ CreatePixelRect(*this, (QT3DSF32)outerLeft, (QT3DSF32)innerLeft, (QT3DSF32)innerBottom,
+ (QT3DSF32)innerTop, m_rectColor);
+ CreatePixelRect(*this, (QT3DSF32)innerRight, (QT3DSF32)outerRight,
+ (QT3DSF32)innerBottom, (QT3DSF32)innerTop, m_rectColor);
+ CreatePixelRect(*this, (QT3DSF32)innerLeft, (QT3DSF32)innerRight, (QT3DSF32)outerBottom,
+ (QT3DSF32)innerBottom, m_rectColor);
+ CreatePixelRect(*this, (QT3DSF32)innerLeft, (QT3DSF32)innerRight, (QT3DSF32)innerTop,
+ (QT3DSF32)outerTop, m_rectColor);
+ DrawTickMarksOnHorizontalRects(*this, (QT3DSF32)innerLeft, (QT3DSF32)innerRight,
+ (QT3DSF32)innerBottom, (QT3DSF32)innerTop,
+ (QT3DSF32)outerBottom, (QT3DSF32)outerTop, m_lineColor);
+ DrawTickMarksOnVerticalRects(*this, (QT3DSF32)innerLeft, (QT3DSF32)innerRight,
+ (QT3DSF32)innerBottom, (QT3DSF32)innerTop,
+ (QT3DSF32)outerLeft, (QT3DSF32)outerRight, m_lineColor);
+ UICDM::TGuideHandleList theGuides = m_Doc.GetDocumentReader().GetGuides();
+ UICDM::CUICDMGuideHandle theSelectedGuide;
+ Q3DStudio::SSelectedValue theSelection = m_Doc.GetSelectedValue();
+ if (theSelection.getType() == Q3DStudio::SelectedValueTypes::Guide)
+ theSelectedGuide = theSelection.getData<UICDM::CUICDMGuideHandle>();
+
+ // Draw guides
+ for (size_t guideIdx = 0, guideEnd = theGuides.size(); guideIdx < guideEnd;
+ ++guideIdx) {
+ UICDM::SGuideInfo theInfo =
+ m_Doc.GetDocumentReader().GetGuideInfo(theGuides[guideIdx]);
+ bool isGuideSelected = theGuides[guideIdx] == theSelectedGuide;
+ QT3DSVec4 theColor = isGuideSelected ? m_selectedGuideColor : m_guideColor;
+ QT3DSVec4 theFillColor = isGuideSelected ? m_selectedGuideFillColor
+ : m_guideFillColor;
+ switch (theInfo.m_Direction) {
+ case UICDM::GuideDirections::Horizontal: {
+ SHorizontalGuideFactory theFactory(*this, (QT3DSF32)innerLeft, (QT3DSF32)innerRight,
+ theColor, theFillColor);
+ CreateGuide(theFactory, (QT3DSF32)m_InnerRect.m_Bottom + theInfo.m_Position,
+ (QT3DSF32)theInfo.m_Width);
+ } break;
+ case UICDM::GuideDirections::Vertical: {
+ SVerticalGuideFactory theFactory(*this, (QT3DSF32)innerBottom, (QT3DSF32)innerTop,
+ theColor, theFillColor);
+ CreateGuide(theFactory, (QT3DSF32)m_InnerRect.m_Left + theInfo.m_Position,
+ (QT3DSF32)theInfo.m_Width);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ m_UICContext.GetPixelGraphicsRenderer().Render(
+ qt3ds::foundation::toDataRef(m_GuideContainer.data(), m_GuideContainer.size()));
+
+ m_GuideContainer.clear();
+ m_GuideAllocator.reset();
+ }
+
+ m_UICContext.EndFrame();
+
+ if (m_ZoomRender.hasValue()) {
+ RenderZoomRender(*m_ZoomRender);
+ m_ZoomRender = Empty();
+ }
+
+ // Render the pick buffer, useful for debugging why a widget wasn't hit.
+ /*
+ if ( m_PickBuffer )
+ {
+ qt3ds::render::NVRenderContext& theRenderContext( m_UICContext.GetRenderContext() );
+ qt3ds::render::STextureDetails thePickDetails = m_PickBuffer->GetTextureDetails();
+ theRenderContext.SetViewport( qt3ds::render::NVRenderRect( 0, 0, thePickDetails.m_Width,
+ thePickDetails.m_Height ) );
+ uic::render::SCamera theCamera;
+ theCamera.MarkDirty( uic::render::NodeTransformDirtyFlag::TransformIsDirty );
+ theCamera.m_Flags.SetOrthographic( true );
+ QT3DSVec2 theDimensions( (QT3DSF32)thePickDetails.m_Width, (QT3DSF32)thePickDetails.m_Height );
+ theCamera.CalculateGlobalVariables( render::NVRenderRectF( 0, 0, theDimensions.x,
+ theDimensions.y ), theDimensions );
+ QT3DSMat44 theVP;
+ theCamera.CalculateViewProjectionMatrix( theVP );
+ theRenderContext.SetCullingEnabled( false );
+ theRenderContext.SetBlendingEnabled( false );
+ theRenderContext.SetDepthTestEnabled( false );
+ theRenderContext.SetDepthWriteEnabled( false );
+ m_UICContext.GetRenderer().RenderQuad( theDimensions, theVP, *m_PickBuffer );
+ }*/
+ }
+}
+
+void STranslation::ResetWidgets()
+{
+ if (m_ScaleWidget)
+ m_ScaleWidget->SetAxisScale(QT3DSVec3(1, 1, 1));
+ if (m_RotationWidget)
+ m_RotationWidget->ClearRotationEdges();
+ m_CumulativeRotation = 0.0f;
+}
+
+void STranslation::DoPrepareForDrag(SNode *inSelectedNode)
+{
+ if (inSelectedNode == nullptr)
+ return;
+
+ m_MouseDownNode = *inSelectedNode;
+ m_MouseDownParentGlobalTransformInverse = Empty();
+ m_MouseDownParentRotationInverse = Empty();
+ m_MouseDownGlobalRotation = Empty();
+ // Orphan this node manually since it is a straight copy
+ m_MouseDownNode.m_Parent = nullptr;
+ m_MouseDownNode.m_FirstChild = nullptr;
+ m_MouseDownNode.m_NextSibling = nullptr;
+ SCamera *theCamera = m_UICContext.GetRenderer().GetCameraForNode(*inSelectedNode);
+ m_CumulativeRotation = 0.0f;
+ if (theCamera == nullptr)
+ return;
+ m_MouseDownCamera = *theCamera;
+ m_LastPathDragValue = Empty();
+}
+
+void STranslation::EndDrag()
+{
+ ResetWidgets();
+}
+
+bool STranslation::IsPathWidgetActive()
+{
+ UICDM::TInstanceHandleList theHandles = m_Doc.GetSelectedValue().GetSelectedInstances();
+ for (size_t selectedIdx = 0, selectedEnd = theHandles.size(); selectedIdx < selectedEnd;
+ ++selectedIdx) {
+ UICDM::CUICDMInstanceHandle theInstance(theHandles[selectedIdx]);
+ if (m_Doc.GetDocumentReader().GetObjectTypeName(theInstance) == L"PathAnchorPoint")
+ theInstance = m_AssetGraph.GetParent(m_AssetGraph.GetParent(theInstance));
+ SGraphObjectTranslator *theTranslator = GetOrCreateTranslator(theInstance);
+ if (theTranslator && theTranslator->GetGraphObject().m_Type == GraphObjectTypes::Path)
+ return true;
+ }
+ return false;
+}
+
+inline uic::render::SLayer *GetLayerForNode(const uic::render::SNode &inNode)
+{
+ SNode *theNode;
+ // empty loop intentional
+ for (theNode = const_cast<SNode *>(&inNode);
+ theNode && theNode->m_Type != GraphObjectTypes::Layer; theNode = theNode->m_Parent) {
+ }
+ if (theNode && theNode->m_Type == GraphObjectTypes::Layer)
+ return static_cast<SLayer *>(theNode);
+ return nullptr;
+}
+
+void STranslation::RenderZoomRender(SZoomRender &inRender)
+{
+ SLayer *theLayer(inRender.m_Layer);
+ CPt thePoint(inRender.m_Point);
+ if (theLayer) {
+ uic::render::IUICRenderer &theRenderer(m_UICContext.GetRenderer());
+ Option<uic::render::SLayerPickSetup> thePickSetup(
+ theRenderer.GetLayerPickSetup(*theLayer, QT3DSVec2((QT3DSF32)thePoint.x, (QT3DSF32)thePoint.y),
+ uic::render::SWindowDimensions(16, 16)));
+ if (thePickSetup.hasValue()) {
+ qt3ds::render::NVRenderContext &theRenderContext(m_UICContext.GetRenderContext());
+ theRenderContext.SetViewport(qt3ds::render::NVRenderRect(0, 0, 100, 100));
+ theRenderContext.SetScissorRect(qt3ds::render::NVRenderRect(0, 0, 100, 100));
+ theRenderContext.SetDepthWriteEnabled(true);
+ theRenderContext.SetScissorTestEnabled(true);
+ theRenderContext.SetClearColor(QT3DSVec4(.2, .2, .2, 0));
+ theRenderContext.Clear(qt3ds::render::NVRenderClearFlags(
+ qt3ds::render::NVRenderClearValues::Color | qt3ds::render::NVRenderClearValues::Depth));
+ theRenderer.RunLayerRender(*theLayer, thePickSetup->m_ViewProjection);
+ theRenderContext.SetScissorTestEnabled(false);
+ }
+ }
+}
+
+void STranslation::DrawBoundingBox(SNode &inNode, QT3DSVec3 inColor)
+{
+ qt3ds::NVBounds3 theBounds = inNode.GetBounds(m_UICContext.GetBufferManager(),
+ m_UICContext.GetPathManager(), true, this);
+ uic::render::IRenderWidget &theBBoxWidget = uic::render::IRenderWidget::CreateBoundingBoxWidget(
+ inNode, theBounds, inColor, m_UICContext.GetRenderer().GetPerFrameAllocator());
+ m_UICContext.GetRenderer().AddRenderWidget(theBBoxWidget);
+}
+
+void STranslation::DrawLightBoundingBox(SNode &inNode, QT3DSVec3 inColor)
+{
+ SLight *theLight = reinterpret_cast<SLight *>(&inNode);
+ if (theLight->m_LightType != uic::render::RenderLightTypes::Area) {
+ return;
+ }
+
+ qt3ds::NVBounds3 theBounds(
+ qt3ds::QT3DSVec3(-theLight->m_AreaWidth * 0.5f, -theLight->m_AreaHeight * 0.5f, 0.0f),
+ qt3ds::QT3DSVec3(theLight->m_AreaWidth * 0.5f, theLight->m_AreaHeight * 0.5f, 0.0f));
+ uic::render::IRenderWidget &theBBoxWidget = uic::render::IRenderWidget::CreateBoundingBoxWidget(
+ inNode, theBounds, inColor, m_UICContext.GetRenderer().GetPerFrameAllocator());
+ m_UICContext.GetRenderer().AddRenderWidget(theBBoxWidget);
+}
+
+void STranslation::DrawAxis(SGraphObjectTranslator &inTranslator)
+{
+ if (GraphObjectTypes::IsNodeType(inTranslator.GetGraphObject().m_Type)) {
+ uic::render::IRenderWidget &theAxisWidget = uic::render::IRenderWidget::CreateAxisWidget(
+ static_cast<SNode &>(inTranslator.GetGraphObject()),
+ m_UICContext.GetRenderer().GetPerFrameAllocator());
+ m_UICContext.GetRenderer().AddRenderWidget(theAxisWidget);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+}
+
+Option<QT3DSU32> STranslation::PickWidget(CPt inMouseCoords, TranslationSelectMode::Enum,
+ uic::widgets::IStudioWidgetBase &inWidget)
+{
+ SNode &theNode = inWidget.GetNode();
+ SGraphObjectTranslator *theWidgetTranslator =
+ theNode.m_UserData.DynamicCast<SGraphObjectTranslator>();
+ SLayer *theLayer = GetLayerForNode(theNode);
+ if (theLayer && theWidgetTranslator) {
+ Option<uic::render::SLayerPickSetup> thePickSetup(
+ m_UICContext.GetRenderer().GetLayerPickSetup(
+ *theLayer, QT3DSVec2((QT3DSF32)inMouseCoords.x, (QT3DSF32)inMouseCoords.y),
+ uic::render::SWindowDimensions(4, 4)));
+ if (thePickSetup.hasValue()) {
+ qt3ds::render::NVRenderContext &theContext(m_UICContext.GetRenderContext());
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderFrameBuffer *>
+ __currentrt(theContext, &qt3ds::render::NVRenderContext::GetRenderTarget,
+ &qt3ds::render::NVRenderContext::SetRenderTarget);
+ qt3ds::render::NVRenderFrameBuffer *theFBO =
+ m_UICContext.GetResourceManager().AllocateFrameBuffer();
+ const QT3DSU32 fboDims = 8;
+ if (!m_PickBuffer) {
+ m_PickBuffer = theContext.CreateTexture2D();
+ m_PickBuffer->SetTextureData(qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8>(), 0, fboDims,
+ fboDims,
+ qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8);
+ }
+ qt3ds::render::NVRenderRenderBuffer *theRenderBuffer =
+ m_UICContext.GetResourceManager().AllocateRenderBuffer(
+ fboDims, fboDims, qt3ds::render::NVRenderRenderBufferFormats::Depth16);
+ theFBO->Attach(qt3ds::render::NVRenderFrameBufferAttachments::Color0,
+ qt3ds::render::NVRenderTextureOrRenderBuffer(*m_PickBuffer));
+ theFBO->Attach(qt3ds::render::NVRenderFrameBufferAttachments::Depth,
+ qt3ds::render::NVRenderTextureOrRenderBuffer(*theRenderBuffer));
+ qt3ds::render::NVRenderRect theViewport(0, 0, fboDims, fboDims);
+ theContext.SetViewport(theViewport);
+ theContext.SetDepthWriteEnabled(true);
+ theContext.SetDepthTestEnabled(true);
+ theContext.SetScissorTestEnabled(false);
+ theContext.SetBlendingEnabled(false);
+ theContext.SetClearColor(QT3DSVec4(0, 0, 0, 0));
+ theContext.Clear(qt3ds::render::NVRenderClearFlags(
+ qt3ds::render::NVRenderClearValues::Color | qt3ds::render::NVRenderClearValues::Depth));
+ inWidget.RenderPick(thePickSetup->m_ProjectionPreMultiply, theContext,
+ uic::render::SWindowDimensions(4, 4));
+ // Now read the pixels back.
+ m_PixelBuffer.resize(fboDims * fboDims * 3);
+ theContext.ReadPixels(theViewport, qt3ds::render::NVRenderReadPixelFormats::RGB8,
+ m_PixelBuffer);
+ m_UICContext.GetResourceManager().Release(*theFBO);
+ m_UICContext.GetResourceManager().Release(*theRenderBuffer);
+ eastl::hash_map<QT3DSU32, QT3DSU32> tallies;
+ QT3DSU32 numPixels = fboDims * fboDims;
+ for (QT3DSU32 idx = 0; idx < numPixels; ++idx) {
+ qt3ds::QT3DSU16 theChannelAmount =
+ m_PixelBuffer[idx * 3] + (m_PixelBuffer[idx * 3 + 1] << 8);
+ if (theChannelAmount)
+ tallies.insert(eastl::make_pair(theChannelAmount, (QT3DSU32)0)).first->second += 1;
+ }
+ QT3DSU32 tallyMaxTally = 0;
+ QT3DSU32 tallyMaxIdx = 0;
+ for (eastl::hash_map<QT3DSU32, QT3DSU32>::iterator iter = tallies.begin(),
+ end = tallies.end();
+ iter != end; ++iter) {
+ if (iter->second > tallyMaxTally) {
+ tallyMaxTally = iter->second;
+ tallyMaxIdx = iter->first;
+ }
+ }
+ if (tallyMaxIdx > 0) {
+ return tallyMaxIdx;
+ }
+ }
+ }
+ return Empty();
+}
+
+SStudioPickValue STranslation::Pick(CPt inMouseCoords, TranslationSelectMode::Enum inSelectMode)
+{
+ bool requestRender = false;
+
+ if (m_Doc.GetDocumentReader().AreGuidesEditable()) {
+ UICDM::TGuideHandleList theGuides = m_Doc.GetDocumentReader().GetGuides();
+ CPt renderSpacePt(inMouseCoords.x - (long)m_InnerRect.m_Left,
+ (long)GetViewportDimensions().y - inMouseCoords.y
+ - (long)m_InnerRect.m_Bottom);
+ for (size_t guideIdx = 0, guideEnd = theGuides.size(); guideIdx < guideEnd; ++guideIdx) {
+ UICDM::SGuideInfo theGuideInfo =
+ m_Doc.GetDocumentReader().GetGuideInfo(theGuides[guideIdx]);
+ float width = (theGuideInfo.m_Width / 2.0f) + 2.0f;
+ switch (theGuideInfo.m_Direction) {
+ case UICDM::GuideDirections::Horizontal:
+ if (fabs((float)renderSpacePt.y - theGuideInfo.m_Position) <= width)
+ return theGuides[guideIdx];
+ break;
+ case UICDM::GuideDirections::Vertical:
+ if (fabs((float)renderSpacePt.x - theGuideInfo.m_Position) <= width)
+ return theGuides[guideIdx];
+ break;
+ }
+ }
+ }
+ if (IsPathWidgetActive()) {
+ Option<QT3DSU32> picked = PickWidget(inMouseCoords, inSelectMode, *m_PathWidget);
+ if (picked.hasValue()) {
+ RequestRender();
+ DoPrepareForDrag(&m_PathWidget->GetNode());
+ return m_PathWidget->PickIndexToPickValue(*picked);
+ }
+ }
+ // Pick against the widget first if possible.
+ if (m_LastRenderedWidget) {
+ Option<QT3DSU32> picked = PickWidget(inMouseCoords, inSelectMode, *m_LastRenderedWidget);
+ if (picked.hasValue()) {
+ RequestRender();
+ DoPrepareForDrag(&m_LastRenderedWidget->GetNode());
+ return m_LastRenderedWidget->PickIndexToPickValue(*picked);
+ }
+ }
+ if (m_Scene && m_Scene->m_FirstChild) {
+ uic::render::SUICRenderPickResult thePickResult =
+ m_UICContext.GetRenderer().Pick(*m_Scene->m_FirstChild, GetViewportDimensions(),
+ QT3DSVec2((QT3DSF32)inMouseCoords.x, (QT3DSF32)inMouseCoords.y));
+ if (thePickResult.m_HitObject) {
+ const SGraphObject &theObject = *thePickResult.m_HitObject;
+ if (theObject.m_Type == GraphObjectTypes::Model
+ || theObject.m_Type == GraphObjectTypes::Text
+ || theObject.m_Type == GraphObjectTypes::Path) {
+ const SNode &theTranslatorModel(static_cast<const SNode &>(theObject));
+ SGraphObjectTranslator *theTranslator =
+ theTranslatorModel.m_UserData.DynamicCast<SGraphObjectTranslator>();
+ const SNode *theModelPtr = &theTranslatorModel;
+ if (theTranslator->GetPossiblyAliasedInstanceHandle()
+ != theTranslator->GetInstanceHandle()) {
+ theTranslator =
+ GetOrCreateTranslator(theTranslator->GetPossiblyAliasedInstanceHandle());
+ theModelPtr =
+ static_cast<const SNode *>(&theTranslator->GetNonAliasedGraphObject());
+ }
+ CUICDMInstanceHandle theActiveComponent =
+ m_Reader.GetComponentForSlide(m_Doc.GetActiveSlide());
+ if (inSelectMode == TranslationSelectMode::Group) {
+ // Bounce up the hierarchy till one of two conditions are met
+ // the parent is a layer or the our component is the active component
+ // but the parent's is not.
+ while (theTranslator && GraphObjectTypes::IsNodeType(
+ theTranslator->GetGraphObject().m_Type)) {
+ SNode *myNode = static_cast<SNode *>(&theTranslator->GetGraphObject());
+ if (myNode->m_Parent == nullptr) {
+ theTranslator = nullptr;
+ break;
+ }
+ SNode *parentNode = myNode->m_Parent;
+ SGraphObjectTranslator *theParentTranslator =
+ parentNode->m_UserData.DynamicCast<SGraphObjectTranslator>();
+ CUICDMInstanceHandle myComponent =
+ m_Reader.GetAssociatedComponent(theTranslator->GetInstanceHandle());
+ CUICDMInstanceHandle myParentComponent = m_Reader.GetAssociatedComponent(
+ theParentTranslator->GetInstanceHandle());
+ if (parentNode->m_Type == GraphObjectTypes::Layer) {
+ if (myParentComponent != theActiveComponent)
+ theTranslator = nullptr;
+ break;
+ }
+ if (myComponent == theActiveComponent
+ && myParentComponent != theActiveComponent)
+ break;
+ theTranslator = theParentTranslator;
+ }
+ } else {
+ // Bounce up until we get into the active component and then stop.
+ while (inSelectMode == TranslationSelectMode::Single && theTranslator
+ && GraphObjectTypes::IsNodeType(theTranslator->GetGraphObject().m_Type)
+ && m_Reader.GetAssociatedComponent(theTranslator->GetInstanceHandle())
+ != theActiveComponent) {
+ SNode *theNode = static_cast<SNode *>(&theTranslator->GetGraphObject());
+ theNode = theNode->m_Parent;
+ if (theNode && theNode->m_Type != GraphObjectTypes::Layer)
+ theTranslator =
+ theNode->m_UserData.DynamicCast<SGraphObjectTranslator>();
+ else
+ theTranslator = nullptr;
+ }
+ }
+
+ if (theTranslator) {
+ QT3DS_ASSERT(GraphObjectTypes::IsNodeType(theTranslator->GetGraphObject().m_Type));
+ DoPrepareForDrag(static_cast<SNode *>(&theTranslator->GetGraphObject()));
+ return theTranslator->GetInstanceHandle();
+ }
+ }
+ }
+ if (requestRender)
+ RequestRender();
+ }
+ return SStudioPickValue();
+}
+
+qt3ds::foundation::Option<UICDM::SGuideInfo> STranslation::PickRulers(CPt inMouseCoords)
+{
+ CPt renderSpacePt(inMouseCoords.x, (long)GetViewportDimensions().y - inMouseCoords.y);
+ // If mouse is inside outer rect but outside inner rect.
+ if (m_OuterRect.Contains(renderSpacePt.x, renderSpacePt.y)
+ && !m_InnerRect.Contains(renderSpacePt.x, renderSpacePt.y)) {
+ std::shared_ptr<UICDM::IGuideSystem> theGuideSystem =
+ m_StudioSystem.GetFullSystem()->GetCoreSystem()->GetGuideSystem();
+ if (renderSpacePt.x >= m_InnerRect.m_Left && renderSpacePt.x <= m_InnerRect.m_Right) {
+ return UICDM::SGuideInfo((QT3DSF32)renderSpacePt.y - (QT3DSF32)m_InnerRect.m_Bottom,
+ UICDM::GuideDirections::Horizontal);
+ } else if (renderSpacePt.y >= m_InnerRect.m_Bottom
+ && renderSpacePt.y <= m_InnerRect.m_Top) {
+ return UICDM::SGuideInfo((QT3DSF32)renderSpacePt.x - (QT3DSF32)m_InnerRect.m_Left,
+ UICDM::GuideDirections::Vertical);
+ }
+ }
+ return qt3ds::foundation::Option<UICDM::SGuideInfo>();
+}
+
+QT3DSVec3 STranslation::GetIntendedPosition(UICDM::CUICDMInstanceHandle inInstance, CPt inPos)
+{
+ ClearDirtySet();
+ SGraphObjectTranslator *theTranslator = GetOrCreateTranslator(inInstance);
+ if (theTranslator == nullptr)
+ return QT3DSVec3(0, 0, 0);
+ if (GraphObjectTypes::IsNodeType(theTranslator->GetGraphObject().m_Type) == false)
+ return QT3DSVec3(0, 0, 0);
+ SNode *theNode = static_cast<SNode *>(&theTranslator->GetGraphObject());
+ SCamera *theCamera = m_UICContext.GetRenderer().GetCameraForNode(*theNode);
+ {
+ // Get the node's parent
+ CUICDMInstanceHandle theParent = m_AssetGraph.GetParent(inInstance);
+ SGraphObjectTranslator *theParentTranslator = GetOrCreateTranslator(theParent);
+ if (theParentTranslator
+ && GraphObjectTypes::IsNodeType(theParentTranslator->GetGraphObject().m_Type))
+ theCamera = m_UICContext.GetRenderer().GetCameraForNode(
+ *static_cast<SNode *>(&theParentTranslator->GetGraphObject()));
+ }
+ if (theCamera == nullptr)
+ return QT3DSVec3(0, 0, 0);
+
+ QT3DSVec3 theGlobalPos(theNode->GetGlobalPos());
+ return m_UICContext.GetRenderer().UnprojectToPosition(*theCamera, theGlobalPos,
+ QT3DSVec2((QT3DSF32)inPos.x, (QT3DSF32)inPos.y));
+}
+
+static void CheckLockToAxis(QT3DSF32 &inXDistance, QT3DSF32 &inYDistance, bool inLockToAxis)
+{
+ if (inLockToAxis) {
+ if (fabs(inXDistance) > fabs(inYDistance))
+ inYDistance = 0;
+ else
+ inXDistance = 0;
+ }
+}
+
+void STranslation::ApplyPositionalChange(QT3DSVec3 inDiff, SNode &inNode,
+ CUpdateableDocumentEditor &inEditor)
+{
+ if (m_MouseDownParentGlobalTransformInverse.isEmpty()) {
+ if (inNode.m_Parent)
+ m_MouseDownParentGlobalTransformInverse =
+ inNode.m_Parent->m_GlobalTransform.getInverse();
+ else
+ m_MouseDownParentGlobalTransformInverse = QT3DSMat44::createIdentity();
+ }
+ QT3DSMat44 theGlobalTransform = m_MouseDownNode.m_GlobalTransform;
+ QT3DSMat44 theNewLocalTransform =
+ m_MouseDownParentGlobalTransformInverse.getValue() * theGlobalTransform;
+ QT3DSVec3 theOldPos = theNewLocalTransform.column3.getXYZ();
+ theOldPos.z *= -1;
+
+ theGlobalTransform.column3 += QT3DSVec4(inDiff, 0.0f);
+ theNewLocalTransform = m_MouseDownParentGlobalTransformInverse.getValue() * theGlobalTransform;
+ QT3DSVec3 thePos = theNewLocalTransform.column3.getXYZ();
+ thePos.z *= -1;
+
+ QT3DSVec3 theDiff = thePos - theOldPos;
+
+ SetPosition(m_MouseDownNode.m_Position + theDiff, inEditor);
+}
+
+void STranslation::TranslateSelectedInstanceAlongCameraDirection(
+ CPt inOriginalCoords, CPt inMouseCoords, CUpdateableDocumentEditor &inEditor)
+{
+ SNode *theNode = GetSelectedNode();
+ if (theNode == nullptr)
+ return;
+ SCamera *theCamera = m_UICContext.GetRenderer().GetCameraForNode(*theNode);
+ if (theCamera == nullptr)
+ return;
+ QT3DSF32 theYDistance = QT3DSF32(inMouseCoords.y - inOriginalCoords.y);
+ if (fabs(theYDistance) == 0)
+ return;
+
+ QT3DSF32 theMouseMultiplier = 1.0f / 2.0f;
+ QT3DSF32 theDistanceMultiplier = 1.0f + theYDistance * theMouseMultiplier;
+ QT3DSVec3 theCameraDir = m_MouseDownCamera.GetDirection();
+
+ QT3DSVec3 theDiff = theCameraDir * theDistanceMultiplier;
+ ApplyPositionalChange(theDiff, *theNode, inEditor);
+}
+
+void STranslation::TranslateSelectedInstance(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor, bool inLockToAxis)
+{
+ SNode *theNode = GetSelectedNode();
+ if (theNode == nullptr)
+ return;
+ uic::render::IUICRenderer &theRenderer(m_UICContext.GetRenderer());
+
+ QT3DSF32 theXDistance = QT3DSF32(inMouseCoords.x - inOriginalCoords.x);
+ QT3DSF32 theYDistance = QT3DSF32(inMouseCoords.y - inOriginalCoords.y);
+ if (fabs(theXDistance) == 0 && fabs(theYDistance) == 0)
+ return;
+
+ CheckLockToAxis(theXDistance, theYDistance, inLockToAxis);
+
+ inMouseCoords.x = inOriginalCoords.x + (long)theXDistance;
+ inMouseCoords.y = inOriginalCoords.y + (long)theYDistance;
+ QT3DSVec3 theNodeGlobal = m_MouseDownNode.GetGlobalPos();
+ QT3DSVec3 theOriginalPos = theRenderer.UnprojectToPosition(
+ *theNode, theNodeGlobal, QT3DSVec2((QT3DSF32)inOriginalCoords.x, (QT3DSF32)inOriginalCoords.y));
+ QT3DSVec3 theNewPos = theRenderer.UnprojectToPosition(
+ *theNode, theNodeGlobal, QT3DSVec2((QT3DSF32)inMouseCoords.x, (QT3DSF32)inMouseCoords.y));
+
+ QT3DSVec3 theDiff = theNewPos - theOriginalPos;
+ ApplyPositionalChange(theDiff, *theNode, inEditor);
+}
+
+void STranslation::ScaleSelectedInstanceZ(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor)
+{
+ SNode *theNode = GetSelectedNode();
+ if (theNode == nullptr)
+ return;
+
+ // Scale scales uniformly and responds to mouse Y only.
+ QT3DSF32 theYDistance = (QT3DSF32)inMouseCoords.y - (QT3DSF32)inOriginalCoords.y;
+ if (fabs(theYDistance) == 0)
+ return;
+
+ QT3DSF32 theMouseMultiplier = 1.0f / 40.0f;
+ QT3DSF32 theScaleMultiplier = 1.0f + theYDistance * theMouseMultiplier;
+
+ SetScale(QT3DSVec3(m_MouseDownNode.m_Scale.x, m_MouseDownNode.m_Scale.y,
+ m_MouseDownNode.m_Scale.z * theScaleMultiplier),
+ inEditor);
+}
+
+void STranslation::ScaleSelectedInstance(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor)
+{
+ SNode *theNode = GetSelectedNode();
+ if (theNode == nullptr)
+ return;
+
+ // Scale scales uniformly and responds to mouse Y only.
+ QT3DSF32 theYDistance = (QT3DSF32)inMouseCoords.y - (QT3DSF32)inOriginalCoords.y;
+ if (fabs(theYDistance) == 0)
+ return;
+
+ QT3DSF32 theMouseMultiplier = 1.0f / 40.0f;
+ QT3DSF32 theScaleMultiplier = 1.0f + theYDistance * theMouseMultiplier;
+
+ SetScale(m_MouseDownNode.m_Scale * theScaleMultiplier, inEditor);
+}
+
+void STranslation::CalculateNodeGlobalRotation(SNode &inNode)
+{
+ if (inNode.m_Parent)
+ CalculateNodeGlobalRotation(*inNode.m_Parent);
+ if (m_MouseDownParentRotationInverse.isEmpty()) {
+ m_MouseDownParentRotationInverse = QT3DSMat33::createIdentity();
+ m_MouseDownGlobalRotation = QT3DSMat33::createIdentity();
+ }
+
+ QT3DSMat44 localRotation;
+ inNode.CalculateRotationMatrix(localRotation);
+ if (inNode.m_Flags.IsLeftHanded())
+ SNode::FlipCoordinateSystem(localRotation);
+ QT3DSMat33 theRotation;
+ SNode::GetMatrixUpper3x3(theRotation, localRotation);
+
+ m_MouseDownParentRotationInverse = m_MouseDownGlobalRotation;
+ m_MouseDownGlobalRotation = m_MouseDownGlobalRotation.getValue() * theRotation;
+}
+
+void STranslation::ApplyRotationToSelectedInstance(const QT3DSQuat &inFinalRotation, SNode &inNode,
+ CUpdateableDocumentEditor &inEditor,
+ bool inIsMouseRelative)
+{
+ if (m_MouseDownParentRotationInverse.isEmpty()) {
+ CalculateNodeGlobalRotation(inNode);
+ m_MouseDownParentRotationInverse = m_MouseDownParentRotationInverse->getInverse();
+ }
+ QT3DSMat33 theRotationMatrix(inFinalRotation);
+
+ QT3DSMat33 theFinalGlobal = theRotationMatrix * m_MouseDownGlobalRotation.getValue();
+ QT3DSMat33 theLocalGlobal = m_MouseDownParentRotationInverse.getValue() * theFinalGlobal;
+ QT3DSVec3 theRotations = inNode.GetRotationVectorFromRotationMatrix(theLocalGlobal);
+ theRotations = uic::render::SRotationHelper::ToNearestAngle(inNode.m_Rotation, theRotations,
+ inNode.m_RotationOrder);
+ SetRotation(theRotations, inEditor);
+ // Trackball rotation is relative to the previous mouse position.
+ // Rotation manipulator rotation is relative to only the original mouse down position
+ // so inIsMouseRelative is false for rotations that are relative to the original mouse down
+ // position.
+ if (inIsMouseRelative)
+ m_MouseDownGlobalRotation = theFinalGlobal;
+}
+
+void STranslation::RotateSelectedInstanceAboutCameraDirectionVector(
+ CPt inPreviousMouseCoords, CPt inMouseCoords, CUpdateableDocumentEditor &inEditor)
+{
+ SNode *theNode = GetSelectedNode();
+ if (theNode == nullptr)
+ return;
+ SCamera *theCamera = m_UICContext.GetRenderer().GetCameraForNode(*theNode);
+ if (theCamera == nullptr)
+ return;
+
+ QT3DSVec3 theDirection = m_MouseDownCamera.GetDirection();
+ QT3DSF32 theYDistance = (QT3DSF32)inMouseCoords.y - (QT3DSF32)inPreviousMouseCoords.y;
+ QT3DSQuat theYRotation(-1.0f * theYDistance * g_RotationScaleFactor, theDirection);
+
+ ApplyRotationToSelectedInstance(theYRotation, *theNode, inEditor);
+}
+
+// This method never feels right to me. It is difficult to apply it to a single axis (of course for
+// that
+// you can use the inspector palette).
+void STranslation::RotateSelectedInstance(CPt inOriginalCoords, CPt inPreviousCoords,
+ CPt inMouseCoords, CUpdateableDocumentEditor &inEditor,
+ bool inLockToAxis)
+{
+ SNode *theNode = GetSelectedNode();
+ if (theNode == nullptr)
+ return;
+ SCamera *theCamera = m_UICContext.GetRenderer().GetCameraForNode(*theNode);
+ if (theCamera == nullptr)
+ return;
+ // We want to do a similar translation to what we did below but we need to calculate the
+ // parent's
+ // global rotation without scale included.
+
+ QT3DSF32 theXDistance = (QT3DSF32)inMouseCoords.x - (QT3DSF32)inPreviousCoords.x;
+ QT3DSF32 theYDistance = (QT3DSF32)inMouseCoords.y - (QT3DSF32)inPreviousCoords.y;
+ bool xIsZero = fabs(theXDistance) < .001f;
+ bool yIsZero = fabs(theYDistance) < .001f;
+ if (xIsZero && yIsZero)
+ return;
+
+ if (inLockToAxis) {
+ QT3DSF32 originalDistX = (QT3DSF32)inMouseCoords.x - (QT3DSF32)inOriginalCoords.x;
+ QT3DSF32 originalDistY = (QT3DSF32)inMouseCoords.y - (QT3DSF32)inOriginalCoords.y;
+ if (inLockToAxis) {
+ if (fabs(originalDistX) > fabs(originalDistY))
+ theYDistance = 0;
+ else
+ theXDistance = 0;
+ }
+ }
+
+ QT3DSVec3 theXAxis = m_MouseDownCamera.m_GlobalTransform.column0.getXYZ();
+ QT3DSVec3 theYAxis = m_MouseDownCamera.m_GlobalTransform.column1.getXYZ();
+
+ QT3DSVec3 theFinalAxis = theXDistance * theYAxis + theYDistance * theXAxis;
+ QT3DSF32 theTotalDistance = theFinalAxis.normalize();
+ QT3DSQuat theRotation(theTotalDistance * g_RotationScaleFactor / 2.0f, theFinalAxis);
+
+ ApplyRotationToSelectedInstance(theRotation, *theNode, inEditor);
+}
+
+inline void NiceAdd(QT3DSF32 &ioValue, QT3DSF32 inIncrement)
+{
+ QT3DSF32 temp = ioValue + inIncrement;
+ // Round to nearest .5
+ QT3DSF32 sign = temp >= 0 ? 1.0f : -1.0f;
+ QT3DSU32 largerValue = (QT3DSU32)(fabs(temp * 10.0f));
+
+ QT3DSU32 leftover = largerValue % 10;
+ // Round down to zero
+ largerValue -= leftover;
+ if (leftover < 2)
+ leftover = 0;
+ else if (leftover > 7) {
+ leftover = 0;
+ largerValue += 10;
+ } else
+ leftover = 5;
+ largerValue += leftover;
+
+ ioValue = sign * (QT3DSF32)largerValue / 10.0f;
+}
+
+static inline QT3DSVec3 GetAxis(QT3DSU32 inIndex, QT3DSMat33 &inMatrix)
+{
+ QT3DSVec3 retval(0, 0, 0);
+ switch (inIndex) {
+ case 0:
+ retval = inMatrix.column0;
+ break;
+ case 1:
+ retval = inMatrix.column1;
+ break;
+ case 2:
+ retval = inMatrix.column2;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ retval.normalize();
+ return retval;
+}
+
+inline Option<QT3DSF32> GetScaleAlongAxis(const QT3DSVec3 &inAxis, const QT3DSVec3 &inObjToOriginal,
+ const QT3DSVec3 &inObjToCurrent)
+{
+ QT3DSF32 lhs = inAxis.dot(inObjToCurrent);
+ QT3DSF32 rhs = inAxis.dot(inObjToOriginal);
+ if (fabs(rhs) > .001f)
+ return lhs / rhs;
+ return Empty();
+}
+
+// Make a nice rotation from the incoming rotation
+static inline QT3DSF32 MakeNiceRotation(QT3DSF32 inAngle)
+{
+ TODEG(inAngle);
+ inAngle *= 10.0f;
+ QT3DSF32 sign = inAngle > 0.0f ? 1.0f : -1.0f;
+ // Attempt to ensure angle is prtty clean
+ QT3DSU32 clampedAngle = (QT3DSU32)(fabs(inAngle) + .5f);
+ QT3DSU32 leftover = clampedAngle % 10;
+ clampedAngle -= leftover;
+ if (leftover <= 2)
+ leftover = 0;
+ else if (leftover <= 7)
+ leftover = 5;
+ else
+ leftover = 10;
+ clampedAngle += leftover;
+ QT3DSF32 retval = (QT3DSF32)clampedAngle;
+ retval = (retval * sign) / 10.0f;
+ TORAD(retval);
+ return retval;
+}
+
+static inline QT3DSF32 ShortestAngleDifference(QT3DSF32 inCumulative, QT3DSF32 inNewTotal)
+{
+ QT3DSF32 diff = uic::render::SRotationHelper::ToMinimalAngle(inNewTotal - inCumulative);
+ return inCumulative + diff;
+}
+
+Option<SDragPreparationResult>
+STranslation::PrepareWidgetDrag(uic::widgets::StudioWidgetComponentIds::Enum inComponentId,
+ uic::widgets::StudioWidgetTypes::Enum inWidgetId,
+ uic::render::RenderWidgetModes::Enum inWidgetMode, SNode &inNode,
+ CPt inOriginalCoords, CPt inPreviousMouseCoords, CPt inMouseCoords)
+{
+ SDragPreparationResult retval;
+ retval.m_ComponentId = inComponentId;
+ retval.m_WidgetType = inWidgetId;
+ retval.m_WidgetMode = inWidgetMode;
+ uic::render::IUICRenderer &theRenderer(m_UICContext.GetRenderer());
+ retval.m_Renderer = &theRenderer;
+ retval.m_Node = &inNode;
+ retval.m_Layer = GetLayerForNode(inNode);
+ retval.m_Camera = theRenderer.GetCameraForNode(inNode);
+ uic::render::SWindowDimensions theUnsignedDimensions(m_UICContext.GetWindowDimensions());
+ QT3DSVec2 theWindowDimensions((QT3DSF32)theUnsignedDimensions.m_Width,
+ (QT3DSF32)theUnsignedDimensions.m_Height);
+ if (retval.m_Camera == nullptr || retval.m_Layer == nullptr)
+ return Empty();
+
+ SCamera &theCamera(*retval.m_Camera);
+ SLayer &theLayer(*retval.m_Layer);
+ QT3DSVec2 theLayerOriginalCoords = m_UICContext.GetRenderer().GetLayerMouseCoords(
+ *retval.m_Layer, QT3DSVec2((QT3DSF32)inOriginalCoords.x, (QT3DSF32)inOriginalCoords.y),
+ theWindowDimensions, true);
+
+ QT3DSVec2 theLayerMouseCoords = m_UICContext.GetRenderer().GetLayerMouseCoords(
+ *retval.m_Layer, QT3DSVec2((QT3DSF32)inMouseCoords.x, (QT3DSF32)inMouseCoords.y),
+ theWindowDimensions, true);
+
+ QT3DSVec2 thePreviousLayerMouseCoords = m_UICContext.GetRenderer().GetLayerMouseCoords(
+ *retval.m_Layer, QT3DSVec2((QT3DSF32)inPreviousMouseCoords.x, (QT3DSF32)inPreviousMouseCoords.y),
+ theWindowDimensions, true);
+ QT3DSMat44 theGlobalTransform(QT3DSMat44::createIdentity());
+ if (inWidgetMode == uic::render::RenderWidgetModes::Local) {
+ theGlobalTransform = m_MouseDownNode.m_GlobalTransform;
+ }
+ retval.m_GlobalTransform = theGlobalTransform;
+ QT3DSMat33 theNormalMat(theGlobalTransform.column0.getXYZ(), theGlobalTransform.column1.getXYZ(),
+ theGlobalTransform.column2.getXYZ());
+ theNormalMat = theNormalMat.getInverse().getTranspose();
+ retval.m_NormalMatrix = theNormalMat;
+ qt3ds::render::NVRenderRectF theLayerRect(theRenderer.GetLayerRect(theLayer));
+ SRay theOriginalRay =
+ theCamera.Unproject(theLayerOriginalCoords, theLayerRect, theWindowDimensions);
+ SRay theCurrentRay =
+ theCamera.Unproject(theLayerMouseCoords, theLayerRect, theWindowDimensions);
+ SRay thePreviousRay =
+ theCamera.Unproject(thePreviousLayerMouseCoords, theLayerRect, theWindowDimensions);
+ retval.m_OriginalRay = theOriginalRay;
+ retval.m_CurrentRay = theCurrentRay;
+ retval.m_PreviousRay = thePreviousRay;
+ QT3DSVec3 theAxis;
+ QT3DSVec3 thePlaneNormal;
+ bool isPlane = false;
+ QT3DSVec3 globalPos = inNode.GetGlobalPivot();
+ QT3DSVec3 camGlobalPos = theCamera.GetGlobalPos();
+ QT3DSVec3 theCamDirection;
+ retval.m_GlobalPos = globalPos;
+ retval.m_CameraGlobalPos = camGlobalPos;
+ if (theCamera.m_Flags.IsOrthographic())
+ theCamDirection = theCamera.GetDirection();
+ else {
+ theCamDirection = globalPos - camGlobalPos;
+ // The normal will be normalized below.
+ }
+ theCamDirection.normalize();
+ retval.m_CameraDirection = theCamDirection;
+ retval.m_AxisIndex = 0;
+ switch (inComponentId) {
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ case uic::widgets::StudioWidgetComponentIds::XAxis:
+ theAxis = QT3DSVec3(1, 0, 0);
+ break;
+ case uic::widgets::StudioWidgetComponentIds::YAxis:
+ theAxis = QT3DSVec3(0, 1, 0);
+ retval.m_AxisIndex = 1;
+ break;
+ case uic::widgets::StudioWidgetComponentIds::ZAxis:
+ theAxis = QT3DSVec3(0, 0, -1);
+ retval.m_AxisIndex = 2;
+ break;
+ case uic::widgets::StudioWidgetComponentIds::XPlane:
+ thePlaneNormal = QT3DSVec3(1, 0, 0);
+ isPlane = true;
+ break;
+ case uic::widgets::StudioWidgetComponentIds::YPlane:
+ thePlaneNormal = QT3DSVec3(0, 1, 0);
+ isPlane = true;
+ break;
+ case uic::widgets::StudioWidgetComponentIds::ZPlane:
+ thePlaneNormal = QT3DSVec3(0, 0, -1);
+ isPlane = true;
+ break;
+ case uic::widgets::StudioWidgetComponentIds::CameraPlane: {
+ isPlane = true;
+ thePlaneNormal = theCamDirection;
+ } break;
+ }
+ retval.m_IsPlane = isPlane;
+ if (inWidgetId == uic::widgets::StudioWidgetTypes::Rotation) {
+ if (isPlane == false) {
+ theAxis = theNormalMat.transform(theAxis);
+ theAxis.normalize();
+ thePlaneNormal = theAxis;
+ retval.m_Plane = qt3ds::NVPlane(thePlaneNormal, -1.0f * thePlaneNormal.dot(globalPos));
+ } else {
+ if (inComponentId != uic::widgets::StudioWidgetComponentIds::CameraPlane) {
+ thePlaneNormal = theNormalMat.transform(thePlaneNormal);
+ }
+ thePlaneNormal.normalize();
+ retval.m_Plane = qt3ds::NVPlane(thePlaneNormal, -1.0f * (thePlaneNormal.dot(globalPos)));
+ }
+ } else {
+ if (isPlane == false) {
+ theAxis = theNormalMat.transform(theAxis);
+ theAxis.normalize();
+ QT3DSVec3 theCameraToObj = globalPos - camGlobalPos;
+ QT3DSVec3 theTemp = theAxis.cross(theOriginalRay.m_Direction);
+ // Then the axis is parallel to the camera, we can't drag meaningfullly
+ if (theTemp.magnitudeSquared() < .05f) {
+ // Attempt to find a better axis by moving the object back towards the camera.
+ QT3DSF32 theSign = theCameraToObj.dot(theCamDirection) > 0.0 ? -1.0f : 1.0f;
+ QT3DSF32 theDistance = theCameraToObj.dot(theCamDirection);
+ QT3DSVec3 thePoint = globalPos + (theDistance * theSign) * theAxis;
+ QT3DSVec3 theNewDir = thePoint - camGlobalPos;
+ theNewDir.normalize();
+ theTemp = theAxis.cross(theNewDir);
+ // Attempt again to find a better cross
+ if (theTemp.magnitudeSquared() < .05f)
+ return Empty();
+ }
+ thePlaneNormal = theTemp.cross(theAxis);
+ thePlaneNormal.normalize();
+ retval.m_Plane = qt3ds::NVPlane(thePlaneNormal, -1.0f * thePlaneNormal.dot(globalPos));
+ } else {
+ thePlaneNormal = theNormalMat.transform(thePlaneNormal);
+ thePlaneNormal.normalize();
+ retval.m_Plane = qt3ds::NVPlane(thePlaneNormal, -1.0f * (thePlaneNormal.dot(globalPos)));
+ }
+ }
+ retval.m_Axis = theAxis;
+ retval.m_OriginalPlaneCoords = theOriginalRay.Intersect(retval.m_Plane);
+ retval.m_CurrentPlaneCoords = theCurrentRay.Intersect(retval.m_Plane);
+ retval.m_PreviousPlaneCoords = thePreviousRay.Intersect(retval.m_Plane);
+ return retval;
+}
+
+void STranslation::PerformWidgetDrag(int inWidgetSubComponent, CPt inOriginalCoords,
+ CPt inPreviousMouseCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor)
+{
+ if (inWidgetSubComponent == 0 || m_LastRenderedWidget == nullptr) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ Option<SDragPreparationResult> thePrepResult(PrepareWidgetDrag(
+ static_cast<uic::widgets::StudioWidgetComponentIds::Enum>(inWidgetSubComponent),
+ m_LastRenderedWidget->GetWidgetType(), m_LastRenderedWidget->GetRenderWidgetMode(),
+ m_LastRenderedWidget->GetNode(), inOriginalCoords, inPreviousMouseCoords, inMouseCoords));
+ if (!thePrepResult.hasValue())
+ return;
+
+ Option<QT3DSVec3> theOriginalPlaneCoords(thePrepResult->m_OriginalPlaneCoords);
+ Option<QT3DSVec3> theCurrentPlaneCoords(thePrepResult->m_CurrentPlaneCoords);
+ Option<QT3DSVec3> thePreviousPlaneCoords(thePrepResult->m_PreviousPlaneCoords);
+ QT3DSVec3 globalPos(thePrepResult->m_GlobalPos);
+ bool isPlane(thePrepResult->m_IsPlane);
+ QT3DSVec3 theAxis(thePrepResult->m_Axis);
+ QT3DSU32 axisIndex(thePrepResult->m_AxisIndex);
+ SNode *theNode(thePrepResult->m_Node);
+ SRay theCurrentRay(thePrepResult->m_CurrentRay);
+ SRay theOriginalRay(thePrepResult->m_OriginalRay);
+ QT3DSVec3 thePlaneNormal(thePrepResult->m_Plane.n);
+ QT3DSVec3 theCamDirection(thePrepResult->m_CameraDirection);
+ QT3DSVec3 camGlobalPos(thePrepResult->m_CameraGlobalPos);
+
+ switch (m_LastRenderedWidget->GetWidgetType()) {
+ default:
+ QT3DS_ASSERT(false);
+ return;
+ case uic::widgets::StudioWidgetTypes::Scale: {
+ if (theOriginalPlaneCoords.hasValue() && theCurrentPlaneCoords.hasValue()) {
+ QT3DSVec3 objToOriginal = globalPos - *theOriginalPlaneCoords;
+ QT3DSVec3 objToCurrent = globalPos - *theCurrentPlaneCoords;
+ QT3DSVec3 theScaleMultiplier(1, 1, 1);
+ if (!isPlane) {
+ // Ensure that we only have a scale vector in the direction of the axis.
+ objToOriginal = theAxis * (theAxis.dot(objToOriginal));
+ objToCurrent = theAxis * (theAxis.dot(objToCurrent));
+ QT3DSF32 objToOriginalDot = theAxis.dot(objToOriginal);
+ if (fabs(objToOriginalDot) > .001f)
+ theScaleMultiplier[axisIndex] =
+ theAxis.dot(objToCurrent) / theAxis.dot(objToOriginal);
+ else
+ theScaleMultiplier[axisIndex] = 0.0f;
+ }
+
+ QT3DSMat33 theNodeAxisMatrix(theNode->m_GlobalTransform.column0.getXYZ(),
+ theNode->m_GlobalTransform.column1.getXYZ(),
+ theNode->m_GlobalTransform.column2.getXYZ());
+ theNodeAxisMatrix = theNodeAxisMatrix.getInverse().getTranspose();
+ QT3DSVec3 &theLocalXAxis(theNodeAxisMatrix.column0);
+ QT3DSVec3 &theLocalYAxis(theNodeAxisMatrix.column1);
+ QT3DSVec3 &theLocalZAxis(theNodeAxisMatrix.column2);
+ theLocalXAxis.normalize();
+ theLocalYAxis.normalize();
+ theLocalZAxis.normalize();
+
+ Option<QT3DSF32> theXScale = GetScaleAlongAxis(theLocalXAxis, objToOriginal, objToCurrent);
+ Option<QT3DSF32> theYScale = GetScaleAlongAxis(theLocalYAxis, objToOriginal, objToCurrent);
+ Option<QT3DSF32> theZScale = GetScaleAlongAxis(theLocalZAxis, objToOriginal, objToCurrent);
+ QT3DSVec3 theScale = m_MouseDownNode.m_Scale;
+ if (theXScale.isEmpty() && theYScale.isEmpty() && theZScale.isEmpty()) {
+ theScale = QT3DSVec3(0, 0, 0);
+ } else {
+ if (theXScale.hasValue())
+ theScale.x *= *theXScale;
+ if (theYScale.hasValue())
+ theScale.y *= *theYScale;
+ if (theZScale.hasValue())
+ theScale.z *= *theZScale;
+ }
+ m_LastRenderedWidget->SetAxisScale(theScaleMultiplier);
+ SetScale(theScale, inEditor);
+ }
+ } break;
+ case uic::widgets::StudioWidgetTypes::Rotation: {
+ QT3DSF32 theIntersectionCosine = theOriginalRay.m_Direction.dot(thePlaneNormal);
+ QT3DSVec3 objToPrevious;
+ QT3DSVec3 objToCurrent;
+ /*
+ long theModifiers = CHotKeys::GetCurrentKeyModifiers();
+ if ( theModifiers & CHotKeys::MODIFIER_SHIFT )
+ {
+ DebugBreak();
+ }
+ */
+ if (!theOriginalPlaneCoords.hasValue() || !theCurrentPlaneCoords.hasValue())
+ return;
+ if (fabs(theIntersectionCosine) > .08f) {
+ objToPrevious = globalPos - *theOriginalPlaneCoords;
+ objToCurrent = globalPos - *theCurrentPlaneCoords;
+ objToPrevious.normalize();
+ QT3DSF32 lineLen = objToCurrent.normalize();
+ QT3DSF32 cosAngle = objToPrevious.dot(objToCurrent);
+ QT3DSVec3 theCrossProd = objToPrevious.cross(objToCurrent);
+ QT3DSF32 theCrossPlaneDot = theCrossProd.dot(thePlaneNormal);
+ QT3DSF32 angleSign = theCrossPlaneDot >= 0.0f ? 1.0f : -1.0f;
+ QT3DSF32 angleRad = acos(cosAngle) * angleSign;
+ angleRad = MakeNiceRotation(angleRad);
+ QT3DSQuat theRotation(angleRad, thePlaneNormal);
+ m_CumulativeRotation = ShortestAngleDifference(m_CumulativeRotation, angleRad);
+ m_LastRenderedWidget->SetRotationEdges(-1.0f * objToPrevious, thePlaneNormal,
+ m_CumulativeRotation, lineLen);
+ ApplyRotationToSelectedInstance(theRotation, *theNode, inEditor, false);
+ }
+ // In this case we are viewing the plane of rotation pretty much dead on, so we need to
+ // assume
+ // the camera and the object are both in the plane of rotation. In this case we *sort* of
+ // need to
+ // do trackball rotation but force it to one plane of rotation.
+ else {
+ // Setup a plane 600 units away from the camera and have the gadget run from there.
+
+ // This keeps rotation consistent.
+ QT3DSVec3 thePlaneSpot = theCamDirection * -600.0f + camGlobalPos;
+ qt3ds::NVPlane theCameraPlaneAtObject(theCamDirection,
+ -1.0f * (theCamDirection.dot(thePlaneSpot)));
+ theCurrentPlaneCoords = theCurrentRay.Intersect(theCameraPlaneAtObject);
+ theOriginalPlaneCoords = theOriginalRay.Intersect(theCameraPlaneAtObject);
+ QT3DSVec3 theChangeVector = *theOriginalPlaneCoords - *theCurrentPlaneCoords;
+ // Remove any component of the change vector that doesn't lie in the plane.
+ theChangeVector =
+ theChangeVector - theChangeVector.dot(thePlaneNormal) * thePlaneNormal;
+ QT3DSF32 theDistance = theChangeVector.normalize();
+ // We want about 90* per 200 units in imaginary 600-units-from-camera space.
+ QT3DSF32 theScaleFactor = 1.0f / 200.0f;
+ if (thePrepResult->m_Camera->m_Flags.IsOrthographic())
+ theScaleFactor = 1.0f / 100.0f;
+
+ QT3DSF32 theDeg = 90.0f * theDistance * theScaleFactor;
+ // Check the sign of the angle.
+ QT3DSVec3 theCurrentIsectDir = camGlobalPos - *theCurrentPlaneCoords;
+ QT3DSVec3 thePreviousIsectDir = camGlobalPos - *theOriginalPlaneCoords;
+ QT3DSVec3 theCrossProd = theCurrentIsectDir.cross(thePreviousIsectDir);
+ QT3DSF32 theAngleSign = theCrossProd.dot(thePlaneNormal) > 0.0f ? 1.0f : -1.0f;
+ theDeg *= theAngleSign;
+ QT3DSF32 theRad(theDeg);
+ TORAD(theRad);
+ theRad = MakeNiceRotation(theRad);
+ QT3DSQuat theRotation(theRad, thePlaneNormal);
+ ApplyRotationToSelectedInstance(theRotation, *theNode, inEditor, false);
+ }
+ } break;
+ case uic::widgets::StudioWidgetTypes::Translation: {
+ if (theOriginalPlaneCoords.hasValue() && theCurrentPlaneCoords.hasValue()) {
+ QT3DSVec3 theDiff = *theCurrentPlaneCoords - *theOriginalPlaneCoords;
+ if (isPlane) {
+ ApplyPositionalChange(theDiff, *theNode, inEditor);
+ } else {
+ QT3DSVec3 theMovement = theAxis * theAxis.dot(theDiff);
+ ApplyPositionalChange(theMovement, *theNode, inEditor);
+ }
+ }
+ } break;
+ }
+}
+
+static float RoundToNearest(float inValue, float inMin, float inMax, float inRound)
+{
+ float half = (inMin + inMax) / 2.0f;
+ inValue -= half;
+ inValue = inRound * floor(inValue / inRound + .5f);
+ inValue += half;
+ inValue -= inMin;
+ return inValue;
+}
+
+void STranslation::PerformGuideDrag(CUICDMGuideHandle inGuide, CPt inPoint,
+ CUpdateableDocumentEditor &inEditor)
+{
+ UICDM::SGuideInfo theInfo = m_Doc.GetDocumentReader().GetGuideInfo(inGuide);
+ CPt renderSpacePt(inPoint.x, (long)GetViewportDimensions().y - inPoint.y);
+ switch (theInfo.m_Direction) {
+ case UICDM::GuideDirections::Horizontal:
+ theInfo.m_Position = RoundToNearest((float)renderSpacePt.y, (float)m_InnerRect.m_Bottom,
+ (float)m_InnerRect.m_Top, 10.0f);
+ break;
+ case UICDM::GuideDirections::Vertical:
+ theInfo.m_Position = RoundToNearest((float)renderSpacePt.x, (float)m_InnerRect.m_Left,
+ (float)m_InnerRect.m_Right, 10.0f);
+ break;
+ default:
+ QT3DS_ASSERT(FALSE);
+ break;
+ break;
+ }
+ inEditor.EnsureEditor(L"Drag Guide", __FILE__, __LINE__).UpdateGuide(inGuide, theInfo);
+ inEditor.FireImmediateRefresh(UICDM::CUICDMInstanceHandle());
+}
+
+void STranslation::CheckGuideInPresentationRect(CUICDMGuideHandle inGuide,
+ CUpdateableDocumentEditor &inEditor)
+{
+ UICDM::SGuideInfo theInfo = m_Doc.GetDocumentReader().GetGuideInfo(inGuide);
+ bool inPresentation = false;
+ QT3DSF32 presHeight = (QT3DSF32)m_InnerRect.m_Top - (QT3DSF32)m_InnerRect.m_Bottom;
+ QT3DSF32 presWidth = (QT3DSF32)m_InnerRect.m_Right - (QT3DSF32)m_InnerRect.m_Left;
+ switch (theInfo.m_Direction) {
+ case UICDM::GuideDirections::Horizontal:
+ inPresentation = 0.0f <= theInfo.m_Position && presHeight >= theInfo.m_Position;
+ break;
+ case UICDM::GuideDirections::Vertical:
+ inPresentation = 0.0f <= theInfo.m_Position && presWidth >= theInfo.m_Position;
+ break;
+ }
+ if (!inPresentation)
+ inEditor.EnsureEditor(L"Delete Guide", __FILE__, __LINE__).DeleteGuide(inGuide);
+}
+
+namespace {
+
+QT3DSF32 degToRad(const QT3DSF32 a)
+{
+ return (QT3DSF32)0.01745329251994329547 * a;
+}
+
+/**
+\brief Converts radians to degrees.
+*/
+QT3DSF32 radToDeg(const QT3DSF32 a)
+{
+ return (QT3DSF32)57.29577951308232286465 * a;
+}
+}
+
+void STranslation::PerformPathDrag(uic::studio::SPathPick &inPathPick, CPt inOriginalCoords,
+ CPt inPreviousMouseCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor)
+{
+ Option<SDragPreparationResult> thePrepResult(PrepareWidgetDrag(
+ uic::widgets::StudioWidgetComponentIds::ZPlane,
+ uic::widgets::StudioWidgetTypes::Translation, uic::render::RenderWidgetModes::Local,
+ m_PathWidget->GetNode(), inOriginalCoords, inPreviousMouseCoords, inMouseCoords));
+ if (!thePrepResult.hasValue())
+ return;
+
+ Option<QT3DSVec3> theOriginalPlaneCoords(thePrepResult->m_OriginalPlaneCoords);
+ Option<QT3DSVec3> theCurrentPlaneCoords(thePrepResult->m_CurrentPlaneCoords);
+ Option<QT3DSVec3> thePreviousPlaneCoords(thePrepResult->m_PreviousPlaneCoords);
+ if (theOriginalPlaneCoords.hasValue() && theCurrentPlaneCoords.hasValue()) {
+ QT3DSVec3 theGlobalDiff = *theCurrentPlaneCoords - *theOriginalPlaneCoords;
+ QT3DSMat44 theGlobalInverse = thePrepResult->m_GlobalTransform.getInverse();
+ QT3DSVec3 theCurrentPos = theGlobalInverse.transform(*theCurrentPlaneCoords);
+ QT3DSVec3 theOldPos = theGlobalInverse.transform(*theOriginalPlaneCoords);
+ QT3DSVec3 theDiff = theCurrentPos - theOldPos;
+ // Now find the anchor point; nontrivial.
+ SPathTranslator *theTranslator =
+ reinterpret_cast<SPathTranslator *>(thePrepResult->m_Node->m_UserData.m_UserData);
+ UICDM::CUICDMInstanceHandle thePathHandle = theTranslator->GetInstanceHandle();
+ UICDM::CUICDMInstanceHandle theAnchorHandle = GetAnchorPoint(inPathPick);
+
+ if (theAnchorHandle.Valid()) {
+ UICDM::CUICDMPropertyHandle thePosProperty =
+ m_ObjectDefinitions.m_PathAnchorPoint.m_Position.m_Property;
+ UICDM::CUICDMPropertyHandle theAngleProperty =
+ m_ObjectDefinitions.m_PathAnchorPoint.m_IncomingAngle.m_Property;
+ UICDM::CUICDMPropertyHandle theIncomingDistanceProperty =
+ m_ObjectDefinitions.m_PathAnchorPoint.m_IncomingDistance.m_Property;
+ UICDM::CUICDMPropertyHandle theOutgoingDistanceProperty =
+ m_ObjectDefinitions.m_PathAnchorPoint.m_OutgoingDistance.m_Property;
+
+ IDocumentReader &theReader(m_Doc.GetDocumentReader());
+ SFloat2 anchorPos =
+ *theReader.GetTypedInstancePropertyValue<SFloat2>(theAnchorHandle, thePosProperty);
+ QT3DSVec2 anchorPosVec = QT3DSVec2(anchorPos[0], anchorPos[1]);
+ if (m_LastPathDragValue.hasValue() == false) {
+ SPathAnchorDragInitialValue initialValue;
+ initialValue.m_Position = anchorPosVec;
+ initialValue.m_IncomingAngle = theReader.GetTypedInstancePropertyValue<float>(
+ theAnchorHandle, theAngleProperty);
+ initialValue.m_IncomingDistance = theReader.GetTypedInstancePropertyValue<float>(
+ theAnchorHandle, theIncomingDistanceProperty);
+ initialValue.m_OutgoingDistance = theReader.GetTypedInstancePropertyValue<float>(
+ theAnchorHandle, theOutgoingDistanceProperty);
+ m_LastPathDragValue = initialValue;
+ }
+ SPathAnchorDragInitialValue &lastValue(*m_LastPathDragValue);
+ QT3DSVec2 theCurrentValue;
+ switch (inPathPick.m_Property) {
+ case SPathPick::Anchor:
+ theCurrentValue = lastValue.m_Position;
+ break;
+ case SPathPick::IncomingControl:
+ theCurrentValue = uic::render::IPathManagerCore::GetControlPointFromAngleDistance(
+ lastValue.m_Position, lastValue.m_IncomingAngle, lastValue.m_IncomingDistance);
+ break;
+ case SPathPick::OutgoingControl:
+ theCurrentValue = uic::render::IPathManagerCore::GetControlPointFromAngleDistance(
+ lastValue.m_Position, lastValue.m_IncomingAngle + 180.0f,
+ lastValue.m_OutgoingDistance);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ theCurrentValue[0] += theDiff.x;
+ theCurrentValue[1] += theDiff.y;
+ Q3DStudio::IDocumentEditor &theEditor =
+ inEditor.EnsureEditor(L"Anchor Point Drag", __FILE__, __LINE__);
+ switch (inPathPick.m_Property) {
+ case SPathPick::Anchor:
+ theEditor.SetInstancePropertyValue(theAnchorHandle, thePosProperty,
+ SFloat2(theCurrentValue.x, theCurrentValue.y));
+ break;
+ case SPathPick::IncomingControl: {
+ QT3DSVec2 angleDistance =
+ uic::render::IPathManagerCore::GetAngleDistanceFromControlPoint(
+ anchorPosVec, theCurrentValue);
+ float angleDiff = angleDistance.x - lastValue.m_IncomingAngle;
+ float minimalDiff =
+ radToDeg(uic::render::SRotationHelper::ToMinimalAngle(degToRad(angleDiff)));
+ float newAngle = lastValue.m_IncomingAngle + minimalDiff;
+ theEditor.SetInstancePropertyValue(theAnchorHandle, theAngleProperty, newAngle);
+ theEditor.SetInstancePropertyValue(theAnchorHandle, theIncomingDistanceProperty,
+ angleDistance.y);
+ } break;
+ case SPathPick::OutgoingControl: {
+ QT3DSVec2 angleDistance =
+ uic::render::IPathManagerCore::GetAngleDistanceFromControlPoint(
+ anchorPosVec, theCurrentValue);
+ angleDistance.x += 180.0f;
+ float angleDiff = angleDistance.x - lastValue.m_IncomingAngle;
+ float minimalDiff =
+ radToDeg(uic::render::SRotationHelper::ToMinimalAngle(degToRad(angleDiff)));
+ float newAngle = lastValue.m_IncomingAngle + minimalDiff;
+ theEditor.SetInstancePropertyValue(theAnchorHandle, theAngleProperty, newAngle);
+ theEditor.SetInstancePropertyValue(theAnchorHandle, theOutgoingDistanceProperty,
+ angleDistance.y);
+ } break;
+ }
+
+ inEditor.FireImmediateRefresh(m_AssetGraph.GetParent(theAnchorHandle));
+ }
+ }
+}
+
+// Pulled directly from old studio's Node.cpp.
+void STranslation::OnNudge(ENudgeDirection inDirection, int inToolmode, int inFlags,
+ CUpdateableDocumentEditor &inEditor)
+{
+ Q_UNUSED(inFlags);
+ SNode *theSelectedNode = GetSelectedNode();
+ if (theSelectedNode == nullptr)
+ return;
+ ;
+
+ // Increment the key press count
+ m_KeyRepeat++;
+
+ // Increment the acceleration for every 5 key presses
+ float theAcceleration = static_cast<float>(qt3ds::foundation::floor(m_KeyRepeat / 5.0)) + 1.0f;
+
+ CUICDMPropertyHandle thePropertyHandle;
+ SFloat3 theValue;
+ const wchar_t *theCommandName = L"";
+ UICDM::CUICDMInstanceHandle theInstanceHandle = m_Doc.GetSelectedInstance();
+ CDispatchDataModelImmediateScope __dispatchScope(*m_Doc.GetCore()->GetDispatch(),
+ theInstanceHandle);
+ // See what tool mode we are in
+ switch (inToolmode) {
+ // We want to nudge the position vector
+ case STUDIO_TOOLMODE_MOVE:
+ thePropertyHandle = m_ObjectDefinitions.m_Node.m_Position;
+ theValue =
+ m_Reader.GetTypedInstancePropertyValue<SFloat3>(theInstanceHandle, thePropertyHandle);
+ theCommandName = L"Set Position";
+ break;
+
+ // We want to nudge the rotation vector
+ case STUDIO_TOOLMODE_ROTATE:
+ thePropertyHandle = m_ObjectDefinitions.m_Node.m_Rotation;
+ theValue = m_Reader.GetTypedInstancePropertyValue<UICDM::SFloat3>(theInstanceHandle,
+ thePropertyHandle);
+ theCommandName = L"Set Rotation";
+ break;
+
+ // We want to nudge the scale vector
+ case STUDIO_TOOLMODE_SCALE:
+ thePropertyHandle = m_ObjectDefinitions.m_Node.m_Scale;
+ theValue = m_Reader.GetTypedInstancePropertyValue<UICDM::SFloat3>(theInstanceHandle,
+ thePropertyHandle);
+ theCommandName = L"Set Scale";
+ break;
+
+ // We should always have a tool mode, but just in case, default to position
+ default:
+ thePropertyHandle = m_ObjectDefinitions.m_Node.m_Position;
+ theValue = m_Reader.GetTypedInstancePropertyValue<UICDM::SFloat3>(theInstanceHandle,
+ thePropertyHandle);
+ theCommandName = L"Set Position";
+ break;
+ }
+
+ // If we are in rotate mode, we need to switch the x and y values because we want to rotate
+ // *around* the specified axis
+ if ((inToolmode) == STUDIO_TOOLMODE_ROTATE) {
+ // Switch from positive x to negative y
+ if (inDirection == NUDGE_POS_X) {
+ inDirection = NUDGE_NEG_Y;
+ }
+ // Switch from positive y to negative x
+ else if (inDirection == NUDGE_POS_Y) {
+ inDirection = NUDGE_NEG_X;
+ }
+ // Switch from negative x to positive y
+ else if (inDirection == NUDGE_NEG_X) {
+ inDirection = NUDGE_POS_Y;
+ }
+ // Switch from negative y to positive x
+ else if (inDirection == NUDGE_NEG_Y) {
+ inDirection = NUDGE_POS_X;
+ }
+ }
+
+ float theNudgeAmount = static_cast<float>(CStudioPreferences::GetNudgeAmount());
+
+ // Now check which value to change (x, y, or z) and whether to increment or decrement
+ switch (inDirection) {
+ // Nudge along the positive x-axis
+ case NUDGE_POS_X:
+ theValue.m_Floats[0] += (theNudgeAmount * theAcceleration);
+ break;
+
+ // Nudge along the positive y-axis
+ case NUDGE_POS_Y:
+ theValue.m_Floats[1] += (theNudgeAmount * theAcceleration);
+ break;
+
+ // Nudge along the positive z-axis
+ case NUDGE_POS_Z:
+ theValue.m_Floats[2] += (theNudgeAmount * theAcceleration);
+ break;
+
+ // Nudge along the negative x-axis
+ case NUDGE_NEG_X:
+ theValue.m_Floats[0] -= (theNudgeAmount * theAcceleration);
+ break;
+
+ // Nudge along the negative y-axis
+ case NUDGE_NEG_Y:
+ theValue.m_Floats[1] -= (theNudgeAmount * theAcceleration);
+ break;
+
+ // Nudge along the negative z-axis
+ case NUDGE_NEG_Z:
+ theValue.m_Floats[2] -= (theNudgeAmount * theAcceleration);
+ break;
+ }
+
+ inEditor.EnsureEditor(theCommandName, __FILE__, __LINE__)
+ .SetInstancePropertyValue(theInstanceHandle, thePropertyHandle, theValue);
+}
+
+SNode *STranslation::GetEditCameraLayer()
+{
+ if (m_EditCameraLayerTranslator)
+ return static_cast<SNode *>(&m_EditCameraLayerTranslator->GetGraphObject());
+ return nullptr;
+}
+
+PickTargetAreas::Enum STranslation::GetPickArea(CPt inPoint)
+{
+ qt3ds::render::NVRenderRectF displayViewport = m_UICContext.GetDisplayViewport();
+ QT3DSVec2 thePickPoint((QT3DSF32)inPoint.x,
+ m_UICContext.GetWindowDimensions().m_Height - (QT3DSF32)inPoint.y);
+ QT3DSF32 left = displayViewport.m_X;
+ QT3DSF32 right = displayViewport.m_X + displayViewport.m_Width;
+ QT3DSF32 top = displayViewport.m_Y + displayViewport.m_Height;
+ QT3DSF32 bottom = displayViewport.m_Y;
+ if (thePickPoint.x < left || thePickPoint.x > right || thePickPoint.y < bottom
+ || thePickPoint.y > top)
+ return PickTargetAreas::Matte;
+ return PickTargetAreas::Presentation;
+}
diff --git a/src/Authoring/Studio/Render/StudioRendererTranslation.h b/src/Authoring/Studio/Render/StudioRendererTranslation.h
new file mode 100644
index 00000000..7698d8ec
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioRendererTranslation.h
@@ -0,0 +1,691 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_RENDERER_TRANSLATION_H
+#define UIC_STUDIO_RENDERER_TRANSLATION_H
+#pragma once
+#include "StudioRendererImpl.h"
+#include "UICRenderLayer.h"
+#include "UICRenderer.h"
+#include "StudioWidget.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "foundation/FastAllocator.h"
+#include "StudioPickValues.h"
+#include "UICDMGuides.h"
+#include "PathWidget.h"
+#include "StudioPreferences.h"
+
+namespace uic {
+namespace studio {
+ struct SGraphObjectTranslator;
+ extern QT3DSU32 g_GraphObjectTranslatorTag;
+ inline void InitializePointerTags(IStringTable &) { g_GraphObjectTranslatorTag = 0x0088BEEF; }
+}
+}
+namespace uic {
+namespace render {
+ template <>
+ struct SPointerTag<uic::studio::SGraphObjectTranslator>
+ {
+ static QT3DSU32 GetTag() { return uic::studio::g_GraphObjectTranslatorTag; }
+ };
+}
+}
+
+namespace uic {
+namespace studio {
+
+ typedef std::shared_ptr<UICDM::ISignalConnection> TSignalConnection;
+
+ struct STranslation;
+
+ struct SGraphObjectTranslator
+ {
+ protected:
+ UICDM::CUICDMInstanceHandle m_InstanceHandle;
+
+ public:
+ // This will never be null. The reason it is a pointer is because
+ // alias translators need to switch which graph object they point to
+ UICDM::CUICDMInstanceHandle m_AliasInstanceHandle;
+ SGraphObject *m_GraphObject;
+ QT3DSU32 m_DirtyIndex;
+ SGraphObjectTranslator(UICDM::CUICDMInstanceHandle inInstance, SGraphObject &inObj)
+ : m_InstanceHandle(inInstance)
+ , m_GraphObject(&inObj)
+ , m_DirtyIndex(QT3DS_MAX_U32)
+ {
+ m_GraphObject->m_UserData = uic::render::STaggedPointer(this);
+ }
+ // The destructors will not be called at this time for most of the objects
+ // but they will be released.
+ virtual ~SGraphObjectTranslator() {}
+ // Push new data into the UIC render graph.
+ virtual void PushTranslation(STranslation &inTranslatorContext);
+ virtual void AfterRenderGraphIsBuilt(STranslation &) {}
+ virtual void SetActive(bool inActive) = 0;
+ virtual void ClearChildren() = 0;
+ virtual void AppendChild(SGraphObject &inChild) = 0;
+ virtual SGraphObject &GetGraphObject() { return *m_GraphObject; }
+ virtual SGraphObject &GetNonAliasedGraphObject() { return *m_GraphObject; }
+ virtual UICDM::CUICDMInstanceHandle GetInstanceHandle() { return m_InstanceHandle; }
+ virtual UICDM::CUICDMInstanceHandle GetSceneGraphInstanceHandle()
+ {
+ return m_InstanceHandle;
+ }
+ virtual UICDM::CUICDMInstanceHandle GetPossiblyAliasedInstanceHandle()
+ {
+ if (m_AliasInstanceHandle.Valid())
+ return m_AliasInstanceHandle;
+ return GetInstanceHandle();
+ }
+ };
+
+ struct STranslatorGetDirty
+ {
+ QT3DSU32 operator()(const SGraphObjectTranslator &inTrans) const
+ {
+ return inTrans.m_DirtyIndex;
+ }
+ };
+ struct STranslatorSetDirty
+ {
+ void operator()(SGraphObjectTranslator &inTrans, QT3DSU32 idx) const
+ {
+ inTrans.m_DirtyIndex = idx;
+ }
+ };
+
+ typedef InvasiveSet<SGraphObjectTranslator, STranslatorGetDirty, STranslatorSetDirty>
+ TTranslatorDirtySet;
+
+ struct TranslationSelectMode
+ {
+ enum Enum {
+ Group = 0,
+ Single = 1,
+ NestedComponentSingle,
+ };
+ };
+
+ struct EditCameraTypes
+ {
+ enum Enum {
+ SceneCamera = 0,
+ Perspective,
+ Orthographic,
+ Directional,
+ };
+ };
+
+ const QT3DSF32 g_EditCameraFOV = 45.0f;
+ const QT3DSF32 g_RotationScaleFactor = 2 * M_PI / 180.0f;
+
+ struct SEditCameraPersistentInformation
+ {
+ QT3DSVec3 m_Position;
+ QT3DSVec3 m_Direction;
+ QT3DSF32 m_ViewRadius;
+ EditCameraTypes::Enum m_CameraType;
+ QT3DSQuat m_Rotation;
+ SEditCameraPersistentInformation()
+ : m_Position(0, 0, 0)
+ , m_Direction(0, 0, 0)
+ , m_ViewRadius(600)
+ , m_CameraType(EditCameraTypes::Perspective)
+ , m_Rotation(QT3DSQuat::createIdentity())
+ {
+ }
+
+ void ApplyToCamera(SCamera &inCamera, QT3DSVec2 inViewport)
+ {
+ // Setup shared default values.
+ inCamera.m_ClipFar = 2000000.0f;
+ inCamera.m_ClipNear = 1.0f;
+ if (m_CameraType == EditCameraTypes::Perspective) {
+ inCamera.m_FOV = g_EditCameraFOV;
+ TORAD(inCamera.m_FOV);
+ inCamera.m_Flags.SetOrthographic(false);
+ } else
+ inCamera.m_Flags.SetOrthographic(true);
+
+ QT3DSVec3 theDirection = m_Direction;
+ theDirection.normalize();
+
+ // The goal is to setup a global transform that
+ QT3DSMat44 thePivotMatrix = QT3DSMat44::createIdentity();
+ thePivotMatrix.column3.x = m_Position.x;
+ thePivotMatrix.column3.y = m_Position.y;
+ thePivotMatrix.column3.z = m_Position.z;
+ QT3DSMat44 theGlobalTransform = thePivotMatrix;
+
+ QT3DSVec3 theUpDir(QT3DSVec3(0, 1, 0));
+ QT3DSF32 theTestLen = theDirection.cross(theUpDir).magnitudeSquared();
+ if (theTestLen < .01f)
+ theUpDir = QT3DSVec3(0, 0, 1) * theDirection.dot(QT3DSVec3(0, 1, 0));
+ theUpDir.normalize();
+ QT3DSMat33 theLookAtMatrix = inCamera.GetLookAtMatrix(theUpDir, theDirection);
+ QT3DSMat33 theFinalMatrix = theLookAtMatrix * QT3DSMat33(m_Rotation);
+ QT3DSMat44 theRotationTransform = QT3DSMat44(theFinalMatrix.column0, theFinalMatrix.column1,
+ theFinalMatrix.column2, QT3DSVec3(0, 0, 0));
+
+ // The view radius dictates the zoom.
+ QT3DSF32 theZoom = 1.0f;
+ if (inCamera.m_Flags.IsOrthographic()) {
+ QT3DSF32 theViewport = NVMin(inViewport.x, inViewport.y);
+ theZoom = (m_ViewRadius * 2.0f) / theViewport;
+ } else {
+ // We know the hypotenuse is 600.
+ // So if we want to zoom the scene, we do this.
+ theZoom = m_ViewRadius / (sinf(inCamera.m_FOV / 2.0f) * 600.f);
+ }
+ QT3DSMat44 theScaleMatrix = QT3DSMat44(QT3DSVec4(theZoom, theZoom, theZoom, 1));
+ QT3DSMat44 thePositionMatrix = QT3DSMat44::createIdentity();
+ thePositionMatrix.column3.x = m_Position.x;
+ thePositionMatrix.column3.y = m_Position.y;
+ thePositionMatrix.column3.z = m_Position.z + 600;
+ theGlobalTransform = theGlobalTransform * theRotationTransform;
+ theGlobalTransform = theGlobalTransform * theScaleMatrix;
+ theGlobalTransform = theGlobalTransform * thePivotMatrix.getInverse();
+ theGlobalTransform = theGlobalTransform * thePositionMatrix;
+ // This works because the camera has no hierarchy.
+ inCamera.m_LocalTransform = theGlobalTransform;
+ inCamera.m_Flags.SetTransformDirty(false);
+ inCamera.MarkDirty(uic::render::NodeTransformDirtyFlag::TransformNotDirty);
+ }
+
+ bool IsOrthographic() const { return m_CameraType != EditCameraTypes::Perspective; }
+
+ bool SupportsRotation() const { return m_CameraType != EditCameraTypes::Directional; }
+ };
+ struct MovementTypes
+ {
+ enum Enum {
+ Unknown = 0,
+ Translate,
+ TranslateAlongCameraDirection,
+ Scale,
+ ScaleZ,
+ Rotation,
+ RotationAboutCameraDirection,
+ };
+ };
+
+ struct SEditCameraLayerTranslator;
+ struct SZoomRender
+ {
+ CPt m_Point;
+ uic::render::SLayer *m_Layer;
+ SZoomRender(CPt inPoint, uic::render::SLayer *inLayer)
+ : m_Point(inPoint)
+ , m_Layer(inLayer)
+ {
+ }
+ SZoomRender()
+ : m_Layer(nullptr)
+ {
+ }
+ };
+
+ struct PickTargetAreas
+ {
+ enum Enum {
+ Presentation,
+ Matte,
+ };
+ };
+
+ struct SRulerRect
+ {
+ QT3DSI32 m_Left;
+ QT3DSI32 m_Top;
+ QT3DSI32 m_Right;
+ QT3DSI32 m_Bottom;
+ SRulerRect()
+ : m_Left(0)
+ , m_Top(0)
+ , m_Right(0)
+ , m_Bottom(0)
+ {
+ }
+ SRulerRect(QT3DSI32 l, QT3DSI32 t, QT3DSI32 r, QT3DSI32 b)
+ : m_Left(l)
+ , m_Top(t)
+ , m_Right(r)
+ , m_Bottom(b)
+ {
+ }
+ bool Contains(QT3DSI32 x, QT3DSI32 y) const
+ {
+ return x >= m_Left && x <= m_Right && y >= m_Bottom && y <= m_Top;
+ }
+ };
+
+ struct SDragPreparationResult
+ {
+ uic::render::IUICRenderer *m_Renderer;
+ SNode *m_Node;
+ SLayer *m_Layer;
+ SCamera *m_Camera;
+ qt3ds::render::NVPlane m_Plane;
+ QT3DSVec3 m_GlobalPos;
+ QT3DSVec3 m_CameraGlobalPos;
+ QT3DSVec3 m_CameraDirection;
+ QT3DSVec3 m_Axis;
+ QT3DSMat44 m_GlobalTransform;
+ QT3DSMat33 m_NormalMatrix;
+ QT3DSU32 m_AxisIndex;
+ uic::widgets::StudioWidgetComponentIds::Enum m_ComponentId;
+ uic::widgets::StudioWidgetTypes::Enum m_WidgetType;
+ uic::render::RenderWidgetModes::Enum m_WidgetMode;
+ SRay m_OriginalRay;
+ SRay m_CurrentRay;
+ SRay m_PreviousRay;
+ Option<QT3DSVec3> m_OriginalPlaneCoords;
+ Option<QT3DSVec3> m_CurrentPlaneCoords;
+ Option<QT3DSVec3> m_PreviousPlaneCoords;
+ bool m_IsPlane;
+ SDragPreparationResult() {}
+ };
+
+ struct SPathAnchorDragInitialValue
+ {
+ QT3DSVec2 m_Position;
+ float m_IncomingAngle;
+ float m_IncomingDistance;
+ float m_OutgoingDistance;
+ SPathAnchorDragInitialValue() {}
+ };
+
+ struct STranslation : public uic::render::IUICRenderNodeFilter
+ {
+ typedef eastl::pair<UICDM::CUICDMInstanceHandle, SGraphObjectTranslator *>
+ THandleTranslatorPair;
+ typedef eastl::vector<THandleTranslatorPair> THandleTranslatorPairList;
+ // Now that we have aliases, one instance handle can map to several translators. One
+ // translator, however, only
+ // maps to one instance handle.
+ typedef nvhash_map<UICDM::CUICDMInstanceHandle, THandleTranslatorPairList, eastl::hash<int>>
+ TInstanceToTranslatorMap;
+ IStudioRenderer &m_Renderer;
+ IUICRenderContext &m_UICContext;
+ CDoc &m_Doc;
+ IDocumentReader &m_Reader;
+ SComposerObjectDefinitions &m_ObjectDefinitions;
+ UICDM::CStudioSystem &m_StudioSystem;
+ UICDM::CStudioFullSystem &m_FullSystem;
+ Q3DStudio::CGraph &m_AssetGraph;
+
+ // allocator for scene graph and translators
+ qt3ds::foundation::SSAutoDeallocatorAllocator m_Allocator;
+ // All translator related containers must come after the allocator
+ TInstanceToTranslatorMap m_TranslatorMap;
+ TTranslatorDirtySet m_DirtySet;
+ uic::render::SPresentation m_Presentation;
+ uic::render::SScene *m_Scene;
+ Q3DStudio::CGraphIterator m_GraphIterator;
+ nvvector<TSignalConnection> m_SignalConnections;
+ QT3DSI32 m_ComponentSecondsDepth;
+ SNode m_MouseDownNode;
+ SCamera m_MouseDownCamera;
+ Option<QT3DSMat44> m_MouseDownParentGlobalTransformInverse;
+ Option<QT3DSMat33> m_MouseDownParentRotationInverse;
+ Option<QT3DSMat33> m_MouseDownGlobalRotation;
+ QT3DSI32 m_KeyRepeat;
+ bool m_EditCameraEnabled;
+ bool m_EditLightEnabled;
+ SEditCameraPersistentInformation m_EditCameraInfo;
+ SCamera m_EditCamera;
+ SLight m_EditLight;
+ QT3DSVec2 m_Viewport;
+ SEditCameraLayerTranslator *m_EditCameraLayerTranslator;
+ Option<SZoomRender> m_ZoomRender;
+ NVScopedRefCounted<uic::widgets::IStudioWidget> m_TranslationWidget;
+ NVScopedRefCounted<uic::widgets::IStudioWidget> m_RotationWidget;
+ NVScopedRefCounted<uic::widgets::IStudioWidget> m_ScaleWidget;
+ NVScopedRefCounted<uic::widgets::IStudioWidget> m_LastRenderedWidget;
+ NVScopedRefCounted<uic::widgets::IPathWidget> m_PathWidget;
+ NVScopedRefCounted<qt3ds::render::NVRenderTexture2D> m_PickBuffer;
+ Option<SPathAnchorDragInitialValue> m_LastPathDragValue;
+ nvvector<qt3ds::QT3DSU8> m_PixelBuffer;
+ QT3DSF32 m_CumulativeRotation;
+ eastl::vector<uic::render::SPGGraphObject *> m_GuideContainer;
+ qt3ds::foundation::SFastAllocator<> m_GuideAllocator;
+ // The rects are maintained from last render because the render context
+ // doesn't guarantee the rects it returns are valid outside of begin/end render calls.
+ SRulerRect m_OuterRect;
+ SRulerRect m_InnerRect; // presentation rect.
+
+ QT3DSVec4 m_rectColor;
+ QT3DSVec4 m_lineColor;
+ QT3DSVec4 m_guideColor;
+ QT3DSVec4 m_selectedGuideColor;
+ QT3DSVec4 m_guideFillColor;
+ QT3DSVec4 m_selectedGuideFillColor;
+
+ STranslation(IStudioRenderer &inRenderer, IUICRenderContext &inContext);
+ void MarkBeginComponentSeconds(UICDM::CUICDMSlideHandle) { ++m_ComponentSecondsDepth; }
+
+ void MarkComponentSeconds(UICDM::CUICDMSlideHandle)
+ {
+ m_ComponentSecondsDepth = NVMax(0, m_ComponentSecondsDepth - 1);
+ if (m_ComponentSecondsDepth == 0)
+ RequestRender();
+ }
+
+ void ReleaseTranslation(Q3DStudio::TIdentifier inInstance);
+
+ void MarkGraphInstanceDirty(Q3DStudio::TIdentifier inInstance,
+ Q3DStudio::TIdentifier /*inParent*/)
+ {
+ MarkDirty(inInstance);
+ }
+
+ void MarkDirty(UICDM::CUICDMInstanceHandle inInstance);
+
+ void MarkDirty(UICDM::CUICDMInstanceHandle *inInstance, long inInstanceCount)
+ {
+ for (long idx = 0; idx < inInstanceCount; ++idx)
+ MarkDirty(inInstance[idx]);
+ }
+
+ void DrawBoundingBox(SNode &inNode, QT3DSVec3 inColor);
+ void DrawLightBoundingBox(SNode &inNode, QT3DSVec3 inColor);
+
+ void DrawChildBoundingBoxes(SNode &inNode)
+ {
+ ::CColor color = CStudioPreferences::GetGroupBoundingBoxColor();
+ QT3DSVec3 colorVec(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f);
+ for (SNode *theChild = inNode.m_FirstChild; theChild;
+ theChild = theChild->m_NextSibling) {
+ if (IncludeNode(*theChild))
+ DrawBoundingBox(*theChild, colorVec);
+ }
+ }
+
+ void DrawGroupBoundingBoxes(SGraphObjectTranslator &inTranslator)
+ {
+ SNode &theNode = static_cast<SNode &>(inTranslator.GetGraphObject());
+ if (theNode.m_FirstChild) {
+ ::CColor color = CStudioPreferences::GetGroupBoundingBoxColor();
+ QT3DSVec3 colorVec(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f);
+ DrawBoundingBox(theNode, colorVec);
+ if (inTranslator.GetGraphObject().m_Type != GraphObjectTypes::Layer)
+ DrawChildBoundingBoxes(theNode);
+ }
+ }
+
+ void DrawNonGroupBoundingBoxes(SGraphObjectTranslator &inTranslator)
+ {
+ SNode &theNode = static_cast<SNode &>(inTranslator.GetGraphObject());
+ if (inTranslator.GetGraphObject().m_Type == GraphObjectTypes::Light) {
+ ::CColor color = CStudioPreferences::GetLightBoundingBoxColor();
+ QT3DSVec3 colorVec(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f);
+ DrawLightBoundingBox(theNode, colorVec);
+ } else if (inTranslator.GetGraphObject().m_Type != GraphObjectTypes::Layer) {
+ ::CColor color = CStudioPreferences::GetSingleBoundingBoxColor();
+ QT3DSVec3 colorVec(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f);
+ DrawBoundingBox(theNode, colorVec);
+ DrawChildBoundingBoxes(theNode);
+ } else {
+ ::CColor color = CStudioPreferences::GetSingleBoundingBoxColor();
+ QT3DSVec3 colorVec(color.GetRed() / 255.f,
+ color.GetGreen() / 255.f,
+ color.GetBlue() / 255.f);
+ m_UICContext.GetRenderer().RenderLayerRect(
+ static_cast<SLayer &>(inTranslator.GetGraphObject()), colorVec);
+ }
+ }
+
+ void DrawAxis(SGraphObjectTranslator &inTranslator);
+
+ void SetViewport(QT3DSF32 inWidth, QT3DSF32 inHeight) { m_Viewport = QT3DSVec2(inWidth, inHeight); }
+
+ QT3DSVec2 GetViewportDimensions() { return m_Viewport; }
+
+ void ClearDirtySet()
+ {
+ // The dirty set may be modified while this operation is taking place in the case of
+ // alias nodes.
+ for (qt3ds::QT3DSU32 idx = 0; idx < (qt3ds::QT3DSU32)m_DirtySet.size(); ++idx) {
+ if (m_Reader.IsInstance(m_DirtySet[idx]->GetInstanceHandle()))
+ m_DirtySet[idx]->PushTranslation(*this);
+ }
+ m_DirtySet.clear();
+ }
+ // We build the render graph every time we render. This may seem wasteful
+ void BuildRenderGraph(UICDM::CUICDMInstanceHandle inParent,
+ CUICDMInstanceHandle inAliasHandle = UICDM::CUICDMInstanceHandle());
+ void
+ BuildRenderGraph(SGraphObjectTranslator &inParent,
+ UICDM::CUICDMInstanceHandle inAliasHandle = UICDM::CUICDMInstanceHandle());
+ void
+ DeactivateScan(SGraphObjectTranslator &inParent,
+ UICDM::CUICDMInstanceHandle inAliasHandle = UICDM::CUICDMInstanceHandle());
+ void PreRender();
+ void Render(int inWidgetId, bool inDrawGuides);
+ void EndRender();
+ void DoPrepareForDrag(SNode *inSelectedNode);
+ void ResetWidgets();
+ void EndDrag();
+ bool IsPathWidgetActive();
+
+ void PrepareForDrag() { DoPrepareForDrag(GetSelectedNode()); }
+
+ SStudioPickValue Pick(CPt inMouseCoords, TranslationSelectMode::Enum inSelectMode);
+ Option<QT3DSU32> PickWidget(CPt inMouseCoords, TranslationSelectMode::Enum inSelectMode,
+ uic::widgets::IStudioWidgetBase &inWidget);
+
+ qt3ds::foundation::Option<UICDM::SGuideInfo> PickRulers(CPt inMouseCoords);
+
+ SNode *GetSelectedNode()
+ {
+ UICDM::CUICDMInstanceHandle theHandle = m_Doc.GetSelectedInstance();
+ SGraphObjectTranslator *theTranslator = GetOrCreateTranslator(theHandle);
+ if (theTranslator
+ && GraphObjectTypes::IsNodeType(theTranslator->GetGraphObject().m_Type))
+ return static_cast<SNode *>(&theTranslator->GetGraphObject());
+ return nullptr;
+ }
+ static inline SFloat3 ToDataModel(const QT3DSVec3 &inValue)
+ {
+ return SFloat3(inValue.x, inValue.y, inValue.z);
+ }
+
+ static inline SFloat3 ToDataModelRotation(const QT3DSVec3 &inValue)
+ {
+ SFloat3 retval = ToDataModel(inValue);
+ TODEG(retval.m_Floats[0]);
+ TODEG(retval.m_Floats[1]);
+ TODEG(retval.m_Floats[2]);
+ return retval;
+ }
+
+ void SetPosition(const QT3DSVec3 &inPosition, CUpdateableDocumentEditor &inEditor)
+ {
+ inEditor.EnsureEditor(L"Set Position", __FILE__, __LINE__)
+ .SetInstancePropertyValue(m_Doc.GetSelectedInstance(),
+ m_ObjectDefinitions.m_Node.m_Position,
+ ToDataModel(inPosition));
+ inEditor.FireImmediateRefresh(m_Doc.GetSelectedInstance());
+ }
+ void SetRotation(const QT3DSVec3 &inRotation, CUpdateableDocumentEditor &inEditor)
+ {
+ inEditor.EnsureEditor(L"Set Rotation", __FILE__, __LINE__)
+ .SetInstancePropertyValue(m_Doc.GetSelectedInstance(),
+ m_ObjectDefinitions.m_Node.m_Rotation,
+ ToDataModelRotation(inRotation));
+ inEditor.FireImmediateRefresh(m_Doc.GetSelectedInstance());
+ }
+ void SetScale(const QT3DSVec3 &inScale, CUpdateableDocumentEditor &inEditor)
+ {
+ inEditor.EnsureEditor(L"Set Scale", __FILE__, __LINE__)
+ .SetInstancePropertyValue(m_Doc.GetSelectedInstance(),
+ m_ObjectDefinitions.m_Node.m_Scale, ToDataModel(inScale));
+ inEditor.FireImmediateRefresh(m_Doc.GetSelectedInstance());
+ }
+
+ QT3DSVec3 GetIntendedPosition(UICDM::CUICDMInstanceHandle inInstance, CPt inPos);
+
+ void ApplyPositionalChange(QT3DSVec3 inDiff, SNode &inNode,
+ CUpdateableDocumentEditor &inEditor);
+
+ void TranslateSelectedInstanceAlongCameraDirection(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor);
+
+ void TranslateSelectedInstance(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor, bool inLockToAxis);
+
+ void ScaleSelectedInstanceZ(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor);
+
+ void ScaleSelectedInstance(CPt inOriginalCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor);
+
+ void CalculateNodeGlobalRotation(SNode &inNode);
+
+ void ApplyRotationToSelectedInstance(const QT3DSQuat &inFinalRotation, SNode &inNode,
+ CUpdateableDocumentEditor &inEditor,
+ bool inIsMouseRelative = true);
+
+ void RotateSelectedInstanceAboutCameraDirectionVector(CPt inPreviousMouseCoords,
+ CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor);
+
+ // This method never feels right to me. It is difficult to apply it to a single axis (of
+ // course for that
+ // you can use the inspector palette).
+ void RotateSelectedInstance(CPt inOriginalCoords, CPt inPreviousMouseCoords,
+ CPt inMouseCoords, CUpdateableDocumentEditor &inEditor,
+ bool inLockToAxis);
+
+ Option<SDragPreparationResult>
+ PrepareWidgetDrag(uic::widgets::StudioWidgetComponentIds::Enum inComponentId,
+ uic::widgets::StudioWidgetTypes::Enum inWidgetId,
+ uic::render::RenderWidgetModes::Enum inWidgetMode, SNode &inNode,
+ CPt inOriginalCoords, CPt inPreviousMouseCoords, CPt inMouseCoords);
+
+ void PerformWidgetDrag(int inWidgetSubComponent, CPt inOriginalCoords,
+ CPt inPreviousMouseCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor);
+
+ void PerformGuideDrag(CUICDMGuideHandle inGuide, CPt inPoint,
+ CUpdateableDocumentEditor &inEditor);
+ void CheckGuideInPresentationRect(CUICDMGuideHandle inGuide,
+ CUpdateableDocumentEditor &inEditor);
+
+ void PerformPathDrag(uic::studio::SPathPick &inPathPick, CPt inOriginalCoords,
+ CPt inPreviousMouseCoords, CPt inMouseCoords,
+ CUpdateableDocumentEditor &inEditor);
+
+ // Pulled directly from old studio's Node.cpp.
+ void OnNudge(ENudgeDirection inDirection, int inToolmode, int inFlags,
+ CUpdateableDocumentEditor &inEditor);
+
+ void OnNudgeFinished() { m_KeyRepeat = 0; }
+
+ void RequestRender()
+ {
+ if (m_ComponentSecondsDepth == 0)
+ m_Renderer.RequestRender();
+ }
+
+ void RenderZoomRender(SZoomRender &inRender);
+
+ // IUICRenderNodeFilter
+ bool IncludeNode(const SNode &inNode) override;
+
+ PickTargetAreas::Enum GetPickArea(CPt inPoint);
+
+ SNode *GetEditCameraLayer();
+
+ void ReleaseEffect(UICDM::CUICDMInstanceHandle inInstance);
+ // Create a new translator for this type. Do not add to any maps or anything else.
+ SGraphObjectTranslator *CreateTranslator(UICDM::CUICDMInstanceHandle inInstance);
+ // Returns the canonical translator for a given instance or creates a new translator if none
+ // exist.
+ SGraphObjectTranslator *GetOrCreateTranslator(UICDM::CUICDMInstanceHandle inInstance);
+ // Create a new aliased translator for this type.
+ SGraphObjectTranslator *GetOrCreateTranslator(UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMInstanceHandle inAliasInstance);
+ THandleTranslatorPairList &
+ GetTranslatorsForInstance(UICDM::CUICDMInstanceHandle inInstance);
+ UICDM::CUICDMInstanceHandle GetAnchorPoint(SPathPick &inPick);
+ UICDM::CUICDMInstanceHandle GetAnchorPoint(QT3DSU32 inAnchorIndex);
+ };
+
+ struct SDisableUseClearColor
+ {
+ SGraphObjectTranslator *m_SceneTranslator;
+ bool m_PreviousUseClearColor;
+ bool m_DisableUseClearColor;
+
+ SDisableUseClearColor(STranslation &inTranslation, bool disableUseClearColor)
+ : m_SceneTranslator(nullptr)
+ , m_PreviousUseClearColor(false)
+ , m_DisableUseClearColor(disableUseClearColor)
+ {
+ if (m_DisableUseClearColor) {
+ TIdentifier theRoot = inTranslation.m_AssetGraph.GetRoot(0);
+ m_SceneTranslator = inTranslation.GetOrCreateTranslator(theRoot);
+ if (m_SceneTranslator) {
+ SScene &theScene = static_cast<SScene &>(m_SceneTranslator->GetGraphObject());
+ m_PreviousUseClearColor = theScene.m_UseClearColor;
+ SetUseClearColor(false);
+ }
+ }
+ }
+
+ ~SDisableUseClearColor()
+ {
+ if (m_DisableUseClearColor) {
+ SetUseClearColor(m_PreviousUseClearColor);
+ }
+ }
+
+ void SetUseClearColor(bool inUseClearColor)
+ {
+ if (m_SceneTranslator) {
+ SScene &theScene = static_cast<SScene &>(m_SceneTranslator->GetGraphObject());
+ theScene.m_UseClearColor = inUseClearColor;
+ }
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Render/StudioRotationWidget.cpp b/src/Authoring/Studio/Render/StudioRotationWidget.cpp
new file mode 100644
index 00000000..813cf7ac
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioRotationWidget.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "StudioWidgetImpl.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "UICRenderNode.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderCamera.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "StudioUtils.h"
+
+using namespace uic::widgets;
+
+namespace {
+
+struct SRotationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Rotation>
+{
+ typedef SStudioWidgetImpl<StudioWidgetTypes::Rotation> TBase;
+ NVRenderInputAssembler *m_XAxis;
+ NVRenderInputAssembler *m_YAxis;
+ NVRenderInputAssembler *m_ZAxis;
+ NVRenderInputAssembler *m_CameraAxis;
+ // We use a rect to clear the Z buffer.
+ NVRenderInputAssembler *m_CameraRect;
+
+ NVRenderShaderProgram *m_ZClearShader;
+
+ volatile QT3DSI32 mRefCount;
+
+ SRotationWidget(NVAllocatorCallback &inAlloc)
+ : TBase(inAlloc)
+ , m_XAxis(nullptr)
+ , m_YAxis(nullptr)
+ , m_ZAxis(nullptr)
+ , m_CameraAxis(nullptr)
+ , m_CameraRect(nullptr)
+ , m_ZClearShader(nullptr)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+
+ NVRenderInputAssembler *CreateRing(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, QT3DSVec3 inDirection,
+ QT3DSF32 inInnerRadius, QT3DSF32 inOuterRadius, QT3DSF32 inRingColor,
+ const char *inRingName)
+ {
+ QT3DS_ASSERT(inInnerRadius <= inOuterRadius);
+ CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inRingName);
+ NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName);
+ if (retval) {
+ return retval;
+ }
+
+ TResultVecType theVertexData(m_Allocator, "SRotationWidget::theVertexData");
+
+ QT3DSI32 numSubDivisions = 50;
+ QT3DSF32 arcRad = 360.0f / (QT3DSF32)numSubDivisions;
+ TORAD(arcRad);
+ QT3DSVec3 tempCross = inDirection.cross(QT3DSVec3(0, 1, 0));
+ if (tempCross.magnitudeSquared() < .05f)
+ tempCross = inDirection.cross(QT3DSVec3(1, 0, 0));
+
+ QT3DSVec3 upDir = inDirection.cross(tempCross);
+ QT3DSVec3 leftDir = upDir.cross(inDirection);
+ upDir.normalize();
+ leftDir.normalize();
+
+ QT3DSF32 ringWidth = inOuterRadius - inInnerRadius;
+ QT3DSF32 ringHalfWidth = ringWidth / 2.0f;
+ QT3DSF32 middleRadius = inInnerRadius + ringHalfWidth;
+
+ for (QT3DSI32 idx = 0, numLooper = numSubDivisions; idx < numLooper; ++idx) {
+ QT3DSF32 startDeg = idx * 360.0f / numSubDivisions;
+ QT3DSF32 endDeg = (idx + 1) * 360.0f / numSubDivisions;
+ QT3DSF32 startRad(startDeg);
+ QT3DSF32 endRad(endDeg);
+ TORAD(startRad);
+ TORAD(endRad);
+ QT3DSF32 startSin = NVSin(startRad);
+ QT3DSF32 endSin = NVSin(endRad);
+ QT3DSF32 startCos = NVCos(startRad);
+ QT3DSF32 endCos = NVCos(endRad);
+
+ QT3DSVec3 startDir = startSin * upDir + startCos * leftDir;
+ QT3DSVec3 endDir = endSin * upDir + endCos * leftDir;
+
+ QT3DSVec3 discStart = startDir * inInnerRadius;
+ QT3DSVec3 discEnd = endDir * inInnerRadius;
+ QT3DSVec3 ringStart = startDir * inOuterRadius;
+ QT3DSVec3 ringEnd = endDir * inOuterRadius;
+
+ QT3DSVec3 middleStart = startDir * (middleRadius);
+ QT3DSVec3 middleEnd = endDir * (middleRadius);
+ QT3DSVec3 middleTopLeft = middleStart + inDirection * ringHalfWidth;
+ QT3DSVec3 middleTopRight = middleStart - inDirection * ringHalfWidth;
+ QT3DSVec3 middleBottomLeft = middleEnd + inDirection * ringHalfWidth;
+ QT3DSVec3 middleBottomRight = middleEnd - inDirection * ringHalfWidth;
+
+ // Now two tris for the ring
+ theVertexData.push_back(QT3DSVec4(discStart, inRingColor));
+ theVertexData.push_back(QT3DSVec4(ringStart, inRingColor));
+ theVertexData.push_back(QT3DSVec4(ringEnd, inRingColor));
+ theVertexData.push_back(QT3DSVec4(ringEnd, inRingColor));
+ theVertexData.push_back(QT3DSVec4(discEnd, inRingColor));
+ theVertexData.push_back(QT3DSVec4(discStart, inRingColor));
+ // Two tris for the ring that is perpendicular to the viewer
+ theVertexData.push_back(QT3DSVec4(middleTopLeft, inRingColor));
+ theVertexData.push_back(QT3DSVec4(middleTopRight, inRingColor));
+ theVertexData.push_back(QT3DSVec4(middleBottomRight, inRingColor));
+ theVertexData.push_back(QT3DSVec4(middleBottomRight, inRingColor));
+ theVertexData.push_back(QT3DSVec4(middleBottomLeft, inRingColor));
+ theVertexData.push_back(QT3DSVec4(middleTopLeft, inRingColor));
+ }
+
+ QT3DSU32 stride;
+ QT3DSU32 offset = 0;
+ NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout(
+ IStudioWidget::GetVertexBufferAttributesAndStride(stride));
+ NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer(
+ theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size()));
+ retval = &inWidgetContext.GetOrCreateInputAssembler(
+ theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr,
+ toConstDataRef(&stride, 1), toConstDataRef(&offset, 1));
+
+ return retval;
+ }
+
+ NVRenderInputAssembler *CreateRect(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, QT3DSVec3 inDirection,
+ QT3DSF32 inHalfWidth, const char *inItemName)
+ {
+ CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inItemName);
+ NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName);
+ if (retval) {
+ return retval;
+ }
+
+ QT3DSVec3 tempCross = inDirection.cross(QT3DSVec3(0, 1, 0));
+ if (tempCross.magnitudeSquared() < .05f)
+ tempCross = inDirection.cross(QT3DSVec3(1, 0, 0));
+
+ QT3DSVec3 upDir = inDirection.cross(tempCross);
+ QT3DSVec3 leftDir = upDir.cross(inDirection);
+
+ TResultVecType theVertexData(m_Allocator, "SRotationWidget::theVertexData");
+
+ theVertexData.push_back(QT3DSVec4(upDir * inHalfWidth, 0.0f));
+ theVertexData.push_back(QT3DSVec4(leftDir * inHalfWidth, 0.0f));
+ theVertexData.push_back(QT3DSVec4(upDir * -1.0f * inHalfWidth, 0.0f));
+
+ theVertexData.push_back(QT3DSVec4(upDir * -1.0f * inHalfWidth, 0.0f));
+ theVertexData.push_back(QT3DSVec4(leftDir * -1.0f * inHalfWidth, 0.0f));
+ theVertexData.push_back(QT3DSVec4(upDir * inHalfWidth, 0.0f));
+
+ QT3DSU32 stride;
+ QT3DSU32 offset = 0;
+ NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout(
+ IStudioWidget::GetVertexBufferAttributesAndStride(stride));
+ NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer(
+ theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size()));
+
+ retval = &inWidgetContext.GetOrCreateInputAssembler(
+ theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr,
+ toConstDataRef(&stride, 1), toConstDataRef(&offset, 1));
+ return retval;
+ }
+
+ NVRenderShaderProgram *CreateZClearShader(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext,
+ const char *inItemName)
+ {
+ CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inItemName);
+ NVRenderShaderProgram *retval = inWidgetContext.GetShader(theItemName);
+ if (retval) {
+ return retval;
+ }
+
+ uic::render::IShaderProgramGenerator &theGenerator(inWidgetContext.GetProgramGenerator());
+ theGenerator.BeginProgram();
+ uic::render::IShaderStageGenerator &theVertexGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Vertex));
+ uic::render::IShaderStageGenerator &theFragmentGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddUniform("model_view_projection", "mat4");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tgl_FragColor.rgb = vec3(0.0, 0.0, 0.0);");
+ theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;");
+ theFragmentGenerator.Append("}");
+ return inWidgetContext.CompileAndStoreShader(theItemName);
+ }
+
+ static inline QT3DSVec3 ToFixedCameraPos(const QT3DSVec3 &inCameraPos, const SCamera &inCamera)
+ {
+ if (inCamera.m_Flags.IsOrthographic()) {
+ return QT3DSVec3(inCameraPos.x, inCameraPos.y, -600.f);
+ }
+ QT3DSF32 multiplier = -600.f / inCameraPos.z;
+ return inCameraPos * multiplier;
+ }
+
+ void Render(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext) override
+ {
+ // Widgets have to clear the depth buffer; they shouldn't interact with other components
+ // but they should self-occlude.
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ inRenderContext.SetBlendFunction(qt3ds::render::NVRenderBlendFunctionArgument(
+ qt3ds::render::NVRenderSrcBlendFunc::SrcAlpha,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ qt3ds::render::NVRenderSrcBlendFunc::One,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha));
+ inRenderContext.SetBlendEquation(qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add));
+
+ float pixelRatio = float(devicePixelRatio());
+ QT3DSF32 theRingRadius = 100.0f * pixelRatio;
+ QT3DSF32 theRingWidth = 2.0f * pixelRatio;
+ QT3DSF32 theRingInner = theRingRadius;
+ QT3DSF32 theRingOuter = theRingRadius + theRingWidth;
+ if (m_XAxis == nullptr) {
+ TBase::SetupRender(inWidgetContext, inRenderContext);
+ m_PickShader = IStudioWidget::CreateWidgetPickShader(inWidgetContext, inRenderContext);
+ ;
+ m_XAxis = CreateRing(inWidgetContext, inRenderContext, QT3DSVec3(-1, 0, 0), theRingInner,
+ theRingOuter, 0.0f, "RotationWidgetXAxis");
+ m_YAxis = CreateRing(inWidgetContext, inRenderContext, QT3DSVec3(0, -1, 0), theRingInner,
+ theRingOuter, 0.0f, "RotationWidgetYAxis");
+ m_ZAxis = CreateRing(inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1), theRingInner,
+ theRingOuter, 0.0f, "RotationWidgetZAxis");
+ m_CameraAxis =
+ CreateRing(inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1), theRingInner + 5,
+ theRingOuter + 5, 0.0f, "RotationWidgetCameraAxis");
+ m_CameraRect = CreateRect(inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1), 200.0f,
+ "RotationWidgetZClear");
+ m_ZClearShader =
+ CreateZClearShader(inWidgetContext, inRenderContext, "RotationWidgetZClear");
+ }
+ QT3DSVec3 theXColor(GetXAxisColor());
+ QT3DSVec3 theYColor(GetYAxisColor());
+ QT3DSVec3 theZColor(GetZAxisColor());
+ QT3DSVec3 theRingColor(QT3DSVec3(.8, .8, .8));
+
+ QT3DSMat44 theMVP = TBase::SetupMVP(inWidgetContext);
+ inRenderContext.SetCullingEnabled(false);
+ QT3DSMat44 theCameraMVP = m_WidgetInfo.m_LayerProjection * m_CameraTranslationScale;
+
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetColorWritesEnabled(false);
+ inRenderContext.SetDepthTestEnabled(false);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetActiveShader(m_ZClearShader);
+ inRenderContext.SetInputAssembler(m_CameraRect);
+ m_ZClearShader->SetPropertyValue("model_view_projection", theCameraMVP);
+ inRenderContext.Draw(NVRenderDrawMode::Triangles, m_CameraRect->GetVertexCount(), 0);
+
+ inRenderContext.SetColorWritesEnabled(true);
+ inRenderContext.SetActiveShader(m_Shader);
+ m_Shader->SetPropertyValue("model_view_projection", theCameraMVP);
+ inRenderContext.SetDepthTestEnabled(false);
+ inRenderContext.SetDepthWriteEnabled(false);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::CameraPlane, theRingColor,
+ inRenderContext, m_CameraAxis);
+
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetActiveShader(m_Shader);
+ m_Shader->SetPropertyValue("model_view_projection", theMVP);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::XAxis, theXColor, inRenderContext,
+ m_XAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::YAxis, theYColor, inRenderContext,
+ m_YAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::ZAxis, theZColor, inRenderContext,
+ m_ZAxis);
+
+ if (m_RotationWedge.hasValue()) {
+ BeginImmediateDrawing(inWidgetContext, inRenderContext);
+
+ QT3DSMat33 theMVPRotation(m_WidgetInfo.m_CameraGlobalInverse.column0.getXYZ(),
+ m_WidgetInfo.m_CameraGlobalInverse.column1.getXYZ(),
+ m_WidgetInfo.m_CameraGlobalInverse.column2.getXYZ());
+ theMVPRotation = theMVPRotation.getInverse().getTranspose();
+
+ QT3DSVec3 theRotationAxis = theMVPRotation.transform(m_RotationWedge->m_RotationAxis);
+ QT3DSVec3 theStartDirection = theMVPRotation.transform(m_RotationWedge->m_StartDirection);
+ theRotationAxis.normalize();
+ theStartDirection.normalize();
+ QT3DSQuat theRotation(m_RotationWedge->m_Angle, theRotationAxis);
+ QT3DSVec3 theEndDirection = theRotation.rotate(theStartDirection);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ inRenderContext.SetDepthWriteEnabled(false);
+ inRenderContext.SetDepthTestEnabled(false);
+ inRenderContext.SetBlendingEnabled(true);
+ QT3DSVec4 lineColor(1, 1, 1, .7);
+ QT3DSVec4 fillColor(1, 1, 1, .2);
+ switch (m_Highlight) {
+ default:
+ break;
+ case StudioWidgetComponentIds::XAxis:
+ lineColor = QT3DSVec4(theXColor, .7);
+ fillColor = QT3DSVec4(theXColor, .2);
+ break;
+ case StudioWidgetComponentIds::YAxis:
+ lineColor = QT3DSVec4(theYColor, .7);
+ fillColor = QT3DSVec4(theYColor, .2);
+ break;
+ case StudioWidgetComponentIds::ZAxis:
+ lineColor = QT3DSVec4(theZColor, .7);
+ fillColor = QT3DSVec4(theZColor, .2);
+ break;
+ }
+ QT3DSVec3 theStartPos(m_WidgetInfo.m_Position);
+ QT3DSF32 theStartLineLen = theRingOuter * m_WidgetInfo.m_Scale;
+ if (m_Highlight == StudioWidgetComponentIds::CameraPlane)
+ theStartLineLen = (theRingOuter + 5) * m_WidgetInfo.m_Scale;
+ // Get the end line length in camera space.
+ QT3DSVec3 theGlobalStart = m_Node->GetGlobalPivot();
+ QT3DSQuat theGlobalRot(m_RotationWedge->m_Angle, m_RotationWedge->m_RotationAxis);
+ QT3DSVec3 theGlobalDir = theGlobalRot.rotate(m_RotationWedge->m_StartDirection);
+ QT3DSVec3 theGlobalEnd = theGlobalStart + theGlobalDir * m_RotationWedge->m_EndLineLen;
+ // Transform both start, end into camera space and get the length of the resulting
+ // vector
+ QT3DSVec3 theCameraStart = m_WidgetInfo.m_CameraGlobalInverse.transform(theGlobalStart);
+ QT3DSVec3 theCameraEnd = m_WidgetInfo.m_CameraGlobalInverse.transform(theGlobalEnd);
+ QT3DSF32 theCameraEndLineLen = QT3DSVec3(theCameraEnd - theCameraStart).magnitude();
+ QT3DSF32 theEndLineLen = theCameraEndLineLen;
+ // Draw lines in world space
+ SCamera &theCamera(*m_WidgetInfo.m_Camera);
+ QT3DSVec3 lineStart(ToFixedCameraPos(theStartPos, theCamera));
+ QT3DSVec3 startLineEnd(
+ ToFixedCameraPos(theStartPos + theStartDirection * theStartLineLen, theCamera));
+ QT3DSVec3 endLineEnd(ToFixedCameraPos(theCameraEnd, theCamera));
+ DrawImmediateLine(lineStart, startLineEnd, 1.0f, lineColor);
+ DrawImmediateLine(lineStart, endLineEnd, 1.0f, lineColor);
+ DrawFilledArc(theStartPos, theStartDirection, theStartLineLen, theRotationAxis,
+ m_RotationWedge->m_Angle, fillColor);
+ // Now setup the model-view-projection.
+ QT3DSMat44 theProjection = m_WidgetInfo.m_LayerProjection;
+ EndImmediateDrawing(inWidgetContext, inRenderContext, theProjection);
+
+ // Now we attempt to render some text. First we format it.
+
+ char textBuffer[25] = { 0 };
+ QT3DSF32 angleDeg(m_RotationWedge->m_Angle);
+ TODEG(angleDeg);
+ sprintf(textBuffer, "%.1f", angleDeg);
+ STextRenderInfo theInfo;
+ theInfo.m_Text = inRenderContext.GetStringTable().RegisterStr(textBuffer);
+ theInfo.m_HorizontalAlignment = TextHorizontalAlignment::Center;
+ theInfo.m_VerticalAlignment = TextVerticalAlignment::Bottom;
+ theInfo.m_FontSize = 12.0f * pixelRatio;
+ theInfo.m_Font = inRenderContext.GetStringTable().RegisterStr("TitilliumWeb-Regular");
+ QT3DSMat44 theTransMatrix(QT3DSMat44::createIdentity());
+ theTransMatrix.column3.x = endLineEnd.x;
+ theTransMatrix.column3.y = endLineEnd.y;
+ theTransMatrix.column3.z = endLineEnd.z;
+ // We want to scale the text *down* so that it looks better.
+ theTransMatrix.column0[0] = m_WidgetInfo.m_Scale * .8f;
+ theTransMatrix.column1[1] = m_WidgetInfo.m_Scale * .8f;
+ theTransMatrix.column2[2] = m_WidgetInfo.m_Scale * .8f;
+ QT3DSMat44 theTextMVP = theProjection * theTransMatrix;
+ inWidgetContext.RenderText(theInfo, QT3DSVec3(1, 1, 1), QT3DSVec3(.2, .2, .2), theTextMVP);
+ }
+ m_Highlight = StudioWidgetComponentIds::NoId;
+ }
+
+ void RenderPick(const QT3DSMat44 &inProjPremult, NVRenderContext &inRenderContext,
+ uic::render::SWindowDimensions /*inWinDimensions*/) override
+ {
+ if (m_XAxis && m_PickShader) {
+ QT3DSMat44 theCameraMVP =
+ inProjPremult * m_WidgetInfo.m_PureProjection * m_CameraTranslationScale;
+ QT3DSMat44 theMVP = inProjPremult * m_WidgetInfo.m_PureProjection * m_TranslationScale;
+
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetBlendingEnabled(true);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_ZClearShader);
+ m_ZClearShader->SetPropertyValue("model_view_projection", theCameraMVP);
+ inRenderContext.SetInputAssembler(m_CameraRect);
+ inRenderContext.Draw(NVRenderDrawMode::Triangles, m_CameraRect->GetVertexCount(), 0);
+
+ inRenderContext.SetActiveShader(m_PickShader);
+ m_PickShader->SetPropertyValue("model_view_projection", theCameraMVP);
+ RenderPickBuffer(StudioWidgetComponentIds::CameraPlane, m_CameraAxis, inRenderContext);
+
+ m_PickShader->SetPropertyValue("model_view_projection", theMVP);
+
+ RenderPickBuffer(StudioWidgetComponentIds::XAxis, m_XAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::YAxis, m_YAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::ZAxis, m_ZAxis, inRenderContext);
+ }
+ }
+};
+}
+
+IStudioWidget &IStudioWidget::CreateRotationWidget(NVAllocatorCallback &inAlloc)
+{
+ return *QT3DS_NEW(inAlloc, SRotationWidget)(inAlloc);
+}
diff --git a/src/Authoring/Studio/Render/StudioScaleWidget.cpp b/src/Authoring/Studio/Render/StudioScaleWidget.cpp
new file mode 100644
index 00000000..56b8bb33
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioScaleWidget.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "StudioWidgetImpl.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "UICRenderNode.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderShaderCodeGenerator.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "StudioUtils.h"
+
+using namespace uic::widgets;
+
+namespace {
+
+struct SScaleWidget : public SStudioWidgetImpl<StudioWidgetTypes::Scale>
+{
+ typedef SStudioWidgetImpl<StudioWidgetTypes::Scale> TBase;
+
+ NVRenderInputAssembler *m_XAxis;
+ NVRenderInputAssembler *m_YAxis;
+ NVRenderInputAssembler *m_ZAxis;
+
+ NVRenderInputAssembler *m_XPlane;
+ NVRenderInputAssembler *m_YPlane;
+ NVRenderInputAssembler *m_ZPlane;
+
+ volatile QT3DSI32 mRefCount;
+
+ SScaleWidget(NVAllocatorCallback &inAlloc)
+ : TBase(inAlloc)
+ , m_XAxis(nullptr)
+ , m_YAxis(nullptr)
+ , m_ZAxis(nullptr)
+ , m_XPlane(nullptr)
+ , m_YPlane(nullptr)
+ , m_ZPlane(nullptr)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+
+ NVRenderInputAssembler *CreateScaleAxis(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext,
+ const QT3DSVec3 &inDirection, QT3DSF32 inStartOffset,
+ QT3DSF32 inLength, QT3DSF32 inWidth, QT3DSF32 inBoxSideLength,
+ const char *inAxisName)
+ {
+
+ CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inAxisName);
+ NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName);
+ if (retval) {
+ return retval;
+ }
+
+ QT3DSVec3 tempCross = inDirection.cross(QT3DSVec3(0, 1, 0));
+ if (tempCross.magnitudeSquared() < .05f)
+ tempCross = inDirection.cross(QT3DSVec3(1, 0, 0));
+
+ QT3DSVec3 upDir = inDirection.cross(tempCross);
+ QT3DSVec3 leftDir = upDir.cross(inDirection);
+
+ TResultVecType theVertexData(m_Allocator, "SScaleWidget::theVertexData");
+
+ QT3DSVec3 rectStart = inDirection * inStartOffset;
+ // Rect end is also box start, obviously
+ QT3DSVec3 rectEnd = inDirection * (inStartOffset + inLength);
+ QT3DSVec3 boxEnd = inDirection * (inStartOffset + inLength + inBoxSideLength);
+
+ QT3DSF32 axisHalfWidth = inWidth / 2.0f;
+ // Create the axis
+ CreateRect(rectStart, rectEnd, upDir, axisHalfWidth, 0.0f, theVertexData);
+ CreateRect(rectStart, rectEnd, leftDir, axisHalfWidth, 0.0f, theVertexData);
+ // Create box at the top.
+ QT3DSF32 boxSideHalfLength = inBoxSideLength / 2;
+ // Get the four sides
+ QT3DSVec3 boxRectStart = rectEnd + (leftDir * boxSideHalfLength);
+ QT3DSVec3 boxRectEnd = boxEnd + (leftDir * boxSideHalfLength);
+ CreateRect(boxRectStart, boxRectEnd, upDir, boxSideHalfLength, 0.0f, theVertexData);
+
+ boxRectStart = rectEnd - leftDir * boxSideHalfLength;
+ boxRectEnd = boxEnd - leftDir * boxSideHalfLength;
+ CreateRect(boxRectStart, boxRectEnd, upDir, boxSideHalfLength, 0.0f, theVertexData);
+
+ boxRectStart = rectEnd + upDir * boxSideHalfLength;
+ boxRectEnd = boxEnd + upDir * boxSideHalfLength;
+ CreateRect(boxRectStart, boxRectEnd, leftDir, boxSideHalfLength, 0.0f, theVertexData);
+
+ boxRectStart = rectEnd - upDir * boxSideHalfLength;
+ boxRectEnd = boxEnd - upDir * boxSideHalfLength;
+ CreateRect(boxRectStart, boxRectEnd, leftDir, boxSideHalfLength, 0.0f, theVertexData);
+
+ // now create the top and bottom
+ // bottom
+ boxRectStart = rectEnd + upDir * boxSideHalfLength;
+ boxRectEnd = rectEnd - upDir * boxSideHalfLength;
+ CreateRect(boxRectStart, boxRectEnd, leftDir, boxSideHalfLength, 0.0f, theVertexData);
+
+ // top
+ boxRectStart = boxEnd + upDir * boxSideHalfLength;
+ boxRectEnd = boxEnd - upDir * boxSideHalfLength;
+ CreateRect(boxRectStart, boxRectEnd, leftDir, boxSideHalfLength, 0.0f, theVertexData);
+
+ QT3DSU32 stride;
+ QT3DSU32 offset = 0;
+ NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout(
+ IStudioWidget::GetVertexBufferAttributesAndStride(stride));
+ NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer(
+ theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size()));
+ retval = &inWidgetContext.GetOrCreateInputAssembler(
+ theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr,
+ toConstDataRef(&stride, 1), toConstDataRef(&offset, 1));
+
+ return retval;
+ }
+
+ void Render(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext) override
+ {
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ float pixelRatio = float(devicePixelRatio());
+ QT3DSF32 axisStart = 20.0f * pixelRatio;
+ QT3DSF32 axisLength = 60.0f * pixelRatio;
+ QT3DSF32 axisTotalLength = axisStart + axisLength;
+ if (m_XAxis == nullptr) {
+ TBase::SetupRender(inWidgetContext, inRenderContext);
+
+ QT3DSF32 axisWidth = 2.0f * pixelRatio;
+ QT3DSF32 triWidth = 7.0f * pixelRatio;
+ m_XAxis = CreateScaleAxis(inWidgetContext, inRenderContext, QT3DSVec3(1, 0, 0), axisStart,
+ axisLength, axisWidth, triWidth, "ScaleWidgetXAxis");
+ m_YAxis = CreateScaleAxis(inWidgetContext, inRenderContext, QT3DSVec3(0, 1, 0), axisStart,
+ axisLength, axisWidth, triWidth, "ScaleWidgetYAxis");
+ m_ZAxis = CreateScaleAxis(inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1), axisStart,
+ axisLength, axisWidth, triWidth, "ScaleWidgetZAxis");
+
+ QT3DSF32 axisPos = GetDiscPos() * pixelRatio;
+ QT3DSF32 axisDiscRadius = GetDiscRadius() * pixelRatio;
+ QT3DSF32 axisRingRadius = GetDiscRingRadius() * pixelRatio;
+ m_XPlane =
+ CreateRingedDisc(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(1, 0, 0),
+ QT3DSVec3(0, axisPos, -axisPos), axisDiscRadius, axisRingRadius, 0.0f,
+ 1.0f, "ScaleWidgetXPlane");
+ m_YPlane =
+ CreateRingedDisc(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(0, 1, 0),
+ QT3DSVec3(axisPos, 0, -axisPos), axisDiscRadius, axisRingRadius, 0.0f,
+ 1.0f, "ScaleWidgetYPlane");
+ m_ZPlane =
+ CreateRingedDisc(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1),
+ QT3DSVec3(axisPos, axisPos, 0), axisDiscRadius, axisRingRadius, 0.0f,
+ 1.0f, "ScaleWidgetZPlane");
+
+ inRenderContext.SetActiveShader(m_Shader);
+ m_Shader->SetPropertyValue("attr_pos_add_start", axisStart + 1);
+ }
+
+ QT3DSMat44 theMVP = TBase::SetupMVP(inWidgetContext);
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_Shader);
+ m_Shader->SetPropertyValue("model_view_projection", theMVP);
+ // temporary set color1 to white so we can hopefully see mistakes.
+ m_Shader->SetPropertyValue("color1", QT3DSVec3(1, 1, 1));
+
+ QT3DSVec3 theXColor(GetXAxisColor());
+ QT3DSVec3 theYColor(GetYAxisColor());
+ QT3DSVec3 theZColor(GetZAxisColor());
+ QT3DSVec3 theRingColor(QT3DSVec3(.8, .8, .8));
+ QT3DSVec3 theEndOffset = QT3DSVec3(axisTotalLength);
+ QT3DSVec3 theScaledEnd = QT3DSVec3(theEndOffset.x * m_AxisScale.x, theEndOffset.y * m_AxisScale.y,
+ theEndOffset.z * m_AxisScale.z);
+ QT3DSVec3 theEndAddition = theScaledEnd - theEndOffset;
+
+ m_Shader->SetPropertyValue("attr_pos_add_amount", QT3DSVec3(theEndAddition.x, 0, 0));
+ RenderSingleToneGeometry(StudioWidgetComponentIds::XAxis, theXColor, inRenderContext,
+ m_XAxis);
+
+ m_Shader->SetPropertyValue("attr_pos_add_amount", QT3DSVec3(0, theEndAddition.y, 0));
+ RenderSingleToneGeometry(StudioWidgetComponentIds::YAxis, theYColor, inRenderContext,
+ m_YAxis);
+
+ m_Shader->SetPropertyValue("attr_pos_add_amount", QT3DSVec3(0, 0, -1.0f * theEndAddition.z));
+ RenderSingleToneGeometry(StudioWidgetComponentIds::ZAxis, theZColor, inRenderContext,
+ m_ZAxis);
+
+ m_Shader->SetPropertyValue("attr_pos_add_amount", QT3DSVec3(0, 0, 0));
+ RenderTwoToneGeometry(StudioWidgetComponentIds::XPlane, theXColor, theRingColor,
+ inRenderContext, m_XPlane);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::YPlane, theYColor, theRingColor,
+ inRenderContext, m_YPlane);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::ZPlane, theZColor, theRingColor,
+ inRenderContext, m_ZPlane);
+
+ m_Highlight = StudioWidgetComponentIds::NoId;
+ }
+
+ void RenderPick(const QT3DSMat44 &inProjPremult, NVRenderContext &inRenderContext,
+ uic::render::SWindowDimensions /*inWinDimensions*/) override
+ {
+ if (m_XAxis && m_PickShader) {
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_PickShader);
+ // The projection premultiplication step moves the viewport around till
+ // it is centered over the mouse and scales everything *post* rendering (to keep
+ // appropriate aspect).
+ QT3DSMat44 theMVP = inProjPremult * m_PureProjection * m_TranslationScale;
+ m_PickShader->SetPropertyValue("model_view_projection", theMVP);
+
+ RenderPickBuffer(StudioWidgetComponentIds::XAxis, m_XAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::YAxis, m_YAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::ZAxis, m_ZAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::XPlane, m_XPlane, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::YPlane, m_YPlane, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::ZPlane, m_ZPlane, inRenderContext);
+ }
+ }
+};
+}
+
+IStudioWidget &IStudioWidget::CreateScaleWidget(NVAllocatorCallback &inAlloc)
+{
+ return *QT3DS_NEW(inAlloc, SScaleWidget)(inAlloc);
+}
diff --git a/src/Authoring/Studio/Render/StudioTranslationWidget.cpp b/src/Authoring/Studio/Render/StudioTranslationWidget.cpp
new file mode 100644
index 00000000..d75e8567
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioTranslationWidget.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "StudioWidgetImpl.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderShaderCodeGenerator.h"
+#include "UICRenderNode.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "StudioUtils.h"
+
+using namespace uic::widgets;
+
+namespace {
+
+struct STranslationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Translation>
+{
+ typedef SStudioWidgetImpl<StudioWidgetTypes::Translation> TBase;
+ NVRenderInputAssembler *m_XAxis;
+ NVRenderInputAssembler *m_YAxis;
+ NVRenderInputAssembler *m_ZAxis;
+
+ NVRenderInputAssembler *m_XPlane;
+ NVRenderInputAssembler *m_YPlane;
+ NVRenderInputAssembler *m_ZPlane;
+
+ volatile QT3DSI32 mRefCount;
+
+ STranslationWidget(NVAllocatorCallback &inAlloc)
+ : TBase(inAlloc)
+ , m_XAxis(nullptr)
+ , m_YAxis(nullptr)
+ , m_ZAxis(nullptr)
+ , m_XPlane(nullptr)
+ , m_YPlane(nullptr)
+ , m_ZPlane(nullptr)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator);
+
+ void Render(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext) override
+ {
+ // Widgets have to clear the depth buffer; they shouldn't interact with other components
+ // but they should self-occlude.
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ inRenderContext.SetDepthTestEnabled(true);
+ if (m_XAxis == nullptr) {
+ TBase::SetupRender(inWidgetContext, inRenderContext);
+ float pixelRatio = float(devicePixelRatio());
+ QT3DSF32 axisStart = 20.0f * pixelRatio;
+ QT3DSF32 axisLength = 60.0f * pixelRatio;
+ QT3DSF32 triLength = 20.0f * pixelRatio;
+ QT3DSF32 axisWidth = 2.0f * pixelRatio;
+ QT3DSF32 triWidth = 7.0f * pixelRatio;
+ m_XAxis = CreateAxis(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(1, 0, 0),
+ axisStart, axisLength, triLength, axisWidth, triWidth,
+ "TranslationWidgetXAxis");
+ m_YAxis = CreateAxis(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(0, 1, 0),
+ axisStart, axisLength, triLength, axisWidth, triWidth,
+ "TranslationWidgetYAxis");
+ m_ZAxis = CreateAxis(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1),
+ axisStart, axisLength, triLength, axisWidth, triWidth,
+ "TranslationWidgetZAxis");
+
+ QT3DSF32 axisPos = GetDiscPos() * pixelRatio;
+ QT3DSF32 axisDiscRadius = GetDiscRadius() * pixelRatio;
+ QT3DSF32 axisRingRadius = GetDiscRingRadius() * pixelRatio;
+ m_XPlane =
+ CreateRingedDisc(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(1, 0, 0),
+ QT3DSVec3(0, axisPos, -axisPos), axisDiscRadius, axisRingRadius, 0.0f,
+ 1.0f, "TranslationWidgetXPlane");
+ m_YPlane =
+ CreateRingedDisc(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(0, 1, 0),
+ QT3DSVec3(axisPos, 0, -axisPos), axisDiscRadius, axisRingRadius, 0.0f,
+ 1.0f, "TranslationWidgetYPlane");
+ m_ZPlane =
+ CreateRingedDisc(m_Allocator, inWidgetContext, inRenderContext, QT3DSVec3(0, 0, -1),
+ QT3DSVec3(axisPos, axisPos, 0), axisDiscRadius, axisRingRadius, 0.0f,
+ 1.0f, "TranslationWidgetZPlane");
+ }
+ QT3DSMat44 theMVP = TBase::SetupMVP(inWidgetContext);
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_Shader);
+ m_Shader->SetPropertyValue("model_view_projection", theMVP);
+ // temporary set color1 to white so we can hopefully see mistakes.
+ m_Shader->SetPropertyValue("color1", QT3DSVec3(1, 1, 1));
+
+ QT3DSVec3 theXColor(GetXAxisColor());
+ QT3DSVec3 theYColor(GetYAxisColor());
+ QT3DSVec3 theZColor(GetZAxisColor());
+ QT3DSVec3 theRingColor(QT3DSVec3(.8, .8, .8));
+
+ RenderSingleToneGeometry(StudioWidgetComponentIds::XAxis, theXColor, inRenderContext,
+ m_XAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::YAxis, theYColor, inRenderContext,
+ m_YAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::ZAxis, theZColor, inRenderContext,
+ m_ZAxis);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::XPlane, theXColor, theRingColor,
+ inRenderContext, m_XPlane);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::YPlane, theYColor, theRingColor,
+ inRenderContext, m_YPlane);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::ZPlane, theZColor, theRingColor,
+ inRenderContext, m_ZPlane);
+ m_Highlight = StudioWidgetComponentIds::NoId;
+ }
+
+ void RenderPick(const QT3DSMat44 &inProjPremult, NVRenderContext &inRenderContext,
+ uic::render::SWindowDimensions /*inWinDimensions*/) override
+ {
+ if (m_XAxis && m_PickShader) {
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.Clear(qt3ds::render::NVRenderClearValues::Depth);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_PickShader);
+ // The projection premultiplication step moves the viewport around till
+ // it is centered over the mouse and scales everything *post* rendering (to keep
+ // appropriate aspect).
+ QT3DSMat44 theMVP = inProjPremult * m_PureProjection * m_TranslationScale;
+ m_PickShader->SetPropertyValue("model_view_projection", theMVP);
+
+ RenderPickBuffer(StudioWidgetComponentIds::XAxis, m_XAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::YAxis, m_YAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::ZAxis, m_ZAxis, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::XPlane, m_XPlane, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::YPlane, m_YPlane, inRenderContext);
+ RenderPickBuffer(StudioWidgetComponentIds::ZPlane, m_ZPlane, inRenderContext);
+ }
+ }
+};
+}
+
+IStudioWidget &IStudioWidget::CreateTranslationWidget(NVAllocatorCallback &inAlloc)
+{
+ return *QT3DS_NEW(inAlloc, STranslationWidget)(inAlloc);
+}
diff --git a/src/Authoring/Studio/Render/StudioWidget.cpp b/src/Authoring/Studio/Render/StudioWidget.cpp
new file mode 100644
index 00000000..4e8e4717
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioWidget.cpp
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "StudioWidget.h"
+#include "UICRenderWidgets.h"
+#include "UICRenderContext.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+
+using namespace uic::widgets;
+
+void IStudioWidget::CreateRect(QT3DSVec3 rectStart, QT3DSVec3 rectEnd, QT3DSVec3 orth1, QT3DSF32 axisHalfWidth,
+ QT3DSF32 inColorIndex, TResultVecType &outResult)
+{
+ outResult.push_back(QT3DSVec4(rectStart + orth1 * axisHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(rectEnd + orth1 * axisHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(rectEnd - orth1 * axisHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(rectEnd - orth1 * axisHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(rectStart - orth1 * axisHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(rectStart + orth1 * axisHalfWidth, inColorIndex));
+}
+
+void IStudioWidget::CreateTriangle(QT3DSVec3 triStart, QT3DSVec3 triEnd, QT3DSVec3 orth1, QT3DSF32 triHalfWidth,
+ QT3DSF32 inColorIndex, TResultVecType &outResult)
+{
+ outResult.push_back(QT3DSVec4(triStart + orth1 * triHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(triStart - orth1 * triHalfWidth, inColorIndex));
+ outResult.push_back(QT3DSVec4(triEnd, inColorIndex));
+}
+
+NVRenderInputAssembler *IStudioWidget::CreateRingedDisc(
+ NVAllocatorCallback &inAllocator, IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, QT3DSVec3 inDirection, QT3DSVec3 inCenterPt, QT3DSF32 inInnerRadius,
+ QT3DSF32 inOuterRadius, QT3DSF32 inDiscColor, QT3DSF32 inRingColor, const char *inItemName)
+{
+ CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inItemName);
+ NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName);
+ if (retval) {
+ return retval;
+ }
+ TResultVecType theVertexData(inAllocator, "STranslationWidget::theVertexData");
+ QT3DS_ASSERT(inInnerRadius < inOuterRadius);
+ QT3DSI32 numSubDivisions = 50;
+ QT3DSF32 arcRad = 360.0f / (QT3DSF32)numSubDivisions;
+ TORAD(arcRad);
+ QT3DSVec3 tempCross = inDirection.cross(QT3DSVec3(0, 1, 0));
+ if (tempCross.magnitudeSquared() < .05f)
+ tempCross = inDirection.cross(QT3DSVec3(1, 0, 0));
+
+ QT3DSVec3 upDir = inDirection.cross(tempCross);
+ QT3DSVec3 leftDir = upDir.cross(inDirection);
+ upDir.normalize();
+ leftDir.normalize();
+
+ for (QT3DSI32 idx = 0, numLooper = numSubDivisions; idx < numLooper; ++idx) {
+ QT3DSF32 startDeg = idx * 360.0f / numSubDivisions;
+ QT3DSF32 endDeg = (idx + 1) * 360.0f / numSubDivisions;
+ QT3DSF32 startRad(startDeg);
+ QT3DSF32 endRad(endDeg);
+ TORAD(startRad);
+ TORAD(endRad);
+ QT3DSF32 startSin = NVSin(startRad);
+ QT3DSF32 endSin = NVSin(endRad);
+ QT3DSF32 startCos = NVCos(startRad);
+ QT3DSF32 endCos = NVCos(endRad);
+
+ QT3DSVec3 startDir = startSin * upDir + startCos * leftDir;
+ QT3DSVec3 endDir = endSin * upDir + endCos * leftDir;
+
+ QT3DSVec3 discStart = inCenterPt + startDir * inInnerRadius;
+ QT3DSVec3 discEnd = inCenterPt + endDir * inInnerRadius;
+ QT3DSVec3 ringStart = inCenterPt + startDir * inOuterRadius;
+ QT3DSVec3 ringEnd = inCenterPt + endDir * inOuterRadius;
+
+ // Create the Triangles
+ // disc first
+ theVertexData.push_back(QT3DSVec4(inCenterPt, inDiscColor));
+ theVertexData.push_back(QT3DSVec4(discStart, inDiscColor));
+ theVertexData.push_back(QT3DSVec4(discEnd, inDiscColor));
+
+ // Now two tris for the ring
+ theVertexData.push_back(QT3DSVec4(discStart, inRingColor));
+ theVertexData.push_back(QT3DSVec4(ringStart, inRingColor));
+ theVertexData.push_back(QT3DSVec4(ringEnd, inRingColor));
+ theVertexData.push_back(QT3DSVec4(ringEnd, inRingColor));
+ theVertexData.push_back(QT3DSVec4(discEnd, inRingColor));
+ theVertexData.push_back(QT3DSVec4(discStart, inRingColor));
+ }
+
+ QT3DSU32 stride;
+ QT3DSU32 offset = 0;
+ NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout(
+ IStudioWidget::GetVertexBufferAttributesAndStride(stride));
+ NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer(
+ theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size()));
+
+ retval = &inWidgetContext.GetOrCreateInputAssembler(
+ theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr,
+ toConstDataRef(&stride, 1), toConstDataRef(&offset, 1));
+
+ return retval;
+}
+
+// Create an axis with a triangle at the top. Really we create two axis that are orthogonal to each
+// other.
+NVRenderInputAssembler *
+IStudioWidget::CreateAxis(NVAllocatorCallback &inAllocator, IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, const QT3DSVec3 &inAxisDirection,
+ QT3DSF32 inAxisStartOffset, QT3DSF32 inAxisLength, QT3DSF32 inTriLength,
+ QT3DSF32 inAxisWidth, QT3DSF32 inTriWidth, const char *inAxisName)
+{
+ CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inAxisName);
+ NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName);
+ if (retval) {
+ return retval;
+ }
+
+ TResultVecType theVertexData(inAllocator, "STranslationWidget::theVertexData");
+ QT3DSVec3 orth1 = inAxisDirection.cross(QT3DSVec3(0, 0, 1));
+ if (orth1.magnitudeSquared() < .05f)
+ orth1 = inAxisDirection.cross(QT3DSVec3(0, 1, 0));
+ QT3DSVec3 orth2 = inAxisDirection.cross(orth1);
+
+ // Draw a rect that starts at inAxisStartOffset
+ QT3DSVec3 rectStart = inAxisDirection * inAxisStartOffset;
+ // Rect end is also tri start, obviously
+ QT3DSVec3 rectEnd = inAxisDirection * (inAxisStartOffset + inAxisLength);
+ QT3DSVec3 triEnd = inAxisDirection * (inAxisStartOffset + inAxisLength + inTriLength);
+
+ QT3DSF32 axisHalfWidth = inAxisWidth / 2.0f;
+ QT3DSF32 triHalfWidth = inTriWidth / 2.0f;
+ CreateRect(rectStart, rectEnd, orth1, axisHalfWidth, 0.0f, theVertexData);
+ CreateTriangle(rectEnd, triEnd, orth1, triHalfWidth, 0.0f, theVertexData);
+ CreateRect(rectStart, rectEnd, orth2, axisHalfWidth, 0.0f, theVertexData);
+ CreateTriangle(rectEnd, triEnd, orth2, triHalfWidth, 0.0f, theVertexData);
+
+ QT3DSU32 stride;
+ QT3DSU32 offset = 0;
+ NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout(
+ IStudioWidget::GetVertexBufferAttributesAndStride(stride));
+ NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer(
+ theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size()));
+
+ retval = &inWidgetContext.GetOrCreateInputAssembler(
+ theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr,
+ toConstDataRef(&stride, 1), toConstDataRef(&offset, 1));
+
+ return retval;
+};
+
+SWidgetRenderSetupResult::SWidgetRenderSetupResult(IRenderWidgetContext &inWidgetContext,
+ SNode &inNode,
+ RenderWidgetModes::Enum inWidgetMode)
+{
+ m_WidgetInfo =
+ inWidgetContext.GetWidgetRenderInformation(inNode, QT3DSVec3(0, 0, 0), inWidgetMode);
+ QT3DSMat44 theTranslationScale(QT3DSMat44::createIdentity());
+ QT3DSMat33 theRotationMult(QT3DSMat33::createIdentity());
+ bool includeNodeRotation = inWidgetMode == RenderWidgetModes::Local ? true : false;
+ if (includeNodeRotation) {
+ QT3DSMat44 theNodeRotation;
+ inNode.CalculateRotationMatrix(theNodeRotation);
+ if (inNode.m_Flags.IsLeftHanded()) {
+ SNode::FlipCoordinateSystem(theNodeRotation);
+ }
+ theRotationMult =
+ QT3DSMat33(theNodeRotation.column0.getXYZ(), theNodeRotation.column1.getXYZ(),
+ theNodeRotation.column2.getXYZ());
+ }
+
+ QT3DSMat33 theRotationMatrix = m_WidgetInfo.m_NormalMatrix * theRotationMult;
+ QT3DSMat33 theScaleMatrix(QT3DSMat33::createIdentity());
+ theScaleMatrix.column0[0] = m_WidgetInfo.m_Scale;
+ theScaleMatrix.column1[1] = m_WidgetInfo.m_Scale;
+ theScaleMatrix.column2[2] = m_WidgetInfo.m_Scale;
+ QT3DSMat33 theCombined = theRotationMatrix * theScaleMatrix;
+ theTranslationScale.column0 = QT3DSVec4(theCombined.column0, 0.0f);
+ theTranslationScale.column1 = QT3DSVec4(theCombined.column1, 0.0f);
+ theTranslationScale.column2 = QT3DSVec4(theCombined.column2, 0.0f);
+ theTranslationScale.column3.x = m_WidgetInfo.m_Position.x;
+ theTranslationScale.column3.y = m_WidgetInfo.m_Position.y;
+ theTranslationScale.column3.z = m_WidgetInfo.m_Position.z;
+ m_TranslationScale = theTranslationScale;
+ m_PureProjection = m_WidgetInfo.m_PureProjection;
+
+ QT3DSMat44 theCameraTransScale(QT3DSMat44::createIdentity());
+ theCameraTransScale.column0 = QT3DSVec4(m_WidgetInfo.m_LookAtMatrix.column0, 0.0f);
+ theCameraTransScale.column1 = QT3DSVec4(m_WidgetInfo.m_LookAtMatrix.column1, 0.0f);
+ theCameraTransScale.column2 = QT3DSVec4(m_WidgetInfo.m_LookAtMatrix.column2, 0.0f);
+ theCameraTransScale.column3.x = m_WidgetInfo.m_Position.x;
+ theCameraTransScale.column3.y = m_WidgetInfo.m_Position.y;
+ theCameraTransScale.column3.z = m_WidgetInfo.m_Position.z;
+ theCameraTransScale.column0[0] = m_WidgetInfo.m_Scale;
+ theCameraTransScale.column1[1] = m_WidgetInfo.m_Scale;
+ theCameraTransScale.column2[2] = m_WidgetInfo.m_Scale;
+ m_CameraTranslationScale = theCameraTransScale;
+ m_SetupResult = m_WidgetInfo.m_LayerProjection * theTranslationScale;
+}
+
+CRegisteredString IStudioWidget::GetSharedShaderName(IStringTable &inStrTable)
+{
+ return inStrTable.RegisterStr("IStudioWidget Shader");
+}
+
+CRegisteredString IStudioWidget::GetSharedPickShaderName(IStringTable &inStrTable)
+{
+ return inStrTable.RegisterStr("IStudioWidget Pick Shader");
+}
+
+NVRenderShaderProgram *IStudioWidget::CreateWidgetShader(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext)
+{
+ CRegisteredString theSharedName(GetSharedShaderName(inRenderContext.GetStringTable()));
+ NVRenderShaderProgram *retval = inWidgetContext.GetShader(theSharedName);
+ if (retval)
+ return retval;
+ uic::render::IShaderProgramGenerator &theGenerator(inWidgetContext.GetProgramGenerator());
+ theGenerator.BeginProgram();
+ uic::render::IShaderStageGenerator &theVertexGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Vertex));
+ uic::render::IShaderStageGenerator &theFragmentGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddIncoming("attr_color_index", "float");
+ theVertexGenerator.AddOutgoing("output_color_index", "float");
+ theVertexGenerator.AddUniform("model_view_projection", "mat4");
+ // These are required in order to scale the scale widget the way we want to scale it.
+ theVertexGenerator.AddUniform("attr_pos_add_start", "float");
+ theVertexGenerator.AddUniform("attr_pos_add_amount", "vec3");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator
+ << "\tvec3 thePos = attr_pos;" << Endl
+ << "\tif ( length(thePos) > attr_pos_add_start ) thePos = thePos + attr_pos_add_amount;"
+ << Endl;
+ theVertexGenerator.Append("\tgl_Position = model_view_projection * vec4(thePos, 1.0);");
+ theVertexGenerator.Append("\toutput_color_index = attr_color_index;");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.AddUniform("color0", "vec3");
+ theFragmentGenerator.AddUniform("color1", "vec3");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tgl_FragColor.rgb = output_color_index > 0.0 ? color1 : color0;");
+ theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;");
+ theFragmentGenerator.Append("}");
+ return inWidgetContext.CompileAndStoreShader(theSharedName);
+}
+
+NVRenderShaderProgram *IStudioWidget::CreateWidgetPickShader(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext)
+{
+ CRegisteredString theSharedName(GetSharedPickShaderName(inRenderContext.GetStringTable()));
+ NVRenderShaderProgram *retval = inWidgetContext.GetShader(theSharedName);
+ if (retval)
+ return retval;
+ uic::render::IShaderProgramGenerator &theGenerator(inWidgetContext.GetProgramGenerator());
+ theGenerator.BeginProgram();
+ uic::render::IShaderStageGenerator &theVertexGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Vertex));
+ uic::render::IShaderStageGenerator &theFragmentGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddUniform("model_view_projection", "mat4");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.AddUniform("object_id", "int");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tgl_FragColor.r = float(object_id % 256)/255.0;");
+ theFragmentGenerator.Append("\tgl_FragColor.g = float(object_id / 256)/255.0;");
+ theFragmentGenerator.Append("\tgl_FragColor.b = 0;");
+ theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;");
+ theFragmentGenerator.Append("}");
+ return inWidgetContext.CompileAndStoreShader(theSharedName);
+}
+
+NVConstDataRef<qt3ds::render::NVRenderVertexBufferEntry>
+IStudioWidget::GetVertexBufferAttributesAndStride(QT3DSU32 &stride)
+{
+ static qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32,
+ 3),
+ qt3ds::render::NVRenderVertexBufferEntry("attr_color_index",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 1, 12),
+ };
+
+ stride = 3 * sizeof(QT3DSF32) + 1 * sizeof(QT3DSF32);
+
+ return toConstDataRef(theEntries, 2);
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/Render/StudioWidget.h b/src/Authoring/Studio/Render/StudioWidget.h
new file mode 100644
index 00000000..030e6836
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioWidget.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_RENDERER_WIDGET_H
+#define UIC_STUDIO_RENDERER_WIDGET_H
+#pragma once
+#include "UICRenderWindowDimensions.h"
+#include "UICRenderWidgets.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "StudioPickValues.h"
+
+namespace uic {
+namespace widgets {
+ using namespace uic::render;
+
+ struct StudioWidgetTypes
+ {
+ enum Enum {
+ Unknown,
+ Translation,
+ Scale,
+ Rotation,
+ };
+ };
+
+ // These are also the ids used as colors in the pick image.
+ struct StudioWidgetComponentIds
+ {
+ enum Enum {
+ NoId = 0,
+ XAxis,
+ YAxis,
+ ZAxis,
+ XPlane,
+ YPlane,
+ ZPlane,
+ CameraPlane,
+ LastId,
+ };
+ };
+
+ // Functionality shared between the path widget and the various manipulation gadgets
+ class IStudioWidgetBase : public IRenderWidget, public NVRefCounted
+ {
+ public:
+ virtual void SetNode(SNode &inNode) = 0;
+ virtual void RenderPick(const QT3DSMat44 &inProjPreMult, NVRenderContext &inRenderContext,
+ uic::render::SWindowDimensions inWinDimensions) = 0;
+ virtual uic::studio::SStudioPickValue PickIndexToPickValue(QT3DSU32 inPickIndex) = 0;
+ };
+
+ typedef nvvector<QT3DSVec4> TResultVecType;
+
+ struct SWidgetRenderSetupResult
+ {
+ QT3DSMat44 m_TranslationScale;
+ QT3DSMat44 m_CameraTranslationScale;
+ QT3DSMat44 m_PureProjection;
+ SWidgetRenderInformation m_WidgetInfo;
+ QT3DSMat44 m_SetupResult;
+
+ SWidgetRenderSetupResult() {}
+ SWidgetRenderSetupResult(IRenderWidgetContext &inWidgetContext, SNode &inNode,
+ RenderWidgetModes::Enum inWidgetMode);
+ };
+
+ class IStudioWidget : public IStudioWidgetBase
+ {
+ public:
+ static CRegisteredString GetSharedShaderName(IStringTable &inStrTable);
+ static CRegisteredString GetSharedPickShaderName(IStringTable &inStrTable);
+ static NVRenderShaderProgram *CreateWidgetShader(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext);
+ static NVRenderShaderProgram *CreateWidgetPickShader(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext);
+ static NVConstDataRef<qt3ds::render::NVRenderVertexBufferEntry>
+ GetVertexBufferAttributesAndStride(QT3DSU32 &stride);
+ static NVRenderInputAssembler *
+ CreateRingedDisc(NVAllocatorCallback &inAllocator, IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, QT3DSVec3 inDirection, QT3DSVec3 inCenterPt,
+ QT3DSF32 inInnerRadius, QT3DSF32 inOuterRadius, QT3DSF32 inDiscColor,
+ QT3DSF32 inRingColor, const char *inItemName);
+ static NVRenderInputAssembler *
+ CreateAxis(NVAllocatorCallback &inAllocator, IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, const QT3DSVec3 &inAxisDirection,
+ QT3DSF32 inAxisStartOffset, QT3DSF32 inAxisLength, QT3DSF32 inTriLength,
+ QT3DSF32 inAxisWidth, QT3DSF32 inTriWidth, const char *inAxisName);
+ static void CreateRect(QT3DSVec3 rectStart, QT3DSVec3 rectEnd, QT3DSVec3 orth1, QT3DSF32 axisHalfWidth,
+ QT3DSF32 inColorIndex, TResultVecType &outResult);
+ static void CreateTriangle(QT3DSVec3 triStart, QT3DSVec3 triEnd, QT3DSVec3 orth1, QT3DSF32 triHalfWidth,
+ QT3DSF32 inColorIndex, TResultVecType &outResult);
+
+ void SetNode(SNode &inNode) override = 0;
+ virtual StudioWidgetTypes::Enum GetWidgetType() const = 0;
+ virtual void SetSubComponentId(int inSubComponentId) = 0;
+ virtual void SetRenderWidgetMode(RenderWidgetModes::Enum inSpace) = 0;
+ virtual RenderWidgetModes::Enum GetRenderWidgetMode() const = 0;
+ // When we render the axis, we can scale the axis item itself
+ virtual void SetAxisScale(const QT3DSVec3 &inNewScale) = 0;
+ // Set the start/end positions of the rotation arc so the rotation gadget can show
+ // the angle and optionally display an angle readout. The start direction should
+ // be a normalized direction in world space, and the angle should be in radians
+ // inRotationAxis is expected to be a normalized direction in world space.
+ virtual void SetRotationEdges(const QT3DSVec3 &inStartDirection, const QT3DSVec3 &inRotationAxis,
+ QT3DSF32 inAngleRad, QT3DSF32 inEndLineLen) = 0;
+ virtual void ClearRotationEdges() = 0;
+
+ static IStudioWidget &CreateTranslationWidget(NVAllocatorCallback &inAlloc);
+ static IStudioWidget &CreateRotationWidget(NVAllocatorCallback &inAlloc);
+ static IStudioWidget &CreateScaleWidget(NVAllocatorCallback &inAlloc);
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Render/StudioWidgetImpl.h b/src/Authoring/Studio/Render/StudioWidgetImpl.h
new file mode 100644
index 00000000..a00f4fcd
--- /dev/null
+++ b/src/Authoring/Studio/Render/StudioWidgetImpl.h
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STUDIO_RENDERER_WIDGET_IMPL_H
+#define UIC_STUDIO_RENDERER_WIDGET_IMPL_H
+#pragma once
+
+#include "StudioWidget.h"
+#include "foundation/Qt3DSContainers.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include "UICRenderNode.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+
+namespace uic {
+namespace widgets {
+
+ typedef nvvector<QT3DSVec4> TResultVecType;
+
+ struct SRotationWedge
+ {
+ QT3DSVec3 m_StartDirection; // world space position
+ QT3DSVec3 m_RotationAxis;
+ QT3DSF32 m_Angle; // angle in radians.
+ QT3DSF32 m_EndLineLen;
+ SRotationWedge() {}
+ SRotationWedge(const QT3DSVec3 &inStartDirection, const QT3DSVec3 &inRotationAxis, QT3DSF32 inAngle,
+ QT3DSF32 inEndLineLen)
+ : m_StartDirection(inStartDirection)
+ , m_RotationAxis(inRotationAxis)
+ , m_Angle(inAngle)
+ , m_EndLineLen(inEndLineLen)
+ {
+ }
+ };
+
+ struct SImmediateVertex
+ {
+ QT3DSVec3 m_Position;
+ QT3DSVec4 m_Color;
+ SImmediateVertex(const QT3DSVec3 &inPosition, const QT3DSVec4 &inColor)
+ : m_Position(inPosition)
+ , m_Color(inColor)
+ {
+ }
+ SImmediateVertex() {}
+ };
+
+ template <StudioWidgetTypes::Enum TWidgetType>
+ struct SStudioWidgetImpl : public IStudioWidget
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram *m_Shader;
+ NVRenderShaderProgram *m_PickShader;
+ QT3DSMat44 m_TranslationScale;
+ QT3DSMat44 m_CameraTranslationScale;
+ QT3DSMat44 m_PureProjection;
+ SWidgetRenderInformation m_WidgetInfo;
+ StudioWidgetComponentIds::Enum m_Highlight;
+ RenderWidgetModes::Enum m_WidgetMode;
+
+ QT3DSVec3 m_AxisScale;
+ Option<SRotationWedge> m_RotationWedge;
+ nvvector<SImmediateVertex> m_ImmediateBuffer;
+ NVRenderVertexBuffer *m_ImmediateVertexBuffer;
+ NVRenderInputAssembler *m_ImmediateInputAssembler;
+ NVRenderShaderProgram *m_ImmediateShader;
+
+ SStudioWidgetImpl(NVAllocatorCallback &inAlloc)
+ : m_Allocator(inAlloc)
+ , m_Shader(NULL)
+ , m_PickShader(NULL)
+ , m_Highlight(StudioWidgetComponentIds::NoId)
+ , m_WidgetMode(RenderWidgetModes::Local)
+ , m_AxisScale(QT3DSVec3(1, 1, 1))
+ , m_ImmediateBuffer(m_Allocator, "STranslationWidget::theVertexData")
+ , m_ImmediateVertexBuffer(NULL)
+ , m_ImmediateInputAssembler(NULL)
+ , m_ImmediateShader(NULL)
+ {
+ }
+
+ void SetNode(SNode &inNode) override { m_Node = &inNode; }
+
+ void SetSubComponentId(int inId) override
+ {
+ if (inId > 0 && inId < (int)StudioWidgetComponentIds::LastId)
+ m_Highlight = static_cast<StudioWidgetComponentIds::Enum>(inId);
+ else
+ m_Highlight = StudioWidgetComponentIds::NoId;
+ }
+
+ StudioWidgetTypes::Enum GetWidgetType() const override { return TWidgetType; }
+ uic::studio::SStudioPickValue PickIndexToPickValue(QT3DSU32 inPickIndex) override
+ {
+ return uic::studio::SWidgetPick((QT3DSI32)inPickIndex);
+ }
+
+ void SetupRender(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext)
+ {
+ m_Shader = IStudioWidget::CreateWidgetShader(inWidgetContext, inRenderContext);
+ m_PickShader = IStudioWidget::CreateWidgetPickShader(inWidgetContext, inRenderContext);
+ }
+
+ QT3DSMat44 SetupMVP(IRenderWidgetContext &inWidgetContext)
+ {
+ SWidgetRenderSetupResult theSetup(inWidgetContext, *m_Node, m_WidgetMode);
+ m_TranslationScale = theSetup.m_TranslationScale;
+ m_CameraTranslationScale = theSetup.m_CameraTranslationScale;
+ m_PureProjection = theSetup.m_PureProjection;
+ m_WidgetInfo = theSetup.m_WidgetInfo;
+ return theSetup.m_SetupResult;
+ }
+
+ void RenderSingleToneGeometry(StudioWidgetComponentIds::Enum inId,
+ const QT3DSVec3 &inOriginalColor,
+ NVRenderContext &inRenderContext,
+ NVRenderInputAssembler *inGeometryAssembly)
+ {
+ bool isHighlighted = inId == m_Highlight;
+ QT3DSVec3 theColor = isHighlighted ? QT3DSVec3(1, 1, 0) : inOriginalColor;
+
+ m_Shader->SetPropertyValue("color0", theColor);
+ inRenderContext.SetInputAssembler(inGeometryAssembly);
+ inRenderContext.Draw(qt3ds::render::NVRenderDrawMode::Triangles,
+ inGeometryAssembly->GetVertexCount(), 0);
+ };
+
+ void RenderTwoToneGeometry(StudioWidgetComponentIds::Enum inId, QT3DSVec3 inColor0,
+ QT3DSVec3 inColor1, NVRenderContext &inRenderContext,
+ NVRenderInputAssembler *inGeometryAssembly)
+ {
+ bool isHighlighted = inId == m_Highlight;
+ if (isHighlighted) {
+ inColor0 = inColor1 = QT3DSVec3(1, 1, 0);
+ }
+
+ m_Shader->SetPropertyValue("color0", inColor0);
+ m_Shader->SetPropertyValue("color1", inColor1);
+ inRenderContext.SetInputAssembler(inGeometryAssembly);
+ inRenderContext.Draw(qt3ds::render::NVRenderDrawMode::Triangles,
+ inGeometryAssembly->GetVertexCount(), 0);
+ };
+
+ void SetRenderWidgetMode(RenderWidgetModes::Enum inSpace) override { m_WidgetMode = inSpace; }
+
+ RenderWidgetModes::Enum GetRenderWidgetMode() const override { return m_WidgetMode; }
+
+ void RenderPickBuffer(StudioWidgetComponentIds::Enum inId,
+ NVRenderInputAssembler *inGeometryAssembly,
+ NVRenderContext &inRenderContext)
+ {
+ QT3DSI32 theObjectId = inId;
+ m_PickShader->SetPropertyValue("object_id", theObjectId);
+ inRenderContext.SetInputAssembler(inGeometryAssembly);
+ inRenderContext.Draw(qt3ds::render::NVRenderDrawMode::Triangles,
+ inGeometryAssembly->GetVertexCount(), 0);
+ }
+
+ void BeginImmediateDrawing(IRenderWidgetContext &, NVRenderContext &)
+ {
+ m_ImmediateBuffer.clear();
+ }
+
+ void DrawImmediateRect(const QT3DSVec3 &rectStart, const QT3DSVec3 &rectEnd, const QT3DSVec3 &orth1,
+ QT3DSF32 axisHalfWidth, const QT3DSVec4 &inColor)
+ {
+ StaticAssert<sizeof(SImmediateVertex) == 7 * sizeof(QT3DSF32)>::valid_expression();
+ m_ImmediateBuffer.push_back(
+ SImmediateVertex(rectStart + orth1 * axisHalfWidth, inColor));
+ m_ImmediateBuffer.push_back(SImmediateVertex(rectEnd + orth1 * axisHalfWidth, inColor));
+ m_ImmediateBuffer.push_back(SImmediateVertex(rectEnd - orth1 * axisHalfWidth, inColor));
+ m_ImmediateBuffer.push_back(SImmediateVertex(rectEnd - orth1 * axisHalfWidth, inColor));
+ m_ImmediateBuffer.push_back(
+ SImmediateVertex(rectStart - orth1 * axisHalfWidth, inColor));
+ m_ImmediateBuffer.push_back(
+ SImmediateVertex(rectStart + orth1 * axisHalfWidth, inColor));
+ }
+
+ void DrawImmediateLine(const QT3DSVec3 &inStart, const QT3DSVec3 &inEnd, QT3DSF32 inWidth,
+ const QT3DSVec4 &inColor)
+ {
+ QT3DSVec3 theDir = inEnd - inStart;
+ theDir.normalize();
+ QT3DSVec3 theTemp = theDir.cross(QT3DSVec3(0, 0, 1));
+ QT3DSF32 theTempLen = theTemp.normalize();
+ if (theTempLen < .01f) {
+ theTemp = theDir.cross(QT3DSVec3(0, 1, 0));
+ theTemp.normalize();
+ }
+ QT3DSVec3 rectStart(inStart);
+ QT3DSVec3 rectEnd(inEnd);
+ QT3DSVec3 orth1 = theDir.cross(theTemp);
+ QT3DSVec3 orth2 = orth1.cross(theDir);
+ orth1.normalize();
+ orth2.normalize();
+ QT3DSF32 axisHalfWidth = inWidth / 2.0f;
+ DrawImmediateRect(rectStart, rectEnd, orth1, axisHalfWidth, inColor);
+ DrawImmediateRect(rectStart, rectEnd, orth2, axisHalfWidth, inColor);
+ }
+
+ void DrawFilledArc(const QT3DSVec3 &inStartPos, const QT3DSVec3 &inStartDirection, QT3DSF32 inArcLen,
+ const QT3DSVec3 &inRotationAxis, QT3DSF32 inAngle, const QT3DSVec4 &inFillColor)
+ {
+ // 25 small triangles per 180 degrees
+ QT3DSF32 arcLen = (QT3DSF32)(M_PI / 25.0f);
+ QT3DSU32 increments = NVMax((QT3DSU32)1, (QT3DSU32)((fabs(inArcLen) / arcLen) + .5f));
+ QT3DSF32 angleMultiplier = inAngle / (QT3DSF32)increments;
+ for (QT3DSU32 idx = 0; idx < increments; ++idx) {
+ QT3DSF32 localAngle = angleMultiplier * idx;
+ QT3DSF32 nextAngle = angleMultiplier * (idx + 1);
+ QT3DSQuat theQuat(localAngle, inRotationAxis);
+ QT3DSQuat nextQuat(nextAngle, inRotationAxis);
+ QT3DSVec3 startDir = theQuat.rotate(inStartDirection);
+ QT3DSVec3 endDir = nextQuat.rotate(inStartDirection);
+ QT3DSVec3 arcStart = inStartPos + (startDir * inArcLen);
+ QT3DSVec3 arcEnd = inStartPos + (endDir * inArcLen);
+ m_ImmediateBuffer.push_back(SImmediateVertex(inStartPos, inFillColor));
+ m_ImmediateBuffer.push_back(SImmediateVertex(arcStart, inFillColor));
+ m_ImmediateBuffer.push_back(SImmediateVertex(arcEnd, inFillColor));
+ }
+ }
+
+ void EndImmediateDrawing(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext, const QT3DSMat44 &inProjection)
+ {
+ static qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_color", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 4, 12),
+ };
+
+ if (m_ImmediateBuffer.empty())
+ return;
+
+ CRegisteredString theShaderName(
+ inRenderContext.GetStringTable().RegisterStr("StudioWidgetImmedateShader"));
+ m_ImmediateShader = inWidgetContext.GetShader(theShaderName);
+
+ if (m_ImmediateShader == nullptr) {
+ uic::render::IShaderProgramGenerator &theGenerator(
+ inWidgetContext.GetProgramGenerator());
+ theGenerator.BeginProgram();
+ uic::render::IShaderStageGenerator &theVertexGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Vertex));
+ uic::render::IShaderStageGenerator &theFragmentGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddIncoming("attr_color", "vec4");
+ theVertexGenerator.AddUniform("model_view_projection", "mat4");
+ theVertexGenerator.AddOutgoing("vertex_color", "vec4");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append(
+ "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ theVertexGenerator.Append("\tvertex_color = attr_color;");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tgl_FragColor = vertex_color;");
+ theFragmentGenerator.Append("}");
+
+ m_ImmediateShader = inWidgetContext.CompileAndStoreShader(theShaderName);
+ }
+
+ CRegisteredString theBufferName =
+ inRenderContext.GetStringTable().RegisterStr("StudioWidgetImmediateBuffer");
+ m_ImmediateVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer(
+ theBufferName, 3 * sizeof(QT3DSF32) + 4 * sizeof(QT3DSF32),
+ toU8DataRef(m_ImmediateBuffer.begin(), m_ImmediateBuffer.size()));
+
+ if (!m_ImmediateInputAssembler) {
+ QT3DSU32 stride = m_ImmediateVertexBuffer->GetStride();
+ QT3DSU32 offset = 0;
+ NVRenderAttribLayout *theAttribLayout =
+ &inWidgetContext.CreateAttributeLayout(toConstDataRef(theEntries, 2));
+
+ CRegisteredString theString =
+ inRenderContext.GetStringTable().RegisterStr("StudioWidgetImmediateBuffer");
+ m_ImmediateInputAssembler = &inWidgetContext.GetOrCreateInputAssembler(
+ theString, theAttribLayout, toConstDataRef(&m_ImmediateVertexBuffer, 1), nullptr,
+ toConstDataRef(&stride, 1), toConstDataRef(&offset, 1));
+ }
+
+ if (m_ImmediateShader && m_ImmediateInputAssembler) {
+ inRenderContext.SetActiveShader(m_ImmediateShader);
+ m_ImmediateShader->SetPropertyValue("model_view_projection", inProjection);
+ inRenderContext.SetInputAssembler(m_ImmediateInputAssembler);
+ inRenderContext.Draw(NVRenderDrawMode::Triangles,
+ m_ImmediateInputAssembler->GetVertexCount(), 0);
+ }
+ }
+
+ void SetAxisScale(const QT3DSVec3 &inAxisScale) override { m_AxisScale = inAxisScale; }
+
+ void SetRotationEdges(const QT3DSVec3 &inStartDirection, const QT3DSVec3 &inRotationAxis,
+ QT3DSF32 inAngleRad, QT3DSF32 inEndLineLen) override
+ {
+ m_RotationWedge =
+ SRotationWedge(inStartDirection, inRotationAxis, inAngleRad, inEndLineLen);
+ }
+
+ void ClearRotationEdges() override { m_RotationWedge = Empty(); }
+
+ static inline QT3DSF32 ToGLSLColor(QT3DSU32 inItem) { return (QT3DSF32)inItem * 1.0f / 255.0f; }
+ static inline QT3DSVec3 ToGLSLColor(QT3DSU32 R, QT3DSU32 G, QT3DSU32 B)
+ {
+ return QT3DSVec3(ToGLSLColor(R), ToGLSLColor(G), ToGLSLColor(B));
+ }
+
+ static QT3DSVec3 GetXAxisColor() { return ToGLSLColor(202, 47, 46); }
+ static QT3DSVec3 GetYAxisColor() { return ToGLSLColor(100, 205, 53); }
+ static QT3DSVec3 GetZAxisColor() { return ToGLSLColor(30, 159, 205); }
+
+ static inline QT3DSF32 GetDiscPos() { return 65.0f; }
+ static inline QT3DSF32 GetDiscRadius() { return 7.0f; }
+ static inline QT3DSF32 GetDiscRingRadius() { return GetDiscRadius() + 2.0f; }
+ };
+}
+}
+
+#endif
diff --git a/src/Authoring/Studio/Render/WGLRenderContext.cpp b/src/Authoring/Studio/Render/WGLRenderContext.cpp
new file mode 100644
index 00000000..36130d0d
--- /dev/null
+++ b/src/Authoring/Studio/Render/WGLRenderContext.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "stdafx.h"
+
+#include "WGLRenderContext.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "render/Qt3DSRenderContext.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSLogging.h"
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QSurfaceFormat>
+#include <QOpenGLWidget>
+
+//UIC_DEFINE_THISFILE;
+
+//=============================================================================
+/**
+ * Constructor: Creates the object
+ */
+CWGLRenderContext::CWGLRenderContext(UICWindow inWindow)
+ : m_qtContext(0)
+ , m_Foundation(Q3DStudio::Foundation::SStudioFoundation::Create())
+{
+ Open(inWindow);
+}
+
+//=============================================================================
+/**
+ * Destructor: Destroys the object.
+ */
+CWGLRenderContext::~CWGLRenderContext()
+{
+ Close();
+}
+
+//=============================================================================
+/**
+ * Open the render context.
+ * @param inRenderWindow window handle
+ * @param inWindowSize window size
+ */
+void CWGLRenderContext::Open(UICWindow inRenderWindow)
+{
+ // needed because NVidia cards will fail all the system functions below if there is no window.
+ // note: the only time inRenderWindow is nullptr is when CThumbnailGenerator is used. Bug3075.
+ if (!inRenderWindow)
+ return;
+
+ QObject* qObject = static_cast<QObject*>(inRenderWindow);
+ QOpenGLWidget* qRenderWidget = qobject_cast<QOpenGLWidget*>(qObject);
+ Q_ASSERT(qRenderWidget);
+
+ OpenNormalContext(qRenderWidget);
+}
+
+QSurfaceFormat CWGLRenderContext::selectSurfaceFormat(QOpenGLWidget* window)
+{
+ struct ContextVersion {
+ int major;
+ int minor;
+ qt3ds::render::NVRenderContextType contextType;
+ };
+
+ ContextVersion versions[] = {
+ {4, 1, qt3ds::render::NVRenderContextValues::GL4},
+ {3, 3, qt3ds::render::NVRenderContextValues::GL3},
+ {2, 1, qt3ds::render::NVRenderContextValues::GL2},
+ {0, 0, qt3ds::render::NVRenderContextValues::NullContext}
+ };
+
+ QSurfaceFormat result = window->format();
+ bool valid = false;
+
+ for (const auto& ver : versions) {
+ if (ver.contextType == qt3ds::render::NVRenderContextValues::NullContext)
+ break;
+
+ // make an offscreen surface + context to query version
+ QScopedPointer<QOffscreenSurface> offscreenSurface(new QOffscreenSurface);
+
+ QSurfaceFormat format = window->format();
+ format.setRenderableType(QSurfaceFormat::OpenGL);
+ if (ver.major >= 2)
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ format.setMajorVersion(ver.major);
+ format.setMinorVersion(ver.minor);
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+
+ offscreenSurface->setFormat(format);
+ offscreenSurface->create();
+ Q_ASSERT(offscreenSurface->isValid());
+
+ QScopedPointer<QOpenGLContext> queryContext(new QOpenGLContext);
+ queryContext->setFormat(format);
+ if (queryContext->create()) {
+ valid = true;
+ result = format;
+ break;
+ }
+ } // of version test iteration
+
+ if (!valid) {
+ qFatal("Unable to select suitable OpenGL context");
+ }
+
+ qDebug() << Q_FUNC_INFO << "selected surface format:" << result;
+ return result;
+}
+
+//=============================================================================
+/**
+ * Open a non-multisample render context.
+ * @param inRenderWindow window handle
+ * @param inWindowSize window size
+ * @param inPixelDesc the pixel descriptor struct
+ */
+void CWGLRenderContext::OpenNormalContext(QOpenGLWidget* inRenderWindow)
+{
+ // Close before trying to open
+ Close();
+
+ // Save off the window
+ m_Window = inRenderWindow;
+ m_qtContext = m_Window->context();
+ Q_ASSERT(m_qtContext);
+
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> theStringTable =
+ qt3ds::foundation::IStringTable::CreateStringTable(*m_Foundation.m_AllocatorCallback);
+ QSurfaceFormat contextFormat = m_qtContext->format();
+ m_RenderContext = NVScopedRefCounted<NVRenderContext>(
+ NVRenderContext::CreateGL(*m_Foundation.m_Foundation, *theStringTable,
+ contextFormat));
+ if (m_RenderContext) {
+ m_RenderContext->SetDefaultDepthBufferBitCount(contextFormat.depthBufferSize());
+ m_RenderContext->SetDefaultRenderTarget(inRenderWindow->defaultFramebufferObject());
+ }
+}
+
+//=============================================================================
+/**
+ * Close the render context.
+ */
+void CWGLRenderContext::Close()
+{
+ m_qtContext = 0;
+}
+
+//=============================================================================
+/**
+ * Prepare the render context to begin rendering.
+ */
+void CWGLRenderContext::BeginRender()
+{
+ m_Window->makeCurrent();
+ if (m_lastWidgetFBO != m_Window->defaultFramebufferObject()) {
+ m_lastWidgetFBO = m_Window->defaultFramebufferObject();
+ m_RenderContext->SetDefaultRenderTarget(m_lastWidgetFBO);
+ }
+}
+
+//=============================================================================
+/**
+ * Finalize the rendering of this frame, and present the result.
+ */
+void CWGLRenderContext::EndRender()
+{
+ m_Window->doneCurrent();
+}
+
+void CWGLRenderContext::resized()
+{
+ if (m_RenderContext) {
+ m_RenderContext->SetDefaultRenderTarget(m_Window->defaultFramebufferObject());
+ }
+}
+
+void CWGLRenderContext::requestRender()
+{
+ m_Window->update();
+}
diff --git a/src/Authoring/Studio/Render/WGLRenderContext.h b/src/Authoring/Studio/Render/WGLRenderContext.h
new file mode 100644
index 00000000..a6e5bf79
--- /dev/null
+++ b/src/Authoring/Studio/Render/WGLRenderContext.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __WGLRENDERCONTEXT_H_
+#define __WGLRENDERCONTEXT_H_
+#include "PlatformTypes.h"
+#include "Q3DStudioNVFoundation.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+#include <QSurfaceFormat>
+
+QT_BEGIN_NAMESPACE
+class QOpenGLContext;
+class QOpenGLWidget;
+QT_END_NAMESPACE
+
+namespace qt3ds {
+class NVFoundation;
+}
+
+namespace qt3ds {
+namespace render {
+ class NVRenderContext;
+ class CAllocator;
+}
+}
+
+using qt3ds::NVFoundation;
+using qt3ds::render::NVRenderContext;
+using qt3ds::render::CAllocator;
+using qt3ds::foundation::NVScopedRefCounted;
+
+class GLogErrorString;
+
+//==============================================================================
+/**
+ * @class CWGLRenderContext: The OpenGL subclass of the CRenderContext class.
+ */
+class CWGLRenderContext
+{
+ // Field Members
+protected:
+ QOpenGLContext *m_qtContext;
+
+ Q3DStudio::Foundation::SStudioFoundation m_Foundation;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ QOpenGLWidget* m_Window;
+ qt3ds::render::NVRenderContextType m_ContextType;
+
+ quint32 m_lastWidgetFBO = 0;
+
+ // Construction
+public:
+ CWGLRenderContext(UICWindow inRenderWindow);
+ ~CWGLRenderContext();
+
+ // Access
+public:
+ void BeginRender();
+ void EndRender();
+
+ // Only available after open.
+ NVRenderContext &GetRenderContext() { return *m_RenderContext; }
+
+ static QSurfaceFormat selectSurfaceFormat(QOpenGLWidget* window);
+
+ void resized();
+
+ void requestRender();
+
+ // Implementation
+protected:
+ void Open(UICWindow inRenderWindow);
+
+ void OpenNormalContext(QOpenGLWidget* inRenderWindow);
+ void Close();
+};
+
+#endif // __WGLRENDERCONTEXT_H_
diff --git a/src/Authoring/Studio/UI/ContextMenu.h b/src/Authoring/Studio/UI/ContextMenu.h
new file mode 100644
index 00000000..d6b42bbb
--- /dev/null
+++ b/src/Authoring/Studio/UI/ContextMenu.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_CONTEXT_MENU_H
+#define INCLUDED_CONTEXT_MENU_H 1
+
+#pragma once
+
+#ifdef WIN32
+#define MENUHANDLE HMENU
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "GenericFunctor.h"
+#include <vector>
+
+class CContextMenu;
+
+//=============================================================================
+/**
+ * Class declaration for Context Menu performers.
+ */
+class CContextMenuPerformer
+{
+public:
+ CContextMenuPerformer()
+ : m_SubMenu(nullptr)
+ {
+ }
+
+ virtual void OnOptionSelected() = 0;
+
+ void SetSubMenu(CContextMenu *inSubMenu) { m_SubMenu = inSubMenu; }
+ CContextMenu *GetSubMenu() const { return m_SubMenu; }
+
+protected:
+ CContextMenu *m_SubMenu;
+};
+
+//=============================================================================
+/**
+ * Template declaration for Context Menu performers.
+ */
+template <class TClass>
+class CSpecificCContextMenuPerformer : public CContextMenuPerformer
+{
+public:
+ typedef void (TClass::*TFunction)();
+ CSpecificCContextMenuPerformer(TClass *inObject, TFunction inFunction)
+ {
+ m_Object = inObject;
+ m_Function = inFunction;
+ }
+
+ virtual void OnOptionSelected() { (m_Object->*m_Function)(); }
+
+ TClass *m_Object;
+ void (TClass::*m_Function)();
+};
+
+//=============================================================================
+/**
+ * Cross-platform class for creating context menus.
+ */
+class CContextMenu
+{
+ typedef std::vector<CContextMenuPerformer *> TPerformerList;
+ typedef std::vector<Q3DStudio::CString> TOptionList;
+
+public:
+ enum ESelection { NO_SELECTION = -1 };
+
+ CContextMenu();
+ virtual ~CContextMenu();
+
+ long DoPopup(CPt inLocation, HWND inParentWindow);
+ void AddSeparator();
+ void AddOption(int inOptionNameStringID, CContextMenuPerformer *inPerformer,
+ bool inIsEnabled = true);
+ void AddOption(const Q3DStudio::CString &inOptionName, CContextMenuPerformer *inPerformer,
+ bool inIsEnabled = true);
+
+ void Clear();
+ void SetCheck(long inIndex, bool inChecked);
+ void ClearChecked();
+ Q3DStudio::CString GetStringAt(long inIndex);
+ long GetItemCount();
+ long GetSelectedOption() { return m_SelectedOption; }
+ /*
+ template< class TBase >
+ void AddOption( const Q3DStudio::CString& inOptionName, TBase* inClass,
+ CSpecificCContextMenuPerformer<TBase>::TFunction inFunction, bool inIsEnabled )
+ {
+ AddOption( inOptionName, new CSpecificCContextMenuPerformer<TBase>( inClass,
+ inFunction, inIsEnabled ) );
+ }
+ */
+
+ virtual void Update();
+
+ MENUHANDLE GetMenuHandle() const { return m_Menu; }
+ CContextMenuPerformer *GetSelectedMenuPerformer(long inIndex);
+
+ void EnableOptionByIndex(long inIndex, bool inEnabledState = true);
+ void EnableOption(const Q3DStudio::CString &inOptionName, bool inEnabledState = true);
+ void EnableOption(unsigned int inOptionNameStringID, bool inEnabledState = true);
+
+protected:
+ void ProcessSelection(long inIndex);
+ void DeletePerformers();
+
+ TPerformerList m_Performers;
+ TOptionList m_Options;
+ long m_SelectedOption;
+ MENUHANDLE m_Menu;
+ long m_IndexBase; ///< Base index for command ids associated with this context menu
+};
+
+#endif // INCLUDED_CONTEXT_MENU_H \ No newline at end of file
diff --git a/src/Authoring/Studio/UI/CustomReBar.cpp b/src/Authoring/Studio/UI/CustomReBar.cpp
new file mode 100644
index 00000000..31813c3b
--- /dev/null
+++ b/src/Authoring/Studio/UI/CustomReBar.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "CustomReBar.h"
+#include "StudioPreferences.h"
+
+BEGIN_MESSAGE_MAP(CCustomReBar, CReBar)
+//}}AFX_MSG_MAP
+ON_WM_ERASEBKGND()
+END_MESSAGE_MAP()
+
+BOOL CCustomReBar::OnEraseBkgnd(CDC *pDC)
+{
+ CRect theRect;
+ GetClientRect(&theRect);
+ CColor theBaseColor(CStudioPreferences::GetToolBarBaseColor());
+ CBrush theBaseColorBrush(
+ RGB(theBaseColor.GetRed(), theBaseColor.GetGreen(), theBaseColor.GetBlue()));
+ CBrush *pOld = pDC->SelectObject(&theBaseColorBrush);
+ BOOL bRes = pDC->PatBlt(0, 0, theRect.Width(), theRect.Height(), PATCOPY);
+ pDC->SelectObject(pOld); // restore old brush
+ return bRes;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/UI/CustomReBar.h b/src/Authoring/Studio/UI/CustomReBar.h
new file mode 100644
index 00000000..66cbf5a4
--- /dev/null
+++ b/src/Authoring/Studio/UI/CustomReBar.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CUSTOMTOOLBAR_H
+#define INCLUDED_CUSTOMTOOLBAR_H 1
+
+#pragma once
+
+//==============================================================================
+/**
+ * @class CCustomReBar overrides the Win32 CReBar simply to change the background color
+ */
+class CCustomReBar : public CReBar
+{
+public:
+ CCustomReBar() {}
+ ~CCustomReBar() {}
+
+ // Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CCustomToolBar)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+public:
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+};
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/UI/PaletteState.cpp b/src/Authoring/Studio/UI/PaletteState.cpp
new file mode 100644
index 00000000..52750593
--- /dev/null
+++ b/src/Authoring/Studio/UI/PaletteState.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "PaletteState.h"
+#include "Preferences.h"
+
+CPaletteState::CPaletteState(Q3DStudio::CString inWindowName)
+ : m_WindowName(inWindowName)
+ , m_Maximized(false)
+ , m_IsVisible(false)
+{
+}
+
+CPaletteState::~CPaletteState()
+{
+}
+
+CPt CPaletteState::GetPosition() const
+{
+ return m_Position;
+}
+
+void CPaletteState::SetPosition(CPt inPosition)
+{
+ m_Position = inPosition;
+}
+
+CPt CPaletteState::GetSize() const
+{
+ return m_Size;
+}
+
+void CPaletteState::SetSize(CPt inSize)
+{
+ m_Size = inSize;
+}
+
+bool CPaletteState::IsVisible() const
+{
+ return m_IsVisible;
+}
+
+void CPaletteState::SetVisible(bool inIsVisible)
+{
+ m_IsVisible = inIsVisible;
+}
+
+void CPaletteState::LoadState()
+{
+ RestoreDefaults();
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences(m_WindowName);
+
+ m_Maximized = static_cast<bool>(thePrefs.GetValue("maximized", m_Maximized));
+ m_Position.x = thePrefs.GetLongValue("positionX", m_Position.x);
+ m_Position.y = thePrefs.GetLongValue("positionY", m_Position.y);
+ m_Size.x = thePrefs.GetLongValue("sizeX", m_Size.x);
+ m_Size.y = thePrefs.GetLongValue("sizeY", m_Size.y);
+ m_IsVisible = static_cast<bool>(thePrefs.GetValue("visible", m_IsVisible));
+}
+
+void CPaletteState::SaveState() const
+{
+ CPreferences thePrefs = CPreferences::GetUserPreferences(m_WindowName);
+
+ thePrefs.SetValue("maximized", m_Maximized);
+ if (!m_Maximized) {
+ thePrefs.SetLongValue("positionX", m_Position.x);
+ thePrefs.SetLongValue("positionY", m_Position.y);
+ thePrefs.SetLongValue("sizeX", m_Size.x);
+ thePrefs.SetLongValue("sizeY", m_Size.y);
+ }
+ thePrefs.SetValue("visible", m_IsVisible);
+}
+
+void CPaletteState::RestoreDefaults()
+{
+ CPt theDisplaySize = ::GetAvailableDisplaySize();
+ CPt theInitialPos = GetDisplaySize();
+
+ if (m_WindowName == "Library") {
+ m_Position.x = theInitialPos.x;
+ m_Position.y = theInitialPos.y;
+ m_Size.x = ::dtol(theDisplaySize.x * .25);
+ m_Size.y = ::dtol(theDisplaySize.y * .60);
+ m_IsVisible = true;
+ } else if (m_WindowName == "Timeline") {
+ m_Position.x = ::dtol(theDisplaySize.x * .25) + theInitialPos.x;
+ m_Position.y = ::dtol(theDisplaySize.y * .60) + theInitialPos.y;
+ m_Size.x = ::dtol(theDisplaySize.x * .50);
+ m_Size.y = ::dtol(theDisplaySize.y * .40);
+ m_IsVisible = true;
+ } else if (m_WindowName == "Storage") {
+ m_Position.x = ::dtol(theDisplaySize.x * .75) + theInitialPos.x;
+ m_Position.y = ::dtol(theDisplaySize.y * .60) + theInitialPos.y;
+ m_Size.x = ::dtol(theDisplaySize.x * .25);
+ m_Size.y = ::dtol(theDisplaySize.y * .40);
+ m_IsVisible = true;
+ } else if (m_WindowName == "MainWindow") {
+ // m_Position.x = ::dtol( theDisplaySize.x * .25 ) + theInitialPos.x;
+ m_Position.x = theInitialPos.x;
+ m_Position.y = theInitialPos.y;
+ // m_Size.x = ::dtol( theDisplaySize.x * .50 );
+ // m_Size.y = ::dtol( theDisplaySize.y * .60 );
+ m_Size.x = ::dtol(theDisplaySize.x * 1.0);
+ m_Size.y = ::dtol(theDisplaySize.y * 1.0);
+ m_IsVisible = true;
+ } else if (m_WindowName == "Inspector") {
+ m_Position.x = theInitialPos.x;
+ m_Position.y = ::dtol(theDisplaySize.y * .60) + theInitialPos.y;
+ m_Size.x = ::dtol(theDisplaySize.x * .25);
+ m_Size.y = ::dtol(theDisplaySize.y * .40);
+ m_IsVisible = true;
+ } else {
+ m_Position.x = theInitialPos.x;
+ m_Position.y = ::dtol(theDisplaySize.y * .50);
+ m_Size.x = ::dtol(theDisplaySize.x * .25);
+ m_Size.y = ::dtol(theDisplaySize.y * .50);
+ m_IsVisible = true;
+ }
+}
+
+//=============================================================================
+/**
+* @return Returns the resolution in pixels of the current primary display.
+ */
+CPt CPaletteState::GetDisplaySize() const
+{
+ // return CPt( 0, 0 );
+ CRect theWorkArea;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &theWorkArea, FALSE);
+ return CPt(theWorkArea.left, theWorkArea.top);
+}
diff --git a/src/Authoring/Studio/UI/PaletteState.h b/src/Authoring/Studio/UI/PaletteState.h
new file mode 100644
index 00000000..c56b48e6
--- /dev/null
+++ b/src/Authoring/Studio/UI/PaletteState.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_PALETTE_STATE_H
+#define INCLUDED_PALETTE_STATE_H 1
+
+#pragma once
+
+#include "Pt.h"
+
+class CPaletteState
+{
+public:
+ CPaletteState(Q3DStudio::CString inWindowName);
+ virtual ~CPaletteState();
+
+ bool IsMaximized() const { return m_Maximized; }
+ void SetMaximized(bool inMaximized) { m_Maximized = inMaximized; }
+
+ CPt GetPosition() const;
+ void SetPosition(CPt inPosition);
+
+ CPt GetSize() const;
+ void SetSize(CPt inSize);
+
+ bool IsVisible() const;
+ void SetVisible(bool inIsVisible);
+
+ void SaveState() const;
+ void LoadState();
+
+ void RestoreDefaults();
+
+protected:
+ CPt GetDisplaySize() const;
+
+ Q3DStudio::CString m_WindowName;
+ bool m_Maximized;
+ CPt m_Position;
+ CPt m_Size;
+ bool m_IsVisible;
+};
+
+#endif // INCLUDED_PALETTE_STATE_H
diff --git a/src/Authoring/Studio/Utils/CmdLineParser.cpp b/src/Authoring/Studio/Utils/CmdLineParser.cpp
new file mode 100644
index 00000000..2c63c16f
--- /dev/null
+++ b/src/Authoring/Studio/Utils/CmdLineParser.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//=============================================================================
+// Includes
+//==============================================================================
+
+#include "CmdLineParser.h"
+#include "StudioObjectTypes.h"
+#include "UICFile.h"
+#include "UICString.h"
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+//=============================================================================
+/**
+ * Create a new Command Line Parser object.
+ */
+CCmdLineParser::CCmdLineParser()
+ : m_Silent(false)
+ , m_RunUnitTests(false)
+{
+}
+
+CCmdLineParser::~CCmdLineParser()
+{
+}
+
+//=============================================================================
+/**
+ * If the execution mode is to open a file or execute XML tests strings then
+ * this will return the filename used for them.
+ * @return filename for file open or XML tests
+ */
+Q3DStudio::CString CCmdLineParser::GetFilename() const
+{
+ return m_Filename;
+}
+
+//=============================================================================
+/**
+ * Call to parse the specified parameter from the command line format into
+ * a format useful by the app.
+ * @param inParameter the name of the parameter to be parsed.
+ * @param inIsFlag true if the param is a flag, false if it is an argument.
+ */
+void CCmdLineParser::ParseParam(const Q3DStudio::CString &inParameter, bool inIsFlag)
+{
+ if (inIsFlag) {
+ if (inParameter == "t" || inParameter == "test") {
+ m_ExecutionQueue.push_back(TEST_CMD_LINE);
+ m_RunUnitTests = true;
+ } else if (inParameter == "silent") {
+ m_Silent = true;
+ }
+ } else {
+ m_Params.push_back(inParameter);
+ }
+}
+
+//=============================================================================
+/**
+ * Call this to parse all the command line arguments into useful info.
+ * This is most often called with the args from main( ).
+ * @param inArgc the number of argments being given.
+ * @param inArgv the arguments.
+ */
+void CCmdLineParser::ParseArguments(int inArgc, wchar_t **inArgv)
+{
+ m_Filename.Clear();
+ m_Params.clear();
+
+ for (int i = 0; i < inArgc; ++i) {
+ bool isFlag = false;
+ Q3DStudio::CString theArg(inArgv[i]);
+ if (theArg[(long)0] == '-') {
+ isFlag = true;
+ // take off the dash
+ theArg = theArg.Extract(1);
+ }
+ ParseParam(theArg, isFlag);
+ }
+
+ // m_Params[1]is m_Filename
+ // m_Params[0] is the path to the executable
+ if (m_Params.size() > 1) {
+ ConvertToLongFilename(m_Params[1], m_Filename);
+ }
+
+ // Post-processing
+ // If there were no switches modifying m_ExecutionMode, default execution mode
+ // according to the file extension found on m_Filename.
+ if (0 == m_ExecutionQueue.size()) {
+ CUICFile theFile(m_Filename);
+ Q3DStudio::CString theExtension = "." + theFile.GetExtension();
+ if (theExtension.CompareNoCase(::LoadResourceString(IDS_FILE_EXT_UIP)))
+ m_ExecutionQueue.push_back(OPEN_FILE);
+ }
+}
+
+//=============================================================================
+/**
+ * Get the next main mode of execution that the application should be in.
+ * @return EExecutionMode execution mode; END_OF_CMDS if end of queue.
+ */
+CCmdLineParser::EExecutionMode CCmdLineParser::PopExecutionMode()
+{
+ EExecutionMode theMode = END_OF_CMDS;
+ if (m_ExecutionQueue.size() > 0) {
+ theMode = m_ExecutionQueue.front();
+ m_ExecutionQueue.pop_front();
+ }
+ return theMode;
+}
+
+//=============================================================================
+/**
+ * Return true if the silent flag is specified.
+ * @return true if running in muted mode. ie. no dialogs.
+ */
+bool CCmdLineParser::IsSilent() const
+{
+ return m_Silent;
+}
+
+//=============================================================================
+/**
+ * Return true if running unit tests.
+ * @return true if running unit tests.
+ */
+bool CCmdLineParser::IsRunUnitTests() const
+{
+ return m_RunUnitTests;
+}
+
+//=============================================================================
+/**
+ * Converts the specified path to its long form. If no long path is found,
+ * this function simply returns the specified name.
+ * @param inSource Source filename
+ * @param outLongFilename Output filename
+ */
+void CCmdLineParser::ConvertToLongFilename(const Q3DStudio::CString &inSource,
+ Q3DStudio::CString &outLongFilename) const
+{
+#ifdef _WIN32
+ TCHAR thePathBuffer[_MAX_PATH * 2 + 1] = {
+ 0
+ }; // make sure this char buffer is big enough for 2-byte chars
+ long theRet = GetLongPathName(inSource, thePathBuffer, _MAX_PATH * 2);
+ if (theRet != 0 && theRet <= _MAX_PATH * 2)
+ outLongFilename = Q3DStudio::CString(thePathBuffer);
+ else
+ outLongFilename = inSource; // No conversion
+#else
+ outLongFilename = inSource;
+#endif
+}
diff --git a/src/Authoring/Studio/Utils/CmdLineParser.h b/src/Authoring/Studio/Utils/CmdLineParser.h
new file mode 100644
index 00000000..427930a1
--- /dev/null
+++ b/src/Authoring/Studio/Utils/CmdLineParser.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CMD_LINE_PARSER_H
+#define INCLUDED_CMD_LINE_PARSER_H 1
+
+#include <deque>
+
+#include <UICString.h>
+
+class CCmdLineParser
+{
+public:
+ enum EExecutionMode { NORMAL, OPEN_FILE, TEST_CMD_LINE, END_OF_CMDS };
+
+ CCmdLineParser();
+ virtual ~CCmdLineParser();
+
+ void ParseArguments(int inArgc, wchar_t **);
+
+ EExecutionMode PopExecutionMode();
+ bool IsSilent() const;
+ bool IsRunUnitTests() const;
+
+ Q3DStudio::CString GetFilename() const;
+
+protected:
+ virtual void ParseParam(const Q3DStudio::CString &inParameter, bool inIsFlag);
+ void ConvertToLongFilename(const Q3DStudio::CString &inSource,
+ Q3DStudio::CString &outLongFilename) const;
+
+ Q3DStudio::CString m_Filename; ///< input filename for file open
+ bool m_Silent; ///< true if non-dialog alternative output
+ std::vector<Q3DStudio::CString> m_Params; ///< filenames or optional parameters
+ std::deque<EExecutionMode> m_ExecutionQueue; ///< queue holding execution mode commands
+ bool m_RunUnitTests; ///< true if running unit tests
+};
+#endif // INCLUDED_CMD_LINE_PARSER_H
diff --git a/src/Authoring/Studio/Utils/ITickTock.h b/src/Authoring/Studio/Utils/ITickTock.h
new file mode 100644
index 00000000..2a3155bc
--- /dev/null
+++ b/src/Authoring/Studio/Utils/ITickTock.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ITICKTOCKH
+#define ITICKTOCKH
+
+namespace Q3DStudio {
+class CString;
+}
+
+namespace UICDM {
+class ISignalConnection;
+}
+
+QT_BEGIN_NAMESPACE
+class QWidget;
+QT_END_NAMESPACE
+
+typedef std::function<void()> TTickTockProc;
+
+namespace Q3DStudio {
+/**
+ * ITickTock is meant for a relatively small number of scheduled
+ * events that need to happen on the UI thread. Clients can cancel
+ * any event simply by releasing the returned shared pointer.
+ * Interface is completely threadsafe and the returned signal connection
+ * may safely outlive the interface.
+ */
+class ITickTock
+{
+protected:
+ virtual ~ITickTock() {}
+ static ITickTock *m_Instance;
+
+public:
+ // The timer is canceled if the shared ptr deletes the signal connection. Save to call from any
+ // thread.
+ // The callback, however, (inTickTockProc) will be activated solely from the UI thread.
+ virtual std::shared_ptr<UICDM::ISignalConnection>
+ AddTimer(unsigned long inTime, bool inIsPeriodic, TTickTockProc inTickTockProc,
+ const Q3DStudio::CString &inName) = 0;
+
+ // Called from UI thread to process all of the messages
+ // that have happened in the timer thread.
+ // Clients should not generally call this, it will be take care of for them.
+ // In the current implementation, MainFrm.h processes the tick tock message
+ // in order to call this function.
+ virtual void ProcessMessages() = 0;
+
+ friend class std::shared_ptr<ITickTock>;
+
+ // m_Instance is set to the first tick tock created, and unset when that tick tock
+ // goes away.
+ static std::shared_ptr<ITickTock> CreateTickTock(long inMessageID, QWidget* inTarget);
+
+ static ITickTock &GetInstance();
+};
+}
+
+#endif
diff --git a/src/Authoring/Studio/Utils/ImportUtils.cpp b/src/Authoring/Studio/Utils/ImportUtils.cpp
new file mode 100644
index 00000000..0b3ba6a6
--- /dev/null
+++ b/src/Authoring/Studio/Utils/ImportUtils.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "ImportUtils.h"
+#include "Dialogs.h"
+#include "UICFileTools.h"
+
+namespace Q3DStudio {
+
+SObjectFileType ImportUtils::GetObjectFileTypeForFile(const CFilePath &inFile,
+ bool inCheckFileExists /*= true*/)
+{
+ if (inCheckFileExists && inFile.IsFile() == false)
+ return SObjectFileType(OBJTYPE_UNKNOWN, DocumentEditorFileType::Unknown);
+
+ Q3DStudio::CString theExtension(inFile.GetExtension());
+ theExtension.ToLower();
+
+ if (theExtension.Compare(CDialogs::GetImportFileExtension(), Q3DStudio::CString::ENDOFSTRING,
+ false))
+ return SObjectFileType(OBJTYPE_GROUP, DocumentEditorFileType::Import);
+ else if (theExtension.Compare(CDialogs::GetMeshFileExtension(), Q3DStudio::CString::ENDOFSTRING,
+ false))
+ return SObjectFileType(OBJTYPE_MODEL, DocumentEditorFileType::Mesh);
+ else if (CDialogs::IsImageFileExtension(theExtension))
+ return SObjectFileType(
+ OBJTYPE_MODEL, OBJTYPE_IMAGE,
+ DocumentEditorFileType::Image); // Drag-drop image to scene will auto-map to Rectangle.
+ else if (theExtension.Compare(CDialogs::GetLUAFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false)
+ || theExtension.Compare(CDialogs::GetQmlFileExtension(),
+ Q3DStudio::CString::ENDOFSTRING, false))
+ return SObjectFileType(OBJTYPE_BEHAVIOR, DocumentEditorFileType::Behavior);
+ else if (CDialogs::IsFontFileExtension(theExtension))
+ return SObjectFileType(OBJTYPE_TEXT, DocumentEditorFileType::Font);
+ else if (CDialogs::IsEffectFileExtension(theExtension))
+ return SObjectFileType(OBJTYPE_EFFECT, DocumentEditorFileType::Effect);
+ else if (CDialogs::IsMaterialFileExtension(theExtension))
+ return SObjectFileType(OBJTYPE_CUSTOMMATERIAL, DocumentEditorFileType::Material);
+ else if (CDialogs::IsPathFileExtension(theExtension))
+ return SObjectFileType(OBJTYPE_PATH, DocumentEditorFileType::Path);
+ else if (CDialogs::IsPathBufferExtension(theExtension))
+ return SObjectFileType(OBJTYPE_PATH, DocumentEditorFileType::Path);
+ else if (CDialogs::IsSoundFileExtension(theExtension))
+ return SObjectFileType(OBJTYPE_SOUND, DocumentEditorFileType::Sound);
+
+ return SObjectFileType(OBJTYPE_UNKNOWN, DocumentEditorFileType::Unknown);
+}
+
+DocumentEditorInsertType::Enum ImportUtils::GetInsertTypeForDropType(EDROPDESTINATION inDestination)
+{
+ switch (inDestination) {
+ case EDROPDESTINATION_ON:
+ return DocumentEditorInsertType::LastChild;
+ case EDROPDESTINATION_ABOVE:
+ return DocumentEditorInsertType::PreviousSibling;
+ case EDROPDESTINATION_BELOW:
+ return DocumentEditorInsertType::NextSibling;
+ }
+ assert(0);
+ return DocumentEditorInsertType::LastChild;
+}
+}
diff --git a/src/Authoring/Studio/Utils/ImportUtils.h b/src/Authoring/Studio/Utils/ImportUtils.h
new file mode 100644
index 00000000..0a41dd9c
--- /dev/null
+++ b/src/Authoring/Studio/Utils/ImportUtils.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef IMPORTUTILSH
+#define IMPORTUTILSH
+#include "DocumentEditorEnumerations.h"
+#include "StudioObjectTypes.h"
+#include "DropSource.h"
+
+namespace Q3DStudio {
+class CFilePath;
+
+struct SObjectFileType
+{
+ EStudioObjectType m_ObjectType; // The Object Type of the File. Used to specify the result
+ // ObjectType when drag-drop file to Scene.
+ EStudioObjectType m_IconType; // The Icon Type of the File. Used for User Interface (what Icon
+ // to display) such as Project Palette.
+ DocumentEditorFileType::Enum m_FileType; // The File Type of the File.
+
+ SObjectFileType(EStudioObjectType inObjectType, EStudioObjectType inIconType,
+ DocumentEditorFileType::Enum inFileType)
+ : m_ObjectType(inObjectType)
+ , m_IconType(inIconType)
+ , m_FileType(inFileType)
+ {
+ }
+
+ SObjectFileType(EStudioObjectType inObjectType, DocumentEditorFileType::Enum inFileType)
+ : m_ObjectType(inObjectType)
+ , m_IconType(inObjectType) // Icon type is same as object type
+ , m_FileType(inFileType)
+ {
+ }
+};
+
+class ImportUtils
+{
+public:
+ static SObjectFileType GetObjectFileTypeForFile(const CFilePath &inPath,
+ bool inCheckFileExists = true);
+
+ static DocumentEditorInsertType::Enum GetInsertTypeForDropType(EDROPDESTINATION inDestination);
+};
+}
+#endif \ No newline at end of file
diff --git a/src/Authoring/Studio/Utils/MouseCursor.h b/src/Authoring/Studio/Utils/MouseCursor.h
new file mode 100644
index 00000000..a346d597
--- /dev/null
+++ b/src/Authoring/Studio/Utils/MouseCursor.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef INCLUDED_MOUSE_CURSOR_H
+#define INCLUDED_MOUSE_CURSOR_H 1
+
+#pragma once
+
+#include <QCursor>
+
+
+//=============================================================================
+// Includes
+//=============================================================================
+
+//=============================================================================
+/**
+ * Cross-platform cursor class.
+ */
+class CMouseCursor
+{
+public:
+ typedef long TUICMouseCursor;
+
+ static const TUICMouseCursor CURSOR_ARROW;
+ static const TUICMouseCursor CURSOR_WAIT;
+ static const TUICMouseCursor CURSOR_RESIZE_LEFTRIGHT;
+ static const TUICMouseCursor CURSOR_RESIZE_UPDOWN;
+ static const TUICMouseCursor CURSOR_GROUP_MOVE;
+ static const TUICMouseCursor CURSOR_GROUP_ROTATE;
+ static const TUICMouseCursor CURSOR_GROUP_SCALE;
+ static const TUICMouseCursor CURSOR_ITEM_MOVE;
+ static const TUICMouseCursor CURSOR_ITEM_ROTATE;
+ static const TUICMouseCursor CURSOR_ITEM_SCALE;
+ static const TUICMouseCursor CURSOR_EDIT_CAMERA_PAN;
+ static const TUICMouseCursor CURSOR_EDIT_CAMERA_ROTATE;
+ static const TUICMouseCursor CURSOR_EDIT_CAMERA_ZOOM;
+ static const TUICMouseCursor CURSOR_BLANK;
+ static const TUICMouseCursor CURSOR_DROP_INVALID;
+ static const TUICMouseCursor CURSOR_DROP_MOVE;
+ static const TUICMouseCursor CURSOR_DROP_COPY;
+ static const TUICMouseCursor CURSOR_IBEAM;
+
+ CMouseCursor();
+ virtual ~CMouseCursor();
+ QCursor GetHandle();
+ void Show();
+ void Hide();
+ void SetCursorPos(long inXPos, long inYPos);
+ bool Load(TUICMouseCursor inCursor);
+
+protected:
+ void Destroy();
+
+ QCursor m_Handle;
+
+private:
+ bool m_IsThemeCursor;
+ short m_ThemeCursor;
+};
+
+#endif // INCLUDED_MOUSE_CURSOR_H
diff --git a/src/Authoring/Studio/Utils/ResourceCache.cpp b/src/Authoring/Studio/Utils/ResourceCache.cpp
new file mode 100644
index 00000000..5a32ec18
--- /dev/null
+++ b/src/Authoring/Studio/Utils/ResourceCache.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "ResourceCache.h"
+#include "MouseCursor.h"
+#include "StudioUtils.h"
+
+#include <QUrl>
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CResourceCache::CResourceCache()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor: releases all loaded resources.
+ */
+CResourceCache::~CResourceCache()
+{
+ Clear();
+}
+
+//=============================================================================
+/**
+ * Returns a default instance of the resource cache so that the whole application
+ * can use the same cache if desired.
+ * @return Handle to the default instance of the cache
+ */
+CResourceCache *CResourceCache::GetInstance()
+{
+ static CResourceCache theCache;
+ return &theCache;
+}
+
+//=============================================================================
+/**
+ * Retrieves a bitmap image of the specified name. Currently only accepts .png
+ * files.
+ * @param inName Name of the bitmap file to be fetched
+ * @return Pointer to a bitmap object or NULL if the image could not be loaded
+ */
+QPixmap CResourceCache::GetBitmap(const QString &inName)
+{
+ QPixmap theImage;
+
+ // If our image name is not empty, then lets get it...
+ if (!inName.isEmpty()) {
+ TImageMap::iterator thePos = m_Images.find(inName);
+ if (thePos != m_Images.end()) {
+ theImage = thePos->second;
+ } else {
+ const QString resPath = QString("%1%2").arg(resourceImagePath(), inName);
+ if (theImage.load(resPath)) {
+ m_Images[inName] = theImage;
+ } else {
+ qWarning() << Q_FUNC_INFO << "missing image at path:" << resPath;
+ }
+ }
+ }
+ return theImage;
+}
+
+//=============================================================================
+/**
+ * Retrieves the specified cursor resource. The cursor is loaded if necessary
+ * otherwise a previously loaded cursor of the same ID is returned.
+ * @param inResourceID ID of the cursor to be loaded (see SCursor.h)
+ * @return Pointer to the cursor, or NULL if the cursor could not be loaded
+ */
+QCursor CResourceCache::GetCursor(CMouseCursor::TUICMouseCursor inResourceID)
+{
+ CMouseCursor *theCursor = NULL;
+ CMouseCursor::TUICMouseCursor theKey = inResourceID;
+
+ TCursorMap::iterator thePos = m_Cursors.find(theKey);
+ if (thePos != m_Cursors.end()) {
+ theCursor = thePos->second;
+ } else {
+ theCursor = new CMouseCursor();
+ if (theCursor->Load(inResourceID))
+ m_Cursors[theKey] = theCursor;
+ else {
+ delete theCursor;
+ theCursor = nullptr;
+ }
+ }
+
+ return theCursor ? theCursor->GetHandle() : QCursor();
+}
+
+//=============================================================================
+/**
+ * Clears all the maps of resources and deletes any associated resources.
+ * Called by the destructor.
+ */
+void CResourceCache::Clear()
+{
+ m_Images.clear();
+
+ TCursorMap::iterator theCursorPos = m_Cursors.begin();
+ for (; theCursorPos != m_Cursors.end(); ++theCursorPos) {
+ CMouseCursor *theCursor = theCursorPos->second;
+ delete theCursor;
+ }
+ m_Cursors.clear();
+}
diff --git a/src/Authoring/Studio/Utils/ResourceCache.h b/src/Authoring/Studio/Utils/ResourceCache.h
new file mode 100644
index 00000000..4b2f0c39
--- /dev/null
+++ b/src/Authoring/Studio/Utils/ResourceCache.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_RESOURCE_CACHE_H
+#define INCLUDED_RESOURCE_CACHE_H 1
+
+#pragma once
+
+#include "MouseCursor.h"
+#include "UICString.h"
+#include <map>
+
+#include <QCursor>
+#include <QPixmap>
+
+class CResImage;
+
+class CResourceCache
+{
+ typedef std::map<QString, QPixmap> TImageMap;
+ typedef std::map<CMouseCursor::TUICMouseCursor, CMouseCursor *> TCursorMap;
+
+public:
+ CResourceCache();
+ virtual ~CResourceCache();
+
+ static CResourceCache *GetInstance();
+
+ QPixmap GetBitmap(const QString &inName);
+ QCursor GetCursor(CMouseCursor::TUICMouseCursor inResourceID);
+
+ void Clear();
+
+protected:
+ TImageMap m_Images;
+ TCursorMap m_Cursors;
+};
+#endif // INCLUDED_RESOURCE_CACHE_H
diff --git a/src/Authoring/Studio/Utils/StringLoader.cpp b/src/Authoring/Studio/Utils/StringLoader.cpp
new file mode 100644
index 00000000..73a5324f
--- /dev/null
+++ b/src/Authoring/Studio/Utils/StringLoader.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+#include <QtCore/qfile.h>
+#include <QtCore/qxmlstream.h>
+
+CStringLoader CStringLoader::s_GlobalInstance;
+
+CStringLoader::CStringLoader()
+ : m_Strings(nullptr)
+ , m_StringCount(0)
+{
+}
+
+CStringLoader::~CStringLoader()
+{
+ UnloadResourceStrings();
+}
+
+//=============================================================================
+/**
+ * Static function to load the string resource specified by inStringID.
+ * inStringID should have been specified in the Resource.h header file.
+ * This will load the string from the global string resource object.
+ */
+Q3DStudio::CString CStringLoader::LoadString(long inStringID)
+{
+ return s_GlobalInstance.LoadResourceString(inStringID);
+}
+
+//=============================================================================
+/**
+ * Load the string resource specified by inStringID.
+ * inStringID should have been specified in the Resource.h header file.
+ * @param inID the ID of the string to be loaded.
+ * @return theString specified by inStringID.
+ */
+Q3DStudio::CString CStringLoader::LoadResourceString(long inStringID)
+{
+ Q3DStudio::CString theName;
+ // Make sure we aren't going off into la-la land.
+ if (inStringID > 0 && inStringID < m_StringCount) {
+ theName = m_Strings[inStringID];
+ }
+ return theName;
+}
+
+//=============================================================================
+/**
+ * Load the string resources from the specified directory into the global table.
+ * All .stro files in the directory will be processed for strings.
+ * @param inDirectory the directory that should be read for strings.
+ */
+void CStringLoader::LoadStrings(const CUICFile &inDirectory)
+{
+ s_GlobalInstance.LoadResourceStrings(inDirectory);
+}
+
+//=============================================================================
+/**
+ * Load the string resources from the specified directory into this string table.
+ * All .stro files in the directory will be processed for strings.
+ * @param inDirectory the directory that should be read for strings.
+ */
+void CStringLoader::LoadResourceStrings(const CUICFile &inDirectory)
+{
+ UnloadResourceStrings();
+
+ // Sure hope we don't get an absolute ton of strings here...
+ m_Strings = new Q3DStudio::CString[STRING_RESOURCE_COUNT + 1];
+ m_StringCount = STRING_RESOURCE_COUNT;
+
+ Q3DStudio::CString theExtension = ".stro";
+
+ // Go through all the files in the directory and process them.
+ CFileIterator theFiles = inDirectory.GetSubItems();
+ for (; !theFiles.IsDone(); ++theFiles) {
+ CUICFile theFile = theFiles.GetCurrent();
+ Q3DStudio::CString theFilename = theFile.GetAbsolutePath();
+ // Only process .stro files.
+ if (theFilename.Find(theExtension) == theFilename.Length() - theExtension.Length()) {
+ QFile file(theFilename.toQString());
+ file.open(QFile::ReadOnly);
+ QXmlStreamReader reader(&file);
+ while (!reader.atEnd()) {
+ reader.readNextStartElement();
+ if (reader.name() == "string") {
+ Q3DStudio::CString theValue;
+ long theIndex = -1;
+ for (auto attrib : reader.attributes()) {
+ if (attrib.name() == "value")
+ theValue = attrib.value().toUtf8().constData();
+ else if (attrib.name() == "ID")
+ theIndex = attrib.value().toInt();
+ }
+ if (theIndex > 0 && theIndex < STRING_RESOURCE_COUNT) {
+ theValue.Replace("\\n", "\n");
+ theValue.Replace("\\t", "\t");
+ m_Strings[theIndex] = theValue;
+ }
+ }
+ }
+ }
+ }
+}
+
+void CStringLoader::UnloadStrings()
+{
+ s_GlobalInstance.UnloadResourceStrings();
+}
+
+void CStringLoader::UnloadResourceStrings()
+{
+ delete[] m_Strings;
+ m_Strings = nullptr;
+ m_StringCount = 0;
+}
+
+Q3DStudio::CString LoadResourceString(long inID)
+{
+ return CStringLoader::LoadString(inID);
+}
diff --git a/src/Authoring/Studio/Utils/StringLoader.h b/src/Authoring/Studio/Utils/StringLoader.h
new file mode 100644
index 00000000..69595566
--- /dev/null
+++ b/src/Authoring/Studio/Utils/StringLoader.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STRING_LOADER_H
+#define INCLUDED_STRING_LOADER_H 1
+#pragma once
+
+#include "UICFile.h"
+
+class CStringLoader
+{
+public:
+ CStringLoader();
+ virtual ~CStringLoader();
+
+ static Q3DStudio::CString LoadString(long inStringID);
+ static void LoadStrings(const CUICFile &inDirectory);
+ static void UnloadStrings();
+
+ Q3DStudio::CString LoadResourceString(long inStringID);
+ void LoadResourceStrings(const CUICFile &inDirectory);
+ void UnloadResourceStrings();
+
+protected:
+ Q3DStudio::CString *m_Strings;
+ long m_StringCount;
+
+ static CStringLoader s_GlobalInstance;
+};
+
+Q3DStudio::CString LoadResourceString(long inID);
+
+#endif // INCLUDED_STRING_LOADER_H
diff --git a/src/Authoring/Studio/Utils/StudioUtils.cpp b/src/Authoring/Studio/Utils/StudioUtils.cpp
new file mode 100644
index 00000000..34522198
--- /dev/null
+++ b/src/Authoring/Studio/Utils/StudioUtils.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CoreUtils.h"
+#include "StudioPreferences.h"
+#include "StudioClipboard.h"
+#include "Pt.h"
+
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qdesktopwidget.h>
+#include <QtGui/qdesktopservices.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qwindow.h>
+#include <QtCore/qurl.h>
+
+//==============================================================================
+/**
+ * FormatTimeString: Format a time string.
+ * @param inTimeMS Time in milliseconds.
+ * @return The formatted time string in MM:SS:MS format.
+ */
+Q3DStudio::CString FormatTimeString(long inTimeMS)
+{
+ BOOL theNegativeFlag = (inTimeMS < 0);
+ long theTimeMS = abs(inTimeMS);
+ Q3DStudio::CString theTimeString;
+ long theMM, theSS;
+
+ // Format the time in MM:SS:MS format
+
+ // Get the MM value
+ theMM = theTimeMS / 60000;
+ theTimeMS -= (theMM * 60000);
+
+ // Get the SS value
+ theSS = theTimeMS / 1000;
+ theTimeMS -= (theSS * 1000);
+
+ // Remainder is MS value
+
+ // Format the string
+ theTimeString.Format(_UIC("%d:%0.2d.%0.2d"), theMM, theSS, theTimeMS / 10);
+
+ // If the original time was negative, append the "-" to the front of the time string.
+ if (theNegativeFlag) {
+ theTimeString.Insert(0, "-");
+ }
+
+ return theTimeString;
+}
+
+//==============================================================================
+/**
+ * Checks a string to determine if it is numeric.
+ * @param inString String to check for all numeric characters.
+ * @return TRUE if the string is numeric.
+ */
+bool IsNumericString(const Q3DStudio::CString &inString)
+{
+ Q3DStudio::CString theNumbers = "0123456789";
+ long theLoop;
+ bool theNumericFlag = true;
+
+ // Iterate through the entire string
+ for (theLoop = 0; theLoop < inString.Length() && theNumericFlag; theLoop++) {
+ // Check each character for being numeric
+ if (theNumbers.Find(inString.Extract(theLoop, 1)) == Q3DStudio::CString::ENDOFSTRING)
+ theNumericFlag = false;
+ }
+
+ return theNumericFlag;
+}
+
+//=============================================================================
+/**
+ * @return The available resolution in pixels of the display index "screen"
+ * (minus the Dock/Taskbar, etc.). Default is current primary display.
+ */
+QSize GetAvailableDisplaySize(int screen)
+{
+ return QApplication::desktop()->availableGeometry(screen).size();
+}
+
+//=============================================================================
+/**
+* @return The total resolution in pixels of the display index "screen".
+* Default is the current primary display.
+ */
+QSize GetDisplaySize(int screen)
+{
+ return QApplication::desktop()->screenGeometry(screen).size();
+
+}
+
+//=============================================================================
+/**
+* @return The index of the screen containing "widget".
+ */
+int getWidgetScreen(QWidget *widget)
+{
+ return QApplication::desktop()->screenNumber(widget);
+}
+
+//=============================================================================
+/**
+ * Helper function to adjust the point for the color popup dialog so that it
+ * ends up in the right place. Adjust the given point if it is near the left
+ * or bottom part of the screen.
+ * @param ioPoint upper-left corner of the color popup dialog; will be adjust if necessary on return
+ */
+void TranslatePoint(QPoint &ioPoint, const QPoint &inSize)
+{
+ long theBuffer = 10; // Just because the taskbar seems to overlap the dialog by a little bit
+ QPoint theDlgSize(150, 260); // Size of color popup dialog - note that it's hard-coded
+ QSize theScreenSize = GetAvailableDisplaySize(-1);
+ long theVertOffset = theDlgSize.y() - inSize.y();
+ long theHorizOffset = theDlgSize.x();
+
+ // If the point is too close to both the left side and the bottom of the screen, adjust both the
+ // x and y values
+ if ((ioPoint.y() > theScreenSize.height() - theVertOffset - theBuffer)
+ && (ioPoint.x() >= theScreenSize.width() - theHorizOffset)) {
+
+ ioPoint.setX(ioPoint.x() - (theHorizOffset + inSize.x()));
+ ioPoint.setY(ioPoint.y() - theVertOffset);
+ }
+ // If the point is just too close to the bottom of the screen, adjust the y value
+ else if (ioPoint.y() > theScreenSize.height() - theVertOffset - theBuffer)
+ ioPoint.setY(ioPoint.y() - theVertOffset);
+ // If the point is just too close to the left side of the screen, adjust the x value
+ else if (ioPoint.x() >= theScreenSize.width() - theHorizOffset)
+ ioPoint.setX(ioPoint.x() - (theHorizOffset + inSize.x()));
+}
+
+long TimeToPos(long inTime, double inTimeRatio)
+{
+ return ::dtol(inTime * inTimeRatio) + CStudioPreferences::GUTTER_SIZE;
+}
+
+long TimeToPos(double inTime, double inTimeRatio)
+{
+ return ::dtol(inTime * inTimeRatio) + CStudioPreferences::GUTTER_SIZE;
+}
+
+long PosToTime(long inPos, double inTimeRatio)
+{
+ return ::dtol((inPos - CStudioPreferences::GUTTER_SIZE) / inTimeRatio);
+}
+
+//=============================================================================
+/**
+ * opens the url in the web browser
+ *
+ * @param inURL
+ * the URL to open
+ *
+ * @return void
+ */
+void ShowURLInBrowser(const Q3DStudio::CString &inURL)
+{
+ QDesktopServices::openUrl(QUrl(inURL.toQString()));
+}
+
+QString resourcePath()
+{
+ return QStringLiteral(":/res");
+}
+
+QString resourceImagePath()
+{
+ return QStringLiteral(":/images/");
+}
+
+QString resourceImageUrl()
+{
+ return QStringLiteral("qrc:/images/");
+}
+
+// Returns the qml import path required for binary installations
+QString qmlImportPath()
+{
+ QString extraImportPath(QStringLiteral("%1/qml"));
+ return extraImportPath.arg(QApplication::applicationDirPath());
+}
+
+qreal devicePixelRatio()
+{
+ static qreal pixelRatio = 0.0;
+ if (Q_UNLIKELY(pixelRatio == 0.0)) {
+ const QWindowList list = QGuiApplication::topLevelWindows();
+ if (list.size() > 0)
+ pixelRatio = list[0]->devicePixelRatio();
+ }
+ return pixelRatio;
+}
diff --git a/src/Authoring/Studio/Utils/StudioUtils.h b/src/Authoring/Studio/Utils/StudioUtils.h
new file mode 100644
index 00000000..4e248bb3
--- /dev/null
+++ b/src/Authoring/Studio/Utils/StudioUtils.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STUDIO_UTILS_H
+#define INCLUDED_STUDIO_UTILS_H 1
+
+#pragma once
+
+#include "UICString.h"
+#include <QPoint>
+#include <QSize>
+
+//==============================================================================
+// Functions
+//==============================================================================
+Q3DStudio::CString FormatTimeString(long inTimeMS);
+bool IsNumericString(Q3DStudio::CString inString);
+
+QSize GetAvailableDisplaySize(int screen = -1);
+QSize GetDisplaySize(int screen = -1);
+void TranslatePoint(QPoint &ioPoint, const QPoint &inSize);
+
+long TimeToPos(long inTime, double inTimeRatio);
+long TimeToPos(double inTime, double inTimeRatio);
+long PosToTime(long inPos, double inTimeRatio);
+
+void ShowURLInBrowser(Q3DStudio::CString inURL);
+
+QString resourceImagePath();
+QString resourceImageUrl();
+
+QString resourcePath();
+
+QString qmlImportPath();
+
+qreal devicePixelRatio();
+
+int getWidgetScreen(QWidget *widget);
+
+#endif // INCLUDED_STUDIO_UTILS_H
diff --git a/src/Authoring/Studio/Utils/SystemPreferences.cpp b/src/Authoring/Studio/Utils/SystemPreferences.cpp
new file mode 100644
index 00000000..85e5a58b
--- /dev/null
+++ b/src/Authoring/Studio/Utils/SystemPreferences.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CColor.h"
+#include "SystemPreferences.h"
+
+#include <QApplication>
+#include <QPalette>
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSystemPreferences::~CSystemPreferences()
+{
+}
+
+//=============================================================================
+/**
+ * Retrieves the system preferred background color. Example use would be for
+ * the fill color of a button.
+ */
+QColor CSystemPreferences::GetSystemBackgroundColor()
+{
+ const auto palette = QApplication::palette();
+ return palette.color(QPalette::Active, QPalette::Button);
+}
+
+//=============================================================================
+/**
+ * Returns the color used by the system to indicate that an item is selected.
+ */
+QColor CSystemPreferences::GetSelectedItemColor()
+{
+ const auto palette = QApplication::palette();
+ return palette.color(QPalette::Active, QPalette::Highlight);
+}
+
+//=============================================================================
+/**
+ * Returns the color of selected text to be displayed on top of GetSelectedItemColor().
+ */
+QColor CSystemPreferences::GetSelectedTextColor()
+{
+ const auto palette = QApplication::palette();
+ return palette.color(QPalette::Active, QPalette::HighlightedText);
+}
+
+//=============================================================================
+/**
+ * Supposed to get whether or not anti aliasing should be enabled for a specified
+ * font size, but the Theme does not seem to include any data on it. If the
+ * theme starts working in a later release of the OS then this should work.
+ */
+bool CSystemPreferences::IsFontAntiAliasing(float inFontSize)
+{
+ Q_UNUSED(inFontSize);
+ return false;
+}
+
+//=============================================================================
+/**
+ * Scroll bars contain two arrows (up/down or left/right). These can be located
+ * on either end of the scroll bar, or located next to each other at one end. On
+ * Mac OS X, this is a system preference.
+ * @return true if the scroll bar arrows should be next to each other, at one end of the scroll bar
+ */
+bool CSystemPreferences::AreScrollArrowsAdjacent()
+{
+ return false;
+}
diff --git a/src/Authoring/Studio/Utils/SystemPreferences.h b/src/Authoring/Studio/Utils/SystemPreferences.h
new file mode 100644
index 00000000..2d72780e
--- /dev/null
+++ b/src/Authoring/Studio/Utils/SystemPreferences.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_SYSTEM_PREFERENCES_H
+#define INCLUDED_SYSTEM_PREFERENCES_H 1
+
+#pragma once
+
+class CColor;
+
+class CSystemPreferences
+{
+public:
+ CSystemPreferences();
+ virtual ~CSystemPreferences();
+ static QColor GetSystemBackgroundColor();
+ static QColor GetSelectedItemColor();
+ static QColor GetSelectedTextColor();
+ static bool IsFontAntiAliasing(float inFontSize);
+ static bool AreScrollArrowsAdjacent();
+};
+
+#endif // INCLUDED_SYSTEM_PREFERENCES_H
diff --git a/src/Authoring/Studio/Utils/TickTock.cpp b/src/Authoring/Studio/Utils/TickTock.cpp
new file mode 100644
index 00000000..dcf6eb8a
--- /dev/null
+++ b/src/Authoring/Studio/Utils/TickTock.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "ITickTock.h"
+#include "UICDMSignals.h"
+#include "Thread.h"
+#include "Mutex.h"
+#include "Conditional.h"
+#include "StandardExtensions.h"
+#include <vector>
+
+#include <QCoreApplication>
+#include <QDateTime>
+#include <QWidget>
+
+using namespace Q3DStudio;
+using Q3DStudio::CString;
+using namespace UICDM;
+using namespace std;
+
+namespace {
+
+struct TickTockImpl;
+
+struct TickTockItem : public ISignalConnection
+{
+ TTickTockProc m_Callback;
+ bool m_IsPeriodic;
+ unsigned long m_Time;
+ quint64 m_NextTime;
+ CString m_Name;
+ TickTockImpl *m_Impl;
+
+ TickTockItem(TTickTockProc inCallback, bool inPeriodic, unsigned long inTime,
+ quint64 inNextTime, const CString &inName, TickTockImpl &inImpl)
+ : m_Callback(inCallback)
+ , m_IsPeriodic(inPeriodic)
+ , m_Time(inTime)
+ , m_NextTime(inNextTime)
+ , m_Name(inName)
+ , m_Impl(&inImpl)
+ {
+ }
+ // Implemented below to access TickTockImpl API
+ virtual ~TickTockItem();
+
+ // Called when our tick tock impl is through with us.
+ // We cannot access the tick tock impl after this as
+ // it could cause a crash
+ void Release() { m_Impl = nullptr; }
+
+ void Signal()
+ {
+ if (m_Impl)
+ m_Callback();
+ }
+ bool operator<(const TickTockItem &inOther) const { return m_NextTime < inOther.m_NextTime; }
+};
+
+struct TickTockDerefCompare
+{
+ bool operator()(const TickTockItem *lhs, const TickTockItem *rhs) { return *lhs < *rhs; }
+};
+
+typedef vector<TickTockItem *> TTockList;
+
+/**
+ * Struct that implements the ITickTock interface via a thread that runs
+ * and schedules information and a message that is sent back in order to
+ * process that schedule information and send out signals on the UI thread.
+ */
+struct TickTockImpl : public ITickTock, public CRunnable
+{
+ // Mutex to protect our internal datastructures
+ // Mainly m_Tockers and m_SignalledTockers
+ CMutex m_Mutex;
+ // Our thread
+ CThread m_Thread;
+ // Event to wake up schedule thread; used to keep thread from
+ // spinning till next event.
+ CConditional m_Event;
+
+ // The sorted list (by m_NextTime) of tick tock signals
+ TTockList m_Tockers;
+ // The list of signals that are past their time and need to be sent.
+ TTockList m_SignalledTockers;
+ // True if the thread is running and we want it to continue.
+ volatile bool m_IsRunning;
+ // Message to fire into the window in order to get our notifications
+ // processed on the UI thread
+ long m_MessageID;
+ // Target window that we use in order to fire events and get processing
+ // done back on the UI thread from the schedule thread.
+ QWidget *m_Target;
+
+ TickTockImpl(long inMessageID, QWidget *inTarget)
+ : m_Thread(this, "ITickTock", NULL, false)
+ , m_IsRunning(false)
+ , m_MessageID(inMessageID)
+ , m_Target(inTarget)
+ {
+ }
+
+ virtual void Initialize()
+ {
+ m_IsRunning = true;
+ m_Thread.Start();
+ }
+
+ virtual ~TickTockImpl()
+ {
+ if (m_Instance == this)
+ m_Instance = nullptr;
+ {
+ CMutex::Scope __mutexScope(&m_Mutex);
+ UnsafeReleaseTockers(m_Tockers);
+ UnsafeReleaseTockers(m_SignalledTockers);
+ }
+
+ if (m_IsRunning) {
+ m_IsRunning = false;
+ // Wake up the thread to notify it to exit
+ m_Event.Notify();
+ // Wait for the thread to exit.
+ m_Thread.Join();
+ }
+ }
+
+ TSignalConnectionPtr AddTimer(unsigned long inTime, bool inIsPeriodic,
+ TTickTockProc inTickTockProc,
+ const Q3DStudio::CString &inName) override
+ {
+ // Lock down so we don't conflict with the timer thread.
+ CMutex::Scope __mutexScope(&m_Mutex);
+
+ std::shared_ptr<TickTockItem> retval =
+ std::make_shared<TickTockItem>(inTickTockProc, inIsPeriodic, inTime,
+ QDateTime::currentMSecsSinceEpoch() + inTime, inName, std::ref(*this));
+ if (inTime > 0) {
+ UnsafeInsertTimer(*retval);
+ } else {
+ assert(inIsPeriodic == false);
+ m_SignalledTockers.push_back(retval.get());
+ }
+ m_Event.Notify();
+
+ return retval;
+ }
+
+ void RemoveTimer(TickTockItem &inItem)
+ {
+ CMutex::Scope __mutexScope(&m_Mutex);
+ UnsafeRemoveTimer(inItem, m_Tockers);
+ UnsafeRemoveTimer(inItem, m_SignalledTockers);
+ }
+
+ //=============================================================================
+ /**
+ * Call from the main processing thread to process any existing messages.
+ * This should be called when a message of the type specified in the constructor
+ * is recieved. This will call all the functors on the timers that have
+ * triggered.
+ */
+ void ProcessMessages() override
+ {
+ quint64 theCurrentTime = QDateTime::currentMSecsSinceEpoch();
+
+ CMutex::Scope __mutexScope(&m_Mutex);
+ // Go through all the timers looking for expired ones
+ for (TTockList::iterator theTocks = m_SignalledTockers.begin(),
+ end = m_SignalledTockers.end();
+ theTocks != end; ++theTocks) {
+ TickTockItem *theTock = (*theTocks);
+ // If this item hasn't been released in another thread.
+ if (theTock->m_Impl) {
+ theTock->Signal();
+
+ // If it is periodic, re-add it.
+ if (theTock->m_IsPeriodic == true) {
+ theTock->m_NextTime = theCurrentTime + theTock->m_Time;
+ UnsafeInsertTimer(*theTock);
+ }
+ // If it isn't, then we forget about it. The client's have a shared-ptr
+ // to the object so it will get deleted eventually, it just isn't any of
+ // our business any more
+ else
+ theTock->Release();
+ }
+ }
+
+ m_SignalledTockers.clear();
+ m_Event.Notify();
+ }
+
+ void Run(void *) override
+ {
+ unsigned long theNextTime = (unsigned long)-1;
+ // Stay in this loop until the running flag is turned off on the constructor.
+ while (m_IsRunning) {
+ // Wait for either the next time or the change notification
+ m_Event.Wait(theNextTime);
+
+ CMutex::Scope __mutexScope(&m_Mutex);
+
+ // Get the amount of time this should sleep for.
+ theNextTime = (unsigned long)-1;
+ quint64 theCurrentTime = QDateTime::currentMSecsSinceEpoch();
+ // We know that m_Tocks is sorted by m_NextTime.
+ // So we run through it linearly, transferring singalled items
+ // into the signalled vector.
+ size_t idx = 0, end = m_Tockers.size();
+ for (; idx < end; ++idx) {
+ TickTockItem *item(m_Tockers[idx]);
+ if (item->m_NextTime <= theCurrentTime && item->m_Impl != nullptr) {
+ m_SignalledTockers.push_back(item);
+ } else
+ break;
+ }
+ // We then remove all signalled items.
+ if (m_Tockers.empty() == false)
+ m_Tockers.erase(m_Tockers.begin(), m_Tockers.begin() + idx);
+
+ // And we reset next time to the difference between the current time
+ // and the first tock's next time.
+ if (m_Tockers.empty() == false) {
+ assert(m_Tockers.front()->m_NextTime > theCurrentTime);
+ theNextTime = m_Tockers.front()->m_NextTime - theCurrentTime;
+ }
+
+ if (m_SignalledTockers.empty() == false) {
+ // Send the async notification that timers have expired.
+ qApp->postEvent(m_Target, new QTimerEvent(m_MessageID));
+ }
+ }
+ }
+
+private:
+ ////////////////////////////////////////////////////////////////
+ // Unsafe functions are functions that require the mutex locked
+ // in order to function correctly
+ ////////////////////////////////////////////////////////////////
+ void UnsafeInsertTimer(TickTockItem &inItem)
+ {
+ binary_sort_insert_unique(m_Tockers, &inItem, TickTockDerefCompare());
+ }
+
+ void UnsafeReleaseTockers(TTockList &inTockers)
+ {
+ for (size_t idx = 0, end = inTockers.size(); idx < end; ++idx)
+ inTockers[idx]->Release();
+ inTockers.clear();
+ }
+
+ // Unsafe means we don't have the mutex
+ void UnsafeRemoveTimer(TickTockItem &inItem, TTockList &ioList)
+ {
+ TTockList::iterator theTimer = std::find(ioList.begin(), ioList.end(), &inItem);
+ if (theTimer != ioList.end())
+ ioList.erase(theTimer);
+ }
+};
+
+TickTockItem::~TickTockItem()
+{
+ if (m_Impl != NULL)
+ m_Impl->RemoveTimer(*this);
+ m_Impl = NULL;
+}
+}
+
+ITickTock *ITickTock::m_Instance(NULL);
+
+std::shared_ptr<ITickTock> ITickTock::CreateTickTock(long inMessageID, QWidget *inWnd)
+{
+ std::shared_ptr<TickTockImpl> theTickTock(
+ std::make_shared<TickTockImpl>(inMessageID, std::ref(inWnd)));
+ theTickTock->Initialize();
+ if (m_Instance == NULL)
+ m_Instance = theTickTock.get();
+ return theTickTock;
+}
+
+ITickTock &ITickTock::GetInstance()
+{
+ return *m_Instance;
+}
diff --git a/src/Authoring/Studio/Workspace/Dialogs.h b/src/Authoring/Studio/Workspace/Dialogs.h
new file mode 100644
index 00000000..012ce98f
--- /dev/null
+++ b/src/Authoring/Studio/Workspace/Dialogs.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#ifndef INCLUDED_DIALOGS_H
+#define INCLUDED_DIALOGS_H 1
+
+#pragma once
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "UICFile.h"
+#include "StudioObjectTypes.h"
+#include "UICMessageBox.h"
+//#include "MultilineEditDlg.h"
+#include "UICFileTools.h"
+#include "CColor.h"
+#include <QMessageBox>
+
+//=============================================================================
+// Forwards
+//=============================================================================
+class IDoc;
+class CStudioApp;
+class CControl;
+class CDialogControl;
+class IProgressCallback;
+
+class CProgressPalette;
+
+class CDialogs
+{
+public:
+ enum ESavePromptResult {
+ CANCEL_OPERATION,
+ CONTINUE_NO_SAVE,
+ SAVE_FIRST,
+ };
+
+ CDialogs(bool inShowGUI = true);
+ virtual ~CDialogs();
+
+ void DisplayAssetDeleteFailed();
+ void DisplayRefreshResourceFailed(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription);
+ QString ConfirmRefreshModelFile(const QString &inOriginalPath);
+
+ // This is not an appropriate place for these, but better
+ // in an inappropriate place than duplicated
+ static const char *GetDAEFileExtension();
+ static const char *GetFbxFileExtension();
+ // Null terminated list
+ static const char **GetImgFileExtensions();
+ static const char *GetImportFileExtension();
+ static const char *GetMeshFileExtension();
+ static const char *GetLUAFileExtension();
+ static const char *GetQmlFileExtension();
+ static const char **GetFontFileExtensions();
+ static const char **GetEffectFileExtensions();
+ static const char **GetMaterialFileExtensions();
+ static const char **GetSoundFileExtensions();
+ static bool IsImageFileExtension(const char *inExt);
+ static bool IsFontFileExtension(const char *inExt);
+ static bool IsEffectFileExtension(const char *inExt);
+ static bool IsMaterialFileExtension(const char *inExt);
+ static bool IsSoundFileExtension(const char *inExt);
+
+ static const wchar_t *GetWideDAEFileExtension();
+ static const wchar_t *GetWideFbxFileExtension();
+ static const wchar_t *GetWideImportFileExtension();
+ static const wchar_t *GetWideMeshFileExtension();
+ static const wchar_t *GetWideLUAFileExtension();
+ static const wchar_t **GetWideFontFileExtensions();
+ static const wchar_t **GetWideImgFileExtensions();
+ static const wchar_t **GetWideEffectFileExtensions();
+ static const wchar_t **GetWideMaterialFileExtensions();
+ static const wchar_t **GetWideSoundFileExtensions();
+ static bool IsImageFileExtension(const wchar_t *inExt);
+ static bool IsFontFileExtension(const wchar_t *inExt);
+ static bool IsEffectFileExtension(const wchar_t *inExt);
+ static bool IsMaterialFileExtension(const wchar_t *inExt);
+ static bool IsPathFileExtension(const wchar_t *inExt);
+ static bool IsPathBufferExtension(const wchar_t *inExt);
+ static bool IsSoundFileExtension(const wchar_t *inExt);
+
+ CUICFile GetExportChoice(const Q3DStudio::CString &inExtension,
+ const Q3DStudio::CString &inDefaultName);
+
+ std::pair<CUICFile, bool> GetSaveAsChoice(const Q3DStudio::CString &inDialogTitle = "",
+ bool inFilenameUntitled = false);
+ // Returns pair of file along with a boolean indicating the state of the create
+ // new directory checkbox.
+ std::pair<CUICFile, bool>
+ GetNewDocumentChoice(const Q3DStudio::CString &inInitialDirectory = Q3DStudio::CString());
+ CUICFile GetFileOpenChoice(const Q3DStudio::CString &inInitialDirectory = Q3DStudio::CString());
+
+ void DisplayImportFailed(const QUrl &inURL, const QString &inDescription,
+ bool inWarningsOnly);
+ void DisplayLoadingPresentationFailed(const CUICFile &inPresentation, long inErrorIDS = -1);
+ void DisplaySavingPresentationFailed();
+ void DisplaySaveReadOnlyFailed(const CUICFile &inSavedLocation);
+ CUICMessageBox::EMessageBoxReturn DisplayMessageBox(const Q3DStudio::CString &inTitle,
+ const Q3DStudio::CString &inText,
+ CUICMessageBox::EMessageBoxIcon inIcon,
+ bool inShowCancel);
+ int DisplayChoiceBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText,
+ int inIcon);
+ void DisplayKnownErrorDialog(const Q3DStudio::CString &inErrorText);
+
+ bool LocateFileReference(CUICFile &outFile, long inFileType);
+ bool LocateFolderReference(CUICFile &outFile);
+ bool BrowseForFolderDialog(CUICFile &outFile, Q3DStudio::CString inDefaultDir,
+ Q3DStudio::CString inDialogTitle);
+
+ ESavePromptResult PromptForSave();
+ bool PromptForKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut);
+
+ bool ConfirmRevert();
+
+ void DisplayProgressScreen(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle);
+ void DestroyProgressScreen();
+
+ bool PromptObjectTimebarColor(CColor &ioColor);
+ void DisplayProfilingStatistics();
+ /*void DisplayMultilineTextEdit(Q3DStudio::CString &ioText,
+ CMultilineEditDlg::INotification *inNotifiction = NULL);*/
+ IProgressCallback *GetProgressScreen() const;
+
+ void DisplayEnvironmentVariablesError(const Q3DStudio::CString &inErrorMessage);
+
+ Q3DStudio::CString GetFilePathChoice(const Q3DStudio::CString &inFileExtensionFilter,
+ const Q3DStudio::CString &inDefault,
+ const Q3DStudio::CString *inDialogTitle = NULL);
+ void ResetSettings(const Q3DStudio::CString &inCurrentDocPath = "");
+
+ bool DisplayResetKeyframeValuesDlg();
+ void DisplayPasteFailed();
+
+ static void DisplayGLVersionError(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inMinVersion);
+ static void DisplayGLVersionWarning(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inRecommendedVersion);
+
+protected:
+ QString CreateAllowedTypesString(long inFileTypeFilter, bool inForImport);
+ static void DisplayGLVersionDialog(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inRecommendedVersion,
+ bool inError);
+
+#ifdef WIN32
+ CProgressPalette *m_ProgressPalette;
+#endif
+ bool m_ShowGUI;
+
+ Q3DStudio::CString m_LastSaveFile; ///< Path to the file was previously saved
+};
+#endif // INCLUDED_DIALOGS_H
diff --git a/src/Authoring/Studio/Workspace/Views/Views.h b/src/Authoring/Studio/Workspace/Views/Views.h
new file mode 100644
index 00000000..52b075e0
--- /dev/null
+++ b/src/Authoring/Studio/Workspace/Views/Views.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_VIEWS_H
+#define INCLUDED_VIEWS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CMainFrame;
+class CStudioApp;
+class CHotKeys;
+class CStudioPaletteBar;
+class CStudioDialog;
+#ifdef WIN32
+class CRuntimeClass;
+class CFrameWnd;
+#endif
+
+#include <UICString.h>
+
+//==============================================================================
+// Class
+//==============================================================================
+
+class CViews
+{
+public:
+ CViews(CStudioApp *inStudioApp);
+ virtual ~CViews();
+
+ // Implementation
+ void CreateViews();
+ void DestroyViews();
+
+ // Keyboard
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+
+ // Main Frame
+ CMainFrame *GetMainFrame(); // ONLY THE APP SHOULD USE THIS FUNCTION- ABSOLUTELY NO ONE ELSE!!!!
+
+ void RecheckMainframeSizingMode();
+
+#ifdef WIN32
+ static void CreatePaletteAndView(CRuntimeClass *inClass, CStudioPaletteBar *inPalette,
+ CFrameWnd *inParent, Q3DStudio::CString inWindowTitle);
+ static void CreateDialogAndView(CRuntimeClass *inClass, CStudioDialog *inDialog,
+ CFrameWnd *inParent, Q3DStudio::CString inWindowTitle);
+#endif
+
+protected:
+ CMainFrame *m_MainFrame; ///<
+ Q3DStudio::CString m_HelpURL; ///<
+};
+
+#endif // INCLUDED_VIEWS_H
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.cpp b/src/Authoring/Studio/_Win/Application/AboutDlg.cpp
new file mode 100644
index 00000000..533a5601
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/AboutDlg.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "StudioDefs.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "AboutDlg.h"
+#include "ui_AboutDlg.h"
+#include "ProductInfo.h"
+#include "HotKeys.h"
+#include "Preferences.h"
+#include "StudioPreferences.h"
+
+#include <QMouseEvent>
+#include <QPainter>
+#include <QTimer>
+
+//==============================================================================
+// Constants
+//==============================================================================
+const int TIMER_RESIZEABOUT = 6;
+const int TIMER_FADEOUT = 7;
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+CAboutDlg::CAboutDlg(QWidget* parent)
+ : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint)
+ , m_ScrollingCreditsFlag(false)
+ , m_ui(new Ui::AboutDlg)
+{
+ m_ui->setupUi(this);
+ m_IconRect = m_ui->icon->pixmap()->rect();
+ setFixedSize(size());
+
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPointSizeF(7.8);
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPointSizeF(8.8);
+
+ m_Color_Background = CStudioPreferences::GetDarkBaseColor();
+ m_Color_Text = CStudioPreferences::GetNormalColor();
+
+ OnInitDialog();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+CAboutDlg::~CAboutDlg()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the painting of the icon in the About Box.
+ * All additional painting (text, etc) occurs by default by MFC.
+ */
+//==============================================================================
+void CAboutDlg::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ if (!m_ScrollingCreditsFlag) {
+ DrawFadeRect();
+ }
+}
+
+//==============================================================================
+/**
+ * Completes the construction of the About Box.
+ * Stores the product version in the member variable associated with the static
+ * text box in the dialog template. This version information comes from the
+ * VersionNumber.h file in $/Studio/Build.
+ * @return Returns TRUE always.
+ */
+void CAboutDlg::OnInitDialog()
+{
+ // Set the Studio version
+ m_ProductVersionStr.Format(
+ ::LoadResourceString(IDS_UIC_STUDIO_VERSION),
+ static_cast<const wchar_t *>(CStudioPreferences::GetVersionString()));
+
+ // Set the copyright string
+ m_CopyrightStr.Format(::LoadResourceString(IDS_ABOUT_COPYRIGHT),
+ static_cast<const wchar_t *>(Q3DStudio::CString(STUDIO_COPYRIGHT_YEAR)));
+
+ // Set the credit strings
+ m_Credit1Str.Format(::LoadResourceString(IDS_ABOUT_PAINTLIB_CREDIT));
+#ifdef QT_3DSTUDIO_FBX
+ m_Credit2Str.Format(::LoadResourceString(IDS_ABOUT_FBX_CREDIT));
+#endif
+
+#ifdef STUDIOSTORYNUM
+ m_ProductVersionStr += " (Story #";
+ m_ProductVersionStr += STUDIOSTORYNUM;
+ m_ProductVersionStr += ")";
+#endif
+
+#ifdef BETA
+ // Add "beta" to the Studio version if necessary
+ m_ProductVersionStr += " BETA";
+#endif
+
+ // Add link to Web site
+ Q3DStudio::CString theURL(::LoadResourceString(IDS_HELP_VISIT_QT));
+
+ m_ui->m_WebSite->setText(QString("<a href=\"%1\">%2</a>").arg(theURL.toQString(), theURL.toQString()));
+ m_ui->m_WebSite->setToolTip(::LoadResourceString(IDS_WEBSITELINK).toQString());
+ m_ui->m_WebSite->setOpenExternalLinks(true);
+
+ // Add link to support email address
+ Q3DStudio::CString theEmail;
+ Q3DStudio::CString theEmailSansProtocol;
+
+ theEmail = ::LoadResourceString(IDS_SUPPORTEMAIL);
+ theEmailSansProtocol = "support@qt.io";
+
+ m_ui->m_Email->setText(QString("<a href=\"%1\">%2</a>").arg(theEmail.toQString(), theEmailSansProtocol.toQString()));
+ m_ui->m_Email->setToolTip(::LoadResourceString(IDS_SUPPORTEMAIL_TEXT).toQString());
+ m_ui->m_Email->setOpenExternalLinks(true);
+
+ // Set the fonts
+ m_ui->m_Copyright->setFont(m_Font);
+ m_ui->m_Credit1->setFont(m_Font);
+ m_ui->m_Credit2->setFont(m_Font);
+ m_ui->m_WebSiteLabel->setFont(m_Font);
+ m_ui->m_WebSite->setFont(m_Font);
+ m_ui->m_EmailLabel->setFont(m_Font);
+ m_ui->m_Email->setFont(m_Font);
+
+ // Make the font bold for version numbers
+ m_ui->m_ProductVersion->setFont(m_BoldFont);
+
+ // Create brush for background color
+ m_Brush = QBrush(m_Color_Background);
+
+ m_ui->m_ProductVersion->setText(m_ProductVersionStr.toQString());
+ m_ui->m_Copyright->setText(m_CopyrightStr.toQString());
+ m_ui->m_Credit1->setText(m_Credit1Str.toQString());
+ m_ui->m_Credit2->setText(m_Credit2Str.toQString());
+
+ // Hide the email link until we have a valid one.
+ m_ui->m_EmailLabel->setVisible(false);
+ m_ui->m_Email->setVisible(false);
+}
+
+//==============================================================================
+/**
+ * Handles the WM_LBUTTONDBLCLK message
+ * Check to see if the mouse is within the Qt logo and the control key is pressed.
+ * If so, begin the transition to show the detailed credits.
+ */
+void CAboutDlg::mouseDoubleClickEvent(QMouseEvent* event)
+{
+ // If the mouse's left button is double-clicked in the Qt logo while the control key is
+ // pressed...
+ if (m_IconRect.contains(event->pos())) {
+ // if ( CHotKeys::IsKeyDown( VK_CONTROL ) )
+ //{
+ // Start the transition to display the scrolling credits
+ // Crashing... this->BeginCreditsTransition();
+ //}
+ }
+
+ QDialog::mouseDoubleClickEvent(event);
+}
+
+//==============================================================================
+/**
+ * BeginCreditsTransition: Begin the transition from the About box to the scrolling credits.
+ */
+void CAboutDlg::BeginCreditsTransition()
+{
+ m_ScrollingCreditsFlag = TRUE;
+
+ // Hide all controls
+ for (QWidget* w : findChildren<QWidget*>())
+ w->setVisible(false);
+
+ // Invalidate the window
+ update();
+
+ // Set the resizing timer
+ QTimer::singleShot(50, this, &CAboutDlg::ResizeAbout);
+}
+
+//==============================================================================
+/**
+ * Resize the about box height until the Client area is square.
+ */
+void CAboutDlg::ResizeAbout()
+{
+ bool retriggerResizeAbout = true;
+
+ QRect theClientRect = rect();
+ bool theRightSize = false;
+
+ // this is just a sizing stuff to show some transition on size
+ if (theClientRect.height() < theClientRect.width()) {
+ theClientRect.setBottom(theClientRect.bottom() + 5);
+ if (theClientRect.bottom() >= theClientRect.width()) {
+ theRightSize = true;
+ theClientRect.setBottom(theClientRect.width());
+ retriggerResizeAbout = false;
+ }
+ } else {
+ theClientRect.setRight(theClientRect.right() + 5);
+ if (theClientRect.right() >= theClientRect.height()) {
+ theRightSize = true;
+ theClientRect.setRight(theClientRect.height());
+ retriggerResizeAbout = false;
+ }
+ }
+
+ if (parentWidget())
+ theClientRect.moveCenter(parentWidget()->geometry().center());
+ else
+ theClientRect.moveTopLeft(geometry().topLeft());
+
+ setGeometry(theClientRect);
+
+ if (theRightSize) {
+ QColor the3DColor;
+ short theColorValue;
+
+ m_CreditsRect = rect().adjusted(3, 3, -3, -3);
+
+ the3DColor = palette().color(QPalette::Base);
+ theColorValue =
+ (short)((the3DColor.red() + the3DColor.green() + the3DColor.blue()) / 3);
+
+ m_ColorFade = RGB(theColorValue, theColorValue, theColorValue);
+
+ QTimer::singleShot(50, this, &CAboutDlg::FadeOut);
+ }
+
+ if (retriggerResizeAbout) {
+ QTimer::singleShot(50, this, &CAboutDlg::ResizeAbout);
+ }
+}
+
+//==============================================================================
+/**
+ * Fade out a rectangle in the client area, from the background 3D color to black.
+ */
+void CAboutDlg::FadeOut()
+{
+ update();
+
+ // Continue fading to black
+ if (m_ColorFade != Qt::black) {
+ short theColorValue;
+
+ theColorValue = (short)(m_ColorFade.red() - 10);
+
+ if (theColorValue < 0)
+ theColorValue = 0;
+
+ m_ColorFade = qRgb(theColorValue, theColorValue, theColorValue);
+ QTimer::singleShot(50, this, &CAboutDlg::FadeOut);
+ }
+}
+
+//==============================================================================
+/**
+ * DrawFadeRect: Draw the faded rectangle as we transition to the scrolling credits.
+ */
+void CAboutDlg::DrawFadeRect()
+{
+ QPainter painter(this);
+ painter.fillRect(m_CreditsRect, m_ColorFade);
+}
+
+void CAboutDlg::OnStnClickedAboutboxProdver()
+{
+ // TODO: Add your control notification handler code here
+}
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.h b/src/Authoring/Studio/_Win/Application/AboutDlg.h
new file mode 100644
index 00000000..244e7192
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/AboutDlg.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_ABOUT_DLG_H
+#define INCLUDED_ABOUT_DLG_H 1
+
+#pragma once
+
+#include <QDialog>
+
+#include "UICString.h"
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class AboutDlg;
+}
+QT_END_NAMESPACE
+
+class CAboutDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ CAboutDlg(QWidget* parent = nullptr);
+ ~CAboutDlg();
+
+ // Implementation
+protected:
+ bool m_ScrollingCreditsFlag = false; // TRUE if credits are being scrolled
+ QRect m_IconRect; // bounding rectangle to display the about image
+ QRect m_CreditsRect; // bounding rectangle for the scrolling credits
+ QColor m_ColorFade; // fade-out color to fade to the credits window
+ QFont m_Font; // Font for text
+ QFont m_BoldFont; // Font for Studio/Client version number
+
+ QColor m_Color_Background;
+ QColor m_Color_Text;
+ QBrush m_Brush;
+
+ void BeginCreditsTransition();
+
+ void DrawFadeRect();
+
+ void FadeOut();
+
+ void ResizeAbout();
+
+ //{{AFX_MSG(CAboutDlg)
+ void paintEvent(QPaintEvent* event) override;
+ void OnInitDialog();
+
+ void mouseDoubleClickEvent(QMouseEvent* event) override;
+
+ Q3DStudio::CString m_ProductVersionStr;
+ Q3DStudio::CString m_CopyrightStr;
+ Q3DStudio::CString m_Credit1Str;
+ Q3DStudio::CString m_Credit2Str;
+
+public:
+ void OnStnClickedAboutboxProdver();
+
+private:
+ QScopedPointer<Ui::AboutDlg> m_ui;
+};
+
+#endif // INCLUDED_ABOUT_DLG_H
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.ui b/src/Authoring/Studio/_Win/Application/AboutDlg.ui
new file mode 100644
index 00000000..a5fe3433
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/AboutDlg.ui
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDlg</class>
+ <widget class="QDialog" name="AboutDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>502</width>
+ <height>483</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>About Qt 3D Studio</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="icon">
+ <property name="pixmap">
+ <pixmap resource="../../MainFrm.qrc">:/res/About Icon.bmp</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="Line" name="m_Line1">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_ProductVersion">
+ <property name="text">
+ <string>&lt;studio version goes here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Copyright">
+ <property name="text">
+ <string>&lt;Copyright goes here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Credit1">
+ <property name="text">
+ <string>&lt;Credit 1 goes here&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Credit2">
+ <property name="text">
+ <string>&lt;Credit 2 goes here&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="m_Line2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_WebSiteLabel">
+ <property name="text">
+ <string>Web site:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_WebSite">
+ <property name="text">
+ <string>&lt;Link to support site here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_EmailLabel">
+ <property name="text">
+ <string>Support email:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Email">
+ <property name="text">
+ <string>&lt;Link to support email here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../MainFrm.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AboutDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AboutDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/Application/BaseLink.cpp b/src/Authoring/Studio/_Win/Application/BaseLink.cpp
new file mode 100644
index 00000000..5e7b4775
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/BaseLink.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+//#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "BaseLink.h"
+#include "Resource.h"
+#include "StudioColors.h"
+
+// The IDC_HAND should be defined in WinUser.h if the WINVER is 0x5000 or greater
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBaseLink class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CBaseLink::CBaseLink()
+{
+ m_bCapture = FALSE;
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CBaseLink::~CBaseLink()
+{
+}
+
+//==============================================================================
+// Message Map
+//==============================================================================
+
+BEGIN_MESSAGE_MAP(CBaseLink, CWnd)
+//{{AFX_MSG_MAP(CBaseLink)
+ON_WM_PAINT()
+ON_WM_SETCURSOR()
+ON_WM_MOUSEMOVE()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * ShowTextLink: Shows the text link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CBaseLink::ShowTextLink(COLORREF inTextColor, COLORREF inBackColor, UINT inTextFormat,
+ bool inUnderlineText)
+{
+ if (IsWindow(m_hWnd)) {
+ CRect theRect;
+ CFont *theFont;
+ CFont *theOldFont = nullptr;
+ CDC *theDC;
+ CDC theMemDC;
+ CString theTextBuffer;
+
+ // Set up the link font.
+ theFont = GetFont();
+ if (theFont != nullptr) {
+ LOGFONT theLogFont;
+
+ theFont->GetLogFont(&theLogFont);
+
+ // Turn on the underline style...
+ if (inUnderlineText)
+ theLogFont.lfUnderline = TRUE;
+ else
+ theLogFont.lfUnderline = FALSE;
+
+ theFont = new CFont();
+
+ if (theFont != nullptr) {
+ theFont->CreateFontIndirect(&theLogFont);
+ }
+ }
+
+ GetClientRect(&theRect);
+ GetWindowText(theTextBuffer);
+
+ theDC = GetDC();
+
+ theDC->SetTextColor(inTextColor);
+ theDC->SetBkColor(inBackColor);
+
+ // Fill the background.
+ theDC->FillSolidRect(&theRect, inBackColor);
+
+ // Set the font and draw the text.
+ if (theFont != nullptr) {
+ theOldFont = (CFont *)theDC->SelectObject(theFont);
+ }
+ theDC->DrawText(theTextBuffer, &theRect, inTextFormat);
+
+ if (theOldFont != nullptr) {
+ theDC->SelectObject(theOldFont);
+ }
+ ReleaseDC(theDC);
+
+ if (theFont != nullptr) {
+ theFont->DeleteObject();
+ delete theFont;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CBaseLink message handlers
+
+//==============================================================================
+/**
+ * OnPaint - Handler for the WM_PAINT message
+ *
+ * Draw the control.
+ *
+ * @param None
+ */
+//==============================================================================
+void CBaseLink::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+
+ if (IsWindowEnabled())
+ this->ShowLink();
+}
+
+//==============================================================================
+/**
+ * OnSetCursor
+ *
+ * Handle the WM_SETCURSOR message.
+ *
+ * @param inWnd Pointer to the parent CWnd object.
+ * @param inHitTest Specifies the hit-test area code. The hit test determines the
+ *cursor�s location.
+ * @param inMessage Specifies the mouse message number.
+ */
+//==============================================================================
+BOOL CBaseLink::OnSetCursor(CWnd *inWnd, UINT inHitTest, UINT inMessage)
+{
+ UNREFERENCED_PARAMETER(inWnd);
+ UNREFERENCED_PARAMETER(inHitTest);
+ UNREFERENCED_PARAMETER(inMessage);
+
+ SetCursor(LoadCursor(nullptr, IDC_HAND));
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * OnMouseMove
+ *
+ * Windows callback handler for the WM_MOUSEMOVE message
+ *
+ * @param inFlags Flags for the left button up message
+ * @param inPoint Point where the left button was last moved (client coordinates)
+ */
+//==============================================================================
+void CBaseLink::OnMouseMove(UINT inFlags, CPoint inPoint)
+{
+ UNREFERENCED_PARAMETER(inFlags);
+ UNREFERENCED_PARAMETER(inPoint);
+
+ if (IsWindowEnabled()) {
+
+ if (!m_bCapture) {
+ SetCursor(LoadCursor(nullptr, IDC_HAND));
+ SetCapture();
+
+ m_bCapture = TRUE;
+ this->ShowLink();
+ } else {
+ // Already captured...
+ if (!this->IsMouseOverLink()) {
+ m_bCapture = FALSE;
+ ReleaseCapture();
+
+ this->ShowLink();
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * IsMouseOverLink: Determine if the mouse is over the control.
+ *
+ * @param None
+ *
+ * @return true if the mouse is over the control.
+ */
+//==============================================================================
+bool CBaseLink::IsMouseOverLink()
+{
+ POINT theMousePos;
+ RECT theWndRect;
+
+ ::GetCursorPos(&theMousePos);
+ GetWindowRect(&theWndRect);
+
+ return PtInRect(&theWndRect, theMousePos) ? true : false;
+}
diff --git a/src/Authoring/Studio/_Win/Application/BaseLink.h b/src/Authoring/Studio/_Win/Application/BaseLink.h
new file mode 100644
index 00000000..4d89a155
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/BaseLink.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _BASELINK_H_
+#define _BASELINK_H_
+
+/////////////////////////////////////////////////////////////////////////////
+// CBaseLink window
+
+class CBaseLink : public CWnd
+{
+ // Construction
+public:
+ CBaseLink();
+
+ // Attributes
+public:
+ // Operations
+public:
+protected:
+ bool m_bCapture;
+
+ virtual bool IsMouseOverLink();
+ virtual void ShowLink() = 0;
+ virtual void ShowTextLink(COLORREF inTextColor, COLORREF inBackColor, UINT inTextFormat,
+ bool inUnderlineText);
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBaseLink)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CBaseLink();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CBaseLink)
+ virtual afx_msg void OnPaint();
+ virtual afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message);
+ virtual afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/MsgRouter.cpp b/src/Authoring/Studio/_Win/Application/MsgRouter.cpp
new file mode 100644
index 00000000..4ce57cc8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/MsgRouter.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MsgRouter.h"
+#include "StudioConst.h"
+#include "Core.h"
+#include "Doc.h"
+#include "Views.h"
+
+#include <QCoreApplication>
+
+static std::unique_ptr<CMsgRouter> static_theInstance;
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CMsgRouter::CMsgRouter()
+{
+ qApp->installEventFilter(this);
+ m_eventType = QEvent::registerEventType();
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMsgRouter::~CMsgRouter()
+{
+}
+
+CMsgRouter *CMsgRouter::GetInstance()
+{
+ if (!static_theInstance) {
+ static_theInstance.reset(new CMsgRouter);
+ }
+
+ return static_theInstance.get();
+}
+
+//==============================================================================
+/**
+ * Send a command to be executed asynchronously.
+ */
+void CMsgRouter::SendCommand(CCmd *inCommand, CCore *inCore)
+{
+ SMessageData *theMsgData = new SMessageData(m_eventType);
+ theMsgData->Method = &CMsgRouter::OnCommand;
+ theMsgData->Data = inCommand;
+ theMsgData->Data2 = inCore;
+
+ qApp->postEvent(qApp, theMsgData);
+}
+
+bool CMsgRouter::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == m_eventType) {
+ SMessageData *theMsgData = reinterpret_cast<SMessageData *>(event);
+ (this->*(theMsgData->Method))(theMsgData);
+ return true;
+ }
+
+ return false;
+}
+
+//==============================================================================
+/**
+ * Windows entry point for processing generic messages.
+ */
+void CMsgRouter::OnAsyncNotification(SMessageData *inMessageData)
+{
+ try {
+ CRoutedMessageBase *theRoutedMsg = static_cast<CRoutedMessageBase *>(inMessageData->Data);
+ if (theRoutedMsg)
+ theRoutedMsg->Notify();
+ } catch (...) {
+ // Catch crashes in case the object is gone
+ }
+}
+
+//==============================================================================
+/**
+ * Main thread processing for processing command execution messages.
+ */
+void CMsgRouter::OnCommand(SMessageData *inMsgData)
+{
+ CCmd *theCommand = static_cast<CCmd *>(inMsgData->Data);
+ CCore *theCore = static_cast<CCore *>(inMsgData->Data2);
+ theCore->ExecuteCommand(theCommand, true);
+}
+
+
+
+CMsgRouter::SMessageData::SMessageData(int eventType) :
+ QEvent(static_cast<QEvent::Type>(eventType))
+{
+}
diff --git a/src/Authoring/Studio/_Win/Application/StudioApp.cpp b/src/Authoring/Studio/_Win/Application/StudioApp.cpp
new file mode 100644
index 00000000..fa160431
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/StudioApp.cpp
@@ -0,0 +1,1835 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+#include "StudioApp.h"
+#include "SubPresentationsDlg.h"
+#include "UICStateApplication.h"
+
+#include <QtGui/qsurfaceformat.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qurl.h>
+
+int main(int argc, char *argv[])
+{
+ // to enable QOpenGLWidget to work on macOS, we must set the default
+ // QSurfaceFormat before QApplication is created. Otherwise context-sharing
+ // fails and QOpenGLWidget breaks.
+
+ // fortunately, we know which OpenGL version we can use on macOS, so we
+ // can simply hard-code it here.
+#if defined(Q_OS_MACOS)
+ QSurfaceFormat openGL33Format;
+ openGL33Format.setRenderableType(QSurfaceFormat::OpenGL);
+ openGL33Format.setProfile(QSurfaceFormat::CoreProfile);
+ openGL33Format.setMajorVersion(3);
+ openGL33Format.setMinorVersion(3);
+ openGL33Format.setStencilBufferSize(8);
+ QSurfaceFormat::setDefaultFormat(openGL33Format);
+#endif
+
+ // init runtime static resources
+ Q_INIT_RESOURCE(res);
+
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication guiApp(argc, argv);
+ // Load and apply stylesheet for the application
+ QFile styleFile(":/style.qss");
+ styleFile.open(QFile::ReadOnly);
+ guiApp.setStyleSheet(styleFile.readAll());
+ g_StudioApp.InitInstance(argc, argv);
+ return g_StudioApp.Run();
+}
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Exceptions.h"
+#include "IOLibraryException.h"
+#include "Strings.h"
+#include "MainFrm.h"
+#include "AboutDlg.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "StackOps.h"
+#include "Views.h"
+#endif
+#include "StringLoader.h"
+#include "Doc.h"
+#include "Dialogs.h"
+#include "Dispatch.h"
+#include "StartupDlg.h"
+#include "RecentItems.h"
+#include "StudioPreferences.h"
+#include "MsgRouter.h"
+#include "SplashView.h"
+#include "Views.h"
+#include "UICLog.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "WinUtils.h"
+#include "CrashDlg.h"
+#endif
+#include "UICFile.h"
+#include "UICFileTools.h"
+#include "ITickTock.h"
+#include "IStudioRenderer.h"
+#include "IDocumentEditor.h"
+#include "StudioUtils.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "IObjectReferenceHelper.h"
+#endif
+#include "ClientDataModelBridge.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "CommonConstants.h"
+#include "IOLibraryException.h"
+
+#ifdef _DEBUG
+#include "UICMemoryLeak.h"
+#endif
+#include "UICDMErrors.h"
+
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
+#include <string.h>
+
+#include <QApplication>
+#include <QSettings>
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "..\Build\versionnumber.h"
+
+#include "UICDESKey.h" // g_DESKey
+#endif
+
+#include "Core.h"
+#include "HotKeys.h"
+#include "StudioTutorialWidget.h"
+#include "GuideInspectable.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMInspectable.h"
+#include "UICDMSlides.h"
+#include "UICDMMaterialInspectable.h"
+#include "UICDMSceneInspectable.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "UICDMAnimation.h"
+#include "UICDMDataCore.h"
+#include "SlideControl.h"
+#endif
+#include "IDirectoryWatchingSystem.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "ITickTock.h"
+#include "UICFileTools.h"
+#include "foundation/Qt3DSLogging.h"
+
+#endif
+#ifdef USE_LICENSE_HANDLER
+#include "licensehandler.h"
+#endif
+
+CStudioApp g_StudioApp;
+long g_UICErrorCode = 0;
+
+using namespace Q3DStudio;
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+char g_DumpPath[MAX_PATH] = { 0 };
+
+#ifndef WIN32
+namespace qt3ds
+{
+void NVAssert(const char *exp, const char *file, int line, bool *igonore)
+{
+ qFatal("NVAssertion thrown %s(%d): %s", file, line, exp);
+}
+}
+#endif
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CStudioApp::CStudioApp()
+#ifdef KDAB_TEMPORARILY_REMOVED
+ , m_SplashPalette(nullptr)
+ , m_OldHelpFilePath(nullptr)
+ , m_UnitTestResults(0)
+ , m_IsSilent(false)
+ , m_Core(NULL)
+ , m_Views(NULL)
+ , m_Dialogs(NULL)
+ , m_ManipulationMode(StudioManipulationModes::Local)
+ , m_PlaybackTime(0)
+ , m_pGdiToken(0)
+ , m_AuthorZoom(false)
+#endif
+ : m_ToolMode(STUDIO_TOOLMODE_MOVE)
+ , m_SelectMode(STUDIO_SELECTMODE_GROUP)
+ , m_welcomeShownThisSession(false)
+ , m_goStraightToWelcomeFileDialog(false)
+ , m_tutorialPage(0)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+#ifdef _DEBUG
+ AfxEnableMemoryTracking(TRUE);
+ CMemoryLeak::SetXMLFileName("StudioMemoryLeaks.xml");
+ CMemoryLeak::SetShowDialogOnExit(false);
+#endif // _DEBUG
+ g_DumpPath[0] = 0;
+#endif
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CStudioApp::~CStudioApp()
+{
+ // Do not call PerformShutdown from here as the C has already been shutdown (!!)
+}
+
+void CStudioApp::PerformShutdown()
+{
+ m_DirectoryWatcherTicker = std::shared_ptr<UICDM::ISignalConnection>();
+
+ // Dispatch un-registration
+ if (m_Core) {
+ m_Core->GetDispatch()->RemoveAppStatusListener(this);
+ m_Core->GetDispatch()->RemoveCoreAsynchronousEventListener(this);
+ qCInfo(qt3ds::TRACE_INFO) << "Studio exiting successfully";
+ }
+
+ if (m_Renderer) {
+ m_Renderer->Close();
+ m_Renderer = std::shared_ptr<Q3DStudio::IStudioRenderer>();
+ }
+
+ // No need to delete m_SplashPalette. You should not call delete on CFrameWnds,
+ // you should call DestroyWindow( ) instead. See the MSDN.
+ // delete m_SplashPalette;
+#ifdef KDAB_TEMPORARILY_REMOVED
+ delete m_Views;
+ m_Views = nullptr;
+ delete m_Dialogs;
+ m_Dialogs = nullptr;
+ delete m_Core;
+ m_Core = nullptr;
+#endif
+
+ CStringLoader::UnloadStrings();
+
+ // Get rid of the temp files
+ CUICFile::ClearCurrentTempCache();
+
+ qApp->exit();
+}
+
+//=============================================================================
+/**
+ * Entry location for the creation of this application.
+ * This creates the all the views, then returns if everything
+ * was successful.
+ */
+BOOL CStudioApp::InitInstance(int argc, char* argv[])
+{
+ QApplication::setOrganizationName("The Qt Company");
+ QApplication::setOrganizationDomain("qt.io");
+ QApplication::setApplicationName("Qt 3D Studio");
+ QApplication::setApplicationVersion(
+ QString::fromWCharArray(CStudioPreferences::GetVersionString().c_str()));
+
+ qCInfo(qt3ds::TRACE_INFO) << "Studio: " << QApplication::applicationFilePath();
+
+ // Load the strings used by the app gui
+ // This needs to occur prior to parsing command line arguments
+ // since access to the strings are required by some of the cases
+ CUICFile theResDir(CString::fromQString(resourcePath() + QStringLiteral("/strings")));
+ CStringLoader::LoadStrings(theResDir);
+ qCInfo(qt3ds::TRACE_INFO) << "Version: "
+ << CStudioPreferences::GetVersionString().GetCharStar();
+
+ std::vector<wchar_t*> wargv;
+ wargv.resize(argc);
+ for (int i = 0; i < argc; ++i) {
+ QString arg = argv[i];
+ wargv[i] = new wchar_t[arg.size() + 1];
+ wargv[i][arg.size()] = L'\0';
+ arg.toWCharArray(wargv[i]);
+ }
+
+ // Parse the command line so we know what's up
+ m_CmdLineParser.ParseArguments(argc, &(wargv[0]));
+
+ // Silent mode indicates that Studio will be operated in a muted "no-GUI" mode
+ m_IsSilent = m_CmdLineParser.IsSilent();
+
+ // If we're just running unit tests, return before creating windows/MFC controls
+ if (m_CmdLineParser.IsRunUnitTests()) {
+ {
+ RunCmdLineTests(m_CmdLineParser.GetFilename());
+ return FALSE; // return false so we bail from loading the app
+ }
+ }
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need
+ // Change the registry key under which our settings are stored
+ Q3DStudio::CString theRegistryKey =
+ ::LoadResourceString(IDS_UICOMPOSER_PALETTE_SETTINGS_REGISTRY_KEY);
+ SetRegistryKey(theRegistryKey);
+#endif
+
+ CFilePath thePreferencesPath = CFilePath::GetUserApplicationDirectory();
+ thePreferencesPath = CFilePath::CombineBaseAndRelative(
+ thePreferencesPath, CFilePath(L"UIComposer\\Preferences.setting"));
+ CPreferences::SetPreferencesFile(thePreferencesPath);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set up the path to the help file
+ InitHelpSystem();
+#endif
+
+ CStudioPreferences::LoadPreferences();
+
+ m_Dialogs = new CDialogs(!m_IsSilent);
+
+ if (!m_IsSilent) {
+ // Show the splash screen
+ m_SplashPalette = new CSplashView();
+ m_SplashPalette->setWindowTitle(::LoadResourceString(IDS_PROJNAME).toQString());
+ m_SplashPalette->show();
+
+ m_Views = new CViews(this);
+ }
+
+ // All custom icons (PNGs) are drawn using Gdiplus so that transparency are handled.
+ // note that gdiplus.dll are included with WinXP ( previous OS versions require the gdi
+ // redistributables to be installed and unless
+ // support for those OS becomes a priority, we assume Studio is run minimally on a XP machine )
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Gdiplus::GdiplusStartup(&m_pGdiToken, &m_gdiplusStartupInput, nullptr); // gdi+ init
+#endif
+
+ m_Core = new CCore();
+ GetRenderer();
+ m_Core->GetDoc()->SetSceneGraph(m_Renderer);
+
+ // Dispatch registration
+ m_Core->GetDispatch()->AddAppStatusListener(this);
+ m_Core->GetDispatch()->AddCoreAsynchronousEventListener(this);
+
+ return TRUE;
+}
+
+//=============================================================================
+/**
+ * Exit location for the destruction of this application.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::ExitInstance()
+{
+ int theResult = -1;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // CWinApp::InitInstance returns 1(TRUE) on success; 0(FALSE) on failure
+ if (CWinApp::InitInstance() == TRUE)
+ theResult = 0;
+
+ if (m_CmdLineParser.IsRunUnitTests() && 0 == m_UnitTestResults)
+ theResult = m_UnitTestResults; // unit tests return 0 on success; 1 on failure
+
+#ifdef _DEBUG
+ // If appears that MFC takes over dumping memory leaks on exit
+ // this is the only way I've been able to turn it off.
+
+ // Turn off dumping CRT memory leaks
+ ::_CrtSetReportMode(_CRT_WARN, 0);
+ ::_CrtSetReportMode(_CRT_ERROR, 0);
+ ::_CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
+
+ // Make sure any GDI resources have been cleaned up
+ CResourceCache::GetInstance()->Clear();
+ // Called in conjuction with Gdiplus::GdiplusStartup
+ Gdiplus::GdiplusShutdown(m_pGdiToken);
+#endif
+
+ return theResult;
+}
+
+//=============================================================================
+/**
+ * Command handler to display the about dialog.
+ */
+void CStudioApp::OnAppAbout()
+{
+ CAboutDlg aboutDlg;
+ aboutDlg.exec();
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//=============================================================================
+/**
+ * Overrides registry access member functions, direct settings to a XML file
+ */
+UINT CStudioApp::GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ QT3DS_ASSERT(lpszEntry != nullptr);
+
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+ return CPreferences::GetUserPreferences(theSubKeyName).GetLongValue(lpszEntry, nDefault);
+}
+BOOL CStudioApp::WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ QT3DS_ASSERT(lpszEntry != nullptr);
+
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+ CPreferences::GetUserPreferences(theSubKeyName).SetLongValue(lpszEntry, nValue);
+ return TRUE;
+}
+::CString CStudioApp::GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry,
+ LPCTSTR lpszDefault /* = nullptr */)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ QT3DS_ASSERT(lpszEntry != nullptr);
+
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+ return CPreferences::GetUserPreferences(theSubKeyName).GetStringValue(lpszEntry, lpszDefault);
+}
+BOOL CStudioApp::WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+
+ if (lpszEntry == nullptr) // delete whole section
+ {
+ CPreferences::GetUserPreferences(theSubKeyName).Clear();
+ } else if (lpszValue == nullptr) {
+ CPreferences::GetUserPreferences(theSubKeyName).RemoveKey(lpszEntry);
+ } else {
+ CPreferences::GetUserPreferences(theSubKeyName).SetStringValue(lpszEntry, lpszValue);
+ }
+ return TRUE;
+}
+#endif
+
+//=============================================================================
+/**
+ * Main application execution loop.
+ * The application's main thread stays in this until the app exits.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::Run()
+{
+ int theRetVal = -1;
+
+#ifdef USE_LICENSE_HANDLER
+ LicenseHandler lh;
+ if (!lh.handleLicense())
+ return theRetVal;
+#endif
+
+ try {
+ UIC_LOGSTART;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set the crash handler for all unhandled exceptions.
+ CStackOps::SetCrashProc(&StudioUnhandledCrashHandler);
+ CStackOps::RegisterCrashHandler();
+ CStackOps::EnableCrashingOnCrashes();
+#endif
+
+ CCmdLineParser::EExecutionMode theMode = m_CmdLineParser.PopExecutionMode();
+ if (CCmdLineParser::END_OF_CMDS == theMode)
+ theMode = CCmdLineParser::NORMAL;
+
+ for (; CCmdLineParser::END_OF_CMDS != theMode;
+ theMode = m_CmdLineParser.PopExecutionMode()) {
+ // This just switches the execution mode of the app and starts it in the correct state.
+ switch (theMode) {
+ case CCmdLineParser::TEST_CMD_LINE:
+ theRetVal = RunSystemTests(m_CmdLineParser.GetFilename());
+ break;
+ case CCmdLineParser::OPEN_FILE:
+ theRetVal = OpenAndRunApplication(m_CmdLineParser.GetFilename());
+ break;
+ default:
+ theRetVal = BlankRunApplication();
+ break;
+ }
+
+ // if any operations returned a bad value, stop following operations
+ if (-1 == theRetVal)
+ break;
+ }
+ PerformShutdown();
+
+ UIC_LOGSTOP;
+ } catch (CUICExceptionClass &inException) {
+ g_UICErrorCode = inException.GetErrorCode();
+ throw;
+ } catch (UICDM::UICDMError &uicdmError) {
+ Q_UNUSED(uicdmError);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ EXCEPTION_POINTERS *pExPtrs;
+ CStackOps::GetExceptionPointers(1, &pExPtrs);
+ StudioUnhandledCrashHandler(pExPtrs);
+#endif
+ exit(1);
+ } catch (...) {
+ throw;
+ }
+
+ return theRetVal;
+}
+
+bool CStudioApp::HandleWelcomeRes(int res, bool recursive)
+{
+ int theReturn = true;
+ switch (res) {
+ case StudioTutorialWidget::createNewResult: {
+ std::pair<CUICFile, bool> theFile = m_Dialogs->
+ GetNewDocumentChoice(Q3DStudio::CString("."));
+ if (theFile.first.GetPath() != "") {
+ m_Core->OnNewDocument(theFile.first, theFile.second);
+ theReturn = true;
+ m_welcomeShownThisSession = true;
+ } else {
+ // User Cancels the dialog. Show the welcome screen.
+ if (recursive) {
+ m_welcomeShownThisSession = false;
+ m_goStraightToWelcomeFileDialog = true;
+ theReturn = ShowStartupDialog();
+ } else {
+ theReturn = false;
+ }
+ }
+ } break;
+
+ case StudioTutorialWidget::openSampleResult: {
+ // Try three options:
+ // - open a specific example directory with .uip file in it
+ // - failing that, show the main example root dir
+ // - failing all previous, show Qt3DStudio dir
+ Q3DStudio::CFilePath filePath;
+
+ filePath = CUICFile::GetApplicationDirectory().GetPath()+
+ Q3DStudio::CString("../examples/qmldynamickeyframes/presentation");
+
+ if (!filePath.Exists()) {
+ filePath = CUICFile::GetApplicationDirectory().GetPath()+
+ Q3DStudio::CString("../examples");
+ }
+ if (!filePath.Exists()) {
+ filePath = CUICFile::GetApplicationDirectory().GetPath()+
+ Q3DStudio::CString(".");
+ }
+
+ CUICFile theFile = m_Dialogs->GetFileOpenChoice(filePath);
+
+ if (theFile.GetPath() != "") {
+ OnLoadDocument(theFile);
+ theReturn = true;
+ m_welcomeShownThisSession = true;
+ } else {
+ // User Cancels the dialog. Show the welcome screen.
+ if (recursive) {
+ m_welcomeShownThisSession = false;
+ m_goStraightToWelcomeFileDialog = true;
+ theReturn = ShowStartupDialog();
+ } else {
+ theReturn = false;
+ }
+ }
+ } break;
+
+ default:
+ ASSERT(false); // Should not reach this block.
+ theReturn = false;
+ break;
+ }
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Show startup dialog and perform necessary action such as create new doc or load doc.
+ * Return false if user requests to exit
+ */
+bool CStudioApp::ShowStartupDialog()
+{
+ int welcomeRes = QDialog::Rejected;
+ bool theReturn = true;
+
+ if (!m_welcomeShownThisSession){
+ m_welcomeShownThisSession = true;
+
+ bool show = false;
+ QSettings settings;
+
+ if (!settings.contains("showWelcomeScreen")) {
+ settings.setValue("showWelcomeScreen", 1);
+ show = true;
+ } else {
+ // if we are returning to welcome dialog page after canceling
+ // file dialog, do not care about settings but always show
+ // welcome
+ show = settings.value("showWelcomeScreen").toBool()
+ || m_goStraightToWelcomeFileDialog;
+ }
+
+ if (show) {
+ StudioTutorialWidget tutorial(m_goStraightToWelcomeFileDialog);
+ welcomeRes = tutorial.exec();
+ }
+ }
+
+ // show the usual startup dialog only if user rejected tutorial
+ // ( = did not open samples or create new project)
+ if (welcomeRes == QDialog::Rejected) {
+ CStartupDlg theStartupDlg;
+
+ // Populate recent items
+ Q3DStudio::CFilePath theMostRecentDirectory;
+ if (m_Views) {
+ CRecentItems *theRecentItems = m_Views->GetMainFrame()->GetRecentItems();
+ for (long theIndex = 0; theIndex < theRecentItems->GetItemCount(); ++theIndex) {
+ if (theIndex == 0) {
+ theMostRecentDirectory =
+ Q3DStudio::CFilePath(theRecentItems->GetItem(0).GetAbsolutePath())
+ .GetDirectory();
+ }
+ theStartupDlg.AddRecentItem(theRecentItems->GetItem(theIndex));
+ }
+ }
+
+ theStartupDlg.exec();
+ CStartupDlg::EStartupChoice theChoice = theStartupDlg.GetChoice();
+
+ switch (theChoice) {
+ case CStartupDlg::EStartupChoice_Exit:
+ theReturn = false;
+ break;
+
+ case CStartupDlg::EStartupChoice_NewDoc: {
+ std::pair<CUICFile, bool> theFile = m_Dialogs->
+ GetNewDocumentChoice(theMostRecentDirectory);
+ if (theFile.first.GetPath() != "") {
+ m_Core->OnNewDocument(theFile.first, theFile.second);
+ theReturn = true;
+ } else {
+ // User Cancels the dialog. Show startup dialog again.
+ theReturn = ShowStartupDialog();
+ }
+ } break;
+
+ case CStartupDlg::EStartupChoice_OpenDoc: {
+ CUICFile theFile = m_Dialogs->GetFileOpenChoice(theMostRecentDirectory);
+ if (theFile.GetPath() != "") {
+ OnLoadDocument(theFile);
+ theReturn = true;
+ } else {
+ // User Cancels the dialog. Show startup dialog again.
+ theReturn = ShowStartupDialog();
+ }
+ } break;
+
+ case CStartupDlg::EStartupChoice_OpenRecent: {
+ CUICFile theFile = theStartupDlg.GetRecentDoc();
+ if (theFile.GetPath() != "") {
+ OnLoadDocument(theFile);
+ // throw SlideNotFound( L"");
+ theReturn = true;
+ } else {
+ // User Cancels the dialog. Show startup dialog again.
+ theReturn = ShowStartupDialog();
+ }
+ } break;
+
+ default:
+ ASSERT(false); // Should not reach this block.
+ theReturn = false;
+ break;
+ }
+ } else { // open sample or create new
+ theReturn = HandleWelcomeRes(welcomeRes, true);
+ }
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Start the app.
+ */
+int CStudioApp::BlankRunApplication()
+{
+ InitCore();
+
+ if (ShowStartupDialog())
+ return RunApplication();
+ return -1;
+}
+
+//=============================================================================
+/**
+ * Run the unit tests specified on the command line then return.
+ * @param inTestPath input unit test path
+ * @return 0 on success; 1 on failure
+ */
+int CStudioApp::RunCmdLineTests(const Q3DStudio::CString &inTestPath)
+{
+ Q_UNUSED(inTestPath);
+
+ return m_UnitTestResults;
+}
+
+//=============================================================================
+/**
+ * Run the system level tests specified on the command line then return.
+ * @param inTestPath
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::RunSystemTests(const Q3DStudio::CString &inTestPath)
+{
+ int theSystemTestsResult = -1;
+
+ Q_UNUSED(inTestPath);
+
+ if (0 == m_UnitTestResults)
+ theSystemTestsResult = m_UnitTestResults; // unit tests return 0 on success; 1 on failure
+
+ return theSystemTestsResult;
+}
+
+//=============================================================================
+/**
+ * Open the specified file and run the application.
+ * This will load the file then go into the standard app loop.
+ * On load with the -silent flag, this would force the application to exit on
+ * load failures.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::OpenAndRunApplication(const Q3DStudio::CString &inFilename)
+{
+ int theSuccess = -1;
+ InitCore();
+ if (OnLoadDocument(
+ inFilename,
+ false)) // Load document. Upon failure, don't show startup dialog but exit immediately.
+ theSuccess = RunApplication();
+ return theSuccess;
+}
+
+//=============================================================================
+/**
+ * This is the app execution loop, the main thread loops here until the app exits.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::RunApplication()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ BOOL bIdle = TRUE;
+ LONG lIdleCount = 0;
+ MSG theMessage;
+
+ // CStackOps::RegisterCrashHandler( );
+
+ // acquire and dispatch messages until a WM_QUIT message is received.
+ for (;;) {
+ // phase1: check to see if we can do idle work
+ while (bIdle && !::PeekMessage(&theMessage, nullptr, nullptr, nullptr, PM_NOREMOVE)) {
+ // call OnIdle while in bIdle state
+ if (!OnIdle(lIdleCount++))
+ bIdle = FALSE; // assume "no idle" state
+ }
+
+ // phase2: pump messages while available
+ do {
+ try {
+ // Pump message, but quit on WM_QUIT
+ if (!PumpMessage())
+ return ExitInstance();
+ } catch (...) {
+ // Throw here so that any crash goes through the crash reporter
+ throw;
+ }
+
+ // Reset "no idle" state after pumping "normal" message
+ if (IsIdleMessage(&theMessage)) {
+ bIdle = TRUE;
+ lIdleCount = 0;
+ }
+ } while (::PeekMessage(&theMessage, nullptr, nullptr, nullptr, PM_NOREMOVE));
+ }
+#endif
+ return qApp->exec();
+}
+
+//=============================================================================
+/**
+ * Initialize the core and all the views.
+ */
+void CStudioApp::InitCore()
+{
+ // Initialize and cache the RenderSelector values for the first time,
+ // this way, subsequent attempts to instantiate a RenderSelector would circumvent the need
+ // for any extra (unneccesary) creation of render contexts which inadvertently cause exceptions
+ // to be thrown.
+
+ m_Core->Initialize();
+
+ if (m_Views) {
+ m_Views->CreateViews();
+ m_pMainWnd = m_Views->GetMainFrame();
+ } else {
+ ASSERT(0); // No views? wha?
+ }
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CMsgRouter::GetInstance()->SetMainframe(m_pMainWnd);
+#endif
+
+ // At this point, get rid of the splash screen, otherwise any errors dialog would be hidden
+ // behind.
+ // Could happen when this is directly activated due to a uip file being dbl-clicked or dragged
+ // into the executable.
+ if (m_SplashPalette) {
+ m_SplashPalette->deleteLater();
+ m_SplashPalette = nullptr;
+ }
+
+ RegisterGlobalKeyboardShortcuts(m_Core->GetHotKeys());
+ m_Core->GetDispatch()->AddPresentationChangeListener(this);
+}
+
+struct SIImportFailedHandler : public Q3DStudio::IImportFailedHandler
+{
+ CDialogs &m_Dialogs;
+ SIImportFailedHandler(CDialogs &dialogs)
+ : m_Dialogs(dialogs)
+ {
+ }
+ void DisplayImportFailed(const QString &inDocumentPath,
+ const QString &inDescription, bool inWarningsOnly) override
+ {
+ m_Dialogs.DisplayImportFailed(QUrl(inDocumentPath), inDescription, inWarningsOnly);
+ }
+};
+
+struct SIDeletingReferencedObjectHandler : public Q3DStudio::IDeletingReferencedObjectHandler
+{
+ CDialogs &m_Dialogs;
+
+ SIDeletingReferencedObjectHandler(CDialogs &dialogs)
+ : m_Dialogs(dialogs)
+ {
+ }
+
+ void DisplayMessageBox(const Q3DStudio::CString &inDescription) override
+ {
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_DELETE_OBJ_CONFIRM_TITLE));
+ Q3DStudio::CString theFormat(::LoadResourceString(IDS_DELETE_OBJ_CONFIRM_MSG));
+ Q3DStudio::CString theMessage;
+ theMessage.Format(theFormat, static_cast<const wchar_t *>(inDescription));
+
+ m_Dialogs.DisplayMessageBox(theTitle, theMessage, CUICMessageBox::ICON_WARNING, false);
+ }
+};
+
+void CStudioApp::SetupTimer(long inMessageId, QWidget *inWnd)
+{
+ m_TickTock = ITickTock::CreateTickTock(inMessageId, inWnd);
+ GetDirectoryWatchingSystem();
+ m_Core->GetDoc()->SetDirectoryWatchingSystem(m_DirectoryWatchingSystem);
+ m_Core->GetDoc()->SetImportFailedHandler(
+ std::make_shared<SIImportFailedHandler>(std::ref(*GetDialogs())));
+ m_Core->GetDoc()->SetDocMessageBoxHandler(
+ std::make_shared<SIDeletingReferencedObjectHandler>(std::ref(*GetDialogs())));
+}
+
+ITickTock &CStudioApp::GetTickTock()
+{
+ if (m_TickTock == nullptr)
+ throw std::runtime_error("Uninitialized TickTock");
+ return *m_TickTock;
+}
+
+Q3DStudio::IStudioRenderer &CStudioApp::GetRenderer()
+{
+ if (!m_Renderer)
+ m_Renderer = Q3DStudio::IStudioRenderer::CreateStudioRenderer();
+ return *m_Renderer;
+}
+
+void CStudioApp::ClearGuides()
+{
+ SCOPED_DOCUMENT_EDITOR(*m_Core->GetDoc(), QObject::tr("Clear Guides"))->ClearGuides();
+}
+
+void SendAsyncCommand(CDispatch &inDispatch, Q3DStudio::TCallbackFunc inFunc)
+{
+ inDispatch.FireOnAsynchronousCommand(inFunc);
+}
+
+IDirectoryWatchingSystem &CStudioApp::GetDirectoryWatchingSystem()
+{
+ if (m_DirectoryWatchingSystem == nullptr) {
+ Q3DStudio::TCallbackCaller theCaller =
+ std::bind(SendAsyncCommand, std::ref(*m_Core->GetDispatch()), std::placeholders::_1);
+ m_DirectoryWatchingSystem =
+ IDirectoryWatchingSystem::CreateThreadedDirectoryWatchingSystem(theCaller);
+ }
+ return *m_DirectoryWatchingSystem;
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+bool s_testVar = true;
+//==============================================================================
+/**
+ * This gets called any time an unhandled exception is thrown anywhere in the
+ * application.
+ *
+ * @param pExPtrs a description of the exception.
+ * @return 0 if not handled, 1 if it was handled.
+ */
+void CStudioApp::StudioUnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs)
+{
+ TCHAR theTraceBuffer[4096];
+ CCrashDlg theDlg;
+ Q3DStudio::CString errorMessage;
+
+ CStackOps::GetExceptionStackTrace(theTraceBuffer, sizeof(theTraceBuffer),
+ pExPtrs->ContextRecord);
+ if (g_UICErrorCode != 0) {
+ // switch (g_UICErrorCode)
+ //{
+ // default:
+ Q3DStudio::CString description;
+ description.Format(_UIC("Custom error 0x%X "), g_UICErrorCode);
+ errorMessage = CStackOps::GetExceptionDescription(description, pExPtrs);
+ // break;
+ //}
+ } else {
+ errorMessage = CStackOps::GetExceptionDescription(pExPtrs);
+ }
+ theDlg.SetStackTrace(theTraceBuffer);
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Crash!" << theTraceBuffer;
+ // Attempt to save the current project (although this may crash).
+ CDoc &theDoc = *g_StudioApp.m_Core->GetDoc();
+ CFilePath theFullPath = theDoc.GetDocumentPath().GetAbsolutePath();
+ CFilePath theDir = theFullPath.GetDirectory();
+ CFilePath theStem = theFullPath.GetFileStem();
+ theStem.append(L"_Crash");
+ // Attempt to open a dump file ideally next to the log file.
+ CFilePath theSaveFile;
+ {
+ TFilePtr theSaveFilePtr =
+ SFileTools::FindUniqueDestFile(theDir, theStem, CFilePath(L"uip"));
+ theSaveFile = theSaveFilePtr->m_Path;
+ }
+ theSaveFile.DeleteThisFile();
+ theDoc.SaveDocument(CUICFile(theSaveFile));
+ qCInfo(qt3ds::TRACE_INFO) << "Project successfully saved: " << theSaveFile.GetCharStar();
+
+ ::CString fileSaveLocationMessage;
+ fileSaveLocationMessage.Format(L"Project saved as %ls",
+ static_cast<const wchar_t *>(theSaveFile));
+
+ theDlg.SetErrorMessage(errorMessage);
+ theDlg.SetFilename(fileSaveLocationMessage);
+ theDlg.DoModal();
+}
+
+void CStudioApp::InitHelpSystem()
+{
+ Q3DStudio::CString theHelpFile = ::LoadResourceString(IDS_HELP_FILE_NAME);
+
+ ATL::CStringT<TCHAR, StrTraitMFC<TCHAR>> theOldHelpPath(m_pszHelpFilePath);
+ ATL::CStringT<TCHAR, StrTraitMFC<TCHAR>> theNewHelpPath;
+
+ long theIndex = theOldHelpPath.ReverseFind('\\');
+ theOldHelpPath.Delete(theIndex + 1, (theOldHelpPath.GetLength() - theIndex));
+ theNewHelpPath = theOldHelpPath;
+ ::CString theMFCHelpFile(theHelpFile.GetMulti());
+ theNewHelpPath += theMFCHelpFile;
+
+ // Save the m_pszHelpFilePath variable so that CWinApp::SetCurrentHandles()
+ // in appinit.cpp can deallocate the memory it allocated, which causes a
+ // mmgr.h assert when we free it in here
+ m_OldHelpFilePath = const_cast<LPTSTR>(m_pszHelpFilePath);
+
+ long theLength = theNewHelpPath.GetLength();
+ m_pszHelpFilePath = new TCHAR[theLength + 1];
+ ::lstrcpyn(const_cast<LPTSTR>(m_pszHelpFilePath), theNewHelpPath, theLength + 1);
+}
+#endif
+
+CCore *CStudioApp::GetCore()
+{
+ return m_Core;
+}
+
+//=============================================================================
+/**
+ * Get the view manager for this core to communicate to the views.
+ */
+CViews *CStudioApp::GetViews()
+{
+ return m_Views;
+}
+
+//=============================================================================
+/**
+ * Get the dialog manager for this core for displaying dialogs.
+ */
+CDialogs *CStudioApp::GetDialogs()
+{
+ return m_Dialogs;
+}
+
+long CStudioApp::GetToolMode()
+{
+ return m_ToolMode;
+}
+
+void CStudioApp::SetToolMode(long inToolMode)
+{
+ if (m_ToolMode != inToolMode) {
+ m_ToolMode = inToolMode;
+ m_Core->GetDispatch()->FireOnToolbarChange();
+ }
+}
+
+long CStudioApp::GetSelectMode()
+{
+ return m_SelectMode;
+}
+
+void CStudioApp::SetSelectMode(long inSelectMode)
+{
+ if (m_SelectMode != inSelectMode) {
+ m_SelectMode = inSelectMode;
+ m_Core->GetDispatch()->FireOnToolbarChange();
+ }
+}
+
+StudioManipulationModes::Enum CStudioApp::GetMinpulationMode() const
+{
+ return m_ManipulationMode;
+}
+void CStudioApp::SetMinpulationMode(StudioManipulationModes::Enum inManipulationMode)
+{
+ if (m_ManipulationMode != inManipulationMode) {
+ m_ManipulationMode = inManipulationMode;
+ m_Core->GetDispatch()->FireOnToolbarChange();
+ }
+}
+
+//=============================================================================
+/**
+ * return true if undo is possible
+ */
+bool CStudioApp::CanUndo()
+{
+ return m_Core->GetCmdStack()->CanUndo();
+}
+
+//=============================================================================
+/**
+ * return true if redo is possible
+ */
+bool CStudioApp::CanRedo()
+{
+ return m_Core->GetCmdStack()->CanRedo();
+}
+
+void CStudioApp::OnCopy()
+{
+ m_Core->GetDoc()->HandleCopy();
+}
+
+bool CStudioApp::CanCopy()
+{
+ return m_Core->GetDoc()->CanCopy();
+}
+
+//=============================================================================
+/**
+ * Get a string describing the type of the copy operation that can be done.
+ * Precedence of copying is 1) Actions; 2) Keyframes; 3) Objects
+ */
+Q3DStudio::CString CStudioApp::GetCopyType()
+{
+ Q3DStudio::CString theCopyType;
+
+ CDoc *theDoc = m_Core->GetDoc();
+ if (theDoc->CanCopyAction())
+ theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_ACTION);
+ else if (theDoc->CanCopyKeyframe())
+ theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_KEYFRAMES);
+ else
+ theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_OBJECT);
+
+ return theCopyType;
+}
+
+//=============================================================================
+/**
+ * Cuts the selected object or keys
+ */
+void CStudioApp::OnCut()
+{
+ m_Core->GetDoc()->HandleCut();
+}
+
+bool CStudioApp::CanCut()
+{
+ return m_Core->GetDoc()->CanCut();
+}
+
+//=============================================================================
+/**
+ * Paste keys from the copied list yo
+ */
+void CStudioApp::OnPaste()
+{
+ m_Core->GetDoc()->HandlePaste();
+}
+
+bool CStudioApp::CanPaste()
+{
+ return m_Core->GetDoc()->CanPaste();
+}
+
+//=============================================================================
+/**
+ * Get a string describing the type of the paste operation that can be done.
+ * Precedence of paste is 1) Actions; 2) Object ; 3) Keyframes
+ */
+Q3DStudio::CString CStudioApp::GetPasteType()
+{
+ Q3DStudio::CString thePasteType;
+
+ CDoc *theDoc = m_Core->GetDoc();
+ if (theDoc->CanPasteAction())
+ thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_ACTION);
+ else if (theDoc->CanPasteObject())
+ thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_OBJECT);
+ else
+ thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_KEYFRAMES);
+
+ return thePasteType;
+}
+
+bool CStudioApp::CanChangeTimebarColor()
+{
+ bool theRetVal = true;
+ UICDM::CUICDMInstanceHandle theSelectedInstance = m_Core->GetDoc()->GetSelectedInstance();
+ if (!theSelectedInstance.Valid()
+ || m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsSceneInstance(
+ theSelectedInstance))
+ theRetVal = false;
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Sets any changed keyframes on the selected object
+ */
+void CStudioApp::HandleSetChangedKeys()
+{
+ m_Core->GetDoc()->SetChangedKeyframes();
+}
+
+//=============================================================================
+/**
+ * Deletes all selected keys
+ */
+void CStudioApp::DeleteSelectedKeys()
+{
+ m_Core->GetDoc()->DeleteSelectedKeys();
+}
+
+//=============================================================================
+/**
+ * Handles the duplicate object command
+ */
+void CStudioApp::HandleDuplicateCommand()
+{
+ m_Core->GetDoc()->HandleDuplicateCommand();
+}
+
+//=============================================================================
+/**
+ * return true if the selected object is duplicatable
+ */
+bool CStudioApp::CanDuplicateObject()
+{
+ // Get the currently selected object
+ UICDM::CUICDMInstanceHandle theSelectedInstance = m_Core->GetDoc()->GetSelectedInstance();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Check if the object can be duplicated
+ return m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsDuplicateable(
+ theSelectedInstance);
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Toggles the state of autoset keyframes.
+ */
+void CStudioApp::OnToggleAutosetKeyframes()
+{
+ SetAutosetKeyframes(!CStudioPreferences::IsAutosetKeyframesOn());
+
+ m_Core->GetDispatch()->FireOnToolbarChange();
+}
+
+//==============================================================================
+/**
+ * Updates the preferences, and AnimationSystem.
+ */
+void CStudioApp::SetAutosetKeyframes(bool inFlag)
+{
+ CStudioPreferences::SetAutosetKeyframesOn(inFlag);
+
+ m_Core->GetDoc()->GetStudioSystem()->GetAnimationSystem()->SetAutoKeyframe(inFlag);
+}
+
+//==============================================================================
+/**
+ * If the presentation is not currently playing, this function will make it
+ * start playing from the current position. The starting point of the playhead
+ * is saved so that it can be restored later.
+ */
+void CStudioApp::PlaybackPlay()
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ if (!theDoc->IsPlaying()) {
+ m_PlaybackTime = theDoc->GetCurrentViewTime();
+ m_PlaybackOriginalSlide = theDoc->GetActiveSlide();
+ theDoc->SetPlayMode(PLAYMODE_PLAY);
+ }
+}
+
+//==============================================================================
+/**
+ * If the presentation is currently playing, it is stopped. The playhead is
+ * left wherever it was stopped at (hence it's not restored).
+ */
+void CStudioApp::PlaybackStopNoRestore()
+{
+ m_Core->GetDoc()->SetPlayMode(PLAYMODE_STOP);
+}
+
+//==============================================================================
+/**
+ * Moves the playhead back to time zero.
+ */
+void CStudioApp::PlaybackRewind()
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ if (theDoc->IsPlaying()) {
+ theDoc->SetPlayMode(PLAYMODE_STOP, 0);
+ theDoc->SetPlayMode(PLAYMODE_PLAY);
+ } else {
+ m_Core->GetDoc()->NotifyTimeChanged(0);
+ }
+}
+
+//=============================================================================
+/**
+ * Performs a file revert.
+ * This will revert the doc to the last saved version.
+ */
+void CStudioApp::OnRevert()
+{
+ if (!m_Core->GetDoc()->IsModified() || m_Dialogs->ConfirmRevert()) {
+ CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath();
+ OnLoadDocument(theCurrentDoc);
+ }
+}
+
+//=============================================================================
+/**
+ * Check to see if it is possible to perform a revert.
+ */
+bool CStudioApp::CanRevert()
+{
+ return m_Core->GetDoc()->IsModified() && m_Core->GetDoc()->GetDocumentPath().GetPath() != "";
+}
+
+//==============================================================================
+/**
+ * Handles the recent list.
+ */
+void CStudioApp::OnFileOpenRecent(const CUICFile &inDocument)
+{
+ if (PerformSavePrompt())
+ OnLoadDocument(inDocument);
+}
+
+//==============================================================================
+/**
+ * Called when closing the current doc, this prompts the user to save the doc.
+ * This will only prompt if the doc is modified, and if the user selects save
+ * then this will perform the save operation.
+ * @return true if the operation should continue, false if not.
+ */
+bool CStudioApp::PerformSavePrompt()
+{
+ if (m_Core->GetDoc()->IsModified()) {
+ CDialogs::ESavePromptResult theResult = m_Dialogs->PromptForSave();
+ if (theResult == CDialogs::SAVE_FIRST) {
+ bool onSaveResult = OnSave();
+ if (onSaveResult)
+ return true;
+ } else if (theResult == CDialogs::CONTINUE_NO_SAVE)
+ return true;
+
+ return false;
+ }
+ return true;
+}
+
+//==============================================================================
+/**
+ * If the presentation is currently playing, it is stopped. The playhead is
+ * restored to the position found in m_PlaybackTime.
+ */
+void CStudioApp::PlaybackStop()
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ // change it back to the original slide first before restoring the original time
+ if (m_PlaybackOriginalSlide.Valid()) {
+ if (m_PlaybackOriginalSlide != theDoc->GetActiveSlide())
+ theDoc->NotifyActiveSlideChanged(m_PlaybackOriginalSlide);
+ theDoc->SetPlayMode(PLAYMODE_STOP, m_PlaybackTime);
+ }
+ // Invalidate the playback original slide so we don't inadvertently trigger this code later.
+ m_PlaybackOriginalSlide = 0;
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::AdvanceTime()
+{
+ long theDeltaTime = CStudioPreferences::GetTimeAdvanceAmount();
+ long theTime =
+ (m_Core->GetDoc()->GetCurrentViewTime() + theDeltaTime) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::ReduceTime()
+{
+ long theDeltaTime = CStudioPreferences::GetTimeAdvanceAmount();
+ long theTime = (m_Core->GetDoc()->GetCurrentViewTime() - 1) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::AdvanceUltraBigTime()
+{
+ long theDeltaTime = CStudioPreferences::GetBigTimeAdvanceAmount();
+ long theTime =
+ (m_Core->GetDoc()->GetCurrentViewTime() + theDeltaTime) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::ReduceUltraBigTime()
+{
+ long theDeltaTime = CStudioPreferences::GetBigTimeAdvanceAmount();
+ long theTime = (m_Core->GetDoc()->GetCurrentViewTime() - 1) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//==============================================================================
+/**
+ * If the presentation is currently playing, it is stopped. Otherwise, the
+ * presetation starts playing from its current position. Called when the user
+ * presses the Enter key.
+ */
+void CStudioApp::PlaybackToggle()
+{
+ // If the presentation is playing, stop it and leave the playhead where it is
+ if (m_Core->GetDoc()->IsPlaying())
+ PlaybackStopNoRestore();
+ // Otherwise, the presentation is stopped, so start it playing
+ else
+ PlaybackPlay();
+}
+
+CInspectableBase *CStudioApp::GetInspectableFromSelectable(Q3DStudio::SSelectedValue inSelectable)
+{
+ CInspectableBase *theInspectableBase = nullptr;
+ if (inSelectable.empty() == false) {
+ switch (inSelectable.getType()) {
+ case Q3DStudio::SelectedValueTypes::Slide:
+ theInspectableBase = new CUICDMInspectable(
+ *this, m_Core, inSelectable.getData<Q3DStudio::SSlideInstanceWrapper>().m_Instance);
+ break;
+ case Q3DStudio::SelectedValueTypes::MultipleInstances:
+ case Q3DStudio::SelectedValueTypes::Instance: {
+
+ // We need to decide whether to display SlideInspectable or UICDMInspectable
+ // We display SlideInspectable if user selects a Scene or Component where the current
+ // active slide belongs,
+ // for example when user selects the Root in Timeline Palette
+ CDoc *theDoc = m_Core->GetDoc();
+ UICDM::TInstanceHandleList theSelectedInstances =
+ theDoc->GetSelectedValue().GetSelectedInstances();
+ UICDM::CUICDMInstanceHandle theSelectedInstance;
+ if (theSelectedInstances.size() == 1)
+ theSelectedInstance = theSelectedInstances[0];
+
+ if (m_Core->GetDoc()->GetDocumentReader().IsInstance(theSelectedInstance)) {
+ CClientDataModelBridge *theBridge =
+ theDoc->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::CUICDMSlideHandle theCurrentActiveSlide = theDoc->GetActiveSlide();
+
+ // Slide, scene or component
+ if (theSelectedInstance
+ == theBridge->GetOwningComponentInstance(theCurrentActiveSlide)) {
+ CUICDMInstanceHandle theCurrentActiveSlideInstance =
+ theDoc->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(
+ theCurrentActiveSlide);
+
+ if (theBridge->IsSceneInstance(theSelectedInstance))
+ theInspectableBase = new CUICDMSceneInspectable(
+ *this, m_Core, theSelectedInstance, theCurrentActiveSlideInstance);
+ else if (theBridge->IsComponentInstance(theSelectedInstance))
+ theInspectableBase = new CUICDMInspectable(
+ *this, m_Core, theSelectedInstance, theCurrentActiveSlideInstance);
+ }
+ if (theInspectableBase == nullptr) {
+ if (theBridge->IsMaterialBaseInstance(theSelectedInstance))
+ theInspectableBase =
+ new CUICDMMaterialInspectable(*this, m_Core, theSelectedInstance);
+ else
+ theInspectableBase =
+ new CUICDMInspectable(*this, m_Core, theSelectedInstance);
+ }
+ }
+ } break;
+ case Q3DStudio::SelectedValueTypes::Guide: {
+ UICDM::CUICDMGuideHandle theGuide = inSelectable.getData<UICDM::CUICDMGuideHandle>();
+ theInspectableBase = CGuideInspectable::CreateInspectable(*m_Core, theGuide);
+ } break;
+ };
+ }
+
+ return theInspectableBase;
+}
+
+void CStudioApp::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::AdvanceTime), 0, Qt::Key_Period);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::ReduceTime), 0, Qt::Key_Comma);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::AdvanceUltraBigTime),
+ Qt::ShiftModifier, Qt::Key_Greater);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::ReduceUltraBigTime),
+ Qt::ShiftModifier, Qt::Key_Less);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnToggleAutosetKeyframes), 0, Qt::Key_K);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSaveAs),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_S);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSave), Qt::ControlModifier,
+ Qt::Key_S);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSaveCopy),
+ Qt::ControlModifier | Qt::AltModifier, Qt::Key_S);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnFileNew),
+ Qt::ControlModifier, Qt::Key_N);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnFileOpen),
+ Qt::ControlModifier, Qt::Key_O);
+ inShortcutHandler->RegisterKeyUpEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackStop), 0,
+ Qt::Key_Space);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackPlay), 0,
+ Qt::Key_Space);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackToggle), 0,
+ Qt::Key_Return);
+
+ if (m_Views)
+ m_Views->RegisterGlobalKeyboardShortcuts(inShortcutHandler);
+}
+
+//=============================================================================
+/**
+ * Handles the Save command
+ * This will save the file, if the file has not been saved before this will
+ * do a save as operation.
+ * @return true if the file was successfully saved.
+ */
+bool CStudioApp::OnSave()
+{
+ CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath();
+ if (!theCurrentDoc.IsFile()) {
+ return OnSaveAs();
+ } else if (!theCurrentDoc.CanWrite()) {
+ m_Dialogs->DisplaySavingPresentationFailed();
+ return false;
+ } else {
+ m_Core->OnSaveDocument(theCurrentDoc);
+ return true;
+ }
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Save As menu option.
+ * This will prompt the user for a location to save the file out to then
+ * will perform the save.
+ * @return true if the file was successfully saved.
+ */
+bool CStudioApp::OnSaveAs()
+{
+ CUICFile theFile = m_Dialogs->GetSaveAsChoice().first;
+ if (theFile.GetPath() != "") {
+ m_Core->OnSaveDocument(theFile);
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Save As menu option.
+ * This will prompt the user for a location to save the file out to then
+ * save a copy, leaving the original file open in the editor.
+ * @return true if the file was successfully saved.
+ */
+bool CStudioApp::OnSaveCopy()
+{
+ CUICFile theFile = m_Dialogs->GetSaveAsChoice().first;
+ if (theFile.GetPath() != "") {
+ // Send in a "true" to teh save function to indicate this is a copy
+ m_Core->OnSaveDocument(theFile, true);
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Call to load a new document.
+ * There should not be a currently active document when this is called.
+ * @param inDocument the path to the UIP file to be loaded.
+ * @param inShowStartupDialogOnError true to show startup dialog if loading document is error
+ * @return true if loading was successful
+ */
+bool CStudioApp::OnLoadDocument(const CUICFile &inDocument, bool inShowStartupDialogOnError)
+{
+ m_Core->GetDispatch()->FireOnProgressBegin(CString::fromQString(QObject::tr("Loading...")), inDocument.GetName(),
+ CString::fromQString(QObject::tr("Loading...")));
+
+ bool theLoadResult = false;
+ int theLoadErrorParameter = -1;
+ Q3DStudio::CString theErrorText;
+ try {
+ OnLoadDocumentCatcher(inDocument);
+ m_Core->GetDispatch()->FireOnOpenDocument(inDocument, true);
+ // Loading was successful
+ theLoadResult = true;
+ } catch (CUnsupportedFileFormatException &) {
+ theErrorText = CString::fromQString(QObject::tr("The file could not be opened. It is either invalid or was made with an "
+ "old version of Studio."));
+ // We've encountered a file format that is older than the current, OR
+ // corrupt files, unsupported file formats and illegal types.
+ } catch (CInvalidFileFormatException &) {
+ theErrorText = CString::fromQString(QObject::tr("The file could not be opened. It appears to have been made with a newer "
+ "version of Studio."));
+ // Cannot support opening newer file format, the UIP or (AP ie client portion)'s version is
+ // mismatched.
+ } catch (CLoadReferencedFileException &inError) {
+ // referenced files (e.g. Data Files) failed to load
+ theErrorText.Format(L"%ls failed to load due to invalid referenced file: %ls.",
+ static_cast<const wchar_t *>(inDocument.GetName()),
+ inError.GetFilePath()); // TODO: Localize
+ const wchar_t *theDesc = inError.GetDescription();
+ if (theDesc && wcslen(theDesc) > 0) {
+ // append any description is provided
+ theErrorText += L"\n";
+ theErrorText += inError.GetDescription();
+ }
+ } catch (CIOException &) { // provide specific error message if possible
+ if (inDocument.Exists() == false)
+ theLoadErrorParameter = IDS_ERROR_LOADFILENOTEXIST;
+ qCCritical(qt3ds::INTERNAL_ERROR)
+ << "Failed to load document, IO error (file may be unreadable or nonexistent)";
+ } catch (...) {
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to load document, uknown error";
+ // We don't know exactly what went wrong during a load, but let studio 'fail gracefully'.
+ }
+
+ if (theErrorText.Length()) {
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to load document: "
+ << theErrorText.GetCharStar();
+ }
+
+ m_Core->GetDispatch()->FireOnProgressEnd();
+
+ // load fail
+ if (!theLoadResult) {
+ if (!theErrorText.IsEmpty())
+ m_Dialogs->DisplayKnownErrorDialog(theErrorText);
+ else
+ m_Dialogs->DisplayLoadingPresentationFailed(inDocument, theLoadErrorParameter);
+
+ m_Core->GetDispatch()->FireOnOpenDocument(inDocument, false);
+
+ // Show startup dialog
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (inShowStartupDialogOnError)
+ if (!ShowStartupDialog())
+ PostQuitMessage(WM_QUIT);
+#endif
+ } else {
+ m_Dialogs->ResetSettings(inDocument.GetPath());
+
+ m_subpresentations.clear();
+ m_Core->GetDoc()->LoadUIASubpresentations(m_Core->GetDoc()->GetDocumentUIAFile(),
+ m_subpresentations);
+ }
+
+ m_AuthorZoom = false;
+
+ m_Core->GetDispatch()->FireAuthorZoomChanged();
+
+ return theLoadResult;
+}
+
+
+//=============================================================================
+/**
+ *
+ */
+void CStudioApp::SaveUIAFile()
+{
+ QStringList list;
+ for (SubPresentationRecord r : m_subpresentations) {
+ list.append(r.m_type);
+ list.append(r.m_id);
+ list.append(r.m_argsOrSrc);
+ }
+ Q3DStudio::CFilePath doc(GetCore()->GetDoc()->GetDocumentPath().GetAbsolutePath());
+ uic::state::IApplication::EnsureApplicationFile(doc.GetCharStar(), list);
+}
+
+//=============================================================================
+/**
+ * Called by OnLoadDocument, to allow the error reporting to be inserted.
+ * Because of the nature of the error reporting, OnLoadDocument has to have
+ * a certain structure that limits it (C type variables, no object destructors).
+ */
+void CStudioApp::OnLoadDocumentCatcher(const CUICFile &inDocument)
+{
+ {
+ CDispatchDataModelNotificationScope __scope(*m_Core->GetDispatch());
+ m_Core->GetDoc()->CloseDocument();
+ m_Core->GetDoc()->LoadDocument(inDocument);
+ }
+
+ // Make sure the client scene is resized properly
+ if (m_Views)
+ m_Views->RecheckMainframeSizingMode();
+}
+
+void CStudioApp::OnFileOpen()
+{
+ if (PerformSavePrompt()) {
+ CUICFile theFile = m_Dialogs->GetFileOpenChoice();
+ if (theFile.GetPath() != "")
+ OnLoadDocument(theFile);
+ }
+}
+using namespace std;
+
+void CStudioApp::OnFileNew()
+{
+ if (PerformSavePrompt()) {
+ pair<CUICFile, bool> theFile = m_Dialogs->GetNewDocumentChoice();
+ if (theFile.first.GetPath() != "")
+ m_Core->OnNewDocument(theFile.first, theFile.second);
+ }
+}
+
+bool CStudioApp::IsAuthorZoom()
+{
+ return m_AuthorZoom;
+}
+
+void CStudioApp::SetAuthorZoom(bool inZoom)
+{
+ if (m_AuthorZoom != inZoom) {
+ m_AuthorZoom = inZoom;
+ m_Core->GetDispatch()->FireAuthorZoomChanged();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// These commands come over the dispatch from inside the core. The core doesn't
+// have access to the CMsgRouter at the moment, so this relays the message.
+void CStudioApp::OnAsynchronousCommand(CCmd *inCmd)
+{
+ CMsgRouter::GetInstance()->SendCommand(inCmd, m_Core);
+}
+
+void CStudioApp::OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg)
+{
+ // Do nothing, it was used to show this in the status bar
+}
+
+void CStudioApp::OnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle)
+{
+ m_Dialogs->DisplayProgressScreen(inActionText, inFileName, inWindowTitle);
+}
+
+void CStudioApp::OnProgressEnd()
+{
+ m_Dialogs->DestroyProgressScreen();
+}
+
+void CStudioApp::OnAssetDeleteFail()
+{
+ m_Dialogs->DisplayAssetDeleteFailed();
+}
+
+void CStudioApp::OnPasteFail()
+{
+ m_Dialogs->DisplayPasteFailed();
+}
+
+void CStudioApp::OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage)
+{
+ m_Dialogs->DisplayMessageBox(::LoadResourceString(IDS_BUILDCONFIGS_ERROR_TITLE), inMessage,
+ CUICMessageBox::ICON_ERROR, false);
+}
+
+void CStudioApp::OnSaveFail(bool inKnownError)
+{
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to save project: "
+ << (inKnownError ? "KnownError" : "UnknownError");
+ if (inKnownError) {
+ m_Dialogs->DisplaySavingPresentationFailed();
+ } else {
+ m_Dialogs->DisplayKnownErrorDialog(::LoadResourceString(IDS_SAVE_UNKNOWN_ERROR));
+ }
+}
+
+void CStudioApp::OnProjectVariableFail(const Q3DStudio::CString &inMessage)
+{
+ m_Dialogs->DisplayEnvironmentVariablesError(inMessage);
+}
+
+void CStudioApp::OnErrorFail(const Q3DStudio::CString &inText)
+{
+ qCCritical(qt3ds::INTERNAL_ERROR) << inText.GetCharStar();
+ m_Dialogs->DisplayMessageBox(::LoadResourceString(IDS_PROJNAME), inText,
+ CUICMessageBox::ICON_ERROR, false);
+}
+
+void CStudioApp::OnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription)
+{
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to refresh resource: "
+ << inResourceName.GetCharStar();
+ qCCritical(qt3ds::INTERNAL_ERROR) << inDescription.GetCharStar();
+ m_Dialogs->DisplayRefreshResourceFailed(inResourceName, inDescription);
+}
+
+void CStudioApp::OnNewPresentation()
+{
+ m_Core->GetDoc()->GetStudioSystem()->GetAnimationSystem()->SetAutoKeyframe(
+ CStudioPreferences::IsAutosetKeyframesOn());
+ qCInfo(qt3ds::TRACE_INFO) << "New Presentation: "
+ << m_Core->GetDoc()->GetDocumentPath().GetAbsolutePath().GetCharStar();
+}
+
+void CStudioApp::OnPresentationModifiedExternally()
+{
+ int theUserChoice = m_Dialogs->DisplayChoiceBox(
+ ::LoadResourceString(IDS_TITLE_WARNING),
+ ::LoadResourceString(IDS_PRESENTATION_MODIFIED_EXTERNALLY), CUICMessageBox::ICON_WARNING);
+ if (theUserChoice == IDYES) {
+ CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath();
+ OnLoadDocument(theCurrentDoc);
+ }
+}
diff --git a/src/Authoring/Studio/_Win/Application/StudioApp.h b/src/Authoring/Studio/_Win/Application/StudioApp.h
new file mode 100644
index 00000000..caea5158
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/StudioApp.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STUDIO_APP_H
+#define INCLUDED_STUDIO_APP_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CmdLineParser.h"
+#include "StudioObjectTypes.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <minmax.h>
+#include <gdiplus.h>
+#endif
+#include "DispatchListeners.h"
+#include "UICDMHandles.h"
+
+#include <QApplication>
+
+namespace Q3DStudio {
+class IInternalDirectoryWatchingSystem;
+class IDirectoryWatchingSystem;
+class ITickTock;
+class IStudioRenderer;
+struct SSelectedValue;
+};
+
+namespace UICDM {
+class ISignalConnection;
+};
+
+struct StudioManipulationModes
+{
+ enum Enum {
+ Local,
+ Global,
+ };
+};
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CCore;
+class CDialogs;
+class CSplashView;
+class CInspectableBase;
+class CDirectoryWatchingSystemWrapper;
+class CHotKeys;
+class CViews;
+class CMainFrame;
+enum EStudioObjectType;
+struct SubPresentationRecord;
+
+class CStudioApp : public CCoreAsynchronousEventListener,
+ public CAppStatusListener,
+ public CFailListener,
+ public CPresentationChangeListener // to setup auto set keyframes
+{
+public:
+ CStudioApp();
+ virtual ~CStudioApp();
+
+ // Overrides
+public:
+ virtual BOOL InitInstance(int argc, char *argv[]);
+ virtual int ExitInstance();
+ virtual int Run();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ virtual UINT GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault);
+ virtual BOOL WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue);
+ virtual ::CString GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry,
+ LPCTSTR lpszDefault = nullptr);
+ virtual BOOL WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue);
+#endif
+
+ void OnAppAbout();
+
+public:
+ void PerformShutdown();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ static void StudioUnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs);
+#endif
+ Q3DStudio::IDirectoryWatchingSystem &GetDirectoryWatchingSystem();
+ void SetupTimer(long inMessageId, QWidget *inWnd);
+ Q3DStudio::ITickTock &GetTickTock();
+ Q3DStudio::IStudioRenderer &GetRenderer();
+ void ClearGuides();
+
+protected:
+ int RunApplication();
+ int BlankRunApplication();
+ int RunCmdLineTests(const Q3DStudio::CString &inTestArgs);
+ int RunSystemTests(const Q3DStudio::CString &inTestArgs);
+ int OpenAndRunApplication(const Q3DStudio::CString &inFilename);
+ void InitCore();
+ void InitHelpSystem();
+ bool ShowStartupDialog();
+ bool HandleWelcomeRes(int res, bool recursive);
+
+ CCore *m_Core;
+ CSplashView *m_SplashPalette; ///< Startup splash palette
+ QString m_OldHelpFilePath; ///< Stores a pointer to the old
+ CCmdLineParser m_CmdLineParser; ///< Stores and returns execution modes
+ int m_UnitTestResults; ///< 0 on success; 1 on failure
+ bool m_IsSilent; ///< true indicates Studio running in silent mode (no GUI)
+ CViews *m_Views;
+ long m_ToolMode;
+ StudioManipulationModes::Enum
+ m_ManipulationMode; ///< Controls what space the tras,rot,and scale manipulations work in.
+ long m_SelectMode;
+ CDialogs *m_Dialogs;
+ long m_PlaybackTime; ///< Stores the playhead's starting position so that it can be restored
+ ///after playing the presentation for a little while
+ UICDM::CUICDMSlideHandle
+ m_PlaybackOriginalSlide; ///< Stores the current slide handle before playback started.
+
+ std::shared_ptr<Q3DStudio::ITickTock> m_TickTock;
+ std::shared_ptr<Q3DStudio::IDirectoryWatchingSystem> m_DirectoryWatchingSystem;
+ std::shared_ptr<UICDM::ISignalConnection> m_DirectoryWatcherTicker;
+ std::shared_ptr<Q3DStudio::IStudioRenderer> m_Renderer;
+ bool m_AuthorZoom;
+
+private:
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
+ ULONG_PTR m_pGdiToken;
+#endif
+
+ bool m_welcomeShownThisSession;
+ // are we are launching welcome screen again due to
+ // user canceling file dialog?
+ bool m_goStraightToWelcomeFileDialog;
+ int m_tutorialPage;
+public:
+ CMainFrame* m_pMainWnd;
+
+ CCore *GetCore();
+ CViews *GetViews();
+ CDialogs *GetDialogs();
+ long GetToolMode();
+ void SetToolMode(long inToolMode);
+ long GetSelectMode();
+ void SetSelectMode(long inSelectMode);
+
+ StudioManipulationModes::Enum GetMinpulationMode() const;
+ void SetMinpulationMode(StudioManipulationModes::Enum inManipulationMode);
+
+ bool CanUndo();
+ bool CanRedo();
+ void OnCopy();
+ bool CanCopy();
+ Q3DStudio::CString GetCopyType();
+ void OnCut();
+ bool CanCut();
+ void OnPaste();
+ bool CanPaste();
+ Q3DStudio::CString GetPasteType();
+ void SetSelectedObjectTimebarColor();
+ bool CanChangeTimebarColor();
+ void HandleSetChangedKeys();
+ void DeleteSelectedKeys();
+ void HandleDuplicateCommand();
+ bool CanDuplicateObject();
+ void OnToggleAutosetKeyframes();
+ void SetAutosetKeyframes(bool inFlag);
+ void PlaybackPlay();
+ void PlaybackStopNoRestore();
+ void PlaybackRewind();
+ void OnRevert();
+ bool CanRevert();
+ void OnFileOpenRecent(const CUICFile &inDocument);
+ bool PerformSavePrompt();
+ void PlaybackStop();
+ void AdvanceTime();
+ void ReduceTime();
+ void AdvanceUltraBigTime();
+ void ReduceUltraBigTime();
+ void PlaybackToggle();
+ CInspectableBase *GetInspectableFromSelectable(Q3DStudio::SSelectedValue inSelectable);
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+ bool OnSave();
+ bool OnSaveAs();
+ bool OnSaveCopy();
+ bool OnLoadDocument(const CUICFile &inDocument, bool inShowStartupDialogOnError = true);
+ void OnLoadDocumentCatcher(const CUICFile &inLocation);
+ void OnFileOpen();
+ void OnFileNew();
+ bool IsAuthorZoom();
+ void SetAuthorZoom(bool inZoom);
+
+ // CCoreAsynchronousEventListener
+ void OnAsynchronousCommand(CCmd *inCmd) override;
+
+ // CAppStatusListener
+ void OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg) override;
+ void OnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle) override;
+ void OnProgressEnd() override;
+
+ // CFailListener
+ void OnAssetDeleteFail() override;
+ void OnPasteFail() override;
+ void OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage) override;
+ void OnSaveFail(bool inKnownError) override;
+ void OnProjectVariableFail(const Q3DStudio::CString &inMessage) override;
+ void OnErrorFail(const Q3DStudio::CString &inText) override;
+ void OnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription) override;
+
+ // CPresentationChangeListener
+ void OnNewPresentation() override;
+ void OnPresentationModifiedExternally() override;
+
+ Q3DStudio::CString m_pszHelpFilePath;
+
+ QVector<SubPresentationRecord> m_subpresentations;
+ void SaveUIAFile();
+};
+
+extern CStudioApp g_StudioApp;
+
+#endif // INCLUDED_STUDIO_APP_H
diff --git a/src/Authoring/Studio/_Win/Application/StudioColors.h b/src/Authoring/Studio/_Win/Application/StudioColors.h
new file mode 100644
index 00000000..776047a5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/StudioColors.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIOCOLORS_H
+#define INCLUDED_STUDIOCOLORS_H
+
+#pragma once
+
+//==============================================================================
+// Studio colors
+//==============================================================================
+
+const COLORREF STUDIO_MATTE_COLOR = RGB(119, 122, 125); // GetSysColor( COLOR_APPWORKSPACE );
+const COLORREF MENU_IMAGELIST_BACKCOLOR = RGB(255, 0, 255); // RGB( 255, 128, 0 );
+
+//==============================================================================
+// TimeBar colors
+//==============================================================================
+
+// TimeBar pen colors
+
+const COLORREF TIMEBAR_PEN_COLOR_INNER = RGB(254, 254, 254);
+const COLORREF TIMEBAR_PEN_COLOR_INACTIVE = RGB(132, 130, 132);
+const COLORREF TIMEBAR_PEN_COLOR_ACTIVE = RGB(0, 0, 0);
+
+// TimeBar shadow colors
+
+const COLORREF TIMEBAR_INACTIVE_SHADOW_COLOR = RGB(0xC4, 0xC4, 0xC4);
+const COLORREF TIMEBAR_ACTIVE_SHADOW_COLOR = RGB(0x84, 0x84, 0x84);
+
+// TimeBar comment colors
+
+const COLORREF TIMEBAR_COMMENT_ACTIVE_TC = RGB(0x00, 0x00, 0x00);
+const COLORREF TIMEBAR_COMMENT_INACTIVE_TC = RGB(0x72, 0x72, 0x72);
+
+const COLORREF COLOR_TIMEBAR_DISABLED = RGB(207, 207, 207);
+const COLORREF COLOR_TIMEBAR_BEHAVIOR =
+ RGB(148, 189, 150); // RGB( 92, 164, 131 );//RGB( 243, 243, 243 );
+const COLORREF COLOR_TIMEBAR_MATERIAL =
+ RGB(194, 155, 181); // RGB( 190, 184, 152 ); //RGB( 239, 230, 210 );
+const COLORREF COLOR_TIMEBAR_IMAGE =
+ RGB(194, 155, 181); // RGB( 190, 184, 152 ); //RGB( 198, 225, 199 );
+const COLORREF COLOR_TIMEBAR_LOCKED = RGB(228, 228, 228);
+
+const COLORREF TIMEBAR_COLOR_TRANSPARENT = RGB(255, 0, 255);
+
+// A constant to represent color for inner white rectangle of center bar
+const COLORREF COLOR_INNER_BAR_RECTANGLE = RGB(253, 253, 254);
+// Default timebar fill color
+const COLORREF COLOR_TIMEBAR_DEFAULT_FILL = RGB(
+ 163, 178, 227); // RGB( 174, 183, 210 ); //RGB( 148, 166, 189 ); //RGB( 211, 226, 240 );
+
+// Selected time bar colors
+
+const COLORREF COLOR_TIMEBAR_SELECTED = RGB(75, 75, 75); // RGB( 14, 49, 98 );
+const COLORREF COLOR_TIMEBAR_SELECTED_TEXT = RGB(255, 255, 255);
+const COLORREF COLOR_TIMEBAR_SELECTED_BEHAVIOR = RGB(174, 216, 176);
+const COLORREF COLOR_TIMEBAR_SELECTED_HIGHLIGHT = RGB(27, 73, 136);
+
+// const COLORREF COLOR_SELECTED_TIMEBAR_3DOBJECT = RGB( 190, 191, 202
+// );
+
+const COLORREF COLOR_TIMEBAR_HIGHLIGHT = RGB(190, 191, 202);
+const COLORREF COLOR_TIMEBAR_HIGHLIGHT_GROUP = RGB(174, 216, 176);
+
+const COLORREF COLOR_PLAYHEADSCRUBTIME = RGB(0, 85, 0);
+
+//==============================================================================
+// Timeline colors
+//==============================================================================
+
+const BOOL INVERT_TIMELINE_TEXT_COLOR = TRUE;
+
+const COLORREF COLOR_SELECTEDTEXT = RGB(255, 255, 255);
+const COLORREF COLOR_SELECTEDTEXTBKGRND = RGB(14, 49, 98);
+const COLORREF COLOR_DRAGDROPTARGETTEXT = RGB(255, 255, 255);
+const COLORREF COLOR_DRAGDROPTARGETBKGRND = RGB(24, 98, 198);
+
+const COLORREF COLOR_SHADOW = RGB(165, 162, 161); // RGB( 132, 130, 132 );
+
+const COLORREF COLOR_PLAYHEADLINE = RGB(0xDD, 0x04, 0x05);
+const COLORREF COLOR_BACKGRND =
+ GetSysColor(COLOR_3DFACE); // RGB( 206, 203, 198 ); //RGB( 0xE7, 0xE7, 0xE7 );
+const COLORREF COLOR_SELECTED = RGB(255, 255, 255);
+const COLORREF COLOR_DEFAULTOBJECTS = RGB(206, 203, 198); // RGB( 0xE7, 0xE7, 0xE7 );
+const COLORREF COLOR_3DOBJECTS = RGB(206, 203, 198); // RGB( 0xC7, 0xD4, 0xE1 );
+const COLORREF COLOR_DEFAULTOBJECTHIGHLIGHT = RGB(222, 223, 222); // RGB( 255, 255, 255 );
+const COLORREF COLOR_DRAGHIGHLIGHT = RGB(255, 255, 255);
+const COLORREF COLOR_INSERTMARK = RGB(0x00, 0x00, 0x00);
+const COLORREF COLOR_TIMELINEINSERTMARK = RGB(0x00, 0x00, 0xFF);
+const COLORREF COLOR_TEXTCOLOR = RGB(0x00, 0x00, 0x00);
+const COLORREF COLOR_CONTAINERTEXTCOLOR = RGB(80, 80, 140);
+const COLORREF COLOR_LOCKEDTEXTCOLOR = RGB(0x80, 0x80, 0x80);
+const COLORREF COLOR_INDEPENDENTOBJECT = RGB(0x80, 0x80, 0x80);
+const COLORREF COLOR_SPLITLINE = RGB(0x00, 0x00, 0x7F);
+const COLORREF COLOR_SEPARATORLINE = RGB(0x00, 0x00, 0x20);
+const COLORREF COLOR_LIGHTMODEL = RGB(206, 203, 198); // RGB( 198, 211, 224 );
+const COLORREF COLOR_GROUP =
+ RGB(206, 203, 198); // RGB( 198, 211, 224 ); //RGB( 199, 220, 193 );
+const COLORREF COLOR_PROPERTY = RGB(228, 225, 219); // RGB( 241, 241, 241 );
+const COLORREF COLOR_CHANNEL = RGB(228, 225, 219); // RGB( 241, 241, 241 );
+const COLORREF COLOR_CONTAINER =
+ RGB(228, 225, 219); // RGB( 206, 203, 198 ); //RGB( 231, 231, 231 );
+const COLORREF COLOR_MATERIAL = RGB(210, 210, 210); // RGB( 170, 224, 170 );
+const COLORREF COLOR_CONTAINERHIGHLIGHT = RGB(193, 180, 180);
+const COLORREF COLOR_BEHAVIOR = RGB(199, 220, 193);
+const COLORREF COLOR_BEHAVIORHIGHLIGHT = RGB(255, 255, 255);
+const COLORREF COLOR_IMGLISTTRANSPARENT = RGB(0xFF, 0x00, 0xFF);
+const COLORREF COLOR_TIMEMEASURE = GetSysColor(COLOR_3DFACE); // RGB( 170, 166, 160 );
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp
new file mode 100644
index 00000000..e3e25fa1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "StudioDefs.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SubPresentationsDlg.h"
+#include "ui_SubPresentationsDlg.h"
+#include "ProductInfo.h"
+#include "HotKeys.h"
+#include "Preferences.h"
+#include "StudioPreferences.h"
+
+#include <QtGui/qevent.h>
+#include <QtGui/qpainter.h>
+#include <QtCore/qtimer.h>
+#include <QtWidgets/qfiledialog.h>
+
+CSubPresentationsDlg::CSubPresentationsDlg(
+ const QString &directory,
+ const QVector<SubPresentationRecord> &subpresentations,
+ QWidget *parent)
+ : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint)
+ , m_directory(directory)
+ , m_records(subpresentations)
+ , m_ui(new Ui::SubPresentationsDlg)
+{
+ m_ui->setupUi(this);
+
+ connect(m_ui->deleteButton, &QPushButton::clicked, this,
+ &CSubPresentationsDlg::OnDeletePresentation);
+ connect(m_ui->pushButtonNew, &QPushButton::clicked, this,
+ &CSubPresentationsDlg::OnNewPresentation);
+ connect(m_ui->pushButtonBrowse, &QPushButton::clicked, this,
+ &CSubPresentationsDlg::OnBrowsePresentation);
+ connect(m_ui->comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &CSubPresentationsDlg::OnSelectPresentation);
+ connect(m_ui->lineEditId, &QLineEdit::textEdited, this, &CSubPresentationsDlg::OnIdChanged);
+
+ OnInitDialog();
+}
+
+CSubPresentationsDlg::~CSubPresentationsDlg()
+{
+ delete m_ui;
+}
+
+QVector<SubPresentationRecord> CSubPresentationsDlg::subpresentations() const
+{
+ return m_records;
+}
+
+void CSubPresentationsDlg::OnInitDialog()
+{
+ current = -1;
+ if (m_records.size() > 0) {
+ for (SubPresentationRecord rec : m_records)
+ m_ui->comboBox->addItem(rec.m_id);
+ current = 0;
+ m_ui->lineEditId->setText(m_records[0].m_id);
+ m_ui->lineEditPreview->setText(m_records[0].m_argsOrSrc);
+ }
+ m_ui->lineEditPreview->setReadOnly(true);
+ m_ui->buttonBox->setFocusPolicy(Qt::NoFocus);
+}
+
+void CSubPresentationsDlg::OnSelectPresentation(int selectionIndex)
+{
+ if (selectionIndex >= 0 && selectionIndex < m_records.size()) {
+ current = selectionIndex;
+ m_ui->lineEditId->setText(m_records[current].m_id);
+ m_ui->lineEditPreview->setText(m_records[current].m_argsOrSrc);
+ } else {
+ m_ui->lineEditId->setText(QString());
+ m_ui->lineEditPreview->setText(QString());
+ }
+}
+
+void CSubPresentationsDlg::OnDeletePresentation()
+{
+ if (current >= 0 && current < m_records.size()) {
+ m_records.remove(current);
+ m_ui->comboBox->removeItem(current);
+ current = qMax(current - 1, 0);
+ if (m_records.size() == 0)
+ current = -1;
+ OnSelectPresentation(current);
+ }
+}
+
+void CSubPresentationsDlg::OnNewPresentation()
+{
+ int index = m_records.size();
+ m_records.push_back(
+ SubPresentationRecord(QStringLiteral("presentation-qml"),
+ QStringLiteral("presentation-id"), QString()));
+ m_ui->comboBox->addItem(QStringLiteral("presentation-id"));
+ m_ui->comboBox->setCurrentIndex(index);
+ OnSelectPresentation(index);
+}
+
+void CSubPresentationsDlg::OnBrowsePresentation()
+{
+ const QString file = QDir::toNativeSeparators(
+ QFileDialog::getOpenFileName(nullptr, nullptr, m_directory,
+ QStringLiteral("*.qml; *.uip")));
+ QString shortFile = file;
+ int subdir = file.indexOf(m_directory);
+ if (subdir >= 0)
+ shortFile.remove(subdir, m_directory.size() + 1);
+
+ QFileInfo fileInfo(file);
+ if (fileInfo.exists()) {
+ if (fileInfo.suffix() == QStringLiteral("qml"))
+ m_records[current].m_type = QStringLiteral("presentation-qml");
+ else
+ if (fileInfo.suffix() == QStringLiteral("uip"))
+ m_records[current].m_type = QStringLiteral("presentation");
+
+ m_records[current].m_argsOrSrc = shortFile;
+ m_ui->lineEditPreview->setText(shortFile);
+ }
+}
+
+void CSubPresentationsDlg::OnIdChanged(const QString &text)
+{
+ m_records[current].m_id = text;
+ m_ui->comboBox->setItemText(current, text);
+}
+
+void CSubPresentationsDlg::on_buttonBox_accepted()
+{
+ QDialog::accept();
+}
+
+void CSubPresentationsDlg::on_buttonBox_rejected()
+{
+ QDialog::reject();
+}
diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h
new file mode 100644
index 00000000..75828c4e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SUBPRESENTATIONSDLG_H
+#define SUBPRESENTATIONSDLG_H
+
+#include <QtWidgets/qdialog.h>
+
+#include "UICString.h"
+#include "Doc.h"
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class SubPresentationsDlg;
+}
+QT_END_NAMESPACE
+
+class CSubPresentationsDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ CSubPresentationsDlg(const QString &directory,
+ const QVector<SubPresentationRecord> &subpresentations,
+ QWidget* parent = nullptr);
+ ~CSubPresentationsDlg();
+
+ // Implementation
+protected:
+
+ void OnInitDialog();
+
+public:
+
+ QVector<SubPresentationRecord> subpresentations() const;
+
+ void OnDeletePresentation();
+ void OnNewPresentation();
+ void OnBrowsePresentation();
+ void OnSelectPresentation(int selectionIndex);
+ void OnIdChanged(const QString &text);
+
+private Q_SLOTS:
+ void on_buttonBox_accepted();
+ void on_buttonBox_rejected();
+
+private:
+ QString m_directory;
+ QVector<SubPresentationRecord> m_records;
+ Ui::SubPresentationsDlg *m_ui;
+ int current;
+};
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui
new file mode 100644
index 00000000..db673925
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SubPresentationsDlg</class>
+ <widget class="QDialog" name="SubPresentationsDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>512</width>
+ <height>169</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Sub-presentations</string>
+ </property>
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>130</y>
+ <width>491</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="horizontalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>491</width>
+ <height>111</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Sub-presentation</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Presentation Id</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Filename</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QComboBox" name="comboBox"/>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditId">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit the name of the sub-presentation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditPreview">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QPushButton" name="deleteButton">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Delete currently selected sub-presentation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonNew">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add new sub-presentation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonBrowse">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Browse for the sub-presentation source&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/Application/TextLink.cpp b/src/Authoring/Studio/_Win/Application/TextLink.cpp
new file mode 100644
index 00000000..a68aaea8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/TextLink.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+//#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TextLink.h"
+#include "Resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextLink class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CTextLink::CTextLink()
+ : CBaseLink()
+{
+ // Set default colors
+ m_ColorText = CStudioPreferences::GetNormalColor();
+ m_ColorBackground = CStudioPreferences::GetBaseColor();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CTextLink::~CTextLink()
+{
+}
+
+//==============================================================================
+/**
+ * SetColor: Sets the text color and background color
+ *
+ * @param inText Text color for the control.
+ * @param inBackground Background color for the control.
+ */
+//==============================================================================
+void CTextLink::SetColor(COLORREF inText, COLORREF inBackground)
+{
+ m_ColorText = inText;
+ m_ColorBackground = inBackground;
+}
+
+//==============================================================================
+/**
+ * ShowLink: Shows the link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CTextLink::ShowLink()
+{
+ if (IsWindow(m_hWnd)) {
+ ShowTextLink(m_ColorText, m_ColorBackground, DT_VCENTER | DT_SINGLELINE, m_bCapture);
+ }
+}
diff --git a/src/Authoring/Studio/_Win/Application/TextLink.h b/src/Authoring/Studio/_Win/Application/TextLink.h
new file mode 100644
index 00000000..85f5fedf
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/TextLink.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _TEXTLINK_H_
+#define _TEXTLINK_H_
+
+#include "BaseLink.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextLink window
+
+class CTextLink : public CBaseLink
+{
+ // Construction
+public:
+ CTextLink();
+
+ // Attributes
+public:
+ // Operations
+public:
+ virtual void SetColor(COLORREF inText, COLORREF inBackground);
+
+protected:
+ COLORREF m_ColorText;
+ COLORREF m_ColorBackground;
+
+ virtual void ShowLink();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTextLink)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CTextLink();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CTextLink)
+ //}}AFX_MSG
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/WebLink.cpp b/src/Authoring/Studio/_Win/Application/WebLink.cpp
new file mode 100644
index 00000000..258bdffb
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/WebLink.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+//#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "WebLink.h"
+#include "Resource.h"
+#include "BCMenu.h"
+#include "StudioColors.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CWebLink class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CWebLink::CWebLink()
+ : CBaseLink()
+{
+ // Set default link colors
+ m_ColorLink = CStudioPreferences::GetMasterColor(); // green
+ m_ColorHighlight = RGB(0xFF, 0x00, 0x00); // red
+ m_ColorVisited = RGB(0x7F, 0x00, 0x7F); // purple
+ m_ColorBackground = CStudioPreferences::GetDarkBaseColor();
+
+ m_bVisited = FALSE;
+
+ m_URL.Empty();
+
+ m_Bitmap = nullptr;
+
+ m_bPopup = FALSE;
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CWebLink::~CWebLink()
+{
+}
+
+//==============================================================================
+// Message Map
+//==============================================================================
+
+BEGIN_MESSAGE_MAP(CWebLink, CWnd)
+//{{AFX_MSG_MAP(CWebLink)
+ON_WM_PAINT()
+ON_WM_SETCURSOR()
+ON_WM_LBUTTONDOWN()
+ON_WM_MOUSEMOVE()
+ON_WM_CONTEXTMENU()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * SetURL: Sets the URL for the control.
+ *
+ * @param inURL URL to point the default browser to when the control is clicked.
+ */
+//==============================================================================
+void CWebLink::SetURL(CString inURL)
+{
+ m_URL = inURL;
+}
+
+//==============================================================================
+/**
+ * SetImage: Sets an bitmap image for the control.
+ *
+ * @param inResBmp BITMAP resource for the image to load.
+ * @param inAutoSizeFlag TRUE if the control should be resized to the image size.
+ */
+//==============================================================================
+void CWebLink::SetImage(UINT inResBmp, bool inAutoSizeFlag)
+{
+ HBITMAP theBitmap = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inResBmp),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (theBitmap != nullptr) {
+ this->SetImage(theBitmap, inAutoSizeFlag);
+ }
+}
+
+//==============================================================================
+/**
+ * SetImage: Sets an bitmap image for the control.
+ *
+ * @param inBitmap HBITMAP handle of the loaded bitmap.
+ * @param inAutoSizeFlag TRUE if the control should be resized to the image size.
+ */
+//==============================================================================
+void CWebLink::SetImage(HBITMAP inBitmap, bool inAutoSizeFlag)
+{
+ m_Bitmap = inBitmap;
+
+ if (inAutoSizeFlag && m_Bitmap != nullptr) {
+ // Resize this control based on the size of the bitmap.
+ BITMAP theBitmapStruct;
+ int theWidth, theHeight;
+
+ GetObject(m_Bitmap, sizeof(BITMAP), &theBitmapStruct);
+ theWidth = theBitmapStruct.bmWidth;
+ theHeight = theBitmapStruct.bmHeight;
+
+ SetWindowPos(nullptr, 0, 0, theWidth, theHeight, SWP_NOZORDER | SWP_NOMOVE);
+ }
+
+ this->ShowLink();
+}
+
+//==============================================================================
+/**
+ * SetText: Sets the text for the control.
+ *
+ * @param inText Text for the control.
+ */
+//==============================================================================
+void CWebLink::SetText(CString inText)
+{
+ SetWindowText(inText);
+ m_Bitmap = nullptr;
+ this->ShowLink();
+}
+
+COLORREF CWebLink::GetColor()
+{
+ if (m_bCapture) {
+ return m_ColorHighlight;
+ } else {
+ if (m_bVisited)
+ return m_ColorVisited;
+ else
+ return m_ColorLink;
+ }
+}
+
+//==============================================================================
+/**
+ * ShowLink: Shows the link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::ShowLink()
+{
+ if (IsWindow(m_hWnd)) {
+ // Is the link represented by an image?
+ if (m_Bitmap != nullptr) {
+ ShowBitmapLink();
+ } else {
+ ShowTextLink(GetColor(), m_ColorBackground, DT_WORDBREAK | SS_LEFT, true);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * ShowLink: Shows the bitmap link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::ShowBitmapLink()
+{
+ if (IsWindow(m_hWnd)) {
+ CRect theRect;
+ CDC *theDC;
+ CDC theMemDC;
+
+ BITMAP theBitmapStruct;
+ long theWidth, theHeight;
+ CBrush theBrush;
+
+ theDC = GetDC();
+ theMemDC.CreateCompatibleDC(theDC);
+ CBitmap *theBitmap = CBitmap::FromHandle(m_Bitmap);
+
+ CBitmap *theOldBmp = (CBitmap *)theMemDC.SelectObject(theBitmap);
+
+ GetObject(m_Bitmap, sizeof(BITMAP), &theBitmapStruct);
+ theWidth = theBitmapStruct.bmWidth;
+ theHeight = theBitmapStruct.bmHeight;
+
+ theDC->BitBlt(0, 0, theWidth, theHeight, &theMemDC, 0, 0, SRCCOPY);
+
+ COLORREF theColor = GetColor();
+ if (theColor == m_ColorHighlight || theColor == m_ColorVisited) {
+ // Draw a highlight frame
+ GetClientRect(&theRect);
+
+ theBrush.CreateSolidBrush(theColor);
+ theDC->FrameRect(&theRect, &theBrush);
+ theBrush.DeleteObject();
+ }
+
+ theMemDC.SelectObject(theOldBmp);
+
+ theMemDC.DeleteDC();
+ ReleaseDC(theDC);
+ }
+}
+
+//==============================================================================
+/**
+ * JumpLink: Jumps to the link URL.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::JumpLink()
+{
+ CString theWebLink;
+
+ GetWindowText(theWebLink);
+
+ if (!m_URL.IsEmpty())
+ theWebLink = m_URL;
+
+ if (!theWebLink.IsEmpty()) {
+ this->OpenURL(theWebLink);
+ }
+}
+
+//==============================================================================
+/**
+ * OpenURL: Opens the specified URL with the default browser.
+ *
+ * @param inURL URL to open with the browser.
+ */
+//==============================================================================
+void CWebLink::OpenURL(CString inURL)
+{
+ HCURSOR thePrevCursor;
+
+ thePrevCursor = SetCursor(LoadCursor(nullptr, IDC_APPSTARTING));
+ ShellExecute(GetSafeHwnd(), L"open", inURL, nullptr, nullptr, SW_SHOWNORMAL);
+ SetCursor(thePrevCursor);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CWebLink message handlers
+
+//==============================================================================
+/**
+ * OnSetCursor
+ *
+ * Handle the WM_SETCURSOR message.
+ *
+ * @param inWnd Pointer to the parent CWnd object.
+ * @param inHitTest Specifies the hit-test area code. The hit test determines the
+ *cursor�s location.
+ * @param inMessage Specifies the mouse message number.
+ */
+//==============================================================================
+BOOL CWebLink::OnSetCursor(CWnd *inWnd, UINT inHitTest, UINT inMessage)
+{
+ UNREFERENCED_PARAMETER(inWnd);
+ UNREFERENCED_PARAMETER(inHitTest);
+ UNREFERENCED_PARAMETER(inMessage);
+
+ if (m_bPopup) {
+ SetCursor(LoadCursor(nullptr, IDC_ARROW));
+ } else {
+ SetCursor(LoadCursor(nullptr, IDC_HAND));
+ }
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * OnLButtonDown
+ *
+ * Windows callback handler for the WM_LBUTTONDOWN message
+ *
+ * @param inFlags Flags for the left button down message
+ * @param inPoint Point where the mouse was left clicked (client coordinates)
+ */
+//==============================================================================
+void CWebLink::OnLButtonDown(UINT inFlags, CPoint inPoint)
+{
+ UNREFERENCED_PARAMETER(inFlags);
+ UNREFERENCED_PARAMETER(inPoint);
+
+ if (IsWindowEnabled()) {
+ m_bCapture = FALSE;
+ ReleaseCapture();
+
+ m_bVisited = TRUE;
+ this->ShowLink();
+
+ this->JumpLink();
+ }
+}
+
+//==============================================================================
+/**
+ * OnContextMenu: Handle for the WM_CONTEXTMENU message.
+ *
+ * @param inWnd Window for the context menu.
+ * @param inPoint Mouse position when the right button was clicked.
+ */
+//==============================================================================
+void CWebLink::OnContextMenu(CWnd *inWnd, CPoint inPoint)
+{
+ UNREFERENCED_PARAMETER(inWnd);
+
+ BCMenu theContextMenu;
+ BCMenu *thePopupMenu = nullptr;
+ long theMenuCmd;
+
+ ReleaseCapture();
+
+ // Load the context menu
+ theContextMenu.LoadMenu(IDR_WEBLINK_CONTEXT_MENU);
+#ifdef _USECONTENTMENUIMAGES_
+ theContextMenu.SetBitmapBackground(MENU_IMAGELIST_BACKCOLOR);
+ theContextMenu.LoadToolbar(IDR_WEBLINKCONTEXTTOOLBAR);
+#endif
+
+ thePopupMenu = (BCMenu *)theContextMenu.GetSubMenu(0);
+
+ // Set the default menu item to "Open"
+ SetMenuDefaultItem(thePopupMenu->m_hMenu, IDM_OPENLINK, FALSE);
+
+ m_bPopup = TRUE;
+
+ // Show the context menu
+ theMenuCmd = (long)thePopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
+ inPoint.x, inPoint.y, this);
+
+ m_bPopup = FALSE;
+
+ m_bCapture = FALSE;
+
+ theContextMenu.DestroyMenu();
+
+ this->ShowLink();
+
+ // Handle the popup menu command
+
+ switch (theMenuCmd) {
+ case IDM_OPENLINK:
+ this->JumpLink();
+ break;
+
+ case IDM_COPYSHORTCUT2:
+ this->CopyShortcut();
+ break;
+
+ default:
+ break;
+ }
+
+ theContextMenu.DestroyMenu();
+}
+
+//==============================================================================
+/**
+ * CopyShortcut: Copy the link URL text to the clipboard.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::CopyShortcut()
+{
+ // Open the clipboard so we can copy data to it.
+ if (OpenClipboard()) {
+ DWORD theBufferSize;
+ HGLOBAL theGlobalBuffer;
+ LPSTR theClipboardText;
+
+ // Determine the buffer size, based on the length of the URL
+ theBufferSize = m_URL.GetLength();
+
+ // Clear the contents of the clipboard
+ ::EmptyClipboard();
+
+ // Allocate a global buffer and copy the text to it
+ theGlobalBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, theBufferSize + 1);
+ theClipboardText = (LPSTR)GlobalLock(theGlobalBuffer);
+
+ CopyMemory(theClipboardText, m_URL, theBufferSize + 1);
+
+ // Unlock the buffer
+ GlobalUnlock(theGlobalBuffer);
+
+ // Pass the data to the clipboard
+ SetClipboardData(CF_TEXT, theGlobalBuffer);
+
+ // Close the clipboard, but do not GlobalFree() the global buffer
+ CloseClipboard();
+ }
+}
diff --git a/src/Authoring/Studio/_Win/Application/WebLink.h b/src/Authoring/Studio/_Win/Application/WebLink.h
new file mode 100644
index 00000000..4ca3dede
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/WebLink.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _WEBLINK_H_
+#define _WEBLINK_H_
+
+#include "BaseLink.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CWebLink window
+
+class CWebLink : public CBaseLink
+{
+ // Construction
+public:
+ CWebLink();
+
+ // Attributes
+public:
+ // Operations
+public:
+ virtual void SetImage(UINT uiResBmp, bool bAutoSize = true);
+ virtual void SetImage(HBITMAP hBmp, bool bAutoSize = true);
+ virtual void SetText(CString inText);
+ virtual void SetURL(CString inURL);
+
+protected:
+ COLORREF m_ColorLink;
+ COLORREF m_ColorHighlight;
+ COLORREF m_ColorVisited;
+ COLORREF m_ColorBackground;
+
+ bool m_bVisited;
+ bool m_bPopup;
+
+ HBITMAP m_Bitmap;
+
+ CString m_URL;
+
+ virtual COLORREF GetColor();
+
+ virtual void CopyShortcut();
+
+ virtual void JumpLink();
+
+ virtual void OpenURL(CString inURL);
+
+ virtual void ShowLink();
+
+ virtual void ShowBitmapLink();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CWebLink)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CWebLink();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CWebLink)
+ virtual afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message);
+ virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ virtual afx_msg void OnContextMenu(CWnd *pWnd, CPoint pos);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Controls/AppFonts.cpp b/src/Authoring/Studio/_Win/Controls/AppFonts.cpp
new file mode 100644
index 00000000..54039331
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/AppFonts.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "AppFonts.h"
+#include "StudioPreferences.h"
+#include "StringLoader.h"
+
+//=============================================================================
+/**
+ * Constructor for a CAppFonts object.
+ */
+//=============================================================================
+CAppFonts::CAppFonts()
+{
+ // Normal font
+ const QString theFontFace = CStudioPreferences::GetFontFaceName();
+ Q3DStudio::CString theFontSize = ::LoadResourceString(IDS_STUDIOFONT_SIZE);
+
+ m_NormalFont.setFamily(theFontFace);
+ m_NormalFont.setPointSize(13); // atoi( theFontSize.GetCharStar( ) );
+}
+
+//==============================================================================
+/**
+ * Releases the object.
+ */
+//==============================================================================
+CAppFonts::~CAppFonts()
+{
+}
+
+//==============================================================================
+/**
+ * Returns a pointer to the only instance of this class. Automatically cleaned
+ * up when the program exits.
+ */
+//==============================================================================
+CAppFonts *CAppFonts::GetInstance()
+{
+ static CAppFonts theAppFonts;
+ return &theAppFonts;
+}
+
+//==============================================================================
+/**
+ * Returns the normal font for use on GUI elements for the application.
+ */
+//==============================================================================
+QFont CAppFonts::GetNormalFont()
+{
+ return m_NormalFont;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/AppFonts.h b/src/Authoring/Studio/_Win/Controls/AppFonts.h
new file mode 100644
index 00000000..e2036c0e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/AppFonts.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#ifndef INCLUDED_APP_FONTS_H
+#define INCLUDED_APP_FONTS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QFont>
+//==============================================================================
+/**
+ * Dispatches commands
+ */
+//==============================================================================
+class CAppFonts
+{
+public:
+ CAppFonts();
+ virtual ~CAppFonts();
+ static CAppFonts *GetInstance();
+ QFont GetNormalFont();
+
+private:
+ QFont m_NormalFont;
+};
+
+#endif // INCLUDED_APP_FONTS_H
diff --git a/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp
new file mode 100644
index 00000000..34076704
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "BufferedRenderer.h"
+#include "AppFonts.h"
+
+
+//=============================================================================
+/**
+ * Create a buffered renderer.
+ * @param inSize the size of this renderer.
+ */
+CBufferedRenderer::CBufferedRenderer(const QSize &inSize)
+ : CWinRenderer()
+{
+ m_CurrentBitmap = QPixmap(inSize);
+
+ // KDAB_TODO: I don't see why m_OldBitmap is needed, nor what is the difference between CBufferedRenderer and COffscreenRenderer
+ m_OldBitmap = m_CurrentBitmap;
+
+ m_painter = new QPainter(&m_CurrentBitmap);
+ QFont font = CAppFonts::GetInstance()->GetNormalFont();
+ m_painter->setFont(font);
+
+ m_Size = inSize;
+
+ PushClippingRect(QRect(QPoint(0,0), inSize));
+}
+
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CBufferedRenderer::~CBufferedRenderer()
+{
+ delete m_painter;
+ m_painter = nullptr;
+}
+
+//=============================================================================
+/**
+ * Copy this BufferedRenderer to inRenderer using alpha blend.
+ * This will semi-transparently copy the contents of this buffer to inRenderer
+ * using the alpha.
+ * @param inRenderer the destination renderer.
+ * @param inAlpha the opacity, 255 = opaque 0 = transparent.
+ */
+/*void CBufferedRenderer::TransparentBltTo( CRenderer* inRenderer, short inAlpha )
+{
+
+ CPt theDestination;
+ theDestination.Offset( inRenderer->GetTranslation( ) );
+
+ AlphaBlendExt( inRenderer->GetGraphicsDevice( )->m_hDC, (short)theDestination.x,
+(short)theDestination.y, (short)m_Size.x, (short)m_Size.y, m_DC->m_hDC, 0, 0, (short)m_Size.x,
+(short)m_Size.y, inAlpha );
+// ::DrawAlphaBlendBitmap( inRenderer->GetDC( ), (short)theDestination.x,
+(short)theDestination.y, m_CurrentBitmap, (short)m_Size.x, (short)m_Size.y, 0, 0, inAlpha );
+
+}*/
+
+//==============================================================================
+/**
+ * Draws a bitmap using alpha blending. Works in NT/2000/9x
+ *
+ * @param inDCDest Destination device context
+ * @param inX X coordinate for drawing
+ * @param inY Y coordinate for drawing
+ * @param inWidth Drawing width
+ * @param inHeight Drawing height
+ * @param inDCSrc Source device context
+ * @param inSourceX X source coordinate
+ * @param inSourceY Y source coordinate
+ * @param inSourceWidth Source drawing width
+ * @param inSourceHeight Source drawing height
+ * @param inAlpha Alpha blend: 0-255, where 255 is opaque
+ */
+//==============================================================================
+/*bool CBufferedRenderer::AlphaBlendExt( HDC inDCDest, short inX, short inY, short inWidth, short
+inHeight, HDC inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, short inSourceHeight,
+short inAlpha )
+{
+ BITMAPINFOHEADER theBMI;
+
+ theBMI.biSize = sizeof( BITMAPINFOHEADER );
+ theBMI.biWidth = inWidth;
+ theBMI.biHeight = inHeight;
+ theBMI.biPlanes = 1;
+ theBMI.biBitCount = 32; // 24 bits + alpha channel
+ theBMI.biCompression = BI_RGB; // no compression
+ theBMI.biSizeImage = 0;
+ theBMI.biXPelsPerMeter = 0;
+ theBMI.biYPelsPerMeter = 0;
+ theBMI.biClrUsed = 0; // use the whole palette
+ theBMI.biClrImportant = 0;
+
+ BYTE* theSrcBits;
+ HBITMAP theBmpSrc;
+
+ // Create DIB section in shared memory
+ theBmpSrc = CreateDIBSection( inDCSrc, ( BITMAPINFO* ) &theBMI, DIB_RGB_COLORS, ( void** )
+&theSrcBits, 0, 0L );
+
+ BYTE* theDestBits;
+ HBITMAP theBmpDest;
+
+ // Create DIB section in shared memory
+ theBmpDest = CreateDIBSection( inDCDest, ( BITMAPINFO* ) &theBMI, DIB_RGB_COLORS, ( void** )
+&theDestBits, 0, 0L );
+
+ // Copy our source and destination bitmaps onto our DIBSections.
+ // so we can get access to their bits using the BYTE*'s we used
+ // in the CreateDIBSection()s above.
+
+ HDC theDC = CreateCompatibleDC( nullptr );
+
+ HBITMAP theDCOld = ( HBITMAP ) SelectObject( theDC, theBmpSrc );
+
+ if ( !StretchBlt( theDC, 0, 0, inWidth, inHeight, inDCSrc, inSourceX, inSourceY,
+inSourceWidth, inSourceHeight, SRCCOPY ) )
+ {
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+ return false;
+ }
+
+ SelectObject( theDC, theBmpDest );
+
+ if (! StretchBlt( theDC, 0, 0, inWidth, inHeight, inDCDest, inX, inY, inWidth, inHeight,
+SRCCOPY ) )
+ {
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+ return true;
+ }
+
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+
+ short theXLoop, theYLoop;
+
+ for( theYLoop=0; theYLoop<inHeight; ++theYLoop )
+ {
+ LPBYTE theDestRGB = ( LPBYTE ) &( ( DWORD* ) theDestBits)[theYLoop * inWidth];
+ LPBYTE theSrcRGB = ( LPBYTE ) &( ( DWORD* ) theSrcBits)[theYLoop * inWidth];
+
+ for( theXLoop=0; theXLoop<inWidth; theXLoop++ )
+ {
+ theSrcRGB[0] = ( BYTE ) ( ( theDestRGB[0] * ( 255 - inAlpha ) + theSrcRGB[0]
+* inAlpha ) >> 8 );
+ theSrcRGB[1] = ( BYTE ) ( ( theDestRGB[1] * ( 255 - inAlpha ) + theSrcRGB[1]
+* inAlpha ) >> 8 );
+ theSrcRGB[2] = ( BYTE ) ( ( theDestRGB[2] * ( 255 - inAlpha ) + theSrcRGB[2]
+* inAlpha ) >> 8 );
+
+ theSrcRGB += 4;
+ theDestRGB += 4;
+ }
+ }
+
+ theDC = CreateCompatibleDC( nullptr );
+
+ theDCOld = ( HBITMAP ) SelectObject( theDC, theBmpSrc );
+
+ if ( !BitBlt( inDCDest, inX, inY, inWidth, inHeight, theDC, 0, 0, SRCCOPY ) )
+ {
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+ return false;
+ }
+
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+
+ return true;
+}*/
diff --git a/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h
new file mode 100644
index 00000000..19cc8f78
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BUFFERED_RENDERER_H
+#define INCLUDED_BUFFERED_RENDERER_H 1
+
+#pragma once
+
+#include "WinRenderer.h"
+
+#include <QPainter>
+#include <QPixmap>
+#include <QFont>
+
+class CBufferedRenderer : public CWinRenderer
+{
+public:
+ CBufferedRenderer(const QSize &inSize);
+
+ virtual ~CBufferedRenderer();
+ QPixmap pixmap() const override { return m_CurrentBitmap;}
+
+ // void TransparentBltTo( CRenderer* inRenderer, short inAlpha );
+
+protected:
+ QPixmap m_OldBitmap;
+ QPixmap m_CurrentBitmap;
+ QSize m_Size;
+
+ // bool AlphaBlendExt( HDC inDCDest, short inX, short inY, short inWidth, short inHeight, HDC
+ //inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, short inSourceHeight, short
+ //inAlpha );
+};
+#endif // INCLUDED_BUFFERED_RENDERER_H
diff --git a/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp b/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp
new file mode 100644
index 00000000..19b263d9
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MFCEditControl.h"
+
+//==============================================================================
+// Implementation
+//==============================================================================
+
+#ifdef USE_RICHEDIT
+IMPLEMENT_DYNAMIC(CMFCEditControl, CRichEditCtrl)
+#else
+IMPLEMENT_DYNAMIC(CMFCEditControl, CEdit)
+#endif
+
+CMFCEditControl::CMFCEditControl()
+ : m_Changed(false)
+ , m_HotKeys(nullptr)
+{
+}
+
+CMFCEditControl::~CMFCEditControl()
+{
+ // This control's window has been destroyed by PlatformEditControl,
+ // so a SigTextCommit is potentially dangerous as it will lead to GetText (below)
+ // which will try to get text from a destroyed window.
+ // However, if this is needed, note that CEdit works, but CRichEditCtrl don't.
+ // Can revert to using CEdit by commenting out the line in MFCEditControl.h
+
+ // if ( m_Changed )
+ //{
+ // m_Changed = false;
+ // SigTextCommit( );
+ //}
+}
+
+Q3DStudio::CString CMFCEditControl::GetText()
+{
+ Q3DStudio::CString theResult;
+
+#ifdef USE_RICHEDIT
+ GETTEXTLENGTHEX getTextLengthEx;
+ getTextLengthEx.flags = GTL_DEFAULT | GTL_USECRLF;
+ getTextLengthEx.codepage = 1200;
+ LRESULT lResult = SendMessage(EM_GETTEXTLENGTHEX, (WPARAM)&getTextLengthEx, 0);
+ if (lResult > 0) {
+ GETTEXTEX getTextEx;
+ getTextEx.cb = (DWORD)(lResult + 2);
+ getTextEx.codepage = 1200;
+ getTextEx.flags = GT_DEFAULT | GT_USECRLF;
+ getTextEx.lpDefaultChar = nullptr;
+ getTextEx.lpUsedDefChar = nullptr;
+ wchar_t *ws = new wchar_t[lResult / 2 + 1];
+ SendMessage(EM_GETTEXTEX, (WPARAM)&getTextEx, (LPARAM)ws);
+ theResult = ws;
+ delete[] ws;
+ }
+#else
+ ::CString theWindowText;
+ GetWindowText(theWindowText);
+ // normal gettext, which depends on machine's locale
+ theResult = theWindowText;
+#endif
+
+ return theResult;
+}
+
+void CMFCEditControl::SetText(const Q3DStudio::CString &inText)
+{
+ // The text manipulation is actually already being handled by the CEdit/CWnd
+ // This SetText is called by our custom CPropertyMultilineEdit and screws with the MFC's
+ // own text handling functions.
+ // Essentially, we still need this to set up the initial use of the MFC Edit.
+ if (GetText() == "") {
+#ifdef USE_RICHEDIT
+ SETTEXTEX setTextEx;
+ setTextEx.codepage = 1200;
+ setTextEx.flags = ST_DEFAULT;
+ SendMessage(EM_SETTEXTEX, (WPARAM)&setTextEx,
+ (LPARAM)(static_cast<const wchar_t *>(inText)));
+#else
+ // normal settext, which depends on machine's locale
+ SetWindowText(inText.GetMulti());
+#endif
+ }
+}
+
+#ifdef USE_RICHEDIT
+BEGIN_MESSAGE_MAP(CMFCEditControl, CRichEditCtrl)
+#else
+BEGIN_MESSAGE_MAP(CMFCEditControl, CEdit)
+#endif
+ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange)
+ON_WM_LBUTTONDBLCLK()
+ON_WM_SETFOCUS()
+ON_WM_KILLFOCUS()
+END_MESSAGE_MAP()
+
+// CMFCEditControl message handlers
+
+void CMFCEditControl::OnEnChange()
+{
+ m_Changed = true;
+ SigTextChanged();
+}
+
+void CMFCEditControl::OnLButtonDblClk(UINT inSomething, CPoint inPoint)
+{
+#ifdef USE_RICHEDIT
+ CRichEditCtrl::OnLButtonDblClk(inSomething, inPoint);
+#else
+ CEdit::OnLButtonDblClk(inSomething, inPoint);
+#endif
+
+ // select all text in this CEdit/CRichEditCtrl
+ SetSel(0, -1);
+}
+
+void CMFCEditControl::OnSetFocus(CWnd *inWnd)
+{
+#ifdef USE_RICHEDIT
+ CRichEditCtrl::OnSetFocus(inWnd);
+#else
+ CEdit::OnSetFocus(inWnd);
+#endif
+
+ m_Changed = false;
+}
+
+void CMFCEditControl::OnKillFocus(CWnd *inWnd)
+{
+#ifdef USE_RICHEDIT
+ CRichEditCtrl::OnKillFocus(inWnd);
+#else
+ CEdit::OnKillFocus(inWnd);
+#endif
+
+ if (m_Changed) {
+ m_Changed = false;
+ SigTextCommit();
+ }
+}
+
+BOOL CMFCEditControl::PreTranslateMessage(MSG *pMsg)
+{
+ if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) {
+ // Reserve some keys for Studio's hotkeys
+ // This is only a subset of Studio's hotkeys as listed in
+ // CWorkspace::RegisterGlobalKeyboardShortcuts( CHotKeys* inShortcutHandler )
+ // We need to make sure that EditControl's hotkeys won't collide with Studio's hotkeys
+ bool theReservedHotKeys = false;
+ if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN
+ || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP) {
+ if (pMsg->wParam >= CHotKeys::KEY_F1
+ && pMsg->wParam
+ <= CHotKeys::KEY_F12) // F1 to F12 keys, this may fail if not in windows
+ {
+ theReservedHotKeys = true;
+ } else if (CHotKeys::IsKeyDown(VK_CONTROL)) {
+ unsigned int theCharacterCode = ::MapVirtualKey(static_cast<UINT>(pMsg->wParam), 2);
+
+ switch (theCharacterCode) {
+ case 's':
+ case 'S': // save file / save file as
+ case 'o':
+ case 'O': // open file
+ case 'n':
+ case 'N': // new file
+ theReservedHotKeys = true;
+ }
+ }
+ }
+
+ if (theReservedHotKeys) {
+ if (m_HotKeys != nullptr)
+ m_HotKeys->PreTranslateMessage(pMsg);
+ } else {
+ // no idea what all that filtering does, since Bug 1695 appears to be working
+ // and it is causing problem with Japanese text input (2639)
+ ::TranslateMessage(pMsg);
+ ::DispatchMessage(pMsg);
+ }
+ return TRUE;
+
+ //// This is REALLY bad, but it's basically filtering all the messages that it thinks it
+ ///might want and handles those.
+ // if ((::GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0 && (::GetAsyncKeyState(VK_RBUTTON) &
+ // 0x8000) == 0)
+ //{
+ // unsigned int theChar = pMsg->wParam;
+
+ // /*
+ // * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
+ // * 0x40 : unassigned
+ // * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
+ // */
+
+ // /*
+ // #define VK_OEM_1 0xBA // ';:' for US
+ // #define VK_OEM_PLUS 0xBB // '+' any country
+ // #define VK_OEM_COMMA 0xBC // ',' any country
+ // #define VK_OEM_MINUS 0xBD // '-' any country
+ // #define VK_OEM_PERIOD 0xBE // '.' any country
+ // #define VK_OEM_2 0xBF // '/?' for US
+ // #define VK_OEM_3 0xC0 // '`~' for US
+ // #define VK_OEM_4 0xDB // '[{' for US
+ // #define VK_OEM_5 0xDC // '\|' for US
+ // #define VK_OEM_6 0xDD // ']}' for US
+ // #define VK_OEM_7 0xDE // ''"' for US
+ // #define VK_OEM_8 0xDF
+ // */
+
+ // if ( theChar == VK_RETURN || theChar == VK_BACK || theChar == VK_MENU ||
+ // ( theChar >= VK_SPACE && theChar < VK_LWIN ) ||
+ // ( theChar >= VK_OEM_1 && theChar <= VK_OEM_8 )
+ // )
+ // {
+ // ::TranslateMessage( pMsg );
+ // ::DispatchMessage( pMsg );
+ // return TRUE;
+ // }
+ //}
+ }
+
+#ifdef USE_RICHEDIT
+ return CRichEditCtrl::PreTranslateMessage(pMsg);
+#else
+ return CEdit::PreTranslateMessage(pMsg);
+#endif
+}
+
+BOOL CMFCEditControl::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID)
+{
+// TODO: Add your specialized code here and/or call the base class
+
+#ifdef USE_RICHEDIT
+ BOOL theResult = CRichEditCtrl::Create(dwStyle, rect, pParentWnd, nID);
+ SetEventMask(GetEventMask() | ENM_CHANGE);
+#else
+ BOOL theResult = CEdit::Create(dwStyle, rect, pParentWnd, nID);
+#endif
+
+ return theResult;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/MFCEditControl.h b/src/Authoring/Studio/_Win/Controls/MFCEditControl.h
new file mode 100644
index 00000000..9d688fdc
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/MFCEditControl.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "HotKeys.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+// RichEditCtrl, though super useful, has some stability issue to be ironed out.
+// Use CEdit by commenting out the line below if it is causing crashes.
+#define USE_RICHEDIT
+
+#ifdef USE_RICHEDIT
+class CMFCEditControl : public CRichEditCtrl
+#else
+class CMFCEditControl : public CEdit
+#endif
+{
+protected:
+ DECLARE_DYNAMIC(CMFCEditControl)
+
+public:
+ boost::signal<void()> SigTextChanged;
+ boost::signal<void()> SigTextCommit;
+
+protected:
+ bool m_Changed;
+ CHotKeys *m_HotKeys; // global keyboard shortcut (Studio's hotkeys)
+
+public:
+ CMFCEditControl();
+ virtual ~CMFCEditControl();
+
+ Q3DStudio::CString GetText();
+ void SetText(const Q3DStudio::CString &inText);
+
+ void SetGlobalKeyboardShortcuts(CHotKeys *inHotKeys) { m_HotKeys = inHotKeys; }
+
+protected:
+ DECLARE_MESSAGE_MAP()
+public:
+ afx_msg void OnEnChange();
+ afx_msg void OnLButtonDblClk(UINT, CPoint);
+ afx_msg void OnSetFocus(CWnd *);
+ afx_msg void OnKillFocus(CWnd *);
+
+ virtual BOOL PreTranslateMessage(MSG *inMessage);
+ virtual BOOL Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID);
+};
diff --git a/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp
new file mode 100644
index 00000000..72a5f17b
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "OffscreenRenderer.h"
+#include "AppFonts.h"
+
+//=============================================================================
+/**
+ * Constructor: Overrides a protected constructor on the base class. Sets up
+ * all the requirements so that this renderer is valid.
+ */
+COffscreenRenderer::COffscreenRenderer(const QRect &inClippingRect)
+ : CWinRenderer()
+{
+ m_pixmap = QPixmap(inClippingRect.size());
+ m_painter = new QPainter(&m_pixmap);
+ QFont font = CAppFonts::GetInstance()->GetNormalFont();
+ m_painter->setFont(font);
+
+ // Set up the specified clipping region. Renderer is now valid for use.
+ PushClippingRect(inClippingRect);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+COffscreenRenderer::~COffscreenRenderer()
+{
+ delete m_painter;
+ m_painter = nullptr;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h
new file mode 100644
index 00000000..dccd259f
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_OFFSCREEN_RENDERER_H
+#define INCLUDED_OFFSCREEN_RENDERER_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "WinRenderer.h"
+
+//=============================================================================
+/**
+ * Class for creating a renderer compatible with the current display, but that
+ * does not actually draw to the display. Provided so that you controls can
+ * query text size outside of their draw functions. This class could be
+ * further extended to provide offscreen drawing and blitting, though it's
+ * not currently set up to do so.
+ */
+class COffscreenRenderer : public CWinRenderer
+{
+public:
+ COffscreenRenderer(const QRect &inClippingRect);
+ virtual ~COffscreenRenderer();
+
+ QPixmap pixmap() const override { return m_pixmap;}
+
+protected:
+ QPixmap m_pixmap;
+};
+
+#endif // INCLUDED_OFFSCREEN_RENDERER_H
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp
new file mode 100644
index 00000000..4c581806
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PlatformEditControl.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+
+#ifdef WIN32
+
+CPlatformEditControl::CPlatformEditControl(UICRenderDevice inParent)
+ : CPlatformWindowControl(inParent)
+{
+#ifdef USE_RICHEDIT
+ BOOL theReturn = m_EditWindow.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE
+ | ES_WANTRETURN | ES_AUTOVSCROLL,
+ CRect(0, 0, 0, 0), CWnd::FromHandle(inParent), 1);
+#else
+ BOOL theReturn = m_EditWindow.CreateEx(0, _T("EDIT"), "", WS_CHILD | WS_VSCROLL | ES_MULTILINE
+ | ES_WANTRETURN | ES_AUTOVSCROLL,
+ 0, 0, 0, 0, inParent, nullptr);
+#endif
+ ASSERT(theReturn);
+
+ Q_UNUSED(theReturn); // for release builds
+
+ m_EditWindow.SigTextChanged.connect(std::bind(&CPlatformEditControl::OnTextChanged, this));
+ m_EditWindow.SigTextCommit.connect(std::bind(&CPlatformEditControl::OnTextCommit, this));
+
+ m_Font.CreatePointFont(
+ 80, CString(CStudioPreferences::GetFontFaceName())); // size specified in 1/10ths of a point
+ m_EditWindow.SetFont(&m_Font);
+ m_EditWindow.SetTextMode(TM_PLAINTEXT | TM_MULTILEVELUNDO);
+ m_EditWindow.SetBackgroundColor(FALSE, CStudioPreferences::GetLightBaseColor());
+
+ m_Window = m_EditWindow.GetSafeHwnd();
+}
+
+CPlatformEditControl::~CPlatformEditControl()
+{
+ m_EditWindow.DestroyWindow();
+}
+
+//=============================================================================
+/**
+ * Essentially, this just turns the window off. Do not use the CControl::SetVisible
+ * because that would screw with the control's size and you will notice the inspector
+ * palette having cut off rows.
+ *
+ * @param inIsVisible If the window should be visible
+ */
+void CPlatformEditControl::SetWindowVisible(bool inIsVisible)
+{
+ if (inIsVisible)
+ m_EditWindow.ShowWindow(SW_SHOWNORMAL);
+ else
+ m_EditWindow.ShowWindow(SW_HIDE);
+}
+
+void CPlatformEditControl::OnTextChanged()
+{
+ SigTextChanged();
+}
+
+void CPlatformEditControl::OnTextCommit()
+{
+ SigTextCommit();
+}
+
+void CPlatformEditControl::SetText(const Q3DStudio::CString &inText)
+{
+ m_EditWindow.SetText(inText);
+}
+
+Q3DStudio::CString CPlatformEditControl::GetText()
+{
+ return m_EditWindow.GetText();
+}
+
+void CPlatformEditControl::EnableWindow(bool inEnable)
+{
+ m_EditWindow.EnableWindow(inEnable);
+}
+
+//==============================================================================
+// CControl
+//==============================================================================
+
+void CPlatformEditControl::Draw(CRenderer *inRenderer)
+{
+ // Create a clipping region for the MFC Edit
+ CRct theUICClipRect = inRenderer->GetClippingRect();
+ RECT theRect(theUICClipRect);
+ CRgn theClipRgn;
+ theClipRgn.CreateRectRgnIndirect(&theRect);
+ HRGN theClipHandle = (HRGN)theClipRgn;
+ m_EditWindow.SetWindowRgn(theClipHandle, TRUE);
+
+ if (m_EditWindow.IsWindowVisible() == FALSE)
+ m_EditWindow.ShowWindow(SW_SHOWNORMAL);
+
+ // Draw a bounding box around the entire control
+ CColor theTopColor = CStudioPreferences::GetControlRectTopLineColor();
+ CColor theSideColor = CStudioPreferences::GetControlRectSideLineColor();
+ CColor theBottomColor = CStudioPreferences::GetControlRectBottomLineColor();
+
+ inRenderer->DrawRectOutline(GetSize(), theTopColor, theSideColor, theBottomColor, theSideColor);
+}
+
+#endif // WIN32
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h
new file mode 100644
index 00000000..1347b217
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PLATFORM_EDIT_CONTROL_H
+#define INCLUDED_PLATFORM_EDIT_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "PlatformWindowControl.h"
+#include "MFCEditControl.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+#ifdef WIN32
+
+class CPlatformEditControl : public CPlatformWindowControl
+{
+protected:
+ CFont m_Font; ///< MFC font for the edit text
+ CMFCEditControl m_EditWindow; ///< MFC Edit Window
+
+public:
+ std::signal0<void> SigTextChanged;
+ std::signal0<void> SigTextCommit;
+
+public:
+ CPlatformEditControl(UICRenderDevice inParent);
+ virtual ~CPlatformEditControl();
+
+ void SetWindowVisible(bool inIsVisible);
+
+ void SetText(const Q3DStudio::CString &inText);
+ Q3DStudio::CString GetText();
+ void EnableWindow(bool inEnable);
+
+ void SetGlobalKeyboardShortcuts(CHotKeys *inHotKeys)
+ {
+ m_EditWindow.SetGlobalKeyboardShortcuts(inHotKeys);
+ }
+
+ // CControl
+ virtual void Draw(CRenderer *inRenderer);
+
+protected:
+ void OnTextChanged();
+ void OnTextCommit();
+};
+
+#endif // WIN32
+
+#endif // INCLUDED_PLATFORM_EDIT_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp
new file mode 100644
index 00000000..fc2c2509
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PlatformStaticControl.h"
+
+#ifdef WIN32
+
+CPlatformStaticControl::CPlatformStaticControl(UICRenderDevice inParent)
+ : CPlatformWindowControl(inParent)
+{
+ BOOL theReturn = m_EditWindow.CreateEx(0, _T("STATIC"), _T(""), WS_VISIBLE | WS_CHILD, 0, 0, 0,
+ 0, inParent, nullptr);
+ ASSERT(theReturn);
+ theReturn;
+
+ m_Font.CreatePointFont(
+ 80, CString(CStudioPreferences::GetFontFaceName())); // size specified in 1/10ths of a point
+ m_EditWindow.SetFont(&m_Font);
+
+ m_Window = m_EditWindow.GetSafeHwnd();
+}
+
+CPlatformStaticControl::~CPlatformStaticControl()
+{
+ m_EditWindow.DestroyWindow();
+}
+
+void CPlatformStaticControl::SetText(const Q3DStudio::CString &inText)
+{
+ m_EditWindow.SetWindowText(inText);
+}
+
+#endif // WIN32 \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h
new file mode 100644
index 00000000..e8b68fa6
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_PLATFORM_STATIC_CONTROL_H
+#define INCLUDED_PLATFORM_STATIC_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+
+#include "PlatformWindowControl.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+class CPlatformStaticControl : public CPlatformWindowControl
+{
+protected:
+ CFont m_Font; ///< MFC font for the static text
+ CStatic m_EditWindow; ///< MFC Edit Window
+
+public:
+ CPlatformStaticControl(UICRenderDevice inParent);
+ virtual ~CPlatformStaticControl();
+
+ void SetText(const Q3DStudio::CString &inText);
+};
+
+#endif // WIN32
+
+#endif // INCLUDED_PLATFORM_STATIC_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp
new file mode 100644
index 00000000..89279702
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "PlatformWindowControl.h"
+
+CPlatformWindowControl::CPlatformWindowControl(UICRenderDevice inParent)
+ : m_Window(nullptr)
+{
+ inParent;
+}
+
+CPlatformWindowControl::~CPlatformWindowControl()
+{
+}
+
+//==============================================================================
+// CControl
+//==============================================================================
+
+void CPlatformWindowControl::SetPosition(CPt inPosition)
+{
+ CControl::SetPosition(inPosition);
+
+ CPt theGlobalPosition = CControl::GetGlobalPosition(CPt(0, 0));
+
+ ::SetWindowPos(m_Window, nullptr, theGlobalPosition.x + 1, theGlobalPosition.y + 1, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+void CPlatformWindowControl::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+
+ ::SetWindowPos(m_Window, nullptr, 0, 0, inSize.x - 2, inSize.y - 2,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
+}
+
+void CPlatformWindowControl::Invalidate(bool inInvalidate)
+{
+ CControl::Invalidate(inInvalidate);
+
+ // This is neccesary to handle the scroll behavior when
+ // this item is embedded in a scroll window.
+ CPt theGlobalPosition = CControl::GetGlobalPosition(CPt(0, 0));
+ ::SetWindowPos(m_Window, nullptr, theGlobalPosition.x + 1, theGlobalPosition.y + 1, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+void CPlatformWindowControl::OnVisibleStateChange(bool inIsVisible)
+{
+ ::ShowWindow(m_Window, ((inIsVisible) ? (SW_SHOWNORMAL) : (SW_HIDE)));
+}
+
+void CPlatformWindowControl::OnParentVisibleStateChanged(bool inIsVisible)
+{
+ ::ShowWindow(m_Window, ((inIsVisible) ? (SW_SHOWNORMAL) : (SW_HIDE)));
+}
+
+UICRenderDevice CPlatformWindowControl::GetPlatformDevice()
+{
+ return m_Window;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h
new file mode 100644
index 00000000..f76697f6
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_PLATFORM_WINDOW_CONTROL_H
+#define INCLUDED_PLATFORM_WINDOW_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+
+#include "Control.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+class CPlatformWindowControl : public CControl
+{
+protected:
+ UICRenderDevice m_Window; ///<
+
+public:
+ CPlatformWindowControl(UICRenderDevice inParent);
+ virtual ~CPlatformWindowControl();
+
+ // CControl
+ void SetPosition(CPt inPosition) override;
+ void SetSize(CPt inSize) override;
+ void Invalidate(bool inInvalidate = true) override;
+
+ void OnVisibleStateChange(bool inIsVisible) override;
+ void OnParentVisibleStateChanged(bool inIsVisible) override;
+
+ UICRenderDevice GetPlatformDevice() override;
+};
+
+#endif // INCLUDED_PLATFORM_WINDOW_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp b/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp
new file mode 100644
index 00000000..3b9cddf1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "WinRenderer.h"
+#include "MasterP.h"
+#include <math.h>
+#include "CoreUtils.h"
+
+//=============================================================================
+/**
+ * Leaves the Renderer in an invalid state, only for subclasses.
+ * In order for this renderer to be valid, you must do two things: (1) you must
+ * create a CDC and set m_DC equal to it, and (2) you must call PushClippingRect.
+ */
+CWinRenderer::CWinRenderer()
+ : m_painter(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Leaves the Renderer in an invalid state, only for subclasses.
+ * PushClippingRect must be called in order for this to become valid.
+ */
+CWinRenderer::CWinRenderer(QPainter *inDC)
+{
+ m_painter = inDC;
+}
+
+CWinRenderer::CWinRenderer(QPainter *inDC, const QRect &inClippingRect)
+{
+ m_painter = inDC;
+
+ PushClippingRect(inClippingRect);
+}
+
+CWinRenderer::~CWinRenderer()
+{
+ m_Pens.clear();
+}
+
+//=============================================================================
+/**
+ * Draws a rectangle and fills it with inColor.
+ * The rectangle has no border and is solid.
+ * The coordinates are converted to global space using the current translation.
+ * @param inCoordinates the coordinates of the rectangle.
+ * @param inColor the color of the rectangle to draw.
+ */
+void CWinRenderer::FillSolidRect(const QRect &inCoordinates, const QColor &inColor)
+{
+ QRect theRect(inCoordinates.topLeft() + m_Translation,
+ inCoordinates.size());
+
+ m_painter->fillRect(theRect, inColor);
+}
+
+//=============================================================================
+/**
+ * Move the pen to the position.
+ * This will put the pen at inPoint but will not draw a line there from the
+ * current location.
+ * @param inPoint the location to move to, in local coordinates.
+ */
+void CWinRenderer::MoveTo(const QPoint &inPoint)
+{
+ m_currentPos = inPoint + m_Translation;
+}
+
+//=============================================================================
+/**
+ * Move the pen to the position.
+ * This will put the pen to the point but will not draw a line there from the
+ * current location.
+ * @param inX the X location to move to, in local coordinates.
+ * @param inY the Y location to move to, in local coordinates.
+ */
+void CWinRenderer::MoveTo(long inX, long inY)
+{
+ MoveTo(QPoint(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Draw a line from the current pen location to inPoint.
+ * This will draw a line to inPoint and move the current location of the pen
+ * to inPoint.
+ * @param inPoint the location to draw to, in local coordinates.
+ */
+void CWinRenderer::LineTo(const QPoint &inPoint)
+{
+ const QPoint point = inPoint + m_Translation;
+ m_painter->drawLine(m_currentPos, point);
+ m_painter->drawLine(point, QPoint(point.x(), point.y() + 1));
+ m_currentPos = point;
+}
+
+//=============================================================================
+/**
+ * Draw a line from the current pen location to the point.
+ * This will draw a line to the point and move the current location of the pen
+ * to inPoint.
+ * @param inX the X coordinate of the point to draw to, in local coordinates.
+ * @param inY the Y coordinate of the point to draw to, in local coordinates.
+ */
+void CWinRenderer::LineTo(long inX, long inY)
+{
+ LineTo(QPoint(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Change the active pen color.
+ * This acts as a stack so that it does not interfere with previous components.
+ * Once the color is done being used PopPen should be called.
+ * @param inColor the color to make the current pen.
+ * @param inWidth the pen width, in pixels.
+ */
+void CWinRenderer::PushPen(const QColor &inColor, int inWidth)
+{
+ QPen thePen = GetPen(inColor, inWidth, Qt::SolidLine);
+
+ QPen theCurrentPen = m_painter->pen();
+ m_painter->setPen(thePen);
+ m_PenList.push_back(theCurrentPen);
+}
+
+void CWinRenderer::PopPen()
+{
+ QPen thePen = m_PenList.back();
+ m_PenList.pop_back();
+ m_painter->setPen(thePen);
+}
+
+//=============================================================================
+/**
+ * Copy the bits from another renderer into this one.
+ * This will copy the rect from inRenderer into this renderer.
+ * inRect will be offset by this renderer's current translation. inXSrc and inYSrc
+ * will be offset by inRenderer's current translation.
+ * @param inRect the position and size of the area to be copied into this renderer.
+ * @param inPixmap the renderer to copy from.
+ * @param xSrc the x location of the location to copy from in inRenderer.
+ * @param ySrc the y location of the location to copy from in inRenderer.
+ */
+void CWinRenderer::BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc)
+{
+ const auto inTranslation = inRenderer->GetTranslation();
+ inXSrc += inTranslation.x();
+ inYSrc += inTranslation.y();
+
+ auto srcRect = inRect;
+ auto destRect = inRect;
+ destRect.translate(m_Translation);
+ srcRect.moveTo(inXSrc, inYSrc);
+ m_painter->save();
+ m_painter->setCompositionMode(QPainter::CompositionMode_DestinationOver);
+ m_painter->drawPixmap(destRect, inRenderer->pixmap(), srcRect);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draws text out without clipping it.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ */
+void CWinRenderer::DrawText(float inX, float inY, const QString &inText)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+ m_painter->drawText(QPointF(inX, inY), inText);
+}
+
+//=============================================================================
+/**
+ * Draws text out to a clipped rectangle.
+ * If any text occurs outside the bounding box then it will be clipped.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ * @param inBoundingBox the bounding box used to clip the text.
+ * @param inColor color to draw the text in
+ */
+void CWinRenderer::DrawText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingBox, const QColor &inColor)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+
+ QRectF rect(inBoundingBox);
+ rect.translate(inX, inY);
+ m_painter->save();
+ QPen pen(inColor);
+ m_painter->setPen(pen);
+ m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draws BOLD text out to a clipped rectangle.
+ * If any text occurs outside the bounding box then it will be clipped.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ * @param inBoundingBox the bounding box used to clip the text.
+ * @param inColor color to draw the text in
+ */
+void CWinRenderer::DrawBoldText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingBox, const QColor &inColor)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+
+ QRectF rect(inBoundingBox);
+ rect.translate(inX, inY);
+ m_painter->save();
+ QPen pen(inColor);
+ m_painter->setPen(pen);
+ QFont font = m_painter->font();
+ font.setBold(true);
+ m_painter->setFont(font);
+ m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Gets the dimensions of the text string as it would be written out to the
+ * screen.
+ * @param inText the text to check the length on.
+ * @return the length of the text in pixels.
+ */
+QSize CWinRenderer::GetTextSize(const QString &inText)
+{
+ QFontMetrics fm = m_painter->fontMetrics();
+ return fm.size(Qt::TextSingleLine, inText);
+}
+
+//=============================================================================
+/**
+ * Draws a a three-dimensional rectangle with the top and left sides in the
+ * color specified by inTopLeftColor and the bottom and right sides in the color
+ * specified by inBottomRightColor.
+ *
+ * @param inRect The rectangle to draw
+ * @param inTopLeftColor Color for the top and left sides of the rect
+ * @param inBottomRightColor Color for the bottom and right sides of the rect
+ */
+void CWinRenderer::Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor,
+ const QColor &inBottomRightColor)
+{
+ auto rect = inRect;
+ rect.translate(m_Translation);
+ m_painter->drawRect(rect);
+ m_painter->save();
+ m_painter->setPen(inTopLeftColor);
+ m_painter->drawLine(rect.topLeft(), rect.bottomLeft());
+ m_painter->drawLine(rect.topLeft(), rect.topRight());
+ m_painter->setPen(inBottomRightColor);
+ m_painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ m_painter->drawLine(rect.bottomRight(), rect.topRight());
+ m_painter->restore();
+}
+
+//==============================================================================
+/**
+ * DrawBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle.
+ *
+ * @param inDC Device context for drawing
+ * @param inPos CPoint position for drawing
+ * @param inBitmap Handle of the bitmap to draw
+ */
+//==============================================================================
+void CWinRenderer::DrawBitmap(const QPoint &inPos, const QPixmap &inImage)
+{
+ m_painter->save();
+ m_painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ m_painter->drawPixmap(inPos + m_Translation, inImage);
+ m_painter->restore();;
+}
+
+void CWinRenderer::PushTranslation(const QPoint &inTranslation)
+{
+ m_Translation += inTranslation;
+
+ m_Translations.push_back(inTranslation);
+}
+
+void CWinRenderer::PopTranslation()
+{
+ QPoint thePreviousTranslation = m_Translations.back();
+ m_Translation -= thePreviousTranslation;
+
+ m_Translations.pop_back();
+}
+
+QPoint CWinRenderer::GetTranslation()
+{
+ return m_Translation;
+}
+
+QPainter* CWinRenderer::GetPainter()
+{
+ return m_painter;
+}
+
+//==============================================================================
+/**
+ * Get the current clipping rect.
+ * The clipping rect is the boundary of pixels that will be drawn to the DC.
+ * This can be used to not draw non-visible objects.
+ * @return the clipping rect in local coordinates.
+ */
+QRect CWinRenderer::GetClippingRect()
+{
+ QRect theClippingRect = m_painter->clipBoundingRect().toRect();
+ theClippingRect.translate(-m_Translation);
+
+ return theClippingRect;
+}
+
+//==============================================================================
+/**
+ * Push a clipping rect onto the stack of clipping rects.
+ * This will cause any drawing outside of the clipping rect to be ignored. The
+ * Control class also uses this to not draw objects outside of this rect.
+ * @param inClippingRect the new clipping rect, in local coordinates.
+ */
+void CWinRenderer::PushClippingRect(const QRect &inClippingRect)
+{
+ QRect clippingRect(inClippingRect);
+ clippingRect.translate(m_Translation);
+
+ const QRegion currentRegion = m_painter->clipRegion();
+ m_painter->setClipRect(clippingRect);
+
+ m_ClippingRegions.push_back(currentRegion);
+}
+
+//==============================================================================
+/**
+ * Pop the current clipping rect.
+ * This will change the clipping rect to use the one previous to the current
+ * one.
+ */
+void CWinRenderer::PopClippingRect()
+{
+ if (m_ClippingRegions.size() > 1) {
+ QRegion thePreviousRegion = m_ClippingRegions.back();
+ m_painter->setClipRegion(thePreviousRegion);
+ m_ClippingRegions.pop_back();
+ }
+}
+
+//==============================================================================
+/**
+ * DrawGradiantBitmap
+ *
+ * Draws a gradiant based on the begin color
+ *
+ * @param inRct Rct tof the control
+ * @param inBeginColor color to start with
+ * @param inInverted true if this is inverted
+ */
+void CWinRenderer::DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted,
+ double inScalingFactor)
+{
+ QRect rect(inRct);
+ QRect theClippingRect = GetClippingRect();
+ rect &= theClippingRect;
+ rect.translate(m_Translation);
+
+ long theHeight = rect.height();
+ long theWidth = rect.width();
+
+ QImage theCompatibleBitmap(1, theHeight, QImage::Format_RGB32);
+
+ int theR = inBeginColor.red();
+ int theG = inBeginColor.green();
+ int theB = inBeginColor.blue();
+
+ double theExtraRModifier = inScalingFactor * (1.0 - (theR / 255.0));
+ double theExtraGModifier = inScalingFactor * (1.0 - (theG / 255.0));
+ double theExtraBModifier = inScalingFactor * (1.0 - (theB / 255.0));
+
+ for (long thePixel = 0; thePixel < theHeight; ++thePixel) {
+ double theNormPixel = (double)thePixel / (theHeight * 4.8);
+ double theCos = 1.0 / (theNormPixel * theNormPixel + 1.0);
+ double theRValue = (double)theR * (theCos + theExtraRModifier);
+ double theGValue = (double)theG * (theCos + theExtraGModifier);
+ double theBValue = (double)theB * (theCos + theExtraBModifier);
+
+ QColor theTempColor(::dtoi(theRValue), ::dtoi(theGValue), ::dtoi(theBValue));
+ if (inInverted) {
+ theCompatibleBitmap.setPixelColor(0, qMax(0l, theHeight - thePixel - 2), theTempColor);
+ } else {
+ theCompatibleBitmap.setPixelColor(0, thePixel, theTempColor);
+ }
+ theExtraRModifier *= 0.3;
+ theExtraGModifier *= 0.3;
+ theExtraBModifier *= 0.3;
+ }
+
+ m_painter->save();
+ m_painter->drawImage(QRect(rect.x(), rect.y(), theWidth, theHeight), theCompatibleBitmap);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Scroll the selected area of the current view by the specified amount.
+ * This will take the rectangle represented by inVisibleSize and 'scroll' it
+ * by inAmount. The section that goes out of the visible size will be clipped
+ * off and the area entering the visible area will be empty.
+ * @param inAmount the amount to scroll by.
+ * @param inVisibleSize the rectangle to be scrolled.
+ * @return the smallest rect of area that needs to be redrawn.
+ */
+QRect CWinRenderer::Scroll(const QPoint &inAmount, const QRect &inVisibleSize)
+{
+#if KDAB_TEMPORARILY_REMOVED
+ inAmount.Offset(m_Translation);
+ inVisibleSize.Offset(m_Translation);
+
+ QRect theVisibleRect(QPoint(inVisibleSize.position.x, inVisibleSize.position.y),
+ QSize(inVisibleSize.size.x, inVisibleSize.size.y));
+
+ CRgn theDirtyRegion;
+ CRect theDirtyRect;
+ m_painter->ScrollDC(inAmount.x, inAmount.y, theVisibleRect, theVisibleRect, &theDirtyRegion,
+ &theDirtyRect);
+
+ QRect theDirtyRct(theDirtyRect.left, theDirtyRect.top, theDirtyRect.right - theDirtyRect.left,
+ theDirtyRect.bottom - theDirtyRect.top);
+
+ theDirtyRct.Offset(QPoint(-m_Translation.x, -m_Translation.y));
+
+ return theDirtyRct;
+#else
+ return {};
+#endif
+}
+
+//=============================================================================
+/**
+ * Draw a gradient over inRect.
+ * This will blend horizontally across the rect from inBeginColor into inEndColor.
+ * This does linear interpolation.
+ * @param inRect the rect to draw on.
+ * @param inBeginColor the start (left most) color.
+ * @param inEndColor the final (right most) color.
+ */
+void CWinRenderer::DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor)
+{
+ const QRect rect = inRect.translated(m_Translation);
+ QLinearGradient gradient(rect.topLeft(), rect.topRight());
+ gradient.setColorAt(0, inBeginColor);
+ gradient.setColorAt(1, inEndColor);
+
+ QBrush brush(gradient);
+ m_painter->fillRect(rect, brush);
+}
+
+void CWinRenderer::FillHashed(const QRect &inRect, const QColor &inForegroundColor)
+{
+ m_painter->save();
+
+ QBrush theBrush(inForegroundColor, Qt::BDiagPattern);
+ QPen pen(inForegroundColor);
+ m_painter->setPen(pen);
+ m_painter->setBrush(theBrush);
+ m_painter->drawRect(inRect.translated(m_Translation));
+
+ m_painter->restore();
+}
+
+QPen CWinRenderer::GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle)
+{
+ QPen thePen;
+ SPenInfo theInfo = { inColor, inWidth, inStyle };
+ TPenMap::iterator thePos = m_Pens.find(theInfo);
+ if (thePos != m_Pens.end()) {
+ thePen = thePos->second;
+ } else {
+ thePen.setColor(inColor);
+ thePen.setWidth(inWidth);
+ m_Pens[theInfo] = thePen;
+ }
+ return thePen;
+}
+
+QPixmap CWinRenderer::pixmap() const
+{
+ return {};
+}
diff --git a/src/Authoring/Studio/_Win/Controls/WinRenderer.h b/src/Authoring/Studio/_Win/Controls/WinRenderer.h
new file mode 100644
index 00000000..4ebcc689
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WinRenderer.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_WIN_RENDERER_H
+#define INCLUDED_WIN_RENDERER_H 1
+
+#pragma once
+
+#include <vector>
+#include <map>
+
+#include "Pt.h"
+#include "Rct.h"
+#include "Renderer.h"
+
+#include <QPainter>
+#include <QRegion>
+
+QT_BEGIN_NAMESPACE
+class QPixmap;
+QT_END_NAMESPACE
+
+class CWinRenderer : public CRenderer
+{
+ typedef std::vector<QPen> TPenList;
+ typedef std::vector<QRegion> TClippingRegions;
+
+protected:
+ CWinRenderer(); ///< Leaves CRenderer in an invalid state, only for subclasses
+ CWinRenderer(QPainter *inDC); ///< Leaves CRenderer in an invalid state, only for subclasses
+
+public:
+ CWinRenderer(QPainter *inDC, const QRect &inClippingRect);
+ virtual ~CWinRenderer();
+
+ void FillSolidRect(const QRect &inCoordinates, const QColor &inColor) override;
+
+ void MoveTo(const QPoint &inPoint) override;
+ void MoveTo(long inX, long inY) override;
+ void LineTo(const QPoint &inPoint) override;
+ void LineTo(long inX, long inY) override;
+
+ void PushPen(const QColor &inColor, int inWidth = 1) override;
+ void PopPen() override;
+ void BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc) override;
+
+ void DrawText(float inX, float inY, const QString &inText) override;
+ void DrawText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingRect, const QColor &inColor = Qt::black) override;
+ void DrawBoldText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingRect, const QColor &inColor = Qt::black) override;
+
+ QSize GetTextSize(const QString &inText) override;
+
+ void DrawBitmap(const QPoint &inPos, const QPixmap &inImage) override;
+ void Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor,
+ const QColor &inBottomRightColor) override;
+ void DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted,
+ double inScalingFactor = .99) override;
+
+ void DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor) override;
+
+ void PushTranslation(const QPoint &inTranslation) override;
+ void PopTranslation() override;
+ QPoint GetTranslation() override;
+
+ QRect GetClippingRect() override;
+ void PushClippingRect(const QRect &inRect) override;
+ void PopClippingRect() override;
+ void PushAbsoluteClippingRect(const QRect &inRect) override {}
+ void FillHashed(const QRect &inRect, const QColor &inForeGroundColor) override;
+ QRect Scroll(const QPoint &inAmount, const QRect &inVisibleSize) override;
+ QPainter *GetPainter() override;
+ QPen GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle);
+
+ QPixmap pixmap() const override;
+
+protected:
+ TPenList m_PenList;
+ TClippingRegions m_ClippingRegions;
+ QPainter *m_painter;
+ QPoint m_currentPos;
+
+protected:
+ struct SPenInfo
+ {
+ QColor Color;
+ long Width;
+ Qt::PenStyle Style;
+ };
+
+ class CPenInfoLessThan : public std::binary_function<const SPenInfo &, const SPenInfo &, bool>
+ {
+ public:
+ inline bool operator()(const SPenInfo &inValL, const SPenInfo &inValR) const
+ {
+ return memcmp(&inValL, &inValR, sizeof(SPenInfo)) < 0;
+ }
+ };
+
+ typedef std::map<SPenInfo, QPen, CPenInfoLessThan> TPenMap;
+ TPenMap m_Pens;
+};
+#endif // INCLUDED_WIN_RENDERER_H
diff --git a/src/Authoring/Studio/_Win/Controls/WndControl.cpp b/src/Authoring/Studio/_Win/Controls/WndControl.cpp
new file mode 100644
index 00000000..c218f9b9
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WndControl.cpp
@@ -0,0 +1,1006 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "WndControl.h"
+#include "WinRenderer.h"
+#include "Control.h"
+#include "MasterP.h"
+#include "AppFonts.h"
+#include "ContextMenu.h"
+#include "HotKeys.h"
+#include "StudioPreferences.h"
+#include "WinDnd.h"
+#include "Doc.h"
+#include "DropSource.h"
+#include "IDragable.h"
+#include "OffscreenRenderer.h"
+
+BEGIN_MESSAGE_MAP(CWndControl, CWnd)
+//{{AFX_MSG_MAP(CWndControl)
+ON_WM_KILLFOCUS()
+ON_WM_SETFOCUS()
+ON_WM_PAINT()
+ON_WM_LBUTTONUP()
+ON_WM_LBUTTONDOWN()
+ON_WM_RBUTTONDOWN()
+ON_WM_RBUTTONUP()
+ON_WM_LBUTTONDBLCLK()
+ON_WM_SIZING()
+ON_WM_ERASEBKGND()
+ON_WM_SIZE()
+ON_WM_MOUSEMOVE()
+ON_WM_CREATE()
+ON_WM_MOUSEACTIVATE()
+ON_WM_MOUSEWHEEL()
+ON_WM_CTLCOLOR()
+ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange)
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
+ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
+END_MESSAGE_MAP()
+
+//=============================================================================
+/**
+ * Creates the pass thru class for the wnd control.
+ */
+CWndControlControlListener::CWndControlControlListener(CWndControl *inParent)
+{
+ m_Parent = inParent;
+}
+
+//=============================================================================
+/**
+ * Notification from the control that the window was invalidated.
+ */
+void CWndControlControlListener::OnControlInvalidated()
+{
+ m_Parent->OnControlInvalidated();
+}
+
+//=============================================================================
+/**
+ * Notification from the control to do a popup at the specified location.
+ */
+long CWndControlControlListener::DoPopup(CContextMenu *inContextMenu, CPt inPoint)
+{
+ return m_Parent->DoPopup(inContextMenu, inPoint);
+}
+
+//=============================================================================
+/**
+ * Get the location of the point in Screen coordinates.
+ */
+CPt CWndControlControlListener::ClientToScreen(CPt inPoint)
+{
+ CPoint thePoint(inPoint.x, inPoint.y);
+ m_Parent->ClientToScreen(&thePoint);
+
+ return CPt(thePoint.x, thePoint.y);
+}
+
+//=============================================================================
+/**
+ * Get the location of the point into client coordinates.
+ */
+CPt CWndControlControlListener::ScreenToClient(CPt inPoint)
+{
+ CPoint thePoint(inPoint.x, inPoint.y);
+ m_Parent->ScreenToClient(&thePoint);
+
+ return CPt(thePoint.x, thePoint.y);
+}
+
+//=============================================================================
+/**
+ * Get the platform dependent view that this is embedding.
+ * Used when platform dependent controls need to be embedded into the Controls.
+ */
+TPlatformView CWndControlControlListener::GetPlatformView()
+{
+ return m_Parent->m_hWnd;
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's SetIsDragging function.
+ * @param inIsDragging true to specify that a drag is occurring or false to cancel a drag
+ */
+void CWndControlControlListener::SetIsDragging(bool inIsDragging)
+{
+ m_Parent->SetIsDragging(inIsDragging);
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's ShowTooltips function.
+ * @param inLocation mid-point of the tooltip in global coordinates
+ * @param inText text to display as a tooltip
+ */
+void CWndControlControlListener::ShowTooltips(CPt inLocation, Q3DStudio::CString inText)
+{
+ m_Parent->ShowTooltips(inLocation, inText);
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's HideTooltips function.
+ */
+void CWndControlControlListener::HideTooltips()
+{
+ m_Parent->HideTooltips();
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's ShowMoveableTooltips function.
+ * @param inLocation mid-point of the tooltip in global coordinates
+ * @param inText text to display as a tooltip
+ */
+void CWndControlControlListener::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText,
+ CRct inBoundingRct)
+{
+ m_Parent->ShowMoveableWindow(inLocation, inText, inBoundingRct);
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's HideMoveableTooltips function.
+ */
+void CWndControlControlListener::HideMoveableWindow()
+{
+ m_Parent->HideMoveableWindow();
+}
+
+void CWndControlControlListener::DoStartDrag(IDragable *inDragable)
+{
+ m_Parent->DoStartDrag(inDragable);
+}
+
+//===============================================================================
+/**
+* performs a drag operation on a file
+*/
+void CWndControlControlListener::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList)
+{
+ m_Parent->DoStartDrag(inDragFileNameList);
+}
+
+IMPLEMENT_OBJECT_COUNTER(CWndControl);
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CWndControl::CWndControl(CControl *inControl)
+ : m_MouseOver(false)
+ , m_MemDC(nullptr)
+ , m_IsDragging(false)
+ , m_ControlListener(this)
+ , m_IsMouseDown(false)
+{
+ ADDTO_OBJECT_COUNTER(CWndControl);
+
+ m_Control = inControl;
+
+ if (m_Control)
+ m_Control->SetWindowListener(&m_ControlListener);
+
+ RegisterWindowClass();
+
+ // Create the tooltip for this window (there's only one per view)
+ m_Tooltip.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(CS_SAVEBITS), L"CPopupWndTooltip",
+ WS_POPUP | WS_BORDER, CRect(0, 0, 20, 10), this, 0);
+ m_Tooltip.SetStationary(true);
+
+ // Create the tooltip for this window (there's only one per view)
+ m_MoveableTooltip.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(CS_SAVEBITS),
+ L"CPopupWndTooltip", WS_POPUP | WS_BORDER, CRect(0, 0, 20, 10), this,
+ 0);
+ m_MoveableTooltip.SetStationary(false);
+
+ m_Brush.CreateSolidBrush(CStudioPreferences::GetBaseColor());
+
+#ifdef _DEBUG
+ m_IsPainting = false;
+#endif
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CWndControl::~CWndControl()
+{
+ DeleteBuffers();
+
+ REMOVEFROM_OBJECT_COUNTER(CWndControl);
+}
+
+// Register the window class if it has not already been registered.
+BOOL CWndControl::RegisterWindowClass()
+{
+ WNDCLASS wndcls;
+ HINSTANCE hInst = AfxGetInstanceHandle();
+
+ if (!(::GetClassInfo(hInst, WNDCONTROL_CLASSNAME, &wndcls))) {
+ // otherwise we need to register a new class
+ wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+ wndcls.lpfnWndProc = ::DefWindowProc;
+ wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
+ wndcls.hInstance = hInst;
+ wndcls.hIcon = nullptr;
+ wndcls.hCursor = nullptr;
+ wndcls.hbrBackground = m_Brush;
+ wndcls.lpszMenuName = nullptr;
+ wndcls.lpszClassName = WNDCONTROL_CLASSNAME;
+
+ if (!AfxRegisterClass(&wndcls)) {
+ AfxThrowResourceException();
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * Create: Handles the WM_CREATE message.
+ *
+ * Creates the view, sets the font, and loads the toolbar.
+ *
+ * @param lpszClassName Names the Windows class. The class name can be any name
+ *registered with the AfxRegisterWndClass
+ * @param lpszWindowName Represents the window name. Used as text for the title bar.
+ * @param dwStyle Specifies the window style attributes.
+ * @param rect Specifies the size and position of the window.
+ * @param pParentWnd Pointer to the parent of the view.
+ * @param nID The ID for the view.
+ * @param pContext Create context for the view.
+ *
+ * @return TRUE if creation was successful, otherwise FALSE.
+ */
+//==============================================================================
+int CWndControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ return CWnd::OnCreate(lpCreateStruct);
+}
+
+//=============================================================================
+/**
+ * MFC notification that this window needs to be redrawn.
+ * This buffers the draw DC, makes a Renderer and has the Control draw to the
+ * buffered DC.
+ */
+void CWndControl::OnPaint()
+{
+#ifdef _DEBUG
+ m_IsPainting = true;
+#endif
+
+ UICPROFILE(OnPaint);
+
+ CPaintDC dc(this);
+
+ HDC theDeviceContext = dc.GetSafeHdc();
+
+ RECT theSize;
+ this->GetClientRect(&theSize);
+
+ bool theRedrawAllFlag = false;
+
+ if (m_MemDC == nullptr) {
+ m_MemDC = new CDC();
+ m_MemDC->CreateCompatibleDC(&dc);
+ m_MemDC->SelectObject(CAppFonts::GetInstance()->GetNormalFont());
+
+ m_MemBitmap = ::CreateCompatibleBitmap(theDeviceContext, theSize.right, theSize.bottom);
+
+ m_OldBitmap = (HBITMAP)m_MemDC->SelectObject(m_MemBitmap);
+
+ theRedrawAllFlag = true;
+ }
+
+ CRct theDirtyRect;
+ {
+ UICPROFILE(OnPaint_Render);
+ CWinRenderer theRenderer(m_MemDC, CRct(0, 0, theSize.right, theSize.bottom));
+ if (m_Control)
+ m_Control->OnDraw(&theRenderer, theDirtyRect, theRedrawAllFlag);
+ }
+
+ // Copy (BitBlt) bitmap from bitmap memory DC to memory DC
+ // ::BitBlt( theDeviceContext, theDirtyRect.position.x, theDirtyRect.position.y,
+ //theDirtyRect.size.x, theDirtyRect.size.y, m_MemDC->GetSafeHdc( ), theDirtyRect.position.x,
+ //theDirtyRect.position.y, SRCCOPY );
+ ::BitBlt(theDeviceContext, 0, 0, theSize.right, theSize.bottom, m_MemDC->GetSafeHdc(), 0, 0,
+ SRCCOPY);
+
+#ifdef _DEBUG
+ m_IsPainting = false;
+#endif
+}
+
+void CWndControl::DeleteBuffers()
+{
+ if (m_MemDC != nullptr) {
+ m_MemDC->SelectObject(m_OldBitmap);
+ ::DeleteObject(m_MemBitmap);
+ m_MemDC->DeleteDC();
+ delete m_MemDC;
+ m_MemDC = nullptr;
+ }
+}
+
+//=============================================================================
+/**
+ * Notification to this window that it has lost focus.
+ * @param pNewWnd the window that has gained focus.
+ */
+void CWndControl::OnKillFocus(CWnd *pNewWnd)
+{
+ CWnd::OnKillFocus(pNewWnd);
+
+ // This is used for special cases where we lose control of the mouse and lose focus as well.
+ // It makes sure we are not still receiving mouse messages.
+ if (m_IsMouseDown) {
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(-1, -1), CHotKeys::GetCurrentKeyModifiers());
+ ReleaseCapture();
+ }
+
+ if (m_Control) {
+ // For the case where pNewWnd is an "embedded" control in m_Control (eg.
+ // CPlatformEditControl)
+ // m_Control should not lose focus.
+ // Note that since most of the Studio controls uses a common PlatformDevice (the Studio
+ // window),
+ // this (OnKillFocus) only occurs when 1) switching to another app, 2) popping up a dialog
+ // box or 3) an embedded control
+ // takes focus.
+ // This takes care of the case when an embedded control takes focus but unwittingly causes
+ // its parent to lose focus.
+ // This can have dire consequences if the parent control were to do something on losing
+ // focus, such as
+ // destroying all its children. For example, Bug3421.
+ if (!m_Control->IsChildPlatformDevice(pNewWnd->GetSafeHwnd()))
+ m_Control->OnLoseFocus();
+ }
+}
+
+void CWndControl::OnSetFocus(CWnd *pPrevWnd)
+{
+ CWnd::OnSetFocus(pPrevWnd);
+ if (m_Control)
+ m_Control->OnGainFocus();
+}
+
+//=============================================================================
+/**
+ * Notification of mouse up.
+ */
+void CWndControl::OnLButtonUp(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+ m_IsMouseDown = false;
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ ReleaseCapture();
+
+ CWnd::OnLButtonUp(nFlags, inPoint);
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse click.
+ */
+void CWndControl::OnLButtonDown(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+ m_IsMouseDown = true;
+ SetCapture();
+ // Tell the control that it got a mouse down.
+ if (m_Control)
+ m_Control->OnMouseDown(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ CWnd::OnLButtonDown(nFlags, inPoint);
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse click.
+ */
+void CWndControl::OnRButtonDown(UINT nFlags, CPoint inPoint)
+{
+ SetCapture();
+
+ if (m_IsMouseDown) {
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+ m_IsMouseDown = false;
+ }
+
+ // Tell the control that it got a mouse down.
+ if (m_Control)
+ m_Control->OnMouseRDown(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ CWnd::OnRButtonDown(nFlags, inPoint);
+}
+
+//=============================================================================
+/**
+ * Notification of mouse up.
+ */
+void CWndControl::OnRButtonUp(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseRUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ ReleaseCapture();
+}
+
+long CWndControl::DoPopup(CContextMenu *inMenu, CPt inPoint)
+{
+ CPoint thePoint(inPoint.x, inPoint.y);
+ ClientToScreen(&thePoint);
+
+ long theSelectedItem = inMenu->DoPopup(CPt(thePoint.x, thePoint.y), m_hWnd);
+ if (m_IsMouseDown) {
+ m_IsMouseDown = false;
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(-1, -1), 0);
+ }
+ ReleaseCapture();
+
+ return theSelectedItem;
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse double click.
+ */
+void CWndControl::OnLButtonDblClk(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+
+ // Tell the control that it got a mouse down.
+ if (m_Control)
+ m_Control->OnMouseDoubleClick(CPt(inPoint.x, inPoint.y), nFlags);
+}
+
+//=============================================================================
+/**
+ * Notification of a key down message.
+ */
+bool CWndControl::OnKeyDown(UINT inChar, UINT, UINT)
+{
+ return m_Control->OnKeyDown(inChar, CHotKeys::GetCurrentKeyModifiers());
+}
+
+//=============================================================================
+/**
+ * Notification of a key up messages. May be hooked up later.
+ */
+bool CWndControl::OnKeyUp(UINT inChar, UINT, UINT)
+{
+ return m_Control->OnKeyUp(inChar, CHotKeys::GetCurrentKeyModifiers());
+}
+
+//=============================================================================
+/**
+ * Notification of a character press message.
+ *
+ * @return true if the character was processed by the control, otherwise false
+ */
+bool CWndControl::OnChar(UINT inChar, UINT, UINT)
+{
+ return m_Control->OnChar(inChar, CHotKeys::GetCurrentKeyModifiers());
+}
+
+//=============================================================================
+/**
+ * Displays a tooltip at the desired location, and with the desired text.
+ * @param inLocation mid-point of the tooltext message box to be displayed
+ * @param inText text to be displayed as the tooltip
+ */
+void CWndControl::ShowTooltips(CPt inLocation, Q3DStudio::CString inText)
+{
+ // If the global preference for tooltips is enabled
+ if (CStudioPreferences::ShouldShowTooltips()) {
+ // If the tooltip text is not empty, show the tooltip
+ if (!inText.IsEmpty()) {
+ // So that tooltip text renders within the window
+ // this would be nicely taken care of if this were a MFC control...
+ COffscreenRenderer theOffscreenRenderer(CRct(0, 0, 1, 1));
+ float theWidth(0);
+ float theHeight(0);
+ theOffscreenRenderer.GetTextSize(inText, theWidth, theHeight);
+
+ long theRightMargin = m_Control->GetPosition().x + m_Control->GetSize().x;
+ if (inLocation.x + ::dtol(theWidth) > theRightMargin) // re-centers this
+ inLocation.x = theRightMargin - ::dtol(theWidth) / 2;
+
+ // Convert the point to screen coordinates
+ ::CPoint theScreenCoords = ::CPoint(inLocation.x, inLocation.y);
+ ClientToScreen(&theScreenCoords);
+ m_Tooltip.UpdateToolTip(theScreenCoords, ::CString(inText.GetMulti()), true);
+ }
+ // If the tooltip text is empty, hide the tooltip
+ else
+ m_Tooltip.ShowWindow(SW_HIDE);
+ }
+}
+
+//=============================================================================
+/**
+ * Hides any tooltip currently being displayed.
+ */
+void CWndControl::HideTooltips()
+{
+ m_Tooltip.ShowWindow(SW_HIDE);
+}
+
+//=============================================================================
+/**
+ * Starts the Dragging process.
+ * On the given IDragable.
+ * @param inAsset the Asset to be drug.
+ */
+void CWndControl::DoStartDrag(IDragable *inDragable)
+{
+ // Tell the window that we are beginning a drag
+ if (inDragable && !m_IsDragging) {
+ // This should prevent the Container from dragging while it is already dragging.
+ SetIsDragging(true);
+
+ // This is a Wrapper for the OLEDROP
+ CWinDragManager theDragManager;
+
+ // Theoretically: there is no limit to the amount of data you can add.
+ // For now only one object will work, until i figure out how to drag multiple objects in
+ // windows.
+ Q3DStudio::CAutoMemPtr<CDropSource> theDropSource =
+ CDropSourceFactory::Create(inDragable->GetFlavor(), inDragable);
+
+ // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls.
+ theDragManager.AddData(inDragable->GetFlavor(), &theDropSource, sizeof(CDropSource *));
+ // This is a blocking call when we get done with this call we should have no more data in
+ // our Drag list.
+ theDragManager.StartDrag();
+
+ // Tell the window that we are done dragging
+ SetIsDragging(false);
+ }
+}
+
+//===============================================================================
+/**
+* performs a drag operation on a file
+*/
+void CWndControl::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList)
+{
+ // Tell the window that we are beginning a drag
+ if (!m_IsDragging) {
+ SetIsDragging(true);
+
+ try {
+ CWinDragManager theDragManager;
+
+ std::vector<Q3DStudio::CString>::iterator thePos = inDragFileNameList.begin();
+ std::vector<Q3DStudio::CString>::iterator theEndPos = inDragFileNameList.end();
+
+ Q3DStudio::CAutoMemPtr<CDropSource> theDropSource;
+ Q3DStudio::CAutoMemPtr<CUICFile> theDragFile;
+ for (; thePos != theEndPos; ++thePos) {
+ Q3DStudio::CString theDragFileName = *thePos;
+ if (theDragFileName.Length() > 0) {
+ theDragFile = new CUICFile(theDragFileName);
+ theDropSource = CDropSourceFactory::Create(
+ EUIC_FLAVOR_ASSET_UICFILE, (void *)theDragFile, sizeof(theDragFile));
+ // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls.
+ theDragManager.AddData(EUIC_FLAVOR_ASSET_UICFILE, &theDropSource,
+ sizeof(CDropSource *));
+ break;
+ }
+ }
+ theDragManager.StartDrag();
+ } catch (...) { // if there are any errors that throws an exception, there
+ // there will be no more drag and drop, since the flag will not be reset.
+ }
+ // Tell the window that we are done dragging
+ SetIsDragging(false);
+ }
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse wheel movement.
+ */
+BOOL CWndControl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
+{
+ ScreenToClient(&pt);
+ if (m_Control)
+ m_Control->OnMouseWheel(CPt(pt.x, pt.y), zDelta, CHotKeys::GetCurrentKeyModifiers());
+
+ //Q_UNUSED( nFlags );
+ //Q_UNUSED( zDelta );
+ //Q_UNUSED( pt );
+ return CWnd::OnMouseWheel(nFlags, zDelta, pt);
+}
+
+LRESULT CWndControl::OnRegisteredMouseWheel(WPARAM, LPARAM)
+{
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Notification that this window is being resized.
+ */
+void CWndControl::OnSizing(UINT nSide, LPRECT lpRect)
+{
+ Q_UNUSED(nSide);
+ Q_UNUSED(lpRect);
+}
+
+//=============================================================================
+/**
+ * Override of erase to prevent flashing of the background.
+ */
+BOOL CWndControl::OnEraseBkgnd(CDC *pDC)
+{
+ Q_UNUSED(pDC);
+ return FALSE;
+}
+
+//=============================================================================
+/**
+ * Notification that this window has been resized.
+ */
+void CWndControl::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+
+ MoveWindow(0, 0, cx, cy);
+
+ CRect theSize;
+ GetClientRect(&theSize);
+
+ if (m_Control)
+ m_Control->SetSize(CPt(theSize.right, theSize.bottom));
+
+ // Gotta recreate the buffered objects, otherwise they will be the wrong dimensions
+ DeleteBuffers();
+}
+
+//=============================================================================
+/**
+ * Event notification that the mouse has moved.
+ */
+void CWndControl::OnMouseMove(UINT, CPoint point)
+{
+#ifdef _DEBUG
+ m_IsPainting = true;
+#endif
+
+ UICPROFILE(OnMouseMove);
+
+ // Track the mouse while it's in here, this will give us the hover msg
+ m_MouseOver = true;
+
+ TRACKMOUSEEVENT theEventStruct;
+ theEventStruct.cbSize = sizeof(TRACKMOUSEEVENT);
+ theEventStruct.dwFlags = TME_HOVER | TME_LEAVE;
+ theEventStruct.hwndTrack = GetSafeHwnd();
+ theEventStruct.dwHoverTime = HOVER_DEFAULT;
+
+ ::TrackMouseEvent(&theEventStruct);
+
+ // Notify the control that the mouse moved
+ if (m_Control) {
+ m_Control->OnMouseMove(CPt(point.x, point.y), CHotKeys::GetCurrentKeyModifiers());
+
+ // If the control invalidated because of a mouse event then we want to do an immediate
+ // redraw.
+ // this ensures consistent visible feedback.
+ if (m_Control->IsChildInvalidated()) {
+ UICPROFILE(RedrawWindow);
+ RedrawWindow(nullptr, nullptr, RDW_UPDATENOW);
+ }
+ }
+
+#ifdef _DEBUG
+ m_IsPainting = false;
+#endif
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse has left this window.
+ */
+LRESULT CWndControl::OnMouseLeave(WPARAM inwParam, LPARAM inlParam)
+{
+#ifdef _DEBUG
+ if (!m_IsPainting) {
+#endif _DEBUG
+
+ Q_UNUSED(inwParam);
+ Q_UNUSED(inlParam);
+
+ CPoint thePoint;
+
+ ::GetCursorPos(&thePoint);
+
+ // This will tell me what window is under this point.
+ HWND theWindow = ::WindowFromPoint(thePoint);
+
+ if (theWindow != m_hWnd) {
+ m_MouseOver = false;
+ if (m_Control)
+ m_Control->OnMouseMove(CPt(-1, -1), 0);
+ }
+
+#ifdef _DEBUG
+ }
+#endif
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Override to provide the hover message to the control.
+ */
+LRESULT CWndControl::OnMouseHover(WPARAM inwParam, LPARAM inlParam)
+{
+
+ long theX = inlParam & 0xFFFF;
+ long theY = (inlParam >> 16) & 0xFFFF;
+
+ if (m_Control)
+ m_Control->OnMouseHover(CPt(theX, theY), (UINT)inwParam);
+
+ TRACKMOUSEEVENT theEventStruct;
+ theEventStruct.cbSize = sizeof(TRACKMOUSEEVENT);
+ theEventStruct.dwFlags = TME_HOVER | TME_LEAVE;
+ theEventStruct.hwndTrack = GetSafeHwnd();
+ theEventStruct.dwHoverTime = HOVER_DEFAULT;
+
+ ::TrackMouseEvent(&theEventStruct);
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Callback from the control that it has been invalidated.
+ * This will post a message for a redraw.
+ */
+void CWndControl::OnControlInvalidated()
+{
+ if (::IsWindow(m_hWnd)) {
+ Invalidate();
+ ::PostMessage(m_hWnd, WM_PAINT, 0, 0);
+ }
+}
+
+//=============================================================================
+/**
+ * Override of PreTranslateMessage for dragging implementation.
+ */
+BOOL CWndControl::PreTranslateMessage(MSG *inMessage)
+{
+ BOOL theReturn = FALSE;
+
+ switch (inMessage->message) {
+ case WM_KEYDOWN: {
+ theReturn =
+ OnKeyDown((UINT)inMessage->wParam, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam);
+
+ BYTE theKeyboardState[256];
+ ::GetKeyboardState(theKeyboardState);
+
+ theKeyboardState[VK_CONTROL] = 0;
+
+ WORD theChar = 0;
+ // Get the ascii character for the VK key.
+ ::ToAscii((UINT)inMessage->wParam, (inMessage->lParam >> 16) & 0xFF, theKeyboardState,
+ &theChar, 0);
+ unsigned int theCharacterCode = (char)theChar;
+
+ if (theCharacterCode != 0) {
+ theReturn = theReturn
+ || OnChar(theCharacterCode, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam);
+ }
+ } break;
+
+ case WM_KEYUP:
+ // Do the OnKeyUp
+ theReturn =
+ OnKeyUp((UINT)inMessage->wParam, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam);
+ break;
+
+ case WM_CHAR:
+ theReturn = OnChar((UINT)inMessage->wParam, 0, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Call this function to indicate that a drag operation is currently taking
+ * place or has just finished. If the drag operation just finished, a mouse up
+ * event will be sent to all children so that the one who initiated the drag
+ * can clean things up.
+ * @param inIsDragging true to specify that a drag is occurring or false if a drag ended
+ */
+void CWndControl::SetIsDragging(bool inIsDragging)
+{
+ m_IsDragging = inIsDragging;
+
+ // If we are no longer dragging, notify the children that a mouse up occurred since OLE won't
+ // tell us that
+ if (!m_IsDragging)
+ m_Control->OnMouseUp(CPt(-1, -1), 0);
+}
+
+//=============================================================================
+/**
+ * Override of MouseActivate to set the focus on this.
+ */
+int CWndControl::OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message)
+{
+ CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
+ SetFocus();
+ m_Control->OnGainFocus();
+ return MA_ACTIVATE;
+}
+
+bool CWndControl::OnDragWithin(CDropSource &inSource)
+{
+ bool theReturn = false;
+ CPt thePoint = inSource.GetCurrentPoint();
+ long theFlags = inSource.GetCurrentFlags();
+ CDropTarget *theDropTarget = m_Control->FindDropCandidate(thePoint, theFlags);
+
+ if (theDropTarget) {
+ theReturn = theDropTarget->Accept(inSource);
+ delete theDropTarget;
+ }
+ return theReturn;
+}
+
+bool CWndControl::OnDragReceive(CDropSource &inSource)
+{
+ bool theReturn = false;
+ CPt thePoint = inSource.GetCurrentPoint();
+ long theFlags = inSource.GetCurrentFlags();
+
+ CDropTarget *theDropTarget = m_Control->FindDropCandidate(thePoint, theFlags);
+
+ if (theDropTarget) {
+ theReturn = theDropTarget->Drop(inSource);
+ delete theDropTarget;
+ }
+ return theReturn;
+}
+
+void CWndControl::OnDragLeave()
+{
+ m_MouseOver = false;
+ m_Control->OnMouseMove(CPt(-1, -1), 0);
+}
+
+void CWndControl::OnReflectMouse(CPt &inPoint, long inFlags)
+{
+ // Notify the control that the mouse moved
+ m_Control->OnMouseMove(inPoint, inFlags /*CHotKeys::GetCurrentKeyModifiers( )*/);
+
+ // If the control invalidated because of a mouse event then we want to do an immediate redraw.
+ // this ensures consistent visible feedback.
+ if (m_Control->IsChildInvalidated()) {
+ UICPROFILE(RedrawWindow);
+ RedrawWindow(nullptr, nullptr, RDW_UPDATENOW);
+ }
+}
+
+void CWndControl::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct)
+{
+ // If the global preference for tooltips is enabled
+ if (CStudioPreferences::ShouldShowTooltips()) {
+ // This flag is set when the control is created, it tells itself that things should
+ // not move around outside its boundaries.
+ if (inLocation.x < inBoundingRct.position.x)
+ inLocation.x = inBoundingRct.position.x;
+ if (inLocation.y < inBoundingRct.position.y)
+ inLocation.y = inBoundingRct.position.y;
+ if (inLocation.x > (inBoundingRct.position.x + inBoundingRct.size.x))
+ inLocation.x = inBoundingRct.position.x + inBoundingRct.size.x;
+ if (inLocation.y > (inBoundingRct.position.y + inBoundingRct.size.y))
+ inLocation.y = inBoundingRct.position.y + inBoundingRct.size.y;
+
+ // Convert the point to screen coordinates
+ ::CPoint theScreenCoords = ::CPoint(inLocation.x, inLocation.y);
+ ClientToScreen(&theScreenCoords);
+ // If the tooltip text is not empty, show the tooltip
+ if (!inText.IsEmpty())
+ m_MoveableTooltip.UpdateToolTip(theScreenCoords, ::CString(inText.GetMulti()), true);
+ // If the tooltip text is empty, hide the tooltip
+ else
+ m_MoveableTooltip.ShowWindow(SW_HIDE);
+ }
+}
+
+void CWndControl::HideMoveableWindow()
+{
+ m_MoveableTooltip.ShowWindow(SW_HIDE);
+}
+
+//=============================================================================
+/**
+ * Override of OnCtlColor( ) to provide a callback when the dialog is closed.
+ */
+HBRUSH CWndControl::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
+{
+ // Call the base class implementation first! Otherwise, it may undo what we are trying to
+ // accomplish here.
+ HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor);
+
+ // Set the text color to red.
+ // pDC->SetTextColor(RGB(255, 0, 0));
+
+ // pDC->SetBkColor( CStudioPreferences::GetBaseColor( ) );
+
+ // Return handle to our CBrush object.
+ // hbr = m_Brush;
+
+ return hbr;
+}
+
+//=============================================================================
+/**
+ * Override of EN_CHANGE
+ */
+void CWndControl::OnEnChange()
+{
+}
diff --git a/src/Authoring/Studio/_Win/Controls/WndControl.h b/src/Authoring/Studio/_Win/Controls/WndControl.h
new file mode 100644
index 00000000..a7e3c72a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WndControl.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_WND_CONTROL_H
+#define INCLUDED_WND_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "PopupWnd.h"
+#include "DropContainer.h"
+
+#define WNDCONTROL_CLASSNAME _T("WNDCONTROL")
+
+class CWndControl;
+class IDragable;
+
+class CWndControlControlListener : public CControlWindowListener
+{
+public:
+ CWndControlControlListener(CWndControl *inParent);
+ virtual void OnControlInvalidated();
+ virtual long DoPopup(CContextMenu *inMenu, CPt inLocation);
+ virtual CPt ClientToScreen(CPt inPoint);
+ virtual CPt ScreenToClient(CPt inPoint);
+ virtual TPlatformView GetPlatformView();
+ virtual void SetIsDragging(bool inIsDragging);
+ virtual void ShowTooltips(CPt inLocation, Q3DStudio::CString inText);
+ virtual void HideTooltips();
+ virtual void DoStartDrag(IDragable *inDragable);
+ virtual void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList);
+ virtual void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct);
+ virtual void HideMoveableWindow();
+
+protected:
+ CWndControl *m_Parent;
+};
+
+class CWndControl : public CWnd, public CWinDropContainer
+{
+
+public:
+ CWndControl(CControl *inAgent);
+ virtual ~CWndControl();
+
+ DEFINE_OBJECT_COUNTER(CWndControl)
+
+ BOOL RegisterWindowClass();
+
+ virtual void OnControlInvalidated();
+ long DoPopup(CContextMenu *inMenu, CPt inLocation);
+ void SetIsDragging(bool inIsDragging);
+ void DeleteBuffers();
+ bool OnKeyDown(UINT inChar, UINT inRepCnt, UINT inFlags);
+ bool OnKeyUp(UINT inChar, UINT inRepCnt, UINT inFlags);
+ bool OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ void ShowTooltips(CPt inLocation, Q3DStudio::CString inText);
+ void HideTooltips();
+ void DoStartDrag(IDragable *inDragable);
+ void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList);
+ virtual void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct);
+ virtual void HideMoveableWindow();
+
+ bool OnDragWithin(CDropSource &inSource);
+ bool OnDragReceive(CDropSource &inSource);
+ void OnDragLeave();
+ void OnReflectMouse(CPt &inPoint, long inFlags);
+
+ //{{AFX_MSG(CWndControl)
+ afx_msg void OnKillFocus(CWnd *pNewWnd);
+ afx_msg void OnSetFocus(CWnd *pOldWnd);
+ afx_msg void OnPaint();
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
+ afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
+ afx_msg void OnSizing(UINT nFlags, LPRECT pRect);
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg LRESULT OnRegisteredMouseWheel(WPARAM wParam, LPARAM lParam);
+ afx_msg int OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message);
+ afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
+ afx_msg void OnEnChange();
+ //}}AFX_MSG
+
+ afx_msg LRESULT OnMouseLeave(WPARAM inwParam, LPARAM inlParam);
+ afx_msg LRESULT OnMouseHover(WPARAM inwParam, LPARAM inlParam);
+ DECLARE_MESSAGE_MAP()
+protected:
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CLibraryView)
+public:
+protected:
+ virtual BOOL PreTranslateMessage(MSG *pMsg);
+ //}}AFX_VIRTUAL
+
+ CControl *m_Control;
+ CControl *m_Focus;
+ CPopupWnd m_Tooltip;
+ CPopupWnd m_MoveableTooltip;
+ CBrush m_Brush;
+ bool m_MouseOver;
+ CDC *m_MemDC;
+ HBITMAP m_MemBitmap;
+ HBITMAP m_OldBitmap;
+ bool m_IsMouseDown; /// This is used for a hack to make controls get a mouse up when we lose
+ /// focuse and
+/// the mouse is down... say we try and delete a layer while dragging and it is the last layer
+
+#ifdef _DEBUG
+ bool m_IsPainting;
+#endif
+ bool m_IsDragging;
+ CWndControlControlListener m_ControlListener;
+};
+
+#endif // INCLUDED_WND_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp
new file mode 100644
index 00000000..ac835c00
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "HotKeys.h"
+#include "DropProxy.h"
+#include "DropContainer.h"
+#include "DropSource.h"
+#include "UICFile.h"
+#include "UICString.h"
+#include "IDragable.h"
+
+#include <QDragEnterEvent>
+#include <QWidget>
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inParent gesture listener that messages will be passed to
+ */
+CDropProxy::CDropProxy(CDropContainer *inParent)
+{
+ m_Parent = inParent;
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CDropProxy::~CDropProxy()
+{
+}
+
+//=============================================================================
+/**
+ * Called when a drag begins over a window.
+ */
+void CDropProxy::dragEnterEvent(QDragEnterEvent *event)
+{
+ event->ignore();
+ if (GetDragItemCount(event->mimeData())) {
+ CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin();
+ CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd();
+
+ for (; theItr != theEnd; ++theItr) {
+ if (HasMainFlavor(event->mimeData(), *theItr)) {
+ event->accept();
+ event->setDropAction(Qt::CopyAction);
+ break;
+ }
+ }
+ }
+}
+
+//===============================================================================
+/**
+ * This will extract the Data from the OLEDropObject and convert it to a CDropSource.
+ * @param inDataObject the Win specific dropSource.
+ * @param inFlavor the Flavor we need.
+ * @param inItem the position of the data in the DataObject.
+ * @return Newly extracted or created DropSource.
+ * Note: if we created it we need to make sure we destroy this object.
+ */
+CDropSource *CDropProxy::GetDropSource(const QMimeData *inDataObject, long inFlavor, long inItem)
+{
+ const CDropSource *theDropSource = nullptr;
+ switch (inFlavor) {
+ case EUIC_FLAVOR_FILE: {
+ // Check if we have a Drop File on our hands.
+ if (inDataObject->hasUrls()) {
+ // Get the number of files being dragged
+ short theFileCount = inDataObject->urls().count();
+
+ // Only allow single files to be dragged
+ if (theFileCount > inItem && !inDataObject->urls().isEmpty()) {
+ // Get the filename of the object being dragged
+ QString theFilename = inDataObject->urls().at(inItem).toLocalFile();
+
+ CUICFile theFile(Q3DStudio::CString::fromQString(theFilename));
+ // Dragging a single file
+ theDropSource =
+ CDropSourceFactory::Create(EUIC_FLAVOR_FILE, &theFile, sizeof(CUICFile *));
+ }
+ }
+ } break;
+ case EUIC_FLAVOR_TEXT:
+ // Don't do anythiing for this
+ case EUIC_FLAVOR_LISTBOX:
+ // Don't do anythiing for this
+ case EUIC_FLAVOR_BASIC_OBJECTS:
+ // Don't do anythiing for this
+ case EUIC_FLAVOR_ASSET_LIB:
+ // make an Aset out of this.
+ case EUIC_FLAVOR_ASSET_TL:
+ // make an Aset out of this.
+ case EUIC_FLAVOR_ASSET_UICFILE:
+ // make an Aset out of this.
+ // Get a pointer to the object
+ theDropSource = dynamic_cast<const CDropSource *>(inDataObject);
+ if (theDropSource != nullptr && theDropSource->GetFlavor() != inFlavor)
+ theDropSource = nullptr;
+ break;
+ }
+ return const_cast<CDropSource *>(theDropSource);
+}
+
+//===============================================================================
+/**
+ * This is to count the number of objects in the DataObject.
+ * @param inDataObject the WinSpecific dropobject
+ * @return The number of items found.
+ */
+long CDropProxy::GetDragItemCount(const QMimeData *inDataObject)
+{
+ long theCount = 0;
+
+ // Check if we have a Drop File on our hands.
+ if (inDataObject->hasUrls()) {
+ // Get the number of files being dragged
+ theCount = inDataObject->urls().count();
+ } else {
+ auto source = dynamic_cast<const CDropSource *>(inDataObject);
+ theCount = source != nullptr ? 1 : 0;
+ }
+
+ return theCount;
+}
+//===============================================================================
+/**
+ * This will check the DataObject for the Flavor.
+ * @param inDataObject the Win specific data object.
+ * @param inFlavor the requested Flavor.
+ * @param true if the DataObject contains the flavor.
+ */
+bool CDropProxy::HasMainFlavor(const QMimeData *inDataObject, long inFlavor)
+{
+ if (inFlavor == EUIC_FLAVOR_FILE)
+ return inDataObject->hasUrls();
+ auto source = dynamic_cast<const CDropSource *>(inDataObject);
+ return source != nullptr && source->GetFlavor() == inFlavor;
+}
+
+//=============================================================================
+/**
+ * Called when a drag event leaves the window. May cause the drag to end if
+ * the mouse button is no longer down.
+ */
+void CDropProxy::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ if (m_Parent) {
+ m_Parent->OnDragLeave();
+ event->accept();
+ }
+}
+
+//=============================================================================
+/**
+ * Called when an item is being dragged over this window. Passes the message
+ * on to the gesture listener.
+ */
+void CDropProxy::dragMoveEvent(QDragMoveEvent *event)
+{
+ bool theAcceptFlag = false;
+
+ if (m_Parent) {
+ long theCount = GetDragItemCount(event->mimeData());
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ Qt::KeyboardModifiers theModifyerFlags = ReflectMouse(event->pos().x(), event->pos().y());
+
+ CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin();
+ CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd();
+
+ for (; theItr != theEnd; ++theItr) {
+ // Find the Flavor of this Item.
+ if (HasMainFlavor(event->mimeData(), *theItr)) {
+ CDropSource *theDropSource = GetDropSource(event->mimeData(), *theItr, theIndex);
+ if (theDropSource) {
+ CPt thePoint(event->pos());
+ theModifyerFlags = CHotKeys::GetCurrentKeyModifiers();
+ theDropSource->SetCurrentPoint(thePoint);
+ theDropSource->SetCurrentFlags(theModifyerFlags);
+
+ theDropSource->InterpretKeyFlags(theModifyerFlags);
+ // This will be implemented in the cross platform code.
+ theAcceptFlag = m_Parent->OnDragWithin(*theDropSource);
+ event->setAccepted(theAcceptFlag);
+ if (theAcceptFlag) {
+ if (theDropSource->CanCopy())
+ event->setDropAction(Qt::CopyAction);
+ else
+ event->setDropAction(Qt::MoveAction);
+ // Breakout of the outer loop.
+ theIndex = theCount;
+ }
+
+ // delete the drop source if it was a file
+ if (EUIC_FLAVOR_FILE == theDropSource->GetFlavor()) {
+ delete theDropSource;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Called when an OLE item is dropped on this window.
+ * @return TRUE if the drop was valid, otherwise FALSE
+ */
+void CDropProxy::dropEvent(QDropEvent *event)
+{
+ if (m_Parent) {
+ long theCount = GetDragItemCount(event->mimeData());
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ Qt::KeyboardModifiers theModifyerFlags = ReflectMouse(event->pos().x(), event->pos().y());
+
+ theModifyerFlags = CHotKeys::GetCurrentKeyModifiers();
+
+ CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin();
+ CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd();
+
+ for (; theItr != theEnd; ++theItr) {
+ // Find the Flavor of this Item.
+ if (HasMainFlavor(event->mimeData(), *theItr)) {
+ // This will convert all stuff into a DropSource
+ CDropSource *theDropSource = GetDropSource(event->mimeData(), *theItr, theIndex);
+
+ // This will be implemented in the cross platform code.
+ if (theDropSource) {
+ CPt thePoint(event->pos());
+ theDropSource->SetCurrentPoint(thePoint);
+ theDropSource->SetCurrentFlags(theModifyerFlags);
+
+ // Don't call the recieve if we did not have a valid droptarget to begin
+ // with.
+ if (theDropSource->GetHasValidTarget()) {
+ theDropSource->InterpretKeyFlags(theModifyerFlags);
+ // This will be implemented in the cross platform code.
+ m_Parent->OnDragReceive(*theDropSource);
+ }
+ }
+
+ // Don't delete the drop source here, the creator will destroy it
+ // delete theDropSource;
+ }
+ }
+ }
+ }
+
+ event->accept();
+}
+//===============================================================================
+/**
+ * This function is used to report back to the container where the mouse is during a drag.
+ * The container can send this to children as MouseOvers so the children can do mouseover
+ *things.
+ * @param inX the X position
+ * @param inY the Y position.
+ * @return the Key modifyers.
+ */
+Qt::KeyboardModifiers CDropProxy::ReflectMouse(long inX, long inY)
+{
+ Qt::KeyboardModifiers theModifierFlags = Qt::NoModifier;
+
+ if (m_Parent) {
+ // Get the mouse stuff
+ CPt theMouseLoc(inX, inY);
+
+ // Determine which modifier keys are down so that we can pass them along
+
+ theModifierFlags = CHotKeys::GetCurrentKeyModifiers();
+
+ // Pass the gesture into the studio control
+ m_Parent->OnReflectMouse(theMouseLoc, theModifierFlags);
+ }
+ return theModifierFlags;
+}
+
+void CDropProxy::Register(QWidget *widget)
+{
+ widget->installEventFilter(this);
+ widget->setAcceptDrops(true);
+}
+
+bool CDropProxy::eventFilter(QObject *watched, QEvent *event)
+{
+ Q_UNUSED(watched);
+
+ switch (event->type()) {
+ case QEvent::DragEnter:
+ dragEnterEvent(static_cast<QDragEnterEvent *>(event));
+ return event->isAccepted();
+ case QEvent::DragLeave:
+ dragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
+ return event->isAccepted();
+ case QEvent::DragMove:
+ dragMoveEvent(static_cast<QDragMoveEvent *>(event));
+ return event->isAccepted();
+ case QEvent::Drop:
+ dropEvent(static_cast<QDropEvent *>(event));
+ return event->isAccepted();
+ default:
+ return false;
+ }
+}
diff --git a/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h
new file mode 100644
index 00000000..eadb9b83
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_DROP_PROXY
+#define INCLUDED_DROP_PROXY 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <QObject>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+class CDropContainer;
+class CStudioApp;
+class CDropSource;
+
+class QDragEnterEvent;
+class QDragLeaveEvent;
+class QDragMoveEvent;
+class QDropEvent;
+class QMimeData;
+
+class CDropProxy : public QObject
+{
+ Q_OBJECT
+public:
+ CDropProxy(CDropContainer *inParent);
+ virtual ~CDropProxy();
+
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dropEvent(QDropEvent *event);
+
+ CDropSource *GetDropSource(const QMimeData *inDataObject, long inFlavor, long inItem);
+ long GetDragItemCount(const QMimeData *inDataObject);
+ bool HasMainFlavor(const QMimeData *inDataObject, long inFlavor);
+ Qt::KeyboardModifiers ReflectMouse(long inX, long inY);
+
+ void Register(QWidget* widget);
+
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+protected:
+ CDropContainer *m_Parent;
+};
+
+#endif // INCLUDED_DROP_PROXY
diff --git a/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp
new file mode 100644
index 00000000..d6216200
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "WinDnd.h"
+#include "DropSource.h"
+
+//===============================================================================
+/**
+ * Constructor
+ */
+CWinDragManager::CWinDragManager()
+{
+ memset(&m_DragItem, 0, sizeof(SDropItem));
+}
+
+//===============================================================================
+/**
+ * Dtor
+ */
+CWinDragManager::~CWinDragManager()
+{
+}
+
+//===============================================================================
+/**
+ * This will take any data flavor and wrap it up into out drag data.
+ */
+void CWinDragManager::AddData(long inFlavor, void *inData, unsigned long inSize)
+{
+ m_DragItem.m_Flavor = inFlavor;
+ m_DragItem.m_Data = inData;
+ m_DragItem.m_Size = inSize;
+}
+
+//===============================================================================
+/**
+ * I made this so it would kind of match the MAC version.
+ */
+void CWinDragManager::StartDrag()
+{
+ Track();
+}
+
+//===============================================================================
+/**
+ * This is the Blocking function that does the Dragging.
+ * It is assumed that all of the Data is is requested to be dragged, is already in the list
+ * and we take it out of the list and pack it into the Win OLEDropSource and let it go.
+ * We should only return when the whole operation is over.
+ */
+void CWinDragManager::Track()
+{
+ // Convert our data into a OLE DragSource.
+ HGLOBAL theGlobalData = nullptr;
+ COleDataSource theDataSource;
+
+ // Empty the data source
+ theDataSource.Empty();
+
+ // long theDataSize = m_DragItem.m_Size;
+ void *theData = m_DragItem.m_Data;
+ long theFlavor = m_DragItem.m_Flavor;
+
+ // if ( theDataSize > 0 )
+ {
+ // Allocate a global block of data
+ DWORD theGlobalObjectSize = sizeof(CDropSource *);//sizeof(long /*theDataSize*/);
+ theGlobalData = GlobalAlloc(GHND, theGlobalObjectSize);
+
+ // Lock down the global memory object for copying data
+ CDropSource *theDropSource = reinterpret_cast<CDropSource *>(GlobalLock(theGlobalData));
+
+ // Copy the CDropSource pointer
+ CopyMemory(theDropSource, theData, theGlobalObjectSize);
+
+ // Unlock, but do not free
+ GlobalUnlock(theGlobalData);
+
+ // Prepare OLE data for transfer
+ theDataSource.CacheGlobalData((CLIPFORMAT)theFlavor, theGlobalData, nullptr);
+ }
+
+ // This will go through the framework.
+ if (DROPEFFECT_NONE == theDataSource.DoDragDrop()) {
+ theDataSource.Empty();
+ if (theGlobalData)
+ ::GlobalFree(theGlobalData);
+ }
+}
diff --git a/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h
new file mode 100644
index 00000000..8af759c7
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifndef INCLUDED_WINDND
+#define INCLUDED_WINDND
+
+#include <map>
+
+typedef struct _SDropItem
+{
+ long m_Flavor; // The Type of Data.
+ void *m_Data; ///< A nullptr value will cause the Data to be created Later on ( Promise )
+ unsigned long m_Size; //< The size of the Data.
+} SDropItem;
+
+//=============================================================================
+/**
+ * This class only supports dragging one item.
+ */
+class CWinDragManager
+{
+protected:
+ SDropItem m_DragItem; ///< the dragged item
+
+public:
+ CWinDragManager();
+ virtual ~CWinDragManager();
+
+ void Track();
+ void StartDrag();
+
+ void AddData(long inFlavor, void *inData, unsigned long inSize);
+};
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h b/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h
new file mode 100644
index 00000000..114e3bf8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PREFIX_WIN_32_H
+#define INCLUDED_STUDIO_PREFIX_WIN_32_H 1
+
+#pragma once
+
+#define AK_LITTLE_ENDIAN
+//#define WIN32
+
+#include <float.h>
+
+#endif // INCLUDED_STUDIO_PREFIX_WIN_32_H
diff --git a/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp b/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp
new file mode 100644
index 00000000..41f0fe42
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp
@@ -0,0 +1,902 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PaletteManager.h"
+#include "StudioApp.h"
+#include "Views.h"
+#include "MainFrm.h"
+#include "StringLoader.h"
+#include "TimelineControl.h"
+#include "BasicObjectsView.h"
+#include "SlideView.h"
+#include "StringTokenizer.h"
+#include "Preferences.h"
+#include "WidgetControl.h"
+#include "InspectorControlView.h"
+#include "ActionView.h"
+#include "IDragable.h"
+#include "ActionView.h"
+#include "ProjectView.h"
+#include "TabOrderHandler.h"
+
+#include <QDockWidget>
+
+//==============================================================================
+/**
+ * Class for std::for_each to delete each control
+ */
+template <class T>
+class CDeleteAll
+{
+public:
+ void operator()(const T *inControl) const { delete inControl; }
+};
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CPaletteManager::CPaletteManager(CMainFrame *inMainFrame)
+ : m_MainFrame(inMainFrame)
+{
+ // Position tabs to the right
+ inMainFrame->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::East);
+
+ QDockWidget *basicObjectsDock = new QDockWidget(QObject::tr("Basic Objects"), inMainFrame);
+ basicObjectsDock->setObjectName("basic_objects");
+ basicObjectsDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto basicObjectsView = new BasicObjectsView(basicObjectsDock);
+ basicObjectsDock->setWidget(basicObjectsView);
+ inMainFrame->addDockWidget(Qt::RightDockWidgetArea, basicObjectsDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_BASICOBJECTS, basicObjectsDock));
+
+ QDockWidget *projectDock = new QDockWidget(QObject::tr("Project"), inMainFrame);
+ projectDock->setObjectName("project");
+ projectDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto projectView = new ProjectView(projectDock);
+ projectDock->setWidget(projectView);
+ inMainFrame->addDockWidget(Qt::RightDockWidgetArea, projectDock);
+ inMainFrame->tabifyDockWidget(basicObjectsDock, projectDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_PROJECT, projectDock));
+
+ QDockWidget *slideDock = new QDockWidget(QObject::tr("Slide"), inMainFrame);
+ slideDock->setObjectName("slide");
+ slideDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ auto slideView = new SlideView(slideDock);
+ slideDock->setWidget(slideView);
+ inMainFrame->addDockWidget(Qt::LeftDockWidgetArea, slideDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_SLIDE, slideDock));
+
+ QDockWidget *timelineDock = new QDockWidget(QObject::tr("Timeline"), inMainFrame);
+ timelineDock->setObjectName("timeline");
+ timelineDock->setAllowedAreas(Qt::BottomDockWidgetArea);
+ auto c = new CTimelineControl();
+ auto w = new WidgetControl(c, timelineDock);
+ timelineDock->setWidget(w);
+ w->setMinimumWidth(500);
+ inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, timelineDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_TIMELINE, timelineDock));
+
+ int actionViewMinWidth = CStudioPreferences::valueWidth()
+ + CStudioPreferences::idWidth() + 40; // 40 added to accommodate tabs
+
+ QDockWidget *actionDock = new QDockWidget(QObject::tr("Action"), inMainFrame);
+ actionDock->setObjectName("action");
+ actionDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto actionView = new ActionView(actionDock);
+ actionDock->setWidget(actionView);
+ actionView->setMinimumWidth(actionViewMinWidth);
+ inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, actionDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_ACTION, actionDock));
+
+ QDockWidget *inspectorDock = new QDockWidget(QObject::tr("Inspector Control"), inMainFrame);
+ inspectorDock->setObjectName("inspector_control");
+ inspectorDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto inspectorView = new InspectorControlView(inspectorDock);
+ inspectorDock->setWidget(inspectorView);
+ inspectorView->setMinimumWidth(actionViewMinWidth); // Same min size as action view
+ inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, inspectorDock);
+ inMainFrame->tabifyDockWidget(actionDock, inspectorDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_INSPECTOR, inspectorDock));
+
+ w->RegiserForDnd(w);
+ w->AddMainFlavor(EUIC_FLAVOR_LISTBOX);
+ w->AddMainFlavor(EUIC_FLAVOR_FILE);
+ w->AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE);
+ w->AddMainFlavor(EUIC_FLAVOR_ASSET_LIB);
+ w->AddMainFlavor(EUIC_FLAVOR_ASSET_TL);
+ w->AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS);
+
+ // Set to a default state
+ Reset();
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CPaletteManager::~CPaletteManager()
+{
+ TControlMap::iterator theIterator = m_ControlList.begin();
+ TControlMap::iterator theEndIterator = m_ControlList.end();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ for (; theIterator != theEndIterator; ++theIterator) {
+ // Remove the palette from the old master
+ long theType = theIterator->first;
+ CMasterControl *theOldMaster = FindMasterPalette(theType);
+ if (theOldMaster)
+ RemoveControlFromMaster(theOldMaster, theType);
+ }
+ std::for_each(m_PaletteList.begin(), m_PaletteList.end(), CDeleteAll<CStudioPaletteBar>());
+#endif
+ // Delete all the controls
+ for (theIterator = m_ControlList.begin(); theIterator != theEndIterator; ++theIterator)
+ delete theIterator->second;
+}
+
+//==============================================================================
+/**
+ * Clear out old lists and reset all the palettes
+ */
+void CPaletteManager::Reset()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set the visible state to false
+ TControlMap::iterator theIterator = m_ControlList.begin();
+ TControlMap::iterator theEndIterator = m_ControlList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ CControl *theControl = theIterator->second;
+ if (theControl)
+ theControl->SetVisible(false);
+ }
+
+ // Undock all palette
+ TPaletteList::iterator thePaletteIterator = m_PaletteList.begin();
+ for (; thePaletteIterator != m_PaletteList.end(); ++thePaletteIterator) {
+ CStudioPaletteBar *thePaletteBar = (*thePaletteIterator);
+ thePaletteBar->ShowPalette(false);
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Create a palette
+ */
+CStudioPaletteBar *CPaletteManager::CreatePalette()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Build the create context
+ CCreateContext theCreateContext;
+ memset(&theCreateContext, 0, sizeof(CCreateContext));
+ theCreateContext.m_pNewViewClass = RUNTIME_CLASS(CMasterView);
+ theCreateContext.m_pCurrentFrame = m_MainFrame;
+
+ // Create the palette bar
+ CStudioPaletteBar *thePaletteBar = new CStudioPaletteBar;
+ thePaletteBar->Create(::CString("<empty>"), &theCreateContext, GetUniquePaletteId(),
+ m_MainFrame);
+
+ // Set the provider
+ CMasterView *theMasterView = (CMasterView *)thePaletteBar->GetView();
+ theMasterView->SetProvider(this);
+
+ // Must occur after the provider is set
+ thePaletteBar->InitialUpdate();
+
+ // Save the palette
+ ASSERT(thePaletteBar != nullptr);
+ m_PaletteList.push_back(thePaletteBar);
+
+ // Store the information
+ TSMasterInfo theInfo;
+ theInfo.m_Master = theMasterView->GetMasterControl();
+ theInfo.m_PaletteBar = thePaletteBar;
+
+ ASSERT(theInfo.m_PaletteBar != nullptr);
+ m_MasterList.push_back(theInfo);
+
+ return thePaletteBar;
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Find a master control with no contained controls
+ */
+CMasterControl *CPaletteManager::FindUnusedMaster()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Palettes.any() == false)
+ return theIterator->m_Master;
+ }
+#endif
+
+ return nullptr;
+}
+
+CMasterControl *CPaletteManager::FindMasterByPaletteId(long inPaletteId)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ CControlBarInfo theBarInfo;
+ theIterator->m_PaletteBar->GetBarInfo(&theBarInfo);
+
+ if (theBarInfo.m_nBarID == (UINT)inPaletteId)
+ return theIterator->m_Master;
+ }
+#endif
+ return nullptr;
+}
+
+CStudioPaletteBar *CPaletteManager::FindStudioPaletteBar(long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Palettes[inType] == true)
+ return theIterator->m_PaletteBar;
+ }
+#endif
+ return nullptr;
+}
+
+CStudioPaletteBar *CPaletteManager::FindStudioPaletteBar(CMasterControl *inMaster)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Master == inMaster)
+ return theIterator->m_PaletteBar;
+ }
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Add a new master to the list of masters
+ */
+CMasterControl *CPaletteManager::AddMasterPalette(long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Remove the palette from the old master
+ CMasterControl *theOldMaster = FindMasterPalette(inType);
+ if (theOldMaster)
+ RemoveControlFromMaster(theOldMaster, inType);
+
+ // Create a new master
+ CMasterControl *theMasterControl = FindUnusedMaster();
+ if (theMasterControl != nullptr) {
+ // Add the palette to the new master
+ AddControlToMaster(theMasterControl, inType);
+ }
+
+ return theMasterControl;
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Add the specified palette to the specified master
+ */
+void CPaletteManager::AddControlToMaster(CMasterControl *inMaster, long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Make sure this is a valid type ( for backward compatibility )
+ TControlMap::iterator theControlIterator = m_ControlList.find(inType);
+ if (theControlIterator != m_ControlList.end()) {
+ // Make sure the palette is not already on another master
+ CMasterControl *theOldMaster = FindMasterPalette(inType);
+ if (theOldMaster)
+ RemoveControlFromMaster(theOldMaster, inType);
+
+ // Add the palette to this master
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ for (; theIterator != m_MasterList.end(); ++theIterator) {
+ if (theIterator->m_Master == inMaster) {
+ theIterator->m_Palettes[inType] = true;
+ theIterator->m_Master->AddControl(GetControlName(inType), inType,
+ theControlIterator->second);
+ theIterator->m_Master->Invalidate();
+ break;
+ }
+ }
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Remove the specified palette from the specified master
+ */
+void CPaletteManager::RemoveControlFromMaster(CMasterControl *inMaster, long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ for (; theIterator != m_MasterList.end(); ++theIterator) {
+ if (theIterator->m_Master == inMaster) {
+ theIterator->m_Palettes[inType] = false;
+ theIterator->m_Master->RemoveControl(GetControl(inType));
+ theIterator->m_Master->Invalidate();
+ }
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Find the name of the master that contains this palette
+ */
+CMasterControl *CPaletteManager::FindMasterPalette(long inType)
+{
+ CMasterControl *theMaster = nullptr;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Palettes[inType] == true) {
+ theMaster = theIterator->m_Master;
+ break;
+ }
+ }
+#endif
+ return theMaster;
+}
+
+//==============================================================================
+/**
+ * Query the number of masters
+ */
+long CPaletteManager::GetMasterCount()
+{
+ return (long)m_MasterList.size();
+}
+
+//==============================================================================
+/**
+ * Get the master at the specified index
+ */
+CMasterControl *CPaletteManager::GetMaster(long inIndex)
+{
+ CMasterControl *theControl = nullptr;
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ std::advance(theIterator, inIndex);
+ if (theIterator != m_MasterList.end())
+ theControl = theIterator->m_Master;
+#endif
+ return theControl;
+}
+
+//=============================================================================
+/**
+ * Force a control to become invisible
+ */
+void CPaletteManager::HideControl(long inType)
+{
+ auto dock = GetControl(inType);
+
+ if (dock) {
+ // Make sure the control is invisible
+ dock->setVisible(false);
+ }
+}
+//=============================================================================
+/**
+ * Detemine if a control is currently visible
+ */
+bool CPaletteManager::IsControlVisible(long inType) const
+{
+ auto dock = GetControl(inType);
+ return dock && dock->isVisible();
+}
+
+//=============================================================================
+/**
+ * Force a control to become visible
+ */
+void CPaletteManager::ShowControl(long inType)
+{
+ auto dock = GetControl(inType);
+
+ if (dock) {
+ // Make sure the control is visible
+ dock->setVisible(true);
+ dock->setFocus();
+ }
+}
+
+//=============================================================================
+/**
+ * Flip the visible state of a control
+ */
+void CPaletteManager::ToggleControl(long inType)
+{
+ if (IsControlVisible(inType))
+ HideControl(inType);
+ else
+ ShowControl(inType);
+}
+
+//==============================================================================
+/**
+ * Return the Control (Palette) according to its EControlTypes enum.
+ * @param inType EControlTypes
+ */
+QDockWidget *CPaletteManager::GetControl(long inType) const
+{
+ auto dock = m_ControlList.find(inType);
+ if (dock != m_ControlList.end() && dock->second)
+ return dock->second;
+ else
+ return nullptr;
+}
+
+QWidget *CPaletteManager::getFocusWidget() const
+{
+ TControlMap::const_iterator end = m_ControlList.end();
+ for (TControlMap::const_iterator iter = m_ControlList.begin(); iter != end; ++iter) {
+ if (iter->second->widget()->hasFocus())
+ return iter->second->widget();
+ }
+ return nullptr;
+}
+
+bool CPaletteManager::tabNavigateFocusedWidget(bool tabForward)
+{
+ QWidget *palette = getFocusWidget();
+ if (palette) {
+ if (auto inspector = qobject_cast<InspectorControlView *>(palette)) {
+ inspector->tabOrderHandler()->tabNavigate(tabForward);
+ return true;
+ } else if (auto actionview = qobject_cast<ActionView *>(palette)) {
+ actionview->tabOrderHandler()->tabNavigate(tabForward);
+ return true;
+ }
+ }
+ return false;
+}
+
+//==============================================================================
+/**
+ * A helper for CMainFrame::GetTimelineControl() to access the CTimelineControl
+ * inside the QDockWidget
+ */
+CTimelineControl *CPaletteManager::GetTimelineControl() const
+{
+ auto dock = GetControl(CPaletteManager::CONTROLTYPE_TIMELINE);
+
+ if (dock) {
+ auto widget = static_cast<WidgetControl *>(dock->widget());
+
+ if (widget)
+ return static_cast<CTimelineControl *>(widget->getControl());
+ }
+
+ return nullptr;
+}
+
+//==============================================================================
+// Serialization
+//==============================================================================
+
+//==============================================================================
+/**
+ * Load the palette state from the registry
+ */
+bool CPaletteManager::Load()
+{
+ // Clear out existing local stuff
+ Reset();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Test the palette prefs, return false if they don't exist
+ if (CPreferences::GetUserPreferences().Exists(PALETTE_KEY) == false)
+ return false;
+
+ long theCurrentPalette = 0;
+ while (true) {
+ // Format the subkey name
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%ls%ld", PALETTE_SUBKEY, theCurrentPalette);
+
+ // Check to see if we should exit the for loop
+ CPreferences thePalettePrefs = CPreferences::GetUserPreferences(PALETTE_KEY);
+ if (thePalettePrefs.Exists(theSubKeyName) == false)
+ break;
+
+ // Format the subkey name
+ Q3DStudio::CString theFullKeyName;
+ theFullKeyName.Format(L"%ls\\%ls%ld", PALETTE_KEY, PALETTE_SUBKEY, theCurrentPalette);
+
+ // Grab the prefs
+ CPreferences thePrefs = CPreferences::GetUserPreferences(theFullKeyName);
+
+ // Default docking value
+ Q3DStudio::CString theDockString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_DOCKID, L"0"); // left
+ long theDockId = ::atol(theDockString.GetCharStar());
+
+ // Default Rect
+ QRect theWindowRect;
+ Q3DStudio::CString theRectString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_RECT, L"0,0,0,0");
+ CStringTokenizer theRectTokenizer(theRectString, L",");
+ for (long theIndex = 0; theRectTokenizer.HasNextPartition();
+ ++theRectTokenizer, ++theIndex) {
+ Q3DStudio::CString theCurrentString = theRectTokenizer.GetCurrentPartition();
+ long theCurrentItem = ::atol(theCurrentString.GetCharStar());
+
+ switch (theIndex) {
+ case 0:
+ theWindowRect.setLeft(theCurrentItem);
+ break;
+ case 1:
+ theWindowRect.setTop(theCurrentItem);
+ break;
+ case 2:
+ theWindowRect.setRight(theCurrentItem);
+ break;
+ case 3:
+ theWindowRect.setBottom(theCurrentItem);
+ break;
+ };
+ }
+
+ // Palette id
+ Q3DStudio::CString thePaletteIdString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_PALETTEID, L"0");
+ long thePaletteId = ::atol(thePaletteIdString.GetCharStar());
+
+ // Read the selected item
+ Q3DStudio::CString theSelectedString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_SELECTED, L"0");
+ long theSelectedType = ::atol(theSelectedString.GetCharStar());
+
+ // Grab the palette
+ CMasterControl *theMasterControl;
+ if (thePaletteId)
+ theMasterControl = FindMasterByPaletteId(thePaletteId);
+ else
+ theMasterControl = FindUnusedMaster();
+
+ if (theMasterControl != nullptr) {
+ CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(theMasterControl);
+
+ Q3DStudio::CString theContentString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_LIST, L"0");
+ CStringTokenizer theTokenizer(theContentString, L",");
+ for (; theTokenizer.HasNextPartition(); ++theTokenizer) {
+ Q3DStudio::CString theCurrentString = theTokenizer.GetCurrentPartition();
+ long theCurrentItem = ::atol(theCurrentString.GetCharStar());
+
+ if (theCurrentItem != CONTROLTYPE_NONE)
+ AddControlToMaster(theMasterControl, theCurrentItem);
+ }
+
+ // Dock the bar in the appropriate location (if requested)
+ if (theDockId != 0) {
+ CDockBar *theDockBar =
+ (CDockBar *)m_MainFrame->GetControlBar(theDockId + AFX_IDW_DOCKBAR_TOP);
+ theDockBar->ClientToScreen(theWindowRect);
+
+ thePaletteBar->SetHorz(CSize(theWindowRect.Width(), theWindowRect.Height()));
+ thePaletteBar->SetVert(CSize(theWindowRect.Width(), theWindowRect.Height()));
+
+ m_MainFrame->DockControlBar(thePaletteBar, theDockBar, theWindowRect);
+ m_MainFrame->RecalcLayout(TRUE);
+ }
+
+ // Select the old item
+ theMasterControl->SelectControl(theSelectedType);
+
+ // Turn on my heart light
+ thePaletteBar->ShowPalette(true);
+ }
+
+ // Move on to the next key
+ theCurrentPalette++;
+ }
+
+ if (m_MainFrame) {
+ // Allow the control bars (docking palettes, etc) the opportunity to restore
+ // This will use a registry key based off of AFX_IDS_APP_TITLE ("Qt 3D Studio") which
+ // is different than CPreferences (".../Qt 3D Studio/Settings/...")
+ CSizingControlBar::GlobalLoadState(m_MainFrame, PALETTE_LAYOUT_KEY_NAME);
+ m_MainFrame->LoadBarState(PALETTE_LAYOUT_KEY_NAME);
+ }
+#endif
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * Save the palette state to the registry
+ */
+void CPaletteManager::Save()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Destroy current information in the prefs
+ CPreferences theMasterPrefs = CPreferences::GetUserPreferences(PALETTE_KEY);
+ theMasterPrefs.Clear();
+
+ // Iterate through the m_MasterList
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (long theMasterIndex = 0; theIterator != theEndIterator; ++theIterator) {
+ TSMasterInfo &theMasterInfo = *theIterator;
+ if (theMasterInfo.m_PaletteBar->IsVisible()) {
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%ls\\%ls%ld", PALETTE_KEY, PALETTE_SUBKEY, theMasterIndex);
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences(theSubKeyName);
+
+ // Save palette contents
+ Q3DStudio::CString theTempString;
+ Q3DStudio::CString theContentString;
+ for (long theIndex = 0; theIndex < (long)theMasterInfo.m_Palettes.size(); ++theIndex) {
+ if (theMasterInfo.m_Palettes[theIndex]) {
+ theTempString.Format(L"%ld,", theIndex);
+ theContentString += theTempString;
+ }
+ }
+
+ thePrefs.SetStringValue(PALETTE_CONTROL_LIST, theContentString);
+
+ // Save palette id
+ CControlBarInfo theBarInfo;
+ theMasterInfo.m_PaletteBar->GetBarInfo(&theBarInfo);
+ theTempString.Format(L"%ld", theBarInfo.m_nBarID);
+ thePrefs.SetStringValue(PALETTE_CONTROL_PALETTEID, theTempString);
+
+ // Save selected item
+ long theSelectedIndex = theMasterInfo.m_Master->GetActiveIndex();
+ theTempString.Format(L"%ld", theSelectedIndex);
+ thePrefs.SetStringValue(PALETTE_CONTROL_SELECTED, theTempString);
+
+ // Default values
+ thePrefs.SetStringValue(PALETTE_CONTROL_DOCKID, L"0");
+ thePrefs.SetStringValue(PALETTE_CONTROL_RECT, L"0,0,0,0");
+
+ // Increment the palette counter
+ ++theMasterIndex;
+ }
+ }
+
+ // Allow the control bars (docking palettes, etc) the opportunity to store
+ // This will use a registry key based off of AFX_IDS_APP_TITLE ("Qt 3D Studio") which
+ // is different than CPreferences (".../Qt 3D Studio/Settings/...")
+ if (m_MainFrame) {
+ CSizingControlBar::GlobalSaveState(m_MainFrame, PALETTE_LAYOUT_KEY_NAME);
+ m_MainFrame->SaveBarState(PALETTE_LAYOUT_KEY_NAME);
+ }
+#endif
+}
+
+//==============================================================================
+// Defaults
+//==============================================================================
+
+//==============================================================================
+/**
+ * Set the palettes to the default state
+ *
+ * CONTROLTYPE_ACTION = 1, ///<
+ * CONTROLTYPE_BASICOBJECTS = 3, ///<
+ * CONTROLTYPE_INSPECTOR = 4, ///<
+ * CONTROLTYPE_SLIDE = 6, ///<
+ * CONTROLTYPE_TIMELINE = 7, ///<
+ * CONTROLTYPE_COMMAND = 8, ///<
+ * CONTROLTYPE_PROJECT = 9, ///<
+ *
+ * #define AFX_IDW_DOCKBAR_TOP 0xE81B = 0
+ * #define AFX_IDW_DOCKBAR_LEFT 0xE81C = 1
+ * #define AFX_IDW_DOCKBAR_RIGHT 0xE81D = 2
+ * #define AFX_IDW_DOCKBAR_BOTTOM 0xE81E = 3
+ * #define AFX_IDW_DOCKBAR_FLOAT 0xE81F = 4
+ */
+void CPaletteManager::RestoreDefaults(bool inForce)
+{
+ Q_UNUSED(inForce);
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Destroy current information in the prefs (Palettes)
+ CPreferences theMasterPrefs = CPreferences::GetUserPreferences(PALETTE_KEY);
+ theMasterPrefs.Clear();
+
+ // "3,9,2,5:0:2:0,0,300,250#4,1:0:2:0,251,300,601#6:0:1:0,0,125,125#7:0:3:0,0,250,300";
+ Q3DStudio::CString thePaletteString = ::LoadResourceString(IDS_DEFAULT_PALETTE_LAYOUT);
+ CStringTokenizer thePaletteTokenizer(thePaletteString, L"#");
+ for (long thePaletteIndex = 0; thePaletteTokenizer.HasNextPartition();
+ ++thePaletteTokenizer, ++thePaletteIndex) {
+ Q3DStudio::CString theCurrentPalette = thePaletteTokenizer.GetCurrentPartition();
+ CStringTokenizer theSubTokenizer(theCurrentPalette, L":");
+
+ // No error checking, this string better be right!
+ Q3DStudio::CString theControlList = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+ Q3DStudio::CString theSelectedControl = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+ Q3DStudio::CString theDockId = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+ Q3DStudio::CString theControlRect = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+
+ // Create the new registry keys (Palettes\PaletteN)
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%ls\\%s%ld", PALETTE_KEY, PALETTE_SUBKEY, thePaletteIndex);
+ CPreferences thePrefs = CPreferences::GetUserPreferences(theSubKeyName);
+
+ thePrefs.SetStringValue(PALETTE_CONTROL_LIST, theControlList);
+ thePrefs.SetStringValue(PALETTE_CONTROL_SELECTED, theSelectedControl);
+ thePrefs.SetStringValue(PALETTE_CONTROL_DOCKID, theDockId);
+ thePrefs.SetStringValue(PALETTE_CONTROL_RECT, theControlRect);
+ }
+#endif
+ // Load these items
+ Load();
+}
+
+//==============================================================================
+// Palette Context Menu
+//==============================================================================
+
+//=============================================================================
+/**
+ * Callback to create a new palette of the specified type.
+ */
+void CPaletteManager::OnNewPalette(CMasterControl *inMaster)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ ASSERT(inMaster != nullptr);
+
+ // Query the current control type
+ long theType = inMaster->GetActiveType();
+
+ // Add a new master with that control type
+ CMasterControl *theNewMaster = AddMasterPalette(theType);
+
+ // Float the new palette
+ CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(theNewMaster);
+ m_MainFrame->FloatControlBar(thePaletteBar, QPoint(0, 0));
+
+ // Turn on my heart light
+ thePaletteBar->ShowPalette(true);
+#endif
+}
+
+//=============================================================================
+/**
+ * Callback to move a control to the specified palette
+ */
+void CPaletteManager::OnMovePalette(CMasterControl *inMoveFromMaster,
+ CMasterControl *inMoveToMaster)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ ASSERT(inMoveFromMaster != nullptr);
+ ASSERT(inMoveToMaster != nullptr);
+
+ // Move the control to the new master
+ long theType = inMoveFromMaster->GetActiveType();
+ AddControlToMaster(inMoveToMaster, theType);
+
+ // Check to see if the master is empty
+ if (inMoveFromMaster->GetControlCount() <= 0) {
+ // Make sure the palette is visible
+ CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(inMoveFromMaster);
+ thePaletteBar->ShowPalette(false);
+ }
+#endif
+}
+
+//==============================================================================
+// IMasterControlProvider
+//==============================================================================
+
+void CPaletteManager::OnControlRemoved(CMasterControl *inMaster)
+{
+ (void)inMaster;
+}
+
+void CPaletteManager::OnContextMenu(CMasterControl *inMaster, const CPt &inPosition,
+ CContextMenu *inMyMenu)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CPaletteContextMenu theContextMenu(this, inMaster, inMyMenu);
+
+ // Popup the context menu
+ inMaster->DoPopup(&theContextMenu, inPosition);
+#endif
+}
+
+void CPaletteManager::OnControlSelected(CMasterControl *inMaster, CControl *, long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Q3DStudio::CString theControlName = GetControlName(inType);
+
+ CStudioPaletteBar *thePalette = FindStudioPaletteBar(inMaster);
+ ASSERT(thePalette != nullptr);
+
+ thePalette->SetWindowText(theControlName);
+#endif
+}
+
+//==============================================================================
+// Static Methods
+//==============================================================================
+
+//==============================================================================
+/**
+ * Query the name of the specified palette
+ */
+Q3DStudio::CString CPaletteManager::GetControlName(long inType)
+{
+ switch (inType) {
+ case CONTROLTYPE_ACTION:
+ return ::LoadResourceString(IDS_PALETTE_ACTION);
+ case CONTROLTYPE_BASICOBJECTS:
+ return ::LoadResourceString(IDS_PALETTE_BASIC_OBJECTS);
+ case CONTROLTYPE_INSPECTOR:
+ return ::LoadResourceString(IDS_PALETTE_INSPECTOR);
+ case CONTROLTYPE_SLIDE:
+ return ::LoadResourceString(IDS_PALETTE_SLIDE);
+ case CONTROLTYPE_TIMELINE:
+ return ::LoadResourceString(IDS_PALETTE_TIMELINE);
+ case CONTROLTYPE_PROJECT:
+ return ::LoadResourceString(IDS_PALETTE_PROJECT);
+ default:
+ return L"< Empty >";
+ };
+}
+
diff --git a/src/Authoring/Studio/_Win/Palettes/PaletteManager.h b/src/Authoring/Studio/_Win/Palettes/PaletteManager.h
new file mode 100644
index 00000000..e162e7f7
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/PaletteManager.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_VIEW_MANAGER_H
+#define INCLUDED_VIEW_MANAGER_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <bitset>
+#include "MasterControl.h"
+#include "TimelineControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+class CMainFrame;
+class CStudioPaletteBar;
+
+class QDockWidget;
+
+//==============================================================================
+/**
+ * @class CPaletteManager
+ */
+class CPaletteManager : public IMasterControlProvider
+{
+public:
+ // Do NOT change the order/values of this enum, these
+ // values are stored in the registry
+ enum EControlTypes {
+ CONTROLTYPE_NONE = 0, ///<
+ CONTROLTYPE_ACTION = 1, ///<
+ CONTROLTYPE_BASICOBJECTS = 3, ///<
+ CONTROLTYPE_INSPECTOR = 4, ///<
+ CONTROLTYPE_SLIDE = 6, ///<
+ CONTROLTYPE_TIMELINE = 7, ///<
+ CONTROLTYPE_PROJECT = 9, ///<
+
+ CONTROLTYPE_MAXCONTROLS = 32, ///< the maximum number of palettes( a string of this length
+ ///is saved in the registry, changing this value will require
+ ///an upgrade process )
+ };
+
+public:
+ typedef std::bitset<CONTROLTYPE_MAXCONTROLS> TPaletteSet;
+
+protected:
+ typedef struct _TSMasterInfo
+ {
+ CStudioPaletteBar *m_PaletteBar; ///< pointer to the master palette bar
+ TPaletteSet m_Palettes; ///< the palettes contained by the master
+ CMasterControl *m_Master; ///< pointer to the master control
+
+ } TSMasterInfo;
+
+ typedef std::map<long, QDockWidget *> TControlMap;
+ typedef std::vector<CStudioPaletteBar *> TPaletteList;
+ typedef std::vector<TSMasterInfo> TMasterList;
+
+protected:
+ CMainFrame *m_MainFrame; ///<
+ TControlMap m_ControlList; ///< map of EControlTypes and CControl
+ TPaletteList m_PaletteList; ///<
+ TMasterList m_MasterList; ///<
+
+ static long s_PaletteIDBase; ///<
+
+public:
+ CPaletteManager(CMainFrame *inMainFrame);
+ virtual ~CPaletteManager();
+
+ // Access
+ void AddControlToMaster(CMasterControl *inControl, long inType);
+ void RemoveControlFromMaster(CMasterControl *inControl, long inType);
+ CMasterControl *FindMasterPalette(long inType);
+ long GetMasterCount();
+ CMasterControl *GetMaster(long inIndex);
+ void HideControl(long inType);
+ bool IsControlVisible(long inType) const;
+ void ShowControl(long inType);
+ void ToggleControl(long inType);
+
+ QDockWidget *GetControl(long inType) const; ///< return corresponding Palette according to EControlTypes enum value
+ QWidget *getFocusWidget() const;
+ bool tabNavigateFocusedWidget(bool tabForward);
+ CTimelineControl *GetTimelineControl() const;
+
+ // Commands
+ void OnNewPalette(CMasterControl *inMaster);
+ void OnMovePalette(CMasterControl *inMoveFromMaster, CMasterControl *inMoveToMaster);
+
+ // Serialization
+ bool Load();
+ void Save();
+
+ // Defaults
+ void RestoreDefaults(bool inForce = false);
+
+ // IMasterControlProvider
+ void OnControlRemoved(CMasterControl *inControl) override;
+ void OnContextMenu(CMasterControl *inControl, const CPt &inPosition,
+ CContextMenu *inMyMenu) override;
+ void OnControlSelected(CMasterControl *inMaster, CControl *inNewControl, long inType) override;
+
+ // Static Methods
+ static Q3DStudio::CString GetControlName(long inType);
+
+protected:
+ CMasterControl *AddMasterPalette(long inType);
+
+ void Reset();
+ CStudioPaletteBar *CreatePalette();
+
+ CMasterControl *FindUnusedMaster();
+ CMasterControl *FindMasterByPaletteId(long inPaletteId);
+
+ CStudioPaletteBar *FindStudioPaletteBar(long inType);
+ CStudioPaletteBar *FindStudioPaletteBar(CMasterControl *inMaster);
+ void OnAsyncDestroyWindow(CStudioPaletteBar *inWnd);
+};
+
+#endif // INCLUDED_VIEW_MANAGER_H
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp
new file mode 100644
index 00000000..a9f1e546
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ProgressPalette.h"
+#include "StudioConst.h"
+#include "ResourceCache.h"
+#include "ResImage.h"
+#include "ProgressView.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CProgressPalette::CProgressPalette()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CProgressPalette::~CProgressPalette()
+{
+}
+
+//==============================================================================
+/**
+ * A wrapper around the CMiniFrameWnd::Create() method.
+ * Simplifies the create parameters for the palette bar. Overridden because
+ * the loading screen is different from all the other palettes.
+ * @return The result from the Create() call (FALSE if unsuccessful)
+ */
+BOOL CProgressPalette::Create(CString inTitle, CCreateContext *inCreateContext,
+ CWnd *inParent /* = nullptr */)
+{
+ CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_WAIT));
+ BOOL theReturnValue = FALSE;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Get the rectangle that we want this splash screen to occupy in the middle of the screen
+ CPt theScreenSize = ::GetAvailableDisplaySize();
+ CResImage *theImage = CResourceCache::GetInstance()->GetBitmap("progress-screen.png");
+ CPt theImageSize = theImage->GetSize();
+ long theTitleBarHeight = ::GetSystemMetrics(SM_CYCAPTION);
+ long theXPos = theScreenSize.x / 2 - theImageSize.x / 2;
+ long theYPos = theScreenSize.y / 2 - theImageSize.y / 2;
+ CRect theWindowRect(theXPos, theYPos, theXPos + theImageSize.x,
+ theYPos + theImageSize.y + theTitleBarHeight);
+
+ // Create the dialog.
+ theReturnValue = CFrameWnd::Create(theWndClass, inTitle, WS_POPUP | WS_CAPTION, theWindowRect,
+ inParent, nullptr, 0, inCreateContext);
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Sends a message to the view that the progress bar needs to be updated to a
+ * new percentage.
+ * @param inPercent New percent complete to be displayed
+ */
+void CProgressPalette::SetProgress(long inPercent)
+{
+ SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_PERCENT,
+ static_cast<LPARAM>(inPercent));
+ Invalidate();
+ UpdateWindow();
+}
+
+//==============================================================================
+/**
+ * Sends a message to the view that the action text (saving/loading) needs to be changed.
+ * @param inFileName New file name to be displayed
+ */
+void CProgressPalette::SetActionText(const Q3DStudio::CString &inText)
+{
+ SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_ACTIONTEXT,
+ reinterpret_cast<LPARAM>(&inText));
+}
+
+//==============================================================================
+/**
+ * Sends a message to the view that the file name being opened needs to be changed.
+ * @param inFileName New file name to be displayed
+ */
+void CProgressPalette::SetFileName(const Q3DStudio::CString &inFileName)
+{
+ SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_FILENAME,
+ reinterpret_cast<LPARAM>(&inFileName));
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h
new file mode 100644
index 00000000..7d7cb357
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROGRESS_PALETTE_H
+#define INCLUDED_PROGRESS_PALETTE_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPaletteBar.h"
+#include "ProgressCallback.h"
+
+//=============================================================================
+/**
+ * Palette for the loading screen
+ */
+class CProgressPalette : public CStudioDialog, public IProgressCallback
+{
+public:
+ CProgressPalette();
+ virtual ~CProgressPalette();
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *inParent = nullptr);
+ void SetProgress(long inPercent);
+ void SetFileName(const Q3DStudio::CString &inFileName);
+ void SetActionText(const Q3DStudio::CString &inText);
+};
+#endif // INCLUDED_PROGRESS_PALETTE_H \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp
new file mode 100644
index 00000000..8b7e796c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ProgressView.h"
+#include "WndControl.h"
+#include "StudioApp.h"
+#include "ProgressControl.h"
+
+//==============================================================================
+// Message Maps, etc.
+//==============================================================================
+IMPLEMENT_DYNCREATE(CProgressView, CView)
+
+BEGIN_MESSAGE_MAP(CProgressView, CView)
+//{{AFX_MSG_MAP(CProgressView)
+ON_WM_SIZE()
+ON_WM_ERASEBKGND()
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_STUDIO_INITIALIZE_PALETTES, OnInitializePalettes)
+ON_MESSAGE(WM_STUDIO_LOADPROGRESS, OnUpdateProgress)
+END_MESSAGE_MAP()
+
+//=============================================================================
+/**
+ * Constructor: Protected because the view is always created dynamically.
+ * You must call Initialize() before trying to use this class.
+ */
+CProgressView::CProgressView()
+ : m_WndControl(nullptr)
+ , m_ProgressControl(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CProgressView::~CProgressView()
+{
+ if (m_WndControl) {
+ m_WndControl->DestroyWindow();
+ m_WndControl = nullptr;
+
+ SAFE_DELETE(m_ProgressControl);
+ }
+}
+
+//==============================================================================
+/**
+ * Handles the WM_INITIALUPDATE message. Responsible for preparing the view
+ * before it is displayed for the first time.
+ */
+LRESULT CProgressView::OnInitializePalettes(WPARAM, LPARAM)
+{
+ if (!m_WndControl) {
+ m_ProgressControl = new CProgressControl;
+ m_WndControl = new CWndControl(m_ProgressControl);
+ m_ProgressControl->SetName("Progress Control");
+
+ if (!::IsWindow(m_WndControl->m_hWnd))
+ m_WndControl->CreateEx(0, AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(nullptr, IDC_WAIT),
+ (HBRUSH)GetStockObject(BLACK_BRUSH)),
+ L"LoadView", WS_CHILD | WS_VISIBLE | WS_MAXIMIZE,
+ CRect(0, 0, 200, 200), this, 100);
+ }
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Handles the WM_STUDIO_LOADPROGRESS message. Changes text displayed on the
+ * load control, depending on what we are trying to update.
+ * @param inwParam Should be an EProgressMessage to indicate what we are updating
+ * @param inlParam Depends on inwParam. If the message type is PROGRESSUPDATE_PERCENT,
+ * this parameter contains a long value indicating the percent. If the message
+ * type is PROGRESSUPDATE_FILENAME, this parameter contains a pointer to an
+ * Q3DStudio::CString, which is the name of the file that we are loading.
+ * @return 0
+ */
+LRESULT CProgressView::OnUpdateProgress(WPARAM inwParam, LPARAM inlParam)
+{
+ EProgressMessage theMessageType = static_cast<EProgressMessage>(inwParam);
+
+ switch (theMessageType) {
+ // Update the percentage completed
+ case PROGRESSUPDATE_PERCENT: {
+ long thePercent = (long)inlParam;
+ m_ProgressControl->SetProgress(thePercent);
+ } break;
+
+ // Update the name of the file being loaded
+ case PROGRESSUPDATE_FILENAME: {
+ Q3DStudio::CString *theName = reinterpret_cast<Q3DStudio::CString *>(inlParam);
+ m_ProgressControl->SetFileName(*theName);
+ } break;
+
+ // Update the text above the file name (loading or saving)
+ case PROGRESSUPDATE_ACTIONTEXT: {
+ Q3DStudio::CString *theText = reinterpret_cast<Q3DStudio::CString *>(inlParam);
+ m_ProgressControl->SetActionText(*theText);
+ } break;
+
+ // Nothing to do in the default case
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Required by base class but does nothing since all drawing is handled by the
+ * child control.
+ */
+void CProgressView::OnDraw(CDC *inDC)
+{
+ Q_UNUSED(inDC);
+}
+
+//=============================================================================
+/**
+ * Resizes the wnd control to fill the whole view.
+ */
+void CProgressView::OnSize(UINT inType, int inX, int inY)
+{
+ CView::OnSize(inType, inX, inY);
+ if (::IsWindow(m_WndControl->GetSafeHwnd()))
+ m_WndControl->MoveWindow(0, 0, inX, inY);
+}
+
+//==============================================================================
+/**
+ * Tells the view to erase before redrawing. Overridden because erasing
+ * before each draw produces a flashing effect.
+ * @param inDC the DC to erase on.
+ * @return FALSE.
+ */
+BOOL CProgressView::OnEraseBkgnd(CDC *inDC)
+{
+ Q_UNUSED(inDC);
+ return FALSE;
+}
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h
new file mode 100644
index 00000000..ed023c0c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROGRESS_VIEW_H
+#define INCLUDED_PROGRESS_VIEW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CWndControl;
+class CProgressControl;
+class CStudioApp;
+
+//=============================================================================
+/**
+ * Windows view encapsulating the splash screen.
+ */
+class CProgressView : public CView
+{
+public:
+ /// Used to pass messages from the palette, down to this view
+ enum EProgressMessage {
+ PROGRESSUPDATE_PERCENT = 0, ///< Inidicates that the percentage displayed should be updated
+ PROGRESSUPDATE_FILENAME, ///< Indicates that the file name displayed should be updated
+ PROGRESSUPDATE_ACTIONTEXT, ///< Indicates that the text above the file name needs to be
+ ///updated
+ };
+
+ virtual void OnDraw(CDC *inDC);
+ virtual LRESULT OnInitializePalettes(WPARAM inwParam, LPARAM inlParam);
+ virtual LRESULT OnUpdateProgress(WPARAM inwParam, LPARAM inlParam);
+
+protected:
+ CWndControl *m_WndControl;
+ CProgressControl *m_ProgressControl;
+
+ CProgressView(); ///< Constructor is protected because you can only create this view dynamically
+ DECLARE_DYNCREATE(CProgressView)
+ virtual ~CProgressView();
+ afx_msg void OnSize(UINT inType, int inX, int inY);
+ afx_msg BOOL OnEraseBkgnd(CDC *inDC);
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // INCLUDED_PROGRESS_VIEW_H \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp
new file mode 100644
index 00000000..112631e6
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SplashPalette.h"
+#include "SplashControl.h" // Just for getting the control's size; the view owns the real splash control
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CSplashPalette::CSplashPalette()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSplashPalette::~CSplashPalette()
+{
+}
+
+//==============================================================================
+/**
+ * A wrapper around the CMiniFrameWnd::Create() method.
+ * Simplifies the create parameters for the palette bar. Overridden because
+ * the splash screen is different from all the other palettes.
+ * @return The result from the Create() call (FALSE if unsuccessful)
+ */
+BOOL CSplashPalette::Create(CString inTitle, CCreateContext *inCreateContext,
+ CWnd *inParent /* = nullptr */)
+{
+ CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_ARROW));
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Get the rectangle that we want this splash screen to occupy in the middle of the screen
+ CPt theScreenSize = GetAvailableDisplaySize();
+ CSplashControl theSplashControl; // Just for getting the control's size; the view owns the real
+ // splash control
+ CPt theImageSize = theSplashControl.GetSize();
+ long theXPos = theScreenSize.x / 2 - theImageSize.x / 2;
+ long theYPos = theScreenSize.y / 2 - theImageSize.y / 2;
+ CRect theWindowRect(theXPos, theYPos, theXPos + theImageSize.x, theYPos + theImageSize.y);
+
+ // Create the dialog.
+ DWORD theFlags;
+#ifdef DEBUG
+ theFlags = WS_EX_TOOLWINDOW;
+#else
+ theFlags = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
+#endif
+ // Create the palette bar.
+ theReturnValue = CFrameWnd::CreateEx(theFlags, theWndClass, inTitle, WS_POPUP, theWindowRect,
+ inParent, 0, inCreateContext);
+
+ return theReturnValue;
+}
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h
new file mode 100644
index 00000000..5f11af0c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SPLASH_PALETTE_H
+#define INCLUDED_SPLASH_PALETTE_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPaletteBar.h"
+
+//=============================================================================
+/**
+ * Palette for the splash screen
+ */
+class CSplashPalette : public CStudioDialog /*CStudioPaletteBar*/
+{
+public:
+ CSplashPalette();
+ virtual ~CSplashPalette();
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *inParent = nullptr);
+};
+#endif // INCLUDED_SPLASH_PALETTE_H \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp
new file mode 100644
index 00000000..fd78e604
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SplashView.h"
+#include "WidgetControl.h"
+#include "StudioApp.h"
+#include "SplashControl.h"
+
+//=============================================================================
+/**
+ * Constructor: Protected because the view is always created dynamically.
+ * You must call Initialize() before trying to use this class.
+ */
+CSplashView::CSplashView(QWidget *parent)
+ : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint)
+ , m_WndControl(nullptr)
+ , m_SplashControl(nullptr)
+{
+ OnInitializePalettes();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSplashView::~CSplashView()
+{
+ delete m_WndControl;
+ m_WndControl = nullptr;
+
+ delete m_SplashControl;
+}
+
+//==============================================================================
+/**
+ * Handles the WM_INITIALUPDATE message. Responsible for preparing the view
+ * before it is displayed for the first time.
+ */
+void CSplashView::OnInitializePalettes()
+{
+ if (!m_WndControl) {
+ m_SplashControl = new CSplashControl;
+ m_WndControl = new WidgetControl(m_SplashControl, this);
+ m_SplashControl->SetName("Splash Control");
+
+ setFixedSize(m_WndControl->sizeHint());
+ }
+}
+
+//=============================================================================
+/**
+ * Resizes the wnd control to fill the whole view.
+ */
+void CSplashView::resizeEvent(QResizeEvent *event)
+{
+ Q_UNUSED(event);
+ m_WndControl->setGeometry(rect());
+}
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h
new file mode 100644
index 00000000..28498e95
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SPLASH_VIEW_H
+#define INCLUDED_SPLASH_VIEW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QWidget>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class WidgetControl;
+class CSplashControl;
+
+//=============================================================================
+/**
+ * Windows view encapsulating the splash screen.
+ */
+class CSplashView : public QWidget
+{
+public:
+ explicit CSplashView(QWidget *parent = nullptr);
+ ~CSplashView();
+
+protected:
+ void resizeEvent(QResizeEvent *event) override;
+
+public:
+ void OnInitializePalettes();
+
+protected:
+ WidgetControl *m_WndControl;
+ CSplashControl *m_SplashControl;
+};
+
+#endif // INCLUDED_SPLASH_VIEW_H
diff --git a/src/Authoring/Studio/_Win/Studio/stdafx.cpp b/src/Authoring/Studio/_Win/Studio/stdafx.cpp
new file mode 100644
index 00000000..b6cac561
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Studio/stdafx.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// Studio.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h" \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Studio/stdafx.h b/src/Authoring/Studio/_Win/Studio/stdafx.h
new file mode 100644
index 00000000..8fb2d134
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Studio/stdafx.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef __cplusplus
+#pragma once
+
+#pragma warning(disable : 4819)
+
+#include "UICMacros.h"
+
+//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define VC_EXTRALEAN // Exclude morerarely-used stuff from Windows headers
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+#define _AFX_ALL_WARNINGS // turns off MFC's hiding of some common and often safely ignored warning
+ // messages
+
+#ifdef DEBUG
+#define CHECK_BOUNDS // CHECK_BOUNDS affects the way an item is retrieved from container objects
+#endif
+
+#if _MSC_VER >= 1400
+#if defined _M_IX86
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+//==============================================================================
+// Standard Includes
+//==============================================================================
+#include <stdio.h> // Standard includes MUST come first
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+//==============================================================================
+// STL Includes
+//==============================================================================
+#pragma warning(push, 3) // Temporarily pop to warning level 3 while including standard headers
+#pragma warning(disable : 4018) // Disable mismatched < STL warning
+#include <vector>
+#include <map>
+#include <deque>
+#include <string>
+#include <stack>
+#include <set>
+#include <list>
+#include <utility>
+#include <algorithm>
+#include <stdexcept>
+#include <limits>
+#pragma warning(pop) // Pop out to previous warning level (probably level 4)
+
+//==============================================================================
+// MFC Includes
+//==============================================================================
+#pragma warning(push, 1)
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdisp.h> // MFC Automation classes
+#include <afxpriv.h> // AFX Windows Messages (WM_INITIALUPDATE for example)
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#include <atlbase.h>
+#include <atlcom.h>
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+//==============================================================================
+// ATL Includes
+//==============================================================================
+#include "atlbase.h" // For CrystalEdit
+#include "afxtempl.h" // For CrystalEdit
+#include "afxole.h" // For CrystalEdit
+#pragma warning(pop)
+
+// I put these in to help with some of the data model compile times.
+#pragma warning(push)
+#pragma warning(disable : 4100)
+#pragma warning(disable : 4512)
+#pragma warning(disable : 4702)
+#pragma warning(disable : 4996)
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/variant.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/signals.hpp>
+#include <boost/signals/connection.hpp>
+#pragma warning(pop)
+
+//==============================================================================
+// Disable certain warnings since warnings are errors
+//==============================================================================
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#pragma warning(disable : 4702) // Unreachable code
+#pragma warning(disable : 4290) // C++ Exception Specification ignored
+#pragma warning(disable : 4514) // Unreferenced inline function
+#pragma warning(disable : 4121) // Alignment of member sensative to packing
+#pragma warning(disable : 4512) // Assignment not generated
+#pragma warning(disable : 4355) // This used in member initializer list.
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4189) // local variable is initialized but not referenced
+
+//==============================================================================
+// Common Includes
+//==============================================================================
+#include "GUIDUtilities.h"
+#include "UICId.h"
+
+//==============================================================================
+// Application Includes (Aug '08 accumulated most popular include files)
+//==============================================================================
+#include "UICString.h"
+#include "UICMath.h"
+#include "StringLoader.h"
+#include "StudioException.h"
+#include "UICExceptions.h"
+#include "Exceptions.h"
+#include "UICObjectCounter.h"
+#include "STLHelpers.h"
+#include "Pt.h"
+#include "Rct.h"
+#include "SafeArray.h"
+#include "PlatformMacros.h"
+#include "PlatformTypes.h"
+#include "Multicaster.h"
+#include "GenericFunctor.h"
+#include "CColor.h"
+#include "InputStream.h"
+#include "OutputStream.h"
+#include "StudioUtils.h"
+#include "StudioDefs.h"
+#include "StudioErrorIDs.h"
+#include "Strings.h"
+#include "StudioPreferences.h"
+#include "Renderer.h"
+#include "StudioObjectTypes.h"
+#include "HotKeys.h"
+#include "Dispatch.h"
+#include "Cmd.h"
+#include "MasterP.h"
+#include "Dialogs.h"
+#include "Views.h"
+#include "ResourceCache.h"
+#include "CmdBatch.h"
+#include "DispatchListeners.h"
+#include "UICFile.h"
+#include "StudioConst.h"
+#include "resource.h"
+#include "StudioProjectSettings.h"
+#include "Preferences.h"
+#include "StudioClipboard.h"
+#include "DropTarget.h"
+#include "ContextMenu.h"
+#include "TextButton.h"
+
+#include "StudioPrefixWin32.h"
+
+//==============================================================================
+// Common Includes
+//==============================================================================
+#include "Resource.h"
+
+//==============================================================================
+// OpenGL Includes
+//==============================================================================
+#include <GL/gl.h>
+
+#define UIC_LITTLE_ENDIAN
+
+#define SAFE_DELETE(ptr) \
+ if ((ptr) != nullptr) { \
+ delete (ptr); \
+ (ptr) = nullptr; \
+ }
+#endif
diff --git a/src/Authoring/Studio/_Win/UI/ContextMenu.cpp b/src/Authoring/Studio/_Win/UI/ContextMenu.cpp
new file mode 100644
index 00000000..6aedc806
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ContextMenu.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ContextMenu.h"
+#include "StringLoader.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CContextMenu::CContextMenu()
+ : m_SelectedOption(-1)
+ , m_IndexBase(0)
+{
+ m_Menu = ::CreatePopupMenu();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CContextMenu::~CContextMenu()
+{
+ ::DestroyMenu(m_Menu);
+}
+
+//=============================================================================
+/**
+ * Display the popup menu and perform the actions for whatever choice the
+ * user makes.
+ * @param inLocation the screen coordinates of the location to display this menu.
+ * @param inParentWindow the window to attach this menu to.
+ */
+long CContextMenu::DoPopup(CPt inLocation, HWND inParentWindow)
+{
+ // Allow derived classes to update the menu state
+ Update();
+
+ ::SetCursor(::LoadCursor(nullptr, IDC_ARROW));
+
+ // Display the menu and get the user's input
+ unsigned int theCommandID = (unsigned int)::TrackPopupMenuEx(
+ m_Menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTBUTTON,
+ inLocation.x, inLocation.y, inParentWindow, nullptr);
+
+ // If an option was selected then get the performer for that option and execute it.
+ m_SelectedOption = theCommandID - 1;
+ if (m_SelectedOption >= 0) {
+ CContextMenuPerformer *thePerformer = GetSelectedMenuPerformer(m_SelectedOption);
+ if (thePerformer != nullptr) {
+ thePerformer->OnOptionSelected();
+ }
+ }
+
+ return m_SelectedOption;
+}
+
+//=============================================================================
+/**
+ * Append a separator to the list of items in this menu.
+ */
+void CContextMenu::AddSeparator()
+{
+ ::AppendMenu(m_Menu, MF_SEPARATOR, 0, nullptr);
+}
+
+//=============================================================================
+/**
+ * Append the option onto the end of this menu.
+ * @param inOptionNameStringID ID indicating the display name for the option.
+ * @param inPerformer the performer to be called if this option is selected.
+ * @param inIsEnabled false if the option is to be grayed out and disabled.
+ */
+void CContextMenu::AddOption(int inOptionNameStringID, CContextMenuPerformer *inPerformer,
+ bool inIsEnabled /* = true */)
+{
+ Q3DStudio::CString theOptionName(::LoadResourceString(inOptionNameStringID));
+ AddOption(theOptionName, inPerformer, inIsEnabled);
+}
+
+//=============================================================================
+/**
+ * Append the option onto the end of this menu.
+ * @param inOptionName the display name for the option.
+ * @param inPerformer the performer to be called if this option is selected.
+ * @param inIsEnabled false if the option is to be grayed out and disabled.
+ */
+void CContextMenu::AddOption(const Q3DStudio::CString &inOptionName,
+ CContextMenuPerformer *inPerformer, bool inIsEnabled /*= true */)
+{
+ size_t theIndex = m_IndexBase; // start from a base, so that submenu items can be distinguished
+
+ long theFlags = MF_STRING;
+ if (!inIsEnabled)
+ theFlags |= MF_GRAYED;
+
+ m_Performers.push_back(inPerformer);
+ m_Options.push_back(inOptionName);
+ CContextMenu *theSubMenu = (inPerformer ? inPerformer->GetSubMenu() : nullptr);
+ if (!theSubMenu)
+ theIndex += m_Performers.size();
+ else // if performer has a submenu.
+ {
+ theIndex = (UINT)theSubMenu->GetMenuHandle();
+ theFlags |= MF_POPUP;
+ }
+
+ ::AppendMenuW(m_Menu, theFlags, theIndex, inOptionName);
+}
+
+//=============================================================================
+/**
+ * Remove all options from the menu.
+ */
+void CContextMenu::Clear()
+{
+ long theCount = ::GetMenuItemCount(m_Menu);
+ for (long theIndex = theCount - 1; theIndex >= 0; theIndex--)
+ ::DeleteMenu(m_Menu, theIndex, MF_BYPOSITION);
+
+ m_Performers.clear();
+ m_Options.clear();
+}
+
+//=============================================================================
+/**
+ * Delete all the performers on this object.
+ * This is an ease of use method for subclasses if they allocated their
+ * performers on the heap. This just deletes all of them and clears the list.
+ */
+void CContextMenu::DeletePerformers()
+{
+ TPerformerList::iterator thePos = m_Performers.begin();
+ for (; thePos != m_Performers.end(); ++thePos) {
+ delete (*thePos);
+ }
+ m_Performers.clear();
+}
+
+//=============================================================================
+/**
+ * Adds or removes a check mark from the specified item.
+ * @param inIndex Index of context menu item to be edited
+ * @param inChecked true to set a check, false to remove a check
+ */
+void CContextMenu::SetCheck(long inIndex, bool inChecked)
+{
+ long theFlags = MF_BYPOSITION;
+ theFlags |= inChecked ? MF_CHECKED : MF_UNCHECKED;
+
+ long theActualIndex = inIndex;
+ for (long thePos = 0; thePos < (long)::GetMenuItemCount(m_Menu) && thePos <= inIndex;
+ ++thePos) {
+ // Account for separators that doesn't "contribute" to the number of performers.
+ MENUITEMINFO theMenuInfo;
+ ZeroMemory(&theMenuInfo, sizeof(MENUITEMINFO));
+ theMenuInfo.cbSize = sizeof(MENUITEMINFO);
+ theMenuInfo.fMask = MIIM_TYPE;
+ ::GetMenuItemInfo(m_Menu, thePos, TRUE, &theMenuInfo);
+ if (theMenuInfo.fType & MFT_SEPARATOR)
+ ++theActualIndex;
+ }
+ ::CheckMenuItem(m_Menu, theActualIndex, theFlags);
+}
+
+//=============================================================================
+/**
+ * Set all the menu items to being unchecked.
+ * This will uncheck any items that are currently checked.
+ */
+void CContextMenu::ClearChecked()
+{
+ for (long thePos = 0; thePos < (long)::GetMenuItemCount(m_Menu); ++thePos)
+ ::CheckMenuItem(m_Menu, thePos, MF_BYPOSITION | MF_UNCHECKED);
+}
+
+//=============================================================================
+/**
+ * Gets the string located at a certain index in the context menu list. Index
+ * is zero-based.
+ * @param inIndex zero-based index of the item whose string you want
+ * @return the string at the specified index
+ */
+Q3DStudio::CString CContextMenu::GetStringAt(long inIndex)
+{
+ Q3DStudio::CString theString;
+ if (inIndex >= 0 && inIndex < (long)m_Options.size())
+ theString = m_Options.at(inIndex);
+ return theString;
+}
+
+//=============================================================================
+/**
+ * @return the number of items in this context menu
+ */
+long CContextMenu::GetItemCount()
+{
+ return (long)m_Options.size();
+}
+
+//=============================================================================
+/**
+ * Override this to set enable state of options before the menu pops up
+ */
+void CContextMenu::Update()
+{
+}
+
+static inline long GetEnableMenuItemFlags(bool inEnabledState)
+{
+ return MF_BYPOSITION | (inEnabledState ? (MF_ENABLED) : (MF_GRAYED));
+}
+
+void CContextMenu::EnableOptionByIndex(long inIndex, bool inEnabledState /*= true*/)
+{
+ if (inIndex >= 0 && inIndex < (long)m_Options.size())
+ ::EnableMenuItem(m_Menu, inIndex, GetEnableMenuItemFlags(inEnabledState));
+}
+
+void CContextMenu::EnableOption(const Q3DStudio::CString &inOptionName, bool inEnabledState)
+{
+ long theCount = (long)m_Options.size();
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ if (m_Options[theIndex] == inOptionName) {
+ ::EnableMenuItem(m_Menu, theIndex, GetEnableMenuItemFlags(inEnabledState));
+ break;
+ }
+ }
+}
+
+void CContextMenu::EnableOption(unsigned int inOptionNameStringID, bool inEnabledState)
+{
+ Q3DStudio::CString theOptionName(::LoadResourceString(inOptionNameStringID));
+ EnableOption(theOptionName, inEnabledState);
+}
+
+//=============================================================================
+/**
+ * Find the menu performer associated with this index, recursing down any submenu if necessary.
+ * @param inIndex index of the menu performer
+ */
+CContextMenuPerformer *CContextMenu::GetSelectedMenuPerformer(long inIndex)
+{
+ if (inIndex - m_IndexBase < static_cast<long>(m_Performers.size())) {
+ m_SelectedOption =
+ inIndex - m_IndexBase; // update this for any references to the selected option
+ return m_Performers.at(m_SelectedOption);
+ }
+ // if not found, recurse down submenus
+ CContextMenuPerformer *theResult = nullptr;
+ TPerformerList::iterator theIter = m_Performers.begin();
+ for (; theIter != m_Performers.end() && !theResult; ++theIter) {
+ CContextMenu *theSubMenu = (*theIter)->GetSubMenu();
+ if (theSubMenu)
+ theResult = theSubMenu->GetSelectedMenuPerformer(inIndex);
+ }
+ return theResult;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/UI/ControlButton.cpp b/src/Authoring/Studio/_Win/UI/ControlButton.cpp
new file mode 100644
index 00000000..d99ce639
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ControlButton.cpp
@@ -0,0 +1,471 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "resource.h"
+#include "ControlButton.h"
+#include "MemoryDC.h"
+#include "WinUtils.h"
+
+//==============================================================================
+/*
+ * Constructor: Initializes the object.
+ */
+CControlButton::CControlButton()
+ : m_ImageUp(nullptr)
+ , m_ImageDown(nullptr)
+ , m_ImageDisabled(nullptr)
+ , m_ImageActive(nullptr)
+ , m_ImageMouseTrack(nullptr)
+ , m_ImageLimbo(nullptr)
+ , m_ActiveFlag(FALSE)
+ , m_HotTrackFlag(FALSE)
+ , m_MouseOverFlag(FALSE)
+ , m_ActiveDepressedFlag(FALSE)
+ , m_LimboEnabled(FALSE)
+ , m_LimboFlag(FALSE)
+ , m_SimpleFrame(TRUE)
+ , m_DrawFrame(TRUE)
+ , m_DepressFlag(FALSE)
+ , m_3DColorsFlag(FALSE)
+{
+ m_ImageOffset = CPoint(0, 0);
+ m_FillColor = GetSysColor(COLOR_WINDOW);
+ m_TransparentColor = RGB(255, 0, 255);
+ m_FillColor = GetSysColor(COLOR_3DFACE);
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+CControlButton::~CControlButton()
+{
+}
+
+BEGIN_MESSAGE_MAP(CControlButton, CButton)
+//{{AFX_MSG_MAP(CControlButton)
+ON_WM_MOUSEMOVE()
+ON_WM_ERASEBKGND()
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Method to create the button
+ *
+ * @param inStyle Window style for the button
+ * @param inRect Bounding rectangle for the button
+ * @param inParentWnd Parent window for the button
+ * @param inID Child window ID for the button
+ * @param inDepressFlag
+ * @param inLimboEnabled Set to TRUE if this is a tri-state button (defaults to false).
+ *The third state is referred to as "limbo".
+ * Then use SetLimbo() to enter and leave the limbo state.
+ *
+ * @return Returns TRUE if the button was created
+ */
+BOOL CControlButton::Create(DWORD inStyle, const RECT &inRect, CWnd *inParentWnd, short inID,
+ BOOL inDepressFlag, BOOL inLimboEnabled)
+{
+ m_DepressFlag = inDepressFlag;
+ m_LimboEnabled = inLimboEnabled;
+
+ return CButton::Create(L"", inStyle /*| WS_BORDER*/ | BS_OWNERDRAW, inRect, inParentWnd, inID);
+}
+
+//==============================================================================
+/**
+ * Adds images to the button for the different button states.
+ * @param inTransparentColor RGB value of the transparency color used within the
+ *bitmaps. If there is no transparency color,
+ * set this to a value that does not appear in any of
+ *the images.
+ * @param inImageUp Image for the up state
+ * @param inImageDown Image for the down state
+ * @param inImageDisabled Image for the disabled state
+ * @param inImageActive Image for the active state
+ * @param inImageMouseTrack Image for hot mouse tracking
+ * @param inImageLimbo Image for "limbo" state (used for tri-state buttons)
+ */
+void CControlButton::AddImages(COLORREF inTransparentColor, short inImageUp, short inImageDown,
+ short inImageDisabled, short inImageActive, short inImageMouseTrack,
+ short inImageLimbo)
+{
+ if (inImageUp != 0)
+ m_ImageUp = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageUp),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ // You always need to have at least one valid image for a button
+ ASSERT(m_ImageUp != nullptr);
+
+ if (inImageDown != 0)
+ m_ImageDown = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageDown),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageDisabled != 0)
+ m_ImageDisabled =
+ (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageDisabled),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageActive != 0)
+ m_ImageActive = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageActive),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageMouseTrack != 0)
+ m_ImageMouseTrack =
+ (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageMouseTrack),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageLimbo != 0)
+ m_ImageLimbo = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageLimbo),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ m_TransparentColor = inTransparentColor;
+
+ if (IsWindow(m_hWnd))
+ this->Redraw();
+}
+
+//==============================================================================
+/**
+ * SetImageOffset
+ *
+ * Sets an image drawing offset
+ *
+ * @param inOffset Offset for image from (0,0)
+ */
+void CControlButton::SetImageOffset(CPoint inOffset)
+{
+ m_ImageOffset = inOffset;
+}
+
+//==============================================================================
+/**
+ * SetActiveDepressed
+ *
+ * Sets the active depressed flag. If TRUE and this control is set to active,
+ * then the image will be displayed in a depressed state (for toggle items).
+ *
+ * @param inActiveDepressedFlag TRUE if the active state should be depressed
+ */
+void CControlButton::SetActiveDepressed(BOOL inActiveDepressedFlag)
+{
+ m_ActiveDepressedFlag = inActiveDepressedFlag;
+}
+
+//==============================================================================
+/**
+ * SetActive
+ *
+ * Sets the active state for the button
+ *
+ * @param inActiveState Active state for the button
+ */
+void CControlButton::SetActive(BOOL inActiveFlag)
+{
+ m_ActiveFlag = inActiveFlag;
+
+ if (IsWindow(m_hWnd))
+ this->Redraw();
+}
+
+//==============================================================================
+/**
+ * GetActive
+ *
+ * Gets the active state for the button
+ *
+ * @param None
+ *
+ * @return Active state for the button
+ */
+BOOL CControlButton::GetActive()
+{
+ return m_ActiveFlag;
+}
+
+//==============================================================================
+/**
+ * DrawItem
+ *
+ * Handle the owner drawn button
+ *
+ * @param inDrawItemStruct DRAWITEMSTRUCT structure
+ */
+void CControlButton::DrawItem(LPDRAWITEMSTRUCT inDrawItemStruct)
+{
+ CDC *theDC;
+ CMemoryDC theMemDC;
+ BOOL theEnabledFlag;
+ BOOL theDownStateFlag;
+ HBITMAP theBitmap = m_ImageUp;
+ CRect theRect;
+
+ theDC = GetDC();
+
+ // Get the bounding client rectangle
+ GetClientRect(theRect);
+
+ theMemDC.Create(theDC, theRect);
+
+ theDownStateFlag = (inDrawItemStruct->itemState & ODS_SELECTED);
+
+ // Is this window enabled?
+ theEnabledFlag = IsWindowEnabled();
+
+ if (m_ActiveFlag)
+ theBitmap = m_ImageActive;
+
+ if (m_MouseOverFlag)
+ if (m_ImageMouseTrack != 0)
+ theBitmap = m_ImageMouseTrack;
+
+ if (!theEnabledFlag) {
+ // Disabled
+ if (m_ImageDisabled != 0)
+ theBitmap = m_ImageDisabled;
+ } else {
+ // Window is enabled
+ if (theDownStateFlag)
+ if (m_ImageDown != 0)
+ theBitmap = m_ImageDown;
+ }
+
+ // If the button has limbo enabled, and it in limbo state, it overrides any previous button
+ // settings
+ if (m_LimboEnabled && m_LimboFlag)
+ if (m_ImageLimbo != 0)
+ theBitmap = m_ImageLimbo;
+
+ // Fill the background color
+ theMemDC.FillSolidRect(theRect, m_FillColor);
+
+ // Draw the bitmap if it exists
+ if (theBitmap)
+ CWinUtils::DrawTransparentBitmap(
+ &theMemDC, m_ImageOffset.x + theDownStateFlag * m_DepressFlag,
+ m_ImageOffset.y + theDownStateFlag * m_DepressFlag, theBitmap, m_TransparentColor);
+
+ // Hot tracking the mouse over the button?
+ if (m_HotTrackFlag) {
+ if (m_DepressFlag) {
+ if (theDownStateFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, TRUE);
+ else if (m_MouseOverFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, FALSE);
+ } else {
+ if (m_MouseOverFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, FALSE);
+ }
+ } else {
+ // Draw the frame around the button
+ if (!m_ActiveFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, theDownStateFlag * m_DepressFlag);
+ }
+
+ theMemDC.Release();
+
+ ReleaseDC(theDC);
+}
+
+//==============================================================================
+/**
+ * DrawButtonFrame
+ *
+ * Draw the button frame
+ *
+ * @param inDC Device context for drawing
+ * @param inRect Bounding rectangle for the button frame
+ * @param inDownFlag If TRUE, the button is down
+ */
+void CControlButton::DrawButtonFrame(CDC *inDC, CRect *inRect, BOOL inDownFlag)
+{
+ if (m_DrawFrame) {
+ COLORREF theShadowColor = GetSysColor(COLOR_3DSHADOW);
+ COLORREF theHiliteColor = GetSysColor(COLOR_3DHIGHLIGHT);
+
+ if (inDownFlag) {
+ theShadowColor = GetSysColor(COLOR_3DHIGHLIGHT);
+ theHiliteColor = GetSysColor(COLOR_3DSHADOW);
+ }
+
+ CRect theFrameRect;
+
+ theFrameRect.CopyRect(inRect);
+
+ if (m_SimpleFrame) {
+ inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor);
+ } else {
+ if (inDownFlag) {
+ theFrameRect.right--;
+ theFrameRect.bottom--;
+
+ inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor);
+ } else {
+ // the button is up
+ theFrameRect.right--;
+ theFrameRect.bottom--;
+
+ inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor);
+
+ inDC->MoveTo(theFrameRect.right, theFrameRect.top);
+ inDC->LineTo(theFrameRect.right, theFrameRect.bottom);
+ inDC->LineTo(theFrameRect.left, theFrameRect.bottom);
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * SetHotTrack
+ *
+ * Set the hot track (mouse over) flag
+ *
+ * @param inHotTrackFlag Hot tracking flag
+ */
+void CControlButton::SetHotTrack(BOOL inHotTrackFlag)
+{
+ m_HotTrackFlag = inHotTrackFlag;
+
+ if (IsWindow(m_hWnd))
+ this->Redraw();
+}
+
+//==============================================================================
+/**
+ * OnMouseMove
+ *
+ * Handle the WM_MOUSEMOVE message
+ *
+ * @param inFlags Flags for WM_MOUSEMOVE
+ * @param inPoint Cursor position in client coordinates
+ */
+void CControlButton::OnMouseMove(UINT inFlags, CPoint inPoint)
+{
+ CButton::OnMouseMove(inFlags, inPoint);
+
+ if (!m_MouseOverFlag) {
+ this->TrackMouse();
+ m_MouseOverFlag = TRUE;
+
+ this->Redraw();
+ }
+}
+
+//==============================================================================
+/**
+ * OnMouseMove
+ *
+ * Handle the WM_MOUSELEAVE message
+ *
+ * @param inwParam WPARAM for the WM_MOUSELEAVE message
+ * @param inlParam LPARAM for the WM_MOUSELEAVE message
+ *
+ * @param Return code - returns TRUE if this message is processed.
+ */
+LRESULT CControlButton::OnMouseLeave(WPARAM inwParam, LPARAM inlParam)
+{
+ Q_UNUSED(inwParam);
+ Q_UNUSED(inlParam);
+
+ m_MouseOverFlag = FALSE;
+
+ this->TrackMouse(FALSE);
+
+ this->Redraw();
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * TrackMouse
+ *
+ * Register for the WM_MOUSELEAVE message to determine when
+ * the mouse leaves this button.
+ *
+ * @param inTrackEnableFlag - TRUE/FALSE depending on whether we want to track the mouse
+ *event state.
+ */
+void CControlButton::TrackMouse(BOOL inTrackEnableFlag)
+{
+ TRACKMOUSEEVENT theTrackMouseEvent;
+
+ memset(&theTrackMouseEvent, 0, sizeof(theTrackMouseEvent));
+
+ theTrackMouseEvent.cbSize = sizeof(theTrackMouseEvent);
+ theTrackMouseEvent.dwFlags = TME_LEAVE;
+ if (!inTrackEnableFlag)
+ theTrackMouseEvent.dwFlags |= TME_CANCEL;
+ theTrackMouseEvent.hwndTrack = m_hWnd;
+
+ _TrackMouseEvent(&theTrackMouseEvent);
+}
+
+//==============================================================================
+/**
+ * Redraw
+ *
+ * Invalidate and update the button
+ *
+ * @param None
+ */
+void CControlButton::Redraw()
+{
+ // Invalidate and update the window
+ InvalidateRect(nullptr, TRUE);
+ UpdateWindow();
+}
+
+//==============================================================================
+/**
+ * Handles the WM_ERASEBKGND message. This function is overridden so that we
+ * can prevent the background from being erased. When we draw the button, the
+ * background is filled in with the appropriate color. Actually erasing the
+ * background before a draw was producing flickering.
+ *
+ * @param pDC Not used.
+ */
+BOOL CControlButton::OnEraseBkgnd(CDC *pDC)
+{
+ Q_UNUSED(pDC);
+ return 1;
+}
diff --git a/src/Authoring/Studio/_Win/UI/ControlButton.h b/src/Authoring/Studio/_Win/UI/ControlButton.h
new file mode 100644
index 00000000..6f168cb2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ControlButton.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_)
+#define AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+/////////////////////////////////////////////////////////////////////////////
+// CControlButton window
+
+class CControlButton : public CButton
+{
+ // Construction
+public:
+ CControlButton();
+
+ // Attributes
+public:
+protected:
+ HBITMAP m_ImageUp, m_ImageDown, m_ImageDisabled, m_ImageActive, m_ImageMouseTrack,
+ m_ImageLimbo; // resource bitmap values for various button states
+ BOOL m_DepressFlag, m_3DColorsFlag; // drawing flags
+ BOOL m_ActiveFlag; // TRUE if the button is active (ie - selected)
+ BOOL m_ActiveDepressedFlag; // TRUE if the active state should be drawn depressed
+ CPoint m_ImageOffset; // Image offset from (0,0)
+ BOOL m_MouseOverFlag; // TRUE if the mouse is currently over this button
+ BOOL m_HotTrackFlag; // TRUE if the mouse should be hot-tracked
+ BOOL m_SimpleFrame; // TRUE if the button is a simple frame
+ BOOL m_DrawFrame; // TRUE if the frame around the button should be drawn
+ BOOL m_LimboEnabled; ///< TRUE if this button is capable of being in limbo (decided at creation
+ ///time)
+ BOOL m_LimboFlag; ///< TRUE if the button is currently in limbo state
+ COLORREF m_FillColor;
+ COLORREF m_TransparentColor;
+
+ // Operations
+public:
+ void AddImages(COLORREF inTransparentColor, short inImageUp, short inImageDown = 0,
+ short inImageDisabled = 0, short inImageActive = 0, short inImageMouseTrack = 0,
+ short inImageLimbo = 0);
+
+ BOOL Create(DWORD inStyle, const RECT &inRect, CWnd *inParentWnd, short inID,
+ BOOL inDepressFlag = TRUE, BOOL inTriState = FALSE);
+
+ BOOL GetActive();
+
+ void SetActive(BOOL inActiveFlag);
+ void SetActiveDepressed(BOOL inActiveDepressedFlag);
+ /// Sets the "limbo" state of the button. Usefully for making tri-state buttons. Limbo state
+ /// only works if the limbo flag was set during creation.
+ void SetLimbo(BOOL inLimboFlag) { m_LimboFlag = inLimboFlag; }
+ /// Returns TRUE if the button is in "limbo" state
+ BOOL GetLimbo() { return m_LimboFlag; }
+ void SetHotTrack(BOOL inHotTrackFlag);
+ void SetImageOffset(CPoint inOffset);
+ void SetDrawFrame(BOOL inDrawFrame) { m_DrawFrame = inDrawFrame; }
+ /// Use this function to manually set the fill color behind the button. Use this if you notice
+ /// that the wrong color is showing up.
+ void SetFillColor(COLORREF inColor) { m_FillColor = inColor; }
+protected:
+ void DrawButtonFrame(CDC *inDC, CRect *inRect, BOOL inDownFlag);
+ void Redraw();
+ void TrackMouse(BOOL inTrackEnableFlag = TRUE);
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CControlButton)
+public:
+ virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CControlButton();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CControlButton)
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ //}}AFX_MSG
+ afx_msg LRESULT OnMouseLeave(WPARAM inwParam, LPARAM inlParam);
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/CrashDlg.cpp b/src/Authoring/Studio/_Win/UI/CrashDlg.cpp
new file mode 100644
index 00000000..13277385
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/CrashDlg.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MainFrm.h"
+#include "CrashDlg.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrashDlg dialog
+
+CCrashDlg::CCrashDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CCrashDlg::IDD, pParent)
+ , m_Filename(_T(""))
+{
+ //{{AFX_DATA_INIT(CCrashDlg)
+ m_Header = _T("");
+ //}}AFX_DATA_INIT
+
+ m_MediumFont2.CreatePointFont(88, CString(CStudioPreferences::GetFontFaceName()));
+
+ m_Color_Background = CStudioPreferences::GetDarkBaseColor();
+ m_Color_Text = CStudioPreferences::GetMasterColor();
+ m_Color_Gray = CStudioPreferences::GetNormalColor();
+ m_Color_Dark = CStudioPreferences::GetInactiveColor();
+}
+
+void CCrashDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CCrashDlg)
+ DDX_Control(pDX, IDC_CRASHICON, m_CrashIcon);
+ DDX_Text(pDX, IDC_HEADER, m_Header);
+ DDX_Text(pDX, IDC_HEADER2, m_FilenameSaved);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CCrashDlg, CDialog)
+//{{AFX_MSG_MAP(CCrashDlg)
+ON_BN_CLICKED(IDEXIT, OnExit)
+//}}AFX_MSG_MAP
+// ON_STN_CLICKED(IDC_HEADER, &CCrashDlg::OnStnClickedHeader)
+ON_WM_ERASEBKGND()
+ON_WM_CTLCOLOR()
+ON_WM_DESTROY()
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Set the description of the crash.
+ * @param inErrorMessage the error message.
+ */
+//==============================================================================
+void CCrashDlg::SetErrorMessage(CString inErrorMessage)
+{
+ m_ErrorMessage = inErrorMessage;
+}
+
+//==============================================================================
+/**
+ * Set the project filename saved
+ * @param inFilename the filename of the crashed project
+ */
+//==============================================================================
+void CCrashDlg::SetFilename(CString inFilename)
+{
+ m_Filename = inFilename;
+}
+
+//==============================================================================
+/**
+ * Set the stack trace for the crash.
+ * @param inStackTrace the stack trace.
+ */
+//==============================================================================
+void CCrashDlg::SetStackTrace(CString inStackTrace)
+{
+ m_StackTrace = inStackTrace;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrashDlg message handlers
+
+void CCrashDlg::OnExit()
+{
+ this->EndDialog(0);
+ _exit(EXIT_FAILURE);
+}
+
+void CCrashDlg::SplitLongPath(int controlId, CString &text)
+{
+
+ // Get the device context of your control.
+ CDC *dc = GetDlgItem(controlId)->GetDC();
+ CRect filenameTextRect;
+ GetDlgItem(controlId)->GetClientRect(filenameTextRect);
+
+ HGDIOBJ hOldFont = dc->SelectObject(&m_MediumFont2);
+
+ CRect tmpStringRect(0, 0, 0, 0);
+ CString workingString = text;
+
+ CString tmpString;
+ std::vector<int> insertPosition;
+ int previousOffset = 0;
+
+ for (int i = 0; i < workingString.GetLength(); ++i) {
+ tmpString = workingString.Mid(previousOffset, i - previousOffset);
+ dc->DrawText(tmpString, &tmpStringRect, DT_CALCRECT);
+ if (tmpStringRect.Width() + 5 > filenameTextRect.Width()) {
+ previousOffset = i;
+ insertPosition.push_back(i - 1);
+ }
+ }
+
+ // adds in all the \n
+ for (int i = (int)insertPosition.size() - 1; i >= 0; --i) {
+ text.Insert(insertPosition[i], '\n');
+ }
+
+ dc->SelectObject(hOldFont);
+}
+
+BOOL CCrashDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_Brush.CreateSolidBrush(m_Color_Background);
+ GetDlgItem(IDC_HEADER)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_HEADER2)->SetFont(&m_MediumFont2);
+
+ // m_Header = ::LoadResourceString( IDS_ERROR_MSGPASSING ).GetMulti( );
+ m_Header = m_ErrorMessage;
+ m_FilenameSaved = m_Filename;
+
+ CString theTitle = ::LoadResourceString(IDS_ERROR_MSGTITLE);
+ this->SetWindowText(theTitle);
+
+ // Show the exclamation point icon
+ m_CrashIcon.SetIcon(::LoadIcon(nullptr, IDI_ERROR));
+
+ SplitLongPath(IDC_HEADER2, m_FilenameSaved);
+ SplitLongPath(IDC_HEADER, m_Header);
+
+ this->UpdateData(FALSE);
+
+ return TRUE;
+}
+
+BOOL CCrashDlg::OnEraseBkgnd(CDC *pDC)
+{
+ CRect theClientRect;
+ GetClientRect(&theClientRect);
+ pDC->FillSolidRect(theClientRect, m_Color_Background);
+
+ return TRUE;
+}
+
+HBRUSH CCrashDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT)
+{
+ int theCtrlID = pWnd->GetDlgCtrlID();
+ if (theCtrlID == IDREPORT || theCtrlID == IDEXIT || theCtrlID == IDC_LINE_CRASHDLG) {
+ pDC->SetBkMode(TRANSPARENT); // for area just behind the text
+ pDC->SetTextColor(m_Color_Text);
+ } else if (theCtrlID == IDC_HEADER || theCtrlID == IDC_HEADER2) {
+ pDC->SetBkMode(TRANSPARENT); // for area just behind the text
+ pDC->SetTextColor(m_Color_Gray);
+ }
+
+ return m_Brush;
+}
+
+void CCrashDlg::OnDestroy()
+{
+ CDialog::OnDestroy();
+
+ m_Brush.DeleteObject();
+}
diff --git a/src/Authoring/Studio/_Win/UI/CrashDlg.h b/src/Authoring/Studio/_Win/UI/CrashDlg.h
new file mode 100644
index 00000000..75f5765c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/CrashDlg.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CRASH_DIALOG_H
+#define INCLUDED_CRASH_DIALOG_H
+#include "afxwin.h"
+#include <string.h>
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrashDlg dialog
+
+class CCrashDlg : public CDialog
+{
+ // Construction
+public:
+ CCrashDlg(CWnd *pParent = nullptr); // standard constructor
+
+ // Dialog Data
+ //{{AFX_DATA(CCrashDlg)
+ enum { IDD = IDD_CRASHDLG };
+ CStatic m_CrashIcon;
+ CString m_Header;
+ //}}AFX_DATA
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCrashDlg)
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ void SetErrorMessage(CString inErrorMessage);
+ void SetFilename(CString inFilename);
+ void SetStackTrace(CString inStackTrace);
+ void SplitLongPath(int controlId, CString &text);
+
+protected:
+ CString m_ErrorMessage;
+ CString m_FilenameSaved;
+ CString m_StackTrace;
+
+ COLORREF m_Color_Background;
+ COLORREF m_Color_Text;
+ COLORREF m_Color_Gray;
+ COLORREF m_Color_Dark;
+ CBrush m_Brush;
+ CFont m_MediumFont2;
+
+ // Generated message map functions
+ //{{AFX_MSG(CCrashDlg)
+ afx_msg void OnSave();
+ afx_msg void OnExit();
+ afx_msg void OnDestroy();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+public:
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
+ CString m_Filename;
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // INCLUDED_CRASH_DIALOG_H
diff --git a/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp b/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp
new file mode 100644
index 00000000..7827ee93
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EditCameraBar.h"
+#include "MainFrm.h"
+#include "SceneView.h"
+#include "StringLoader.h"
+#include "StudioPreferences.h"
+#include "StudioApp.h"
+#include "IStudioRenderer.h"
+
+#include <QComboBox>
+#include <QLabel>
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CEditCameraBar::CEditCameraBar(QWidget* parent)
+ : QToolBar(parent)
+ , m_SceneView(nullptr)
+ , m_ActiveCameraIndex(-1)
+{
+ OnCustomizeToolbar();
+ auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated);
+ connect(m_CameraSelector, activated, this, &CEditCameraBar::OnCameraChanged);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CEditCameraBar::~CEditCameraBar()
+{
+ delete m_CameraSelector;
+ delete m_CameraText;
+}
+
+//==============================================================================
+/**
+ * Setup the list of edit cameras into the camera combo box
+ * @param inCameras the container that holds the edit cameras
+ */
+void CEditCameraBar::SetupCameras()
+{
+ m_CameraSelector->clear();
+ Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer();
+ QStringList theCameraNames;
+ theRenderer.GetEditCameraList(theCameraNames);
+ int idx = 1;
+ for (const QString &str : qAsConst(theCameraNames)) {
+ m_CameraSelector->addItem(str, QVariant((int)idx));
+ idx++;
+ }
+
+ m_CameraSelector->addItem("--------------------------");
+ m_CameraSelector->setItemData(m_CameraSelector->count() - 1, -1); // set to an invalid pointer
+ m_CameraSelector->addItem(::LoadResourceString(IDS_SCENE_CAMERA_VIEW).toQString());
+ m_CameraSelector->setItemData(m_CameraSelector->count() - 1, 0);
+
+ long thePreferredView = CStudioPreferences::GetPreferredStartupView();
+ long theNumItems = m_CameraSelector->count();
+ if (thePreferredView == -1) // deployment view
+ {
+ m_CameraSelector->setCurrentIndex(theNumItems - 1);
+ HandleCameraChanged(theNumItems - 1); // set to the last one
+ } else {
+ int theIndex;
+ if (thePreferredView < theNumItems - 2)
+ theIndex = thePreferredView;
+ else // possibly from old content where cameras are removed
+ theIndex = 0;
+ m_CameraSelector->setCurrentIndex(theIndex);
+ HandleCameraChanged(theIndex);
+ }
+}
+
+//==============================================================================
+/**
+ * Callback method when the camera is changed from the camera selection combo box
+ */
+void CEditCameraBar::OnCameraChanged()
+{
+ HandleCameraChanged(m_CameraSelector->currentIndex());
+}
+
+//==============================================================================
+/**
+ * Handle the switching of the current edit camera
+ * @param inIndex the index of the to-be-activated camera in the combo box
+ */
+void CEditCameraBar::HandleCameraChanged(int inIndex)
+{
+ Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer();
+ QStringList theCameraNames;
+ theRenderer.GetEditCameraList(theCameraNames);
+ int theNumCameras = theCameraNames.size();
+ if (inIndex < theNumCameras) {
+ theRenderer.SetEditCamera(inIndex);
+ m_ActiveCameraIndex = inIndex;
+ if (m_SceneView)
+ m_SceneView->SetViewMode(CPlayerContainerWnd::VIEW_EDIT);
+ } else if (inIndex > theNumCameras) {
+ theRenderer.SetEditCamera(-1);
+ m_ActiveCameraIndex = inIndex;
+ if (m_SceneView)
+ m_SceneView->SetViewMode(CPlayerContainerWnd::VIEW_SCENE);
+ } else {
+ m_CameraSelector->setCurrentIndex(m_ActiveCameraIndex);
+ }
+ if (m_SceneView)
+ m_SceneView->OnEditCameraChanged();
+
+ CMainFrame *theMainFrame = g_StudioApp.m_pMainWnd;
+ ASSERT(theMainFrame != nullptr);
+
+ // if the current tool is camera rotate and has been switch to 2d camera
+ // set the tool to camera pan
+ if (theMainFrame != nullptr) {
+ long theToolMode = g_StudioApp.GetToolMode();
+ if (theRenderer.DoesEditCameraSupportRotation(theRenderer.GetEditCamera()) == false
+ && theToolMode == STUDIO_TOOLMODE_CAMERA_ROTATE) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ }
+
+ // Trigger for tool changed. Changing between deployment/edit camera can change the tool
+ theMainFrame->OnUpdateToolChange();
+ }
+}
+
+//==============================================================================
+/**
+ * Set the current scene view. This scene view is notified when there is a camera
+ * changed.
+ * @param inSceneView the scene view object
+ */
+void CEditCameraBar::SetSceneView(CSceneView *inSceneView)
+{
+ m_SceneView = inSceneView;
+}
+
+//==============================================================================
+/**
+ * Enable/Disable the edit camera selector combo box.
+ * @param inFlag true to enable the camera selector combo box, false to disable
+ */
+void CEditCameraBar::Enable(bool inFlag)
+{
+ m_CameraSelector->setEnabled(inFlag);
+}
+
+//==============================================================================
+/**
+ * When the active camera is changed, the display string needs to be changed. Hence
+ * find which entry is the one which is modified and update with the new string
+ * @param inCamera the camera that has been modified
+ */
+void CEditCameraBar::OnEditCameraChanged()
+{
+ using qt3ds::QT3DSI32;
+ QT3DSI32 cameraIndex = g_StudioApp.GetRenderer().GetEditCamera();
+ long theNumEntry = m_CameraSelector->count();
+ for (long theIndex = 0; theIndex < theNumEntry; ++theIndex) {
+ if (m_CameraSelector->itemData(theIndex).toInt() == cameraIndex) {
+ if (theIndex != m_CameraSelector->currentIndex()) {
+ m_CameraSelector->setCurrentIndex(theIndex);
+ HandleCameraChanged(theIndex);
+ }
+ break;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Callback while creating the toolbar in MainFrm. This allows the toolbar to add
+ * other controls to it. For this toolbar, we want to add a descriptor and a camera
+ * selector dropdown combobox.
+ */
+//==============================================================================
+void CEditCameraBar::OnCustomizeToolbar()
+{
+ // Create the combo box
+ addWidget(m_CameraSelector = new QComboBox);
+ // We need to specify accessibleName and objectName for the combobox, as it's in the toolbar,
+ // and we want to use a different style for it.
+ m_CameraSelector->setAccessibleName(QStringLiteral("cameraSelector"));
+ m_CameraSelector->setObjectName(QStringLiteral("cameraSelector"));
+ m_CameraSelector->setMinimumWidth(145);
+}
diff --git a/src/Authoring/Studio/_Win/UI/EditCameraBar.h b/src/Authoring/Studio/_Win/UI/EditCameraBar.h
new file mode 100644
index 00000000..bd8427f5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditCameraBar.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_EDIT_CAMERA_BAR
+#define INCLUDED_EDIT_CAMERA_BAR 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DispatchListeners.h"
+#include <vector>
+
+#include <QToolBar>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QLabel;
+QT_END_NAMESPACE
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CSceneView;
+
+//==============================================================================
+/**
+ * @class CEditCameraBar
+ */
+class CEditCameraBar : public QToolBar, public CEditCameraChangeListener
+{
+ Q_OBJECT
+public:
+ CEditCameraBar(QWidget* parent = nullptr); // standard constructor
+ virtual ~CEditCameraBar();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CEditCameraBar)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+ // Generated message map functions
+ void OnCameraChanged();
+ void OnCustomizeToolbar();
+
+public:
+ void SetupCameras();
+ void SetSceneView(CSceneView *inSceneView);
+ void Enable(bool inFlag);
+ void HandleCameraChanged(int inIndex);
+
+ // CEditCameraChangeListener
+ void OnEditCameraChanged() override;
+ void OnEditCamerasTransformed() override {} // I am not interested in this
+ void OnAuthorZoomChanged() override {}
+
+protected:
+ CSceneView *m_SceneView; ///< The scene view object
+ long m_ActiveCameraIndex; ///< The index of the active camera in the list
+
+ // UI Controls definition
+ QLabel* m_CameraText; ///< Static text showing the word "Camera"
+ QComboBox* m_CameraSelector; ///< Combo box for selecting edit camera
+};
+
+#endif
diff --git a/src/Authoring/Studio/_Win/UI/EditorPane.cpp b/src/Authoring/Studio/_Win/UI/EditorPane.cpp
new file mode 100644
index 00000000..ef274392
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditorPane.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EditorPane.h"
+
+//==============================================================================
+/**
+ * Constructor: Creates a CEditorPane
+ */
+CEditorPane::CEditorPane()
+ : m_EditObject(nullptr)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the CEditorPane
+ */
+CEditorPane::~CEditorPane()
+{
+}
+
+//==============================================================================
+/**
+ * Set the object that this window will edit.
+ * Recieve and keep the CAsset to be edited. You can override this method
+ * for each specific editor view class.
+ * @param inEditObject The CAsset to be represented and edited in this view.
+ */
+void CEditorPane::SetEditObject(CAsset *inEditObject)
+{
+ // Retain this object
+ m_EditObject = inEditObject;
+}
+
+//==============================================================================
+/**
+ * Get the object that this window is editing.
+ * return The CAsset that is associated with this window
+ */
+CAsset *CEditorPane::GetEditObject()
+{
+ // Return the asset
+ return m_EditObject;
+}
+
+//==============================================================================
+/**
+ * CloseEditor: Close the editor.
+ * Override to close each individual editor.
+ * @return false
+ */
+bool CEditorPane::CloseEditor()
+{
+ return false;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/UI/EditorPane.h b/src/Authoring/Studio/_Win/UI/EditorPane.h
new file mode 100644
index 00000000..9bc91694
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditorPane.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_EDITOR_PANE
+#define INCLUDED_EDITOR_PANE 1
+
+#pragma once
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CAsset;
+
+//==============================================================================
+/**
+ * @class CEditorPane
+ * @brief Abstract base class for various editor views.
+ *
+ * A base class for universally accessing information from editor views.
+ */
+class CEditorPane
+{
+ // Fields
+protected:
+ CAsset *m_EditObject; ///< object being edited by this window.
+
+ // Methods
+public:
+ CEditorPane();
+ virtual ~CEditorPane();
+ virtual void SetEditObject(CAsset *inEditObject);
+ CAsset *GetEditObject();
+ virtual bool CloseEditor();
+};
+
+#endif // INCLUDED_EDITOR_PANE \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp b/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp
new file mode 100644
index 00000000..9183e536
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+#include <afxpriv.h>
+#include "FileDialogEX.h"
+#include "resource.h"
+#include "windowsx.h"
+#include "Userenv.h"
+#include "Commdlg.h"
+#include "CdErr.h"
+#include "Preferences.h"
+
+static const long SFILELISTBUFFERSIZE =
+ 2048; // Size of the char buffer used to store selected filenames
+// static BOOL IsWin2000();
+
+/////////////////////////////////////////////////////////////////////////////
+// CFileDialogEx
+
+IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog)
+
+//==============================================================================
+/**
+ * CFileDialogEx: constructor
+ */
+//==============================================================================
+CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
+ DWORD dwFlags, LPCTSTR lpszFilter, CWnd *pParentWnd)
+ : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
+ , m_IsSaving(FALSE)
+ , m_LastFilterIndex(1)
+ , m_FileListBuffer(nullptr)
+ , m_WasCreateNewDirectoryChecked(false)
+ , m_CreateDirectoryCheckboxEnabled(false)
+ , m_Preferences(CPreferences::GetUserPreferences())
+{
+ m_IsSaving = !bOpenFileDialog; // if not openfiledlg, is saving
+ m_FilterIndex = 0; // init to 0; index starts from 1
+ m_ofnEx.pvReserved = nullptr;
+ m_ofnEx.dwReserved = 0;
+ m_ofnEx.FlagsEx = 0;
+
+ if (dwFlags & OFN_ALLOWMULTISELECT) {
+ // Create buffer for multiple selection
+ m_FileListBuffer = new TCHAR[SFILELISTBUFFERSIZE];
+ m_FileListBuffer[0] = '\0';
+
+ GetOFN().lpstrFile = m_FileListBuffer;
+ GetOFN().nMaxFile = SFILELISTBUFFERSIZE;
+ }
+}
+
+CFileDialogEx::~CFileDialogEx()
+{
+ if (m_FileListBuffer) {
+ delete[] m_FileListBuffer;
+ }
+}
+
+BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog)
+//{{AFX_MSG_MAP(CFileDialogEX)
+ON_COMMAND(IDC_CHECK1, OnCreateNewDirectory)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * IsWin2000: function to determine if we are on win2k
+ *
+ * @return true if we are on win2k
+ */
+//==============================================================================
+// BOOL IsWin2000 ()
+//{
+// OSVERSIONINFOEX theOsvi;
+// BOOL OsVersionInfoEx;
+//
+// // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
+// // which is supported on Windows 2000.
+// //
+// // If that fails, try using the OSVERSIONINFO structure.
+//
+// ZeroMemory( &theOsvi, sizeof( OSVERSIONINFOEX ) );
+// theOsvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
+// OsVersionInfoEx = GetVersionEx ( ( OSVERSIONINFO* ) &theOsvi );
+//
+// if( !OsVersionInfoEx )
+// {
+// // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
+//
+// theOsvi.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
+// if ( !GetVersionEx( ( OSVERSIONINFO* ) &theOsvi) )
+// return FALSE;
+// }
+//
+// switch ( theOsvi.dwPlatformId )
+// {
+// case VER_PLATFORM_WIN32_NT:
+//
+// if ( theOsvi.dwMajorVersion >= 5 )
+// return TRUE;
+//
+// break;
+// }
+// return FALSE;
+//}
+
+void CFileDialogEx::EnableCreateDirectoryCheckbox()
+{
+ m_CreateDirectoryCheckboxEnabled = true;
+}
+
+// http://msdn.microsoft.com/en-us/magazine/cc300434.aspx
+struct RegKeyOverrider
+{
+ const char *getRegKeyName()
+ {
+ return "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\ComDlg32\\PlacesBar";
+ }
+ HKEY m_TempKey;
+
+ RegKeyOverrider()
+ {
+ memset(&m_TempKey, 0, sizeof(HKEY));
+ long newKeyResult =
+ RegCreateKeyEx(HKEY_CURRENT_USER, L"UIComposer_FileDialog", 0, nullptr,
+ REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr, &m_TempKey, nullptr);
+ if (newKeyResult == ERROR_SUCCESS) {
+ long overrideResult = RegOverridePredefKey(HKEY_CURRENT_USER, m_TempKey);
+ ASSERT(overrideResult == ERROR_SUCCESS);
+ if (overrideResult == ERROR_SUCCESS) {
+ // Customize the places bar now in or overridden key.
+ HKEY placesKey;
+ long placesResult =
+ RegCreateKeyEx(HKEY_CURRENT_USER, CString(getRegKeyName()), 0, nullptr,
+ REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr, &placesKey, nullptr);
+ if (placesResult == ERROR_SUCCESS) {
+ TCHAR szHomeDirBuf[MAX_PATH] = { 0 };
+
+ HANDLE hToken = 0;
+ OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
+
+ DWORD BufSize = MAX_PATH;
+ GetUserProfileDirectory(hToken, szHomeDirBuf, &BufSize);
+
+ CloseHandle(hToken);
+
+ wcscat(szHomeDirBuf, L"\\Links");
+
+ size_t len = wcslen(szHomeDirBuf);
+ RegSetValueEx(placesKey, L"Place0", 0, REG_SZ, (const BYTE *)szHomeDirBuf,
+ (DWORD)len);
+
+ TCHAR buffer[32] = { 0 };
+ DWORD folderIds[] = { 8, 0, 17, 18 };
+
+ for (int idx = 0; idx < 4; ++idx) {
+ swprintf_s(buffer, L"Place%d", idx + 1);
+ long setKeyResult =
+ RegSetValueEx(placesKey, buffer, 0, REG_DWORD,
+ (const BYTE *)(folderIds + idx), sizeof(DWORD));
+ ASSERT(setKeyResult == ERROR_SUCCESS);
+ }
+ }
+ RegCloseKey(placesKey);
+ }
+ }
+ }
+ ~RegKeyOverrider()
+ {
+ RegOverridePredefKey(HKEY_CURRENT_USER, nullptr);
+ RegDeleteKey(m_TempKey, nullptr);
+ RegCloseKey(m_TempKey);
+ }
+};
+struct SErrorMap
+{
+ DWORD m_Error;
+ const char *m_Name;
+};
+static SErrorMap g_ErrorMap[] = {
+#define MAKE_STRUCT(name) { name, #name },
+ MAKE_STRUCT(CDERR_DIALOGFAILURE) MAKE_STRUCT(CDERR_FINDRESFAILURE)
+ MAKE_STRUCT(CDERR_INITIALIZATION) MAKE_STRUCT(CDERR_LOADRESFAILURE)
+ MAKE_STRUCT(CDERR_LOADSTRFAILURE) MAKE_STRUCT(CDERR_LOCKRESFAILURE)
+ MAKE_STRUCT(CDERR_MEMALLOCFAILURE) MAKE_STRUCT(CDERR_MEMLOCKFAILURE)
+ MAKE_STRUCT(CDERR_NOHINSTANCE) MAKE_STRUCT(CDERR_NOHOOK)
+ MAKE_STRUCT(CDERR_NOTEMPLATE) MAKE_STRUCT(CDERR_STRUCTSIZE)
+ MAKE_STRUCT(FNERR_BUFFERTOOSMALL) MAKE_STRUCT(FNERR_INVALIDFILENAME)
+ MAKE_STRUCT(FNERR_SUBCLASSFAILURE)
+#undef MAKE_STRUCT
+ { 0, nullptr },
+};
+//==============================================================================
+/**
+ * IsWin2000: Overloaded CFileDialog Function
+ *
+ * adds extra parameter if the operating system is win2k
+ *
+ * @return true for file open... false for file save as
+ */
+//==============================================================================
+INT_PTR CFileDialogEx::DoModal()
+{
+ ASSERT_VALID(this);
+ ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
+ ASSERT(m_ofn.lpfnHook != nullptr); // can still be a user hook
+
+ // zero out the file buffer for consistent parsing later
+ ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
+ DWORD nOffset = (DWORD)_tcslen(m_ofn.lpstrFile) + 1;
+ ASSERT(nOffset <= m_ofn.nMaxFile);
+ memset(m_ofn.lpstrFile + nOffset, 0, (m_ofn.nMaxFile - nOffset) * sizeof(TCHAR));
+
+ if (!m_InitialDir.IsEmpty())
+ m_ofn.lpstrInitialDir = m_InitialDir;
+
+ // If the title has been specified, change it from the OS default
+ if (!m_Title.IsEmpty())
+ m_ofn.lpstrTitle = m_Title;
+
+ // If filterIndex has been changed, use it instead of the default
+ if (m_FilterIndex != 0)
+ m_ofn.nFilterIndex = m_FilterIndex;
+
+ if (m_CreateDirectoryCheckboxEnabled) {
+ // Begin customization for the checkbox for new project dialog
+ m_ofn.hInstance = GetModuleHandle(nullptr);
+ m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_NEWPROJEXT);
+ m_ofn.Flags |= OFN_ENABLETEMPLATE;
+ }
+
+ // WINBUG: This is a special case for the file open/save dialog,
+ // which sometimes pumps while it is coming up but before it has
+ // disabled the main window.
+ HWND hWndFocus = ::GetFocus();
+ BOOL bEnableParent = FALSE;
+
+ // OVerride the places bar so that is always shows favorites.
+ RegKeyOverrider regOverrider;
+ m_ofn.hwndOwner = PreModal();
+ AfxUnhookWindowCreate();
+ if (m_ofn.hwndOwner != nullptr && ::IsWindowEnabled(m_ofn.hwndOwner)) {
+ bEnableParent = TRUE;
+ ::EnableWindow(m_ofn.hwndOwner, FALSE);
+ }
+
+ _AFX_THREAD_STATE *pThreadState = AfxGetThreadState();
+ ASSERT(pThreadState->m_pAlternateWndInit == nullptr);
+
+ if (m_ofn.Flags & OFN_EXPLORER)
+ pThreadState->m_pAlternateWndInit = this;
+ else
+ AfxHookWindowCreate(this);
+
+ // This is whre is differs for 2000
+ ::memset(&m_ofnEx, 0, sizeof(m_ofnEx));
+ ::memcpy(&m_ofnEx, &m_ofn, sizeof(m_ofn));
+ // if ( IsWin2000() ){
+ // m_ofnEx.lStructSize = sizeof( m_ofnEx );
+ //}
+
+ int nResult;
+ if (m_bOpenFileDialog)
+ nResult = ::GetOpenFileName(&m_ofnEx);
+ else
+ nResult = ::GetSaveFileName(&m_ofnEx);
+
+ if (nResult == 0) {
+ DWORD error = ::CommDlgExtendedError();
+ if (error) {
+ SErrorMap *theError = nullptr;
+ for (theError = g_ErrorMap; theError->m_Name; ++theError) {
+ if (theError->m_Error == error) {
+ OutputDebugStringA("Massive failure in FileDialogEX!!\n");
+ OutputDebugStringA(theError->m_Name);
+ ASSERT(false);
+ }
+ }
+ }
+ }
+
+ // Copy back m_ofnEx -> m_ofn
+ ::memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));
+ m_ofn.lStructSize = sizeof(m_ofn);
+
+ if (nResult)
+ ASSERT(pThreadState->m_pAlternateWndInit == nullptr);
+ pThreadState->m_pAlternateWndInit = nullptr;
+
+ // WINBUG: Second part of special case for file open/save dialog.
+ if (bEnableParent)
+ ::EnableWindow(m_ofn.hwndOwner, TRUE);
+ if (::IsWindow(hWndFocus))
+ ::SetFocus(hWndFocus);
+
+ PostModal();
+
+ if (nResult) {
+ m_LastFilterIndex = GetOFN().nFilterIndex;
+ }
+
+ return nResult ? nResult : IDCANCEL;
+}
+
+BOOL CFileDialogEx::OnFileNameOK()
+{
+ CFileStatus theFileStatus;
+ CString theFilePath = Q3DStudio::CString(GetOFN().lpstrFile);
+ // CString theFilePath = this->GetPathName(); // Somehow, this does not return the filename
+ // with extension
+ BOOL theReturnValue = FALSE;
+
+ if (m_IsSaving && CFile::GetStatus(theFilePath, theFileStatus)) {
+ if (theFileStatus.m_attribute & CFile::readOnly) {
+ Q3DStudio::CString theMsgTitle;
+ Q3DStudio::CString theMsg;
+ Q3DStudio::CString theFormattedText;
+ Q3DStudio::CString theFileNameText = GetOFN().lpstrFileTitle;
+ // Q3DStudio::CString theFileNameText = GetFileName( );
+
+ theMsgTitle = ::LoadResourceString(IDS_PROJNAME);
+ theMsg = ::LoadResourceString(IDS_SAVE_READONLY_WARNING);
+ theFormattedText.Format(theMsg, static_cast<const wchar_t *>(theFileNameText));
+
+ ::MessageBox(this->GetSafeHwnd(), theFormattedText, theMsgTitle,
+ MB_OK | MB_ICONEXCLAMATION);
+ theReturnValue = TRUE;
+ }
+ }
+
+ return theReturnValue;
+}
+
+void CFileDialogEx::SetInitialDirectory(const Q3DStudio::CString &inDir)
+{
+ Q3DStudio::CFilePath thePath(inDir);
+ if (thePath.IsFile())
+ thePath = thePath.GetDirectory();
+ m_InitialDir = thePath;
+}
+
+void CFileDialogEx::OnCreateNewDirectory()
+{
+ m_WasCreateNewDirectoryChecked = !m_WasCreateNewDirectoryChecked;
+ m_Preferences.SetValue("CreateDirForProject", m_WasCreateNewDirectoryChecked);
+}
+
+//=============================================================================
+/**
+ * Allows the user to set the title of the dialog. By default, the title is
+ * determined by the first parameter of the constructor (bOpenFileDialog).
+ * TRUE specifies a file open dialog and FALSE specifies a Save As dialog.
+ * The title of the window is then generated by the OS. This function enables
+ * you to set the title to any string you want, overriding the OS value.
+ * @param inTitle new title for this dialog; if an empty string is specified,
+ * the OS generated title will be displayed.
+ */
+void CFileDialogEx::SetWindowTitle(const Q3DStudio::CString &inTitle)
+{
+ m_Title = inTitle;
+}
+
+//=============================================================================
+/**
+ * Sets the filter to be selected when the dialog is opened, if specified.
+ * The filter is indexed from 1 to n.
+ *
+ * @param inFilterIndex the index of the filter to be applied as the default
+ * extension to be used when displaying the dialog.
+ * @author AT May 29 2003
+ */
+void CFileDialogEx::SetFilterIndex(const LONG inFilterIndex)
+{
+ m_FilterIndex = inFilterIndex;
+}
+
+BOOL CFileDialogEx::OnInitDialog()
+{
+ BOOL retval = CFileDialog::OnInitDialog();
+ if (m_CreateDirectoryCheckboxEnabled) {
+ CWnd *theWnd = GetDlgItem(IDC_CHECK1);
+ if (theWnd) {
+ m_WasCreateNewDirectoryChecked =
+ m_Preferences.GetValue("CreateDirForProject", true) ? 1 : 0;
+ Button_SetCheck(theWnd->GetSafeHwnd(), m_WasCreateNewDirectoryChecked ? 1 : 0);
+ }
+ }
+ return retval;
+}
+
+//=============================================================================
+/**
+ * Gets the filter index when the dialog is opened.
+ * The filter is indexed from 1 to n.
+ * The member was set at the end of DoModal.
+ *
+ * @return the filter index, starting from 1 to n
+ */
+long CFileDialogEx::GetLastFilterIndex()
+{
+ return m_LastFilterIndex;
+}
+
+//=============================================================================
+/**
+ * Retrieves the list of files selected during multiple selection
+ * @param outFileList vector to hold filenames
+ */
+void CFileDialogEx::RetrieveFileList(TFILELIST &outFileList) const
+{
+ outFileList.clear();
+ POSITION theStartPosition = GetStartPosition();
+
+ Q3DStudio::CString theFileName;
+ while (nullptr != theStartPosition) {
+ theFileName = GetNextPathName(theStartPosition);
+ outFileList.push_back(CUICFile(theFileName));
+ }
+}
diff --git a/src/Authoring/Studio/_Win/UI/FileDialogEX.h b/src/Authoring/Studio/_Win/UI/FileDialogEX.h
new file mode 100644
index 00000000..ad82de14
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/FileDialogEX.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#if !defined(AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_)
+#define AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+struct OPENFILENAMEEX : public OPENFILENAME
+{
+ void *pvReserved;
+ DWORD dwReserved;
+ DWORD FlagsEx;
+};
+
+//==============================================================================
+/**
+ * CFileDialog: Extends the regular CFileDialog for win2k dialog box
+ */
+//==============================================================================
+class CFileDialogEx : public CFileDialog
+{
+ DECLARE_DYNAMIC(CFileDialogEx)
+
+public:
+ typedef std::vector<CUICFile> TFILELIST;
+ OPENFILENAMEEX m_ofnEx; ///< Extra structure passed in for win 2k dialog
+
+ //==========================================================================
+ // Methods
+ //==========================================================================
+ CFileDialogEx(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
+ LPCTSTR lpszDefExt = nullptr, LPCTSTR lpszFileName = nullptr,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = nullptr,
+ CWnd *pParentWnd = nullptr);
+
+ virtual ~CFileDialogEx();
+
+ void EnableCreateDirectoryCheckbox();
+ virtual void SetInitialDirectory(const Q3DStudio::CString &inDir);
+ virtual void SetWindowTitle(const Q3DStudio::CString &inTitle);
+ virtual void SetFilterIndex(const LONG inFilterIndex);
+ virtual BOOL OnInitDialog();
+ long GetLastFilterIndex();
+ void RetrieveFileList(TFILELIST &outFileList) const;
+
+ virtual INT_PTR DoModal();
+ virtual BOOL OnFileNameOK();
+ void IsSaving() { m_IsSaving = TRUE; }
+ bool WasCreateNewDirectoryChecked() { return m_WasCreateNewDirectoryChecked; }
+
+protected:
+ BOOL m_IsSaving;
+ Q3DStudio::CString m_InitialDir;
+ Q3DStudio::CString m_Title;
+ LONG m_FilterIndex;
+ long m_LastFilterIndex; //< the last filter index for when a file was selected
+ wchar_t *m_FileListBuffer;
+ bool m_CreateDirectoryCheckboxEnabled;
+ bool m_WasCreateNewDirectoryChecked;
+ // We have to cache a CPreferences here because we reroute the registry during
+ // doModal in order to make the file dialogue behavior differently.
+ // see RegKeyOverrider
+ CPreferences m_Preferences;
+
+ //==========================================================================
+ // Members
+ //==========================================================================
+
+ // Generated message map functions
+ //{{AFX_MSG(CFileDialogEx)
+ afx_msg void OnCreateNewDirectory();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp b/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp
new file mode 100644
index 00000000..cb02578b
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "GLVersionDlg.h"
+
+CGLVersionDlg::CGLVersionDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CGLVersionDlg::IDD, pParent)
+{
+ m_Title = _T("");
+ m_Message = _T("");
+ m_Icon = nullptr;
+ m_DontShowAgain = FALSE;
+}
+
+CGLVersionDlg::~CGLVersionDlg()
+{
+}
+
+void CGLVersionDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_GL_VERSION_ICON, m_WarningIcon);
+ DDX_Text(pDX, IDC_GL_VERSION_MESSAGE, m_Message);
+ DDX_Check(pDX, IDC_CHECK1, m_DontShowAgain);
+}
+
+BEGIN_MESSAGE_MAP(CGLVersionDlg, CDialog)
+END_MESSAGE_MAP()
+
+BOOL CGLVersionDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Set the title
+ this->SetWindowText(m_Title);
+
+ // Set icon
+ m_WarningIcon.SetIcon(::AfxGetApp()->LoadStandardIcon(m_Icon));
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CGLVersionDlg::Initialize(const Q3DStudio::CString &inTitle,
+ const Q3DStudio::CString &inMessage, bool inErrorIcon)
+{
+ // Set title and message
+ m_Title = CString(inTitle);
+ m_Message = CString(inMessage);
+
+ // Set which icon to load
+ if (inErrorIcon)
+ m_Icon = IDI_ERROR;
+ else
+ m_Icon = IDI_WARNING;
+}
+
+BOOL CGLVersionDlg::GetDontShowAgain()
+{
+ return m_DontShowAgain;
+}
diff --git a/src/Authoring/Studio/_Win/UI/GLVersionDlg.h b/src/Authoring/Studio/_Win/UI/GLVersionDlg.h
new file mode 100644
index 00000000..908a8441
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/GLVersionDlg.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_GL_VERSION_DLG
+#define INCLUDED_GL_VERSION_DLG 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "resource.h"
+
+//==============================================================================
+/**
+ * CGLVersionDlg: Dialog class for showing Open GL Version Warning
+ */
+//==============================================================================
+class CGLVersionDlg : public CDialog
+{
+public:
+ CGLVersionDlg(CWnd *pParent = nullptr); // standard constructor
+ virtual ~CGLVersionDlg();
+
+ // Dialog Data
+ enum { IDD = IDD_GL_VERSION_DLG };
+
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+
+ DECLARE_MESSAGE_MAP()
+ CStatic m_WarningIcon; // Warning icon
+ CString m_Title; // Title for the dialog
+ CString m_Message; // Warning message
+ BOOL m_DontShowAgain; // Set to true to "Don't show this dialog again"
+ LPCTSTR m_Icon; // Which icon to load
+
+public:
+ virtual BOOL OnInitDialog();
+ void Initialize(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inMessage,
+ bool inErrorIcon);
+ BOOL GetDontShowAgain();
+};
+
+#endif // INCLUDED_GL_VERSION_DLG
diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp b/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp
new file mode 100644
index 00000000..57d6ae1d
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix / Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "InterpolationDlg.h"
+#include "ui_InterpolationDlg.h"
+
+//==============================================================================
+/**
+ * Constructor: Creates a CInterpolationDlg.
+ *
+ * @param parent Pointer to the parent of this dialog (defaults to NULL)
+ */
+//==============================================================================
+CInterpolationDlg::CInterpolationDlg(QWidget *parent)
+ : QDialog(parent)
+ , m_ui(new Ui::InterpolationDlg)
+{
+ m_ui->setupUi(this);
+}
+
+CInterpolationDlg::~CInterpolationDlg()
+{
+ delete m_ui;
+ m_ui = nullptr;
+}
+
+void CInterpolationDlg::setEaseIn(uint value)
+{
+ m_ui->easeInSlider->setValue(value);
+}
+
+void CInterpolationDlg::setEaseOut(uint value)
+{
+ m_ui->easeOutSlider->setValue(value);
+}
+
+int CInterpolationDlg::easeIn() const
+{
+ return m_ui->easeInSlider->value();
+}
+
+int CInterpolationDlg::easeOut() const
+{
+ return m_ui->easeOutSlider->value();
+}
+
+
diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.h b/src/Authoring/Studio/_Win/UI/InterpolationDlg.h
new file mode 100644
index 00000000..5f371625
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_INTERPOLATION_DLG
+#define INCLUDED_INTERPOLATION_DLG 1
+
+#pragma once
+
+#include <QDialog>
+
+namespace Ui {
+class InterpolationDlg;
+}
+
+//==============================================================================
+/**
+ * CInterpolationDlg: Dialog class for editing the ease-in/ease-out values of keyframes.
+ */
+//==============================================================================
+class CInterpolationDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit CInterpolationDlg(QWidget *parent = nullptr); // standard constructor
+ ~CInterpolationDlg();
+
+ void setEaseIn(uint value);
+ void setEaseOut(uint value);
+ int easeIn() const;
+ int easeOut() const;
+
+protected:
+ Ui::InterpolationDlg* m_ui = nullptr;
+};
+
+#endif // INCLUDED_INTERPOLATION_DLG
diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui b/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui
new file mode 100644
index 00000000..f0a0a759
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InterpolationDlg</class>
+ <widget class="QDialog" name="InterpolationDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>425</width>
+ <height>195</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Set Keyframe Interpolation</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1" colspan="2">
+ <widget class="QSlider" name="easeOutSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ease In:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smooth</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <widget class="QSlider" name="easeInSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smooth</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ease Out:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QSpinBox" name="easeInSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QSpinBox" name="easeOutSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>InterpolationDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>224</x>
+ <y>272</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>InterpolationDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeInSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeInSpinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>331</x>
+ <y>21</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>542</x>
+ <y>35</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeOutSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeOutSpinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>210</x>
+ <y>93</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>545</x>
+ <y>93</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeInSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeInSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>533</x>
+ <y>24</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>408</x>
+ <y>18</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeOutSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeOutSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>546</x>
+ <y>98</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>338</x>
+ <y>84</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/MemoryDC.cpp b/src/Authoring/Studio/_Win/UI/MemoryDC.cpp
new file mode 100644
index 00000000..a253e89a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MemoryDC.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "resource.h"
+#include "MemoryDC.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CMemoryDC
+
+//==============================================================================
+/*
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CMemoryDC::CMemoryDC()
+ : m_ValidFlag(FALSE)
+ , m_SrcDC(nullptr)
+ , m_OldBmp(nullptr)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CMemoryDC::~CMemoryDC()
+{
+ // automatically release and draw on exit
+ Release();
+}
+
+//==============================================================================
+/**
+ * Create
+ *
+ * Creates the memory DC and image bitmap
+ *
+ * @param inDC Source device context
+ * @param inSrcRect CRect containing the source rectangle for drawing
+ */
+//==============================================================================
+void CMemoryDC::Create(CDC *inDC, CRect inSrcRect)
+{
+ ASSERT(inDC != nullptr);
+
+ if (!m_ValidFlag) {
+ // create the memory DC
+ CreateCompatibleDC(inDC);
+
+ // save the source DC
+ m_SrcDC = inDC;
+
+ // keep track of the destination rectangle
+ m_SrcRect.CopyRect(inSrcRect);
+
+ // create a bitmap for the memory bitmap image
+ m_MemBmp.CreateCompatibleBitmap(inDC, inSrcRect.Width(), inSrcRect.Height());
+
+ // select the memory image into the memory DC
+ m_OldBmp = SelectObject(&m_MemBmp);
+
+ m_ValidFlag = TRUE;
+ }
+}
+
+//==============================================================================
+/**
+ * Release
+ *
+ * Releases the memory DC and image bitmap and optionally copies the image
+ * to the source DC.
+ *
+ * @param inCopyToSourceFlag If TRUE, copies the memory image to the source DC
+ */
+//==============================================================================
+void CMemoryDC::Release(BOOL inCopyToSourceFlag)
+{
+ // copy the offscreen buffer to the sourceDC passed in Create()
+
+ if (m_ValidFlag) {
+ // blit to source DC to the m_SrcRect
+ if ((inCopyToSourceFlag) && (m_SrcDC != nullptr))
+ m_SrcDC->BitBlt(m_SrcRect.left, m_SrcRect.top, m_SrcRect.Width(), m_SrcRect.Height(),
+ this, 0, 0, SRCCOPY);
+
+ // de-select the memory image from the DC
+ SelectObject(m_OldBmp);
+
+ // delete the memory bitmap image
+ m_MemBmp.DeleteObject();
+
+ // delete the memory DC
+ DeleteDC();
+
+ m_ValidFlag = FALSE;
+ m_OldBmp = nullptr;
+ }
+}
+
+//==============================================================================
+/**
+ * CopySourceImage
+ *
+ * Copies the source image from the m_SrcRect into the memory DC/image.
+ *
+ * @param None
+ */
+//==============================================================================
+void CMemoryDC::CopySourceImage()
+{
+ if (m_ValidFlag) {
+ // copy the image from the source rectangle to the offscreen image
+ if (m_SrcDC != nullptr)
+ this->BitBlt(0, 0, m_SrcRect.Width(), m_SrcRect.Height(), m_SrcDC, m_SrcRect.left,
+ m_SrcRect.top, SRCCOPY);
+ }
+}
+
+//==============================================================================
+/**
+ * ConvertRect
+ *
+ * Converts a rectangle based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inDrawRect Source drawing CRect
+ *
+ * @return CRect Contains the converted rectangle
+ */
+//==============================================================================
+CRect CMemoryDC::ConvertRect(CRect inDrawRect)
+{
+ CRect theRect;
+
+ theRect.CopyRect(inDrawRect);
+ theRect.OffsetRect(-m_SrcRect.left, -m_SrcRect.top);
+
+ return theRect;
+}
+
+//==============================================================================
+/**
+ * ConvertPoint
+ *
+ * Converts a point based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inDrawRect Source drawing CPoint
+ *
+ * @return CPoint Contains the converted point
+ */
+//==============================================================================
+CPoint CMemoryDC::ConvertPoint(CPoint inDrawPoint)
+{
+ CPoint thePoint;
+
+ // convert point relative to this DC
+ thePoint = inDrawPoint;
+ thePoint.x -= m_SrcRect.left;
+ thePoint.y -= m_SrcRect.top;
+
+ return thePoint;
+}
+
+//==============================================================================
+/**
+ * ConvertXPos
+ *
+ * Converts an x-position based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inXValue Source drawing x-position
+ *
+ * @return long Contains the converted x-position
+ */
+//==============================================================================
+long CMemoryDC::ConvertXPos(long inXValue)
+{
+ long theXPos;
+
+ // convert x coordinate relative to this DC
+ theXPos = (long)inXValue - (long)m_SrcRect.left;
+
+ return theXPos;
+}
+
+//==============================================================================
+/**
+ * ConvertYPos
+ *
+ * Converts an y-position based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inYValue Source drawing y-position
+ *
+ * @return long Contains the converted y-position
+ */
+//==============================================================================
+long CMemoryDC::ConvertYPos(long inYValue)
+{
+ long theYPos;
+
+ // convert y coordinate relative to this DC
+ theYPos = (long)inYValue - (long)m_SrcRect.top;
+
+ return theYPos;
+}
+
+//==============================================================================
+/**
+ * SetRect
+ *
+ * Sets the drawing/output bounding rectangle.
+ *
+ * @param inRect Bounding rectangle for drawing
+ */
+//==============================================================================
+void CMemoryDC::SetRect(CRect inRect)
+{
+ m_SrcRect = inRect;
+}
diff --git a/src/Authoring/Studio/_Win/UI/MemoryDC.h b/src/Authoring/Studio/_Win/UI/MemoryDC.h
new file mode 100644
index 00000000..f72701e0
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MemoryDC.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MEMORY_DC_H
+#define INCLUDED_MEMORY_DC_H
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+/**
+ * CMemoryDC: Subclassed CDC for drawing offscreen
+ *
+ * This is a subclassed CDC so we can control drawing into a DC with offscreen
+ * buffers to prevent flickering.
+ */
+//==============================================================================
+
+class CMemoryDC : public CDC
+{
+public:
+ //==========================================================================
+ // Fields
+ //==========================================================================
+
+protected:
+ BOOL m_ValidFlag; // TRUE if we can successfully release/copy the offscreen image to the screen
+ CRect m_SrcRect; // Bounding rectangle for drawing
+ CBitmap m_MemBmp; // Offscreen bitmap image
+ CBitmap *m_OldBmp; // Previous bitmap in the offscreen DC
+ CDC *m_SrcDC; // Source device context for final blit
+
+ //==========================================================================
+ // Methods
+ //==========================================================================
+
+public:
+ void SetRect(CRect inRect);
+
+ // Construction
+
+ CMemoryDC();
+ virtual ~CMemoryDC();
+
+ // Access
+
+ CPoint ConvertPoint(CPoint inDrawPoint);
+ CRect ConvertRect(CRect inDrawRect);
+ long ConvertXPos(long inXValue);
+ long ConvertYPos(long inYValue);
+ void CopySourceImage();
+ void Create(CDC *inDC, CRect inSrcRect);
+
+ void Release(BOOL inCopyToSourceFlag = TRUE);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // INCLUDED_MEMORY_DC_H
diff --git a/src/Authoring/Studio/_Win/UI/MenuEdit.cpp b/src/Authoring/Studio/_Win/UI/MenuEdit.cpp
new file mode 100644
index 00000000..39c82246
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuEdit.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "MenuEdit.h"
+#include "BCMenu.h"
+#include "StudioColors.h"
+
+//==============================================================================
+// Message Map
+//==============================================================================
+
+BEGIN_MESSAGE_MAP(CMenuEdit, CEdit)
+//{{AFX_MSG_MAP(CMenuEdit)
+ON_WM_SETFOCUS()
+ON_WM_CONTEXTMENU()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Constructor: Creates a CMenuEdit
+ */
+//==============================================================================
+CMenuEdit::CMenuEdit()
+{
+}
+
+//==============================================================================
+/**
+ * OnSetFocus: The message handler for accepting focus.
+ *
+ * @param pOldWnd The window that had focus last.
+ */
+//==============================================================================
+void CMenuEdit::OnSetFocus(CWnd *pOldWnd)
+{
+ // Allow the parent to handle the request.
+ CEdit::OnSetFocus(pOldWnd);
+
+ // Select the entire text.
+ this->SetSel(0, -1);
+}
+
+//******************************************************************************
+// DYNAMIC CREATION
+//******************************************************************************
+
+IMPLEMENT_DYNAMIC(CMenuEdit, CEdit)
+
+//==============================================================================
+/**
+ * OnContextMenu: WM_CONTEXTMENU handler for the CMenuEdit.
+ *
+ * @param inWnd This window.
+ * @param inPoint Mouse position when the right button was clicked.
+ */
+//==============================================================================
+void CMenuEdit::OnContextMenu(CWnd *inWnd, CPoint inPoint)
+{
+ Q_UNUSED(inWnd);
+
+ // Added just because Justin has an eye for detail. :)
+
+ BCMenu theMenu;
+ BCMenu *thePopupMenu = nullptr;
+ long theMenuCmd;
+
+ if (GetFocus() != this)
+ this->SetFocus();
+
+ // Load the context menu
+ theMenu.LoadMenu(IDR_CONTEXT_EDIT);
+#ifdef _USECONTENTMENUIMAGES_
+ theMenu.SetBitmapBackground(MENU_IMAGELIST_BACKCOLOR);
+ theMenu.LoadToolbar(IDC_EDITCONTEXTTOOLBAR);
+#endif
+
+ thePopupMenu = (BCMenu *)theMenu.GetSubMenu(0);
+
+ // Enable/disable menu items
+ if (!this->CanUndo())
+ thePopupMenu->EnableMenuItem(IDC_UNDO, MF_BYCOMMAND | MF_GRAYED);
+
+ // Disable the Select All if there is no text in the control
+ if (this->GetWindowTextLength() == 0)
+ thePopupMenu->EnableMenuItem(IDC_SELECTALL, MF_BYCOMMAND | MF_GRAYED);
+
+ // Disable paste if there is no CF_TEXT on the clipboard
+ if (!IsClipboardFormatAvailable(CF_TEXT))
+ thePopupMenu->EnableMenuItem(IDC_PASTE, MF_BYCOMMAND | MF_GRAYED);
+
+ // Check if any text is selected
+ DWORD theSelection = this->GetSel();
+ if (LOWORD(theSelection) == HIWORD(theSelection)) {
+ // Disable cut, copy and delete commands if no text is selected
+ thePopupMenu->EnableMenuItem(IDC_CUT, MF_BYCOMMAND | MF_GRAYED);
+ thePopupMenu->EnableMenuItem(IDC_COPY, MF_BYCOMMAND | MF_GRAYED);
+ thePopupMenu->EnableMenuItem(IDC_DELETE, MF_BYCOMMAND | MF_GRAYED);
+ }
+
+ // Post the menu and handle the command here.
+ theMenuCmd = (long)thePopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD
+ | TPM_NONOTIFY,
+ inPoint.x, inPoint.y, this, nullptr);
+ switch (theMenuCmd) {
+ case IDC_UNDO:
+ this->Undo();
+ break;
+
+ case IDC_CUT:
+ this->Cut();
+ break;
+
+ case IDC_COPY:
+ this->Copy();
+ break;
+
+ case IDC_PASTE:
+ this->Paste();
+ break;
+
+ case IDC_DELETE:
+ // Delete the selected text
+ this->ReplaceSel(L"", FALSE);
+ break;
+
+ case IDC_SELECTALL:
+ // Select the entire text.
+ this->SetSel(0, -1);
+ break;
+ }
+
+ theMenu.DestroyMenu();
+}
diff --git a/src/Authoring/Studio/_Win/UI/MenuEdit.h b/src/Authoring/Studio/_Win/UI/MenuEdit.h
new file mode 100644
index 00000000..9aae97e2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuEdit.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef _MENUEDIT_H_
+#define _MENUEDIT_H_
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CMenuEdit
+ * @brief This edit control has a BCMenu context menu.
+ */
+//==============================================================================
+class CMenuEdit : public CEdit
+{
+ // Fields
+
+public:
+ // Methods
+
+public:
+ DECLARE_DYNAMIC(CMenuEdit)
+ CMenuEdit();
+ virtual ~CMenuEdit() {}
+
+protected:
+ //{{AFX_MSG(CMenuEdit)
+ afx_msg void OnSetFocus(CWnd *pOldWnd);
+ afx_msg void OnContextMenu(CWnd *pWnd, CPoint point);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // _MENUEDIT_H_
diff --git a/src/Authoring/Studio/_Win/UI/MenuItem.cpp b/src/Authoring/Studio/_Win/UI/MenuItem.cpp
new file mode 100644
index 00000000..beb77d98
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuItem.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "MenuItem.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+//==============================================================================
+/**
+ * CMenuItem: constructor
+ *
+ * @param inName name of the file
+ * @param inPath path to the file
+ * @param inID ID tag for this handler in the menu
+ */
+//==============================================================================
+CMenuItem::CMenuItem(CString inName, CString inPath, UINT inID)
+{
+ m_Name = inName;
+ m_ID = inID;
+ m_Path = inPath;
+}
+
+CMenuItem::~CMenuItem()
+{
+}
diff --git a/src/Authoring/Studio/_Win/UI/MenuItem.h b/src/Authoring/Studio/_Win/UI/MenuItem.h
new file mode 100644
index 00000000..f8033b81
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuItem.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_)
+#define AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// CMenuItem Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * CMenuItem: Object for creating dynamic menus
+ */
+//==============================================================================
+class CMenuItem : public CObject
+{
+public:
+ CMenuItem(CString inName, CString inPath, UINT inID);
+ virtual ~CMenuItem();
+ UINT GetID() { return m_ID; };
+ CString GetPath() { return m_Path; };
+ CString GetName() { return m_Name; };
+protected:
+ CString m_Path; ///< Path to the file
+ CString m_Name; ///< Name to use in the menu
+ UINT m_ID; ///< ID of this menu item
+};
+
+#endif // !defined(AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/NumericEdit.cpp b/src/Authoring/Studio/_Win/UI/NumericEdit.cpp
new file mode 100644
index 00000000..73ff7bc8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/NumericEdit.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "NumericEdit.h"
+
+#include <minmax.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumericEdit class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CNumericEdit::CNumericEdit()
+{
+ m_RangeLow = -1;
+ m_RangeHigh = -1;
+
+ m_WrapFlag = FALSE;
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CNumericEdit::~CNumericEdit()
+{
+}
+
+//=============================================================================
+/**
+ * Message Map
+ */
+//=============================================================================
+BEGIN_MESSAGE_MAP(CNumericEdit, CEdit)
+//{{AFX_MSG_MAP(CNumericEdit)
+ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillFocus)
+ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
+ON_WM_CHAR()
+ON_WM_MOUSEWHEEL()
+ON_WM_KEYDOWN()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//=============================================================================
+/**
+ * SetRange: Sets the value range for this control.
+ *
+ * @param inRangeLow Low range.
+ * @param inRangeHigh High range
+ */
+//=============================================================================
+void CNumericEdit::SetRange(long inRangeLow, long inRangeHigh)
+{
+ // Ensure they are in low/high order
+ m_RangeLow = min(inRangeLow, inRangeHigh);
+ m_RangeHigh = max(inRangeLow, inRangeHigh);
+}
+
+//=============================================================================
+/**
+ * SetValue: Sets the numeric value for this control.
+ *
+ * @param inValue The new value for this control.
+ */
+//=============================================================================
+void CNumericEdit::SetValue(long inValue)
+{
+ CString theStrValue;
+
+ theStrValue.Format(L"%lu", inValue);
+ this->SetWindowText(theStrValue);
+}
+
+//=============================================================================
+/**
+ * GetValue: Returns the numeric value for this control.
+ *
+ * @param None
+ *
+ * @return long The numeric value for this control.
+ */
+//=============================================================================
+long CNumericEdit::GetValue()
+{
+ CString theStrValue;
+
+ // Get the current control value.
+ this->GetWindowText(theStrValue);
+
+ // Convert to long and return.
+ return atol((char *)LPCTSTR(theStrValue));
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumericEdit message handlers
+
+//=============================================================================
+/**
+ * OnKillFocus: Handle the EN_KILLFOCUS and validate data.
+ *
+ * @param None
+ */
+//=============================================================================
+void CNumericEdit::OnKillFocus()
+{
+ this->ValidateData();
+}
+
+//=============================================================================
+/**
+ * OnUpdate: Handle the EN_UPDATE and handle validation before the control is updated.
+ *
+ * @param None
+ */
+//=============================================================================
+void CNumericEdit::OnUpdate()
+{
+ // TODO: If this is a RICHEDIT control, the control will not
+ // send this notification unless you override the CEdit::OnInitDialog()
+ // function to send the EM_SETEVENTMASK message to the control
+ // with the ENM_UPDATE flag ORed into the lParam mask.
+
+ // TODO: Add your control notification handler code here
+
+ this->ValidateData();
+}
+
+//=============================================================================
+/**
+ * OnChar: Handle the WM_CHAR and validate the key that was pressed.
+ *
+ * @param inChar
+ * @param inRepCnt
+ * @param inFlags
+ */
+//=============================================================================
+void CNumericEdit::OnChar(UINT inChar, UINT inRepCnt, UINT inFlags)
+{
+ if (IsNumeric(inChar) || IsEditKey(inChar)) {
+ CEdit::OnChar(inChar, inRepCnt, inFlags);
+ }
+}
+
+//=============================================================================
+/**
+ * OnKeyDown: Handle the WM_KEYDOWN and validate the key that was pressed.
+ *
+ * @param inChar
+ * @param inRepCnt
+ * @param inFlags
+ */
+//=============================================================================
+void CNumericEdit::OnKeyDown(UINT inChar, UINT inRepCnt, UINT inFlags)
+{
+ if (inChar == VK_UP) {
+ this->IncrementValue(+1);
+ this->SetSel(0, -1);
+ } else if (inChar == VK_DOWN) {
+ this->IncrementValue(-1);
+ this->SetSel(0, -1);
+ } else {
+ CEdit::OnKeyDown(inChar, inRepCnt, inFlags);
+ }
+}
+
+//=============================================================================
+/**
+ * IsEditKey: Determine if the pressed key was an edit key.
+ *
+ * @param inChar Key character value.
+ *
+ * @return TRUE if an editing key
+ */
+//=============================================================================
+BOOL CNumericEdit::IsEditKey(UINT inChar)
+{
+ BOOL theEditKeyFlag = FALSE;
+
+ if (inChar == VK_DELETE || inChar == VK_BACK || inChar == VK_LEFT || inChar == VK_RIGHT
+ || inChar == VK_HOME || inChar == VK_END || inChar == VK_UP || inChar == VK_DOWN)
+ theEditKeyFlag = TRUE;
+
+ return theEditKeyFlag;
+}
+
+//=============================================================================
+/**
+ * IsNumeric: Determine if the pressed key was a numeric key.
+ *
+ * @param inChar Key character value.
+ *
+ * @return TRUE if a numeric key
+ */
+//=============================================================================
+BOOL CNumericEdit::IsNumeric(UINT inChar)
+{
+ CString theNumericCheck = L"0123456789";
+ BOOL theNumericFlag = FALSE;
+
+ // Determine if the character is a numeric value.
+ if (theNumericCheck.Find((TCHAR)inChar) != -1) {
+ theNumericFlag = TRUE;
+ }
+
+ return theNumericFlag;
+}
+
+//=============================================================================
+/**
+ * ValidateData: Validates the value in the control to keep within range.
+ *
+ * @param None
+ */
+//=============================================================================
+void CNumericEdit::ValidateData()
+{
+ CString theStrValue;
+ long theValue = 0;
+ BOOL theChangeFlag = FALSE;
+
+ // Get the current text in the control.
+ this->GetWindowText(theStrValue);
+ if (theStrValue.GetLength() == 0) {
+ theValue = 0;
+ theChangeFlag = TRUE;
+ } else
+ // Check to see that a range has been set
+ if (m_RangeLow != -1 && m_RangeHigh != -1) {
+ theValue = this->GetValue();
+
+ // Check against the low and high range
+ if (theValue < m_RangeLow) {
+ theValue = m_RangeLow;
+ theChangeFlag = TRUE;
+ } else if (theValue > m_RangeHigh) {
+ theValue = m_RangeHigh;
+ theChangeFlag = TRUE;
+ }
+ }
+
+ // Has the value changed?
+ if (theChangeFlag) {
+ // Update the control's value.
+ this->SetValue(theValue);
+ this->SetSel(0, -1);
+ }
+}
+
+//=============================================================================
+/**
+ * IncrementValue: Increments the current value by inAmount
+ *
+ * @param inAmount Amount to change the current control value.
+ */
+//=============================================================================
+void CNumericEdit::IncrementValue(long inAmount)
+{
+ long theValue;
+
+ // Get the current value
+ theValue = this->GetValue();
+
+ // Change theValue
+ theValue += inAmount;
+
+ // Has a range been set?
+ if (m_RangeLow != -1 && m_RangeHigh != -1) {
+ if (theValue < m_RangeLow) {
+ theValue = m_RangeLow;
+
+ if (m_WrapFlag)
+ theValue = m_RangeHigh;
+ } else if (theValue > m_RangeHigh) {
+ theValue = m_RangeHigh;
+
+ if (m_WrapFlag)
+ theValue = m_RangeLow;
+ }
+ }
+
+ this->SetValue(theValue);
+}
+
+//=============================================================================
+/**
+ * OnMouseWheel: Handle the WM_MOUSEWHEEL message.
+ *
+ * @param inFlags
+ * @param inzDelta
+ * @param inPoint
+ *
+ * @return TRUE if processed.
+ */
+//=============================================================================
+BOOL CNumericEdit::OnMouseWheel(UINT inFlags, short inzDelta, CPoint inPoint)
+{
+ long theWheelDelta = 0;
+
+ if (inzDelta != 0)
+ theWheelDelta = inzDelta / abs(inzDelta);
+
+ this->IncrementValue(theWheelDelta);
+
+ this->SetSel(0, -1);
+
+ return CEdit::OnMouseWheel(inFlags, inzDelta, inPoint);
+}
diff --git a/src/Authoring/Studio/_Win/UI/NumericEdit.h b/src/Authoring/Studio/_Win/UI/NumericEdit.h
new file mode 100644
index 00000000..61a4017a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/NumericEdit.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_)
+#define AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "MenuEdit.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumericEdit window
+
+class CNumericEdit : public CMenuEdit
+{
+ // Construction
+public:
+ CNumericEdit();
+
+ // Attributes
+public:
+ void SetAllowWrap(BOOL inWrapFlag) { m_WrapFlag = inWrapFlag; }
+
+protected:
+ long m_RangeLow, m_RangeHigh;
+ BOOL m_WrapFlag;
+
+ // Operations
+public:
+ long GetValue();
+
+ void SetRange(long inRangeLow, long inRangeHigh);
+ void SetValue(long inValue);
+
+protected:
+ void IncrementValue(long inAmount);
+ BOOL IsEditKey(UINT inChar);
+ BOOL IsNumeric(UINT inChar);
+
+ void ValidateData();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CNumericEdit)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CNumericEdit();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CNumericEdit)
+ afx_msg void OnKillFocus();
+ afx_msg void OnUpdate();
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp
new file mode 100644
index 00000000..64d7e2f0
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp
@@ -0,0 +1,510 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "UICOptions.h"
+#include "SceneView.h"
+#include "Doc.h"
+#include "StudioProjectSettings.h"
+#include "Dispatch.h"
+#include "HotKeys.h"
+#include "MasterP.h"
+#include "StudioApp.h"
+#include "IStudioRenderer.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "PlatformStrings.h"
+#include "PlayerContainerWnd.h"
+#include "UICDMStudioSystem.h"
+#include "Core.h"
+#include "MainFrm.h"
+#include "StudioUtils.h"
+
+#include <QtWidgets/qscrollbar.h>
+#include <QtGui/qevent.h>
+
+//==============================================================================
+// Class CPlayerContainerWnd
+//==============================================================================
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CPlayerContainerWnd::CPlayerContainerWnd(CSceneView *inSceneView)
+ : QAbstractScrollArea(inSceneView)
+ , m_SceneView(inSceneView)
+ , m_PlayerWnd(NULL)
+ , m_IsMouseDown(false)
+ , m_IsMiddleMouseDown(false)
+ , m_ViewMode(VIEW_SCENE)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CPlayerContainerWnd::~CPlayerContainerWnd()
+{
+}
+
+bool CPlayerContainerWnd::ShouldHideScrollBars()
+{
+ return m_ViewMode == VIEW_EDIT || g_StudioApp.IsAuthorZoom();
+}
+
+//==============================================================================
+/**
+ * SetPlayerWndPosition: Sets the position of the child player window
+ *
+ * Called when the view is scrolled to position the child player window
+ * @param outLeftPresentationEdge the left edge of the presentation, with the scroll position
+ *taken into consideration
+ * @param outTopPresentionEdge the top edge of the presentation, with the scroll
+ *position taken into consideration
+ *
+ */
+//==============================================================================
+void CPlayerContainerWnd::SetPlayerWndPosition(long &outLeftPresentationEdge,
+ long &outTopPresentionEdge)
+{
+ long theHScrollPosition, theVScrollPosition;
+ // Negate to adjust actual client positions
+ theHScrollPosition = -horizontalScrollBar()->value();
+ theVScrollPosition = -verticalScrollBar()->value();
+
+ QRect theClientRect = rect();
+
+ // Horizontal scrollbar does not exist
+ if (m_ClientRect.width() < theClientRect.width()) {
+ theHScrollPosition =
+ theClientRect.left() + (theClientRect.width() / 2) - (m_ClientRect.width() / 2);
+ outLeftPresentationEdge = theHScrollPosition;
+ } else // This stays a negated value
+ outLeftPresentationEdge = theHScrollPosition;
+
+ // Vertical scrollbar does not exist
+ if (m_ClientRect.height() < theClientRect.height()) {
+ theVScrollPosition =
+ theClientRect.top() + (theClientRect.height() / 2) - (m_ClientRect.height() / 2);
+ outTopPresentionEdge = theVScrollPosition;
+ } else // This stays a negated value
+ outTopPresentionEdge = theVScrollPosition;
+
+ // Move the child player window
+ m_PlayerWnd->setGeometry(QRect(QPoint(theHScrollPosition, theVScrollPosition), m_ClientRect.size()));
+}
+
+//==============================================================================
+/**
+ * SetScrollRanges: Sets the scroll ranges when the view is being resized
+ */
+//==============================================================================
+void CPlayerContainerWnd::SetScrollRanges()
+{
+
+ long theScrollWidth = 0;
+ long theScrollHeight = 0;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (ShouldHideScrollBars()) {
+ horizontalScrollBar()->setRange(0, 0);
+ verticalScrollBar()->setRange(0, 0);
+ horizontalScrollBar()->setValue(0);
+ verticalScrollBar()->setValue(0);
+ } else
+#endif
+ {
+ QSize theSize = GetEffectivePresentationSize();
+
+ theScrollWidth = theSize.width();
+ theScrollHeight = theSize.height();
+
+
+ // Set scrollbar ranges
+ horizontalScrollBar()->setRange(0, theScrollWidth - width());
+ verticalScrollBar()->setRange(0, theScrollHeight - height());
+ horizontalScrollBar()->setPageStep(width());
+ verticalScrollBar()->setPageStep(height());
+ horizontalScrollBar()->setVisible(true);
+ verticalScrollBar()->setVisible(true);
+ }
+}
+
+//==============================================================================
+/**
+ * OnRulerGuideToggled:
+ * Handle scrollbar position when ruler, guide has been toggled
+ *
+ */
+//==============================================================================
+void CPlayerContainerWnd::OnRulerGuideToggled()
+{
+ int scrollAmount = g_StudioApp.GetRenderer().AreGuidesEnabled() ? 16 : -16;
+ bool hasHorz = horizontalScrollBar()->isVisible();
+ bool hasVert = verticalScrollBar()->isVisible();
+ int hscrollPos = 0, vscrollPos = 0;
+ if (hasHorz) {
+ hscrollPos = qMax(horizontalScrollBar()->value() + scrollAmount, 0);
+ }
+ if (hasVert) {
+ vscrollPos = qMax(verticalScrollBar()->value() + scrollAmount, 0);
+ }
+ horizontalScrollBar()->setValue(hscrollPos);
+ verticalScrollBar()->setValue(vscrollPos);
+ m_PlayerWnd->update();
+}
+
+//==============================================================================
+/**
+ * RecenterClient: Recenters the Client rect in the View's client area.
+ */
+//==============================================================================
+void CPlayerContainerWnd::RecenterClient()
+{
+ QRect theViewClientRect = rect();
+ QSize theClientSize;
+ m_ClientRect = theViewClientRect;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (ShouldHideScrollBars()) {
+ } else
+#endif
+ {
+ theClientSize = GetEffectivePresentationSize();
+
+ // Only center if we need to scroll
+ if (theClientSize.width() > theViewClientRect.width()) {
+ // compute the size of the client rectangle to display
+ m_ClientRect.setLeft(
+ (theViewClientRect.width() / 2) - (theClientSize.width() / 2) - (theClientSize.width() % 2));
+ m_ClientRect.setRight((theViewClientRect.width() / 2) + (theClientSize.width() / 2));
+ }
+
+ if (theClientSize.height() > theViewClientRect.height()) {
+ m_ClientRect.setTop(
+ (theViewClientRect.height() / 2) - (theClientSize.height() / 2) - (theClientSize.height() % 2));
+ m_ClientRect.setBottom((theViewClientRect.height() / 2) + (theClientSize.height() / 2));
+ }
+ }
+
+ QRect glRect = m_ClientRect;
+ glRect.setWidth(int(devicePixelRatio() * m_ClientRect.width()));
+ glRect.setHeight(int(devicePixelRatio() * m_ClientRect.height()));
+ g_StudioApp.GetRenderer().SetViewRect(glRect);
+}
+
+//==============================================================================
+/**
+ * OnLButtonDown: Called whenever the user left clicks in the view.
+ * This processes the WM_LBUTTONDOWN message. This message is generated whenever
+ * the user left clicks in the view. Since this could involve selection of an item
+ * in the scene, it may (if the click is in the Client rect) call ProcessMouseClick()
+ * on the Document to perform the selection.
+ * @param inFlags the flags passed in from the message call
+ * @param inPoint the point where the event takes place
+ */
+void CPlayerContainerWnd::mousePressEvent(QMouseEvent *event)
+{
+ if ((event->button() == Qt::LeftButton) || (event->button() == Qt::RightButton)) {
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::Matte, event->pos(),
+ theToolMode);
+ m_IsMouseDown = true;
+ } else if (event->button() == Qt::MiddleButton) {
+#ifdef INCLUDE_EDIT_CAMERA
+ const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier;
+ const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier;
+
+ bool theToolChanged = false;
+ if (rect().contains(event->pos()) && !IsDeploymentView()) {
+ // If both the control key and the Alt key is not down
+ if (!theCtrlKeyIsDown && !theAltKeyIsDown) {
+ // press Scroll Wheel Click
+ // Do Camera Pan
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ theToolChanged = true;
+ } else if ((theAltKeyIsDown) && (!theCtrlKeyIsDown)) {
+ // press Alt-Scroll Wheel Click
+ // Do Camera Rotate if we are in 3D Camera
+ if (g_StudioApp.GetRenderer().DoesEditCameraSupportRotation(
+ g_StudioApp.GetRenderer().GetEditCamera())) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ theToolChanged = true;
+ }
+ }
+ }
+
+ if (theToolChanged) {
+ Q_EMIT toolChanged();
+ m_SceneView->SetViewCursor();
+
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::Matte,
+ event->pos(), theToolMode);
+ m_IsMouseDown = true;
+ m_IsMiddleMouseDown = true;
+ }
+#else
+ Q_UNUSED(inFlags);
+ Q_UNUSED(inPoint);
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * OnLButtonUp: Called whenever the user releases the left mouse button.
+ *
+ * This processes the WM_LBUTTONUP message. This message is generated whenever
+ * the left mouse button. We release the mouse capture to stop dragging.
+ *
+ * @param inFlags The flags passed in from the message call
+ * @param inPoint The point where the event takes place
+ */
+//==============================================================================
+void CPlayerContainerWnd::mouseReleaseEvent(QMouseEvent *event)
+{
+ if ((event->button() == Qt::LeftButton) || (event->button() == Qt::RightButton)) {
+ // Need to commit the current command when we have a mouse up. :)
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::Matte);
+ g_StudioApp.GetCore()->CommitCurrentCommand();
+ m_IsMouseDown = false;
+ } else if (event->button() == Qt::MiddleButton) {
+ #ifdef INCLUDE_EDIT_CAMERA
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::Matte);
+ g_StudioApp.GetCore()->CommitCurrentCommand();
+ if (m_IsMiddleMouseDown) {
+ m_IsMouseDown = false;
+ m_IsMiddleMouseDown = false;
+
+ const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier;
+ const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier;
+
+ if (!IsDeploymentView()) {
+ if (!theCtrlKeyIsDown && !theAltKeyIsDown) {
+ // none of the modifier key is pressed... reset to previous tool
+ m_SceneView->RestorePreviousTool();
+ } else if (theCtrlKeyIsDown && theAltKeyIsDown) {
+ // since both modifier is down... let the ctrl has priority
+ m_SceneView->SetToolOnCtrl();
+ }
+ m_SceneView->SetViewCursor();
+ Q_EMIT toolChanged();
+ }
+ }
+ #endif
+ }
+}
+
+//==============================================================================
+/**
+ * OnMouseMove: Called whenever the user moves the mouse in the window.
+ *
+ * This processes the WM_MOUSEMOVE message. This message is generated whenever
+ * the user moves the mouse in the view. This tells lets the document process it
+ * as well since the user could be dragging an object.
+ *
+ * @param inFlags The flags passed in from the message call
+ * @param inPoint The point where the event takes place
+ */
+//==============================================================================
+void CPlayerContainerWnd::mouseMoveEvent(QMouseEvent* event)
+{
+ if (m_IsMouseDown) {
+ UICPROFILE(OnMouseMove);
+
+ long theModifierKeys = 0;
+ if (event->buttons() & Qt::LeftButton)
+ theModifierKeys = CHotKeys::MOUSE_LBUTTON | CHotKeys::GetCurrentKeyModifiers();
+ else if (event->buttons() & Qt::RightButton)
+ theModifierKeys = CHotKeys::MOUSE_RBUTTON | CHotKeys::GetCurrentKeyModifiers();
+
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDrag(
+ SceneDragSenderType::Matte, event->pos(), theToolMode, theModifierKeys);
+ }
+}
+
+//==============================================================================
+/**
+ * OnMouseWheel: Called whenever the mouse wheel.
+ *
+ * This processes the WM_MOUSEWHEEL message.
+ *
+ * @param inFlags the flags passed in from the message call
+ * @param inPoint the point where the event takes place
+ */
+//==============================================================================
+void CPlayerContainerWnd::wheelEvent(QWheelEvent* event)
+{
+#ifdef INCLUDE_EDIT_CAMERA
+ // Note : Mouse wheel is a special animal of the scene drag tool. We dont change the tool
+ // so as not to affect the toolbar button and the view cursor. This will just do the zoom
+ // and the cursor is not changed.
+
+ const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier;
+ const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier;
+
+ // Keeping these codes here, till we finalized the behavior and confirm these not needed
+ // long theToolMode = g_StudioApp.GetToolMode( );
+ //// If both the control key and the Alt key is not down
+ // if ( !theCtrlKeyIsDown && !theAltKeyIsDown && !IsDeploymentView( ) )
+ //{
+ // if ( theToolMode != STUDIO_TOOLMODE_CAMERA_ZOOM )
+ // {
+ // g_StudioApp.SetToolMode( STUDIO_TOOLMODE_CAMERA_ZOOM );
+ // theToolMode = STUDIO_TOOLMODE_CAMERA_ZOOM;
+ // m_MouseWheeling = true;
+
+ // Q_EMIT toolChanged();
+ // SetViewCursor( );
+ // }
+ //}
+
+ // Mouse Wheel
+ // Do Camera Zoom
+ if (!theCtrlKeyIsDown && !theAltKeyIsDown && !IsDeploymentView())
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseWheel(
+ SceneDragSenderType::Matte, event->delta(), STUDIO_TOOLMODE_CAMERA_ZOOM);
+#else
+ Q_UNUSED(event);
+#endif
+}
+
+void CPlayerContainerWnd::scrollContentsBy(int, int)
+{
+ long x, y;
+ SetPlayerWndPosition(x, y);
+}
+
+//==============================================================================
+/**
+ * Set the view mode of the current scene view, whether we are in editing mode
+ * or deployment mode. For editing mode, we want to use the full scene area without
+ * any matte area.
+ * @param inViewMode the view mode of this scene
+ */
+void CPlayerContainerWnd::SetViewMode(EViewMode inViewMode)
+{
+ m_ViewMode = inViewMode;
+ m_SceneView->RecheckSizingMode();
+ if (m_ViewMode == VIEW_SCENE) {
+ // switching from edit mode to deployment mode, release the edit camera tool and set it to
+ // object move
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ bool theIsCameraTool = (theCurrentToolSettings & STUDIO_CAMERATOOL_MASK ? true : false);
+ if (theIsCameraTool) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_MOVE);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * return the view mode of the current scene view, whether we are in editing mode
+ * or deployment mode. For editing mode, we want to use the full scene area without
+ * any matte area.
+ * @return the current view mode
+ */
+CPlayerContainerWnd::EViewMode CPlayerContainerWnd::GetViewMode()
+{
+ return m_ViewMode;
+}
+
+//==============================================================================
+/**
+ * Checks whether we are in deployment view mode.
+ * @return true if is in deployment view mode, else false
+ */
+bool CPlayerContainerWnd::IsDeploymentView()
+{
+ return m_ViewMode == VIEW_SCENE ? true : false;
+}
+
+QSize CPlayerContainerWnd::GetEffectivePresentationSize() const
+{
+ CPt cSize = g_StudioApp.GetCore()->GetStudioProjectSettings()->GetPresentationSize();
+ QSize theSize(cSize.x, cSize.y);
+
+ // If we have guides, resize the window with enough space for the guides as well as the
+ // presentation
+ // This is a very dirty hack because we are of course hardcoding the size of the guides.
+ // If the size of the guides never changes, the bet paid off.
+ if (g_StudioApp.GetRenderer().AreGuidesEnabled()) {
+ theSize += QSize(32, 32);
+ }
+
+ return theSize / devicePixelRatio();
+}
+
+//==============================================================================
+
+void CPlayerContainerWnd::SetPlayerWnd(CPlayerWnd *inPlayerWnd)
+{
+ m_PlayerWnd = inPlayerWnd;
+ viewport()->setBackgroundRole(QPalette::Dark);
+ m_PlayerWnd->SetContainerWnd(this);
+ m_PlayerWnd->setParent(viewport());
+ m_PlayerWnd->setVisible(true);
+ m_PlayerWnd->resize(m_PlayerWnd->sizeHint());
+}
+
+//==============================================================================
+/**
+ * OnSize: Handles the WM_SIZE message
+ *
+ * Recenters the Client and recaluclates the matte when a resize message is
+ * generated.
+ *
+ * @param nType Specifies the type of resizing requested.
+ * @param cx Specifies the new width of the client area.
+ * @param cy Specifies the new height of the client area.
+ */
+//==============================================================================
+void CPlayerContainerWnd::resizeEvent(QResizeEvent* event)
+{
+ QAbstractScrollArea::resizeEvent(event);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ SetScrollRanges();
+#endif
+}
diff --git a/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h
new file mode 100644
index 00000000..d4ac3cf5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PLAYER_CONTAINER_WND_H
+#define INCLUDED_PLAYER_CONTAINER_WND_H 1
+
+#pragma once
+
+#include <QScrollArea>
+
+class CSceneView;
+class CStudioApp;
+class CPlayerWnd;
+class CWGLRenderContext;
+
+//==============================================================================
+// Class CPlayerContainerWnd
+//==============================================================================
+
+class CPlayerContainerWnd : public QAbstractScrollArea
+{
+ Q_OBJECT
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef enum {
+ VIEW_EDIT = 0, ///< Edit View
+ VIEW_SCENE, ///< Scene View
+ } EViewMode;
+
+public:
+ CPlayerContainerWnd(CSceneView *inSceneView);
+ virtual ~CPlayerContainerWnd();
+
+ void SetPlayerWnd(CPlayerWnd *inPlayerWnd);
+ void SetPlayerWndPosition(long &outLeftPresentationEdge, long &outTopPresentionEdge);
+ void SetScrollRanges();
+ void RecenterClient();
+ void OnRulerGuideToggled();
+
+ void SetViewMode(EViewMode inViewMode);
+ EViewMode GetViewMode();
+ bool IsDeploymentView();
+
+ QRect GetDisplayedClientRect() const { return m_ClientRect; }
+ bool IsMouseDown() const { return m_IsMouseDown; }
+ bool IsMiddleMouseDown() const { return m_IsMiddleMouseDown; }
+
+ QSize GetEffectivePresentationSize() const;
+
+Q_SIGNALS:
+ void toolChanged();
+
+protected:
+ void resizeEvent(QResizeEvent *) override;
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void wheelEvent(QWheelEvent *) override;
+
+ void scrollContentsBy(int, int) override;
+
+private:
+ CPlayerContainerWnd() {}
+ bool ShouldHideScrollBars();
+
+protected:
+ CSceneView *m_SceneView; ///< Pointer to the SceneView for rulers manipulation
+ CPlayerWnd *m_PlayerWnd; ///< Pointer to the window control that contains client
+ QRect m_ClientRect; ///< The rect where the client is drawn
+ bool m_IsMouseDown; ///< true if the mouse (any button) is down
+ bool m_IsMiddleMouseDown; ///< true if the middle mouse ( or scroll wheel ) is down
+ EViewMode m_ViewMode;
+};
+
+#endif // INCLUDED_PLAYER_CONTAINER_WND_H
diff --git a/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp b/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp
new file mode 100644
index 00000000..ca9c7c51
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "PlayerWnd.h"
+#include "MainFrm.h"
+#include "SceneView.h"
+#include "Dispatch.h"
+#include "MasterP.h"
+#include "HotKeys.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Dispatch.h"
+#include "HotKeys.h"
+#include "MouseCursor.h"
+#include "ResourceCache.h"
+#include "SceneDropTarget.h"
+#include "Core.h"
+#include "IDragable.h"
+#include "WGLRenderContext.h"
+#include "IStudioRenderer.h"
+
+#include <QMouseEvent>
+
+//==============================================================================
+// Class CPlayerWnd
+//==============================================================================
+
+CPlayerWnd::CPlayerWnd(QWidget *parent)
+ : QOpenGLWidget(parent)
+ , m_ContainerWnd(nullptr)
+ , m_IsMouseDown(false)
+ , m_PreviousToolMode(0)
+ , m_FitClientToWindow(false)
+{
+ m_LastKnownMousePosition = QPoint(-1, -1);
+
+ setAcceptDrops(true);
+ RegiserForDnd(this);
+ AddMainFlavor(EUIC_FLAVOR_FILE);
+ AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE);
+ AddMainFlavor(EUIC_FLAVOR_ASSET_LIB);
+ AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS);
+
+ setFormat(CWGLRenderContext::selectSurfaceFormat(this));
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CPlayerWnd::~CPlayerWnd()
+{
+}
+
+//==============================================================================
+/**
+ * OnMouseMove: Handle the WM_MOUSEMOVE message
+ *
+ * @param inFlags flags passed in with th mouse move message
+ * @param inPoint where the mouse is
+ */
+//==============================================================================
+void CPlayerWnd::mouseMoveEvent(QMouseEvent *event)
+{
+ if (event->buttons() & Qt::MiddleButton) {
+ // Middle button events are handled by the parent CPlayerContainerWnd
+ event->ignore();
+ } else {
+ if (m_IsMouseDown) {
+ long theModifierKeys = 0;
+ if (event->buttons() & Qt::LeftButton)
+ theModifierKeys = CHotKeys::MOUSE_LBUTTON | CHotKeys::GetCurrentKeyModifiers();
+ else if (event->buttons() & Qt::RightButton)
+ theModifierKeys = CHotKeys::MOUSE_RBUTTON | CHotKeys::GetCurrentKeyModifiers();
+
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDrag(
+ SceneDragSenderType::SceneWindow, event->pos(), theToolMode, theModifierKeys);
+ } else {
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseMove(
+ SceneDragSenderType::SceneWindow, event->pos());
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * OnSize: Handle the WM_SIZE message
+ *
+ * @param nType Passed to the base class
+ * @param cx change in x window size
+ * @param cy change in y window size
+ */
+//==============================================================================
+void CPlayerWnd::resizeEvent(QResizeEvent *event)
+{
+ QOpenGLWidget::resizeEvent(event);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CWnd *theChildWnd = this->GetWindow(GW_CHILD);
+
+ if (theChildWnd != nullptr) {
+ CRect theWndRect;
+
+ // Set the child window at the same position as the parent
+ this->GetWindowRect(&theWndRect);
+
+ theChildWnd->ScreenToClient(&theWndRect);
+ theChildWnd->MoveWindow(&theWndRect, FALSE);
+ }
+#endif
+ update();
+}
+
+//==============================================================================
+/**
+ * OnLButtonDown: Handle the WM_LBUTTONDOWN message
+ *
+ * @param inFlags Flags passed in from the message
+ * @param inPoint The point wher the button was clicked
+ */
+//==============================================================================
+void CPlayerWnd::mousePressEvent(QMouseEvent *event)
+{
+ const Qt::MouseButton btn = event->button();
+ if ((btn == Qt::LeftButton) || (btn == Qt::RightButton)) {
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::SceneWindow,
+ event->pos(), theToolMode);
+ m_IsMouseDown = true;
+ } else if (btn == Qt::MiddleButton) {
+ event->ignore();
+ }
+}
+
+//==============================================================================
+/**
+ * OnLButtonUp: Called whenever the user releases the left mouse button.
+ *
+ * This processes the WM_LBUTTONUP message. This message is generated whenever
+ * the left mouse button. We release the mouse capture to stop dragging.
+ *
+ * @param inFlags the flags passed in from the message call
+ * @param the point where the lbutton up takes place
+ */
+//==============================================================================
+void CPlayerWnd::mouseReleaseEvent(QMouseEvent *event)
+{
+ const Qt::MouseButton btn = event->button();
+ if ((btn == Qt::LeftButton) || (btn == Qt::RightButton)) {
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::SceneWindow);
+ g_StudioApp.GetCore()->CommitCurrentCommand();
+ m_IsMouseDown = false;
+ } else if (btn == Qt::MiddleButton) {
+ event->ignore();
+ }
+}
+
+void CPlayerWnd::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDblClick(
+ SceneDragSenderType::SceneWindow, event->pos());
+}
+
+
+bool CPlayerWnd::OnDragWithin(CDropSource &inSource)
+{
+ CSceneViewDropTarget theTarget;
+ return theTarget.Accept(inSource);
+}
+bool CPlayerWnd::OnDragReceive(CDropSource &inSource)
+{
+ CSceneViewDropTarget theTarget;
+ Q_EMIT dropReceived();
+ return theTarget.Drop(inSource);
+}
+void CPlayerWnd::OnDragLeave()
+{
+}
+
+//==============================================================================
+/**
+ * SetContainerWnd: keep track of a pointer to the containing window
+ *
+ * @param inContainerWnd pointer to what the containing window will be set to
+ */
+//==============================================================================
+void CPlayerWnd::SetContainerWnd(CPlayerContainerWnd *inContainerWnd)
+{
+ m_ContainerWnd = inContainerWnd;
+ updateGeometry();
+}
+
+QSize CPlayerWnd::sizeHint() const
+{
+ if (m_ContainerWnd)
+ return m_ContainerWnd->GetEffectivePresentationSize();
+ else
+ return QOpenGLWidget::sizeHint();
+}
+
+void CPlayerWnd::initializeGL()
+{
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ if (theRenderer.IsInitialized() == false) {
+ try {
+ theRenderer.Initialize(this);
+ } catch (...) {
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ wchar_t theBufferString[MAX_ENTRY_LENGTH];
+
+ _aswprintf(theBufferString, MAX_ENTRY_LENGTH - 1,
+ L"Unable to initialize OpenGL.\nThis may be because your graphic device is "
+ L"not sufficient, or simply because your driver is too old.\n\nPlease try "
+ L"upgrading your graphics driver and try again.");
+ ::wcsncat(theBufferString, L"\r\n\r\n", MAX_ENTRY_LENGTH - 1);
+
+ ::MessageBoxW(nullptr, theBufferString, L"Fatal Error",
+ MB_OK | MB_ICONSTOP | MB_DEFBUTTON1);
+#endif
+ exit(1);
+ }
+ }
+}
+
+void CPlayerWnd::paintGL()
+{
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ // don't use request render here, this has to be
+ // synchronous inside paintGL
+ theRenderer.RenderNow();
+}
+
+void CPlayerWnd::resizeGL(int width, int height)
+{
+ // this also passes the new FBO to the CWGLContext
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ theRenderer.SetViewRect(QRect(0, 0, width * devicePixelRatio(),
+ height * devicePixelRatio()));
+}
diff --git a/src/Authoring/Studio/_Win/UI/PlayerWnd.h b/src/Authoring/Studio/_Win/UI/PlayerWnd.h
new file mode 100644
index 00000000..25dfd949
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerWnd.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PLAYERWND_H
+#define INCLUDED_PLAYERWND_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropContainer.h"
+#include "PlayerContainerWnd.h"
+
+#include <QOpenGLWidget>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CPlayerContainerWnd;
+class CStudioApp;
+class CMouseCursor;
+class CHotkeys;
+
+//==============================================================================
+// Class CPlayerWnd
+//==============================================================================
+
+class CPlayerWnd : public QOpenGLWidget, public CWinDropContainer
+{
+ Q_OBJECT
+public:
+ explicit CPlayerWnd(QWidget *parent = nullptr);
+ ~CPlayerWnd();
+
+ void SetContainerWnd(CPlayerContainerWnd *inSceneView);
+
+ QSize sizeHint() const override;
+
+ bool OnDragWithin(CDropSource &inSource) override;
+ bool OnDragReceive(CDropSource &inSource) override;
+ void OnDragLeave() override;
+ void OnReflectMouse(CPt &inPoint, Qt::KeyboardModifiers inFlags) override {}
+
+protected:
+
+ CPlayerContainerWnd *m_ContainerWnd;
+ bool m_IsMouseDown;
+ long m_PreviousToolMode; ///< The previous tool mode (used when toggling with hotkeys to switch
+ ///back to previous mode on release)
+ bool m_FitClientToWindow; ///< True if we are in Fit to Window Mode
+
+ QPoint m_LastKnownMousePosition;
+
+Q_SIGNALS:
+ void dropReceived();
+
+protected:
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+
+ void initializeGL() override;
+ void paintGL() override;
+ void resizeGL(int width, int height) override;
+};
+
+#endif // INCLUDED_PLAYERWND_H
diff --git a/src/Authoring/Studio/_Win/UI/PopupWnd.cpp b/src/Authoring/Studio/_Win/UI/PopupWnd.cpp
new file mode 100644
index 00000000..f0b5d2cd
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PopupWnd.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PopupWnd.h"
+#include "AppFonts.h"
+
+#include "StudioPreferences.h"
+
+//==============================================================================
+/**
+ * Constructor: Initialize the object.
+ *
+ * Creates default fonts, colors, etc.
+ */
+CPopupWnd::CPopupWnd()
+ : m_CenterPt(0, 0)
+ , m_IsStationary(false)
+{
+ // get the proper font from appfonts
+ m_Font = CAppFonts::GetInstance()->GetNormalFont();
+
+ // Set the default colors (use default system tooltip colors)
+ m_TextColor = ::GetSysColor(COLOR_INFOTEXT);
+ m_BkColor = ::GetSysColor(COLOR_INFOBK);
+ ::CColor theBGColor(CStudioPreferences::GetTooltipBackgroundColor());
+ m_BkColor = theBGColor.GetRGBColor();
+ m_BkBrush = new CBrush();
+ m_BkBrush->CreateSolidBrush(m_BkColor);
+}
+
+//==============================================================================
+/**
+ * Destructor: Destroys the object and releases associated memory.
+ */
+CPopupWnd::~CPopupWnd()
+{
+ // Clean up GDI objects
+
+ // m_Font.DeleteObject();
+
+ if (m_BkBrush) {
+ DeleteObject(m_BkBrush);
+ delete m_BkBrush;
+ }
+}
+
+//==============================================================================
+// Message Map
+//==============================================================================
+BEGIN_MESSAGE_MAP(CPopupWnd, CWnd)
+//{{AFX_MSG_MAP(CPopupWnd)
+ON_WM_PAINT()
+ON_WM_ERASEBKGND()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * OnPaint: Handles the WM_PAINT windows message.
+ *
+ * Calls GetWindowText() and draws the text to the screen.
+ */
+void CPopupWnd::OnPaint()
+{
+ CPaintDC theDC(this); // device context for painting
+ CString theText;
+
+ GetWindowText(theText);
+ if (theText.GetLength() > 0) {
+
+ // Change the font
+ CFont *theOldFont = theDC.SelectObject(m_Font);
+ theDC.SetTextColor(m_TextColor);
+ theDC.SetBkColor(m_BkColor);
+
+ // Paint the text
+ CRect theClientRect;
+ this->GetClientRect(theClientRect);
+ theDC.DrawText(theText, theClientRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+
+ // Restore original font
+ theDC.SelectObject(theOldFont);
+ }
+}
+
+//==============================================================================
+/**
+ * SetWindowText: Sets the text for this window.
+ *
+ * Overridden from parent so that we can calculate how big we need to make the
+ * pop-up window so that the text fits. Automatically adjusts the window
+ * size/position to fit the new text string.
+ */
+void CPopupWnd::SetWindowText(LPCTSTR lpszString)
+{
+ CString theNewText;
+ theNewText.Format(L" %s ", lpszString);
+
+ // Set the window text
+ CWnd::SetWindowText(theNewText);
+
+ // Calculate the new window rect with the specified text
+ CDC *theDC = GetDC();
+ CRect theRect(0, 0, 1, 1);
+ CFont *theOldFont = theDC->SelectObject(m_Font);
+
+ theDC->DrawText(theNewText, theRect, DT_CALCRECT);
+ theDC->SelectObject(theOldFont);
+ ::AdjustWindowRect(theRect, this->GetStyle(), FALSE);
+ CPoint theTopLeft = theRect.TopLeft();
+ CPoint theBottomRight = theRect.BottomRight();
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theTopLeft);
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theBottomRight);
+ CRect theAdjustedRect(theTopLeft, theBottomRight);
+ int theX = abs((int)(theAdjustedRect.Width() / 2) - m_CenterPt.x);
+ int theY = abs((int)(theAdjustedRect.Height() / 2) - m_CenterPt.y);
+
+ ReleaseDC(theDC);
+
+ // Move the window to the new position, with the new size, still centered at m_CenterPt
+ this->SetWindowPos(nullptr, theX, theY, theAdjustedRect.Width(), theAdjustedRect.Height(),
+ SWP_NOZORDER | SWP_NOACTIVATE);
+}
+
+//==============================================================================
+/**
+ * SetCenterPoint: Changes the center of this window.
+ *
+ * Use this function to specify where you want the center of the pop-up window
+ * to appear. The window is automatically moved to the new center position.
+ */
+void CPopupWnd::SetCenterPoint(CPoint inPoint)
+{
+ if ((m_IsStationary && !IsWindowVisible()) || !m_IsStationary) {
+ // Store the center point
+ m_CenterPt = inPoint;
+
+ // Calculate the new window position so that it is centered at the new point
+ CRect theWindowRect;
+ this->GetWindowRect(theWindowRect);
+ CPoint theTopLeft = theWindowRect.TopLeft();
+ CPoint theBottomRight = theWindowRect.BottomRight();
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theTopLeft);
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theBottomRight);
+ CRect theAdjustedRect(theTopLeft, theBottomRight);
+ int theX = abs((int)(theAdjustedRect.Width() / 2) - m_CenterPt.x);
+ int theY = abs((int)(theAdjustedRect.Height() / 2) - m_CenterPt.y);
+
+ // Move the window
+ SetWindowPos(nullptr, theX, theY, theAdjustedRect.Width(), theAdjustedRect.Height(),
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+}
+
+//==============================================================================
+/**
+ * SetBkColor: Changes the background color of this window.
+ *
+ * Defaults to COLOR_INFOBK (tooltip background color). Creates a brush used
+ * in OnEraseBkgnd() of the specified color.
+ *
+ * @param inColor The new background color.
+ */
+void CPopupWnd::SetBkColor(COLORREF inColor)
+{
+ m_BkColor = inColor;
+
+ // If we already have a background brush
+ if (m_BkBrush) {
+ // Kill it
+ DeleteObject(m_BkBrush);
+ delete m_BkBrush;
+ }
+
+ // Make a brush of the specified color
+ m_BkBrush = new CBrush();
+ m_BkBrush->CreateSolidBrush(m_BkColor);
+}
+
+//==============================================================================
+/**
+ * OnEraseBkgnd: Handles the WM_ERASEBKGND windows message.
+ * Redraws the client rect using the current background brush.
+ *
+ * @param pDC Pointer to a display context for drawing.
+ * @return TRUE.
+ */
+BOOL CPopupWnd::OnEraseBkgnd(CDC *pDC)
+{
+ // Erase the client rect using the background brush so it's the right color
+ CRect theClientRect;
+ this->GetClientRect(theClientRect);
+ pDC->FillRect(theClientRect, m_BkBrush);
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * UpdateToolTip: Allows you to change multiple properties on this window at once.
+ *
+ * @param inCenter New center point of the popup window
+ * @param inText New window text for the window
+ * @param inShowWindow true to show the window, false to hide the window
+ */
+void CPopupWnd::UpdateToolTip(CPoint inCenter, CString inText, bool inShowWindow)
+{
+ int theShowFlag = (inShowWindow) ? SW_SHOWNA : SW_HIDE;
+
+ this->SetCenterPoint(inCenter);
+ this->SetWindowText(inText);
+ this->ShowWindow(theShowFlag);
+ this->Invalidate(FALSE);
+ this->UpdateWindow();
+}
diff --git a/src/Authoring/Studio/_Win/UI/PopupWnd.h b/src/Authoring/Studio/_Win/UI/PopupWnd.h
new file mode 100644
index 00000000..da58c9b1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PopupWnd.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_POP_UP_WND
+#define INCLUDED_POP_UP_WND 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+/**
+ * CPopupWnd: Class for making pop-up windows (a replacement for tooltips).
+ *
+ * To use, just create a CPopupWnd, set the text that you want displayed, then
+ * call ShowWindow() to toggle the window on and off. Default color scheme of
+ * this window mimics the system settings for tooltips.
+ */
+class CPopupWnd : public CWnd
+{
+public:
+ CPopupWnd();
+
+ virtual ~CPopupWnd();
+
+ /// Sets the text to display in this window
+ void SetWindowText(LPCTSTR lpszString);
+
+ /// Sets the center point of this window in screen coordinates
+ void SetCenterPoint(CPoint inPoint);
+
+ /// Sets the center point of this window from an x,y pair (screen coordinates)
+ void SetCenterPoint(int inX, int inY) { SetCenterPoint(CPoint(inX, inY)); }
+
+ /// Retrieves the center point of this window (screen coordinates)
+ CPoint GetCenterPoint() { return m_CenterPt; }
+
+ /// Sets the color of the text
+ void SetTextColor(COLORREF inColor) { m_TextColor = inColor; }
+
+ /// Sets the background color of the window
+ void SetBkColor(COLORREF inColor);
+
+ /// Returns a pointer to the CFont object used to draw the text. You can make changes to the
+ /// font using the pointer that's returned,
+ /// just don't delete it. The default font is set in the constructor as Arial 13.
+ CFont *GetFont() { return m_Font; }
+
+ /// Allows you to change multiple properties on this window at once.
+ void UpdateToolTip(CPoint inCenter, CString inText, bool inShowWindow);
+
+ ///
+ void SetStationary(bool inIsStationary) { m_IsStationary = inIsStationary; }
+
+protected:
+ CPoint m_CenterPt; ///< Center of this window in screen coordinates
+ CFont *m_Font; ///< Font for the window text
+ COLORREF m_TextColor; ///< Color of the text
+ COLORREF m_BkColor; ///< Background color of the window
+ CBrush *m_BkBrush; ///< Brush used for paiting the background of the window
+ bool m_IsStationary; ///< If the window is stationary, then it can only be moved while it is not
+ ///showing
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CPopupWnd)
+ afx_msg void OnPaint();
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // INCLUDED_POP_UP_WND
diff --git a/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp
new file mode 100644
index 00000000..649efa8c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+#pragma warning(disable : 4127)
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PreviewOutputDlg.h"
+#include "StudioClipboard.h"
+#include "UICFileTools.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Mainfrm.h"
+#include "Dialogs.h"
+#include "Strings.h"
+#include "Resource.h"
+#include "Core.h"
+
+// CPreviewOutput dialog
+
+IMPLEMENT_DYNAMIC(CPreviewOutputDlg, CDialog)
+
+CPreviewOutputDlg::CPreviewOutputDlg(const Q3DStudio::CString &inCmd,
+ const Q3DStudio::CString &inExportedFile,
+ CPreviewHelper::EExecMode inViewMode)
+ : CDialog(CPreviewOutputDlg::IDD, nullptr)
+ , m_Cmd(inCmd)
+ , m_ExportedFile(inExportedFile)
+ , m_ViewMode(inViewMode)
+ , m_ReadThreadHandle(nullptr)
+ , m_PreviewProcessHandle(nullptr)
+{
+ m_OutputReadThreadParam.m_ReadHandle = nullptr;
+ m_OutputReadThreadParam.m_Context = nullptr;
+}
+
+CPreviewOutputDlg::~CPreviewOutputDlg()
+{
+ if (m_ReadThreadHandle) {
+ TerminateThread(m_ReadThreadHandle, 0);
+ m_ReadThreadHandle = nullptr;
+ }
+
+ if (m_OutputReadThreadParam.m_ReadHandle) {
+ CloseHandle(m_OutputReadThreadParam.m_ReadHandle);
+ m_OutputReadThreadParam.m_ReadHandle = nullptr;
+ }
+}
+
+void CPreviewOutputDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_LIST_PREVIEW_STATUS, m_ListCtrl);
+}
+
+//=============================================================================
+/**
+ * Message Handler when dialog is initially opened.
+ */
+//=============================================================================
+BOOL CPreviewOutputDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Set the dialog header
+ Q3DStudio::CString theFile = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath().GetName();
+ if (theFile == "")
+ theFile = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE);
+ Q3DStudio::CString theDlgHeader;
+ Q3DStudio::CString theOperation;
+ switch (m_ViewMode) {
+ case CPreviewHelper::EXECMODE_PREVIEW:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_PREVIEW);
+ break;
+
+ case CPreviewHelper::EXECMODE_DEPLOY:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_DEPLOY);
+ break;
+ }
+ theDlgHeader.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_TITLE),
+ static_cast<const wchar_t *>(theOperation),
+ static_cast<const wchar_t *>(theFile));
+ SetWindowText(theDlgHeader);
+
+ // Prepare the list control
+ COLORREF theColor = 0x00C0C0C0;
+ m_ListCtrl.SetBkColor(theColor);
+ m_ListCtrl.SetTextBkColor(theColor);
+ CRect theRect;
+ m_ListCtrl.GetClientRect(theRect);
+ m_ListCtrl.InsertColumn(0, L"", LVCFMT_LEFT,
+ theRect.Width() * 2); // Double the width to see more
+
+ // Start the preview
+ if (!ExecutePreview()) {
+ CUICFile thePreviewerFile(CUICFile::GetApplicationDirectory(), m_ExportedFile);
+ Q3DStudio::CString theMessage;
+ theMessage.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_MSG),
+ static_cast<const wchar_t *>(thePreviewerFile.GetAbsolutePosixPath()));
+ g_StudioApp.GetDialogs()->DisplayMessageBox(
+ ::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_TITLE), theMessage,
+ CUICMessageBox::ICON_ERROR, false);
+ }
+
+ return TRUE;
+}
+
+//=============================================================================
+/**
+ * Handler for copying
+ */
+//=============================================================================
+void CPreviewOutputDlg::OnCopyText()
+{
+ try {
+ Q3DStudio::CString theText = "";
+ int theNumEntry = m_ListCtrl.GetItemCount();
+ for (int theIndex = 0; theIndex < theNumEntry; ++theIndex) {
+ theText += m_ListCtrl.GetItemText(theIndex, 0);
+ theText += "\r\n";
+ }
+ CStudioClipboard::CopyTextToClipboard(theText);
+ } catch (...) {
+ }
+}
+
+//=============================================================================
+/**
+ * Handler for OK Button
+ */
+//=============================================================================
+void CPreviewOutputDlg::OnOK()
+{
+ TerminateThread(m_ReadThreadHandle, 0);
+ CDialog::OnOK();
+ m_ReadThreadHandle = nullptr;
+}
+
+BEGIN_MESSAGE_MAP(CPreviewOutputDlg, CDialog)
+ON_BN_CLICKED(IDC_BUTTON_COPY_TEXT, OnCopyText)
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Spawn the process to execute the preview operation and redirect it's output
+ * to the list control
+ */
+//==============================================================================
+BOOL CPreviewOutputDlg::ExecutePreview()
+{
+ HANDLE theOutputReadHandleTmp;
+ HANDLE theOutputReadHandle;
+ HANDLE theOutputWriteHandle;
+
+ // Set up the security attributes struct.
+ SECURITY_ATTRIBUTES theSecurityAttr;
+ theSecurityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ theSecurityAttr.lpSecurityDescriptor = nullptr;
+ theSecurityAttr.bInheritHandle = TRUE;
+
+ // Create the child output pipe.
+ if (!CreatePipe(&theOutputReadHandleTmp, &theOutputWriteHandle, &theSecurityAttr, 0))
+ return FALSE;
+
+ // Create new output read handle. Set the Properties to FALSE.
+ // Otherwise, the child inherits the properties and, as a result,
+ // non-closeable handles to the pipes are created.
+ if (!DuplicateHandle(GetCurrentProcess(), theOutputReadHandleTmp, GetCurrentProcess(),
+ &theOutputReadHandle, // Address of new handle.
+ 0, FALSE, // Make it uninheritable.
+ DUPLICATE_SAME_ACCESS))
+ return FALSE;
+
+ // Close inheritable copies of the handles you do not want to be inherited.
+ CloseHandle(theOutputReadHandleTmp);
+
+ LaunchPreviewProcess(theOutputWriteHandle, m_Cmd);
+
+ // Close pipe handles (do not continue to modify the parent).
+ // You need to make sure that no handles to the write end of the
+ // output pipe are maintained in this process or else the pipe will
+ // not close when the child process exits and the ReadFile will hang.
+ CloseHandle(theOutputWriteHandle);
+
+ // Spawn a thread to busy read the preivew process output.
+ DWORD theThreadId;
+ m_OutputReadThreadParam.m_Context = this;
+ m_OutputReadThreadParam.m_ReadHandle = theOutputReadHandle;
+ m_ReadThreadHandle = CreateThread(nullptr, 0, CPreviewOutputDlg::ReadOutputThread,
+ (LPVOID)&m_OutputReadThreadParam, 0, &theThreadId);
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * Callback when the preview operation has completed.
+ */
+//==============================================================================
+void CPreviewOutputDlg::PreviewProcessTerminated()
+{
+ DWORD theExitCode;
+ GetExitCodeProcess(m_PreviewProcessHandle, &theExitCode);
+ if (theExitCode == 0)
+ PostMessage(WM_CLOSE); // close the window
+ else {
+ Q3DStudio::CString theOperation;
+ switch (m_ViewMode) {
+ case CPreviewHelper::EXECMODE_PREVIEW:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_PREVIEW);
+ break;
+
+ case CPreviewHelper::EXECMODE_DEPLOY:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_DEPLOY);
+ break;
+ }
+ Q3DStudio::CString theMessage;
+ theMessage.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_TEXT),
+ static_cast<const wchar_t *>(theOperation));
+ DisplayOutput(theMessage);
+ }
+}
+
+//==============================================================================
+/**
+ * Write the string into the list control.
+ * @param inString the string to display
+ */
+//==============================================================================
+void CPreviewOutputDlg::DisplayOutput(CString inStr)
+{
+ const wchar_t *DELIMITERS = L"\r\t\n";
+
+ wchar_t theBuffer[512] = { 0 };
+ ::wcscpy(theBuffer, inStr);
+
+ wchar_t *theToken = ::wcstok(theBuffer, DELIMITERS);
+ while (theToken) {
+ m_ListCtrl.InsertItem(m_ListCtrl.GetItemCount(), theToken);
+ theToken = ::wcstok(nullptr, DELIMITERS);
+ }
+
+ m_ListCtrl.EnsureVisible(m_ListCtrl.GetItemCount() - 1, FALSE);
+}
+
+//==============================================================================
+/**
+ * Spawn the process to execute the preview operation
+ * @param inStdOutput the handle to write the output to
+ * @param inCmd the command to execute
+ * @return true is spawned successfully, else false
+ */
+//==============================================================================
+BOOL CPreviewOutputDlg::LaunchPreviewProcess(HANDLE inStdOutput, Q3DStudio::CString &inCmd)
+{
+ // Further usability hax, you love them.
+ DisplayOutput(L"Checking for .NET Framework install:");
+ HKEY theHKey;
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", 0,
+ KEY_QUERY_VALUE, &theHKey)) {
+ DisplayOutput(L" - OK: .NET Framework present.");
+ } else {
+ DisplayOutput(L" - WARNING: .NET Framework Missing?");
+ }
+
+ // Launch the process with the working directory set to the parent directory of current document
+ CUICFile theDocument = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath();
+
+ Q3DStudio::CString theWorkingPath;
+ if (theDocument.Exists())
+ theWorkingPath = theDocument.GetAbsolutePath();
+ else
+ theWorkingPath = m_ExportedFile;
+
+ CUICFile thePreviewerFile(CUICFile::GetApplicationDirectory(), theWorkingPath);
+ Q3DStudio::CFilePath theWorkingDirectory(thePreviewerFile.GetAbsolutePosixPath());
+
+ PROCESS_INFORMATION theProcessInfo;
+ STARTUPINFO theStartupInfo;
+
+ // Set up the start up info struct.
+ ZeroMemory(&theStartupInfo, sizeof(STARTUPINFO));
+ theStartupInfo.cb = sizeof(STARTUPINFO);
+ theStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ theStartupInfo.hStdOutput = inStdOutput;
+ theStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE) /*hChildStdIn*/;
+ theStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ theStartupInfo.wShowWindow = SW_HIDE;
+
+ if (!CreateProcess(nullptr, const_cast<wchar_t *>(inCmd.c_str()), nullptr, nullptr, TRUE, 0, nullptr,
+ theWorkingDirectory.GetDirectory(), &theStartupInfo, &theProcessInfo))
+ return FALSE;
+
+ // Close any unnecessary handles.
+ CloseHandle(theProcessInfo.hThread);
+ m_PreviewProcessHandle = theProcessInfo.hProcess;
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * Spawn the thread to busy read the output and write to the list control
+ * @param inThreadParam the parameter used by this thread
+ * @return 1
+ */
+//==============================================================================
+DWORD WINAPI CPreviewOutputDlg::ReadOutputThread(LPVOID inThreadParam)
+{
+ char theBuffer[512];
+ DWORD theBytesRead;
+ SThreadParam *theParam = (SThreadParam *)inThreadParam;
+ HANDLE thePipeRead = theParam->m_ReadHandle;
+ CPreviewOutputDlg *theDlg = (CPreviewOutputDlg *)(theParam->m_Context);
+
+ while (TRUE) {
+ if (!ReadFile(thePipeRead, theBuffer, sizeof(theBuffer) - sizeof(char), &theBytesRead, nullptr)
+ || !theBytesRead) {
+ if (GetLastError() == ERROR_BROKEN_PIPE) {
+ theDlg->PreviewProcessTerminated();
+ CloseHandle(thePipeRead);
+ theParam->m_ReadHandle = nullptr;
+ break; // pipe done - normal exit path.
+ } else
+ theDlg->DisplayOutput(::LoadResourceString(
+ IDS_CONFIG_PREVIEW_REDIRECT_ERROR)); // Something bad happened.
+ } else {
+ if (theBytesRead) {
+ theBuffer[theBytesRead] = '\0'; // Follow input with a nullptr.
+ theDlg->DisplayOutput(CString(theBuffer));
+ }
+ }
+ }
+ return 1;
+}
diff --git a/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h
new file mode 100644
index 00000000..19361d3d
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PREVIEW_OUTPUT_DIALOG_H
+#define INCLUDED_PREVIEW_OUTPUT_DIALOG_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "resource.h"
+#include "PreviewHelper.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+namespace Q3DStudio {
+class CFilePath;
+}
+
+class CPreviewOutputDlg : public CDialog
+{
+ DECLARE_DYNAMIC(CPreviewOutputDlg)
+
+protected:
+ struct SThreadParam
+ {
+ void *m_Context;
+ HANDLE m_ReadHandle;
+ };
+
+public:
+ CPreviewOutputDlg(const Q3DStudio::CString &inCmd, const Q3DStudio::CString &inExportedFile,
+ CPreviewHelper::EExecMode inViewMode);
+ virtual ~CPreviewOutputDlg();
+
+ // Dialog Data
+ enum { IDD = IDD_DIALOG_PREVIEW_STATUS };
+ CListCtrl m_ListCtrl;
+
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+ virtual BOOL OnInitDialog();
+ virtual void OnCopyText();
+ virtual void OnOK();
+ DECLARE_MESSAGE_MAP()
+
+protected:
+ BOOL ExecutePreview();
+ BOOL LaunchPreviewProcess(HANDLE inStdOutput, Q3DStudio::CString &inCmd);
+ static DWORD WINAPI ReadOutputThread(LPVOID lpvThreadParam);
+ void DisplayOutput(CString inStr);
+ void PreviewProcessTerminated();
+
+protected:
+ Q3DStudio::CString m_Cmd;
+ Q3DStudio::CString m_ExportedFile;
+ SThreadParam m_OutputReadThreadParam;
+ HANDLE m_PreviewProcessHandle;
+ HANDLE m_ReadThreadHandle;
+ CPreviewHelper::EExecMode m_ViewMode;
+};
+
+#endif // INCLUDED_PREVIEW_OUTPUT_DIALOG_H
diff --git a/src/Authoring/Studio/_Win/UI/RecentItems.cpp b/src/Authoring/Studio/_Win/UI/RecentItems.cpp
new file mode 100644
index 00000000..b229ff29
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/RecentItems.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+
+#include "RecentItems.h"
+#include "Preferences.h"
+
+#include <QMenu>
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+const Q3DStudio::CString CRecentItems::RECENTITEM_KEY = "RecentItem";
+const Q3DStudio::CString CRecentItems::RECENTIMPORT_KEY = "RecentImport";
+const Q3DStudio::CString CRecentItems::RECENTITEM_VALID = "RecentValid";
+
+CRecentItems::CRecentItems(QMenu *inMenuID, long inCommandID, Q3DStudio::CString inPreferenceKey)
+{
+ Q_UNUSED(inCommandID)
+
+ m_Menu = inMenuID;
+ m_ValidItems = 10;
+ m_PreferenceKey = inPreferenceKey;
+
+ ReconstructList();
+}
+
+CRecentItems::~CRecentItems()
+{
+}
+
+void CRecentItems::AddRecentItem(const CUICFile &inItem)
+{
+ RemoveRecentItem(inItem);
+
+ m_RecentItems.insert(m_RecentItems.begin(), inItem);
+
+ while (m_RecentItems.size() > 10)
+ m_RecentItems.pop_back();
+
+ RebuildList();
+}
+
+void CRecentItems::RemoveRecentItem(const CUICFile &inItem)
+{
+ TFileList::iterator thePos = m_RecentItems.begin();
+ for (; thePos != m_RecentItems.end(); ++thePos) {
+ if ((*thePos) == inItem) {
+ m_RecentItems.erase(thePos);
+ break;
+ }
+ }
+
+ RebuildList();
+}
+
+void CRecentItems::ReconstructList()
+{
+ ClearMenu();
+ m_RecentItems.clear();
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences();
+
+ m_ValidItems = thePrefs.GetLongValue(RECENTITEM_VALID, m_ValidItems);
+
+ for (long theIndex = 0; theIndex < (m_ValidItems > 10 ? 10 : m_ValidItems); ++theIndex) {
+ Q3DStudio::CString theKey;
+ theKey.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(m_PreferenceKey), theIndex);
+
+ Q3DStudio::CString theFilename = thePrefs.GetStringValue(theKey, "");
+ if (theFilename != "") {
+ CUICFile theFile(theFilename);
+
+ QAction *act = m_Menu->addAction(theFile.GetName().toQString(),
+ this, &CRecentItems::onTriggerRecent);
+ act->setData(static_cast<int>(m_RecentItems.size()));
+ m_RecentItems.push_back(theFile);
+ }
+ }
+}
+
+void CRecentItems::RebuildList()
+{
+ ClearMenu();
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences();
+ thePrefs.SetLongValue(RECENTITEM_VALID, GetItemCount());
+ TFileList::iterator thePos = m_RecentItems.begin();
+ for (long theIndex = 0; thePos != m_RecentItems.end(); ++thePos, ++theIndex) {
+ Q3DStudio::CString theFilename = (*thePos).GetName();
+
+ QAction *act = m_Menu->addAction(theFilename.toQString(),
+ this, &CRecentItems::onTriggerRecent);
+ act->setData(static_cast<int>(theIndex));
+
+ Q3DStudio::CString theKey;
+ theKey.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(m_PreferenceKey), theIndex);
+
+ thePrefs.SetStringValue(theKey, (*thePos).GetAbsolutePath());
+ }
+}
+
+void CRecentItems::ClearMenu()
+{
+ m_Menu->clear();
+}
+
+CUICFile CRecentItems::GetItem(long inIndex)
+{
+ return m_RecentItems.at(inIndex);
+}
+
+void CRecentItems::onTriggerRecent()
+{
+ const int index = qobject_cast<QAction *>(sender())->data().toInt();
+ Q_EMIT openRecent(index);
+}
+
diff --git a/src/Authoring/Studio/_Win/UI/RecentItems.h b/src/Authoring/Studio/_Win/UI/RecentItems.h
new file mode 100644
index 00000000..bc295079
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/RecentItems.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_RECENT_ITEMS_H
+#define INCLUDED_RECENT_ITEMS_H 1
+
+#pragma once
+
+#include <QObject>
+
+#include "UICString.h"
+#include "UICFile.h"
+
+#include <vector>
+
+class CUICFile;
+
+QT_BEGIN_NAMESPACE
+class QMenu;
+QT_END_NAMESPACE
+
+class CRecentItems : public QObject
+{
+ Q_OBJECT
+
+ typedef std::vector<CUICFile> TFileList;
+
+public:
+ static const Q3DStudio::CString RECENTITEM_KEY;
+ static const Q3DStudio::CString RECENTIMPORT_KEY;
+ static const Q3DStudio::CString RECENTITEM_VALID;
+
+Q_SIGNALS:
+ void openRecent(int index);
+public:
+ CRecentItems(QMenu *inMenu, long inCommandID,
+ Q3DStudio::CString inPreferenceKey = RECENTITEM_KEY);
+ virtual ~CRecentItems();
+
+ void AddRecentItem(const CUICFile &inItem);
+ void RemoveRecentItem(const CUICFile &inItem);
+
+ CUICFile GetItem(long inIndex);
+ long GetItemCount() const { return (long)m_RecentItems.size(); }
+
+protected:
+ void ClearMenu();
+ void ReconstructList();
+ void RebuildList();
+ void SaveRecentList();
+
+ TFileList m_RecentItems;
+
+ long m_CommandID;
+ long m_ValidItems;
+ QMenu *m_Menu;
+ Q3DStudio::CString m_PreferenceKey;
+
+private Q_SLOTS:
+ void onTriggerRecent();
+};
+#endif // INCLUDED_RECENT_ITEMS_H
diff --git a/src/Authoring/Studio/_Win/UI/ReportDlg.cpp b/src/Authoring/Studio/_Win/UI/ReportDlg.cpp
new file mode 100644
index 00000000..2563a4c1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ReportDlg.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// ReportDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Strings.h"
+
+#include "ReportDlg.h"
+#include "CrashInfo.h"
+
+#include "CompConfig.h"
+
+#include "StudioInstance.h"
+#include <strstream>
+
+extern char g_DumpPath[MAX_PATH];
+/////////////////////////////////////////////////////////////////////////////
+// CReportDlg dialog
+
+CReportDlg::CReportDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CReportDlg::IDD, pParent)
+ , m_SysInfoText(_T(""))
+{
+ //{{AFX_DATA_INIT(CReportDlg)
+ m_Info = _T("");
+ m_DescHeader = _T("");
+ m_EmailAddress = _T("");
+ m_EmailHeader = _T("");
+ //}}AFX_DATA_INIT
+
+ m_MediumFont2.CreatePointFont(88, CString(CStudioPreferences::GetFontFaceName()));
+
+ m_Color_Background = CStudioPreferences::GetDarkBaseColor();
+ m_Color_Text = CStudioPreferences::GetMasterColor();
+ m_Color_Gray = CStudioPreferences::GetNormalColor();
+ m_Color_Dark = CStudioPreferences::GetInactiveColor();
+}
+
+void CReportDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CReportDlg)
+ DDX_Control(pDX, IDC_REPORTDLG_SYSINFO, m_SendSysInfo);
+ DDX_Control(pDX, IDC_REPORTDLG_DESC, m_Description);
+ DDX_Text(pDX, IDC_REPORTDLG_INFO, m_Info);
+ DDX_Text(pDX, IDC_REPORTDLG_DESCHEADER, m_DescHeader);
+ DDX_Text(pDX, IDC_REPORTDLG_EMAILADDR, m_EmailAddress);
+ DDX_Text(pDX, IDC_REPORTDLG_EMAILHEADER, m_EmailHeader);
+ //}}AFX_DATA_MAP
+ DDX_Text(pDX, IDC_CRASHDLG_SYSINFO_TEXT, m_SysInfoText);
+}
+
+BEGIN_MESSAGE_MAP(CReportDlg, CDialog)
+//{{AFX_MSG_MAP(CReportDlg)
+ON_BN_CLICKED(IDSUBMIT, OnSubmit)
+//}}AFX_MSG_MAP
+ON_WM_CTLCOLOR()
+ON_WM_ERASEBKGND()
+// ON_STN_CLICKED(IDC_REPORTDLG__SYSINFO_TEXT, &CReportDlg::OnStnClickedReportdlg)
+ON_STN_CLICKED(IDC_REPORTDLG__SYSINFO_TEXT, &CReportDlg::OnStnClickedReportdlg)
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Set the description of the crash.
+ * @param inErrorMessage the error message.
+ */
+//==============================================================================
+void CReportDlg::SetErrorMessage(CString inErrorMessage)
+{
+ m_ErrorMessage = inErrorMessage;
+}
+
+//==============================================================================
+/**
+ * Set the stack trace for the crash.
+ * @param inStackTrace the stack trace.
+ */
+//==============================================================================
+void CReportDlg::SetStackTrace(CString inStackTrace)
+{
+ m_StackTrace = inStackTrace;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CReportDlg message handlers
+
+void CReportDlg::OnSubmit()
+{
+ CWaitCursor theWaitCursor;
+
+ this->UpdateData(TRUE);
+
+ // Actual reporting functionality missing
+
+ this->EndDialog(TRUE);
+ exit(1);
+}
+
+void CReportDlg::OnCancel()
+{
+ this->EndDialog(FALSE);
+}
+
+BOOL CReportDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_Info = ::LoadResourceString(IDS_REPORTDLG_INFO).GetMulti();
+ m_DescHeader = ::LoadResourceString(IDS_REPORTDLG_DESCHEADER).GetMulti();
+ m_EmailHeader = ::LoadResourceString(IDS_REPORTDLG_EMAILHEADER).GetMulti();
+
+ CString theSysInfoText;
+ theSysInfoText = ""; //::LoadResourceString( IDS_REPORTDLG_SYSINFOHEADER ).GetMulti( );
+ // this is done this way, as i had problem changing the color of the text of the checkbox.
+ // it is now a seperate checkbox and a static text
+ // Made a workaround where the static text has notify flag on and would toggle the checkbox
+ // control on and off
+ // when clicked
+ m_SysInfoText = ::LoadResourceString(IDS_REPORTDLG_SYSINFOHEADER).GetMulti();
+
+ m_SendSysInfo.SetWindowText(theSysInfoText);
+ m_SendSysInfo.SetFont(&m_MediumFont2);
+ m_SendSysInfo.SetCheck(BST_CHECKED);
+
+ m_Brush.CreateSolidBrush(m_Color_Background);
+ GetDlgItem(IDC_REPORTDLG_INFO)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG_DESCHEADER)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG_EMAILADDR)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG_EMAILHEADER)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG__SYSINFO_TEXT)->SetFont(&m_MediumFont2);
+
+ this->UpdateData(FALSE);
+
+ return TRUE;
+}
+
+HBRUSH CReportDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
+{
+ Q_UNUSED(nCtlColor);
+
+ int theCtrlID = pWnd->GetDlgCtrlID();
+ if (theCtrlID == IDSUBMIT || theCtrlID == IDCANCEL || theCtrlID == IDC_REPORTDLG_SEPERATOR
+ || theCtrlID == IDC_REPORTDLG_SYSINFO || theCtrlID == IDC_REPORTDLG__SYSINFO_TEXT
+ || theCtrlID == IDC_REPORTDLG_INFO || theCtrlID == IDC_REPORTDLG_DESCHEADER
+ || theCtrlID == IDC_REPORTDLG_EMAILHEADER) {
+ pDC->SetBkMode(TRANSPARENT); // for area just behind the text
+ pDC->SetTextColor(m_Color_Gray);
+ } else if (theCtrlID == IDC_REPORTDLG_DESC || theCtrlID == IDC_REPORTDLG_EMAILADDR) {
+ pDC->SetBkColor(m_Color_Background);
+ pDC->SetBkMode(OPAQUE); // for area just behind the text
+ pDC->SetTextColor(m_Color_Text);
+ }
+
+ return m_Brush;
+}
+
+BOOL CReportDlg::OnEraseBkgnd(CDC *pDC)
+{
+ CRect theClientRect;
+ GetClientRect(&theClientRect);
+ pDC->FillSolidRect(theClientRect, m_Color_Background);
+
+ return TRUE;
+}
+
+void CReportDlg::OnStnClickedReportdlg()
+{
+ m_SendSysInfo.SetCheck(!m_SendSysInfo.GetCheck());
+}
diff --git a/src/Authoring/Studio/_Win/UI/ReportDlg.h b/src/Authoring/Studio/_Win/UI/ReportDlg.h
new file mode 100644
index 00000000..c54743da
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ReportDlg.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_)
+#define AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ReportDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CReportDlg dialog
+
+class CReportDlg : public CDialog
+{
+ // Construction
+public:
+ CReportDlg(CWnd *pParent = nullptr); // standard constructor
+
+ COLORREF m_Color_Background;
+ COLORREF m_Color_Text;
+ COLORREF m_Color_Gray;
+ COLORREF m_Color_Dark;
+ CBrush m_Brush;
+ CFont m_MediumFont2;
+
+ // Dialog Data
+ //{{AFX_DATA(CReportDlg)
+ enum { IDD = IDD_REPORTDLG };
+ CButton m_SendSysInfo;
+ CEdit m_Description;
+ CString m_Info;
+ CString m_DescHeader;
+ CString m_EmailAddress;
+ CString m_EmailHeader;
+ //}}AFX_DATA
+
+ void SetErrorMessage(CString inErrorMessage);
+ void SetStackTrace(CString inStackTrace);
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CReportDlg)
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ // Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CReportDlg)
+ afx_msg void OnSubmit();
+ virtual void OnCancel();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ CString m_ErrorMessage;
+ CString m_StackTrace;
+
+public:
+ afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ CString m_SysInfoText;
+ // afx_msg void OnStnClickedReportdlg();
+ afx_msg void OnStnClickedReportdlg();
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp
new file mode 100644
index 00000000..2eaa293a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "ResetKeyframeValuesDlg.h"
+#include ".\resetkeyframevaluesdlg.h"
+
+IMPLEMENT_DYNAMIC(CResetKeyframeValuesDlg, CDialog)
+CResetKeyframeValuesDlg::CResetKeyframeValuesDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CResetKeyframeValuesDlg::IDD, pParent)
+{
+}
+
+CResetKeyframeValuesDlg::~CResetKeyframeValuesDlg()
+{
+}
+
+void CResetKeyframeValuesDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_RESETKEYFRAMEVALUES_DLG_ICON, m_WarningIcon);
+ DDX_Control(pDX, IDCANCEL, m_CancelButton);
+}
+
+BEGIN_MESSAGE_MAP(CResetKeyframeValuesDlg, CDialog)
+END_MESSAGE_MAP()
+
+BOOL CResetKeyframeValuesDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_WarningIcon.SetIcon(::AfxGetApp()->LoadStandardIcon(IDI_WARNING));
+ m_CancelButton.SetButtonStyle(BS_DEFPUSHBUTTON);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h
new file mode 100644
index 00000000..d0a883d1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+#include "Resource.h"
+#include "afxwin.h"
+
+class CResetKeyframeValuesDlg : public CDialog
+{
+ DECLARE_DYNAMIC(CResetKeyframeValuesDlg)
+
+public:
+ CResetKeyframeValuesDlg(CWnd *pParent = nullptr); // standard constructor
+ virtual ~CResetKeyframeValuesDlg();
+
+ // Dialog Data
+ enum { IDD = IDD_RESETKEYFRAMEVALUES_DLG };
+
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+
+ DECLARE_MESSAGE_MAP()
+ CStatic m_WarningIcon;
+
+public:
+ virtual BOOL OnInitDialog();
+ CButton m_CancelButton;
+};
diff --git a/src/Authoring/Studio/_Win/UI/SceneView.cpp b/src/Authoring/Studio/_Win/UI/SceneView.cpp
new file mode 100644
index 00000000..6fcbc6d0
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/SceneView.cpp
@@ -0,0 +1,861 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#ifdef _WIN32
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICOptions.h"
+#include "SceneView.h"
+//#include "InterpolationDlg.h"
+#include "MainFrm.h"
+#include "StudioProjectSettings.h"
+#include "StudioInstance.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Dispatch.h"
+#include "MouseCursor.h"
+#include "ResourceCache.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "WndControl.h"
+#endif
+#include "Core.h"
+#include "UICDMStudioSystem.h"
+#include "IStudioRenderer.h"
+#include "ClientDataModelBridge.h"
+
+#include <QKeyEvent>
+#include <QScrollBar>
+#include <QSettings>
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+
+CSceneView::CSceneView(CStudioApp *inStudioApp, QWidget *parent)
+ : QWidget(parent)
+{
+ Q_UNUSED(inStudioApp)
+ m_PreviousToolMode = g_StudioApp.GetToolMode();
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+
+ m_PlayerContainerWnd = new CPlayerContainerWnd(this);
+ connect(m_PlayerContainerWnd, &CPlayerContainerWnd::toolChanged, this, &CSceneView::toolChanged);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Create the player container window
+ CPt theSize = CStudioPreferences::GetDefaultClientSize();
+
+ // Note that creating with WS_CLIPCHILDREN prevents flickering when SceneView is being
+ // resized.
+ m_PlayerContainerWnd->CreateEx(0, AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW),
+ (HBRUSH)GetStockObject(BLACK_BRUSH)),
+ L"player_container_wnd",
+ WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ CRect(0, 0, theSize.x, theSize.y), this, 1000);
+#endif
+
+ m_PlayerWnd = new CPlayerWnd(m_PlayerContainerWnd);
+ connect(m_PlayerWnd, &CPlayerWnd::dropReceived, this, &CSceneView::onDropReceived);
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Create the player frame child window
+ m_PlayerWnd.Create(AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW),
+ (HBRUSH)GetStockObject(WHITE_BRUSH)),
+ L"player_wnd", WS_CHILD | WS_VISIBLE, CRect(0, 0, theSize.x, theSize.y),
+ m_PlayerContainerWnd, 1001);
+#endif
+ m_PlayerContainerWnd->SetPlayerWnd(m_PlayerWnd);
+
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+CSceneView::CSceneView()
+{
+ m_PreviousToolMode = g_StudioApp.GetToolMode();
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+}
+
+void CSceneView::onDropReceived()
+{
+ setFocus();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+CSceneView::~CSceneView()
+{
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ // Stop listening for selection change events
+ theDispatch->RemoveSelectedNodePropChangeListener(this);
+ theDispatch->RemoveClientPlayChangeListener(this);
+#ifdef INCLUDE_EDIT_CAMERA
+ theDispatch->RemoveEditCameraChangeListener(this);
+#endif
+}
+
+QSize CSceneView::sizeHint() const
+{
+ CPt theSize = CStudioPreferences::GetDefaultClientSize();
+ return QSize(theSize.x, theSize.y);
+}
+
+//====================================================m==========================
+/**
+ * Called by the framework after the view is first attached
+ * to the document, but before the view is initially displayed.
+ * Notifies the Main Frame that the palettes need to be shown, and destroys the
+ * splash screen.
+ */
+void CSceneView::showEvent(QShowEvent *event)
+{
+ QWidget::showEvent(event);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Modify the style for WS_CLIPCHILDREN
+ ModifyStyle(0, WS_CLIPCHILDREN);
+#endif
+
+ m_PlayerContainerWnd->RecenterClient();
+
+ // Set the scroll information.
+ m_PlayerContainerWnd->SetScrollRanges();
+
+ // Create the cursors
+ m_ArrowCursor = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ARROW);
+ m_CursorGroupMove = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_MOVE);
+ m_CursorGroupRotate =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_ROTATE);
+ m_CursorGroupScale = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_SCALE);
+ m_CursorItemMove = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_MOVE);
+ m_CursorItemRotate = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_ROTATE);
+ m_CursorItemScale = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_SCALE);
+ m_CursorEditCameraPan =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_PAN);
+ m_CursorEditCameraRotate =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ROTATE);
+ m_CursorEditCameraZoom =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ g_StudioApp.GetCore()->GetDispatch()->AddEditCameraChangeListener(this);
+#endif
+
+ // Set the default cursor
+ OnSetCursor();
+}
+
+void CSceneView::keyPressEvent(QKeyEvent *event)
+{
+ /*switch (event->key())
+ {
+ case Qt::Key_Control:
+ case Qt::Key_Alt:
+ case Qt::Key_Shift:
+ case Qt::Key_Meta:
+ HandleModifierDown(event->key(), event->isAutoRepeat() ? 2 : 1, event->modifiers());
+ break;
+ default:
+ break;
+ }*/
+}
+
+//==============================================================================
+/**
+ * OnToolGroupSelection: Called when the Group Selection button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CSceneView::OnToolGroupSelection()
+{
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+ g_StudioApp.SetSelectMode(STUDIO_SELECTMODE_GROUP);
+ OnSetCursor();
+ Q_EMIT toolChanged();
+}
+
+//==============================================================================
+/**
+ * OnToolItemSelection: Called when the Item Selection button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CSceneView::OnToolItemSelection()
+{
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+ g_StudioApp.SetSelectMode(STUDIO_SELECTMODE_ENTITY);
+ OnSetCursor();
+ Q_EMIT toolChanged();
+}
+
+
+//==============================================================================
+/**
+ * SetViewCursor: Sets the cursor for the view according to the current Client Tool.
+ *
+ * Changes the cursor depending on the current tool mode. Each time the Tool mode
+ * changes, you should call this function. If you add extra tool modes, you
+ * will need to adjust this function.
+ */
+void CSceneView::SetViewCursor()
+{
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ long theCurrentSelectSettings = g_StudioApp.GetSelectMode();
+
+ // See what tool mode we are in
+ switch (theCurrentToolSettings) {
+ case STUDIO_TOOLMODE_MOVE:
+ switch (theCurrentSelectSettings) {
+ case STUDIO_SELECTMODE_ENTITY:
+ m_PlayerWnd->setCursor(m_CursorItemMove);
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ m_PlayerWnd->setCursor(m_CursorGroupMove);
+ break;
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemMove);
+ break;
+ }
+ break;
+
+ case STUDIO_TOOLMODE_ROTATE:
+ switch (theCurrentSelectSettings) {
+ case STUDIO_SELECTMODE_ENTITY:
+ m_PlayerWnd->setCursor(m_CursorItemRotate);
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ m_PlayerWnd->setCursor(m_CursorGroupRotate);
+ break;
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemRotate);
+ break;
+ }
+ break;
+
+ case STUDIO_TOOLMODE_SCALE:
+ switch (theCurrentSelectSettings) {
+ case STUDIO_SELECTMODE_ENTITY:
+ m_PlayerWnd->setCursor(m_CursorItemScale);
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ m_PlayerWnd->setCursor(m_CursorGroupScale);
+ break;
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemScale);
+ break;
+ }
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ m_PlayerWnd->setCursor(m_CursorEditCameraPan);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ m_PlayerWnd->setCursor(m_CursorEditCameraZoom);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ m_PlayerWnd->setCursor(m_CursorEditCameraRotate);
+ break;
+#endif
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemMove);
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * RecalcMatte: Recalculates the matte around the Client based on the settings.
+ *
+ * This will recalculate the matting around the Client based on the Client's
+ * current size. If the Client is a "Fit To Window" mode, then the matte region
+ * is cleared.
+ */
+//==============================================================================
+void CSceneView::RecalcMatte()
+{
+ long theXOffset = 0;
+ long theYOffset = 0;
+ QRect theClientRect = rect();
+
+ // Adjust the client area based if rulers are visible
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->setGeometry(theXOffset, theYOffset,
+ theClientRect.width() - theXOffset,
+ theClientRect.height() - theYOffset);
+
+ // Recenter the Client rect
+ m_PlayerContainerWnd->RecenterClient();
+ }
+}
+
+//==============================================================================
+/**
+ * PtInClientRect: Returns true if the point lies in the client rect, false otherwise.
+ *
+ * @param inPoint The point to check.
+ */
+//==============================================================================
+bool CSceneView::PtInClientRect(const QPoint& inPoint)
+{
+ return m_PlayerContainerWnd && m_PlayerContainerWnd->geometry().contains(inPoint);
+}
+
+//==============================================================================
+/**
+ * HandleModifierDown: Called when a modifier key (ctrl or alt) is pressed and held.
+ *
+ * Changes tool modes and saves the previous mode.
+ *
+ * @param inChar Contains the character code value of the key.
+ * @param inRepCnt Contains the repeat count, the number of times the keystroke
+ *is repeated when user holds down the key.
+ * @param inFlags Contains the scan code, key-transition code, previous
+ *key state, and context code.
+ */
+//==============================================================================
+bool CSceneView::HandleModifierDown(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers)
+{
+ bool theHandledFlag = false;
+
+ UNREFERENCED_PARAMETER(inRepCnt);
+
+ // Get the position of the mouse and the rectangle containing the scene view
+ QPoint theCursorPosition = mapFromGlobal(QCursor::pos());
+ QRect theWindowRect = rect();
+
+ // If we are currently dragging an object or the cursor is over the scene
+ if (((theWindowRect.contains(theCursorPosition))
+ || (m_PlayerContainerWnd && m_PlayerContainerWnd->IsMouseDown()))) {
+ bool theCtrlKeyIsDown = modifiers & Qt::ControlModifier;
+ bool theAltKeyIsDown = modifiers & Qt::AltModifier;
+
+ // If the control key is being pressed and the Alt key is not down
+ if ((inChar == Qt::Key_Control) && (!theAltKeyIsDown)) {
+ // If this is the first press, toggle tool modes
+ m_RegisteredKeyDown = true;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (m_PlayerContainerWnd->IsMiddleMouseDown() && !IsDeploymentView()) {
+ // Do nothing, do not let it switch to other tool when middle mouse is down
+ } else
+#endif
+ {
+ // See what tool mode we are in and change modes accordingly
+ SetToolOnCtrl();
+ theHandledFlag = true;
+ }
+ }
+ // If the alt key is being pressed and the control key is not down
+ else if ((inChar == Qt::Key_Alt) && (!theCtrlKeyIsDown)) {
+ m_RegisteredKeyDown = true;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (m_PlayerContainerWnd->IsMiddleMouseDown() && !IsDeploymentView()) {
+ // press Alt-Scroll Wheel Click
+ // Do Camera Rotate if we are in 3D Camera
+ if (g_StudioApp.GetRenderer().DoesEditCameraSupportRotation(
+ g_StudioApp.GetRenderer().GetEditCamera())) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ theHandledFlag = true;
+ }
+ } else
+#endif
+ {
+ // See what tool mode we are in and change modes accordingly
+ SetToolOnAlt();
+ theHandledFlag = true;
+ }
+ }
+ OnSetCursor();
+ Q_EMIT toolChanged();
+ }
+
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * HandleModifierUp: Handles the release of a modifier key (ctrl or alt).
+ *
+ * Changes tool modes back to the original tool mode.
+ *
+ * @param inChar Contains the character code value of the key.
+ * @param inRepCnt Contains the repeat count, the number of times the keystroke is
+ *repeated when user holds down the key.
+ * @param inFlags Contains the scan code, key-transition code, previous key
+ *state, and context code.
+ */
+//==============================================================================
+bool CSceneView::HandleModifierUp(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers)
+{
+ UNREFERENCED_PARAMETER(inRepCnt);
+
+ bool theHandledFlag = false;
+
+ // Get the position of the mouse and the rectangle containing the scene view
+ QPoint theCursorPosition = mapFromGlobal(QCursor::pos());
+ QRect theWindowRect = rect();
+
+ // If we are currently dragging an object or the cursor is over the scene
+ if (((theWindowRect.contains(theCursorPosition))
+ || (m_PlayerContainerWnd && m_PlayerContainerWnd->IsMouseDown()))) {
+ bool theCtrlKeyIsDown = modifiers & Qt::ControlModifier;
+ bool theAltKeyIsDown = modifiers & Qt::AltModifier;
+
+ // If the control key or alt key is released (and the opposite key is not down) revert back
+ // to the original tool mode
+ if (((inChar == Qt::Key_Control) && (!theAltKeyIsDown))
+ || ((inChar == Qt::Key_Alt) && (!theCtrlKeyIsDown))) {
+#ifdef INCLUDE_EDIT_CAMERA
+ if (m_PlayerContainerWnd->IsMiddleMouseDown())
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ else
+#endif
+ {
+ RestorePreviousTool();
+ }
+
+ OnSetCursor();
+ Q_EMIT toolChanged();
+
+ theHandledFlag = true;
+ }
+ // m_RegisteredKeyDown = false;
+ }
+
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * resizeEvent: Handles the WM_SIZE message
+ *
+ * Recenters the Client and recaluclates the matte when a resize message is
+ * generated.
+ *
+ * @param nType Specifies the type of resizing requested.
+ * @param cx Specifies the new width of the client area.
+ * @param cy Specifies the new height of the client area.
+ */
+//==============================================================================
+void CSceneView::resizeEvent(QResizeEvent* event)
+{
+ QWidget::resizeEvent(event);
+ if (m_PlayerContainerWnd) {
+ RecalcMatte();
+ SetPlayerWndPosition();
+ g_StudioApp.GetCore()->GetDoc( )->GetSceneGraph()->RequestRender();
+ }
+}
+
+//==============================================================================
+/**
+ * SetPlayerWndPosition: Sets the position of the child player window
+ *
+ * Called when the view is scrolled to position the child player window
+ *
+ */
+//==============================================================================
+void CSceneView::SetPlayerWndPosition()
+{
+ // Move the child player window to coincide with the scrollbars
+ if (m_PlayerContainerWnd) {
+ long theLeft, theTop;
+ // Retrieve the left and top edge of the presentation currently in view
+ m_PlayerContainerWnd->SetPlayerWndPosition(theLeft, theTop);
+
+ m_PlayerContainerWnd->update();
+ }
+}
+
+//==============================================================================
+/**
+ * GetPlayerHwnd: Gets the window handle for the player object.
+ *
+ * @return <HWND> Window handle for the player window
+ */
+//==============================================================================
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+HWND CSceneView::GetPlayerHwnd()
+{
+ HWND thePlayerWnd;
+
+ thePlayerWnd = this->GetSafeHwnd();
+
+ if (IsWindow(m_PlayerWnd.GetSafeHwnd()))
+ thePlayerWnd = m_PlayerWnd.GetSafeHwnd();
+
+ return thePlayerWnd;
+}
+#endif
+//==============================================================================
+/**
+ * SetRegisteredKey: Sets the staus to true or false
+ *
+ * If we've already processesed an alt or tab, then set the flag
+ */
+//==============================================================================
+void CSceneView::SetRegisteredKey(bool inStatus)
+{
+ m_RegisteredKeyDown = inStatus;
+}
+
+//==============================================================================
+/**
+ * GetKeyStatus: get the staus
+ *
+ * check to see if the flag is true or false
+ */
+//==============================================================================
+bool CSceneView::GetKeyStatus()
+{
+ return m_RegisteredKeyDown;
+}
+
+//=============================================================================
+/**
+ * Register all the events for hotkeys that are active for the entire application.
+ * Hotkeys for the entire application are ones that are not view specific in
+ * scope.
+ *
+ * @param inShortcutHandler the global shortcut handler.
+ */
+//=============================================================================
+void CSceneView::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::OnToolGroupSelection), 0, Qt::Key_A);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::OnToolItemSelection), 0, Qt::Key_V);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierDown),
+ Qt::ControlModifier, Qt::Key_Control);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierDown),
+ Qt::AltModifier, Qt::Key_Alt);
+ inShortcutHandler->RegisterKeyUpEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierUp), 0,
+ Qt::Key_Control);
+ inShortcutHandler->RegisterKeyUpEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierUp), 0,
+ Qt::Key_Alt);
+}
+
+//==============================================================================
+/**
+ * OnSetCursor: Handles the WM_SETCURSOR Windows message.
+ *
+ * Changes the cursor depending on the current tool mode.
+ *
+ * @param inWnd Specifies a pointer to the window that contains the cursor.
+ * @param inHitTest Specifies the hit-test area code. The hit test determines the cursor�s
+ *location.
+ * @param inMessage Specifies the mouse message number.
+ *
+ * @return true if the cursor was set
+ */
+void CSceneView::OnSetCursor()
+{
+ SetViewCursor();
+}
+
+//==============================================================================
+/**
+ * Called when the tool mode changes, scene view maintains its own mode so it can
+ * return to that mode when modifiers are pressed
+ * @param inMode the mode to which to change
+ */
+void CSceneView::SetToolMode(long inMode)
+{
+ m_PreviousToolMode = inMode;
+ SetViewCursor();
+}
+
+//==============================================================================
+/**
+ * Resets its scroll ranges and recenters client in the window. This is called when
+ * an outside source needs to tell the scene view that size ranges have changed such
+ * as the preferences telling the sceneview that the size changed.
+ */
+void CSceneView::RecheckSizingMode()
+{
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->SetScrollRanges();
+ }
+}
+
+//=============================================================================
+/**
+ * Called a selected node property has changed.
+ * @param inPropertyName name of the property changed
+ */
+void CSceneView::OnPropValueChanged(const Q3DStudio::CString &inPropertyName)
+{
+}
+
+//=============================================================================
+/**
+ * Called a selected node property has its property changed via a mouse drag
+ * @param inConstrainXAxis true if dragging is constrained along the X-Axis
+ * @param inConstrainYAxis true if dragging is constrained along the Y-Axis
+ */
+void CSceneView::OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis)
+{
+ // If not constraining to Y-Axis, snap horizontally
+ // If not constraining to X-Axis, snap vertically
+ // true to update tranform, as this is called from a mouse drag and the global transform may be
+ // outdated.
+ // false to not update the scene, since this is a result of a mouse drag which is already doing
+ // the updating
+}
+
+//==========================================================================
+/**
+ * Called when the presentation time changes.
+ * When animating an object, the markers must be updated with the selected object
+ */
+void CSceneView::OnTimeChanged(long inTime)
+{
+ UNREFERENCED_PARAMETER(inTime);
+}
+
+//==============================================================================
+/**
+ * Restore to the previous tool mode. This is called when the modifier is released
+ */
+//==============================================================================
+void CSceneView::RestorePreviousTool()
+{
+ // What was the original tool mode?
+ switch (m_PreviousToolMode) {
+ case STUDIO_TOOLMODE_MOVE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ break;
+
+ case STUDIO_TOOLMODE_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ break;
+
+ case STUDIO_TOOLMODE_SCALE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ break;
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * Change the tool when the Ctrl Key is pressed
+ */
+//==============================================================================
+void CSceneView::SetToolOnCtrl()
+{
+ switch (m_PreviousToolMode) {
+ // If we are in move mode, switch to rotate
+ case STUDIO_TOOLMODE_MOVE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ break;
+
+ // If we are in rotate mode, switch to move
+ case STUDIO_TOOLMODE_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ break;
+
+ // If we are in scale mode, switch to move
+ case STUDIO_TOOLMODE_SCALE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // If we are in camera pan mode, switch to camera orbit
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ break;
+
+ // If we are in camera orbit mode, switch to camera pan
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ break;
+
+ // If we are in camera zoom mode, switch to camera pan
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ break;
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * Change the tool when the Alt Key is pressed
+ */
+//==============================================================================
+void CSceneView::SetToolOnAlt()
+{
+ switch (m_PreviousToolMode) {
+ // If we are in move mode, switch to rotate
+ case STUDIO_TOOLMODE_MOVE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ break;
+
+ // If we are in rotate mode, switch to move
+ case STUDIO_TOOLMODE_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ break;
+
+ // If we are in scale mode, switch to move
+ case STUDIO_TOOLMODE_SCALE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // If we are in camera pan mode, switch to camera zoom
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ break;
+
+ // If we are in camera orbit mode, switch to camera zoom
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ break;
+
+ // If we are in camera zoom mode, switch to camera orbit
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ break;
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * Redirect to PlayerContainerWnd to check whether we are in deployment view mode.
+ * @return true if is in deployment view mode, else false
+ */
+bool CSceneView::IsDeploymentView()
+{
+ // default mode is SCENE_VIEW so if playercontainerwnd does not exist ( should only happen on
+ // startup ),
+ // it is deployment view
+ bool theStatus = true;
+ if (m_PlayerContainerWnd)
+ theStatus = m_PlayerContainerWnd->IsDeploymentView();
+
+ return theStatus;
+}
+
+//==============================================================================
+/**
+ * Redirect to PlayerContainerWnd to set the view mode of the current scene view,
+ * whether we are in editing mode or deployment mode. For editing mode, we want to
+ * use the full scene area without any matte area.
+ * @param inViewMode the view mode of this scene
+ */
+void CSceneView::SetViewMode(CPlayerContainerWnd::EViewMode inViewMode)
+{
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->SetViewMode(inViewMode);
+ }
+}
+
+//==============================================================================
+/**
+ * When the active camera is changed, the display string needs to be changed. Hence
+ * find which entry is the one which is modified and update with the new string
+ * @param inCamera the camera that has been modified
+ */
+void CSceneView::OnEditCameraChanged()
+{
+ // reset any scrolling and recalculate the window position.
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->SetScrollRanges();
+ RecalcMatte();
+ SetPlayerWndPosition();
+ }
+
+ // update the view mode accordingly
+ SetViewMode(g_StudioApp.GetRenderer().GetEditCamera() >= 0 ? CPlayerContainerWnd::VIEW_EDIT
+ : CPlayerContainerWnd::VIEW_SCENE);
+ // redraw the scene so that markers can be calculated correctly
+ // g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false );
+ m_PlayerWnd->update();
+}
+
+//==============================================================================
+/**
+ * When the active camera is changed, the display string needs to be changed. Hence
+ * find which entry is the one which is modified and update with the new string
+ * @param inCamera the camera that has been modified
+ */
+void CSceneView::OnEditCamerasTransformed()
+{
+}
+
+void CSceneView::OnAuthorZoomChanged()
+{
+ OnEditCameraChanged();
+}
+
+void CSceneView::OnRulerGuideToggled()
+{
+ m_PlayerContainerWnd->OnRulerGuideToggled();
+}
diff --git a/src/Authoring/Studio/_Win/UI/SceneView.h b/src/Authoring/Studio/_Win/UI/SceneView.h
new file mode 100644
index 00000000..12a58c6a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/SceneView.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SCENE_VIEW_H
+#define INCLUDED_SCENE_VIEW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QWidget>
+#include <QCursor>
+
+#include "EditorPane.h"
+#include "PlayerWnd.h"
+#include "PlayerContainerWnd.h"
+#include "DispatchListeners.h"
+
+class CStudioApp;
+class CHotKeys;
+class CMouseCursor;
+class CWndControl;
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Class CSceneView
+//==============================================================================
+
+//==============================================================================
+/**
+ * CSceneView: Scene View.
+ *
+ * Provides the view of the scene and displays the 3D Client window.
+ */
+//==============================================================================
+class CSceneView : public QWidget,
+ public CEditorPane,
+ public CSelectedNodePropChangeListener,
+ public CClientPlayChangeListener,
+ public CEditCameraChangeListener
+{
+ Q_OBJECT
+ //==========================================================================
+ // Protected Properties
+ //==========================================================================
+protected:
+ bool m_FitClientToWindow = false; ///< True if user selected fit to window in prefrences
+ bool m_RegisteredKeyDown = false; ///< True if a key is down
+ CPlayerContainerWnd *m_PlayerContainerWnd = nullptr; ///< first-level child
+ CPlayerWnd *m_PlayerWnd = nullptr; ///< second-level child (grandchild)
+ QCursor m_ArrowCursor; ///< A pointer to the current cursor (changes according to mode)
+ QCursor m_CursorGroupMove; ///< The move group cursor
+ QCursor m_CursorGroupRotate; ///< The rotate group cursor
+ QCursor m_CursorGroupScale; ///< The scale group cursor
+ QCursor m_CursorItemMove; ///< The move item cursor
+ QCursor m_CursorItemRotate; ///< The rotate item cursor
+ QCursor m_CursorItemScale; ///< The scale item cursor
+ QCursor m_CursorEditCameraPan; ///< The edit camera pan cursor
+ QCursor m_CursorEditCameraRotate; ///< The edit camera rotate cursor
+ QCursor m_CursorEditCameraZoom; ///< The edit camera zoom cursor
+
+ long m_PreviousToolMode; ///< The previous tool mode (used when toggling with hotkeys to switch
+ ///back to previous mode on release)
+ long m_PreviousSelectMode; ///< The previous select mode
+
+ //==========================================================================
+ // Protected Methods
+ //==========================================================================
+protected: // create from serialization only
+
+ //==========================================================================
+ // Public Methods
+ //==========================================================================
+public:
+ CSceneView(CStudioApp *inStudioApp, QWidget *parent = nullptr);
+ CSceneView(); // used for serialization only!
+ virtual ~CSceneView();
+
+ bool HandleModifierUp(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers);
+ bool HandleModifierDown(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers);
+ bool PtInClientRect(const QPoint& inPoint);
+ void SetViewCursor();
+ void SetToolMode(long inMode);
+ void RecheckSizingMode();
+
+ void SetRegisteredKey(bool inStatus);
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+ bool GetKeyStatus();
+
+ void SetPlayerWndPosition();
+
+ // redirect to/from PlayerContainerWnd
+ bool IsDeploymentView();
+ void SetViewMode(CPlayerContainerWnd::EViewMode inViewMode);
+
+ // Tool helper methods
+ void RestorePreviousTool();
+ void SetToolOnCtrl();
+ void SetToolOnAlt();
+
+ void OnRulerGuideToggled();
+
+ // CSelectedNodePropChangeListener
+ void OnPropValueChanged(const Q3DStudio::CString &inPropertyName) override;
+ void OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis) override;
+
+ // CClientPlayChangeListener
+ void OnTimeChanged(long inTime) override;
+
+ // CEditCameraChangeListener
+
+ void OnEditCameraChanged() override;
+ void OnEditCamerasTransformed() override;
+ void OnAuthorZoomChanged() override;
+
+ QSize sizeHint() const override;
+
+ void OnToolGroupSelection();
+ void OnToolItemSelection();
+public:
+
+ void resizeEvent(QResizeEvent *event) override;
+
+Q_SIGNALS:
+ void toolChanged();
+
+protected:
+ void RecalcMatte();
+
+ // Generated message map functions
+protected:
+ void OnSetCursor();
+ void showEvent(QShowEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+private:
+ void onDropReceived();
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_SCENE_VIEW_H
diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.cpp b/src/Authoring/Studio/_Win/UI/StartupDlg.cpp
new file mode 100644
index 00000000..286d94e3
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StartupDlg.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "StudioDefs.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "StartupDlg.h"
+
+#include "StudioPreferences.h"
+#include "ui_StartupDlg.h"
+
+#include <QtCore/qfileinfo.h>
+#include <QtGui/qpalette.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdir.h>
+
+// CStartupDlg dialog
+
+CStartupDlg::CStartupDlg(QWidget *pParent)
+ : QDialog(pParent, Qt::MSWindowsFixedSizeDialogHint | Qt::FramelessWindowHint)
+ , m_Choice(EStartupChoice_Invalid)
+ , m_RecentDocSelected("")
+ , m_ui(new Ui::StartupDlg)
+ , m_palette(nullptr)
+{
+ m_ui->setupUi(this);
+}
+
+CStartupDlg::~CStartupDlg()
+{
+ delete m_palette;
+}
+
+static QString GetFileTimeReadable(const CUICFile &inFile)
+{
+ QFileInfo finfo(inFile.GetAbsolutePath().toQString());
+ if (!finfo.exists())
+ return {};
+
+ return finfo.lastModified().toString("MM/dd/yyyy");
+}
+
+void CStartupDlg::showEvent(QShowEvent *ev)
+{
+ OnInitDialog();
+ QDialog::showEvent(ev);
+}
+
+void CStartupDlg::OnInitDialog()
+{
+ connect(m_ui->newDocument, &QPushButton::clicked, this, &CStartupDlg::OnNewDocClicked);
+ connect(m_ui->openDocument, &QPushButton::clicked, this, &CStartupDlg::OnOpenDocClicked);
+
+ // Load the product version
+ m_ProductVersionStr.Format(
+ ::LoadResourceString(IDS_UIC_STUDIO_VERSION),
+ static_cast<const wchar_t *>(CStudioPreferences::GetVersionString()));
+ m_ui->versionStr->setText(m_ProductVersionStr.toQString());
+
+ // Populate the recent document list
+ for (uint theIndex = 0; theIndex < RECENT_COUNT; ++theIndex) {
+ ClickableLabel *recent
+ = findChild<ClickableLabel *>(QStringLiteral("recent%1").arg(theIndex));
+ connect(recent, &ClickableLabel::clicked, this, &CStartupDlg::OnStnClickedStartupRecent);
+
+ recent->setProperty("recentIndex", theIndex);
+
+ if (m_RecentDocs.size() > theIndex) {
+ // Set the name
+ recent->setText(m_RecentDocs[theIndex].GetName().toQString());
+ // Set path and date to tooltip
+ QFileInfo thePath(m_RecentDocs[theIndex].GetAbsolutePath().toQString());
+ QString toolTip = thePath.absoluteDir().path();
+ toolTip.append(QStringLiteral("\n"));
+ toolTip.append(GetFileTimeReadable(m_RecentDocs[theIndex]));
+ recent->setToolTip(toolTip);
+ } else {
+ recent->hide();
+ }
+ }
+}
+
+void CStartupDlg::AddRecentItem(const CUICFile &inRecentItem)
+{
+ m_RecentDocs.push_back(inRecentItem);
+}
+
+CStartupDlg::EStartupChoice CStartupDlg::GetChoice()
+{
+ return m_Choice;
+}
+
+CUICFile CStartupDlg::GetRecentDoc() const
+{
+ return m_RecentDocSelected;
+}
+
+void CStartupDlg::OnNewDocClicked()
+{
+ m_Choice = EStartupChoice_NewDoc;
+ QDialog::accept();
+}
+
+void CStartupDlg::OnOpenDocClicked()
+{
+ m_Choice = EStartupChoice_OpenDoc;
+ QDialog::accept();
+}
+
+void CStartupDlg::OnStnClickedStartupRecent()
+{
+ const int index = sender()->property("recentIndex").toInt();
+ OpenRecent(index);
+}
+
+void CStartupDlg::OpenRecent(size_t inIndex)
+{
+ if (inIndex < m_RecentDocs.size()) {
+ m_RecentDocSelected = m_RecentDocs[inIndex];
+ m_Choice = EStartupChoice_OpenRecent;
+ QDialog::accept();
+ }
+}
+
+void CStartupDlg::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event)
+ if (m_palette)
+ return;
+
+ delete m_palette;
+ m_palette = new QPalette;
+ QPixmap pic = QPixmap(":/startup/open_dialog.png");
+ pic.setDevicePixelRatio(devicePixelRatio());
+ m_palette->setBrush(QPalette::Window, pic);
+ setPalette(*m_palette);
+ resize(pic.size());
+ setFixedSize(size());
+}
diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.h b/src/Authoring/Studio/_Win/UI/StartupDlg.h
new file mode 100644
index 00000000..6fbd0a2a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StartupDlg.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STARTUP_DLG
+#define INCLUDED_STARTUP_DLG 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QDialog>
+
+#include "UICString.h"
+#include "UICFile.h"
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class StartupDlg;
+}
+QT_END_NAMESPACE
+
+//==============================================================================
+/**
+ * CGLVersionDlg: Dialog class for showing what user can do upon startup
+ */
+//==============================================================================
+class CStartupDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ enum EStartupChoice {
+ EStartupChoice_Invalid = -1,
+ EStartupChoice_NewDoc,
+ EStartupChoice_OpenDoc,
+ EStartupChoice_OpenRecent,
+ EStartupChoice_Exit
+ };
+
+public:
+ CStartupDlg(QWidget *pParent = nullptr); // standard constructor
+ virtual ~CStartupDlg();
+
+protected:
+ const static int RECENT_COUNT = 5;
+
+ void paintEvent(QPaintEvent *event) override;
+ void showEvent(QShowEvent *) override;
+
+protected Q_SLOTS:
+ void OnNewDocClicked();
+ void OnOpenDocClicked();
+ void OnStnClickedStartupRecent();
+ void OpenRecent(size_t inIndex);
+
+private:
+ // Dialog background
+ QPalette *m_palette;
+
+ // Product version string
+ Q3DStudio::CString m_ProductVersionStr;
+
+ // Choice
+ EStartupChoice m_Choice = EStartupChoice_Invalid;
+
+ // Recent Docs
+ std::vector<CUICFile> m_RecentDocs;
+ CUICFile m_RecentDocSelected;
+
+public:
+ void OnInitDialog();
+ void AddRecentItem(const CUICFile &inRecentItem);
+ EStartupChoice GetChoice();
+ CUICFile GetRecentDoc() const;
+
+private:
+ QScopedPointer<Ui::StartupDlg> m_ui;
+};
+
+#endif // INCLUDED_STARTUP_DLG
diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.ui b/src/Authoring/Studio/_Win/UI/StartupDlg.ui
new file mode 100644
index 00000000..619c857a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StartupDlg.ui
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StartupDlg</class>
+ <widget class="QDialog" name="StartupDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>442</width>
+ <height>650</height>
+ </rect>
+ </property>
+ <widget class="QLabel" name="recentDocLabel">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>250</y>
+ <width>411</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>RECENT FILES</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QWidget" name="verticalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>290</y>
+ <width>401</width>
+ <height>341</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="recentList">
+ <item>
+ <widget class="ClickableLabel" name="recent0">
+ <property name="text">
+ <string>Recent0.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent1">
+ <property name="text">
+ <string>Recent1.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent2">
+ <property name="text">
+ <string>Recent2.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent3">
+ <property name="text">
+ <string>Recent3.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>3</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent4">
+ <property name="text">
+ <string>Recent3.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>3</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="verticalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>130</y>
+ <width>161</width>
+ <height>101</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="buttons">
+ <item>
+ <widget class="QPushButton" name="newDocument">
+ <property name="text">
+ <string>Create Project...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/Toolbar-00.png</normaloff>:/res/Toolbar-00.png</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="openDocument">
+ <property name="text">
+ <string>Open Project...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/Toolbar-01.png</normaloff>:/res/Toolbar-01.png</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="versionStr">
+ <property name="geometry">
+ <rect>
+ <x>290</x>
+ <y>90</y>
+ <width>141</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Qt 3D Studio version string</string>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ClickableLabel</class>
+ <extends>QLabel</extends>
+ <header>ClickableLabel.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../../MainFrm.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp
new file mode 100644
index 00000000..bde792eb
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp
@@ -0,0 +1,590 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+#include "ui_StudioAppPrefsPage.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICOptions.h"
+#include "Doc.h"
+#include "StudioAppPrefsPage.h"
+#include "StudioConst.h"
+#include "StudioProjectSettings.h"
+#include "StudioPreferences.h"
+#include "StudioApp.h"
+#include "StudioPreferences.h"
+#include "StringLoader.h"
+#include "CommonConstants.h"
+#include "Views.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "IStudioRenderer.h"
+
+#include <QColorDialog>
+#include <QMessageBox>
+
+#define WM_PREVIEW_DYNAMIC_CONTROLS WM_USER + 1200
+const long MIN_PAGESIZE = 380;
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioAppPrefsPage property page
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CStudioAppPrefsPage::CStudioAppPrefsPage(QWidget *parent)
+ : CStudioPreferencesPropPage(parent)
+ , m_nudgeValue(0.0)
+ , m_TimebarShowTime(FALSE)
+ , m_InterpolationIsSmooth(FALSE)
+ , m_ui(new Ui::StudioAppPrefsPage)
+{
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPixelSize(CStudioPreferences::fontSize());
+
+ // Create a bold font for the group box text
+ m_BoldFont = m_Font;
+ m_BoldFont.setBold(true);
+
+ OnInitDialog();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CStudioAppPrefsPage::~CStudioAppPrefsPage()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioAppPrefsPage message handlers
+
+void CStudioAppPrefsPage::OnInitDialog()
+{
+ m_ui->setupUi(this);
+ m_ui->m_editNudgeAmount->setValidator(new QDoubleValidator(this));
+
+ // Add tool tips for controls
+ m_ui->m_editNudgeAmount->setToolTip(::LoadResourceString(IDS_PREFS_NUDGEAMOUNT).toQString());
+ m_ui->m_DefaultInterpolation->setToolTip(::LoadResourceString(IDS_PREFS_INTERPOLATIONDEFAULT).toQString());
+ m_ui->m_checkTimelineAbsoluteSnapping->setToolTip(
+ ::LoadResourceString(IDS_PREFS_TIMELINEGRIDSNAPPING).toQString());
+ m_ui->m_SnapRangeCombo->setToolTip(::LoadResourceString(IDS_PREFS_TIMELINEGRIDRESOLUTION).toQString());
+ m_ui->m_buttonRestoreDefaults->setToolTip(::LoadResourceString(IDS_PREFS_RESTOREDEFAULTS).toQString());
+ m_ui->m_EditViewBGColor->setAutoFillBackground(true);
+
+ // Set fonts for child windows.
+ for (auto w : findChildren<QWidget *>())
+ w->setFont(m_Font);
+
+ // Make the group text bold
+ for (auto w : findChildren<QGroupBox *>())
+ w->setFont(m_BoldFont);
+
+#ifndef INCLUDE_EDIT_CAMERA
+ ASSERT(0);
+ // This won't work as all the controls have to move accordingly. Don't think INCLUDE_EDIT_CAMERA
+ // will be undefined
+ // Hide controls related to Edit Camera
+ m_ui->m_groupBoxEditingView->setVisible(false);
+#endif
+
+ // Load the settings for the controls
+ LoadSettings();
+
+ auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated);
+ connect(m_ui->m_buttonRestoreDefaults, &QPushButton::clicked, this, &CStudioAppPrefsPage::OnButtonRestoreDefaults);
+ connect(m_ui->m_DefaultInterpolation, activated, this, &CStudioAppPrefsPage::OnSelChangeInterpolationDefault);
+ connect(m_ui->m_SnapRangeCombo, activated, this, &CStudioAppPrefsPage::OnSelChangeSnapRange);
+ connect(m_ui->m_checkTimelineAbsoluteSnapping, &QCheckBox::clicked, this, &CStudioAppPrefsPage::OnCheckTimelineAbsoluteSnapping);
+ connect(m_ui->m_EditViewBGColor, &QPushButton::clicked, this, &CStudioAppPrefsPage::OnBgColorButtonClicked);
+ connect(m_ui->m_editNudgeAmount, &QLineEdit::textEdited, this, &CStudioAppPrefsPage::OnChangeEditNudgeAmount);
+ connect(m_ui->m_EditViewStartupView, activated, this, &CStudioAppPrefsPage::OnSelChangeStartupView);
+ connect(m_ui->m_PreviewSelector, activated, this, &CStudioAppPrefsPage::OnChangePreviewConfiguration);
+}
+
+//==============================================================================
+/**
+ * LoadSettings: Load the settings from the CDoc and set the control values.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::LoadSettings()
+{
+ m_nudgeValue = CStudioPreferences::GetNudgeAmount();
+
+ // Get the Interpolation Preference
+ Q3DStudio::CString theComboItem;
+ theComboItem = ::LoadResourceString(IDS_PREF_INTERPOLATION_1);
+ m_ui->m_DefaultInterpolation->addItem(theComboItem.toQString());
+ theComboItem = ::LoadResourceString(IDS_PREF_INTERPOLATION_2);
+ m_ui->m_DefaultInterpolation->addItem(theComboItem.toQString());
+
+ long theInterpolationPref = 0;
+ if (CStudioPreferences::GetInterpolation())
+ theInterpolationPref = 0;
+ else
+ theInterpolationPref = 1;
+ m_ui->m_DefaultInterpolation->setCurrentIndex(theInterpolationPref);
+
+ // Timeline snapping grid
+ m_ui->m_checkTimelineAbsoluteSnapping->setChecked(
+ CStudioPreferences::IsTimelineSnappingGridActive());
+
+ // Load the combo boxes with values from the string table so that they are localizable.
+ // The scale mode
+ (void)theComboItem;
+ theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_1);
+ m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString());
+ theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_2);
+ m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString());
+ theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_3);
+ m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString());
+ long theResolution = (long)CStudioPreferences::GetTimelineSnappingGridResolution();
+ m_ui->m_SnapRangeCombo->setCurrentIndex(theResolution);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // Edit View Background color
+ // TODO: Visualize selected color on the bg color change button
+ InitEditStartViewCombo();
+#endif
+
+ EnableOptions();
+
+ LoadPreviewSelections();
+
+ m_ui->m_editNudgeAmount->setText(QString::number(m_nudgeValue));
+ m_bgColor = CStudioPreferences::GetEditViewBackgroundColor();
+ updateColorButton();
+}
+
+void CStudioAppPrefsPage::updateColorButton()
+{
+ QPalette pal = m_ui->m_EditViewBGColor->palette();
+ pal.setColor(QPalette::Button, m_bgColor);
+ m_ui->m_EditViewBGColor->setPalette(pal);
+}
+
+//==============================================================================
+/**
+ * SaveSettings: Save the settings from the controls to the CDoc
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::SaveSettings()
+{
+ // Nudge amount
+ CStudioPreferences::SetNudgeAmount(m_nudgeValue);
+
+ // Default interpolation
+ g_StudioApp.GetCore()->GetDoc()->SetDefaultKeyframeInterpolation(
+ m_ui->m_DefaultInterpolation->currentIndex() == 0);
+
+ // Timeline snapping grid
+ CStudioPreferences::SetTimelineSnappingGridActive(
+ m_ui->m_checkTimelineAbsoluteSnapping->isChecked());
+ long theCurrentSelection = m_ui->m_SnapRangeCombo->currentIndex();
+ CStudioPreferences::SetTimelineSnappingGridResolution((ESnapGridResolution)theCurrentSelection);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // Edit View Background Color
+ CStudioPreferences::SetEditViewBackgroundColor(m_bgColor);
+ //
+ // g_StudioApp.GetCore()->GetDoc( )->SetEditViewBackgroundColor( theColor );
+
+ // Preferred Startup View
+ long theSel = m_ui->m_EditViewStartupView->currentIndex();
+ long theNumItems = m_ui->m_EditViewStartupView->count();
+ CStudioPreferences::SetPreferredStartupView(
+ (theSel == theNumItems - 1) ? -1 : theSel); // -1 for deployment view
+// g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false );
+#endif
+
+ SavePreviewSettings();
+}
+
+//==============================================================================
+/**
+ * OnApply: Handler for the Apply button
+ *
+ * @param None
+ */
+//==============================================================================
+bool CStudioAppPrefsPage::OnApply()
+{
+ // Apply was clicked - save settings and disabled the Apply button
+ this->SaveSettings();
+
+ this->SetModified(FALSE);
+
+ // Request that the renderer refreshes as settings may have changed
+ g_StudioApp.GetRenderer().RequestRender();
+
+ return CStudioPreferencesPropPage::OnApply();
+}
+
+//==============================================================================
+/**
+ * OnOK: Handler for the OK button
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnOK()
+{
+ CStudioPreferencesPropPage::OnOK();
+}
+
+//==============================================================================
+/**
+ * OnCancel: Handler for the Cancel button
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnCancel()
+{
+#ifdef INCLUDE_EDIT_CAMERA
+ // if the edit view background color was changed, reset it back to the original
+ // value
+ CColor theOrigColor = CStudioPreferences::GetEditViewBackgroundColor();
+ if (m_bgColor != theOrigColor) {
+ // g_StudioApp.GetCore()->GetDoc( )->SetEditViewBackgroundColor( theOrigColor );
+ // g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false );
+ }
+#endif
+ CStudioPreferencesPropPage::OnCancel();
+}
+
+//==============================================================================
+/**
+ * OnButtonRestoreDefaults: Restore the defaults and exit the preferences.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnButtonRestoreDefaults()
+{
+ Q3DStudio::CString theMessage;
+ Q3DStudio::CString theTitle;
+ int theChoice = 0;
+
+ // Load the text strings for the message box
+ theTitle = ::LoadResourceString(IDS_PREF_RESTOREDEFAULT_TITLE);
+ theMessage = ::LoadResourceString(IDS_PREF_RESTOREDEFAULT_TEXT);
+
+ // Ask the user if she really wants to do this
+ theChoice = QMessageBox::question(this, theTitle.toQString(), theMessage.toQString());
+
+ // If the "yes" button was selected
+ if (theChoice == QMessageBox::Yes) {
+ // Restore default preferences by passing PREFS_RESET_DEFAULTS back
+ // to the CStudioDocPreferences (that called this preferences sheet)
+ CStudioPreferencesPropPage::EndDialog(PREFS_RESET_DEFAULTS);
+ }
+}
+
+//==============================================================================
+/**
+ * OnSelChangeInterpolationDefault: CBN_SELCHANGE handler for the
+ * IDC_INTERPOLATION_DEFAULT combo
+ *box.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnSelChangeInterpolationDefault()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeEditNudgeAmount: EN_UPDATE handler for the IDC_EDIT_NUDGE
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnChangeEditNudgeAmount()
+{
+ QString editStr = m_ui->m_editNudgeAmount->text();
+ m_nudgeValue = editStr.toDouble();
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * OnSelChangeSnapRange: CBN_SELCHANGE handler for the IDC_SNAPRANGE combo box.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnSelChangeSnapRange()
+{
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * OnCheckTimelineAbsoluteSnapping: Handler for the IDC_CHECK_TIMELINEABSOLUTESNAPPING
+ *checkbox.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnCheckTimelineAbsoluteSnapping()
+{
+ this->SetModified(true);
+ this->EnableOptions();
+}
+
+//==============================================================================
+/**
+ * EnableOptions: Enable/disable options.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::EnableOptions()
+{
+ m_ui->m_SnapRangeCombo->setEnabled(m_ui->m_checkTimelineAbsoluteSnapping->isChecked());
+}
+
+//==============================================================================
+/**
+ * OnSelChangeStartupView: CBN_SELCHANGE handler for the IDC_COMBO_EDIT_STARTUP_VIEW
+ * Combo box
+ */
+void CStudioAppPrefsPage::OnSelChangeStartupView()
+{
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * Initialise the combo box that displays the preferred startup view.
+ * Set the initial selection to that saved to the preferences
+ */
+//==============================================================================
+void CStudioAppPrefsPage::InitEditStartViewCombo()
+{
+ Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer();
+ QStringList theCameraNames;
+ theRenderer.GetEditCameraList(theCameraNames);
+ for (size_t idx = 0, end = theCameraNames.size(); idx < end; ++idx) {
+ m_ui->m_EditViewStartupView->addItem(
+ theCameraNames.at(idx));
+ m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, QVariant((int)idx + 1));
+ }
+
+ m_ui->m_EditViewStartupView->addItem("--------------------------");
+ m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, -1); // set to an invalid pointer
+ // add the deployment view as the last selection
+ m_ui->m_EditViewStartupView->addItem(::LoadResourceString(IDS_SCENE_CAMERA_VIEW).toQString());
+ m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, 0);
+
+ long thePreferredView = CStudioPreferences::GetPreferredStartupView();
+ long theNumItems = m_ui->m_EditViewStartupView->count();
+ if (thePreferredView == -1) // deployment view
+ m_ui->m_EditViewStartupView->setCurrentIndex(theNumItems - 1); // set to the last one
+ else if (thePreferredView < theNumItems - 1)
+ m_ui->m_EditViewStartupView->setCurrentIndex(thePreferredView);
+ else // possibly from old content where cameras are removed
+ m_ui->m_EditViewStartupView->setCurrentIndex(0);
+}
+
+void CStudioAppPrefsPage::LoadPreviewSelections()
+{
+ // Load the configurations from all the .build files
+ Q3DStudio::CBuildConfigurations &theConfig = g_StudioApp.GetCore()->GetBuildConfigurations();
+ Q3DStudio::CBuildConfigurations::TBuildConfigurations theConfigurations =
+ theConfig.GetConfigurations();
+ Q3DStudio::CBuildConfigurations::TBuildConfigurations::iterator theIter;
+ for (theIter = theConfigurations.begin(); theIter != theConfigurations.end(); ++theIter) {
+ const Q3DStudio::CString &theConfig = theIter->first;
+ m_ui->m_PreviewSelector->addItem(theConfig.toQString());
+ m_ui->m_PreviewSelector->setItemData(m_ui->m_PreviewSelector->count() - 1,
+ QVariant::fromValue(theIter->second));
+ }
+
+ int thePreviewSelected = m_ui->m_PreviewSelector->findText(CStudioPreferences::GetPreviewConfig().toQString());
+ m_ui->m_PreviewSelector->setCurrentIndex(thePreviewSelected);
+ if (thePreviewSelected == -1) {
+ // select the first build configuration, or if no conriguration, the first application, i.e.
+ // AMPlayer
+ m_ui->m_PreviewSelector->setCurrentIndex(0);
+ long thePreviewCount = m_ui->m_PreviewSelector->count();
+ for (long theIndex = 0; theIndex < thePreviewCount; ++theIndex) {
+ if (m_ui->m_PreviewSelector->itemData(theIndex).value<Q3DStudio::CBuildConfiguration *>() != nullptr) {
+ m_ui->m_PreviewSelector->setCurrentIndex(theIndex);
+ break;
+ }
+ }
+ }
+
+ LoadBuildProperties();
+}
+
+//==============================================================================
+/**
+ * When the build configuration is changed, all the properties have to be updated.
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnChangePreviewConfiguration()
+{
+ LoadBuildProperties();
+}
+
+void CStudioAppPrefsPage::OnBgColorButtonClicked()
+{
+ QColorDialog dlg(this);
+ dlg.setCurrentColor(m_bgColor);
+ if (dlg.exec() == QDialog::Accepted) {
+ m_bgColor = dlg.selectedColor();
+ updateColorButton();
+ }
+
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * Load the build properties for the current preview application selected
+ */
+//==============================================================================
+void CStudioAppPrefsPage::LoadBuildProperties()
+{
+ // Remove those dynamic controls
+ RemovePreviewPropertyControls();
+
+ if (m_ui->m_PreviewSelector->count() > 0) {
+ Q3DStudio::CBuildConfiguration *theConfig =
+ m_ui->m_PreviewSelector->itemData(m_ui->m_PreviewSelector->currentIndex()).value<Q3DStudio::CBuildConfiguration *>();
+ if (theConfig) {
+ // Only configuration read from .build files will have the ItemDataPtr set.
+
+ Q3DStudio::CBuildConfiguration::TConfigProperties &theProperties =
+ theConfig->GetBuildProperties();
+
+ auto layout = qobject_cast<QFormLayout *>(m_ui->groupBoxPreview->layout());
+ auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated);
+
+ if (theProperties.empty() == false) {
+ Q3DStudio::CBuildConfiguration::TConfigProperties::iterator theIter;
+
+ for (theIter = theProperties.begin(); theIter != theProperties.end(); ++theIter) {
+ Q3DStudio::CBuildConfiguration::TConfigPropertyValues &theValues =
+ theIter->GetAcceptableValues();
+ // Only create the combo if there is more than 1 choices
+ if (theValues.size() > 1) {
+ Q3DStudio::CBuildConfiguration::TConfigPropertyValues::iterator
+ theValueIter;
+ long theMaxLength = 0;
+ for (theValueIter = theValues.begin(); theValueIter != theValues.end();
+ ++theValueIter) {
+ long theLabelLength = theValueIter->GetLabel().Length();
+ if (theLabelLength > theMaxLength)
+ theMaxLength = theLabelLength;
+ }
+
+ QLabel *theStaticText = new QLabel(theIter->GetLabel().toQString());
+ theStaticText->setFont(m_Font);
+ QComboBox *thePropertyDropdown = new QComboBox();
+ connect(thePropertyDropdown, activated, [&]() {SetModified(true);});
+ thePropertyDropdown->setFont(m_Font);
+ layout->addRow(theStaticText, thePropertyDropdown);
+
+ m_BuildProperties.push_back(std::make_pair(
+ &*theIter, std::make_pair(theStaticText, thePropertyDropdown)));
+
+ Q3DStudio::CString thePropertyValue =
+ CStudioPreferences::GetPreviewProperty(theIter->GetName());
+ for (theValueIter = theValues.begin(); theValueIter != theValues.end();
+ ++theValueIter) {
+ thePropertyDropdown->addItem(theValueIter->GetLabel().toQString());
+ thePropertyDropdown->setItemData(thePropertyDropdown->count() - 1, QVariant::fromValue(&*theValueIter));
+ if (theValueIter->GetName() == thePropertyValue)
+ thePropertyDropdown->setCurrentIndex(thePropertyDropdown->count() - 1);
+ }
+
+ // Select the first entry
+ if (thePropertyDropdown->currentIndex() == -1)
+ thePropertyDropdown->setCurrentIndex(0);
+ }
+ }
+ }
+ }
+ }
+}
+
+void CStudioAppPrefsPage::SavePreviewSettings()
+{
+ QString thePreviewApp = m_ui->m_PreviewSelector->currentText();
+ CStudioPreferences::SetPreviewConfig(Q3DStudio::CString::fromQString(thePreviewApp));
+
+ std::list<TBuildNameControlPair>::iterator theIter;
+ for (theIter = m_BuildProperties.begin(); theIter != m_BuildProperties.end(); ++theIter) {
+ QComboBox *theCombo = theIter->second.second;
+ Q3DStudio::CString theName = theIter->first->GetName();
+ Q3DStudio::CBuildConfiguration::SConfigPropertyValue *thePropertyValue =
+ theCombo->itemData(theCombo->currentIndex()).value<Q3DStudio::CBuildConfiguration::SConfigPropertyValue *>();
+ CStudioPreferences::SetPreviewProperty(theName, thePropertyValue->GetName());
+ }
+}
+
+//==============================================================================
+/**
+ * Remove all the dynamically added controls that was read in from the build file
+ */
+//==============================================================================
+void CStudioAppPrefsPage::RemovePreviewPropertyControls()
+{
+ // Remove the created control
+ std::list<TBuildNameControlPair>::iterator theIter;
+ for (theIter = m_BuildProperties.begin(); theIter != m_BuildProperties.end(); ++theIter) {
+ delete theIter->second.first;
+ delete theIter->second.second;
+ }
+ m_BuildProperties.clear();
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h
new file mode 100644
index 00000000..a3be36c2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_)
+#define AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BuildConfigParser.h"
+
+#include "StudioPreferencesPropSheet.h"
+
+class QComboBox;
+class QLabel;
+
+class CStudioApp;
+/////////////////////////////////////////////////////////////////////////////
+// CStudioAppPrefsPage dialog
+
+namespace Ui
+{
+ class StudioAppPrefsPage;
+}
+
+class CStudioAppPrefsPage : public CStudioPreferencesPropPage
+{
+ Q_OBJECT
+protected:
+ typedef std::pair<QLabel *, QComboBox *> TBuildLabelDropdownPair;
+ typedef std::pair<Q3DStudio::CBuildConfiguration::SConfigProperty *, TBuildLabelDropdownPair>
+ TBuildNameControlPair;
+
+ // Construction
+public:
+ explicit CStudioAppPrefsPage(QWidget *parent = nullptr);
+ ~CStudioAppPrefsPage();
+
+ // Dialog Data
+ QColor m_bgColor;
+
+ double m_nudgeValue;
+
+public:
+ bool OnApply() override;
+ void OnOK() override;
+ void OnCancel() override;
+
+ // Implementation
+protected:
+ BOOL m_TimebarShowTime; ///< TRUE if timebars are to display their time value
+ BOOL m_InterpolationIsSmooth; ///< TRUE if default interpolation is smooth
+ QFont m_Font; ///< Font for text
+ QFont m_BoldFont; ///< Bold font for drawing the group boxes
+ void EnableOptions();
+ void LoadSettings();
+ void SaveSettings();
+
+ // Generated message map functions
+ virtual void OnInitDialog();
+ void OnButtonRestoreDefaults();
+ void OnSelChangeInterpolationDefault();
+ void OnSelChangeSnapRange();
+ void OnCheckTimelineAbsoluteSnapping();
+ void OnChangeEditNudgeAmount();
+ void OnSelChangeStartupView();
+ void OnChangePreviewConfiguration();
+ void OnBgColorButtonClicked();
+
+protected: // helper functions
+ void InitEditStartViewCombo();
+
+protected:
+ std::list<TBuildNameControlPair>
+ m_BuildProperties; ///< List of build properties, either ComboBox or Static
+
+ void LoadPreviewSelections();
+ void LoadBuildProperties();
+ void SavePreviewSettings();
+ void RemovePreviewPropertyControls();
+
+ QScopedPointer<Ui::StudioAppPrefsPage> m_ui;
+
+private:
+ void updateColorButton();
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui
new file mode 100644
index 00000000..5e1b88c5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioAppPrefsPage</class>
+ <widget class="QWidget" name="StudioAppPrefsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>347</width>
+ <height>387</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>General</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Nudge Increment</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_editNudgeAmount</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Default Interpolation</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_DefaultInterpolation</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="m_DefaultInterpolation"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="m_checkTimelineAbsoluteSnapping">
+ <property name="text">
+ <string>Timeline Snapping Grid</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="m_SnapRangeCombo"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="m_editNudgeAmount"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="m_groupBoxEditingView">
+ <property name="title">
+ <string>Editing View</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Background Color</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_EditViewBGColor</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" colspan="2">
+ <widget class="QPushButton" name="m_EditViewBGColor">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Preferred Startup View</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_EditViewStartupView</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" colspan="2">
+ <widget class="QComboBox" name="m_EditViewStartupView"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="m_buttonRestoreDefaults">
+ <property name="maximumSize">
+ <size>
+ <width>293</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Restore Defaults</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBoxPreview">
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Configuration</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_PreviewSelector</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="m_PreviewSelector"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp
new file mode 100644
index 00000000..747ba442
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPaletteBar.h"
+#include "Preferences.h"
+#include "StudioConst.h"
+#include "PaletteState.h"
+#include "StudioApp.h"
+
+//==============================================================================
+// Message Maps
+//==============================================================================
+BEGIN_MESSAGE_MAP(CStudioPaletteBar, CViewBar)
+//{{AFX_MSG_MAP(CStudioPaletteBar)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+// Constructors/Destructors
+//==============================================================================
+
+CStudioPaletteBar::CStudioPaletteBar()
+{
+}
+
+CStudioPaletteBar::~CStudioPaletteBar()
+{
+}
+
+void CStudioPaletteBar::SetHorz(CSize inSize)
+{
+ m_szHorz.cx = max(m_szMinHorz.cx, inSize.cx);
+ m_szHorz.cy = max(m_szMinHorz.cy, inSize.cy);
+}
+
+void CStudioPaletteBar::SetVert(CSize inSize)
+{
+ m_szVert.cx = max(m_szMinVert.cx, inSize.cx);
+ m_szVert.cy = max(m_szMinVert.cy, inSize.cy);
+}
+
+void CStudioPaletteBar::SetFloat(CSize inSize)
+{
+ m_szFloat.cx = max(m_szMinFloat.cx, inSize.cx);
+ m_szFloat.cy = max(m_szMinFloat.cy, inSize.cy);
+}
+
+//==============================================================================
+/**
+ * Create: A wrapper around the CViewBar::Create() method.
+ *
+ * Simplifies the create parameters for the palette bar.
+ *
+ * @return BOOL The result from the Create() call (FALSE if unsuccessful)
+ */
+BOOL CStudioPaletteBar::Create(CString inTitle, CCreateContext *inCreateContext, long inControlId,
+ CWnd *theParent /* = nullptr */)
+{
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_PaletteName = inTitle;
+
+ // Create the palette bar.
+ theReturnValue =
+ CViewBar::Create(theParent, inCreateContext, inTitle, WS_CHILD | CBRS_TOP, inControlId);
+ ASSERT(theReturnValue == TRUE);
+
+ SetBarStyle(GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+ EnableDocking(CBRS_ALIGN_ANY);
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Call this function when the palette's view needs to be updated for the first
+ * time on application launch.
+ */
+void CStudioPaletteBar::InitialUpdate()
+{
+ // Send the update message to the attached CView
+ SendMessageToDescendants(WM_STUDIO_INITIALIZE_PALETTES, reinterpret_cast<WPARAM>(&g_StudioApp));
+}
+
+//==============================================================================
+/**
+ * Shows or hides the palette and saves the visibility.
+ *
+ * This function should be called instead of ShowWindow(), so that the visibility
+ * will be saved in the registry.
+ */
+void CStudioPaletteBar::ShowPalette(bool inState /* = true */)
+{
+ ShowWindow(inState ? SW_SHOW : SW_HIDE);
+ m_pDockSite->ShowControlBar(this, inState, FALSE);
+}
+
+//==============================================================================
+/**
+ * Query the view associated with this palette
+ */
+CView *CStudioPaletteBar::GetView()
+{
+ // Looks like the first grandchild is the view
+ return (CView *)GetWindow(GW_CHILD)->GetWindow(GW_CHILD);
+}
+
+//==============================================================================
+// Message Maps
+//==============================================================================
+BEGIN_MESSAGE_MAP(CStudioDialog, CMiniFrameWnd)
+//{{AFX_MSG_MAP(CStudioDialog)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+// Constructors/Destructors
+//==============================================================================
+
+CStudioDialog::CStudioDialog()
+{
+}
+
+CStudioDialog::~CStudioDialog()
+{
+}
+
+//==============================================================================
+/**
+ * Create: A wrapper around the CMiniFrameWnd::Create() method.
+ *
+ * Simplifies the create parameters for the palette bar.
+ *
+ * @return BOOL The result from the Create() call (FALSE if unsuccessful)
+ */
+/*
+BOOL CStudioDialog::Create( CString inTitle, CCreateContext* inCreateContext, long inControlId,
+CWnd* theParent )
+{
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Create the palette bar.
+ theReturnValue = CMiniFrameWnd::Create( theParent, inCreateContext, _T( inTitle ), WS_CHILD
+| CBRS_TOP, inControlId );
+ ASSERT( theReturnValue == TRUE );
+
+ SetBarStyle( GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC );
+ EnableDocking(CBRS_ALIGN_ANY);
+
+ return theReturnValue;
+}*/
+
+//==============================================================================
+/**
+* Create: A wrapper around the CMiniFrameWnd::Create() method.
+*
+* Simplifies the create parameters for the palette bar.
+*
+* @return BOOL The result from the Create() call (FALSE if unsuccessful)
+*/
+//==============================================================================
+BOOL CStudioDialog::Create(CString inTitle, CCreateContext *inCreateContext,
+ CWnd *theParent /* = nullptr */)
+{
+ CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_ARROW));
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Create the palette bar.
+ theReturnValue = CFrameWnd::Create(
+ theWndClass, inTitle, WS_SYSMENU | MFS_SYNCACTIVE | WS_POPUP | WS_CAPTION | MFS_THICKFRAME,
+ CRect(300, 300, 550, 800), theParent, nullptr, 0, inCreateContext);
+
+ // Get the view to initialize.
+ this->InitialUpdateFrame(inCreateContext->m_pCurrentDoc, FALSE);
+
+ // Get a handle to the system menu on the palette window
+ CMenu *theSystemMenu = GetSystemMenu(FALSE);
+
+ // Remove the unwanted system menu items
+ theSystemMenu->DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND);
+ theSystemMenu->DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND);
+ theSystemMenu->DeleteMenu(SC_RESTORE, MF_BYCOMMAND);
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Call this function when the palette's view needs to be updated for the first
+ * time on application launch.
+ */
+void CStudioDialog::InitialUpdate()
+{
+ // Send the update message to the attached CView
+ SendMessageToDescendants(WM_STUDIO_INITIALIZE_PALETTES, reinterpret_cast<WPARAM>(&g_StudioApp));
+}
+
+//==============================================================================
+/**
+ * Shows or hides the dialog and saves the visibility.
+ *
+ * This function should be called instead of ShowWindow(), so that the visibility
+ * will be saved in the registry.
+ */
+void CStudioDialog::ShowDialog(bool inState /* = true */)
+{
+ ShowWindow(inState ? SW_SHOW : SW_HIDE);
+ // m_pDockSite->ShowControlBar( this, inState, FALSE );
+}
+
+//==============================================================================
+/**
+ * Query the view associated with this palette
+ */
+CView *CStudioDialog::GetView()
+{
+ // Looks like the first grandchild is the view
+ return (CView *)GetWindow(GW_CHILD)->GetWindow(GW_CHILD);
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h
new file mode 100644
index 00000000..eed3fd05
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PALETTE_BAR_H
+#define INCLUDED_STUDIO_PALETTE_BAR_H 1
+
+#pragma once
+
+#include "ViewBar.h"
+
+class CStudioApp;
+class CPaletteState;
+class CStudioApp;
+
+class CStudioPaletteBar : public CViewBar
+{
+public:
+ CStudioPaletteBar();
+ virtual ~CStudioPaletteBar();
+
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, long inControlId,
+ CWnd *theParent = nullptr);
+
+ void ShowPalette(bool inState = true);
+ void InitialUpdate();
+ CView *GetView();
+ CSize GetHorz() { return m_szHorz; }
+ void SetHorz(CSize inSize);
+ CSize GetVert() { return m_szVert; }
+ void SetVert(CSize inSize);
+ CSize GetFloat() { return m_szFloat; }
+ void SetFloat(CSize inSize);
+
+protected:
+ Q3DStudio::CString m_PaletteName;
+
+ //{{AFX_MSG(CStudioPaletteBar)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+class CStudioDialog : public CMiniFrameWnd
+{
+public:
+ CStudioDialog();
+ virtual ~CStudioDialog();
+
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *theParent = nullptr);
+
+ void ShowDialog(bool inState = true);
+ void InitialUpdate();
+ CView *GetView();
+
+protected:
+ Q3DStudio::CString m_DialogName;
+
+ //{{AFX_MSG(CStudioDialog)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // INCLUDED_STUDIO_PALETTE_BAR_H
diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp
new file mode 100644
index 00000000..eb645d5e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#include "ui_StudioPreferencesPropSheet.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPreferences.h"
+#include "StudioPreferencesPropSheet.h"
+#include "StudioProjectSettingsPage.h"
+#include "StringLoader.h"
+
+#include <QPushButton>
+
+CStudioPreferencesPropPage::CStudioPreferencesPropPage(QWidget *parent)
+ : QWidget(parent)
+{
+}
+
+void CStudioPreferencesPropPage::SetModified(bool modified)
+{
+ setProperty("modified", modified);
+
+ auto s = sheet();
+ if (s) {
+ auto buttons = s->findChild<QDialogButtonBox *>();
+ bool anyModified = false;
+ for (auto page : s->findChildren<CStudioPreferencesPropPage *>())
+ anyModified |= page->property("modified").toBool();
+ buttons->button(QDialogButtonBox::Apply)->setEnabled(anyModified);
+ }
+}
+
+CStudioPreferencesPropSheet* CStudioPreferencesPropPage::sheet()
+{
+ QWidget *parent = parentWidget();
+ while (parent != nullptr) {
+ if (auto sheet = qobject_cast<CStudioPreferencesPropSheet *>(parent))
+ return sheet;
+ parent = parent->parentWidget();
+ }
+ return nullptr;
+}
+
+
+void CStudioPreferencesPropPage::EndDialog(int returnCode)
+{
+ auto s = sheet();
+ if (s)
+ s->done(returnCode);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioPreferencesPropSheet
+
+CStudioPreferencesPropSheet::CStudioPreferencesPropSheet(int nIDCaption, QWidget *pParentWnd,
+ int iSelectPage)
+ : QDialog(pParentWnd)
+ , m_ui(new Ui::StudioPreferencesPropSheet)
+{
+ setWindowTitle(::LoadResourceString(nIDCaption).toQString());
+ OnInitDialog();
+ m_ui->m_TabCtrl->setCurrentIndex(iSelectPage);
+}
+
+CStudioPreferencesPropSheet::CStudioPreferencesPropSheet(const QString &pszCaption, QWidget *pParentWnd,
+ int iSelectPage)
+ : QDialog(pParentWnd)
+ , m_ui(new Ui::StudioPreferencesPropSheet)
+{
+ setWindowTitle(pszCaption);
+ OnInitDialog();
+ m_ui->m_TabCtrl->setCurrentIndex(iSelectPage);
+}
+
+CStudioPreferencesPropSheet::~CStudioPreferencesPropSheet()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioPreferencesPropSheet message handlers
+
+//==============================================================================
+/**
+ * OnInitDialog: Handle the WM_INITDIALOG message to initialize the property sheet.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioPreferencesPropSheet::OnInitDialog()
+{
+ m_ui->setupUi(this);
+ m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
+
+ m_Font = QFont(CStudioPreferences::GetFontFaceName(), 8);
+ setFont(m_Font);
+
+ connect(m_ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked,
+ this, &CStudioPreferencesPropSheet::apply);
+}
+
+bool CStudioPreferencesPropSheet::apply()
+{
+ for (auto page : findChildren<CStudioPreferencesPropPage *>()) {
+ if (!page->OnApply())
+ return false;
+ }
+ return true;
+}
+
+void CStudioPreferencesPropSheet::accept()
+{
+ if (apply())
+ QDialog::accept();
+}
+
+void CStudioPreferencesPropSheet::reject()
+{
+ for (auto page : findChildren<CStudioPreferencesPropPage *>())
+ page->OnCancel();
+ QDialog::reject();
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h
new file mode 100644
index 00000000..7057ba0f
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_)
+#define AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QDialog>
+
+class CStudioProjectSettingsPage;
+class CStudioPreferencesPropSheet;
+class CStudioApp;
+
+namespace Ui
+{
+ class StudioPreferencesPropSheet;
+}
+
+class CStudioPreferencesPropPage : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit CStudioPreferencesPropPage(QWidget *parent = nullptr);
+
+ virtual bool OnApply() { OnOK(); SetModified(false); return true; }
+ virtual void OnOK() {}
+ virtual void OnCancel() {}
+
+protected:
+ CStudioPreferencesPropSheet* sheet();
+
+ void SetModified(bool modified);
+ void EndDialog(int returnCode);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioPreferencesPropSheet
+
+class CStudioPreferencesPropSheet : public QDialog
+{
+ Q_OBJECT
+ // Construction
+public:
+ explicit CStudioPreferencesPropSheet(int nIDCaption, QWidget *pParentWnd = nullptr,
+ int iSelectPage = 0);
+ explicit CStudioPreferencesPropSheet(const QString &pszCaption, QWidget *pParentWnd = nullptr,
+ int iSelectPage = 0);
+
+protected:
+ QFont m_Font; // Font for text
+
+ // Implementation
+public:
+ virtual ~CStudioPreferencesPropSheet();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CStudioPreferencesPropSheet)
+ virtual void OnInitDialog();
+
+ bool apply();
+ void accept() override;
+ void reject() override;
+
+private:
+ QScopedPointer<Ui::StudioPreferencesPropSheet> m_ui;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui
new file mode 100644
index 00000000..813d6016
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioPreferencesPropSheet</class>
+ <widget class="QDialog" name="StudioPreferencesPropSheet">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>484</width>
+ <height>466</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Studio Preferences</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="m_TabCtrl">
+ <widget class="CStudioAppPrefsPage" name="m_AppPrefsPage">
+ <attribute name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/prefstab-00.png</normaloff>:/res/prefstab-00.png</iconset>
+ </attribute>
+ <attribute name="title">
+ <string>Studio</string>
+ </attribute>
+ </widget>
+ <widget class="CStudioProjectSettingsPage" name="m_ProjectSettingsPage">
+ <attribute name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/prefstab-01.png</normaloff>:/res/prefstab-01.png</iconset>
+ </attribute>
+ <attribute name="title">
+ <string>Presentation Settings</string>
+ </attribute>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CStudioProjectSettingsPage</class>
+ <extends>QWidget</extends>
+ <header>StudioProjectSettingsPage.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>CStudioAppPrefsPage</class>
+ <extends>QWidget</extends>
+ <header>StudioAppPrefsPage.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../../MainFrm.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>StudioPreferencesPropSheet</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>StudioPreferencesPropSheet</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp
new file mode 100644
index 00000000..c2a7e26c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+#include "ui_StudioProjectSettingsPage.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioProjectSettingsPage.h"
+#include "StudioProjectSettings.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Views.h"
+#include "MainFrm.h"
+#include "CommonConstants.h"
+
+#include "StudioPreferences.h"
+#include "Core.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioProjectSettingsPage property page
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CStudioProjectSettingsPage::CStudioProjectSettingsPage(QWidget *parent)
+ : CStudioPreferencesPropPage(parent)
+ , m_AspectRatio(0.0f)
+ , m_ui(new Ui::StudioProjectSettingsPage)
+{
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPixelSize(CStudioPreferences::fontSize());
+
+ // Create a bold font for the group box text
+ m_BoldFont = m_Font;
+ m_BoldFont.setBold(true);
+
+ OnInitDialog();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CStudioProjectSettingsPage::~CStudioProjectSettingsPage()
+{
+}
+
+//==============================================================================
+// Message Map is defined by subclasses, since there is any specific handlers must be
+// defined within the BEGIN_MESSAGE_MAP macros.
+//==============================================================================
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioProjectSettingsPage message handlers
+
+//==============================================================================
+/**
+ * OnInitDialog: Handle the WM_INITDIALOG message.
+ *
+ * Initialize the dialog by setting the various control values.
+ *
+ * @param None
+ *
+ * @return Returns TRUE always.
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnInitDialog()
+{
+ m_ui->setupUi(this);
+
+ m_ui->m_ClientSizeWidth->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONWIDTH).toQString());
+ m_ui->m_ClientSizeHeight->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONHEIGHT).toQString());
+ m_ui->m_checkConstrainProportions->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONASPECTRATIO).toQString());
+ m_ui->m_Author->setToolTip(::LoadResourceString(IDS_PREFS_AUTHORNAME).toQString());
+ m_ui->m_Company->setToolTip(::LoadResourceString(IDS_PREFS_COMPANYNAME).toQString());
+
+ // Set fonts for child windows.
+ for (auto w : findChildren<QWidget *>())
+ w->setFont(m_Font);
+
+ // Make the group text bold
+ for (auto w : findChildren<QGroupBox *>())
+ w->setFont(m_BoldFont);
+
+ // Set the ranges of the client width and height
+ m_ui->m_ClientSizeWidth->setRange(1, 16384);
+ m_ui->m_ClientSizeHeight->setRange(1, 16384);
+
+ // Load the settings for the controls
+ this->LoadSettings();
+
+ auto valueChanged = static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged);
+ connect(m_ui->m_ClientSizeWidth, valueChanged, this, &CStudioProjectSettingsPage::OnChangeEditPresWidth);
+ connect(m_ui->m_ClientSizeHeight, valueChanged, this, &CStudioProjectSettingsPage::OnChangeEditPresHeight);
+ connect(m_ui->m_checkConstrainProportions, &QCheckBox::clicked, this, &CStudioProjectSettingsPage::OnCheckMaintainRatio);
+ connect(m_ui->m_Author, &QLineEdit::textEdited, this, &CStudioProjectSettingsPage::OnChangeAuthor);
+ connect(m_ui->m_Company, &QLineEdit::textEdited, this, &CStudioProjectSettingsPage::OnChangeCompany);
+}
+
+//==============================================================================
+/**
+ * LoadSettings: Load the settings from the project settings and set the control values.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::LoadSettings()
+{
+ // Get the Client size
+ CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings();
+ CPt theClientSize = theProjectSettings->GetPresentationSize();
+
+ // Set client width & height
+ m_ui->m_ClientSizeWidth->setValue(theClientSize.x);
+ m_ui->m_ClientSizeHeight->setValue(theClientSize.y);
+
+ // Save the aspect ratio
+ m_AspectRatio = (double)theClientSize.x / (double)theClientSize.y;
+
+ // Maintain Aspect Ratio checkbox
+ m_ui->m_checkConstrainProportions->setChecked(theProjectSettings->GetMaintainAspect());
+
+ m_ui->m_checkPortraitFormat->setChecked(theProjectSettings->GetRotatePresentation());
+
+ // Author
+ m_ui->m_Author->setText(theProjectSettings->GetAuthor());
+
+ // Company
+ m_ui->m_Company->setText(theProjectSettings->GetCompany());
+}
+
+//==============================================================================
+/**
+ * SaveSettings: Save the settings from the controls to the project settings.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::SaveSettings()
+{
+ CPt theClientSize;
+ CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings();
+
+ // Presentation width & height
+ theClientSize.x = m_ui->m_ClientSizeWidth->value();
+ theClientSize.y = m_ui->m_ClientSizeHeight->value();
+ theProjectSettings->SetPresentationSize(theClientSize);
+
+ // Author
+ QString theAuthor = m_ui->m_Author->text();
+ theProjectSettings->SetAuthor(theAuthor);
+
+ // Company
+ QString theCompany = m_ui->m_Company->text();
+ theProjectSettings->SetCompany(theCompany);
+
+ g_StudioApp.GetViews()->RecheckMainframeSizingMode();
+
+ // Maintain Aspect Ratio checkbox
+ theProjectSettings->SetMaintainAspect(m_ui->m_checkConstrainProportions->isChecked());
+
+ theProjectSettings->SetRotatePresentation(m_ui->m_checkPortraitFormat->isChecked());
+}
+
+//==============================================================================
+/**
+ * Generic function when settings are modified.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnSettingsModified()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnApply: Handler for the Apply button
+ *
+ * @param None
+ */
+//==============================================================================
+bool CStudioProjectSettingsPage::OnApply()
+{
+ // Apply was clicked - save settings and disabled the Apply button
+ this->SaveSettings();
+
+ this->SetModified(FALSE);
+
+ return CStudioPreferencesPropPage::OnApply();
+}
+
+//==============================================================================
+/**
+ * OnOK: Handler for the OK button
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnOK()
+{
+ CStudioPreferencesPropPage::OnOK();
+}
+
+//==============================================================================
+/**
+ * OnChangeEditPresWidth: EN_CHANGE handler for the IDC_EDIT_PRESWIDTH field
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeEditPresWidth()
+{
+ this->SetModified(TRUE);
+
+ // Should the aspect ratio be maintained?
+ if (m_ui->m_checkConstrainProportions->isChecked()) {
+ long thePresWidth, thePresHeight;
+
+ thePresWidth = m_ui->m_ClientSizeWidth->value();
+
+ // Change the height
+ thePresHeight = ((double)thePresWidth / m_AspectRatio);
+
+ QSignalBlocker sb(m_ui->m_ClientSizeHeight);
+ m_ui->m_ClientSizeHeight->setValue(thePresHeight);
+ }
+}
+
+//==============================================================================
+/**
+ * OnChangeEditPresHeight: EN_CHANGE handler for the IDC_EDIT_PRESHEIGHT field
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeEditPresHeight()
+{
+ this->SetModified(TRUE);
+
+ // Should the aspect ratio be maintained?
+ if (m_ui->m_checkConstrainProportions->isChecked()) {
+ long thePresWidth, thePresHeight;
+
+ thePresHeight = m_ui->m_ClientSizeHeight->value();
+
+ // Change the width
+ thePresWidth = ((double)thePresHeight * m_AspectRatio);
+
+ QSignalBlocker sb(m_ui->m_ClientSizeWidth);
+ m_ui->m_ClientSizeWidth->setValue(thePresWidth);
+ }
+}
+
+//==============================================================================
+/**
+ * OnCheckMaintainRatio: The aspect ratio checkbox has changed.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnCheckMaintainRatio()
+{
+ this->SetModified(TRUE);
+
+ long thePresWidth, thePresHeight;
+
+ // Get the width and height
+ thePresWidth = m_ui->m_ClientSizeWidth->value();
+ thePresHeight = m_ui->m_ClientSizeHeight->value();
+
+ // Save the Aspect Ratio
+ m_AspectRatio = (double)thePresWidth / (double)thePresHeight;
+}
+
+//==============================================================================
+/**
+ * OnChangeAuthor: EN_CHANGE handler for the IDC_AUTHOR field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeAuthor()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeCompany: EN_CHANGE handler for the IDC_COMPANY field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeCompany()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet1: EN_CHANGE handler for the IDC_SET1 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet1()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet2: EN_CHANGE handler for the IDC_SET2 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet2()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet3: EN_CHANGE handler for the IDC_SET3 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet3()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet5: EN_CHANGE handler for the IDC_SET5 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet5()
+{
+ this->SetModified(TRUE);
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h
new file mode 100644
index 00000000..64465e98
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if !defined(AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_)
+#define AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//#include "ParameterColor.h"
+
+#include "StudioPreferencesPropSheet.h"
+
+#ifdef _USENEWCOLORPICKER_
+#include "StudioColorPicker.h"
+#endif
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+
+namespace Ui {
+ class StudioProjectSettingsPage;
+}
+
+//==============================================================================
+// Base class for the settings for different modes
+//==============================================================================
+class CStudioProjectSettingsPage : public CStudioPreferencesPropPage
+{
+ Q_OBJECT
+ // Construction
+public:
+ explicit CStudioProjectSettingsPage(QWidget *parent = nullptr);
+ ~CStudioProjectSettingsPage();
+
+ // Overrides
+ // ClassWizard generate virtual function overrides
+public:
+ bool OnApply() override;
+ void OnOK() override;
+
+ // Implementation
+protected:
+ double m_AspectRatio; ///< Stores the presentation width divided by the presentation height
+ QFont m_Font; ///< Font for text
+ QFont m_BoldFont; ///< Bold font for drawing the group boxes
+
+ void LoadSettings();
+ void SaveSettings();
+
+protected:
+ // Generated message map functions
+ virtual void OnInitDialog();
+ void OnChangeEditPresWidth();
+ void OnChangeEditPresHeight();
+ void OnCheckMaintainRatio();
+ void OnChangeAuthor();
+ void OnChangeCompany();
+ void OnSettingsModified();
+ void OnSelChangePreviewApp();
+ void OnCustomPreviewMore();
+ void OnChangeSet1();
+ void OnChangeSet2();
+ void OnChangeSet3();
+ void OnChangeSet5();
+
+ QScopedPointer<Ui::StudioProjectSettingsPage> m_ui;
+};
+
+#endif // !defined(AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui
new file mode 100644
index 00000000..07a4bf65
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioProjectSettingsPage</class>
+ <widget class="QWidget" name="StudioProjectSettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>259</width>
+ <height>269</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Presentation</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Width x Height</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_ClientSizeWidth</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QSpinBox" name="m_ClientSizeWidth">
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="m_ClientSizeHeight">
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="m_checkConstrainProportions">
+ <property name="text">
+ <string>Constrain Proportions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QCheckBox" name="m_checkPortraitFormat">
+ <property name="text">
+ <string>Portrait Format</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Project Info</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Author</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_Author</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="m_Author"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Company</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_Company</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="m_Company"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>m_ClientSizeWidth</tabstop>
+ <tabstop>m_ClientSizeHeight</tabstop>
+ <tabstop>m_checkConstrainProportions</tabstop>
+ <tabstop>m_checkPortraitFormat</tabstop>
+ <tabstop>m_Author</tabstop>
+ <tabstop>m_Company</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp b/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp
new file mode 100644
index 00000000..619d7651
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp
@@ -0,0 +1,524 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+
+#include "ui_timeeditdlg.h"
+
+#include "stdafx.h"
+#include "StudioPreferences.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TimeEditDlg.h"
+#include "IDoc.h"
+#include "Bindings/ITimelineKeyframesManager.h"
+
+#include <QFont>
+#include <QPalette>
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimeEditDlg::CTimeEditDlg(QWidget *pParent)
+ : QDialog(pParent)
+ , m_MaxTime(0)
+ , m_MaxTimeDisplay(0)
+ , m_MinTimeDisplay(0)
+ , m_InitialTime1(0)
+ , m_InitialTime2(0)
+ , m_MinOffset(0)
+ , m_SecOffset(0)
+ , m_MSecOffset(0)
+ , m_MinMinorOffset(0)
+ , m_SecMinorOffset(0)
+ , m_MSecMinorOffset(0)
+ , m_CursorPosition(0)
+ , m_TimeFormat(0)
+ , m_PreviousFormat(0)
+ , m_TimeInMins(0.0f)
+ , m_NumberOfDigitsDrop(0)
+ , m_ColonPosition1(0)
+ , m_ColonPosition2(0)
+ , m_ObjectAssociation(0)
+ , m_OffsetFromInitialTime(0)
+ , m_Time1(0)
+ , m_Time2(0)
+ , m_Doc(nullptr)
+ , m_KeyframesManager(nullptr)
+ , m_Callback(nullptr)
+ , m_ui(new Ui::TimeEditDlg)
+{
+ m_ui->setupUi(this);
+ setAutoFillBackground(true);
+
+ connect(m_ui->startTimeEdit, &QDateTimeEdit::timeChanged, this, &CTimeEditDlg::OnEnChangeTimeEdit1);
+ connect(m_ui->endTimeEdit, &QDateTimeEdit::timeChanged, this, &CTimeEditDlg::OnEnChangeTimeEdit2);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimeEditDlg::~CTimeEditDlg()
+{
+ delete m_ui;
+}
+
+void CTimeEditDlg::SetKeyframesManager(ITimelineKeyframesManager *inKeyframesManager)
+{
+ m_KeyframesManager = inKeyframesManager;
+}
+
+//=============================================================================
+/**
+ * InitData: Initializes the Time Edit Dialog Box.
+ * @param inTime1 is the intial start time, which will be shown when the time edit
+ * dialog box pops up
+ * @param inTime2 is the intial end time, which will be shown when the time edit
+ * dialog box pops up
+ * @param inDoc this can be nullptr where its not applicable
+ * @param inObjectAssociation is the identifier for that identifies the object
+ * associated with the time edit dialog
+ *(e.g.
+ * playhead, keyframe, timebar)
+ */
+void CTimeEditDlg::ShowDialog(long inTime1, long inTime2, IDoc *inDoc, long inObjectAssociation,
+ ITimeChangeCallback *inCallback /*= nullptr*/)
+{
+ m_InitialTime1 = inTime1;
+ m_InitialTime2 = inTime2;
+ m_ObjectAssociation = inObjectAssociation;
+ m_Doc = inDoc;
+ m_Callback = inCallback;
+
+ m_OffsetFromInitialTime = 0;
+ m_NumberOfDigitsDrop = 0;
+ m_MinTimeDisplay = 0;
+ // if it is a Timebar, this will be adjusted, else this should be initialized to some value at
+ // least,
+ // for OverflowHandling to work correctly
+ m_MaxTimeDisplay = LONG_MAX;
+
+ // 9999:59:999 converted to milliseconds
+ m_MaxTime =
+ TimeConversion(9999, CONVERT_MIN_TO_MSEC) + TimeConversion(59, CONVERT_SEC_TO_MSEC) + 999;
+
+ m_TimeDisplay2 = FormatTime(m_InitialTime2);
+ // In cases Keyframes, where its only one set of time, do m_InitialTime1 later so that
+ // m_Min, etc. values are initializd to the valid values.
+ m_TimeDisplay1 = FormatTime(m_InitialTime1);
+
+ // Present the dialog
+ exec();
+}
+
+//==============================================================================
+/**
+ * FormatTime: Called to break up a given time in milliseconds into min:sec:msec
+ * store it in a string. The string is formatted in 99:59:999 form.
+ * @param inTime stores the time in milliseconds, which will be converted
+ * and stored in ioTimeString in 99:59:999 format.
+ * @return ioTimeString stores the result of the FormatTime method.
+ */
+QString CTimeEditDlg::FormatTime(long inTime)
+{
+ long theTime = inTime;
+ long hour = 0;
+ long min = 0;
+ long sec = 0;
+ long msec = 0;
+ // Translates the m_InitialTime1 (in milliseconds) into Minutes, Seconds and Milliseconds
+ if (inTime != 0) {
+ min = TimeConversion(theTime, CONVERT_MSEC_TO_MIN);
+ hour = min / 60;
+ theTime = theTime - TimeConversion(min, CONVERT_MIN_TO_MSEC);
+ min -= hour * 60;
+ sec = TimeConversion(theTime, CONVERT_MSEC_TO_SEC);
+ theTime = theTime - TimeConversion(sec, CONVERT_SEC_TO_MSEC);
+ msec = theTime;
+ }
+ return QString::asprintf("%02d:%02d:%02d:%03d", hour, min, sec, msec);
+}
+
+//==============================================================================
+/**
+ * OnInitDialog: Handle the WM_INITDIALOG message.
+ * @param None
+ * @return Returns TRUE always.
+ */
+void CTimeEditDlg::showEvent(QShowEvent *ev)
+{
+ OnInitDialog();
+ QDialog::showEvent(ev);
+}
+
+
+void CTimeEditDlg::OnInitDialog()
+{
+ // Hide the window items associated with end time.
+ if (m_ObjectAssociation != TIMEBAR)
+ HideUnnecessaryFields();
+ m_ui->startTimeEdit->setTime(QTime::fromString(m_TimeDisplay1, "hh:mm:ss:zzz"));
+ Q3DStudio::CString theTitle;
+ // Display the window captions for the correct object type
+ switch (m_ObjectAssociation) {
+ case PLAYHEAD:
+ theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_GO_TO_TIME);
+ setWindowTitle(theTitle.toQString());
+ break;
+ case ASSETKEYFRAME:
+ theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_SET_KEYFRAME_TIME);
+ setWindowTitle(theTitle.toQString());
+ break;
+ case TIMEBAR:
+ theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_SET_TIMEBAR_TIME);
+ // m_TimeEditBoxNumber is a flag that switches the output between
+ // the first and second text box.
+ // When m_TimeEditBoxNumber = EDITBOX1, we are writing to the first text box
+ // (the one that appears on top).
+ // When it is EDITBOX2, the SetTimeEdit will write to the second text box.
+ setWindowTitle(theTitle.toQString());
+ m_ui->endTimeEdit->setTime(QTime::fromString(m_TimeDisplay2, "hh:mm:ss:zzz"));
+ break;
+ }
+}
+//==============================================================================
+/**
+ * accept: Upon clicking ok, the dialog will be exited
+ */
+void CTimeEditDlg::accept()
+{
+ // Only commit here, cos dup keyframes will be deleted.
+ if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager)
+ m_KeyframesManager->CommitChangedKeyframes();
+ else if (m_ObjectAssociation == TIMEBAR)
+ m_Callback->Commit();
+
+ QDialog::accept();
+}
+
+//==============================================================================
+/**
+ * reject: Upon clicking Cancel, revert to the initial time.
+ */
+void CTimeEditDlg::reject()
+{
+ // Only commit here, cos dup keyframes will be deleted.
+ if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager)
+ m_KeyframesManager->RollbackChangedKeyframes();
+ else if (m_ObjectAssociation == TIMEBAR)
+ m_Callback->Rollback();
+ QDialog::reject();
+}
+
+//==============================================================================
+/**
+ * CountDigits: Counts the number of digits in a given number
+ * @param inNumber is the number that is used to count the number of digits
+ * @return the number of digits
+ */
+long CTimeEditDlg::CountDigits(long inNumber)
+{
+ long theNumberOfDigits = 0;
+ for (long theNumber = inNumber; theNumber >= 1; theNumber = theNumber / 10)
+ theNumberOfDigits++;
+ return theNumberOfDigits;
+}
+
+
+//==============================================================================
+/**
+ * TimeOverflowUnderflow: Checks if inMin, inSec or inMSec has exceeded the overflow/
+ * underflow limit. It will correct the time if it
+ *overflow/
+ * underflow.
+ * @param inMin stores the min segment of the time
+ * @param inSec stores the sec segment of the time
+ * @param inMSec stores the msec segment of the time
+ * @param inTimeLimit stores the time limit before the overflow/underflow occurs
+ * @param inOverflowOrUnderflow is set to true if we are checking for overflow else
+ * we are checking for underflow
+ * @returns true if overflow/underflow occurs, otherwise returns false.
+ */
+bool CTimeEditDlg::TimeOverflowUnderflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit,
+ bool inOverflowOrUnderflow)
+{
+ // The codes below translates inTimeLimit into theLimitMin:theLimitSec:theLimitMsec
+ bool theLimitExceeds = false;
+ long theLimitMin;
+ long theLimitSec;
+ long theLimitMsec;
+ TimeConversion(inTimeLimit, &theLimitMin, &theLimitSec, &theLimitMsec,
+ CONVERT_MSEC_TO_MIN_SEC_MSEC);
+ // Handle time overflow/underflow
+ if ((*inMin > theLimitMin && inOverflowOrUnderflow)
+ || (*inMin < theLimitMin && inOverflowOrUnderflow == false)) // Minutes exceeds limit
+ {
+ // Set all time segments to the limit
+ *inMin = theLimitMin;
+ *inSec = theLimitSec;
+ *inMSec = theLimitMsec;
+ theLimitExceeds = true;
+ } else if (*inMin == theLimitMin) {
+ if ((*inSec > theLimitSec && inOverflowOrUnderflow)
+ || (*inSec < theLimitSec && inOverflowOrUnderflow == false)) // Seconds exceeds limit
+ {
+ // Set the Sec and Msec segments to the limit
+ *inSec = theLimitSec;
+ *inMSec = theLimitMsec;
+ theLimitExceeds = true;
+ } else if (*inSec == theLimitSec) {
+ if ((*inMSec > theLimitMsec && inOverflowOrUnderflow)
+ || (*inMSec < theLimitMsec
+ && inOverflowOrUnderflow == false)) // Milliseconds exceeds limit
+ {
+ // Msec segments to the limit
+ *inMSec = theLimitMsec;
+ theLimitExceeds = true;
+ }
+ }
+ }
+ return theLimitExceeds;
+}
+
+//==============================================================================
+/**
+ * TimeConversion: Converts inTime to the format specified by inFlags.
+ * For example:
+ * inTime = 5 sec inFlags = CONVERT_SEC_TO_MSEC
+ * The method will convert 5 sec into 5000 msec and
+ *returns
+ * the result.
+ * @param inTime stores the time to be converted.
+ * inOperationCode determines the type of time conversion to be done on the
+ * inTime.
+ * @return theResult stores the result of the time conversion.
+ */
+long CTimeEditDlg::TimeConversion(long inTime, long inOperationCode)
+{
+ long theResult = 0;
+ switch (inOperationCode) {
+ case CONVERT_MIN_TO_MSEC:
+ theResult = inTime * 60 * 1000;
+ break;
+ case CONVERT_SEC_TO_MSEC:
+ theResult = inTime * 1000;
+ break;
+ case CONVERT_MSEC_TO_MIN:
+ theResult = inTime / (60 * 1000);
+ break;
+ case CONVERT_MSEC_TO_SEC:
+ theResult = inTime / 1000;
+ break;
+ }
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * TimeConversion: Takes in the time in mins:secs:msec and convert it to
+ * the corresponding time in msec.
+ * @param inMin stores the minutes to be converted.
+ * inSec stores the seconds to be converted.
+ * inMsec stores the milliseconds to be converted.
+ * inOperationCode determines the type of time conversion to be done on the
+ * inMin, inSec and inMsec.
+ * @return theResult stores the result of the time conversion.
+ */
+long CTimeEditDlg::TimeConversion(long inMin, long inSec, long inMsec, long inOperationCode)
+{
+ long theResult = 0;
+ switch (inOperationCode) {
+ case CONVERT_TIME_TO_MSEC:
+ theResult = TimeConversion(inMin, CONVERT_MIN_TO_MSEC)
+ + TimeConversion(inSec, CONVERT_SEC_TO_MSEC) + inMsec;
+ break;
+ }
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * TimeConversion: Takes in the time in milliseconds and converts them
+ * to min : sec : msec.
+ * @param inTotalTime stores the total time in msec.
+ * ioMin stores the mins result of the time conversion
+ * ioSec stores the secs result of the time conversion
+ * ioMsec stores the msecs result of the time conversion
+ * inOperationCode determines the type of time conversion to be done on the
+ * inTotalTime.
+ * @return NONE
+ */
+void CTimeEditDlg::TimeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
+ long inOperationCode)
+{
+ switch (inOperationCode) {
+ case CONVERT_MSEC_TO_MIN_SEC_MSEC:
+ *ioMin = TimeConversion(inTotalTime, CONVERT_MSEC_TO_MIN);
+ *ioSec = inTotalTime - TimeConversion(*ioMin, CONVERT_MIN_TO_MSEC);
+ *ioSec = TimeConversion(*ioSec, CONVERT_MSEC_TO_SEC);
+ *ioMsec = inTotalTime - TimeConversion(*ioMin, CONVERT_MIN_TO_MSEC)
+ - TimeConversion(*ioSec, CONVERT_SEC_TO_MSEC);
+ break;
+ }
+}
+//==============================================================================
+/**
+ * UpdateObjectTime: It updates the playhead, keyframe or timebar time according
+ * to the time displayed in the time edit dialogue.
+ * @param inTime is the time that will be updated.
+ * @param startTime if true, updates the start time on the object, otherwise the end time
+ * @return NONE
+ */
+void CTimeEditDlg::UpdateObjectTime(long inTime, bool startTime)
+{
+ long theDiff = 0;
+ switch (m_ObjectAssociation) {
+ case PLAYHEAD: // Update the playhead time
+ if (m_Doc) {
+ m_Doc->NotifyTimeChanged(inTime);
+ m_Doc->NotifyTimeChanged(inTime);
+ }
+ break;
+ case ASSETKEYFRAME: // Update the keyframe time
+ if (m_Doc) {
+ theDiff = inTime - m_OffsetFromInitialTime - m_InitialTime1;
+ m_OffsetFromInitialTime = m_OffsetFromInitialTime + theDiff;
+ if (theDiff != 0 && m_KeyframesManager) {
+ m_KeyframesManager->OffsetSelectedKeyframes(theDiff);
+ }
+ }
+ break;
+ case TIMEBAR: // Update the timebar start/end time
+ if (m_Callback) {
+ if (startTime) // Update Start Time
+ m_Callback->ChangeStartTime(inTime);
+ else // Update End Time
+ m_Callback->ChangeEndTime(inTime);
+ }
+ break;
+ }
+}
+
+//==============================================================================
+/** The codes methods below are provides platform independent wrappers for
+ * User Interface.
+ */
+//==============================================================================
+
+/**
+ * OnEnChangeTimeEdit: Event triggered when the text in the 1st time edit box has
+ * been changed.
+ * @param NONE
+ * @return NONE
+ */
+void CTimeEditDlg::OnEnChangeTimeEdit1()
+{
+ // Making sure that the start time is not greater than the end time, when
+ // the user modifies the start time of the timebar
+ if (m_ObjectAssociation == TIMEBAR) {
+ m_MaxTimeDisplay = m_InitialTime2; // the initial end time
+ }
+ m_MinTimeDisplay = 0;
+
+ const auto time = m_ui->startTimeEdit->time();
+ long min = time.minute() + time.hour() * 60;
+ long sec = time.second();
+ long msec = time.msec();
+ TimeOverflowUnderflow(&min, &sec, &sec, m_MaxTimeDisplay, true);
+ TimeOverflowUnderflow(&min, &sec, &msec, m_MinTimeDisplay, false);
+ if (min != time.minute() || sec != time.second() ||
+ msec != time.msec()) {
+ m_ui->startTimeEdit->setTime(QTime(0, min, sec, msec));
+ }
+ m_ui->startTimeMin->setText(QString::number(min));
+ m_ui->startTimeSec->setText(QString::number(sec));
+ m_ui->startTimeMsec->setText(QString::number(msec));
+
+ long theGoToTime = TimeConversion(min, CONVERT_MIN_TO_MSEC)
+ + TimeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ // Go to the time specified in the time edit display
+ UpdateObjectTime(theGoToTime, true /*start time*/);
+}
+
+//==============================================================================
+/**
+ * OnEnChangeTimeEdit2: Event triggered when the text in the 2nd time edit box has
+ * been changed.
+ * @param NONE
+ * @return NONE
+ */
+void CTimeEditDlg::OnEnChangeTimeEdit2()
+{
+ // Let the end time of the time bar go as far as possible
+ if (m_ObjectAssociation == TIMEBAR) {
+ m_MaxTimeDisplay = m_MaxTime;
+ m_MinTimeDisplay = m_InitialTime1; // the initial start time
+ }
+ const auto time = m_ui->endTimeEdit->time();
+ long min = time.minute() + time.hour() * 60;
+ long sec = time.second();
+ long msec = time.msec();
+ TimeOverflowUnderflow(&min, &sec, &sec, m_MaxTimeDisplay, true);
+ TimeOverflowUnderflow(&min, &sec, &msec, m_MinTimeDisplay, false);
+ if (min != time.minute() || sec != time.second() ||
+ msec != time.msec()) {
+ m_ui->endTimeEdit->setTime(QTime(0, min, sec, msec));
+ }
+ m_ui->endTimeMin->setText(QString::number(min));
+ m_ui->endTimeSec->setText(QString::number(sec));
+ m_ui->endTimeMsec->setText(QString::number(msec));
+
+ long theGoToTime = TimeConversion(min, CONVERT_MIN_TO_MSEC)
+ + TimeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ // Go to the time specified in the time edit display
+ UpdateObjectTime(theGoToTime, false /*end time*/);
+}
+
+
+//==============================================================================
+/**
+ * HideUnnecessaryFields: Hides unused dialog items
+ * @param NONE
+ * @return NONE
+ */
+void CTimeEditDlg::HideUnnecessaryFields()
+{
+ m_ui->endTimeGroup->hide();
+ m_ui->startTimeLabel->hide();
+}
+
diff --git a/src/Authoring/Studio/_Win/UI/TimeEditDlg.h b/src/Authoring/Studio/_Win/UI/TimeEditDlg.h
new file mode 100644
index 00000000..7103dd3e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/TimeEditDlg.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TIME_EDIT_DIALOG_H
+#define INCLUDED_TIME_EDIT_DIALOG_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Dialogs.h"
+#include <QDialog>
+#include <QDateTimeEdit>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTimebarControl;
+class IDoc;
+class ITimelineKeyframesManager;
+
+//==============================================================================
+// Defines
+//==============================================================================
+
+enum ECursorPosition { MIN_POSITION, SEC_POSITION, MSEC_POSITION };
+
+enum ETimeFormat { MSEC, SEC_MSEC, MIN_SEC_MSEC };
+
+enum ETimeConversionOperation {
+ CONVERT_MIN_TO_MSEC,
+ CONVERT_SEC_TO_MSEC,
+ CONVERT_MSEC_TO_MIN,
+ CONVERT_MSEC_TO_SEC,
+ CONVERT_TIME_TO_MSEC,
+ CONVERT_MSEC_TO_MIN_SEC_MSEC
+};
+
+enum ETimeEditBoxNumber { EDITBOX1, EDITBOX2 };
+
+enum EObjectAssociation {
+ PLAYHEAD,
+ ASSETKEYFRAME,
+ TIMEBAR,
+};
+
+class ITimeChangeCallback
+{
+public:
+ virtual ~ITimeChangeCallback() {}
+ virtual void ChangeStartTime(long) = 0;
+ virtual void ChangeEndTime(long) = 0;
+ virtual void Commit() = 0;
+ virtual void Rollback() = 0;
+};
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class TimeEditDlg;
+}
+QT_END_NAMESPACE
+
+// This class workaround the problem of QDateTimeEdit overwriting the selected section
+// See https://bugreports.qt.io/browse/QTBUG-34759
+class CDateTimeEdit : public QDateTimeEdit
+{
+ Q_OBJECT
+public:
+ using QDateTimeEdit::QDateTimeEdit;
+
+protected:
+ void focusInEvent(QFocusEvent *event) {
+ QDateTimeEdit::focusInEvent(event);
+ setSelectedSection(QDateTimeEdit::SecondSection);
+ }
+};
+
+//==============================================================================
+/**
+ * CTimeEditDlg: It is a dialog box that allows user to specify the time that
+ * he/she wishes to go to. This dialog box can be activated by
+ * pressing Control G or clicking on the time edit box in the
+ * timeline.
+ */
+//==============================================================================
+class CTimeEditDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CTimeEditDlg(QWidget *pParent = nullptr); // standard constructor
+ virtual ~CTimeEditDlg();
+ void SetKeyframesManager(ITimelineKeyframesManager *inKeyframeManager);
+ void ShowDialog(long inTime1, long inTime2, IDoc *inDoc, long inObjectAssociation,
+ ITimeChangeCallback *inCallback = nullptr);
+
+public Q_SLOTS:
+ void accept() override;
+ void reject() override;
+
+protected:
+ void showEvent(QShowEvent *) override;
+
+ // Generated message map functions
+ void OnInitDialog();
+ void OnEnChangeTimeEdit1();
+ void OnEnChangeTimeEdit2();
+
+ QString FormatTime(long inTime);
+ long CountDigits(long inNumber);
+ long TimeConversion(long inTime, long inOperationCode);
+ long TimeConversion(long inMin, long inSec, long inMsec, long inOperationCode);
+ void TimeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
+ long inOperationCode);
+ void UpdateObjectTime(long inTime, bool startTime);
+ bool TimeOverflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit);
+ bool TimeOverflowUnderflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit,
+ bool inOverflowOrUnderflow);
+ void HideUnnecessaryFields();
+
+protected:
+ QString m_MinString;
+ QString m_SecString;
+ QString m_MSecString;
+ QString m_TimeDisplay1;
+ QString m_TimeDisplay2;
+ long m_MaxTime;
+ long m_MaxTimeDisplay;
+ long m_MinTimeDisplay;
+ long m_InitialTime1;
+ long m_InitialTime2;
+ long m_MinOffset;
+ long m_SecOffset;
+ long m_MSecOffset;
+ long m_MinMinorOffset;
+ long m_SecMinorOffset;
+ long m_MSecMinorOffset;
+ long m_CursorPosition;
+ long m_TimeFormat;
+ long m_PreviousFormat;
+ double m_TimeInMins;
+ long m_NumberOfDigitsDrop;
+ long m_ColonPosition1;
+ long m_ColonPosition2;
+ long m_ObjectAssociation;
+ long m_OffsetFromInitialTime;
+ QString m_DTime;
+ QString m_DTimeDisplay;
+ long m_Time1;
+ long m_Time2;
+ IDoc *m_Doc;
+ ITimelineKeyframesManager *m_KeyframesManager;
+
+ ITimeChangeCallback *m_Callback;
+ Ui::TimeEditDlg *m_ui;
+};
+#endif // INCLUDED_TIME_EDIT_DIALOG_H
diff --git a/src/Authoring/Studio/_Win/UI/timeeditdlg.ui b/src/Authoring/Studio/_Win/UI/timeeditdlg.ui
new file mode 100644
index 00000000..f46cb1a2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/timeeditdlg.ui
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TimeEditDlg</class>
+ <widget class="QDialog" name="TimeEditDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>371</width>
+ <height>274</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Go To Time</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="startTimeGroup" native="true">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="CDateTimeEdit" name="startTimeEdit">
+ <property name="currentSection">
+ <enum>QDateTimeEdit::SecondSection</enum>
+ </property>
+ <property name="displayFormat">
+ <string>hh:mm:ss:zzz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="startTimeMin">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>sec</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="startTimeSec">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>min</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QLabel" name="startTimeMsec">
+ <property name="text">
+ <string>000</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="startTimeLabel">
+ <property name="text">
+ <string>Start Time</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="endTimeGroup" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="endTimeLabel">
+ <property name="text">
+ <string>End Time</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="CDateTimeEdit" name="endTimeEdit">
+ <property name="currentSection">
+ <enum>QDateTimeEdit::SecondSection</enum>
+ </property>
+ <property name="displayFormat">
+ <string>hh:mm:ss:zzz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="endTimeMin">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>sec</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="endTimeSec">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>min</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QLabel" name="endTimeMsec">
+ <property name="text">
+ <string>000</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CDateTimeEdit</class>
+ <extends>QTimeEdit</extends>
+ <header>TimeEditDlg.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>TimeEditDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>TimeEditDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp b/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp
new file mode 100644
index 00000000..9cd7328d
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// WIN32 VERSION
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "MouseCursor.h"
+#include <QPixmap>
+#include <QDebug>
+
+//#ifdef WIN32
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ARROW = 0; // IDC_ARROW
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_WAIT = 1; // IDC_WAIT
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_RESIZE_LEFTRIGHT = 2; // IDC_SIZEWE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_RESIZE_UPDOWN = 3; // IDC_SIZENS
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_MOVE = 4; // IDC_GROUP_MOVE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_ROTATE = 5; // IDC_GROUP_ROTATE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_SCALE = 6; // IDC_GROUP_SCALE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_MOVE = 7; // IDC_ITEM_MOVE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_ROTATE = 8; // IDC_ITEM_ROTATE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_SCALE = 9; // IDC_ITEM_SCALE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_PAN =
+ 10; // IDC_EDIT_CAMERA_PAN
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_ROTATE =
+ 11; // IDC_EDIT_CAMERA_ROTATE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM =
+ 12; // IDC_EDIT_CAMERA_ZOOM
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_BLANK = 13; // blank cursor
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_IBEAM = 14;
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CMouseCursor::CMouseCursor()
+ : m_IsThemeCursor(false)
+ , m_ThemeCursor(-1)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CMouseCursor::~CMouseCursor()
+{
+ Destroy();
+}
+
+//=============================================================================
+/**
+ * @return A platform-specific handle to the cursor, or nullptr if no cursor has been loaded
+ */
+QCursor CMouseCursor::GetHandle()
+{
+ return m_Handle;
+}
+
+//=============================================================================
+/**
+ * If a cursor has been loaded, this function will change the current cursor
+ * to the newly loaded one.
+ */
+void CMouseCursor::Show()
+{
+ qWarning() << Q_FUNC_INFO << "QCursor doesn't work this way - set a breakpoint and debug caller";
+}
+
+//=============================================================================
+/**
+* Sets the cursor position
+* @param inXPos x position of the cursor (in pixels)
+* @param inYPos y position of the cursor (in pixels)
+*/
+void CMouseCursor::SetCursorPos(long inXPos, long inYPos)
+{
+ QCursor::setPos(QPoint(inXPos, inYPos));
+}
+
+//=============================================================================
+/**
+ * Releases the cursor if one has been loaded. Called by the destructor.
+ * WINDOWS IMPLEMENTATION
+ */
+void CMouseCursor::Destroy()
+{
+}
+
+//=============================================================================
+/**
+ * Loads the specified cursor resource. All cursors are expected to be
+ * resources that are loaded from ".cur" files. Some standard cursors are
+ * defined by the system and can be found in the MSDN (IDC_ARROW for example).
+ * WINDOWS IMPLEMENTATION
+ *
+ * @param inCursor ID of the cursor to be loaded
+ * @return true if the cursor was successfully loaded, otherwise false
+ */
+bool CMouseCursor::Load(TUICMouseCursor inCursor)
+{
+ // Convert from our cursors to Windows specific cursors
+ switch (inCursor) {
+ case CURSOR_ARROW:
+ m_Handle = Qt::ArrowCursor;
+ break;
+
+ case CURSOR_WAIT:
+ m_Handle = Qt::WaitCursor;
+ break;
+
+ case CURSOR_RESIZE_LEFTRIGHT:
+ m_Handle = Qt::SizeHorCursor;
+ break;
+
+ case CURSOR_RESIZE_UPDOWN:
+ m_Handle = Qt::SizeVerCursor;
+ break;
+
+ case CURSOR_GROUP_MOVE:
+ m_Handle = QCursor(QPixmap(":/cursors/group_move.png"), 0, 0);
+ break;
+
+ case CURSOR_GROUP_ROTATE:
+ m_Handle = QCursor(QPixmap(":/cursors/group_rotate.png"), 0, 0);
+ break;
+
+ case CURSOR_GROUP_SCALE:
+ m_Handle = QCursor(QPixmap(":/cursors/group_scale.png"), 0, 0);
+ break;
+
+ case CURSOR_ITEM_MOVE:
+ m_Handle = QCursor(QPixmap(":/cursors/item_move.png"), 0, 0);
+ break;
+
+ case CURSOR_ITEM_ROTATE:
+ m_Handle = QCursor(QPixmap(":/cursors/item_rotate.png"), 0, 0);
+ break;
+
+ case CURSOR_ITEM_SCALE:
+ m_Handle = QCursor(QPixmap(":/cursors/item_scale.png"), 0, 0);
+ break;
+
+ case CURSOR_EDIT_CAMERA_PAN:
+ m_Handle = QCursor(QPixmap(":/cursors/edit_camera_pan.png"), 10, 10);
+ break;
+
+ case CURSOR_EDIT_CAMERA_ROTATE:
+ m_Handle = QCursor(QPixmap(":/cursors/edit_camera_rot.png"), 8, 10);
+ break;
+
+ case CURSOR_EDIT_CAMERA_ZOOM:
+ m_Handle = QCursor(QPixmap(":/cursors/edit_camera_zoom.png"), 8, 8);
+ break;
+
+ case CURSOR_BLANK:
+ m_Handle = Qt::BlankCursor;
+ break;
+ case CURSOR_IBEAM:
+ m_Handle = Qt::IBeamCursor;
+ break;
+ default:
+ m_Handle = QCursor();
+ break;
+ }
+ return true;
+}
diff --git a/src/Authoring/Studio/_Win/Utils/WinUtils.cpp b/src/Authoring/Studio/_Win/Utils/WinUtils.cpp
new file mode 100644
index 00000000..e159fa12
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Utils/WinUtils.cpp
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "Strings.h"
+
+#include "WinUtils.h"
+
+//==============================================================================
+/**
+ * DrawBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle.
+ *
+ * @param inDC Device context for drawing
+ * @param inPos CPoint position for drawing
+ * @param inBitmap Handle of the bitmap to draw
+ */
+//==============================================================================
+void CWinUtils::DrawBitmap(CDC *inDC, CPoint inPos, HBITMAP inBitmap)
+{
+ CDC theMemDC;
+ BITMAP theBitmapStruct;
+ CBitmap *theOldBitmap;
+
+ if ((inDC != nullptr) && (inBitmap != nullptr)) {
+ GetObject(inBitmap, sizeof(BITMAP), &theBitmapStruct);
+
+ theMemDC.CreateCompatibleDC(inDC);
+ theOldBitmap = theMemDC.SelectObject(CBitmap::FromHandle(inBitmap));
+
+ inDC->BitBlt(inPos.x, inPos.y, theBitmapStruct.bmWidth, theBitmapStruct.bmHeight, &theMemDC,
+ 0, 0, SRCCOPY);
+
+ theMemDC.SelectObject(theOldBitmap);
+ theMemDC.DeleteDC();
+ }
+}
+
+//==============================================================================
+/**
+ * DrawTransparentBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle using transparency
+ *
+ * @param inDC Device context for drawing
+ * @param inDestX Destination X position
+ * @param inDestY Destination Y position
+ * @param inBmp Bitmap for drawing
+ * @param inColorTransparent Transparent color
+ * @param inWidth Destination width
+ * @param inHeight Destination height
+ * @param inSourceX Source X position
+ * @param inSourceY Source Y position
+ */
+//==============================================================================
+void CWinUtils::DrawTransparentBitmap(CDC *inDC, long inDestX, long inDestY, HBITMAP inBmp,
+ COLORREF inColorTransparent, long inWidth, long inHeight,
+ long inSourceX, long inSourceY)
+{
+ CDC theMemDC;
+ BITMAP theBitmap;
+ CBitmap *theOldBmp;
+
+ GetObject(inBmp, sizeof(BITMAP), &theBitmap);
+
+ if (inWidth == -1)
+ inWidth = theBitmap.bmWidth;
+ if (inHeight == -1)
+ inHeight = theBitmap.bmHeight;
+
+ theMemDC.CreateCompatibleDC(inDC);
+ theOldBmp = theMemDC.SelectObject(CBitmap::FromHandle(inBmp));
+
+ TransparentBltExt(inDC->m_hDC, inDestX, inDestY, inWidth, inHeight, theMemDC.m_hDC, inSourceX,
+ inSourceY, inWidth, inHeight, inColorTransparent);
+
+ theMemDC.SelectObject(theOldBmp);
+ theMemDC.DeleteDC();
+}
+
+//==============================================================================
+/**
+ * TransparentBltExt
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle using transparency
+ *
+ * @param inDC Device context for drawing
+ * @param inDestX Destination X position
+ * @param inDestY Destination Y position
+ * @param inBmp Bitmap for drawing
+ * @param inColorTransparent Transparent color
+ * @param inWidth Destination width
+ * @param inHeight Destination height
+ * @param inSourceX Source X position
+ * @param inSourceY Source Y position
+ */
+//==============================================================================
+BOOL CWinUtils::TransparentBltExt(HDC inDCDest, long inXOriginDest, long inYOriginDest,
+ long inWidthDest, long inHeightDest, HDC inDCSrc,
+ long inXOriginSrc, long inYOriginSrc, long inWidthSrc,
+ long inHeightSrc, UINT inColorTransparent)
+{
+ if ((inWidthDest < 1) || (inWidthSrc < 1) || (inHeightDest < 1) || (inHeightSrc < 1))
+ return FALSE;
+
+ HDC theDC, theMaskDC;
+ HDC theNewMaskDC;
+ HBITMAP theBmp, theOldBmp, theMaskBmp, theOldMask;
+ HBITMAP theNewMask;
+
+ theDC = CreateCompatibleDC(nullptr);
+ theBmp = CreateBitmap(inWidthSrc, inHeightSrc, 1, GetDeviceCaps(theDC, BITSPIXEL), nullptr);
+
+ if (theBmp == nullptr) {
+ DeleteDC(theDC);
+ return FALSE;
+ }
+
+ theOldBmp = (HBITMAP)SelectObject(theDC, theBmp);
+
+ if (!BitBlt(theDC, 0, 0, inWidthSrc, inHeightSrc, inDCSrc, inXOriginSrc, inYOriginSrc,
+ SRCCOPY)) {
+ SelectObject(theDC, theOldBmp);
+ DeleteObject(theBmp);
+ DeleteDC(theDC);
+ return FALSE;
+ }
+
+ theMaskDC = CreateCompatibleDC(nullptr);
+ theMaskBmp = CreateBitmap(inWidthSrc, inHeightSrc, 1, 1, nullptr);
+
+ if (theMaskBmp == nullptr) {
+ SelectObject(theDC, theOldBmp);
+ DeleteObject(theBmp);
+ DeleteDC(theDC);
+ DeleteDC(theMaskDC);
+ return FALSE;
+ }
+
+ theOldMask = (HBITMAP)SelectObject(theMaskDC, theMaskBmp);
+ SetBkColor(theMaskDC, RGB(0x00, 0x00, 0x00));
+ SetTextColor(theMaskDC, RGB(0xFF, 0xFF, 0xFF));
+
+ if (!BitBlt(theMaskDC, 0, 0, inWidthSrc, inHeightSrc, nullptr, 0, 0, BLACKNESS)) {
+ SelectObject(theMaskDC, theOldMask);
+ DeleteObject(theMaskBmp);
+ DeleteDC(theMaskDC);
+ SelectObject(theDC, theOldBmp);
+ DeleteObject(theBmp);
+ DeleteDC(theDC);
+ return FALSE;
+ }
+
+ SetBkColor(theDC, inColorTransparent);
+ BitBlt(theMaskDC, 0, 0, inWidthSrc, inHeightSrc, theDC, 0, 0, SRCINVERT);
+
+ SetBkColor(theDC, RGB(0x00, 0x00, 0x00));
+ SetTextColor(theDC, RGB(0xFF, 0xFF, 0xFF));
+ BitBlt(theDC, 0, 0, inWidthSrc, inHeightSrc, theMaskDC, 0, 0, SRCAND);
+
+ theNewMaskDC = CreateCompatibleDC(nullptr);
+ theNewMask =
+ CreateBitmap(inWidthDest, inHeightDest, 1, GetDeviceCaps(theNewMaskDC, BITSPIXEL), nullptr);
+ if (theNewMask == nullptr) {
+ SelectObject(theDC, theOldBmp);
+ DeleteDC(theDC);
+ SelectObject(theMaskDC, theOldMask);
+ DeleteDC(theMaskDC);
+ DeleteDC(theNewMaskDC);
+ DeleteObject(theBmp);
+ DeleteObject(theMaskBmp);
+ return FALSE;
+ }
+
+ SetStretchBltMode(theNewMaskDC, COLORONCOLOR);
+ HBITMAP theOldNewMask = (HBITMAP)SelectObject(theNewMaskDC, theNewMask);
+ StretchBlt(theNewMaskDC, 0, 0, inWidthDest, inHeightDest, theMaskDC, 0, 0, inWidthSrc,
+ inHeightSrc, SRCCOPY);
+
+ SelectObject(theMaskDC, theOldMask);
+ DeleteDC(theMaskDC);
+ DeleteObject(theMaskBmp);
+
+ HDC theNewImageDC = CreateCompatibleDC(nullptr);
+ HBITMAP theNewImage =
+ CreateBitmap(inWidthDest, inHeightDest, 1, GetDeviceCaps(theNewMaskDC, BITSPIXEL), nullptr);
+ if (theNewImage == nullptr) {
+ SelectObject(theDC, theOldBmp);
+ DeleteDC(theDC);
+ DeleteDC(theNewMaskDC);
+ DeleteObject(theBmp);
+ return FALSE;
+ }
+
+ HBITMAP theOldNewImage = (HBITMAP)SelectObject(theNewImageDC, theNewImage);
+ StretchBlt(theNewImageDC, 0, 0, inWidthDest, inHeightDest, theDC, 0, 0, inWidthSrc, inHeightSrc,
+ SRCCOPY);
+
+ SelectObject(theDC, theOldBmp);
+ DeleteDC(theDC);
+ DeleteObject(theBmp);
+
+ // Finally, do the final blitting to get the image to the destination device context.
+ BitBlt(inDCDest, inXOriginDest, inYOriginDest, inWidthDest, inHeightDest, theNewMaskDC, 0, 0,
+ SRCAND);
+ BitBlt(inDCDest, inXOriginDest, inYOriginDest, inWidthDest, inHeightDest, theNewImageDC, 0, 0,
+ SRCPAINT);
+
+ SelectObject(theNewImageDC, theOldNewImage);
+ DeleteDC(theNewImageDC);
+ SelectObject(theNewMaskDC, theOldNewMask);
+ DeleteDC(theNewMaskDC);
+ DeleteObject(theNewImage);
+ DeleteObject(theNewMask);
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * DrawAlphaBlendBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle using
+ * alpha blending and transparency.
+ *
+ * @param inDC Device context for drawing
+ * @param inDestX Destination X position
+ * @param inDestY Destination Y position
+ * @param inBmp Bitmap for drawing
+ * @param inColorTransparent Transparent color
+ * @param inWidth Destination width
+ * @param inHeight Destination height
+ * @param inSourceX Source X position
+ * @param inSourceY Source Y position
+ */
+//==============================================================================
+void CWinUtils::DrawAlphaBlendBitmap(CDC *inDC, short inDestX, short inDestY, HBITMAP inBmp,
+ short inWidth, short inHeight, short inSourceX,
+ short inSourceY, short inAlpha, BOOL inTransparentFlag,
+ COLORREF inColorTransparent)
+{
+ Q_UNUSED(inColorTransparent);
+
+ CDC theMemDC;
+ BITMAP theBitmap;
+ CBitmap *theOldBmp;
+ short theWidth = inWidth;
+ short theHeight = inHeight;
+
+ COLORREF theBackColor;
+
+ // Get the size of the bitmap.
+ GetObject(inBmp, sizeof(BITMAP), &theBitmap);
+
+ if (inWidth == -1)
+ theWidth = (short)theBitmap.bmWidth;
+ if (inHeight == -1)
+ theHeight = (short)theBitmap.bmHeight;
+
+ theMemDC.CreateCompatibleDC(inDC);
+ theOldBmp = theMemDC.SelectObject(CBitmap::FromHandle(inBmp));
+
+ if (inTransparentFlag) {
+ // Get the current background pixel at 0,0
+ theBackColor = theMemDC.GetPixel(0, 0);
+
+ // Create a fill brush and select into the device context
+ CBrush theFillBrush(inColorTransparent);
+ CBrush *theOldFillBrush;
+
+ // Fill to replace the existing background color with the replacement color.
+ theOldFillBrush = theMemDC.SelectObject(&theFillBrush);
+ theMemDC.ExtFloodFill(0, 0, theBackColor, FLOODFILLSURFACE);
+ theMemDC.ExtFloodFill(theWidth - 1, 0, theBackColor, FLOODFILLSURFACE);
+ theMemDC.ExtFloodFill(theWidth - 1, theHeight - 1, theBackColor, FLOODFILLSURFACE);
+ theMemDC.ExtFloodFill(0, theHeight - 1, theBackColor, FLOODFILLSURFACE);
+ theMemDC.SelectObject(theOldFillBrush);
+ }
+
+ // Draw the alpha-blended image.
+ AlphaBlendExt(inDC->m_hDC, inDestX, inDestY, theWidth, theHeight, theMemDC.m_hDC, inSourceX,
+ inSourceY, theWidth, theHeight, inAlpha);
+
+ theMemDC.SelectObject(theOldBmp);
+ theMemDC.DeleteDC();
+}
+
+//==============================================================================
+/**
+ * AlphaBlendExt
+ *
+ * Draws a bitmap using alpha blending. Works in NT/2000/9x
+ *
+ * @param inDCDest Destination device context
+ * @param inX X coordinate for drawing
+ * @param inY Y coordinate for drawing
+ * @param inWidth Drawing width
+ * @param inHeight Drawing height
+ * @param inDCSrc Source device context
+ * @param inSourceX X source coordinate
+ * @param inSourceY Y source coordinate
+ * @param inSourceWidth Source drawing width
+ * @param inSourceHeight Source drawing height
+ * @param inAlpha Alpha blend: 0-255, where 255 is opaque
+ */
+//==============================================================================
+BOOL CWinUtils::AlphaBlendExt(HDC inDCDest, short inX, short inY, short inWidth, short inHeight,
+ HDC inDCSrc, short inSourceX, short inSourceY, short inSourceWidth,
+ short inSourceHeight, short inAlpha)
+{
+ BITMAPINFOHEADER theBMI;
+
+ theBMI.biSize = sizeof(BITMAPINFOHEADER);
+ theBMI.biWidth = inWidth;
+ theBMI.biHeight = inHeight;
+ theBMI.biPlanes = 1;
+ theBMI.biBitCount = 32; // 24 bits + alpha channel
+ theBMI.biCompression = BI_RGB; // no compression
+ theBMI.biSizeImage = 0;
+ theBMI.biXPelsPerMeter = 0;
+ theBMI.biYPelsPerMeter = 0;
+ theBMI.biClrUsed = 0; // use the whole palette
+ theBMI.biClrImportant = 0;
+
+ BYTE *theSrcBits;
+ HBITMAP theBmpSrc;
+
+ // Create DIB section in shared memory
+ theBmpSrc = CreateDIBSection(inDCSrc, (BITMAPINFO *)&theBMI, DIB_RGB_COLORS,
+ (void **)&theSrcBits, 0, 0L);
+
+ BYTE *theDestBits;
+ HBITMAP theBmpDest;
+
+ // Create DIB section in shared memory
+ theBmpDest = CreateDIBSection(inDCDest, (BITMAPINFO *)&theBMI, DIB_RGB_COLORS,
+ (void **)&theDestBits, 0, 0L);
+
+ // Copy our source and destination bitmaps onto our DIBSections.
+ // so we can get access to their bits using the BYTE*'s we used
+ // in the CreateDIBSection()s above.
+
+ HDC theDC = CreateCompatibleDC(nullptr);
+ HBITMAP theDCOld = (HBITMAP)SelectObject(theDC, theBmpSrc);
+
+ if (!StretchBlt(theDC, 0, 0, inWidth, inHeight, inDCSrc, inSourceX, inSourceY, inSourceWidth,
+ inSourceHeight, SRCCOPY)) {
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+ return FALSE;
+ }
+
+ SelectObject(theDC, theBmpDest);
+
+ if (!StretchBlt(theDC, 0, 0, inWidth, inHeight, inDCDest, inX, inY, inWidth, inHeight,
+ SRCCOPY)) {
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+ return FALSE;
+ }
+
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+
+ short theXLoop, theYLoop;
+
+ for (theYLoop = 0; theYLoop < inHeight; ++theYLoop) {
+ LPBYTE theDestRGB = (LPBYTE) & ((DWORD *)theDestBits)[theYLoop * inWidth];
+ LPBYTE theSrcRGB = (LPBYTE) & ((DWORD *)theSrcBits)[theYLoop * inWidth];
+
+ for (theXLoop = 0; theXLoop < inWidth; theXLoop++) {
+ theSrcRGB[0] = (BYTE)((theDestRGB[0] * (255 - inAlpha) + theSrcRGB[0] * inAlpha) >> 8);
+ theSrcRGB[1] = (BYTE)((theDestRGB[1] * (255 - inAlpha) + theSrcRGB[1] * inAlpha) >> 8);
+ theSrcRGB[2] = (BYTE)((theDestRGB[2] * (255 - inAlpha) + theSrcRGB[2] * inAlpha) >> 8);
+
+ theSrcRGB += 4;
+ theDestRGB += 4;
+ }
+ }
+
+ theDC = CreateCompatibleDC(nullptr);
+
+ theDCOld = (HBITMAP)SelectObject(theDC, theBmpSrc);
+
+ if (!BitBlt(inDCDest, inX, inY, inWidth, inHeight, theDC, 0, 0, SRCCOPY)) {
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+ return FALSE;
+ }
+
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * GetStudioLogFont: Fill a LOGFONT structure with the default font information for Studio
+ *objects.
+ *
+ * Create a LOGFONT structure with data used by the various palettes and controls in Studio.
+ *
+ * @param outLogFont LOGFONT structure returned by this function.
+ */
+//==============================================================================
+void CWinUtils::GetStudioLogFont(LOGFONT &outLogFont)
+{
+ // Create the default Studio font - specified in string table so that it can be changed for
+ // different languages
+ memset(&outLogFont, 0, sizeof(LOGFONT));
+ CString theFontSize = ::LoadResourceString(IDS_STUDIOFONT_SIZE);
+ CString theFontFace = L"SegoeUI";
+ outLogFont.lfHeight = _wtoi(theFontSize);
+ wcscpy(outLogFont.lfFaceName, theFontFace);
+ // Make sure that you set the character set to the system default or your strings won't be
+ // localizable
+ outLogFont.lfCharSet = DEFAULT_CHARSET;
+}
+
+//=============================================================================
+/**
+ * Copy the contents of a File into an Archive.
+ * This will read the entire file into the archive.
+ * The file should exist already.
+ * @param inFilename the name of the file to read in.
+ * @param inDestination the destination archive for the data.
+ */
+//=============================================================================
+void CWinUtils::CopyFileToArchive(CString inFilename, CArchive &inDestination)
+{
+ CFile theFile(inFilename, CFile::modeRead);
+
+ unsigned long theLength = (unsigned long)theFile.GetLength();
+ unsigned long theBufferSize = 1024;
+ while (theBufferSize < theLength / 10 && theBufferSize < 1e6)
+ theBufferSize *= 2; // double until we have a buffer that is about %10 of file size
+ char *theBuffer = new char[theBufferSize];
+
+ unsigned long theReadCount = theBufferSize;
+ unsigned long theTotalReadCount = 0;
+
+ // Loop around reading the file in chunks
+ while (theTotalReadCount < theLength) {
+ if (theLength - theTotalReadCount < theReadCount)
+ theReadCount = theLength - theTotalReadCount;
+
+ theFile.Read(theBuffer, theReadCount);
+ inDestination.Write(theBuffer, theReadCount);
+
+ theTotalReadCount += theReadCount;
+ }
+
+ theFile.Close();
+ delete[] theBuffer;
+}
+
+//=============================================================================
+/**
+ * Copy the contents of an Archive into a File.
+ * If the file does not exist it will be created. If it does exist it will be
+ * cleared.
+ * @param inArchive the source of the data for the file.
+ * @param inDestination the file the data is to be written to.
+ * @param inLength the amount of data to copy to the file.
+ */
+//=============================================================================
+void CWinUtils::CopyArchiveToFile(CArchive &inArchive, CString inDestination,
+ unsigned long inLength)
+{
+ CFile theFile(inDestination, CFile::modeWrite | CFile::modeCreate);
+
+ unsigned long theBufferSize = 1024;
+ while (theBufferSize < inLength / 10 && theBufferSize < 1e6)
+ theBufferSize *= 2; // double until we have a buffer that is about %10 of file size
+ char *theBuffer = new char[theBufferSize];
+
+ unsigned long theLength = inLength;
+ unsigned long theReadCount = theBufferSize;
+ unsigned long theTotalReadCount = 0;
+
+ // Loop around reading from the archive and writing to the file.
+ while (theTotalReadCount < theLength) {
+ if (theLength - theTotalReadCount < theReadCount)
+ theReadCount = theLength - theTotalReadCount;
+
+ inArchive.Read(theBuffer, theReadCount);
+ theFile.Write(theBuffer, theReadCount);
+
+ theTotalReadCount += theReadCount;
+ }
+ theFile.Close();
+ delete[] theBuffer;
+}
+
+//=============================================================================
+/**
+ * Used for StringToInt64 to avoid double errors in math.h's pow( ).
+ *
+ * @param inNumber Base number
+ * @param inPower Power to raise the base
+ *
+ * @return Result of x^y
+ */
+//=============================================================================
+unsigned __int64 CWinUtils::RaisePower(unsigned __int64 inNumber, unsigned long inPower)
+{
+ if (inPower == 0)
+ return 1;
+ return inNumber * RaisePower(inNumber, inPower - 1);
+}
+
+//=============================================================================
+/**
+ * Parse the string into an __int64.
+ *
+ * @param inString the string to parse.
+ * @param inStringLen the length of the string.
+ * @param inBase the base of the character encoding (16 is Hex, 10 is decimal).
+ *
+ * @return <the parsed string.
+ */
+//=============================================================================
+unsigned __int64 CWinUtils::StringToInt64(const char *inString, unsigned short inStringLen,
+ unsigned short inBase)
+{
+ unsigned __int64 theKey = 0;
+ char theChar;
+ unsigned short i;
+
+ for (i = 0; i < inStringLen; ++i) {
+ theChar = inString[i];
+ if (theChar < 'A')
+ theChar -= '0';
+ else if (theChar < 'a')
+ theChar -= 'A' - 10;
+ else
+ theChar -= 'a' - 10;
+
+ theKey +=
+ ((unsigned __int64)theChar) * (unsigned __int64)RaisePower(inBase, inStringLen - 1 - i);
+ }
+ return theKey;
+}
+
+//=============================================================================
+/**
+ * Get a wchar_t from an MFC CString (used to go to Q3DStudio::CString without flattening unicode)
+ *
+ * @param inMFCString the string convert
+ *
+ * @return <the null-terminated wchar_t buffer. caller must delete[]!!!!
+ */
+//=============================================================================
+wchar_t *CWinUtils::WideFromMFC(::CString inMFCString)
+{
+ TCHAR *theBuffer = inMFCString.GetBuffer(0);
+ long theMultiLength = inMFCString.GetLength();
+ wchar_t *theDestBuffer = new wchar_t[theMultiLength * 2 + 1]; // times 2 so we know we are big
+ // enough for 1 and 2 byte chars
+ // from multibyte
+ wcscpy(theDestBuffer, theBuffer);
+ inMFCString.ReleaseBuffer();
+ return theDestBuffer;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Utils/WinUtils.h b/src/Authoring/Studio/_Win/Utils/WinUtils.h
new file mode 100644
index 00000000..121a61bd
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Utils/WinUtils.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_WIN_UTILS_H
+#define INCLUDED_WIN_UTILS_H 1
+
+#pragma once
+
+class CWinUtils
+{
+public:
+ static BOOL AlphaBlendExt(HDC hDCDest, short x, short y, short cx, short cy, HDC hDCSrc,
+ short sx, short sy, short sw, short sh, short inAlpha);
+ static void DrawAlphaBlendBitmap(CDC *inDC, short inDestX, short inDestY, HBITMAP inBmp,
+ short inWidth, short inHeight, short inSourceX,
+ short inSourceY, short inAlpha, BOOL inTransparentFlag = FALSE,
+ COLORREF inColorTransparent = RGB(0x00, 0x00, 0x00));
+ static void DrawBitmap(CDC *inDC, CPoint inPos, HBITMAP inBitmap);
+ static void DrawTransparentBitmap(CDC *pDC, long x, long y, HBITMAP hBmp,
+ COLORREF colorTransparent, long w = -1, long h = -1,
+ long sx = 0, long sy = 0);
+ static BOOL TransparentBltExt(HDC inDCDest, long inXOriginDest, long inYOriginDest,
+ long inWidthDest, long inHeightDest, HDC inDCSrc,
+ long inXOriginSrc, long inYOriginSrc, long inWidthSrc,
+ long inHeightSrc, UINT inColorTransparent);
+
+ static void GetStudioLogFont(LOGFONT &outLogFont);
+ static unsigned __int64 StringToInt64(const char *inString, unsigned short inStringLen,
+ unsigned short inBase);
+ static void CopyFileToArchive(CString inFilename, CArchive &inDestination);
+ static void CopyArchiveToFile(CArchive &inArchive, CString inDestination,
+ unsigned long inLength);
+ static wchar_t *WideFromMFC(::CString inMFCString);
+
+protected:
+ static unsigned __int64 RaisePower(unsigned __int64 inNumber, unsigned long inPower);
+};
+
+#endif // INCLUDED_WIN_UTILS_H
diff --git a/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp b/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp
new file mode 100644
index 00000000..517aed97
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp
@@ -0,0 +1,1332 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+#include "Dialogs.h"
+#include "StudioApp.h"
+#include "Doc.h"
+
+#include "InterpolationDlg.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "UICMessageBox.h"
+#include "StringTokenizer.h"
+#include "Resource.h"
+#include "Preferences.h"
+#include "ProgressPalette.h"
+#include "ProgressView.h"
+#include "Views.h"
+#include "WinUtils.h"
+#include "MasterP.h"
+#include "TimeEditDlg.h"
+#include "StudioPreferences.h"
+#include "ResetKeyframeValuesDlg.h"
+#include "GLVersionDlg.h"
+#endif
+#include "Core.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "UICMacros.h"
+#include "IDocumentEditor.h"
+#include "UICFileTools.h"
+#endif
+#include "ImportUtils.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "FileDialogEx.h"
+#endif
+
+#include "StringLoader.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QStandardPaths>
+
+#include <iostream>
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inShowGUI true if dialogs should be displayed or piped to std:cout instead
+ */
+CDialogs::CDialogs(bool inShowGUI /*= true*/)
+#ifdef KDAB_TEMPORARILY_REMOVED
+ : m_ProgressPalette(nullptr)
+ , m_ShowGUI(inShowGUI)
+ , m_LastSaveFile(CUICFile::GetApplicationDirectory().GetAbsolutePath())
+#endif
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CDialogs::~CDialogs()
+{
+}
+
+//=============================================================================
+/**
+ * Displays a multiline text edit.
+ * @param ioText
+ * @param inNotification
+ */
+#if 0
+void CDialogs::DisplayMultilineTextEdit(Q3DStudio::CString &ioText,
+ CMultilineEditDlg::INotification *inNotifiction)
+{
+ CRct theLocation = CStudioPreferences::GetMultilineTextLocation();
+
+ CMultilineEditDlg theMultilineEditDlg(inNotifiction, theLocation);
+ theMultilineEditDlg.SetString(ioText);
+ if (theMultilineEditDlg.DoModal() == IDOK) {
+ // Set the string
+ ioText = theMultilineEditDlg.GetString();
+
+ // Save the window position
+ theLocation = theMultilineEditDlg.GetLocation();
+ CStudioPreferences::SetMultilineTextLocation(theLocation);
+ }
+}
+#endif
+
+//=============================================================================
+/**
+ * Displays a dialog asking the user to choose the keyframe interpolation.
+ *
+ * @param ioEaseIn value to be set as the ease in default - passes back the value chosen by the user
+ * @param ioEaseOut value to be set as the ease out default - passes back the value chosen by the
+ * user
+ * @return true if the user clicked OK on the dialog (indicating that the values should be updated
+ * on the track)
+ */
+bool CDialogs::PromptForKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut)
+{
+ bool theReturnValue = false;
+
+ CInterpolationDlg theInterpolationDialog;
+ theInterpolationDialog.setEaseIn(ioEaseIn);
+ theInterpolationDialog.setEaseOut(ioEaseOut);
+
+ // If the user presses the OK button
+ if (theInterpolationDialog.exec() == QDialog::Accepted) {
+ // Retrieve the new interpolation values
+ ioEaseIn = theInterpolationDialog.easeIn();
+ ioEaseOut = theInterpolationDialog.easeOut();
+ theReturnValue = true;
+ }
+
+ return theReturnValue;
+}
+
+//=============================================================================
+/**
+ * Notify the user that the deletion of an asset has failed.
+ */
+void CDialogs::DisplayAssetDeleteFailed()
+{
+ Q3DStudio::CString theMessage =
+ ::LoadResourceString(IDS_ERROR_CLIENTSAVE); // TODO: Should display the correct string
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_ERROR_MSGTITLE);
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl;
+ }
+}
+
+//=============================================================================
+/**
+ * Get the export choice.
+ */
+CUICFile CDialogs::GetExportChoice(const Q3DStudio::CString &, const Q3DStudio::CString &)
+{
+ // Need to fix this for windows if we decide to use it
+ return CUICFile("", false, false);
+}
+
+//==============================================================================
+/**
+ * Notify that we are unable to refresh the resource.
+ */
+void CDialogs::DisplayRefreshResourceFailed(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription)
+{
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_REFRESHRESOURCETITLE));
+
+ Q3DStudio::CString theText;
+ theText.Format(::LoadResourceString(IDS_ERROR_REFRESHRESOURCETEXT),
+ static_cast<const wchar_t *>(inResourceName));
+
+ if (!inDescription.IsEmpty())
+ theText += inDescription;
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theText, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theText.GetCharStar() << std::endl << std::endl;
+ }
+}
+
+//=============================================================================
+/**
+ * Notify the user that the loading of the requested resource failed.
+ *
+ * Possible failed import messages are:
+ * IDS_ERROR_IMPORTLUARESOURCETEXT - Sorry - Studio was unable to
+ *import the LUA script.\nPlease check the file and try again.\nNote that LUA files must be
+ *syntactically correct to be importable.
+ * IDS_ERROR_IMPORTRESOURCETEXT - Sorry - Studio was unable to
+ *import the resource.\nPlease check the above file and try again.
+ * IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT - Sorry - Studio was unable to import
+ *the resource file.\nThis resource file type is not currently supported by Studio.\n
+ *
+ * @param inURL the URL for the asset that was to have been imported
+ * @param inErrorDescription description for the failure, if any
+ * @param inWarningsOnly not a failure, just warnings
+ */
+void CDialogs::DisplayImportFailed(const QUrl &inURL, const QString &inDescription,
+ bool inWarningsOnly)
+{
+ // Notify the user we couldn't load the resource.
+ Q3DStudio::CString theTitle, theText, theMsgText;
+
+ theTitle = ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE);
+ // specify if its an error or warning
+ theTitle = (!inWarningsOnly) ? ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE_ERROR)
+ : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE_WARNING);
+
+ // Determine the asset type
+ EStudioObjectType theAssetType =
+ Q3DStudio::ImportUtils::GetObjectFileTypeForFile(inURL.path(), false)
+ .m_ObjectType;
+
+ bool theIsStudioObject = theAssetType != OBJTYPE_UNKNOWN;
+
+ // Is this a LUA file, but perhaps incorrectly formatted?
+ if (theAssetType == OBJTYPE_BEHAVIOR) {
+ // Load the message about the LUA format
+ if (inWarningsOnly)
+ theText = ::LoadResourceString(IDS_WARNING_IMPORTLUARESOURCETEXT);
+ else
+ theText = ::LoadResourceString(IDS_ERROR_IMPORTLUARESOURCETEXT);
+ if (!inDescription.isEmpty()) {
+ theText += L"\n";
+ theText += Q3DStudio::CString::fromQString(inDescription);
+ }
+ } else if (theAssetType != OBJTYPE_UNKNOWN || theIsStudioObject) {
+ // Valid registered file type, but invalid file
+
+ bool theNoDescription = inDescription.isEmpty();
+ // Load default text stating that the import resource failed.
+ // descriptions if present are presented as "reasons" for failure.
+ if (!inWarningsOnly || theNoDescription) {
+ theText.Format(::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT), theNoDescription
+ ? L"."
+ : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_REASON).c_str());
+ theText += "\n";
+ }
+ if (!theNoDescription)
+ theText += Q3DStudio::CString::fromQString(inDescription);
+ else
+ theText += ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_CHECKFILE);
+ } else {
+ // Display the warning messsage if we have one
+ // instead of a meaningless message. This provides more feed back
+ if (!inDescription.isEmpty())
+ theText += Q3DStudio::CString::fromQString(inDescription);
+ else
+ theText = ::LoadResourceString(
+ IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT); // Load default text stating that the
+ // import resource failed.
+ }
+
+ Q3DStudio::CString theFormatString(
+ !inWarningsOnly ? ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_FAILED)
+ : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_COMPLETEWITHWARNING));
+ theFormatString += _UIC("\n%ls\n\n");
+ std::wstring wstr = inURL.path().toStdWString();
+ theMsgText.Format(theFormatString, static_cast<const wchar_t *>(wstr.c_str()));
+ theMsgText += theText;
+
+ // Display the failed import resource message.
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMsgText, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theMsgText.GetCharStar() << std::endl;
+ }
+}
+
+namespace {
+
+inline Q3DStudio::CString CreateExtensionsList(const char **extList)
+{
+ Q3DStudio::CString retval;
+ for (const char **ext = extList; *ext != nullptr; ++ext) {
+ if (retval.Length())
+ retval += " ";
+ retval += Q3DStudio::CString("*.") + *ext;
+ }
+ return retval;
+}
+
+struct SAllowedTypesEntry
+{
+ Q3DStudio::DocumentEditorFileType::Enum m_FileType;
+ long m_ResourceStringId; // Model Files, Image Files, etc
+ const char **m_FileExtensions;
+};
+const char *imgExts[] = {
+ "png", "jpg", "jpeg", "dds", "bmp", "gif", "hdr", nullptr,
+};
+const wchar_t *wideImgExts[] = {
+ L"png", L"jpg", L"jpeg", L"dds", L"bmp", L"gif", L"hdr", nullptr,
+};
+const char *modelExts[] = {
+ CDialogs::GetDAEFileExtension(),
+#ifdef QT_3DSTUDIO_FBX
+ CDialogs::GetFbxFileExtension(),
+#endif
+ // TODO CDialogs::GetImportFileExtension(),
+ // TODO CDialogs::GetMeshFileExtension(),
+ nullptr,
+};
+const char *meshExts[] = {
+ CDialogs::GetMeshFileExtension(), nullptr,
+};
+const char *importExts[] = {
+ CDialogs::GetImportFileExtension(), nullptr,
+};
+const char *behaviorExts[] = {
+ CDialogs::GetLUAFileExtension(), nullptr,
+};
+const char *fontExts[] = {
+ "ttf", "otf", nullptr,
+};
+const wchar_t *wideFontExts[] = {
+ L"ttf", L"otf", nullptr,
+};
+const char *effectExts[] = {
+ "effect", nullptr,
+};
+const wchar_t *wideEffectExts[] = {
+ L"effect", nullptr,
+};
+const char *materialExts[] = {
+ "material", nullptr,
+};
+const wchar_t *wideMaterialExts[] = {
+ L"material", nullptr,
+};
+const char *soundExts[] = {
+ "wav", nullptr,
+};
+const wchar_t *wideSoundExts[] = {
+ L"wav", nullptr,
+};
+
+// List of file types allowed during import
+SAllowedTypesEntry g_AllowedImportTypes[] = {
+ { Q3DStudio::DocumentEditorFileType::DAE, IDS_LIBRARYIMPORT_MODEL, modelExts },
+#ifdef QT_3DSTUDIO_FBX
+ { Q3DStudio::DocumentEditorFileType::FBX, IDS_LIBRARYIMPORT_MODEL, modelExts },
+#endif
+};
+size_t g_NumAllowedImportTypes = sizeof(g_AllowedImportTypes) / sizeof(*g_AllowedImportTypes);
+
+// List of file types allowed for file references
+SAllowedTypesEntry g_AllowedFileReferencesTypes[] = {
+ { Q3DStudio::DocumentEditorFileType::Image, IDS_LIBRARYIMPORT_IMAGE, imgExts },
+ { Q3DStudio::DocumentEditorFileType::Behavior, IDS_LIBRARYIMPORT_BEHAVIOR, behaviorExts },
+ { Q3DStudio::DocumentEditorFileType::Mesh, IDS_LIBRARYIMPORT_MESH, meshExts },
+ { Q3DStudio::DocumentEditorFileType::Import, IDS_LIBRARYIMPORT_IMPORT, importExts },
+ { Q3DStudio::DocumentEditorFileType::Effect, IDS_LIBRARYIMPORT_EFFECT, effectExts },
+};
+size_t g_NumAllowedFileReferencesTypes =
+ sizeof(g_AllowedFileReferencesTypes) / sizeof(*g_AllowedFileReferencesTypes);
+}
+
+QString CDialogs::ConfirmRefreshModelFile(const QString &inFile)
+{
+ // this produces an extension string which contains all allowed formats specified in
+ // g_AllowedImportTypes
+ // currently DAE and FBX
+ QString theFileFilter =
+ CreateAllowedTypesString(Q3DStudio::DocumentEditorFileType::DAE, true);
+
+
+ return QFileDialog::getOpenFileName(qApp->activeWindow(), QObject::tr("Open"),
+ inFile, theFileFilter);
+}
+
+//==============================================================================
+/**
+ * Allows the user to select/confirm the file to fix broken file reference.
+ * This method opens a file dialog to the specified location, and allows the user to
+ * accept, or select a different file.
+ * @param outFile The output path
+ * @param inFileType The file type filter for the dialog.
+ * @return true If the user accepted the file, false if the user canceled.
+ */
+bool CDialogs::LocateFileReference(CUICFile &outFile, long inFileType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Q3DStudio::CString theFileFilter = CreateAllowedTypesString(inFileType, false);
+
+ bool theResult = false;
+
+ // Open the dialog.
+ CFileDialogEx theFileDialog(TRUE, nullptr, nullptr, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+ theFileFilter, nullptr);
+
+ // Set the initial directory to document path's directory (it should exist).
+ CUICFile theDocumentFile(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath());
+ Q3DStudio::CFilePath theInitDir =
+ Q3DStudio::CFilePath(theDocumentFile.GetAbsolutePath()).GetDirectory();
+ theFileDialog.SetInitialDirectory(theInitDir);
+
+ // Set the title of the dialog
+ theFileDialog.SetWindowTitle(::LoadResourceString(IDS_PROJECT_CM_LOCATE_FILE));
+
+ INT_PTR refreshResult = theFileDialog.DoModal();
+
+ if (refreshResult == IDOK) {
+ Q3DStudio::CString thePath = theFileDialog.GetPathName();
+ Q3DStudio::CString theName = theFileDialog.GetFileName();
+ outFile = CUICFile(thePath, theName);
+
+ // The user has accepted this file.
+ theResult = true;
+ }
+
+ return theResult;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Allows the user to select/confirm the folder to fix broken folder reference.
+ * This method opens a folder dialog to the specified location, and allows the user to
+ * accept, or select a different folder.
+ * @param outFile The output path
+ * @return true If the user accepted the file, false if the user canceled.
+ */
+bool CDialogs::LocateFolderReference(CUICFile &outFile)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set the initial directory to document path's directory (it should exist).
+ CUICFile theDocumentFile(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath());
+ Q3DStudio::CFilePath theInitDir =
+ Q3DStudio::CFilePath(theDocumentFile.GetAbsolutePath()).GetDirectory();
+
+ // Set the title of the dialog
+ Q3DStudio::CString theDialogTitle(::LoadResourceString(IDS_PROJECT_CM_LOCATE_FOLDER));
+
+ return BrowseForFolderDialog(outFile, theInitDir, theDialogTitle);
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * BrowseCallbackProc: Handles the callback proc for SHBrowseForFolder()
+ *
+ * Handles selecting the correct path when the SHBrowseForFolder dialog is
+ * initially displayed.
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+static int CALLBACK BrowseCallbackProc(HWND inHwnd, UINT inMsg, LPARAM /*inlParam*/,
+ LPARAM inlpData)
+{
+ switch (inMsg) {
+ case BFFM_INITIALIZED:
+ // Indicates the browse dialog box has finished initializing. The lParam value is zero.
+ if (inlpData != nullptr) {
+ // Do so by sendint the BFFM_SETSELECTION message to the inHwnd:
+ // Selects the specified folder. To use a PIDL to specify the folder, set the
+ // message's lParam to the PIDL, and set wParam to FALSE. To specify the folder's
+ // path, set the message's lParam value to point to a nullptr-terminated string with
+ // the path, and set wParam to TRUE.
+
+ SendMessage(inHwnd, BFFM_SETSELECTION, (WPARAM)TRUE, (LPARAM)inlpData);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+#endif
+
+//==============================================================================
+/**
+ * Show browse for folder dialog
+ * @param outFile The output path
+ * @param inDefaultDir The default directory
+ * @param inDialogTitle The title of the dialog
+ * @return true If the user accepted the file, false if the user canceled.
+ */
+bool CDialogs::BrowseForFolderDialog(CUICFile &outFile, Q3DStudio::CString inDefaultDir,
+ Q3DStudio::CString inDialogTitle)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ bool theResult = false;
+ BROWSEINFO theInfo = { 0 };
+ TCHAR theDispName[MAX_PATH] = { '\0' };
+
+ theInfo.pszDisplayName = theDispName;
+ theInfo.lpszTitle = inDialogTitle;
+ theInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_NONEWFOLDERBUTTON;
+ theInfo.lpfn = BrowseCallbackProc;
+ theInfo.lParam = (LPARAM)inDefaultDir.c_str();
+
+ // Ask the user to choose a directory
+ LPITEMIDLIST theItem = SHBrowseForFolder(&theInfo);
+
+ if (theItem != nullptr) {
+ TCHAR thePath[MAX_PATH] = { '\0' };
+ // If a path was chosen
+ if (::SHGetPathFromIDList(theItem, thePath)) {
+ theResult = true;
+ outFile = CUICFile(Q3DStudio::CString(thePath));
+ }
+
+ // Free Memory used
+ LPMALLOC thePMalloc = 0;
+ if (SUCCEEDED(SHGetMalloc(&thePMalloc))) {
+ thePMalloc->Free(theItem);
+ thePMalloc->Release();
+ }
+ }
+
+ return theResult;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Notify the user that the presentation we tried to load has failed.
+ * @param inPresentation The AKFile that we failed to load.
+ */
+void CDialogs::DisplayLoadingPresentationFailed(const CUICFile &inPresentation,
+ long inErrorIDS /*= -1 */)
+{
+ Q_UNUSED(inPresentation);
+
+ if (inErrorIDS == -1) // if unspecified, default to the 'generic' string
+ inErrorIDS = IDS_ERROR_LOADPRESENTATION;
+ Q3DStudio::CString theErrorMessage;
+ theErrorMessage.Format(::LoadResourceString(inErrorIDS),
+ static_cast<const wchar_t *>(inPresentation.GetName()));
+ Q3DStudio::CString theErrorTitle(::LoadResourceString(IDS_ERROR_LOADPRESENTATION_TITLE));
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theErrorTitle, theErrorMessage, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theErrorTitle.GetCharStar() << ": " << theErrorMessage.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Notify the user that the presentation we tried to save has failed.
+ *
+ * @param inSavedLocation The AKFile that we failed to save.
+ */
+void CDialogs::DisplaySavingPresentationFailed()
+{
+ Q3DStudio::CString theErrorMessage = ::LoadResourceString(IDS_ERROR_EXPORTPRESENTATION);
+ Q3DStudio::CString theErrorTitle = ::LoadResourceString(IDS_PROJNAME);
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theErrorTitle, theErrorMessage, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theErrorTitle.GetCharStar() << ": " << theErrorMessage.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Display a message box to indicate failure to overwrite a read-only file
+ *
+ * @param inSavedLocation
+ * the file location to be saved
+ *
+ * @return void
+ */
+void CDialogs::DisplaySaveReadOnlyFailed(const CUICFile &inSavedLocation)
+{
+ Q3DStudio::CString theMsg = ::LoadResourceString(IDS_SAVE_READONLY_WARNING);
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_PROJNAME);
+
+ Q3DStudio::CString theFormattedText;
+ theFormattedText.Format(theMsg, static_cast<const wchar_t *>(inSavedLocation.GetName()));
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theFormattedText, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theFormattedText.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Displays a CUICMessageBox using the specified parameters. The message box
+ * is modal to the main frame. This provides an easy way to place modal dialogs
+ * to the user, without requiring your class to know about the main frame or
+ * window refs.
+ * @param inTitle Title of the message box (not used on Mac)
+ * @param inText Text of the message
+ * @param inIcon Icon to be displayed next to the text
+ * @param inShowCancel true to show a Cancel button, false only show an OK button
+ * @return Indication of which button was pressed to dismiss the dialog
+ */
+CUICMessageBox::EMessageBoxReturn
+CDialogs::DisplayMessageBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText,
+ CUICMessageBox::EMessageBoxIcon inIcon, bool inShowCancel)
+{
+ CUICMessageBox::EMessageBoxReturn theUserChoice;
+
+ if (m_ShowGUI) {
+ theUserChoice =
+ CUICMessageBox::Show(inTitle, inText, inIcon, inShowCancel, qApp->activeWindow());
+ } else {
+ std::cout << inTitle.GetCharStar() << ": " << inText.GetCharStar() << std::endl;
+ theUserChoice = CUICMessageBox::MSGBX_OK;
+ }
+
+ return theUserChoice;
+}
+
+int CDialogs::DisplayChoiceBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText,
+ int inIcon)
+{
+ if (m_ShowGUI) {
+ QMessageBox box;
+ box.setWindowTitle(inTitle.toQString());
+ box.setText(inText.toQString());
+ switch (inIcon) {
+ case CUICMessageBox::ICON_WARNING:
+ box.setIcon(QMessageBox::Warning);
+ break;
+ case CUICMessageBox::ICON_ERROR:
+ box.setIcon(QMessageBox::Critical);
+ break;
+ case CUICMessageBox::ICON_INFO:
+ box.setIcon(QMessageBox::Information);
+ break;
+ default:
+ break;
+ }
+ box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+ switch (box.exec()) {
+ case QMessageBox::Yes:
+ return IDYES;
+ case QMessageBox::No:
+ return IDNO;
+ default:
+ Q_UNREACHABLE();
+ }
+ } else {
+ std::cout << inTitle.GetCharStar() << ": " << inText << std::endl;
+ return IDYES;
+ }
+}
+
+const char *CDialogs::GetDAEFileExtension()
+{
+ return "dae";
+}
+const char *CDialogs::GetFbxFileExtension()
+{
+ return "fbx";
+}
+// Null terminated list
+const char **CDialogs::GetImgFileExtensions()
+{
+ return imgExts;
+}
+const char *CDialogs::GetImportFileExtension()
+{
+ return "import";
+}
+const char *CDialogs::GetMeshFileExtension()
+{
+ return "mesh";
+}
+const char *CDialogs::GetLUAFileExtension()
+{
+ return "lua";
+}
+const char *CDialogs::GetQmlFileExtension()
+{
+ return "qml";
+}
+const char **CDialogs::GetFontFileExtensions()
+{
+ return fontExts;
+}
+const char **CDialogs::GetEffectFileExtensions()
+{
+ return effectExts;
+}
+const char **CDialogs::GetMaterialFileExtensions()
+{
+ return materialExts;
+}
+const char **CDialogs::GetSoundFileExtensions()
+{
+ return soundExts;
+}
+
+bool IsFileExtension(const char *inExt, const char **inExts)
+{
+ if (inExt == nullptr)
+ return false;
+ for (const char **ext = inExts; *ext != nullptr; ++ext)
+ if (QString::compare(inExt, *ext, Qt::CaseInsensitive) == 0)
+ return true;
+ return false;
+}
+bool CDialogs::IsImageFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, imgExts);
+}
+bool CDialogs::IsFontFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, fontExts);
+}
+bool CDialogs::IsEffectFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, effectExts);
+}
+bool CDialogs::IsMaterialFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, materialExts);
+}
+bool CDialogs::IsSoundFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, soundExts);
+}
+
+const wchar_t **CDialogs::GetWideImgFileExtensions()
+{
+ return wideImgExts;
+}
+const wchar_t *CDialogs::GetWideDAEFileExtension()
+{
+ return L"dae";
+}
+const wchar_t *CDialogs::GetWideFbxFileExtension()
+{
+ return L"fbx";
+}
+const wchar_t *CDialogs::GetWideImportFileExtension()
+{
+ return L"import";
+}
+const wchar_t *CDialogs::GetWideMeshFileExtension()
+{
+ return L"mesh";
+}
+const wchar_t *CDialogs::GetWideLUAFileExtension()
+{
+ return L"lua";
+}
+const wchar_t **CDialogs::GetWideFontFileExtensions()
+{
+ return wideFontExts;
+}
+const wchar_t **CDialogs::GetWideEffectFileExtensions()
+{
+ return wideEffectExts;
+}
+const wchar_t **CDialogs::GetWideMaterialFileExtensions()
+{
+ return wideMaterialExts;
+}
+
+bool IsFileExtension(const wchar_t *inExt, const wchar_t **inExts)
+{
+ if (inExt == nullptr)
+ return false;
+ for (const wchar_t **ext = inExts; *ext != nullptr; ++ext) {
+ if (QString::compare(QString::fromWCharArray(inExt),
+ QString::fromWCharArray(*ext), Qt::CaseInsensitive) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+bool CDialogs::IsImageFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideImgExts);
+}
+bool CDialogs::IsFontFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideFontExts);
+}
+bool CDialogs::IsEffectFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideEffectExts);
+}
+
+bool CDialogs::IsMaterialFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideMaterialExts);
+}
+
+bool CDialogs::IsPathFileExtension(const wchar_t *inExt)
+{
+ return QString::compare(QString::fromWCharArray(inExt), "svg", Qt::CaseInsensitive) == 0;
+}
+
+bool CDialogs::IsPathBufferExtension(const wchar_t *inExt)
+{
+ return QString::compare(QString::fromWCharArray(inExt), "path", Qt::CaseInsensitive) == 0;
+}
+
+bool CDialogs::IsSoundFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideSoundExts);
+}
+
+//==============================================================================
+/**
+ * File picker.
+ * Format for filter is as follows:
+ * Each entry in the filter list is '<description>|*.ext'
+ * String must end with '|'
+ * Example, XML Exporter (*.xml)|*.xml|All files (*.*)|*.*|
+ *
+ * @param inFileExtensionFilter Well-formed extension filter string. See comments
+ *above for the format.
+ * @param inDefault Default string in case of abortion or
+ *failure
+ * @return chosen file path if successful, inDefault otherwise.
+ */
+Q3DStudio::CString CDialogs::GetFilePathChoice(const Q3DStudio::CString &inFileExtensionFilter,
+ const Q3DStudio::CString &inDefault,
+ const Q3DStudio::CString *inDialogTitle /*= nullptr */)
+{
+ Q3DStudio::CString theResult(inDefault);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CFileDialogEx theFileDlg(true, nullptr, nullptr, 0, inFileExtensionFilter, AfxGetMainWnd());
+
+ Q3DStudio::CString theInitDir =
+ CPreferences::GetUserPreferences().GetStringValue("LastChosenFile", "");
+ theFileDlg.SetInitialDirectory(theInitDir);
+
+ // Remember the filter setting between invokations
+ static long s_LastFilterIndex = -1;
+ if (s_LastFilterIndex > 0)
+ theFileDlg.SetFilterIndex(s_LastFilterIndex);
+
+ if (inDialogTitle) // Set the title of the dialog if specied
+ theFileDlg.SetWindowTitle(*inDialogTitle);
+
+ if (theFileDlg.DoModal() == IDOK) {
+ theResult = theFileDlg.GetPathName();
+ CPreferences::GetUserPreferences().SetStringValue("LastChosenFile", theResult);
+ s_LastFilterIndex = theFileDlg.GetLastFilterIndex();
+ }
+#endif
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * CreateAllowedTypesString: Creates the string used to determine allowable types for import or
+ *for filereferences
+ * @return the string that dynamicly created with the extensions supported.
+ */
+QString CDialogs::CreateAllowedTypesString(long inFileTypeFilter, bool inForImport)
+{
+ QString theReturnString;
+ size_t theCount = inForImport ? g_NumAllowedImportTypes : g_NumAllowedFileReferencesTypes;
+ for (size_t idx = 0; idx < theCount; ++idx) {
+ const SAllowedTypesEntry &entry =
+ inForImport ? g_AllowedImportTypes[idx] : g_AllowedFileReferencesTypes[idx];
+ if (inFileTypeFilter == Q3DStudio::DocumentEditorFileType::Unknown
+ || inFileTypeFilter == entry.m_FileType) {
+ QString theTypeString(::LoadResourceString(entry.m_ResourceStringId).toQString());
+ QString theExtensions(CreateExtensionsList(entry.m_FileExtensions).toQString());
+ theReturnString += theTypeString + " (" + theExtensions + ");;";
+ }
+ }
+ return theReturnString;
+}
+
+//==============================================================================
+/**
+ * Display a error dialog box with the given text string that describes the error.
+ */
+void CDialogs::DisplayKnownErrorDialog(const Q3DStudio::CString &inErrorText)
+{
+ if (inErrorText.Length() > 0) // make sure this is valid
+ {
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_PROJNAME));
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, inErrorText, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else
+ std::cout << inErrorText.GetCharStar() << ": " << inErrorText.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Prompt the user to save the document before losing their changes.
+ * This is used when closing, loading or newing up a document when the current
+ * one has modifications.
+ * @return the user's choice.
+ */
+CDialogs::ESavePromptResult CDialogs::PromptForSave()
+{
+ Q3DStudio::CString theDocTitle;
+
+ CUICFile theCurrentDoc = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath();
+ if (theCurrentDoc.IsFile())
+ theDocTitle = theCurrentDoc.GetName();
+ else // if the current doc has not been saved then use the default title.
+ theDocTitle = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE);
+
+ Q3DStudio::CString thePrompt = ::LoadResourceString(IDS_PROMPT_FOR_SAVE);
+ thePrompt.Format(thePrompt, static_cast<const wchar_t *>(theDocTitle));
+
+ int theChoice = QMessageBox::warning(nullptr, ::LoadResourceString(IDS_PROJNAME).toQString(),
+ thePrompt.toQString(), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
+
+ ESavePromptResult theResult = CANCEL_OPERATION;
+
+ switch (theChoice) {
+ case QMessageBox::Yes:
+ theResult = SAVE_FIRST;
+ break;
+ case QMessageBox::No:
+ theResult = CONTINUE_NO_SAVE;
+ break;
+ case QMessageBox::Cancel:
+ theResult = CANCEL_OPERATION;
+ break;
+ default:
+ break;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Prompt the user for a file to save to from the SaveAs menu option.
+ * @return an invalid file if the user cancels the save dialog.
+ */
+std::pair<CUICFile, bool> CDialogs::GetSaveAsChoice(const Q3DStudio::CString &inDialogTitle,
+ bool inFilenameUntitled)
+{
+ CUICFile theFile("");
+ Q3DStudio::CString theFileExt;
+ Q3DStudio::CString theImportFilter;
+
+ Q3DStudio::CString theFilename = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath().GetAbsolutePath();
+
+ if (theFilename == "" || inFilenameUntitled)
+ theFilename = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE);
+
+ theFileExt = ::LoadResourceString(IDS_FILE_EXT_UIP);
+ theImportFilter = ::LoadResourceString(IDS_FILE_DESC_UIP);
+
+ theImportFilter += " (*" + theFileExt + ")|*" + theFileExt + "|";
+
+ QFileDialog theFileDlg;
+ theFileDlg.setOption(QFileDialog::DontConfirmOverwrite);
+ const QFileInfo fi(m_LastSaveFile.toQString());
+ theFileDlg.setDirectory((fi.path() == QLatin1Char('.')) ? QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) : fi.path());
+ theFileDlg.setAcceptMode(QFileDialog::AcceptSave);
+ theFileDlg.setDefaultSuffix(theFileExt.toQString());
+ if (inDialogTitle != "")
+ theFileDlg.setWindowTitle(inDialogTitle.toQString());
+
+ bool theCreateDir = false;
+ bool theShowDialog = true;
+
+ while (theShowDialog && theFileDlg.exec()) {
+ theShowDialog = false;
+ theFile = CUICFile(Q3DStudio::CString::fromQString(theFileDlg.selectedFiles().front()));
+
+ m_LastSaveFile = theFile.GetAbsolutePath();
+ // customising a dialog box will force us to use non-native.
+ // defaulting this for now, until we can agree a better workflow for
+ // creating new projects
+ theCreateDir = true;
+
+ if (theCreateDir) {
+ // If user checks "Create directory for project"
+ // we need to check manually if the file in the directory already exists (because the
+ // default file dialog can't do that for you)
+ // If the file exists, show warning message if user wants to overwrite the file
+ // This is to fix bug #6315: Create new project in folder with same name will overwrite
+ // existing file without warning
+ Q3DStudio::CFilePath theFinalDir;
+ Q3DStudio::CFilePath theFinalDoc;
+ g_StudioApp.GetCore()->GetCreateDirectoryFileName(theFile, theFinalDir, theFinalDoc);
+
+ // Update last save file to final doc
+ m_LastSaveFile = theFinalDoc;
+ if (theFinalDoc.Exists()) {
+ const QString theTitle(QObject::tr("Confirm Save As"));
+ const QString filePath(theFinalDir.GetFileName().toQString() + QDir::separator() + theFinalDoc.GetFileName().toQString());
+ const QString theString = QObject::tr("%1 already exists.\nDo you want to replace it?").arg(filePath);
+
+ auto result = QMessageBox::question(nullptr, theTitle, theString);
+ if (result != QMessageBox::Yes) {
+ // Reset the file and show the file dialog again
+ theFile = CUICFile("");
+ theShowDialog = true;
+ continue;
+ }
+ } // of over-writing case
+ }
+ }
+
+ return std::make_pair(theFile, theCreateDir);
+}
+
+//==============================================================================
+/**
+ * Prompt the user for a file to create.
+ * @return an invalid file if the user cancels the save dialog.
+ */
+std::pair<CUICFile, bool>
+CDialogs::GetNewDocumentChoice(const Q3DStudio::CString &inInitialDirectory)
+{
+ if (inInitialDirectory.size())
+ m_LastSaveFile = inInitialDirectory;
+ return GetSaveAsChoice(::LoadResourceString(IDS_CREATE_NEW_DOCUMENT_TITLE), true);
+}
+
+//==============================================================================
+/**
+ * Prompt the user for a file to open.
+ * This will return an invalid file if the user cancels the save dialog.
+ */
+CUICFile CDialogs::GetFileOpenChoice(const Q3DStudio::CString &inInitialDirectory)
+{
+ CUICFile theFile("");
+ Q3DStudio::CString theFileExt;
+ Q3DStudio::CString theImportFilter;
+
+ theFileExt = ::LoadResourceString(IDS_FILE_EXT_UIP);
+ theImportFilter = ::LoadResourceString(IDS_FILE_DESC_UIP);
+
+ theImportFilter += " (*" + theFileExt + ")";
+
+ QFileDialog theFileDlg(qApp->activeWindow(), QString(), inInitialDirectory.toQString(), theImportFilter.toQString());
+ theFileDlg.setAcceptMode(QFileDialog::AcceptOpen);
+
+ if (theFileDlg.exec() == QDialog::Accepted) {
+ QFileInfo fi(theFileDlg.selectedFiles().first());
+ Q3DStudio::CString thePath = Q3DStudio::CString::fromQString(fi.absolutePath());
+ Q3DStudio::CString theName = Q3DStudio::CString::fromQString(fi.fileName());
+ theFile = CUICFile(thePath, theName);
+
+ m_LastSaveFile = theFile.GetAbsolutePath();
+ }
+
+ return theFile;
+}
+
+//==============================================================================
+/**
+ * Prompt the user to make sure they want to revert the current project.
+ * @return true if they do want to continue with the revert.
+ */
+bool CDialogs::ConfirmRevert()
+{
+ bool theConfirmation = false;
+ Q3DStudio::CString thePrompt = ::LoadResourceString(IDS_PROMPT_FOR_REVERT);
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_PROJNAME);
+
+ CUICMessageBox::EMessageBoxReturn theChoice;
+
+ if (m_ShowGUI)
+ theChoice = CUICMessageBox::Show(theTitle, thePrompt, CUICMessageBox::ICON_WARNING, true,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << thePrompt.GetCharStar() << std::endl;
+ theChoice = CUICMessageBox::MSGBX_OK;
+ }
+
+ // user decided to go ahead and delete all unused resources
+ if (theChoice == CUICMessageBox::MSGBX_OK)
+ theConfirmation = true;
+
+ return theConfirmation;
+}
+
+//==============================================================================
+/**
+ * Displays a progress screen, if there is not one aleady being shown. The
+ * progress screen doesn't get dismissed until you call
+ * CDialogs::DestroyProgressScreen().
+ * @param inActionText text to be displayed above the file name on the screen
+ * @param inFileName name of the file that you are loading
+ * @param inWindowTitle the window's title
+ */
+void CDialogs::DisplayProgressScreen(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (m_ShowGUI && (!m_ProgressPalette || !m_ProgressPalette->GetSafeHwnd())) {
+ m_ProgressPalette = new CProgressPalette();
+ CViews::CreateDialogAndView(RUNTIME_CLASS(CProgressView), m_ProgressPalette,
+ (CFrameWnd *)AfxGetMainWnd(), inWindowTitle);
+ m_ProgressPalette->ShowDialog();
+ m_ProgressPalette->InitialUpdate();
+ m_ProgressPalette->SetActionText(inActionText);
+ m_ProgressPalette->SetFileName(inFileName);
+ m_ProgressPalette->RedrawWindow(nullptr, nullptr, RDW_UPDATENOW);
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Retrieve the pointer to the progress screen.
+ * @return m_ProgressPalette
+ */
+IProgressCallback *CDialogs::GetProgressScreen() const
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ return m_ProgressPalette;
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * If a loading screen is currently being shown, this function destroys it. You
+ * can show the loading screen again with another call to
+ * CDialogs::DisplayLoadingScreen().
+ */
+void CDialogs::DestroyProgressScreen()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (m_ShowGUI && (m_ProgressPalette && m_ProgressPalette->GetSafeHwnd())) {
+ // Don't call delete on m_ProgressPalette. You should only call DestroyWindow on
+ // CFrameWnds. See the MSDN.
+ m_ProgressPalette->DestroyWindow();
+ m_ProgressPalette = nullptr;
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Prompt the user for the Object Timebar color.
+ * @param ioColor
+ * @return true if we successfully obtained a color using the displayed dialog.
+ */
+bool CDialogs::PromptObjectTimebarColor(CColor &ioColor)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ std::auto_ptr<CColorDialog> theColorDlg(new CColorDialog(ioColor, CC_SOLIDCOLOR | CC_FULLOPEN));
+ ::CColor theSelectedColor;
+ if (theColorDlg->DoModal() == IDOK) {
+ ioColor = theColorDlg->GetColor();
+ return true;
+ }
+ return false;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Display statistics from profiling.
+ */
+void CDialogs::DisplayProfilingStatistics()
+{
+ Q3DStudio::CString theStatistics = "<Not Enabled>";
+#ifdef KDAB_TEMPORARILY_REMOVED
+#ifdef PERFORM_PROFILE
+ CMasterProf *theMasterP = CMasterProf::GetInstance();
+
+ for (long theIndex = 0; theIndex < theMasterP->GetProfilerCount(); ++theIndex) {
+ CMethProf *theProf = theMasterP->GetProfiler(theIndex);
+ if (theProf->GetCount() > 0) {
+ theStatistics += theProf->GetDescription();
+ theStatistics += "\n";
+ }
+ }
+#endif // #ifdef PERFORM_PROFILE
+ if (m_ShowGUI)
+ CUICMessageBox::Show("Profiling Statistics", theStatistics, CUICMessageBox::ICON_INFO);
+ else {
+ std::cout << "Profiling Statistics"
+ << ": " << theStatistics.GetMulti() << std::endl;
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Inform the user that the environment variables entered does not match the format
+ * expected, listing down all those settings that are wrong.
+ * @param inErrorMessage the listing of all those errors.
+ */
+void CDialogs::DisplayEnvironmentVariablesError(const Q3DStudio::CString &inErrorMessage)
+{
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_ERROR_PROJECT_VARIABLES_TITLE);
+ Q3DStudio::CString theMessage = ::LoadResourceString(IDS_ERROR_PROJECT_VARIABLES_MSG);
+ theMessage += inErrorMessage;
+ theMessage += ::LoadResourceString(IDS_PROJECT_VARIABLES_FORMAT);
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Reset settings.
+ * Typically inCurrentDocPath is only set when Studio is first launched.
+ * @param inCurrentDocPath the current document path, if any. Application directory if
+ *there is none.
+ */
+void CDialogs::ResetSettings(const Q3DStudio::CString &inCurrentDocPath)
+{
+ // Initialize the default dir/paths to the current document path if specified, otherwise leave
+ // everything as it is.
+ if (!inCurrentDocPath.IsEmpty()) {
+ m_LastSaveFile = inCurrentDocPath;
+ }
+}
+
+bool CDialogs::DisplayResetKeyframeValuesDlg()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CResetKeyframeValuesDlg theDialog;
+ return theDialog.DoModal() == IDOK;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * User trying to do a pathological paste, such as pasting a component copied from a different
+ *instance
+ * of Studio into an instance of the same component that already exists in the current instance
+ *of Studio, and
+ * is potentially replaced and deleted.
+ */
+void CDialogs::DisplayPasteFailed()
+{
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_PATHOLOGICAL_PASTE_TITLE));
+ Q3DStudio::CString theMessage(::LoadResourceString(IDS_ERROR_PATHOLOGICAL_PASTE_MESSAGE));
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else
+ std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl;
+}
+
+//==============================================================================
+/**
+ * Video card OpenGL version is too low to be supported.
+ */
+void CDialogs::DisplayGLVersionError(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inMinVersion)
+{
+ DisplayGLVersionDialog(inGLVersion, inMinVersion, true);
+}
+
+//==============================================================================
+/**
+ * Video card OpenGL version is outdated, but could be usable.
+ */
+void CDialogs::DisplayGLVersionWarning(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inRecommendedVersion)
+{
+ DisplayGLVersionDialog(inGLVersion, inRecommendedVersion, false);
+}
+
+//==============================================================================
+/**
+ * Display the error dialog or warning dialog that OpenGL version is lower than what is
+ *expected
+ */
+void CDialogs::DisplayGLVersionDialog(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inRecommendedVersion, bool inError)
+{
+ long theTitleResourceID;
+ long theMessageResourceID;
+
+ if (inError) {
+ theTitleResourceID = IDS_ERROR_MSGTITLE;
+ theMessageResourceID = IDS_GL_VERSION_ERROR;
+ } else {
+ theTitleResourceID = IDS_WARNING_MSGTITLE;
+ theMessageResourceID = IDS_GL_VERSION_WARNING;
+ }
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Q3DStudio::CString theTitle(::LoadResourceString(theTitleResourceID));
+ Q3DStudio::CString theMessage(::LoadResourceString(theMessageResourceID));
+ Q3DStudio::CString theFormattedMessage;
+ theFormattedMessage.Format(theMessage, static_cast<const wchar_t *>(inGLVersion),
+ static_cast<const wchar_t *>(inRecommendedVersion));
+
+ CGLVersionDlg theGLVersionDlg;
+ theGLVersionDlg.Initialize(theTitle, theFormattedMessage, inError);
+ theGLVersionDlg.DoModal();
+
+ if (theGLVersionDlg.GetDontShowAgain())
+ CStudioPreferences::SetDontShowGLVersionDialog(true);
+#endif
+}
diff --git a/src/Authoring/Studio/_Win/Workspace/Views.cpp b/src/Authoring/Studio/_Win/Workspace/Views.cpp
new file mode 100644
index 00000000..50ab6f62
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Workspace/Views.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Views.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "Doc.h"
+#endif
+#include "MainFrm.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "TimelineTimelineLayout.h"
+#include "ScalableScroller.h"
+#include "PaletteManager.h"
+#include "HotKeys.h"
+#include "Dispatch.h"
+#include "ActionControl.h"
+#include "StudioPaletteBar.h"
+#endif
+
+//==============================================================================
+// Implementation
+//==============================================================================
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CViews::CViews(CStudioApp * /*inStudioApp*/)
+ : m_MainFrame(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CViews::~CViews()
+{
+ DestroyViews();
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CViews::CreateViews()
+{
+ // To create the main window, this code creates a new frame window
+ // object and then sets it as the application's main window object
+ m_MainFrame = new CMainFrame();
+ m_MainFrame->show();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // create and load the frame with its resources
+ m_MainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, nullptr, nullptr);
+
+ m_MainFrame->RestoreLayout();
+#endif
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CViews::DestroyViews()
+{
+ if (m_MainFrame) {
+ // Do NOT use delete to destroy a CFrameWnd object! Use DestroyWindow() instead.
+ m_MainFrame->deleteLater();
+ m_MainFrame = nullptr;
+ }
+}
+
+//==============================================================================
+// Keyboard
+//==============================================================================
+
+//=============================================================================
+/**
+ * Register all Application specific shortcut keys.
+ * Used to map hotkeys that are active through the whole app, not just one
+ * view.
+ * @param inHotKeys the handler to register on.
+ */
+void CViews::RegisterGlobalKeyboardShortcuts(CHotKeys *inHotKeys)
+{
+ if (m_MainFrame)
+ m_MainFrame->RegisterGlobalKeyboardShortcuts(inHotKeys);
+}
+
+//=============================================================================
+/**
+ * NO ONE SHOULD USE THIS FUNCTION OTHER THAN THE MAINFRAME ON WINDOWS
+ */
+CMainFrame *CViews::GetMainFrame()
+{
+ return m_MainFrame;
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CViews::RecheckMainframeSizingMode()
+{
+ if (m_MainFrame != nullptr)
+ m_MainFrame->RecheckSizingMode();
+}
+
+//==============================================================================
+// Static
+//==============================================================================
+
+//=============================================================================
+/**
+ * Creates a palette and the associated view.
+ * @param inClass Should be RUNTIME_CLASS( CCLASS ) where CCLASS is a class that
+ * inherits from MFC::CView (must implement dynamic creation) and is the view
+ * that you want associated with the palette.
+ * @param inPalette Palette that you want the view attached to
+ * @param inParent Parent window or nullptr for top level windows
+ * @param inWindowTitle Title caption to appear on the title bar of the palette
+ * @param inShowWindow true to show the window after creation, false to hide it
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+void CViews::CreatePaletteAndView(CRuntimeClass *inClass, CStudioPaletteBar *inPalette,
+ CFrameWnd *inParent, Q3DStudio::CString inWindowTitle)
+{
+ CCreateContext theCreateContext;
+ memset(&theCreateContext, 0, sizeof(CCreateContext));
+ theCreateContext.m_pNewViewClass = inClass;
+ theCreateContext.m_pCurrentFrame = inParent;
+ theCreateContext.m_pCurrentDoc = nullptr;
+
+ inPalette->Create(::CString(inWindowTitle.GetMulti()), &theCreateContext,
+ CPaletteManager::GetUniquePaletteId(), inParent);
+}
+#endif
+
+//=============================================================================
+/**
+ * Creates a dialog and the associated view.
+ * @param inClass Should be RUNTIME_CLASS( CCLASS ) where CCLASS is a class that
+ * inherits from MFC::CView (must implement dynamic creation) and is the view
+ * that you want associated with the palette.
+ * @param inPalette Palette that you want the view attached to
+ * @param inParent Parent window or nullptr for top level windows
+ * @param inWindowTitle Title caption to appear on the title bar of the palette
+ * @param inShowWindow true to show the window after creation, false to hide it
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+void CViews::CreateDialogAndView(CRuntimeClass *inClass, CStudioDialog *inDialog,
+ CFrameWnd *inParent, Q3DStudio::CString inWindowTitle)
+{
+ CCreateContext theCreateContext;
+ memset(&theCreateContext, 0, sizeof(CCreateContext));
+ theCreateContext.m_pNewViewClass = inClass;
+ theCreateContext.m_pCurrentFrame = inParent;
+ theCreateContext.m_pCurrentDoc = nullptr;
+
+ inDialog->Create(::CString(inWindowTitle.GetMulti()), &theCreateContext, inParent);
+}
+#endif
diff --git a/src/Authoring/Studio/images.qrc b/src/Authoring/Studio/images.qrc
new file mode 100644
index 00000000..19cabdc1
--- /dev/null
+++ b/src/Authoring/Studio/images.qrc
@@ -0,0 +1,179 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/Action-MasterAction.png</file>
+ <file>images/Action-Trash-Disabled.png</file>
+ <file>images/Action-Trash-Disabled@2x.png</file>
+ <file>images/Action-Trash-Normal.png</file>
+ <file>images/Action-Trash-Normal@2x.png</file>
+ <file>images/add.png</file>
+ <file>images/add@2x.png</file>
+ <file>images/arrow.png</file>
+ <file>images/arrow@2x.png</file>
+ <file>images/arrow_down.png</file>
+ <file>images/arrow_down@2x.png</file>
+ <file>images/Asset-Alias-Normal.png</file>
+ <file>images/Asset-Alias-Normal@2x.png</file>
+ <file>images/Asset-Camera-Normal.png</file>
+ <file>images/Asset-Camera-Normal@2x.png</file>
+ <file>images/Asset-Component-Normal.png</file>
+ <file>images/Asset-Component-Normal@2x.png</file>
+ <file>images/Asset-Cone-Normal.png</file>
+ <file>images/Asset-Cone-Normal@2x.png</file>
+ <file>images/Asset-Cube-Normal.png</file>
+ <file>images/Asset-Cube-Normal@2x.png</file>
+ <file>images/Asset-Cylinder-Normal.png</file>
+ <file>images/Asset-Cylinder-Normal@2x.png</file>
+ <file>images/Asset-Group-Normal.png</file>
+ <file>images/Asset-Group-Normal@2x.png</file>
+ <file>images/Asset-Layer-Normal.png</file>
+ <file>images/Asset-Layer-Normal@2x.png</file>
+ <file>images/Asset-Light-Normal.png</file>
+ <file>images/Asset-Light-Normal@2x.png</file>
+ <file>images/Asset-Rectangle-Normal.png</file>
+ <file>images/Asset-Rectangle-Normal@2x.png</file>
+ <file>images/Asset-Sphere-Normal.png</file>
+ <file>images/Asset-Sphere-Normal@2x.png</file>
+ <file>images/Asset-Text-Normal.png</file>
+ <file>images/Asset-Text-Normal@2x.png</file>
+ <file>images/checkbox-checked.png</file>
+ <file>images/checkbox-unchecked.png</file>
+ <file>images/Inspector-AnimateToggle-Active.png</file>
+ <file>images/Inspector-AnimateToggle-Active@2x.png</file>
+ <file>images/Inspector-AnimateToggle-Normal.png</file>
+ <file>images/Inspector-AnimateToggle-Normal@2x.png</file>
+ <file>images/Objects-Behavior-Normal.png</file>
+ <file>images/Objects-Effect-Normal.png</file>
+ <file>images/Objects-Folder-Normal.png</file>
+ <file>images/Objects-Image-Normal.png</file>
+ <file>images/Objects-Layer-Normal.png</file>
+ <file>images/Objects-Layer-Normal@2x.png</file>
+ <file>images/Objects-Material-Normal.png</file>
+ <file>images/Objects-Model-Normal.png</file>
+ <file>images/Objects-Text-Normal.png</file>
+ <file>images/Objects-Text-Normal@2x.png</file>
+ <file>images/Slide-Active.png</file>
+ <file>images/Slide-Active@2x.png</file>
+ <file>images/Slide-Master-Active.png</file>
+ <file>images/Slide-Normal.png</file>
+ <file>images/Objects-Group-Normal.png</file>
+ <file>images/Objects-Group-Normal@2x.png</file>
+ <file>images/Objects-Light-Normal.png</file>
+ <file>images/Objects-Light-Normal@2x.png</file>
+ <file>images/Objects-Property-Normal.png</file>
+ <file>images/Objects-Property-Normal@2x.png</file>
+ <file>images/filter-shy-down.png</file>
+ <file>images/filter-shy-down@2x.png</file>
+ <file>images/filter-toggle-eye-down.png</file>
+ <file>images/filter-toggle-eye-down@2x.png</file>
+ <file>images/filter-toggle-eye-up.png</file>
+ <file>images/filter-toggle-eye-up@2x.png</file>
+ <file>images/PlaybackHead.png</file>
+ <file>images/PlaybackHead@2x.png</file>
+ <file>images/Toggle-HideShow.png</file>
+ <file>images/Toggle-HideShow@2x.png</file>
+ <file>images/obsolete_placeholder.png</file>
+ <file>images/empty-pixel.png</file>
+ <file>images/Toggle-Lock.png</file>
+ <file>images/Toggle-Lock@2x.png</file>
+ <file>images/Toggle-Shy.png</file>
+ <file>images/Toggle-Shy@2x.png</file>
+ <file>images/Toggle-Empty.png</file>
+ <file>images/Objects-Scene-Normal.png</file>
+ <file>images/Objects-Scene-Normal@2x.png</file>
+ <file>images/Action-Action.png</file>
+ <file>images/Action-ChildAction.png</file>
+ <file>images/Objects-Camera-Normal.png</file>
+ <file>images/timebarhandle-disabled-left.png</file>
+ <file>images/timebarhandle-disabled-right.png</file>
+ <file>images/timebarhandle-left.png</file>
+ <file>images/timebarhandle-right.png</file>
+ <file>images/Toggle-HideShow-disabled.png</file>
+ <file>images/Toggle-HideShow-disabled@2x.png</file>
+ <file>images/Objects-Alias-Normal.png</file>
+ <file>images/Objects-Alias-Normal@2x.png</file>
+ <file>images/Objects-Behavior-Normal@2x.png</file>
+ <file>images/Objects-Camera-Normal@2x.png</file>
+ <file>images/Objects-Component-Normal.png</file>
+ <file>images/Objects-Component-Normal@2x.png</file>
+ <file>images/Objects-Effect-Normal@2x.png</file>
+ <file>images/Objects-Folder-Normal@2x.png</file>
+ <file>images/Objects-Image-Normal@2.png</file>
+ <file>images/Objects-Material-Normal@2x.png</file>
+ <file>images/Objects-Model-Normal@2x.png</file>
+ <file>images/scrollbar-arrows-down-depressed.png</file>
+ <file>images/scrollbar-arrows-down-disabled.png</file>
+ <file>images/scrollbar-arrows-down-normal.png</file>
+ <file>images/scrollbar-arrows-left-depressed.png</file>
+ <file>images/scrollbar-arrows-left-disabled.png</file>
+ <file>images/scrollbar-arrows-left-normal.png</file>
+ <file>images/scrollbar-arrows-right-depressed.png</file>
+ <file>images/scrollbar-arrows-right-disabled.png</file>
+ <file>images/scrollbar-arrows-right-normal.png</file>
+ <file>images/scrollbar-arrows-up-depressed.png</file>
+ <file>images/scrollbar-arrows-up-disabled.png</file>
+ <file>images/scrollbar-arrows-up-normal.png</file>
+ <file>images/Keyframe-Master-Disabled.png</file>
+ <file>images/Keyframe-MasterDynamic-Normal.png</file>
+ <file>images/Keyframe-MasterDynamic-Selected.png</file>
+ <file>images/Keyframe-MasterLeft-disabled.png</file>
+ <file>images/Keyframe-MasterLeftDynamic-Normal.png</file>
+ <file>images/Keyframe-MasterLeftDynamic-Selected.png</file>
+ <file>images/Keyframe-MasterLeft-Normal.png</file>
+ <file>images/Keyframe-MasterLeft-Selected.png</file>
+ <file>images/Keyframe-Master-Normal.png</file>
+ <file>images/Keyframe-MasterRight-disabled.png</file>
+ <file>images/Keyframe-MasterRightDynamic-Normal.png</file>
+ <file>images/Keyframe-MasterRightDynamic-Selected.png</file>
+ <file>images/Keyframe-MasterRight-Normal.png</file>
+ <file>images/Keyframe-MasterRight-Selected.png</file>
+ <file>images/Keyframe-Master-Selected.png</file>
+ <file>images/Keyframe-Property-Disabled.png</file>
+ <file>images/Keyframe-PropertyDynamic-Normal.png</file>
+ <file>images/Keyframe-PropertyDynamic-Selected.png</file>
+ <file>images/Keyframe-Property-Normal.png</file>
+ <file>images/Keyframe-Property-Selected.png</file>
+ <file>images/Objects-Property-Disabled.png</file>
+ <file>images/Objects-Property-Disabled@2x.png</file>
+ <file>images/Action-ChildMasterAction.png</file>
+ <file>images/Action-ComponentAction.png</file>
+ <file>images/Action-ComponentMasterAction.png</file>
+ <file>images/breadcrumb_component_button.png</file>
+ <file>images/breadcrumb_component_colon_button.png</file>
+ <file>images/breadcrumb_component_grey_button.png</file>
+ <file>images/breadcrumb_component_scene.png</file>
+ <file>images/Insert-Left.png</file>
+ <file>images/Insert-Rearrange-Left.png</file>
+ <file>images/Insert-Rearrange-Right.png</file>
+ <file>images/Insert-Right.png</file>
+ <file>images/Objects-Alias-Disabled.png</file>
+ <file>images/Objects-Behavior-Disabled.png</file>
+ <file>images/Objects-Camera-Disabled.png</file>
+ <file>images/Objects-Component-Disabled.png</file>
+ <file>images/Objects-Effect-Disabled.png</file>
+ <file>images/Objects-Group-Disabled.png</file>
+ <file>images/Objects-Group-Disabled@2x.png</file>
+ <file>images/Objects-Image-Disabled.png</file>
+ <file>images/Objects-Layer-Disabled.png</file>
+ <file>images/Objects-Layer-Disabled@2x.png</file>
+ <file>images/Objects-Light-Disabled.png</file>
+ <file>images/Objects-Light-Disabled@2x.png</file>
+ <file>images/Objects-Material-Disabled.png</file>
+ <file>images/Objects-Model-Disabled.png</file>
+ <file>images/Objects-Scene-Disabled.png</file>
+ <file>images/Objects-Text-Disabled.png</file>
+ <file>images/Objects-Alias-Disabled@2x.png</file>
+ <file>images/Objects-Behavior-Disabled@2x.png</file>
+ <file>images/Objects-Camera-Disabled@2x.png</file>
+ <file>images/Objects-Component-Disabled@2x.png</file>
+ <file>images/Objects-Effect-Disabled@2x.png</file>
+ <file>images/Objects-Folder-Disabled.png</file>
+ <file>images/Objects-Folder-Disabled@2x.png</file>
+ <file>images/Objects-Image-Disabled@2x.png</file>
+ <file>images/Objects-Material-Disabled@2x.png</file>
+ <file>images/Objects-Model-Disabled@2x.png</file>
+ <file>images/Objects-Scene-Disabled@2x.png</file>
+ <file>images/Objects-Text-Disabled@2x.png</file>
+ <file>images/Slide-Master-Active@2x.png</file>
+ <file>images/Slide-Normal@2x.png</file>
+ </qresource>
+</RCC>
diff --git a/src/Authoring/Studio/images/Action-Action.png b/src/Authoring/Studio/images/Action-Action.png
new file mode 100644
index 00000000..4b8d9c8e
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-Action.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-ChildAction.png b/src/Authoring/Studio/images/Action-ChildAction.png
new file mode 100644
index 00000000..6589b104
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-ChildAction.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-ChildMasterAction.png b/src/Authoring/Studio/images/Action-ChildMasterAction.png
new file mode 100644
index 00000000..39159191
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-ChildMasterAction.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-ComponentAction.png b/src/Authoring/Studio/images/Action-ComponentAction.png
new file mode 100644
index 00000000..d7287f46
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-ComponentAction.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-ComponentMasterAction.png b/src/Authoring/Studio/images/Action-ComponentMasterAction.png
new file mode 100644
index 00000000..bb34a3da
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-ComponentMasterAction.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-MasterAction.png b/src/Authoring/Studio/images/Action-MasterAction.png
new file mode 100644
index 00000000..74f06661
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-MasterAction.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-Trash-Disabled.png b/src/Authoring/Studio/images/Action-Trash-Disabled.png
new file mode 100644
index 00000000..c175290d
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-Trash-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-Trash-Disabled@2x.png b/src/Authoring/Studio/images/Action-Trash-Disabled@2x.png
new file mode 100644
index 00000000..2793f0c2
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-Trash-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-Trash-Normal.png b/src/Authoring/Studio/images/Action-Trash-Normal.png
new file mode 100644
index 00000000..616a85a0
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-Trash-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Action-Trash-Normal@2x.png b/src/Authoring/Studio/images/Action-Trash-Normal@2x.png
new file mode 100644
index 00000000..1365907e
--- /dev/null
+++ b/src/Authoring/Studio/images/Action-Trash-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Alias-Normal.png b/src/Authoring/Studio/images/Asset-Alias-Normal.png
new file mode 100644
index 00000000..4a40aecf
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Alias-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Alias-Normal@2x.png b/src/Authoring/Studio/images/Asset-Alias-Normal@2x.png
new file mode 100644
index 00000000..6b14d31f
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Alias-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Camera-Normal.png b/src/Authoring/Studio/images/Asset-Camera-Normal.png
new file mode 100644
index 00000000..faa642c2
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Camera-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Camera-Normal@2x.png b/src/Authoring/Studio/images/Asset-Camera-Normal@2x.png
new file mode 100644
index 00000000..d69675e8
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Camera-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Component-Normal.png b/src/Authoring/Studio/images/Asset-Component-Normal.png
new file mode 100644
index 00000000..9b1fc237
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Component-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Component-Normal@2x.png b/src/Authoring/Studio/images/Asset-Component-Normal@2x.png
new file mode 100644
index 00000000..45b10cb5
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Component-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Cone-Normal.png b/src/Authoring/Studio/images/Asset-Cone-Normal.png
new file mode 100644
index 00000000..5b42abe9
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Cone-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Cone-Normal@2x.png b/src/Authoring/Studio/images/Asset-Cone-Normal@2x.png
new file mode 100644
index 00000000..4edac2fa
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Cone-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Cube-Normal.png b/src/Authoring/Studio/images/Asset-Cube-Normal.png
new file mode 100644
index 00000000..c858a011
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Cube-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Cube-Normal@2x.png b/src/Authoring/Studio/images/Asset-Cube-Normal@2x.png
new file mode 100644
index 00000000..07bfc514
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Cube-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Cylinder-Normal.png b/src/Authoring/Studio/images/Asset-Cylinder-Normal.png
new file mode 100644
index 00000000..99b8b418
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Cylinder-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Cylinder-Normal@2x.png b/src/Authoring/Studio/images/Asset-Cylinder-Normal@2x.png
new file mode 100644
index 00000000..887855e9
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Cylinder-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Group-Normal.png b/src/Authoring/Studio/images/Asset-Group-Normal.png
new file mode 100644
index 00000000..4575da6e
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Group-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Group-Normal@2x.png b/src/Authoring/Studio/images/Asset-Group-Normal@2x.png
new file mode 100644
index 00000000..162c008b
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Group-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Layer-Normal.png b/src/Authoring/Studio/images/Asset-Layer-Normal.png
new file mode 100644
index 00000000..e11e3d26
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Layer-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Layer-Normal@2x.png b/src/Authoring/Studio/images/Asset-Layer-Normal@2x.png
new file mode 100644
index 00000000..d479fca7
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Layer-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Light-Normal.png b/src/Authoring/Studio/images/Asset-Light-Normal.png
new file mode 100644
index 00000000..47bc8d89
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Light-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Light-Normal@2x.png b/src/Authoring/Studio/images/Asset-Light-Normal@2x.png
new file mode 100644
index 00000000..d36e0bf8
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Light-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Rectangle-Normal.png b/src/Authoring/Studio/images/Asset-Rectangle-Normal.png
new file mode 100644
index 00000000..dd904770
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Rectangle-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Rectangle-Normal@2x.png b/src/Authoring/Studio/images/Asset-Rectangle-Normal@2x.png
new file mode 100644
index 00000000..1ad5bc31
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Rectangle-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Sphere-Normal.png b/src/Authoring/Studio/images/Asset-Sphere-Normal.png
new file mode 100644
index 00000000..c53885ba
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Sphere-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Sphere-Normal@2x.png b/src/Authoring/Studio/images/Asset-Sphere-Normal@2x.png
new file mode 100644
index 00000000..e14312f1
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Sphere-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Text-Normal.png b/src/Authoring/Studio/images/Asset-Text-Normal.png
new file mode 100644
index 00000000..0ae00949
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Text-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Asset-Text-Normal@2x.png b/src/Authoring/Studio/images/Asset-Text-Normal@2x.png
new file mode 100644
index 00000000..734900e8
--- /dev/null
+++ b/src/Authoring/Studio/images/Asset-Text-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Insert-Left.png b/src/Authoring/Studio/images/Insert-Left.png
new file mode 100644
index 00000000..14871c90
--- /dev/null
+++ b/src/Authoring/Studio/images/Insert-Left.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Insert-Rearrange-Left.png b/src/Authoring/Studio/images/Insert-Rearrange-Left.png
new file mode 100644
index 00000000..7a0d2703
--- /dev/null
+++ b/src/Authoring/Studio/images/Insert-Rearrange-Left.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Insert-Rearrange-Right.png b/src/Authoring/Studio/images/Insert-Rearrange-Right.png
new file mode 100644
index 00000000..58bbc0c8
--- /dev/null
+++ b/src/Authoring/Studio/images/Insert-Rearrange-Right.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Insert-Right.png b/src/Authoring/Studio/images/Insert-Right.png
new file mode 100644
index 00000000..4393a84a
--- /dev/null
+++ b/src/Authoring/Studio/images/Insert-Right.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Inspector-AnimateToggle-Active.png b/src/Authoring/Studio/images/Inspector-AnimateToggle-Active.png
new file mode 100644
index 00000000..1ed0e731
--- /dev/null
+++ b/src/Authoring/Studio/images/Inspector-AnimateToggle-Active.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Inspector-AnimateToggle-Active@2x.png b/src/Authoring/Studio/images/Inspector-AnimateToggle-Active@2x.png
new file mode 100644
index 00000000..ef83fea8
--- /dev/null
+++ b/src/Authoring/Studio/images/Inspector-AnimateToggle-Active@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Inspector-AnimateToggle-Normal.png b/src/Authoring/Studio/images/Inspector-AnimateToggle-Normal.png
new file mode 100644
index 00000000..ff00f71c
--- /dev/null
+++ b/src/Authoring/Studio/images/Inspector-AnimateToggle-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Inspector-AnimateToggle-Normal@2x.png b/src/Authoring/Studio/images/Inspector-AnimateToggle-Normal@2x.png
new file mode 100644
index 00000000..dc1cee05
--- /dev/null
+++ b/src/Authoring/Studio/images/Inspector-AnimateToggle-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-Master-Disabled.png b/src/Authoring/Studio/images/Keyframe-Master-Disabled.png
new file mode 100644
index 00000000..7e66cd27
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-Master-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-Master-Normal.png b/src/Authoring/Studio/images/Keyframe-Master-Normal.png
new file mode 100644
index 00000000..9fb6281b
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-Master-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-Master-Selected.png b/src/Authoring/Studio/images/Keyframe-Master-Selected.png
new file mode 100644
index 00000000..5d3806ba
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-Master-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterDynamic-Normal.png b/src/Authoring/Studio/images/Keyframe-MasterDynamic-Normal.png
new file mode 100644
index 00000000..919c310f
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterDynamic-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterDynamic-Selected.png b/src/Authoring/Studio/images/Keyframe-MasterDynamic-Selected.png
new file mode 100644
index 00000000..7712d96f
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterDynamic-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterLeft-Normal.png b/src/Authoring/Studio/images/Keyframe-MasterLeft-Normal.png
new file mode 100644
index 00000000..bb198c49
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterLeft-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterLeft-Selected.png b/src/Authoring/Studio/images/Keyframe-MasterLeft-Selected.png
new file mode 100644
index 00000000..1fbd3e06
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterLeft-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterLeft-disabled.png b/src/Authoring/Studio/images/Keyframe-MasterLeft-disabled.png
new file mode 100644
index 00000000..46fb034f
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterLeft-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Normal.png b/src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Normal.png
new file mode 100644
index 00000000..2e8a3f1b
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Selected.png b/src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Selected.png
new file mode 100644
index 00000000..51d2be2e
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterLeftDynamic-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterRight-Normal.png b/src/Authoring/Studio/images/Keyframe-MasterRight-Normal.png
new file mode 100644
index 00000000..56bcacff
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterRight-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterRight-Selected.png b/src/Authoring/Studio/images/Keyframe-MasterRight-Selected.png
new file mode 100644
index 00000000..1d98fc59
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterRight-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterRight-disabled.png b/src/Authoring/Studio/images/Keyframe-MasterRight-disabled.png
new file mode 100644
index 00000000..2b1086a7
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterRight-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Normal.png b/src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Normal.png
new file mode 100644
index 00000000..105f61f4
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Selected.png b/src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Selected.png
new file mode 100644
index 00000000..5c706f5c
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-MasterRightDynamic-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-Property-Disabled.png b/src/Authoring/Studio/images/Keyframe-Property-Disabled.png
new file mode 100644
index 00000000..87e5dde9
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-Property-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-Property-Normal.png b/src/Authoring/Studio/images/Keyframe-Property-Normal.png
new file mode 100644
index 00000000..7afc5b09
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-Property-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-Property-Selected.png b/src/Authoring/Studio/images/Keyframe-Property-Selected.png
new file mode 100644
index 00000000..7eb45ab3
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-Property-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-PropertyDynamic-Normal.png b/src/Authoring/Studio/images/Keyframe-PropertyDynamic-Normal.png
new file mode 100644
index 00000000..2231a10c
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-PropertyDynamic-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Keyframe-PropertyDynamic-Selected.png b/src/Authoring/Studio/images/Keyframe-PropertyDynamic-Selected.png
new file mode 100644
index 00000000..02186956
--- /dev/null
+++ b/src/Authoring/Studio/images/Keyframe-PropertyDynamic-Selected.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Alias-Disabled.png b/src/Authoring/Studio/images/Objects-Alias-Disabled.png
new file mode 100644
index 00000000..85e6dd94
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Alias-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Alias-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Alias-Disabled@2x.png
new file mode 100644
index 00000000..6f9dffc3
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Alias-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Alias-Normal.png b/src/Authoring/Studio/images/Objects-Alias-Normal.png
new file mode 100644
index 00000000..c97c38f2
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Alias-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Alias-Normal@2x.png b/src/Authoring/Studio/images/Objects-Alias-Normal@2x.png
new file mode 100644
index 00000000..620608d8
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Alias-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Behavior-Disabled.png b/src/Authoring/Studio/images/Objects-Behavior-Disabled.png
new file mode 100644
index 00000000..a7c71f93
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Behavior-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Behavior-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Behavior-Disabled@2x.png
new file mode 100644
index 00000000..5ded4633
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Behavior-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Behavior-Normal.png b/src/Authoring/Studio/images/Objects-Behavior-Normal.png
new file mode 100644
index 00000000..0aa09e8f
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Behavior-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Behavior-Normal@2x.png b/src/Authoring/Studio/images/Objects-Behavior-Normal@2x.png
new file mode 100644
index 00000000..aa65ef2d
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Behavior-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Camera-Disabled.png b/src/Authoring/Studio/images/Objects-Camera-Disabled.png
new file mode 100644
index 00000000..5d87e29a
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Camera-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Camera-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Camera-Disabled@2x.png
new file mode 100644
index 00000000..47efdc5c
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Camera-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Camera-Normal.png b/src/Authoring/Studio/images/Objects-Camera-Normal.png
new file mode 100644
index 00000000..69f6e385
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Camera-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Camera-Normal@2x.png b/src/Authoring/Studio/images/Objects-Camera-Normal@2x.png
new file mode 100644
index 00000000..2c8bc946
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Camera-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Component-Disabled.png b/src/Authoring/Studio/images/Objects-Component-Disabled.png
new file mode 100644
index 00000000..f417a7a2
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Component-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Component-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Component-Disabled@2x.png
new file mode 100644
index 00000000..bfb5d2d2
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Component-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Component-Normal.png b/src/Authoring/Studio/images/Objects-Component-Normal.png
new file mode 100644
index 00000000..c95f7b4d
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Component-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Component-Normal@2x.png b/src/Authoring/Studio/images/Objects-Component-Normal@2x.png
new file mode 100644
index 00000000..e852f0a7
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Component-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Effect-Disabled.png b/src/Authoring/Studio/images/Objects-Effect-Disabled.png
new file mode 100644
index 00000000..0b0bde6e
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Effect-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Effect-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Effect-Disabled@2x.png
new file mode 100644
index 00000000..34eb98d8
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Effect-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Effect-Normal.png b/src/Authoring/Studio/images/Objects-Effect-Normal.png
new file mode 100644
index 00000000..d54948a4
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Effect-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Effect-Normal@2x.png b/src/Authoring/Studio/images/Objects-Effect-Normal@2x.png
new file mode 100644
index 00000000..c2edac40
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Effect-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Folder-Disabled.png b/src/Authoring/Studio/images/Objects-Folder-Disabled.png
new file mode 100644
index 00000000..67585cd3
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Folder-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Folder-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Folder-Disabled@2x.png
new file mode 100644
index 00000000..fc1fadc8
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Folder-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Folder-Normal.png b/src/Authoring/Studio/images/Objects-Folder-Normal.png
new file mode 100644
index 00000000..2cc95c46
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Folder-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Folder-Normal@2x.png b/src/Authoring/Studio/images/Objects-Folder-Normal@2x.png
new file mode 100644
index 00000000..44c2e3b6
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Folder-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Group-Disabled.png b/src/Authoring/Studio/images/Objects-Group-Disabled.png
new file mode 100644
index 00000000..0e4e6eaf
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Group-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Group-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Group-Disabled@2x.png
new file mode 100644
index 00000000..2feb6c6b
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Group-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Group-Normal.png b/src/Authoring/Studio/images/Objects-Group-Normal.png
new file mode 100644
index 00000000..3c22bb61
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Group-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Group-Normal@2x.png b/src/Authoring/Studio/images/Objects-Group-Normal@2x.png
new file mode 100644
index 00000000..286be9b8
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Group-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Image-Disabled.png b/src/Authoring/Studio/images/Objects-Image-Disabled.png
new file mode 100644
index 00000000..34654dae
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Image-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Image-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Image-Disabled@2x.png
new file mode 100644
index 00000000..2f1dfd5e
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Image-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Image-Normal.png b/src/Authoring/Studio/images/Objects-Image-Normal.png
new file mode 100644
index 00000000..3d657b8a
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Image-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Image-Normal@2.png b/src/Authoring/Studio/images/Objects-Image-Normal@2.png
new file mode 100644
index 00000000..c99df5d2
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Image-Normal@2.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Layer-Disabled.png b/src/Authoring/Studio/images/Objects-Layer-Disabled.png
new file mode 100644
index 00000000..c52e0340
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Layer-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Layer-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Layer-Disabled@2x.png
new file mode 100644
index 00000000..6fa6f7aa
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Layer-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Layer-Normal.png b/src/Authoring/Studio/images/Objects-Layer-Normal.png
new file mode 100644
index 00000000..d06bb2cd
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Layer-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Layer-Normal@2x.png b/src/Authoring/Studio/images/Objects-Layer-Normal@2x.png
new file mode 100644
index 00000000..532764ab
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Layer-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Light-Disabled.png b/src/Authoring/Studio/images/Objects-Light-Disabled.png
new file mode 100644
index 00000000..9fea9d3f
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Light-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Light-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Light-Disabled@2x.png
new file mode 100644
index 00000000..d476c9b3
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Light-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Light-Normal.png b/src/Authoring/Studio/images/Objects-Light-Normal.png
new file mode 100644
index 00000000..68fec179
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Light-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Light-Normal@2x.png b/src/Authoring/Studio/images/Objects-Light-Normal@2x.png
new file mode 100644
index 00000000..4b627f1d
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Light-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Material-Disabled.png b/src/Authoring/Studio/images/Objects-Material-Disabled.png
new file mode 100644
index 00000000..ec77957f
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Material-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Material-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Material-Disabled@2x.png
new file mode 100644
index 00000000..f9b216d0
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Material-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Material-Normal.png b/src/Authoring/Studio/images/Objects-Material-Normal.png
new file mode 100644
index 00000000..225bb4b5
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Material-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Material-Normal@2x.png b/src/Authoring/Studio/images/Objects-Material-Normal@2x.png
new file mode 100644
index 00000000..d51fd360
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Material-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Model-Disabled.png b/src/Authoring/Studio/images/Objects-Model-Disabled.png
new file mode 100644
index 00000000..ead6ede5
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Model-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Model-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Model-Disabled@2x.png
new file mode 100644
index 00000000..8c0f635a
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Model-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Model-Normal.png b/src/Authoring/Studio/images/Objects-Model-Normal.png
new file mode 100644
index 00000000..9e066414
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Model-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Model-Normal@2x.png b/src/Authoring/Studio/images/Objects-Model-Normal@2x.png
new file mode 100644
index 00000000..075663bf
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Model-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Property-Disabled.png b/src/Authoring/Studio/images/Objects-Property-Disabled.png
new file mode 100644
index 00000000..84c55833
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Property-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Property-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Property-Disabled@2x.png
new file mode 100644
index 00000000..15428fe9
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Property-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Property-Normal.png b/src/Authoring/Studio/images/Objects-Property-Normal.png
new file mode 100644
index 00000000..a75d0561
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Property-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Property-Normal@2x.png b/src/Authoring/Studio/images/Objects-Property-Normal@2x.png
new file mode 100644
index 00000000..e1cf503a
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Property-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Scene-Disabled.png b/src/Authoring/Studio/images/Objects-Scene-Disabled.png
new file mode 100644
index 00000000..a4aba973
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Scene-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Scene-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Scene-Disabled@2x.png
new file mode 100644
index 00000000..2d21542a
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Scene-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Scene-Normal.png b/src/Authoring/Studio/images/Objects-Scene-Normal.png
new file mode 100644
index 00000000..56253242
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Scene-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Scene-Normal@2x.png b/src/Authoring/Studio/images/Objects-Scene-Normal@2x.png
new file mode 100644
index 00000000..c963c77b
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Scene-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Text-Disabled.png b/src/Authoring/Studio/images/Objects-Text-Disabled.png
new file mode 100644
index 00000000..f8ba1b9a
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Text-Disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Text-Disabled@2x.png b/src/Authoring/Studio/images/Objects-Text-Disabled@2x.png
new file mode 100644
index 00000000..22cec550
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Text-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Text-Normal.png b/src/Authoring/Studio/images/Objects-Text-Normal.png
new file mode 100644
index 00000000..0ae00949
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Text-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Objects-Text-Normal@2x.png b/src/Authoring/Studio/images/Objects-Text-Normal@2x.png
new file mode 100644
index 00000000..734900e8
--- /dev/null
+++ b/src/Authoring/Studio/images/Objects-Text-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/PlaybackHead.png b/src/Authoring/Studio/images/PlaybackHead.png
new file mode 100644
index 00000000..ce001ad2
--- /dev/null
+++ b/src/Authoring/Studio/images/PlaybackHead.png
Binary files differ
diff --git a/src/Authoring/Studio/images/PlaybackHead@2x.png b/src/Authoring/Studio/images/PlaybackHead@2x.png
new file mode 100644
index 00000000..f1a579a7
--- /dev/null
+++ b/src/Authoring/Studio/images/PlaybackHead@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Slide-Active.png b/src/Authoring/Studio/images/Slide-Active.png
new file mode 100644
index 00000000..8ee8a8bd
--- /dev/null
+++ b/src/Authoring/Studio/images/Slide-Active.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Slide-Active@2x.png b/src/Authoring/Studio/images/Slide-Active@2x.png
new file mode 100644
index 00000000..8c2031e1
--- /dev/null
+++ b/src/Authoring/Studio/images/Slide-Active@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Slide-Master-Active.png b/src/Authoring/Studio/images/Slide-Master-Active.png
new file mode 100644
index 00000000..0672c3c0
--- /dev/null
+++ b/src/Authoring/Studio/images/Slide-Master-Active.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Slide-Master-Active@2x.png b/src/Authoring/Studio/images/Slide-Master-Active@2x.png
new file mode 100644
index 00000000..43baf38f
--- /dev/null
+++ b/src/Authoring/Studio/images/Slide-Master-Active@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Slide-Normal.png b/src/Authoring/Studio/images/Slide-Normal.png
new file mode 100644
index 00000000..bb44401c
--- /dev/null
+++ b/src/Authoring/Studio/images/Slide-Normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Slide-Normal@2x.png b/src/Authoring/Studio/images/Slide-Normal@2x.png
new file mode 100644
index 00000000..5f6bf90e
--- /dev/null
+++ b/src/Authoring/Studio/images/Slide-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-Empty.png b/src/Authoring/Studio/images/Toggle-Empty.png
new file mode 100644
index 00000000..3f6660c9
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-Empty.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-HideShow-disabled.png b/src/Authoring/Studio/images/Toggle-HideShow-disabled.png
new file mode 100644
index 00000000..fa28ed9c
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-HideShow-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-HideShow-disabled@2x.png b/src/Authoring/Studio/images/Toggle-HideShow-disabled@2x.png
new file mode 100644
index 00000000..e75f821f
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-HideShow-disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-HideShow.png b/src/Authoring/Studio/images/Toggle-HideShow.png
new file mode 100644
index 00000000..bfa3c734
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-HideShow.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-HideShow@2x.png b/src/Authoring/Studio/images/Toggle-HideShow@2x.png
new file mode 100644
index 00000000..5425b285
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-HideShow@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-Lock.png b/src/Authoring/Studio/images/Toggle-Lock.png
new file mode 100644
index 00000000..627fa7f7
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-Lock.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-Lock@2x.png b/src/Authoring/Studio/images/Toggle-Lock@2x.png
new file mode 100644
index 00000000..d1a6dfc4
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-Lock@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-Shy.png b/src/Authoring/Studio/images/Toggle-Shy.png
new file mode 100644
index 00000000..2b990ad3
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-Shy.png
Binary files differ
diff --git a/src/Authoring/Studio/images/Toggle-Shy@2x.png b/src/Authoring/Studio/images/Toggle-Shy@2x.png
new file mode 100644
index 00000000..1c9fa9f4
--- /dev/null
+++ b/src/Authoring/Studio/images/Toggle-Shy@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/add.png b/src/Authoring/Studio/images/add.png
new file mode 100644
index 00000000..efd65386
--- /dev/null
+++ b/src/Authoring/Studio/images/add.png
Binary files differ
diff --git a/src/Authoring/Studio/images/add@2x.png b/src/Authoring/Studio/images/add@2x.png
new file mode 100644
index 00000000..98fd8d80
--- /dev/null
+++ b/src/Authoring/Studio/images/add@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/arrow.png b/src/Authoring/Studio/images/arrow.png
new file mode 100644
index 00000000..40ebda88
--- /dev/null
+++ b/src/Authoring/Studio/images/arrow.png
Binary files differ
diff --git a/src/Authoring/Studio/images/arrow@2x.png b/src/Authoring/Studio/images/arrow@2x.png
new file mode 100644
index 00000000..1a21ee06
--- /dev/null
+++ b/src/Authoring/Studio/images/arrow@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/arrow_down.png b/src/Authoring/Studio/images/arrow_down.png
new file mode 100644
index 00000000..238f8b6f
--- /dev/null
+++ b/src/Authoring/Studio/images/arrow_down.png
Binary files differ
diff --git a/src/Authoring/Studio/images/arrow_down@2x.png b/src/Authoring/Studio/images/arrow_down@2x.png
new file mode 100644
index 00000000..831189b6
--- /dev/null
+++ b/src/Authoring/Studio/images/arrow_down@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/breadcrumb_component_button.png b/src/Authoring/Studio/images/breadcrumb_component_button.png
new file mode 100644
index 00000000..4f0cd4b5
--- /dev/null
+++ b/src/Authoring/Studio/images/breadcrumb_component_button.png
Binary files differ
diff --git a/src/Authoring/Studio/images/breadcrumb_component_colon_button.png b/src/Authoring/Studio/images/breadcrumb_component_colon_button.png
new file mode 100644
index 00000000..ff80c8b7
--- /dev/null
+++ b/src/Authoring/Studio/images/breadcrumb_component_colon_button.png
Binary files differ
diff --git a/src/Authoring/Studio/images/breadcrumb_component_grey_button.png b/src/Authoring/Studio/images/breadcrumb_component_grey_button.png
new file mode 100644
index 00000000..0db36558
--- /dev/null
+++ b/src/Authoring/Studio/images/breadcrumb_component_grey_button.png
Binary files differ
diff --git a/src/Authoring/Studio/images/breadcrumb_component_scene.png b/src/Authoring/Studio/images/breadcrumb_component_scene.png
new file mode 100644
index 00000000..f1c68fe6
--- /dev/null
+++ b/src/Authoring/Studio/images/breadcrumb_component_scene.png
Binary files differ
diff --git a/src/Authoring/Studio/images/checkbox-checked.png b/src/Authoring/Studio/images/checkbox-checked.png
new file mode 100644
index 00000000..f13b9aa5
--- /dev/null
+++ b/src/Authoring/Studio/images/checkbox-checked.png
Binary files differ
diff --git a/src/Authoring/Studio/images/checkbox-unchecked.png b/src/Authoring/Studio/images/checkbox-unchecked.png
new file mode 100644
index 00000000..7482c028
--- /dev/null
+++ b/src/Authoring/Studio/images/checkbox-unchecked.png
Binary files differ
diff --git a/src/Authoring/Studio/images/empty-pixel.png b/src/Authoring/Studio/images/empty-pixel.png
new file mode 100644
index 00000000..0ae92115
--- /dev/null
+++ b/src/Authoring/Studio/images/empty-pixel.png
Binary files differ
diff --git a/src/Authoring/Studio/images/filter-shy-down.png b/src/Authoring/Studio/images/filter-shy-down.png
new file mode 100644
index 00000000..2b990ad3
--- /dev/null
+++ b/src/Authoring/Studio/images/filter-shy-down.png
Binary files differ
diff --git a/src/Authoring/Studio/images/filter-shy-down@2x.png b/src/Authoring/Studio/images/filter-shy-down@2x.png
new file mode 100644
index 00000000..1c9fa9f4
--- /dev/null
+++ b/src/Authoring/Studio/images/filter-shy-down@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/filter-toggle-eye-down.png b/src/Authoring/Studio/images/filter-toggle-eye-down.png
new file mode 100644
index 00000000..fa28ed9c
--- /dev/null
+++ b/src/Authoring/Studio/images/filter-toggle-eye-down.png
Binary files differ
diff --git a/src/Authoring/Studio/images/filter-toggle-eye-down@2x.png b/src/Authoring/Studio/images/filter-toggle-eye-down@2x.png
new file mode 100644
index 00000000..e75f821f
--- /dev/null
+++ b/src/Authoring/Studio/images/filter-toggle-eye-down@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/filter-toggle-eye-up.png b/src/Authoring/Studio/images/filter-toggle-eye-up.png
new file mode 100644
index 00000000..bfa3c734
--- /dev/null
+++ b/src/Authoring/Studio/images/filter-toggle-eye-up.png
Binary files differ
diff --git a/src/Authoring/Studio/images/filter-toggle-eye-up@2x.png b/src/Authoring/Studio/images/filter-toggle-eye-up@2x.png
new file mode 100644
index 00000000..5425b285
--- /dev/null
+++ b/src/Authoring/Studio/images/filter-toggle-eye-up@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/images/obsolete_placeholder.png b/src/Authoring/Studio/images/obsolete_placeholder.png
new file mode 100644
index 00000000..4837e5f0
--- /dev/null
+++ b/src/Authoring/Studio/images/obsolete_placeholder.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-down-depressed.png b/src/Authoring/Studio/images/scrollbar-arrows-down-depressed.png
new file mode 100644
index 00000000..3c50a1a0
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-down-depressed.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-down-disabled.png b/src/Authoring/Studio/images/scrollbar-arrows-down-disabled.png
new file mode 100644
index 00000000..be0b4a3d
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-down-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-down-normal.png b/src/Authoring/Studio/images/scrollbar-arrows-down-normal.png
new file mode 100644
index 00000000..9e70abe1
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-down-normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-left-depressed.png b/src/Authoring/Studio/images/scrollbar-arrows-left-depressed.png
new file mode 100644
index 00000000..fde5c4e6
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-left-depressed.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-left-disabled.png b/src/Authoring/Studio/images/scrollbar-arrows-left-disabled.png
new file mode 100644
index 00000000..15fb43a5
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-left-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-left-normal.png b/src/Authoring/Studio/images/scrollbar-arrows-left-normal.png
new file mode 100644
index 00000000..9ecd27d4
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-left-normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-right-depressed.png b/src/Authoring/Studio/images/scrollbar-arrows-right-depressed.png
new file mode 100644
index 00000000..4f473c04
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-right-depressed.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-right-disabled.png b/src/Authoring/Studio/images/scrollbar-arrows-right-disabled.png
new file mode 100644
index 00000000..a32ea1cc
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-right-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-right-normal.png b/src/Authoring/Studio/images/scrollbar-arrows-right-normal.png
new file mode 100644
index 00000000..8ad8f45f
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-right-normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-up-depressed.png b/src/Authoring/Studio/images/scrollbar-arrows-up-depressed.png
new file mode 100644
index 00000000..74060ef8
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-up-depressed.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-up-disabled.png b/src/Authoring/Studio/images/scrollbar-arrows-up-disabled.png
new file mode 100644
index 00000000..ee9fbecc
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-up-disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/images/scrollbar-arrows-up-normal.png b/src/Authoring/Studio/images/scrollbar-arrows-up-normal.png
new file mode 100644
index 00000000..2174ba70
--- /dev/null
+++ b/src/Authoring/Studio/images/scrollbar-arrows-up-normal.png
Binary files differ
diff --git a/src/Authoring/Studio/images/timebarhandle-disabled-left.png b/src/Authoring/Studio/images/timebarhandle-disabled-left.png
new file mode 100644
index 00000000..a5c0e661
--- /dev/null
+++ b/src/Authoring/Studio/images/timebarhandle-disabled-left.png
Binary files differ
diff --git a/src/Authoring/Studio/images/timebarhandle-disabled-right.png b/src/Authoring/Studio/images/timebarhandle-disabled-right.png
new file mode 100644
index 00000000..a23ba5fe
--- /dev/null
+++ b/src/Authoring/Studio/images/timebarhandle-disabled-right.png
Binary files differ
diff --git a/src/Authoring/Studio/images/timebarhandle-left.png b/src/Authoring/Studio/images/timebarhandle-left.png
new file mode 100644
index 00000000..598b6151
--- /dev/null
+++ b/src/Authoring/Studio/images/timebarhandle-left.png
Binary files differ
diff --git a/src/Authoring/Studio/images/timebarhandle-right.png b/src/Authoring/Studio/images/timebarhandle-right.png
new file mode 100644
index 00000000..149d834a
--- /dev/null
+++ b/src/Authoring/Studio/images/timebarhandle-right.png
Binary files differ
diff --git a/src/Authoring/Studio/qt3dstudio.qrc b/src/Authoring/Studio/qt3dstudio.qrc
new file mode 100644
index 00000000..dba77f4a
--- /dev/null
+++ b/src/Authoring/Studio/qt3dstudio.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/">
+ <file>res/Tutorial/button_back.png</file>
+ <file>res/Tutorial/button_next.png</file>
+ <file>res/Tutorial/screens/1.png</file>
+ <file>res/Tutorial/screens/2.png</file>
+ <file>res/Tutorial/screens/3.png</file>
+ <file>res/Tutorial/screens/4.png</file>
+ <file>res/Tutorial/screens/5.png</file>
+ <file>res/Tutorial/screens/6.png</file>
+ <file>res/Tutorial/screens/7.png</file>
+ <file>res/Tutorial/button_back@2x.png</file>
+ <file>res/Tutorial/button_next@2x.png</file>
+ <file alias="res/strings/Static.stro">English.lproj/Strings/Static.stro</file>
+ </qresource>
+</RCC>
diff --git a/src/Authoring/Studio/remoteproject.cpp b/src/Authoring/Studio/remoteproject.cpp
new file mode 100644
index 00000000..f1b0cfe1
--- /dev/null
+++ b/src/Authoring/Studio/remoteproject.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "remoteproject.h"
+
+#include <QtCore/qpair.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qdiriterator.h>
+#include <QtWidgets/qinputdialog.h>
+#include <QtWidgets/qmessagebox.h>
+#include <QtWidgets/qdialog.h>
+#include <QtWidgets/qlabel.h>
+#include <QtWidgets/qgridlayout.h>
+#include <QtWidgets/qdialogbuttonbox.h>
+
+class ConnectionDialog : public QDialog
+{
+public:
+ static QPair<QString, int> getInfo(QWidget *parent);
+
+private:
+ ConnectionDialog(QWidget *parent);
+ QLineEdit *m_hostLineEdit = nullptr;
+ QLineEdit *m_portLineEdit = nullptr;
+};
+
+ConnectionDialog::ConnectionDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_hostLineEdit = new QLineEdit(this);
+ QLabel *hostLabel = new QLabel(tr("Address:"));
+ hostLabel->setBuddy(m_hostLineEdit);
+
+ m_portLineEdit = new QLineEdit(this);
+ m_portLineEdit->setText("36000");
+ QLabel *portLabel = new QLabel(tr("Port:"));
+ portLabel->setBuddy(m_portLineEdit);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(
+ QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
+
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ QGridLayout *mainLayout = new QGridLayout(this);
+ mainLayout->addWidget(hostLabel, 0, 0);
+ mainLayout->addWidget(m_hostLineEdit, 0, 1);
+ mainLayout->addWidget(portLabel, 1, 0);
+ mainLayout->addWidget(m_portLineEdit, 1, 1);
+ mainLayout->addWidget(buttonBox, 3, 0, 1, 2);
+
+ setWindowTitle(tr("Connect to Device"));
+ m_hostLineEdit->setFocus();
+}
+
+QPair<QString, int> ConnectionDialog::getInfo(QWidget *parent)
+{
+ ConnectionDialog dialog(parent);
+ if (!dialog.exec())
+ return QPair<QString, int>();
+
+ return qMakePair(dialog.m_hostLineEdit->text(),
+ dialog.m_portLineEdit->text().toInt());
+}
+
+RemoteProject::RemoteProject(QWidget *parent)
+ : QObject(parent)
+ , m_tcpSocket(0)
+ , m_mainWindow(parent)
+{
+}
+
+void RemoteProject::connect()
+{
+ if (isConnected())
+ return;
+
+ delete m_tcpSocket;
+ m_tcpSocket = new QTcpSocket(this);
+
+ QObject::connect(m_tcpSocket, &QTcpSocket::connected, this,
+ &RemoteProject::checkConnection);
+ QObject::connect(m_tcpSocket, &QTcpSocket::disconnected, this,
+ &RemoteProject::checkConnection);
+ QObject::connect(m_tcpSocket,
+ static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>
+ (&QAbstractSocket::error),
+ this, &RemoteProject::connectionError);
+
+ QPair<QString, int> info = ConnectionDialog::getInfo(m_mainWindow);
+
+ m_tcpSocket->connectToHost(info.first, info.second);
+ if (!m_tcpSocket->waitForConnected(2000)) {
+ m_tcpSocket->abort();
+ checkConnection();
+ }
+}
+
+void RemoteProject::disconnect()
+{
+ Q_ASSERT(m_tcpSocket);
+ m_tcpSocket->disconnectFromHost();
+}
+
+bool RemoteProject::isConnected() const
+{
+ return m_tcpSocket && m_tcpSocket->state()
+ == QAbstractSocket::ConnectedState;
+}
+
+void RemoteProject::checkConnection()
+{
+ Q_EMIT connectionChanged(isConnected());
+}
+
+void RemoteProject::connectionError()
+{
+ if (m_tcpSocket) {
+ QMessageBox::warning(m_mainWindow, tr("Connect to Device"),
+ tr("Device connection error: ") + m_tcpSocket->errorString());
+ }
+ Q_EMIT connectionChanged(isConnected());
+}
+
+void RemoteProject::streamProject(const QString &projectFile)
+{
+ Q_ASSERT(isConnected());
+ if (!isConnected())
+ return;
+
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_5_8);
+
+ const QFileInfo fileInfo(projectFile);
+ if (!fileInfo.exists()) {
+ qWarning() << "failed to find file " << projectFile;
+ return;
+ }
+
+ const QDir projectDirectory(fileInfo.absolutePath());
+
+ // The file to be loaded
+ const QString relativePath
+ = projectDirectory.relativeFilePath(fileInfo.filePath());
+
+ int fileCount = 0;
+ QDirIterator it(fileInfo.absolutePath(), QDir::Files,
+ QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ const QString filePath = it.next();
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "could not open file " << filePath;
+ return;
+ }
+
+ fileCount++;
+ const QString relativePath = projectDirectory.relativeFilePath(filePath);
+ const QByteArray payload = file.readAll();
+ out << relativePath;
+ out << payload;
+ }
+
+ QByteArray metaBlock;
+ QDataStream metaOut(&metaBlock, QIODevice::WriteOnly);
+ metaOut.setVersion(QDataStream::Qt_5_8);
+ metaOut << block.size();
+ metaOut << fileCount;
+ metaOut << relativePath;
+
+ m_tcpSocket->write(metaBlock);
+ m_tcpSocket->write(block);
+}
diff --git a/src/Authoring/Studio/remoteproject.h b/src/Authoring/Studio/remoteproject.h
new file mode 100644
index 00000000..9aeb096e
--- /dev/null
+++ b/src/Authoring/Studio/remoteproject.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REMOTEPROJECT_H
+#define REMOTEPROJECT_H
+
+#include <QtCore/qobject.h>
+#include <QtWidgets/qwidget.h>
+#include <QtNetwork/qtcpsocket.h>
+
+class RemoteProject : public QObject
+{
+ Q_OBJECT
+public:
+ explicit RemoteProject(QWidget *parent);
+
+ void connect();
+ void disconnect();
+ bool isConnected() const;
+
+ void streamProject(const QString &);
+
+public Q_SLOTS:
+ void checkConnection();
+ void connectionError();
+
+Q_SIGNALS:
+ void connectionChanged(bool) const;
+
+private:
+ QTcpSocket *m_tcpSocket;
+ QWidget *m_mainWindow;
+};
+
+#endif // REMOTEPROJECT_H
diff --git a/src/Authoring/Studio/res/About Icon.bmp b/src/Authoring/Studio/res/About Icon.bmp
new file mode 100644
index 00000000..97764f42
--- /dev/null
+++ b/src/Authoring/Studio/res/About Icon.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/Flippy-Right.bmp b/src/Authoring/Studio/res/Flippy-Right.bmp
new file mode 100644
index 00000000..e4471ec6
--- /dev/null
+++ b/src/Authoring/Studio/res/Flippy-Right.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/Flippy-down.bmp b/src/Authoring/Studio/res/Flippy-down.bmp
new file mode 100644
index 00000000..4c1dd0d2
--- /dev/null
+++ b/src/Authoring/Studio/res/Flippy-down.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/Studio.ico b/src/Authoring/Studio/res/Studio.ico
new file mode 100644
index 00000000..0911ac1f
--- /dev/null
+++ b/src/Authoring/Studio/res/Studio.ico
Binary files differ
diff --git a/src/Authoring/Studio/res/Studio.manifest b/src/Authoring/Studio/res/Studio.manifest
new file mode 100644
index 00000000..6386fac9
--- /dev/null
+++ b/src/Authoring/Studio/res/Studio.manifest
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+ version="1.0.0.0"
+ processorArchitecture="X86"
+ name="Microsoft.Windows.Studio"
+ type="win32"
+/>
+<description>Your app description here</description>
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="X86"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/src/Authoring/Studio/res/Studio.png b/src/Authoring/Studio/res/Studio.png
new file mode 100644
index 00000000..11c6e526
--- /dev/null
+++ b/src/Authoring/Studio/res/Studio.png
Binary files differ
diff --git a/src/Authoring/Studio/res/StudioDoc.ico b/src/Authoring/Studio/res/StudioDoc.ico
new file mode 100644
index 00000000..0d531110
--- /dev/null
+++ b/src/Authoring/Studio/res/StudioDoc.ico
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-00.png b/src/Authoring/Studio/res/Toolbar-00.png
new file mode 100644
index 00000000..4111f8f0
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-00.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-01.png b/src/Authoring/Studio/res/Toolbar-01.png
new file mode 100644
index 00000000..76e3b5c2
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-01.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-02.png b/src/Authoring/Studio/res/Toolbar-02.png
new file mode 100644
index 00000000..3cd03094
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-02.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-03.png b/src/Authoring/Studio/res/Toolbar-03.png
new file mode 100644
index 00000000..3cde7c2e
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-03.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-04.png b/src/Authoring/Studio/res/Toolbar-04.png
new file mode 100644
index 00000000..3e04587b
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-04.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-05.png b/src/Authoring/Studio/res/Toolbar-05.png
new file mode 100644
index 00000000..8b4dbb5c
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-05.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-06.png b/src/Authoring/Studio/res/Toolbar-06.png
new file mode 100644
index 00000000..b4cdcc3c
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-06.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar-07.png b/src/Authoring/Studio/res/Toolbar-07.png
new file mode 100644
index 00000000..27e904f8
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar-07.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Toolbar.bmp b/src/Authoring/Studio/res/Toolbar.bmp
new file mode 100644
index 00000000..8b7a3424
--- /dev/null
+++ b/src/Authoring/Studio/res/Toolbar.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/button_back.png b/src/Authoring/Studio/res/Tutorial/button_back.png
new file mode 100644
index 00000000..8113df5b
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/button_back.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/button_back@2x.png b/src/Authoring/Studio/res/Tutorial/button_back@2x.png
new file mode 100644
index 00000000..ec6a2f13
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/button_back@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/button_next.png b/src/Authoring/Studio/res/Tutorial/button_next.png
new file mode 100644
index 00000000..857dcada
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/button_next.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/button_next@2x.png b/src/Authoring/Studio/res/Tutorial/button_next@2x.png
new file mode 100644
index 00000000..f32c4f26
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/button_next@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/1.png b/src/Authoring/Studio/res/Tutorial/screens/1.png
new file mode 100644
index 00000000..028f939f
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/1.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/2.png b/src/Authoring/Studio/res/Tutorial/screens/2.png
new file mode 100644
index 00000000..9ba67e3b
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/2.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/3.png b/src/Authoring/Studio/res/Tutorial/screens/3.png
new file mode 100644
index 00000000..849dfce7
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/3.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/4.png b/src/Authoring/Studio/res/Tutorial/screens/4.png
new file mode 100644
index 00000000..4933f401
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/4.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/5.png b/src/Authoring/Studio/res/Tutorial/screens/5.png
new file mode 100644
index 00000000..26adcf4b
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/5.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/6.png b/src/Authoring/Studio/res/Tutorial/screens/6.png
new file mode 100644
index 00000000..25b7a5bf
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/6.png
Binary files differ
diff --git a/src/Authoring/Studio/res/Tutorial/screens/7.png b/src/Authoring/Studio/res/Tutorial/screens/7.png
new file mode 100644
index 00000000..9ed864a3
--- /dev/null
+++ b/src/Authoring/Studio/res/Tutorial/screens/7.png
Binary files differ
diff --git a/src/Authoring/Studio/res/arrow_down.png b/src/Authoring/Studio/res/arrow_down.png
new file mode 100644
index 00000000..b6cfcf77
--- /dev/null
+++ b/src/Authoring/Studio/res/arrow_down.png
Binary files differ
diff --git a/src/Authoring/Studio/res/arrow_down@2x.png b/src/Authoring/Studio/res/arrow_down@2x.png
new file mode 100644
index 00000000..5c409dcb
--- /dev/null
+++ b/src/Authoring/Studio/res/arrow_down@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_grayed_out.bmp b/src/Authoring/Studio/res/client_tools_grayed_out.bmp
new file mode 100644
index 00000000..da15cc18
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_grayed_out.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-00.png b/src/Authoring/Studio/res/client_tools_hi_color-00.png
new file mode 100644
index 00000000..f466a1c3
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-00.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-00@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-00@2x.png
new file mode 100644
index 00000000..0b68e6b3
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-00@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-01.png b/src/Authoring/Studio/res/client_tools_hi_color-01.png
new file mode 100644
index 00000000..aad1b000
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-01.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-01@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-01@2x.png
new file mode 100644
index 00000000..e9589689
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-01@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-02.png b/src/Authoring/Studio/res/client_tools_hi_color-02.png
new file mode 100644
index 00000000..871a5e7d
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-02.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-02@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-02@2x.png
new file mode 100644
index 00000000..235d6804
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-02@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-03.png b/src/Authoring/Studio/res/client_tools_hi_color-03.png
new file mode 100644
index 00000000..68a7848a
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-03.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-03@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-03@2x.png
new file mode 100644
index 00000000..bc861678
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-03@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-04.png b/src/Authoring/Studio/res/client_tools_hi_color-04.png
new file mode 100644
index 00000000..0a2a7bc9
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-04.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-04@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-04@2x.png
new file mode 100644
index 00000000..bdf10c1f
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-04@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-05.png b/src/Authoring/Studio/res/client_tools_hi_color-05.png
new file mode 100644
index 00000000..de315cab
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-05.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-05@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-05@2x.png
new file mode 100644
index 00000000..89ba3fba
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-05@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-06.png b/src/Authoring/Studio/res/client_tools_hi_color-06.png
new file mode 100644
index 00000000..eeb93638
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-06.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color-06@2x.png b/src/Authoring/Studio/res/client_tools_hi_color-06@2x.png
new file mode 100644
index 00000000..5fe71abb
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color-06@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_hi_color.bmp b/src/Authoring/Studio/res/client_tools_hi_color.bmp
new file mode 100644
index 00000000..50f90ab7
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_hi_color.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/client_tools_low_color.bmp b/src/Authoring/Studio/res/client_tools_low_color.bmp
new file mode 100644
index 00000000..7dccd64e
--- /dev/null
+++ b/src/Authoring/Studio/res/client_tools_low_color.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/cursors.bmp b/src/Authoring/Studio/res/cursors.bmp
new file mode 100644
index 00000000..dff7330e
--- /dev/null
+++ b/src/Authoring/Studio/res/cursors.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/edit_camera_pan.png b/src/Authoring/Studio/res/edit_camera_pan.png
new file mode 100644
index 00000000..9248a875
--- /dev/null
+++ b/src/Authoring/Studio/res/edit_camera_pan.png
Binary files differ
diff --git a/src/Authoring/Studio/res/edit_camera_rot.png b/src/Authoring/Studio/res/edit_camera_rot.png
new file mode 100644
index 00000000..55c6ddac
--- /dev/null
+++ b/src/Authoring/Studio/res/edit_camera_rot.png
Binary files differ
diff --git a/src/Authoring/Studio/res/edit_camera_zoom.png b/src/Authoring/Studio/res/edit_camera_zoom.png
new file mode 100644
index 00000000..46f69c43
--- /dev/null
+++ b/src/Authoring/Studio/res/edit_camera_zoom.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_disabled.bmp b/src/Authoring/Studio/res/editcamera_tools_disabled.bmp
new file mode 100644
index 00000000..53709e04
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_disabled.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-00.png b/src/Authoring/Studio/res/editcamera_tools_hi-00.png
new file mode 100644
index 00000000..ad07bf8f
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-00.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-00@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-00@2x.png
new file mode 100644
index 00000000..d8c5fc46
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-00@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-00_disabled.png b/src/Authoring/Studio/res/editcamera_tools_hi-00_disabled.png
new file mode 100644
index 00000000..f8499e9d
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-00_disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-00_disabled@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-00_disabled@2x.png
new file mode 100644
index 00000000..96564a1c
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-00_disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-01.png b/src/Authoring/Studio/res/editcamera_tools_hi-01.png
new file mode 100644
index 00000000..10b16c6d
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-01.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-01@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-01@2x.png
new file mode 100644
index 00000000..b872a674
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-01@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-01_disabled.png b/src/Authoring/Studio/res/editcamera_tools_hi-01_disabled.png
new file mode 100644
index 00000000..ce5d85d2
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-01_disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-01_disabled@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-01_disabled@2x.png
new file mode 100644
index 00000000..a4a93e53
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-01_disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-02.png b/src/Authoring/Studio/res/editcamera_tools_hi-02.png
new file mode 100644
index 00000000..77b5a93e
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-02.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-02@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-02@2x.png
new file mode 100644
index 00000000..13b2ce61
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-02@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-02_disabled.png b/src/Authoring/Studio/res/editcamera_tools_hi-02_disabled.png
new file mode 100644
index 00000000..a21cea23
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-02_disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-02_disabled@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-02_disabled@2x.png
new file mode 100644
index 00000000..bba1b104
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-02_disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-03.png b/src/Authoring/Studio/res/editcamera_tools_hi-03.png
new file mode 100644
index 00000000..c8929b76
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-03.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-03@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-03@2x.png
new file mode 100644
index 00000000..26292608
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-03@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-03_disabled.png b/src/Authoring/Studio/res/editcamera_tools_hi-03_disabled.png
new file mode 100644
index 00000000..db8944b2
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-03_disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-03_disabled@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-03_disabled@2x.png
new file mode 100644
index 00000000..15904fee
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-03_disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-04.png b/src/Authoring/Studio/res/editcamera_tools_hi-04.png
new file mode 100644
index 00000000..22da1b6d
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-04.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-04@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-04@2x.png
new file mode 100644
index 00000000..9110519b
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-04@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-04_disabled.png b/src/Authoring/Studio/res/editcamera_tools_hi-04_disabled.png
new file mode 100644
index 00000000..1d9e0ac0
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-04_disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-04_disabled@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-04_disabled@2x.png
new file mode 100644
index 00000000..0a3f5527
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-04_disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-05.png b/src/Authoring/Studio/res/editcamera_tools_hi-05.png
new file mode 100644
index 00000000..147f8e29
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-05.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-05@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-05@2x.png
new file mode 100644
index 00000000..844a61e4
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-05@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-05_disabled.png b/src/Authoring/Studio/res/editcamera_tools_hi-05_disabled.png
new file mode 100644
index 00000000..ee55b391
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-05_disabled.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi-05_disabled@2x.png b/src/Authoring/Studio/res/editcamera_tools_hi-05_disabled@2x.png
new file mode 100644
index 00000000..072be7ed
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi-05_disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_hi.bmp b/src/Authoring/Studio/res/editcamera_tools_hi.bmp
new file mode 100644
index 00000000..c2b73a43
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_hi.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/editcamera_tools_low.bmp b/src/Authoring/Studio/res/editcamera_tools_low.bmp
new file mode 100644
index 00000000..66bf41a4
--- /dev/null
+++ b/src/Authoring/Studio/res/editcamera_tools_low.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/group_move.png b/src/Authoring/Studio/res/group_move.png
new file mode 100644
index 00000000..d7d06770
--- /dev/null
+++ b/src/Authoring/Studio/res/group_move.png
Binary files differ
diff --git a/src/Authoring/Studio/res/group_rotate.png b/src/Authoring/Studio/res/group_rotate.png
new file mode 100644
index 00000000..23a3eb3e
--- /dev/null
+++ b/src/Authoring/Studio/res/group_rotate.png
Binary files differ
diff --git a/src/Authoring/Studio/res/group_scale.png b/src/Authoring/Studio/res/group_scale.png
new file mode 100644
index 00000000..64024dfe
--- /dev/null
+++ b/src/Authoring/Studio/res/group_scale.png
Binary files differ
diff --git a/src/Authoring/Studio/res/item_move.png b/src/Authoring/Studio/res/item_move.png
new file mode 100644
index 00000000..d7b923bf
--- /dev/null
+++ b/src/Authoring/Studio/res/item_move.png
Binary files differ
diff --git a/src/Authoring/Studio/res/item_rotate.png b/src/Authoring/Studio/res/item_rotate.png
new file mode 100644
index 00000000..514c567c
--- /dev/null
+++ b/src/Authoring/Studio/res/item_rotate.png
Binary files differ
diff --git a/src/Authoring/Studio/res/item_scale.png b/src/Authoring/Studio/res/item_scale.png
new file mode 100644
index 00000000..6ef8acdb
--- /dev/null
+++ b/src/Authoring/Studio/res/item_scale.png
Binary files differ
diff --git a/src/Authoring/Studio/res/keyframe.bmp b/src/Authoring/Studio/res/keyframe.bmp
new file mode 100644
index 00000000..39a5fa17
--- /dev/null
+++ b/src/Authoring/Studio/res/keyframe.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/library_buttons_hi_color.bmp b/src/Authoring/Studio/res/library_buttons_hi_color.bmp
new file mode 100644
index 00000000..b648bcae
--- /dev/null
+++ b/src/Authoring/Studio/res/library_buttons_hi_color.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/library_buttons_low_color.bmp b/src/Authoring/Studio/res/library_buttons_low_color.bmp
new file mode 100644
index 00000000..682f3a2c
--- /dev/null
+++ b/src/Authoring/Studio/res/library_buttons_low_color.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/libtoolb.bmp b/src/Authoring/Studio/res/libtoolb.bmp
new file mode 100644
index 00000000..2a07520a
--- /dev/null
+++ b/src/Authoring/Studio/res/libtoolb.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/menubtn_down.bmp b/src/Authoring/Studio/res/menubtn_down.bmp
new file mode 100644
index 00000000..84df200b
--- /dev/null
+++ b/src/Authoring/Studio/res/menubtn_down.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/menubtn_normal.bmp b/src/Authoring/Studio/res/menubtn_normal.bmp
new file mode 100644
index 00000000..f2357600
--- /dev/null
+++ b/src/Authoring/Studio/res/menubtn_normal.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/menubtn_selected.bmp b/src/Authoring/Studio/res/menubtn_selected.bmp
new file mode 100644
index 00000000..7bc4618d
--- /dev/null
+++ b/src/Authoring/Studio/res/menubtn_selected.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/menuedit.bmp b/src/Authoring/Studio/res/menuedit.bmp
new file mode 100644
index 00000000..de0869ad
--- /dev/null
+++ b/src/Authoring/Studio/res/menuedit.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/menutool.bmp b/src/Authoring/Studio/res/menutool.bmp
new file mode 100644
index 00000000..73b54017
--- /dev/null
+++ b/src/Authoring/Studio/res/menutool.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/open_dialog.png b/src/Authoring/Studio/res/open_dialog.png
new file mode 100644
index 00000000..c7e74ef0
--- /dev/null
+++ b/src/Authoring/Studio/res/open_dialog.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_grayed.bmp b/src/Authoring/Studio/res/playback_tools_grayed.bmp
new file mode 100644
index 00000000..0225b6db
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_grayed.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_hi.bmp b/src/Authoring/Studio/res/playback_tools_hi.bmp
new file mode 100644
index 00000000..2047ac6b
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_hi.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-00.png b/src/Authoring/Studio/res/playback_tools_low-00.png
new file mode 100644
index 00000000..d7cae98d
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-00.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-00@2x.png b/src/Authoring/Studio/res/playback_tools_low-00@2x.png
new file mode 100644
index 00000000..88d6cf17
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-00@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-01.png b/src/Authoring/Studio/res/playback_tools_low-01.png
new file mode 100644
index 00000000..bf4d7f59
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-01.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-01@2x.png b/src/Authoring/Studio/res/playback_tools_low-01@2x.png
new file mode 100644
index 00000000..8230c6e8
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-01@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-02.png b/src/Authoring/Studio/res/playback_tools_low-02.png
new file mode 100644
index 00000000..471b2573
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-02.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-02@2x.png b/src/Authoring/Studio/res/playback_tools_low-02@2x.png
new file mode 100644
index 00000000..02370d25
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-02@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-03.png b/src/Authoring/Studio/res/playback_tools_low-03.png
new file mode 100644
index 00000000..5c5f9018
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-03.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low-03@2x.png b/src/Authoring/Studio/res/playback_tools_low-03@2x.png
new file mode 100644
index 00000000..e6fe8e10
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low-03@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/playback_tools_low.bmp b/src/Authoring/Studio/res/playback_tools_low.bmp
new file mode 100644
index 00000000..cb9b6b29
--- /dev/null
+++ b/src/Authoring/Studio/res/playback_tools_low.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/prefstab-00.png b/src/Authoring/Studio/res/prefstab-00.png
new file mode 100644
index 00000000..8a452d15
--- /dev/null
+++ b/src/Authoring/Studio/res/prefstab-00.png
Binary files differ
diff --git a/src/Authoring/Studio/res/prefstab-00@2x.png b/src/Authoring/Studio/res/prefstab-00@2x.png
new file mode 100644
index 00000000..5703d0be
--- /dev/null
+++ b/src/Authoring/Studio/res/prefstab-00@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/prefstab-01.png b/src/Authoring/Studio/res/prefstab-01.png
new file mode 100644
index 00000000..35c99cea
--- /dev/null
+++ b/src/Authoring/Studio/res/prefstab-01.png
Binary files differ
diff --git a/src/Authoring/Studio/res/prefstab-01@2x.png b/src/Authoring/Studio/res/prefstab-01@2x.png
new file mode 100644
index 00000000..4c35e2b0
--- /dev/null
+++ b/src/Authoring/Studio/res/prefstab-01@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/prefstab.bmp b/src/Authoring/Studio/res/prefstab.bmp
new file mode 100644
index 00000000..3201d15e
--- /dev/null
+++ b/src/Authoring/Studio/res/prefstab.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/preview_tools.bmp b/src/Authoring/Studio/res/preview_tools.bmp
new file mode 100644
index 00000000..2cfdbfd9
--- /dev/null
+++ b/src/Authoring/Studio/res/preview_tools.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/project-icon-new.bmp b/src/Authoring/Studio/res/project-icon-new.bmp
new file mode 100644
index 00000000..01123652
--- /dev/null
+++ b/src/Authoring/Studio/res/project-icon-new.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/project-icon-open.bmp b/src/Authoring/Studio/res/project-icon-open.bmp
new file mode 100644
index 00000000..50b279f7
--- /dev/null
+++ b/src/Authoring/Studio/res/project-icon-open.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/qt3ds_header.bmp b/src/Authoring/Studio/res/qt3ds_header.bmp
new file mode 100644
index 00000000..cfe81cc2
--- /dev/null
+++ b/src/Authoring/Studio/res/qt3ds_header.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/separator.png b/src/Authoring/Studio/res/separator.png
new file mode 100644
index 00000000..c86aac17
--- /dev/null
+++ b/src/Authoring/Studio/res/separator.png
Binary files differ
diff --git a/src/Authoring/Studio/res/separator@2x.png b/src/Authoring/Studio/res/separator@2x.png
new file mode 100644
index 00000000..052003a4
--- /dev/null
+++ b/src/Authoring/Studio/res/separator@2x.png
Binary files differ
diff --git a/src/Authoring/Studio/res/stmtool.bmp b/src/Authoring/Studio/res/stmtool.bmp
new file mode 100644
index 00000000..71ed95fc
--- /dev/null
+++ b/src/Authoring/Studio/res/stmtool.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/storagep.bmp b/src/Authoring/Studio/res/storagep.bmp
new file mode 100644
index 00000000..d784a3dc
--- /dev/null
+++ b/src/Authoring/Studio/res/storagep.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/tmchmenu.bmp b/src/Authoring/Studio/res/tmchmenu.bmp
new file mode 100644
index 00000000..329bbf96
--- /dev/null
+++ b/src/Authoring/Studio/res/tmchmenu.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/tmlntool.bmp b/src/Authoring/Studio/res/tmlntool.bmp
new file mode 100644
index 00000000..6678d093
--- /dev/null
+++ b/src/Authoring/Studio/res/tmlntool.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/tmtbmenu.bmp b/src/Authoring/Studio/res/tmtbmenu.bmp
new file mode 100644
index 00000000..ddf00990
--- /dev/null
+++ b/src/Authoring/Studio/res/tmtbmenu.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/weblinkc.bmp b/src/Authoring/Studio/res/weblinkc.bmp
new file mode 100644
index 00000000..e9f941b4
--- /dev/null
+++ b/src/Authoring/Studio/res/weblinkc.bmp
Binary files differ
diff --git a/src/Authoring/Studio/res/winxp1.bin b/src/Authoring/Studio/res/winxp1.bin
new file mode 100644
index 00000000..065c2edf
--- /dev/null
+++ b/src/Authoring/Studio/res/winxp1.bin
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly
+ xmlns="urn:schemas-microsoft-com:asm.v1"
+ manifestVersion="1.0">
+<assemblyIdentity
+ processorArchitecture="x86"
+ version="5.1.0.0"
+ type="win32"
+ name="test.exe"/>
+ <description>Test Application</description>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ processorArchitecture="x86"/>
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/src/Authoring/Studio/style.qss b/src/Authoring/Studio/style.qss
new file mode 100644
index 00000000..1bb92ddc
--- /dev/null
+++ b/src/Authoring/Studio/style.qss
@@ -0,0 +1,219 @@
+/* General coloring and font size */
+QWidget {
+ color: #ffffff;
+ background: #2e2f30;
+ font-size: 12px;
+ border: 0px;
+}
+
+/* DockWidget separators */
+QMainWindow::separator {
+ background: #000000;
+ width: 1px; /* when vertical */
+ height: 1px; /* when horizontal */
+}
+
+/* Tabs */
+QTabBar::tab:selected {
+ background: #2e2f30;
+ padding: 5px;
+}
+
+QTabBar::tab:!selected {
+ background: #262829;
+ color: #727476;
+ padding: 5px;
+}
+
+QTabWidget::pane {
+ border: 1px solid #404244;
+}
+
+/* Scrollbar */
+QScrollBar:horizontal {
+ border: 1px solid #262829;
+ background: #404244;
+}
+
+QScrollBar::handle:horizontal {
+ background: #727476;
+}
+
+QScrollBar::add-line:horizontal,
+QScrollBar::sub-line:horizontal {
+ width: 0px;
+}
+
+QScrollBar:vertical {
+ border: 1px solid #262829;
+ background: #404244;
+}
+
+QScrollBar::handle:vertical {
+ background: #727476;
+}
+
+QScrollBar::add-line:vertical,
+QScrollBar::sub-line:vertical {
+ height: 0px;
+}
+
+/* Menubar */
+QMenuBar {
+ background: #404244;
+ border-top: 1px solid #262829;
+}
+
+QMenuBar::item {
+ background: transparent;
+}
+
+QMenuBar::item:selected {
+ background: #46a2da;
+ border: 1px solid #262829;
+}
+
+/* Menu */
+QMenu {
+ background: #262829;
+ border: 1px solid #727476;
+}
+
+QMenu::item {
+ padding: 4px 20px 4px 20px;
+}
+
+QMenu::item:selected:enabled {
+ background: #46a2da;
+}
+
+QMenu::item:disabled {
+ padding: 4px 20px 4px 20px;
+ color: #727476;
+}
+
+QMenu::separator {
+ height: 1px;
+ background: #727476;
+}
+
+/* Toolbar */
+QToolBar {
+ background: #404244;
+ border-top: 1px solid #262829;
+ min-height: 24px;
+ max-height: 24px;
+}
+
+QToolBar::handle {
+ image: url(:/res/separator.png);
+}
+
+QToolBar::separator {
+ background: #727476;
+ width: 1px;
+ margin: 3px;
+}
+
+QToolButton:!checked {
+ min-width: 22px;
+ min-height: 22px;
+ background-color: #404244;
+}
+
+QToolButton:checked, QToolButton:hover {
+ min-width: 22px;
+ min-height: 22px;
+ background-color: #262829;
+}
+
+QToolButton:pressed {
+ min-width: 22px;
+ min-height: 22px;
+ background-color: #46a2da;
+}
+
+QComboBox#cameraSelector {
+ /* We have a specific style for camera selector combobox, as it's in the toolbar and needs to
+ blend in */
+ background: #404244;
+ border: 0px;
+ border-radius: 0;
+ padding: 3px;
+}
+
+/* ToolTip */
+QToolTip {
+ background: #404244;
+ color: #ffffff;
+ font-size: 12px;
+ border: 1px solid #727476;
+ border-radius: 2;
+}
+
+/* Dialog widgets */
+QComboBox,
+QLineEdit,
+QSpinBox,
+QTimeEdit {
+ background: #404244;
+ border: 1px solid #262829;
+ border-radius: 2;
+ padding: 3px;
+}
+
+QComboBox::drop-down {
+ background: #404244;
+}
+
+QComboBox::down-arrow {
+ image: url(:/res/arrow_down.png);
+}
+
+QGroupBox {
+ padding: 14px 0px 0px 0px;
+ border: 1px solid #262829;
+}
+
+QGroupBox::title {
+ subcontrol-origin: padding;
+ margin-top: 2px;
+ margin-left: 10px;
+}
+
+QPushButton {
+ background: #404244;
+ border: 1px solid #262829;
+ border-radius: 2;
+ padding: 3px 10px 3px 10px;
+ min-width: 75;
+}
+
+/* Tutorial Dialog */
+QDialog#StudioTutorialWidget,
+QDialog#StudioTutorialWidget QWidget {
+ color: #ffffff;
+ background-color: transparent;
+ border: 0px;
+}
+
+QPushButton:!pressed#studioTutorialOpen,
+QPushButton:!pressed#studioTutorialNew {
+ background: transparent;
+ border: 1px solid #41cd52;
+}
+
+QPushButton:pressed#studioTutorialOpen,
+QPushButton:pressed#studioTutorialNew {
+ background: #41cd52;
+ border: 1px solid #41cd52;
+}
+
+/* Startup Dialog */
+QDialog#StartupDlg,
+QDialog#StartupDlg QWidget {
+ color: #ffffff;
+ background-color: transparent;
+ border: 0px;
+ font-size: 16px;
+}
diff --git a/src/Authoring/Studio/version.h b/src/Authoring/Studio/version.h
new file mode 100644
index 00000000..118d95b5
--- /dev/null
+++ b/src/Authoring/Studio/version.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_VERSION
+
+#ifdef WIN32
+#include "..\Build\VersionNumber.h"
+#endif
+
+#endif
diff --git a/src/Authoring/UICDM.pri b/src/Authoring/UICDM.pri
new file mode 100644
index 00000000..0bad8fc9
--- /dev/null
+++ b/src/Authoring/UICDM.pri
@@ -0,0 +1,33 @@
+SOURCES += \
+ UICDM/EASTL_new.cpp \
+ UICDM/UICDMPrefix.cpp \
+ UICDM/Systems/ActionSystem.cpp \
+ UICDM/Systems/SignalsImpl.cpp \
+ UICDM/Systems/SlideSystem.cpp \
+ UICDM/Systems/StudioAnimationSystem.cpp \
+ UICDM/Systems/StudioCoreSystem.cpp \
+ UICDM/Systems/StudioFullSystem.cpp \
+ UICDM/Systems/StudioPropertySystem.cpp \
+ UICDM/Systems/UICDMComposerTypeDefinitions.cpp \
+ UICDM/Systems/UICDMGuides.cpp \
+ UICDM/Systems/UICDMHandles.cpp \
+ UICDM/Systems/UICDMMetaData.cpp \
+ UICDM/Systems/UICDMSignalSystem.cpp \
+ UICDM/Systems/UICDMStringTable.cpp \
+ UICDM/Systems/UICDMValue.cpp \
+ UICDM/Systems/UICDMXML.cpp \
+ UICDM/Systems/Cores/ActionCoreProducer.cpp \
+ UICDM/Systems/Cores/AnimationCoreProducer.cpp \
+ UICDM/Systems/Cores/DataCoreProducer.cpp \
+ UICDM/Systems/Cores/SimpleActionCore.cpp \
+ UICDM/Systems/Cores/SimpleAnimationCore.cpp \
+ UICDM/Systems/Cores/SimpleDataCore.cpp \
+ UICDM/Systems/Cores/SimpleSlideCore.cpp \
+ UICDM/Systems/Cores/SimpleSlideGraphCore.cpp \
+ UICDM/Systems/Cores/SlideCoreProducer.cpp \
+ UICDM/Systems/Cores/SlideGraphCoreProducer.cpp \
+
+HEADERS += \
+ UICDM/Systems/UICDMDataTypes.h \
+ UICDM/Systems/UICDMMetaDataTypes.h \
+ UICDM/Systems/UICDMMetaDataValue.h
diff --git a/src/Authoring/UICDM.pro b/src/Authoring/UICDM.pro
new file mode 100644
index 00000000..360b74ec
--- /dev/null
+++ b/src/Authoring/UICDM.pro
@@ -0,0 +1,28 @@
+TEMPLATE = lib
+TARGET = UICDM
+CONFIG += staticlib
+include($$PWD/commoninclude.pri)
+DEFINES += UIC_AUTHORING _AFXDLL \
+ PCRE_STATIC BOOST_SIGNALS_NO_DEPRECATION_WARNING BOOST_ALL_NO_LIB \
+ _UNICODE
+
+linux {
+ DEFINES += UICDM_META_DATA_NO_SIGNALS
+}
+
+INCLUDEPATH += \
+ UICDM \
+ UICDM/Systems \
+ UICDM/Systems/Cores \
+ $$PWD/../Runtime/Source/System/Include \
+ $$PWD/../Runtime/Source/Qt3DSFoundation/Include \
+ $$PWD/../Runtime/Source/UICRender/Include \
+ $$PWD/../Runtime/Source/RuntimeUICDM/Include \
+ $$PWD/../Runtime/Source/Qt3DSRender/Include \
+ ../3rdparty/EASTL/UnknownVersion/include \
+ ../3rdparty/utf8cpp/2.3.2/source \
+ ../3rdparty/color
+
+PRECOMPILED_HEADER = UICDM/UICDMPrefix.h
+
+include(UICDM.pri)
diff --git a/src/Authoring/UICDM/EASTL_new.cpp b/src/Authoring/UICDM/EASTL_new.cpp
new file mode 100644
index 00000000..de0c2501
--- /dev/null
+++ b/src/Authoring/UICDM/EASTL_new.cpp
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "EASTL/allocator.h"
+
+void *operator new[](size_t size, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+
+void *operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
diff --git a/src/Authoring/UICDM/Systems/ActionSystem.cpp b/src/Authoring/UICDM/Systems/ActionSystem.cpp
new file mode 100644
index 00000000..aaa0074a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/ActionSystem.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "ActionSystem.h"
+
+using namespace std;
+
+namespace UICDM {
+
+CActionSystem::CActionSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore,
+ TSlideGraphCorePtr inSlideGraphCore, TActionCorePtr inActionCore,
+ TSlideSystemPtr inSlideSystem, CUICDMInstanceHandle inActionInstance,
+ CUICDMPropertyHandle inActionEyeball)
+ : m_DataCore(inDataCore)
+ , m_SlideCore(inSlideCore)
+ , m_SlideGraphCore(inSlideGraphCore)
+ , m_ActionCore(inActionCore)
+ , m_SlideSystem(inSlideSystem)
+ , m_ActionInstance(inActionInstance)
+ , m_ActionEyeball(inActionEyeball)
+{
+ m_Signaller = CreateActionSystemSignaller();
+}
+
+CUICDMActionHandle CActionSystem::CreateAction(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner,
+ SLong4 inTriggerTargetObjects)
+{
+ Q_ASSERT(inSlide.Valid() && inOwner.Valid());
+
+ // Create Action instance handle that derives from Action instance
+ CUICDMInstanceHandle theActionInstance = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(theActionInstance, m_ActionInstance);
+
+ // Associate Action instance handle with Slide
+ m_SlideSystem->AssociateInstanceWithSlide(inSlide, theActionInstance);
+
+ // Unlink the eyeball property because Action can be eyeballed-on/off per-slide
+ m_SlideSystem->UnlinkProperty(theActionInstance, m_ActionEyeball);
+
+ // Create the Action handle
+ CUICDMActionHandle retval =
+ m_ActionCore->CreateAction(theActionInstance, inSlide, inOwner, inTriggerTargetObjects);
+
+ GetSignalSender()->SendActionCreated(retval, inSlide, inOwner);
+ return retval;
+}
+
+void CActionSystem::DeleteAction(CUICDMActionHandle inAction)
+{
+ CUICDMInstanceHandle theActionInstance;
+ SActionInfo theActionInfo = m_ActionCore->GetActionInfo(inAction);
+ m_ActionCore->DeleteAction(inAction, theActionInstance);
+ m_DataCore->DeleteInstance(theActionInstance);
+ GetSignalSender()->SendActionDeleted(inAction, theActionInfo.m_Slide, theActionInfo.m_Owner);
+}
+
+void CActionSystem::GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const
+{
+ // Get all actions that exist in inSlide
+ m_ActionCore->GetActions(inSlide, inOwner, outActions);
+
+ // if inSlide is not master, get all actions that exist in master slide
+ CUICDMSlideHandle theMaster = m_SlideSystem->GetMasterSlide(inSlide);
+ if (theMaster != inSlide) {
+ TActionHandleList theMasterActions;
+ m_ActionCore->GetActions(theMaster, inOwner, theMasterActions);
+ outActions.insert(outActions.end(), theMasterActions.begin(), theMasterActions.end());
+ sort(outActions.begin(), outActions.end());
+ }
+}
+
+bool CActionSystem::GetActionEyeballValue(CUICDMSlideHandle inActiveSlide,
+ CUICDMActionHandle inAction) const
+{
+ SValue theValue;
+ CUICDMInstanceHandle theInstance = m_ActionCore->GetActionInstance(inAction);
+ // Get the eyeball property value from SlideCore. There is no animation on eyeball so we can
+ // query SlideCore directly.
+ m_SlideCore->GetInstancePropertyValue(inActiveSlide, theInstance, m_ActionEyeball, theValue);
+ if (m_SlideCore->IsSlide(inActiveSlide))
+ return UICDM::get<bool>(theValue);
+ return false;
+}
+
+void CActionSystem::SetActionEyeballValue(CUICDMSlideHandle inActiveSlide,
+ CUICDMActionHandle inAction, bool inValue)
+{
+ CUICDMInstanceHandle theInstance = m_ActionCore->GetActionInstance(inAction);
+ // Set the eyeball property value to SlideCore.
+ m_SlideCore->ForceSetInstancePropertyValue(inActiveSlide, theInstance, m_ActionEyeball,
+ inValue);
+}
+
+IActionSystemSignalProvider *CActionSystem::GetSignalProvider()
+{
+ return dynamic_cast<IActionSystemSignalProvider *>(m_Signaller.get());
+}
+
+IActionSystemSignalSender *CActionSystem::GetSignalSender()
+{
+ return dynamic_cast<IActionSystemSignalSender *>(m_Signaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/ActionSystem.h b/src/Authoring/UICDM/Systems/ActionSystem.h
new file mode 100644
index 00000000..49ef0830
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/ActionSystem.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ACTIONSYSTEMH
+#define ACTIONSYSTEMH
+#include "UICDMActionSystem.h"
+#include "UICDMActionCore.h"
+#include "UICDMDataCore.h"
+#include "UICDMSlideCore.h"
+#include "UICDMSlideGraphCore.h"
+#include "UICDMSlides.h"
+#include "UICDMTransactions.h"
+#include "SignalsImpl.h"
+
+namespace UICDM {
+
+class CActionSystem : public IActionSystem
+{
+ TDataCorePtr m_DataCore;
+ TSlideCorePtr m_SlideCore;
+ TSlideGraphCorePtr m_SlideGraphCore;
+ TActionCorePtr m_ActionCore;
+
+ TSlideSystemPtr m_SlideSystem;
+
+ CUICDMInstanceHandle m_ActionInstance;
+ CUICDMPropertyHandle m_ActionEyeball;
+
+ std::shared_ptr<ISignalItem> m_Signaller;
+
+public:
+ CActionSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore,
+ TSlideGraphCorePtr inSlideGraphCore, TActionCorePtr inActionCore,
+ TSlideSystemPtr inSlideSystem, CUICDMInstanceHandle inActionInstance,
+ CUICDMPropertyHandle inActionEyeball);
+
+ CUICDMActionHandle CreateAction(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ SLong4 inTriggerTargetObjects) override;
+ void DeleteAction(CUICDMActionHandle inAction) override;
+ void GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const override;
+
+ bool GetActionEyeballValue(CUICDMSlideHandle inActiveSlide,
+ CUICDMActionHandle inAction) const override;
+ void SetActionEyeballValue(CUICDMSlideHandle inActiveSlide, CUICDMActionHandle inAction,
+ bool inValue) override;
+
+ virtual IActionSystemSignalProvider *GetSignalProvider();
+
+private:
+ virtual IActionSystemSignalSender *GetSignalSender();
+
+ CActionSystem(const CActionSystem&) = delete;
+ CActionSystem& operator=(const CActionSystem&) = delete;
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.cpp b/src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.cpp
new file mode 100644
index 00000000..1e065b7a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "ActionCoreProducer.h"
+#include "HandleSystemTransactions.h"
+#include "VectorTransactions.h"
+#include "SignalsImpl.h"
+
+using namespace std;
+
+namespace UICDM {
+
+CUICDMActionHandle CActionCoreProducer::CreateAction(CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner,
+ SLong4 inTriggerTargetObjects)
+{
+ CUICDMActionHandle retval =
+ m_Data->CreateAction(inInstance, inSlide, inOwner, inTriggerTargetObjects);
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ return retval;
+}
+
+void CActionCoreProducer::DeleteAction(CUICDMActionHandle inAction,
+ CUICDMInstanceHandle &outInstance)
+{
+ // Ensure action exists
+ SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects);
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inAction, m_Data->m_Objects);
+ do_all(theAction->m_ActionInfo.m_HandlerArgs,
+ std::bind(DoCreateHandleDeleteTransaction, __FILE__, __LINE__, m_Consumer,
+ std::placeholders::_1, std::ref(m_Data->m_Objects)));
+ m_Data->DeleteAction(inAction, outInstance);
+}
+
+const SActionInfo &CActionCoreProducer::GetActionInfo(CUICDMActionHandle inAction) const
+{
+ return m_Data->GetActionInfo(inAction);
+}
+
+void CActionCoreProducer::GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const
+{
+ return m_Data->GetActions(inSlide, inOwner, outActions);
+}
+
+void CActionCoreProducer::GetActions(CUICDMSlideHandle inSlide, TActionHandleList &outActions) const
+{
+ return m_Data->GetActions(inSlide, outActions);
+}
+
+void CActionCoreProducer::GetActions(CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const
+{
+ return m_Data->GetActions(inOwner, outActions);
+}
+
+void CActionCoreProducer::GetActions(TActionHandleList &outActions) const
+{
+ return m_Data->GetActions(outActions);
+}
+
+CUICDMInstanceHandle CActionCoreProducer::GetActionInstance(CUICDMActionHandle inAction) const
+{
+ return m_Data->GetActionInstance(inAction);
+}
+
+CUICDMActionHandle
+CActionCoreProducer::GetActionByInstance(CUICDMInstanceHandle inActionInstance) const
+{
+ return m_Data->GetActionByInstance(inActionInstance);
+}
+
+void CActionCoreProducer::SetTriggerObject(CUICDMActionHandle inAction,
+ const SObjectRefType &inTriggerObject)
+{
+ SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleActionCore::SetTriggerObject, m_Data, inAction, inTriggerObject),
+ std::bind(&CSimpleActionCore::SetTriggerObject, m_Data, inAction,
+ theAction->m_ActionInfo.m_TriggerObject))));
+ }
+ m_Data->SetTriggerObject(inAction, inTriggerObject);
+ GetSignalSender()->SendTriggerObjectSet(inAction, theAction->m_ActionInfo.m_TriggerObject);
+}
+
+void CActionCoreProducer::SetTargetObject(CUICDMActionHandle inAction,
+ const SObjectRefType &inTargetObject)
+{
+ SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleActionCore::SetTargetObject, m_Data, inAction, inTargetObject),
+ std::bind(&CSimpleActionCore::SetTargetObject, m_Data, inAction,
+ theAction->m_ActionInfo.m_TargetObject))));
+ }
+ m_Data->SetTargetObject(inAction, inTargetObject);
+ GetSignalSender()->SendTargetObjectSet(inAction, theAction->m_ActionInfo.m_TargetObject);
+}
+
+void CActionCoreProducer::SetEvent(CUICDMActionHandle inAction, const wstring &inEventHandle)
+{
+ SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleActionCore::SetEvent, m_Data, inAction, inEventHandle),
+ std::bind(&CSimpleActionCore::SetEvent, m_Data, inAction,
+ theAction->m_ActionInfo.m_Event))));
+ }
+ m_Data->SetEvent(inAction, inEventHandle);
+ GetSignalSender()->SendEventSet(inAction, inEventHandle);
+}
+
+void CActionCoreProducer::SetHandler(CUICDMActionHandle inAction, const wstring &inHandlerHandle)
+{
+ SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleActionCore::SetHandler, m_Data, inAction, inHandlerHandle),
+ std::bind(&CSimpleActionCore::SetHandler, m_Data, inAction,
+ theAction->m_ActionInfo.m_Handler))));
+ }
+ m_Data->SetHandler(inAction, inHandlerHandle);
+ GetSignalSender()->SendHandlerSet(inAction, inHandlerHandle);
+}
+
+CUICDMHandlerArgHandle CActionCoreProducer::AddHandlerArgument(CUICDMActionHandle inAction,
+ const TCharStr &inName,
+ HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType)
+{
+ CUICDMHandlerArgHandle retval =
+ m_Data->AddHandlerArgument(inAction, inName, inArgType, inValueType);
+ SAction *theAction = CSimpleActionCore::GetActionNF(inAction, m_Data->m_Objects);
+ CreateVecInsertTransaction<CUICDMHandlerArgHandle>(__FILE__, __LINE__, m_Consumer, retval,
+ theAction->m_ActionInfo.m_HandlerArgs);
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ GetSignalSender()->SendHandlerArgumentAdded(inAction, retval, inName, inArgType, inValueType);
+ return retval;
+}
+
+void CActionCoreProducer::RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument)
+{
+ SHandlerArgument *theHandlerArgument =
+ CSimpleActionCore::GetHandlerArgumentNF(inHandlerArgument, m_Data->m_Objects);
+ SAction *theAction = CSimpleActionCore::GetActionNF(
+ theHandlerArgument->m_HandlerArgInfo.m_Action, m_Data->m_Objects);
+ if (exists(theAction->m_ActionInfo.m_HandlerArgs,
+ std::bind(equal_to<CUICDMHandlerArgHandle>(), inHandlerArgument,
+ std::placeholders::_1))) {
+ CreateVecEraseTransaction<CUICDMHandlerArgHandle>(__FILE__, __LINE__, m_Consumer,
+ inHandlerArgument,
+ theAction->m_ActionInfo.m_HandlerArgs);
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inHandlerArgument, m_Data->m_Objects);
+ }
+ m_Data->RemoveHandlerArgument(inHandlerArgument);
+ GetSignalSender()->SendHandlerArgumentRemoved(theAction->m_Handle, theHandlerArgument->m_Handle,
+ theHandlerArgument->m_HandlerArgInfo.m_Name,
+ theHandlerArgument->m_HandlerArgInfo.m_ArgType,
+ theHandlerArgument->m_HandlerArgInfo.m_ValueType);
+}
+
+const SHandlerArgumentInfo &
+CActionCoreProducer::GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const
+{
+ return m_Data->GetHandlerArgumentInfo(inHandlerArgument);
+}
+
+void CActionCoreProducer::GetHandlerArguments(CUICDMActionHandle inAction,
+ THandlerArgHandleList &outHandlerArguments) const
+{
+ return m_Data->GetHandlerArguments(inAction, outHandlerArguments);
+}
+
+void CActionCoreProducer::GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ SValue &outValue) const
+{
+ return m_Data->GetHandlerArgumentValue(inHandlerArgument, outValue);
+}
+
+void CActionCoreProducer::SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ const SValue &inValue)
+{
+ SHandlerArgument *theHandlerArgument =
+ CSimpleActionCore::GetHandlerArgumentNF(inHandlerArgument, m_Data->m_Objects);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleActionCore::SetHandlerArgumentValue, m_Data, inHandlerArgument,
+ inValue),
+ std::bind(&CSimpleActionCore::SetHandlerArgumentValue, m_Data, inHandlerArgument,
+ theHandlerArgument->m_HandlerArgInfo.m_Value))));
+ }
+ m_Data->SetHandlerArgumentValue(inHandlerArgument, inValue);
+ GetSignalSender()->SendHandlerArgumentValueSet(inHandlerArgument, inValue);
+}
+
+// CHandleBase
+bool CActionCoreProducer::HandleValid(int inHandle) const
+{
+ return m_Data->HandleValid(inHandle);
+}
+
+// ITransactionProducer implementation
+void CActionCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_Consumer = inConsumer;
+}
+
+TSignalConnectionPtr CActionCoreProducer::ConnectTriggerObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectTriggerObjectSet(inCallback);
+}
+TSignalConnectionPtr CActionCoreProducer::ConnectTargetObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectTargetObjectSet(inCallback);
+}
+TSignalConnectionPtr CActionCoreProducer::ConnectEventSet(
+ const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectEventSet(inCallback);
+}
+TSignalConnectionPtr CActionCoreProducer::ConnectHandlerSet(
+ const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectHandlerSet(inCallback);
+}
+
+TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentAdded(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback)
+{
+ return GetSignalProvider()->ConnectHandlerArgumentAdded(inCallback);
+}
+TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentRemoved(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback)
+{
+ return GetSignalProvider()->ConnectHandlerArgumentRemoved(inCallback);
+}
+TSignalConnectionPtr CActionCoreProducer::ConnectHandlerArgumentValueSet(
+ const std::function<void(CUICDMHandlerArgHandle, const SValue &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectHandlerArgumentValueSet(inCallback);
+}
+
+void CActionCoreProducer::InitSignaller()
+{
+ m_Signaller = CreateActionCoreSignaller();
+}
+
+IActionCoreSignalProvider *CActionCoreProducer::GetSignalProvider()
+{
+ return dynamic_cast<IActionCoreSignalProvider *>(m_Signaller.get());
+}
+
+IActionCoreSignalSender *CActionCoreProducer::GetSignalSender()
+{
+ return dynamic_cast<IActionCoreSignalSender *>(m_Signaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.h b/src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.h
new file mode 100644
index 00000000..ac48591b
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/ActionCoreProducer.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ACTIONCOREPRODUCERH
+#define ACTIONCOREPRODUCERH
+
+#include "SimpleActionCore.h"
+#include "UICDMTransactions.h"
+#include "UICDMSignals.h"
+#include "UICDMStringTable.h"
+
+namespace UICDM {
+class CActionCoreProducer : public IActionCore,
+ public ITransactionProducer,
+ public IActionCoreSignalProvider
+{
+ Q_DISABLE_COPY(CActionCoreProducer)
+
+ TSimpleActionCorePtr m_Data;
+ TTransactionConsumerPtr m_Consumer;
+ TSignalItemPtr m_Signaller;
+
+public:
+ CActionCoreProducer(TStringTablePtr inStringTable)
+ : m_Data(new CSimpleActionCore(inStringTable))
+ {
+ InitSignaller();
+ }
+
+ TSimpleActionCorePtr GetTransactionlessActionCore() const { return m_Data; }
+
+ // IActionCore implementation
+ IStringTable &GetStringTable() const override { return m_Data->GetStringTable(); }
+ TStringTablePtr GetStringTablePtr() const override { return m_Data->GetStringTablePtr(); }
+ // Action
+ CUICDMActionHandle CreateAction(CUICDMInstanceHandle inInstance, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner, SLong4 inTriggerTargetObjects) override;
+ void DeleteAction(CUICDMActionHandle inAction, CUICDMInstanceHandle &outInstance) override;
+ const SActionInfo &GetActionInfo(CUICDMActionHandle inAction) const override;
+ void GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const override;
+ void GetActions(CUICDMSlideHandle inSlide, TActionHandleList &outActions) const override;
+ void GetActions(CUICDMInstanceHandle inOwner, TActionHandleList &outActions) const override;
+ void GetActions(TActionHandleList &outActions) const override;
+ CUICDMInstanceHandle GetActionInstance(CUICDMActionHandle inAction) const override;
+ CUICDMActionHandle GetActionByInstance(CUICDMInstanceHandle inActionInstance) const override;
+
+ // Action Properties
+ void SetTriggerObject(CUICDMActionHandle inAction, const SObjectRefType &inTriggerObject) override;
+ void SetTargetObject(CUICDMActionHandle inAction, const SObjectRefType &inTargetObject) override;
+ void SetEvent(CUICDMActionHandle inAction, const wstring &inEventHandle) override;
+ void SetHandler(CUICDMActionHandle inAction, const wstring &inHandlerHandle) override;
+
+ // Action Argument
+ CUICDMHandlerArgHandle AddHandlerArgument(CUICDMActionHandle inAction, const TCharStr &inName,
+ HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) override;
+ void RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument) override;
+ const SHandlerArgumentInfo &
+ GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const override;
+ void GetHandlerArguments(CUICDMActionHandle inAction,
+ THandlerArgHandleList &outHandlerArguments) const override;
+
+ // Action Argument Properties
+ void GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, SValue &outValue) const override;
+ void SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, const SValue &inValue) override;
+
+ // CHandleBase
+ bool HandleValid(int inHandle) const override;
+
+ // ITransactionProducer implementation
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+
+ TSignalConnectionPtr ConnectTriggerObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) override;
+ TSignalConnectionPtr ConnectTargetObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectEventSet(const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectHandlerSet(const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) override;
+
+ TSignalConnectionPtr ConnectHandlerArgumentAdded(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override;
+ TSignalConnectionPtr ConnectHandlerArgumentRemoved(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override;
+ TSignalConnectionPtr ConnectHandlerArgumentValueSet(
+ const std::function<void(CUICDMHandlerArgHandle, const SValue &)> &inCallback) override;
+
+private:
+ void InitSignaller();
+ IActionCoreSignalProvider *GetSignalProvider();
+ IActionCoreSignalSender *GetSignalSender();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.cpp b/src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.cpp
new file mode 100644
index 00000000..5ebe97a0
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.cpp
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "AnimationCoreProducer.h"
+#include "HandleSystemTransactions.h"
+#include "VectorTransactions.h"
+#include "SignalsImpl.h"
+#ifdef _WIN32
+#pragma warning(disable : 4512) // assignment operator not generated
+#endif
+
+using namespace std;
+
+namespace UICDM {
+
+struct SArtistEditedUndoRedoScope
+{
+ TSimpleAnimationCorePtr m_AnimationCore;
+ CUICDMAnimationHandle m_Animation;
+ TTransactionConsumerPtr m_Consumer;
+ bool m_ArtistEdited;
+ SArtistEditedUndoRedoScope(TSimpleAnimationCorePtr inAnimCore, CUICDMAnimationHandle inAnim,
+ TTransactionConsumerPtr inConsumer)
+ : m_AnimationCore(inAnimCore)
+ , m_Animation(inAnim)
+ , m_Consumer(inConsumer)
+ , m_ArtistEdited(inAnimCore->IsArtistEdited(inAnim))
+ {
+ }
+ ~SArtistEditedUndoRedoScope()
+ {
+ bool edited = m_AnimationCore->IsArtistEdited(m_Animation);
+ if (m_Consumer && edited != m_ArtistEdited) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleAnimationCore::SetIsArtistEdited, m_AnimationCore, m_Animation,
+ edited),
+ std::bind(&CSimpleAnimationCore::SetIsArtistEdited, m_AnimationCore, m_Animation,
+ m_ArtistEdited))));
+ }
+ }
+};
+
+struct SLookupCacheDoUndoOp : public ITransaction
+{
+ std::shared_ptr<SAnimationTrack> m_Animation;
+ TSimpleAnimationCorePtr m_AnimationCore;
+ bool m_AddOnDo;
+ SLookupCacheDoUndoOp(const char *inFile, int inLine, CUICDMAnimationHandle inAnimHandle,
+ TSimpleAnimationCorePtr inCore, bool addOnDo)
+ : ITransaction(inFile, inLine)
+ , m_AnimationCore(inCore)
+ , m_AddOnDo(addOnDo)
+ {
+ THandleObjectMap::const_iterator theIter(inCore->m_Objects.find(inAnimHandle));
+ if (theIter != inCore->m_Objects.end())
+ m_Animation = static_pointer_cast<SAnimationTrack>(theIter->second);
+ }
+ void Remove()
+ {
+ if (m_Animation)
+ m_AnimationCore->RemoveAnimationFromLookupCache(m_Animation);
+ }
+ void Add()
+ {
+ if (m_Animation)
+ m_AnimationCore->AddAnimationToLookupCache(m_Animation);
+ }
+ void Do() override
+ {
+ if (m_AddOnDo)
+ Add();
+ else
+ Remove();
+ }
+ void Undo() override
+ {
+ if (m_AddOnDo)
+ Remove();
+ else
+ Add();
+ }
+};
+
+CUICDMAnimationHandle
+CAnimationCoreProducer::CreateAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType, bool inFirstKeyframeDynamic)
+{
+ CUICDMAnimationHandle retval = m_Data->CreateAnimation(inSlide, inInstance, inProperty, inIndex,
+ inAnimationType, inFirstKeyframeDynamic);
+
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ if (m_Consumer)
+ m_Consumer->OnTransaction(
+ std::make_shared<SLookupCacheDoUndoOp>(__FILE__, __LINE__, retval, m_Data, true));
+ GetSignalSender()->SendAnimationCreated(retval, inSlide, inInstance, inProperty, inIndex,
+ inAnimationType);
+ return retval;
+}
+
+void CAnimationCoreProducer::DeleteAnimation(CUICDMAnimationHandle inAnimation)
+{
+ // Ensure animation exists
+ SAnimationTrack *theAnimation =
+ CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects);
+ GetSignalSender()->SendBeforeAnimationDeleted(inAnimation);
+ if (m_Consumer)
+ m_Consumer->OnTransaction(std::make_shared<SLookupCacheDoUndoOp>(
+ __FILE__, __LINE__, inAnimation, m_Data, false));
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inAnimation, m_Data->m_Objects);
+ do_all(theAnimation->m_Keyframes,
+ std::bind(DoCreateHandleDeleteTransaction, __FILE__, __LINE__, m_Consumer,
+ std::placeholders::_1, std::ref(m_Data->m_Objects)));
+ SAnimationInfo theInfo = m_Data->GetAnimationInfo(inAnimation);
+ m_Data->DeleteAnimation(inAnimation);
+ GetSignalSender()->SendAnimationDeleted(inAnimation, theInfo.m_Slide, theInfo.m_Instance,
+ theInfo.m_Property, theInfo.m_Index,
+ theInfo.m_AnimationType);
+}
+
+CUICDMAnimationHandle CAnimationCoreProducer::GetAnimation(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ size_t inIndex) const
+{
+ return m_Data->GetAnimation(inSlide, inInstance, inProperty, inIndex);
+}
+
+SAnimationInfo CAnimationCoreProducer::GetAnimationInfo(CUICDMAnimationHandle inAnimation) const
+{
+ return m_Data->GetAnimationInfo(inAnimation);
+}
+
+void CAnimationCoreProducer::GetAnimations(TAnimationHandleList &outAnimations) const
+{
+ return m_Data->GetAnimations(outAnimations);
+}
+
+void CAnimationCoreProducer::GetAnimations(TAnimationInfoList &outAnimations,
+ CUICDMSlideHandle inMaster,
+ CUICDMSlideHandle inSlide) const
+{
+ return m_Data->GetAnimations(outAnimations, inMaster, inSlide);
+}
+
+void CAnimationCoreProducer::SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation,
+ bool inValue)
+{
+ SAnimationInfo theInfo(m_Data->GetAnimationInfo(inAnimation));
+ SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSimpleAnimationCore::SetFirstKeyframeDynamic, m_Data, inAnimation,
+ inValue),
+ std::bind(&CSimpleAnimationCore::SetFirstKeyframeDynamic, m_Data, inAnimation,
+ theInfo.m_DynamicFirstKeyframe))));
+ }
+ m_Data->SetFirstKeyframeDynamic(inAnimation, inValue);
+ GetSignalSender()->SendFirstKeyframeDynamicSet(inAnimation, inValue);
+}
+
+inline void DirtyKeyframes(CUICDMAnimationHandle inAnimation, THandleObjectMap &inObjects)
+{
+ SAnimationTrack *theAnimation = CSimpleAnimationCore::GetAnimationNF(inAnimation, inObjects);
+ theAnimation->m_KeyframesDirty = true;
+}
+
+inline void CreateDirtyKeyframesTransaction(TTransactionConsumerPtr inConsumer,
+ CUICDMAnimationHandle inAnimation,
+ THandleObjectMap &inObjects)
+{
+ if (inConsumer) {
+ inConsumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(DirtyKeyframes, inAnimation, std::ref(inObjects)),
+ std::bind(DirtyKeyframes, inAnimation, std::ref(inObjects)))));
+ }
+}
+
+CUICDMKeyframeHandle CAnimationCoreProducer::InsertKeyframe(CUICDMAnimationHandle inAnimation,
+ const TKeyframe &inKeyframe)
+{
+ SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer);
+ CUICDMKeyframeHandle retval = m_Data->InsertKeyframe(inAnimation, inKeyframe);
+ SAnimationTrack *theAnimation =
+ CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects);
+ CreateVecInsertTransaction<CUICDMKeyframeHandle>(__FILE__, __LINE__, m_Consumer, retval,
+ theAnimation->m_Keyframes);
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ CreateDirtyKeyframesTransaction(m_Consumer, inAnimation, m_Data->m_Objects);
+ GetSignalSender()->SendKeyframeInserted(inAnimation, retval, inKeyframe);
+ return retval;
+}
+
+void CAnimationCoreProducer::EraseKeyframe(CUICDMKeyframeHandle inKeyframe)
+{
+ SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, m_Data->m_Objects);
+ SArtistEditedUndoRedoScope __editedScope(m_Data, theKeyframe->m_Animation, m_Consumer);
+ GetSignalSender()->SendBeforeKeyframeErased(inKeyframe);
+ SAnimationTrack *theAnimation =
+ CSimpleAnimationCore::GetAnimationNF(theKeyframe->m_Animation, m_Data->m_Objects);
+ if (exists(theAnimation->m_Keyframes, std::bind(equal_to<int>(), inKeyframe,
+ std::placeholders::_1))) {
+ CreateVecEraseTransaction<CUICDMKeyframeHandle>(__FILE__, __LINE__, m_Consumer, inKeyframe,
+ theAnimation->m_Keyframes);
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inKeyframe, m_Data->m_Objects);
+ CreateDirtyKeyframesTransaction(m_Consumer, theKeyframe->m_Animation, m_Data->m_Objects);
+ }
+ int theKeyframeHandle = theKeyframe->m_Handle;
+ TKeyframe theData = theKeyframe->m_Keyframe;
+ m_Data->EraseKeyframe(inKeyframe);
+ GetSignalSender()->SendKeyframeErased(theAnimation->m_Handle, theKeyframeHandle, theData);
+}
+
+template <typename TDataType>
+struct VectorSwapTransaction : public ITransaction
+{
+ vector<TDataType> m_Data;
+ vector<TDataType> &m_Target;
+ VectorSwapTransaction(const char *inFile, int inLine, vector<TDataType> &inTarget)
+ : ITransaction(inFile, inLine)
+ , m_Data(inTarget)
+ , m_Target(inTarget)
+ {
+ }
+ void Do() override { std::swap(m_Data, m_Target); }
+ void Undo() override { Do(); }
+};
+
+void CAnimationCoreProducer::DeleteAllKeyframes(CUICDMAnimationHandle inAnimation)
+{
+ // Ensure animation exists
+ SAnimationTrack *theAnimation =
+ CSimpleAnimationCore::GetAnimationNF(inAnimation, m_Data->m_Objects);
+ SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer);
+ GetSignalSender()->SendBeforeAllKeyframesErased(inAnimation);
+ do_all(theAnimation->m_Keyframes,
+ std::bind(DoCreateHandleDeleteTransaction, __FILE__, __LINE__, m_Consumer,
+ std::placeholders::_1, std::ref(m_Data->m_Objects)));
+ if (m_Consumer)
+ m_Consumer->OnTransaction(std::make_shared<VectorSwapTransaction<CUICDMKeyframeHandle>>(
+ __FILE__, __LINE__, std::ref(theAnimation->m_Keyframes)));
+ theAnimation->m_Keyframes.clear();
+}
+
+CUICDMAnimationHandle
+CAnimationCoreProducer::GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const
+{
+ return m_Data->GetAnimationForKeyframe(inKeyframe);
+}
+
+struct KeyframeDataTransaction : public ITransaction, public IMergeableTransaction<TKeyframe>
+{
+ TSimpleAnimationCorePtr m_AnimationCore;
+ CUICDMKeyframeHandle m_Keyframe;
+ TKeyframe m_OldData;
+ TKeyframe m_NewData;
+
+ KeyframeDataTransaction(const char *inFile, int inLine, TSimpleAnimationCorePtr animCore,
+ CUICDMKeyframeHandle keyframe, TKeyframe oldData, TKeyframe newData)
+ : ITransaction(inFile, inLine)
+ , m_AnimationCore(animCore)
+ , m_Keyframe(keyframe)
+ , m_OldData(oldData)
+ , m_NewData(newData)
+ {
+ }
+
+ void Do() override { m_AnimationCore->DoSetKeyframeData(m_Keyframe, m_NewData); }
+ void Undo() override { m_AnimationCore->DoSetKeyframeData(m_Keyframe, m_OldData); }
+
+ void Update(const TKeyframe &inKeyframe) override { m_NewData = inKeyframe; }
+};
+
+void CAnimationCoreProducer::SetKeyframeData(CUICDMKeyframeHandle inKeyframe,
+ const TKeyframe &inData)
+{
+ SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, m_Data->m_Objects);
+ SArtistEditedUndoRedoScope __editedScope(m_Data, theKeyframe->m_Animation, m_Consumer);
+ TKeyframe theNewData(inData);
+ TKeyframe theOldData = theKeyframe->m_Keyframe;
+ m_Data->SetKeyframeData(inKeyframe, inData);
+ TKeyframeDataMergeMap::iterator iter(m_KeyframeMergeMap.find(inKeyframe));
+ if (iter != m_KeyframeMergeMap.end())
+ iter->second->Update(theNewData);
+ else {
+ if (m_Consumer) {
+ std::shared_ptr<KeyframeDataTransaction> theKeyframeTransaction(
+ std::make_shared<KeyframeDataTransaction>(__FILE__, __LINE__, m_Data, inKeyframe,
+ theOldData, theNewData));
+ m_Consumer->OnTransaction(static_pointer_cast<ITransaction>(theKeyframeTransaction));
+ m_KeyframeMergeMap.insert(make_pair(
+ inKeyframe,
+ static_pointer_cast<IMergeableTransaction<TKeyframe>>(theKeyframeTransaction)));
+ }
+ GetSignalSender()->SendKeyframeUpdated(inKeyframe, inData);
+ }
+}
+
+TKeyframe CAnimationCoreProducer::GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const
+{
+ return m_Data->GetKeyframeData(inKeyframe);
+}
+
+void CAnimationCoreProducer::GetKeyframes(CUICDMAnimationHandle inAnimation,
+ TKeyframeHandleList &outKeyframes) const
+{
+ return m_Data->GetKeyframes(inAnimation, outKeyframes);
+}
+
+size_t CAnimationCoreProducer::GetKeyframeCount(CUICDMAnimationHandle inAnimation) const
+{
+ return m_Data->GetKeyframeCount(inAnimation);
+}
+
+void CAnimationCoreProducer::OffsetAnimations(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ long inMillisecondOffset)
+{
+ float theOffsetSeconds = static_cast<float>(inMillisecondOffset) / 1000.f;
+ for (THandleObjectMap::const_iterator iter = m_Data->m_Objects.begin(),
+ end = m_Data->m_Objects.end();
+ iter != end; ++iter) {
+ SAnimationTrack *theTrack = static_cast<SAnimationTrack *>(iter->second.get());
+ if (theTrack->m_Slide == inSlide && theTrack->m_Instance == inInstance) {
+ for (size_t keyframeIdx = 0, keyframeEnd = theTrack->m_Keyframes.size();
+ keyframeIdx < keyframeEnd; ++keyframeIdx) {
+ CUICDMKeyframeHandle theKeyframeHandle(theTrack->m_Keyframes[keyframeIdx]);
+ TKeyframe theCurrentKeyframe = m_Data->GetKeyframeData(theKeyframeHandle);
+
+ float seconds = UICDM::GetKeyframeSeconds(theCurrentKeyframe);
+
+ theCurrentKeyframe =
+ UICDM::SetKeyframeSeconds(theCurrentKeyframe, seconds + theOffsetSeconds);
+
+ SetKeyframeData(theKeyframeHandle, theCurrentKeyframe);
+ }
+ }
+ }
+}
+
+void CAnimationCoreProducer::SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited)
+{
+ SArtistEditedUndoRedoScope __editedScope(m_Data, inAnimation, m_Consumer);
+ m_Data->SetIsArtistEdited(inAnimation, inEdited);
+}
+
+bool CAnimationCoreProducer::IsArtistEdited(CUICDMAnimationHandle inAnimation) const
+{
+ return m_Data->IsArtistEdited(inAnimation);
+}
+// Animation Evaluation.
+float CAnimationCoreProducer::EvaluateAnimation(CUICDMAnimationHandle inAnimation,
+ float inSeconds) const
+{
+ return m_Data->EvaluateAnimation(inAnimation, inSeconds);
+}
+
+bool CAnimationCoreProducer::KeyframeValid(CUICDMKeyframeHandle inKeyframe) const
+{
+ return m_Data->KeyframeValid(inKeyframe);
+}
+
+bool CAnimationCoreProducer::AnimationValid(CUICDMAnimationHandle inAnimation) const
+{
+ return m_Data->AnimationValid(inAnimation);
+}
+
+void CAnimationCoreProducer::CopyAnimations(CUICDMSlideHandle inSourceSlide,
+ CUICDMInstanceHandle inSourceInstance,
+ CUICDMSlideHandle inDestSlide,
+ CUICDMInstanceHandle inDestInstance)
+{
+ std::vector<SAnimationTrack *> theAnimations;
+ for (THandleObjectMap::const_iterator iter = m_Data->m_Objects.begin(),
+ end = m_Data->m_Objects.end();
+ iter != end; ++iter) {
+ SAnimationTrack *theTrack = static_cast<SAnimationTrack *>(iter->second.get());
+ if (theTrack->m_Instance == inSourceInstance && theTrack->m_Slide == inSourceSlide)
+ theAnimations.push_back(theTrack);
+ }
+ for (size_t idx = 0, end = theAnimations.size(); idx < end; ++idx) {
+ const SAnimationTrack &newTrack(*theAnimations[idx]);
+ CUICDMAnimationHandle theNewAnimation(
+ CreateAnimation(inDestSlide, inDestInstance, newTrack.m_Property, newTrack.m_Index,
+ newTrack.m_AnimationType, newTrack.m_FirstKeyframeDynamic));
+ for (size_t keyIdx = 0, keyEnd = newTrack.m_Keyframes.size(); keyIdx < keyEnd; ++keyIdx)
+ InsertKeyframe(theNewAnimation, GetKeyframeData(newTrack.m_Keyframes[keyIdx]));
+ }
+}
+
+// ITransactionProducer implementation
+void CAnimationCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_Consumer = inConsumer;
+ m_KeyframeMergeMap.clear();
+}
+
+TSignalConnectionPtr CAnimationCoreProducer::ConnectAnimationCreated(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback)
+{
+ return GetSignalProvider()->ConnectAnimationCreated(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeAnimationDeleted(
+ const std::function<void(CUICDMAnimationHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectBeforeAnimationDeleted(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectAnimationDeleted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback)
+{
+ return GetSignalProvider()->ConnectAnimationDeleted(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeInserted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback)
+{
+ return GetSignalProvider()->ConnectKeyframeInserted(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeKeyframeErased(
+ const std::function<void(CUICDMKeyframeHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectBeforeKeyframeErased(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeErased(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback)
+{
+ return GetSignalProvider()->ConnectKeyframeErased(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectBeforeAllKeyframesErased(
+ const std::function<void(CUICDMAnimationHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectBeforeAllKeyframesErased(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectKeyframeUpdated(
+ const std::function<void(CUICDMKeyframeHandle, const TKeyframe &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectKeyframeUpdated(inCallback);
+}
+TSignalConnectionPtr CAnimationCoreProducer::ConnectFirstKeyframeDynamicSet(
+ const std::function<void(CUICDMAnimationHandle, bool)> &inCallback)
+{
+ return GetSignalProvider()->ConnectFirstKeyframeDynamicSet(inCallback);
+}
+
+void CAnimationCoreProducer::InitSignaller()
+{
+ m_Signaller = CreateAnimationCoreSignaller();
+}
+
+IAnimationCoreSignalProvider *CAnimationCoreProducer::GetSignalProvider()
+{
+ return dynamic_cast<IAnimationCoreSignalProvider *>(m_Signaller.get());
+}
+
+IAnimationCoreSignalSender *CAnimationCoreProducer::GetSignalSender()
+{
+ return dynamic_cast<IAnimationCoreSignalSender *>(m_Signaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.h b/src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.h
new file mode 100644
index 00000000..0ec0490e
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/AnimationCoreProducer.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ANIMATIONCOREPRODUCERH
+#define ANIMATIONCOREPRODUCERH
+#include "SimpleAnimationCore.h"
+#include "UICDMTransactions.h"
+#include "UICDMSignals.h"
+
+namespace UICDM {
+class CAnimationCoreProducer : public IAnimationCore,
+ public ITransactionProducer,
+ public IAnimationCoreSignalProvider
+{
+ Q_DISABLE_COPY(CAnimationCoreProducer)
+
+ typedef std::shared_ptr<IMergeableTransaction<TKeyframe>> TKeyframeDataMergeMapEntry;
+ typedef std::unordered_map<int, TKeyframeDataMergeMapEntry> TKeyframeDataMergeMap;
+
+ TSimpleAnimationCorePtr m_Data;
+ TTransactionConsumerPtr m_Consumer;
+ TSignalItemPtr m_Signaller;
+ TKeyframeDataMergeMap m_KeyframeMergeMap;
+
+public:
+ CAnimationCoreProducer()
+ : m_Data(new CSimpleAnimationCore())
+ {
+ InitSignaller();
+ }
+ CAnimationCoreProducer(TStringTablePtr strTable)
+ : m_Data(new CSimpleAnimationCore(strTable))
+ {
+ InitSignaller();
+ }
+
+ TSimpleAnimationCorePtr GetTransactionlessAnimationCore() const { return m_Data; }
+
+ // IAnimationManger implementation
+
+ CUICDMAnimationHandle CreateAnimation(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic) override;
+ void DeleteAnimation(CUICDMAnimationHandle inAnimation) override;
+ CUICDMAnimationHandle GetAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex) const override;
+ SAnimationInfo GetAnimationInfo(CUICDMAnimationHandle inAnimation) const override;
+ void GetAnimations(TAnimationHandleList &outAnimations) const override;
+ void GetAnimations(TAnimationInfoList &outAnimations, CUICDMSlideHandle inMaster,
+ CUICDMSlideHandle inSlide) const override;
+ void GetSpecificInstanceAnimations(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations) override
+ {
+ m_Data->GetSpecificInstanceAnimations(inSlide, inInstance, outAnimations);
+ }
+
+ void SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation, bool inValue) override;
+
+ CUICDMKeyframeHandle InsertKeyframe(CUICDMAnimationHandle inAnimation,
+ const TKeyframe &inKeyframe) override;
+ void EraseKeyframe(CUICDMKeyframeHandle) override;
+ void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) override;
+ CUICDMAnimationHandle GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const override;
+ TKeyframe GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const override;
+ void SetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) override;
+ void GetKeyframes(CUICDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override;
+ size_t GetKeyframeCount(CUICDMAnimationHandle inAnimation) const override;
+ bool IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const override
+ {
+ return m_Data->IsFirstKeyframe(inKeyframe);
+ }
+ void OffsetAnimations(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ long inMillisecondOffset) override;
+
+ void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) override;
+ bool IsArtistEdited(CUICDMAnimationHandle inAnimation) const override;
+
+ // Animation Evaluation.
+ float EvaluateAnimation(CUICDMAnimationHandle inAnimation, float inSeconds) const override;
+
+ bool KeyframeValid(CUICDMKeyframeHandle inKeyframe) const override;
+ bool AnimationValid(CUICDMAnimationHandle inAnimation) const override;
+
+ void CopyAnimations(CUICDMSlideHandle inSourceSlide, CUICDMInstanceHandle inSourceInstance,
+ CUICDMSlideHandle inDestSlide, CUICDMInstanceHandle inDestInstance) override;
+
+ // ITransactionProducer implementation
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+
+ TSignalConnectionPtr ConnectAnimationCreated(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectBeforeAnimationDeleted(const std::function<void(CUICDMAnimationHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectAnimationDeleted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback) override;
+ TSignalConnectionPtr ConnectKeyframeInserted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectBeforeKeyframeErased(const std::function<void(CUICDMKeyframeHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectKeyframeErased(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectBeforeAllKeyframesErased(const std::function<void(CUICDMAnimationHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectKeyframeUpdated(
+ const std::function<void(CUICDMKeyframeHandle, const TKeyframe &)> &inCallback) override;
+ TSignalConnectionPtr ConnectFirstKeyframeDynamicSet(
+ const std::function<void(CUICDMAnimationHandle, bool)> &inCallback) override;
+
+private:
+ void InitSignaller();
+ IAnimationCoreSignalProvider *GetSignalProvider();
+ IAnimationCoreSignalSender *GetSignalSender();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/DataCoreProducer.cpp b/src/Authoring/UICDM/Systems/Cores/DataCoreProducer.cpp
new file mode 100644
index 00000000..6fd98020
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/DataCoreProducer.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "DataCoreProducer.h"
+#include "HandleSystemTransactions.h"
+#include "VectorTransactions.h"
+#include "SignalsImpl.h"
+#ifdef _WIN32
+#pragma warning(disable : 4503) // decorated name length exceeded
+#endif
+namespace UICDM {
+
+CUICDMInstanceHandle CDataCoreProducer::CreateInstance(CUICDMInstanceHandle inTargetId)
+{
+ CUICDMInstanceHandle retval = m_Data->CreateInstance(inTargetId);
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ GetDataCoreSender()->SignalInstanceCreated(retval);
+ return retval;
+}
+
+inline tuple<CUICDMPropertyHandle, SUICDMPropertyDefinition>
+TransformProperty(CUICDMPropertyHandle inProperty, CSimpleDataCore &inData)
+{
+ return make_tuple(inProperty, inData.GetProperty(inProperty));
+}
+
+inline void SignalPropertyRemoved(CUICDMInstanceHandle inInstance,
+ tuple<CUICDMPropertyHandle, SUICDMPropertyDefinition> inData,
+ IDataCoreSignalSender *inSender)
+{
+ inSender->SignalPropertyRemoved(inInstance, get<0>(inData), get<1>(inData).m_Name.wide_str(),
+ get<1>(inData).m_Type);
+}
+
+void CDataCoreProducer::DeleteInstance(CUICDMInstanceHandle inInstance)
+{
+ TIntList theProperties;
+ TIntList theInstances;
+
+ GetDataCoreSender()->SignalBeforeInstanceDeleted(inInstance);
+ // Ensure the instance exists
+ m_Data->GetInstanceNF(inInstance, m_Data->m_Objects);
+ do_all(m_Data->m_Objects,
+ std::bind(CSimpleDataCore::FindRelatedItemsForDelete, inInstance.GetHandleValue(),
+ std::ref(theProperties), std::ref(theInstances), std::placeholders::_1));
+
+ if (m_Consumer) {
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inInstance, m_Data->m_Objects);
+ do_all(theProperties, std::bind(HandleDeleteTransaction, __FILE__, __LINE__,
+ std::placeholders::_1,
+ std::ref(m_Data->m_Objects), m_Consumer));
+ }
+
+ vector<tuple<CUICDMPropertyHandle, SUICDMPropertyDefinition>> theDefinitionList;
+ theDefinitionList.resize(theProperties.size());
+
+ function<tuple<CUICDMPropertyHandle, SUICDMPropertyDefinition>(CUICDMPropertyHandle)>
+ thePropertyTransform(bind(TransformProperty, std::placeholders::_1, ref(*m_Data)));
+ transform(theProperties.begin(), theProperties.end(), theDefinitionList.begin(),
+ thePropertyTransform);
+
+ GetDataCoreSender()->SignalInstanceDeleted(inInstance);
+
+ m_Data->DeleteInstance(inInstance);
+ // Signal that these theProperties are no longer with us.
+ do_all(theDefinitionList, bind(SignalPropertyRemoved, inInstance,
+ std::placeholders::_1, GetDataCoreSender()));
+}
+
+bool CDataCoreProducer::IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const
+{
+ return m_Data->IsInstanceOrDerivedFrom(inInstance, inParent);
+}
+
+void CDataCoreProducer::GetInstances(TInstanceHandleList &outInstances) const
+{
+ m_Data->GetInstances(outInstances);
+}
+void CDataCoreProducer::GetInstancesDerivedFrom(TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParentHandle) const
+{
+ m_Data->GetInstancesDerivedFrom(outInstances, inParentHandle);
+}
+
+struct ClearInstanceParentCacheTransaction : public ITransaction
+{
+ const CDataModelInstance &m_Instance;
+ ClearInstanceParentCacheTransaction(const char *inFile, int inLine,
+ const CDataModelInstance &inst)
+ : ITransaction(inFile, inLine)
+ , m_Instance(inst)
+ {
+ }
+ void Do() override { m_Instance.ClearParentCache(); }
+ void Undo() override { m_Instance.ClearParentCache(); }
+};
+
+void CDataCoreProducer::DeriveInstance(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent)
+{
+ m_Data->DeriveInstance(inInstance, inParent);
+ TDataModelInstancePtr theInstance =
+ CSimpleDataCore::GetInstanceNF(inInstance, m_Data->m_Objects);
+ if (m_Consumer) {
+ CreateHashMapInsertTransaction(
+ __FILE__, __LINE__, m_Consumer,
+ make_pair(inParent.GetHandleValue(),
+ CSimpleDataCore::GetInstanceNF(inParent, m_Data->m_Objects)),
+ theInstance->m_Parents);
+ m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>(
+ std::make_shared<ClearInstanceParentCacheTransaction>(__FILE__, __LINE__,
+ *theInstance)));
+ }
+ GetDataCoreSender()->SignalInstanceDerived(inInstance, inParent);
+}
+
+void CDataCoreProducer::GetInstanceParents(CUICDMInstanceHandle inHandle,
+ TInstanceHandleList &outParents) const
+{
+ m_Data->GetInstanceParents(inHandle, outParents);
+}
+
+CUICDMPropertyHandle CDataCoreProducer::AddProperty(CUICDMInstanceHandle inInstance,
+ TCharPtr inName, DataModelDataType::Value inPropType)
+{
+ CUICDMPropertyHandle retval = m_Data->AddProperty(inInstance, inName, inPropType);
+ TDataModelInstancePtr theInstance =
+ CSimpleDataCore::GetInstanceNF(inInstance, m_Data->m_Objects);
+ CreateVecInsertTransaction<int>(__FILE__, __LINE__, m_Consumer, retval,
+ theInstance->m_Properties);
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ GetDataCoreSender()->SignalPropertyAdded(inInstance, retval, inName, inPropType);
+ return retval;
+}
+
+void CDataCoreProducer::GetInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const
+{
+ m_Data->GetInstanceProperties(inInstance, outProperties);
+}
+
+const SUICDMPropertyDefinition &
+CDataCoreProducer::GetProperty(CUICDMPropertyHandle inProperty) const
+{
+ return m_Data->GetProperty(inProperty);
+}
+
+void CDataCoreProducer::RemoveProperty(CUICDMPropertyHandle inProperty)
+{
+ SUICDMPropertyDefinition theDef = GetProperty(inProperty);
+ TDataModelInstancePtr theInstance =
+ CSimpleDataCore::GetInstanceNF(theDef.m_Instance, m_Data->m_Objects);
+ if (find_if<TIntList::iterator>(theInstance->m_Properties,
+ std::bind(equal_to<int>(), inProperty, std::placeholders::_1))
+ != theInstance->m_Properties.end()) {
+ CreateVecEraseTransaction<int>(__FILE__, __LINE__, m_Consumer, inProperty,
+ theInstance->m_Properties);
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inProperty, m_Data->m_Objects);
+ GetDataCoreSender()->SignalPropertyRemoved(theDef.m_Instance, inProperty,
+ theDef.m_Name.wide_str(), theDef.m_Type);
+ m_Data->RemoveProperty(inProperty);
+ } else {
+ throw PropertyNotFound(L"");
+ }
+}
+
+inline void AddCopyInstancePropertyTransaction(int inProperty, const TIntList &inOriginalList,
+ CDataModelInstance &inInstance,
+ TTransactionConsumerPtr &inConsumer)
+{
+ // if this property was never in the original list
+ if (find_if<TIntList::const_iterator>(inOriginalList,
+ std::bind(equal_to<int>(), inProperty,
+ std::placeholders::_1))
+ == inOriginalList.end())
+ CreateVecInsertTransaction<int>(__FILE__, __LINE__, inConsumer,
+ CUICDMPropertyHandle(inProperty), inInstance.m_Properties);
+}
+
+inline void AddCopyInstanceValuePropertyTransaction(const TPropertyPair &inProperty,
+ const TPropertyPairHash &inOriginalList,
+ CDataModelInstance &inInstance,
+ TTransactionConsumerPtr &inConsumer)
+{
+ // if this property was never in the original list
+ if (inOriginalList.end() == inOriginalList.find(inProperty.first))
+ CreateHashMapInsertTransaction(__FILE__, __LINE__, inConsumer, inProperty,
+ inInstance.m_PropertyValues);
+}
+
+struct InstancePropertyValuesTransaction : public ITransaction
+{
+ CDataModelInstance &m_Instance;
+ TIntList m_OldProperties;
+ TPropertyPairList m_OldValues;
+ TIntList m_NewProperties;
+ TPropertyPairList m_NewValues;
+
+ InstancePropertyValuesTransaction(const char *inFile, int inLine,
+ CDataModelInstance &inInstance)
+ : ITransaction(inFile, inLine)
+ , m_Instance(inInstance)
+ , m_OldProperties(inInstance.m_Properties)
+ {
+ inInstance.ToPropertyPairList(m_OldValues);
+ }
+
+ void SetNew()
+ {
+ m_NewProperties = m_Instance.m_Properties;
+ m_Instance.ToPropertyPairList(m_NewValues);
+ }
+
+ void Do() override
+ {
+ m_Instance.m_Properties = m_NewProperties;
+ m_Instance.FromPropertyPairList(m_NewValues);
+ }
+
+ void Undo() override
+ {
+ m_Instance.m_Properties = m_OldProperties;
+ m_Instance.FromPropertyPairList(m_OldValues);
+ }
+};
+
+void CDataCoreProducer::CopyInstanceProperties(CUICDMInstanceHandle inSrcInstance,
+ CUICDMInstanceHandle inDestInstance)
+{
+ TDataModelInstancePtr theInstance =
+ CSimpleDataCore::GetInstanceNF(inDestInstance, m_Data->m_Objects);
+ if (m_Consumer) {
+ // Create the transaction object setting its 'old values' property to the current instance
+ // property values.
+ std::shared_ptr<InstancePropertyValuesTransaction> theTransaction(
+ std::make_shared<InstancePropertyValuesTransaction>(__FILE__, __LINE__,
+ ref(*theInstance)));
+
+ // Change the current instance property values
+ m_Data->CopyInstanceProperties(inSrcInstance, inDestInstance);
+
+ // Ask the transaction to copy the new values into it's new values datastructure.
+ theTransaction->SetNew();
+
+ m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>(theTransaction));
+ } else {
+ m_Data->CopyInstanceProperties(inSrcInstance, inDestInstance);
+ }
+}
+
+CUICDMPropertyHandle
+CDataCoreProducer::GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const
+{
+ return m_Data->GetAggregateInstancePropertyByName(inInstance, inStr);
+}
+
+void CDataCoreProducer::GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const
+{
+ m_Data->GetAggregateInstanceProperties(inInstance, outProperties);
+}
+
+void CDataCoreProducer::GetSpecificInstancePropertyValues(CUICDMInstanceHandle inHandle,
+ TPropertyHandleValuePairList &outValues)
+{
+ m_Data->GetSpecificInstancePropertyValues(inHandle, outValues);
+}
+
+bool CDataCoreProducer::HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ return m_Data->HasAggregateInstanceProperty(inInstance, inProperty);
+}
+
+void CDataCoreProducer::CheckValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ const SValue &inValue) const
+{
+ return m_Data->CheckValue(inInstance, inProperty, inValue);
+}
+
+bool CDataCoreProducer::GetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ return m_Data->GetInstancePropertyValue(inHandle, inProperty, outValue);
+}
+
+inline void EraseProperty(TPropertyPairHash &inProperties, int inProperty)
+{
+ inProperties.erase(
+ find_if(inProperties.begin(), inProperties.end(),
+ std::bind(CSimpleDataCore::InstancePropertyMatches, inProperty,
+ std::placeholders::_1)));
+}
+
+void CDataCoreProducer::SetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ // Two possible courses of actions. The property exists, in which case
+ // we need to get its old value.
+ // If it doesn't exist, then we need to erase for undo.
+ TPropertyValuePair theOldValue(PropertyValueFlags(PropertyValueFlags::SetViaAutoPropagate),
+ SInternValue(0.0f, GetStringTable()));
+ TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inHandle, m_Data->m_Objects);
+ TPropertyPairHash::iterator theItem =
+ theInstance->m_PropertyValues.find(inProperty.GetHandleValue());
+ bool foundProp = theItem != theInstance->m_PropertyValues.end();
+ if (foundProp)
+ theOldValue = theItem->second;
+ m_Data->SetInstancePropertyValue(inHandle, inProperty, inValue);
+ TPropertyValuePair theNewValue =
+ theInstance->m_PropertyValues.find(inProperty.GetHandleValue())->second;
+ if (m_Consumer) {
+ // Check if we already have the entry
+ TSlideInstancePropertyPair theKey(inHandle, inProperty);
+ TPropertyMergeMap::iterator iter = m_PropertyMergeMap.find(theKey);
+ // Then we merge the values in to the original event where they
+ // first happened.
+ if (iter != m_PropertyMergeMap.end()) {
+ iter->second->Update(theNewValue);
+ return; // don't send the signal if we just updated value
+ } else // Else we add a new merge entry.
+ {
+ TPropertyMergeMapEntry theEntry;
+ if (!foundProp)
+ theEntry = CreateHashMapInsertTransaction(
+ __FILE__, __LINE__, m_Consumer,
+ make_pair(inProperty.GetHandleValue(), theNewValue),
+ theInstance->m_PropertyValues);
+ else
+ theEntry = CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer,
+ inProperty.GetHandleValue(), theOldValue,
+ theNewValue, theInstance->m_PropertyValues);
+ m_PropertyMergeMap.insert(std::make_pair(theKey, theEntry));
+ }
+ }
+ GetPropertyCoreSender()->SignalInstancePropertyValue(inHandle, inProperty, inValue);
+}
+
+bool CDataCoreProducer::HandleValid(int inHandle) const
+{
+ return m_Data->HandleValid(inHandle);
+}
+
+void CDataCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_Consumer = inConsumer;
+ m_PropertyMergeMap.clear();
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectInstancePropertyValue(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue &)>
+ &inCallback)
+{
+ return GetPropertyCoreProvider()->ConnectInstancePropertyValue(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectInstanceCreated(
+ const std::function<void(CUICDMInstanceHandle)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectInstanceCreated(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectInstanceDeleted(
+ const std::function<void(CUICDMInstanceHandle)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectInstanceDeleted(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectBeforeInstanceDeleted(
+ const std::function<void(CUICDMInstanceHandle)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectBeforeInstanceDeleted(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectInstanceDerived(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectInstanceDerived(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectInstanceParentRemoved(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectInstanceParentRemoved(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectPropertyAdded(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, TCharPtr,
+ DataModelDataType::Value)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectPropertyAdded(inCallback);
+}
+
+TSignalConnectionPtr CDataCoreProducer::ConnectPropertyRemoved(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, TCharPtr,
+ DataModelDataType::Value)> &inCallback)
+{
+ return GetDataCoreProvider()->ConnectPropertyRemoved(inCallback);
+}
+
+void CDataCoreProducer::InitSignallers()
+{
+ m_InstancePropertyCoreSignaller = CreatePropertyCoreSignaller();
+ m_DataCoreSignaller = CreateDataCoreSignaller();
+}
+
+IInstancePropertyCoreSignalProvider *CDataCoreProducer::GetPropertyCoreProvider()
+{
+ return dynamic_cast<IInstancePropertyCoreSignalProvider *>(
+ m_InstancePropertyCoreSignaller.get());
+}
+
+IInstancePropertyCoreSignalSender *CDataCoreProducer::GetPropertyCoreSender()
+{
+ return dynamic_cast<IInstancePropertyCoreSignalSender *>(m_InstancePropertyCoreSignaller.get());
+}
+
+IDataCoreSignalProvider *CDataCoreProducer::GetDataCoreProvider()
+{
+ return dynamic_cast<IDataCoreSignalProvider *>(m_DataCoreSignaller.get());
+}
+
+IDataCoreSignalSender *CDataCoreProducer::GetDataCoreSender()
+{
+ return dynamic_cast<IDataCoreSignalSender *>(m_DataCoreSignaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/DataCoreProducer.h b/src/Authoring/UICDM/Systems/Cores/DataCoreProducer.h
new file mode 100644
index 00000000..cd44646c
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/DataCoreProducer.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef DATACOREPRODUCERH
+#define DATACOREPRODUCERH
+
+#include "UICDMTransactions.h"
+#include "SimpleDataCore.h"
+#include "UICDMSignals.h"
+#include "SimpleSlideCore.h"
+
+namespace UICDM {
+
+class CDataCoreProducer : public IDataCore,
+ public ITransactionProducer,
+ public IInstancePropertyCoreSignalProvider,
+ public IDataCoreSignalProvider
+{
+ typedef std::shared_ptr<IMergeableTransaction<TPropertyValuePair>> TPropertyMergeMapEntry;
+ typedef std::unordered_map<TSlideInstancePropertyPair, TPropertyMergeMapEntry>
+ TPropertyMergeMap;
+
+ TTransactionConsumerPtr m_Consumer;
+ TSimpleDataCorePtr m_Data;
+ TSignalItemPtr m_InstancePropertyCoreSignaller;
+ TSignalItemPtr m_DataCoreSignaller;
+
+ TPropertyMergeMap m_PropertyMergeMap;
+
+public:
+ CDataCoreProducer(TStringTablePtr inStringTable)
+ : m_Data(new CSimpleDataCore(inStringTable))
+ {
+ InitSignallers();
+ }
+ virtual ~CDataCoreProducer() {}
+
+ IStringTable &GetStringTable() const override { return m_Data->GetStringTable(); }
+ std::shared_ptr<IStringTable> GetStringTablePtr() const override
+ {
+ return m_Data->GetStringTablePtr();
+ }
+
+ // IHandleBase
+ bool HandleValid(int inHandle) const override;
+
+ // IInstancePropertyCore
+ //===============================================================
+ CUICDMPropertyHandle GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const override;
+ void GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const override;
+ void GetSpecificInstancePropertyValues(CUICDMInstanceHandle inHandle,
+ TPropertyHandleValuePairList &outValues) override;
+ bool HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+
+ void CheckValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ const SValue &inValue) const override;
+ bool GetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ void SetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+ //===============================================================
+
+ // IDataCore
+ //===============================================================
+ CUICDMInstanceHandle CreateInstance(CUICDMInstanceHandle hdl = CUICDMInstanceHandle()) override;
+ void GetInstances(TInstanceHandleList &outInstances) const override;
+ void GetInstancesDerivedFrom(TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParent) const override;
+ void DeleteInstance(CUICDMInstanceHandle inHandle) override;
+
+ void DeriveInstance(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent) override;
+ void GetInstanceParents(CUICDMInstanceHandle inHandle,
+ TInstanceHandleList &outParents) const override;
+ bool IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const override;
+
+ CUICDMPropertyHandle AddProperty(CUICDMInstanceHandle inInstance, TCharPtr inName,
+ DataModelDataType::Value inPropType) override;
+ void GetInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const override;
+ const SUICDMPropertyDefinition &GetProperty(CUICDMPropertyHandle inProperty) const override;
+ void RemoveProperty(CUICDMPropertyHandle inProperty) override;
+ void CopyInstanceProperties(CUICDMInstanceHandle inSrcInstance,
+ CUICDMInstanceHandle inDestInstance) override;
+
+ void RemoveCachedValues(CUICDMInstanceHandle inInstance) override
+ {
+ m_Data->RemoveCachedValues(inInstance);
+ }
+ bool IsInstance(int inHandle) const override { return m_Data->IsInstance(inHandle); }
+ bool IsProperty(int inHandle) const override { return m_Data->IsProperty(inHandle); }
+ //===============================================================
+
+ //===============================================================
+ // Set the current consumer
+ //===============================================================
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+
+ //===============================================================
+ // Return a serializable data model for load/save
+ //===============================================================
+ virtual TSimpleDataCorePtr GetTransactionlessDataCore() { return m_Data; }
+ virtual TSimpleDataCorePtr GetTransactionlessDataCore() const { return m_Data; }
+
+ //===============================================================
+ // Signal provider implementation
+ //===============================================================
+ TSignalConnectionPtr ConnectInstancePropertyValue(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue &)>
+ &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectInstanceCreated(const std::function<void(CUICDMInstanceHandle)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectBeforeInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectInstanceDerived(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectInstanceParentRemoved(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectPropertyAdded(const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle,
+ TCharPtr, DataModelDataType::Value)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectPropertyRemoved(const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle,
+ TCharPtr, DataModelDataType::Value)> &inCallback) override;
+
+private:
+ CDataCoreProducer(const CDataCoreProducer&) = delete;
+ CDataCoreProducer& operator=(const CDataCoreProducer&) = delete;
+
+ template <typename TTransactionType>
+ inline void RunWithConsumer(TTransactionType inTransaction)
+ {
+ UICDM::RunWithConsumer(m_Consumer, inTransaction);
+ }
+
+ void InitSignallers();
+ IInstancePropertyCoreSignalProvider *GetPropertyCoreProvider();
+ IInstancePropertyCoreSignalSender *GetPropertyCoreSender();
+ IDataCoreSignalProvider *GetDataCoreProvider();
+ IDataCoreSignalSender *GetDataCoreSender();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleActionCore.cpp b/src/Authoring/UICDM/Systems/Cores/SimpleActionCore.cpp
new file mode 100644
index 00000000..684c06f7
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleActionCore.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "SimpleActionCore.h"
+
+namespace UICDM {
+
+CUICDMActionHandle CSimpleActionCore::CreateAction(CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner,
+ SLong4 inTriggerTargetObjects)
+{
+ int nextId = GetNextId();
+ CUICDMActionHandle retval = CreateActionWithHandle(nextId, inInstance, inSlide, inOwner);
+ SetTriggerObject(retval, inTriggerTargetObjects);
+ SetTargetObject(retval, inTriggerTargetObjects);
+ return retval;
+}
+
+void CSimpleActionCore::DeleteAction(CUICDMActionHandle inAction, CUICDMInstanceHandle &outInstance)
+{
+ SAction *theAction = GetActionNF(inAction, m_Objects);
+ outInstance = theAction->m_ActionInfo.m_Instance;
+ do_all(theAction->m_ActionInfo.m_HandlerArgs,
+ std::bind(EraseHandle, std::placeholders::_1, std::ref(m_Objects)));
+ EraseHandle(inAction, m_Objects);
+}
+
+const SActionInfo &CSimpleActionCore::GetActionInfo(CUICDMActionHandle inAction) const
+{
+ const SAction *theAction = GetActionNF(inAction, m_Objects);
+ return theAction->m_ActionInfo;
+}
+
+inline void AddIfActionMatches(const THandleObjectPair &inPair, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner, TActionHandleList &outActions)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeAction) {
+ const SAction *theAction = static_cast<SAction *>(inPair.second.get());
+ if ((!inSlide.Valid() || inSlide == theAction->m_ActionInfo.m_Slide)
+ && (!inOwner.Valid() || inOwner == theAction->m_ActionInfo.m_Owner))
+ outActions.push_back(inPair.first);
+ }
+}
+
+// Return all actions that belong to a certain instance in a certain slide
+void CSimpleActionCore::GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const
+{
+ outActions.clear();
+ do_all(m_Objects,
+ std::bind(AddIfActionMatches,
+ std::placeholders::_1, inSlide, inOwner, std::ref(outActions)));
+}
+
+// Return all actions that exist in a certain slide
+void CSimpleActionCore::GetActions(CUICDMSlideHandle inSlide, TActionHandleList &outActions) const
+{
+ GetActions(inSlide, 0, outActions);
+}
+
+// Return all actions that belong to a certain instance
+void CSimpleActionCore::GetActions(CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const
+{
+ GetActions(0, inOwner, outActions);
+}
+
+// Return all actions
+void CSimpleActionCore::GetActions(TActionHandleList &outActions) const
+{
+ outActions.clear();
+ outActions.reserve(m_Objects.size());
+ do_all(m_Objects,
+ std::bind(MaybeAddObject<SAction, CUICDMActionHandle>,
+ std::placeholders::_1, std::ref(outActions)));
+}
+
+// Return the instance that was allocated for this action.
+CUICDMInstanceHandle CSimpleActionCore::GetActionInstance(CUICDMActionHandle inAction) const
+{
+ return GetActionNF(inAction, m_Objects)->m_ActionInfo.m_Instance;
+}
+
+inline bool ActionInstanceMatches(const THandleObjectPair &inPair, CUICDMInstanceHandle inInstance)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeAction) {
+ const SAction *theAction = static_cast<SAction *>(inPair.second.get());
+ if (inInstance == theAction->m_ActionInfo.m_Instance)
+ return true;
+ }
+ return false;
+}
+
+// Reverse lookup into the action system so you can match actions to instances.
+CUICDMActionHandle
+CSimpleActionCore::GetActionByInstance(CUICDMInstanceHandle inActionInstance) const
+{
+ THandleObjectMap::const_iterator theAction =
+ find_if(m_Objects.begin(), m_Objects.end(),
+ std::bind(ActionInstanceMatches, std::placeholders::_1, inActionInstance));
+ if (theAction != m_Objects.end())
+ return theAction->first;
+ throw ActionNotFound(L"");
+}
+
+// Action Properties
+void CSimpleActionCore::SetTriggerObject(CUICDMActionHandle inAction,
+ const SObjectRefType &inTriggerObject)
+{
+ SAction *theAction = GetActionNF(inAction, m_Objects);
+ theAction->m_ActionInfo.m_TriggerObject = inTriggerObject;
+}
+
+void CSimpleActionCore::SetTargetObject(CUICDMActionHandle inAction,
+ const SObjectRefType &inTargetObject)
+{
+ SAction *theAction = GetActionNF(inAction, m_Objects);
+ theAction->m_ActionInfo.m_TargetObject = inTargetObject;
+}
+
+void CSimpleActionCore::SetEvent(CUICDMActionHandle inAction, const wstring &inEventHandle)
+{
+ SAction *theAction = GetActionNF(inAction, m_Objects);
+ theAction->m_ActionInfo.m_Event = inEventHandle;
+}
+
+void CSimpleActionCore::SetHandler(CUICDMActionHandle inAction, const wstring &inHandlerHandle)
+{
+ SAction *theAction = GetActionNF(inAction, m_Objects);
+ theAction->m_ActionInfo.m_Handler = inHandlerHandle;
+}
+
+// Action Argument
+CUICDMHandlerArgHandle CSimpleActionCore::AddHandlerArgument(CUICDMActionHandle inAction,
+ const TCharStr &inName,
+ HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType)
+{
+ int nextId = GetNextId();
+ return AddHandlerArgumentWithHandle(nextId, inAction, inName, inArgType, inValueType);
+}
+
+void CSimpleActionCore::RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument)
+{
+ SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects);
+ SAction *theAction = GetActionNF(theHandlerArgument->m_HandlerArgInfo.m_Action, m_Objects);
+ EraseHandle(inHandlerArgument, m_Objects);
+ erase_if(theAction->m_ActionInfo.m_HandlerArgs,
+ std::bind(equal_to<int>(), std::placeholders::_1, inHandlerArgument.GetHandleValue()));
+}
+
+const SHandlerArgumentInfo &
+CSimpleActionCore::GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const
+{
+ if (HandleValid(inHandlerArgument)) {
+ const SHandlerArgument *theHandlerArgument =
+ GetHandlerArgumentNF(inHandlerArgument, m_Objects);
+ return theHandlerArgument->m_HandlerArgInfo;
+ } else {
+ static SHandlerArgumentInfo dummy;
+ return dummy;
+ }
+}
+
+void CSimpleActionCore::GetHandlerArguments(CUICDMActionHandle inAction,
+ THandlerArgHandleList &outHandlerArguments) const
+{
+ const SAction *theAction = GetActionNF(inAction, m_Objects);
+ outHandlerArguments = theAction->m_ActionInfo.m_HandlerArgs;
+}
+
+// Action Argument Properties
+void CSimpleActionCore::GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ SValue &outValue) const
+{
+ const SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects);
+ outValue = theHandlerArgument->m_HandlerArgInfo.m_Value;
+}
+
+void CSimpleActionCore::SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ const SValue &inValue)
+{
+ SHandlerArgument *theHandlerArgument = GetHandlerArgumentNF(inHandlerArgument, m_Objects);
+ theHandlerArgument->m_HandlerArgInfo.m_Value = inValue;
+}
+
+// Helper functions
+CUICDMActionHandle CSimpleActionCore::CreateActionWithHandle(int inHandle,
+ CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner)
+{
+ if (HandleValid(inHandle))
+ throw HandleExists(L"");
+ m_Objects.insert(make_pair(
+ inHandle, (THandleObjectPtr) new SAction(inHandle, inInstance, inSlide, inOwner)));
+ return inHandle;
+}
+
+CUICDMHandlerArgHandle
+CSimpleActionCore::AddHandlerArgumentWithHandle(int inHandle, CUICDMActionHandle inAction,
+ const TCharStr &inName, HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType)
+{
+ if (HandleValid(inHandle))
+ throw HandleExists(L"");
+ m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SHandlerArgument(
+ inHandle, inAction, inName, inArgType, inValueType)));
+ SAction *theAction = GetActionNF(inAction, m_Objects);
+ theAction->m_ActionInfo.m_HandlerArgs.push_back(inHandle);
+ return inHandle;
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleActionCore.h b/src/Authoring/UICDM/Systems/Cores/SimpleActionCore.h
new file mode 100644
index 00000000..bf82c57a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleActionCore.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ACTIONCOREH
+#define ACTIONCOREH
+
+#include "UICDMActionCore.h"
+#include "HandleSystemBase.h"
+#include "UICDMErrors.h"
+
+namespace UICDM {
+struct SAction : public CHandleObject
+{
+ SActionInfo m_ActionInfo;
+
+ SAction() {}
+
+ SAction(int inHandle, CUICDMInstanceHandle inInstance, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner)
+ : CHandleObject(inHandle)
+ , m_ActionInfo(inInstance, inSlide, inOwner)
+ {
+ }
+
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeAction;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+struct SHandlerArgument : public CHandleObject
+{
+ SHandlerArgumentInfo m_HandlerArgInfo;
+
+ SHandlerArgument() {}
+
+ SHandlerArgument(int inHandle, CUICDMActionHandle inAction, const TCharStr &inName,
+ HandlerArgumentType::Value inArgType, DataModelDataType::Value inValueType)
+ : CHandleObject(inHandle)
+ , m_HandlerArgInfo(inAction, inName, inArgType, inValueType)
+ {
+ }
+
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeActionHandlerArgument;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+class CSimpleActionCore : public CHandleBase, public IActionCore
+{
+ mutable TStringTablePtr m_StringTable;
+
+public: // Use
+ CSimpleActionCore(TStringTablePtr strTable)
+ : m_StringTable(strTable)
+ {
+ }
+
+ IStringTable &GetStringTable() const override { return *m_StringTable.get(); }
+ TStringTablePtr GetStringTablePtr() const override { return m_StringTable; }
+ // Action
+ CUICDMActionHandle CreateAction(CUICDMInstanceHandle inInstance, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner, SLong4 inTriggerTargetObjects) override;
+ void DeleteAction(CUICDMActionHandle inAction, CUICDMInstanceHandle &outInstance) override;
+ const SActionInfo &GetActionInfo(CUICDMActionHandle inAction) const override;
+ void GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const override;
+ void GetActions(CUICDMSlideHandle inSlide, TActionHandleList &outActions) const override;
+ void GetActions(CUICDMInstanceHandle inOwner, TActionHandleList &outActions) const override;
+ void GetActions(TActionHandleList &outActions) const override;
+
+ // Return the instance that was allocated for this action.
+ CUICDMInstanceHandle GetActionInstance(CUICDMActionHandle inAction) const override;
+ // Reverse lookup into the action system so you can match actions to instances.
+ CUICDMActionHandle GetActionByInstance(CUICDMInstanceHandle inActionInstance) const override;
+
+ // Action Properties
+ void SetTriggerObject(CUICDMActionHandle inAction, const SObjectRefType &inTriggerObject) override;
+ void SetTargetObject(CUICDMActionHandle inAction, const SObjectRefType &inTargetObject) override;
+ void SetEvent(CUICDMActionHandle inAction, const wstring &inEvent) override;
+ void SetHandler(CUICDMActionHandle inAction, const wstring &inHandler) override;
+
+ // Action Argument
+ CUICDMHandlerArgHandle AddHandlerArgument(CUICDMActionHandle inAction, const TCharStr &inName,
+ HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) override;
+ void RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument) override;
+ const SHandlerArgumentInfo &
+ GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const override;
+ void GetHandlerArguments(CUICDMActionHandle inAction,
+ THandlerArgHandleList &outHandlerArguments) const override;
+
+ // Action Argument Properties
+ void GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, SValue &outValue) const override;
+ void SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument, const SValue &inValue) override;
+
+ // CHandleBase
+ bool HandleValid(int inHandle) const override { return CHandleBase::HandleValid(inHandle); }
+
+ // Helper functions
+ CUICDMActionHandle CreateActionWithHandle(int inHandle, CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner);
+ CUICDMHandlerArgHandle AddHandlerArgumentWithHandle(int inHandle, CUICDMActionHandle inAction,
+ const TCharStr &inName,
+ HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType);
+
+ static SAction *GetActionNF(int inHandle, THandleObjectMap &inObjects)
+ {
+ return const_cast<SAction *>(
+ GetActionNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const SAction *GetActionNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ const SAction *theAction = GetHandleObject<SAction>(inHandle, inObjects);
+ if (theAction)
+ return theAction;
+ throw ActionNotFound(L"");
+ }
+
+ static SHandlerArgument *GetHandlerArgumentNF(int inHandle, THandleObjectMap &inObjects)
+ {
+ return const_cast<SHandlerArgument *>(
+ GetHandlerArgumentNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const SHandlerArgument *GetHandlerArgumentNF(int inHandle,
+ const THandleObjectMap &inObjects)
+ {
+ const SHandlerArgument *theItem = GetHandleObject<SHandlerArgument>(inHandle, inObjects);
+ if (theItem)
+ return theItem;
+ throw HandlerArgumentNotFound(L"");
+ }
+};
+
+typedef std::shared_ptr<CSimpleActionCore> TSimpleActionCorePtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.cpp b/src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.cpp
new file mode 100644
index 00000000..7f000324
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.cpp
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "SimpleAnimationCore.h"
+
+typedef long INT32;
+typedef float FLOAT;
+#define DATALOGGER_CUBICROOT 0
+
+struct SPerfLogEvent
+{
+ SPerfLogEvent(int) {}
+};
+
+typedef SPerfLogEvent TPerfLogMathEvent1;
+
+#include "UICCubicRoots.h"
+#include "UICCubicRootsImpl.h"
+#include "UICBezierEval.h"
+#include <boost/unordered_map.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+using namespace std;
+using namespace boost;
+
+namespace UICDM {
+
+CUICDMAnimationHandle
+CSimpleAnimationCore::CreateAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType, bool inFirstKeyframeDynamic)
+{
+ if (GetAnimation(inSlide, inInstance, inProperty, inIndex).Valid())
+ throw AnimationExists(L"");
+
+ int nextId = GetNextId();
+ CUICDMAnimationHandle retval = CreateAnimationWithHandle(
+ nextId, inSlide, inInstance, inProperty, inIndex, inAnimationType, inFirstKeyframeDynamic);
+ AddAnimationToLookupCache(retval);
+ return retval;
+}
+
+void CSimpleAnimationCore::DeleteAnimation(CUICDMAnimationHandle inAnimation)
+{
+ RemoveAnimationFromLookupCache(inAnimation);
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ do_all(theItem->m_Keyframes, std::bind(EraseHandle,
+ std::placeholders::_1, std::ref(m_Objects)));
+ EraseHandle(inAnimation, m_Objects);
+}
+
+void CSimpleAnimationCore::EnsureAnimationCache() const
+{
+ if (m_AnimationMatchesCache.size() == 0) {
+ for (THandleObjectMap::const_iterator theIter = m_Objects.begin(), theEnd = m_Objects.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack)
+ AddAnimationToLookupCache(static_pointer_cast<SAnimationTrack>(theIter->second));
+ }
+ }
+}
+
+CUICDMAnimationHandle CSimpleAnimationCore::GetAnimation(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ size_t inIndex) const
+{
+ EnsureAnimationCache();
+
+ pair<TStateInstanceAnimationMap::const_iterator, TStateInstanceAnimationMap::const_iterator>
+ theRange(m_AnimationMatchesCache.equal_range(
+ make_pair(inSlide.GetHandleValue(), inInstance.GetHandleValue())));
+ for (TStateInstanceAnimationMap::const_iterator theIter = theRange.first;
+ theIter != theRange.second; ++theIter) {
+ std::shared_ptr<SAnimationTrack> theItem = theIter->second;
+ if (inSlide.GetHandleValue() == theItem->m_Slide
+ && inInstance.GetHandleValue() == theItem->m_Instance
+ && inProperty.GetHandleValue() == theItem->m_Property && inIndex == theItem->m_Index)
+ return theItem->m_Handle;
+ }
+ return 0;
+}
+
+SAnimationInfo CSimpleAnimationCore::GetAnimationInfo(CUICDMAnimationHandle inAnimation) const
+{
+ if (m_Objects.find(inAnimation) != m_Objects.end()) {
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ return CreateAnimationInfo(theItem->m_Slide, theItem->m_Instance, theItem->m_Property,
+ theItem->m_Index, theItem->m_AnimationType,
+ theItem->m_FirstKeyframeDynamic, theItem->m_ArtistEdited);
+ }
+ return SAnimationInfo();
+}
+
+inline void AddIfAnimation(const THandleObjectPair &inPair, TAnimationHandleList &outAnimations)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack)
+ outAnimations.push_back(inPair.first);
+}
+
+void CSimpleAnimationCore::GetAnimations(TAnimationHandleList &outAnimations) const
+{
+ outAnimations.clear();
+ do_all(m_Objects, std::bind(AddIfAnimation, std::placeholders::_1, std::ref(outAnimations)));
+}
+
+void CSimpleAnimationCore::GetAnimations(TAnimationInfoList &outAnimations,
+ CUICDMSlideHandle inMaster,
+ CUICDMSlideHandle inSlide) const
+{
+ outAnimations.clear();
+ for (THandleObjectMap::const_iterator iter = m_Objects.begin(), end = m_Objects.end();
+ iter != end; ++iter) {
+ if (iter->second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) {
+ const SAnimationTrack *theItem =
+ static_cast<const SAnimationTrack *>(iter->second.get());
+ // If either master or slide is valid, then item slide must match.
+ // If item slide matches neither, then we ignore unless neither are valid.
+ bool keep = (theItem->m_Slide == inMaster || theItem->m_Slide == inSlide)
+ || (inMaster.Valid() == false && inSlide.Valid() == false);
+ if (keep) {
+ outAnimations.push_back(
+ CreateAnimationInfo(theItem->m_Slide, theItem->m_Instance, theItem->m_Property,
+ theItem->m_Index, theItem->m_AnimationType,
+ theItem->m_FirstKeyframeDynamic, theItem->m_ArtistEdited));
+ }
+ }
+ }
+}
+
+inline void AddSpecificAnimationsIf(const THandleObjectPair &inPair, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSAnimationTrack) {
+ const SAnimationTrack *theTrack = static_cast<const SAnimationTrack *>(inPair.second.get());
+ if (theTrack->m_Slide == inSlide && theTrack->m_Instance == inInstance)
+ outAnimations.push_back(inPair.first);
+ }
+}
+
+void CSimpleAnimationCore::GetSpecificInstanceAnimations(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations)
+{
+ EnsureAnimationCache();
+ pair<TStateInstanceAnimationMap::const_iterator, TStateInstanceAnimationMap::const_iterator>
+ theRange(m_AnimationMatchesCache.equal_range(
+ make_pair(inSlide.GetHandleValue(), inInstance.GetHandleValue())));
+ for (TStateInstanceAnimationMap::const_iterator iter = theRange.first; iter != theRange.second;
+ ++iter)
+ outAnimations.push_back(iter->second->m_Handle);
+}
+
+void CSimpleAnimationCore::SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation, bool inValue)
+{
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ theItem->m_FirstKeyframeDynamic = inValue;
+ SetIsArtistEdited(inAnimation);
+}
+
+inline void CheckKeyframeType(EAnimationType inExpected, const TKeyframe &inKeyframe)
+{
+ if (inExpected != GetKeyframeType(inKeyframe))
+ throw AnimationKeyframeTypeError(L"");
+}
+
+// keyframe manipulation
+CUICDMKeyframeHandle CSimpleAnimationCore::InsertKeyframe(CUICDMAnimationHandle inAnimation,
+ const TKeyframe &inKeyframe)
+{
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ CheckKeyframeType(theItem->m_AnimationType, inKeyframe);
+ int nextId = GetNextId();
+ m_Objects.insert(
+ make_pair(nextId, (THandleObjectPtr) new SKeyframe(nextId, inAnimation, inKeyframe)));
+ theItem->m_Keyframes.push_back(nextId);
+ theItem->m_KeyframesDirty = true;
+ SetIsArtistEdited(inAnimation);
+ return nextId;
+}
+
+void CSimpleAnimationCore::EraseKeyframe(CUICDMKeyframeHandle inKeyframe)
+{
+ SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ int theAnimHandle(theKeyframe->m_Animation);
+ SAnimationTrack *theItem = GetAnimationNF(theAnimHandle, m_Objects);
+ EraseHandle(inKeyframe, m_Objects);
+ erase_if(theItem->m_Keyframes, std::bind(equal_to<int>(),
+ std::placeholders::_1, inKeyframe.GetHandleValue()));
+ SetIsArtistEdited(theAnimHandle);
+}
+
+void CSimpleAnimationCore::DeleteAllKeyframes(CUICDMAnimationHandle inAnimation)
+{
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ do_all(theItem->m_Keyframes, std::bind(EraseHandle,
+ std::placeholders::_1, std::ref(m_Objects)));
+ theItem->m_Keyframes.clear();
+ SetIsArtistEdited(inAnimation);
+}
+
+CUICDMAnimationHandle
+CSimpleAnimationCore::GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const
+{
+ const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ return theKeyframe->m_Animation;
+}
+
+TKeyframe CSimpleAnimationCore::GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const
+{
+ const SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ return theKeyframe->m_Keyframe;
+}
+
+void CSimpleAnimationCore::SetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData)
+{
+ DoSetKeyframeData(inKeyframe, inData);
+ SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ SetIsArtistEdited(theKeyframe->m_Animation);
+}
+
+void CSimpleAnimationCore::DoSetKeyframeData(CUICDMKeyframeHandle inKeyframe,
+ const TKeyframe &inData)
+{
+ SKeyframe *theKeyframe = GetKeyframeNF(inKeyframe, m_Objects);
+ CheckKeyframeType(GetKeyframeType(theKeyframe->m_Keyframe), inData);
+ theKeyframe->m_Keyframe = inData;
+ SAnimationTrack *theItem = GetAnimationNF(theKeyframe->m_Animation, m_Objects);
+ theItem->m_KeyframesDirty = true;
+}
+
+bool KeyframeLessThan(int inLeftSide, int inRightSide, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theLeft = CSimpleAnimationCore::GetKeyframeNF(inLeftSide, inObjects);
+ const SKeyframe *theRight = CSimpleAnimationCore::GetKeyframeNF(inRightSide, inObjects);
+ return KeyframeTime(theLeft->m_Keyframe) < KeyframeTime(theRight->m_Keyframe);
+}
+
+void SortKeyframes(TKeyframeHandleList &inKeyframes, const THandleObjectMap &inObjects)
+{
+ return stable_sort(inKeyframes.begin(), inKeyframes.end(),
+ std::bind(KeyframeLessThan, std::placeholders::_1,
+ std::placeholders::_2, std::ref(inObjects)));
+}
+
+void CheckKeyframesSorted(const SAnimationTrack *theItem, const THandleObjectMap &inObjects)
+{
+ if (theItem->m_KeyframesDirty) {
+ SAnimationTrack *theNonConst = const_cast<SAnimationTrack *>(theItem);
+ SortKeyframes(theNonConst->m_Keyframes, inObjects);
+ theNonConst->m_KeyframesDirty = false;
+ }
+}
+
+void CSimpleAnimationCore::GetKeyframes(CUICDMAnimationHandle inAnimation,
+ TKeyframeHandleList &outKeyframes) const
+{
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ CheckKeyframesSorted(theItem, m_Objects);
+ outKeyframes = theItem->m_Keyframes;
+}
+
+size_t CSimpleAnimationCore::GetKeyframeCount(CUICDMAnimationHandle inAnimation) const
+{
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ return theItem->m_Keyframes.size();
+}
+
+bool CSimpleAnimationCore::IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const
+{
+ CUICDMAnimationHandle theAnimation = GetAnimationForKeyframe(inKeyframe);
+ if (theAnimation.Valid()) {
+ const SAnimationTrack *theItem = GetAnimationNF(theAnimation, m_Objects);
+ return theItem->m_Keyframes.size() && theItem->m_Keyframes[0] == inKeyframe;
+ }
+ return false;
+}
+
+void CSimpleAnimationCore::OffsetAnimations(CUICDMSlideHandle /*inSlide*/,
+ CUICDMInstanceHandle /*inInstance*/, long /*inOffset*/)
+{
+ throw std::runtime_error("unimplemented");
+}
+
+void CSimpleAnimationCore::SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited)
+{
+ if (m_Objects.find(inAnimation) == m_Objects.end()) {
+ Q_ASSERT(false);
+ return;
+ }
+ SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ if (theItem->m_ArtistEdited != inEdited)
+ theItem->m_ArtistEdited = inEdited;
+}
+
+bool CSimpleAnimationCore::IsArtistEdited(CUICDMAnimationHandle inAnimation) const
+{
+ if (m_Objects.find(inAnimation) == m_Objects.end()) {
+ return false;
+ }
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ return theItem->m_ArtistEdited;
+}
+
+inline bool KeyframeTimeLessThan(int inKeyframe, float inSeconds, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects);
+ return KeyframeTime(theKeyframe->m_Keyframe) < inSeconds;
+}
+
+inline bool KeyframeValueTimeLessThan(const TKeyframe &inLeft, const TKeyframe &inRight)
+{
+ return KeyframeTime(inLeft) < KeyframeTime(inRight);
+}
+
+TKeyframe IntToKeyframe(int inKeyframe, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects);
+ return theKeyframe->m_Keyframe;
+}
+
+inline float KeyframeValue(int inKeyframe, const THandleObjectMap &inObjects)
+{
+ const SKeyframe *theKeyframe = CSimpleAnimationCore::GetKeyframeNF(inKeyframe, inObjects);
+ return KeyframeValueValue(theKeyframe->m_Keyframe);
+}
+
+inline float EvaluateLinear(float inS1, float inS2, float inV1, float inV2, float inSeconds)
+{
+ float amount = (inSeconds - inS1) / (inS2 - inS1);
+ return inV1 + amount * (inV2 - inV1);
+}
+
+inline float EvaluateLinearKeyframe(SLinearKeyframe &inK1, SLinearKeyframe &inK2, float inSeconds)
+{
+ return EvaluateLinear(inK1.m_KeyframeSeconds, inK2.m_KeyframeSeconds, inK1.m_KeyframeValue,
+ inK2.m_KeyframeValue, inSeconds);
+}
+
+inline float DoBezierEvaluation(float inSeconds, const SBezierKeyframe &inK1,
+ const SBezierKeyframe &inK2)
+{
+ return Q3DStudio::EvaluateBezierKeyframe(
+ inSeconds, inK1.m_KeyframeSeconds, inK1.m_KeyframeValue, inK1.m_OutTangentTime,
+ inK1.m_OutTangentValue, inK2.m_InTangentTime, inK2.m_InTangentValue, inK2.m_KeyframeSeconds,
+ inK2.m_KeyframeValue);
+}
+
+// Animation Evaluation.
+float CSimpleAnimationCore::EvaluateAnimation(CUICDMAnimationHandle inAnimation,
+ float inSeconds) const
+{
+ const SAnimationTrack *theItem = GetAnimationNF(inAnimation, m_Objects);
+ if (theItem->m_Keyframes.empty())
+ return 0.0f;
+ CheckKeyframesSorted(theItem, m_Objects);
+ // Default to linear for now.
+ SLinearKeyframe theKeyframe = { 0 };
+ theKeyframe.m_KeyframeSeconds = inSeconds;
+ TKeyframe theSearchKey(theKeyframe);
+ function<TKeyframe(int)> theIntToKeyframe(
+ std::bind(IntToKeyframe, std::placeholders::_1, std::ref(m_Objects)));
+ typedef transform_iterator<function<TKeyframe(int)>, TKeyframeHandleList::const_iterator>
+ TTransformIterator;
+ TTransformIterator theBound =
+ lower_bound(make_transform_iterator(theItem->m_Keyframes.begin(), theIntToKeyframe),
+ make_transform_iterator(theItem->m_Keyframes.end(), theIntToKeyframe),
+ theSearchKey, KeyframeValueTimeLessThan);
+ if (theBound.base() == theItem->m_Keyframes.end())
+ return KeyframeValue(theItem->m_Keyframes.back(), m_Objects);
+ if (theBound.base() == theItem->m_Keyframes.begin())
+ return KeyframeValue(*theItem->m_Keyframes.begin(), m_Objects);
+ TTransformIterator theStartIter = theBound;
+ --theStartIter;
+
+ // Both iterators must be valid at this point...
+ TKeyframe theStart = *theStartIter;
+ TKeyframe theFinish = *theBound;
+ switch (theItem->m_AnimationType) {
+ default:
+ throw AnimationEvaluationError(L"");
+ case EAnimationTypeLinear: {
+ SLinearKeyframe k1 = get<SLinearKeyframe>(theStart);
+ SLinearKeyframe k2 = get<SLinearKeyframe>(theFinish);
+ return EvaluateLinearKeyframe(k1, k2, inSeconds);
+ }
+ case EAnimationTypeBezier: {
+ SBezierKeyframe k1 = get<SBezierKeyframe>(theStart);
+ SBezierKeyframe k2 = get<SBezierKeyframe>(theFinish);
+ return DoBezierEvaluation(inSeconds, k1, k2);
+ }
+ case EAnimationTypeEaseInOut: {
+ SEaseInEaseOutKeyframe k1 = get<SEaseInEaseOutKeyframe>(theStart);
+ SEaseInEaseOutKeyframe k2 = get<SEaseInEaseOutKeyframe>(theFinish);
+ return DoBezierEvaluation(
+ inSeconds, CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, k1, &k2.m_KeyframeValue),
+ CreateBezierKeyframeFromEaseInEaseOutKeyframe(&k1.m_KeyframeValue, k2, NULL));
+ }
+ }
+}
+
+bool CSimpleAnimationCore::KeyframeValid(CUICDMKeyframeHandle inKeyframe) const
+{
+ return HandleObjectValid<SKeyframe>(inKeyframe, m_Objects);
+}
+
+bool CSimpleAnimationCore::AnimationValid(CUICDMAnimationHandle inAnimation) const
+{
+ return HandleObjectValid<SAnimationTrack>(inAnimation, m_Objects);
+}
+
+CUICDMAnimationHandle CSimpleAnimationCore::CreateAnimationWithHandle(
+ int inHandle, CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic)
+{
+ if (HandleValid(inHandle))
+ throw HandleExists(L"");
+ m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SAnimationTrack(
+ inHandle, inSlide, inInstance, inProperty, inIndex,
+ inAnimationType, inFirstKeyframeDynamic, true)));
+ return inHandle;
+}
+
+void CSimpleAnimationCore::AddAnimationToLookupCache(CUICDMAnimationHandle inAnimation) const
+{
+ THandleObjectMap::const_iterator theAnim = m_Objects.find(inAnimation);
+ if (theAnim != m_Objects.end())
+ AddAnimationToLookupCache(static_pointer_cast<SAnimationTrack>(theAnim->second));
+}
+void CSimpleAnimationCore::RemoveAnimationFromLookupCache(CUICDMAnimationHandle inAnimation) const
+{
+ THandleObjectMap::const_iterator theAnim = m_Objects.find(inAnimation);
+ if (theAnim != m_Objects.end())
+ RemoveAnimationFromLookupCache(static_pointer_cast<SAnimationTrack>(theAnim->second));
+}
+
+// Ensure there is only one of these in the multimap.
+void CSimpleAnimationCore::AddAnimationToLookupCache(
+ std::shared_ptr<SAnimationTrack> inAnimation) const
+{
+ CUICDMSlideHandle theSlide = inAnimation->m_Slide;
+ CUICDMInstanceHandle theInstance = inAnimation->m_Instance;
+ pair<TStateInstanceAnimationMap::iterator, TStateInstanceAnimationMap::iterator> theRange =
+ m_AnimationMatchesCache.equal_range(
+ make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()));
+ for (TStateInstanceAnimationMap::iterator theIter = theRange.first; theIter != theRange.second;
+ ++theIter) {
+ if (theIter->second == inAnimation)
+ return;
+ }
+ m_AnimationMatchesCache.insert(
+ make_pair(make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()), inAnimation));
+}
+
+// Remove this from the multimap
+void CSimpleAnimationCore::RemoveAnimationFromLookupCache(
+ std::shared_ptr<SAnimationTrack> inAnimation) const
+{
+ TStateInstanceAnimationMap &theMap(m_AnimationMatchesCache);
+ CUICDMSlideHandle theSlide = inAnimation->m_Slide;
+ CUICDMInstanceHandle theInstance = inAnimation->m_Instance;
+ pair<TStateInstanceAnimationMap::iterator, TStateInstanceAnimationMap::iterator> theRange =
+ theMap.equal_range(make_pair(theSlide.GetHandleValue(), theInstance.GetHandleValue()));
+ for (TStateInstanceAnimationMap::iterator theIter = theRange.first; theIter != theRange.second;
+ ++theIter) {
+ if (theIter->second == inAnimation) {
+ theMap.erase(theIter);
+ break;
+ }
+ }
+}
+
+//================================================================================
+// UICDMAnimation.h function implementations
+//================================================================================
+
+void CopyKeyframe(CUICDMAnimationHandle inAnimation, CUICDMKeyframeHandle inKeyframe,
+ const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore)
+{
+ TKeyframe theData = inSourceAnimationCore.GetKeyframeData(inKeyframe);
+ inDestAnimationCore.InsertKeyframe(inAnimation, theData);
+}
+
+void CopyKeyframes(const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore,
+ CUICDMAnimationHandle inDestAnimation, const TKeyframeHandleList &inKeyframes)
+{
+ do_all(inKeyframes,
+ std::bind(CopyKeyframe, inDestAnimation, std::placeholders::_1,
+ std::cref(inSourceAnimationCore), std::ref(inDestAnimationCore)));
+}
+
+CUICDMAnimationHandle CopyAnimation(TAnimationCorePtr inAnimationCore,
+ CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inNewSlide,
+ CUICDMInstanceHandle inNewInstance,
+ CUICDMPropertyHandle inNewProperty, size_t inNewIndex)
+{
+ TKeyframeHandleList theKeyframes;
+ inAnimationCore->GetKeyframes(inAnimation, theKeyframes);
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ CUICDMAnimationHandle theAnimation =
+ inAnimationCore->CreateAnimation(inNewSlide, inNewInstance, inNewProperty, inNewIndex,
+ theInfo.m_AnimationType, theInfo.m_DynamicFirstKeyframe);
+ CopyKeyframes(*inAnimationCore, *inAnimationCore, theAnimation, theKeyframes);
+ return theAnimation;
+}
+
+SBezierKeyframe GetBezierKeyframeData(CUICDMKeyframeHandle inKeyframe,
+ const IAnimationCore &inAnimationCore)
+{
+ return get<SBezierKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe));
+}
+
+SEaseInEaseOutKeyframe GetEaseInEaseOutKeyframeData(CUICDMKeyframeHandle inKeyframe,
+ const IAnimationCore &inAnimationCore)
+{
+ return get<SEaseInEaseOutKeyframe>(inAnimationCore.GetKeyframeData(inKeyframe));
+}
+
+TKeyframeHandleList::iterator SafeIncrementIterator(TKeyframeHandleList::iterator inIter,
+ const TKeyframeHandleList::iterator &inEnd)
+{
+ return inIter == inEnd ? inEnd : inIter + 1;
+}
+
+void GetKeyframesAsBezier(CUICDMAnimationHandle inAnimation, const IAnimationCore &inAnimationCore,
+ TBezierKeyframeList &outKeyframes)
+{
+ SAnimationInfo theInfo(inAnimationCore.GetAnimationInfo(inAnimation));
+ TKeyframeHandleList theKeyframes;
+ inAnimationCore.GetKeyframes(inAnimation, theKeyframes);
+ outKeyframes.resize(theKeyframes.size());
+ switch (theInfo.m_AnimationType) {
+ default:
+ throw invalid_argument("AnimationType");
+ case EAnimationTypeBezier:
+ transform(theKeyframes.begin(), theKeyframes.end(), outKeyframes.begin(),
+ std::bind(GetBezierKeyframeData, std::placeholders::_1,
+ std::cref(inAnimationCore)));
+ break;
+ case EAnimationTypeEaseInOut: {
+
+ TKeyframeHandleList::iterator theEndKeyframe = theKeyframes.end();
+
+ typedef std::function<SEaseInEaseOutKeyframe(CUICDMKeyframeHandle)> TConvertFunc;
+ TConvertFunc theDataConverter(
+ std::bind(GetEaseInEaseOutKeyframeData, std::placeholders::_1,
+ std::cref(inAnimationCore)));
+ typedef boost::transform_iterator<TConvertFunc, TKeyframeHandleList::iterator>
+ TTransformIterator;
+ TTransformIterator thePreviousKeyframe(
+ make_transform_iterator(theKeyframes.begin(), theDataConverter));
+ TTransformIterator theCurrentKeyframe(make_transform_iterator(
+ SafeIncrementIterator(thePreviousKeyframe.base(), theEndKeyframe), theDataConverter));
+ TTransformIterator theNextKeyframe(make_transform_iterator(
+ SafeIncrementIterator(theCurrentKeyframe.base(), theEndKeyframe), theDataConverter));
+
+ TBezierKeyframeList::iterator theResult(outKeyframes.begin());
+
+ if (thePreviousKeyframe.base() != theEndKeyframe) {
+ float *theNextValuePtr = NULL;
+ float theNextValue;
+ if (theCurrentKeyframe.base() != theEndKeyframe) {
+ theNextValue = theCurrentKeyframe->m_KeyframeValue;
+ theNextValuePtr = &theNextValue;
+ }
+ *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, *thePreviousKeyframe,
+ theNextValuePtr);
+ theResult = theResult + 1;
+ }
+ for (; theCurrentKeyframe.base() != theEndKeyframe;
+ ++thePreviousKeyframe,
+ theCurrentKeyframe = make_transform_iterator(
+ SafeIncrementIterator(theCurrentKeyframe.base(), theEndKeyframe),
+ theDataConverter),
+ theNextKeyframe = make_transform_iterator(
+ SafeIncrementIterator(theNextKeyframe.base(), theEndKeyframe), theDataConverter),
+ ++theResult) {
+ float theLastValue(thePreviousKeyframe->m_KeyframeValue);
+ float *theNextValuePtr = NULL;
+ float theNextValue;
+ if (theNextKeyframe.base() != theEndKeyframe) {
+ theNextValue = theNextKeyframe->m_KeyframeValue;
+ theNextValuePtr = &theNextValue;
+ }
+ *theResult = CreateBezierKeyframeFromEaseInEaseOutKeyframe(
+ &theLastValue, *theCurrentKeyframe, theNextValuePtr);
+ }
+ } break;
+ }
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.h b/src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.h
new file mode 100644
index 00000000..78b4934d
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleAnimationCore.h
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef ANIMATIONCOREH
+#define ANIMATIONCOREH
+#include "UICDMAnimation.h"
+#include "HandleSystemBase.h"
+#include <boost/unordered_map.hpp>
+
+namespace UICDM {
+struct SAnimationTrack : public CHandleObject
+{
+ int m_Slide;
+ int m_Instance;
+ int m_Property;
+ EAnimationType m_AnimationType;
+ size_t m_Index;
+ TKeyframeHandleList m_Keyframes;
+ bool m_KeyframesDirty;
+ bool m_FirstKeyframeDynamic;
+ bool m_ArtistEdited;
+
+ SAnimationTrack()
+ : m_Slide(0)
+ , m_Instance(0)
+ , m_Property(0)
+ , m_AnimationType(EAnimationTypeLinear)
+ , m_Index(0)
+ , m_KeyframesDirty(false)
+ , m_FirstKeyframeDynamic(false)
+ , m_ArtistEdited(true)
+ {
+ }
+
+ SAnimationTrack(int inHandle, CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic, bool inArtistEdited)
+ : CHandleObject(inHandle)
+ , m_Slide(inSlide)
+ , m_Instance(inInstance)
+ , m_Property(inProperty)
+ , m_AnimationType(inAnimationType)
+ , m_Index(inIndex)
+ , m_KeyframesDirty(false)
+ , m_FirstKeyframeDynamic(inFirstKeyframeDynamic)
+ , m_ArtistEdited(inArtistEdited)
+ {
+ }
+
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSAnimationTrack;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+struct SKeyframe : public CHandleObject
+{
+ TKeyframe m_Keyframe;
+ int m_Animation;
+
+ SKeyframe(int inHandle, int inAnimation, const TKeyframe &inKeyframe)
+ : CHandleObject(inHandle)
+ , m_Keyframe(inKeyframe)
+ , m_Animation(inAnimation)
+ {
+ }
+
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSKeyframe;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+class CAnimationCoreProducer;
+
+class CSimpleAnimationCore : public CHandleBase, public IAnimationCore
+{
+ TStringTablePtr m_StringTable;
+ typedef boost::unordered_multimap<std::pair<int, int>, std::shared_ptr<SAnimationTrack>>
+ TStateInstanceAnimationMap;
+ // state,instance pair map to animation handle to speed up querying if a particular
+ // property is animated.
+ mutable TStateInstanceAnimationMap m_AnimationMatchesCache;
+
+public: // Use
+ friend class CAnimationCoreProducer;
+ // We don't use the string table ptr we are constructed with
+ // but the testing system needs an unified interface to creating
+ // objects
+ CSimpleAnimationCore() {}
+ CSimpleAnimationCore(TStringTablePtr strTable)
+ : m_StringTable(strTable)
+ {
+ }
+ TStringTablePtr GetStringTablePtr() const { return m_StringTable; }
+
+ CUICDMAnimationHandle CreateAnimation(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic) override;
+ void DeleteAnimation(CUICDMAnimationHandle inAnimation) override;
+ CUICDMAnimationHandle GetAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex) const override;
+ SAnimationInfo GetAnimationInfo(CUICDMAnimationHandle inAnimation) const override;
+ void GetAnimations(TAnimationHandleList &outAnimations) const override;
+ void GetAnimations(TAnimationInfoList &outAnimations, CUICDMSlideHandle inMaster,
+ CUICDMSlideHandle inSlide) const override;
+ void GetSpecificInstanceAnimations(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations) override;
+
+ void SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation, bool inValue) override;
+
+ // keyframe manipulation
+ CUICDMKeyframeHandle InsertKeyframe(CUICDMAnimationHandle inAnimation,
+ const TKeyframe &inKeyframe) override;
+ void EraseKeyframe(CUICDMKeyframeHandle inKeyframe) override;
+ void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) override;
+ CUICDMAnimationHandle GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const override;
+ TKeyframe GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const override;
+ void SetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) override;
+ // Set the keyframe data, but don't set the artist edited flag. Used for undo/redo operations
+ // where the artist edited flag has handeled by a different transaction
+ void DoSetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData);
+ void GetKeyframes(CUICDMAnimationHandle inAnimation, TKeyframeHandleList &outKeyframes) const override;
+ size_t GetKeyframeCount(CUICDMAnimationHandle inAnimation) const override;
+ bool IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const override;
+ // Only implemented in the producer for now.
+ void OffsetAnimations(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ long inOffset) override;
+
+ void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) override;
+ bool IsArtistEdited(CUICDMAnimationHandle inAnimation) const override;
+
+ // Animation Evaluation.
+ float EvaluateAnimation(CUICDMAnimationHandle inAnimation, float inSeconds) const override;
+
+ bool KeyframeValid(CUICDMKeyframeHandle inKeyframe) const override;
+ bool AnimationValid(CUICDMAnimationHandle inAnimation) const override;
+
+ // Only implemented at the producer level, not at the simple core level.
+ void CopyAnimations(CUICDMSlideHandle /*inSourceSlide*/,
+ CUICDMInstanceHandle /*inSourceInstance*/,
+ CUICDMSlideHandle /*inDestSlide*/, CUICDMInstanceHandle /*inDestInstance*/) override
+ {
+ throw AnimationNotFound(L"");
+ }
+
+ // Lookup cache management so we can find particular animations quickly.
+ void ClearAnimationMatchesLookupCache() const { m_AnimationMatchesCache.clear(); }
+ void AddAnimationToLookupCache(CUICDMAnimationHandle inAnimation) const;
+ void RemoveAnimationFromLookupCache(CUICDMAnimationHandle inAnimation) const;
+ void AddAnimationToLookupCache(std::shared_ptr<SAnimationTrack> inAnimation) const;
+ void RemoveAnimationFromLookupCache(std::shared_ptr<SAnimationTrack> inAnimation) const;
+
+ void EnsureAnimationCache() const;
+
+ CUICDMAnimationHandle CreateAnimationWithHandle(int inHandle, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic);
+
+ static SAnimationTrack *GetAnimationNF(int inHandle, THandleObjectMap &inObjects)
+ {
+ return const_cast<SAnimationTrack *>(
+ GetAnimationNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const SAnimationTrack *GetAnimationNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ const SAnimationTrack *theAnimation = GetHandleObject<SAnimationTrack>(inHandle, inObjects);
+ if (theAnimation)
+ return theAnimation;
+ throw AnimationNotFound(L"");
+ }
+
+ static SKeyframe *GetKeyframeNF(int inHandle, THandleObjectMap &inObjects)
+ {
+ return const_cast<SKeyframe *>(
+ GetKeyframeNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const SKeyframe *GetKeyframeNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ const SKeyframe *theItem = GetHandleObject<SKeyframe>(inHandle, inObjects);
+ if (theItem)
+ return theItem;
+ throw AnimationKeyframeNotFound(L"");
+ }
+};
+
+typedef std::shared_ptr<CSimpleAnimationCore> TSimpleAnimationCorePtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleDataCore.cpp b/src/Authoring/UICDM/Systems/Cores/SimpleDataCore.cpp
new file mode 100644
index 00000000..67cc724a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleDataCore.cpp
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "SimpleDataCore.h"
+
+namespace UICDM {
+TUICDMDebugLogFunction g_UICDMDebugLogger = NULL;
+// Instances
+CUICDMInstanceHandle CSimpleDataCore::CreateInstance(CUICDMInstanceHandle hdl)
+{
+ int nextId = hdl;
+ if (hdl.Valid() == false)
+ nextId = GetNextId();
+
+ return CreateInstanceWithHandle(nextId);
+}
+
+inline void RemoveParentFromClass(int inParent, int inChild, THandleObjectMap &inMap)
+{
+ TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inChild, inMap);
+ theInstance->m_Parents.erase(theInstance->m_Parents.find(inParent));
+ // Cascade the delete operation
+}
+
+void CSimpleDataCore::DeleteInstance(CUICDMInstanceHandle inHandle)
+{
+ // Ensure it exists in the first place.
+ CSimpleDataCore::GetInstanceNF(inHandle, m_Objects); // Check for instance existance
+ CSimpleDataCore::EraseHandle(inHandle, m_Objects);
+ TIntList properties;
+ TIntList instances;
+ do_all(m_Objects, std::bind(FindRelatedItemsForDelete, inHandle.GetHandleValue(),
+ std::ref(properties), std::ref(instances), std::placeholders::_1));
+ do_all(instances, std::bind(RemoveParentFromClass, inHandle.GetHandleValue(),
+ std::placeholders::_1, std::ref(m_Objects)));
+ do_all(properties, std::bind(EraseHandle, std::placeholders::_1, std::ref(m_Objects)));
+}
+
+void CSimpleDataCore::GetInstances(TInstanceHandleList &outInstances) const
+{
+ // reserve the vector to m_Objects.size() to prevent vector reallocation
+ // m_Objects.size() is the upper bound of the no of instances
+ // the exact no of instances = m_Objects.size() - the no of properties as added by
+ // CClientDataModelBridge::InitializeDataCore (as of now, we have 31 properties)
+ outInstances.reserve(m_Objects.size());
+ do_all(m_Objects, std::bind(MaybeAddObject<CDataModelInstance, CUICDMInstanceHandle>,
+ std::placeholders::_1, std::ref(outInstances)));
+}
+
+// Get instances that are derived from a specific parent
+void CSimpleDataCore::GetInstancesDerivedFrom(TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParentHandle) const
+{
+ do_all(m_Objects, std::bind(&CSimpleDataCore::AddInstanceIfDerivedFrom, this,
+ std::placeholders::_1,
+ std::ref(outInstances), inParentHandle));
+}
+
+// add instance that is derived from a specific parent
+void CSimpleDataCore::AddInstanceIfDerivedFrom(const std::pair<int, THandleObjectPtr> &inItem,
+ TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParentHandle) const
+{
+ if (inItem.second->GetType() == CHandleObject::EHandleObjectTypeCDataModelInstance) {
+ TDataModelInstancePtr theInstance = static_pointer_cast<CDataModelInstance>(inItem.second);
+ if (IsInstanceOrDerivedFromHelper(theInstance, inParentHandle))
+ outInstances.push_back(inItem.first);
+ }
+}
+
+// Derivation
+void CSimpleDataCore::DeriveInstance(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent)
+{
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger("CSimpleDataCore::DeriveInstance Enter");
+ TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inInstance, m_Objects);
+ if (theInstance->m_Parents.find(inParent) == theInstance->m_Parents.end()) {
+ std::shared_ptr<CDataModelInstance> theParent(GetInstanceNF(inParent, m_Objects));
+ theInstance->m_Parents.insert(make_pair(inParent, theParent));
+ }
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger("CSimpleDataCore::DeriveInstance Leave");
+}
+
+void CSimpleDataCore::GetInstanceParents(CUICDMInstanceHandle inHandle,
+ TInstanceHandleList &outParents) const
+{
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inHandle, m_Objects);
+ for (CDataModelInstance::TInstancePairList::const_iterator theParent =
+ theInstance->m_Parents.begin();
+ theParent != theInstance->m_Parents.end(); ++theParent)
+ outParents.push_back(theParent->first);
+}
+
+inline bool ComparePropertyNames(const TCharStr &inName, int inPropHandle,
+ const THandleObjectMap &inObjects)
+{
+ if (CSimpleDataCore::GetPropertyDefinitionNF(inPropHandle, inObjects)->m_Definition.m_Name
+ == inName)
+ return true;
+ return false;
+}
+
+inline const wchar_t *SafeStrPtr(const wchar_t *inData)
+{
+ return inData == NULL ? L"" : inData;
+}
+
+// Properties
+CUICDMPropertyHandle CSimpleDataCore::AddProperty(CUICDMInstanceHandle inInstance, TCharPtr inName,
+ DataModelDataType::Value inPropType)
+{
+ UICDM_LOG_FUNCTION("CSimpleDataCore::AddProperty");
+ UICDM_DEBUG_LOG(m_StringTable->GetNarrowStr(inName));
+ TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ TCharStr theName(inName);
+ if (find_if<TIntList::iterator>(
+ theInstance->m_Properties,
+ std::bind(ComparePropertyNames, std::ref(theName),
+ std::placeholders::_1, std::ref(m_Objects)))
+ != theInstance->m_Properties.end()) {
+ UICDM_DEBUG_LOG("Property Exists!!");
+ throw PropertyExists(L"");
+ }
+
+ int nextId = GetNextId();
+ return AddPropertyWithHandle(nextId, inInstance, inName, inPropType);
+}
+
+void CSimpleDataCore::GetInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const
+{
+ transformv_all(GetInstanceNF(inInstance, m_Objects)->m_Properties, outProperties);
+}
+
+const SUICDMPropertyDefinition &CSimpleDataCore::GetProperty(CUICDMPropertyHandle inProperty) const
+{
+ const CDataModelPropertyDefinitionObject *theProp =
+ GetPropertyDefinitionNF(inProperty, m_Objects);
+ return theProp->m_Definition;
+}
+
+void CSimpleDataCore::RemoveProperty(CUICDMPropertyHandle inProperty)
+{
+ CDataModelPropertyDefinitionObject *theProp =
+ CSimpleDataCore::GetPropertyDefinitionNF(inProperty, m_Objects);
+ TDataModelInstancePtr theInstance =
+ CSimpleDataCore::GetInstanceNF(theProp->m_Definition.m_Instance, m_Objects);
+ erase_if(theInstance->m_Properties,
+ std::bind(equal_to<int>(), inProperty.GetHandleValue(), std::placeholders::_1));
+ CSimpleDataCore::EraseHandle(inProperty, m_Objects);
+}
+
+inline bool PropertyMatches(int inProperty, CUICDMPropertyHandle inTarget)
+{
+ return inProperty == inTarget.GetHandleValue();
+}
+
+inline bool GetInstanceValue(CUICDMInstanceHandle inInstanceHandle,
+ CUICDMPropertyHandle inPropertyHandle, CSimpleDataCore &inDataCore,
+ SValue &outValue)
+{
+ const TDataModelInstancePtr theInstance =
+ CSimpleDataCore::GetInstanceNF(inInstanceHandle, inDataCore.m_Objects);
+
+ TPropertyPairHash::const_iterator theInstanceProp =
+ theInstance->m_PropertyValues.find(inPropertyHandle.GetHandleValue());
+ if (theInstanceProp != theInstance->m_PropertyValues.end()) {
+ outValue = theInstanceProp->second.second.GetValue();
+ return true;
+ }
+ return false;
+}
+
+inline void CopyInstanceProperty(CUICDMPropertyHandle inSrcPropertyHandle,
+ CUICDMInstanceHandle inSrcInstanceHandle,
+ CUICDMInstanceHandle inInstanceHandle, CSimpleDataCore &inDataCore)
+{
+ // create the property definition that matches the source
+ const SUICDMPropertyDefinition &theProperty = inDataCore.GetProperty(inSrcPropertyHandle);
+ CUICDMPropertyHandle theNewProperty =
+ inDataCore.AddProperty(inInstanceHandle, theProperty.m_Name.wide_str(), theProperty.m_Type);
+ // copy the value if one exists on the src.
+ SValue theValue;
+ if (GetInstanceValue(inSrcInstanceHandle, inSrcPropertyHandle, inDataCore, theValue))
+ inDataCore.SetInstancePropertyValue(inInstanceHandle, theNewProperty, theValue);
+}
+
+// logic : if destination property is one gained through derivation in inSrcInstanceHandle, copy the
+// value over.
+inline void CopyAggregatedPropertyValues(CUICDMPropertyHandle inDestPropertyHandle,
+ CUICDMInstanceHandle inSrcInstanceHandle,
+ CUICDMInstanceHandle inInstanceHandle,
+ const TPropertyHandleList &inSrcNonAggregateList,
+ CSimpleDataCore &inDataCore)
+{
+ if (find_if(inSrcNonAggregateList.begin(), inSrcNonAggregateList.end(),
+ bind(PropertyMatches, inDestPropertyHandle, std::placeholders::_1))
+ == inSrcNonAggregateList.end()
+ && inDataCore.HasAggregateInstanceProperty(inSrcInstanceHandle, inDestPropertyHandle)) {
+ SValue theValue;
+ if (GetInstanceValue(inSrcInstanceHandle, inDestPropertyHandle, inDataCore, theValue))
+ inDataCore.SetInstancePropertyValue(inInstanceHandle, inDestPropertyHandle, theValue);
+ }
+}
+
+void CSimpleDataCore::CopyInstanceProperties(CUICDMInstanceHandle inSrcInstance,
+ CUICDMInstanceHandle inDestInstance)
+{
+ TPropertyHandleList theList;
+ GetInstanceProperties(inSrcInstance, theList);
+ do_all(theList, bind(CopyInstanceProperty, std::placeholders::_1,
+ inSrcInstance, inDestInstance, ref(*this)));
+
+ TPropertyHandleList theDestList;
+ GetAggregateInstanceProperties(inDestInstance, theDestList);
+ do_all(theDestList, std::bind(CopyAggregatedPropertyValues, std::placeholders::_1,
+ inSrcInstance, inDestInstance,
+ theList, std::ref(*this)));
+}
+
+void CSimpleDataCore::RemoveCachedValues(CUICDMInstanceHandle inInstance)
+{
+ const TDataModelInstancePtr theInstance = CSimpleDataCore::GetInstanceNF(inInstance, m_Objects);
+ theInstance->RemoveCachedValues();
+}
+
+void GetAggregateProperties(const TDataModelInstancePtr inInstance, TIntList &inVisited,
+ TPropertyHandleList &outProperties)
+{
+ if (find(inVisited.begin(), inVisited.end(), inInstance->m_Handle) == inVisited.end()) {
+ inVisited.push_back(inInstance->m_Handle);
+ size_t theSize = outProperties.size();
+ outProperties.resize(theSize + inInstance->m_Properties.size());
+ transform(inInstance->m_Properties.begin(), inInstance->m_Properties.end(),
+ outProperties.begin() + theSize, identity<int>);
+ for (CDataModelInstance::TInstancePairList::const_iterator theParent =
+ inInstance->m_Parents.begin();
+ theParent != inInstance->m_Parents.end(); ++theParent)
+ GetAggregateProperties(theParent->second, inVisited, outProperties);
+ }
+}
+
+template <typename TPredicate>
+inline std::tuple<bool, CUICDMInstanceHandle, CUICDMPropertyHandle>
+RecurseFindProperty(const TDataModelInstancePtr inInstance, TPredicate inPredicate)
+{
+ TIntList::const_iterator theFind = eastl::find_if(inInstance->m_Properties.begin(),
+ inInstance->m_Properties.end(), inPredicate);
+ if (theFind != inInstance->m_Properties.end())
+ return make_tuple(true, inInstance->m_Handle, *theFind);
+
+ for (CDataModelInstance::TInstancePairList::const_iterator theParent =
+ inInstance->m_Parents.begin();
+ theParent != inInstance->m_Parents.end(); ++theParent) {
+ std::tuple<bool, CUICDMInstanceHandle, CUICDMPropertyHandle> theValue =
+ RecurseFindProperty(theParent->second, inPredicate);
+ if (get<0>(theValue))
+ return theValue;
+ }
+ return make_tuple(false, 0, 0);
+}
+
+inline bool PropertyNameMatches(int inProperty, const THandleObjectMap &inObjects,
+ const TCharStr &inStr)
+{
+ const CDataModelPropertyDefinitionObject *theProp =
+ CSimpleDataCore::GetPropertyDefinitionNF(inProperty, inObjects);
+ return (theProp->m_Definition.m_Name == inStr);
+}
+
+CUICDMPropertyHandle
+CSimpleDataCore::GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const
+{
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ return get<2>(
+ RecurseFindProperty(theInstance, std::bind(PropertyNameMatches,
+ std::placeholders::_1, std::ref(m_Objects),
+ std::ref(inStr))));
+}
+
+// A simplified RecurseFindProperty function
+bool RecurseFindPropertyMatches(const TDataModelInstancePtr inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ TIntList::const_iterator theFind =
+ find(inInstance->m_Properties.begin(), inInstance->m_Properties.end(),
+ inProperty.GetHandleValue());
+ if (theFind != inInstance->m_Properties.end())
+ return true;
+
+ for (CDataModelInstance::TInstancePairList::const_iterator theParent =
+ inInstance->m_Parents.begin();
+ theParent != inInstance->m_Parents.end(); ++theParent) {
+ if (RecurseFindPropertyMatches(theParent->second, inProperty))
+ return true;
+ }
+ return false;
+}
+
+bool CSimpleDataCore::HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ if (theInstance->m_PropertyValues.find(inProperty.GetHandleValue())
+ != theInstance->m_PropertyValues.end())
+ return true;
+
+ return RecurseFindPropertyMatches(theInstance, inProperty);
+}
+
+void CSimpleDataCore::GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const
+{
+ TIntList inVisited;
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ GetAggregateProperties(theInstance, inVisited, outProperties);
+}
+
+void CSimpleDataCore::CheckValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ const SValue &inValue) const
+{
+ CheckPropertyExistence(GetInstanceNF(inInstance, m_Objects), inProperty, m_Objects);
+ const CDataModelPropertyDefinitionObject *theDefinition =
+ CSimpleDataCore::GetPropertyDefinitionNF(inProperty, m_Objects);
+ CheckValueType(theDefinition->m_Definition.m_Type, inValue);
+}
+
+bool CSimpleDataCore::GetInstancePropertyValueHelper(const TDataModelInstancePtr inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ TPropertyPairHash::const_iterator theInstanceProp =
+ inInstance->m_PropertyValues.find(inProperty);
+ if (theInstanceProp != inInstance->m_PropertyValues.end()) {
+ outValue = theInstanceProp->second.second.GetValue();
+ return true;
+ } else {
+ // Is the property valid?
+ const CDataModelPropertyDefinitionObject *theProp =
+ GetPropertyDefinitionNF(inProperty, m_Objects);
+ int thePropInstance = theProp->m_Definition.m_Instance;
+ if (thePropInstance != inInstance->m_Handle) {
+ for (CDataModelInstance::TInstancePairList::const_iterator theParent =
+ inInstance->m_Parents.begin();
+ theParent != inInstance->m_Parents.end(); ++theParent) {
+ if (IsInstanceOrDerivedFromHelper(theParent->second, thePropInstance)
+ && GetInstancePropertyValueHelper(theParent->second, inProperty, outValue)) {
+ // Quietly propagate to this instance so next time we won't go through this
+ // large property lookup chain.
+ inInstance->m_PropertyValues.insert(std::make_pair(
+ inProperty,
+ TPropertyValuePair(
+ PropertyValueFlags(PropertyValueFlags::SetViaAutoPropagate),
+ SInternValue::ISwearThisHasAlreadyBeenInternalized(outValue))));
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool CSimpleDataCore::GetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ if (IsInstance(inHandle) == false || IsProperty(inProperty) == false) {
+ Q_ASSERT(0);
+ return false;
+ }
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inHandle, m_Objects);
+ return GetInstancePropertyValueHelper(theInstance, inProperty, outValue);
+}
+
+void CSimpleDataCore::SetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ if (IsInstance(inHandle) == false || IsProperty(inProperty) == false) {
+ Q_ASSERT(0);
+ return;
+ }
+ CheckValue(inHandle, inProperty, inValue);
+ UncheckedSetSpecificInstancePropertyValue(inHandle, inProperty, inValue, PropertyValueFlags());
+}
+
+void CSimpleDataCore::GetSpecificInstancePropertyValues(CUICDMInstanceHandle inHandle,
+ TPropertyHandleValuePairList &outValues)
+{
+ if (IsInstance(inHandle) == false)
+ return;
+
+ TDataModelInstancePtr theInstance = GetInstanceNF(inHandle, m_Objects);
+ for (TPropertyPairHash::const_iterator theIter = theInstance->m_PropertyValues.begin(),
+ theEnd = theInstance->m_PropertyValues.end();
+ theIter != theEnd; ++theIter) {
+ const pair<int, TPropertyValuePair> &thePair(*theIter);
+ if (thePair.second.first.IsSetViaAutoPropagation() == false) {
+ CUICDMPropertyHandle thePropertyHandle(thePair.first);
+ SValue theValue(thePair.second.second.GetValue());
+ outValues.push_back(make_pair(thePair.first, theValue));
+ }
+ }
+}
+
+bool CSimpleDataCore::IsInstance(int inHandle) const
+{
+ return HandleObjectValid<CDataModelInstance>(inHandle, m_Objects);
+}
+bool CSimpleDataCore::IsProperty(int inHandle) const
+{
+ return HandleObjectValid<CDataModelPropertyDefinitionObject>(inHandle, m_Objects);
+}
+
+CUICDMInstanceHandle CSimpleDataCore::CreateInstanceWithHandle(int inHandle)
+{
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger("CSimpleDataCore::CreateInstance Enter");
+ if (HandleValid(inHandle)) {
+ if (g_UICDMDebugLogger) {
+ g_UICDMDebugLogger("CSimpleDataCore::CreateInstance Handle Exists!!");
+ char buf[32];
+ sprintf(buf, "%d", inHandle);
+ g_UICDMDebugLogger(buf);
+ }
+ throw HandleExists(L"");
+ }
+
+ THandleObjectPtr theHandleObjectPtr(new CDataModelInstance(inHandle));
+ const pair<int, THandleObjectPtr> thePair(std::make_pair(inHandle, theHandleObjectPtr));
+ m_Objects.insert(thePair);
+
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger("CSimpleDataCore::CreateInstance Leave");
+
+ return inHandle;
+}
+
+CUICDMPropertyHandle CSimpleDataCore::AddPropertyWithHandle(int inHandle,
+ CUICDMInstanceHandle inInstance,
+ TCharPtr inName,
+ DataModelDataType::Value inPropType)
+{
+ UICDM_DEBUG_LOG("CSimpleDataCore::AddPropertyWithHandle Enter");
+ UICDM_DEBUG_LOG(m_StringTable->GetNarrowStr(inName));
+ if (HandleValid(inHandle)) {
+ if (g_UICDMDebugLogger) {
+ g_UICDMDebugLogger("CSimpleDataCore::AddPropertyWithHandle Handle Exists!!");
+ char buf[32];
+ sprintf(buf, "%d", inHandle);
+ g_UICDMDebugLogger(buf);
+ }
+
+ throw HandleExists(L"");
+ }
+
+ TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+
+ SUICDMPropertyDefinition theDefinition(inInstance, SafeStrPtr(inName), inPropType);
+ THandleObjectPtr theHandleObjectPtr(
+ new CDataModelPropertyDefinitionObject(inHandle, theDefinition));
+ const pair<int, THandleObjectPtr> thePair(std::make_pair(inHandle, theHandleObjectPtr));
+ m_Objects.insert(thePair);
+ theInstance->m_Properties.push_back(inHandle);
+ UICDM_DEBUG_LOG("CSimpleDataCore::AddPropertyWithHandle Leave");
+ return inHandle;
+}
+
+bool CSimpleDataCore::GetSpecificInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ TPropertyPairHash::const_iterator theInstanceProp =
+ theInstance->m_PropertyValues.find(inProperty);
+ if (theInstanceProp != theInstance->m_PropertyValues.end()) {
+ outValue = theInstanceProp->second.second.GetValue();
+ return true;
+ }
+ return false;
+}
+
+void CSimpleDataCore::GetSpecificInstancePropertyValues(CUICDMInstanceHandle inInstance,
+ TPropertyPairHash &outValues) const
+{
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ outValues = theInstance->m_PropertyValues;
+}
+
+void CSimpleDataCore::UncheckedSetSpecificInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue,
+ PropertyValueFlags inIsUserSet)
+{
+ TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ TPropertyValuePair theValuePair(inIsUserSet, SInternValue(inValue, GetStringTable()));
+
+ std::pair<TPropertyPairHash::iterator, bool> theInsert = theInstance->m_PropertyValues.insert(
+ std::make_pair(inProperty.GetHandleValue(), theValuePair));
+ if (theInsert.second == false)
+ theInsert.first->second = theValuePair;
+}
+
+bool CSimpleDataCore::CheckParentPropertyExistenceWithFail(const TDataModelInstancePtr inInstance,
+ int inProperty,
+ const THandleObjectMap &inObjects)
+{
+ if (find(inInstance->m_Properties.begin(), inInstance->m_Properties.end(), inProperty)
+ != inInstance->m_Properties.end())
+ return true;
+ for (CDataModelInstance::TInstancePairList::const_iterator theParent =
+ inInstance->m_Parents.begin();
+ theParent != inInstance->m_Parents.end(); ++theParent) {
+ if (CheckParentPropertyExistenceWithFail(theParent->second, inProperty, inObjects))
+ return true;
+ }
+ return false;
+}
+
+// safety check to see if property exists
+void CSimpleDataCore::CheckPropertyExistence(const TDataModelInstancePtr inInstance, int inProperty,
+ const THandleObjectMap &inObjects)
+{
+ if (!CheckParentPropertyExistenceWithFail(inInstance, inProperty, inObjects))
+ throw PropertyNotFound(L"");
+}
+
+bool CSimpleDataCore::IsInstanceOrDerivedFromHelper(const TDataModelInstancePtr inInstance,
+ CUICDMInstanceHandle inParent) const
+{
+ if (inInstance->m_Handle == inParent) // Am I this object?
+ return true;
+ return inInstance->IsDerivedFrom(inParent);
+}
+
+bool CSimpleDataCore::IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const
+{
+ if (IsInstance(inInstance) == false || IsInstance(inParent) == false)
+ return false;
+ if (inInstance == inParent) // Am I this object?
+ return true;
+ const TDataModelInstancePtr theInstance = GetInstanceNF(inInstance, m_Objects);
+ return IsInstanceOrDerivedFromHelper(theInstance, inParent);
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleDataCore.h b/src/Authoring/UICDM/Systems/Cores/SimpleDataCore.h
new file mode 100644
index 00000000..4bedc131
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleDataCore.h
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef DATACOREH
+#define DATACOREH
+
+#include "UICDMDataTypes.h"
+#include "UICDMSignals.h"
+#include "HandleSystemBase.h"
+#include "UICDMPropertyDefinition.h"
+#include "UICDMDataCore.h"
+#include "UICDMStringTable.h"
+#include <unordered_set>
+#include "UICDMValue.h"
+
+namespace UICDM {
+
+struct PropertyValueFlags
+{
+ enum Enum {
+ // Property values that are set via event propagation should
+ // not be serialized to a file. The auto-propagation step
+ // is meant to make looking up property values quicker because
+ // the the derivation chain doesn't need to be followed to get
+ // the latest default value.
+ SetViaAutoPropagate = 1,
+ };
+
+ int m_Flags;
+
+ PropertyValueFlags()
+ : m_Flags(0)
+ {
+ }
+ explicit PropertyValueFlags(int inFlags)
+ : m_Flags(inFlags)
+ {
+ }
+
+ bool IsSetViaAutoPropagation() const { return (m_Flags & SetViaAutoPropagate) > 0; }
+};
+
+// Pair of property value flags and property value. The property value flags allow
+// us to track metadata that is
+typedef std::pair<PropertyValueFlags, SInternValue> TPropertyValuePair;
+typedef std::unordered_map<int, TPropertyValuePair> TPropertyPairHash;
+// Property pairs are referred to by property handle.
+typedef std::pair<int, TPropertyValuePair> TPropertyPair;
+typedef std::vector<TPropertyPair> TPropertyPairList;
+
+class CDataModelPropertyDefinitionObject : public CHandleObject
+{
+public:
+ SUICDMPropertyDefinition m_Definition;
+
+ CDataModelPropertyDefinitionObject(int inHandle, const SUICDMPropertyDefinition &inDefinition)
+ : CHandleObject(inHandle)
+ , m_Definition(inDefinition)
+ {
+ }
+ CDataModelPropertyDefinitionObject() {}
+
+ static const EHandleObjectType s_Type =
+ CHandleObject::EHandleObjectTypeCDataModelPropertyDefinitionObject;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+typedef std::unordered_map<int, SInternValue> TIntStringVariantList;
+
+class CDataModelInstance : public CHandleObject
+{
+public:
+ typedef std::pair<int, std::shared_ptr<CDataModelInstance>> TInstancePair;
+ typedef std::unordered_map<int, std::shared_ptr<CDataModelInstance>> TInstancePairList;
+ typedef std::unordered_map<int, bool> TInstanceParentMap;
+
+ TInstancePairList m_Parents;
+ mutable TInstanceParentMap m_CachedParents;
+ // Properties specific to this class
+ TIntList m_Properties;
+ TPropertyPairHash m_PropertyValues;
+
+ CDataModelInstance() {}
+ CDataModelInstance(int inHandle)
+ : CHandleObject(inHandle)
+ {
+ }
+
+ void ToPropertyPairList(TPropertyPairList &outList) const
+ {
+ for (TPropertyPairHash::const_iterator iter = m_PropertyValues.begin(),
+ end = m_PropertyValues.end();
+ iter != end; ++iter)
+ outList.push_back(*iter);
+ }
+
+ void FromPropertyPairList(const TPropertyPairList &inList)
+ {
+ m_PropertyValues.clear();
+ for (TPropertyPairList::const_iterator iter = inList.begin(), end = inList.end();
+ iter != end; ++iter)
+ m_PropertyValues.insert(*iter);
+ }
+
+ void ClearParentCache() const { m_CachedParents.clear(); }
+
+ bool IsDerivedFrom(CUICDMInstanceHandle inParent) const
+ {
+ std::pair<TInstanceParentMap::iterator, bool> theQueryResult =
+ m_CachedParents.insert(std::make_pair(inParent.GetHandleValue(), false));
+ // If the insert failed, returned what the hashtable already had in it
+ if (theQueryResult.second == false)
+ return theQueryResult.first->second;
+
+ // Else find a valid answer
+ if (m_Parents.find(inParent.GetHandleValue()) != m_Parents.end()) {
+ theQueryResult.first->second = true;
+ } else {
+ for (TInstancePairList::const_iterator iter = m_Parents.begin(), end = m_Parents.end();
+ iter != end; ++iter) {
+ if (iter->second->IsDerivedFrom(inParent)) {
+ theQueryResult.first->second = true;
+ break;
+ }
+ }
+ }
+
+ // Note that we inserted false to begin with. This means that
+ // we can return the insert result here safely as if it wasn't
+ // supposed to be false, we would have set it above.
+ return theQueryResult.first->second;
+ }
+
+ void RemoveCachedValues()
+ {
+ vector<int> theCachedProperties;
+
+ for (TPropertyPairHash::iterator theProperty = m_PropertyValues.begin(),
+ end = m_PropertyValues.end();
+ theProperty != end; ++theProperty) {
+ if (theProperty->second.first.IsSetViaAutoPropagation())
+ theCachedProperties.push_back(theProperty->first);
+ }
+
+ for (size_t idx = 0, end = theCachedProperties.size(); idx < end; ++idx)
+ m_PropertyValues.erase(theCachedProperties[idx]);
+ }
+
+ // CHandleObject
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeCDataModelInstance;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+typedef std::shared_ptr<CDataModelInstance> TDataModelInstancePtr;
+
+class CSimpleDataCore : public CHandleBase, public IDataCore
+{
+ mutable TStringTablePtr m_StringTable;
+
+public:
+ CSimpleDataCore(TStringTablePtr strTable)
+ : m_StringTable(strTable)
+ {
+ }
+ CSimpleDataCore(const CSimpleDataCore &inOther)
+ : CHandleBase(inOther)
+ , m_StringTable(inOther.m_StringTable)
+ {
+ }
+
+ CSimpleDataCore &operator=(const CSimpleDataCore &inOther)
+ {
+ CHandleBase::operator=(inOther);
+ return *this;
+ }
+
+ IStringTable &GetStringTable() const override { return *m_StringTable.get(); }
+ TStringTablePtr GetStringTablePtr() const override { return m_StringTable; }
+
+ // IHandleBase
+ bool HandleValid(int inHandle) const override
+ {
+ return m_Objects.find(inHandle) != m_Objects.end();
+ }
+
+ // IInstancePropertyCore
+ CUICDMPropertyHandle GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const override;
+ void GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const override;
+ void GetSpecificInstancePropertyValues(CUICDMInstanceHandle inHandle,
+ TPropertyHandleValuePairList &outValues) override;
+ bool HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ void CheckValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ const SValue &inValue) const override;
+ bool GetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ void SetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+
+ // IDataCore
+ //===============================================================
+ CUICDMInstanceHandle CreateInstance(CUICDMInstanceHandle hdl = CUICDMInstanceHandle()) override;
+ void DeleteInstance(CUICDMInstanceHandle inHandle) override;
+ void GetInstances(TInstanceHandleList &outInstances) const override;
+ void GetInstancesDerivedFrom(TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParentHandle) const override;
+
+ void DeriveInstance(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent) override;
+ void GetInstanceParents(CUICDMInstanceHandle inHandle,
+ TInstanceHandleList &outParents) const override;
+ // Returns true if inParent == inInstance || inInstance is derived from inParent somehow.
+ // Recursive.
+ bool IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const override;
+
+ CUICDMPropertyHandle AddProperty(CUICDMInstanceHandle inClass, TCharPtr inName,
+ DataModelDataType::Value inPropType) override;
+ const SUICDMPropertyDefinition &GetProperty(CUICDMPropertyHandle inProperty) const override;
+ void GetInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const override;
+ void RemoveProperty(CUICDMPropertyHandle inProperty) override;
+ void CopyInstanceProperties(CUICDMInstanceHandle inSrcInstance,
+ CUICDMInstanceHandle inDestInstance) override;
+ void RemoveCachedValues(CUICDMInstanceHandle inInstance) override;
+
+ bool IsInstance(int inHandle) const override;
+ bool IsProperty(int inHandle) const override;
+ //===============================================================
+
+ bool GetSpecificInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const;
+ void GetSpecificInstancePropertyValues(CUICDMInstanceHandle inInstance,
+ TPropertyPairHash &outValues) const;
+
+ static CDataModelPropertyDefinitionObject *GetPropertyDefinitionNF(int inHandle,
+ THandleObjectMap &inObjects)
+ {
+ return const_cast<CDataModelPropertyDefinitionObject *>(
+ GetPropertyDefinitionNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const CDataModelPropertyDefinitionObject *
+ GetPropertyDefinitionNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ const CDataModelPropertyDefinitionObject *theClass =
+ GetHandleObject<CDataModelPropertyDefinitionObject>(inHandle, inObjects);
+ if (theClass)
+ return theClass;
+ throw PropertyNotFound(L"");
+ }
+
+ static TDataModelInstancePtr GetInstance(int inHandle, const THandleObjectMap &inObjects)
+ {
+ THandleObjectMap::const_iterator theFind(inObjects.find(inHandle));
+ // dynamic cast isn't allowed in runtime code as the runtime doesn't enable rtti.
+ if (theFind != inObjects.end())
+ return std::static_pointer_cast<CDataModelInstance>(theFind->second);
+ return TDataModelInstancePtr();
+ }
+
+ static TDataModelInstancePtr GetInstanceNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ TDataModelInstancePtr retval = GetInstance(inHandle, inObjects);
+ if (retval)
+ return retval;
+ throw InstanceNotFound(L"");
+ }
+
+ static inline bool InstancePairMatches(int inHandle,
+ const CDataModelInstance::TInstancePair &inInstancePair)
+ {
+ return inHandle == inInstancePair.first;
+ }
+
+ // if inInstance doesn't exists in inObjects, it will push back NULL instead of throwing
+ // exception
+ static inline void UncheckAddInstancePair(CDataModelInstance::TInstancePairList &outInstances,
+ CUICDMInstanceHandle inInstance,
+ THandleObjectMap &inObjects)
+ {
+ outInstances.insert(
+ std::make_pair(inInstance, CSimpleDataCore::GetInstance(inInstance, inObjects)));
+ }
+
+ static inline bool InstancePropertyMatches(int inProp, const TPropertyPair &inPropPair)
+ {
+ return inProp == inPropPair.first;
+ }
+
+ static bool CheckParentPropertyExistenceWithFail(const TDataModelInstancePtr inInstance,
+ int inProperty,
+ const THandleObjectMap &inObjects);
+
+ static void CheckPropertyExistence(const TDataModelInstancePtr inInstance, int inProperty,
+ const THandleObjectMap &inObjects);
+
+ static inline void FindRelatedItemsForDelete(int inInstance, TIntList &outProperties,
+ TIntList &outChildInstances,
+ const std::pair<int, THandleObjectPtr> &inPair)
+ {
+
+ using namespace std;
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeCDataModelInstance) {
+ TDataModelInstancePtr theInstance =
+ static_pointer_cast<CDataModelInstance>(inPair.second);
+ // No longer a parent class.
+ if (find_if(theInstance->m_Parents.begin(), theInstance->m_Parents.end(),
+ std::bind(InstancePairMatches, inInstance, std::placeholders::_1))
+ != theInstance->m_Parents.end())
+ outChildInstances.push_back(inPair.first);
+ } else if (inPair.second->GetType()
+ == CHandleObject::EHandleObjectTypeCDataModelPropertyDefinitionObject) {
+ const CDataModelPropertyDefinitionObject *theProperty =
+ static_cast<const CDataModelPropertyDefinitionObject *>(inPair.second.get());
+ if (theProperty->m_Definition.m_Instance.GetHandleValue() == inInstance)
+ outProperties.push_back(inPair.first);
+ }
+ }
+
+protected:
+ bool IsInstanceOrDerivedFromHelper(const TDataModelInstancePtr inInstance,
+ CUICDMInstanceHandle inParent) const;
+ void AddInstanceIfDerivedFrom(const std::pair<int, THandleObjectPtr> &inItem,
+ TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParentHandle) const;
+
+ bool GetInstancePropertyValueHelper(const TDataModelInstancePtr inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const;
+
+ // Create an instance *at* this specific handle position
+ // This is used for special cases of serialization
+ CUICDMInstanceHandle CreateInstanceWithHandle(int inHandle);
+ CUICDMPropertyHandle AddPropertyWithHandle(int inHandle, CUICDMInstanceHandle inClass,
+ TCharPtr inName, DataModelDataType::Value inPropType);
+
+ void UncheckedSetSpecificInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue,
+ PropertyValueFlags inIsUserSet);
+};
+
+typedef std::shared_ptr<CSimpleDataCore> TSimpleDataCorePtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.cpp b/src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.cpp
new file mode 100644
index 00000000..b85639e2
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "SimpleSlideCore.h"
+
+using namespace std;
+#ifdef _WIN32
+#pragma warning(disable : 4503)
+#endif
+
+namespace UICDM {
+
+CUICDMSlideHandle CSimpleSlideCore::CreateSlide(CUICDMInstanceHandle inInstance)
+{
+ int nextId = GetNextId();
+ return CreateSlideWithHandle(nextId, inInstance);
+}
+
+CUICDMInstanceHandle CSimpleSlideCore::GetSlideInstance(CUICDMSlideHandle inSlide) const
+{
+ return GetSlideNF(inSlide, m_Objects)->m_Instance;
+}
+
+inline bool SlideInstanceMatches(const THandleObjectPair &inPair, int inInstance)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSSlide
+ && static_cast<const SSlide *>(inPair.second.get())->m_Instance == inInstance)
+ return true;
+ return false;
+}
+
+CUICDMSlideHandle CSimpleSlideCore::GetSlideByInstance(CUICDMInstanceHandle inInstance) const
+{
+ THandleObjectMap::const_iterator theSlide =
+ find_if(m_Objects.begin(), m_Objects.end(),
+ std::bind(SlideInstanceMatches,
+ std::placeholders::_1, inInstance.GetHandleValue()));
+ if (theSlide != m_Objects.end())
+ return theSlide->first;
+ throw SlideNotFound(L"");
+}
+
+void RecurseDeleteSlide(CUICDMSlideHandle inSlide, THandleObjectMap &inObjects,
+ TInstanceHandleList &outInstances)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, inObjects);
+ do_all(theSlide->m_Children,
+ std::bind(RecurseDeleteSlide, std::placeholders::_1,
+ std::ref(inObjects), std::ref(outInstances)));
+ outInstances.push_back(theSlide->m_Instance);
+ CHandleBase::EraseHandle(inSlide, inObjects);
+}
+
+void CSimpleSlideCore::DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances)
+{
+ SSlide *theSlide = GetSlideNF(inSlide, m_Objects);
+ if (theSlide->m_Parent) {
+ SSlide *theParent = GetSlideNF(theSlide->m_Parent, m_Objects);
+ erase_if(theParent->m_Children, std::bind(equal_to<int>(), theSlide->m_Handle,
+ std::placeholders::_1));
+ }
+ RecurseDeleteSlide(inSlide, m_Objects, outInstances);
+}
+
+template <typename TDataType, typename TVectorType>
+inline void MaybeAddObject(const THandleObjectPair &inPair, vector<TVectorType> &outVectorItems)
+{
+ if (inPair.second->GetType() == TDataType::s_Type)
+ outVectorItems.push_back(inPair.first);
+}
+
+void CSimpleSlideCore::GetSlides(TSlideHandleList &outSlides) const
+{
+ do_all(m_Objects,
+ std::bind(MaybeAddObject<SSlide, CUICDMSlideHandle>,
+ std::placeholders::_1, std::ref(outSlides)));
+}
+
+float CSimpleSlideCore::GetSlideTime(CUICDMSlideHandle inSlide) const
+{
+ return GetSlideNF(inSlide, m_Objects)->m_Time;
+}
+
+void CSimpleSlideCore::SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime)
+{
+ GetSlideNF(inSlide, m_Objects)->m_Time = inNewTime;
+}
+
+void CSimpleSlideCore::DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent,
+ int inIndex)
+{
+ int oldParent = GetSlideNF(inSlide, m_Objects)->m_Parent;
+ if (oldParent)
+ erase_if(GetSlideNF(oldParent, m_Objects)->m_Children,
+ std::bind(equal_to<int>(), inSlide, std::placeholders::_1));
+ if (inParent.Valid()) {
+ SSlide *theParent = GetSlideNF(inParent, m_Objects);
+ if (exists(theParent->m_Children, std::bind(equal_to<int>(), inSlide,
+ std::placeholders::_1)))
+ throw SlideDerivationError(L"Already derived");
+ if (inIndex < 0 || inIndex >= (int)theParent->m_Children.size())
+ inIndex = (int)theParent->m_Children.size();
+ theParent->m_Children.insert(theParent->m_Children.begin() + inIndex,
+ inSlide.GetHandleValue());
+ }
+ GetSlideNF(inSlide, m_Objects)->m_Parent = inParent;
+}
+
+CUICDMSlideHandle CSimpleSlideCore::GetParentSlide(CUICDMSlideHandle inSlide) const
+{
+ return GetSlideNF(inSlide, m_Objects)->m_Parent;
+}
+
+void CSimpleSlideCore::GetChildSlides(CUICDMSlideHandle inSlide,
+ TSlideHandleList &outChildren) const
+{
+ transformv_all(GetSlideNF(inSlide, m_Objects)->m_Children, outChildren);
+}
+
+int CSimpleSlideCore::GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const
+{
+ const SSlide *theSlide = GetSlideNF(inParent, m_Objects);
+ size_t dist = distance(theSlide->m_Children.begin(),
+ find_if<TIntList::const_iterator>(
+ theSlide->m_Children, std::bind(equal_to<int>(), inChild,
+ std::placeholders::_1)));
+ if (dist == theSlide->m_Children.size())
+ throw SlideChildNotFoundError(L"");
+ return (int)dist;
+}
+
+bool CSimpleSlideCore::GetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ const SSlide *theSlide = GetSlideNF(inSlide, m_Objects);
+ SInternValue *theValue = theSlide->GetInstancePropertyValue(inHandle, inProperty);
+ if (theValue) {
+ outValue = theValue->GetValue();
+ return true;
+ }
+ if (theSlide->m_Parent)
+ return GetInstancePropertyValue(theSlide->m_Parent, inHandle, inProperty, outValue);
+ return false;
+}
+
+std::pair<SSlide *, SInternValue *> CSimpleSlideCore::ResolveSetInstancePropertyValue(
+ CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle, CUICDMPropertyHandle inProperty)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Objects);
+ SInternValue *theValue = theSlide->GetInstancePropertyValue(inHandle, inProperty);
+ // If we have the value already *or* or parent is not a valid slide, then return now
+ if (theValue || theSlide->m_Parent == 0)
+ return std::make_pair(theSlide, theValue);
+ // Else give our parent a chance.
+ return ResolveSetInstancePropertyValue(theSlide->m_Parent, inHandle, inProperty);
+}
+
+void CSimpleSlideCore::SetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ std::pair<SSlide *, SInternValue *> theTarget(
+ ResolveSetInstancePropertyValue(inSlide, inHandle, inProperty));
+ SInternValue theValue(inValue, GetStringTable());
+ if (theTarget.second)
+ *theTarget.second = theValue;
+ else
+ theTarget.first->SetInstancePropertyValue(inHandle, inProperty, theValue);
+}
+
+void CSimpleSlideCore::ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ CSimpleSlideCore::ForceSetPropertyValue(GetStringTable(), m_Objects, inSlide, inHandle,
+ inProperty, inValue);
+}
+
+bool CSimpleSlideCore::GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ const SSlide *theSlide = GetSlideNF(inSlide, m_Objects);
+ SInternValue *theValue = theSlide->GetInstancePropertyValue(inInstance, inProperty);
+ if (theValue) {
+ outValue = theValue->GetValue();
+ return true;
+ }
+ return false;
+}
+
+void CSimpleSlideCore::GetSpecificInstancePropertyValues(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outValues)
+{
+ const SSlide *theSlide = GetSlideNF(inSlide, m_Objects);
+ theSlide->GetSpecificInstancePropertyValues(inInstance, outValues);
+}
+
+void CSimpleSlideCore::GetSlidePropertyEntries(CUICDMSlideHandle inSlide,
+ TSlideEntryList &outEntries) const
+{
+ const SSlide *theSlide = GetSlideNF(inSlide, m_Objects);
+ theSlide->ToSlideEntryList(outEntries);
+}
+
+bool CSimpleSlideCore::ContainsProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) const
+{
+ const SSlide *theSlide = GetSlideNF(inSlide, m_Objects);
+ return theSlide->GetInstancePropertyValue(inHandle, inProperty) != NULL;
+}
+
+CUICDMSlideHandle CSimpleSlideCore::CreateSlideWithHandle(int inHandle,
+ CUICDMInstanceHandle inInstance)
+{
+ if (HandleValid(inHandle))
+ throw HandleExists(L"");
+ m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SSlide(inHandle, inInstance)));
+ return inHandle;
+}
+
+void CSimpleSlideCore::GetSlideProperties(CUICDMSlideHandle inSlide,
+ TSlideEntryList &outProperties) const
+{
+ outProperties.clear();
+ GetSlidePropertyEntries(inSlide, outProperties);
+}
+
+bool CSimpleSlideCore::IsSlide(CUICDMSlideHandle inSlide) const
+{
+ return m_Objects.find(inSlide) != m_Objects.end();
+}
+
+void CSimpleSlideCore::ForceSetPropertyValue(IStringTable &inStringTable,
+ THandleObjectMap &inObjects, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue)
+{
+ CSimpleSlideCore::GetSlideNF(inSlide, inObjects)
+ ->SetInstancePropertyValue(inHandle, inProperty, SInternValue(inValue, inStringTable));
+}
+
+void CSimpleSlideCore::PushPropertyValueToChildren(CUICDMSlideHandle inParent,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ ForceSetPropertyValue(GetStringTable(), m_Objects, inParent, inHandle, inProperty, inValue);
+ do_all(CSimpleSlideCore::GetSlideNF(inParent, m_Objects)->m_Children,
+ std::bind(ForceSetPropertyValue, std::ref(GetStringTable()), std::ref(m_Objects),
+ std::placeholders::_1, inHandle, inProperty, inValue));
+}
+
+inline void AddIntersectingEntry(TSlideEntryList &outEntries, CUICDMInstanceHandle inst,
+ CUICDMPropertyHandle prop, const SInternValue &inValue)
+{
+ outEntries.push_back(TSlideEntry(inst, prop, inValue.GetValue()));
+}
+
+void CSimpleSlideCore::GetIntersectingProperties(CUICDMSlideHandle inSlide1,
+ CUICDMSlideHandle inSlide2,
+ TSlideEntryList &outEntries) const
+{
+ const SSlide *theSlide1 = GetSlideNF(inSlide1, m_Objects);
+ const SSlide *theSlide2 = GetSlideNF(inSlide2, m_Objects);
+ theSlide1->IntersectProperties(
+ *theSlide2, std::bind(AddIntersectingEntry, std::ref(outEntries),
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+}
+
+void CSimpleSlideCore::PushIntersectingProperties(CUICDMSlideHandle inSlide1,
+ CUICDMSlideHandle inSlide2,
+ CUICDMSlideHandle inDestination)
+{
+ const SSlide *theSlide1 = GetSlideNF(inSlide1, m_Objects);
+ const SSlide *theSlide2 = GetSlideNF(inSlide2, m_Objects);
+ SSlide *theDest = GetSlideNF(inDestination, m_Objects);
+ theSlide1->IntersectProperties(
+ *theSlide2, std::bind(&SSlide::SetInstancePropertyValue, theDest,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+}
+
+void CSimpleSlideCore::ClearPropertyValue(THandleObjectMap &inObjects, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ CSimpleSlideCore::GetSlideNF(inSlide, inObjects)
+ ->RemoveInstancePropertyValue(inInstance, inProperty);
+}
+
+inline void DoForEachSlide(std::pair<int, THandleObjectPtr> inObject,
+ std::function<void(SSlide *)> inFunction)
+{
+ inFunction((SSlide *)inObject.second.get());
+}
+
+void CSimpleSlideCore::ForEachSlide(std::function<void(SSlide *)> inFunction)
+{
+ do_all(m_Objects, std::bind(DoForEachSlide, std::placeholders::_1, inFunction));
+}
+
+void LookupSlideAndDoSomething(CUICDMSlideHandle inSlide, THandleObjectMap &inObjects,
+ std::function<void(SSlide *)> inFunction)
+{
+ inFunction(CSimpleSlideCore::GetSlideNF(inSlide, inObjects));
+}
+
+void CSimpleSlideCore::ForEachChild(CUICDMSlideHandle inParent,
+ std::function<void(SSlide *)> inFunction)
+{
+ do_all(GetSlideNF(inParent, m_Objects)->m_Children,
+ std::bind(LookupSlideAndDoSomething, std::placeholders::_1, m_Objects, inFunction));
+}
+
+bool InstanceMatches(CUICDMInstanceHandle inTarget, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle)
+{
+ return inTarget == inHandle;
+}
+
+bool PropertyMatches(CUICDMPropertyHandle inTarget, CUICDMInstanceHandle,
+ CUICDMPropertyHandle inProp)
+{
+ return inTarget == inProp;
+}
+
+bool InstancePropertyMatchesVector(const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties,
+ CUICDMInstanceHandle slideInst, CUICDMPropertyHandle slideProp)
+{
+ return std::find(inInstances.begin(), inInstances.end(), slideInst) != inInstances.end()
+ && std::find(inProperties.begin(), inProperties.end(), slideProp) != inProperties.end();
+}
+
+bool InstancePropertyMatches(const CUICDMInstanceHandle inInstance,
+ const CUICDMPropertyHandle inProperty, CUICDMInstanceHandle slideInst,
+ CUICDMPropertyHandle slideProp)
+{
+ return inInstance == slideInst && inProperty == slideProp;
+}
+
+void CSimpleSlideCore::DeleteAllInstanceEntries(CUICDMInstanceHandle inHandle)
+{
+ std::function<bool(CUICDMInstanceHandle, CUICDMPropertyHandle)> predicate(
+ std::bind(InstanceMatches, inHandle, std::placeholders::_1, std::placeholders::_2));
+ ForEachSlide(std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate));
+}
+
+void CSimpleSlideCore::DeleteAllPropertyEntries(CUICDMPropertyHandle inHandle)
+{
+ std::function<bool(CUICDMInstanceHandle, CUICDMPropertyHandle)> predicate(
+ std::bind(PropertyMatches, inHandle, std::placeholders::_1, std::placeholders::_2));
+ ForEachSlide(std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate));
+}
+
+void CSimpleSlideCore::DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties)
+{
+ std::function<bool(CUICDMInstanceHandle, CUICDMPropertyHandle)> predicate(
+ std::bind(InstancePropertyMatchesVector, inInstances, inProperties,
+ std::placeholders::_1, std::placeholders::_2));
+ ForEachSlide(std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate));
+}
+
+void CSimpleSlideCore::ClearChildrenPropertyValues(CUICDMSlideHandle inParent,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty)
+{
+ std::function<bool(CUICDMInstanceHandle, CUICDMPropertyHandle)> predicate(
+ std::bind(InstancePropertyMatches, inHandle, inProperty,
+ std::placeholders::_1, std::placeholders::_2));
+ ForEachChild(inParent, std::bind(&SSlide::ClearPropertiesIf, std::placeholders::_1, predicate));
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.h b/src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.h
new file mode 100644
index 00000000..59b31a17
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleSlideCore.h
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef SLIDECOREH
+#define SLIDECOREH
+#include "HandleSystemBase.h"
+#include "UICDMSlideCore.h"
+#include "SimpleDataCore.h"
+#include "UICDMStringTable.h"
+#include <unordered_map>
+
+namespace std {
+
+template<> struct hash<std::pair<int,int> >
+{
+ typedef std::pair<int,int> argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(std::pair<int,int> const& pa) const
+ {
+ result_type const h1 ( std::hash<int>{}(pa.first) );
+ result_type const h2 ( std::hash<int>{}(pa.second) );
+ return h1 ^ (h2 << 1);
+ }
+};
+
+}
+
+namespace UICDM {
+
+// The first revision of this
+typedef std::pair<int, int> TSlideInstancePropertyPair;
+typedef std::unordered_map<TSlideInstancePropertyPair, SInternValue > TSlideEntryHash;
+
+using std::make_pair;
+
+// Abstract access to these objects a little bit because in the future we are going to
+// reorganize the data such that getting a defined set of properties for a single instance is
+// very fast.
+struct SSlide : public CHandleObject
+{
+ SSlide()
+ : m_Instance(0)
+ , m_Parent(0)
+ {
+ }
+ SSlide(int inHandle, int inInstance)
+ : CHandleObject(inHandle)
+ , m_Instance(inInstance)
+ , m_Parent(0)
+ , m_Time(0)
+ {
+ }
+ int m_Instance;
+ int m_Parent;
+ TIntList m_Children;
+ TSlideEntryHash m_Properties;
+ float m_Time;
+
+ // Returns true if it was inserted, false if the property value was set.
+ bool SetInstancePropertyValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ const SInternValue &inValue)
+ {
+ TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue());
+ std::pair<TSlideEntryHash::iterator, bool> insertResult =
+ m_Properties.insert(std::make_pair(theKey, inValue));
+ if (insertResult.second == false)
+ insertResult.first->second = inValue;
+ return insertResult.second;
+ }
+ // Returns true if the property was deleted
+ bool RemoveInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+ {
+ TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue());
+ TSlideEntryHash::iterator find(m_Properties.find(theKey));
+ if (find != m_Properties.end()) {
+ m_Properties.erase(find);
+ return true;
+ }
+ return false;
+ }
+ // Return a pointer to out property value. This allows quicker checks for isset and such
+ SInternValue *GetInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+ {
+ TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue());
+ TSlideEntryHash::const_iterator find(m_Properties.find(theKey));
+ if (find != m_Properties.end())
+ return const_cast<SInternValue *>(&find->second);
+ return NULL;
+ }
+
+ void GetSpecificInstancePropertyValues(CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outProperties) const
+ {
+ for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(),
+ theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->first.first == inInstance)
+ outProperties.push_back(
+ make_pair(theIter->first.second, theIter->second.GetValue()));
+ }
+ }
+
+ bool HasProperty(std::function<bool(const TSlideEntry &)> inPredicate) const
+ {
+ for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(),
+ theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ if (inPredicate(TSlideEntry(theIter->first.first, theIter->first.second,
+ theIter->second.GetValue())))
+ return true;
+ }
+ return false;
+ }
+
+ void DeleteSlideEntries(TSlideEntryList &outList,
+ std::function<bool(const TSlideEntry &)> inPredicate)
+ {
+ for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(),
+ theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ if (inPredicate(TSlideEntry(theIter->first.first, theIter->first.second,
+ theIter->second.GetValue())))
+ outList.push_back(TSlideEntry(theIter->first.first, theIter->first.second,
+ theIter->second.GetValue()));
+ }
+ DeleteEntriesFromList(outList);
+ }
+
+ void DeleteEntriesFromList(const TSlideEntryList &inList)
+ {
+ for (size_t idx = 0, end = inList.size(); idx < end; ++idx)
+ m_Properties.erase(
+ std::pair<int, int>(std::get<0>(inList[idx]), std::get<1>(inList[idx])));
+ }
+
+ void InsertSlideEntries(const TSlideEntryList &inList, IStringTable &inStringTable)
+ {
+ for (size_t idx = 0, end = inList.size(); idx < end; ++idx) {
+ TSlideInstancePropertyPair theKey(std::get<0>(inList[idx]),
+ std::get<1>(inList[idx]));
+ Q_ASSERT(m_Properties.find(theKey) == m_Properties.end());
+ m_Properties.insert(
+ std::make_pair(theKey, SInternValue(std::get<2>(inList[idx]), inStringTable)));
+ }
+ }
+
+ // Convert to the older, straight forward representation of the
+ // data in this slide.
+ void ToSlideEntryList(TSlideEntryList &outList) const
+ {
+ for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(),
+ theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter)
+ outList.push_back(TSlideEntry(theIter->first.first, theIter->first.second,
+ theIter->second.GetValue()));
+ }
+
+ void FromSlideEntryList(const TSlideEntryList &inList, IStringTable &inStringTable)
+ {
+ using namespace std;
+ m_Properties.clear();
+ for (TSlideEntryList::const_iterator theIter = inList.begin(), theEnd = inList.end();
+ theIter != theEnd; ++theIter)
+ SetInstancePropertyValue(get<0>(*theIter), get<1>(*theIter),
+ SInternValue(get<2>(*theIter), inStringTable));
+ }
+
+ // result is the instance, property, myvalue, othervalue
+ void IntersectProperties(const SSlide &inOther,
+ std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle,
+ SInternValue, SInternValue)>
+ inResult) const
+ {
+ for (TSlideEntryHash::const_iterator theIter = m_Properties.begin(),
+ theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ SInternValue *otherValue =
+ inOther.GetInstancePropertyValue(theIter->first.first, theIter->first.second);
+ if (otherValue)
+ inResult(theIter->first.first, theIter->first.second, theIter->second, *otherValue);
+ }
+ }
+
+ // Call the predicate, if it returns true set the property for all properties.
+ // This allows a third party to manipulate the property values during the process.
+ void SetPropertyValuesIf(
+ IStringTable &inStringTable,
+ std::function<bool(CUICDMInstanceHandle, CUICDMPropertyHandle, SValue &)> inPredIntercept)
+ {
+ for (TSlideEntryHash::iterator theIter = m_Properties.begin(), theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ SValue theValue(theIter->second.GetValue());
+ if (inPredIntercept(theIter->first.first, theIter->first.second, theValue))
+ theIter->second = SInternValue(theValue, inStringTable);
+ }
+ }
+
+ void
+ ClearPropertiesIf(std::function<bool(CUICDMInstanceHandle, CUICDMPropertyHandle)> inPredicate)
+ {
+ bool foundOne;
+ do {
+ foundOne = false;
+ for (TSlideEntryHash::iterator theIter = m_Properties.begin(),
+ theEnd = m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ if (inPredicate(theIter->first.first, theIter->first.second)) {
+ foundOne = true;
+ m_Properties.erase(theIter->first);
+ break;
+ }
+ }
+
+ } while (foundOne);
+ }
+
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSSlide;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+class CSimpleSlideCore : public CHandleBase, public ISlideCore
+{
+ TStringTablePtr m_StringTable;
+
+public: // use
+ CSimpleSlideCore(TStringTablePtr inStrTable)
+ : m_StringTable(inStrTable)
+ {
+ }
+
+ TStringTablePtr GetStringTablePtr() const override { return m_StringTable; }
+ IStringTable &GetStringTable() const override { return *m_StringTable.get(); }
+ CUICDMSlideHandle CreateSlide(CUICDMInstanceHandle inInstance) override;
+ CUICDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inSlide) const override;
+ CUICDMSlideHandle GetSlideByInstance(CUICDMInstanceHandle inInstance) const override;
+ void DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances) override;
+ void GetSlides(TSlideHandleList &outSlides) const override;
+
+ float GetSlideTime(CUICDMSlideHandle inSlide) const override;
+ void SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime) override;
+
+ void DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent, int inIndex = -1) override;
+ CUICDMSlideHandle GetParentSlide(CUICDMSlideHandle inSlide) const override;
+ void GetChildSlides(CUICDMSlideHandle inSlide, TSlideHandleList &outChildren) const override;
+ int GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const override;
+
+ bool GetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ void SetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+
+ // Return the slide this property should be set on, along with the previous value if any.
+ // Set the value on the slide.
+ std::pair<SSlide *, SInternValue *>
+ ResolveSetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty);
+ void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+
+ bool GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+
+ void GetSpecificInstancePropertyValues(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outValues) override;
+
+ void GetSlidePropertyEntries(CUICDMSlideHandle inSlide, TSlideEntryList &outEntries) const override;
+
+ void PushPropertyValueToChildren(CUICDMSlideHandle inParent, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+
+ void GetIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ TSlideEntryList &outEntries) const override;
+ void PushIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ CUICDMSlideHandle inDestination) override;
+
+ void ClearChildrenPropertyValues(CUICDMSlideHandle inParent, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) override;
+
+ void DeleteAllInstanceEntries(CUICDMInstanceHandle inHandle) override;
+ void DeleteAllPropertyEntries(CUICDMPropertyHandle inHandle) override;
+ void DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties) override;
+
+ bool ContainsProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) const override;
+ bool HandleValid(int inHandle) const override { return CHandleBase::HandleValid(inHandle); }
+
+ CUICDMSlideHandle CreateSlideWithHandle(int inHandle, CUICDMInstanceHandle inInstance);
+ void GetSlideProperties(CUICDMSlideHandle inSlide, TSlideEntryList &outProperties) const;
+
+ bool IsSlide(CUICDMSlideHandle inSlide) const override;
+
+ // Possibly alter every slide in the database
+ void ForEachSlide(std::function<void(SSlide *)> inFunction);
+ void ForEachChild(CUICDMSlideHandle inSlide, std::function<void(SSlide *)> inFunction);
+
+ // Only implemented at the producer level, not at this lower level.
+ void CopyProperties(CUICDMSlideHandle /*inSourceSlide*/,
+ CUICDMInstanceHandle /*inSourceInstance*/,
+ CUICDMSlideHandle /*inDestSlide*/, CUICDMInstanceHandle /*inDestInstance*/) override
+ {
+ throw SlideNotFound(L"");
+ }
+
+ static SSlide *GetSlideNF(int inHandle, THandleObjectMap &inObjects)
+ {
+ return const_cast<SSlide *>(
+ GetSlideNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const SSlide *GetSlideNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ const SSlide *theSlide = GetHandleObject<SSlide>(inHandle, inObjects);
+ if (theSlide)
+ return theSlide;
+ throw SlideNotFound(L"");
+ }
+
+ static inline bool PropertyFound(int inInstance, int inProperty, const TSlideEntry &inEntry)
+ {
+ if (inInstance == std::get<0>(inEntry) && inProperty == std::get<1>(inEntry))
+ return true;
+ return false;
+ }
+
+ static void ForceSetPropertyValue(IStringTable &inStringTable, THandleObjectMap &inObjects,
+ CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue);
+
+ static void ClearPropertyValue(THandleObjectMap &inObjects, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty);
+
+ static inline bool SlideEntryInstanceMatches(const TSlideEntry &inEntry,
+ CUICDMInstanceHandle inHandle)
+ {
+ using namespace std;
+ if (inHandle.GetHandleValue() == get<0>(inEntry))
+ return true;
+ return false;
+ }
+
+ static inline bool SlideEntryPropertyMatches(const TSlideEntry &inEntry,
+ CUICDMPropertyHandle inProperty)
+ {
+ using namespace std;
+ return inProperty.GetHandleValue() == get<1>(inEntry);
+ }
+
+ static inline bool SlideEntryInstancePropertyMatches(const TSlideEntry &inEntry,
+ const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties)
+ {
+ using namespace std;
+ return exists(inInstances, std::bind(equal_to<int>(), get<0>(inEntry),
+ std::placeholders::_1))
+ && exists(inProperties, std::bind(equal_to<int>(), get<1>(inEntry),
+ std::placeholders::_1));
+ }
+};
+
+typedef std::shared_ptr<CSimpleSlideCore> TSimpleSlideCorePtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.cpp b/src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.cpp
new file mode 100644
index 00000000..c52a1422
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "SimpleSlideGraphCore.h"
+
+using namespace std;
+
+namespace UICDM {
+
+CUICDMSlideGraphHandle CSimpleSlideGraphCore::CreateSlideGraph(CUICDMSlideHandle inRoot)
+{
+ int nextId = GetNextId();
+ return CreateSlideGraphWithHandle(nextId, inRoot);
+}
+
+CUICDMSlideHandle CSimpleSlideGraphCore::GetGraphRoot(CUICDMSlideGraphHandle inGraph) const
+{
+ return GetSlideGraphNF(inGraph, m_Objects)->m_Root;
+}
+
+inline bool RootSlideMatches(const THandleObjectPair &inPair, CUICDMSlideHandle inSlide)
+{
+ const SSlideGraph *theGraph = static_cast<SSlideGraph *>(inPair.second.get());
+ if (theGraph->m_Root == inSlide)
+ return true;
+ return false;
+}
+
+CUICDMSlideGraphHandle CSimpleSlideGraphCore::GetSlideGraph(CUICDMSlideHandle inSlide) const
+{
+ THandleObjectMap::const_iterator theFind = find_if<THandleObjectMap::const_iterator>(
+ m_Objects, std::bind(RootSlideMatches, std::placeholders::_1, inSlide));
+ if (theFind != m_Objects.end())
+ return theFind->first;
+ return 0;
+}
+
+inline CUICDMSlideGraphHandle ToGraphHandle(const THandleObjectPair &inPair)
+{
+ return inPair.first;
+}
+
+void CSimpleSlideGraphCore::GetSlideGraphs(TSlideGraphHandleList &outGraphs) const
+{
+ outGraphs.resize(m_Objects.size());
+ transform(m_Objects.begin(), m_Objects.end(), outGraphs.begin(), ToGraphHandle);
+}
+
+void CSimpleSlideGraphCore::DeleteSlideGraph(CUICDMSlideGraphHandle inHandle)
+{
+ TSlideInstancePairList theAssociatedInstances;
+ GetAssociatedInstances(inHandle, theAssociatedInstances);
+ for (size_t idx = 0, end = theAssociatedInstances.size(); idx < end; ++idx)
+ DissociateInstance(theAssociatedInstances[idx].second);
+ EraseHandle(inHandle, m_Objects);
+}
+
+void CSimpleSlideGraphCore::AssociateInstance(CUICDMSlideGraphHandle inSlideGraph,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+{
+ pair<TInstanceToGraphMap::iterator, bool> theResult =
+ m_InstanceToGraph.insert(make_pair(inInstance, make_pair(inSlideGraph, inSlide)));
+ Q_ASSERT(theResult.second);
+ if (theResult.second == false) {
+ theResult.first->second.first = inSlideGraph;
+ theResult.first->second.second = inSlide;
+ }
+ pair<TGraphToInstanceMap::iterator, bool> theGraphResult =
+ m_GraphToInstances.insert(make_pair(inSlideGraph, TSlideInstancePairList()));
+ insert_unique(theGraphResult.first->second, make_pair(inSlide, inInstance));
+}
+
+void CSimpleSlideGraphCore::GetAssociatedInstances(CUICDMSlideGraphHandle inSlideGraph,
+ TSlideInstancePairList &outAssociations) const
+{
+ TGraphToInstanceMap::const_iterator theFind = m_GraphToInstances.find(inSlideGraph);
+ if (theFind != m_GraphToInstances.end())
+ outAssociations.insert(outAssociations.end(), theFind->second.begin(),
+ theFind->second.end());
+}
+
+TGraphSlidePair CSimpleSlideGraphCore::GetAssociatedGraph(CUICDMInstanceHandle inInstance) const
+{
+ TInstanceToGraphMap::const_iterator theResult = m_InstanceToGraph.find(inInstance);
+ if (theResult != m_InstanceToGraph.end())
+ return theResult->second;
+ return TGraphSlidePair();
+}
+
+struct SInstanceMatcher
+{
+ CUICDMInstanceHandle m_Instance;
+ SInstanceMatcher(CUICDMInstanceHandle inInst)
+ : m_Instance(inInst)
+ {
+ }
+ bool operator()(const pair<CUICDMSlideHandle, CUICDMInstanceHandle> &inItem) const
+ {
+ return m_Instance == inItem.second;
+ }
+};
+
+void CSimpleSlideGraphCore::DissociateInstance(CUICDMInstanceHandle inInstance)
+{
+ TGraphSlidePair theAssociatedGraph(GetAssociatedGraph(inInstance));
+
+ TGraphToInstanceMap::iterator theFind = m_GraphToInstances.find(theAssociatedGraph.first);
+ if (theFind != m_GraphToInstances.end()) {
+ erase_if(theFind->second, SInstanceMatcher(inInstance));
+ if (theFind->second.size() == 0)
+ m_GraphToInstances.erase(theAssociatedGraph.first);
+ }
+
+ m_InstanceToGraph.erase(inInstance);
+}
+
+void CSimpleSlideGraphCore::SetGraphActiveSlide(CUICDMSlideGraphHandle inGraph,
+ CUICDMSlideHandle inSlide)
+{
+ GetSlideGraphNF(inGraph, m_Objects)->m_ActiveSlide = inSlide;
+}
+
+CUICDMSlideHandle CSimpleSlideGraphCore::GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const
+{
+ const SSlideGraph *theSlide = GetSlideGraphNF(inGraph, m_Objects);
+ if (theSlide->m_ActiveSlide)
+ return theSlide->m_ActiveSlide;
+ return theSlide->m_Root;
+}
+
+bool CSimpleSlideGraphCore::HandleValid(int inHandle) const
+{
+ return CHandleBase::HandleValid(inHandle);
+}
+
+CUICDMSlideGraphHandle CSimpleSlideGraphCore::CreateSlideGraphWithHandle(int inHandle,
+ CUICDMSlideHandle inRoot)
+{
+ m_Objects.insert(make_pair(inHandle, (THandleObjectPtr) new SSlideGraph(inHandle, inRoot)));
+ return inHandle;
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.h b/src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.h
new file mode 100644
index 00000000..272df008
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SimpleSlideGraphCore.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef SLIDEGRAPHCOREH
+#define SLIDEGRAPHCOREH
+#include "UICDMStringTable.h"
+#include "UICDMSlideGraphCore.h"
+#include "HandleSystemBase.h"
+#include "UICDMErrors.h"
+
+namespace UICDM {
+using namespace std;
+struct SSlideGraph : public CHandleObject
+{
+ SSlideGraph()
+ : m_Root(0)
+ , m_ActiveSlide(0)
+ {
+ }
+ SSlideGraph(int inHandle, int inSlideRoot)
+ : CHandleObject(inHandle)
+ , m_Root(inSlideRoot)
+ , m_ActiveSlide(0)
+ {
+ }
+ CUICDMSlideHandle m_Root;
+ CUICDMSlideHandle m_ActiveSlide;
+
+ static const EHandleObjectType s_Type = CHandleObject::EHandleObjectTypeSSlideGraph;
+ EHandleObjectType GetType() override { return s_Type; }
+};
+
+class CSimpleSlideGraphCore : public CHandleBase, public ISlideGraphCore
+{
+ TStringTablePtr m_StringTable;
+ typedef std::unordered_map<CUICDMInstanceHandle,
+ pair<CUICDMSlideGraphHandle, CUICDMSlideHandle>, std::hash<int>>
+ TInstanceToGraphMap;
+ typedef std::unordered_map<CUICDMSlideGraphHandle, TSlideInstancePairList, std::hash<int>>
+ TGraphToInstanceMap;
+
+ TInstanceToGraphMap m_InstanceToGraph;
+ TGraphToInstanceMap m_GraphToInstances;
+
+public:
+ CSimpleSlideGraphCore(TStringTablePtr strTable = TStringTablePtr())
+ : m_StringTable(strTable)
+ {
+ }
+ TStringTablePtr GetStringTablePtr() { return m_StringTable; }
+ /**
+ * A slide graph is used to associate a set of instances to a set of slides.
+ * This allows rapid lookup of properties, as an implementation of these.
+ * There are a few assumptions here. First is that a given slide can be a member
+ * of one and only one graph (i.e. it does not derive from another slide outside of the graph).
+ * Second is that an instance is a member of one and only one graph.
+ */
+ CUICDMSlideGraphHandle CreateSlideGraph(CUICDMSlideHandle inRoot) override;
+ CUICDMSlideHandle GetGraphRoot(CUICDMSlideGraphHandle inGraph) const override;
+ CUICDMSlideGraphHandle GetSlideGraph(CUICDMSlideHandle inSlide) const override;
+ void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const override;
+ void DeleteSlideGraph(CUICDMSlideGraphHandle inHandle) override;
+
+ /**
+ * Associate a given instance handle with a given graph. This will ensure that property
+ *lookups
+ * will travel through this graph before they hit the main data core. Instances may be
+ *associated
+ * with a sub-slide of a given graph, not just the root. An instance associated with the root
+ *is
+ * implicitly associated with any root-derived slides.
+ */
+ void AssociateInstance(CUICDMSlideGraphHandle inSlideGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) override;
+ void GetAssociatedInstances(CUICDMSlideGraphHandle inSlideGraph,
+ TSlideInstancePairList &outAssociations) const override;
+ TGraphSlidePair GetAssociatedGraph(CUICDMInstanceHandle inInstance) const override;
+ void DissociateInstance(CUICDMInstanceHandle inInstance) override;
+
+ /**
+ * All graphs always have an active slide. This is assumed to be the root right off the bat.
+ */
+ void SetGraphActiveSlide(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override;
+ CUICDMSlideHandle GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const override;
+
+ bool HandleValid(int inHandle) const override;
+
+ CUICDMSlideGraphHandle CreateSlideGraphWithHandle(int inHandle, CUICDMSlideHandle inRoot);
+
+ static SSlideGraph *GetSlideGraphNF(int inHandle, THandleObjectMap &inObjects)
+ {
+ return const_cast<SSlideGraph *>(
+ GetSlideGraphNF(inHandle, static_cast<const THandleObjectMap &>(inObjects)));
+ }
+
+ static const SSlideGraph *GetSlideGraphNF(int inHandle, const THandleObjectMap &inObjects)
+ {
+ const SSlideGraph *theSlide = GetHandleObject<SSlideGraph>(inHandle, inObjects);
+ if (theSlide)
+ return theSlide;
+ throw SlideGraphNotFound(L"");
+ }
+};
+
+typedef std::shared_ptr<CSimpleSlideGraphCore> TSimpleSlideGraphCorePtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.cpp b/src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.cpp
new file mode 100644
index 00000000..fcd4812b
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.cpp
@@ -0,0 +1,555 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#ifdef _WIN32
+#pragma warning(disable : 4503) // decorated name length exceeded
+#endif
+#include "SlideCoreProducer.h"
+#include "HandleSystemTransactions.h"
+#include "VectorTransactions.h"
+#include "SignalsImpl.h"
+
+using namespace std;
+
+namespace UICDM {
+
+CUICDMSlideHandle CSlideCoreProducer::CreateSlide(CUICDMInstanceHandle inInstance)
+{
+ CUICDMSlideHandle retval = m_Data->CreateSlide(inInstance);
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ GetSignalSender()->SendSlideCreated(retval);
+ return retval;
+}
+
+CUICDMInstanceHandle CSlideCoreProducer::GetSlideInstance(CUICDMSlideHandle inSlide) const
+{
+ return m_Data->GetSlideInstance(inSlide);
+}
+
+CUICDMSlideHandle CSlideCoreProducer::GetSlideByInstance(CUICDMInstanceHandle inSlide) const
+{
+ return m_Data->GetSlideByInstance(inSlide);
+}
+
+void SendPropertyRemoved(const TSlideEntry &inEntry, CUICDMSlideHandle inSlide,
+ ISlideCoreSignalSender *inSender)
+{
+ inSender->SendPropertyValueRemoved(inSlide, get<0>(inEntry), get<1>(inEntry), get<2>(inEntry));
+}
+
+void RecurseCreateDeleteTransactions(TTransactionConsumerPtr inConsumer, CUICDMSlideHandle inSlide,
+ THandleObjectMap &inObjects, ISlideCoreSignalSender *inSender)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, inObjects);
+ inSender->SendBeforeSlideDeleted(theSlide->m_Handle);
+ do_all(theSlide->m_Children, std::bind(RecurseCreateDeleteTransactions, inConsumer,
+ std::placeholders::_1,
+ std::ref(inObjects), inSender));
+ if (inConsumer)
+ CREATE_HANDLE_DELETE_TRANSACTION(inConsumer, inSlide, inObjects);
+ inSender->SendSlideDeleted(theSlide->m_Handle);
+}
+
+void CSlideCoreProducer::DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances)
+{
+ // Ensure exists
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects);
+ if (theSlide->m_Parent) {
+ SSlide *theParent = CSimpleSlideCore::GetSlideNF(theSlide->m_Parent, m_Data->m_Objects);
+ CreateVecEraseTransaction<int>(__FILE__, __LINE__, m_Consumer, inSlide,
+ theParent->m_Children);
+ }
+ RecurseCreateDeleteTransactions(m_Consumer, inSlide, m_Data->m_Objects, GetSignalSender());
+ // Not any more...
+ m_Data->DeleteSlide(inSlide, outInstances);
+}
+
+void CSlideCoreProducer::GetSlides(TSlideHandleList &outSlides) const
+{
+ m_Data->GetSlides(outSlides);
+}
+
+float CSlideCoreProducer::GetSlideTime(CUICDMSlideHandle inSlide) const
+{
+ return m_Data->GetSlideTime(inSlide);
+}
+
+void CSlideCoreProducer::SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects);
+ float oldTime = theSlide->m_Time;
+ theSlide->m_Time = inNewTime;
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(std::shared_ptr<ITransaction>(CREATE_GENERIC_TRANSACTION(
+ std::bind(&CSlideCoreProducer::SetSlideTime, this, inSlide, inNewTime),
+ std::bind(&CSlideCoreProducer::SetSlideTime, this, inSlide, oldTime))));
+ } else
+ GetSignalSender()->SendSlideTimeChanged(inSlide);
+}
+
+inline void SetSlideParent(THandleObjectMap &inObjects, int inSlide, int inParent)
+{
+ CSimpleSlideCore::GetSlideNF(inSlide, inObjects)->m_Parent = inParent;
+}
+
+void CSlideCoreProducer::DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent,
+ int inIndex)
+{
+ // Integrity checks to ensure operation will proceed
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects);
+ SSlide *theNewParent = NULL;
+ if (inParent)
+ theNewParent = CSimpleSlideCore::GetSlideNF(inParent, m_Data->m_Objects);
+ SSlide *theOldParent = NULL;
+ if (theSlide->m_Parent)
+ theOldParent = CSimpleSlideCore::GetSlideNF(theSlide->m_Parent, m_Data->m_Objects);
+
+ if (theSlide->m_Parent && m_Consumer) {
+ m_Consumer->OnTransaction(TTransactionPtr(CREATE_GENERIC_TRANSACTION(
+ std::bind(SetSlideParent, std::ref(m_Data->m_Objects), inSlide, inParent),
+ std::bind(SetSlideParent, std::ref(m_Data->m_Objects), inSlide,
+ theSlide->m_Parent))));
+ if (theOldParent)
+ CreateVecEraseTransaction<int>(__FILE__, __LINE__, m_Consumer, inSlide,
+ theOldParent->m_Children);
+ GetSignalSender()->SendSlideDerived(inSlide, 0, inIndex);
+ }
+ m_Data->DeriveSlide(inSlide, inParent, inIndex);
+ if (theNewParent)
+ CreateVecInsertTransaction<int>(__FILE__, __LINE__, m_Consumer, inSlide,
+ theNewParent->m_Children);
+ GetSignalSender()->SendSlideDerived(inSlide, inParent, inIndex);
+}
+
+CUICDMSlideHandle CSlideCoreProducer::GetParentSlide(CUICDMSlideHandle inSlide) const
+{
+ return m_Data->GetParentSlide(inSlide);
+}
+
+void CSlideCoreProducer::GetChildSlides(CUICDMSlideHandle inSlide,
+ TSlideHandleList &outChildren) const
+{
+ m_Data->GetChildSlides(inSlide, outChildren);
+}
+
+int CSlideCoreProducer::GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const
+{
+ return m_Data->GetChildIndex(inParent, inChild);
+}
+
+bool CSlideCoreProducer::GetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ return m_Data->GetInstancePropertyValue(inSlide, inHandle, inProperty, outValue);
+}
+
+inline void EraseProperty(TSlideEntryList &inProperties, int inInstance, int inProperty)
+{
+ erase_if(inProperties,
+ std::bind(CSimpleSlideCore::PropertyFound, inInstance, inProperty,
+ std::placeholders::_1));
+}
+
+void CSlideCoreProducer::SetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ std::pair<SSlide *, SInternValue *> slideAndProp(
+ m_Data->ResolveSetInstancePropertyValue(inSlide, inHandle, inProperty));
+ DoForceSetInstancePropertyValue(slideAndProp.first->m_Handle, inHandle, inProperty, inValue);
+}
+
+struct HashMapDataValueInsertTransaction
+ : public HashMapInsertTransaction<TSlideInstancePropertyPair, SInternValue,
+ TSlideEntryHash::hasher>
+{
+ typedef HashMapInsertTransaction<TSlideInstancePropertyPair, SInternValue,
+ TSlideEntryHash::hasher>
+ TBase;
+ HashMapDataValueInsertTransaction(
+ const char *inFile, int inLine, TSlideEntryHash &map,
+ const std::pair<TSlideInstancePropertyPair, SInternValue> &val)
+ : TBase(inFile, inLine, map, val)
+ {
+ }
+ void Do() override
+ {
+ std::pair<int, int> theKey = m_Value.first;
+ SValue theTempValue = m_Value.second.GetValue();
+ TDataStrPtr theStrPtr;
+ if (GetValueType(theTempValue) == DataModelDataType::String) {
+ theStrPtr = UICDM::get<TDataStrPtr>(theTempValue);
+ }
+ (void)theStrPtr;
+ TBase::Add();
+ }
+};
+
+inline void CSlideCoreProducer::DoForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, m_Data->m_Objects);
+ SInternValue theNewValue(inValue, m_Data->GetStringTable());
+ SInternValue *theCurrentValue(theSlide->GetInstancePropertyValue(inHandle, inProperty));
+
+ std::pair<int, int> theKey(inHandle, inProperty);
+ SlideInstancePropertyKey mergeMapKey(inSlide, inHandle, inProperty);
+ TSlidePropertyMergeMap::iterator iter = m_PropertyMergeMap.find(mergeMapKey);
+ if (iter != m_PropertyMergeMap.end()) {
+ const SValue &theTempValue(theNewValue.GetValue());
+ CSimpleSlideCore::ForceSetPropertyValue(m_Data->GetStringTable(), m_Data->m_Objects,
+ inSlide, inHandle, inProperty, theTempValue);
+ iter->second->Update(theNewValue);
+ if (GetValueType(theTempValue) == DataModelDataType::String) {
+ TDataStrPtr theStrPtr = UICDM::get<TDataStrPtr>(theTempValue);
+ UICDM_DEBUG_LOG(m_Data->GetStringTable().GetNarrowStr(theStrPtr->GetData()));
+ }
+ return; // don't signal
+ } else {
+ TSlidePropertyMergeMapEntry theEntry;
+ if (theCurrentValue) {
+ theEntry =
+ CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, theKey,
+ *theCurrentValue, theNewValue, theSlide->m_Properties);
+ } else {
+ if (m_Consumer) {
+ std::shared_ptr<HashMapDataValueInsertTransaction> theTransaction =
+ std::make_shared<HashMapDataValueInsertTransaction>(
+ __FILE__, __LINE__, std::ref(theSlide->m_Properties),
+ std::make_pair(theKey, theNewValue));
+ m_Consumer->OnTransaction(theTransaction);
+ theEntry = theTransaction;
+ }
+ }
+ if (theEntry)
+ m_PropertyMergeMap.insert(make_pair(mergeMapKey, theEntry));
+ CSimpleSlideCore::ForceSetPropertyValue(m_Data->GetStringTable(), m_Data->m_Objects,
+ inSlide, inHandle, inProperty,
+ theNewValue.GetValue());
+ GetSignalSender()->SendPropertyValueSet(inSlide, inHandle, inProperty,
+ theNewValue.GetValue());
+ }
+}
+
+void CSlideCoreProducer::ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ if (m_Consumer)
+ DoForceSetInstancePropertyValue(inSlide, inHandle, inProperty, inValue);
+ else
+ m_Data->ForceSetInstancePropertyValue(inSlide, inHandle, inProperty, inValue);
+}
+
+bool CSlideCoreProducer::GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ return m_Data->GetSpecificInstancePropertyValue(inSlide, inInstance, inProperty, outValue);
+}
+
+bool CSlideCoreProducer::ContainsProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) const
+{
+ return m_Data->ContainsProperty(inSlide, inHandle, inProperty);
+}
+
+void CSlideCoreProducer::GetSlidePropertyEntries(CUICDMSlideHandle inSlide,
+ TSlideEntryList &outEntries) const
+{
+ return m_Data->GetSlidePropertyEntries(inSlide, outEntries);
+}
+
+void CSlideCoreProducer::PushPropertyValueToChildren(CUICDMSlideHandle inParent,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ SSlide *theParent = CSimpleSlideCore::GetSlideNF(inParent, m_Data->m_Objects);
+ DoForceSetInstancePropertyValue(inParent, inHandle, inProperty, inValue);
+ do_all(theParent->m_Children, std::bind(&CSlideCoreProducer::DoForceSetInstancePropertyValue,
+ this, std::placeholders::_1,
+ inHandle, inProperty, inValue));
+}
+
+inline void ClearValueWithTransactions(TTransactionConsumerPtr inConsumer,
+ THandleObjectMap &inObjects,
+ ISlideCoreSignalSender *inSignalSender, int inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(inSlide, inObjects);
+ SInternValue *theCurrentValue(theSlide->GetInstancePropertyValue(inHandle, inProperty));
+ if (theCurrentValue) {
+ SValue theValue(theCurrentValue->GetValue());
+ std::pair<int, int> theKey(inHandle, inProperty);
+ CreateHashMapEraseTransaction(__FILE__, __LINE__, inConsumer,
+ std::make_pair(theKey, *theCurrentValue),
+ theSlide->m_Properties);
+ CSimpleSlideCore::ClearPropertyValue(inObjects, inSlide, inHandle, inProperty);
+ inSignalSender->SendPropertyValueRemoved(inSlide, inHandle, inProperty, theValue);
+ }
+}
+
+void CSlideCoreProducer::ClearChildrenPropertyValues(CUICDMSlideHandle inParent,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty)
+{
+ SSlide *theParent = CSimpleSlideCore::GetSlideNF(inParent, m_Data->m_Objects);
+ do_all(theParent->m_Children,
+ std::bind(ClearValueWithTransactions, m_Consumer, std::ref(m_Data->m_Objects),
+ GetSignalSender(), std::placeholders::_1, inHandle, inProperty));
+}
+
+typedef tuple<int, TSlideEntryList, TSlideEntryList> TSlideSlideEntryTuple;
+typedef std::vector<TSlideSlideEntryTuple> TSlideSlideEntryTupleList;
+
+inline void CreateVectorPreReplaceData(THandleObjectPair inPair,
+ TSlideSlideEntryTupleList &outSlideSlideEntries,
+ function<bool(const TSlideEntry &)> inPredicate)
+{
+ if (inPair.second->GetType() == CHandleObject::EHandleObjectTypeSSlide) {
+ SSlide *theSlide = static_cast<SSlide *>(inPair.second.get());
+ if (theSlide->HasProperty(inPredicate)) {
+ outSlideSlideEntries.push_back(
+ TSlideSlideEntryTuple(inPair.first, TSlideEntryList(), TSlideEntryList()));
+ theSlide->DeleteSlideEntries(get<1>(outSlideSlideEntries.back()), inPredicate);
+ }
+ }
+}
+
+inline void RunInsert(tuple<int, TSlideEntryList, TSlideEntryList> &inTuple,
+ THandleObjectMap &inObjects, IStringTable &inStringTable)
+{
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(get<0>(inTuple), inObjects);
+ theSlide->InsertSlideEntries(get<1>(inTuple), inStringTable);
+}
+
+inline void RunFullInsert(std::shared_ptr<TSlideSlideEntryTupleList> inList,
+ THandleObjectMap &inObjects, IStringTable &inStringTable)
+{
+ for (TSlideSlideEntryTupleList::iterator theIter = inList->begin(); theIter != inList->end();
+ ++theIter)
+ RunInsert(*theIter, inObjects, inStringTable);
+}
+
+inline void RunFullErase(std::shared_ptr<TSlideSlideEntryTupleList> inList,
+ THandleObjectMap &inObjects)
+{
+ for (TSlideSlideEntryTupleList::iterator theIter = inList->begin(); theIter != inList->end();
+ ++theIter) {
+ SSlide *theSlide = CSimpleSlideCore::GetSlideNF(get<0>(*theIter), inObjects);
+ theSlide->DeleteEntriesFromList(std::get<1>(*theIter));
+ }
+}
+
+void DeleteAllSlideEntriesWithUndo(TTransactionConsumerPtr inConsumer, IStringTable &inStringTable,
+ THandleObjectMap &inObjects,
+ function<bool(const TSlideEntry &)> inPredicate)
+{
+ std::shared_ptr<TSlideSlideEntryTupleList> theEntries(new TSlideSlideEntryTupleList);
+ do_all(inObjects,
+ std::bind(CreateVectorPreReplaceData,
+ std::placeholders::_1, std::ref(*theEntries), inPredicate));
+ if (inConsumer)
+ CreateGenericTransactionWithConsumer(
+ __FILE__, __LINE__, inConsumer,
+ std::bind(RunFullErase, theEntries, std::ref(inObjects)),
+ std::bind(RunFullInsert, theEntries, std::ref(inObjects),
+ std::ref(inStringTable)));
+}
+
+void CSlideCoreProducer::DeleteAllInstanceEntries(CUICDMInstanceHandle inInstance)
+{
+ DeleteAllSlideEntriesWithUndo(
+ m_Consumer, GetStringTable(), m_Data->m_Objects,
+ std::bind(CSimpleSlideCore::SlideEntryInstanceMatches, std::placeholders::_1, inInstance));
+}
+void CSlideCoreProducer::DeleteAllPropertyEntries(CUICDMPropertyHandle inHandle)
+{
+ DeleteAllSlideEntriesWithUndo(
+ m_Consumer, GetStringTable(), m_Data->m_Objects,
+ std::bind(CSimpleSlideCore::SlideEntryPropertyMatches, std::placeholders::_1, inHandle));
+}
+
+void CSlideCoreProducer::DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties)
+{
+ DeleteAllSlideEntriesWithUndo(m_Consumer, GetStringTable(), m_Data->m_Objects,
+ std::bind(CSimpleSlideCore::SlideEntryInstancePropertyMatches,
+ std::placeholders::_1, std::cref(inInstances),
+ std::cref(inProperties)));
+}
+
+void CSlideCoreProducer::GetIntersectingProperties(CUICDMSlideHandle inSlide1,
+ CUICDMSlideHandle inSlide2,
+ TSlideEntryList &outEntries) const
+{
+ return m_Data->GetIntersectingProperties(inSlide1, inSlide2, outEntries);
+}
+
+bool InstancePropMatches(CUICDMInstanceHandle instance, CUICDMPropertyHandle prop,
+ const TSlideEntry &entry)
+{
+ return instance == get<0>(entry) && prop == get<1>(entry);
+}
+
+bool SendPropertyAddedIfNotInList(CUICDMInstanceHandle instance, CUICDMPropertyHandle prop,
+ SValue & /*value*/, const TSlideEntryList &inList,
+ CUICDMSlideHandle inSource, CUICDMSlideHandle inSlide,
+ ISlideCoreSignalSender * /*inSignalSender*/)
+{
+ if (find_if<TSlideEntryList::const_iterator>(
+ inList, std::bind(InstancePropMatches, instance, prop, std::placeholders::_1))
+ == inList.end()) {
+ return true;
+ }
+ return false;
+}
+
+// destination gets the properties from slide 1 that have corresponding entries in slide 2
+void CSlideCoreProducer::PushIntersectingProperties(CUICDMSlideHandle inSlide1,
+ CUICDMSlideHandle inSlide2,
+ CUICDMSlideHandle inDestination)
+{
+ SSlide *theDest = CSimpleSlideCore::GetSlideNF(inDestination, m_Data->m_Objects);
+ TSlideEntryList theProperties;
+ theDest->ToSlideEntryList(theProperties);
+ m_Data->PushIntersectingProperties(inSlide1, inSlide2, inDestination);
+ theDest->SetPropertyValuesIf(GetStringTable(), std::bind(SendPropertyAddedIfNotInList,
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3,
+ theProperties, inSlide1,
+ inDestination, GetSignalSender()));
+ if (m_Consumer) {
+ TSlideEntryList theResult;
+ theDest->ToSlideEntryList(theResult);
+ m_Consumer->OnTransaction(TTransactionPtr(
+ CREATE_GENERIC_TRANSACTION(std::bind(&SSlide::FromSlideEntryList, theDest, theResult,
+ std::ref(GetStringTable())),
+ std::bind(&SSlide::FromSlideEntryList, theDest,
+ theProperties, std::ref(GetStringTable())))));
+ }
+}
+
+void CSlideCoreProducer::CopyProperties(CUICDMSlideHandle inSourceSlide,
+ CUICDMInstanceHandle inSourceInstance,
+ CUICDMSlideHandle inDestSlide,
+ CUICDMInstanceHandle inDestInstance)
+{
+ SSlide *sourceSlide = CSimpleSlideCore::GetSlideNF(inSourceSlide, m_Data->m_Objects);
+
+ for (TSlideEntryHash::iterator theIter = sourceSlide->m_Properties.begin(),
+ theEnd = sourceSlide->m_Properties.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->first.first == inSourceInstance) {
+ // Set it once so it appears in the slide
+ // Then call the main method that will send the events.
+ DoForceSetInstancePropertyValue(inDestSlide, inDestInstance, theIter->first.second,
+ theIter->second.GetValue());
+ }
+ }
+}
+
+bool CSlideCoreProducer::HandleValid(int inHandle) const
+{
+ return m_Data->HandleValid(inHandle);
+}
+
+bool CSlideCoreProducer::IsSlide(CUICDMSlideHandle inSlide) const
+{
+ return m_Data->IsSlide(inSlide);
+}
+
+void CSlideCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_Consumer = inConsumer;
+ m_PropertyMergeMap.clear();
+}
+
+TSignalConnectionPtr
+CSlideCoreProducer::ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectSlideCreated(inCallback);
+}
+TSignalConnectionPtr CSlideCoreProducer::ConnectBeforeSlideDeleted(
+ const std::function<void(CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectBeforeSlideDeleted(inCallback);
+}
+TSignalConnectionPtr
+CSlideCoreProducer::ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectSlideDeleted(inCallback);
+}
+TSignalConnectionPtr CSlideCoreProducer::ConnectSlideDerived(
+ const std::function<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> &inCallback)
+{
+ return GetSignalProvider()->ConnectSlideDerived(inCallback);
+}
+TSignalConnectionPtr CSlideCoreProducer::ConnectInstancePropertyValueSet(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectInstancePropertyValueSet(inCallback);
+}
+TSignalConnectionPtr CSlideCoreProducer::ConnectInstancePropertyValueRemoved(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback)
+{
+ return GetSignalProvider()->ConnectInstancePropertyValueRemoved(inCallback);
+}
+TSignalConnectionPtr CSlideCoreProducer::ConnectSlideTimeChanged(
+ const std::function<void(CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectSlideTimeChanged(inCallback);
+}
+
+void CSlideCoreProducer::InitSignaller()
+{
+ m_SlideCoreSignaller = CreateSlideCoreSignaller();
+}
+
+ISlideCoreSignalProvider *CSlideCoreProducer::GetSignalProvider()
+{
+ return dynamic_cast<ISlideCoreSignalProvider *>(m_SlideCoreSignaller.get());
+}
+ISlideCoreSignalSender *CSlideCoreProducer::GetSignalSender()
+{
+ return dynamic_cast<ISlideCoreSignalSender *>(m_SlideCoreSignaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.h b/src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.h
new file mode 100644
index 00000000..57fc26aa
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SlideCoreProducer.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef SLIDECOREPRODUCERH
+#define SLIDECOREPRODUCERH
+#include "UICDMTransactions.h"
+#include "SimpleSlideCore.h"
+#include "UICDMSignals.h"
+
+namespace UICDM {
+struct SlideInstancePropertyKey
+{
+ int m_Slide;
+ int m_Instance;
+ int m_Property;
+ SlideInstancePropertyKey(int slide, int inst, int prop)
+ : m_Slide(slide)
+ , m_Instance(inst)
+ , m_Property(prop)
+ {
+ }
+ SlideInstancePropertyKey()
+ : m_Slide(0)
+ , m_Instance(0)
+ , m_Property(0)
+ {
+ }
+
+ bool operator==(const SlideInstancePropertyKey &inOther) const
+ {
+ return m_Slide == inOther.m_Slide && m_Instance == inOther.m_Instance
+ && m_Property == inOther.m_Property;
+ }
+};
+
+struct SlideInstancePropertyKeyHasher
+{
+ std::size_t operator()(const SlideInstancePropertyKey &inEntry) const
+ {
+ return std::hash<int>()(inEntry.m_Slide) ^ std::hash<int>()(inEntry.m_Instance)
+ ^ std::hash<int>()(inEntry.m_Property);
+ }
+};
+
+typedef std::shared_ptr<IMergeableTransaction<SInternValue>> TSlidePropertyMergeMapEntry;
+typedef std::unordered_map<SlideInstancePropertyKey, TSlidePropertyMergeMapEntry,
+ SlideInstancePropertyKeyHasher>
+ TSlidePropertyMergeMap;
+
+class CSlideCoreProducer : public ISlideCore,
+ public ITransactionProducer,
+ public ISlideCoreSignalProvider
+{
+ Q_DISABLE_COPY(CSlideCoreProducer)
+
+ TTransactionConsumerPtr m_Consumer;
+ TSimpleSlideCorePtr m_Data;
+ TSignalItemPtr m_SlideCoreSignaller;
+ TSlidePropertyMergeMap m_PropertyMergeMap;
+
+public:
+ CSlideCoreProducer(TStringTablePtr inStrTable)
+ : m_Data(new CSimpleSlideCore(inStrTable))
+ {
+ InitSignaller();
+ }
+
+ IStringTable &GetStringTable() const override { return m_Data->GetStringTable(); }
+ TStringTablePtr GetStringTablePtr() const override { return m_Data->GetStringTablePtr(); }
+
+ TSimpleSlideCorePtr GetTransactionlessSlideCore() { return m_Data; }
+ TSimpleSlideCorePtr GetTransactionlessSlideCore() const { return m_Data; }
+
+ CUICDMSlideHandle CreateSlide(CUICDMInstanceHandle inInstance) override;
+ CUICDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inSlide) const override;
+ CUICDMSlideHandle GetSlideByInstance(CUICDMInstanceHandle inSlide) const override;
+ void DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances) override;
+ void GetSlides(TSlideHandleList &outSlides) const override;
+
+ float GetSlideTime(CUICDMSlideHandle inSlide) const override;
+ void SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime) override;
+
+ void DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent, int inIndex = -1) override;
+ CUICDMSlideHandle GetParentSlide(CUICDMSlideHandle inSlide) const override;
+ void GetChildSlides(CUICDMSlideHandle inSlide, TSlideHandleList &outChildren) const override;
+ int GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const override;
+
+ bool GetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ void SetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+ void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+ bool GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ void GetSpecificInstancePropertyValues(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outValues) override
+ {
+ return m_Data->GetSpecificInstancePropertyValues(inSlide, inInstance, outValues);
+ }
+ bool ContainsProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) const override;
+ void GetSlidePropertyEntries(CUICDMSlideHandle inSlide, TSlideEntryList &outEntries) const override;
+
+ void PushPropertyValueToChildren(CUICDMSlideHandle inParent, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+ void ClearChildrenPropertyValues(CUICDMSlideHandle inParent, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) override;
+ void DeleteAllInstanceEntries(CUICDMInstanceHandle inHandle) override;
+ void DeleteAllPropertyEntries(CUICDMPropertyHandle inHandle) override;
+ void DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties) override;
+
+ void GetIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ TSlideEntryList &outEntries) const override;
+ void PushIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ CUICDMSlideHandle inDestination) override;
+ void CopyProperties(CUICDMSlideHandle inSourceSlide, CUICDMInstanceHandle inSourceInstance,
+ CUICDMSlideHandle inDestSlide, CUICDMInstanceHandle inDestInstance) override;
+
+ bool IsSlide(CUICDMSlideHandle inSlide) const override;
+
+ bool HandleValid(int inHandle) const override;
+
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+
+ //===================================================================
+ // Signals
+ //===================================================================
+
+ virtual TSignalConnectionPtr
+ ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectBeforeSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectSlideDerived(
+ const std::function<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> &inCallback) override;
+ TSignalConnectionPtr ConnectInstancePropertyValueSet(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback) override;
+ TSignalConnectionPtr ConnectInstancePropertyValueRemoved(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback) override;
+ virtual TSignalConnectionPtr
+ ConnectSlideTimeChanged(const std::function<void(CUICDMSlideHandle)> &inCallback) override;
+
+private:
+ inline void DoForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue);
+ void InitSignaller();
+ ISlideCoreSignalProvider *GetSignalProvider();
+ ISlideCoreSignalSender *GetSignalSender();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.cpp b/src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.cpp
new file mode 100644
index 00000000..b9e8aae1
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "SlideGraphCoreProducer.h"
+#include "HandleSystemTransactions.h"
+#include "VectorTransactions.h"
+#include "SignalsImpl.h"
+using namespace std;
+
+namespace UICDM {
+
+CUICDMSlideGraphHandle CSlideGraphCoreProducer::CreateSlideGraph(CUICDMSlideHandle inRoot)
+{
+ CUICDMSlideGraphHandle retval(m_Data->CreateSlideGraph(inRoot));
+ CREATE_HANDLE_CREATE_TRANSACTION(m_Consumer, retval, m_Data->m_Objects);
+ GetSignalSender()->SendGraphCreated(retval, inRoot);
+ return retval;
+}
+
+CUICDMSlideHandle CSlideGraphCoreProducer::GetGraphRoot(CUICDMSlideGraphHandle inGraph) const
+{
+ return m_Data->GetGraphRoot(inGraph);
+}
+
+CUICDMSlideGraphHandle CSlideGraphCoreProducer::GetSlideGraph(CUICDMSlideHandle inSlide) const
+{
+ return m_Data->GetSlideGraph(inSlide);
+}
+
+void CSlideGraphCoreProducer::GetSlideGraphs(TSlideGraphHandleList &outGraphs) const
+{
+ return m_Data->GetSlideGraphs(outGraphs);
+}
+
+struct DissocateAllInstanceTrans : public ITransaction
+{
+ std::shared_ptr<CSimpleSlideGraphCore> m_Graph;
+ CUICDMSlideGraphHandle m_Handle;
+ TSlideInstancePairList m_Instances;
+ DissocateAllInstanceTrans(const char *inFile, int inLine,
+ std::shared_ptr<CSimpleSlideGraphCore> inGraph,
+ CUICDMSlideGraphHandle inHandle)
+ : ITransaction(inFile, inLine)
+ , m_Graph(inGraph)
+ , m_Handle(inHandle)
+ {
+ inGraph->GetAssociatedInstances(m_Handle, m_Instances);
+ }
+ void Do() override
+ {
+ for (size_t idx = 0, end = m_Instances.size(); idx < end; ++idx)
+ m_Graph->DissociateInstance(m_Instances[idx].second);
+ }
+ void Undo() override
+ {
+ for (size_t idx = 0, end = m_Instances.size(); idx < end; ++idx)
+ m_Graph->AssociateInstance(m_Handle, m_Instances[idx].first, m_Instances[idx].second);
+ }
+};
+
+void CSlideGraphCoreProducer::DeleteSlideGraph(CUICDMSlideGraphHandle inHandle)
+{
+ SSlideGraph *theGraph = CSimpleSlideGraphCore::GetSlideGraphNF(inHandle, m_Data->m_Objects);
+ CUICDMSlideHandle theRootSlide(theGraph->m_Root);
+ if (m_Consumer)
+ m_Consumer->OnTransaction(
+ make_shared<DissocateAllInstanceTrans>(__FILE__, __LINE__, m_Data, inHandle));
+ CREATE_HANDLE_DELETE_TRANSACTION(m_Consumer, inHandle, m_Data->m_Objects);
+ m_Data->DeleteSlideGraph(inHandle);
+ GetSignalSender()->SendGraphDeleted(inHandle, theRootSlide);
+}
+
+struct SInstanceAssociateTrans : public ITransaction
+{
+ std::shared_ptr<CSimpleSlideGraphCore> m_Graph;
+ CUICDMSlideGraphHandle m_GraphHandle;
+ CUICDMSlideHandle m_Slide;
+ CUICDMInstanceHandle m_Instance;
+ bool m_InsertOnDo;
+ SInstanceAssociateTrans(const char *inFile, int inLine,
+ std::shared_ptr<CSimpleSlideGraphCore> inGraph,
+ CUICDMSlideGraphHandle inGraphHandle, CUICDMSlideHandle inSlideHandle,
+ CUICDMInstanceHandle inInstance, bool inInsertOnDo)
+ : ITransaction(inFile, inLine)
+ , m_Graph(inGraph)
+ , m_GraphHandle(inGraphHandle)
+ , m_Slide(inSlideHandle)
+ , m_Instance(inInstance)
+ , m_InsertOnDo(inInsertOnDo)
+ {
+ }
+ void Insert() { m_Graph->AssociateInstance(m_GraphHandle, m_Slide, m_Instance); }
+ void Remove() { m_Graph->DissociateInstance(m_Instance); }
+
+ void Do() override
+ {
+ if (m_InsertOnDo)
+ Insert();
+ else
+ Remove();
+ }
+ void Undo() override
+ {
+ if (m_InsertOnDo)
+ Remove();
+ else
+ Insert();
+ }
+};
+
+void CSlideGraphCoreProducer::AssociateInstance(CUICDMSlideGraphHandle inSlideGraph,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+{
+ m_Data->AssociateInstance(inSlideGraph, inSlide, inInstance);
+ if (m_Consumer)
+ m_Consumer->OnTransaction(make_shared<SInstanceAssociateTrans>(
+ __FILE__, __LINE__, m_Data, inSlideGraph, inSlide, inInstance, true));
+
+ GetSignalSender()->SendInstanceAssociated(inSlideGraph, inSlide, inInstance);
+}
+void CSlideGraphCoreProducer::GetAssociatedInstances(CUICDMSlideGraphHandle inSlideGraph,
+ TSlideInstancePairList &outAssociations) const
+{
+ m_Data->GetAssociatedInstances(inSlideGraph, outAssociations);
+}
+
+TGraphSlidePair CSlideGraphCoreProducer::GetAssociatedGraph(CUICDMInstanceHandle inInstance) const
+{
+ return m_Data->GetAssociatedGraph(inInstance);
+}
+
+void CSlideGraphCoreProducer::DissociateInstance(CUICDMInstanceHandle inInstance)
+{
+ TGraphSlidePair theAssociatedGraph(m_Data->GetAssociatedGraph(inInstance));
+
+ if (theAssociatedGraph.first.Valid()) {
+ m_Data->DissociateInstance(inInstance);
+ if (m_Consumer)
+ m_Consumer->OnTransaction(make_shared<SInstanceAssociateTrans>(
+ __FILE__, __LINE__, m_Data, theAssociatedGraph.first, theAssociatedGraph.second,
+ inInstance, false));
+ GetSignalSender()->SendInstanceDissociated(theAssociatedGraph.first,
+ theAssociatedGraph.second, inInstance);
+ }
+}
+
+void CSlideGraphCoreProducer::SetGraphActiveSlide(CUICDMSlideGraphHandle inGraph,
+ CUICDMSlideHandle inSlide)
+{
+ if (m_Consumer) {
+ CUICDMSlideHandle current = m_Data->GetGraphActiveSlide(inGraph);
+ TTransactionPtr theTransaction(CREATE_GENERIC_TRANSACTION(
+ bind(&CSimpleSlideGraphCore::SetGraphActiveSlide, m_Data, inGraph, inSlide),
+ bind(&CSimpleSlideGraphCore::SetGraphActiveSlide, m_Data, inGraph, current)));
+ m_Consumer->OnTransaction(theTransaction);
+ }
+ m_Data->SetGraphActiveSlide(inGraph, inSlide);
+ GetSignalSender()->SendGraphActiveSlide(inGraph, inSlide);
+}
+
+CUICDMSlideHandle CSlideGraphCoreProducer::GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const
+{
+ return m_Data->GetGraphActiveSlide(inGraph);
+}
+
+bool CSlideGraphCoreProducer::HandleValid(int inHandle) const
+{
+ return m_Data->HandleValid(inHandle);
+}
+
+void CSlideGraphCoreProducer::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_Consumer = inConsumer;
+}
+
+TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphCreated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectGraphCreated(inCallback);
+}
+TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphDeleted(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectGraphDeleted(inCallback);
+}
+TSignalConnectionPtr CSlideGraphCoreProducer::ConnectInstanceAssociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback)
+{
+ return GetSignalProvider()->ConnectInstanceAssociated(inCallback);
+}
+TSignalConnectionPtr CSlideGraphCoreProducer::ConnectInstanceDissociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback)
+{
+ return GetSignalProvider()->ConnectInstanceDissociated(inCallback);
+}
+TSignalConnectionPtr CSlideGraphCoreProducer::ConnectGraphActiveSlide(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback)
+{
+ return GetSignalProvider()->ConnectGraphActiveSlide(inCallback);
+}
+
+void CSlideGraphCoreProducer::InitSignaller()
+{
+ m_Signaller = CreateSlideGraphCoreSignaller();
+}
+
+ISlideGraphCoreSignalProvider *CSlideGraphCoreProducer::GetSignalProvider()
+{
+ return dynamic_cast<ISlideGraphCoreSignalProvider *>(m_Signaller.get());
+}
+
+ISlideGraphCoreSignalSender *CSlideGraphCoreProducer::GetSignalSender()
+{
+ return dynamic_cast<ISlideGraphCoreSignalSender *>(m_Signaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.h b/src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.h
new file mode 100644
index 00000000..e6056d27
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/Cores/SlideGraphCoreProducer.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef SLIDEGRAPHCOREPRODUCERH
+#define SLIDEGRAPHCOREPRODUCERH
+#include "SimpleSlideGraphCore.h"
+#include "UICDMTransactions.h"
+#include "UICDMSignals.h"
+
+namespace UICDM {
+class CSlideGraphCoreProducer : public ISlideGraphCore,
+ public ITransactionProducer,
+ public ISlideGraphCoreSignalProvider
+{
+ Q_DISABLE_COPY(CSlideGraphCoreProducer)
+
+ TSimpleSlideGraphCorePtr m_Data;
+ TTransactionConsumerPtr m_Consumer;
+ TSignalItemPtr m_Signaller;
+
+public:
+ CSlideGraphCoreProducer(TStringTablePtr strTable = TStringTablePtr())
+ : m_Data(new CSimpleSlideGraphCore(strTable))
+ {
+ InitSignaller();
+ }
+ TSimpleSlideGraphCorePtr GetTransactionlessSlideGraphCore() { return m_Data; }
+ TSimpleSlideGraphCorePtr GetTransactionlessSlideGraphCore() const { return m_Data; }
+
+ CUICDMSlideGraphHandle CreateSlideGraph(CUICDMSlideHandle inRoot) override;
+ CUICDMSlideHandle GetGraphRoot(CUICDMSlideGraphHandle inGraph) const override;
+ CUICDMSlideGraphHandle GetSlideGraph(CUICDMSlideHandle inSlide) const override;
+ void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const override;
+ void DeleteSlideGraph(CUICDMSlideGraphHandle inHandle) override;
+
+ void AssociateInstance(CUICDMSlideGraphHandle inSlideGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) override;
+ void GetAssociatedInstances(CUICDMSlideGraphHandle inSlideGraph,
+ TSlideInstancePairList &outAssociations) const override;
+ TGraphSlidePair GetAssociatedGraph(CUICDMInstanceHandle inInstance) const override;
+ void DissociateInstance(CUICDMInstanceHandle inInstance) override;
+
+ void SetGraphActiveSlide(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override;
+ CUICDMSlideHandle GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const override;
+
+ bool HandleValid(int inHandle) const override;
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+
+ //===================================================================
+ // Signals
+ //===================================================================
+ TSignalConnectionPtr ConnectGraphCreated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectGraphDeleted(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override;
+ TSignalConnectionPtr ConnectInstanceAssociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override;
+ TSignalConnectionPtr ConnectInstanceDissociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override;
+ TSignalConnectionPtr ConnectGraphActiveSlide(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override;
+
+private:
+ void InitSignaller();
+ ISlideGraphCoreSignalProvider *GetSignalProvider();
+ ISlideGraphCoreSignalSender *GetSignalSender();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/HandleSystemBase.h b/src/Authoring/UICDM/Systems/HandleSystemBase.h
new file mode 100644
index 00000000..01fb031a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/HandleSystemBase.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef HANDLESYSTEMIMPLH
+#define HANDLESYSTEMIMPLH
+
+#include <unordered_map>
+
+namespace UICDM {
+
+class CHandleObject
+{
+public:
+ // Type of CHandleObject
+ // Each subclass needs to specify what type it is
+ // This is used to avoid dynamic_cast (RTTI) which is expensive
+ enum EHandleObjectType {
+ EHandleObjectTypeUnknown = 0,
+ EHandleObjectTypeCDataModelInstance,
+ EHandleObjectTypeCDataModelPropertyDefinitionObject,
+ EHandleObjectTypeSAnimationTrack,
+ EHandleObjectTypeSKeyframe,
+ EHandleObjectTypeSSlide,
+ EHandleObjectTypeSSlideGraph,
+ EHandleObjectTypeAction,
+ EHandleObjectTypeActionHandlerArgument,
+ EHandleObjectTypeCustomProperty,
+ EHandleObjectTypeEvent,
+ EHandleObjectTypeCustomHandler,
+ EHandleObjectTypeHandlerParam,
+ EHandleObjectTypeEnd,
+ };
+
+ CHandleObject(int inHandle = 0)
+ : m_Handle(inHandle)
+ {
+ }
+ virtual ~CHandleObject() {}
+
+ virtual EHandleObjectType GetType() = 0;
+
+ int m_Handle;
+
+private: //noncopyable
+ CHandleObject(const CHandleObject&) = delete;
+ CHandleObject& operator=(const CHandleObject&) = delete;
+
+};
+
+typedef std::shared_ptr<CHandleObject> THandleObjectPtr;
+
+// Note that maps don't need to copy their objects.
+typedef std::unordered_map<int, THandleObjectPtr> THandleObjectMap;
+typedef std::pair<int, THandleObjectPtr> THandleObjectPair;
+
+class IHandleBase
+{
+public:
+ /**
+ * Check whether a given handle exists
+ */
+ virtual bool HandleValid(int inHandle) const = 0;
+};
+
+struct CHandleBase : public IHandleBase
+{
+ THandleObjectMap m_Objects;
+ int m_NextId;
+
+ CHandleBase()
+ : m_NextId(1)
+ {
+ }
+ CHandleBase(const CHandleBase &inOther)
+ : m_Objects(inOther.m_Objects)
+ , m_NextId(inOther.m_NextId)
+ {
+ }
+
+ CHandleBase &operator=(const CHandleBase &inOther)
+ {
+ m_Objects = inOther.m_Objects;
+ m_NextId = inOther.m_NextId;
+ return *this;
+ }
+
+ // IHandleBase
+ bool HandleValid(int inHandle) const override
+ {
+ return m_Objects.find(inHandle) != m_Objects.end();
+ }
+
+ template <typename T>
+ static inline bool HandleObjectValid(int inHandle, const THandleObjectMap &inMap)
+ {
+ THandleObjectMap::const_iterator theIter = inMap.find(inHandle);
+ if (theIter != inMap.end()) {
+ if (theIter->second->GetType() == T::s_Type)
+ return true;
+ }
+ return false;
+ }
+
+ template <typename T>
+ static inline const T *GetHandleObject(int inHandle, const THandleObjectMap &inMap)
+ {
+ THandleObjectMap::const_iterator theIter = inMap.find(inHandle);
+ if (theIter != inMap.end()) {
+ if (theIter->second->GetType() == T::s_Type)
+ return static_cast<const T *>(theIter->second.get());
+ }
+ return NULL;
+ }
+
+ template <typename ObjectType, typename HandleType>
+ static inline void MaybeAddObject(const std::pair<int, THandleObjectPtr> &inItem,
+ std::vector<HandleType> &outHandles)
+ {
+ if (inItem.second->GetType() == ObjectType::s_Type)
+ outHandles.push_back(HandleType(inItem.first));
+ }
+
+ static void EraseHandle(int inHandle, THandleObjectMap &inObjects)
+ {
+ THandleObjectMap::iterator theFind = inObjects.find(inHandle);
+ if (theFind != inObjects.end())
+ inObjects.erase(theFind);
+ }
+
+ // Return the next unused id. There are no guarantees whether positive or negative; what this
+ // will
+ // guarantee is that it isn't currently used in the object map and it is non-zero.
+ int GetNextId()
+ {
+ do {
+ ++m_NextId;
+ } while (m_Objects.find(m_NextId) != m_Objects.end());
+ return m_NextId;
+ }
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/HandleSystemTransactions.h b/src/Authoring/UICDM/Systems/HandleSystemTransactions.h
new file mode 100644
index 00000000..5d0c6a3b
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/HandleSystemTransactions.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef HANDLESYSTEMTRANSACTIONSH
+#define HANDLESYSTEMTRANSACTIONSH
+#include "HandleSystemBase.h"
+#include "UICDMTransactions.h"
+
+namespace UICDM {
+inline void InsertItemInMap(THandleObjectMap &inObjects,
+ const std::pair<int, THandleObjectPtr> &inItem)
+{
+ inObjects.insert(inItem);
+}
+inline void HandleCreateTransaction(const char *inFile, int inLine, int inHandle,
+ THandleObjectMap &inObjects,
+ TTransactionConsumerPtr &inConsumer)
+{
+ std::pair<int, THandleObjectPtr> theEntry = *inObjects.find(inHandle);
+ std::function<void()> doOp(std::bind(InsertItemInMap, std::ref(inObjects), theEntry));
+ std::function<void()> undoOp(
+ std::bind(CHandleBase::EraseHandle, inHandle, std::ref(inObjects)));
+ TTransactionPtr theTransaction(DoCreateGenericTransaction(inFile, inLine, doOp, undoOp));
+ inConsumer->OnTransaction(theTransaction);
+}
+
+inline void HandleDeleteTransaction(const char *inFile, int inLine, int inHandle,
+ THandleObjectMap &inObjects,
+ TTransactionConsumerPtr &inConsumer)
+{
+ using namespace std;
+ pair<int, THandleObjectPtr> theEntry = *inObjects.find(inHandle);
+ TTransactionPtr theTransaction(DoCreateGenericTransaction(
+ inFile, inLine, std::bind(CHandleBase::EraseHandle, inHandle, std::ref(inObjects)),
+ std::bind(InsertItemInMap, std::ref(inObjects), theEntry)));
+ inConsumer->OnTransaction(theTransaction);
+}
+
+inline void DoCreateHandleCreateTransaction(const char *inFile, int inLine,
+ TTransactionConsumerPtr inConsumer, int inHandle,
+ THandleObjectMap &inObjects)
+{
+ RunWithConsumer(inConsumer, std::bind(HandleCreateTransaction, inFile, inLine, inHandle,
+ std::ref(inObjects), std::placeholders::_1));
+}
+
+#define CREATE_HANDLE_CREATE_TRANSACTION(inConsumer, inHandle, inObjects) \
+ DoCreateHandleCreateTransaction(__FILE__, __LINE__, inConsumer, inHandle, inObjects);
+
+inline void DoCreateHandleDeleteTransaction(const char *inFile, int inLine,
+ TTransactionConsumerPtr inConsumer, int inHandle,
+ THandleObjectMap &inObjects)
+{
+ RunWithConsumer(inConsumer, std::bind(HandleDeleteTransaction, inFile, inLine, inHandle,
+ std::ref(inObjects), std::placeholders::_1));
+}
+
+#define CREATE_HANDLE_DELETE_TRANSACTION(inConsumer, inHandle, inObjects) \
+ DoCreateHandleDeleteTransaction(__FILE__, __LINE__, inConsumer, inHandle, inObjects);
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/SignalsImpl.cpp b/src/Authoring/UICDM/Systems/SignalsImpl.cpp
new file mode 100644
index 00000000..831196f4
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/SignalsImpl.cpp
@@ -0,0 +1,1527 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#ifdef WIN32
+#pragma warning(disable : 4103 4512 4503)
+#endif
+#include "SignalsImpl.h"
+#include <boost/signal.hpp>
+#include <boost/signals/connection.hpp>
+
+using namespace boost;
+
+using namespace std;
+using namespace boost::BOOST_SIGNALS_NAMESPACE;
+
+namespace {
+bool g_UICDMSignalsEnabled = true;
+
+#define CHECK_SIGNALS_ENABLED() \
+ { \
+ if (g_UICDMSignalsEnabled == false) \
+ return; \
+ }
+}
+
+namespace UICDM {
+void SetUICDMSignalsEnabled(bool inEnabled)
+{
+ g_UICDMSignalsEnabled = inEnabled;
+}
+// Defaults to true
+bool AreUICDMSignalsEnabled()
+{
+ return g_UICDMSignalsEnabled;
+}
+struct SBoostSignalConnection : public ISignalConnection
+{
+ Q_DISABLE_COPY(SBoostSignalConnection)
+
+ boost::BOOST_SIGNALS_NAMESPACE::scoped_connection m_connection;
+ SBoostSignalConnection(const boost::BOOST_SIGNALS_NAMESPACE::connection &inConnection)
+ : m_connection(inConnection)
+ {
+ }
+};
+
+#define CONNECT(x) TSignalConnectionPtr(new SBoostSignalConnection(x))
+#define CONNECT_SIGNAL(x) CONNECT(x.connect(inCallback))
+
+class CPropertyCoreSignaller : public IInstancePropertyCoreSignalProvider,
+ public IInstancePropertyCoreSignalSender
+{
+ boost::signal<void(CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue)> m_PropertySignal;
+
+public:
+ TSignalConnectionPtr ConnectInstancePropertyValue(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue &)>
+ &inCallback) override
+ {
+ return CONNECT(m_PropertySignal.connect(inCallback));
+ }
+ void SignalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertySignal(inInstance, inProperty, inValue);
+ }
+};
+
+TSignalItemPtr CreatePropertyCoreSignaller()
+{
+ return TSignalItemPtr(
+ static_cast<IInstancePropertyCoreSignalProvider *>(new CPropertyCoreSignaller()));
+}
+
+class CDataCoreSignaller : public IDataCoreSignalProvider, public IDataCoreSignalSender
+{
+ boost::signal<void(CUICDMInstanceHandle)> m_InstanceCreated;
+ boost::signal<void(CUICDMInstanceHandle)> m_BeforeInstanceDeleted;
+ boost::signal<void(CUICDMInstanceHandle)> m_InstanceDeleted;
+ boost::signal<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> m_InstanceDerived;
+ boost::signal<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> m_InstanceParentRemoved;
+ boost::signal<void(CUICDMInstanceHandle, CUICDMPropertyHandle, TCharPtr, DataModelDataType::Value)>
+ m_PropertyAdded;
+ boost::signal<void(CUICDMInstanceHandle, CUICDMPropertyHandle, TCharPtr, DataModelDataType::Value)>
+ m_PropertyRemoved;
+
+public:
+ virtual TSignalConnectionPtr
+ ConnectInstanceCreated(const std::function<void(CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT(m_InstanceCreated.connect(inCallback));
+ }
+ virtual TSignalConnectionPtr
+ ConnectBeforeInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT(m_BeforeInstanceDeleted.connect(inCallback));
+ }
+ virtual TSignalConnectionPtr
+ ConnectInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT(m_InstanceDeleted.connect(inCallback));
+ }
+ TSignalConnectionPtr ConnectInstanceDerived(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT(m_InstanceDerived.connect(inCallback));
+ }
+ TSignalConnectionPtr ConnectInstanceParentRemoved(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT(m_InstanceParentRemoved.connect(inCallback));
+ }
+ virtual TSignalConnectionPtr
+ ConnectPropertyAdded(const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle,
+ TCharPtr, DataModelDataType::Value)> &inCallback) override
+ {
+ return CONNECT(m_PropertyAdded.connect(inCallback));
+ }
+ virtual TSignalConnectionPtr
+ ConnectPropertyRemoved(const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle,
+ TCharPtr, DataModelDataType::Value)> &inCallback) override
+ {
+ return CONNECT(m_PropertyRemoved.connect(inCallback));
+ }
+
+ void SignalInstanceCreated(CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceCreated(inInstance);
+ }
+ void SignalBeforeInstanceDeleted(CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_BeforeInstanceDeleted(inInstance);
+ }
+ void SignalInstanceDeleted(CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceDeleted(inInstance);
+ }
+ void SignalInstanceDerived(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceDerived(inInstance, inParent);
+ }
+ void SignalInstanceParentRemoved(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceParentRemoved(inInstance, inParent);
+ }
+ void SignalPropertyAdded(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, TCharPtr inName,
+ DataModelDataType::Value inDataType) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertyAdded(inInstance, inProperty, inName, inDataType);
+ }
+ void SignalPropertyRemoved(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, TCharPtr inName,
+ DataModelDataType::Value inDataType) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertyRemoved(inInstance, inProperty, inName, inDataType);
+ }
+};
+
+TSignalItemPtr CreateDataCoreSignaller()
+{
+ return TSignalItemPtr(static_cast<IDataCoreSignalProvider *>(new CDataCoreSignaller()));
+}
+
+class CSlideCoreSignaller : public ISlideCoreSignalProvider, public ISlideCoreSignalSender
+{
+ boost::signal<void(CUICDMSlideHandle)> m_SlideCreated;
+ boost::signal<void(CUICDMSlideHandle)> m_BeforeSlideDeleted;
+ boost::signal<void(CUICDMSlideHandle)> m_SlideDeleted;
+ boost::signal<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> m_SlideDerived;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue &)>
+ m_InstancePropertyValueSet;
+ boost::signal<SValue(CUICDMSlideHandle, CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)>
+ m_InstancePropertyValueAdded;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue &)>
+ m_InstancePropertyValueRemoved;
+ boost::signal<void(CUICDMSlideHandle)> m_SlideTimeChanged;
+
+public:
+ virtual TSignalConnectionPtr
+ ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideCreated);
+ }
+ virtual TSignalConnectionPtr
+ ConnectBeforeSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_BeforeSlideDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideDeleted);
+ }
+ TSignalConnectionPtr ConnectSlideDerived(
+ const std::function<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideDerived);
+ }
+ TSignalConnectionPtr ConnectInstancePropertyValueSet(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstancePropertyValueSet);
+ }
+ virtual TSignalConnectionPtr ConnectInstancePropertyValueAdded(
+ const std::function<SValue(CUICDMSlideHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, const SValue &)> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_InstancePropertyValueAdded);
+ }
+ TSignalConnectionPtr ConnectInstancePropertyValueRemoved(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstancePropertyValueRemoved);
+ }
+ virtual TSignalConnectionPtr
+ ConnectSlideTimeChanged(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideTimeChanged);
+ }
+
+ void SendSlideCreated(CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideCreated(inSlide);
+ }
+ void SendBeforeSlideDeleted(CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_BeforeSlideDeleted(inSlide);
+ }
+ void SendSlideDeleted(CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideDeleted(inSlide);
+ }
+ void SendSlideDerived(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent,
+ int inIndex) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideDerived(inSlide, inParent, inIndex);
+ }
+ void SendPropertyValueSet(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstancePropertyValueSet(inSlide, inInstance, inProperty, inValue);
+ }
+ virtual SValue SendPropertyValueAdded(CUICDMSlideHandle inSource, CUICDMSlideHandle inDest,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue)
+ {
+ // Signals that return values tend to assert if there aren't
+ // any clients for those signals. Thus we only call them if
+ // there are currently clients connected.
+ // Good luck finding the number of connected items on a boost signal...
+ size_t theNumSlots(m_InstancePropertyValueAdded.num_slots());
+ if (theNumSlots)
+ return m_InstancePropertyValueAdded(inSource, inDest, inInstance, inProperty, inValue);
+ return inValue;
+ }
+ void SendPropertyValueRemoved(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override
+ {
+ m_InstancePropertyValueRemoved(inSlide, inInstance, inProperty, inValue);
+ }
+ void SendSlideTimeChanged(CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideTimeChanged(inSlide);
+ }
+};
+
+TSignalItemPtr CreateSlideCoreSignaller()
+{
+ return TSignalItemPtr(static_cast<ISlideCoreSignalProvider *>(new CSlideCoreSignaller()));
+}
+
+class CSlideGraphCoreSignaller : public ISlideGraphCoreSignalProvider,
+ public ISlideGraphCoreSignalSender
+{
+ boost::signal<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> m_GraphCreated;
+ boost::signal<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> m_GraphDeleted;
+ boost::signal<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ m_InstanceAssociated;
+ boost::signal<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ m_InstanceDissociated;
+ boost::signal<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> m_GraphActiveSlide;
+ boost::signal<void(CUICDMSlideGraphHandle, float)> m_GraphSeconds;
+
+public:
+ TSignalConnectionPtr ConnectGraphCreated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_GraphCreated);
+ }
+ TSignalConnectionPtr ConnectGraphDeleted(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_GraphDeleted);
+ }
+ TSignalConnectionPtr ConnectInstanceAssociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstanceAssociated);
+ }
+ TSignalConnectionPtr ConnectInstanceDissociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstanceDissociated);
+ }
+ TSignalConnectionPtr ConnectGraphActiveSlide(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_GraphActiveSlide);
+ }
+ virtual TSignalConnectionPtr
+ ConnectGraphSeconds(const std::function<void(CUICDMSlideGraphHandle, float)> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_GraphSeconds);
+ }
+
+ void SendGraphCreated(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_GraphCreated(inGraph, inSlide);
+ }
+ void SendGraphDeleted(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_GraphDeleted(inGraph, inSlide);
+ }
+ void SendInstanceAssociated(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceAssociated(inGraph, inSlide, inInstance);
+ }
+ void SendInstanceDissociated(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceDissociated(inGraph, inSlide, inInstance);
+ }
+ void SendGraphActiveSlide(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_GraphActiveSlide(inGraph, inSlide);
+ }
+ virtual void SendGraphSeconds(CUICDMSlideGraphHandle inGraph, float inSeconds)
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_GraphSeconds(inGraph, inSeconds);
+ }
+};
+
+TSignalItemPtr CreateSlideGraphCoreSignaller()
+{
+ return TSignalItemPtr(
+ static_cast<ISlideGraphCoreSignalProvider *>(new CSlideGraphCoreSignaller()));
+}
+
+class CAnimationCoreSignaller : public IAnimationCoreSignalProvider,
+ public IAnimationCoreSignalSender
+{
+ boost::signal<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)>
+ m_AnimationCreated;
+ boost::signal<void(CUICDMAnimationHandle)> m_BeforeAnimationDeleted;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)>
+ m_AnimationDeleted;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)> m_KeyframeInserted;
+ boost::signal<void(CUICDMKeyframeHandle)> m_BeforeKeyframeErased;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)> m_KeyframeErased;
+ boost::signal<void(CUICDMAnimationHandle)> m_BeforeAllKeyframesErased;
+ boost::signal<void(CUICDMKeyframeHandle, const TKeyframe &)> m_KeyframeUpdated;
+ boost::signal<void(CUICDMAnimationHandle, bool)> m_FirstKeyframeDynamic;
+
+public:
+ TSignalConnectionPtr ConnectAnimationCreated(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_AnimationCreated);
+ }
+ virtual TSignalConnectionPtr
+ ConnectBeforeAnimationDeleted(const std::function<void(CUICDMAnimationHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_BeforeAnimationDeleted);
+ }
+ TSignalConnectionPtr ConnectAnimationDeleted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_AnimationDeleted);
+ }
+ TSignalConnectionPtr ConnectKeyframeInserted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_KeyframeInserted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectBeforeKeyframeErased(const std::function<void(CUICDMKeyframeHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_BeforeKeyframeErased);
+ }
+ TSignalConnectionPtr ConnectKeyframeErased(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_KeyframeErased);
+ }
+ virtual TSignalConnectionPtr
+ ConnectBeforeAllKeyframesErased(const std::function<void(CUICDMAnimationHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_BeforeAllKeyframesErased);
+ }
+ TSignalConnectionPtr ConnectKeyframeUpdated(
+ const std::function<void(CUICDMKeyframeHandle, const TKeyframe &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_KeyframeUpdated);
+ }
+ TSignalConnectionPtr ConnectFirstKeyframeDynamicSet(
+ const std::function<void(CUICDMAnimationHandle, bool)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_FirstKeyframeDynamic);
+ }
+
+ void SendAnimationCreated(CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_AnimationCreated(inAnimation, inSlide, inInstance, inProperty, inIndex, inAnimationType);
+ }
+ void SendBeforeAnimationDeleted(CUICDMAnimationHandle inAnimation) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_BeforeAnimationDeleted(inAnimation);
+ }
+ void SendAnimationDeleted(CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_AnimationDeleted(inAnimation, inSlide, inInstance, inProperty, inIndex, inAnimationType);
+ }
+ void SendKeyframeInserted(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_KeyframeInserted(inAnimation, inKeyframe, inData);
+ }
+ void SendBeforeKeyframeErased(CUICDMKeyframeHandle inKeyframe) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_BeforeKeyframeErased(inKeyframe);
+ }
+ void SendKeyframeErased(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_KeyframeErased(inAnimation, inKeyframe, inData);
+ }
+ void SendBeforeAllKeyframesErased(CUICDMAnimationHandle inAnimation) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_BeforeAllKeyframesErased(inAnimation);
+ }
+ void SendKeyframeUpdated(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_KeyframeUpdated(inKeyframe, inData);
+ }
+ void SendFirstKeyframeDynamicSet(CUICDMAnimationHandle inAnimation,
+ bool inKeyframeDynamic) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_FirstKeyframeDynamic(inAnimation, inKeyframeDynamic);
+ }
+};
+
+TSignalItemPtr CreateAnimationCoreSignaller()
+{
+ return TSignalItemPtr(
+ static_cast<IAnimationCoreSignalProvider *>(new CAnimationCoreSignaller()));
+}
+
+class CActionCoreSignaller : public IActionCoreSignalProvider, public IActionCoreSignalSender
+{
+ boost::signal<void(CUICDMActionHandle, SObjectRefType &)> m_TriggerObjectSet;
+ boost::signal<void(CUICDMActionHandle, SObjectRefType &)> m_TargetObjectSet;
+ boost::signal<void(CUICDMActionHandle, const wstring &)> m_EventHandleSet;
+ boost::signal<void(CUICDMActionHandle, const wstring &)> m_HandlerHandleSet;
+
+ boost::signal<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &, HandlerArgumentType::Value,
+ DataModelDataType::Value)>
+ m_HandlerArgumentAdded;
+ boost::signal<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &, HandlerArgumentType::Value,
+ DataModelDataType::Value)>
+ m_HandlerArgumentRemoved;
+ boost::signal<void(CUICDMHandlerArgHandle, const SValue &)> m_HandlerArgumentValueSet;
+
+public:
+ TSignalConnectionPtr ConnectTriggerObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_TriggerObjectSet);
+ }
+ TSignalConnectionPtr ConnectTargetObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_TargetObjectSet);
+ }
+ virtual TSignalConnectionPtr
+ ConnectEventSet(const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_EventHandleSet);
+ }
+ virtual TSignalConnectionPtr
+ ConnectHandlerSet(const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_HandlerHandleSet);
+ }
+
+ TSignalConnectionPtr ConnectHandlerArgumentAdded(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_HandlerArgumentAdded);
+ }
+ TSignalConnectionPtr ConnectHandlerArgumentRemoved(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_HandlerArgumentRemoved);
+ }
+ TSignalConnectionPtr ConnectHandlerArgumentValueSet(
+ const std::function<void(CUICDMHandlerArgHandle, const SValue &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_HandlerArgumentValueSet);
+ }
+
+ void SendTriggerObjectSet(CUICDMActionHandle inAction, SObjectRefType &inTriggerObject) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_TriggerObjectSet(inAction, inTriggerObject);
+ }
+ void SendTargetObjectSet(CUICDMActionHandle inAction, SObjectRefType &inTargetObject) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_TargetObjectSet(inAction, inTargetObject);
+ }
+ void SendEventSet(CUICDMActionHandle inAction, const wstring &inEventHandle) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_EventHandleSet(inAction, inEventHandle);
+ }
+ void SendHandlerSet(CUICDMActionHandle inAction, const wstring &inHandlerHandle) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_HandlerHandleSet(inAction, inHandlerHandle);
+ }
+
+ void SendHandlerArgumentAdded(CUICDMActionHandle inAction,
+ CUICDMHandlerArgHandle inHandlerArgument,
+ const TCharStr &inName, HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_HandlerArgumentAdded(inAction, inHandlerArgument, inName, inArgType, inValueType);
+ }
+ void SendHandlerArgumentRemoved(CUICDMActionHandle inAction,
+ CUICDMHandlerArgHandle inHandlerArgument,
+ const TCharStr &inName, HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_HandlerArgumentRemoved(inAction, inHandlerArgument, inName, inArgType, inValueType);
+ }
+ void SendHandlerArgumentValueSet(CUICDMHandlerArgHandle inHandlerArgument,
+ const SValue &inValue) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_HandlerArgumentValueSet(inHandlerArgument, inValue);
+ }
+};
+
+TSignalItemPtr CreateActionCoreSignaller()
+{
+ return TSignalItemPtr(static_cast<IActionCoreSignalProvider *>(new CActionCoreSignaller()));
+}
+
+class CActionSystemSignaller : public IActionSystemSignalProvider, public IActionSystemSignalSender
+{
+ boost::signal<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)> m_ActionCreated;
+ boost::signal<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)> m_ActionDeleted;
+
+public:
+ TSignalConnectionPtr ConnectActionCreated(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ActionCreated);
+ }
+ TSignalConnectionPtr ConnectActionDeleted(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ActionDeleted);
+ }
+
+ void SendActionCreated(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ActionCreated(inAction, inSlide, inOwner);
+ }
+ void SendActionDeleted(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ActionDeleted(inAction, inSlide, inOwner);
+ }
+};
+
+TSignalItemPtr CreateActionSystemSignaller()
+{
+ return TSignalItemPtr(static_cast<IActionSystemSignalProvider *>(new CActionSystemSignaller()));
+}
+
+class CSlideSystemSignaller : public ISlideSystemSignalProvider, public ISlideSystemSignalSender
+{
+ boost::signal<void(CUICDMSlideHandle)> m_MasterCreated;
+ boost::signal<void(CUICDMSlideHandle)> m_MasterDeleted;
+ boost::signal<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> m_SlideCreated;
+ boost::signal<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> m_SlideDeleted;
+ boost::signal<void(CUICDMSlideHandle, int, int)> m_SlideRearranged;
+ boost::signal<void(CUICDMSlideHandle, float)> m_ComponentSeconds;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle)> m_InstanceAssociated;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle)> m_InstanceDissociated;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)> m_PropertyLinked;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)> m_PropertyUnlinked;
+ boost::signal<void(CUICDMSlideHandle, int, CUICDMSlideHandle, CUICDMSlideHandle)> m_ActiveSlide;
+
+ boost::signal<SValue(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue)>
+ m_ValueCreated;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue)>
+ m_ValueDestroyed;
+
+public:
+ virtual TSignalConnectionPtr
+ ConnectMasterCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_MasterCreated);
+ }
+ virtual TSignalConnectionPtr
+ ConnectMasterDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_MasterDeleted);
+ }
+ TSignalConnectionPtr ConnectSlideCreated(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideCreated);
+ }
+ TSignalConnectionPtr ConnectSlideDeleted(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectSlideRearranged(const std::function<void(CUICDMSlideHandle, int, int)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideRearranged);
+ }
+ virtual TSignalConnectionPtr
+ ConnectComponentSeconds(const std::function<void(CUICDMSlideHandle, float)> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_ComponentSeconds);
+ }
+ TSignalConnectionPtr ConnectInstanceAssociated(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstanceAssociated);
+ }
+ TSignalConnectionPtr ConnectInstanceDissociated(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstanceDissociated);
+ }
+ TSignalConnectionPtr ConnectPropertyLinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_PropertyLinked);
+ }
+ TSignalConnectionPtr ConnectPropertyUnlinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_PropertyUnlinked);
+ }
+ TSignalConnectionPtr ConnectActiveSlide(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle, CUICDMSlideHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ActiveSlide);
+ }
+ virtual TSignalConnectionPtr ConnectPropertyValueCreated(
+ const std::function<SValue(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_ValueCreated);
+ }
+ virtual TSignalConnectionPtr ConnectPropertyValueDestroyed(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_ValueDestroyed);
+ }
+
+ void SendMasterCreated(CUICDMSlideHandle inMaster) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_MasterCreated(inMaster);
+ }
+ void SendMasterDeleted(CUICDMSlideHandle inMaster) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_MasterDeleted(inMaster);
+ }
+ void SendSlideCreated(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideCreated(inMaster, inIndex, inSlide);
+ }
+ void SendSlideDeleted(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideDeleted(inMaster, inIndex, inSlide);
+ }
+ void SendSlideRearranged(CUICDMSlideHandle inMaster, int inOldIndex, int inNewIndex) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideRearranged(inMaster, inOldIndex, inNewIndex);
+ }
+ virtual void SendComponentSeconds(CUICDMSlideHandle inMaster, float inSeconds)
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ComponentSeconds(inMaster, inSeconds);
+ }
+ void SendInstanceAssociated(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceAssociated(inMaster, inInstance);
+ }
+ void SendInstanceDissociated(CUICDMSlideHandle inMaster,
+ CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceDissociated(inMaster, inInstance);
+ }
+ void SendPropertyLinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertyLinked(inMaster, inInstance, inProperty);
+ }
+ void SendPropertyUnlinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertyUnlinked(inMaster, inInstance, inProperty);
+ }
+ void SendActiveSlide(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inOldSlide, CUICDMSlideHandle inNewSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ActiveSlide(inMaster, inIndex, inOldSlide, inNewSlide);
+ }
+
+ virtual SValue SendPropertyValueCreated(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue)
+ {
+ size_t theNumSlots(m_ValueCreated.num_slots());
+ if (theNumSlots)
+ return m_ValueCreated(inSlide, inInstance, inProperty, inValue);
+ return inValue;
+ }
+ virtual void SendPropertyValueDestroyed(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue)
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ValueDestroyed(inSlide, inInstance, inProperty, inValue);
+ }
+};
+
+TSignalItemPtr CreateSlideSystemSignaller()
+{
+ return TSignalItemPtr(static_cast<ISlideSystemSignalProvider *>(new CSlideSystemSignaller()));
+}
+
+class CCustomPropCoreSignaller : public ICustomPropCoreSignalProvider,
+ public ICustomPropCoreSignalSender
+{
+ boost::signal<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> m_CustomPropertyCreated;
+ boost::signal<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> m_CustomPropertyDeleted;
+ boost::signal<void(CUICDMPropertyHandle)> m_CustomPropertyModified;
+ boost::signal<void(CUICDMEventHandle, CUICDMInstanceHandle)> m_CustomEventCreated;
+ boost::signal<void(CUICDMEventHandle, CUICDMInstanceHandle)> m_CustomEventDeleted;
+ boost::signal<void(CUICDMEventHandle)> m_CustomEventModified;
+ boost::signal<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> m_CustomHandlerCreated;
+ boost::signal<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> m_CustomHandlerDeleted;
+ boost::signal<void(CUICDMHandlerHandle)> m_CustomHandlerModified;
+ boost::signal<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> m_CustomHandlerParamCreated;
+ boost::signal<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> m_CustomHandlerParamDeleted;
+ boost::signal<void(CUICDMHandlerParamHandle)> m_CustomHandlerParamModified;
+ boost::signal<void(CUICDMInstanceHandle, const TCharStr &)> m_CustomReferencesModified;
+
+public:
+ TSignalConnectionPtr ConnectCustomPropertyCreated(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomPropertyCreated);
+ }
+ TSignalConnectionPtr ConnectCustomPropertyDeleted(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomPropertyDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectCustomPropertyModified(const std::function<void(CUICDMPropertyHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomPropertyModified);
+ }
+ TSignalConnectionPtr ConnectCustomEventCreated(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomEventCreated);
+ }
+ TSignalConnectionPtr ConnectCustomEventDeleted(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomEventDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectCustomEventModified(const std::function<void(CUICDMEventHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomEventModified);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerCreated(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerCreated);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerDeleted(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectCustomHandlerModified(const std::function<void(CUICDMHandlerHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerModified);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerParamCreated(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerParamCreated);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerParamDeleted(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerParamDeleted);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerParamModified(
+ const std::function<void(CUICDMHandlerParamHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerParamModified);
+ }
+ TSignalConnectionPtr ConnectCustomReferencesModified(
+ const std::function<void(CUICDMInstanceHandle, const TCharStr &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomReferencesModified);
+ }
+
+ void SendCustomPropertyCreated(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomPropertyCreated(inProp, inOwner);
+ }
+ void SendCustomPropertyDeleted(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomPropertyDeleted(inProp, inOwner);
+ }
+ void SendCustomPropertyModified(CUICDMPropertyHandle inProp) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomPropertyModified(inProp);
+ }
+ void SendCustomEventCreated(CUICDMEventHandle inEvent, CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomEventCreated(inEvent, inOwner);
+ }
+ void SendCustomEventDeleted(CUICDMEventHandle inEvent, CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomEventDeleted(inEvent, inOwner);
+ }
+ void SendCustomEventModified(CUICDMEventHandle inEvent) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomEventModified(inEvent);
+ }
+ void SendCustomHandlerCreated(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerCreated(inHandler, inOwner);
+ }
+ void SendCustomHandlerDeleted(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerDeleted(inHandler, inOwner);
+ }
+ void SendCustomHandlerModified(CUICDMHandlerHandle inHandler) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerModified(inHandler);
+ }
+ void SendCustomHandlerParamCreated(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerParamCreated(inParameter, inHandler);
+ }
+ void SendCustomHandlerParamDeleted(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerParamDeleted(inParameter, inHandler);
+ }
+ void SendCustomHandlerParamModified(CUICDMHandlerParamHandle inParameter) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerParamModified(inParameter);
+ }
+ void SendCustomReferencesModified(CUICDMInstanceHandle inOwner,
+ const TCharStr &inString) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomReferencesModified(inOwner, inString);
+ }
+};
+
+TSignalItemPtr CreateCustomPropCoreSignaller()
+{
+ return TSignalItemPtr(
+ static_cast<ICustomPropCoreSignalProvider *>(new CCustomPropCoreSignaller()));
+}
+
+class CStudioFullSystemSignaller : public IStudioFullSystemSignalProvider,
+ public IStudioFullSystemSignalSender
+{
+ boost::signal<void()> m_ChangeSetBegin;
+ boost::signal<void()> m_ChangeSetEnd;
+ boost::signal<void()> m_AnimationBegin;
+ boost::signal<void()> m_AnimationEnd;
+ boost::signal<void(CUICDMSlideHandle)> m_SlideCreated;
+ boost::signal<void(CUICDMSlideHandle)> m_SlideDeleted;
+ boost::signal<void(CUICDMSlideHandle, int, int)> m_SlideRearranged;
+ boost::signal<void(CUICDMSlideHandle)> m_ComponentSeconds;
+ boost::signal<void(CUICDMSlideHandle)> m_BeginComponentSeconds;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)> m_PropertyLinked;
+ boost::signal<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)> m_PropertyUnlinked;
+ boost::signal<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> m_ActiveSlide;
+ boost::signal<void(CUICDMInstanceHandle)> m_InstanceCreated;
+ boost::signal<void(CUICDMInstanceHandle)> m_InstanceDeleted;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ m_AnimationCreated;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ m_AnimationDeleted;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMKeyframeHandle)> m_KeyframeInserted;
+ boost::signal<void(CUICDMAnimationHandle, CUICDMKeyframeHandle)> m_KeyframeErased;
+ boost::signal<void(CUICDMKeyframeHandle)> m_KeyframeUpdated;
+ boost::signal<void(CUICDMAnimationHandle, bool)> m_ConnectFirstKeyframeDynamicSet;
+ boost::signal<void(CUICDMInstanceHandle, CUICDMPropertyHandle)> m_InstancePropertyValue;
+ boost::signal<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)> m_ActionCreated;
+ boost::signal<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)> m_ActionDeleted;
+ boost::signal<void(CUICDMActionHandle)> m_TriggerObjectSet;
+ boost::signal<void(CUICDMActionHandle)> m_TargetObjectSet;
+ boost::signal<void(CUICDMActionHandle)> m_EventHandleSet;
+ boost::signal<void(CUICDMActionHandle)> m_HandlerHandleSet;
+ boost::signal<void(CUICDMHandlerArgHandle)> m_HandlerArgumentValueSet;
+ boost::signal<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> m_CustomPropertyCreated;
+ boost::signal<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> m_CustomPropertyDeleted;
+ boost::signal<void(CUICDMPropertyHandle)> m_CustomPropertyModified;
+ boost::signal<void(CUICDMEventHandle, CUICDMInstanceHandle)> m_CustomEventCreated;
+ boost::signal<void(CUICDMEventHandle, CUICDMInstanceHandle)> m_CustomEventDeleted;
+ boost::signal<void(CUICDMEventHandle)> m_CustomEventModified;
+ boost::signal<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> m_CustomHandlerCreated;
+ boost::signal<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> m_CustomHandlerDeleted;
+ boost::signal<void(CUICDMHandlerHandle)> m_CustomHandlerModified;
+ boost::signal<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> m_CustomHandlerParamCreated;
+ boost::signal<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> m_CustomHandlerParamDeleted;
+ boost::signal<void(CUICDMHandlerParamHandle)> m_CustomHandlerParamModified;
+ boost::signal<void(CUICDMInstanceHandle, const TCharStr &)> m_CustomReferencesModified;
+
+ ISlideSystemSignalProvider *m_SlideSystemSignalProvider;
+
+public:
+ CStudioFullSystemSignaller(ISlideSystemSignalProvider *inProvider)
+ : m_SlideSystemSignalProvider(inProvider)
+ {
+ }
+
+ virtual TSignalConnectionPtr ConnectChangeSetBegin(const std::function<void()> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_ChangeSetBegin);
+ }
+ virtual TSignalConnectionPtr ConnectChangeSetEnd(const std::function<void()> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_ChangeSetEnd);
+ }
+
+ // Used when people start to set component times.
+ virtual TSignalConnectionPtr ConnectAnimationSetBegin(const std::function<void()> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_AnimationBegin);
+ }
+ virtual TSignalConnectionPtr ConnectAnimationSetEnd(const std::function<void()> &inCallback)
+ {
+ return CONNECT_SIGNAL(m_AnimationEnd);
+ }
+
+ virtual TSignalConnectionPtr
+ ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideCreated);
+ }
+ virtual TSignalConnectionPtr
+ ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectSlideRearranged(const std::function<void(CUICDMSlideHandle, int, int)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_SlideRearranged);
+ }
+ virtual TSignalConnectionPtr
+ ConnectBeginComponentSeconds(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_BeginComponentSeconds);
+ }
+ virtual TSignalConnectionPtr
+ ConnectComponentSeconds(const std::function<void(CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ComponentSeconds);
+ }
+ TSignalConnectionPtr ConnectPropertyLinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_PropertyLinked);
+ }
+ TSignalConnectionPtr ConnectPropertyUnlinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_PropertyUnlinked);
+ }
+ TSignalConnectionPtr ConnectActiveSlide(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ActiveSlide);
+ }
+
+ virtual TSignalConnectionPtr
+ ConnectInstanceCreated(const std::function<void(CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstanceCreated);
+ }
+ virtual TSignalConnectionPtr
+ ConnectInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstanceDeleted);
+ }
+
+ virtual TSignalConnectionPtr
+ ConnectAnimationCreated(const std::function<void(CUICDMAnimationHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_AnimationCreated);
+ }
+ virtual TSignalConnectionPtr
+ ConnectAnimationDeleted(const std::function<void(CUICDMAnimationHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_AnimationDeleted);
+ }
+ TSignalConnectionPtr ConnectKeyframeInserted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_KeyframeInserted);
+ }
+ TSignalConnectionPtr ConnectKeyframeErased(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_KeyframeErased);
+ }
+ virtual TSignalConnectionPtr
+ ConnectKeyframeUpdated(const std::function<void(CUICDMKeyframeHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_KeyframeUpdated);
+ }
+ TSignalConnectionPtr ConnectInstancePropertyValue(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_InstancePropertyValue);
+ }
+ TSignalConnectionPtr ConnectFirstKeyframeDynamicSet(
+ const std::function<void(CUICDMAnimationHandle, bool)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ConnectFirstKeyframeDynamicSet);
+ }
+
+ TSignalConnectionPtr ConnectActionCreated(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ActionCreated);
+ }
+ TSignalConnectionPtr ConnectActionDeleted(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_ActionDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectTriggerObjectSet(const std::function<void(CUICDMActionHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_TriggerObjectSet);
+ }
+ virtual TSignalConnectionPtr
+ ConnectTargetObjectSet(const std::function<void(CUICDMActionHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_TargetObjectSet);
+ }
+ virtual TSignalConnectionPtr
+ ConnectEventSet(const std::function<void(CUICDMActionHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_EventHandleSet);
+ }
+ virtual TSignalConnectionPtr
+ ConnectHandlerSet(const std::function<void(CUICDMActionHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_HandlerHandleSet);
+ }
+ virtual TSignalConnectionPtr
+ ConnectHandlerArgumentValueSet(const std::function<void(CUICDMHandlerArgHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_HandlerArgumentValueSet);
+ }
+
+ TSignalConnectionPtr ConnectCustomPropertyCreated(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomPropertyCreated);
+ }
+ TSignalConnectionPtr ConnectCustomPropertyDeleted(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomPropertyDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectCustomPropertyModified(const std::function<void(CUICDMPropertyHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomPropertyModified);
+ }
+ TSignalConnectionPtr ConnectCustomEventCreated(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomEventCreated);
+ }
+ TSignalConnectionPtr ConnectCustomEventDeleted(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomEventDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectCustomEventModified(const std::function<void(CUICDMEventHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomEventModified);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerCreated(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerCreated);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerDeleted(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerDeleted);
+ }
+ virtual TSignalConnectionPtr
+ ConnectCustomHandlerModified(const std::function<void(CUICDMHandlerHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerModified);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerParamCreated(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerParamCreated);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerParamDeleted(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerParamDeleted);
+ }
+ TSignalConnectionPtr ConnectCustomHandlerParamModified(
+ const std::function<void(CUICDMHandlerParamHandle)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomHandlerParamModified);
+ }
+ TSignalConnectionPtr ConnectCustomReferencesModified(
+ const std::function<void(CUICDMInstanceHandle, const TCharStr &)> &inCallback) override
+ {
+ return CONNECT_SIGNAL(m_CustomReferencesModified);
+ }
+
+ virtual void SendChangeSetBegin()
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ChangeSetBegin();
+ }
+ virtual void SendChangeSetEnd()
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ChangeSetEnd();
+ }
+
+ virtual void SendAnimationSetBegin()
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_AnimationBegin();
+ }
+ virtual void SendAnimationSetEnd()
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_AnimationEnd();
+ }
+
+ void SendSlideCreated(CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideCreated(inSlide);
+ }
+ void SendSlideDeleted(CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideDeleted(inSlide);
+ }
+ void SendSlideRearranged(CUICDMSlideHandle inMaster, int inOldIndex, int inNewIndex) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_SlideRearranged(inMaster, inOldIndex, inNewIndex);
+ }
+ void SendBeginComponentSeconds(CUICDMSlideHandle inMaster) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_BeginComponentSeconds(inMaster);
+ }
+ void SendComponentSeconds(CUICDMSlideHandle inMaster) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ComponentSeconds(inMaster);
+ }
+ void SendPropertyLinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertyLinked(inMaster, inInstance, inProperty);
+ }
+ void SendPropertyUnlinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_PropertyUnlinked(inMaster, inInstance, inProperty);
+ }
+ void SendActiveSlide(CUICDMSlideHandle inMaster, int inIndex, CUICDMSlideHandle inSlide) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ActiveSlide(inMaster, inIndex, inSlide);
+ }
+
+ void SendInstanceCreated(CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceCreated(inInstance);
+ }
+ void SendInstanceDeleted(CUICDMInstanceHandle inInstance) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstanceDeleted(inInstance);
+ }
+
+ void SendAnimationCreated(CUICDMAnimationHandle inAnimation,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_AnimationCreated(inAnimation, inInstance, inProperty);
+ }
+ void SendAnimationDeleted(CUICDMAnimationHandle inAnimation,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_AnimationDeleted(inAnimation, inInstance, inProperty);
+ }
+ void SendKeyframeInserted(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_KeyframeInserted(inAnimation, inKeyframe);
+ }
+ void SendKeyframeErased(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_KeyframeErased(inAnimation, inKeyframe);
+ }
+ void SendKeyframeUpdated(CUICDMKeyframeHandle inKeyframe) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_KeyframeUpdated(inKeyframe);
+ }
+ void SendConnectFirstKeyframeDynamicSet(CUICDMAnimationHandle inAnimation,
+ bool inDynamic) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ConnectFirstKeyframeDynamicSet(inAnimation, inDynamic);
+ }
+
+ void SendInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_InstancePropertyValue(inInstance, inProperty);
+ }
+
+ void SendActionCreated(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ActionCreated(inAction, inSlide, inOwner);
+ }
+ void SendActionDeleted(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_ActionDeleted(inAction, inSlide, inOwner);
+ }
+ void SendTriggerObjectSet(CUICDMActionHandle inAction) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_TriggerObjectSet(inAction);
+ }
+ void SendTargetObjectSet(CUICDMActionHandle inAction) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_TargetObjectSet(inAction);
+ }
+ void SendEventSet(CUICDMActionHandle inAction) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_EventHandleSet(inAction);
+ }
+ void SendHandlerSet(CUICDMActionHandle inAction) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_HandlerHandleSet(inAction);
+ }
+ void SendHandlerArgumentValueSet(CUICDMHandlerArgHandle inHandlerArgument) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_HandlerArgumentValueSet(inHandlerArgument);
+ }
+
+ void SendCustomPropertyCreated(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomPropertyCreated(inProp, inOwner);
+ }
+ void SendCustomPropertyDeleted(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomPropertyDeleted(inProp, inOwner);
+ }
+ void SendCustomPropertyModified(CUICDMPropertyHandle inProp) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomPropertyModified(inProp);
+ }
+ void SendCustomEventCreated(CUICDMEventHandle inEvent, CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomEventCreated(inEvent, inOwner);
+ }
+ void SendCustomEventDeleted(CUICDMEventHandle inEvent, CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomEventDeleted(inEvent, inOwner);
+ }
+ void SendCustomEventModified(CUICDMEventHandle inEvent) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomEventModified(inEvent);
+ }
+ void SendCustomHandlerCreated(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerCreated(inHandler, inOwner);
+ }
+ void SendCustomHandlerDeleted(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerDeleted(inHandler, inOwner);
+ }
+ void SendCustomHandlerModified(CUICDMHandlerHandle inHandler) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerModified(inHandler);
+ }
+ void SendCustomHandlerParamCreated(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerParamCreated(inParameter, inHandler);
+ }
+ void SendCustomHandlerParamDeleted(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerParamDeleted(inParameter, inHandler);
+ }
+ void SendCustomHandlerParamModified(CUICDMHandlerParamHandle inParameter) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomHandlerParamModified(inParameter);
+ }
+ void SendCustomReferencesModified(CUICDMInstanceHandle inOwner,
+ const TCharStr &inString) override
+ {
+ CHECK_SIGNALS_ENABLED();
+ m_CustomReferencesModified(inOwner, inString);
+ }
+};
+
+TSignalItemPtr
+CreateStudioFullSystemSignaller(ISlideSystemSignalProvider *inSlideSystemSignalProvider)
+{
+ return TSignalItemPtr(static_cast<IStudioFullSystemSignalProvider *>(
+ new CStudioFullSystemSignaller(inSlideSystemSignalProvider)));
+}
+}
diff --git a/src/Authoring/UICDM/Systems/SignalsImpl.h b/src/Authoring/UICDM/Systems/SignalsImpl.h
new file mode 100644
index 00000000..9f1e7fad
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/SignalsImpl.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef SIGNALSIMPLH
+#define SIGNALSIMPLH
+#include "UICDMSignals.h"
+
+namespace UICDM {
+class ISlideSystemSignalProvider;
+
+TSignalItemPtr CreatePropertyCoreSignaller();
+TSignalItemPtr CreateDataCoreSignaller();
+TSignalItemPtr CreateSlideCoreSignaller();
+TSignalItemPtr CreateSlideGraphCoreSignaller();
+TSignalItemPtr CreateAnimationCoreSignaller();
+TSignalItemPtr CreateActionCoreSignaller();
+TSignalItemPtr CreateActionSystemSignaller();
+TSignalItemPtr CreateSlideSystemSignaller();
+TSignalItemPtr CreateCustomPropCoreSignaller();
+TSignalItemPtr
+CreateStudioFullSystemSignaller(ISlideSystemSignalProvider *inSlideSystemSignalProvider);
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/SlideSystem.cpp b/src/Authoring/UICDM/Systems/SlideSystem.cpp
new file mode 100644
index 00000000..86f4acaf
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/SlideSystem.cpp
@@ -0,0 +1,854 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#ifdef WIN32
+#pragma warning(disable : 4503)
+#endif
+#include "SlideSystem.h"
+#include "SimpleSlideCore.h"
+
+using namespace std;
+
+namespace UICDM {
+
+SSlideSystem::SSlideSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore,
+ TSlideGraphCorePtr inSlideGraphCore, TAnimationCorePtr inAnimationCore,
+ CUICDMInstanceHandle inSlideInstance,
+ CUICDMPropertyHandle inComponentGuidProperty)
+ : m_DataCore(inDataCore)
+ , m_SlideCore(inSlideCore)
+ , m_SlideGraphCore(inSlideGraphCore)
+ , m_AnimationCore(inAnimationCore)
+ , m_SlideInstance(inSlideInstance)
+ , m_ComponentGuid(inComponentGuidProperty)
+{
+ m_Signaller = CreateSlideSystemSignaller();
+}
+void SSlideSystem::SetPropertySystem(TPropertySystemPtr inPropertySystem)
+{
+ m_PropertySystem = inPropertySystem;
+}
+
+CUICDMSlideHandle SSlideSystem::CreateMasterSlide()
+{
+ CUICDMInstanceHandle theSlideInstance = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(theSlideInstance, m_SlideInstance);
+ CUICDMSlideHandle retval = m_SlideCore->CreateSlide(theSlideInstance);
+ m_SlideGraphCore->CreateSlideGraph(retval);
+ GetSignalSender()->SendMasterCreated(retval);
+ return retval;
+}
+
+inline bool PropertyHandlePairEquals(const TPropertyHandlePropertyInfoPair &inPair,
+ CUICDMPropertyHandle inProperty)
+{
+ return (inProperty == inPair.first);
+}
+
+void AddReferencedInstance(const TSlideEntry &inEntry,
+ const TPropertyHandlePropertyInfoPairList &inInfoPairList,
+ CUICDMSlideHandle inSourceSlide, CUICDMSlideHandle inDestSlide,
+ TInstanceHandleList &outInstances, TSlideEntryList &outReferencedEntries)
+{
+ TPropertyHandlePropertyInfoPairList::const_iterator theFind =
+ find_if<TPropertyHandlePropertyInfoPairList::const_iterator>(
+ inInfoPairList, std::bind(PropertyHandlePairEquals,
+ std::placeholders::_1, get<1>(inEntry)));
+ if (theFind != inInfoPairList.end()) {
+ TPropertyInstanceInfoPtr theInfo(theFind->second);
+ CUICDMInstanceHandle theReferenced(theInfo->GetInstanceForProperty(get<2>(inEntry)));
+ if (theReferenced.Valid()
+ && !exists(outInstances, std::bind(equal_to<int>(), theReferenced,
+ std::placeholders::_1))) {
+ insert_unique(outInstances, theReferenced);
+ SValue theNewValue(
+ theInfo->CreateInstanceForProperty(inSourceSlide, inDestSlide, theReferenced));
+ outReferencedEntries.push_back(
+ make_tuple(get<0>(inEntry), get<1>(inEntry), theNewValue));
+ }
+ }
+}
+
+void CopySpecificAnimation(CUICDMSlideHandle inMaster, CUICDMSlideHandle inTarget,
+ TInstancePropertyPair inPropertyPair, TAnimationCorePtr inAnimationCore,
+ size_t inIndex)
+{
+ CUICDMAnimationHandle theAnimation = inAnimationCore->GetAnimation(
+ inMaster, inPropertyPair.first, inPropertyPair.second, inIndex);
+ if (theAnimation.Valid())
+ CopyAnimation(inAnimationCore, theAnimation, inTarget, inPropertyPair.first,
+ inPropertyPair.second, inIndex);
+}
+
+void CopyAnimationIfExist(CUICDMSlideHandle inMaster, CUICDMSlideHandle inTarget,
+ TInstancePropertyPair inPropertyPair, TPropertySystemPtr inPropertySystem,
+ TAnimationCorePtr inAnimationCore)
+{
+ DataModelDataType::Value thePropertyType = inPropertySystem->GetDataType(inPropertyPair.second);
+ std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(thePropertyType);
+ if (std::get<0>(theArity))
+ do_times(std::get<1>(theArity), std::bind(CopySpecificAnimation, inMaster, inTarget,
+ inPropertyPair, inAnimationCore,
+ std::placeholders::_1));
+}
+
+void SetEntryValueIfNotReferenced(const TSlideEntry &inEntry,
+ const TInstanceHandleList &inReferencedInstances,
+ const TSlideEntryList &inReferencedEntries,
+ CUICDMSlideHandle inSource, CUICDMSlideHandle inDestSlide,
+ TPropertySystemPtr inPropertySystem, TSlideCorePtr inDestCore,
+ TAnimationCorePtr inAnimationCore)
+{
+ // Don't copy referenced instance properties.
+ if (exists(inReferencedInstances, std::bind(equal_to<int>(), get<0>(inEntry),
+ std::placeholders::_1)))
+ return;
+ TSlideEntryList::const_iterator theFind = find_if<TSlideEntryList::const_iterator>(
+ inReferencedEntries,
+ std::bind(CSimpleSlideCore::PropertyFound, get<0>(inEntry), get<1>(inEntry),
+ std::placeholders::_1));
+ if (theFind != inReferencedEntries.end())
+ inDestCore->ForceSetInstancePropertyValue(inDestSlide, get<0>(inEntry), get<1>(inEntry),
+ get<2>(*theFind));
+ else
+ inDestCore->ForceSetInstancePropertyValue(inDestSlide, get<0>(inEntry), get<1>(inEntry),
+ get<2>(inEntry));
+ CopyAnimationIfExist(inSource, inDestSlide, make_pair(get<0>(inEntry), get<1>(inEntry)),
+ inPropertySystem, inAnimationCore);
+}
+
+CUICDMSlideHandle SSlideSystem::CreateSlide(CUICDMSlideHandle inMaster, int inIndex)
+{
+ return DuplicateSlide(inMaster, inIndex);
+}
+
+CUICDMSlideHandle SSlideSystem::DuplicateSlide(CUICDMSlideHandle inSourceSlide, int inIndex)
+{
+ CUICDMSlideHandle theMaster = GetMasterSlide(inSourceSlide);
+ CUICDMInstanceHandle theSlideInstance = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(theSlideInstance, m_SlideInstance);
+ CUICDMSlideHandle retval = m_SlideCore->CreateSlide(theSlideInstance);
+
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(theMaster, theChildren);
+ m_SlideCore->DeriveSlide(retval, theMaster, inIndex - 1);
+ int finalIndex = m_SlideCore->GetChildIndex(theMaster, retval) + 1;
+ if (!theChildren.empty()) {
+ // If the master was passed in, we get the intersecting properties
+ // of the master and first child.
+ // if another slide was passed in, we again do the intersection but we
+ // take the values from the source slide instead of the master.
+ TSlideEntryList theIntersectingEntries;
+ if (inSourceSlide == theMaster)
+ m_SlideCore->GetIntersectingProperties(theMaster, theChildren.at(0),
+ theIntersectingEntries);
+ else
+ m_SlideCore->GetIntersectingProperties(inSourceSlide, theMaster,
+ theIntersectingEntries);
+
+ // duplicates the instance properties, from source slide (could be master (a new slide
+ // command) or another other slides (duplicate slide) to the newly created slide
+ m_DataCore->CopyInstanceProperties(this->GetSlideInstance(inSourceSlide), theSlideInstance);
+
+ TInstanceHandleList theReferencedInstances;
+ TSlideEntryList theReferencedEntries;
+ do_all(theIntersectingEntries,
+ std::bind(AddReferencedInstance, std::placeholders::_1,
+ std::cref(m_PropertyInfoPairList),
+ inSourceSlide, retval, std::ref(theReferencedInstances),
+ std::ref(theReferencedEntries)));
+ do_all(theIntersectingEntries,
+ std::bind(SetEntryValueIfNotReferenced, std::placeholders::_1,
+ std::cref(theReferencedInstances),
+ std::cref(theReferencedEntries), inSourceSlide, retval,
+ m_PropertySystem, m_SlideCore, m_AnimationCore));
+ }
+ GetSignalSender()->SendSlideCreated(theMaster, finalIndex, retval);
+ return retval;
+}
+
+CUICDMSlideHandle SSlideSystem::GetMasterSlide(CUICDMSlideHandle inSlide) const
+{
+ if (inSlide.Valid() && m_SlideCore->IsSlide(inSlide)) {
+ CUICDMSlideHandle theParent = m_SlideCore->GetParentSlide(inSlide);
+ if (theParent.Valid())
+ return theParent;
+ return inSlide;
+ }
+ return 0;
+}
+
+bool SSlideSystem::IsMasterSlide(CUICDMSlideHandle inSlide) const
+{
+ CUICDMSlideHandle theParent = m_SlideCore->GetParentSlide(inSlide);
+ if (!theParent.Valid())
+ return true;
+ else
+ return false;
+}
+
+inline bool GraphGuidMatches(CUICDMSlideGraphHandle inGraph, TSlideGraphCorePtr inSlideGraph,
+ TSlideCorePtr inSlideCore, TDataCorePtr inDataCore,
+ CUICDMPropertyHandle inProperty, SValue inValue)
+{
+ CUICDMSlideHandle theMaster = inSlideGraph->GetGraphRoot(inGraph);
+ CUICDMInstanceHandle theInstance = inSlideCore->GetSlideInstance(theMaster);
+ SValue theValue;
+ if (inDataCore->GetInstancePropertyValue(theInstance, inProperty, theValue)
+ && Equals(inValue, theValue.toOldSkool()))
+ return true;
+ return false;
+}
+
+CUICDMSlideHandle SSlideSystem::GetMasterSlideByComponentGuid(SLong4 inGuid) const
+{
+ TSlideGraphHandleList theGraphs;
+ m_SlideGraphCore->GetSlideGraphs(theGraphs);
+ TSlideGraphHandleList::iterator theFind = find_if<TSlideGraphHandleList::iterator>(
+ theGraphs, std::bind(GraphGuidMatches,
+ std::placeholders::_1, m_SlideGraphCore, m_SlideCore, m_DataCore,
+ m_ComponentGuid, inGuid));
+ if (theFind != theGraphs.end())
+ return m_SlideGraphCore->GetGraphRoot(*theFind);
+ return 0;
+}
+
+void InsertIfReferencedProperty(const TSlideEntry &inEntry,
+ const TPropertyHandlePropertyInfoPairList &inRefProperties,
+ TInstanceHandleList &inInstances)
+{
+ TPropertyHandlePropertyInfoPairList::const_iterator theFind =
+ find_if<TPropertyHandlePropertyInfoPairList::const_iterator>(
+ inRefProperties, std::bind(PropertyHandlePairEquals, std::placeholders::_1, get<1>(inEntry)));
+ if (theFind != inRefProperties.end()) {
+ CUICDMInstanceHandle theInstance(theFind->second->GetInstanceForProperty(get<2>(inEntry)));
+ if (theInstance.Valid())
+ inInstances.push_back(theInstance);
+ }
+}
+
+void SSlideSystem::InsertEntryAndPropertyInstance(const TSlideEntry &inEntry,
+ TInstanceHandleList &inInstances,
+ CUICDMSlideHandle inSlide)
+{
+ CUICDMInstanceHandle theEntryInstance = get<0>(inEntry);
+ if (find(inInstances.begin(), inInstances.end(), theEntryInstance) == inInstances.end()) {
+ TGraphSlidePair thePair = m_SlideGraphCore->GetAssociatedGraph(theEntryInstance);
+ if (thePair.second == inSlide) // if this instance belongs to this slide
+ {
+ // get all references belong to this instance (ex: image instances that belong to this
+ // material instance)
+ UICDM::SValue theValue;
+ for (TPropertyHandlePropertyInfoPairList::iterator theIter =
+ m_PropertyInfoPairList.begin();
+ theIter != m_PropertyInfoPairList.end(); ++theIter) {
+ if (m_DataCore->HasAggregateInstanceProperty(
+ theEntryInstance,
+ theIter->first) // check if the property exists before querying the value
+ && m_DataCore->GetInstancePropertyValue(
+ theEntryInstance, theIter->first,
+ theValue)) // this function may throw error if the property doesn't exist
+ {
+ CUICDMInstanceHandle theInstance(
+ theIter->second->GetInstanceForProperty(theValue.toOldSkool()));
+ if (theInstance.Valid())
+ inInstances.push_back(theInstance);
+ }
+ }
+ // get this instance as well
+ inInstances.push_back(theEntryInstance);
+ }
+ }
+}
+
+// Delete the referenced instances of this slide
+// This function is very similar to GetReferencedInstances
+// You change one function, you need to change the other function
+void SSlideSystem::DeleteReferencedInstances(CUICDMSlideHandle inSlide)
+{
+ // Recursively delete the children of this slide
+ // Usually the slide has children if it is a Master slide (for example when deleting a
+ // Component)
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(inSlide, theChildren);
+ do_all(theChildren, std::bind(&SSlideSystem::DeleteReferencedInstances, this,
+ std::placeholders::_1));
+
+ // Delete the referenced instances from this slide
+ TSlideEntryList theEntries;
+ m_SlideCore->GetSlidePropertyEntries(inSlide, theEntries);
+
+ // Run through all entries, if you find a reference property delete the associated instance.
+ // This is for properties that are set on this slide (because you can set property on slide or
+ // on instance)
+ TInstanceHandleList theReferencedInstances;
+ do_all(theEntries,
+ std::bind(InsertIfReferencedProperty, std::placeholders::_1,
+ std::cref(m_PropertyInfoPairList),
+ std::ref(theReferencedInstances)));
+ do_all(theReferencedInstances, std::bind(&IDataCore::DeleteInstance, m_DataCore,
+ std::placeholders::_1));
+
+ // Run through all entries, delete all instances that belong to this slide and its reference
+ // property instances
+ // This is for properties that are set on instance
+ theReferencedInstances.clear();
+ do_all(theEntries, std::bind(&SSlideSystem::InsertEntryAndPropertyInstance, this,
+ std::placeholders::_1,
+ std::ref(theReferencedInstances), inSlide));
+ do_all(theReferencedInstances, std::bind(&IDataCore::DeleteInstance, m_DataCore,
+ std::placeholders::_1));
+}
+
+// Get the referenced instances of this slide
+// This function is very similar to DeleteReferencedInstances
+// You change one function, you need to change the other function
+void SSlideSystem::GetReferencedInstances(CUICDMSlideHandle inSlide,
+ TInstanceHandleList &outReferencedInstances)
+{
+ // Recursively get the children of this slide
+ // Usually the slide has children if it is a Master slide (for example Component)
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(inSlide, theChildren);
+ do_all(theChildren, std::bind(&SSlideSystem::GetReferencedInstances, this,
+ std::placeholders::_1,
+ std::ref(outReferencedInstances)));
+
+ // Get the referenced instances from this slide
+ TSlideEntryList theEntries;
+ m_SlideCore->GetSlidePropertyEntries(inSlide, theEntries);
+
+ // Run through all entries, if you find a reference property get the associated instance.
+ // This is for properties that are set on this slide (because you can set property on slide or
+ // on instance)
+ do_all(theEntries,
+ std::bind(InsertIfReferencedProperty, std::placeholders::_1,
+ std::cref(m_PropertyInfoPairList),
+ std::ref(outReferencedInstances)));
+
+ // Run through all entries, get all instances that belong to this slide and its reference
+ // property instances
+ // This is for properties that are set on instance
+ do_all(theEntries, std::bind(&SSlideSystem::InsertEntryAndPropertyInstance, this,
+ std::placeholders::_1,
+ std::ref(outReferencedInstances), inSlide));
+}
+
+void SSlideSystem::DeleteSlideByIndex(CUICDMSlideHandle inMaster, size_t inIndex)
+{
+ CUICDMSlideHandle theChild = GetSlideByIndex(inMaster, inIndex);
+ TInstanceHandleList theInstances;
+ if (theChild.Valid()) {
+ DeleteReferencedInstances(theChild);
+ m_SlideCore->DeleteSlide(theChild, theInstances);
+ do_all(theInstances, std::bind(&IDataCore::DeleteInstance, m_DataCore,
+ std::placeholders::_1));
+ }
+ if (inIndex == 0)
+ GetSignalSender()->SendMasterDeleted(inMaster);
+ else
+ GetSignalSender()->SendSlideDeleted(inMaster, (int)inIndex, theChild);
+}
+
+void SSlideSystem::GetSlideReferencedInstances(CUICDMSlideHandle inMaster, size_t inIndex,
+ TInstanceHandleList &outReferencedInstances)
+{
+ outReferencedInstances.clear();
+ CUICDMSlideHandle theChild = GetSlideByIndex(inMaster, inIndex);
+ if (theChild.Valid()) {
+ GetReferencedInstances(theChild, outReferencedInstances);
+ }
+}
+
+CUICDMSlideHandle SSlideSystem::GetSlideByIndex(CUICDMSlideHandle inMaster, size_t inIndex) const
+{
+ if (inIndex == 0)
+ return inMaster;
+ --inIndex;
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(inMaster, theChildren);
+ if (inIndex < theChildren.size())
+ return theChildren[inIndex];
+ return CUICDMSlideHandle();
+}
+
+void SSlideSystem::SetActiveSlide(CUICDMSlideHandle inMaster, size_t inIndex)
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(inMaster);
+ CUICDMSlideHandle theActiveSlide = inMaster;
+ if (inIndex > 0)
+ theActiveSlide = GetSlideByIndex(inMaster, inIndex);
+ CUICDMSlideHandle theOldSlide = m_SlideGraphCore->GetGraphActiveSlide(theGraph);
+ m_SlideGraphCore->SetGraphActiveSlide(theGraph, theActiveSlide);
+ GetSignalSender()->SendActiveSlide(inMaster, (int)inIndex, theOldSlide, theActiveSlide);
+}
+
+size_t SSlideSystem::GetSlideCount(CUICDMSlideHandle inMaster) const
+{
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(inMaster, theChildren);
+ return 1 + theChildren.size();
+}
+
+void SSlideSystem::RearrangeSlide(CUICDMSlideHandle inMaster, size_t inOldIndex, size_t inNewIndex)
+{
+ if (inOldIndex == 0)
+ throw RearrangeSlideArgumentsMustNotBeZero(L"");
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(inMaster, theChildren);
+ CUICDMSlideHandle theChild = theChildren.at(inOldIndex - 1);
+ m_SlideCore->DeriveSlide(theChild, inMaster, (int)inNewIndex - 1);
+ GetSignalSender()->SendSlideRearranged(inMaster, (int)inOldIndex, (int)inNewIndex);
+}
+
+void SSlideSystem::SetComponentSeconds(CUICDMSlideHandle inSlide, float inSeconds)
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inSlide));
+ m_SlideCore->SetSlideTime(m_SlideGraphCore->GetGraphActiveSlide(theGraph), inSeconds);
+}
+
+float SSlideSystem::GetComponentSeconds(CUICDMSlideHandle inSlide) const
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inSlide));
+ return m_SlideCore->GetSlideTime(m_SlideGraphCore->GetGraphActiveSlide(theGraph));
+}
+
+long SSlideSystem::GetComponentSecondsLong(CUICDMSlideHandle inSlide) const
+{
+ float seconds(GetComponentSeconds(inSlide));
+ return static_cast<long>((seconds * 1000) + .5f);
+}
+
+long SSlideSystem::GetComponentSecondsLong(CUICDMInstanceHandle inInstance) const
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetAssociatedGraph(inInstance).first;
+ float seconds = m_SlideCore->GetSlideTime(m_SlideGraphCore->GetGraphActiveSlide(theGraph));
+ return static_cast<long>((seconds * 1000) + .5f);
+}
+
+SInstanceSlideInformation
+SSlideSystem::GetInstanceSlideInformation(CUICDMInstanceHandle inInstance) const
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ CUICDMSlideHandle theAssociatedSlide(theGraphSlidePair.second);
+ if (theAssociatedSlide.Valid() == false)
+ return SInstanceSlideInformation();
+ CUICDMSlideHandle theMasterSlide(GetMasterSlide(theGraphSlidePair.second));
+ CUICDMSlideHandle theActiveSlide(
+ m_SlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first));
+ float seconds = m_SlideCore->GetSlideTime(theActiveSlide);
+ long theMilliseconds = static_cast<long>((seconds * 1000) + .5f);
+ return SInstanceSlideInformation(theAssociatedSlide, theMasterSlide, theActiveSlide,
+ theMilliseconds);
+}
+
+/**
+ * Use the instance for storing information such as name, or the GUID of the object
+ * this slide links to.
+ */
+CUICDMInstanceHandle SSlideSystem::GetSlideInstance(CUICDMSlideHandle inSlide) const
+{
+ return m_SlideCore->GetSlideInstance(inSlide);
+}
+/**
+ * Reverse lookup into the slide system so you can match slides to instances.
+ */
+CUICDMSlideHandle SSlideSystem::GetSlideByInstance(CUICDMInstanceHandle inSlide) const
+{
+ return m_SlideCore->GetSlideByInstance(inSlide);
+}
+
+/**
+ * Slide may be either a master slide
+ */
+void SSlideSystem::AssociateInstanceWithSlide(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inSlide));
+ m_SlideGraphCore->AssociateInstance(theGraph, inSlide, inInstance);
+ GetSignalSender()->SendInstanceAssociated(inSlide, inInstance);
+}
+
+CUICDMSlideHandle SSlideSystem::GetAssociatedSlide(CUICDMInstanceHandle inInstance) const
+{
+ return m_SlideGraphCore->GetAssociatedGraph(inInstance).second;
+}
+
+/**
+ * This gets the instances that resides int the SlideGraph, i.e. all the instances in all the
+ *slides for this component/scene
+ * TODO rename this to make it more clear
+ */
+void SSlideSystem::GetAssociatedInstances(CUICDMSlideHandle inMaster,
+ TSlideInstancePairList &outAssociations) const
+{
+ m_SlideGraphCore->GetAssociatedInstances(
+ m_SlideGraphCore->GetSlideGraph(GetMasterSlide(inMaster)), outAssociations);
+}
+
+/**
+ * Gets all the instances in this slide
+ */
+void SSlideSystem::GetAssociatedInstances(CUICDMSlideHandle inSlide,
+ TInstanceHandleList &outAssociations) const
+{
+ CUICDMSlideHandle theMasterSlide = GetMasterSlide(inSlide);
+ TSlideInstancePairList theGraphInstances;
+ m_SlideGraphCore->GetAssociatedInstances(m_SlideGraphCore->GetSlideGraph(theMasterSlide),
+ theGraphInstances);
+ for (TSlideInstancePairList::const_iterator theIter = theGraphInstances.begin();
+ theIter != theGraphInstances.end(); ++theIter) {
+ if (theIter->first == inSlide || theIter->first == theMasterSlide) {
+ // in the current slide or master slide
+ outAssociations.push_back(theIter->second);
+ }
+ }
+}
+
+void DeleteInstanceIfExistsAsProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, TSlideCorePtr inSlideCore,
+ TPropertyInstanceInfoPtr inPropertyInfoPtr,
+ TDataCorePtr inDataCore)
+{
+ SValue theValue;
+ if (inSlideCore->GetSpecificInstancePropertyValue(inSlide, inInstance, inProperty, theValue)) {
+ CUICDMInstanceHandle theInstance(inPropertyInfoPtr->GetInstanceForProperty(theValue));
+ if (theInstance.Valid())
+ inDataCore->DeleteInstance(theInstance);
+ }
+}
+
+void SSlideSystem::LinkProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty)
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetAssociatedGraph(inInstance).first;
+ CUICDMSlideHandle theSlide = m_SlideGraphCore->GetGraphRoot(theGraph);
+ TPropertyHandlePropertyInfoPairList::const_iterator theFind =
+ find_if<TPropertyHandlePropertyInfoPairList::const_iterator>(
+ m_PropertyInfoPairList, std::bind(PropertyHandlePairEquals,
+ std::placeholders::_1, inProperty));
+ if (theFind != m_PropertyInfoPairList.end()) {
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(theSlide, theChildren);
+ do_all(theChildren, std::bind(DeleteInstanceIfExistsAsProperty, std::placeholders::_1, inInstance,
+ inProperty, m_SlideCore, theFind->second, m_DataCore));
+ }
+ m_SlideCore->ClearChildrenPropertyValues(theSlide, inInstance, inProperty);
+ GetSignalSender()->SendPropertyLinked(theSlide, inInstance, inProperty);
+}
+
+void ClearPropertyValueIfLinked(CUICDMSlideHandle inMaster, const TSlideHandleList &inChildren,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ TSlideCorePtr inSlideCore)
+{
+ if (inChildren.empty())
+ return;
+
+ if (inSlideCore->ContainsProperty(inChildren.at(0), inInstance,
+ inProperty)) // if property is linked,
+ inSlideCore->ClearChildrenPropertyValues(inMaster, inInstance,
+ inProperty); // get it off non-master slides
+}
+
+void SetReferencedEntryValue(CUICDMSlideHandle inMaster, CUICDMSlideHandle inDestSlide,
+ TPropertyInstanceInfoPtr inInfo, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ CUICDMInstanceHandle inReferencedInstance, TSlideCorePtr inSlideCore)
+{
+ SValue theNewValue(
+ inInfo->CreateInstanceForProperty(inMaster, inDestSlide, inReferencedInstance));
+ inSlideCore->ForceSetInstancePropertyValue(inDestSlide, inInstance, inProperty, theNewValue);
+}
+
+void SSlideSystem::UnlinkProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty)
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetAssociatedGraph(inInstance).first;
+ CUICDMSlideHandle theSlide = m_SlideGraphCore->GetGraphRoot(theGraph);
+ SValue theValue;
+ SValue theTempValue;
+ if (!m_SlideCore->GetInstancePropertyValue(theSlide, inInstance, inProperty, theValue)) {
+ if (!m_PropertySystem->GetInstancePropertyValue(inInstance, inProperty, theTempValue))
+ throw PropertyLinkError(L"");
+ theValue = theTempValue.toOldSkool();
+ }
+
+ m_SlideCore->ForceSetInstancePropertyValue(theSlide, inInstance, inProperty, theValue);
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(theSlide, theChildren);
+
+ CUICDMInstanceHandle theReferenced;
+ TPropertyHandlePropertyInfoPairList::const_iterator theFind =
+ find_if<TPropertyHandlePropertyInfoPairList::const_iterator>(
+ m_PropertyInfoPairList, std::bind(PropertyHandlePairEquals,
+ std::placeholders::_1, inProperty));
+ TPropertyInstanceInfoPtr theInfo;
+ if (theFind != m_PropertyInfoPairList.end()) {
+ theInfo = theFind->second;
+ theReferenced = theInfo->GetInstanceForProperty(theValue);
+ }
+ if (theReferenced.Valid()) {
+ TPropertyHandleList theProperties;
+ m_PropertySystem->GetAggregateInstanceProperties(
+ theReferenced,
+ theProperties); // TODO: We should make the method return the custom properties.
+ // Remove the property instance's unlinked properties from non-master slides.
+ do_all(theProperties,
+ std::bind(ClearPropertyValueIfLinked, theSlide, std::cref(theChildren),
+ theReferenced, std::placeholders::_1, m_SlideCore));
+ // Remove all property values from the children from that instance.
+ do_all(theChildren, std::bind(SetReferencedEntryValue, theSlide,
+ std::placeholders::_1, theInfo, inInstance,
+ inProperty, theReferenced, m_SlideCore));
+ } else {
+ do_all(theChildren, std::bind(&ISlideCore::ForceSetInstancePropertyValue, m_SlideCore,
+ std::placeholders::_1,
+ inInstance, inProperty, theValue));
+ do_all(theChildren,
+ std::bind(CopyAnimationIfExist, theSlide, std::placeholders::_1, make_pair(inInstance, inProperty),
+ m_PropertySystem, m_AnimationCore));
+ }
+ GetSignalSender()->SendPropertyUnlinked(theSlide, inInstance, inProperty);
+}
+
+bool SSlideSystem::IsPropertyLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ CUICDMSlideGraphHandle theGraph = theGraphSlidePair.first;
+ if (!theGraph.Valid())
+ return false;
+
+ CUICDMSlideHandle theSlide = m_SlideGraphCore->GetGraphRoot(theGraph);
+ if (theGraphSlidePair.second != theSlide)
+ return false;
+
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(theSlide, theChildren);
+ bool containsProperty = false;
+ for (TSlideHandleList::iterator theIter = theChildren.begin();
+ theIter != theChildren.end() && !containsProperty; ++theIter) {
+ containsProperty =
+ containsProperty || m_SlideCore->ContainsProperty(*theIter, inInstance, inProperty);
+ }
+
+ return !containsProperty;
+}
+
+bool SSlideSystem::CanPropertyBeLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ if (theGraphSlidePair.first.Valid()
+ && theGraphSlidePair.second == m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first))
+ return true;
+ return false;
+}
+
+bool SSlideSystem::GetSlidePropertyValue(size_t inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue)
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ CUICDMSlideGraphHandle theGraph = theGraphSlidePair.first;
+ if (!theGraph.Valid())
+ return false;
+ CUICDMSlideHandle theSlide = GetSlideByIndex(m_SlideGraphCore->GetGraphRoot(theGraph), inSlide);
+ if (!theSlide.Valid())
+ return false;
+ return m_SlideCore->GetSpecificInstancePropertyValue(theSlide, inInstance, inProperty,
+ outValue);
+}
+
+void AddEntriesToHash(const TSlideEntryList &theSlideEntries, TSlideEntryHash &theEntryHash,
+ TInstancePropertyPairList &outProperties)
+{
+ for (size_t idx = 0, end = theSlideEntries.size(); idx < end; ++idx) {
+ const TSlideEntry &theEntry(theSlideEntries[idx]);
+ pair<TSlideEntryHash::iterator, bool> insertRecord(theEntryHash.insert(
+ make_pair(TSlideInstancePropertyPair(get<0>(theEntry), get<1>(theEntry)),
+ SInternValue::ISwearThisHasAlreadyBeenInternalized(get<2>(theEntry)))));
+ if (insertRecord.second)
+ outProperties.push_back(insertRecord.first->first);
+ }
+}
+
+void SSlideSystem::GetUnionOfProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ TInstancePropertyPairList &outProperties) const
+{
+ TSlideEntryHash theEntryHash;
+ TSlideEntryList theSlideEntries;
+ if (m_SlideCore->IsSlide(inSlide1)) {
+ m_SlideCore->GetSlidePropertyEntries(inSlide1, theSlideEntries);
+ AddEntriesToHash(theSlideEntries, theEntryHash, outProperties);
+ }
+ if (m_SlideCore->IsSlide(inSlide2)) {
+ m_SlideCore->GetSlidePropertyEntries(inSlide2, theSlideEntries);
+ AddEntriesToHash(theSlideEntries, theEntryHash, outProperties);
+ }
+}
+
+void SSlideSystem::SetActiveSlide(CUICDMSlideHandle inSlide)
+{
+ CUICDMSlideHandle theMaster = GetMasterSlide(inSlide);
+ int theIndex = GetSlideIndex(inSlide);
+ SetActiveSlide(theMaster, theIndex);
+}
+
+CUICDMSlideHandle SSlideSystem::GetAssociatedSlide(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ CUICDMSlideGraphHandle theGraph = theGraphSlidePair.first;
+ if (!theGraph.Valid())
+ return 0;
+ CUICDMSlideHandle theSlide = m_SlideGraphCore->GetGraphActiveSlide(theGraph);
+ if (theSlide.Valid()) {
+ if (m_SlideCore->ContainsProperty(theSlide, inInstance, inProperty))
+ return theSlide;
+ theSlide = m_SlideCore->GetParentSlide(theSlide);
+ if (theSlide.Valid() && m_SlideCore->ContainsProperty(theSlide, inInstance, inProperty))
+ return theSlide;
+ return theGraphSlidePair.second;
+ }
+ return 0;
+}
+
+bool SSlideSystem::SlideValid(CUICDMSlideHandle inSlide) const
+{
+ return m_SlideCore->HandleValid(inSlide);
+}
+
+int SSlideSystem::GetSlideIndex(CUICDMSlideHandle inSlide) const
+{
+ CUICDMSlideHandle theMaster = GetMasterSlide(inSlide);
+ if (inSlide.Valid() && inSlide != theMaster)
+ return m_SlideCore->GetChildIndex(theMaster, inSlide) + 1;
+ return 0;
+}
+
+int SSlideSystem::GetActiveSlideIndex(CUICDMSlideHandle inMaster) const
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(inMaster);
+ CUICDMSlideHandle theActiveSlide = m_SlideGraphCore->GetGraphActiveSlide(theGraph);
+ if (theActiveSlide == inMaster)
+ return 0;
+ return GetSlideIndex(theActiveSlide);
+}
+
+CUICDMSlideHandle SSlideSystem::GetActiveSlide(CUICDMSlideHandle inMaster) const
+{
+ CUICDMSlideGraphHandle theGraph = m_SlideGraphCore->GetSlideGraph(inMaster);
+ return m_SlideGraphCore->GetGraphActiveSlide(theGraph);
+}
+
+CUICDMInstanceHandle SSlideSystem::GetSlideSelectedInstance(CUICDMSlideHandle inSlide) const
+{
+ TIntIntMap::const_iterator theIter = m_SlideSelectedInstances.find(inSlide);
+ if (theIter != m_SlideSelectedInstances.end() && m_DataCore->IsInstance(theIter->second))
+ return theIter->second;
+ return 0;
+}
+
+void SSlideSystem::SetSlideSelectedInstance(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance)
+{
+ m_SlideSelectedInstances[inSlide] = inInstance;
+}
+
+void SSlideSystem::RegisterPropertyInstance(CUICDMPropertyHandle inPropertyHandle,
+ TPropertyInstanceInfoPtr inPropertyInfo)
+{
+ m_PropertyInfoPairList.push_back(make_pair(inPropertyHandle, inPropertyInfo));
+}
+
+ISlideSystemSignalProvider *SSlideSystem::GetSignalProvider()
+{
+ return dynamic_cast<ISlideSystemSignalProvider *>(m_Signaller.get());
+}
+
+ISlideSystemSignalSender *SSlideSystem::GetSignalSender()
+{
+ return dynamic_cast<ISlideSystemSignalSender *>(m_Signaller.get());
+}
+
+UICDM::CUICDMSlideHandle SSlideSystem::GetApplicableSlide(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty)
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inHandle);
+ if (!theGraphSlidePair.first.Valid())
+ return CUICDMSlideHandle();
+
+ CUICDMSlideHandle theMaster = m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first);
+ if (theGraphSlidePair.second != theMaster)
+ return theGraphSlidePair.second;
+
+ CUICDMSlideHandle theActive = m_SlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first);
+ if (m_SlideCore->ContainsProperty(theActive, inHandle, inProperty))
+ return theActive;
+
+ return theMaster;
+}
+
+bool SSlideSystem::GetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const
+{
+ return m_SlideCore->GetInstancePropertyValue(inSlide, inInstance, inProperty, outValue);
+}
+
+bool SSlideSystem::GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ if (theGraphSlidePair.first.Valid()) {
+ // Check to see if the object is on the master slide;
+ if (theGraphSlidePair.second == m_SlideGraphCore->GetGraphRoot(theGraphSlidePair.first)) {
+ TSlideHandleList theChildren;
+ m_SlideCore->GetChildSlides(theGraphSlidePair.second, theChildren);
+ // See if the value exists on slide 1.
+ if (!theChildren.empty()
+ && m_SlideCore->GetSpecificInstancePropertyValue(theChildren.at(0), inInstance,
+ inProperty, outValue))
+ return true;
+ }
+
+ if (m_SlideCore->GetSpecificInstancePropertyValue(theGraphSlidePair.second, inInstance,
+ inProperty, outValue))
+ return true;
+ }
+ return false;
+}
+
+void SSlideSystem::ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ m_SlideCore->ForceSetInstancePropertyValue(inSlide, inInstance, inProperty, inValue);
+}
+}
diff --git a/src/Authoring/UICDM/Systems/SlideSystem.h b/src/Authoring/UICDM/Systems/SlideSystem.h
new file mode 100644
index 00000000..f33bd540
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/SlideSystem.h
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef SLIDESYSTEMH
+#define SLIDESYSTEMH
+#include "UICDMDataCore.h"
+#include "UICDMSlideCore.h"
+#include "UICDMSlideGraphCore.h"
+#include "UICDMTransactions.h"
+#include "UICDMSlides.h"
+#include "UICDMAnimation.h"
+#include "StudioPropertySystem.h"
+#include "SignalsImpl.h"
+
+/**
+ * The systems aggregate the various cores and provide further information or
+ * integrity checking taking the various cores into account.
+ */
+
+namespace UICDM {
+
+typedef std::pair<CUICDMPropertyHandle, TPropertyInstanceInfoPtr> TPropertyHandlePropertyInfoPair;
+typedef std::vector<TPropertyHandlePropertyInfoPair> TPropertyHandlePropertyInfoPairList;
+/**
+ * Provides more thorough checking and will return an appropriate
+ * slide graph when calling GetSlideGraph
+ */
+struct SSlideSystem : public ISlideSystem
+{
+ Q_DISABLE_COPY(SSlideSystem)
+
+ TDataCorePtr m_DataCore; // TODO: We might want to throw this away and use the PropertySystem,
+ // unless we have a clean seperate of IPropertySystem and IDataCore
+ TPropertySystemPtr m_PropertySystem;
+ TSlideCorePtr m_SlideCore;
+ TSlideGraphCorePtr m_SlideGraphCore;
+ TAnimationCorePtr m_AnimationCore;
+ CUICDMInstanceHandle m_SlideInstance;
+ CUICDMPropertyHandle m_ComponentGuid;
+ std::shared_ptr<ISignalItem> m_Signaller;
+ TPropertyHandlePropertyInfoPairList m_PropertyInfoPairList;
+ typedef std::unordered_map<int, int> TIntIntMap;
+ TIntIntMap m_SlideSelectedInstances;
+
+ SSlideSystem(TDataCorePtr inDataCore, TSlideCorePtr inSlideCore,
+ TSlideGraphCorePtr inSlideGraphCore, TAnimationCorePtr inAnimationCore,
+ CUICDMInstanceHandle inSlideInstance,
+ CUICDMPropertyHandle inComponentGuidProperty);
+
+ void SetPropertySystem(TPropertySystemPtr inPropertySystem);
+
+ CUICDMSlideHandle CreateMasterSlide() override;
+ CUICDMSlideHandle CreateSlide(CUICDMSlideHandle inMaster, int inIndex = -1) override;
+ CUICDMSlideHandle DuplicateSlide(CUICDMSlideHandle inSourceSlide, int inDestIndex = -1) override;
+ CUICDMSlideHandle GetMasterSlide(CUICDMSlideHandle inSlide) const override;
+ bool IsMasterSlide(CUICDMSlideHandle inSlide) const override;
+ CUICDMSlideHandle GetMasterSlideByComponentGuid(SLong4 inGuid) const override;
+ // Indexes are 1 based. Index 0 refers to the master slide; you can't delete this.
+ void DeleteSlideByIndex(CUICDMSlideHandle inMaster, size_t inIndex) override;
+ void GetSlideReferencedInstances(CUICDMSlideHandle inMaster, size_t inIndex,
+ TInstanceHandleList &outReferencedInstances) override;
+ CUICDMSlideHandle GetSlideByIndex(CUICDMSlideHandle inMaster, size_t inIndex) const override;
+ void SetActiveSlide(CUICDMSlideHandle inMaster, size_t inIndex) override;
+ size_t GetSlideCount(CUICDMSlideHandle inMaster) const override;
+ void RearrangeSlide(CUICDMSlideHandle inMaster, size_t inOldIndex, size_t inNewIndex) override;
+
+ void SetComponentSeconds(CUICDMSlideHandle inSlide, float inSeconds) override;
+ float GetComponentSeconds(CUICDMSlideHandle inSlide) const override;
+ long GetComponentSecondsLong(CUICDMSlideHandle inSlide) const override;
+ // For any given instance, find the current seconds via backtracking to the graph, finding the
+ // active
+ // slide, and return.
+ long GetComponentSecondsLong(CUICDMInstanceHandle inInstance) const override;
+ virtual SInstanceSlideInformation
+ GetInstanceSlideInformation(CUICDMInstanceHandle inInstance) const override;
+ /**
+ * Use the instance for storing information such as name, or the GUID of the object
+ * this slide links to.
+ */
+ CUICDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inInstance) const override;
+ /**
+ * Reverse lookup into the slide system so you can match slides to instances.
+ */
+ CUICDMSlideHandle GetSlideByInstance(CUICDMInstanceHandle inInstance) const override;
+
+ /**
+ * Slide may be either a master slide or a normal slide. This will associate this instance
+ * with this set of slides. Property lookups (using the above IInstancePropertyCore interface)
+ * will now run through the slide set before hitting the main data core database.
+ */
+ void AssociateInstanceWithSlide(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) override;
+ CUICDMSlideHandle GetAssociatedSlide(CUICDMInstanceHandle inInstance) const override;
+ void GetAssociatedInstances(
+ CUICDMSlideHandle inMaster,
+ std::vector<std::pair<CUICDMSlideHandle, CUICDMInstanceHandle>> &outAssociations) const override;
+ void GetAssociatedInstances(CUICDMSlideHandle inSlide,
+ TInstanceHandleList &outAssociations) const override;
+ void LinkProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override;
+ void UnlinkProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override;
+ bool IsPropertyLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ bool CanPropertyBeLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ bool GetSlidePropertyValue(size_t inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) override;
+ void GetUnionOfProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide,
+ TInstancePropertyPairList &outProperties) const override;
+
+ void SetActiveSlide(CUICDMSlideHandle inSlide) override;
+ CUICDMSlideHandle GetAssociatedSlide(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+
+ bool SlideValid(CUICDMSlideHandle inSlide) const override;
+ int GetSlideIndex(CUICDMSlideHandle inSlide) const override;
+ int GetActiveSlideIndex(CUICDMSlideHandle inMaster) const override;
+ CUICDMSlideHandle GetActiveSlide(CUICDMSlideHandle inMaster) const override;
+ CUICDMInstanceHandle GetSlideSelectedInstance(CUICDMSlideHandle inSlide) const override;
+ void SetSlideSelectedInstance(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance) override;
+
+ CUICDMSlideHandle GetApplicableSlide(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) override;
+
+ bool GetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ bool GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const override;
+ void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) override;
+
+ void RegisterPropertyInstance(CUICDMPropertyHandle inPropertyHandle,
+ TPropertyInstanceInfoPtr inPropertyInfo) override;
+
+ virtual ISlideSystemSignalProvider *GetSignalProvider();
+
+private:
+ virtual ISlideSystemSignalSender *GetSignalSender();
+ // helper method
+ void InsertEntryAndPropertyInstance(const TSlideEntry &inEntry,
+ TInstanceHandleList &inInstances,
+ CUICDMSlideHandle inSlide);
+ void DeleteReferencedInstances(CUICDMSlideHandle inSlide);
+ void GetReferencedInstances(CUICDMSlideHandle inSlide,
+ TInstanceHandleList &outReferencedInstances);
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/StandardExtensions.h b/src/Authoring/UICDM/Systems/StandardExtensions.h
new file mode 100644
index 00000000..de430e7e
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StandardExtensions.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef STANDARDEXTENSIONSH
+#define STANDARDEXTENSIONSH
+#include <algorithm>
+
+namespace UICDM {
+template <typename TContainer, typename TPred>
+inline void erase_if(TContainer &inContainer, TPred inPred)
+{
+ inContainer.erase(std::remove_if(inContainer.begin(), inContainer.end(), inPred),
+ inContainer.end());
+}
+
+template <typename TRetType, typename TContainerType, typename TPred>
+inline TRetType find_if(TContainerType &inContainer, TPred inPred)
+{
+ return std::find_if(inContainer.begin(), inContainer.end(), inPred);
+}
+
+template <typename TContainer, typename TTransaction>
+inline void do_all(TContainer &inContainer, TTransaction inTransaction)
+{
+ std::for_each(inContainer.begin(), inContainer.end(), inTransaction);
+}
+
+template <typename TNumType, typename TTransaction>
+inline void do_times(TNumType numberOfTimes, TTransaction inTransaction)
+{
+ for (TNumType index = 0; index < numberOfTimes; ++index)
+ inTransaction(index);
+}
+
+template <typename TCountFunc, typename TItemByIndexFunc, typename TTransaction>
+inline void for_each_item(TCountFunc inCountFunc, TItemByIndexFunc inItemByIndex,
+ TTransaction inTransaction)
+{
+ int theEnd = static_cast<int>(inCountFunc());
+ for (int index = 0; index < theEnd; ++index)
+ inTransaction(inItemByIndex(index));
+}
+
+template <typename TContainerType, typename TItemType>
+inline void insert_unique(TContainerType &inContainer, const TItemType &inItem)
+{
+ if (find(inContainer.begin(), inContainer.end(), inItem) == inContainer.end())
+ inContainer.insert(inContainer.end(), inItem);
+}
+
+template <typename TContainerType, typename TItemType, typename TPred>
+inline void insert_unique_if(TContainerType &inContainer, const TItemType &inItem, TPred inPred)
+{
+ if (find_if(inContainer.begin(), inContainer.end(), inPred) == inContainer.end())
+ inContainer.insert(inContainer.end(), inItem);
+}
+
+template <typename TItemType>
+inline TItemType identity(const TItemType &inValue)
+{
+ return inValue;
+}
+
+template <typename TItemType, typename TOutContainerType>
+inline void transformv_all(const std::vector<TItemType> &inSource, TOutContainerType &outDest)
+{
+ outDest.resize(inSource.size());
+ std::transform(inSource.begin(), inSource.end(), outDest.begin(), identity<TItemType>);
+}
+
+template <typename TContainerType, typename Pred>
+inline bool exists(TContainerType &inContainer, Pred inPredicate)
+{
+ return std::find_if(inContainer.begin(), inContainer.end(), inPredicate) != inContainer.end();
+}
+
+// Always return a default value (useful for default true for false)
+template <typename TRetType>
+inline TRetType always(TRetType inValue)
+{
+ return inValue;
+}
+
+template <typename TRetType, typename TIgnoreType>
+inline TRetType always_ignore(TIgnoreType, TRetType inValue)
+{
+ return inValue;
+}
+
+template <typename TArgument, typename TTransaction, typename TPredicate>
+inline void predicate_apply(TArgument inArgument, TTransaction inTransaction,
+ TPredicate inPredicate)
+{
+ if (inPredicate(inArgument))
+ inTransaction(inArgument);
+}
+
+template <typename TItemType>
+inline void assign_to(const TItemType &inSource, TItemType &inDest)
+{
+ inDest = inSource;
+}
+
+template <typename TPredType, typename TArgType>
+bool complement(TPredType inPredicate, TArgType inArgument)
+{
+ return !(inPredicate(inArgument));
+}
+
+template <typename TItemType, typename TPredicate>
+void insert_or_update(const TItemType &inItem, std::vector<TItemType> &inItems,
+ TPredicate inPredicate)
+{
+ typename std::vector<TItemType>::iterator theIter =
+ find_if<typename std::vector<TItemType>::iterator>(inItems, inPredicate);
+ if (theIter == inItems.end())
+ inItems.push_back(inItem);
+ else
+ *theIter = inItem;
+}
+
+template <typename TItemType>
+typename std::vector<TItemType>::iterator binary_sort_find(std::vector<TItemType> &inItems,
+ const TItemType &inItem)
+{
+ typedef typename std::vector<TItemType>::iterator TIterType;
+ TIterType insertPos = std::lower_bound(inItems.begin(), inItems.end(), inItem);
+ if (insertPos != inItems.end() && *insertPos == inItem)
+ return insertPos;
+ return inItems.end();
+}
+
+template <typename TItemType, typename TPredicate>
+std::pair<typename std::vector<TItemType>::iterator, bool>
+binary_sort_insert_unique(std::vector<TItemType> &inItems, const TItemType &inItem,
+ TPredicate inPredicate)
+{
+ typedef typename std::vector<TItemType>::iterator TIterType;
+ TIterType insertPos = std::lower_bound(inItems.begin(), inItems.end(), inItem, inPredicate);
+ // OK, insertPos can equal begin, it can equal end, or somewhere in between.
+ // If it doesn't equal end, then we may be pointing at the object and we let
+ // the caller figure out what to do. Else we insert
+ if (insertPos != inItems.end() && *insertPos == inItem)
+ return std::make_pair(insertPos, false);
+ size_t diff = insertPos - inItems.begin();
+ inItems.insert(insertPos, inItem);
+ return std::make_pair(inItems.begin() + diff, true);
+}
+
+template <typename TItemType>
+std::pair<typename std::vector<TItemType>::iterator, bool>
+binary_sort_insert_unique(std::vector<TItemType> &inItems, const TItemType &inItem)
+{
+ return binary_sort_insert_unique(inItems, inItem, std::less<TItemType>());
+}
+
+template <typename TItemType>
+bool binary_sort_erase(std::vector<TItemType> &inItems, const TItemType &inItem)
+{
+ typedef typename std::vector<TItemType>::iterator TIterType;
+ TIterType insertPos = binary_sort_find(inItems, inItem);
+ if (insertPos != inItems.end()) {
+ inItems.erase(insertPos);
+ return true;
+ }
+ return false;
+}
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/StudioAnimationSystem.cpp b/src/Authoring/UICDM/Systems/StudioAnimationSystem.cpp
new file mode 100644
index 00000000..206f13bd
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioAnimationSystem.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "StudioAnimationSystem.h"
+#include "StudioPropertySystem.h"
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/bind.hpp>
+
+using namespace std;
+using namespace boost;
+
+namespace UICDM {
+
+bool AnimationFloatPairContainsAnimation(CUICDMAnimationHandle inAnimation,
+ const TAnimationFloatPair &inPair)
+{
+ return inAnimation == inPair.first;
+}
+
+CStudioAnimationSystem::CStudioAnimationSystem(TPropertySystemPtr inPropertySystem,
+ TSlideSystemPtr inSlideSystem,
+ TSlideCorePtr inSlideCore,
+ TSlideGraphCorePtr inSlideGraphCore,
+ TAnimationCorePtr inAnimationCore)
+ : m_PropertySystem(inPropertySystem)
+ , m_SlideSystem(inSlideSystem)
+ , m_SlideCore(inSlideCore)
+ , m_SlideGraphCore(inSlideGraphCore)
+ , m_AnimationCore(inAnimationCore)
+ , m_AutoKeyframe(false)
+ , m_SmoothInterpolation(false)
+{
+ IAnimationCoreSignalProvider *theAnimationSignals =
+ dynamic_cast<IAnimationCoreSignalProvider *>(m_AnimationCore.get());
+ m_Connections.push_back(theAnimationSignals->ConnectAnimationDeleted(
+ std::bind(&CStudioAnimationSystem::OnAnimationDeleted, this, std::placeholders::_1)));
+}
+
+void CStudioAnimationSystem::OnAnimationDeleted(CUICDMAnimationHandle inAnimation)
+{
+ ClearTemporaryAnimationValues(inAnimation);
+}
+
+void CStudioAnimationSystem::ClearTemporaryAnimationValues()
+{
+ m_AnimationFloatPairs.clear();
+}
+
+void CStudioAnimationSystem::ClearTemporaryAnimationValues(CUICDMAnimationHandle inAnimation)
+{
+ erase_if(m_AnimationFloatPairs,
+ std::bind(AnimationFloatPairContainsAnimation, inAnimation, std::placeholders::_1));
+}
+
+inline bool IsAnimationInfoEqual(const SAnimationInfo &inInfo, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty)
+{
+ if (inInfo.m_Slide == inSlide && inInfo.m_Instance == inInstance
+ && inInfo.m_Property == inProperty)
+ return true;
+ return false;
+}
+inline bool IsAnimationInfoEqual(const SAnimationInfo &inInfo, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ size_t inIndex)
+{
+ if (IsAnimationInfoEqual(inInfo, inSlide, inInstance, inProperty) && inInfo.m_Index == inIndex)
+ return true;
+ return false;
+}
+
+inline bool ApplyIfAnimationMatches(TAnimationFloatPair inAnimationFloatPair,
+ CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ TAnimationCorePtr inAnimationCore, SValue &outValue)
+{
+ SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimationFloatPair.first);
+ if (IsAnimationInfoEqual(theInfo, inSlide, inInstance, inProperty)) {
+ SetAnimationValue(inAnimationFloatPair.second, theInfo.m_Index, outValue);
+ return true;
+ }
+ return false;
+}
+
+void CStudioAnimationSystem::OverrideChannelIfAnimated(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ size_t inIndex, float inSeconds,
+ bool &ioAnimated, SValue &outValue) const
+{
+ CUICDMAnimationHandle theAnimation =
+ m_AnimationCore->GetAnimation(inSlide, inInstance, inProperty, inIndex);
+ if (theAnimation.Valid() && m_AnimationCore->GetKeyframeCount(theAnimation)) {
+ float theValue = m_AnimationCore->EvaluateAnimation(theAnimation, inSeconds);
+ SetAnimationValue(theValue, inIndex, outValue);
+ ioAnimated |= true;
+ }
+}
+
+// Value must be *primed* first.
+bool CStudioAnimationSystem::GetAnimatedInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ bool retval = false;
+
+ tuple<bool, size_t> arity = GetVariantAnimatableAndArity(outValue);
+ if (get<0>(arity)) {
+ for (size_t index = 0; index < m_AnimationFloatPairs.size(); ++index)
+ retval |= ApplyIfAnimationMatches(m_AnimationFloatPairs.at(index), inSlide, inInstance,
+ inProperty, m_AnimationCore, outValue);
+ }
+
+ if (!retval) {
+ bool animatable;
+ size_t numChannels;
+ bool animated = false;
+
+ std::tie(animatable, numChannels) = GetVariantAnimatableAndArity(outValue);
+ if (animatable) {
+ TGraphSlidePair theGraphSlidePair = m_SlideGraphCore->GetAssociatedGraph(inInstance);
+ float theSeconds = m_SlideCore->GetSlideTime(
+ m_SlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first));
+
+ do_times(numChannels, std::bind(&CStudioAnimationSystem::OverrideChannelIfAnimated,
+ this, inSlide, inInstance, inProperty,
+ std::placeholders::_1, theSeconds,
+ std::ref(animated), std::ref(outValue)));
+ }
+
+ if (animated)
+ retval = true;
+ }
+
+ return retval;
+}
+
+bool KeyframeNear(const TKeyframe &inKeyframe, float inSeconds)
+{
+ return fabs(KeyframeTime(inKeyframe) - inSeconds) < .01;
+}
+CUICDMKeyframeHandle CreateKeyframeExplicit(CUICDMAnimationHandle inAnimation, float inValue,
+ float inSeconds, TAnimationCorePtr inAnimationCore,
+ float inEaseIn, float inEaseOut)
+{
+ TKeyframeHandleList theKeyframes;
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ float theValue = inValue;
+ inAnimationCore->GetKeyframes(inAnimation, theKeyframes);
+ function<TKeyframe(CUICDMKeyframeHandle)> theConverter(
+ std::bind(&IAnimationCore::GetKeyframeData, inAnimationCore, std::placeholders::_1));
+
+ //TODO no transform iterator in STL
+ typedef transform_iterator<function<TKeyframe(CUICDMKeyframeHandle)>,
+ TKeyframeHandleList::iterator>
+ TKeyframeDataTransformIterator;
+ TKeyframeDataTransformIterator theFind =
+ find_if(make_transform_iterator(theKeyframes.begin(), theConverter),
+ make_transform_iterator(theKeyframes.end(), theConverter),
+ std::bind(KeyframeNear, std::placeholders::_1, inSeconds));
+
+ float theEaseIn = inEaseIn;
+ float theEaseOut = inEaseOut;
+ CUICDMKeyframeHandle theKeyframe;
+ if (theFind.base() != theKeyframes.end()) {
+ theKeyframe = *theFind.base();
+
+ inAnimationCore->SetKeyframeData(
+ theKeyframe, CreateEaseInEaseOutKeyframe(inSeconds, theValue, theEaseIn, theEaseOut));
+ } else {
+ theKeyframe = inAnimationCore->InsertKeyframe(
+ inAnimation, CreateEaseInEaseOutKeyframe(inSeconds, theValue, theEaseIn, theEaseOut));
+ }
+ return theKeyframe;
+}
+
+CUICDMKeyframeHandle CreateKeyframe(CUICDMAnimationHandle inAnimation, const SValue &inValue,
+ float inSeconds, TAnimationCorePtr inAnimationCore,
+ float inEaseIn, float inEaseOut)
+{
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ return CreateKeyframeExplicit(inAnimation, GetAnimationValue(theInfo.m_Index, inValue),
+ inSeconds, inAnimationCore, inEaseIn, inEaseOut);
+}
+
+void MaybeAddAnimation(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations)
+{
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ if (IsAnimationInfoEqual(theInfo, inSlide, inInstance, inProperty))
+ outAnimations.push_back(inAnimation);
+}
+
+bool SortAnimationHandlesByIndex(CUICDMAnimationHandle lhs, CUICDMAnimationHandle rhs,
+ TAnimationCorePtr inCore)
+{
+ return inCore->GetAnimationInfo(lhs).m_Index < inCore->GetAnimationInfo(rhs).m_Index;
+}
+
+void GetPresentAnimations(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const TAnimationFloatPairList &inAnimationPairs,
+ TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations)
+{
+ function<CUICDMAnimationHandle(TAnimationFloatPair)> theTransform(
+ std::bind(&TAnimationFloatPair::first, std::placeholders::_1));
+ function<void(CUICDMAnimationHandle)> theOperation(
+ std::bind(MaybeAddAnimation, inSlide, inInstance, inProperty,
+ std::placeholders::_1, inAnimationCore,
+ std::ref(outAnimations)));
+
+ for_each(boost::make_transform_iterator(inAnimationPairs.begin(), theTransform),
+ boost::make_transform_iterator(inAnimationPairs.end(), theTransform), theOperation);
+
+ if (outAnimations.empty()) {
+ TAnimationHandleList theAnimationHandles;
+ inAnimationCore->GetAnimations(theAnimationHandles);
+ do_all(theAnimationHandles, theOperation);
+ }
+ std::sort(outAnimations.begin(), outAnimations.end(),
+ std::bind(SortAnimationHandlesByIndex,
+ std::placeholders::_1, std::placeholders::_2, inAnimationCore));
+}
+
+void CreateAnimationAndAdd(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ TAnimationCorePtr inAnimationCore, TAnimationHandleList &outAnimations)
+{
+ outAnimations.push_back(inAnimationCore->CreateAnimation(
+ inSlide, inInstance, inProperty, inIndex, EAnimationTypeEaseInOut, false));
+}
+
+bool AnimationValueDiffers(CUICDMAnimationHandle inAnimation, const SValue &inValue,
+ float inSeconds, TAnimationCorePtr inAnimationCore)
+{
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ if (inAnimationCore->GetKeyframeCount(inAnimation) == 0)
+ return true; // currently there is no keyframe, so return true
+ float theValue = GetAnimationValue(theInfo.m_Index, inValue);
+ float theAnimatedValue = inAnimationCore->EvaluateAnimation(inAnimation, inSeconds);
+ return fabs(theValue - theAnimatedValue) > .001;
+}
+
+bool AnimationExistsInPresentAnimations(const TAnimationFloatPair &inAnimation,
+ TAnimationHandleList &inPresentAnimations)
+{
+ return exists(inPresentAnimations,
+ std::bind(equal_to<CUICDMAnimationHandle>(), inAnimation.first,
+ std::placeholders::_1));
+}
+
+void DoKeyframeProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue, float inTimeInSecs,
+ bool inDoDiffValue, TAnimationCorePtr inAnimationCore,
+ TAnimationFloatPairList &inAnimationFloatPairs, float inEaseIn,
+ float inEaseOut)
+{
+ tuple<bool, size_t> arity = GetVariantAnimatableAndArity(inValue);
+ TAnimationHandleList thePresentAnimations;
+ GetPresentAnimations(inSlide, inInstance, inProperty, std::cref(inAnimationFloatPairs),
+ inAnimationCore, thePresentAnimations);
+ if (thePresentAnimations.empty())
+ do_times(get<1>(arity), std::bind(CreateAnimationAndAdd, inSlide, inInstance, inProperty,
+ std::placeholders::_1,
+ inAnimationCore, std::ref(thePresentAnimations)));
+ if (!inDoDiffValue
+ || find_if(thePresentAnimations.begin(), thePresentAnimations.end(),
+ std::bind(AnimationValueDiffers,
+ std::placeholders::_1, inValue, inTimeInSecs, inAnimationCore))
+ != thePresentAnimations.end()) {
+ do_all(thePresentAnimations,
+ std::bind(CreateKeyframe, std::placeholders::_1,
+ std::cref(inValue), inTimeInSecs, inAnimationCore,
+ inEaseIn, inEaseOut));
+ erase_if(inAnimationFloatPairs, std::bind(AnimationExistsInPresentAnimations,
+ std::placeholders::_1,
+ std::ref(thePresentAnimations)));
+ }
+}
+
+void DoKeyframeProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue, bool inDoDiffValue,
+ TAnimationCorePtr inAnimationCore, TSlideGraphCorePtr inSlideGraphCore,
+ TSlideCorePtr inSlideCore, TAnimationFloatPairList &inAnimationFloatPairs,
+ float inEaseIn, float inEaseOut)
+{
+ TGraphSlidePair theGraphSlidePair = inSlideGraphCore->GetAssociatedGraph(inInstance);
+ float theCurrentTime =
+ inSlideCore->GetSlideTime(inSlideGraphCore->GetGraphActiveSlide(theGraphSlidePair.first));
+ DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, theCurrentTime, inDoDiffValue,
+ inAnimationCore, inAnimationFloatPairs, inEaseIn, inEaseOut);
+}
+
+void DoKeyframeProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue, bool inDoDiffValue,
+ TAnimationCorePtr inAnimationCore, TSlideGraphCorePtr inSlideGraphCore,
+ TSlideCorePtr inSlideCore, TAnimationFloatPairList &inAnimationFloatPairs,
+ bool inSmoothInterpolation)
+{
+ float theEaseIn = 0.0f, theEaseOut = 0.0f;
+ if (inSmoothInterpolation)
+ theEaseIn = theEaseOut = 100.f;
+ DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, inDoDiffValue, inAnimationCore,
+ inSlideGraphCore, inSlideCore, inAnimationFloatPairs, theEaseIn, theEaseOut);
+}
+
+TAnimationFloatPair CreateAnimationFloatPair(CUICDMAnimationHandle inAnimation,
+ const SValue &inValue,
+ TAnimationCorePtr inAnimationCore)
+{
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ float theValue = GetAnimationValue(theInfo.m_Index, inValue);
+ return make_pair(inAnimation, theValue);
+}
+
+void InsertUniqueAnimationFloatPair(CUICDMAnimationHandle inAnimation,
+ TAnimationFloatPairList &inList, const SValue &inValue,
+ TAnimationCorePtr inAnimationCore)
+{
+ TAnimationFloatPair thePair = CreateAnimationFloatPair(inAnimation, inValue, inAnimationCore);
+ insert_or_update(thePair, inList,
+ std::bind(AnimationFloatPairContainsAnimation, inAnimation, std::placeholders::_1));
+}
+
+bool CStudioAnimationSystem::SetAnimatedInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ tuple<bool, size_t> arity = GetVariantAnimatableAndArity(inValue);
+ if (get<0>(arity)) {
+ if (m_AutoKeyframe && IsPropertyAnimated(inInstance, inProperty)) // prerequisite for
+ // autoset-keyframes is
+ // that the property is
+ // already animated.
+ {
+ DoKeyframeProperty(inSlide, inInstance, inProperty, inValue, true, m_AnimationCore,
+ m_SlideGraphCore, m_SlideCore, m_AnimationFloatPairs,
+ m_SmoothInterpolation);
+ return true;
+ }
+
+ TAnimationHandleList thePresentAnimations;
+ GetPresentAnimations(inSlide, inInstance, inProperty, std::cref(m_AnimationFloatPairs),
+ m_AnimationCore, thePresentAnimations);
+ if (!thePresentAnimations.empty()) {
+ TAnimationFloatPairList thePreList(m_AnimationFloatPairs);
+ do_all(thePresentAnimations, std::bind(InsertUniqueAnimationFloatPair, std::placeholders::_1,
+ std::ref(m_AnimationFloatPairs),
+ std::cref(inValue), m_AnimationCore));
+ CreateGenericTransactionWithConsumer(
+ __FILE__, __LINE__, m_Consumer,
+ std::bind(assign_to<TAnimationFloatPairList>, m_AnimationFloatPairs,
+ std::ref(m_AnimationFloatPairs)),
+ std::bind(assign_to<TAnimationFloatPairList>, thePreList,
+ std::ref(m_AnimationFloatPairs)));
+ return true;
+ }
+ }
+ return false;
+}
+
+void CStudioAnimationSystem::SetAutoKeyframe(bool inAutoKeyframe)
+{
+ m_AutoKeyframe = inAutoKeyframe;
+}
+bool CStudioAnimationSystem::GetAutoKeyframe() const
+{
+ return m_AutoKeyframe;
+}
+
+CUICDMSlideHandle CStudioAnimationSystem::GetApplicableGraphAndSlide(
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty, const SValue &inValue)
+{
+ CUICDMSlideHandle theApplicableSlide;
+ tuple<bool, size_t> arity = GetVariantAnimatableAndArity(inValue);
+ if (get<0>(arity))
+ theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty);
+ return theApplicableSlide;
+}
+
+void InsertUniqueAnimationKeyframesPair(TAnimationKeyframesPairList &ioList, SAnimationInfo &inInfo,
+ TKeyframeList &inKeyframes)
+{
+ bool theFound = false;
+ for (TAnimationKeyframesPairList::iterator theAnimationKeyframeIter = ioList.begin();
+ theAnimationKeyframeIter < ioList.end(); ++theAnimationKeyframeIter) {
+ if (IsAnimationInfoEqual(theAnimationKeyframeIter->first, inInfo.m_Slide, inInfo.m_Instance,
+ inInfo.m_Property, inInfo.m_Index)) {
+ theFound = true;
+ // Overwrite the existing value
+ SAnimationInfo &theInfo = theAnimationKeyframeIter->first;
+ theInfo.m_AnimationType = inInfo.m_AnimationType;
+ theInfo.m_DynamicFirstKeyframe = inInfo.m_DynamicFirstKeyframe;
+ theAnimationKeyframeIter->second = inKeyframes;
+ break;
+ }
+ }
+ if (!theFound) {
+ ioList.push_back(std::make_pair(inInfo, inKeyframes));
+ }
+}
+
+void CStudioAnimationSystem::Animate(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ SValue theValue;
+ m_PropertySystem->GetInstancePropertyValue(inInstance, inProperty, theValue);
+ CUICDMSlideHandle theApplicableSlide =
+ GetApplicableGraphAndSlide(inInstance, inProperty, theValue.toOldSkool());
+ if (theApplicableSlide.Valid()) {
+ // Check if previously we have set animation & keyframes
+ DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty);
+ std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType);
+ bool theFound = false;
+ for (size_t i = 0; i < std::get<1>(theArity); ++i) {
+ TAnimationKeyframesPairList::iterator theAnimationKeyframeIter =
+ m_DeletedAnimationData.begin();
+ for (; theAnimationKeyframeIter < m_DeletedAnimationData.end();
+ ++theAnimationKeyframeIter) {
+ if (IsAnimationInfoEqual(theAnimationKeyframeIter->first, theApplicableSlide,
+ inInstance, inProperty, i)) {
+ theFound = true;
+
+ // We use previously set animation & keyframes to create new animation &
+ // keyframe
+ SAnimationInfo &theInfo = theAnimationKeyframeIter->first;
+ CUICDMAnimationHandle theAnimation = m_AnimationCore->CreateAnimation(
+ theInfo.m_Slide, theInfo.m_Instance, theInfo.m_Property, theInfo.m_Index,
+ theInfo.m_AnimationType, theInfo.m_DynamicFirstKeyframe);
+
+ TKeyframeList theKeyframes = theAnimationKeyframeIter->second;
+ for (TKeyframeList::const_iterator theKeyframeIter = theKeyframes.begin();
+ theKeyframeIter < theKeyframes.end(); ++theKeyframeIter)
+ m_AnimationCore->InsertKeyframe(theAnimation, *theKeyframeIter);
+
+ break;
+ }
+ }
+ }
+
+ if (!theFound)
+ DoKeyframeProperty(theApplicableSlide, inInstance, inProperty, theValue.toOldSkool(),
+ true, m_AnimationCore, m_SlideGraphCore, m_SlideCore,
+ m_AnimationFloatPairs, m_SmoothInterpolation);
+ }
+}
+
+void CStudioAnimationSystem::Deanimate(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty);
+ std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType);
+ for (size_t i = 0; i < std::get<1>(theArity); ++i) {
+ CUICDMAnimationHandle theAnimationHandle =
+ GetControllingAnimation(inInstance, inProperty, i);
+
+ if (theAnimationHandle.Valid()) {
+ // Get animation & keyframe data and save it
+ SAnimationInfo theInfo(m_AnimationCore->GetAnimationInfo(theAnimationHandle));
+ TKeyframeHandleList theKeyframeHandles;
+ m_AnimationCore->GetKeyframes(theAnimationHandle, theKeyframeHandles);
+ TKeyframeList theKeyframeList;
+ for (TKeyframeHandleList::const_iterator theKeyframeIter = theKeyframeHandles.begin();
+ theKeyframeIter < theKeyframeHandles.end(); ++theKeyframeIter)
+ theKeyframeList.push_back(m_AnimationCore->GetKeyframeData(*theKeyframeIter));
+ InsertUniqueAnimationKeyframesPair(m_DeletedAnimationData, theInfo, theKeyframeList);
+
+ // Delete the animation
+ m_AnimationCore->DeleteAnimation(theAnimationHandle);
+ }
+ }
+}
+
+void CStudioAnimationSystem::KeyframeProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, bool inDoDiffValue)
+{
+ SValue theValue;
+ m_PropertySystem->GetInstancePropertyValue(inInstance, inProperty, theValue);
+ CUICDMSlideHandle theApplicableSlide =
+ GetApplicableGraphAndSlide(inInstance, inProperty, theValue.toOldSkool());
+ if (theApplicableSlide.Valid())
+ DoKeyframeProperty(theApplicableSlide, inInstance, inProperty, theValue.toOldSkool(),
+ inDoDiffValue, m_AnimationCore, m_SlideGraphCore, m_SlideCore,
+ m_AnimationFloatPairs, m_SmoothInterpolation);
+}
+void CStudioAnimationSystem::SetOrCreateKeyframe(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ float inTimeInSeconds,
+ SGetOrSetKeyframeInfo *inKeyframeInfo,
+ size_t inNumInfos)
+{
+ UICDM::DataModelDataType::Value thePropertyType = m_PropertySystem->GetDataType(inProperty);
+ CUICDMSlideHandle theApplicableSlide;
+ std::tuple<bool, size_t> arity = GetDatatypeAnimatableAndArity(thePropertyType);
+ if (std::get<0>(arity)) {
+ theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty);
+ if (theApplicableSlide.Valid()) {
+
+ TAnimationHandleList thePresentAnimations;
+ GetPresentAnimations(theApplicableSlide, inInstance, inProperty,
+ std::cref(m_AnimationFloatPairs), m_AnimationCore,
+ thePresentAnimations);
+ size_t numIterations = std::min(inNumInfos, get<1>(arity));
+ if (thePresentAnimations.empty()) {
+ for (size_t idx = 0, end = numIterations; idx < end; ++idx) {
+ CreateAnimationAndAdd(theApplicableSlide, inInstance, inProperty, idx,
+ m_AnimationCore, thePresentAnimations);
+ }
+ }
+ for (size_t idx = 0, end = numIterations; idx < end; ++idx) {
+ CreateKeyframeExplicit(thePresentAnimations[idx], inKeyframeInfo[idx].m_Value,
+ inTimeInSeconds, m_AnimationCore,
+ inKeyframeInfo[idx].m_EaseIn, inKeyframeInfo[idx].m_EaseOut);
+ if (inKeyframeInfo[idx].m_AnimationTrackIsDynamic)
+ m_AnimationCore->SetFirstKeyframeDynamic(thePresentAnimations[idx], true);
+ }
+ erase_if(m_AnimationFloatPairs, std::bind(AnimationExistsInPresentAnimations,
+ std::placeholders::_1,
+ std::ref(thePresentAnimations)));
+ }
+ }
+}
+
+inline bool FindMatchingAnimation(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore, size_t inIndex)
+{
+ return inAnimationCore->GetAnimationInfo(inAnimation).m_Index == inIndex;
+}
+
+CUICDMAnimationHandle CStudioAnimationSystem::GetControllingAnimation(
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty, size_t inIndex) const
+{
+ CUICDMSlideHandle theApplicableSlide =
+ m_SlideSystem->GetApplicableSlide(inInstance, inProperty);
+ // first check our anim float pairs
+ for (size_t idx = 0, end = m_AnimationFloatPairs.size(); idx < end; ++idx) {
+ const SAnimationInfo &theInfo =
+ m_AnimationCore->GetAnimationInfo(m_AnimationFloatPairs[idx].first);
+ if (IsAnimationInfoEqual(theInfo, theApplicableSlide, inInstance, inProperty, inIndex))
+ return m_AnimationFloatPairs[idx].first;
+ }
+ // Use the cache lookup instead of linear search algorithm
+ return m_AnimationCore->GetAnimation(theApplicableSlide, inInstance, inProperty, inIndex);
+}
+
+bool CStudioAnimationSystem::IsPropertyAnimatable(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty);
+ std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType);
+ if (std::get<0>(theArity))
+ return m_SlideGraphCore->GetAssociatedGraph(inInstance).first.Valid();
+ return false;
+}
+
+bool CStudioAnimationSystem::IsPropertyAnimated(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ DataModelDataType::Value theDataType = m_PropertySystem->GetDataType(inProperty);
+ std::tuple<bool, size_t> theArity = GetDatatypeAnimatableAndArity(theDataType);
+ for (size_t i = 0; i < std::get<1>(theArity); ++i) {
+ if (GetControllingAnimation(inInstance, inProperty, i).Valid())
+ return true;
+ }
+ return false;
+}
+
+void CStudioAnimationSystem::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_Consumer = inConsumer;
+}
+}
diff --git a/src/Authoring/UICDM/Systems/StudioAnimationSystem.h b/src/Authoring/UICDM/Systems/StudioAnimationSystem.h
new file mode 100644
index 00000000..29e3bd63
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioAnimationSystem.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef STUDIOANIMATIONSYSTEMIMPLH
+#define STUDIOANIMATIONSYSTEMIMPLH
+
+#include "UICDMAnimation.h"
+#include "UICDMSlides.h"
+#include "UICDMSlideCore.h"
+#include "UICDMSlideGraphCore.h"
+#include "UICDMTransactions.h"
+#include "UICDMDataCore.h"
+#include "UICDMSignals.h"
+
+namespace UICDM {
+
+typedef std::pair<CUICDMAnimationHandle, float> TAnimationFloatPair;
+typedef std::vector<TAnimationFloatPair> TAnimationFloatPairList;
+
+class CStudioAnimationSystem : public IStudioAnimationSystem,
+ public ITransactionProducer
+{
+ Q_DISABLE_COPY(CStudioAnimationSystem)
+
+ TPropertySystemPtr m_PropertySystem;
+ TSlideSystemPtr m_SlideSystem;
+ TSlideCorePtr m_SlideCore;
+ TSlideGraphCorePtr m_SlideGraphCore;
+ TAnimationCorePtr m_AnimationCore;
+
+ bool m_AutoKeyframe;
+ // When a property has an animation associated with it, then writes
+ // do not go all the way down to the db. They stay on this object.
+ TAnimationFloatPairList m_AnimationFloatPairs;
+ bool m_SmoothInterpolation;
+
+ TAnimationKeyframesPairList m_DeletedAnimationData; // list to store deanimated animation &
+ // keyframe data. This will be use if user
+ // wants to animate the same property again
+
+ TTransactionConsumerPtr m_Consumer;
+
+ std::vector<std::shared_ptr<ISignalConnection>> m_Connections;
+
+public:
+ CStudioAnimationSystem(TPropertySystemPtr inPropertySystem, TSlideSystemPtr inSlideSystem,
+ TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore,
+ TAnimationCorePtr inAnimationCore);
+
+ void ClearTemporaryAnimationValues();
+ void ClearTemporaryAnimationValues(CUICDMAnimationHandle inAnimation);
+
+ void SetPropertySystem(TPropertySystemPtr inPropertySystem)
+ {
+ m_PropertySystem = inPropertySystem;
+ } // HACK: TODO: We should really consider having all the subsytem know everyone else without
+ // passing in so many things in the constructor
+
+ //====================================================================
+ // IStudioAnimationSystem implementation
+ //====================================================================
+ void SetAutoKeyframe(bool inAutoKeyframe) override;
+ bool GetAutoKeyframe() const override;
+ void Animate(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override;
+ void Deanimate(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override;
+ void KeyframeProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inDoDiffValue) override;
+ void SetOrCreateKeyframe(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, float inTimeInSeconds,
+ SGetOrSetKeyframeInfo *inKeyframeInfo, size_t inNumInfos) override;
+ CUICDMAnimationHandle GetControllingAnimation(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ size_t inIndex) const override;
+ bool IsPropertyAnimatable(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ bool IsPropertyAnimated(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ void SetInterpolation(bool inSmooth) override { m_SmoothInterpolation = inSmooth; }
+
+ bool GetAnimatedInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const override;
+ bool SetAnimatedInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) override;
+ //====================================================================
+
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+
+private:
+ void OnAnimationDeleted(CUICDMAnimationHandle inAnimation);
+
+ CUICDMSlideHandle GetApplicableGraphAndSlide(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue);
+
+ void OverrideChannelIfAnimated(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex, float inSeconds,
+ bool &ioAnimated, SValue &outValue) const;
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/StudioCoreSystem.cpp b/src/Authoring/UICDM/Systems/StudioCoreSystem.cpp
new file mode 100644
index 00000000..c8ab4337
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioCoreSystem.cpp
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "StudioCoreSystem.h"
+#include "SlideCoreProducer.h"
+#include "SlideGraphCoreProducer.h"
+#include "DataCoreProducer.h"
+#include "AnimationCoreProducer.h"
+#include "ActionCoreProducer.h"
+#include "UICDMSignals.h"
+#include "UICDMMetaData.h"
+#include "UICDMGuides.h"
+
+using namespace std;
+
+namespace UICDM {
+
+inline bool AnimationInstanceMatches(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore,
+ CUICDMInstanceHandle inInstance)
+{
+ return inInstance == inAnimationCore->GetAnimationInfo(inAnimation).m_Instance;
+}
+
+inline bool AnimationPropertyMatches(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore,
+ CUICDMPropertyHandle inProperty)
+{
+ return inProperty == inAnimationCore->GetAnimationInfo(inAnimation).m_Property;
+}
+
+inline bool AnimationSlideMatches(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore, CUICDMSlideHandle inSlide)
+{
+ return inSlide == inAnimationCore->GetAnimationInfo(inAnimation).m_Slide;
+}
+
+inline bool AnimationSlideInstancePropertyMatch(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore,
+ CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimation);
+ return theInfo.m_Slide == inSlide && theInfo.m_Instance == inInstance
+ && theInfo.m_Property == inProperty;
+}
+
+inline bool AnimationInstancesPropertiesMatch(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore,
+ const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties)
+{
+ SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimation);
+ return exists(inInstances, std::bind(equal_to<int>(), theInfo.m_Instance,
+ std::placeholders::_1))
+ && exists(inProperties, std::bind(equal_to<int>(), theInfo.m_Property,
+ std::placeholders::_1));
+}
+
+void EraseAnimationsThatMatch(TAnimationCorePtr inAnimationCore,
+ function<bool(CUICDMAnimationHandle)> inPredicate)
+{
+ TAnimationHandleList theAnimations;
+ inAnimationCore->GetAnimations(theAnimations);
+ function<bool(CUICDMAnimationHandle)> theComp(std::bind(
+ complement<function<bool(CUICDMAnimationHandle)>, CUICDMAnimationHandle>, inPredicate,
+ std::placeholders::_1));
+ TAnimationHandleList::iterator theRemovals =
+ remove_if(theAnimations.begin(), theAnimations.end(), theComp);
+ for_each(theAnimations.begin(), theRemovals,
+ std::bind(&IAnimationCore::DeleteAnimation, inAnimationCore, std::placeholders::_1));
+}
+
+void EraseActions(TDataCorePtr inDataCore, TActionCorePtr inActionCore,
+ const TActionHandleList &inActions)
+{
+ for (TActionHandleList::const_iterator theActionIter = inActions.begin();
+ theActionIter != inActions.end(); ++theActionIter) {
+ CUICDMInstanceHandle theActionInstance;
+ inActionCore->DeleteAction(*theActionIter, theActionInstance);
+ inDataCore->DeleteInstance(theActionInstance);
+ }
+}
+
+void CascadeInstanceDelete(CUICDMInstanceHandle inInstance, TDataCorePtr inDataCore,
+ TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore,
+ TAnimationCorePtr inAnimationCore, TActionCorePtr inActionCore)
+{
+ inSlideCore->DeleteAllInstanceEntries(inInstance);
+
+ inSlideGraphCore->DissociateInstance(inInstance);
+
+ function<bool(CUICDMAnimationHandle)> thePredicate(
+ std::bind(AnimationInstanceMatches, std::placeholders::_1, inAnimationCore, inInstance));
+ EraseAnimationsThatMatch(inAnimationCore, thePredicate);
+
+ TActionHandleList theActions;
+ inActionCore->GetActions(inInstance, theActions);
+ EraseActions(inDataCore, inActionCore, theActions);
+}
+
+void CascadePropertyRemove(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore,
+ TAnimationCorePtr inAnimationCore)
+{
+ inSlideCore->DeleteAllPropertyEntries(inProperty);
+ function<bool(CUICDMAnimationHandle)> thePredicate(
+ std::bind(AnimationPropertyMatches, std::placeholders::_1, inAnimationCore, inProperty));
+ EraseAnimationsThatMatch(inAnimationCore, thePredicate);
+}
+
+void CascadeSlideDelete(CUICDMSlideHandle inSlide, TDataCorePtr inDataCore,
+ TSlideCorePtr inSlideCore, TSlideGraphCorePtr inSlideGraphCore,
+ TAnimationCorePtr inAnimationCore, TActionCorePtr inActionCore)
+{
+ CUICDMSlideGraphHandle theGraph = inSlideGraphCore->GetSlideGraph(inSlide);
+ if (theGraph.Valid()) {
+ TSlideHandleList theChildren;
+ inSlideCore->GetChildSlides(inSlide, theChildren);
+ TInstanceHandleList instances;
+ for (size_t idx = 0, end = theChildren.size(); idx < end; ++idx) {
+ instances.clear();
+ inSlideCore->DeleteSlide(theChildren[idx], instances);
+ for (size_t instIdx = 0, instEnd = instances.size(); instIdx < instEnd; ++instIdx)
+ inDataCore->DeleteInstance(instances[instIdx]);
+ }
+ inSlideGraphCore->DeleteSlideGraph(theGraph);
+ }
+
+ else {
+ CUICDMSlideHandle theMaster(inSlideCore->GetParentSlide(inSlide));
+ if (theMaster.Valid()) {
+ CUICDMSlideGraphHandle theGraph = inSlideGraphCore->GetSlideGraph(theMaster);
+ if (theGraph.Valid()) {
+ /*
+ tricky stuff. The slide change was recorded in the transaction system when the
+ slide was created. But since there didn't *have* to be a slide change when the
+ slide was destroyed there was no slide change recorded at that point.
+
+ Then on the first redo, the system quietly switched the active slide to the new
+ slide. On the second redo the system crashed due to attempting to access the
+ new slide after it had been deleted (as nothing switched the system back to the
+ current slide).
+
+ So the correct answer is that the cascading system needs to *always* set the
+ active slide, even if it seems like it would be, at the moment, unnecessary
+ because the slide getting deleted is not currently active. This is the mirror
+ of the fact that new slide *always* sets the active slide so it does make
+ logical sense.*/
+ CUICDMSlideHandle theNewActiveSlide =
+ inSlideGraphCore->GetGraphActiveSlide(theGraph);
+ if (theNewActiveSlide == inSlide) {
+ TSlideHandleList theChildren;
+ inSlideCore->GetChildSlides(theMaster, theChildren);
+ size_t idx = 0;
+ for (size_t end = theChildren.size(); idx < end; ++idx) {
+ if (theChildren[idx] != inSlide) {
+ theNewActiveSlide = theChildren[idx];
+ break;
+ }
+ }
+ if (theNewActiveSlide == inSlide)
+ theNewActiveSlide = theMaster;
+ }
+ inSlideGraphCore->SetGraphActiveSlide(theGraph, theNewActiveSlide);
+ }
+ }
+ }
+ EraseAnimationsThatMatch(inAnimationCore,
+ std::bind(AnimationSlideMatches,
+ std::placeholders::_1, inAnimationCore, inSlide));
+
+ TActionHandleList theActions;
+ inActionCore->GetActions(inSlide, theActions);
+ EraseActions(inDataCore, inActionCore, theActions);
+}
+
+void CascadeSlidePropertyRemove(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, TAnimationCorePtr inAnimationCore)
+{
+ EraseAnimationsThatMatch(inAnimationCore,
+ std::bind(AnimationSlideInstancePropertyMatch,
+ std::placeholders::_1, inAnimationCore,
+ inSlide, inInstance, inProperty));
+}
+
+void CascadeInstanceParentRemoved(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent,
+ TDataCorePtr inDataCore, TSlideCorePtr inSlideCore,
+ TAnimationCorePtr inAnimationCore)
+{
+ TPropertyHandleList theProperties;
+ inDataCore->GetInstanceProperties(inParent, theProperties);
+ TInstanceHandleList allInstances;
+ inDataCore->GetInstances(allInstances);
+ function<bool(CUICDMInstanceHandle)> InstanceOrDerived(
+ std::bind(&IDataCore::IsInstanceOrDerivedFrom, inDataCore,
+ std::placeholders::_1, inInstance));
+ function<bool(CUICDMInstanceHandle)> DerivedComplement(
+ std::bind(complement<function<bool(CUICDMInstanceHandle)>, CUICDMInstanceHandle>,
+ InstanceOrDerived, std::placeholders::_1));
+ TInstanceHandleList::iterator all_derived =
+ remove_if(allInstances.begin(), allInstances.end(), DerivedComplement);
+ TInstanceHandleList derivedInstances(allInstances.begin(), all_derived);
+ inSlideCore->DeleteAllInstancePropertyEntries(derivedInstances, theProperties);
+ EraseAnimationsThatMatch(
+ inAnimationCore, std::bind(AnimationInstancesPropertiesMatch,
+ std::placeholders::_1, inAnimationCore,
+ std::cref(derivedInstances), std::cref(theProperties)));
+}
+
+void CascadeBeforeAnimationDeleted(CUICDMAnimationHandle inAnimation,
+ TAnimationCorePtr inAnimationCore, TDataCorePtr inDataCore,
+ TSlideCorePtr inSlideCore)
+{
+ SAnimationInfo theInfo = inAnimationCore->GetAnimationInfo(inAnimation);
+ SValue theSlideValue;
+ if (inDataCore->IsInstance(theInfo.m_Instance) && inSlideCore->IsSlide(theInfo.m_Slide)
+ && inSlideCore->GetSpecificInstancePropertyValue(theInfo.m_Slide, theInfo.m_Instance,
+ theInfo.m_Property, theSlideValue)
+ && inAnimationCore->GetKeyframeCount(inAnimation)) {
+ float theTime = inSlideCore->GetSlideTime(theInfo.m_Slide);
+ float theValue = inAnimationCore->EvaluateAnimation(inAnimation, theTime);
+ SetAnimationValue(theValue, theInfo.m_Index, theSlideValue);
+ inSlideCore->ForceSetInstancePropertyValue(theInfo.m_Slide, theInfo.m_Instance,
+ theInfo.m_Property, theSlideValue);
+ }
+}
+
+void CascadeBeforeKeyframeErased(CUICDMKeyframeHandle inKeyframe, TAnimationCorePtr inAnimationCore,
+ TDataCorePtr inDataCore, TSlideCorePtr inSlideCore)
+{
+ CUICDMAnimationHandle theAnimation = inAnimationCore->GetAnimationForKeyframe(inKeyframe);
+ if (inAnimationCore->GetKeyframeCount(theAnimation) == 1)
+ CascadeBeforeAnimationDeleted(theAnimation, inAnimationCore, inDataCore, inSlideCore);
+}
+
+CStudioCoreSystem::CStudioCoreSystem(TStringTablePtr strTable)
+ : m_StringTable(strTable.get() != NULL ? strTable : IStringTable::CreateStringTable())
+ , m_DataCore(new CDataCoreProducer(m_StringTable))
+ , m_SlideCore(new CSlideCoreProducer(m_StringTable))
+ , m_SlideGraphCore(new CSlideGraphCoreProducer())
+ , m_AnimationCore(new CAnimationCoreProducer())
+ , m_ActionCore(new CActionCoreProducer(m_StringTable))
+ , m_NewMetaData(
+ IMetaData::CreateNewMetaData(dynamic_pointer_cast<CDataCoreProducer>(m_DataCore)))
+ , m_GuideSystem(IGuideSystem::CreateGuideSystem())
+{
+ IDataCoreSignalProvider *theProvider =
+ dynamic_cast<IDataCoreSignalProvider *>(m_DataCore.get());
+ m_Connections.push_back(theProvider->ConnectInstanceDeleted(
+ std::bind(CascadeInstanceDelete, std::placeholders::_1, m_DataCore, m_SlideCore,
+ m_SlideGraphCore, m_AnimationCore, m_ActionCore)));
+ m_Connections.push_back(theProvider->ConnectPropertyRemoved(std::bind(
+ CascadePropertyRemove, std::placeholders::_1,
+ std::placeholders::_2, m_SlideCore, m_SlideGraphCore, m_AnimationCore)));
+ m_Connections.push_back(theProvider->ConnectInstanceParentRemoved(std::bind(
+ CascadeInstanceParentRemoved, std::placeholders::_1,
+ std::placeholders::_2, m_DataCore, m_SlideCore, m_AnimationCore)));
+ ISlideCoreSignalProvider *theSlideCoreSignalProvider =
+ dynamic_cast<ISlideCoreSignalProvider *>(m_SlideCore.get());
+ m_Connections.push_back(theSlideCoreSignalProvider->ConnectBeforeSlideDeleted(
+ std::bind(CascadeSlideDelete, std::placeholders::_1, m_DataCore, m_SlideCore,
+ m_SlideGraphCore, m_AnimationCore, m_ActionCore)));
+ m_Connections.push_back(theSlideCoreSignalProvider->ConnectInstancePropertyValueRemoved(
+ std::bind(CascadeSlidePropertyRemove, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, m_AnimationCore)));
+ IAnimationCoreSignalProvider *theAnimProvider =
+ dynamic_cast<IAnimationCoreSignalProvider *>(m_AnimationCore.get());
+ m_Connections.push_back(theAnimProvider->ConnectBeforeAnimationDeleted(
+ std::bind(CascadeBeforeAnimationDeleted, std::placeholders::_1,
+ m_AnimationCore, m_DataCore, m_SlideCore)));
+ m_Connections.push_back(theAnimProvider->ConnectBeforeKeyframeErased(
+ std::bind(CascadeBeforeKeyframeErased, std::placeholders::_1,
+ m_AnimationCore, m_DataCore, m_SlideCore)));
+ m_Connections.push_back(theAnimProvider->ConnectBeforeAllKeyframesErased(
+ std::bind(CascadeBeforeAnimationDeleted, std::placeholders::_1,
+ m_AnimationCore, m_DataCore, m_SlideCore)));
+}
+
+CStudioCoreSystem::~CStudioCoreSystem()
+{
+}
+
+std::shared_ptr<IDataCore> CStudioCoreSystem::GetDataCore()
+{
+ return m_DataCore;
+}
+std::shared_ptr<ISlideCore> CStudioCoreSystem::GetSlideCore()
+{
+ return m_SlideCore;
+}
+std::shared_ptr<ISlideGraphCore> CStudioCoreSystem::GetSlideGraphCore()
+{
+ return m_SlideGraphCore;
+}
+std::shared_ptr<IAnimationCore> CStudioCoreSystem::GetAnimationCore()
+{
+ return m_AnimationCore;
+}
+std::shared_ptr<IActionCore> CStudioCoreSystem::GetActionCore()
+{
+ return m_ActionCore;
+}
+std::shared_ptr<ICustomPropCore> CStudioCoreSystem::GetCustomPropCore()
+{
+ return m_CustomPropCore;
+}
+std::shared_ptr<IMetaData> CStudioCoreSystem::GetNewMetaData()
+{
+ return m_NewMetaData;
+}
+std::shared_ptr<IGuideSystem> CStudioCoreSystem::GetGuideSystem()
+{
+ return m_GuideSystem;
+}
+
+std::shared_ptr<IDataCore> CStudioCoreSystem::GetTransactionlessDataCore()
+{
+ return dynamic_cast<CDataCoreProducer *>(m_DataCore.get())->GetTransactionlessDataCore();
+}
+std::shared_ptr<ISlideCore> CStudioCoreSystem::GetTransactionlessSlideCore()
+{
+ return dynamic_cast<CSlideCoreProducer *>(m_SlideCore.get())->GetTransactionlessSlideCore();
+}
+std::shared_ptr<ISlideGraphCore> CStudioCoreSystem::GetTransactionlessSlideGraphCore()
+{
+ return dynamic_cast<CSlideGraphCoreProducer *>(m_SlideGraphCore.get())
+ ->GetTransactionlessSlideGraphCore();
+}
+std::shared_ptr<IAnimationCore> CStudioCoreSystem::GetTransactionlessAnimationCore()
+{
+ return dynamic_cast<CAnimationCoreProducer *>(m_AnimationCore.get())
+ ->GetTransactionlessAnimationCore();
+}
+std::shared_ptr<IActionCore> CStudioCoreSystem::GetTransactionlessActionCore()
+{
+ return dynamic_cast<CActionCoreProducer *>(m_ActionCore.get())->GetTransactionlessActionCore();
+}
+
+inline bool InstanceSpecificNameMatches(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const TCharStr &inName,
+ const CSimpleDataCore &inData)
+{
+ TPropertyHandleList theProperties;
+ inData.GetAggregateInstanceProperties(inInstance, theProperties);
+ SValue theValue;
+ if (exists(theProperties, std::bind(equal_to<int>(), inProperty, std::placeholders::_1))
+ && inData.GetSpecificInstancePropertyValue(inInstance, inProperty, theValue)) {
+ return inName == get<TDataStrPtr>(theValue)->GetData();
+ }
+ return false;
+}
+
+CUICDMInstanceHandle CStudioCoreSystem::FindInstanceByName(CUICDMPropertyHandle inNameProperty,
+ const TCharStr &inName) const
+{
+ TInstanceHandleList theInstances;
+ m_DataCore->GetInstances(theInstances);
+ TInstanceHandleList::iterator theFind = find_if<TInstanceHandleList::iterator>(
+ theInstances,
+ std::bind(InstanceSpecificNameMatches, std::placeholders::_1, inNameProperty, std::cref(inName),
+ std::cref(*dynamic_cast<CDataCoreProducer *>(m_DataCore.get())
+ ->GetTransactionlessDataCore())));
+ if (theFind != theInstances.end())
+ return *theFind;
+ return 0;
+}
+
+void CStudioCoreSystem::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ DoSetConsumer(inConsumer, m_DataCore);
+ DoSetConsumer(inConsumer, m_SlideCore);
+ DoSetConsumer(inConsumer, m_SlideGraphCore);
+ DoSetConsumer(inConsumer, m_AnimationCore);
+ DoSetConsumer(inConsumer, m_ActionCore);
+ DoSetConsumer(inConsumer, m_GuideSystem);
+ // In general the meta data doesn't participate in the undo/redo system except
+ // in special cases. This is because we don't want to generate undo/redo information
+ // when loading lua files and such
+ if (!inConsumer)
+ DoSetConsumer(inConsumer, m_NewMetaData);
+}
+}
diff --git a/src/Authoring/UICDM/Systems/StudioCoreSystem.h b/src/Authoring/UICDM/Systems/StudioCoreSystem.h
new file mode 100644
index 00000000..6fb4ce54
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioCoreSystem.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef STUDIOCORESYSTEMH
+#define STUDIOCORESYSTEMH
+#include "UICDMTransactions.h"
+#include "UICDMHandles.h"
+
+namespace UICDM {
+class IDataCore;
+class ISlideCore;
+class ISlideGraphCore;
+class IAnimationCore;
+class IActionCore;
+class ICustomPropCore;
+class ISignalConnection;
+class IMetaData;
+class IGuideSystem;
+
+// Manages cascading operations between cores so that the entire group of
+// cores stays up to date.
+class CStudioCoreSystem : public ITransactionProducer
+{
+ Q_DISABLE_COPY(CStudioCoreSystem)
+
+ TStringTablePtr m_StringTable;
+ std::shared_ptr<IDataCore> m_DataCore;
+ std::shared_ptr<ISlideCore> m_SlideCore;
+ std::shared_ptr<ISlideGraphCore> m_SlideGraphCore;
+ std::shared_ptr<IAnimationCore> m_AnimationCore;
+ std::shared_ptr<IActionCore> m_ActionCore;
+ std::shared_ptr<ICustomPropCore> m_CustomPropCore;
+ std::shared_ptr<IMetaData> m_NewMetaData;
+ std::shared_ptr<IGuideSystem> m_GuideSystem;
+
+ std::vector<std::shared_ptr<ISignalConnection>> m_Connections;
+
+public:
+ CStudioCoreSystem(TStringTablePtr strTable = TStringTablePtr());
+ virtual ~CStudioCoreSystem();
+ TStringTablePtr GetStringTablePtr() const { return m_StringTable; }
+
+ std::shared_ptr<IDataCore> GetDataCore();
+ std::shared_ptr<ISlideCore> GetSlideCore();
+ std::shared_ptr<ISlideGraphCore> GetSlideGraphCore();
+ std::shared_ptr<IAnimationCore> GetAnimationCore();
+ std::shared_ptr<IActionCore> GetActionCore();
+ std::shared_ptr<ICustomPropCore> GetCustomPropCore();
+ std::shared_ptr<IMetaData> GetNewMetaData();
+ std::shared_ptr<IGuideSystem> GetGuideSystem();
+
+ std::shared_ptr<IDataCore> GetTransactionlessDataCore();
+ std::shared_ptr<ISlideCore> GetTransactionlessSlideCore();
+ std::shared_ptr<ISlideGraphCore> GetTransactionlessSlideGraphCore();
+ std::shared_ptr<IAnimationCore> GetTransactionlessAnimationCore();
+ std::shared_ptr<IActionCore> GetTransactionlessActionCore();
+ std::shared_ptr<ICustomPropCore> GetTransactionlessCustomPropCore();
+
+ CUICDMInstanceHandle FindInstanceByName(CUICDMPropertyHandle inNameProperty,
+ const TCharStr &inName) const;
+
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+};
+
+typedef std::shared_ptr<CStudioCoreSystem> TStudioCoreSystemPtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/StudioFullSystem.cpp b/src/Authoring/UICDM/Systems/StudioFullSystem.cpp
new file mode 100644
index 00000000..da5e307c
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioFullSystem.cpp
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "StudioFullSystem.h"
+#include "StudioCoreSystem.h"
+#include "StudioPropertySystem.h"
+#include "SlideSystem.h"
+#include "StudioAnimationSystem.h"
+#include "ActionSystem.h"
+#include "SignalsImpl.h"
+#include "SimpleDataCore.h"
+#include "SimpleSlideCore.h"
+#include "SimpleSlideGraphCore.h"
+#include "SimpleAnimationCore.h"
+#include "DataCoreProducer.h"
+#include "SlideCoreProducer.h"
+#include "SlideGraphCoreProducer.h"
+#include "ActionCoreProducer.h"
+
+using namespace std;
+
+namespace UICDM {
+
+template <typename TDoTransaction, typename TUndoTransaction>
+inline void NotifyConsumer(TTransactionConsumerPtr inConsumer, TDoTransaction inDoNotification,
+ TUndoTransaction inUndoNotification)
+{
+ if (inConsumer) {
+ inConsumer->OnDoNotification(inDoNotification);
+ inConsumer->OnUndoNotification(inUndoNotification);
+ } else {
+ inDoNotification(); // No consumer, send notification right away
+ }
+}
+
+void NotifySlideCreated(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inSlide)
+{
+ NotifyConsumer(inConsumer,
+ bind(&IStudioFullSystemSignalSender::SendSlideCreated, inSender, inSlide),
+ bind(&IStudioFullSystemSignalSender::SendSlideDeleted, inSender, inSlide));
+}
+
+void NotifySlideDeleted(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inSlide)
+{
+ NotifyConsumer(inConsumer,
+ bind(&IStudioFullSystemSignalSender::SendSlideDeleted, inSender, inSlide),
+ bind(&IStudioFullSystemSignalSender::SendSlideCreated, inSender, inSlide));
+}
+
+void NotifySlideRearranged(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inSlide,
+ int inOldIndex, int inNewIndex)
+{
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendSlideRearranged, inSender,
+ inSlide, inOldIndex, inNewIndex),
+ bind(&IStudioFullSystemSignalSender::SendSlideRearranged, inSender, inSlide,
+ inNewIndex, inOldIndex));
+}
+
+void SendInstancePropertyValueChanged(TDataCorePtr inCore, IStudioFullSystemSignalSender *inSender,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ // Ignore when the instance is not an instance (undoing an add operation may create this, as
+ // transactions are run first and notifications second).
+ if (inCore->IsInstance(inInstance))
+ inSender->SendInstancePropertyValue(inInstance, inProperty);
+}
+
+void NotifyInstancePropertyChanged(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inIsAggregate)
+{
+ if (inConsumer) {
+ if (inIsAggregate == false) {
+ NotifyConsumer(
+ inConsumer,
+ bind(SendInstancePropertyValueChanged, inCore, inSender, inInstance, inProperty),
+ bind(SendInstancePropertyValueChanged, inCore, inSender, inInstance, inProperty));
+ }
+ } else {
+ SendInstancePropertyValueChanged(inCore, inSender, inInstance, inProperty);
+ }
+}
+
+void RunAnimations(IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inMaster,
+ CUICDMSlideHandle inSlide, TAnimationCorePtr inAnimationCore,
+ TDataCorePtr inDataCore, TTransactionConsumerPtr &inConsumer)
+{
+ TAnimationInfoList theAnimations;
+ inAnimationCore->GetAnimations(theAnimations, inMaster, inSlide);
+ size_t theEnd = theAnimations.size();
+ for (size_t theIndex = 0; theIndex < theEnd; ++theIndex) {
+ SAnimationInfo &theInfo(theAnimations[theIndex]);
+ NotifyInstancePropertyChanged(inConsumer, inDataCore, inSender, theInfo.m_Instance,
+ theInfo.m_Property, false);
+ }
+}
+
+void NotifyComponentSeconds(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inSlide,
+ TDataCorePtr inCore, TAnimationCorePtr inAnimationCore,
+ TStudioAnimationSystemPtr inAnimationSystem,
+ TSlideSystemPtr inSlideSystem)
+{
+ CUICDMSlideHandle theMaster = inSlideSystem->GetMasterSlide(inSlide);
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendBeginComponentSeconds,
+ inSender, theMaster),
+ bind(&IStudioFullSystemSignalSender::SendComponentSeconds, inSender, theMaster));
+ RunAnimations(inSender, theMaster, inSlide, inAnimationCore, inCore, inConsumer);
+ dynamic_cast<CStudioAnimationSystem *>(inAnimationSystem.get())
+ ->ClearTemporaryAnimationValues();
+ NotifyConsumer(
+ inConsumer, bind(&IStudioFullSystemSignalSender::SendComponentSeconds, inSender, theMaster),
+ bind(&IStudioFullSystemSignalSender::SendBeginComponentSeconds, inSender, theMaster));
+}
+
+void NotifyPropertyLinked(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inMaster,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inAggregate)
+{
+ if (inAggregate == false) {
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendPropertyLinked,
+ inSender, inMaster, inInstance, inProperty),
+ bind(&IStudioFullSystemSignalSender::SendPropertyUnlinked, inSender,
+ inMaster, inInstance, inProperty));
+ NotifyInstancePropertyChanged(inConsumer, inCore, inSender, inInstance, inProperty,
+ inAggregate);
+ }
+}
+
+void NotifyPropertyUnlinked(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inMaster,
+ CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inAggregate)
+{
+ if (inAggregate == false) {
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendPropertyUnlinked,
+ inSender, inMaster, inInstance, inProperty),
+ bind(&IStudioFullSystemSignalSender::SendPropertyLinked, inSender, inMaster,
+ inInstance, inProperty));
+ NotifyInstancePropertyChanged(inConsumer, inCore, inSender, inInstance, inProperty,
+ inAggregate);
+ }
+}
+
+void NotifyActiveSlide(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender, CUICDMSlideHandle inMaster,
+ int /*inIndex*/, CUICDMSlideHandle inOldSlide, CUICDMSlideHandle inNewSlide,
+ TAnimationCorePtr inAnimationCore, TSlideSystemPtr inSlideSystem)
+{
+ TInstancePropertyPairList thePropertyList;
+ inSlideSystem->GetUnionOfProperties(inOldSlide, inNewSlide, thePropertyList);
+ for (size_t idx = 0, end = thePropertyList.size(); idx < end; ++idx)
+ NotifyInstancePropertyChanged(inConsumer, inCore, inSender, thePropertyList[idx].first,
+ thePropertyList[idx].second, false);
+
+ RunAnimations(inSender, inMaster, inNewSlide, inAnimationCore, inCore, inConsumer);
+}
+
+void NotifyAnimationCreated(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMAnimationHandle inAnimation, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, bool inIsAggregate)
+{
+ if (!inIsAggregate) {
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendAnimationCreated,
+ inSender, inAnimation, inInstance, inProperty),
+ bind(&IStudioFullSystemSignalSender::SendAnimationDeleted, inSender,
+ inAnimation, inInstance, inProperty));
+ }
+}
+
+void NotifyAnimationDeleted(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMAnimationHandle inAnimation, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendAnimationDeleted, inSender,
+ inAnimation, inInstance, inProperty),
+ bind(&IStudioFullSystemSignalSender::SendAnimationCreated, inSender, inAnimation,
+ inInstance, inProperty));
+ NotifyInstancePropertyChanged(inConsumer, inCore, inSender, inInstance, inProperty, false);
+}
+
+void NotifyAnimationChanged(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMAnimationHandle inAnimation, TAnimationCorePtr inAnimationCore,
+ bool inIsAggregate)
+{
+ if (!inIsAggregate) {
+ SAnimationInfo theInfo(inAnimationCore->GetAnimationInfo(inAnimation));
+ NotifyInstancePropertyChanged(inConsumer, inCore, inSender, theInfo.m_Instance,
+ theInfo.m_Property, inIsAggregate);
+ }
+}
+
+void NotifyKeyframeInserted(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMAnimationHandle inAnimation, CUICDMKeyframeHandle inKeyframe,
+ TAnimationCorePtr inAnimationCore, bool inIsAggregate)
+{
+ if (!inIsAggregate) {
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendKeyframeInserted,
+ inSender, inAnimation, inKeyframe),
+ bind(&IStudioFullSystemSignalSender::SendKeyframeErased, inSender,
+ inAnimation, inKeyframe));
+ NotifyAnimationChanged(inConsumer, inCore, inSender, inAnimation, inAnimationCore, false);
+ }
+}
+
+void NotifyKeyframeErased(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMAnimationHandle inAnimation, CUICDMKeyframeHandle inKeyframe,
+ TAnimationCorePtr inAnimationCore)
+{
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendKeyframeErased, inSender,
+ inAnimation, inKeyframe),
+ bind(&IStudioFullSystemSignalSender::SendKeyframeInserted, inSender, inAnimation,
+ inKeyframe));
+ NotifyAnimationChanged(inConsumer, inCore, inSender, inAnimation, inAnimationCore, false);
+}
+
+void NotifyKeyframeUpdated(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender, CUICDMKeyframeHandle inKeyframe,
+ TAnimationCorePtr inAnimationCore)
+{
+ NotifyConsumer(inConsumer,
+ bind(&IStudioFullSystemSignalSender::SendKeyframeUpdated, inSender, inKeyframe),
+ bind(&IStudioFullSystemSignalSender::SendKeyframeUpdated, inSender, inKeyframe));
+ CUICDMAnimationHandle theAnimation(inAnimationCore->GetAnimationForKeyframe(inKeyframe));
+ NotifyAnimationChanged(inConsumer, inCore, inSender, theAnimation, inAnimationCore, false);
+}
+
+void NotifyConnectFirstKeyframeDynamicSet(TTransactionConsumerPtr &inConsumer, TDataCorePtr inCore,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMAnimationHandle inAnimation, bool inDynamic,
+ TAnimationCorePtr inAnimationCore)
+{
+ NotifyConsumer(inConsumer,
+ bind(&IStudioFullSystemSignalSender::SendConnectFirstKeyframeDynamicSet,
+ inSender, inAnimation, inDynamic),
+ bind(&IStudioFullSystemSignalSender::SendConnectFirstKeyframeDynamicSet,
+ inSender, inAnimation, inDynamic));
+ NotifyAnimationChanged(inConsumer, inCore, inSender, inAnimation, inAnimationCore, false);
+}
+
+inline ISlideCoreSignalProvider *GetSlideSignaller(TSlideCorePtr inSlideCore)
+{
+ return dynamic_cast<CSlideCoreProducer *>(inSlideCore.get());
+}
+
+void NotifyInstanceCreated(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMInstanceHandle instance)
+{
+ NotifyConsumer(inConsumer,
+ bind(&IStudioFullSystemSignalSender::SendInstanceCreated, inSender, instance),
+ bind(&IStudioFullSystemSignalSender::SendInstanceDeleted, inSender, instance));
+}
+
+void NotifyInstanceDeleted(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMInstanceHandle instance)
+{
+ NotifyConsumer(inConsumer,
+ bind(&IStudioFullSystemSignalSender::SendInstanceDeleted, inSender, instance),
+ bind(&IStudioFullSystemSignalSender::SendInstanceCreated, inSender, instance));
+}
+
+void NotifyActionCreated(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMActionHandle inAction,
+ CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance)
+{
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendActionCreated, inSender,
+ inAction, inSlide, inInstance),
+ bind(&IStudioFullSystemSignalSender::SendActionDeleted, inSender, inAction,
+ inSlide, inInstance));
+}
+
+void NotifyActionDestroyed(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMActionHandle inAction,
+ CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance)
+{
+ NotifyConsumer(inConsumer, bind(&IStudioFullSystemSignalSender::SendActionDeleted, inSender,
+ inAction, inSlide, inInstance),
+ bind(&IStudioFullSystemSignalSender::SendActionCreated, inSender, inAction,
+ inSlide, inInstance));
+}
+
+void SendActionEvent(CUICDMActionHandle inAction, TActionCorePtr inCore,
+ function<void()> inFunction)
+{
+ if (inCore->HandleValid(inAction))
+ inFunction();
+}
+
+void NotifyTriggerObjectSet(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMActionHandle inAction,
+ TActionCorePtr inCore)
+{
+ function<void()> theFunc(
+ bind(&IStudioFullSystemSignalSender::SendTriggerObjectSet, inSender, inAction));
+ NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc),
+ bind(SendActionEvent, inAction, inCore, theFunc));
+}
+
+void NotifyTargetObjectSet(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender, CUICDMActionHandle inAction,
+ TActionCorePtr inCore)
+{
+ function<void()> theFunc(
+ bind(&IStudioFullSystemSignalSender::SendTargetObjectSet, inSender, inAction));
+ NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc),
+ bind(SendActionEvent, inAction, inCore, theFunc));
+}
+
+void NotifyEventSet(TTransactionConsumerPtr &inConsumer, IStudioFullSystemSignalSender *inSender,
+ CUICDMActionHandle inAction, TActionCorePtr inCore)
+{
+ function<void()> theFunc(
+ bind(&IStudioFullSystemSignalSender::SendEventSet, inSender, inAction));
+ NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc),
+ bind(SendActionEvent, inAction, inCore, theFunc));
+}
+
+void NotifyHandlerSet(TTransactionConsumerPtr &inConsumer, IStudioFullSystemSignalSender *inSender,
+ CUICDMActionHandle inAction, TActionCorePtr inCore)
+{
+ function<void()> theFunc(
+ bind(&IStudioFullSystemSignalSender::SendHandlerSet, inSender, inAction));
+ NotifyConsumer(inConsumer, bind(SendActionEvent, inAction, inCore, theFunc),
+ bind(SendActionEvent, inAction, inCore, theFunc));
+}
+
+void NotifyHandlerArgumentValueSet(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender,
+ CUICDMHandlerArgHandle inAction, TActionCorePtr inCore)
+{
+ function<void()> theFunc(
+ bind(&IStudioFullSystemSignalSender::SendHandlerArgumentValueSet, inSender, inAction));
+ CUICDMActionHandle theActionHdl(inCore->GetHandlerArgumentInfo(inAction).m_Action);
+ NotifyConsumer(inConsumer, bind(SendActionEvent, theActionHdl, inCore, theFunc),
+ bind(SendActionEvent, theActionHdl, inCore, theFunc));
+}
+
+void NotifyAllKeyframesErased(TTransactionConsumerPtr &inConsumer,
+ IStudioFullSystemSignalSender *inSender,
+ TAnimationCorePtr inAnimationCore, CUICDMAnimationHandle inAnimation)
+{
+ if (inConsumer) {
+ TKeyframeHandleList theKeyframes;
+ inAnimationCore->GetKeyframes(inAnimation, theKeyframes);
+ for (size_t idx = 0, end = theKeyframes.size(); idx < end; ++idx) {
+ inConsumer->OnDoNotification(bind(&IStudioFullSystemSignalSender::SendKeyframeErased,
+ inSender, inAnimation, theKeyframes[idx]));
+ inConsumer->OnUndoNotification(
+ bind(&IStudioFullSystemSignalSender::SendKeyframeInserted, inSender, inAnimation,
+ theKeyframes[idx]));
+ }
+ }
+}
+
+CStudioFullSystem::CStudioFullSystem(std::shared_ptr<CStudioCoreSystem> inCoreSystem,
+ CUICDMInstanceHandle inSlideInstance,
+ CUICDMPropertyHandle inComponentGuidProperty,
+ CUICDMInstanceHandle inActionInstance,
+ CUICDMPropertyHandle inActionEyeball)
+ : m_CoreSystem(inCoreSystem)
+ , m_SlideSystem(new SSlideSystem(m_CoreSystem->GetDataCore(), m_CoreSystem->GetSlideCore(),
+ m_CoreSystem->GetSlideGraphCore(),
+ m_CoreSystem->GetAnimationCore(), inSlideInstance,
+ inComponentGuidProperty))
+ , m_ActionSystem(new CActionSystem(m_CoreSystem->GetDataCore(), m_CoreSystem->GetSlideCore(),
+ m_CoreSystem->GetSlideGraphCore(),
+ m_CoreSystem->GetActionCore(), m_SlideSystem,
+ inActionInstance, inActionEyeball))
+ , m_AggregateOperation(false)
+{
+ // TODO: Too many parameters passed in to the subsystem. Just make them know about FullSystem so
+ // they can get whatever they want
+ CStudioAnimationSystem *theAnimationSystem = new CStudioAnimationSystem(
+ m_PropertySystem, m_SlideSystem, m_CoreSystem->GetSlideCore(),
+ m_CoreSystem->GetSlideGraphCore(), m_CoreSystem->GetAnimationCore());
+ m_AnimationSystem = std::shared_ptr<UICDM::IStudioAnimationSystem>(theAnimationSystem);
+
+ m_PropertySystem = std::shared_ptr<UICDM::IPropertySystem>(
+ new CStudioPropertySystem(m_CoreSystem->GetNewMetaData(), m_CoreSystem->GetDataCore(),
+ m_SlideSystem, m_AnimationSystem));
+ theAnimationSystem->SetPropertySystem(m_PropertySystem);
+
+ TDataCorePtr dataCore(m_CoreSystem->GetDataCore());
+
+ static_cast<SSlideSystem *>(m_SlideSystem.get())->SetPropertySystem(m_PropertySystem);
+
+ ISlideSystemSignalProvider *theSlideSignaller =
+ dynamic_cast<SSlideSystem *>(m_SlideSystem.get())->GetSignalProvider();
+ m_Signaller = CreateStudioFullSystemSignaller(theSlideSignaller);
+ IStudioFullSystemSignalSender *theSystemSender =
+ dynamic_cast<IStudioFullSystemSignalSender *>(m_Signaller.get());
+ m_Connections.push_back(theSlideSignaller->ConnectSlideRearranged(
+ bind(NotifySlideRearranged, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theSlideSignaller->ConnectPropertyLinked(
+ bind(NotifyPropertyLinked, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3,
+ std::cref(m_AggregateOperation))));
+ m_Connections.push_back(theSlideSignaller->ConnectPropertyUnlinked(
+ bind(NotifyPropertyUnlinked, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3,
+ std::cref(m_AggregateOperation))));
+
+ m_Connections.push_back(theSlideSignaller->ConnectActiveSlide(
+ bind(NotifyActiveSlide, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, std::placeholders::_4,
+ GetAnimationCore(), GetSlideSystem())));
+
+ IDataCoreSignalProvider *theDataSignals =
+ dynamic_cast<IDataCoreSignalProvider *>(m_CoreSystem->GetDataCore().get());
+ m_Connections.push_back(theDataSignals->ConnectInstanceCreated(
+ bind(NotifyInstanceCreated, ref(m_Consumer), theSystemSender, std::placeholders::_1)));
+ m_Connections.push_back(theDataSignals->ConnectInstanceDeleted(
+ bind(NotifyInstanceDeleted, ref(m_Consumer), theSystemSender, std::placeholders::_1)));
+
+ ISlideCoreSignalProvider *theSlideCoreSignaller =
+ dynamic_cast<ISlideCoreSignalProvider *>(m_CoreSystem->GetSlideCore().get());
+ m_Connections.push_back(theSlideCoreSignaller->ConnectInstancePropertyValueSet(
+ bind(NotifyInstancePropertyChanged, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_2, std::placeholders::_3,
+ std::cref(m_AggregateOperation))));
+ m_Connections.push_back(theSlideCoreSignaller->ConnectSlideTimeChanged(
+ bind(NotifyComponentSeconds, ref(m_Consumer), theSystemSender, std::placeholders::_1,
+ dataCore, GetAnimationCore(), GetAnimationSystem(), GetSlideSystem())));
+ m_Connections.push_back(theSlideCoreSignaller->ConnectSlideCreated(
+ bind(NotifySlideCreated, ref(m_Consumer), theSystemSender, std::placeholders::_1)));
+ m_Connections.push_back(theSlideCoreSignaller->ConnectSlideDeleted(
+ bind(NotifySlideDeleted, ref(m_Consumer), theSystemSender, std::placeholders::_1)));
+
+ IAnimationCoreSignalProvider *theAnimationSignals =
+ dynamic_cast<IAnimationCoreSignalProvider *>(GetAnimationCore().get());
+ m_Connections.push_back(theAnimationSignals->ConnectAnimationCreated(
+ bind(NotifyAnimationCreated, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, std::placeholders::_3, std::placeholders::_4,
+ std::cref(m_AggregateOperation))));
+ m_Connections.push_back(theAnimationSignals->ConnectAnimationDeleted(
+ bind(NotifyAnimationDeleted, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1, std::placeholders::_3, std::placeholders::_4)));
+ m_Connections.push_back(theAnimationSignals->ConnectKeyframeInserted(
+ bind(NotifyKeyframeInserted, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1, std::placeholders::_2,
+ GetAnimationCore(), std::cref(m_AggregateOperation))));
+ m_Connections.push_back(theAnimationSignals->ConnectKeyframeErased(
+ bind(NotifyKeyframeErased, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1, std::placeholders::_2,
+ GetAnimationCore())));
+ m_Connections.push_back(theAnimationSignals->ConnectKeyframeUpdated(
+ bind(NotifyKeyframeUpdated, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1, GetAnimationCore())));
+ m_Connections.push_back(theAnimationSignals->ConnectFirstKeyframeDynamicSet(
+ bind(NotifyConnectFirstKeyframeDynamicSet, ref(m_Consumer), dataCore,
+ theSystemSender, std::placeholders::_1,
+ std::placeholders::_2, GetAnimationCore())));
+ m_Connections.push_back(theAnimationSignals->ConnectBeforeAllKeyframesErased(
+ bind(NotifyAllKeyframesErased, ref(m_Consumer), theSystemSender,
+ GetAnimationCore(), std::placeholders::_1)));
+
+ IInstancePropertyCoreSignalProvider *thePropertyCoreSignaller =
+ dynamic_cast<CStudioPropertySystem *>(m_PropertySystem.get())
+ ->GetPropertyCoreSignalProvider();
+ m_Connections.push_back(thePropertyCoreSignaller->ConnectInstancePropertyValue(
+ bind(NotifyInstancePropertyChanged, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1, std::placeholders::_2, std::cref(m_AggregateOperation))));
+
+ thePropertyCoreSignaller = dynamic_cast<CStudioPropertySystem *>(m_PropertySystem.get())
+ ->GetImmediatePropertyCoreSignalProvider();
+ m_Connections.push_back(thePropertyCoreSignaller->ConnectInstancePropertyValue(
+ bind(&IStudioFullSystemSignalSender::SendInstancePropertyValue, theSystemSender,
+ std::placeholders::_1, std::placeholders::_2)));
+
+ thePropertyCoreSignaller =
+ dynamic_cast<IInstancePropertyCoreSignalProvider *>(m_CoreSystem->GetDataCore().get());
+ m_Connections.push_back(thePropertyCoreSignaller->ConnectInstancePropertyValue(
+ bind(NotifyInstancePropertyChanged, ref(m_Consumer), dataCore, theSystemSender,
+ std::placeholders::_1, std::placeholders::_2, std::cref(m_AggregateOperation))));
+
+ IActionCoreSignalProvider *theActionSignals =
+ dynamic_cast<IActionCoreSignalProvider *>(m_CoreSystem->GetActionCore().get());
+ m_Connections.push_back(theActionSignals->ConnectTriggerObjectSet(
+ bind(NotifyTriggerObjectSet, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, GetActionCore())));
+ m_Connections.push_back(theActionSignals->ConnectTargetObjectSet(
+ bind(NotifyTargetObjectSet, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, GetActionCore())));
+ m_Connections.push_back(theActionSignals->ConnectEventSet(
+ bind(NotifyEventSet, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, GetActionCore())));
+ m_Connections.push_back(theActionSignals->ConnectHandlerSet(
+ bind(NotifyHandlerSet, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, GetActionCore())));
+ m_Connections.push_back(theActionSignals->ConnectHandlerArgumentValueSet(bind(
+ NotifyHandlerArgumentValueSet, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, GetActionCore())));
+
+ IActionSystemSignalProvider *theActionSystemSignals =
+ dynamic_cast<CActionSystem *>(m_ActionSystem.get())->GetSignalProvider();
+ m_Connections.push_back(theActionSystemSignals->ConnectActionCreated(
+ bind(NotifyActionCreated, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+ m_Connections.push_back(theActionSystemSignals->ConnectActionDeleted(
+ bind(NotifyActionDestroyed, ref(m_Consumer), theSystemSender,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+}
+
+CStudioFullSystem::~CStudioFullSystem()
+{
+}
+
+std::shared_ptr<IPropertySystem> CStudioFullSystem::GetPropertySystem()
+{
+ return m_PropertySystem;
+}
+std::shared_ptr<ISlideSystem> CStudioFullSystem::GetSlideSystem()
+{
+ return m_SlideSystem;
+}
+std::shared_ptr<ISlideCore> CStudioFullSystem::GetSlideCore()
+{
+ return m_CoreSystem->GetSlideCore();
+}
+std::shared_ptr<IAnimationCore> CStudioFullSystem::GetAnimationCore()
+{
+ return m_CoreSystem->GetAnimationCore();
+}
+std::shared_ptr<IStudioAnimationSystem> CStudioFullSystem::GetAnimationSystem()
+{
+ return m_AnimationSystem;
+}
+std::shared_ptr<IActionCore> CStudioFullSystem::GetActionCore()
+{
+ return m_CoreSystem->GetActionCore();
+}
+std::shared_ptr<IActionSystem> CStudioFullSystem::GetActionSystem()
+{
+ return m_ActionSystem;
+}
+
+std::shared_ptr<IPropertySystem> CStudioFullSystem::GetPropertySystem() const
+{
+ return m_PropertySystem;
+}
+std::shared_ptr<ISlideSystem> CStudioFullSystem::GetSlideSystem() const
+{
+ return m_SlideSystem;
+}
+std::shared_ptr<ISlideCore> CStudioFullSystem::GetSlideCore() const
+{
+ return m_CoreSystem->GetSlideCore();
+}
+std::shared_ptr<IAnimationCore> CStudioFullSystem::GetAnimationCore() const
+{
+ return m_CoreSystem->GetAnimationCore();
+}
+std::shared_ptr<IStudioAnimationSystem> CStudioFullSystem::GetAnimationSystem() const
+{
+ return m_AnimationSystem;
+}
+std::shared_ptr<IActionCore> CStudioFullSystem::GetActionCore() const
+{
+ return m_CoreSystem->GetActionCore();
+}
+std::shared_ptr<IActionSystem> CStudioFullSystem::GetActionSystem() const
+{
+ return m_ActionSystem;
+}
+
+std::shared_ptr<CStudioCoreSystem> CStudioFullSystem::GetCoreSystem()
+{
+ return m_CoreSystem;
+}
+
+bool CStudioFullSystem::GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ SValue theTemp;
+ bool retval = dynamic_cast<const CStudioPropertySystem *>(m_PropertySystem.get())
+ ->GetCanonicalInstancePropertyValue(inInstance, inProperty, theTemp);
+ if (retval)
+ outValue = theTemp.toOldSkool();
+ return retval;
+}
+
+CUICDMInstanceHandle CStudioFullSystem::FindInstanceByName(CUICDMPropertyHandle inNameProperty,
+ const TCharStr &inName) const
+{
+ return m_CoreSystem->FindInstanceByName(inNameProperty, inName);
+}
+
+void CStudioFullSystem::SetConsumer(TTransactionConsumerPtr inConsumer)
+{
+ m_CoreSystem->SetConsumer(inConsumer);
+ DoSetConsumer(inConsumer, m_AnimationSystem);
+ m_Consumer = inConsumer;
+}
+
+IStudioFullSystemSignalProvider *CStudioFullSystem::GetSignalProvider()
+{
+ return dynamic_cast<IStudioFullSystemSignalProvider *>(m_Signaller.get());
+}
+
+IStudioFullSystemSignalSender *CStudioFullSystem::GetSignalSender()
+{
+ return dynamic_cast<IStudioFullSystemSignalSender *>(m_Signaller.get());
+}
+}
diff --git a/src/Authoring/UICDM/Systems/StudioFullSystem.h b/src/Authoring/UICDM/Systems/StudioFullSystem.h
new file mode 100644
index 00000000..005bcb00
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioFullSystem.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef STUDIOFULLSYSTEMH
+#define STUDIOFULLSYSTEMH
+#include "UICDMTransactions.h"
+#include "UICDMHandles.h"
+#include "UICDMSignals.h"
+#include "UICDMDataTypes.h"
+
+namespace UICDM {
+class IPropertySystem;
+class ISlideSystem;
+class IStudioAnimationSystem;
+class CStudioCoreSystem;
+class IInstancePropertyCore;
+class INotificationEngine;
+class IAnimationCore;
+class IActionCore;
+class ISlideCore;
+class IActionSystem;
+class ISignalConnection;
+
+class IStudioFullSystemSerializeHelper
+{
+public:
+ virtual ~IStudioFullSystemSerializeHelper() {}
+ /**
+ * Given an instance, set the name if possible. Called for parents of existing instances
+ * so we can find instances by name later. There is an implicit assumption for partial
+ * serialization that none of the instances that are serialized out are base instances
+ * for other serialized instances. There is another implicit assumption that the system
+ * can name any instances used a base.
+ */
+ virtual bool GetInstanceName(CUICDMInstanceHandle inInstance, TCharStr &outName) = 0;
+};
+
+typedef std::shared_ptr<IStudioFullSystemSerializeHelper> TStudioFullSystemSerializeHelperPtr;
+
+// The full studio system needs extra information in the deserialize stage. This information
+// requires knowledge of the larger studio universe in order to work and thus clients need to
+// pass in an interface.
+class IStudioFullSystemDeserializeHelper
+{
+public:
+ virtual ~IStudioFullSystemDeserializeHelper() {}
+ /**
+ * Return an instance by name. Whatever method was used above to name instances
+ * should be used to find a given instance by name.
+ */
+ virtual CUICDMInstanceHandle FindInstanceByName(const TCharStr &inName) = 0;
+ /**
+ * Translate a given guid. For pass 1, you should only translate ids and just return identity
+ * for anything that isn't an id.
+ */
+ virtual void TranslateGuidPass1(CUICDMPropertyHandle inProperty, SLong4 inValue) = 0;
+ /**
+ * Now translate guids that are used as data variables. These are links to other objects and
+ *the GUID
+ * information should come from what was created in pass 1.
+ */
+ virtual SLong4 TranslateGuidPass2(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SLong4 inValue) = 0;
+};
+
+typedef std::shared_ptr<IStudioFullSystemDeserializeHelper> TStudioFullSystemDeserializeHelperPtr;
+
+class CStudioFullSystem : public ITransactionProducer
+{
+ Q_DISABLE_COPY(CStudioFullSystem)
+
+ // Base that the other types are built upon
+ std::shared_ptr<CStudioCoreSystem> m_CoreSystem;
+
+ // The data model exposed to studio
+ std::shared_ptr<IPropertySystem> m_PropertySystem;
+ std::shared_ptr<ISlideSystem> m_SlideSystem;
+ std::shared_ptr<IStudioAnimationSystem> m_AnimationSystem;
+ std::shared_ptr<IActionSystem> m_ActionSystem;
+
+ std::vector<std::shared_ptr<ISignalConnection>> m_Connections;
+
+ TTransactionConsumerPtr m_Consumer;
+ TSignalItemPtr m_Signaller;
+ bool m_AggregateOperation;
+
+public:
+ CStudioFullSystem(std::shared_ptr<CStudioCoreSystem> inCoreSystem,
+ CUICDMInstanceHandle inSlideInstance,
+ CUICDMPropertyHandle inComponentGuidProperty,
+ CUICDMInstanceHandle inActionInstance, CUICDMPropertyHandle inActionEyeball);
+ virtual ~CStudioFullSystem();
+
+ void BeginAggregateOperation() { m_AggregateOperation = true; }
+ void EndAggregateOperation() { m_AggregateOperation = false; }
+
+ std::shared_ptr<IPropertySystem> GetPropertySystem();
+ std::shared_ptr<ISlideSystem> GetSlideSystem();
+ std::shared_ptr<ISlideCore> GetSlideCore();
+ std::shared_ptr<IAnimationCore> GetAnimationCore();
+ std::shared_ptr<IStudioAnimationSystem> GetAnimationSystem();
+ std::shared_ptr<IActionCore> GetActionCore();
+ std::shared_ptr<IActionSystem> GetActionSystem();
+
+ std::shared_ptr<IPropertySystem> GetPropertySystem() const;
+ std::shared_ptr<ISlideSystem> GetSlideSystem() const;
+ std::shared_ptr<ISlideCore> GetSlideCore() const;
+ std::shared_ptr<IAnimationCore> GetAnimationCore() const;
+ std::shared_ptr<IStudioAnimationSystem> GetAnimationSystem() const;
+ std::shared_ptr<IActionCore> GetActionCore() const;
+ std::shared_ptr<IActionSystem> GetActionSystem() const;
+
+ // Don't use this unless you are a test harness or some other more-knowledgeable-than-ordinary
+ // entity.
+ std::shared_ptr<CStudioCoreSystem> GetCoreSystem();
+
+ // Ignoring animation and the currently active slide, get the canonical instance property value
+ // for this instance.
+ bool GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const;
+ CUICDMInstanceHandle FindInstanceByName(CUICDMPropertyHandle inNameProperty,
+ const TCharStr &inName) const;
+
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override;
+ TTransactionConsumerPtr GetConsumer() { return m_Consumer; }
+
+ // This signal provider sends signals during undo/redo and during
+ // animation runs.
+ IStudioFullSystemSignalProvider *GetSignalProvider();
+
+ // Return the signal sender so that we can activate/deactivate signals
+ IStudioFullSystemSignalSender *GetSignalSender();
+};
+
+typedef std::shared_ptr<CStudioFullSystem> TStudioFullSystemPtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/StudioPropertySystem.cpp b/src/Authoring/UICDM/Systems/StudioPropertySystem.cpp
new file mode 100644
index 00000000..ebd5b7cd
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioPropertySystem.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICDMPrefix.h"
+#include "StudioPropertySystem.h"
+#include "StudioAnimationSystem.h"
+#include "SignalsImpl.h"
+
+using namespace std;
+
+namespace UICDM {
+
+CStudioPropertySystem::CStudioPropertySystem(std::shared_ptr<IMetaData> inMetaData,
+ TDataCorePtr inDataCore, TSlideSystemPtr inSlideSystem,
+ TStudioAnimationSystemPtr inStudioAnimationSystem)
+ : m_MetaData(inMetaData)
+ , m_DataCore(inDataCore)
+ , m_SlideSystem(inSlideSystem)
+ , m_StudioAnimationSystem(inStudioAnimationSystem)
+{
+ m_PropertyCoreSignaller = CreatePropertyCoreSignaller();
+ m_ImmediateModePropertyCoreSignaller = CreatePropertyCoreSignaller();
+}
+
+DataModelDataType::Value CStudioPropertySystem::GetDataType(CUICDMPropertyHandle inProperty) const
+{
+ if (m_DataCore->IsProperty(inProperty))
+ return m_DataCore->GetProperty(inProperty).m_Type;
+ return DataModelDataType::None;
+}
+
+TCharStr CStudioPropertySystem::GetName(CUICDMPropertyHandle inProperty) const
+{
+ if (m_DataCore->IsProperty(inProperty))
+ return m_DataCore->GetProperty(inProperty).m_Name;
+ return TCharStr();
+}
+
+TCharStr CStudioPropertySystem::GetFormalName(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ if (inInstance.Valid() && inProperty.Valid())
+ return m_MetaData->GetFormalName(inInstance, inProperty);
+ return TCharStr();
+}
+
+AdditionalMetaDataType::Value
+CStudioPropertySystem::GetAdditionalMetaDataType(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ return m_MetaData->GetAdditionalMetaDataType(inInstance, inProperty);
+}
+
+TMetaDataData
+CStudioPropertySystem::GetAdditionalMetaDataData(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ return m_MetaData->GetAdditionalMetaDataData(inInstance, inProperty);
+}
+
+CUICDMInstanceHandle CStudioPropertySystem::GetPropertyOwner(CUICDMPropertyHandle inProperty) const
+{
+
+ UICDM::SUICDMPropertyDefinition thePropDef = m_DataCore->GetProperty(inProperty);
+ return thePropDef.m_Instance;
+}
+
+CUICDMPropertyHandle
+CStudioPropertySystem::GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const
+{
+ return m_DataCore->GetAggregateInstancePropertyByName(inInstance, inStr);
+}
+
+void CStudioPropertySystem::GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const
+{
+ m_DataCore->GetAggregateInstanceProperties(inInstance, outProperties);
+}
+
+bool CStudioPropertySystem::HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const
+{
+ return m_DataCore->HasAggregateInstanceProperty(inInstance, inProperty);
+}
+
+bool ApplyValueAndReturnTrue(const SValue &inValue, SValue &outValue)
+{
+ outValue = inValue;
+ return true;
+}
+
+bool CStudioPropertySystem::GetInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ if (!m_DataCore->IsInstance(inInstance))
+ return false;
+ if (!m_DataCore->IsProperty(inProperty))
+ return false;
+
+ CUICDMSlideHandle theAnimationSlide;
+ theAnimationSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty);
+ SValue theTemp;
+ bool retval = SetDefault(GetDataType(inProperty), theTemp);
+ if (retval && theAnimationSlide.Valid()
+ && m_StudioAnimationSystem->GetAnimatedInstancePropertyValue(theAnimationSlide, inInstance,
+ inProperty, theTemp))
+ return ApplyValueAndReturnTrue(theTemp, outValue);
+ if (theAnimationSlide.Valid()
+ && m_SlideSystem->GetInstancePropertyValue(theAnimationSlide, inInstance, inProperty,
+ theTemp))
+ return ApplyValueAndReturnTrue(theTemp, outValue);
+ return m_DataCore->GetInstancePropertyValue(inInstance, inProperty, outValue);
+}
+
+void CStudioPropertySystem::SetInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue)
+{
+ m_DataCore->CheckValue(inInstance, inProperty, inValue);
+
+ CUICDMSlideHandle theApplicableSlide;
+ theApplicableSlide = m_SlideSystem->GetApplicableSlide(inInstance, inProperty);
+ if (theApplicableSlide.Valid()) {
+ if (!m_StudioAnimationSystem->SetAnimatedInstancePropertyValue(
+ theApplicableSlide, inInstance, inProperty, inValue.toOldSkool())) {
+ // Force set on slide where item exists as it doesn't exist on the root.
+ m_SlideSystem->ForceSetInstancePropertyValue(theApplicableSlide, inInstance, inProperty,
+ inValue.toOldSkool());
+ }
+ } else {
+ m_DataCore->SetInstancePropertyValue(inInstance, inProperty, inValue);
+ }
+}
+
+CUICDMInstanceHandle CStudioPropertySystem::CreateInstance()
+{
+ return m_DataCore->CreateInstance();
+}
+
+void CStudioPropertySystem::GetInstances(TInstanceHandleList &outInstances) const
+{
+ m_DataCore->GetInstances(outInstances);
+}
+
+void CStudioPropertySystem::DeleteInstance(CUICDMInstanceHandle inHandle)
+{
+ m_DataCore->DeleteInstance(inHandle);
+}
+
+void CStudioPropertySystem::DeriveInstance(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent)
+{
+ m_DataCore->DeriveInstance(inInstance, inParent);
+}
+
+bool CStudioPropertySystem::IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, inParent);
+}
+
+CUICDMPropertyHandle CStudioPropertySystem::AddProperty(CUICDMInstanceHandle inInstance,
+ TCharPtr inName,
+ DataModelDataType::Value inPropType)
+{
+ return m_DataCore->AddProperty(inInstance, inName, inPropType);
+}
+
+bool CStudioPropertySystem::HandleValid(int inHandle) const
+{
+ return m_DataCore->HandleValid(inHandle);
+}
+
+bool CStudioPropertySystem::GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const
+{
+ SValue theTempValue;
+ if (m_SlideSystem->GetCanonicalInstancePropertyValue(inInstance, inProperty, theTempValue)) {
+ outValue = SValue(theTempValue);
+ return true;
+ }
+ return m_DataCore->GetInstancePropertyValue(inInstance, inProperty, outValue);
+}
+}
diff --git a/src/Authoring/UICDM/Systems/StudioPropertySystem.h b/src/Authoring/UICDM/Systems/StudioPropertySystem.h
new file mode 100644
index 00000000..09ba0b62
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/StudioPropertySystem.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef INSTANCEPROPERTYCORESYSTEMH
+#define INSTANCEPROPERTYCORESYSTEMH
+
+#include "UICDMSlides.h"
+#include "UICDMAnimation.h"
+#include "UICDMSignals.h"
+#include "UICDMDataCore.h"
+
+namespace UICDM {
+
+typedef std::tuple<CUICDMInstanceHandle, CUICDMPropertyHandle, SValue> TTemporaryPropertyValue;
+typedef std::vector<TTemporaryPropertyValue> TTemporaryPropertyValueList;
+
+/**
+ * Get/set instance properties taking the slide and slide graph, and animation systems into
+ *account.
+ * Also takes care of notifying external entities when a property changes.
+ */
+class CStudioPropertySystem : public IPropertySystem
+{
+ std::shared_ptr<IMetaData> m_MetaData;
+ TDataCorePtr m_DataCore;
+
+ TSlideSystemPtr m_SlideSystem;
+ TStudioAnimationSystemPtr m_StudioAnimationSystem;
+
+ TSignalItemPtr m_PropertyCoreSignaller;
+ TSignalItemPtr m_ImmediateModePropertyCoreSignaller;
+
+public:
+ CStudioPropertySystem(std::shared_ptr<IMetaData> inMetaData, TDataCorePtr inDataCore,
+ TSlideSystemPtr inSlideSystem,
+ TStudioAnimationSystemPtr inStudioAnimationSystem);
+
+ IInstancePropertyCoreSignalProvider *GetPropertyCoreSignalProvider()
+ {
+ return dynamic_cast<IInstancePropertyCoreSignalProvider *>(m_PropertyCoreSignaller.get());
+ }
+ // The immediate signaller is used before changes have been committed for very live feedback.
+ IInstancePropertyCoreSignalProvider *GetImmediatePropertyCoreSignalProvider()
+ {
+ return dynamic_cast<IInstancePropertyCoreSignalProvider *>(
+ m_ImmediateModePropertyCoreSignaller.get());
+ }
+
+ IInstancePropertyCoreSignalSender *GetPropertyCoreSignalSender()
+ {
+ return dynamic_cast<IInstancePropertyCoreSignalSender *>(m_PropertyCoreSignaller.get());
+ }
+
+ DataModelDataType::Value GetDataType(CUICDMPropertyHandle inProperty) const override;
+ TCharStr GetName(CUICDMPropertyHandle inProperty) const override;
+ TCharStr GetFormalName(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ virtual AdditionalMetaDataType::Value
+ GetAdditionalMetaDataType(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ TMetaDataData GetAdditionalMetaDataData(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+ CUICDMInstanceHandle GetPropertyOwner(CUICDMPropertyHandle inProperty) const override;
+
+ CUICDMPropertyHandle GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const override;
+ void GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const override;
+ bool HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const override;
+
+ bool GetInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const override;
+ void SetInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, const SValue &inValue) override;
+
+ CUICDMInstanceHandle CreateInstance() override;
+ void GetInstances(TInstanceHandleList &outInstances) const override;
+ void DeleteInstance(CUICDMInstanceHandle inHandle) override;
+
+ void DeriveInstance(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent) override;
+ bool IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const override;
+
+ CUICDMPropertyHandle AddProperty(CUICDMInstanceHandle inInstance, TCharPtr inName,
+ DataModelDataType::Value inPropType) override;
+ bool HandleValid(int inHandle) const override;
+
+ // Get the instance property value from the slide that owns the instance or the data core if the
+ // slide doesn't have the value
+ bool GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) const;
+
+private:
+ static bool DerivedGuidMatches(UICDM::IDataCore &inDataCore,
+ UICDM::CUICDMInstanceHandle inInstance,
+ UICDM::CUICDMPropertyHandle inProperty, UICDM::SLong4 inGuid);
+ CStudioPropertySystem(const CStudioPropertySystem&) = delete;
+ CStudioPropertySystem& operator=(const CStudioPropertySystem&) = delete;
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMActionCore.h b/src/Authoring/UICDM/Systems/UICDMActionCore.h
new file mode 100644
index 00000000..54983202
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMActionCore.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMACTIONCOREH
+#define UICDMACTIONCOREH
+
+#include "UICDMHandles.h"
+#include "HandleSystemBase.h"
+#include "UICDMActionInfo.h"
+
+namespace UICDM {
+const long REFERENCED_AS_OWNER = 0x01;
+const long REFERENCED_AS_TRIGGER = 0x02;
+const long REFERENCED_AS_TARGET = 0x04;
+class IStringTable;
+
+/**
+ * ActionCore
+ */
+class IActionCore : public IHandleBase
+{
+public:
+ virtual ~IActionCore() {}
+
+ virtual TStringTablePtr GetStringTablePtr() const = 0;
+ virtual IStringTable &GetStringTable() const = 0;
+ // Action
+ virtual CUICDMActionHandle CreateAction(CUICDMInstanceHandle inInstance,
+ CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ SLong4 inTriggerTargetObjects) = 0;
+ virtual void DeleteAction(CUICDMActionHandle inAction, CUICDMInstanceHandle &outInstance) = 0;
+ virtual const SActionInfo &GetActionInfo(CUICDMActionHandle inAction) const = 0;
+ virtual void GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const = 0;
+ virtual void GetActions(CUICDMSlideHandle inSlide, TActionHandleList &outActions) const = 0;
+ virtual void GetActions(CUICDMInstanceHandle inOwner, TActionHandleList &outActions) const = 0;
+ virtual void GetActions(TActionHandleList &outActions) const = 0;
+
+ // Return the instance that was allocated for this action.
+ virtual CUICDMInstanceHandle GetActionInstance(CUICDMActionHandle inAction) const = 0;
+ // Reverse lookup into the action system so you can match actions to instances.
+ virtual CUICDMActionHandle GetActionByInstance(CUICDMInstanceHandle inActionInstance) const = 0;
+
+ // Action Properties
+ virtual void SetTriggerObject(CUICDMActionHandle inAction,
+ const SObjectRefType &inTriggerObject) = 0;
+ virtual void SetTargetObject(CUICDMActionHandle inAction,
+ const SObjectRefType &inTargetObject) = 0;
+ virtual void SetEvent(CUICDMActionHandle inAction, const wstring &inEventName) = 0;
+ virtual void SetHandler(CUICDMActionHandle inAction, const wstring &inHandlerName) = 0;
+
+ // Handler Argument
+ virtual CUICDMHandlerArgHandle AddHandlerArgument(CUICDMActionHandle inAction,
+ const TCharStr &inName,
+ HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) = 0;
+ virtual void RemoveHandlerArgument(CUICDMHandlerArgHandle inHandlerArgument) = 0;
+ virtual const SHandlerArgumentInfo &
+ GetHandlerArgumentInfo(CUICDMHandlerArgHandle inHandlerArgument) const = 0;
+ virtual void GetHandlerArguments(CUICDMActionHandle inAction,
+ THandlerArgHandleList &outHandlerArguments) const = 0;
+
+ // Handler Argument Properties
+ virtual void GetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ SValue &outValue) const = 0;
+ virtual void SetHandlerArgumentValue(CUICDMHandlerArgHandle inHandlerArgument,
+ const SValue &inValue) = 0;
+};
+
+typedef std::shared_ptr<IActionCore> TActionCorePtr;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMActionInfo.h b/src/Authoring/UICDM/Systems/UICDMActionInfo.h
new file mode 100644
index 00000000..b003316b
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMActionInfo.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMACTIONINFOH
+#define UICDMACTIONINFOH
+
+#include "UICDMDataTypes.h"
+#include "UICDMMetaDataTypes.h"
+
+namespace UICDM {
+using std::wstring;
+struct SActionInfo
+{
+ CUICDMInstanceHandle m_Instance; // InstanceHandle corresponding to this action (to store other
+ // properties not listed here)
+
+ // Where the action is added to
+ CUICDMSlideHandle m_Slide; // the slide that the action is added to
+ CUICDMInstanceHandle
+ m_Owner; // the object that the action is added to (the owner of the action)
+
+ // Trigger object
+ SObjectRefType m_TriggerObject; // trigger object
+ wstring m_Event; // the list of applicable events is based on object type and stored, by type,
+ // in metadata
+
+ // Target object
+ SObjectRefType m_TargetObject; // target object
+ wstring m_Handler; // the list of applicable action handlers is loaded from metadata xml file
+ // and based on object type
+ THandlerArgHandleList m_HandlerArgs; // the list of applicable action arguments is dependent on
+ // the handler and loaded from the metadata xml file.
+
+ SActionInfo() {}
+
+ SActionInfo(CUICDMInstanceHandle inInstance, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner)
+ : m_Instance(inInstance)
+ , m_Slide(inSlide)
+ , m_Owner(inOwner)
+ {
+ }
+};
+
+struct SHandlerArgumentInfo
+{
+ CUICDMActionHandle m_Action; // Action that owns this Action Argument
+ TCharStr m_Name; // Name of the Action Argument
+ HandlerArgumentType::Value m_ArgType; // m_ArgType will override m_ValueType
+ DataModelDataType::Value m_ValueType; // m_ValueType is ignored if ArgType is specified
+ SValue m_Value; // Value of the Action Argument
+
+ SHandlerArgumentInfo()
+ : m_ArgType(HandlerArgumentType::None)
+ , m_ValueType(DataModelDataType::None)
+ {
+ }
+
+ SHandlerArgumentInfo(CUICDMActionHandle inAction, const TCharStr &inName,
+ HandlerArgumentType::Value inArgType, DataModelDataType::Value inValueType)
+ : m_Action(inAction)
+ , m_Name(inName)
+ , m_ArgType(inArgType)
+ , m_ValueType(inValueType)
+ {
+ }
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMActionSystem.h b/src/Authoring/UICDM/Systems/UICDMActionSystem.h
new file mode 100644
index 00000000..b2407e2c
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMActionSystem.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMACTIONSYSTEMH
+#define UICDMACTIONSYSTEMH
+#include "UICDMHandles.h"
+#include "UICDMActionCore.h"
+
+namespace UICDM {
+/**
+ * ActionSystem acts as a wrapper or helper around ActionCore. ActionSystem will call
+ * ActionCore and perform other necessary setups. It also has the knowledge of other
+ * system or core so there are some synchronization being done here.
+ *
+ * When in doubts which one to use (ActionSystem or ActionCore), always use ActionSystem
+ */
+class IActionSystem
+{
+public:
+ virtual ~IActionSystem() {}
+
+ // CreateAction will create Action's InstanceHandle and Action's ActionHandle and do some
+ // necessary setup
+ virtual CUICDMActionHandle CreateAction(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ SLong4 inTriggerTargetObjects) = 0;
+ // DeleteAction will delete both Action's ActionHandle and Action's InstanceHandle
+ virtual void DeleteAction(CUICDMActionHandle inAction) = 0;
+ // Return all actions that belong to a certain instance in a certain slide + the master slide
+ virtual void GetActions(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inOwner,
+ TActionHandleList &outActions) const = 0;
+
+ // Get/set action eyeball property value
+ virtual bool GetActionEyeballValue(CUICDMSlideHandle inActiveSlide,
+ CUICDMActionHandle inAction) const = 0;
+ virtual void SetActionEyeballValue(CUICDMSlideHandle inActiveSlide, CUICDMActionHandle inAction,
+ bool inValue) = 0;
+};
+
+typedef std::shared_ptr<IActionSystem> TActionSystemPtr;
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMAnimation.h b/src/Authoring/UICDM/Systems/UICDMAnimation.h
new file mode 100644
index 00000000..4e9e4c99
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMAnimation.h
@@ -0,0 +1,828 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMANIMATIONH
+#define UICDMANIMATIONH
+#include "UICDMHandles.h"
+#include "UICDMDataTypes.h"
+#include "UICDMValue.h"
+
+namespace UICDM {
+
+struct SLinearKeyframe
+{
+ float m_KeyframeSeconds;
+ float m_KeyframeValue;
+};
+
+struct SBezierKeyframe : public SLinearKeyframe
+{
+ float m_InTangentTime; // time
+ float m_InTangentValue; // value offset
+ float m_OutTangentTime; // time offset in seconds
+ float m_OutTangentValue; // value offset
+};
+
+typedef std::vector<SBezierKeyframe> TBezierKeyframeList;
+
+/**
+ * Ease in/out are parameters that affect the bezier evaluation.
+ * Ease in/out at 100 means that the control values are at the end points thus creating
+ * a gradual deceleration. Ease in/out at 0 means that interpolation is linear, the
+ * control points are at 1/3 and 2/3's the distance to the next value.
+ * Ease in/out go from 0.f to 100.0f
+ */
+struct SEaseInEaseOutKeyframe : public SLinearKeyframe
+{
+ float m_EaseIn;
+ float m_EaseOut;
+};
+}
+
+namespace qt3ds {
+namespace foundation {
+ // Disable calling destructor of these pod types
+ template <>
+ struct DestructTraits<UICDM::SEaseInEaseOutKeyframe>
+ {
+ void destruct(UICDM::SEaseInEaseOutKeyframe &) {}
+ };
+ template <>
+ struct DestructTraits<UICDM::SBezierKeyframe>
+ {
+ void destruct(UICDM::SBezierKeyframe &) {}
+ };
+ template <>
+ struct DestructTraits<UICDM::SLinearKeyframe>
+ {
+ void destruct(UICDM::SLinearKeyframe &) {}
+ };
+}
+}
+
+namespace UICDM {
+
+enum EAnimationType {
+ EAnimationTypeNone = 0,
+ EAnimationTypeLinear,
+ EAnimationTypeBezier,
+ EAnimationTypeEaseInOut,
+};
+
+template <typename TDataType>
+struct SAnimationTypeTraits
+{
+};
+
+template <>
+struct SAnimationTypeTraits<SBezierKeyframe>
+{
+ EAnimationType getType() { return EAnimationTypeBezier; }
+};
+template <>
+struct SAnimationTypeTraits<SLinearKeyframe>
+{
+ EAnimationType getType() { return EAnimationTypeLinear; }
+};
+template <>
+struct SAnimationTypeTraits<SEaseInEaseOutKeyframe>
+{
+ EAnimationType getType() { return EAnimationTypeEaseInOut; }
+};
+
+struct SKeyframeUnionTraits
+{
+ typedef EAnimationType TIdType;
+ enum {
+ TBufferSize = sizeof(SBezierKeyframe),
+ };
+ static TIdType getNoDataId() { return EAnimationTypeNone; }
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SAnimationTypeTraits<TDataType>().getType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case EAnimationTypeBezier:
+ return inVisitor(*reinterpret_cast<SBezierKeyframe *>(inData));
+ case EAnimationTypeLinear:
+ return inVisitor(*reinterpret_cast<SLinearKeyframe *>(inData));
+ case EAnimationTypeEaseInOut:
+ return inVisitor(*reinterpret_cast<SEaseInEaseOutKeyframe *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case EAnimationTypeNone:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case EAnimationTypeBezier:
+ return inVisitor(*reinterpret_cast<const SBezierKeyframe *>(inData));
+ case EAnimationTypeLinear:
+ return inVisitor(*reinterpret_cast<const SLinearKeyframe *>(inData));
+ case EAnimationTypeEaseInOut:
+ return inVisitor(*reinterpret_cast<const SEaseInEaseOutKeyframe *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case EAnimationTypeNone:
+ return inVisitor();
+ }
+ }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SKeyframeUnionTraits,
+ SKeyframeUnionTraits::TBufferSize>,
+ SKeyframeUnionTraits::TBufferSize>
+ TKeyframe;
+
+template <>
+struct SUICDMGetter<TKeyframe>
+{
+ template <typename TRetType>
+ TRetType doGet(const TKeyframe &inValue)
+ {
+ return inValue.getData<TRetType>();
+ }
+};
+
+typedef std::vector<TKeyframe> TKeyframeList;
+
+struct SAnimationInfo
+{
+ CUICDMSlideHandle m_Slide;
+ CUICDMInstanceHandle m_Instance;
+ CUICDMPropertyHandle m_Property;
+ size_t m_Index;
+ EAnimationType m_AnimationType;
+ // Use the existing value for the value of the first keyframe.
+ // Not reflected in studio at this time, purely a runtime problem.
+ // Defaults to false
+ bool m_DynamicFirstKeyframe;
+ bool m_ArtistEdited;
+ SAnimationInfo()
+ : m_Index(0)
+ , m_AnimationType(EAnimationTypeLinear)
+ , m_DynamicFirstKeyframe(false)
+ // Animations are assumed to be artist edited.
+ // And any change will force this flag to true.
+ , m_ArtistEdited(true)
+
+ {
+ }
+ SAnimationInfo(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex, EAnimationType inAnimationType,
+ bool inDynamicFirstKeyframe, bool inArtistEdited)
+ : m_Slide(inSlide)
+ , m_Instance(inInstance)
+ , m_Property(inProperty)
+ , m_Index(inIndex)
+ , m_AnimationType(inAnimationType)
+ , m_DynamicFirstKeyframe(inDynamicFirstKeyframe)
+ , m_ArtistEdited(inArtistEdited)
+ {
+ }
+};
+
+typedef std::pair<SAnimationInfo, TKeyframeList> TAnimationKeyframesPair;
+typedef std::vector<TAnimationKeyframesPair> TAnimationKeyframesPairList;
+typedef std::vector<SAnimationInfo> TAnimationInfoList;
+
+/**
+ * Pure animation core. Not wrapped in any niceties.
+ */
+class IAnimationCore
+{
+public:
+ virtual ~IAnimationCore() {}
+ virtual CUICDMAnimationHandle CreateAnimation(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic) = 0;
+ virtual void DeleteAnimation(CUICDMAnimationHandle inAnimation) = 0;
+ virtual CUICDMAnimationHandle GetAnimation(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ size_t inIndex) const = 0;
+ virtual SAnimationInfo GetAnimationInfo(CUICDMAnimationHandle inAnimation) const = 0;
+ virtual void GetAnimations(TAnimationHandleList &outAnimations) const = 0;
+ virtual void GetAnimations(TAnimationInfoList &outAnimations,
+ CUICDMSlideHandle inMaster = CUICDMSlideHandle(),
+ CUICDMSlideHandle inSlide = CUICDMSlideHandle()) const = 0;
+
+ virtual void GetSpecificInstanceAnimations(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TAnimationHandleList &outAnimations) = 0;
+
+ virtual void SetFirstKeyframeDynamic(CUICDMAnimationHandle inAnimation, bool inValue) = 0;
+
+ // keyframe manipulation
+ virtual CUICDMKeyframeHandle InsertKeyframe(CUICDMAnimationHandle inAnimation,
+ const TKeyframe &inKeyframe) = 0;
+ virtual void EraseKeyframe(CUICDMKeyframeHandle inKeyframe) = 0;
+ virtual void DeleteAllKeyframes(CUICDMAnimationHandle inAnimation) = 0;
+
+ // All of these mutators will force the artist edited property
+ // of the animation to true.
+ virtual CUICDMAnimationHandle
+ GetAnimationForKeyframe(CUICDMKeyframeHandle inKeyframe) const = 0;
+ virtual TKeyframe GetKeyframeData(CUICDMKeyframeHandle inKeyframe) const = 0;
+ virtual void SetKeyframeData(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0;
+ virtual void GetKeyframes(CUICDMAnimationHandle inAnimation,
+ TKeyframeHandleList &outKeyframes) const = 0;
+ virtual size_t GetKeyframeCount(CUICDMAnimationHandle inAnimation) const = 0;
+ virtual bool IsFirstKeyframe(CUICDMKeyframeHandle inKeyframe) const = 0;
+
+ virtual void OffsetAnimations(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ long inOffset) = 0;
+
+ // Direct mutators of the artist edited feature of animations
+ virtual void SetIsArtistEdited(CUICDMAnimationHandle inAnimation, bool inEdited = true) = 0;
+ virtual bool IsArtistEdited(CUICDMAnimationHandle inAnimation) const = 0;
+
+ // Animation Evaluation.
+ virtual float EvaluateAnimation(CUICDMAnimationHandle inAnimation, float inSeconds) const = 0;
+
+ virtual bool KeyframeValid(CUICDMKeyframeHandle inKeyframe) const = 0;
+ virtual bool AnimationValid(CUICDMAnimationHandle inAnimation) const = 0;
+
+ virtual void CopyAnimations(CUICDMSlideHandle inSourceSlide,
+ CUICDMInstanceHandle inSourceInstance,
+ CUICDMSlideHandle inDestSlide,
+ CUICDMInstanceHandle inDestInstance) = 0;
+};
+
+typedef std::shared_ptr<IAnimationCore> TAnimationCorePtr;
+
+struct SGetOrSetKeyframeInfo
+{
+ float m_Value;
+ float m_EaseIn;
+ float m_EaseOut;
+ bool m_AnimationTrackIsDynamic;
+ SGetOrSetKeyframeInfo(float inValue, float inEaseIn = -1.f, float inEaseOut = -1.f,
+ bool inDynamic = false)
+ : m_Value(inValue)
+ , m_EaseIn(inEaseIn)
+ , m_EaseOut(inEaseOut)
+ , m_AnimationTrackIsDynamic(inDynamic)
+ {
+ }
+ SGetOrSetKeyframeInfo()
+ : m_Value(0)
+ , m_EaseIn(-1.f)
+ , m_EaseOut(-1.f)
+ , m_AnimationTrackIsDynamic(false)
+ {
+ }
+};
+/**
+ * Interface from studio into the animation system that speaks
+ * a language near to that of studio. Public interface.
+ */
+class IStudioAnimationSystem
+{
+public:
+ virtual ~IStudioAnimationSystem() {}
+
+ /**
+ * When auto-keyframing is on, all calls to setinstancepropertyvalue will
+ * case a keyframe to be set if the instance is a member of a slide graph.
+ */
+ virtual void SetAutoKeyframe(bool inAutoKeyframe) = 0;
+ /**
+ * Returns true when auto keyframing is set.
+ */
+ virtual bool GetAutoKeyframe() const = 0;
+ /**
+ * Create animation on the property on this instance. If the property was animated and had
+ *keyframes previously,
+ * this function will also set the keyframes accordingly.
+ */
+ virtual void Animate(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) = 0;
+ /**
+ * Delete animation on the property on this instance
+ */
+ virtual void Deanimate(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) = 0;
+ /**
+ * Set a keyframe on this property. Uses the current time of the slide graph.
+ * If the keyframe is within a given time distance of another, this function will simply change
+ * the keyframed value of the other property to match the current value of this property.
+ */
+ virtual void KeyframeProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ bool inDoDiffValue) = 0;
+ /**
+ * Set the value of a existing a keyframe or create a new one, on this property, at the given
+ *time.
+ * If ease in or ease out are unset then the keyframe gets the default ease in or out.
+ */
+ virtual void SetOrCreateKeyframe(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, float inTimeInSeconds,
+ SGetOrSetKeyframeInfo *inKeyframeInfo, size_t inNumInfos) = 0;
+ /**
+ * Return the animation that is currently controlling this property. This function will return
+ * an invalid handle value if there is currently no animation controlling this property.
+ */
+ virtual CUICDMAnimationHandle GetControllingAnimation(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ size_t inIndex) const = 0;
+
+ /**
+ * Return true if the given property is animatable. You can begin animation by calling
+ *KeyframeProperty *or*
+ * by setting auto keyframe to on and setting a property value through the
+ *IInstancePropertyCore system.
+ */
+ virtual bool IsPropertyAnimatable(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+
+ /**
+ * Return true if the given property is animated. Currently, either 0 or ALL channels are
+ *animated. Hence, checking for index = 0 suffices.
+ * And if that changes, this function can be updated accordingly.
+ */
+ virtual bool IsPropertyAnimated(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+
+ /**
+ * Specify if new keyframes should be created with smooth ( ie Ease In/Out values = 100 ) or
+ *linear ( Ease In/Out values = 0 )
+ */
+ virtual void SetInterpolation(bool inSmooth) = 0;
+
+ /**
+ * Get an instance property value. Will override outValue only if the slide, instance,
+ *property is animated.
+ */
+ virtual bool GetAnimatedInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+ /**
+ * Set an instance property value. Will return true in the cases where
+ * the property is actually animated. May only set local values, or may auto set a keyframed
+ *value.
+ */
+ virtual bool SetAnimatedInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+};
+
+typedef std::shared_ptr<IStudioAnimationSystem> TStudioAnimationSystemPtr;
+
+inline SLinearKeyframe CreateLinearKeyframe(float inSeconds, float inValue)
+{
+ SLinearKeyframe retval = { inSeconds, inValue };
+ return retval;
+}
+
+inline SBezierKeyframe CreateBezierKeyframe(float inSeconds, float inValue, float inInTangentTime,
+ float inInTangentValue, float inOutTangentTime,
+ float inOutTangentValue)
+{
+ SBezierKeyframe theBezierKeyframe;
+ theBezierKeyframe.m_KeyframeSeconds = inSeconds;
+ theBezierKeyframe.m_KeyframeValue = inValue;
+ theBezierKeyframe.m_InTangentTime = inInTangentTime;
+ theBezierKeyframe.m_InTangentValue = inInTangentValue;
+ theBezierKeyframe.m_OutTangentTime = inOutTangentTime;
+ theBezierKeyframe.m_OutTangentValue = inOutTangentValue;
+ return theBezierKeyframe;
+}
+
+inline SEaseInEaseOutKeyframe CreateEaseInEaseOutKeyframe(float inSeconds, float inValue,
+ float inEaseIn, float inEaseOut)
+{
+ SEaseInEaseOutKeyframe retval;
+ retval.m_KeyframeSeconds = inSeconds;
+ retval.m_KeyframeValue = inValue;
+ retval.m_EaseIn = inEaseIn;
+ retval.m_EaseOut = inEaseOut;
+ return retval;
+}
+
+inline SAnimationInfo CreateAnimationInfo(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType,
+ bool inFirstKeyframeDynamic, bool inArtistEdited)
+{
+ SAnimationInfo retval(inSlide, inInstance, inProperty, inIndex, inAnimationType,
+ inFirstKeyframeDynamic, inArtistEdited);
+ return retval;
+}
+
+struct SKeyframeValueVisitor
+{
+ float operator()(const SLinearKeyframe &inKeyframe) const { return inKeyframe.m_KeyframeValue; }
+ float operator()(const SBezierKeyframe &inKeyframe) const { return inKeyframe.m_KeyframeValue; }
+ float operator()(const SEaseInEaseOutKeyframe &inKeyframe) const
+ {
+ return inKeyframe.m_KeyframeValue;
+ }
+ float operator()()
+ {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+};
+
+inline float KeyframeValueValue(const TKeyframe &inKeyframe)
+{
+ return inKeyframe.visit<float>(SKeyframeValueVisitor());
+}
+
+struct SKeyframeTimeAnalyzer
+{
+ float operator()(const SLinearKeyframe &inValue) const { return inValue.m_KeyframeSeconds; }
+ float operator()(const SBezierKeyframe &inValue) const { return inValue.m_KeyframeSeconds; }
+ float operator()(const SEaseInEaseOutKeyframe &inValue) const
+ {
+ return inValue.m_KeyframeSeconds;
+ }
+ float operator()()
+ {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+};
+
+inline float KeyframeTime(const TKeyframe &inValue)
+{
+ return inValue.visit<float>(SKeyframeTimeAnalyzer());
+}
+
+inline EAnimationType GetKeyframeType(const TKeyframe &inKeyframe)
+{
+ return inKeyframe.getType();
+}
+
+struct SAnimatableArityVisitor
+{
+ std::tuple<bool, size_t> operator()(bool) const
+ {
+ return std::tuple<bool, size_t>(true, 1);
+ }
+ std::tuple<bool, size_t> operator()(long) const
+ {
+ return std::tuple<bool, size_t>(true, 1);
+ }
+ std::tuple<bool, size_t> operator()(float) const
+ {
+ return std::tuple<bool, size_t>(true, 1);
+ }
+ std::tuple<bool, size_t> operator()(const SFloat2 &) const
+ {
+ return std::tuple<bool, size_t>(true, 2);
+ }
+ std::tuple<bool, size_t> operator()(const SFloat3 &) const
+ {
+ return std::tuple<bool, size_t>(true, 3);
+ }
+ template <typename TDataType>
+ std::tuple<bool, size_t> operator()(const TDataType &) const
+ {
+ return std::tuple<bool, size_t>(false, 0);
+ }
+ std::tuple<bool, size_t> operator()()
+ {
+ QT3DS_ASSERT(false);
+ return std::tuple<bool, size_t>(false, 0);
+ }
+};
+
+inline std::tuple<bool, size_t> GetVariantAnimatableAndArity(const SValue &inValue)
+{
+ return inValue.visit<std::tuple<bool, size_t>>(SAnimatableArityVisitor());
+}
+
+inline std::tuple<bool, size_t> GetDatatypeAnimatableAndArity(DataModelDataType::Value inDataType)
+{
+ switch (inDataType) {
+ default:
+ return std::make_tuple(false, 0);
+ case DataModelDataType::Long:
+ case DataModelDataType::Float:
+ return std::make_tuple(true, 1);
+ case DataModelDataType::Float2:
+ return std::make_tuple(true, 2);
+ case DataModelDataType::Float3:
+ return std::make_tuple(true, 3);
+ }
+}
+
+template <typename TDataType>
+inline TDataType SetFloatValue(float inValue, size_t inIndex, const TDataType &inDataType)
+{
+ TDataType retval(inDataType);
+ retval[inIndex] = inValue;
+ return retval;
+}
+
+struct SAnimationApplier
+{
+ float m_Value;
+ size_t m_Index;
+ SValue operator()(const bool &) { return m_Value > 0.5f ? true : false; }
+ SValue operator()(const qt3ds::QT3DSI32 &) { return static_cast<qt3ds::QT3DSI32>(m_Value + .5f); }
+ SValue operator()(const float &) { return m_Value; }
+ SValue operator()(const SFloat2 &inValue) { return SetFloatValue(m_Value, m_Index, inValue); }
+ SValue operator()(const SFloat3 &inValue) { return SetFloatValue(m_Value, m_Index, inValue); }
+ template <typename TDataType>
+ SValue operator()(const TDataType &inValue)
+ {
+ return inValue;
+ }
+ SValue operator()()
+ {
+ QT3DS_ASSERT(false);
+ return SValue();
+ }
+};
+
+inline void SetAnimationValue(float inValue, size_t inIndex, SValue &ioValue)
+{
+ using namespace std;
+ SAnimationApplier theApplier;
+ theApplier.m_Value = inValue;
+ theApplier.m_Index = inIndex;
+ ioValue = ioValue.visit<SValue>(theApplier);
+}
+
+template <typename TDataType>
+inline float GetFloatValue(const TDataType &inValue, size_t inIndex)
+{
+ return inValue[inIndex];
+}
+
+struct SAnimationGetter
+{
+ size_t m_Index;
+ float operator()(const bool &inValue) const { return inValue ? 1.f : 0.f; }
+ float operator()(const long &inValue) const { return static_cast<float>(inValue); }
+ float operator()(const float &inValue) const { return inValue; }
+ float operator()(const SFloat2 &inValue) const { return GetFloatValue(inValue, m_Index); }
+ float operator()(const SFloat3 &inValue) const { return GetFloatValue(inValue, m_Index); }
+ template <typename TDataType>
+ float operator()(const TDataType & /*inValue*/) const
+ {
+ return 0.f;
+ }
+ float operator()()
+ {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+};
+
+inline float GetAnimationValue(size_t inIndex, const SValue &ioValue)
+{
+ SAnimationGetter theGetter;
+ theGetter.m_Index = inIndex;
+ return ioValue.visit<float>(theGetter);
+}
+
+struct SKeyframeTimeSetter
+{
+ float m_Seconds;
+ TKeyframe operator()(const SLinearKeyframe &inValue) const
+ {
+ return CreateLinearKeyframe(m_Seconds, inValue.m_KeyframeValue);
+ }
+ TKeyframe operator()(const SBezierKeyframe &inValue) const
+ {
+ return CreateBezierKeyframe(m_Seconds, inValue.m_KeyframeValue, inValue.m_InTangentTime,
+ inValue.m_InTangentValue, inValue.m_OutTangentTime,
+ inValue.m_OutTangentValue);
+ }
+ TKeyframe operator()(const SEaseInEaseOutKeyframe &inValue) const
+ {
+ return CreateEaseInEaseOutKeyframe(m_Seconds, inValue.m_KeyframeValue, inValue.m_EaseIn,
+ inValue.m_EaseOut);
+ }
+ TKeyframe operator()()
+ {
+ QT3DS_ASSERT(false);
+ return TKeyframe();
+ }
+};
+
+inline TKeyframe SetKeyframeSeconds(const TKeyframe &inKeyframe, float inSeconds)
+{
+ SKeyframeTimeSetter theSetter;
+ theSetter.m_Seconds = inSeconds;
+ return inKeyframe.visit<TKeyframe>(theSetter);
+}
+
+struct SKeyframeTimeGetter
+{
+ template <typename TKeyframeType>
+ float operator()(const TKeyframeType &inValue) const
+ {
+ return inValue.m_KeyframeSeconds;
+ }
+ float operator()()
+ {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+};
+
+inline float GetKeyframeSeconds(const TKeyframe &inKeyframe)
+{
+ SKeyframeTimeGetter theGetter;
+ return inKeyframe.visit<float>(theGetter);
+}
+
+struct SKeyframeValueSetter
+{
+ float m_Value;
+ TKeyframe operator()(const SLinearKeyframe &inValue) const
+ {
+ return CreateLinearKeyframe(inValue.m_KeyframeSeconds, m_Value);
+ }
+ TKeyframe operator()(const SBezierKeyframe &inValue) const
+ {
+ return CreateBezierKeyframe(inValue.m_KeyframeSeconds, m_Value, inValue.m_InTangentTime,
+ inValue.m_InTangentValue, inValue.m_OutTangentTime,
+ inValue.m_OutTangentValue);
+ }
+ TKeyframe operator()(const SEaseInEaseOutKeyframe &inValue) const
+ {
+ return CreateEaseInEaseOutKeyframe(inValue.m_KeyframeSeconds, m_Value, inValue.m_EaseIn,
+ inValue.m_EaseOut);
+ }
+ TKeyframe operator()()
+ {
+ QT3DS_ASSERT(false);
+ return TKeyframe();
+ }
+};
+
+inline TKeyframe SetKeyframeValue(const TKeyframe &inKeyframe, float inValue)
+{
+ SKeyframeValueSetter theSetter;
+ theSetter.m_Value = inValue;
+ return inKeyframe.visit<TKeyframe>(theSetter);
+}
+
+inline float AnimationClamp(float inLowerBound, float inUpperBound, float inValue)
+{
+ if (inValue < inLowerBound)
+ return inLowerBound;
+ if (inValue > inUpperBound)
+ return inUpperBound;
+ return inValue;
+}
+
+inline SBezierKeyframe
+CreateBezierKeyframeFromEaseInEaseOutKeyframe(float *inPreviousValue,
+ SEaseInEaseOutKeyframe inCurrent, float *inNextValue)
+{
+ float theValue = inCurrent.m_KeyframeValue;
+ float theSeconds = inCurrent.m_KeyframeSeconds;
+ float inSeconds = 0.f;
+ float inValue = 0.f;
+ float outSeconds = 0.f;
+ float outValue = 0.f;
+ if (inPreviousValue) {
+ float thePercent = 1.0f - AnimationClamp(0.0f, 1.0f, inCurrent.m_EaseIn / 100.f);
+ double theAmount = 1.0f - thePercent * .333333333334;
+ inValue = (float)(*inPreviousValue
+ + ((inCurrent.m_KeyframeValue - *inPreviousValue) * theAmount));
+ }
+ if (inNextValue) {
+ float thePercent = 1.0f - AnimationClamp(0.0f, 1.0f, inCurrent.m_EaseOut / 100.f);
+ double theAmount = thePercent * .3333333333334;
+ outValue = (float)(inCurrent.m_KeyframeValue
+ + ((*inNextValue - inCurrent.m_KeyframeValue) * theAmount));
+ }
+ return CreateBezierKeyframe(theSeconds, theValue, inSeconds, inValue, outSeconds, outValue);
+}
+
+void CopyKeyframes(const IAnimationCore &inSourceAnimationCore, IAnimationCore &inDestAnimationCore,
+ CUICDMAnimationHandle inDestAnimation, const TKeyframeHandleList &inKeyframes);
+
+CUICDMAnimationHandle CopyAnimation(TAnimationCorePtr inSourceAnimationCore,
+ CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inNewSlide,
+ CUICDMInstanceHandle inNewInstance,
+ CUICDMPropertyHandle inNewProperty, size_t inNewIndex);
+
+struct SEaseInGetter
+{
+ float operator()(const SLinearKeyframe &) const { return 0.f; }
+ float operator()(const SBezierKeyframe &) const { return 0.f; }
+ float operator()(const SEaseInEaseOutKeyframe &inValue) const { return inValue.m_EaseIn; }
+ float operator()()
+ {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+};
+struct SEaseOutGetter
+{
+ float operator()(const SLinearKeyframe &) const { return 0.f; }
+ float operator()(const SBezierKeyframe &) const { return 0.f; }
+ float operator()(const SEaseInEaseOutKeyframe &inValue) const { return inValue.m_EaseOut; }
+ float operator()()
+ {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+};
+inline void GetEaseInOutValues(const TKeyframe &inValue, float &outEaseIn, float &outEaseOut)
+{
+ SEaseInGetter theGetter;
+ outEaseIn = inValue.visit<float>(theGetter);
+
+ SEaseOutGetter theEaseOutGetter;
+ outEaseOut = inValue.visit<float>(theEaseOutGetter);
+}
+
+struct SEaseInSetter
+{
+ float m_Value;
+ TKeyframe operator()(SLinearKeyframe &inValue) const { return inValue; }
+ TKeyframe operator()(SBezierKeyframe &inValue) const { return inValue; }
+ TKeyframe operator()(SEaseInEaseOutKeyframe &inKeyframe) const
+ {
+ inKeyframe.m_EaseIn = m_Value;
+ return inKeyframe;
+ }
+ TKeyframe operator()()
+ {
+ QT3DS_ASSERT(false);
+ return TKeyframe();
+ }
+};
+struct SEaseOutSetter
+{
+ float m_Value;
+ TKeyframe operator()(SLinearKeyframe &inValue) const { return inValue; }
+ TKeyframe operator()(SBezierKeyframe &inValue) const { return inValue; }
+ TKeyframe operator()(SEaseInEaseOutKeyframe &inKeyframe) const
+ {
+ inKeyframe.m_EaseOut = m_Value;
+ return inKeyframe;
+ }
+ TKeyframe operator()()
+ {
+ QT3DS_ASSERT(false);
+ return TKeyframe();
+ }
+};
+inline TKeyframe SetEaseInOutValues(TKeyframe &inKeyframe, float inEaseIn, float inEaseOut)
+{
+ SEaseInSetter theSetter;
+ theSetter.m_Value = inEaseIn;
+ inKeyframe.visit<TKeyframe>(theSetter);
+
+ SEaseOutSetter theEaseOutSetter;
+ theEaseOutSetter.m_Value = inEaseOut;
+ inKeyframe.visit<TKeyframe>(theEaseOutSetter);
+
+ return inKeyframe;
+}
+
+void GetKeyframesAsBezier(CUICDMAnimationHandle inAnimation, const IAnimationCore &inAnimationCore,
+ TBezierKeyframeList &outKeyframes);
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.cpp b/src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.cpp
new file mode 100644
index 00000000..f5d96f04
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.cpp
@@ -0,0 +1,561 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include <memory>
+#include "UICDMDataCore.h"
+#include "SimpleDataCore.h"
+#include "DataCoreProducer.h"
+#include "UICDMSlideCore.h"
+
+#include <QtGlobal>
+
+using namespace UICDM;
+using std::make_shared;
+using std::shared_ptr;
+
+#ifdef _WIN32
+#pragma warning(disable : 4100)
+#endif
+
+// SComposerTypePropertyDefinition constructors
+
+namespace {
+
+template <typename TDataType>
+struct DataConstructor
+{
+ template <typename TInputType>
+ TDataType Construct(const TInputType &inInput)
+ {
+ return TDataType(inInput);
+ }
+};
+
+template <>
+struct DataConstructor<SLong4>
+{
+ SLong4 Construct(int inValue)
+ {
+ unsigned long theValue((unsigned long)inValue);
+ return SLong4(theValue, theValue, theValue, theValue);
+ }
+};
+
+template <>
+struct DataConstructor<TDataStrPtr>
+{
+ TDataStrPtr Construct(const wchar_t *inData)
+ {
+ if (IsTrivial(inData))
+ return make_shared<CDataStr>();
+ return make_shared<CDataStr>(inData);
+ }
+};
+template <>
+struct DataConstructor<SStringOrInt>
+{
+ SStringOrInt Construct(const wchar_t *inData)
+ {
+ if (IsTrivial(inData))
+ return make_shared<CDataStr>();
+ return make_shared<CDataStr>(inData);
+ }
+};
+template <>
+struct DataConstructor<SObjectRefType>
+{
+ SObjectRefType Construct(const wchar_t *) { return SObjectRefType(); }
+};
+}
+
+#define UIC_WCHAR_T_Typed L"Typed"
+#define UIC_WCHAR_T_Guided L"Guided"
+#define UIC_WCHAR_T_Named L"Named"
+#define UIC_WCHAR_T_SlideOwner L"SlideOwner"
+#define UIC_WCHAR_T_Slide L"Slide"
+#define UIC_WCHAR_T_Action L"Action"
+#define UIC_WCHAR_T_Asset L"Asset"
+#define UIC_WCHAR_T_Scene L"Scene"
+#define UIC_WCHAR_T_Image L"Image"
+#define UIC_WCHAR_T_Material L"Material"
+#define UIC_WCHAR_T_Behavior L"Behavior"
+#define UIC_WCHAR_T_Node L"Node"
+#define UIC_WCHAR_T_Layer L"Layer"
+#define UIC_WCHAR_T_Group L"Group"
+#define UIC_WCHAR_T_Model L"Model"
+#define UIC_WCHAR_T_Light L"Light"
+#define UIC_WCHAR_T_Camera L"Camera"
+#define UIC_WCHAR_T_Component L"Component"
+#define UIC_WCHAR_T_Text L"Text"
+#define UIC_WCHAR_T_Effect L"Effect"
+#define UIC_WCHAR_T_RenderPlugin L"RenderPlugin"
+#define UIC_WCHAR_T_MaterialBase L"MaterialBase"
+#define UIC_WCHAR_T_CustomMaterial L"CustomMaterial"
+#define UIC_WCHAR_T_ReferencedMaterial L"ReferencedMaterial"
+#define UIC_WCHAR_T_Alias L"Alias"
+#define UIC_WCHAR_T_Lightmaps L"Lightmaps"
+
+#define UIC_WCHAR_T_type L"type"
+#define UIC_WCHAR_T_id L"id"
+#define UIC_WCHAR_T_name L"name"
+#define UIC_WCHAR_T_componentid L"componentid"
+#define UIC_WCHAR_T_playmode L"playmode"
+#define UIC_WCHAR_T_playthroughto L"playthroughto"
+#define UIC_WCHAR_T_initialplaystate L"initialplaystate"
+#define UIC_WCHAR_T_actioneyeball L"actioneyeball"
+#define UIC_WCHAR_T_sourcepath L"sourcepath"
+#define UIC_WCHAR_T_importid L"importid"
+#define UIC_WCHAR_T_starttime L"starttime"
+#define UIC_WCHAR_T_endtime L"endtime"
+#define UIC_WCHAR_T_eyeball L"eyeball"
+#define UIC_WCHAR_T_shy L"shy"
+#define UIC_WCHAR_T_locked L"locked"
+#define UIC_WCHAR_T_timebarcolor L"timebarcolor"
+#define UIC_WCHAR_T_timebartext L"timebartext"
+#define UIC_WCHAR_T_bgcolorenable L"bgcolorenable"
+#define UIC_WCHAR_T_background L"background"
+#define UIC_WCHAR_T_backgroundcolor L"backgroundcolor"
+#define UIC_WCHAR_T_blendtype L"blendtype"
+#define UIC_WCHAR_T_scaleu L"scaleu"
+#define UIC_WCHAR_T_scalev L"scalev"
+#define UIC_WCHAR_T_mappingmode L"mappingmode"
+#define UIC_WCHAR_T_tilingmodehorz L"tilingmodehorz"
+#define UIC_WCHAR_T_tilingmodevert L"tilingmodevert"
+#define UIC_WCHAR_T_rotationuv L"rotationuv"
+#define UIC_WCHAR_T_positionu L"positionu"
+#define UIC_WCHAR_T_positionv L"positionv"
+#define UIC_WCHAR_T_pivotu L"pivotu"
+#define UIC_WCHAR_T_pivotv L"pivotv"
+#define UIC_WCHAR_T_subpresentation L"subpresentation"
+#define UIC_WCHAR_T_iblprobe L"iblprobe"
+#define UIC_WCHAR_T_shaderlighting L"shaderlighting"
+#define UIC_WCHAR_T_blendmode L"blendmode"
+#define UIC_WCHAR_T_diffuse L"diffuse"
+#define UIC_WCHAR_T_diffusemap L"diffusemap"
+#define UIC_WCHAR_T_diffusemap2 L"diffusemap2"
+#define UIC_WCHAR_T_diffusemap3 L"diffusemap3"
+#define UIC_WCHAR_T_specularreflection L"specularreflection"
+#define UIC_WCHAR_T_specularmap L"specularmap"
+#define UIC_WCHAR_T_specularmodel L"specularmodel"
+#define UIC_WCHAR_T_speculartint L"speculartint"
+#define UIC_WCHAR_T_ior L"ior"
+#define UIC_WCHAR_T_specularamount L"specularamount"
+#define UIC_WCHAR_T_specularroughness L"specularroughness"
+#define UIC_WCHAR_T_opacitymap L"opacitymap"
+#define UIC_WCHAR_T_emissivepower L"emissivepower"
+#define UIC_WCHAR_T_emissivecolor L"emissivecolor"
+#define UIC_WCHAR_T_emissivemap L"emissivemap"
+#define UIC_WCHAR_T_emissivemap2 L"emissivemap2"
+#define UIC_WCHAR_T_normalmap L"normalmap"
+#define UIC_WCHAR_T_normalstrength L"normalstrength"
+#define UIC_WCHAR_T_position L"position"
+#define UIC_WCHAR_T_rotation L"rotation"
+#define UIC_WCHAR_T_scale L"scale"
+#define UIC_WCHAR_T_pivot L"pivot"
+#define UIC_WCHAR_T_opacity L"opacity"
+#define UIC_WCHAR_T_rotationorder L"rotationorder"
+#define UIC_WCHAR_T_orientation L"orientation"
+#define UIC_WCHAR_T_progressiveaa L"progressiveaa"
+#define UIC_WCHAR_T_multisampleaa L"multisampleaa"
+#define UIC_WCHAR_T_disabledepthtest L"disabledepthtest"
+#define UIC_WCHAR_T_disabledepthprepass L"disabledepthprepass"
+#define UIC_WCHAR_T_layerwidth L"layerwidth"
+#define UIC_WCHAR_T_layerheight L"layerheight"
+#define UIC_WCHAR_T_lighttype L"lighttype"
+#define UIC_WCHAR_T_lightdiffuse L"lightdiffuse"
+#define UIC_WCHAR_T_lightspecular L"lightspecular"
+#define UIC_WCHAR_T_lightambient L"lightambient"
+#define UIC_WCHAR_T_brightness L"brightness"
+#define UIC_WCHAR_T_linearfade L"linearfade"
+#define UIC_WCHAR_T_expfade L"expfade"
+#define UIC_WCHAR_T_areawidth L"areawidth"
+#define UIC_WCHAR_T_areaheight L"areaheight"
+#define UIC_WCHAR_T_castshadow L"castshadow"
+#define UIC_WCHAR_T_shdwbias L"shdwbias"
+#define UIC_WCHAR_T_shdwfactor L"shdwfactor"
+#define UIC_WCHAR_T_shdwmapres L"shdwmapres"
+#define UIC_WCHAR_T_shdwmapfar L"shdwmapfar"
+#define UIC_WCHAR_T_shdwfilter L"shdwfilter"
+#define UIC_WCHAR_T_orthographic L"orthographic"
+#define UIC_WCHAR_T_fov L"fov"
+#define UIC_WCHAR_T_clipnear L"clipnear"
+#define UIC_WCHAR_T_clipfar L"clipfar"
+#define UIC_WCHAR_T_lookatlock L"lookatlock"
+#define UIC_WCHAR_T_lookatpoint L"lookatpoint"
+#define UIC_WCHAR_T_textstring L"textstring"
+#define UIC_WCHAR_T_textcolor L"textcolor"
+#define UIC_WCHAR_T_font L"font"
+#define UIC_WCHAR_T_size L"size"
+#define UIC_WCHAR_T_horzalign L"horzalign"
+#define UIC_WCHAR_T_vertalign L"vertalign"
+#define UIC_WCHAR_T_leading L"leading"
+#define UIC_WCHAR_T_tracking L"tracking"
+#define UIC_WCHAR_T_enableacceleratedfont L"enableacceleratedfont"
+#define UIC_WCHAR_T_importfile L"importfile"
+#define UIC_WCHAR_T_fileid L"fileid"
+#define UIC_WCHAR_T_size L"size"
+#define UIC_WCHAR_T_location L"location"
+#define UIC_WCHAR_T_boneid L"boneid"
+#define UIC_WCHAR_T_poseroot L"poseroot"
+#define UIC_WCHAR_T_ignoresparent L"ignoresparent"
+#define UIC_WCHAR_T_tessellation L"tessellation"
+#define UIC_WCHAR_T_edgetess L"edgetess"
+#define UIC_WCHAR_T_innertess L"innertess"
+#define UIC_WCHAR_T_scalemode L"scalemode"
+#define UIC_WCHAR_T_scaleanchor L"scaleanchor"
+#define UIC_WCHAR_T_horzfields L"horzfields"
+#define UIC_WCHAR_T_left L"left"
+#define UIC_WCHAR_T_leftunits L"leftunits"
+#define UIC_WCHAR_T_width L"width"
+#define UIC_WCHAR_T_widthunits L"widthunits"
+#define UIC_WCHAR_T_right L"right"
+#define UIC_WCHAR_T_rightunits L"rightunits"
+#define UIC_WCHAR_T_vertfields L"vertfields"
+#define UIC_WCHAR_T_top L"top"
+#define UIC_WCHAR_T_topunits L"topunits"
+#define UIC_WCHAR_T_height L"height"
+#define UIC_WCHAR_T_heightunits L"heightunits"
+#define UIC_WCHAR_T_bottom L"bottom"
+#define UIC_WCHAR_T_bottomunits L"bottomunits"
+#define UIC_WCHAR_T_aostrength L"aostrength"
+#define UIC_WCHAR_T_aodistance L"aodistance"
+#define UIC_WCHAR_T_aosoftness L"aosoftness"
+#define UIC_WCHAR_T_aobias L"aobias"
+#define UIC_WCHAR_T_aosamplerate L"aosamplerate"
+#define UIC_WCHAR_T_aodither L"aodither"
+#define UIC_WCHAR_T_shadowstrength L"shadowstrength"
+#define UIC_WCHAR_T_shadowdist L"shadowdist"
+#define UIC_WCHAR_T_shadowsoftness L"shadowsoftness"
+#define UIC_WCHAR_T_shadowbias L"shadowbias"
+#define UIC_WCHAR_T_source L"source"
+#define UIC_WCHAR_T_referencedmaterial L"referencedmaterial"
+#define UIC_WCHAR_T_lightprobe L"lightprobe"
+#define UIC_WCHAR_T_probebright L"probebright"
+#define UIC_WCHAR_T_fastibl L"fastibl"
+#define UIC_WCHAR_T_probehorizon L"probehorizon"
+#define UIC_WCHAR_T_probefov L"probefov"
+#define UIC_WCHAR_T_lightprobe2 L"lightprobe2"
+#define UIC_WCHAR_T_probe2fade L"probe2fade"
+#define UIC_WCHAR_T_probe2window L"probe2window"
+#define UIC_WCHAR_T_probe2pos L"probe2pos"
+#define UIC_WCHAR_T_bumpmap L"bumpmap"
+#define UIC_WCHAR_T_bumpamount L"bumpamount"
+#define UIC_WCHAR_T_normalmap L"normalmap"
+#define UIC_WCHAR_T_displacementmap L"displacementmap"
+#define UIC_WCHAR_T_displaceamount L"displaceamount"
+#define UIC_WCHAR_T_translucencymap L"translucencymap"
+#define UIC_WCHAR_T_translucentfalloff L"translucentfalloff"
+#define UIC_WCHAR_T_diffuselightwrap L"diffuselightwrap"
+#define UIC_WCHAR_T_fresnelPower L"fresnelPower"
+#define UIC_WCHAR_T_referencednode L"referencednode"
+#define UIC_WCHAR_T_temporalaa L"temporalaa"
+#define UIC_WCHAR_T_scope L"scope"
+#define UIC_WCHAR_T_Path L"Path"
+#define UIC_WCHAR_T_pathdata L"pathdata"
+#define UIC_WCHAR_T_PathAnchorPoint L"PathAnchorPoint"
+#define UIC_WCHAR_T_incomingangle L"incomingangle"
+#define UIC_WCHAR_T_incomingdistance L"incomingdistance"
+#define UIC_WCHAR_T_outgoingdistance L"outgoingdistance"
+#define UIC_WCHAR_T_linearerror L"linearerror"
+#define UIC_WCHAR_T_edgetessamount L"edgetessamount"
+#define UIC_WCHAR_T_innertessamount L"innertessamount"
+#define UIC_WCHAR_T_begincap L"begincap"
+#define UIC_WCHAR_T_begincapoffset L"begincapoffset"
+#define UIC_WCHAR_T_begincapopacity L"begincapopacity"
+#define UIC_WCHAR_T_begincapwidth L"begincapwidth"
+#define UIC_WCHAR_T_endcap L"endcap"
+#define UIC_WCHAR_T_endcapoffset L"endcapoffset"
+#define UIC_WCHAR_T_endcapopacity L"endcapopacity"
+#define UIC_WCHAR_T_endcapwidth L"endcapwidth"
+#define UIC_WCHAR_T_pathtype L"pathtype"
+#define UIC_WCHAR_T_closed L"closed"
+#define UIC_WCHAR_T_paintstyle L"paintstyle"
+#define UIC_WCHAR_T_SubPath L"SubPath"
+#define UIC_WCHAR_T_lightmapindirect L"lightmapindirect"
+#define UIC_WCHAR_T_lightmapradiosity L"lightmapradiosity"
+#define UIC_WCHAR_T_lightmapshadow L"lightmapshadow"
+
+const wchar_t *ComposerObjectTypes::Convert(ComposerObjectTypes::Enum inType)
+{
+ switch (inType) {
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ case name: \
+ return UIC_WCHAR_T_##name;
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+ }
+ QT3DS_ASSERT(false);
+ return L"Unknown";
+}
+
+ComposerObjectTypes::Enum ComposerObjectTypes::Convert(const wchar_t *inType)
+{
+
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ if (AreEqual(UIC_WCHAR_T_##name, inType)) \
+ return ComposerObjectTypes::name;
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+
+ QT3DS_ASSERT(false);
+ return ComposerObjectTypes::Unknown;
+}
+
+ComposerObjectTypes::Enum ComposerObjectTypes::Convert(const char8_t *inType)
+{
+
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ if (AreEqual(#name, inType)) \
+ return ComposerObjectTypes::name;
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+
+ QT3DS_ASSERT(false);
+ return ComposerObjectTypes::Unknown;
+}
+
+const wchar_t *ComposerPropertyNames::Convert(ComposerPropertyNames::Enum inType)
+{
+ switch (inType) {
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue)
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \
+ case name: \
+ return UIC_WCHAR_T_##name;
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type)
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return L"Unknown";
+}
+
+ComposerPropertyNames::Enum ComposerPropertyNames::Convert(const wchar_t *inType)
+{
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue)
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \
+ if (AreEqual(inType, UIC_WCHAR_T_##name)) \
+ return name;
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type)
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+ QT3DS_ASSERT(false);
+ return ComposerPropertyNames::Unknown;
+}
+
+const char8_t *ComposerPropertyNames::ConvertNarrow(ComposerPropertyNames::Enum inType)
+{
+ switch (inType) {
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue)
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \
+ case name: \
+ return #name;
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type)
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return "Unknown";
+}
+
+ComposerPropertyNames::Enum ComposerPropertyNames::Convert(const char8_t *inType)
+{
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue)
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) \
+ if (AreEqual(inType, #name)) \
+ return name;
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type)
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+ QT3DS_ASSERT(false);
+ return ComposerPropertyNames::Unknown;
+}
+
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \
+ , memberName(inCore, inInstance, DataConstructor<dtype>().Construct(defaultValue))
+
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \
+ , memberName(inCore, inInstance)
+
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue)
+
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ SComposerTypePropertyDefinition<ComposerObjectTypes::name>::SComposerTypePropertyDefinition( \
+ IDataCore &inCore, CUICDMInstanceHandle inInstance) \
+ : reserved(false) propmacro \
+ { \
+ Q_UNUSED(inCore);\
+ Q_UNUSED(inInstance);\
+ }
+ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+
+void ComposerTypeDefinitionsHelper::SetInstanceAsCanonical(IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ ComposerObjectTypes::Enum inObjectType)
+{
+ inMetaData.SetInstanceAsCanonical(inInstance, ComposerObjectTypes::Convert(inObjectType));
+}
+
+void ComposerTypeDefinitionsHelper::SetInstancePropertyValue(IDataCore &inDataCore,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const wchar_t *inPropValue)
+{
+ inDataCore.SetInstancePropertyValue(inInstance, inProperty, make_shared<CDataStr>(inPropValue));
+}
+
+void ComposerTypeDefinitionsHelper::DeriveInstance(IDataCore &inDataCore,
+ CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent)
+{
+ inDataCore.DeriveInstance(inInstance, inParent);
+}
+
+// Container object for all of the object definitions
+SComposerObjectDefinitions::SComposerObjectDefinitions(
+ IDataCore &inCore,
+ IMetaData &inMetaData /*, ISlideCore& inSlideCore, IPropertySystem& inPropertySystem*/)
+ : m_DataCore(inCore)
+ , m_MetaData(inMetaData)
+ //, m_SlideCore( inSlideCore )
+ //, m_PropertySystem( inPropertySystem )
+ , m_Typed(inCore, inMetaData, inCore.CreateInstance())
+ , m_Guided(inCore, inMetaData, inCore.CreateInstance())
+ , m_Named(inCore, inMetaData, inCore.CreateInstance())
+ , m_SlideOwner(inCore, inMetaData, inCore.CreateInstance())
+ , m_Slide(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Named)
+ , m_Action(inCore, inMetaData, inCore.CreateInstance(), m_Typed)
+ , m_Asset(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Guided, m_Named)
+ , m_Scene(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset, m_SlideOwner)
+ , m_Image(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_Lightmaps(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_MaterialBase(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Lightmaps)
+ , m_Material(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_MaterialBase)
+ , m_CustomMaterial(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_MaterialBase)
+ , m_ReferencedMaterial(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_MaterialBase)
+ , m_Behavior(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_Node(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_Layer(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Model(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Group(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Light(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Camera(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Component(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node, m_SlideOwner)
+ , m_Text(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Effect(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_RenderPlugin(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_Alias(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Path(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_PathAnchorPoint(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+ , m_SubPath(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
+{
+}
+
+bool SComposerObjectDefinitions::IsA(CUICDMInstanceHandle inInstance,
+ ComposerObjectTypes::Enum inType)
+{
+ if (m_DataCore.IsInstance(inInstance) == false)
+ return false;
+
+ switch (inType) {
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ case ComposerObjectTypes::name: \
+ return m_DataCore.IsInstanceOrDerivedFrom(inInstance, m_##name.m_Instance);
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+ }
+ QT3DS_ASSERT(false);
+ return false;
+}
+
+// Could easily return None, meaning we can't identify the object type.
+// Checks the type of the first derivation parent, so this won't ever return
+// SlideOwner, for instance.
+ComposerObjectTypes::Enum SComposerObjectDefinitions::GetType(CUICDMInstanceHandle inInstance)
+{
+ if (m_DataCore.IsInstance(inInstance) == false)
+ return ComposerObjectTypes::Unknown;
+
+ CUICDMInstanceHandle theTargetInstance = inInstance;
+ TInstanceHandleList theHandleList;
+ m_DataCore.GetInstanceParents(inInstance, theHandleList);
+ if (theHandleList.empty() == false)
+ theTargetInstance = theHandleList[0];
+
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ if (m_##name.m_Instance == theTargetInstance) \
+ return ComposerObjectTypes::name;
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+
+ return ComposerObjectTypes::Unknown;
+}
+
+CUICDMInstanceHandle
+SComposerObjectDefinitions::GetInstanceForType(ComposerObjectTypes::Enum inType)
+{
+ switch (inType) {
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ case ComposerObjectTypes::name: \
+ return m_##name.m_Instance;
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.h b/src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.h
new file mode 100644
index 00000000..49a290d3
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.h
@@ -0,0 +1,922 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#include "UICDMHandles.h"
+#include "UICDMDataTypes.h"
+#include "foundation/Qt3DSOption.h"
+#include "UICDMDataCore.h"
+#include <utility>
+
+// Defines the minimal property model that UIComposer needs to
+// run off of.
+namespace UICDM {
+class IDataCore;
+class IMetaData;
+class ISlideCore;
+class IPropertySystem;
+
+// Extensible macro definitions
+// Enumerations *have* to be in derivation order
+// else initialization of the SComposerObjectDefinitions class
+// will fail catastrophically
+// Specific type documentation is below
+#define ITERATE_COMPOSER_OBJECT_TYPES \
+ HANDLE_COMPOSER_OBJECT_TYPE(Typed, ITERATE_COMPOSER_TYPED_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Guided, ITERATE_COMPOSER_GUIDED_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Named, ITERATE_COMPOSER_NAMED_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(SlideOwner, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Slide, ITERATE_COMPOSER_SLIDE_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Action, ITERATE_COMPOSER_ACTION_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Asset, ITERATE_COMPOSER_ASSET_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Scene, ITERATE_COMPOSER_SCENE_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Image, ITERATE_COMPOSER_IMAGE_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Lightmaps, ITERATE_COMPOSER_LIGHTMAP_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(MaterialBase, ITERATE_COMPOSER_MATERIAL_BASE_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Material, ITERATE_COMPOSER_MATERIAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(CustomMaterial, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(ReferencedMaterial, \
+ ITERATE_COMPOSER_REFERENCED_MATERIAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Behavior, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Effect, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Node, ITERATE_COMPOSER_NODE_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Layer, ITERATE_COMPOSER_LAYER_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Group, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Model, ITERATE_COMPOSER_MODEL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Light, ITERATE_COMPOSER_LIGHT_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Camera, ITERATE_COMPOSER_CAMERA_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Component, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Text, ITERATE_COMPOSER_TEXT_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(RenderPlugin, ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Alias, ITERATE_COMPOSER_ALIAS_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Path, ITERATE_COMPOSER_PATH_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(PathAnchorPoint, ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(SubPath, ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES)
+
+#define ITERATE_COMPOSER_NO_ADDITIONAL_PROPERTIES
+
+#define ITERATE_COMPOSER_TYPED_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(type, m_TypeProp, TDataStrPtr, L"Typed")
+
+#define ITERATE_COMPOSER_GUIDED_PROPERTIES HANDLE_COMPOSER_PROPERTY(id, m_GuidProp, SLong4, 0)
+
+#define ITERATE_COMPOSER_NAMED_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(name, m_NameProp, TDataStrPtr, L"Unnamed")
+
+#define ITERATE_COMPOSER_ASSET_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(sourcepath, m_SourcePath, TDataStrPtr, L"") \
+ HANDLE_COMPOSER_PROPERTY(importid, m_ImportId, TDataStrPtr, L"") \
+ HANDLE_COMPOSER_PROPERTY(importfile, m_ImportFile, TDataStrPtr, L"") \
+ HANDLE_COMPOSER_PROPERTY(fileid, m_FileId, TDataStrPtr, L"") \
+ HANDLE_COMPOSER_PROPERTY(starttime, m_StartTime, qt3ds::QT3DSI32, 0) \
+ HANDLE_COMPOSER_PROPERTY(endtime, m_EndTime, qt3ds::QT3DSI32, 10000) \
+ HANDLE_COMPOSER_PROPERTY(eyeball, m_Eyeball, bool, true) \
+ HANDLE_COMPOSER_PROPERTY(shy, m_Shy, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(locked, m_Locked, bool, false) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(timebarcolor, m_TimebarColor, SFloat3) \
+ HANDLE_COMPOSER_PROPERTY(timebartext, m_TimebarText, SStringRef, L"")
+
+#define ITERATE_COMPOSER_SCENE_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(bgcolorenable, m_BgColorEnable, bool, true) \
+ HANDLE_COMPOSER_PROPERTY(backgroundcolor, m_BackgroundColor, SFloat3, SFloat3(0, 0, 0))
+
+#define ITERATE_COMPOSER_NODE_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(position, m_Position, SFloat3, SFloat3(0, 0, 0)) \
+ HANDLE_COMPOSER_PROPERTY(rotation, m_Rotation, SFloat3, SFloat3(0, 0, 0)) \
+ HANDLE_COMPOSER_PROPERTY(scale, m_Scale, SFloat3, SFloat3(1, 1, 1)) \
+ HANDLE_COMPOSER_PROPERTY(pivot, m_Pivot, SFloat3, SFloat3(0, 0, 0)) \
+ HANDLE_COMPOSER_PROPERTY(opacity, m_Opacity, float, 100.f) \
+ HANDLE_COMPOSER_PROPERTY(rotationorder, m_RotationOrder, TDataStrPtr, L"YXZ") \
+ HANDLE_COMPOSER_PROPERTY(orientation, m_Orientation, TDataStrPtr, L"Left Handed") \
+ HANDLE_COMPOSER_PROPERTY(boneid, m_BoneId, qt3ds::QT3DSI32, 0) \
+ HANDLE_COMPOSER_PROPERTY(ignoresparent, m_IgnoresParent, bool, false)
+
+#define ITERATE_COMPOSER_MODEL_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(poseroot, m_PoseRoot, qt3ds::QT3DSI32, -1) \
+ HANDLE_COMPOSER_PROPERTY(tessellation, m_Tessellation, TDataStrPtr, L"None") \
+ HANDLE_COMPOSER_PROPERTY(edgetess, m_EdgeTess, float, 1.0) \
+ HANDLE_COMPOSER_PROPERTY(innertess, m_InnerTess, float, 1.0)
+
+#define ITERATE_COMPOSER_IMAGE_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(scaleu, m_RepeatU, float, 1.0f) \
+ HANDLE_COMPOSER_PROPERTY(scalev, m_RepeatV, float, 1.0f) \
+ HANDLE_COMPOSER_PROPERTY(mappingmode, m_TextureMapping, TDataStrPtr, L"UV Mapping") \
+ HANDLE_COMPOSER_PROPERTY(tilingmodehorz, m_TilingU, TDataStrPtr, L"No Tiling") \
+ HANDLE_COMPOSER_PROPERTY(tilingmodevert, m_TilingV, TDataStrPtr, L"No Tiling") \
+ HANDLE_COMPOSER_PROPERTY(rotationuv, m_RotationUV, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(positionu, m_PositionU, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(positionv, m_PositionV, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(pivotu, m_PivotU, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(pivotv, m_PivotV, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(subpresentation, m_SubPresentation, TDataStrPtr, L"")
+
+#define ITERATE_COMPOSER_LIGHTMAP_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(lightmapindirect, m_LightmapIndirect, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(lightmapradiosity, m_LightmapRadiosity, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(lightmapshadow, m_LightmapShadow, SLong4, 0)
+
+#define ITERATE_COMPOSER_CUSTOM_MATERIAL_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(iblprobe, m_IblProbe, SLong4, 0)
+
+#define ITERATE_COMPOSER_MATERIAL_BASE_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(iblprobe, m_IblProbe, SLong4, 0)
+
+#define ITERATE_COMPOSER_MATERIAL_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(shaderlighting, m_ShaderLighting, TDataStrPtr, L"Vertex") \
+ HANDLE_COMPOSER_PROPERTY(blendmode, m_BlendMode, TDataStrPtr, L"Normal") \
+ HANDLE_COMPOSER_PROPERTY(diffuse, m_DiffuseColor, SFloat3, SFloat3(1, 1, 1)) \
+ HANDLE_COMPOSER_PROPERTY(diffusemap, m_DiffuseMap1, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(diffusemap2, m_DiffuseMap2, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(diffusemap3, m_DiffuseMap3, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(specularreflection, m_SpecularReflection, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(specularamount, m_SpecularAmount, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(specularroughness, m_SpecularRoughness, float, 50.f) \
+ HANDLE_COMPOSER_PROPERTY_DUPLICATE(opacity, m_Opacity, float, 100.f) \
+ HANDLE_COMPOSER_PROPERTY(opacitymap, m_OpacityMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(emissivecolor, m_EmissiveColor, SFloat3, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(emissivepower, m_EmissivePower, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(emissivemap, m_EmissiveMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(emissivemap2, m_EmissiveMap2, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(bumpmap, m_BumpMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(bumpamount, m_BumpAmount, float, 9.0f) \
+ HANDLE_COMPOSER_PROPERTY(normalmap, m_NormalMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(displacementmap, m_DisplacementMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(displaceamount, m_DisplaceAmount, float, 0.5f) \
+ HANDLE_COMPOSER_PROPERTY(translucencymap, m_TranslucencyMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(translucentfalloff, m_TranslucentFalloff, float, 1.f) \
+ HANDLE_COMPOSER_PROPERTY(diffuselightwrap, m_DiffuseLightWrap, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(specularmap, m_SpecularMap, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(specularmodel, m_SpecularModel, TDataStrPtr, L"Default") \
+ HANDLE_COMPOSER_PROPERTY(speculartint, m_SpecularTint, SFloat3, SFloat3(1, 1, 1)) \
+ HANDLE_COMPOSER_PROPERTY(ior, m_IOR, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(fresnelPower, m_FresnelPower, float, 0)
+
+#define ITERATE_COMPOSER_REFERENCED_MATERIAL_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(referencedmaterial, m_ReferencedMaterial, SObjectRefType, L"")
+
+#define ITERATE_COMPOSER_LAYER_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(progressiveaa, m_ProgressiveAA, TDataStrPtr, L"None") \
+ HANDLE_COMPOSER_PROPERTY(multisampleaa, m_MultisampleAA, TDataStrPtr, L"None") \
+ HANDLE_COMPOSER_PROPERTY(temporalaa, m_TemporalAA, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(disabledepthtest, m_DisableDepthTest, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(disabledepthprepass, m_DisableDepthPrepass, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(background, m_Background, TDataStrPtr, L"Transparent") \
+ HANDLE_COMPOSER_PROPERTY_DUPLICATE(backgroundcolor, m_BackgroundColor, SFloat3, \
+ SFloat3(0, 0, 0)) \
+ HANDLE_COMPOSER_PROPERTY(blendtype, m_BlendType, TDataStrPtr, L"Normal") \
+ HANDLE_COMPOSER_PROPERTY(horzfields, m_HorizontalFieldValues, TDataStrPtr, L"Left/Width") \
+ HANDLE_COMPOSER_PROPERTY(left, m_Left, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(leftunits, m_LeftUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(width, m_Width, float, 100.0f) \
+ HANDLE_COMPOSER_PROPERTY(widthunits, m_WidthUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(right, m_Right, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(rightunits, m_RightUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(vertfields, m_VerticalFieldValues, TDataStrPtr, L"Top/Height") \
+ HANDLE_COMPOSER_PROPERTY(top, m_Top, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(topunits, m_TopUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(height, m_Height, float, 100.0f) \
+ HANDLE_COMPOSER_PROPERTY(heightunits, m_HeightUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(bottom, m_Bottom, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(bottomunits, m_BottomUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(aostrength, m_AoStrength, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(aodistance, m_AoDistance, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(aosoftness, m_AoSoftness, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(aobias, m_AoBias, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(aosamplerate, m_AoSamplerate, qt3ds::QT3DSI32, 1) \
+ HANDLE_COMPOSER_PROPERTY(aodither, m_AoDither, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(shadowstrength, m_ShadowStrength, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(shadowdist, m_ShadowDist, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(shadowsoftness, m_ShadowSoftness, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(shadowbias, m_ShadowBias, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(lightprobe, m_LightProbe, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(probebright, m_ProbeBright, float, 100.0f) \
+ HANDLE_COMPOSER_PROPERTY(fastibl, m_FastIbl, bool, true) \
+ HANDLE_COMPOSER_PROPERTY(probehorizon, m_ProbeHorizon, float, -1) \
+ HANDLE_COMPOSER_PROPERTY(probefov, m_ProbeFov, float, 180.0f) \
+ HANDLE_COMPOSER_PROPERTY(lightprobe2, m_LightProbe2, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(probe2fade, m_Probe2Fade, float, 1) \
+ HANDLE_COMPOSER_PROPERTY(probe2window, m_Probe2Window, float, 1) \
+ HANDLE_COMPOSER_PROPERTY(probe2pos, m_Probe2Pos, float, 0.5f)
+
+#define ITERATE_COMPOSER_LIGHT_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(lighttype, m_LightType, TDataStrPtr, L"Directional") \
+ HANDLE_COMPOSER_PROPERTY(scope, m_Scope, SObjectRefType, L"") \
+ HANDLE_COMPOSER_PROPERTY(lightdiffuse, m_LightColor, SFloat3, SFloat3(1, 1, 1)) \
+ HANDLE_COMPOSER_PROPERTY(lightspecular, m_SpecularColor, SFloat3, SFloat3(1, 1, 1)) \
+ HANDLE_COMPOSER_PROPERTY(lightambient, m_AmbientColor, SFloat3, SFloat3(0, 0, 0)) \
+ HANDLE_COMPOSER_PROPERTY(brightness, m_Brightness, float, 100.0f) \
+ HANDLE_COMPOSER_PROPERTY(linearfade, m_LinearFade, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(expfade, m_ExpFade, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(areawidth, m_AreaWidth, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(areaheight, m_AreaHeight, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(castshadow, m_CastShadow, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(shdwbias, m_ShadowBias, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(shdwfactor, m_ShadowFactor, float, 5.0f) \
+ HANDLE_COMPOSER_PROPERTY(shdwmapres, m_ShadowMapRes, qt3ds::QT3DSI32, 9) \
+ HANDLE_COMPOSER_PROPERTY(shdwmapfar, m_ShadowMapFar, float, 5000.0f) \
+ HANDLE_COMPOSER_PROPERTY(shdwfilter, m_ShadowFilter, float, 35.0f)
+
+#define ITERATE_COMPOSER_CAMERA_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(orthographic, m_Orthographic, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(fov, m_Fov, float, 60.f) \
+ HANDLE_COMPOSER_PROPERTY(clipnear, m_ClipNear, float, 10.f) \
+ HANDLE_COMPOSER_PROPERTY(clipfar, m_ClipFar, float, 100000.f) \
+ HANDLE_COMPOSER_PROPERTY(scalemode, m_ScaleMode, TDataStrPtr, L"Fit") \
+ HANDLE_COMPOSER_PROPERTY(scaleanchor, m_ScaleAnchor, TDataStrPtr, L"Center")
+
+#define ITERATE_COMPOSER_EDIT_CAMERA_PROPERTIES HANDLE_COMPOSER_PROPERTY(is3d, m_Is3d, bool, false)
+
+#define ITERATE_COMPOSER_TEXT_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(textstring, m_TextString, TDataStrPtr, L"Text") \
+ HANDLE_COMPOSER_PROPERTY(textcolor, m_TextColor, SFloat3, SFloat3(1, 1, 1)) \
+ HANDLE_COMPOSER_PROPERTY(font, m_Font, TDataStrPtr, L"arial") \
+ HANDLE_COMPOSER_PROPERTY(size, m_Size, float, 24.f) \
+ HANDLE_COMPOSER_PROPERTY(horzalign, m_HorzAlign, TDataStrPtr, L"Center") \
+ HANDLE_COMPOSER_PROPERTY(vertalign, m_VertAlign, TDataStrPtr, L"Middle") \
+ HANDLE_COMPOSER_PROPERTY(leading, m_Leading, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(tracking, m_Tracking, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(enableacceleratedfont, m_EnableAcceleratedFont, bool, false)
+
+#define ITERATE_COMPOSER_SLIDE_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(componentid, m_ComponentId, SLong4, 0) \
+ HANDLE_COMPOSER_PROPERTY(playmode, m_PlayMode, TDataStrPtr, L"Looping") \
+ HANDLE_COMPOSER_PROPERTY(playthroughto, m_PlaythroughTo, SStringOrInt, L"Next") \
+ HANDLE_COMPOSER_PROPERTY(initialplaystate, m_InitialPlayState, TDataStrPtr, L"Play")
+
+#define ITERATE_COMPOSER_ACTION_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(actioneyeball, m_ActionEyeball, bool, true)
+
+#define ITERATE_COMPOSER_ALIAS_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(referencednode, m_ReferencedNode, SObjectRefType, L"")
+
+#define ITERATE_COMPOSER_PATH_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(pathtype, m_PathType, TDataStrPtr, L"Geometry") \
+ HANDLE_COMPOSER_PROPERTY_DUPLICATE(width, m_Width, float, 5.0f) \
+ HANDLE_COMPOSER_PROPERTY(linearerror, m_LinearError, float, 10) \
+ HANDLE_COMPOSER_PROPERTY(edgetessamount, m_EdgeTessAmount, float, 8) \
+ HANDLE_COMPOSER_PROPERTY(innertessamount, m_InnerTessAmount, float, 8) \
+ HANDLE_COMPOSER_PROPERTY(begincap, m_BeginCap, TDataStrPtr, L"None") \
+ HANDLE_COMPOSER_PROPERTY(begincapoffset, m_BeginCapOffset, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(begincapopacity, m_BeginCapOpacity, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(begincapwidth, m_BeginCapWidth, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(endcap, m_EndCap, TDataStrPtr, L"None") \
+ HANDLE_COMPOSER_PROPERTY(endcapoffset, m_EndCapOffset, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(endcapopacity, m_EndCapOpacity, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(endcapwidth, m_EndCapWidth, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(paintstyle, m_PaintStyle, TDataStrPtr, L"Stroked")
+
+#define ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY_DUPLICATE(position, m_Position, SFloat2, SFloat2(0.0f, 0.0f)) \
+ HANDLE_COMPOSER_PROPERTY(incomingangle, m_IncomingAngle, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(incomingdistance, m_IncomingDistance, float, 0.0f) \
+ HANDLE_COMPOSER_PROPERTY(outgoingdistance, m_OutgoingDistance, float, 0.0f)
+
+#define ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY(closed, m_Closed, bool, true)
+
+struct ComposerObjectTypes
+{
+ enum Enum {
+ Unknown = 0,
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) name,
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+ };
+ static const wchar_t *Convert(ComposerObjectTypes::Enum inType);
+ static ComposerObjectTypes::Enum Convert(const wchar_t *inType);
+ static ComposerObjectTypes::Enum Convert(const char8_t *inType);
+};
+
+struct ComposerPropertyNames
+{
+ enum Enum {
+ Unknown = 0,
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, type) name,
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, type, defaultValue)
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, type, defaultValue) name,
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) propmacro
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+ };
+
+ static const wchar_t *Convert(ComposerPropertyNames::Enum inType);
+ static ComposerPropertyNames::Enum Convert(const wchar_t *inType);
+ static const char8_t *ConvertNarrow(ComposerPropertyNames::Enum inType);
+ static ComposerPropertyNames::Enum Convert(const char8_t *inType);
+};
+
+template <typename TDataType>
+struct TypeToDataTypeMap
+{
+ bool force_compile_error;
+};
+template <DataModelDataType::Value TEnum>
+struct DataTypeToTypeMap
+{
+ bool force_compile_error;
+};
+
+#define UICDM_DEFINE_TYPE_TO_DATA_TYPE(enumName, type) \
+ template <> \
+ struct TypeToDataTypeMap<type> \
+ { \
+ static DataModelDataType::Value GetDataType() { return enumName; } \
+ }; \
+ template <> \
+ struct DataTypeToTypeMap<enumName> \
+ { \
+ typedef type TDataType; \
+ };
+
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float, float)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float2, SFloat2)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Float3, SFloat3)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Long, qt3ds::QT3DSI32)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::String, TDataStrPtr)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Bool, bool)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::Long4, SLong4)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::StringRef, SStringRef)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::StringOrInt, SStringOrInt)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::ObjectRef, SObjectRefType)
+UICDM_DEFINE_TYPE_TO_DATA_TYPE(DataModelDataType::FloatList, TFloatList)
+
+#undef UICDM_DEFINE_TYPE_TO_DATA_TYPE
+
+template <typename TDataType>
+inline DataModelDataType::Value TypeToDataType()
+{
+ return TypeToDataTypeMap<TDataType>::GetDataType();
+}
+
+template <ComposerPropertyNames::Enum TPropName, typename TDataType>
+struct SComposerPropertyDefinition
+{
+ qt3ds::foundation::Option<TDataType> m_DefaultValue;
+ CUICDMPropertyHandle m_Property;
+ SComposerPropertyDefinition(IDataCore &inDataCore, CUICDMInstanceHandle inInstance,
+ const TDataType &inDefault)
+ : m_DefaultValue(inDefault)
+ {
+ UICDM_LOG_FUNCTION("SComposerPropertyDefinition-1");
+ m_Property = inDataCore.AddProperty(inInstance, ComposerPropertyNames::Convert(TPropName),
+ TypeToDataType<TDataType>());
+ if (m_DefaultValue.hasValue())
+ inDataCore.SetInstancePropertyValue(inInstance, m_Property, m_DefaultValue.getValue());
+ }
+ SComposerPropertyDefinition(IDataCore &inDataCore, CUICDMInstanceHandle inInstance)
+ {
+ UICDM_LOG_FUNCTION("SComposerPropertyDefinition-2");
+ m_Property = inDataCore.AddProperty(inInstance, ComposerPropertyNames::Convert(TPropName),
+ TypeToDataType<TDataType>());
+ }
+ operator CUICDMPropertyHandle() const { return m_Property; }
+};
+
+// Define all the objects with their properties
+
+template <ComposerObjectTypes::Enum>
+struct SComposerTypePropertyDefinition
+{
+ bool force_compile_error;
+};
+
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \
+ SComposerPropertyDefinition<ComposerPropertyNames::name, dtype> memberName;
+
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype)
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue)
+
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ template <> \
+ struct SComposerTypePropertyDefinition<ComposerObjectTypes::name> \
+ { \
+ bool reserved; \
+ propmacro SComposerTypePropertyDefinition(IDataCore &inCore, \
+ CUICDMInstanceHandle inInstance); \
+ };
+
+ITERATE_COMPOSER_OBJECT_TYPES
+
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+
+struct ComposerTypeDefinitionsHelper
+{
+ // Functions here so we don't have to include UICDMDataCore.h or UICDMMetaData.h
+ static void SetInstanceAsCanonical(IMetaData &inMetaData, CUICDMInstanceHandle inInstance,
+ ComposerObjectTypes::Enum inObjectType);
+ static void SetInstancePropertyValue(IDataCore &inDataCore, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const wchar_t *inPropValue);
+ static void DeriveInstance(IDataCore &inDataCore, CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent);
+};
+
+template <ComposerObjectTypes::Enum TEnumType>
+struct SComposerBaseObjectDefinition : public SComposerTypePropertyDefinition<TEnumType>
+{
+ CUICDMInstanceHandle m_Instance;
+ SComposerBaseObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance)
+ : SComposerTypePropertyDefinition<TEnumType>(inCore, inInstance)
+ , m_Instance(inInstance)
+ {
+ UICDM_LOG_FUNCTION("SComposerBaseObjectDefinition");
+ ComposerTypeDefinitionsHelper::SetInstanceAsCanonical(inMetaData, inInstance, TEnumType);
+ }
+
+ template <ComposerObjectTypes::Enum TBaseType>
+ void Derive(IDataCore &inCore, const SComposerBaseObjectDefinition<TBaseType> &inParent)
+ {
+ UICDM_LOG_FUNCTION("SComposerBaseObjectDefinition::Derive");
+ ComposerTypeDefinitionsHelper::DeriveInstance(inCore, m_Instance, inParent.m_Instance);
+ }
+ void SetType(IDataCore &inCore,
+ const SComposerBaseObjectDefinition<ComposerObjectTypes::Typed> &inParent)
+ {
+ UICDM_LOG_FUNCTION("SComposerBaseObjectDefinition::SetInstancePropertyValue");
+ ComposerTypeDefinitionsHelper::SetInstancePropertyValue(
+ inCore, m_Instance, inParent.m_TypeProp, ComposerObjectTypes::Convert(TEnumType));
+ }
+ void TypedDerive(IDataCore &inCore,
+ const SComposerBaseObjectDefinition<ComposerObjectTypes::Typed> &inParent)
+ {
+ UICDM_LOG_FUNCTION("SComposerBaseObjectDefinition::TypedDerive");
+ Derive(inCore, inParent);
+ SetType(inCore, inParent);
+ }
+};
+
+template <ComposerObjectTypes::Enum TEnumType>
+struct SComposerObjectDefinition : public SComposerBaseObjectDefinition<TEnumType>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance)
+ : SComposerBaseObjectDefinition<TEnumType>(inCore, inMetaData, inInstance)
+ {
+ }
+};
+
+// Base class of slides
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Slide>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Slide>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Named> &inNamed)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Slide>(inCore, inMetaData, inInstance)
+ {
+ TypedDerive(inCore, inTyped);
+ Derive(inCore, inNamed);
+ }
+};
+
+// Base class of actions
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Action>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Action>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Action>(inCore, inMetaData, inInstance)
+ {
+ TypedDerive(inCore, inTyped);
+ }
+};
+
+// Base class of assets
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Asset>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Asset>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Guided> &inGuided,
+ SComposerObjectDefinition<ComposerObjectTypes::Named> &inNamed)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Asset>(inCore, inMetaData, inInstance)
+ {
+ TypedDerive(inCore, inTyped);
+ Derive(inCore, inGuided);
+ Derive(inCore, inNamed);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Scene>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Scene>
+{
+ SComposerObjectDefinition(
+ IDataCore &inCore, IMetaData &inMetaData, CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset,
+ SComposerObjectDefinition<ComposerObjectTypes::SlideOwner> &inSlideOwner)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Scene>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inAsset);
+ Derive(inCore, inSlideOwner);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Image>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Image>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Image>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Lightmaps>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Lightmaps>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Lightmaps>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::MaterialBase>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::MaterialBase>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Lightmaps> &inBase)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::MaterialBase>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inBase);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Material>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Material>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::MaterialBase> &inBase)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Material>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inBase);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::CustomMaterial>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::CustomMaterial>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::MaterialBase> &inBase)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::CustomMaterial>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inBase);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::ReferencedMaterial>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::ReferencedMaterial>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::MaterialBase> &inBase)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::ReferencedMaterial>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inBase);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Behavior>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Behavior>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Behavior>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Effect>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Effect>
+
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Effect>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Node>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Node>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Node>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Layer>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Layer>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Layer>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Model>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Model>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Model>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Group>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Group>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Group>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Light>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Light>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Light>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Camera>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Camera>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Camera>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Text>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Text>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Text>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Component>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Component>
+{
+ SComposerObjectDefinition(
+ IDataCore &inCore, IMetaData &inMetaData, CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode,
+ SComposerObjectDefinition<ComposerObjectTypes::SlideOwner> &inSlideOwner)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Component>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inNode);
+ Derive(inCore, inSlideOwner);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::RenderPlugin>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::RenderPlugin>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::RenderPlugin>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Alias>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Alias>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Alias>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Path>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Path>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Path>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::PathAnchorPoint>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::PathAnchorPoint>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::PathAnchorPoint>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::SubPath>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::SubPath>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ CUICDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Asset> &inAsset)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::SubPath>(inCore, inMetaData,
+ inInstance)
+ {
+ Derive(inCore, inAsset);
+ SetType(inCore, inTyped);
+ }
+};
+
+// Container object for all of the object definitions
+class SComposerObjectDefinitions
+{
+public:
+ IDataCore &m_DataCore;
+ IMetaData &m_MetaData;
+
+#define HANDLE_COMPOSER_OBJECT_TYPE(name, propmacro) \
+ SComposerObjectDefinition<ComposerObjectTypes::name> m_##name;
+ ITERATE_COMPOSER_OBJECT_TYPES
+#undef HANDLE_COMPOSER_OBJECT_TYPE
+
+ SComposerObjectDefinitions(
+ IDataCore &inDataCore,
+ IMetaData &inMetaData /*, ISlideCore& inSlideCore, IPropertySystem& inPropertySystem */);
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // RTTI API
+ bool IsA(CUICDMInstanceHandle inInstance, ComposerObjectTypes::Enum inType);
+ // Could easily return None, meaning we can't identify the object type.
+ // Checks the type of the first derivation parent, so this won't ever return
+ // SlideOwner, for instance.
+ ComposerObjectTypes::Enum GetType(CUICDMInstanceHandle inInstance);
+
+ CUICDMInstanceHandle GetInstanceForType(ComposerObjectTypes::Enum inType);
+ SComposerObjectDefinitions() = default;
+ ~SComposerObjectDefinitions() = default;
+private:
+ SComposerObjectDefinitions(const SComposerObjectDefinitions&) = delete;
+ SComposerObjectDefinitions& operator=(const SComposerObjectDefinitions&) = delete;
+};
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMDataCore.h b/src/Authoring/UICDM/Systems/UICDMDataCore.h
new file mode 100644
index 00000000..d823cf93
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMDataCore.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMDATACOREH
+#define UICDMDATACOREH
+#include "UICDMHandles.h"
+#include "UICDMPropertyDefinition.h"
+#include "HandleSystemBase.h"
+#include "UICDMMetaData.h"
+#include "UICDMValue.h"
+
+namespace UICDM {
+
+typedef std::pair<CUICDMPropertyHandle, SValue> TPropertyHandleValuePair;
+typedef std::vector<TPropertyHandleValuePair> TPropertyHandleValuePairList;
+
+class IInstancePropertyCore
+{
+public:
+ virtual ~IInstancePropertyCore() {}
+
+ /**
+ * Find a given instance property by name. May return an invalid handle.
+ */
+ virtual CUICDMPropertyHandle
+ GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const = 0;
+ /**
+ * Get the entire list of instance properties;
+ */
+ virtual void GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const = 0;
+ // Get the properties that are stored only on this instance, not on any parents.
+ virtual void GetSpecificInstancePropertyValues(CUICDMInstanceHandle inHandle,
+ TPropertyHandleValuePairList &outValues) = 0;
+ /**
+ * Return true if this property is on this instance or one of its parents.
+ */
+ virtual bool HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+
+ /**
+ * Does this value match the approperty property type.
+ * error - PropertyNotFound
+ * error - ValueTypeError
+ */
+ virtual void CheckValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty,
+ const SValue &inValue) const = 0;
+ /**
+ * Get this property from this instance. This includes looking up the default value. If the
+ *instance doesn't have the property
+ * and it has no default the return value is false.
+ * error - InstanceNotFound
+ * error - PropertyNotFound if this property doesn't exist on this instance or doesn't exist.
+ */
+ virtual bool GetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+ /**
+ * Set this property on this instance.
+ * error - InstanceNotFound
+ * error - PropertyNotFound if this property doesn't exist on this instance or doesn't exist.
+ * error - ValueTypeError if this value is of the wrong type
+ */
+ virtual void SetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+};
+
+typedef std::shared_ptr<IInstancePropertyCore> TInstancePropertyCorePtr;
+
+class IStringTable;
+
+/**
+ * Primary interface to data model system. This allows you to define 'classes', which are
+ *really just
+ * collections of properties, and instances of those classes. A zero handle value is regarded
+ *as empty.
+ */
+class IDataCore : public IHandleBase, public IInstancePropertyCore
+{
+public:
+ virtual ~IDataCore() {}
+
+ // Bookkeeping
+ virtual IStringTable &GetStringTable() const = 0;
+ virtual std::shared_ptr<IStringTable> GetStringTablePtr() const = 0;
+
+ //===============================================================
+ // Instances
+ //===============================================================
+ /**
+ * Create a new instance of a class. Instances can be named, in which case
+ * they are sometimes treated differently when serialized. If the name is null
+ * or has no length then it is ignored. If the name is non-null, then a check is
+ * run as named instances must have unique names. When a named instance is a parent
+ * of another instance, only its name is serialized out; not its handle thus you can safely
+ * use names as inter-application instance handles.
+ * May use a target id to specify what the ideal id is; id must not exist.
+ * - error DuplicateInstanceName
+ */
+ virtual CUICDMInstanceHandle
+ CreateInstance(CUICDMInstanceHandle inTargetId = CUICDMInstanceHandle()) = 0;
+ /**
+ * Delete an instance.
+ * error - InstanceNotFound
+ */
+ virtual void DeleteInstance(CUICDMInstanceHandle inHandle) = 0;
+ /**
+ * Return all the instances in the system.
+ */
+ virtual void GetInstances(TInstanceHandleList &outInstances) const = 0;
+ /**
+ * Return all the instances in the system that is derived from parent.
+ */
+ virtual void GetInstancesDerivedFrom(TInstanceHandleList &outInstances,
+ CUICDMInstanceHandle inParentHandle) const = 0;
+
+ //===============================================================
+ // Instance Derivation
+ //===============================================================
+ /**
+ * Derive an instance from another instance. This implies a rebuild of
+ * the aggregate properties of a given instance.
+ * error - InstanceNotFound if either instance or parent aren't found
+ */
+ virtual void DeriveInstance(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent) = 0;
+ /**
+ * Return a count of the parent's of a given instance.
+ * error - InstanceNotFound
+ */
+ virtual void GetInstanceParents(CUICDMInstanceHandle inHandle,
+ TInstanceHandleList &outParents) const = 0;
+
+ /**
+ * Returns true if the instance is derived from the parent somehow.
+ */
+ virtual bool IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const = 0;
+ //===============================================================
+
+ //===============================================================
+ // Class Properties
+ //===============================================================
+ /**
+ * Add a new property to a given instances. You can use this to overshadow properties
+ * on base instances but you can't add two properties of the same name to a given
+ * instance.
+ * error - InstanceNotFound
+ * error - PropertyExists if the property already exists on this class
+ * error - ValueTypeError if the default value exists and is if a different type than
+ *inPropType
+ */
+ virtual CUICDMPropertyHandle AddProperty(CUICDMInstanceHandle inInstance, TCharPtr inName,
+ DataModelDataType::Value inPropType) = 0;
+ /**
+ * Return the property definition that corresponds to a given property value.
+ */
+ virtual const SUICDMPropertyDefinition &GetProperty(CUICDMPropertyHandle inProperty) const = 0;
+ /**
+ * Return the properties specific to this instance, not including properties
+ * gained by derivation
+ */
+ virtual void GetInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const = 0;
+ /**
+ * Remove a property from an instance. Instances will no long have this property accessible
+ *nor will
+ * child instances.
+ */
+ virtual void RemoveProperty(CUICDMPropertyHandle inProperty) = 0;
+ /**
+ * Copy properties (definitions & values) specific to one instance, not including properties
+ * gained by derivation, to another instance.
+ */
+ virtual void CopyInstanceProperties(CUICDMInstanceHandle inSrcInstance,
+ CUICDMInstanceHandle inDestInstance) = 0;
+ /**
+ * Removed cached intermediate values from the instance. UICDM pull properties from the
+ *inheritance hierarchy chain
+ * up to the current instance when someone requests a property in order to make the next
+ *request quicker. This breaks
+ * some forms of updating where a parent's default value gets changed and the instance won't
+ *reflect it (until you
+ * save/load the file).
+ */
+ //===============================================================
+ virtual void RemoveCachedValues(CUICDMInstanceHandle inInstance) = 0;
+
+ //===============================================================
+ // Handle validation
+ //===============================================================
+ /**
+ * Is valid and is instances
+ */
+ virtual bool IsInstance(int inHandle) const = 0;
+ /**
+ * is valid and is property
+ */
+ virtual bool IsProperty(int inHandle) const = 0;
+};
+
+typedef std::shared_ptr<IDataCore> TDataCorePtr;
+
+class IPropertySystem : public IHandleBase
+{
+public:
+ virtual ~IPropertySystem() {}
+
+ virtual CUICDMInstanceHandle CreateInstance() = 0;
+ virtual void DeleteInstance(CUICDMInstanceHandle inHandle) = 0;
+ virtual void DeriveInstance(CUICDMInstanceHandle inInstance, CUICDMInstanceHandle inParent) = 0;
+
+ virtual void GetInstances(TInstanceHandleList &outInstances) const = 0;
+
+ virtual CUICDMPropertyHandle AddProperty(CUICDMInstanceHandle inInstance, TCharPtr inName,
+ DataModelDataType::Value inPropType) = 0;
+
+ virtual CUICDMPropertyHandle
+ GetAggregateInstancePropertyByName(CUICDMInstanceHandle inInstance,
+ const TCharStr &inStr) const = 0;
+ virtual void GetAggregateInstanceProperties(CUICDMInstanceHandle inInstance,
+ TPropertyHandleList &outProperties) const = 0;
+ virtual bool HasAggregateInstanceProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+
+ virtual bool GetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+ virtual void SetInstancePropertyValue(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+
+ virtual bool IsInstanceOrDerivedFrom(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) const = 0;
+
+ virtual DataModelDataType::Value GetDataType(CUICDMPropertyHandle inProperty) const = 0;
+ virtual TCharStr GetName(CUICDMPropertyHandle inProperty) const = 0;
+ virtual TCharStr GetFormalName(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+ virtual AdditionalMetaDataType::Value
+ GetAdditionalMetaDataType(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+ virtual TMetaDataData GetAdditionalMetaDataData(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+ virtual CUICDMInstanceHandle GetPropertyOwner(CUICDMPropertyHandle inProperty) const = 0;
+};
+typedef std::shared_ptr<IPropertySystem> TPropertySystemPtr;
+
+template <typename TCoreType>
+inline SValue GetInstancePropertyValue(TCoreType inCore, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ SValue retval;
+ if (!inCore->GetInstancePropertyValue(inInstance, inProperty, retval))
+ throw PropertyNotFound(L"");
+ return retval;
+}
+
+template <typename TDataType, typename TCoreType>
+inline TDataType GetSpecificInstancePropertyValue(TCoreType inDataCore,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty)
+{
+ return UICDM::get<TDataType>(GetInstancePropertyValue(inDataCore, inInstance, inProperty));
+}
+
+template <typename TDataType, typename TCoreType>
+inline TDataType GetNamedInstancePropertyValue(TCoreType inDataCore,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inName)
+{
+ CUICDMPropertyHandle theProperty =
+ inDataCore->GetAggregateInstancePropertyByName(inInstance, inName);
+ return GetSpecificInstancePropertyValue<TDataType, TCoreType>(inDataCore, inInstance,
+ theProperty);
+}
+
+inline CUICDMPropertyHandle AddPropertyWithValue(IPropertySystem &inPropertySystem,
+ CUICDMInstanceHandle inInstance, TCharPtr inName,
+ DataModelDataType::Value inDataType,
+ const SValue &inValue)
+{
+ CUICDMPropertyHandle theProperty(inPropertySystem.AddProperty(inInstance, inName, inDataType));
+ inPropertySystem.SetInstancePropertyValue(inInstance, theProperty, inValue);
+ return theProperty;
+}
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMDataTypes.h b/src/Authoring/UICDM/Systems/UICDMDataTypes.h
new file mode 100644
index 00000000..1282540a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMDataTypes.h
@@ -0,0 +1,840 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMDATAH
+#define UICDMDATAH
+
+#include <memory>
+#include <functional>
+
+#include "UICDMErrors.h"
+#include "UICDMStringTable.h"
+#include "UICDMWindowsCompatibility.h"
+#include <stdexcept>
+#include <vector>
+#include <map>
+#include <set>
+#include <EABase/eabase.h> //char8_t, etc.
+#include <EASTL/string.h>
+#include <EASTL/vector.h>
+#include "foundation/StrConvertUTF.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+
+#include <QObject>
+
+namespace UICDM {
+
+typedef const wchar_t *TCharPtr;
+struct SUICDMStr : public eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType>
+{
+ typedef qt3ds::foundation::TWCharEASTLConverter::TCharType TCharType;
+ typedef eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> TStrType;
+ SUICDMStr() {}
+ SUICDMStr(const wchar_t *inStr)
+ : TStrType(qt3ds::NVUnionCast<const TCharType *>(inStr))
+ {
+ }
+ SUICDMStr(const TStrType &inOther)
+ : TStrType(inOther)
+ {
+ }
+
+ const wchar_t *wide_str() const { return reinterpret_cast<const wchar_t *>(c_str()); }
+ bool operator==(const SUICDMStr &inOther) const { return TStrType::compare(inOther) == 0; }
+ bool operator!=(const SUICDMStr &inOther) const { return TStrType::compare(inOther) != 0; }
+ bool operator==(const wchar_t *inOther) const
+ {
+ return TStrType::compare(reinterpret_cast<const TCharType *>(inOther)) == 0;
+ }
+ bool operator!=(const wchar_t *inOther) const
+ {
+ return TStrType::compare(reinterpret_cast<const TCharType *>(inOther)) != 0;
+ }
+
+ TStrType::size_type find_first_of(const wchar_t *p, size_type position = 0) const
+ {
+ return TStrType::find_first_of(reinterpret_cast<const TCharType *>(p), position);
+ }
+ TStrType::size_type find_first_not_of(const wchar_t *p, size_type position = 0) const
+ {
+ return TStrType::find_first_not_of(reinterpret_cast<const TCharType *>(p), position);
+ }
+ TStrType::size_type find_last_not_of(const wchar_t *p,
+ size_type position = TStrType::npos) const
+ {
+ return TStrType::find_last_not_of(reinterpret_cast<const TCharType *>(p), position);
+ }
+ TStrType::size_type find(const wchar_t *p, size_type position = 0) const
+ {
+ return TStrType::find(reinterpret_cast<const TCharType *>(p), position);
+ }
+ TStrType::size_type find(wchar_t p, size_type position = 0) const
+ {
+ return TStrType::find(static_cast<TCharType>(p), position);
+ }
+ TStrType::size_type rfind(const wchar_t *p, size_type position = TStrType::npos) const
+ {
+ return TStrType::rfind(reinterpret_cast<const TCharType *>(p), position);
+ }
+ TStrType::size_type rfind(wchar_t p, size_type position = TStrType::npos) const
+ {
+ return TStrType::rfind(p, position);
+ }
+ SUICDMStr replace(size_type position, size_type length, const wchar_t *inNewStr)
+ {
+ return TStrType::replace(position, length, reinterpret_cast<const TCharType *>(inNewStr));
+ }
+
+ void append(const wchar_t *p) { TStrType::append(reinterpret_cast<const TCharType *>(p)); }
+ void append(const wchar_t *p, size_type position, size_type n)
+ {
+ TStrType::append(reinterpret_cast<const TCharType *>(p), position, n);
+ }
+ void append(const SUICDMStr &p) { TStrType::append(p); }
+ void assign(const wchar_t *p) { TStrType::assign(reinterpret_cast<const TCharType *>(p)); }
+ void assign(const SUICDMStr &p) { TStrType::assign(p); }
+};
+typedef SUICDMStr TCharStr;
+typedef std::vector<wchar_t> TCharList;
+typedef eastl::vector<TCharStr> TCharStrList;
+typedef std::map<TCharStr, int> TCharStrIntMap;
+typedef std::map<int, TCharStr> TIntTCharStrMap;
+typedef std::vector<int> TIntList;
+typedef std::set<int> TIntSet;
+typedef eastl::vector<float> TFloatList;
+
+template <typename TDataType>
+class CImmutableVector : private std::vector<TDataType>
+{
+public:
+ typedef std::vector<TDataType> base;
+
+ CImmutableVector(const std::vector<TDataType> &inSrc)
+ : base(inSrc)
+ {
+ }
+ CImmutableVector(const CImmutableVector &inSrc)
+ : base(inSrc)
+ {
+ }
+
+ CImmutableVector &operator=(const CImmutableVector &inSrc)
+ {
+ base::operator=(inSrc);
+ return *this;
+ }
+
+ typename std::vector<TDataType>::const_iterator begin() const { return base::begin(); }
+ typename std::vector<TDataType>::const_iterator end() const { return base::end(); }
+
+ size_t size() const { return base::size(); }
+
+ const TDataType &at(int inIndex) const { return base::at(inIndex); }
+ const TDataType &operator[](int inIndex) const { return base::at(inIndex); }
+};
+
+typedef CImmutableVector<TCharStr> TImmutableCharStrList;
+typedef std::shared_ptr<TImmutableCharStrList> TImmutableCharStrListPtr;
+
+class CDataStr
+{
+ TCharList m_Data;
+
+public:
+ CDataStr() {}
+ CDataStr(TCharList &inData) { m_Data.swap(inData); }
+ CDataStr(const wchar_t *inData)
+ {
+ if (inData && *inData)
+ m_Data.insert(m_Data.begin(), inData, inData + wcslen(inData));
+ m_Data.push_back(0);
+ }
+ CDataStr(const wchar_t *inData, size_t inLen)
+ {
+ if (inData && *inData)
+ m_Data.insert(m_Data.begin(), inData, inData + inLen);
+ if (m_Data.size() > 0 && m_Data.back() != 0)
+ m_Data.push_back(0);
+ }
+ CDataStr(const CDataStr &inOther)
+ : m_Data(inOther.m_Data)
+ {
+ }
+ virtual ~CDataStr() {}
+
+ CDataStr &operator=(const CDataStr &inOther)
+ {
+ m_Data = inOther.m_Data;
+ return *this;
+ }
+ const wchar_t *GetData() const { return m_Data.size() <= 1 ? L"" : &(*m_Data.begin()); }
+ size_t GetLength() const { return m_Data.size() > 1 ? m_Data.size() - 1 : 0; }
+ bool operator==(const CDataStr &inOther) const { return m_Data == inOther.m_Data; }
+};
+
+typedef std::shared_ptr<CDataStr> TDataStrPtr;
+
+struct SFloat2
+{
+ float m_Floats[2];
+ SFloat2(float f1 = 0, float f2 = 0)
+ {
+ m_Floats[0] = f1;
+ m_Floats[1] = f2;
+ }
+ SFloat2(const SFloat2 &inOther) { operator=(inOther); }
+ SFloat2 &operator=(const SFloat2 &inOther)
+ {
+ m_Floats[0] = inOther.m_Floats[0];
+ m_Floats[1] = inOther.m_Floats[1];
+ return *this;
+ }
+ bool operator==(const SFloat2 &other) const
+ {
+ return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1];
+ }
+ float &operator[](size_t inIndex)
+ {
+ switch (inIndex) {
+ default:
+ throw std::out_of_range("");
+ case 0:
+ case 1:
+ return m_Floats[inIndex];
+ }
+ }
+ const float &operator[](size_t inIndex) const
+ {
+ switch (inIndex) {
+ default:
+ throw std::out_of_range("");
+ case 0:
+ case 1:
+ return m_Floats[inIndex];
+ }
+ }
+};
+
+struct SFloat3
+{
+ float m_Floats[3];
+
+ SFloat3(float f1 = 0, float f2 = 0, float f3 = 0)
+ {
+ m_Floats[0] = f1;
+ m_Floats[1] = f2;
+ m_Floats[2] = f3;
+ }
+ SFloat3(const SFloat3 &inOther) { operator=(inOther); }
+ SFloat3 &operator=(const SFloat3 &inOther)
+ {
+ m_Floats[0] = inOther.m_Floats[0];
+ m_Floats[1] = inOther.m_Floats[1];
+ m_Floats[2] = inOther.m_Floats[2];
+ return *this;
+ }
+
+ bool operator==(const SFloat3 &other) const
+ {
+ return m_Floats[0] == other.m_Floats[0] && m_Floats[1] == other.m_Floats[1]
+ && m_Floats[2] == other.m_Floats[2];
+ }
+
+ float &operator[](size_t inIndex)
+ {
+ switch (inIndex) {
+ default:
+ throw std::out_of_range("");
+ case 0:
+ case 1:
+ case 2:
+ return m_Floats[inIndex];
+ }
+ }
+ const float &operator[](size_t inIndex) const
+ {
+ switch (inIndex) {
+ default:
+ throw std::out_of_range("");
+ case 0:
+ case 1:
+ case 2:
+ return m_Floats[inIndex];
+ }
+ }
+};
+
+struct SLong4
+{
+ qt3ds::QT3DSU32 m_Longs[4];
+
+ SLong4(qt3ds::QT3DSU32 l1 = 0,
+ qt3ds::QT3DSU32 l2 = 0,
+ qt3ds::QT3DSU32 l3 = 0,
+ qt3ds::QT3DSU32 l4 = 0)
+ {
+ m_Longs[0] = l1;
+ m_Longs[1] = l2;
+ m_Longs[2] = l3;
+ m_Longs[3] = l4;
+ }
+ SLong4(const SLong4 &inOther) { operator=(inOther); }
+ SLong4 &operator=(const SLong4 &inOther)
+ {
+ m_Longs[0] = inOther.m_Longs[0];
+ m_Longs[1] = inOther.m_Longs[1];
+ m_Longs[2] = inOther.m_Longs[2];
+ m_Longs[3] = inOther.m_Longs[3];
+ return *this;
+ }
+
+ bool operator==(const SLong4 &other) const
+ {
+ return m_Longs[0] == other.m_Longs[0] && m_Longs[1] == other.m_Longs[1]
+ && m_Longs[2] == other.m_Longs[2] && m_Longs[3] == other.m_Longs[3];
+ }
+
+ bool operator<(const SLong4 &other) const
+ {
+ if (m_Longs[0] < other.m_Longs[0])
+ return true;
+ else if (m_Longs[0] == other.m_Longs[0]) {
+ if (m_Longs[1] < other.m_Longs[1])
+ return true;
+ else if (m_Longs[1] == other.m_Longs[1]) {
+ if (m_Longs[2] < other.m_Longs[2])
+ return true;
+ else if (m_Longs[3] < other.m_Longs[3])
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool Valid() const
+ {
+ bool retval = false;
+ for (int idx = 0; idx < 4; ++idx)
+ retval = retval || m_Longs[0] > 0;
+ return retval;
+ }
+};
+
+typedef std::vector<SLong4> TLong4Vec;
+
+struct SSizet4
+{
+ size_t m_Longs[4];
+
+ SSizet4(size_t l1 = 0, size_t l2 = 0, size_t l3 = 0, size_t l4 = 0)
+ {
+ m_Longs[0] = l1;
+ m_Longs[1] = l2;
+ m_Longs[2] = l3;
+ m_Longs[3] = l4;
+ }
+ SSizet4(const SSizet4 &inOther) { operator=(inOther); }
+ SSizet4 &operator=(const SSizet4 &inOther)
+ {
+ m_Longs[0] = inOther.m_Longs[0];
+ m_Longs[1] = inOther.m_Longs[1];
+ m_Longs[2] = inOther.m_Longs[2];
+ m_Longs[3] = inOther.m_Longs[3];
+ return *this;
+ }
+
+ bool operator==(const SSizet4 &other) const
+ {
+ return m_Longs[0] == other.m_Longs[0] && m_Longs[1] == other.m_Longs[1]
+ && m_Longs[2] == other.m_Longs[2] && m_Longs[3] == other.m_Longs[3];
+ }
+
+ bool operator<(const SSizet4 &other) const
+ {
+ if (m_Longs[0] < other.m_Longs[0])
+ return true;
+ else if (m_Longs[0] == other.m_Longs[0]) {
+ if (m_Longs[1] < other.m_Longs[1])
+ return true;
+ else if (m_Longs[1] == other.m_Longs[1]) {
+ if (m_Longs[2] < other.m_Longs[2])
+ return true;
+ else if (m_Longs[3] < other.m_Longs[3])
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool Valid() const
+ {
+ bool retval = false;
+ for (int idx = 0; idx < 4; ++idx)
+ retval = retval || m_Longs[0] > 0;
+ return retval;
+ }
+};
+
+inline bool IsTrivial(const wchar_t *inStr)
+{
+ return inStr == NULL || *inStr == 0;
+}
+inline const wchar_t *NonNull(const wchar_t *inStr)
+{
+ return inStr ? inStr : L"";
+}
+inline bool AreEqual(const wchar_t *lhs, const wchar_t *rhs)
+{
+ return wcscmp(NonNull(lhs), NonNull(rhs)) == 0;
+}
+
+inline bool IsTrivial(const char8_t *inStr)
+{
+ return inStr == NULL || *inStr == 0;
+}
+inline const char8_t *NonNull(const char8_t *inStr)
+{
+ return inStr ? inStr : "";
+}
+inline bool AreEqual(const char8_t *lhs, const char8_t *rhs)
+{
+ return strcmp(NonNull(lhs), NonNull(rhs)) == 0;
+}
+
+inline bool AreEqualCaseless(const char8_t *lhs, const char8_t *rhs)
+{
+ if (IsTrivial(lhs) && IsTrivial(rhs))
+ return true;
+ if (IsTrivial(lhs) || IsTrivial(rhs))
+ return false;
+ for (; *lhs && *rhs; ++lhs, ++rhs)
+ if (tolower(*lhs) != tolower(*rhs))
+ return false;
+ if (*lhs || *rhs)
+ return false;
+ return true;
+}
+
+struct SStringRef
+{
+ const wchar_t *m_Id;
+
+ SStringRef(const wchar_t *id = L"")
+ : m_Id(NonNull(id))
+ {
+ }
+
+ operator const wchar_t *() const { return m_Id; }
+ bool operator==(const SStringRef &inOther) const { return AreEqual(m_Id, inOther.m_Id); }
+};
+}
+
+// Traits specializations have to be in the same namespace as they were first declared.
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<UICDM::SFloat2>
+ {
+ void destruct(UICDM::SFloat2 &) {}
+ };
+ template <>
+ struct DestructTraits<UICDM::SFloat3>
+ {
+ void destruct(UICDM::SFloat3 &) {}
+ };
+ template <>
+ struct DestructTraits<UICDM::SLong4>
+ {
+ void destruct(UICDM::SLong4 &) {}
+ };
+ template <>
+ struct DestructTraits<UICDM::SStringRef>
+ {
+ void destruct(UICDM::SStringRef &) {}
+ };
+
+ template <>
+ struct EqualVisitorTraits<UICDM::TDataStrPtr>
+ {
+ bool operator()(const UICDM::TDataStrPtr &lhs, const UICDM::TDataStrPtr &rhs)
+ {
+ if (lhs && rhs)
+ return *lhs == *rhs;
+ if (lhs || rhs)
+ return false;
+ return true;
+ }
+ };
+}
+}
+
+namespace UICDM {
+
+using qt3ds::NVUnionCast;
+
+struct ObjectReferenceType
+{
+ enum Enum {
+ Unknown = 0,
+ Absolute = 1,
+ Relative = 2,
+ };
+};
+
+template <typename TDataType>
+struct SObjectRefTypeTraits
+{
+};
+
+template <>
+struct SObjectRefTypeTraits<SLong4>
+{
+ ObjectReferenceType::Enum getType() { return ObjectReferenceType::Absolute; }
+};
+template <>
+struct SObjectRefTypeTraits<TDataStrPtr>
+{
+ ObjectReferenceType::Enum getType() { return ObjectReferenceType::Relative; }
+};
+
+struct SObjectRefUnionTraits
+{
+ typedef ObjectReferenceType::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(SSizet4),
+ };
+
+ static ObjectReferenceType::Enum getNoDataId() { return ObjectReferenceType::Unknown; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SObjectRefTypeTraits<TDataType>().getType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case ObjectReferenceType::Absolute:
+ return inVisitor(*NVUnionCast<SLong4 *>(inData));
+ case ObjectReferenceType::Relative:
+ return inVisitor(*NVUnionCast<TDataStrPtr *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case ObjectReferenceType::Unknown:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case ObjectReferenceType::Absolute:
+ return inVisitor(*NVUnionCast<const SLong4 *>(inData));
+ case ObjectReferenceType::Relative:
+ return inVisitor(*NVUnionCast<const TDataStrPtr *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case ObjectReferenceType::Unknown:
+ return inVisitor();
+ }
+ }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SObjectRefUnionTraits,
+ SObjectRefUnionTraits::TBufferSize>,
+ SObjectRefUnionTraits::TBufferSize>
+ TObjRefUnionType;
+
+template <typename TDataType>
+struct SUICDMGetter
+{
+};
+
+template <typename TRetType, typename TDataType>
+TRetType get(const TDataType &inType)
+{
+ return SUICDMGetter<TDataType>().template doGet<TRetType>(inType);
+}
+
+template <>
+struct SUICDMGetter<TObjRefUnionType>
+{
+ template <typename TRetType>
+ TRetType doGet(const TObjRefUnionType &inValue)
+ {
+ return inValue.getData<TRetType>();
+ }
+};
+
+// Either an absolute reference (SLong4) or a relative reference (string)
+struct SObjectRefType
+{
+ TObjRefUnionType m_Value;
+
+ SObjectRefType(const TDataStrPtr &inValue)
+ : m_Value(inValue)
+ {
+ }
+ SObjectRefType(const SLong4 &inValue)
+ : m_Value(inValue)
+ {
+ }
+ SObjectRefType(const SObjectRefType &inOther)
+ : m_Value(inOther.m_Value)
+ {
+ }
+ SObjectRefType() {}
+ SObjectRefType &operator=(const SObjectRefType &inOther)
+ {
+ m_Value = inOther.m_Value;
+ return *this;
+ }
+ ObjectReferenceType::Enum GetReferenceType() const { return m_Value.getType(); }
+ bool operator==(const SObjectRefType &inOther) const { return m_Value == inOther.m_Value; }
+};
+
+inline bool Equals(const SObjectRefType &lhs, const SObjectRefType &rhs)
+{
+ return lhs == rhs;
+}
+
+struct SStringOrIntTypes
+{
+ enum Enum {
+ Unknown = 0,
+ Int,
+ String,
+ };
+};
+
+template <typename TDataType>
+struct SStringOrIntTypeTraits
+{
+};
+
+template <>
+struct SStringOrIntTypeTraits<long>
+{
+ SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::Int; }
+};
+template <>
+struct SStringOrIntTypeTraits<int>
+{
+ SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::Int; }
+};
+template <>
+struct SStringOrIntTypeTraits<TDataStrPtr>
+{
+ SStringOrIntTypes::Enum getType() { return SStringOrIntTypes::String; }
+};
+
+struct SStringOrIntUnionTraits
+{
+ typedef SStringOrIntTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(TDataStrPtr),
+ };
+
+ static SStringOrIntTypes::Enum getNoDataId() { return SStringOrIntTypes::Unknown; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SStringOrIntTypeTraits<TDataType>().getType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case SStringOrIntTypes::Int:
+ return inVisitor(*NVUnionCast<long *>(inData));
+ case SStringOrIntTypes::String:
+ return inVisitor(*NVUnionCast<TDataStrPtr *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case SStringOrIntTypes::Unknown:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case SStringOrIntTypes::Int:
+ return inVisitor(*NVUnionCast<const qt3ds::QT3DSI32 *>(inData));
+ case SStringOrIntTypes::String:
+ return inVisitor(*NVUnionCast<const TDataStrPtr *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case SStringOrIntTypes::Unknown:
+ return inVisitor();
+ }
+ }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SStringOrIntUnionTraits,
+ SStringOrIntUnionTraits::TBufferSize>,
+ SStringOrIntUnionTraits::TBufferSize>
+ TStringOrIntUnionType;
+
+template <>
+struct SUICDMGetter<TStringOrIntUnionType>
+{
+ template <typename TRetType>
+ TRetType doGet(const TStringOrIntUnionType &inValue)
+ {
+ return inValue.getData<TRetType>();
+ }
+};
+
+struct SStringOrInt
+{
+ TStringOrIntUnionType m_Value;
+
+ SStringOrInt() {}
+ SStringOrInt(int inValue)
+ : m_Value(inValue)
+ {
+ }
+ SStringOrInt(TDataStrPtr inValue)
+ : m_Value(inValue)
+ {
+ }
+ SStringOrInt(const SStringOrInt &inOther)
+ : m_Value(inOther.m_Value)
+ {
+ }
+
+ SStringOrInt &operator=(const SStringOrInt &inOther)
+ {
+ m_Value = inOther.m_Value;
+ return *this;
+ }
+
+ SStringOrIntTypes::Enum GetType() const { return m_Value.getType(); }
+
+ bool operator==(const SStringOrInt &inOther) const { return m_Value == inOther.m_Value; }
+};
+
+inline bool Equals(const SStringOrInt &lhs, const SStringOrInt &rhs)
+{
+ return lhs == rhs;
+}
+
+//comes from broken X.h
+#ifdef None
+#undef None
+#endif
+
+#ifdef Bool
+#undef Bool
+#endif
+
+struct DataModelDataType {
+
+ enum Value {
+ None,
+ Float,
+ Float2,
+ Float3,
+ Long,
+ String,
+ Bool,
+ Long4,
+ StringRef,
+ ObjectRef,
+ StringOrInt,
+ FloatList,
+ };
+
+
+ Q_ENUM(Value)
+ Q_GADGET
+};
+
+
+class IStringTable;
+
+template <typename TDataType>
+struct SUICDMValueTyper
+{
+};
+
+template <typename TDataType>
+inline DataModelDataType::Value GetValueType(const TDataType &inValue)
+{
+ return SUICDMValueTyper<TDataType>().Get(inValue);
+}
+
+template <typename TDataType>
+struct SDefaulter
+{
+};
+
+template <typename TDataType>
+inline bool SetDefault(DataModelDataType::Value inDataType, TDataType &outValue)
+{
+ return SDefaulter<TDataType>().SetDefault(inDataType, outValue);
+}
+
+typedef void (*TUICDMDebugLogFunction)(const char *message);
+// UICDMSimpleDataCore.cpp
+extern TUICDMDebugLogFunction g_UICDMDebugLogger;
+
+#define UICDM_DEBUG_LOG(msg) \
+ { \
+ if (g_UICDMDebugLogger) { \
+ g_UICDMDebugLogger(msg); \
+ } \
+ }
+struct SUICDMLogScope
+{
+ const char *m_EndMessage;
+ SUICDMLogScope(const char *inStartMessage, const char *inEndMessage)
+ : m_EndMessage(inEndMessage)
+ {
+ UICDM_DEBUG_LOG(inStartMessage);
+ }
+ ~SUICDMLogScope() { UICDM_DEBUG_LOG(m_EndMessage); }
+};
+
+#define UICDM_LOG_FUNCTION(fnname) SUICDMLogScope __fn_scope(fnname " Enter", fnname " Leave");
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMErrors.h b/src/Authoring/UICDM/Systems/UICDMErrors.h
new file mode 100644
index 00000000..694c5bb6
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMErrors.h
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMERRORSH
+#define UICDMERRORSH
+#include "UICDMWindowsCompatibility.h"
+
+namespace UICDM {
+class UICDMError : public std::exception
+{
+public:
+ UICDMError(const wchar_t *inMessage)
+ : std::exception()
+ {
+ wcscpy_s(m_Message, inMessage);
+ }
+ wchar_t m_Message[1024];
+};
+
+class HandleExists : public UICDMError
+{
+public:
+ HandleExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class PropertyNotFound : public UICDMError
+{
+public:
+ PropertyNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class PropertyExists : public UICDMError
+{
+public:
+ PropertyExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class DuplicateInstanceName : public UICDMError
+{
+public:
+ DuplicateInstanceName(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class InstanceNotFound : public UICDMError
+{
+public:
+ InstanceNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class ValueTypeError : public UICDMError
+{
+public:
+ ValueTypeError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SerializationError : public UICDMError
+{
+public:
+ SerializationError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SlideNotFound : public UICDMError
+{
+public:
+ SlideNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SlideExists : public UICDMError
+{
+public:
+ SlideExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SlideDerivationError : public UICDMError
+{
+public:
+ SlideDerivationError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SlideChildNotFoundError : public UICDMError
+{
+public:
+ SlideChildNotFoundError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SlideGraphNotFound : public UICDMError
+{
+public:
+ SlideGraphNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class SlideGraphExists : public UICDMError
+{
+public:
+ SlideGraphExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class PropertyLinkError : public UICDMError
+{
+public:
+ PropertyLinkError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class RearrangeSlideArgumentsMustNotBeZero : public UICDMError
+{
+public:
+ RearrangeSlideArgumentsMustNotBeZero(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class AnimationNotFound : public UICDMError
+{
+public:
+ AnimationNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class AnimationExists : public UICDMError
+{
+public:
+ AnimationExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class AnimationKeyframeTypeError : public UICDMError
+{
+public:
+ AnimationKeyframeTypeError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class AnimationKeyframeNotFound : public UICDMError
+{
+public:
+ AnimationKeyframeNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class AnimationEvaluationError : public UICDMError
+{
+public:
+ AnimationEvaluationError(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class ActionNotFound : public UICDMError
+{
+public:
+ ActionNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class ActionExists : public UICDMError
+{
+public:
+ ActionExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class HandlerArgumentNotFound : public UICDMError
+{
+public:
+ HandlerArgumentNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class HandlerArgumentExists : public UICDMError
+{
+public:
+ HandlerArgumentExists(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class CustomPropertyNotFound : public UICDMError
+{
+public:
+ CustomPropertyNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class CustomEventNotFound : public UICDMError
+{
+public:
+ CustomEventNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class CustomHandlerNotFound : public UICDMError
+{
+public:
+ CustomHandlerNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class CustomHandlerParamNotFound : public UICDMError
+{
+public:
+ CustomHandlerParamNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+
+class AttributeTypeNotFound : public UICDMError
+{
+public:
+ AttributeTypeNotFound(const wchar_t *inMessage)
+ : UICDMError(inMessage)
+ {
+ }
+};
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMGuides.cpp b/src/Authoring/UICDM/Systems/UICDMGuides.cpp
new file mode 100644
index 00000000..709d192e
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMGuides.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "UICDMGuides.h"
+#include <unordered_map>
+#include "boost/signals.hpp"
+#include <boost/signals/connection.hpp>
+#include "VectorTransactions.h"
+
+using namespace UICDM;
+
+namespace {
+
+struct SBoostSignalConnection : public ISignalConnection
+{
+ Q_DISABLE_COPY(SBoostSignalConnection)
+ boost::BOOST_SIGNALS_NAMESPACE::scoped_connection m_connection;
+ SBoostSignalConnection(const boost::BOOST_SIGNALS_NAMESPACE::connection &inConnection)
+ : m_connection(inConnection)
+ {
+ }
+};
+
+#define CONNECT(x) std::make_shared<SBoostSignalConnection>(x.connect(inCallback))
+
+struct SGuideSystem : public IGuideSystem
+{
+ typedef std::unordered_map<long, SGuideInfo> TGuideMap;
+ typedef std::shared_ptr<IMergeableTransaction<SGuideInfo>> TMergeableTransaction;
+ typedef std::unordered_map<long, TMergeableTransaction> TGuideInfoMergeMap;
+
+ long m_NextHandleValue;
+ TGuideMap m_Guides;
+ bool m_GuidesEditable;
+
+ std::shared_ptr<ITransactionConsumer> m_CurrentTransaction;
+ TGuideInfoMergeMap m_GuideMergeMap;
+
+ boost::signal<void(CUICDMGuideHandle, SGuideInfo)> m_GuideCreated;
+ boost::signal<void(CUICDMGuideHandle, SGuideInfo)> m_GuideDestroyed;
+ boost::signal<void(CUICDMGuideHandle, SGuideInfo)> m_GuideModified;
+ boost::signal<void(CUICDMGuideHandle, SGuideInfo)> m_GuideModifiedImmediate;
+
+ SGuideSystem()
+ : m_NextHandleValue(0)
+ , m_GuidesEditable(true)
+ {
+ }
+
+ void SignalGuideCreated(long hdl, const SGuideInfo &inInfo) { m_GuideCreated(hdl, inInfo); }
+
+ void SignalGuideDestroyed(long hdl, const SGuideInfo &inInfo) { m_GuideDestroyed(hdl, inInfo); }
+
+ void SignalGuideModified(long hdl, const SGuideInfo &inInfo) { m_GuideModified(hdl, inInfo); }
+
+ CUICDMGuideHandle CreateGuide() override
+ {
+ ++m_NextHandleValue;
+ std::pair<long, SGuideInfo> entry(std::make_pair(m_NextHandleValue, SGuideInfo()));
+ m_Guides.insert(entry);
+ if (m_CurrentTransaction) {
+ CreateHashMapInsertTransaction(__FILE__, __LINE__, m_CurrentTransaction, entry,
+ m_Guides);
+ m_CurrentTransaction->OnDoNotification(std::bind(
+ &SGuideSystem::SignalGuideCreated, this, m_NextHandleValue, SGuideInfo()));
+ m_CurrentTransaction->OnUndoNotification(std::bind(
+ &SGuideSystem::SignalGuideDestroyed, this, m_NextHandleValue, SGuideInfo()));
+ }
+
+ return m_NextHandleValue;
+ }
+
+ SGuideInfo *InternalGetGuideInfo(CUICDMGuideHandle inGuideHandle)
+ {
+ TGuideMap::iterator theFind = m_Guides.find((long)inGuideHandle.GetHandleValue());
+ if (theFind != m_Guides.end())
+ return &theFind->second;
+ return NULL;
+ }
+
+ const SGuideInfo *InternalGetGuideInfo(CUICDMGuideHandle inGuideHandle) const
+ {
+ return const_cast<SGuideSystem &>(*this).InternalGetGuideInfo(inGuideHandle);
+ }
+
+ void SetGuideInfo(CUICDMGuideHandle inGuideHandle, const SGuideInfo &info) override
+ {
+ SGuideInfo *existing = InternalGetGuideInfo(inGuideHandle);
+ long theHdlValue = (long)inGuideHandle.GetHandleValue();
+ TGuideInfoMergeMap::iterator iter = m_GuideMergeMap.find(theHdlValue);
+ if (iter != m_GuideMergeMap.end()) {
+ iter->second->Update(info);
+ *existing = info;
+ } else {
+ if (!existing) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SGuideInfo oldValue(*existing);
+ *existing = info;
+ if (m_CurrentTransaction) {
+ TMergeableTransaction newTransaction =
+ CreateHashMapSwapTransaction(__FILE__, __LINE__, m_CurrentTransaction,
+ theHdlValue, oldValue, info, m_Guides);
+ m_GuideMergeMap.insert(std::make_pair(theHdlValue, newTransaction));
+ m_CurrentTransaction->OnDoNotification(
+ std::bind(&SGuideSystem::SignalGuideModified, this, theHdlValue, info));
+ m_CurrentTransaction->OnUndoNotification(
+ std::bind(&SGuideSystem::SignalGuideModified, this, theHdlValue, oldValue));
+ }
+ }
+ if (AreUICDMSignalsEnabled())
+ m_GuideModifiedImmediate(theHdlValue, info);
+ }
+
+ SGuideInfo GetGuideInfo(CUICDMGuideHandle inGuideHandle) const override
+ {
+ const SGuideInfo *existing = InternalGetGuideInfo(inGuideHandle);
+ if (existing)
+ return *existing;
+ QT3DS_ASSERT(false);
+ return SGuideInfo();
+ }
+
+ void DeleteGuide(CUICDMGuideHandle inGuideHandle) override
+ {
+
+ SGuideInfo *existing = InternalGetGuideInfo(inGuideHandle);
+ if (!existing) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ long theHdlValue = (long)inGuideHandle.GetHandleValue();
+ SGuideInfo oldValue = *existing;
+ m_Guides.erase(theHdlValue);
+
+ if (m_CurrentTransaction) {
+ std::pair<long, SGuideInfo> entry(std::make_pair(theHdlValue, oldValue));
+ CreateHashMapEraseTransaction(__FILE__, __LINE__, m_CurrentTransaction, entry,
+ m_Guides);
+ m_CurrentTransaction->OnDoNotification(
+ std::bind(&SGuideSystem::SignalGuideDestroyed, this, theHdlValue, oldValue));
+ m_CurrentTransaction->OnUndoNotification(
+ std::bind(&SGuideSystem::SignalGuideCreated, this, theHdlValue, oldValue));
+ }
+ }
+
+ TGuideHandleList GetAllGuides() const override
+ {
+ TGuideHandleList retval;
+ for (TGuideMap::const_iterator iter = m_Guides.begin(), end = m_Guides.end(); iter != end;
+ ++iter)
+ retval.push_back(iter->first);
+ return retval;
+ }
+
+ bool IsGuideValid(CUICDMGuideHandle inGuideHandle) const override
+ {
+ return InternalGetGuideInfo(inGuideHandle) != NULL;
+ }
+ bool AreGuidesEditable() const override { return m_GuidesEditable; }
+ void SetGuidesEditable(bool val) override { m_GuidesEditable = val; }
+
+ // Undo/Redo
+ void SetConsumer(std::shared_ptr<ITransactionConsumer> inConsumer) override
+ {
+ m_CurrentTransaction = inConsumer;
+ m_GuideMergeMap.clear();
+ }
+
+ // These are events coming from undo/redo operations, not events coming directly from the
+ // modification of the guides
+ virtual TSignalConnectionPtr
+ ConnectGuideCreated(const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) override
+ {
+ return CONNECT(m_GuideCreated);
+ }
+
+ virtual TSignalConnectionPtr
+ ConnectGuideDestroyed(const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) override
+ {
+ return CONNECT(m_GuideDestroyed);
+ }
+
+ virtual TSignalConnectionPtr
+ ConnectGuideModified(const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) override
+ {
+ return CONNECT(m_GuideModified);
+ }
+
+ // Signal happens immediately instead of on undo/redo, used for live-update of the inspector
+ // palette
+ TSignalConnectionPtr ConnectGuideModifiedImmediate(
+ const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) override
+ {
+ return CONNECT(m_GuideModifiedImmediate);
+ }
+};
+}
+
+shared_ptr<IGuideSystem> IGuideSystem::CreateGuideSystem()
+{
+ return std::make_shared<SGuideSystem>();
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMGuides.h b/src/Authoring/UICDM/Systems/UICDMGuides.h
new file mode 100644
index 00000000..bb4bda9f
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMGuides.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMGUIDESH
+#define UICDMGUIDESH
+#include "UICDMDataTypes.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "UICDMSignals.h"
+#include "UICDMHandles.h"
+#include "UICDMTransactions.h"
+#include <functional>
+
+namespace UICDM {
+struct GuideDirections
+{
+ enum Enum {
+ UnknownDirection = 0,
+ Vertical,
+ Horizontal,
+ };
+};
+
+struct SGuideInfo
+{
+ qt3ds::QT3DSF32 m_Position;
+ GuideDirections::Enum m_Direction;
+ qt3ds::QT3DSI32 m_Width;
+ SGuideInfo(qt3ds::QT3DSF32 pos = 0.0f, GuideDirections::Enum dir = GuideDirections::UnknownDirection,
+ qt3ds::QT3DSI32 width = 1)
+ : m_Position(pos)
+ , m_Direction(dir)
+ , m_Width(width)
+ {
+ }
+};
+
+class IGuideSystem : public ITransactionProducer
+{
+protected:
+ virtual ~IGuideSystem() {}
+public:
+ friend class std::shared_ptr<IGuideSystem>;
+
+ virtual CUICDMGuideHandle CreateGuide() = 0;
+ virtual void SetGuideInfo(CUICDMGuideHandle inGuideHandle, const SGuideInfo &info) = 0;
+ virtual SGuideInfo GetGuideInfo(CUICDMGuideHandle inGuideHandle) const = 0;
+ virtual void DeleteGuide(CUICDMGuideHandle inGuideHandle) = 0;
+ virtual TGuideHandleList GetAllGuides() const = 0;
+ virtual bool IsGuideValid(CUICDMGuideHandle inGuideHandle) const = 0;
+ // No real effect on datamodel because you can still create guides when they are locked.
+ // Just used in the UI.
+ virtual bool AreGuidesEditable() const = 0;
+ virtual void SetGuidesEditable(bool val) = 0;
+
+ // Undo/Redo
+ void SetConsumer(std::shared_ptr<ITransactionConsumer> inConsumer) override = 0;
+
+ // These are events coming from undo/redo operations, not events coming directly from the
+ // modification of the guides
+ virtual TSignalConnectionPtr
+ ConnectGuideCreated(const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectGuideDestroyed(
+ const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectGuideModified(
+ const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) = 0;
+
+ // Signal happens immediately instead of on undo/redo, used for live-update of the inspector
+ // palette
+ virtual TSignalConnectionPtr ConnectGuideModifiedImmediate(
+ const std::function<void(CUICDMGuideHandle, SGuideInfo)> &inCallback) = 0;
+
+ static std::shared_ptr<IGuideSystem> CreateGuideSystem();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMHandles.cpp b/src/Authoring/UICDM/Systems/UICDMHandles.cpp
new file mode 100644
index 00000000..24324943
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMHandles.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICDMPrefix.h"
+#include "UICDMHandles.h"
+
+namespace UICDM {
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMHandles.h b/src/Authoring/UICDM/Systems/UICDMHandles.h
new file mode 100644
index 00000000..c6653872
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMHandles.h
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMHANDLESH
+#define UICDMHANDLESH
+
+#include <QMetaType>
+
+namespace UICDM {
+
+class IDataCore;
+
+class CDataModelHandle
+{
+ int m_Handle;
+
+public:
+ inline CDataModelHandle(int inHandle = 0);
+ inline CDataModelHandle(const CDataModelHandle &other);
+ virtual ~CDataModelHandle();
+
+ // Operators
+ inline CDataModelHandle &operator=(const CDataModelHandle &other);
+ inline bool operator==(const CDataModelHandle &other) const;
+ inline bool operator<(const CDataModelHandle &other) const;
+ inline operator int() const { return GetHandleValue(); }
+
+ // Use
+ inline bool Valid() const { return m_Handle != 0; }
+ int GetHandleValue() const { return m_Handle; }
+};
+
+inline CDataModelHandle::CDataModelHandle(int inHandle)
+ : m_Handle(inHandle)
+{
+}
+inline CDataModelHandle::CDataModelHandle(const CDataModelHandle &other)
+ : m_Handle(other.m_Handle)
+{
+}
+inline CDataModelHandle::~CDataModelHandle()
+{
+}
+
+inline CDataModelHandle &CDataModelHandle::operator=(const CDataModelHandle &other)
+{
+ if (this != &other) {
+ m_Handle = other.m_Handle;
+ }
+ return *this;
+}
+
+inline bool CDataModelHandle::operator==(const CDataModelHandle &other) const
+{
+ return m_Handle == other.m_Handle;
+}
+
+inline bool CDataModelHandle::operator<(const CDataModelHandle &other) const
+{
+ return m_Handle < other.m_Handle;
+}
+
+class CUICDMInstanceHandle : public CDataModelHandle
+{
+public:
+ CUICDMInstanceHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMInstanceHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMInstanceHandle(const CUICDMInstanceHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMInstanceHandle &operator=(const CUICDMInstanceHandle &inOther)
+ {
+ return static_cast<CUICDMInstanceHandle &>(CDataModelHandle::operator=(inOther));
+ }
+
+ inline bool operator==(const CUICDMInstanceHandle &other) const
+ {
+ return CDataModelHandle::operator==(other);
+ }
+};
+
+typedef std::vector<CUICDMInstanceHandle> TInstanceHandleList;
+
+class CUICDMPropertyHandle : public CDataModelHandle
+{
+public:
+ CUICDMPropertyHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMPropertyHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMPropertyHandle(const CUICDMInstanceHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMPropertyHandle &operator=(const CUICDMPropertyHandle &inOther)
+ {
+ return static_cast<CUICDMPropertyHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMPropertyHandle> TPropertyHandleList;
+
+class CUICDMSlideHandle : public CDataModelHandle
+{
+public:
+ CUICDMSlideHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMSlideHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMSlideHandle(const CUICDMSlideHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMSlideHandle &operator=(const CUICDMSlideHandle &inOther)
+ {
+ return static_cast<CUICDMSlideHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMSlideHandle> TSlideHandleList;
+
+class CUICDMSlideGraphHandle : public CDataModelHandle
+{
+public:
+ CUICDMSlideGraphHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMSlideGraphHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMSlideGraphHandle(const CUICDMSlideGraphHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMSlideGraphHandle &operator=(const CUICDMSlideGraphHandle &inOther)
+ {
+ return static_cast<CUICDMSlideGraphHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMSlideGraphHandle> TSlideGraphHandleList;
+
+class CUICDMAnimationHandle : public CDataModelHandle
+{
+public:
+ CUICDMAnimationHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMAnimationHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMAnimationHandle(const CUICDMAnimationHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMAnimationHandle &operator=(const CUICDMAnimationHandle &inOther)
+ {
+ return static_cast<CUICDMAnimationHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMAnimationHandle> TAnimationHandleList;
+
+class CUICDMKeyframeHandle : public CDataModelHandle
+{
+public:
+ CUICDMKeyframeHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMKeyframeHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMKeyframeHandle(const CUICDMKeyframeHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMKeyframeHandle &operator=(const CUICDMKeyframeHandle &inOther)
+ {
+ return static_cast<CUICDMKeyframeHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMKeyframeHandle> TKeyframeHandleList;
+
+class CUICDMActionHandle : public CDataModelHandle
+{
+public:
+ CUICDMActionHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMActionHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMActionHandle(const CUICDMActionHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMActionHandle &operator=(const CUICDMActionHandle &inOther)
+ {
+ return static_cast<CUICDMActionHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMActionHandle> TActionHandleList;
+
+class CUICDMHandlerArgHandle : public CDataModelHandle
+{
+public:
+ CUICDMHandlerArgHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMHandlerArgHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMHandlerArgHandle(const CUICDMHandlerArgHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+ CUICDMHandlerArgHandle &operator=(const CUICDMHandlerArgHandle &inOther)
+ {
+ return static_cast<CUICDMHandlerArgHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMHandlerArgHandle> THandlerArgHandleList;
+
+class CUICDMEventHandle : public CDataModelHandle
+{
+public:
+ CUICDMEventHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMEventHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMEventHandle(const CUICDMEventHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMEventHandle &operator=(const CUICDMEventHandle &inOther)
+ {
+ return static_cast<CUICDMEventHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMEventHandle> TEventHandleList;
+
+class CUICDMHandlerHandle : public CDataModelHandle
+{
+public:
+ CUICDMHandlerHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMHandlerHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMHandlerHandle(const CUICDMHandlerHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMHandlerHandle &operator=(const CUICDMHandlerHandle &inOther)
+ {
+ return static_cast<CUICDMHandlerHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMHandlerHandle> THandlerHandleList;
+
+class CUICDMHandlerParamHandle : public CDataModelHandle
+{
+public:
+ CUICDMHandlerParamHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMHandlerParamHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMHandlerParamHandle(const CUICDMHandlerParamHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMHandlerParamHandle &operator=(const CUICDMHandlerParamHandle &inOther)
+ {
+ return static_cast<CUICDMHandlerParamHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMHandlerParamHandle> THandlerParamHandleList;
+
+class CUICDMMetaDataPropertyHandle : public CDataModelHandle
+{
+public:
+ CUICDMMetaDataPropertyHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMMetaDataPropertyHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMMetaDataPropertyHandle(const CUICDMMetaDataPropertyHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMMetaDataPropertyHandle &operator=(const CUICDMMetaDataPropertyHandle &inOther)
+ {
+ return static_cast<CUICDMMetaDataPropertyHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMMetaDataPropertyHandle> TMetaDataPropertyHandleList;
+
+class CUICDMCategoryHandle : public CDataModelHandle
+{
+public:
+ CUICDMCategoryHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMCategoryHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMCategoryHandle(const CUICDMCategoryHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+ CUICDMCategoryHandle &operator=(const CUICDMCategoryHandle &inOther)
+ {
+ return static_cast<CUICDMCategoryHandle &>(CDataModelHandle::operator=(inOther));
+ }
+};
+
+typedef std::vector<CUICDMCategoryHandle> TCategoryHandleList;
+
+class CUICDMGuideHandle : public CDataModelHandle
+{
+public:
+ CUICDMGuideHandle(int inHandle = 0)
+ : CDataModelHandle(inHandle)
+ {
+ }
+
+ CUICDMGuideHandle(const CDataModelHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+
+ CUICDMGuideHandle(const CUICDMCategoryHandle &inOther)
+ : CDataModelHandle(inOther)
+ {
+ }
+ CUICDMGuideHandle &operator=(const CUICDMGuideHandle &inOther)
+ {
+ CDataModelHandle::operator=(inOther);
+ return *this;
+ }
+};
+
+typedef std::vector<CUICDMGuideHandle> TGuideHandleList;
+}
+
+Q_DECLARE_METATYPE(UICDM::CUICDMSlideHandle);
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMMetaData.cpp b/src/Authoring/UICDM/Systems/UICDMMetaData.cpp
new file mode 100644
index 00000000..132419aa
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMMetaData.cpp
@@ -0,0 +1,4094 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#ifdef _WIN32
+#pragma warning(disable : 4103)
+#endif
+#include "UICDMMetaData.h"
+#include "UICDMXML.h"
+#include "foundation/Qt3DSAssert.h"
+#include "StandardExtensions.h"
+#include <unordered_map>
+#include <memory>
+#include <unordered_set>
+#include "UICDMTransactions.h"
+#include "VectorTransactions.h"
+#include "UICDMSignals.h"
+// Pull in the fancy str-type implementations
+#include "UICDMWStrOpsImpl.h"
+#include "UICDMDataCore.h"
+#include "DataCoreProducer.h"
+#include "UICDMWindowsCompatibility.h"
+#include "UICRenderEffectSystem.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "foundation/StringConversionImpl.h"
+#include <QtCore/qdir.h>
+
+#ifndef UICDM_META_DATA_NO_SIGNALS
+#include <boost/signal.hpp>
+#include <boost/signals/connection.hpp>
+using boost::BOOST_SIGNALS_NAMESPACE::scoped_connection;
+using boost::BOOST_SIGNALS_NAMESPACE::connection;
+#endif
+
+using namespace UICDM;
+using std::shared_ptr;
+using std::make_shared;
+using std::static_pointer_cast;
+using std::unordered_map;
+using std::unordered_set;
+using std::function;
+using std::bind;
+using std::ref;
+using std::get;
+using qt3ds::foundation::Empty;
+
+typedef CUICDMInstanceHandle TInstanceHandle;
+typedef CUICDMPropertyHandle TPropertyHandle;
+typedef CUICDMEventHandle TEventHandle;
+typedef CUICDMHandlerHandle THandlerHandle;
+typedef CUICDMHandlerArgHandle THandlerArgHandle;
+typedef CUICDMMetaDataPropertyHandle TMetaDataPropertyHandle;
+typedef CUICDMCategoryHandle TCategoryHandle;
+
+namespace UICDM {
+#define UIC_WCHAR_T_None L"None"
+#define UIC_WCHAR_T_StringList L"StringList"
+#define UIC_WCHAR_T_Range L"Range"
+#define UIC_WCHAR_T_Image L"Image"
+#define UIC_WCHAR_T_Color L"Color"
+#define UIC_WCHAR_T_Rotation L"Rotation"
+#define UIC_WCHAR_T_Font L"Font"
+#define UIC_WCHAR_T_FontSize L"FontSize"
+#define UIC_WCHAR_T_MultiLine L"MultiLine"
+#define UIC_WCHAR_T_ObjectRef L"ObjectRef"
+#define UIC_WCHAR_T_Mesh L"Mesh"
+#define UIC_WCHAR_T_Import L"Import"
+#define UIC_WCHAR_T_Texture L"Texture"
+#define UIC_WCHAR_T_Image2D L"Image2D"
+#define UIC_WCHAR_T_Buffer L"Buffer"
+#define UIC_WCHAR_T_Property L"Property"
+#define UIC_WCHAR_T_Dependent L"Dependent"
+#define UIC_WCHAR_T_Slide L"Slide"
+#define UIC_WCHAR_T_Event L"Event"
+#define UIC_WCHAR_T_Object L"Object"
+#define UIC_WCHAR_T_Signal L"Signal"
+#define UIC_WCHAR_T_Renderable L"Renderable"
+#define UIC_WCHAR_T_PathBuffer L"PathBuffer"
+#define UIC_WCHAR_T_ShadowMapResolution L"ShadowMapResolution"
+
+#define ITERATE_ADDITIONAL_META_DATA_TYPES \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(None) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(StringList) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Range) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Image) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Color) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Rotation) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Font) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(FontSize) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(MultiLine) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(ObjectRef) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Mesh) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Import) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Texture) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(Renderable) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(PathBuffer) \
+ HANDLE_ADDITIONAL_META_DATA_TYPE(ShadowMapResolution)
+template <>
+struct WStrOps<AdditionalMetaDataType::Value>
+{
+ QT3DSU32 ToStr(AdditionalMetaDataType::Value item, NVDataRef<wchar_t> buffer)
+ {
+ switch (item) {
+#define HANDLE_ADDITIONAL_META_DATA_TYPE(name) \
+ case AdditionalMetaDataType::name: \
+ wcscpy_s(buffer.begin(), buffer.size(), UIC_WCHAR_T_##name); \
+ return 1;
+ ITERATE_ADDITIONAL_META_DATA_TYPES
+ #undef HANDLE_ADDITIONAL_META_DATA_TYPE
+ }
+ return 0;
+ }
+ bool StrTo(const wchar_t *buffer, AdditionalMetaDataType::Value &item)
+ {
+#define HANDLE_ADDITIONAL_META_DATA_TYPE(name) \
+ if (AreEqual(buffer, UIC_WCHAR_T_##name)) { \
+ item = AdditionalMetaDataType::name; \
+ return true; \
+ }
+ ITERATE_ADDITIONAL_META_DATA_TYPES
+ #undef HANDLE_ADDITIONAL_META_DATA_TYPE
+ return false;
+ }
+};
+
+#undef ITERATE_ADDITIONAL_META_DATA_TYPES
+
+#define ITERATE_HANDLER_ARG_TYPES \
+ HANDLE_HANDLER_ARG_TYPE(None) \
+ HANDLE_HANDLER_ARG_TYPE(Property) \
+ HANDLE_HANDLER_ARG_TYPE(Dependent) \
+ HANDLE_HANDLER_ARG_TYPE(Slide) \
+ HANDLE_HANDLER_ARG_TYPE(Event) \
+ HANDLE_HANDLER_ARG_TYPE(Object) \
+ HANDLE_HANDLER_ARG_TYPE(Signal)
+
+QT3DSU32 WStrOps<HandlerArgumentType::Value>::ToStr(HandlerArgumentType::Value item, NVDataRef<wchar_t> buffer)
+{
+ switch (item) {
+#define HANDLE_HANDLER_ARG_TYPE(name) \
+ case HandlerArgumentType::name: \
+ wcscpy_s(buffer.begin(), buffer.size(), UIC_WCHAR_T_##name); \
+ return 1;
+ ITERATE_HANDLER_ARG_TYPES
+ #undef HANDLE_HANDLER_ARG_TYPE
+ }
+ return 0;
+}
+
+bool WStrOps<HandlerArgumentType::Value>::StrTo(const wchar_t *buffer, HandlerArgumentType::Value &item)
+{
+#define HANDLE_HANDLER_ARG_TYPE(name) \
+ if (AreEqual(buffer, UIC_WCHAR_T_##name)) { \
+ item = HandlerArgumentType::name; \
+ return true; \
+}
+ ITERATE_HANDLER_ARG_TYPES
+ #undef HANDLE_HANDLER_ARG_TYPE
+ return false;
+}
+
+#define UIC_WCHAR_T_FloatRange L"FloatRange"
+#define UIC_WCHAR_T_LongRange L"LongRange"
+#define UIC_WCHAR_T_Vector L"Vector"
+#define UIC_WCHAR_T_MultiLineString L"MultiLineString"
+#define UIC_WCHAR_T_Boolean L"Boolean"
+#define UIC_WCHAR_T_Guid L"Guid"
+#define UIC_WCHAR_T_StringListOrInt L"StringListOrInt"
+#define UIC_WCHAR_T_Scale L"Scale"
+
+#define ITERATE_UICDM_COMPLETE_TYPES \
+ HANDLE_UIDM_COMPLETE_NONE_TYPE \
+ HANDLE_UIDM_COMPLETE_TYPE(StringList, StringList, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(FloatRange, Range, DataModelDataType::Float) \
+ HANDLE_UIDM_COMPLETE_TYPE(LongRange, Range, DataModelDataType::Long) \
+ HANDLE_UIDM_COMPLETE_TYPE(Float, None, DataModelDataType::Float) \
+ HANDLE_UIDM_COMPLETE_TYPE(Long, None, DataModelDataType::Long) \
+ HANDLE_UIDM_COMPLETE_TYPE(Float2, None, DataModelDataType::Float2) \
+ HANDLE_UIDM_COMPLETE_TYPE(Vector, None, DataModelDataType::Float3) \
+ HANDLE_UIDM_COMPLETE_TYPE(Scale, None, DataModelDataType::Float3) \
+ HANDLE_UIDM_COMPLETE_TYPE(Rotation, Rotation, DataModelDataType::Float3) \
+ HANDLE_UIDM_COMPLETE_TYPE(Color, Color, DataModelDataType::Float3) \
+ HANDLE_UIDM_COMPLETE_TYPE(Boolean, None, DataModelDataType::Bool) \
+ HANDLE_UIDM_COMPLETE_TYPE(Slide, None, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(Font, Font, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(FontSize, FontSize, DataModelDataType::Float) \
+ HANDLE_UIDM_COMPLETE_TYPE(String, None, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(MultiLineString, MultiLine, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(ObjectRef, ObjectRef, DataModelDataType::ObjectRef) \
+ HANDLE_UIDM_COMPLETE_TYPE(Image, Image, DataModelDataType::Long4) \
+ HANDLE_UIDM_COMPLETE_TYPE(Mesh, Mesh, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(Import, Import, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(Texture, Texture, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(Image2D, Texture, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(Buffer, Texture, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(Guid, None, DataModelDataType::Long4) \
+ HANDLE_UIDM_COMPLETE_TYPE(StringListOrInt, StringList, DataModelDataType::StringOrInt) \
+ HANDLE_UIDM_COMPLETE_TYPE(Renderable, Renderable, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(PathBuffer, PathBuffer, DataModelDataType::String) \
+ HANDLE_UIDM_COMPLETE_TYPE(ShadowMapResolution, ShadowMapResolution, DataModelDataType::Long)
+
+DataModelDataType::Value CompleteMetaDataType::ToDataType(CompleteMetaDataType::Enum inCompleteType)
+{
+ switch (inCompleteType) {
+#define HANDLE_UIDM_COMPLETE_NONE_TYPE \
+ case Unknown: \
+ return DataModelDataType::None;
+#define HANDLE_UIDM_COMPLETE_TYPE(name, addtype, dtype) \
+ case name: \
+ return dtype;
+ ITERATE_UICDM_COMPLETE_TYPES
+ #undef HANDLE_UIDM_COMPLETE_NONE_TYPE
+ #undef HANDLE_UIDM_COMPLETE_TYPE
+ }
+ QT3DS_ASSERT(false);
+ return DataModelDataType::None;
+}
+
+AdditionalMetaDataType::Value
+CompleteMetaDataType::ToAdditionalType(CompleteMetaDataType::Enum inCompleteType)
+{
+ switch (inCompleteType) {
+#define HANDLE_UIDM_COMPLETE_NONE_TYPE \
+ case Unknown: \
+ return AdditionalMetaDataType::None;
+#define HANDLE_UIDM_COMPLETE_TYPE(name, addtype, dtype) \
+ case name: \
+ return AdditionalMetaDataType::addtype;
+ ITERATE_UICDM_COMPLETE_TYPES
+ #undef HANDLE_UIDM_COMPLETE_NONE_TYPE
+ #undef HANDLE_UIDM_COMPLETE_TYPE
+ }
+ QT3DS_ASSERT(false);
+ return AdditionalMetaDataType::None;
+}
+
+CompleteMetaDataType::Enum
+CompleteMetaDataType::ToCompleteType(DataModelDataType::Value inDataType,
+ AdditionalMetaDataType::Value inAdditionalType)
+{
+#define HANDLE_UIDM_COMPLETE_NONE_TYPE \
+ if (inDataType == DataModelDataType::None) \
+ return CompleteMetaDataType::Unknown;
+#define HANDLE_UIDM_COMPLETE_TYPE(name, addtype, dtype) \
+ if (inDataType == dtype \
+ && inAdditionalType == AdditionalMetaDataType::addtype) \
+ return CompleteMetaDataType::name;
+
+ ITERATE_UICDM_COMPLETE_TYPES
+ #undef HANDLE_UIDM_COMPLETE_NONE_TYPE
+ #undef HANDLE_UIDM_COMPLETE_TYPE
+ QT3DS_ASSERT(false);
+ return CompleteMetaDataType::Unknown;
+}
+
+QT3DSU32 WStrOps<CompleteMetaDataType::Enum>::ToStr(CompleteMetaDataType::Enum item,
+ NVDataRef<wchar_t> buffer)
+{
+ switch (item) {
+#define HANDLE_UIDM_COMPLETE_NONE_TYPE \
+ case CompleteMetaDataType::Unknown: \
+ wcscpy_s(buffer.begin(), buffer.size(), L"None"); \
+ return 1;
+#define HANDLE_UIDM_COMPLETE_TYPE(name, addtype, dtype) \
+ case CompleteMetaDataType::name: \
+ wcscpy_s(buffer.begin(), buffer.size(), UIC_WCHAR_T_##name); \
+ return 1;
+
+ ITERATE_UICDM_COMPLETE_TYPES
+ #undef HANDLE_UIDM_COMPLETE_NONE_TYPE
+ #undef HANDLE_UIDM_COMPLETE_TYPE
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+}
+bool WStrOps<CompleteMetaDataType::Enum>::StrTo(const wchar_t *buffer,
+ CompleteMetaDataType::Enum &item)
+{
+
+#define HANDLE_UIDM_COMPLETE_NONE_TYPE \
+ if (AreEqual(buffer, L"None")) { \
+ item = CompleteMetaDataType::Unknown; \
+ return true; \
+}
+#define HANDLE_UIDM_COMPLETE_TYPE(name, addtype, dtype) \
+ if (AreEqual(buffer, UIC_WCHAR_T_##name)) { \
+ item = CompleteMetaDataType::name; \
+ return true; \
+}
+
+ ITERATE_UICDM_COMPLETE_TYPES
+ #undef HANDLE_UIDM_COMPLETE_NONE_TYPE
+ #undef HANDLE_UIDM_COMPLETE_TYPE
+ return false;
+}
+}
+
+namespace {
+
+#ifndef UICDM_META_DATA_NO_SIGNALS
+
+struct SBoostSignalConnection : public ISignalConnection
+{
+ Q_DISABLE_COPY(SBoostSignalConnection)
+
+ scoped_connection m_connection;
+ SBoostSignalConnection(const connection &inConnection)
+ : m_connection(inConnection)
+ {
+ }
+};
+
+#define CONNECT(x) std::make_shared<SBoostSignalConnection>(x.connect(inCallback))
+#else
+
+#define CONNECT(x) std::shared_ptr<UICDM::ISignalConnection>()
+
+struct SNullFunc
+{
+ template <typename TArgType>
+ void operator()(TArgType)
+ {
+ }
+ template <typename TA1, typename TA2>
+ void operator()(TA1, TA2)
+ {
+ }
+};
+
+#endif
+
+typedef TCharStr TStrType;
+using std::hash;
+
+struct InstanceHandleVecHash
+{
+ size_t operator()(const vector<TInstanceHandle> &inInstances) const
+ {
+ size_t retval = 0;
+ for (size_t idx = 0, end = inInstances.size(); idx < end; ++idx)
+ retval = retval ^ hash<int>()(inInstances[idx]);
+ return retval;
+ }
+};
+
+struct SEventAndHandlerBase
+{
+ CUICDMInstanceHandle m_Instance;
+ TStrType m_Name;
+ TStrType m_FormalName;
+ TStrType m_Category;
+ TStrType m_Description;
+ SEventAndHandlerBase() {}
+ SEventAndHandlerBase(CUICDMInstanceHandle hdl)
+ : m_Instance(hdl)
+ {
+ }
+};
+
+struct SEvent : public SEventAndHandlerBase
+{
+ SEvent() {}
+ SEvent(CUICDMInstanceHandle hdl)
+ : SEventAndHandlerBase(hdl)
+ {
+ }
+};
+
+struct SHandler : public SEventAndHandlerBase
+{
+ SHandler() {}
+ SHandler(CUICDMInstanceHandle hdl)
+ : SEventAndHandlerBase(hdl)
+ {
+ }
+ vector<SMetaDataHandlerArgumentInfo> m_Arguments;
+};
+
+// Note that this hash item only works for strings that are in the string table.
+// These have the property that pointer comparison also indicates string equality.
+struct SInstanceStrHash
+{
+ size_t operator()(const pair<TInstanceHandle, TCharPtr> &inPair) const
+ {
+ return hash<int>()(inPair.first) ^ hash<const void *>()(inPair.second);
+ }
+};
+
+template <typename TDataType>
+NVConstDataRef<TDataType> VecToCRef(const eastl::vector<TDataType> &inType)
+{
+ return NVConstDataRef<TDataType>(inType.data(), (QT3DSU32)inType.size());
+}
+
+struct SMetaDataDynamicObjectImpl
+{
+private:
+ SMetaDataDynamicObjectImpl &operator=(const SMetaDataDynamicObjectImpl &inOther);
+
+public:
+ TCharStr m_Name;
+ TCharStr m_SourcePath;
+ eastl::vector<SMetaDataShader> m_Shaders;
+ eastl::vector<uic::render::dynamic::SPropertyDefinition> m_Properties;
+ eastl::vector<eastl::vector<qt3ds::foundation::CRegisteredString> *> m_EnumValueNames;
+ ~SMetaDataDynamicObjectImpl() { ClearEnumValueNames(); }
+
+ void ClearEnumValueNames()
+ {
+ for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx)
+ delete (m_EnumValueNames[idx]);
+ m_EnumValueNames.clear();
+ }
+};
+
+struct SMetaDataEffectImpl : public SMetaDataDynamicObjectImpl
+{
+private:
+ SMetaDataEffectImpl &operator=(const SMetaDataEffectImpl &inOther);
+
+public:
+ eastl::vector<uic::render::dynamic::SCommand *> m_EffectCommands;
+
+ void ClearEffectCommands()
+ {
+ for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx)
+ free(m_EffectCommands[idx]);
+ m_EffectCommands.clear();
+ }
+ SMetaDataEffect ToEffect() const
+ {
+ return SMetaDataEffect(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties),
+ VecToCRef(m_EffectCommands));
+ }
+};
+
+struct SMetaDataCustomMaterialImpl : public SMetaDataDynamicObjectImpl
+{
+private:
+ SMetaDataCustomMaterialImpl &operator=(const SMetaDataCustomMaterialImpl &);
+
+public:
+ eastl::vector<uic::render::dynamic::SCommand *>
+ m_CustomerMaterialCommands; ///< our command stream used for rendering
+ bool m_HasTransparency; ///< this material is transparent
+ bool m_HasRefraction; ///< this material is refractive (e.g glass)
+ bool m_AlwaysDirty;
+ QT3DSU32 m_ShaderKey; ///< What does this shader contain ( e.g. specular, diffuse, ...)
+ QT3DSU32 m_LayerCount; ///< How much layers does this material have
+
+ void ClearEffectCommands()
+ {
+ for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx) {
+ free(m_CustomerMaterialCommands[idx]);
+ }
+
+ m_CustomerMaterialCommands.clear();
+ }
+
+ SMetaDataCustomMaterial ToMaterial() const
+ {
+ return SMetaDataCustomMaterial(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties),
+ VecToCRef(m_CustomerMaterialCommands), m_HasTransparency,
+ m_HasRefraction, m_AlwaysDirty, m_ShaderKey, m_LayerCount);
+ }
+};
+
+struct SNewMetaDataImpl : public IMetaData
+{
+ typedef unordered_map<TCharPtr, TInstanceHandle> TStrInstanceMap;
+ typedef unordered_map<TInstanceHandle, TCharPtr, hash<int>> TInstanceStrMap;
+ // Caching the derivation chain lookup so we can quickly lookup the entire list of
+ // derived instances (and have it ordered, somewhat).
+ typedef unordered_map<vector<TInstanceHandle>, vector<TInstanceHandle>, InstanceHandleVecHash>
+ TDerivationMap;
+
+ typedef unordered_map<TCategoryHandle, SCategoryInfo, hash<int>> TCategoryMap;
+ typedef unordered_map<TCharPtr, TCategoryHandle> TNameCategoryMap;
+
+ typedef unordered_map<TMetaDataPropertyHandle, SMetaDataPropertyInfo, hash<int>>
+ TMetaDataPropertyMap;
+ typedef unordered_map<TInstanceHandle, vector<TMetaDataPropertyHandle>, hash<int>>
+ TInstancePropertyMap;
+ typedef unordered_map<pair<TInstanceHandle, TCharPtr>, TMetaDataPropertyHandle,
+ SInstanceStrHash>
+ TInstancePropertyNamePropertyMap;
+ typedef unordered_map<TMetaDataPropertyHandle, eastl::vector<SPropertyFilterInfo>, hash<int>>
+ TMetaDataPropertyFilterMap;
+ typedef unordered_map<TInstanceHandle, vector<TCharPtr>, hash<int>> TInstanceGroupMap;
+
+ typedef unordered_map<TEventHandle, SEvent, hash<int>> TEventMap;
+ typedef unordered_map<TInstanceHandle, vector<TEventHandle>, hash<int>> TInstanceEventMap;
+ typedef unordered_map<pair<TInstanceHandle, TCharPtr>, TEventHandle, SInstanceStrHash>
+ TInstanceEventNameEventMap;
+
+ typedef unordered_map<THandlerHandle, SHandler, hash<int>> THandlerMap;
+ typedef unordered_map<TInstanceHandle, vector<THandlerHandle>, hash<int>> TInstanceHandlerMap;
+ typedef unordered_map<pair<TInstanceHandle, TCharPtr>, THandlerHandle, SInstanceStrHash>
+ TInstanceHandlerNameHandlerMap;
+
+ typedef unordered_map<TInstanceHandle, vector<TCharPtr>, hash<int>> TInstanceStringListMap;
+ typedef unordered_map<TCharPtr, SMetaDataEffectImpl> TEffectMap;
+ typedef unordered_map<TCharPtr, SMetaDataCustomMaterialImpl> TCustomMaterialMap;
+
+ std::shared_ptr<IDataCore> m_DataCore;
+ IStringTable &m_StringTable;
+ TTransactionConsumerPtr m_Consumer;
+
+ int m_NextId;
+
+ // Helper objects to speed up queries
+ TStrInstanceMap m_CanonicalTypeToInstances;
+ TInstanceStrMap m_InstancesToCanonicalType;
+ TDerivationMap m_DerivationMap;
+
+ TCategoryMap m_Categories;
+ TNameCategoryMap m_NameToCategories;
+
+ TMetaDataPropertyMap m_Properties;
+ TInstancePropertyMap m_InstanceToProperties;
+ TInstancePropertyNamePropertyMap m_InstanceNameToProperties;
+ TMetaDataPropertyFilterMap m_PropertyFilters;
+ TInstanceGroupMap m_InstanceGroupMap;
+
+ TEventMap m_Events;
+ TInstanceEventMap m_InstanceToEvents;
+ TInstanceEventNameEventMap m_InstanceNameToEvents;
+
+ THandlerMap m_Handlers;
+ TInstanceHandlerMap m_InstanceToHandlers;
+ TInstanceHandlerNameHandlerMap m_InstanceNameToHandlers;
+
+ TInstanceStringListMap m_InstanceToReferences;
+
+ vector<TInstanceHandle> m_Parents;
+ vector<TInstanceHandle> m_NextParents;
+ vector<TInstanceHandle> m_DerivationChain;
+ unordered_set<int> m_UniqueSet;
+ unordered_set<size_t> m_SizeTSet;
+
+ MemoryBuffer<RawAllocator> m_TempBuffer;
+ MemoryBuffer<RawAllocator> m_ReadBuffer;
+
+ eastl::string m_ConvertStr;
+
+ TCharStr m_ObjectName;
+
+ TEffectMap m_EffectMap;
+ TCustomMaterialMap m_CustomMaterials;
+
+#ifndef UICDM_META_DATA_NO_SIGNALS
+
+ boost::signal<void(CUICDMCategoryHandle)> m_InternalCategoryDestroyed;
+ boost::signal<void(CUICDMMetaDataPropertyHandle)> m_InternalMetaDataPropertyDestroyed;
+ boost::signal<void(CUICDMEventHandle)> m_InternalEventDestroyed;
+ boost::signal<void(CUICDMHandlerHandle)> m_InternalHandlerDestroyed;
+ boost::signal<void(CUICDMHandlerHandle, QT3DSU32)> m_InternalHandlerArgDestroyed;
+#else
+ SNullFunc m_InternalCategoryDestroyed;
+ SNullFunc m_InternalMetaDataPropertyDestroyed;
+ SNullFunc m_InternalEventDestroyed;
+ SNullFunc m_InternalHandlerDestroyed;
+ SNullFunc m_InternalHandlerArgDestroyed;
+#endif
+
+ TSignalConnectionPtr m_PropertyDeletedConnection;
+ bool m_IgnorePropertyDeleted;
+ TSignalConnectionPtr m_InstanceDeletedConnection;
+
+ SNewMetaDataImpl(std::shared_ptr<IDataCore> inDataCore)
+ : m_DataCore(inDataCore)
+ , m_StringTable(inDataCore->GetStringTable())
+ , m_NextId(1)
+ , m_IgnorePropertyDeleted(false)
+ {
+#ifndef UICDM_META_DATA_NO_SIGNALS
+ CDataCoreProducer *producer = dynamic_cast<CDataCoreProducer *>(inDataCore.get());
+ if (producer) {
+ m_PropertyDeletedConnection = producer->ConnectPropertyRemoved(
+ bind(&SNewMetaDataImpl::OnPropertyRemoved, this,
+ std::placeholders::_1, std::placeholders::_2));
+ m_InstanceDeletedConnection = producer->ConnectBeforeInstanceDeleted(
+ bind(&SNewMetaDataImpl::OnInstanceRemoved, this,
+ std::placeholders::_1));
+ }
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Helper Functions
+
+ const wchar_t *Intern(TStrType inData) { return m_StringTable.RegisterStr(inData.wide_str()); }
+ const wchar_t *Intern(const char *inData) { return m_StringTable.GetWideStr(inData); }
+
+ inline int GetNextId()
+ {
+ int retval = m_NextId;
+ ++m_NextId;
+ return retval;
+ }
+
+ template <typename TMapType, typename THandleType>
+ static void AddItemToInstanceList(TInstanceHandle inInstance, THandleType inHandle, QT3DSU32 inIdx,
+ TMapType &ioMap)
+ {
+ pair<typename TMapType::iterator, bool> inserter =
+ ioMap.insert(make_pair(inInstance, vector<THandleType>()));
+ inserter.first->second.insert(inserter.first->second.begin() + inIdx, inHandle);
+ }
+
+ template <typename TMapType, typename THandleType>
+ static QT3DSU32 AddItemToInstanceList(TInstanceHandle inInstance, THandleType inHandle,
+ TMapType &ioMap)
+ {
+ pair<typename TMapType::iterator, bool> inserter =
+ ioMap.insert(make_pair(inInstance, vector<THandleType>()));
+ QT3DSU32 offset = (QT3DSU32)inserter.first->second.size();
+ inserter.first->second.push_back(inHandle);
+ return offset;
+ }
+
+ template <typename TItemType>
+ struct VectorEqualPred
+ {
+ TItemType m_Item;
+ VectorEqualPred(const TItemType &inItem)
+ : m_Item(inItem)
+ {
+ }
+
+ bool operator()(const TItemType &inOther) const { return m_Item == inOther; }
+ };
+
+ template <typename THandleType, typename TMapType>
+ static QT3DSU32 DoRemoveItemFromInstanceList(TInstanceHandle inInstance, THandleType inHandle,
+ TMapType &ioMap)
+ {
+ typename TMapType::iterator find = ioMap.find(inInstance);
+ if (find != ioMap.end()) {
+ typename vector<THandleType>::iterator theVecFind =
+ std::find(find->second.begin(), find->second.end(), inHandle);
+ if (theVecFind != find->second.end()) {
+ QT3DSU32 retval = (QT3DSU32)(theVecFind - find->second.begin());
+ find->second.erase(theVecFind);
+ if (find->second.empty())
+ ioMap.erase(find);
+ return retval;
+ }
+ }
+ QT3DS_ASSERT(false);
+ return QT3DS_MAX_U32;
+ }
+
+ template <typename TMapType, typename THandleType>
+ struct InstanceListTransaction : ITransaction
+ {
+ TInstanceHandle m_Instance;
+ THandleType m_Handle;
+ TMapType &m_Map;
+ QT3DSU32 m_Idx;
+ bool m_InsertOnDo;
+
+ InstanceListTransaction(const char *inFile, int inLine, TInstanceHandle inst,
+ THandleType handle, TMapType &map, QT3DSU32 inIdx, bool inInsertOnDo)
+ : ITransaction(inFile, inLine)
+ , m_Instance(inst)
+ , m_Handle(handle)
+ , m_Map(map)
+ , m_Idx(inIdx)
+ , m_InsertOnDo(inInsertOnDo)
+ {
+ }
+
+ void insert()
+ {
+ SNewMetaDataImpl::AddItemToInstanceList(m_Instance, m_Handle, m_Idx, m_Map);
+ }
+ void remove()
+ {
+ SNewMetaDataImpl::DoRemoveItemFromInstanceList(m_Instance, m_Handle, m_Map);
+ }
+
+ void Do() override
+ {
+ if (m_InsertOnDo)
+ insert();
+ else
+ remove();
+ }
+ void Undo() override
+ {
+ if (m_InsertOnDo)
+ remove();
+ else
+ insert();
+ }
+ };
+
+ template <typename THandleType, typename TMapType>
+ void RemoveItemFromInstanceList(const char *inFile, int inLine, TInstanceHandle inInstance,
+ THandleType inHandle, TMapType &ioMap)
+ {
+ typename TMapType::iterator find = ioMap.find(inInstance);
+ if (find != ioMap.end()) {
+ QT3DSU32 idx = DoRemoveItemFromInstanceList(inInstance, inHandle, ioMap);
+ if (m_Consumer != NULL) {
+ m_Consumer->OnTransaction(
+ std::make_shared<InstanceListTransaction<TMapType, THandleType>>(
+ inFile, inLine, inInstance, inHandle, std::ref(ioMap), idx, false));
+ }
+ }
+ }
+
+ template <typename THandleType, typename TValueType, typename TMapType,
+ typename TInstanceListMapType>
+ THandleType CreateItem(const char *inFile, int inLine, CUICDMInstanceHandle inInstance,
+ TMapType &inMap, TInstanceListMapType &inInstanceListMap)
+ {
+ int retval = GetNextId();
+ pair<THandleType, TValueType> thePair(make_pair(retval, TValueType(inInstance)));
+ inMap.insert(thePair);
+ QT3DSU32 idx = AddItemToInstanceList(inInstance, THandleType(retval), inInstanceListMap);
+ if (m_Consumer) {
+ CreateHashMapInsertTransaction(inFile, inLine, m_Consumer, thePair, inMap);
+ m_Consumer->OnTransaction(
+ std::make_shared<InstanceListTransaction<TInstanceListMapType, THandleType>>(
+ inFile, inLine, inInstance, retval, std::ref(inInstanceListMap), idx, true));
+ }
+ return retval;
+ }
+
+ template <typename TKeyType, typename TValueType, typename THashType>
+ TValueType *FindHashItem(TKeyType inHandle,
+ unordered_map<TKeyType, TValueType, THashType> &ioHash)
+ {
+ typename unordered_map<TKeyType, TValueType, THashType>::iterator find =
+ ioHash.find(inHandle);
+ if (find != ioHash.end())
+ return &find->second;
+ return NULL;
+ }
+
+ template <typename THandleType, typename TMapType>
+ static void DoReplaceNamedItem(TInstanceHandle inInst, TCharPtr inOldName, TCharPtr inNewName,
+ THandleType inNewHandle, TMapType &ioMap)
+ {
+ ioMap.erase(make_pair(inInst, inOldName));
+ bool success = ioMap.insert(make_pair(make_pair(inInst, inNewName), inNewHandle)).second;
+ (void)success;
+ QT3DS_ASSERT(success);
+ }
+
+ template <typename TMapType, typename THandleType>
+ struct ReplaceNamedItemTransaction : ITransaction
+ {
+ TInstanceHandle m_Instance;
+ TCharPtr m_OldName;
+ TCharPtr m_NewName;
+ THandleType m_OldHandle;
+ THandleType m_NewHandle;
+ TMapType &m_Map;
+ ReplaceNamedItemTransaction(const char *inFile, int inLine, TInstanceHandle inst,
+ TCharPtr oldNm, TCharPtr newNm, THandleType oldHdl,
+ THandleType newHdl, TMapType &map)
+ : ITransaction(inFile, inLine)
+ , m_Instance(inst)
+ , m_OldName(oldNm)
+ , m_NewName(newNm)
+ , m_OldHandle(oldHdl)
+ , m_NewHandle(newHdl)
+ , m_Map(map)
+ {
+ }
+ void Do() override
+ {
+ SNewMetaDataImpl::DoReplaceNamedItem(m_Instance, m_OldName, m_NewName, m_NewHandle,
+ m_Map);
+ }
+ void Undo() override
+ {
+ SNewMetaDataImpl::DoReplaceNamedItem(m_Instance, m_NewName, m_OldName, m_OldHandle,
+ m_Map);
+ }
+ };
+
+ template <typename THandleType, typename TMapType>
+ void ReplaceNamedItem(const char *inFile, int inLine, TInstanceHandle inInst,
+ TCharPtr inOldName, TCharPtr inNewName, THandleType inNewHandle,
+ TMapType &ioMap)
+ {
+ typename TMapType::iterator find = ioMap.find(std::make_pair(inInst, inOldName));
+ THandleType oldHandle;
+ if (find != ioMap.end())
+ oldHandle = find->second;
+ DoReplaceNamedItem(inInst, inOldName, inNewName, inNewHandle, ioMap);
+ if (m_Consumer) {
+ if (oldHandle.Valid()) {
+ m_Consumer->OnTransaction(
+ std::make_shared<ReplaceNamedItemTransaction<TMapType, THandleType>>(
+ inFile, inLine, inInst, inOldName, inNewName, oldHandle, inNewHandle,
+ std::ref(ioMap)));
+ } else
+ CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer,
+ make_pair(make_pair(inInst, inNewName), inNewHandle),
+ ioMap);
+ }
+ }
+
+ template <typename THandleType, typename TMapType>
+ void DestroyNamedItem(const char *inFile, int inLine, TInstanceHandle inInst, TCharPtr inName,
+ TMapType &ioMap)
+ {
+ typename TMapType::iterator iter = ioMap.find(make_pair(inInst, inName));
+ if (iter != ioMap.end()) {
+ pair<pair<TInstanceHandle, TCharPtr>, THandleType> existing(*iter);
+ ioMap.erase(iter);
+ CreateHashMapEraseTransaction(inFile, inLine, m_Consumer, existing, ioMap);
+ }
+ }
+
+ template <typename THandleType, typename TInfoType, typename TMapType, typename TNamedMapType>
+ void SetItemInfo(const char *inFile, int inLine, THandleType inItem, const TInfoType &oldInfo,
+ const TInfoType &newInfo, TMapType &inMap, TNamedMapType &inNamedMap)
+ {
+ TCharPtr newName = Intern(newInfo.m_Name.wide_str());
+ TCharPtr oldName = Intern(oldInfo.m_Name.wide_str());
+ ReplaceNamedItem(inFile, inLine, newInfo.m_Instance, oldName, newName, inItem, inNamedMap);
+ CreateHashMapSwapTransaction(inFile, inLine, m_Consumer, inItem, oldInfo, newInfo, inMap);
+ }
+
+ bool AddDerivationChainItem(TInstanceHandle inInst)
+ {
+ if (m_UniqueSet.find(inInst) == m_UniqueSet.end()) {
+ m_DerivationChain.push_back(inInst);
+ m_UniqueSet.insert(inInst);
+ return true;
+ }
+ return false;
+ }
+
+ void GetDerivationChain(TInstanceHandle inInst)
+ {
+ m_Parents.clear();
+ m_DerivationChain.clear();
+ m_UniqueSet.clear();
+ m_NextParents.clear();
+ m_DataCore->GetInstanceParents(inInst, m_Parents);
+
+ TDerivationMap::iterator mapIter = m_DerivationMap.find(m_Parents);
+ if (mapIter != m_DerivationMap.end())
+ m_DerivationChain = mapIter->second;
+ else {
+ while (m_Parents.empty() == false) {
+ for (size_t idx = 0, end = m_Parents.size(); idx < end; ++idx) {
+ if (AddDerivationChainItem(m_Parents[idx]))
+ m_DataCore->GetInstanceParents(m_Parents[idx], m_NextParents);
+ }
+ m_Parents = m_NextParents;
+ m_NextParents.clear();
+ }
+ m_NextParents.clear();
+
+ m_DataCore->GetInstanceParents(inInst, m_NextParents);
+ m_DerivationMap.insert(make_pair(m_NextParents, m_DerivationChain));
+ }
+ }
+
+ template <typename THandleType, typename TMapType>
+ THandleType FindItemByName(TInstanceHandle inInst, TCharPtr inName, TMapType &ioMap)
+ {
+ typename TMapType::iterator find(ioMap.find(make_pair(inInst, inName)));
+ if (find != ioMap.end())
+ return find->second;
+
+ GetDerivationChain(inInst);
+ for (size_t idx = 0, end = m_DerivationChain.size(); idx < end; ++idx) {
+ find = ioMap.find(make_pair(m_DerivationChain[idx], inName));
+ if (find != ioMap.end())
+ return find->second;
+ }
+ return 0;
+ }
+
+ template <typename TItemType, typename TVectorType>
+ void AddListMapItems(const std::vector<TItemType> &inMapEntry, TVectorType &outVector)
+ {
+ typedef typename std::vector<TItemType>::const_iterator TIterType;
+ for (TIterType theIter = inMapEntry.begin(), theEnd = inMapEntry.end(); theIter != theEnd;
+ ++theIter)
+ outVector.push_back(*theIter);
+ }
+
+ template <typename TListMapType, typename TSizeTOpType, typename TVectorType>
+ void DoGetHandleList(CUICDMInstanceHandle inInstance, TListMapType &inMap,
+ TVectorType &outHandles, TSizeTOpType inOperator)
+ {
+ typename TListMapType::iterator find;
+ GetDerivationChain(inInstance);
+ for (size_t idx = 0, end = m_DerivationChain.size(); idx < end; ++idx) {
+ // Add base classes to the list first
+ find = inMap.find(m_DerivationChain[end - idx - 1]);
+ if (find != inMap.end()) {
+ AddListMapItems(find->second, outHandles);
+ }
+ }
+ find = inMap.find(inInstance);
+ if (find != inMap.end()) {
+ AddListMapItems(find->second, outHandles);
+ }
+ m_SizeTSet.clear();
+ for (size_t ridx = 0; ridx < outHandles.size(); ++ridx) {
+ size_t idx = outHandles.size() - ridx - 1;
+ // Run through the list backwards, making sure that items further in the list
+ // completely overshadow items earlier in the list.
+
+ // Create unique key from the item that we can check against
+ size_t item = inOperator(outHandles[idx]);
+ if (m_SizeTSet.insert(item).second == false) {
+ outHandles.erase(outHandles.begin() + idx);
+ --ridx;
+ }
+ }
+ }
+
+ template <typename THandleType, typename TMapType>
+ struct NameSizeTOpType
+ {
+ SNewMetaDataImpl &m_Impl;
+ TMapType &m_Map;
+ NameSizeTOpType(SNewMetaDataImpl &inImpl, TMapType &inMap)
+ : m_Impl(inImpl)
+ , m_Map(inMap)
+ {
+ }
+
+ size_t operator()(THandleType inHandle)
+ {
+ return reinterpret_cast<size_t>(m_Impl.Intern(m_Map[inHandle].m_Name));
+ }
+ };
+
+ // Ensure we don't return two items of the same name.
+ template <typename THandleType, typename TListMapType, typename TMapType>
+ void GetHandleList(CUICDMInstanceHandle inInstance, TListMapType &inMap, TMapType &inTypeName,
+ vector<THandleType> &outHandles)
+ {
+ DoGetHandleList(inInstance, inMap, outHandles,
+ NameSizeTOpType<THandleType, TMapType>(*this, inTypeName));
+ }
+
+ template <typename THandleType, typename TSignalType, typename TMapType, typename TNameMapType,
+ typename TListMapType>
+ void DestroyItem(const char *inFile, int inLine, THandleType inItem, TSignalType &inSignal,
+ TMapType &inMap, TNameMapType &inNameMap, TListMapType &inListMap)
+ {
+ typename TMapType::iterator find(inMap.find(inItem));
+ if (find == inMap.end()) {
+ return;
+ }
+ inSignal(inItem);
+
+ DestroyNamedItem<THandleType>(inFile, inLine, find->second.m_Instance,
+ Intern(find->second.m_Name.wide_str()), inNameMap);
+ RemoveItemFromInstanceList(inFile, inLine, find->second.m_Instance, inItem, inListMap);
+ CreateHashMapEraseTransaction(inFile, inLine, m_Consumer,
+ make_pair(find->first, find->second), inMap);
+ inMap.erase(find);
+ }
+
+ template <typename THandleType, typename TListMapType>
+ void ForEachItem(CUICDMInstanceHandle inInstance, TListMapType &ioMap,
+ function<void(THandleType)> inOperation)
+ {
+ typename TListMapType::iterator find = ioMap.find(inInstance);
+ if (find != ioMap.end()) {
+ vector<THandleType> itemData(find->second);
+ for (size_t idx = 0, end = itemData.size(); idx < end; ++idx)
+ inOperation(itemData[idx]);
+ }
+ }
+
+ SCategoryInfo *FindCategory(CUICDMCategoryHandle inCategory)
+ {
+ return FindHashItem(inCategory, m_Categories);
+ }
+
+ SMetaDataPropertyInfo *FindProperty(CUICDMMetaDataPropertyHandle inPropertyHandle)
+ {
+ return FindHashItem(inPropertyHandle, m_Properties);
+ }
+
+ SEvent *FindEvent(CUICDMEventHandle inEventHandle)
+ {
+ return FindHashItem(inEventHandle, m_Events);
+ }
+
+ SHandler *FindHandler(CUICDMHandlerHandle inHandle)
+ {
+ return FindHashItem(inHandle, m_Handlers);
+ }
+
+ SMetaDataHandlerArgumentInfo *FindHandlerArg(CUICDMHandlerHandle inHandler, QT3DSU32 inIdx)
+ {
+ SHandler *theHandler(FindHandler(inHandler));
+ if (theHandler && theHandler->m_Arguments.size() > inIdx)
+ return &theHandler->m_Arguments[inIdx];
+ return NULL;
+ }
+
+ void OnPropertyRemoved(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty)
+ {
+ if (m_IgnorePropertyDeleted)
+ return;
+
+ vector<CUICDMMetaDataPropertyHandle> propertiesToDestroy;
+ for (TMetaDataPropertyMap::iterator iter = m_Properties.begin(), end = m_Properties.end();
+ iter != end; ++iter) {
+ if (iter->second.m_Property == inProperty)
+ propertiesToDestroy.push_back(iter->first);
+ }
+
+ for (size_t idx = 0, end = propertiesToDestroy.size(); idx < end; ++idx)
+ DestroyMetaDataProperty(propertiesToDestroy[idx]);
+ }
+
+ void OnInstanceRemoved(CUICDMInstanceHandle inInstance) { DestroyMetaData(inInstance); }
+ template <typename TEntryType, typename TMapType>
+ void InsertWithTransaction(const char *inFile, int inLine, const TEntryType &inEntry,
+ TMapType &inMap)
+ {
+ inMap.insert(inEntry);
+ CreateHashMapInsertTransaction(inFile, inLine, m_Consumer, inEntry, inMap);
+ }
+
+ template <typename TKeyType, typename TMapType>
+ void EraseWithTransaction(const char *inFile, int inLine, TKeyType inKey, TMapType &inMap)
+ {
+ typename TMapType::iterator find(inMap.find(inKey));
+ if (find != inMap.end()) {
+ CreateHashMapEraseTransaction(inFile, inLine, m_Consumer,
+ std::make_pair(find->first, find->second), inMap);
+ inMap.erase(find);
+ }
+ }
+
+ template <typename TEntryType, typename TMapType>
+ void InsertOrUpdateWithTransaction(const TEntryType &inEntry, TMapType &inMap)
+ {
+ pair<typename TMapType::iterator, bool> inserter = inMap.insert(inEntry);
+ if (inserter.second)
+ CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer, inEntry, inMap);
+ else {
+ typename TMapType::iterator theIter(inserter.first);
+ CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, theIter->first,
+ theIter->second, inEntry.second, inMap);
+ theIter->second = inEntry.second;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // API Implementation
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Sharing some utility objects
+ IStringTable &GetStringTable() override { return m_DataCore->GetStringTable(); }
+ TStringTablePtr GetStringTablePtr() override { return m_DataCore->GetStringTablePtr(); }
+ TDataCorePtr GetDataCore() override { return m_DataCore; }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Canonical Instances
+ void SetInstanceAsCanonical(CUICDMInstanceHandle inInstance, TStrType inTypename) override
+ {
+ const wchar_t *theTypename(Intern(inTypename));
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger("IMetaData::SetInstanceAsCanonical Enter");
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger(GetStringTable().GetNarrowStr(inTypename.wide_str()));
+ m_CanonicalTypeToInstances.insert(make_pair(theTypename, inInstance));
+ m_InstancesToCanonicalType.insert(make_pair(inInstance, theTypename));
+ CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer,
+ make_pair(theTypename, inInstance),
+ m_CanonicalTypeToInstances);
+ CreateHashMapInsertTransaction(__FILE__, __LINE__, m_Consumer,
+ make_pair(inInstance, theTypename),
+ m_InstancesToCanonicalType);
+ if (g_UICDMDebugLogger)
+ g_UICDMDebugLogger("IMetaData::SetInstanceAsCanonical Leave");
+ }
+
+ CUICDMInstanceHandle GetCanonicalInstanceForType(TStrType inTypename) override
+ {
+ TStrInstanceMap::iterator find = m_CanonicalTypeToInstances.find(Intern(inTypename));
+ if (find != m_CanonicalTypeToInstances.end())
+ return find->second;
+ return 0;
+ }
+
+ Option<TCharStr> GetTypeForCanonicalInstance(CUICDMInstanceHandle inInstance) override
+ {
+ TInstanceStrMap::iterator find = m_InstancesToCanonicalType.find(inInstance);
+ if (find != m_InstancesToCanonicalType.end())
+ return TCharStr(find->second);
+ return Empty();
+ }
+
+ Option<TCharStr> GetTypeForInstance(CUICDMInstanceHandle inInstance) override
+ {
+ Option<TCharStr> theType = GetTypeForCanonicalInstance(inInstance);
+ if (theType.hasValue())
+ return theType;
+ GetDerivationChain(inInstance);
+ for (size_t idx = 0, end = m_DerivationChain.size(); idx < end; ++idx) {
+ theType = GetTypeForCanonicalInstance(m_DerivationChain[idx]);
+ if (theType.hasValue())
+ return theType;
+ }
+ return Empty();
+ }
+
+ QT3DSU32 GetGroupCountForInstance(CUICDMInstanceHandle inInstance) override
+ {
+ std::vector<TCharStr> outNames;
+ QT3DSU32 count = GetGroupNamesForInstance(inInstance, outNames);
+ return (count == 0) ? 1 : count;
+ }
+
+ QT3DSU32 GetGroupNamesForInstance(CUICDMInstanceHandle inInstance,
+ std::vector<TCharStr> &outNames) override
+ {
+ TInstanceStrMap::iterator canonicalFind = m_InstancesToCanonicalType.find(inInstance);
+ if (canonicalFind != m_InstancesToCanonicalType.end()) {
+ TInstanceGroupMap::iterator find = m_InstanceGroupMap.find(inInstance);
+ if (find != m_InstanceGroupMap.end()) {
+ pair<typename TInstanceGroupMap::iterator, bool> inserter =
+ m_InstanceGroupMap.insert(make_pair(inInstance, vector<TCharPtr>()));
+ vector<TCharPtr> &itemList = inserter.first->second;
+ for (size_t i = 0, j = itemList.size(); i < j; ++i) {
+ bool alreadyInList = false;
+ // discard duplicates
+ for (size_t k = 0, l = outNames.size(); k < l; ++k) {
+ TCharStr curListName = itemList[i];
+ if (curListName == outNames[k].wide_str()) {
+ alreadyInList = true;
+ break;
+ }
+ }
+ if (!alreadyInList)
+ outNames.push_back(itemList[i]);
+ }
+ }
+ return (QT3DSU32)outNames.size();
+ }
+
+ GetDerivationChain(inInstance);
+
+ for (int idx = (int)m_DerivationChain.size() - 1, end = 0; idx >= end; --idx) {
+ TInstanceGroupMap::iterator find = m_InstanceGroupMap.find(m_DerivationChain[idx]);
+ if (find != m_InstanceGroupMap.end()) {
+ pair<typename TInstanceGroupMap::iterator, bool> inserter =
+ m_InstanceGroupMap.insert(
+ make_pair(m_DerivationChain[idx], vector<TCharPtr>()));
+ vector<TCharPtr> &itemList = inserter.first->second;
+ for (size_t i = 0, j = itemList.size(); i < j; ++i) {
+ bool alreadyInList = false;
+ // discard duplicates
+ for (size_t k = 0, l = outNames.size(); k < l; ++k) {
+ TCharStr curListName = itemList[i];
+ if (curListName == outNames[k].wide_str()) {
+ alreadyInList = true;
+ break;
+ }
+ }
+ if (!alreadyInList)
+ outNames.push_back(itemList[i]);
+ }
+ }
+ }
+
+ return (QT3DSU32)outNames.size();
+ }
+
+ Option<TCharStr> GetGroupFilterNameForInstance(CUICDMInstanceHandle inInstance,
+ long inIndex) override
+ {
+ std::vector<TCharStr> outNames;
+ QT3DSU32 count = GetGroupNamesForInstance(inInstance, outNames);
+ if (count > (QT3DSU32)inIndex)
+ return outNames[inIndex];
+
+ return Empty();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Categories
+
+ std::pair<CUICDMCategoryHandle, bool> GetOrCreateCategory(TStrType inName) override
+ {
+ TCharPtr theName(Intern(inName));
+ TNameCategoryMap::iterator find = m_NameToCategories.find(theName);
+ if (find != m_NameToCategories.end())
+ return make_pair(find->second, false);
+
+ TCategoryHandle retval(GetNextId());
+ InsertWithTransaction(__FILE__, __LINE__, make_pair(retval, SCategoryInfo(inName)),
+ m_Categories);
+ InsertWithTransaction(__FILE__, __LINE__, make_pair(theName, retval), m_NameToCategories);
+ return make_pair(retval, true);
+ }
+
+ void SetCategoryInfo(CUICDMCategoryHandle inCategory, TStrType inIcon,
+ TStrType inHighlight, TStrType inDescription) override
+ {
+ SCategoryInfo *infoPtr(FindCategory(inCategory));
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SCategoryInfo &newInfo(*infoPtr);
+ SCategoryInfo oldInfo(newInfo);
+
+ newInfo.m_Icon = inIcon;
+ newInfo.m_HighlightIcon = inHighlight;
+ newInfo.m_Description = inDescription;
+ CreateHashMapSwapTransaction(__FILE__, __LINE__, m_Consumer, inCategory, oldInfo, newInfo,
+ m_Categories);
+ }
+
+ void DestroyCategory(CUICDMCategoryHandle inCategory) override
+ {
+ SCategoryInfo *infoPtr(FindCategory(inCategory));
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ EraseWithTransaction(__FILE__, __LINE__, Intern(infoPtr->m_Name), m_NameToCategories);
+ EraseWithTransaction(__FILE__, __LINE__, inCategory, m_Categories);
+ }
+ Option<SCategoryInfo> GetCategoryInfo(CUICDMCategoryHandle inCategory) override
+ {
+ SCategoryInfo *infoPtr(FindCategory(inCategory));
+ if (infoPtr)
+ return *infoPtr;
+ return Empty();
+ }
+ CUICDMCategoryHandle FindCategoryByName(TStrType inName) override
+ {
+ TCharPtr theName(Intern(inName));
+ TNameCategoryMap::iterator find = m_NameToCategories.find(theName);
+ if (find != m_NameToCategories.end())
+ return find->second;
+ return 0;
+ }
+
+ void GetCategories(vector<CUICDMCategoryHandle> &outCategories) override
+ {
+ for (TCategoryMap::iterator iter = m_Categories.begin(), end = m_Categories.end();
+ iter != end; ++iter)
+ outCategories.push_back(iter->first);
+ }
+
+ Option<SCategoryInfo> GetEventCategory(TStrType inName) override
+ {
+ return GetCategoryInfo(FindCategoryByName(inName));
+ }
+
+ Option<SCategoryInfo> GetHandlerCategory(TStrType inName) override
+ {
+ return GetCategoryInfo(FindCategoryByName(inName));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Properties
+
+ CUICDMMetaDataPropertyHandle CreateMetaDataProperty(CUICDMInstanceHandle inInstance) override
+ {
+ return CreateItem<CUICDMMetaDataPropertyHandle, SMetaDataPropertyInfo>(
+ __FILE__, __LINE__, inInstance, m_Properties, m_InstanceToProperties);
+ }
+
+ void EnsureDataCoreProperty(SMetaDataPropertyInfo &newInfo)
+ {
+ m_IgnorePropertyDeleted = true;
+ // If the existing property under the new name doesn't match
+ // the new info, then we also have to delete the property
+ CUICDMPropertyHandle theExistingProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(newInfo.m_Instance, newInfo.m_Name);
+ // Ensure the types match.
+ if (theExistingProperty.Valid()) {
+ SUICDMPropertyDefinition theDefinition(m_DataCore->GetProperty(theExistingProperty));
+ if (theDefinition.m_Name != newInfo.m_Name
+ || theDefinition.m_Type != newInfo.GetDataType()) {
+ m_DataCore->RemoveProperty(theExistingProperty);
+ theExistingProperty = 0;
+ }
+ }
+
+ // Finally, if we don't have a property at this point, create a new property
+ if (theExistingProperty.Valid() == false)
+ theExistingProperty = m_DataCore->AddProperty(
+ newInfo.m_Instance, newInfo.m_Name.wide_str(), newInfo.GetDataType());
+ newInfo.m_Property = theExistingProperty;
+ m_IgnorePropertyDeleted = false;
+ }
+
+ // If the type doesn't match the default, then it has no default.
+ SValue VerifyDefaultPropertyType(DataModelDataType::Value inDataType, const SValue &inValue)
+ {
+ if (inValue.empty() == false) {
+ DataModelDataType::Value theType = GetValueType(inValue);
+ if (theType != inDataType) {
+ return SValue(0.0f);
+ }
+ }
+ return inValue;
+ }
+ // If the datatype doesn't match the value, force the value to match the type.
+ // some types *have* to have values.
+ TMetaDataData VerifyMetaDataDataType(AdditionalMetaDataType::Value inDataType,
+ const TMetaDataData &inValue)
+ {
+ if (inDataType == AdditionalMetaDataType::StringList
+ || inDataType == AdditionalMetaDataType::Range) {
+ if (inValue.empty() == true || inDataType != GetMetaDataValueType(inValue)) {
+ QT3DS_ASSERT(false);
+ if (inDataType == AdditionalMetaDataType::StringList)
+ return TMetaDataStringList();
+ if (inDataType == AdditionalMetaDataType::Range)
+ return SMetaDataRange(0, 1);
+ }
+ }
+ return inValue;
+ }
+
+ void SetPropertyBaseInfo(SMetaPropertyBase &newInfo, TStrType inName, TStrType inFormalName,
+ TStrType inDescription, TStrType inUsage,
+ CompleteMetaDataType::Enum inDataType, const SValue &inDefaultValue,
+ const TMetaDataData &inMetaData)
+ {
+ newInfo.m_Name = inName;
+ newInfo.m_FormalName = inFormalName;
+ newInfo.m_Description = inDescription;
+ newInfo.m_Usage = inUsage;
+ newInfo.m_CompleteType = inDataType;
+ newInfo.m_DefaultValue =
+ VerifyDefaultPropertyType(CompleteMetaDataType::ToDataType(inDataType), inDefaultValue);
+ newInfo.m_MetaDataData =
+ VerifyMetaDataDataType(CompleteMetaDataType::ToAdditionalType(inDataType), inMetaData);
+ }
+
+ // For properties, you set the default values separately
+ // This may delete the underlying data model property rebuild it.
+ void SetMetaDataPropertyInfo(CUICDMMetaDataPropertyHandle inPropertyHandle,
+ TStrType inName, TStrType inFormalName,
+ TStrType inDescription, TStrType inUsage,
+ CompleteMetaDataType::Enum inDataType,
+ const SValue &inDefaultValue,
+ const TMetaDataData &inMetaData, TStrType inGroupName,
+ bool inIsHidden, bool inIsAnimatable) override
+ {
+ SMetaDataPropertyInfo *infoPtr = FindProperty(inPropertyHandle);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SMetaDataPropertyInfo &newInfo(*infoPtr);
+ SMetaDataPropertyInfo oldInfo(newInfo);
+
+ SetPropertyBaseInfo(newInfo, inName, inFormalName, inDescription, inUsage, inDataType,
+ inDefaultValue, inMetaData);
+ newInfo.m_IsHidden = inIsHidden;
+ newInfo.m_Animatable = inIsAnimatable;
+ newInfo.m_GroupName = inGroupName;
+ EnsureDataCoreProperty(newInfo);
+
+ SetItemInfo(__FILE__, __LINE__, inPropertyHandle, oldInfo, newInfo, m_Properties,
+ m_InstanceNameToProperties);
+
+ SetPropertyDefault(newInfo, CompleteMetaDataType::ToDataType(inDataType));
+ }
+
+ void SetPropertyDefault(SMetaDataPropertyInfo &newInfo, DataModelDataType::Value inDataType)
+ {
+ if (newInfo.m_DefaultValue.empty() == false
+ && GetValueType(newInfo.m_DefaultValue) == inDataType)
+ m_DataCore->SetInstancePropertyValue(newInfo.m_Instance, newInfo.m_Property,
+ newInfo.m_DefaultValue);
+ }
+
+ // Destroy just this meta data property
+ void DestroyMetaDataProperty(CUICDMMetaDataPropertyHandle inProperty) override
+ {
+ SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ DestroyItem(__FILE__, __LINE__, inProperty, m_InternalMetaDataPropertyDestroyed,
+ m_Properties, m_InstanceNameToProperties, m_InstanceToProperties);
+ RemoveMetaDataPropertyFilters(inProperty);
+ }
+
+ CUICDMMetaDataPropertyHandle GetMetaDataProperty(CUICDMInstanceHandle inInstance,
+ TStrType inPropertyName) override
+ {
+ return FindItemByName<CUICDMMetaDataPropertyHandle>(inInstance, Intern(inPropertyName),
+ m_InstanceNameToProperties);
+ }
+ CUICDMMetaDataPropertyHandle GetMetaDataProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ SUICDMPropertyDefinition propDef(m_DataCore->GetProperty(inProperty));
+ return GetMetaDataProperty(inInstance, propDef.m_Name);
+ }
+ // Sets the value in the data core
+ virtual Option<SMetaDataPropertyInfo>
+ GetMetaDataPropertyInfo(CUICDMMetaDataPropertyHandle inProperty) override
+ {
+ SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty);
+ if (infoPtr == NULL) {
+ return Empty();
+ }
+ return *infoPtr;
+ }
+
+ void GetMetaDataProperties(CUICDMInstanceHandle inInstance,
+ vector<CUICDMMetaDataPropertyHandle> &outProperties) override
+ {
+ return GetHandleList<CUICDMMetaDataPropertyHandle>(inInstance, m_InstanceToProperties,
+ m_Properties, outProperties);
+ }
+ virtual CUICDMMetaDataPropertyHandle
+ GetSpecificMetaDataProperty(CUICDMInstanceHandle inInstance, TStrType inPropertyName)
+ {
+ TInstancePropertyNamePropertyMap::iterator theFind = m_InstanceNameToProperties.find(
+ make_pair(inInstance, m_StringTable.RegisterStr(inPropertyName.wide_str())));
+ if (theFind != m_InstanceNameToProperties.end())
+ return theFind->second;
+ return 0;
+ }
+ virtual CUICDMMetaDataPropertyHandle
+ GetOrCreateSpecificMetaDataProperty(CUICDMInstanceHandle inInstance, TStrType inPropertyName) override
+ {
+ CUICDMMetaDataPropertyHandle theProp(
+ GetSpecificMetaDataProperty(inInstance, inPropertyName));
+ if (theProp.Valid())
+ return theProp;
+ return CreateMetaDataProperty(inInstance);
+ }
+
+ void GetSpecificMetaDataProperties(CUICDMInstanceHandle inInstance,
+ vector<CUICDMMetaDataPropertyHandle> &outProperties) override
+ {
+ TInstancePropertyMap::iterator find = m_InstanceToProperties.find(inInstance);
+ if (find != m_InstanceToProperties.end())
+ outProperties.insert(outProperties.end(), find->second.begin(), find->second.end());
+ }
+
+ TCharStr GetFormalName(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override
+ {
+ CUICDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty));
+ SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle);
+ if (infoPtr)
+ return infoPtr->m_FormalName;
+ return TCharStr();
+ }
+ AdditionalMetaDataType::Value GetAdditionalMetaDataType(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CUICDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty));
+ SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle);
+ if (infoPtr)
+ return infoPtr->GetAdditionalType();
+ return AdditionalMetaDataType::None;
+ }
+ TMetaDataData GetAdditionalMetaDataData(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) override
+ {
+ CUICDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty));
+ SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle);
+ if (propHandle.Valid())
+ return infoPtr->m_MetaDataData;
+ return TMetaDataData();
+ }
+
+ bool IsCustomInstance(CUICDMInstanceHandle inInstance)
+ {
+ return m_InstancesToCanonicalType.find(inInstance) == m_InstancesToCanonicalType.end();
+ }
+
+ SValue GetDefaultValue(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override
+ {
+ CUICDMMetaDataPropertyHandle theProperty(GetMetaDataProperty(inInstance, inProperty));
+ if (theProperty.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return SValue();
+ }
+ return FindProperty(theProperty)->m_DefaultValue;
+ }
+
+ bool IsCustomProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) override
+ {
+ CUICDMMetaDataPropertyHandle propHandle(GetMetaDataProperty(inInstance, inProperty));
+ SMetaDataPropertyInfo *infoPtr = FindProperty(propHandle);
+ if (infoPtr)
+ return IsCustomInstance(infoPtr->m_Instance);
+
+ return false;
+ }
+
+ bool IsFilterValid(CUICDMMetaDataPropertyHandle inProperty, const SPropertyFilterInfo &inFilter)
+ {
+ SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty);
+ if (m_DataCore->IsProperty(inFilter.m_FilterProperty) == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ SUICDMPropertyDefinition theProp(m_DataCore->GetProperty(inFilter.m_FilterProperty));
+ CUICDMPropertyHandle propCheck =
+ m_DataCore->GetAggregateInstancePropertyByName(infoPtr->m_Instance, theProp.m_Name);
+ if (propCheck != inFilter.m_FilterProperty) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ DataModelDataType::Value theType = GetValueType(inFilter.m_Value);
+ if (theType != theProp.m_Type) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ return true;
+ }
+
+ void SetMetaDataPropertyFilters(CUICDMMetaDataPropertyHandle inProperty,
+ NVConstDataRef<SPropertyFilterInfo> inFilters) override
+ {
+ SMetaDataPropertyInfo *infoPtr = FindProperty(inProperty);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ eastl::vector<SPropertyFilterInfo> newFilters;
+ for (QT3DSU32 idx = 0, end = inFilters.size(); idx < end; ++idx) {
+ const SPropertyFilterInfo &theFilter(inFilters[idx]);
+ if (IsFilterValid(inProperty, theFilter))
+ newFilters.push_back(theFilter);
+ }
+
+ InsertOrUpdateWithTransaction(std::make_pair(inProperty, newFilters), m_PropertyFilters);
+ }
+
+ virtual NVConstDataRef<SPropertyFilterInfo>
+ GetMetaDataPropertyFilters(CUICDMMetaDataPropertyHandle inProperty) override
+ {
+ TMetaDataPropertyFilterMap::iterator theIter(m_PropertyFilters.find(inProperty));
+ if (theIter != m_PropertyFilters.end())
+ return qt3ds::foundation::toDataRef(theIter->second.data(), theIter->second.size());
+ return NVConstDataRef<SPropertyFilterInfo>();
+ }
+
+ void RemoveMetaDataPropertyFilters(CUICDMMetaDataPropertyHandle inProperty) override
+ {
+ TMetaDataPropertyFilterMap::iterator theIter(m_PropertyFilters.find(inProperty));
+ if (theIter != m_PropertyFilters.end())
+ EraseWithTransaction(__FILE__, __LINE__, inProperty, m_PropertyFilters);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Properties
+ CUICDMEventHandle CreateMetaDataEvent(TInstanceHandle inInstance) override
+ {
+ return CreateItem<CUICDMEventHandle, SEvent>(__FILE__, __LINE__, inInstance, m_Events,
+ m_InstanceToEvents);
+ }
+
+ void SetEventInfo(CUICDMEventHandle inEventHandle, TStrType inName,
+ TStrType inFormalName, TStrType inCategory, TStrType inDescription) override
+ {
+ SEvent *infoPtr = FindEvent(inEventHandle);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SEvent &newInfo(*infoPtr);
+ SEvent oldInfo(newInfo);
+ newInfo.m_Name = inName;
+ newInfo.m_FormalName = inFormalName;
+ newInfo.m_Category = inCategory;
+ newInfo.m_Description = inDescription;
+ SetItemInfo(__FILE__, __LINE__, inEventHandle, oldInfo, newInfo, m_Events,
+ m_InstanceNameToEvents);
+ }
+
+ void DestroyEvent(CUICDMEventHandle inEventHandle) override
+ {
+ DestroyItem(__FILE__, __LINE__, inEventHandle, m_InternalEventDestroyed, m_Events,
+ m_InstanceNameToEvents, m_InstanceToEvents);
+ }
+
+ void GetEvents(CUICDMInstanceHandle inInstance, TEventHandleList &outEvents) override
+ {
+ return GetHandleList<CUICDMEventHandle>(inInstance, m_InstanceToEvents, m_Events,
+ outEvents);
+ }
+
+ CUICDMEventHandle FindEvent(CUICDMInstanceHandle inInstance, TStrType inName) override
+ {
+ return FindItemByName<CUICDMEventHandle>(inInstance, Intern(inName),
+ m_InstanceNameToEvents);
+ }
+
+ Option<SEventInfo> GetEventInfo(CUICDMEventHandle inEventHandle) override
+ {
+ SEvent *infoPtr = FindEvent(inEventHandle);
+ if (infoPtr == NULL) {
+ return Empty();
+ }
+ SEventInfo retval;
+ retval.m_Name = infoPtr->m_Name;
+ retval.m_FormalName = infoPtr->m_FormalName;
+ retval.m_Description = infoPtr->m_Description;
+ retval.m_Category = infoPtr->m_Category;
+ return retval;
+ }
+
+ bool IsCustomEvent(CUICDMEventHandle inEventHandle) override
+ {
+ SEvent *infoPtr = FindEvent(inEventHandle);
+ if (infoPtr != NULL)
+ return IsCustomInstance(infoPtr->m_Instance);
+ return false;
+ }
+
+ void GetSpecificEvents(CUICDMInstanceHandle inInstance, TEventHandleList &outEvents) override
+ {
+ TInstanceEventMap::iterator theFind(m_InstanceToEvents.find(inInstance));
+ if (theFind != m_InstanceToEvents.end())
+ outEvents.insert(outEvents.end(), theFind->second.begin(), theFind->second.end());
+ }
+
+ CUICDMEventHandle GetOrCreateSpecificEvent(CUICDMInstanceHandle inInstance,
+ TStrType inName) override
+ {
+ TInstanceEventNameEventMap::iterator theFind(
+ m_InstanceNameToEvents.find(make_pair(inInstance, Intern(inName))));
+ if (theFind != m_InstanceNameToEvents.end())
+ return theFind->second;
+ return CreateMetaDataEvent(inInstance);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Handlers
+
+ CUICDMHandlerHandle CreateHandler(CUICDMInstanceHandle inInstance) override
+ {
+ return CreateItem<CUICDMHandlerHandle, SHandler>(__FILE__, __LINE__, inInstance, m_Handlers,
+ m_InstanceToHandlers);
+ }
+
+ void SetHandlerInfo(CUICDMHandlerHandle inHandle, TStrType inName,
+ TStrType inFormalName, TStrType inCategoryName,
+ TStrType inDescription) override
+ {
+ SHandler *infoPtr = FindHandler(inHandle);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SHandler &newInfo(*infoPtr);
+ SHandler oldInfo(newInfo);
+ newInfo.m_Name = inName;
+ newInfo.m_FormalName = inFormalName;
+ newInfo.m_Description = inDescription;
+ newInfo.m_Category = inCategoryName;
+ SetItemInfo(__FILE__, __LINE__, inHandle, oldInfo, newInfo, m_Handlers,
+ m_InstanceNameToHandlers);
+ }
+
+ void DestroyHandler(CUICDMHandlerHandle inHandlerHandle) override
+ {
+ SHandler *infoPtr(FindHandler(inHandlerHandle));
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ while (infoPtr->m_Arguments.empty() == false)
+ DestroyHanderArgument(inHandlerHandle, (QT3DSU32)infoPtr->m_Arguments.size() - 1);
+ DestroyItem(__FILE__, __LINE__, inHandlerHandle, m_InternalHandlerDestroyed, m_Handlers,
+ m_InstanceNameToHandlers, m_InstanceToHandlers);
+ }
+
+ CUICDMHandlerHandle FindHandlerByName(CUICDMInstanceHandle inInstance, TStrType inName) override
+ {
+ return FindItemByName<CUICDMHandlerHandle>(inInstance, Intern(inName),
+ m_InstanceNameToHandlers);
+ }
+
+ Option<SHandlerInfo> GetHandlerInfo(CUICDMHandlerHandle inHandlerHandle) override
+ {
+ SHandler *infoPtr = FindHandler(inHandlerHandle);
+ if (infoPtr == NULL)
+ return Empty();
+
+ SHandlerInfo retval;
+ retval.m_Name = infoPtr->m_Name;
+ retval.m_FormalName = infoPtr->m_FormalName;
+ retval.m_Category = infoPtr->m_Category;
+ retval.m_Description = infoPtr->m_Description;
+
+ return retval;
+ }
+
+ void GetHandlers(CUICDMInstanceHandle inInstance, THandlerHandleList &outHandlers) override
+ {
+ return GetHandleList<CUICDMHandlerHandle>(inInstance, m_InstanceToHandlers, m_Handlers,
+ outHandlers);
+ }
+
+ bool IsCustomHandler(CUICDMHandlerHandle inHandle) override
+ {
+ SHandler *infoPtr = FindHandler(inHandle);
+ if (infoPtr != NULL)
+ return IsCustomInstance(infoPtr->m_Instance);
+ return false;
+ }
+
+ void GetSpecificHandlers(CUICDMInstanceHandle inInstance,
+ THandlerHandleList &outHandlers) override
+ {
+ TInstanceHandlerMap::iterator theFind = m_InstanceToHandlers.find(inInstance);
+ if (theFind != m_InstanceToHandlers.end())
+ outHandlers.insert(outHandlers.end(), theFind->second.begin(), theFind->second.end());
+ }
+
+ CUICDMHandlerHandle GetOrCreateSpecificHandler(CUICDMInstanceHandle inInstance,
+ TStrType inName) override
+ {
+ TInstanceHandlerNameHandlerMap::iterator theFind =
+ m_InstanceNameToHandlers.find(make_pair(inInstance, Intern(inName)));
+ if (theFind != m_InstanceNameToHandlers.end())
+ return theFind->second;
+ return CreateHandler(inInstance);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Handler Arguments
+
+ void DoAddHandlerArgument(CUICDMHandlerHandle inHandler,
+ const SMetaDataHandlerArgumentInfo &inArgHandle, QT3DSU32 inIdx)
+ {
+ SHandler *infoPtr = FindHandler(inHandler);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ infoPtr->m_Arguments.insert(infoPtr->m_Arguments.begin() + inIdx, inArgHandle);
+ }
+
+ struct ArgNameEqual
+ {
+ const TCharStr &m_Name;
+ ArgNameEqual(const TCharStr &nm)
+ : m_Name(nm)
+ {
+ }
+ bool operator()(const SMetaDataHandlerArgumentInfo &info) const
+ {
+ return m_Name == info.m_Name;
+ }
+ };
+
+ void DoRemoveHandlerArgument(CUICDMHandlerHandle inHandler,
+ const SMetaDataHandlerArgumentInfo &inArgHandle)
+ {
+ SHandler *infoPtr = FindHandler(inHandler);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ erase_if(infoPtr->m_Arguments, ArgNameEqual(inArgHandle.m_Name));
+ }
+
+ struct HandlerArgumentAddRemoveTransaction : public ITransaction
+ {
+ SNewMetaDataImpl &m_Impl;
+ CUICDMHandlerHandle m_Handler;
+ SMetaDataHandlerArgumentInfo m_Arg;
+ QT3DSU32 m_Idx;
+ bool m_AddOnDo;
+
+ HandlerArgumentAddRemoveTransaction(const char *inFile, int inLine, SNewMetaDataImpl &impl,
+ CUICDMHandlerHandle hdl,
+ const SMetaDataHandlerArgumentInfo &arg, QT3DSU32 inIdx,
+ bool inAddOnDo)
+ : ITransaction(inFile, inLine)
+ , m_Impl(impl)
+ , m_Handler(hdl)
+ , m_Arg(arg)
+ , m_Idx(inIdx)
+ , m_AddOnDo(inAddOnDo)
+ {
+ }
+ void insert() { m_Impl.DoAddHandlerArgument(m_Handler, m_Arg, m_Idx); }
+ void remove() { m_Impl.DoRemoveHandlerArgument(m_Handler, m_Arg); }
+ void Do() override
+ {
+ if (m_AddOnDo)
+ insert();
+ else
+ remove();
+ }
+ void Undo() override
+ {
+ if (m_AddOnDo)
+ remove();
+ else
+ insert();
+ }
+ };
+
+ QT3DSU32 AddHandlerArgument(CUICDMHandlerHandle inHandler) override
+ {
+ SHandler *infoPtr = FindHandler(inHandler);
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ SMetaDataHandlerArgumentInfo theInfo(inHandler);
+ QT3DSU32 idx = (QT3DSU32)infoPtr->m_Arguments.size();
+ DoAddHandlerArgument(inHandler, theInfo, idx);
+ if (m_Consumer)
+ m_Consumer->OnTransaction(make_shared<HandlerArgumentAddRemoveTransaction>(
+ __FILE__, __LINE__, ref(*this), inHandler, theInfo, idx, true));
+
+ return idx;
+ }
+
+ void DoSetHandlerArgument(THandlerHandle inHandler, QT3DSU32 inIdx,
+ const SMetaDataHandlerArgumentInfo &inInfo)
+ {
+ SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandler, inIdx));
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ *infoPtr = inInfo;
+ }
+
+ struct SetHandlerArgumentInfoTrans : public ITransaction
+ {
+ SNewMetaDataImpl &m_Impl;
+ THandlerHandle m_Handler;
+ QT3DSU32 m_Idx;
+ SMetaDataHandlerArgumentInfo m_NewValue;
+ SMetaDataHandlerArgumentInfo m_OldValue;
+ SetHandlerArgumentInfoTrans(const char *inFile, int inLine, SNewMetaDataImpl &impl,
+ THandlerHandle handler, QT3DSU32 inIdx,
+ const SMetaDataHandlerArgumentInfo &inNewVal,
+ const SMetaDataHandlerArgumentInfo &inOldVal)
+ : ITransaction(inFile, inLine)
+ , m_Impl(impl)
+ , m_Handler(handler)
+ , m_Idx(inIdx)
+ , m_NewValue(inNewVal)
+ , m_OldValue(inOldVal)
+ {
+ }
+ void Do() override { m_Impl.DoSetHandlerArgument(m_Handler, m_Idx, m_NewValue); }
+ void Undo() override { m_Impl.DoSetHandlerArgument(m_Handler, m_Idx, m_OldValue); }
+ };
+
+ void SetHandlerArgumentInfo(THandlerHandle inHandler, QT3DSU32 inIdx, TStrType inName,
+ TStrType inFormalName, TStrType inDescription,
+ CompleteMetaDataType::Enum inDataType,
+ const SValue &inDefaultValue,
+ const TMetaDataData &inMetaData, HandlerArgumentType::Value inArgType) override
+ {
+ SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandler, inIdx));
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SMetaDataHandlerArgumentInfo &newInfo(*infoPtr);
+ SMetaDataHandlerArgumentInfo oldInfo(newInfo);
+ SetPropertyBaseInfo(newInfo, inName, inFormalName, inDescription, L"", inDataType,
+ inDefaultValue, inMetaData);
+ newInfo.m_ArgType = inArgType;
+ if (m_Consumer != NULL)
+ m_Consumer->OnTransaction(make_shared<SetHandlerArgumentInfoTrans>(
+ __FILE__, __LINE__, ref(*this), inHandler, inIdx, newInfo, oldInfo));
+ }
+
+ void DestroyHanderArgument(THandlerHandle inHandler, QT3DSU32 inIdx) override
+ {
+ SHandler *ownerPtr = FindHandler(inHandler);
+ SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandler, inIdx));
+ if (infoPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (ownerPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ m_InternalHandlerArgDestroyed(inHandler, inIdx);
+
+ if (m_Consumer)
+ m_Consumer->OnTransaction(make_shared<HandlerArgumentAddRemoveTransaction>(
+ __FILE__, __LINE__, ref(*this), infoPtr->m_Handler, *infoPtr, inIdx, false));
+
+ DoRemoveHandlerArgument(infoPtr->m_Handler, *infoPtr);
+ }
+
+ Option<SMetaDataHandlerArgumentInfo> FindHandlerArgumentByName(THandlerHandle inHandler,
+ TStrType inName) override
+ {
+ SHandler *ownerPtr = FindHandler(inHandler);
+ if (ownerPtr == NULL) {
+ return Empty();
+ }
+ for (size_t idx = 0, end = ownerPtr->m_Arguments.size(); idx < end; ++idx) {
+ if (ownerPtr->m_Arguments[idx].m_Name == inName)
+ return ownerPtr->m_Arguments[idx];
+ }
+ return Empty();
+ }
+
+ void GetHandlerArguments(THandlerHandle inHandler,
+ vector<SMetaDataHandlerArgumentInfo> &outArguments) override
+ {
+ SHandler *ownerPtr = FindHandler(inHandler);
+ if (ownerPtr == NULL) {
+ return;
+ }
+ outArguments.insert(outArguments.end(), ownerPtr->m_Arguments.begin(),
+ ownerPtr->m_Arguments.end());
+ }
+
+ virtual Option<SMetaDataHandlerArgumentInfo>
+ GetHandlerArgumentInfo(CUICDMHandlerHandle inHandle, QT3DSU32 inIdx) override
+ {
+ SMetaDataHandlerArgumentInfo *infoPtr(FindHandlerArg(inHandle, inIdx));
+ if (infoPtr == NULL) {
+ return Empty();
+ }
+ return *infoPtr;
+ }
+
+ QT3DSU32 GetNumHandlerArguments(CUICDMHandlerHandle inHandler) override
+ {
+ SHandler *ownerPtr = FindHandler(inHandler);
+ if (ownerPtr == NULL) {
+ return 0;
+ }
+ return (QT3DSU32)ownerPtr->m_Arguments.size();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // References
+ void AddReference(CUICDMInstanceHandle inInstance, TStrType inRefString) override
+ {
+ // trim whitespace from the beginning and the end of the string
+ TCharStr::size_type startPos = inRefString.find_first_not_of(L"\n\r\t ");
+ TCharStr::size_type endPos = inRefString.find_last_not_of(L"\n\r\t ");
+ const wchar_t *theStr = NULL;
+ if (startPos != TCharStr::npos) {
+ TStrType temp = inRefString.substr(startPos, endPos - startPos + 1);
+ theStr = Intern(temp);
+ } else
+ theStr = Intern(inRefString);
+
+ QT3DSU32 idx = AddItemToInstanceList(inInstance, theStr, m_InstanceToReferences);
+ if (m_Consumer) {
+ m_Consumer->OnTransaction(
+ std::make_shared<InstanceListTransaction<TInstanceStringListMap,
+ const wchar_t *>>(
+ __FILE__, __LINE__, inInstance, theStr, std::ref(m_InstanceToReferences), idx,
+ true));
+ }
+ }
+
+ void DestroyReferences(CUICDMInstanceHandle inInstance) override
+ {
+ TInstanceStringListMap::iterator find = m_InstanceToReferences.find(inInstance);
+
+ if (find == m_InstanceToReferences.end())
+ return;
+
+ CreateHashMapEraseTransaction(__FILE__, __LINE__, m_Consumer,
+ make_pair(find->first, find->second), m_InstanceToReferences);
+ m_InstanceToReferences.erase(find);
+ }
+
+ struct InternSizeTOpType
+ {
+ SNewMetaDataImpl &m_Impl;
+ InternSizeTOpType(SNewMetaDataImpl &inImpl)
+ : m_Impl(inImpl)
+ {
+ }
+
+ size_t operator()(const TCharStr &inHandle)
+ {
+ return reinterpret_cast<size_t>(m_Impl.Intern(inHandle));
+ }
+ };
+
+ void GetReferences(CUICDMInstanceHandle inInstance, vector<TCharStr> &outReferences) override
+ {
+ DoGetHandleList(inInstance, m_InstanceToReferences, outReferences,
+ InternSizeTOpType(*this));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Instance-global functions
+ // Destroy all meta data that relates to this instance.
+ // Calling this on a derived instance does nothing, this only works if this specific
+ // instance was mapped to a type.
+ // This function must be completely undoable.
+ void DestroyMetaData(CUICDMInstanceHandle inInstance) override
+ {
+ ForEachItem<TMetaDataPropertyHandle>(
+ inInstance, m_InstanceToProperties,
+ bind(&SNewMetaDataImpl::DestroyMetaDataProperty, this,
+ std::placeholders::_1));
+ ForEachItem<TEventHandle>(inInstance, m_InstanceToEvents,
+ bind(&SNewMetaDataImpl::DestroyEvent, this,
+ std::placeholders::_1));
+ ForEachItem<THandlerHandle>(inInstance, m_InstanceToHandlers,
+ bind(&SNewMetaDataImpl::DestroyHandler, this,
+ std::placeholders::_1));
+ DestroyReferences(inInstance);
+
+ TInstanceStrMap::iterator find = m_InstancesToCanonicalType.find(inInstance);
+ if (find != m_InstancesToCanonicalType.end()) {
+ TCharPtr theName(find->second);
+ m_CanonicalTypeToInstances.erase(theName);
+ m_InstancesToCanonicalType.erase(inInstance);
+ CreateHashMapEraseTransaction(__FILE__, __LINE__, m_Consumer,
+ make_pair(theName, inInstance),
+ m_CanonicalTypeToInstances);
+ CreateHashMapEraseTransaction(__FILE__, __LINE__, m_Consumer,
+ make_pair(inInstance, theName),
+ m_InstancesToCanonicalType);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Serialization
+ // You can either save out in canonical format (and it will only save canonical-instance-related
+ // information *or* you can save out in normal format where we link directly to instance handle
+ // instead of to typename
+ template <typename THashType>
+ void AddInstancesFromHash(THashType &inHash,
+ unordered_set<TInstanceHandle, hash<int>> &outInstances)
+ {
+ for (typename THashType::const_iterator iter = inHash.begin(), end = inHash.end();
+ iter != end; ++iter)
+ outInstances.insert(iter->first);
+ }
+
+ void SerializeMetaDataData(IDOMWriter &inWriter, TMetaDataData &inItem,
+ AdditionalMetaDataType::Value inType)
+ {
+ if (!inItem.empty()) {
+ if (inType == AdditionalMetaDataType::Range) {
+ SMetaDataRange theRange(get<SMetaDataRange>(inItem));
+ inWriter.Att(L"min", theRange.m_Min);
+ inWriter.Att(L"max", theRange.m_Max);
+ } else if (inType == AdditionalMetaDataType::StringList) {
+ const TMetaDataStringList &theList(get<TMetaDataStringList>(inItem));
+ TCharStr theBuffer;
+ for (uint32_t idx = 0, end = theList.size(); idx < end; ++idx) {
+ if (idx)
+ theBuffer.append(L":");
+ theBuffer.append(theList[idx]);
+ }
+ inWriter.Att(L"list", theBuffer.wide_str());
+ }
+ }
+ }
+
+ void SerializeDataModelValue(IDOMWriter &inWriter, const SValue &inValue,
+ DataModelDataType::Value /*inType*/, const wchar_t *inName = L"default")
+ {
+ if (inValue.empty())
+ return;
+
+ m_TempBuffer.clear();
+ WCharTWriter writer(m_TempBuffer);
+ WStrOps<SValue>().ToBuf(inValue, writer);
+
+ if (m_TempBuffer.size()) {
+ m_TempBuffer.write((QT3DSU16)0);
+ inWriter.Att(inName, (const wchar_t *)m_TempBuffer.begin());
+ }
+ }
+
+ void SerializeDataModelValue(IDOMReader &inReader, SValue &outValue, DataModelDataType::Value inType,
+ const wchar_t *inName = L"default")
+ {
+ const char8_t *theDefaultValue;
+ qt3ds::foundation::ConvertUTF(
+ reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(inName), 0,
+ m_ConvertStr);
+ if (inReader.UnregisteredAtt(m_ConvertStr.c_str(), theDefaultValue)) {
+ m_TempBuffer.clear();
+ // We have to write a temporary value because the parsing of floats,
+ // in order to be efficient, is destructive.
+ if (theDefaultValue && *theDefaultValue)
+ m_TempBuffer.write(theDefaultValue, (QT3DSU32)strlen(theDefaultValue) + 1);
+
+ if (m_TempBuffer.size() == 0) {
+ SetDefault(inType, outValue);
+ return;
+ }
+ m_ReadBuffer.clear();
+
+ char8_t *trashPtr = (char8_t *)m_TempBuffer.begin();
+ WCharTReader theReader(trashPtr, m_ReadBuffer, m_StringTable);
+ outValue = WStrOps<SValue>().BufTo(inType, theReader);
+ } else
+ SetDefault(inType, outValue);
+ }
+
+ void SerializeMetaDataData(IDOMReader &inReader, TMetaDataData &ioItem,
+ CompleteMetaDataType::Enum &ioType)
+ {
+ // Use the meta data extra information to force the type
+ // to something that works correctly.
+ SMetaDataRange theRange;
+ if (inReader.Att("min", theRange.m_Min) && inReader.Att("max", theRange.m_Max)) {
+ ioItem = theRange;
+ if (ioType == CompleteMetaDataType::Long)
+ ioType = CompleteMetaDataType::LongRange;
+ else
+ ioType = CompleteMetaDataType::FloatRange;
+ } else {
+ TMetaDataStringList theList;
+ TCharStr theItems;
+ if (inReader.Att(L"list", theItems)) {
+ for (TCharStr::size_type theIter = theItems.find_first_of(L":,");
+ theIter != theItems.npos; theIter = theItems.find_first_of(L":,")) {
+ theList.push_back(theItems.substr(0, theIter));
+ theItems = theItems.substr(theIter + 1);
+ }
+ theList.push_back(theItems);
+ ioItem = theList;
+ if (ioType != CompleteMetaDataType::StringListOrInt)
+ ioType = CompleteMetaDataType::StringList;
+ }
+ }
+ }
+ void EnsureCategory(IDOMWriter &, const TCharStr &, const TCharStr &) {}
+ void EnsureCategory(IDOMReader &, TCharStr &inCategory, const TCharStr &inObjectName)
+ {
+ CUICDMCategoryHandle theCategory = FindCategoryByName(inCategory);
+ if (theCategory.Valid() == false) {
+ if (inObjectName.empty()) {
+ QT3DS_ASSERT(false);
+ } else {
+ if (inCategory.empty())
+ inCategory = inObjectName;
+
+ pair<CUICDMCategoryHandle, bool> theGetOrCreateResult(
+ GetOrCreateCategory(inCategory));
+
+ if (theGetOrCreateResult.second == true) {
+ SetCategoryInfo(theGetOrCreateResult.first, L"Objects-Behavior-Normal.png",
+ L"Objects-Behavior-Normal.png", inCategory);
+ }
+ }
+ }
+ }
+
+ void SerializePropertyBase(IDOMWriter &inArchive, SMetaPropertyBase &inItem)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ if (inItem.m_FormalName != inItem.m_Name)
+ inArchive.Att(L"formalName", inItem.m_FormalName);
+ if (inItem.m_Description != inItem.m_Name)
+ inArchive.Att(L"description", inItem.m_Description);
+ if (inItem.m_CompleteType != CompleteMetaDataType::Float
+ && inItem.m_CompleteType != CompleteMetaDataType::FloatRange
+ && inItem.m_CompleteType != CompleteMetaDataType::LongRange
+ && inItem.m_CompleteType != CompleteMetaDataType::StringList)
+ inArchive.Att(L"type", inItem.m_CompleteType);
+
+ // Ensure that all types work
+ if (inItem.GetAdditionalType() != AdditionalMetaDataType::None)
+ SerializeMetaDataData(inArchive, inItem.m_MetaDataData, inItem.GetAdditionalType());
+
+ if (inItem.GetDataType() != DataModelDataType::None) {
+ SValue theGlobalDefault;
+ SetDefault(inItem.GetDataType(), theGlobalDefault);
+ if (!Equals(theGlobalDefault.toOldSkool(), inItem.m_DefaultValue.toOldSkool()))
+ SerializeDataModelValue(inArchive, inItem.m_DefaultValue, inItem.GetDataType());
+ }
+ }
+
+ void SerializePropertyBase(IDOMReader &inArchive, SMetaPropertyBase &inItem)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ inArchive.Att(L"formalName", inItem.m_FormalName);
+ inArchive.Att(L"usage", inItem.m_Usage);
+ inArchive.Att(L"description", inItem.m_Description);
+ inArchive.Att(L"type", inItem.m_CompleteType);
+ // Setup reasonable defaults in the case where the users are specifying little information
+ // in the file format
+ if (inItem.m_FormalName.empty())
+ inItem.m_FormalName = inItem.m_Name;
+ if (inItem.m_Description.empty())
+ inItem.m_Description = inItem.m_Name;
+
+ // Ensure that users can use a float type and make minimal decisions
+ SerializeMetaDataData(inArchive, inItem.m_MetaDataData, inItem.m_CompleteType);
+
+ if (inItem.GetDataType() != DataModelDataType::None)
+ SerializeDataModelValue(inArchive, inItem.m_DefaultValue, inItem.GetDataType());
+ }
+
+ void FinalizeCategory(IDOMWriter &, SCategoryInfo &) {}
+
+ void FinalizeCategory(IDOMReader &, SCategoryInfo &inCategory)
+ {
+ if (inCategory.m_Description.empty())
+ inCategory.m_Description = inCategory.m_Name;
+ }
+
+ template <typename TArchiveType>
+ void SerializeItem(TArchiveType &inArchive, SCategoryInfo &inItem)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ inArchive.Att(L"description", inItem.m_Description);
+ inArchive.Att(L"icon", inItem.m_Icon);
+ inArchive.Att(L"highlightIcon", inItem.m_HighlightIcon);
+
+ FinalizeCategory(inArchive, inItem);
+ }
+
+ void SerializeItem(IDOMWriter &inArchive, SMetaDataPropertyInfo &inItem,
+ CUICDMMetaDataPropertyHandle inHandle)
+ {
+ SerializePropertyBase(inArchive, inItem);
+ if (inItem.m_IsHidden == true)
+ inArchive.Att(L"hidden", inItem.m_IsHidden);
+ if (inItem.m_Animatable == false)
+ inArchive.Att(L"animatable", inItem.m_Animatable);
+ NVConstDataRef<SPropertyFilterInfo> theInfos = GetMetaDataPropertyFilters(inHandle);
+ for (QT3DSU32 idx = 0, end = theInfos.size(); idx < end; ++idx) {
+ const SPropertyFilterInfo &theInfo(theInfos[idx]);
+ SUICDMPropertyDefinition thePropertyInfo(
+ m_DataCore->GetProperty(theInfo.m_FilterProperty));
+
+ const wchar_t *theFilterName;
+ if (theInfo.m_FilterType == PropertyFilterTypes::HideIfEqual)
+ theFilterName = L"HideIfEqual";
+ else
+ theFilterName = L"ShowIfEqual";
+
+ IDOMWriter::Scope filterScope(inArchive, theFilterName);
+ inArchive.Att(L"property", thePropertyInfo.m_Name);
+ SerializeDataModelValue(inArchive, theInfo.m_Value, thePropertyInfo.m_Type, L"value");
+ }
+ }
+
+ void SerializeItem(IDOMReader &inArchive, SMetaDataPropertyInfo &inItem,
+ CUICDMMetaDataPropertyHandle inHandle)
+ {
+ QT3DS_ASSERT(inHandle.Valid());
+
+ SerializePropertyBase(inArchive, inItem);
+ inArchive.Att(L"hidden", inItem.m_IsHidden);
+ inArchive.Att(L"animatable", inItem.m_Animatable);
+ inArchive.Att(L"category", inItem.m_GroupName);
+ }
+
+ void ReadChildren(IDOMReader &inArchive, SMetaDataPropertyInfo &inItem,
+ CUICDMMetaDataPropertyHandle inHandle)
+ {
+ IDOMReader::Scope __readerScope(inArchive);
+ eastl::vector<SPropertyFilterInfo> theFilters;
+ for (bool success = inArchive.MoveToFirstChild(); success;
+ success = inArchive.MoveToNextSibling()) {
+
+ if (AreEqual(inArchive.GetElementName(), L"ShowIfEqual")) {
+ TCharStr theName;
+ inArchive.Att(L"property", theName);
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(inItem.m_Instance, theName);
+ if (theProperty.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SUICDMPropertyDefinition thePropDef(m_DataCore->GetProperty(theProperty));
+
+ SPropertyFilterInfo theInfo;
+ theInfo.m_FilterType = PropertyFilterTypes::ShowIfEqual;
+ theInfo.m_FilterProperty = theProperty;
+ SerializeDataModelValue(inArchive, theInfo.m_Value, thePropDef.m_Type, L"value");
+ theFilters.push_back(theInfo);
+ } else if (AreEqual(inArchive.GetElementName(), L"HideIfEqual")) {
+ TCharStr theName;
+ inArchive.Att(L"property", theName);
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(inItem.m_Instance, theName);
+ if (theProperty.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SUICDMPropertyDefinition thePropDef(m_DataCore->GetProperty(theProperty));
+
+ SPropertyFilterInfo theInfo;
+ theInfo.m_FilterType = PropertyFilterTypes::HideIfEqual;
+ theInfo.m_FilterProperty = theProperty;
+ SerializeDataModelValue(inArchive, theInfo.m_Value, thePropDef.m_Type, L"value");
+ theFilters.push_back(theInfo);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ if (theFilters.size())
+ SetMetaDataPropertyFilters(
+ inHandle, qt3ds::foundation::toDataRef(theFilters.data(), theFilters.size()));
+ }
+
+ void EnsureEventHandlerBase(IDOMWriter &, SEventAndHandlerBase &) {}
+
+ void EnsureEventHandlerBase(IDOMReader &, SEventAndHandlerBase &inItem)
+ {
+ if (inItem.m_FormalName.empty())
+ inItem.m_FormalName = inItem.m_Name;
+ if (inItem.m_Description.empty())
+ inItem.m_Description = inItem.m_Name;
+ }
+
+ void SerializeItem(IDOMWriter &inArchive, SEvent &inItem, CUICDMEventHandle &)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ if (inItem.m_Name != inItem.m_FormalName)
+ inArchive.Att(L"formalName", inItem.m_FormalName);
+ if (inItem.m_Category != L"Default")
+ inArchive.Att(L"category", inItem.m_Category);
+ if (inItem.m_Description != inItem.m_Name)
+ inArchive.Att(L"description", inItem.m_Description);
+
+ EnsureCategory(inArchive, inItem.m_Category, m_ObjectName);
+ EnsureEventHandlerBase(inArchive, inItem);
+ }
+
+ void SerializeItem(IDOMReader &inArchive, SEvent &inItem, CUICDMEventHandle &)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ inArchive.Att(L"formalName", inItem.m_FormalName);
+ inArchive.Att(L"category", inItem.m_Category);
+ EnsureCategory(inArchive, inItem.m_Category, m_ObjectName);
+ inArchive.Att(L"description", inItem.m_Description);
+ EnsureEventHandlerBase(inArchive, inItem);
+ }
+
+ void SerializeHandlerArgument(IDOMWriter &inArchive, SMetaDataHandlerArgumentInfo &inArgument)
+ {
+ SerializePropertyBase(inArchive, inArgument);
+ if (inArgument.m_ArgType != HandlerArgumentType::None)
+ inArchive.Att(L"argumentType", inArgument.m_ArgType);
+ }
+
+ void SerializeHandlerArgument(IDOMReader &inArchive, SMetaDataHandlerArgumentInfo &inArgument)
+ {
+ SerializePropertyBase(inArchive, inArgument);
+ inArchive.Att(L"argumentType", inArgument.m_ArgType);
+ }
+
+ void SerializeHandlerArguments(IDOMWriter &inWriter, SHandler &inItem, CUICDMHandlerHandle &)
+ {
+ for (size_t idx = 0, end = inItem.m_Arguments.size(); idx < end; ++idx) {
+ SMetaDataHandlerArgumentInfo &theArg(inItem.m_Arguments[idx]);
+ IDOMWriter::Scope __argScope(inWriter, L"Argument");
+ SerializeHandlerArgument(inWriter, theArg);
+ }
+ }
+
+ void SerializeHandlerArguments(IDOMReader &inReader, SHandler &inItem, THandlerHandle &inHandle)
+ {
+ if (inHandle.GetHandleValue() == 0)
+ inHandle = THandlerHandle(GetNextId());
+
+ IDOMReader::Scope __handlerScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ SMetaDataHandlerArgumentInfo theArg(inHandle);
+ SerializeHandlerArgument(inReader, theArg);
+ inItem.m_Arguments.push_back(theArg);
+ }
+ }
+
+ void SerializeHandlerItem(IDOMWriter &inArchive, SHandler &inItem)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ if (inItem.m_FormalName != inItem.m_Name)
+ inArchive.Att(L"formalName", inItem.m_FormalName);
+ if (inItem.m_Category != L"Default")
+ inArchive.Att(L"category", inItem.m_Category);
+ if (inItem.m_Description != inItem.m_Name)
+ inArchive.Att(L"description", inItem.m_Description);
+ EnsureEventHandlerBase(inArchive, inItem);
+ }
+
+ void SerializeHandlerItem(IDOMReader &inArchive, SHandler &inItem)
+ {
+ inArchive.Att(L"name", inItem.m_Name);
+ inArchive.Att(L"formalName", inItem.m_FormalName);
+ inArchive.Att(L"category", inItem.m_Category);
+ EnsureCategory(inArchive, inItem.m_Category, m_ObjectName);
+ inArchive.Att(L"description", inItem.m_Description);
+ EnsureEventHandlerBase(inArchive, inItem);
+ }
+
+ template <typename TArchiveType>
+ void SerializeItem(TArchiveType &inArchive, SHandler &inItem, CUICDMHandlerHandle &inHandle)
+ {
+ SerializeHandlerItem(inArchive, inItem);
+ SerializeHandlerArguments(inArchive, inItem, inHandle);
+ }
+
+ template <typename TInfoType, typename THandleType, typename TListMapType, typename THashType,
+ typename TNameMapType>
+ void SerializeInstanceData(IDOMWriter &inArchive, TInstanceHandle inInstanceHandle,
+ TCharPtr inElementName,
+ unordered_map<THandleType, TInfoType, THashType> &inMap,
+ TListMapType &inListMap, TNameMapType & /*inNameMap*/)
+ {
+ typedef unordered_map<THandleType, TInfoType, THashType> TMapType;
+ typename TListMapType::iterator find = inListMap.find(inInstanceHandle);
+ if (find == inListMap.end())
+ return;
+
+ vector<THandleType> &itemList = find->second;
+ for (size_t idx = 0, end = itemList.size(); idx < end; ++idx) {
+ typename TMapType::iterator iter = inMap.find(itemList[idx]);
+ if (iter == inMap.end()) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ TInfoType &theType = iter->second;
+ IDOMWriter::Scope __elemScope(inArchive, inElementName);
+ SerializeItem(inArchive, theType, itemList[idx]);
+ }
+ }
+
+ void CreateInstanceGroupInfo(SMetaDataPropertyInfo &inProperty)
+ {
+ if (!inProperty.m_GroupName.empty()) {
+ const wchar_t *theGroupName = Intern(inProperty.m_GroupName);
+ bool found = false;
+ pair<typename TInstanceGroupMap::iterator, bool> inserter =
+ m_InstanceGroupMap.insert(make_pair(inProperty.m_Instance, vector<TCharPtr>()));
+ vector<TCharPtr> &itemList = inserter.first->second;
+ for (size_t idx = 0, end = itemList.size(); idx < end; ++idx) {
+ TCharStr curListName = itemList[idx];
+ if (curListName == theGroupName) {
+ found = true;
+ break;
+ }
+ }
+ if (!found && !inProperty.m_IsHidden)
+ inserter.first->second.push_back(theGroupName);
+ }
+ }
+ void CreateInstanceGroupInfo(SEvent &) {}
+ void CreateInstanceGroupInfo(SHandler &) {}
+
+ // Make sure the data core
+ void PostLoad(SMetaDataPropertyInfo &inProperty)
+ {
+ EnsureDataCoreProperty(inProperty);
+ SetPropertyDefault(inProperty, inProperty.GetDataType());
+ }
+
+ void ReadChildren(IDOMReader &, SEvent &, CUICDMEventHandle) {}
+ void ReadChildren(IDOMReader &, SHandler &, CUICDMHandlerHandle) {}
+
+ void PostLoad(SEvent &) {}
+ void PostLoad(SHandler &) {}
+ template <typename TInfoType, typename THandleType, typename TListMapType, typename THashType,
+ typename TNameMapType>
+ void SerializeInstanceData(IDOMReader &inArchive, TInstanceHandle inInstanceHandle,
+ TCharPtr inElementName,
+ unordered_map<THandleType, TInfoType, THashType> &inMap,
+ TListMapType &inListMap, TNameMapType &inNameMap)
+ {
+ // Ensure we pop out to where we were.
+ IDOMReader::Scope __readerScope(inArchive);
+ for (bool success = inArchive.MoveToFirstChild(inElementName); success;
+ success = inArchive.MoveToNextSibling(inElementName)) {
+ TInfoType theInfo(inInstanceHandle);
+ THandleType theHandle(GetNextId());
+ SerializeItem(inArchive, theInfo, theHandle);
+ PostLoad(theInfo);
+ CreateInstanceGroupInfo(theInfo);
+ inMap.insert(make_pair(theHandle, theInfo));
+ this->AddItemToInstanceList(inInstanceHandle, theHandle, inListMap);
+ inNameMap.insert(
+ make_pair(make_pair(inInstanceHandle, Intern(theInfo.m_Name)), theHandle));
+ ReadChildren(inArchive, theInfo, theHandle);
+ }
+ }
+
+ void SerializeInstanceData(IDOMWriter &inArchive, TInstanceHandle inInstance,
+ TCharPtr inElementName, TInstanceStringListMap &inMap)
+ {
+ TInstanceStringListMap::iterator iter = inMap.find(inInstance);
+ if (iter == inMap.end())
+ return;
+ const vector<TCharPtr> &theValueList(iter->second);
+ for (size_t idx = 0, end = theValueList.size(); idx < end; ++idx) {
+ IDOMWriter::Scope __elemScope(inArchive, inElementName);
+ inArchive.Value(theValueList[idx]);
+ }
+ }
+
+ void SerializeInstanceData(IDOMReader &inArchive, TInstanceHandle inInstance,
+ TCharPtr inElementName, TInstanceStringListMap &inMap)
+ {
+ IDOMReader::Scope __readerScope(inArchive);
+ for (bool success = inArchive.MoveToFirstChild(inElementName); success;
+ success = inArchive.MoveToNextSibling(inElementName)) {
+ const wchar_t *theValue;
+ if (inArchive.RegisteredValue(theValue))
+ AddItemToInstanceList(inInstance, theValue, inMap);
+ }
+ }
+
+ template <typename TArchiveType>
+ void SerializeInstance(TArchiveType &inArchive, TInstanceHandle inInstance)
+ {
+ SerializeInstanceData(inArchive, inInstance, L"Property", m_Properties,
+ m_InstanceToProperties, m_InstanceNameToProperties);
+ SerializeInstanceData(inArchive, inInstance, L"Event", m_Events, m_InstanceToEvents,
+ m_InstanceNameToEvents);
+ SerializeInstanceData(inArchive, inInstance, L"Handler", m_Handlers, m_InstanceToHandlers,
+ m_InstanceNameToHandlers);
+ SerializeInstanceData(inArchive, inInstance, L"Reference", m_InstanceToReferences);
+ }
+ void SerializeCategories(IDOMWriter &inWriter)
+ {
+ for (TCategoryMap::iterator iter = m_Categories.begin(), end = m_Categories.end();
+ iter != end; ++iter) {
+ IDOMWriter::Scope __writerScope(inWriter, L"Category");
+ SerializeItem(inWriter, iter->second);
+ }
+ }
+ void SerializeCategories(IDOMReader &inReader)
+ {
+ IDOMReader::Scope __readerScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(L"Category"); success;
+ success = inReader.MoveToNextSibling(L"Category")) {
+ SCategoryInfo theInfo;
+ SerializeItem(inReader, theInfo);
+ TCategoryHandle newHandle(GetNextId());
+ theInfo.m_Canonical = true;
+ m_Categories.insert(make_pair(newHandle, theInfo));
+ m_NameToCategories.insert(make_pair(Intern(theInfo.m_Name), newHandle));
+ }
+ }
+
+ struct SInstanceSorter
+ {
+ const TInstanceStrMap &m_Map;
+ SInstanceSorter(const TInstanceStrMap &inMap)
+ : m_Map(inMap)
+ {
+ }
+ bool operator()(TInstanceHandle lhs, TInstanceHandle rhs)
+ {
+ TInstanceStrMap::const_iterator lhsIter(m_Map.find(lhs));
+ TInstanceStrMap::const_iterator rhsIter(m_Map.find(rhs));
+ if (lhsIter == rhsIter)
+ return false;
+ if (lhsIter == m_Map.end())
+ return false;
+ if (rhsIter == m_Map.end())
+ return true;
+ return wcscmp(lhsIter->second, rhsIter->second) < 0;
+ }
+ };
+
+ void Save(IDOMWriter &inWriter) override
+ {
+ SerializeCategories(inWriter);
+ typedef unordered_set<TInstanceHandle, hash<int>> TInstanceListType;
+ TInstanceListType theInstanceList;
+ // Get the list of instances to serialize.
+
+ AddInstancesFromHash(m_InstanceToProperties, theInstanceList);
+ AddInstancesFromHash(m_InstanceToEvents, theInstanceList);
+ AddInstancesFromHash(m_InstanceToHandlers, theInstanceList);
+ AddInstancesFromHash(m_InstanceToReferences, theInstanceList);
+
+ vector<TInstanceHandle> theInstances;
+ theInstances.reserve(theInstanceList.size());
+ theInstances.insert(theInstances.begin(), theInstanceList.begin(), theInstanceList.end());
+ sort(theInstances.begin(), theInstances.end(), SInstanceSorter(m_InstancesToCanonicalType));
+
+ for (vector<TInstanceHandle>::iterator iter = theInstances.begin(),
+ end = theInstances.end();
+ iter != end; ++iter) {
+ TInstanceHandle instHandle = *iter;
+ Option<TCharStr> theType(GetTypeForCanonicalInstance(*iter));
+ if (theType.hasValue()) {
+ IDOMWriter::Scope __instanceElem(inWriter, theType->wide_str());
+ SerializeInstance(inWriter, *iter);
+ }
+ }
+ }
+
+ // Loading expects the canonical instances to be setup already which means that
+ // it will perform lookups based on
+ void Load(IDOMReader &inReader) override
+ {
+ if (!inReader.Att("NextId", m_NextId))
+ m_NextId = 1;
+ m_ObjectName = L"";
+ SerializeCategories(inReader);
+ IDOMReader::Scope __instanceGatherScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ const wchar_t *elemName = inReader.GetElementName();
+ TStrInstanceMap::iterator find = m_CanonicalTypeToInstances.find(elemName);
+ if (find == m_CanonicalTypeToInstances.end()) {
+ continue;
+ }
+
+ SerializeInstance(inReader, find->second);
+ }
+ }
+
+ template <typename THandleType, typename TMapType>
+ void RemoveOldItemsAndSetOrder(
+ CUICDMInstanceHandle inInstance, vector<THandleType> &inNewHandles,
+ void (SNewMetaDataImpl::*inGetSpecificFun)(CUICDMInstanceHandle, vector<THandleType> &),
+ void (SNewMetaDataImpl::*inDestroyFun)(THandleType), TMapType &inListMap)
+ {
+ vector<THandleType> theHandles;
+ (this->*inGetSpecificFun)(inInstance, theHandles);
+ for (size_t idx = 0, end = theHandles.size(); idx < end; ++idx)
+ if (find(inNewHandles.begin(), inNewHandles.end(), theHandles[idx])
+ == inNewHandles.end())
+ (this->*inDestroyFun)(theHandles[idx]);
+
+ InsertOrUpdateWithTransaction(make_pair(inInstance, inNewHandles), inListMap);
+ }
+
+ // Load meta data and apply it to just this instance
+ // This needs to be undoable so we have to do this through a slightly different
+ // system than we did before.
+ void LoadInstance(IDOMReader &inReader, CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings) override
+ {
+ const wchar_t *theAtt;
+ vector<CUICDMMetaDataPropertyHandle> theProperties;
+ vector<CUICDMEventHandle> theEvents;
+ vector<CUICDMHandlerHandle> theHandlers;
+ DestroyReferences(inInstance);
+ m_ObjectName = inObjectName;
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetElementName(), L"Category")) {
+ SCategoryInfo theInfo;
+ SerializeItem(inReader, theInfo);
+ CUICDMCategoryHandle theCategoryInfo(GetOrCreateCategory(theInfo.m_Name).first);
+ SetCategoryInfo(theCategoryInfo, theInfo.m_Icon, theInfo.m_HighlightIcon,
+ theInfo.m_Description);
+ } else if (AreEqual(inReader.GetElementName(), L"Property")) {
+ SMetaDataPropertyInfo theInfo(inInstance);
+ if (inReader.Att(L"name", theAtt)) {
+ CUICDMMetaDataPropertyHandle theProperty(
+ GetOrCreateSpecificMetaDataProperty(inInstance, theAtt));
+ SerializeItem(inReader, theInfo, theProperty);
+ SetMetaDataPropertyInfo(theProperty, theInfo.m_Name, theInfo.m_FormalName,
+ theInfo.m_Description, theInfo.m_Usage,
+ theInfo.m_CompleteType, theInfo.m_DefaultValue,
+ theInfo.m_MetaDataData, theInfo.m_GroupName,
+ theInfo.m_IsHidden, theInfo.m_Animatable);
+ CreateInstanceGroupInfo(theInfo);
+ theProperties.push_back(theProperty);
+ ReadChildren(inReader, theInfo, theProperty);
+ } else
+ outWarnings.push_back(
+ SMetaDataLoadWarning(MetaDataLoadWarningType::InvalidProperty,
+ MetaDataLoadWarningMessage::MissingName));
+ } else if (AreEqual(inReader.GetElementName(), L"Event")) {
+ SEvent theInfo(inInstance);
+ if (inReader.Att(L"name", theAtt)) {
+ CUICDMEventHandle theEvent(GetOrCreateSpecificEvent(inInstance, theAtt));
+ SerializeItem(inReader, theInfo, theEvent);
+ SetEventInfo(theEvent, theInfo.m_Name, theInfo.m_FormalName, theInfo.m_Category,
+ theInfo.m_Description);
+ theEvents.push_back(theEvent);
+ } else
+ outWarnings.push_back(
+ SMetaDataLoadWarning(MetaDataLoadWarningType::InvalidEvent,
+ MetaDataLoadWarningMessage::MissingName));
+ } else if (AreEqual(inReader.GetElementName(), L"Handler")) {
+ if (inReader.Att(L"name", theAtt)) {
+ CUICDMHandlerHandle theHandler(GetOrCreateSpecificHandler(inInstance, theAtt));
+ SHandler theInfo(inInstance);
+ SerializeHandlerItem(inReader, theInfo);
+ SetHandlerInfo(theHandler, theInfo.m_Name, theInfo.m_FormalName,
+ theInfo.m_Category, theInfo.m_Description);
+ IDOMReader::Scope __argScope(inReader);
+ QT3DSU32 argIdx = 0;
+ for (bool argSuccess = inReader.MoveToFirstChild(); argSuccess;
+ argSuccess = inReader.MoveToNextSibling(), ++argIdx) {
+ SMetaDataHandlerArgumentInfo theArg(theHandler);
+ SerializeHandlerArgument(inReader, theArg);
+ while (argIdx >= GetNumHandlerArguments(theHandler))
+ AddHandlerArgument(theHandler);
+
+ if (argIdx < GetNumHandlerArguments(theHandler)) {
+ SetHandlerArgumentInfo(theHandler, argIdx, theArg.m_Name,
+ theArg.m_FormalName, theArg.m_Description,
+ theArg.m_CompleteType, theArg.m_DefaultValue,
+ theArg.m_MetaDataData, theArg.m_ArgType);
+ }
+ }
+ while (GetNumHandlerArguments(theHandler) > argIdx)
+ DestroyHanderArgument(theHandler, GetNumHandlerArguments(theHandler) - 1);
+ theHandlers.push_back(theHandler);
+ } else
+ outWarnings.push_back(
+ SMetaDataLoadWarning(MetaDataLoadWarningType::InvalidHandler,
+ MetaDataLoadWarningMessage::MissingName));
+ } else if (AreEqual(inReader.GetElementName(), L"Reference")) {
+ const wchar_t *theValue;
+ if (inReader.Value(theValue))
+ AddReference(inInstance, theValue);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ RemoveOldItemsAndSetOrder(
+ inInstance, theProperties, &SNewMetaDataImpl::GetSpecificMetaDataProperties,
+ &SNewMetaDataImpl::DestroyMetaDataProperty, m_InstanceToProperties);
+ RemoveOldItemsAndSetOrder(inInstance, theEvents, &SNewMetaDataImpl::GetSpecificEvents,
+ &SNewMetaDataImpl::DestroyEvent, m_InstanceToEvents);
+ RemoveOldItemsAndSetOrder(inInstance, theHandlers, &SNewMetaDataImpl::GetSpecificHandlers,
+ &SNewMetaDataImpl::DestroyHandler, m_InstanceToHandlers);
+ }
+
+ // Save just this instances meta data out to the writer
+ void SaveInstance(IDOMWriter &inWriter, CUICDMInstanceHandle inInstance) override
+ {
+ SerializeInstance(inWriter, inInstance);
+ }
+
+ // Helper to convert char to wchar_t
+ eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> m_Buf;
+ const wchar_t *ConvertChar(const char *inName)
+ {
+ if (inName && *inName) {
+ qt3ds::foundation::ConvertUTF(inName, 0, m_Buf);
+ return reinterpret_cast<const wchar_t *>(m_Buf.c_str());
+ }
+ return NULL;
+ }
+
+ void LoadEffectInstance(const char *inShaderFile, CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) override
+ {
+ QString shaderFile(inShaderFile);
+ if (shaderFile.endsWith(".effect")) {
+ LoadEffectXMLFromSourcePath(inShaderFile, inInstance, inObjectName, outWarnings,
+ inStream);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ bool IsEffectInstanceRegistered(const char *inName) override
+ {
+ return m_EffectMap.find(Intern(inName)) != m_EffectMap.end();
+ }
+
+ inline qt3ds::render::NVRenderTextureFormats::Enum
+ ConvertTypeAndFormatToTextureFormat(const char8_t *inType, const char8_t *inFormat)
+ {
+ qt3ds::render::NVRenderTextureFormats::Enum retval = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ if (AreEqual(inFormat, "source"))
+ retval = qt3ds::render::NVRenderTextureFormats::Unknown;
+ else if (AreEqual(inFormat, "depth24stencil8"))
+ retval = qt3ds::render::NVRenderTextureFormats::Depth24Stencil8;
+ else {
+ if (AreEqual(inType, "ubyte")) {
+ if (AreEqual(inFormat, "rgb"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGB8;
+ else if (AreEqual(inFormat, "rgba"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ else if (AreEqual(inFormat, "alpha"))
+ retval = qt3ds::render::NVRenderTextureFormats::Alpha8;
+ else if (AreEqual(inFormat, "lum"))
+ retval = qt3ds::render::NVRenderTextureFormats::Luminance8;
+ else if (AreEqual(inFormat, "lum_alpha"))
+ retval = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8;
+ else if (AreEqual(inFormat, "rg"))
+ retval = qt3ds::render::NVRenderTextureFormats::RG8;
+ } else if (AreEqual(inType, "ushort")) {
+ if (AreEqual(inFormat, "rgb"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGB565;
+ else if (AreEqual(inFormat, "rgba"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGBA5551;
+ } else if (AreEqual(inType, "fp16")) {
+ if (AreEqual(inFormat, "rgba"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGBA16F;
+ else if (AreEqual(inFormat, "rg"))
+ retval = qt3ds::render::NVRenderTextureFormats::RG16F;
+ } else if (AreEqual(inType, "fp32")) {
+ if (AreEqual(inFormat, "rgba"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGBA32F;
+ else if (AreEqual(inFormat, "rg"))
+ retval = qt3ds::render::NVRenderTextureFormats::RG32F;
+ } else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported texture type %s,
+ // defaulting to RGBA8", inType );
+ }
+ }
+ return retval;
+ }
+
+ static inline qt3ds::render::NVRenderTextureMagnifyingOp::Enum
+ ConvertFilterToMagOp(const char8_t *inFilter)
+ {
+ if (AreEqual(inFilter, "linear"))
+ return qt3ds::render::NVRenderTextureMagnifyingOp::Linear;
+ if (IsTrivial(inFilter) || AreEqual(inFilter, "nearest"))
+ return qt3ds::render::NVRenderTextureMagnifyingOp::Nearest;
+ else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting to
+ // linear", inFilter );
+ return qt3ds::render::NVRenderTextureMagnifyingOp::Linear;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderTextureMinifyingOp::Enum
+ ConvertFilterToMinOp(const char8_t *inFilter)
+ {
+ // we make the decision based on the texture usage
+ if (AreEqual(inFilter, "linear"))
+ return qt3ds::render::NVRenderTextureMinifyingOp::Linear;
+ if (AreEqual(inFilter, "nearest"))
+ return qt3ds::render::NVRenderTextureMinifyingOp::Nearest;
+ if (AreEqual(inFilter, "linearMipmapLinear"))
+ return qt3ds::render::NVRenderTextureMinifyingOp::LinearMipmapLinear;
+ if (AreEqual(inFilter, "nearestMipmapNearest"))
+ return qt3ds::render::NVRenderTextureMinifyingOp::NearestMipmapNearest;
+ if (AreEqual(inFilter, "nearestMipmapLinear"))
+ return qt3ds::render::NVRenderTextureMinifyingOp::NearestMipmapLinear;
+ if (AreEqual(inFilter, "linearMipmapNearest"))
+ return qt3ds::render::NVRenderTextureMinifyingOp::LinearMipmapNearest;
+ else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting to
+ // linear", inFilter );
+ return qt3ds::render::NVRenderTextureMinifyingOp::Linear;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderTextureCoordOp::Enum
+ ConvertTextureCoordOp(const char8_t *inWrap)
+ {
+ if (IsTrivial(inWrap) || AreEqual(inWrap, "clamp"))
+ return qt3ds::render::NVRenderTextureCoordOp::ClampToEdge;
+ if (AreEqual(inWrap, "repeat"))
+ return qt3ds::render::NVRenderTextureCoordOp::Repeat;
+ else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported wrap type %s, defaulting to
+ // clamp", inWrap );
+ return qt3ds::render::NVRenderTextureCoordOp::ClampToEdge;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderTextureTypeValue::Enum
+ ConvertTextureType(const char8_t *inTexType)
+ {
+ // this usually comes from a MDL description file
+ if (IsTrivial(inTexType))
+ return qt3ds::render::NVRenderTextureTypeValue::Unknown;
+ if (AreEqual(inTexType, "environment"))
+ return qt3ds::render::NVRenderTextureTypeValue::Environment;
+ if (AreEqual(inTexType, "diffuse"))
+ return qt3ds::render::NVRenderTextureTypeValue::Diffuse;
+ if (AreEqual(inTexType, "specular"))
+ return qt3ds::render::NVRenderTextureTypeValue::Specular;
+ if (AreEqual(inTexType, "bump"))
+ return qt3ds::render::NVRenderTextureTypeValue::Bump;
+ if (AreEqual(inTexType, "displacement"))
+ return qt3ds::render::NVRenderTextureTypeValue::Displace;
+ if (AreEqual(inTexType, "shadow"))
+ return qt3ds::render::NVRenderTextureTypeValue::LightmapShadow;
+ if (AreEqual(inTexType, "emissive"))
+ return qt3ds::render::NVRenderTextureTypeValue::Emissive;
+ if (AreEqual(inTexType, "emissive_mask"))
+ return qt3ds::render::NVRenderTextureTypeValue::Emissive2;
+ else {
+ return qt3ds::render::NVRenderTextureTypeValue::Unknown;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderSrcBlendFunc::Enum
+ ConvertToSrcBlendFunc(const char8_t *inFilter)
+ {
+ if (AreEqual(inFilter, "SrcAlpha"))
+ return qt3ds::render::NVRenderSrcBlendFunc::SrcAlpha;
+ if (AreEqual(inFilter, "OneMinusSrcAlpha"))
+ return qt3ds::render::NVRenderSrcBlendFunc::OneMinusSrcAlpha;
+ if (AreEqual(inFilter, "One"))
+ return qt3ds::render::NVRenderSrcBlendFunc::One;
+ else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting to
+ // linear", inFilter );
+ return qt3ds::render::NVRenderSrcBlendFunc::One;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderDstBlendFunc::Enum
+ ConvertToDstBlendFunc(const char8_t *inFilter)
+ {
+ if (AreEqual(inFilter, "SrcAlpha"))
+ return qt3ds::render::NVRenderDstBlendFunc::SrcAlpha;
+ if (AreEqual(inFilter, "OneMinusSrcAlpha"))
+ return qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha;
+ if (AreEqual(inFilter, "One"))
+ return qt3ds::render::NVRenderDstBlendFunc::One;
+ else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting to
+ // linear", inFilter );
+ return qt3ds::render::NVRenderDstBlendFunc::One;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderState::Enum ConvertRenderState(const char8_t *inState)
+ {
+ if (AreEqual(inState, "Stencil"))
+ return qt3ds::render::NVRenderState::StencilTest;
+ else {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting to
+ // linear", inFilter );
+ return qt3ds::render::NVRenderState::StencilTest;
+ }
+ }
+
+ static inline qt3ds::render::NVRenderImageAccessType::Enum
+ ConvertToImageAccessType(const char8_t *inAccess)
+ {
+ if (AreEqual(inAccess, "read"))
+ return qt3ds::render::NVRenderImageAccessType::Read;
+ if (AreEqual(inAccess, "write"))
+ return qt3ds::render::NVRenderImageAccessType::Write;
+ if (AreEqual(inAccess, "readwrite"))
+ return qt3ds::render::NVRenderImageAccessType::ReadWrite;
+ else
+ QT3DS_ASSERT(false);
+
+ return qt3ds::render::NVRenderImageAccessType::ReadWrite;
+ }
+
+ static inline size_t GetTypeSize(const char8_t *inType)
+ {
+ if (AreEqual(inType, "uint"))
+ return sizeof(QT3DSU32);
+ else if (AreEqual(inType, "int"))
+ return sizeof(QT3DSI32);
+ else if (AreEqual(inType, "uvec4"))
+ return sizeof(QT3DSU32) * 4;
+ else
+ QT3DS_ASSERT(false);
+
+ return 1;
+ }
+
+ inline qt3ds::render::NVRenderBufferBindValues::Enum
+ ConvertFormatToBufferBindFlags(const char8_t *inFormat)
+ {
+ if (AreEqual(inFormat, "storage"))
+ return qt3ds::render::NVRenderBufferBindValues::Storage;
+ else if (AreEqual(inFormat, "indirect"))
+ return qt3ds::render::NVRenderBufferBindValues::Draw_Indirect;
+ else
+ QT3DS_ASSERT(false);
+
+ return qt3ds::render::NVRenderBufferBindValues::Unknown;
+ }
+
+ static inline void AppendShaderUniform(const char8_t *type, const char8_t *name,
+ eastl::string &shaderPrefix)
+ {
+ shaderPrefix.append("uniform ");
+ shaderPrefix.append(type);
+ shaderPrefix.append(" ");
+ shaderPrefix.append(name);
+ shaderPrefix.append(";\n");
+ }
+ static inline void AppendShaderCode(
+ const char8_t *inCode, SUICDMStr &ioStr,
+ eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> &inConvertBuffer)
+ {
+ qt3ds::foundation::ConvertUTF(inCode, 0, inConvertBuffer);
+ ioStr.append(inConvertBuffer);
+ }
+ void HideEffectProperty(CUICDMInstanceHandle inInstance, const char8_t *inParamName)
+ {
+ CUICDMMetaDataPropertyHandle theProp =
+ GetSpecificMetaDataProperty(inInstance, Intern(inParamName));
+ if (theProp.Valid()) {
+ SMetaDataPropertyInfo theInfo = GetMetaDataPropertyInfo(theProp);
+ SetMetaDataPropertyInfo(theProp, theInfo.m_Name, theInfo.m_FormalName,
+ theInfo.m_Description, theInfo.m_Usage, theInfo.m_CompleteType,
+ theInfo.m_DefaultValue, theInfo.m_MetaDataData,
+ theInfo.m_GroupName, true, theInfo.m_Animatable);
+ }
+ }
+ static inline void GetShaderName(const TCharStr &inObjectName,
+ const char8_t *inShaderSpecificName,
+ eastl::string &outShaderName)
+ {
+ outShaderName.clear();
+ qt3ds::foundation::ConvertUTF(inObjectName.c_str(), 0, outShaderName);
+ outShaderName.append(" - ");
+ outShaderName.append(inShaderSpecificName);
+ }
+
+ void LoadDynamicObjectProperties(IDOMReader &inStream, SMetaDataDynamicObjectImpl &ioObject,
+ CUICDMInstanceHandle inInstance, const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ eastl::string &shaderPrefix)
+ {
+ using namespace uic::render::dynamic;
+ ioObject.m_Properties.clear();
+ ioObject.ClearEnumValueNames();
+ IDOMReader::Scope __readerScope(inStream);
+ if (inStream.MoveToFirstChild("MetaData")) {
+ {
+ IDOMReader::Scope __readerScope(inStream);
+ LoadInstance(inStream, inInstance, inObjectName, outWarnings);
+ }
+
+ vector<CUICDMMetaDataPropertyHandle> theProperties;
+ GetSpecificMetaDataProperties(inInstance, theProperties);
+ size_t propIdx = 0, propEnd = theProperties.size();
+ for (bool success = inStream.MoveToFirstChild("Property"); success && propIdx < propEnd;
+ success = inStream.MoveToNextSibling("Property"), ++propIdx) {
+ ioObject.m_Properties.push_back();
+ SPropertyDefinition &theNewDefinition = ioObject.m_Properties.back();
+ SMetaDataPropertyInfo theInfo(GetMetaDataPropertyInfo(theProperties[propIdx]));
+ theNewDefinition.m_Name =
+ m_StringTable.GetRenderStringTable().RegisterStr(theInfo.m_Name.c_str());
+ const char8_t *xmlName;
+ inStream.Att("name", xmlName);
+ if (AreEqual(xmlName, theNewDefinition.m_Name.c_str())) {
+ switch (theInfo.GetDataType()) {
+ case DataModelDataType::Bool:
+ theNewDefinition.m_DataType =
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool;
+ AppendShaderUniform("bool", theNewDefinition.m_Name.c_str(), shaderPrefix);
+ break;
+ case DataModelDataType::Long:
+ theNewDefinition.m_DataType = qt3ds::render::NVRenderShaderDataTypes::QT3DSI32;
+ AppendShaderUniform("int", theNewDefinition.m_Name.c_str(), shaderPrefix);
+ break;
+ case DataModelDataType::Float2:
+ theNewDefinition.m_DataType = qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2;
+ AppendShaderUniform("vec2", theNewDefinition.m_Name.c_str(), shaderPrefix);
+ break;
+ case DataModelDataType::Float3:
+ theNewDefinition.m_DataType = qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3;
+ AppendShaderUniform("vec3", theNewDefinition.m_Name.c_str(), shaderPrefix);
+ break;
+ case DataModelDataType::String:
+ if (theInfo.m_CompleteType == CompleteMetaDataType::Texture) {
+ theNewDefinition.m_DataType =
+ qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr;
+ const char8_t *filter = "linear", *minFilter = "linear",
+ *clamp = "clamp", *usage = "", *path = "";
+ if (inStream.Att("filter", filter))
+ theNewDefinition.m_MagFilterOp = ConvertFilterToMagOp(filter);
+ if (inStream.Att("minfilter", minFilter))
+ theNewDefinition.m_MinFilterOp = ConvertFilterToMinOp(minFilter);
+ if (inStream.Att("clamp", clamp))
+ theNewDefinition.m_CoordOp = ConvertTextureCoordOp(clamp);
+ if (inStream.Att("usage", usage))
+ theNewDefinition.m_TexUsageType = ConvertTextureType(usage);
+ if (inStream.Att("default", path)) {
+ TDataStrPtr theDataStr(
+ theInfo.m_DefaultValue.getData<TDataStrPtr>());
+ theNewDefinition.m_ImagePath =
+ m_StringTable.GetRenderStringTable().RegisterStr(
+ theDataStr->GetData());
+ }
+
+ // Output macro so we can change the set of variables used for this
+ // independent of the
+ // meta data system.
+ shaderPrefix.append("SNAPPER_SAMPLER2D(");
+ shaderPrefix.append(theNewDefinition.m_Name.c_str());
+ shaderPrefix.append(", ");
+ shaderPrefix.append(theNewDefinition.m_Name.c_str());
+ shaderPrefix.append(", ");
+ shaderPrefix.append(filter);
+ shaderPrefix.append(", ");
+ shaderPrefix.append(clamp);
+ shaderPrefix.append(", ");
+ shaderPrefix.append("false )\n");
+ } else if (theInfo.m_CompleteType == CompleteMetaDataType::StringList) {
+ theNewDefinition.m_DataType =
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSI32;
+ const TMetaDataStringList &theList =
+ UICDM::get<TMetaDataStringList>(theInfo.m_MetaDataData);
+ ioObject.m_EnumValueNames.push_back(
+ new eastl::vector<qt3ds::foundation::CRegisteredString>());
+ eastl::vector<qt3ds::foundation::CRegisteredString> &theBack =
+ *ioObject.m_EnumValueNames.back();
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)theList.size(); idx < end; ++idx)
+ theBack.push_back(m_StringTable.GetRenderStringTable().RegisterStr(
+ theList[idx].c_str()));
+ theNewDefinition.m_EnumValueNames = VecToCRef(theBack);
+ theNewDefinition.m_IsEnumProperty = true;
+ AppendShaderUniform("int", theNewDefinition.m_Name.c_str(),
+ shaderPrefix);
+ } else if (theInfo.m_CompleteType == CompleteMetaDataType::Image2D) {
+ theNewDefinition.m_DataType =
+ qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr;
+ const char8_t *format = "", *binding = "", *access = "readonly";
+ shaderPrefix.append("layout(");
+ inStream.Att("format", format);
+ shaderPrefix.append(format);
+ if (inStream.Att("binding", binding)) {
+ shaderPrefix.append(", binding = ");
+ shaderPrefix.append(binding);
+ }
+ shaderPrefix.append(") ");
+
+ // if we have format layout we cannot set an additional access qualifier
+ if (inStream.Att("access", access) && !AreEqual(format, ""))
+ shaderPrefix.append(access);
+
+ shaderPrefix.append(" uniform image2D ");
+ shaderPrefix.append(theNewDefinition.m_Name.c_str());
+ shaderPrefix.append(";\n");
+ } else if (theInfo.m_CompleteType == CompleteMetaDataType::Buffer) {
+ theNewDefinition.m_DataType =
+ qt3ds::render::NVRenderShaderDataTypes::NVRenderDataBufferPtr;
+ const char8_t *align = "std140", *usage = "storage", *binding = "",
+ *format = "float";
+ shaderPrefix.append("layout(");
+
+ inStream.Att("format", format);
+ inStream.Att("usage", usage);
+ if (AreEqual(usage, "storage")) {
+ inStream.Att("align", align);
+ shaderPrefix.append(align);
+
+ if (inStream.Att("binding", binding)) {
+ shaderPrefix.append(", binding = ");
+ shaderPrefix.append(binding);
+ }
+
+ shaderPrefix.append(") ");
+
+ shaderPrefix.append("buffer ");
+ shaderPrefix.append(theNewDefinition.m_Name.c_str());
+ shaderPrefix.append("\n{ \n");
+ shaderPrefix.append(format);
+ shaderPrefix.append(" ");
+ shaderPrefix.append(theNewDefinition.m_Name.c_str());
+ shaderPrefix.append("_data[]; \n};\n");
+ } else {
+ // currently we only handle storage counters
+ QT3DS_ASSERT(false);
+ }
+ }
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ // Fallthrough intentional
+ case DataModelDataType::Float:
+ theNewDefinition.m_DataType = qt3ds::render::NVRenderShaderDataTypes::QT3DSF32;
+ AppendShaderUniform("float", theNewDefinition.m_Name.c_str(), shaderPrefix);
+ break;
+ }
+ } else {
+ // It is conceivable that we not every property tag gets parsed into a property.
+ QT3DS_ASSERT(false);
+ // So we will bump to the next item and try again.
+ --propIdx;
+ }
+ }
+ }
+ }
+
+ void LoadDynamicObjectShaders(IDOMReader &inStream, SMetaDataDynamicObjectImpl &ioObject,
+ eastl::string &shaderPrefix, const TCharStr &inObjectName)
+ {
+ eastl::string theShaderNameStr;
+ eastl::string theShaderTypeStr;
+ eastl::string theShaderVersionStr;
+ {
+ IDOMReader::Scope __readerScope(inStream);
+ eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> theConvertBuffer;
+ if (inStream.MoveToFirstChild("Shaders")) {
+ const char8_t *globalShared = "";
+ const char8_t *globalVertexShared = "";
+ const char8_t *globalFragmentShared = "";
+ inStream.ChildValue("Shared", globalShared);
+ inStream.ChildValue("VertexShaderShared", globalVertexShared);
+ inStream.ChildValue("FragmentShaderShared", globalFragmentShared);
+
+ inStream.Att("type", theShaderTypeStr); // can be empty
+ inStream.Att("version", theShaderVersionStr); // can be empty
+
+ for (bool success = inStream.MoveToFirstChild(); success;
+ success = inStream.MoveToNextSibling()) {
+ IDOMReader::Scope __shaderScope(inStream);
+ const char8_t *elemName = inStream.GetNarrowElementName();
+ // If this is neither a compute shader nor a normal shader, go on and ignore
+ // element.
+ if (!(AreEqual(elemName, "Shader") || AreEqual(elemName, "ComputeShader")))
+ continue;
+
+ ioObject.m_Shaders.push_back();
+ SMetaDataShader &theShader = ioObject.m_Shaders.back();
+
+ qt3ds::foundation::ConvertUTF(theShaderTypeStr.c_str(), theShaderTypeStr.size(),
+ theShader.m_Type);
+ qt3ds::foundation::ConvertUTF(theShaderVersionStr.c_str(),
+ theShaderVersionStr.size(), theShader.m_Version);
+ const char8_t *theName = "";
+ char8_t theITOABuffer[64] = { 0 };
+ if (!inStream.Att("name", theName)) {
+ sprintf(theITOABuffer, "%d", (int)ioObject.m_Shaders.size() - 1);
+ theName = theITOABuffer;
+ }
+ GetShaderName(inObjectName, theName, theShaderNameStr);
+ qt3ds::foundation::ConvertUTF(theShaderNameStr.c_str(), theShaderNameStr.size(),
+ theShader.m_Name);
+
+ if (AreEqual(elemName, "Shader")) {
+ const char8_t *shaderShared = "";
+ inStream.ChildValue("Shared", shaderShared);
+ const char8_t *vertexCode = "";
+ inStream.ChildValue("VertexShader", vertexCode);
+ if (IsTrivial(vertexCode))
+ vertexCode = "void vert(){}";
+ const char8_t *fragmentCode = "void frag(){}";
+ inStream.ChildValue("FragmentShader", fragmentCode);
+ if (IsTrivial(fragmentCode))
+ fragmentCode = "void frag(){}";
+ const char8_t *geomCode = "";
+ inStream.ChildValue("GeometryShader", geomCode);
+
+ AppendShaderCode(shaderPrefix.c_str(), theShader.m_Code, theConvertBuffer);
+ AppendShaderCode(globalShared, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode(shaderShared, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode("\n#ifdef VERTEX_SHADER\n", theShader.m_Code,
+ theConvertBuffer);
+ AppendShaderCode(globalVertexShared, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode(vertexCode, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode("\n#endif\n", theShader.m_Code, theConvertBuffer);
+ if (!IsTrivial(geomCode)) {
+ AppendShaderCode("\n#ifdef USER_GEOMETRY_SHADER\n", theShader.m_Code,
+ theConvertBuffer);
+ AppendShaderCode(geomCode, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode("\n#endif\n", theShader.m_Code, theConvertBuffer);
+ theShader.m_HasGeomShader = true;
+ }
+ AppendShaderCode("\n#ifdef FRAGMENT_SHADER\n", theShader.m_Code,
+ theConvertBuffer);
+ AppendShaderCode(globalFragmentShared, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode(fragmentCode, theShader.m_Code, theConvertBuffer);
+ AppendShaderCode("\n#endif\n", theShader.m_Code, theConvertBuffer);
+ } else if (AreEqual(elemName, "ComputeShader")) {
+ const char8_t *shaderCode = "";
+ inStream.Value(shaderCode);
+ theShader.m_IsComputeShader = true;
+ AppendShaderCode(shaderCode, theShader.m_Code, theConvertBuffer);
+ }
+ }
+ }
+ }
+ }
+
+ static size_t Align(size_t inValue)
+ {
+ if (inValue % 4)
+ return inValue + (4 - (inValue % 4));
+ return inValue;
+ }
+
+ static uic::render::dynamic::SDepthStencilFlags ParseDepthStencilFlags(const char8_t *inFlags)
+ {
+ eastl::string parseStr(inFlags);
+ eastl::string tokenStr;
+ uic::render::dynamic::SDepthStencilFlags retval;
+ for (uint32_t pos = parseStr.find('|'); parseStr.empty() == false;
+ pos = parseStr.find('|')) {
+ if (pos != eastl::string::npos) {
+ tokenStr = parseStr.substr(pos);
+ parseStr.erase(parseStr.begin(), parseStr.begin() + pos + 1);
+ } else {
+ tokenStr = parseStr;
+ parseStr.clear();
+ }
+ if (AreEqual(tokenStr.c_str(), "clear-stencil"))
+ retval |= uic::render::dynamic::DepthStencilFlagValues::ClearStencil;
+ if (AreEqual(tokenStr.c_str(), "clear-depth"))
+ retval |= uic::render::dynamic::DepthStencilFlagValues::ClearDepth;
+ }
+ return retval;
+ }
+
+ static qt3ds::render::NVRenderBoolOp::Enum ParseBoolOp(const char8_t *inOp)
+ {
+ if (AreEqual(inOp, "never"))
+ return qt3ds::render::NVRenderBoolOp::Never;
+ if (AreEqual(inOp, "less"))
+ return qt3ds::render::NVRenderBoolOp::Less;
+ if (AreEqual(inOp, "less-than-or-equal"))
+ return qt3ds::render::NVRenderBoolOp::LessThanOrEqual;
+ if (AreEqual(inOp, "equal"))
+ return qt3ds::render::NVRenderBoolOp::Equal;
+ if (AreEqual(inOp, "not-equal"))
+ return qt3ds::render::NVRenderBoolOp::NotEqual;
+ if (AreEqual(inOp, "greater"))
+ return qt3ds::render::NVRenderBoolOp::Greater;
+ if (AreEqual(inOp, "greater-than-or-equal"))
+ return qt3ds::render::NVRenderBoolOp::GreaterThanOrEqual;
+ if (AreEqual(inOp, "always"))
+ return qt3ds::render::NVRenderBoolOp::AlwaysTrue;
+
+ QT3DS_ASSERT(false);
+ return qt3ds::render::NVRenderBoolOp::Unknown;
+ }
+
+ static qt3ds::render::NVRenderStencilOp::Enum ParseStencilOp(const char8_t *inOp)
+ {
+
+ if (AreEqual(inOp, "keep"))
+ return qt3ds::render::NVRenderStencilOp::Keep;
+ if (AreEqual(inOp, "zero"))
+ return qt3ds::render::NVRenderStencilOp::Zero;
+ if (AreEqual(inOp, "replace"))
+ return qt3ds::render::NVRenderStencilOp::Replace;
+ if (AreEqual(inOp, "increment"))
+ return qt3ds::render::NVRenderStencilOp::Increment;
+ if (AreEqual(inOp, "increment-wrap"))
+ return qt3ds::render::NVRenderStencilOp::IncrementWrap;
+ if (AreEqual(inOp, "decrement"))
+ return qt3ds::render::NVRenderStencilOp::Decrement;
+ if (AreEqual(inOp, "decrement-wrap"))
+ return qt3ds::render::NVRenderStencilOp::DecrementWrap;
+ if (AreEqual(inOp, "invert"))
+ return qt3ds::render::NVRenderStencilOp::Invert;
+
+ QT3DS_ASSERT(false);
+ return qt3ds::render::NVRenderStencilOp::Unknown;
+ }
+
+ // Reloads an effect if one is already loaded so we can replace the existing effect definition
+ void LoadEffectXML(IDOMReader &inStream, CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ const TCharStr &inSourcePath) override
+ {
+ using namespace uic::render::dynamic;
+ std::pair<TEffectMap::iterator, bool> theInserter =
+ m_EffectMap.insert(std::make_pair(Intern(inObjectName), SMetaDataEffectImpl()));
+ /*if ( inStream.MoveToFirstChild( "Effect" ) == false )
+ {
+ outWarnings.push_back( SMetaDataLoadWarning( MetaDataLoadWarningType::Unknown,
+ MetaDataLoadWarningMessage::GeneralError, L"File doesn't appear to be an effect xml file,
+ missing top level Effect tag" ) );
+ return;
+ }*/
+ eastl::string shaderPrefix = "#include \"effect.glsllib\"\n";
+
+ SMetaDataEffectImpl &theEffect = theInserter.first->second;
+ m_ObjectName = inObjectName;
+ theEffect.m_Name = inObjectName;
+ theEffect.m_SourcePath = inSourcePath;
+ theEffect.ClearEffectCommands();
+ LoadDynamicObjectProperties(inStream, theEffect, inInstance, inObjectName, outWarnings,
+ shaderPrefix);
+ theEffect.m_Shaders.clear();
+ LoadDynamicObjectShaders(inStream, theEffect, shaderPrefix, inObjectName);
+ eastl::string theShaderNameStr;
+ {
+ IDOMReader::Scope __readerScope(inStream);
+ if (inStream.MoveToFirstChild("Passes")) {
+ for (bool success = inStream.MoveToFirstChild(); success;
+ success = inStream.MoveToNextSibling()) {
+ IDOMReader::Scope __passScope(inStream);
+ if (AreEqual("Pass", inStream.GetNarrowElementName())) {
+ bool drawIndirect = false;
+ const char8_t *shader = "", *input = "[source]", *output = "[dest]",
+ *outputFormat = "rgba";
+ inStream.Att("shader", shader);
+ inStream.Att("input", input);
+ inStream.Att("output", output);
+ // this is only for the final output of the effect
+ inStream.Att("format", outputFormat);
+ qt3ds::render::NVRenderTextureFormats::Enum theOutputFormat =
+ ConvertTypeAndFormatToTextureFormat("ubyte", outputFormat);
+ if (AreEqual(output, "[dest]") || IsTrivial(output))
+ theEffect.m_EffectCommands.push_back(new SBindTarget(theOutputFormat));
+ else
+ theEffect.m_EffectCommands.push_back(new SBindBuffer(
+ m_StringTable.GetRenderStringTable().RegisterStr(output), false));
+ GetShaderName(inObjectName, shader, theShaderNameStr);
+ theEffect.m_EffectCommands.push_back(
+ new SBindShader(m_StringTable.GetRenderStringTable().RegisterStr(
+ theShaderNameStr.c_str())));
+ theEffect.m_EffectCommands.push_back(new SApplyInstanceValue());
+ if (AreEqual(input, "[source]") || IsTrivial(input))
+ theEffect.m_EffectCommands.push_back(new SApplyBufferValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(""),
+ m_StringTable.GetRenderStringTable().RegisterStr("")));
+ else
+ theEffect.m_EffectCommands.push_back(new SApplyBufferValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(input),
+ m_StringTable.GetRenderStringTable().RegisterStr("")));
+ for (bool bufParam = inStream.MoveToFirstChild(); bufParam;
+ bufParam = inStream.MoveToNextSibling()) {
+ if (AreEqual("BufferInput", inStream.GetNarrowElementName())) {
+ const char8_t *param = "";
+ const char8_t *value = "";
+ inStream.Att("param", param);
+ inStream.Att("value", value);
+ if (AreEqual("[source]", value))
+ value = "";
+ theEffect.m_EffectCommands.push_back(new SApplyBufferValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(value),
+ m_StringTable.GetRenderStringTable().RegisterStr(param)));
+ HideEffectProperty(inInstance, param);
+ } else if (AreEqual("DepthInput", inStream.GetNarrowElementName())) {
+ const char8_t *param = "";
+ inStream.Att("param", param);
+ theEffect.m_EffectCommands.push_back(new SApplyDepthValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(param)));
+ HideEffectProperty(inInstance, param);
+ } else if (AreEqual("ImageInput", inStream.GetNarrowElementName())) {
+ bool useAsTexture = false;
+ bool needSync = false;
+ const char8_t *param = "";
+ const char8_t *value = "";
+ const char8_t *usage = "";
+ const char8_t *sync = "";
+ inStream.Att("param", param);
+ inStream.Att("value", value);
+ if (AreEqual("[source]", value))
+ value = "";
+ inStream.Att("usage", usage);
+ if (AreEqual("texture", usage))
+ useAsTexture = true;
+ inStream.Att("sync", sync);
+ if (AreEqual("true", sync))
+ needSync = true;
+
+ theEffect.m_EffectCommands.push_back(new SApplyImageValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(value),
+ m_StringTable.GetRenderStringTable().RegisterStr(param),
+ useAsTexture, needSync));
+ HideEffectProperty(inInstance, param);
+ } else if (AreEqual("DataBufferInput",
+ inStream.GetNarrowElementName())) {
+ const char8_t *param = "";
+ const char8_t *usage = "";
+ inStream.Att("param", param);
+ inStream.Att("usage", usage);
+ qt3ds::render::NVRenderBufferBindValues::Enum bufType =
+ ConvertFormatToBufferBindFlags(usage);
+
+ // check if we using an indirect buffer for drawing
+ if (bufType == qt3ds::render::NVRenderBufferBindValues::Draw_Indirect)
+ drawIndirect = true;
+
+ theEffect.m_EffectCommands.push_back(new SApplyDataBufferValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(param),
+ bufType));
+ HideEffectProperty(inInstance, param);
+ } else if (AreEqual("SetParam", inStream.GetNarrowElementName())) {
+ const char8_t *name = "";
+ inStream.Att("name", name);
+ const char8_t *value = "";
+ inStream.Att("value", value);
+ // find the param and the type.
+ qt3ds::foundation::CRegisteredString propName =
+ m_StringTable.GetRenderStringTable().RegisterStr(name);
+ uic::render::dynamic::SPropertyDefinition *theDefinition = NULL;
+ for (uint32_t propIdx = 0, propEnd = theEffect.m_Properties.size();
+ propIdx < propEnd && theDefinition == NULL; ++propIdx) {
+ if (theEffect.m_Properties[propIdx].m_Name == propName)
+ theDefinition = &theEffect.m_Properties[propIdx];
+ }
+ if (theDefinition != NULL) {
+ // Hack it for now because the shader datatypes don't have a
+ // built in sizeof operator.
+ QT3DSU32 valueSize = 4;
+ qt3ds::render::NVRenderShaderDataTypes::Enum theDataType =
+ theDefinition->m_DataType;
+ size_t allocSize = sizeof(SApplyValue) + valueSize;
+ QT3DSU8 *theCommandData = (QT3DSU8 *)malloc(allocSize);
+ QT3DSU8 *theValueData = theCommandData + sizeof(SApplyValue);
+ new (theCommandData) SApplyValue(propName, theDataType);
+ SApplyValue *theCommand =
+ reinterpret_cast<SApplyValue *>(theCommandData);
+ switch (theDataType) {
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool: {
+ bool &target = *reinterpret_cast<bool *>(theValueData);
+ qt3ds::foundation::StringConversion<bool>().StrTo(value,
+ target);
+ } break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32: {
+ QT3DSI32 &target = *reinterpret_cast<QT3DSI32 *>(theValueData);
+ qt3ds::foundation::StringConversion<QT3DSI32>().StrTo(value,
+ target);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ // Fallthrough intentional
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32: {
+ QT3DSF32 &target = *reinterpret_cast<QT3DSF32 *>(theValueData);
+ qt3ds::foundation::StringConversion<QT3DSF32>().StrTo(value,
+ target);
+ } break;
+ }
+ theCommand->m_Value = NVDataRef<QT3DSU8>(theValueData, valueSize);
+ theEffect.m_EffectCommands.push_back(theCommand);
+ }
+ } else if (AreEqual("Blending", inStream.GetNarrowElementName())) {
+ const char8_t *theSrcBlendFuncStr = "", *theDestBlendFuncStr = "";
+ inStream.Att("source", theSrcBlendFuncStr);
+ inStream.Att("dest", theDestBlendFuncStr);
+
+ qt3ds::render::NVRenderSrcBlendFunc::Enum theSrcBlendFunc =
+ ConvertToSrcBlendFunc(theSrcBlendFuncStr);
+ qt3ds::render::NVRenderDstBlendFunc::Enum theDstBlendFuc =
+ ConvertToDstBlendFunc(theDestBlendFuncStr);
+
+ // this will setup blending
+ theEffect.m_EffectCommands.push_back(
+ new SApplyBlending(theSrcBlendFunc, theDstBlendFuc));
+ } else if (AreEqual("RenderState", inStream.GetNarrowElementName())) {
+ const char8_t *name = "";
+ inStream.Att("name", name);
+ const char8_t *value = "";
+ inStream.Att("value", value);
+ // find the param and the type.
+ bool theStateEnable = false;
+ qt3ds::render::NVRenderState::Enum theState = ConvertRenderState(name);
+ if (AreEqual("true", value))
+ theStateEnable = true;
+
+ // this will setup blending
+ theEffect.m_EffectCommands.push_back(
+ new SApplyRenderState(theState, theStateEnable));
+ } else if (AreEqual("DepthStencil", inStream.GetNarrowElementName())) {
+ const char8_t *bufferName = "";
+ inStream.Att("buffer", bufferName);
+ QT3DSU32 stencilvalue = 0;
+ inStream.Att("reference", stencilvalue);
+ const char8_t *flags = "";
+ inStream.Att("flags", flags);
+ QT3DSU32 mask = QT3DS_MAX_U32;
+ inStream.Att("mask", mask);
+ qt3ds::render::NVRenderBoolOp::Enum stencilFunction =
+ qt3ds::render::NVRenderBoolOp::Equal;
+ qt3ds::render::NVRenderStencilOp::Enum stencilFailOperation =
+ qt3ds::render::NVRenderStencilOp::Keep;
+ qt3ds::render::NVRenderStencilOp::Enum depthPass =
+ qt3ds::render::NVRenderStencilOp::Keep;
+ qt3ds::render::NVRenderStencilOp::Enum depthFail =
+ qt3ds::render::NVRenderStencilOp::Keep;
+ const char8_t *temp;
+ if (inStream.Att("stencil-fail", temp))
+ stencilFailOperation = ParseStencilOp(temp);
+ if (inStream.Att("depth-pass", temp))
+ depthPass = ParseStencilOp(temp);
+ if (inStream.Att("depth-fail", temp))
+ depthFail = ParseStencilOp(temp);
+ if (inStream.Att("stencil-function", temp))
+ stencilFunction = ParseBoolOp(temp);
+
+ uic::render::dynamic::SDepthStencilFlags flagValues =
+ ParseDepthStencilFlags(flags);
+ theEffect.m_EffectCommands.push_back(new SDepthStencil(
+ m_StringTable.GetRenderStringTable().RegisterStr(bufferName),
+ flagValues, stencilFailOperation, depthPass, depthFail,
+ stencilFunction, stencilvalue, mask));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ theEffect.m_EffectCommands.push_back(new SRender(drawIndirect));
+ } else if (AreEqual("Buffer", inStream.GetNarrowElementName())
+ || AreEqual("Image", inStream.GetNarrowElementName())) {
+ SAllocateBufferFlags theFlags;
+ const char8_t *theLifetimeStr = "", *theType = "", *theFormat = "",
+ *theFilter = "", *theWrap = "", *theName = "";
+ QT3DSF32 theSize = 1.0f;
+ bool isImage = AreEqual("Image", inStream.GetNarrowElementName());
+ inStream.Att("name", theName);
+ inStream.Att("lifetime", theLifetimeStr);
+ inStream.Att("type", theType);
+ inStream.Att("format", theFormat);
+ inStream.Att("filter", theFilter);
+ inStream.Att("wrap", theWrap);
+ inStream.Att("size", theSize);
+ // Clamp the size to valid amounts
+ if (theSize <= 0)
+ theSize = 1.0f;
+ if (theSize > 1.0f)
+ theSize = 1.0f;
+ if (AreEqual(theLifetimeStr, "scene"))
+ theFlags.SetSceneLifetime(true);
+ qt3ds::render::NVRenderTextureFormats::Enum theTexFormat =
+ ConvertTypeAndFormatToTextureFormat(theType, theFormat);
+ qt3ds::render::NVRenderTextureMagnifyingOp::Enum theMagOp =
+ ConvertFilterToMagOp(theFilter);
+ qt3ds::render::NVRenderTextureCoordOp::Enum theCoordOp =
+ ConvertTextureCoordOp(theWrap);
+ if (*theName == 0) {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Buffer is missing its
+ // name" );
+ } else if (isImage) {
+ const char8_t *temp;
+ qt3ds::render::NVRenderImageAccessType::Enum theAccess =
+ qt3ds::render::NVRenderImageAccessType::ReadWrite;
+ if (inStream.Att("access", temp))
+ theAccess = ConvertToImageAccessType(temp);
+
+ theEffect.m_EffectCommands.push_back(new SAllocateImage(
+ m_StringTable.GetRenderStringTable().RegisterStr(theName),
+ theTexFormat, theMagOp, theCoordOp, theSize, theFlags, theAccess));
+ } else {
+ theEffect.m_EffectCommands.push_back(new SAllocateBuffer(
+ m_StringTable.GetRenderStringTable().RegisterStr(theName),
+ theTexFormat, theMagOp, theCoordOp, theSize, theFlags));
+ }
+ } else if (AreEqual("DataBuffer", inStream.GetNarrowElementName())) {
+ SAllocateBufferFlags theFlags;
+ const char8_t *theLifetimeStr = "", *theType = "", *theWrapName = "",
+ *theWrapType = "", *theFormat = "", *theName = "";
+ QT3DSF32 theSize = 1.0f;
+ qt3ds::render::NVRenderBufferBindValues::Enum bufType,
+ wrapBufType = qt3ds::render::NVRenderBufferBindValues::Unknown;
+
+ inStream.Att("name", theName);
+ inStream.Att("lifetime", theLifetimeStr);
+ inStream.Att("type", theType);
+ inStream.Att("format", theFormat);
+ inStream.Att("size", theSize);
+ if (AreEqual(theLifetimeStr, "scene"))
+ theFlags.SetSceneLifetime(true);
+ bufType = ConvertFormatToBufferBindFlags(theType);
+
+ if (inStream.Att("wrapType", theWrapType)) {
+ wrapBufType = ConvertFormatToBufferBindFlags(theWrapType);
+ inStream.Att("wrapName", theWrapName);
+ if (*theWrapName == 0)
+ QT3DS_ASSERT(false);
+ }
+
+ theSize *= GetTypeSize(theFormat);
+
+ if (theSize <= 0)
+ theSize = 1.0f;
+
+ if (*theName == 0) {
+ QT3DS_ASSERT(false);
+ } else {
+ theEffect.m_EffectCommands.push_back(new SAllocateDataBuffer(
+ m_StringTable.GetRenderStringTable().RegisterStr(theName), bufType,
+ m_StringTable.GetRenderStringTable().RegisterStr(theWrapName),
+ wrapBufType, theSize, theFlags));
+ }
+ } else {
+ QT3DS_ASSERT(false); // Unrecognized effect passes member.
+ }
+ }
+
+ } else {
+ if (theEffect.m_Shaders.size()) {
+ // Create the minimal set of commands that we could run the first shader with.
+ theEffect.m_EffectCommands.push_back(new SBindTarget());
+ theEffect.m_EffectCommands.push_back(
+ new SBindShader(m_StringTable.GetRenderStringTable().RegisterStr(
+ theEffect.m_Shaders[0].m_Name.c_str())));
+ theEffect.m_EffectCommands.push_back(new SApplyInstanceValue());
+ theEffect.m_EffectCommands.push_back(new SRender(false));
+ }
+ }
+ }
+ }
+
+ bool LoadEffectXMLFromSourcePath(const char *inSourcePath,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) override
+ {
+ std::shared_ptr<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_DataCore->GetStringTablePtr()));
+ UICDM::SDOMElement *theElem = CDOMSerializer::Read(*theFactory, inStream, NULL);
+ if (theElem != NULL) {
+ std::shared_ptr<IDOMReader> theReader(
+ IDOMReader::CreateDOMReader(*theElem, m_DataCore->GetStringTablePtr(), theFactory));
+ LoadEffectXML(*theReader, inInstance, inObjectName, outWarnings,
+ TCharStr(Intern(inSourcePath)));
+ return true;
+ }
+ return false;
+ }
+
+ Option<SMetaDataEffect> GetEffectBySourcePath(const char *inSourcePath) override
+ {
+ QDir sourcePath = QDir::cleanPath(QString(inSourcePath));
+ for (TEffectMap::iterator iter = m_EffectMap.begin(), end = m_EffectMap.end(); iter != end;
+ ++iter) {
+ QDir effectPath = QDir::cleanPath(QString::fromWCharArray(
+ iter->second.m_SourcePath.wide_str()));
+ if (effectPath == sourcePath)
+ return iter->second.ToEffect();
+ }
+ return Empty();
+ }
+
+ void LoadMaterialInstance(const char *inShaderFile, CUICDMInstanceHandle inInstance,
+ const TCharStr &inName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) override
+ {
+ QString shaderFile(inShaderFile);
+ if (shaderFile.endsWith(".material")) {
+ LoadMaterialClassFromSourcePath(inShaderFile, inInstance, inName, outWarnings,
+ inStream);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ bool IsMaterialClassRegistered(const char *inName) override
+ {
+ return m_CustomMaterials.find(Intern(inName)) != m_CustomMaterials.end();
+ }
+
+ void LoadMaterialClassXML(IDOMReader &inStream, CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ const TCharStr &inSourcePath) override
+ {
+ using namespace uic::render::dynamic;
+
+ std::pair<TCustomMaterialMap::iterator, bool> theInserter = m_CustomMaterials.insert(
+ std::make_pair(Intern(inObjectName), SMetaDataCustomMaterialImpl()));
+ /*if ( inStream.MoveToFirstChild( "Effect" ) == false )
+ {
+ outWarnings.push_back( SMetaDataLoadWarning( MetaDataLoadWarningType::Unknown,
+ MetaDataLoadWarningMessage::GeneralError, L"File doesn't appear to be an effect xml file,
+ missing top level Effect tag" ) );
+ return;
+ }*/
+ eastl::string shaderPrefix = "#include \"customMaterial.glsllib\"\n";
+
+ SMetaDataCustomMaterialImpl &theMaterial = theInserter.first->second;
+ m_ObjectName = inObjectName;
+ theMaterial.m_Name = inObjectName;
+ theMaterial.m_SourcePath = inSourcePath;
+ theMaterial.m_HasTransparency = false;
+ theMaterial.m_HasRefraction = false;
+ theMaterial.m_AlwaysDirty = false;
+ theMaterial.m_ShaderKey = 0;
+ theMaterial.m_LayerCount = 0;
+ inStream.Att("always-dirty", theMaterial.m_AlwaysDirty);
+ LoadDynamicObjectProperties(inStream, theMaterial, inInstance, inObjectName, outWarnings,
+ shaderPrefix);
+ LoadDynamicObjectShaders(inStream, theMaterial, shaderPrefix, inObjectName);
+
+ // currently single pass shader only
+ if (theMaterial.m_Shaders.size()) {
+ eastl::string theShaderNameStr;
+
+ // in Passes we store additional render commands
+ IDOMReader::Scope __readerScope(inStream);
+ if (inStream.MoveToFirstChild("Passes")) {
+ for (bool success = inStream.MoveToFirstChild(); success;
+ success = inStream.MoveToNextSibling()) {
+ IDOMReader::Scope __passScope(inStream);
+ if (AreEqual("Pass", inStream.GetNarrowElementName())) {
+ const char8_t *typeStr;
+ if (!inStream.UnregisteredAtt("type", typeStr))
+ typeStr = "render";
+ if (AreEqual(typeStr, "render")) {
+ const char8_t *shader = "", *input = "[source]", *output = "[dest]",
+ *outputFormat = "rgba", *clear = "";
+ bool needsClear = false;
+ inStream.Att("shader", shader);
+ inStream.Att("input", input);
+ inStream.Att("output", output);
+ // for multi pass materials
+ inStream.Att("clear", clear);
+ if (AreEqual("true", clear))
+ needsClear = true;
+
+ GetShaderName(inObjectName, shader, theShaderNameStr);
+ // this is only for the final output of the effect
+ inStream.Att("format", outputFormat);
+ qt3ds::render::NVRenderTextureFormats::Enum theOutputFormat =
+ ConvertTypeAndFormatToTextureFormat("ubyte", outputFormat);
+
+ if (AreEqual(output, "[dest]") || IsTrivial(output)) {
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SBindTarget(theOutputFormat));
+ } else
+ theMaterial.m_CustomerMaterialCommands.push_back(new SBindBuffer(
+ m_StringTable.GetRenderStringTable().RegisterStr(output),
+ needsClear));
+
+ // add shader to command stream
+ qt3ds::render::CRegisteredString theShaderName;
+ if (!IsTrivial(shader)) {
+ for (QT3DSU32 idx = 0, end = theMaterial.m_Shaders.size();
+ idx < end && theShaderName.IsValid() == false; ++idx) {
+ qt3ds::render::CRegisteredString thePossibleNameStr =
+ m_StringTable.GetRenderStringTable().RegisterStr(
+ theMaterial.m_Shaders[idx].m_Name.c_str());
+ if (AreEqual(thePossibleNameStr.c_str(),
+ theShaderNameStr.c_str()))
+ theShaderName = thePossibleNameStr;
+ }
+ }
+ if (theShaderName.IsValid() == false
+ && theMaterial.m_Shaders.empty() == false)
+ theShaderName = m_StringTable.GetRenderStringTable().RegisterStr(
+ theMaterial.m_Shaders[0].m_Name.c_str());
+ if (theShaderName.IsValid()) {
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SBindShader(theShaderName));
+ // this is a place holder for our input values to the shader
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyInstanceValue());
+
+ for (bool bufParam = inStream.MoveToFirstChild(); bufParam;
+ bufParam = inStream.MoveToNextSibling()) {
+ if (AreEqual("BufferBlit", inStream.GetNarrowElementName())) {
+ const char8_t *value = "";
+ const char8_t *dest = "";
+ const char8_t *source = "";
+ inStream.Att("dest", dest);
+ if (AreEqual("[dest]", dest))
+ value = "";
+ inStream.Att("source", source);
+ if (AreEqual("[source]", source))
+ value = "";
+
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyBlitFramebuffer(
+ m_StringTable.GetRenderStringTable().RegisterStr(
+ source),
+ m_StringTable.GetRenderStringTable().RegisterStr(
+ dest)));
+
+ // note need a better way to pass information from MDL to
+ // our input
+ // We use buffer blits to simulate glass refraction
+ theMaterial.m_HasRefraction = true;
+ } else if (AreEqual("BufferInput",
+ inStream.GetNarrowElementName())) {
+ const char8_t *param = "";
+ const char8_t *value = "";
+ inStream.Att("param", param);
+ inStream.Att("value", value);
+ if (AreEqual("[source]", value))
+ value = "";
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyBufferValue(
+ m_StringTable.GetRenderStringTable().RegisterStr(
+ value),
+ m_StringTable.GetRenderStringTable().RegisterStr(
+ param)));
+ HideEffectProperty(inInstance, param);
+ } else if (AreEqual("Blending",
+ inStream.GetNarrowElementName())) {
+ const char8_t *theSrcBlendFuncStr = "",
+ *theDestBlendFuncStr = "";
+ inStream.Att("source", theSrcBlendFuncStr);
+ inStream.Att("dest", theDestBlendFuncStr);
+
+ qt3ds::render::NVRenderSrcBlendFunc::Enum theSrcBlendFunc =
+ ConvertToSrcBlendFunc(theSrcBlendFuncStr);
+ qt3ds::render::NVRenderDstBlendFunc::Enum theDstBlendFuc =
+ ConvertToDstBlendFunc(theDestBlendFuncStr);
+
+ // this will setup blending
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyBlending(theSrcBlendFunc, theDstBlendFuc));
+ // if we have blending we have transparency
+ theMaterial.m_HasTransparency = true;
+ } else if (AreEqual("RenderState",
+ inStream.GetNarrowElementName())) {
+ // UdoL Todo: add this one
+ }
+ }
+ }
+ // add the render command as last thing in the pass, it is a render
+ // pass.
+ theMaterial.m_CustomerMaterialCommands.push_back(new SRender(false));
+ }
+ } else if (AreEqual("ShaderKey", inStream.GetNarrowElementName())) {
+ QT3DSU32 theValue = 0;
+ inStream.Att("value", theValue);
+ theMaterial.m_ShaderKey = theValue;
+ } else if (AreEqual("LayerKey", inStream.GetNarrowElementName())) {
+ QT3DSU32 theValue = 0;
+ inStream.Att("count", theValue);
+ theMaterial.m_LayerCount = theValue;
+ } else if (AreEqual("Buffer", inStream.GetNarrowElementName())) {
+ SAllocateBufferFlags theFlags;
+ const char8_t *theLifetimeStr = "", *theType = "", *theFormat = "",
+ *theFilter = "", *theWrap = "", *theName = "";
+ QT3DSF32 theSize = 1.0f;
+ inStream.Att("name", theName);
+ inStream.Att("lifetime", theLifetimeStr);
+ inStream.Att("type", theType);
+ inStream.Att("format", theFormat);
+ inStream.Att("filter", theFilter);
+ inStream.Att("wrap", theWrap);
+ inStream.Att("size", theSize);
+ // Clamp the size to valid amounts
+ if (theSize <= 0)
+ theSize = 1.0f;
+ if (theSize > 1.0f)
+ theSize = 1.0f;
+ if (AreEqual(theLifetimeStr, "scene"))
+ theFlags.SetSceneLifetime(true);
+ qt3ds::render::NVRenderTextureFormats::Enum theTexFormat =
+ ConvertTypeAndFormatToTextureFormat(theType, theFormat);
+ qt3ds::render::NVRenderTextureMagnifyingOp::Enum theMagOp =
+ ConvertFilterToMagOp(theFilter);
+ qt3ds::render::NVRenderTextureCoordOp::Enum theCoordOp =
+ ConvertTextureCoordOp(theWrap);
+ if (*theName == 0) {
+ QT3DS_ASSERT(false);
+ // inFoundation.error( QT3DS_INVALID_PARAMETER, "Buffer is missing its
+ // name" );
+ } else {
+ theMaterial.m_CustomerMaterialCommands.push_back(new SAllocateBuffer(
+ m_StringTable.GetRenderStringTable().RegisterStr(theName),
+ theTexFormat, theMagOp, theCoordOp, theSize, theFlags));
+ }
+ } else if (AreEqual(inStream.GetNarrowElementName(), "Lua")) {
+ const char8_t *luaScript;
+ bool hasTransparency = false;
+ if (inStream.Att("hasTransparency", hasTransparency))
+ theMaterial.m_HasTransparency = hasTransparency;
+ inStream.Value(luaScript);
+ SLuaCommand *theCommand = new SLuaCommand();
+ theCommand->m_LuaScript =
+ m_StringTable.GetRenderStringTable().RegisterStr(luaScript);
+ theMaterial.m_CustomerMaterialCommands.push_back(theCommand);
+ }
+ }
+ }
+
+ if (theMaterial.m_CustomerMaterialCommands.size() == 0) {
+ // add minimal set
+ // add shader to command stream
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SBindShader(m_StringTable.GetRenderStringTable().RegisterStr(
+ theMaterial.m_Shaders[0].m_Name.c_str())));
+ // this is a place holder for our input values to the shader
+ theMaterial.m_CustomerMaterialCommands.push_back(new SApplyInstanceValue());
+ // add the render command as last thing
+ theMaterial.m_CustomerMaterialCommands.push_back(new SRender(false));
+ }
+ }
+ }
+
+ bool LoadMaterialClassFromSourcePath(const char *inSourcePath,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) override
+ {
+ std::shared_ptr<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_DataCore->GetStringTablePtr()));
+ UICDM::SDOMElement *theElem = CDOMSerializer::Read(*theFactory, inStream, NULL);
+ if (theElem != NULL) {
+ std::shared_ptr<IDOMReader> theReader(
+ IDOMReader::CreateDOMReader(*theElem, m_DataCore->GetStringTablePtr(), theFactory));
+ LoadMaterialClassXML(*theReader, inInstance, inObjectName, outWarnings,
+ TCharStr(Intern(inSourcePath)));
+ return true;
+ }
+ return false;
+ }
+
+ Option<SMetaDataCustomMaterial> GetMaterialBySourcePath(const char *inSourcePath) override
+ {
+ TCharStr theSourcePath(Intern(inSourcePath));
+ for (TCustomMaterialMap::iterator iter = m_CustomMaterials.begin(),
+ end = m_CustomMaterials.end();
+ iter != end; ++iter) {
+ if (iter->second.m_SourcePath == theSourcePath)
+ return iter->second.ToMaterial();
+ }
+ return Empty();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Undo/Redo
+ void SetConsumer(TTransactionConsumerPtr inConsumer) override { m_Consumer = inConsumer; }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Signals
+ virtual TSignalConnectionPtr
+ ConnectInternalCategoryDestroyed(function<void(CUICDMCategoryHandle)> inCallback)
+ {
+ return CONNECT(m_InternalCategoryDestroyed);
+ }
+ virtual TSignalConnectionPtr
+ ConnectInternalPropertyDestroyed(function<void(CUICDMMetaDataPropertyHandle)> inCallback)
+ {
+ return CONNECT(m_InternalMetaDataPropertyDestroyed);
+ }
+ virtual TSignalConnectionPtr
+ ConnectInternalEventDestroyed(function<void(CUICDMEventHandle)> inCallback)
+ {
+ return CONNECT(m_InternalEventDestroyed);
+ }
+ virtual TSignalConnectionPtr
+ ConnectInternalHandlerDestroyed(function<void(CUICDMHandlerHandle)> inCallback)
+ {
+ return CONNECT(m_InternalHandlerDestroyed);
+ }
+ virtual TSignalConnectionPtr
+ ConnectInternalHandlerArgDestroyed(function<void(CUICDMHandlerHandle, QT3DSU32)> inCallback)
+ {
+ return CONNECT(m_InternalHandlerArgDestroyed);
+ }
+};
+}
+
+std::shared_ptr<IMetaData> IMetaData::CreateNewMetaData(std::shared_ptr<IDataCore> inDataCore)
+{
+ return std::make_shared<SNewMetaDataImpl>(inDataCore);
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMMetaData.h b/src/Authoring/UICDM/Systems/UICDMMetaData.h
new file mode 100644
index 00000000..c8d8b653
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMMetaData.h
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+#include "UICDMMetaDataTypes.h"
+#include "foundation/Qt3DSOption.h"
+#include <functional>
+#include <memory>
+#include "UICDMActionInfo.h"
+#include "UICDMStringTable.h"
+#include "UICDMValue.h"
+
+struct SShaderParameters;
+namespace qt3ds {
+namespace foundation {
+ class IInStream;
+}
+}
+
+namespace UICDM {
+
+using qt3ds::foundation::Option;
+using qt3ds::QT3DSU32;
+using std::pair;
+using std::vector;
+
+class ISignalConnection;
+class ITransactionConsumer;
+class IDOMWriter;
+class IDOMReader;
+class IDataCore;
+class CDataCoreProducer;
+
+struct MetaDataLoadWarningType
+{
+ enum Enum {
+ Unknown = 0,
+ InvalidProperty,
+ InvalidEvent,
+ InvalidHandler,
+ };
+};
+
+struct MetaDataLoadWarningMessage
+{
+ enum Enum {
+ Unknown = 0,
+ GeneralError,
+ MissingName,
+ InvalidDefault,
+ };
+};
+
+struct SMetaDataLoadWarning
+{
+ MetaDataLoadWarningType::Enum m_Type;
+ MetaDataLoadWarningMessage::Enum m_Message;
+ TCharStr m_ExtraInfo;
+
+ SMetaDataLoadWarning(MetaDataLoadWarningType::Enum inType,
+ MetaDataLoadWarningMessage::Enum inMessage, TCharStr inInfo = TCharStr())
+ : m_Type(inType)
+ , m_Message(inMessage)
+ , m_ExtraInfo(inInfo)
+ {
+ }
+ SMetaDataLoadWarning()
+ : m_Type(MetaDataLoadWarningType::Unknown)
+ , m_Message(MetaDataLoadWarningMessage::Unknown)
+ {
+ }
+};
+
+/**
+ * Meta data class to hold meta data descriptions of the objects used in UICDM.
+ * A user-visible type in UICDM (things in the timeline) has a specific set of metadata,
+ * the type can have properties, events, handlers, and references.
+ *
+ * Properties are exactly what they sound like. Events are messages the object can send,
+ * and handlers are functions that are exported from the object.
+ *
+ * Events are hooked up to handlers using an ActionCore which takes tuples
+ * of instance, event, handler and slide and maintains a specific instance of an action.
+ *
+ * References allow us to track which properties are being accessed. Properties are stripped
+ * from the engine portion of the runtime (although they still appear in the scenegraph)
+ * if they aren't animated nor set in a given slide. Referencing a property allows us to
+ * avoid stripping them for lua scripts which do not animate the property through the
+ * tranditional system.
+ *
+ * This design allows an artist to create and maintain a fairly complex interactive
+ *presentation
+ * without the intervention of a lua scripter.
+ */
+class IMetaData
+{
+protected:
+ virtual ~IMetaData() {}
+public:
+ typedef const TCharStr &TStrType;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Sharing some utility objects
+ virtual IStringTable &GetStringTable() = 0;
+ virtual TStringTablePtr GetStringTablePtr() = 0;
+ virtual std::shared_ptr<IDataCore> GetDataCore() = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Canonical Instances
+ // Map an instance to a given type name. The type name is stored, along with the instance
+ // handle in the file if this object is *not* canonical.
+ // If this object is canonical, then we expect this mapping setup before loading the
+ // canonical data, and we will use a type lookup instead of a direct handle lookup
+ // when loading canonical information.
+ virtual void SetInstanceAsCanonical(CUICDMInstanceHandle inInstance, TStrType inTypename) = 0;
+
+ virtual CUICDMInstanceHandle GetCanonicalInstanceForType(TStrType inTypename) = 0;
+ // If this instance wasn't registered as canonical, then we return empty.
+ virtual Option<TCharStr> GetTypeForCanonicalInstance(CUICDMInstanceHandle inInstance) = 0;
+ // Gets the type for this instance via derivation
+ virtual Option<TCharStr> GetTypeForInstance(CUICDMInstanceHandle inInstance) = 0;
+ // Get group count for instance
+ virtual QT3DSU32 GetGroupCountForInstance(CUICDMInstanceHandle inInstance) = 0;
+ // Get all group names
+ virtual QT3DSU32 GetGroupNamesForInstance(CUICDMInstanceHandle inInstance,
+ std::vector<TCharStr> &outNames) = 0;
+ // Get group count for instance
+ virtual Option<TCharStr> GetGroupFilterNameForInstance(CUICDMInstanceHandle inInstance,
+ long inIndex) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Categories
+ // Categories appear in the UI to divide up large lists of events, actions, and properties.
+ // Returns <handle,true> if a category was created
+ // else returns <handle,false>
+ virtual pair<CUICDMCategoryHandle, bool> GetOrCreateCategory(TStrType inName) = 0;
+
+ virtual void SetCategoryInfo(CUICDMCategoryHandle inCategory, TStrType inIcon,
+ TStrType inHighlight, TStrType inDescription) = 0;
+ virtual void DestroyCategory(CUICDMCategoryHandle inCategory) = 0;
+
+ virtual Option<SCategoryInfo> GetCategoryInfo(CUICDMCategoryHandle inCategory) = 0;
+ virtual CUICDMCategoryHandle FindCategoryByName(TStrType inName) = 0;
+ virtual void GetCategories(vector<CUICDMCategoryHandle> &outCategories) = 0;
+ virtual Option<SCategoryInfo> GetEventCategory(TStrType inName) = 0;
+ virtual Option<SCategoryInfo> GetHandlerCategory(TStrType inName) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Properties
+ // Will create the property on the instance associated with this type name if it doesn't exist.
+ // Metadata properties can be redifined for child instances and this re-definition will override
+ // the parent definition. We currently use this to give different formal names and description
+ // to the sourcepath property (for models it is mesh, for materials it is image).
+ virtual CUICDMMetaDataPropertyHandle
+ CreateMetaDataProperty(CUICDMInstanceHandle inInstance) = 0;
+
+ // For properties, you set the default values separately
+ // This may delete the underlying data model property rebuild it.
+ virtual void SetMetaDataPropertyInfo(CUICDMMetaDataPropertyHandle inPropertyHandle,
+ TStrType inName, TStrType inFormalName,
+ TStrType inDescription, TStrType inUsage,
+ CompleteMetaDataType::Enum inDataType,
+ const SValue &inDefaultValue,
+ const TMetaDataData &inMetaData, TStrType inGroupName,
+ bool inIsHidden = false, bool inIsAnimatable = false) = 0;
+
+ // Destroy just this meta data property
+ // Does not destroy the underlying data core property, so this function isn't a perfect
+ // reverse of the above system. This *just* destroyed the meta data pointed to by
+ // this property.
+ virtual void DestroyMetaDataProperty(CUICDMMetaDataPropertyHandle inProperty) = 0;
+
+ virtual CUICDMMetaDataPropertyHandle GetMetaDataProperty(CUICDMInstanceHandle inInstance,
+ TStrType inPropertyName) = 0;
+ virtual CUICDMMetaDataPropertyHandle GetMetaDataProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual Option<SMetaDataPropertyInfo>
+ GetMetaDataPropertyInfo(CUICDMMetaDataPropertyHandle inProperty) = 0;
+ // Get all of the meta data properties defined on this object or its derivation parents
+ virtual void GetMetaDataProperties(CUICDMInstanceHandle inInstance,
+ vector<CUICDMMetaDataPropertyHandle> &outProperties) = 0;
+
+ // Get the meta data properties defined on *only* this object, don't search parents
+ virtual CUICDMMetaDataPropertyHandle
+ GetOrCreateSpecificMetaDataProperty(CUICDMInstanceHandle inInstance,
+ TStrType inPropertyName) = 0;
+ virtual void
+ GetSpecificMetaDataProperties(CUICDMInstanceHandle inInstance,
+ vector<CUICDMMetaDataPropertyHandle> &outProperties) = 0;
+
+ virtual TCharStr GetFormalName(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual AdditionalMetaDataType::Value GetAdditionalMetaDataType(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual TMetaDataData GetAdditionalMetaDataData(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual bool IsCustomProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual SValue GetDefaultValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+
+ virtual void
+ SetMetaDataPropertyFilters(CUICDMMetaDataPropertyHandle inProperty,
+ qt3ds::foundation::NVConstDataRef<SPropertyFilterInfo> inFilters) = 0;
+ virtual qt3ds::foundation::NVConstDataRef<SPropertyFilterInfo>
+ GetMetaDataPropertyFilters(CUICDMMetaDataPropertyHandle inProperty) = 0;
+ virtual void RemoveMetaDataPropertyFilters(CUICDMMetaDataPropertyHandle inProperty) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Events
+ // CreateMetaDataEvent was original named CreateEvent but this collides with
+ // the microsoft macro CreateEvent which expands to CreateEventA or CreateEventW
+ virtual CUICDMEventHandle CreateMetaDataEvent(CUICDMInstanceHandle inInstance) = 0;
+ virtual void SetEventInfo(CUICDMEventHandle inEventHandle, TStrType inName,
+ TStrType inFormalName, TStrType inCategory,
+ TStrType inDescription) = 0;
+
+ virtual void DestroyEvent(CUICDMEventHandle inEventHandle) = 0;
+
+ virtual void GetEvents(CUICDMInstanceHandle inInstance, TEventHandleList &outEvents) = 0;
+ virtual CUICDMEventHandle FindEvent(CUICDMInstanceHandle inInstance, TStrType inName) = 0;
+ virtual Option<SEventInfo> GetEventInfo(CUICDMEventHandle inEventHandle) = 0;
+ virtual bool IsCustomEvent(CUICDMEventHandle inEventHandle) = 0;
+
+ // Get/Find an event that occurs on just this instance, don't search parent instances
+ virtual void GetSpecificEvents(CUICDMInstanceHandle inInstance,
+ TEventHandleList &outEvents) = 0;
+ virtual CUICDMEventHandle GetOrCreateSpecificEvent(CUICDMInstanceHandle inInstance,
+ TStrType inName) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Handlers
+ virtual CUICDMHandlerHandle CreateHandler(CUICDMInstanceHandle inInstance) = 0;
+ virtual void SetHandlerInfo(CUICDMHandlerHandle inHandle, TStrType inName,
+ TStrType inFormalName, TStrType inCategory,
+ TStrType inDescription) = 0;
+ virtual void DestroyHandler(CUICDMHandlerHandle inHandlerHandle) = 0;
+
+ virtual CUICDMHandlerHandle FindHandlerByName(CUICDMInstanceHandle inInstance,
+ TStrType inName) = 0;
+ virtual Option<SHandlerInfo> GetHandlerInfo(CUICDMHandlerHandle inHandlerHandle) = 0;
+ virtual void GetHandlers(CUICDMInstanceHandle inInstance, THandlerHandleList &outHandlers) = 0;
+ virtual bool IsCustomHandler(CUICDMHandlerHandle inEventHandle) = 0;
+
+ virtual void GetSpecificHandlers(CUICDMInstanceHandle inInstance,
+ THandlerHandleList &outHandlers) = 0;
+ virtual CUICDMHandlerHandle GetOrCreateSpecificHandler(CUICDMInstanceHandle inInstance,
+ TStrType inName) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Handler Arguments
+ virtual QT3DSU32 AddHandlerArgument(CUICDMHandlerHandle inHandler) = 0;
+ virtual void
+ SetHandlerArgumentInfo(CUICDMHandlerHandle inHandler, QT3DSU32 inArgIndex, TStrType inName,
+ TStrType inFormalName, TStrType inDescription,
+ CompleteMetaDataType::Enum inDataType, const SValue &inDefaultValue,
+ const TMetaDataData &inMetaData, HandlerArgumentType::Value inArgType) = 0;
+
+ virtual void DestroyHanderArgument(CUICDMHandlerHandle inHandler, QT3DSU32 inArgIndex) = 0;
+
+ virtual Option<SMetaDataHandlerArgumentInfo>
+ FindHandlerArgumentByName(CUICDMHandlerHandle inHandler, TStrType inName) = 0;
+ virtual void GetHandlerArguments(CUICDMHandlerHandle inHandler,
+ vector<SMetaDataHandlerArgumentInfo> &outArguments) = 0;
+ virtual Option<SMetaDataHandlerArgumentInfo>
+ GetHandlerArgumentInfo(CUICDMHandlerHandle inHandle, QT3DSU32 inIndex) = 0;
+ virtual QT3DSU32 GetNumHandlerArguments(CUICDMHandlerHandle inHandler) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // References
+ // Duplicate references are removed from this instance
+ virtual void AddReference(CUICDMInstanceHandle inInstance, TStrType inRefString) = 0;
+ virtual void DestroyReferences(CUICDMInstanceHandle inInstance) = 0;
+
+ // Does the recursive gather from all the parents. Duplicate references are removed from the
+ // final list.
+ virtual void GetReferences(CUICDMInstanceHandle inInstance,
+ std::vector<TCharStr> &outReferences) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Instance-global functions
+ // Destroy all meta data that relates to this instance.
+ // Calling this on a derived instance does nothing, this only works if this specific
+ // instance was mapped directly to meta data.
+ virtual void DestroyMetaData(CUICDMInstanceHandle inInstance) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Serialization
+ // You can either save out in canonical format (and it will only save canonical-instance-related
+ // information *or* you can save out in normal format where we link directly to instance handle
+ // instead of to typename
+ virtual void Save(IDOMWriter &inWriter) = 0;
+ // Loading expects the canonical instances to be setup already which means that
+ // it will perform lookups based on
+ // One huge assumption is that the reader is using the same string table
+ // that this object was built with
+ // InIsCanonical tells us whether to mark loaded categories as canonical
+ // or not.
+ virtual void Load(IDOMReader &ioStream) = 0;
+
+ // Load meta data and apply it to just this instance
+ virtual void LoadInstance(IDOMReader &inReader, CUICDMInstanceHandle inInstance,
+ const TCharStr &inName,
+ std::vector<SMetaDataLoadWarning> &outWarnings) = 0;
+
+ // Save just this instances meta data out to the writer
+ virtual void SaveInstance(IDOMWriter &inWriter, CUICDMInstanceHandle inInstance) = 0;
+
+ // Load effect meta data from file and apply it to just this instance
+ virtual void LoadEffectInstance(const char *inShaderFile, CUICDMInstanceHandle inInstance,
+ const TCharStr &inName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) = 0;
+
+ virtual bool IsEffectInstanceRegistered(const char *inName) = 0;
+ virtual void LoadEffectXML(IDOMReader &inStream, CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ const TCharStr &inSourcePath) = 0;
+ virtual bool LoadEffectXMLFromSourcePath(const char *inSourcePath,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) = 0;
+ virtual Option<SMetaDataEffect> GetEffectBySourcePath(const char *inName) = 0;
+
+ virtual void LoadMaterialInstance(const char *inShaderFile,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) = 0;
+ virtual bool IsMaterialClassRegistered(const char *inName) = 0;
+ virtual void LoadMaterialClassXML(IDOMReader &inStream, CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ const TCharStr &inSourcePath) = 0;
+ virtual bool LoadMaterialClassFromSourcePath(const char *inSourcePath,
+ CUICDMInstanceHandle inInstance,
+ const TCharStr &inObjectName,
+ std::vector<SMetaDataLoadWarning> &outWarnings,
+ qt3ds::foundation::IInStream &inStream) = 0;
+ virtual Option<SMetaDataCustomMaterial> GetMaterialBySourcePath(const char *inSourcePath) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Undo/Redo
+ virtual void SetConsumer(std::shared_ptr<ITransactionConsumer> inConsumer) = 0;
+
+#ifndef UICDM_META_DATA_NO_SIGNALS
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Signals
+ // These events are sent out only once, they aren't set into the transaction consumer
+ // to be sent out upon undo and redo. These events are meant for chaining together side effects
+ // so other systems don't have references to invalid handler arguments and handles.
+ // Also, the objects in these messages are still valid so you can query information about them
+ // at this time. They will be destroyed subsequent to the event.
+ virtual std::shared_ptr<ISignalConnection>
+ ConnectInternalCategoryDestroyed(std::function<void(CUICDMCategoryHandle)> inCallback) = 0;
+ virtual std::shared_ptr<ISignalConnection> ConnectInternalPropertyDestroyed(
+ std::function<void(CUICDMMetaDataPropertyHandle)> inCallback) = 0;
+ virtual std::shared_ptr<ISignalConnection>
+ ConnectInternalEventDestroyed(std::function<void(CUICDMEventHandle)> inCallback) = 0;
+ virtual std::shared_ptr<ISignalConnection>
+ ConnectInternalHandlerDestroyed(std::function<void(CUICDMHandlerHandle)> inCallback) = 0;
+ virtual std::shared_ptr<ISignalConnection> ConnectInternalHandlerArgDestroyed(
+ std::function<void(CUICDMHandlerHandle, QT3DSU32)> inCallback) = 0;
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ // Creation/Lifetime Management
+ friend class std::shared_ptr<IMetaData>;
+ // The data core is used to create the properties if they don't exist or
+ // query their underlying type if they do exist. We also subscribe to
+ // the datacore's beforeInstanceDelete function in order to ensure
+ // that we delete our existing meta data for instances that are being deleted.
+ static std::shared_ptr<IMetaData> CreateNewMetaData(std::shared_ptr<IDataCore> inDataCore);
+};
+
+typedef std::shared_ptr<IMetaData> TNewMetaDataPtr;
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMMetaDataTypes.h b/src/Authoring/UICDM/Systems/UICDMMetaDataTypes.h
new file mode 100644
index 00000000..c42df6f8
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMMetaDataTypes.h
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#include "UICDMMetaDataValue.h"
+
+namespace uic {
+namespace render {
+ namespace dynamic {
+ struct SCommand;
+ struct SPropertyDeclaration;
+ struct SPropertyDefinition;
+ }
+}
+}
+
+namespace UICDM {
+
+struct HandlerArgumentType {
+
+ enum Value {
+ None,
+ Property, // Property reference. Load the Properties of the Target Object.
+ Dependent, // Property type depends on another property.
+ Slide, // Slide reference. Load the list of slides of the Target Object if
+ // applicable.
+ Event, // Event reference. Load the applicable Events of the Target Object.
+ Object, // Object reference. Used for dynamic actions with object referenced
+ // property.
+ Signal, // Signal reference. Used for emiting signals fired from the trigger
+ // object.
+ };
+
+ Q_ENUM(Value)
+ Q_GADGET
+};
+
+struct CompleteMetaDataType
+{
+ enum Enum {
+ Unknown = 0,
+ StringList,
+ FloatRange,
+ LongRange,
+ Float,
+ Long,
+ Float2,
+ Vector,
+ Scale,
+ Rotation,
+ Color,
+ Boolean,
+ Slide,
+ Font,
+ FontSize,
+ String,
+ MultiLineString,
+ ObjectRef,
+ Image,
+ Mesh,
+ Import,
+ Texture,
+ Guid,
+ StringListOrInt,
+ Renderable,
+ Image2D,
+ Buffer,
+ PathBuffer,
+ ShadowMapResolution,
+ };
+
+ // Functions defined in UICDMMetaData.cpp
+ static DataModelDataType::Value ToDataType(Enum inCompleteType);
+ static AdditionalMetaDataType::Value ToAdditionalType(Enum inCompleteType);
+ static CompleteMetaDataType::Enum ToCompleteType(DataModelDataType::Value inDataType,
+ AdditionalMetaDataType::Value inAdditionalType);
+ Q_ENUM(Enum)
+ Q_GADGET
+};
+
+typedef std::pair<DataModelDataType::Value, AdditionalMetaDataType::Value> TDataTypePair;
+
+inline bool Equals(const TMetaDataData &lhs, const TMetaDataData &rhs)
+{
+ return rhs == lhs;
+}
+
+inline AdditionalMetaDataType::Value GetMetaDataValueType(const TMetaDataData &inValue)
+{
+ return inValue.getType();
+}
+
+// Base class shared between property info
+// and handler arguments.
+struct SMetaPropertyBase
+{
+ TCharStr m_Name;
+ TCharStr m_FormalName;
+ TCharStr m_Usage;
+ TCharStr m_Description;
+ CompleteMetaDataType::Enum m_CompleteType;
+ TMetaDataData m_MetaDataData;
+ SValue m_DefaultValue;
+
+ SMetaPropertyBase()
+ : m_CompleteType(CompleteMetaDataType::Float)
+ {
+ }
+ bool operator==(const SMetaPropertyBase &inOther) const
+ {
+ return m_Name == inOther.m_Name && m_FormalName == inOther.m_FormalName
+ && m_Usage == inOther.m_Usage && m_Description == inOther.m_Description
+ && m_CompleteType == inOther.m_CompleteType
+ && Equals(m_DefaultValue.toOldSkool(), inOther.m_DefaultValue.toOldSkool())
+ && Equals(m_MetaDataData, inOther.m_MetaDataData);
+ }
+ DataModelDataType::Value GetDataType() const
+ {
+ return CompleteMetaDataType::ToDataType(m_CompleteType);
+ }
+ AdditionalMetaDataType::Value GetAdditionalType() const
+ {
+ return CompleteMetaDataType::ToAdditionalType(m_CompleteType);
+ }
+};
+
+struct SMetaDataPropertyInfo : SMetaPropertyBase
+{
+ CUICDMInstanceHandle m_Instance;
+ CUICDMPropertyHandle m_Property;
+ bool m_IsHidden; // Is this property visible in the UI
+ bool m_Animatable; // Is this property visible in the UI
+ TCharStr m_GroupName; // Name of the group this property belongs to or "default"
+
+ SMetaDataPropertyInfo(CUICDMInstanceHandle inInstance)
+ : m_Instance(inInstance)
+ {
+ init();
+ }
+ SMetaDataPropertyInfo() { init(); }
+ void init()
+ {
+ m_IsHidden = false;
+ // We default to being animatable
+ m_Animatable = true;
+ }
+ bool operator==(const SMetaDataPropertyInfo &inOther) const
+ {
+ return m_Instance == inOther.m_Instance && m_Property == inOther.m_Property
+ && m_IsHidden == inOther.m_IsHidden && m_Animatable == inOther.m_Animatable
+ && m_GroupName == inOther.m_GroupName && SMetaPropertyBase::operator==(inOther);
+ }
+
+ bool operator!=(const SMetaDataPropertyInfo &inOther) const { return !(*this == inOther); }
+};
+
+struct SMetaDataHandlerArgumentInfo : SMetaPropertyBase
+{
+ CUICDMHandlerHandle m_Handler;
+ HandlerArgumentType::Value m_ArgType;
+ SMetaDataHandlerArgumentInfo(CUICDMHandlerHandle inHandler = CUICDMHandlerHandle())
+ : m_Handler(inHandler)
+ , m_ArgType(HandlerArgumentType::None)
+ {
+ }
+};
+
+struct SCategoryInfo
+{
+ TCharStr m_Name;
+ TCharStr m_Description;
+ TCharStr m_Icon;
+ TCharStr m_HighlightIcon;
+ bool m_Canonical;
+
+ SCategoryInfo()
+ : m_Canonical(false)
+ {
+ }
+ SCategoryInfo(TCharStr inName)
+ : m_Name(inName)
+ , m_Canonical(false)
+ {
+ }
+};
+
+struct SEventInfo
+{
+ bool operator!=(const SEventInfo &inEvent) const
+ {
+ return (m_Name != inEvent.m_Name || m_FormalName != inEvent.m_FormalName
+ || m_Category != inEvent.m_Category || m_Description != inEvent.m_Description);
+ }
+
+ TCharStr m_Name;
+ TCharStr m_FormalName;
+ TCharStr m_Category;
+ TCharStr m_Description;
+};
+
+struct SHandlerInfo
+{
+ TCharStr m_Name;
+ TCharStr m_FormalName;
+ TCharStr m_Category;
+ TCharStr m_Description;
+
+ bool operator!=(const SHandlerInfo &inHandler) const
+ {
+ return (m_Name != inHandler.m_Name || m_FormalName != inHandler.m_FormalName
+ || m_Category != inHandler.m_Category || m_Description != inHandler.m_Description);
+ }
+};
+
+struct PropertyFilterTypes
+{
+ enum Enum {
+ Unknown,
+ ShowIfEqual,
+ HideIfEqual,
+ };
+};
+
+struct SPropertyFilterInfo
+{
+ PropertyFilterTypes::Enum m_FilterType;
+ CUICDMPropertyHandle m_FilterProperty;
+ SValue m_Value;
+ SPropertyFilterInfo()
+ : m_FilterType(PropertyFilterTypes::Unknown)
+ {
+ }
+ SPropertyFilterInfo(PropertyFilterTypes::Enum inFilterType, CUICDMPropertyHandle inProp,
+ const SValue &inValue)
+ : m_FilterType(inFilterType)
+ , m_FilterProperty(inProp)
+ , m_Value(inValue)
+ {
+ }
+};
+struct SMetaDataShader
+{
+ TCharStr m_Name;
+ TCharStr m_Type; ///< shader type (GLSL or HLSL)
+ TCharStr m_Version; ///< shader version (e.g. 330 vor GLSL)
+ // Code contains both the vertex and fragment portions separated by #define's.
+ //#define VERTEX_SHADER, #define FRAGMENT_SHADER
+ TCharStr m_Code;
+ bool m_HasGeomShader;
+ bool m_IsComputeShader;
+ SMetaDataShader()
+ : m_HasGeomShader(false)
+ , m_IsComputeShader(false)
+ {
+ }
+ SMetaDataShader(const TCharStr &inName, const TCharStr &inType, const TCharStr &inVersion,
+ const TCharStr &inCode, bool hasGeom, bool isCompute)
+ : m_Name(inName)
+ , m_Type(inType)
+ , m_Version(inVersion)
+ , m_Code(inCode)
+ , m_HasGeomShader(hasGeom)
+ , m_IsComputeShader(isCompute)
+ {
+ }
+};
+
+struct SMetaDataDynamicObject
+{
+ TCharStr m_Name;
+ qt3ds::foundation::NVConstDataRef<SMetaDataShader> m_Shaders;
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SPropertyDefinition> m_Properties;
+ SMetaDataDynamicObject() {}
+ SMetaDataDynamicObject(
+ const TCharStr &inName, qt3ds::foundation::NVConstDataRef<SMetaDataShader> inShaders,
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SPropertyDefinition> inProperties)
+ : m_Name(inName)
+ , m_Shaders(inShaders)
+ , m_Properties(inProperties)
+ {
+ }
+};
+
+struct SMetaDataEffect : public SMetaDataDynamicObject
+{
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SCommand *> m_EffectCommands;
+ SMetaDataEffect() {}
+ SMetaDataEffect(
+ const TCharStr &inName, qt3ds::foundation::NVConstDataRef<SMetaDataShader> inShaders,
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SPropertyDefinition> inProperties,
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SCommand *> inEffectCommands)
+ : SMetaDataDynamicObject(inName, inShaders, inProperties)
+ , m_EffectCommands(inEffectCommands)
+ {
+ }
+};
+
+struct SMetaDataCustomMaterial : public SMetaDataDynamicObject
+{
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SCommand *> m_CustomMaterialCommands;
+ bool m_HasTransparency;
+ bool m_HasRefraction;
+ bool m_AlwaysDirty;
+ unsigned int m_ShaderKey;
+ unsigned int m_LayerCount;
+ SMetaDataCustomMaterial() {}
+ SMetaDataCustomMaterial(
+ const TCharStr &inName, qt3ds::foundation::NVConstDataRef<SMetaDataShader> inShaders,
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SPropertyDefinition> inProperties,
+ qt3ds::foundation::NVConstDataRef<uic::render::dynamic::SCommand *> inCustomMaterialCommands,
+ bool inHasTransparency, bool inHasRefraction, bool inIsAlwaysDirty,
+ unsigned int inShaderKey, unsigned int inLayerCount)
+ : SMetaDataDynamicObject(inName, inShaders, inProperties)
+ , m_CustomMaterialCommands(inCustomMaterialCommands)
+ , m_HasTransparency(inHasTransparency)
+ , m_HasRefraction(inHasRefraction)
+ , m_AlwaysDirty(inIsAlwaysDirty)
+ , m_ShaderKey(inShaderKey)
+ , m_LayerCount(inLayerCount)
+ {
+ }
+};
+}
+
+Q_DECLARE_METATYPE(UICDM::HandlerArgumentType::Value)
+
diff --git a/src/Authoring/UICDM/Systems/UICDMMetaDataValue.h b/src/Authoring/UICDM/Systems/UICDMMetaDataValue.h
new file mode 100644
index 00000000..409879ea
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMMetaDataValue.h
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#include <EASTL/string.h>
+#include <EASTL/vector.h>
+#include "UICDMHandles.h"
+#include "UICDMDataTypes.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "UICDMValue.h"
+
+#include <QStringList>
+
+namespace UICDM {
+
+struct AdditionalMetaDataType {
+
+ enum Value {
+ None,
+ StringList,
+ Range,
+ Image,
+ Color,
+ Rotation,
+ Font,
+ FontSize,
+ MultiLine,
+ ObjectRef,
+ Mesh,
+ Import,
+ Texture,
+ Renderable,
+ PathBuffer,
+ ShadowMapResolution
+ };
+
+
+ Q_ENUM(Value)
+ Q_GADGET
+};
+
+// List type metadata
+typedef eastl::vector<TCharStr> TMetaDataStringList;
+
+// Float type metadata
+struct SMetaDataRange
+{
+ SMetaDataRange()
+ : m_Min(0.0f)
+ , m_Max(0.0f)
+ {
+ }
+
+ SMetaDataRange(float inMin, float inMax)
+ : m_Min(inMin)
+ , m_Max(inMax)
+ {
+ }
+
+ bool operator==(const SMetaDataRange &other) const
+ {
+ return m_Min == other.m_Min && m_Max == other.m_Max;
+ }
+
+ float m_Min;
+ float m_Max;
+};
+}
+
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<UICDM::SMetaDataRange>
+ {
+ void destruct(UICDM::SMetaDataRange &) {}
+ };
+}
+}
+
+namespace UICDM {
+
+template <typename TDataType>
+struct SMetaDataTypeToEnumMap
+{
+};
+template <>
+struct SMetaDataTypeToEnumMap<eastl::vector<TCharStr>>
+{
+ static AdditionalMetaDataType::Value getType() { return AdditionalMetaDataType::StringList; }
+};
+template <>
+struct SMetaDataTypeToEnumMap<SMetaDataRange>
+{
+ static AdditionalMetaDataType::Value getType() { return AdditionalMetaDataType::Range; }
+};
+
+struct SMetaDataValueTraits
+{
+ typedef AdditionalMetaDataType::Value TIdType;
+
+ enum {
+ TBufferSize = sizeof(TMetaDataStringList),
+ };
+
+ static TIdType getNoDataId() { return AdditionalMetaDataType::None; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SMetaDataTypeToEnumMap<TDataType>::getType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, AdditionalMetaDataType::Value inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case AdditionalMetaDataType::StringList:
+ return inVisitor(*reinterpret_cast<TMetaDataStringList *>(inData));
+ case AdditionalMetaDataType::Range:
+ return inVisitor(*reinterpret_cast<SMetaDataRange *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case AdditionalMetaDataType::None:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, AdditionalMetaDataType::Value inType,
+ TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case AdditionalMetaDataType::StringList:
+ return inVisitor(*reinterpret_cast<const TMetaDataStringList *>(inData));
+ case AdditionalMetaDataType::Range:
+ return inVisitor(*reinterpret_cast<const SMetaDataRange *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case AdditionalMetaDataType::None:
+ return inVisitor();
+ }
+ }
+};
+
+struct SMetaDataData
+ : public qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SMetaDataValueTraits,
+ SUICDMDataTypeUnionTraits::
+ TBufferSize>,
+ SMetaDataValueTraits::TBufferSize>
+{
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::DiscriminatedUnionGenericBase<SMetaDataValueTraits,
+ SUICDMDataTypeUnionTraits::
+ TBufferSize>,
+ SMetaDataValueTraits::TBufferSize>
+ TBase;
+ SMetaDataData() {}
+ SMetaDataData(const SMetaDataData &inOther)
+ : TBase(static_cast<const TBase &>(inOther))
+ {
+ }
+ SMetaDataData &operator=(const SMetaDataData &inOther)
+ {
+ TBase::operator=(static_cast<const TBase &>(inOther));
+ return *this;
+ }
+ SMetaDataData(const TMetaDataStringList &inData)
+ : TBase(inData)
+ {
+ }
+ SMetaDataData(const SMetaDataRange &inData)
+ : TBase(inData)
+ {
+ }
+ SMetaDataData &operator=(const TMetaDataStringList &inData)
+ {
+ TBase::operator=(inData);
+ return *this;
+ }
+ SMetaDataData &operator=(const SMetaDataRange &inData)
+ {
+ TBase::operator=(inData);
+ return *this;
+ }
+ bool empty() const { return getType() == AdditionalMetaDataType::None; }
+};
+
+template <>
+struct SUICDMGetter<SMetaDataData>
+{
+ template <typename TRetType>
+ TRetType doGet(const SMetaDataData &inValue)
+ {
+ return inValue.getData<TRetType>();
+ }
+};
+
+template <>
+struct SUICDMValueTyper<SMetaDataData>
+{
+ AdditionalMetaDataType::Value Get(const SMetaDataData &inValue) { return inValue.getType(); }
+};
+
+typedef SMetaDataData TMetaDataData;
+
+
+template <>
+inline QStringList get<QStringList>(const UICDM::SMetaDataData &inType)
+{
+ QStringList result;
+ if (inType.getType() == UICDM::AdditionalMetaDataType::None)
+ return result;
+
+ auto list = UICDM::get<UICDM::TMetaDataStringList>(inType);
+ std::transform(list.begin(), list.end(), std::back_inserter(result), [](const SUICDMStr &s) {
+ return QString::fromWCharArray(s.wide_str());
+ });
+ return result;
+}
+}
+
+Q_DECLARE_METATYPE(UICDM::AdditionalMetaDataType)
+
diff --git a/src/Authoring/UICDM/Systems/UICDMPropertyDefinition.h b/src/Authoring/UICDM/Systems/UICDMPropertyDefinition.h
new file mode 100644
index 00000000..5e94a40f
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMPropertyDefinition.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMPROPERTYDEFINITIONH
+#define UICDMPROPERTYDEFINITIONH
+
+#include "UICDMDataTypes.h"
+
+namespace UICDM {
+
+struct SUICDMPropertyDefinition
+{
+ TCharStr m_Name;
+ CUICDMInstanceHandle m_Instance;
+ DataModelDataType::Value m_Type;
+
+ SUICDMPropertyDefinition()
+ : m_Type(DataModelDataType::None)
+ {
+ }
+ SUICDMPropertyDefinition(CUICDMInstanceHandle inInstanceHandle, TCharPtr inName,
+ DataModelDataType::Value inType)
+ : m_Name(inName)
+ , m_Instance(inInstanceHandle)
+ , m_Type(inType)
+ {
+ }
+ SUICDMPropertyDefinition(const SUICDMPropertyDefinition &inOther)
+ : m_Name(inOther.m_Name)
+ , m_Instance(inOther.m_Instance)
+ , m_Type(inOther.m_Type)
+ {
+ }
+
+ SUICDMPropertyDefinition &operator=(const SUICDMPropertyDefinition &inOther)
+ {
+ if (this != &inOther) {
+ m_Name = inOther.m_Name;
+ m_Instance = inOther.m_Instance;
+ m_Type = inOther.m_Type;
+ }
+ return *this;
+ }
+};
+
+typedef std::vector<SUICDMPropertyDefinition> TPropertyDefinitionList;
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMSignalStructImpl.h b/src/Authoring/UICDM/Systems/UICDMSignalStructImpl.h
new file mode 100644
index 00000000..fa70bc06
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSignalStructImpl.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSIGNALSTRUCTIMPLH
+#define UICDMSIGNALSTRUCTIMPLH
+#include "UICDMSignalStructs.h"
+
+namespace UICDM {
+
+struct SSignalDataStruct0
+{
+ typedef SSignalDataStruct0 TThisType;
+ typedef std::function<void()> TFunType;
+ static void Send(ISignalSystem &system, void *sender, const char *sigName)
+ {
+ system.Signal(sender, sigName, NULL, 0);
+ }
+
+ static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize,
+ TFunType inHandler)
+ {
+ if (inDataSize == 0)
+ inHandler();
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static TGenericSignalHandlerFunc CreateHandler(std::function<void()> inHandler)
+ {
+ return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, inHandler);
+ }
+
+ static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender,
+ const char *inName, TFunType inHandler)
+ {
+ return inSystem.AddListener(inSender, inName, CreateHandler(inHandler));
+ }
+};
+
+#define UICDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT0(name) \
+ std::shared_ptr<ISignalConnection> Sig##name::AddListener( \
+ ISignalSystem &inSystem, void *inSender, std::function<void()> inHandler) \
+ { \
+ typedef SSignalDataStruct0 TBase; \
+ return TBase::AddListener(inSystem, inSender, #name, inHandler); \
+ } \
+ void Sig##name::Send(ISignalSystem &system, void *sender) \
+ { \
+ typedef SSignalDataStruct0 TBase; \
+ TBase::Send(system, sender, #name); \
+ }
+
+template <typename TData1>
+struct SSignalDataStruct1
+{
+ typedef SSignalDataStruct1<TData1> TThisType;
+ TData1 m_Data1;
+ typedef std::function<void(TData1)> TFunType;
+ SSignalDataStruct1(TData1 d1)
+ : m_Data1(d1)
+ {
+ }
+ static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1)
+ {
+ TThisType theData(d1);
+ system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType));
+ }
+
+ static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize,
+ TFunType inHandler)
+ {
+ if (inDataSize == sizeof(TThisType)) {
+ const TThisType *theData = reinterpret_cast<const TThisType *>(inData);
+ inHandler(theData->m_Data1);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler)
+ {
+ return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, inHandler);
+ }
+
+ static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender,
+ const char *inName, TFunType inHandler)
+ {
+ return inSystem.AddListener(inSender, inName, CreateHandler(inHandler));
+ }
+};
+
+#define UICDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT1(name, d1) \
+ std::shared_ptr<ISignalConnection> Sig##name::AddListener( \
+ ISignalSystem &inSystem, void *inSender, std::function<void(d1)> inHandler) \
+ { \
+ typedef SSignalDataStruct1<d1> TBase; \
+ return TBase::AddListener(inSystem, inSender, #name, inHandler); \
+ } \
+ void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg) \
+ { \
+ typedef SSignalDataStruct1<d1> TBase; \
+ TBase::Send(system, sender, #name, arg); \
+ }
+
+template <typename TData1, typename TData2>
+struct SSignalDataStruct2
+{
+ typedef SSignalDataStruct2<TData1, TData2> TThisType;
+ typedef std::function<void(TData1, TData2)> TFunType;
+ TData1 m_Data1;
+ TData2 m_Data2;
+ SSignalDataStruct2(TData1 d1, TData2 d2)
+ : m_Data1(d1)
+ , m_Data2(d2)
+ {
+ }
+ static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1,
+ const TData2 &d2)
+ {
+ TThisType theData(d1, d2);
+ system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType));
+ }
+
+ static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize,
+ TFunType inHandler)
+ {
+ if (inDataSize == sizeof(TThisType)) {
+ const TThisType *theData = reinterpret_cast<const TThisType *>(inData);
+ inHandler(theData->m_Data1, theData->m_Data2);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler)
+ {
+ return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, inHandler);
+ }
+
+ static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender,
+ const char *inName, TFunType inHandler)
+ {
+ return inSystem.AddListener(inSender, inName, CreateHandler(inHandler));
+ }
+};
+
+#define UICDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT2(name, d1, d2) \
+ std::shared_ptr<ISignalConnection> Sig##name::AddListener( \
+ ISignalSystem &inSystem, void *inSender, std::function<void(d1, d2)> inHandler) \
+ { \
+ return SSignalDataStruct2<d1, d2>::AddListener(inSystem, inSender, #name, inHandler); \
+ } \
+ void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2) \
+ { \
+ SSignalDataStruct2<d1, d2>::Send(system, sender, #name, arg1, arg2); \
+ }
+
+template <typename TData1, typename TData2, typename TData3>
+struct SSignalDataStruct3
+{
+ typedef SSignalDataStruct3<TData1, TData2, TData3> TThisType;
+ typedef std::function<void(TData1, TData2, TData3)> TFunType;
+ TData1 m_Data1;
+ TData2 m_Data2;
+ TData3 m_Data3;
+ SSignalDataStruct3(const TData1 &d1, const TData2 &d2, const TData3 &d3)
+ : m_Data1(d1)
+ , m_Data2(d2)
+ , m_Data3(d3)
+ {
+ }
+ static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1,
+ const TData2 &d2, const TData3 &d3)
+ {
+ TThisType theData(d1, d2, d3);
+ system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType));
+ }
+
+ static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize,
+ TFunType inHandler)
+ {
+ if (inDataSize == sizeof(TThisType)) {
+ const TThisType *theData = reinterpret_cast<const TThisType *>(inData);
+ inHandler(theData->m_Data1, theData->m_Data2, theData->m_Data2);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler)
+ {
+ return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, inHandler);
+ }
+
+ static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender,
+ const char *inName, TFunType inHandler)
+ {
+ return inSystem.AddListener(inSender, inName, CreateHandler(inHandler));
+ }
+};
+
+#define UICDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT3(name, d1, d2, d3) \
+ std::shared_ptr<ISignalConnection> Sig##name::AddListener( \
+ ISignalSystem &inSystem, void *inSender, std::function<void(d1, d2, d3)> inHandler) \
+ { \
+ return SSignalDataStruct3<d1, d2, d3>::AddListener(inSystem, inSender, #name, inHandler); \
+ } \
+ void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \
+ const d3 &arg3) \
+ { \
+ SSignalDataStruct3<d1, d2, d3>::Send(system, sender, #name, arg1, arg2, arg3); \
+ }
+
+template <typename TData1, typename TData2, typename TData3, typename TData4>
+struct SSignalDataStruct4
+{
+ typedef SSignalDataStruct4<TData1, TData2, TData3, TData4> TThisType;
+ typedef std::function<void(TData1, TData2, TData3, TData4)> TFunType;
+ TData1 m_Data1;
+ TData2 m_Data2;
+ TData3 m_Data3;
+ TData4 m_Data4;
+ SSignalDataStruct4(const TData1 &d1, const TData2 &d2, const TData3 &d3, const TData4 &d4)
+ : m_Data1(d1)
+ , m_Data2(d2)
+ , m_Data3(d3)
+ , m_Data4(d4)
+ {
+ }
+ static void Send(ISignalSystem &system, void *sender, const char *sigName, const TData1 &d1,
+ const TData2 &d2, const TData3 &d3, const TData4 &d4)
+ {
+ TThisType theData(d1, d2, d3, d4);
+ system.Signal(sender, sigName, reinterpret_cast<const char *>(&theData), sizeof(TThisType));
+ }
+
+ static void Unpack(void *inSender, const char *inName, const char *inData, size_t inDataSize,
+ TFunType inHandler)
+ {
+ if (inDataSize == sizeof(TThisType)) {
+ const TThisType *theData = reinterpret_cast<const TThisType *>(inData);
+ inHandler(theData->m_Data1, theData->m_Data2, theData->m_Data2, theData->m_Data4);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static TGenericSignalHandlerFunc CreateHandler(TFunType inHandler)
+ {
+ return std::bind(&TThisType::Unpack, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, inHandler);
+ }
+
+ static std::shared_ptr<ISignalConnection> AddListener(ISignalSystem &inSystem, void *inSender,
+ const char *inName, TFunType inHandler)
+ {
+ return inSystem.AddListener(inSender, inName, CreateHandler(inHandler));
+ }
+};
+
+#define UICDM_SIGNALS_DEFINE_SPECIFIC_SIGNAL_STRUCT4(name, d1, d2, d3, d4) \
+ std::shared_ptr<ISignalConnection> Sig##name::AddListener( \
+ ISignalSystem &inSystem, void *inSender, std::function<void(d1, d2, d3, d4)> inHandler) \
+ { \
+ return SSignalDataStruct4<d1, d2, d3, d4>::AddListener(inSystem, inSender, #name, \
+ inHandler); \
+ } \
+ void Sig##name::Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \
+ const d3 &arg3, const d4 &arg4) \
+ { \
+ SSignalDataStruct4<d1, d2, d3, d4>::Send(system, sender, #name, arg1, arg2, arg3, arg4); \
+ }
+}
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMSignalStructs.h b/src/Authoring/UICDM/Systems/UICDMSignalStructs.h
new file mode 100644
index 00000000..6ac0ae4d
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSignalStructs.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSIGNALSTRUCTSH
+#define UICDMSIGNALSTRUCTSH
+#include "UICDMSignalSystem.h"
+// Helper structs for signals of different arity.
+namespace UICDM {
+// Helper defines to create static tables of signals
+// Macros with the same number of args but with 'declare' replaced by 'define
+// are available in UICDMSignalStructImpl.h. You will need to place these somewhere but
+// they rely on std::bind so I don't place them here.
+#define UICDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT0(name) \
+ struct Sig##name \
+ { \
+ static std::shared_ptr<ISignalConnection> \
+ AddListener(ISignalSystem &inSystem, void *inSender, std::function<void()> inHandler); \
+ static void Send(ISignalSystem &system, void *sender); \
+ };
+
+// Helper defines to create static tables of signals
+#define UICDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT1(name, d1) \
+ struct Sig##name \
+ { \
+ static std::shared_ptr<ISignalConnection> \
+ AddListener(ISignalSystem &inSystem, void *inSender, std::function<void(d1)> inHandler); \
+ static void Send(ISignalSystem &system, void *sender, const d1 &arg); \
+ };
+
+// Helper defines to create static tables of signals
+#define UICDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT2(name, d1, d2) \
+ struct Sig##name \
+ { \
+ static std::shared_ptr<ISignalConnection> \
+ AddListener(ISignalSystem &inSystem, void *inSender, \
+ std::function<void(d1, d2)> inHandler); \
+ static void Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2); \
+ };
+
+// Helper defines to create static tables of signals
+#define UICDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT3(name, d1, d2, d3) \
+ struct Sig##name \
+ { \
+ static std::shared_ptr<ISignalConnection> \
+ AddListener(ISignalSystem &inSystem, void *inSender, \
+ std::function<void(d1, d2, d3)> inHandler); \
+ static void Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \
+ const d3 &arg3); \
+ };
+
+// Helper defines to create static tables of signals
+#define UICDM_SIGNALS_DECLARE_SPECIFIC_SIGNAL_STRUCT4(name, d1, d2, d3, d4) \
+ struct Sig##name \
+ { \
+ static std::shared_ptr<ISignalConnection> \
+ AddListener(ISignalSystem &inSystem, void *inSender, \
+ std::function<void(d1, d2, d3, d4)> inHandler); \
+ static void Send(ISignalSystem &system, void *sender, const d1 &arg1, const d2 &arg2, \
+ const d3 &arg3, const d4 &arg4); \
+ };
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMSignalSystem.cpp b/src/Authoring/UICDM/Systems/UICDMSignalSystem.cpp
new file mode 100644
index 00000000..3058a247
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSignalSystem.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "UICDMSignalSystem.h"
+#include "EASTL/hash_map.h"
+
+using namespace UICDM;
+
+namespace {
+
+struct SSignalListener;
+class ISignalSystemImpl
+{
+public:
+ virtual ~ISignalSystemImpl() {}
+ virtual void RemoveListener(SSignalListener &inListener) = 0;
+};
+
+struct SSignalSystemKey
+{
+ void *m_Sender;
+ const char *m_SignalName;
+ SSignalSystemKey(void *inSender, const char *inSigName, IStringTable &inStrTable)
+ : m_Sender(inSender)
+ , m_SignalName(inStrTable.GetNarrowStr(inSigName))
+ {
+ }
+ SSignalSystemKey(const SSignalSystemKey &inOther)
+ : m_Sender(inOther.m_Sender)
+ , m_SignalName(inOther.m_SignalName)
+ {
+ }
+
+ SSignalSystemKey &operator=(const SSignalSystemKey &inOther)
+ {
+ if (this != &inOther) {
+ m_Sender = inOther.m_Sender;
+ m_SignalName = inOther.m_SignalName;
+ }
+ return *this;
+ }
+
+ bool operator==(const SSignalSystemKey &inOther) const
+ {
+ return m_Sender == inOther.m_Sender && m_SignalName == inOther.m_SignalName;
+ }
+};
+
+struct SSignalListener : ISignalConnection
+{
+ shared_ptr<ISignalSystemImpl> m_SignalSystem;
+ TGenericSignalHandlerFunc m_Handler;
+ SSignalSystemKey m_Key;
+ SSignalListener(shared_ptr<ISignalSystemImpl> inSystem, TGenericSignalHandlerFunc inHandler,
+ SSignalSystemKey inKey)
+ : m_SignalSystem(inSystem)
+ , m_Handler(inHandler)
+ , m_Key(inKey)
+ {
+ }
+ ~SSignalListener() { m_SignalSystem->RemoveListener(*this); }
+ void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize)
+ {
+ m_Handler(inSender, inName, inData, inDataSize);
+ }
+};
+
+typedef eastl::vector<SSignalListener *> TSignalListenerPtrList;
+}
+
+namespace eastl {
+template <>
+struct hash<SSignalSystemKey>
+{
+ size_t operator()(const SSignalSystemKey &inKey) const
+ {
+ return hash<void *>()(inKey.m_Sender) ^ hash<const char *>()(inKey.m_SignalName);
+ }
+};
+}
+
+namespace {
+typedef eastl::hash_map<SSignalSystemKey, TSignalListenerPtrList> TSignalHandlerMap;
+
+struct SSignalSystemImpl : public ISignalSystemImpl
+{
+ TSignalHandlerMap m_SignalHandlers;
+ shared_ptr<IStringTable> m_StringTable;
+ SSignalSystemImpl(shared_ptr<IStringTable> inStrTable)
+ : m_StringTable(inStrTable)
+ {
+ }
+
+ TSignalListenerPtrList *FindListenerList(const SSignalSystemKey &inKey)
+ {
+ TSignalHandlerMap::iterator theIter = m_SignalHandlers.find(inKey);
+ if (theIter != m_SignalHandlers.end())
+ return &theIter->second;
+ return NULL;
+ }
+
+ void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize)
+ {
+ TSignalListenerPtrList *theSignals =
+ FindListenerList(SSignalSystemKey(inSender, inName, *m_StringTable));
+ if (theSignals) {
+ for (eastl_size_t idx = 0, end = theSignals->size(); idx < end; ++idx) {
+ (*theSignals)[idx]->Signal(inSender, inName, inData, inDataSize);
+ }
+ }
+ }
+
+ void RemoveListener(SSignalListener &inListener) override
+ {
+ TSignalListenerPtrList *theSignals = FindListenerList(inListener.m_Key);
+ if (theSignals) {
+ // If we could allow unordered access then this could potentially be a lot faster.
+ TSignalListenerPtrList::iterator theFind =
+ eastl::find(theSignals->begin(), theSignals->end(), &inListener);
+ if (theFind != theSignals->end())
+ theSignals->erase(theFind);
+ }
+ }
+};
+
+struct SSignalSystem : public ISignalSystem
+{
+ shared_ptr<SSignalSystemImpl> m_System;
+ SSignalSystem(shared_ptr<IStringTable> inStrTable)
+ {
+ m_System = std::make_shared<SSignalSystemImpl>(inStrTable);
+ }
+
+ shared_ptr<ISignalConnection> AddListener(void *inSender, const char *inName,
+ TGenericSignalHandlerFunc inFunc) override
+ {
+ SSignalSystemKey theKey(inSender, inName, *m_System->m_StringTable);
+ TSignalHandlerMap::iterator theIter =
+ m_System->m_SignalHandlers.insert(eastl::make_pair(theKey, TSignalListenerPtrList()))
+ .first;
+ TSignalListenerPtrList &theList(theIter->second);
+ shared_ptr<SSignalListener> theSender =
+ std::make_shared<SSignalListener>(m_System, inFunc, theKey);
+ theList.push_back(theSender.get());
+ return theSender;
+ }
+
+ void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize) override
+ {
+ m_System->Signal(inSender, inName, inData, inDataSize);
+ }
+};
+}
+
+shared_ptr<ISignalSystem> ISignalSystem::CreateSignalSystem(shared_ptr<IStringTable> inStrTable)
+{
+ return std::make_shared<SSignalSystem>(inStrTable);
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMSignalSystem.h b/src/Authoring/UICDM/Systems/UICDMSignalSystem.h
new file mode 100644
index 00000000..bfd66c78
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSignalSystem.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSIGNALSYSTEMH
+#define UICDMSIGNALSYSTEMH
+#include <functional>
+#include "UICDMSignals.h"
+
+namespace UICDM {
+typedef std::function<void(void *, const char *, const char *, size_t)> TGenericSignalHandlerFunc;
+
+class ISignalSystem
+{
+protected:
+ virtual ~ISignalSystem() {}
+public:
+ virtual shared_ptr<ISignalConnection> AddListener(void *inSender, const char *inName,
+ TGenericSignalHandlerFunc inFunc) = 0;
+ virtual void Signal(void *inSender, const char *inName, const char *inData,
+ size_t inDataSize) = 0;
+
+ static shared_ptr<ISignalSystem> CreateSignalSystem(shared_ptr<IStringTable> inStrTable);
+};
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMSignals.h b/src/Authoring/UICDM/Systems/UICDMSignals.h
new file mode 100644
index 00000000..24351484
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSignals.h
@@ -0,0 +1,597 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSIGNALSH
+#define UICDMSIGNALSH
+#include "UICDMDataTypes.h"
+#include "UICDMHandles.h"
+#include "UICDMAnimation.h"
+#include "UICDMActionInfo.h"
+#include "UICDMValue.h"
+#include <functional>
+#include <string>
+
+namespace UICDM {
+// One may notice this looks a lot like std::signals.
+// One may also notice that I chose to hide the implementation completely instead
+// taking the route of boost/function.hpp instead.
+
+// This is because boost/signal.hpp includes boost/any.hpp and boost/any.hpp
+// doesn't currently compile in studio due to a #define problem.
+// Strings.h defines placeholder to be a number and boost/any.hpp uses
+// an inner class named placeholder...
+class ISignalConnection
+{
+public:
+ virtual ~ISignalConnection() {}
+};
+
+class ISignalItem
+{
+public:
+ virtual ~ISignalItem() {}
+};
+
+typedef std::shared_ptr<ISignalItem> TSignalItemPtr;
+
+typedef std::shared_ptr<ISignalConnection> TSignalConnectionPtr;
+
+class IInstancePropertyCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr ConnectInstancePropertyValue(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, const SValue &)>
+ &inCallback) = 0;
+};
+
+class IInstancePropertyCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SignalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+};
+
+class IDataCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr
+ ConnectInstanceCreated(const std::function<void(CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectBeforeInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstanceDerived(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstanceParentRemoved(
+ const std::function<void(CUICDMInstanceHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectPropertyAdded(const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle,
+ TCharPtr, DataModelDataType::Value)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectPropertyRemoved(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle, TCharPtr,
+ DataModelDataType::Value)> &inCallback) = 0;
+};
+
+class IDataCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SignalInstanceCreated(CUICDMInstanceHandle inInstance) = 0;
+ virtual void SignalBeforeInstanceDeleted(CUICDMInstanceHandle inInstance) = 0;
+ virtual void SignalInstanceDeleted(CUICDMInstanceHandle inInstance) = 0;
+ virtual void SignalInstanceDerived(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) = 0;
+ virtual void SignalInstanceParentRemoved(CUICDMInstanceHandle inInstance,
+ CUICDMInstanceHandle inParent) = 0;
+ virtual void SignalPropertyAdded(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, TCharPtr inName,
+ DataModelDataType::Value inDataType) = 0;
+ virtual void SignalPropertyRemoved(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, TCharPtr inName,
+ DataModelDataType::Value inDataType) = 0;
+};
+
+class ISlideCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr
+ ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectBeforeSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectSlideDerived(
+ const std::function<void(CUICDMSlideHandle, CUICDMSlideHandle, int)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstancePropertyValueSet(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstancePropertyValueRemoved(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle,
+ const SValue &)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectSlideTimeChanged(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+};
+
+class ISlideCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SendSlideCreated(CUICDMSlideHandle inSlide) = 0;
+ virtual void SendBeforeSlideDeleted(CUICDMSlideHandle inSlide) = 0;
+ virtual void SendSlideDeleted(CUICDMSlideHandle inSlide) = 0;
+ virtual void SendSlideDerived(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent,
+ int inIndex) = 0;
+ virtual void SendPropertyValueSet(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inParent, const SValue &inValue) = 0;
+ // This gives clients a chance to override a property value the first time it is set on a slide
+ virtual void SendPropertyValueRemoved(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inParent, const SValue &inValue) = 0;
+ virtual void SendSlideTimeChanged(CUICDMSlideHandle inSlide) = 0;
+};
+
+class ISlideGraphCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr ConnectGraphCreated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectGraphDeleted(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstanceAssociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstanceDissociated(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectGraphActiveSlide(
+ const std::function<void(CUICDMSlideGraphHandle, CUICDMSlideHandle)> &inCallback) = 0;
+};
+
+class ISlideGraphCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SendGraphCreated(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) = 0;
+ virtual void SendGraphDeleted(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) = 0;
+ virtual void SendInstanceAssociated(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) = 0;
+ virtual void SendInstanceDissociated(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) = 0;
+ virtual void SendGraphActiveSlide(CUICDMSlideGraphHandle inGraph,
+ CUICDMSlideHandle inSlide) = 0;
+};
+
+class IAnimationCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr ConnectAnimationCreated(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectBeforeAnimationDeleted(
+ const std::function<void(CUICDMAnimationHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectAnimationDeleted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMSlideHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle, size_t, EAnimationType)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectKeyframeInserted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectBeforeKeyframeErased(const std::function<void(CUICDMKeyframeHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectKeyframeErased(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle, const TKeyframe &)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectBeforeAllKeyframesErased(
+ const std::function<void(CUICDMAnimationHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectKeyframeUpdated(
+ const std::function<void(CUICDMKeyframeHandle, const TKeyframe &)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectFirstKeyframeDynamicSet(
+ const std::function<void(CUICDMAnimationHandle, bool)> &inCallback) = 0;
+};
+
+class IAnimationCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SendAnimationCreated(CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType) = 0;
+ virtual void SendBeforeAnimationDeleted(CUICDMAnimationHandle inAnimation) = 0;
+ virtual void SendAnimationDeleted(CUICDMAnimationHandle inAnimation, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, size_t inIndex,
+ EAnimationType inAnimationType) = 0;
+ virtual void SendKeyframeInserted(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0;
+ virtual void SendBeforeKeyframeErased(CUICDMKeyframeHandle inAnimation) = 0;
+ virtual void SendKeyframeErased(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0;
+ virtual void SendBeforeAllKeyframesErased(CUICDMAnimationHandle inAnimation) = 0;
+ virtual void SendKeyframeUpdated(CUICDMKeyframeHandle inKeyframe, const TKeyframe &inData) = 0;
+ virtual void SendFirstKeyframeDynamicSet(CUICDMAnimationHandle inAnimation,
+ bool inKeyframeDynamic) = 0;
+};
+
+class IActionCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr ConnectTriggerObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectTargetObjectSet(
+ const std::function<void(CUICDMActionHandle, SObjectRefType &)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectEventSet(
+ const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectHandlerSet(
+ const std::function<void(CUICDMActionHandle, const wstring &)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectHandlerArgumentAdded(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectHandlerArgumentRemoved(
+ const std::function<void(CUICDMActionHandle, CUICDMHandlerArgHandle, const TCharStr &,
+ HandlerArgumentType::Value, DataModelDataType::Value)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectHandlerArgumentValueSet(
+ const std::function<void(CUICDMHandlerArgHandle, const SValue &)> &inCallback) = 0;
+};
+
+class IActionCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SendTriggerObjectSet(CUICDMActionHandle inAction,
+ SObjectRefType &inTriggerObject) = 0;
+ virtual void SendTargetObjectSet(CUICDMActionHandle inAction,
+ SObjectRefType &inTargetObject) = 0;
+ virtual void SendEventSet(CUICDMActionHandle inAction, const wstring &inEventHandle) = 0;
+ virtual void SendHandlerSet(CUICDMActionHandle inAction, const wstring &inActionName) = 0;
+
+ virtual void SendHandlerArgumentAdded(CUICDMActionHandle inAction,
+ CUICDMHandlerArgHandle inHandlerArgument,
+ const TCharStr &inName, HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) = 0;
+ virtual void SendHandlerArgumentRemoved(CUICDMActionHandle inAction,
+ CUICDMHandlerArgHandle inHandlerArgument,
+ const TCharStr &inName, HandlerArgumentType::Value inArgType,
+ DataModelDataType::Value inValueType) = 0;
+ virtual void SendHandlerArgumentValueSet(CUICDMHandlerArgHandle inHandlerArgument,
+ const SValue &inValue) = 0;
+};
+
+class IActionSystemSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr ConnectActionCreated(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectActionDeleted(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) = 0;
+};
+
+class IActionSystemSignalSender : public ISignalItem
+{
+public:
+ virtual void SendActionCreated(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendActionDeleted(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) = 0;
+};
+
+class ICustomPropCoreSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr ConnectCustomPropertyCreated(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomPropertyDeleted(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomPropertyModified(
+ const std::function<void(CUICDMPropertyHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectCustomEventCreated(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomEventDeleted(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectCustomEventModified(const std::function<void(CUICDMEventHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectCustomHandlerCreated(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerDeleted(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectCustomHandlerModified(const std::function<void(CUICDMHandlerHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectCustomHandlerParamCreated(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerParamDeleted(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerParamModified(
+ const std::function<void(CUICDMHandlerParamHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectCustomReferencesModified(
+ const std::function<void(CUICDMInstanceHandle, const TCharStr &)> &inCallback) = 0;
+};
+
+class ICustomPropCoreSignalSender : public ISignalItem
+{
+public:
+ virtual void SendCustomPropertyCreated(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomPropertyDeleted(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomPropertyModified(CUICDMPropertyHandle inProp) = 0;
+
+ virtual void SendCustomEventCreated(CUICDMEventHandle inEvent,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomEventDeleted(CUICDMEventHandle inEvent,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomEventModified(CUICDMEventHandle inEvent) = 0;
+
+ virtual void SendCustomHandlerCreated(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomHandlerDeleted(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomHandlerModified(CUICDMHandlerHandle inHandler) = 0;
+
+ virtual void SendCustomHandlerParamCreated(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) = 0;
+ virtual void SendCustomHandlerParamDeleted(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) = 0;
+ virtual void SendCustomHandlerParamModified(CUICDMHandlerParamHandle inParameter) = 0;
+
+ virtual void SendCustomReferencesModified(CUICDMInstanceHandle inOwner,
+ const TCharStr &inString) = 0;
+};
+
+class ISlideSystemSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr
+ ConnectMasterCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectMasterDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectSlideCreated(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectSlideDeleted(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectSlideRearranged(
+ const std::function<void(CUICDMSlideHandle, int, int)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstanceAssociated(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectInstanceDissociated(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectPropertyLinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectPropertyUnlinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectActiveSlide(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle, CUICDMSlideHandle)>
+ &inCallback) = 0;
+};
+
+class ISlideSystemSignalSender : public ISignalItem
+{
+public:
+ virtual void SendMasterCreated(CUICDMSlideHandle inMaster) = 0;
+ virtual void SendMasterDeleted(CUICDMSlideHandle inMaster) = 0;
+ virtual void SendSlideCreated(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inSlide) = 0;
+ virtual void SendSlideDeleted(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inSlide) = 0;
+ virtual void SendSlideRearranged(CUICDMSlideHandle inMaster, int inOldIndex,
+ int inNewIndex) = 0;
+ virtual void SendInstanceAssociated(CUICDMSlideHandle inMaster,
+ CUICDMInstanceHandle inInstance) = 0;
+ virtual void SendInstanceDissociated(CUICDMSlideHandle inMaster,
+ CUICDMInstanceHandle inInstance) = 0;
+ virtual void SendPropertyLinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual void SendPropertyUnlinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual void SendActiveSlide(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inOldSlide, CUICDMSlideHandle inNewSlide) = 0;
+};
+
+class IStudioFullSystemSignalProvider : public ISignalItem
+{
+public:
+ virtual TSignalConnectionPtr
+ ConnectSlideCreated(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectSlideDeleted(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectSlideRearranged(
+ const std::function<void(CUICDMSlideHandle, int, int)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectBeginComponentSeconds(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectComponentSeconds(const std::function<void(CUICDMSlideHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectPropertyLinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectPropertyUnlinked(
+ const std::function<void(CUICDMSlideHandle, CUICDMInstanceHandle, CUICDMPropertyHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectActiveSlide(
+ const std::function<void(CUICDMSlideHandle, int, CUICDMSlideHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr
+ ConnectInstanceCreated(const std::function<void(CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectInstanceDeleted(const std::function<void(CUICDMInstanceHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr
+ ConnectAnimationCreated(const std::function<void(CUICDMAnimationHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectAnimationDeleted(const std::function<void(CUICDMAnimationHandle, CUICDMInstanceHandle,
+ CUICDMPropertyHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectKeyframeInserted(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectKeyframeErased(
+ const std::function<void(CUICDMAnimationHandle, CUICDMKeyframeHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectKeyframeUpdated(const std::function<void(CUICDMKeyframeHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectFirstKeyframeDynamicSet(
+ const std::function<void(CUICDMAnimationHandle, bool)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectInstancePropertyValue(
+ const std::function<void(CUICDMInstanceHandle, CUICDMPropertyHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectActionCreated(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectActionDeleted(
+ const std::function<void(CUICDMActionHandle, CUICDMSlideHandle, CUICDMInstanceHandle)>
+ &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectTriggerObjectSet(const std::function<void(CUICDMActionHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectTargetObjectSet(const std::function<void(CUICDMActionHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectEventSet(const std::function<void(CUICDMActionHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectHandlerSet(const std::function<void(CUICDMActionHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectHandlerArgumentValueSet(
+ const std::function<void(CUICDMHandlerArgHandle)> &inCallback) = 0;
+
+ virtual TSignalConnectionPtr ConnectCustomPropertyCreated(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomPropertyDeleted(
+ const std::function<void(CUICDMPropertyHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomPropertyModified(
+ const std::function<void(CUICDMPropertyHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomEventCreated(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomEventDeleted(
+ const std::function<void(CUICDMEventHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectCustomEventModified(const std::function<void(CUICDMEventHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerCreated(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerDeleted(
+ const std::function<void(CUICDMHandlerHandle, CUICDMInstanceHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr
+ ConnectCustomHandlerModified(const std::function<void(CUICDMHandlerHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerParamCreated(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerParamDeleted(
+ const std::function<void(CUICDMHandlerParamHandle, CUICDMHandlerHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomHandlerParamModified(
+ const std::function<void(CUICDMHandlerParamHandle)> &inCallback) = 0;
+ virtual TSignalConnectionPtr ConnectCustomReferencesModified(
+ const std::function<void(CUICDMInstanceHandle, const TCharStr &)> &inCallback) = 0;
+};
+
+class IStudioFullSystemSignalSender : public ISignalItem
+{
+public:
+ virtual void SendSlideCreated(CUICDMSlideHandle inSlide) = 0;
+ virtual void SendSlideDeleted(CUICDMSlideHandle inSlide) = 0;
+ virtual void SendSlideRearranged(CUICDMSlideHandle inMaster, int inOldIndex,
+ int inNewIndex) = 0;
+ virtual void SendComponentSeconds(CUICDMSlideHandle inMaster) = 0;
+ virtual void SendBeginComponentSeconds(CUICDMSlideHandle inMaster) = 0;
+ virtual void SendPropertyLinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual void SendPropertyUnlinked(CUICDMSlideHandle inMaster, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual void SendActiveSlide(CUICDMSlideHandle inMaster, int inIndex,
+ CUICDMSlideHandle inSlide) = 0;
+
+ virtual void SendInstanceCreated(CUICDMInstanceHandle inInstance) = 0;
+ virtual void SendInstanceDeleted(CUICDMInstanceHandle inInstance) = 0;
+
+ virtual void SendAnimationCreated(CUICDMAnimationHandle inAnimation,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual void SendAnimationDeleted(CUICDMAnimationHandle inAnimation,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual void SendKeyframeInserted(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe) = 0;
+ virtual void SendKeyframeErased(CUICDMAnimationHandle inAnimation,
+ CUICDMKeyframeHandle inKeyframe) = 0;
+ virtual void SendKeyframeUpdated(CUICDMKeyframeHandle inKeyframe) = 0;
+ virtual void SendConnectFirstKeyframeDynamicSet(CUICDMAnimationHandle inAnimation,
+ bool inDynamic) = 0;
+
+ virtual void SendInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+
+ virtual void SendActionCreated(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendActionDeleted(CUICDMActionHandle inAction, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendTriggerObjectSet(CUICDMActionHandle inAction) = 0;
+ virtual void SendTargetObjectSet(CUICDMActionHandle inAction) = 0;
+ virtual void SendEventSet(CUICDMActionHandle inAction) = 0;
+ virtual void SendHandlerSet(CUICDMActionHandle inAction) = 0;
+ virtual void SendHandlerArgumentValueSet(CUICDMHandlerArgHandle inHandlerArgument) = 0;
+
+ virtual void SendCustomPropertyCreated(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomPropertyDeleted(CUICDMPropertyHandle inProp,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomPropertyModified(CUICDMPropertyHandle inProp) = 0;
+ virtual void SendCustomEventCreated(CUICDMEventHandle inEvent,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomEventDeleted(CUICDMEventHandle inEvent,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomEventModified(CUICDMEventHandle inEvent) = 0;
+ virtual void SendCustomHandlerCreated(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomHandlerDeleted(CUICDMHandlerHandle inHandler,
+ CUICDMInstanceHandle inOwner) = 0;
+ virtual void SendCustomHandlerModified(CUICDMHandlerHandle inHandler) = 0;
+ virtual void SendCustomHandlerParamCreated(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) = 0;
+ virtual void SendCustomHandlerParamDeleted(CUICDMHandlerParamHandle inParameter,
+ CUICDMHandlerHandle inHandler) = 0;
+ virtual void SendCustomHandlerParamModified(CUICDMHandlerParamHandle inParameter) = 0;
+ virtual void SendCustomReferencesModified(CUICDMInstanceHandle inOwner,
+ const TCharStr &inString) = 0;
+};
+
+// Use this if you want to register for only a specific instance or specific property
+template <typename TTransaction>
+inline void MaybackCallbackInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ CUICDMInstanceHandle inDesiredInstance,
+ CUICDMPropertyHandle inDesiredProperty,
+ TTransaction inCallback)
+{
+ if ((!inDesiredInstance.Valid() || (inDesiredInstance == inInstance))
+ && (!inDesiredProperty.Valid() || (inDesiredProperty == inProperty)))
+ inCallback(inInstance, inProperty);
+}
+
+void SetUICDMSignalsEnabled(bool inEnabled);
+// Defaults to true
+bool AreUICDMSignalsEnabled();
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMSlideCore.h b/src/Authoring/UICDM/Systems/UICDMSlideCore.h
new file mode 100644
index 00000000..c4e3cdb8
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSlideCore.h
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSLIDECOREH
+#define UICDMSLIDECOREH
+#include "UICDMHandles.h"
+#include "UICDMDataTypes.h"
+#include "HandleSystemBase.h"
+#include "UICDMStringTable.h"
+#include "UICDMDataCore.h"
+
+namespace UICDM {
+typedef std::pair<CUICDMInstanceHandle, CUICDMPropertyHandle> TInstancePropertyPair;
+typedef std::vector<TInstancePropertyPair> TInstancePropertyPairList;
+
+// instance,property,value
+typedef std::tuple<CUICDMInstanceHandle, CUICDMPropertyHandle, SValue> TSlideEntry;
+typedef std::vector<TSlideEntry> TSlideEntryList;
+
+class ISlideCore : public IHandleBase
+{
+public:
+ virtual ~ISlideCore() {}
+ virtual TStringTablePtr GetStringTablePtr() const = 0;
+ virtual IStringTable &GetStringTable() const = 0;
+ //===============================================================
+ // Slide lifetime management
+ //===============================================================
+ /**
+ * Create a new slide. Slides must have an instance allocated for them.
+ */
+ virtual CUICDMSlideHandle CreateSlide(CUICDMInstanceHandle inInstance) = 0;
+ /**
+ * Return the instance that was allocated for this slide.
+ */
+ virtual CUICDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inSlide) const = 0;
+ /**
+ * Reverse lookup into the slide system so you can match slides to instances.
+ */
+ virtual CUICDMSlideHandle GetSlideByInstance(CUICDMInstanceHandle inSlide) const = 0;
+ /**
+ * Delete a given slide. This recursively deletes all children. All associated instances
+ * are returned in the outInstances list so the caller can further delete them.
+ * The deleted object is removed from the parent's list of children. Child objects are
+ * also deleted.
+ */
+ virtual void DeleteSlide(CUICDMSlideHandle inSlide, TInstanceHandleList &outInstances) = 0;
+ /**
+ * Return all of the slides in the core.
+ */
+ virtual void GetSlides(TSlideHandleList &outSlides) const = 0;
+
+ virtual float GetSlideTime(CUICDMSlideHandle inSlide) const = 0;
+
+ virtual void SetSlideTime(CUICDMSlideHandle inSlide, float inNewTime) = 0;
+
+ //===============================================================
+ // Slide derivation
+ //===============================================================
+ /**
+ * Derive a slide from another slide. This simply provides an alternate path for property
+ *lookup
+ * if it isn't found on this slide. OK for parent to be an invalid handle. It is also fine
+ * for the slide to have a valid parent; all involved parties are notified and updated.
+ */
+ virtual void DeriveSlide(CUICDMSlideHandle inSlide, CUICDMSlideHandle inParent,
+ int inIndex = -1) = 0;
+ /**
+ * Return the parent slide for this slide. Invalid handle if no parent.
+ */
+ virtual CUICDMSlideHandle GetParentSlide(CUICDMSlideHandle inSlide) const = 0;
+ /**
+ * Return a list of derived slides for this slide.
+ */
+ virtual void GetChildSlides(CUICDMSlideHandle inSlide, TSlideHandleList &outChildren) const = 0;
+
+ /**
+ * Return the index of this child. Exception if child isn't found
+ */
+ virtual int GetChildIndex(CUICDMSlideHandle inParent, CUICDMSlideHandle inChild) const = 0;
+ //===============================================================
+
+ //===============================================================
+ // Instance Property Access
+ //===============================================================
+ /**
+ * Get this property from this instance in this slide. Includes lookup into any parent slides.
+ */
+ virtual bool GetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+
+ /**
+ * Set this property. If this slide doesn't already contain an entry
+ *(PushPropertyValueToChildren)
+ * then this will attempt to set it on the parent slide. If it does not have a parent slide or
+ *if
+ * it already has a property entry then it sets the value locally.
+ */
+ virtual void SetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+
+ /**
+ * Set this property on this slide; do not try to set on parent slide under any circumstances.
+ *Always adds entry to this slide.
+ */
+ virtual void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+
+ /**
+ * Return the value for this property if it exists on this slide.
+ */
+ virtual bool GetSpecificInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+
+ /**
+ * Return all of the properties for this instance stored on this slide.
+ */
+ virtual void GetSpecificInstancePropertyValues(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ TPropertyHandleValuePairList &outValues) = 0;
+
+ /**
+ * Get all of the property entries for the slide.
+ */
+ virtual void GetSlidePropertyEntries(CUICDMSlideHandle inSlide,
+ TSlideEntryList &outEntries) const = 0;
+
+ /**
+ * Set this property value on all my child slides.
+ */
+ virtual void PushPropertyValueToChildren(CUICDMSlideHandle inParent,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+
+ /**
+ * If any property entries in slide1 intersect (have matching instance and property handles)
+ *with slide 2,
+ * add said property entry from slide1 to outEntries;
+ */
+ virtual void GetIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ TSlideEntryList &outEntries) const = 0;
+
+ /**
+ * Take the intersection of the properties of slide1 and slide2 and push values from slide1 to
+ *destination.
+ * Used for new slide operations.
+ */
+ virtual void PushIntersectingProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide2,
+ CUICDMSlideHandle inDestination) = 0;
+
+ /**
+ * Ensure the children of this parent item do not contain entries for a given property.
+ */
+ virtual void ClearChildrenPropertyValues(CUICDMSlideHandle inParent,
+ CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) = 0;
+
+ /**
+ * Delete all property entries related to this instance.
+ */
+ virtual void DeleteAllInstanceEntries(CUICDMInstanceHandle inHandle) = 0;
+
+ /**
+ * Delete all of the property entries related to this property
+ */
+ virtual void DeleteAllPropertyEntries(CUICDMPropertyHandle inHandle) = 0;
+
+ /**
+ * Delete all property entries that have an instance in the instances list *and*
+ * a property in the properties list.
+ */
+ virtual void DeleteAllInstancePropertyEntries(const TInstanceHandleList &inInstances,
+ const TPropertyHandleList &inProperties) = 0;
+
+ /**
+ * Does this slide contain this property?
+ */
+ virtual bool ContainsProperty(CUICDMSlideHandle inSlide, CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) const = 0;
+
+ /**
+ * Copy the properties from the source slide and source instance to the destination slide and
+ *destination
+ * instance.
+ */
+ virtual void CopyProperties(CUICDMSlideHandle inSourceSlide,
+ CUICDMInstanceHandle inSourceInstance,
+ CUICDMSlideHandle inDestSlide,
+ CUICDMInstanceHandle inDestInstance) = 0;
+
+ virtual bool IsSlide(CUICDMSlideHandle inSlide) const = 0;
+};
+
+typedef std::shared_ptr<ISlideCore> TSlideCorePtr;
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMSlideGraphCore.h b/src/Authoring/UICDM/Systems/UICDMSlideGraphCore.h
new file mode 100644
index 00000000..28032725
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSlideGraphCore.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSLIDEGRAPHCOREH
+#define UICDMSLIDEGRAPHCOREH
+
+#include "UICDMHandles.h"
+#include "HandleSystemBase.h"
+
+namespace UICDM {
+
+typedef std::pair<CUICDMSlideHandle, CUICDMInstanceHandle> TSlideInstancePair;
+typedef std::vector<TSlideInstancePair> TSlideInstancePairList;
+typedef std::pair<CUICDMSlideGraphHandle, CUICDMSlideHandle> TGraphSlidePair;
+
+/**
+ * Binding instances to slide graphs.
+ */
+class ISlideGraphCore : public IHandleBase
+{
+public:
+ virtual ~ISlideGraphCore() {}
+
+ /**
+ * A slide graph is used to associate a set of instances to a set of slides.
+ * This allows rapid lookup of properties, as an implementation of these.
+ * There are a few assumptions here. First is that a given slide can be a member
+ * of one and only one graph (i.e. it does not derive from another slide outside of the graph).
+ * Second is that an instance is a member of one and only one graph.
+ */
+ virtual CUICDMSlideGraphHandle CreateSlideGraph(CUICDMSlideHandle inRoot) = 0;
+ virtual CUICDMSlideHandle GetGraphRoot(CUICDMSlideGraphHandle inGraph) const = 0;
+ virtual CUICDMSlideGraphHandle GetSlideGraph(CUICDMSlideHandle inSlide) const = 0;
+ virtual void GetSlideGraphs(TSlideGraphHandleList &outGraphs) const = 0;
+ virtual void DeleteSlideGraph(CUICDMSlideGraphHandle inHandle) = 0;
+
+ /**
+ * Associate a given instance handle with a given graph. This will ensure that property
+ *lookups
+ * will travel through this graph before they hit the main data core. Instances may be
+ *associated
+ * with a sub-slide of a given graph, not just the root. An instance associated with the root
+ *is
+ * implicitly associated with any root-derived slides.
+ */
+ virtual void AssociateInstance(CUICDMSlideGraphHandle inSlideGraph, CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) = 0;
+ virtual void GetAssociatedInstances(CUICDMSlideGraphHandle inSlideGraph,
+ TSlideInstancePairList &outAssociations) const = 0;
+ virtual TGraphSlidePair GetAssociatedGraph(CUICDMInstanceHandle inInstance) const = 0;
+ virtual void DissociateInstance(CUICDMInstanceHandle inInstance) = 0;
+
+ /**
+ * All graphs always have an active slide. This is assumed to be the root right off the bat.
+ */
+ virtual void SetGraphActiveSlide(CUICDMSlideGraphHandle inGraph, CUICDMSlideHandle inSlide) = 0;
+ virtual CUICDMSlideHandle GetGraphActiveSlide(CUICDMSlideGraphHandle inGraph) const = 0;
+};
+
+typedef std::shared_ptr<ISlideGraphCore> TSlideGraphCorePtr;
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMSlides.h b/src/Authoring/UICDM/Systems/UICDMSlides.h
new file mode 100644
index 00000000..017f6516
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMSlides.h
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMSLIDESH
+#define UICDMSLIDESH
+#include "UICDMHandles.h"
+#include "UICDMSlideCore.h"
+
+namespace UICDM {
+/**
+ * Some properties point to instances which act like extended properties.
+ * An example of this would be the images on materials. If a material has an
+ * image in one of its slots, that image should be duplicated upon property unlink
+ * and deleted upon property link. It (and its animations) should be duplicated upon
+ * create slide and deleted upon slide destruction such that the concept that the image
+ * is really a property on the material stays sound.
+ */
+class IPropertyInstanceInfo
+{
+public:
+ virtual ~IPropertyInstanceInfo() {}
+
+ /**
+ * Return the instance that relates to this property
+ */
+ virtual CUICDMInstanceHandle GetInstanceForProperty(const SValue &inValue) = 0;
+
+ /**
+ * Duplicate this instance and whichever properties and animations you desire,
+ * returning a new data model value that will be set on the newly created property.
+ * Don't forget to associate the instance with a the dest slide. I doubt things
+ * will work correctly if you do not.
+ */
+ virtual SValue CreateInstanceForProperty(CUICDMSlideHandle inSourceSlide,
+ CUICDMSlideHandle inDestSlide,
+ CUICDMInstanceHandle inInstance) = 0;
+};
+
+typedef std::shared_ptr<IPropertyInstanceInfo> TPropertyInstanceInfoPtr;
+
+struct SInstanceSlideInformation
+{
+ // The slide associated with the instance
+ CUICDMSlideHandle m_AssociatedSlide;
+ // The master slide of the component.
+ CUICDMSlideHandle m_MasterSlide;
+ // The active slide of the component.
+ CUICDMSlideHandle m_ActiveSlide;
+ // The current milliseconds of the active slide on the component.
+ long m_ComponentMilliseconds;
+
+ SInstanceSlideInformation()
+ : m_ComponentMilliseconds(0)
+ {
+ }
+ SInstanceSlideInformation(CUICDMSlideHandle inAssoc, CUICDMSlideHandle inMaster,
+ CUICDMSlideHandle inActive, long inMilliseconds)
+ : m_AssociatedSlide(inAssoc)
+ , m_MasterSlide(inMaster)
+ , m_ActiveSlide(inActive)
+ , m_ComponentMilliseconds(inMilliseconds)
+ {
+ }
+};
+
+class ISlideSystem
+{
+public:
+ virtual ~ISlideSystem() {}
+ virtual CUICDMSlideHandle CreateMasterSlide() = 0;
+ virtual CUICDMSlideHandle CreateSlide(CUICDMSlideHandle inMaster, int inIndex = -1) = 0;
+ // Duplicate this slide and put it into the master's child lists at index.
+ virtual CUICDMSlideHandle DuplicateSlide(CUICDMSlideHandle inSourceSlide, int inDestIndex) = 0;
+ virtual CUICDMSlideHandle GetMasterSlide(CUICDMSlideHandle inSlide) const = 0;
+ virtual bool IsMasterSlide(CUICDMSlideHandle inSlide) const = 0;
+ virtual CUICDMSlideHandle GetMasterSlideByComponentGuid(SLong4 inGuid) const = 0;
+ // Indexes are 1 based. Index 0 refers to the master slide; you can't delete this.
+ virtual void DeleteSlideByIndex(CUICDMSlideHandle inMaster, size_t inIndex) = 0;
+ virtual void GetSlideReferencedInstances(CUICDMSlideHandle inMaster, size_t inIndex,
+ TInstanceHandleList &outReferencedInstances) = 0;
+ virtual CUICDMSlideHandle GetSlideByIndex(CUICDMSlideHandle inMaster, size_t inIndex) const = 0;
+ virtual void SetActiveSlide(CUICDMSlideHandle inMaster, size_t inIndex) = 0;
+ virtual void RearrangeSlide(CUICDMSlideHandle inMaster, size_t inOldIndex,
+ size_t inNewIndex) = 0;
+ /**
+ * Set the current component time. This object will figure out the component from the slide.
+ */
+ virtual void SetComponentSeconds(CUICDMSlideHandle inSlide, float inSeconds) = 0;
+ /**
+ * Return the current time of the component
+ */
+ virtual float GetComponentSeconds(CUICDMSlideHandle inSlide) const = 0;
+ virtual long GetComponentSecondsLong(CUICDMSlideHandle inSlide) const = 0;
+ virtual long GetComponentSecondsLong(CUICDMInstanceHandle inInstance) const = 0;
+
+ // The fastest way possible, get all of the slide information for this instance.
+ virtual SInstanceSlideInformation
+ GetInstanceSlideInformation(CUICDMInstanceHandle inInstance) const = 0;
+ /**
+ * Slide count includes the master slide;
+ */
+ virtual size_t GetSlideCount(CUICDMSlideHandle inMaster) const = 0;
+ /**
+ * Use the instance for storing information such as name, or the GUID of the object
+ * this slide links to.
+ */
+ virtual CUICDMInstanceHandle GetSlideInstance(CUICDMSlideHandle inSlide) const = 0;
+ /**
+ * Reverse lookup into the slide system so you can match slides to instances.
+ */
+ virtual CUICDMSlideHandle GetSlideByInstance(CUICDMInstanceHandle inInstance) const = 0;
+ /**
+ * Slide may be either a master slide
+ */
+ virtual void AssociateInstanceWithSlide(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) = 0;
+ virtual CUICDMSlideHandle GetAssociatedSlide(CUICDMInstanceHandle inInstance) const = 0;
+ virtual void GetAssociatedInstances(
+ CUICDMSlideHandle inMaster,
+ std::vector<std::pair<CUICDMSlideHandle, CUICDMInstanceHandle>> &outAssociations) const = 0;
+ virtual void GetAssociatedInstances(CUICDMSlideHandle inSlide,
+ TInstanceHandleList &outAssociations) const = 0;
+ virtual void LinkProperty(CUICDMInstanceHandle inInstance, CUICDMPropertyHandle inProperty) = 0;
+ virtual void UnlinkProperty(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) = 0;
+ virtual bool IsPropertyLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+ virtual bool CanPropertyBeLinked(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+ virtual void GetUnionOfProperties(CUICDMSlideHandle inSlide1, CUICDMSlideHandle inSlide,
+ TInstancePropertyPairList &outProperties) const = 0;
+
+ virtual bool GetSlidePropertyValue(size_t inSlide, CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty, SValue &outValue) = 0;
+
+ virtual void SetActiveSlide(CUICDMSlideHandle inSlide) = 0;
+ virtual CUICDMSlideHandle GetAssociatedSlide(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty) const = 0;
+
+ virtual bool SlideValid(CUICDMSlideHandle inSlide) const = 0;
+ virtual int GetSlideIndex(CUICDMSlideHandle inSlide) const = 0;
+ virtual int GetActiveSlideIndex(CUICDMSlideHandle inMaster) const = 0;
+ virtual CUICDMSlideHandle GetActiveSlide(CUICDMSlideHandle inMaster) const = 0;
+ virtual CUICDMInstanceHandle GetSlideSelectedInstance(CUICDMSlideHandle inSlide) const = 0;
+ virtual void SetSlideSelectedInstance(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance) = 0;
+
+ virtual CUICDMSlideHandle GetApplicableSlide(CUICDMInstanceHandle inHandle,
+ CUICDMPropertyHandle inProperty) = 0;
+
+ virtual bool GetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+ virtual bool GetCanonicalInstancePropertyValue(CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ SValue &outValue) const = 0;
+ virtual void ForceSetInstancePropertyValue(CUICDMSlideHandle inSlide,
+ CUICDMInstanceHandle inInstance,
+ CUICDMPropertyHandle inProperty,
+ const SValue &inValue) = 0;
+
+ /**
+ * Let this object know that this property will sometimes reference another property
+ * and give an outside entity the chance to create new objects and properties when
+ * the property is unlinked and linked.
+ */
+ virtual void RegisterPropertyInstance(CUICDMPropertyHandle inPropertyHandle,
+ TPropertyInstanceInfoPtr inPropertyInfo) = 0;
+};
+
+typedef std::shared_ptr<ISlideSystem> TSlideSystemPtr;
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMStringTable.cpp b/src/Authoring/UICDM/Systems/UICDMStringTable.cpp
new file mode 100644
index 00000000..d3e15cfd
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMStringTable.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "UICDMStringTable.h"
+#include "foundation/StringTable.h"
+#include "foundation/TrackingAllocator.h"
+
+using namespace UICDM;
+using namespace eastl;
+using namespace qt3ds;
+
+namespace {
+
+struct StringTableImpl : public IStringTable
+{
+ qt3ds::foundation::MallocAllocator m_MallocAllocator;
+ qt3ds::foundation::IStringTable &m_StringTable;
+ StringTableImpl()
+ : m_StringTable(qt3ds::foundation::IStringTable::CreateStringTable(m_MallocAllocator))
+ {
+ m_StringTable.addRef();
+ }
+ StringTableImpl(qt3ds::foundation::IStringTable &inStrTable)
+ : m_StringTable(inStrTable)
+ {
+ m_StringTable.addRef();
+ }
+
+ virtual ~StringTableImpl() { m_StringTable.release(); }
+ const wchar_t *RegisterStr(const wchar_t *inStr) override
+ {
+ return m_StringTable.GetWideStr(inStr);
+ }
+ const char8_t *RegisterStr(const char8_t *inStr) override
+ {
+ return m_StringTable.GetNarrowStr(inStr);
+ }
+ // Get the utf-8 or utf-(sizeof wchar_t) converted strings
+ const wchar_t *GetWideStr(const char8_t *inStr) override
+ {
+ return m_StringTable.GetWideStr(inStr);
+ }
+ const char8_t *GetNarrowStr(const wchar_t *inStr) override
+ {
+ return m_StringTable.GetNarrowStr(inStr);
+ }
+ qt3ds::foundation::IStringTable &GetRenderStringTable() override { return m_StringTable; }
+};
+}
+
+TStringTablePtr IStringTable::CreateStringTable()
+{
+ return std::make_shared<StringTableImpl>();
+}
+
+TStringTablePtr IStringTable::CreateStringTable(qt3ds::foundation::IStringTable &inStrTable)
+{
+ return std::make_shared<StringTableImpl>(std::ref(inStrTable));
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMStringTable.h b/src/Authoring/UICDM/Systems/UICDMStringTable.h
new file mode 100644
index 00000000..7fea9a08
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMStringTable.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTSTRINGTABLEH
+#define UICIMPORTSTRINGTABLEH
+
+#include <string>
+#include <EABase/eabase.h>
+
+namespace qt3ds {
+namespace foundation {
+ class IStringTable;
+}
+}
+
+namespace UICDM {
+
+class IStringTable
+{
+public:
+ virtual ~IStringTable() {}
+
+ virtual const wchar_t *RegisterStr(const wchar_t *inStr) = 0;
+ virtual const char8_t *RegisterStr(const char8_t *inStr) = 0;
+ // Get the utf-8 or utf-(sizeof wchar_t) converted strings
+ virtual const wchar_t *GetWideStr(const char8_t *inStr) = 0;
+ virtual const char8_t *GetNarrowStr(const wchar_t *inStr) = 0;
+
+ const wchar_t *GetWideStr(const wchar_t *inStr) { return RegisterStr(inStr); }
+ const char8_t *GetNarrowStr(const char8_t *inStr) { return RegisterStr(inStr); }
+
+ const wchar_t *RegisterStr(const std::wstring &inStr) { return RegisterStr(inStr.c_str()); }
+ const char8_t *RegisterStr(const std::string &inStr) { return RegisterStr(inStr.c_str()); }
+
+ virtual qt3ds::foundation::IStringTable &GetRenderStringTable() = 0;
+
+ static std::shared_ptr<IStringTable> CreateStringTable();
+ static std::shared_ptr<IStringTable>
+ CreateStringTable(qt3ds::foundation::IStringTable &inStrTable);
+};
+typedef std::shared_ptr<IStringTable> TStringTablePtr;
+};
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMTestOps.h b/src/Authoring/UICDM/Systems/UICDMTestOps.h
new file mode 100644
index 00000000..19d4dc1d
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMTestOps.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMOPSH
+#define UICDMOPSH
+
+namespace UICDM {
+inline const TCharStr &GetPropertyName(const IDataCore &inModel, CUICDMPropertyHandle inProperty)
+{
+ return inModel.GetProperty(inProperty).m_Name;
+}
+
+inline bool PropertyNameMatches(const IDataCore &inModel, const TCharStr &inName,
+ CUICDMPropertyHandle inProperty)
+{
+ return inName == GetPropertyName(inModel, inProperty);
+}
+
+inline const CUICDMPropertyHandle
+GetPropertyByName(const IDataCore &inModel, CUICDMInstanceHandle inInstance, const TCharStr &inName)
+{
+ using namespace std;
+ TPropertyHandleList properties;
+ inModel.GetAggregateInstanceProperties(inInstance, properties);
+ TPropertyHandleList::iterator theProp =
+ std::find_if(properties.begin(), properties.end(),
+ std::bind(PropertyNameMatches, std::ref(inModel), inName,
+ std::placeholders::_1));
+ if (theProp != properties.end())
+ return *theProp;
+ return 0;
+}
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMTransactions.h b/src/Authoring/UICDM/Systems/UICDMTransactions.h
new file mode 100644
index 00000000..279ef3a2
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMTransactions.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMTRANSACTIONSH
+#define UICDMTRANSACTIONSH
+#include "UICDMDataTypes.h"
+#include "StandardExtensions.h"
+#include <functional>
+
+namespace UICDM {
+
+/**
+ * Transaction is some small entity that changes data. A transaction consumer is expected to
+ *execute
+ * a list of these either forward on a "redo" command or backwards on an "undo" command.
+ *
+ * Transactions merely change data. There are two other lists on consumers for "do"
+ *notifications
+ * and "undo" notifications. These lists control the events sent out to the UI about what
+ *actually
+ * changed in the model. Note that undo/do notifications may be more clever than simple
+ *send-signal
+ * commands in that they may check if an object is alive or not before sending a notification
+ *and may
+ * decline to send a notification if the target object is not currently alive.
+ *
+ * Currently the undo/redo system first executes all of the transactions and then sends the
+ *appropriate
+ * notifications. This means that when the UI receives any notification, the model is in its
+ *most-updated
+ * state.
+ */
+class ITransaction
+{
+public:
+ const char *m_File;
+ int m_Line;
+
+ ITransaction(const char *inFile, int inLine)
+ : m_File(inFile)
+ , m_Line(inLine)
+ {
+ }
+ virtual ~ITransaction() {}
+ virtual void Do() = 0;
+ virtual void Undo() = 0;
+};
+
+/**
+ * Merging allows us to efficient handle situations where the users are continuously
+ * modifying an object (or set of objects). These are referred to as live-update
+ * scenarios. Dragging an object in the 3d view or dragging keyframes in the timeline
+ * would be an example of live-update scenarios.
+ */
+template <typename TValueType>
+class IMergeableTransaction
+{
+public:
+ virtual ~IMergeableTransaction() {}
+ // Called when a new value has arrived and we would rather update
+ // an existing representation rather than create a new one.
+ virtual void Update(const TValueType &inValue) = 0;
+};
+
+/**
+ * A consumer is an object that records the transaction. This interface keeps the
+ * base producer objects from binding to how the transaction or the notifications
+ * are stored.
+ */
+class ITransactionConsumer
+{
+public:
+ virtual ~ITransactionConsumer() {}
+ virtual void OnTransaction(std::shared_ptr<ITransaction> inTransaction) = 0;
+ // Notifications to be sent for undo/redo These are used to
+ // notify clients that something is different.
+ virtual void OnDoNotification(std::function<void()> inNotification) = 0;
+ virtual void OnUndoNotification(std::function<void()> inNotification) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of helper objects and functions.
+///////////////////////////////////////////////////////////////////////////////
+
+typedef std::vector<std::function<void()>> TVoidFunctionList;
+
+typedef std::shared_ptr<ITransactionConsumer> TTransactionConsumerPtr;
+
+class ITransactionProducer
+{
+public:
+ virtual ~ITransactionProducer() {}
+ virtual void SetConsumer(TTransactionConsumerPtr inConsumer) = 0;
+};
+
+template <typename TDoTransaction, typename TUndoTransaction>
+class CGenericTransaction : public ITransaction
+{
+ Q_DISABLE_COPY(CGenericTransaction)
+
+ TUndoTransaction m_UndoTransaction;
+ TDoTransaction m_DoTransaction;
+
+public:
+ CGenericTransaction(const char *inFile, int inLine, TDoTransaction inDo,
+ TUndoTransaction inUndo)
+ : ITransaction(inFile, inLine)
+ , m_UndoTransaction(inUndo)
+ , m_DoTransaction(inDo)
+ {
+ }
+ void Do() override { m_DoTransaction(); }
+ void Undo() override { m_UndoTransaction(); }
+};
+
+template <typename TDoTransaction, typename TUndoTransaction>
+ITransaction *DoCreateGenericTransaction(const char *inFile, int inLine, TDoTransaction inDo,
+ TUndoTransaction inUndo)
+{
+ return static_cast<ITransaction *>(
+ new CGenericTransaction<TDoTransaction, TUndoTransaction>(inFile, inLine, inDo, inUndo));
+}
+
+#define CREATE_GENERIC_TRANSACTION(inDo, inUndo) \
+ DoCreateGenericTransaction(__FILE__, __LINE__, inDo, inUndo)
+
+typedef std::shared_ptr<ITransaction> TTransactionPtr;
+typedef std::vector<TTransactionPtr> TTransactionPtrList;
+
+struct CTransactionConsumer : public ITransactionConsumer
+{
+ TTransactionPtrList m_TransactionList;
+ TVoidFunctionList m_DoNotifications;
+ TVoidFunctionList m_UndoNotifications;
+ void OnTransaction(TTransactionPtr inTransaction) override
+ {
+ m_TransactionList.push_back(inTransaction);
+ }
+ void OnDoNotification(std::function<void()> inNotification) override
+ {
+ m_DoNotifications.push_back(inNotification);
+ }
+ void OnUndoNotification(std::function<void()> inNotification) override
+ {
+ m_UndoNotifications.push_back(inNotification);
+ }
+
+ // Merge with another CTransactionConsumer
+ virtual void Merge(const ITransactionConsumer *inConsumer)
+ {
+ const CTransactionConsumer *theConsumer =
+ static_cast<const CTransactionConsumer *>(inConsumer);
+ m_TransactionList.insert(m_TransactionList.begin(), theConsumer->m_TransactionList.begin(),
+ theConsumer->m_TransactionList.end());
+ }
+ void Reset()
+ {
+ m_TransactionList.clear();
+ m_DoNotifications.clear();
+ m_UndoNotifications.clear();
+ }
+};
+
+struct SIgnorantTransactionConsumer : public ITransactionConsumer
+{
+ void OnTransaction(UICDM::TTransactionPtr) override {}
+ // Notifications to be sent for undo/redo These are used to
+ // notify clients that something is different.
+ void OnDoNotification(std::function<void()>) override {}
+ void OnUndoNotification(std::function<void()>) override {}
+};
+
+template <typename TTransactionType>
+inline void RunWithConsumer(TTransactionConsumerPtr inConsumer, TTransactionType inTransaction)
+{
+ if (inConsumer)
+ inTransaction(inConsumer);
+}
+
+template <typename TDoTransaction, typename TUndoTransaction>
+inline void CreateGenericTransactionWithConsumer(const char *inFile, int inLine,
+ TTransactionConsumerPtr inConsumer,
+ TDoTransaction inDoTransaction,
+ TUndoTransaction inUndoTransaction)
+{
+ if (inConsumer)
+ inConsumer->OnTransaction(TTransactionPtr(
+ DoCreateGenericTransaction(inFile, inLine, inDoTransaction, inUndoTransaction)));
+}
+
+template <typename TItemType>
+inline void DoSetConsumer(TTransactionConsumerPtr inConsumer,
+ std::shared_ptr<TItemType> inTypePtr)
+{
+ ITransactionProducer *theProducer = dynamic_cast<ITransactionProducer *>(inTypePtr.get());
+ if (theProducer)
+ theProducer->SetConsumer(inConsumer);
+}
+
+template <typename TContainer>
+inline void Undo(TContainer &inTransactions)
+{
+ std::for_each(inTransactions.rbegin(), inTransactions.rend(), std::bind(&ITransaction::Undo,
+ std::placeholders::_1));
+}
+
+template <typename TContainer>
+inline void Redo(TContainer &inTransactions)
+{
+ do_all(inTransactions, std::bind(&ITransaction::Do, std::placeholders::_1));
+}
+
+template <typename TItemType>
+void Notify(std::vector<TItemType> &inNotifications)
+{
+ do_all(inNotifications, std::bind(&TItemType::operator(), std::placeholders::_1));
+}
+
+template <typename TItemType>
+void NotifyReverse(std::vector<TItemType> &inNotifications)
+{
+ std::for_each(inNotifications.rbegin(), inNotifications.rend(),
+ std::bind(&TItemType::operator(), std::placeholders::_1));
+}
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMValue.cpp b/src/Authoring/UICDM/Systems/UICDMValue.cpp
new file mode 100644
index 00000000..4db465c0
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMValue.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "UICDMValue.h"
+
+#include <QColor>
+#include <QDebug>
+#include <QVariant>
+
+using namespace UICDM;
+
+SValue::SValue(const QVariant &inData)
+{
+ switch (inData.type()) {
+ case QVariant::Bool:
+ {
+ *this = inData.toBool();
+ break;
+ }
+ case QVariant::Color:
+ {
+ const QColor c = inData.value<QColor>();
+ *this = UICDM::SFloat3(c.redF(), c.greenF(), c.blueF());
+ break;
+ }
+ case QVariant::String:
+ {
+ const QString q = inData.toString();
+ const int count = q.size() + 1;
+#ifdef __INTEGRITY
+ wchar_t* tempBuf = reinterpret_cast<wchar_t*>(malloc(count * sizeof(wchar_t)));
+#else
+ wchar_t* tempBuf = reinterpret_cast<wchar_t*>(alloca(count * sizeof(wchar_t)));
+#endif
+ tempBuf[count - 1] = 0;
+ q.toWCharArray(tempBuf);
+ *this = std::make_shared<UICDM::CDataStr>(tempBuf);
+#ifdef __INTEGRITY
+ free(tempBuf);
+#endif
+ break;
+ }
+ case QVariant::Int: {
+ *this = inData.toInt();
+ break;
+ }
+ case QVariant::Double: {
+ *this = inData.toFloat();
+ break;
+ }
+
+ case QVariant::Vector3D: {
+ const auto v = inData.value<QVector3D>();
+ *this = UICDM::SFloat3(v.x(), v.y(), v.z());
+ break;
+ }
+
+ default:
+ qDebug() << "Add a handler for QVariant::type" << inData.type();
+ throw std::runtime_error("Cannot transform this QVariant into SValue");
+ }
+}
+
+QVariant SValue::toQVariant() const
+{
+ switch (getType()) {
+ case DataModelDataType::String:
+ case DataModelDataType::StringRef:
+ {
+ return get<QString>(*this);
+ }
+ case DataModelDataType::Float: {
+ return get<float>(*this);
+ }
+ case DataModelDataType::Float2: {
+ return QVariant::fromValue(get<QVector2D>(*this));
+ }
+ case DataModelDataType::Float3: {
+ return QVariant::fromValue(get<QVector3D>(*this));
+ }
+ case DataModelDataType::Long: {
+ return QVariant::fromValue(get<qt3ds::QT3DSI32>(*this));
+ }
+ case DataModelDataType::Bool: {
+ return get<bool>(*this);
+ }
+ case DataModelDataType::FloatList: {
+ //KDAB_TODO
+ qDebug() << "Add a handler for type DataModelDataType::FloatList";
+ return {};
+ }
+ case DataModelDataType::Long4: {
+ return QVariant::fromValue(get<QVector<qt3ds::QT3DSU32> >(*this));
+ }
+ case DataModelDataType::ObjectRef: {
+ const SObjectRefType &theRef(get<SObjectRefType>(*this));
+ switch (theRef.GetReferenceType()) {
+ case ObjectReferenceType::Absolute:
+ return SValue(get<SLong4>(theRef.m_Value)).toQVariant();
+ break;
+ case ObjectReferenceType::Relative:
+ return SValue(get<TDataStrPtr>(theRef.m_Value)).toQVariant();
+ break;
+ case ObjectReferenceType::Unknown:
+ return QVariant::fromValue(QVector<qt3ds::QT3DSU32>());
+ break;
+ }
+ }
+ case DataModelDataType::StringOrInt: {
+ const SStringOrInt &theData(get<SStringOrInt>(*this));
+ if (theData.GetType() == SStringOrIntTypes::Int) {
+ return QVariant::fromValue(get<qt3ds::QT3DSI32>(theData.m_Value));
+ } else if (theData.GetType() == SStringOrIntTypes::String) {
+ auto wideStr = get<TDataStrPtr>(theData.m_Value)->GetData();
+ return QString::fromWCharArray(wideStr);
+ } else {
+ return {};
+ }
+
+ }
+ case DataModelDataType::None:
+ return {};
+ }
+ return {};
+}
+
+SInternValue::SInternValue(const SValue &inValue, IStringTable &inStringTable)
+{
+ if (GetValueType(inValue) == DataModelDataType::StringRef) {
+ const SStringRef &current = get<SStringRef>(inValue);
+ SStringRef newId = inStringTable.RegisterStr(current.m_Id);
+ m_Value = SValue(newId);
+ } else {
+ m_Value = inValue;
+ }
+}
+
+SInternValue::SInternValue(const SInternValue &inOther)
+ : m_Value(inOther.m_Value)
+{
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMValue.h b/src/Authoring/UICDM/Systems/UICDMValue.h
new file mode 100644
index 00000000..a10d39aa
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMValue.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMVALUEH
+#define UICDMVALUEH
+#include "UICDMDataTypes.h"
+
+#include <QColor>
+#include <QMetaType>
+#include <QVariant>
+#include <QVector>
+#include <QVector2D>
+#include <QVector3D>
+
+namespace UICDM {
+
+template <typename TDataType>
+struct SDataTypeToEnumMap
+{
+};
+
+template <DataModelDataType::Value TEnumVal>
+struct SEnumToDataTypeMap
+{
+};
+
+#define DEFINE_UICDM_DATA_TYPE_MAP(dtype, enumName) \
+ template <> \
+ struct SDataTypeToEnumMap<dtype> \
+ { \
+ static DataModelDataType::Value getType() { return enumName; } \
+ }; \
+ template <> \
+ struct SEnumToDataTypeMap<enumName> \
+ { \
+ typedef dtype TDataType; \
+ };
+
+#define ITERATE_UICDM_DATA_TYPES \
+ HANDLE_UICDM_DATA_TYPE(float, DataModelDataType::Float); \
+ HANDLE_UICDM_DATA_TYPE(SFloat2, DataModelDataType::Float2); \
+ HANDLE_UICDM_DATA_TYPE(SFloat3, DataModelDataType::Float3); \
+ HANDLE_UICDM_DATA_TYPE(qt3ds::QT3DSI32, DataModelDataType::Long); \
+ HANDLE_UICDM_DATA_TYPE(TDataStrPtr, DataModelDataType::String); \
+ HANDLE_UICDM_DATA_TYPE(bool, DataModelDataType::Bool); \
+ HANDLE_UICDM_DATA_TYPE(SLong4, DataModelDataType::Long4); \
+ HANDLE_UICDM_DATA_TYPE(SStringRef, DataModelDataType::StringRef); \
+ HANDLE_UICDM_DATA_TYPE(SObjectRefType, DataModelDataType::ObjectRef); \
+ HANDLE_UICDM_DATA_TYPE(SStringOrInt, DataModelDataType::StringOrInt); \
+ HANDLE_UICDM_DATA_TYPE(TFloatList, DataModelDataType::FloatList);
+
+#define HANDLE_UICDM_DATA_TYPE(a, b) DEFINE_UICDM_DATA_TYPE_MAP(a, b)
+ITERATE_UICDM_DATA_TYPES
+#undef HANDLE_UICDM_DATA_TYPE
+
+struct SUICDMDataTypeUnionTraits
+{
+ typedef DataModelDataType::Value TIdType;
+
+ enum {
+ TBufferSize = sizeof(SObjectRefType),
+ };
+
+ static TIdType getNoDataId() { return DataModelDataType::None; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SDataTypeToEnumMap<TDataType>::getType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, DataModelDataType::Value inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+#define HANDLE_UICDM_DATA_TYPE(dtype, enumType) \
+ case enumType: \
+ return inVisitor(*NVUnionCast<dtype *>(inData));
+ ITERATE_UICDM_DATA_TYPES
+#undef HANDLE_UICDM_DATA_TYPE
+
+ default:
+ QT3DS_ASSERT(false);
+ case DataModelDataType::None:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, DataModelDataType::Value inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+#define HANDLE_UICDM_DATA_TYPE(dtype, enumType) \
+ case enumType: \
+ return inVisitor(*NVUnionCast<const dtype *>(inData));
+ ITERATE_UICDM_DATA_TYPES
+#undef HANDLE_UICDM_DATA_TYPE
+
+ default:
+ QT3DS_ASSERT(false);
+ case DataModelDataType::None:
+ return inVisitor();
+ }
+ }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SUICDMDataTypeUnionTraits,
+ SUICDMDataTypeUnionTraits::TBufferSize>,
+ SUICDMDataTypeUnionTraits::TBufferSize>
+ TValue;
+
+struct SValue : public TValue
+{
+ SValue() {}
+ SValue(const SValue &inOther)
+ : TValue(static_cast<const TValue &>(inOther))
+ {
+ }
+ SValue(const QVariant &inData);
+
+ template <typename TDataType>
+ SValue(const TDataType &inData)
+ : TValue(inData)
+ {
+ }
+ SValue &operator=(const SValue &inOther)
+ {
+ TValue::operator=(inOther);
+ return *this;
+ }
+ bool operator==(const SValue &inOther) const { return TValue::operator==(inOther); }
+ bool operator!=(const SValue &inOther) const { return TValue::operator!=(inOther); }
+ bool empty() const { return getType() == DataModelDataType::None; }
+
+ // Conversion from this data type into a data model value
+ const SValue &toOldSkool() const { return *this; }
+
+ QVariant toQVariant() const;
+};
+
+typedef std::shared_ptr<SValue> SValuePtr;
+
+template <>
+struct SUICDMGetter<SValue>
+{
+ template <typename TRetType>
+ TRetType doGet(const SValue &inValue)
+ {
+ return inValue.getData<TRetType>();
+ }
+};
+
+template <>
+struct SUICDMValueTyper<SValue>
+{
+ DataModelDataType::Value Get(const SValue &inValue) { return inValue.getType(); }
+};
+
+inline bool CheckValueType(DataModelDataType::Value inType, const SValue &inValue)
+{
+ bool retval = inType == inValue.getType();
+ if (!retval)
+ throw ValueTypeError(L"");
+ return retval;
+}
+
+inline bool Equals(const SValue &lhs, const SValue &rhs)
+{
+ return lhs == rhs;
+}
+
+class SInternValue
+{
+ SValue m_Value;
+
+public:
+ SInternValue(const SValue &inValue, IStringTable &inTable);
+ SInternValue() {}
+ SInternValue(const SInternValue &inOther);
+ SInternValue &operator=(const SInternValue &inOther)
+ {
+ m_Value = inOther.m_Value;
+ return *this;
+ }
+
+ static SInternValue ISwearThisHasAlreadyBeenInternalized(const SValue &inValue)
+ {
+ SInternValue retval;
+ retval.m_Value = inValue;
+ return retval;
+ }
+
+ const SValue &GetValue() const { return m_Value; }
+ operator const SValue &() const { return m_Value; }
+};
+
+template <>
+struct SDefaulter<SValue>
+{
+ inline bool SetDefault(DataModelDataType::Value inDataType, SValue &outValue)
+ {
+ switch (inDataType) {
+ case DataModelDataType::Float:
+ outValue = SValue(0.f);
+ break;
+ case DataModelDataType::Float2:
+ outValue = SValue(SFloat2());
+ break;
+ case DataModelDataType::Float3:
+ outValue = SValue(SFloat3());
+ break;
+ case DataModelDataType::Long:
+ outValue = SValue(0);
+ break;
+ case DataModelDataType::String:
+ outValue = SValue(TDataStrPtr(new CDataStr(L"")));
+ break;
+ case DataModelDataType::Bool:
+ outValue = SValue(false);
+ break;
+ case DataModelDataType::Long4:
+ outValue = SValue(SLong4());
+ break;
+ case DataModelDataType::StringRef:
+ outValue = SValue(SStringRef());
+ break;
+ case DataModelDataType::ObjectRef:
+ outValue = SValue(SObjectRefType());
+ break;
+ case DataModelDataType::FloatList:
+ outValue = SValue(TFloatList());
+ break;
+ case DataModelDataType::StringOrInt:
+ default:
+ outValue = SValue(SStringOrInt());
+ return false;
+ }
+ return true;
+ }
+};
+
+inline SObjectRefType ConvertToObjectRef(const SValue &inValue)
+{
+ using namespace std;
+ switch (GetValueType(inValue)) {
+ case DataModelDataType::StringRef:
+ return SObjectRefType(make_shared<CDataStr>(get<SStringRef>(inValue).m_Id));
+ case DataModelDataType::String:
+ return SObjectRefType(get<TDataStrPtr>(inValue));
+ case DataModelDataType::Long4:
+ return SObjectRefType(get<SLong4>(inValue));
+ case DataModelDataType::ObjectRef:
+ return get<SObjectRefType>(inValue);
+ default:
+ break;
+ }
+ return SObjectRefType();
+}
+
+
+template <>
+inline QColor get<QColor>(const SValue &inType)
+{
+ auto f = get<UICDM::SFloat3>(inType);
+ return QColor::fromRgbF(f.m_Floats[0], f.m_Floats[1], f.m_Floats[2]);
+}
+
+template <>
+inline QString get<QString>(const UICDM::SValue &inType)
+{
+ return QString::fromWCharArray(UICDM::get<UICDM::TDataStrPtr>(inType)->GetData());
+}
+
+template <>
+inline QVector2D get<QVector2D>(const UICDM::SValue &inType)
+{
+ auto f = get<UICDM::SFloat2>(inType);
+ return QVector2D(f.m_Floats[0], f.m_Floats[1]);
+}
+
+template <>
+inline QVector3D get<QVector3D>(const UICDM::SValue &inType)
+{
+ auto f = get<UICDM::SFloat3>(inType);
+ return QVector3D(f.m_Floats[0], f.m_Floats[1], f.m_Floats[2]);
+}
+
+// KDAB_TODO Shortcut to not define our own 4 member long structure
+template <>
+inline QVector<qt3ds::QT3DSU32> get<QVector<qt3ds::QT3DSU32> >(const UICDM::SValue &inType)
+{
+ auto f = get<UICDM::SLong4>(inType);
+ return {f.m_Longs[0], f.m_Longs[1], f.m_Longs[2], f.m_Longs[3]};
+}
+
+}
+Q_DECLARE_METATYPE(UICDM::DataModelDataType)
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMWStrOps.h b/src/Authoring/UICDM/Systems/UICDMWStrOps.h
new file mode 100644
index 00000000..00756ff4
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMWStrOps.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMWSTROPSH
+#define UICDMWSTROPSH
+namespace UICDM {
+// Template base class so that we can convert items to and from wide string
+template <typename TDataType>
+struct WStrOps
+{
+ bool force_compile_error;
+};
+}
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMWStrOpsImpl.h b/src/Authoring/UICDM/Systems/UICDMWStrOpsImpl.h
new file mode 100644
index 00000000..60bb03d9
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMWStrOpsImpl.h
@@ -0,0 +1,745 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTWSTROPSIMPLH
+#define UICIMPORTWSTROPSIMPLH
+#include "UICDMDataTypes.h"
+#include "UICDMWStrOps.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "UICDMHandles.h"
+#include "UICDMAnimation.h"
+#include "UICDMMetaDataTypes.h"
+#include "UICDMXML.h"
+#include "EABase/eabase.h"
+#include "UICDMStringTable.h"
+
+namespace UICDM {
+using qt3ds::QT3DSI8;
+using qt3ds::QT3DSU8;
+using qt3ds::QT3DSI16;
+using qt3ds::QT3DSU16;
+using qt3ds::QT3DSU32;
+using qt3ds::QT3DSI32;
+using qt3ds::QT3DSU64;
+using qt3ds::QT3DSI64;
+using qt3ds::QT3DSF32;
+using qt3ds::QT3DSF64;
+template <>
+struct WStrOps<bool>
+{
+ QT3DSU32 ToStr(bool item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ swprintf(buffer.begin(), buffer.size(), L"%s", item ? L"True" : L"False"));
+ }
+ bool StrTo(const wchar_t *buffer, bool &item)
+ {
+ if (AreEqual(buffer, L"True"))
+ item = true;
+ else
+ item = false;
+ return true;
+ }
+ QT3DSU32 ToStr(bool item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ _snprintf(buffer.begin(), buffer.size(), "%s", item ? "True" : "False"));
+ }
+ bool StrTo(const char8_t *buffer, bool &item)
+ {
+ if (AreEqualCaseless(buffer, "True"))
+ item = true;
+ else
+ item = false;
+ return true;
+ }
+};
+template <>
+struct WStrOps<QT3DSU8>
+{
+ QT3DSU32 ToStr(QT3DSU8 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ swprintf(buffer.begin(), buffer.size(), L"%hu", static_cast<QT3DSU16>(item)));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU8 &item)
+ {
+ item = static_cast<QT3DSU8>(strtoul(buffer, NULL, 10));
+ return true;
+ }
+};
+template <>
+struct WStrOps<QT3DSI8>
+{
+ QT3DSU32 ToStr(QT3DSI8 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ swprintf(buffer.begin(), buffer.size(), L"%hd", static_cast<QT3DSI16>(item)));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI8 &item)
+ {
+ item = static_cast<QT3DSI8>(strtol(buffer, NULL, 10));
+ return true;
+ }
+};
+template <>
+struct WStrOps<QT3DSU16>
+{
+ QT3DSU32 ToStr(QT3DSU16 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%hu", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU16 &item)
+ {
+ item = static_cast<QT3DSU16>(strtoul(buffer, NULL, 10));
+ return true;
+ }
+};
+template <>
+struct WStrOps<QT3DSI16>
+{
+ QT3DSU32 ToStr(QT3DSI16 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%hd", item));
+ }
+ QT3DSU32 ToStr(QT3DSI16 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(sprintf(buffer.begin(), "%hd", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI16 &item)
+ {
+ item = static_cast<QT3DSI16>(strtol(buffer, NULL, 10));
+ return true;
+ }
+};
+
+template <>
+struct WStrOps<QT3DSU32>
+{
+ QT3DSU32 ToStr(QT3DSU32 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%lu", item));
+ }
+ QT3DSU32 ToStr(QT3DSU32 item, NVDataRef<char8_t> buffer)
+ {
+ // hope the buffer is big enough...
+ return static_cast<QT3DSU32>(sprintf(buffer.begin(), "%u", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU32 &item)
+ {
+ item = strtoul(buffer, NULL, 10);
+ return true;
+ }
+};
+
+template <>
+struct WStrOps<QT3DSI32>
+{
+ QT3DSU32 ToStr(QT3DSI32 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%ld", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI32 &item)
+ {
+ item = strtol(buffer, NULL, 10);
+ return true;
+ }
+};
+template <>
+struct WStrOps<QT3DSF32>
+{
+ QT3DSU32 ToStr(QT3DSF32 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ swprintf(buffer.begin(), buffer.size(), L"%g", static_cast<QT3DSF64>(item)));
+ }
+ QT3DSU32 ToStr(QT3DSF32 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ _snprintf(buffer.begin(), buffer.size(), "%g", static_cast<QT3DSF64>(item)));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSF32 &item)
+ {
+ item = (QT3DSF32)strtod(buffer, NULL);
+ return true;
+ }
+};
+
+template <>
+struct WStrOps<QT3DSF64>
+{
+ QT3DSU32 ToStr(QT3DSF64 item, NVDataRef<wchar_t> buffer)
+ {
+ return static_cast<QT3DSU32>(swprintf(buffer.begin(), buffer.size(), L"%g", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSF64 &item)
+ {
+ item = strtod(buffer, NULL);
+ return true;
+ }
+};
+#define UIC_WCHAR_T_None L"None"
+#define UIC_WCHAR_T_Float L"Float"
+#define UIC_WCHAR_T_Float2 L"Float2"
+#define UIC_WCHAR_T_Float3 L"Float3"
+#define UIC_WCHAR_T_Long L"Long"
+#define UIC_WCHAR_T_String L"String"
+#define UIC_WCHAR_T_Bool L"Bool"
+#define UIC_WCHAR_T_Long4 L"Long4"
+#define UIC_WCHAR_T_StringRef L"StringRef"
+#define UIC_WCHAR_T_ObjectRef L"ObjectRef"
+#define UIC_WCHAR_T_StringOrInt L"StringOrInt"
+#define UIC_WCHAR_T_FloatList L"FloatList"
+
+#define UIC_IMPORT_ITERATE_DMTYPE \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::None, None, QT3DSF32) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float, Float, QT3DSF32) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float2, Float2, SFloat2) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::Float3, Float3, SFloat3) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::Long, Long, QT3DSI32) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::String, String, TDataStrPtr) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::Bool, Bool, bool) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::Long4, Long4, SLong4) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::StringRef, StringRef, SStringRef) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::ObjectRef, ObjectRef, SObjectRefType) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::StringOrInt, StringOrInt, SStringOrInt) \
+ UIC_IMPORT_HANDLE_DMTYPE(DataModelDataType::FloatList, FloatList, TFloatList)
+
+template <>
+struct WStrOps<DataModelDataType::Value>
+{
+ QT3DSU32 ToStr(DataModelDataType::Value item, NVDataRef<wchar_t> buffer)
+ {
+ const wchar_t *data = NULL;
+ switch (item) {
+#define UIC_IMPORT_HANDLE_DMTYPE(x, y, z) \
+ case x: \
+ data = UIC_WCHAR_T_##y; \
+ break;
+ UIC_IMPORT_ITERATE_DMTYPE
+#undef UIC_IMPORT_HANDLE_DMTYPE
+ }
+ if (data == NULL) {
+ QT3DS_ASSERT(false);
+ data = L"Unknown";
+ }
+ return (QT3DSU32)swprintf(buffer.begin(), buffer.size(), L"%ls", data);
+ }
+ bool StrTo(const wchar_t *buffer, DataModelDataType::Value &item)
+ {
+
+#define UIC_IMPORT_HANDLE_DMTYPE(x, y, z) \
+ if (AreEqual(buffer, UIC_WCHAR_T_##y)) { \
+ item = x; \
+ return true; \
+ }
+ UIC_IMPORT_ITERATE_DMTYPE
+#undef UIC_IMPORT_HANDLE_DMTYPE
+ item = DataModelDataType::None;
+ return false;
+ }
+};
+template <typename TBufferType>
+struct WStrOpsDMWriter
+{
+ TBufferType &buf;
+ WStrOpsDMWriter(TBufferType &_buf)
+ : buf(_buf)
+ {
+ }
+
+ void operator()(float val) { buf.Write(val); }
+ void operator()(const SFloat2 &val) { buf.Write(NVConstDataRef<QT3DSF32>(&val[0], 2)); }
+ void operator()(const SFloat3 &val) { buf.Write(NVConstDataRef<QT3DSF32>(&val[0], 3)); }
+ void operator()(QT3DSI32 val) { buf.Write(val); }
+ void operator()(bool val) { buf.Write(val); }
+ void operator()(const TDataStrPtr &val)
+ {
+ if (val != NULL)
+ buf.Write(NVConstDataRef<wchar_t>(val->GetData(), (QT3DSU32)val->GetLength()));
+ }
+ void operator()(const SLong4 &val)
+ {
+ buf.Write(NVConstDataRef<QT3DSU32>(&val.m_Longs[0], 4), 4);
+ }
+ void operator()(const SStringRef &val) { buf.Write(val.m_Id, (QT3DSU32)wcslen(val.m_Id) + 1); }
+ void operator()(const SObjectRefType &val) { val.m_Value.visit<void>(*this); }
+ void operator()(const SStringOrInt &val) { val.m_Value.visit<void>(*this); }
+ void operator()(const TFloatList &val)
+ {
+ buf.Write(NVConstDataRef<float>(val.data(), (QT3DSU32)val.size()));
+ }
+ void operator()() { QT3DS_ASSERT(false); }
+};
+
+template <>
+struct WStrOps<SValue>
+{
+ template <typename TBufferType>
+ void ToBuf(const SValue &item, TBufferType &outBuffer)
+ {
+ WStrOpsDMWriter<TBufferType> writer(outBuffer);
+ item.visit<void>(writer);
+ }
+ template <typename TBufferType>
+ SValue BufTo(DataModelDataType::Value type, TBufferType &inReader)
+ {
+ switch (type) {
+#define UIC_IMPORT_HANDLE_DMTYPE(x, y, z) \
+ case x: { \
+ z retval; \
+ Read(inReader, retval); \
+ return retval; \
+ }
+ UIC_IMPORT_ITERATE_DMTYPE
+#undef UIC_IMPORT_HANDLE_DMTYPE
+ }
+ QT3DS_ASSERT(false);
+ return SValue();
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, float &val)
+ {
+ reader.Read(val);
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, SFloat2 &val)
+ {
+ reader.ReadRef(NVDataRef<QT3DSF32>(&val[0], 2));
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, SFloat3 &val)
+ {
+ reader.ReadRef(NVDataRef<QT3DSF32>(&val[0], 3));
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, QT3DSI32 &val)
+ {
+ reader.Read(val);
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, bool &val)
+ {
+ reader.Read(val);
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, TDataStrPtr &val)
+ {
+ NVConstDataRef<wchar_t> buffer;
+ reader.ReadBuffer(buffer);
+ val = std::make_shared<CDataStr>(buffer.begin(), buffer.size());
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, SLong4 &val)
+ {
+ reader.ReadRef(NVDataRef<QT3DSU32>(&val.m_Longs[0], 4));
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, SStringRef &val)
+ {
+ NVConstDataRef<wchar_t> buffer;
+ reader.ReadBuffer(buffer);
+ val = SStringRef(buffer.begin());
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, TFloatList &val)
+ {
+ NVConstDataRef<QT3DSF32> buffer;
+ reader.ReadBuffer(buffer);
+ val.assign(buffer.begin(), buffer.end());
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, SObjectRefType &val)
+ {
+ // Force the read to be as string; callers can always convert to a different
+ // format later if required.
+ TDataStrPtr theValue;
+ Read(reader, theValue);
+ val.m_Value = theValue;
+ }
+ template <typename TBufferType>
+ void Read(TBufferType &reader, SStringOrInt &val)
+ {
+ NVConstDataRef<char8_t> buffer;
+ reader.ReadBuffer(buffer);
+ if (buffer.size() == 0)
+ return;
+
+ if ((buffer[0] >= '0' && buffer[0] <= '9') || buffer[0] == '-') {
+ QT3DSI32 theVal;
+ WStrOps<QT3DSI32>().StrTo(buffer.begin(), theVal);
+ val = SStringOrInt(theVal);
+ } else {
+ NVConstDataRef<wchar_t> wideBuffer;
+ reader.ReadBuffer(wideBuffer);
+ val = SStringOrInt(std::make_shared<CDataStr>(wideBuffer.begin()));
+ }
+ }
+};
+
+// Write the wchar_t but exlude the null terminator
+// Meant to write data model values.
+// Memory buffer contains a non-null-terminated
+// wchar_t string
+struct WCharTWriter
+{
+ MemoryBuffer<RawAllocator> &m_Buffer;
+ WCharTWriter(MemoryBuffer<RawAllocator> &buf)
+ : m_Buffer(buf)
+ {
+ }
+ void Write(const wchar_t *value, QT3DSU32 len = 0)
+ {
+ if (IsTrivial(value))
+ return;
+ if (len == 0)
+ len = (QT3DSU32)wcslen(value);
+ m_Buffer.write(value, len);
+ }
+ void Write(wchar_t value) { m_Buffer.write(value); }
+ void Write(bool value) { Write(value ? L"True" : L"False"); }
+
+ // Takes care of long and float
+ template <typename TDataType>
+ void Write(TDataType value)
+ {
+ wchar_t buf[256];
+ QT3DSU32 numWritten = WStrOps<TDataType>().ToStr(value, NVDataRef<wchar_t>(buf, 256));
+ if (numWritten)
+ Write((const wchar_t *)buf);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ template <typename TDataType>
+ void Write(NVConstDataRef<TDataType> values, QT3DSU32 grouping = 6, QT3DSU32 tabCount = 0)
+ {
+ for (QT3DSU32 idx = 0; idx < values.size(); ++idx) {
+ if (idx) {
+ if ((idx % grouping) == 0) {
+ Write((wchar_t)'\n');
+ for (QT3DSU32 tabIdx = 0; tabIdx < tabCount; ++tabIdx)
+ Write((wchar_t)'\t');
+ } else
+ Write((wchar_t)' ');
+ }
+ Write(values[idx]);
+ }
+ }
+
+ void Write(NVConstDataRef<wchar_t> values, QT3DSU32 ignored = 6)
+ {
+ (void)ignored;
+ if (values.size() && values[0] != 0) {
+ QT3DSU32 lastItem = values.size() - 1;
+ if (values[lastItem] == 0)
+ --lastItem;
+ Write(values.begin(), lastItem + 1);
+ }
+ }
+};
+
+inline bool IsWhite(wchar_t value)
+{
+ return value == '\n' || value == '\r' || value == ' ' || value == '\t';
+}
+
+// skip until we find whitespace.
+inline wchar_t *FindNextWhitespace(wchar_t *input)
+{
+ if (input == NULL)
+ return input;
+ wchar_t *marker = input;
+ // Empty loop intentional
+ for (; *marker && !IsWhite(*marker); ++marker)
+ ;
+ return marker;
+}
+
+// skip until we find whitespace.
+inline char8_t *FindNextWhitespace(char8_t *input)
+{
+ if (input == NULL)
+ return input;
+ char8_t *marker = input;
+ // Empty loop intentional
+ for (; *marker && !IsWhite(*marker); ++marker)
+ ;
+ return marker;
+}
+
+// skip until we find something that isn't whitespace.
+inline wchar_t *FindNextNonWhitespace(wchar_t *input)
+{
+ if (input == NULL)
+ return input;
+ wchar_t *marker = input;
+ // Empty loop intentional
+ for (; *marker && IsWhite(*marker); ++marker)
+ ;
+ return marker;
+}
+
+inline char8_t *FindNextNonWhitespace(char8_t *input)
+{
+ if (input == NULL)
+ return input;
+ char8_t *marker = input;
+ // Empty loop intentional
+ for (; *marker && IsWhite(*marker); ++marker)
+ ;
+ return marker;
+}
+
+// Reading is destructive in the case of floating point lists, so we may
+// destroy the incoming string.
+// We are assuming the string is null-terminated at end ptr.
+struct WCharTReader
+{
+ char8_t *m_StartPtr;
+ // Buffer used for temp storage
+ MemoryBuffer<RawAllocator> &m_Buffer;
+ IStringTable &m_StringTable;
+ WCharTReader(char8_t *sp, MemoryBuffer<RawAllocator> &buf, IStringTable &inStringTable)
+ : m_StartPtr(sp)
+ , m_Buffer(buf)
+ , m_StringTable(inStringTable)
+ {
+ }
+ void Read(const char8_t *&outPtr) { outPtr = m_StartPtr; }
+ void Read(const wchar_t *&outPtr) { outPtr = m_StringTable.GetWideStr(m_StartPtr); }
+ template <typename TDataType>
+ void Read(TDataType &data)
+ {
+ bool success = WStrOps<TDataType>().StrTo(m_StartPtr, data);
+ QT3DS_ASSERT(success);
+ (void)success;
+ }
+ // Destructive operation because we can't trust
+ // strtod to do the right thing. On windows, for long strings,
+ // it calls strlen every operation thus leading to basically N^2
+ // behavior
+ template <typename TDataType>
+ void ReadRef(NVDataRef<TDataType> data)
+ {
+ QT3DSU32 idx = 0;
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr);
+ for (; idx < data.size() && m_StartPtr && *m_StartPtr; ++idx) {
+ char8_t *nextPtr = FindNextWhitespace(m_StartPtr);
+ if (nextPtr && *nextPtr)
+ *nextPtr = 0;
+ else
+ nextPtr = NULL;
+ WStrOps<TDataType>().StrTo(m_StartPtr, data[idx]);
+ m_StartPtr = nextPtr;
+ if (m_StartPtr)
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr + 1);
+ }
+ QT3DS_ASSERT(idx == data.size());
+ }
+
+ void ReadBuffer(NVConstDataRef<char8_t> &outBuffer)
+ {
+ if (m_StartPtr && *m_StartPtr) {
+ QT3DSU32 len = (QT3DSU32)strlen(m_StartPtr);
+ outBuffer = NVConstDataRef<char8_t>(m_StartPtr, len + 1);
+ }
+ }
+ void ReadBuffer(NVConstDataRef<wchar_t> &outBuffer)
+ {
+ if (m_StartPtr && *m_StartPtr) {
+ QT3DSU32 len = (QT3DSU32)strlen(m_StartPtr);
+ outBuffer = NVConstDataRef<wchar_t>(m_StringTable.GetWideStr(m_StartPtr), len + 1);
+ }
+ }
+
+ // Destructive operation because we can't trust
+ // strtod to do the right thing. On windows, for long strings,
+ // it calls strlen every operation thus leading to basically N^2
+ // behavior
+ template <typename TDataType>
+ void ReadBuffer(NVConstDataRef<TDataType> &outBuffer)
+ {
+ m_Buffer.clear();
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr);
+ while (m_StartPtr && *m_StartPtr) {
+ char8_t *nextPtr = FindNextWhitespace(m_StartPtr);
+ if (nextPtr && *nextPtr)
+ *nextPtr = 0;
+ else
+ nextPtr = NULL;
+ TDataType temp;
+ WStrOps<TDataType>().StrTo(m_StartPtr, temp);
+ m_Buffer.write(temp);
+ m_StartPtr = nextPtr;
+ if (m_StartPtr)
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr + 1);
+ }
+ QT3DSU32 numItems = m_Buffer.size() / sizeof(TDataType);
+ if (numItems)
+ outBuffer = NVConstDataRef<TDataType>((TDataType *)m_Buffer.begin(), numItems);
+ else
+ outBuffer = NVConstDataRef<TDataType>();
+ }
+};
+
+template <>
+struct WStrOps<CDataModelHandle>
+{
+ template <typename THandleType>
+ QT3DSU32 ToStr(THandleType item, NVDataRef<wchar_t> buffer)
+ {
+ int theValue(item);
+ return WStrOps<int>().ToStr(theValue, buffer);
+ }
+ template <typename THandleType>
+ bool StrTo(const char8_t *buffer, THandleType &item)
+ {
+ int theValue;
+ bool retval = WStrOps<int>().StrTo(buffer, theValue);
+ item = theValue;
+ return retval;
+ }
+};
+
+#define IMPLEMENT_HANDLE_WSTROPS(HandleType) \
+ template <> \
+ struct WStrOps<HandleType> : public WStrOps<CDataModelHandle> \
+ { \
+ };
+IMPLEMENT_HANDLE_WSTROPS(CUICDMInstanceHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMPropertyHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMSlideHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMSlideGraphHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMAnimationHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMKeyframeHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMActionHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMHandlerArgHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMEventHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMHandlerHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMHandlerParamHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMMetaDataPropertyHandle);
+IMPLEMENT_HANDLE_WSTROPS(CUICDMCategoryHandle);
+#undef IMPLEMENT_HANDLE_WSTROPS
+
+template <>
+struct WStrOps<EAnimationType>
+{
+ QT3DSU32 ToStr(EAnimationType value, NVDataRef<wchar_t> buffer)
+ {
+ const wchar_t *animType = NULL;
+ switch (value) {
+ case EAnimationTypeLinear:
+ animType = L"Linear";
+ break;
+ case EAnimationTypeBezier:
+ animType = L"Bezier";
+ break;
+ case EAnimationTypeEaseInOut:
+ animType = L"EaseInOut";
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ if (animType != NULL)
+ return swprintf(buffer.begin(), buffer.size(), L"%ls", animType);
+ else {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ }
+ bool StrTo(const wchar_t *buffer, EAnimationType &item)
+ {
+ if (AreEqual(L"Linear", buffer)) {
+ item = EAnimationTypeLinear;
+ return true;
+ }
+ if (AreEqual(L"Bezier", buffer)) {
+ item = EAnimationTypeBezier;
+ return true;
+ }
+ if (AreEqual(L"EaseInOut", buffer)) {
+ item = EAnimationTypeEaseInOut;
+ return true;
+ }
+ return false;
+ }
+};
+
+// Implemented in UICDMMetaData.h
+template <>
+struct WStrOps<CompleteMetaDataType::Enum>
+{
+ QT3DSU32 ToStr(CompleteMetaDataType::Enum item, NVDataRef<wchar_t> buffer);
+ bool StrTo(const wchar_t *buffer, CompleteMetaDataType::Enum &item);
+};
+
+template <>
+struct WStrOps<HandlerArgumentType::Value>
+{
+ QT3DSU32 ToStr(HandlerArgumentType::Value item, NVDataRef<wchar_t> buffer);
+ bool StrTo(const wchar_t *buffer, HandlerArgumentType::Value &item);
+};
+
+#ifndef __clang__
+#ifndef __INTEGRITY
+// IDOMReader implementations
+template <typename TDataType>
+bool IDOMReader::ValueList(NVDataRef<TDataType> data)
+{
+ const wchar_t *value;
+ if (Value(value)) {
+ WCharTReader reader(const_cast<wchar_t *>(value), m_TempBuf);
+ reader.ReadRef(data);
+ }
+ return true;
+}
+
+// Destructive operation because we can't trust
+// strtod to do the right thing. On windows, for long strings,
+// it calls strlen every operation thus leading to basically N^2
+// behavior
+template <typename TDataType>
+NVConstDataRef<TDataType> IDOMReader::ChildValueList(TWideXMLCharPtr listName)
+{
+ NVConstDataRef<TDataType> retval;
+ TWideXMLCharPtr childValue = NULL;
+ if (ChildValue(listName, childValue)) {
+ WCharTReader reader(const_cast<wchar_t *>(childValue), m_TempBuf);
+ reader.ReadBuffer(retval);
+ }
+ return retval;
+}
+#endif
+#endif
+}
+
+#endif
diff --git a/src/Authoring/UICDM/Systems/UICDMWindowsCompatibility.h b/src/Authoring/UICDM/Systems/UICDMWindowsCompatibility.h
new file mode 100644
index 00000000..a2ef43e5
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMWindowsCompatibility.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICDMWINDOWSCOMPATIBILITYH
+#define UICDMWINDOWSCOMPATIBILITYH
+#include "EABase/config/eaplatform.h"
+#include "EABase/eabase.h"
+#include <string>
+#ifndef __INTEGRITY
+#include <memory.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#if defined UIC_PLATFORM_NEEDS_WCHAR_T
+
+inline size_t wcslen(const wchar_t *inStr)
+{
+ size_t retval = 0;
+ while (inStr && *inStr) {
+ ++retval;
+ ++inStr;
+ }
+ return retval;
+}
+
+inline int wmemcmp(const wchar_t *lhs, const wchar_t *rhs, size_t count)
+{
+ return memcmp(lhs, rhs, count * sizeof(wchar_t));
+}
+
+inline wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count)
+{
+ memcpy(dest, src, count * sizeof(wchar_t));
+ return dest;
+}
+
+inline const wchar_t *wmemchr(const wchar_t *inFirst, size_t count, const wchar_t val)
+{
+ size_t idx;
+ // empty loop intentional
+ for (idx = 0; idx < count && inFirst[idx] != val; ++idx) {
+ }
+ if (idx < count)
+ return inFirst + idx;
+ return NULL;
+}
+
+inline wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count)
+{
+ memmove(dest, src, count * sizeof(wchar_t));
+ return dest;
+}
+
+inline wchar_t *wmemset(wchar_t *dest, size_t count, wchar_t val)
+{
+ for (size_t idx = 0; idx < count; ++idx)
+ dest[idx] = val;
+ return dest;
+}
+
+#endif
+
+inline size_t WideToNarrow(char *inDest, size_t inDestLen, const wchar_t *inWideStr);
+template <unsigned int N>
+inline size_t WideToNarrow(char (&inDest)[N], const wchar_t *inWideStr);
+
+#if !defined EA_PLATFORM_WINDOWS
+
+inline void wcscpy_s(wchar_t *inDest, size_t destLen, const wchar_t *inMessage)
+{
+ if (destLen) {
+ size_t idx = 0;
+ while (inMessage && *inMessage && idx < destLen) {
+ inDest[idx] = *inMessage;
+ ++inMessage;
+ ++idx;
+ }
+
+ idx = idx < destLen ? idx : destLen - 1;
+ inDest[idx] = 0;
+ }
+}
+
+template <unsigned int N>
+inline void wcscpy_s(wchar_t (&inDest)[N], const wchar_t *inMessage)
+{
+ wcscpy_s(inDest, N, inMessage);
+}
+
+inline FILE *_wfopen(const wchar_t *inFname, const wchar_t *inFlags)
+{
+ char name[1024] = { 0 };
+ WideToNarrow(name, inFname);
+ char flags[24] = { 0 };
+ WideToNarrow(flags, inFlags);
+ return fopen(name, flags);
+}
+
+inline int _fseeki64(FILE *inFile, int64_t pos, int seekFlags)
+{
+ return fseek(inFile, (int32_t)pos, seekFlags);
+}
+
+inline int64_t _ftelli64(FILE *inFile)
+{
+ return ftell(inFile);
+}
+
+#define _snprintf snprintf
+
+#endif
+
+template <typename TLHS, typename TRHS>
+inline size_t ConvertStr(TLHS *inDest, size_t inDestLen, const TRHS *inWideStr)
+{
+ if (inDestLen == 0)
+ return 0;
+
+ size_t nameLen = 0;
+
+ // empty loop intentional.
+ for (const TRHS *tempPtr = inWideStr; tempPtr && *tempPtr; ++tempPtr, ++nameLen) {
+ }
+
+ if (nameLen > inDestLen - 1)
+ nameLen = inDestLen - 1;
+ for (size_t idx = 0; idx < nameLen; ++idx)
+ inDest[idx] = (char)inWideStr[idx];
+ inDest[nameLen] = 0;
+ return nameLen;
+}
+
+inline size_t WideToNarrow(char *inDest, size_t inDestLen, const wchar_t *inWideStr)
+{
+ return ConvertStr(inDest, inDestLen, inWideStr);
+}
+
+template <unsigned int N>
+inline size_t WideToNarrow(char (&inDest)[N], const wchar_t *inWideStr)
+{
+ return WideToNarrow(inDest, N, inWideStr);
+}
+
+inline size_t WideToNarrow(char *inDest, size_t inDestLen, const char16_t *inWideStr)
+{
+ return ConvertStr(inDest, inDestLen, inWideStr);
+}
+
+template <unsigned int N>
+inline size_t WideToNarrow(char (&inDest)[N], const char16_t *inWideStr)
+{
+ return WideToNarrow(inDest, N, inWideStr);
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICDM/Systems/UICDMXML.cpp b/src/Authoring/UICDM/Systems/UICDMXML.cpp
new file mode 100644
index 00000000..1f562b83
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMXML.cpp
@@ -0,0 +1,1317 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICDMPrefix.h"
+#include "UICDMXML.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICDMStringTable.h"
+#include "UICDMWStrOpsImpl.h"
+#include <memory>
+#include "foundation/StrConvertUTF.h"
+#include "foundation/StringTable.h"
+#include "utf8.h"
+#ifdef QT3DS_VC
+#include <winsock2.h>
+#include <windows.h> //output debug string
+#endif
+
+#include <QtCore/qxmlstream.h>
+
+typedef char XML_Char;
+typedef char XML_LChar;
+
+using namespace UICDM;
+using std::shared_ptr;
+using namespace qt3ds::foundation;
+using qt3ds::foundation::Pool;
+
+#define QT3DSXML_FOREACH(idxnm, val) \
+ for (QT3DSU32 idxnm = 0, __numItems = (QT3DSU32)val; idxnm < __numItems; ++idxnm)
+
+namespace UICDM {
+
+// All names are string table values so we can do straight
+// pointer comparisons on them, we don't have the compare their
+// values.
+struct SDOMAttribute
+{
+ TXMLCharPtr m_Name;
+ TXMLCharPtr m_Value;
+ SDOMAttribute *m_NextAttribute;
+
+ SDOMAttribute(TXMLCharPtr nm, TXMLCharPtr val)
+ : m_Name(nm)
+ , m_Value(val)
+ , m_NextAttribute(NULL)
+ {
+ }
+};
+
+struct SDOMElement
+{
+ TXMLCharPtr m_Name;
+ SDOMAttribute *m_FirstAttribute;
+ SDOMAttribute *m_LastAttribute;
+ SDOMElement *m_Parent;
+ SDOMElement *m_FirstChild;
+ SDOMElement *m_LastChild;
+ SDOMElement *m_NextSibling;
+ TXMLCharPtr m_Value;
+
+ SDOMElement(TXMLCharPtr nm)
+ : m_Name(nm)
+ , m_FirstAttribute(NULL)
+ , m_LastAttribute(NULL)
+ , m_Parent(NULL)
+ , m_FirstChild(NULL)
+ , m_LastChild(NULL)
+ , m_NextSibling(NULL)
+ , m_Value("")
+ {
+ }
+
+ void AddAttribute(SDOMAttribute &att)
+ {
+ if (m_LastAttribute) {
+ m_LastAttribute->m_NextAttribute = &att;
+ m_LastAttribute = &att;
+ } else {
+ QT3DS_ASSERT(m_FirstAttribute == NULL);
+ m_FirstAttribute = m_LastAttribute = &att;
+ }
+ }
+ // Used to ensure duplicate attributes can't happen
+ void SetAttributeValue(TXMLCharPtr inName, TXMLCharPtr inValue, IDOMFactory &inFactory,
+ const SDOMFlags &inFlags)
+ {
+ inName = inFactory.GetStringTable()->RegisterStr(inName);
+ SDOMAttribute *att = FindAttribute(inName, inFlags);
+ if (att) {
+ att->m_Value = inFactory.RegisterValue(inValue);
+ } else {
+ AddAttribute(*inFactory.NextAttribute(inName, inValue));
+ }
+ }
+ void SetAttributeValue(TWideXMLCharPtr inName, TWideXMLCharPtr inValue, IDOMFactory &inFactory,
+ const SDOMFlags &inFlags)
+ {
+ TXMLCharPtr theName = inFactory.GetStringTable()->GetNarrowStr(inName);
+ SDOMAttribute *att = FindAttribute(theName, inFlags);
+ if (att) {
+ att->m_Value = inFactory.RegisterValue(inValue);
+ } else {
+ AddAttribute(
+ *inFactory.NextAttribute(inFactory.GetStringTable()->GetWideStr(inName), inValue));
+ }
+ }
+ const SDOMAttribute *FindAttribute(TXMLCharPtr nm, const SDOMFlags &inFlags) const
+ {
+ return const_cast<SDOMElement *>(this)->FindAttribute(nm, inFlags);
+ }
+ SDOMAttribute *FindAttribute(TXMLCharPtr nm, const SDOMFlags &inFlags)
+ {
+ for (SDOMAttribute *att = m_FirstAttribute; att != NULL; att = att->m_NextAttribute) {
+ if (att->m_Name == nm)
+ return att;
+ else if (inFlags.CaselessAttributes() && AreEqualCaseless(nm, att->m_Name))
+ return att;
+ }
+ return NULL;
+ }
+ void RemoveAttribute(TXMLCharPtr nm, const SDOMFlags &inFlags)
+ {
+ SDOMAttribute *preatt = m_FirstAttribute;
+ for (SDOMAttribute *att = m_FirstAttribute; att != NULL;
+ preatt = att, att = att->m_NextAttribute) {
+ if (att->m_Name == nm
+ || (inFlags.CaselessAttributes() && AreEqualCaseless(nm, att->m_Name))) {
+ if (att == m_FirstAttribute) {
+ m_FirstAttribute = att->m_NextAttribute;
+ } else {
+ preatt->m_NextAttribute = att->m_NextAttribute;
+ if (att == m_LastAttribute)
+ m_LastAttribute = preatt;
+ }
+
+ att->m_NextAttribute = NULL;
+ }
+ }
+ }
+ TXMLCharPtr GetAttributeValue(TXMLCharPtr nm, SDOMFlags &inFlags) const
+ {
+ const SDOMAttribute *att = FindAttribute(nm, inFlags);
+ if (att)
+ return att->m_Value;
+ return NULL;
+ }
+ void AddChild(SDOMElement &elem)
+ {
+ elem.m_Parent = this;
+ if (m_LastChild) {
+ m_LastChild->m_NextSibling = &elem;
+ m_LastChild = &elem;
+ } else {
+ QT3DS_ASSERT(m_FirstChild == NULL);
+ m_FirstChild = m_LastChild = &elem;
+ }
+ }
+ SDOMElement *FindPreviousChild(SDOMElement &elem)
+ {
+ if (&elem == m_FirstChild)
+ return NULL;
+ // Find the previous sibling.
+ SDOMElement *theChild = m_FirstChild;
+ // Empty loop intentional
+ for (; theChild && theChild->m_NextSibling != &elem; theChild = theChild->m_NextSibling) {
+ }
+
+ return theChild;
+ }
+ void RemoveChild(SDOMElement &elem)
+ {
+ if (elem.m_Parent != this) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ elem.m_Parent = NULL;
+ if (&elem == m_FirstChild) {
+ m_FirstChild = elem.m_NextSibling;
+ } else {
+ SDOMElement *theChild(FindPreviousChild(elem));
+ QT3DS_ASSERT(theChild);
+ if (theChild) {
+ theChild->m_NextSibling = elem.m_NextSibling;
+ if (&elem == m_LastChild)
+ m_LastChild = theChild;
+ }
+ }
+ elem.m_NextSibling = NULL;
+ }
+
+ void ReplaceChild(SDOMElement &inChild, SDOMElement &inReplacement)
+ {
+ inChild.m_Parent = NULL;
+ if (&inChild == m_FirstChild)
+ m_FirstChild = &inReplacement;
+ else {
+ SDOMElement *theChild(FindPreviousChild(inChild));
+ QT3DS_ASSERT(theChild);
+ if (theChild) {
+ theChild->m_NextSibling = &inReplacement;
+ if (&inChild == m_LastChild)
+ m_LastChild = &inReplacement;
+ }
+ }
+ inReplacement.m_NextSibling = inChild.m_NextSibling;
+ inReplacement.m_Parent = this;
+ inChild.m_NextSibling = NULL;
+ }
+
+ void InsertChildBefore(SDOMElement &elem, SDOMElement &theSibling)
+ {
+ // Ensure elem isn't in the graph.
+ QT3DS_ASSERT(elem.m_Parent == NULL);
+ QT3DS_ASSERT(elem.m_NextSibling == NULL);
+ elem.m_Parent = this;
+ if (&theSibling == m_FirstChild)
+ m_FirstChild = &elem;
+ else {
+ SDOMElement *thePrevious = FindPreviousChild(theSibling);
+ QT3DS_ASSERT(thePrevious);
+ if (thePrevious)
+ thePrevious->m_NextSibling = &elem;
+ }
+
+ elem.m_NextSibling = &theSibling;
+ }
+ QT3DSU32 GetNumChildren(TXMLCharPtr inChildName, const SDOMFlags &inFlags) const
+ {
+ QT3DSU32 idx = 0;
+ for (SDOMElement *elem = m_FirstChild; elem != NULL; elem = elem->m_NextSibling) {
+ if (elem->m_Name == inChildName)
+ ++idx;
+ else if (inFlags.CaselessElements() && AreEqualCaseless(inChildName, elem->m_Name))
+ ++idx;
+ }
+ return idx;
+ }
+ QT3DSU32 GetNumChildren() const
+ {
+ QT3DSU32 idx = 0;
+ for (SDOMElement *elem = m_FirstChild; elem != NULL; elem = elem->m_NextSibling)
+ ++idx;
+ return idx;
+ }
+ SDOMElement *FindChildByName(TXMLCharPtr nm, const SDOMFlags &inFlags) const
+ {
+ for (SDOMElement *elem = m_FirstChild; elem != NULL; elem = elem->m_NextSibling) {
+ if (elem->m_Name == nm)
+ return elem;
+ else if (inFlags.CaselessElements() && AreEqualCaseless(nm, elem->m_Name))
+ return elem;
+ }
+ return NULL;
+ }
+ SDOMElement *FindNextSiblingByName(TXMLCharPtr nm, const SDOMFlags &inFlags) const
+ {
+ for (SDOMElement *elem = m_NextSibling; elem != NULL; elem = elem->m_NextSibling) {
+ if (elem->m_Name == nm)
+ return elem;
+ else if (inFlags.CaselessElements() && AreEqualCaseless(nm, elem->m_Name))
+ return elem;
+ }
+ return NULL;
+ }
+};
+}
+
+namespace {
+
+const QT3DSU16 g_BOMMarker = (QT3DSU16)0xFEFF;
+
+struct SElemPointer : eastl::pair<SDOMElement *, SDOMAttribute *>
+{
+ SElemPointer(SDOMElement *elem = NULL)
+ : eastl::pair<SDOMElement *, SDOMAttribute *>(elem, NULL)
+ {
+ }
+ SElemPointer &operator=(SDOMElement *elem)
+ {
+ first = elem;
+ second = NULL;
+ return *this;
+ }
+ SElemPointer &operator=(SDOMAttribute *att)
+ {
+ second = att;
+ return *this;
+ }
+ SElemPointer &operator=(const eastl::pair<SDOMElement *, SDOMAttribute *> &other)
+ {
+ eastl::pair<SDOMElement *, SDOMAttribute *>::operator=(other);
+ return *this;
+ }
+ operator SDOMElement *() const { return first; }
+ SDOMElement *operator->() const { return first; }
+};
+
+// Some DOM parsing operations are destructive. If you need
+// them to not be destructive, then we need to modify
+// the reader. Specifically parsing lists of floats, due
+// to a bug in strtod, is destructive.
+struct SDOMReader : public IDOMReader
+{
+ SElemPointer m_TopElement;
+ eastl::vector<eastl::pair<SDOMElement *, SDOMAttribute *>> m_ScopeStack;
+ std::shared_ptr<IDOMFactory> m_Factory;
+ SDOMFlags m_Flags;
+ eastl::basic_string<TWCharEASTLConverter::TCharType> m_TempBuffer;
+
+ SDOMReader(SDOMElement &te, std::shared_ptr<UICDM::IStringTable> s,
+ std::shared_ptr<IDOMFactory> inFactory = std::shared_ptr<IDOMFactory>())
+ : IDOMReader(s)
+ , m_TopElement(&te)
+ , m_Factory(inFactory)
+ {
+ }
+
+ SDOMElement *Current() const { return m_TopElement.first; }
+ void SetDOMFlags(SDOMFlags inFlags) override { m_Flags = inFlags; }
+ SDOMFlags GetDOMFlags() const override { return m_Flags; }
+
+ void PushScope() override { m_ScopeStack.push_back(m_TopElement); }
+ void PopScope() override
+ {
+ if (m_ScopeStack.size()) {
+ m_TopElement = m_ScopeStack.back();
+ m_ScopeStack.pop_back();
+ } else
+ m_TopElement = eastl::pair<SDOMElement *, SDOMAttribute *>(NULL, NULL);
+ }
+
+ void *GetScope() override { return m_TopElement.first; }
+
+ void SetScope(void *inScope) override
+ {
+ m_TopElement =
+ eastl::make_pair(reinterpret_cast<SDOMElement *>(inScope), (SDOMAttribute *)NULL);
+ }
+
+ TWideXMLCharPtr GetElementName() const override
+ {
+ return m_StringTable->GetWideStr(GetNarrowElementName());
+ }
+
+ TXMLCharPtr GetNarrowElementName() const override
+ {
+ if (!Current()) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ return Current()->m_Name;
+ }
+
+ bool UnregisteredAtt(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) override
+ {
+ outValue = L"";
+ SDOMElement *current(Current());
+ if (current) {
+ TXMLCharPtr theValue =
+ current->GetAttributeValue(m_StringTable->GetNarrowStr(name), m_Flags);
+ if (theValue && *theValue) {
+ ConvertUTF(theValue, 0, m_TempBuffer);
+ outValue = reinterpret_cast<const wchar_t *>(m_TempBuffer.c_str());
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ bool UnregisteredAtt(TXMLCharPtr name, TXMLCharPtr &outValue) override
+ {
+ outValue = "";
+ SDOMElement *current(Current());
+ if (current) {
+ outValue = current->GetAttributeValue(m_StringTable->GetNarrowStr(name), m_Flags);
+ if (outValue)
+ return true;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ bool Att(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) override
+ {
+ if (UnregisteredAtt(name, outValue)) {
+ outValue = m_StringTable->RegisterStr(outValue);
+ return true;
+ }
+ return false;
+ }
+ bool Att(TXMLCharPtr name, TXMLCharPtr &outValue) override
+ {
+ if (UnregisteredAtt(name, outValue)) {
+ outValue = m_StringTable->RegisterStr(outValue);
+ return true;
+ }
+ return false;
+ }
+
+ QT3DSU32 CountChildren() override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ return elem->GetNumChildren();
+ }
+
+ QT3DSU32 CountChildren(TWideXMLCharPtr childName) override
+ {
+ return CountChildren(m_StringTable->GetNarrowStr(childName));
+ }
+
+ QT3DSU32 CountChildren(TXMLCharPtr childName) override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ return elem->GetNumChildren(m_StringTable->GetNarrowStr(childName), m_Flags);
+ }
+
+ eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr>
+ ToWide(const eastl::pair<TXMLCharPtr, TXMLCharPtr> &att)
+ {
+ return eastl::make_pair(m_StringTable->GetWideStr(att.first),
+ m_StringTable->GetWideStr(att.second));
+ }
+ eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> CurrentAtt()
+ {
+ return ToWide(CurrentAttNarrow());
+ }
+
+ eastl::pair<TXMLCharPtr, TXMLCharPtr> CurrentAttNarrow()
+ {
+ if (m_TopElement.second)
+ return eastl::make_pair(m_TopElement.second->m_Name, m_TopElement.second->m_Value);
+ return eastl::make_pair("", "");
+ }
+ eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowFirstAttribute() override
+ {
+ if (m_TopElement.first == NULL) {
+ QT3DS_ASSERT(false);
+ eastl::make_pair("", "");
+ }
+ m_TopElement.second = m_TopElement.first->m_FirstAttribute;
+ return CurrentAttNarrow();
+ }
+
+ eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetFirstAttribute() override
+ {
+ return ToWide(GetNarrowFirstAttribute());
+ }
+ eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowNextAttribute() override
+ {
+ if (m_TopElement.second)
+ m_TopElement.second = m_TopElement.second->m_NextAttribute;
+ return CurrentAttNarrow();
+ }
+
+ eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetNextAttribute() override
+ {
+ return ToWide(GetNarrowNextAttribute());
+ }
+
+ bool MoveToFirstChild() override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (elem->m_FirstChild) {
+ m_TopElement = elem->m_FirstChild;
+ return true;
+ }
+ return false;
+ }
+ bool MoveToFirstChild(TXMLCharPtr childName) override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ SDOMElement *child = elem->FindChildByName(m_StringTable->RegisterStr(childName), m_Flags);
+ if (child != NULL) {
+ m_TopElement = child;
+ return true;
+ }
+ return false;
+ }
+
+ bool MoveToFirstChild(TWideXMLCharPtr childName) override
+ {
+ return MoveToFirstChild(m_StringTable->GetNarrowStr(childName));
+ }
+
+ bool MoveToNextSibling() override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (elem->m_NextSibling) {
+ m_TopElement = elem->m_NextSibling;
+ return true;
+ }
+ return false;
+ }
+ bool MoveToNextSibling(TXMLCharPtr childName) override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ SDOMElement *nextSibling =
+ elem->FindNextSiblingByName(m_StringTable->RegisterStr(childName), m_Flags);
+ if (nextSibling) {
+ m_TopElement = nextSibling;
+ return true;
+ }
+ return false;
+ }
+ bool MoveToNextSibling(TWideXMLCharPtr childName) override
+ {
+ return MoveToNextSibling(m_StringTable->GetNarrowStr(childName));
+ }
+ // Leave element means go to its parent.
+ void Leave() override
+ {
+ if (m_TopElement)
+ m_TopElement = m_TopElement->m_Parent;
+
+ QT3DS_ASSERT(m_TopElement);
+ }
+ bool Value(TXMLCharPtr &outValue) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ outValue = current->m_Value;
+ return true;
+ }
+
+ bool Value(TWideXMLCharPtr &outValue) override
+ {
+ outValue = L"";
+ TXMLCharPtr theValue;
+ if (Value(theValue)) {
+ ConvertUTF(theValue, 0, m_TempBuffer);
+ outValue = reinterpret_cast<const wchar_t *>(m_TempBuffer.c_str());
+ return true;
+ }
+ return false;
+ }
+
+ SDOMElement *GetTopElement() override
+ {
+ SDOMElement *current(Current());
+ while (current && current->m_Parent)
+ current = current->m_Parent;
+ return current;
+ }
+
+ virtual std::shared_ptr<IDOMFactory> GetFactory() { return m_Factory; }
+};
+
+struct SDOMWriter : public IDOMWriter, public SDOMReader
+{
+ std::shared_ptr<IDOMFactory> m_FactoryPtr;
+ IDOMFactory &m_Factory;
+
+ SDOMWriter(std::shared_ptr<IDOMFactory> inDOMFactory,
+ std::shared_ptr<UICDM::IStringTable> inStringTable, SDOMElement &inTopElem)
+ : m_FactoryPtr(inDOMFactory)
+ , m_Factory(*inDOMFactory)
+ , SDOMReader(inTopElem, inStringTable)
+ {
+ }
+ void SetDOMFlags(SDOMFlags inFlags) override { m_Flags = inFlags; }
+ SDOMFlags GetDOMFlags() const override { return m_Flags; }
+
+ void Begin(TXMLCharPtr inElemName) override
+ {
+ if (!m_TopElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SDOMElement *current(Current());
+ SDOMElement *newElement(m_Factory.NextElement(inElemName));
+ current->AddChild(*newElement);
+ m_TopElement = newElement;
+ }
+
+ void Begin(TWideXMLCharPtr inElemName) override
+ {
+ Begin(m_FactoryPtr->GetStringTable()->GetNarrowStr(inElemName));
+ }
+
+ void Att(TXMLCharPtr name, TXMLCharPtr value) override
+ {
+ if (!m_TopElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_TopElement->SetAttributeValue(name, value, m_Factory, m_Flags);
+ }
+ // Attributes. They may be sorted just before write
+ void Att(TWideXMLCharPtr name, TWideXMLCharPtr value) override
+ {
+ if (!m_TopElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_TopElement->SetAttributeValue(name, value, m_Factory, m_Flags);
+ }
+
+ void Value(TWideXMLCharPtr value) override
+ {
+ if (!m_TopElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (value == NULL)
+ value = L"";
+ size_t len = wcslen(value);
+ m_Factory.AppendStrBuf(value, (QT3DSU32)len);
+ m_TopElement->m_Value = m_Factory.FinalizeStrBuf();
+ }
+ void Value(TXMLCharPtr value) override
+ {
+ if (!m_TopElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (value == NULL)
+ value = "";
+ size_t len = strlen(value);
+ m_Factory.AppendStrBuf(value, (QT3DSU32)len);
+ m_TopElement->m_Value = m_Factory.FinalizeStrBuf();
+ }
+
+ void End() override
+ {
+ if (!m_TopElement) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ Leave();
+ }
+ void RemoveCurrent() override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (current->m_Parent) {
+ m_TopElement = current->m_Parent;
+ m_TopElement->RemoveChild(*current);
+ }
+ }
+ void ReplaceCurrent(SDOMElement &inElement) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (current->m_Parent) {
+ current->m_Parent->ReplaceChild(*current, inElement);
+ m_TopElement = &inElement;
+ } else {
+ m_TopElement = &inElement;
+ inElement.m_Parent = NULL;
+ inElement.m_NextSibling = NULL;
+ }
+ }
+ void AppendChildren(SDOMElement &inElement) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SDOMElement *theChild = inElement.m_FirstChild;
+ inElement.m_FirstChild = inElement.m_LastChild = NULL;
+ while (theChild) {
+ SDOMElement *theCurrentChild = theChild;
+ theChild = theChild->m_NextSibling;
+
+ theCurrentChild->m_Parent = NULL;
+ theCurrentChild->m_NextSibling = NULL;
+ current->AddChild(*theCurrentChild);
+ }
+ }
+ void RemoveAttribute(TXMLCharPtr inItem) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ current->RemoveAttribute(m_StringTable->RegisterStr(inItem), m_Flags);
+ }
+ void RemoveAttribute(TWideXMLCharPtr inItem) override
+ {
+ RemoveAttribute(m_StringTable->GetNarrowStr(inItem));
+ }
+
+ void MoveBefore(TXMLCharPtr inItem, TXMLCharPtr inSibling) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ SDOMElement *theItem =
+ current->FindChildByName(m_StringTable->RegisterStr(inItem), m_Flags);
+ SDOMElement *theSibling =
+ current->FindChildByName(m_StringTable->RegisterStr(inSibling), m_Flags);
+ QT3DS_ASSERT(theItem && theSibling);
+ if (theItem && theSibling) {
+ current->RemoveChild(*theItem);
+ current->InsertChildBefore(*theItem, *theSibling);
+ }
+ }
+
+ void MoveBefore(TWideXMLCharPtr inItem, TWideXMLCharPtr inSibling) override
+ {
+ MoveBefore(m_StringTable->GetNarrowStr(inItem), m_StringTable->GetNarrowStr(inSibling));
+ }
+
+ // If current has no parent, then we are at the top
+ // of the tree and we should return 0. Or if there is no
+ // current.
+ // If there is one parent, we should return 1.
+ QT3DSU32 GetTabs() override
+ {
+ QT3DSU32 retval = 0;
+ SDOMElement *current(Current());
+ do {
+ if (current)
+ current = current->m_Parent;
+ if (current)
+ ++retval;
+ } while (current);
+ return retval;
+ }
+
+ SDOMElement *GetTopElement() override { return SDOMReader::GetTopElement(); }
+
+ std::shared_ptr<IDOMFactory> GetFactory() override { return m_FactoryPtr; }
+};
+
+struct SimpleXmlWriter
+{
+ IOutStream &m_Stream;
+ eastl::vector<eastl::pair<TXMLCharPtr, bool>> m_OpenElements;
+ bool m_ElementOpen;
+ wchar_t m_PrintBuf[256];
+ QT3DSU32 m_Tabs;
+ eastl::basic_string<char8_t> m_ConvertBuf;
+ eastl::basic_string<TWCharEASTLConverter::TCharType> m_WideBuffer;
+
+ SimpleXmlWriter(IOutStream &stream, QT3DSU32 inTabs = 0)
+ : m_Stream(stream)
+ , m_ElementOpen(false)
+ , m_Tabs(inTabs)
+ {
+ }
+ void Write(TWideXMLCharPtr data)
+ {
+ if (!IsTrivial(data)) {
+ ConvertUTF(reinterpret_cast<const TWCharEASTLConverter::TCharType *>(data), 0,
+ m_ConvertBuf);
+ m_Stream.Write(m_ConvertBuf.begin(), m_ConvertBuf.size());
+ }
+ }
+ void Write(const char8_t *data)
+ {
+ if (!IsTrivial(data)) {
+ m_Stream.Write(data, (QT3DSU32)strlen(data));
+ }
+ }
+ void BeginWideWrite() { m_WideBuffer.clear(); }
+ void WriteTemp(wchar_t data) { m_WideBuffer.append(1, data); }
+ void WriteTemp(const wchar_t *data)
+ {
+ m_WideBuffer.append(reinterpret_cast<const TWCharEASTLConverter::TCharType *>(data));
+ }
+ void EndWideWrite() { Write(reinterpret_cast<const wchar_t *>(m_WideBuffer.c_str())); }
+ void Write(char8_t data) { m_Stream.Write(data); }
+ void Tabs()
+ {
+ QT3DSXML_FOREACH(idx, (m_OpenElements.size() + m_Tabs))
+ Write('\t');
+ }
+ void Close(bool newline)
+ {
+ if (m_ElementOpen) {
+ Write(L" >");
+ if (newline)
+ Write('\n');
+ }
+ m_ElementOpen = false;
+ }
+ void Begin(TXMLCharPtr name)
+ {
+ Close(true);
+ Tabs();
+ Write('<');
+ Write(name);
+ m_OpenElements.push_back(eastl::pair<TXMLCharPtr, bool>(name, false));
+ m_ElementOpen = true;
+ }
+ TWideXMLCharPtr ToStr(char8_t val)
+ {
+ m_PrintBuf[0] = val;
+ m_PrintBuf[1] = 0;
+ return m_PrintBuf;
+ }
+ template <typename TDataType>
+ TWideXMLCharPtr ToStr(TDataType val)
+ {
+ WStrOps<TDataType>().ToStr(val, NVDataRef<wchar_t>(m_PrintBuf, 256));
+ return m_PrintBuf;
+ }
+ void Att(TXMLCharPtr name, TXMLCharPtr value)
+ {
+ QT3DS_ASSERT(m_ElementOpen);
+ Write(' ');
+ Write(name);
+ Write("=\"");
+ size_t valueLen = strlen(NonNull(value));
+ TXMLCharPtr start = value;
+ TXMLCharPtr end = value + valueLen;
+ TXMLCharPtr last = start;
+ uint32_t item = 0;
+ // Write out the data escaping unicode values where necessary
+ // I am using utf8::internal because it returns an error code and does not through
+ // exceptions; we don't always know the system we are running on will support or handle
+ // exceptions gracefully.
+ for (utf8::internal::utf_error err_code = utf8::internal::validate_next(start, end, item);
+ last != end && err_code == utf8::internal::UTF8_OK;
+ err_code = utf8::internal::validate_next(start, end, item)) {
+ switch (item) {
+ case '\r':
+ break;
+ case '\n':
+ Write("&#10;");
+ break;
+ case '\t':
+ Write("&#09;");
+ break;
+ case '<':
+ Write("&lt;");
+ break;
+ case '>':
+ Write("&gt;");
+ break;
+ case '"':
+ Write("&quot;");
+ break;
+ case '&':
+ Write("&amp;");
+ break;
+ default:
+ m_Stream.Write(NVConstDataRef<QT3DSU8>((const QT3DSU8 *)last, (QT3DSU32)(start - last)));
+ break;
+ }
+ last = start;
+ }
+ Write("\"");
+ }
+ template <typename TData>
+ void Att(TXMLCharPtr name, TData value)
+ {
+ Att(name, ToStr(value));
+ }
+
+ void Value(TXMLCharPtr value)
+ {
+ if (!IsTrivial(value)) {
+ Close(false);
+ size_t valueLen = strlen(NonNull(value));
+ TXMLCharPtr start = value;
+ TXMLCharPtr end = value + valueLen;
+ TXMLCharPtr last = start;
+ uint32_t item = 0;
+ // Write out the data escaping unicode values where necessary
+ for (utf8::internal::utf_error err_code =
+ utf8::internal::validate_next(start, end, item);
+ last != end && err_code == utf8::internal::UTF8_OK;
+ err_code = utf8::internal::validate_next(start, end, item)) {
+ switch (item) {
+ case '<':
+ Write("&lt;");
+ break;
+ case '>':
+ Write("&gt;");
+ break;
+ case '&':
+ Write("&amp;");
+ break;
+ default:
+ m_Stream.Write(NVConstDataRef<QT3DSU8>((const QT3DSU8 *)last, (QT3DSU32)(start - last)));
+ break;
+ }
+ last = start;
+ }
+ m_OpenElements.back().second = true;
+ }
+ }
+ void ChildValue(TXMLCharPtr name, TXMLCharPtr value)
+ {
+ Begin(name);
+ Value(value);
+ End();
+ }
+ void End(bool newlineAfterClose = true)
+ {
+ QT3DS_ASSERT(m_OpenElements.size());
+ eastl::pair<TXMLCharPtr, bool> topElem = m_OpenElements.back();
+ m_OpenElements.pop_back();
+ if (m_ElementOpen)
+ Write(" />");
+ else {
+ if (topElem.second == false)
+ Tabs();
+ Write("</");
+ Write(topElem.first);
+ Write(">");
+ }
+ m_ElementOpen = false;
+ if (newlineAfterClose == true)
+ Write('\n');
+ }
+};
+
+struct DOMParser
+{
+ typedef eastl::basic_string<TWCharEASTLConverter::TCharType> TStrType;
+ IDOMFactory &m_Factory;
+ SDOMElement *m_TopElement;
+ SDOMElement *m_FirstElement;
+
+ DOMParser(IDOMFactory &factory)
+ : m_Factory(factory)
+ , m_FirstElement(NULL)
+ {
+ }
+
+ template <QT3DSU32 THeaderLen>
+ struct SHeaderInStream : public IInStream
+ {
+ QT3DSU8 m_Header[THeaderLen];
+ QT3DSU32 m_BytesRead;
+ IInStream &m_InStream;
+ SHeaderInStream(IInStream &inStream)
+ : m_InStream(inStream)
+ , m_BytesRead(0)
+ {
+ }
+ bool readHeader()
+ {
+ QT3DSU32 amountRead = m_InStream.Read(NVDataRef<QT3DSU8>(m_Header, THeaderLen));
+ return amountRead == THeaderLen;
+ }
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ if (data.size() == 0)
+ return 0;
+ QT3DSU8 *writePtr(data.begin());
+ QT3DSU32 amountToRead(data.size());
+ QT3DSU32 amountRead = 0;
+ if (m_BytesRead < THeaderLen) {
+ QT3DSU32 headerLeft = NVMin(THeaderLen - m_BytesRead, amountToRead);
+ memCopy(writePtr, m_Header + m_BytesRead, headerLeft);
+ writePtr += headerLeft;
+ amountToRead -= headerLeft;
+ amountRead += headerLeft;
+ }
+ if (amountToRead)
+ amountRead += m_InStream.Read(NVDataRef<QT3DSU8>(writePtr, amountToRead));
+ m_BytesRead += amountRead;
+ return amountRead;
+ }
+ };
+
+ static SDOMElement *ParseXMLFile(IDOMFactory &factory, IInStream &inStream,
+ CXmlErrorHandler *handler = NULL)
+ {
+ QXmlStreamReader sreader;
+
+ DOMParser domParser(factory);
+ QT3DSU8 dataBuf[2048];
+ QT3DSU32 amountRead = 0;
+ do {
+ amountRead = inStream.Read(toDataRef(dataBuf, 2048));
+ if (amountRead) {
+ QByteArray tmp = QByteArray::fromRawData((char*)dataBuf,amountRead);
+ sreader.addData(tmp);
+ }
+ } while (amountRead > 0);
+
+ while (!sreader.atEnd()) {
+ QXmlStreamReader::TokenType token = sreader.readNext();
+
+ if (token == QXmlStreamReader::StartElement) {
+ domParser.m_Factory.IgnoreStrBuf();
+ SDOMElement *newElem = domParser.m_Factory.NextElement(
+ (TXMLCharPtr)sreader.name().toUtf8().data());
+ if (domParser.m_FirstElement == NULL) {
+ domParser.m_FirstElement = newElem;
+ domParser.m_TopElement = newElem;
+ } else {
+ domParser.m_TopElement->AddChild(*newElem);
+ domParser.m_TopElement = newElem;
+ }
+ const QXmlStreamAttributes& attributes = sreader.attributes();
+ for (auto attrib : attributes) {
+ SDOMAttribute *att = domParser.m_Factory.NextAttribute(
+ (TXMLCharPtr)attrib.name().toUtf8().data(),
+ (TXMLCharPtr)attrib.value().toUtf8().data());
+ newElem->AddAttribute(*att);
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ QByteArray text = sreader.text().toUtf8();
+ domParser.m_Factory.AppendStrBuf(text.data(),text.length());
+ } else if (token == QXmlStreamReader::EndElement) {
+ domParser.m_TopElement->m_Value = domParser.m_Factory.FinalizeStrBuf();
+ domParser.m_TopElement = domParser.m_TopElement->m_Parent;
+ }
+ if (sreader.hasError()) {
+ if (handler) {
+ wchar_t *error = new wchar_t[sreader.errorString().length() + 1];
+ sreader.errorString().toWCharArray(error);
+ handler->OnXmlError((TWideXMLCharPtr)error,
+ sreader.lineNumber(), sreader.columnNumber());
+ delete [] error;
+ } else {
+ qWarning() << "XML parse error:" << sreader.errorString()
+ << "line:" << sreader.lineNumber()
+ << "column:" << sreader.columnNumber();
+ }
+ return nullptr;
+ }
+ }
+ return domParser.m_FirstElement;
+ }
+};
+
+class SimpleDomFactory : public IDOMFactory
+{
+ typedef eastl::basic_string<char8_t> TNarrowStr;
+ Pool<SDOMElement> m_ElementPool;
+ Pool<SDOMAttribute> m_AttributePool;
+ eastl::vector<char8_t *> m_BigStrings;
+ eastl::vector<char8_t> m_StringBuilder;
+ TNarrowStr m_ConvertBuffer;
+ std::shared_ptr<UICDM::IStringTable> m_StringTable;
+
+public:
+ SimpleDomFactory(std::shared_ptr<UICDM::IStringTable> strt)
+ : m_StringTable(strt)
+ {
+ }
+ ~SimpleDomFactory()
+ {
+ QT3DSXML_FOREACH(idx, m_BigStrings.size())
+ free(m_BigStrings[idx]);
+ }
+
+ TWideXMLCharPtr RegisterStr(TWideXMLCharPtr str)
+ {
+ if (str == NULL || *str == 0)
+ return L"";
+ return m_StringTable->RegisterStr(str);
+ }
+
+ TXMLCharPtr RegisterStr(TXMLCharPtr str)
+ {
+ if (str == NULL || *str == 0)
+ return "";
+ return m_StringTable->RegisterStr(str);
+ }
+
+ void Release() override { delete this; }
+ void AppendStrBuf(TXMLCharPtr str, QT3DSU32 len) override
+ {
+ if (len && *str) {
+ QT3DSU32 offset = m_StringBuilder.size();
+ m_StringBuilder.resize(offset + len);
+ memCopy(&m_StringBuilder[0] + offset, str, len * sizeof(char8_t));
+ }
+ }
+ // Str does not need to be null terminated.
+ void AppendStrBuf(TWideXMLCharPtr str, QT3DSU32 len) override
+ {
+ if (len && *str) {
+ const TWCharEASTLConverter::TCharType *bufPtr =
+ reinterpret_cast<const TWCharEASTLConverter::TCharType *>(str);
+ ConvertUTF(bufPtr, len, m_ConvertBuffer);
+ AppendStrBuf(m_ConvertBuffer.data(), m_ConvertBuffer.size());
+ }
+ }
+
+ // Null terminate what is there and return the buffer.
+ // This pointer needs to be persistent.
+ TXMLCharPtr FinalizeStrBuf() override
+ {
+ if (m_StringBuilder.size() == 0)
+ return "";
+ m_StringBuilder.push_back(0);
+ QT3DSU32 len = m_StringBuilder.size();
+ QT3DSU32 numBytes = len * sizeof(char8_t);
+ char8_t *newMem = (char8_t *)malloc(numBytes);
+ memCopy(newMem, &m_StringBuilder[0], numBytes);
+ m_BigStrings.push_back(newMem);
+ m_StringBuilder.clear();
+ return newMem;
+ }
+ void IgnoreStrBuf() override { m_StringBuilder.clear(); }
+
+ SDOMAttribute *NextAttribute(TXMLCharPtr name, TXMLCharPtr val) override
+ {
+ TXMLCharPtr n(m_StringTable->GetNarrowStr(name));
+ TXMLCharPtr v(RegisterValue(val));
+ return m_AttributePool.construct(n, v, __FILE__, __LINE__);
+ }
+
+ SDOMAttribute *NextAttribute(TWideXMLCharPtr name, TWideXMLCharPtr val) override
+ {
+ TXMLCharPtr n(m_StringTable->GetNarrowStr(name));
+ TXMLCharPtr v(RegisterValue(val));
+ return m_AttributePool.construct(n, v, __FILE__, __LINE__);
+ }
+
+ SDOMElement *NextElement(TXMLCharPtr name) override
+ {
+ IgnoreStrBuf();
+ TXMLCharPtr n(m_StringTable->GetNarrowStr(name));
+ return m_ElementPool.construct(n, __FILE__, __LINE__);
+ }
+ SDOMElement *NextElement(TWideXMLCharPtr name) override
+ {
+ IgnoreStrBuf();
+ TXMLCharPtr n(m_StringTable->GetNarrowStr(name));
+ return m_ElementPool.construct(n, __FILE__, __LINE__);
+ }
+
+ std::shared_ptr<UICDM::IStringTable> GetStringTable() override { return m_StringTable; }
+};
+}
+
+bool IDOMReader::Value(DataModelDataType::Value type, SValue &outValue)
+{
+ TXMLCharPtr value;
+ if (Value(value)) {
+ WCharTReader reader(const_cast<char8_t *>(value), m_TempBuf, *GetStringTable());
+ outValue = WStrOps<SValue>().BufTo(type, reader);
+ return true;
+ }
+ return false;
+}
+
+std::shared_ptr<IDOMReader>
+IDOMReader::CreateDOMReader(SDOMElement &inRootElement,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ std::shared_ptr<IDOMFactory> inFactory)
+{
+ return std::make_shared<SDOMReader>(std::ref(inRootElement), std::ref(inStringTable),
+ inFactory);
+}
+
+eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>>
+IDOMWriter::CreateDOMWriter(std::shared_ptr<IDOMFactory> inFactory, SDOMElement &inRootElement,
+ std::shared_ptr<UICDM::IStringTable> inStringTable)
+{
+ std::shared_ptr<SDOMWriter> writer(std::make_shared<SDOMWriter>(
+ inFactory, std::ref(inStringTable), std::ref(inRootElement)));
+ return eastl::make_pair(writer, writer);
+}
+
+TXMLCharPtr IDOMFactory::RegisterValue(TWideXMLCharPtr inValue)
+{
+ if (IsTrivial(inValue))
+ return "";
+ IgnoreStrBuf();
+ AppendStrBuf(inValue, (QT3DSU32)wcslen(inValue));
+ return FinalizeStrBuf();
+}
+
+TXMLCharPtr IDOMFactory::RegisterValue(TXMLCharPtr inValue)
+{
+ if (IsTrivial(inValue))
+ return "";
+ IgnoreStrBuf();
+ AppendStrBuf(inValue, (QT3DSU32)strlen(inValue));
+ return FinalizeStrBuf();
+}
+
+std::shared_ptr<IDOMFactory>
+IDOMFactory::CreateDOMFactory(std::shared_ptr<UICDM::IStringTable> inStrTable)
+{
+ return std::make_shared<SimpleDomFactory>(std::ref(inStrTable));
+}
+
+void CDOMSerializer::WriteXMLHeader(IOutStream &inStream)
+{
+ SimpleXmlWriter writer(inStream);
+ writer.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
+}
+
+// Lexigraphically sort the attributes.
+struct SAttributeComparator
+{
+ bool operator()(const SDOMAttribute *lhs, const SDOMAttribute *rhs)
+ {
+ return strcmp(lhs->m_Name, rhs->m_Name) < 0;
+ }
+};
+
+// Write an element with attributes sorted by name so a file diff is effective.
+void WriteElement(SDOMElement &inElement, SimpleXmlWriter &inWriter,
+ std::vector<SDOMAttribute *> &inAttSorter)
+{
+ inAttSorter.clear();
+ for (SDOMAttribute *att = inElement.m_FirstAttribute; att; att = att->m_NextAttribute)
+ inAttSorter.push_back(att);
+ // We decided that we don't want attribute sorting; the code that adds attributes needs
+ // to be consistent.
+ // std::sort( inAttSorter.begin(), inAttSorter.end(), SAttributeComparator() );
+ // This element doesn't add anything to the system in this case.
+ if (inElement.m_FirstAttribute == NULL && inElement.m_FirstChild == NULL
+ && IsTrivial(inElement.m_Value))
+ return;
+
+ inWriter.Begin(inElement.m_Name);
+
+ const char8_t *theLastAttName = 0;
+ for (size_t idx = 0, end = inAttSorter.size(); idx < end; ++idx) {
+ SDOMAttribute *theAtt(inAttSorter[idx]);
+ if (theAtt->m_Name != theLastAttName)
+ inWriter.Att(theAtt->m_Name, theAtt->m_Value);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ theLastAttName = theAtt->m_Name;
+ }
+ // Elements can either have children or values but not both at this point.
+ if (inElement.m_FirstChild) {
+ for (SDOMElement *theChild = inElement.m_FirstChild; theChild;
+ theChild = theChild->m_NextSibling)
+ WriteElement(*theChild, inWriter, inAttSorter);
+ inWriter.End();
+ } else {
+ if (!IsTrivial(inElement.m_Value))
+ inWriter.Value(inElement.m_Value);
+
+ inWriter.End();
+ }
+}
+
+void CDOMSerializer::Write(SDOMElement &inElement, IOutStream &inStream, QT3DSU32 inTabs)
+{
+ // TODO: QXmlStreamWriter here?
+ std::vector<SDOMAttribute *> theAttributes;
+ SimpleXmlWriter writer(inStream, inTabs);
+ std::vector<SDOMAttribute *> theAttSorter;
+ WriteElement(inElement, writer, theAttSorter);
+}
+
+SDOMElement *CDOMSerializer::Read(IDOMFactory &inFactory, IInStream &inStream,
+ CXmlErrorHandler *inErrorHandler)
+{
+ return DOMParser::ParseXMLFile(inFactory, inStream, inErrorHandler);
+}
diff --git a/src/Authoring/UICDM/Systems/UICDMXML.h b/src/Authoring/UICDM/Systems/UICDMXML.h
new file mode 100644
index 00000000..9112c08a
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/UICDMXML.h
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTXMLH
+#define UICIMPORTXMLH
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "UICDMDataTypes.h"
+#include <string>
+#include "UICDMWStrOps.h" //Conversion between string and various datatypes.
+#include "foundation/Qt3DSFlags.h"
+#include "EASTL/algorithm.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/IOStreams.h"
+#include "UICDMValue.h"
+#include <memory>
+
+namespace UICDM {
+using qt3ds::foundation::MemoryBuffer;
+using qt3ds::foundation::RawAllocator;
+class IStringTable;
+
+class IDOMFactory;
+struct SDOMAttribute;
+struct SDOMElement;
+
+typedef const char8_t *TXMLCharPtr;
+typedef const wchar_t *TWideXMLCharPtr;
+
+typedef TCharStr TXMLWideStr;
+typedef eastl::basic_string<char8_t> TXMLStr;
+
+using qt3ds::QT3DSU32;
+using qt3ds::NVFlags;
+using qt3ds::foundation::NVDataRef;
+using qt3ds::foundation::NVConstDataRef;
+using qt3ds::foundation::IOutStream;
+
+class IDOMFactory
+{
+protected:
+ virtual ~IDOMFactory() {}
+public:
+ friend class std::shared_ptr<IDOMFactory>;
+
+ virtual void Release() = 0;
+ // Str does not need to be null terminated.
+ virtual void AppendStrBuf(TXMLCharPtr str, QT3DSU32 len) = 0;
+ virtual void AppendStrBuf(TWideXMLCharPtr str, QT3DSU32 len) = 0;
+ // Null terminate what is there and return the buffer.
+ // This pointer needs to be persistent.
+ virtual TXMLCharPtr FinalizeStrBuf() = 0;
+ virtual void IgnoreStrBuf() = 0;
+
+ virtual std::shared_ptr<IStringTable> GetStringTable() = 0;
+
+ virtual SDOMAttribute *NextAttribute(TWideXMLCharPtr name, TWideXMLCharPtr val) = 0;
+ virtual SDOMElement *NextElement(TWideXMLCharPtr name) = 0;
+
+ virtual SDOMAttribute *NextAttribute(TXMLCharPtr name, TXMLCharPtr val) = 0;
+ virtual SDOMElement *NextElement(TXMLCharPtr name) = 0;
+
+ TXMLCharPtr RegisterValue(TXMLCharPtr inValue);
+ TXMLCharPtr RegisterValue(TWideXMLCharPtr inValue);
+
+ static std::shared_ptr<IDOMFactory>
+ CreateDOMFactory(std::shared_ptr<IStringTable> inStrTable);
+};
+
+struct DOMFlagValues
+{
+ enum Enum {
+ CaselessElementNames = 1 << 0,
+ CaselessAttributeNames = 1 << 1,
+ };
+};
+
+struct SDOMFlags : NVFlags<DOMFlagValues::Enum, int>
+{
+ SDOMFlags()
+ : NVFlags<DOMFlagValues::Enum, int>(DOMFlagValues::CaselessElementNames
+ | DOMFlagValues::CaselessAttributeNames)
+ {
+ }
+ bool CaselessAttributes() const { return *this & DOMFlagValues::CaselessAttributeNames; }
+ bool CaselessElements() const { return *this & DOMFlagValues::CaselessElementNames; }
+};
+
+class IDOMReader
+{
+protected:
+ virtual ~IDOMReader() {}
+public:
+ friend class std::shared_ptr<IDOMReader>;
+
+ // Stack object to save the reader's state.
+ struct Scope
+ {
+ IDOMReader &m_Reader;
+ Scope(IDOMReader &reader)
+ : m_Reader(reader)
+ {
+ m_Reader.PushScope();
+ }
+ ~Scope() { m_Reader.PopScope(); }
+ };
+
+ // Parse buffer
+ MemoryBuffer<RawAllocator> m_TempBuf;
+ std::shared_ptr<IStringTable> m_StringTable;
+
+ IDOMReader(std::shared_ptr<IStringTable> inStringTable)
+ : m_StringTable(inStringTable)
+ {
+ }
+
+ std::shared_ptr<IStringTable> GetStringTable() { return m_StringTable; }
+
+ // DOM reader flags change the nature of the DOM reader.
+ // see DOMFlagValues
+ // Defaults to caseless comparisons for attributes and for
+ // element names.
+ virtual void SetDOMFlags(SDOMFlags inFlags) = 0;
+ virtual SDOMFlags GetDOMFlags() const = 0;
+
+ // Pushing scope saves your state so no matter where you are when
+ // you next pop scope, you come back to the same state.
+ virtual void PushScope() = 0;
+ virtual void PopScope() = 0;
+
+ // Sometimes pushing and popping scope isn't enough and you need
+ // somewhat random access to scope.
+ // This scope does not remember the current attribute.
+ virtual void *GetScope() = 0;
+ virtual void SetScope(void *inScope) = 0;
+ // Return an attribute whose value is *not* registered with the string table.
+ // You can't hold onto this value for any length of time, but when you need to
+ // immediately convert to a different value this is the most efficient way.
+ virtual bool UnregisteredAtt(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) = 0;
+ virtual bool UnregisteredAtt(TXMLCharPtr name, TXMLCharPtr &outValue) = 0;
+ // Return an attribute whose value *is* registered with the string table.
+ virtual bool Att(TWideXMLCharPtr name, TWideXMLCharPtr &outValue) = 0;
+ virtual bool Att(TXMLCharPtr name, TXMLCharPtr &outValue) = 0;
+ virtual eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetFirstAttribute() = 0;
+ virtual eastl::pair<TWideXMLCharPtr, TWideXMLCharPtr> GetNextAttribute() = 0;
+ virtual eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowFirstAttribute() = 0;
+ virtual eastl::pair<TXMLCharPtr, TXMLCharPtr> GetNarrowNextAttribute() = 0;
+ virtual QT3DSU32 CountChildren() = 0;
+ virtual QT3DSU32 CountChildren(TWideXMLCharPtr childName) = 0;
+ virtual QT3DSU32 CountChildren(TXMLCharPtr childName) = 0;
+ virtual bool MoveToFirstChild(TWideXMLCharPtr childName) = 0;
+ virtual bool MoveToFirstChild(TXMLCharPtr childName) = 0;
+ virtual bool MoveToFirstChild() = 0;
+ virtual bool MoveToNextSibling(TWideXMLCharPtr siblingName) = 0;
+ virtual bool MoveToNextSibling(TXMLCharPtr siblingName) = 0;
+ virtual bool MoveToNextSibling() = 0;
+ // Leave element means go to its parent.
+ virtual void Leave() = 0;
+ virtual TWideXMLCharPtr GetElementName() const = 0;
+ virtual TXMLCharPtr GetNarrowElementName() const = 0;
+
+ // Value is the concatentated text node values inside the element
+ virtual bool Value(TWideXMLCharPtr &outValue) = 0;
+ virtual bool Value(TXMLCharPtr &outValue) = 0;
+
+ // Get the element this reader was created with
+ virtual SDOMElement *GetTopElement() = 0;
+
+ bool Att(TWideXMLCharPtr name, TXMLWideStr &outValue)
+ {
+ TWideXMLCharPtr temp;
+ if (UnregisteredAtt(name, temp)) {
+ outValue.assign(temp);
+ return true;
+ }
+ return false;
+ }
+
+ bool Att(TXMLCharPtr name, TXMLStr &outValue)
+ {
+ TXMLCharPtr temp;
+ if (UnregisteredAtt(name, temp)) {
+ outValue.assign(temp);
+ return true;
+ }
+ return false;
+ }
+
+ // Helpers to help make the parsing a bit easier.
+ template <typename TDataType>
+ bool Att(TWideXMLCharPtr name, TDataType &outValue)
+ {
+ TWideXMLCharPtr temp;
+ if (UnregisteredAtt(name, temp)) {
+ WStrOps<TDataType>().StrTo(temp, outValue);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ template <typename TDataType>
+ bool Att(TXMLCharPtr name, TDataType &outValue)
+ {
+ TXMLCharPtr temp;
+ if (UnregisteredAtt(name, temp)) {
+ WStrOps<TDataType>().StrTo(temp, outValue);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool ChildValue(TXMLCharPtr name, TXMLCharPtr &value)
+ {
+ if (MoveToFirstChild(name)) {
+ Value(value);
+ Leave();
+ return true;
+ }
+ return false;
+ }
+
+ bool ChildValue(TWideXMLCharPtr name, TWideXMLCharPtr &value)
+ {
+ if (MoveToFirstChild(name)) {
+ Value(value);
+ Leave();
+ return true;
+ }
+ return false;
+ }
+
+ bool RegisteredChildValue(TWideXMLCharPtr name, TWideXMLCharPtr &value)
+ {
+ if (MoveToFirstChild(name)) {
+ RegisteredValue(value);
+ Leave();
+ return true;
+ }
+ return false;
+ }
+ bool RegisteredChildValue(TXMLCharPtr name, TXMLCharPtr &value)
+ {
+ if (MoveToFirstChild(name)) {
+ RegisteredValue(value);
+ Leave();
+ return true;
+ }
+ return false;
+ }
+ bool RegisteredValue(TWideXMLCharPtr &outValue)
+ {
+ bool retval = Value(outValue);
+ if (retval)
+ outValue = m_StringTable->RegisterStr(outValue);
+ return retval;
+ }
+ bool RegisteredValue(TXMLCharPtr &outValue)
+ {
+ bool retval = Value(outValue);
+ if (retval)
+ outValue = m_StringTable->RegisterStr(outValue);
+ return retval;
+ }
+ bool Value(DataModelDataType::Value type, SValue &outValue);
+
+ template <typename TDataType>
+ bool Value(TDataType &outValue)
+ {
+ TXMLCharPtr value;
+ if (Value(value)) {
+ WStrOps<TDataType>().StrTo(value, outValue);
+ return true;
+ }
+ return false;
+ }
+
+ // Functions below implemented in WStrOpsImpl
+ // to avoid circular dependencies
+ // Returns the number of items read
+ // Destructive parsing
+ template <typename TDataType>
+ bool ValueList(NVDataRef<TDataType> data);
+
+ // Destructive operation because we can't trust
+ // strtod to do the right thing. On windows, for long strings,
+ // it calls strlen every operation thus leading to basically N^2
+ // behavior
+ template <typename TDataType>
+ NVConstDataRef<TDataType> ChildValueList(TWideXMLCharPtr listName);
+
+ template <typename TDataType>
+ NVConstDataRef<TDataType> ChildValueList(TXMLCharPtr listName);
+
+ template <typename TSerializer>
+ void Serialize(const wchar_t *elemName, TSerializer &serializer)
+ {
+ IDOMReader::Scope __theScope(*this);
+ if (MoveToFirstChild(elemName)) {
+ serializer.Serialize(*this);
+ }
+ }
+ // Optionally hold on to the factory to keep our elements in memory as long as we are.
+ static std::shared_ptr<IDOMReader>
+ CreateDOMReader(SDOMElement &inRootElement, std::shared_ptr<IStringTable> inStringTable,
+ std::shared_ptr<IDOMFactory> inFactory = std::shared_ptr<IDOMFactory>());
+};
+
+// Write out data in an xml-like fasion without specifying exactly
+// where that data is being written.
+class IDOMWriter
+{
+protected:
+ virtual ~IDOMWriter() {}
+public:
+ friend class std::shared_ptr<IDOMWriter>;
+
+ // Control the element scope.
+ struct Scope
+ {
+ IDOMWriter &m_Writer;
+ Scope(IDOMWriter &writer, TWideXMLCharPtr inElemName)
+ : m_Writer(writer)
+ {
+ m_Writer.Begin(inElemName);
+ }
+ Scope(IDOMWriter &writer, TXMLCharPtr inElemName)
+ : m_Writer(writer)
+ {
+ m_Writer.Begin(inElemName);
+ }
+ ~Scope() { m_Writer.End(); }
+ };
+
+ wchar_t m_PrintBuf[256];
+ char8_t m_NarrowBuf[256];
+
+ virtual void SetDOMFlags(SDOMFlags inFlags) = 0;
+ virtual SDOMFlags GetDOMFlags() const = 0;
+ // There tend to be two types of elements.
+ // Containers (<a>\n\t<b/><b/>\n</a>)
+ // and Values <b>onetwothree</b>
+ virtual void Begin(TWideXMLCharPtr inElemName) = 0;
+ virtual void Begin(TXMLCharPtr inElemName) = 0;
+ // Attributes. They may be sorted just before write
+ virtual void Att(TWideXMLCharPtr name, TWideXMLCharPtr value) = 0;
+ virtual void Att(TXMLCharPtr name, TXMLCharPtr value) = 0;
+ virtual void Value(TWideXMLCharPtr value) = 0;
+ virtual void Value(TXMLCharPtr value) = 0;
+ virtual void End() = 0;
+ virtual void RemoveCurrent() = 0;
+ virtual void ReplaceCurrent(SDOMElement &inElement) = 0;
+ // Append all the children of inElement to the child list of the current items.
+ virtual void AppendChildren(SDOMElement &inElement) = 0;
+ virtual void RemoveAttribute(TWideXMLCharPtr inItem) = 0;
+ virtual void RemoveAttribute(TXMLCharPtr inItem) = 0;
+ // Get the number of tabs required to line up the next line
+ // with the opening of the previous line
+ virtual QT3DSU32 GetTabs() = 0;
+ virtual SDOMElement *GetTopElement() = 0;
+ virtual std::shared_ptr<IDOMFactory> GetFactory() = 0;
+ // Move this item before this sibling. Function does not rearrange the
+ // tree in any major way and will not work if inItem and inSibling aren't
+ // siblings.
+ virtual void MoveBefore(TWideXMLCharPtr inItem, TWideXMLCharPtr inSibling) = 0;
+ virtual void MoveBefore(TXMLCharPtr inItem, TXMLCharPtr inSibling) = 0;
+
+ virtual void ChildValue(TWideXMLCharPtr name, TWideXMLCharPtr value)
+ {
+ Begin(name);
+ Value(value);
+ End();
+ }
+
+ virtual void ChildValue(TXMLCharPtr name, TXMLCharPtr value)
+ {
+ Begin(name);
+ Value(value);
+ End();
+ }
+
+ TWideXMLCharPtr ToStr(wchar_t val)
+ {
+ m_PrintBuf[0] = val;
+ m_PrintBuf[1] = 0;
+ return m_PrintBuf;
+ }
+ TXMLCharPtr ToStr(char8_t val)
+ {
+ m_NarrowBuf[0] = val;
+ m_NarrowBuf[1] = 0;
+ return m_NarrowBuf;
+ }
+ template <typename TDataType>
+ TWideXMLCharPtr ToStr(TDataType val)
+ {
+ WStrOps<TDataType>().ToStr(val, NVDataRef<wchar_t>(m_PrintBuf, 256));
+ return m_PrintBuf;
+ }
+
+ template <typename TDataType>
+ TXMLCharPtr ToNarrowStr(TDataType val)
+ {
+ WStrOps<TDataType>().ToStr(val, NVDataRef<char8_t>(m_NarrowBuf, 256));
+ return m_NarrowBuf;
+ }
+
+ void Att(TWideXMLCharPtr name, const TXMLWideStr &inValue)
+ {
+ return Att(name, inValue.wide_str());
+ }
+
+ void Att(TXMLCharPtr name, const TXMLStr &inValue) { return Att(name, inValue.c_str()); }
+
+ template <typename TData>
+ void Att(TWideXMLCharPtr name, TData value)
+ {
+ Att(name, ToStr(value));
+ }
+
+ template <typename TData>
+ void Att(TXMLCharPtr name, TData value)
+ {
+ Att(name, ToNarrowStr(value));
+ }
+
+ template <typename TSerializer>
+ void Serialize(const wchar_t *elemName, TSerializer &serializer)
+ {
+ IDOMWriter::Scope __theScope(*this, elemName);
+ serializer.Serialize(*this);
+ }
+
+ template <typename TSerializer>
+ void Serialize(const char8_t *elemName, TSerializer &serializer)
+ {
+ IDOMWriter::Scope __theScope(*this, elemName);
+ serializer.Serialize(*this);
+ }
+
+ std::shared_ptr<IDOMReader> CreateDOMReader()
+ {
+ std::shared_ptr<IDOMFactory> theFactory(GetFactory());
+ return IDOMReader::CreateDOMReader(*GetTopElement(), theFactory->GetStringTable(),
+ theFactory);
+ }
+
+ // Note that the default method of creating a writer also creates a reader; they can
+ // both manipulation the DOM hierarch.
+ static eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>>
+ CreateDOMWriter(std::shared_ptr<IDOMFactory> inFactory, SDOMElement &inRootElement,
+ std::shared_ptr<IStringTable> inStringTable);
+
+ static eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>>
+ CreateDOMWriter(const wchar_t *inTopElemName, std::shared_ptr<IStringTable> inStringTable)
+ {
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(inStringTable));
+ SDOMElement *theRoot = theFactory->NextElement(inTopElemName);
+ return CreateDOMWriter(theFactory, *theRoot, inStringTable);
+ }
+};
+
+class CXmlErrorHandler
+{
+protected:
+ virtual ~CXmlErrorHandler() {}
+public:
+ virtual void OnXmlError(TWideXMLCharPtr errorName, int line, int column) = 0;
+};
+
+class CDOMSerializer
+{
+public:
+ static void WriteXMLHeader(IOutStream &inStream);
+ static void Write(SDOMElement &inElement, IOutStream &inStream, QT3DSU32 inTabs = 0);
+ static SDOMElement *Read(IDOMFactory &inFactory, qt3ds::foundation::IInStream &inStream,
+ CXmlErrorHandler *inErrorHandler = NULL);
+};
+}
+#endif
diff --git a/src/Authoring/UICDM/Systems/VectorTransactions.h b/src/Authoring/UICDM/Systems/VectorTransactions.h
new file mode 100644
index 00000000..55c9c4aa
--- /dev/null
+++ b/src/Authoring/UICDM/Systems/VectorTransactions.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef VECTORTRANSACTIONSH
+#define VECTORTRANSACTIONSH
+
+namespace UICDM {
+template <typename TItemType>
+inline void VecInsert(std::vector<TItemType> &inItems, const TItemType &inItem, size_t inIndex)
+{
+ inItems.insert(inItems.begin() + inIndex, inItem);
+}
+
+template <typename TItemType>
+inline void VecErase(std::vector<TItemType> &inItems, const TItemType &inItem)
+{
+ erase_if(inItems, std::bind(std::equal_to<TItemType>(), inItem, std::placeholders::_1));
+}
+
+template <typename TItemType>
+inline void VecInsertTransaction(const char *inFile, int inLine, std::vector<TItemType> &inItems,
+ size_t inIndex, TTransactionConsumerPtr &inConsumer)
+{
+ TItemType theItem = inItems.at(inIndex);
+ TTransactionPtr theTransaction(DoCreateGenericTransaction(
+ inFile, inLine, std::bind(VecInsert<TItemType>, std::ref(inItems), theItem, inIndex),
+ std::bind(VecErase<TItemType>, std::ref(inItems), theItem)));
+ inConsumer->OnTransaction(theTransaction);
+}
+
+template <typename TItemType>
+inline void VecEraseTransaction(const char *inFile, int inLine, std::vector<TItemType> &inItems,
+ size_t inIndex, const TItemType &inItem,
+ TTransactionConsumerPtr &inConsumer)
+{
+ TTransactionPtr theTransaction(DoCreateGenericTransaction(
+ inFile, inLine, std::bind(VecErase<TItemType>, std::ref(inItems), inItem),
+ std::bind(VecInsert<TItemType>, std::ref(inItems), inItem, inIndex)));
+ inConsumer->OnTransaction(theTransaction);
+}
+
+template <typename TItemType>
+inline void CreateVecInsertTransaction(const char *inFile, int inLine,
+ TTransactionConsumerPtr inConsumer, const TItemType &inItem,
+ std::vector<TItemType> &inItems)
+{
+ using namespace std;
+ size_t theDistance = distance(inItems.begin(), find(inItems.begin(), inItems.end(), inItem));
+ RunWithConsumer(inConsumer, std::bind(VecInsertTransaction<TItemType>, inFile, inLine,
+ std::ref(inItems), theDistance, std::placeholders::_1));
+}
+
+template <typename TItemType>
+inline void CreateVecEraseTransaction(const char *inFile, int inLine,
+ TTransactionConsumerPtr inConsumer, const TItemType &inItem,
+ std::vector<TItemType> &inItems)
+{
+ using namespace std;
+ size_t theDistance = distance(inItems.begin(), find(inItems.begin(), inItems.end(), inItem));
+ RunWithConsumer(inConsumer,
+ std::bind(VecEraseTransaction<TItemType>, inFile, inLine, std::ref(inItems),
+ theDistance, std::ref(inItem), std::placeholders::_1));
+}
+
+template <typename TKeyType, typename TValueType, typename THashType>
+struct HashMapAction
+{
+ std::unordered_map<TKeyType, TValueType, THashType> &m_HashMap;
+ std::pair<TKeyType, TValueType> m_Value;
+
+ HashMapAction(std::unordered_map<TKeyType, TValueType, THashType> &map,
+ const std::pair<TKeyType, TValueType> &val)
+ : m_HashMap(map)
+ , m_Value(val)
+ {
+ }
+ bool Exists() { return m_HashMap.find(m_Value.first) != m_HashMap.end(); }
+ void Add()
+ {
+ Q_ASSERT(!Exists());
+ m_HashMap.insert(m_Value);
+ }
+ void Remove()
+ {
+ Q_ASSERT(Exists());
+ m_HashMap.erase(m_HashMap.find(m_Value.first));
+ }
+};
+
+template <typename TKeyType, typename TValueType, typename THashType>
+struct HashMapInsertTransaction : public HashMapAction<TKeyType, TValueType, THashType>,
+ public ITransaction,
+ public IMergeableTransaction<TValueType>
+{
+ typedef HashMapAction<TKeyType, TValueType, THashType> base;
+ HashMapInsertTransaction(const char *inFile, int inLine,
+ std::unordered_map<TKeyType, TValueType, THashType> &map,
+ const std::pair<TKeyType, TValueType> &val)
+ : HashMapAction<TKeyType, TValueType, THashType>(map, val)
+ , ITransaction(inFile, inLine)
+ {
+ }
+ void Do() override { base::Add(); }
+ void Undo() override { base::Remove(); }
+ void Update(const TValueType &inValue) override { base::m_Value.second = inValue; }
+};
+
+template <typename TKeyType, typename TValueType, typename THashType>
+struct HashMapEraseTransaction : public HashMapAction<TKeyType, TValueType, THashType>,
+ public ITransaction
+{
+ typedef HashMapAction<TKeyType, TValueType, THashType> base;
+ HashMapEraseTransaction(const char *inFile, int inLine,
+ std::unordered_map<TKeyType, TValueType, THashType> &map,
+ const std::pair<TKeyType, TValueType> &val)
+ : HashMapAction<TKeyType, TValueType, THashType>(map, val)
+ , ITransaction(inFile, inLine)
+ {
+ }
+ void Do() override { base::Remove(); }
+ void Undo() override { base::Add(); }
+};
+
+template <typename TKeyType, typename TValueType, typename THashType>
+inline std::shared_ptr<IMergeableTransaction<TValueType>>
+CreateHashMapInsertTransaction(const char *inFile, int inLine, TTransactionConsumerPtr inConsumer,
+ const std::pair<TKeyType, TValueType> &inItem,
+ std::unordered_map<TKeyType, TValueType, THashType> &inItems)
+{
+ using namespace std;
+ std::shared_ptr<IMergeableTransaction<TValueType>> retval;
+ if (inConsumer) {
+ std::shared_ptr<HashMapInsertTransaction<TKeyType, TValueType, THashType>> transaction(
+ std::make_shared<HashMapInsertTransaction<TKeyType, TValueType, THashType>>(
+ inFile, inLine, std::ref(inItems), std::cref(inItem)));
+ retval = static_pointer_cast<IMergeableTransaction<TValueType>>(transaction);
+ inConsumer->OnTransaction(static_pointer_cast<ITransaction>(transaction));
+ }
+ return retval;
+}
+
+template <typename TKeyType, typename TValueType, typename THashType>
+inline void
+CreateHashMapEraseTransaction(const char *inFile, int inLine, TTransactionConsumerPtr inConsumer,
+ const std::pair<TKeyType, TValueType> &inItem,
+ std::unordered_map<TKeyType, TValueType, THashType> &inItems)
+{
+ using namespace std;
+ if (inConsumer)
+ inConsumer->OnTransaction(static_pointer_cast<ITransaction>(
+ std::make_shared<HashMapEraseTransaction<TKeyType, TValueType, THashType>>(
+ inFile, inLine, std::ref(inItems), std::cref(inItem))));
+}
+
+template <typename TKeyType, typename TValueType, typename THashType>
+struct HashMapSwapTransaction : public ITransaction, public IMergeableTransaction<TValueType>
+{
+ typedef std::unordered_map<TKeyType, TValueType, THashType> TMapType;
+
+ TMapType &m_HashMap;
+ TKeyType m_Key;
+ TValueType m_OldValue;
+ TValueType m_NewValue;
+
+ HashMapSwapTransaction(const char *inFile, int inLine, TMapType &inMap, const TKeyType &inKey,
+ const TValueType &inOldVal, const TValueType &inNewVal)
+ : ITransaction(inFile, inLine)
+ , m_HashMap(inMap)
+ , m_Key(inKey)
+ , m_OldValue(inOldVal)
+ , m_NewValue(inNewVal)
+ {
+ }
+
+ bool Exists() { return m_HashMap.find(m_Key) != m_HashMap.end(); }
+ void SetValue(const TValueType &inVal)
+ {
+ typename TMapType::iterator find(m_HashMap.find(m_Key));
+ if (find != m_HashMap.end())
+ find->second = inVal;
+ else {
+ Q_ASSERT(0);
+ m_HashMap.insert(std::make_pair(m_Key, inVal));
+ }
+ }
+ void Do() override { SetValue(m_NewValue); }
+ void Undo() override { SetValue(m_OldValue); }
+ void Update(const TValueType &inValue) override { m_NewValue = inValue; }
+};
+
+template <typename TKeyType, typename TValueType, typename THashType>
+inline std::shared_ptr<IMergeableTransaction<TValueType>>
+CreateHashMapSwapTransaction(const char *inFile, int inLine, TTransactionConsumerPtr inConsumer,
+ const TKeyType &inKey, const TValueType &inOldValue,
+ const TValueType &inNewValue,
+ std::unordered_map<TKeyType, TValueType, THashType> &inItems)
+{
+ using namespace std;
+ std::shared_ptr<IMergeableTransaction<TValueType>> retval;
+ if (inConsumer) {
+ std::shared_ptr<HashMapSwapTransaction<TKeyType, TValueType, THashType>> transaction =
+ std::make_shared<HashMapSwapTransaction<TKeyType, TValueType, THashType>>(
+ inFile, inLine, std::ref(inItems), inKey, inOldValue, inNewValue);
+ retval = static_pointer_cast<IMergeableTransaction<TValueType>>(transaction);
+ inConsumer->OnTransaction(static_pointer_cast<ITransaction>(transaction));
+ }
+ return retval;
+}
+}
+
+#endif
diff --git a/src/Authoring/UICDM/UICDMPrefix.cpp b/src/Authoring/UICDM/UICDMPrefix.cpp
new file mode 100644
index 00000000..681e136d
--- /dev/null
+++ b/src/Authoring/UICDM/UICDMPrefix.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// UICDM.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "UICDMPrefix.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/Authoring/UICDM/UICDMPrefix.h b/src/Authoring/UICDM/UICDMPrefix.h
new file mode 100644
index 00000000..4b60c666
--- /dev/null
+++ b/src/Authoring/UICDM/UICDMPrefix.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#ifdef __cplusplus
+#pragma once
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT \
+ 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+// TODO: reference additional headers your program requires here
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4100)
+#pragma warning(disable : 4512)
+#pragma warning(disable : 4702)
+#pragma warning(disable : 4996)
+#endif
+
+// std includes
+#include <map>
+#include <vector>
+#include <string>
+#include <exception>
+#include <set>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <memory>
+#include <functional>
+
+// Project includes
+#include "StandardExtensions.h"
+
+namespace UICDM {
+using std::ref;
+using std::get;
+using std::bind;
+using std::tuple;
+using std::static_pointer_cast;
+using std::make_pair;
+using std::equal_to;
+using std::vector;
+using std::make_tuple;
+using std::function;
+using std::shared_ptr;
+using std::make_shared;
+}
+#ifdef WIN32
+#pragma warning(pop)
+#endif
+#endif
diff --git a/src/Authoring/UICIMP/ReadMe.txt b/src/Authoring/UICIMP/ReadMe.txt
new file mode 100644
index 00000000..3fb7ab86
--- /dev/null
+++ b/src/Authoring/UICIMP/ReadMe.txt
@@ -0,0 +1,30 @@
+========================================================================
+ STATIC LIBRARY : UICImportLib Project Overview
+========================================================================
+
+AppWizard has created this UICImportLib library project for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your UICImportLib application.
+
+
+UICImportLib.vcproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named UICImportLib.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/Authoring/UICIMP/UICImportLib/UICFileToolsSeekableMeshBufIOStream.h b/src/Authoring/UICIMP/UICImportLib/UICFileToolsSeekableMeshBufIOStream.h
new file mode 100644
index 00000000..221c433b
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICFileToolsSeekableMeshBufIOStream.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICFILETOOLSSEEKABLEMESHBUFIOSTREAM
+#define UICFILETOOLSSEEKABLEMESHBUFIOSTREAM
+#include "foundation/IOStreams.h"
+
+namespace Q3DStudio {
+struct SFile;
+}
+
+namespace UICIMP {
+class CUICFileToolsSeekableMeshBufIOStream : public qt3ds::foundation::ISeekableIOStream
+{
+protected:
+ std::shared_ptr<Q3DStudio::SFile> m_File;
+
+public:
+ CUICFileToolsSeekableMeshBufIOStream(std::shared_ptr<Q3DStudio::SFile> inFile)
+ : m_File(inFile)
+ {
+ }
+ virtual bool IsOpen() { return m_File != NULL; }
+
+ void SetPosition(qt3ds::QT3DSI64 inOffset, qt3ds::foundation::SeekPosition::Enum inEnum) override;
+ qt3ds::QT3DSI64 GetPosition() const override;
+ qt3ds::QT3DSU32 Read(qt3ds::foundation::NVDataRef<QT3DSU8> data) override;
+ bool Write(qt3ds::foundation::NVConstDataRef<QT3DSU8> data) override;
+};
+}
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImport.cpp b/src/Authoring/UICIMP/UICImportLib/UICImport.cpp
new file mode 100644
index 00000000..8f57b726
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImport.cpp
@@ -0,0 +1,1942 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICImportLibPrecompile.h"
+#include "UICImport.h"
+#include "UICImportImpl.h"
+#include <algorithm>
+#include "UICFileTools.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "UICDMXML.h"
+#include "UICDMWStrOps.h"
+#include "UICDMWStrOpsImpl.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "UICImportComposerTypes.h"
+#include "UICFileToolsSeekableMeshBufIOStream.h"
+#include "foundation/StrConvertUTF.h"
+
+using UICDM::IStringTable;
+
+namespace UICDM {
+}
+
+using namespace UICIMP;
+
+namespace eastl {
+template <>
+struct hash<AnimationId>
+{
+ size_t operator()(const AnimationId &id) const
+ {
+ return hash<TIMPHandle>()(id.m_Instance) ^ hash<TCharPtr>()(id.m_Property)
+ ^ hash<QT3DSU32>()(id.m_SubPropIndex);
+ }
+};
+
+template <>
+struct equal_to<AnimationId>
+{
+ bool operator()(const AnimationId &lhs, const AnimationId &rhs) const
+ {
+ return lhs.m_Instance == rhs.m_Instance && AreEqual(lhs.m_Property, rhs.m_Property)
+ && lhs.m_SubPropIndex == rhs.m_SubPropIndex;
+ }
+};
+}
+
+using eastl::make_pair;
+using std::get;
+using std::tuple;
+using std::shared_ptr;
+
+namespace qt3ds {
+namespace foundation {
+}
+}
+
+using namespace Q3DStudio;
+
+namespace {
+
+template <typename TDataType>
+struct AddRemoveImpl
+{
+ ImportArray<TDataType> m_Existing;
+ ImportArray<TDataType> m_Added;
+ ImportArray<TDataType> m_Removed;
+
+ operator AddRemoveData<TDataType>() const
+ {
+ return AddRemoveData<TDataType>(m_Existing, m_Added, m_Removed);
+ }
+ void clear()
+ {
+ m_Existing.clear();
+ m_Added.clear();
+ m_Removed.clear();
+ }
+};
+
+struct ImportReportImpl
+{
+ // There is a precondition upon added instances that parents are
+ // added before children.
+ AddRemoveImpl<InstanceDesc> m_Instances;
+ AddRemoveImpl<ParentChildLink> m_Links;
+ ImportArray<Pair<InstanceDesc, ComposerObjectTypes::Enum>> m_TypeChanges;
+ AddRemoveImpl<Pair<TCharPtr, TCharPtr>> m_Images;
+ AddRemoveImpl<Pair<TCharPtr, TCharPtr>> m_Meshes;
+ AddRemoveImpl<Pair<TCharPtr, TCharPtr>> m_PathBuffers;
+ AddRemoveImpl<Animation> m_Animations;
+
+ operator ImportReport()
+ {
+ return ImportReport(m_Instances, m_Links, m_Images, m_Meshes, m_PathBuffers, m_Animations);
+ }
+
+ void clear()
+ {
+ m_Instances.clear();
+ m_Links.clear();
+ m_Images.clear();
+ m_Meshes.clear();
+ m_PathBuffers.clear();
+ m_Animations.clear();
+ }
+};
+
+struct InstanceDiffOp
+{
+ QT3DSU32 NumItems(const Import &src) { return src.GetNumInstances(); }
+ void GetItems(const Import &src, NVDataRef<InstanceDesc> data) { src.GetInstances(data); }
+ // ID's *and* types have to match in order to get valid output
+ bool HasItem(const Import &src, const InstanceDesc &data)
+ {
+ Option<InstanceDesc> result(src.FindInstanceById(data.m_Id));
+ return result.hasValue() && result->m_Type == data.m_Type;
+ }
+};
+
+bool FindChild(Option<InstanceDesc> hdlOpt, TCharPtr inCompareNextSibling,
+ ComposerObjectTypes::Enum childType, NVDataRef<InstanceDesc> children)
+{
+ if (hdlOpt.hasValue() == false)
+ return false;
+ TCharPtr id = hdlOpt->m_Id;
+ QT3DSIMP_FOREACH(idx, children.size())
+ {
+ TCharPtr nextSibling = idx + 1 < children.size() ? children[idx + 1].m_Id : L"";
+ // Because we know that the import objects share a single string table,
+ // we know that equal strings will actually be equal via ptr comparison
+ if (children[idx].m_Id == id && children[idx].m_Type == childType
+ && inCompareNextSibling == nextSibling)
+ return true;
+ }
+ return false;
+}
+
+struct ImageDiffOp
+{
+ QT3DSU32 NumItems(const Import &src) { return src.GetNumImages(); }
+ void GetItems(const Import &src, NVDataRef<Pair<TCharPtr, TCharPtr>> data)
+ {
+ src.GetImages(data);
+ }
+ bool HasItem(const Import &src, const Pair<TCharPtr, TCharPtr> &data)
+ {
+ return src.FindImageByRelativePath(data.first).hasValue();
+ }
+};
+
+struct MeshDiffOp
+{
+ QT3DSU32 NumItems(const Import &src) { return src.GetNumMeshes(); }
+ void GetItems(const Import &src, NVDataRef<Pair<TCharPtr, TCharPtr>> data)
+ {
+ src.GetMeshes(data);
+ }
+ bool HasItem(const Import &src, const Pair<TCharPtr, TCharPtr> &data)
+ {
+ return src.HasMesh(data.first);
+ }
+};
+
+struct PathBufferDiffOp
+{
+ QT3DSU32 NumItems(const Import &src) { return src.GetNumPathBuffers(); }
+ void GetItems(const Import &src, NVDataRef<Pair<TCharPtr, TCharPtr>> data)
+ {
+ src.GetPathBuffers(data);
+ }
+ bool HasItem(const Import &src, const Pair<TCharPtr, TCharPtr> &data)
+ {
+ return src.FindPathBufferByRelativePath(data.first).hasValue();
+ }
+};
+
+struct AnimationDiffOp
+{
+ QT3DSU32 NumItems(const Import &src) { return src.GetNumAnimations(); }
+ void GetItems(const Import &src, NVDataRef<Animation> data) { src.GetAnimations(data); }
+ bool HasItem(const Import &src, const Animation &data)
+ {
+ return src.FindAnimation(data.m_InstanceId, data.m_PropertyName, data.m_SubPropertyIndex)
+ .hasValue();
+ }
+};
+
+/* Numbers generated from random.org
+-784146867 -929005747 161935609 -555777497 -951253607
+44567464 -991929537(used) -541528542 -52708032 765363476
+*/
+
+struct MeshEntry
+{
+ TCharPtr m_SourceId;
+ TCharPtr m_FilePath;
+ TCharPtr m_ReferencePath; // file path plus revision
+ MeshEntry(TCharPtr inSourceId, CFilePath inPath, QT3DSU32 inRevision,
+ UICDM::IStringTable &inStringTable)
+ : m_SourceId(inSourceId)
+ , m_FilePath(L"")
+ , m_ReferencePath(L"")
+ {
+ m_FilePath = inStringTable.RegisterStr(inPath);
+ inPath.SetIdentifier(inRevision);
+ m_ReferencePath = inStringTable.RegisterStr(inPath);
+ }
+
+ MeshEntry(TCharPtr inSourceId, TCharPtr inPath, UICDM::IStringTable &inStringTable)
+ : m_SourceId(inStringTable.RegisterStr(inSourceId))
+ , m_FilePath(inStringTable.RegisterStr(inPath))
+ , m_ReferencePath(L"")
+ {
+ }
+};
+
+struct STCharPtrHash
+{
+#ifdef _WIN32
+ size_t operator()(TCharPtr nm) const
+ {
+ StaticAssert<sizeof(wchar_t) == sizeof(char16_t)>::valid_expression();
+ return eastl::hash<const char16_t *>()(reinterpret_cast<const char16_t *>(nm));
+ }
+
+#else
+ size_t operator()(TCharPtr nm) const
+ {
+ StaticAssert<sizeof(wchar_t) == sizeof(char32_t)>::valid_expression();
+ return eastl::hash<const char32_t *>()(reinterpret_cast<const char32_t *>(nm));
+ }
+#endif
+};
+
+struct STCharPtrEqualTo
+{
+ bool operator()(TCharPtr lhs, TCharPtr rhs) const { return AreEqual(lhs, rhs); }
+};
+
+class ImportImpl : public Import
+{
+public:
+ typedef ImportHashMap<TCharPtr, Instance *, STCharPtrHash, STCharPtrEqualTo> TIdToInstanceMap;
+ typedef ImportHashMap<TCharPtr, TCharPtr, STCharPtrHash, STCharPtrEqualTo> TStrToStrMap;
+ typedef ImportHashMap<TCharPtr, MeshEntry, STCharPtrHash, STCharPtrEqualTo> TPathToMeshMap;
+
+ TStringTablePtr m_StringTablePtr;
+ UICDM::IStringTable &m_StringTable;
+ ImportHashSet<TIMPHandle> m_ValidInstances;
+ ImportHashSet<TIMPHandle> m_InValidInstances;
+ TIdToInstanceMap m_IdToInstMap;
+ // Mapping from original ID to new location
+ TStrToStrMap m_Images;
+ TStrToStrMap m_PathBuffers;
+ // Mapping from mesh name to new location
+ TPathToMeshMap m_Meshes;
+ ImportHashMap<AnimationId, Animation *> m_Animations;
+
+ CFilePath m_DestDirectory;
+ CFilePath m_SrcDirectory;
+ CFilePath m_SrcFile;
+ CFilePath m_FullSrcDirectory;
+ CFilePath m_ImageDir;
+ CFilePath m_MeshDir;
+ CFilePath m_PathBufferDir;
+ mutable ImportReportImpl m_ImportReport;
+ eastl::string m_ConvertStr;
+
+ virtual ~ImportImpl()
+ {
+ for (ImportHashSet<TIMPHandle>::iterator iter = m_ValidInstances.begin(),
+ end = m_ValidInstances.end();
+ iter != end; ++iter)
+ delete fromHdl((*iter));
+ for (ImportHashMap<AnimationId, Animation *>::iterator iter = m_Animations.begin(),
+ end = m_Animations.end();
+ iter != end; ++iter)
+ free(iter->second);
+ m_ValidInstances.clear();
+ m_Animations.clear();
+ m_InValidInstances.clear();
+ }
+
+ ImportImpl(TStringTablePtr strTable, const Q3DStudio::CString &srcFile,
+ const Q3DStudio::CString &destDirectory, const wchar_t *imagesDir = L"",
+ const wchar_t *meshesDir = L"")
+ : m_StringTablePtr(strTable)
+ , m_StringTable(*strTable.get())
+ , m_DestDirectory(destDirectory)
+ {
+ if (srcFile.Length()) {
+ m_FullSrcDirectory = CFilePath(srcFile).GetDirectory();
+ m_SrcFile = CFilePath::GetRelativePathFromBase(destDirectory, srcFile);
+ m_SrcDirectory = CFilePath(m_SrcFile).GetDirectory();
+ }
+ // On load, images and meshes directories will be trivial.
+ if (!IsTrivial(imagesDir))
+ m_ImageDir = CFilePath::CombineBaseAndRelative(destDirectory, CString(imagesDir));
+ if (!IsTrivial(meshesDir))
+ m_MeshDir = CFilePath::CombineBaseAndRelative(destDirectory, CString(meshesDir));
+ m_PathBufferDir = CFilePath::CombineBaseAndRelative(destDirectory, CString(L"paths"));
+ }
+
+ TCharPtr RegisterStr(TCharPtr str) override { return m_StringTable.RegisterStr(str); }
+ TCharPtr GetSrcFile() const override { return m_SrcFile.c_str(); }
+ TCharPtr GetDestDir() const override { return m_DestDirectory.c_str(); }
+ TCharPtr GetImageDir() const override { return m_ImageDir.c_str(); }
+ TCharPtr GetMeshDir() const override { return m_MeshDir.c_str(); }
+ TCharPtr GetPathBufferDir() const override { return m_PathBufferDir.c_str(); }
+ void Release() override { delete this; }
+
+ Instance *GetInstance(TIMPHandle inst) const
+ {
+ if (m_ValidInstances.contains(inst))
+ return fromHdl(inst);
+ return NULL;
+ }
+
+ Instance *GetInstance(TIMPHandle inst)
+ {
+ if (m_ValidInstances.contains(inst))
+ return fromHdl(inst);
+ return NULL;
+ }
+
+ Instance *GetInstance(TCharPtr id)
+ {
+ ImportHashMap<TCharPtr, Instance *>::const_iterator entry = m_IdToInstMap.find(id);
+ if (entry != m_IdToInstMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ Instance *GetInstance(TCharPtr id) const
+ {
+ ImportHashMap<TCharPtr, Instance *>::const_iterator entry = m_IdToInstMap.find(id);
+ if (entry != m_IdToInstMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ Option<InstanceDesc> GetInstanceByHandle(TIMPHandle inst) const override
+ {
+ if (m_ValidInstances.contains(inst))
+ return *fromHdl(inst);
+ return Empty();
+ }
+ Option<InstanceDesc> FindInstanceById(TCharPtr inst) const override
+ {
+ Instance *retval = GetInstance(inst);
+ if (retval && retval->m_Valid)
+ return *retval;
+ return Empty();
+ }
+
+ Option<InstanceDesc> FindAnyInstanceById(TCharPtr inst) const override
+ {
+ Instance *retval = GetInstance(inst);
+ if (retval)
+ return *retval;
+ return Empty();
+ }
+
+ // Add a mapping from an named id to a handle
+ QT3DSU32 GetNumInstances() const override
+ {
+ return (QT3DSU32)(m_ValidInstances.size() - m_InValidInstances.size());
+ }
+
+ void AddInstance(Instance *inInstance, NVDataRef<InstanceDesc> &inAdded, QT3DSU32 &addIdx,
+ QT3DSU32 numItems) const
+ {
+ if (addIdx < numItems) {
+ inAdded[addIdx] = *inInstance;
+ ++addIdx;
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)inInstance->m_Children.size())
+ {
+ Instance *child = GetInstance(inInstance->m_Children[idx]);
+ AddInstance(child, inAdded, addIdx, numItems);
+ }
+ }
+ }
+
+ QT3DSU32 GetInstances(NVDataRef<InstanceDesc> outDescs) const override
+ {
+ QT3DS_ASSERT(outDescs.size() >= GetNumInstances());
+ QT3DSU32 numItems = NVMin(outDescs.size(), GetNumInstances());
+ QT3DSU32 idx = 0;
+
+ ImportHashSet<TIMPHandle> &validInstances(
+ const_cast<ImportHashSet<TIMPHandle> &>(m_ValidInstances));
+ for (ImportHashSet<TIMPHandle>::iterator theIter = validInstances.begin(),
+ end = validInstances.end();
+ theIter != end; ++theIter) {
+ if (m_InValidInstances.contains(*theIter))
+ continue;
+
+ Instance *theInstance = GetInstance(*theIter);
+ if (theInstance->m_Parent == 0)
+ AddInstance(theInstance, outDescs, idx, numItems);
+ }
+
+ return numItems;
+ }
+ QT3DSU32 GetNumProperties(TIMPHandle instance) const override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ return (QT3DSU32)inst->m_PropertyValues.size();
+ }
+ QT3DSU32 GetProperties(TIMPHandle instance, NVDataRef<PropertyValue> outBuffer) const override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ QT3DSU32 numItems = NVMin((QT3DSU32)outBuffer.size(), (QT3DSU32)inst->m_PropertyValues.size());
+ QT3DSU32 idx = 0;
+ for (ImportHashMap<ComposerPropertyNames::Enum, SInternValue>::iterator
+ iter = inst->m_PropertyValues.begin(),
+ end = inst->m_PropertyValues.end();
+ iter != end && idx < numItems; ++iter, ++idx)
+ outBuffer[idx] = PropertyValue(iter->first, iter->second);
+ return numItems;
+ }
+ Option<SValue> GetInstancePropertyValue(TIMPHandle instance,
+ ComposerPropertyNames::Enum val) const override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ const ImportHashMap<ComposerPropertyNames::Enum, SInternValue>::iterator entry =
+ inst->m_PropertyValues.find(val);
+ if (entry != inst->m_PropertyValues.end())
+ return entry->second.GetValue();
+ return Empty();
+ }
+
+ // Returns number of valid child instances
+ QT3DSU32 GetNumChildren(TIMPHandle instance) const override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ QT3DSU32 count = 0;
+ for (QT3DSU32 i = 0; i < inst->m_Children.size(); ++i) {
+ Instance *theInstance(GetInstance(inst->m_Children[i]));
+ if (theInstance && theInstance->m_Valid)
+ count++;
+ }
+
+ return count;
+ }
+
+ // Returns valid children in the childBuffer parameter.
+ QT3DSU32 GetChildren(TIMPHandle instance, NVDataRef<InstanceDesc> childBuffer) const override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ QT3DSU32 count = 0;
+ for (QT3DSU32 i = 0; i < inst->m_Children.size(); ++i) {
+ Instance *theInstance(GetInstance(inst->m_Children[i]));
+ if (theInstance && theInstance->m_Valid) {
+ childBuffer[count] = FindInstanceById(inst->m_Children[i]);
+ count++;
+ if (count == childBuffer.size())
+ break;
+ }
+ }
+ return count;
+ }
+
+ void MarkInstanceInvalid(TIMPHandle instance) override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (m_InValidInstances.insert(instance).second) {
+ inst->MarkInvalid();
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)inst->m_Children.size())
+ {
+ Instance *theInstance(GetInstance(inst->m_Children[idx]));
+ if (theInstance)
+ MarkInstanceInvalid(toHdl(theInstance));
+ }
+ std::vector<AnimationId> animationsToErase;
+ for (ImportHashMap<AnimationId, Animation *>::iterator iter = m_Animations.begin(),
+ end = m_Animations.end();
+ iter != end; ++iter) {
+ if (iter->first.m_Instance == instance)
+ animationsToErase.push_back(iter->first);
+ }
+ for (size_t idx = 0, end = animationsToErase.size(); idx < end; ++idx)
+ m_Animations.erase(animationsToErase[idx]);
+ }
+ }
+
+ TIMPHandle CreateInstance(TCharPtr name, ComposerObjectTypes::Enum inType) override
+ {
+ if (IsTrivial(name) == false) {
+ Option<InstanceDesc> exists = FindInstanceById(name);
+ bool hasValue = exists.hasValue();
+ if (hasValue) {
+ QT3DS_ASSERT(false);
+ return exists->m_Handle;
+ }
+ }
+ name = m_StringTable.RegisterStr(name);
+ InstanceDesc newDesc;
+ newDesc.m_Id = name;
+ newDesc.m_Type = inType;
+ Instance *newInst = new Instance(newDesc);
+ m_ValidInstances.insert(toHdl(newInst));
+ m_IdToInstMap.insert(eastl::make_pair(name, newInst));
+ return toHdl(newInst);
+ }
+
+ Instance *CopyInstanceHierarchy(Instance &inSource, ImportHashMap<TCharPtr, TCharPtr> &inIdMap)
+ {
+ wstring uniqueStem(inSource.m_Id);
+ wstring instId(uniqueStem);
+ int index = 1;
+ do {
+ wchar_t buf[16];
+ WStrOps<QT3DSU32>().ToStr(index, toDataRef(buf, 16));
+ ++index;
+ instId.assign(uniqueStem);
+ instId.append(L"_");
+ instId.append(buf);
+ } while (FindInstanceById(RegisterStr(instId.c_str())).hasValue());
+
+ Instance *retval =
+ GetInstance(CreateInstance(RegisterStr(instId.c_str()), inSource.m_Type));
+ inIdMap.insert(eastl::make_pair(RegisterStr(inSource.m_Id), RegisterStr(retval->m_Id)));
+
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)inSource.m_Children.size())
+ {
+ Instance *oldChild = GetInstance(inSource.m_Children[idx]);
+ if (oldChild == NULL) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ Instance *child = CopyInstanceHierarchy(*oldChild, inIdMap);
+ AddChild(toHdl(retval), toHdl(child));
+ }
+ return retval;
+ }
+
+ void CopyInstancePropertiesAndAnimation(Instance &inSource,
+ ImportHashMap<TCharPtr, TCharPtr> &inIdMap)
+ {
+ const ImportHashMap<TCharPtr, TCharPtr>::iterator theNewItemId =
+ inIdMap.find(inSource.m_Id);
+ if (theNewItemId == inIdMap.end()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ Instance *theCopy = GetInstance(theNewItemId->second);
+ if (theCopy == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ for (ImportHashMap<ComposerPropertyNames::Enum, SInternValue>::iterator
+ iter = inSource.m_PropertyValues.begin(),
+ end = inSource.m_PropertyValues.end();
+ iter != end; ++iter) {
+ SInternValue current(iter->second);
+ if (GetValueType(current.GetValue()) == DataModelDataType::StringRef) {
+ const SStringRef &theRef = get<SStringRef>(current.GetValue());
+ const ImportHashMap<TCharPtr, TCharPtr>::iterator theNewId =
+ inIdMap.find(theRef.m_Id);
+ if (theNewId != inIdMap.end())
+ current = SInternValue::ISwearThisHasAlreadyBeenInternalized(
+ SValue(SStringRef(theNewId->second)));
+ }
+ theCopy->m_PropertyValues.insert(eastl::make_pair(iter->first, current));
+ }
+ for (ImportHashMap<AnimationId, Animation *>::iterator iter = m_Animations.begin(),
+ end = m_Animations.end();
+ iter != end; ++iter) {
+ if (iter->first.m_Instance == toHdl(&inSource)) {
+ const Animation *theSrcAnimation = iter->second;
+ DoAddAnimation(theCopy->m_Id, theSrcAnimation->m_PropertyName,
+ theSrcAnimation->m_SubPropertyIndex, theSrcAnimation->m_Type,
+ theSrcAnimation->m_Keyframes);
+ }
+ }
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)inSource.m_Children.size())
+ {
+ Instance *oldChild = GetInstance(inSource.m_Children[idx]);
+ if (oldChild == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ CopyInstancePropertiesAndAnimation(*oldChild, inIdMap);
+ }
+ }
+
+ TIMPHandle CopyInstance(TIMPHandle inSource) override
+ {
+ Instance *inst = GetInstance(inSource);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ // map from old ids to new ids
+ ImportHashMap<TCharPtr, TCharPtr> idMap;
+ // copy the hierarchy first
+ Instance *retval = CopyInstanceHierarchy(*inst, idMap);
+
+ Instance *parent = fromHdl(inst->m_Parent);
+ if (parent != NULL)
+ parent->AddChild(retval, inst);
+
+ // Copy properties and animations
+ CopyInstancePropertiesAndAnimation(*inst, idMap);
+
+ return toHdl(retval);
+ }
+
+ bool SetInstanceProperties(TIMPHandle instance, NVConstDataRef<PropertyValue> inBuffer) override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ inst->SetPropertyValues(inBuffer, m_StringTable);
+ return true;
+ }
+ bool DoSetInstancePropertyValue(TIMPHandle instance, ComposerPropertyNames::Enum pname,
+ const TImportModelValue &val) override
+ {
+ Instance *inst = GetInstance(instance);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ inst->SetPropertyValue(pname, SInternValue(val, m_StringTable));
+ return true;
+ }
+
+ bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
+ TCharPtr val) override
+ {
+ return DoSetInstancePropertyValue(inst, pname, std::make_shared<CDataStr>(val));
+ }
+ bool AddChild(TIMPHandle instance, TIMPHandle childHdl) override
+ {
+ Instance *inst = GetInstance(instance);
+ Instance *child = GetInstance(childHdl);
+ if (inst == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (child == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ // Hmm, two parents both have same child...
+ // not idea.
+ if (child->m_Parent != 0) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ inst->AddChild(child);
+ return true;
+ }
+
+ static inline ImportErrorCodes::Enum FromFileErrorCode(Q3DStudio::FileErrorCodes::Enum val)
+ {
+ switch (val) {
+ case Q3DStudio::FileErrorCodes::SourceNotReadable:
+ return ImportErrorCodes::SourceFileNotReadable;
+ case Q3DStudio::FileErrorCodes::DestNotWriteable:
+ return ImportErrorCodes::ResourceNotWriteable;
+ case Q3DStudio::FileErrorCodes::NoError:
+ return ImportErrorCodes::NoError;
+ }
+ QT3DS_ASSERT(false);
+ return ImportErrorCodes::ResourceNotWriteable;
+ }
+
+ QT3DSU32 GetNumImages() const override { return (QT3DSU32)m_Images.size(); }
+ QT3DSU32 GetImages(NVDataRef<Pair<TCharPtr, TCharPtr>> imgPaths) const override
+ {
+ QT3DSU32 numItems = NVMin((QT3DSU32)imgPaths.size(), (QT3DSU32)m_Images.size());
+ QT3DS_ASSERT(numItems == m_Images.size());
+ QT3DSU32 idx = 0;
+ for (ImportHashMap<TCharPtr, TCharPtr>::const_iterator iter = m_Images.begin(),
+ end = m_Images.end();
+ iter != end && idx < numItems; ++iter, ++idx)
+ imgPaths[idx] = Pair<TCharPtr, TCharPtr>(iter->first, iter->second);
+ return numItems;
+ }
+
+ // Copies the an appropriate location in our import directory
+ // Returns the path of the added image. This may mangle the name slightly
+ // In case of a conflict.
+ CharPtrOrError AddImage(TCharPtr _imgPath) override
+ {
+ Option<TCharPtr> added = FindImageByPath(_imgPath);
+ if (added.hasValue())
+ return *added;
+
+ if (!m_ImageDir.IsDirectory())
+ m_ImageDir.CreateDir(true);
+
+ if (!m_ImageDir.IsDirectory())
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_ImageDir);
+
+ Q3DStudio::CString imgPath = CFilePath::GetAbsolutePath(CString(_imgPath));
+ Q3DStudio::CString srcImgPath =
+ CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, imgPath);
+
+ Q3DStudio::SFileErrorCodeFileNameAndNumBytes copyResult =
+ Q3DStudio::SFileTools::FindAndCopyDestFile(m_ImageDir, imgPath);
+ // Get the actual return value relative do our destination directory
+ Q3DStudio::CString _retval =
+ CFilePath::GetRelativePathFromBase(m_DestDirectory, copyResult.m_DestFilename);
+ // Register the string, so we can hand retval back to clients
+ TCharPtr retval = m_StringTable.RegisterStr(_retval.c_str());
+ m_Images.insert(eastl::make_pair(m_StringTable.RegisterStr(srcImgPath.c_str()), retval));
+
+ if (copyResult.m_Error != Q3DStudio::FileErrorCodes::NoError) {
+ CharPtrOrError errorValue(
+ ImportErrorData(FromFileErrorCode(copyResult.m_Error), RegisterStr(imgPath)));
+ errorValue.m_Value = retval;
+ return errorValue;
+ }
+ return retval;
+ }
+ CharPtrOrError AddOrReplaceImage(TCharPtr _imgPath, Option<TCharPtr> dstPath)
+ {
+ if (dstPath.hasValue()) {
+ if (!m_ImageDir.IsDirectory())
+ m_ImageDir.CreateDir(true);
+ if (!m_ImageDir.IsDirectory())
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_ImageDir);
+ CFilePath fullDestPath =
+ CFilePath::CombineBaseAndRelative(m_DestDirectory, CString(dstPath.getValue()));
+ Q3DStudio::SFileErrorCodeAndNumBytes copyResult = Q3DStudio::SFileTools::Copy(
+ fullDestPath, Q3DStudio::FileOpenFlags(Q3DStudio::FileOpenFlagValues::Truncate
+ | Q3DStudio::FileOpenFlagValues::Open
+ | Q3DStudio::FileOpenFlagValues::Create),
+ CString(_imgPath));
+ // Regardless of if the copy operation succeeds or not, if the destination exists
+ // already
+ // Then we enter it into our dictionary
+ if (fullDestPath.IsFile()) {
+ CFilePath imgPath = CFilePath::GetAbsolutePath(CString(_imgPath));
+ CFilePath srcImgPath =
+ CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, imgPath);
+ m_Images.insert(eastl::make_pair(m_StringTable.RegisterStr(srcImgPath.c_str()),
+ m_StringTable.RegisterStr(dstPath.getValue())));
+ }
+
+ TCharPtr returnPath = dstPath.getValue();
+
+ if (copyResult.m_Error != Q3DStudio::FileErrorCodes::NoError) {
+ QT3DS_ASSERT(false);
+ const wchar_t *extraData = NULL;
+ ImportErrorCodes::Enum error = FromFileErrorCode(copyResult.m_Error);
+ if (error == ImportErrorCodes::ResourceNotWriteable)
+ extraData = dstPath.getValue();
+ else if (error == ImportErrorCodes::SourceFileNotReadable)
+ extraData = _imgPath;
+ CharPtrOrError errorRet(ImportErrorData(error, extraData));
+ errorRet.m_Value = returnPath;
+ return errorRet;
+ }
+ return returnPath;
+ }
+ return AddImage(_imgPath);
+ }
+ Option<TCharPtr> FindImageByPath(TCharPtr _imgPath) const override
+ {
+ Q3DStudio::CString imgPath = CFilePath::GetAbsolutePath(CString(_imgPath));
+ Q3DStudio::CString srcImgPath =
+ CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, imgPath);
+ return FindImageByRelativePath(srcImgPath.c_str());
+ }
+
+ Option<TCharPtr> FindImageByRelativePath(TCharPtr imgPath) const override
+ {
+ ImportHashMap<TCharPtr, TCharPtr>::const_iterator entry = m_Images.find(imgPath);
+ if (entry != m_Images.end())
+ return entry->second;
+ return Empty();
+ }
+
+ QT3DSU32 GetNumMeshes() const override { return (QT3DSU32)m_Meshes.size(); }
+ QT3DSU32 GetMeshes(NVDataRef<Pair<TCharPtr, TCharPtr>> bufferPaths) const override
+ {
+ QT3DSU32 numItems = NVMin((QT3DSU32)m_Meshes.size(), bufferPaths.size());
+ QT3DS_ASSERT(numItems == m_Meshes.size());
+ QT3DSU32 idx = 0;
+ for (ImportHashMap<TCharPtr, MeshEntry>::const_iterator iter = m_Meshes.begin(),
+ end = m_Meshes.end();
+ iter != end && idx < numItems; ++iter, ++idx)
+ bufferPaths[idx] = Pair<TCharPtr, TCharPtr>(iter->first, iter->second.m_FilePath);
+ return numItems;
+ }
+ // Copies the vertex buffer into the appropriate location, renaming if necessary.
+ CharPtrOrError AddMesh(const Mesh &meshBuffer, TCharPtr _name) override
+ {
+ if (IsTrivial(_name)) {
+ QT3DS_ASSERT(false);
+ return L"";
+ }
+ Q3DStudio::CString name = CFilePath::MakeSafeFileStem(_name);
+
+ Option<TCharPtr> meshOpt = FindMeshReferencePathByName(name.c_str());
+ if (meshOpt.hasValue())
+ return *meshOpt;
+
+ if (!m_MeshDir.IsDirectory())
+ m_MeshDir.CreateDir(true);
+ if (!m_MeshDir.IsDirectory())
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_MeshDir);
+
+ Q3DStudio::TFilePtr handf =
+ Q3DStudio::SFileTools::FindUniqueDestFile(m_MeshDir, name, L"mesh");
+ CUICFileToolsSeekableMeshBufIOStream output(handf);
+ MallocAllocator alloc;
+ QT3DSU32 meshId = meshBuffer.SaveMulti(alloc, output);
+ CFilePath _retval = CFilePath::GetRelativePathFromBase(m_DestDirectory, handf->m_Path);
+ MeshEntry newEntry(m_StringTable.RegisterStr(name.c_str()), _retval, meshId, m_StringTable);
+ m_Meshes.insert(eastl::make_pair(newEntry.m_SourceId, newEntry));
+ return newEntry.m_ReferencePath;
+ }
+
+ CharPtrOrError AddOrReplaceMesh(const Mesh &meshBuffer, TCharPtr name, Option<TCharPtr> srcMesh)
+ {
+ using namespace Q3DStudio;
+ if (srcMesh.hasValue()) {
+ if (!m_MeshDir.IsDirectory())
+ m_MeshDir.CreateDir(true);
+ if (!m_MeshDir.IsDirectory())
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_MeshDir);
+
+ CFilePath meshPath =
+ CFilePath::CombineBaseAndRelative(m_DestDirectory, CString(srcMesh.getValue()));
+
+ meshPath = meshPath.GetPathWithoutIdentifier();
+ CUICFileToolsSeekableMeshBufIOStream output(SFile::Wrap(
+ SFile::OpenForWrite(
+ meshPath, FileOpenFlags(FileOpenFlagValues::Open | FileOpenFlagValues::Create)),
+ meshPath));
+ if (output.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return ImportErrorData(ImportErrorCodes::ResourceNotWriteable, srcMesh.getValue());
+ }
+ MallocAllocator allocator;
+ QT3DSU32 meshId = meshBuffer.SaveMulti(allocator, output);
+
+ CFilePath relativePath = CFilePath::GetRelativePathFromBase(m_DestDirectory, meshPath);
+
+ MeshEntry newEntry(m_StringTable.RegisterStr(name), relativePath, meshId,
+ m_StringTable);
+ m_Meshes.insert(eastl::make_pair(newEntry.m_SourceId, newEntry));
+ return newEntry.m_ReferencePath;
+ }
+ return AddMesh(meshBuffer, name);
+ }
+
+ bool HasMesh(TCharPtr meshName) const override
+ {
+ return m_Meshes.find(meshName) != m_Meshes.end();
+ }
+
+ Option<TCharPtr> FindMeshReferencePathByName(TCharPtr meshName) const override
+ {
+ ImportHashMap<TCharPtr, MeshEntry>::const_iterator entry = m_Meshes.find(meshName);
+ if (entry != m_Meshes.end()) {
+ QT3DS_ASSERT(!IsTrivial(entry->second.m_ReferencePath));
+ return entry->second.m_ReferencePath;
+ }
+ return Empty();
+ }
+
+ Option<TCharPtr> FindMeshFilePathByName(TCharPtr meshName) const override
+ {
+ ImportHashMap<TCharPtr, MeshEntry>::const_iterator entry = m_Meshes.find(meshName);
+ if (entry != m_Meshes.end()) {
+ QT3DS_ASSERT(!IsTrivial(entry->second.m_FilePath));
+ return entry->second.m_FilePath;
+ }
+ return Empty();
+ }
+
+ QT3DSU32 GetNumPathBuffers() const override { return (QT3DSU32)m_PathBuffers.size(); }
+ QT3DSU32 GetPathBuffers(NVDataRef<Pair<TCharPtr, TCharPtr>> pathBufferPaths) const override
+ {
+ QT3DSU32 numItems = NVMin((QT3DSU32)pathBufferPaths.size(), (QT3DSU32)m_PathBuffers.size());
+ QT3DS_ASSERT(numItems == m_PathBuffers.size());
+ QT3DSU32 idx = 0;
+ for (ImportHashMap<TCharPtr, TCharPtr>::const_iterator iter = m_PathBuffers.begin(),
+ end = m_PathBuffers.end();
+ iter != end && idx < numItems; ++iter, ++idx)
+ pathBufferPaths[idx] = Pair<TCharPtr, TCharPtr>(iter->first, iter->second);
+ return numItems;
+ }
+
+ // Copies the vertex buffer into the appropriate location, renaming if necessary.
+ CharPtrOrError AddPathBuffer(const SPathBuffer &pathBuffer, TCharPtr _name) override
+ {
+ if (IsTrivial(_name)) {
+ QT3DS_ASSERT(false);
+ return L"";
+ }
+ Q3DStudio::CString name = CFilePath::MakeSafeFileStem(_name);
+
+ Option<TCharPtr> pathBufferOpt = FindPathBufferByRelativePath(name.c_str());
+ if (pathBufferOpt.hasValue())
+ return *pathBufferOpt;
+
+ if (!m_PathBufferDir.IsDirectory())
+ m_PathBufferDir.CreateDir(true);
+ if (!m_PathBufferDir.IsDirectory())
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_PathBufferDir);
+
+ Q3DStudio::TFilePtr handf =
+ Q3DStudio::SFileTools::FindUniqueDestFile(m_PathBufferDir, name, L"path");
+ CUICFileToolsSeekableMeshBufIOStream output(handf);
+ MallocAllocator alloc;
+ pathBuffer.Save(output);
+ CFilePath _retval = CFilePath::GetRelativePathFromBase(m_DestDirectory, handf->m_Path);
+ const wchar_t *return_Value = m_StringTable.RegisterStr(_retval.c_str());
+ m_PathBuffers.insert(
+ eastl::make_pair(m_StringTable.RegisterStr(name.c_str()), return_Value));
+ return return_Value;
+ }
+
+ CharPtrOrError AddOrReplacePathBuffer(const SPathBuffer &pathBuffer, TCharPtr name,
+ Option<TCharPtr> srcPathBuffer)
+ {
+ using namespace Q3DStudio;
+ if (srcPathBuffer.hasValue()) {
+ if (!m_PathBufferDir.IsDirectory())
+ m_PathBufferDir.CreateDir(true);
+ if (!m_PathBufferDir.IsDirectory())
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_PathBufferDir);
+
+ CFilePath pathBufferPath = CFilePath::CombineBaseAndRelative(
+ m_DestDirectory, CString(srcPathBuffer.getValue()));
+
+ pathBufferPath = pathBufferPath.GetPathWithoutIdentifier();
+ CUICFileToolsSeekableMeshBufIOStream output(SFile::Wrap(
+ SFile::OpenForWrite(pathBufferPath, FileOpenFlags(FileOpenFlagValues::Open
+ | FileOpenFlagValues::Create)),
+ pathBufferPath));
+ if (output.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return ImportErrorData(ImportErrorCodes::ResourceNotWriteable,
+ srcPathBuffer.getValue());
+ }
+ MallocAllocator allocator;
+ pathBuffer.Save(output);
+
+ CFilePath relativePath =
+ CFilePath::GetRelativePathFromBase(m_DestDirectory, pathBufferPath);
+
+ const wchar_t *relPath = m_StringTable.RegisterStr(relativePath.c_str());
+ m_PathBuffers.insert(eastl::make_pair(m_StringTable.RegisterStr(name), relPath));
+ return relPath;
+ }
+ return AddPathBuffer(pathBuffer, name);
+ }
+
+ Option<TCharPtr> FindPathBufferByPath(TCharPtr _pathBufferPath) const override
+ {
+ Q3DStudio::CString pathBufferPath = CFilePath::GetAbsolutePath(CString(_pathBufferPath));
+ Q3DStudio::CString srcpathBufferPath =
+ CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, pathBufferPath);
+ return FindPathBufferByRelativePath(srcpathBufferPath.c_str());
+ }
+
+ Option<TCharPtr> FindPathBufferByRelativePath(TCharPtr pathBufferPath) const override
+ {
+ ImportHashMap<TCharPtr, TCharPtr>::const_iterator entry =
+ m_PathBuffers.find(pathBufferPath);
+ if (entry != m_PathBuffers.end())
+ return entry->second;
+ return Empty();
+ }
+
+ QT3DSU32 GetNumAnimations() const override { return (QT3DSU32)m_Animations.size(); }
+ QT3DSU32 GetAnimations(NVDataRef<Animation> outBuffers) const override
+ {
+ QT3DSU32 numItems = NVMin((QT3DSU32)m_Animations.size(), (QT3DSU32)outBuffers.size());
+ QT3DS_ASSERT(numItems == m_Animations.size());
+ QT3DSU32 idx = 0;
+ for (ImportHashMap<AnimationId, Animation *>::const_iterator iter = m_Animations.begin(),
+ end = m_Animations.end();
+ iter != end && idx < numItems; ++iter, ++idx)
+ outBuffers[idx] = *iter->second;
+ return numItems;
+ }
+
+ // Data is copied into this object, you can release the anim buffer data after this
+ void DoAddAnimation(TCharPtr instance, TCharPtr propName, QT3DSU32 subPropIndex,
+ EAnimationType bufType, NVConstDataRef<QT3DSF32> values) override
+ {
+ propName = m_StringTable.RegisterStr(propName);
+ Option<Animation> buffer(FindAnimation(instance, propName, subPropIndex));
+ if (buffer.hasValue()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ // Find Instance by id checks for the validity of the instance, so we should be OK here.
+ Option<InstanceDesc> instOpt = FindInstanceById(instance);
+ if (instOpt.hasValue() == false)
+ return;
+
+ m_Animations.insert(eastl::make_pair(
+ AnimationId(instOpt->m_Handle, propName, subPropIndex),
+ CreateAnimation(instOpt->m_Id, propName, subPropIndex, bufType, values)));
+ }
+
+ Option<Animation> FindAnimation(TCharPtr instId, TCharPtr propName,
+ QT3DSU32 subPropIndex) const override
+ {
+ Option<InstanceDesc> instance(FindInstanceById(instId));
+ if (instance.hasValue() == false)
+ return Empty();
+ AnimationId id(instance->m_Handle, propName, subPropIndex);
+ ImportHashMap<AnimationId, Animation *>::const_iterator entry(m_Animations.find(id));
+ if (entry != m_Animations.end())
+ return *entry->second;
+ return Empty();
+ }
+
+ template <typename TDataType, typename TDiffOp>
+ void AddAddedItems(AddRemoveImpl<TDataType> &dtype, TDiffOp op) const
+ {
+ dtype.m_Added.resize(op.NumItems(*this));
+ op.GetItems(*this, dtype.m_Added);
+ }
+
+ void FinalizeReport() const
+ {
+ // Now ensure the links are ordered appropriately so a single pass through each vector
+ // is enough.
+ std::stable_sort(m_ImportReport.m_Links.m_Existing.begin(),
+ m_ImportReport.m_Links.m_Existing.end());
+ std::stable_sort(m_ImportReport.m_Links.m_Added.begin(),
+ m_ImportReport.m_Links.m_Added.end());
+ std::stable_sort(m_ImportReport.m_Links.m_Removed.begin(),
+ m_ImportReport.m_Links.m_Removed.end());
+ }
+
+ // Add instances in depth first order in order to reduce the number of parent/child reording
+ // issues.
+ ImportReport CompileReport() const override
+ {
+ m_ImportReport.clear();
+ AddAddedItems(m_ImportReport.m_Instances, InstanceDiffOp());
+ AddAddedItems(m_ImportReport.m_Images, ImageDiffOp());
+ AddAddedItems(m_ImportReport.m_Meshes, MeshDiffOp());
+ AddAddedItems(m_ImportReport.m_Animations, AnimationDiffOp());
+
+ ImportArray<InstanceDesc> childList;
+ QT3DSIMP_FOREACH(idx, m_ImportReport.m_Instances.m_Added.size())
+ {
+ const InstanceDesc &inst(m_ImportReport.m_Instances.m_Added[idx]);
+ childList.resize(GetNumChildren(inst.m_Handle));
+
+ GetChildren(inst.m_Handle, childList);
+ QT3DSIMP_FOREACH(child, childList.size())
+ {
+ TCharPtr sibling = child + 1 < childList.size() ? childList[child + 1].m_Id : L"";
+ m_ImportReport.m_Links.m_Added.push_back(
+ ParentChildLink(inst.m_Id, childList[child].m_Id, sibling));
+ }
+ }
+ FinalizeReport();
+ return m_ImportReport;
+ }
+
+ static QT3DSU32 FindHighestRevisionInDocument(IDOMReader &inReader)
+ {
+ QT3DSU32 retval = 0;
+ IDOMReader::Scope readerScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(L"Project"); success;
+ success = inReader.MoveToNextSibling(L"Project")) {
+ QT3DSU32 tempId;
+ if (inReader.Att("Revision", tempId))
+ retval = NVMax(retval, tempId);
+ }
+ return retval;
+ }
+
+ void Serialize(IDOMWriter &writer, ComposerObjectTypes::Enum inType, Animation &inAnimation,
+ MemoryBuffer<RawAllocator> &inTempBuf)
+ {
+ Instance *theInstance = GetInstance(inAnimation.m_InstanceId);
+ if (theInstance == NULL || theInstance->m_Valid == false)
+ return;
+ IDOMWriter::Scope __animScope(writer, L"AnimationTrack");
+ TCharStr thePropName(inAnimation.m_PropertyName);
+ SImportComposerTypes theTypes;
+ SImportAsset &theAsset(theTypes.GetImportAssetForType(inType));
+ DataModelDataType::Value theType(theAsset.GetPropertyDataType(thePropName.wide_str()));
+ std::tuple<bool, size_t> animAndArity = GetDatatypeAnimatableAndArity(theType);
+ if (std::get<0>(animAndArity) == false) {
+ QT3DS_ASSERT(false);
+ return;
+ };
+ if (std::get<1>(animAndArity) > 1) {
+ thePropName.append(L".");
+ switch (inAnimation.m_SubPropertyIndex) {
+ case 0:
+ thePropName.append(L"x");
+ break;
+ case 1:
+ thePropName.append(L"y");
+ break;
+ case 2:
+ thePropName.append(L"z");
+ break;
+ case 3:
+ thePropName.append(L"w");
+ break;
+ }
+ }
+
+ writer.Att(L"property", thePropName);
+ writer.Att(L"type", inAnimation.m_Type);
+ inTempBuf.clear();
+ WCharTWriter bufWriter(inTempBuf);
+ bufWriter.Write(
+ toConstDataRef(inAnimation.m_Keyframes.begin(), inAnimation.m_Keyframes.size()), 20,
+ writer.GetTabs() + 1);
+ if (inTempBuf.size()) {
+ char buffer[] = { 0, 0 };
+ inTempBuf.write(buffer, 2);
+ writer.Value((const wchar_t *)inTempBuf.begin());
+ }
+ }
+ void SerializeAnimation(IDOMReader &reader, const wchar_t *inInstanceId,
+ MemoryBuffer<RawAllocator> &inTempBuf,
+ MemoryBuffer<RawAllocator> &inAttributeBuffer)
+ {
+ Animation theAnimation;
+ theAnimation.m_InstanceId = inInstanceId;
+ TCharStr theName;
+ reader.Att(L"property", theName);
+ eastl_size_t theDotPos(theName.find(L"."));
+ if (theDotPos != wstring::npos) {
+ wchar_t theExtension(theName.at(theDotPos + 1));
+ theName = theName.substr(0, theDotPos);
+ switch (theExtension) {
+ default:
+ QT3DS_ASSERT(false);
+ // fallthrough intentional
+ case 'x':
+ case 'r':
+ theAnimation.m_SubPropertyIndex = 0;
+ break;
+ case 'y':
+ case 'g':
+ theAnimation.m_SubPropertyIndex = 1;
+ break;
+ case 'z':
+ case 'b':
+ theAnimation.m_SubPropertyIndex = 2;
+ break;
+ case 'w':
+ case 'a':
+ theAnimation.m_SubPropertyIndex = 3;
+ break;
+ }
+ }
+ theAnimation.m_PropertyName = m_StringTable.RegisterStr(theName.wide_str());
+ reader.Att(L"type", theAnimation.m_Type);
+ inAttributeBuffer.clear();
+ const char8_t *theValue;
+ reader.Value(theValue);
+ inAttributeBuffer.write(theValue, (QT3DSU32)strlen(theValue) + 1);
+ inAttributeBuffer.write((QT3DSU16)0);
+ WCharTReader theReader((char8_t *)inAttributeBuffer.begin(), inTempBuf, m_StringTable);
+ NVConstDataRef<float> theData;
+ theReader.ReadBuffer(theData);
+ Animation *newAnim =
+ CreateAnimation(theAnimation.m_InstanceId, theAnimation.m_PropertyName,
+ theAnimation.m_SubPropertyIndex, theAnimation.m_Type, theData);
+ m_Animations.insert(eastl::make_pair(
+ AnimationId(toHdl(GetInstance(theAnimation.m_InstanceId)), theAnimation.m_PropertyName,
+ theAnimation.m_SubPropertyIndex),
+ newAnim));
+ }
+ struct PropertyNameSorter
+ {
+ bool operator()(ComposerPropertyNames::Enum lhs, ComposerPropertyNames::Enum rhs) const
+ {
+ if (lhs == rhs)
+ return false;
+ if (lhs == ComposerPropertyNames::name)
+ return true;
+ if (rhs == ComposerPropertyNames::name)
+ return false;
+ return wcscmp(ComposerPropertyNames::Convert(lhs), ComposerPropertyNames::Convert(rhs))
+ < 0;
+ }
+ };
+
+ void Serialize(IDOMWriter &writer, Instance &inInstance, MemoryBuffer<RawAllocator> &inTempBuf)
+ {
+ if (inInstance.m_Valid == false)
+ return;
+ IDOMWriter::Scope __instanceScope(writer, ComposerObjectTypes::Convert(inInstance.m_Type));
+ writer.Att(L"id", inInstance.m_Id);
+ // Write properties, then write animations
+ ImportArray<ComposerPropertyNames::Enum> theNames;
+ for (ImportHashMap<ComposerPropertyNames::Enum, SInternValue>::iterator
+ iter = inInstance.m_PropertyValues.begin(),
+ end = inInstance.m_PropertyValues.end();
+ iter != end; ++iter) {
+ theNames.push_back(iter->first);
+ }
+ std::sort(theNames.begin(), theNames.end(), PropertyNameSorter());
+
+ for (QT3DSU32 nameIdx = 0, nameEnd = (QT3DSU32)theNames.size(); nameIdx < nameEnd; ++nameIdx) {
+ ImportHashMap<ComposerPropertyNames::Enum, SInternValue>::const_iterator iter(
+ inInstance.m_PropertyValues.find(theNames[nameIdx]));
+ inTempBuf.clear();
+ WCharTWriter bufWriter(inTempBuf);
+ WStrOps<SValue>().ToBuf(iter->second.GetValue(), bufWriter);
+ if (inTempBuf.size()) {
+ inTempBuf.writeZeros(sizeof(wchar_t));
+ writer.Att(ComposerPropertyNames::Convert(iter->first),
+ (const wchar_t *)inTempBuf.begin());
+ }
+ }
+ for (ImportHashMap<AnimationId, Animation *>::const_iterator iter = m_Animations.begin(),
+ end = m_Animations.end();
+ iter != end; ++iter) {
+ if (iter->first.m_Instance == toHdl(&inInstance))
+ Serialize(writer, inInstance.m_Type, *iter->second, inTempBuf);
+ }
+ for (QT3DSU32 childIdx = 0, childEnd = (QT3DSU32)inInstance.m_Children.size();
+ childIdx < childEnd; ++childIdx) {
+ Instance *childInstance = GetInstance(inInstance.m_Children[childIdx]);
+ if (childInstance)
+ Serialize(writer, *childInstance, inTempBuf);
+ }
+ }
+ void Serialize(IDOMReader &reader, Instance &inInstance, MemoryBuffer<RawAllocator> &inTempBuf,
+ MemoryBuffer<RawAllocator> &inAttributeBuffer)
+ {
+ inInstance.m_Type = ComposerObjectTypes::Convert(reader.GetElementName());
+ reader.Att(L"id", inInstance.m_Id);
+ SImportComposerTypes theTypes;
+ SImportAsset &theAsset(theTypes.GetImportAssetForType(inInstance.m_Type));
+ m_ValidInstances.insert(inInstance.m_Handle);
+ m_IdToInstMap.insert(eastl::make_pair(inInstance.m_Id, &inInstance));
+ for (eastl::pair<const char8_t *, const char8_t *> att = reader.GetNarrowFirstAttribute();
+ !IsTrivial(att.first); att = reader.GetNarrowNextAttribute()) {
+ if (AreEqual("id", att.first))
+ continue;
+ DataModelDataType::Value thePropertyType = theAsset.GetPropertyDataType(att.first);
+ if (thePropertyType != DataModelDataType::None) {
+ if (thePropertyType == DataModelDataType::Long4)
+ thePropertyType = DataModelDataType::StringRef;
+ inAttributeBuffer.clear();
+ inAttributeBuffer.write(att.second, (QT3DSU32)strlen(att.second) + 1);
+ inAttributeBuffer.write((QT3DSU16)0);
+ WCharTReader theReader((char8_t *)inAttributeBuffer.begin(), inTempBuf,
+ m_StringTable);
+ SValue theValue = WStrOps<SValue>().BufTo(thePropertyType, theReader);
+ inInstance.m_PropertyValues.insert(
+ eastl::make_pair(ComposerPropertyNames::Convert(att.first),
+ SInternValue(theValue, m_StringTable)));
+ }
+ }
+ {
+ IDOMReader::Scope animScope(reader);
+ for (bool success = reader.MoveToFirstChild(); success;
+ success = reader.MoveToNextSibling()) {
+ if (AreEqual(reader.GetElementName(), L"AnimationTrack")) {
+ SerializeAnimation(reader, inInstance.m_Id, inTempBuf, inAttributeBuffer);
+ } else {
+ Instance *newInstance = new Instance();
+ Serialize(reader, *newInstance, inTempBuf, inAttributeBuffer);
+ inInstance.AddChild(newInstance);
+ }
+ }
+ }
+ }
+
+ void Serialize(IDOMWriter &inWriter, const wchar_t *inElemName, TStrToStrMap &inHashMap) const
+ {
+ for (TStrToStrMap::iterator iter = inHashMap.begin(), end = inHashMap.end(); iter != end;
+ ++iter) {
+ IDOMWriter::Scope __elemScope(inWriter, inElemName);
+ inWriter.ChildValue(L"Source", iter->first);
+ inWriter.ChildValue(L"Dest", iter->second);
+ }
+ }
+
+ void Serialize(IDOMReader &inReader, const wchar_t *inElemName, TStrToStrMap &inHashMap)
+ {
+ IDOMReader::Scope itemScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(inElemName); success;
+ success = inReader.MoveToNextSibling(inElemName)) {
+ const char8_t *source, *dest;
+ inReader.ChildValue("Source", source);
+ inReader.ChildValue("Dest", dest);
+ inHashMap.insert(
+ eastl::make_pair(m_StringTable.GetWideStr(source), m_StringTable.GetWideStr(dest)));
+ }
+ }
+
+ void Serialize(IDOMWriter &inWriter, const wchar_t *inElemName, TPathToMeshMap &inHashMap) const
+ {
+ for (TPathToMeshMap::iterator iter = inHashMap.begin(), end = inHashMap.end(); iter != end;
+ ++iter) {
+ IDOMWriter::Scope __elemScope(inWriter, inElemName);
+ inWriter.ChildValue(L"Source", iter->first);
+ inWriter.ChildValue(L"Dest", iter->second.m_FilePath);
+ }
+ }
+
+ void Serialize(IDOMReader &inReader, const wchar_t *inElemName, TPathToMeshMap &inHashMap)
+ {
+ IDOMReader::Scope itemScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(inElemName); success;
+ success = inReader.MoveToNextSibling(inElemName)) {
+ const char8_t *source, *dest;
+ inReader.ChildValue("Source", source);
+ inReader.ChildValue("Dest", dest);
+ MeshEntry theEntry(m_StringTable.GetWideStr(source), m_StringTable.GetWideStr(dest),
+ m_StringTable);
+ inHashMap.insert(eastl::make_pair(theEntry.m_SourceId, theEntry));
+ }
+ }
+
+ QT3DSU32 Save(TCharPtr fname) const override
+ {
+ using namespace Q3DStudio;
+ QT3DSU32 theRevisionId = 1;
+ CFilePath fullPath = CFilePath::CombineBaseAndRelative(m_DestDirectory, CString(fname));
+
+ std::shared_ptr<IDOMFactory> factory(IDOMFactory::CreateDOMFactory(m_StringTablePtr));
+ std::shared_ptr<IDOMWriter> theWriter;
+ SDOMElement *theTopElement = NULL;
+ bool exists = fullPath.Exists();
+
+ {
+ if (exists) {
+ CFileSeekableIOStream stream(fullPath, FileReadFlags());
+
+ // OK, ensure we can open this file in append mode.
+ // This is kind of tricky because we need to write the data to the file
+ // after we read it.
+ if (stream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ stream.SetPosition(0, SeekPosition::Begin);
+
+ theTopElement = CDOMSerializer::Read(*factory, stream);
+
+ if (theTopElement == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>>
+ theDomAccess(
+ IDOMWriter::CreateDOMWriter(factory, *theTopElement, m_StringTablePtr));
+ theWriter = theDomAccess.first;
+ theRevisionId = FindHighestRevisionInDocument(*theDomAccess.second) + 1;
+ } else {
+ theTopElement = factory->NextElement(L"UIP");
+ theWriter =
+ IDOMWriter::CreateDOMWriter(factory, *theTopElement, m_StringTablePtr).first;
+ // Should be GetUIP file version
+ theWriter->Att(L"Version", Import::GetImportFileVersion());
+ }
+
+ QT3DS_ASSERT(theTopElement);
+ QT3DS_ASSERT(theWriter.get());
+
+ IDOMWriter &writer(*theWriter);
+
+ IDOMWriter::Scope __docScope(writer, L"Project");
+ writer.Att(L"Revision", theRevisionId);
+
+ MemoryBuffer<RawAllocator> tempBuf;
+ ImportArray<Instance *> rootList;
+ for (ImportHashMap<TCharPtr, Instance *>::const_iterator iter = m_IdToInstMap.begin(),
+ end = m_IdToInstMap.end();
+ iter != end; ++iter) {
+ if (iter->second->m_Parent == 0)
+ rootList.push_back(iter->second);
+ }
+ {
+ IDOMWriter::Scope __graphScope(writer, L"Graph");
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)rootList.size(); idx < end; ++idx)
+ const_cast<ImportImpl &>(*this).Serialize(writer, *rootList[idx], tempBuf);
+ }
+ {
+ IDOMWriter::Scope __importScope(writer, L"Import");
+ CFilePath theDirectory(fullPath.GetDirectory());
+ CFilePath theSrcFile = m_SrcFile;
+ if (theSrcFile.IsAbsolute())
+ theSrcFile = CFilePath::GetRelativePathFromBase(theDirectory, m_SrcFile);
+
+ writer.Att(L"SrcFile", theSrcFile.c_str());
+ writer.Att(L"ImageDir", L"Images");
+ writer.Att(L"MeshDir", L"Meshes");
+ Serialize(writer, L"Image", const_cast<TStrToStrMap &>(m_Images));
+ Serialize(writer, L"Mesh", const_cast<TPathToMeshMap &>(m_Meshes));
+ }
+ }
+ {
+ CFileSeekableIOStream stream(fullPath, FileWriteFlags());
+ stream.SetPosition(0, SeekPosition::Begin);
+ CDOMSerializer::WriteXMLHeader(stream);
+ CDOMSerializer::Write(*theTopElement, stream);
+ }
+
+ return theRevisionId;
+ }
+
+ bool Load(const Q3DStudio::CString &fname, QT3DSU32 inDocumentId)
+ {
+ using namespace Q3DStudio;
+ std::shared_ptr<IDOMFactory> factory(IDOMFactory::CreateDOMFactory(m_StringTablePtr));
+ SDOMElement *topElement = NULL;
+ {
+ CUICFileToolsSeekableMeshBufIOStream stream(
+ SFile::Wrap(SFile::OpenForRead(fname), fname));
+ if (stream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ topElement = CDOMSerializer::Read(*factory, stream);
+ }
+
+ if (topElement == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ std::shared_ptr<IDOMReader> readerPtr(
+ IDOMReader::CreateDOMReader(*topElement, m_StringTablePtr));
+ IDOMReader &reader(*readerPtr);
+
+ QT3DSU32 fileVersion = (QT3DSU32)-1;
+ reader.Att("Version", fileVersion);
+
+ if (inDocumentId == 0)
+ inDocumentId = FindHighestRevisionInDocument(reader);
+
+ bool success = false;
+ for (success = reader.MoveToFirstChild(L"Project"); success;
+ success = reader.MoveToNextSibling(L"Project")) {
+ QT3DSU32 temp;
+ if (reader.Att("Revision", temp) && temp == inDocumentId)
+ break;
+ }
+ if (success == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ const wchar_t *srcFile, *imagesDir, *meshDir;
+
+ if (fileVersion > Import::GetImportFileVersion()) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ MemoryBuffer<RawAllocator> attBuf;
+ MemoryBuffer<RawAllocator> tempBuf;
+ {
+ IDOMReader::Scope __graphScope(reader);
+ if (reader.MoveToFirstChild(L"Graph")) {
+
+ for (bool success = reader.MoveToFirstChild(); success;
+ success = reader.MoveToNextSibling()) {
+ Instance *newInstance = new Instance();
+ Serialize(reader, *newInstance, tempBuf, attBuf);
+ }
+ }
+ }
+ {
+ IDOMReader::Scope __importScope(reader);
+ if (reader.MoveToFirstChild(L"Import")) {
+ reader.Att(L"SrcFile", srcFile);
+ reader.Att(L"ImageDir", imagesDir);
+ reader.Att(L"MeshDir", meshDir);
+ // We ignore, however, srcpath.
+ // because it may be different.
+ m_SrcFile = CString(srcFile);
+ m_SrcDirectory = m_SrcFile.GetDirectory();
+ m_FullSrcDirectory =
+ CFilePath::CombineBaseAndRelative(m_DestDirectory, m_SrcDirectory);
+ m_ImageDir = CFilePath::CombineBaseAndRelative(m_DestDirectory, CString(imagesDir));
+ m_MeshDir = CFilePath::CombineBaseAndRelative(m_DestDirectory, CString(meshDir));
+ Serialize(reader, L"Image", m_Images);
+ Serialize(reader, L"Mesh", m_Meshes);
+ }
+ }
+ return true;
+ }
+};
+
+class RefreshImpl : public Import
+{
+ mutable ImportReportImpl m_ImportReport;
+ ImportImpl m_Import;
+ Import &m_Source;
+ mutable MemoryBuffer<RawAllocator> m_TempBuffer;
+
+public:
+ RefreshImpl(ImportImpl &src, const Q3DStudio::CString &srcDirectory)
+ : m_Import(src.m_StringTablePtr, srcDirectory, src.m_DestDirectory, src.m_ImageDir.c_str(),
+ src.m_MeshDir.c_str())
+ , m_Source(src)
+ {
+ }
+ virtual ~RefreshImpl() { m_Source.Release(); }
+
+ // Returns the import interface you should use to import again from the new source.
+ Import &GetImportInterface() { return *this; }
+
+ // Implement the import interface...
+
+ TCharPtr RegisterStr(TCharPtr str) override { return m_Import.RegisterStr(str); }
+ TCharPtr GetSrcFile() const override { return m_Import.GetSrcFile(); }
+ TCharPtr GetDestDir() const override { return m_Import.GetDestDir(); }
+ TCharPtr GetImageDir() const override { return m_Import.GetImageDir(); }
+ TCharPtr GetMeshDir() const override { return m_Import.GetMeshDir(); }
+ TCharPtr GetPathBufferDir() const override { return m_Import.GetPathBufferDir(); }
+ QT3DSU32 Save(TCharPtr fname) const override { return m_Import.Save(fname); }
+
+ // Add a mapping from an named id to a handle
+ Option<InstanceDesc> GetInstanceByHandle(TIMPHandle inst) const override
+ {
+ return m_Import.GetInstanceByHandle(inst);
+ }
+ Option<InstanceDesc> FindInstanceById(TCharPtr inst) const override
+ {
+ return m_Import.FindInstanceById(inst);
+ }
+ Option<InstanceDesc> FindAnyInstanceById(TCharPtr inst) const override
+ {
+ return m_Import.FindAnyInstanceById(inst);
+ }
+ QT3DSU32 GetNumInstances() const override { return m_Import.GetNumInstances(); }
+ QT3DSU32 GetInstances(NVDataRef<InstanceDesc> outDescs) const override
+ {
+ return m_Import.GetInstances(outDescs);
+ }
+ QT3DSU32 GetNumProperties(TIMPHandle instance) const override
+ {
+ return m_Import.GetNumProperties(instance);
+ }
+ QT3DSU32 GetProperties(TIMPHandle inst, NVDataRef<PropertyValue> outBuffer) const override
+ {
+ return m_Import.GetProperties(inst, outBuffer);
+ }
+ Option<SValue> GetInstancePropertyValue(TIMPHandle inst,
+ ComposerPropertyNames::Enum val) const override
+ {
+ return m_Import.GetInstancePropertyValue(inst, val);
+ }
+ QT3DSU32 GetNumChildren(TIMPHandle instance) const override
+ {
+ return m_Import.GetNumChildren(instance);
+ }
+ QT3DSU32 GetChildren(TIMPHandle instance, NVDataRef<InstanceDesc> childBuffer) const override
+ {
+ return m_Import.GetChildren(instance, childBuffer);
+ }
+
+ // Carry user id's across.
+ TIMPHandle CreateInstance(TCharPtr name, ComposerObjectTypes::Enum inType) override
+ {
+ TIMPHandle retval = m_Import.CreateInstance(name, inType);
+ Option<InstanceDesc> srcInst = m_Source.FindInstanceById(name);
+ if (srcInst.hasValue()) {
+ if (srcInst->m_Type != inType) {
+ Instance *inst = fromHdl(retval);
+ m_ImportReport.m_TypeChanges.push_back(
+ Pair<InstanceDesc, ComposerObjectTypes::Enum>(*inst, srcInst->m_Type));
+ }
+ }
+ return retval;
+ }
+
+ TIMPHandle CopyInstance(TIMPHandle inSource) override { return m_Import.CopyInstance(inSource); }
+ bool SetInstanceProperties(TIMPHandle inst, NVConstDataRef<PropertyValue> inBuffer) override
+ {
+ return m_Import.SetInstanceProperties(inst, inBuffer);
+ }
+ bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
+ const TImportModelValue &val) override
+ {
+ return m_Import.DoSetInstancePropertyValue(inst, pname, val);
+ }
+ bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
+ TCharPtr val) override
+ {
+ return m_Import.DoSetInstancePropertyValue(inst, pname, val);
+ }
+ bool AddChild(TIMPHandle inst, TIMPHandle child) override
+ {
+ return m_Import.AddChild(inst, child);
+ }
+ void MarkInstanceInvalid(TIMPHandle inst) override { m_Import.MarkInstanceInvalid(inst); }
+
+ QT3DSU32 GetNumImages() const override { return m_Import.GetNumImages(); }
+ QT3DSU32 GetImages(NVDataRef<Pair<TCharPtr, TCharPtr>> imgPaths) const override
+ {
+ return m_Import.GetImages(imgPaths);
+ }
+ // Copies the an appropriate location in our import directory
+ // Returns the path of the added image. This may mangle the name slightly
+ // In case of a conflict.
+ CharPtrOrError AddImage(TCharPtr _imgPath) override
+ {
+ Option<TCharPtr> added = m_Source.FindImageByPath(_imgPath);
+ return m_Import.AddOrReplaceImage(_imgPath, added);
+ }
+ Option<TCharPtr> FindImageByPath(TCharPtr imgPath) const override
+ {
+ return m_Import.FindImageByPath(imgPath);
+ }
+
+ Option<TCharPtr> FindImageByRelativePath(TCharPtr imgPath) const override
+ {
+ return m_Import.FindImageByRelativePath(imgPath);
+ }
+
+ QT3DSU32 GetNumMeshes() const override { return m_Import.GetNumMeshes(); }
+ QT3DSU32 GetMeshes(NVDataRef<Pair<TCharPtr, TCharPtr>> bufferPaths) const override
+ {
+ return m_Import.GetMeshes(bufferPaths);
+ }
+ // Copies the vertex buffer into the appropriate location, renaming if necessary.
+ // Mesh name is used to write out a reasonable buffer *and* on refresh to know
+ // if a buffer is changed/updated or not
+ CharPtrOrError AddMesh(const Mesh &meshBuffer, TCharPtr meshName) override
+ {
+ Q3DStudio::CString safeName = CFilePath::MakeSafeFileStem(meshName);
+ return m_Import.AddOrReplaceMesh(meshBuffer, meshName,
+ m_Source.FindMeshFilePathByName(safeName.c_str()));
+ }
+
+ bool HasMesh(TCharPtr meshName) const override { return m_Import.HasMesh(meshName); }
+
+ Option<TCharPtr> FindMeshReferencePathByName(TCharPtr meshName) const override
+ {
+ return m_Import.FindMeshReferencePathByName(meshName);
+ }
+
+ Option<TCharPtr> FindMeshFilePathByName(TCharPtr meshName) const override
+ {
+ return m_Import.FindMeshFilePathByName(meshName);
+ }
+
+ QT3DSU32 GetNumPathBuffers() const override { return m_Import.GetNumPathBuffers(); }
+ QT3DSU32 GetPathBuffers(NVDataRef<Pair<TCharPtr, TCharPtr>> pathBufferPaths) const override
+ {
+ return m_Import.GetPathBuffers(pathBufferPaths);
+ }
+ // Copies the an appropriate location in our import directory
+ // Returns the path of the added PathBuffer. This may mangle the name slightly
+ // In case of a conflict.
+ CharPtrOrError AddPathBuffer(const SPathBuffer &pathBuffer, TCharPtr pathName) override
+ {
+ Option<TCharPtr> added = m_Source.FindPathBufferByPath(pathName);
+ return m_Import.AddOrReplacePathBuffer(pathBuffer, pathName, added);
+ }
+
+ Option<TCharPtr> FindPathBufferByPath(TCharPtr pathBufferPath) const override
+ {
+ return m_Import.FindPathBufferByPath(pathBufferPath);
+ }
+
+ Option<TCharPtr> FindPathBufferByRelativePath(TCharPtr pathBufferPath) const override
+ {
+ return m_Import.FindPathBufferByRelativePath(pathBufferPath);
+ }
+
+ QT3DSU32 GetNumAnimations() const override { return m_Import.GetNumAnimations(); }
+ QT3DSU32 GetAnimations(NVDataRef<Animation> outBuffers) const override
+ {
+ return m_Import.GetAnimations(outBuffers);
+ }
+ // Data is copied into this object, you can release the anim buffer data after this
+ void DoAddAnimation(TCharPtr instance, TCharPtr propName, QT3DSU32 subPropIndex,
+ EAnimationType type, NVConstDataRef<QT3DSF32> values) override
+ {
+ m_Import.DoAddAnimation(instance, propName, subPropIndex, type, values);
+ }
+ Option<Animation> FindAnimation(TCharPtr instance, TCharPtr propName,
+ QT3DSU32 subPropIndex) const override
+ {
+ return m_Import.FindAnimation(instance, propName, subPropIndex);
+ }
+
+ template <typename TDataType>
+ NVDataRef<TDataType> TempAlloc(QT3DSU32 numItems) const
+ {
+ m_TempBuffer.reserve(numItems * sizeof(TDataType));
+ return toDataRef((TDataType *)m_TempBuffer.begin(), numItems);
+ }
+
+ template <typename TDataType, typename TDiffOp>
+ void CompileItemReport(AddRemoveImpl<TDataType> &result, TDiffOp op) const
+ {
+ QT3DSU32 numItems = op.NumItems(m_Import);
+ NVDataRef<TDataType> tempData(TempAlloc<TDataType>(numItems));
+ op.GetItems(m_Import, tempData);
+ QT3DSIMP_FOREACH(idx, numItems)
+ {
+ const TDataType &newDesc(tempData[idx]);
+ if (op.HasItem(m_Source, newDesc))
+ result.m_Existing.push_back(newDesc);
+ else
+ result.m_Added.push_back(newDesc);
+ }
+ numItems = op.NumItems(m_Source);
+ tempData = TempAlloc<TDataType>(numItems);
+ op.GetItems(m_Source, tempData);
+ QT3DSIMP_FOREACH(idx, numItems)
+ {
+ const TDataType &oldDesc(tempData[idx]);
+ if (op.HasItem(m_Import, oldDesc) == false)
+ result.m_Removed.push_back(oldDesc);
+ }
+ }
+
+ ImportReport CompileReport() const override
+ {
+ m_ImportReport.clear();
+ // Find existint, added, and removed items
+ CompileItemReport(m_ImportReport.m_Instances, InstanceDiffOp());
+ CompileItemReport(m_ImportReport.m_Images, ImageDiffOp());
+ CompileItemReport(m_ImportReport.m_Meshes, MeshDiffOp());
+ CompileItemReport(m_ImportReport.m_PathBuffers, PathBufferDiffOp());
+ CompileItemReport(m_ImportReport.m_Animations, AnimationDiffOp());
+
+ // OK, prepare parent child links
+
+ QT3DSIMP_FOREACH(idx, m_ImportReport.m_Instances.m_Removed.size())
+ {
+ const InstanceDesc &oldDesc(m_ImportReport.m_Instances.m_Removed[idx]);
+ QT3DSU32 numChildren = m_Source.GetNumChildren(oldDesc.m_Handle);
+ NVDataRef<InstanceDesc> tempData(TempAlloc<InstanceDesc>(numChildren));
+ m_Source.GetChildren(oldDesc.m_Handle, tempData);
+ QT3DSIMP_FOREACH(chld, numChildren)
+ m_ImportReport.m_Links.m_Removed.push_back(
+ ParentChildLink(oldDesc.m_Id, tempData[chld].m_Id, L""));
+ }
+ QT3DSIMP_FOREACH(idx, m_ImportReport.m_Instances.m_Added.size())
+ {
+ const InstanceDesc &newDesc(m_ImportReport.m_Instances.m_Added[idx]);
+ QT3DSU32 numChildren = GetNumChildren(newDesc.m_Handle);
+ NVDataRef<InstanceDesc> tempData(TempAlloc<InstanceDesc>(numChildren));
+ m_Import.GetChildren(newDesc.m_Handle, tempData);
+ QT3DSIMP_FOREACH(chldIdx, numChildren)
+ {
+ // Run through children in reverse order
+ // so that we know the sibling pointer is good.
+ QT3DSU32 chld = numChildren - chldIdx - 1;
+ TCharPtr child = tempData[chld].m_Id;
+ // If the chlid existed in the original, then it also needs to be added here.
+ // Because that means the a new object was added and an original object was
+ // re-attached.
+ if (m_Source.FindInstanceById(child).hasValue()) {
+ TCharPtr sibling = chld + 1 < numChildren ? tempData[chld + 1].m_Id : L"";
+ m_ImportReport.m_Links.m_Added.push_back(
+ ParentChildLink(newDesc.m_Id, child, sibling));
+ }
+ }
+ }
+ QT3DSIMP_FOREACH(idx, m_ImportReport.m_Instances.m_Existing.size())
+ {
+ const InstanceDesc &newDesc(m_ImportReport.m_Instances.m_Existing[idx]);
+ const InstanceDesc &oldDesc(m_Source.FindInstanceById(newDesc.m_Id));
+ QT3DSU32 numNewChildren(GetNumChildren(newDesc.m_Handle));
+ QT3DSU32 numOldChildren(m_Source.GetNumChildren(oldDesc.m_Handle));
+ NVDataRef<InstanceDesc> tempData(
+ TempAlloc<InstanceDesc>(numNewChildren + numOldChildren));
+ NVDataRef<InstanceDesc> newChildren(tempData.begin(), numNewChildren);
+ NVDataRef<InstanceDesc> oldChildren(tempData.begin() + numNewChildren, numOldChildren);
+ m_Import.GetChildren(newDesc.m_Handle, newChildren);
+ m_Source.GetChildren(oldDesc.m_Handle, oldChildren);
+ QT3DSIMP_FOREACH(childIdx, numNewChildren)
+ {
+ // Run through the links in reverse order so we know the sibling pointer is good.
+ // This is necessary for addChild.
+ QT3DSU32 child = numNewChildren - childIdx - 1;
+ const InstanceDesc &childDesc = newChildren[child];
+ TCharPtr sibling = child + 1 < numNewChildren ? newChildren[child + 1].m_Id : L"";
+ ParentChildLink link(newDesc.m_Id, childDesc.m_Id, sibling);
+ if (FindChild(m_Source.FindInstanceById(childDesc.m_Id), sibling, childDesc.m_Type,
+ oldChildren))
+ m_ImportReport.m_Links.m_Existing.push_back(link);
+ else
+ m_ImportReport.m_Links.m_Added.push_back(link);
+ }
+ QT3DSIMP_FOREACH(child, oldChildren.size())
+ {
+ const InstanceDesc &childDesc = oldChildren[child];
+ TCharPtr sibling =
+ child + 1 < oldChildren.size() ? oldChildren[child + 1].m_Id : L"";
+ if (FindChild(m_Import.FindInstanceById(childDesc.m_Id), sibling, childDesc.m_Type,
+ newChildren)
+ == false)
+ m_ImportReport.m_Links.m_Removed.push_back(
+ ParentChildLink(oldDesc.m_Id, childDesc.m_Id, L""));
+ }
+ }
+ m_Import.FinalizeReport();
+
+ return m_ImportReport;
+ }
+
+ void Release() override { delete this; }
+};
+
+}
+
+ImportPtrOrError Import::Create(TCharPtr _srcPath, TCharPtr _destDir)
+{
+ CFilePath srcPath(CFilePath::GetAbsolutePath(_srcPath));
+ CFilePath destDir(CFilePath::GetAbsolutePath(_destDir));
+
+ if (!srcPath.IsFile())
+ return ImportErrorData(ImportErrorCodes::SourceFileDoesNotExist, srcPath);
+
+ if (!destDir.CreateDir(true))
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, destDir);
+
+ TStringTablePtr strTable = UICDM::IStringTable::CreateStringTable();
+ return new ImportImpl(strTable, srcPath, destDir, L"maps", L"meshes");
+}
+
+ImportPtrOrError Import::Load(TCharPtr pathToFile, QT3DSU32 inImportVersion)
+{
+ CFilePath fullFilePath(CFilePath::GetAbsolutePath(pathToFile));
+ CFilePath destDir(fullFilePath.GetDirectory());
+
+ if (fullFilePath.IsFile() == false)
+ return ImportErrorData(ImportErrorCodes::SourceFileNotReadable, fullFilePath);
+
+ TStringTablePtr strTable = UICDM::IStringTable::CreateStringTable();
+ ImportImpl *impl = new ImportImpl(strTable, Q3DStudio::CString(), destDir);
+ bool success = impl->Load(fullFilePath, inImportVersion);
+ QT3DS_ASSERT(success);
+ if (success == false) {
+ impl->Release();
+ return ImportErrorData(ImportErrorCodes::SourceFileNotReadable, fullFilePath.c_str());
+ }
+ return impl;
+}
+
+ImportPtrOrError Import::CreateForRefresh(Import &original, TCharPtr _srcPath)
+{
+ CFilePath srcPath(CFilePath::GetAbsolutePath(_srcPath));
+
+ if (!srcPath.IsFile()) {
+ original.Release();
+ return ImportErrorData(ImportErrorCodes::SourceFileDoesNotExist, srcPath);
+ }
+
+ RefreshImpl *refresh(new RefreshImpl(static_cast<ImportImpl &>(original), srcPath));
+ return &refresh->GetImportInterface();
+}
+
+QT3DSU32 Import::GetHighestImportRevision(TCharPtr pathToFile)
+{
+ using std::shared_ptr;
+ CFilePath fullFilePath(CFilePath::GetAbsolutePath(pathToFile));
+ CFileSeekableIOStream stream(fullFilePath, FileReadFlags());
+ if (stream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ std::shared_ptr<UICDM::IStringTable> theStringTable =
+ UICDM::IStringTable::CreateStringTable();
+ std::shared_ptr<IDOMFactory> theFactory = IDOMFactory::CreateDOMFactory(theStringTable);
+ SDOMElement *theTopElement = CDOMSerializer::Read(*theFactory, stream);
+
+ if (theTopElement == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ std::shared_ptr<IDOMReader> theReader =
+ IDOMReader::CreateDOMReader(*theTopElement, theStringTable);
+ return ImportImpl::FindHighestRevisionInDocument(*theReader);
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImport.h b/src/Authoring/UICIMP/UICImportLib/UICImport.h
new file mode 100644
index 00000000..b9128cd0
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImport.h
@@ -0,0 +1,421 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTH
+#define UICIMPORTH
+#include "UICImportLibPrecompile.h"
+#include "UICImportMesh.h"
+#include "UICImportPath.h"
+#include "UICImportPerformImport.h"
+#include "UICDMStringTable.h"
+#include "UICImportComposerTypes.h"
+#include <string>
+
+namespace UICIMP {
+using namespace std;
+typedef QT3DSU64 TIMPHandle;
+
+struct InstanceDesc
+{
+ TCharPtr m_Id;
+ TIMPHandle m_Parent;
+ TIMPHandle m_Handle;
+ ComposerObjectTypes::Enum m_Type;
+ InstanceDesc()
+ : m_Id(NULL)
+ , m_Parent(0)
+ , m_Handle(0)
+ , m_Type(ComposerObjectTypes::Unknown)
+ {
+ }
+};
+
+struct Animation
+{
+ TCharPtr m_InstanceId;
+ TCharPtr m_PropertyName;
+ QT3DSU32 m_SubPropertyIndex;
+ EAnimationType m_Type;
+ NVConstDataRef<QT3DSF32> m_Keyframes;
+ Animation(TCharPtr iid, TCharPtr pname, QT3DSU32 subPropIndex, EAnimationType bufType,
+ NVConstDataRef<QT3DSF32> keyframes)
+ : m_InstanceId(iid)
+ , m_PropertyName(pname)
+ , m_SubPropertyIndex(subPropIndex)
+ , m_Type(bufType)
+ , m_Keyframes(keyframes)
+ {
+ }
+ Animation()
+ : m_InstanceId(L"")
+ , m_PropertyName(L"")
+ , m_SubPropertyIndex(0)
+ , m_Type(EAnimationTypeNone)
+ {
+ }
+};
+
+struct AddRemoveInfo
+{
+ QT3DSU32 m_Existing; // intersection of new and old
+ QT3DSU32 m_NumAdded; // new that doesn't exist in old
+ QT3DSU32 m_NumRemoved; // old that doesn't exist in new
+ AddRemoveInfo()
+ : m_Existing(0)
+ , m_NumAdded(0)
+ , m_NumRemoved(0)
+ {
+ }
+ AddRemoveInfo(QT3DSU32 exist, QT3DSU32 add, QT3DSU32 remove)
+ : m_Existing(exist)
+ , m_NumAdded(add)
+ , m_NumRemoved(remove)
+ {
+ }
+};
+
+struct ParentChildLink
+{
+ TCharPtr m_Parent;
+ TCharPtr m_Child;
+ TCharPtr m_NextSibling;
+
+ ParentChildLink(TCharPtr p, TCharPtr c, TCharPtr ns)
+ : m_Parent(p)
+ , m_Child(c)
+ , m_NextSibling(ns)
+ {
+ }
+ ParentChildLink() {}
+ bool operator<(const ParentChildLink &other) const
+ {
+ // This works because at this point id's are in the string table
+ // so equal strings are pointed to by the same pointer.
+ return m_Parent < other.m_Parent;
+ }
+};
+
+template <typename TDataType>
+struct AddRemoveData
+{
+ NVConstDataRef<TDataType> m_Existing;
+ NVConstDataRef<TDataType> m_Added;
+ NVConstDataRef<TDataType> m_Removed;
+ AddRemoveData() {}
+ AddRemoveData(NVConstDataRef<TDataType> exist, NVConstDataRef<TDataType> add,
+ NVConstDataRef<TDataType> rem)
+ : m_Existing(exist)
+ , m_Added(add)
+ , m_Removed(rem)
+ {
+ }
+};
+
+// Contains the basic information to perform an import or a refresh.
+// Note that during an import or refresh, the user-id information on the
+// descriptors may change. So you can't ever use exactly this information
+// on the descriptors. You have to always query the descriptor. Specifically,
+// Create instance, delete instance, and update instance can change user id
+// information.
+struct ImportReport
+{
+ // There is a precondition you can rely on that parents are added
+ // before children. Furthermore, instances that are added won't
+ // appear in the below parent child link added section.
+ AddRemoveData<InstanceDesc> m_Instances;
+ // For children, existing does tell you the intersection of the two
+ // sets *but* existing is in the order of the new set.
+ // This allows clients to detect child reordering where it may have
+ // a substantial effect (such as materials which would then get mapped
+ // to a different mesh instance).
+ AddRemoveData<ParentChildLink> m_Links;
+
+ AddRemoveData<Pair<TCharPtr, TCharPtr>> m_Images;
+ AddRemoveData<Pair<TCharPtr, TCharPtr>> m_Meshes;
+ AddRemoveData<Pair<TCharPtr, TCharPtr>> m_PathBuffers;
+ AddRemoveData<Animation> m_Animations;
+
+ ImportReport() {}
+ ImportReport(AddRemoveData<InstanceDesc> instances, AddRemoveData<ParentChildLink> links,
+ AddRemoveData<Pair<TCharPtr, TCharPtr>> imageBuffers,
+ AddRemoveData<Pair<TCharPtr, TCharPtr>> meshes,
+ AddRemoveData<Pair<TCharPtr, TCharPtr>> pathBuffers,
+ AddRemoveData<Animation> animBuffers)
+ : m_Instances(instances)
+ , m_Links(links)
+ , m_Images(imageBuffers)
+ , m_Meshes(meshes)
+ , m_PathBuffers(pathBuffers)
+ , m_Animations(animBuffers)
+ {
+ }
+};
+
+template <typename TDataType>
+struct DatatypeOrError
+{
+ bool m_Error;
+ ImportErrorData m_ErrorData;
+ TDataType m_Value;
+ DatatypeOrError(const TDataType &value)
+ : m_Error(false)
+ , m_Value(value)
+ {
+ }
+ DatatypeOrError(const ImportErrorData &error, const TDataType &badValue = TDataType())
+ : m_Error(true)
+ , m_ErrorData(error)
+ , m_Value(badValue)
+ {
+ }
+
+ TDataType &operator->()
+ {
+ QT3DS_ASSERT(m_Error == false);
+ return m_Value;
+ }
+ TDataType &operator*()
+ {
+ QT3DS_ASSERT(m_Error == false);
+ return m_Value;
+ }
+ operator TDataType()
+ {
+ QT3DS_ASSERT(m_Error == false);
+ return m_Value;
+ }
+};
+class Import;
+typedef DatatypeOrError<Import *> ImportPtrOrError;
+typedef DatatypeOrError<TCharPtr> CharPtrOrError;
+
+template <typename TDataType>
+struct SImportConverter
+{
+ TImportModelValue Convert(const TDataType &inType) { return inType; }
+};
+
+template <>
+struct SImportConverter<TDataStrPtr>
+{
+ const wchar_t *Convert(const wchar_t *inValue) { return inValue; }
+};
+// Long4s are string refs, so they are set by string
+template <>
+struct SImportConverter<SLong4>
+{
+ SValue Convert(const wchar_t *inValue) { return SStringRef(inValue); }
+};
+
+class Import
+{
+protected:
+ virtual ~Import(){}
+
+public:
+ // So users can check if a file is an import file.
+ //<UICImportLib version="${fileversion}"
+ static QT3DSU32 GetImportFileVersion() { return 1; }
+
+ // Cache this string in the string table and return
+ // a representation that will be around until this import object
+ // is destroyed.
+ virtual TCharPtr RegisterStr(TCharPtr data) = 0;
+ // Returns the source directory relative to the dest directory
+ // or the full path if it is on a different drive
+ virtual TCharPtr GetSrcFile() const = 0;
+ // Returns the full path of the destination directory
+ virtual TCharPtr GetDestDir() const = 0;
+ // Returns the full path of the image directory
+ virtual TCharPtr GetImageDir() const = 0;
+ // Returns the full path of the mesh directory
+ virtual TCharPtr GetMeshDir() const = 0;
+ // Returns the full path to the path buffer directory
+ virtual TCharPtr GetPathBufferDir() const = 0;
+ virtual void Release() = 0;
+ // returns false if fname couldn't be opened for write
+ // Fname is appended to the directory this object was created with.
+ // This is necessary in order to keep relative paths valid within
+ // the import file. Returns an ID that uniquely identifies this import
+ // object within the final document.
+ virtual QT3DSU32 Save(TCharPtr fname) const = 0;
+
+ // Add a mapping from an named id to a handle
+ virtual Option<InstanceDesc> GetInstanceByHandle(TIMPHandle inst) const = 0;
+ virtual Option<InstanceDesc> FindInstanceById(TCharPtr inst) const = 0;
+ virtual Option<InstanceDesc> FindAnyInstanceById(TCharPtr inst) const = 0;
+ virtual QT3DSU32 GetNumInstances() const = 0;
+ virtual QT3DSU32 GetInstances(NVDataRef<InstanceDesc> outDescs) const = 0;
+ virtual QT3DSU32 GetNumProperties(TIMPHandle instance) const = 0;
+ virtual QT3DSU32 GetProperties(TIMPHandle inst, NVDataRef<PropertyValue> outBuffer) const = 0;
+ virtual Option<SValue> GetInstancePropertyValue(TIMPHandle inst,
+ ComposerPropertyNames::Enum val) const = 0;
+ virtual QT3DSU32 GetNumChildren(TIMPHandle instance) const = 0;
+ virtual QT3DSU32 GetChildren(TIMPHandle instance, NVDataRef<InstanceDesc> childBuffer) const = 0;
+ // Invalid instances will not be saved out to the import file and should be ignored
+ // in the import report.
+ virtual void MarkInstanceInvalid(TIMPHandle inst) = 0;
+
+ virtual TIMPHandle CreateInstance(TCharPtr id, ComposerObjectTypes::Enum inType) = 0;
+ // The new instance ends up attached to the same parent
+ // and just after inSource in the parent's children lists.
+ // This performs a deep copy and fixes up references if they occur in the
+ // new hierarchy.
+ virtual TIMPHandle CopyInstance(TIMPHandle inSource) = 0;
+
+ // Returns true if inst exists, false otherwise.
+
+ virtual bool SetInstanceProperties(TIMPHandle inst, NVConstDataRef<PropertyValue> inBuffer) = 0;
+
+ template <typename TPropertyType, typename TDataType>
+ void SetInstancePropertyValue(TIMPHandle inst,
+ const SImportPropertyDefinition<TPropertyType> &inProperty,
+ const TDataType &val)
+ {
+ DoSetInstancePropertyValue(inst, inProperty.m_Name,
+ SImportConverter<TPropertyType>().Convert(val));
+ }
+
+ virtual bool AddChild(TIMPHandle inst, TIMPHandle child) = 0;
+
+ virtual QT3DSU32 GetNumImages() const = 0;
+ // Returns imgOriginalPath,imgDestPath pair
+ virtual QT3DSU32 GetImages(NVDataRef<Pair<TCharPtr, TCharPtr>> imgPaths) const = 0;
+ // Copies the an appropriate location in our import directory
+ // Returns the path of the added image. This may mangle the name slightly
+ // In case of a conflict.
+ // If this function returns L"", there was a problem copying the data
+ // and you need to abort the import process immediately. For a new import,
+ // then delete the existing imported images. For refresh, the user may just
+ // be stuck with a half-updated dataset.
+ // This path is relative to the current working directory when this object was created
+ // or absolute.
+ // Returns a relative path, from dest directory, where the image was saved out to.
+ virtual CharPtrOrError AddImage(TCharPtr imgPath) = 0;
+ // Assuming this image path is relative to the current working directory, find the image
+ virtual Option<TCharPtr> FindImageByPath(TCharPtr imgPath) const = 0;
+ // Assuming this path is relative to the import source document, find the image.
+ virtual Option<TCharPtr> FindImageByRelativePath(TCharPtr imgPath) const = 0;
+
+ virtual QT3DSU32 GetNumMeshes() const = 0;
+ // Returns meshName,meshDestPath pair
+ virtual QT3DSU32 GetMeshes(NVDataRef<Pair<TCharPtr, TCharPtr>> bufferPaths) const = 0;
+
+ // Copies the vertex buffer into the appropriate location, renaming if necessary.
+ // Mesh name is used to write out a reasonable buffer *and* on refresh to know
+ // if a buffer is changed/updated or not
+ // If this function returns L"", there was a problem copying the data
+ // and you need to abort the import process immediately. For a new import,
+ // then delete the existing imported images. For refresh, the user may just
+ // be stuck with a half-updated dataset.
+ // Returns a relative path, from the mesh directory, where the mesh was saved out
+ // to.
+ virtual CharPtrOrError AddMesh(const Mesh &meshBuffer, TCharPtr meshName) = 0;
+ virtual bool HasMesh(TCharPtr meshName) const = 0;
+ // Return the mesh path with the current version number
+ virtual Option<TCharPtr> FindMeshReferencePathByName(TCharPtr meshName) const = 0;
+ virtual Option<TCharPtr> FindMeshFilePathByName(TCharPtr meshName) const = 0;
+
+ virtual QT3DSU32 GetNumPathBuffers() const = 0;
+ // Returns imgOriginalPath,imgDestPath pair
+ virtual QT3DSU32 GetPathBuffers(NVDataRef<Pair<TCharPtr, TCharPtr>> pathBufferPaths) const = 0;
+ virtual CharPtrOrError AddPathBuffer(const SPathBuffer &pathBuffer, TCharPtr pathName) = 0;
+ // Assuming this Path path is relative to the current working directory, find the Path
+ virtual Option<TCharPtr> FindPathBufferByPath(TCharPtr pathBufferPath) const = 0;
+ // Assuming this path is relative to the import source document, find the Path.
+ virtual Option<TCharPtr> FindPathBufferByRelativePath(TCharPtr pathBufferPath) const = 0;
+
+ virtual QT3DSU32 GetNumAnimations() const = 0;
+ virtual QT3DSU32 GetAnimations(NVDataRef<Animation> outBuffers) const = 0;
+ // Data is copied into this object, you can release the anim buffer data after this
+ virtual Option<Animation> FindAnimation(TCharPtr instance, TCharPtr propName,
+ QT3DSU32 subPropIndex) const = 0;
+ template <typename TDataType>
+ void AddAnimation(TCharPtr instance, const SImportPropertyDefinition<TDataType> &inProperty,
+ QT3DSU32 subPropIndex, EAnimationType type, NVConstDataRef<QT3DSF32> values)
+ {
+ std::tuple<bool, size_t> isAnimatableAndArity(
+ GetDatatypeAnimatableAndArity(TypeToDataType<TDataType>()));
+ if (std::get<0>(isAnimatableAndArity)) {
+ if (subPropIndex >= std::get<1>(isAnimatableAndArity)) {
+ QT3DS_ASSERT(false);
+ subPropIndex = 0;
+ }
+ DoAddAnimation(instance, ComposerPropertyNames::Convert(inProperty.GetName()),
+ subPropIndex, type, values);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ // Call after the import process is complete in order to get all the new items.
+ virtual ImportReport CompileReport() const = 0;
+
+protected:
+ // Careful with this. If the property value contains heap memory
+ // Then this may crash if you are coming from a dll.
+ virtual void DoAddAnimation(TCharPtr instance, TCharPtr propName, QT3DSU32 subPropIndex,
+ EAnimationType type, NVConstDataRef<QT3DSF32> values) = 0;
+ virtual bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
+ const TImportModelValue &val) = 0;
+ virtual bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
+ TCharPtr val) = 0;
+
+public:
+ // Create blank import object
+ // It is the caller's responsibility to ensure that imgPath and meshBufPath exist and
+ // are writable.
+ // Of srcDirectoryOrFile is a file, we get the directory of that file using
+ // FilePath::GetDirName( srcDirectoryOrFile )
+ // We then get its absolute path, get our absolute path, and attempt to create
+ // a relative path from dest directory to src directory.
+ static ImportPtrOrError Create(TCharPtr srcFile, TCharPtr destDirectory);
+
+ // Load an import object from a file. This can obviously fail
+ // Also, an import file can contain multiple documents so you need to identify
+ // which document you are talking about.
+ // 0 means load the latest document.
+ static ImportPtrOrError Load(TCharPtr pathToFile, QT3DSU32 inDocumentId = 0);
+
+ // Create an import object that will update heavy resources (like images and mesh objects)
+ // and it CompileReport will return objects that indicate the differences between the new
+ // document and the existing document.
+ // You have a chance to refresh from a document that isn't in the same location.
+ // We use relative paths throughout the system so that image src paths are relative
+ // to the src document directory and such, so we can still import sanely.
+ // Dest directory is set to where original's dest directory was set to.
+ static ImportPtrOrError CreateForRefresh(Import &original, TCharPtr srcFile);
+
+ // Return the highest import version in a given document. Returns zero upon
+ // failure, else an integer that is valid for load.
+ static QT3DSU32 GetHighestImportRevision(TCharPtr pathToFile);
+};
+}
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.cpp
new file mode 100644
index 00000000..6eefb793
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICImportLibPrecompile.h"
+#include "UICImportComposerTypes.h"
+
+using namespace UICIMP;
+
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \
+ if (AreEqual(inPropertyName, L"" #name)) \
+ return TypeToDataType<dtype>();
+
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype)
+
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue)
+
+DataModelDataType::Value SImportAsset::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_NAMED_PROPERTIES
+ ITERATE_COMPOSER_ASSET_PROPERTIES
+
+ QT3DS_ASSERT(false);
+ return DataModelDataType::None;
+}
+
+DataModelDataType::Value SImportNode::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_NODE_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportModel::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_MODEL_PROPERTIES
+ return SImportNode::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportMaterial::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_MATERIAL_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportImage::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_IMAGE_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportPath::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_PATH_PROPERTIES
+ return SImportNode::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportSubPath::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportPathAnchorPoint::GetPropertyDataType(const wchar_t *inPropertyName)
+{
+ ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \
+ if (AreEqual(inPropertyName, #name)) \
+ return TypeToDataType<dtype>();
+
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype)
+
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue)
+
+DataModelDataType::Value SImportAsset::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_NAMED_PROPERTIES
+ ITERATE_COMPOSER_ASSET_PROPERTIES
+
+ QT3DS_ASSERT(false);
+ return DataModelDataType::None;
+}
+
+DataModelDataType::Value SImportNode::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_NODE_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportModel::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_MODEL_PROPERTIES
+ return SImportNode::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportMaterial::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_MATERIAL_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportImage::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_IMAGE_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportPath::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_PATH_PROPERTIES
+ return SImportNode::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportSubPath::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+DataModelDataType::Value SImportPathAnchorPoint::GetPropertyDataType(const char8_t *inPropertyName)
+{
+ ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES
+ return SImportAsset::GetPropertyDataType(inPropertyName);
+}
+
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+
+SImportAsset &SImportComposerTypes::GetImportAssetForType(ComposerObjectTypes::Enum inTypeName)
+{
+ ComposerObjectTypes::Enum theType = inTypeName;
+ switch (theType) {
+ case ComposerObjectTypes::Asset:
+ return m_Asset;
+ case ComposerObjectTypes::Group:
+ return m_Group;
+ case ComposerObjectTypes::Model:
+ return m_Model;
+ case ComposerObjectTypes::Node:
+ return m_Node;
+ case ComposerObjectTypes::Image:
+ return m_Image;
+ case ComposerObjectTypes::Material:
+ return m_Material;
+ case ComposerObjectTypes::Path:
+ return m_Path;
+ case ComposerObjectTypes::SubPath:
+ return m_SubPath;
+ case ComposerObjectTypes::PathAnchorPoint:
+ return m_PathAnchorPoint;
+ }
+ QT3DS_ASSERT(false);
+ return m_Asset;
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.h b/src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.h
new file mode 100644
index 00000000..235de59b
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportComposerTypes.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTCOMPOSERTYPESH
+#define UICIMPORTCOMPOSERTYPESH
+#include "UICDMComposerTypeDefinitions.h"
+
+// Define the subset of types that the import library supports.
+namespace UICIMP {
+using namespace UICDM;
+
+template <typename TDataType>
+struct SImportPropertyDefinition
+{
+ const ComposerPropertyNames::Enum m_Name;
+ ComposerPropertyNames::Enum GetName() const { return m_Name; }
+
+ SImportPropertyDefinition(ComposerPropertyNames::Enum inName)
+ : m_Name(inName)
+ {
+ }
+};
+
+template <ComposerPropertyNames::Enum TEnumName, typename TDataType>
+struct SSpecificImportPropertyDefinition : public SImportPropertyDefinition<TDataType>
+{
+ SSpecificImportPropertyDefinition()
+ : SImportPropertyDefinition<TDataType>(TEnumName)
+ {
+ }
+};
+
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \
+ SSpecificImportPropertyDefinition<ComposerPropertyNames::name, dtype> memberName;
+
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype)
+
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue)
+
+struct SImportAsset
+{
+ ITERATE_COMPOSER_NAMED_PROPERTIES
+ ITERATE_COMPOSER_ASSET_PROPERTIES
+ virtual DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName);
+ virtual DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName);
+ virtual ComposerObjectTypes::Enum GetObjectType() { return ComposerObjectTypes::Asset; }
+ const wchar_t *GetObjectName() { return ComposerObjectTypes::Convert(GetObjectType()); }
+};
+
+struct SImportNode : public SImportAsset
+{
+ ITERATE_COMPOSER_NODE_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Node; }
+};
+
+struct SImportGroup : public SImportNode
+{
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Group; }
+};
+
+struct SImportModel : public SImportNode
+{
+ ITERATE_COMPOSER_MODEL_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Model; }
+};
+
+struct SImportMaterial : public SImportAsset
+{
+ ITERATE_COMPOSER_MATERIAL_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Material; }
+};
+
+struct SImportImage : public SImportAsset
+{
+ ITERATE_COMPOSER_IMAGE_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Image; }
+};
+
+struct SImportPath : public SImportNode
+{
+ ITERATE_COMPOSER_PATH_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Path; }
+};
+
+struct SImportSubPath : public SImportAsset
+{
+ ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::SubPath; }
+};
+
+struct SImportPathAnchorPoint : public SImportAsset
+{
+ ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES
+ DataModelDataType::Value GetPropertyDataType(const wchar_t *inPropertyName) override;
+ DataModelDataType::Value GetPropertyDataType(const char8_t *inPropertyName) override;
+ ComposerObjectTypes::Enum GetObjectType() override
+ {
+ return ComposerObjectTypes::PathAnchorPoint;
+ }
+};
+
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+
+template <typename TOperator>
+inline void ImportVisitPropertyType(ComposerPropertyNames::Enum inName, TOperator &inOperator)
+{
+ switch (inName) {
+#define HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype) \
+ case ComposerPropertyNames::name: \
+ inOperator.template Handle<dtype>(inName); \
+ return;
+#define HANDLE_COMPOSER_PROPERTY_DUPLICATE(name, memberName, dtype, defaultValue)
+#define HANDLE_COMPOSER_PROPERTY(name, memberName, dtype, defaultValue) \
+ HANDLE_COMPOSER_PROPERTY_NO_DEFAULT(name, memberName, dtype)
+
+ ITERATE_COMPOSER_NAMED_PROPERTIES
+ ITERATE_COMPOSER_ASSET_PROPERTIES
+ ITERATE_COMPOSER_NODE_PROPERTIES
+ ITERATE_COMPOSER_MATERIAL_PROPERTIES
+ ITERATE_COMPOSER_IMAGE_PROPERTIES
+ ITERATE_COMPOSER_PATH_PROPERTIES
+ ITERATE_COMPOSER_PATH_SUBPATH_PROPERTIES
+ ITERATE_COMPOSER_PATH_ANCHOR_POINT_PROPERTIES
+
+#undef HANDLE_COMPOSER_PROPERTY
+#undef HANDLE_COMPOSER_PROPERTY_DUPLICATE
+#undef HANDLE_COMPOSER_PROPERTY_NO_DEFAULT
+ }
+ QT3DS_ASSERT(false);
+}
+
+struct SImportComposerTypes
+{
+ SImportAsset m_Asset;
+ SImportGroup m_Group;
+ SImportModel m_Model;
+ SImportNode m_Node;
+ SImportMaterial m_Material;
+ SImportImage m_Image;
+ SImportPath m_Path;
+ SImportSubPath m_SubPath;
+ SImportPathAnchorPoint m_PathAnchorPoint;
+
+ SImportAsset &GetImportAssetForType(ComposerObjectTypes::Enum inTypeName);
+};
+};
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportContainers.h b/src/Authoring/UICIMP/UICImportLib/UICImportContainers.h
new file mode 100644
index 00000000..d6874459
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportContainers.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTCONTAINERSH
+#define UICIMPORTCONTAINERSH
+
+#include "EASTL/hash_map.h"
+#include "EASTL/hash_set.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "UICDMWStrOps.h"
+
+namespace UICIMP {
+
+#define QT3DSIMP_FOREACH(idxnm, val) \
+ for (QT3DSU32 idxnm = 0, __numItems = (QT3DSU32)val; idxnm < __numItems; ++idxnm)
+
+template <typename TKey, typename TValue, typename THash = eastl::hash<TKey>,
+ typename TPredicate = eastl::equal_to<TKey>>
+struct ImportHashMap : public eastl::hash_map<TKey, TValue, THash, TPredicate>
+{
+ using base_type = eastl::hash_map<TKey, TValue, THash, TPredicate>;
+
+ ImportHashMap() {}
+
+
+
+ bool contains(const TKey &key) const { return find(key) != base_type::end(); }
+};
+template <typename TKey>
+struct ImportHashSet : public eastl::hash_set<TKey, eastl::hash<TKey>, eastl::equal_to<TKey>>
+{
+ using base_type = eastl::hash_set<TKey, eastl::hash<TKey>, eastl::equal_to<TKey>>;
+ ImportHashSet() {}
+ bool contains(const TKey &key) const { return base_type::find(key) != base_type::end(); }
+};
+template <typename TValue>
+struct ImportArray : public eastl::vector<TValue>
+{
+ using base_type = eastl::vector<TValue>;
+
+ ImportArray() {}
+ operator NVConstDataRef<TValue>() const
+ {
+ return NVConstDataRef<TValue>(base_type::data(), (QT3DSU32) base_type::size());
+ }
+
+ operator NVDataRef<TValue>() {
+ return NVDataRef<TValue>(base_type::data(), (QT3DSU32) base_type::size());
+ }
+};
+
+inline NVConstDataRef<wchar_t> toRef(const wchar_t *data, QT3DSU32 len = 0)
+{
+ if (IsTrivial(data))
+ return NVConstDataRef<wchar_t>(L"", 0);
+ len = len ? len : (QT3DSU32)wcslen(data);
+ return NVConstDataRef<wchar_t>(data, len);
+}
+}
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportErrorCodes.h b/src/Authoring/UICIMP/UICImportLib/UICImportErrorCodes.h
new file mode 100644
index 00000000..21d2f4ed
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportErrorCodes.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTERRORCODESH
+#define UICIMPORTERRORCODESH
+
+namespace UICIMP {
+
+#define NVIMP_ITERATE_ERROR_CODES \
+ NVIMP_HANDLE_ERROR_CODE(ResourceNotWriteable) \
+ NVIMP_HANDLE_ERROR_CODE(SourceFileNotReadable) \
+ NVIMP_HANDLE_ERROR_CODE(UnableToCreateDirectory) \
+ NVIMP_HANDLE_ERROR_CODE(SourceFileDoesNotExist) \
+ NVIMP_HANDLE_ERROR_CODE(TranslationToImportFailed)
+
+struct ImportErrorCodes
+{
+ enum Enum {
+ NoError = 0,
+#define NVIMP_HANDLE_ERROR_CODE(x) x,
+ NVIMP_ITERATE_ERROR_CODES
+#undef NVIMP_HANDLE_ERROR_CODE
+ };
+ static const wchar_t *GetEnglishFormatString(Enum value)
+ {
+ switch (value) {
+ case ResourceNotWriteable:
+ return L"Refresh failed because could not update Resource:\n %s\nPlease check out "
+ L"resource and try again";
+ case SourceFileNotReadable:
+ return L"Could not open %s for read\n";
+ case UnableToCreateDirectory:
+ return L"Unable to create directory %s\n";
+ default: ;
+ }
+ return L"No error code";
+ }
+};
+}
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportImpl.h b/src/Authoring/UICIMP/UICImportLib/UICImportImpl.h
new file mode 100644
index 00000000..5be7f3d1
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportImpl.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTIMPLH
+#define UICIMPORTIMPLH
+#include "UICImport.h"
+#include "UICImportContainers.h"
+#include "EASTL/functional.h"
+
+namespace eastl {
+template <>
+struct hash<UICDM::ComposerPropertyNames::Enum>
+{
+ size_t operator()(UICDM::ComposerPropertyNames::Enum val) const
+ {
+ return hash<qt3ds::QT3DSU32>()((qt3ds::QT3DSU32)val);
+ }
+};
+}
+
+namespace UICIMP {
+
+struct Instance;
+inline TIMPHandle toHdl(Instance *inst)
+{
+ return (QT3DSU64)inst;
+}
+
+inline Instance *fromHdl(TIMPHandle hdl)
+{
+ return reinterpret_cast<Instance *>(reinterpret_cast<void *>(hdl));
+}
+
+struct Instance : public InstanceDesc
+{
+ ImportHashMap<ComposerPropertyNames::Enum, SInternValue> m_PropertyValues;
+ eastl::vector<TCharPtr> m_Children;
+ bool m_Valid;
+
+public:
+ Instance()
+ : m_Valid(true)
+ {
+ m_Handle = toHdl(this);
+ }
+ Instance(const InstanceDesc &desc)
+ : InstanceDesc(desc)
+ , m_Valid(true)
+ {
+ m_Handle = toHdl(this);
+ }
+ void SetPropertyValue(ComposerPropertyNames::Enum name, const SInternValue &val)
+ {
+ m_PropertyValues[name] = val;
+ }
+ void SetPropertyValues(NVConstDataRef<PropertyValue> values, UICDM::IStringTable &inStringTable)
+ {
+ m_PropertyValues.clear();
+ QT3DSIMP_FOREACH(idx, values.size())
+ SetPropertyValue(values[idx].m_Name, SInternValue(values[idx].m_Value, inStringTable));
+ }
+ void AddChild(Instance *child)
+ {
+ if (m_Valid == false)
+ child->m_Valid = false;
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)m_Children.size())
+ {
+ // Pointer comparison is fine as both strings are just in the
+ // string table.
+ if (m_Children[idx] == child->m_Id)
+ return;
+ }
+ QT3DS_ASSERT(child->m_Parent == 0);
+ child->m_Parent = toHdl(this);
+ m_Children.push_back(child->m_Id);
+ }
+ void AddChild(Instance *child, Instance *inInsertAfter)
+ {
+ if (m_Valid == false)
+ child->m_Valid = false;
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)m_Children.size())
+ {
+ // Pointer comparison is fine as both strings are just in the
+ // string table.
+ if (m_Children[idx] == child->m_Id)
+ return;
+ }
+ QT3DS_ASSERT(child->m_Parent == 0);
+ child->m_Parent = toHdl(this);
+ eastl::vector<TCharPtr>::iterator theIter =
+ std::find(m_Children.begin(), m_Children.end(), inInsertAfter->m_Id);
+ if (theIter != m_Children.end())
+ ++theIter;
+ m_Children.insert(theIter, child->m_Id);
+ }
+ void MarkInvalid() { m_Valid = false; }
+};
+
+struct AnimationId
+{
+ TIMPHandle m_Instance;
+ TCharPtr m_Property;
+ QT3DSU32 m_SubPropIndex;
+ AnimationId(TIMPHandle inst, TCharPtr p, QT3DSU32 spi)
+ : m_Instance(inst)
+ , m_Property(p)
+ , m_SubPropIndex(spi)
+ {
+ }
+ AnimationId()
+ : m_Instance(0)
+ , m_Property(0)
+ , m_SubPropIndex(0)
+ {
+ }
+};
+
+inline Animation *CreateAnimation(TCharPtr instance, TCharPtr propName, QT3DSU32 spi,
+ EAnimationType bufType, NVConstDataRef<QT3DSF32> values)
+{
+ QT3DSU32 animBufSize = sizeof(Animation);
+ QT3DSU32 valueSize = values.size() * sizeof(QT3DSF32);
+ QT3DSU8 *memBuf = (QT3DSU8 *)malloc(animBufSize + valueSize);
+ QT3DSF32 *framePtr = (QT3DSF32 *)(memBuf + animBufSize);
+ memCopy(framePtr, values.begin(), valueSize);
+ values = toConstDataRef(framePtr, values.size());
+ Animation *newBuf = new (memBuf) Animation(instance, propName, spi, bufType, values);
+ return newBuf;
+}
+}
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.cpp
new file mode 100644
index 00000000..9243f7eb
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// UICImportLib.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "UICImportLibPrecompile.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.h b/src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.h
new file mode 100644
index 00000000..8ceac213
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportLibPrecompile.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT \
+ 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSOption.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include <map>
+#include <vector>
+#include <string>
+#include <exception>
+#include <set>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include "UICDMDataTypes.h"
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSBasicTemplates.h"
+
+namespace UICIMP {
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::render;
+using namespace UICDM;
+using namespace std;
+}
+
+// TODO: reference additional headers your program requires here
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportMesh.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportMesh.cpp
new file mode 100644
index 00000000..b4e5486d
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportMesh.cpp
@@ -0,0 +1,831 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef WIN32
+#pragma warning(disable : 4100)
+#endif
+#include "UICImportLibPrecompile.h"
+#include "UICImportMesh.h"
+
+// This file is compiled for both studio and the runtime so you can't
+// add boost or much UICDM. Note that the only UICDM file included is
+// UICDMStreams and this file does not include UICDMDatatypes or anything
+// like that.
+
+using namespace UICIMP;
+
+#ifdef QT3DS_X86
+
+// Ensure our objects are of expected sizes. This keeps us honest
+// And ensures that we can load the datastructures we expect to by simply
+// mapping the memory.
+QT3DS_COMPILE_TIME_ASSERT(sizeof(NVRenderComponentTypes::Enum) == 4);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(NVRenderDrawMode::Enum) == 4);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(NVRenderVertexBufferEntry) == 20);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(VertexBuffer) == 20);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(IndexBuffer) == 12);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(MeshSubset) == 40);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(MeshDataHeader) == 12);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(Mesh) == 56);
+
+#endif
+
+#define QT3DSIMP_FOREACH(idxnm, val) \
+ for (QT3DSU32 idxnm = 0, __numItems = (QT3DSU32)val; idxnm < __numItems; ++idxnm)
+
+namespace {
+
+struct MeshSubsetV1
+{
+ // See description of a logical vertex buffer below
+ QT3DSU32 m_LogicalVbufIndex;
+ // QT3DS_MAX_U32 means use all available items
+ QT3DSU32 m_Count;
+ // Offset is in item size, not bytes.
+ QT3DSU32 m_Offset;
+ // Bounds of this subset. This is filled in by the builder
+ // see AddMeshSubset
+ NVBounds3 m_Bounds;
+};
+
+struct LogicalVertexBuffer
+{
+ QT3DSU32 m_ByteOffset;
+ QT3DSU32 m_ByteSize;
+ LogicalVertexBuffer(QT3DSU32 byteOff, QT3DSU32 byteSize)
+ : m_ByteOffset(byteOff)
+ , m_ByteSize(byteSize)
+ {
+ }
+ LogicalVertexBuffer()
+ : m_ByteOffset(0)
+ , m_ByteSize(0)
+ {
+ }
+};
+
+struct MeshV1
+{
+ VertexBuffer m_VertexBuffer;
+ IndexBuffer m_IndexBuffer;
+ SOffsetDataRef<LogicalVertexBuffer> m_LogicalVertexBuffers; // may be empty
+ SOffsetDataRef<MeshSubsetV1> m_Subsets;
+ NVRenderDrawMode::Enum m_DrawMode;
+ NVRenderWinding::Enum m_Winding;
+ typedef MeshSubsetV1 TSubsetType;
+};
+
+template <typename TSerializer>
+void Serialize(TSerializer &serializer, MeshV1 &mesh)
+{
+ QT3DSU8 *baseAddr = reinterpret_cast<QT3DSU8 *>(&mesh);
+ serializer.streamify(mesh.m_VertexBuffer.m_Entries);
+ serializer.align();
+ QT3DSIMP_FOREACH(entry, mesh.m_VertexBuffer.m_Entries.size())
+ {
+ MeshVertexBufferEntry &entryData = const_cast<MeshVertexBufferEntry &>(
+ mesh.m_VertexBuffer.m_Entries.index(baseAddr, entry));
+ serializer.streamifyCharPointerOffset(entryData.m_NameOffset);
+ serializer.align();
+ }
+ serializer.streamify(mesh.m_VertexBuffer.m_Data);
+ serializer.align();
+ serializer.streamify(mesh.m_IndexBuffer.m_Data);
+ serializer.align();
+ serializer.streamify(mesh.m_LogicalVertexBuffers);
+ serializer.align();
+ serializer.streamify(mesh.m_Subsets);
+ serializer.align();
+}
+
+struct MeshSubsetV2
+{
+ QT3DSU32 m_LogicalVbufIndex;
+ QT3DSU32 m_Count;
+ QT3DSU32 m_Offset;
+ NVBounds3 m_Bounds;
+ SOffsetDataRef<char16_t> m_Name;
+};
+
+struct MeshV2
+{
+ static const char16_t *s_DefaultName;
+
+ VertexBuffer m_VertexBuffer;
+ IndexBuffer m_IndexBuffer;
+ SOffsetDataRef<LogicalVertexBuffer> m_LogicalVertexBuffers; // may be empty
+ SOffsetDataRef<MeshSubsetV2> m_Subsets;
+ NVRenderDrawMode::Enum m_DrawMode;
+ NVRenderWinding::Enum m_Winding;
+ typedef MeshSubsetV2 TSubsetType;
+};
+
+template <typename TSerializer>
+void Serialize(TSerializer &serializer, MeshV2 &mesh)
+{
+ QT3DSU8 *baseAddr = reinterpret_cast<QT3DSU8 *>(&mesh);
+ serializer.streamify(mesh.m_VertexBuffer.m_Entries);
+ serializer.align();
+ QT3DSIMP_FOREACH(entry, mesh.m_VertexBuffer.m_Entries.size())
+ {
+ MeshVertexBufferEntry &entryData = const_cast<MeshVertexBufferEntry &>(
+ mesh.m_VertexBuffer.m_Entries.index(baseAddr, entry));
+ serializer.streamifyCharPointerOffset(entryData.m_NameOffset);
+ serializer.align();
+ }
+ serializer.streamify(mesh.m_VertexBuffer.m_Data);
+ serializer.align();
+ serializer.streamify(mesh.m_IndexBuffer.m_Data);
+ serializer.align();
+ serializer.streamify(mesh.m_LogicalVertexBuffers);
+ serializer.align();
+ serializer.streamify(mesh.m_Subsets);
+ serializer.align();
+ QT3DSIMP_FOREACH(entry, mesh.m_Subsets.size())
+ {
+ MeshSubsetV2 &theSubset = const_cast<MeshSubsetV2 &>(mesh.m_Subsets.index(baseAddr, entry));
+ serializer.streamify(theSubset.m_Name);
+ serializer.align();
+ }
+}
+
+// Localize the knowledge required to read/write a mesh into one function
+// written in such a way that you can both read and write by passing
+// in one serializer type or another.
+// This function needs to be careful to request alignment after every write of a
+// buffer that may leave us unaligned. The easiest way to be correct is to request
+// alignment a lot. The hardest way is to use knowledge of the datatypes and
+// only request alignment when necessary.
+template <typename TSerializer>
+void Serialize(TSerializer &serializer, Mesh &mesh)
+{
+ QT3DSU8 *baseAddr = reinterpret_cast<QT3DSU8 *>(&mesh);
+ serializer.streamify(mesh.m_VertexBuffer.m_Entries);
+ serializer.align();
+ QT3DSIMP_FOREACH(entry, mesh.m_VertexBuffer.m_Entries.size())
+ {
+ MeshVertexBufferEntry &entryData = mesh.m_VertexBuffer.m_Entries.index(baseAddr, entry);
+ serializer.streamifyCharPointerOffset(entryData.m_NameOffset);
+ serializer.align();
+ }
+ serializer.streamify(mesh.m_VertexBuffer.m_Data);
+ serializer.align();
+ serializer.streamify(mesh.m_IndexBuffer.m_Data);
+ serializer.align();
+ serializer.streamify(mesh.m_Subsets);
+ serializer.align();
+ QT3DSIMP_FOREACH(entry, mesh.m_Subsets.size())
+ {
+ MeshSubset &theSubset = const_cast<MeshSubset &>(mesh.m_Subsets.index(baseAddr, entry));
+ serializer.streamify(theSubset.m_Name);
+ serializer.align();
+ }
+ serializer.streamify(mesh.m_Joints);
+ serializer.align();
+}
+
+struct TotallingSerializer
+{
+ QT3DSU32 m_NumBytes;
+ QT3DSU8 *m_BaseAddress;
+ TotallingSerializer(QT3DSU8 *inBaseAddr)
+ : m_NumBytes(0)
+ , m_BaseAddress(inBaseAddr)
+ {
+ }
+ template <typename TDataType>
+ void streamify(const SOffsetDataRef<TDataType> &data)
+ {
+ m_NumBytes += data.size() * sizeof(TDataType);
+ }
+ void streamify(const char *data)
+ {
+ if (data == NULL)
+ data = "";
+ QT3DSU32 len = (QT3DSU32)strlen(data) + 1;
+ m_NumBytes += 4;
+ m_NumBytes += len;
+ }
+ void streamifyCharPointerOffset(QT3DSU32 inOffset)
+ {
+ if (inOffset) {
+ const char *dataPtr = (const char *)(inOffset + m_BaseAddress);
+ streamify(dataPtr);
+ } else
+ streamify("");
+ }
+ bool needsAlignment() const { return getAlignmentAmount() > 0; }
+ QT3DSU32 getAlignmentAmount() const { return 4 - (m_NumBytes % 4); }
+ void align()
+ {
+ if (needsAlignment())
+ m_NumBytes += getAlignmentAmount();
+ }
+};
+
+struct ByteWritingSerializer
+{
+ IOutStream &m_Stream;
+ TotallingSerializer m_ByteCounter;
+ QT3DSU8 *m_BaseAddress;
+ ByteWritingSerializer(IOutStream &str, QT3DSU8 *inBaseAddress)
+ : m_Stream(str)
+ , m_ByteCounter(inBaseAddress)
+ , m_BaseAddress(inBaseAddress)
+ {
+ }
+
+ template <typename TDataType>
+ void streamify(const SOffsetDataRef<TDataType> &data)
+ {
+ m_ByteCounter.streamify(data);
+ m_Stream.Write(data.begin(m_BaseAddress), data.size());
+ }
+ void streamify(const char *data)
+ {
+ m_ByteCounter.streamify(data);
+ if (data == NULL)
+ data = "";
+ QT3DSU32 len = (QT3DSU32)strlen(data) + 1;
+ m_Stream.Write(len);
+ m_Stream.Write(data, len);
+ }
+ void streamifyCharPointerOffset(QT3DSU32 inOffset)
+ {
+ const char *dataPtr = (const char *)(inOffset + m_BaseAddress);
+ streamify(dataPtr);
+ }
+
+ void align()
+ {
+ if (m_ByteCounter.needsAlignment()) {
+ QT3DSU8 buffer[] = { 0, 0, 0, 0 };
+ m_Stream.Write(buffer, m_ByteCounter.getAlignmentAmount());
+ m_ByteCounter.align();
+ }
+ }
+};
+
+struct MemoryAssigningSerializer
+{
+ QT3DSU8 *m_Memory;
+ QT3DSU8 *m_BaseAddress;
+ QT3DSU32 m_Size;
+ TotallingSerializer m_ByteCounter;
+ bool m_Failure;
+ MemoryAssigningSerializer(QT3DSU8 *data, QT3DSU32 size, QT3DSU32 startOffset)
+ : m_Memory(data + startOffset)
+ , m_BaseAddress(data)
+ , m_Size(size)
+ , m_ByteCounter(data)
+ , m_Failure(false)
+ {
+ // We expect 4 byte aligned memory to begin with
+ QT3DS_ASSERT((((size_t)m_Memory) % 4) == 0);
+ }
+
+ template <typename TDataType>
+ void streamify(const SOffsetDataRef<TDataType> &_data)
+ {
+ SOffsetDataRef<TDataType> &data = const_cast<SOffsetDataRef<TDataType> &>(_data);
+ if (m_Failure) {
+ data.m_Size = 0;
+ data.m_Offset = 0;
+ return;
+ }
+ QT3DSU32 current = m_ByteCounter.m_NumBytes;
+ m_ByteCounter.streamify(_data);
+ if (m_ByteCounter.m_NumBytes > m_Size) {
+ data.m_Size = 0;
+ data.m_Offset = 0;
+ m_Failure = true;
+ return;
+ }
+ QT3DSU32 numBytes = m_ByteCounter.m_NumBytes - current;
+ if (numBytes) {
+ data.m_Offset = (QT3DSU32)(m_Memory - m_BaseAddress);
+ updateMemoryBuffer(numBytes);
+ } else {
+ data.m_Offset = 0;
+ data.m_Size = 0;
+ }
+ }
+ void streamify(const char *&_data)
+ {
+ QT3DSU32 len;
+ m_ByteCounter.m_NumBytes += 4;
+ if (m_ByteCounter.m_NumBytes > m_Size) {
+ _data = "";
+ m_Failure = true;
+ return;
+ }
+ qt3ds::intrinsics::memCopy(&len, m_Memory, 4);
+ updateMemoryBuffer(4);
+ m_ByteCounter.m_NumBytes += len;
+ if (m_ByteCounter.m_NumBytes > m_Size) {
+ _data = "";
+ m_Failure = true;
+ return;
+ }
+ _data = (const char *)m_Memory;
+ updateMemoryBuffer(len);
+ }
+ void streamifyCharPointerOffset(QT3DSU32 &inOffset)
+ {
+ const char *dataPtr;
+ streamify(dataPtr);
+ inOffset = (QT3DSU32)(dataPtr - (const char *)m_BaseAddress);
+ }
+ void align()
+ {
+ if (m_ByteCounter.needsAlignment()) {
+ QT3DSU32 numBytes = m_ByteCounter.getAlignmentAmount();
+ m_ByteCounter.align();
+ updateMemoryBuffer(numBytes);
+ }
+ }
+ void updateMemoryBuffer(QT3DSU32 numBytes) { m_Memory += numBytes; }
+};
+
+inline QT3DSU32 GetMeshDataSize(Mesh &mesh)
+{
+ TotallingSerializer s(reinterpret_cast<QT3DSU8 *>(&mesh));
+ Serialize(s, mesh);
+ return s.m_NumBytes;
+}
+
+template <typename TDataType>
+QT3DSU32 NextIndex(const QT3DSU8 *inBaseAddress, const SOffsetDataRef<QT3DSU8> data, QT3DSU32 idx)
+{
+ QT3DSU32 numItems = data.size() / sizeof(TDataType);
+ if (idx < numItems) {
+ const TDataType *dataPtr(reinterpret_cast<const TDataType *>(data.begin(inBaseAddress)));
+ return dataPtr[idx];
+ } else {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+}
+
+template <typename TDataType>
+QT3DSU32 NextIndex(NVConstDataRef<QT3DSU8> data, QT3DSU32 idx)
+{
+ QT3DSU32 numItems = data.size() / sizeof(TDataType);
+ if (idx < numItems) {
+ const TDataType *dataPtr(reinterpret_cast<const TDataType *>(data.begin()));
+ return dataPtr[idx];
+ } else {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+}
+
+inline QT3DSU32 NextIndex(NVConstDataRef<QT3DSU8> inData,
+ qt3ds::render::NVRenderComponentTypes::Enum inCompType, QT3DSU32 idx)
+{
+ if (inData.size() == 0)
+ return idx;
+ switch (inCompType) {
+ case NVRenderComponentTypes::QT3DSU8:
+ return NextIndex<QT3DSU8>(inData, idx);
+ case NVRenderComponentTypes::QT3DSI8:
+ return NextIndex<QT3DSI8>(inData, idx);
+ case NVRenderComponentTypes::QT3DSU16:
+ return NextIndex<QT3DSU16>(inData, idx);
+ case NVRenderComponentTypes::QT3DSI16:
+ return NextIndex<QT3DSI16>(inData, idx);
+ case NVRenderComponentTypes::QT3DSU32:
+ return NextIndex<QT3DSU32>(inData, idx);
+ case NVRenderComponentTypes::QT3DSI32:
+ return NextIndex<QT3DSI32>(inData, idx);
+ }
+ // Invalid index buffer index type.
+ QT3DS_ASSERT(false);
+ return 0;
+}
+
+template <typename TMeshType>
+// Not exposed to the outside world
+TMeshType *DoInitialize(MeshBufHeaderFlags /*meshFlags*/, NVDataRef<QT3DSU8> data)
+{
+ QT3DSU8 *newMem = data.begin();
+ QT3DSU32 amountLeft = data.size() - sizeof(TMeshType);
+ MemoryAssigningSerializer s(newMem, amountLeft, sizeof(TMeshType));
+ TMeshType *retval = (TMeshType *)newMem;
+ Serialize(s, *retval);
+ if (s.m_Failure)
+ return NULL;
+ return retval;
+}
+}
+
+NVBounds3 Mesh::CalculateSubsetBounds(const NVRenderVertexBufferEntry &inEntry,
+ NVConstDataRef<QT3DSU8> inVertxData, QT3DSU32 inStride,
+ NVConstDataRef<QT3DSU8> inIndexData,
+ qt3ds::render::NVRenderComponentTypes::Enum inIndexCompType,
+ QT3DSU32 inSubsetCount, QT3DSU32 inSubsetOffset)
+{
+ NVBounds3 retval(NVBounds3::empty());
+ const NVRenderVertexBufferEntry &entry(inEntry);
+ if (entry.m_ComponentType != NVRenderComponentTypes::QT3DSF32 || entry.m_NumComponents != 3) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+
+ const QT3DSU8 *beginPtr = inVertxData.begin();
+ QT3DSU32 numBytes = inVertxData.size();
+ QT3DSU32 dataStride = inStride;
+ QT3DSU32 posOffset = entry.m_FirstItemOffset;
+ // The loop below could be template specialized *if* we wanted to do this.
+ // and the perf of the existing loop was determined to be a problem.
+ // Else I would rather stay way from the template specialization.
+ QT3DSIMP_FOREACH(idx, inSubsetCount)
+ {
+ QT3DSU32 dataIdx = NextIndex(inIndexData, inIndexCompType, idx + inSubsetOffset);
+ QT3DSU32 finalOffset = (dataIdx * dataStride) + posOffset;
+ if (finalOffset + sizeof(QT3DSVec3) <= numBytes) {
+ const QT3DSU8 *dataPtr = beginPtr + finalOffset;
+ retval.include(*reinterpret_cast<const QT3DSVec3 *>(dataPtr));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ return retval;
+}
+
+void Mesh::Save(IOutStream &outStream) const
+{
+ Mesh &mesh(const_cast<Mesh &>(*this));
+ QT3DSU8 *baseAddress = reinterpret_cast<QT3DSU8 *>(&mesh);
+ QT3DSU32 numBytes = sizeof(Mesh) + GetMeshDataSize(mesh);
+ MeshDataHeader header(numBytes);
+ outStream.Write(header);
+ outStream.Write(*this);
+ ByteWritingSerializer writer(outStream, baseAddress);
+ Serialize(writer, mesh);
+}
+
+wchar_t g_DefaultName[] = { 0 };
+
+const wchar_t *Mesh::s_DefaultName = g_DefaultName;
+
+template <typename TMeshType>
+struct SubsetNameHandler
+{
+};
+
+template <>
+struct SubsetNameHandler<MeshV1>
+{
+ void AssignName(const QT3DSU8 * /*v1BaseAddress*/, const MeshSubsetV1 & /*mesh*/,
+ QT3DSU8 * /*baseAddress*/, QT3DSU8 *& /*nameBuffer*/, MeshSubset &outDest)
+ {
+ outDest.m_Name = SOffsetDataRef<char16_t>();
+ }
+ QT3DSU32 NameLength(const MeshSubsetV1 &) { return 0; }
+};
+
+using qt3ds::intrinsics::memCopy;
+
+template <>
+struct SubsetNameHandler<MeshV2>
+{
+ void AssignName(const QT3DSU8 *v2BaseAddress, const MeshSubsetV2 &mesh, QT3DSU8 *baseAddress,
+ QT3DSU8 *&nameBuffer, MeshSubset &outDest)
+ {
+ outDest.m_Name.m_Size = mesh.m_Name.m_Size;
+ outDest.m_Name.m_Offset = (QT3DSU32)(nameBuffer - baseAddress);
+ QT3DSU32 dtypeSize = mesh.m_Name.m_Size * 2;
+ memCopy(nameBuffer, mesh.m_Name.begin(v2BaseAddress), dtypeSize);
+ nameBuffer += dtypeSize;
+ }
+ QT3DSU32 NameLength(const MeshSubsetV2 &mesh) { return (mesh.m_Name.size() + 1) * 2; }
+};
+
+QT3DSU32 GetAlignedOffset(QT3DSU32 offset, QT3DSU32 align)
+{
+ QT3DSU32 leftover = offset % align;
+ if (leftover)
+ return offset + (align - leftover);
+ return offset;
+}
+
+template <typename TPreviousMeshType>
+Mesh *CreateMeshFromPreviousMesh(TPreviousMeshType *temp, NVAllocatorCallback &alloc)
+{
+ QT3DSU32 newMeshSize = sizeof(Mesh);
+ QT3DSU8 *tempBaseAddress = reinterpret_cast<QT3DSU8 *>(temp);
+ QT3DSU32 alignment = sizeof(void *);
+
+ QT3DSU32 vertBufferSize = GetAlignedOffset(temp->m_VertexBuffer.m_Data.size(), alignment);
+ newMeshSize += vertBufferSize;
+ QT3DSU32 entryDataSize = temp->m_VertexBuffer.m_Entries.size() * sizeof(MeshVertexBufferEntry);
+ newMeshSize += entryDataSize;
+ QT3DSU32 indexBufferSize = GetAlignedOffset(temp->m_IndexBuffer.m_Data.size(), alignment);
+ newMeshSize += indexBufferSize;
+ QT3DSU32 entryNameSize = 0;
+ for (QT3DSU32 entryIdx = 0, entryEnd = temp->m_VertexBuffer.m_Entries.size(); entryIdx < entryEnd;
+ ++entryIdx) {
+ const qt3ds::render::NVRenderVertexBufferEntry theEntry =
+ temp->m_VertexBuffer.m_Entries.index(tempBaseAddress, entryIdx)
+ .ToVertexBufferEntry(tempBaseAddress);
+ const char *namePtr = theEntry.m_Name;
+ if (namePtr == NULL)
+ namePtr = "";
+
+ entryNameSize += (QT3DSU32)strlen(theEntry.m_Name) + 1;
+ }
+ entryNameSize = GetAlignedOffset(entryNameSize, alignment);
+
+ newMeshSize += entryNameSize;
+ QT3DSU32 subsetBufferSize = temp->m_Subsets.size() * sizeof(MeshSubset);
+ newMeshSize += subsetBufferSize;
+ QT3DSU32 nameLength = 0;
+ for (QT3DSU32 subsetIdx = 0, subsetEnd = temp->m_Subsets.size(); subsetIdx < subsetEnd;
+ ++subsetIdx) {
+ nameLength += SubsetNameHandler<TPreviousMeshType>().NameLength(
+ temp->m_Subsets.index(tempBaseAddress, subsetIdx));
+ }
+ nameLength = GetAlignedOffset(nameLength, alignment);
+
+ newMeshSize += nameLength;
+
+ Mesh *retval = (Mesh *)alloc.allocate(newMeshSize, "TempData", __FILE__, __LINE__);
+ new (retval) Mesh();
+ QT3DSU8 *baseOffset = reinterpret_cast<QT3DSU8 *>(retval);
+ QT3DSU8 *vertBufferData = baseOffset + sizeof(Mesh);
+ QT3DSU8 *entryBufferData = vertBufferData + vertBufferSize;
+ QT3DSU8 *entryNameBuffer = entryBufferData + entryDataSize;
+ QT3DSU8 *indexBufferData = entryNameBuffer + entryNameSize;
+ QT3DSU8 *subsetBufferData = indexBufferData + indexBufferSize;
+ QT3DSU8 *nameData = subsetBufferData + subsetBufferSize;
+
+ retval->m_DrawMode = temp->m_DrawMode;
+ retval->m_Winding = temp->m_Winding;
+ retval->m_VertexBuffer = temp->m_VertexBuffer;
+ retval->m_VertexBuffer.m_Data.m_Offset = (QT3DSU32)(vertBufferData - baseOffset);
+ retval->m_VertexBuffer.m_Entries.m_Offset = (QT3DSU32)(entryBufferData - baseOffset);
+ memCopy(vertBufferData, temp->m_VertexBuffer.m_Data.begin(tempBaseAddress),
+ temp->m_VertexBuffer.m_Data.size());
+ memCopy(entryBufferData, temp->m_VertexBuffer.m_Entries.begin(tempBaseAddress), entryDataSize);
+ QT3DSIMP_FOREACH(idx, temp->m_VertexBuffer.m_Entries.size())
+ {
+ const MeshVertexBufferEntry &src =
+ temp->m_VertexBuffer.m_Entries.index(tempBaseAddress, idx);
+ MeshVertexBufferEntry &dest = retval->m_VertexBuffer.m_Entries.index(baseOffset, idx);
+
+ const char *targetName = reinterpret_cast<const char *>(src.m_NameOffset + tempBaseAddress);
+ if (src.m_NameOffset == 0)
+ targetName = "";
+ QT3DSU32 nameLen = (QT3DSU32)strlen(targetName) + 1;
+ dest.m_NameOffset = (QT3DSU32)(entryNameBuffer - baseOffset);
+ memCopy(entryNameBuffer, targetName, nameLen);
+ entryNameBuffer += nameLen;
+ }
+
+ retval->m_IndexBuffer = temp->m_IndexBuffer;
+ retval->m_IndexBuffer.m_Data.m_Offset = (QT3DSU32)(indexBufferData - baseOffset);
+ memCopy(indexBufferData, temp->m_IndexBuffer.m_Data.begin(tempBaseAddress),
+ temp->m_IndexBuffer.m_Data.size());
+
+ retval->m_Subsets.m_Size = temp->m_Subsets.m_Size;
+ retval->m_Subsets.m_Offset = (QT3DSU32)(subsetBufferData - baseOffset);
+ QT3DSIMP_FOREACH(idx, temp->m_Subsets.size())
+ {
+ MeshSubset &dest = const_cast<MeshSubset &>(retval->m_Subsets.index(baseOffset, idx));
+ const typename TPreviousMeshType::TSubsetType &src =
+ temp->m_Subsets.index(tempBaseAddress, idx);
+ dest.m_Count = src.m_Count;
+ dest.m_Offset = src.m_Offset;
+ dest.m_Bounds = src.m_Bounds;
+ SubsetNameHandler<TPreviousMeshType>().AssignName(tempBaseAddress, src, baseOffset,
+ nameData, dest);
+ }
+ alloc.deallocate(temp);
+ return retval;
+}
+
+Mesh *Mesh::Load(NVAllocatorCallback &alloc, IInStream &inStream)
+{
+ MeshDataHeader header;
+ inStream.Read(header);
+ QT3DS_ASSERT(header.m_FileId == MeshDataHeader::GetFileId());
+ if (header.m_FileId != MeshDataHeader::GetFileId())
+ return NULL;
+ if (header.m_FileVersion < 1 || header.m_FileVersion > MeshDataHeader::GetCurrentFileVersion())
+ return NULL;
+ if (header.m_SizeInBytes < sizeof(Mesh))
+ return NULL;
+ QT3DSU8 *newMem = (QT3DSU8 *)alloc.allocate(header.m_SizeInBytes, "Mesh", __FILE__, __LINE__);
+ QT3DSU32 amountRead = inStream.Read(NVDataRef<QT3DSU8>(newMem, header.m_SizeInBytes));
+ if (amountRead != header.m_SizeInBytes)
+ goto failure;
+
+ if (header.m_FileVersion == 1) {
+ MeshV1 *temp = DoInitialize<MeshV1>(header.m_HeaderFlags,
+ NVDataRef<QT3DSU8>(newMem, header.m_SizeInBytes));
+ if (temp == NULL)
+ goto failure;
+ return CreateMeshFromPreviousMesh(temp, alloc);
+
+ } else if (header.m_FileVersion == 2) {
+ MeshV2 *temp = DoInitialize<MeshV2>(header.m_HeaderFlags,
+ NVDataRef<QT3DSU8>(newMem, header.m_SizeInBytes));
+ if (temp == NULL)
+ goto failure;
+ return CreateMeshFromPreviousMesh(temp, alloc);
+ } else {
+ Mesh *retval = Initialize(header.m_FileVersion, header.m_HeaderFlags,
+ NVDataRef<QT3DSU8>(newMem, header.m_SizeInBytes));
+ if (retval == NULL)
+ goto failure;
+ return retval;
+ }
+
+failure:
+ QT3DS_ASSERT(false);
+ alloc.deallocate(newMem);
+ return NULL;
+}
+
+Mesh *Mesh::Initialize(QT3DSU16 meshVersion, MeshBufHeaderFlags meshFlags, NVDataRef<QT3DSU8> data)
+{
+ if (meshVersion != MeshDataHeader::GetCurrentFileVersion())
+ return NULL;
+ return DoInitialize<Mesh>(meshFlags, data);
+}
+
+// Multimesh support where you have multiple meshes in a single file.
+// Save multi where you have overridden the allocator.
+QT3DSU32 Mesh::SaveMulti(NVAllocatorCallback &alloc, ISeekableIOStream &inStream, QT3DSU32 inId) const
+{
+ QT3DSU32 nextId = 1;
+ MeshMultiHeader tempHeader;
+ MeshMultiHeader *theHeader = NULL;
+ MeshMultiHeader *theWriteHeader = NULL;
+
+ QT3DSI64 newMeshStartPos = 0;
+ if (inStream.GetLength() != 0) {
+ theHeader = LoadMultiHeader(alloc, inStream);
+ if (theHeader == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ QT3DSU8 *headerBaseAddr = reinterpret_cast<QT3DSU8 *>(theHeader);
+ for (QT3DSU32 idx = 0, end = theHeader->m_Entries.size(); idx < end; ++idx) {
+ if (inId != 0) {
+ QT3DS_ASSERT(inId != theHeader->m_Entries.index(headerBaseAddr, idx).m_MeshId);
+ }
+ nextId = NVMax(nextId, theHeader->m_Entries.index(headerBaseAddr, idx).m_MeshId + 1);
+ }
+ newMeshStartPos =
+ sizeof(MeshMultiHeader) + theHeader->m_Entries.size() * sizeof(MeshMultiEntry);
+ theWriteHeader = theHeader;
+ } else
+ theWriteHeader = &tempHeader;
+
+ inStream.SetPosition(-newMeshStartPos, SeekPosition::End);
+ QT3DSI64 meshOffset = inStream.GetPosition();
+
+ Save(inStream);
+
+ if (inId != 0)
+ nextId = inId;
+ QT3DSU8 *theWriteBaseAddr = reinterpret_cast<QT3DSU8 *>(theWriteHeader);
+ // Now write a new header out.
+ inStream.Write(theWriteHeader->m_Entries.begin(theWriteBaseAddr),
+ theWriteHeader->m_Entries.size());
+ MeshMultiEntry newEntry(static_cast<QT3DSI64>(meshOffset), nextId);
+ inStream.Write(newEntry);
+ theWriteHeader->m_Entries.m_Size++;
+ inStream.Write(*theWriteHeader);
+
+ if (theHeader != NULL) {
+ alloc.deallocate(theHeader);
+ }
+ return static_cast<QT3DSU32>(nextId);
+}
+
+// Load a single mesh directly from a multi file with the provided overridden items
+SMultiLoadResult Mesh::LoadMulti(NVAllocatorCallback &alloc, ISeekableIOStream &inStream,
+ QT3DSU32 inId)
+{
+ MeshMultiHeader *theHeader(LoadMultiHeader(alloc, inStream));
+ if (theHeader == NULL) {
+ return SMultiLoadResult();
+ }
+ QT3DSU64 fileOffset = (QT3DSU64)-1;
+ QT3DSU32 theId = inId;
+ QT3DSU8 *theHeaderBaseAddr = reinterpret_cast<QT3DSU8 *>(theHeader);
+ bool foundMesh = false;
+ for (QT3DSU32 idx = 0, end = theHeader->m_Entries.size(); idx < end && !foundMesh; ++idx) {
+ const MeshMultiEntry &theEntry(theHeader->m_Entries.index(theHeaderBaseAddr, idx));
+ if (theEntry.m_MeshId == inId || (inId == 0 && theEntry.m_MeshId > theId)) {
+ if (theEntry.m_MeshId == inId)
+ foundMesh = true;
+ theId = NVMax(theId, (QT3DSU32)theEntry.m_MeshId);
+ fileOffset = theEntry.m_MeshOffset;
+ }
+ }
+ Mesh *retval = NULL;
+ if (fileOffset == (QT3DSU64)-1) {
+ goto endFunction;
+ }
+
+ inStream.SetPosition(static_cast<QT3DSI64>(fileOffset), SeekPosition::Begin);
+ retval = Load(alloc, inStream);
+endFunction:
+ if (theHeader != NULL)
+ alloc.deallocate(theHeader);
+ return SMultiLoadResult(retval, theId);
+}
+
+// Returns true if this is a multimesh (several meshes in one file).
+bool Mesh::IsMulti(ISeekableIOStream &inStream)
+{
+ MeshMultiHeader theHeader;
+ inStream.SetPosition(-((QT3DSI64)(sizeof(MeshMultiHeader))), SeekPosition::End);
+ QT3DSU32 numBytes = inStream.Read(theHeader);
+ if (numBytes != sizeof(MeshMultiHeader))
+ return false;
+ return theHeader.m_Version == MeshMultiHeader::GetMultiStaticFileId();
+}
+// Load a multi header from a stream.
+MeshMultiHeader *Mesh::LoadMultiHeader(NVAllocatorCallback &alloc, ISeekableIOStream &inStream)
+{
+ MeshMultiHeader theHeader;
+ inStream.SetPosition(-((QT3DSI64)sizeof(MeshMultiHeader)), SeekPosition::End);
+ QT3DSU32 numBytes = inStream.Read(theHeader);
+ if (numBytes != sizeof(MeshMultiHeader)
+ || theHeader.m_FileId != MeshMultiHeader::GetMultiStaticFileId()
+ || theHeader.m_Version > MeshMultiHeader::GetMultiStaticVersion()) {
+ return NULL;
+ }
+ size_t allocSize =
+ sizeof(MeshMultiHeader) + theHeader.m_Entries.m_Size * sizeof(MeshMultiEntry);
+ MeshMultiHeader *retval =
+ (MeshMultiHeader *)alloc.allocate(allocSize, "MeshMultiHeader", __FILE__, __LINE__);
+ if (retval == NULL) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ QT3DSU8 *baseAddr = reinterpret_cast<QT3DSU8 *>(retval);
+ QT3DSU8 *entryData = baseAddr + sizeof(MeshMultiHeader);
+ *retval = theHeader;
+ retval->m_Entries.m_Offset = (QT3DSU32)(entryData - baseAddr);
+ inStream.SetPosition(-((QT3DSI64)allocSize), SeekPosition::End);
+
+ numBytes =
+ inStream.Read(reinterpret_cast<MeshMultiEntry *>(entryData), retval->m_Entries.m_Size);
+ if (numBytes != retval->m_Entries.m_Size * sizeof(MeshMultiEntry)) {
+ QT3DS_ASSERT(false);
+ alloc.deallocate(retval);
+ retval = NULL;
+ }
+ return retval;
+}
+
+QT3DSU32 GetHighestId(NVAllocatorCallback &inAlloc, MeshMultiHeader *inHeader)
+{
+ if (inHeader == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ QT3DSU8 *baseHeaderAddr = reinterpret_cast<QT3DSU8 *>(inHeader);
+ QT3DSU32 highestId = 0;
+ for (QT3DSU32 idx = 0, end = inHeader->m_Entries.size(); idx < end; ++idx)
+ highestId = NVMax(highestId, inHeader->m_Entries.index(baseHeaderAddr, idx).m_MeshId);
+ inAlloc.deallocate(inHeader);
+ return highestId;
+}
+
+QT3DSU32 Mesh::GetHighestMultiVersion(NVAllocatorCallback &alloc, ISeekableIOStream &inStream)
+{
+ return GetHighestId(alloc, LoadMultiHeader(alloc, inStream));
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportMesh.h b/src/Authoring/UICIMP/UICImportLib/UICImportMesh.h
new file mode 100644
index 00000000..a5f57b58
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportMesh.h
@@ -0,0 +1,529 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTMESHH
+#define UICIMPORTMESHH
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/IOStreams.h"
+
+namespace UICIMP {
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::render;
+template <typename TDataType>
+struct SOffsetDataRef
+{
+ QT3DSU32 m_Offset;
+ QT3DSU32 m_Size;
+ SOffsetDataRef()
+ : m_Offset(0)
+ , m_Size(0)
+ {
+ }
+ TDataType *begin(QT3DSU8 *inBase) { return reinterpret_cast<TDataType *>(inBase + m_Offset); }
+ TDataType *end(QT3DSU8 *inBase) { return begin(inBase) + m_Size; }
+ const TDataType *begin(const QT3DSU8 *inBase) const
+ {
+ return reinterpret_cast<const TDataType *>(inBase + m_Offset);
+ }
+ const TDataType *end(const QT3DSU8 *inBase) const { return begin(inBase) + m_Size; }
+ QT3DSU32 size() const { return m_Size; }
+ bool empty() const { return m_Size == 0; }
+ TDataType &index(QT3DSU8 *inBase, QT3DSU32 idx)
+ {
+ QT3DS_ASSERT(idx < m_Size);
+ return begin(inBase)[idx];
+ }
+ const TDataType &index(const QT3DSU8 *inBase, QT3DSU32 idx) const
+ {
+ QT3DS_ASSERT(idx < m_Size);
+ return begin(inBase)[idx];
+ }
+};
+
+struct MeshVertexBufferEntry
+{
+ QT3DSU32 m_NameOffset;
+ /** Datatype of the this entry points to in the buffer */
+ NVRenderComponentTypes::Enum m_ComponentType;
+ /** Number of components of each data member. 1,2,3, or 4. Don't be stupid.*/
+ QT3DSU32 m_NumComponents;
+ /** Offset from the beginning of the buffer of the first item */
+ QT3DSU32 m_FirstItemOffset;
+ MeshVertexBufferEntry()
+ : m_NameOffset(0)
+ , m_ComponentType(NVRenderComponentTypes::QT3DSF32)
+ , m_NumComponents(3)
+ , m_FirstItemOffset(0)
+ {
+ }
+ NVRenderVertexBufferEntry ToVertexBufferEntry(QT3DSU8 *inBaseAddress)
+ {
+ const char *nameBuffer = "";
+ if (m_NameOffset)
+ nameBuffer = reinterpret_cast<const char *>(inBaseAddress + m_NameOffset);
+ return NVRenderVertexBufferEntry(nameBuffer, m_ComponentType, m_NumComponents,
+ m_FirstItemOffset);
+ }
+};
+
+struct VertexBuffer
+{
+ SOffsetDataRef<MeshVertexBufferEntry> m_Entries;
+ QT3DSU32 m_Stride;
+ SOffsetDataRef<QT3DSU8> m_Data;
+ VertexBuffer(SOffsetDataRef<MeshVertexBufferEntry> entries, QT3DSU32 stride,
+ SOffsetDataRef<QT3DSU8> data)
+ : m_Entries(entries)
+ , m_Stride(stride)
+ , m_Data(data)
+ {
+ }
+ VertexBuffer()
+ : m_Stride(0)
+ {
+ }
+};
+
+struct IndexBuffer
+{
+ // Component types must be either QT3DSU16 or QT3DSU8 in order for the
+ // graphics hardware to deal with the buffer correctly.
+ NVRenderComponentTypes::Enum m_ComponentType;
+ SOffsetDataRef<QT3DSU8> m_Data;
+ // Either QT3DSU8 or QT3DSU16 component types are allowed by the underlying rendering
+ // system, so you would be wise to stick with those.
+ IndexBuffer(NVRenderComponentTypes::Enum compType, SOffsetDataRef<QT3DSU8> data)
+ : m_ComponentType(compType)
+ , m_Data(data)
+ {
+ }
+ IndexBuffer()
+ : m_ComponentType(NVRenderComponentTypes::Unknown)
+ {
+ }
+};
+
+template <QT3DSU32 TNumBytes>
+struct MeshPadding
+{
+ QT3DSU8 m_Padding[TNumBytes];
+ MeshPadding() { memZero(m_Padding, TNumBytes); }
+};
+
+struct MeshSubset
+{
+ // QT3DS_MAX_U32 means use all available items
+ QT3DSU32 m_Count;
+ // Offset is in item size, not bytes.
+ QT3DSU32 m_Offset;
+ // Bounds of this subset. This is filled in by the builder
+ // see AddMeshSubset
+ NVBounds3 m_Bounds;
+
+ // Subsets have to be named else artists will be unable to use
+ // a mesh with multiple subsets as they won't have any idea
+ // while part of the model a given mesh actually maps to.
+ SOffsetDataRef<char16_t> m_Name;
+
+ MeshSubset(QT3DSU32 count, QT3DSU32 off, const NVBounds3 &bounds, SOffsetDataRef<char16_t> inName)
+ : m_Count(count)
+ , m_Offset(off)
+ , m_Bounds(bounds)
+ , m_Name(inName)
+ {
+ }
+ MeshSubset()
+ : m_Count((QT3DSU32)-1)
+ , m_Offset(0)
+ , m_Bounds(NVBounds3::empty())
+ {
+ }
+ bool HasCount() const { return m_Count != QT3DS_MAX_U32; }
+};
+
+// Placeholder for bitflags in the mesh header.
+struct MeshBufHeaderFlagValues
+{
+ enum Enum {};
+};
+
+struct MeshBufHeaderFlags : NVFlags<MeshBufHeaderFlagValues::Enum, QT3DSU16>
+{
+ MeshBufHeaderFlags() {}
+ MeshBufHeaderFlags(QT3DSU16 value)
+ : NVFlags<MeshBufHeaderFlagValues::Enum, QT3DSU16>(value)
+ {
+ }
+ // Binary or creates an integer.
+ MeshBufHeaderFlags(int value)
+ : NVFlags<MeshBufHeaderFlagValues::Enum, QT3DSU16>((QT3DSU16)value)
+ {
+ }
+};
+
+struct MeshDataHeader
+{
+ static QT3DSU32 GetFileId() { return (QT3DSU32)-929005747; }
+ static QT3DSU16 GetCurrentFileVersion() { return 3; }
+ QT3DSU32 m_FileId;
+ QT3DSU16 m_FileVersion;
+ MeshBufHeaderFlags m_HeaderFlags;
+ QT3DSU32 m_SizeInBytes;
+ MeshDataHeader(QT3DSU32 size = 0)
+ : m_FileId(GetFileId())
+ , m_FileVersion(GetCurrentFileVersion())
+ , m_SizeInBytes(size)
+ {
+ }
+};
+
+struct Joint
+{
+ QT3DSI32 m_JointID;
+ QT3DSI32 m_ParentID;
+ QT3DSF32 m_invBindPose[16];
+ QT3DSF32 m_localToGlobalBoneSpace[16];
+
+ Joint(QT3DSI32 jointID, QT3DSI32 parentID, const QT3DSF32 *invBindPose,
+ const QT3DSF32 *localToGlobalBoneSpace)
+ : m_JointID(jointID)
+ , m_ParentID(parentID)
+ {
+ ::memcpy(m_invBindPose, invBindPose, sizeof(float) * 16);
+ ::memcpy(m_localToGlobalBoneSpace, localToGlobalBoneSpace, sizeof(float) * 16);
+ }
+ Joint()
+ : m_JointID(-1)
+ , m_ParentID(-1)
+ {
+ ::memset(m_invBindPose, 0, sizeof(float) * 16);
+ ::memset(m_localToGlobalBoneSpace, 0, sizeof(float) * 16);
+ }
+};
+
+// Tells us what offset a mesh with this ID starts.
+struct MeshMultiEntry
+{
+ QT3DSU64 m_MeshOffset;
+ QT3DSU32 m_MeshId;
+ QT3DSU32 m_Padding;
+ MeshMultiEntry()
+ : m_MeshOffset(0)
+ , m_MeshId(0)
+ , m_Padding(0)
+ {
+ }
+ MeshMultiEntry(QT3DSU64 mo, QT3DSU32 meshId)
+ : m_MeshOffset(mo)
+ , m_MeshId(meshId)
+ , m_Padding(0)
+ {
+ }
+};
+
+// The multi headers are actually saved at the end of the file.
+// Thus when you append to the file we overwrite the last header
+// then write out a new header structure.
+// The last 8 bytes of the file contain the multi header.
+// The previous N*8 bytes contain the mesh entries.
+struct MeshMultiHeader
+{
+ QT3DSU32 m_FileId;
+ QT3DSU32 m_Version;
+ SOffsetDataRef<MeshMultiEntry> m_Entries;
+ static QT3DSU32 GetMultiStaticFileId() { return (QT3DSU32)555777497; }
+ static QT3DSU32 GetMultiStaticVersion() { return 1; }
+
+ MeshMultiHeader()
+ : m_FileId(GetMultiStaticFileId())
+ , m_Version(GetMultiStaticVersion())
+ {
+ }
+};
+
+struct Mesh;
+
+// Result of a multi-load operation. This returns both the mesh
+// and the id of the mesh that was loaded.
+struct SMultiLoadResult
+{
+ Mesh *m_Mesh;
+ QT3DSU32 m_Id;
+ SMultiLoadResult(Mesh *inMesh, QT3DSU32 inId)
+ : m_Mesh(inMesh)
+ , m_Id(inId)
+ {
+ }
+ SMultiLoadResult()
+ : m_Mesh(NULL)
+ , m_Id(0)
+ {
+ }
+ operator Mesh *() { return m_Mesh; }
+};
+
+/**
+* A Mesh defines one vertex buffer layout, one or more logical vertex buffers
+* one index buffer, and a set of defined draw calls (subsets).
+*
+* The vertex buffer data is held together continguously and the layout cannot
+* change. There can be several actual vertex buffers on the card, however, in order
+* to facilitate using index buffer components of smaller component sizes than there
+* are actual vertex buffer data entries. For instance, you may have a very large vertex
+* buffer, larger than 64 K but openglES has a restriction on the size of the index buffer
+*component
+* that it cannot be larger than two bytes per entry. So you would need to split the vertex
+*buffer
+* into multiple logical vertex buffers and adjust your indexes such that you indexed into
+* only one logical vertex buffer per draw call.
+*
+* No logical vertex buffers means that the vertex buffer index on a mesh subset will be
+*ignored.
+*/
+struct Mesh
+{
+ static const wchar_t *s_DefaultName;
+
+ VertexBuffer m_VertexBuffer;
+ IndexBuffer m_IndexBuffer;
+ SOffsetDataRef<MeshSubset> m_Subsets;
+ SOffsetDataRef<Joint> m_Joints;
+ NVRenderDrawMode::Enum m_DrawMode;
+ NVRenderWinding::Enum m_Winding;
+
+ Mesh()
+ : m_DrawMode(NVRenderDrawMode::Triangles)
+ , m_Winding(NVRenderWinding::CounterClockwise)
+ {
+ }
+ Mesh(VertexBuffer vbuf, IndexBuffer ibuf, const SOffsetDataRef<MeshSubset> &insts,
+ const SOffsetDataRef<Joint> &joints,
+ NVRenderDrawMode::Enum drawMode = NVRenderDrawMode::Triangles,
+ NVRenderWinding::Enum winding = NVRenderWinding::CounterClockwise)
+ : m_VertexBuffer(vbuf)
+ , m_IndexBuffer(ibuf)
+ , m_Subsets(insts)
+ , m_Joints(joints)
+ , m_DrawMode(drawMode)
+ , m_Winding(winding)
+ {
+ }
+
+ QT3DSU8 *GetBaseAddress() { return reinterpret_cast<QT3DSU8 *>(this); }
+ const QT3DSU8 *GetBaseAddress() const { return reinterpret_cast<const QT3DSU8 *>(this); }
+
+ static const char *GetPositionAttrName() { return "attr_pos"; }
+ static const char *GetNormalAttrName() { return "attr_norm"; }
+ static const char *GetUVAttrName() { return "attr_uv0"; }
+ static const char *GetUV2AttrName() { return "attr_uv1"; }
+ static const char *GetTexTanAttrName() { return "attr_textan"; }
+ static const char *GetTexBinormalAttrName() { return "attr_binormal"; }
+ static const char *GetWeightAttrName() { return "attr_weight"; }
+ static const char *GetBoneIndexAttrName() { return "attr_boneid"; }
+
+ // Run through the vertex buffer items indicated by subset
+ // Assume vbuf entry[posEntryIndex] is the position entry
+ // This entry has to be QT3DSF32 and 3 components.
+ // Using this entry and the (possibly empty) index buffer
+ // along with the (possibly emtpy) logical vbuf data
+ // return a bounds of the given vertex buffer.
+ static NVBounds3 CalculateSubsetBounds(const NVRenderVertexBufferEntry &inEntry,
+ NVConstDataRef<QT3DSU8> inVertxData, QT3DSU32 inStride,
+ NVConstDataRef<QT3DSU8> inIndexData,
+ qt3ds::render::NVRenderComponentTypes::Enum inIndexCompType,
+ QT3DSU32 inSubsetCount, QT3DSU32 inSubsetOffset);
+
+ // Format is:
+ // MeshDataHeader
+ // mesh data.
+ void Save(IOutStream &outStream) const;
+
+ // Save a mesh using fopen and fwrite
+ bool Save(const char *inFilePath) const;
+
+ // read the header, then read the object.
+ // Object data is written in LE format for now.
+ // Free the new mesh by calling:
+ // alloc.deallocate( mesh );
+ // All the memory is allocated once and then pointers are back
+ // filled, so this will work.
+ static Mesh *Load(NVAllocatorCallback &alloc, IInStream &inStream);
+
+ // Load a mesh using fopen and fread
+ // Mesh needs to be freed by the caller using free
+ static Mesh *Load(const char *inFilePath);
+
+ // Create a mesh given this header, and that data. data.size() must match
+ // header.SizeInBytes. The mesh returned starts a data[0], so however data
+ // was allocated is how the mesh should be deallocated.
+ static Mesh *Initialize(QT3DSU16 meshVersion, MeshBufHeaderFlags meshFlags, NVDataRef<QT3DSU8> data);
+
+ // Multimesh support where you have multiple meshes in a single file.
+ // Save multi where you have overridden the allocator.
+ QT3DSU32 SaveMulti(NVAllocatorCallback &alloc, ISeekableIOStream &inStream, QT3DSU32 inId = 0) const;
+ // You can save multiple meshes in a file. Each mesh returns an incrementing
+ // integer for the multi file. The original meshes aren't changed, and the file
+ // is appended to.
+ QT3DSU32 SaveMulti(const char *inFilePath) const;
+
+ // Load a single mesh directly from a multi file with the provided overridden items
+ // Loading a multimesh with id == 0 indicates to just load the mesh with the highest id.
+ static SMultiLoadResult LoadMulti(NVAllocatorCallback &alloc, ISeekableIOStream &inStream,
+ QT3DSU32 inId = 0);
+ // Load a single mesh using c file API and malloc/free.
+ static SMultiLoadResult LoadMulti(const char *inFilePath, QT3DSU32 inId);
+ // Returns true if this is a multimesh (several meshes in one file).
+ static bool IsMulti(ISeekableIOStream &inStream);
+ // Load a multi header from a stream.
+ static MeshMultiHeader *LoadMultiHeader(NVAllocatorCallback &alloc,
+ ISeekableIOStream &inStream);
+ // Load a multi header from a file using malloc. Header needs to be freed using free.
+ static MeshMultiHeader *LoadMultiHeader(const char *inFilePath);
+
+ // Get the highest mesh version from a stream.
+ static QT3DSU32 GetHighestMultiVersion(NVAllocatorCallback &alloc, ISeekableIOStream &inStream);
+ // Get the highest mesh version from a file.
+ static QT3DSU32 GetHighestMultiVersion(const char *inFilePath);
+};
+
+struct ScopedMesh
+{
+ Mesh *m_Mesh;
+ NVAllocatorCallback *m_Callback;
+ ScopedMesh(Mesh *m, NVAllocatorCallback *cback = NULL)
+ : m_Mesh(m)
+ , m_Callback(cback)
+ {
+ }
+ ~ScopedMesh()
+ {
+ if (m_Mesh) {
+ if (m_Callback)
+ m_Callback->deallocate(m_Mesh);
+ else
+ free(m_Mesh);
+ }
+ }
+ Mesh *operator->() { return m_Mesh; }
+ operator Mesh *() { return m_Mesh; }
+};
+
+struct MeshBuilderVBufEntry
+{
+ const char *m_Name;
+ NVConstDataRef<QT3DSU8> m_Data;
+ NVRenderComponentTypes::Enum m_ComponentType;
+ QT3DSU32 m_NumComponents;
+ MeshBuilderVBufEntry()
+ : m_Name(NULL)
+ , m_ComponentType(NVRenderComponentTypes::Unknown)
+ , m_NumComponents(0)
+ {
+ }
+ MeshBuilderVBufEntry(const char *name, NVConstDataRef<QT3DSU8> data,
+ NVRenderComponentTypes::Enum componentType, QT3DSU32 numComponents)
+ : m_Name(name)
+ , m_Data(data)
+ , m_ComponentType(componentType)
+ , m_NumComponents(numComponents)
+ {
+ }
+};
+
+// Useful class to build up a mesh. Necessary since meshes don't include that
+// sort of utility.
+class MeshBuilder
+{
+protected:
+ virtual ~MeshBuilder() {}
+public:
+ virtual void Release() = 0;
+ virtual void Reset() = 0;
+ // Set the draw parameters for any subsets. Defaults to triangles and counter clockwise
+ virtual void SetDrawParameters(NVRenderDrawMode::Enum drawMode,
+ NVRenderWinding::Enum winding) = 0;
+ // Set the vertex buffer and have the mesh builder interleave the data for you
+ virtual bool SetVertexBuffer(NVConstDataRef<MeshBuilderVBufEntry> entries) = 0;
+ // Set the vertex buffer from interleaved data.
+ virtual void SetVertexBuffer(NVConstDataRef<NVRenderVertexBufferEntry> entries, QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> data) = 0;
+ // The builder (and the majority of the rest of the product) only supports unsigned 16 bit
+ // indexes
+ virtual void SetIndexBuffer(NVConstDataRef<QT3DSU8> data, NVRenderComponentTypes::Enum comp) = 0;
+ // Assets if the supplied parameters are out of range.
+ virtual void AddJoint(QT3DSI32 jointID, QT3DSI32 parentID, const QT3DSF32 *invBindPose,
+ const QT3DSF32 *localToGlobalBoneSpace) = 0;
+ /**
+ * Add a subset, which equates roughly to a draw call.
+ * A logical vertex buffer allows you to have more that 64K vertexes but still
+ * use u16 index buffers. In any case, if the mesh has an index buffer then this subset
+ * refers to that index buffer, else it is assumed to index into the vertex buffer.
+ * count and offset do exactly what they seem to do, while boundsPositionEntryIndex, if set to
+ * something other than QT3DS_MAX_U32, drives the calculation of the aa-bounds of the subset
+ * using mesh::CalculateSubsetBounds
+ */
+ virtual void AddMeshSubset(const wchar_t *inSubsetName = Mesh::s_DefaultName,
+ QT3DSU32 count = QT3DS_MAX_U32, QT3DSU32 offset = 0,
+ QT3DSU32 boundsPositionEntryIndex = QT3DS_MAX_U32) = 0;
+
+ virtual void AddMeshSubset(const wchar_t *inSubsetName, QT3DSU32 count, QT3DSU32 offset,
+ const NVBounds3 &inBounds) = 0;
+
+ // Call to optimize the index and vertex buffers. This doesn't change the subset information,
+ // each triangle is rendered precisely the same.
+ // It just orders the vertex data so we iterate through it as linearly as possible.
+ // This *only* works if the *entire* builder is using triangles as the draw mode. This will be
+ // a disaster if that
+ // condition is not met.
+ virtual void OptimizeMesh() = 0;
+
+ /**
+ * @brief This functions stitches together sub-meshes with the same material.
+ * This re-writes the index buffer
+ *
+ * @return no return.
+ */
+ virtual void ConnectSubMeshes() = 0;
+
+ // Return the current mesh. This is only good for this function call, item may change or be
+ // released
+ // due to any further function calls.
+ virtual Mesh &GetMesh() = 0;
+
+ // Uses new/delete.
+ static MeshBuilder &CreateMeshBuilder();
+};
+}
+
+#endif
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportMeshBuilder.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportMeshBuilder.cpp
new file mode 100644
index 00000000..7aa947f6
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportMeshBuilder.cpp
@@ -0,0 +1,599 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICImportLibPrecompile.h"
+#include "UICImportMesh.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "UICFileTools.h"
+#include "UICImportContainers.h"
+
+using namespace UICIMP;
+
+// Disable mesh optimization. TODO: After removing NvTriStrip need
+// to implement mesh optimization.
+//#define DISABLE_MESH_OPTIMIZATION 1
+
+// It turns out we can't enable vertex remapping because it would break
+// mesh morphing.
+#define DISABLE_VERTEX_REMAP 1
+
+namespace {
+template <typename TDataType>
+NVConstDataRef<TDataType> toRefBuf(QT3DSU8 *bufData, QT3DSU32 off, QT3DSU32 size)
+{
+ QT3DS_ASSERT(size % sizeof(TDataType) == 0);
+ if (size)
+ return NVConstDataRef<TDataType>((TDataType *)(bufData + off), size / sizeof(TDataType));
+ return NVConstDataRef<TDataType>();
+}
+struct DynamicVBuf
+{
+ QT3DSU32 m_Stride;
+ ImportArray<NVRenderVertexBufferEntry> m_VertexBufferEntries;
+ MemoryBuffer<RawAllocator> m_VertexData;
+
+ void clear()
+ {
+ m_Stride = 0;
+ m_VertexBufferEntries.clear();
+ m_VertexData.clear();
+ }
+};
+struct DynamicIndexBuf
+{
+ NVRenderComponentTypes::Enum m_CompType;
+ MemoryBuffer<RawAllocator> m_IndexData;
+ DynamicIndexBuf() {}
+
+ void clear() { m_IndexData.clear(); }
+};
+
+struct SubsetDesc
+{
+ QT3DSU32 m_Count;
+ QT3DSU32 m_Offset;
+
+ NVBounds3 m_Bounds;
+ QString m_Name;
+ SubsetDesc(QT3DSU32 c, QT3DSU32 off)
+ : m_Count(c)
+ , m_Offset(off)
+ {
+ }
+ SubsetDesc()
+ : m_Count(0)
+ , m_Offset(0)
+ {
+ }
+};
+
+QT3DSU32 GetAlignedOffset(QT3DSU32 offset, QT3DSU32 align)
+{
+ QT3DSU32 leftover = offset % align;
+ if (leftover)
+ return offset + (align - leftover);
+ return offset;
+}
+
+class MeshBuilderImpl : public MeshBuilder
+{
+ DynamicVBuf m_VertexBuffer;
+ DynamicIndexBuf m_IndexBuffer;
+ ImportArray<Joint> m_Joints;
+ ImportArray<SubsetDesc> m_MeshSubsetDescs;
+ NVRenderDrawMode::Enum m_DrawMode;
+ NVRenderWinding::Enum m_Winding;
+ MemoryBuffer<RawAllocator> m_RemappedVertexData;
+ MemoryBuffer<RawAllocator> m_NewIndexBuffer;
+ ImportArray<QT3DSU8> m_MeshBuffer;
+
+public:
+ MeshBuilderImpl() { Reset(); }
+ virtual ~MeshBuilderImpl() { Reset(); }
+ void Release() override { delete this; }
+ void Reset() override
+ {
+ m_VertexBuffer.clear();
+ m_IndexBuffer.clear();
+ m_Joints.clear();
+ m_MeshSubsetDescs.clear();
+ m_DrawMode = NVRenderDrawMode::Triangles;
+ m_Winding = NVRenderWinding::CounterClockwise;
+ m_MeshBuffer.clear();
+ }
+
+ void SetDrawParameters(NVRenderDrawMode::Enum drawMode, NVRenderWinding::Enum winding) override
+ {
+ m_DrawMode = drawMode;
+ m_Winding = winding;
+ }
+
+ // Somewhat burly method to interleave the data as tightly as possible
+ // while taking alignment into account.
+ bool SetVertexBuffer(NVConstDataRef<MeshBuilderVBufEntry> entries) override
+ {
+ QT3DSU32 currentOffset = 0;
+ QT3DSU32 bufferAlignment = 0;
+ QT3DSU32 numItems = 0;
+ bool retval = true;
+ QT3DSIMP_FOREACH(idx, entries.size())
+ {
+ const MeshBuilderVBufEntry &entry(entries[idx]);
+ // Ignore entries with no data.
+ if (entry.m_Data.begin() == NULL || entry.m_Data.size() == 0)
+ continue;
+
+ QT3DSU32 alignment = NVRenderComponentTypes::getSizeofType(entry.m_ComponentType);
+ bufferAlignment = NVMax(bufferAlignment, alignment);
+ QT3DSU32 byteSize = alignment * entry.m_NumComponents;
+
+ if (entry.m_Data.size() % alignment != 0) {
+ QT3DS_ASSERT(false);
+ retval = false;
+ }
+
+ QT3DSU32 localNumItems = entry.m_Data.size() / byteSize;
+ if (numItems == 0) {
+ numItems = localNumItems;
+ } else if (numItems != localNumItems) {
+ QT3DS_ASSERT(false);
+ retval = false;
+ numItems = NVMin(numItems, localNumItems);
+ }
+ // Lots of platforms can't handle non-aligned data.
+ // so ensure we are aligned.
+ currentOffset = GetAlignedOffset(currentOffset, alignment);
+ NVRenderVertexBufferEntry vbufEntry(entry.m_Name, entry.m_ComponentType,
+ entry.m_NumComponents, currentOffset);
+ m_VertexBuffer.m_VertexBufferEntries.push_back(vbufEntry);
+ currentOffset += byteSize;
+ }
+ m_VertexBuffer.m_Stride = GetAlignedOffset(currentOffset, bufferAlignment);
+
+ // Packed interleave the data
+ QT3DSIMP_FOREACH(idx, numItems)
+ {
+ QT3DSU32 dataOffset = 0;
+ QT3DSIMP_FOREACH(entryIdx, entries.size())
+ {
+ const MeshBuilderVBufEntry &entry(entries[entryIdx]);
+ // Ignore entries with no data.
+ if (entry.m_Data.begin() == NULL || entry.m_Data.size() == 0)
+ continue;
+
+ QT3DSU32 alignment = NVRenderComponentTypes::getSizeofType(entry.m_ComponentType);
+ QT3DSU32 byteSize = alignment * entry.m_NumComponents;
+ QT3DSU32 offset = byteSize * idx;
+ QT3DSU32 newOffset = GetAlignedOffset(dataOffset, alignment);
+ if (newOffset != dataOffset)
+ m_VertexBuffer.m_VertexData.writeZeros(newOffset - dataOffset);
+ m_VertexBuffer.m_VertexData.write(entry.m_Data.begin() + offset, byteSize);
+ dataOffset = newOffset + byteSize;
+ }
+ QT3DS_ASSERT(dataOffset == m_VertexBuffer.m_Stride);
+ }
+ return retval;
+ }
+
+ void SetVertexBuffer(NVConstDataRef<NVRenderVertexBufferEntry> entries, QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> data) override
+ {
+ QT3DSIMP_FOREACH(idx, (QT3DSU32)entries.size())
+ {
+ m_VertexBuffer.m_VertexBufferEntries.push_back(entries[idx]);
+ }
+ m_VertexBuffer.m_VertexData.write(data.begin(), data.size());
+ if (stride == 0) {
+ // Calculate the stride of the buffer using the vbuf entries
+ QT3DSIMP_FOREACH(idx, entries.size())
+ {
+ const NVRenderVertexBufferEntry &entry(entries[idx]);
+ stride = NVMax(stride, entry.m_FirstItemOffset
+ + (entry.m_NumComponents * NVRenderComponentTypes::getSizeofType(
+ entry.m_ComponentType)));
+ }
+ }
+ m_VertexBuffer.m_Stride = stride;
+ }
+
+ void SetIndexBuffer(NVConstDataRef<QT3DSU8> data, NVRenderComponentTypes::Enum comp) override
+ {
+ m_IndexBuffer.m_CompType = comp;
+ m_IndexBuffer.m_IndexData.write(data.begin(), data.size());
+ }
+
+ void AddJoint(QT3DSI32 jointID, QT3DSI32 parentID, const QT3DSF32 *invBindPose,
+ const QT3DSF32 *localToGlobalBoneSpace) override
+ {
+ m_Joints.push_back(Joint(jointID, parentID, invBindPose, localToGlobalBoneSpace));
+ }
+
+ SubsetDesc CreateSubset(const wchar_t *inName, QT3DSU32 count, QT3DSU32 offset)
+ {
+ if (inName == NULL)
+ inName = L"";
+ SubsetDesc retval(count, offset);
+ retval.m_Name = QString::fromWCharArray(inName);
+ return retval;
+ }
+
+ // indexBuffer QT3DS_MAX_U32 means no index buffer.
+ // count of QT3DS_MAX_U32 means use all available items
+ // offset means exactly what you would think. Offset is in item size, not bytes.
+ void AddMeshSubset(const wchar_t *inName, QT3DSU32 count, QT3DSU32 offset,
+ QT3DSU32 boundsPositionEntryIndex) override
+ {
+ SubsetDesc retval = CreateSubset(inName, count, offset);
+ if (boundsPositionEntryIndex != QT3DS_MAX_U32) {
+ retval.m_Bounds = Mesh::CalculateSubsetBounds(
+ m_VertexBuffer.m_VertexBufferEntries[boundsPositionEntryIndex],
+ m_VertexBuffer.m_VertexData, m_VertexBuffer.m_Stride, m_IndexBuffer.m_IndexData,
+ m_IndexBuffer.m_CompType, count, offset);
+ }
+ m_MeshSubsetDescs.push_back(retval);
+ }
+
+ void AddMeshSubset(const wchar_t *inName, QT3DSU32 count, QT3DSU32 offset,
+ const NVBounds3 &inBounds) override
+ {
+ SubsetDesc retval = CreateSubset(inName, count, offset);
+ retval.m_Bounds = inBounds;
+ m_MeshSubsetDescs.push_back(retval);
+ }
+#ifndef DISABLE_MESH_OPTIMIZATION
+ void DeletePrimitiveGroup(PrimitiveGroup *&inGroup)
+ {
+ if (inGroup)
+ delete[] inGroup;
+ inGroup = NULL;
+ }
+#endif
+ // We connect sub meshes which habe the same material
+ void ConnectSubMeshes() override
+ {
+ if (m_MeshSubsetDescs.size() < 2) {
+ // nothing to do
+ return;
+ }
+
+ QT3DSU32 matDuplicates = 0;
+
+ // as a pre-step we check if we have duplicate material at all
+ for (QT3DSU32 i = 0, subsetEnd = m_MeshSubsetDescs.size(); i < subsetEnd && !matDuplicates;
+ ++i) {
+ SubsetDesc &currentSubset = m_MeshSubsetDescs[i];
+
+ for (QT3DSU32 j = 0, subsetEnd = m_MeshSubsetDescs.size(); j < subsetEnd; ++j) {
+ SubsetDesc &theSubset = m_MeshSubsetDescs[j];
+
+ if (i == j)
+ continue;
+
+ if (currentSubset.m_Name == theSubset.m_Name) {
+ matDuplicates++;
+ break; // found a duplicate bail out
+ }
+ }
+ }
+
+ // did we find some duplicates?
+ if (matDuplicates) {
+ ImportArray<SubsetDesc> newMeshSubsetDescs;
+ ImportArray<SubsetDesc>::iterator theIter;
+ QString curMatName;
+ m_NewIndexBuffer.clear();
+
+ for (theIter = m_MeshSubsetDescs.begin(); theIter != m_MeshSubsetDescs.end();
+ ++theIter) {
+ bool bProcessed = false;
+
+ for (ImportArray<SubsetDesc>::iterator iter = newMeshSubsetDescs.begin();
+ iter != newMeshSubsetDescs.end(); ++iter) {
+ if (theIter->m_Name == iter->m_Name) {
+ bProcessed = true;
+ break;
+ }
+ }
+
+ if (bProcessed)
+ continue;
+
+ curMatName = theIter->m_Name;
+
+ QT3DSU32 theIndexCompSize =
+ NVRenderComponentTypes::getSizeofType(m_IndexBuffer.m_CompType);
+ // get pointer to indices
+ QT3DSU8 *theIndices =
+ (m_IndexBuffer.m_IndexData.begin()) + (theIter->m_Offset * theIndexCompSize);
+ // write new offset
+ theIter->m_Offset = m_NewIndexBuffer.size() / theIndexCompSize;
+ // store indices
+ m_NewIndexBuffer.write(theIndices, theIter->m_Count * theIndexCompSize);
+
+ for (QT3DSU32 j = 0, subsetEnd = m_MeshSubsetDescs.size(); j < subsetEnd; ++j) {
+ if (theIter == &m_MeshSubsetDescs[j])
+ continue;
+
+ SubsetDesc &theSubset = m_MeshSubsetDescs[j];
+
+ if (curMatName == theSubset.m_Name) {
+ // get pointer to indices
+ QT3DSU8 *theIndices = (m_IndexBuffer.m_IndexData.begin())
+ + (theSubset.m_Offset * theIndexCompSize);
+ // store indices
+ m_NewIndexBuffer.write(theIndices, theSubset.m_Count * theIndexCompSize);
+ // increment indices count
+ theIter->m_Count += theSubset.m_Count;
+ }
+ }
+
+ newMeshSubsetDescs.push_back(*theIter);
+ }
+
+ m_MeshSubsetDescs.clear();
+ m_MeshSubsetDescs = newMeshSubsetDescs;
+ m_IndexBuffer.m_IndexData.clear();
+ m_IndexBuffer.m_IndexData.write(m_NewIndexBuffer.begin(), m_NewIndexBuffer.size());
+
+ // compute new bounding box
+ for (theIter = m_MeshSubsetDescs.begin(); theIter != m_MeshSubsetDescs.end();
+ ++theIter) {
+ theIter->m_Bounds = Mesh::CalculateSubsetBounds(
+ m_VertexBuffer.m_VertexBufferEntries[0], m_VertexBuffer.m_VertexData,
+ m_VertexBuffer.m_Stride, m_IndexBuffer.m_IndexData, m_IndexBuffer.m_CompType,
+ theIter->m_Count, theIter->m_Offset);
+ }
+ }
+ }
+
+ // Here is the NVTriStrip magic.
+ void OptimizeMesh() override
+ {
+ if (NVRenderComponentTypes::getSizeofType(m_IndexBuffer.m_CompType) != 2) {
+ // we currently re-arrange unsigned int indices.
+ // this is because NvTriStrip only supports short indices
+ QT3DS_ASSERT(NVRenderComponentTypes::getSizeofType(m_IndexBuffer.m_CompType) == 4);
+ return;
+ }
+#ifndef DISABLE_MESH_OPTIMIZATION
+ SetCacheSize(CACHESIZE_GEFORCE3);
+ SetStitchStrips(true);
+ SetMinStripSize(0);
+ // Create the optimized list indices
+ SetListsOnly(true);
+ // Optimize the indices using NvTriStrip
+
+ // First, nv-tri-strip all of the indexes. They shouldn't be interleaved, meaning
+ // there is an assumption here that mesh subset1 doesn't uses indexes from mesh subset 2.
+ // They may share vertexes, however, which means that we need to be careful when remapping
+ // them.
+ // Have to go subset by subset in order for the tri-strip to avoid stepping on subsets.
+ m_NewIndexBuffer.clear();
+ for (QT3DSU32 subsetIdx = 0, subsetEnd = m_MeshSubsetDescs.size(); subsetIdx < subsetEnd;
+ ++subsetIdx) {
+ SubsetDesc &theSubset = m_MeshSubsetDescs[subsetIdx];
+ QT3DSU16 *theIndices =
+ reinterpret_cast<QT3DSU16 *>(m_IndexBuffer.m_IndexData.begin()) + theSubset.m_Offset;
+ QT3DSU32 theIndexCount = theSubset.m_Count;
+ QT3DSU16 theNumGroups = 0;
+ PrimitiveGroup *thePrimitiveGroupsList = NULL;
+ theSubset.m_Offset = m_NewIndexBuffer.size() / sizeof(QT3DSU16);
+ theSubset.m_Count = 0;
+
+ // We don't support larger vertex buffers. That requires splitting the buffer,
+ // an operation we haven't implemented (yet).
+ if (GenerateStrips(theIndices, theIndexCount, &thePrimitiveGroupsList, &theNumGroups)) {
+ if (theNumGroups) {
+ QT3DS_ASSERT(theNumGroups == 1);
+ PrimitiveGroup &srcGroup(thePrimitiveGroupsList[0]);
+ QT3DS_ASSERT(srcGroup.type == PT_LIST);
+ m_NewIndexBuffer.write(srcGroup.indices, srcGroup.numIndices);
+ theSubset.m_Count = srcGroup.numIndices;
+ }
+ }
+
+ DeletePrimitiveGroup(thePrimitiveGroupsList);
+ }
+ m_IndexBuffer.m_IndexData.clear();
+ m_IndexBuffer.m_IndexData.write(m_NewIndexBuffer.begin(), m_NewIndexBuffer.size());
+
+#ifndef DISABLE_VERTEX_REMAP
+ // This operation does not go subset by subset
+ // by rather remaps the entire vertex buffer in one shot
+ // once all of the index buffers are setup.
+ QT3DSU16 *theIndices = reinterpret_cast<QT3DSU16 *>(m_IndexBuffer.m_IndexData.begin());
+ QT3DSU32 theIndexCount = m_IndexBuffer.m_IndexData.size() / sizeof(QT3DSU16);
+
+ // Setup input to the remap system
+ QT3DSU16 theNumGroups = 1;
+ PrimitiveGroup thePrimitiveGroup;
+ thePrimitiveGroup.type = PT_LIST;
+ thePrimitiveGroup.numIndices = theIndexCount;
+ thePrimitiveGroup.indices = new QT3DSU16[theIndexCount];
+ memCopy(thePrimitiveGroup.indices, theIndices, theIndexCount * sizeof(QT3DSU16));
+
+ PrimitiveGroup *theRemappedGroup = NULL;
+ QT3DSU32 vertBufByteSize = m_VertexBuffer.m_VertexData.size();
+ QT3DSU32 numVertexIndices = vertBufByteSize / m_VertexBuffer.m_Stride;
+ QT3DS_ASSERT(numVertexIndices < QT3DS_MAX_U16);
+ QT3DSU32 vertBufStride = m_VertexBuffer.m_Stride;
+ // This remaps the vertexes
+ RemapIndices(&thePrimitiveGroup, theNumGroups, static_cast<QT3DSU16>(numVertexIndices),
+ &theRemappedGroup);
+ m_RemappedVertexData.reserve(vertBufByteSize);
+ const QT3DSU8 *srcVertexPtr(m_VertexBuffer.m_VertexData.begin());
+ QT3DSU8 *dstVertexPtr(m_RemappedVertexData.begin());
+ QT3DS_ASSERT(theNumGroups == 1);
+ for (QT3DSU32 theGroupIdx = 0; theGroupIdx < 1; ++theGroupIdx) {
+ PrimitiveGroup &srcGroup(thePrimitiveGroup);
+ PrimitiveGroup &dstGroup(theRemappedGroup[theGroupIdx]);
+ QT3DS_ASSERT(srcGroup.type == PT_LIST);
+
+ for (QT3DSU32 theIndexIdx = 0; theIndexIdx < srcGroup.numIndices; ++theIndexIdx) {
+ QT3DSU16 srcIndex = srcGroup.indices[theIndexIdx];
+ QT3DSU16 dstIndex = dstGroup.indices[theIndexIdx];
+ QT3DS_ASSERT(dstIndex * m_VertexBuffer.m_Stride < vertBufByteSize);
+ QT3DS_ASSERT(srcIndex * m_VertexBuffer.m_Stride < vertBufByteSize);
+ // Maybe add in a check to see if we possibly already copied this information
+ // That would of course be only an optimization.
+ memCopy(dstVertexPtr + dstIndex * vertBufStride,
+ srcVertexPtr + srcIndex * vertBufStride, vertBufStride);
+ theIndices[theIndexIdx] = dstIndex;
+ }
+ memCopy(m_VertexBuffer.m_VertexData.begin(), m_RemappedVertexData.begin(),
+ vertBufByteSize);
+ }
+
+ DeletePrimitiveGroup(theRemappedGroup);
+#endif // DISABLE_VERTEX_REMAP
+#endif // DISABLE_MESH_OPTIMIZATION
+ }
+
+ template <typename TDataType>
+ static void Assign(QT3DSU8 *inBaseAddress, QT3DSU8 *inDataAddress,
+ SOffsetDataRef<TDataType> &inBuffer, const TDataType *inDestData,
+ QT3DSU32 inDestSize)
+ {
+ inBuffer.m_Offset = (QT3DSU32)(inDataAddress - inBaseAddress);
+ inBuffer.m_Size = inDestSize;
+ memCopy(inDataAddress, inDestData, inDestSize * sizeof(TDataType));
+ }
+ template <typename TDataType>
+ static void Assign(QT3DSU8 *inBaseAddress, QT3DSU8 *inDataAddress,
+ SOffsetDataRef<TDataType> &inBuffer, QT3DSU32 inDestSize)
+ {
+ inBuffer.m_Offset = (QT3DSU32)(inDataAddress - inBaseAddress);
+ inBuffer.m_Size = inDestSize;
+ }
+ // Return the current mesh. This is only good for this function call, item may change or be
+ // released
+ // due to any further function calls.
+ Mesh &GetMesh() override
+ {
+ QT3DSU32 meshSize = sizeof(Mesh);
+ QT3DSU32 alignment = sizeof(void *);
+ QT3DSU32 vertDataSize = GetAlignedOffset(m_VertexBuffer.m_VertexData.size(), alignment);
+ meshSize += vertDataSize;
+ QT3DSU32 entrySize = m_VertexBuffer.m_VertexBufferEntries.size()
+ * sizeof(qt3ds::render::NVRenderVertexBufferEntry);
+ meshSize += entrySize;
+ QT3DSU32 entryNameSize = 0;
+ for (QT3DSU32 idx = 0, end = m_VertexBuffer.m_VertexBufferEntries.size(); idx < end; ++idx) {
+ const qt3ds::render::NVRenderVertexBufferEntry &theEntry(
+ m_VertexBuffer.m_VertexBufferEntries[idx]);
+ const char *entryName = theEntry.m_Name;
+ if (entryName == NULL)
+ entryName = "";
+ entryNameSize += (QT3DSU32)(strlen(theEntry.m_Name)) + 1;
+ }
+ entryNameSize = GetAlignedOffset(entryNameSize, alignment);
+ meshSize += entryNameSize;
+ QT3DSU32 indexBufferSize = GetAlignedOffset(m_IndexBuffer.m_IndexData.size(), alignment);
+ meshSize += indexBufferSize;
+ QT3DSU32 subsetSize = m_MeshSubsetDescs.size() * sizeof(MeshSubset);
+ QT3DSU32 nameSize = 0;
+ for (QT3DSU32 idx = 0, end = m_MeshSubsetDescs.size(); idx < end; ++idx) {
+ if (!m_MeshSubsetDescs[idx].m_Name.isEmpty())
+ nameSize += m_MeshSubsetDescs[idx].m_Name.size() + 1;
+ }
+ nameSize *= sizeof(char16_t);
+ nameSize = GetAlignedOffset(nameSize, alignment);
+
+ meshSize += subsetSize + nameSize;
+ QT3DSU32 jointsSize = m_Joints.size() * sizeof(UICIMP::Joint);
+ meshSize += jointsSize;
+ m_MeshBuffer.resize(meshSize);
+ QT3DSU8 *baseAddress = m_MeshBuffer.data();
+ Mesh *retval = reinterpret_cast<Mesh *>(baseAddress);
+ retval->m_DrawMode = m_DrawMode;
+ retval->m_Winding = m_Winding;
+ QT3DSU8 *vertBufferData = baseAddress + sizeof(Mesh);
+ QT3DSU8 *vertEntryData = vertBufferData + vertDataSize;
+ QT3DSU8 *vertEntryNameData = vertEntryData + entrySize;
+ QT3DSU8 *indexBufferData = vertEntryNameData + entryNameSize;
+ QT3DSU8 *subsetBufferData = indexBufferData + indexBufferSize;
+ QT3DSU8 *nameBufferData = subsetBufferData + subsetSize;
+ QT3DSU8 *jointBufferData = nameBufferData + nameSize;
+
+ retval->m_VertexBuffer.m_Stride = m_VertexBuffer.m_Stride;
+ Assign(baseAddress, vertBufferData, retval->m_VertexBuffer.m_Data,
+ m_VertexBuffer.m_VertexData.begin(), m_VertexBuffer.m_VertexData.size());
+ retval->m_VertexBuffer.m_Entries.m_Size = m_VertexBuffer.m_VertexBufferEntries.size();
+ retval->m_VertexBuffer.m_Entries.m_Offset = (QT3DSU32)(vertEntryData - baseAddress);
+ for (QT3DSU32 idx = 0, end = m_VertexBuffer.m_VertexBufferEntries.size(); idx < end; ++idx) {
+ const qt3ds::render::NVRenderVertexBufferEntry &theEntry(
+ m_VertexBuffer.m_VertexBufferEntries[idx]);
+ MeshVertexBufferEntry &theDestEntry(
+ retval->m_VertexBuffer.m_Entries.index(baseAddress, idx));
+ theDestEntry.m_ComponentType = theEntry.m_ComponentType;
+ theDestEntry.m_FirstItemOffset = theEntry.m_FirstItemOffset;
+ theDestEntry.m_NumComponents = theEntry.m_NumComponents;
+ const char *targetName = theEntry.m_Name;
+ if (targetName == NULL)
+ targetName = "";
+
+ QT3DSU32 entryNameLen = (QT3DSU32)(strlen(targetName)) + 1;
+ theDestEntry.m_NameOffset = (QT3DSU32)(vertEntryNameData - baseAddress);
+ memCopy(vertEntryNameData, theEntry.m_Name, entryNameLen);
+ vertEntryNameData += entryNameLen;
+ }
+
+ retval->m_IndexBuffer.m_ComponentType = m_IndexBuffer.m_CompType;
+ Assign(baseAddress, indexBufferData, retval->m_IndexBuffer.m_Data,
+ m_IndexBuffer.m_IndexData.begin(), m_IndexBuffer.m_IndexData.size());
+ Assign(baseAddress, subsetBufferData, retval->m_Subsets, m_MeshSubsetDescs.size());
+ for (QT3DSU32 idx = 0, end = m_MeshSubsetDescs.size(); idx < end; ++idx) {
+ SubsetDesc &theDesc = m_MeshSubsetDescs[idx];
+ MeshSubset &theSubset = reinterpret_cast<MeshSubset *>(subsetBufferData)[idx];
+ theSubset.m_Bounds = theDesc.m_Bounds;
+ theSubset.m_Count = theDesc.m_Count;
+ theSubset.m_Offset = theDesc.m_Offset;
+ if (!theDesc.m_Name.isEmpty()) {
+ theSubset.m_Name.m_Size = theDesc.m_Name.size() + 1;
+ theSubset.m_Name.m_Offset = (QT3DSU32)(nameBufferData - baseAddress);
+ std::transform(theDesc.m_Name.begin(), theDesc.m_Name.end(),
+ reinterpret_cast<char16_t *>(nameBufferData),
+ [](QChar c) { return static_cast<char16_t>(c.unicode()); });
+ reinterpret_cast<char16_t *>(nameBufferData)[theDesc.m_Name.size()] = 0;
+ nameBufferData += (theDesc.m_Name.size() + 1) * sizeof(char16_t);
+ } else {
+ theSubset.m_Name.m_Size = 0;
+ theSubset.m_Name.m_Offset = 0;
+ }
+ }
+ Assign(baseAddress, jointBufferData, retval->m_Joints, m_Joints.data(), m_Joints.size());
+ return *retval;
+ }
+};
+}
+
+// Uses new/delete.
+MeshBuilder &MeshBuilder::CreateMeshBuilder()
+{
+ return *(new MeshBuilderImpl());
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportMeshStudioOnly.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportMeshStudioOnly.cpp
new file mode 100644
index 00000000..2f6e8d5a
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportMeshStudioOnly.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICImportLibPrecompile.h"
+#include "UICImportContainers.h"
+#include "UICImportMesh.h"
+#include "UICFileTools.h"
+#include "UICFileToolsSeekableMeshBufIOStream.h"
+
+using namespace UICIMP;
+using namespace Q3DStudio;
+
+Mesh *Mesh::Load(const char *inFilePath)
+{
+ Q3DStudio::CFilePath thePath(inFilePath);
+ CFileSeekableIOStream stream(thePath, FileReadFlags());
+ if (stream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ MallocAllocator allocator;
+ return Load(allocator, stream);
+}
+
+bool Mesh::Save(const char *inFilePath) const
+{
+ CFileSeekableIOStream stream(inFilePath, FileWriteFlags());
+ if (stream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ Save(stream);
+ return true;
+}
+
+// You can save multiple meshes in a file. Each mesh returns an incrementing
+// integer for the multi file. The original meshes aren't changed, and the file
+// is appended to.
+QT3DSU32 Mesh::SaveMulti(const char *inFilePath) const
+{
+ MallocAllocator allocator;
+ Q3DStudio::CFilePath thePath(inFilePath);
+ FileOpenFlags theFlags = thePath.Exists() ? FileAppendFlags() : FileWriteFlags();
+ CFileSeekableIOStream stream(thePath, theFlags);
+ return SaveMulti(allocator, stream);
+}
+
+// Load a single mesh using c file API and malloc/free.
+SMultiLoadResult Mesh::LoadMulti(const char *inFilePath, QT3DSU32 inId)
+{
+ MallocAllocator allocator;
+ Q3DStudio::CFilePath thePath(inFilePath);
+ CFileSeekableIOStream stream(thePath, FileReadFlags());
+ return LoadMulti(allocator, stream, inId);
+}
+
+// Load a multi header from a file using malloc. Header needs to be freed using free.
+MeshMultiHeader *Mesh::LoadMultiHeader(const char *inFilePath)
+{
+ MallocAllocator allocator;
+ Q3DStudio::CFilePath thePath(inFilePath);
+ CFileSeekableIOStream stream(thePath, FileReadFlags());
+ return LoadMultiHeader(allocator, stream);
+}
+
+QT3DSU32 Mesh::GetHighestMultiVersion(const char *inFilePath)
+{
+ MallocAllocator allocator;
+ Q3DStudio::CFilePath thePath(inFilePath);
+ CFileSeekableIOStream stream(thePath, FileReadFlags());
+ return GetHighestMultiVersion(allocator, stream);
+}
+
+void CUICFileToolsSeekableMeshBufIOStream::SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inEnum)
+{
+ m_File->SetPosition(inOffset, (Q3DStudio::SeekPosition::Enum)inEnum);
+}
+QT3DSI64 CUICFileToolsSeekableMeshBufIOStream::GetPosition() const
+{
+ return m_File->GetPosition();
+}
+QT3DSU32 CUICFileToolsSeekableMeshBufIOStream::Read(NVDataRef<QT3DSU8> data)
+{
+ return m_File->Read(data.begin(), data.size());
+}
+bool CUICFileToolsSeekableMeshBufIOStream::Write(NVConstDataRef<QT3DSU8> data)
+{
+ return m_File->Write(data.begin(), data.size()) == data.size();
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportPath.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportPath.cpp
new file mode 100644
index 00000000..da8c2686
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportPath.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICImportLibPrecompile.h"
+#include "UICImportPath.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+
+using namespace UICIMP;
+
+void SPathBuffer::Save(IOutStream &outStream) const
+{
+ outStream.Write(GetFileTag());
+ outStream.Write(GetFileVersion());
+ outStream.Write((QT3DSU32)m_Commands.size());
+ outStream.Write((QT3DSU32)m_Data.size());
+ outStream.Write(toU8ConstDataRef((PathCommand::Enum *)m_Commands.begin(), m_Commands.size()));
+ outStream.Write(toU8ConstDataRef((QT3DSF32 *)m_Data.begin(), m_Data.size()));
+}
+
+SPathBuffer *SPathBuffer::Load(IInStream &inStream, NVFoundationBase &inFoundation)
+{
+ QT3DSU64 fileTag;
+ QT3DSU32 version, numCommands, numData;
+ inStream.Read(fileTag);
+ inStream.Read(version);
+ inStream.Read(numCommands);
+ inStream.Read(numData);
+ if (fileTag != GetFileTag()) {
+ qCCritical(INVALID_OPERATION, "Invalid file, not a path file");
+ return NULL;
+ }
+ if (version > GetFileVersion()) {
+ qCCritical(INVALID_OPERATION, "Version number out of range.");
+ return NULL;
+ }
+ QT3DSU32 commandSize = numCommands * sizeof(QT3DSU32);
+ QT3DSU32 dataSize = numData * sizeof(QT3DSF32);
+ QT3DSU32 objectSize = sizeof(SPathBuffer);
+ QT3DSU32 allocSize = objectSize + commandSize + dataSize;
+ QT3DSU8 *rawData =
+ (QT3DSU8 *)inFoundation.getAllocator().allocate(allocSize, "SPathBuffer", __FILE__, __LINE__);
+ SPathBuffer *retval = new (rawData) SPathBuffer();
+ QT3DSU8 *commandBuffer = rawData + sizeof(SPathBuffer);
+ QT3DSU8 *dataBuffer = commandBuffer + commandSize;
+ inStream.Read(commandBuffer, commandSize);
+ inStream.Read(dataBuffer, dataSize);
+ retval->m_Commands = toDataRef((PathCommand::Enum *)commandBuffer, numCommands);
+ retval->m_Data = toDataRef((QT3DSF32 *)dataBuffer, numData);
+ return retval;
+}
+
+void SPathBuffer::Free(NVAllocatorCallback &inAllocator)
+{
+ inAllocator.deallocate(this);
+}
+
+namespace {
+struct SBuilder : public IPathBufferBuilder
+{
+ NVFoundationBase &m_Foundation;
+ nvvector<PathCommand::Enum> m_Commands;
+ nvvector<QT3DSF32> m_Data;
+ QT3DSI32 m_RefCount;
+
+ SBuilder(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , m_Commands(inFoundation.getAllocator(), "m_Commands")
+ , m_Data(inFoundation.getAllocator(), "m_Data")
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &theAlloc(m_Foundation.getAllocator());
+ NVDelete(theAlloc, this);
+ }
+ }
+
+ void Clear() override
+ {
+ m_Commands.clear();
+ m_Data.clear();
+ }
+
+ void Push(const QT3DSVec2 inPos)
+ {
+ m_Data.push_back(inPos.x);
+ m_Data.push_back(inPos.y);
+ }
+
+ void MoveTo(const QT3DSVec2 &inPos) override
+ {
+ m_Commands.push_back(PathCommand::MoveTo);
+ Push(inPos);
+ }
+
+ void CubicCurveTo(const QT3DSVec2 &inC1, const QT3DSVec2 &inC2, const QT3DSVec2 &inP2) override
+ {
+ m_Commands.push_back(PathCommand::CubicCurveTo);
+ Push(inC1);
+ Push(inC2);
+ Push(inP2);
+ }
+
+ void Close() override { m_Commands.push_back(PathCommand::Close); }
+
+ // Points back to internal data structures, must use or copy.
+ SPathBuffer GetPathBuffer() override
+ {
+ SPathBuffer retval;
+ retval.m_Data = m_Data;
+ retval.m_Commands = m_Commands;
+ return retval;
+ }
+};
+}
+
+IPathBufferBuilder &IPathBufferBuilder::CreateBuilder(NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SBuilder)(inFoundation);
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportPath.h b/src/Authoring/UICIMP/UICImportLib/UICImportPath.h
new file mode 100644
index 00000000..f81386b9
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportPath.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTPATHH
+#define UICIMPORTPATHH
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSVec2.h"
+
+namespace UICIMP {
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::render;
+struct PathCommand
+{
+ enum Enum {
+ Noner = 0,
+ MoveTo, // 2 floats
+ CubicCurveTo, // 6 floats, c1, c2, p2. p1 is existing location
+ Close, // 0 floats
+ };
+};
+
+struct SPathBuffer
+{
+ // 64 bit random number to uniquely identify this file type.
+ static QT3DSU64 GetFileTag() { return 0x7b1a41633c43a6afULL; }
+ static QT3DSU32 GetFileVersion() { return 1; }
+ NVConstDataRef<PathCommand::Enum> m_Commands;
+ NVConstDataRef<QT3DSF32> m_Data;
+ SPathBuffer() {}
+ void Save(IOutStream &outStream) const;
+ static SPathBuffer *Load(IInStream &inStream, NVFoundationBase &inFoundation);
+
+ // Object is unused after this call. Anything created with Load must use this function.
+ void Free(NVAllocatorCallback &inAllocator);
+ SPathBuffer *Copy(NVAllocatorCallback &inAllocator) const;
+};
+
+class IPathBufferBuilder : public NVRefCounted
+{
+public:
+ virtual void Clear() = 0;
+
+ virtual void MoveTo(const QT3DSVec2 &inPos) = 0;
+ virtual void CubicCurveTo(const QT3DSVec2 &inC1, const QT3DSVec2 &inC2, const QT3DSVec2 &inP2) = 0;
+ virtual void Close() = 0;
+ // Points back to internal data structures, must use or copy.
+ virtual SPathBuffer GetPathBuffer() = 0;
+
+ static IPathBufferBuilder &CreateBuilder(NVFoundationBase &inFoundation);
+};
+}
+
+#endif \ No newline at end of file
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.cpp b/src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.cpp
new file mode 100644
index 00000000..49848e03
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICImportLibPrecompile.h"
+#include "UICImport.h"
+#include "UICImportPerformImport.h"
+#include "UICImportImpl.h"
+#include "UICFileTools.h"
+
+using namespace UICIMP;
+using namespace Q3DStudio;
+
+namespace {
+template <typename TDataType>
+struct ScopedReleaser
+{
+ TDataType *dtype;
+ ScopedReleaser(TDataType &dt)
+ : dtype(&dt)
+ {
+ }
+ ~ScopedReleaser()
+ {
+ if (dtype)
+ dtype->Release();
+ }
+};
+
+void DoUpdateInstances(Import &import, IComposerEditor &composer,
+ NVConstDataRef<InstanceDesc> instances,
+ ImportArray<PropertyValue> &properties)
+{
+ QT3DSIMP_FOREACH(idx, instances.size())
+ {
+ // We have to re-lookup instances here because the instance data may have changed since it
+ // was put
+ // into the import report. For instance, you get an import report, then you add instances.
+ // This adds
+ // user ids. But the import report is already created so the instance descriptions in the
+ // report's
+ // add list won't reflect the new reality.
+ const InstanceDesc &desc(instances[idx]);
+ QT3DSU32 numProps = import.GetNumProperties(desc.m_Handle);
+ properties.resize(numProps);
+ import.GetProperties(desc.m_Handle, properties);
+ composer.UpdateInstanceProperties(desc.m_Id, properties.data(), (QT3DSU32)properties.size());
+ }
+}
+}
+
+SImportResult::SImportResult(const Q3DStudio::CFilePath &inFilePath, QT3DSU32 inFileVersion)
+ : m_Error(ImportErrorCodes::NoError)
+ , m_FilePath(inFilePath)
+{
+ m_FilePath.SetIdentifier(inFileVersion);
+}
+
+/**
+ * This function has a simple concept but really complex implications.
+ * We are taking a document with perhaps multiple user-id, import-id pairs
+ * and applying it to another document where any one of those pairs may
+ * or may not apply.
+ *
+ * Just for import, you can consider three different cases:
+ * 1. Document imported into project once.
+ * 2. Document *that has been imported* imported into project again.
+ * 3. Document *that has been imported* imported into new, different project.
+ *
+ * And then consider what correct refresh behavior should be in each one of those
+ * cases.
+ */
+void CPerformImport::DoImportToComposer(Import &import, IComposerEditor &composer)
+{
+ ImportReport report(import.CompileReport());
+ composer.BeginImport(import);
+ // Remove links.
+ QT3DSIMP_FOREACH(idx, report.m_Links.m_Removed.size())
+ {
+ const ParentChildLink link(report.m_Links.m_Removed[idx]);
+ composer.RemoveChild(link.m_Parent, link.m_Child);
+ }
+
+ // Remove instances
+ QT3DSIMP_FOREACH(idx, report.m_Instances.m_Removed.size())
+ {
+ composer.RemoveInstance(report.m_Instances.m_Removed[idx].m_Id);
+ }
+
+ // Create the new instances.
+ QT3DSIMP_FOREACH(idx, report.m_Instances.m_Added.size())
+ {
+ const InstanceDesc &desc(report.m_Instances.m_Added[idx]);
+ if (AreEqual(desc.m_Id, L"__import__root__"))
+ composer.CreateRootInstance(desc.m_Id, desc.m_Type);
+ else {
+ Option<InstanceDesc> parent(import.GetInstanceByHandle(desc.m_Parent));
+ TImportId parentId = L"";
+ if (parent.hasValue())
+ parentId = parent->m_Id;
+ composer.CreateInstance(desc.m_Id, desc.m_Type, parentId);
+ }
+ }
+
+ ImportArray<PropertyValue> properties;
+ DoUpdateInstances(import, composer, report.m_Instances.m_Added, properties);
+ DoUpdateInstances(import, composer, report.m_Instances.m_Existing, properties);
+
+ // Add links
+ QT3DSIMP_FOREACH(idx, report.m_Links.m_Added.size())
+ {
+ const ParentChildLink link(report.m_Links.m_Added[idx]);
+ composer.AddChild(link.m_Parent, link.m_Child, link.m_NextSibling);
+ }
+
+ // Remove animations (some of these may be to removed objects).
+ QT3DSIMP_FOREACH(idx, report.m_Animations.m_Removed.size())
+ {
+ const Animation &anim(report.m_Animations.m_Removed[idx]);
+ composer.RemoveAnimation(anim.m_InstanceId, anim.m_PropertyName, anim.m_SubPropertyIndex);
+ }
+
+ QT3DSIMP_FOREACH(idx, report.m_Animations.m_Added.size())
+ {
+ const Animation &anim(report.m_Animations.m_Added[idx]);
+ composer.AddAnimation(anim.m_InstanceId, anim.m_PropertyName, anim.m_SubPropertyIndex,
+ anim.m_Type, anim.m_Keyframes.begin(), anim.m_Keyframes.size());
+ }
+
+ QT3DSIMP_FOREACH(idx, report.m_Animations.m_Existing.size())
+ {
+ const Animation &anim(report.m_Animations.m_Existing[idx]);
+ composer.UpdateAnimation(anim.m_InstanceId, anim.m_PropertyName, anim.m_SubPropertyIndex,
+ anim.m_Type, anim.m_Keyframes.begin(), anim.m_Keyframes.size());
+ }
+
+ composer.EndImport();
+}
+
+SImportResult CPerformImport::RefreshToComposer(ITranslator &translator,
+ IComposerEditor &inComposer,
+ Import &inOriginalImport,
+ const Q3DStudio::CFilePath &ioImportFile)
+{
+ ScopedReleaser<Import> __originalScope(inOriginalImport);
+
+ ScopedReleaser<ITranslator> __translatorScope(translator);
+ const CFilePath &importDestFile(ioImportFile);
+
+ if (importDestFile.IsFile() && importDestFile.GetFileFlags().CanWrite() == false)
+ return ImportErrorCodes::ResourceNotWriteable;
+
+ __originalScope.dtype = NULL;
+
+ ImportPtrOrError importPtr =
+ Import::CreateForRefresh(inOriginalImport, translator.GetSourceFile().toStdWString().c_str());
+ if (importPtr.m_Value == NULL)
+ return importPtr.m_ErrorData.m_Error;
+
+ ScopedReleaser<Import> __importScope(*importPtr.m_Value);
+ if (translator.PerformTranslation(*importPtr.m_Value)) {
+ DoImportToComposer(*importPtr.m_Value, inComposer);
+ Q3DStudio::CString fname = Q3DStudio::CFilePath(importDestFile).GetFileName();
+ QT3DSU32 importId = importPtr.m_Value->Save(fname.c_str());
+ return SImportResult(importDestFile, importId);
+ }
+ return ImportErrorCodes::TranslationToImportFailed;
+}
+SImportResult CPerformImport::RefreshToComposer(ITranslator &translator, IComposerEditor &composer,
+ const CFilePath &ioImportFile)
+{
+ ImportPtrOrError originalPtr = Import::Load(ioImportFile.c_str());
+ if (originalPtr.m_Value == NULL)
+ return originalPtr.m_ErrorData.m_Error;
+
+ return RefreshToComposer(translator, composer, *originalPtr.m_Value, ioImportFile);
+}
+
+SImportResult CPerformImport::ImportToComposer(ITranslator &translator, IComposerEditor &composer,
+ const Q3DStudio::CFilePath &inImportFile)
+{
+ ScopedReleaser<ITranslator> __translatorScope(translator);
+ const CFilePath &importDestFile(inImportFile);
+ if (importDestFile.IsFile() && importDestFile.GetFileFlags().CanWrite() == false)
+ return ImportErrorCodes::ResourceNotWriteable;
+ ImportPtrOrError importPtr =
+ Import::Create(translator.GetSourceFile().toStdWString().c_str(), importDestFile.GetDirectory());
+ if (importPtr.m_Value == NULL)
+ return importPtr.m_ErrorData.m_Error;
+ ScopedReleaser<Import> __importScope(*importPtr.m_Value);
+ if (translator.PerformTranslation(*importPtr.m_Value)) {
+ DoImportToComposer(*importPtr.m_Value, composer);
+ Q3DStudio::CString fname = importDestFile.GetFileName();
+ QT3DSU32 importId = importPtr.m_Value->Save(fname.c_str());
+ return SImportResult(importDestFile, importId);
+ }
+ return ImportErrorCodes::TranslationToImportFailed;
+}
+
+SImportResult
+CPerformImport::ImportToComposerFromImportFile(IComposerEditor &composer,
+ const Q3DStudio::CFilePath &inImportFile)
+{
+ const CFilePath &importDestFile(inImportFile);
+ if (importDestFile.IsFile() == false)
+ return ImportErrorCodes::SourceFileDoesNotExist;
+
+ QT3DSU32 fileId = Import::GetHighestImportRevision(inImportFile.c_str());
+ if (fileId == 0)
+ return ImportErrorCodes::SourceFileNotReadable;
+
+ ImportPtrOrError importPtr = Import::Load(importDestFile.c_str(), fileId);
+ if (importPtr.m_Value == NULL)
+ return importPtr.m_ErrorData.m_Error;
+ ScopedReleaser<Import> __importScope(*importPtr.m_Value);
+ DoImportToComposer(*importPtr.m_Value, composer);
+ return SImportResult(inImportFile, fileId);
+}
+
+SImportResult CPerformImport::TranslateToImportFile(ITranslator &translator,
+ const Q3DStudio::CFilePath &inImportFile)
+{
+ ScopedReleaser<ITranslator> __translatorScope(translator);
+ const CFilePath &importDestFile(inImportFile);
+ if (importDestFile.IsFile() && importDestFile.GetFileFlags().CanWrite() == false)
+ return ImportErrorCodes::ResourceNotWriteable;
+
+ ImportPtrOrError importPtr =
+ Import::Create(translator.GetSourceFile().toStdWString().c_str(), importDestFile.GetDirectory());
+ if (importPtr.m_Value == NULL)
+ return importPtr.m_ErrorData.m_Error;
+ ScopedReleaser<Import> __importScope(*importPtr.m_Value);
+ if (translator.PerformTranslation(*importPtr.m_Value)) {
+ Q3DStudio::CString fname = importDestFile.GetFileName();
+ QT3DSU32 importId = importPtr.m_Value->Save(fname.c_str());
+ return SImportResult(inImportFile, importId);
+ }
+ return ImportErrorCodes::TranslationToImportFailed;
+}
diff --git a/src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.h b/src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.h
new file mode 100644
index 00000000..1885810e
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportLib/UICImportPerformImport.h
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UICIMPORTPERFORMIMPORTH
+#define UICIMPORTPERFORMIMPORTH
+#include "UICDMDataTypes.h"
+#include "UICDMHandles.h"
+#include "foundation/Qt3DS.h"
+#include "UICString.h"
+#include "UICDMHandles.h"
+#include "UICFileTools.h"
+#include "UICDMAnimation.h"
+#include "UICImportErrorCodes.h"
+#include "UICDMComposerTypeDefinitions.h"
+
+namespace Q3DStudio {
+class CFilePath;
+};
+
+namespace UICIMP {
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace std;
+using namespace UICDM;
+
+struct ParentChildLink;
+struct PropertyValue;
+class Import;
+
+struct ImportErrorData
+{
+ ImportErrorCodes::Enum m_Error;
+ const wchar_t *m_ExtraInfo;
+ explicit ImportErrorData(ImportErrorCodes::Enum err, TCharPtr extraInfo)
+ : m_Error(err)
+ , m_ExtraInfo(extraInfo)
+ {
+ }
+ ImportErrorData()
+ : m_Error(ImportErrorCodes::NoError)
+ , m_ExtraInfo(L"")
+ {
+ }
+
+ void PrintErrorString(wchar_t *buffer, QT3DSU32 bufLen)
+ {
+ if (m_Error != ImportErrorCodes::NoError)
+ swprintf(buffer, bufLen, ImportErrorCodes::GetEnglishFormatString(m_Error),
+ m_ExtraInfo);
+ else
+ swprintf(buffer, bufLen, L"No error");
+ }
+};
+
+typedef SValue TImportModelValue;
+
+struct PropertyValue
+{
+ ComposerPropertyNames::Enum m_Name;
+ TImportModelValue m_Value;
+
+ PropertyValue(ComposerPropertyNames::Enum nm, const TImportModelValue &val)
+ : m_Name(nm)
+ , m_Value(val)
+ {
+ }
+ PropertyValue()
+ : m_Name(ComposerPropertyNames::Unknown)
+ {
+ }
+};
+
+typedef const wchar_t *TImportId;
+
+/**
+ * Interface to allow abstract UIComposer details (doc, slides, etc)
+ * from the operation of applying a import result to composer.
+ *
+ * Implementations must remember that a document may be imported several times.
+ * Each time the import id will be incremented.
+ *
+ * If they can't guarantee they will give back a unique handle every time the
+ * document is imported, including in the case where they create a new project
+ * and import a previously imported document into the new project, then they
+ * need to use the combination of import id and handle in order to identify
+ * precisely which object the import library is attempting to update.
+ */
+class IComposerEditor
+{
+protected:
+ virtual ~IComposerEditor() {}
+public:
+ virtual void Release() = 0;
+ virtual void BeginImport(Import &importObj) = 0;
+ virtual void RemoveChild(TImportId inParentId, TImportId inChildId) = 0;
+ virtual void RemoveInstance(TImportId parent) = 0;
+ /**
+ * Note that instance properties that point to files (sourcepath generally) point to files
+ * relative to the import file. You need to do combineBaseAndRelative with those files
+ * and the a new getRelativeFromBase with the final file in order to transfer data
+ * successfully. The time to do this sort of thing is upon create or update instance.
+ */
+ virtual void CreateRootInstance(TImportId inImportId, ComposerObjectTypes::Enum type) = 0;
+ // inParent may be null (or an invalid handle) if the instance doesn't have a parent (images)
+ virtual void CreateInstance(TImportId inImportId, ComposerObjectTypes::Enum type,
+ TImportId inParent) = 0;
+
+ // We guarantee that all instances will be created before their properties are updated thus you
+ // can resolve references during this updateInstanceProperties call if necessary.
+ virtual void UpdateInstanceProperties(TImportId hdl, const PropertyValue *propertBuffer,
+ QT3DSU32 propertyBufferSize) = 0;
+ // This is called even for new instances where we told you the parent because
+ // they may be out of order so if the child already has this parent relationship you need
+ // to check the order and ensure that is also (somewhat) correct.
+ virtual void AddChild(TImportId parent, TImportId child, TImportId nextSibling) = 0;
+ virtual void RemoveAnimation(TImportId hdl, const wchar_t *propName, long propSubIndex) = 0;
+ virtual void UpdateAnimation(TImportId hdl, const wchar_t *propName, long propSubIndex,
+ EAnimationType animType, const float *animData,
+ QT3DSU32 numFloats) = 0;
+ virtual void AddAnimation(TImportId hdl, const wchar_t *propName, long propSubIndex,
+ EAnimationType animType, const float *animData, QT3DSU32 numFloats) = 0;
+
+ virtual void EndImport() = 0;
+};
+
+// Translators perform src file to import translation,
+// so from collada to import format translation.
+class ITranslator
+{
+protected:
+ virtual ~ITranslator() {}
+public:
+ virtual void Release() = 0;
+
+ virtual const QString &GetSourceFile() = 0;
+ // Returning false causes the rest of the import or refresh process
+ // to fail.
+ virtual bool PerformTranslation(Import &import) = 0;
+};
+
+// The result of an import or a refresh. The file path contains a string that
+// will have a import file version number at the end.
+struct SImportResult
+{
+ ImportErrorCodes::Enum m_Error;
+ // The file path will probably contain a version number at the end of the
+ // string, so you need to be aware of this.
+ Q3DStudio::CFilePath m_FilePath;
+
+ SImportResult(ImportErrorCodes::Enum inError)
+ : m_Error(inError)
+ {
+ }
+ SImportResult(const Q3DStudio::CFilePath &inFilePath, QT3DSU32 inFileVersion);
+};
+
+// The file path
+
+class CPerformImport
+{
+public:
+ // Note that the translator has the source file in all the functions below,
+ // so we don't pass in "colladaFile" anywhere but we get the source file
+ // from the translator.
+
+ /**
+ * Exception safe! translator and importer are always released!!
+ * 2. Perform translation to import format
+ * 3. Diff original with new translation
+ * 4. Transfer results to each composer interface
+ * 5. Save import results out original file under new version
+ * 6. Release translator and importer
+ *
+ * This interface is meant to refresh each and every composer interface
+ * that was imported.
+ */
+ static SImportResult RefreshToComposer(ITranslator &translator, IComposerEditor &inComposers,
+ Import &inOriginalFile,
+ const Q3DStudio::CFilePath &ioImportFile);
+
+ /**
+ * Exception safe! translator and importer are always released!!
+ * 1. Load original file
+ * 2. Perform translation to import format
+ * 3. Diff original with new translation
+ * 4. Transfer results to each composer interface
+ * 5. Save import results out original file under new version
+ * 6. Release translator and importer
+ *
+ * This interface is meant to refresh each and every composer interface
+ * that was imported.
+ */
+ static SImportResult RefreshToComposer(ITranslator &translator, IComposerEditor &inComposers,
+ const Q3DStudio::CFilePath &ioImportFile);
+ /**
+ * Exception safe! translator and importer are always released!!
+ * 1. Create blank importer
+ * 2. Perform translation to import format
+ * 3. Transfer result to composer and update import with uicdm handles
+ * 4. Save import results out into destination
+ * 5. Release translator and importer
+ *
+ * If the import file exists, a new import version will be written to the file.
+ */
+ static SImportResult ImportToComposer(ITranslator &translator, IComposerEditor &composer,
+ const Q3DStudio::CFilePath &inImportFile);
+
+ /**
+ * Load the dest file, and import the objects into composer.
+ * Do steps 3+ of ImportToComposer (sans save step).
+ *
+ * The import file must exist.
+ */
+ static SImportResult ImportToComposerFromImportFile(IComposerEditor &composer,
+ const Q3DStudio::CFilePath &inImportFile);
+
+ /**
+ * Translate an outside file type to an import file but don't import that file. If thei mport
+ *file exists a new
+ * version is written to the import file.
+ */
+ static SImportResult TranslateToImportFile(ITranslator &translator,
+ const Q3DStudio::CFilePath &inImportFile);
+
+ static void DoImportToComposer(Import &import, IComposerEditor &composer);
+};
+}
+#endif
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaAnimationUtils.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaAnimationUtils.h
new file mode 100644
index 00000000..c307c800
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaAnimationUtils.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+#include "UICImportTranslationCommon.h"
+#include "dom/domTranslate.h"
+#include "dom/domCommon_color_or_texture_type.h"
+#include "dom/domCg_param_type.h"
+#include "dom/domCommon_newparam_type.h"
+#include "dom/domGles_basic_type_common.h"
+#include "dom/domGlsl_param_type.h"
+#include "dom/domFx_sampler1D_common.h"
+#include "dom/domFx_sampler2D_common.h"
+#include "dom/domFx_sampler3D_common.h"
+#include "dom/domFx_samplerCUBE_common.h"
+#include "dom/domFx_samplerDEPTH_common.h"
+#include "dom/domFx_samplerRECT_common.h"
+#include "dom/domSource.h"
+
+namespace UICIMP {
+
+typedef std::vector<std::string> TStringList;
+
+//==============================================================================
+/**
+ * Converts a Collada <rotate> tag into a x, y or z rotation.
+ * This only works when one axis is being animated.
+ */
+const char *FindRotationAxis(daeDoubleArray *inRotationArray)
+{
+ daeDoubleArray &theArray = *inRotationArray;
+
+ if (theArray[0] == 1 && theArray[1] == 0 && theArray[2] == 0)
+ return "rotate.x";
+ else if (theArray[0] == 0 && theArray[1] == 1 && theArray[2] == 0)
+ return "rotate.y";
+ else if (theArray[0] == 0 && theArray[1] == 0 && theArray[2] == 1)
+ return "rotate.z";
+
+ return NULL;
+}
+
+inline int GetElementType(daeElement &inElement)
+{
+#define MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domType, colldataType) \
+ if (dynamic_cast<ColladaDOM141::domType *>(&inElement)) \
+ return COLLADA_TYPE::colldataType;
+
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domRotate, ROTATE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domTranslate, TRANSLATE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domScale, SCALE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domMatrix, MATRIX);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domCommon_color_or_texture_type_complexType::domColor, COLOR);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domCg_param_type::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domCommon_float_or_param_type_complexType::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domCommon_newparam_type_complexType::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_annotate_type_common::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_basic_type_common::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domGles_basic_type_common::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domGlsl_param_type::domFloat, FLOAT);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domSource, SOURCE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_samplerRECT_common_complexType::domSource, SOURCE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_samplerDEPTH_common_complexType::domSource, SOURCE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_samplerCUBE_common_complexType::domSource, SOURCE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_sampler3D_common_complexType::domSource, SOURCE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_sampler2D_common_complexType::domSource, SOURCE);
+ MAP_DYNAMIC_TYPE_TO_COLLADA_TYPE(domFx_sampler1D_common_complexType::domSource, SOURCE);
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Retrieves information about the animated element.
+ * Finds out the animated property name (using the element's name or it's parent's name).
+ * Determines the sub components of the property (e.g. xyz or rgb)
+ * Looks for the element that is the target of the animation.
+ */
+const char *GetAnimatedPropertyInfoFromElement(const char *inTarget, domCOLLADA *inColladaRoot,
+ daeElement *&outContainerElement,
+ TStringList &outIdentifiers)
+{
+ daeSidRef::resolveData theData = daeSidRef(inTarget, inColladaRoot).resolve();
+
+ // Push any identifiers after the '.' into the identifier list
+ std::string theIdentifier(inTarget);
+ std::string::size_type theOffset = theIdentifier.rfind('.');
+ if (theOffset != std::string::npos)
+ outIdentifiers.push_back(theIdentifier.substr(theOffset + 1));
+
+ if (theData.elt) {
+ outContainerElement = theData.elt;
+
+ // HACK: Special case for animation on the angle component of <rotate>
+ if (GetElementType(*outContainerElement) == COLLADA_TYPE::ROTATE && theData.scalar
+ && (std::find(outIdentifiers.begin(), outIdentifiers.end(), "ANGLE")
+ != outIdentifiers.end()
+ || std::find(outIdentifiers.begin(), outIdentifiers.end(), "W")
+ != outIdentifiers.end())) {
+ return FindRotationAxis(theData.array);
+ } else if (outIdentifiers.empty()) // If no identifiers found at the end of inTarget, obtain
+ // identifiers based on the element that is being
+ // animated.
+ {
+ switch (GetElementType(*outContainerElement)) {
+ case COLLADA_TYPE::TRANSLATE:
+ case COLLADA_TYPE::SCALE:
+ outIdentifiers = g_XYZIdentifiers;
+ break;
+ case COLLADA_TYPE::ROTATE:
+ // outIdentifiers = g_XYZANGLEIdentifiers; // TODO: We don't support x,y,z,angle
+ // animation currently
+ break;
+ case COLLADA_TYPE::COLOR:
+ outIdentifiers = g_RGBAIdentifiers;
+ break;
+ case COLLADA_TYPE::FLOAT:
+ outIdentifiers = g_FLOATIdentifiers; // Actually, there wouldn't be any name in the
+ // accessor param for single float animations.
+ // This is just a placeholder.
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The element's or parent's name will be used as the name of the base property to animate.
+ switch (GetElementType(*outContainerElement)) {
+ case COLLADA_TYPE::TRANSLATE:
+ case COLLADA_TYPE::SCALE:
+ case COLLADA_TYPE::ROTATE:
+ return theData.elt->getElementName();
+ break;
+ case COLLADA_TYPE::COLOR:
+ case COLLADA_TYPE::FLOAT:
+ return outContainerElement->getParentElement()->getElementName();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return "";
+}
+} \ No newline at end of file
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaDOMUtils.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaDOMUtils.h
new file mode 100644
index 00000000..14e7e3d7
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaDOMUtils.h
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+#include "UICImportSceneGraphTranslation.h"
+#include "UICImportTranslationCommon.h"
+#include "UICImportColladaAnimationUtils.h"
+
+namespace UICIMP {
+
+typedef struct _SSourceArrayInfo
+{
+ long m_POffset;
+ long m_Stride;
+ std::vector<long> m_Offset;
+ domFloat_arrayRef m_Array;
+
+ _SSourceArrayInfo()
+ : m_POffset(-1)
+ , m_Stride(-1)
+ , m_Array(NULL)
+ {
+ }
+} SSourceArrayInfo;
+
+//==============================================================================
+/**
+ * Attempts to retrieve an identifier string from an daeElement.
+ * The precedence is to try to use 'name' first, failing that the 'id' and lastly
+ * the 'sid'.
+ */
+const char *GetNameOrIDOrSid(const daeElement *inElement)
+{
+ static std::string theBuffer;
+
+ daeElement *theElement = const_cast<daeElement *>(inElement);
+
+ theBuffer.clear();
+
+ if (theElement->isAttributeSet("name"))
+ theElement->getAttribute("name", theBuffer);
+ else if (theElement->isAttributeSet("id"))
+ theElement->getAttribute("id", theBuffer);
+ else if (theElement->isAttributeSet("sid"))
+ theElement->getAttribute("sid", theBuffer);
+ else
+ return theElement->getElementName();
+
+ return theBuffer.c_str();
+}
+
+static inline float GetFloatFromElementChar(const daeElementRef inElement)
+{
+ return static_cast<float>(::atof(inElement->getCharData().c_str()));
+}
+
+static inline int GetIntFromElementChar(const daeElementRef inElement)
+{
+ return ::atoi(inElement->getCharData().c_str());
+}
+
+//==============================================================================
+/**
+ * Helper function to retrieve the appropriate source array for this input semantic.
+ */
+void GetSourceArrayInfo(
+ const domSource *inDomSource, const TStringList &inParamIdentifiers, long inPOffset,
+ SSourceArrayInfo &outArrayInfo,
+ std::function<void(ESceneGraphWarningCode, const char *)> inLogWarningFunction = NULL)
+{
+ if (outArrayInfo.m_POffset > -1) // we don't support multiple array infos (ex: collada file with
+ // multiple TEXCOORD for the same triangle)
+ {
+ if (inLogWarningFunction)
+ inLogWarningFunction(ESceneGraphWarningCode_TrianglesDuplicateSemantic,
+ GetNameOrIDOrSid(inDomSource));
+ return;
+ }
+
+ outArrayInfo.m_POffset = inPOffset;
+ outArrayInfo.m_Stride =
+ (long)inParamIdentifiers.size(); // Assumption in case domTechnique_common does not exist
+
+ outArrayInfo.m_Array = inDomSource->getFloat_array(); // TODO: Support other array types?
+
+ for (long theIdentifierIndex = 0; theIdentifierIndex < (long)inParamIdentifiers.size();
+ ++theIdentifierIndex)
+ outArrayInfo.m_Offset.push_back(-1);
+
+ const domSource::domTechnique_commonRef theTechniqueCommonRef =
+ inDomSource->getTechnique_common();
+ if (theTechniqueCommonRef) {
+ domAccessorRef theAccessorRef = theTechniqueCommonRef->getAccessor();
+ outArrayInfo.m_Stride = (long)theAccessorRef->getStride();
+
+ const domParam_Array &theParamsArray = theAccessorRef->getParam_array();
+ long theParamCount = (long)theParamsArray.getCount();
+
+ // Search for required identifiers and their relative indicies within the array
+ for (long theIdentifierIndex = 0; theIdentifierIndex < (long)inParamIdentifiers.size();
+ ++theIdentifierIndex) {
+ for (long theParamIndex = 0; theParamIndex < theParamCount; ++theParamIndex) {
+ // Skip param indicies that have already been assigned, since repeats of the same
+ // param is possible
+ if (std::find(outArrayInfo.m_Offset.begin(), outArrayInfo.m_Offset.end(),
+ theParamIndex)
+ != outArrayInfo.m_Offset.end())
+ continue;
+
+ const daeString &theParamName = theParamsArray[theParamIndex]->getName();
+
+ if (!theParamName)
+ outArrayInfo.m_Offset[theIdentifierIndex] = theParamIndex;
+ // Valid param name present
+ else if (qstricmp(theParamName, inParamIdentifiers[theIdentifierIndex].c_str())
+ == 0) {
+ outArrayInfo.m_Offset[theIdentifierIndex] =
+ theParamIndex; // Get the actual offset within the params for identifiers
+ // that we are interested in
+ break;
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Helper function to retrieve the appropriate source array for this input semantic.
+ */
+void GetDomSourceArrayAndVectorCapacity(
+ const domInputLocalOffsetRef inInputOffsetRef, const TStringList &inParamIdentifiers,
+ SSourceArrayInfo &outArrayInfo,
+ std::function<void(ESceneGraphWarningCode, const char *)> inLogWarningFunction = NULL)
+{
+ domSource *theDomSource = NULL;
+
+ daeElement *theInputSource = inInputOffsetRef->getSource().getElement();
+ switch (GetElementType(*theInputSource)) {
+ case COLLADA_TYPE::SOURCE:
+ theDomSource = daeSafeCast<domSource>(theInputSource);
+ break;
+ default:
+ break;
+ }
+
+ GetSourceArrayInfo(theDomSource, inParamIdentifiers, (long)inInputOffsetRef->getOffset(),
+ outArrayInfo, inLogWarningFunction);
+}
+
+//==============================================================================
+/**
+ * Helper function to retrieve the appropriate source array for this input semantic.
+ */
+void GetDomSourceArrayInfo(const domInputLocal_Array &inInputsArray, const char *inSemantic,
+ const TStringList &inParamIdentifiers, SSourceArrayInfo &outArrayInfo)
+{
+ long theInputOffsetsCount = (long)inInputsArray.getCount();
+
+ // Retrieve the appropriate source array depending on the semantic name (inputs with offsets)
+ for (long theIndex = 0; theIndex < theInputOffsetsCount; ++theIndex) {
+ const domInputLocalRef theInputRef = inInputsArray[theIndex];
+ const char *theSemantic = theInputRef->getSemantic();
+
+ if (::strcmp(theSemantic, inSemantic) == 0) {
+ domSource *theDomSource = daeSafeCast<domSource>(theInputRef->getSource().getElement());
+ GetSourceArrayInfo(theDomSource, inParamIdentifiers, -1, outArrayInfo);
+ break;
+ }
+ }
+
+ return;
+}
+
+//==============================================================================
+/**
+ * Helper function to push raw float values into outVector.
+ */
+void Push3Floats(std::vector<float> &outVector, unsigned long inFaceIndex, const float *inValues)
+{
+ inFaceIndex *= 3;
+
+ outVector[inFaceIndex] = inValues[0];
+ outVector[inFaceIndex + 1] = inValues[1];
+ outVector[inFaceIndex + 2] = inValues[2];
+}
+
+//==============================================================================
+/**
+ * Helper function to push raw float values into outVector.
+ */
+void Push2Floats(std::vector<float> &outVector, unsigned long inFaceIndex, const float *inValues)
+{
+ inFaceIndex *= 2;
+
+ outVector[inFaceIndex] = inValues[0];
+ outVector[inFaceIndex + 1] = inValues[1];
+}
+
+//==============================================================================
+/**
+ * Retrieves float values from a source array given the array index.
+ */
+void GetFaceTupleValue(float *outValues, const SSourceArrayInfo &inSourceArray,
+ unsigned long inArrayIndex)
+{
+ inArrayIndex %= ULONG_MAX; // Fixes any overflowed indicies due to bad Collada data.
+
+ long theIdentifiersCount = (long)inSourceArray.m_Offset.size();
+ inArrayIndex *= inSourceArray.m_Stride;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // This helps some bogus .dae files load. Today we're loading:
+ // //sw/devtools/metools/public/UIComposer/Main/Test/Collada/Maya/2009/NextGen/SimpleTexture.dae
+ while (inArrayIndex >= inSourceArray.m_Array->getCount())
+ inArrayIndex -= inSourceArray.m_Stride;
+ //////////////////////////////////////////////////////////////////////////////
+
+ for (long theIdentifierIndex = 0; theIdentifierIndex < theIdentifiersCount;
+ ++theIdentifierIndex) {
+ outValues[theIdentifierIndex] =
+ (float)inSourceArray.m_Array
+ ->getValue()[inArrayIndex + inSourceArray.m_Offset[theIdentifierIndex]];
+ }
+}
+
+//==============================================================================
+/**
+ * Retrieves float values from a source array given the array index.
+ * Here we assume a packed source array with 3 components
+ */
+void GetFaceTupleValue(float *outValues, const std::vector<SVector3> &inSourceArray,
+ unsigned long inArrayIndex)
+{
+ inArrayIndex %= ULONG_MAX; // Fixes any overflowed indicies due to bad Collada data.
+
+ outValues[0] = inSourceArray[inArrayIndex][0];
+ outValues[1] = inSourceArray[inArrayIndex][1];
+ outValues[2] = inSourceArray[inArrayIndex][2];
+}
+
+//==============================================================================
+/**
+ * Find an element using it's SID.
+ */
+bool FindElementBySid(const xsNCName &inSidString, daeElement *&outElement,
+ const daeElement *inContainerElement)
+{
+ outElement = NULL;
+
+ outElement = daeSidRef(inSidString, const_cast<daeElement *>(inContainerElement)).resolve().elt;
+ if (outElement != NULL)
+ return true;
+ else
+ return false;
+}
+
+//==============================================================================
+/**
+ * Recursively travel through parents in an attempt to find an element using it's SID.
+ * inStartElement defines where to start looking for.
+ * inStartAtType and inEndAtAtype determines which element types to start and end the seatch.
+ * All elements in the middle of the two are searched as well.
+ * Supplying a -1 for inStartAtType starts the search immediately from inStartElement.
+ */
+bool RecursiveFindElementBySid(const xsNCName &inSidString, daeElement *&outElement,
+ daeElement *inStartElement, const daeInt inStartAtType,
+ const daeInt inEndAtType, bool inBegin = false)
+{
+ if (inStartElement == NULL)
+ return false;
+
+ daeInt theStartType = inStartElement->typeID();
+
+ if (theStartType == inStartAtType
+ || inStartAtType == -1) // -1 means start the search immediately
+ inBegin = true;
+
+ if (inBegin) {
+ if (FindElementBySid(inSidString, outElement, inStartElement))
+ return true;
+ else if (theStartType != inEndAtType)
+ return RecursiveFindElementBySid(inSidString, outElement, inStartElement->getParent(),
+ inStartAtType, inEndAtType, inBegin);
+ } else
+ return RecursiveFindElementBySid(inSidString, outElement, inStartElement->getParent(),
+ inStartAtType, inEndAtType, inBegin);
+
+ return false;
+}
+
+//==============================================================================
+/**
+ * Helper macros for accessing color, float and texture params for profile_common
+ * material properties.
+ */
+// Begin macro defination
+#define BeginCommonTechniqueObject(inProfileObject, inTechniqueType) \
+ { \
+ const domProfile_COMMON::domTechnique::dom##inTechniqueType##Ref theTechniqueObject = \
+ inProfileObject->get##inTechniqueType(); \
+ if (theTechniqueObject != NULL) { \
+ SMaterialParameters theMaterialParameters( \
+ EMatCommonProfileTechnique_##inTechniqueType); \
+ ProcessProfileCommonTechniqueExtra(inProfileObject, theMaterialParameters.m_Extra);
+
+#define EndCommonTechniqueObject() \
+ SetMaterial(theMaterialParameters); \
+ } \
+ }
+
+#define ProcessFloatParam(inParamName) \
+ { \
+ domCommon_float_or_param_typeRef theFloatOrParamRef = \
+ theTechniqueObject->get##inParamName(); \
+ if (theFloatOrParamRef) { \
+ domCommon_float_or_param_type::domFloatRef theFloatRef = \
+ theFloatOrParamRef->getFloat(); \
+ if (theFloatRef) \
+ theMaterialParameters.m_##inParamName.SetValue((float)theFloatRef->getValue()); \
+ } \
+ }
+
+#define ProcessColorOrTextureParam(inParamName, inMapType) \
+ GetColorOrTextureParamInfo(theTechniqueObject->get##inParamName(), \
+ theMaterialParameters.m_##inParamName, inMapType);
+
+#define ProcessTransparentParam(inParamName) \
+ domCommon_transparent_typeRef theTransparentParamRef = theTechniqueObject->get##inParamName(); \
+ if (theTransparentParamRef) { \
+ theMaterialParameters.m_##inParamName##OpaqueType.SetValue( \
+ theTransparentParamRef->getOpaque()); \
+ GetColorOrTextureParamInfo(theTransparentParamRef, theMaterialParameters.m_##inParamName, \
+ ETextureMapTypeOpacity); \
+ }
+
+// End macro definations
+}
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaSGTranslation.cpp b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaSGTranslation.cpp
new file mode 100644
index 00000000..181f10bf
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaSGTranslation.cpp
@@ -0,0 +1,1634 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "dae.h"
+#include "dom/domCOLLADA.h"
+#include "dom/domConstants.h"
+#include "dom/domCommon_float_or_param_type.h"
+#include "dom/domCommon_transparent_type.h"
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include "UICMath.h"
+#include "UICImportColladaDOMUtils.h"
+#include "UICImportColladaTransformUtils.h"
+#include "UICImportColladaAnimationUtils.h"
+#include "foundation/Qt3DSVec3.h"
+#include <memory>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/tuple/tuple.hpp>
+#include "dom/domElements.h"
+#include "dom/domProfile_COMMON.h"
+#include "dom/domCommon_color_or_texture_type.h"
+#include "UICImportTranslationCommon.h"
+#include "UICImportSceneGraphTranslation.h"
+#include "UICImportTranslation.h"
+
+#include <QByteArray>
+
+using namespace UICIMP;
+
+namespace {
+//==============================================================================
+// Loads Collada document and processes it.
+// It starts 'walking' begining with the visual_scene, and calls various
+// function objects to process each encountered element hierachically.
+// A stack concept is used here to denote the active element being processed.
+// This flows nicely with the XML structure of the Collada file.
+//==============================================================================
+class ColladaDOMWalker
+{
+public:
+ ColladaDOMWalker(ISceneGraphTranslation *inTranslation);
+ ~ColladaDOMWalker();
+
+public:
+ typedef boost::tuple<SVector3, SVector3, SVector2, SVector3, SVector3, SVector2>
+ TVertexInfoTuple;
+ typedef std::vector<std::pair<std::string, daeURI>> TURIList;
+ typedef std::pair<std::map<TVertexInfoTuple, long>,
+ std::vector<std::pair<std::string, TLongsList>>>
+ TFaceIndicies;
+
+ typedef std::multimap<const daeElement *, long> TElementToIndicesMap;
+
+public:
+ bool LoadDocument(const std::string &inFilePath);
+ void ProcessScene();
+ void ProcessLibraryAnimations();
+
+protected:
+ void SetFColladaAuthoringTool(const char *inName);
+ long GetFColladaVersion(std::string theAuthoringToolLowerCase);
+
+ void ProcessVisualScene(domVisual_scene *inVisualScene);
+ void ProcessNode(const domNodeRef inNode);
+ bool ProcessInstanceGeometry(const domNodeRef inNode,
+ domInstance_geometryRef inInstanceGeometryRef);
+ void ProcessGeometry(const domGeometry *inGeometry, TFaceIndicies &ioIndicies);
+ void ProcessTriangle(const domTrianglesRef inTrianglesRef, TFaceIndicies &ioFaceIndicies,
+ bool &outHasNormals, bool &outHasTexCoords, bool &outHasTexCoords2,
+ bool &outHasTexTangents, bool &outHasTexBinormals);
+ void GenerateMeshTangents(const domTrianglesRef inTrianglesRef,
+ const SSourceArrayInfo &inVertexArrayInfo,
+ const SSourceArrayInfo &inNormalArrayInfo,
+ const SSourceArrayInfo &inTexCoordArrayInfo,
+ const SSourceArrayInfo &inTexCoord2ArrayInfo,
+ std::vector<SVector3> &outTangents,
+ std::vector<SVector3> &outBinormals);
+ void ProcessTransform(const domNodeRef inNode);
+ void ProcessBindMaterial(const domBind_materialRef inBindMaterialRef,
+ const TFaceIndicies &inFaceIndicies);
+ void ProcessDefaultMaterial(const TFaceIndicies &inFaceIndicies);
+ void ProcessInstanceMaterial(const domInstance_materialRef inInstanceMaterialRef);
+ void ProcessMaterial(const domMaterial *inMaterial);
+ void ProcessInstanceEffect(const domInstance_effectRef inEffectRef);
+ void ProcessEffect(const domEffect *inEffect);
+ void ProcessProfile(const domFx_profile_abstractRef &inProfile);
+ void ProcessProfileCommon(const domProfile_COMMON *inProfileCommon);
+ void ProcessProfileCommonTechnique(const domProfile_COMMON::domTechniqueRef inTechniqueRef);
+ void ProcessProfileCommonTechniqueExtra(const domProfile_COMMON::domTechniqueRef inTechniqueRef,
+ SMaterialExtraParameters &outMaterialExtraParameters);
+ void
+ ProcessTexture(const domCommon_color_or_texture_type_complexType::domTextureRef inTextureRef,
+ long inMapType);
+ void ProcessTextureParameters(const domExtraRef inTextureExtraRef,
+ STextureParameters &outTextureParameters);
+
+ void ProcessAnimations(const domLibrary_animationsRef inLibraryAnimation);
+ void ProcessAnimation(const domAnimationRef inAnimation);
+ void ProcessChannel(const domChannelRef inChannel);
+ void ProcessSampler(const domSampler *inSamplerRef, daeElement *inSourceElement,
+ const char *inBaseProperty, const TStringList &inIdentifiers);
+
+protected:
+ void GetColorOrTextureParamInfo(
+ const domCommon_color_or_texture_type_complexType *inColorOrTexturePtr,
+ SColorOrTexture &outColor, long inMapType);
+ daeElement *FindElementByID(const char *inElementID);
+ void TrackObjectIndex(const daeElement *inElement, long inIndex);
+ void GetIndicesFromElement(const daeElement *inElement, TLongsList &outIndicies);
+ bool ApplyAnimation(const daeElement *inContainerElement);
+
+protected:
+ boost::function<void(const char *)> PushGroup;
+ boost::function<void()> PopGroup;
+ boost::function<void(const char *)> PushModel;
+ boost::function<void()> PopModel;
+ boost::function<void(const char *)> PushMaterial;
+ boost::function<void(long, long)> PopMaterial;
+ boost::function<void(const char *, const char *, long)> PushTexture;
+ boost::function<void()> PopTexture;
+ boost::function<void(daeElement *inElement)> CacheAnimationTrack;
+ boost::function<void(long)> ApplyAnimationTrack;
+
+protected:
+ boost::function<void()> MarkInvalid;
+
+protected:
+ boost::function<void(EAuthoringToolType, long)> SetAuthoringTool;
+ boost::function<void(const TTransformList &inTransforms)> SetTransforms;
+ boost::function<void(const SMaterialParameters &inMaterialParameters)> SetMaterial;
+ boost::function<void(long inMapType, const STextureParameters &inTextureParameters)> SetTexture;
+
+ boost::function<void(const char *, const char *)> SetAnimationTrack;
+ boost::function<void(const char *, const char *, const SKeyframeParameters &)>
+ CacheAnimationKey;
+
+ static void dummy() {}
+
+protected:
+ boost::function<void(ESceneGraphWarningCode, const char *)> LogWarning;
+
+protected:
+ std::auto_ptr<DAE> m_DAE;
+ domCOLLADA *m_ColladaRoot;
+ ISceneGraphTranslation *m_Translator;
+ const char *m_DAEFilename;
+ TElementToIndicesMap m_ElementToIndicies;
+};
+
+void FindTexturesViaNewParam(daeElement *inElementPtr, ColladaDOMWalker::TURIList &outTexturePaths)
+{
+ domCommon_newparam_type *theNewParam = daeSafeCast<domCommon_newparam_type>(inElementPtr);
+
+ if (theNewParam) {
+ const domFx_sampler2D_commonRef theSampler2DRef = theNewParam->getSampler2D();
+
+ if (theSampler2DRef) // Found a <sampler2D>, follow through to get to <surface>
+ {
+ const domFx_sampler2D_common_complexType::domSourceRef theSourceRef =
+ theSampler2DRef->getSource();
+ if (theSourceRef) {
+ const xsNCName theSourceSid = theSourceRef->getValue();
+
+ daeElement *theSurfaceNewParamPtr = NULL;
+ if (RecursiveFindElementBySid(theSourceSid, theSurfaceNewParamPtr,
+ theNewParam->getParent(), -1, domEffect::ID())) {
+ FindTexturesViaNewParam(theSurfaceNewParamPtr, outTexturePaths);
+ }
+ }
+ } else {
+ const domFx_surface_commonRef theSurfaceRef = theNewParam->getSurface();
+ if (theSurfaceRef) // Found a <surface>, get the referenced texture from
+ // <library_images>
+ {
+ const domFx_surface_init_commonRef theSurfaceInitCommonRef =
+ theSurfaceRef->getFx_surface_init_common(); // look for <init_XXX>s
+ if (theSurfaceInitCommonRef) {
+ const domFx_surface_init_from_common_Array &theInitFromArray =
+ theSurfaceInitCommonRef->getInit_from_array(); // look for <init_from>s
+ long theTextureCount = (long)theInitFromArray.getCount();
+ for (long theIndex = 0; theIndex < theTextureCount; ++theIndex) {
+ const xsIDREF &theTextureRef = theInitFromArray[theIndex]->getValue();
+ domImage *theImage = daeSafeCast<domImage>(theTextureRef.getElement());
+ if (theImage) {
+ const domImage::domInit_fromRef theInitFromRef =
+ theImage->getInit_from();
+ if (theInitFromRef)
+ outTexturePaths.push_back(
+ std::make_pair(theImage->getID(), theInitFromRef->getValue()));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Returns a unique face index which is made up of a vertex, normal and
+ * texcoord index tuple.
+ * The order of ioFaceIndicies.first eventually becomes the order which we will
+ * fill the vertex, normal and texcoord arrays for Model.
+ */
+long RetrieveFaceIndex(ColladaDOMWalker::TFaceIndicies &ioFaceIndicies,
+ const ColladaDOMWalker::TVertexInfoTuple &inFaceValues)
+{
+ std::pair<ColladaDOMWalker::TFaceIndicies::first_type::iterator, bool> theTupleEntry;
+
+ theTupleEntry = ioFaceIndicies.first.insert(
+ std::make_pair(inFaceValues, (long)(ioFaceIndicies.first.size())));
+
+ return theTupleEntry.first->second;
+}
+
+//==============================================================================
+/**
+ * CTOR
+ * Sets up the ISceneGraphTranslation class and binds function objects to
+ * the actual functions within that class.
+ */
+ColladaDOMWalker::ColladaDOMWalker(ISceneGraphTranslation *inTranslation)
+ : m_ColladaRoot(NULL)
+ , m_Translator(inTranslation)
+{
+ PushGroup = boost::bind(&ISceneGraphTranslation::PushGroup, m_Translator, _1);
+ PopGroup = boost::bind(&ISceneGraphTranslation::PopGroup, m_Translator);
+ PushModel = boost::bind(&ISceneGraphTranslation::PushModel, m_Translator, _1);
+ PopModel = boost::bind(&ISceneGraphTranslation::PopModel, m_Translator);
+
+ PushMaterial = boost::bind(&ISceneGraphTranslation::PushMaterial, m_Translator, _1);
+ PopMaterial = boost::bind(&ISceneGraphTranslation::PopMaterial, m_Translator, _1, _2);
+ PushTexture = boost::bind(&ISceneGraphTranslation::PushTexture, m_Translator, _1, _2, _3);
+ PopTexture = boost::bind(&ISceneGraphTranslation::PopTexture, m_Translator);
+
+ CacheAnimationTrack =
+ boost::bind(&ColladaDOMWalker::TrackObjectIndex, this, _1,
+ boost::bind(&ISceneGraphTranslation::CacheAnimationTrack, m_Translator));
+ ApplyAnimationTrack =
+ boost::bind(&ISceneGraphTranslation::ApplyAnimationTrack, m_Translator, _1);
+
+ MarkInvalid = boost::bind(&ISceneGraphTranslation::MarkInvalid, m_Translator);
+
+ SetAuthoringTool = boost::bind(&ISceneGraphTranslation::SetAuthoringTool, m_Translator, _1, _2);
+
+ SetTransforms = boost::bind(&ISceneGraphTranslation::SetTransforms, m_Translator, _1);
+
+ SetMaterial = boost::bind(&ISceneGraphTranslation::SetMaterial, m_Translator, _1);
+ SetTexture = boost::bind(&ISceneGraphTranslation::SetTexture, m_Translator, _1, _2);
+
+ SetAnimationTrack =
+ boost::bind(&ISceneGraphTranslation::SetAnimationTrack, m_Translator, _1, _2);
+ CacheAnimationKey =
+ boost::bind(&ISceneGraphTranslation::CacheAnimationKey, m_Translator, _1, _2, _3);
+
+ LogWarning = boost::bind(&ISceneGraphTranslation::LogWarning, m_Translator, _1, _2);
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+ColladaDOMWalker::~ColladaDOMWalker()
+{
+}
+
+//==============================================================================
+/**
+ * Loads a Collada document into the Collada DOM.
+ */
+bool ColladaDOMWalker::LoadDocument(const std::string &inFilePath)
+{
+ if (boost::filesystem::exists(inFilePath)) {
+ m_DAE.reset(new DAE);
+ m_ColladaRoot = m_DAE->open141(inFilePath);
+ m_DAEFilename = inFilePath.c_str();
+
+ // Extract authoring_tool information
+ const domAssetRef theAssetRef = m_ColladaRoot->getAsset();
+ if (theAssetRef) {
+ const domAsset::domContributor_Array theContributorArray =
+ theAssetRef->getContributor_array();
+ long theContributorCount = (long)theContributorArray.getCount();
+ for (long theIndex = 0; theIndex < (long)theContributorCount; ++theIndex) {
+ const domAsset::domContributor::domAuthoring_toolRef theAuthoringTool =
+ theContributorArray[theIndex]->getAuthoring_tool();
+ if (theAuthoringTool) {
+ // There may be > 1 authoring tool in dae. But currently only take the 1st one
+ // we find
+ SetFColladaAuthoringTool(theAuthoringTool->getValue());
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+//==============================================================================
+/**
+ * Starts the import process.
+ * This begins by looking at the active visual_scene node and starting import
+ * from that node.
+ */
+void ColladaDOMWalker::ProcessScene()
+{
+ if (m_ColladaRoot != NULL) {
+ const domCOLLADA::domSceneRef theScene = m_ColladaRoot->getScene();
+ // Retrieve the active visual_scene
+ const domInstanceWithExtraRef theInstanceVisualScene = theScene->getInstance_visual_scene();
+ const xsAnyURI &theVisualSceneURI = theInstanceVisualScene->getUrl();
+ const daeElementRef theVisualSceneRef = theVisualSceneURI.getElement();
+ domVisual_scene *theVisualScene = daeSafeCast<domVisual_scene>(theVisualSceneRef);
+
+ // Get the up axis for this COLLADA doc
+ // TODO: Collada specs does allow up-axis to vary within the DAE, but I have not seen a DAE
+ // that does that.
+ // We might need to support varying up-axis in the future.
+ domUpAxisType theAxisType = UPAXISTYPE_Y_UP;
+ const domAssetRef theAssetRef = m_ColladaRoot->getAsset();
+ if (theAssetRef) {
+ const domAsset::domUp_axisRef theUpAxisRef = theAssetRef->getUp_axis();
+ if (theUpAxisRef)
+ theAxisType = theUpAxisRef->getValue();
+ }
+
+ // Disable wrapping the visual scene in it's own group, since m_TopMostParent exists
+ // We might encounter DAEs that have multiple <visual_scene>s
+ // PushGroup( GetNameOrIDOrSid( theVisualScene ) );
+
+ switch (theAxisType) {
+ // TODO: What about X up?
+ case UPAXISTYPE_Z_UP: {
+ std::vector<INodeTransform *> theTransforms;
+
+ NodeTransform *theRotX = new NodeTransform(ETransformType_Rotation4);
+ (*theRotX)[0] = 1.0f;
+ (*theRotX)[1] = (*theRotX)[2] = 0.0f;
+ (*theRotX)[3] =
+ -90.0f; // Apply a -90 degree rotation on the X-axis to 'right' the model
+ theTransforms.push_back(theRotX);
+
+ SetTransforms(theTransforms);
+ delete theRotX;
+ } break;
+ default:
+ break;
+ }
+
+ ProcessVisualScene(theVisualScene);
+
+ // Disable wrapping the visual scene in it's own group, since m_TopMostParent exists
+ // PopGroup( );
+ }
+}
+
+void ColladaDOMWalker::SetFColladaAuthoringTool(const char *inName)
+{
+ // There may be > 1 authoring tool in dae. But currently only take the 1st one we find
+
+ // Guess the authoring tool type & version
+ // This looks very hackish because there is no standard and it is based on the test data that I
+ // have
+ const std::string theAuthoringToolLowerCase = QByteArray::fromRawData(inName, strlen(inName)).toLower().toStdString();
+
+ EAuthoringToolType theAuthoringToolType = EAuthoringToolType_Unknown;
+ if (theAuthoringToolLowerCase.find("studiocore") != std::string::npos) {
+ theAuthoringToolType = EAuthoringToolType_StudioCORE;
+ } else if (theAuthoringToolLowerCase.find("cinema4d") != std::string::npos) {
+ theAuthoringToolType = EAuthoringToolType_Cinema4D;
+ } else if (theAuthoringToolLowerCase.find("sketchup") != std::string::npos) {
+ theAuthoringToolType = EAuthoringToolType_SketchUp;
+ } else if (theAuthoringToolLowerCase.find("nextgen") != std::string::npos) {
+ if (theAuthoringToolLowerCase.find("max") != std::string::npos) {
+ // Max NextGen 0.9.5 will export something like this:
+ // <authoring_tool>COLLADAMax NextGen; Version: 0.9.5; Revision: 447; Platform:
+ // Win32; Configuration: Release Max2009</authoring_tool>
+ theAuthoringToolType = EAuthoringToolType_NextGen_Max;
+ } else // if ( theAuthoringToolLowerCase.find( "maya" ) != std::string::npos )
+ {
+ theAuthoringToolType = EAuthoringToolType_NextGen_Maya;
+ }
+ } else if (theAuthoringToolLowerCase.find("feeling") != std::string::npos
+ || theAuthoringToolLowerCase.find("fcollada") != std::string::npos) {
+ if (theAuthoringToolLowerCase.find("max") != std::string::npos) {
+ // ColladaMax 3.0.5C will export something like this:
+ // <authoring_tool>3dsMax 11 - Feeling ColladaMax v3.05B.</authoring_tool>
+ theAuthoringToolType = EAuthoringToolType_FCollada_Max;
+ } else // if ( theAuthoringToolLowerCase.find( "maya" ) != std::string::npos )
+ {
+ // <authoring_tool>Maya 8.5 | ColladaMaya v3.02 | FCollada v3.2</authoring_tool>
+ theAuthoringToolType = EAuthoringToolType_FCollada_Maya;
+ }
+ } else if (theAuthoringToolLowerCase.find("collada maya") != std::string::npos) {
+ // Maya NextGen 0.9.5 will export something like this:
+ // <authoring_tool>COLLADA Maya2009</authoring_tool>
+ theAuthoringToolType = EAuthoringToolType_NextGen_Maya;
+ } else if (theAuthoringToolLowerCase.find("colladamaya") != std::string::npos) {
+ // ColladaMaya 3.05C will export something like this:
+ // <authoring_tool>Maya2008 | ColladaMaya v3.05B</authoring_tool>
+ // Other version of ColladaMaya:
+ // <authoring_tool>Maya8.5 | ColladaMaya v3.04E</authoring_tool>
+ theAuthoringToolType = EAuthoringToolType_FCollada_Maya;
+ } else if (theAuthoringToolLowerCase.find("colladamax") != std::string::npos) {
+ theAuthoringToolType = EAuthoringToolType_FCollada_Max;
+ } else if (theAuthoringToolLowerCase.find("opencollada") != std::string::npos
+ && theAuthoringToolLowerCase.find("3ds max") != std::string::npos) {
+ theAuthoringToolType = EAuthoringToolType_FCollada_Max;
+ }
+
+ long theAuthoringToolVersion = 0;
+ if (theAuthoringToolType == EAuthoringToolType_FCollada_Max
+ || theAuthoringToolType == EAuthoringToolType_FCollada_Maya)
+ theAuthoringToolVersion = GetFColladaVersion(theAuthoringToolLowerCase);
+
+ SetAuthoringTool(theAuthoringToolType, theAuthoringToolVersion);
+}
+
+long ColladaDOMWalker::GetFColladaVersion(std::string theAuthoringToolLowerCase)
+{
+ // Quick & dirty way to get the version
+ if (theAuthoringToolLowerCase.find("v3.05") != std::string::npos)
+ return 305;
+ else if (theAuthoringToolLowerCase.find("v3.04") != std::string::npos)
+ return 304;
+ else if (theAuthoringToolLowerCase.find("v3.03") != std::string::npos)
+ return 303;
+ else if (theAuthoringToolLowerCase.find("v3.02") != std::string::npos)
+ return 302;
+ else if (theAuthoringToolLowerCase.find("v3.01") != std::string::npos)
+ return 301;
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Process nodes in the visual_scene.
+ */
+void ColladaDOMWalker::ProcessVisualScene(domVisual_scene *inVisualScene)
+{
+ const domNode_Array &theNodes = inVisualScene->getNode_array();
+ long theNodeCount = (long)theNodes.getCount();
+
+ for (long theIndex = 0; theIndex < theNodeCount; ++theIndex) {
+ ProcessNode(theNodes[theIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Process a <node> object.
+ * This ia recursive and may end up creating parent-child node objects.
+ */
+void ColladaDOMWalker::ProcessNode(const domNodeRef inNode)
+{
+ switch (inNode->getType()) {
+ case NODETYPE_NODE: {
+ const domInstance_geometry_Array &theInstanceGeometryArray =
+ inNode->getInstance_geometry_array();
+ long theGeometryCount = (long)theInstanceGeometryArray.getCount();
+ bool thePushModelFlag = false;
+
+ if (theGeometryCount == 1) // Just a single model
+ {
+ thePushModelFlag = true;
+ PushModel(GetNameOrIDOrSid(inNode));
+ ProcessTransform(inNode);
+ if (!ProcessInstanceGeometry(inNode, theInstanceGeometryArray[0])) {
+ // The model doesn't have valid geometry. Pop it then process it as group
+ PopModel();
+ thePushModelFlag = false;
+ PushGroup(GetNameOrIDOrSid(inNode));
+ ProcessTransform(inNode);
+ }
+ } else // Multiple models
+ {
+ thePushModelFlag = false;
+ PushGroup(GetNameOrIDOrSid(inNode));
+ ProcessTransform(inNode);
+
+ for (long theIndex = 0; theIndex < theGeometryCount; ++theIndex) {
+ const domInstance_geometryRef theInstanceGeometryRef =
+ theInstanceGeometryArray[theIndex];
+ PushModel(GetNameOrIDOrSid(theInstanceGeometryRef));
+ ProcessInstanceGeometry(inNode, theInstanceGeometryRef);
+ PopModel();
+ }
+ }
+
+ const domNode_Array &theNodes = inNode->getNode_array();
+ long theNodesCount = (long)theNodes.getCount();
+
+ for (long theIndex = 0; theIndex < theNodesCount; ++theIndex) {
+ ProcessNode(theNodes[theIndex]);
+ }
+
+ if (thePushModelFlag)
+ PopModel();
+ else
+ PopGroup();
+ } break;
+ default: // No support for other types currently
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * Processes transform elements on a <node>.
+ */
+void ColladaDOMWalker::ProcessTransform(const domNodeRef inNode)
+{
+ std::vector<INodeTransform *> theTransforms;
+
+ daeTArray<daeSmartRef<daeElement>> theChildren = inNode->getChildren();
+ long theChildCount = (long)theChildren.getCount();
+ for (long theIndex = 0; theIndex < theChildCount; ++theIndex) {
+ daeElement *theChild = theChildren[theIndex];
+
+ if (!ApplyAnimation(theChild)) // if there is animation, do not process transformation
+ // because animation overwrites transformation
+ {
+ switch (GetElementType(*theChild)) {
+ case COLLADA_TYPE::MATRIX:
+ theTransforms.push_back(new NodeTransform(ETransformType_Matrix4x4));
+ ProcessMatrix(theChild, *theTransforms.back());
+ break;
+ case COLLADA_TYPE::ROTATE:
+ theTransforms.push_back(new NodeTransform(ETransformType_Rotation4));
+ ProcessRotation(theChild, *theTransforms.back());
+ break;
+ case COLLADA_TYPE::SCALE:
+ theTransforms.push_back(new NodeTransform(ETransformType_Scale3));
+ ProcessScale(theChild, *theTransforms.back());
+ break;
+ case COLLADA_TYPE::SKEW:
+ // TODO: Skew??
+ break;
+ case COLLADA_TYPE::TRANSLATE:
+ theTransforms.push_back(new NodeTransform(ETransformType_Translate3));
+ ProcessTranslation(theChild, *theTransforms.back());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ SetTransforms(theTransforms);
+
+ std::for_each(theTransforms.begin(), theTransforms.end(), NodeTransform::Delete);
+}
+
+//==============================================================================
+/**
+ * Attempts to locate a daeElement via it's string ID from the collada root.
+ */
+daeElement *ColladaDOMWalker::FindElementByID(const char *inElementID)
+{
+ daeDefaultIDRefResolver theIDResolver(*m_DAE);
+
+ daeElement *theElement =
+ theIDResolver.resolveElement(inElementID, m_ColladaRoot->getDocument());
+
+ return theElement;
+}
+
+//==============================================================================
+/**
+ * Processes <instance_geometry> on a <node>
+ * Returns true if the model has valid geometry
+ */
+bool ColladaDOMWalker::ProcessInstanceGeometry(const domNodeRef inNode,
+ domInstance_geometryRef inInstanceGeometryRef)
+{
+ TFaceIndicies theFaceIndicies;
+
+ const xsAnyURI &theGeometryURI = inInstanceGeometryRef->getUrl();
+ const daeElementRef theGeometryRef = theGeometryURI.getElement();
+ const domGeometry *theGeometry = daeSafeCast<domGeometry>(theGeometryRef);
+ ProcessGeometry(theGeometry, theFaceIndicies);
+
+ if (theFaceIndicies.first.size() == 0) {
+ MarkInvalid(); // Mark the Model as invalid
+ return false; // No valid geometry
+ }
+
+ const domBind_materialRef theBindMaterialRef = inInstanceGeometryRef->getBind_material();
+ if (theBindMaterialRef) // <bind_material> is present, use it instead
+ ProcessBindMaterial(theBindMaterialRef, theFaceIndicies);
+ else // Use material defined in <triangles>
+ ProcessDefaultMaterial(theFaceIndicies);
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * Processes <geometry> referenced from an <instance_geometry>
+ */
+void ColladaDOMWalker::ProcessGeometry(const domGeometry *inGeometry, TFaceIndicies &ioFaceIndicies)
+{
+ TFloatsList theVertices;
+ TFloatsList theNormals;
+ TFloatsList theTexCoords;
+ TFloatsList theTexTangents;
+ TFloatsList theTexBinormals;
+ TFloatsList theWeights;
+ TFloatsList theBoneIndex;
+ TFloatsList theTexCoords2;
+
+ bool theHasNormals = false;
+ bool theHasTexCoords = false;
+ bool theHasTexCoords2 = false;
+ bool theHasTexTangents = false;
+ bool theHasTexBinormals = false;
+
+ const domMeshRef theMesh = inGeometry->getMesh();
+
+ // TODO: Support <lines> element?
+
+ // Process <triangles> element
+ const domTriangles_Array &theTriangles = theMesh->getTriangles_array();
+ long theTriangleArrayCount = (long)theTriangles.getCount();
+ for (long theIndex = 0; theIndex < theTriangleArrayCount; ++theIndex) {
+ ProcessTriangle(theTriangles[theIndex], ioFaceIndicies, theHasNormals, theHasTexCoords,
+ theHasTexCoords2, theHasTexTangents, theHasTexBinormals);
+ }
+
+ // Prepare arrays for population
+ long theNumberOfUniqueFacePoints = (long)ioFaceIndicies.first.size();
+ if (theNumberOfUniqueFacePoints == 0)
+ return;
+
+ theVertices.resize(theNumberOfUniqueFacePoints * 3);
+ if (theHasNormals)
+ theNormals.resize(theNumberOfUniqueFacePoints * 3);
+ if (theHasTexCoords)
+ theTexCoords.resize(theNumberOfUniqueFacePoints * 2);
+ if (theHasTexCoords2)
+ theTexCoords2.resize(theNumberOfUniqueFacePoints * 2);
+ if (theHasTexTangents)
+ theTexTangents.resize(theNumberOfUniqueFacePoints * 3);
+ if (theHasTexBinormals)
+ theTexBinormals.resize(theNumberOfUniqueFacePoints * 3);
+
+ // Populate vertex, normal and texcoord arrays so that face indicies can reference from them
+ TFaceIndicies::first_type::const_iterator theIter = ioFaceIndicies.first.begin();
+ TFaceIndicies::first_type::const_iterator theEnd = ioFaceIndicies.first.end();
+ for (; theIter != theEnd; ++theIter) {
+ long theFaceIndex = theIter->second;
+ const TVertexInfoTuple &thePointTuple = theIter->first;
+
+ Push3Floats(theVertices, theFaceIndex, thePointTuple.get<0>());
+
+ if (theHasNormals)
+ Push3Floats(theNormals, theFaceIndex, thePointTuple.get<1>());
+ if (theHasTexCoords)
+ Push2Floats(theTexCoords, theFaceIndex, thePointTuple.get<2>());
+ if (theHasTexTangents)
+ Push3Floats(theTexTangents, theFaceIndex, thePointTuple.get<3>());
+ if (theHasTexBinormals)
+ Push3Floats(theTexBinormals, theFaceIndex, thePointTuple.get<4>());
+ if (theHasTexCoords2)
+ Push2Floats(theTexCoords2, theFaceIndex, thePointTuple.get<5>());
+ }
+
+ // Lump all acquired face indicies from different materials, into a single list
+ long theMaterialCount = (long)ioFaceIndicies.second.size();
+ TLongsList theEntireFaceIndiciesList;
+ for (long theIndex = 0; theIndex < theMaterialCount; ++theIndex) {
+ theEntireFaceIndiciesList.insert(theEntireFaceIndiciesList.end(),
+ ioFaceIndicies.second[theIndex].second.begin(),
+ ioFaceIndicies.second[theIndex].second.end());
+ }
+
+ m_Translator->SetGeometry(theVertices, theNormals, theTexCoords, theTexCoords2, theTexTangents,
+ theTexBinormals, theWeights, theBoneIndex, theEntireFaceIndiciesList);
+
+ // Pop up warning message if model contains non-triangles geometry
+ if (theMesh->getPolylist_array().getCount() || theMesh->getPolygons_array().getCount()
+ || theMesh->getLines_array().getCount() || theMesh->getLinestrips_array().getCount()
+ || theMesh->getTrifans_array().getCount() || theMesh->getTristrips_array().getCount()) {
+ LogWarning(ESceneGraphWarningCode_OnlySupportTriangles, GetNameOrIDOrSid(inGeometry));
+ }
+}
+
+//==============================================================================
+/**
+ * Processes the <triangle> element.
+ */
+void ColladaDOMWalker::ProcessTriangle(const domTrianglesRef inTrianglesRef,
+ TFaceIndicies &ioFaceIndicies, bool &outHasNormals,
+ bool &outHasTexCoords, bool &outHasTexCoords2,
+ bool &outHasTexTangents, bool &outHasTexBinormals)
+{
+ SSourceArrayInfo theVertexArrayInfo;
+ SSourceArrayInfo theNormalArrayInfo;
+ SSourceArrayInfo theTexCoordArrayInfo;
+ SSourceArrayInfo theTexCoord2ArrayInfo;
+ SSourceArrayInfo theTexTangentArrayInfo;
+ SSourceArrayInfo theTexBinormalArrayInfo;
+
+ const domInputLocalOffset_Array &theInputOffsets = inTrianglesRef->getInput_array();
+ long theInputOffsetsCount = (long)theInputOffsets.getCount();
+ long theMaxOffset = 0; // Some <input>s share the same offset, so we want to advance our <p> by
+ // the max offset that we find
+ long theVertexArrayOffset = -1;
+
+ // Retrieve the appropriate source array depending on the semantic name (inputs with offsets)
+ for (long theIndex = 0; theIndex < theInputOffsetsCount; ++theIndex) {
+ const char *theSemantic = theInputOffsets[theIndex]->getSemantic();
+ long theCurrentOffset = (long)theInputOffsets[theIndex]->getOffset();
+ theMaxOffset =
+ Q3DStudio::MAX(theCurrentOffset, theMaxOffset); // Retrieve the max offset amount
+
+ if (::strcmp(theSemantic, "VERTEX") == 0) {
+ // VERTEX require one more lookup to find it's POSITION <source>
+ theVertexArrayOffset = theCurrentOffset;
+ } else if (::strcmp(theSemantic, "NORMAL") == 0) {
+ GetDomSourceArrayAndVectorCapacity(theInputOffsets[theIndex], g_XYZIdentifiers,
+ theNormalArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXCOORD") == 0 && theTexCoordArrayInfo.m_POffset == -1) {
+ GetDomSourceArrayAndVectorCapacity(theInputOffsets[theIndex], g_STIdentifiers,
+ theTexCoordArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXCOORD") == 0
+ && theTexCoord2ArrayInfo.m_POffset == -1) {
+ GetDomSourceArrayAndVectorCapacity(theInputOffsets[theIndex], g_STIdentifiers,
+ theTexCoord2ArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXTANGENT") == 0) {
+ GetDomSourceArrayAndVectorCapacity(theInputOffsets[theIndex], g_XYZIdentifiers,
+ theTexTangentArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXBINORMAL") == 0) {
+ GetDomSourceArrayAndVectorCapacity(theInputOffsets[theIndex], g_XYZIdentifiers,
+ theTexBinormalArrayInfo, LogWarning);
+ }
+ }
+
+ ++theMaxOffset; // Increment offset by 1 which becomes the stride of the <p> list
+
+ // Retrieve inputs without offsets in vertices
+ domMesh *theMesh = (domMesh *)theInputOffsets[0]->getParentElement()->getParentElement();
+ domVertices *theVertices = theMesh->getVertices();
+ domInputLocal_Array &theVerticesInputArray = theVertices->getInput_array();
+ long theInputArrayCount = (long)theVerticesInputArray.getCount();
+ for (long theInputArrayIndex = 0; theInputArrayIndex < theInputArrayCount;
+ ++theInputArrayIndex) {
+ const char *theSemantic = theVerticesInputArray[theInputArrayIndex]->getSemantic();
+ domSource *theDomSource = daeSafeCast<domSource>(
+ theVerticesInputArray[theInputArrayIndex]->getSource().getElement());
+ if (::strcmp(theSemantic, "POSITION") == 0) {
+ GetSourceArrayInfo(theDomSource, g_XYZIdentifiers, theVertexArrayOffset,
+ theVertexArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "NORMAL") == 0) {
+ GetSourceArrayInfo(theDomSource, g_XYZIdentifiers, theVertexArrayOffset,
+ theNormalArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXCOORD") == 0 && theTexCoordArrayInfo.m_POffset == -1) {
+ GetSourceArrayInfo(theDomSource, g_STIdentifiers, theVertexArrayOffset,
+ theTexCoordArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXCOORD") == 0
+ && theTexCoord2ArrayInfo.m_POffset == -1) {
+ GetSourceArrayInfo(theDomSource, g_STIdentifiers, theVertexArrayOffset,
+ theTexCoord2ArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXTANGENT") == 0) {
+ GetSourceArrayInfo(theDomSource, g_XYZIdentifiers, theVertexArrayOffset,
+ theTexTangentArrayInfo, LogWarning);
+ } else if (::strcmp(theSemantic, "TEXBINORMAL") == 0) {
+ GetSourceArrayInfo(theDomSource, g_XYZIdentifiers, theVertexArrayOffset,
+ theTexBinormalArrayInfo, LogWarning);
+ }
+ }
+
+ outHasNormals |= theNormalArrayInfo.m_POffset > -1;
+ outHasTexCoords |= theTexCoordArrayInfo.m_POffset > -1;
+ outHasTexCoords2 |= theTexCoord2ArrayInfo.m_POffset > -1;
+ outHasTexTangents |= theTexTangentArrayInfo.m_POffset > -1;
+ outHasTexBinormals |= theTexBinormalArrayInfo.m_POffset > -1;
+
+ // check if we need to generate tangents and binormals
+ std::vector<SVector3> newTangents;
+ std::vector<SVector3> newBinormals;
+ if ((theTexTangentArrayInfo.m_POffset == -1) && (theTexBinormalArrayInfo.m_POffset == -1)) {
+ GenerateMeshTangents(inTrianglesRef, theVertexArrayInfo, theNormalArrayInfo,
+ theTexCoordArrayInfo, theTexCoord2ArrayInfo, newTangents,
+ newBinormals);
+ }
+
+ // Organize face points into face indicies.
+ TLongsList theMaterialFaceIndicies;
+ theMaterialFaceIndicies.reserve((long)inTrianglesRef->getCount());
+
+ const domPRef thePRef = inTrianglesRef->getP();
+ const domListOfUInts &theListOfPInts = thePRef->getValue();
+ long thePIntsCount = (long)theListOfPInts.getCount();
+ for (long theIndex = 0; theIndex < thePIntsCount; theIndex += theMaxOffset) {
+ TVertexInfoTuple theFaceTupleValues;
+
+ GetFaceTupleValue(theFaceTupleValues.get<0>(), theVertexArrayInfo,
+ (unsigned long)theListOfPInts[theIndex + theVertexArrayInfo.m_POffset]);
+
+ if (outHasNormals)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<1>(), theNormalArrayInfo,
+ (unsigned long)theListOfPInts[theIndex + theNormalArrayInfo.m_POffset]);
+
+ if (outHasTexCoords)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<2>(), theTexCoordArrayInfo,
+ (unsigned long)theListOfPInts[theIndex + theTexCoordArrayInfo.m_POffset]);
+
+ // first check if we generated the tangents
+ if (newTangents.size() > 0)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<3>(), newTangents,
+ (unsigned long)theListOfPInts[theIndex + theVertexArrayInfo.m_POffset]);
+ else if (outHasTexTangents)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<3>(), theTexTangentArrayInfo,
+ (unsigned long)theListOfPInts[theIndex + theTexTangentArrayInfo.m_POffset]);
+
+ // first check if we generated the binormals
+ if (newBinormals.size() > 0)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<4>(), newBinormals,
+ (unsigned long)theListOfPInts[theIndex + theVertexArrayInfo.m_POffset]);
+ else if (outHasTexBinormals)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<4>(), theTexBinormalArrayInfo,
+ (unsigned long)theListOfPInts[theIndex + theTexBinormalArrayInfo.m_POffset]);
+
+ if (outHasTexCoords2)
+ GetFaceTupleValue(
+ theFaceTupleValues.get<5>(), theTexCoord2ArrayInfo,
+ (unsigned long)theListOfPInts[theIndex + theTexCoord2ArrayInfo.m_POffset]);
+
+ long theFaceIndex = RetrieveFaceIndex(ioFaceIndicies, theFaceTupleValues);
+
+ theMaterialFaceIndicies.push_back(theFaceIndex);
+ }
+
+ outHasTexTangents |= newTangents.size() > 0;
+ outHasTexBinormals |= newBinormals.size() > 0;
+
+ // Set the face indicies used by this particular material
+ const xsNCName theMaterialName =
+ inTrianglesRef->getMaterial(); // TODO: Handle the material settings for this face
+ ioFaceIndicies.second.push_back(std::make_pair(theMaterialName, theMaterialFaceIndicies));
+}
+
+/**
+* @brief computer tangents and binormals from mesh input data like
+* normals and uv's.
+* If you are interested in how it works check
+* "Math for 3D Game programming and CG"
+*
+* @param[in] inTrianglesRef pointer to triangle data
+* @param[in] inVertexArrayInfo vertex array info
+* @param[in] inNormalArrayInfo normal array info
+* @param[in] inTexCoordArrayInfo tex coord array info
+* @param[in/out] outTangents output vectors of tangents
+* @param[in/out] outBinormals output vectors of binormals
+*
+* @return none
+*/
+void ColladaDOMWalker::GenerateMeshTangents(const domTrianglesRef inTrianglesRef,
+ const SSourceArrayInfo &inVertexArrayInfo,
+ const SSourceArrayInfo &inNormalArrayInfo,
+ const SSourceArrayInfo &inTexCoordArrayInfo,
+ const SSourceArrayInfo &inTexCoordArray2Info,
+ std::vector<SVector3> &outTangents,
+ std::vector<SVector3> &outBinormals)
+{
+ // we need this information
+ if (inVertexArrayInfo.m_POffset == -1 || inNormalArrayInfo.m_POffset == -1
+ || inTexCoordArrayInfo.m_POffset == -1) {
+ return;
+ }
+
+ long triCount = (long)inTrianglesRef->getCount();
+ if (triCount == 0)
+ return;
+
+ // allocate arrays
+ long vertexCount = (long)inVertexArrayInfo.m_Array->getCount() / 3;
+ SVector3 *tan1 = new SVector3[vertexCount * 2];
+ SVector3 *tan2 = tan1 + vertexCount;
+ SVector3 *normals = new SVector3[vertexCount];
+
+ // failed to allocate menory
+ if (!tan1 || !normals)
+ return;
+
+ memset(tan1, 0x00, vertexCount * sizeof(SVector3) * 2);
+
+ const domPRef thePRef = inTrianglesRef->getP();
+ const domListOfUInts &theListOfPInts = thePRef->getValue();
+
+ long maxOffset = (inNormalArrayInfo.m_POffset > inVertexArrayInfo.m_POffset)
+ ? inNormalArrayInfo.m_POffset
+ : inVertexArrayInfo.m_POffset;
+ maxOffset =
+ (inTexCoordArrayInfo.m_POffset > maxOffset) ? inTexCoordArrayInfo.m_POffset : maxOffset;
+ maxOffset =
+ (inTexCoordArray2Info.m_POffset > maxOffset) ? inTexCoordArray2Info.m_POffset : maxOffset;
+ maxOffset++;
+
+ SVector3 vx1, vx2, vx3;
+ SVector3 uv1, uv2, uv3;
+
+ for (long i = 0; i < triCount; i++) {
+ // read an entire triangle
+ // read vertex 1 data
+ long indexCount = i * maxOffset * 3; // we have a vertex, normal and texcoord entry;
+ long index1 = (unsigned long)theListOfPInts[indexCount + inVertexArrayInfo.m_POffset];
+ GetFaceTupleValue((float *)vx1, inVertexArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inVertexArrayInfo.m_POffset]);
+ GetFaceTupleValue((float *)normals[index1], inNormalArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inNormalArrayInfo.m_POffset]);
+ GetFaceTupleValue(
+ (float *)uv1, inTexCoordArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inTexCoordArrayInfo.m_POffset]);
+
+ // read vertex 2 data
+ indexCount += maxOffset; // we have a vertex, normal and texcoord entry;
+ long index2 = (unsigned long)theListOfPInts[indexCount + inVertexArrayInfo.m_POffset];
+ GetFaceTupleValue((float *)vx2, inVertexArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inVertexArrayInfo.m_POffset]);
+ GetFaceTupleValue((float *)normals[index2], inNormalArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inNormalArrayInfo.m_POffset]);
+ GetFaceTupleValue(
+ (float *)uv2, inTexCoordArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inTexCoordArrayInfo.m_POffset]);
+
+ // read vertex 3 data
+ indexCount += maxOffset; // we have a vertex, normal and texcoord entry;
+ long index3 = (unsigned long)theListOfPInts[indexCount + inVertexArrayInfo.m_POffset];
+ GetFaceTupleValue((float *)vx3, inVertexArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inVertexArrayInfo.m_POffset]);
+ GetFaceTupleValue((float *)normals[index3], inNormalArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inNormalArrayInfo.m_POffset]);
+ GetFaceTupleValue(
+ (float *)uv3, inTexCoordArrayInfo,
+ (unsigned long)theListOfPInts[indexCount + inTexCoordArrayInfo.m_POffset]);
+
+ // compute triangle vectors
+ float x1 = vx2[0] - vx1[0];
+ float x2 = vx3[0] - vx1[0];
+ float y1 = vx2[1] - vx1[1];
+ float y2 = vx3[1] - vx1[1];
+ float z1 = vx2[2] - vx1[2];
+ float z2 = vx3[2] - vx1[2];
+
+ float s1 = uv2[0] - uv1[0];
+ float s2 = uv3[0] - uv1[0];
+ float t1 = uv2[1] - uv1[1];
+ float t2 = uv3[1] - uv1[1];
+
+ float area = (s1 * t2 - s2 * t1);
+ if (area == 0.0)
+ area = 1.0;
+
+ float r = 1.0f / area;
+
+ float sx = ((t2 * x1 - t1 * x2) * r);
+ float sy = ((t2 * y1 - t1 * y2) * r);
+ float sz = ((t2 * z1 - t1 * z2) * r);
+
+ float tx = ((s1 * x2 - s2 * x1) * r);
+ float ty = ((s1 * y2 - s2 * y1) * r);
+ float tz = ((s1 * z2 - s2 * z1) * r);
+
+ tan1[index1][0] += sx;
+ tan1[index1][1] += sy;
+ tan1[index1][2] += sz;
+ tan1[index2][0] += sx;
+ tan1[index2][1] += sy;
+ tan1[index2][2] += sz;
+ tan1[index3][0] += sx;
+ tan1[index3][1] += sy;
+ tan1[index3][2] += sz;
+
+ tan2[index1][0] += tx;
+ tan2[index1][1] += ty;
+ tan2[index1][2] += tz;
+ tan2[index2][0] += tx;
+ tan2[index2][1] += ty;
+ tan2[index2][2] += tz;
+ tan2[index3][0] += tx;
+ tan2[index3][1] += ty;
+ tan2[index3][2] += tz;
+ }
+
+ outTangents.resize(vertexCount);
+ outBinormals.resize(vertexCount);
+
+ // compute actual tangents
+ for (int i = 0; i < vertexCount; i++) {
+ const QT3DSVec3 n(normals[i][0], normals[i][1], normals[i][2]);
+ const qt3ds::QT3DSVec3 t(tan1[i][0], tan1[i][1], tan1[i][2]);
+ const qt3ds::QT3DSVec3 t2(tan2[i][0], tan2[i][1], tan2[i][2]);
+
+ // Gram-Schmidt orthogonalize
+ qt3ds::QT3DSVec3 temp, t3, bi;
+ temp = t - n * n.dot(t);
+ t3 = temp;
+ t3.normalize();
+ outTangents[i][0] = t3.x;
+ outTangents[i][1] = t3.y;
+ outTangents[i][2] = t3.z;
+
+ // Calculate binormal
+ temp = n.cross(t);
+ temp.normalize();
+ float dp = temp.dot(t2);
+ float sig = (dp < 0.0f) ? -1.0f : 1.0f;
+ outBinormals[i][0] = temp.x * sig;
+ outBinormals[i][1] = temp.y * sig;
+ outBinormals[i][2] = temp.z * sig;
+ }
+
+ delete[] tan1;
+ delete[] normals;
+}
+
+//==============================================================================
+/**
+ * Processes the <bind_material> element.
+ */
+void ColladaDOMWalker::ProcessBindMaterial(const domBind_materialRef inBindMaterialRef,
+ const TFaceIndicies &inFaceIndicies)
+{
+ const domBind_material::domTechnique_commonRef theTechiniqueCommon =
+ inBindMaterialRef->getTechnique_common();
+ const domInstance_material_Array &theInstanceMaterials =
+ theTechiniqueCommon->getInstance_material_array();
+ long theInstanceMaterialCount = (long)theInstanceMaterials.getCount();
+
+ // Match stored material subsets with the list from <bind_material>
+ long theNumberOfMaterials = (long)inFaceIndicies.second.size();
+ long theFaceIndexStart = 0;
+
+ for (long theMaterialIndex = 0; theMaterialIndex < theNumberOfMaterials; ++theMaterialIndex) {
+ for (long theInstanceMaterialIndex = 0; theInstanceMaterialIndex < theInstanceMaterialCount;
+ ++theInstanceMaterialIndex) {
+ const domInstance_materialRef theInstanceMaterialRef =
+ theInstanceMaterials[theInstanceMaterialIndex];
+ if (inFaceIndicies.second[theMaterialIndex].first
+ == theInstanceMaterialRef->getSymbol()) {
+ std::string theName;
+ daeElementRef theMaterialElementRef =
+ theInstanceMaterialRef->getTarget().getElement();
+
+ if (theMaterialElementRef)
+ theName = GetNameOrIDOrSid(theMaterialElementRef);
+
+ PushMaterial(theName.empty() ? theInstanceMaterialRef->getSymbol()
+ : theName.c_str());
+ ProcessInstanceMaterial(theInstanceMaterialRef);
+ PopMaterial(theFaceIndexStart,
+ (long)(inFaceIndicies.second[theMaterialIndex].second.size() / 3));
+ }
+ }
+
+ theFaceIndexStart += (long)(inFaceIndicies.second[theMaterialIndex].second.size() / 3);
+ }
+}
+
+//==============================================================================
+/**
+ * Processes default materials found in <triangles>.
+ */
+void ColladaDOMWalker::ProcessDefaultMaterial(const TFaceIndicies &inFaceIndicies)
+{
+ // Collada specs indicates that when <bind_material> is not defined, the shading becomes
+ // application defined.
+ // But we can try to locate the material within <library_materials> and use that instead if
+ // available.
+ TFaceIndicies::second_type::const_iterator theIter = inFaceIndicies.second.begin();
+ TFaceIndicies::second_type::const_iterator theEnd = inFaceIndicies.second.end();
+ long theFaceIndexStart = 0;
+ for (; theIter != theEnd; ++theIter) {
+ domMaterial *theMaterial =
+ daeSafeCast<domMaterial>(FindElementByID(theIter->first.c_str()));
+
+ PushMaterial(theMaterial ? GetNameOrIDOrSid(theMaterial) : "Default");
+ if (theMaterial)
+ ProcessMaterial(theMaterial);
+
+ PopMaterial(theFaceIndexStart, (long)(theIter->second.size() / 3));
+ theFaceIndexStart += (long)(theIter->second.size());
+ }
+}
+
+//==============================================================================
+/**
+ * Processes the <instance_material> element.
+ */
+void ColladaDOMWalker::ProcessInstanceMaterial(const domInstance_materialRef inInstanceMaterialRef)
+{
+ // Process material
+ const xsAnyURI &theMaterialURI = inInstanceMaterialRef->getTarget();
+ const daeElementRef theMaterialRef = theMaterialURI.getElement();
+ const domMaterial *theMaterial = daeSafeCast<domMaterial>(theMaterialRef);
+ if (theMaterial)
+ ProcessMaterial(theMaterial);
+}
+
+//==============================================================================
+/**
+ * Processes the <material> element referenced by <instance_material>.
+ */
+void ColladaDOMWalker::ProcessMaterial(const domMaterial *inMaterial)
+{
+ const domInstance_effectRef theInstanceEffectRef = inMaterial->getInstance_effect();
+ ProcessInstanceEffect(theInstanceEffectRef);
+}
+
+//==============================================================================
+/**
+ * Processes the <instance_effect> element referenced by <material>.
+ */
+void ColladaDOMWalker::ProcessInstanceEffect(const domInstance_effectRef inInstanceEffectRef)
+{
+ const xsAnyURI &theEffectURI = inInstanceEffectRef->getUrl();
+ const daeElementRef theEffectRef = theEffectURI.getElement();
+ const domEffect *theEffect = daeSafeCast<domEffect>(theEffectRef);
+ ProcessEffect(theEffect);
+}
+
+//==============================================================================
+/**
+ * Processes the <effect> element referenced by <instance_effect>.
+ */
+void ColladaDOMWalker::ProcessEffect(const domEffect *inEffect)
+{
+ const domFx_profile_abstract_Array &theProfiles = inEffect->getFx_profile_abstract_array();
+ long theProfilesCount = (long)theProfiles.getCount();
+ for (long theIndex = 0; theIndex < theProfilesCount; ++theIndex) {
+ ProcessProfile(theProfiles[theIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Processes the profile element referenced by <effect>.
+ */
+void ColladaDOMWalker::ProcessProfile(const domFx_profile_abstractRef &inProfile)
+{
+ // Support profile_Common for now
+ switch (inProfile->getElementType()) {
+ case COLLADA_TYPE::PROFILE_COMMON: {
+ const domProfile_COMMON *theProfileCommon =
+ daeSmartRef<domProfile_COMMON>::staticCast(inProfile);
+ ProcessProfileCommon(theProfileCommon);
+ } break;
+
+ default:
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * Processes the <profile_common> element.
+ */
+void ColladaDOMWalker::ProcessProfileCommon(const domProfile_COMMON *inProfileCommon)
+{
+ const domProfile_COMMON::domTechniqueRef theTechinqueRef = inProfileCommon->getTechnique();
+ ProcessProfileCommonTechnique(theTechinqueRef);
+}
+
+//==============================================================================
+/**
+ * Process texture parameters which is stored under <extra> tag
+ * This is used to extract Maya texture placement MAYA extension
+ */
+void ColladaDOMWalker::ProcessTextureParameters(const domExtraRef inTextureExtraRef,
+ STextureParameters &outTextureParameters)
+{
+ if (inTextureExtraRef) {
+ const domTechnique_Array &theTechniqueArray = inTextureExtraRef->getTechnique_array();
+ long theNoOfTechnique = (long)theTechniqueArray.getCount();
+ for (long i = 0; i < theNoOfTechnique; ++i) {
+ domTechniqueRef theTechnique = theTechniqueArray[i];
+ const char *theProfile = theTechnique->getProfile();
+ if (::strcmp(theProfile, "MAYA") == 0) {
+ // Extract Maya information
+ outTextureParameters.m_Flag = true;
+ if (daeElement *theElement = theTechnique->getChild("coverageU")) {
+ outTextureParameters.m_coverageU.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("coverageV")) {
+ outTextureParameters.m_coverageV.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("repeatU")) {
+ outTextureParameters.m_repeatU.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("repeatV")) {
+ outTextureParameters.m_repeatV.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("offsetU")) {
+ outTextureParameters.m_offsetU.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("offsetV")) {
+ outTextureParameters.m_offsetV.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("rotateUV")) {
+ outTextureParameters.m_rotateUV.SetValue(GetFloatFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("wrapU")) {
+ outTextureParameters.m_wrapU.SetValue(GetIntFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("wrapV")) {
+ outTextureParameters.m_wrapV.SetValue(GetIntFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("mirrorU")) {
+ outTextureParameters.m_mirrorU.SetValue(GetIntFromElementChar(theElement));
+ }
+ if (daeElement *theElement = theTechnique->getChild("mirrorV")) {
+ outTextureParameters.m_mirrorV.SetValue(GetIntFromElementChar(theElement));
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Process texture references.
+ */
+void ColladaDOMWalker::ProcessTexture(
+ const domCommon_color_or_texture_type_complexType::domTextureRef inTextureRef, long inMapType)
+{
+ if (inTextureRef != NULL) {
+ // TODO: What about texcoord?
+ const xsNCName theTextureParamSid = inTextureRef->getTexture();
+ ColladaDOMWalker::TURIList theTextures;
+ STextureParameters theTextureParameters;
+ ProcessTextureParameters(inTextureRef->getExtra(), theTextureParameters);
+
+ daeElement *theNewParamPtr = NULL;
+
+ // Look for param name in <newparam>s
+ if (RecursiveFindElementBySid(theTextureParamSid, theNewParamPtr, inTextureRef,
+ domProfile_COMMON::domTechnique::ID(), domEffect::ID())) {
+ FindTexturesViaNewParam(theNewParamPtr, theTextures);
+
+ TURIList::const_iterator theIter = theTextures.begin();
+ TURIList::const_iterator theEnd = theTextures.end();
+ for (; theIter != theEnd; ++theIter) {
+ PushTexture(theIter->first.c_str(), theIter->second.path().c_str(), inMapType);
+ SetTexture(inMapType, theTextureParameters);
+ PopTexture();
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Process color or texture references.
+ */
+void ColladaDOMWalker::GetColorOrTextureParamInfo(
+ const domCommon_color_or_texture_type_complexType *inColorOrTexturePtr,
+ SColorOrTexture &outColor, long inMapType)
+{
+ if (inColorOrTexturePtr) {
+ if (const domCommon_color_or_texture_type_complexType::domColorRef theColorRef =
+ inColorOrTexturePtr->getColor()) {
+ domFloat4 theDomFloat4 = theColorRef->getValue();
+ outColor.SetColor((float)theDomFloat4[0], (float)theDomFloat4[1],
+ (float)theDomFloat4[2], (float)theDomFloat4[3]);
+ ApplyAnimation(theColorRef);
+ } else if (const domCommon_color_or_texture_type_complexType::domTextureRef theTextureRef =
+ inColorOrTexturePtr->getTexture()) {
+ ProcessTexture(theTextureRef, inMapType);
+ outColor.SetTexture();
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Process <technique_common> element.
+ */
+void ColladaDOMWalker::ProcessProfileCommonTechnique(
+ const domProfile_COMMON::domTechniqueRef inTechniqueRef)
+{
+ static const float theZeroColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+ // Blinn COMMON
+ BeginCommonTechniqueObject(inTechniqueRef, Blinn)
+ ProcessColorOrTextureParam(Emission, ETextureMapTypeEmissive);
+ ProcessColorOrTextureParam(Ambient, ETextureMapTypeDiffuse);
+ ProcessColorOrTextureParam(Diffuse, ETextureMapTypeDiffuse);
+ ProcessColorOrTextureParam(Specular, ETextureMapTypeSpecular);
+ ProcessFloatParam(Shininess);
+ ProcessColorOrTextureParam(Reflective, ETextureMapTypeDiffuse);
+ ProcessFloatParam(Reflectivity);
+ ProcessTransparentParam(Transparent);
+ ProcessFloatParam(Transparency);
+ ProcessFloatParam(Index_of_refraction);
+ EndCommonTechniqueObject()
+
+ // Constant COMMON
+ BeginCommonTechniqueObject(inTechniqueRef, Constant)
+ ProcessColorOrTextureParam(Emission, ETextureMapTypeEmissive);
+ ProcessColorOrTextureParam(Reflective, ETextureMapTypeDiffuse);
+ ProcessFloatParam(Reflectivity);
+ ProcessTransparentParam(Transparent);
+ ProcessFloatParam(Transparency);
+ ProcessFloatParam(Index_of_refraction);
+ EndCommonTechniqueObject()
+
+ // Lambert COMMON
+ BeginCommonTechniqueObject(inTechniqueRef, Lambert)
+ ProcessColorOrTextureParam(Emission, ETextureMapTypeEmissive);
+ ProcessColorOrTextureParam(Ambient, ETextureMapTypeDiffuse);
+ ProcessColorOrTextureParam(Diffuse, ETextureMapTypeDiffuse);
+ ProcessColorOrTextureParam(Reflective, ETextureMapTypeDiffuse);
+ ProcessFloatParam(Reflectivity);
+ ProcessTransparentParam(Transparent);
+ ProcessFloatParam(Transparency);
+ ProcessFloatParam(Index_of_refraction);
+ EndCommonTechniqueObject()
+
+ // Phong COMMON
+ BeginCommonTechniqueObject(inTechniqueRef, Phong)
+ ProcessColorOrTextureParam(Emission, ETextureMapTypeEmissive);
+ ProcessColorOrTextureParam(Ambient, ETextureMapTypeDiffuse);
+ ProcessColorOrTextureParam(Diffuse, ETextureMapTypeDiffuse);
+ ProcessColorOrTextureParam(Specular, ETextureMapTypeSpecular);
+ ProcessFloatParam(Shininess);
+ ProcessColorOrTextureParam(Reflective, ETextureMapTypeDiffuse);
+ ProcessFloatParam(Reflectivity);
+ ProcessTransparentParam(Transparent);
+ ProcessFloatParam(Transparency);
+ ProcessFloatParam(Index_of_refraction);
+ EndCommonTechniqueObject()
+}
+
+//==============================================================================
+/**
+ * Process <technique_common> <extra> element.
+ */
+void ColladaDOMWalker::ProcessProfileCommonTechniqueExtra(
+ const domProfile_COMMON::domTechniqueRef inTechniqueRef,
+ SMaterialExtraParameters &outMaterialExtraParameters)
+{
+ const domExtra_Array &theExtras = inTechniqueRef->getExtra_array();
+ long theNoOfExtras = (long)theExtras.getCount();
+
+ for (long theExtraIndex = 0; theExtraIndex < theNoOfExtras; ++theExtraIndex) {
+ const domTechnique_Array &theTechniqueArray =
+ theExtras[theExtraIndex]->getTechnique_array();
+ long theNoOfTechnique = (long)theTechniqueArray.getCount();
+ for (long i = 0; i < theNoOfTechnique; ++i) {
+ domTechniqueRef theTechnique = theTechniqueArray[i];
+ const char *theProfile = theTechnique->getProfile();
+ if (::strcmp(theProfile, "FCOLLADA") == 0) {
+ // Extract FCollada information
+ outMaterialExtraParameters.m_Flag = true;
+ if (daeElement *theElement = theTechnique->getChild("spec_level")) {
+ if (daeElement *theElementValue = theElement->getChild("float")) {
+ outMaterialExtraParameters.m_SpecLevel.SetValue(
+ GetFloatFromElementChar(theElementValue));
+ }
+ }
+ if (daeElement *theElement = theTechnique->getChild("emission_level")) {
+ if (daeElement *theElementValue = theElement->getChild("float")) {
+ outMaterialExtraParameters.m_EmissionLevel.SetValue(
+ GetFloatFromElementChar(theElementValue));
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Processes any <library_animations> within the Collada file.
+ */
+void ColladaDOMWalker::ProcessLibraryAnimations()
+{
+ const domLibrary_animations_Array &theAnimationsArray =
+ m_ColladaRoot->getLibrary_animations_array();
+
+ long theLibrariesCount = (long)theAnimationsArray.getCount();
+
+ for (long theIndex = 0; theIndex < theLibrariesCount; ++theIndex) {
+ ProcessAnimations(theAnimationsArray[theIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Process animations within a <library_animations>.
+ */
+void ColladaDOMWalker::ProcessAnimations(const domLibrary_animationsRef inLibraryAnimation)
+{
+ const domAnimation_Array &theAnimationsArray = inLibraryAnimation->getAnimation_array();
+ long theAnimationsCount = (long)theAnimationsArray.getCount();
+
+ for (long theIndex = 0; theIndex < theAnimationsCount; ++theIndex) {
+ ProcessAnimation(theAnimationsArray[theIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Processes an <animation< element.
+ */
+void ColladaDOMWalker::ProcessAnimation(const domAnimationRef inAnimation)
+{
+ const domChannel_Array &theChannels = inAnimation->getChannel_array();
+
+ long theChannelCount = (long)theChannels.getCount();
+
+ for (long theIndex = 0; theIndex < theChannelCount; ++theIndex) {
+ ProcessChannel(theChannels[theIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Processes <channel> elements within <animation>
+ */
+void ColladaDOMWalker::ProcessChannel(const domChannelRef inChannel)
+{
+ TStringList theIdentifierList;
+ daeElement *theContainerElement = NULL;
+
+ const char *theBaseProperty = GetAnimatedPropertyInfoFromElement(
+ inChannel->getTarget(), m_ColladaRoot, theContainerElement, theIdentifierList);
+
+ if (theBaseProperty && !theIdentifierList.empty()) {
+ const domURIFragmentType &theSamplerSource = inChannel->getSource();
+ const daeElementRef theSamplerRef = theSamplerSource.getElement();
+ const domSampler *theDomSampler = daeSafeCast<domSampler>(theSamplerRef);
+
+ ProcessSampler(theDomSampler, theContainerElement, theBaseProperty, theIdentifierList);
+ }
+}
+
+//==============================================================================
+/**
+ * Processes <sampler> elements refered from <channel>.
+ * Creates animation tracks and maps them to their target elements.
+ * This will then be used to determine which elements are animated when processing
+ * the scene.
+ */
+void ColladaDOMWalker::ProcessSampler(const domSampler *inSamplerRef,
+ daeElement *inContainerElement, const char *inBaseProperty,
+ const TStringList &inIdentifiers)
+{
+ const domInputLocal_Array &theInputArray = inSamplerRef->getInput_array();
+
+ SSourceArrayInfo theINPUTInfo;
+ SSourceArrayInfo theOUTPUTInfo;
+ SSourceArrayInfo theIN_TANGENTInfo;
+ SSourceArrayInfo theOUT_TANGENTInfo;
+
+ // TODO: We should check the interpolation type
+ // SSourceArrayInfo theINTERPOLATIONInfo;
+
+ GetDomSourceArrayInfo(theInputArray, "INPUT", g_TIMEIdentifiers, theINPUTInfo);
+ GetDomSourceArrayInfo(theInputArray, "OUTPUT", inIdentifiers, theOUTPUTInfo);
+ // GetDomSourceArrayInfo( theInputArray, "INTERPOLATION", inIdentifiers, theINTERPOLATIONInfo );
+
+ // The number of XY animation tangents is equal to the number of animated floats
+ TStringList theAnimTangentsIdentifiers;
+ for (long theIndex = 0; theIndex < theOUTPUTInfo.m_Stride; ++theIndex)
+ theAnimTangentsIdentifiers.insert(theAnimTangentsIdentifiers.begin(),
+ g_XYIdentifiers.begin(), g_XYIdentifiers.end());
+
+ GetDomSourceArrayInfo(theInputArray, "IN_TANGENT", theAnimTangentsIdentifiers,
+ theIN_TANGENTInfo);
+ GetDomSourceArrayInfo(theInputArray, "OUT_TANGENT", theAnimTangentsIdentifiers,
+ theOUT_TANGENTInfo);
+
+ // Process the sampler and convert them to tracks
+ for (long theAnimatedSubPropertyIndex = 0;
+ theAnimatedSubPropertyIndex < (long)theOUTPUTInfo.m_Offset.size();
+ ++theAnimatedSubPropertyIndex) {
+ // For each animated sub property, create a track
+ CacheAnimationTrack(inContainerElement);
+
+ // Set the base property and sub property to animate
+ SetAnimationTrack(inBaseProperty, inIdentifiers[theAnimatedSubPropertyIndex].c_str());
+
+ for (long theKeyframeIndex = 0; theKeyframeIndex < theINPUTInfo.m_Array->getCount();
+ ++theKeyframeIndex) {
+ // Create a key
+ SKeyframeParameters theKeyframeInfo(
+ (float)theINPUTInfo.m_Array->getValue()[theKeyframeIndex],
+ (float)theOUTPUTInfo.m_Array
+ ->getValue()[theKeyframeIndex * theOUTPUTInfo.m_Stride
+ + theOUTPUTInfo.m_Offset[theAnimatedSubPropertyIndex]],
+ theIN_TANGENTInfo.m_Array != NULL
+ ? (float)theIN_TANGENTInfo.m_Array
+ ->getValue()[theKeyframeIndex * theIN_TANGENTInfo.m_Stride
+ + theAnimatedSubPropertyIndex * 2]
+ : 0.0f,
+ theIN_TANGENTInfo.m_Array != NULL
+ ? (float)theIN_TANGENTInfo.m_Array
+ ->getValue()[theKeyframeIndex * theIN_TANGENTInfo.m_Stride
+ + theAnimatedSubPropertyIndex * 2 + 1]
+ : 0.0f,
+ theOUT_TANGENTInfo.m_Array != NULL
+ ? (float)theOUT_TANGENTInfo.m_Array
+ ->getValue()[theKeyframeIndex * theOUT_TANGENTInfo.m_Stride
+ + theAnimatedSubPropertyIndex * 2]
+ : 0.0f,
+ theOUT_TANGENTInfo.m_Array != NULL
+ ? (float)theOUT_TANGENTInfo.m_Array
+ ->getValue()[theKeyframeIndex * theOUT_TANGENTInfo.m_Stride
+ + theAnimatedSubPropertyIndex * 2 + 1]
+ : 0.0f);
+
+ // Set information about the key
+ CacheAnimationKey(inBaseProperty, inIdentifiers[theAnimatedSubPropertyIndex].c_str(),
+ theKeyframeInfo);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Associates inElement with an index returned from the ColladaTranslation class.
+ */
+void ColladaDOMWalker::TrackObjectIndex(const daeElement *inElement, long inIndex)
+{
+ if (inElement)
+ m_ElementToIndicies.insert(std::make_pair(inElement, inIndex));
+}
+
+//==============================================================================
+/**
+ * Retrieved the stored index associated with inElement
+ */
+void ColladaDOMWalker::GetIndicesFromElement(const daeElement *inElement, TLongsList &outIndicies)
+{
+ auto theResult = m_ElementToIndicies.equal_range(inElement);
+
+ outIndicies.clear();
+
+ for (TElementToIndicesMap::const_iterator theIter = theResult.first;
+ theIter != theResult.second; ++theIter) {
+ outIndicies.push_back(theIter->second);
+ }
+}
+
+//==============================================================================
+/**
+ * Checks an element to determine if it's been animated.
+ * If it is, the relavent animation tracks will be retrieved from storage and
+ * attached to the target object.
+ */
+bool ColladaDOMWalker::ApplyAnimation(const daeElement *inContainerElement)
+{
+ TLongsList theAnimationTrackIndicies;
+ GetIndicesFromElement(inContainerElement, theAnimationTrackIndicies);
+ bool theAnimated = false;
+
+ for (TLongsList::const_iterator theIter = theAnimationTrackIndicies.begin();
+ theIter != theAnimationTrackIndicies.end(); ++theIter) {
+ theAnimated = true;
+ ApplyAnimationTrack(*theIter);
+ }
+
+ return theAnimated;
+}
+
+} // End anonymous namespace
+
+struct ScopedHelper
+{
+ ISceneGraphTranslation &m_Helper;
+ ScopedHelper(ISceneGraphTranslation &h)
+ : m_Helper(h)
+ {
+ }
+ ~ScopedHelper() { m_Helper.Release(); }
+};
+
+bool CImportTranslation::ParseColladaFile(const std::string &fileName, Import &import,
+ ISGTranslationLog &log)
+{
+ ISceneGraphTranslation &transHelper = ISceneGraphTranslation::CreateTranslation(import, log);
+ ScopedHelper __scope(transHelper);
+ ColladaDOMWalker theDOMWalker(&transHelper);
+ if (theDOMWalker.LoadDocument(fileName)) {
+ theDOMWalker.ProcessLibraryAnimations();
+ theDOMWalker.ProcessScene();
+ return true;
+ }
+ return false;
+}
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaTransformUtils.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaTransformUtils.h
new file mode 100644
index 00000000..e0aeb10f
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportColladaTransformUtils.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICImportTranslationCommon.h"
+
+namespace UICIMP {
+
+void GetFloatsToFloatArray(const domListOfFloats &inFloats, float *outArray)
+{
+ long theCount = (long)inFloats.getCount();
+ for (long theIndex = 0; theIndex < theCount; ++theIndex)
+ outArray[theIndex] = (float)inFloats[theIndex];
+}
+
+template <typename T>
+void ProcessTransformElement(daeElement *inElement, float *outArray)
+{
+ const T *theDomElement = daeSafeCast<T>(inElement);
+ assert(theDomElement != NULL);
+ if (theDomElement)
+ GetFloatsToFloatArray(theDomElement->getValue(), outArray);
+}
+
+void ProcessMatrix(daeElement *inMatrixElement, float *outMatrix)
+{
+ ProcessTransformElement<domMatrix>(inMatrixElement, outMatrix);
+}
+
+void ProcessTranslation(daeElement *inTranslateElement, float *outTranslate)
+{
+ ProcessTransformElement<domTranslate>(inTranslateElement, outTranslate);
+}
+
+void ProcessRotation(daeElement *inRotationElement, float *outRotate)
+{
+ ProcessTransformElement<domRotate>(inRotationElement, outRotate);
+}
+
+void ProcessScale(daeElement *inScaleElement, float *outScale)
+{
+ ProcessTransformElement<domScale>(inScaleElement, outScale);
+}
+} \ No newline at end of file
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxDomUtils.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxDomUtils.h
new file mode 100644
index 00000000..e703bfd4
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxDomUtils.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#pragma once
+
+#include "UICImportSceneGraphTranslation.h"
+#include "UICImportTranslationCommon.h"
+
+namespace UICIMP {
+typedef struct _SFaceMaterialInfo
+{
+ long m_StartFace;
+ long m_FaceCount;
+ std::vector<int> m_MatElementsIDs;
+ std::vector<int> m_MatIDs;
+
+ _SFaceMaterialInfo()
+ : m_StartFace(-1)
+ , m_FaceCount(-1)
+ {
+ }
+
+ _SFaceMaterialInfo(const _SFaceMaterialInfo &info)
+ : m_StartFace(info.m_StartFace)
+ , m_FaceCount(info.m_FaceCount)
+ {
+ m_MatElementsIDs.resize(info.m_MatElementsIDs.size());
+ for (size_t i = 0; i < info.m_MatElementsIDs.size(); i++) {
+ m_MatElementsIDs[i] = info.m_MatElementsIDs[i];
+ }
+
+ m_MatIDs.resize(info.m_MatIDs.size());
+ for (size_t i = 0; i < info.m_MatIDs.size(); i++) {
+ m_MatIDs[i] = info.m_MatIDs[i];
+ }
+ }
+
+ bool operator==(const _SFaceMaterialInfo &info)
+ {
+ // Note: by intension we only compare the material id's
+ if (info.m_MatIDs.size() != m_MatIDs.size()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < info.m_MatIDs.size(); i++) {
+ if (m_MatIDs[i] != info.m_MatIDs[i])
+ return false;
+ }
+
+ return true;
+ }
+
+} SFaceMaterialInfo;
+
+typedef struct _SVertexWeightInfo
+{
+ long m_JointID;
+ float m_Weight;
+ SVector3 m_Position;
+
+ _SVertexWeightInfo(int jointID, float weight, FbxVector4 pos)
+ : m_JointID(jointID)
+ , m_Weight(weight)
+ {
+ m_Position[0] = (float)pos[0];
+ m_Position[1] = (float)pos[1];
+ m_Position[2] = (float)pos[2];
+ }
+ // copy constructor
+ _SVertexWeightInfo(const _SVertexWeightInfo &info)
+ : m_JointID(info.m_JointID)
+ , m_Weight(info.m_Weight)
+ , m_Position(info.m_Position)
+ {
+ }
+
+} SVertexWeightInfo;
+
+void ReadFloat3(FbxDouble3 inArray, float *outFloat)
+{
+ outFloat[0] = (float)inArray[0];
+ outFloat[1] = (float)inArray[1];
+ outFloat[2] = (float)inArray[2];
+}
+
+void ReadFMatrix4(FbxAMatrix inMatrix, float *outFloat)
+{
+ for (int theRow = 0; theRow < 4; theRow++)
+ for (int theColumn = 0; theColumn < 4; theColumn++)
+ outFloat[(theRow * 4) + theColumn] = (float)inMatrix.Get(theColumn, theRow);
+}
+
+void ReadFMatrix4T(FbxAMatrix inMatrix, float *outFloat)
+{
+ for (int theRow = 0; theRow < 4; theRow++)
+ for (int theColumn = 0; theColumn < 4; theColumn++)
+ outFloat[(theRow * 4) + theColumn] = (float)inMatrix.Get(theRow, theColumn);
+}
+
+void WriteFloat4(std::vector<float> &outVector, unsigned long inFaceIndex, const float *inValues)
+{
+ inFaceIndex *= 4;
+
+ outVector[inFaceIndex] = inValues[0];
+ outVector[inFaceIndex + 1] = inValues[1];
+ outVector[inFaceIndex + 2] = inValues[2];
+ outVector[inFaceIndex + 3] = inValues[3];
+}
+
+void WriteFloat3(std::vector<float> &outVector, unsigned long inFaceIndex, const float *inValues)
+{
+ inFaceIndex *= 3;
+
+ outVector[inFaceIndex] = inValues[0];
+ outVector[inFaceIndex + 1] = inValues[1];
+ outVector[inFaceIndex + 2] = inValues[2];
+}
+
+void WriteFloat2(std::vector<float> &outVector, unsigned long inFaceIndex, const float *inValues)
+{
+ inFaceIndex *= 2;
+
+ outVector[inFaceIndex] = inValues[0];
+ outVector[inFaceIndex + 1] = inValues[1];
+}
+
+#define PushAnimationCurve(theAnimCurvesList, inProperty, inComponent) \
+ { \
+ theAnimCurve = inNode->Lcl##inProperty.GetCurve(inAnimLayer, \
+ FBXSDK_CURVENODE_COMPONENT_##inComponent); \
+ if (theAnimCurve) { \
+ theAnimCurvesList.push_back(theAnimCurve); \
+ } \
+ }
+}
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxSGTranslation.cpp b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxSGTranslation.cpp
new file mode 100644
index 00000000..53d15aab
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportFbxSGTranslation.cpp
@@ -0,0 +1,2412 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtAuthoring-config.h"
+
+#ifdef QT_3DSTUDIO_FBX
+
+#include "stdafx.h"
+
+#define FBXSDK_NEW_API 1
+
+#include <boost/filesystem.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <memory>
+#include <map>
+#include <fbxsdk.h>
+#include "UICImportFbxDomUtils.h"
+#include "UICImportSceneGraphTranslation.h"
+#include "foundation/Qt3DSVec3.h"
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+
+using namespace UICIMP;
+
+namespace {
+
+#define IOSREF FbxIOSettings::IOSettingsRef()
+
+typedef boost::unordered_set<FbxNode *> TNodeSet;
+
+//==============================================================================
+// Loads FBX document and processes it.
+//==============================================================================
+
+class FbxDomWalker
+{
+public:
+ FbxDomWalker(ISceneGraphTranslation *inTranslation);
+ ~FbxDomWalker();
+
+public:
+ typedef std::vector<SFaceMaterialInfo> TFaceMaterialIndices;
+ typedef std::vector<_SVertexWeightInfo> TPerVertexWeightInfo;
+ typedef std::vector<_SJointInfo> TJointInfoList;
+ typedef boost::tuple<SVector3, SVector3, SVector2, SVector3, SVector3, SVector4, SVector4,
+ SVector2>
+ TVertexInfoTuple;
+ typedef std::pair<std::map<TVertexInfoTuple, long>,
+ std::vector<std::pair<std::string, TLongsList>>>
+ TFaceIndicies;
+
+ typedef std::vector<TPerVertexWeightInfo> TVertexWeigthList;
+ typedef std::vector<FbxAnimCurve *> TAnimCurveList;
+ typedef std::multimap<const FbxNode *, long> TNodeToIndicesMap;
+ typedef boost::unordered_map<const FbxNode *, bool> TNodeIsAnimatedMap;
+ typedef boost::unordered_map<const FbxNode *, long> TJointNodeHierarchyMap;
+ typedef boost::unordered_set<const FbxNode *> TJointNodeRootSet;
+
+public:
+ bool LoadDocument(const std::string &inFilePath);
+ void ProcessScene();
+ void ProcessAnimationStacks();
+
+protected:
+ template <typename TNodeFilter>
+ void FilterNodeHierarchy(TNodeFilter inFilter, TNodeSet &inSet);
+ void ProcessNode(FbxNode *inFbxNode);
+ void ProcessGroup(FbxNode *inFbxNode);
+ void ProcessMesh(FbxNode *inFbxNode);
+ void ProcessNodeChildren(FbxNode *inFbxNode);
+ long ProcessSkeletonNode(FbxNode *inFbxNode, TNodeSet &inNodeSet, bool inIsRoot);
+ void ProcessTransform(FbxNode *inFbxNode);
+ void ReadVertex(const FbxVector4 *inFbxCtrlPoints, int inFbxCtrlPointIndex, float *outValue,
+ FbxAMatrix &geometricTransformation);
+ void ReadVertex(const TPerVertexWeightInfo &inFbxWeights, int inFbxCtrlPointIndex,
+ float *outValue);
+ void ReadNormal(const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex, float *outValue);
+ void ReadTexCoord(const FbxGeometryElementUV *inFbxUVs, int inFbxIndex, float *outValue);
+ void ReadTexTangent(const FbxGeometryElementTangent *inFbxTangents, int inFbxIndex,
+ float *outValue);
+ void ReadTexTangent(std::vector<SVector3> &inTangentPoints,
+ const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex,
+ float *outValue);
+ void ReadTexBinormal(const FbxGeometryElementBinormal *inFbxBinormals, int inFbxIndex,
+ float *outValue);
+ void ReadTexBinormal(std::vector<SVector3> &inBinormalPoints,
+ const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex,
+ float *outValue);
+ void ReadWeight(const TPerVertexWeightInfo &inFbxWeights, int inFbxIndex, float *outValue);
+ void ReadBoneIndex(const TPerVertexWeightInfo &inFbxWeights, int inFbxIndex, float *outValue,
+ const TJointInfoList &inAbsoluteJoints);
+ void ReadMaterial(const FbxSurfaceMaterial *inMaterial, const int startFace,
+ const int faceCount);
+ void ReadDefaultMaterial(const FbxNode *pNode, const int startFace, const int faceCount);
+ void ProcessTextures(const FbxSurfaceMaterial *inMaterial, const char *fbxMatType,
+ ETextureMapType sgMapType, SColorOrTexture &outColor);
+ void ProcessTextureParameter(FbxTexture *inTexture, STextureParameters &outTextureParameters);
+ void ProcessAnimLayer(FbxNode *inNode, FbxAnimLayer *inAnimLayer);
+ void ProcessAnimCurve(FbxAnimCurve *inAnimCurve, const char *transformType,
+ const char *channelName);
+ // skeletal animation related
+ long GetJointNodeID(const FbxNode *inFbxNode);
+ long GetOrCreateJointNodeID(const FbxNode *inFbxNode);
+ int GetParentJointID(const FbxNode *inFbxNode);
+ void AddJointNode(int jointID, int parentID, FbxAMatrix &invBindPose,
+ FbxAMatrix &localToGlobalBoneSpace, TJointInfoList &outJointInfoList);
+
+ // mesh pre-processing
+ void GenerateMeshTangents(const FbxMesh *inFbxMesh, std::vector<SVector3> &outTangents,
+ std::vector<SVector3> &outBinormals);
+
+ void QueryMaterialInfo(FbxMesh *theFbxMesh, SFaceMaterialInfo *faceMatInfo);
+ // mesh deformer related
+ void GetVertexWeights(FbxMesh *theFbxMesh, TVertexWeigthList &outWeights,
+ TJointInfoList &outJointInfoList, TNodeSet &outBoneSet);
+
+ // Animation related
+ bool ApplyAnimation(const FbxNode *inNode);
+ bool IsAnimated(const FbxNode *inNode);
+ void GetIndicesFromNode(const FbxNode *inNode, TLongsList &outIndicies);
+ bool CurveNodeIsAnimated(FbxAnimCurveNode *inAnimCurveNode);
+ void FilterAnimCurve(FbxAnimCurve *inAnimCurve, std::vector<int> &outKeyIndexList);
+
+protected:
+ FbxManager *m_FbxManager;
+ FbxScene *m_FbxScene;
+ ISceneGraphTranslation *m_Translator;
+ long m_AnimationTrackCount;
+ TNodeToIndicesMap m_NodeToIndicies;
+ TNodeIsAnimatedMap m_NodeIsAnimatedMap;
+ TJointNodeHierarchyMap m_JointNodeHierarchyMap;
+ // Set if nodes we need to export in order to see all meshes in the file.
+ TNodeSet m_meshNodes;
+ EAuthoringToolType m_AuthoringToolType;
+};
+
+FbxDomWalker::FbxDomWalker(ISceneGraphTranslation *inTranslation)
+ : m_FbxManager(NULL)
+ , m_FbxScene(NULL)
+ , m_Translator(inTranslation)
+ , m_AnimationTrackCount(0)
+ , m_AuthoringToolType(EAuthoringToolType_Unknown)
+{
+}
+
+FbxDomWalker::~FbxDomWalker()
+{
+ if (m_FbxScene != NULL)
+ m_FbxScene->Destroy();
+ if (m_FbxManager != NULL)
+ m_FbxManager->Destroy();
+}
+
+/**
+* @brief Load a FBX document
+*
+* @return load status
+*/
+bool FbxDomWalker::LoadDocument(const std::string &inFilePath)
+{
+ if (QFile::exists(QString::fromStdString(inFilePath))) {
+ m_FbxManager = FbxManager::Create();
+
+ FbxIOSettings *theIOSettings = FbxIOSettings::Create(m_FbxManager, IOSROOT);
+ m_FbxManager->SetIOSettings(theIOSettings);
+
+ m_FbxScene = FbxScene::Create(m_FbxManager, "");
+
+ FbxImporter *theImporter = FbxImporter::Create(m_FbxManager, "");
+ if (!theImporter->Initialize(inFilePath.c_str(), -1, m_FbxManager->GetIOSettings())) {
+ theImporter->Destroy();
+ return false;
+ }
+
+ int major = 0, minor = 0, revision = 0;
+ theImporter->GetFileVersion(major, minor, revision);
+
+ if (theImporter->IsFBX()) {
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_MATERIAL, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_TEXTURE, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_LINK, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_SHAPE, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_GOBO, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_ANIMATION, true);
+ m_FbxManager->GetIOSettings()->SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, true);
+ }
+
+ bool theStatus = theImporter->Import(m_FbxScene);
+ if (theStatus) {
+ // get authoring tool
+ FbxDocumentInfo *pDocInfo = m_FbxScene->GetDocumentInfo();
+ if (pDocInfo) {
+ const char *appName = "3ds Max";
+ FbxString appString;
+
+ // this should give us the latest used app on this file
+ FbxProperty lastSavedAppProp = pDocInfo->LastSaved_ApplicationName;
+ if (lastSavedAppProp.IsValid()) {
+ FbxDataType lPropertyDataType = lastSavedAppProp.GetPropertyDataType();
+
+ if (lPropertyDataType.GetType() == eFbxString) {
+ appString = lastSavedAppProp.Get<FbxString>();
+ appName = appString.Buffer();
+ }
+ }
+
+ if (!strcmp(appName, "")) {
+ // otherwise try to get original app name
+ FbxProperty originAppProp = pDocInfo->Original_ApplicationName;
+ if (originAppProp.IsValid()) {
+ FbxDataType lPropertyDataType = originAppProp.GetPropertyDataType();
+
+ if (lPropertyDataType.GetType() == eFbxString) {
+ appString = originAppProp.Get<FbxString>();
+ appName = appString.Buffer();
+ }
+ }
+ }
+
+ if (!strcmp(appName, "3ds Max")) {
+ m_Translator->SetAuthoringTool(EAuthoringToolType_FBX_Max,
+ major * 1000 + minor * 100 + revision);
+ m_AuthoringToolType = EAuthoringToolType_FBX_Max;
+ } else if (!strcmp(appName, "modo")) {
+ m_Translator->SetAuthoringTool(EAuthoringToolType_FBX_Modo,
+ major * 1000 + minor * 100 + revision);
+ m_AuthoringToolType = EAuthoringToolType_FBX_Modo;
+ } else if (!strcmp(appName, "Maya")) {
+ m_Translator->SetAuthoringTool(EAuthoringToolType_FBX_Maya,
+ major * 1000 + minor * 100 + revision);
+ m_AuthoringToolType = EAuthoringToolType_FBX_Maya;
+ } else {
+ m_Translator->SetAuthoringTool(EAuthoringToolType_FBX_Max,
+ major * 1000 + minor * 100 + revision);
+ m_AuthoringToolType = EAuthoringToolType_FBX_Max;
+ }
+ } else {
+ m_Translator->SetAuthoringTool(EAuthoringToolType_FBX_Max,
+ major * 1000 + minor * 100 + revision);
+ m_AuthoringToolType = EAuthoringToolType_FBX_Max;
+ }
+ }
+
+ theImporter->Destroy();
+
+ return theStatus;
+ }
+
+ return false;
+}
+
+inline void AddParentsToSet(FbxNode &inNode, TNodeSet &ioSet)
+{
+ FbxNode *theParent = inNode.GetParent();
+ while (theParent && ioSet.find(theParent) == ioSet.end()) {
+ ioSet.insert(theParent);
+ theParent = theParent->GetParent();
+ }
+}
+
+template <typename TNodeFilter>
+void DoFilterNodeHierarchy(TNodeFilter inFilter, TNodeSet &ioSet, FbxNode &inNode)
+{
+ if (inFilter(inNode) && ioSet.find(&inNode) == ioSet.end()) {
+ ioSet.insert(&inNode);
+ AddParentsToSet(inNode, ioSet);
+ }
+ int childCount = inNode.GetChildCount();
+ for (int idx = 0; idx < childCount; ++idx) {
+ FbxNode *theNode = inNode.GetChild(idx);
+ DoFilterNodeHierarchy(inFilter, ioSet, *theNode);
+ }
+}
+
+template <typename TNodeFilter>
+void FbxDomWalker::FilterNodeHierarchy(TNodeFilter inFilter, TNodeSet &inSet)
+{
+ if (m_FbxScene->GetRootNode())
+ DoFilterNodeHierarchy(inFilter, inSet, *m_FbxScene->GetRootNode());
+}
+
+struct SMeshFilter
+{
+ // filter out valid meshes. Anything else we don't care about.
+ bool operator()(FbxNode &inFbxNode) const
+ {
+ if (inFbxNode.GetNodeAttribute() != NULL) {
+ return inFbxNode.GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh
+ && inFbxNode.GetMesh() && inFbxNode.GetMesh()->GetControlPointsCount() != 0;
+ }
+
+ return false;
+ }
+};
+
+struct SNodeSetFilter
+{
+ const TNodeSet &m_NodeSet;
+ SNodeSetFilter(const TNodeSet &inSet)
+ : m_NodeSet(inSet)
+ {
+ }
+ bool operator()(FbxNode &inNode) const { return m_NodeSet.find(&inNode) != m_NodeSet.end(); }
+};
+
+/**
+* @brief Process a scene
+*
+* @return no return
+*/
+void FbxDomWalker::ProcessScene()
+{
+ if (m_FbxScene != NULL) {
+ // FbxAxisSystem::MayaYUp.ConvertScene( m_FbxScene );
+ int sign;
+ FbxAxisSystem SceneAxisSystem = m_FbxScene->GetGlobalSettings().GetAxisSystem();
+ if (SceneAxisSystem.GetUpVector(sign) == FbxAxisSystem::eZAxis) {
+ std::vector<INodeTransform *> theTransforms;
+
+ NodeTransform *theRotX = new NodeTransform(ETransformType_Rotation4);
+ (*theRotX)[0] = 1.0f;
+ (*theRotX)[1] = (*theRotX)[2] = 0.0f;
+ (*theRotX)[3] =
+ -90.0f; // Apply a -90 degree rotation on the X-axis to 'right' the model
+ theTransforms.push_back(theRotX);
+
+ m_Translator->SetTransforms(theTransforms);
+ delete theRotX;
+ }
+
+ // triangulate just in case
+ FbxGeometryConverter theFbxGeometryConverter(m_FbxManager);
+ bool bOk = theFbxGeometryConverter.Triangulate(m_FbxScene, true, true);
+ if (!bOk) {
+ QT3DS_ASSERT(false);
+ }
+
+ m_meshNodes.clear();
+ FilterNodeHierarchy(SMeshFilter(), m_meshNodes);
+ ProcessNode(m_FbxScene->GetRootNode());
+ }
+}
+
+/**
+* @brief Get/create the ID of a joint
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return joint id
+*/
+long FbxDomWalker::GetJointNodeID(const FbxNode *inFbxNode)
+{
+ TJointNodeHierarchyMap::iterator theIter;
+
+ theIter = m_JointNodeHierarchyMap.find(inFbxNode);
+
+ if (theIter == m_JointNodeHierarchyMap.end())
+ theIter = m_JointNodeHierarchyMap
+ .insert(std::make_pair(inFbxNode, (long)m_JointNodeHierarchyMap.size()))
+ .first;
+
+ return theIter->second;
+}
+
+/**
+* @brief Get the parent ID of a joint
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return parent joint id
+*/
+int FbxDomWalker::GetParentJointID(const FbxNode *inFbxNode)
+{
+ long nodeIndex = -1;
+ TJointNodeHierarchyMap::iterator theIter;
+ const FbxNode *parent = inFbxNode->GetParent();
+
+ while (parent) {
+ theIter = m_JointNodeHierarchyMap.find(parent);
+
+ if (theIter != m_JointNodeHierarchyMap.end()) {
+ nodeIndex = theIter->second;
+ break;
+ }
+
+ parent = parent->GetParent();
+ }
+
+ return nodeIndex;
+}
+
+/**
+* @brief Process children nodes
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return no return
+*/
+void FbxDomWalker::ProcessNodeChildren(FbxNode *inFbxNode)
+{
+ for (int i = 0; i < inFbxNode->GetChildCount(); ++i) {
+ if (m_meshNodes.find(inFbxNode) != m_meshNodes.end())
+ ProcessNode(inFbxNode->GetChild(i));
+ }
+}
+
+/**
+* @brief Process a group
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return no return
+*/
+void FbxDomWalker::ProcessGroup(FbxNode *inFbxNode)
+{
+ std::string groupName = "Group_";
+ groupName += inFbxNode->GetName();
+ m_Translator->PushGroup(groupName.c_str());
+ ProcessTransform(inFbxNode);
+ ProcessNodeChildren(inFbxNode);
+ m_Translator->PopGroup();
+}
+
+/**
+* @brief Process a skeleton node and the children
+*
+* @param[in] inFbxNode Pointer to node element
+* @param[in] inNodeSet Pointer to a skeleton node set to process
+* @param[in] inRoot True if root skeleton node
+*
+* @return root id
+*/
+long FbxDomWalker::ProcessSkeletonNode(FbxNode *inFbxNode, TNodeSet &inNodeSet, bool inRoot)
+{
+ bool pushGroup = false;
+ long groupId = -1;
+ if (inFbxNode->GetNodeAttribute() != NULL) {
+ std::string groupName = "Skeleton_";
+ groupName += inFbxNode->GetName();
+ m_Translator->PushGroup(groupName.c_str());
+ pushGroup = true;
+ groupId = GetJointNodeID(inFbxNode);
+
+ ProcessTransform(inFbxNode);
+ if (inRoot)
+ m_Translator->SetIgnoresParentTransform(true);
+
+ inRoot = false;
+
+ m_Translator->SetGroupSkeletonId(groupId);
+ }
+
+ for (int i = 0; i < inFbxNode->GetChildCount(); ++i) {
+ FbxNode *childNode = inFbxNode->GetChild(i);
+ if (inNodeSet.find(childNode) != inNodeSet.end()) {
+ long subId = ProcessSkeletonNode(inFbxNode->GetChild(i), inNodeSet, inRoot);
+ if (groupId == -1)
+ groupId = subId;
+ }
+ }
+
+ if (pushGroup)
+ m_Translator->PopGroup();
+
+ return groupId;
+}
+
+/**
+* @brief Process a node and the children
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return no return
+*/
+void FbxDomWalker::ProcessNode(FbxNode *inFbxNode)
+{
+ if (inFbxNode->GetNodeAttribute() != NULL && m_meshNodes.find(inFbxNode) != m_meshNodes.end()) {
+
+ FbxNodeAttribute::EType theAttribType = inFbxNode->GetNodeAttribute()->GetAttributeType();
+ switch (theAttribType) {
+ case FbxNodeAttribute::eMesh: {
+ FbxMesh *theFbxMesh = inFbxNode->GetMesh();
+ if (theFbxMesh == NULL || theFbxMesh->GetControlPointsCount() == 0) {
+ ProcessGroup(inFbxNode);
+ } else {
+ ProcessMesh(inFbxNode);
+ }
+ } break;
+ // Ignore skeleton for now; we add them as the first child of the model with a special
+ // flag indicating they ignore parent transforms.
+ case FbxNodeAttribute::eSkeleton:
+ break;
+ default:
+ ProcessGroup(inFbxNode);
+ break;
+ }
+ } else
+ ProcessNodeChildren(inFbxNode);
+}
+
+/**
+* @brief Get the geometric transform of a node
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return geometric transform matrix
+*/
+FbxAMatrix getGeometricTransform(const FbxNode *pNode)
+{
+ FbxAMatrix GeometryMat;
+
+ GeometryMat.SetT(pNode->GetGeometricTranslation(FbxNode::eSourcePivot));
+ GeometryMat.SetR(pNode->GetGeometricRotation(FbxNode::eSourcePivot));
+ GeometryMat.SetS(pNode->GetGeometricScaling(FbxNode::eSourcePivot));
+
+ return GeometryMat;
+}
+
+/**
+* @brief Process a transform for a node and apply animation track
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @returna no return
+*/
+void FbxDomWalker::ProcessTransform(FbxNode *inFbxNode)
+{
+ std::vector<INodeTransform *> theTransforms;
+
+ // first apply animation
+ ApplyAnimation(inFbxNode);
+
+ // add local node transforms
+ // if animated the non-static transforms are overwritten by the animation
+ {
+ FbxAMatrix theTransformMatrix;
+
+ theTransformMatrix = inFbxNode->EvaluateLocalTransform();
+
+ theTransforms.push_back(new NodeTransform(ETransformType_Matrix4x4));
+
+ ReadFMatrix4(theTransformMatrix, *theTransforms.back());
+ }
+
+ m_Translator->SetTransforms(theTransforms);
+
+ std::for_each(theTransforms.begin(), theTransforms.end(), NodeTransform::Delete);
+}
+
+/**
+* @brief Add a joint node to the list
+*
+* @param[in] jointID Joint ID
+* @param[in] parentID Parent joint ID
+* @param[in] invBindPose Bind pose matrix
+* @param[in] localToGlobalBoneSpace Global bone space matrix
+* @param[in/out] outJointInfoList List of joint nodes belonging to a mesh
+*
+* @returna no return
+*/
+void FbxDomWalker::AddJointNode(int jointID, int parentID, FbxAMatrix &invBindPose,
+ FbxAMatrix &localToGlobalBoneSpace,
+ TJointInfoList &outJointInfoList)
+{
+ float invMatrix[16];
+ ReadFMatrix4T(invBindPose, invMatrix);
+ float lTobMatrix[16];
+ ReadFMatrix4T(localToGlobalBoneSpace, lTobMatrix);
+
+ outJointInfoList.push_back(SJointInfo(jointID, parentID, invMatrix, lTobMatrix));
+}
+
+// Get the matrix of the given pose
+FbxAMatrix GetPoseMatrix(FbxPose *pPose, int pNodeIndex)
+{
+ FbxAMatrix lPoseMatrix;
+ FbxMatrix lMatrix = pPose->GetMatrix(pNodeIndex);
+
+ memcpy((double *)lPoseMatrix, (double *)lMatrix, sizeof(lMatrix.mData));
+
+ return lPoseMatrix;
+}
+
+// get the global position of a node
+FbxAMatrix GetGlobalPosition(FbxNode *pNode, FbxPose *pPose)
+{
+ FbxAMatrix lGlobalPosition;
+ bool lPositionFound = false;
+
+ if (pPose) {
+ int lNodeIndex = pPose->Find(pNode);
+
+ if (lNodeIndex > -1) {
+ // The bind pose is always a global matrix.
+ // If we have a rest pose, we need to check if it is
+ // stored in global or local space.
+ if (pPose->IsBindPose() || !pPose->IsLocalMatrix(lNodeIndex)) {
+ lGlobalPosition = GetPoseMatrix(pPose, lNodeIndex);
+ } else {
+ // We have a local matrix, we need to convert it to
+ // a global space matrix.
+ FbxAMatrix lParentGlobalPosition;
+
+ if (pNode->GetParent()) {
+ lParentGlobalPosition = GetGlobalPosition(pNode->GetParent(), pPose);
+ }
+
+ FbxAMatrix lLocalPosition = GetPoseMatrix(pPose, lNodeIndex);
+ lGlobalPosition = lParentGlobalPosition * lLocalPosition;
+ }
+
+ lPositionFound = true;
+ }
+ }
+
+ if (!lPositionFound) {
+ // There is no pose entry for that node, get the current global position instead.
+
+ // Ideally this would use parent global position and local position to compute the global
+ // position.
+ // Unfortunately the equation
+ // lGlobalPosition = pParentGlobalPosition * lLocalPosition
+ // does not hold when inheritance type is other than "Parent" (RSrs).
+ // To compute the parent rotation and scaling is tricky in the RrSs and Rrs cases.
+ lGlobalPosition = pNode->EvaluateGlobalTransform(0);
+ }
+ return lGlobalPosition;
+}
+
+// Compute the transform matrix that the cluster will transform the vertex at binding time.
+void ComputeInitialBindPoseTransform(FbxAMatrix &pMeshGlobalPosition, FbxMesh *pMesh,
+ FbxCluster *pCluster, FbxPose * /* pPose */,
+ FbxAMatrix &pInverseBindMatrix,
+ FbxAMatrix &pJointToGlobalMatrix)
+{
+ FbxCluster::ELinkMode lClusterMode = pCluster->GetLinkMode();
+
+ FbxAMatrix lReferenceGlobalInitPosition;
+ FbxAMatrix lReferenceGlobalCurrentPosition;
+ FbxAMatrix lAssociateGlobalInitPosition;
+ FbxAMatrix lAssociateGlobalCurrentPosition;
+ FbxAMatrix lClusterGlobalInitPosition;
+ FbxAMatrix lClusterGlobalCurrentPosition;
+
+ FbxAMatrix lReferenceGeometry;
+ FbxAMatrix lAssociateGeometry;
+ FbxAMatrix lClusterGeometry;
+
+ FbxAMatrix lClusterRelativeInitPosition;
+ FbxAMatrix lClusterRelativeCurrentPositionInverse;
+
+ if (lClusterMode == FbxCluster::eAdditive && pCluster->GetAssociateModel()) {
+ // not supported yet
+ QT3DS_ASSERT(false);
+ } else {
+ pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
+ lReferenceGlobalCurrentPosition = pMeshGlobalPosition;
+ // Multiply lReferenceGlobalInitPosition by Geometric Transformation
+ lReferenceGeometry = getGeometricTransform(pMesh->GetNode());
+ lReferenceGlobalInitPosition *= lReferenceGeometry;
+
+ // Get the link initial global position and the link current global position.
+ pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
+
+ // Compute the initial position of the link relative to the reference.
+ lClusterRelativeInitPosition =
+ lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
+
+ pInverseBindMatrix = lReferenceGlobalCurrentPosition.Inverse();
+ pJointToGlobalMatrix = lClusterRelativeInitPosition;
+ }
+}
+
+/**
+* @brief Reads the weigths belonging to each vertex
+*
+* @param[in] inNode Pointer to node element
+* @param[in] inFbxMesh Pointer to mesh element
+* @param[out] outWeights List of all weights for al vertices
+* @param[out] outJointInfoList List of joint (bones) info belonging to this mesh
+* @param[out] outBoneSet List of bones nodes belonging to this mesh
+*
+* @returna unique index
+*/
+void FbxDomWalker::GetVertexWeights(FbxMesh *inFbxMesh, TVertexWeigthList &outWeights,
+ TJointInfoList &outJointInfoList, TNodeSet &outBoneSet)
+{
+ int theDeformerCount = inFbxMesh->GetDeformerCount(FbxDeformer::eSkin);
+ int theBlendShapeDeformerCount = inFbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
+ int theVertexCacheDeformerCount = inFbxMesh->GetDeformerCount(FbxDeformer::eVertexCache);
+
+ if (theBlendShapeDeformerCount && theVertexCacheDeformerCount) {
+ QT3DS_ASSERT(false);
+ // not supported
+ return;
+ }
+
+ if (!theDeformerCount) {
+ return;
+ }
+
+ FbxCluster::ELinkMode theClusterMode = FbxCluster::eNormalize;
+
+ // a weight entry for each vertex
+ outWeights.resize(inFbxMesh->GetControlPointsCount());
+
+ // right now we do not handle multiple deformers per mesh
+ QT3DS_ASSERT(theDeformerCount <= 1);
+
+ for (int i = 0; i < theDeformerCount; i++) {
+ FbxSkin *theSkin = FbxCast<FbxSkin>(inFbxMesh->GetDeformer(i));
+
+ if (theSkin && theSkin->GetClusterCount() > 0) {
+ std::vector<FbxVector4>
+ theGlobaBindPose; // contains the transformed vertices to bone space
+
+ FbxDeformer::EDeformerType theDeformerType = theSkin->GetDeformerType();
+ // we only support skin deformer
+ if (theDeformerType != FbxDeformer::eSkin) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ theClusterMode = theSkin->GetCluster(0)->GetLinkMode();
+
+ theGlobaBindPose.resize(inFbxMesh->GetControlPointsCount());
+
+ // same for all clusters
+ // GetTransformMatrix is the matrix to convert vertices of the mesh (skin) to world
+ // space
+ // at initial binding
+ FbxAMatrix thelocalSkinToWorldSpace;
+ theSkin->GetCluster(0)->GetTransformMatrix(thelocalSkinToWorldSpace);
+ thelocalSkinToWorldSpace *= getGeometricTransform(inFbxMesh->GetNode());
+
+ // convert all vertices from mesh space to world space
+ for (unsigned long vertexId = 0; vertexId < theGlobaBindPose.size(); vertexId++) {
+ theGlobaBindPose[vertexId] =
+ thelocalSkinToWorldSpace.MultT(inFbxMesh->GetControlPoints()[vertexId]);
+ }
+
+ for (int clusterId = 0; clusterId < theSkin->GetClusterCount(); clusterId++) {
+ const FbxCluster *theCluster = theSkin->GetCluster(clusterId);
+
+ if (!theCluster->GetLink())
+ continue;
+
+ // this call adds the link node to our global list if not found
+ int jointIdx = GetJointNodeID(theCluster->GetLink());
+ int parentJointIdx = GetParentJointID(theCluster->GetLink());
+
+ // should always be a skleton right now
+ QT3DS_ASSERT(theCluster->GetLink()->GetNodeAttribute()->GetAttributeType()
+ == FbxNodeAttribute::eSkeleton);
+
+ // All the links must have the same link mode. and right now we don't support
+ // additive mode
+ if ((theCluster->GetLinkMode() != theClusterMode)
+ || (theClusterMode == FbxCluster::eAdditive)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ // Add the link node to the bone list
+ outBoneSet.insert(const_cast<FbxNode *>(theCluster->GetLink()));
+
+ int *vertexIDs = theCluster->GetControlPointIndices();
+ double *weights = theCluster->GetControlPointWeights();
+
+ FbxAMatrix BoneBindposeMatrix;
+ FbxAMatrix invBoneBindposeMatrix;
+ // GetTransformLinkMatrix converts from cluster (bone) space to world space
+ theCluster->GetTransformLinkMatrix(BoneBindposeMatrix);
+ // The inverse converts from world space to cluster (bone) sapce
+ invBoneBindposeMatrix = BoneBindposeMatrix.Inverse();
+ // This Matrix convertes from local bone space to world space
+ FbxAMatrix boneLocalToSkinWorldSpace =
+ invBoneBindposeMatrix * thelocalSkinToWorldSpace;
+ FbxAMatrix worldSpaceToSkinSpace = thelocalSkinToWorldSpace.Inverse();
+
+ // add a joint node to our internal list
+ AddJointNode(jointIdx, parentJointIdx, boneLocalToSkinWorldSpace,
+ worldSpaceToSkinSpace, outJointInfoList);
+
+ // get the actual weights
+ for (int j = 0; j < theCluster->GetControlPointIndicesCount(); j++) {
+ const int vertexID = vertexIDs[j];
+ const float w = (float)weights[j];
+
+ // this can happen with smooting groups
+ if (vertexID >= inFbxMesh->GetControlPointsCount())
+ continue;
+ if (w == 0.0f)
+ continue;
+
+ // store away values and convert vertices to local bone space
+ outWeights[vertexID].push_back(_SVertexWeightInfo(
+ jointIdx, w, invBoneBindposeMatrix.MultT(theGlobaBindPose[vertexID])));
+ }
+ }
+ }
+ }
+
+ // according to the cluster link mode we must adjust the weights
+ for (unsigned long vertexID = 0; vertexID < outWeights.size(); vertexID++) {
+ float weightSum = 0.0f;
+
+ // we currently only support up to 4 weights per vertex
+ QT3DS_ASSERT(outWeights[vertexID].size() < 4);
+
+ // get total sum of the weigths for each vertex
+ for (unsigned long i = 0; i < outWeights[vertexID].size(); i++) {
+ weightSum += outWeights[vertexID][i].m_Weight;
+ }
+
+ if (weightSum != 0.0f) {
+ switch (theClusterMode) {
+ case FbxCluster::eNormalize: {
+ float oneOverWeightSum = 1.0f / weightSum;
+ // in this mode we need to normalize the weights
+ for (unsigned long i = 0; i < outWeights[vertexID].size(); i++) {
+ outWeights[vertexID][i].m_Weight *= oneOverWeightSum;
+ }
+ } break;
+ case FbxCluster::eTotalOne: {
+ // in this mode we must sum up to one
+ if (weightSum < 1.0f) {
+ outWeights[vertexID].push_back(_SVertexWeightInfo(
+ 0, 1.0f - weightSum, inFbxMesh->GetControlPoints()[vertexID]));
+ }
+ } break;
+ case FbxCluster::eAdditive:
+ // how should we handle this mode?
+ break;
+ }
+ }
+ }
+}
+
+static int GetNormalIndex(const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex)
+{
+ int theFbxNormalIndex = 0;
+ switch (inFbxNormals->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxNormalIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxNormalIndex = inFbxNormals->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ return theFbxNormalIndex;
+}
+
+/**
+* @brief computer tangents and binormals from mesh input data like
+* normals and uv's.
+* If you are interested in how it works check
+* "Math for 3D Game programming and CG"
+*
+* @param[in] inFbxMesh pointer to fbx mesh
+* @param[in/out] outTangents output vectors of tangents
+* @param[in/out] outBinormals output vectors of binormals
+*
+* @returna unique index
+*/
+void FbxDomWalker::GenerateMeshTangents(const FbxMesh *inFbxMesh,
+ std::vector<SVector3> &outTangents,
+ std::vector<SVector3> &outBinormals)
+{
+ // check if we have everything we need
+
+ // vertex data
+ // int theFbxCtrlPointCount = inFbxMesh->GetControlPointsCount();
+ const FbxVector4 *theFbxCtrlPoints = inFbxMesh->GetControlPoints();
+
+ // normal data
+ const FbxGeometryElementNormal *theFbxNormals = inFbxMesh->GetElementNormal();
+ int theFbxNormalCount = 0;
+ FbxGeometryElement::EMappingMode theFbxNormalsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxNormals) {
+ theFbxNormalCount = theFbxNormals->GetDirectArray().GetCount();
+ theFbxNormalsMappingMode = theFbxNormals->GetMappingMode();
+ }
+ // uv data
+ const FbxGeometryElementUV *theFbxUVs = inFbxMesh->GetElementUV();
+ int theFbxUVsCount = 0;
+ FbxGeometryElement::EMappingMode theFbxUVsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxUVs) {
+ theFbxUVsCount = theFbxUVs->GetDirectArray().GetCount();
+ theFbxUVsMappingMode = theFbxUVs->GetMappingMode();
+ }
+
+ // we need normals and uv's
+ if (theFbxNormalCount == 0 || theFbxUVsCount == 0) {
+ return;
+ }
+
+ // allocate arrays
+ SVector3 *tan1 = new SVector3[theFbxNormalCount * 2];
+ SVector3 *tan2 = tan1 + theFbxNormalCount;
+ SVector3 *normals = new SVector3[theFbxNormalCount];
+ char *normalsPerVtx = new char[theFbxNormalCount];
+
+ // failed to allocate menory
+ if (!tan1 || !normals || !normalsPerVtx) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ memset(tan1, 0x00, theFbxNormalCount * sizeof(SVector3) * 2);
+ memset(normals, 0x00, theFbxNormalCount * sizeof(SVector3));
+ memset(normalsPerVtx, 0x00, theFbxNormalCount * sizeof(char));
+
+ FbxAMatrix identidy;
+ identidy.SetIdentity();
+
+ int theVertexID = 0;
+ SVector3 vx1, vx2, vx3;
+ SVector3 n1, n2, n3;
+ SVector2 uv1, uv2, uv3;
+
+ int theFbxTriangleCount = inFbxMesh->GetPolygonCount();
+ for (int i = 0; i < theFbxTriangleCount; i++) {
+ QT3DS_ASSERT(inFbxMesh->GetPolygonSize(i) == 3);
+
+ // read vertex 1 data
+ int theFbxCtrlPointIndex1 = inFbxMesh->GetPolygonVertex(i, 0);
+ ReadVertex(theFbxCtrlPoints, theFbxCtrlPointIndex1, (float *)vx1, identidy);
+ ReadNormal(theFbxNormals, (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex1,
+ (float *)n1);
+ ReadTexCoord(theFbxUVs, (theFbxUVsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex1,
+ (float *)uv1);
+ theFbxCtrlPointIndex1 = GetNormalIndex(
+ theFbxNormals, (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex1);
+ ++theVertexID;
+
+ // read vertex 2 data
+ int theFbxCtrlPointIndex2 = inFbxMesh->GetPolygonVertex(i, 1);
+ ReadVertex(theFbxCtrlPoints, theFbxCtrlPointIndex2, (float *)vx2, identidy);
+ ReadNormal(theFbxNormals, (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex2,
+ (float *)n2);
+ ReadTexCoord(theFbxUVs, (theFbxUVsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex2,
+ (float *)uv2);
+ theFbxCtrlPointIndex2 = GetNormalIndex(
+ theFbxNormals, (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex2);
+ ++theVertexID;
+
+ // read vertex 3 data
+ int theFbxCtrlPointIndex3 = inFbxMesh->GetPolygonVertex(i, 2);
+ ReadVertex(theFbxCtrlPoints, theFbxCtrlPointIndex3, (float *)vx3, identidy);
+ ReadNormal(theFbxNormals, (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex3,
+ (float *)n3);
+ ReadTexCoord(theFbxUVs, (theFbxUVsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex3,
+ (float *)uv3);
+ theFbxCtrlPointIndex3 = GetNormalIndex(
+ theFbxNormals, (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex3);
+ ++theVertexID;
+
+ // compute triangle vectors
+ float x1 = vx2[0] - vx1[0];
+ float x2 = vx3[0] - vx1[0];
+ float y1 = vx2[1] - vx1[1];
+ float y2 = vx3[1] - vx1[1];
+ float z1 = vx2[2] - vx1[2];
+ float z2 = vx3[2] - vx1[2];
+
+ float s1 = uv2[0] - uv1[0];
+ float s2 = uv3[0] - uv1[0];
+ float t1 = uv2[1] - uv1[1];
+ float t2 = uv3[1] - uv1[1];
+
+ float area = (s1 * t2 - s2 * t1);
+ if (area == 0.0)
+ area = 1.0;
+
+ float r = 1.0f / area;
+
+ float sx = ((t2 * x1 - t1 * x2) * r);
+ float sy = ((t2 * y1 - t1 * y2) * r);
+ float sz = ((t2 * z1 - t1 * z2) * r);
+
+ float tx = ((s1 * x2 - s2 * x1) * r);
+ float ty = ((s1 * y2 - s2 * y1) * r);
+ float tz = ((s1 * z2 - s2 * z1) * r);
+
+ tan1[theFbxCtrlPointIndex1][0] += sx;
+ tan1[theFbxCtrlPointIndex1][1] += sy;
+ tan1[theFbxCtrlPointIndex1][2] += sz;
+ tan1[theFbxCtrlPointIndex2][0] += sx;
+ tan1[theFbxCtrlPointIndex2][1] += sy;
+ tan1[theFbxCtrlPointIndex2][2] += sz;
+ tan1[theFbxCtrlPointIndex3][0] += sx;
+ tan1[theFbxCtrlPointIndex3][1] += sy;
+ tan1[theFbxCtrlPointIndex3][2] += sz;
+
+ tan2[theFbxCtrlPointIndex1][0] += tx;
+ tan2[theFbxCtrlPointIndex1][1] += ty;
+ tan2[theFbxCtrlPointIndex1][2] += tz;
+ tan2[theFbxCtrlPointIndex2][0] += tx;
+ tan2[theFbxCtrlPointIndex2][1] += ty;
+ tan2[theFbxCtrlPointIndex2][2] += tz;
+ tan2[theFbxCtrlPointIndex3][0] += tx;
+ tan2[theFbxCtrlPointIndex3][1] += ty;
+ tan2[theFbxCtrlPointIndex3][2] += tz;
+
+ normals[theFbxCtrlPointIndex1][0] += n1.m_Data[0];
+ normals[theFbxCtrlPointIndex1][1] += n1.m_Data[1];
+ normals[theFbxCtrlPointIndex1][2] += n1.m_Data[2];
+ normals[theFbxCtrlPointIndex2][0] += n2.m_Data[0];
+ normals[theFbxCtrlPointIndex2][1] += n2.m_Data[1];
+ normals[theFbxCtrlPointIndex2][2] += n2.m_Data[2];
+ normals[theFbxCtrlPointIndex3][0] += n3.m_Data[0];
+ normals[theFbxCtrlPointIndex3][1] += n3.m_Data[1];
+ normals[theFbxCtrlPointIndex3][2] += n3.m_Data[2];
+
+ normalsPerVtx[theFbxCtrlPointIndex1] += 1;
+ normalsPerVtx[theFbxCtrlPointIndex2] += 1;
+ normalsPerVtx[theFbxCtrlPointIndex3] += 1;
+ }
+
+ outTangents.resize(theFbxNormalCount);
+ outBinormals.resize(theFbxNormalCount);
+ // compute actual tangents
+ for (int i = 0; i < theFbxNormalCount; i++) {
+ QT3DSVec3 n(normals[i][0], normals[i][1], normals[i][2]);
+ const qt3ds::QT3DSVec3 t(tan1[i][0], tan1[i][1], tan1[i][2]);
+ const qt3ds::QT3DSVec3 t2(tan2[i][0], tan2[i][1], tan2[i][2]);
+
+ n = n / normalsPerVtx[i];
+
+ // Gram-Schmidt orthogonalize
+ qt3ds::QT3DSVec3 temp, t3, bi;
+ temp = t - n * n.dot(t);
+ t3 = temp;
+ t3.normalize();
+ outTangents[i][0] = t3.x;
+ outTangents[i][1] = t3.y;
+ outTangents[i][2] = t3.z;
+
+ // Calculate bi tangent
+ temp = n.cross(t);
+ temp.normalize();
+ float dp = temp.dot(t2);
+ float sig = (dp < 0.0f) ? -1.0f : 1.0f;
+ outBinormals[i][0] = temp.x * sig;
+ outBinormals[i][1] = temp.y * sig;
+ outBinormals[i][2] = temp.z * sig;
+ }
+
+ delete[] tan1;
+ delete[] normals;
+ delete[] normalsPerVtx;
+}
+
+/**
+* @brief Returns a unique face index which is made up of a vertex, normal,
+* texcoord index and weights tuple.
+* The order of ioFaceIndicies.first eventually becomes the order which we will
+ * fill the vertex, normal and texcoord arrays weights the for Model.
+*
+* @param[in/out] ioFaceIndicies List to add the element
+* @param[in/out] inFaceValues The tuple which is the key
+*
+* @returna unique index
+*/
+long RetrieveFaceIndex(FbxDomWalker::TFaceIndicies &ioFaceIndicies,
+ const FbxDomWalker::TVertexInfoTuple &inFaceValues)
+{
+ std::pair<FbxDomWalker::TFaceIndicies::first_type::iterator, bool> theTupleEntry;
+
+ theTupleEntry = ioFaceIndicies.first.insert(
+ std::make_pair(inFaceValues, (long)(ioFaceIndicies.first.size())));
+
+ return theTupleEntry.first->second;
+}
+
+/**
+* @brief Processes a mesh entity and it childs.
+* In addition it processes a skeleton belonging to a mesh
+*
+* @param[in] inFbxNode Pointer to node element
+*
+* @return no return.
+*/
+void FbxDomWalker::ProcessMesh(FbxNode *inFbxNode)
+{
+ FbxMesh *theFbxMesh = inFbxNode->GetMesh();
+ if (theFbxMesh == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ // push mesh onto stack
+ m_Translator->PushModel(inFbxNode->GetName());
+ ProcessTransform(inFbxNode);
+
+ theFbxMesh = inFbxNode->GetMesh();
+
+ // GetVertexWeights produces a joint info list.
+ // theJointInfoList retrieves information about the per vertex weights,
+ // and the bone index list for each vertex.
+ // and a list of current bones for this mesh
+ TNodeSet theBoneSet;
+ TJointInfoList theJointInfoList;
+ TVertexWeigthList theVertexWeights;
+ GetVertexWeights(theFbxMesh, theVertexWeights, theJointInfoList, theBoneSet);
+
+ TFaceIndicies theFaceIndices;
+ TFaceMaterialIndices theFaceMaterialIndices;
+ bool canUseDirectMode = true; // if we have a direct mapping we can read data in faster way
+
+ // vertex data
+ int theFbxCtrlPointCount = theFbxMesh->GetControlPointsCount();
+ const FbxVector4 *theFbxCtrlPoints = theFbxMesh->GetControlPoints();
+ // index data
+ // int theFbxVertexIndexCount = theFbxMesh->GetPolygonVertexCount();
+ // int* theFbxIndexArray = theFbxMesh->GetPolygonVertices();
+ // normal data
+ const FbxGeometryElementNormal *theFbxNormals = theFbxMesh->GetElementNormal();
+ int theFbxNormalCount = 0;
+ FbxGeometryElement::EMappingMode theFbxNormalsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxNormals) {
+ theFbxNormalCount = theFbxNormals->GetDirectArray().GetCount();
+ theFbxNormalsMappingMode = theFbxNormals->GetMappingMode();
+ canUseDirectMode &=
+ (theFbxNormalsMappingMode == FbxGeometryElement::eByControlPoint) ? true : false;
+ }
+ // uv data
+ int theFbxUVsSetCount = theFbxMesh->GetElementUVCount(); // overall uv set count
+
+ const FbxGeometryElementUV *theFbxUVs = theFbxMesh->GetElementUV();
+ int theFbxUVsCount = 0;
+ FbxGeometryElement::EMappingMode theFbxUVsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxUVs) {
+ theFbxUVsCount = theFbxUVs->GetDirectArray().GetCount();
+ theFbxUVsMappingMode = theFbxUVs->GetMappingMode();
+ canUseDirectMode &=
+ (theFbxUVsMappingMode == FbxGeometryElement::eByControlPoint) ? true : false;
+ }
+ // uv data second set
+ const FbxGeometryElementUV *theFbxUV2s = theFbxMesh->GetElementUV(1);
+ int theFbxUV2sCount = 0;
+ FbxGeometryElement::EMappingMode theFbxUV2sMappingMode = FbxGeometryElement::eNone;
+ if (theFbxUV2s && theFbxUVsSetCount > 1) {
+ theFbxUV2sCount = theFbxUV2s->GetDirectArray().GetCount();
+ theFbxUV2sMappingMode = theFbxUV2s->GetMappingMode();
+ canUseDirectMode &=
+ (theFbxUV2sMappingMode == FbxGeometryElement::eByControlPoint) ? true : false;
+ }
+
+ // tangent data
+ FbxGeometryElementTangent *theFbxTangents = theFbxMesh->GetElementTangent();
+ int theFbxTangentsCount = 0;
+ FbxGeometryElement::EMappingMode theFbxTangentsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxTangents) {
+ theFbxTangentsCount = theFbxTangents->GetDirectArray().GetCount();
+ theFbxTangentsMappingMode = theFbxTangents->GetMappingMode();
+ canUseDirectMode &=
+ (theFbxTangentsMappingMode == FbxGeometryElement::eByControlPoint) ? true : false;
+ }
+ // binormal data
+ FbxGeometryElementBinormal *theFbxBinormals = theFbxMesh->GetElementBinormal();
+ int theFbxBinormalsCount = 0;
+ FbxGeometryElement::EMappingMode theFbxBinormalsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxBinormals) {
+ theFbxBinormalsCount = theFbxBinormals->GetDirectArray().GetCount();
+ theFbxBinormalsMappingMode = theFbxBinormals->GetMappingMode();
+ canUseDirectMode &=
+ (theFbxBinormalsMappingMode == FbxGeometryElement::eByControlPoint) ? true : false;
+ }
+ // material data
+ FbxGeometryElementMaterial *theFbxMaterials = theFbxMesh->GetElementMaterial();
+ int theFbxMaterialsCount = 0;
+ FbxGeometryElement::EMappingMode theFbxMaterialsMappingMode = FbxGeometryElement::eNone;
+ if (theFbxMaterials) {
+ theFbxMaterialsCount = theFbxMesh->GetElementMaterialCount();
+ theFbxMaterialsMappingMode = theFbxMaterials->GetMappingMode();
+ }
+
+ // check if we need to generate tangents and binormals
+ std::vector<SVector3> newTangents;
+ std::vector<SVector3> newBinormals;
+ if (!theFbxTangents && !theFbxBinormals) {
+ GenerateMeshTangents(theFbxMesh, newTangents, newBinormals);
+ }
+
+ // polygon data
+ int theFbxTriangleCount = theFbxMesh->GetPolygonCount();
+
+ SFaceMaterialInfo thePerFaceMaterialnfo;
+ thePerFaceMaterialnfo.m_StartFace = 0;
+ QueryMaterialInfo(theFbxMesh, &thePerFaceMaterialnfo);
+
+ TLongsList theMaterialFaceIndicies;
+ theMaterialFaceIndicies.reserve(theFbxTriangleCount);
+
+ // When we build a transform history we build everything into one matrix
+ // but the geometric transform is not inherited therefore
+ // we transform it on load
+ FbxAMatrix geomTransform = getGeometricTransform(inFbxNode);
+
+ // when we can go direct mode everything is easier
+ canUseDirectMode = false; // currently disabled
+ if (canUseDirectMode) {
+ QT3DS_ASSERT(!theFbxNormals
+ || theFbxNormalsMappingMode == FbxGeometryElement::eByControlPoint);
+ QT3DS_ASSERT(!theFbxUVs || theFbxUVsMappingMode == FbxGeometryElement::eByControlPoint);
+ QT3DS_ASSERT(!theFbxTangents
+ || theFbxTangentsMappingMode == FbxGeometryElement::eByControlPoint);
+ QT3DS_ASSERT(!theFbxBinormals
+ || theFbxBinormalsMappingMode == FbxGeometryElement::eByControlPoint);
+
+ for (int i = 0; i < theFbxCtrlPointCount; ++i) {
+ TVertexInfoTuple theFaceTupleValues;
+
+ ReadVertex(theFbxCtrlPoints, i, theFaceTupleValues.get<0>(), geomTransform);
+
+ if (theFbxNormals)
+ ReadNormal(theFbxNormals, i, theFaceTupleValues.get<1>());
+ if (theFbxUVs)
+ ReadTexCoord(theFbxUVs, i, theFaceTupleValues.get<2>());
+
+ if (theFbxTangents)
+ ReadTexTangent(theFbxTangents, i, theFaceTupleValues.get<3>());
+ else if (newTangents.size() > 0)
+ ReadTexTangent(newTangents, theFbxNormals, i, theFaceTupleValues.get<3>());
+
+ if (theFbxBinormals)
+ ReadTexBinormal(theFbxBinormals, i, theFaceTupleValues.get<4>());
+ else if (newBinormals.size() > 0)
+ ReadTexBinormal(newBinormals, theFbxNormals, i, theFaceTupleValues.get<4>());
+
+ long theFaceIndex = RetrieveFaceIndex(theFaceIndices, theFaceTupleValues);
+ theMaterialFaceIndicies.push_back(theFaceIndex);
+
+ if (theFbxMaterialsCount) {
+ SFaceMaterialInfo currentPerFaceMaterialnfo;
+ currentPerFaceMaterialnfo.m_StartFace = i / 3;
+ QueryMaterialInfo(theFbxMesh, &currentPerFaceMaterialnfo);
+
+ if (!(thePerFaceMaterialnfo == currentPerFaceMaterialnfo)) {
+ // add per face material info
+ thePerFaceMaterialnfo.m_FaceCount = i / 3 - thePerFaceMaterialnfo.m_StartFace;
+ QT3DS_ASSERT(i % 3 == 0);
+ theFaceMaterialIndices.push_back(thePerFaceMaterialnfo);
+
+ thePerFaceMaterialnfo = currentPerFaceMaterialnfo;
+ }
+ }
+ }
+ } else {
+ int theVertexID = 0;
+
+ for (int i = 0; i < theFbxTriangleCount; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ TVertexInfoTuple theFaceTupleValues;
+
+ int theFbxCtrlPointIndex = theFbxMesh->GetPolygonVertex(i, j);
+ QT3DS_ASSERT(theFbxMesh->GetPolygonSize(i) == 3);
+ QT3DS_ASSERT(theFbxCtrlPointIndex < theFbxCtrlPointCount
+ && theFbxCtrlPointIndex != -1);
+
+ ReadVertex(theFbxCtrlPoints, theFbxCtrlPointIndex, theFaceTupleValues.get<0>(),
+ geomTransform);
+
+ if (theFbxNormals) {
+ ReadNormal(theFbxNormals,
+ (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<1>());
+ }
+ if (theFbxUVs) {
+ ReadTexCoord(theFbxUVs,
+ (theFbxUVsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<2>());
+ }
+ if (theFbxTangents) {
+ ReadTexTangent(theFbxTangents, (theFbxTangentsMappingMode
+ == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<3>());
+ } else if (newTangents.size() > 0) {
+ // we use the mapping as the normals
+ ReadTexTangent(
+ newTangents, theFbxNormals,
+ (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<3>());
+ }
+ if (theFbxBinormals) {
+ ReadTexBinormal(theFbxBinormals, (theFbxBinormalsMappingMode
+ == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<4>());
+ } else if (newBinormals.size() > 0) {
+ ReadTexBinormal(
+ newBinormals, theFbxNormals,
+ (theFbxNormalsMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<4>());
+ }
+
+ if (theVertexWeights.size() > 0) {
+ ReadWeight(theVertexWeights[theFbxCtrlPointIndex], theFbxCtrlPointIndex,
+ theFaceTupleValues.get<5>());
+ ReadBoneIndex(theVertexWeights[theFbxCtrlPointIndex], theFbxCtrlPointIndex,
+ theFaceTupleValues.get<6>(), theJointInfoList);
+ }
+
+ if (theFbxUV2s) {
+ ReadTexCoord(theFbxUV2s,
+ (theFbxUV2sMappingMode == FbxGeometryElement::eByPolygonVertex)
+ ? theVertexID
+ : theFbxCtrlPointIndex,
+ theFaceTupleValues.get<7>());
+ }
+
+ long theFaceIndex = RetrieveFaceIndex(theFaceIndices, theFaceTupleValues);
+ theMaterialFaceIndicies.push_back(theFaceIndex);
+
+ ++theVertexID;
+ }
+
+ if (theFbxMaterialsCount) {
+ SFaceMaterialInfo currentPerFaceMaterialnfo;
+ currentPerFaceMaterialnfo.m_StartFace = i;
+ QueryMaterialInfo(theFbxMesh, &currentPerFaceMaterialnfo);
+
+ if (!(thePerFaceMaterialnfo == currentPerFaceMaterialnfo)) {
+ // the material changed add per face material info
+ thePerFaceMaterialnfo.m_FaceCount = i - thePerFaceMaterialnfo.m_StartFace;
+ theFaceMaterialIndices.push_back(thePerFaceMaterialnfo);
+
+ thePerFaceMaterialnfo = currentPerFaceMaterialnfo;
+ }
+ }
+ }
+ }
+
+ TFloatsList theVertices;
+ TFloatsList theNormals;
+ TFloatsList theTexCoords;
+ TFloatsList theTexTangents;
+ TFloatsList theTexBinormals;
+ TFloatsList theWeights;
+ TFloatsList theBoneIndex;
+ TFloatsList theTexCoords2;
+
+ // Prepare arrays for population
+ long theNumberOfUniqueFacePoints = (long)theFaceIndices.first.size();
+ if (theNumberOfUniqueFacePoints == 0)
+ return;
+
+ theVertices.resize(theNumberOfUniqueFacePoints * 3);
+ if (theFbxNormals) {
+ theNormals.resize(theNumberOfUniqueFacePoints * 3);
+ }
+ if (theFbxUVs) {
+ theTexCoords.resize(theNumberOfUniqueFacePoints * 2);
+ }
+ if (theFbxTangents || newTangents.size() > 0) {
+ theTexTangents.resize(theNumberOfUniqueFacePoints * 3);
+ }
+ if (theFbxBinormals || newBinormals.size() > 0) {
+ theTexBinormals.resize(theNumberOfUniqueFacePoints * 3);
+ }
+ if (theVertexWeights.size() > 0) {
+ theWeights.resize(theNumberOfUniqueFacePoints * 4);
+ theBoneIndex.resize(theNumberOfUniqueFacePoints * 4);
+ }
+ if (theFbxUV2s) {
+ theTexCoords2.resize(theNumberOfUniqueFacePoints * 2);
+ }
+
+ // Populate vertex, normal and texcoord arrays so that face indicies can reference from them
+ TFaceIndicies::first_type::const_iterator theIter = theFaceIndices.first.begin();
+ TFaceIndicies::first_type::const_iterator theEnd = theFaceIndices.first.end();
+ for (; theIter != theEnd; ++theIter) {
+ long theFaceIndex = theIter->second;
+ const TVertexInfoTuple &thePointTuple = theIter->first;
+
+ WriteFloat3(theVertices, theFaceIndex, thePointTuple.get<0>());
+
+ if (theFbxNormals)
+ WriteFloat3(theNormals, theFaceIndex, thePointTuple.get<1>());
+ if (theFbxUVs)
+ WriteFloat2(theTexCoords, theFaceIndex, thePointTuple.get<2>());
+ if (theFbxTangents || newTangents.size() > 0)
+ WriteFloat3(theTexTangents, theFaceIndex, thePointTuple.get<3>());
+ if (theFbxBinormals || newBinormals.size() > 0)
+ WriteFloat3(theTexBinormals, theFaceIndex, thePointTuple.get<4>());
+ if (theVertexWeights.size() > 0) {
+ WriteFloat4(theWeights, theFaceIndex, thePointTuple.get<5>());
+ WriteFloat4(theBoneIndex, theFaceIndex, thePointTuple.get<6>());
+ }
+ if (theFbxUV2s)
+ WriteFloat2(theTexCoords2, theFaceIndex, thePointTuple.get<7>());
+ }
+
+ m_Translator->SetGeometry(theVertices, theNormals, theTexCoords, theTexCoords2, theTexTangents,
+ theTexBinormals, theWeights, theBoneIndex, theMaterialFaceIndicies);
+
+ // Read material belonging to this mesh
+ // At this point theFaceMaterialIndices contains the information which material is used for each
+ // face
+ if (theFbxMaterialsCount) {
+ // add final per face material
+ thePerFaceMaterialnfo.m_FaceCount = theFbxTriangleCount - thePerFaceMaterialnfo.m_StartFace;
+ theFaceMaterialIndices.push_back(thePerFaceMaterialnfo);
+
+ for (size_t i = 0; i < theFaceMaterialIndices.size(); i++) {
+ SFaceMaterialInfo thePerFaceMaterialnfo = theFaceMaterialIndices.at(i);
+
+ for (size_t elCount = 0; elCount < thePerFaceMaterialnfo.m_MatElementsIDs.size();
+ elCount++) {
+ FbxGeometryElementMaterial *theMaterialElement = theFbxMesh->GetElementMaterial(
+ thePerFaceMaterialnfo.m_MatElementsIDs.at(elCount));
+ FbxSurfaceMaterial *theMaterial = inFbxNode->GetMaterial(
+ theMaterialElement->GetIndexArray().GetAt(thePerFaceMaterialnfo.m_StartFace));
+ if (theMaterial)
+ ReadMaterial(theMaterial, thePerFaceMaterialnfo.m_StartFace,
+ thePerFaceMaterialnfo.m_FaceCount);
+ }
+ }
+ } else if (theFbxNormals) {
+ // if there is no material defined try to create a default one
+ // add final per face material
+ thePerFaceMaterialnfo.m_FaceCount = theFbxTriangleCount - thePerFaceMaterialnfo.m_StartFace;
+ theFaceMaterialIndices.push_back(thePerFaceMaterialnfo);
+
+ ReadDefaultMaterial(inFbxNode, thePerFaceMaterialnfo.m_StartFace,
+ thePerFaceMaterialnfo.m_FaceCount);
+ }
+
+ // stream out joint info if any
+ if (theJointInfoList.size()) {
+ TJointInfoList::iterator theIter;
+
+ for (theIter = theJointInfoList.begin(); theIter != theJointInfoList.end(); theIter++) {
+ m_Translator->SetJointNode(*theIter);
+ }
+ }
+
+ // Here we process a skeleton hierarchy which belongs to a mesh.
+ // Note this means we actually copy skeleton instance into a mesh
+ // We do this that at render time we get the relationship mesh <-> skeleton
+ if (theBoneSet.size()) {
+ // This should be equal
+ QT3DS_ASSERT(theBoneSet.size() == theJointInfoList.size());
+
+ // Set the bones for this mesh.
+ // In ProcessSkeletonNode we only process bones which belong to the current set
+ TNodeSet skeletonSet;
+ FilterNodeHierarchy(SNodeSetFilter(theBoneSet), skeletonSet);
+
+ if (skeletonSet.size()) {
+ // start with parent of root bone otherwise we miss our inserted animation node
+ long skeletonRoot = ProcessSkeletonNode(m_FbxScene->GetRootNode(), skeletonSet, true);
+ m_Translator->SetModelSkeletonRoot(skeletonRoot);
+ }
+ }
+
+ ProcessNodeChildren(inFbxNode);
+ m_Translator->PopModel();
+}
+
+/**
+* @brief Read psoition value for a vertex.
+* This version convertes the vertex with the local geometric transform
+*
+* @param[in] inFbxCtrlPoints Pointer to normal element
+* @param[in] inFbxCtrlPointIndex Unused
+* @param[out] outValue Retrieves the position for this vertex.
+* @param[out] geometricTransformation Local transform matrix to convert with.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadVertex(const FbxVector4 *inFbxCtrlPoints, int inFbxCtrlPointIndex,
+ float *outValue, FbxAMatrix &geometricTransformation)
+{
+ const FbxVector4 &inCtrlPoint = inFbxCtrlPoints[inFbxCtrlPointIndex];
+ FbxVector4 transformedCtrlPoint = geometricTransformation.MultT(inCtrlPoint);
+
+ outValue[0] = (float)transformedCtrlPoint[0];
+ outValue[1] = (float)transformedCtrlPoint[1];
+ outValue[2] = (float)transformedCtrlPoint[2];
+}
+
+/**
+* @brief Read psoition value for a vertex
+* This version read the position from the inFbxWeights array.
+* This position is in bone space
+*
+* @param[in] inFbxWeights Pointer to normal element
+* @param[in] inFbxCtrlPointIndex Unused
+* @param[out] outValue Retrieves the position for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadVertex(const TPerVertexWeightInfo &inFbxWeights,
+ int /* inFbxCtrlPointIndex */, float *outValue)
+{
+ outValue[0] = inFbxWeights[0].m_Position[0];
+ outValue[1] = inFbxWeights[0].m_Position[1];
+ outValue[2] = inFbxWeights[0].m_Position[2];
+}
+
+/**
+* @brief Read normal for a vertex
+*
+* @param[in] inFbxNormals Pointer to normal element
+* @param[in] inFbxIndex Index to read from (direct or indirect)
+* @param[out] outValue Retrieves the normal for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadNormal(const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex,
+ float *outValue)
+{
+ int theFbxNormalIndex = 0;
+ switch (inFbxNormals->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxNormalIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxNormalIndex = inFbxNormals->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ FbxVector4 theNormal = inFbxNormals->GetDirectArray().GetAt(theFbxNormalIndex);
+
+ outValue[0] = (float)theNormal[0];
+ outValue[1] = (float)theNormal[1];
+ outValue[2] = (float)theNormal[2];
+}
+
+/**
+* @brief Read texture coords for a vertex
+*
+* @param[in] inFbxUVs Pointer to UV element
+* @param[in] inFbxIndex Index to read from (direct or indirect)
+* @param[out] outValue Retrieves the texture coords for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadTexCoord(const FbxGeometryElementUV *inFbxUVs, int inFbxIndex,
+ float *outValue)
+{
+ int theFbxUVIndex = 0;
+ switch (inFbxUVs->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxUVIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxUVIndex = inFbxUVs->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ const FbxVector2 uv(inFbxUVs->GetDirectArray().GetAt(theFbxUVIndex));
+ outValue[0] = (float) uv[0];
+ outValue[1] = (float) uv[1];
+}
+
+/**
+* @brief Read tangents for a vertex
+*
+* @param[in] inFbxTangents Pointer to tangents element
+* @param[in] inFbxIndex Index to read from (direct or indirect)
+* @param[out] outValue Retrieves the tangents for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadTexTangent(const FbxGeometryElementTangent *inFbxTangents, int inFbxIndex,
+ float *outValue)
+{
+ int theFbxTangentIndex = 0;
+ switch (inFbxTangents->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxTangentIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxTangentIndex = inFbxTangents->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ FbxVector4 theTexTangent = inFbxTangents->GetDirectArray().GetAt(theFbxTangentIndex);
+
+ outValue[0] = (float)theTexTangent[0];
+ outValue[1] = (float)theTexTangent[1];
+ outValue[2] = (float)theTexTangent[2];
+}
+
+/**
+* @brief Read tangents for a vertex
+*
+* @param[in] inTangentPoints Pointer to tangents array
+* @param[in] inFbxIndex Index to read from (direct or indirect)
+* @param[out] outValue Retrieves the tangents for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadTexTangent(std::vector<SVector3> &inTangentPoints,
+ const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex,
+ float *outValue)
+{
+ int theFbxTangentIndex = 0;
+ switch (inFbxNormals->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxTangentIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxTangentIndex = inFbxNormals->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ outValue[0] = inTangentPoints[theFbxTangentIndex][0];
+ outValue[1] = inTangentPoints[theFbxTangentIndex][1];
+ outValue[2] = inTangentPoints[theFbxTangentIndex][2];
+}
+
+/**
+* @brief Read binormals for a vertex
+*
+* @param[in] inFbxBinormals Pointer to binormal element
+* @param[in] inFbxIndex Index to read from (direct or indirect)
+* @param[out] outValue Retrieves the binormal for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadTexBinormal(const FbxGeometryElementBinormal *inFbxBinormals, int inFbxIndex,
+ float *outValue)
+{
+ int theFbxBinormalIndex = 0;
+ switch (inFbxBinormals->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxBinormalIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxBinormalIndex = inFbxBinormals->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ FbxVector4 theTexBinormal = inFbxBinormals->GetDirectArray().GetAt(theFbxBinormalIndex);
+
+ outValue[0] = (float)theTexBinormal[0];
+ outValue[1] = (float)theTexBinormal[1];
+ outValue[2] = (float)theTexBinormal[2];
+}
+
+/**
+* @brief Read binormals for a vertex
+*
+* @param[in] inBinormalPoints Pointer to binormal array
+* @param[in] inFbxIndex Index to read from (direct or indirect)
+* @param[out] outValue Retrieves the binormal for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadTexBinormal(std::vector<SVector3> &inBinormalPoints,
+ const FbxGeometryElementNormal *inFbxNormals, int inFbxIndex,
+ float *outValue)
+{
+ int theFbxBinormalIndex = 0;
+ switch (inFbxNormals->GetReferenceMode()) {
+ case FbxGeometryElement::eDirect:
+ theFbxBinormalIndex = inFbxIndex;
+ break;
+ case FbxGeometryElement::eIndexToDirect:
+ theFbxBinormalIndex = inFbxNormals->GetIndexArray().GetAt(inFbxIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ outValue[0] = inBinormalPoints[theFbxBinormalIndex][0];
+ outValue[1] = inBinormalPoints[theFbxBinormalIndex][1];
+ outValue[2] = inBinormalPoints[theFbxBinormalIndex][2];
+}
+
+/**
+* @brief Read weights for a vertex
+*
+* @param[in] inFbxWeights Pointer to per vertex weights, bone indices array
+* @param[in] inFbxIndex Unused here
+* @param[out] outValue Retrieves the bone indices for this vertex.
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadWeight(const FbxDomWalker::TPerVertexWeightInfo &inFbxWeights,
+ int /* inFbxIndex */, float *outValue)
+{
+ // clear since we might not use all values
+ outValue[0] = outValue[1] = outValue[2] = outValue[3] = 0;
+ for (unsigned long i = 0; i < inFbxWeights.size() && i < 4; i++) {
+ outValue[i] = inFbxWeights[i].m_Weight;
+ }
+}
+
+/**
+* @brief Read bone indices for a vertex
+*
+* @param[in] inFbxWeights Pointer to per vertex weights, bone indices array
+* @param[in] inFbxIndex Unused here
+* @param[out] outValue Retrieves the bone indices for this vertex.
+* @param[in] inAbsoluteJoints Absolute joint ID's
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadBoneIndex(const FbxDomWalker::TPerVertexWeightInfo &inFbxWeights,
+ int /* inFbxIndex */, float *outValue,
+ const TJointInfoList &inAbsoluteJoints)
+{
+ // clear since we might not use all values
+ outValue[0] = outValue[1] = outValue[2] = outValue[3] = 0;
+
+ for (size_t i = 0; i < inFbxWeights.size() && i < 4; i++) {
+ size_t relativeIndex = 0;
+ // At render time we build a bone array which start always at zero index for each mesh.
+ // Therefore we need to remap the absolute bone index to a relative bone index
+ for (size_t relJointIdx = 0, relJointEnd = inAbsoluteJoints.size();
+ relJointIdx < relJointEnd; ++relJointIdx) {
+ if (inAbsoluteJoints[relJointIdx].m_JointID == inFbxWeights[i].m_JointID) {
+ relativeIndex = relJointIdx;
+ break;
+ }
+ }
+ outValue[i] = (float)relativeIndex;
+ }
+}
+
+/**
+* @brief Process textures parameters
+*
+* @param[in] inTexture Pointer to exture entry
+* @param[out] outTextureParameters Contains information about texture parameter
+*
+* @return no return.
+*/
+void FbxDomWalker::ProcessTextureParameter(FbxTexture *inTexture,
+ STextureParameters &outTextureParameters)
+{
+ if (inTexture) {
+ outTextureParameters.m_offsetU.m_Value = (float)inTexture->GetTranslationU();
+ outTextureParameters.m_offsetV.m_Value = (float)inTexture->GetTranslationV();
+ if (inTexture->GetWrapModeU() == FbxTexture::eRepeat)
+ outTextureParameters.m_wrapU.m_Value = 1;
+ if (inTexture->GetWrapModeV() == FbxTexture::eRepeat)
+ outTextureParameters.m_wrapV.m_Value = 1;
+ }
+}
+
+/**
+* @brief Process textures of the import file
+*
+* @param[in] inMaterial Pointer to material entry
+* @param[in] fbxMatType Name of the material type like ambient, diffuse,...
+* @param[in] sgMapType Convered material type for ambient, diffuse,...
+* @param[out] outColor Contains information if material is color or texture
+*
+* @return no return.
+*/
+void FbxDomWalker::ProcessTextures(const FbxSurfaceMaterial *inMaterial, const char *fbxMatType,
+ ETextureMapType sgMapType, SColorOrTexture &outColor)
+{
+ FbxProperty theProperty = inMaterial->FindProperty(fbxMatType);
+
+ if (theProperty.IsValid()) {
+ STextureParameters theTextureParameters;
+ int textureCount = theProperty.GetSrcObjectCount<FbxTexture>();
+
+ if (textureCount)
+ outColor.SetTexture();
+
+ for (int i = 0; i < textureCount; ++i) {
+ FbxLayeredTexture *theLayeredTexture = theProperty.GetSrcObject<FbxLayeredTexture>(i);
+ // do we have layered textures for this property?
+ if (theLayeredTexture) {
+ int layeredTextureCount = theLayeredTexture->GetSrcObjectCount<FbxLayeredTexture>();
+ // texture blending
+ for (int j = 0; j < layeredTextureCount; ++j) {
+ FbxTexture *theTexture = theLayeredTexture->GetSrcObject<FbxTexture>(j);
+ if (theTexture) {
+ ProcessTextureParameter(theTexture, theTextureParameters);
+ FbxFileTexture *theFileTexture = FbxCast<FbxFileTexture>(theLayeredTexture);
+ m_Translator->PushTexture(theFileTexture->GetRelativeFileName(),
+ theFileTexture->GetFileName(), sgMapType);
+ m_Translator->SetTexture(sgMapType, theTextureParameters);
+ m_Translator->PopTexture();
+ }
+ }
+ } else {
+ FbxTexture *theTexture = theProperty.GetSrcObject<FbxTexture>(i);
+ if (theTexture) {
+ ProcessTextureParameter(theTexture, theTextureParameters);
+ FbxFileTexture *theFileTexture = FbxCast<FbxFileTexture>(theTexture);
+ m_Translator->PushTexture(theFileTexture->GetRelativeFileName(),
+ theFileTexture->GetFileName(), sgMapType);
+ m_Translator->SetTexture(sgMapType, theTextureParameters);
+ m_Translator->PopTexture();
+ }
+ }
+ }
+ }
+}
+
+/**
+* @brief Query material information for a certain face
+*
+* @param[in] fbxMesh Pointer to mesh entry
+* @param[in/out] info info contains the face to query.
+* At return info contains the material ID for this
+*face
+*
+* @return no return.
+*/
+void FbxDomWalker::QueryMaterialInfo(FbxMesh *fbxMesh, SFaceMaterialInfo *info)
+{
+ for (int l = 0; l < fbxMesh->GetElementMaterialCount(); l++) {
+ FbxGeometryElementMaterial *theMaterialElement = fbxMesh->GetElementMaterial(l);
+ FbxSurfaceMaterial *theMaterial = NULL;
+ int theMatId = -1;
+ theMaterial = fbxMesh->GetNode()->GetMaterial(
+ theMaterialElement->GetIndexArray().GetAt(info->m_StartFace));
+ theMatId = theMaterialElement->GetIndexArray().GetAt(info->m_StartFace);
+
+ if (theMatId >= 0) {
+ info->m_MatElementsIDs.push_back(l);
+ info->m_MatIDs.push_back(theMatId);
+ }
+ }
+}
+
+/**
+* @brief Read material and attach to mesh
+*
+* @param[in] inMaterial Pointer to material entry
+* @param[in] startFace The start face index for this material
+* @param[in] faceCount The face count for this material
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadMaterial(const FbxSurfaceMaterial *inMaterial, const int startFace,
+ const int faceCount)
+{
+ SMaterialParameters theNewMaterial;
+ FbxDouble3 fbxColor;
+ float attenuationFactor = 0;
+
+ if (!inMaterial)
+ return;
+
+ QT3DS_ASSERT(inMaterial->GetClassId().Is(FbxSurfaceMaterial::ClassId)
+ || inMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)
+ || inMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId));
+
+ // init some base values
+ theNewMaterial.m_Ambient.SetColor(0, 0, 0, 1);
+ theNewMaterial.m_Diffuse.SetColor(1, 1, 1, 1);
+
+ if (inMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) {
+ // lambert is base for all materials
+ // for phong we override the type and read the additional values later below
+ FbxSurfaceLambert *lambertMaterial = (FbxSurfaceLambert *)inMaterial;
+ theNewMaterial.m_TechniqueType = EMatCommonProfileTechnique_Lambert;
+
+ fbxColor = lambertMaterial->Ambient;
+ attenuationFactor = (float)lambertMaterial->AmbientFactor;
+ theNewMaterial.m_Ambient.SetColor((float)fbxColor.mData[0] * attenuationFactor,
+ (float)fbxColor.mData[1] * attenuationFactor,
+ (float)fbxColor.mData[2] * attenuationFactor, 1);
+ fbxColor = lambertMaterial->Diffuse;
+ attenuationFactor = (float)lambertMaterial->DiffuseFactor;
+ theNewMaterial.m_Diffuse.SetColor((float)fbxColor.mData[0] * attenuationFactor,
+ (float)fbxColor.mData[1] * attenuationFactor,
+ (float)fbxColor.mData[2] * attenuationFactor, 1);
+ fbxColor = lambertMaterial->Emissive;
+ attenuationFactor = (float)lambertMaterial->EmissiveFactor;
+ theNewMaterial.m_Emission.SetColor((float)fbxColor.mData[0] * attenuationFactor,
+ (float)fbxColor.mData[1] * attenuationFactor,
+ (float)fbxColor.mData[2] * attenuationFactor, 1);
+ fbxColor = lambertMaterial->TransparentColor;
+ theNewMaterial.m_Transparent.SetColor((float)fbxColor.mData[0], (float)fbxColor.mData[1],
+ (float)fbxColor.mData[2], 1);
+ theNewMaterial.m_Transparency.SetValue((float)lambertMaterial->TransparencyFactor);
+ }
+
+ if (inMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) {
+ FbxSurfacePhong *phongMaterial = (FbxSurfacePhong *)inMaterial;
+ theNewMaterial.m_TechniqueType = EMatCommonProfileTechnique_Phong;
+
+ fbxColor = phongMaterial->Specular;
+ attenuationFactor = (float)phongMaterial->SpecularFactor;
+ theNewMaterial.m_Specular.SetColor((float)fbxColor.mData[0] * attenuationFactor,
+ (float)fbxColor.mData[1] * attenuationFactor,
+ (float)fbxColor.mData[2] * attenuationFactor, 1);
+ fbxColor = phongMaterial->Reflection;
+ theNewMaterial.m_Reflective.SetColor((float)fbxColor.mData[0], (float)fbxColor.mData[1],
+ (float)fbxColor.mData[2], 1);
+ theNewMaterial.m_Reflectivity.SetValue((float)phongMaterial->ReflectionFactor);
+ theNewMaterial.m_Shininess.SetValue((float)phongMaterial->Shininess);
+ }
+
+ m_Translator->PushMaterial(inMaterial->GetName());
+
+ // handle textures if any
+ ProcessTextures(inMaterial, FbxSurfaceMaterial::sAmbient, ETextureMapTypeDiffuse,
+ theNewMaterial.m_Ambient);
+ ProcessTextures(inMaterial, FbxSurfaceMaterial::sDiffuse, ETextureMapTypeDiffuse,
+ theNewMaterial.m_Diffuse);
+ ProcessTextures(inMaterial, FbxSurfaceMaterial::sEmissive, ETextureMapTypeEmissive,
+ theNewMaterial.m_Emission);
+ ProcessTextures(inMaterial, FbxSurfaceMaterial::sTransparentColor, ETextureMapTypeOpacity,
+ theNewMaterial.m_Transparent);
+ ProcessTextures(inMaterial, FbxSurfaceMaterial::sSpecular, ETextureMapTypeSpecular,
+ theNewMaterial.m_Specular);
+
+ m_Translator->SetMaterial(theNewMaterial);
+ m_Translator->PopMaterial(startFace, faceCount);
+}
+
+/**
+* @brief Add a default material in the import file does not specifiy one
+*
+* @param[in] inFbxNode Node to attach the material
+* @param[in] startFace The start face index for this material
+* @param[in] faceCount The face count for this material
+*
+* @return no return.
+*/
+void FbxDomWalker::ReadDefaultMaterial(const FbxNode *inFbxNode, const int startFace,
+ const int faceCount)
+{
+ SMaterialParameters theNewMaterial;
+ theNewMaterial.m_Diffuse.SetColor(0.8f, 0.8f, 0.8f, 1.0f);
+ theNewMaterial.m_Transparency.SetValue(0.0); // opaque
+
+ FbxProperty theProperty = inFbxNode->GetFirstProperty();
+
+ // iterate throug the porperty list
+ while (theProperty.IsValid()) {
+ FbxDataType theFbxType = theProperty.GetPropertyDataType();
+
+ if (FbxColor3DT == theFbxType) {
+ FbxDouble3 theDouble3 = theProperty.Get<FbxDouble3>();
+
+ theNewMaterial.m_Diffuse.SetColor((float)theDouble3[0], (float)theDouble3[1],
+ (float)theDouble3[2], 1);
+ break;
+ } else if (FbxColor4DT == theFbxType) {
+ FbxDouble4 theDouble4 = theProperty.Get<FbxDouble4>();
+
+ theNewMaterial.m_Diffuse.SetColor((float)theDouble4[0], (float)theDouble4[1],
+ (float)theDouble4[2], (float)theDouble4[3]);
+ break;
+ }
+
+ theProperty = inFbxNode->GetNextProperty(theProperty);
+ }
+
+ std::string theMatName = inFbxNode->GetName();
+ theMatName += "_Diffuse_Default";
+
+ m_Translator->PushMaterial(theMatName.c_str());
+
+ m_Translator->SetMaterial(theNewMaterial);
+ m_Translator->PopMaterial(startFace, faceCount);
+}
+
+/**
+* @brief Searches for the animation track indices of a node
+*
+* @param[in] inNode Node to find the animation tracks
+* @param[out] outIndicies List of animation track indices for this node
+*
+* @return no return.
+*/
+void FbxDomWalker::GetIndicesFromNode(const FbxNode *inNode, TLongsList &outIndicies)
+{
+ auto theResult = m_NodeToIndicies.equal_range(inNode);
+
+ outIndicies.clear();
+
+ for (TNodeToIndicesMap::const_iterator theIter = theResult.first; theIter != theResult.second;
+ ++theIter) {
+ outIndicies.push_back(theIter->second);
+ }
+}
+
+/**
+* @brief Apply animation tracks if node is animated
+*
+* @param[in] inNode Node to animate
+*
+* @return true if animated.
+*/
+bool FbxDomWalker::ApplyAnimation(const FbxNode *inNode)
+{
+ TLongsList theAnimationTrackIndicies;
+ GetIndicesFromNode(inNode, theAnimationTrackIndicies);
+ bool theAnimated = false;
+
+ for (TLongsList::const_iterator theIter = theAnimationTrackIndicies.begin();
+ theIter != theAnimationTrackIndicies.end(); ++theIter) {
+ theAnimated = true;
+ m_Translator->ApplyAnimationTrack(*theIter);
+ }
+
+ return theAnimated;
+}
+
+/**
+* @brief Check if the Fbx node is animated
+*
+* @param[in] inNode Node to search for
+*
+* @return true if animated.
+*/
+bool FbxDomWalker::IsAnimated(const FbxNode *inNode)
+{
+ bool isAnimated = false;
+ TNodeIsAnimatedMap::iterator theIter;
+
+ theIter = m_NodeIsAnimatedMap.find(inNode);
+
+ if (theIter != m_NodeIsAnimatedMap.end())
+ isAnimated = true;
+
+ return isAnimated;
+}
+
+/**
+* @brief Check if to floats are alomst equal.
+* We might need to figure a good epsilon
+*
+* @param[in] lhs Left hand float
+* @param[in] rhs Right hand float
+*
+* @return true if almost equal.
+*/
+inline bool floatAlmostEquals(float lhs, float rhs)
+{
+ return fabs(lhs - rhs) < .01f;
+}
+
+/**
+* @brief Check all attached curves of the node if they contains actual animation.
+*
+* @param[in] inAnimCurveNode Pointer to animation curve node
+*
+* @return true or false.
+*/
+bool FbxDomWalker::CurveNodeIsAnimated(FbxAnimCurveNode *inAnimCurveNode)
+{
+ bool hasValidAnimation = false;
+
+ for (unsigned int i = 0; i < inAnimCurveNode->GetChannelsCount() && !hasValidAnimation; i++) {
+ FbxAnimCurve *theAnimCurve = inAnimCurveNode->GetCurve(i);
+
+ if (theAnimCurve && theAnimCurve->KeyGetCount()) {
+ int theKeyCount = theAnimCurve->KeyGetCount();
+ // get start value
+ FbxAnimCurveKey theKey = theAnimCurve->KeyGet(0);
+ float lastValue = theKey.GetValue();
+
+ // Run through all keyframes, compare key values per keyframe.
+ for (int i = 1; i < theKeyCount; i++) {
+ theKey = theAnimCurve->KeyGet(i);
+ float curValue = theKey.GetValue();
+ if (!floatAlmostEquals(lastValue, curValue)) {
+ hasValidAnimation = true;
+ break;
+ }
+ lastValue = curValue;
+ }
+ }
+ }
+
+ return hasValidAnimation;
+}
+
+/**
+* @brief Filter the key entries of a single animation curve. This creates a flat animation curve
+*
+* @param[in] inAnimCurve Pointer to animation curve
+* @param[in/out] outKeyIndexList This vector contains the filtered indices with different
+* keys
+*
+* @return no return.
+*/
+void FbxDomWalker::FilterAnimCurve(FbxAnimCurve *inAnimCurve, std::vector<int> &outKeyIndexList)
+{
+ if (inAnimCurve && inAnimCurve->KeyGetCount()) {
+ int theKeyCount = inAnimCurve->KeyGetCount();
+ // get start value
+ FbxAnimCurveKey theKey = inAnimCurve->KeyGet(0);
+ float value = theKey.GetValue();
+
+ outKeyIndexList.push_back(0);
+
+ // Run through all keyframes, compare key values per keyframe.
+ for (int i = 1; i < theKeyCount - 1; i++) {
+ theKey = inAnimCurve->KeyGet(i);
+ float curValue = theKey.GetValue();
+ if (!floatAlmostEquals(value, curValue)) {
+ outKeyIndexList.push_back(i);
+ // this is our new value which we compare against
+ value = curValue;
+ }
+ }
+
+ // push last entry to the list
+ outKeyIndexList.push_back(theKeyCount - 1);
+ }
+}
+
+/**
+* @brief Write out a single keyframe which we use internaly
+*
+* @param[in] FbxAnimCurveKey Pointer to a curve key entry
+* @param[in] transformType Name of the transform type (R, S, T)
+* @param[in] channelName Name of the channel type (X, Y, Z)
+* @param[in] inTranslator Pointer to our scene graph translator
+*
+* @return no return.
+*/
+inline void WriteKeyframe(const FbxAnimCurveKey &inKey, const char *transformType,
+ const char *channelName, UICIMP::ISceneGraphTranslation *inTranslator)
+{
+ // Create a key
+ SKeyframeParameters theKeyframeInfo((float)inKey.GetTime().GetSecondDouble(), inKey.GetValue(),
+ 0, 0, 0, 0);
+
+ // Set information about the key
+ inTranslator->CacheAnimationKey(transformType, channelName, theKeyframeInfo);
+}
+
+/**
+* @brief Produce keyframes for an animation curve
+*
+* @param[in] FbxAnimCurveKey Pointer to a curve key entry
+* @param[in] transformType Name of the transform type (R, S, T)
+* @param[in] channelName Name of the channel type (X, Y, Z)
+*
+* @return no return.
+*/
+void FbxDomWalker::ProcessAnimCurve(FbxAnimCurve *inAnimCurve, const char *transformType,
+ const char *channelName)
+{
+ if (inAnimCurve && inAnimCurve->KeyGetCount()) {
+ int theKeyCount = inAnimCurve->KeyGetCount();
+
+ // Run through all keyframes, writing time and value.
+ for (int i = 0; i < theKeyCount; i++) {
+ FbxAnimCurveKey theKey = inAnimCurve->KeyGet(i);
+ WriteKeyframe(theKey, transformType, channelName, m_Translator);
+ }
+ }
+}
+
+/**
+* @brief Produce animation information regarding a node
+*
+* @param[in] inNode Pointer to a Fbx node which contains animation
+* @param[in] inAnimLayer Pointer to a Fbx animation layer
+*
+* @return no return.
+*/
+void FbxDomWalker::ProcessAnimLayer(FbxNode *inNode, FbxAnimLayer *inAnimLayer)
+{
+ if (inNode && inAnimLayer) {
+ bool isAnimated = false;
+ // get animation curve nodes
+ FbxAnimCurveNode *theTranslateCurveNode = inNode->LclTranslation.GetCurveNode(inAnimLayer);
+ FbxAnimCurveNode *theRotateCurveNode = inNode->LclRotation.GetCurveNode(inAnimLayer);
+ FbxAnimCurveNode *theScaleCurveNode = inNode->LclScaling.GetCurveNode(inAnimLayer);
+ // color animation
+ FbxAnimCurve *redAnimCurve = NULL;
+ FbxAnimCurve *greenAnimCurve = NULL;
+ FbxAnimCurve *blueAnimCurve = NULL;
+
+ FbxNodeAttribute *nodeAttribute = inNode->GetNodeAttribute();
+ if (nodeAttribute) {
+ redAnimCurve = nodeAttribute->Color.GetCurve(inAnimLayer, FBXSDK_CURVENODE_COLOR_RED);
+ greenAnimCurve =
+ nodeAttribute->Color.GetCurve(inAnimLayer, FBXSDK_CURVENODE_COLOR_GREEN);
+ blueAnimCurve = nodeAttribute->Color.GetCurve(inAnimLayer, FBXSDK_CURVENODE_COLOR_BLUE);
+ }
+
+ if (theTranslateCurveNode && CurveNodeIsAnimated(theTranslateCurveNode)) {
+ for (unsigned int i = 0; i < theTranslateCurveNode->GetChannelsCount(); i++) {
+ isAnimated = true;
+
+ // For each animated sub property, create a track
+ m_NodeToIndicies.insert(std::make_pair(inNode, m_AnimationTrackCount++));
+ m_Translator->CacheAnimationTrack();
+
+ m_Translator->SetAnimationTrack(FBXSDK_CURVENODE_TRANSLATION,
+ theTranslateCurveNode->GetChannelName(i));
+
+ ProcessAnimCurve(theTranslateCurveNode->GetCurve(i), FBXSDK_CURVENODE_TRANSLATION,
+ theTranslateCurveNode->GetChannelName(i));
+ }
+ }
+
+ if (theRotateCurveNode && CurveNodeIsAnimated(theRotateCurveNode)) {
+ for (unsigned int i = 0; i < theRotateCurveNode->GetChannelsCount(); i++) {
+ isAnimated = true;
+
+ // For each animated sub property, create a track
+ m_NodeToIndicies.insert(std::make_pair(inNode, m_AnimationTrackCount++));
+ m_Translator->CacheAnimationTrack();
+
+ m_Translator->SetAnimationTrack(FBXSDK_CURVENODE_ROTATION,
+ theRotateCurveNode->GetChannelName(i));
+
+ ProcessAnimCurve(theRotateCurveNode->GetCurve(i), FBXSDK_CURVENODE_ROTATION,
+ theRotateCurveNode->GetChannelName(i));
+ }
+ }
+
+ if (theScaleCurveNode && CurveNodeIsAnimated(theScaleCurveNode)) {
+ for (unsigned int i = 0; i < theScaleCurveNode->GetChannelsCount(); i++) {
+ isAnimated = true;
+
+ // For each animated sub property, create a track
+ m_NodeToIndicies.insert(std::make_pair(inNode, m_AnimationTrackCount++));
+ m_Translator->CacheAnimationTrack();
+
+ m_Translator->SetAnimationTrack(FBXSDK_CURVENODE_SCALING,
+ theScaleCurveNode->GetChannelName(i));
+
+ ProcessAnimCurve(theScaleCurveNode->GetCurve(i), FBXSDK_CURVENODE_SCALING,
+ theScaleCurveNode->GetChannelName(i));
+ }
+ }
+
+ if (redAnimCurve) {
+ isAnimated = true;
+ m_NodeToIndicies.insert(std::make_pair(inNode, m_AnimationTrackCount++));
+ m_Translator->CacheAnimationTrack();
+
+ m_Translator->SetAnimationTrack(FBXSDK_CURVENODE_COLOR,
+ theScaleCurveNode->GetChannelName(0));
+
+ ProcessAnimCurve(redAnimCurve, FBXSDK_CURVENODE_COLOR, FBXSDK_CURVENODE_COLOR_RED);
+ }
+ if (greenAnimCurve) {
+ isAnimated = true;
+ m_NodeToIndicies.insert(std::make_pair(inNode, m_AnimationTrackCount++));
+ m_Translator->CacheAnimationTrack();
+
+ m_Translator->SetAnimationTrack(FBXSDK_CURVENODE_COLOR,
+ theScaleCurveNode->GetChannelName(0));
+
+ ProcessAnimCurve(greenAnimCurve, FBXSDK_CURVENODE_COLOR, FBXSDK_CURVENODE_COLOR_GREEN);
+ }
+ if (blueAnimCurve) {
+ isAnimated = true;
+ m_NodeToIndicies.insert(std::make_pair(inNode, m_AnimationTrackCount++));
+ m_Translator->CacheAnimationTrack();
+
+ m_Translator->SetAnimationTrack(FBXSDK_CURVENODE_COLOR,
+ theScaleCurveNode->GetChannelName(0));
+
+ ProcessAnimCurve(blueAnimCurve, FBXSDK_CURVENODE_COLOR, FBXSDK_CURVENODE_COLOR_BLUE);
+ }
+
+ // mark this node as animated
+ if (isAnimated)
+ m_NodeIsAnimatedMap.insert(std::make_pair(inNode, true));
+
+ // process node children
+ for (int i = 0; i < inNode->GetChildCount(); ++i) {
+ ProcessAnimLayer(inNode->GetChild(i), inAnimLayer);
+ }
+ }
+}
+
+/**
+* @brief Produce animations
+*
+*
+* @return no return.
+*/
+void FbxDomWalker::ProcessAnimationStacks()
+{
+ if (m_FbxScene != NULL) {
+ // get animation stack count
+ int numAnimStacks = m_FbxScene->GetSrcObjectCount<FbxAnimStack>();
+
+ // iterate throug all animations stacks
+ for (int i = 0; i < numAnimStacks; i++) {
+ FbxAnimStack *theAnimStack = m_FbxScene->GetSrcObject<FbxAnimStack>(i);
+
+ if (theAnimStack) {
+ FbxNode *theRootNode = m_FbxScene->GetRootNode();
+ // our internal animation system cannot handle pivots.
+ // This means fbx can contain "pre-rotations" which must be applied
+ // to the object before the aniamtion is applied. In addition this rotation
+ // is inherited to children. This messes up our converion entirely.
+ // Convert animation to not contain pivots and such.
+ theRootNode->ResetPivotSetAndConvertAnimation();
+ int numAnimLayers = theAnimStack->GetMemberCount<FbxAnimLayer>();
+
+ // iterate throug all animations layers
+ for (int n = 0; n < numAnimLayers; n++) {
+ FbxAnimLayer *theAnimLayer = theAnimStack->GetMember<FbxAnimLayer>(n);
+ for (int nodeCount = 0; nodeCount < theRootNode->GetChildCount(); nodeCount++) {
+ ProcessAnimLayer(theRootNode->GetChild(nodeCount), theAnimLayer);
+ }
+ }
+ }
+ }
+ }
+}
+
+} // End anonymous namespace
+
+struct ScopedHelper
+{
+ ISceneGraphTranslation &m_Helper;
+ ScopedHelper(ISceneGraphTranslation &h)
+ : m_Helper(h)
+ {
+ }
+ ~ScopedHelper() { m_Helper.Release(); }
+};
+
+bool CImportTranslation::ParseFbxFile(const std::string &fileName, Import &import, ISGTranslationLog &log)
+{
+ ISceneGraphTranslation &transHelper = ISceneGraphTranslation::CreateTranslation(import, log);
+ ScopedHelper __scope(transHelper);
+ FbxDomWalker theDomWalker(&transHelper);
+ if (theDomWalker.LoadDocument(fileName)) {
+ theDomWalker.ProcessAnimationStacks();
+ theDomWalker.ProcessScene();
+ return true;
+ }
+ return false;
+}
+#endif
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.cpp b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.cpp
new file mode 100644
index 00000000..e3b2e06f
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.cpp
@@ -0,0 +1,1155 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "UICImportSceneGraphTranslation.h"
+#include "UICImportImpl.h"
+#include "UICImportMesh.h"
+#include "Matrix.h"
+#include "Rotation3.h"
+#include "EulerAngles.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "UICImportComposerTypes.h"
+#include "CommonConstants.h"
+
+#include <QString>
+
+using namespace UICIMP;
+
+namespace {
+
+struct SubsetEntry
+{
+ long m_FaceStartIndex;
+ long m_NumFaces;
+ SubsetEntry(long off = 0, long numFace = 0)
+ : m_FaceStartIndex(off)
+ , m_NumFaces(numFace)
+ {
+ }
+};
+
+struct SGKeyframe
+{
+ QT3DSF32 m_Seconds;
+ QT3DSF32 m_Value;
+ QT3DSF32 m_EaseIn;
+ QT3DSF32 m_EaseOut;
+ SGKeyframe(QT3DSF32 sec, QT3DSF32 val, QT3DSF32 ei = 100.0f, QT3DSF32 eo = 100.0f)
+ : m_Seconds(sec)
+ , m_Value(val)
+ , m_EaseIn(ei)
+ , m_EaseOut(eo)
+ {
+ }
+ SGKeyframe()
+ : m_Seconds(0)
+ , m_Value(0)
+ , m_EaseIn(0)
+ , m_EaseOut(0)
+ {
+ }
+};
+
+struct SGAnimationApplier
+{
+ virtual ~SGAnimationApplier() {}
+ virtual void Apply(Import &inImport, const wchar_t *inInstanceId, QT3DSU32 subPropIndex,
+ EAnimationType inAnimType, NVConstDataRef<float> inData) = 0;
+};
+
+template <typename TDataType>
+struct SSpecificSGAnimationApplier : public SGAnimationApplier
+{
+ SImportPropertyDefinition<TDataType> m_Property;
+ SSpecificSGAnimationApplier(const SImportPropertyDefinition<TDataType> &inProp)
+ : m_Property(inProp)
+ {
+ }
+ void Apply(Import &inImport, const wchar_t *inInstanceId, QT3DSU32 subPropIndex,
+ EAnimationType inAnimType, NVConstDataRef<float> inData) override
+ {
+ inImport.AddAnimation(inInstanceId, m_Property, subPropIndex, inAnimType, inData);
+ }
+};
+
+struct SGAnimation
+{
+ std::function<void(Import &, QT3DSU32, ImportArray<SGKeyframe> &)> m_AnimationApplier;
+ ImportArray<SGKeyframe> m_Keyframes;
+ QT3DSU32 m_SubPropIndex;
+
+ std::shared_ptr<SGAnimationApplier> m_Applier;
+
+ template <typename TDataType>
+ void SetProperty(const SImportPropertyDefinition<TDataType> &inProperty)
+ {
+ m_Applier = std::make_shared<SSpecificSGAnimationApplier<TDataType>>(inProperty);
+ }
+ template <typename TDataType>
+ void Handle(ComposerPropertyNames::Enum inName)
+ {
+ SetProperty(SImportPropertyDefinition<TDataType>(inName));
+ }
+
+ SGAnimation()
+ : m_SubPropIndex(0)
+ {
+ }
+ void AddKey(QT3DSF32 sec, QT3DSF32 val, QT3DSF32 ei = 100.0f, QT3DSF32 eo = 100.0f)
+ {
+ (void)ei, (void)eo;
+ m_Keyframes.push_back(SGKeyframe(sec, val));
+ }
+};
+
+static inline UICDM::SValue ToColor(const float p[])
+{
+ return UICDM::SFloat3(p[0], p[1], p[2]);
+}
+static inline UICDM::SValue ToColor(const float p[], float inMult)
+{
+ return UICDM::SFloat3(p[0] * inMult, p[1] * inMult, p[2] * inMult);
+}
+template <typename TDataType>
+static inline TDataType GetMin(TDataType a, TDataType b)
+{
+ return NVMin(a, b);
+}
+template <typename TDataType>
+static inline TDataType GetMax(TDataType a, TDataType b)
+{
+ return NVMax(a, b);
+}
+static void RGBtoHSV(float r, float g, float b, float *h, float *s, float *v)
+{
+ float min, max, delta;
+
+ min = GetMin(GetMin(r, g), b);
+ max = GetMax(GetMax(r, g), b);
+ *v = max; // v
+ delta = max - min;
+ if (max != 0)
+ *s = delta / max; // s
+ else {
+ // r = g = b = 0 // s = 0, v is undefined
+ *s = 0;
+ *h = -1;
+ return;
+ }
+ if (r == max)
+ *h = (g - b) / delta; // between yellow & magenta
+ else if (g == max)
+ *h = 2 + (b - r) / delta; // between cyan & yellow
+ else
+ *h = 4 + (r - g) / delta; // between magenta & cyan
+ *h *= 60; // degrees
+ if (*h < 0)
+ *h += 360;
+}
+
+//==============================================================================
+/**
+ * Swizzle the vertex value to match Studio format
+ */
+void SwizzleVertex(TFloatsList &ioValues)
+{
+ long theSize = (long)ioValues.size();
+ for (long i = 0; i < theSize; i += 3) {
+ // Negate z component
+ ioValues[i + 2] = -ioValues[i + 2];
+ }
+}
+
+//==============================================================================
+/**
+ * Negate the vertex value
+ */
+void NegateVertex(TFloatsList &ioValues)
+{
+ long theSize = (long)ioValues.size();
+ for (long i = 0; i < theSize; i += 3) {
+ // Negate xyz component
+ ioValues[i] = -ioValues[i];
+ ioValues[i + 1] = -ioValues[i + 1];
+ ioValues[i + 2] = -ioValues[i + 2];
+ }
+}
+
+//==============================================================================
+/**
+ * Swizzle the TexCoord value to match Studio format
+ */
+void SwizzleTexCoord(TFloatsList &ioValues)
+{
+ long theSize = (long)ioValues.size();
+ for (long i = 0; i < theSize; i += 2) {
+ // Flip y axis
+ ioValues[i + 1] = 1 - ioValues[i + 1];
+ }
+}
+
+//==============================================================================
+/**
+ * Swizzle the Face Indices to match Studio format
+ */
+void SwizzleFaceIndices(TLongsList &ioValues)
+{
+ long theSize = (long)ioValues.size();
+ long theTemp;
+ for (long i = 0; i < theSize; i += 3) {
+ // Swap x & z value
+ theTemp = ioValues[i];
+ ioValues[i] = ioValues[i + 2];
+ ioValues[i + 2] = theTemp;
+ }
+}
+
+//==============================================================================
+/**
+ * Convert an axis angle rotation vector into a matrix representation.
+ * This code is modified from FCollada's FMMatrix44::AxisRotationMatrix
+ */
+void matrixFromAxisAngle(float inDegreeAngle, float inXAxis, float inYAxis, float inZAxis,
+ float inMatrix[4][4])
+{
+ // If axis or angle is zero, we're going to get a bad matrix, so bail.
+ if (fabsf(inDegreeAngle) < 0.001f
+ || (fabsf(inXAxis) < 0.001f && fabsf(inYAxis) < 0.001f && fabsf(inZAxis) < 0.001f)) {
+ return;
+ }
+
+ inDegreeAngle *= (float)UIC3D_DEGREES_TO_RADIANS;
+
+ Q3DStudio::CVector3 theAxis(inXAxis, inYAxis, inZAxis);
+ if (theAxis.LengthSquared() != 1.0f)
+ theAxis.Normalize();
+
+ // Formulae inspired from
+ // http://www.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html
+ float xSq = theAxis.x * theAxis.x;
+ float ySq = theAxis.y * theAxis.y;
+ float zSq = theAxis.z * theAxis.z;
+ float cT = cosf(inDegreeAngle);
+ float sT = sinf(inDegreeAngle);
+
+ inMatrix[0][0] = xSq + (ySq + zSq) * cT;
+ inMatrix[0][1] = theAxis.x * theAxis.y * (1.0f - cT) + theAxis.z * sT;
+ inMatrix[0][2] = theAxis.x * theAxis.z * (1.0f - cT) - theAxis.y * sT;
+ inMatrix[0][3] = 0;
+ inMatrix[1][0] = theAxis.x * theAxis.y * (1.0f - cT) - theAxis.z * sT;
+ inMatrix[1][1] = ySq + (xSq + zSq) * cT;
+ inMatrix[1][2] = theAxis.y * theAxis.z * (1.0f - cT) + theAxis.x * sT;
+ inMatrix[1][3] = 0;
+ inMatrix[2][0] = theAxis.x * theAxis.z * (1.0f - cT) + theAxis.y * sT;
+ inMatrix[2][1] = theAxis.y * theAxis.z * (1.0f - cT) - theAxis.x * sT;
+ inMatrix[2][2] = zSq + (xSq + ySq) * cT;
+ inMatrix[2][3] = 0;
+ inMatrix[3][2] = inMatrix[3][1] = inMatrix[3][0] = 0;
+ inMatrix[3][3] = 1;
+}
+
+#define FLT_TOLERANCE 0.0001f
+
+template <class T>
+T Sign(const T &val)
+{
+ return (val >= T(0)) ? T(1) : T(-1);
+}
+
+//==============================================================================
+/**
+ * Get a 2x2 determinant
+ */
+static float det2x2(float a1, float a2, float b1, float b2)
+{
+ return a1 * b2 - b1 * a2;
+}
+
+//==============================================================================
+/**
+ * Get the 3x3 determinant
+ */
+static float det3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2,
+ float c3)
+{
+ return a1 * det2x2(b2, b3, c2, c3) - b1 * det2x2(a2, a3, c2, c3) + c1 * det2x2(a2, a3, b2, b3);
+}
+
+//==============================================================================
+/**
+ * Decomposes the scale portion of a matrix.
+ * Modified from FCollada's FMMatrix44::Decompose
+ */
+void DecomposeScale(Q3DStudio::CVector3 &outScale, float inMatrix[4][4])
+{
+ outScale.x = sqrtf(inMatrix[0][0] * inMatrix[0][0] + inMatrix[0][1] * inMatrix[0][1]
+ + inMatrix[0][2] * inMatrix[0][2]);
+ outScale.y = sqrtf(inMatrix[1][0] * inMatrix[1][0] + inMatrix[1][1] * inMatrix[1][1]
+ + inMatrix[1][2] * inMatrix[1][2]);
+ outScale.z = sqrtf(inMatrix[2][0] * inMatrix[2][0] + inMatrix[2][1] * inMatrix[2][1]
+ + inMatrix[2][2] * inMatrix[2][2]);
+
+ float isInverted =
+ Sign(det3x3(inMatrix[0][0], inMatrix[0][1], inMatrix[0][2], inMatrix[1][0], inMatrix[1][1],
+ inMatrix[1][2], inMatrix[2][0], inMatrix[2][1], inMatrix[2][2]));
+
+ if (isInverted < 0.0f) {
+ outScale.x = -outScale.x;
+ outScale.y = -outScale.y;
+ outScale.z = -outScale.z;
+ }
+}
+
+static SFloat3 ConvertToSValue(const Q3DStudio::CVector3 &data)
+{
+ return SFloat3(data.x, data.y, data.z);
+}
+//==============================================================================
+/**
+* Translate SubPropertyName to index.
+*/
+long GetSubPropertyIndex(const char *inSubPropertyName)
+{
+ if (qstricmp(inSubPropertyName, "x") == 0 || qstricmp(inSubPropertyName, "r") == 0)
+ return 0;
+ else if (qstricmp(inSubPropertyName, "y") == 0 || qstricmp(inSubPropertyName, "g") == 0)
+ return 1;
+ else if (qstricmp(inSubPropertyName, "z") == 0 || qstricmp(inSubPropertyName, "b") == 0)
+ return 2;
+ else if (qstricmp(inSubPropertyName, "a") == 0)
+ return 3;
+ return 0;
+}
+
+bool Replace(std::string &str, const char *find, const char *replace)
+{
+ std::string::size_type pos = str.find(find);
+ if (pos != std::string::npos) {
+ size_t len = strlen(find);
+ str = str.replace(pos, len, replace);
+ return true;
+ }
+ return false;
+}
+
+class SGTrans : public ISceneGraphTranslation, public SImportComposerTypes
+{
+ // uses relationship, not owns.
+ Import &m_Import;
+ ImportArray<TIMPHandle> m_InstanceStack;
+ ImportHashMap<TIMPHandle, MeshBuilder *> m_Helpers;
+ ImportHashSet<TIMPHandle> m_DuplicateMaterials;
+ ImportArray<SGAnimation> m_Animations;
+ ImportHashSet<TIMPHandle> m_Invalids;
+ ISGTranslationLog &m_Log;
+ MemoryBuffer<RawAllocator> m_TempBuffer;
+ EAuthoringToolType m_AuthoringToolType;
+ long m_AuthoringToolVersion;
+ bool m_isDuplicatedMaterial;
+
+public:
+ SGTrans(Import &imp, ISGTranslationLog &log)
+ : m_Import(imp)
+ , m_Log(log)
+ , m_AuthoringToolType(EAuthoringToolType_Unknown)
+ , m_AuthoringToolVersion(0)
+ , m_isDuplicatedMaterial(false)
+ {
+ TIMPHandle root =
+ imp.CreateInstance(CImportTranslation::GetRootNodeId(), ComposerObjectTypes::Group);
+ m_InstanceStack.push_back(root);
+ m_Animations.reserve(100);
+ }
+ virtual ~SGTrans()
+ {
+ for (ImportHashMap<TIMPHandle, MeshBuilder *>::iterator iter = m_Helpers.begin(),
+ end = m_Helpers.end();
+ iter != end; ++iter)
+ iter->second->Release();
+ }
+
+ template <typename TDataType>
+ TDataType *TempAlloc(QT3DSU32 size)
+ {
+ m_TempBuffer.reserve(size * sizeof(TDataType));
+ return (TDataType *)m_TempBuffer.begin();
+ }
+
+ TCharPtr ToImport(const char *data)
+ {
+ if (data == NULL || *data == 0)
+ return L"";
+
+ // Convert from multi byte to wide character string
+ QString s = QString::fromLocal8Bit(data);
+ wchar_t *dataPtr(TempAlloc<wchar_t>(s.length() + 1));
+ const long theWideBufferSize = s.toWCharArray(dataPtr);
+ dataPtr[theWideBufferSize] = 0;
+ return dataPtr;
+ }
+
+ TCharPtr ToImport(const wchar_t *data) { return data; }
+
+ template <typename TNameType>
+ void InternalPushObject(const TNameType *inName, ComposerObjectTypes::Enum inType)
+ {
+ if (m_InstanceStack.size() == 0) {
+ MarkInvalid();
+ return;
+ }
+ TCharPtr name(ToImport(inName));
+
+ if (name == NULL || *name == 0)
+ name = ComposerObjectTypes::Convert(inType);
+
+ Q3DStudio::CFilePath objectName = Q3DStudio::CFilePath(name);
+ Q3DStudio::CString normName = objectName.GetPathWithoutIdentifier();
+ name = normName;
+
+ TCharPtr nameStem = name;
+ if (m_Import.FindInstanceById(name).hasValue()) {
+ wchar_t nameBuf[1024];
+ int idx = 1;
+ do {
+ swprintf(nameBuf, 1024, L"%ls_%04d", nameStem, idx);
+ ++idx;
+ name = nameBuf;
+ } while (m_Import.FindAnyInstanceById(name)
+ .hasValue()); // don't use any instance which was already used valid or not
+ }
+ TIMPHandle inst = m_Import.CreateInstance(name, inType);
+ m_Import.AddChild(m_InstanceStack.back(), inst);
+ m_Import.SetInstancePropertyValue(inst, m_Asset.m_NameProp, nameStem);
+ m_InstanceStack.push_back(inst);
+ }
+
+ void PushObject(const char *inName, ComposerObjectTypes::Enum inType)
+ {
+ InternalPushObject(inName, inType);
+ }
+
+ TIMPHandle PopObject()
+ {
+ TIMPHandle back = m_InstanceStack.back();
+ m_InstanceStack.pop_back();
+ if (m_Invalids.contains(back))
+ return 0;
+ return back;
+ }
+
+ void Release() override { delete this; }
+
+ //==============================================================================
+ /**
+ * Set Authoring Tool
+ */
+ void SetAuthoringTool(EAuthoringToolType inAuthoringToolType,
+ long inAuthoringToolVersion) override
+ {
+ m_AuthoringToolType = inAuthoringToolType;
+ m_AuthoringToolVersion = inAuthoringToolVersion;
+ }
+
+ virtual bool isFbxFormatType(EAuthoringToolType inAuthoringToolType)
+ {
+ return ((inAuthoringToolType == EAuthoringToolType_FBX_Max)
+ || (inAuthoringToolType == EAuthoringToolType_FBX_Modo)
+ || (inAuthoringToolType == EAuthoringToolType_FBX_Maya));
+ }
+
+ void PushGroup(const char *inName) override { PushObject(inName, ComposerObjectTypes::Group); }
+ void SetGroupSkeletonId(long inId) override
+ {
+ TIMPHandle model = m_InstanceStack.back();
+ m_Import.SetInstancePropertyValue(model, m_Node.m_BoneId, inId);
+ }
+
+ void SetIgnoresParentTransform(bool inValue) override
+ {
+ TIMPHandle model = m_InstanceStack.back();
+ m_Import.SetInstancePropertyValue(model, m_Node.m_IgnoresParent, inValue);
+ }
+
+ void PopGroup() override { PopObject(); }
+ void PushModel(const char *inName) override { PushObject(inName, ComposerObjectTypes::Model); }
+ void SetModelSkeletonRoot(long inName) override
+ {
+ TIMPHandle model = m_InstanceStack.back();
+ m_Import.SetInstancePropertyValue(model, m_Model.m_PoseRoot, inName);
+ }
+ void PopModel() override
+ {
+ TIMPHandle model = PopObject();
+ if (model) {
+ TCharPtr modelId = m_Import.GetInstanceByHandle(model)->m_Id;
+ ImportHashMap<TIMPHandle, MeshBuilder *>::const_iterator entry = m_Helpers.find(model);
+ if (entry != m_Helpers.end()) {
+ entry->second->ConnectSubMeshes();
+ entry->second->OptimizeMesh();
+ Mesh &mesh = entry->second->GetMesh();
+ CharPtrOrError meshData = m_Import.AddMesh(mesh, modelId);
+ if (meshData.m_Value && *meshData.m_Value)
+ m_Import.SetInstancePropertyValue(model, m_Asset.m_SourcePath,
+ meshData.m_Value);
+ if (meshData.m_Error)
+ m_Log.OnWarning(ESceneGraphWarningCode_LockedDestFile, meshData.m_Value);
+ }
+ }
+ }
+ void PushMaterial(const char *inName) override
+ {
+ // mark as not duplicated material
+ m_isDuplicatedMaterial = false;
+ // find if there exists already an instance of this material
+ TCharPtr name(ToImport(inName));
+ Option<InstanceDesc> inst = m_Import.FindInstanceById(name);
+
+ if (inst.hasValue()) {
+ if (m_DuplicateMaterials.contains(inst.getValue().m_Handle)) {
+ m_isDuplicatedMaterial = true;
+ }
+ }
+
+ PushObject(inName, ComposerObjectTypes::Material);
+
+ // add to list if unique for this mesh instance and PushObject succeeded
+ if (!m_isDuplicatedMaterial && !m_Invalids.contains(m_InstanceStack.back())) {
+ // always add the original instance if exists because this is what we looking for
+ if (inst.hasValue())
+ m_DuplicateMaterials.insert(inst.getValue().m_Handle);
+ else
+ m_DuplicateMaterials.insert(m_InstanceStack.back());
+ }
+ }
+ void PopMaterial(long inStartFaceIndex, long inNumberOfFaces) override
+ {
+ TIMPHandle material = m_InstanceStack.back();
+
+ if (material) {
+ // this is a duplicated material mark it invalid
+ // this means it is not written to the import file
+ if (m_isDuplicatedMaterial) {
+ MarkInvalid();
+ }
+
+ PopObject();
+
+ const wchar_t *theNameBuf = L"";
+ Option<SValue> theName(
+ m_Import.GetInstancePropertyValue(material, m_Asset.m_NameProp.GetName()));
+ if (theName.hasValue()) {
+ theNameBuf = UICDM::get<TDataStrPtr>(*theName)->GetData();
+
+ GetOrCreateMeshBuilder()->AddMeshSubset(
+ theNameBuf, inNumberOfFaces * 3,
+ inStartFaceIndex * 3, 0);
+ }
+ }
+ }
+ void PushTexture(const char * /*inName*/, const char *inSourcePath, long inMapType) override
+ {
+ TCharPtr source = m_Import.RegisterStr(ToImport(inSourcePath));
+ // Ignore paths such as:
+ // /d:/something
+ if (source[2] == ':') {
+ if (source[0] == '\\' || source[0] == '/')
+ ++source;
+ }
+ CharPtrOrError result = m_Import.AddImage(source);
+ TCharPtr dest = result.m_Value;
+ TCharPtr imgPath = NULL;
+ wchar_t pathBuf[1024];
+ if (result.m_Error) {
+ ESceneGraphWarningCode code = ESceneGraphWarningCode_Generic;
+ const wchar_t *errorStr = source;
+ if (result.m_ErrorData.m_Error == ImportErrorCodes::SourceFileNotReadable)
+ code = ESceneGraphWarningCode_MissingSourceFile;
+ else if (result.m_ErrorData.m_Error == ImportErrorCodes::ResourceNotWriteable) {
+ code = ESceneGraphWarningCode_LockedDestFile;
+ errorStr = m_Import.RegisterStr(dest);
+ }
+ m_Log.OnWarning(code, errorStr);
+ }
+ if (result.m_Value != NULL && *result.m_Value)
+ imgPath = result.m_Value;
+ else {
+ swprintf(pathBuf, 1024, L"%ls/missing.png", m_Import.GetImageDir());
+ imgPath = pathBuf;
+ }
+ // We want to name the texture after the material id concatenated with the map type.
+ // This ensures that we carry texture settings across for materials because the material
+ // id doesn't change.
+ TIMPHandle theMaterial = m_InstanceStack.back();
+ std::wstring theId(m_Import.GetInstanceByHandle(theMaterial)->m_Id);
+ theId.append(L"_");
+ switch (inMapType) {
+ case ETextureMapTypeDiffuse:
+ theId.append(L"diffusemap");
+ break;
+ case ETextureMapTypeOpacity:
+ theId.append(L"opacitymap");
+ break;
+ case ETextureMapTypeSpecular:
+ theId.append(L"specularmap");
+ break;
+ case ETextureMapTypeEmissive:
+ theId.append(L"emissivemap");
+ break;
+ }
+ InternalPushObject(theId.c_str(), ComposerObjectTypes::Image);
+ TIMPHandle topObj = m_InstanceStack.back();
+ m_Import.SetInstancePropertyValue(topObj, m_Image.m_SourcePath, imgPath);
+ }
+
+ void PopTexture() override { PopObject(); }
+
+ void MarkInvalid() override
+ {
+ m_Invalids.insert(m_InstanceStack.back());
+ m_Import.MarkInstanceInvalid(m_InstanceStack.back());
+ }
+
+ template <typename TPropertyType, typename TDataType>
+ void SetInstancePropertyValue(TIMPHandle hdl,
+ const SImportPropertyDefinition<TPropertyType> &name,
+ const TDataType &value)
+ {
+ m_Import.SetInstancePropertyValue(hdl, name, value);
+ }
+
+ void SetMaterial(const SMaterialParameters &inMaterialParameters) override
+ {
+ TIMPHandle theMaterial = m_InstanceStack.back();
+
+ if (inMaterialParameters.m_Diffuse.m_Type == SColorOrTexture::Texture)
+ // Set diffuse color to 1.0 if there is diffuse texture because I think diffuse color is
+ // multiplied with diffuse texture to get the final color
+ SetInstancePropertyValue(theMaterial, m_Material.m_DiffuseColor,
+ UICDM::SFloat3(1.0f, 1.0f, 1.0f));
+ else
+ SetInstancePropertyValue(theMaterial, m_Material.m_DiffuseColor,
+ UICDM::SFloat3(inMaterialParameters.m_Diffuse.m_Color[0],
+ inMaterialParameters.m_Diffuse.m_Color[1],
+ inMaterialParameters.m_Diffuse.m_Color[2]));
+
+ if (inMaterialParameters.m_Extra.m_EmissionLevel.m_Flag) {
+ SetInstancePropertyValue(theMaterial, m_Material.m_EmissivePower,
+ inMaterialParameters.m_Extra.m_EmissionLevel.m_Value * 100);
+ } else {
+ float theHSV[3];
+ RGBtoHSV(inMaterialParameters.m_Emission.m_Color[0],
+ inMaterialParameters.m_Emission.m_Color[1],
+ inMaterialParameters.m_Emission.m_Color[2], &theHSV[0], &theHSV[1],
+ &theHSV[2]);
+ SetInstancePropertyValue(theMaterial, m_Material.m_EmissivePower, theHSV[2] * 100);
+ }
+
+ if (inMaterialParameters.m_Shininess.m_Flag) {
+ float theShininess = inMaterialParameters.m_Shininess.m_Value;
+ if (inMaterialParameters.m_TechniqueType == EMatCommonProfileTechnique_Blinn) {
+ // From Collada spec 1.4
+ // To maximize application compatibility, it is suggested that developers use the
+ // Blinn-Torrance-Sparrow for
+ // <shininess> range of 0 to 1. For <shininess> greater than 1.0, the COLLADA author
+ // was probably
+ // using an application that followed the Blinn-Phong lighting model, so it is
+ // recommended to support both
+ // Blinn equations according to whichever range the shininess resides in.
+
+ // We don't support Blinn-Torance-Sparrow, so the workaround is to multiply by 100
+ // if it's within the range 0 to 1
+ if (theShininess <= 1.0f)
+ theShininess *= 100.0f;
+ }
+ SetInstancePropertyValue(theMaterial, m_Material.m_SpecularRoughness, theShininess);
+ }
+
+ bool theSpecularEnable = false;
+ if (theSpecularEnable)
+ SetInstancePropertyValue(theMaterial, m_Material.m_SpecularAmount, 1.0f);
+ else
+ SetInstancePropertyValue(theMaterial, m_Material.m_SpecularAmount, 0.0f);
+
+ // Opacity
+ float theTransparency = 1.0f;
+ if (inMaterialParameters.m_Transparency.m_Flag) {
+ // This is true for MAX and MODO but not for MAYA
+ if ((m_AuthoringToolType == EAuthoringToolType_FBX_Max)
+ || (m_AuthoringToolType == EAuthoringToolType_FBX_Modo)) {
+ // on FBX 0 is fully opaque and 1 is fully transparent
+ // we treat it vice versa
+ theTransparency = 1.0f - inMaterialParameters.m_Transparency.m_Value;
+ } else {
+ theTransparency = inMaterialParameters.m_Transparency.m_Value;
+ }
+ }
+ float theTransparent = 1.0f;
+ float theOpacity = theTransparency * theTransparent;
+ if (inMaterialParameters.m_TransparentOpaqueType.m_Flag
+ && inMaterialParameters.m_Transparent.m_Type == SColorOrTexture::Color) {
+ if (inMaterialParameters.m_TransparentOpaqueType.m_Value == EMatOpaqueType_A_ONE) {
+ theTransparent = inMaterialParameters.m_Transparent.m_Color[3];
+ theOpacity = theTransparency * theTransparent;
+ } else // EMatOpaqueType_RGB_ZERO
+ {
+ theTransparent = (inMaterialParameters.m_Transparent.m_Color[0]
+ + inMaterialParameters.m_Transparent.m_Color[1]
+ + inMaterialParameters.m_Transparent.m_Color[2])
+ / 3.0f;
+ theOpacity = 1.0f - (theTransparency * theTransparent);
+ }
+ }
+ SetInstancePropertyValue(theMaterial, m_Material.m_Opacity, theOpacity * 100.0f);
+
+ SetInstancePropertyValue(theMaterial, m_Material.m_BlendMode, L"Normal");
+ }
+ void SetTexture(long inMapType, const STextureParameters &inTextureParameters) override
+ {
+ QT3DS_ASSERT(m_InstanceStack.size() > 2);
+
+ TIMPHandle theImageInstance = m_InstanceStack.back(); // This refers to the texture
+ m_InstanceStack.pop_back();
+ m_InstanceStack.push_back(theImageInstance);
+
+ // Create Image Instance at specified map property
+ SImportPropertyDefinition<SLong4> *theProperty = &m_Material.m_DiffuseMap1;
+ switch (inMapType) {
+ case ETextureMapTypeDiffuse:
+ theProperty = &m_Material.m_DiffuseMap1;
+ break;
+ case ETextureMapTypeOpacity:
+ theProperty = &m_Material.m_OpacityMap;
+ break;
+ case ETextureMapTypeSpecular:
+ theProperty = &m_Material.m_SpecularReflection;
+ break;
+ case ETextureMapTypeEmissive:
+ theProperty = &m_Material.m_EmissiveMap;
+ break;
+ }
+ if (m_InstanceStack.size() > 1) {
+ // Set the map property.
+ Option<InstanceDesc> theImage(m_Import.GetInstanceByHandle(theImageInstance));
+ Option<InstanceDesc> theMaterial(
+ m_Import.GetInstanceByHandle(m_InstanceStack[m_InstanceStack.size() - 2]));
+ QT3DS_ASSERT(theImage.hasValue() && theMaterial.hasValue());
+ if (theImage.hasValue() && theMaterial.hasValue()) {
+ QT3DS_ASSERT(theMaterial->m_Type == ComposerObjectTypes::Material);
+ m_Import.SetInstancePropertyValue(theMaterial->m_Handle, *theProperty,
+ theImage->m_Id);
+ }
+ }
+
+ // Set the Image Instance properties
+ if (inTextureParameters.m_Flag) {
+ // Ok, this portion requires some explanation.
+ // It seems that Coverage in Maya affects the Repeat in some ways.
+ // The relation seems to be IDE Repeat = Maya Repeat / Maya Coverage for Coverage >= 1.0
+ // However, if Coverage is less than 1.0, this doesn't seems to hold anymore....
+ float theCoverageU = 1.0f;
+ float theCoverageV = 1.0f;
+ if (inTextureParameters.m_coverageU.m_Flag) {
+ theCoverageU = inTextureParameters.m_coverageU.m_Value;
+ }
+
+ if (inTextureParameters.m_coverageV.m_Flag) {
+ theCoverageV = inTextureParameters.m_coverageV.m_Value;
+ }
+
+ float theScaleU = 1.0f;
+ if (inTextureParameters.m_repeatU.m_Flag) {
+ theScaleU = inTextureParameters.m_repeatU.m_Value;
+ SetInstancePropertyValue(theImageInstance, m_Image.m_RepeatU,
+ theScaleU / theCoverageU);
+ }
+
+ float theScaleV = 1.0f;
+ if (inTextureParameters.m_repeatV.m_Flag) {
+ theScaleV = inTextureParameters.m_repeatV.m_Value;
+ SetInstancePropertyValue(theImageInstance, m_Image.m_RepeatV,
+ theScaleV / theCoverageV);
+ }
+
+ // From AMXMayaExporter: pivot values are ignored and defaults to 0.5
+ const float theDefaultPivot = 0.5;
+ // It seems that Coverage is affecting Pivot & Position
+
+ SetInstancePropertyValue(theImageInstance, m_Image.m_PivotU,
+ theDefaultPivot / theCoverageU);
+ SetInstancePropertyValue(theImageInstance, m_Image.m_PivotV,
+ theDefaultPivot / theCoverageV);
+
+ // From AMXMayaExporter: do offset with pivotU and scaleU
+ // maya does rotateUV about pivot(0.5,0.5) while position/scaleUV is done via (0,0)
+ // then we gotta translate to Studio's way of UV pivot...
+ if (inTextureParameters.m_offsetU.m_Flag) {
+ SetInstancePropertyValue(
+ theImageInstance, m_Image.m_PositionU,
+ (theDefaultPivot - 1 + inTextureParameters.m_offsetU.m_Value * theCoverageU)
+ / theScaleU);
+ }
+ // From AMXMayaExporter: do offset with pivotV and scaleV...
+ // Same explanation as for position U
+ if (inTextureParameters.m_offsetV.m_Flag) {
+ SetInstancePropertyValue(
+ theImageInstance, m_Image.m_PositionV,
+ (theDefaultPivot - 1 + inTextureParameters.m_offsetV.m_Value * theCoverageV)
+ / theScaleV);
+ }
+
+ if (inTextureParameters.m_rotateUV.m_Flag) {
+ SetInstancePropertyValue(theImageInstance, m_Image.m_RotationUV,
+ inTextureParameters.m_rotateUV.m_Value);
+ }
+
+ // tiling mode U
+ std::wstring theHorizontalTilingMode = L"Tiled"; // tiled
+ if (inTextureParameters.m_wrapU.m_Flag) {
+ if (inTextureParameters.m_wrapU.m_Value == 0)
+ theHorizontalTilingMode = L"No Tiling"; // not tiled
+ }
+ if (inTextureParameters.m_mirrorU.m_Flag) {
+ if (inTextureParameters.m_mirrorU.m_Value == 1)
+ theHorizontalTilingMode = L"Mirrored"; // mirrored
+ }
+
+ SetInstancePropertyValue(theImageInstance, m_Image.m_TilingU,
+ theHorizontalTilingMode.c_str());
+
+ // tiling mode V
+ std::wstring theVerticalTilingMode = L"Tiled"; // tiled
+ if (inTextureParameters.m_wrapV.m_Flag) {
+ if (inTextureParameters.m_wrapV.m_Value == 0)
+ theVerticalTilingMode = L"No Tiling"; // not tiled
+ }
+ if (inTextureParameters.m_mirrorV.m_Flag) {
+ if (inTextureParameters.m_mirrorV.m_Value == 1)
+ theVerticalTilingMode = L"Mirrored"; // mirrored
+ }
+
+ SetInstancePropertyValue(theImageInstance, m_Image.m_TilingV,
+ theVerticalTilingMode.c_str());
+ }
+ }
+
+ void SetTransforms(const TTransformList &inTransforms) override
+ {
+ TIMPHandle theNode = m_InstanceStack.back();
+
+ Q3DStudio::CMatrix theTransformStack;
+ theTransformStack.Identity();
+
+ TTransformList::const_iterator theIter = inTransforms.begin();
+ TTransformList::const_iterator theEnd = inTransforms.end();
+ for (; theIter != theEnd; ++theIter) {
+ const INodeTransform *theTransform = *theIter;
+
+ Q3DStudio::CMatrix theMatrix;
+
+ switch ((*theIter)->GetType()) {
+ case ETransformType_Matrix4x4: {
+ Q3DStudio::CMatrix::TArray &theArray = theMatrix.GetArray();
+
+ for (long theRow = 0; theRow < 4; ++theRow)
+ for (long theColumn = 0; theColumn < 4; ++theColumn)
+ theArray[theColumn][theRow] = (*theTransform)[(theRow * 4) + theColumn];
+ } break;
+ case ETransformType_Rotation3: {
+ // this a rotation is defined by 3 angles
+ Q3DStudio::CRotation3 rotation;
+ rotation.SetAngles((*theTransform)[0], (*theTransform)[1], (*theTransform)[2]);
+ theMatrix.Rotate(rotation);
+ } break;
+ case ETransformType_Rotation4: {
+ // EulerAngleConverter::CEulerAngleConverter theConverter;
+ // EulerAngleConverter::EulerAngles theAxisAngle ={ ( *theTransform )[0], (
+ // *theTransform )[1], ( *theTransform )[2], ( *theTransform )[3] *
+ // (float)Q3DStudio::UIC3D_DEGREES_TO_RADIANS };
+ // theConverter.Eul_ToHMatrix( theAxisAngle, theMatrix.GetArray( ) );
+ matrixFromAxisAngle((*theTransform)[3], (*theTransform)[0], (*theTransform)[1],
+ (*theTransform)[2], theMatrix.GetArray());
+ } break;
+ case ETransformType_Translate3: {
+ theMatrix.SetTranslate(Q3DStudio::CVector3((*theTransform)[0], (*theTransform)[1],
+ (*theTransform)[2]));
+ } break;
+ case ETransformType_Scale3: {
+ theMatrix.SetScale(Q3DStudio::CVector3((*theTransform)[0], (*theTransform)[1],
+ (*theTransform)[2]));
+ } break;
+ default:
+ break;
+ }
+
+ theTransformStack = theMatrix * theTransformStack;
+ }
+
+ // Get out the rotation
+ EulerAngleConverter::CEulerAngleConverter theConverter;
+ EulerAngleConverter::EulerAngles theEulerAngles =
+ theConverter.Eul_FromHMatrix(theTransformStack.GetArray(), EulOrdXYZr);
+ Q3DStudio::CRotation3 theRotation;
+ theRotation.SetRadians(-theEulerAngles.x, -theEulerAngles.y, -theEulerAngles.z);
+
+ Q3DStudio::CVector3 theTranslation = theTransformStack.GetTranslation();
+ theTranslation.z *= -1;
+
+ Q3DStudio::CVector3 theScale;
+ DecomposeScale(theScale, theTransformStack.GetArray());
+
+ SFloat3 theRotationAngles;
+ theRotation.GetAngles(theRotationAngles[0], theRotationAngles[1], theRotationAngles[2]);
+
+ SetInstancePropertyValue(theNode, m_Node.m_Rotation, theRotationAngles);
+ SetInstancePropertyValue(theNode, m_Node.m_Position, ConvertToSValue(theTranslation));
+ SetInstancePropertyValue(theNode, m_Node.m_Scale, ConvertToSValue(theScale));
+
+ SetInstancePropertyValue(theNode, m_Node.m_Orientation, L"Right Handed");
+ SetInstancePropertyValue(theNode, m_Node.m_RotationOrder, L"XYZr");
+ }
+
+ MeshBuilder *GetOrCreateMeshBuilder()
+ {
+ ImportHashMap<TIMPHandle, MeshBuilder *>::iterator entry =
+ m_Helpers.find(m_InstanceStack.back());
+ if (entry != m_Helpers.end())
+ return entry->second;
+ MeshBuilder *newHelper = &MeshBuilder::CreateMeshBuilder();
+ m_Helpers.insert(eastl::make_pair(m_InstanceStack.back(), newHelper));
+ return newHelper;
+ }
+
+ template <typename TDataType>
+ static NVConstDataRef<QT3DSU8> toRef(const std::vector<TDataType> &data)
+ {
+ const TDataType *dataPtr = data.size() ? &data[0] : NULL;
+ return toU8ConstDataRef(dataPtr, (QT3DSU32)data.size());
+ }
+
+ static inline MeshBuilderVBufEntry ToEntry(const TFloatsList &data, const char *name,
+ QT3DSU32 numComponents)
+ {
+ return MeshBuilderVBufEntry(name, toRef(data), NVRenderComponentTypes::QT3DSF32,
+ numComponents);
+ }
+
+ std::vector<QT3DSU16> m_ShortIndicies;
+ std::vector<QT3DSU32> m_UIntIndicies;
+
+ // We used to swizzle vertexes, which was intended to go from right to left handed coordinates.
+ // But the mesh that we save out gets loaded in its native format by the runtime.
+ // Thus we shouldn't here, but swizzle it when it is loaded into studio.
+ void SetGeometry(TFloatsList &ioVertices, TFloatsList &ioNormals,
+ TFloatsList &ioTexCoords, TFloatsList &ioTexCoords2,
+ TFloatsList &ioTexTangents, TFloatsList &ioTexBinormals,
+ TFloatsList &ioWeights, TFloatsList &ioBoneIndex,
+ TLongsList &ioFaceIndicies) override
+ {
+ // we clear our duplicate materials for each new geometry
+ m_DuplicateMaterials.clear();
+
+ MeshBuilder *theModel = GetOrCreateMeshBuilder();
+ ////////////////////////////////////////// To Fix Bug 4043
+ /////////////////////////////////////////////
+ // TexTangents exported from ColladaMaya 3.05C or ColladaMax 3.05C are inverted!
+ // But ColladaMaya 3.02 & NextGen 0.9.5 are not inverted
+ if (m_AuthoringToolType == EAuthoringToolType_FCollada_Max
+ || m_AuthoringToolType == EAuthoringToolType_FCollada_Maya) {
+ if (m_AuthoringToolVersion == 305) // TODO: Test with version 303 and 304
+ {
+ NegateVertex(ioTexTangents);
+ }
+ }
+ ///////////////////////////////////////////// End fix
+ //////////////////////////////////////////////////
+
+ bool valid = true;
+ NVRenderComponentTypes::Enum theIndexCompType = NVRenderComponentTypes::QT3DSU16;
+
+ // check if we exceed 65k vertex count
+ // ioVertices is a float array of xyz per vertex
+ if (ioVertices.size() / 3 > QT3DS_MAX_U16) {
+ theIndexCompType = NVRenderComponentTypes::QT3DSU32;
+ }
+
+ QT3DSU32 theIndexCompSize = NVRenderComponentTypes::getSizeofType(theIndexCompType);
+
+ MeshBuilderVBufEntry entries[] = {
+ ToEntry(ioVertices, Mesh::GetPositionAttrName(), 3),
+ ToEntry(ioNormals, Mesh::GetNormalAttrName(), 3),
+ ToEntry(ioTexCoords, Mesh::GetUVAttrName(), 2),
+ ToEntry(ioTexCoords2, Mesh::GetUV2AttrName(), 2),
+ ToEntry(ioTexTangents, Mesh::GetTexTanAttrName(), 3),
+ ToEntry(ioTexBinormals, Mesh::GetTexBinormalAttrName(), 3),
+ ToEntry(ioWeights, Mesh::GetWeightAttrName(), 4),
+ ToEntry(ioBoneIndex, Mesh::GetBoneIndexAttrName(), 4),
+ };
+ valid = valid && theModel->SetVertexBuffer(toDataRef(entries, 8));
+
+ if (!valid) {
+ valid = false;
+ } else if (theIndexCompSize == 2) {
+ m_ShortIndicies.resize(ioFaceIndicies.size());
+ for (size_t idx = 0, end = ioFaceIndicies.size(); idx < end; ++idx)
+ m_ShortIndicies[idx] = static_cast<QT3DSU16>(ioFaceIndicies[idx]);
+ if (m_ShortIndicies.size())
+ theModel->SetIndexBuffer(
+ NVDataRef<QT3DSU8>(reinterpret_cast<QT3DSU8 *>(&m_ShortIndicies[0]),
+ (QT3DSU32)m_ShortIndicies.size() * theIndexCompSize),
+ theIndexCompType);
+ else
+ valid = false;
+ } else if (theIndexCompSize == 4) {
+ m_UIntIndicies.resize(ioFaceIndicies.size());
+ for (size_t idx = 0, end = ioFaceIndicies.size(); idx < end; ++idx)
+ m_UIntIndicies[idx] = static_cast<QT3DSU32>(ioFaceIndicies[idx]);
+ if (m_UIntIndicies.size())
+ theModel->SetIndexBuffer(
+ NVDataRef<QT3DSU8>(reinterpret_cast<QT3DSU8 *>(&m_UIntIndicies[0]),
+ (QT3DSU32)m_UIntIndicies.size() * theIndexCompSize),
+ theIndexCompType);
+ else
+ valid = false;
+ }
+
+ if (!valid) {
+ MarkInvalid();
+ theModel->SetIndexBuffer(NVDataRef<QT3DSU8>(), theIndexCompType);
+ }
+ }
+
+ void SetJointNode(SJointInfo &inJointInfo) override
+ {
+ MeshBuilder *theModel = GetOrCreateMeshBuilder();
+ theModel->AddJoint(inJointInfo.m_JointID, inJointInfo.m_ParentID, inJointInfo.m_invBindPose,
+ inJointInfo.m_localToGlobalBoneSpace);
+ }
+
+ long CacheAnimationTrack() override
+ {
+ m_Animations.push_back(SGAnimation());
+ return (QT3DSI32)m_Animations.size() - 1;
+ }
+ void ApplyAnimationTrack(long inAnimationTrackIndex) override
+ {
+ if (inAnimationTrackIndex >= (long)m_Animations.size() || m_InstanceStack.size() == 0) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SGAnimation &anim = m_Animations[inAnimationTrackIndex];
+ if (!anim.m_Applier) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ TIMPHandle instance(m_InstanceStack.back());
+ InstanceDesc theDesc(m_Import.GetInstanceByHandle(instance));
+ TCharPtr instId = theDesc.m_Id;
+ anim.m_Applier->Apply(
+ m_Import, instId, anim.m_SubPropIndex, EAnimationTypeEaseInOut,
+ toConstDataRef((float *)anim.m_Keyframes.begin(), (QT3DSU32)anim.m_Keyframes.size() * 4));
+ }
+
+ void CacheAnimationKey(const char *inBaseProperty, const char *inSubPropertyName,
+ const SKeyframeParameters &inParameters) override
+ {
+ // Hardcode to use SEaseInEaseOutKeyframe. It seems that Studio needs this in order to
+ // animate properly.
+ // (I tried using SBezierKeyframe, but Studio doesn't Animate properly).
+ SGKeyframe theKeyframe(inParameters.m_KeyframeTime, inParameters.m_Value);
+
+ // Negate if we are animating position.z
+ if (isFbxFormatType(m_AuthoringToolType)) {
+ if (qstricmp(inBaseProperty, "T") == 0 && qstricmp(inSubPropertyName, "Z") == 0)
+ theKeyframe.m_Value = -theKeyframe.m_Value;
+ } else {
+ if (qstricmp(inBaseProperty, "translate") == 0
+ && qstricmp(inSubPropertyName, "z") == 0)
+ theKeyframe.m_Value = -theKeyframe.m_Value;
+ }
+
+ m_Animations.back().m_Keyframes.push_back(theKeyframe);
+ }
+
+ void SetAnimationTrack(const char *inBasePropertyName, const char *inSubPropertyName) override
+ {
+ if (m_Animations.size() == 0) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ SGAnimation &theTrack = m_Animations.back();
+
+ // Extract if there is any SubPropertyName merged into inBasePropertyName.
+ std::string theBasePropertyName(inBasePropertyName);
+ std::string theSubPropertyName(inSubPropertyName);
+ std::string::size_type thePos = theBasePropertyName.rfind('.');
+ if (thePos != std::string::npos) {
+ theSubPropertyName = theBasePropertyName.substr(thePos + 1);
+ theBasePropertyName = theBasePropertyName.substr(0, thePos);
+ }
+
+ std::string theStudioPropertyName(theBasePropertyName.c_str());
+
+ if (isFbxFormatType(m_AuthoringToolType)) {
+ // Translate FBX element names into actual property names for Studio
+ (Replace(theStudioPropertyName, "T", "position") != 0)
+ || (Replace(theStudioPropertyName, "R", "rotation") != 0)
+ || (Replace(theStudioPropertyName, "S", "scale") != 0);
+ } else {
+ // Translate COLLADA element names into actual property names for Studio
+ (Replace(theStudioPropertyName, "translate", "position") != 0)
+ || (Replace(theStudioPropertyName, "rotate", "rotation") != 0)
+ || (Replace(theStudioPropertyName, "transparency", "opacity") != 0);
+ }
+
+ long idx = GetSubPropertyIndex(theSubPropertyName.c_str());
+ theTrack.m_SubPropIndex = idx;
+ Q3DStudio::CString theName(theStudioPropertyName.c_str());
+ ComposerPropertyNames::Enum thePropertyName(ComposerPropertyNames::Convert(theName));
+ ImportVisitPropertyType(thePropertyName, theTrack);
+ }
+
+ void LogWarning(ESceneGraphWarningCode inWarningCode, const char *inAssociatedName) override
+ {
+ m_Log.OnWarning(inWarningCode, m_Import.RegisterStr(ToImport(inAssociatedName)));
+ }
+};
+}
+
+ISceneGraphTranslation &ISceneGraphTranslation::CreateTranslation(Import &import,
+ ISGTranslationLog &log)
+{
+ return *new SGTrans(import, log);
+}
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.h
new file mode 100644
index 00000000..e42ae0b2
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportSceneGraphTranslation.h
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+
+#include <vector>
+#include "UICImportTranslation.h"
+#include "UICImportTranslationCommon.h"
+
+namespace UICIMP {
+
+typedef enum _ETransformType {
+ ETransformType_Matrix4x4,
+ ETransformType_Rotation3, // rotation defined with 3 angles
+ ETransformType_Rotation4, // rotation defined with an axis and angle
+ ETransformType_Translate3,
+ ETransformType_Scale3,
+ ETransformType_Unknown
+} ETransformType;
+
+class INodeTransform
+{
+public:
+ virtual ~INodeTransform() {}
+ virtual operator float *() const = 0;
+ virtual ETransformType GetType() const = 0;
+};
+
+class NodeTransform : public INodeTransform
+{
+public:
+ NodeTransform(ETransformType inType)
+ {
+ m_Data = NULL;
+ switch (inType) {
+ case ETransformType_Matrix4x4:
+ m_Data = new float[16];
+ break;
+ case ETransformType_Rotation3:
+ m_Data = new float[3];
+ break;
+ case ETransformType_Rotation4:
+ m_Data = new float[4];
+ break;
+ case ETransformType_Translate3:
+ m_Data = new float[3];
+ break;
+ case ETransformType_Scale3:
+ m_Data = new float[3];
+ break;
+ }
+
+ m_Type = inType;
+ }
+
+ ~NodeTransform() { delete[] m_Data; }
+
+ operator float *() const override { return m_Data; }
+
+ ETransformType GetType() const override { return m_Type; }
+
+ static void Delete(INodeTransform *inTransform) { delete inTransform; }
+
+protected:
+ float *m_Data;
+ ETransformType m_Type;
+};
+
+typedef std::vector<INodeTransform *> TTransformList;
+
+typedef enum _ETextureMapType {
+ ETextureMapTypeDiffuse,
+ ETextureMapTypeOpacity,
+ ETextureMapTypeSpecular,
+ ETextureMapTypeEmissive
+} ETextureMapType;
+
+typedef enum _EMatCommonProfileTechnique {
+ EMatCommonProfileTechnique_Blinn,
+ EMatCommonProfileTechnique_Constant,
+ EMatCommonProfileTechnique_Lambert,
+ EMatCommonProfileTechnique_Phong,
+ EMatCommonProfileTechnique_Count
+} EMatCommonProfileTechnique;
+
+typedef enum _EMatOpaqueType // refer to domFx_opaque_enum
+{ EMatOpaqueType_A_ONE, // When a transparent opaque attribute is set to A_ONE, it means the
+ // transparency information will be taken from the alpha channel of the
+ // color, texture, or parameter supplying the value. The value of 1.0 is
+ // opaque in this mode.
+ EMatOpaqueType_RGB_ZERO, // When a transparent opaque attribute is set to RGB_ZERO, it means the
+ // transparency information will be taken from the red, green, and blue
+ // channels of the color, texture, or parameter supplying the value. Each
+ // channel is modulated independently. The value of 0.0 is opaque in this
+ // mode.
+} EMatOpaqueType;
+
+typedef struct _SFloatFlag
+{
+ float m_Value; // the value of this struct
+ bool m_Flag; // to indicate if this value presents in SceneGraph
+ _SFloatFlag()
+ : m_Value(0.0f)
+ , m_Flag(false)
+ {
+ }
+ void SetValue(float inValue)
+ {
+ m_Value = inValue;
+ m_Flag = true;
+ }
+} SFloatFlag;
+
+typedef struct _SLongFlag
+{
+ long m_Value; // the value of this struct
+ bool m_Flag; // to indicate if this value presents in SceneGraph
+ _SLongFlag()
+ : m_Value(0)
+ , m_Flag(false)
+ {
+ }
+ void SetValue(long inValue)
+ {
+ m_Value = inValue;
+ m_Flag = true;
+ }
+} SLongFlag;
+
+typedef struct _SColorOrTexture
+{
+ typedef enum _Type {
+ None, // This information doesn't present in SceneGraph or of Param Type
+ Color, // Color type
+ Texture, // Texture type
+ } Type;
+
+ Type m_Type;
+ float m_Color[4]; // the color, if present
+ _SColorOrTexture()
+ : m_Type(None)
+ {
+ m_Color[0] = m_Color[1] = m_Color[2] = m_Color[3] = 0.0f;
+ }
+ void SetColor(const float inColor[])
+ {
+ m_Color[0] = inColor[0];
+ m_Color[1] = inColor[1];
+ m_Color[2] = inColor[2];
+ m_Color[3] = inColor[3];
+ m_Type = Color;
+ }
+ void SetColor(float c0, float c1, float c2, float c3)
+ {
+ m_Color[0] = c0;
+ m_Color[1] = c1;
+ m_Color[2] = c2;
+ m_Color[3] = c3;
+ m_Type = Color;
+ }
+ void SetTexture() { m_Type = Texture; }
+} SColorOrTexture;
+
+//==============================================================================
+// To store information regarding texture parameters which normally stored under <extra> tag
+//==============================================================================
+typedef struct _STextureParameters
+{
+ SFloatFlag m_coverageU;
+ SFloatFlag m_coverageV;
+ SFloatFlag m_repeatU;
+ SFloatFlag m_repeatV;
+ SFloatFlag m_offsetU;
+ SFloatFlag m_offsetV;
+ SFloatFlag m_rotateUV;
+ SLongFlag m_wrapU;
+ SLongFlag m_wrapV;
+ SLongFlag m_mirrorU;
+ SLongFlag m_mirrorV;
+ bool m_Flag; // to indicate if dae contains texture parameters information
+ _STextureParameters()
+ : m_Flag(false)
+ {
+ }
+} STextureParameters;
+
+//==============================================================================
+// To store information regarding material parameters which normally stored under <extra> tag
+//==============================================================================
+typedef struct _SMaterialExtraParameters
+{
+ SFloatFlag m_SpecLevel;
+ SFloatFlag m_EmissionLevel;
+ bool m_Flag; // to indicate if dae contains profile_COMMON technique extra information
+ _SMaterialExtraParameters()
+ : m_Flag(false)
+ {
+ }
+} SMaterialExtraParameters;
+
+//==============================================================================
+// To store information regarding material parameters which stored under profile_COMMON technique
+//==============================================================================
+typedef struct _SMaterialParameters
+{
+ EMatCommonProfileTechnique m_TechniqueType;
+ SColorOrTexture m_Emission;
+ SColorOrTexture m_Ambient;
+ SColorOrTexture m_Diffuse;
+ SColorOrTexture m_Specular;
+ SFloatFlag m_Shininess;
+ SColorOrTexture m_Reflective;
+ SFloatFlag m_Reflectivity;
+ SColorOrTexture m_Transparent;
+ SLongFlag m_TransparentOpaqueType;
+ SFloatFlag m_Transparency;
+ SFloatFlag m_Index_of_refraction;
+ SMaterialExtraParameters m_Extra;
+
+ _SMaterialParameters()
+ : m_TechniqueType(EMatCommonProfileTechnique_Count)
+ {
+ }
+ _SMaterialParameters(EMatCommonProfileTechnique inTechniqueType)
+ : m_TechniqueType(inTechniqueType)
+ {
+ }
+} SMaterialParameters;
+
+//==============================================================================
+// To store information regarding animation keyframes
+//==============================================================================
+typedef struct _SKeyframeParameters
+{
+ float m_KeyframeTime;
+ float m_Value;
+ float m_INTANGENTX;
+ float m_INTANGENTY;
+ float m_OUTTANGENTX;
+ float m_OUTTANGENTY;
+
+ _SKeyframeParameters(float inKeyframeTime, float inValue, float inINTANGENTX,
+ float inINTANGENTY, float inOUTTANGENTX, float inOUTTANGENTY)
+ : m_KeyframeTime(inKeyframeTime)
+ , m_Value(inValue)
+ , m_INTANGENTX(inINTANGENTX)
+ , m_INTANGENTY(inINTANGENTY)
+ , m_OUTTANGENTX(inOUTTANGENTX)
+ , m_OUTTANGENTY(inOUTTANGENTY)
+ {
+ }
+
+} SKeyframeParameters;
+
+//==============================================================================
+// To store information regarding skelatal animations
+//==============================================================================
+typedef struct _SJointInfo
+{
+ int m_JointID;
+ int m_ParentID;
+ float m_invBindPose[16];
+ float m_localToGlobalBoneSpace[16];
+
+ _SJointInfo(int jointIndex, int parentID, float *invBindPose, float *localToGlobal)
+ : m_JointID(jointIndex)
+ , m_ParentID(parentID)
+ {
+ ::memcpy(m_invBindPose, invBindPose, sizeof(float) * 16);
+ ::memcpy(m_localToGlobalBoneSpace, localToGlobal, sizeof(float) * 16);
+ }
+
+} SJointInfo;
+
+//==============================================================================
+// Templatized container for floats
+//==============================================================================
+template <size_t N>
+struct _SVector
+{
+ float m_Data[N];
+
+ bool operator<(const struct _SVector<N> &inVector) const
+ {
+ return ::memcmp(m_Data, inVector.m_Data, sizeof(m_Data)) < 0;
+ }
+
+ operator float *() { return m_Data; }
+
+ operator const float *() const { return m_Data; }
+};
+
+typedef struct _SVector<4> SVector4;
+typedef struct _SVector<3> SVector3;
+typedef struct _SVector<2> SVector2;
+
+class Import;
+
+typedef enum _EAuthoringToolType {
+ EAuthoringToolType_Unknown = 0,
+ EAuthoringToolType_NextGen_Max,
+ EAuthoringToolType_NextGen_Maya,
+ EAuthoringToolType_FCollada_Max,
+ EAuthoringToolType_FCollada_Maya,
+ EAuthoringToolType_SketchUp,
+ EAuthoringToolType_Cinema4D,
+ EAuthoringToolType_StudioCORE,
+ EAuthoringToolType_FBX_Max,
+ EAuthoringToolType_FBX_Modo,
+ EAuthoringToolType_FBX_Maya,
+} EAuthoringToolType;
+
+//==============================================================================
+// Function interfaces for a translation class to allow much easier (and typed)
+// data writing to the base import library.
+//==============================================================================
+class ISceneGraphTranslation
+{
+protected:
+ virtual ~ISceneGraphTranslation() {}
+
+public:
+ virtual void Release() = 0;
+
+ virtual void SetAuthoringTool(EAuthoringToolType inAuthoringToolType,
+ long inAuthoringToolVersion) = 0;
+
+ virtual void PushGroup(const char *inName) = 0;
+ virtual void SetGroupSkeletonId(long inId) = 0;
+ virtual void SetIgnoresParentTransform(bool inValue) = 0;
+ virtual void PopGroup() = 0;
+ virtual void PushModel(const char *inName) = 0;
+ virtual void SetModelSkeletonRoot(long inId) = 0;
+ virtual void PopModel() = 0;
+ virtual void PushMaterial(const char *inName) = 0;
+ virtual void PopMaterial(long inStartFaceIndex, long inNumberOfFaces) = 0;
+ virtual void PushTexture(const char *inName, const char *inSourcePath, long inMapType) = 0;
+ virtual void PopTexture() = 0;
+
+ // Translation failed, mark top object as invalid.
+ virtual void MarkInvalid() = 0;
+
+ virtual void SetTransforms(const TTransformList &inTransforms) = 0;
+ virtual void SetGeometry(TFloatsList &ioVertices, TFloatsList &ioNormals,
+ TFloatsList &ioTexCoords, TFloatsList &ioTexCoords2,
+ TFloatsList &ioTexTangents, TFloatsList &ioTexBinormals,
+ TFloatsList &ioWeights, TFloatsList &ioBoneIndex,
+ TLongsList &ioFaceIndicies) = 0;
+ virtual void SetMaterial(const SMaterialParameters &inMaterialParameters) = 0;
+ virtual void SetTexture(long inMapType, const STextureParameters &inTextureParameters) = 0;
+ virtual void SetJointNode(SJointInfo &inJointInfo) = 0;
+
+ virtual long CacheAnimationTrack() = 0;
+ virtual void ApplyAnimationTrack(long inAnimationTrackIndex) = 0;
+ virtual void SetAnimationTrack(const char *inBasePropertyName,
+ const char *inSubPropertyName) = 0;
+ virtual void CacheAnimationKey(const char *inBaseProperty, const char *inSubPropertyName,
+ const SKeyframeParameters &inParameters) = 0;
+
+ virtual void LogWarning(ESceneGraphWarningCode inWarningCode, const char *inAssociatedName) = 0;
+
+ static ISceneGraphTranslation &CreateTranslation(Import &import, ISGTranslationLog &log);
+};
+}
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslation.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslation.h
new file mode 100644
index 00000000..67e7fb5e
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslation.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+#ifndef UICIMPORTTRANSLATIONH
+#define UICIMPORTTRANSLATIONH
+
+#include "qtAuthoring-config.h"
+#include "UICImportPerformImport.h"
+
+namespace UICIMP {
+
+class Import;
+
+typedef enum _ESceneGraphWarningCode {
+ ESceneGraphWarningCode_OnlySupportTriangles, ///< Model contains geometric elements other than
+ ///triangles (note that this won't throw exception,
+ ///just pop up warning)
+ ESceneGraphWarningCode_TrianglesDuplicateSemantic, ///< Triangle contains duplicate semantics,
+ ///ex: 1 triangle has multiple TEXCOORD
+ ///(multiple UV maps)
+ ESceneGraphWarningCode_VertexBufferTooLarge, ///< Triangle contains duplicate semantics, ex: 1
+ ///triangle has multiple TEXCOORD (multiple UV
+ ///maps)
+ ESceneGraphWarningCode_MissingSourceFile, ///< Couldn't find a source image file
+ ESceneGraphWarningCode_LockedDestFile, ///< An image or mesh file we need to write to is not
+ ///writeable.
+ ESceneGraphWarningCode_Generic, ///< For generic warnings
+} ESceneGraphWarningCode;
+
+class ISGTranslationLog
+{
+protected:
+ virtual ~ISGTranslationLog() {}
+public:
+ virtual void OnWarning(ESceneGraphWarningCode inWarningCode,
+ const wchar_t *inAssociatedName) = 0;
+};
+
+#ifdef UICIMPORT_TRANSLATION_INTERNAL
+#define EXPORT_FUNCTION
+#else
+#define EXPORT_FUNCTION
+#endif
+
+class CImportTranslation
+{
+public:
+ static inline const wchar_t *GetRootNodeId() { return L"__import__root__"; }
+ // Parse the collada file, marking when things don't line up correctly.
+ // Translate a collada file into an import datastructure.
+ static EXPORT_FUNCTION bool ParseColladaFile(const std::string &fileName, Import &import,
+ ISGTranslationLog &log);
+#ifdef QT_3DSTUDIO_FBX
+ // Parse the FBX file.
+ // Translate a FBX file into an import datastructure.
+ static EXPORT_FUNCTION bool ParseFbxFile(const std::string &fileName, Import &import,
+ ISGTranslationLog &log);
+#endif
+};
+
+struct STranslationLog : public UICIMP::ISGTranslationLog
+{
+ vector<pair<UICIMP::ESceneGraphWarningCode, Q3DStudio::CString>> m_Warnings;
+ void OnWarning(UICIMP::ESceneGraphWarningCode inWarningCode,
+ const wchar_t *inAssociatedName) override
+ {
+ m_Warnings.push_back(std::make_pair(inWarningCode, inAssociatedName));
+ }
+};
+
+struct SColladaTranslator : public UICIMP::ITranslator
+{
+ QString m_SourceFile;
+ STranslationLog m_TranslationLog;
+
+ SColladaTranslator(const QString& srcFile)
+ : m_SourceFile(srcFile)
+ {
+ }
+
+ // Object is created on the stack, no reason to release.
+ void Release() override {}
+
+ const QString &GetSourceFile() override { return m_SourceFile; }
+ // Returning false causes the rest of the import or refresh process
+ // to fail.
+ bool PerformTranslation(Import &import) override
+ {
+ return CImportTranslation::ParseColladaFile(m_SourceFile.toStdString(), import,
+ m_TranslationLog);
+ }
+};
+
+#ifdef QT_3DSTUDIO_FBX
+struct SFbxTranslator : public UICIMP::ITranslator
+{
+ QString m_SourceFile;
+ STranslationLog m_TranslationLog;
+
+ SFbxTranslator(const QString& srcFile)
+ : m_SourceFile(srcFile)
+ {
+ }
+
+ // Object is created on the stack, no reason to release.
+ void Release() override {}
+
+ const QString &GetSourceFile() override { return m_SourceFile; }
+ // Returning false causes the rest of the import or refresh process
+ // to fail.
+ bool PerformTranslation(Import &import) override
+ {
+ return CImportTranslation::ParseFbxFile(m_SourceFile.toStdString(), import,
+ m_TranslationLog);
+ }
+};
+#endif
+}
+#endif
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslationCommon.h b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslationCommon.h
new file mode 100644
index 00000000..3e83c8a8
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/UICImportTranslationCommon.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include <vector>
+#include <string>
+
+namespace UICIMP {
+
+typedef std::vector<long> TLongsList;
+typedef std::vector<float> TFloatsList;
+typedef std::vector<std::string> TStringList;
+
+static const char *ST[] = { "S", "T" };
+static const char *XY[] = { "X", "Y" };
+static const char *XYZ[] = { "X", "Y", "Z" };
+static const char *XYZANGLE[] = { "X", "Y", "Z", "ANGLE" };
+static const char *RGBA[] = { "R", "G", "B", "A" };
+static const char *TIME[] = { "TIME" };
+static const char *SINGLEFLOAT[] = { "F" };
+
+static const TStringList g_STIdentifiers(ST, ST + sizeof(ST) / sizeof(*ST));
+static const TStringList g_XYIdentifiers(XY, XY + sizeof(XY) / sizeof(*XY));
+static const TStringList g_XYZIdentifiers(XYZ, XYZ + sizeof(XYZ) / sizeof(*XYZ));
+static const TStringList g_XYZANGLEIdentifiers(XYZANGLE,
+ XYZANGLE + sizeof(XYZANGLE) / sizeof(*XYZANGLE));
+static const TStringList g_RGBAIdentifiers(RGBA, RGBA + sizeof(RGBA) / sizeof(*RGBA));
+static const TStringList g_TIMEIdentifiers(TIME, TIME + sizeof(TIME) / sizeof(*TIME));
+static const TStringList g_FLOATIdentifiers(SINGLEFLOAT, SINGLEFLOAT
+ + sizeof(SINGLEFLOAT) / sizeof(*SINGLEFLOAT));
+} \ No newline at end of file
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/stdafx.cpp b/src/Authoring/UICIMP/UICImportSGTranslation/stdafx.cpp
new file mode 100644
index 00000000..7d91494b
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/stdafx.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// UICImportSGTranslation.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/Authoring/UICIMP/UICImportSGTranslation/stdafx.h b/src/Authoring/UICIMP/UICImportSGTranslation/stdafx.h
new file mode 100644
index 00000000..a84c11ea
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportSGTranslation/stdafx.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include <QtGlobal>
+
+#ifdef WIN32
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT \
+ 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#endif
+
+#ifndef _WIN32
+typedef void *HANDLE;
+#endif
+
+#include <assert.h>
+#ifndef ASSERT
+#define ASSERT(a) assert(a)
+#endif
+
+#ifdef WIN32
+#pragma warning(disable : 4819)
+#endif
+#include "UICImportLibPrecompile.h"
+#include "PlatformTypes.h"
+
+#define SAFE_DELETE(ptr) \
+ if ((ptr) != NULL) { \
+ delete (ptr); \
+ (ptr) = NULL; \
+ }
+// TODO: reference additional headers your program requires here
diff --git a/src/Authoring/UICIMP/UICImportStudioLib/stdafx.cpp b/src/Authoring/UICIMP/UICImportStudioLib/stdafx.cpp
new file mode 100644
index 00000000..129378bc
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportStudioLib/stdafx.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// UICImportStudioLib.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/Authoring/UICIMP/UICImportStudioLib/stdafx.h b/src/Authoring/UICIMP/UICImportStudioLib/stdafx.h
new file mode 100644
index 00000000..382263fe
--- /dev/null
+++ b/src/Authoring/UICIMP/UICImportStudioLib/stdafx.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT \
+ 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+#include "UICImportLibPrecompile.h"
+
+// TODO: reference additional headers your program requires here
diff --git a/src/Authoring/commoninclude.pri b/src/Authoring/commoninclude.pri
new file mode 100644
index 00000000..a27e20cf
--- /dev/null
+++ b/src/Authoring/commoninclude.pri
@@ -0,0 +1,49 @@
+include($$PWD/../commonplatform.pri)
+
+contains(TEMPLATE, lib) {
+ load(qt_helper_lib)
+ # qt_helper_lib assumes non-qt lib, so it clears qt from config - reset that
+ CONFIG += qt exceptions
+ QT += core gui
+}
+
+# Prevents problems with boost signals and qt signals macros conflicting
+CONFIG += no_keywords
+
+# TODO: Investigate whether these can be moved to commonplatform
+win32 {
+ QMAKE_CXXFLAGS += /EHsc /GA
+ QMAKE_CFLAGS += /EHsc /GA
+}
+
+INCLUDEPATH += $$PWD/../Runtime/Source
+
+win32 {
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/PlatformSpecific/Windows/PlatformLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Windows/PlatformLibs \
+ $$PWD/../Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Windows/Qt3DSLibs
+}
+
+linux {
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/PlatformSpecific/Linux/PlatformLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Linux/PlatformLibs \
+ $$PWD/../Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs
+}
+
+macos {
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/PlatformSpecific/Macos/PlatformLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Macos/PlatformLibs \
+ $$PWD/../Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs
+
+}
+android {
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs
+ $$PWD/../Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread
+}
diff --git a/src/Authoring/configure.json b/src/Authoring/configure.json
new file mode 100644
index 00000000..768fbdef
--- /dev/null
+++ b/src/Authoring/configure.json
@@ -0,0 +1,60 @@
+{
+ "module": "Authoring",
+ "testDir": "../../config.tests",
+
+ "libraries": {
+ "fbx": {
+ "label": "Autodesk FBX",
+ "test": "fbx",
+ "comment": "Specify FBX SDK location with FBXSDK env variable, if not in 3rdparty folder",
+ "sources": [
+ {
+ "type": "fbx",
+ "libs": "-lfbxsdk",
+ "compiler": "clang",
+ "condition": "config.osx"
+ },
+ {
+ "type": "fbx",
+ "libs": "-lfbxsdk",
+ "compiler": "gcc4",
+ "condition": "config.linux"
+ },
+ {
+ "comment": "This is custom library path/naming for old provisioning",
+ "type": "fbx",
+ "debuglibs": "-llibfbxsdk-mdd",
+ "releaselibs": "-llibfbxsdk-md",
+ "compiler": "vs2015",
+ "condition": "config.win32"
+ },
+ {
+ "type": "fbx",
+ "libs": "-llibfbxsdk-md",
+ "compiler": "vs2015",
+ "condition": "config.win32"
+ }
+ ]
+ }
+ },
+
+ "features": {
+ "qt3dstudio-fbx": {
+ "label": "Autodesk FBX",
+ "condition": "libs.fbx",
+ "output": [
+ "privateFeature",
+ { "type": "define", "name": "QT_3DSTUDIO_FBX" }
+ ]
+ }
+ },
+
+ "summary": [
+ {
+ "section": "Qt 3D Studio dependencies",
+ "entries": [
+ "qt3dstudio-fbx"
+ ]
+ }
+ ]
+}
diff --git a/src/Authoring/configure.pri b/src/Authoring/configure.pri
new file mode 100644
index 00000000..87577a5d
--- /dev/null
+++ b/src/Authoring/configure.pri
@@ -0,0 +1,53 @@
+defineTest(qtConfLibrary_fbx) {
+ libs = $$eval($${1}.libs)
+ compiler = $$eval($${1}.compiler)
+ includedir =
+
+ CONFIG(debug, debug|release) {
+ isEmpty(libs) {
+ libs = $$eval($${1}.debuglibs)
+ } else {
+ build = /debug
+ }
+ } else {
+ isEmpty(libs) {
+ libs = $$eval($${1}.releaselibs)
+ } else {
+ build = /release
+ }
+ }
+
+ contains(QT_ARCH, x86_64) {
+ !macos: architecture = /x64
+ } else {
+ !macos: architecture = /x86
+ }
+
+ fbx_sdk = $$getenv(FBXSDK)
+
+ isEmpty(fbx_sdk) {
+ # Expect FBX libs and headers to be in our 3rdparty folder, as that's
+ # the only place we look for FBX in the build
+ THIRDPARTY_DIR = $$getenv(QT3DSTUDIO_3RDPARTY_DIR)
+ isEmpty(THIRDPARTY_DIR) {
+ THIRDPARTY_DIR = $$_PRO_FILE_PWD_/src/3rdparty
+ }
+ exists($$THIRDPARTY_DIR/FBX/2016.1.2) {
+ fbx_sdk = $$THIRDPARTY_DIR/FBX/2016.1.2
+ }
+ }
+
+ !isEmpty(fbx_sdk) {
+ includedir += $${fbx_sdk}/include
+ libs += "-L$${fbx_sdk}/lib/$${compiler}$${architecture}$${build}"
+ }
+
+ $${1}.libs = $$val_escape(libs)
+ $${1}.includedir = $$val_escape(includedir)
+
+ export($${1}.libs)
+ export($${1}.includedir)
+
+ return(true)
+}
+
diff --git a/src/Authoring/licensehandler.pro b/src/Authoring/licensehandler.pro
new file mode 100644
index 00000000..b7aa411f
--- /dev/null
+++ b/src/Authoring/licensehandler.pro
@@ -0,0 +1,16 @@
+isEmpty(TQTC_LICENSE_MANAGING): TQTC_LICENSE_MANAGING=$$(TQTC_LICENSE_MANAGING)
+!isEmpty(TQTC_LICENSE_MANAGING) {
+ include($$TQTC_LICENSE_MANAGING/studio3d/licensehandler.pri)
+}
+
+TEMPLATE = lib
+TARGET = $$qtLibraryTarget(licensehandler)
+
+DEFINES += LICENSE_HANDLER_AS_DLL LICENSE_HANDLER_EXPORTS
+
+target.path = $$[QT_INSTALL_LIBS]
+dlltarget.path = $$[QT_INSTALL_BINS]
+INSTALLS += target dlltarget
+
+DESTDIR = $$[QT_INSTALL_LIBS]
+DLLDESTDIR = $$[QT_INSTALL_BINS]
diff --git a/src/Authoring/mfcconsole.cpp b/src/Authoring/mfcconsole.cpp
new file mode 100644
index 00000000..a0ae87c0
--- /dev/null
+++ b/src/Authoring/mfcconsole.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stdafx.h"
+#if 0
+#ifdef _DEBUG
+
+#pragma comment(linker, "/SUBSYSTEM:CONSOLE")
+
+#include <string.h>
+#include <stdio.h>
+#include <winsock2.h>
+#include <windows.h>
+
+extern "C"
+{
+ int PASCAL WinMain(HINSTANCE inst,HINSTANCE dumb,LPSTR param,int show);
+};
+
+int main(int ac,char *av[])
+{
+ char buf[256];
+ int i;
+ HINSTANCE inst;
+
+ inst = (HINSTANCE)GetModuleHandle(NULL);
+
+ buf[0] = 0;
+ for(i = 1; i < ac; i++)
+ {
+ strcat_s(buf, 256, av[i]);
+ strcat_s(buf, 256, " ");
+ //strcat(buf,av[i]);
+ //strcat(buf," ");
+ }
+
+ return WinMain(inst, NULL, buf, SW_SHOWNORMAL);
+}
+
+#endif _DEBUG
+#endif
diff --git a/src/Authoring/qml.qrc b/src/Authoring/qml.qrc
new file mode 100644
index 00000000..e23639f2
--- /dev/null
+++ b/src/Authoring/qml.qrc
@@ -0,0 +1,42 @@
+<RCC>
+ <qresource prefix="/">
+ <file>Studio/Palettes/Action/ActionView.qml</file>
+ <file>Studio/Palettes/BasicObjects/BasicObjectsView.qml</file>
+ <file>Studio/Palettes/Slide/SlideView.qml</file>
+ <file>Studio/Palettes/Inspector/InspectorControlView.qml</file>
+ <file>Studio/Palettes/Inspector/ObjectBrowser.qml</file>
+ <file>Studio/Palettes/Action/HandlerEmitSignal.qml</file>
+ <file>Studio/Palettes/Action/HandlerGenericText.qml</file>
+ <file>Studio/Palettes/Action/HandlerFireEvent.qml</file>
+ <file>Studio/Palettes/Action/HandlerGenericCheckbox.qml</file>
+ <file>Studio/Palettes/Action/HandlerGoToSlide.qml</file>
+ <file>Studio/Palettes/Action/EventsBrowser.qml</file>
+ <file>Studio/Palettes/Action/HandlerPropertyXYZ.qml</file>
+ <file>Studio/Palettes/Action/HandlerPropertySlider.qml</file>
+ <file>Studio/Palettes/Action/HandlerPropertyCombo.qml</file>
+ <file>Studio/Palettes/Action/HandlerProperty.qml</file>
+ <file>Studio/Palettes/Action/HandlerPropertyBaseXYZ.qml</file>
+ <file>Studio/Palettes/Action/HandlerPropertyBaseSlider.qml</file>
+ <file>Studio/Palettes/Action/HandlerGenericColor.qml</file>
+ <file>Studio/Palettes/Inspector/HandlerFilesChooser.qml</file>
+ <file>Studio/Palettes/Inspector/ImageChooser.qml</file>
+ <file>Studio/Palettes/Inspector/MeshChooser.qml</file>
+ <file>Studio/Palettes/Inspector/HandlerGenericChooser.qml</file>
+ <file>Studio/Palettes/Inspector/ObjectReference.qml</file>
+ <file>Studio/Palettes/Inspector/ChooserDelegate.qml</file>
+ <file>Studio/Palettes/Inspector/TextureChooser.qml</file>
+ <file>Studio/Palettes/Project/ProjectView.qml</file>
+ <file>Studio/Palettes/Action/HandlerMultilineText.qml</file>
+ <file>Studio/Palettes/Action/HandlerGenericBaseColor.qml</file>
+ <file>Studio/Palettes/Inspector/FileChooser.qml</file>
+ <file>Studio/Palettes/controls/StyledLabel.qml</file>
+ <file>Studio/Palettes/controls/StyledTextField.qml</file>
+ <file>Studio/Palettes/controls/FloatTextField.qml</file>
+ <file>Studio/Palettes/controls/StyledComboBox.qml</file>
+ <file>Studio/Palettes/controls/BrowserCombo.qml</file>
+ <file>Studio/Palettes/controls/StyledMenuItem.qml</file>
+ <file>Studio/Palettes/controls/StyledTooltip.qml</file>
+ <file>Studio/Palettes/controls/StyledToolButton.qml</file>
+ <file>Studio/Palettes/controls/StyledMenuSeparator.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/QtExtras/QtExtras.pro b/src/QtExtras/QtExtras.pro
new file mode 100644
index 00000000..36916d01
--- /dev/null
+++ b/src/QtExtras/QtExtras.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += qmlstreamer
diff --git a/src/QtExtras/qmlstreamer/q3dsincubationcontroller.h b/src/QtExtras/qmlstreamer/q3dsincubationcontroller.h
new file mode 100644
index 00000000..733037c6
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsincubationcontroller.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QCoreApplication>
+#include <QGuiApplication>
+#include <QQmlComponent>
+#include <QQuickItem>
+#include <QQmlIncubationController>
+#include <QScreen>
+
+class Q3DSIncubationController : public QObject, public QQmlIncubationController
+{
+ Q_OBJECT
+public:
+ explicit Q3DSIncubationController(QObject *parent = nullptr)
+ : QObject(parent)
+ , m_incubationTime(std::max(1, int(333 / QGuiApplication::primaryScreen()->refreshRate())))
+ {
+ startTimer(QGuiApplication::primaryScreen()->refreshRate());
+ }
+
+ void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE
+ {
+ incubateFor(m_incubationTime);
+ }
+
+private:
+ const int m_incubationTime;
+};
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstream.cpp b/src/QtExtras/qmlstreamer/q3dsqmlstream.cpp
new file mode 100644
index 00000000..ec231d83
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstream.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlstream.h"
+
+Q3DSQmlStream::Q3DSQmlStream(QObject *parent)
+ : QObject(parent)
+ , m_item(nullptr)
+{
+
+}
+
+Q3DSQmlStream::~Q3DSQmlStream()
+{
+
+}
+
+QString Q3DSQmlStream::presentationId() const
+{
+ return m_presentationId;
+}
+
+QQuickItem *Q3DSQmlStream::item() const
+{
+ return m_item;
+}
+
+void Q3DSQmlStream::setPresentationId(const QString presentationId)
+{
+ if (m_presentationId != presentationId) {
+ m_presentationId = presentationId;
+ emit presentationIdChanged(presentationId);
+ }
+}
+
+void Q3DSQmlStream::setItem(QQuickItem *item)
+{
+ if (m_item != item) {
+ m_item = item;
+ emit itemChanged(item);
+ }
+}
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstream.h b/src/QtExtras/qmlstreamer/q3dsqmlstream.h
new file mode 100644
index 00000000..74825902
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstream.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAM_H
+#define Q3DS_QMLSTREAM_H
+
+#include <QObject>
+
+#include "q3dsqmlstreamer_global.h"
+
+QT_BEGIN_NAMESPACE
+class QQuickItem;
+QT_END_NAMESPACE
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT Q3DSQmlStream : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString presentationId READ presentationId WRITE setPresentationId NOTIFY presentationIdChanged)
+ Q_PROPERTY(QQuickItem *item READ item WRITE setItem NOTIFY itemChanged)
+
+ Q_CLASSINFO("DefaultProperty", "item")
+public:
+ Q3DSQmlStream(QObject *parent = nullptr);
+ ~Q3DSQmlStream();
+
+ QString presentationId() const;
+ QQuickItem *item() const;
+
+public Q_SLOTS:
+ void setPresentationId(const QString presentationId);
+ void setItem(QQuickItem *item);
+
+Q_SIGNALS:
+ void presentationIdChanged(const QString presentationId);
+ void itemChanged(QQuickItem *item);
+
+private:
+ QString m_presentationId;
+ QQuickItem *m_item;
+};
+
+#endif // Q3DSQMLSTREAM_H
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamer_global.h b/src/QtExtras/qmlstreamer/q3dsqmlstreamer_global.h
new file mode 100644
index 00000000..af12e6f0
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamer_global.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAMER_GLOBAL_H
+#define Q3DS_QMLSTREAMER_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(QMLSTREAMER_LIBRARY)
+# define Q3DS_QMLSTREAMERSHARED_EXPORT Q_DECL_EXPORT
+#else
+# define Q3DS_QMLSTREAMERSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // Q3DS_QMLSTREAMER_GLOBAL_H
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.cpp b/src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.cpp
new file mode 100644
index 00000000..78c0a36a
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlstreamerserviceimpl.h"
+
+Q3DSQmlStreamServiceImpl::Q3DSQmlStreamServiceImpl()
+{
+
+}
+
+IQ3DSQmlStreamRenderer *Q3DSQmlStreamServiceImpl::getRenderer(const char *id)
+{
+ if (m_producers[QString(id)])
+ return m_producers[QString(id)]->getRenderer();
+ return nullptr;
+}
+
+bool Q3DSQmlStreamServiceImpl::registerProducer(IQ3DSQmlStreamProducer *producer, const char *id)
+{
+ m_producers[QString(id)] = producer;
+ return true;
+}
+
+void Q3DSQmlStreamServiceImpl::unregisterProducer(IQ3DSQmlStreamProducer *producer)
+{
+ auto iter = m_producers.begin();
+ for (; iter != m_producers.end(); ++iter) {
+ if (*iter == producer) {
+ m_producers.erase(iter);
+ return;
+ }
+ }
+}
+
+static Q3DSQmlStreamServiceImpl *service = nullptr;
+IQ3DSQmlStreamService *IQ3DSQmlStreamService::getQmlStreamService()
+{
+ if (!service)
+ service = new Q3DSQmlStreamServiceImpl();
+ return service;
+}
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.h b/src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.h
new file mode 100644
index 00000000..a17bf340
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamerserviceimpl.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAM_SERVICE_IMPL_H
+#define Q3DS_QMLSTREAM_SERVICE_IMPL_H
+
+#include <QMap>
+
+#include "q3dsqmlstreamservice.h"
+
+#include "q3dsqmlstreamer_global.h"
+
+class Q3DSQmlStreamServiceImpl : public IQ3DSQmlStreamService
+{
+public:
+ Q3DSQmlStreamServiceImpl();
+
+ IQ3DSQmlStreamRenderer *getRenderer(const char *id) override;
+ bool registerProducer(IQ3DSQmlStreamProducer *producer, const char *id) override;
+ void unregisterProducer(IQ3DSQmlStreamProducer *producer) override;
+private:
+
+ QMap<QString, IQ3DSQmlStreamProducer *> m_producers;
+};
+
+#endif // Q3DS_QMLSTREAMER_SERVICE_IMPL_H
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.cpp b/src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.cpp
new file mode 100644
index 00000000..39eccb1b
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlstreamproducer.h"
+#include "q3dsqmlstreamrenderer.h"
+
+Q3DSQmlStreamProducer::Q3DSQmlStreamProducer(const QString &id, const QString &args,
+ QObject *parent)
+ : QObject(parent), m_id(id), m_args(args), m_renderer(new Q3DSQmlStreamRenderer)
+{
+
+}
+
+Q3DSQmlStreamProducer::~Q3DSQmlStreamProducer()
+{
+ delete m_renderer;
+}
+
+IQ3DSQmlStreamRenderer* Q3DSQmlStreamProducer::getRenderer()
+{
+ return m_renderer;
+}
+
+void Q3DSQmlStreamProducer::setPresentationItem(QQuickItem *item)
+{
+ m_renderer->setItem(item);
+}
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.h b/src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.h
new file mode 100644
index 00000000..d3b330d1
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamproducer.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAM_PRODUCER_H
+#define Q3DS_QMLSTREAM_PRODUCER_H
+
+#include <QObject>
+#include "q3dsqmlstreamservice.h"
+#include "q3dsqmlstreamer_global.h"
+
+QT_BEGIN_NAMESPACE
+class QQuickItem;
+QT_END_NAMESPACE
+
+class Q3DSQmlStreamRenderer;
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT Q3DSQmlStreamProducer : public QObject,
+ public IQ3DSQmlStreamProducer
+{
+ Q_OBJECT
+public:
+ Q3DSQmlStreamProducer(const QString &id, const QString &args, QObject *parent = nullptr);
+ virtual ~Q3DSQmlStreamProducer();
+
+ IQ3DSQmlStreamRenderer* getRenderer() override;
+
+ void setPresentationItem(QQuickItem *item);
+
+private:
+ QString m_id;
+ QString m_args;
+ Q3DSQmlStreamRenderer *m_renderer;
+};
+
+#endif // Q3DS_QMLSTREAM_PRODUCER_H
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.cpp b/src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.cpp
new file mode 100644
index 00000000..4c115f28
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlstreamservice.h"
+#include "q3dsqmlstreamproxy.h"
+#include "q3dsqmlstreamproducer.h"
+#include "q3dsincubationcontroller.h"
+
+#include <QCoreApplication>
+#include <QGuiApplication>
+#include <QQmlComponent>
+#include <QQuickItem>
+#include <QQmlIncubationController>
+#include <QScreen>
+#include <QFileInfo>
+
+class Qt3DSQmlStreamEvent : public QEvent
+{
+public:
+ Qt3DSQmlStreamEvent(const QString &id, const QString &args)
+ : QEvent(QEvent::User), presentationId(id), presentationArgs(args)
+ {
+
+ }
+ QString presentationId;
+ QString presentationArgs;
+};
+
+Q3DSQmlStreamProxy::renderitem::~renderitem()
+{
+ delete item;
+ delete component;
+}
+
+Q3DSQmlStreamProxy::Q3DSQmlStreamProxy(QObject *parent)
+ : QObject(parent), m_engine(nullptr), m_settings(nullptr)
+{
+}
+
+Q3DSQmlStreamProxy::~Q3DSQmlStreamProxy()
+{
+ for (Q3DSQmlStreamProducer *p : m_streamProducers) {
+ IQ3DSQmlStreamService::getQmlStreamService()->unregisterProducer(p);
+ delete p;
+ }
+}
+
+void Q3DSQmlStreamProxy::loadPresentationItem(const QString& presentationId,
+ const QString& presentationArgs)
+{
+ if (!m_engine) {
+ m_engine = new QQmlEngine;
+
+ // Add extra import path for binary installations
+ QString extraImportPath(QStringLiteral("%1/qml"));
+ m_engine->addImportPath(extraImportPath.arg(QGuiApplication::applicationDirPath()));
+
+ m_engine->setIncubationController(new Q3DSIncubationController(this));
+ }
+
+ QUrl purl = QUrl(presentationArgs);
+ if (purl.isRelative()) {
+ purl.setPath(m_path.path() + QStringLiteral("/") + purl.path());
+ purl.setScheme(m_path.scheme());
+ } else {
+ purl = pathToUrl(presentationArgs);
+ }
+
+ QQmlComponent *component = new QQmlComponent(m_engine, purl);
+ if (!component)
+ return;
+ renderitem *item = new renderitem;
+ item->args = presentationArgs;
+ item->component = component;
+ item->presentationId = presentationId;
+ m_loadedItems.push_back(item);
+
+ if (component->isLoading())
+ connect(component, &QQmlComponent::statusChanged, this, &Q3DSQmlStreamProxy::itemLoaded);
+ else
+ itemLoaded();
+}
+
+void Q3DSQmlStreamProxy::itemLoaded()
+{
+ for (renderitem *item : m_loadedItems) {
+ if (item->item == nullptr && item->component->isLoading() == false) {
+ disconnect(item->component, &QQmlComponent::statusChanged,
+ this, &Q3DSQmlStreamProxy::itemLoaded);
+ if (!item->component->errors().isEmpty()) {
+ QList<QQmlError> errorList = item->component->errors();
+ for (const QQmlError &error: errorList)
+ qWarning() << error.url() << error.line() << error;
+ m_loadedItems.removeAll(item);
+ delete item;
+ } else {
+ QObject *root = item->component->create();
+ if (!root) {
+ QList<QQmlError> errorList = item->component->errors();
+ for (const QQmlError &error: errorList)
+ qWarning() << error.url() << error.line() << error;
+ m_loadedItems.removeAll(item);
+ delete item;
+ } else {
+ QQuickItem *qi = qobject_cast<QQuickItem *>(root);
+ if (!qi) {
+ m_loadedItems.removeAll(item);
+ delete item;
+ } else {
+ item->item = qi;
+ m_streamProducers[item->presentationId]->setPresentationItem(qi);
+ }
+ }
+ }
+ }
+ }
+}
+
+QUrl Q3DSQmlStreamProxy::pathToUrl(const QString &path)
+{
+ QUrl retval;
+ if (path.startsWith(QStringLiteral(":"))) {
+ retval.setScheme(QStringLiteral("qrc"));
+ retval.setPath(QStringLiteral("//") + path.mid(1));
+ } else if (path.startsWith(QStringLiteral("qrc:"), Qt::CaseInsensitive)) {
+ retval.setScheme(QStringLiteral("qrc"));
+ retval.setPath(path.mid(4));
+ } else {
+ retval.setScheme(QStringLiteral("file"));
+ retval.setPath(QStringLiteral("//") + path);
+ }
+ return retval;
+}
+
+bool Q3DSQmlStreamProxy::event(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+ Qt3DSQmlStreamEvent *e = static_cast<Qt3DSQmlStreamEvent *>(event);
+ Q3DSQmlStreamProducer *producer = nullptr;
+ if (!m_streamProducers[e->presentationId]) {
+ producer = new Q3DSQmlStreamProducer(e->presentationId, e->presentationArgs, this);
+ m_streamProducers[e->presentationId] = producer;
+ IQ3DSQmlStreamService::getQmlStreamService()
+ ->registerProducer(producer, e->presentationId.toLatin1().data());
+ } else {
+ producer = static_cast<Q3DSQmlStreamProducer *>(m_streamProducers[e->presentationId]);
+ }
+
+ if (m_settings) {
+ for (Q3DSQmlStream *s : m_settings->qmlStreamsList()) {
+ if (s->presentationId() == e->presentationId) {
+ producer->setPresentationItem(s->item());
+ break;
+ }
+ }
+ } else if (!e->presentationArgs.isNull()){
+ loadPresentationItem(e->presentationId, e->presentationArgs);
+ }
+ return true;
+ }
+ return false;
+}
+
+void Q3DSQmlStreamProxy::registerPresentation(const QString &presentationId, const QString &args)
+{
+ QCoreApplication::postEvent(this,
+ new Qt3DSQmlStreamEvent(QString(presentationId), QString(args)));
+}
+
+void Q3DSQmlStreamProxy::setSettings(Q3DSSubPresentationSettings *settings)
+{
+ m_settings = settings;
+}
+
+void Q3DSQmlStreamProxy::setPath(const QString& path)
+{
+ QFileInfo fi(path);
+ QString modPath = fi.path(); // Strip filename out
+ m_path = pathToUrl(modPath);
+}
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.h b/src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.h
new file mode 100644
index 00000000..4576b836
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamproxy.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAM_PROXY_H
+#define Q3DS_QMLSTREAM_PROXY_H
+
+#include <QtCore/QObject>
+#include <QtCore/QEvent>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtQml/QQmlEngine>
+
+#include "q3dsqmlstreamproducer.h"
+#include "q3dsqmlsubpresentationsettings.h"
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT Q3DSQmlStreamProxy : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q3DSQmlStreamProxy(QObject *parent = nullptr);
+ ~Q3DSQmlStreamProxy();
+
+ bool event(QEvent *event) Q_DECL_OVERRIDE;
+ void registerPresentation(const QString &presentationId, const QString &args);
+ void setSettings(Q3DSSubPresentationSettings *settings);
+ void setPath(const QString& path);
+
+private:
+ void loadPresentationItem(const QString& presentationId, const QString& presentationArgs);
+ void itemLoaded();
+ QUrl pathToUrl(const QString &path);
+
+ QQmlEngine *m_engine;
+ Q3DSSubPresentationSettings *m_settings;
+ QMap<QString, Q3DSQmlStreamProducer *> m_streamProducers;
+ struct renderitem {
+ QString args;
+ QString presentationId;
+ QQmlComponent *component;
+ QQuickItem *item;
+ renderitem()
+ : component(nullptr), item(nullptr) {}
+ ~renderitem();
+ };
+
+ QUrl m_path;
+ QVector<renderitem *> m_loadedItems;
+};
+
+#endif // Q3DS_QMLSTREAM_PROXY_H
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.cpp b/src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.cpp
new file mode 100644
index 00000000..0f8c256c
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlstreamrenderer.h"
+
+#include <QCoreApplication>
+#include <qdebug.h>
+#include <QOpenGLContext>
+#include <QSurface>
+#include <QPainter>
+#include <QOpenGLFunctions>
+#include <QWindow>
+#include <QQuickWindow>
+#include <QQuickRenderControl>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlContext>
+#include <QQuickWindow>
+#include <QQuickItem>
+#include <QThread>
+#include <QOffscreenSurface>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLShaderProgram>
+#include <QOpenGLBuffer>
+#include <QOpenGLVertexArrayObject>
+
+Q_GLOBAL_STATIC(QThread, renderThread)
+Q_GLOBAL_STATIC(QAtomicInt, renderThreadClientCount)
+
+#define RenderEvent(name, value) \
+ class name : public QEvent \
+ { \
+ public: \
+ name() : QEvent(_type) {} \
+ static const QEvent::Type _type; \
+ }; \
+ const QEvent::Type name::_type = QEvent::Type(value);
+
+RenderEvent(InitializeRender, QEvent::User + 1)
+RenderEvent(RequestUpdate, QEvent::User + 2)
+RenderEvent(InitializeRenderThread, QEvent::User + 3)
+RenderEvent(PrepareRender, QEvent::User + 4)
+RenderEvent(Cleanup, QEvent::User + 5)
+
+#define EventType(e) (e::_type)
+
+class RenderControl : public QQuickRenderControl
+{
+public:
+ RenderControl(QWindow *w)
+ : m_window(w)
+ {
+ }
+
+ QWindow *renderWindow(QPoint *offset) Q_DECL_OVERRIDE
+ {
+ if (offset)
+ *offset = QPoint(0, 0);
+ return m_window;
+ }
+
+private:
+ QWindow *m_window;
+};
+
+Q3DSQmlStreamEventHandler::Q3DSQmlStreamEventHandler(Q3DSQmlStreamRenderer *renderer)
+ : m_renderer(renderer)
+{
+
+}
+
+bool Q3DSQmlStreamEventHandler::event(QEvent *e)
+{
+ switch (e->type()) {
+
+ case EventType(RequestUpdate): {
+ m_renderer->renderTexture();
+ return true;
+ }
+
+ case EventType(InitializeRenderThread): {
+ m_renderer->initializeRender();
+ return true;
+ }
+
+ case EventType(Cleanup): {
+ m_renderer->cleanup();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return QObject::event(e);
+}
+
+Q3DSQmlStreamRenderer::Q3DSQmlStreamRenderer()
+ : m_renderControl(nullptr)
+ , m_quickWindow(nullptr)
+ , m_rootItem(nullptr)
+ , m_frameBuffer(nullptr)
+ , m_program(nullptr)
+ , m_vao(nullptr)
+ , m_vertices(nullptr)
+ , m_context(nullptr)
+ , m_offscreenSurface(nullptr)
+ , m_renderObject(nullptr)
+ , m_renderThread(nullptr)
+ , m_requestRender(false)
+ , m_initialized(false)
+ , m_prepared(false)
+ , m_renderControlInitialized(false)
+ , m_update(false)
+{
+ renderThreadClientCount->fetchAndAddAcquire(1);
+
+ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
+ if (QOpenGLContext::currentContext())
+ format = QOpenGLContext::currentContext()->format();
+ else {
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+ }
+
+ m_offscreenSurface = new QOffscreenSurface;
+ m_offscreenSurface->setFormat(format);
+ m_offscreenSurface->create();
+
+ m_renderControl = new RenderControl(nullptr);
+ m_quickWindow = new QQuickWindow(m_renderControl);
+
+ m_renderObject = new Q3DSQmlStreamEventHandler(this);
+ renderThread->setObjectName(QStringLiteral("Qt3DSQmlStreamRenderer::renderThread"));
+ m_renderThread = renderThread;
+
+ m_renderObject->moveToThread(m_renderThread);
+ if (!m_renderThread->isRunning())
+ m_renderThread->start();
+}
+
+Q3DSQmlStreamRenderer::~Q3DSQmlStreamRenderer()
+{
+ QMutexLocker lock(&m_mutex);
+ QCoreApplication::postEvent(m_renderObject, new Cleanup());
+ m_waitCondition.wait(&m_mutex);
+
+ delete m_offscreenSurface;
+ delete m_renderControl;
+ delete m_quickWindow;
+ delete m_renderObject;
+
+ renderThreadClientCount->fetchAndSubAcquire(1);
+ if (renderThreadClientCount->load() == 0)
+ renderThread->quit();
+}
+
+void Q3DSQmlStreamRenderer::cleanup()
+{
+ if (m_context)
+ m_context->makeCurrent(m_offscreenSurface);
+ if (m_renderControl)
+ m_renderControl->invalidate();
+
+ delete m_frameBuffer;
+ delete m_program;
+ delete m_vertices;
+
+ if (m_context)
+ m_context->doneCurrent();
+ delete m_context;
+
+ if (m_renderObject)
+ m_renderObject->moveToThread(QCoreApplication::instance()->thread());
+ m_waitCondition.wakeOne();
+}
+
+bool Q3DSQmlStreamRenderer::initialize(QOpenGLContext *context, QSurface *surface)
+{
+ if (m_initialized) {
+ Q_ASSERT(QOpenGLContext::areSharing(context, m_context));
+ return true;
+ }
+ m_context = new QOpenGLContext();
+ m_context->setShareContext(context);
+ m_context->setFormat(context->format());
+ m_context->create();
+
+ m_context->moveToThread(m_renderThread);
+
+ if (m_rootItem) {
+ m_rootItem->setParentItem(m_quickWindow->contentItem());
+ updateSizes();
+
+ connect(m_renderControl, &QQuickRenderControl::renderRequested,
+ this, &Q3DSQmlStreamRenderer::requestUpdate);
+ connect(m_renderControl, &QQuickRenderControl::sceneChanged,
+ this, &Q3DSQmlStreamRenderer::requestUpdate);
+
+ }
+ m_initialized = true;
+ // Initialize render thread
+ QCoreApplication::postEvent(m_renderObject,
+ new InitializeRenderThread());
+ return true;
+}
+void Q3DSQmlStreamRenderer::initializeFboCopy()
+{
+ m_program = new QOpenGLShaderProgram;
+ if (m_context->format().renderableType() == QSurfaceFormat::OpenGLES) {
+ static const char *vsSource =
+ "attribute highp vec4 pos;\n"
+ "attribute highp vec2 tc;\n"
+ "varying lowp vec2 texcoord;\n"
+ "void main() {\n"
+ " texcoord = tc;\n"
+ " gl_Position = pos;\n"
+ "}\n";
+ static const char *fsSource =
+ "varying highp vec2 texcoord;\n"
+ "uniform sampler2D sampler;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(sampler, texcoord);\n"
+ "}\n";
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vsSource);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fsSource);
+ } else {
+ static const char *vsSource =
+ "#version 150 core\n"
+ "in vec4 pos;\n"
+ "in vec2 tc;\n"
+ "out vec2 texcoord;\n"
+ "void main() {\n"
+ " texcoord = tc;\n"
+ " gl_Position = pos;\n"
+ "}\n";
+ static const char *fsSource =
+ "#version 150 core\n"
+ "in vec2 texcoord;\n"
+ "out vec4 fragColor;\n"
+ "uniform sampler2D sampler;\n"
+ "void main() {\n"
+ " fragColor = texture(sampler, texcoord);\n"
+ "}\n";
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vsSource);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fsSource);
+ }
+
+ m_program->bindAttributeLocation("pos", 0);
+ m_program->bindAttributeLocation("tc", 1);
+
+ if (!m_program->link())
+ qDebug () << "failed: " << m_program->log();
+
+ m_vertices = new QOpenGLBuffer;
+ m_vertices->create();
+ m_vertices->bind();
+
+ static const float vertices[] =
+ {
+ -1, -1, 0, 1, 0, 0,
+ 1, -1, 0, 1, 1, 0,
+ 1, 1, 0, 1, 1, 1,
+ -1, -1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 1, 1,
+ -1, 1, 0, 1, 0, 1,
+ };
+
+ m_vertices->allocate(vertices, sizeof(vertices));
+ m_vertices->release();
+}
+
+void Q3DSQmlStreamRenderer::initializeRender()
+{
+ m_context->makeCurrent(m_offscreenSurface);
+ m_renderControl->initialize(m_context);
+ m_context->doneCurrent();
+ QCoreApplication::postEvent(this, new PrepareRender());
+}
+
+QSize Q3DSQmlStreamRenderer::getDesiredSize()
+{
+ return m_size;
+}
+
+E_TEXTURE_FORMAT Q3DSQmlStreamRenderer::getDesiredFormat()
+{
+ return E_TEXTURE_RGBA8;
+}
+
+bool Q3DSQmlStreamRenderer::isUpdateRequested()
+{
+ return m_update;
+}
+
+// Called by stream renderer client when it stops using the renderer
+// TODO: We are sharing the context so stop using it.
+void Q3DSQmlStreamRenderer::uninitialize()
+{
+}
+
+void Q3DSQmlStreamRenderer::setItem(QQuickItem *item)
+{
+ m_rootItem = item;
+}
+
+bool Q3DSQmlStreamRenderer::event(QEvent *event)
+{
+ switch (event->type()) {
+
+ case EventType(PrepareRender): {
+
+ m_renderControl->prepareThread(m_renderThread);
+ m_prepared = true;
+
+ requestUpdate();
+
+ return true;
+ }
+
+ case EventType(RequestUpdate): {
+
+ m_renderControl->polishItems();
+ QMutexLocker lock(&m_mutex);
+ m_requestRender = true;
+ QCoreApplication::postEvent(m_renderObject, new RequestUpdate());
+ m_waitCondition.wait(&m_mutex);
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void Q3DSQmlStreamRenderer::updateSizes()
+{
+ if (m_rootItem->width() > 0 && m_rootItem->height() > 0) {
+ m_size = QSize(m_rootItem->width(), m_rootItem->height());
+ } else {
+ m_rootItem->setWidth(256);
+ m_rootItem->setHeight(256);
+ }
+
+ m_quickWindow->setGeometry(0, 0, m_size.width(), m_size.height());
+}
+
+void Q3DSQmlStreamRenderer::requestUpdate()
+{
+ if (!m_requestRender)
+ QCoreApplication::postEvent(this, new RequestUpdate());
+}
+
+void Q3DSQmlStreamRenderer::renderTexture()
+{
+ QMutexLocker lock(&m_renderMutex);
+ m_context->makeCurrent(m_offscreenSurface);
+
+ if (!m_frameBuffer || m_frameBuffer->size() != m_size) {
+ if (m_frameBuffer)
+ delete m_frameBuffer;
+
+ m_frameBuffer = new QOpenGLFramebufferObject(m_size);
+ m_frameBuffer->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ m_quickWindow->setRenderTarget(m_frameBuffer);
+ }
+
+ {
+ QMutexLocker lock(&m_mutex);
+ if (m_requestRender) {
+ m_renderControl->sync();
+ m_renderControl->render();
+ m_requestRender = false;
+ m_waitCondition.wakeOne();
+ }
+ }
+
+ m_context->functions()->glFlush();
+ m_quickWindow->resetOpenGLState();
+ m_context->doneCurrent();
+ m_update = true;
+}
+
+void Q3DSQmlStreamRenderer::render()
+{
+ QMutexLocker lock(&m_renderMutex);
+ if (m_update) {
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QOpenGLFunctions *func = context->functions();
+ GLuint texture = m_frameBuffer->texture();
+
+ if (!m_program)
+ initializeFboCopy();
+
+ m_program->bind();
+
+ if (!m_vao) {
+ m_vao = new QOpenGLVertexArrayObject;
+ m_vao->create();
+ m_vao->bind();
+ m_vertices->bind();
+
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+ func->glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
+ func->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float),
+ (const void *)(4 * sizeof(GLfloat)));
+ m_vertices->release();
+ } else {
+ m_vao->bind();
+ }
+
+ func->glActiveTexture(GL_TEXTURE0);
+ func->glBindTexture(GL_TEXTURE_2D, texture);
+ func->glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ m_update = false;
+ m_program->release();
+ m_vao->release();
+ }
+}
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.h b/src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.h
new file mode 100644
index 00000000..7cb1dacf
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamrenderer.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAM_RENDERER_H
+#define Q3DS_QMLSTREAM_RENDERER_H
+
+#include "q3dsqmlstreamservice.h"
+
+#include <QOpenGLFunctions>
+#include <QSize>
+#include <QThread>
+#include <QWaitCondition>
+#include <QMutex>
+
+QT_BEGIN_NAMESPACE
+class QQuickRenderControl;
+class QQuickWindow;
+class QQuickItem;
+class QOpenGLContext;
+class QOffscreenSurface;
+class QOpenGLFramebufferObject;
+class QOpenGLShaderProgram;
+class QOpenGLBuffer;
+class QOpenGLVertexArrayObject;
+QT_END_NAMESPACE
+
+class Q3DSQmlStreamRenderer;
+
+class Q3DSQmlStreamEventHandler : public QObject
+{
+ Q_OBJECT
+public:
+ Q3DSQmlStreamEventHandler(Q3DSQmlStreamRenderer *renderer);
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
+private:
+ Q3DSQmlStreamRenderer *m_renderer;
+};
+
+class Q3DSQmlStreamRenderer : public QObject,
+ public IQ3DSQmlStreamRenderer
+{
+ Q_OBJECT
+public:
+ Q3DSQmlStreamRenderer();
+ virtual ~Q3DSQmlStreamRenderer();
+
+ bool initialize(QOpenGLContext *context, QSurface *surface) override;
+
+ QSize getDesiredSize() override;
+ E_TEXTURE_FORMAT getDesiredFormat() override;
+ bool isUpdateRequested() override;
+
+ void render() override;
+
+ void uninitialize() override;
+
+ void setItem(QQuickItem *item);
+
+ bool event(QEvent *event) Q_DECL_OVERRIDE;
+
+private:
+
+ void updateSizes();
+ void requestUpdate();
+ void cleanup();
+ void initializeRender();
+ void renderTexture();
+ void initializeFboCopy();
+
+ QSize m_size;
+ QMutex m_mutex, m_renderMutex;
+ QWaitCondition m_waitCondition;
+
+ QQuickRenderControl *m_renderControl;
+ QQuickWindow *m_quickWindow;
+ QQuickItem *m_rootItem;
+
+ QOpenGLFramebufferObject *m_frameBuffer;
+ QOpenGLShaderProgram *m_program;
+ QOpenGLVertexArrayObject *m_vao;
+ QOpenGLBuffer *m_vertices;
+ QOpenGLContext *m_context;
+ QOffscreenSurface *m_offscreenSurface;
+
+ Q3DSQmlStreamEventHandler *m_renderObject;
+ QThread *m_renderThread;
+
+ bool m_requestRender;
+ bool m_initialized;
+ bool m_prepared;
+ bool m_renderControlInitialized;
+ bool m_update;
+
+ friend class Q3DSQmlStreamEventHandler;
+};
+
+#endif // Q3DS_QMLSTREAM_RENDERER_H
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlstreamservice.h b/src/QtExtras/qmlstreamer/q3dsqmlstreamservice.h
new file mode 100644
index 00000000..da3b94ea
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlstreamservice.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QMLSTREAM_SERVICE_H
+#define Q3DS_QMLSTREAM_SERVICE_H
+
+#include <qglobal.h>
+#include <q3dsqmlstreamer_global.h>
+
+QT_BEGIN_NAMESPACE
+class QOpenGLContext;
+class QSurface;
+class QSize;
+QT_END_NAMESPACE
+
+enum E_TEXTURE_FORMAT
+{
+ E_TEXTURE_RGBA8,
+};
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT IQ3DSQmlStreamRenderer
+{
+public:
+ virtual bool initialize(QOpenGLContext *context, QSurface *surface) = 0;
+
+ virtual QSize getDesiredSize() = 0;
+ virtual E_TEXTURE_FORMAT getDesiredFormat() = 0;
+ virtual bool isUpdateRequested() = 0;
+
+ virtual void render() = 0;
+
+ virtual void uninitialize() = 0;
+};
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT IQ3DSQmlStreamProducer
+{
+public:
+ virtual IQ3DSQmlStreamRenderer *getRenderer() = 0;
+};
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT IQ3DSQmlStreamService
+{
+public:
+ virtual IQ3DSQmlStreamRenderer *getRenderer(const char *id) = 0;
+ virtual bool registerProducer(IQ3DSQmlStreamProducer *producer, const char *id) = 0;
+ virtual void unregisterProducer(IQ3DSQmlStreamProducer *producer) = 0;
+
+ static IQ3DSQmlStreamService *getQmlStreamService();
+};
+
+#endif // Q3DS_QMLSTREAM_SERVICE_H
+
+
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.cpp b/src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.cpp
new file mode 100644
index 00000000..8487909b
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlsubpresentationsettings.h"
+#include "q3dsqmlstream.h"
+
+Q3DSSubPresentationSettings::Q3DSSubPresentationSettings(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+Q3DSSubPresentationSettings::~Q3DSSubPresentationSettings()
+{
+ qDeleteAll(m_list);
+}
+
+QQmlListProperty<Q3DSQmlStream> Q3DSSubPresentationSettings::qmlStreams()
+{
+ return QQmlListProperty<Q3DSQmlStream>(this, m_list);
+}
+
+QList<Q3DSQmlStream *> Q3DSSubPresentationSettings::qmlStreamsList()
+{
+ return m_list;
+}
+
diff --git a/src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.h b/src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.h
new file mode 100644
index 00000000..b295f2a0
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/q3dsqmlsubpresentationsettings.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_QML_SUBPRESENTATION_SETTINGS_H
+#define Q3DS_QML_SUBPRESENTATION_SETTINGS_H
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtQml/QQmlListProperty>
+
+#include "q3dsqmlstream.h"
+#include "q3dsqmlstreamer_global.h"
+
+class Q3DS_QMLSTREAMERSHARED_EXPORT Q3DSSubPresentationSettings : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Q3DSQmlStream> qmlStreams READ qmlStreams)
+public:
+
+ Q3DSSubPresentationSettings(QObject *parent = nullptr);
+ ~Q3DSSubPresentationSettings();
+
+ QQmlListProperty<Q3DSQmlStream> qmlStreams();
+ QList<Q3DSQmlStream *> qmlStreamsList();
+private:
+ QList<Q3DSQmlStream *> m_list;
+};
+
+#endif // Q3DS_QML_SUBPRESENTATION_SETTINGS_H
diff --git a/src/QtExtras/qmlstreamer/qmlstreamer.pro b/src/QtExtras/qmlstreamer/qmlstreamer.pro
new file mode 100644
index 00000000..ef1761b6
--- /dev/null
+++ b/src/QtExtras/qmlstreamer/qmlstreamer.pro
@@ -0,0 +1,47 @@
+TEMPLATE = lib
+TARGET = qt3dsqmlstreamer
+include($$PWD/../../commonplatform.pri)
+
+CONFIG += installed
+load(qt_helper_lib)
+
+# qt_helper_lib assumes non-qt lib, so it clears some qt variables, reset those
+CONFIG += qt
+QT += core qml quick opengl
+
+DEFINES += QMLSTREAMER_LIBRARY
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which as been marked as deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+ q3dsqmlstream.cpp \
+ q3dsqmlstreamerserviceimpl.cpp \
+ q3dsqmlstreamproducer.cpp \
+ q3dsqmlstreamproxy.cpp \
+ q3dsqmlstreamrenderer.cpp \
+ q3dsqmlsubpresentationsettings.cpp
+
+HEADERS += \
+ q3dsincubationcontroller.h \
+ q3dsqmlstream.h \
+ q3dsqmlstreamer_global.h \
+ q3dsqmlstreamerserviceimpl.h \
+ q3dsqmlstreamproducer.h \
+ q3dsqmlstreamproxy.h \
+ q3dsqmlstreamrenderer.h \
+ q3dsqmlstreamservice.h \
+ q3dsqmlsubpresentationsettings.h
+
+INCLUDEPATH += \
+ $$PWD/../Runtime/Source/Engine/Include \
+ $$PWD/../Runtime/Source/System/Include \
+ $$PWD/../QtExtras/qmlstreamer
diff --git a/src/Runtime/AttributeHashes.pri b/src/Runtime/AttributeHashes.pri
new file mode 100644
index 00000000..172bcec0
--- /dev/null
+++ b/src/Runtime/AttributeHashes.pri
@@ -0,0 +1 @@
+SOURCES += $$PWD/../Runtime/SDKsAndTools/AttributeHashes/AttributeHashes.cpp
diff --git a/src/Runtime/AttributeHashes.pro b/src/Runtime/AttributeHashes.pro
new file mode 100644
index 00000000..aeadfc06
--- /dev/null
+++ b/src/Runtime/AttributeHashes.pro
@@ -0,0 +1,15 @@
+TEMPLATE = app
+TARGET = AttributeHashes
+CONFIG += console
+
+win32 {
+LIBS += \
+ -lws2_32
+}
+
+include(commoninclude.pri)
+include(AttributeHashes.pri)
+
+load(qt_tool)
+
+INSTALLS -= target
diff --git a/src/Runtime/Qt3DSRuntime.pro b/src/Runtime/Qt3DSRuntime.pro
new file mode 100644
index 00000000..aaf7d08f
--- /dev/null
+++ b/src/Runtime/Qt3DSRuntime.pro
@@ -0,0 +1,69 @@
+TEMPLATE = lib
+TARGET = qt3dsruntime
+
+DEFINES += QT3DS_RUNTIME_EXPORTS
+
+CONFIG += installed
+include(commoninclude.pri)
+QT += qml
+
+boot2qt: {
+ RESOURCES += res.qrc
+ DEFINES += EMBEDDED_LINUX # TODO: Is there a compile-time flag for boot2qt?
+}
+
+integrity {
+RESOURCES += res.qrc
+}
+
+SOURCES += \
+ Source/Viewer/UICViewerApp.cpp \
+ Source/Viewer/UICAudioPlayerImpl.cpp
+
+HEADERS += \
+ Source/Viewer/qt3dsruntimeglobal.h \
+ Source/Viewer/UICViewerApp.h \
+ Source/Viewer/UICAudioPlayerImpl.h \
+ Source/Viewer/UICViewerTimer.h
+
+linux {
+ BEGIN_ARCHIVE = -Wl,--whole-archive
+ END_ARCHIVE = -Wl,--no-whole-archive
+}
+
+STATICRUNTIME = \
+ $$BEGIN_ARCHIVE \
+ -lEASTL$$qtPlatformTargetSuffix() \
+ -lLua$$qtPlatformTargetSuffix() \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix() \
+ $$END_ARCHIVE
+
+# On non-windows systems link the whole static archives and do not put them
+# in the prl file to prevent them being linked again by targets that depend
+# upon this shared library
+!win32:!CONFIG(static){
+ QMAKE_LFLAGS += $$STATICRUNTIME
+ LIBS += -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+} else {
+ LIBS += \
+ $$STATICRUNTIME \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+}
+
+win32 {
+ LIBS += \
+ -lws2_32
+
+ RESOURCES += platformres.qrc
+}
+
+linux {
+ LIBS += \
+ -ldl \
+ -lEGL
+}
+
+PREDEPS_LIBS = qt3dsruntimestatic
+
+include($$PWD/../utils.pri)
+PRE_TARGETDEPS += $$fixLibPredeps($$LIBDIR, PREDEPS_LIBS)
diff --git a/src/Runtime/Qt3DSRuntimeStatic.pro b/src/Runtime/Qt3DSRuntimeStatic.pro
new file mode 100644
index 00000000..8fa1aac8
--- /dev/null
+++ b/src/Runtime/Qt3DSRuntimeStatic.pro
@@ -0,0 +1,694 @@
+TEMPLATE = lib
+TARGET = qt3dsruntimestatic
+CONFIG += staticlib
+include(commoninclude.pri)
+
+!boot2qt:!integrity {
+ RESOURCES += res.qrc
+}
+
+QT += qml
+
+# Foundation
+SOURCES += \
+ Source/Qt3DSFoundation/Source/foundation/ConvertUTF.cpp \
+ Source/Qt3DSFoundation/Source/foundation/EASTL_new.cpp \
+ Source/Qt3DSFoundation/Source/foundation/FileTools.cpp \
+ Source/Qt3DSFoundation/Source/foundation/IOStreams.cpp \
+ Source/Qt3DSFoundation/Source/foundation/Qt3DSLogging.cpp \
+ Source/Qt3DSFoundation/Source/foundation/Qt3DSFoundation.cpp \
+ Source/Qt3DSFoundation/Source/foundation/Qt3DSMathUtils.cpp \
+ Source/Qt3DSFoundation/Source/foundation/Qt3DSPerfTimer.cpp \
+ Source/Qt3DSFoundation/Source/foundation/Qt3DSSystem.cpp \
+ Source/Qt3DSFoundation/Source/foundation/Socket.cpp \
+ Source/Qt3DSFoundation/Source/foundation/StringTable.cpp \
+ Source/Qt3DSFoundation/Source/foundation/XML.cpp \
+ Source/UICRender/Source/q3dsqmlrender.cpp
+
+HEADERS += \
+ Source/Qt3DSFoundation/Include/foundation/ConvertUTF.h \
+ Source/Qt3DSFoundation/Include/foundation/FileTools.h \
+ Source/Qt3DSFoundation/Include/foundation/IOStreams.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSLogging.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSFoundation.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSMathUtils.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSPerfTimer.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSSystem.h \
+ Source/Qt3DSFoundation/Include/foundation/Socket.h \
+ Source/Qt3DSFoundation/Include/foundation/StringTable.h \
+ Source/Qt3DSFoundation/Include/foundation/XML.h \
+ Source/Qt3DSFoundation/Include/foundation/AutoDeallocatorAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/FastAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/PoolingAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/PreAllocatedAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DS.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocatorCallback.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSAssert.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSAtomic.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSBasicTemplates.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSBounds3.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSBroadcastingAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSContainers.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSDataRef.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSDiscriminatedUnion.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSFastIPC.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSFlags.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSFPU.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSIndexableLinkedList.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSIntrinsics.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveLinkedList.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveSet.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSIPC.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSMat33.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSMat44.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSMath.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSMemoryBuffer.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSMutex.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSNoCopy.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSOption.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSPlane.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSPool.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSPreprocessor.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSQuat.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSRefCounted.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSSemaphore.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSSimpleTypes.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSStringTokenizer.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSSync.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSThread.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSTime.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSTransform.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSUnionCast.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSUtilities.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSVec2.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSVec3.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSVec4.h \
+ Source/Qt3DSFoundation/Include/foundation/Qt3DSVersionNumber.h \
+ Source/Qt3DSFoundation/Include/foundation/SerializationTypes.h \
+ Source/Qt3DSFoundation/Include/foundation/StrConvertUTF.h \
+ Source/Qt3DSFoundation/Include/foundation/StringConversion.h \
+ Source/Qt3DSFoundation/Include/foundation/StringConversionImpl.h \
+ Source/Qt3DSFoundation/Include/foundation/TaggedPointer.h \
+ Source/Qt3DSFoundation/Include/foundation/ThreadSafeQueue.h \
+ Source/Qt3DSFoundation/Include/foundation/TrackingAllocator.h \
+ Source/Qt3DSFoundation/Include/foundation/Utils.h \
+ Source/UICRender/Include/q3dsqmlrender.h
+
+win32 {
+SOURCES += \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsAtomic.cpp \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsFPU.cpp \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsMutex.cpp \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSemaphore.cpp \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSync.cpp \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsThread.cpp \
+ Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsTime.cpp
+
+HEADERS += \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsAoS.h \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsFile.h \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInclude.h \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInlineAoS.h \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsIntrinsics.h \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsString.h \
+ Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsTrigConstants.h
+}
+
+macos: SOURCES += \
+ Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixAtomic.cpp \
+ Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixFPU.cpp \
+ Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixMutex.cpp \
+ Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSemaphore.cpp \
+ Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSync.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxThread.cpp \
+ Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixTime.cpp
+
+linux|integrity {
+SOURCES += \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxAtomic.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxFPU.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxMutex.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSemaphore.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSync.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxThread.cpp \
+ Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxTime.cpp
+
+HEADERS += \
+ Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxAoS.h \
+ Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxFile.h \
+ Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxInlineAoS.h \
+ Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxIntrinsics.h \
+ Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxString.h \
+ Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxTrigConstants.h
+}
+
+# Libs
+SOURCES += \
+ ../3rdparty/RuntimePlatformSpecific/$$PlatformSpecificDir/Qt3DSLibs/KD/MinKD.c \
+ Source/PlatformSpecific/$$PlatformSpecificDir/Qt3DSLibs/nv_math/nv_math.cpp \
+ Source/PlatformSpecific/$$PlatformSpecificDir/Qt3DSLibs/nv_math/nv_matrix.cpp \
+ Source/PlatformSpecific/$$PlatformSpecificDir/Qt3DSLibs/nv_math/nv_quat.cpp
+
+# RenderBase
+SOURCES += \
+ Source/Qt3DSRender/Source/Qt3DSRenderAtomicCounterBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderAttribLayout.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderComputeShader.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderContext.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderDataBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderDepthStencilState.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderDrawIndirectBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderFragmentShader.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderFrameBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderGeometryShader.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderImageTexture.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderIndexBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderInputAssembler.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderOcclusionQuery.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderPathFontSpecification.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderPathFontText.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderPathRender.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderPathSpecification.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderProgramPipeline.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderQueryBase.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderRasterizerState.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderRenderBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderSampler.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderShaderProgram.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderStorageBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderSync.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderTessellationShader.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderTexture2D.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderTexture2DArray.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderTextureBase.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderTextureCube.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderTimerQuery.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderVertexBuffer.cpp \
+ Source/Qt3DSRender/Source/Qt3DSRenderVertexShader.cpp
+
+HEADERS += \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderAtomicCounterBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderAttribLayout.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderBaseTypes.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderComputeShader.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderConstantBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderDataBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderDepthStencilState.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderDrawable.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderDrawIndirectBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderFragmentShader.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderFrameBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderGeometryShader.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderImageTexture.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderIndexBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderInputAssembler.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderOcclusionQuery.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontSpecification.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontText.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderPathRender.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderPathSpecification.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderProgramPipeline.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderQueryBase.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderRasterizerState.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderRenderBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderSampler.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderShader.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderStorageBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderSync.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderTessellationShader.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2D.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2DArray.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderTextureBase.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderTextureCube.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderTimerQuery.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderVertexBuffer.h \
+ Source/Qt3DSRender/Include/render/Qt3DSRenderVertexShader.h \
+ Source/Qt3DSRender/Include/render/glg/Qt3DSGLImplObjects.h
+
+# Render
+SOURCES += \
+ Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp \
+ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp \
+ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp \
+ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp \
+ Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp \
+ Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp
+
+HEADERS += \
+ Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL4.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h \
+ Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h \
+ Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h
+
+# UICDM
+SOURCES += \
+ Source/RuntimeUICDM/Source/UICMetadata.cpp \
+ $$PWD/../Authoring/UICIMP/UICImportLib/UICImportMesh.cpp \
+ $$PWD/../Authoring/UICIMP/UICImportLib/UICImportPath.cpp \
+ $$PWD/../Authoring/UICDM/Systems/UICDMMetaData.cpp \
+ $$PWD/../Authoring/UICDM/Systems/UICDMXML.cpp \
+ $$PWD/../Authoring/UICDM/Systems/UICDMStringTable.cpp \
+ $$PWD/../Authoring/UICDM/Systems/UICDMHandles.cpp \
+ $$PWD/../Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.cpp \
+ $$PWD/../Authoring/UICDM/Systems/UICDMValue.cpp \
+ $$PWD/../Authoring/UICDM/Systems/Cores/SimpleDataCore.cpp
+
+HEADERS += \
+ Source/RuntimeUICDM/Include/UICMetadata.h \
+ Source/RuntimeUICDM/Include/DocumentResourceManagerScriptParser.h \
+ $$PWD/../Authoring/UICIMP/UICImportLib/UICImportMesh.h \
+ $$PWD/../Authoring/UICIMP/UICImportLib/UICImportPath.h \
+ $$PWD/../Authoring/UICDM/Systems/UICDMMetaData.h \
+ $$PWD/../Authoring/UICDM/Systems/UICDMXML.h \
+ $$PWD/../Authoring/UICDM/Systems/UICDMStringTable.h \
+ $$PWD/../Authoring/UICDM/Systems/UICDMHandles.h \
+ $$PWD/../Authoring/UICDM/Systems/UICDMComposerTypeDefinitions.h \
+ $$PWD/../Authoring/UICDM/Systems/UICDMValue.h \
+ $$PWD/../Authoring/UICDM/Systems/Cores/SimpleDataCore.h
+
+# Engine
+HEADERS += \
+ Source/Engine/Include/EnginePrefix.h \
+ Source/Engine/Include/UICTegraApplication.h \
+ Source/Engine/Include/UICTegraInputEngine.h \
+ Source/Engine/Include/UICRenderRuntimeBinding.h \
+ Source/Engine/Include/UICRenderRuntimeBindingImpl.h
+
+SOURCES += \
+ Source/Engine/Source/EnginePrefix.cpp \
+ Source/Engine/Source/UICOSSpecificFunctions.cpp \
+ Source/Engine/Source/UICRenderRuntimeBinding.cpp \
+ Source/Engine/Source/UICRenderRuntimeBindingImplRenderer.cpp \
+ Source/Engine/Source/UICRenderRuntimeBindingImplTranslation.cpp \
+ Source/Engine/Source/UICTegraApplication.cpp \
+ Source/Engine/Source/UICTegraInputEngine.cpp
+
+# Event
+SOURCES += \
+ Source/UICEvent/Source/EventFactory.cpp \
+ Source/UICEvent/Source/EventPoller.cpp \
+ Source/UICEvent/Source/EventPollingSystemLuaBinding.cpp \
+ Source/UICEvent/Source/EventSystemC.cpp
+
+HEADERS += \
+ Source/UICEvent/InternalInclude/EventPollingSystem.h \
+ Source/UICEvent/InternalInclude/EventPollingSystemLuaBinding.h \
+ Source/UICEvent/Include/EventSystem.h \
+ Source/UICEvent/Include/EventSystemC.h
+
+# Render
+SOURCES += \
+ Source/UICRender/Source/UICOffscreenRenderManager.cpp \
+ Source/UICRender/Source/UICOldNBustedRenderPlugin.cpp \
+ Source/UICRender/Source/UICOnscreenTextRenderer.cpp \
+ Source/UICRender/Source/UICRenderClippingFrustum.cpp \
+ Source/UICRender/Source/UICRenderContext.cpp \
+ Source/UICRender/Source/UICRenderCustomMaterialShaderGenerator.cpp \
+ Source/UICRender/Source/UICRenderCustomMaterialSystem.cpp \
+ Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp \
+ Source/UICRender/Source/UICRenderDynamicObjectSystem.cpp \
+ Source/UICRender/Source/UICRenderEffectSystem.cpp \
+ Source/UICRender/Source/UICRendererUtil.cpp \
+ Source/UICRender/Source/UICRenderEulerAngles.cpp \
+ Source/UICRender/Source/UICRenderGpuProfiler.cpp \
+ Source/UICRender/Source/UICRenderGraphObjectSerializer.cpp \
+ Source/UICRender/Source/UICRenderImageScaler.cpp \
+ Source/UICRender/Source/UICRenderInputStreamFactory.cpp \
+ Source/UICRender/Source/UICRenderPathManager.cpp \
+ Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp \
+ Source/UICRender/Source/UICRenderPixelGraphicsTypes.cpp \
+ Source/UICRender/Source/UICRenderPlugin.cpp \
+ Source/UICRender/Source/UICRenderRay.cpp \
+ Source/UICRender/Source/UICRenderRenderList.cpp \
+ Source/UICRender/Source/UICRenderShaderCache.cpp \
+ Source/UICRender/Source/UICRenderShaderCodeGenerator.cpp \
+ Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp \
+ Source/UICRender/Source/UICRenderShadowMap.cpp \
+ Source/UICRender/Source/UICRenderSubpresentation.cpp \
+ Source/UICRender/Source/UICRenderTextTextureAtlas.cpp \
+ Source/UICRender/Source/UICRenderTextTextureCache.cpp \
+ Source/UICRender/Source/UICRenderTextureAtlas.cpp \
+ Source/UICRender/Source/UICRenderThreadPool.cpp \
+ Source/UICRender/Source/UICRenderUIPLoader.cpp \
+ Source/UICRender/Source/UICRenderUIPSharedTranslation.cpp \
+ Source/UICRender/Source/UICRenderWidgets.cpp \
+ Source/UICRender/Source/UICTextRenderer.cpp \
+ Source/UICRender/Source/UICQtTextRenderer.cpp \
+ Source/UICRender/GraphObjects/UICRenderCamera.cpp \
+ Source/UICRender/GraphObjects/UICRenderDefaultMaterial.cpp \
+ Source/UICRender/GraphObjects/UICRenderDynamicObject.cpp \
+ Source/UICRender/GraphObjects/UICRenderEffect.cpp \
+ Source/UICRender/GraphObjects/UICRenderImage.cpp \
+ Source/UICRender/GraphObjects/UICRenderLayer.cpp \
+ Source/UICRender/GraphObjects/UICRenderLight.cpp \
+ Source/UICRender/GraphObjects/UICRenderLightmaps.cpp \
+ Source/UICRender/GraphObjects/UICRenderModel.cpp \
+ Source/UICRender/GraphObjects/UICRenderNode.cpp \
+ Source/UICRender/GraphObjects/UICRenderPath.cpp \
+ Source/UICRender/GraphObjects/UICRenderPresentation.cpp \
+ Source/UICRender/GraphObjects/UICRenderScene.cpp \
+ Source/UICRender/GraphObjects/UICRenderText.cpp \
+ Source/UICRender/RendererImpl/UICRenderableObjects.cpp \
+ Source/UICRender/RendererImpl/UICRendererImpl.cpp \
+ Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp \
+ Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.cpp \
+ Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp \
+ Source/UICRender/RendererImpl/UICRendererImplShaders.cpp \
+ Source/UICRender/ResourceManager/UICRenderBufferLoader.cpp \
+ Source/UICRender/ResourceManager/UICRenderBufferManager.cpp \
+ Source/UICRender/ResourceManager/UICRenderImageBatchLoader.cpp \
+ Source/UICRender/ResourceManager/UICRenderLoadedTexture.cpp \
+ Source/UICRender/ResourceManager/UICRenderLoadedTextureBMP.cpp \
+ Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.cpp \
+ Source/UICRender/ResourceManager/UICRenderLoadedTextureGIF.cpp \
+ Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp \
+ Source/UICRender/ResourceManager/UICRenderPrefilterTexture.cpp \
+ Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.cpp \
+ Source/UICRender/ResourceManager/UICRenderResourceManager.cpp \
+ Source/UICRender/ResourceManager/UICRenderResourceTexture2D.cpp
+
+HEADERS += \
+ Source/UICRender/Include/UICOffscreenRenderKey.h \
+ Source/UICRender/Include/UICOffscreenRenderManager.h \
+ Source/UICRender/Include/UICOldNBustedRenderPlugin.h \
+ Source/UICRender/Include/UICRender.h \
+ Source/UICRender/Include/UICRenderableImage.h \
+ Source/UICRender/Include/UICRenderClippingFrustum.h \
+ Source/UICRender/Include/UICRenderContext.h \
+ Source/UICRender/Include/UICRenderCustomMaterialRenderContext.h \
+ Source/UICRender/Include/UICRenderCustomMaterialShaderGenerator.h \
+ Source/UICRender/Include/UICRenderCustomMaterialSystem.h \
+ Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h \
+ Source/UICRender/Include/UICRenderDynamicObjectSystem.h \
+ Source/UICRender/Include/UICRenderDynamicObjectSystemCommands.h \
+ Source/UICRender/Include/UICRenderDynamicObjectSystemUtil.h \
+ Source/UICRender/Include/UICRenderEffectSystem.h \
+ Source/UICRender/Include/UICRenderer.h \
+ Source/UICRender/Include/UICRendererUtil.h \
+ Source/UICRender/Include/UICRenderEulerAngles.h \
+ Source/UICRender/Include/UICRenderGraphObjectPickQuery.h \
+ Source/UICRender/Include/UICRenderGraphObjectSerializer.h \
+ Source/UICRender/Include/UICRenderGraphObjectTypes.h \
+ Source/UICRender/Include/UICRenderImageScaler.h \
+ Source/UICRender/Include/UICRenderImageTextureData.h \
+ Source/UICRender/Include/UICRenderInputStreamFactory.h \
+ Source/UICRender/Include/UICRenderMaterialHelpers.h \
+ Source/UICRender/Include/UICRenderMaterialShaderGenerator.h \
+ Source/UICRender/Include/UICRenderMesh.h \
+ Source/UICRender/Include/UICRenderPathManager.h \
+ Source/UICRender/Include/UICRenderPathMath.h \
+ Source/UICRender/Include/UICRenderPathRenderContext.h \
+ Source/UICRender/Include/UICRenderPixelGraphicsRenderer.h \
+ Source/UICRender/Include/UICRenderPixelGraphicsTypes.h \
+ Source/UICRender/Include/UICRenderPlugin.h \
+ Source/UICRender/Include/UICRenderPluginCInterface.h \
+ Source/UICRender/Include/UICRenderPluginGraphObject.h \
+ Source/UICRender/Include/UICRenderPluginPropertyValue.h \
+ Source/UICRender/Include/UICRenderProfiler.h \
+ Source/UICRender/Include/UICRenderRay.h \
+ Source/UICRender/Include/UICRenderRenderList.h \
+ Source/UICRender/Include/UICRenderRotationHelper.h \
+ Source/UICRender/Include/UICRenderShaderCache.h \
+ Source/UICRender/Include/UICRenderShaderCodeGenerator.h \
+ Source/UICRender/Include/UICRenderShaderCodeGeneratorV2.h \
+ Source/UICRender/Include/UICRenderShaderKeys.h \
+ Source/UICRender/Include/UICRenderShadowMap.h \
+ Source/UICRender/Include/UICRenderString.h \
+ Source/UICRender/Include/UICRenderSubpresentation.h \
+ Source/UICRender/Include/UICRenderSubPresentationHelper.h \
+ Source/UICRender/Include/UICRenderTaggedPointer.h \
+ Source/UICRender/Include/UICRenderTessModeValues.h \
+ Source/UICRender/Include/UICRenderTextTextureAtlas.h \
+ Source/UICRender/Include/UICRenderTextTextureCache.h \
+ Source/UICRender/Include/UICRenderTextTypes.h \
+ Source/UICRender/Include/UICRenderTextureAtlas.h \
+ Source/UICRender/Include/UICRenderThreadPool.h \
+ Source/UICRender/Include/UICRenderUIPLoader.h \
+ Source/UICRender/Include/UICRenderUIPSharedTranslation.h \
+ Source/UICRender/Include/UICRenderWidgets.h \
+ Source/UICRender/Include/UICRenderWindowDimensions.h \
+ Source/UICRender/Include/UICTextRenderer.h \
+ Source/UICRender/GraphObjects/UICRenderCamera.h \
+ Source/UICRender/GraphObjects/UICRenderCustomMaterial.h \
+ Source/UICRender/GraphObjects/UICRenderDefaultMaterial.h \
+ Source/UICRender/GraphObjects/UICRenderDynamicObject.h \
+ Source/UICRender/GraphObjects/UICRenderEffect.h \
+ Source/UICRender/GraphObjects/UICRenderGraphObject.h \
+ Source/UICRender/GraphObjects/UICRenderImage.h \
+ Source/UICRender/GraphObjects/UICRenderLayer.h \
+ Source/UICRender/GraphObjects/UICRenderLight.h \
+ Source/UICRender/GraphObjects/UICRenderLightmaps.h \
+ Source/UICRender/GraphObjects/UICRenderMaterialDirty.h \
+ Source/UICRender/GraphObjects/UICRenderModel.h \
+ Source/UICRender/GraphObjects/UICRenderNode.h \
+ Source/UICRender/GraphObjects/UICRenderPath.h \
+ Source/UICRender/GraphObjects/UICRenderPathSubPath.h \
+ Source/UICRender/GraphObjects/UICRenderPresentation.h \
+ Source/UICRender/GraphObjects/UICRenderReferencedMaterial.h \
+ Source/UICRender/GraphObjects/UICRenderScene.h \
+ Source/UICRender/GraphObjects/UICRenderText.h \
+ Source/UICRender/RendererImpl/UICRenderableObjects.h \
+ Source/UICRender/RendererImpl/UICRendererImpl.h \
+ Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.h \
+ Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.h \
+ Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.h \
+ Source/UICRender/RendererImpl/UICRendererImplShaders.h \
+ Source/UICRender/RendererImpl/UICVertexPipelineImpl.h \
+ Source/UICRender/ResourceManager/UICRenderBufferLoader.h \
+ Source/UICRender/ResourceManager/UICRenderBufferManager.h \
+ Source/UICRender/ResourceManager/UICRenderImageBatchLoader.h \
+ Source/UICRender/ResourceManager/UICRenderLoadedTexture.h \
+ Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.h \
+ Source/UICRender/ResourceManager/UICRenderLoadedTextureFreeImageCompat.h \
+ Source/UICRender/ResourceManager/UICRenderPrefilterTexture.h \
+ Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.h \
+ Source/UICRender/ResourceManager/UICRenderResourceManager.h \
+ Source/UICRender/ResourceManager/UICRenderResourceTexture2D.h \
+ Source/UICRender/Include/ANDROID/DynamicLibLoader.h \
+ Source/UICRender/Include/LINUX/DynamicLibLoader.h \
+ Source/UICRender/Include/OSX/DynamicLibLoader.h \
+ Source/UICRender/Include/QNX/DynamicLibLoader.h \
+ Source/UICRender/Include/WINDOWS/DynamicLibLoader.h
+
+# Runtime
+HEADERS += \
+ Source/Runtime/Include/RuntimePrefix.h \
+ Source/Runtime/Include/UICActivationManager.h \
+ Source/Runtime/Include/UICAnimationSystem.h \
+ Source/Runtime/Include/UICApplication.h \
+ Source/Runtime/Include/UICAttributeHashes.h \
+ Source/Runtime/Include/UICBinarySerializerImpl.h \
+ Source/Runtime/Include/UICComponentManager.h \
+ Source/Runtime/Include/UICElementSystem.h \
+ Source/Runtime/Include/UICEventCallbacks.h \
+ Source/Runtime/Include/UICInputEngine.h \
+ Source/Runtime/Include/UICLogicSystem.h \
+ Source/Runtime/Include/UICLuaAxis.h \
+ Source/Runtime/Include/UICLuaButton.h \
+ Source/Runtime/Include/UICLuaColor.h \
+ Source/Runtime/Include/UICLuaCommandHelper.h \
+ Source/Runtime/Include/UICLuaElementHelper.h \
+ Source/Runtime/Include/UICLuaEngine.h \
+ Source/Runtime/Include/UICLuaEventHelper.h \
+ Source/Runtime/Include/UICLuaHelper.h \
+ Source/Runtime/Include/UICLuaKeyboard.h \
+ Source/Runtime/Include/UICLuaMatrix.h \
+ Source/Runtime/Include/UICLuaRotation.h \
+ Source/Runtime/Include/UICLuaSceneHelper.h \
+ Source/Runtime/Include/UICLuaVector.h \
+ Source/Runtime/Include/UICOutputMemoryStream.h \
+ Source/Runtime/Include/UICParametersSystem.h \
+ Source/Runtime/Include/UICPresentation.h \
+ Source/Runtime/Include/UICPresentationFrameData.h \
+ Source/Runtime/Include/UICQmlEngine.h \
+ Source/Runtime/Include/UICSlideSystem.h \
+ Source/Runtime/Include/UICTimePolicy.h \
+ Source/Runtime/Include/UICQmlElementHelper.h \
+ Source/Runtime/Include/q3dsqmlscript.h
+
+SOURCES += \
+ Source/Runtime/Source/RuntimePrefix.cpp \
+ Source/Runtime/Source/UICActivationManager.cpp \
+ Source/Runtime/Source/UICAnimationSystem.cpp \
+ Source/Runtime/Source/UICApplication.cpp \
+ Source/Runtime/Source/UICAttributeHashes.cpp \
+ Source/Runtime/Source/UICBinarySerializerImpl.cpp \
+ Source/Runtime/Source/UICComponentManager.cpp \
+ Source/Runtime/Source/UICElementSystem.cpp \
+ Source/Runtime/Source/UICEventCallbacks.cpp \
+ Source/Runtime/Source/UICInputEngine.cpp \
+ Source/Runtime/Source/UICLogicSystem.cpp \
+ Source/Runtime/Source/UICLuaAxis.cpp \
+ Source/Runtime/Source/UICLuaButton.cpp \
+ Source/Runtime/Source/UICLuaColor.cpp \
+ Source/Runtime/Source/UICLuaCommandHelper.cpp \
+ Source/Runtime/Source/UICLuaElementHelper.cpp \
+ Source/Runtime/Source/UICLuaEngine.cpp \
+ Source/Runtime/Source/UICLuaEventHelper.cpp \
+ Source/Runtime/Source/UICLuaHelper.cpp \
+ Source/Runtime/Source/UICLuaKeyboard.cpp \
+ Source/Runtime/Source/UICLuaMatrix.cpp \
+ Source/Runtime/Source/UICLuaRotation.cpp \
+ Source/Runtime/Source/UICLuaSceneHelper.cpp \
+ Source/Runtime/Source/UICLuaVector.cpp \
+ Source/Runtime/Source/UICOutputMemoryStream.cpp \
+ Source/Runtime/Source/UICParametersSystem.cpp \
+ Source/Runtime/Source/UICPresentation.cpp \
+ Source/Runtime/Source/UICPresentationFrameData.cpp \
+ Source/Runtime/Source/UICQmlEngine.cpp \
+ Source/Runtime/Source/UICSlideSystem.cpp \
+ Source/Runtime/Source/UICTimePolicy.cpp \
+ Source/Runtime/Source/UICQmlElementHelper.cpp \
+ Source/Runtime/Source/q3dsqmlscript.cpp
+
+# State
+SOURCES += \
+ Source/UICState/Source/UICStateContext.cpp \
+ Source/UICState/Source/UICStateExecutionContext.cpp \
+ Source/UICState/Source/UICStateInterpreter.cpp \
+ Source/UICState/Source/UICStateLuaScriptContext.cpp \
+ Source/UICState/Source/UICStateVisualBindingContext.cpp \
+ Source/UICState/Source/UICStateXMLIO.cpp \
+ Source/UICState/Debugger/UICLuaDatamodelCache.cpp \
+ Source/UICState/Debugger/UICLuaSideDebugger.cpp \
+ Source/UICState/Debugger/UICSceneGraphRuntimeDebugger.cpp \
+ Source/UICState/Debugger/UICStateDataTest.cpp \
+ Source/UICState/Debugger/UICStateDebuggedInterpreter.cpp \
+ Source/UICState/Debugger/UICStateDebugger.cpp \
+ Source/UICState/Debugger/UICStateDebuggerListener.cpp \
+ Source/UICState/Debugger/UICStateDebugStreams.cpp \
+ Source/UICState/Debugger/UICStateLuaTest.cpp \
+ Source/UICState/Application/UICStateApplication.cpp
+
+HEADERS += \
+ Source/UICState/Include/UICState.h \
+ Source/UICState/Include/UICStateContext.h \
+ Source/UICState/Include/UICStateExecutionContext.h \
+ Source/UICState/Include/UICStateExecutionTypes.h \
+ Source/UICState/Include/UICStateIdValue.h \
+ Source/UICState/Include/UICStateInterpreter.h \
+ Source/UICState/Include/UICStateLuaScriptContext.h \
+ Source/UICState/Include/UICStateScriptContext.h \
+ Source/UICState/Include/UICStateSharedImpl.h \
+ Source/UICState/Include/UICStateSignalConnection.h \
+ Source/UICState/Include/UICStateTypes.h \
+ Source/UICState/Include/UICStateVisualBindingContext.h \
+ Source/UICState/Include/UICStateVisualBindingContextCommands.h \
+ Source/UICState/Include/UICStateVisualBindingContextValues.h \
+ Source/UICState/Include/UICStateXMLIO.h \
+ Source/UICState/Application/UICStateApplication.h \
+ Source/UICState/Debugger/UICLuaDebugger.h \
+ Source/UICState/Debugger/UICLuaDebuggerImpl.h \
+ Source/UICState/Debugger/UICLuaDebuggerProtocol.h \
+ Source/UICState/Debugger/UICSceneGraphDebugger.h \
+ Source/UICState/Debugger/UICSceneGraphDebuggerProtocol.h \
+ Source/UICState/Debugger/UICSceneGraphDebuggerValue.h \
+ Source/UICState/Debugger/UICStateDebugger.h \
+ Source/UICState/Debugger/UICStateDebuggerProtocol.h \
+ Source/UICState/Debugger/UICStateDebuggerValues.h \
+ Source/UICState/Debugger/UICStateDebugStreams.h \
+ Source/UICState/Debugger/UICStateTest.h \
+ Source/UICState/Debugger/UICStateTestCommon.h
+
+# System
+SOURCES += \
+ Source/System/Source/SystemPrefix.cpp \
+ Source/System/Source/UICAssert.cpp \
+ Source/System/Source/UICBoundingBox.cpp \
+ Source/System/Source/UICColor.cpp \
+ Source/System/Source/UICCubicRoots.cpp \
+ Source/System/Source/UICDataLogger.cpp \
+ Source/System/Source/UICDLLManager.cpp \
+ Source/System/Source/UICEulerAngles.cpp \
+ Source/System/Source/UICFile.cpp \
+ Source/System/Source/UICFileStream.cpp \
+ Source/System/Source/UICFunctionWrappers.cpp \
+ Source/System/Source/UICMatrix.cpp \
+ Source/System/Source/UICMemory.cpp \
+ Source/System/Source/UICMemoryFilter.cpp \
+ Source/System/Source/UICMemoryHeap.cpp \
+ Source/System/Source/UICMemoryManager.cpp \
+ Source/System/Source/UICMemoryPool.cpp \
+ Source/System/Source/UICMemoryProbe.cpp \
+ Source/System/Source/UICMemoryStatistics.cpp \
+ Source/System/Source/UICMemoryTracker.cpp \
+ Source/System/Source/UICSyncPrimitive.cpp \
+ Source/System/Source/UICThreadManager.cpp \
+ Source/System/Source/UICTimer.cpp \
+ Source/System/Source/UICTypes.cpp \
+ Source/System/Source/UICVector3.cpp
+
+HEADERS += \
+ Source/System/Include/SystemPrefix.h \
+ Source/System/Include/UICArray.h \
+ Source/System/Include/UICAssert.h \
+ Source/System/Include/UICAudioPlayer.h \
+ Source/System/Include/UICBasicPluginDLL.h \
+ Source/System/Include/UICBezierEval.h \
+ Source/System/Include/UICBoundingBox.h \
+ Source/System/Include/UICCircularArray.h \
+ Source/System/Include/UICColor.h \
+ Source/System/Include/UICConfig.h \
+ Source/System/Include/UICCubicRoots.h \
+ Source/System/Include/UICCubicRootsImpl.h \
+ Source/System/Include/UICDataLogger.h \
+ Source/System/Include/UICDataLogger.hpp \
+ Source/System/Include/UICDataLoggerEnums.h \
+ Source/System/Include/UICDataLoggerViewer.h \
+ Source/System/Include/UICDLLManager.h \
+ Source/System/Include/UICEGLTimer.h \
+ Source/System/Include/UICEndian.h \
+ Source/System/Include/UICEulerAngles.h \
+ Source/System/Include/UICFile.h \
+ Source/System/Include/UICFileStream.h \
+ Source/System/Include/UICFixedArray.h \
+ Source/System/Include/UICFNDTimer.h \
+ Source/System/Include/UICFunctionWrappers.h \
+ Source/System/Include/UICHash.h \
+ Source/System/Include/UICIFileStream.h \
+ Source/System/Include/UICIStream.h \
+ Source/System/Include/UICITimer.h \
+ Source/System/Include/UICMacros.h \
+ Source/System/Include/UICMatrix.h \
+ Source/System/Include/UICMemory.h \
+ Source/System/Include/UICMemoryFilter.h \
+ Source/System/Include/UICMemoryHeap.h \
+ Source/System/Include/UICMemoryManager.h \
+ Source/System/Include/UICMemoryPool.h \
+ Source/System/Include/UICMemoryProbe.h \
+ Source/System/Include/UICMemorySettings.h \
+ Source/System/Include/UICMemoryStatistics.h \
+ Source/System/Include/UICMemoryTracker.h \
+ Source/System/Include/UICPlatformSpecific.h \
+ Source/System/Include/UICSyncPrimitive.h \
+ Source/System/Include/UICThreadManager.h \
+ Source/System/Include/UICThreadSafeQueue.h \
+ Source/System/Include/UICThreadSafeScratchpad.h \
+ Source/System/Include/UICTimer.h \
+ Source/System/Include/UICTypes.h \
+ Source/System/Include/UICVector3.h
+
+# Parser
+SOURCES += \
+ Source/UIPParser/Source/UICUIPParserActionHelper.cpp \
+ Source/UIPParser/Source/UICUIPParserImpl.cpp \
+ Source/UIPParser/Source/UICUIPParserObjectRefHelper.cpp
+
+HEADERS += \
+ Source/UIPParser/Include/UICIPresentation.h \
+ Source/UIPParser/Include/UICUIPParser.h \
+ Source/UIPParser/Include/UICUIPParserActionHelper.h \
+ Source/UIPParser/Include/UICUIPParserImpl.h \
+ Source/UIPParser/Include/UICUIPParserObjectRefHelper.h
diff --git a/src/Runtime/Runtime.pro b/src/Runtime/Runtime.pro
new file mode 100644
index 00000000..6d844995
--- /dev/null
+++ b/src/Runtime/Runtime.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS += \
+ Qt3DSRuntimeStatic.pro \
+ Qt3DSRuntime.pro
+
+win32 {
+SUBDIRS += \
+ AttributeHashes.pro
+}
diff --git a/src/Runtime/SDKsAndTools/AttributeHashes/AttributeHashes.cpp b/src/Runtime/SDKsAndTools/AttributeHashes/AttributeHashes.cpp
new file mode 100644
index 00000000..6cd72373
--- /dev/null
+++ b/src/Runtime/SDKsAndTools/AttributeHashes/AttributeHashes.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT \
+ 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <stdio.h>
+
+#if defined(_PCPLATFORM) || defined(_TEGRAPLATFORM)
+#include <tchar.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <vector>
+#include <fstream>
+#include <string>
+
+#include "UICConfig.h"
+#include "UICTypes.h"
+#include "UICKernelTypes.h"
+#include "UICHash.h"
+
+//==============================================================================
+// Types
+//==============================================================================
+typedef std::vector<std::string> TStringList;
+
+//==============================================================================
+// Constants
+//==============================================================================
+const char g_Text[] = "UICAttributeHashes.txt";
+const char g_Include[] = "UICAttributeHashes.h";
+const char g_Source[] = "..\\Source\\UICAttributeHashes.cpp";
+const char g_TestString[] = "qt.io";
+
+//==============================================================================
+// Globals
+//==============================================================================
+TStringList g_StringList;
+TStringList g_EnumList;
+
+//==============================================================================
+/**
+ * Convert a string to an enum entry and write it out
+ */
+void WriteEnumEntry(FILE *inDestination, const char *inEnum, const char *inString)
+{
+ // Save out the enum
+ if (inEnum) {
+ // Right justify the value by cutting a string of spaces
+ char thePadding[] = " ";
+ int theLength = (int)strlen(inEnum);
+ theLength = theLength > 30 ? 30 : theLength;
+ thePadding[30 - theLength] = '\0';
+
+ // "ATTRIBUTE_NAME = 0x04CECA21, // name"
+ fprintf(inDestination, "\t%s = %s0x%08X, // %s\n", inEnum, thePadding,
+ Q3DStudio::CHash::HashAttribute(inString), inString);
+ } else
+ fprintf(inDestination, "\n");
+}
+
+//==============================================================================
+/**
+ * Write out the enum section
+ */
+void WriteEnum(FILE *inDestination)
+{
+ // Enum entry
+ fprintf(inDestination, "/// Key for the CElement attribute-value pair\n"
+ "enum EAttribute\n"
+ "{\n");
+
+ // Write all enums
+ for (TStringList::size_type theIndex = 0; theIndex < g_EnumList.size(); ++theIndex)
+ if (!g_StringList[theIndex].empty())
+ WriteEnumEntry(inDestination, g_EnumList[theIndex].c_str(),
+ g_StringList[theIndex].c_str());
+
+ // Enum Footer
+ fprintf(inDestination, "}; // enum EAttribute\n"
+ "\n"
+ "#define AK_STRING_QT_IO \"%s\"\n",
+ g_TestString);
+}
+
+//==============================================================================
+/**
+ * Convert strings to enums
+ */
+void ProcessEnums()
+{
+ // Write all enums
+ for (TStringList::iterator theAttribute = g_StringList.begin();
+ theAttribute != g_StringList.end(); ++theAttribute) {
+ std::string theEnum = std::string("ATTRIBUTE_");
+ theEnum += *theAttribute;
+
+ // Replace all '.' with '_'
+ // Make uppercase
+ for (std::string::size_type thePosition = 0; thePosition < theEnum.length();
+ ++thePosition) {
+ if (theEnum[thePosition] == '.')
+ theEnum[thePosition] = '_';
+
+ if (theEnum[thePosition] == '\n' || theEnum[thePosition] == '\r')
+ theEnum[thePosition] = '\0';
+
+ theEnum[thePosition] = static_cast<char>(toupper(theEnum[thePosition]));
+ }
+
+ g_EnumList.push_back(theEnum);
+ }
+}
+
+//==============================================================================
+/**
+ * Write out lookup function section
+ */
+void WriteLookup(FILE *inDestination)
+{
+ // Lookup function entry
+ fprintf(inDestination, "\n"
+ "\n"
+ "/// Function providing reverse hash lookup\n"
+ "const char* GetAttributeString( const EAttribute inAttribute )\n"
+ "{\n"
+ " switch ( inAttribute )\n"
+ " {\n");
+
+ // Write all enums
+ for (TStringList::size_type theIndex = 0; theIndex < g_EnumList.size(); ++theIndex)
+ if (!g_StringList[theIndex].empty())
+ fprintf(inDestination, "\t\tcase %s: return \"%s\";\n", g_EnumList[theIndex].c_str(),
+ g_StringList[theIndex].c_str());
+
+ // End function
+ fprintf(inDestination,
+ " default:\n"
+ " {\n"
+ " static char s_UnknownHash[16];\n"
+ " sprintf( s_UnknownHash, \"(0x%%08X)\", inAttribute );\n"
+ " return s_UnknownHash;\n"
+ " }\n"
+ " }\n"
+ "}\n");
+}
+
+//==============================================================================
+/**
+ * Single lookup to check new strings
+ */
+int SingleLookup(const char *inString)
+{
+ fprintf(stdout, "String: %s\n", inString);
+ fprintf(stdout, "Hash: 0x%08X\n", Q3DStudio::CHash::HashAttribute(inString));
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Main function.
+ * Open two files, read lines from source and write enum entry to destination.
+ */
+int _tmain(int argc, char *argv[])
+{
+ // Application notice
+ fprintf(
+ stdout,
+ "AttributeHashes\nConverting a string or a file of strings into enums of hashes...\n\n");
+
+ // Checking a single string?
+ if (argc > 1)
+ return SingleLookup(argv[1]);
+
+ // Standard file conversion
+ fprintf(stdout, "Input: %s\n", g_Text);
+ fprintf(stdout, "Output: %s, %s\n\n", g_Include, g_Source);
+
+ // Open source
+ std::ifstream theText(g_Text);
+ if (!theText) {
+ fprintf(stderr, "Failed: Could not input text file, set working directory to "
+ "Runtime\\Source\\Include and try again.\n");
+ return -1;
+ }
+
+ // Add all the strings in text file
+ while (theText) {
+ std::string theLine;
+ theText >> theLine;
+ g_StringList.push_back(theLine);
+ }
+ theText.close();
+
+ // Add unit test string
+ g_StringList.push_back(g_TestString);
+
+ // Process all string to enums
+ ProcessEnums();
+
+ // Open include file
+ FILE *theInclude = NULL;
+ fopen_s(&theInclude, g_Include, "w");
+ if (!theInclude) {
+ fprintf(stderr, "Failed: Could not open output include file\n");
+ return -1;
+ }
+
+ const char* theFileHeader =
+ "/****************************************************************************\n"
+ "**\n"
+ "** Copyright (C) 1993-2009 NVIDIA Corporation.\n"
+ "** Copyright (C) 2017 The Qt Company Ltd.\n"
+ "** Contact: https://www.qt.io/licensing/\n"
+ "**\n"
+ "** This file is part of Qt 3D Studio.\n"
+ "**\n"
+ "** $QT_BEGIN_LICENSE:GPL$\n"
+ "** Commercial License Usage\n"
+ "** Licensees holding valid commercial Qt licenses may use this file in\n"
+ "** accordance with the commercial license agreement provided with the\n"
+ "** Software or, alternatively, in accordance with the terms contained in\n"
+ "** a written agreement between you and The Qt Company. For licensing terms\n"
+ "** and conditions see https://www.qt.io/terms-conditions. For further\n"
+ "** information use the contact form at https://www.qt.io/contact-us.\n"
+ "**\n"
+ "** GNU General Public License Usage\n"
+ "** Alternatively, this file may be used under the terms of the GNU\n"
+ "** General Public License version 3 or (at your option) any later version\n"
+ "** approved by the KDE Free Qt Foundation. The licenses are as published by\n"
+ "** the Free Software Foundation and appearing in the file LICENSE.GPL3\n"
+ "** included in the packaging of this file. Please review the following\n"
+ "** information to ensure the GNU General Public License requirements will\n"
+ "** be met: https://www.gnu.org/licenses/gpl-3.0.html.\n"
+ "**\n"
+ "** $QT_END_LICENSE$\n"
+ "**\n"
+ "****************************************************************************/\n\n";
+
+ // Header
+ fprintf(theInclude, theFileHeader);
+ fprintf(
+ theInclude,
+ "#pragma once\n"
+ "\n"
+ "//==============================================================================\n"
+ "// Namespace\n"
+ "//==============================================================================\n"
+ "namespace Q3DStudio\n"
+ "{\n"
+ "\n"
+ "// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AUTOGENERATED CODE "
+ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "\n"
+ "// Run the AttributeHashes project to regenerate this file from Attributehashes.txt list\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n");
+
+ WriteEnum(theInclude);
+
+ // Footer
+ fprintf(theInclude, "\n"
+ "/// Function providing reverse hash lookup\n"
+ "const char* GetAttributeString( const EAttribute inAttribute );\n"
+ "\n"
+ "} // namespace Q3DStudio\n"
+ "\n");
+
+ // Close include
+ fclose(theInclude);
+
+ // Open source file
+ FILE *theSource = NULL;
+ fopen_s(&theSource, g_Source, "w");
+ if (!theSource) {
+ fprintf(stderr, "Failed: Could not open output source file\n");
+ return -1;
+ }
+
+ fprintf(theSource, theFileHeader);
+
+ // Source
+ fprintf(
+ theSource,
+ "#include \"RuntimePrefix.h\"\n"
+ "\n"
+ "//==============================================================================\n"
+ "// Includes\n"
+ "//==============================================================================\n"
+ "#include \"UICAttributeHashes.h\"\n"
+ "\n"
+ "//==============================================================================\n"
+ "// Namespace\n"
+ "//==============================================================================\n"
+ "namespace Q3DStudio\n"
+ "{\n"
+ "\n"
+ "// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AUTOGENERATED CODE "
+ "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "\n"
+ "// Run the AttributeHashes project to regenerate this file from Attributehashes.txt list\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n");
+
+ WriteLookup(theSource);
+
+ // Footer
+ fprintf(theSource, "\n"
+ "} // namespace Q3DStudio\n"
+ "\n");
+
+ // Close include
+ fclose(theSource);
+
+ // Completed
+ fprintf(stdout, "Completed converting %d string to hashes.\n", int(g_StringList.size()));
+ return 0;
+}
diff --git a/src/Runtime/Source/Engine/Include/EnginePrefix.h b/src/Runtime/Source/Engine/Include/EnginePrefix.h
new file mode 100644
index 00000000..475b513b
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/EnginePrefix.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "render/backends/gl/Qt3DSOpenGLPrefix.h"
+
+#ifdef _WIN32
+//==============================================================================
+// DEFINES
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+//==============================================================================
+// DISABLED WARNINGS
+//
+// Note that most of these warnings are tuned off by default by the compiler
+// even at warning level 4. Using option /Wall turns on all warnings and makes
+// even standard Microsoft include files cry. We had to turn off these or
+// turn off warnings individually for each standard include file which was
+// too much work. Point is that /Wall is like Warning Level 5 and this brings
+// it down to about Warning level 4.5, still way above /W4.
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+//#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
+//#pragma warning( disable : 4511 ) // copy constructor could not be generated
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#pragma warning(disable : 4514) // unreferenced inline function has been removed
+//#pragma warning( disable : 4619 ) // #pragma warning : there is no warning number '4619' (in
+//string.h)
+#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy
+ // constructor is inaccessible
+#pragma warning(disable : 4626) // assignment operator could not be generated because a base class
+ // assignment operator is inaccessible
+//#pragma warning( disable : 4640 ) // TODO MF Remove - construction of local static object is
+//not thread-safe
+#pragma warning(disable : 4710) // function not inlined
+#pragma warning(disable : 4711) // function selected for automatic inline expansion
+#pragma warning( \
+ disable : 4738) // storing 32-bit float result in memory, possible loss of performance
+#pragma warning(disable : 4826) // Conversion from 'const void *' to 'void *' is sign-extended
+//#pragma warning( disable : 4996 ) // _snprintf' was declared deprecated
+
+#endif //_WIN32
+
+//==============================================================================
+// Non-windows environments need to declare this
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+//==============================================================================
+// STD - Standard includes MUST come first
+#ifdef _WIN32
+#pragma warning(push, 3)
+#pragma warning( \
+ disable : 4548) // expression before comma has no effect; expected expression with side-effect
+#endif
+
+#include <stdio.h>
+#include <iostream>
+
+#if defined(_PCPLATFORM) || defined(_TEGRAPLATFORM)
+#include <tchar.h>
+#endif
+
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+//==============================================================================
+// Runtime
+//==============================================================================
+#include "UICAssert.h"
+#include "UICMacros.h"
+#include "UICElementSystem.h"
+#include "UICLuaEngine.h"
+#include "UICQmlEngine.h"
+#include "UICAttributeHashes.h"
+
+//==============================================================================
+// Additional Linux only dependencies
+//==============================================================================
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+
+#pragma pack(1)
+struct BITMAPFILEHEADER
+{
+ Q3DStudio::UINT16 bfType;
+ Q3DStudio::UINT32 bfSize;
+ Q3DStudio::UINT16 bfReserved1;
+ Q3DStudio::UINT16 bfReserved2;
+ Q3DStudio::UINT32 bfOffBits;
+};
+#pragma pack()
+
+#pragma pack(1)
+
+typedef struct tagBITMAPINFOHEADER
+{
+ Q3DStudio::UINT32 biSize;
+ Q3DStudio::INT32 biWidth;
+ Q3DStudio::INT32 biHeight;
+ Q3DStudio::UINT16 biPlanes;
+ Q3DStudio::UINT16 biBitCount;
+ Q3DStudio::UINT32 biCompression;
+ Q3DStudio::UINT32 biSizeImage;
+ Q3DStudio::INT32 biXPelsPerMeter;
+ Q3DStudio::INT32 biYPelsPerMeter;
+ Q3DStudio::UINT32 biClrUsed;
+ Q3DStudio::UINT32 biClrImportant;
+} BITMAPINFOHEADER;
+
+#pragma pack()
+
+#define UNREFERENCED_PARAMETER(theParam) theParam;
+
+#endif
diff --git a/src/Runtime/Source/Engine/Include/NVImageScaler.h b/src/Runtime/Source/Engine/Include/NVImageScaler.h
new file mode 100644
index 00000000..069604a6
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/NVImageScaler.h
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+namespace Q3DStudio {
+namespace ImageScaler {
+
+ //==============================================================================
+ /**
+ *
+ */
+ template <INT32 TNumChannels>
+ inline void BilinearReduceRows(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ CHAR *outDstBuffer, INT32 inDstHeight)
+ {
+ INT32 theDDAConst = static_cast<INT32>(1024.0 * inDstHeight / inSrcHeight);
+ INT32 theDDAAccum = 0;
+ INT32 thePixelCount;
+
+ INT32 theSrcRow;
+ INT32 theSrcCol;
+ INT32 theDstRow;
+
+ INT32 theChannelAccum[TNumChannels] = { 0 };
+
+ CHAR *theDstPointer = outDstBuffer;
+ const CHAR *theSrcPointer = inSrcBuffer;
+ const CHAR *theSrcColPointer = NULL;
+ CHAR *theDstColPointer = NULL;
+
+ INT32 theStepSize = TNumChannels;
+ INT32 theSrcStride = TNumChannels * inSrcWidth;
+ INT32 theDstStride = TNumChannels * inSrcWidth;
+
+ for (theSrcCol = 0; theSrcCol < inSrcWidth; ++theSrcCol) {
+ theSrcColPointer = theSrcPointer + (theSrcCol * theStepSize);
+ theDstColPointer = theDstPointer + (theSrcCol * theStepSize);
+
+ theSrcRow = 0L;
+ theDstRow = 0L;
+ thePixelCount = 0L;
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] = 0L;
+
+ theDDAAccum = 0L;
+
+ while (theSrcRow < inSrcHeight) {
+ while ((theDDAAccum < 1024L) && (theSrcRow < inSrcHeight)) {
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] +=
+ 1024L * theSrcColPointer[(theSrcRow * theSrcStride) + idx];
+
+ theDDAAccum += theDDAConst;
+ thePixelCount += 1024L;
+ ++theSrcRow;
+ }
+
+ theDDAAccum = (theSrcRow < inSrcHeight) ? (theDDAAccum - 1024L) : (0L);
+ thePixelCount -= theDDAAccum;
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] -= theDDAAccum
+ * (INT32)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + idx];
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theDstColPointer[(theDstRow * theDstStride) + idx] =
+ (CHAR)(theChannelAccum[idx] / thePixelCount);
+
+ thePixelCount = 1024L - theDDAAccum;
+ ++theDstRow;
+
+ if (theDstRow >= inDstHeight)
+ break;
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] = thePixelCount
+ * (INT32)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + idx];
+ }
+ }
+ }
+
+ inline void BilinearReduceRows(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ INT32 inChannels, CHAR *outDstBuffer, INT32 inDstHeight)
+ {
+ switch (inChannels) {
+ case 4:
+ BilinearReduceRows<4>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight);
+ break;
+ case 3:
+ BilinearReduceRows<3>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight);
+ break;
+ case 2:
+ BilinearReduceRows<2>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight);
+ break;
+ case 1:
+ BilinearReduceRows<1>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight);
+ break;
+ }
+ }
+
+ template <INT32 TNumChannels>
+ inline void BilinearReduceCols(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ CHAR *outDstBuffer, INT32 inDstWidth)
+ {
+ INT32 theDDAConst = static_cast<INT32>(1024.0 * inDstWidth / inSrcWidth);
+ INT32 theDDAAccum = 0L;
+ INT32 thePixelCount;
+
+ INT32 theSrcRow;
+ INT32 theSrcCol;
+ INT32 theDstCol;
+
+ INT32 theChannelAccum[TNumChannels];
+
+ CHAR *theDstPointer = outDstBuffer;
+ const CHAR *theSrcPointer = inSrcBuffer;
+ const CHAR *theSrcRowPointer;
+ CHAR *theDstRowPointer;
+
+ INT32 theSrcStepSize = TNumChannels;
+ INT32 theDstStepSize = TNumChannels;
+
+ for (theSrcRow = 0; theSrcRow < inSrcHeight; ++theSrcRow) {
+
+ theSrcRowPointer = theSrcPointer + (theSrcRow * inSrcWidth * theSrcStepSize);
+ theDstRowPointer = theDstPointer + (theSrcRow * inDstWidth * theDstStepSize);
+
+ theSrcCol = 0L;
+ theDstCol = 0L;
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] = 0L;
+ thePixelCount = 0L;
+ theDDAAccum = 0L;
+
+ while (theSrcCol < inSrcWidth) {
+ while ((theDDAAccum < 1024L) && (theSrcCol < inSrcWidth)) {
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] +=
+ 1024L * theSrcRowPointer[(theSrcCol * theSrcStepSize) + idx];
+
+ theDDAAccum += theDDAConst;
+ thePixelCount += 1024L;
+ ++theSrcCol;
+ }
+
+ theDDAAccum = (theSrcCol < inSrcWidth) ? (theDDAAccum - 1024L) : (0L);
+ thePixelCount -= theDDAAccum;
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] -= theDDAAccum
+ * (INT32)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + idx];
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theDstRowPointer[(theDstCol * theDstStepSize) + idx] =
+ (CHAR)(theChannelAccum[idx] / thePixelCount);
+
+ thePixelCount = 1024L - theDDAAccum;
+ ++theDstCol;
+
+ if (theDstCol >= inDstWidth) {
+ break;
+ }
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theChannelAccum[idx] = thePixelCount
+ * (INT32)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + idx];
+ }
+ }
+ }
+
+ inline void BilinearReduceCols(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ INT32 inChannels, CHAR *&outDstBuffer, INT32 inDstWidth)
+ {
+ switch (inChannels) {
+ case 4:
+ BilinearReduceCols<4>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth);
+ break;
+ case 3:
+ BilinearReduceCols<3>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth);
+ break;
+ case 2:
+ BilinearReduceCols<2>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth);
+ break;
+ case 1:
+ BilinearReduceCols<1>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth);
+ break;
+ }
+ }
+
+ template <INT32 TNumChannels>
+ inline void BilinearReduceImage(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ CHAR *outDstBuffer, INT32 inDstWidth, INT32 inDstHeight)
+ {
+ // Number larger than 1024
+ // One pixel in the source image is equivalent to this much of a pixel
+ // in terms of dest pixels.
+ INT32 theXIncrement = static_cast<INT32>(1024.f * inSrcWidth / inDstWidth);
+ // How many rows do we skip, in fixed point arithmetic, when we bump lines
+ INT32 theYIncrement = static_cast<INT32>(1024.f * inSrcHeight / inDstHeight);
+ // We are starting at position .5 in textel space
+ INT32 theSrcYPtr = 0;
+ CHAR *theDstPtr = outDstBuffer;
+ for (INT32 theHeightIndex = 0; theHeightIndex < inDstHeight;
+ ++theHeightIndex, theSrcYPtr += theYIncrement) {
+ INT32 theSrcXPtr = 0;
+ for (INT32 theWidthIndex = 0; theWidthIndex < inDstWidth;
+ ++theWidthIndex, theSrcXPtr += theXIncrement, theDstPtr += TNumChannels) {
+ INT32 theAccum[TNumChannels] = { 0 };
+ INT32 theNumPixels = 0;
+ // Pull all reasonable pixels from the source image.
+ INT32 theStartRow = (theSrcYPtr / 1024);
+ INT32 theStopRow = (theSrcYPtr + theYIncrement) / 1024;
+ INT32 theStartColumn = theSrcXPtr / 1024;
+ INT32 theStopColumn = (theSrcXPtr + theXIncrement) / 1024;
+ // Average everything between the columns
+ for (INT32 theRow = theStartRow; theRow < theStopRow; ++theRow) {
+ INT32 theSrcAddr = (theRow * inSrcWidth + theStartColumn) * TNumChannels;
+ for (INT32 theCol = theStartColumn; theCol < theStopColumn;
+ ++theCol, theSrcAddr += TNumChannels) {
+ ++theNumPixels;
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theAccum[idx] += inSrcBuffer[theSrcAddr + idx];
+ }
+ }
+
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theDstPtr[idx] = theAccum[idx] / theNumPixels;
+ }
+ }
+ }
+
+ template <INT32 TNumChannels>
+ inline void NearestReduceImage(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ CHAR *outDstBuffer, INT32 inDstWidth, INT32 inDstHeight)
+ {
+ // Number larger than 1024
+ // One pixel in the source image is equivalent to this much of a pixel
+ // in terms of dest pixels.
+ INT32 theXIncrement = static_cast<INT32>(1024.f * inSrcWidth / inDstWidth);
+ // How many rows do we skip, in fixed point arithmetic, when we bump lines
+ INT32 theYIncrement = static_cast<INT32>(1024.f * inSrcHeight / inDstHeight);
+ // We are starting at position .5 in textel space
+ INT32 theSrcYPtr = theYIncrement / 2;
+ CHAR *theDstPtr = outDstBuffer;
+ for (INT32 theHeightIndex = 0; theHeightIndex < inDstHeight;
+ ++theHeightIndex, theSrcYPtr += theYIncrement) {
+ INT32 theSrcRow = (theSrcYPtr / 1024) * inSrcWidth * TNumChannels;
+ INT32 theSrcXPtr = theXIncrement / 2;
+ for (INT32 theWidthIndex = 0; theWidthIndex < inDstWidth;
+ ++theWidthIndex, theSrcXPtr += theXIncrement, theDstPtr += TNumChannels) {
+ INT32 theSrcPtr = theSrcRow + (theSrcXPtr >> 10) * TNumChannels;
+ for (INT32 idx = 0; idx < TNumChannels; ++idx)
+ theDstPtr[idx] = inSrcBuffer[theSrcPtr + idx];
+ }
+ }
+ }
+
+ inline void NearestReduceImage(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ INT32 inChannels, CHAR *outDstBuffer, INT32 inDstWidth,
+ INT32 inDstHeight)
+ {
+ switch (inChannels) {
+ case 4:
+ NearestReduceImage<4>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth,
+ inDstHeight);
+ break;
+ case 3:
+ NearestReduceImage<3>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth,
+ inDstHeight);
+ break;
+ case 2:
+ NearestReduceImage<2>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth,
+ inDstHeight);
+ break;
+ case 1:
+ NearestReduceImage<1>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth,
+ inDstHeight);
+ break;
+ }
+ }
+}
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Engine/Include/OpenKodeInclude.h b/src/Runtime/Source/Engine/Include/OpenKodeInclude.h
new file mode 100644
index 00000000..06bdf006
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/OpenKodeInclude.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+// Wrap the <kd/kd.h> include so we can ensure it gets compiled with 8 byte alignment
+// also, this means we need to compile nv_main.c (via right click -> properties) with 8 byte
+// alignment too!
+
+#pragma pack(push)
+#pragma pack(8)
+#include <KD/kd.h>
+#pragma pack(pop)
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace NVUI {
+
+} // namespace NVUI
diff --git a/src/Runtime/Source/Engine/Include/UICEGLInfo.h b/src/Runtime/Source/Engine/Include/UICEGLInfo.h
new file mode 100644
index 00000000..c8ffcf2f
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICEGLInfo.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_EGLINFO_H
+#define UIC_EGLINFO_H
+#include <EGL/egl.h>
+
+namespace Q3DStudio {
+struct SEGLInfo
+{
+ EGLDisplay display;
+ EGLSurface surface;
+ EGLContext context;
+ EGLConfig config;
+ EGLNativeWindowType nativewin;
+};
+};
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Engine/Include/UICEGLWindowSystem.h b/src/Runtime/Source/Engine/Include/UICEGLWindowSystem.h
new file mode 100644
index 00000000..a28cf341
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICEGLWindowSystem.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_EGL_WINDOW_SYSTEM_H
+#define UIC_EGL_WINDOW_SYSTEM_H
+#include "UICEGLInfo.h"
+#include "UICWindowSystem.h"
+#include "nv_main/nv_main.h"
+
+namespace Q3DStudio {
+struct SEGLWindowSystemImpl : public IWindowSystem
+{
+ SEGLInfo m_EGLInfo;
+
+ virtual SSize GetWindowDimensions()
+ {
+ int w, h;
+
+ eglQuerySurface(gEGLHandles[0].display, gEGLHandles[0].surface, EGL_WIDTH, &w);
+ eglQuerySurface(gEGLHandles[0].display, gEGLHandles[0].surface, EGL_HEIGHT, &h);
+
+ return SSize(w, h);
+ }
+ virtual void SetWindowDimensions(const SSize &) {}
+ // For platforms that support it, we get the egl info for render plugins
+ // Feel free to return NULL.
+ virtual SEGLInfo *GetEGLInfo()
+ {
+ m_EGLInfo.display = gEGLHandles[0].display;
+ m_EGLInfo.surface = gEGLHandles[0].surface;
+ m_EGLInfo.context = gEGLHandles[0].context;
+ m_EGLInfo.config = gEGLHandles[0].config;
+ m_EGLInfo.nativewin = gEGLHandles[0].nativewin;
+ return &m_EGLInfo;
+ }
+ // on some systems we allow our default render target to be a offscreen buffer
+ // otherwise return 0;
+ virtual int GetDefaultRenderTargetID() { return 0; }
+ // returns the depth buffer bit count for the render window
+ // overwrite this one for your own needs
+ virtual int GetDepthBitCount()
+ {
+ EGLint depth = 16;
+#ifdef _PLATFORM_USE_EGL
+ if (gEGLHandles[0].display && gEGLHandles[0].config)
+ eglGetConfigAttrib(gEGLHandles[0].display, gEGLHandles[0].config, EGL_DEPTH_SIZE,
+ &depth);
+#endif
+
+ return depth;
+ }
+};
+};
+
+#endif
diff --git a/src/Runtime/Source/Engine/Include/UICPluginDLL.h b/src/Runtime/Source/Engine/Include/UICPluginDLL.h
new file mode 100644
index 00000000..3d9e0b40
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICPluginDLL.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+#include "UICBasicPluginDLL.h"
+
+#include <QtGlobal>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+// Enums
+//==============================================================================
+// Texture format
+typedef enum _ETEXTUREFORMAT {
+ ETEXTUREFORMAT_Unknown = 0,
+ ETEXTUREFORMAT_RGBA8,
+ ETEXTUREFORMAT_RGB8,
+ ETEXTUREFORMAT_RGB565,
+ ETEXTUREFORMAT_RGBA5551,
+ ETEXTUREFORMAT_Alpha8,
+ ETEXTUREFORMAT_Luminance8,
+ ETEXTUREFORMAT_LuminanceAlpha8,
+ ETEXTUREFORMAT_RGBA_DXT1,
+ ETEXTUREFORMAT_RGB_DXT1,
+ ETEXTUREFORMAT_RGBA_DXT3,
+ ETEXTUREFORMAT_RGBA_DXT5,
+} ETEXTUREFORMAT;
+
+//==============================================================================
+// Functions declarations
+//==============================================================================
+
+//==============================================================================
+/**
+ * Perform plugin initialization.
+ * @param inArgs string arguments from XIF arg parameter
+ * @return EDLLSTATUS_OK if initialization suceeds
+ */
+typedef long (*PROC_Initialize)(const char *inArgs);
+Q_DECL_EXPORT long Initialize(const char *inArgs);
+
+//==============================================================================
+/**
+ * Passes the current screen size and format to the plugin.
+ * Plugin should override with it's own desired settings.
+ * This affects the size and format of the allocated offscreen texture.
+ * When resources are allocated, SetAllocatedRenderInfo will be called to
+ * inform the plugin of the allocated resources
+ * @param ioWidth width
+ * @param ioHeight height
+ * @param ioTextureFormat See ETEXTUREFORMAT
+ */
+typedef void (*PROC_GetDesiredTextureSize)(long *ioWidth, long *ioHeight,
+ ETEXTUREFORMAT *ioTextureFormat);
+Q_DECL_EXPORT void GetDesiredTextureSize(long *ioWidth, long *ioHeight,
+ ETEXTUREFORMAT *ioTextureFormat);
+
+//==============================================================================
+/**
+ * Information about the current EGL environment.
+ * Useful if plugin wishes to switch EGLContext to manage it's own state.
+ * Optional
+ * @param inEGLDisplay pointer to EGLDisplay
+ * @param inEGLCurrentContext pointer to current EGLContext
+ * @param inEGLSurface pointer to EGLSurface
+ * @param inEGLConfig pointer to EGLConfig attributes
+ */
+typedef void (*PROC_SetEGLInfo)(void *inEGLDisplay, void *inEGLCurrentContext, void *inEGLSurface,
+ void *inEGLConfig);
+Q_DECL_EXPORT void SetEGLInfo(void *inEGLDisplay, void *inEGLCurrentContext,
+ void *inEGLSurface, void *inEGLConfig);
+
+//==============================================================================
+/**
+ * Render pulse whenever the runtime requires a frame from the plugin.
+ * Note that if plugin wishes to switch EGLContext,
+ * it should restore the previous EGLContext(obtained from SetEGLInfo) at the end of this
+ *function.
+ * @param inHostWidth width of the host rectangle
+ * @param inHostHeight height of the host rectangle
+ * @param inDrawTime current time in milliseconds
+ */
+typedef void (*PROC_Render)(long inHostWidth, long inHostHeight, long inDrawTime);
+Q_DECL_EXPORT void Render(long inHostWidth, long inHostHeight, long inDrawTime);
+
+//==============================================================================
+/**
+ * Send a message comprising of 2 longs into the plugin.
+ * This can be invoked from Lua script using 'sendPluginMessage'.
+ * @param inArg1 first argument
+ * @param inArg2 second argument
+ * @return EDLLSTATUS_OK if successful
+ */
+typedef long (*PROC_SendPluginMessage)(long inArg1, long inArg2);
+Q_DECL_EXPORT long SendPluginMessage(long inArg1, long inArg2);
+
+//==============================================================================
+/**
+ * Perform plugin uninitialization.
+ * @return EDLLSTATUS_OK if successful
+ */
+typedef long (*PROC_Uninitialize)();
+Q_DECL_EXPORT long Uninitialize();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/Runtime/Source/Engine/Include/UICRenderRuntimeBinding.h b/src/Runtime/Source/Engine/Include/UICRenderRuntimeBinding.h
new file mode 100644
index 00000000..e38c78fa
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICRenderRuntimeBinding.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef UIC_RENDER_RUNTIME_BINDING_H
+#define UIC_RENDER_RUNTIME_BINDING_H
+#include "UICRuntimeFactory.h"
+#include "EABase/eabase.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+
+#include <QSurfaceFormat>
+
+namespace Q3DStudio {
+class ITegraApplicationRenderEngine;
+class ITimeProvider;
+class IWindowSystem;
+}
+
+namespace uic {
+namespace render {
+
+ class ITextRenderer;
+ class IRuntimeFactoryRenderFactory
+ {
+ protected:
+ virtual ~IRuntimeFactoryRenderFactory() {}
+ public:
+ virtual qt3ds::render::NVRenderContext *
+ CreateRenderContext(qt3ds::NVFoundationBase &foundat, qt3ds::foundation::IStringTable &strt) = 0;
+ };
+
+ class IUICRenderFactory;
+
+ class IUICRenderFactoryCore : public Q3DStudio::IRuntimeFactoryCore
+ {
+ public:
+ virtual IUICRenderFactory &
+ CreateRenderFactory(const QSurfaceFormat &format) = 0;
+
+ static IUICRenderFactoryCore &
+ CreateRenderFactoryCore(const char8_t *inApplicationDirectory,
+ Q3DStudio::IWindowSystem &inWindowSystem,
+ Q3DStudio::ITimeProvider &inTimeProvider);
+ };
+
+ class IUICRenderFactory : public Q3DStudio::IRuntimeFactory
+ {
+ public:
+ virtual Q3DStudio::ITegraApplicationRenderEngine &CreateRenderEngine() = 0;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Engine/Include/UICRenderRuntimeBindingImpl.h b/src/Runtime/Source/Engine/Include/UICRenderRuntimeBindingImpl.h
new file mode 100644
index 00000000..7d0e512b
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICRenderRuntimeBindingImpl.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_RUNTIME_BINDING_IMPL_H
+#define UIC_RENDER_RUNTIME_BINDING_IMPL_H
+
+#include "UICRenderRuntimeBinding.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Utils.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICRender.h"
+#include "UICRenderContext.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICIPresentation.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICRenderPresentation.h"
+#include "UICRenderScene.h"
+#include "UICRenderLayer.h"
+#include "UICRenderLight.h"
+#include "UICRenderCamera.h"
+#include "UICRenderModel.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderImage.h"
+#include "UICUIPParser.h"
+#include "UICRenderEffect.h"
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderEffectSystem.h"
+#include "foundation/Qt3DSInvasiveSet.h"
+#include "UICIPresentation.h"
+#include "UICTextRenderer.h"
+#include "UICRenderText.h"
+#include "foundation/StrConvertUTF.h"
+#include "UICMetadata.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderContext.h"
+#include "UICWindowSystem.h"
+#include "UICRenderPluginGraphObject.h"
+#include "UICRenderReferencedMaterial.h"
+#include "UICRenderText.h"
+#include "foundation/Qt3DSMutex.h"
+
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4355)
+#else
+#define stricmp strcasecmp
+#endif
+
+using namespace uic::render;
+using eastl::make_pair;
+using eastl::pair;
+
+namespace uic {
+namespace render {
+
+ extern qt3ds::foundation::MallocAllocator g_BaseAllocator;
+ // Small core object shared between the larger objects.
+ // creates the object stack needed by the rest of the system.
+ struct SBindingCore : public NVRefCounted
+ {
+ qt3ds::render::CAllocator m_Allocator;
+ QT3DSU8 *m_FlowData;
+ NVScopedRefCounted<NVFoundation> m_Foundation;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IUICRenderContextCore> m_CoreContext;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ NVScopedRefCounted<IUICRenderContext> m_UICContext;
+ SWindowDimensions m_WindowDimensions;
+ eastl::string m_PrimitivePath;
+ bool m_RenderRotationsEnabled;
+ bool m_WriteOutShaderCache;
+ volatile QT3DSI32 mRefCount;
+ Q3DStudio::IWindowSystem &m_WindowSystem;
+ Q3DStudio::ITimeProvider &m_TimeProvider;
+
+ SBindingCore(const char8_t *inPrimitivePath, Q3DStudio::IWindowSystem &inWindowSystem,
+ Q3DStudio::ITimeProvider &inTimeProvider)
+ : m_Allocator()
+ , m_FlowData(NULL)
+ , m_Foundation(NVCreateFoundation(QT3DS_FOUNDATION_VERSION, m_Allocator))
+ , m_StringTable(IStringTable::CreateStringTable(m_Foundation->getAllocator()))
+ , m_CoreContext(IUICRenderContextCore::Create(*m_Foundation, *m_StringTable))
+ , m_PrimitivePath(inPrimitivePath)
+ , m_RenderRotationsEnabled(false)
+ , m_WriteOutShaderCache(false)
+ , mRefCount(0)
+ , m_WindowSystem(inWindowSystem)
+ , m_TimeProvider(inTimeProvider)
+ {
+ m_CoreContext->SetTextRendererCore(
+ ITextRendererCore::CreateQtTextRenderer(*m_Foundation, *m_StringTable));
+
+ m_CoreContext->SetOnscreenTextRendererCore(
+ ITextRendererCore::CreateOnscreenTextRenderer(*m_Foundation));
+ }
+ virtual ~SBindingCore()
+ {
+ m_CoreContext = NULL;
+ m_UICContext = NULL;
+ m_RenderContext = NULL;
+ if (m_FlowData)
+ m_Allocator.deallocate(m_FlowData);
+ m_FlowData = NULL;
+ }
+
+ void CreateRenderContext(uic::render::IRuntimeFactoryRenderFactory &inContextFactory)
+ {
+ m_RenderContext = inContextFactory.CreateRenderContext(*m_Foundation, *m_StringTable);
+ if (m_RenderContext)
+ m_UICContext =
+ m_CoreContext->CreateRenderContext(*m_RenderContext, m_PrimitivePath.c_str());
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_BaseAllocator)
+
+ NVAllocatorCallback &GetAllocator() { return m_Allocator; }
+
+ Q3DStudio::ITegraApplicationRenderEngine &CreateRenderer();
+ };
+ struct STranslatorContext
+ {
+ };
+
+ ////////////////////////////////////////
+ // Translators are the set of objects that translate
+ // changes in the elements to changes in the scene graph.
+ // TODO - get rid of the virtual functions and just do dispatch
+ // on the m_RenderObject.m_Type.
+ ////////////////////////////////////////
+ class CUICTranslator
+ {
+ public:
+ QT3DSU32 m_DirtyIndex;
+ Q3DStudio::TElement *m_Element;
+ SGraphObject *m_RenderObject;
+ STranslatorContext *m_TranslatorContext;
+
+ CUICTranslator(Q3DStudio::TElement &inElement, SGraphObject &inRenderObject);
+ GraphObjectTypes::Enum GetUIPType() const { return m_RenderObject->m_Type; }
+ Q3DStudio::TElement &Element() { return *m_Element; }
+ SGraphObject &RenderObject() { return *m_RenderObject; }
+
+ // This function is done via a dispatch mechanism on the graph object type.
+ void OnElementChanged(SPresentation &inPresentation, IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation);
+
+ void Save(SWriteBuffer &inWriteBuffer, QT3DSU32 inGraphObjectOffset);
+ // Most translators don't need an extra allocation but effects due because the mapping from
+ // effect property
+ // to runtime property is too complex to do quickly.
+ static CUICTranslator *LoadTranslator(SDataReader &inReader, size_t inElemOffset,
+ NVDataRef<QT3DSU8> inSGSection,
+ NVAllocatorCallback &inAllocator);
+
+ static CUICTranslator *GetTranslatorFromGraphNode(SGraphObject &inObject);
+ static CUICTranslator *CreateTranslatorForElement(Q3DStudio::TElement &inElement,
+ SGraphObject &inGraphObject,
+ NVAllocatorCallback &inAlloc);
+ static Q3DStudio::IPresentation *
+ GetPresentationFromPresentation(SPresentation &inPresentation);
+ static void InitializePointerTags(IStringTable &inTable);
+ static void AssignUserData(Q3DStudio::IPresentation &inPresentation,
+ SPresentation &inGraphPresentation);
+ };
+
+ struct STranslatorGetOp
+ {
+ QT3DSU32 operator()(const CUICTranslator &translator) { return translator.m_DirtyIndex; }
+ };
+ struct STranslatorSetOp
+ {
+ void operator()(CUICTranslator &translator, QT3DSU32 value)
+ {
+ translator.m_DirtyIndex = value;
+ }
+ };
+
+ typedef InvasiveSet<CUICTranslator, STranslatorGetOp, STranslatorSetOp> TTranslatorDirytSet;
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Engine/Include/UICTegraApplication.h b/src/Runtime/Source/Engine/Include/UICTegraApplication.h
new file mode 100644
index 00000000..0f9fea4a
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICTegraApplication.h
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "EnginePrefix.h"
+#include "UICIStateful.h"
+#include "foundation/Qt3DSVec4.h"
+#include "foundation/Qt3DSOption.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICWindowSystem.h"
+#include "UICTimer.h"
+#include "UICPresentation.h"
+#include "UICRenderRuntimeBinding.h"
+#include <QtCore/qobject.h>
+#include <QtGui/qsurfaceformat.h>
+#include <KD/kd.h>
+//==============================================================================
+// Namespace
+//==============================================================================
+
+struct lua_State;
+
+typedef void (*qml_Function)(void *inUserData);
+
+class QINDDViewSignalProxy : public QObject
+{
+ Q_OBJECT
+Q_SIGNALS:
+ void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
+ void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
+};
+
+namespace uic {
+class UICAssetVisitor;
+}
+
+namespace qt3ds {
+namespace render {
+class NVRenderContext;
+}
+}
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTegraInputEngine;
+class CTegraRenderEngine;
+class IScene;
+class CInputEngine;
+class IAudioPlayer;
+
+class ITegraRenderStateManager : public IStatefulStackBase
+{
+protected:
+ virtual ~ITegraRenderStateManager() {}
+public:
+ virtual void SetViewport(INT32 inX, INT32 inY, INT32 inWidth, INT32 inHeight) = 0;
+ virtual void SetScissorTestEnabled(bool inValue) = 0;
+ virtual void SaveAllState() = 0;
+ virtual void RestoreAllState() = 0;
+};
+
+struct TegraRenderScaleModes
+{
+ enum Enum {
+ ExactSize = 0, // Ensure the viewport is exactly same size as application
+ ScaleToFit = 1, // Resize viewport keeping aspect ratio
+ ScaleToFill = 2, // Resize viewport to entire window
+ };
+};
+
+struct TegraRenderShadeModes
+{
+ enum Enum {
+ Shaded = 0, // Geometry is shaded only
+ ShadedWireframe = 1, // Wireframe is drawn on top shaded geometry
+ Wireframe = 2, // Wireframe only
+ };
+};
+
+class ITegraApplicationRenderEngine
+{
+protected:
+ virtual ~ITegraApplicationRenderEngine() {}
+
+public:
+ virtual void SetViewport(INT32 inX, INT32 inY, INT32 inWidth, INT32 inHeight) = 0;
+ virtual void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) = 0;
+ virtual void ensureRenderTarget() = 0;
+ virtual void CheckResize(bool inForce, IPresentation &inActivePresentation) = 0;
+ virtual BOOL LoadShaderCache(const CHAR *inFilePath) = 0;
+ virtual void AbandonLoadingImages(IScene &inScene) = 0;
+ virtual BOOL IsPickValid(KDfloat32 &outX, KDfloat32 &outY,
+ const IPresentation &inPresentation) const = 0;
+ virtual void SetScaleMode(TegraRenderScaleModes::Enum inScale) = 0;
+ virtual void SetShadeMode(TegraRenderShadeModes::Enum inShade) = 0;
+ virtual TegraRenderScaleModes::Enum GetScaleMode() const = 0;
+
+ // TODO: To be removed, not used anywhere anymore
+ void CycleScaleMode()
+ {
+ int mode = (int)GetScaleMode();
+ mode = (mode + 1) % 3;
+ SetScaleMode((TegraRenderScaleModes::Enum)mode);
+ }
+
+ virtual ITegraRenderStateManager &GetTegraRenderStateManager() = 0;
+ virtual qt3ds::render::NVRenderContext &GetRenderContext() = 0;
+ virtual void SetMatteColor(qt3ds::foundation::Option<qt3ds::QT3DSVec4> inColor) = 0;
+ virtual void EnableRenderRotation(bool inEnable) = 0;
+ virtual void SetWriteOutShaderCache(bool inWriteOutShaderCache) = 0;
+ virtual void Release() = 0;
+ virtual void RenderText2D(FLOAT x, FLOAT y, qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
+ const char *text) = 0;
+ virtual void RenderGpuProfilerStats(FLOAT x, FLOAT y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor) = 0;
+
+ // Set the watermark texture as a compressed PNG file.
+ virtual bool SetWatermarkTextureDataDDS(const unsigned char *inTextureData,
+ size_t inDataSize) = 0;
+ virtual void SetWatermarkLocation(float x, float y) = 0;
+};
+
+class INDDView : public qt3ds::foundation::NVRefCounted
+{
+public:
+ virtual ~INDDView(){}
+
+public: // loading
+ virtual bool BeginLoad(const QString &sourcePath) = 0;
+ virtual bool HasOfflineLoadingCompleted() = 0;
+ virtual void InitializeGraphics(const QSurfaceFormat &format) = 0;
+
+ virtual void Cleanup() = 0;
+
+ virtual bool CanRender() = 0;
+
+ virtual void Render() = 0;
+
+ virtual bool WasLastFrameDirty() = 0;
+
+ virtual KDint HandleMessage(const KDEvent *inEvent) = 0;
+
+ virtual void Pause() = 0;
+ virtual void UnPause() = 0;
+ virtual bool IsPaused() = 0;
+ virtual INT32 GetFrameCount() = 0;
+ virtual void showOnScreenStats(bool) = 0;
+
+public: // Input engine access
+ virtual CInputEngine *GetInputEngine() = 0;
+ // Only valid after InitializeGraphics
+ virtual ITegraApplicationRenderEngine *GetTegraRenderEngine() = 0;
+
+public:
+ virtual void GoToSlideByName(const char *elementPath, const char *slideName) = 0;
+ virtual void GoToSlideByIndex(const char *elementPath, const int slideIndex) = 0;
+ virtual void GoToSlideRelative(const char *elementPath, const bool next, const bool wrap) = 0;
+ virtual bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName) = 0;
+ virtual void SetPresentationAttribute(const char *presId, const char *, const char *value) = 0;
+ virtual void GoToTime(const char *elementPath, const float time) = 0;
+ virtual void SetGlobalAnimationTime(qint64 inMilliSecs) = 0;
+ virtual void SetAttribute(const char *elementPath, const char *attributeName,
+ const char *value) = 0;
+ virtual bool GetAttribute(const char *elementPath, const char *attributeName, void *value) = 0;
+ virtual void FireEvent(const char *element, const char *evtName) = 0;
+ virtual bool PeekCustomAction(char *&outElementPath, char *&outActionName) = 0;
+ virtual bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) = 0;
+ virtual void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) = 0;
+ virtual bool AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction) = 0;
+ virtual qt3ds::foundation::Option<SPresentationSize> GetPresentationSize() = 0;
+
+ virtual void setAssetVisitor(uic::UICAssetVisitor *) = 0;
+
+public:
+ static INDDView &Create(ITimeProvider &inProvider, IWindowSystem &inWindowSystem,
+ IAudioPlayer *inAudioPlayer = NULL);
+
+public:
+ QINDDViewSignalProxy *signalProxy();
+private:
+ QINDDViewSignalProxy m_SignalProxy;
+};
+
+class CTegraApplication
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ qt3ds::foundation::NVScopedRefCounted<INDDView> m_NDDView;
+
+public:
+ CTegraApplication(ITimeProvider &inProvider, IWindowSystem &inWindowSystem,
+ IAudioPlayer *inAudioPlayer = 0);
+ virtual ~CTegraApplication();
+ // loading
+ KDint BeginLoad(const QString &sourcePath);
+ // asynchronous BeginLoad completed? That only valid for binary presentation, for text
+ // presentation, always true
+ bool HasOfflineLoadingCompleted() { return m_NDDView->HasOfflineLoadingCompleted(); }
+ // Invokes m_ApplicationCore->CreateApplication(), a blocking function ensures binary loading
+ // completed
+ void InitializeGraphics(const QSurfaceFormat& format);
+
+ void Cleanup() { m_NDDView->Cleanup(); }
+ bool CanRender() { return m_NDDView->CanRender(); }
+ void Render();
+ bool WasLastFrameDirty() { return m_NDDView->WasLastFrameDirty(); }
+
+ KDint HandleMessage(const KDEvent *inEvent);
+ void Pause() { m_NDDView->Pause(); }
+ void UnPause() { m_NDDView->UnPause(); }
+ bool IsPaused() { return m_NDDView->IsPaused(); }
+ INT32 GetFrameCount() { return m_NDDView->GetFrameCount(); }
+
+public:
+ CInputEngine *GetInputEngine() { return m_NDDView->GetInputEngine(); }
+ // Only valid after InitializeGraphics
+ ITegraApplicationRenderEngine *GetTegraRenderEngine()
+ {
+ return m_NDDView->GetTegraRenderEngine();
+ }
+
+public:
+ void GoToSlideByName(const char *elementPath, const char *slideName)
+ {
+ m_NDDView->GoToSlideByName(elementPath, slideName);
+ }
+ void GoToSlideByIndex(const char *elementPath, const int slideIndex)
+ {
+ m_NDDView->GoToSlideByIndex(elementPath, slideIndex);
+ }
+ void GoToSlideRelative(const char *elementPath, const bool next, const bool wrap)
+ {
+ m_NDDView->GoToSlideRelative(elementPath, next, wrap);
+ }
+ bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName)
+ {
+ return m_NDDView->GetSlideInfo(elementPath, currentIndex, previousIndex,
+ currentName, previousName);
+ }
+ void SetPresentationAttribute(const char *presId, const char *, const char *value)
+ {
+ m_NDDView->SetPresentationAttribute(presId, nullptr, value);
+ }
+ void GoToTime(const char *elementPath, const float time)
+ {
+ m_NDDView->GoToTime(elementPath, time);
+ }
+ void SetGlobalAnimationTime(qint64 inMilliSecs)
+ {
+ m_NDDView->SetGlobalAnimationTime(inMilliSecs);
+ }
+ void SetAttribute(const char *elementPath, const char *attributeName, const char *value)
+ {
+ m_NDDView->SetAttribute(elementPath, attributeName, value);
+ }
+ bool GetAttribute(const char *elementPath, const char *attributeName, void *value)
+ {
+ return m_NDDView->GetAttribute(elementPath, attributeName, value);
+ }
+ void FireEvent(const char *element, const char *evtName)
+ {
+ m_NDDView->FireEvent(element, evtName);
+ }
+ bool PeekCustomAction(char *&outElementPath, char *&outActionName)
+ {
+ return m_NDDView->PeekCustomAction(outElementPath, outActionName);
+ }
+ bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData)
+ {
+ return m_NDDView->RegisterScriptCallback(callbackType, func, inUserData);
+ };
+ void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument)
+ {
+ m_NDDView->FireEvent(inEventType, inArgument);
+ }
+ bool AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction)
+ {
+ return m_NDDView->AddGlobalFunction(inFunctionName, inFunction);
+ }
+ qt3ds::foundation::Option<SPresentationSize> GetPrimaryPresentationSize()
+ {
+ return m_NDDView->GetPresentationSize();
+ }
+ qt3ds::foundation::NVScopedRefCounted<INDDView> getNDDView()
+ {
+ return m_NDDView;
+ }
+};
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Engine/Include/UICTegraInputEngine.h b/src/Runtime/Source/Engine/Include/UICTegraInputEngine.h
new file mode 100644
index 00000000..17b9a1dd
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICTegraInputEngine.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICInputEngine.h"
+#include "UICTegraApplication.h"
+#include "UICInputEventTypes.h"
+#include "UICPresentation.h"
+#include "KD/kd.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTegraRenderEngine;
+class CPresentation;
+class ITegraApplicationRenderEngine;
+
+//==============================================================================
+/**
+* @class CTegraInputEngine
+* @brief
+*/
+class CTegraInputEngine : public CInputEngine
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CTegraInputEngine();
+ virtual ~CTegraInputEngine();
+
+public: // Access
+ SInputFrame &GetInputFrame() override;
+
+ void HandleMessage(const KDEvent *inEvent, ITegraApplicationRenderEngine &inRenderEngine,
+ CPresentation *inPresentation);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Engine/Include/UICWindowSystem.h b/src/Runtime/Source/Engine/Include/UICWindowSystem.h
new file mode 100644
index 00000000..25f5bf71
--- /dev/null
+++ b/src/Runtime/Source/Engine/Include/UICWindowSystem.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_WINDOW_SYSTEM_H
+#define UIC_WINDOW_SYSTEM_H
+
+namespace Q3DStudio {
+struct SSize
+{
+ int m_Width;
+ int m_Height;
+ SSize(int w = 0, int h = 0)
+ : m_Width(w)
+ , m_Height(h)
+ {
+ }
+};
+
+struct SEGLInfo;
+
+class IWindowSystem
+{
+protected:
+ virtual ~IWindowSystem() {}
+public:
+ virtual SSize GetWindowDimensions() = 0;
+ virtual void SetWindowDimensions(const SSize &inSize) = 0;
+ // For platforms that support it, we get the egl info for render plugins
+ // Feel free to return NULL.
+ virtual SEGLInfo *GetEGLInfo() = 0;
+ // on some systems we allow our default render target to be a offscreen buffer
+ // otherwise return 0;
+ virtual int GetDefaultRenderTargetID() = 0;
+ // returns the depth buffer bit count for the render window
+ virtual int GetDepthBitCount() = 0;
+};
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Engine/Source/EnginePrefix.cpp b/src/Runtime/Source/Engine/Source/EnginePrefix.cpp
new file mode 100644
index 00000000..d3c2930f
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/EnginePrefix.cpp
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EnginePrefix.h"
diff --git a/src/Runtime/Source/Engine/Source/UICOSSpecificFunctions.cpp b/src/Runtime/Source/Engine/Source/UICOSSpecificFunctions.cpp
new file mode 100644
index 00000000..c2224b5d
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/UICOSSpecificFunctions.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EnginePrefix.h"
+
+#include "UICSyncPrimitive.h"
+#include "UICThreadManager.h"
+#include "NVImageScaler.h"
+
+//==============================================================================
+// OpenKode
+//==============================================================================
+#ifdef _WIN32
+#pragma warning(push, 3)
+#endif
+#include "OpenKodeInclude.h" // TODO AH is this enough, or is it required around nv_main/nv_main.h also????
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+static const Q3DStudio::INT32 CONST_THREAD_SLEEP = 10;
+
+//==============================================================================
+// OS specific functions that are declared and used in our code, that need to be
+// defined somewhere else that has OS specific knowledge.
+//==============================================================================
+
+//==============================================================================
+/**
+ * Create a lock primitive
+ */
+void AppCreateLockPrimitive(Q3DStudio::TLockPrimitive *inPrimitive)
+{
+ Q3DStudio_ASSERT(inPrimitive);
+ *inPrimitive = reinterpret_cast<Q3DStudio::TLockPrimitive *>(kdThreadMutexCreate(NULL));
+}
+
+//==============================================================================
+/**
+* Destroy a lock primitive
+*/
+void AppDestroyLockPrimitive(Q3DStudio::TLockPrimitive *inPrimitive)
+{
+ Q3DStudio_ASSERT(inPrimitive);
+ kdThreadMutexFree(reinterpret_cast<KDThreadMutex *>(*inPrimitive));
+ *inPrimitive = NULL;
+}
+
+//==============================================================================
+/**
+* Enter the thread sync point
+*/
+void AppBeginSync(Q3DStudio::TLockPrimitive inPrimitive)
+{
+ Q3DStudio_ASSERT(inPrimitive);
+ kdThreadMutexLock(reinterpret_cast<KDThreadMutex *>(inPrimitive));
+}
+
+//==============================================================================
+/**
+* Leave the thread sync point
+*/
+void AppEndSync(Q3DStudio::TLockPrimitive inPrimitive)
+{
+ Q3DStudio_ASSERT(inPrimitive);
+ kdThreadMutexUnlock(reinterpret_cast<KDThreadMutex *>(inPrimitive));
+}
+
+//==============================================================================
+/**
+* Create a thread and return an abstract ID (void*)
+*/
+Q3DStudio::TThreadID AppCreateThread(Q3DStudio::TThreadSpinFunction inFunc, void *inUserData)
+{
+ KDThread *theThread = kdThreadCreate(NULL, inFunc, inUserData);
+ return static_cast<Q3DStudio::TThreadID>(theThread);
+}
+
+//==============================================================================
+/**
+* Destroy the thread
+*/
+void AppDestroyThread(Q3DStudio::TThreadID inThreadID)
+{
+ void *ignored = NULL;
+ kdThreadJoin(static_cast<KDThread *>(inThreadID), &ignored);
+}
+
+//==============================================================================
+/**
+* Call a OS specific sleep function, to yield the cpu to other threads
+*/
+void AppSleepThread()
+{
+ Q3DStudio_sleepmillisec(CONST_THREAD_SLEEP);
+}
+
+static const Q3DStudio::INT32 CMAX_THUMBNAIL_SIZE = 148;
+//==============================================================================
+/**
+ * Find the correct thumbnail scaling
+ */
+inline static Q3DStudio::FLOAT FindThumbnailScale(const Q3DStudio::INT32 inMaxThumbnailSize,
+ Q3DStudio::INT32 inSourceWidth,
+ Q3DStudio::INT32 inSourceHeight)
+{
+ Q3DStudio::FLOAT theXScale = inMaxThumbnailSize / (Q3DStudio::FLOAT)inSourceWidth;
+ Q3DStudio::FLOAT theYScale = inMaxThumbnailSize / (Q3DStudio::FLOAT)inSourceHeight;
+ return theXScale < theYScale ? theXScale : theYScale;
+}
+
+inline static Q3DStudio::INT32 FourByteAlign(Q3DStudio::INT32 inSrc)
+{
+ return (inSrc + 3) & ~3;
+}
+
+namespace Q3DStudio {
+
+inline static BOOL FileExists(const char *inPath)
+{
+ KDFile *theFile = kdFopen(inPath, "rb");
+ if (theFile != NULL) {
+ kdFclose(theFile);
+ return true;
+ }
+ return false;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Engine/Source/UICRenderRuntimeBinding.cpp b/src/Runtime/Source/Engine/Source/UICRenderRuntimeBinding.cpp
new file mode 100644
index 00000000..7dccf48c
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/UICRenderRuntimeBinding.cpp
@@ -0,0 +1,1997 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EnginePrefix.h"
+#include "UICRenderRuntimeBindingImpl.h"
+#include "UICSceneManager.h"
+#include "UICIScene.h"
+#include "UICTegraApplication.h"
+#include "UICLuaEngine.h"
+#include "UICQmlEngine.h"
+#include "UICRenderUIPLoader.h"
+#include "UICPresentationFrameData.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "UICRenderSubpresentation.h"
+#include "UICIScriptBridge.h"
+#include "UICFileStream.h"
+#include "UICDMPrefix.h"
+#include "foundation/IOStreams.h"
+#include "UICDMStringTable.h"
+#include "UICDMXML.h"
+#include "UICRenderBufferManager.h"
+#include "foundation/SerializationTypes.h"
+#include "UICRenderGraphObjectSerializer.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderImageBatchLoader.h"
+#include "UICPresentation.h"
+
+#include "UICDLLManager.h"
+#include "UICBasicPluginDLL.h"
+#include "UICPluginDLL.h"
+#include "UICRenderPlugin.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSTime.h"
+#include "UICStateVisualBindingContext.h"
+#include "UICStateVisualBindingContextValues.h"
+#include "UICStateScriptContext.h"
+#include "EventPollingSystem.h"
+#include "EventSystem.h"
+#include "UICApplication.h"
+#include "UICMatrix.h"
+#include "UICWindowSystem.h"
+#if !defined (Q_OS_MACOS)
+#include "UICEGLInfo.h"
+#endif
+#include "UICOffscreenRenderKey.h"
+#include "UICOldNBustedRenderPlugin.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "UICRenderBufferLoader.h"
+#include "UICRenderRenderList.h"
+#include "UICRenderPrefilterTexture.h"
+#include "foundation/PoolingAllocator.h"
+#include "q3dsqmlrender.h"
+
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4355)
+#endif
+
+using namespace uic::render;
+using eastl::make_pair;
+using eastl::pair;
+using uic::runtime::IApplication;
+
+#ifndef _WIN32
+#define stricmp strcasecmp
+#endif
+namespace uic {
+namespace render {
+ qt3ds::foundation::MallocAllocator g_BaseAllocator;
+}
+}
+namespace {
+struct SUICRenderScene;
+
+struct UICRenderSceneSubPresRenderer : public CSubPresentationRenderer
+{
+ SUICRenderScene &m_Scene;
+ UICRenderSceneSubPresRenderer(SUICRenderScene &inScene, IUICRenderContext &inRenderContext,
+ SPresentation &inPresentation)
+ : CSubPresentationRenderer(inRenderContext, inPresentation)
+ , m_Scene(inScene)
+ {
+ }
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
+ SOffscreenRenderFlags NeedsRender(const SOffscreenRendererEnvironment &inEnvironment,
+ QT3DSVec2 inPresScale) override;
+ void Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 inPresScale,
+ SScene::RenderClearCommand inClearBuffer) override;
+};
+
+struct SSceneLoadData
+{
+ NVAllocatorCallback &m_Allocator;
+ NVScopedRefCounted<ILoadedBuffer> m_Data;
+ SPresentation *m_Presentation;
+ NVDataRef<QT3DSU8> m_TranslatorData;
+ NVDataRef<QT3DSU8> m_SceneGraphData;
+ eastl::vector<CUICTranslator *> m_Translators;
+ SPoolingAllocator m_AutoAllocator;
+ Q3DStudio::IPresentation *m_RuntimePresentation;
+ QT3DSI32 mRefCount;
+
+ SSceneLoadData(NVAllocatorCallback &alloc)
+ : m_Allocator(alloc)
+ , m_Presentation(NULL)
+ , m_AutoAllocator(alloc)
+ , m_RuntimePresentation(NULL)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+};
+
+struct SUICRenderScene : public Q3DStudio::IScene
+{
+ SBindingCore &m_BindingCore;
+ NVScopedRefCounted<IUICRenderContext> m_Context;
+ NVScopedRefCounted<SSceneLoadData> m_LoadData;
+ // The scene graph gets allocated kind of on its own
+ // So do the smaller translation objects that translate TElement properties
+ // into the graph.
+ SPresentation *m_Presentation;
+ Q3DStudio::IPresentation *m_RuntimePresentation;
+ void *m_UserData;
+ TTranslatorDirytSet m_DirtySet;
+ CRegisteredString m_OffscreenRendererId;
+ IOffscreenRenderer *m_OffscreenRenderer;
+ CRegisteredString m_SubPresentationType;
+ nvvector<SGraphObject *> m_GraphObjectList;
+ bool m_LoggedPickLastFrame;
+ NVRenderRect m_LastRenderViewport;
+ CRegisteredString m_PathSubPathType;
+
+ SUICRenderScene(SBindingCore &inBindingCore, IUICRenderContext &inContext,
+ SSceneLoadData &inLoadData)
+ : m_BindingCore(inBindingCore)
+ , m_Context(inContext)
+ , m_LoadData(inLoadData)
+ , m_Presentation(inLoadData.m_Presentation)
+ , m_RuntimePresentation(inLoadData.m_RuntimePresentation)
+ , m_UserData(NULL)
+ , m_DirtySet(inContext.GetAllocator(), "SUICRenderScene::m_DirtySet")
+ , m_OffscreenRenderer(NULL)
+ , m_SubPresentationType(
+ inContext.GetStringTable().RegisterStr(CSubPresentationRenderer::GetRendererName()))
+ , m_GraphObjectList(inContext.GetAllocator(), "SUICRenderScene::m_GraphObjectList")
+ , m_LoggedPickLastFrame(false)
+ {
+ for (QT3DSU32 idx = 0, end = inLoadData.m_Translators.size(); idx < end; ++idx) {
+ m_DirtySet.insert(*inLoadData.m_Translators[idx]);
+ }
+ m_PathSubPathType = inContext.GetStringTable().RegisterStr("PathAnchorPoint");
+ }
+
+ virtual ~SUICRenderScene()
+ {
+ if (m_OffscreenRenderer)
+ m_Context->GetOffscreenRenderManager().ReleaseOffscreenRenderer(m_OffscreenRendererId);
+ m_OffscreenRenderer = NULL;
+ if (m_Presentation && m_Presentation->m_Scene) {
+ for (SLayer *theLayer = m_Presentation->m_Scene->m_FirstChild; theLayer;
+ theLayer = static_cast<SLayer *>(theLayer->m_NextSibling)) {
+ m_Context->GetRenderer().ReleaseLayerRenderResources(*theLayer);
+ }
+ }
+ }
+
+ Q3DStudio::IPresentation &GetPresentation() override { return *m_RuntimePresentation; }
+
+ // Update really just adds objects to the dirty set
+ bool Update()
+ {
+ Q3DStudio::TElementList &theDirtyList =
+ m_RuntimePresentation->GetFrameData().GetDirtyList();
+ for (QT3DSU32 idx = 0, end = theDirtyList.GetCount(); idx < end; ++idx) {
+ Q3DStudio::TElement &theElement = *theDirtyList[idx];
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(theElement.GetAssociation());
+ if (!theTranslator && theElement.GetType() == m_PathSubPathType) {
+ Q3DStudio::TElement *theParent = theElement.GetParent();
+ if (theParent) {
+ theTranslator = reinterpret_cast<CUICTranslator *>(theParent->GetAssociation());
+ // The path translator responds to anchor point changes as well as its own data
+ // changes.
+ if (theTranslator
+ && theTranslator->RenderObject().m_Type != GraphObjectTypes::PathSubPath)
+ theTranslator = NULL;
+ }
+ }
+ if (theTranslator)
+ m_DirtySet.insert(*theTranslator);
+ }
+ return m_DirtySet.size() > 0;
+ }
+
+ void TransferDirtyProperties()
+ {
+ if (m_Presentation) {
+ for (QT3DSU32 idx = 0, end = m_DirtySet.size(); idx < end; ++idx) {
+ QT3DS_ASSERT(m_DirtySet.size() == end);
+ m_DirtySet[idx]->OnElementChanged(*m_Presentation, *m_Context,
+ *m_RuntimePresentation);
+ }
+ m_DirtySet.clear();
+ }
+ }
+
+ bool PrepareForRender()
+ {
+ TransferDirtyProperties();
+ m_LastRenderViewport = m_Context->GetRenderList().GetViewport();
+ if (m_Presentation && m_Presentation->m_Scene) {
+ NVRenderRect theViewportSize(m_LastRenderViewport);
+ return m_Presentation->m_Scene->PrepareForRender(
+ QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
+ *m_Context);
+ }
+ return false;
+ }
+
+ void Render()
+ {
+ if (m_Presentation && m_Presentation->m_Scene) {
+ NVRenderRect theViewportSize(m_LastRenderViewport);
+ m_Presentation->m_Scene->Render(
+ QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height), *m_Context,
+ SScene::DoNotClear);
+ }
+ }
+
+ // Note that we do not need to call WindowToPresentation on the mouse coordinates because they
+ // are specifically
+ // supposed to be the return values from getMousePosition which applies that transformation. We
+ // do, however need
+ // to reverse part of this transformation; whatever part happens after
+ // m_Context->GetMousePickMouseCoords
+ Q3DStudio::TElement *UserPick(float mouseX, float mouseY)
+ {
+ // Note that lua:getMousePosition calls WindowToPresentation.
+ // Note that the pick code below only calls GetMousePickMouseCoords
+ // while windowToPresentation subtracts the window positional offset from
+ // the mouse position.
+ // Thus we have to add it back.
+ QT3DSVec2 mousePos(mouseX + m_LastRenderViewport.m_X, mouseY + m_LastRenderViewport.m_Y);
+
+ SUICRenderPickResult thePickResult = m_Context->GetRenderer().Pick(
+ *m_Presentation->m_Scene->m_FirstChild, m_Context->GetMousePickViewport()
+ // GetMousePickMouseCoords is called by the renderer to setup the pick frame.
+ // This is so that the presentation's lastMouseX and lastMouseY variables are correctly
+ // setup.
+ ,
+ mousePos, true, true);
+
+ if (thePickResult.m_HitObject != NULL) {
+ SModel *theHitModel =
+ static_cast<SModel *>(const_cast<SGraphObject *>(thePickResult.m_HitObject));
+ return &CUICTranslator::GetTranslatorFromGraphNode(*theHitModel)->Element();
+ }
+ return NULL;
+ }
+
+ virtual Option<QT3DSVec2> FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
+ NVDataRef<Q3DStudio::TElement *> inMapperElements,
+ Q3DStudio::FacePositionPlanes::Enum inPlane)
+ {
+ if (inElement.GetBelongedPresentation() != this->m_RuntimePresentation
+ && inMapperElements.size() == 0) {
+ return Empty();
+ }
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement.GetAssociation());
+ if (theTranslator == NULL)
+ return Empty();
+ bool isValidPickObject =
+ GraphObjectTypes::IsNodeType(theTranslator->m_RenderObject->m_Type);
+ if (isValidPickObject == false)
+ return Empty();
+ SNode &theNode = static_cast<SNode &>(*theTranslator->m_RenderObject);
+ NVBounds3 theBounds = GetNodeLocalBoundingBox(&inElement, false);
+ // See commens in UserPick
+ QT3DSVec2 mousePos(mouseX + m_LastRenderViewport.m_X, mouseY + m_LastRenderViewport.m_Y);
+ eastl::vector<SGraphObject *> theMapperObjects(inMapperElements.size());
+ for (QT3DSU32 idx = 0, end = inMapperElements.size(); idx < end; ++idx) {
+ CUICTranslator *theMapperTranslator =
+ reinterpret_cast<CUICTranslator *>(inMapperElements[idx]->GetAssociation());
+ SGraphObject *theMapperObject = NULL;
+ if (theMapperTranslator) {
+ theMapperObject = theMapperTranslator->m_RenderObject;
+ }
+ if (theMapperObject == NULL) {
+ QT3DS_ASSERT(false);
+ } else {
+ theMapperObjects[idx] = theMapperObject;
+ }
+ }
+ uic::render::SBasisPlanes::Enum thePlane(uic::render::SBasisPlanes::XY);
+ switch (inPlane) {
+ case Q3DStudio::FacePositionPlanes::XY:
+ thePlane = uic::render::SBasisPlanes::XY;
+ break;
+ case Q3DStudio::FacePositionPlanes::YZ:
+ thePlane = uic::render::SBasisPlanes::YZ;
+ break;
+ case Q3DStudio::FacePositionPlanes::XZ:
+ thePlane = uic::render::SBasisPlanes::XZ;
+ break;
+ }
+ if (theBounds.isEmpty() == false)
+ return m_Context->GetRenderer().FacePosition(
+ theNode, theBounds, theNode.m_GlobalTransform, m_Context->GetMousePickViewport(),
+ mousePos,
+ NVDataRef<SGraphObject *>(theMapperObjects.data(), (QT3DSU32)theMapperObjects.size()),
+ thePlane);
+ return Empty();
+ }
+
+ void Pick(Q3DStudio::SPickFrame &ioPickFrame)
+ {
+ // Presentation's m_Hide can disable rendering
+ bool wasPickLoggedLastFrame = m_LoggedPickLastFrame;
+ m_LoggedPickLastFrame = false;
+ if (ioPickFrame.m_InputFrame.m_PickValid) {
+ // If we have not already found a valid pick on a previous layer
+ if (!ioPickFrame.m_ResultValid && m_Presentation && m_Presentation->m_Scene
+ && m_Presentation->m_Scene->m_FirstChild) {
+ SUICRenderPickResult thePickResult = m_Context->GetRenderer().Pick(
+ *m_Presentation->m_Scene->m_FirstChild, m_Context->GetMousePickViewport()
+ // GetMousePickMouseCoords is called by the renderer to setup the pick frame.
+ // This is so that the presentation's lastMouseX and lastMouseY variables are
+ // correctly setup.
+ ,
+ m_Context->GetMousePickMouseCoords(
+ QT3DSVec2(ioPickFrame.m_InputFrame.m_PickX, ioPickFrame.m_InputFrame.m_PickY)),
+ true);
+ if (thePickResult.m_HitObject != NULL) {
+ SModel *theHitModel = static_cast<SModel *>(
+ const_cast<SGraphObject *>(thePickResult.m_HitObject));
+ ioPickFrame.m_Model =
+ &CUICTranslator::GetTranslatorFromGraphNode(*theHitModel)->Element();
+ // I don't think local hit is used any more, but not sure. If they are used,
+ // then the code below is probably wrong.
+ ioPickFrame.m_LocalHit[0] = thePickResult.m_LocalUVCoords.x;
+ ioPickFrame.m_LocalHit[1] = thePickResult.m_LocalUVCoords.y;
+ ioPickFrame.m_SquaredDistance = thePickResult.m_CameraDistanceSq;
+ ioPickFrame.m_ResultValid = true;
+ if (wasPickLoggedLastFrame == false) {
+ m_LoggedPickLastFrame = true;
+ Q3DStudio::IPresentation *thePresentation =
+ ioPickFrame.m_Model->GetBelongedPresentation();
+ IApplication &theRuntime = thePresentation->GetApplication();
+ // We are picking against the previous frame of information.
+ qCInfo(TRACE_INFO, "Model Picked: %s on frame %d",
+ theHitModel->m_Id.c_str(),
+ theRuntime.GetFrameCount() - 1);
+ }
+ } else {
+ // The scene is always picked if it is pickable; nothing else really makes
+ // sense.
+ CUICTranslator *theTranslator =
+ CUICTranslator::GetTranslatorFromGraphNode(*m_Presentation->m_Scene);
+
+ if (theTranslator) {
+ ioPickFrame.m_Model = &theTranslator->Element();
+ // I don't think local hit is used any more, but not sure. If they are
+ // used, then the code below is probably wrong.
+ ioPickFrame.m_LocalHit[0] = ioPickFrame.m_InputFrame.m_PickX
+ / m_Presentation->m_PresentationDimensions.x;
+ ioPickFrame.m_LocalHit[1] = 1.0f
+ - ioPickFrame.m_InputFrame.m_PickY
+ / m_Presentation->m_PresentationDimensions.y;
+ ioPickFrame.m_SquaredDistance = 0;
+ ioPickFrame.m_ResultValid = true;
+ }
+ }
+ }
+ }
+ }
+
+ void SetUserData(void *inUserData) override { m_UserData = inUserData; }
+ void *GetUserData() override { return m_UserData; }
+
+ // Unfortunately, you should expect the node to be dirty at this point so we may need to force
+ // an update
+ void CalculateGlobalTransform(Q3DStudio::TElement *inElement,
+ Q3DStudio::RuntimeMatrix &outTransform) override
+ {
+ if (inElement == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ Update();
+ TransferDirtyProperties();
+ SNode *theNode = static_cast<SNode *>(&theTranslator->RenderObject());
+ // Ensure the node stays dirty
+ bool wasDirty = theNode->m_Flags.IsDirty();
+ theNode->CalculateGlobalVariables();
+ theNode->m_Flags.SetDirty(wasDirty);
+ memCopy(outTransform.m_Data, theNode->m_GlobalTransform.front(), sizeof(QT3DSMat44));
+ } else {
+ qCCritical(INVALID_OPERATION, "Calculate global transform called on invalide object");
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void SetLocalTransformMatrix(Q3DStudio::TElement *inElement,
+ const Q3DStudio::RuntimeMatrix &inTransform) override
+ {
+ if (inElement == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ SNode *theNode = static_cast<SNode *>(&theTranslator->RenderObject());
+ QT3DSMat44 transform;
+ memCopy(transform.front(), inTransform.m_Data, sizeof(QT3DSMat44));
+ theNode->SetLocalTransformFromMatrix(transform);
+ theNode->MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ }
+ }
+
+ void EnsureNodeIsUpToDate(SNode &inNode, bool inIncludeChildren)
+ {
+ bool wasDirty = inNode.m_Flags.IsDirty();
+ if (wasDirty) {
+ inNode.CalculateGlobalVariables();
+ inNode.m_Flags.SetDirty(wasDirty);
+ if (inIncludeChildren) {
+ for (SNode *theChild = inNode.m_FirstChild; theChild;
+ theChild = theChild->m_NextSibling)
+ EnsureNodeIsUpToDate(*theChild, inIncludeChildren);
+ }
+ }
+ }
+
+ NVBounds3 GetNodeLocalBoundingBox(Q3DStudio::TElement *inElement, bool inSelfOnly)
+ {
+ NVBounds3 retval(NVBounds3::empty());
+ if (inElement == NULL) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ Update();
+ TransferDirtyProperties();
+ SNode *theNode = static_cast<SNode *>(&theTranslator->RenderObject());
+ bool theIncludeChildren = !inSelfOnly;
+ EnsureNodeIsUpToDate(*theNode, theIncludeChildren);
+ IBufferManager &theBufferManager(m_Context->GetBufferManager());
+ return theNode->GetBounds(theBufferManager, m_Context->GetPathManager(),
+ theIncludeChildren);
+ } else {
+ qCCritical(INVALID_OPERATION, "GetBoundingBox called on invalid object");
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+
+ static void Assign(Q3DStudio::CBoundingBox &lhs, NVBounds3 &rhs)
+ {
+ lhs.m_Min.m_X = rhs.minimum.x;
+ lhs.m_Min.m_Y = rhs.minimum.y;
+ lhs.m_Min.m_Z = rhs.minimum.z;
+
+ lhs.m_Max.m_X = rhs.maximum.x;
+ lhs.m_Max.m_Y = rhs.maximum.y;
+ lhs.m_Max.m_Z = rhs.maximum.z;
+ }
+
+ Q3DStudio::CBoundingBox GetBoundingBox(Q3DStudio::TElement *inElement, bool inSelfOnly) override
+ {
+ Q3DStudio::CBoundingBox retval;
+ retval.SetEmpty();
+ NVBounds3 theLocalBox = GetNodeLocalBoundingBox(inElement, inSelfOnly);
+ if (theLocalBox.isEmpty() == false) {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ SNode *theNode = static_cast<SNode *>(&theTranslator->RenderObject());
+ theLocalBox.transform(theNode->m_GlobalTransform);
+ Assign(retval, theLocalBox);
+ // Left handed nodes need to return values in their space, not in the global space
+ // This is a hack fix due to a bug.
+ if (theNode->m_Flags.IsLeftHanded()) {
+ eastl::swap(retval.m_Min.m_Z, retval.m_Max.m_Z);
+ retval.m_Min.m_Z *= -1;
+ retval.m_Max.m_Z *= -1;
+ }
+ }
+ }
+ return retval;
+ }
+
+ Q3DStudio::CBoundingBox GetLocalBoundingBox(Q3DStudio::TElement *inElement,
+ bool inSelfOnly) override
+ {
+ Q3DStudio::CBoundingBox retval;
+ retval.SetEmpty();
+ if (inElement == NULL) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ NVBounds3 theLocalBounds = GetNodeLocalBoundingBox(inElement, inSelfOnly);
+ if (theLocalBounds.isEmpty() == false)
+ Assign(retval, theLocalBounds);
+
+ return retval;
+ }
+
+ Q3DStudio::SCameraRect GetCameraBounds(Q3DStudio::TElement &inElem) override
+ {
+ CUICTranslator *theTranslator = reinterpret_cast<CUICTranslator *>(inElem.GetAssociation());
+ if (theTranslator && theTranslator->m_RenderObject) {
+ Option<uic::render::SCuboidRect> theRectOpt =
+ m_Context->GetRenderer().GetCameraBounds(*theTranslator->m_RenderObject);
+ if (theRectOpt.hasValue()) {
+ uic::render::SCuboidRect theRect(*theRectOpt);
+ return Q3DStudio::SCameraRect(theRect.m_Left, theRect.m_Top, theRect.m_Right,
+ theRect.m_Bottom);
+ }
+ }
+ return Q3DStudio::SCameraRect();
+ }
+
+ void PositionToScreen(Q3DStudio::TElement &inElement, QT3DSVec3 &inPos, QT3DSVec3 &outScreen) override
+ {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement.GetAssociation());
+ if (theTranslator && theTranslator->m_RenderObject) {
+ SNode *theNode = reinterpret_cast<SNode *>(theTranslator->m_RenderObject);
+ QT3DSVec3 thePos = theNode->m_GlobalTransform.transform(inPos);
+ outScreen = m_Context->GetRenderer().ProjectPosition(*theNode, thePos);
+ }
+ }
+
+ void ScreenToPosition(Q3DStudio::TElement &inElement, QT3DSVec3 &inScreen, QT3DSVec3 &outPos) override
+ {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement.GetAssociation());
+ if (theTranslator && theTranslator->m_RenderObject) {
+ SNode *theNode = reinterpret_cast<SNode *>(theTranslator->m_RenderObject);
+ QT3DSVec3 objPos = theNode->GetGlobalPos();
+ outPos = m_Context->GetRenderer().UnprojectWithDepth(*(theNode), objPos, inScreen);
+ }
+ }
+
+ static inline int wrapMod(int a, int base) { return (a >= 0) ? a % base : (a % base) + base; }
+ static inline float fMin(float a, float b) { return (a < b) ? a : b; }
+ static inline int iMax(int a, int b) { return (a > b) ? a : b; }
+
+ static inline void getWrappedCoords(int &sX, int &sY, int width, int height)
+ {
+ if (sY < 0) {
+ sX -= width >> 1;
+ sY = -sY;
+ }
+ if (sY >= height) {
+ sX += width >> 1;
+ sY = height - sY;
+ }
+ sX = wrapMod(sX, width);
+ sY = wrapMod(sY, height);
+ }
+
+ static void GenerateBsdfMipmaps(SImage *theImage, const unsigned char *inBuffer,
+ Q3DStudio::INT32 inBufferLength, Q3DStudio::INT32 inWidth,
+ Q3DStudio::INT32 inHeight,
+ qt3ds::render::NVRenderTextureFormats::Enum inFormat,
+ IUICRenderContext *theContext)
+ {
+ NVRenderTextureFormats::Enum destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F;
+
+ UICRenderPrefilterTexture *theBSDFMipMap = theImage->m_TextureData.m_BSDFMipMap;
+ if (theBSDFMipMap == NULL) {
+ theBSDFMipMap = UICRenderPrefilterTexture::Create(
+ &theContext->GetRenderContext(), inWidth, inHeight,
+ *theImage->m_TextureData.m_Texture, destFormat, theContext->GetFoundation());
+ theImage->m_TextureData.m_BSDFMipMap = theBSDFMipMap;
+ }
+
+ if (theBSDFMipMap)
+ theBSDFMipMap->Build((void *)inBuffer, inBufferLength, inFormat);
+ }
+
+ // This could cause some significant drama.
+ void SetTextureData(Q3DStudio::TElement *inElement, const unsigned char *inBuffer,
+ Q3DStudio::INT32 inBufferLength, Q3DStudio::INT32 inWidth,
+ Q3DStudio::INT32 inHeight,
+ qt3ds::render::NVRenderTextureFormats::Enum inFormat,
+ Q3DStudio::INT32 inHasTransparency) override
+ {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ if (theTranslator && theTranslator->GetUIPType() == GraphObjectTypes::Image) {
+ SImage *theImage = static_cast<SImage *>(&theTranslator->RenderObject());
+ // Attempt to resolve the image's path
+ if (!theImage->m_TextureData.m_Texture) {
+ if (theImage->m_ImagePath.IsValid())
+ theImage->m_TextureData = m_Context->GetBufferManager().LoadRenderImage(
+ theImage->m_ImagePath, false,
+ theImage->m_MappingMode == ImageMappingModes::LightProbe);
+ }
+ // Here we go, updating the texture.
+ if (theImage->m_TextureData.m_Texture) {
+
+ if (theImage->m_MappingMode == ImageMappingModes::LightProbe) {
+ // theImage->m_TextureData.m_Texture->GenerateMipmaps();
+ GenerateBsdfMipmaps(theImage, inBuffer, inBufferLength, inWidth, inHeight,
+ inFormat, m_Context);
+ } else
+ theImage->m_TextureData.m_Texture->SetTextureData(
+ NVDataRef<QT3DSU8>((QT3DSU8 *)inBuffer, (QT3DSU32)inBufferLength), 0, inWidth,
+ inHeight, inFormat);
+
+ if (inHasTransparency >= 0) {
+ bool hasTransparency = inHasTransparency ? true : false;
+ theImage->m_TextureData.m_TextureFlags.SetHasTransparency(hasTransparency);
+ m_Context->GetBufferManager().SetImageHasTransparency(theImage->m_ImagePath,
+ hasTransparency);
+ }
+ theImage->m_Flags.SetDirty(true);
+ }
+ } else {
+ qCCritical(INVALID_OPERATION, "SetTextureData called on object that is not an image");
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ bool CreateOrSetMeshData(const char *inPathStr, unsigned char *vertData,
+ unsigned int numVerts, unsigned int vertStride,
+ unsigned int *indexData, unsigned int numIndices,
+ qt3ds::NVBounds3 &objBounds) override
+ {
+ SRenderMesh *theMesh = NULL;
+
+ if (inPathStr && vertData && indexData) {
+ theMesh = m_Context->GetBufferManager().CreateMesh(
+ inPathStr, vertData, numVerts, vertStride, indexData, numIndices, objBounds);
+ } else {
+ qCCritical(INVALID_OPERATION,
+ "CreateOrSetMeshData was not supplied necessary buffers or object path");
+ }
+
+ return (theMesh != NULL);
+ }
+
+ Q3DStudio::STextSizes MeasureText(Q3DStudio::TElement *inElement, const char *inTextStr) override
+ {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ Q3DStudio::STextSizes retval;
+ if (theTranslator && theTranslator->GetUIPType() == GraphObjectTypes::Text) {
+ if (inElement->IsDirty()) {
+ theTranslator->OnElementChanged(*m_Presentation, *m_Context,
+ *m_RuntimePresentation);
+ }
+ SText *theText = static_cast<SText *>(&theTranslator->RenderObject());
+ if (theText) {
+
+ STextDimensions theDimensions =
+ m_Context->GetTextRenderer()->MeasureText(*theText, 1.0f, inTextStr);
+
+ retval = Q3DStudio::STextSizes((Q3DStudio::INT32)theDimensions.m_TextWidth,
+ (Q3DStudio::INT32)theDimensions.m_TextHeight);
+ }
+ } else {
+ qCCritical(INVALID_OPERATION, "MeasureText called on object that is not text");
+ QT3DS_ASSERT(false);
+
+ }
+ return retval;
+ }
+
+ Q3DStudio::STextSizes GetPresentationDesignDimensions() override
+ {
+ if (m_Presentation) {
+ return Q3DStudio::STextSizes(
+ static_cast<Q3DStudio::INT32>(m_Presentation->m_PresentationDimensions.x),
+ static_cast<Q3DStudio::INT32>(m_Presentation->m_PresentationDimensions.y));
+ }
+ QT3DS_ASSERT(false);
+ return Q3DStudio::STextSizes();
+ }
+
+ // This is the best place for now...
+ void GetImageInfoFromRenderEngine(Q3DStudio::TElement *inElement,
+ Q3DStudio::INT32 &ioWidth, Q3DStudio::INT32 &ioHeight) override
+ {
+ ioWidth = 0;
+ ioHeight = 0;
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(inElement->GetAssociation());
+ if (theTranslator->GetUIPType() == GraphObjectTypes::Image) {
+ SImage *theImage = static_cast<SImage *>(&theTranslator->RenderObject());
+ if (theImage) {
+ SImageTextureData theTextureData(
+ m_Context->GetBufferManager().LoadRenderImage(theImage->m_ImagePath));
+ if (theTextureData.m_Texture) {
+ STextureDetails theDetails = theTextureData.m_Texture->GetTextureDetails();
+ ioWidth = theDetails.m_Width;
+ ioHeight = theDetails.m_Height;
+ }
+ }
+ }
+ }
+
+ virtual Q3DStudio::SMousePosition
+ WindowToPresentation(const Q3DStudio::SMousePosition &inWindowCoords) override
+ {
+ // If there aren't any rotations, then account for the difference in width/height of the
+ // presentation and the window
+ QT3DSVec2 theCoords = m_Context->GetMousePickMouseCoords(
+ QT3DSVec2((QT3DSF32)inWindowCoords.m_X, (QT3DSF32)inWindowCoords.m_Y));
+ theCoords.x -= m_LastRenderViewport.m_X;
+ // Note that the mouse Y is reversed. Thus a positive offset of the viewport will reduce
+ // the mouse value.
+ theCoords.y -= m_LastRenderViewport.m_Y;
+ return Q3DStudio::SMousePosition(theCoords.x, theCoords.y);
+ }
+
+ qt3ds::foundation::CRegisteredString RegisterStr(const char *inStr) override
+ {
+ return m_Context->GetStringTable().RegisterStr(inStr);
+ }
+
+ Q3DStudio::INT32 LoadImageBatch(qt3ds::foundation::CRegisteredString *inFullPaths,
+ Q3DStudio::INT32 inNumPaths,
+ qt3ds::foundation::CRegisteredString inDefaultImage,
+ uic::render::IImageLoadListener *inLoadCallback) override
+ {
+ return static_cast<Q3DStudio::INT32>(m_Context->GetImageBatchLoader().LoadImageBatch(
+ toConstDataRef(inFullPaths, (QT3DSU32)inNumPaths), inDefaultImage, inLoadCallback));
+ }
+
+ void RegisterOffscreenRenderer(const char *inKey) override
+ {
+ m_OffscreenRenderer = QT3DS_NEW(m_Context->GetAllocator(), UICRenderSceneSubPresRenderer)(
+ *this, *m_Context, *m_Presentation);
+ m_OffscreenRendererId = m_Context->GetStringTable().RegisterStr(inKey);
+ m_Context->GetOffscreenRenderManager().RegisterOffscreenRenderer(m_OffscreenRendererId,
+ *m_OffscreenRenderer);
+ }
+
+ void Release() override { NVDelete(m_Context->GetAllocator(), this); }
+};
+
+SOffscreenRenderFlags
+UICRenderSceneSubPresRenderer::NeedsRender(const SOffscreenRendererEnvironment &inEnvironment,
+ QT3DSVec2 inPresScale)
+{
+ m_Scene.TransferDirtyProperties();
+ return CSubPresentationRenderer::NeedsRender(inEnvironment, inPresScale);
+}
+
+void UICRenderSceneSubPresRenderer::Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 inPresScale,
+ SScene::RenderClearCommand inClearBuffer)
+{
+ CSubPresentationRenderer::Render(inEnvironment, inRenderContext, inPresScale, inClearBuffer);
+}
+
+//////////////////////////////////////////////////////////////////
+// Scene Manager
+//////////////////////////////////////////////////////////////////
+
+struct SUICRenderSceneManager : public Q3DStudio::ISceneManager,
+ public Q3DStudio::ISceneBinaryLoader
+{
+ typedef nvhash_map<CRegisteredString, bool> TStrBoolMap;
+
+ NVScopedRefCounted<SBindingCore> m_Context;
+ nvvector<pair<Q3DStudio::IPresentation *, SUICRenderScene *>> m_Scenes;
+ nvvector<pair<qt3ds::foundation::CRegisteredString, long>> m_RenderPlugins;
+ Q3DStudio::INT32 m_ViewWidth;
+ Q3DStudio::INT32 m_ViewHeight;
+ Q3DStudio::SPickFrame m_PickFrame;
+ NVDataRef<QT3DSU8> m_StrTableData;
+ // The boolean is to mark transparent images
+ nvvector<eastl::pair<CRegisteredString, bool>> m_SourcePaths;
+ eastl::hash_set<CRegisteredString> m_SourcePathSet;
+
+ SUICRenderScene *m_LastRenderedScene;
+ Q3DStudio::IWindowSystem &m_WindowSystem;
+ Mutex m_LoadingScenesMutex;
+ eastl::vector<NVScopedRefCounted<SSceneLoadData>> m_LoadingScenes;
+ CRegisteredString m_ProjectDir;
+ CRegisteredString m_BinaryDir;
+ bool m_ProjectInitialized;
+ QT3DSI32 mRefCount;
+
+ SUICRenderSceneManager(SBindingCore &ctx, Q3DStudio::IWindowSystem &inWindowSystem)
+ : m_Context(ctx)
+ , m_Scenes(ctx.GetAllocator(), "SUICRenderSceneManager::m_Scenes")
+ , m_RenderPlugins(ctx.GetAllocator(), "SUICRenderSceneManager::m_RenderPlugins")
+ , m_ViewWidth(0)
+ , m_ViewHeight(0)
+ , m_SourcePaths(ctx.GetAllocator(), "SUICRenderSceneManager::m_SourcePaths")
+ , m_LastRenderedScene(NULL)
+ , m_WindowSystem(inWindowSystem)
+ , m_LoadingScenesMutex(ctx.GetAllocator())
+ , m_ProjectInitialized(false)
+ , mRefCount(0)
+ {
+ memZero(&m_PickFrame, sizeof(m_PickFrame));
+ }
+ virtual ~SUICRenderSceneManager()
+ {
+ for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end; ++idx)
+ m_Scenes[idx].second->Release();
+ m_Scenes.clear();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Context->GetAllocator())
+
+ static QT3DSU32 GetFileTag()
+ {
+ const char *fileTag = "UICS";
+ const QT3DSU32 *theTagPtr = reinterpret_cast<const QT3DSU32 *>(fileTag);
+ return *theTagPtr;
+ }
+
+ static bool IsImage(const char *ending)
+ {
+ if (!ending)
+ return false;
+ return stricmp(ending, "jpg") == 0 || stricmp(ending, "peg") == 0
+ || stricmp(ending, "png") == 0 || stricmp(ending, "dds") == 0
+ || stricmp(ending, "hdr") == 0;
+ }
+ static bool IsMesh(const char *ending)
+ {
+ if (!ending)
+ return false;
+ return stricmp(ending, "mesh") == 0;
+ }
+
+ void FinalizeScene(Q3DStudio::IPresentation &inPresentation, SUICRenderScene &inScene)
+ {
+ inPresentation.SetScene(&inScene);
+ if (m_ProjectInitialized == false) {
+ m_ProjectInitialized = true;
+ if (m_Context->m_UICContext->GetTextRenderer())
+ m_Context->m_UICContext->GetTextRenderer()->AddProjectFontDirectory(
+ inScene.m_Presentation->m_PresentationDirectory);
+ eastl::string theBinaryPath(inPresentation.GetFilePath().toLatin1().constData());
+ qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(theBinaryPath, "binary");
+ eastl::string theBinaryDir(theBinaryPath);
+ qt3ds::foundation::CFileTools::GetDirectory(theBinaryDir);
+ if (m_Context->m_WriteOutShaderCache)
+ qt3ds::foundation::CFileTools::CreateDir(theBinaryDir.c_str());
+ }
+ inScene.m_RuntimePresentation = &inPresentation;
+ m_Scenes.push_back(make_pair(&inPresentation, &inScene));
+ CUICTranslator::AssignUserData(inPresentation, *inScene.m_Presentation);
+ }
+
+ static const char *GetBinaryExtension() { return "uibsg"; }
+
+ struct SPluginInstanceTableProvider : public Q3DStudio::ILuaScriptTableProvider
+ {
+ IRenderPluginInstance &m_Instance;
+ SPluginInstanceTableProvider(IRenderPluginInstance &ins)
+ : m_Instance(ins)
+ {
+ }
+ void CreateTable(lua_State *inState) override { m_Instance.CreateLuaProxy(inState); }
+ };
+
+ void InitializeTranslator(CUICTranslator &inTranslator, Q3DStudio::IScriptBridge &inBridge)
+ {
+ if (inTranslator.m_RenderObject->m_Type == GraphObjectTypes::RenderPlugin) {
+ SRenderPlugin &theRenderPlugin =
+ static_cast<SRenderPlugin &>(*inTranslator.m_RenderObject);
+ IRenderPluginInstance *thePluginInstance =
+ m_Context->m_UICContext->GetRenderPluginManager().GetOrCreateRenderPluginInstance(
+ theRenderPlugin.m_PluginPath, &theRenderPlugin);
+ if (thePluginInstance) {
+ SPluginInstanceTableProvider theProvider(*thePluginInstance);
+ inBridge.SetTableForElement(*inTranslator.m_Element, theProvider);
+ }
+ }
+ }
+
+ struct SResolver : public uic::render::IUIPReferenceResolver
+ {
+ IStringTable &m_StringTable;
+ Q3DStudio::IUIPParser &m_Parser;
+ SResolver(IStringTable &strt, Q3DStudio::IUIPParser &p)
+ : m_StringTable(strt)
+ , m_Parser(p)
+ {
+ }
+
+ CRegisteredString ResolveReference(CRegisteredString inStart,
+ const char *inReference) override
+ {
+ eastl::string theResolvedId = m_Parser.ResolveReference(inStart, inReference);
+ if (theResolvedId.size())
+ return m_StringTable.RegisterStr(theResolvedId.c_str());
+ return CRegisteredString();
+ }
+ };
+
+ Q3DStudio::IScene *LoadScene(Q3DStudio::IPresentation *inPresentation,
+ Q3DStudio::IUIPParser *inParser,
+ Q3DStudio::IScriptBridge &inBridge) override
+ {
+ // We have to initialize the tags late so that we can load flow data before adding anything
+ // to the string table.
+ CUICTranslator::InitializePointerTags(m_Context->m_RenderContext->GetStringTable());
+ NVScopedRefCounted<SSceneLoadData> theScene =
+ QT3DS_NEW(m_Context->GetAllocator(), SSceneLoadData)(m_Context->GetAllocator());
+ SUICRenderScene *theIScene = NULL;
+ if (inParser) {
+ QString thePath(inPresentation->GetFilePath());
+ QFileInfo fileInfo(thePath);
+ TIdObjectMap theObjMap(m_Context->GetAllocator(), "LoadScene::theObjMap");
+ SResolver theResolver(m_Context->m_CoreContext->GetStringTable(), *inParser);
+
+ theScene->m_Presentation = IUIPLoader::LoadUIPFile(
+ inParser->GetDOMReader(),
+ fileInfo.absoluteFilePath().toLatin1().constData(),
+ inParser->GetMetaData(),
+ m_Context->m_CoreContext->GetStringTable(),
+ m_Context->m_RenderContext->GetFoundation(),
+ theScene->m_AutoAllocator, theObjMap,
+ m_Context->m_UICContext->GetBufferManager(),
+ m_Context->m_UICContext->GetEffectSystem(),
+ fileInfo.path().toLatin1().constData(),
+ m_Context->m_UICContext->GetRenderPluginManager(),
+ m_Context->m_UICContext->GetCustomMaterialSystem(),
+ m_Context->m_UICContext->GetDynamicObjectSystem(),
+ m_Context->m_UICContext->GetPathManager(), &theResolver, false);
+ if (!theScene->m_Presentation) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ NVConstDataRef<eastl::string> theSourcePathData(inParser->GetSourcePaths());
+ IBufferManager &theManager(m_Context->m_UICContext->GetBufferManager());
+ // List of image paths to be loaded in parallel at the end.
+ eastl::vector<CRegisteredString> theSourcePathList;
+ for (QT3DSU32 idx = 0, end = theSourcePathData.size(); idx < end; ++idx) {
+ const eastl::string &theValue = theSourcePathData[idx];
+ CRegisteredString theSourcePath =
+ m_Context->m_CoreContext->GetStringTable().RegisterStr(theValue.c_str());
+ size_t theValueSize = theValue.size();
+ if (theValueSize > 3) {
+ const char *ending = theValue.c_str() + theValueSize - 3;
+ CRegisteredString theObjectPath = theSourcePath;
+ if (IsImage(ending)) {
+ theManager.SetImageTransparencyToFalseIfNotSet(theObjectPath);
+ if (m_SourcePathSet.insert(theSourcePath).second)
+ m_SourcePaths.push_back(eastl::make_pair(
+ theSourcePath, theManager.GetImageHasTransparency(theObjectPath)));
+ theSourcePathList.push_back(theObjectPath);
+ } else if (theValue.find(".mesh") != eastl::string::npos) {
+ theManager.LoadMesh(theObjectPath);
+ }
+ }
+ }
+
+ // Fire off parallel loading of the source paths
+ QT3DSU64 imageBatchId = m_Context->m_UICContext->GetImageBatchLoader().LoadImageBatch(
+ toConstDataRef(theSourcePathList.data(), theSourcePathList.size()),
+ CRegisteredString(), NULL);
+ m_Context->m_UICContext->GetImageBatchLoader().BlockUntilLoaded(
+ static_cast<TImageBatchId>(imageBatchId));
+
+ theIScene = QT3DS_NEW(m_Context->GetAllocator(),
+ SUICRenderScene)(*m_Context, *m_Context->m_UICContext, *theScene);
+ // Now we need to associate the presentation with everything else.
+ NVAllocatorCallback &translatorAllocator = theScene->m_AutoAllocator;
+ for (TIdObjectMap::iterator iter = theObjMap.begin(), end = theObjMap.end();
+ iter != end; ++iter) {
+ theIScene->m_GraphObjectList.push_back(iter->second);
+ Q3DStudio::SElementAndType theElement =
+ inParser->GetElementForID(iter->first.c_str());
+ if (theElement.m_Element
+ && theElement.m_Type != Q3DStudio::UIPElementTypes::Unknown) {
+ CUICTranslator *theTranslator = CUICTranslator::CreateTranslatorForElement(
+ *theElement.m_Element, *iter->second, translatorAllocator);
+ if (theTranslator) {
+ theIScene->m_DirtySet.insert(*theTranslator);
+ InitializeTranslator(*theTranslator, inBridge);
+ }
+ }
+ }
+ } else {
+ // Binary load path is quite different than normal load path and
+ // nothing else will load here.
+ QT3DS_ASSERT(false);
+ }
+ if (inPresentation && theIScene)
+ FinalizeScene(*inPresentation, *theIScene);
+ return theIScene;
+ }
+
+ // threadsafe
+ // Can be called from any thread
+ bool GetBinaryLoadFileName(eastl::string &inPresentationFilename,
+ eastl::string &outResult) override
+ {
+ eastl::string theBinaryPath(inPresentationFilename.c_str());
+ qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(theBinaryPath, "binary");
+ qt3ds::foundation::CFileTools::SetExtension(
+ theBinaryPath, GetBinaryExtension()); // uibb: short for ui binary binding
+ outResult = theBinaryPath;
+ return true;
+ }
+
+ // threadsafe
+ // returns a handle to the loaded object. Return value of zero means error.
+ qt3ds::QT3DSU32 LoadSceneStage1(CRegisteredString inPresentationDirectory,
+ uic::render::ILoadedBuffer &inData) override
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load Scene Graph Stage 1");
+ NVDataRef<QT3DSU8> theLoadedData(inData.Data());
+ SDataReader theReader(theLoadedData.begin(), theLoadedData.end());
+
+ QT3DSU32 theFileSig = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theBinaryVersion = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theDataSectionSize = (QT3DSU32)(theReader.m_EndPtr - theReader.m_CurrentPtr);
+
+ if (theFileSig != GetFileTag()
+ || theBinaryVersion != SGraphObject::GetSceneGraphBinaryVersion()) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ QT3DSU32 theLoadingSceneIndex = 0;
+ SSceneLoadData *theScene;
+ {
+ Mutex::ScopedLock __locker(m_LoadingScenesMutex);
+ theLoadingSceneIndex = (QT3DSU32)m_LoadingScenes.size() + 1;
+ m_LoadingScenes.push_back(
+ QT3DS_NEW(m_Context->GetAllocator(), SSceneLoadData)(m_Context->GetAllocator()));
+ theScene = m_LoadingScenes.back();
+ }
+ // preserve the data buffer because we run directly from it; there isn't a memcopy.
+ theScene->m_Data = inData;
+
+ QT3DSU32 theTranslatorOffset = theReader.LoadRef<QT3DSU32>();
+
+ NVDataRef<QT3DSU8> theSGData = NVDataRef<QT3DSU8>(theReader.m_CurrentPtr, theTranslatorOffset);
+ NVDataRef<QT3DSU8> theTranslatorData = NVDataRef<QT3DSU8>(
+ theReader.m_CurrentPtr + theTranslatorOffset, theDataSectionSize - theTranslatorOffset);
+
+ CStrTableOrDataRef theStrTableData(m_Context->m_CoreContext->GetStringTable());
+ if (m_StrTableData.size())
+ theStrTableData = CStrTableOrDataRef(m_StrTableData);
+
+ theScene->m_Presentation = SGraphObjectSerializer::Load(
+ theSGData, m_StrTableData, m_Context->m_CoreContext->GetDynamicObjectSystemCore(),
+ m_Context->m_CoreContext->GetPathManagerCore(), m_Context->GetAllocator(),
+ inPresentationDirectory);
+ if (theScene->m_Presentation)
+ theScene->m_Presentation->m_PresentationDirectory = inPresentationDirectory;
+
+ theScene->m_TranslatorData = theTranslatorData;
+ theScene->m_SceneGraphData = theSGData;
+
+ {
+ Mutex::ScopedLock __locker(m_LoadingScenesMutex);
+ m_LoadingScenes[theLoadingSceneIndex - 1] = theScene;
+ }
+ return theLoadingSceneIndex;
+ }
+
+ // threadsafe
+ // still does not require openGL context but has dependency on a few other things.
+ void LoadSceneStage2(qt3ds::QT3DSU32 inSceneHandle, Q3DStudio::IPresentation &inPresentation,
+ size_t inElementMemoryOffset, Q3DStudio::IScriptBridge &inBridge) override
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load Scene Graph Stage 2");
+ QT3DSU32 theSceneIndex = QT3DS_MAX_U32;
+ SSceneLoadData *theScene;
+ {
+ Mutex::ScopedLock __locker(m_LoadingScenesMutex);
+ QT3DSU32 numLoadingScenes = (QT3DSU32)m_LoadingScenes.size();
+ if (inSceneHandle && inSceneHandle <= numLoadingScenes) {
+ theSceneIndex = inSceneHandle - 1;
+ theScene = m_LoadingScenes[theSceneIndex];
+ } else {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ }
+ SDataReader theReader(theScene->m_TranslatorData.begin(), theScene->m_TranslatorData.end());
+ QT3DSU32 theNumTranslators = theReader.LoadRef<QT3DSU32>();
+ theScene->m_Translators.resize(theNumTranslators);
+ theScene->m_RuntimePresentation = &inPresentation;
+ for (QT3DSU32 idx = 0, end = theNumTranslators; idx < end; ++idx) {
+ CUICTranslator *theTranslator = CUICTranslator::LoadTranslator(
+ theReader, inElementMemoryOffset, theScene->m_SceneGraphData,
+ theScene->m_AutoAllocator);
+ if (theTranslator) {
+ InitializeTranslator(*theTranslator, inBridge);
+ }
+ theScene->m_Translators[idx] = theTranslator;
+ }
+ }
+
+ void OnGraphicsInitialized()
+ {
+ QT3DS_ASSERT(m_Context->m_UICContext.mPtr);
+ // this means graphics have been initialized
+ eastl::string theSourcePathStr;
+ IBufferManager &theManager(m_Context->m_UICContext->GetBufferManager());
+ nvvector<CRegisteredString> theSourcePathList(m_Context->GetAllocator(),
+ "TempSourcePathList");
+ for (QT3DSU32 idx = 0, end = m_SourcePaths.size(); idx < end; ++idx) {
+ theSourcePathStr.assign(m_SourcePaths[idx].first);
+ bool hasTransparency = m_SourcePaths[idx].second;
+ if (theSourcePathStr.size() > 4) {
+ CRegisteredString theObjectPath = m_SourcePaths[idx].first;
+ const char *theEnding = theSourcePathStr.c_str() + theSourcePathStr.size() - 3;
+ if (IsImage(theEnding)) {
+ theManager.SetImageHasTransparency(theObjectPath, hasTransparency);
+ theSourcePathList.push_back(theObjectPath);
+ } else {
+ if (theSourcePathStr.find(".mesh") != eastl::string::npos)
+ theManager.LoadMesh(theObjectPath);
+ }
+ }
+ }
+
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Initial Batch Image Load");
+
+ m_Context->m_UICContext->GetImageBatchLoader().LoadImageBatch(
+ toConstDataRef(theSourcePathList.data(), theSourcePathList.size()),
+ CRegisteredString(), NULL);
+ }
+
+ {
+
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Initialize Scenes");
+ for (QT3DSU32 idx = 0, end = m_LoadingScenes.size(); idx < end; ++idx) {
+ SSceneLoadData &theScene = *m_LoadingScenes[idx];
+ // m_Context->m_Foundation->error( QT3DS_WARN, "Finalizing scene %d", (int)idx+1 );
+ if (theScene.m_RuntimePresentation) {
+ SUICRenderScene *theIScene = QT3DS_NEW(m_Context->GetAllocator(), SUICRenderScene)(
+ *m_Context, *m_Context->m_UICContext, theScene);
+ FinalizeScene(*theScene.m_RuntimePresentation, *theIScene);
+ } else {
+ qCWarning(WARNING, "Failed to finalize scene %d", (int)idx + 1);
+ }
+ }
+ }
+ }
+
+ void LoadRenderPlugin(const char *inAssetIDString, const char *inPath,
+ const char *inArgs) override
+ {
+ Q3DStudio::CDLLManager &theDLLManager = Q3DStudio::CDLLManager::GetDLLManager();
+ long theHandle = theDLLManager.LoadLibrary(inPath, EDLLTYPE_RENDERABLE_PLUGIN);
+ if (theHandle >= 0) {
+ uic::render::IOffscreenRenderer *theOffscreenRenderer =
+ QT3DS_NEW(m_Context->GetAllocator(),
+ uic::render::COldNBustedPluginRenderer)(*m_Context->m_UICContext, theHandle);
+ qt3ds::foundation::CRegisteredString theAssetString =
+ m_Context->m_CoreContext->GetStringTable().RegisterStr(inAssetIDString);
+
+ m_Context->m_UICContext->GetOffscreenRenderManager().RegisterOffscreenRenderer(
+ theAssetString, *theOffscreenRenderer);
+
+ PROC_Initialize theInitializeProc =
+ reinterpret_cast<PROC_Initialize>(theDLLManager.GetProc("Initialize", theHandle));
+ Q3DStudio_ASSERT(theInitializeProc);
+#if !defined (Q_OS_MACOS)
+ PROC_SetEGLInfo theSetEGLInfoProc =
+ reinterpret_cast<PROC_SetEGLInfo>(theDLLManager.GetProc("SetEGLInfo", theHandle));
+ // Set EGL parameters used for optional context creation
+ if (theSetEGLInfoProc) {
+ Q3DStudio::SEGLInfo *theInfo = m_WindowSystem.GetEGLInfo();
+ if (theInfo)
+ theSetEGLInfoProc(theInfo->display, theInfo->context, theInfo->surface,
+ theInfo->config);
+ }
+#endif
+ if (theInitializeProc && theInitializeProc(inArgs) == EDLLSTATUS_OK)
+ m_RenderPlugins.push_back(make_pair(theAssetString, theHandle));
+ else
+ qCWarning(qt3ds::INVALID_OPERATION) << "Unable to load plugin " << inAssetIDString;
+ } else
+ qCWarning(qt3ds::INVALID_OPERATION) << "Unable to load plugin " << inAssetIDString;
+
+ return;
+ }
+
+ void LoadQmlStreamerPlugin(const char *inAssetIDString) override
+ {
+ uic::render::IOffscreenRenderer *theOffscreenRenderer =
+ QT3DS_NEW(m_Context->GetAllocator(),
+ Q3DSQmlRender)(*m_Context->m_UICContext, inAssetIDString);
+ if (theOffscreenRenderer) {
+ qt3ds::foundation::CRegisteredString theAssetString =
+ m_Context->m_CoreContext->GetStringTable().RegisterStr(inAssetIDString);
+ m_Context->m_UICContext->GetOffscreenRenderManager().RegisterOffscreenRenderer(
+ SOffscreenRendererKey(theAssetString), *theOffscreenRenderer);
+
+ m_RenderPlugins.push_back(make_pair(theAssetString, 0));
+ }
+ }
+
+ void BinarySave(Q3DStudio::IScene &inScene) override
+ {
+ SUICRenderScene &theScene = static_cast<SUICRenderScene &>(inScene);
+ qt3ds::render::SWriteBuffer theWriteBuffer(m_Context->GetAllocator(), "BinarySaveBuffer");
+ qt3ds::render::SPtrOffsetMap theSGOffsetMap(m_Context->GetAllocator(), "PointerOffsetMap");
+ // Start with some versioning and sanity checks.
+ theWriteBuffer.write(GetFileTag());
+ theWriteBuffer.write(SGraphObject::GetSceneGraphBinaryVersion());
+ QT3DSU32 theTranslatorOffsetAddress = theWriteBuffer.size();
+ // Now the data section starts. Offsets should be relative to here, not the first
+ // 8 bytes.
+ theWriteBuffer.writeZeros(4); // offset where the translator data starts;
+ QT3DSU32 theDataSectionStart = theWriteBuffer.size();
+
+ // These offsets are after we have read in the data section
+ SGraphObjectSerializer::Save(
+ m_Context->m_RenderContext->GetFoundation(), *theScene.m_Presentation, theWriteBuffer,
+ m_Context->m_UICContext->GetDynamicObjectSystem(),
+ m_Context->m_UICContext->GetPathManager(), theSGOffsetMap,
+ m_Context->m_CoreContext->GetStringTable(), theScene.m_GraphObjectList);
+
+ theWriteBuffer.align(sizeof(void *));
+ QT3DSU32 theTranslatorCountAddress = theWriteBuffer.size();
+ QT3DSU32 theTranslatorOffset = theTranslatorCountAddress - theDataSectionStart;
+
+ theWriteBuffer.writeZeros(4);
+ // Now write out the translators verbatim. We get an adjustment parameter on save that
+ // allows a translation
+ // from old element ptr->new element ptr.
+ QT3DSU32 theTranslatorCount = 0;
+ for (QT3DSU32 idx = 0, end = theScene.m_GraphObjectList.size(); idx < end; ++idx) {
+ CUICTranslator *theTranslator =
+ CUICTranslator::GetTranslatorFromGraphNode(*theScene.m_GraphObjectList[idx]);
+ // Presentation nodes don't have translator
+ if (theTranslator) {
+ qt3ds::render::SPtrOffsetMap::iterator theIter =
+ theSGOffsetMap.find(theScene.m_GraphObjectList[idx]);
+ if (theIter != theSGOffsetMap.end()) {
+ QT3DSU32 theOffset = theIter->second;
+ theTranslator->Save(theWriteBuffer, theOffset);
+ ++theTranslatorCount;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ QT3DSU32 *theTranslatorCountPtr =
+ reinterpret_cast<QT3DSU32 *>(theWriteBuffer.begin() + theTranslatorCountAddress);
+ *theTranslatorCountPtr = theTranslatorCount;
+ QT3DSU32 *theTranslatorOffsetPtr =
+ reinterpret_cast<QT3DSU32 *>(theWriteBuffer.begin() + theTranslatorOffsetAddress);
+ *theTranslatorOffsetPtr = theTranslatorOffset;
+
+ Q3DStudio::IPresentation &thePresentation = *theScene.m_RuntimePresentation;
+ eastl::string theBinaryPath(thePresentation.GetFilePath().toLatin1().constData());
+ qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(theBinaryPath, "binary");
+ eastl::string theBinaryDir(theBinaryPath);
+ qt3ds::foundation::CFileTools::GetDirectory(theBinaryDir);
+ qt3ds::foundation::CFileTools::SetExtension(
+ theBinaryPath, GetBinaryExtension()); // uibb: short for ui binary binding
+
+ Q3DStudio::CFileStream theStream(theBinaryPath.c_str(), "wb");
+ if (theStream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ }
+
+ theStream.WriteRaw(theWriteBuffer.begin(), theWriteBuffer.size());
+ theStream.Close();
+ }
+
+ // We save in the reverse order that we load because the effect system may add strings
+ // to the string table when it is writing its data out, this the string table needs to come
+ // last.
+ // Loading, obviously, the string table needs to be the first object loaded.
+ void BinarySaveManagerData(qt3ds::foundation::IOutStream &inStream,
+ const char *inBinaryDir) override
+ {
+ qt3ds::render::SWriteBuffer theWriteBuffer(m_Context->GetAllocator(), "BinarySaveBuffer");
+ IStringTable &theStrTable = m_Context->m_CoreContext->GetStringTable();
+ eastl::string theProjectDir(inBinaryDir);
+ qt3ds::foundation::CFileTools::GetDirectory(theProjectDir);
+
+ // We save everything before the string table because often times saving something creates
+ // new strings.
+ theWriteBuffer.writeZeros(4); // Total data size
+ // Dynamic object system
+ theWriteBuffer.writeZeros(4); // Effect system offset
+ // effect system
+ theWriteBuffer.writeZeros(4); // Material system offset
+ // material system
+ theWriteBuffer.writeZeros(4); // Binary path offset
+ // binary path data
+ theWriteBuffer.writeZeros(4); // Plugin manager offset
+ // plugin manager
+ theWriteBuffer.writeZeros(4); // String system offset
+ // string system last.
+ QT3DSU32 theOffsetStart = theWriteBuffer.size();
+ m_Context->m_UICContext->GetDynamicObjectSystem().Save(
+ theWriteBuffer, theStrTable.GetRemapMap(), theProjectDir.c_str());
+ theWriteBuffer.align(sizeof(void *));
+ QT3DSU32 theEffectSystemOffset = theWriteBuffer.size() - theOffsetStart;
+ m_Context->m_UICContext->GetEffectSystem().Save(theWriteBuffer, theStrTable.GetRemapMap(),
+ theProjectDir.c_str());
+ theWriteBuffer.align(sizeof(void *));
+ QT3DSU32 theMaterialSystemOffset = theWriteBuffer.size() - theOffsetStart;
+ m_Context->m_UICContext->GetCustomMaterialSystem().Save(
+ theWriteBuffer, theStrTable.GetRemapMap(), theProjectDir.c_str());
+ QT3DSU32 theBinaryPathOffset = theWriteBuffer.size() - theOffsetStart;
+
+ theWriteBuffer.write((QT3DSU32)m_SourcePaths.size());
+ for (nvvector<pair<CRegisteredString, bool>>::iterator iter = m_SourcePaths.begin(),
+ end = m_SourcePaths.end();
+ iter != end; ++iter) {
+ CRegisteredString theStr(iter->first);
+ theStr.Remap(theStrTable.GetRemapMap());
+ theWriteBuffer.write((size_t)theStr.c_str());
+ QT3DSU32 theSourcePathFlags = iter->second ? 1 : 0;
+ theWriteBuffer.write(theSourcePathFlags);
+ }
+
+ QT3DSU32 thePluginManagerOffset = theWriteBuffer.size() - theOffsetStart;
+
+ m_Context->m_UICContext->GetRenderPluginManager().Save(
+ theWriteBuffer, theStrTable.GetRemapMap(), theProjectDir.c_str());
+
+ QT3DSU32 theStringTableOffset = theWriteBuffer.size() - theOffsetStart;
+
+ theStrTable.Save(theWriteBuffer);
+
+ QT3DSU32 *theSizePtr = reinterpret_cast<QT3DSU32 *>(theWriteBuffer.begin());
+
+ theSizePtr[0] = theWriteBuffer.size() - 4; // overall size
+ theSizePtr[1] = theEffectSystemOffset;
+ theSizePtr[2] = theMaterialSystemOffset;
+ theSizePtr[3] = theBinaryPathOffset; // thePathOffset
+ theSizePtr[4] = thePluginManagerOffset;
+ theSizePtr[5] = theStringTableOffset;
+
+ inStream.Write(theWriteBuffer.begin(), theWriteBuffer.size());
+ }
+
+ NVDataRef<qt3ds::QT3DSU8> BinaryLoadManagerData(qt3ds::foundation::IInStream &inStream,
+ const char *inBinaryDir) override
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - String Table + Render Objects");
+ QT3DS_ASSERT(m_Context->m_FlowData == NULL);
+ QT3DSU32 dataSize = 0;
+ inStream.Read(dataSize);
+ m_Context->m_FlowData = (QT3DSU8 *)m_Context->m_CoreContext->GetAllocator().allocate(
+ dataSize, "SceneManager::BinaryFlowData", __FILE__, __LINE__);
+
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - Initial Data Load");
+ inStream.Read(m_Context->m_FlowData, dataSize);
+ }
+ SDataReader theReader(m_Context->m_FlowData, m_Context->m_FlowData + dataSize);
+ QT3DSU32 theEffectSystemOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theMaterialSystemOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theBinaryPathOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 thePluginManagerOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theStringTableOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU8 *theStartOffset = theReader.m_CurrentPtr;
+ IStringTable &theStrTable = m_Context->m_CoreContext->GetStringTable();
+
+ // Load string table.
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - Load String Table");
+ m_StrTableData = toDataRef(theReader.m_CurrentPtr + theStringTableOffset,
+ dataSize - theStringTableOffset);
+ theStrTable.Load(m_StrTableData);
+ }
+
+ // Load source paths to preload heavy data
+ theReader.m_CurrentPtr = theStartOffset + theBinaryPathOffset;
+ QT3DSU32 theNumSourcePaths = theReader.LoadRef<QT3DSU32>();
+ eastl::string theSourcePathStr;
+ eastl::string theProjectDir(inBinaryDir);
+ eastl::string theShaderCacheDir(inBinaryDir);
+
+ // Up one moves to the project directory.
+ qt3ds::foundation::CFileTools::GetDirectory(theProjectDir);
+ const char8_t *theBasePath(theProjectDir.c_str());
+
+ m_ProjectDir = theStrTable.RegisterStr(theProjectDir.c_str());
+ m_BinaryDir = theStrTable.RegisterStr(theShaderCacheDir.c_str());
+
+ // Preload the heavy buffers
+ m_SourcePaths.resize(theNumSourcePaths);
+ for (QT3DSU32 idx = 0, end = theNumSourcePaths; idx < end; ++idx) {
+ CRegisteredString thePath = theReader.LoadRef<CRegisteredString>();
+ QT3DSU32 theFlags = theReader.LoadRef<QT3DSU32>();
+ thePath.Remap(m_StrTableData);
+ bool theBoolFlagValue = theFlags ? true : false;
+ m_SourcePaths[idx] = eastl::make_pair(thePath, theBoolFlagValue);
+ }
+
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - Base Dynamic System");
+ // Load effect system.
+ NVDataRef<QT3DSU8> theDynamicSystemData(theStartOffset, theEffectSystemOffset);
+ m_Context->m_CoreContext->GetDynamicObjectSystemCore().Load(
+ theDynamicSystemData, m_StrTableData, theBasePath);
+ }
+
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - Effect System");
+ NVDataRef<QT3DSU8> theEffectSystemData(theStartOffset + theEffectSystemOffset,
+ theMaterialSystemOffset - theEffectSystemOffset);
+ m_Context->m_CoreContext->GetEffectSystemCore().Load(theEffectSystemData,
+ m_StrTableData, theBasePath);
+ }
+
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - Material System");
+ NVDataRef<QT3DSU8> theMaterialSystemData(theStartOffset + theMaterialSystemOffset,
+ thePluginManagerOffset - theMaterialSystemOffset);
+ m_Context->m_CoreContext->GetMaterialSystemCore().Load(theMaterialSystemData,
+ m_StrTableData, theBasePath);
+ }
+
+ {
+ SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(),
+ "Load UIAB - Plugin Manager Data");
+ NVDataRef<QT3DSU8> thePluginManagerData(theStartOffset + thePluginManagerOffset,
+ theStringTableOffset - thePluginManagerOffset);
+ m_Context->m_CoreContext->GetRenderPluginCore().Load(thePluginManagerData,
+ m_StrTableData, theBasePath);
+ }
+
+ return m_StrTableData;
+ }
+
+ virtual void DeleteScene(Q3DStudio::IPresentation *inPresentation)
+ {
+ QT3DSU32 idx;
+ QT3DSU32 end;
+ for (idx = 0, end = m_Scenes.size(); idx < end; ++idx) {
+ if (m_Scenes[idx].first == inPresentation)
+ break;
+ }
+ if (idx < m_Scenes.size()) {
+ m_Scenes[idx].second->Release();
+ m_Scenes.erase(m_Scenes.begin() + idx);
+ }
+ }
+
+ Q3DStudio::BOOL Update() override
+ {
+ bool theResult = false;
+ long theSceneCount = m_Scenes.size();
+ for (long theSceneIndex = 0; theSceneIndex < theSceneCount; ++theSceneIndex) {
+ SUICRenderScene *theScene = m_Scenes[theSceneIndex].second;
+ theResult |= theScene->Update();
+ }
+ return theResult;
+ }
+
+ Q3DStudio::BOOL RenderPresentation(Q3DStudio::IPresentation *inPresentation) override
+ {
+ SUICRenderScene *theFirstScene = NULL;
+ for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == NULL; ++idx)
+ if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation)
+ theFirstScene = m_Scenes[idx].second;
+
+ if (theFirstScene && theFirstScene->m_Presentation) {
+ m_LastRenderedScene = theFirstScene;
+ if (theFirstScene->m_Presentation->m_Scene
+ && theFirstScene->m_Presentation->m_Scene->m_UseClearColor) {
+ m_Context->m_UICContext->SetSceneColor(
+ QT3DSVec4(theFirstScene->m_Presentation->m_Scene->m_ClearColor, 1.0f));
+ } else
+ m_Context->m_UICContext->SetSceneColor(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+
+ // Setup the render rotation *before* rendering so that the magic can happen on begin
+ // render.
+ if (m_Context->m_RenderRotationsEnabled)
+ m_Context->m_UICContext->SetRenderRotation(
+ theFirstScene->m_Presentation->m_PresentationRotation);
+ else
+ m_Context->m_UICContext->SetRenderRotation(RenderRotationValues::NoRotation);
+
+ m_Context->m_UICContext->SetPresentationDimensions(SWindowDimensions(
+ (QT3DSU32)theFirstScene->m_Presentation->m_PresentationDimensions.x,
+ (QT3DSU32)theFirstScene->m_Presentation->m_PresentationDimensions.y));
+ }
+
+ m_Context->m_UICContext->BeginFrame();
+ m_Context->m_RenderContext->ResetBlendState();
+
+ // How exactly does this work, I have no idea.
+ // Should we only render the first scene and not every scene, perhaps?
+ bool wasDirty = false;
+ if (theFirstScene)
+ wasDirty = theFirstScene->PrepareForRender();
+ else {
+ m_Context->m_RenderContext->SetClearColor(QT3DSVec4(0, 0, 0, 0));
+ m_Context->m_RenderContext->Clear(qt3ds::render::NVRenderClearFlags(
+ NVRenderClearValues::Color | NVRenderClearValues::Depth));
+ }
+ m_Context->m_UICContext->RunRenderTasks();
+ if (theFirstScene)
+ theFirstScene->Render();
+
+ m_Context->m_UICContext->EndFrame();
+
+ return wasDirty;
+ }
+ // I think render::check resize is called so this isn't necessary
+ void OnViewResize(Q3DStudio::INT32 inViewWidth, Q3DStudio::INT32 inViewHeight) override
+ {
+ m_ViewWidth = inViewWidth;
+ m_ViewHeight = inViewHeight;
+ }
+ void GetViewSize(Q3DStudio::INT32 &outWidth, Q3DStudio::INT32 &outHeight) override
+ {
+ outWidth = m_ViewWidth;
+ outHeight = m_ViewHeight;
+ }
+
+ Q3DStudio::STextSizes GetDisplayDimensions(Q3DStudio::IPresentation *inPresentation) override
+ {
+ SUICRenderScene *theFirstScene = NULL;
+ for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == NULL; ++idx)
+ if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation)
+ theFirstScene = m_Scenes[idx].second;
+ if (theFirstScene) {
+ m_Context->m_UICContext->SetPresentationDimensions(SWindowDimensions(
+ (QT3DSU32)theFirstScene->m_Presentation->m_PresentationDimensions.x,
+ (QT3DSU32)theFirstScene->m_Presentation->m_PresentationDimensions.y));
+ render::NVRenderRectF theDisplayViewport =
+ m_Context->m_UICContext->GetDisplayViewport();
+ return Q3DStudio::STextSizes(
+ static_cast<Q3DStudio::INT32>(theDisplayViewport.m_Width),
+ static_cast<Q3DStudio::INT32>(theDisplayViewport.m_Height));
+ }
+ return Q3DStudio::STextSizes(static_cast<Q3DStudio::INT32>(0),
+ static_cast<Q3DStudio::INT32>(0));
+ }
+
+ Q3DStudio::TElement *UserPick(float mouseX, float mouseY) override
+ {
+ if (m_LastRenderedScene) {
+ return m_LastRenderedScene->UserPick(mouseX, mouseY);
+ }
+ return NULL;
+ }
+
+ Option<QT3DSVec2> FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
+ NVDataRef<Q3DStudio::TElement *> inElements,
+ Q3DStudio::FacePositionPlanes::Enum inPlane) override
+ {
+ if (m_LastRenderedScene) {
+
+ return m_LastRenderedScene->FacePosition(inElement, mouseX, mouseY, inElements,
+ inPlane);
+ }
+ return Empty();
+ }
+
+ Q3DStudio::SPickFrame AdvancePickFrame(const Q3DStudio::SInputFrame &inInputFrame) override
+ {
+ // We now have a new input frame, and our results are invalid but ready to be filled
+ m_PickFrame.m_InputFrame = inInputFrame;
+ m_PickFrame.m_Model = NULL;
+ m_PickFrame.m_ResultValid = false;
+ if (m_LastRenderedScene) {
+ if (m_PickFrame.m_InputFrame.m_PickValid)
+ m_LastRenderedScene->Pick(m_PickFrame);
+ }
+ return m_PickFrame;
+ }
+
+ void Release() override
+ {
+ long theRenderPluginSize = m_RenderPlugins.size();
+ Q3DStudio::CDLLManager &theDLLManager = Q3DStudio::CDLLManager::GetDLLManager();
+ for (int theRenderPluginIndex = 0; theRenderPluginIndex < theRenderPluginSize;
+ ++theRenderPluginIndex) {
+ long theDLLHandle = m_RenderPlugins[theRenderPluginIndex].second;
+ PROC_Uninitialize theUninitializeProc = reinterpret_cast<PROC_Uninitialize>(
+ theDLLManager.GetProc("Uninitialize", theDLLHandle));
+ Q3DStudio_ASSERT(theUninitializeProc);
+ theUninitializeProc &&theUninitializeProc();
+
+ theDLLManager.UnloadLibrary(theDLLHandle);
+ }
+
+ // Ensure the binding core doesn't get released until after we get released.
+ NVScopedRefCounted<SBindingCore> theContext(m_Context);
+ NVDelete(m_Context->GetAllocator(), this);
+ }
+};
+
+struct SRenderFactory;
+
+struct SVisualStateHandler : public uic::state::IVisualStateInterpreterFactory,
+ public uic::state::IVisualStateCommandHandler
+{
+ NVAllocatorCallback &m_Allocator;
+ QT3DSI32 mRefCount;
+ SRenderFactory &m_Factory;
+
+public:
+ SVisualStateHandler(NVAllocatorCallback &alloc, SRenderFactory &inFactory)
+ : m_Allocator(alloc)
+ , mRefCount(0)
+ , m_Factory(inFactory)
+ {
+ }
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Allocator)
+
+ uic::state::IStateInterpreter *OnNewStateMachine(const char8_t *inPath,
+ const char8_t *inId,
+ const char8_t *inDatamodelFunction) override;
+
+ void Handle(const uic::state::SVisualStateCommand &inCommand,
+ uic::state::IScriptContext &inScriptContext) override;
+};
+
+struct SRenderFactory : public IUICRenderFactoryCore, public IUICRenderFactory
+{
+ NVScopedRefCounted<SBindingCore> m_Context;
+
+ NVScopedRefCounted<Q3DStudio::CLuaEngine> m_ScriptBridge;
+ NVScopedRefCounted<Q3DStudio::CQmlEngine> m_ScriptBridgeQml;
+ NVScopedRefCounted<SUICRenderSceneManager> m_SceneManager;
+ NVScopedRefCounted<uic::state::IVisualStateContext> m_VisualStateContext;
+ NVScopedRefCounted<uic::evt::IEventSystem> m_EventSystem;
+ uic::runtime::IApplicationCore *m_ApplicationCore;
+ uic::runtime::IApplication *m_Application;
+ QT3DSI32 m_RefCount;
+
+ SRenderFactory(SBindingCore &inCore)
+ : m_Context(inCore)
+ , m_ScriptBridge(NULL)
+ , m_ScriptBridgeQml(NULL)
+ , m_SceneManager(NULL)
+ , m_ApplicationCore(NULL)
+ , m_Application(NULL)
+ , m_RefCount(0)
+ {
+ }
+
+ ~SRenderFactory()
+ {
+ using namespace Q3DStudio;
+ // Release the visual state context.
+ m_VisualStateContext = NULL;
+ // Release the event system, it must be released before script engine
+ m_EventSystem = NULL;
+ m_ScriptBridge->Shutdown(*m_Context->m_Foundation);
+ m_ScriptBridgeQml->Shutdown(*m_Context->m_Foundation);
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVScopedRefCounted<SBindingCore> theContext(m_Context);
+ NVDelete(m_Context->GetAllocator(), this);
+ }
+ }
+
+ uic::render::IUICRenderContextCore &GetUICRenderContextCore() override
+ {
+ return *m_Context->m_CoreContext;
+ }
+
+ uic::runtime::IApplicationCore *GetApplicationCore() override { return m_ApplicationCore; }
+ void SetApplicationCore(uic::runtime::IApplicationCore *app) override
+ {
+ m_ApplicationCore = app;
+ }
+
+ Q3DStudio::ISceneBinaryLoader &GetSceneLoader() override
+ {
+ if (m_SceneManager == NULL)
+ m_SceneManager = QT3DS_NEW(m_Context->GetAllocator(),
+ SUICRenderSceneManager)(*m_Context, m_Context->m_WindowSystem);
+ return *m_SceneManager;
+ }
+
+ Q3DStudio::ITegraApplicationRenderEngine &CreateRenderEngine() override
+ {
+ return m_Context->CreateRenderer();
+ }
+ Q3DStudio::ISceneManager &GetSceneManager() override
+ {
+ if (m_SceneManager == NULL)
+ m_SceneManager = QT3DS_NEW(m_Context->GetAllocator(),
+ SUICRenderSceneManager)(*m_Context, m_Context->m_WindowSystem);
+ return *m_SceneManager;
+ }
+ Q3DStudio::IScriptBridge &GetScriptEngine() override
+ {
+ if (m_ScriptBridge == NULL) {
+ m_ScriptBridge =
+ Q3DStudio::CLuaEngine::Create(*m_Context->m_Foundation, m_Context->m_TimeProvider);
+ m_ScriptBridge->PreInitialize();
+ }
+
+ return *m_ScriptBridge;
+ }
+ Q3DStudio::IScriptBridge &GetScriptEngineQml() override
+ {
+ if (m_ScriptBridgeQml == NULL) {
+ m_ScriptBridgeQml =
+ Q3DStudio::CQmlEngine::Create(*m_Context->m_Foundation, m_Context->m_TimeProvider);
+ }
+
+ return *m_ScriptBridgeQml;
+ }
+ uic::render::IInputStreamFactory &GetInputStreamFactory() override
+ {
+ return m_Context->m_CoreContext->GetInputStreamFactory();
+ }
+
+ uic::render::IUICRenderContext &GetUICRenderContext() override
+ {
+ return *m_Context->m_UICContext;
+ }
+ uic::state::IVisualStateContext &GetVisualStateContext() override
+ {
+ if (!m_VisualStateContext) {
+ m_VisualStateContext = uic::state::IVisualStateContext::Create(
+ *m_Context->m_Foundation, m_Context->m_CoreContext->GetStringTable());
+ SVisualStateHandler *newHandle =
+ QT3DS_NEW(m_Context->m_Foundation->getAllocator(),
+ SVisualStateHandler)(m_Context->m_Foundation->getAllocator(), *this);
+ m_VisualStateContext->SetCommandHandler(newHandle);
+ m_VisualStateContext->SetInterpreterFactory(newHandle);
+ }
+ return *m_VisualStateContext;
+ }
+ uic::evt::IEventSystem &GetEventSystem() override
+ {
+ if (!m_EventSystem) {
+ m_EventSystem = uic::evt::IEventSystem::Create(*m_Context->m_Foundation);
+ }
+ return *m_EventSystem;
+ }
+ Q3DStudio::ITimeProvider &GetTimeProvider() override { return m_Context->m_TimeProvider; }
+ qt3ds::foundation::IStringTable &GetStringTable() override
+ {
+ return m_Context->m_CoreContext->GetStringTable();
+ }
+ qt3ds::NVFoundationBase &GetFoundation() override { return *m_Context->m_Foundation.mPtr; }
+ qt3ds::foundation::IPerfTimer &GetPerfTimer() override
+ {
+ return m_Context->m_CoreContext->GetPerfTimer();
+ }
+ uic::runtime::IApplication *GetApplication() override { return m_Application; }
+ void SetApplication(uic::runtime::IApplication *app) override
+ {
+ m_Application = app;
+ if (app) {
+ GetScriptEngine();
+ m_ScriptBridge->SetApplication(*app);
+ // Most of the script bridge lua functions will hard crash if
+ // the initialization happens before the application is set.
+ // This keeps the errors in lua-land instead of in crashing ui composer.
+ m_ScriptBridge->Initialize();
+
+ // QML engine
+ GetScriptEngineQml();
+ m_ScriptBridgeQml->SetApplication(*app);
+ }
+ }
+ void SetDllDir(const char *dllDir) override
+ {
+ m_Context->m_CoreContext->GetRenderPluginCore().SetDllDir(dllDir);
+ }
+
+ void AddSearchPath(const char8_t *inFile) override
+ {
+ m_Context->m_CoreContext->GetInputStreamFactory().AddSearchDirectory(inFile);
+ }
+ virtual void Release() { NVDelete(m_Context->GetAllocator(), this); }
+
+ struct SContextTypeRenderFactory : public IRuntimeFactoryRenderFactory
+ {
+ QSurfaceFormat format;
+ SContextTypeRenderFactory(const QSurfaceFormat &fmt)
+ : format(fmt)
+ {
+ }
+
+ qt3ds::render::NVRenderContext *CreateRenderContext(qt3ds::NVFoundationBase &foundat,
+ IStringTable &strt) override
+ {
+#ifndef UIC_NO_RENDER_SYMBOLS
+ qt3ds::render::NVRenderContext &retval = NVRenderContext::CreateGL(foundat, strt, format);
+ return &retval;
+#else
+ qt3ds::render::NVRenderContext &retval = NVRenderContext::CreateNULL(foundat, strt);
+ return &retval;
+#endif
+ }
+ };
+
+ IUICRenderFactory &CreateRenderFactory(const QSurfaceFormat& format) override
+ {
+
+ SContextTypeRenderFactory theContextFactory(format);
+ m_Context->CreateRenderContext(theContextFactory);
+
+ GetSceneLoader();
+ {
+ SStackPerfTimer __loadTimer(GetPerfTimer(), "SceneManager OnGraphicsInitialized");
+ m_SceneManager->OnGraphicsInitialized();
+ }
+ return *this;
+ }
+};
+
+uic::state::IStateInterpreter *
+SVisualStateHandler::OnNewStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodelFunction)
+{
+ m_Factory.GetScriptEngine();
+ m_Factory.GetSceneManager();
+
+ return m_Factory.m_ScriptBridge->CreateStateMachine(inPath, inId, inDatamodelFunction);
+}
+
+Q3DStudio::SScriptEngineGotoSlideArgs ToEngine(const uic::state::SGotoSlideData &inData)
+{
+ using namespace uic::state;
+ Q3DStudio::SScriptEngineGotoSlideArgs retval;
+ if (inData.m_Mode.hasValue()) {
+ switch (*inData.m_Mode) {
+ case SlidePlaybackModes::StopAtEnd:
+ retval.m_Mode = Q3DStudio::TimePolicyModes::StopAtEnd;
+ break;
+ case SlidePlaybackModes::Looping:
+ retval.m_Mode = Q3DStudio::TimePolicyModes::Looping;
+ break;
+ case SlidePlaybackModes::Ping:
+ retval.m_Mode = Q3DStudio::TimePolicyModes::Ping;
+ break;
+ case SlidePlaybackModes::PingPong:
+ retval.m_Mode = Q3DStudio::TimePolicyModes::PingPong;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ if (inData.m_PlaythroughTo.hasValue())
+ retval.m_PlaythroughTo = inData.m_PlaythroughTo->c_str();
+ if (inData.m_Paused.hasValue())
+ retval.m_Paused = inData.m_Paused;
+ retval.m_Rate = inData.m_Rate;
+ retval.m_Reverse = inData.m_Reverse;
+ if (inData.m_StartTime.hasValue())
+ retval.m_StartTime = *inData.m_StartTime;
+ return retval;
+}
+
+class CStateScriptEngineCallFunctionArgRetriever
+ : public Q3DStudio::CScriptEngineCallFunctionArgRetriever
+{
+public:
+ CStateScriptEngineCallFunctionArgRetriever(const char *inArguments,
+ uic::state::IScriptContext &inScriptContext)
+ : CScriptEngineCallFunctionArgRetriever(inArguments)
+ , m_ScriptContext(inScriptContext)
+ {
+ }
+ int RetrieveArgument(lua_State *inState) override
+ {
+ (void *)inState;
+ return m_ScriptContext.ExecuteStr(m_ArgumentString, true) ? 1 : -1;
+ }
+
+private:
+ uic::state::IScriptContext &m_ScriptContext;
+};
+
+void SVisualStateHandler::Handle(const uic::state::SVisualStateCommand &inCommand,
+ uic::state::IScriptContext &inScriptContext)
+{
+ using namespace uic::state;
+ switch (inCommand.getType()) {
+ case VisualStateCommandTypes::GotoSlide: {
+ const SGotoSlide &theInfo(inCommand.getData<SGotoSlide>());
+ m_Factory.m_ScriptBridge->GotoSlide(theInfo.m_Component.c_str(), theInfo.m_Slide.c_str(),
+ ToEngine(theInfo.m_GotoSlideData));
+ } break;
+ case VisualStateCommandTypes::CallFunction: {
+ const SCallFunction &theInfo(inCommand.getData<SCallFunction>());
+ // I have to suppose the Lua state in the script context of this state machine is the same
+ // as the main Lua state
+ // That means all SScriptContext should be created with the main lua state
+ CStateScriptEngineCallFunctionArgRetriever theArgRetriever(theInfo.m_Arguments,
+ inScriptContext);
+ m_Factory.m_ScriptBridge->CallFunction(theInfo.m_Behavior.c_str(),
+ theInfo.m_Handler.c_str(), theArgRetriever);
+ } break;
+ case VisualStateCommandTypes::SetAttribute: {
+ const SSetAttribute &theInfo(inCommand.getData<SSetAttribute>());
+ m_Factory.m_ScriptBridge->SetAttribute(
+ theInfo.m_Element.c_str(), theInfo.m_Attribute.c_str(), theInfo.m_Value.c_str());
+ } break;
+ case VisualStateCommandTypes::GotoSlideRelative: {
+ const SGotoSlideRelative &theInfo(inCommand.getData<SGotoSlideRelative>());
+ if (theInfo.m_Direction == SGotoSlideRelative::Error) {
+ qCCritical(INVALID_OPERATION,
+ "Goto slide relative has invalid attribute (neither 'next' nor 'previous')");
+ } else {
+ m_Factory.m_ScriptBridge->GotoSlideRelative(
+ theInfo.m_Component.c_str(), theInfo.m_Direction == SGotoSlideRelative::Next,
+ theInfo.m_Wrap, ToEngine(theInfo.m_GotoSlideData));
+ }
+ } break;
+ case VisualStateCommandTypes::FireEvent: {
+ const SFireEvent &theInfo(inCommand.getData<SFireEvent>());
+ m_Factory.m_ScriptBridge->FireEvent(theInfo.m_Element, theInfo.m_Event);
+ } break;
+ case VisualStateCommandTypes::PresentationAttribute: {
+ const SPresentationAttribute &theInfo(inCommand.getData<SPresentationAttribute>());
+ m_Factory.m_ScriptBridge->SetPresentationAttribute(theInfo.m_Presentation,
+ theInfo.m_Attribute, theInfo.m_Value);
+ } break;
+ case VisualStateCommandTypes::PlaySound: {
+ const SPlaySound &theInfo(inCommand.getData<SPlaySound>());
+ m_Factory.m_ScriptBridge->PlaySoundFile(theInfo.m_SoundFilePath);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+}
+}
+
+IUICRenderFactoryCore &
+IUICRenderFactoryCore::CreateRenderFactoryCore(const char8_t *inApplicationDirectory,
+ Q3DStudio::IWindowSystem &inWindowSystem,
+ Q3DStudio::ITimeProvider &inTimeProvider)
+{
+ SBindingCore *theCore = (SBindingCore *)malloc(sizeof(SBindingCore));
+ new (theCore) SBindingCore(inApplicationDirectory, inWindowSystem, inTimeProvider);
+ return *QT3DS_NEW(theCore->GetAllocator(), SRenderFactory)(*theCore);
+}
diff --git a/src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplRenderer.cpp b/src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplRenderer.cpp
new file mode 100644
index 00000000..232a1395
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplRenderer.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "EnginePrefix.h"
+#include "UICRenderRuntimeBindingImpl.h"
+#include "UICTegraApplication.h"
+#include "UICWindowSystem.h"
+#include "UICRenderLoadedTexture.h"
+
+using uic::render::SWindowDimensions;
+
+struct SRenderer;
+struct SRendererRSM : public Q3DStudio::ITegraRenderStateManager
+{
+ SRenderer &m_Renderer;
+
+public:
+ SRendererRSM(SRenderer &renderer)
+ : m_Renderer(renderer)
+ {
+ }
+
+ void SetViewport(Q3DStudio::INT32 inX, Q3DStudio::INT32 inY, Q3DStudio::INT32 inWidth,
+ Q3DStudio::INT32 inHeight) override;
+ void PushState() override;
+ void PopState() override;
+ void SetScissorTestEnabled(bool inValue) override;
+ void SaveAllState() override;
+ void RestoreAllState() override;
+};
+
+struct SRenderer : public Q3DStudio::ITegraApplicationRenderEngine
+{
+ NVScopedRefCounted<SBindingCore> m_BindingCore;
+ NVScopedRefCounted<IUICRenderContext> m_UICContext;
+ NVRenderRect m_Viewport;
+ nvvector<NVRenderRect> m_StateStack;
+ SWindowDimensions m_PresentationDimensions;
+ SRendererRSM m_RSM;
+ Q3DStudio::IWindowSystem &m_WindowSystem;
+
+ SRenderer(SBindingCore &inCore, Q3DStudio::IWindowSystem &inWindowSystem)
+ : m_BindingCore(inCore)
+ , m_UICContext(*inCore.m_UICContext)
+ , m_StateStack(inCore.m_UICContext->GetAllocator(), "SRenderer::m_StateStack")
+ , m_RSM(*this)
+ , m_WindowSystem(inWindowSystem)
+ {
+ m_UICContext->SetSceneColor(QT3DSVec4(0, 0, 0, 0.0f));
+ if (m_BindingCore->m_RenderContext) {
+ m_BindingCore->m_RenderContext->SetDefaultRenderTarget(
+ m_WindowSystem.GetDefaultRenderTargetID());
+ m_BindingCore->m_RenderContext->SetDefaultDepthBufferBitCount(
+ m_WindowSystem.GetDepthBitCount());
+ }
+ }
+
+ void ensureRenderTarget() override
+ {
+ m_BindingCore->m_RenderContext->SetDefaultRenderTarget(
+ m_WindowSystem.GetDefaultRenderTargetID());
+ }
+
+ void CheckResize(bool, Q3DStudio::IPresentation & /*inPresentation*/) override
+ {
+ Q3DStudio::SSize theWindowDims(m_WindowSystem.GetWindowDimensions());
+ m_BindingCore->m_WindowDimensions =
+ SWindowDimensions(theWindowDims.m_Width, theWindowDims.m_Height);
+ m_BindingCore->m_UICContext->SetWindowDimensions(m_BindingCore->m_WindowDimensions);
+ }
+ Q3DStudio::BOOL LoadShaderCache(const char * /*inFilePath*/) override { return true; }
+
+ void AbandonLoadingImages(Q3DStudio::IScene & /*inScene*/) override {}
+
+ Q3DStudio::BOOL IsPickValid(KDfloat32 &outX, KDfloat32 &outY,
+ const Q3DStudio::IPresentation & /*inPresentation*/) const override
+ {
+ KDfloat32 theX = outX;
+ KDfloat32 theY = outY;
+ theX = theX / static_cast<KDfloat32>(m_BindingCore->m_WindowDimensions.m_Width);
+ theY = theY / static_cast<KDfloat32>(m_BindingCore->m_WindowDimensions.m_Height);
+ Q3DStudio::BOOL theValid = false;
+
+ if ((theX >= 0.0f) && (theY >= 0.0f) && (theX <= 1.0f) && (theY <= 1.0f))
+ theValid = true;
+ return theValid;
+ }
+
+ void SetScaleMode(Q3DStudio::TegraRenderScaleModes::Enum inScale) override
+ {
+ if (m_BindingCore && m_BindingCore->m_UICContext)
+ m_BindingCore->m_UICContext->SetScaleMode(static_cast<ScaleModes::Enum>(inScale));
+ }
+ Q3DStudio::TegraRenderScaleModes::Enum GetScaleMode() const override
+ {
+ if (m_BindingCore && m_BindingCore->m_UICContext)
+ return static_cast<Q3DStudio::TegraRenderScaleModes::Enum>(
+ const_cast<SRenderer &>(*this).m_BindingCore->m_UICContext->GetScaleMode());
+
+ QT3DS_ASSERT(false);
+ return Q3DStudio::TegraRenderScaleModes::ExactSize;
+ }
+
+ void SetShadeMode(Q3DStudio::TegraRenderShadeModes::Enum inShade) override
+ {
+ if (m_BindingCore && m_BindingCore->m_UICContext) {
+ m_BindingCore->m_UICContext->SetWireframeMode(
+ (inShade == Q3DStudio::TegraRenderShadeModes::Shaded) ? false : true);
+ }
+ }
+
+ void EnableRenderRotation(bool inEnable) override
+ {
+ m_BindingCore->m_RenderRotationsEnabled = inEnable;
+ }
+
+ void SetWriteOutShaderCache(bool inWriteOutShaderCache) override
+ {
+ m_BindingCore->m_WriteOutShaderCache = inWriteOutShaderCache;
+ }
+
+ Q3DStudio::ITegraRenderStateManager &GetTegraRenderStateManager() override { return m_RSM; }
+ qt3ds::render::NVRenderContext &GetRenderContext() override
+ {
+ return *m_BindingCore->m_RenderContext;
+ }
+
+ void Release() override
+ {
+ // Ensure the core doesn't die until after we do.
+ NVScopedRefCounted<SBindingCore> theContext(m_BindingCore);
+ NVDelete(m_UICContext->GetAllocator(), this);
+ }
+
+ void SetViewport(Q3DStudio::INT32 inX, Q3DStudio::INT32 inY, Q3DStudio::INT32 inWidth,
+ Q3DStudio::INT32 inHeight) override
+ {
+ m_Viewport = NVRenderRect(inX, inY, inWidth, inHeight);
+ m_BindingCore->m_RenderContext->SetViewport(m_Viewport);
+ }
+ void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) override
+ {
+ m_BindingCore->m_UICContext->SetViewport(inViewport);
+ }
+
+ void SetMatteColor(Option<QT3DSVec4> inColor) override { m_UICContext->SetMatteColor(inColor); }
+ virtual void PushState() { m_StateStack.push_back(m_Viewport); }
+ virtual void PopState()
+ {
+ m_Viewport = m_StateStack.back();
+ m_StateStack.pop_back();
+ SetViewport(m_Viewport.m_X, m_Viewport.m_Y, m_Viewport.m_Width, m_Viewport.m_Height);
+ }
+
+ void RenderText2D(Q3DStudio::FLOAT x, Q3DStudio::FLOAT y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor, const char *text) override
+ {
+ m_UICContext->RenderText2D(x, y, inColor, text);
+ }
+
+ void RenderGpuProfilerStats(Q3DStudio::FLOAT x, Q3DStudio::FLOAT y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor) override
+ {
+ m_UICContext->RenderGpuProfilerStats(x, y, inColor);
+ }
+
+ bool SetWatermarkTextureDataDDS(const unsigned char *inTextureData, size_t inDataSize) override
+ {
+ bool retval = false;
+ if (inTextureData && inDataSize) {
+ SMemoryInStream theInStream(inTextureData, inTextureData + inDataSize);
+ NVFoundationBase &theFoundation(*m_BindingCore->m_Foundation);
+ uic::render::SLoadedTexture *theLoadedTexture =
+ uic::render::SLoadedTexture::LoadDDS(theInStream, true, theFoundation);
+ if (theLoadedTexture && theLoadedTexture->dds) {
+ theLoadedTexture->EnsureMultiplerOfFour(theFoundation, "AutoworksWatermark.png");
+ qt3ds::render::NVRenderContext &theContext = *m_BindingCore->m_RenderContext;
+ qt3ds::render::NVRenderTexture2D *theTexture = theContext.CreateTexture2D();
+ if (theTexture) {
+ bool supportsDXT = theContext.AreDXTImagesSupported();
+ bool isDXT =
+ NVRenderTextureFormats::isCompressedTextureFormat(theLoadedTexture->format);
+ bool requiresDecompression = (supportsDXT == false && isDXT) || false;
+ STextureData theDecompressedImage;
+ for (QT3DSU32 idx = 0, end = theLoadedTexture->dds->numMipmaps; idx < end; ++idx) {
+ if (theLoadedTexture->dds->mipwidth[idx]
+ && theLoadedTexture->dds->mipheight[idx]) {
+ if (requiresDecompression == false) {
+ theTexture->SetTextureData(
+ toU8DataRef((char *)theLoadedTexture->dds->data[idx],
+ (QT3DSU32)theLoadedTexture->dds->size[idx]),
+ (QT3DSU8)idx, (QT3DSU32)theLoadedTexture->dds->mipwidth[idx],
+ (QT3DSU32)theLoadedTexture->dds->mipheight[idx],
+ theLoadedTexture->format);
+ } else {
+ theDecompressedImage = theLoadedTexture->DecompressDXTImage(
+ idx, &theDecompressedImage);
+
+ if (theDecompressedImage.data) {
+ theTexture->SetTextureData(
+ toU8DataRef((char *)theDecompressedImage.data,
+ (QT3DSU32)theDecompressedImage.dataSizeInBytes),
+ (QT3DSU8)idx, (QT3DSU32)theLoadedTexture->dds->mipwidth[idx],
+ (QT3DSU32)theLoadedTexture->dds->mipheight[idx],
+ theDecompressedImage.format);
+ }
+ }
+ }
+ }
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ if (theLoadedTexture->dds->numMipmaps > 1)
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
+ else
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+
+ theLoadedTexture->ReleaseDecompressedTexture(theDecompressedImage);
+ m_BindingCore->m_UICContext->SetWatermark(*theTexture);
+ retval = true;
+ }
+ theLoadedTexture->release();
+ }
+ }
+ return retval;
+ }
+
+ void SetWatermarkLocation(float x, float y) override
+ {
+ m_BindingCore->m_UICContext->SetWatermarkLocation(QT3DSVec2(x, y));
+ }
+};
+
+void SRendererRSM::SetViewport(Q3DStudio::INT32 inX, Q3DStudio::INT32 inY, Q3DStudio::INT32 inWidth,
+ Q3DStudio::INT32 inHeight)
+{
+ m_Renderer.SetViewport(inX, inY, inWidth, inHeight);
+}
+void SRendererRSM::PushState()
+{
+ m_Renderer.PushState();
+}
+void SRendererRSM::PopState()
+{
+ m_Renderer.PopState();
+}
+void SRendererRSM::SetScissorTestEnabled(bool inValue)
+{
+ m_Renderer.m_BindingCore->m_RenderContext->SetScissorTestEnabled(inValue);
+}
+void SRendererRSM::SaveAllState()
+{
+ m_Renderer.m_BindingCore->m_RenderContext->PushPropertySet();
+}
+void SRendererRSM::RestoreAllState()
+{
+ m_Renderer.m_BindingCore->m_RenderContext->PopPropertySet(true);
+}
+
+Q3DStudio::ITegraApplicationRenderEngine &SBindingCore::CreateRenderer()
+{
+ SRenderer *retval = NULL;
+ if (m_UICContext)
+ retval = QT3DS_NEW(m_UICContext->GetAllocator(), SRenderer)(*this, this->m_WindowSystem);
+
+ return *retval;
+}
diff --git a/src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplTranslation.cpp b/src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplTranslation.cpp
new file mode 100644
index 00000000..b9e0dbe3
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/UICRenderRuntimeBindingImplTranslation.cpp
@@ -0,0 +1,1792 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "EnginePrefix.h"
+#include "UICRenderRuntimeBindingImpl.h"
+#include "UICRenderUIPSharedTranslation.h"
+#include "UICRenderBufferManager.h"
+#include "foundation/SerializationTypes.h"
+#include "UICRenderString.h"
+#include "foundation/FileTools.h"
+#include "UICHash.h"
+#include "UICRenderPlugin.h"
+#include "UICRenderPluginPropertyValue.h"
+#include "UICLuaElementHelper.h"
+#include "UICPresentation.h"
+#include "UICApplication.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderPath.h"
+#include "UICRenderPathSubPath.h"
+#include "UICRenderPathManager.h"
+
+namespace Q3DStudio {
+enum ExtendedAttributes {
+ ATTRIBUTE_NONE = 0,
+ ATTRIBUTE_NONE_R,
+ ATTRIBUTE_NONE_G,
+ ATTRIBUTE_NONE_B
+};
+}
+
+namespace {
+QT3DSU32 g_TranslatorTag;
+QT3DSU32 g_PresentationTag;
+}
+
+// Add specializations for the tagged pointer operations to make casting
+// a bit safer and more transparent.
+namespace uic {
+namespace render {
+ template <>
+ struct SPointerTag<CUICTranslator>
+ {
+ static QT3DSU32 GetTag() { return g_TranslatorTag; }
+ };
+ template <>
+ struct SPointerTag<Q3DStudio::IPresentation>
+ {
+ static QT3DSU32 GetTag() { return g_PresentationTag; }
+ };
+}
+}
+
+namespace {
+
+template <UICRenderDirtyFlags::Enum TDirtyType>
+struct SDirtySetter
+{
+};
+
+template <>
+struct SDirtySetter<UICRenderDirtyFlags::Dirty>
+{
+ static void Set(bool &dirty, bool & /*transformDirty*/, bool & /*textDirty*/) { dirty = true; }
+};
+template <>
+struct SDirtySetter<UICRenderDirtyFlags::TransformDirty>
+{
+ static void Set(bool &dirty, bool &transformDirty, bool & /*textDirty*/)
+ {
+ dirty = true;
+ transformDirty = true;
+ }
+};
+template <>
+struct SDirtySetter<UICRenderDirtyFlags::TextDirty>
+{
+ static void Set(bool &dirty, bool & /*transformDirty*/, bool &textDirty)
+ {
+ dirty = true;
+ textDirty = true;
+ }
+};
+template <>
+struct SDirtySetter<UICRenderDirtyFlags::Unknown>
+{
+ static void Set(bool & /*dirty*/, bool & /*transformDirty*/, bool & /*textDirty*/) {}
+};
+
+// Translates individual property values from the runtime into the rendering system.
+struct SRuntimePropertyParser
+{
+ QT3DSI32 m_PropertyName;
+ Q3DStudio::UVariant m_Value;
+ Q3DStudio::EAttributeType m_Type;
+ Q3DStudio::TElement &m_Element;
+ SPresentation &m_Presentation;
+ IUICRenderContext &m_RenderContext;
+ bool m_Dirty;
+ bool m_TransformDirty;
+ bool m_TextDirty;
+
+ SRuntimePropertyParser(SPresentation &inPresentation, IUICRenderContext &inRenderContext,
+ Q3DStudio::TElement &inElement)
+ : m_PropertyName(0)
+ , m_Type((Q3DStudio::EAttributeType)0)
+ , m_Element(inElement)
+ , m_Presentation(inPresentation)
+ , m_RenderContext(inRenderContext)
+ , m_Dirty(false)
+ , m_TransformDirty(false)
+ , m_TextDirty(false)
+ {
+ }
+
+ void Setup(QT3DSI32 inPropName, Q3DStudio::UVariant inValue, Q3DStudio::EAttributeType inType)
+ {
+ m_PropertyName = inPropName;
+ m_Value = inValue;
+ m_Type = inType;
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ void SetDirty()
+ {
+ SDirtySetter<TDirtyType>::Set(m_Dirty, m_TransformDirty, m_TextDirty);
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(QT3DSF32 &outValue)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT) {
+ QT3DSF32 newValue = m_Value.m_FLOAT;
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ };
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(QT3DSU32 &outValue)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_INT32) {
+ QT3DSU32 newValue = (QT3DSU32)m_Value.m_INT32;
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ };
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(SGraphObject *&outValue)
+ {
+ Q3DStudio::TElement *theElem = NULL;
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_ELEMENTREF) {
+ theElem = m_Element.GetBelongedPresentation()->GetApplication().GetElementByHandle(
+ m_Value.m_ElementHandle);
+ } else if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) {
+ CRegisteredString theString =
+ m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle);
+ theElem = Q3DStudio::CLuaElementHelper::GetElement(
+ m_Element.GetBelongedPresentation()->GetApplication(),
+ m_Element.GetBelongedPresentation(), theString.c_str(), &m_Element);
+ }
+
+ SGraphObject *newValue = NULL;
+ if (theElem) {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(theElem->GetAssociation());
+ if (theTranslator)
+ newValue = theTranslator->m_RenderObject;
+ }
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ };
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseRadianProperty(QT3DSF32 &outValue)
+ {
+ if (ParseProperty<TDirtyType>(outValue)) {
+ TORAD(outValue);
+ return true;
+ }
+ return false;
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseOpacityProperty(QT3DSF32 &outValue)
+ {
+ if (ParseProperty<TDirtyType>(outValue)) {
+ outValue *= 1.0f / 100.0f;
+ return true;
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseOrientationProperty(bool &ioCurrent)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) {
+ CRegisteredString strValue =
+ m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle);
+ bool newValue = AreEqual(strValue.c_str(), "Left Handed") ? true : false;
+ if (ioCurrent != newValue) {
+ ioCurrent = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(bool &ioCurrent)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_BOOL || m_Type == Q3DStudio::ATTRIBUTETYPE_INT32) {
+ bool newValue = m_Value.m_INT32 ? true : false;
+ if (ioCurrent != newValue) {
+ ioCurrent = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseInverseBoolean(bool &ioCurrent)
+ {
+ bool temp = !ioCurrent;
+ if (ParseProperty<TDirtyType>(temp)) {
+ ioCurrent = temp;
+ return true;
+ }
+ return false;
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(QT3DSVec3 &outValue)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT3) {
+ QT3DSVec3 newValue(m_Value.m_FLOAT3[0], m_Value.m_FLOAT3[1], m_Value.m_FLOAT3[2]);
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(CRegisteredString &outValue)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) {
+ CRegisteredString newValue =
+ m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle);
+ if (newValue.c_str() != outValue.c_str()) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseRotationOrder(QT3DSU32 &outValue)
+ {
+ CRegisteredString theString;
+ ParseProperty<UICRenderDirtyFlags::Unknown>(theString);
+ if (theString.IsValid()) {
+ QT3DSU32 newRotationOrder = MapRotationOrder(theString);
+ if (newRotationOrder != outValue) {
+ outValue = newRotationOrder;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseOrientation(NodeFlags &outValue)
+ {
+ bool temp = false;
+ ParseOrientationProperty<TDirtyType>(temp);
+ bool wasLeftHanded = outValue.IsLeftHanded();
+ if (wasLeftHanded != temp) {
+ outValue.SetLeftHanded(temp);
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseNodeFlagsProperty(NodeFlags &outValue, NodeFlagValues::Enum inFlag)
+ {
+ bool temp = false;
+ ParseProperty<UICRenderDirtyFlags::Unknown>(temp);
+ bool wasSet = outValue & inFlag;
+ if (temp != wasSet) {
+ outValue.ClearOrSet(temp, inFlag);
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseNodeFlagsInverseProperty(NodeFlags &outValue, NodeFlagValues::Enum inFlag)
+ {
+ bool temp = false;
+ ParseProperty<UICRenderDirtyFlags::Unknown>(temp);
+ temp = !temp;
+ bool wasSet = outValue & inFlag;
+ if (temp != wasSet) {
+ outValue.ClearOrSet(temp, inFlag);
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType, typename TEnumType>
+ bool ParseEnumProperty(TEnumType &outValue)
+ {
+ CRegisteredString theString;
+ ParseProperty<UICRenderDirtyFlags::Unknown>(theString);
+ if (theString.IsValid()) {
+ SEnumNameMap *theMap = SEnumParseMap<TEnumType>::GetMap();
+ for (SEnumNameMap *theItem = theMap; theItem->m_Name && *theItem->m_Name; ++theItem) {
+ if (strcmp(theString, theItem->m_Name) == 0) {
+ TEnumType theNewValue = static_cast<TEnumType>(theItem->m_Enum);
+ if (outValue != theNewValue) {
+ outValue = theNewValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseAndResolveSourcePath(CRegisteredString &outValue)
+ {
+ CRegisteredString theTemp;
+ ParseProperty<UICRenderDirtyFlags::Unknown>(theTemp);
+ CRegisteredString theNewStr = theTemp;
+ if (outValue.c_str() != theNewStr.c_str()) {
+ SetDirty<TDirtyType>();
+ outValue = theNewStr;
+ return true;
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(SImage *&ioImagePtr)
+ {
+ Q3DStudio::TElement *theElem =
+ m_Element.GetBelongedPresentation()->GetApplication().GetElementByHandle(
+ m_Value.m_ElementHandle);
+ // Try to be very careful in here as casting things around like crazy is a sure
+ // way to crash the runtime at a bad point.
+ if (theElem != NULL) {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(theElem->GetAssociation());
+ if (theTranslator != NULL && theTranslator->GetUIPType() == GraphObjectTypes::Image) {
+ SImage *theImage = static_cast<SImage *>(theTranslator->m_RenderObject);
+ if (ioImagePtr != theImage) {
+ ioImagePtr = theImage;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ template <UICRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(SNode *&ioNodePtr)
+ {
+ Q3DStudio::TElement *theElem =
+ m_Element.GetBelongedPresentation()->GetApplication().GetElementByHandle(
+ m_Value.m_ElementHandle);
+ // Try to be very careful in here as casting things around like crazy is a sure
+ // way to crash the runtime at a bad point.
+ SNode *theNode = NULL;
+ if (theElem != NULL
+ && theElem->GetBelongedPresentation() == m_Element.GetBelongedPresentation()) {
+ CUICTranslator *theTranslator =
+ reinterpret_cast<CUICTranslator *>(theElem->GetAssociation());
+ if (theTranslator != NULL
+ && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ theNode = static_cast<SNode *>(theTranslator->m_RenderObject);
+ }
+ }
+ if (ioNodePtr != theNode) {
+ ioNodePtr = theNode;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+};
+
+// Fill out parse name table.
+#define Scene_ClearColor_R ATTRIBUTE_BACKGROUNDCOLOR_R
+#define Scene_ClearColor_G ATTRIBUTE_BACKGROUNDCOLOR_G
+#define Scene_ClearColor_B ATTRIBUTE_BACKGROUNDCOLOR_B
+#define Scene_UseClearColor ATTRIBUTE_BGCOLORENABLE
+#define Node_Rotation ATTRIBUTE_ROTATION
+#define Node_Rotation_X ATTRIBUTE_ROTATION_X
+#define Node_Rotation_Y ATTRIBUTE_ROTATION_Y
+#define Node_Rotation_Z ATTRIBUTE_ROTATION_Z
+#define Node_Position ATTRIBUTE_POSITION
+#define Node_Position_X ATTRIBUTE_POSITION_X
+#define Node_Position_Y ATTRIBUTE_POSITION_Y
+#define Node_Position_Z ATTRIBUTE_POSITION_Z
+#define Node_Scale ATTRIBUTE_SCALE
+#define Node_Scale_X ATTRIBUTE_SCALE_X
+#define Node_Scale_Y ATTRIBUTE_SCALE_Y
+#define Node_Scale_Z ATTRIBUTE_SCALE_Z
+#define Node_Pivot ATTRIBUTE_PIVOT
+#define Node_Pivot_X ATTRIBUTE_PIVOT_X
+#define Node_Pivot_Y ATTRIBUTE_PIVOT_Y
+#define Node_Pivot_Z ATTRIBUTE_PIVOT_Z
+#define Node_LocalOpacity ATTRIBUTE_OPACITY
+#define Node_RotationOrder ATTRIBUTE_ROTATIONORDER
+#define Node_LeftHanded ATTRIBUTE_ORIENTATION
+#define Layer_TemporalAAEnabled ATTRIBUTE_TEMPORALAA
+#define Layer_LayerEnableDepthTest ATTRIBUTE_DISABLEDEPTHTEST
+#define Layer_LayerEnableDepthPrePass ATTRIBUTE_DISABLEDEPTHPREPASS
+#define Layer_ClearColor_R ATTRIBUTE_BACKGROUNDCOLOR_R
+#define Layer_ClearColor_G ATTRIBUTE_BACKGROUNDCOLOR_G
+#define Layer_ClearColor_B ATTRIBUTE_BACKGROUNDCOLOR_B
+#define Layer_Background ATTRIBUTE_BACKGROUND
+#define Layer_BlendType ATTRIBUTE_BLENDTYPE
+#define Layer_ProgressiveAAMode ATTRIBUTE_PROGRESSIVEAA
+#define Layer_MultisampleAAMode ATTRIBUTE_MULTISAMPLEAA
+#define Layer_HorizontalFieldValues ATTRIBUTE_HORZFIELDS
+#define Layer_Left ATTRIBUTE_LEFT
+#define Layer_LeftUnits ATTRIBUTE_LEFTUNITS
+#define Layer_Width ATTRIBUTE_WIDTH
+#define Layer_WidthUnits ATTRIBUTE_WIDTHUNITS
+#define Layer_Right ATTRIBUTE_RIGHT
+#define Layer_RightUnits ATTRIBUTE_RIGHTUNITS
+#define Layer_VerticalFieldValues ATTRIBUTE_VERTFIELDS
+#define Layer_Top ATTRIBUTE_TOP
+#define Layer_TopUnits ATTRIBUTE_TOPUNITS
+#define Layer_Height ATTRIBUTE_HEIGHT
+#define Layer_HeightUnits ATTRIBUTE_HEIGHTUNITS
+#define Layer_Bottom ATTRIBUTE_BOTTOM
+#define Layer_BottomUnits ATTRIBUTE_BOTTOMUNITS
+#define Layer_AoStrength ATTRIBUTE_AOSTRENGTH
+#define Layer_AoDistance ATTRIBUTE_AODISTANCE
+#define Layer_AoSoftness ATTRIBUTE_AOSOFTNESS
+#define Layer_AoBias ATTRIBUTE_AOBIAS
+#define Layer_AoSamplerate ATTRIBUTE_AOSAMPLERATE
+#define Layer_AoDither ATTRIBUTE_AODITHER
+#define Layer_ShadowStrength ATTRIBUTE_SHADOWSTRENGTH
+#define Layer_ShadowDist ATTRIBUTE_SHADOWDIST
+#define Layer_ShadowSoftness ATTRIBUTE_SHADOWSOFTNESS
+#define Layer_ShadowBias ATTRIBUTE_SHADOWBIAS
+#define Layer_LightProbe ATTRIBUTE_LIGHTPROBE
+#define Layer_ProbeBright ATTRIBUTE_PROBEBRIGHT
+#define Layer_FastIbl ATTRIBUTE_FASTIBL
+#define Layer_ProbeTheta ATTRIBUTE_PROBETHETA
+#define Layer_ProbePhi ATTRIBUTE_PROBEPHI
+#define Layer_ProbeHorizon ATTRIBUTE_PROBEHORIZON
+#define Layer_LightProbe2 ATTRIBUTE_LIGHTPROBE2
+#define Layer_Probe2Fade ATTRIBUTE_PROBE2FADE
+#define Layer_Probe2Window ATTRIBUTE_PROBE2WINDOW
+#define Layer_Probe2Pos ATTRIBUTE_PROBE2POS
+#define Layer_ProbeFov ATTRIBUTE_PROBEFOV
+#define Layer_TexturePath ATTRIBUTE_SOURCEPATH
+#define Camera_ClipNear ATTRIBUTE_CLIPNEAR
+#define Camera_ClipFar ATTRIBUTE_CLIPFAR
+#define Camera_FOV ATTRIBUTE_FOV
+#define Camera_Orthographic ATTRIBUTE_ORTHOGRAPHIC
+#define Camera_ScaleMode ATTRIBUTE_SCALEMODE
+#define Camera_ScaleAnchor ATTRIBUTE_SCALEANCHOR
+#define Light_ImageSource ATTRIBUTE_IMAGESOURCE
+#define Light_Scope ATTRIBUTE_SCOPE
+#define Light_ImageSetsColor ATTRIBUTE_IMAGESETSCOLOR
+#define Light_ImageSetsRotation ATTRIBUTE_IMAGESETSROTATION
+#define Light_ImageHFov ATTRIBUTE_IMAGEHFOV
+#define Light_ImageIsFisheye ATTRIBUTE_IMAGEISFISHEYE
+#define Light_LightType ATTRIBUTE_LIGHTTYPE
+#define Light_DiffuseColor ATTRIBUTE_LIGHTDIFFUSE
+#define Light_DiffuseColor_R ATTRIBUTE_LIGHTDIFFUSE_R
+#define Light_DiffuseColor_G ATTRIBUTE_LIGHTDIFFUSE_G
+#define Light_DiffuseColor_B ATTRIBUTE_LIGHTDIFFUSE_B
+#define Light_SpecularColor ATTRIBUTE_LIGHTSPECULAR
+#define Light_SpecularColor_R ATTRIBUTE_LIGHTSPECULAR_R
+#define Light_SpecularColor_G ATTRIBUTE_LIGHTSPECULAR_G
+#define Light_SpecularColor_B ATTRIBUTE_LIGHTSPECULAR_B
+#define Light_AmbientColor ATTRIBUTE_LIGHTAMBIENT
+#define Light_AmbientColor_R ATTRIBUTE_LIGHTAMBIENT_R
+#define Light_AmbientColor_G ATTRIBUTE_LIGHTAMBIENT_G
+#define Light_AmbientColor_B ATTRIBUTE_LIGHTAMBIENT_B
+#define Light_Brightness ATTRIBUTE_BRIGHTNESS
+#define Light_LinearFade ATTRIBUTE_LINEARFADE
+#define Light_ExponentialFade ATTRIBUTE_EXPFADE
+#define Light_AreaWidth ATTRIBUTE_AREAWIDTH
+#define Light_AreaHeight ATTRIBUTE_AREAHEIGHT
+#define Light_CastShadow ATTRIBUTE_CASTSHADOW
+#define Light_ShadowBias ATTRIBUTE_SHDWBIAS
+#define Light_ShadowFactor ATTRIBUTE_SHDWFACTOR
+#define Light_ShadowMapRes ATTRIBUTE_SHDWMAPRES
+#define Light_ShadowMapFar ATTRIBUTE_SHDWMAPFAR
+#define Light_ShadowFilter ATTRIBUTE_SHDWFILTER
+#define Model_MeshPath ATTRIBUTE_SOURCEPATH
+#define Model_TessellationMode ATTRIBUTE_TESSELLATION
+#define Model_EdgeTess ATTRIBUTE_EDGETESS
+#define Model_InnerTess ATTRIBUTE_INNERTESS
+#define Lightmaps_LightmapIndirect ATTRIBUTE_LIGHTMAPINDIRECT
+#define Lightmaps_LightmapRadiosity ATTRIBUTE_LIGHTMAPRADIOSITY
+#define Lightmaps_LightmapShadow ATTRIBUTE_LIGHTMAPSHADOW
+#define Material_Lighting ATTRIBUTE_SHADERLIGHTING
+#define Material_BlendMode ATTRIBUTE_BLENDMODE
+#define MaterialBase_IblProbe ATTRIBUTE_IBLPROBE
+#define Material_DiffuseColor ATTRIBUTE_DIFFUSE
+#define Material_DiffuseColor_R ATTRIBUTE_DIFFUSE_R
+#define Material_DiffuseColor_G ATTRIBUTE_DIFFUSE_G
+#define Material_DiffuseColor_B ATTRIBUTE_DIFFUSE_B
+#define Material_DiffuseMaps_0 ATTRIBUTE_DIFFUSEMAP
+#define Material_DiffuseMaps_1 ATTRIBUTE_DIFFUSEMAP2
+#define Material_DiffuseMaps_2 ATTRIBUTE_DIFFUSEMAP3
+#define Material_EmissivePower ATTRIBUTE_EMISSIVEPOWER
+#define Material_EmissiveColor ATTRIBUTE_EMISSIVECOLOR
+#define Material_EmissiveColor_R ATTRIBUTE_EMISSIVECOLOR_R
+#define Material_EmissiveColor_G ATTRIBUTE_EMISSIVECOLOR_G
+#define Material_EmissiveColor_B ATTRIBUTE_EMISSIVECOLOR_B
+#define Material_EmissiveMap ATTRIBUTE_EMISSIVEMAP
+#define Material_EmissiveMap2 ATTRIBUTE_EMISSIVEMAP2
+#define Material_SpecularReflection ATTRIBUTE_SPECULARREFLECTION
+#define Material_SpecularMap ATTRIBUTE_SPECULARMAP
+#define Material_SpecularModel ATTRIBUTE_SPECULARMODEL
+#define Material_SpecularTint ATTRIBUTE_SPECULARTINT
+#define Material_SpecularTint_R ATTRIBUTE_SPECULARTINT_R
+#define Material_SpecularTint_G ATTRIBUTE_SPECULARTINT_G
+#define Material_SpecularTint_B ATTRIBUTE_SPECULARTINT_B
+#define Material_IOR ATTRIBUTE_IOR
+#define Material_FresnelPower ATTRIBUTE_FRESNELPOWER
+#define Material_SpecularAmount ATTRIBUTE_SPECULARAMOUNT
+#define Material_SpecularRoughness ATTRIBUTE_SPECULARROUGHNESS
+#define Material_Opacity ATTRIBUTE_OPACITY
+#define Material_OpacityMap ATTRIBUTE_OPACITYMAP
+#define Material_BumpAmount ATTRIBUTE_BUMPAMOUNT
+#define Material_BumpMap ATTRIBUTE_BUMPMAP
+#define Material_NormalMap ATTRIBUTE_NORMALMAP
+#define Material_DisplaceAmount ATTRIBUTE_DISPLACEAMOUNT
+#define Material_DisplacementMap ATTRIBUTE_DISPLACEMENTMAP
+#define Material_TranslucentFalloff ATTRIBUTE_TRANSLUCENTFALLOFF
+#define Material_TranslucencyMap ATTRIBUTE_TRANSLUCENCYMAP
+#define Material_DiffuseLightWrap ATTRIBUTE_DIFFUSELIGHTWRAP
+#define Material_ReferencedMaterial ATTRIBUTE_REFERENCEDMATERIAL
+#define Image_ImagePath ATTRIBUTE_SOURCEPATH
+#define Image_OffscreenRendererId ATTRIBUTE_SUBPRESENTATION
+#define Image_Scale_X ATTRIBUTE_SCALEU
+#define Image_Scale_Y ATTRIBUTE_SCALEV
+#define Image_Pivot_X ATTRIBUTE_PIVOTU
+#define Image_Pivot_Y ATTRIBUTE_PIVOTV
+#define Image_Rotation ATTRIBUTE_ROTATIONUV
+#define Image_Position_X ATTRIBUTE_POSITIONU
+#define Image_Position_Y ATTRIBUTE_POSITIONV
+#define Image_MappingMode ATTRIBUTE_MAPPINGMODE
+#define Image_HorizontalTilingMode ATTRIBUTE_TILINGMODEHORZ
+#define Image_VerticalTilingMode ATTRIBUTE_TILINGMODEVERT
+#define Text_Text ATTRIBUTE_TEXTSTRING
+#define Text_Font ATTRIBUTE_FONT
+#define Text_FontSize ATTRIBUTE_SIZE
+#define Text_HorizontalAlignment ATTRIBUTE_HORZALIGN
+#define Text_VerticalAlignment ATTRIBUTE_VERTALIGN
+#define Text_Leading ATTRIBUTE_LEADING
+#define Text_Tracking ATTRIBUTE_TRACKING
+#define Text_TextColor ATTRIBUTE_TEXTCOLOR
+#define Text_TextColor_R ATTRIBUTE_TEXTCOLOR_R
+#define Text_TextColor_G ATTRIBUTE_TEXTCOLOR_G
+#define Text_TextColor_B ATTRIBUTE_TEXTCOLOR_B
+#define Text_BackColor_R ATTRIBUTE_BACKCOLOR_R
+#define Text_BackColor_G ATTRIBUTE_BACKCOLOR_G
+#define Text_BackColor_B ATTRIBUTE_BACKCOLOR_B
+#define Text_UseBackColor ATTRIBUTE_USEBACKCOLOR
+#define Text_EnableAcceleratedFont ATTRIBUTE_ENABLEACCELERATEDFONT
+#define Path_PathType ATTRIBUTE_PATHTYPE
+#define Path_Width ATTRIBUTE_WIDTH
+#define Path_LinearError ATTRIBUTE_LINEARERROR
+#define Path_EdgeTessAmount ATTRIBUTE_EDGETESSAMOUNT
+#define Path_InnerTessAmount ATTRIBUTE_INNERTESSAMOUNT
+#define Path_BeginCapping ATTRIBUTE_BEGINCAP
+#define Path_BeginCapOffset ATTRIBUTE_BEGINCAPOFFSET
+#define Path_BeginCapOpacity ATTRIBUTE_BEGINCAPOPACITY
+#define Path_BeginCapWidth ATTRIBUTE_BEGINCAPWIDTH
+#define Path_EndCapping ATTRIBUTE_ENDCAP
+#define Path_EndCapOffset ATTRIBUTE_ENDCAPOFFSET
+#define Path_EndCapOpacity ATTRIBUTE_ENDCAPOPACITY
+#define Path_EndCapWidth ATTRIBUTE_ENDCAPWIDTH
+#define Path_PaintStyle ATTRIBUTE_PAINTSTYLE
+#define Path_PathBuffer ATTRIBUTE_SOURCEPATH
+#define SubPath_Closed ATTRIBUTE_CLOSED
+
+// Fill in implementations for the actual parse tables.
+#define HANDLE_UIC_RENDER_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_RENDER_VEC3_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break; \
+ case Q3DStudio::type##_##name##_Z: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.z); \
+ break;
+
+#define HANDLE_UIC_RENDER_REAL_VEC2_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break;
+
+#define HANDLE_UIC_RENDER_COLOR_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_R: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_G: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break; \
+ case Q3DStudio::type##_##name##_B: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.z); \
+ break;
+
+#define HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_RENDER_RADIAN_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseRadianProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+// The runtime converts rotations for us.
+#define HANDLE_UIC_RENDER_VEC3_RADIAN_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break; \
+ case Q3DStudio::type##_##name##_Z: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.z); \
+ break;
+
+#define HANDLE_UIC_RENDER_OPACITY_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseOpacityProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_ROTATION_ORDER_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseRotationOrder<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_NODE_ORIENTATION_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseOrientation<UICRenderDirtyFlags::dirty>(theItem.m_Flags); \
+ break;
+
+#define HANDLE_UIC_RENDER_DEPTH_TEST_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseInverseBoolean<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_NODE_FLAGS_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseNodeFlagsProperty<UICRenderDirtyFlags::dirty>(theItem.m_Flags, \
+ NodeFlagValues::name); \
+ break;
+
+#define HANDLE_UIC_NODE_FLAGS_INVERSE_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseNodeFlagsInverseProperty<UICRenderDirtyFlags::dirty>(theItem.m_Flags, \
+ NodeFlagValues::name); \
+ break;
+
+#define HANDLE_UIC_RENDER_ENUM_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseEnumProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseAndResolveSourcePath<UICRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_UIC_RENDER_ARRAY_PROPERTY(type, name, index, dirty) \
+ case Q3DStudio::type##_##name##_##index: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name[index]); \
+ break;
+
+#define HANDLE_UIC_RENDER_VEC2_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<UICRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break;
+
+const float g_DegToRad = float(M_PI / 180.0);
+
+struct SSceneTranslator : public CUICTranslator
+{
+ typedef SScene TNodeType;
+ SSceneTranslator(Q3DStudio::TElement &inElement, SScene &inRenderObject)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ }
+ // Ignored, scenes are always active
+ void SetActive(bool /*inElementActive*/) {}
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SScene &theItem = *static_cast<SScene *>(m_RenderObject);
+
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_SCENE_PROPERTIES
+ // These are ignored by the renderer
+ case Q3DStudio::ATTRIBUTE_NAME:
+ case Q3DStudio::ATTRIBUTE_STARTTIME:
+ case Q3DStudio::ATTRIBUTE_ENDTIME:
+ case Q3DStudio::ATTRIBUTE_IMPORTID:
+ case Q3DStudio::ATTRIBUTE_EYEBALL:
+ break;
+ default:
+ // Unknown attribute
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+ void PostPropertyChanged(const SRuntimePropertyParser &, Q3DStudio::IPresentation &) {}
+};
+
+struct SNodeTranslator : public CUICTranslator
+{
+ typedef SNode TNodeType;
+ SNodeTranslator(Q3DStudio::TElement &inElement, SNode &inRenderObject)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ SNode &theItem = *static_cast<SNode *>(m_RenderObject);
+ theItem.m_Flags.SetLocallyPickable(false);
+ }
+ void SetActive(bool inElementActive)
+ {
+ SNode &theItem = *static_cast<SNode *>(m_RenderObject);
+ if (theItem.m_Flags.IsActive() != inElementActive) {
+ theItem.m_Flags.SetActive(inElementActive);
+ theItem.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ }
+ }
+
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SNode &theItem = *static_cast<SNode *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_NODE_PROPERTIES
+ case Q3DStudio::ATTRIBUTE_NAME:
+ case Q3DStudio::ATTRIBUTE_STARTTIME:
+ case Q3DStudio::ATTRIBUTE_ENDTIME:
+ case Q3DStudio::ATTRIBUTE_IMPORTID:
+ case Q3DStudio::ATTRIBUTE_EYEBALL:
+ // Groups have a source path property on them that we like to ignore.
+ case Q3DStudio::ATTRIBUTE_SOURCEPATH:
+ break;
+ default:
+ // Unknown attribute
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+ void PostPropertyChanged(const SRuntimePropertyParser &inParser,
+ Q3DStudio::IPresentation & /*inStudioPresentation*/)
+ {
+ SNode &theItem = *static_cast<SNode *>(m_RenderObject);
+ if (inParser.m_TransformDirty)
+ theItem.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ else if (inParser.m_Dirty)
+ theItem.MarkDirty(NodeTransformDirtyFlag::TransformNotDirty);
+ if (inParser.m_TextDirty)
+ theItem.m_Flags.SetTextDirty(true);
+ SetActive(Element().GetActive());
+ bool isNodePickable = m_Element->IsPickEnabled();
+ if (theItem.m_Flags.IsLocallyPickable() != isNodePickable) {
+ theItem.m_Flags.SetLocallyPickable(isNodePickable);
+ theItem.MarkDirty(NodeTransformDirtyFlag::TransformNotDirty);
+ }
+ }
+};
+
+struct SLayerTranslator : public SNodeTranslator
+{
+ typedef SLayer TNodeType;
+ SLayerTranslator(Q3DStudio::TElement &inElement, SLayer &inRenderObject)
+ : SNodeTranslator(inElement, inRenderObject)
+ {
+ }
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ const char *propName =
+ Q3DStudio::GetAttributeString((Q3DStudio::EAttribute)inParser.m_PropertyName);
+ (void)propName;
+ SLayer &theItem = *static_cast<SLayer *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_LAYER_PROPERTIES
+ // Ignored
+ default:
+ SNodeTranslator::OnSpecificPropertyChange(inParser);
+ }
+ }
+};
+
+struct SLightTranslator : public SNodeTranslator
+{
+ typedef SLight TNodeType;
+ SLightTranslator(Q3DStudio::TElement &inElement, SLight &inRenderObject)
+ : SNodeTranslator(inElement, inRenderObject)
+ {
+ }
+
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SLight &theItem = *static_cast<SLight *>(m_RenderObject);
+ // I guess there is no switching of light type in the runtime right now.
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_LIGHT_PROPERTIES
+ default:
+ SNodeTranslator::OnSpecificPropertyChange(inParser);
+ break;
+ }
+ }
+};
+struct SCameraTranslator : public SNodeTranslator
+{
+ typedef SCamera TNodeType;
+ SCameraTranslator(Q3DStudio::TElement &inElement, SCamera &inRenderObject)
+ : SNodeTranslator(inElement, inRenderObject)
+ {
+ }
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SCamera &theItem = *static_cast<SCamera *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_CAMERA_PROPERTIES
+ default:
+ SNodeTranslator::OnSpecificPropertyChange(inParser);
+ break;
+ }
+ }
+};
+
+struct SModelTranslator : public SNodeTranslator
+{
+ typedef SModel TNodeType;
+ SModelTranslator(Q3DStudio::TElement &inElement, SModel &inRenderObject)
+ : SNodeTranslator(inElement, inRenderObject)
+ {
+ }
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SModel &theItem = *static_cast<SModel *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_MODEL_PROPERTIES
+ default:
+ SNodeTranslator::OnSpecificPropertyChange(inParser);
+ break;
+ }
+ }
+};
+
+struct SPathTranslator : public SNodeTranslator
+{
+ typedef SPath TNodeType;
+ SPathTranslator(Q3DStudio::TElement &inElement, SPath &inRenderObject)
+ : SNodeTranslator(inElement, inRenderObject)
+ {
+ }
+
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SPath &theItem = *static_cast<SPath *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_PATH_PROPERTIES
+ default:
+ SNodeTranslator::OnSpecificPropertyChange(inParser);
+ break;
+ }
+ }
+};
+
+struct SPathSubPathTranslator : public CUICTranslator
+{
+
+ typedef SPathSubPath TNodeType;
+
+ SPathSubPathTranslator(Q3DStudio::TElement &inElement, SPathSubPath &inRenderObject)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ }
+
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SPathSubPath &theItem = *static_cast<SPathSubPath *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_PATH_SUBPATH_PROPERTIES
+ default:
+ break;
+ }
+ }
+
+ void PostPropertyChanged(const SRuntimePropertyParser &inParser,
+ Q3DStudio::IPresentation & /*inStudioPresentation*/)
+ {
+ SPathSubPath &theItem = *static_cast<SPathSubPath *>(m_RenderObject);
+ uic::render::IPathManager &theManager = inParser.m_RenderContext.GetPathManager();
+ QT3DSU32 numAnchors = 0;
+ bool updatePath = false;
+ CRegisteredString theAnchorType =
+ inParser.m_RenderContext.GetStringTable().RegisterStr("PathAnchorPoint");
+ for (Q3DStudio::TElement *theChild = Element().GetChild(); theChild;
+ theChild = theChild->GetSibling()) {
+ if (theChild->GetType() == theAnchorType) {
+ ++numAnchors;
+ if (theChild->IsDirty())
+ updatePath = true;
+ }
+ }
+ if (updatePath) {
+ NVDataRef<uic::render::SPathAnchorPoint> thePathBuffer =
+ theManager.ResizePathSubPathBuffer(theItem, numAnchors);
+ if (thePathBuffer.size()) {
+ QT3DSU32 anchorIndex = 0;
+ for (Q3DStudio::TElement *theChild = Element().GetChild(); theChild;
+ theChild = theChild->GetSibling()) {
+ if (theChild->GetType() == theAnchorType) {
+ if (theChild->IsDirty()) {
+ uic::render::SPathAnchorPoint &thePoint(thePathBuffer[anchorIndex]);
+
+ for (QT3DSI32 idx = 0, end = theChild->GetAttributeCount(); idx < end;
+ ++idx) {
+ uic::runtime::element::TPropertyDescAndValuePtr thePropInfo =
+ theChild->GetPropertyByIndex(idx);
+ switch (thePropInfo.first.GetNameHash()) {
+ case Q3DStudio::ATTRIBUTE_POSITION_X:
+ thePoint.m_Position.x = thePropInfo.second->m_FLOAT;
+ break;
+ case Q3DStudio::ATTRIBUTE_POSITION_Y:
+ thePoint.m_Position.y = thePropInfo.second->m_FLOAT;
+ break;
+ case Q3DStudio::ATTRIBUTE_INCOMINGANGLE:
+ thePoint.m_IncomingAngle = thePropInfo.second->m_FLOAT;
+ thePoint.m_OutgoingAngle = thePoint.m_IncomingAngle + 180.0f;
+ break;
+ case Q3DStudio::ATTRIBUTE_INCOMINGDISTANCE:
+ thePoint.m_IncomingDistance = thePropInfo.second->m_FLOAT;
+ break;
+ case Q3DStudio::ATTRIBUTE_OUTGOINGDISTANCE:
+ thePoint.m_OutgoingDistance = thePropInfo.second->m_FLOAT;
+ break;
+ default: // ignored
+ break;
+ }
+ }
+ }
+ ++anchorIndex;
+ }
+ }
+ }
+ }
+ }
+};
+
+struct SDefaultMaterialTranslator : public CUICTranslator
+{
+ typedef SDefaultMaterial TNodeType;
+ SDefaultMaterialTranslator(Q3DStudio::TElement &inElement, SDefaultMaterial &inRenderObject)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ }
+ // Right now materials do not respect the active flag
+ void SetActive(bool) {}
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SDefaultMaterial &theItem = *static_cast<SDefaultMaterial *>(m_RenderObject);
+ // There is no render-time caching on a material, so the dirty flag doesn't do much.
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_MATERIAL_PROPERTIES
+
+ case Q3DStudio::ATTRIBUTE_NAME:
+ case Q3DStudio::ATTRIBUTE_STARTTIME:
+ case Q3DStudio::ATTRIBUTE_ENDTIME:
+ case Q3DStudio::ATTRIBUTE_IMPORTID:
+ case Q3DStudio::ATTRIBUTE_EYEBALL:
+ case Q3DStudio::ATTRIBUTE_SOURCEPATH:
+ break;
+ default:
+ // Unknown attribute
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+
+ void PostPropertyChanged(const SRuntimePropertyParser &, Q3DStudio::IPresentation &)
+ {
+ SDefaultMaterial &theItem = *static_cast<SDefaultMaterial *>(m_RenderObject);
+ theItem.m_Dirty.SetDirty();
+ }
+};
+
+struct SImageTranslator : public CUICTranslator
+{
+ typedef SImage TNodeType;
+ SImageTranslator(Q3DStudio::TElement &inElement, SImage &inRenderObject)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ }
+
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SImage &theItem = *static_cast<SImage *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_IMAGE_PROPERTIES
+ case Q3DStudio::ATTRIBUTE_STARTTIME:
+ case Q3DStudio::ATTRIBUTE_ENDTIME:
+ case Q3DStudio::ATTRIBUTE_NAME:
+ case Q3DStudio::ATTRIBUTE_EYEBALL:
+ break;
+ default:
+ // Unknown attribute
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+ void PostPropertyChanged(const SRuntimePropertyParser &inParser, Q3DStudio::IPresentation &)
+ {
+ SImage &theItem = *static_cast<SImage *>(m_RenderObject);
+ if (inParser.m_Dirty)
+ theItem.m_Flags.SetDirty(true);
+ if (inParser.m_TransformDirty)
+ theItem.m_Flags.SetTransformDirty(true);
+ }
+};
+
+struct SReferencedMaterialTranslator : public CUICTranslator
+{
+ typedef SReferencedMaterial TNodeType;
+ SReferencedMaterialTranslator(Q3DStudio::TElement &inElement, TNodeType &inRenderObject)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ }
+
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ TNodeType &theItem = *static_cast<TNodeType *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_REFERENCED_MATERIAL_PROPERTIES
+ case Q3DStudio::ATTRIBUTE_STARTTIME:
+ case Q3DStudio::ATTRIBUTE_ENDTIME:
+ case Q3DStudio::ATTRIBUTE_NAME:
+ case Q3DStudio::ATTRIBUTE_EYEBALL:
+ break;
+ default:
+ // Unknown attribute
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+ void PostPropertyChanged(const SRuntimePropertyParser &inParser, Q3DStudio::IPresentation &)
+ {
+ TNodeType &theItem = *static_cast<TNodeType *>(m_RenderObject);
+ if (inParser.m_Dirty)
+ theItem.m_Dirty.SetDirty();
+ }
+};
+
+struct STextTranslator : public SNodeTranslator
+{
+ typedef SText TNodeType;
+ STextTranslator(Q3DStudio::TElement &inElement, SText &inRenderObject)
+ : SNodeTranslator(inElement, inRenderObject)
+ {
+ }
+ void OnSpecificPropertyChange(SRuntimePropertyParser &inParser)
+ {
+ SText &theItem = *static_cast<SText *>(m_RenderObject);
+ switch (inParser.m_PropertyName) {
+ ITERATE_UIC_RENDER_TEXT_PROPERTIES
+ case Q3DStudio::ATTRIBUTE_TEXTTYPE:
+ case Q3DStudio::ATTRIBUTE_RENDERSTYLE:
+ case Q3DStudio::ATTRIBUTE_WORDWRAP:
+ case Q3DStudio::ATTRIBUTE_HORZSCROLL:
+ case Q3DStudio::ATTRIBUTE_VERTSCROLL:
+ case Q3DStudio::ATTRIBUTE_BOXHEIGHT:
+ case Q3DStudio::ATTRIBUTE_BOXWIDTH:
+ case Q3DStudio::ATTRIBUTE_REMOTESTRINGSOURCE:
+ case Q3DStudio::ATTRIBUTE_CACHEDTEXTSTRING:
+ // These text properties are ignored for now.
+ break;
+ default:
+ SNodeTranslator::OnSpecificPropertyChange(inParser);
+ break;
+ }
+ }
+};
+struct SEffectPropertyEntry
+{
+ Q3DStudio::EAttributeType m_AttributeType;
+ QT3DSU32 m_PropertyOffset; // offset into the property array for the property def
+ QT3DSU32 m_DataOffset;
+ SEffectPropertyEntry(Q3DStudio::EAttributeType attType, QT3DSU32 poff, QT3DSU32 doff = 0)
+ : m_AttributeType(attType)
+ , m_PropertyOffset(poff)
+ , m_DataOffset(doff)
+ {
+ }
+};
+
+struct SDynamicObjectTranslatorContext : public STranslatorContext
+{
+ typedef nvhash_map<Q3DStudio::INT32, SEffectPropertyEntry> THashToOffsetMap;
+ THashToOffsetMap m_PropertyHashes;
+ NVAllocatorCallback &m_Allocator;
+ CRenderString m_Workspace;
+ SDynamicObjectTranslatorContext(NVAllocatorCallback &inCallback)
+ : m_PropertyHashes(inCallback, "SEffectTranslatorContext::PropertyHashes")
+ , m_Allocator(inCallback)
+ {
+ }
+ ~SDynamicObjectTranslatorContext() {}
+ void AddEffectExtendedProperty(const uic::render::dynamic::SPropertyDefinition &thePropDef,
+ const char *inExtension, Q3DStudio::EAttributeType inType,
+ CRenderString &ioStringBuilder, QT3DSU32 inOffset, QT3DSU32 dataOffset)
+ {
+ ioStringBuilder.assign(thePropDef.m_Name.c_str());
+ ioStringBuilder.append(inExtension);
+ Q3DStudio::INT32 theHash = Q3DStudio::CHash::HashAttribute(ioStringBuilder.c_str());
+ m_PropertyHashes.insert(
+ eastl::make_pair(theHash, SEffectPropertyEntry(inType, inOffset, dataOffset)));
+ }
+ void BuildPropertyHashes(NVConstDataRef<uic::render::dynamic::SPropertyDefinition> inProperties)
+ {
+ if (m_PropertyHashes.size() == 0) {
+ uic::render::CRenderString theNameBuilder;
+ for (QT3DSU32 idx = 0, end = inProperties.size(); idx < end; ++idx) {
+ const uic::render::dynamic::SPropertyDefinition &thePropDef = inProperties[idx];
+ switch (thePropDef.m_DataType) {
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32:
+ m_PropertyHashes.insert(eastl::make_pair(
+ Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()),
+ SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_FLOAT, idx)));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool:
+ m_PropertyHashes.insert(
+ eastl::make_pair(Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()),
+ SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_BOOL, idx)));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32:
+ if (thePropDef.m_IsEnumProperty == false) {
+ m_PropertyHashes.insert(eastl::make_pair(
+ Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()),
+ SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_INT32, idx)));
+ } else {
+ m_PropertyHashes.insert(eastl::make_pair(
+ Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()),
+ SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_STRING, idx)));
+ }
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2:
+ AddEffectExtendedProperty(thePropDef, ".x", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 0);
+ AddEffectExtendedProperty(thePropDef, ".y", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, sizeof(QT3DSF32));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3:
+ AddEffectExtendedProperty(thePropDef, ".x", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 0);
+ AddEffectExtendedProperty(thePropDef, ".y", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, sizeof(QT3DSF32));
+ AddEffectExtendedProperty(thePropDef, ".z", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 2 * sizeof(QT3DSF32));
+
+ AddEffectExtendedProperty(thePropDef, ".r", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 0);
+ AddEffectExtendedProperty(thePropDef, ".g", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, sizeof(QT3DSF32));
+ AddEffectExtendedProperty(thePropDef, ".b", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 2 * sizeof(QT3DSF32));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4:
+ AddEffectExtendedProperty(thePropDef, ".x", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 0);
+ AddEffectExtendedProperty(thePropDef, ".y", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, sizeof(QT3DSF32));
+ AddEffectExtendedProperty(thePropDef, ".z", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 2 * sizeof(QT3DSF32));
+ AddEffectExtendedProperty(thePropDef, ".w", Q3DStudio::ATTRIBUTETYPE_FLOAT,
+ theNameBuilder, idx, 3 * sizeof(QT3DSF32));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr:
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr:
+ m_PropertyHashes.insert(eastl::make_pair(
+ Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()),
+ SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_STRING, idx)));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderDataBufferPtr:
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+ }
+ void ApplyChanges(SPresentation &inPresentation, IUICRenderContext &inRenderContext,
+ SDynamicObject &inObject, Q3DStudio::TElement &element,
+ IDynamicObjectSystem &inSystem)
+ {
+ if (element.GetActive()) {
+ NVConstDataRef<uic::render::dynamic::SPropertyDefinition> theProperties =
+ inSystem.GetProperties(inObject.m_ClassName);
+ BuildPropertyHashes(theProperties);
+ SDynamicObject &theItem(inObject);
+ for (long idx = 0, end = element.GetAttributeCount(); idx < end; ++idx) {
+ uic::runtime::element::TPropertyDescAndValuePtr thePropInfo =
+ *element.GetPropertyByIndex(idx);
+ THashToOffsetMap::iterator theFind =
+ m_PropertyHashes.find(thePropInfo.first.GetNameHash());
+ if (theFind != m_PropertyHashes.end()) {
+ const SEffectPropertyEntry &theEntry(theFind->second);
+ const uic::render::dynamic::SPropertyDefinition &theDefinition(
+ theProperties[theEntry.m_PropertyOffset]);
+ if (theEntry.m_AttributeType
+ == (Q3DStudio::EAttributeType)thePropInfo.first.m_Type) {
+ switch (theEntry.m_AttributeType) {
+ case Q3DStudio::ATTRIBUTETYPE_BOOL:
+ theItem.SetPropertyValue(theDefinition,
+ thePropInfo.second->m_INT32 ? true : false);
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_FLOAT:
+ theItem.SetPropertyValue(theDefinition, thePropInfo.second->m_FLOAT,
+ theEntry.m_DataOffset);
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_INT32:
+ theItem.SetPropertyValue(theDefinition,
+ (QT3DSI32)thePropInfo.second->m_INT32);
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_STRING: {
+ CRegisteredString theStr =
+ element.GetBelongedPresentation()->GetStringTable().HandleToStr(
+ thePropInfo.second->m_StringHandle);
+ theItem.SetPropertyValue(theDefinition, theStr.c_str(),
+ inPresentation.m_PresentationDirectory.c_str(),
+ m_Workspace, inRenderContext.GetStringTable());
+ } break;
+ default:
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ } else {
+ // QT3DS_ASSERT( false );
+ }
+ }
+ }
+ theItem.m_Flags.SetDirty(true);
+ }
+ }
+};
+
+struct SEffectTranslator : public CUICTranslator
+{
+ typedef SEffect TNodeType;
+ SEffectTranslator(Q3DStudio::TElement &inElement, SEffect &inRenderObject,
+ NVAllocatorCallback &inCallback)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ m_TranslatorContext = QT3DS_NEW(inCallback, SDynamicObjectTranslatorContext)(inCallback);
+ }
+
+ void OnElementChanged(SPresentation &inPresentation, IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &)
+ {
+ SRuntimePropertyParser theParser(inPresentation, inRenderContext, *m_Element);
+ SEffect &theItem = *static_cast<SEffect *>(m_RenderObject);
+ static_cast<SDynamicObjectTranslatorContext *>(m_TranslatorContext)
+ ->ApplyChanges(inPresentation, inRenderContext, theItem, Element(),
+ inRenderContext.GetDynamicObjectSystem());
+ theItem.SetActive(Element().GetActive(), inRenderContext.GetEffectSystem());
+ }
+};
+
+struct SCustomMaterialTranslator : public CUICTranslator
+{
+ typedef SCustomMaterial TNodeType;
+ SCustomMaterialTranslator(Q3DStudio::TElement &inElement, SCustomMaterial &inRenderObject,
+ NVAllocatorCallback &inCallback)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ m_TranslatorContext = QT3DS_NEW(inCallback, SDynamicObjectTranslatorContext)(inCallback);
+ }
+
+ void OnElementChanged(SPresentation &inPresentation, IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &)
+ {
+ SRuntimePropertyParser theParser(inPresentation, inRenderContext, *m_Element);
+ SCustomMaterial &theItem = *static_cast<SCustomMaterial *>(m_RenderObject);
+ static_cast<SDynamicObjectTranslatorContext *>(m_TranslatorContext)
+ ->ApplyChanges(inPresentation, inRenderContext, theItem, Element(),
+ inRenderContext.GetDynamicObjectSystem());
+ bool active = m_Element->GetActive();
+ if (active != theItem.m_Flags.IsActive()) {
+ theItem.m_Flags.SetActive(active);
+ ICustomMaterialSystem &theSystem(inRenderContext.GetCustomMaterialSystem());
+ theSystem.OnMaterialActivationChange(theItem, active);
+ }
+ }
+};
+
+struct SRenderPluginTranslatorContext : public STranslatorContext
+{
+ NVAllocatorCallback &m_Allocator;
+ nvhash_map<int, CRegisteredString> m_AttribHashIndexMap;
+ nvvector<SRenderPropertyValueUpdate> m_PropertyUpdates;
+ SRenderPluginTranslatorContext(NVAllocatorCallback &alloc)
+ : m_Allocator(alloc)
+ , m_AttribHashIndexMap(alloc, "SRenderPluginTranslatorContext::AttribIndexMap")
+ , m_PropertyUpdates(alloc, "SRenderPluginTranslatorContext::m_PropertyUpdates")
+ {
+ }
+ void ReverseMap(CRegisteredString str)
+ {
+ m_AttribHashIndexMap.insert(
+ eastl::make_pair(Q3DStudio::CHash::HashAttribute(str.c_str()), str));
+ }
+};
+
+struct SRenderPluginTranslator : public CUICTranslator
+{
+ typedef SRenderPlugin TNodeType;
+ SRenderPluginTranslator(Q3DStudio::TElement &inElement, SRenderPlugin &inRenderObject,
+ NVAllocatorCallback &inCallback)
+ : CUICTranslator(inElement, inRenderObject)
+ {
+ m_TranslatorContext = QT3DS_NEW(inCallback, SRenderPluginTranslatorContext)(inCallback);
+ }
+
+ void OnElementChanged(SPresentation & /*inPresentation*/, IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &)
+ {
+ SRenderPlugin &theItem = *static_cast<SRenderPlugin *>(m_RenderObject);
+ theItem.m_Flags.SetActive(Element().GetActive());
+ IRenderPluginInstance *theInstance =
+ inRenderContext.GetRenderPluginManager().GetOrCreateRenderPluginInstance(
+ theItem.m_PluginPath, &theItem);
+ if (theInstance != NULL) {
+ IRenderPluginClass &theClass(theInstance->GetPluginClass());
+ SRenderPluginTranslatorContext &theTransContext =
+ static_cast<SRenderPluginTranslatorContext &>(*m_TranslatorContext);
+ if (theTransContext.m_AttribHashIndexMap.empty()) {
+ NVConstDataRef<SRenderPluginPropertyDeclaration> theProperties(
+ theClass.GetRegisteredProperties());
+ for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
+ const SRenderPluginPropertyDeclaration &theDec(theProperties[idx]);
+ switch (theDec.m_Type) {
+ case SRenderPluginPropertyTypes::Boolean:
+ theTransContext.ReverseMap(theDec.m_Name);
+ break;
+ case SRenderPluginPropertyTypes::Float:
+ theTransContext.ReverseMap(theDec.m_Name);
+ break;
+ case SRenderPluginPropertyTypes::Long:
+ theTransContext.ReverseMap(theDec.m_Name);
+ break;
+ case SRenderPluginPropertyTypes::String:
+ theTransContext.ReverseMap(theDec.m_Name);
+ break;
+ case SRenderPluginPropertyTypes::Vector2:
+ theTransContext.ReverseMap(
+ theClass.GetPropertyValueInfo(theDec.m_StartOffset).first);
+ theTransContext.ReverseMap(
+ theClass.GetPropertyValueInfo(theDec.m_StartOffset + 1).first);
+ break;
+ case SRenderPluginPropertyTypes::Vector3:
+ case SRenderPluginPropertyTypes::Color:
+ theTransContext.ReverseMap(
+ theClass.GetPropertyValueInfo(theDec.m_StartOffset).first);
+ theTransContext.ReverseMap(
+ theClass.GetPropertyValueInfo(theDec.m_StartOffset + 1).first);
+ theTransContext.ReverseMap(
+ theClass.GetPropertyValueInfo(theDec.m_StartOffset + 2).first);
+ break;
+ default:
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+ } // ok, now we have an efficient mapping from attribute to plugin value name.
+ theTransContext.m_PropertyUpdates.clear();
+ for (long idx = 0, end = Element().GetAttributeCount(); idx < end; ++idx) {
+ uic::runtime::element::TPropertyDescAndValuePtr thePropInfo =
+ *Element().GetPropertyByIndex(idx);
+ nvhash_map<int, CRegisteredString>::iterator theFind =
+ theTransContext.m_AttribHashIndexMap.find(thePropInfo.first.GetNameHash());
+ if (theFind != theTransContext.m_AttribHashIndexMap.end()) {
+ CRegisteredString thePropName(theFind->second);
+ Q3DStudio::EAttributeType theType =
+ (Q3DStudio::EAttributeType)thePropInfo.first.m_Type;
+ switch (theType) {
+ case Q3DStudio::ATTRIBUTETYPE_BOOL:
+ theTransContext.m_PropertyUpdates.push_back(SRenderPropertyValueUpdate(
+ thePropName, thePropInfo.second->m_INT32 ? true : false));
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_FLOAT:
+ theTransContext.m_PropertyUpdates.push_back(
+ SRenderPropertyValueUpdate(thePropName, thePropInfo.second->m_FLOAT));
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_INT32:
+ theTransContext.m_PropertyUpdates.push_back(SRenderPropertyValueUpdate(
+ thePropName, (QT3DSI32)thePropInfo.second->m_INT32));
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_STRING: {
+ CRegisteredString theStr = inRenderContext.GetStringTable().HandleToStr(
+ thePropInfo.second->m_StringHandle);
+ theTransContext.m_PropertyUpdates.push_back(
+ SRenderPropertyValueUpdate(thePropName, theStr));
+ } break;
+ default:
+ // QT3DS_ASSERT( false );
+ break;
+ }
+ }
+ }
+ if (theTransContext.m_PropertyUpdates.empty() == false) {
+ theInstance->Update(toConstDataRef(theTransContext.m_PropertyUpdates.data(),
+ theTransContext.m_PropertyUpdates.size()));
+ }
+ }
+ }
+};
+}
+
+CUICTranslator::CUICTranslator(Q3DStudio::TElement &inElement, SGraphObject &inRenderObject)
+ : m_DirtyIndex(QT3DS_MAX_U32)
+ , m_Element(&inElement)
+ , m_RenderObject(&inRenderObject)
+ , m_TranslatorContext(NULL)
+{
+ Element().SetAssociation(reinterpret_cast<void *>(this));
+ inRenderObject.m_UserData = STaggedPointer(this);
+}
+
+void CUICTranslator::Save(SWriteBuffer &inWriteBuffer, QT3DSU32 inGraphObjectOffset)
+{
+ // We have to start on pointer aligned boundaries.
+ QT3DS_ASSERT(inWriteBuffer.size() % sizeof(void *) == 0);
+ QT3DSU32 theOffset = inWriteBuffer.size();
+ inWriteBuffer.write(*this);
+ CUICTranslator *theNewTranslator =
+ reinterpret_cast<CUICTranslator *>(inWriteBuffer.begin() + theOffset);
+ theNewTranslator->m_DirtyIndex = QT3DS_MAX_U32;
+ if (theNewTranslator->m_Element)
+ theNewTranslator->m_Element = m_Element->GetBelongedPresentation()
+ ->GetApplication()
+ .GetElementAllocator()
+ .GetRemappedElementAddress(m_Element);
+ size_t *graphObjPtr = reinterpret_cast<size_t *>(&theNewTranslator->m_RenderObject);
+ *graphObjPtr = inGraphObjectOffset;
+}
+
+CUICTranslator *CUICTranslator::GetTranslatorFromGraphNode(SGraphObject &inObject)
+{
+ return inObject.m_UserData.DynamicCast<CUICTranslator>();
+}
+
+namespace {
+struct SPresentationTranslator;
+struct SEffectTranslator;
+template <typename TTranslatorType>
+struct STranslatorCreator
+{
+ static TTranslatorType *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject,
+ NVAllocatorCallback &inAllocator)
+ {
+ typedef typename TTranslatorType::TNodeType TNodeType;
+ // This assert needs to be here because we serialize all translators generically without
+ // regard for type.
+ StaticAssert<sizeof(TTranslatorType) == sizeof(CUICTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, TTranslatorType)(inElement, static_cast<TNodeType &>(inObject));
+ }
+ static void InitializeTranslator(CUICTranslator &inTranslator, NVAllocatorCallback &)
+ {
+ typedef typename TTranslatorType::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator) TTranslatorType(inTranslator.Element(),
+ static_cast<TNodeType &>(inTranslator.RenderObject()));
+ }
+
+ static void OnElementChanged(CUICTranslator &inTranslator, SPresentation &inPresentation,
+ IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ TTranslatorType &theTranslator(static_cast<TTranslatorType &>(inTranslator));
+ SRuntimePropertyParser theParser(inPresentation, inRenderContext, *theTranslator.m_Element);
+ if (theTranslator.Element().GetActive()) {
+ // Don't push properties from inactive elements.
+ for (long idx = 0, end = theTranslator.Element().GetAttributeCount(); idx < end;
+ ++idx) {
+ uic::runtime::element::TPropertyDescAndValuePtr thePropInfo =
+ *theTranslator.Element().GetPropertyByIndex(idx);
+ theParser.Setup(thePropInfo.first.GetNameHash(), *thePropInfo.second,
+ (Q3DStudio::EAttributeType)thePropInfo.first.m_Type);
+ // right now, this is the best we can do because the attribute's dirty system
+ // is all jacked up.
+ theTranslator.OnSpecificPropertyChange(theParser);
+ }
+ // same for dynamic properties
+ for (long idx = 0, end = theTranslator.Element().GetDynamicAttributeCount(); idx < end;
+ ++idx) {
+ uic::runtime::element::TPropertyDescAndValuePtr thePropInfo =
+ *theTranslator.Element().GetDynamicPropertyByIndex(idx);
+ theParser.Setup(thePropInfo.first.GetNameHash(), *thePropInfo.second,
+ (Q3DStudio::EAttributeType)thePropInfo.first.m_Type);
+ // right now, this is the best we can do because the attribute's dirty system
+ // is all jacked up.
+ theTranslator.OnSpecificPropertyChange(theParser);
+ }
+ // Set appropriate dirty flags
+ }
+ theTranslator.PostPropertyChanged(theParser, inStudioPresentation);
+ }
+};
+
+template <>
+struct STranslatorCreator<SPresentationTranslator>
+{
+ static CUICTranslator *Create(Q3DStudio::TElement &, SGraphObject &, NVAllocatorCallback &)
+ {
+ return NULL;
+ }
+ static void InitializeTranslator(CUICTranslator &, NVAllocatorCallback &) {}
+ static void OnElementChanged(CUICTranslator & /*inTranslator*/,
+ SPresentation & /*inPresentation*/
+ ,
+ IUICRenderContext & /*inRenderContext*/,
+ Q3DStudio::IPresentation & /*inStudioPresentation*/)
+ {
+ QT3DS_ASSERT(false);
+ }
+};
+
+template <>
+struct STranslatorCreator<SEffectTranslator>
+{
+ static SEffectTranslator *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject,
+ NVAllocatorCallback &inAllocator)
+ {
+ typedef SEffectTranslator::TNodeType TNodeType;
+ // This assert needs to be here because we serialize all translators generically without
+ // regard for type.
+ StaticAssert<sizeof(SEffectTranslator) == sizeof(CUICTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, SEffectTranslator)(inElement, static_cast<TNodeType &>(inObject),
+ inAllocator);
+ }
+
+ static void InitializeTranslator(CUICTranslator &inTranslator, NVAllocatorCallback &inAllocator)
+ {
+ typedef SEffectTranslator::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator)
+ SEffectTranslator(inTranslator.Element(),
+ static_cast<TNodeType &>(inTranslator.RenderObject()), inAllocator);
+ }
+ static void OnElementChanged(CUICTranslator &inTranslator, SPresentation &inPresentation,
+ IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ static_cast<SEffectTranslator &>(inTranslator)
+ .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation);
+ }
+};
+
+template <>
+struct STranslatorCreator<SCustomMaterialTranslator>
+{
+ static SCustomMaterialTranslator *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject,
+ NVAllocatorCallback &inAllocator)
+ {
+ typedef SCustomMaterialTranslator::TNodeType TNodeType;
+ // This assert needs to be here because we serialize all translators generically without
+ // regard for type.
+ StaticAssert<sizeof(SCustomMaterialTranslator)
+ == sizeof(CUICTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, SCustomMaterialTranslator)(
+ inElement, static_cast<TNodeType &>(inObject), inAllocator);
+ }
+
+ static void InitializeTranslator(CUICTranslator &inTranslator, NVAllocatorCallback &inAllocator)
+ {
+ typedef SCustomMaterialTranslator::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator) SCustomMaterialTranslator(
+ inTranslator.Element(), static_cast<TNodeType &>(inTranslator.RenderObject()),
+ inAllocator);
+ }
+
+ static void OnElementChanged(CUICTranslator &inTranslator, SPresentation &inPresentation,
+ IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ static_cast<SCustomMaterialTranslator &>(inTranslator)
+ .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation);
+ }
+};
+
+template <>
+struct STranslatorCreator<SRenderPluginTranslator>
+{
+ static SRenderPluginTranslator *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject,
+ NVAllocatorCallback &inAllocator)
+ {
+ typedef SRenderPluginTranslator::TNodeType TNodeType;
+ // This assert needs to be here because we serialize all translators generically without
+ // regard for type.
+ StaticAssert<sizeof(SRenderPluginTranslator) == sizeof(CUICTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, SRenderPluginTranslator)(
+ inElement, static_cast<TNodeType &>(inObject), inAllocator);
+ }
+
+ static void InitializeTranslator(CUICTranslator &inTranslator, NVAllocatorCallback &inAllocator)
+ {
+ typedef SRenderPluginTranslator::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator) SRenderPluginTranslator(
+ inTranslator.Element(), static_cast<TNodeType &>(inTranslator.RenderObject()),
+ inAllocator);
+ }
+ static void OnElementChanged(CUICTranslator &inTranslator, SPresentation &inPresentation,
+ IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ static_cast<SRenderPluginTranslator &>(inTranslator)
+ .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation);
+ }
+};
+}
+CUICTranslator *CUICTranslator::CreateTranslatorForElement(Q3DStudio::TElement &inElement,
+ SGraphObject &inObject,
+ NVAllocatorCallback &inAlloc)
+{
+ CUICTranslator *theTranslator = NULL;
+ switch (inObject.m_Type) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case GraphObjectTypes::type: \
+ theTranslator = \
+ STranslatorCreator<S##type##Translator>::Create(inElement, inObject, inAlloc); \
+ break;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return theTranslator;
+}
+
+void CUICTranslator::OnElementChanged(SPresentation &inPresentation,
+ IUICRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+{
+ switch (m_RenderObject->m_Type) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case GraphObjectTypes::type: \
+ STranslatorCreator<S##type##Translator>::OnElementChanged( \
+ *this, inPresentation, inRenderContext, inStudioPresentation); \
+ break;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+}
+
+CUICTranslator *CUICTranslator::LoadTranslator(SDataReader &inReader, size_t inElemOffset,
+ NVDataRef<QT3DSU8> inSGSection,
+ NVAllocatorCallback &inAllocator)
+{
+ // Reader points to a new translator but we don't know what type
+ QT3DSU8 *theTranslatorStart = inReader.m_CurrentPtr;
+ // Make sure things are aligned
+ (void)theTranslatorStart;
+ QT3DS_ASSERT((size_t)theTranslatorStart % sizeof(void *) == 0);
+ CUICTranslator *theTranslator = inReader.Load<CUICTranslator>();
+ if (theTranslator) {
+ size_t *elemPtr = reinterpret_cast<size_t *>(&theTranslator->m_Element);
+ *elemPtr += inElemOffset;
+ size_t *graphObjPtr = reinterpret_cast<size_t *>(&theTranslator->m_RenderObject);
+ size_t sgSectionStart = reinterpret_cast<size_t>(inSGSection.begin());
+ *graphObjPtr += sgSectionStart;
+ // Call actual constructor to initialize vtable.
+ switch (theTranslator->RenderObject().m_Type) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case GraphObjectTypes::type: \
+ STranslatorCreator<S##type##Translator>::InitializeTranslator(*theTranslator, \
+ inAllocator); \
+ break;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ return theTranslator;
+}
+Q3DStudio::IPresentation *
+CUICTranslator::GetPresentationFromPresentation(SPresentation &inPresentation)
+{
+ return inPresentation.m_UserData.DynamicCast<Q3DStudio::IPresentation>();
+}
+
+void CUICTranslator::InitializePointerTags(IStringTable &)
+{
+ g_TranslatorTag = 0x0044FEED;
+ g_PresentationTag = 0x0022ABBA;
+}
+
+void CUICTranslator::AssignUserData(Q3DStudio::IPresentation &inPresentation,
+ SPresentation &inGraphPresentation)
+{
+ inGraphPresentation.m_UserData = STaggedPointer(&inPresentation);
+}
diff --git a/src/Runtime/Source/Engine/Source/UICTegraApplication.cpp b/src/Runtime/Source/Engine/Source/UICTegraApplication.cpp
new file mode 100644
index 00000000..440ba36c
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/UICTegraApplication.cpp
@@ -0,0 +1,754 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTegraApplication.h"
+#include "UICTegraInputEngine.h"
+#include "UICDataLogger.h"
+#include "UICFileStream.h"
+#include "UICThreadManager.h"
+#include "UICArray.h"
+#include "UICApplication.h"
+#include "foundation/FileTools.h"
+#include "UICIPresentation.h"
+#include "UICPresentation.h"
+#include "EASTL/string.h"
+#include "UICMemory.h"
+#include "UICKernelTypes.h"
+#include "UICRenderContext.h"
+#include "UICRenderer.h"
+
+#include "UICDLLManager.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/TrackingAllocator.h"
+// For perf log timestamp
+#include <time.h>
+#include "UICArray.h"
+// For perf log timestamp
+#include <time.h>
+
+#if Q_OS_WINDOWS
+#include "qt3ds_launcher_defs.h"
+#endif
+
+#ifdef _LINUXPLATFORM
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
+#include <QCoreApplication>
+#include <QSurfaceFormat>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace uic {
+namespace render {
+extern qt3ds::foundation::MallocAllocator g_BaseAllocator;
+}
+}
+
+namespace Q3DStudio {
+
+namespace {
+
+bool CaselessEqual(const char *lhs, const char *rhs)
+{
+ if (lhs == NULL)
+ lhs = "";
+ if (rhs == NULL)
+ rhs = "";
+ return Q3DStudio_stricmp(lhs, rhs) == 0;
+}
+
+CInputEngine *CreateInputEngine()
+{
+ return Q3DStudio_virtual_new(CTegraInputEngine) CTegraInputEngine();
+}
+
+static eastl::string *theAppDir = nullptr;
+const eastl::string &GetAppDir(const eastl::string &inAppExe)
+{
+ if (!theAppDir)
+ theAppDir = new eastl::string;
+#ifndef __ANDROID__
+ theAppDir->assign(inAppExe.empty() == false ? inAppExe : "");
+#ifdef UIC_OS_LINUX
+ char theBuf[1024] = { 0 };
+ int rc = readlink("/proc/self/exe", theBuf, sizeof(theBuf));
+ if (rc > 0)
+ theAppDir->assign(theBuf);
+#endif
+#ifdef UIC_OS_QNX
+ char theBuf[1024] = { 0 };
+ FILE *exefile = fopen("/proc/self/exefile", "r");
+ if (exefile != NULL) {
+ fgets(theBuf, sizeof(theBuf), exefile);
+ fclose(exefile);
+ theAppDir->assign(theBuf);
+ }
+#endif
+ eastl::string::size_type pos = theAppDir->find_last_of("\\/");
+ if (pos != eastl::string::npos)
+ *theAppDir = theAppDir->substr(0, pos);
+ theAppDir->append("\\");
+#endif
+ return *theAppDir;
+}
+}
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+
+//==============================================================================
+/**
+ * CNDDView
+ */
+class CNDDView : public INDDView
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ ITegraApplicationRenderEngine *m_RenderEngine; ///< Handles all rendering functions
+ CTegraInputEngine *m_InputEngine; ///< Handles all user input events
+ // Pre graphics init objects
+ NVScopedRefCounted<uic::render::IUICRenderFactoryCore> m_RuntimeFactoryCore;
+ NVScopedRefCounted<uic::runtime::IApplicationCore>
+ m_ApplicationCore; ///< Base application before graphis
+
+ // Post graphics init objects
+ NVScopedRefCounted<uic::render::IUICRenderFactory> m_RuntimeFactory;
+ NVScopedRefCounted<uic::runtime::IApplication> m_Application; ///< Application after graphics
+ CPresentation *m_Presentation; ///< Currently loaded presentation, this should be removed in the future
+
+ CPausingTimeProvider m_TimeProvider;
+ IWindowSystem &m_WindowSystem;
+ IAudioPlayer *m_AudioPlayer;
+
+ volatile QT3DSI32 mRefCount;
+
+ uic::UICAssetVisitor *m_visitor;
+ bool m_showOnScreenStats;
+
+public:
+ CNDDView(ITimeProvider &inTimeProvider, IWindowSystem &inWindowSystem,
+ IAudioPlayer *inAudioPlayer);
+ ~CNDDView();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(uic::render::g_BaseAllocator);
+
+ bool BeginLoad(const QString &sourcePath) override;
+ bool HasOfflineLoadingCompleted() override;
+ void InitializeGraphics(const QSurfaceFormat &format) override;
+
+ void Cleanup() override;
+
+ bool CanRender() override;
+ void Render() override;
+ bool WasLastFrameDirty() override;
+
+ KDint HandleMessage(const KDEvent *inEvent) override;
+
+ void Pause() override;
+ void UnPause() override;
+ bool IsPaused() override;
+ void setAssetVisitor(uic::UICAssetVisitor *) override;
+
+ INT32 GetFrameCount() override;
+ void showOnScreenStats(bool) override;
+
+ CInputEngine *GetInputEngine() override;
+ // Only valid after InitializeGraphics
+ ITegraApplicationRenderEngine *GetTegraRenderEngine() override { return m_RenderEngine; }
+
+ void GoToSlideByName(const char *elementPath, const char *slideName) override;
+ void GoToSlideByIndex(const char *elementPath, const int slideIndex) override;
+ void GoToSlideRelative(const char *elementPath, const bool next, const bool wrap) override;
+ bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName) override;
+ void SetPresentationAttribute(const char *presId, const char *, const char *value) override;
+ void GoToTime(const char *elementPath, const float time) override;
+ void SetGlobalAnimationTime(qint64 inMilliSecs) override;
+ void SetAttribute(const char *elementPath, const char *attributeName, const char *value) override;
+ bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override;
+ void FireEvent(const char *element, const char *evtName) override;
+ bool PeekCustomAction(char *&outElementPath, char *&outActionName) override;
+ bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) override;
+ void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) override;
+ bool AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction) override;
+ qt3ds::foundation::Option<SPresentationSize> GetPresentationSize() override;
+
+ void BootupPreGraphicsInitObjects();
+};
+
+CNDDView::CNDDView(ITimeProvider &inTimeProvider, IWindowSystem &inWindowSystem,
+ IAudioPlayer *inAudioPlayer)
+ : m_RenderEngine(NULL)
+ , m_InputEngine(NULL)
+ , m_Application(NULL)
+ , m_Presentation(NULL)
+ , m_TimeProvider(inTimeProvider)
+ , m_WindowSystem(inWindowSystem)
+ , m_AudioPlayer(inAudioPlayer)
+ , mRefCount(0)
+ , m_visitor(nullptr)
+ , m_showOnScreenStats(false)
+{
+}
+
+CNDDView::~CNDDView()
+{
+}
+
+bool CNDDView::BeginLoad(const QString &sourcePath)
+{
+ bool theResult = false;
+
+ // boot up the application
+ BootupPreGraphicsInitObjects();
+
+ // If there was a presentation file then we have to load it or something failed.
+ if (m_ApplicationCore->BeginLoad(sourcePath.toUtf8()))
+ theResult = true;
+ else
+ theResult = false;
+
+ // If Initialize wasn't successful - this means the CShaderFactory failed to initialize
+ // or, the presentation failed to load.
+ //
+ // NOTE: if no presentation was passed, this is 'ok'
+ if (!theResult)
+ Cleanup();
+
+ return theResult;
+}
+
+bool CNDDView::HasOfflineLoadingCompleted()
+{
+ if (m_Application.mPtr == NULL) {
+ if (m_ApplicationCore)
+ return m_ApplicationCore->HasCompletedLoading();
+ else
+ return false;
+ }
+ return true;
+}
+
+void CNDDView::InitializeGraphics(const QSurfaceFormat &format)
+{
+ m_ApplicationCore->EndLoad();
+ // Next call will initialize the render portion of the scenes. This *must* have a loaded
+ // application to go further as it will bind scene graph data to application data.
+ m_RuntimeFactory = m_RuntimeFactoryCore->CreateRenderFactory(format);
+ m_Application
+ = m_ApplicationCore->CreateApplication(*m_InputEngine, m_AudioPlayer,
+ *m_RuntimeFactory);
+ m_Application->ResetTime();
+ m_RenderEngine = &m_RuntimeFactory->CreateRenderEngine();
+ m_Presentation = m_Application->GetPrimaryPresentation();
+
+ QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigSlideEntered,
+ signalProxy(), &QINDDViewSignalProxy::SigSlideEntered);
+ QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigSlideExited,
+ signalProxy(), &QINDDViewSignalProxy::SigSlideExited);
+
+ m_TimeProvider.Reset();
+}
+
+void CNDDView::Cleanup()
+{
+ // Q3DStudio_virtual_delete( m_Timer, CTimer );
+ // Q3DStudio_virtual_delete( m_PerfFileStream, CFileStream );
+ m_Application = NULL;
+ Q3DStudio_virtual_delete(m_InputEngine, CTegraInputEngine);
+ if (m_RenderEngine) {
+ m_RenderEngine->Release();
+ m_RenderEngine = NULL;
+ }
+
+ CDLLManager &theDLLManager = CDLLManager::GetDLLManager();
+ theDLLManager.Cleanup();
+ QObject::disconnect(m_Presentation->signalProxy(), 0, signalProxy(), 0);
+
+ m_InputEngine = NULL;
+ m_RenderEngine = NULL;
+ m_Presentation = NULL;
+}
+
+bool CNDDView::CanRender()
+{
+ return m_Application.mPtr != NULL;
+}
+
+//==============================================================================
+/**
+ * nv_main APP-SPECIFIC rendering call
+ * returns KD_TRUE to call egl_render and swap properly, KD_FALSE if there has been no scene update
+ *or redraw.
+ */
+void CNDDView::Render()
+{
+ if (m_Application.mPtr == NULL) {
+ // InitializeGraphics has not been called
+ QT3DS_ASSERT(false);
+ }
+
+ PerfLogGeneralEvent1(DATALOGGER_FRAME);
+
+ m_Application->UpdateAndRender();
+
+ if (m_showOnScreenStats) {
+ ITegraRenderStateManager &manager
+ = GetTegraRenderEngine()->GetTegraRenderStateManager();
+ manager.PushState();
+
+ SSize dim = m_WindowSystem.GetWindowDimensions();
+ manager.SetScissorTestEnabled(false);
+ manager.SetViewport(0, 0, dim.m_Width, dim.m_Height);
+
+ QPair<QT3DSF32, QT3DSF32> fps
+ = m_RuntimeFactory->GetUICRenderContext().GetFPS();
+
+ QString text;
+ QTextStream stream(&text);
+ stream << QStringLiteral("Render Statistics: ");
+ stream << QString::number(fps.first, 'f', 2);
+ stream << " fps, frame count ";
+ stream << QString::number(fps.second);
+
+ // bottom left coordinates
+ GetTegraRenderEngine()->RenderText2D(
+ dim.m_Width / 4, dim.m_Height - 25, qt3ds::QT3DSVec3(0.0, 1.0, 0.0),
+ text.toLatin1().constData());
+ GetTegraRenderEngine()->RenderGpuProfilerStats(
+ 20.0, dim.m_Height - 80, qt3ds::QT3DSVec3(0.0, 1.0, 0.0));
+
+ manager.PopState();
+ }
+}
+
+bool CNDDView::WasLastFrameDirty()
+{
+ if (m_Application)
+ return m_Application->IsApplicationDirty();
+ return false;
+}
+
+//==============================================================================
+/**
+ * nv_main APP-SPECIFIC message call
+ * HandleMessage
+ */
+KDint CNDDView::HandleMessage(const KDEvent *inEvent)
+{
+ if (m_Application.mPtr == NULL || m_RenderEngine == NULL)
+ return 0;
+ KDint theReturn = KD_FALSE;
+ switch (inEvent->type) {
+ case KD_EVENT_INPUT:
+ theReturn = KD_TRUE;
+ break;
+ case KD_EVENT_INPUT_POINTER:
+ m_InputEngine->SetPickInput(static_cast<FLOAT>(inEvent->data.inputpointer.x),
+ static_cast<FLOAT>(inEvent->data.inputpointer.y), true);
+ m_InputEngine->SetPickFlags(inEvent->data.inputpointer.select ? LMOUSE_DOWN : LMOUSE_UP);
+ theReturn = KD_TRUE;
+ break;
+#if !defined(Q_OS_MACOS)
+ case KD_EVENT_WINDOW_CLOSE:
+ theReturn = KD_FALSE;
+ break;
+ case KD_EVENT_WINDOW_REDRAW:
+ case KD_EVENT_WINDOW_FOCUS:
+ theReturn = KD_TRUE;
+ break;
+ case KD_EVENT_WINDOWPROPERTY_CHANGE:
+ if (inEvent->data.windowproperty.pname == KD_WINDOWPROPERTY_SIZE
+ && m_Application->GetPrimaryPresentation())
+ m_RenderEngine->CheckResize(KD_TRUE, *m_Application->GetPrimaryPresentation());
+ theReturn = KD_TRUE;
+ break;
+#endif
+ default:
+ kdDefaultEvent(inEvent);
+ theReturn = KD_TRUE;
+ break;
+ }
+ m_InputEngine->HandleMessage(inEvent, *m_RenderEngine, m_Application->GetPrimaryPresentation());
+ return theReturn;
+}
+
+void CNDDView::Pause()
+{
+ m_TimeProvider.Pause();
+}
+
+void CNDDView::UnPause()
+{
+ m_TimeProvider.UnPause();
+}
+
+bool CNDDView::IsPaused()
+{
+ return m_TimeProvider.IsPaused();
+}
+
+INT32 CNDDView::GetFrameCount()
+{
+ return m_Application->GetFrameCount();
+}
+
+void CNDDView::showOnScreenStats(bool show)
+{
+ m_showOnScreenStats = show;
+}
+
+CInputEngine *CNDDView::GetInputEngine()
+{
+ return m_InputEngine;
+}
+
+//==============================================================================
+/**
+ * Generates an event in the presentation.
+ */
+void CNDDView::GoToSlideByName(const char *elementPath, const char *slideName)
+{
+ if (m_Application) {
+ if (!elementPath || !slideName)
+ return;
+
+ CPresentation *thePresentation = m_Application->GetPrimaryPresentation();
+ IScriptBridge *theBridge = thePresentation->GetScriptBridgeQml();
+
+ if (!theBridge)
+ return;
+
+ theBridge->GotoSlide(elementPath, slideName, SScriptEngineGotoSlideArgs());
+ }
+}
+
+void CNDDView::GoToSlideByIndex(const char *elementPath, const int slideIndex)
+{
+ if (m_Application) {
+ if (!elementPath || slideIndex < 0)
+ return;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.GotoSlideIndex(elementPath, slideIndex, SScriptEngineGotoSlideArgs());
+ }
+}
+
+void CNDDView::GoToSlideRelative(const char *elementPath, const bool next, const bool wrap)
+{
+ if (m_Application) {
+ if (!elementPath)
+ return;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.GotoSlideRelative(elementPath, next, wrap, SScriptEngineGotoSlideArgs());
+ }
+}
+
+bool CNDDView::GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName)
+{
+ if (m_Application && elementPath) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ return theBridgeEngine.GetSlideInfo(elementPath, currentIndex, previousIndex,
+ currentName, previousName);
+ }
+ return false;
+}
+
+void CNDDView::SetPresentationAttribute(const char *presId, const char *, const char *value)
+{
+ if (m_Application) {
+ if (!presId || !value)
+ return;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.SetPresentationAttribute(presId, nullptr, value);
+ }
+}
+
+bool CNDDView::RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData)
+{
+ if (m_Application) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ return theBridgeEngine.RegisterCallback(callbackType, func, inUserData);
+ }
+
+ return false;
+}
+
+void CNDDView::GoToTime(const char *elementPath, const float time)
+{
+ if (m_Application) {
+ if (!elementPath || time < 0.0)
+ return;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.GotoTime(elementPath, time);
+ }
+}
+
+void CNDDView::SetGlobalAnimationTime(qint64 inMilliSecs)
+{
+ if (m_Application)
+ m_Application->SetTimeMilliSecs(inMilliSecs);
+}
+
+void CNDDView::SetAttribute(const char *elementPath, const char *attributeName, const char *value)
+{
+ if (m_Application) {
+ if (!elementPath || !attributeName || !value)
+ return;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.SetAttribute(elementPath, attributeName, value);
+ }
+}
+
+bool CNDDView::GetAttribute(const char *elementPath, const char *attributeName, void *value)
+{
+ if (m_Application) {
+ if (!elementPath || !attributeName || !value)
+ return false;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ return theBridgeEngine.GetAttribute(elementPath, attributeName, (char *)value);
+ }
+
+ return false;
+}
+
+void CNDDView::FireEvent(const char *element, const char *evtName)
+{
+ if (m_Application) {
+ if (!element || !evtName)
+ return;
+
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.FireEvent(element, evtName);
+ }
+}
+
+bool CNDDView::PeekCustomAction(char *&outElementPath, char *&outActionName)
+{
+ bool actionAvailable = true;
+
+ if (m_Application) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ Q3DStudio::TElement *theElement = NULL;
+ actionAvailable = theBridgeEngine.PeekSignal(theElement, outActionName);
+ if (actionAvailable && theElement)
+ outElementPath = (char *)theElement->m_Path.c_str();
+ }
+
+ return actionAvailable;
+}
+
+void CNDDView::FireEvent(const TEventCommandHash inEventType, eastl::string inArgument)
+{
+ if (m_Application) {
+ CPresentation *thePresentation = m_Application->GetPrimaryPresentation();
+ TElement *theScene = thePresentation->GetRoot();
+ if (inArgument.empty()) {
+ thePresentation->FireEvent(inEventType, theScene, NULL, NULL, ATTRIBUTETYPE_NONE,
+ ATTRIBUTETYPE_NONE);
+ } else {
+ UVariant inArg;
+ inArg.m_StringHandle = thePresentation->GetStringTable().GetHandle(inArgument.c_str());
+ thePresentation->FireEvent(inEventType, theScene, &inArg, NULL, ATTRIBUTETYPE_STRING,
+ ATTRIBUTETYPE_NONE);
+ }
+ }
+}
+
+bool CNDDView::AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction)
+{
+ bool theResult = false;
+ if (m_Presentation) {
+ if (m_Application) {
+ // this is lua specific
+ Q3DStudio::CLuaEngine &theScriptEngine
+ = static_cast<Q3DStudio::CLuaEngine &>(m_RuntimeFactoryCore->GetScriptEngine());
+ theScriptEngine.AddGlobalFunction(inFunctionName, inFunction);
+ theResult = true;
+ }
+ }
+ return theResult;
+}
+qt3ds::foundation::Option<SPresentationSize> CNDDView::GetPresentationSize()
+{
+ if (m_Application) {
+ CPresentation *thePresentation = m_Application->GetPrimaryPresentation();
+ if (thePresentation)
+ return thePresentation->GetSize();
+ }
+ return qt3ds::foundation::Empty();
+}
+
+//==============================================================================
+/**
+ * Perform the initialization steps prior to loading any presentation.
+ */
+void CNDDView::BootupPreGraphicsInitObjects()
+{
+ qCInfo(TRACE_INFO) << "CNDDView::BootupPreGraphicsInitObjects: DoInitialize";
+ // Create engines and runtime
+ const eastl::string &theAppDir = QCoreApplication::applicationDirPath().toLatin1().constData();
+
+ m_RuntimeFactoryCore = uic::render::IUICRenderFactoryCore::CreateRenderFactoryCore(
+ theAppDir.c_str(), m_WindowSystem, m_TimeProvider);
+ m_ApplicationCore = uic::runtime::IApplicationCore::CreateApplicationCore(*m_RuntimeFactoryCore,
+ theAppDir.c_str());
+
+ if (m_ApplicationCore && m_visitor)
+ m_ApplicationCore->setAssetVisitor(m_visitor);
+
+ m_InputEngine = static_cast<CTegraInputEngine *>(CreateInputEngine());
+ Q3DStudio_ASSERT(m_InputEngine != NULL);
+
+ qCInfo(TRACE_INFO) << "CNDDView::DoInitialize: Successfully initialized!";
+}
+
+void CNDDView::setAssetVisitor(uic::UICAssetVisitor *v)
+{
+ m_visitor = v;
+ if (m_ApplicationCore)
+ m_ApplicationCore->setAssetVisitor(v);
+}
+
+INDDView &INDDView::Create(ITimeProvider &inProvider, IWindowSystem &inWindowSystem,
+ IAudioPlayer *inAudioPlayer)
+{
+ return *QT3DS_NEW(uic::render::g_BaseAllocator, CNDDView)(inProvider, inWindowSystem,
+ inAudioPlayer);
+}
+
+QINDDViewSignalProxy *INDDView::signalProxy()
+{
+ return &m_SignalProxy;
+}
+
+//==============================================================================
+/**
+ * CTegraApplication
+ */
+CTegraApplication::CTegraApplication(ITimeProvider &inProvider, IWindowSystem &inWindowSystem,
+ IAudioPlayer *inAudioPlayer)
+{
+ m_NDDView = INDDView::Create(inProvider, inWindowSystem, inAudioPlayer);
+}
+
+CTegraApplication::~CTegraApplication()
+{
+}
+
+KDint CTegraApplication::BeginLoad(const QString &sourcePath)
+{
+#ifndef UIC_NO_SEARCH_PATH
+ // We need these later on in case we try to load any files
+ // such as images
+ NvFSAppendSearchPath("/res");
+ NvFSAppendSearchPath("/res/..");
+ NvFSAppendSearchPath("/data");
+#endif
+
+ KDint theResult = KD_FALSE;
+
+ qCInfo(TRACE_INFO) << "CTegraApplication::BeginLoad: Attempting presentation beginload";
+
+ if (!sourcePath.isEmpty()) {
+ // If there was a presentation file then we have to load it or something failed.
+ if (m_NDDView->BeginLoad(sourcePath)) {
+ qCInfo(TRACE_INFO)
+ << "CTegraApplication::BeginLoad: Successfully begin loading presentation: "
+ << sourcePath;
+ theResult = KD_TRUE;
+ } else {
+ qCInfo(TRACE_INFO) << "CTegraApplication::BeginLoad: Failed to load presentation: "
+ << sourcePath;
+ theResult = KD_FALSE;
+ }
+ } else {
+ // If there wasn't, then we are still in an OK state.
+ qCInfo(TRACE_INFO) << "CTegraApplication::BeginLoad: Presentation file not provided";
+ theResult = KD_TRUE;
+ }
+
+ qCInfo(TRACE_INFO) << "CTegraApplication::BeginLoad: End beginload";
+ return theResult;
+}
+
+void CTegraApplication::InitializeGraphics(const QSurfaceFormat &format)
+{
+ m_NDDView->InitializeGraphics(format);
+}
+
+void CTegraApplication::Render()
+{
+ m_NDDView->Render();
+}
+
+KDint CTegraApplication::HandleMessage(const KDEvent *inEvent)
+{
+ return m_NDDView->HandleMessage(inEvent);
+}
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Engine/Source/UICTegraInputEngine.cpp b/src/Runtime/Source/Engine/Source/UICTegraInputEngine.cpp
new file mode 100644
index 00000000..3bb15604
--- /dev/null
+++ b/src/Runtime/Source/Engine/Source/UICTegraInputEngine.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EnginePrefix.h"
+#include "UICTegraInputEngine.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * XXX
+ */
+CTegraInputEngine::CTegraInputEngine()
+{
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+CTegraInputEngine::~CTegraInputEngine()
+{
+}
+
+//==============================================================================
+/**
+ * Returns the structure that contains the input information for the current frame.
+ */
+SInputFrame &CTegraInputEngine::GetInputFrame()
+{
+ return m_InputFrame;
+}
+
+//==============================================================================
+/**
+ * Handles the input message.
+ */
+void CTegraInputEngine::HandleMessage(const KDEvent *inEvent,
+ ITegraApplicationRenderEngine &inRenderEngine,
+ CPresentation *inPresentation)
+{
+ static KDboolean s_PointerWasDown = KD_FALSE;
+
+ if (NULL == inPresentation)
+ return;
+
+ switch (inEvent->type) {
+ // we still want to preserve the mouse events support, hence process this event as usual.
+ case KD_EVENT_INPUT_POINTER: {
+ const KDEventInputPointer *ptr = &(inEvent->data.inputpointer);
+
+ KDfloat32 x = static_cast<KDfloat32>(ptr->x);
+ KDfloat32 y = static_cast<KDfloat32>(ptr->y);
+
+ if (inRenderEngine.IsPickValid(x, y, *inPresentation)) {
+ // printf( "INPUT x %ld y %ld\n", (int)x, (int)y );
+ SetPickInput(x, y, (ptr->select || s_PointerWasDown) ? true : false);
+
+ if (ptr->select) {
+ if (s_PointerWasDown)
+ SetPickFlags(LMOUSE_DOWN);
+ else
+ SetPickFlags(LMOUSE_PRESSED);
+
+ s_PointerWasDown = KD_TRUE;
+ } else {
+ if (s_PointerWasDown)
+ SetPickFlags(LMOUSE_RELEASED);
+ else
+ SetPickFlags(LMOUSE_UP);
+
+ s_PointerWasDown = KD_FALSE;
+ }
+ } else {
+ if (s_PointerWasDown)
+ SetPickFlags(LMOUSE_RELEASED);
+ else
+ SetPickFlags(LMOUSE_UP);
+
+ s_PointerWasDown = KD_FALSE;
+ }
+ } break;
+#if !defined(Q_OS_MACOS)
+ case KD_EVENT_WINDOW_FOCUS:
+ /* On loss of focus, we simulate a pointer-up event */
+ if (!inEvent->data.windowfocus.focusstate) {
+ /*if ( s_PointerWasDown )
+ SetPickFlags( LMOUSE_RELEASED );
+ else
+ SetPickFlags( LMOUSE_UP );*/
+ s_PointerWasDown = KD_FALSE;
+ }
+ break;
+#endif
+ }
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/HDR/Include/CUDABSDFMipmap.h b/src/Runtime/Source/HDR/Include/CUDABSDFMipmap.h
new file mode 100644
index 00000000..6f2106c4
--- /dev/null
+++ b/src/Runtime/Source/HDR/Include/CUDABSDFMipmap.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUDABSDfMIPMAP_H
+#define CUDABSDFMIPMAP_H
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "MipmapBSDF.h"
+
+#include "UICRenderLoadedTexture.h"
+
+#include "UICTypes.h"
+struct cudaGraphicsResource;
+#ifdef _LINUXPLATFORM
+#define __declspec(dllexport)
+#define __cdecl
+
+#endif
+using namespace qt3ds::render;
+using namespace uic::render;
+
+class CUDABSDFMipMap : public BSDFMipMap
+{
+public:
+ CUDABSDFMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture, NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+ ~CUDABSDFMipMap();
+ void Build(void *inTextureData, int inTextureDataSize,
+ NVRenderBackend::NVRenderBackendTextureObject inTextureHandle,
+ NVRenderTextureFormats::Enum inFormat);
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation);
+
+private:
+ void CreateBsdfMipMaps(uic::render::SLoadedTexture &inLoadedImage, void **result, int width,
+ int height); //, qt3ds::foundation::IPerfTimer& inPerfTimer);
+
+ void BindTexture();
+ void TransferTexture();
+
+ cudaGraphicsResource *m_CudaMipMapResource;
+ void **md_MipMapsData;
+ size_t *m_Pitches;
+ NVRenderBackend::NVRenderBackendTextureObject m_TextureHandle;
+ bool m_TextureBinded;
+};
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/HDR/Include/GLComputeMipMap.h b/src/Runtime/Source/HDR/Include/GLComputeMipMap.h
new file mode 100644
index 00000000..aa0443eb
--- /dev/null
+++ b/src/Runtime/Source/HDR/Include/GLComputeMipMap.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GLCOMPUTE_BSDF_MIMAP_H
+#define GLCOMPUTE_BSDF_MIMAP_H
+
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "MipmapBSDF.h"
+
+#include "UICRenderLoadedTexture.h"
+#include "UICTypes.h"
+
+using namespace qt3ds::render;
+using namespace uic::render;
+
+class qt3ds::render::NVRenderContext;
+class qt3ds::render::NVRenderShaderProgram;
+class qt3ds::render::NVRenderTexture2D;
+
+class GLComputeMipMap : public BSDFMipMap
+{
+public:
+ GLComputeMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture, NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+ ~GLComputeMipMap();
+ void Build(void *inTextureData, int inTextureDataSize,
+ NVRenderBackend::NVRenderBackendTextureObject inTextureHandle,
+ NVRenderTextureFormats::Enum inFormat);
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation);
+
+private:
+ void CreateLevel0Tex(void *inTextureData, int inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat);
+
+ NVScopedRefCounted<NVRenderShaderProgram> m_BSDFProgram;
+ NVScopedRefCounted<NVRenderShaderProgram> m_UploadProgram_RGBA8;
+ NVScopedRefCounted<NVRenderShaderProgram> m_UploadProgram_RGB8;
+ NVScopedRefCounted<NVRenderTexture2D> m_Level0Tex;
+ bool m_TextureCreated;
+
+ void createComputeProgram(NVRenderContext *context);
+ NVRenderShaderProgram *getOrCreateUploadComputeProgram(NVRenderContext *context,
+ NVRenderTextureFormats::Enum inFormat);
+};
+
+#endif
diff --git a/src/Runtime/Source/HDR/Include/HDR.h b/src/Runtime/Source/HDR/Include/HDR.h
new file mode 100644
index 00000000..fbc4ea41
--- /dev/null
+++ b/src/Runtime/Source/HDR/Include/HDR.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef HDR_H
+#define HDR_H
+
+#include "foundation/Qt3DSVec3.h"
+//#include "HDR.h"
+
+namespace qt3ds {
+class QT3DSVec3;
+
+namespace HDR {
+
+ template <int N>
+ class HDRConfiguration;
+
+ template <int N>
+ class Histogram
+ {
+ public:
+ /**
+ * @brief build the histogram based on 2^10 binning.
+ *
+ * @param[in] inImage Pointer to image
+ * @param[in] inWidth Width of image
+ * @param[in] inHeight Height of image
+ * @param[out] outHistogram
+ *
+ * @return No return
+ */
+ static void Build(QT3DSVec3 *inImage, int inWidth, int inHeight, QT3DSVec3 *outHistogram)
+ {
+ long noPixels = inWidth * inHeight;
+
+ for (int i = 0; i < noPixels; ++i) {
+ outHistogram[(int)inImage[i].x].x++;
+ outHistogram[(int)inImage[i].y].y++;
+ outHistogram[(int)inImage[i].z].z++;
+ }
+ }
+ };
+
+ template <int N>
+ class HDR
+ {
+
+ public:
+ HDR(HDRConfiguration<N> *inConfiguration) { mHDRConfiguration = inConfiguration; }
+
+ void Build(QT3DSVec3 **inImages, int inNoImages, int inWidth, int inHeight, float *inExposures,
+ QT3DSVec3 *outRadiance)
+ {
+ for (int x = 0; x < inWidth; ++x) {
+ for (int y = 0; y < inHeight; ++y) {
+ QT3DSVec3 divisor(0.0f);
+ QT3DSVec3 dividend(0.0f);
+ for (int i = 0; i < inNoImages; ++i) {
+ QT3DSVec3 pixel = inImages[i][x + y * inWidth];
+
+ dividend += (LUT(mHDRConfiguration->weights, pixel) * inExposures[i])
+ .multiply(LUT(mHDRConfiguration->CRF, pixel));
+ divisor += LUT(mHDRConfiguration->weights, pixel) * inExposures[i]
+ * inExposures[i];
+ }
+ divisor.x = 1.0f / divisor.x;
+ divisor.y = 1.0f / divisor.y;
+ divisor.z = 1.0f / divisor.z;
+
+ outRadiance[x + y * inWidth] = dividend.multiply(divisor);
+ }
+ }
+ }
+
+ private:
+ /**
+ * @brief Return the value based off from array as a LUT
+ *
+ * @param[in] inLUT The LUT table of interest
+ * @param[in] inValue The value that you have
+ * @param[out] QT3DSVec3 The corresponding value of array based on input
+ * tuple
+ *
+ * @return No return
+ */
+ QT3DSVec3 LUT(float *inLUT, QT3DSVec3 inValue)
+ {
+ return QT3DSVec3(inLUT[(int)inValue.x], inLUT[(int)inValue.y], inLUT[(int)inValue.z]);
+ }
+
+ QT3DSVec3 LUT(QT3DSVec3 *inLUT, QT3DSVec3 inValue)
+ {
+ return QT3DSVec3(inLUT[(int)inValue.x].x, inLUT[(int)inValue.y].y,
+ inLUT[(int)inValue.z].z);
+ }
+
+ HDRConfiguration<N> *mHDRConfiguration;
+ };
+
+ template <int N>
+ class HDRConfiguration
+ {
+ public:
+ HDRConfiguration()
+ {
+ threshold = 0.1f;
+ maxIterations = 30;
+ GenerateRobertsonWeighting();
+ }
+
+ void SetCRF(QT3DSVec3 *inCRF) { memcpy(CRF, inCRF, sizeof(QT3DSVec3) * N); }
+
+ /**
+ * @brief build the camera response function
+ *
+ * @param[in] inImages Pointer to images
+ * @param[in] inNoImages Number of images
+ * @param[in] inWidth Width of image
+ * @param[in] inHeight Height of image
+ * @param[out] outHistogram
+ *
+ * @return No return
+ */
+ void BuildCRF(QT3DSVec3 **inImages, int inNoImages, int inWidth, int inHeight,
+ float *inExposures)
+ {
+ QT3DSVec3 histogram[N];
+ QT3DSVec3 newCRF[N];
+
+ HDR<N> hdr(this);
+
+ memset(histogram, 0, sizeof(QT3DSVec3) * N);
+
+ for (int i = 0; i < inNoImages; ++i) {
+ Histogram<N>::Build(inImages[i], inWidth, inHeight, histogram);
+ }
+
+ for (int i = 0; i < N; ++i) {
+ histogram[i].x = histogram[i].x > 0 ? 1 / histogram[i].x : 0;
+ histogram[i].y = histogram[i].y > 0 ? 1 / histogram[i].y : 0;
+ histogram[i].z = histogram[i].z > 0 ? 1 / histogram[i].z : 0;
+ }
+
+ QT3DSVec3 *radiance = new QT3DSVec3[inWidth * inHeight * sizeof(QT3DSVec3)];
+
+ // iteration 0, linearize CRF
+ for (int i = 0; i < N; ++i) {
+ CRF[i] = QT3DSVec3((float)i) * 2.0f / N;
+ }
+
+ for (int iteration = 0; iteration < maxIterations; ++iteration) {
+ hdr.Build(inImages, inNoImages, inWidth, inHeight, inExposures, radiance);
+
+ memset(newCRF, 0, sizeof(QT3DSVec3) * N);
+
+ for (int i = 0; i < inNoImages; ++i) {
+ for (int x = 0; x < inWidth; ++x) {
+ for (int y = 0; y < inHeight; ++y) {
+ long offset = x + y * inWidth;
+ QT3DSVec3 pixel = inImages[i][offset];
+ newCRF[(int)pixel.x].x += (inExposures[i] * radiance[offset].x);
+ newCRF[(int)pixel.y].y += (inExposures[i] * radiance[offset].y);
+ newCRF[(int)pixel.z].z += (inExposures[i] * radiance[offset].z);
+ }
+ }
+ }
+
+ float difference = 0;
+ for (int i = 0; i < N; ++i) {
+ newCRF[i] = newCRF[i].multiply(histogram[i]);
+ }
+
+ QT3DSVec3 middle = newCRF[N / 2];
+ for (int i = 0; i < N; ++i) {
+ newCRF[i].x = newCRF[i].x / middle.x;
+ newCRF[i].y = newCRF[i].y / middle.y;
+ newCRF[i].z = newCRF[i].z / middle.z;
+ difference += (CRF[i] - newCRF[i]).magnitude();
+ }
+ for (int i = 0; i < N; ++i) {
+ CRF[i] = newCRF[i];
+ }
+ if (difference < threshold) {
+ break;
+ }
+ }
+ delete[] radiance;
+ }
+
+ float weights[N];
+ QT3DSVec3 CRF[N];
+
+ private:
+ void GenerateRobertsonWeighting()
+ {
+ // Dynamic Range Improvement Through Multiple Exposures (5)
+ // gaussian random weighting
+ float divisor = (N - 1) * (N - 1) / 4.0;
+ for (int i = 0; i < N; ++i) {
+ float dividend = (i - (N - 1) / 2.0f);
+ dividend *= dividend;
+ weights[i] = exp(-4.0f * dividend / divisor);
+ }
+ }
+
+ int maxIterations;
+ float threshold;
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/HDR/Include/MipmapBSDF.h b/src/Runtime/Source/HDR/Include/MipmapBSDF.h
new file mode 100644
index 00000000..7682f897
--- /dev/null
+++ b/src/Runtime/Source/HDR/Include/MipmapBSDF.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MIPMAPBSDF_H
+#define MIPMAPBSDF_H
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/backends/gl/Qt3DSOpenGLUtil.h"
+
+#include "UICRenderLoadedTexture.h"
+
+#include "UICTypes.h"
+#ifdef _LINUXPLATFORM
+#define __declspec(dllexport)
+#define __cdecl
+
+#endif
+using namespace qt3ds::render;
+using namespace uic::render;
+
+class BSDFMipMap : public NVRefCounted
+{
+public:
+ BSDFMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture, NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+ virtual ~BSDFMipMap();
+
+ virtual void Build(void *inTextureData, int inTextureDataSize,
+ NVRenderBackend::NVRenderBackendTextureObject inTextureHandle,
+ NVRenderTextureFormats::Enum inFormat) = 0;
+ static BSDFMipMap *Create(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+
+protected:
+ volatile QT3DSI32 mRefCount; ///< reference count
+ NVFoundationBase &m_Foundation; ///< Foundation class for allocations and other base things
+
+ NVRenderTexture2D &m_Texture2D;
+ NVRenderTextureFormats::Enum m_InternalFormat;
+ NVRenderTextureFormats::Enum m_DestinationFormat;
+ int m_Width;
+ int m_Height;
+ int m_MaxMipMapLevel;
+ int m_SizeOfFormat;
+ int m_SizeOfInternalFormat;
+ int m_InternalNoOfComponent;
+ int m_NoOfComponent;
+ NVRenderContext *m_NVRenderContext;
+};
+
+class BasicBSDFMipMap : public BSDFMipMap
+{
+public:
+ BasicBSDFMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture, NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+
+ void Build(void *inTextureData, int inTextureDataSize,
+ NVRenderBackend::NVRenderBackendTextureObject inTextureHandle,
+ NVRenderTextureFormats::Enum inFormat);
+
+ STextureData CreateBsdfMipLevel(STextureData &inCurMipLevel, STextureData &inPrevMipLevel,
+ int width, int height); //, IPerfTimer& inPerfTimer );
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation);
+
+ int wrapMod(int a, int base);
+ void getWrappedCoords(int &sX, int &sY, int width, int height);
+ NVRenderBackend::NVRenderBackendTextureObject m_TextureHandle;
+};
+
+#endif
diff --git a/src/Runtime/Source/HDR/Source/CUDABSDFMipmap.cpp b/src/Runtime/Source/HDR/Source/CUDABSDFMipmap.cpp
new file mode 100644
index 00000000..94f6712f
--- /dev/null
+++ b/src/Runtime/Source/HDR/Source/CUDABSDFMipmap.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef PLATFORM_HAS_CUDA
+
+#include "CUDABSDFMipmap.h"
+#include "cuda.h"
+#include "cuda_runtime.h"
+#include "cuda_gl_interop.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "nv_log.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+
+__host__ void jerror1(cudaError error);
+#ifdef _DEBUG
+#define CHECK_AND_HANDLE_CUDA_ERROR(func) \
+ func; \
+ { \
+ cudaError error = cudaGetLastError(); \
+ if (error != cudaSuccess) { \
+ printf("%s\n", cudaGetErrorString(error)); \
+ jerror1(error); \
+ QT3DS_ASSERT(false); \
+ } \
+ }
+#else
+#define CHECK_AND_HANDLE_CUDA_ERROR(func) func;
+#endif
+
+CUDABSDFMipMap::CUDABSDFMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat, NVFoundationBase &inFnd)
+ : BSDFMipMap(inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd)
+ , m_TextureBinded(false)
+{
+
+ // CHECK_AND_HANDLE_CUDA_ERROR( cudaFree( 0 ); )
+ m_Pitches = (size_t *)QT3DS_ALLOC(m_Foundation.getAllocator(),
+ sizeof(size_t) * m_MaxMipMapLevel + 1, "BSDF MipMap pitches");
+ md_MipMapsData = (void **)QT3DS_ALLOC(m_Foundation.getAllocator(),
+ sizeof(void *) * m_MaxMipMapLevel + 1, "BSDF MipMap data");
+ // CHECK_AND_HANDLE_CUDA_ERROR();
+ size_t imagePitch;
+ int width = m_Width;
+ int height = m_Height;
+
+ for (int i = 0; i <= m_MaxMipMapLevel; ++i) {
+ imagePitch = m_SizeOfFormat * width;
+ // checkCudaErrors(cudaMalloc((void **)&cuda_dest_resource[mip], size_tex_data));
+ CHECK_AND_HANDLE_CUDA_ERROR(
+ cudaMallocPitch((void **)&md_MipMapsData[i], &m_Pitches[i], imagePitch, height);)
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaMemset(md_MipMapsData[i], -1, m_Pitches[i] * height);)
+
+ width = width > 2 ? width >> 1 : 1;
+ height = height > 2 ? height >> 1 : 1;
+ }
+}
+
+CUDABSDFMipMap::~CUDABSDFMipMap()
+{
+ // CHECK_AND_HANDLE_CUDA_ERROR( cudaDeviceReset(); )
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaDeviceSynchronize();)
+ for (int i = 0; i <= m_MaxMipMapLevel; ++i) {
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaFree(md_MipMapsData[i]);)
+ }
+ QT3DS_FREE(m_Foundation.getAllocator(), md_MipMapsData);
+ QT3DS_FREE(m_Foundation.getAllocator(), m_Pitches);
+}
+
+void CUDABSDFMipMap::BindTexture()
+{
+ if (!m_TextureBinded) {
+ m_TextureBinded = true;
+
+ int width = m_Width;
+ int height = m_Height;
+ for (int i = 0; i <= m_MaxMipMapLevel; ++i) {
+ // if you wwant to change some texture filter settings use m_Texture2D object
+ m_Texture2D.SetTextureData(NVDataRef<QT3DSU8>(), (QT3DSU8)i, width, height,
+ NVRenderTextureFormats::RGBA16F,
+ NVRenderTextureFormats::RGBA16F);
+
+ width = width > 2 ? width >> 1 : 1;
+ height = height > 2 ? height >> 1 : 1;
+ }
+ // CHECK_AND_HANDLE_CUDA_ERROR( cudaGraphicsGLRegisterImage( &m_CudaMipMapResource,
+ // (GLuint)m_TextureHandle, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard |
+ // cudaGraphicsRegisterFlagsTextureGather) )
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaGraphicsGLRegisterImage(
+ &m_CudaMipMapResource, (GLuint)m_TextureHandle, GL_TEXTURE_2D,
+ cudaGraphicsRegisterFlagsWriteDiscard | cudaGraphicsRegisterFlagsTextureGather))
+ }
+}
+
+void CUDABSDFMipMap::TransferTexture() // after cuda generation
+{
+ cudaArray *texturePtr;
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaGraphicsMapResources(1, &m_CudaMipMapResource, 0))
+ int width = m_Width;
+ int height = m_Height;
+ for (int i = 0; i <= m_MaxMipMapLevel; ++i) {
+ CHECK_AND_HANDLE_CUDA_ERROR(
+ cudaGraphicsSubResourceGetMappedArray(&texturePtr, m_CudaMipMapResource, 0, i))
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaMemcpy2DToArray(texturePtr, 0, 0, md_MipMapsData[i],
+ m_Pitches[i], width * m_SizeOfFormat,
+ height, cudaMemcpyDeviceToDevice));
+
+ width = width > 2 ? width >> 1 : 1;
+ height = height > 2 ? height >> 1 : 1;
+ }
+ CHECK_AND_HANDLE_CUDA_ERROR(cudaGraphicsUnmapResources(1, &m_CudaMipMapResource, 0))
+}
+
+#endif
diff --git a/src/Runtime/Source/HDR/Source/GLComputeMipmap.cpp b/src/Runtime/Source/HDR/Source/GLComputeMipmap.cpp
new file mode 100644
index 00000000..36b550dd
--- /dev/null
+++ b/src/Runtime/Source/HDR/Source/GLComputeMipmap.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "GLComputeMipMap.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "nv_log.h"
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+
+static const char *computeUploadShader(std::string &prog, NVRenderTextureFormats::Enum inFormat,
+ bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "precision mediump image2D;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ if (inFormat == NVRenderTextureFormats::RGBA8) {
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (rgba8, binding = 1) uniform image2D inputImage;\n\n"
+ "layout (rgba16f, binding = 2) uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " if ( gl_GlobalInvocationID.x >= gl_NumWorkGroups.x || gl_GlobalInvocationID.y "
+ ">= gl_NumWorkGroups.y )\n"
+ " return;\n"
+ " vec4 value = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.xy));\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), value );\n"
+ "}\n";
+ } else {
+ prog += "float convertToFloat( in uint inValue )\n"
+ "{\n"
+ " uint v = inValue & uint(0xFF);\n"
+ " float f = float(v)/256.0;\n"
+ " return f;\n"
+ "}\n";
+
+ prog += "int getMod( in int inValue, in int mod )\n"
+ "{\n"
+ " int v = mod * (inValue/mod);\n"
+ " return inValue - v;\n"
+ "}\n";
+
+ prog += "vec4 getRGBValue( in int byteNo, vec4 inVal, vec4 inVal1 )\n"
+ "{\n"
+ " vec4 result= vec4(0.0);\n"
+ " if( byteNo == 0) {\n"
+ " result.r = inVal.r;\n"
+ " result.g = inVal.g;\n"
+ " result.b = inVal.b;\n"
+ " }\n"
+ " else if( byteNo == 1) {\n"
+ " result.r = inVal.g;\n"
+ " result.g = inVal.b;\n"
+ " result.b = inVal.a;\n"
+ " }\n"
+ " else if( byteNo == 2) {\n"
+ " result.r = inVal.b;\n"
+ " result.g = inVal.a;\n"
+ " result.b = inVal1.r;\n"
+ " }\n"
+ " else if( byteNo == 3) {\n"
+ " result.r = inVal.a;\n"
+ " result.g = inVal1.r;\n"
+ " result.b = inVal1.g;\n"
+ " }\n"
+ " return result;\n"
+ "}\n";
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (rgba8, binding = 1) uniform image2D inputImage;\n\n"
+ "layout (rgba16f, binding = 2) uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " vec4 result = vec4(0.0);\n"
+ " if ( gl_GlobalInvocationID.x >= gl_NumWorkGroups.x || gl_GlobalInvocationID.y "
+ ">= gl_NumWorkGroups.y )\n"
+ " return;\n"
+ " int xpos = (int(gl_GlobalInvocationID.x)*3)/4;\n"
+ " int xmod = getMod(int(gl_GlobalInvocationID.x)*3, 4);\n"
+ " ivec2 readPos = ivec2(xpos, gl_GlobalInvocationID.y);\n"
+ " vec4 value = imageLoad(inputImage, readPos);\n"
+ " vec4 value1 = imageLoad(inputImage, ivec2(readPos.x + 1, readPos.y));\n"
+ " result = getRGBValue( xmod, value, value1);\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), result );\n"
+ "}\n";
+ }
+ return prog.c_str();
+}
+
+static const char *computeWorkShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "precision mediump image2D;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ prog += "int wrapMod( in int a, in int base )\n"
+ "{\n"
+ " return ( a >= 0 ) ? a % base : -(a % base) + base;\n"
+ "}\n";
+
+ prog += "void getWrappedCoords( inout int sX, inout int sY, in int width, in int height )\n"
+ "{\n"
+ " if (sY < 0) { sX -= width >> 1; sY = -sY; }\n"
+ " if (sY >= height) { sX += width >> 1; sY = height - sY; }\n"
+ " sX = wrapMod( sX, width );\n"
+ "}\n";
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (rgba16f, binding = 1) uniform image2D inputImage;\n\n"
+ "layout (rgba16f, binding = 2) uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " int prevWidth = int(gl_NumWorkGroups.x) << 1;\n"
+ " int prevHeight = int(gl_NumWorkGroups.y) << 1;\n"
+ " if ( gl_GlobalInvocationID.x >= gl_NumWorkGroups.x || gl_GlobalInvocationID.y >= "
+ "gl_NumWorkGroups.y )\n"
+ " return;\n"
+ " vec4 accumVal = vec4(0.0);\n"
+ " for ( int sy = -2; sy <= 2; ++sy )\n"
+ " {\n"
+ " for ( int sx = -2; sx <= 2; ++sx )\n"
+ " {\n"
+ " int sampleX = sx + (int(gl_GlobalInvocationID.x) << 1);\n"
+ " int sampleY = sy + (int(gl_GlobalInvocationID.y) << 1);\n"
+ " getWrappedCoords(sampleX, sampleY, prevWidth, prevHeight);\n"
+ " if ((sampleY * prevWidth + sampleX) < 0 )\n"
+ " sampleY = prevHeight + sampleY;\n"
+ " ivec2 pos = ivec2(sampleX, sampleY);\n"
+ " vec4 value = imageLoad(inputImage, pos);\n"
+ " float filterPdf = 1.0 / ( 1.0 + float(sx*sx + sy*sy)*2.0 );\n"
+ " filterPdf /= 4.71238898;\n"
+ " accumVal[0] += filterPdf * value.r;\n"
+ " accumVal[1] += filterPdf * value.g;\n"
+ " accumVal[2] += filterPdf * value.b;\n"
+ " accumVal[3] += filterPdf * value.a;\n"
+ " }\n"
+ " }\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), accumVal );\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+GLComputeMipMap::GLComputeMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat, NVFoundationBase &inFnd)
+ : BSDFMipMap(inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd)
+ , m_BSDFProgram(NULL)
+ , m_UploadProgram_RGBA8(NULL)
+ , m_UploadProgram_RGB8(NULL)
+ , m_Level0Tex(NULL)
+ , m_TextureCreated(false)
+{
+}
+
+GLComputeMipMap::~GLComputeMipMap()
+{
+ m_UploadProgram_RGB8 = NULL;
+ m_UploadProgram_RGBA8 = NULL;
+ m_BSDFProgram = NULL;
+ m_Level0Tex = NULL;
+}
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+static bool isGLESContext(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+
+ // Need minimum of GL3 or GLES3
+ if (ctxType == NVRenderContextValues::GLES2 || ctxType == NVRenderContextValues::GLES3
+ || ctxType == NVRenderContextValues::GLES31) {
+ return true;
+ }
+
+ return false;
+}
+
+#define WORKGROUP_SIZE 16
+
+void GLComputeMipMap::createComputeProgram(NVRenderContext *context)
+{
+ std::string computeProg;
+
+ if (!m_BSDFProgram) {
+ m_BSDFProgram = context
+ ->CompileComputeSource(
+ "Compute BSDF mipmap shader",
+ toRef(computeWorkShader(computeProg, isGLESContext(context))))
+ .mShader;
+ }
+}
+
+NVRenderShaderProgram *
+GLComputeMipMap::getOrCreateUploadComputeProgram(NVRenderContext *context,
+ NVRenderTextureFormats::Enum inFormat)
+{
+ std::string computeProg;
+
+ if (inFormat == NVRenderTextureFormats::RGB8) {
+ if (!m_UploadProgram_RGB8) {
+ m_UploadProgram_RGB8 =
+ context
+ ->CompileComputeSource(
+ "Compute BSDF mipmap level 0 RGB8 shader",
+ toRef(computeUploadShader(computeProg, inFormat, isGLESContext(context))))
+ .mShader;
+ }
+
+ return m_UploadProgram_RGB8;
+ } else {
+ if (!m_UploadProgram_RGBA8) {
+ m_UploadProgram_RGBA8 =
+ context
+ ->CompileComputeSource(
+ "Compute BSDF mipmap level 0 RGBA8 shader",
+ toRef(computeUploadShader(computeProg, inFormat, isGLESContext(context))))
+ .mShader;
+ }
+
+ return m_UploadProgram_RGBA8;
+ }
+}
+
+void GLComputeMipMap::CreateLevel0Tex(void *inTextureData, int inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat)
+{
+ NVRenderTextureFormats::Enum theFormat = inFormat;
+ int theWidth = m_Width;
+
+ // Since we cannot use RGB format in GL compute
+ // we treat it as a RGBA component format
+ if (inFormat == NVRenderTextureFormats::RGB8) {
+ // This works only with 4 byte aligned data
+ QT3DS_ASSERT(m_Width % 4 == 0);
+ theFormat = NVRenderTextureFormats::RGBA8;
+ theWidth = (m_Width * 3) / 4;
+ }
+
+ if (m_Level0Tex == NULL) {
+ m_Level0Tex = m_NVRenderContext->CreateTexture2D();
+ m_Level0Tex->SetTextureStorage(1, theWidth, m_Height, theFormat, theFormat,
+ NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize));
+ } else {
+ m_Level0Tex->SetTextureSubData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
+ 0, 0, theWidth, m_Height, theFormat);
+ }
+}
+
+void GLComputeMipMap::Build(void *inTextureData, int inTextureDataSize,
+ NVRenderBackend::NVRenderBackendTextureObject,
+ NVRenderTextureFormats::Enum inFormat)
+{
+ bool needMipUpload = (inFormat != m_DestinationFormat);
+ // re-upload data
+ if (!m_TextureCreated) {
+ m_Texture2D.SetTextureStorage(
+ m_MaxMipMapLevel + 1, m_Width, m_Height, m_DestinationFormat, inFormat, (needMipUpload)
+ ? NVDataRef<QT3DSU8>()
+ : NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize));
+ m_Texture2D.addRef();
+ // create a compute shader (if not aloread done) which computes the BSDF mipmaps for this
+ // texture
+ createComputeProgram(m_NVRenderContext);
+
+ if (!m_BSDFProgram) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ m_TextureCreated = true;
+ } else if (!needMipUpload) {
+ m_Texture2D.SetTextureSubData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
+ 0, 0, m_Width, m_Height, inFormat);
+ }
+
+ if (needMipUpload) {
+ CreateLevel0Tex(inTextureData, inTextureDataSize, inFormat);
+ }
+
+ NVScopedRefCounted<NVRenderImage2D> theInputImage;
+ NVScopedRefCounted<NVRenderImage2D> theOutputImage;
+ theInputImage =
+ m_NVRenderContext->CreateImage2D(&m_Texture2D, NVRenderImageAccessType::ReadWrite);
+ theOutputImage =
+ m_NVRenderContext->CreateImage2D(&m_Texture2D, NVRenderImageAccessType::ReadWrite);
+
+ if (needMipUpload && m_Level0Tex) {
+ NVRenderShaderProgram *uploadProg =
+ getOrCreateUploadComputeProgram(m_NVRenderContext, inFormat);
+ if (!uploadProg)
+ return;
+
+ m_NVRenderContext->SetActiveShader(uploadProg);
+
+ NVScopedRefCounted<NVRenderImage2D> theInputImage0;
+ theInputImage0 =
+ m_NVRenderContext->CreateImage2D(m_Level0Tex, NVRenderImageAccessType::ReadWrite);
+
+ theInputImage0->SetTextureLevel(0);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedinputImage0("inputImage",
+ *uploadProg);
+ theCachedinputImage0.Set(theInputImage0);
+
+ theOutputImage->SetTextureLevel(0);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedOutputImage("outputImage",
+ *uploadProg);
+ theCachedOutputImage.Set(theOutputImage);
+
+ m_NVRenderContext->DispatchCompute(uploadProg, m_Width, m_Height, 1);
+
+ // sync
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderImageAccess);
+ m_NVRenderContext->SetMemoryBarrier(flags);
+ }
+
+ int width = m_Width >> 1;
+ int height = m_Height >> 1;
+
+ m_NVRenderContext->SetActiveShader(m_BSDFProgram);
+
+ for (int i = 1; i <= m_MaxMipMapLevel; ++i) {
+ theOutputImage->SetTextureLevel(i);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedOutputImage("outputImage",
+ *m_BSDFProgram);
+ theCachedOutputImage.Set(theOutputImage);
+ theInputImage->SetTextureLevel(i - 1);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedinputImage("inputImage",
+ *m_BSDFProgram);
+ theCachedinputImage.Set(theInputImage);
+
+ m_NVRenderContext->DispatchCompute(m_BSDFProgram, width, height, 1);
+
+ width = width > 2 ? width >> 1 : 1;
+ height = height > 2 ? height >> 1 : 1;
+
+ // sync
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderImageAccess);
+ m_NVRenderContext->SetMemoryBarrier(flags);
+ }
+}
diff --git a/src/Runtime/Source/HDR/Source/HDR.cpp b/src/Runtime/Source/HDR/Source/HDR.cpp
new file mode 100644
index 00000000..9abe2b3b
--- /dev/null
+++ b/src/Runtime/Source/HDR/Source/HDR.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "HDR.h"
diff --git a/src/Runtime/Source/HDR/Source/MipmapBSDF.cpp b/src/Runtime/Source/HDR/Source/MipmapBSDF.cpp
new file mode 100644
index 00000000..fd57015e
--- /dev/null
+++ b/src/Runtime/Source/HDR/Source/MipmapBSDF.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "MipmapBSDF.h"
+#include "GLComputeMipMap.h"
+
+#ifdef PLATFORM_HAS_CUDA
+#include "cuda.h"
+#include "cuda_runtime.h"
+#include "CUDABSDFMipmap.h"
+#endif
+
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "nv_log.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+
+BSDFMipMap::BSDFMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture2D, NVRenderTextureFormats::Enum inDestFormat,
+ NVFoundationBase &inFnd)
+ : m_Foundation(inFnd)
+ , m_Texture2D(inTexture2D)
+ , m_Width(inWidth)
+ , m_Height(inHeight)
+ , m_DestinationFormat(inDestFormat)
+ , m_NVRenderContext(inNVRenderContext)
+{
+ // Calculate mip level
+ int maxDim = inWidth >= inHeight ? inWidth : inHeight;
+
+ m_MaxMipMapLevel = static_cast<int>(logf((float)maxDim) / logf(2.0f));
+ // no concept of sizeOfFormat just does'nt make sense
+ m_SizeOfFormat = NVRenderTextureFormats::getSizeofFormat(m_DestinationFormat);
+ m_NoOfComponent = NVRenderTextureFormats::getNumberOfComponent(m_DestinationFormat);
+}
+
+BSDFMipMap *BSDFMipMap::Create(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd)
+{
+ BSDFMipMap *theBSDFMipMap = NULL;
+#ifdef PLATFORM_HAS_CUDA
+ int deviceCount;
+ cudaError_t e = cudaGetDeviceCount(&deviceCount);
+#endif
+
+ if (inNVRenderContext->IsComputeSupported()) {
+ theBSDFMipMap = QT3DS_NEW(inFnd.getAllocator(), GLComputeMipMap)(
+ inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd);
+ } else
+#ifdef PLATFORM_HAS_CUDA
+ if (e == cudaSuccess && deviceCount > 0) {
+ theBSDFMipMap = QT3DS_NEW(inFnd.getAllocator(), CUDABSDFMipMap)(
+ inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd);
+ } else
+#endif
+ if (!theBSDFMipMap) {
+ theBSDFMipMap = QT3DS_NEW(inFnd.getAllocator(), BasicBSDFMipMap)(
+ inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd);
+ }
+
+ return theBSDFMipMap;
+}
+
+BasicBSDFMipMap::BasicBSDFMipMap(NVRenderContext *inNVRenderContext, int inWidth, int inHeight,
+ NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat, NVFoundationBase &inFnd)
+ : BSDFMipMap(inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd)
+{
+}
+
+BSDFMipMap::~BSDFMipMap()
+{
+}
+
+void BasicBSDFMipMap::Build(void *inTextureData, int inTextureDataSize,
+ NVRenderBackend::NVRenderBackendTextureObject,
+ NVRenderTextureFormats::Enum inFormat)
+{
+
+ m_InternalFormat = inFormat;
+ m_SizeOfInternalFormat = NVRenderTextureFormats::getSizeofFormat(m_InternalFormat);
+ m_InternalNoOfComponent = NVRenderTextureFormats::getNumberOfComponent(m_InternalFormat);
+
+ m_Texture2D.SetTextureData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
+ m_Width, m_Height, inFormat, m_DestinationFormat);
+
+ STextureData theMipImage;
+ STextureData prevImage;
+ prevImage.data = inTextureData;
+ prevImage.dataSizeInBytes = inTextureDataSize;
+ prevImage.format = inFormat;
+ int curWidth = m_Width;
+ int curHeight = m_Height;
+ int size = NVRenderTextureFormats::getSizeofFormat(m_InternalFormat);
+ for (int idx = 1; idx <= m_MaxMipMapLevel; ++idx) {
+ theMipImage =
+ CreateBsdfMipLevel(theMipImage, prevImage, curWidth, curHeight); //, m_PerfTimer );
+ curWidth = curWidth >> 1;
+ curHeight = curHeight >> 1;
+ curWidth = curWidth >= 1 ? curWidth : 1;
+ curHeight = curHeight >= 1 ? curHeight : 1;
+ inTextureDataSize = curWidth * curHeight * size;
+
+ m_Texture2D.SetTextureData(toU8DataRef((char *)theMipImage.data, (QT3DSU32)inTextureDataSize),
+ (QT3DSU8)idx, (QT3DSU32)curWidth, (QT3DSU32)curHeight, theMipImage.format,
+ m_DestinationFormat);
+
+ if (prevImage.data == inTextureData)
+ prevImage = STextureData();
+
+ STextureData temp = prevImage;
+ prevImage = theMipImage;
+ theMipImage = temp;
+ }
+ QT3DS_FREE(m_Foundation.getAllocator(), theMipImage.data);
+ QT3DS_FREE(m_Foundation.getAllocator(), prevImage.data);
+}
+
+inline int BasicBSDFMipMap::wrapMod(int a, int base)
+{
+ return (a >= 0) ? a % base : (a % base) + base;
+}
+
+inline void BasicBSDFMipMap::getWrappedCoords(int &sX, int &sY, int width, int height)
+{
+ if (sY < 0) {
+ sX -= width >> 1;
+ sY = -sY;
+ }
+ if (sY >= height) {
+ sX += width >> 1;
+ sY = height - sY;
+ }
+ sX = wrapMod(sX, width);
+}
+
+STextureData BasicBSDFMipMap::CreateBsdfMipLevel(STextureData &inCurMipLevel,
+ STextureData &inPrevMipLevel, int width,
+ int height) //, IPerfTimer& inPerfTimer )
+{
+ // SStackPerfTimer __timer( inPerfTimer, "Image BSDF Mip Level" );
+ STextureData retval;
+ int newWidth = width >> 1;
+ int newHeight = height >> 1;
+ newWidth = newWidth >= 1 ? newWidth : 1;
+ newHeight = newHeight >= 1 ? newHeight : 1;
+
+ if (inCurMipLevel.data) {
+ retval = inCurMipLevel;
+ retval.dataSizeInBytes =
+ newWidth * newHeight * NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
+ } else {
+ retval.dataSizeInBytes =
+ newWidth * newHeight * NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
+ retval.format = inPrevMipLevel.format; // inLoadedImage.format;
+ retval.data = m_Foundation.getAllocator().allocate(
+ retval.dataSizeInBytes, "Bsdf Scaled Image Data", __FILE__, __LINE__);
+ }
+
+ for (int y = 0; y < newHeight; ++y) {
+ for (int x = 0; x < newWidth; ++x) {
+ float accumVal[4];
+ accumVal[0] = 0;
+ accumVal[1] = 0;
+ accumVal[2] = 0;
+ accumVal[3] = 0;
+ for (int sy = -2; sy <= 2; ++sy) {
+ for (int sx = -2; sx <= 2; ++sx) {
+ int sampleX = sx + (x << 1);
+ int sampleY = sy + (y << 1);
+ getWrappedCoords(sampleX, sampleY, width, height);
+
+ // Cauchy filter (this is simply because it's the easiest to evaluate, and
+ // requires no complex
+ // functions).
+ float filterPdf = 1.f / (1.f + float(sx * sx + sy * sy) * 2.f);
+ // With FP HDR formats, we're not worried about intensity loss so much as
+ // unnecessary energy gain,
+ // whereas with LDR formats, the fear with a continuous normalization factor is
+ // that we'd lose
+ // intensity and saturation as well.
+ filterPdf /= (NVRenderTextureFormats::getSizeofFormat(retval.format) >= 8)
+ ? 4.71238898f
+ : 4.5403446f;
+ // filterPdf /= 4.5403446f; // Discrete normalization factor
+ // filterPdf /= 4.71238898f; // Continuous normalization factor
+ float curPix[4];
+ QT3DSI32 byteOffset = (sampleY * width + sampleX)
+ * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ if (byteOffset < 0) {
+ sampleY = height + sampleY;
+ byteOffset = (sampleY * width + sampleX)
+ * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ }
+
+ NVRenderTextureFormats::decodeToFloat(inPrevMipLevel.data, byteOffset, curPix,
+ retval.format);
+
+ accumVal[0] += filterPdf * curPix[0];
+ accumVal[1] += filterPdf * curPix[1];
+ accumVal[2] += filterPdf * curPix[2];
+ accumVal[3] += filterPdf * curPix[3];
+ }
+ }
+
+ /*
+ // Re-adjustment after the fact for the RGBD hack.
+ if (retval.format == NVRenderTextureFormats::RGBA8 || retval.format ==
+ NVRenderTextureFormats::SRGB8A8)
+ {
+ float divVal = (accumVal[0] > accumVal[1]) ? accumVal[0] : accumVal[1];
+ divVal = (divVal > accumVal[2]) ? divVal : accumVal[2];
+ if (divVal > 1.0)
+ {
+ divVal = 1.0f / divVal;
+ accumVal[0] *= divVal;
+ accumVal[1] *= divVal;
+ accumVal[2] *= divVal;
+ accumVal[3] = divVal;
+ }
+ else
+ accumVal[3] = 1.0f;
+ }
+ */
+ QT3DSU32 newIdx =
+ (y * newWidth + x) * NVRenderTextureFormats::getSizeofFormat(retval.format);
+
+ NVRenderTextureFormats::encodeToPixel(accumVal, retval.data, newIdx, retval.format);
+ }
+ }
+
+ return retval;
+}
diff --git a/src/Runtime/Source/HDR/Source/MipmapBSDF.cu b/src/Runtime/Source/HDR/Source/MipmapBSDF.cu
new file mode 100644
index 00000000..6ddac4be
--- /dev/null
+++ b/src/Runtime/Source/HDR/Source/MipmapBSDF.cu
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if defined (_PLATFORM_USE_EGL)
+#include <GLES31/gl31.h>
+#include <GLES31/gl2ext.h>
+#endif
+
+#include "CUDABSDFMipmap.h"
+#include "cuda.h"
+#include "cuda_runtime.h"
+#include "cuda_gl_interop.h"
+#include <iostream>
+
+using namespace nv;
+using namespace nv::render;
+__host__ void jerror1(cudaError error)
+{
+ static int i = 0;
+ ++i;
+}
+#ifdef _DEBUG
+#define CHECK_AND_HANDLE_CUDA_ERROR(func) \
+ func; \
+ { \
+ cudaError error = cudaGetLastError(); \
+ if ( error != cudaSuccess ) \
+ { \
+ printf("%s\n", cudaGetErrorString(error)); \
+ jerror1(error);\
+ NV_ASSERT( false ); \
+ } \
+ }
+#else
+#define CHECK_AND_HANDLE_CUDA_ERROR(func) \
+func;
+#endif
+
+__device__ inline int wrapMod( int a, int base )
+{
+ int ret = a % base;
+ if (ret < 0 ) ret += base;
+ return ret;
+}
+
+__device__ inline void getWrappedCoords( int &sX, int &sY, int width, int height )
+{
+ if (sY < 0) { sX -= width >> 1; sY = -sY; }
+ if (sY >= height) { sX += width >> 1; sY = height - sY; }
+ sX = wrapMod( sX, width );
+ sY = wrapMod( sY, height );
+}
+
+__device__ void decodeToFloat( void *inPtr, NVU32 byteOfs, float *outPtr, NVRenderTextureFormats::Enum inFmt, unsigned int numberOfComponent )
+{
+ outPtr[0] = 0.0f; outPtr[1] = 0.0f; outPtr[2] = 0.0f; outPtr[3] = 0.0f;
+ NVU8 *src = reinterpret_cast<NVU8 *>(inPtr);
+ //float divisor; // If we want to support RGBD?
+ switch(inFmt)
+ {
+ case NVRenderTextureFormats::Alpha8:
+ outPtr[0] = ((float)src[byteOfs]) / 255.0f;
+ break;
+
+ case NVRenderTextureFormats::Luminance8:
+ case NVRenderTextureFormats::LuminanceAlpha8:
+ case NVRenderTextureFormats::R8:
+ case NVRenderTextureFormats::RG8:
+ case NVRenderTextureFormats::RGB8:
+ case NVRenderTextureFormats::RGBA8:
+ case NVRenderTextureFormats::SRGB8:
+ case NVRenderTextureFormats::SRGB8A8:
+ // NOTE : RGBD Hack here for reference. Not meant for installation.
+ //divisor = (NVRenderTextureFormats::getSizeofFormat(inFmt) == 4) ? ((float)src[byteOfs+3]) / 255.0f : 1.0f;
+ for ( NVU32 i = 0; i < numberOfComponent; ++i )
+ {
+ float val = ((float)src[byteOfs + i]) / 255.0f;
+ outPtr[i] = (i < 3) ? powf(val, 0.4545454545f) : val;
+ // Assuming RGBA8 actually means RGBD (which is stupid, I know)
+ //if ( NVRenderTextureFormats::getSizeofFormat(inFmt) == 4 ) { outPtr[i] /= divisor; }
+ }
+ //outPtr[3] = divisor;
+ break;
+
+ case NVRenderTextureFormats::RGBA32F:
+ outPtr[0] = reinterpret_cast<float *>(src+byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src+byteOfs)[1];
+ outPtr[2] = reinterpret_cast<float *>(src+byteOfs)[2];
+ outPtr[3] = reinterpret_cast<float *>(src+byteOfs)[3];
+ break;
+ case NVRenderTextureFormats::RGB32F:
+ outPtr[0] = reinterpret_cast<float *>(src+byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src+byteOfs)[1];
+ outPtr[2] = reinterpret_cast<float *>(src+byteOfs)[2];
+ break;
+
+ case NVRenderTextureFormats::RGBA16F:
+ /*
+ for ( NVU32 i = 0; i < 4; ++i )
+ {
+ // NOTE : This only works on the assumption that we don't have any denormals, Infs or NaNs.
+ // Every pixel in our source image should be "regular"
+ NVU16 h = reinterpret_cast<NVU16 *>(src + byteOfs)[i];
+ NVU32 sign = (h & 0x8000) << 16;
+ NVU32 exponent = (((((h & 0x7c00) >> 10) - 15) + 127) << 23);
+ NVU32 mantissa = ((h & 0x3ff) << 13);
+ NVU32 result = sign | exponent | mantissa;
+
+ if (h == 0 || h == 0x8000) { result = 0; } // Special case for zero and negative zero
+ memcpy( reinterpret_cast<NVU32 *>(outPtr) + i, &result, 4 );
+ }*/
+
+ for ( NVU32 i = 0; i < 2; i++ )
+ {
+ // NOTE : This only works on the assumption that we don't have any denormals, Infs or NaNs.
+ // Every pixel in our source image should be "regular"
+
+ NVU32 h1 = reinterpret_cast<NVU32 *>(src + byteOfs)[i];
+
+ for ( NVU8 j = 0; j < 2; j++ )
+ {
+ NVU16 h = (h1 & (0x0000FFFF << j*16 )) >> j*16;
+ NVU32 sign = (h & 0x8000) << 16;
+ NVU32 exponent = (((((h & 0x7c00) >> 10) - 15) + 127) << 23);
+ NVU32 mantissa = ((h & 0x3ff) << 13);
+ NVU32 result = sign | exponent | mantissa;
+
+ if (h == 0 || h == 0x8000) { result = 0; } // Special case for zero and negative zero
+ memcpy( reinterpret_cast<NVU32 *>(outPtr) + i*2 + j, &result, 4 );
+ }
+ }
+ break;
+
+ case NVRenderTextureFormats::R11G11B10:
+ // place holder
+ NV_ASSERT( false );
+ break;
+
+ default:
+ outPtr[0] = 0.0f;
+ outPtr[1] = 0.0f;
+ outPtr[2] = 0.0f;
+ outPtr[3] = 0.0f;
+ break;
+ }
+}
+
+void __device__ encodeToPixel( float *inPtr, void *outPtr, NVU32 byteOfs, NVRenderTextureFormats::Enum inFmt, unsigned int noOfComponent )
+{
+ NVU8 *dest = reinterpret_cast<NVU8 *>(outPtr);
+ switch(inFmt)
+ {
+ case NVRenderTextureFormats::Alpha8:
+ dest[byteOfs] = NVU8( inPtr[0] * 255.0f );
+ break;
+
+ case NVRenderTextureFormats::Luminance8:
+ case NVRenderTextureFormats::LuminanceAlpha8:
+ case NVRenderTextureFormats::R8:
+ case NVRenderTextureFormats::RG8:
+ case NVRenderTextureFormats::RGB8:
+ case NVRenderTextureFormats::RGBA8:
+ case NVRenderTextureFormats::SRGB8:
+ case NVRenderTextureFormats::SRGB8A8:
+ for ( NVU32 i = 0; i < noOfComponent; ++i )
+ {
+ inPtr[i] = (inPtr[i] > 1.0f) ? 1.0f : inPtr[i];
+ if (i < 3)
+ dest[byteOfs+i] = NVU8( powf( inPtr[i], 2.2f ) * 255.0f);
+ else
+ dest[byteOfs+i] = NVU8( inPtr[i] * 255.0f );
+ }
+ break;
+
+ case NVRenderTextureFormats::RGBA32F:
+ reinterpret_cast<float *>(dest+byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest+byteOfs)[1] = inPtr[1];
+ reinterpret_cast<float *>(dest+byteOfs)[2] = inPtr[2];
+ reinterpret_cast<float *>(dest+byteOfs)[3] = inPtr[3];
+ break;
+ case NVRenderTextureFormats::RGB32F:
+ reinterpret_cast<float *>(dest+byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest+byteOfs)[1] = inPtr[1];
+ reinterpret_cast<float *>(dest+byteOfs)[2] = inPtr[2];
+ break;
+
+ case NVRenderTextureFormats::RGBA16F:
+ for ( NVU32 i = 0; i < 4; ++i )
+ {
+ // NOTE : This also has the limitation of not handling infs, NaNs and denormals, but it should be
+ // sufficient for our purposes.
+ if (inPtr[i] > 65519.0f) { inPtr[i] = 65519.0f; }
+ if (fabs(inPtr[i]) < 6.10352E-5f) { inPtr[i] = 0.0f; }
+ NVU32 f = reinterpret_cast<NVU32 *>(inPtr)[i];
+ NVU32 sign = (f & 0x80000000) >> 16;
+ NVI32 exponent = (f & 0x7f800000) >> 23;
+ NVU32 mantissa = (f >> 13) & 0x3ff;
+ exponent = exponent - 112;
+ if (exponent > 31) { exponent = 31; }
+ if (exponent < 0) { exponent = 0; }
+ exponent = exponent << 10;
+ reinterpret_cast<NVU16 *>(dest + byteOfs)[i] = NVU16(sign | exponent | mantissa);
+ }
+ break;
+
+ case NVRenderTextureFormats::R11G11B10:
+ // place holder
+ NV_ASSERT( false );
+ break;
+
+ default:
+ dest[byteOfs] = 0;
+ dest[byteOfs+1] = 0;
+ dest[byteOfs+2] = 0;
+ dest[byteOfs+3] = 0;
+ break;
+ }
+}
+
+void __global__ Convert3To4Component( cudaTextureObject_t tex, float *d_outBuffer, Q3DStudio::INT32 dpitch, Q3DStudio::INT32 width, Q3DStudio::INT32 height )
+{
+ float *dest = d_outBuffer;
+
+ int x = threadIdx.x + blockIdx.x * blockDim.x;
+ int y = threadIdx.y + blockIdx.y * blockDim.y;
+ if ( x >= width || y >= height )
+ return;
+ int inX = x * 3;
+ int outX = x * 4;
+ dest[outX + y * width * 4] = tex2D<float>(tex, inX, y);
+ dest[outX + y * width * 4 + 1] = tex2D<float>(tex, inX + 1, y);
+ dest[outX + y * width * 4 + 2] = tex2D<float>(tex, inX + 2, y);
+ dest[outX + y * width * 4 + 3] = 255 * 255;
+}
+
+void __global__ ConvertData( void* d_InBuffer, NVRenderTextureFormats::Enum inFmt, int inSizeOfFormat, int inNoOfComponent, int inPitch,
+ void* d_OutBuffer, NVRenderTextureFormats::Enum outFmt, int outSizeOfFormat, int outNoOfComponent, int outPitch, int width, int height )
+{
+
+ int x = threadIdx.x + blockIdx.x * blockDim.x;
+ int y = threadIdx.y + blockIdx.y * blockDim.y;
+ if ( x >= width || y >= height )
+ return;
+ float values[4];
+
+ decodeToFloat( d_InBuffer, (inPitch * y) + (x * inSizeOfFormat), values, inFmt, inNoOfComponent );
+ encodeToPixel( values, d_OutBuffer, (outPitch * y) + (x * outSizeOfFormat), outFmt, outSizeOfFormat );
+}
+
+void __global__ CreateBsdfMipLevel( cudaTextureObject_t tex, void *d_curBuffer, void *d_prevBuffer, Q3DStudio::INT32 pitch, Q3DStudio::INT32 width, Q3DStudio::INT32 height,
+ nv::render::NVRenderTextureFormats::Enum inFormat, unsigned int sizeOfFormat )
+{
+ float accumVal[4];
+ //unsigned int sizeofFormat = getSizeofFormat(inFormat);
+ //__shared__ float dataBlock[ ]; //(32+4) * (32+4) * 12
+ int x = threadIdx.x + blockIdx.x * blockDim.x;
+ int y = threadIdx.y + blockIdx.y * blockDim.y;
+
+ if ( x >= (width > 2 ? width >> 1 : 1) || y >= (height > 2 ? height >> 1 : 1)) return;
+
+ accumVal[0] = 0; accumVal[1] = 0; accumVal[2] = 0; accumVal[3] = 0;
+
+ for ( int sy = -2; sy <= 2; ++sy )
+ {
+ for ( int sx = -2; sx <= 2; ++sx )
+ {
+ int sampleX = sx + (x << 1);
+ int sampleY = sy + (y << 1);
+ //getWrappedCoords(sampleX, sampleY, width, height);
+ // Cauchy filter (this is simply because it's the easiest to evaluate, and requires no complex
+ // functions).
+ float filterPdf = 1.f / ( 1.f + float(sx*sx + sy*sy)*2.f );
+ // With FP HDR formats, we're not worried about intensity loss so much as unnecessary energy gain,
+ // whereas with LDR formats, the fear with a continuous normalization factor is that we'd lose
+ // intensity and saturation as well.
+ filterPdf /= sizeOfFormat >= 8 ? 4.71238898f : 4.5403446f;
+ //filterPdf /= 4.5403446f; // Discrete normalization factor
+ //filterPdf /= 4.71238898f; // Continuous normalization factor
+ //float curPix[4];
+ sampleX = sampleX*4;
+ getWrappedCoords(sampleX, sampleY, width*4, height);
+ accumVal[0] += filterPdf * tex2D<float>(tex, sampleX, sampleY);
+ accumVal[1] += filterPdf * tex2D<float>(tex, sampleX + 1, sampleY);
+ accumVal[2] += filterPdf * tex2D<float>(tex, sampleX + 2, sampleY);
+ accumVal[3] += filterPdf * tex2D<float>(tex, sampleX + 3, sampleY);
+ }
+ }
+
+ encodeToPixel(accumVal, d_curBuffer, y * pitch + x * sizeOfFormat, inFormat, sizeOfFormat);
+}
+
+struct SMipTextureData
+{
+ void* data;
+ unsigned int dataSize;
+ unsigned int mipLevel;
+ unsigned int width;
+ unsigned int height;
+ NVRenderTextureFormats::Enum format;
+};
+
+__host__ void CUDABSDFMipMap::Build( void* inTextureData, int inTextureDataSize, NVRenderBackend::NVRenderBackendTextureObject inTextureHandle, NVRenderTextureFormats::Enum inFormat )
+{
+ m_TextureHandle = inTextureHandle;
+ m_InternalFormat = inFormat;
+ m_SizeOfInternalFormat = NVRenderTextureFormats::getSizeofFormat( m_InternalFormat );
+ m_InternalNoOfComponent = NVRenderTextureFormats::getNumberOfComponent( m_InternalFormat );
+
+ m_Texture2D.SetTextureData( NVDataRef<NVU8>( (NVU8*)inTextureData, inTextureDataSize )
+ , 0
+ , m_Width
+ , m_Height
+ , inFormat
+ , m_DestinationFormat );
+
+ size_t pitch;
+ float* d_inTextureData;
+
+ cudaMallocPitch(&d_inTextureData, &pitch, m_Width * m_SizeOfInternalFormat, m_Height); CHECK_AND_HANDLE_CUDA_ERROR();
+ CHECK_AND_HANDLE_CUDA_ERROR( cudaMemcpy2D( d_inTextureData, pitch, inTextureData, m_Width * m_SizeOfInternalFormat, m_Width * m_SizeOfInternalFormat, m_Height, cudaMemcpyHostToDevice ) );
+ {
+ dim3 blockDim(16, 16, 1);
+ dim3 gridDim(ceil(m_Width / 16.0f), ceil(m_Height / 16.0f) ,1 );
+
+ //std::cerr << "if= " << m_InternalFormat << " sizeOut= " << m_SizeOfInternalFormat << " numOfIntComp" << m_InternalNoOfComponent << " pitch= " << pitch << " destFormat= " << m_DestinationFormat << " sizeFormat= " << m_SizeOfFormat << " numOfComp= " << m_NoOfComponent << " Pitch0=" << m_Pitches[0] << std::endl;
+ //NVLogWarn("cuda", "%i %i %i %i %i %i %i %i\n",(int)m_InternalFormat ,m_SizeOfInternalFormat ,m_InternalNoOfComponent , pitch, (int)m_DestinationFormat, m_SizeOfFormat, m_NoOfComponent ,m_Pitches[0]);
+ ConvertData<<<gridDim, blockDim>>>( d_inTextureData, m_InternalFormat, m_SizeOfInternalFormat, m_InternalNoOfComponent, pitch,
+ md_MipMapsData[0], m_DestinationFormat, m_SizeOfFormat, m_NoOfComponent, m_Pitches[0], m_Width, m_Height );
+ }
+ cudaFree(d_inTextureData);
+
+ int curWidth = m_Width;
+ int curHeight = m_Height;
+
+ cudaTextureObject_t* tex;
+ tex = new cudaTextureObject_t[m_MaxMipMapLevel];
+ for ( int idx = 1; idx <= m_MaxMipMapLevel; ++idx )
+ {
+ tex[idx-1] = -1;
+ dim3 blockDim(16, 16, 1);
+ dim3 gridDim(ceil(curWidth / 32.0f), ceil(curHeight / 32.0f) ,1 );
+
+ cudaResourceDesc resDesc;
+ memset(&resDesc, 0, sizeof(resDesc));
+ resDesc.res.pitch2D.desc.f = cudaChannelFormatKindFloat;
+ resDesc.res.pitch2D.desc.x = m_SizeOfFormat / m_NoOfComponent * 8; // bits per channel
+ resDesc.resType = cudaResourceTypePitch2D;
+ resDesc.res.pitch2D.devPtr = (char*)(md_MipMapsData[idx-1]);
+ resDesc.res.pitch2D.height = curHeight;
+ resDesc.res.pitch2D.width = curWidth * m_NoOfComponent;
+ resDesc.res.pitch2D.pitchInBytes = m_Pitches[idx-1];// aligned to texturePitchAlignment
+
+ cudaTextureDesc texDesc;
+ memset(&texDesc, 0, sizeof(texDesc));
+ texDesc.addressMode[0] = cudaAddressModeWrap;
+ texDesc.addressMode[1] = cudaAddressModeWrap;
+ texDesc.readMode = cudaReadModeElementType;
+ //texDesc.normalizedCoords = 1;
+
+
+ CHECK_AND_HANDLE_CUDA_ERROR( cudaCreateTextureObject( &tex[idx-1], &resDesc, &texDesc, NULL ) );
+ CreateBsdfMipLevel<<<gridDim, blockDim>>>( tex[idx-1], (reinterpret_cast<NVU8 *>(md_MipMapsData[idx])), (reinterpret_cast<NVU8 *>(md_MipMapsData[idx-1])), m_Pitches[idx], curWidth, curHeight, m_DestinationFormat, m_SizeOfFormat );
+
+ curWidth = curWidth > 2 ? curWidth >> 1 : 1;
+ curHeight = curHeight > 2 ? curHeight >> 1 : 1;
+ }
+
+ CHECK_AND_HANDLE_CUDA_ERROR( cudaDeviceSynchronize(); )
+ BindTexture();
+ TransferTexture();
+ for (int idx = 0; idx < m_MaxMipMapLevel;++idx )
+ cudaDestroyTextureObject(tex[idx]);
+// CHECK_AND_HANDLE_CUDA_ERROR( cudaDeviceReset(); )
+ CHECK_AND_HANDLE_CUDA_ERROR( cudaDeviceSynchronize(); )
+
+ //NV_FREE( m_Foundation.getAllocator(), inTextureData );
+
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/Android.mk b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/Android.mk
new file mode 100644
index 00000000..74713ed3
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/Android.mk
@@ -0,0 +1,164 @@
+#############################################################################
+##
+## Copyright (C) 2009-2010 NVIDIA Corporation.
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt 3D Studio.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+MY_LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_math
+LOCAL_MODULE := nvmath
+LOCAL_SRC_FILES := nv_math.cpp nv_matrix.cpp nv_quat.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_shader
+LOCAL_MODULE := nvshader
+LOCAL_SRC_FILES := nv_shader.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_util
+LOCAL_MODULE := nvutil
+LOCAL_SRC_FILES := nv_util.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_time
+LOCAL_MODULE := nvtime
+LOCAL_SRC_FILES := nv_time.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_event
+LOCAL_MODULE := nvevent
+LOCAL_SRC_FILES := nv_event.cpp nv_event_queue.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_file
+LOCAL_MODULE := nvfile
+LOCAL_SRC_FILES := nv_file.c
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_thread
+LOCAL_MODULE := nvthread
+LOCAL_SRC_FILES := nv_thread.c
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_hhdds
+LOCAL_MODULE := nvhhdds
+LOCAL_SRC_FILES := nv_hhdds.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_glesutil
+LOCAL_MODULE := nvglesutil
+LOCAL_SRC_FILES := nv_images.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_sound
+LOCAL_MODULE := nvsound
+LOCAL_SRC_FILES := nv_sound.cpp
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_apk_file_am
+LOCAL_MODULE := nv_apk_file_am
+LOCAL_SRC_FILES := nv_apk_file_am.c
+LOCAL_ARM_MODE := arm
+LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/KD
+LOCAL_MODULE := MinKD
+LOCAL_SRC_FILES := MinKD.c
+LOCAL_ARM_MODE := arm
+LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_gesture
+LOCAL_MODULE := nvgesture
+LOCAL_SRC_FILES := nv_gesture.c
+LOCAL_ARM_MODE := arm
+LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_PATH := $(MY_LOCAL_PATH)/nv_bitfont
+LOCAL_MODULE := nvbitfont
+LOCAL_SRC_FILES := nv_bitfont.cpp
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -DOPENKODE -DANDROID
+LOCAL_C_INCLUDES := $(MY_LOCAL_PATH)
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_color.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_color.h
new file mode 100644
index 00000000..b9347529
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_color.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_COLOR_H
+#define _QT3DS_COLOR_H
+
+/** @file nv_color.h
+ Simple abstraction for RGBA colors as parameters to various libraries/functions.
+*/
+
+/** Base type for a single color channel (8-bit unsigned). */
+typedef unsigned char NvPCColor8;
+
+//#define NV_COLOR_BREAKOLD
+#ifdef NV_COLOR_BREAKOLD // uses a struct to break backwards-compat and accidental uses
+
+typedef struct
+{
+ NvPCColor8 r;
+ NvPCColor8 g;
+ NvPCColor8 b;
+ NvPCColor8 a;
+} NvPackedColor;
+
+static const NvPackedColor gnvpcwhite = { 255, 255, 255, 255 };
+static const NvPackedColor gnvpcblack = { 0, 0, 0, 255 };
+
+#define NV_PACKED_COLOR(r, g, b, a) \
+ { \
+ (NvPCColor8)(r), (NvPCColor8)(g), (NvPCColor8)(b), (NvPCColor8)(a) \
+ }
+
+#define NV_PC_PREDEF_WHITE gnvpcwhite
+#define NV_PC_PREDEF_BLACK gnvpcblack
+
+#define NV_PC_RED(c) (c.r)
+#define NV_PC_GREEN(c) (c.g)
+#define NV_PC_BLUE(c) (c.b)
+#define NV_PC_ALPHA(c) (c.a)
+
+#define NV_PC_PACK_UINT(c) (*(unsigned int *)(&(c)))
+
+#define NV_PC_EQUAL(x, y) ((x).r == (y).r && (x).g == (y).g && (x).b == (y).b && (x).a == (y).a)
+
+#else /* code that doesn't break old pass-as-uint stuff */
+
+/** Main type declaration for a packed 4-color construct. */
+typedef unsigned int NvPackedColor;
+
+/** A macro to build a packed color, passing in RGBA as four 8-bit integer values. */
+#define NV_PACKED_COLOR(r, g, b, a) \
+ ((NvPackedColor)(((((int)(a)) & 0xFF) << 24) | ((((int)(b)) & 0xFF) << 16) \
+ | ((((int)(g)) & 0xFF) << 8) | ((((int)(r)) & 0xFF))))
+
+/** A predefined constant for WHITE. */
+#define NV_PC_PREDEF_WHITE NV_PACKED_COLOR(0xFF, 0xFF, 0xFF, 0xFF)
+/** A predefined constant for BLACK. */
+#define NV_PC_PREDEF_BLACK NV_PACKED_COLOR(0x00, 0x00, 0x00, 0xFF)
+
+/** A macro for 'extracting' the red value from an NvPackedColor. */
+#define NV_PC_RED(c) ((c >> 0) & 0xff)
+/** A macro for 'extracting' the green value from an NvPackedColor. */
+#define NV_PC_GREEN(c) ((c >> 8) & 0xff)
+/** A macro for 'extracting' the blue value from an NvPackedColor. */
+#define NV_PC_BLUE(c) ((c >> 16) & 0xff)
+/** A macro for 'extracting' the alpha value from an NvPackedColor. */
+#define NV_PC_ALPHA(c) ((c >> 24) & 0xff)
+
+/** A macro requesting the packed color repacked into a 32-bit unsigned int.
+ This is a no-op for the color-as-uint approach.
+*/
+#define NV_PC_PACK_UINT(c) (c)
+/** A macro for testing the equality of two NvPackedColors. */
+#define NV_PC_EQUAL(x, y) (x == y)
+#endif
+
+/** A macro for mapping a single packed color channel into its floating point [0,1] rep. */
+#define NV_PC_TO_FLOAT(c) (c / 255.0f)
+
+#endif /*_QT3DS_COLOR_H*/
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_debug.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_debug.h
new file mode 100644
index 00000000..2559dd6f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_debug.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_DEBUG_H
+#define __INCLUDED_QT3DS_DEBUG_H
+
+#define CT_ASSERT(tag, cond) enum { COMPILE_TIME_ASSERT__##tag = 1 / (cond) }
+
+#define dimof(x) (sizeof(x) / sizeof(x[0]))
+#include <android/log.h>
+
+#define DBG_DETAILED 0
+
+#if 0
+
+ // the detailed prefix can be customised by setting DBG_DETAILED_PREFIX. See
+ // below as a reference.
+ // NOTE: fmt is the desired format string and must be in the prefix.
+ //#ifndef DBG_DETAILED_PREFIX
+ // #define DBG_DETAILED_PREFIX "%s, %s, line %d: " fmt, __FILE__, __FUNCTION__, __LINE__,
+ //#endif
+ //#define DEBUG_D_(fmt, args...)
+ //#define DEBUG_D(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, (DBG_DETAILED_PREFIX) ## args)
+
+#else
+
+#ifdef STRINGIFY
+#pragma push_macro("STRINGIFY")
+#undef STRINGIFY
+#define STRINGIFYPUSHED_____
+#endif
+#define STRINGIFY(x) #x
+
+// debug macro, includes file name function name and line number
+#define TO(x) typeof(x)
+#define DEBUG_D_(file, line, fmt, args...) \
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, file ", %s, line(" STRINGIFY(line) "): " fmt, \
+ __FUNCTION__, ##args)
+#define DEBUG_D(fmt, args...) DEBUG_D_(__FILE__, __LINE__, fmt, ##args)
+
+#ifdef STRINGIFYPUSHED_____
+#undef STRINGIFYPUSHED_____
+#pragma pop_macro("STRINGIFY")
+#endif
+
+#endif
+
+// basic debug macro
+#define DEBUG_(fmt, args...) (__android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args))
+
+// Debug macro that can be switched to spew a file name,
+// function and line number using DEBUG_DETAILED
+#if DBG_DETAILED == 1
+#define DEBUG(fmt, args...) DEBUG_D(fmt, ##args)
+#else
+#define DEBUG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args)
+#endif
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.cpp
new file mode 100644
index 00000000..b719eb7d
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.cpp
@@ -0,0 +1,890 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define MODULE "NVEvent"
+#define DBG_DETAILED 0
+
+#include "nv_event.h"
+
+#include <stdlib.h>
+#include <jni.h>
+#include <pthread.h>
+#include <android/log.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+#include "../nv_time/nv_time.h"
+#include "../nv_thread/nv_thread.h"
+#include "../nv_debug.h"
+#include "scoped_profiler.h"
+#include "nv_keycode_mapping.h"
+#include "nv_event_queue.h"
+
+// TODO TBD - this should be done in NVTimeInit(), but we use a different
+// class than most apps. Need to clean this up, as it is fragile w.r.t.
+// changes in nv_time
+extern void nvAcquireTimeExtensionJNI(JNIEnv *, jobject);
+extern jlong nvGetSystemTimeJNI(JNIEnv *, jobject);
+
+#define CT_ASSERT(tag, cond) enum { COMPILE_TIME_ASSERT__##tag = 1 / (cond) }
+
+enum {
+ // Android lifecycle status flags. Not app-specific
+ // Set between onCreate and onDestroy
+ NVEVENT_STATUS_RUNNING = 0x00000001,
+ // Set between onResume and onPause
+ NVEVENT_STATUS_ACTIVE = 0x00000002,
+ // Set between onWindowFocusChanged(true) and (false)
+ NVEVENT_STATUS_FOCUSED = 0x00000004,
+ // Set when the app's SurfaceHolder points to a
+ // valid, nonzero-sized surface
+ NVEVENT_STATUS_HAS_REAL_SURFACE = 0x00000008,
+
+ // Mask of all app lifecycle status flags, useful for checking when is it
+ // a reasonable time to be setting up EGL and rendering
+ NVEVENT_STATUS_INTERACTABLE = 0x0000000f,
+
+ // NvEvent EGL status flags. Not app-specific
+ // Set between calls to NVEventInitEGL and NVEventCleanupEGL
+ NVEVENT_STATUS_EGL_INITIALIZED = 0x00000010,
+ // Set when the EGL surface is allocated
+ NVEVENT_STATUS_EGL_HAS_SURFACE = 0x00000020,
+ // Set when a surface and context are available and bound
+ NVEVENT_STATUS_EGL_BOUND = 0x00000040,
+};
+
+static unsigned int s_appStatus = 0;
+
+static void ZeroAppFlags()
+{
+ s_appStatus = 0;
+}
+
+static void SetAppFlag(unsigned int status)
+{
+ s_appStatus |= status;
+}
+
+static void ClearAppFlag(unsigned int status)
+{
+ s_appStatus &= ~status;
+}
+
+static bool QueryAppFlag(unsigned int status)
+{
+ return (s_appStatus & status) ? true : false;
+}
+
+static bool QueryAppFlagsEqualMasked(unsigned int status, unsigned int mask)
+{
+ return ((s_appStatus & mask) == status) ? true : false;
+}
+
+static NVKeyCodeMapping s_keyMapping;
+static NVEventQueue s_eventQueue;
+static jobject s_globalThiz;
+static jfieldID s_lengthId;
+static jfieldID s_dataId;
+static jfieldID s_widthId;
+static jfieldID s_heightId;
+static jfieldID s_texDataId;
+static pthread_t s_mainThread;
+static bool s_appThreadExited = false;
+static bool s_javaPostedQuit = false;
+
+static int NVEVENT_ACTION_DOWN = 0;
+static int NVEVENT_ACTION_UP = 0;
+static int NVEVENT_ACTION_CANCEL = 0;
+static int NVEVENT_ACTION_POINTER_INDEX_MASK = 0;
+static int NVEVENT_ACTION_POINTER_INDEX_SHIFT = 0;
+static int NVEVENT_ACTION_KEY_UP = 0;
+
+class MethodRef
+{
+public:
+ MethodRef(const char *name, const char *signature)
+ : m_name(name)
+ , m_signature(signature)
+ , m_index(NULL)
+ {
+ }
+
+ bool QueryID(JNIEnv *env, jclass k)
+ {
+ m_index = env->GetMethodID(k, m_name, m_signature);
+ return true;
+ }
+
+ bool CallBoolean()
+ {
+ JNIEnv *jniEnv = NVThreadGetCurrentJNIEnv();
+
+ if (!jniEnv || !s_globalThiz) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error: No valid JNI env in %s", m_name);
+ return false;
+ }
+ if (!m_index) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error: No valid function pointer in %s",
+ m_name);
+ return false;
+ }
+ // __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Calling JNI up to %s", m_name);
+ return jniEnv->CallBooleanMethod(s_globalThiz, m_index);
+ }
+
+ bool CallInt()
+ {
+ JNIEnv *jniEnv = NVThreadGetCurrentJNIEnv();
+
+ if (!jniEnv || !s_globalThiz) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error: No valid JNI env in %s", m_name);
+ return 0;
+ }
+ if (!m_index) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error: No valid function pointer in %s",
+ m_name);
+ return false;
+ }
+ return (int)jniEnv->CallIntMethod(s_globalThiz, m_index);
+ }
+
+ const char *m_name;
+ const char *m_signature;
+ jmethodID m_index;
+};
+
+static MethodRef s_InitEGL("InitEGL", "()Z");
+static MethodRef s_CleanupEGL("CleanupEGL", "()Z");
+static MethodRef s_CreateSurfaceEGL("CreateSurfaceEGL", "()Z");
+static MethodRef s_DestroySurfaceEGL("DestroySurfaceEGL", "()Z");
+static MethodRef s_SwapBuffersEGL("SwapBuffersEGL", "()Z");
+static MethodRef s_BindSurfaceAndContextEGL("BindSurfaceAndContextEGL", "()Z");
+static MethodRef s_UnbindSurfaceAndContextEGL("UnbindSurfaceAndContextEGL", "()Z");
+static MethodRef s_GetErrorEGL("GetErrorEGL", "()I");
+static MethodRef s_finish("finish", "()V");
+static MethodRef
+ s_loadFile("loadFile", "(Ljava/lang/String;)Lcom/nvidia/devtech/NvEventQueueActivity$RawData;");
+static MethodRef
+ s_loadTexture("loadTexture",
+ "(Ljava/lang/String;)Lcom/nvidia/devtech/NvEventQueueActivity$RawTexture;");
+
+// True between onCreate and onDestroy
+bool NVEventStatusIsRunning()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_RUNNING);
+}
+
+// True between onResume and onPause
+bool NVEventStatusIsActive()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_ACTIVE);
+}
+
+// True between onWindowFocusChanged(true) and (false)
+bool NVEventStatusIsFocused()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_FOCUSED);
+}
+
+// True when the app's SurfaceHolder points to a
+// valid, nonzero-sized window
+bool NVEventStatusHasRealSurface()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_HAS_REAL_SURFACE);
+}
+
+// True when all of IsRunning, IsActive, IsFocused, HasRealSurface are true
+// useful for checking when is it a reasonable time to be setting up EGL and rendering
+bool NVEventStatusIsInteractable()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlagsEqualMasked(NVEVENT_STATUS_INTERACTABLE, NVEVENT_STATUS_INTERACTABLE);
+}
+
+// True between calls to NVEventInitEGL and NVEventCleanupEGL
+bool NVEventStatusEGLInitialized()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_EGL_INITIALIZED);
+}
+
+// True when the EGL surface is allocated
+bool NVEventStatusEGLHasSurface()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_EGL_HAS_SURFACE);
+}
+
+// True when a surface and context are available and bound
+bool NVEventStatusEGLIsBound()
+{
+ // TBD - need to lock a mutex?
+ return QueryAppFlag(NVEVENT_STATUS_EGL_BOUND);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Init and shutdown functions
+
+static void NVEventInitFileFunctions(JNIEnv *env)
+{
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "file methods");
+
+ jclass activity_class = env->FindClass("com/nvidia/devtech/NvEventQueueActivity");
+ s_loadFile.QueryID(env, activity_class);
+ jclass RawData_class = env->FindClass("com/nvidia/devtech/NvEventQueueActivity$RawData");
+ s_lengthId = env->GetFieldID(RawData_class, "length", "I");
+ s_dataId = env->GetFieldID(RawData_class, "data", "[B");
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "texture methods");
+
+ s_loadTexture.QueryID(env, activity_class);
+ jclass RawTexture_class = env->FindClass("com/nvidia/devtech/NvEventQueueActivity$RawTexture");
+ s_widthId = env->GetFieldID(RawTexture_class, "width", "I");
+ s_heightId = env->GetFieldID(RawTexture_class, "height", "I");
+ s_texDataId = env->GetFieldID(RawTexture_class, "data", "[B");
+}
+
+static void NVEventInitInputFields(JNIEnv *env)
+{
+ jclass Motion_class = env->FindClass("android/view/MotionEvent");
+ jfieldID ACTION_DOWN_id = env->GetStaticFieldID(Motion_class, "ACTION_DOWN", "I");
+ jfieldID ACTION_UP_id = env->GetStaticFieldID(Motion_class, "ACTION_UP", "I");
+ jfieldID ACTION_CANCEL_id = env->GetStaticFieldID(Motion_class, "ACTION_CANCEL", "I");
+ jfieldID ACTION_POINTER_INDEX_SHIFT_id =
+ env->GetStaticFieldID(Motion_class, "ACTION_POINTER_ID_SHIFT", "I");
+ jfieldID ACTION_POINTER_INDEX_MASK_id =
+ env->GetStaticFieldID(Motion_class, "ACTION_POINTER_ID_MASK", "I");
+ NVEVENT_ACTION_DOWN = env->GetStaticIntField(Motion_class, ACTION_DOWN_id);
+ NVEVENT_ACTION_UP = env->GetStaticIntField(Motion_class, ACTION_UP_id);
+ NVEVENT_ACTION_CANCEL = env->GetStaticIntField(Motion_class, ACTION_CANCEL_id);
+ NVEVENT_ACTION_POINTER_INDEX_MASK =
+ env->GetStaticIntField(Motion_class, ACTION_POINTER_INDEX_MASK_id);
+ NVEVENT_ACTION_POINTER_INDEX_SHIFT =
+ env->GetStaticIntField(Motion_class, ACTION_POINTER_INDEX_SHIFT_id);
+
+ jclass KeyCode_class = env->FindClass("android/view/KeyEvent");
+ jfieldID ACTION_KEY_UP_id = env->GetStaticFieldID(KeyCode_class, "ACTION_UP", "I");
+ NVEVENT_ACTION_KEY_UP = env->GetStaticIntField(KeyCode_class, ACTION_KEY_UP_id);
+}
+
+static void *NVEventMainLoopThreadFunc(void *)
+{
+ NVEventAppMain(0, NULL);
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "NvEvent native app Main returned");
+
+ // signal the condition variable to unblock
+ // java from waiting on pause or quit
+ s_eventQueue.UnblockProducer();
+
+ s_appThreadExited = true;
+
+ // IF that app main returned because we posted a QUIT, then Java knows what to
+ // do regarding lifecycle. But, if the app returned from main of its own accord,
+ // we need to call finish.
+ if (!s_javaPostedQuit) {
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+ env->CallVoidMethod(s_globalThiz, s_finish.m_index);
+ }
+
+ return NULL;
+}
+
+NVEventPlatformAppHandle NVEventGetPlatformAppHandle()
+{
+ return s_globalThiz;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Native event-handling functions
+
+const char *NVEventGetEventStr(NVEventType eventType)
+{
+ switch (eventType) {
+ case QT3DS_EVENT_KEY:
+ return "QT3DS_EVENT_KEY";
+ case QT3DS_EVENT_CHAR:
+ return "QT3DS_EVENT_CHAR";
+ case QT3DS_EVENT_TOUCH:
+ return "QT3DS_EVENT_TOUCH";
+ case QT3DS_EVENT_MULTITOUCH:
+ return "QT3DS_EVENT_MULTITOUCH";
+ case QT3DS_EVENT_ACCEL:
+ return "QT3DS_EVENT_ACCEL";
+ case QT3DS_EVENT_START:
+ return "QT3DS_EVENT_START";
+ case QT3DS_EVENT_RESTART:
+ return "QT3DS_EVENT_RESTART";
+ case QT3DS_EVENT_RESUME:
+ return "QT3DS_EVENT_RESUME";
+ case QT3DS_EVENT_FOCUS_GAINED:
+ return "QT3DS_EVENT_FOCUS_GAINED";
+ case QT3DS_EVENT_SURFACE_CREATED:
+ return "QT3DS_EVENT_SURFACE_CREATED";
+ case QT3DS_EVENT_SURFACE_SIZE:
+ return "QT3DS_EVENT_SURFACE_SIZE";
+ case QT3DS_EVENT_SURFACE_DESTROYED:
+ return "QT3DS_EVENT_SURFACE_DESTROYED";
+ case QT3DS_EVENT_FOCUS_LOST:
+ return "QT3DS_EVENT_FOCUS_LOST";
+ case QT3DS_EVENT_PAUSE:
+ return "QT3DS_EVENT_PAUSE";
+ case QT3DS_EVENT_STOP:
+ return "QT3DS_EVENT_STOP";
+ case QT3DS_EVENT_QUIT:
+ return "QT3DS_EVENT_QUIT";
+ case QT3DS_EVENT_USER:
+ return "QT3DS_EVENT_USER";
+ }
+ // update this if you end up having to edit something.
+ CT_ASSERT(NEED_TO_ADD_STRING_HERE, QT3DS_EVENT_NUM_EVENTS == 17);
+ return "unknown event type!";
+}
+
+const NVEvent *NVEventGetNextEvent(int waitMSecs)
+{
+ return s_eventQueue.RemoveOldest(waitMSecs);
+}
+
+void NVEventDoneWithEvent(bool handled)
+{
+ return s_eventQueue.DoneWithEvent(handled);
+}
+
+static void NVEventInsert(NVEvent *ev)
+{
+ if (!s_appThreadExited)
+ s_eventQueue.Insert(ev);
+}
+
+static bool NVEventInsertBlocking(NVEvent *ev)
+{
+ if (!s_appThreadExited)
+ return s_eventQueue.InsertBlocking(ev);
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Native to Java EGL call-up functions
+
+bool NVEventInitEGL()
+{
+ if (s_InitEGL.CallBoolean()) {
+ SetAppFlag(NVEVENT_STATUS_EGL_INITIALIZED);
+ return true;
+ } else
+ return false;
+}
+
+bool NVEventCleanupEGL()
+{
+ ClearAppFlag(NVEVENT_STATUS_EGL_BOUND);
+ ClearAppFlag(NVEVENT_STATUS_EGL_HAS_SURFACE);
+ ClearAppFlag(NVEVENT_STATUS_EGL_INITIALIZED);
+ return s_CleanupEGL.CallBoolean();
+}
+
+bool NVEventCreateSurfaceEGL()
+{
+ if (s_CreateSurfaceEGL.CallBoolean()) {
+ SetAppFlag(NVEVENT_STATUS_EGL_HAS_SURFACE);
+ return true;
+ } else
+ return false;
+}
+
+bool NVEventDestroySurfaceEGL()
+{
+ if (!QueryAppFlag(NVEVENT_STATUS_EGL_HAS_SURFACE))
+ return true;
+
+ if (QueryAppFlag(NVEVENT_STATUS_EGL_BOUND))
+ NVEventUnbindSurfaceAndContextEGL();
+
+ ClearAppFlag(NVEVENT_STATUS_EGL_HAS_SURFACE);
+ return s_DestroySurfaceEGL.CallBoolean();
+}
+
+bool NVEventBindSurfaceAndContextEGL()
+{
+ if (s_BindSurfaceAndContextEGL.CallBoolean()) {
+ SetAppFlag(NVEVENT_STATUS_EGL_BOUND);
+ return true;
+ } else
+ return false;
+}
+
+bool NVEventUnbindSurfaceAndContextEGL()
+{
+ ClearAppFlag(NVEVENT_STATUS_EGL_BOUND);
+ return s_UnbindSurfaceAndContextEGL.CallBoolean();
+}
+
+bool NVEventSwapBuffersEGL()
+{
+ if (!s_SwapBuffersEGL.CallBoolean())
+ return false;
+ RESET_PROFILING();
+ return true;
+}
+
+EGLint NVEventGetErrorEGL()
+{
+ return s_GetErrorEGL.CallInt();
+}
+
+bool NVEventReadyToRenderEGL(bool allocateIfNeeded)
+{
+ // If we have a bound context and surface, then EGL is ready
+ if (!NVEventStatusEGLIsBound()) {
+ if (!allocateIfNeeded)
+ return false;
+
+ // If we have not bound the context and surface, do we even _have_ a surface?
+ if (!NVEventStatusEGLHasSurface()) {
+ // No surface, so we need to check if EGL is set up at all
+ if (!NVEventStatusEGLInitialized()) {
+ if (!NVEventInitEGL())
+ return false;
+ }
+
+ // Create the rendering surface now that we have a context
+ if (!NVEventCreateSurfaceEGL())
+ return false;
+ }
+
+ // We have a surface and context, so bind them
+ if (NVEventBindSurfaceAndContextEGL())
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Input event-related Java to Native callback functions
+
+static jboolean NVEventTouchEvent(JNIEnv *env, jobject thiz, jint action, jint mx, jint my)
+{
+ {
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_TOUCH;
+ ev.m_data.m_touch.m_action = (NVEVENT_ACTION_UP == action)
+ ? QT3DS_TOUCHACTION_UP
+ : ((NVEVENT_ACTION_DOWN == action) ? QT3DS_TOUCHACTION_DOWN : QT3DS_TOUCHACTION_MOVE);
+ ev.m_data.m_touch.m_x = mx;
+ ev.m_data.m_touch.m_y = my;
+ NVEventInsert(&ev);
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean NVEventMultiTouchEvent(JNIEnv *env, jobject thiz, jint action, jint count, jint mx1,
+ jint my1, jint mx2, jint my2)
+{
+ {
+ NVEvent ev;
+
+ int actionOnly = action & (~NVEVENT_ACTION_POINTER_INDEX_MASK);
+ int maskOnly = (count >= 2) ? 0x3 : ((count == 0) ? 0x0 : 0x1);
+
+ ev.m_type = QT3DS_EVENT_MULTITOUCH;
+
+ if (actionOnly == NVEVENT_ACTION_UP) {
+ ev.m_data.m_multi.m_action = QT3DS_MULTITOUCH_UP;
+ } else if (actionOnly == NVEVENT_ACTION_DOWN) {
+ ev.m_data.m_multi.m_action = QT3DS_MULTITOUCH_DOWN;
+ } else if (actionOnly == NVEVENT_ACTION_CANCEL) {
+ ev.m_data.m_multi.m_action = QT3DS_MULTITOUCH_CANCEL;
+ } else {
+ ev.m_data.m_multi.m_action = QT3DS_MULTITOUCH_MOVE;
+ }
+ ev.m_data.m_multi.m_action = (NVMultiTouchEventType)(
+ ev.m_data.m_multi.m_action | (maskOnly << QT3DS_MULTITOUCH_POINTER_SHIFT));
+ ev.m_data.m_multi.m_x1 = mx1;
+ ev.m_data.m_multi.m_y1 = my1;
+ ev.m_data.m_multi.m_x2 = mx2;
+ ev.m_data.m_multi.m_y2 = my2;
+ NVEventInsert(&ev);
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean NVEventKeyEvent(JNIEnv *env, jobject thiz, jint action, jint keycode, jint unichar)
+{
+ // TBD - remove these or make them resettable for safety...
+ static int lastKeyAction = 0;
+ static int lastKeyCode = 0;
+ bool ret = false;
+
+ NVKeyCode code = QT3DS_KEYCODE_NULL;
+ if (s_keyMapping.MapKey((int)keycode, code)) {
+ if ((code != QT3DS_KEYCODE_NULL) && ((code != lastKeyCode) || (action != lastKeyAction))) {
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_KEY;
+ ev.m_data.m_key.m_action =
+ (NVEVENT_ACTION_UP == action) ? QT3DS_KEYACTION_UP : QT3DS_KEYACTION_DOWN;
+ ev.m_data.m_key.m_code = code;
+ ret = NVEventInsertBlocking(&ev);
+ }
+
+ lastKeyAction = action;
+ lastKeyCode = code;
+ }
+
+ if (unichar && (NVEVENT_ACTION_UP != action)) {
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_CHAR;
+ ev.m_data.m_char.m_unichar = unichar;
+ NVEventInsert(&ev);
+ }
+
+ return ret;
+}
+
+static jboolean NVEventAccelerometerEvent(JNIEnv *env, jobject thiz, jfloat values0, jfloat values1,
+ jfloat values2)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_ACCEL;
+ ev.m_data.m_accel.m_x = values0;
+ ev.m_data.m_accel.m_y = values1;
+ ev.m_data.m_accel.m_z = values2;
+ NVEventInsert(&ev);
+ return JNI_TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Java to Native app lifecycle callback functions
+
+static jboolean onCreateNative(JNIEnv *env, jobject thiz)
+{
+ ZeroAppFlags();
+
+ if (!s_globalThiz) {
+ s_globalThiz = env->NewGlobalRef(thiz);
+ if (!s_globalThiz) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error: Thiz NewGlobalRef failed!");
+ }
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Thiz NewGlobalRef: 0x%p", s_globalThiz);
+ }
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Init KeyCode Map");
+ s_keyMapping.Init(env, thiz);
+
+ NVEventInitFileFunctions(env);
+ NVEventInitInputFields(env);
+
+ s_eventQueue.Init();
+
+ s_javaPostedQuit = false;
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Calling NVEventAppInit");
+
+ if (NVEventAppInit(0, NULL)) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "NVEventAppInit error");
+ return JNI_FALSE;
+ }
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "spawning thread");
+
+ s_appThreadExited = false;
+ SetAppFlag(NVEVENT_STATUS_RUNNING);
+
+ /* Launch thread with main loop */
+ NVThreadSpawnJNIThread(&s_mainThread, NULL, NVEventMainLoopThreadFunc, NULL);
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "thread spawned");
+
+ return JNI_TRUE;
+}
+
+static jboolean onStartNative(JNIEnv *env, jobject thiz)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_START;
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onRestartNative(JNIEnv *env, jobject thiz)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_RESTART;
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onResumeNative(JNIEnv *env, jobject thiz)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_RESUME;
+ SetAppFlag(NVEVENT_STATUS_ACTIVE);
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onSurfaceCreatedNative(JNIEnv *env, jobject thiz, int w, int h)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_SURFACE_CREATED;
+ ev.m_data.m_size.m_w = w;
+ ev.m_data.m_size.m_h = h;
+ if ((w > 0) && (h > 0))
+ SetAppFlag(NVEVENT_STATUS_HAS_REAL_SURFACE);
+ else
+ ClearAppFlag(NVEVENT_STATUS_HAS_REAL_SURFACE);
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onFocusChangedNative(JNIEnv *env, jobject thiz, jboolean focused)
+{
+ NVEvent ev;
+ ev.m_type = (focused == JNI_TRUE) ? QT3DS_EVENT_FOCUS_GAINED : QT3DS_EVENT_FOCUS_LOST;
+ if (focused)
+ SetAppFlag(NVEVENT_STATUS_FOCUSED);
+ else
+ ClearAppFlag(NVEVENT_STATUS_FOCUSED);
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onSurfaceChangedNative(JNIEnv *env, jobject thiz, int w, int h)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_SURFACE_SIZE;
+ ev.m_data.m_size.m_w = w;
+ ev.m_data.m_size.m_h = h;
+ if (w * h)
+ SetAppFlag(NVEVENT_STATUS_HAS_REAL_SURFACE);
+ else
+ ClearAppFlag(NVEVENT_STATUS_HAS_REAL_SURFACE);
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onSurfaceDestroyedNative(JNIEnv *env, jobject thiz)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_SURFACE_DESTROYED;
+ ClearAppFlag(NVEVENT_STATUS_HAS_REAL_SURFACE);
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onPauseNative(JNIEnv *env, jobject thiz)
+{
+ // TODO: we could selectively flush here to
+ // improve responsiveness to the pause
+ s_eventQueue.Flush();
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_PAUSE;
+ ClearAppFlag(NVEVENT_STATUS_ACTIVE);
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onStopNative(JNIEnv *env, jobject thiz)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_STOP;
+ return NVEventInsertBlocking(&ev);
+}
+
+static jboolean onDestroyNative(JNIEnv *env, jobject thiz)
+{
+ if (!env || !s_globalThiz) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE,
+ "Error: DestroyingRegisteredObjectInstance no TLS data!");
+ }
+
+ if (!s_appThreadExited) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Posting quit event");
+
+ // flush ALL events
+ s_eventQueue.Flush();
+
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_QUIT;
+ ClearAppFlag(NVEVENT_STATUS_RUNNING);
+
+ // We're posting quit, so we need to mark that; when the main loop
+ // thread exits, we check this flag to ensure that we only call "finish"
+ // if the app returned of its own accord, not if we posted it
+ s_javaPostedQuit = true;
+ NVEventInsert(&ev);
+
+ // ensure that the native side
+ // isn't blocked waiting for an event -- since we've flushed
+ // all the events save quit, we must artificially unblock native
+ s_eventQueue.UnblockConsumer();
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Waiting for main loop exit");
+ pthread_join(s_mainThread, NULL);
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Main loop exited");
+ }
+
+ env->DeleteGlobalRef(s_globalThiz);
+ s_globalThiz = NULL;
+
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Released global thiz!");
+
+ s_eventQueue.Shutdown();
+
+ return JNI_TRUE;
+}
+
+static jboolean postUserEvent(JNIEnv *env, jobject thiz, jint u0, jint u1, jint u2, jint u3,
+ jboolean blocking)
+{
+ NVEvent ev;
+ ev.m_type = QT3DS_EVENT_USER;
+ ev.m_data.m_user.m_u0 = u0;
+ ev.m_data.m_user.m_u1 = u1;
+ ev.m_data.m_user.m_u2 = u2;
+ ev.m_data.m_user.m_u3 = u3;
+ if (blocking == JNI_TRUE) {
+ return NVEventInsertBlocking(&ev);
+ } else {
+ NVEventInsert(&ev);
+ return true;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// File and APK handling functions
+
+char *NVEventLoadFile(const char *file)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ jstring test = env->NewStringUTF(file);
+ jobject rawData = env->CallObjectMethod(s_globalThiz, s_loadFile.m_index, test);
+
+ jbyteArray data = (jbyteArray)env->GetObjectField(rawData, s_dataId);
+ int size = env->GetIntField(rawData, s_lengthId);
+
+ unsigned char *data2 = (unsigned char *)env->GetByteArrayElements(data, NULL);
+ char *buffer = new char[size + 1];
+ memcpy(buffer, data2, size);
+ buffer[size] = '\0';
+
+ env->ReleaseByteArrayElements(data, (jbyte *)data2, 0);
+ env->DeleteLocalRef(rawData);
+
+ return buffer;
+}
+
+void *NVEventGetTextureData(const char *filename, unsigned char *&pixels, unsigned int &width,
+ unsigned int &height, unsigned int &format, unsigned int &type)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ jstring test = env->NewStringUTF(filename);
+ jobject rawTexture = env->CallObjectMethod(s_globalThiz, s_loadTexture.m_index, test);
+
+ jbyteArray data = (jbyteArray)env->GetObjectField(rawTexture, s_texDataId);
+ width = env->GetIntField(rawTexture, s_widthId);
+ height = env->GetIntField(rawTexture, s_heightId);
+
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+
+ pixels = (unsigned char *)env->GetByteArrayElements(data, NULL);
+ env->DeleteLocalRef(rawTexture);
+
+ return (void *)data;
+}
+
+void NVEventReleaseTextureData(void *data, unsigned char *pixels)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->ReleaseByteArrayElements((jbyteArray)data, (jbyte *)pixels, JNI_ABORT);
+ env->DeleteLocalRef((jbyteArray)data);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JVM Initialization functions
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+
+ NVThreadInit(vm);
+
+ DEBUG("JNI_OnLoad called");
+ if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) {
+ DEBUG("Failed to get the environment using GetEnv()");
+ return -1;
+ }
+ JNINativeMethod methods[] = {
+ { "onCreateNative", "()Z", (void *)onCreateNative },
+ { "onStartNative", "()Z", (void *)onStartNative },
+ { "onRestartNative", "()Z", (void *)onRestartNative },
+ { "onResumeNative", "()Z", (void *)onResumeNative },
+ { "onSurfaceCreatedNative", "(II)Z", (void *)onSurfaceCreatedNative },
+ { "onFocusChangedNative", "(Z)Z", (void *)onFocusChangedNative },
+ { "onSurfaceChangedNative", "(II)Z", (void *)onSurfaceChangedNative },
+ { "onSurfaceDestroyedNative", "()Z", (void *)onSurfaceDestroyedNative },
+ { "onPauseNative", "()Z", (void *)onPauseNative },
+ { "onStopNative", "()Z", (void *)onStopNative },
+ { "onDestroyNative", "()Z", (void *)onDestroyNative },
+ { "postUserEvent", "(IIIIZ)Z", (void *)postUserEvent },
+ { "touchEvent", "(IIILandroid/view/MotionEvent;)Z", (void *)NVEventTouchEvent
+
+ },
+ { "multiTouchEvent", "(IIIIIILandroid/view/MotionEvent;)Z", (void *)NVEventMultiTouchEvent
+
+ },
+ { "keyEvent", "(IIILandroid/view/KeyEvent;)Z", (void *)NVEventKeyEvent },
+ { "accelerometerEvent", "(FFF)Z", (void *)NVEventAccelerometerEvent },
+ // TODO TBD - this should be done in NVTimeInit(), but we use a different
+ // class than most apps. Need to clean this up, as it is fragile w.r.t.
+ // changes in nv_time
+ { "nvAcquireTimeExtension", "()V", (void *)nvAcquireTimeExtensionJNI },
+ { "nvGetSystemTime", "()J", (void *)nvGetSystemTimeJNI },
+ };
+ jclass k;
+ k = (env)->FindClass("com/nvidia/devtech/NvEventQueueActivity");
+ (env)->RegisterNatives(k, methods, dimof(methods));
+
+ s_InitEGL.QueryID(env, k);
+ s_CleanupEGL.QueryID(env, k);
+ s_CreateSurfaceEGL.QueryID(env, k);
+ s_DestroySurfaceEGL.QueryID(env, k);
+ s_SwapBuffersEGL.QueryID(env, k);
+ s_BindSurfaceAndContextEGL.QueryID(env, k);
+ s_UnbindSurfaceAndContextEGL.QueryID(env, k);
+ s_GetErrorEGL.QueryID(env, k);
+ s_finish.QueryID(env, k);
+
+ return JNI_VERSION_1_4;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.h
new file mode 100644
index 00000000..c62288c2
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event.h
@@ -0,0 +1,553 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_EVENT_H
+#define _QT3DS_EVENT_H
+#include <sys/types.h>
+#include <EGL/egl.h>
+
+/** @file nv_event.h
+Contains a framework for event loop-based applications. This library replaces
+most or all of the normally-required JNI code for Android NDK applications,
+presenting the application developer with two callbacks into which they can
+write their application. The framework runs in a natively-created thread,
+allowing the application to implement a classic "event loop and render" structure
+without having to return to Java code to avoid ANR warnings. The library
+includes support for input and system event passing as well as JNI initialization
+and exposes basic EGL functionality to native as well. Put together, the library
+can form the basis of a simple interactive 3D application. All applications that
+are based on this library must also be subclassed on the Java side from the
+provided NvEventQueueActivity. Additional external documentation on the use of
+this library, the related Java code and the tool provided to create a template
+application based on the library are provided with the SDK.
+@see NvEventQueueActivity
+*/
+
+#ifdef ANDROID
+
+#include <jni.h>
+typedef jobject NVEventPlatformAppHandle;
+
+#else // unknown platform
+
+typedef void *NVEventPlatformAppHandle;
+
+#endif
+
+enum {
+ /** Timeout argument to NVEventGetNextEvent() that indicates the function should
+ block until there is an event pending or the app exits
+ @see NVEventGetNextEvent()
+ */
+ QT3DS_EVENT_WAIT_FOREVER = -1
+};
+
+/** Event type values
+*/
+typedef enum NVEventType {
+ /** Key up/down events */
+ QT3DS_EVENT_KEY = 1,
+ /** Translated character events */
+ QT3DS_EVENT_CHAR,
+ /** Single-touch pointer events */
+ QT3DS_EVENT_TOUCH,
+ /** Multi-touch events */
+ QT3DS_EVENT_MULTITOUCH,
+ /** Accelerometer events */
+ QT3DS_EVENT_ACCEL,
+ /** onStart lifecycle events */
+ QT3DS_EVENT_START,
+ /** onRestart lifecycle events */
+ QT3DS_EVENT_RESTART,
+ /** onResume lifecycle events */
+ QT3DS_EVENT_RESUME,
+ /** onWindowFocusChanged(TRUE) lifecycle events */
+ QT3DS_EVENT_FOCUS_GAINED,
+ /** Surface created events */
+ QT3DS_EVENT_SURFACE_CREATED,
+ /** Surface size changed events */
+ QT3DS_EVENT_SURFACE_SIZE,
+ /** Surface destroyed events */
+ QT3DS_EVENT_SURFACE_DESTROYED,
+ /** onWindowFocusChanged(FALSE) lifecycle events */
+ QT3DS_EVENT_FOCUS_LOST,
+ /** onPause lifecycle events */
+ QT3DS_EVENT_PAUSE,
+ /** onStop lifecycle events */
+ QT3DS_EVENT_STOP,
+ /** (onDestroy) Quit request events */
+ QT3DS_EVENT_QUIT,
+ /** App-specific events */
+ QT3DS_EVENT_USER,
+ /* a dummy enum value used to compute num_events */
+ QT3DS_EVENT_NUM_EVENT_DUMMY_DONTUSEME,
+ /* total number of events */
+ QT3DS_EVENT_NUM_EVENTS = QT3DS_EVENT_NUM_EVENT_DUMMY_DONTUSEME - 1,
+ QT3DS_EVENT_FORCE_32BITS = 0x7fffffff
+} NVEventType;
+
+/** Touch event actions
+*/
+typedef enum NVTouchEventType {
+ /** Pointer has just left the screen */
+ QT3DS_TOUCHACTION_UP,
+ /** Pointer has just gone down onto the screen */
+ QT3DS_TOUCHACTION_DOWN,
+ /** Pointer is moving on the screen */
+ QT3DS_TOUCHACTION_MOVE,
+ QT3DS_TOUCHACTION_FORCE_32BITS = 0x7fffffff
+} NVTouchEventType;
+
+/** Multitouch event flags
+*/
+typedef enum NVMultiTouchEventType {
+ /** Indicated pointers are leaving the screen */
+ QT3DS_MULTITOUCH_UP = 0x00000001,
+ /** Indicated pointers have just touched the screen */
+ QT3DS_MULTITOUCH_DOWN = 0x00000002,
+ /** Indicated pointers are moving on the screen */
+ QT3DS_MULTITOUCH_MOVE = 0x00000003,
+ /** Indicated pointers have halted the current gesture
+ app should cancel any actions implied by the gesture */
+ QT3DS_MULTITOUCH_CANCEL = 0x00000004,
+ /** Mask to be AND'ed with the flag value
+ to get the active pointer bits */
+ QT3DS_MULTITOUCH_POINTER_MASK = 0x0000ff00,
+ /** Number of bits to right-shift the masked value
+ to get the active pointer bits */
+ QT3DS_MULTITOUCH_POINTER_SHIFT = 0x00000008,
+ /** Mask to be AND'ed with the flag value
+ to get the event action */
+ QT3DS_MULTITOUCH_ACTION_MASK = 0x000000ff,
+ QT3DS_MULTITOUCH_FORCE_32BITS = 0x7fffffff
+} NVMultiTouchEventType;
+
+/** Key event types
+*/
+typedef enum NVKeyEventType {
+ /** Key has just been pressed (no repeats) */
+ QT3DS_KEYACTION_UP,
+ /** Key has just been released */
+ QT3DS_KEYACTION_DOWN,
+ QT3DS_KEYACTION_FORCE_32BITS = 0x7fffffff
+} NVKeyEventType;
+
+/** Key event key codes
+*/
+#define QT3DS_MAX_KEYCODE 256
+typedef enum NVKeyCode {
+ QT3DS_KEYCODE_NULL = 0,
+ QT3DS_KEYCODE_BACK,
+ QT3DS_KEYCODE_TAB,
+ QT3DS_KEYCODE_ENTER,
+ QT3DS_KEYCODE_DEL,
+ QT3DS_KEYCODE_SPACE,
+ QT3DS_KEYCODE_ENDCALL,
+ QT3DS_KEYCODE_HOME,
+
+ QT3DS_KEYCODE_STAR,
+ QT3DS_KEYCODE_PLUS,
+ QT3DS_KEYCODE_MINUS,
+ QT3DS_KEYCODE_NUM,
+
+ QT3DS_KEYCODE_DPAD_LEFT,
+ QT3DS_KEYCODE_DPAD_UP,
+ QT3DS_KEYCODE_DPAD_RIGHT,
+ QT3DS_KEYCODE_DPAD_DOWN,
+
+ QT3DS_KEYCODE_0,
+ QT3DS_KEYCODE_1,
+ QT3DS_KEYCODE_2,
+ QT3DS_KEYCODE_3,
+ QT3DS_KEYCODE_4,
+ QT3DS_KEYCODE_5,
+ QT3DS_KEYCODE_6,
+ QT3DS_KEYCODE_7,
+ QT3DS_KEYCODE_8,
+ QT3DS_KEYCODE_9,
+
+ QT3DS_KEYCODE_A,
+ QT3DS_KEYCODE_B,
+ QT3DS_KEYCODE_C,
+ QT3DS_KEYCODE_D,
+ QT3DS_KEYCODE_E,
+ QT3DS_KEYCODE_F,
+ QT3DS_KEYCODE_G,
+ QT3DS_KEYCODE_H,
+ QT3DS_KEYCODE_I,
+ QT3DS_KEYCODE_J,
+ QT3DS_KEYCODE_K,
+ QT3DS_KEYCODE_L,
+ QT3DS_KEYCODE_M,
+ QT3DS_KEYCODE_N,
+ QT3DS_KEYCODE_O,
+ QT3DS_KEYCODE_P,
+ QT3DS_KEYCODE_Q,
+ QT3DS_KEYCODE_R,
+ QT3DS_KEYCODE_S,
+ QT3DS_KEYCODE_T,
+ QT3DS_KEYCODE_U,
+ QT3DS_KEYCODE_V,
+ QT3DS_KEYCODE_W,
+ QT3DS_KEYCODE_X,
+ QT3DS_KEYCODE_Y,
+ QT3DS_KEYCODE_Z,
+
+ QT3DS_KEYCODE_ALT_LEFT,
+ QT3DS_KEYCODE_ALT_RIGHT,
+
+ QT3DS_KEYCODE_SHIFT_LEFT,
+ QT3DS_KEYCODE_SHIFT_RIGHT,
+
+ QT3DS_KEYCODE_APOSTROPHE,
+ QT3DS_KEYCODE_SEMICOLON,
+ QT3DS_KEYCODE_EQUALS,
+ QT3DS_KEYCODE_COMMA,
+ QT3DS_KEYCODE_PERIOD,
+ QT3DS_KEYCODE_SLASH,
+ QT3DS_KEYCODE_GRAVE,
+ QT3DS_KEYCODE_BACKSLASH,
+
+ QT3DS_KEYCODE_LEFT_BRACKET,
+ QT3DS_KEYCODE_RIGHT_BRACKET,
+
+ QT3DS_KEYCODE_FORCE_32BIT = 0x7fffffff
+} NVKeyCode;
+
+/** Single-touch event data
+*/
+typedef struct NVEventTouch
+{
+ /** The action code */
+ NVTouchEventType m_action;
+ /** The window-relative X position (in pixels) */
+ float m_x;
+ /** The window-relative Y position (in pixels) */
+ float m_y;
+} NVEventTouch;
+
+/** Multi-touch event data
+*/
+typedef struct NVEventMultiTouch
+{
+ /** The action flags */
+ NVMultiTouchEventType m_action;
+ /** The window-relative X position of the first pointer (in pixels)
+ only valid if bit 0 of the pointer bits is set */
+ float m_x1;
+ /** The window-relative Y position of the first pointer (in pixels)
+ only valid if bit 0 of the pointer bits is set */
+ float m_y1;
+ /** The window-relative X position of the second pointer (in pixels)
+ only valid if bit 1 of the pointer bits is set */
+ float m_x2;
+ /** The window-relative Y position of the second pointer (in pixels)
+ only valid if bit 1 of the pointer bits is set */
+ float m_y2;
+} NVEventMultiTouch;
+
+/** Key down/up event data
+*/
+typedef struct NVEventKey
+{
+ /** The action flags */
+ NVKeyEventType m_action;
+ /** The code of the key pressed or released */
+ NVKeyCode m_code;
+} NVEventKey;
+
+/** Translated character event data
+*/
+typedef struct NVEventChar
+{
+ /** The UNICODE character represented */
+ int32_t m_unichar;
+} NVEventChar;
+
+/** Accelerometer event data
+*/
+typedef struct NVEventAccel
+{
+ /** Signed X magnitude of the force vector */
+ float m_x;
+ /** Signed Y magnitude of the force vector */
+ float m_y;
+ /** Signed Z magnitude of the force vector */
+ float m_z;
+} NVEventAccel;
+
+/** Surface size change event data
+*/
+typedef struct NVEventSurfaceSize
+{
+ /** New surface client area width (in pixels) */
+ int32_t m_w;
+ /** New surface client area height (in pixels) */
+ int32_t m_h;
+} NVEventSurfaceSize;
+
+/** User/App-specific event data
+*/
+typedef struct NVEventUser
+{
+ /** First 32-bit user data item */
+ int32_t m_u0;
+ /** Second 32-bit user data item */
+ int32_t m_u1;
+ /** Third 32-bit user data item */
+ int32_t m_u2;
+ /** Fourth 32-bit user data item */
+ int32_t m_u3;
+} NVEventUser;
+
+/** All-encompassing event structure
+*/
+typedef struct NVEvent
+{
+ /** The type of the event, which also indicates which m_data union holds the data */
+ NVEventType m_type;
+ /** Union containing all possible event type data */
+ union NVEventData {
+ /** Data for single-touch events */
+ NVEventTouch m_touch;
+ /** Data for multi-touch events */
+ NVEventMultiTouch m_multi;
+ /** Data for key up/down events */
+ NVEventKey m_key;
+ /** Data for charcter events */
+ NVEventChar m_char;
+ /** Data for accelerometer events */
+ NVEventAccel m_accel;
+ /** Data for surface size events */
+ NVEventSurfaceSize m_size;
+ /** Data for user/app events */
+ NVEventUser m_user;
+ } m_data;
+} NVEvent;
+
+/** Returns a string describing the event
+@param eventType The event type
+@return Returns a string containing a description of the event. Do not free or delete this memory.
+@see NVEvent */
+const char *NVEventGetEventStr(NVEventType eventType);
+
+/** Returns the next pending event for the application to process. Can return immediately if there
+is no event, or can wait a fixed number of milisecs (or "forever") if desired.
+The application should always pair calls to this function that return non-NULL events with calls
+to NVEventDoneWithEvent()
+@param waitMSecs The maximum time (in milisecs) to wait for an event before returning "no event".
+ Pass QT3DS_EVENT_WAIT_FOREVER to wait indefinitely for an event. Note that
+QT3DS_EVENT_WAIT_FOREVER
+ does not gaurantee an event on return. The function can still return on error or if the
+ app is exiting. Default is to return immediately, event or not.
+@return Non-NULL pointer to a constant event structure if an event was pending, NULL if no event was
+ pending in the requested timeout period
+@see NVEvent
+@see NVEventDoneWithEvent
+*/
+const NVEvent *NVEventGetNextEvent(int waitMSecs = 0);
+
+/** Indicates that the application has finished handling the event returned from the last
+call to NVEventGetNextEvent. This function should always be called prior to the next call
+to NVEventGetNextEvent. If the current event is a blocking event, this call will unblock
+the posting thread (normally in Java). This is particularly important for application
+lifecycle events like onPause, as calling this function indicates that the native code has
+completed the handling of the lifecycle callback. Failure to call this function promptly
+for all events can lead to Application Not Responding errors.
+@param handled The return value that should be passed back to Java for blocking events. For
+non-blocking
+events, this parameter is discard.
+@see NVEvent
+@see NVEventGetNextEvent
+*/
+void NVEventDoneWithEvent(bool handled);
+
+/** The app-supplied "callback" for initialization during JNI_OnLoad.
+Declares the application's pre-main initialization function. Does not define the
+function. <b>The app must define this in its own code</b>, even if the function is empty.
+JNI init code can be safely called from here, as it WILL be called from
+within a JNI function thread
+@parm argc Passes the number of command line arguments.
+ This is currently unsupported and is always passed 0
+@parm argv Passes the array of command line arguments.
+ This is currently unsupported and is always passed NULL
+@return The function should return 0 on success and nonzero on failure.
+*/
+extern int32_t NVEventAppInit(int32_t argc, char **argv);
+
+/** The app-supplied "callback" for running the application's main loop.
+Declares the application's main loop function. Does not define the
+function. <b>The app must define this in its own code</b>
+This function will be spawned in its own thread.
+@parm argc Passes the number of command line arguments.
+ This is currently unsupported and is always passed 0
+@parm argv Passes the array of command line arguments.
+ This is currently unsupported and is always passed NULL
+@return The function should return 0 on success and nonzero on failure.
+*/
+extern int32_t NVEventAppMain(int32_t argc, char **argv);
+
+/** Initializes EGL, queries a valid ES2 config and creates (but does not bind)
+ an ES2-compatible EGLContext
+@return true on success, false on failure
+*/
+bool NVEventInitEGL();
+
+/** Releases any existing EGLSurface and EGLContext and terminates EGL
+@return true on success, false on failure
+*/
+bool NVEventCleanupEGL();
+
+/** Creates an EGLSurface for the current Android surface. Will attempt to initialize
+ EGL and an EGLContext if not already done. Fails if there is no valid Android surface
+ or if there is an EGL error.
+@return true on success, false on failure
+*/
+bool NVEventCreateSurfaceEGL();
+
+/** Unbinds (if needed) and releases the app's EGLSurface
+@return true on success, false on failure
+*/
+bool NVEventDestroySurfaceEGL();
+
+/** Binds the app's EGLSurface and EGLContext to the calling thread. The EGLSurface and
+ EGLContext must both exist already, or else the function will fail.
+@return true on success, false on failure
+*/
+bool NVEventBindSurfaceAndContextEGL();
+
+/** Un-binds the app's EGLSurface and EGLContext from the calling thread.
+@return true on success, false on failure
+*/
+bool NVEventUnbindSurfaceAndContextEGL();
+
+/** Swaps the currently-bound EGLSurface
+@return true on success, false on failure
+*/
+bool NVEventSwapBuffersEGL();
+
+/** Accessor for the last EGL error
+@return the EGL error
+*/
+EGLint NVEventGetErrorEGL();
+
+/** Utility function: checks if EGl is completely ready to render, including
+ initialization, surface creation and context/surface binding.
+@parm allocateIfNeeded If the parameter is false, then the function immediately returns if any
+ part of the requirements have not already been satisfied. If the parameter is
+ true, then the function attempts to initialize any of the steps needed, failing
+ and returning false only if a step cannot be completed at this time.
+@return The function returns true if EGL/GLES is ready to render/load content (i.e.
+ a context and surface are bound) and false it not
+*/
+bool NVEventReadyToRenderEGL(bool allocateIfNeeded);
+
+/** Convenience conditional function to determine if the app is between onCreate
+ and onDestroy callbacks (i.e. the app is in a running state).
+@return true if the application is between onCreate and onDestroy and false after
+ an onDestroy event has been delivered.
+*/
+bool NVEventStatusIsRunning();
+
+/** Convenience conditional function to determine if the app is between onResume and onPause
+ callbacks (i.e. the app is in a "resumed" state).
+@return true if the application is between onResume and onPause and false if the application
+ has not yet been resumed, or is currently paused.
+*/
+bool NVEventStatusIsActive();
+
+/** Convenience conditional function to determine if the app's window is focused (between
+ calls to onWindowFocusChanged(true) and onWindowFocusChanged(false))
+@return true between onWindowFocusChanged(true) and onWindowFocusChanged(false)
+*/
+bool NVEventStatusIsFocused();
+
+/** Convenience conditional function to determine if the app has a surface and that surface
+ has non-zero area
+@return true if the app is between surfaceCreated and surfaceDestroyed callbacks and
+ the surface has non-zero pixel area (not 0x0 pixels)
+*/
+bool NVEventStatusHasRealSurface();
+
+/** Convenience conditional function to determine if the app is in a fully-focused, visible
+ state. This is a logical "AND" of IsRunning, IsActive, IsFocused and HasRealSurface
+@return true if IsRunning, IsActive, IsFocused and HasRealSurface are all currently true,
+false otherwise
+*/
+bool NVEventStatusIsInteractable();
+
+/** Convenience conditional function to determine if the app has active EGL
+@return true between successful calls to NVEventInitEGL and NVEventCleanupEGL,
+false otherwise
+*/
+bool NVEventStatusEGLInitialized();
+
+/** Convenience conditional function to determine if the app has an EGLSurface (need not be bound)
+@return true if the EGLSurface for the app is allocated, false otherwise
+*/
+bool NVEventStatusEGLHasSurface();
+
+/** Convenience conditional function to determine if the app has an EGLSurface and EGLContext
+ and they are bound
+@return true if the EGLSurface and EGLContext for the app are allocated and bound, false otherwise
+*/
+bool NVEventStatusEGLIsBound();
+
+/** Finds and loads the named texture from the application's APK or the device's /data folder,
+returning the width, height and format information, as well as a pointer to the pixels. The
+pixel data can be loaded to OpenGL ES via glTexImage2D. When the application is done loading the
+texture, it MUST call NVEventReleaseTextureData() with the handle and pixels to avoid leaving
+resources
+@param filename The string name of the image file to be found and loaded. Supported formats include
+PNG
+and JPG.
+@param pixels (OUT) Returns a pointer to a block of pixel data allocated by the function and filled
+with
+the given image
+@param width (OUT) The width of the image in pixels
+@param height (OUT) The height of the image in pixels
+@param format (OUT) The GL format of the image (e.g. GL_RGB)
+@param type (OUT) The GL type of the image (e.g. GL_UNSIGNED_BYTE)
+@return An opaque handle to the texture resources to be passed to NVEventReleaseTextureData().
+Returns NULL on failure */
+void *NVEventGetTextureData(const char *filename, unsigned char *&pixels, unsigned int &width,
+ unsigned int &height, unsigned int &format, unsigned int &type);
+
+/** Releases the resources loaded in a successful call to NVEventGetTextureData()
+@param data The handle returned from the call to NVEventGetTextureData()
+@param pixels The pixel pointer returned from the matching call to NVEventGetTextureData() */
+void NVEventReleaseTextureData(void *data, unsigned char *pixels);
+
+/** Returns the platform-specific handle to the application instance, if supported. This
+function is, by definition platform-specific.
+@return A platform-specific handle to the application. */
+NVEventPlatformAppHandle NVEventGetPlatformAppHandle();
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.cpp
new file mode 100644
index 00000000..f2d3f983
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define MODULE "NVEventQueue"
+#define DBG_DETAILED 0
+#include "../nv_debug.h"
+
+#include "nv_event_queue.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <jni.h>
+#include <pthread.h>
+#include <time.h>
+#include <errno.h>
+#include <android/log.h>
+
+#define NVNextWrapped(index) (((index) + 1) & QUEUE_MASK)
+#define NVPrevWrapped(index) (((index)-1) & QUEUE_MASK)
+
+/* you must be inside a m_accessLock lock to invoke this! */
+static void unlockAll(NVEventSync *sem)
+{
+ sem->m_block = false;
+ pthread_cond_broadcast(&(sem->m_cond));
+}
+
+static int32_t pthread_cond_timeout(pthread_cond_t *cond, pthread_mutex_t *mutex, unsigned waitMS)
+{
+ struct timespec ts;
+ int32_t status;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ ts.tv_sec += (waitMS / 1000);
+ ts.tv_nsec += ((waitMS % 1000) * 1000000);
+
+ status = pthread_cond_timedwait(cond, mutex, &ts);
+
+ if (status == ETIMEDOUT)
+ return ETIMEDOUT;
+
+ return 0;
+}
+
+/* you must be inside mutex lock to invoke this! */
+static int32_t wait(NVEventSync *sem, pthread_mutex_t *mutex, int waitMS)
+{
+ // TBD - spec is dodgy; do we definitely release the mutex even if
+ // wait fails?
+ if (sem->m_block) {
+ if (waitMS < 0) {
+ return pthread_cond_wait(&sem->m_cond, mutex);
+ } else {
+ return pthread_cond_timeout(&sem->m_cond, mutex, (unsigned)waitMS);
+ }
+ } else {
+ // must release this, as failure assumes no lock
+ pthread_mutex_unlock(mutex);
+ return 1; // do not return 0 - we do not own the lock!
+ }
+}
+
+static void signal(NVEventSync *sem)
+{
+ pthread_cond_signal(&sem->m_cond);
+}
+
+static void broadcast(NVEventSync *sem)
+{
+ pthread_cond_broadcast(&sem->m_cond);
+}
+
+static void syncInit(NVEventSync *sync)
+{
+ pthread_cond_init(&(sync->m_cond), NULL);
+ sync->m_block = true;
+}
+
+static void syncDestroy(NVEventSync *sync)
+{
+ pthread_cond_destroy(&sync->m_cond);
+}
+
+/* you must be inside a m_accessLock lock to invoke this! */
+bool NVEventQueue::insert(const NVEvent *ev)
+{
+ // Is the queue full?
+ int32_t nextNext = NVNextWrapped(m_nextInsertIndex);
+ if (nextNext == m_headIndex) {
+ // TBD - what to do when we cannot insert (full queue)
+ return false;
+ }
+
+ NVEvent *evDest = m_events + m_nextInsertIndex;
+ memcpy(evDest, ev, sizeof(NVEvent));
+
+ m_nextInsertIndex = nextNext;
+ return true;
+}
+
+void NVEventQueue::Init()
+{
+ m_nextInsertIndex = 0;
+ m_headIndex = 0;
+ pthread_mutex_init(&(m_accessLock), NULL);
+ syncInit(&m_consumerSync);
+ syncInit(&m_blockerSync);
+
+ m_blocker = NULL;
+ m_blockerState = NO_BLOCKER;
+ m_blockerReturnVal = false;
+}
+
+void NVEventQueue::Shutdown()
+{
+ pthread_mutex_destroy(&(m_accessLock));
+
+ // free everyone...
+ unlockAll(&m_consumerSync);
+ unlockAll(&m_blockerSync);
+ syncDestroy(&(m_consumerSync));
+ syncDestroy(&(m_blockerSync));
+}
+
+void NVEventQueue::Flush()
+{
+ // TBD: Lock the mutex????
+ m_headIndex = m_nextInsertIndex;
+}
+
+void NVEventQueue::UnblockConsumer()
+{
+ unlockAll(&(m_consumerSync));
+}
+
+void NVEventQueue::UnblockProducer()
+{
+ unlockAll(&(m_blockerSync));
+}
+
+void NVEventQueue::Insert(const NVEvent *ev)
+{
+ pthread_mutex_lock(&(m_accessLock));
+
+ // insert the event and unblock a waiter
+ insert(ev);
+ signal(&m_consumerSync);
+ pthread_mutex_unlock(&(m_accessLock));
+}
+
+bool NVEventQueue::InsertBlocking(const NVEvent *ev)
+{
+ // TBD - how to handle the destruction of these mutexes
+
+ pthread_mutex_lock(&(m_accessLock));
+ while (m_blocker) {
+ if (wait(&(m_blockerSync), &(m_accessLock), QT3DS_EVENT_WAIT_FOREVER))
+ return false;
+ }
+
+ assert(!m_blocker);
+ assert(m_blockerState == NO_BLOCKER);
+
+ // we have the mutex _and_ the blocking event is NULL
+ // So now we can push a new one
+ m_blocker = ev;
+ m_blockerState = PENDING_BLOCKER;
+
+ // Release the consumer, as we just posted a new event
+ signal(&(m_consumerSync));
+
+ // Loop on the condition variable until we find out that
+ // there is a return value waiting for us. Since only we
+ // will null the blocker pointer, we will not let anyone
+ // else start to post a blocking event
+ while (m_blockerState != RETURNED_BLOCKER) {
+ if (wait(&(m_blockerSync), &(m_accessLock), QT3DS_EVENT_WAIT_FOREVER))
+ return false;
+ }
+
+ bool handled = m_blockerReturnVal;
+ m_blocker = NULL;
+ m_blockerState = NO_BLOCKER;
+
+ DEBUG("producer unblocking from consumer handling blocking event (%s)",
+ handled ? "true" : "false");
+
+ // We've handled the event, so the producer can release the
+ // next thread to potentially post a blocking event
+ signal(&(m_blockerSync));
+ pthread_mutex_unlock(&(m_accessLock));
+
+ return handled;
+}
+
+const NVEvent *NVEventQueue::RemoveOldest(int waitMSecs)
+{
+ pthread_mutex_lock(&(m_accessLock));
+
+ // Hmm - the last event we got from RemoveOldest was a
+ // blocker, and DoneWithEvent not called.
+ // Default to "false" as a return value
+ if (m_blockerState == PROCESSING_BLOCKER) {
+ m_blockerReturnVal = false;
+ m_blockerState = RETURNED_BLOCKER;
+ broadcast(&(m_blockerSync));
+ }
+
+ // Blocker is waiting - return it
+ // And push the blocker pipeline forward
+ if (m_blockerState == PENDING_BLOCKER) {
+ m_blockerState = PROCESSING_BLOCKER;
+ const NVEvent *ev = m_blocker;
+ pthread_mutex_unlock(&(m_accessLock));
+
+ return ev;
+ } else if (m_nextInsertIndex == m_headIndex) {
+ // We're empty - so what do we do?
+ if (waitMSecs == 0) {
+ goto no_event;
+ } else {
+ // wait for the specified time
+ wait(&(m_consumerSync), &(m_accessLock), (unsigned)waitMSecs);
+ }
+
+ // check again after exiting cond waits, either we had a timeout
+ if (m_blockerState == PENDING_BLOCKER) {
+ m_blockerState = PROCESSING_BLOCKER;
+ const NVEvent *ev = m_blocker;
+ pthread_mutex_unlock(&(m_accessLock));
+
+ return ev;
+ } else if (m_nextInsertIndex == m_headIndex) {
+ goto no_event;
+ }
+ }
+
+ {
+ // One way or another, we have an event...
+ const NVEvent *ev = m_events + m_headIndex;
+ m_headIndex = NVNextWrapped(m_headIndex);
+
+ pthread_mutex_unlock(&(m_accessLock));
+ return ev;
+ }
+
+no_event:
+ pthread_mutex_unlock(&(m_accessLock));
+ return NULL;
+}
+
+void NVEventQueue::DoneWithEvent(bool ret)
+{
+ // We only care about blockers for now.
+ // All other events just NOP
+ pthread_mutex_lock(&(m_accessLock));
+ if (m_blockerState == PROCESSING_BLOCKER) {
+ m_blockerReturnVal = ret;
+ m_blockerState = RETURNED_BLOCKER;
+ broadcast(&(m_blockerSync));
+ }
+ pthread_mutex_unlock(&(m_accessLock));
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.h
new file mode 100644
index 00000000..cde0bf26
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_event_queue.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_EVENT_QUEUE
+#define QT3DS_EVENT_QUEUE
+
+#include "nv_event.h"
+#include <pthread.h>
+
+class NVEventSync
+{
+public:
+ pthread_cond_t m_cond;
+ bool m_block;
+};
+
+class NVEventQueue
+{
+public:
+ void Init();
+ void Shutdown();
+ void Flush();
+ void UnblockConsumer();
+ void UnblockProducer();
+ // Events are copied, so caller can reuse ev immediately
+ void Insert(const NVEvent *ev);
+ // Waits until the event is consumed. Returns whether the
+ // consumer indicates handling the event or ignoring it
+ bool InsertBlocking(const NVEvent *ev);
+
+ // Returned event is valid only until the next call to
+ // RemoveOldest or until a call to DoneWithEvent
+ // Calling RemoveOldest again without calling DoneWithEvent
+ // indicates that the last event returned was NOT handled, and
+ // thus InsertNewestAndWait for that even would return false
+ const NVEvent *RemoveOldest(int waitMSecs);
+
+ // Indicates that all processing of the last event returned
+ // from RemoveOldest is complete. Also allows the app to indicate
+ // whether it handled the event or not.
+ // Do not dereference the last event pointer after calling this function
+ void DoneWithEvent(bool ret);
+
+protected:
+ bool insert(const NVEvent *ev);
+
+ enum { QUEUE_ELEMS = 256 };
+ enum { QUEUE_MASK = 0x000000ff };
+
+ int32_t m_nextInsertIndex;
+ int32_t m_headIndex;
+
+ pthread_mutex_t m_accessLock;
+
+ NVEventSync m_blockerSync;
+ NVEventSync m_consumerSync;
+
+ NVEvent m_events[QUEUE_ELEMS];
+ const NVEvent *m_blocker;
+ enum BlockerState { NO_BLOCKER, PENDING_BLOCKER, PROCESSING_BLOCKER, RETURNED_BLOCKER };
+ BlockerState m_blockerState;
+ bool m_blockerReturnVal;
+};
+
+#endif // #ifndef QT3DS_EVENT_QUEUE
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_keycode_mapping.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_keycode_mapping.h
new file mode 100644
index 00000000..143b633c
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/nv_keycode_mapping.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+class NVKeyCodeMapping
+{
+public:
+ NVKeyCodeMapping() { memset(m_keyMapping, 0, sizeof(NVKeyCode) * QT3DS_MAX_KEYCODE); }
+
+ void Init(JNIEnv *env, jobject thiz);
+
+ bool MapKey(int key, NVKeyCode &code);
+
+protected:
+ void AddKeyMapping(JNIEnv *env, jobject thiz, jclass KeyCode_class, const char *name,
+ NVKeyCode value);
+ NVKeyCode m_keyMapping[QT3DS_MAX_KEYCODE];
+};
+
+/* Init the mapping array, set up the event queue */
+void NVKeyCodeMapping::AddKeyMapping(JNIEnv *env, jobject thiz, jclass KeyCode_class,
+ const char *name, NVKeyCode value)
+{
+ // Add a new mapping...
+ jfieldID id = env->GetStaticFieldID(KeyCode_class, name, "I");
+ int keyID = env->GetStaticIntField(KeyCode_class, id);
+
+ if (keyID < QT3DS_MAX_KEYCODE) {
+ /* TODO TBD Should check for collision */
+ m_keyMapping[keyID] = value;
+ }
+}
+
+#define AddKeymappingMacro(name, value) AddKeyMapping(env, thiz, KeyCode_class, name, value)
+
+void NVKeyCodeMapping::Init(JNIEnv *env, jobject thiz)
+{
+ jclass KeyCode_class = env->FindClass("android/view/KeyEvent");
+
+ AddKeymappingMacro("KEYCODE_BACK", QT3DS_KEYCODE_BACK);
+ AddKeymappingMacro("KEYCODE_TAB", QT3DS_KEYCODE_TAB);
+ AddKeymappingMacro("KEYCODE_ENTER", QT3DS_KEYCODE_ENTER);
+
+ AddKeymappingMacro("KEYCODE_SPACE", QT3DS_KEYCODE_SPACE);
+ AddKeymappingMacro("KEYCODE_ENDCALL", QT3DS_KEYCODE_ENDCALL);
+ AddKeymappingMacro("KEYCODE_HOME", QT3DS_KEYCODE_HOME);
+
+ AddKeymappingMacro("KEYCODE_DPAD_LEFT", QT3DS_KEYCODE_DPAD_LEFT);
+ AddKeymappingMacro("KEYCODE_DPAD_UP", QT3DS_KEYCODE_DPAD_UP);
+ AddKeymappingMacro("KEYCODE_DPAD_RIGHT", QT3DS_KEYCODE_DPAD_RIGHT);
+ AddKeymappingMacro("KEYCODE_DPAD_DOWN", QT3DS_KEYCODE_DPAD_DOWN);
+
+ AddKeymappingMacro("KEYCODE_DEL", QT3DS_KEYCODE_DEL);
+
+ AddKeymappingMacro("KEYCODE_0", QT3DS_KEYCODE_0);
+ AddKeymappingMacro("KEYCODE_1", QT3DS_KEYCODE_1);
+ AddKeymappingMacro("KEYCODE_2", QT3DS_KEYCODE_2);
+ AddKeymappingMacro("KEYCODE_3", QT3DS_KEYCODE_3);
+ AddKeymappingMacro("KEYCODE_4", QT3DS_KEYCODE_4);
+ AddKeymappingMacro("KEYCODE_5", QT3DS_KEYCODE_5);
+ AddKeymappingMacro("KEYCODE_6", QT3DS_KEYCODE_6);
+ AddKeymappingMacro("KEYCODE_7", QT3DS_KEYCODE_7);
+ AddKeymappingMacro("KEYCODE_8", QT3DS_KEYCODE_8);
+ AddKeymappingMacro("KEYCODE_9", QT3DS_KEYCODE_9);
+
+ AddKeymappingMacro("KEYCODE_A", QT3DS_KEYCODE_A);
+ AddKeymappingMacro("KEYCODE_B", QT3DS_KEYCODE_B);
+ AddKeymappingMacro("KEYCODE_C", QT3DS_KEYCODE_C);
+ AddKeymappingMacro("KEYCODE_D", QT3DS_KEYCODE_D);
+ AddKeymappingMacro("KEYCODE_E", QT3DS_KEYCODE_E);
+ AddKeymappingMacro("KEYCODE_F", QT3DS_KEYCODE_F);
+ AddKeymappingMacro("KEYCODE_G", QT3DS_KEYCODE_G);
+ AddKeymappingMacro("KEYCODE_H", QT3DS_KEYCODE_H);
+ AddKeymappingMacro("KEYCODE_I", QT3DS_KEYCODE_I);
+ AddKeymappingMacro("KEYCODE_J", QT3DS_KEYCODE_J);
+ AddKeymappingMacro("KEYCODE_K", QT3DS_KEYCODE_K);
+ AddKeymappingMacro("KEYCODE_L", QT3DS_KEYCODE_L);
+ AddKeymappingMacro("KEYCODE_M", QT3DS_KEYCODE_M);
+ AddKeymappingMacro("KEYCODE_N", QT3DS_KEYCODE_N);
+ AddKeymappingMacro("KEYCODE_O", QT3DS_KEYCODE_O);
+ AddKeymappingMacro("KEYCODE_P", QT3DS_KEYCODE_P);
+ AddKeymappingMacro("KEYCODE_Q", QT3DS_KEYCODE_Q);
+ AddKeymappingMacro("KEYCODE_R", QT3DS_KEYCODE_R);
+ AddKeymappingMacro("KEYCODE_S", QT3DS_KEYCODE_S);
+ AddKeymappingMacro("KEYCODE_T", QT3DS_KEYCODE_T);
+ AddKeymappingMacro("KEYCODE_U", QT3DS_KEYCODE_U);
+ AddKeymappingMacro("KEYCODE_V", QT3DS_KEYCODE_V);
+ AddKeymappingMacro("KEYCODE_W", QT3DS_KEYCODE_W);
+ AddKeymappingMacro("KEYCODE_X", QT3DS_KEYCODE_X);
+ AddKeymappingMacro("KEYCODE_Y", QT3DS_KEYCODE_Y);
+ AddKeymappingMacro("KEYCODE_Z", QT3DS_KEYCODE_Z);
+
+ AddKeymappingMacro("KEYCODE_STAR", QT3DS_KEYCODE_STAR);
+ AddKeymappingMacro("KEYCODE_PLUS", QT3DS_KEYCODE_PLUS);
+ AddKeymappingMacro("KEYCODE_MINUS", QT3DS_KEYCODE_MINUS);
+
+ AddKeymappingMacro("KEYCODE_NUM", QT3DS_KEYCODE_NUM);
+
+ AddKeymappingMacro("KEYCODE_ALT_LEFT", QT3DS_KEYCODE_ALT_LEFT);
+ AddKeymappingMacro("KEYCODE_ALT_RIGHT", QT3DS_KEYCODE_ALT_RIGHT);
+
+ AddKeymappingMacro("KEYCODE_SHIFT_LEFT", QT3DS_KEYCODE_SHIFT_LEFT);
+ AddKeymappingMacro("KEYCODE_SHIFT_RIGHT", QT3DS_KEYCODE_SHIFT_RIGHT);
+
+ AddKeymappingMacro("KEYCODE_APOSTROPHE", QT3DS_KEYCODE_APOSTROPHE);
+ AddKeymappingMacro("KEYCODE_SEMICOLON", QT3DS_KEYCODE_SEMICOLON);
+ AddKeymappingMacro("KEYCODE_EQUALS", QT3DS_KEYCODE_EQUALS);
+ AddKeymappingMacro("KEYCODE_COMMA", QT3DS_KEYCODE_COMMA);
+ AddKeymappingMacro("KEYCODE_PERIOD", QT3DS_KEYCODE_PERIOD);
+ AddKeymappingMacro("KEYCODE_SLASH", QT3DS_KEYCODE_SLASH);
+ AddKeymappingMacro("KEYCODE_GRAVE", QT3DS_KEYCODE_GRAVE);
+ AddKeymappingMacro("KEYCODE_LEFT_BRACKET", QT3DS_KEYCODE_LEFT_BRACKET);
+ AddKeymappingMacro("KEYCODE_BACKSLASH", QT3DS_KEYCODE_BACKSLASH);
+ AddKeymappingMacro("KEYCODE_RIGHT_BRACKET", QT3DS_KEYCODE_RIGHT_BRACKET);
+}
+
+bool NVKeyCodeMapping::MapKey(int key, NVKeyCode &code)
+{
+ if (key < QT3DS_MAX_KEYCODE) {
+ code = m_keyMapping[key];
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/scoped_profiler.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/scoped_profiler.h
new file mode 100644
index 00000000..86b38663
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_event/scoped_profiler.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCOPED_PROFILER_H
+#define SCOPED_PROFILER_H
+
+#define PERF_STMTS 0
+#if PERF_STMTS == 1
+#include "../nv_time/nv_time.h"
+#include "stdio.h"
+#include "stdlib.h"
+
+static char s_bigString[4096];
+static int s_bigStringSize;
+
+static char s_tmpBuf[1024];
+
+class ScopedProfiler
+{
+public:
+ ScopedProfiler(const char *text)
+ {
+ _text = text;
+ _startTime = nvGetSystemTime();
+ __last = this;
+ }
+ ~ScopedProfiler() { stop(); }
+ inline void stop()
+ {
+ if (_text) {
+ int size = snprintf(s_tmpBuf, dimof(s_tmpBuf) - 1, "%d ms spent in %s",
+ (int)(nvGetSystemTime() - _startTime), _text);
+ strcat(s_bigString + s_bigStringSize, s_tmpBuf);
+ s_bigStringSize += size;
+ _text = 0;
+ }
+ }
+ static void stopLast()
+ {
+ if (__last)
+ __last->stop();
+ __last = 0;
+ }
+ const char *_text;
+ long _startTime;
+ static ScopedProfiler *__last;
+};
+ScopedProfiler *ScopedProfiler::__last = 0;
+
+#define STRINGIFIER(s) #s
+#define CONCAT_(a, b) a##b
+#define CONCAT(a, b) CONCAT_(a, b)
+#define PERFBLURB(s) \
+ static const char CONCAT(___str, __LINE__)[] = s "\n"; \
+ ScopedProfiler CONCAT(SCOPED_PROFILER, __LINE__)(CONCAT(___str, __LINE__));
+#define RESET_PROFILING() \
+ { \
+ DEBUG_D("%s", s_bigString); \
+ s_bigString[0] = 0; \
+ s_bigStringSize = 0; \
+ }
+#else
+#define PERFBLURB(s)
+#define RESET_PROFILING()
+#endif
+
+#endif // SCOPED_PROFILER_H
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_global.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_global.h
new file mode 100644
index 00000000..9d23d45f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_global.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_GLOBAL_H
+#define __INCLUDED_QT3DS_GLOBAL_H
+
+#include "nv_types.h"
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/NvVec.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/NvVec.h
new file mode 100644
index 00000000..4e5b09ce
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/NvVec.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_VEC_H
+#define INCLUDED_QT3DS_MATH_CPP_VEC_H
+
+#include "misc.h"
+
+struct _NvVec3
+{
+ union {
+ struct
+ {
+ float x, y, z;
+ };
+ float v[3];
+ };
+};
+
+struct NvVec3 : public _NvVec3
+{
+ NvVec3() { zero(); }
+
+ NvVec3(float x, float y, float z)
+ {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ }
+
+ NvVec3(NvVec3 const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ v[2] = that.v[2];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ v[2] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec3 &operator+=(NvVec3 const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ v[2] += that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator-=(NvVec3 const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ v[2] -= that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ v[2] *= s;
+ return *this;
+ }
+
+ NvVec3 &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ v[2] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec3 const &a, NvVec3 const &b)
+{
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+inline NvVec3 operator+(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a)
+{
+
+ return NvVec3(-a.v[0], -a.v[1], -a.v[2]);
+}
+
+inline NvVec3 operator*(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] * s, a.v[1] * s, a.v[2] * s);
+}
+
+inline NvVec3 operator*(float s, NvVec3 const &a)
+{
+
+ return NvVec3(s * a.v[0], s * a.v[1], s * a.v[2]);
+}
+
+inline NvVec3 operator/(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] / s, a.v[1] / s, a.v[2] / s);
+}
+
+inline float magnitude(NvVec3 const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec3 normalize(NvVec3 const &v)
+{
+ float l = magnitude(v);
+ return NvVec3(v[0] / l, v[1] / l, v[2] / l);
+}
+
+inline NvVec3 cross(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[1] * b.v[2] - a.v[2] * b.v[1], a.v[2] * b.v[0] - a.v[0] * b.v[2],
+ a.v[0] * b.v[1] - a.v[1] * b.v[0]);
+}
+
+inline bool operator==(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] == b.v[0] && a.v[1] == b.v[1] && a.v[2] == b.v[2]);
+}
+
+inline bool operator!=(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] != b.v[0] || a.v[1] != b.v[1] || a.v[2] != b.v[2]);
+}
+
+struct NvVec2f
+{
+ union {
+ struct
+ {
+ float x, y;
+ float v[2];
+ };
+ };
+
+ NvVec2f() { zero(); }
+
+ NvVec2f(float x, float y)
+ {
+ v[0] = x;
+ v[1] = y;
+ }
+
+ NvVec2f(NvVec2f const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec2f &operator+=(NvVec2f const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator-=(NvVec2f const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ return *this;
+ }
+
+ NvVec2f &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a[0] * b[0] + a[1] * b[1];
+}
+
+inline NvVec2f operator+(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] + b.v[0], a.v[1] + b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] - b.v[0], a.v[1] - b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a)
+{
+
+ return NvVec2f(-a.v[0], -a.v[1]);
+}
+
+inline NvVec2f operator*(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] * s, a.v[1] * s);
+}
+
+inline NvVec2f operator*(float s, NvVec2f const &a)
+{
+
+ return NvVec2f(s * a.v[0], s * a.v[1]);
+}
+
+inline NvVec2f operator/(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] / s, a.v[1] / s);
+}
+
+inline float magnitude(NvVec2f const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec2f normalize(NvVec2f const &v)
+{
+ float l = dot(v, v);
+ return NvVec2f(v[0] / l, v[1] / l);
+}
+
+inline float cross(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a.v[0] * b.v[1] - b.v[0] * a.v[1];
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/misc.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/misc.h
new file mode 100644
index 00000000..983410f3
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/misc.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_MISC_H
+#define INCLUDED_QT3DS_MATH_CPP_MISC_H
+
+inline bool nvIsPowerOfTwo(unsigned int i)
+{
+ return (i & (i - 1)) == 0;
+}
+
+inline float nvDegToRadf(float d)
+{
+ return d * 3.14159265358979323846f / 180.0f;
+}
+
+inline float nvRadToDegf(float r)
+{
+ return r * 180.0f / 3.14159265358979323846f;
+}
+
+/*
+ 'mod' differs from '%' in that it behaves correctly when either the
+ numerator or denominator is negative.
+*/
+
+inline int nvMod(int n, int d)
+{
+ int m = n % d;
+ return (((m < 0) && (d > 0)) || ((m > 0) && (d < 0))) ? (m + d) : m;
+}
+
+inline int nvAbs(int n)
+{
+ if (n < 0)
+ return -n;
+ return n;
+}
+
+inline int nvSign(int n)
+{
+ if (n > 0)
+ return 1;
+ if (n < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ This returns the smallest amplitude value x such that
+ nvMod(b + x, m) == a
+*/
+
+inline int nvDifMod(int a, int b, int m)
+{
+
+ int x1 = a - b;
+ int x2 = (x1 > 0) ? x1 - m : x1 + m;
+ return (nvAbs(x1) < nvAbs(x2)) ? x1 : x2;
+}
+
+inline float nvWrapf(float a, float min, float max)
+{
+
+ assert(max > min);
+
+ float d = max - min;
+ float s = a - min;
+ float q = s / d;
+ float m = q - floorf(q);
+ return m * d + min;
+}
+
+inline float nvClampf(float a, float min, float max)
+{
+ return (a < min) ? min : ((a > max) ? max : a);
+}
+
+inline int nvClampi(int i, int min, int max)
+{
+ return (i < min) ? min : ((i > max) ? max : i);
+}
+
+inline float nvGaussian(float x, float s)
+{
+ float c = s * sqrtf(2.0f * 3.14159265358979323846f);
+ return expf(-(x * x) / (2.0f * s * s)) / c;
+}
+
+inline float nvLerpf(float a, float b, float t)
+{
+ return a * (1.0f - t) + b * t;
+}
+
+inline float nvEasef(float t)
+{
+
+ float t_2 = t * t;
+ float t_3 = t_2 * t;
+ return 3.0f * t_2 - 2.0f * t_3;
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.cpp
new file mode 100644
index 00000000..b83cb39e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_math.h"
+
+static const double a = 16807.0;
+static const double m = 2147483647.0;
+
+static double nextSeed(double seed)
+{
+ double t = a * seed;
+ return t - m * (double)((int)(t / m));
+}
+
+GLfloat NvRandf()
+{
+ static double seed = 1.0;
+ seed = nextSeed(seed);
+ return (GLfloat)(seed * (1 / m));
+}
+
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime)
+{
+ // kdGetTimeUST is never supposed to decrease (i.e. that
+ // means it can't wrap, either. IIRC, it will wrap in
+ // 593 years). So we ignore that option...
+
+ // Used for frame-to-frame diffs, this will fit in 32b
+ // as long as the times are < ~4.3s apart
+ long long int diffTime = newTime - oldTime;
+
+ // Need to find a better way to do this.
+ // However, I believe we will be uSec precise (not run
+ // out of mantissa bits for uSecs) as long as the diff
+ // is < ~16s (1e-6 * (2^24))
+ return ((GLfloat)diffTime) / 1.0e9f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.h
new file mode 100644
index 00000000..cf2d8b30
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_math.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_MATH_H
+#define _QT3DS_MATH_H
+
+#include <GLES2/gl2.h>
+
+GLfloat NvRandf();
+
+/* These are the recommended "safer" ways to use GLfloat for time */
+
+/* Returns the seconds between the two given times */
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime);
+
+#define QT3DS_MILISECS_TO_UST(ms) ((long long int)(ms)*1000000)
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.cpp
new file mode 100644
index 00000000..e208ac31
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.cpp
@@ -0,0 +1,1030 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_matrix.h"
+
+int NvDifferentMatsf(GLfloat a[4][4], const GLfloat b[4][4])
+{
+ return ((&a[3][3] < &b[0][0]) || (&b[3][3] < &a[0][0]));
+}
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+}
+
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+}
+
+GLfloat NvVecLengthf(const GLfloat v[3])
+{
+ return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+}
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3])
+{
+ GLfloat const l = NvVecLengthf(v);
+ r[0] = v[0] / l;
+ r[1] = v[1] / l;
+ r[2] = v[2] / l;
+}
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] + b[0];
+ r[1] = a[1] + b[1];
+ r[2] = a[2] + b[2];
+}
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+ r[2] = a[2] - b[2];
+}
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ GLfloat t[3];
+
+ t[0] = a[1] * b[2] - a[2] * b[1];
+ t[1] = a[2] * b[0] - a[0] * b[2];
+ t[2] = a[0] * b[1] - a[1] * b[0];
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+}
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ GLfloat inv_w = 1.0f / (m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3]);
+
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * inv_w;
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * inv_w;
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * inv_w;
+}
+
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * a[3];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * a[3];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * a[3];
+ r[3] = m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3] * a[3];
+}
+
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2];
+}
+
+static void NvMultMat3x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2];
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x4f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2] + a[3][0] * b[0][3];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2] + a[3][1] * b[0][3];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2] + a[3][2] * b[0][3];
+ r[0][3] = a[0][3] * b[0][0] + a[1][3] * b[0][1] + a[2][3] * b[0][2] + a[3][3] * b[0][3];
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2] + a[3][0] * b[1][3];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2] + a[3][1] * b[1][3];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2] + a[3][2] * b[1][3];
+ r[1][3] = a[0][3] * b[1][0] + a[1][3] * b[1][1] + a[2][3] * b[1][2] + a[3][3] * b[1][3];
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2] + a[3][0] * b[2][3];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2] + a[3][1] * b[2][3];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2] + a[3][2] * b[2][3];
+ r[2][3] = a[0][3] * b[2][0] + a[1][3] * b[2][1] + a[2][3] * b[2][2] + a[3][3] * b[2][3];
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0] * b[3][3];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1] * b[3][3];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2] * b[3][3];
+ r[3][3] = a[0][3] * b[3][0] + a[1][3] * b[3][1] + a[2][3] * b[3][2] + a[3][3] * b[3][3];
+}
+
+void NvMultMatf(GLfloat result[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((a[0][3] == 0.0f) && (a[1][3] == 0.0f) && (a[2][3] == 0.0f) && (a[2][3] == 1.0f)
+ && (b[0][3] == 0.0f) && (b[1][3] == 0.0f) && (b[2][3] == 0.0f) && (b[2][3] == 1.0f)) {
+ if ((a[3][0] == 0.0f) && (a[3][1] == 0.0f) && (a[3][2] == 0.0f) && (b[3][0] == 0.0f)
+ && (b[3][1] == 0.0f) && (b[3][2] == 0.0f)) {
+ NvMultMat3x3f(r, a, b);
+ } else {
+ NvMultMat4x3f(r, a, b);
+ }
+ } else {
+ NvMultMat4x4f(r, a, b);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+static void NvInvMat3x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ /* x */
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ /* y */
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ /* z */
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x4f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] * m[3][3] + m[0][0] * m[1][2] * m[2][3] * m[3][1]
+ + m[0][0] * m[1][3] * m[2][1] * m[3][2] + m[0][1] * m[1][0] * m[2][3] * m[3][2]
+ + m[0][1] * m[1][2] * m[2][0] * m[3][3] + m[0][1] * m[1][3] * m[2][2] * m[3][0]
+ + m[0][2] * m[1][0] * m[2][1] * m[3][3] + m[0][2] * m[1][1] * m[2][3] * m[3][0]
+ + m[0][2] * m[1][3] * m[2][0] * m[3][1] + m[0][3] * m[1][0] * m[2][2] * m[3][1]
+ + m[0][3] * m[1][1] * m[2][0] * m[3][2] + m[0][3] * m[1][2] * m[2][1] * m[3][0]
+ + -m[0][0] * m[1][1] * m[2][3] * m[3][2] + -m[0][0] * m[1][2] * m[2][1] * m[3][3]
+ + -m[0][0] * m[1][3] * m[2][2] * m[3][1] + -m[0][1] * m[1][0] * m[2][2] * m[3][3]
+ + -m[0][1] * m[1][2] * m[2][3] * m[3][0] + -m[0][1] * m[1][3] * m[2][0] * m[3][2]
+ + -m[0][2] * m[1][0] * m[2][3] * m[3][1] + -m[0][2] * m[1][1] * m[2][0] * m[3][3]
+ + -m[0][2] * m[1][3] * m[2][1] * m[3][0] + -m[0][3] * m[1][0] * m[2][1] * m[3][2]
+ + -m[0][3] * m[1][1] * m[2][2] * m[3][0] + -m[0][3] * m[1][2] * m[2][0] * m[3][1];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] * m[3][3] + m[1][2] * m[2][3] * m[3][1]
+ + m[1][3] * m[2][1] * m[3][2] + -m[1][1] * m[2][3] * m[3][2]
+ + -m[1][2] * m[2][1] * m[3][3] + -m[1][3] * m[2][2] * m[3][1])
+ / d;
+
+ r[0][1] = (m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3]
+ + m[0][3] * m[2][2] * m[3][1] + -m[0][1] * m[2][2] * m[3][3]
+ + -m[0][2] * m[2][3] * m[3][1] + -m[0][3] * m[2][1] * m[3][2])
+ / d;
+
+ r[0][2] = (m[0][1] * m[1][2] * m[3][3] + m[0][2] * m[1][3] * m[3][1]
+ + m[0][3] * m[1][1] * m[3][2] + -m[0][1] * m[1][3] * m[3][2]
+ + -m[0][2] * m[1][1] * m[3][3] + -m[0][3] * m[1][2] * m[3][1])
+ / d;
+
+ r[0][3] = (m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3]
+ + m[0][3] * m[1][2] * m[2][1] + -m[0][1] * m[1][2] * m[2][3]
+ + -m[0][2] * m[1][3] * m[2][1] + -m[0][3] * m[1][1] * m[2][2])
+ / d;
+
+ r[1][0] = (m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3]
+ + m[1][3] * m[2][2] * m[3][0] + -m[1][0] * m[2][2] * m[3][3]
+ + -m[1][2] * m[2][3] * m[3][0] + -m[1][3] * m[2][0] * m[3][2])
+ / d;
+
+ r[1][1] = (m[0][0] * m[2][2] * m[3][3] + m[0][2] * m[2][3] * m[3][0]
+ + m[0][3] * m[2][0] * m[3][2] + -m[0][0] * m[2][3] * m[3][2]
+ + -m[0][2] * m[2][0] * m[3][3] + -m[0][3] * m[2][2] * m[3][0])
+ / d;
+
+ r[1][2] = (m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3]
+ + m[0][3] * m[1][2] * m[3][0] + -m[0][0] * m[1][2] * m[3][3]
+ + -m[0][2] * m[1][3] * m[3][0] + -m[0][3] * m[1][0] * m[3][2])
+ / d;
+
+ r[1][3] = (m[0][0] * m[1][2] * m[2][3] + m[0][2] * m[1][3] * m[2][0]
+ + m[0][3] * m[1][0] * m[2][2] + -m[0][0] * m[1][3] * m[2][2]
+ + -m[0][2] * m[1][0] * m[2][3] + -m[0][3] * m[1][2] * m[2][0])
+ / d;
+
+ r[2][0] = (m[1][0] * m[2][1] * m[3][3] + m[1][1] * m[2][3] * m[3][0]
+ + m[1][3] * m[2][0] * m[3][1] + -m[1][0] * m[2][3] * m[3][1]
+ + -m[1][1] * m[2][0] * m[3][3] + -m[1][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][1] =
+ (-m[0][0] * m[2][1] * m[3][3] + -m[0][1] * m[2][3] * m[3][0] + -m[0][3] * m[2][0] * m[3][1]
+ + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] + m[0][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][2] = (m[0][0] * m[1][1] * m[3][3] + m[0][1] * m[1][3] * m[3][0]
+ + m[0][3] * m[1][0] * m[3][1] + -m[0][0] * m[1][3] * m[3][1]
+ + -m[0][1] * m[1][0] * m[3][3] + -m[0][3] * m[1][1] * m[3][0])
+ / d;
+
+ r[2][3] = (m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3]
+ + m[0][3] * m[1][1] * m[2][0] + -m[0][1] * m[1][3] * m[2][0]
+ + -m[0][3] * m[1][0] * m[2][1] + -m[0][0] * m[1][1] * m[2][3])
+ / d;
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = (m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1]
+ + -m[0][1] * m[1][0] * m[2][2] + -m[0][2] * m[1][1] * m[2][0])
+ / d;
+}
+
+void NvInvMatf(GLfloat result[4][4], const GLfloat m[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((m[0][3] == 0.0f) && (m[1][3] == 0.0f) && (m[2][3] == 0.0f) && (m[2][3] == 1.0f)) {
+ if ((m[3][0] == 0.0f) && (m[3][1] == 0.0f) && (m[3][2] == 0.0f)) {
+ NvInvMat3x3f(r, m);
+ } else {
+ NvInvMat4x3f(r, m);
+ }
+ } else {
+ NvInvMat4x4f(r, m);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildIdentityMatf(GLfloat r[4][4])
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = x;
+ r[3][1] = y;
+ r[3][2] = z;
+ r[3][3] = 1.0f;
+}
+
+void NvMultTranslateMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y,
+ GLfloat z)
+{
+ GLfloat r[4][4]; /*temporary storage for result */
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[0][0] * x + m[1][0] * y + m[2][0] * z + m[3][0];
+ r[3][1] = m[0][1] * x + m[1][1] * y + m[2][1] * z + m[3][1];
+ r[3][2] = m[0][2] * x + m[1][2] * y + m[2][2] * z + m[3][2];
+ r[3][3] = m[0][3] * x + m[1][3] * y + m[2][3] * z + m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = x;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = y;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = z;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultScaleMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * x;
+ r[0][1] = m[0][1] * x;
+ r[0][2] = m[0][2] * x;
+ r[0][3] = m[0][3] * x;
+
+ r[1][0] = m[1][0] * y;
+ r[1][1] = m[1][1] * y;
+ r[1][2] = m[1][2] * y;
+ r[1][3] = m[1][3] * y;
+
+ r[2][0] = m[2][0] * z;
+ r[2][1] = m[2][1] * z;
+ r[2][2] = m[2][2] * z;
+ r[2][3] = m[2][3] * z;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = c;
+ r[1][2] = s;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = -s;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = 0.0f;
+ r[0][2] = -s;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = s;
+ r[2][1] = 0.0f;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = s;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = -s;
+ r[1][1] = c;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultRotXRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0] * c + m[2][0] * s;
+ r[1][1] = m[1][1] * c + m[2][1] * s;
+ r[1][2] = m[1][2] * c + m[2][2] * s;
+ r[1][3] = m[1][3] * c + m[2][3] * s;
+
+ r[2][0] = m[1][0] * -s + m[2][0] * c;
+ r[2][1] = m[1][1] * -s + m[2][1] * c;
+ r[2][2] = m[1][2] * -s + m[2][2] * c;
+ r[2][3] = m[1][3] * -s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotYRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[2][0] * -s;
+ r[0][1] = m[0][1] * c + m[2][1] * -s;
+ r[0][2] = m[0][2] * c + m[2][2] * -s;
+ r[0][3] = m[0][3] * c + m[2][3] * -s;
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[0][0] * s + m[2][0] * c;
+ r[2][1] = m[0][1] * s + m[2][1] * c;
+ r[2][2] = m[0][2] * s + m[2][2] * c;
+ r[2][3] = m[0][3] * s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotZRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[1][0] * s;
+ r[0][1] = m[0][1] * c + m[1][1] * s;
+ r[0][2] = m[0][2] * c + m[1][2] * s;
+ r[0][3] = m[0][3] * c + m[1][3] * s;
+
+ r[1][0] = m[0][0] * -s + m[1][0] * c;
+ r[1][1] = m[0][1] * -s + m[1][1] * c;
+ r[1][2] = m[0][2] * -s + m[1][2] * c;
+ r[1][3] = m[0][3] * -s + m[1][3] * c;
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotRadMatf(GLfloat result[4][4], const GLfloat axis[3], GLfloat radians)
+{
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ /* build a matrix from the quat */
+
+ result[0][0] = 1.0f - 2.0f * (j * j + k * k);
+ result[0][1] = 2.0f * (i * j + r * k);
+ result[0][2] = 2.0f * (i * k - r * j);
+ result[0][3] = 0.0f;
+
+ result[1][0] = 2.0f * (i * j - r * k);
+ result[1][1] = 1.0f - 2.0f * (i * i + k * k);
+ result[1][2] = 2.0f * (j * k + r * i);
+ result[1][3] = 0.0f;
+
+ result[2][0] = 2.0f * (i * k + r * j);
+ result[2][1] = 2.0f * (j * k - r * i);
+ result[2][2] = 1.0f - 2.0f * (i * i + j * j);
+ result[2][3] = 0.0f;
+
+ result[3][0] = 0.0f;
+ result[3][1] = 0.0f;
+ result[3][2] = 0.0f;
+ result[3][3] = 1.0f;
+}
+
+void NvMultRotRadMatf(GLfloat result[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians)
+{
+ GLfloat r[4][4];
+
+ {
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat const dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ {
+ /* build a matrix from the quat */
+
+ GLfloat const a00 = 1.0f - 2.0f * (j * j + k * k);
+ GLfloat const a01 = 2.0f * (i * j + r * k);
+ GLfloat const a02 = 2.0f * (i * k - r * j);
+
+ GLfloat const a10 = 2.0f * (i * j - r * k);
+ GLfloat const a11 = 1.0f - 2.0f * (i * i + k * k);
+ GLfloat const a12 = 2.0f * (j * k + r * i);
+
+ GLfloat const a20 = 2.0f * (i * k + r * j);
+ GLfloat const a21 = 2.0f * (j * k - r * i);
+ GLfloat const a22 = 1.0f - 2.0f * (i * i + j * j);
+
+ result[0][0] = m[0][0] * a00 + m[1][0] * a01 + m[2][0] * a02;
+ result[0][1] = m[0][1] * a00 + m[1][1] * a01 + m[2][1] * a02;
+ result[0][2] = m[0][2] * a00 + m[1][2] * a01 + m[2][2] * a02;
+ result[0][3] = m[0][3] * a00 + m[1][3] * a01 + m[2][3] * a02;
+
+ result[1][0] = m[0][0] * a10 + m[1][0] * a11 + m[2][0] * a12;
+ result[1][1] = m[0][1] * a10 + m[1][1] * a11 + m[2][1] * a12;
+ result[1][2] = m[0][2] * a10 + m[1][2] * a11 + m[2][2] * a12;
+ result[1][3] = m[0][3] * a10 + m[1][3] * a11 + m[2][3] * a12;
+
+ result[2][0] = m[0][0] * a20 + m[1][0] * a21 + m[2][0] * a22;
+ result[2][1] = m[0][1] * a20 + m[1][1] * a21 + m[2][1] * a22;
+ result[2][2] = m[0][2] * a20 + m[1][2] * a21 + m[2][2] * a22;
+ result[2][3] = m[0][3] * a20 + m[1][3] * a21 + m[2][3] * a22;
+
+ result[3][0] = m[3][0];
+ result[3][1] = m[3][1];
+ result[3][2] = m[3][2];
+ result[3][3] = m[3][3];
+ }
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotXRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotYRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotZRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotXRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotYRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotZRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees)
+{
+ NvBuildRotRadMatf(r, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees)
+{
+ NvMultRotRadMatf(r, m, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3])
+{
+ GLfloat ev[3];
+ GLfloat z[3];
+ GLfloat x_tmp[3];
+ GLfloat x[3];
+ GLfloat y[3];
+
+ NvSubVecf(ev, eye, obj);
+
+ NvNormalizeVecf(z, ev);
+
+ NvCrossProductf(x_tmp, up, z);
+
+ NvNormalizeVecf(x, x_tmp);
+
+ NvCrossProductf(y, z, x);
+
+ r[0][0] = x[0];
+ r[0][1] = y[0];
+ r[0][2] = z[0];
+ r[0][3] = 0.0f;
+
+ r[1][0] = x[1];
+ r[1][1] = y[1];
+ r[1][2] = z[1];
+ r[1][3] = 0.0f;
+
+ r[2][0] = x[2];
+ r[2][1] = y[2];
+ r[2][2] = z[2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = -x[0] * eye[0] + -x[1] * eye[1] + -x[2] * eye[2];
+ r[3][1] = -y[0] * eye[0] + -y[1] * eye[1] + -y[2] * eye[2];
+ r[3][2] = -z[0] * eye[0] + -z[1] * eye[1] + -z[2] * eye[2];
+ r[3][3] = 1.0f;
+}
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const m00 = znear * 2.0f / (right - left);
+ GLfloat const m11 = znear * 2.0f / (top - bottom);
+ GLfloat const m22 = -(zfar + znear) / (zfar - znear);
+
+ GLfloat const m20 = (right + left) / (right - left);
+ GLfloat const m21 = (top + bottom) / (top - bottom);
+
+ GLfloat const m32 = -(2.0f * zfar * znear) / (zfar - znear);
+ GLfloat const m23 = -1.0f;
+
+ r[0][0] = m00;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = m11;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = m20;
+ r[2][1] = m21;
+ r[2][2] = m22;
+ r[2][3] = m23;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = m32;
+ r[3][3] = 0.0f;
+}
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+ GLfloat const sz = -2.0f / (zfar - znear);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+ GLfloat const tz = -(zfar + znear) / (zfar - znear);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = sz;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = tz;
+ r[3][3] = 1.0f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.h
new file mode 100644
index 00000000..2a8e186e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_matrix.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MATRIX_H
+#define INCLUDED_MATRIX_H
+
+#include <GLES2/gl2.h>
+#include <math.h>
+#include <assert.h>
+
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4]);
+
+/* vector utilities */
+
+GLfloat NvVecLengthf(const GLfloat v[3]);
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3]);
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4]);
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+
+/* matrix utilities */
+
+void NvMultMatf(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4]);
+
+void NvInvMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+
+/* matrix building utilities */
+
+void NvBuildIdentityMatf(GLfloat r[4][4]);
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees);
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees);
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians);
+
+void NvBuildRotRadMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat radians);
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3]);
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top);
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+/* matrix concatenation utilities */
+
+void NvMultTranslateMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+void NvMultScaleMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees);
+
+void NvMultRotXRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotYRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotZRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+
+void NvMultRotRadMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.cpp
new file mode 100644
index 00000000..ae7ee010
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_quat.h"
+#include <stdlib.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4])
+{
+ memcpy(r, q, 4 * sizeof(GLfloat));
+}
+
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4])
+{
+ // Assumes that the quaternion is normalized!
+ GLfloat x2 = q[0] * 2.0f;
+ GLfloat y2 = q[1] * 2.0f;
+ GLfloat z2 = q[2] * 2.0f;
+ GLfloat xSq2 = x2 * q[0];
+ GLfloat ySq2 = y2 * q[1];
+ GLfloat zSq2 = z2 * q[2];
+ GLfloat xy2 = x2 * q[1];
+ GLfloat xz2 = x2 * q[2];
+ GLfloat xw2 = x2 * q[3];
+ GLfloat yz2 = y2 * q[2];
+ GLfloat yw2 = y2 * q[3];
+ GLfloat zw2 = z2 * q[3];
+
+ /* Matrix is
+ * | 1 - 2y^2 - 2z^2 2xy - 2zw 2xz + 2yw |
+ * | 2xy + 2zw 1 - 2x^2 - 2z^2 2yz - 2xw |
+ * | 2xz - 2yw 2yz + 2xw 1 - 2x^2 - 2y^2 |
+ */
+ r[0][0] = 1.0f - ySq2 - zSq2;
+ r[0][1] = xy2 - zw2;
+ r[0][2] = xz2 + yw2;
+
+ r[1][0] = xy2 + zw2;
+ r[1][1] = 1.0f - xSq2 - zSq2;
+ r[1][2] = yz2 - xw2;
+
+ r[2][0] = xz2 - yw2;
+ r[2][1] = yz2 + xw2;
+ r[2][2] = 1.0f - xSq2 - ySq2;
+}
+
+void NvQuatIdentity(GLfloat r[4])
+{
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = 1.0f;
+}
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3])
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = axis[0] * sina;
+ r[1] = axis[1] * sina;
+ r[2] = axis[2] * sina;
+ r[3] = cosa;
+}
+
+void NvQuatX(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = sina;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatY(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = sina;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatZ(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = sina;
+ r[3] = cosa;
+}
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatY(h, heading);
+ NvQuatX(p, pitch);
+ NvQuatZ(ro, roll);
+
+ NvQuatMult(r, h, p);
+ NvQuatMult(r, ro, r);
+}
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatZ(ro, roll);
+ NvQuatX(p, pitch);
+ NvQuatY(h, heading);
+
+ NvQuatMult(r, p, h);
+ NvQuatMult(r, r, ro);
+}
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4])
+{
+ return q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3];
+}
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4])
+{
+ const GLfloat q1x = q1[0];
+ const GLfloat q1y = q1[1];
+ const GLfloat q1z = q1[2];
+ const GLfloat q1w = q1[3];
+ const GLfloat q2x = q2[0];
+ const GLfloat q2y = q2[1];
+ const GLfloat q2z = q2[2];
+ const GLfloat q2w = q2[3];
+
+ r[0] = q1y * q2z - q2y * q1z + q1w * q2x + q2w * q1x;
+ r[1] = q1z * q2x - q2z * q1x + q1w * q2y + q2w * q1y;
+ r[2] = q1x * q2y - q2x * q1y + q1w * q2z + q2w * q1z;
+ r[3] = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
+}
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t)
+{
+ GLfloat omt = 1.0f - t;
+
+ if (NvQuatDot(q1, q2) < 0.0f) {
+ r[0] = -q1[0] * omt + q2[0] * t;
+ r[1] = -q1[1] * omt + q2[1] * t;
+ r[2] = -q1[2] * omt + q2[2] * t;
+ r[3] = -q1[3] * omt + q2[3] * t;
+ } else {
+ r[0] = q1[0] * omt + q2[0] * t;
+ r[1] = q1[1] * omt + q2[1] * t;
+ r[2] = q1[2] * omt + q2[2] * t;
+ r[3] = q1[3] * omt + q2[3] * t;
+ }
+
+ NvQuatNormalize(r, r);
+}
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4])
+{
+ GLfloat invLength = 1.0f / sqrtf(NvQuatDot(q, q));
+
+ r[0] = invLength * q[0];
+ r[1] = invLength * q[1];
+ r[2] = invLength * q[2];
+ r[3] = invLength * q[3];
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.h
new file mode 100644
index 00000000..688c30a7
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_math/nv_quat.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QUAT_H
+#define INCLUDED_QUAT_H
+
+#include <GLES2/gl2.h>
+#include <math.h>
+#include <assert.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4]);
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4]);
+
+void NvQuatIdentity(GLfloat r[4]);
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3]);
+
+void NvQuatX(GLfloat r[4], GLfloat radians);
+
+void NvQuatY(GLfloat r[4], GLfloat radians);
+
+void NvQuatZ(GLfloat r[4], GLfloat radians);
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t);
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4]);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.cpp
new file mode 100644
index 00000000..5d327551
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <jni.h>
+#include <android/log.h>
+#include <stdlib.h>
+#include "../nv_thread/nv_thread.h"
+
+#define MODULE "soundlib"
+#define THE_ACTIVITY "com/nvidia/devtech/AudioHelper"
+
+#include "nv_sound.h"
+
+static jobject s_globalThiz;
+static jclass NvAudioHelper_class;
+
+static jmethodID s_load;
+static jmethodID s_loadasset;
+static jmethodID s_resume;
+static jmethodID s_stop;
+static jmethodID s_play;
+static jmethodID s_volume;
+static jmethodID s_unload;
+static jmethodID s_source;
+static jmethodID s_startmusic;
+static jmethodID s_musicvolume;
+static jmethodID s_stopmusic;
+static jmethodID s_maxvolume;
+
+void NvSoundInit()
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ NvAudioHelper_class = env->FindClass(THE_ACTIVITY);
+
+ jmethodID getInstance = env->GetStaticMethodID(NvAudioHelper_class, "getInstance",
+ "()Lcom/nvidia/devtech/AudioHelper;");
+
+ __android_log_print(ANDROID_LOG_DEBUG, "apk", "inst = %d\n", getInstance);
+
+ s_load = env->GetMethodID(NvAudioHelper_class, "LoadSound", "(Ljava/lang/String;I)I");
+ s_loadasset = env->GetMethodID(NvAudioHelper_class, "LoadSoundAsset", "(Ljava/lang/String;I)I");
+ s_resume = env->GetMethodID(NvAudioHelper_class, "ResumeSound", "(I)V");
+ s_stop = env->GetMethodID(NvAudioHelper_class, "StopSound", "(I)V");
+ s_play = env->GetMethodID(NvAudioHelper_class, "PlaySound", "(IFFIIF)I");
+ s_volume = env->GetMethodID(NvAudioHelper_class, "SetVolume", "(IFF)V");
+ s_unload = env->GetMethodID(NvAudioHelper_class, "UnloadSample", "(I)Z");
+ s_source = env->GetMethodID(NvAudioHelper_class, "MusicSetDataSource", "(Ljava/lang/String;)V");
+ s_startmusic = env->GetMethodID(NvAudioHelper_class, "MusicStart", "()V");
+ s_musicvolume = env->GetMethodID(NvAudioHelper_class, "MusicVolume", "(FF)V");
+ s_stopmusic = env->GetMethodID(NvAudioHelper_class, "MusicStop", "()V");
+ s_maxvolume = env->GetMethodID(NvAudioHelper_class, "SetMaxVolume", "()V");
+
+ jobject thiz = env->CallStaticObjectMethod(NvAudioHelper_class, getInstance);
+
+ if (thiz == NULL) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "no this");
+ }
+
+ s_globalThiz = env->NewGlobalRef(thiz);
+}
+
+void NVSoundShutdown()
+{
+ s_globalThiz = NULL;
+}
+
+int SoundPoolLoadSFX(const char *FileName, int Priority)
+{
+ int SoundID;
+
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ jstring s = env->NewStringUTF(FileName);
+ SoundID = env->CallIntMethod(s_globalThiz, s_load, s, Priority);
+ env->DeleteLocalRef((jobject)s);
+
+ return SoundID;
+}
+
+int SoundPoolLoadSFXAsset(const char *FileName, int Priority)
+{
+ int SoundID;
+
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ jstring s = env->NewStringUTF(FileName);
+ SoundID = env->CallIntMethod(s_globalThiz, s_loadasset, s, Priority);
+ env->DeleteLocalRef((jobject)s);
+
+ return SoundID;
+}
+
+void SoundPoolResume(int StreamID)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->CallVoidMethod(s_globalThiz, s_resume, StreamID);
+}
+
+void SoundPoolStop(int StreamID)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ jint i = StreamID;
+
+ env->CallVoidMethod(s_globalThiz, s_stop, i);
+}
+
+int SoundPoolPlaySound(int SoundID, float LeftVolume, float RightVolume, int Priority, int Loop,
+ float Rate)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ return env->CallIntMethod(s_globalThiz, s_play, SoundID, LeftVolume, RightVolume, Priority,
+ Loop, Rate);
+}
+
+void SoundPoolSetVolume(int StreamID, float LeftVolume, float RightVolume)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->CallVoidMethod(s_globalThiz, s_volume, StreamID, LeftVolume, RightVolume);
+}
+
+bool SoundPoolUnloadSample(int SoundID)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ return env->CallBooleanMethod(s_globalThiz, s_unload, SoundID);
+}
+
+void MediaPlayerSetDataSource(const char *FileName)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ jstring s = env->NewStringUTF(FileName);
+ env->CallVoidMethod(s_globalThiz, s_source, s);
+ env->DeleteLocalRef((jobject)s);
+}
+
+void MediaPlayerStart()
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->CallVoidMethod(s_globalThiz, s_startmusic);
+}
+
+void MediaPlayerSetVolume(float LeftVolume, float RightVolume)
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->CallVoidMethod(s_globalThiz, s_musicvolume, LeftVolume, RightVolume);
+}
+
+void MediaPlayerStop()
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->CallVoidMethod(s_globalThiz, s_stopmusic);
+}
+
+void MediaSetMaxVolume()
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ env->CallVoidMethod(s_globalThiz, s_maxvolume);
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.h
new file mode 100644
index 00000000..006e04cc
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_sound/nv_sound.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_SOUND_H
+#define _QT3DS_SOUND_H
+
+void NvSoundInit();
+void NVSoundShutdown();
+
+int SoundPoolLoadSFX(const char *FileName, int Priority);
+int SoundPoolLoadSFXAsset(const char *FileName, int Priority);
+void SoundPoolResume(int StreamID);
+void SoundPoolStop(int StreamID);
+int SoundPoolPlaySound(int SoundID, float LeftVolume, float RightVolume, int Priority, int Loop,
+ float Rate);
+void SoundPoolSetVolume(int StreamID, float LeftVolume, float RightVolume);
+bool SoundPoolUnloadSample(int SoundID);
+
+void MediaPlayerSetDataSource(const char *FileName);
+void MediaPlayerStart();
+void MediaPlayerSetVolume(float LeftVolume, float RightVolume);
+void MediaPlayerStop();
+void MediaSetMaxVolume();
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.c b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.c
new file mode 100644
index 00000000..4fee911e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.c
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <jni.h>
+
+#include "nv_thread.h"
+#include <android/log.h>
+#include <pthread.h>
+
+static JavaVM *s_vm = NULL;
+static pthread_key_t s_jniEnvKey = 0;
+
+#define MODULE "NVThread"
+
+#include "../nv_debug.h"
+
+void NVThreadInit(JavaVM *vm)
+{
+ s_vm = vm;
+}
+
+JNIEnv *NVThreadGetCurrentJNIEnv()
+{
+ JNIEnv *env = NULL;
+ if (s_jniEnvKey) {
+ env = (JNIEnv *)pthread_getspecific(s_jniEnvKey);
+ } else {
+ pthread_key_create(&s_jniEnvKey, NULL);
+ }
+
+ if (!env) {
+ // do we have a VM cached?
+ if (!s_vm) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error - could not find JVM!");
+ return NULL;
+ }
+
+ // Hmm - no env for this thread cached yet
+ int error = (*s_vm)->AttachCurrentThread(s_vm, &env, NULL);
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, "AttachCurrentThread: %d, 0x%p", error, env);
+ if (error || !env) {
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE,
+ "Error - could not attach thread to JVM!");
+ return NULL;
+ }
+
+ pthread_setspecific(s_jniEnvKey, env);
+ }
+
+ return env;
+}
+
+typedef struct NVThreadInitStruct
+{
+ void *m_arg;
+ void *(*m_startRoutine)(void *);
+} NVThreadInitStruct;
+
+static void *NVThreadSpawnProc(void *arg)
+{
+ NVThreadInitStruct *init = (NVThreadInitStruct *)arg;
+ void *(*start_routine)(void *) = init->m_startRoutine;
+ void *data = init->m_arg;
+ void *ret;
+
+ free(arg);
+
+ NVThreadGetCurrentJNIEnv();
+
+ ret = start_routine(data);
+
+ if (s_vm)
+ (*s_vm)->DetachCurrentThread(s_vm);
+
+ return ret;
+}
+
+int NVThreadSpawnJNIThread(pthread_t *thread, pthread_attr_t const *attr,
+ void *(*start_routine)(void *), void *arg)
+{
+ if (!start_routine)
+ return -1;
+
+ NVThreadInitStruct *initData = malloc(sizeof(NVThreadInitStruct));
+
+ initData->m_startRoutine = start_routine;
+ initData->m_arg = arg;
+
+ int err = pthread_create(thread, attr, NVThreadSpawnProc, initData);
+
+ // If the thread was not started, then we need to delete the init data ourselves
+ if (err) {
+ free(initData);
+ }
+
+ return err;
+}
+
+// on linuces, signals can interrupt sleep functions, so you might need to
+// retry to get the full sleep going. I'm not entirely sure this is necessary
+// *here* clients could retry themselves when the exposed function returns
+// nonzero
+inline int __sleep(const struct timespec *req, struct timespec *rem)
+{
+ int ret = 1;
+ int i;
+ static const int sleepTries = 2;
+
+ struct timespec req_tmp = { 0 }, rem_tmp = { 0 };
+
+ rem_tmp = *req;
+ for (i = 0; i < sleepTries; ++i) {
+ req_tmp = rem_tmp;
+ int ret = nanosleep(&req_tmp, &rem_tmp);
+ if (ret == 0) {
+ ret = 0;
+ break;
+ }
+ }
+ if (rem)
+ *rem = rem_tmp;
+ return ret;
+}
+
+int NVThreadSleep(unsigned long millisec)
+{
+ struct timespec req = { 0 }, rem = { 0 };
+ time_t sec = (int)(millisec / 1000);
+
+ millisec = millisec - (sec * 1000);
+ req.tv_sec = sec;
+ req.tv_nsec = millisec * 1000000L;
+ return __sleep(&req, &rem);
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.h
new file mode 100644
index 00000000..63da9d54
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_THREAD_H
+#define __INCLUDED_QT3DS_THREAD_H
+
+#include <jni.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/** @file nv_thread.h
+ The NVThread library makes it easy to create native threads that can acess
+ JNI objects. By default, pthreads created in the Android NDK are NOT connected
+ to the JVM and JNI calls will fail. This library wraps thread creation in
+ such a way that pthreads created using it will connect to and disconnect from
+ the JVM as appropriate. Applications creating all of their threads with these
+ interfaces can use the provided NVThreadGetCurrentJNIEnv() function to
+ get the current thread's JNI context at any time.
+
+ Note that native-created threads still have JNI limitations over threads
+ that are calls down to native from Java. The JNI function FindClass will
+ NOT find application-specific classes when called from native threads.
+ Native code that needs to call FindClass and record the indices of Java
+ class members for later access must call FindClass and Get*FieldID/Get*MethodID
+ in threads calling from Java, such as JNI_OnLoad
+ */
+
+/**
+ Initializes the nv_thread system by connecting it to the JVM. This
+ function must be called as early as possible in the native code's
+ JNI_OnLoad function, so that the thread system is prepared for any
+ JNI-dependent library initialization calls.
+ @param vm The VM pointer - should be the JavaVM pointer sent to JNI_OnLoad.
+ */
+void NVThreadInit(JavaVM *vm);
+
+/**
+ Retrieves the JNIEnv object associated with the current thread, allowing
+ any thread that was creating with NVThreadSpawnJNIThread() to access the
+ JNI at will. This JNIEnv is NOT usable across multiple calls or threads
+ The function should be called in each function that requires a JNIEnv
+ @return The current thread's JNIEnv, or NULL if the thread was not created
+ by NVThreadSpawnJNIThread
+ @see NVThreadSpawnJNIThread
+ */
+JNIEnv *NVThreadGetCurrentJNIEnv();
+
+/**
+ Spwans a new native thread that is registered for use with JNI. Threads
+ created with this function will have access to JNI data via the JNIEnv
+ available from NVThreadGetCurrentJNIEnv().
+ @param thread is the same as in pthread_create
+ @param attr is the same as in pthread_create
+ @param start_routine is the same as in pthread_create
+ @param arg is the same as in pthread_create
+ @return 0 on success, -1 on failure
+ @see NVThreadGetCurrentJNIEnv
+*/
+int NVThreadSpawnJNIThread(pthread_t *thread, pthread_attr_t const *attr,
+ void *(*start_routine)(void *), void *arg);
+
+/**
+ Sleeps the current thread for the specified number of milliseconds
+ @param millisec Sleep time in ms
+ @return 0 on success, -1 on failure
+*/
+int NVThreadSleep(unsigned long millisec);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.cpp
new file mode 100644
index 00000000..425153d7
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_time.h"
+#include "../nv_thread/nv_thread.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <EGL/eglplatform.h>
+#include <time.h>
+#include <jni.h>
+#include <android/log.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_uint64_t EGLuint64NV;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
+#endif
+typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void);
+typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
+#endif
+
+void nvAcquireTimeExtensionJNI(JNIEnv *, jobject)
+{
+ nvAcquireTimeExtension();
+}
+
+jlong nvGetSystemTimeJNI(JNIEnv *, jobject)
+{
+ return (jlong)nvGetSystemTime();
+}
+
+static PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNVProc = NULL;
+static PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNVProc = NULL;
+static EGLuint64NV eglSystemTimeFrequency = 0;
+static bool timeExtensionQueried = false;
+
+void nvAcquireTimeExtension()
+{
+ if (timeExtensionQueried)
+ return;
+ timeExtensionQueried = true;
+
+ eglGetSystemTimeFrequencyNVProc =
+ (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)eglGetProcAddress("eglGetSystemTimeFrequencyNV");
+ eglGetSystemTimeNVProc = (PFNEGLGETSYSTEMTIMENVPROC)eglGetProcAddress("eglGetSystemTimeNV");
+
+ // now, we'll proceed through a series of sanity checking.
+ // if they all succeed, we'll return.
+ // if any fail, we fall out of conditional tests to end of function, null pointers, and return.
+ if (eglGetSystemTimeFrequencyNVProc && eglGetSystemTimeNVProc) {
+ eglSystemTimeFrequency = eglGetSystemTimeFrequencyNVProc();
+ }
+
+ // fall back if we've not returned already.
+ eglGetSystemTimeFrequencyNVProc = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)NULL;
+ eglGetSystemTimeNVProc = (PFNEGLGETSYSTEMTIMENVPROC)NULL;
+}
+
+bool nvValidTimeExtension()
+{
+ if (NULL == eglGetSystemTimeFrequencyNVProc || NULL == eglGetSystemTimeNVProc)
+ return false;
+ else
+ return true;
+}
+
+long nvGetSystemTime()
+{
+ static struct timeval start_time, end_time;
+ static int isinit = 0;
+ jlong curr_time = 0;
+
+ if (eglGetSystemTimeNVProc) {
+ EGLuint64NV egltime;
+ EGLuint64NV egltimequot;
+ EGLuint64NV egltimerem;
+
+ egltime = eglGetSystemTimeNVProc();
+
+ egltimequot = egltime / eglSystemTimeFrequency;
+ egltimerem = egltime - (eglSystemTimeFrequency * egltimequot);
+ egltimequot *= 1000;
+ egltimerem *= 1000;
+ egltimerem /= eglSystemTimeFrequency;
+ egltimequot += egltimerem;
+ return (jlong)egltimequot;
+ }
+
+ if (!isinit) {
+ gettimeofday(&start_time, 0);
+ isinit = 1;
+ }
+ gettimeofday(&end_time, 0);
+ curr_time = (end_time.tv_sec - start_time.tv_sec) * 1000;
+ curr_time += (end_time.tv_usec - start_time.tv_usec) / 1000;
+
+ return curr_time;
+}
+
+void NVTimeInit()
+{
+ JNIEnv *env = NVThreadGetCurrentJNIEnv();
+
+ JNINativeMethod methods_time[] = {
+ { "nvAcquireTimeExtension", "()V", (void *)nvAcquireTimeExtension },
+ { "nvGetSystemTime", "()J", (void *)nvGetSystemTime },
+ };
+ jclass k_time;
+ k_time = (env)->FindClass("com/nvidia/devtech/NvActivity");
+ (env)->RegisterNatives(k_time, methods_time, 2);
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.h
new file mode 100644
index 00000000..b6aacfc6
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_time/nv_time.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_TIME_H
+#define __INCLUDED_QT3DS_TIME_H
+
+#include <stdlib.h>
+
+void NVTimeInit();
+
+void nvAcquireTimeExtension();
+bool nvValidTimeExtension();
+// Return the system time, since boot, in milliseconds.
+long nvGetSystemTime();
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_types.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_types.h
new file mode 100644
index 00000000..1d1b0300
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_types.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_TYPES_H
+#define __INCLUDED_QT3DS_TYPES_H
+
+typedef unsigned char NvU8; // 0 to 255
+typedef unsigned short NvU16; // 0 to 65535
+typedef unsigned int NvU32; // 0 to 4294967295
+typedef unsigned long long NvU64; // 0 to 18446744073709551615
+typedef signed char NvS8; // -128 to 127
+typedef signed short NvS16; // -32768 to 32767
+typedef signed int NvS32; // -2147483648 to 2147483647
+typedef signed long long NvS64; // 2^-63 to 2^63-1
+
+// Explicitly sized floats
+typedef float NvF32; // IEEE Single Precision (S1E8M23)
+typedef double NvF64; // IEEE Double Precision (S1E11M52)
+
+// Boolean type
+#define QT3DS_FALSE 0
+#define QT3DS_TRUE 1
+typedef NvU8 NvBool;
+
+// Result of sizeof operator
+typedef unsigned long NvSize;
+
+// Type large enough to hold a relative file offset
+typedef long NvOffset;
+
+// Base NULL type.
+#define QT3DS_NULL 0
+
+// Error related
+typedef enum {
+ NvError_Success = 0,
+ NvError_NotSupported,
+ NvError_NotInitialized,
+ NvError_BadParameter,
+ NvError_InsufficientMemory,
+ NvError_NoEntries,
+ NvError_UnknownError,
+} NvError;
+
+#if 1 // defined(_DEBUG) // !!!!TBD TODO
+#define NvAssert(c)
+#else
+#define NvAssert(c) ((void)((c) ? 0 : (NvHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+// Other standardized typedefs
+typedef NvU64 NvUST; // U64 unadjusted system time value
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.cpp b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.cpp
new file mode 100644
index 00000000..8d450a1c
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_util.h"
+#include <jni.h>
+#include "../nv_thread/nv_thread.h"
+#include <string.h>
+
+static jmethodID g_hasAppLocalValue;
+static jmethodID g_getAppLocalValue;
+static jmethodID g_setAppLocalValue;
+static jmethodID g_getParameter;
+static jobject g_globalThiz;
+
+void NvUtilInit()
+{
+ JNIEnv *jniEnv = NVThreadGetCurrentJNIEnv();
+ jclass k = jniEnv->FindClass("com/nvidia/devtech/NvUtil");
+ g_hasAppLocalValue = jniEnv->GetMethodID(k, "hasAppLocalValue", "(Ljava/lang/String;)Z");
+ g_getAppLocalValue =
+ jniEnv->GetMethodID(k, "getAppLocalValue", "(Ljava/lang/String;)Ljava/lang/String;");
+ g_setAppLocalValue =
+ jniEnv->GetMethodID(k, "setAppLocalValue", "(Ljava/lang/String;Ljava/lang/String;)V");
+ g_getParameter =
+ jniEnv->GetMethodID(k, "getParameter", "(Ljava/lang/String;)Ljava/lang/String;");
+
+ jmethodID getInstance =
+ jniEnv->GetStaticMethodID(k, "getInstance", "()Lcom/nvidia/devtech/NvUtil;");
+ g_globalThiz = jniEnv->CallStaticObjectMethod(k, getInstance);
+}
+
+static void NvUtilGetStringValue(jmethodID method, char *buffer, int bufferLength, const char *name)
+{
+ JNIEnv *jniEnv = NVThreadGetCurrentJNIEnv();
+ jstring nameJava = jniEnv->NewStringUTF(name);
+ jstring valueJava = (jstring)jniEnv->CallObjectMethod(g_globalThiz, method, nameJava);
+
+ int len = 0;
+ if (valueJava) {
+ const char *string = jniEnv->GetStringUTFChars(valueJava, NULL);
+
+ len = strlen(string);
+ if (len > bufferLength - 1)
+ len = bufferLength - 1;
+ strncpy(buffer, string, len);
+ jniEnv->ReleaseStringUTFChars(valueJava, string);
+ }
+ buffer[len] = '\0';
+}
+
+void NvUtilGetLocalAppValue(char *buffer, int bufferLength, const char *name)
+{
+ NvUtilGetStringValue(g_getAppLocalValue, buffer, bufferLength, name);
+}
+
+bool NvUtilHasLocalAppValue(const char *name)
+{
+ JNIEnv *jniEnv = NVThreadGetCurrentJNIEnv();
+ jstring nameJava = jniEnv->NewStringUTF(name);
+ jboolean hasIt = jniEnv->CallBooleanMethod(g_globalThiz, g_hasAppLocalValue, nameJava);
+
+ return (hasIt == JNI_TRUE) ? true : false;
+}
+
+void NvUtilSetLocalAppValue(const char *name, const char *value)
+{
+ JNIEnv *jniEnv = NVThreadGetCurrentJNIEnv();
+ jstring nameJava = jniEnv->NewStringUTF(name);
+ jstring valueJava = jniEnv->NewStringUTF(value);
+ jniEnv->CallVoidMethod(g_globalThiz, g_setAppLocalValue, nameJava, valueJava);
+}
+
+void NvUtilGetParameter(char *buffer, int bufferLength, const char *parameter)
+{
+ NvUtilGetStringValue(g_getParameter, buffer, bufferLength, parameter);
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.h b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.h
new file mode 100644
index 00000000..2ff38690
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_util/nv_util.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_NV_UTIL_H
+#define __INCLUDED_NV_UTIL_H
+
+/** @file nv_util.h
+ * Used to set and retrieve Java parameter and shader values from
+ * within native code. Both command-line arguments and predefined
+ * shared values, such as the location of the external storage are
+ * available
+ */
+
+/**
+ Initializes the library. This function MUST be called from the application's
+ JNI_OnLoad, from a function known to be called by JNI_OnLoad, or from a function
+ in a Java-called thread. nv_thread-created native threads cannot call this
+ initialization function.
+ @see nv_thread.h
+ */
+void NvUtilInit();
+
+/**
+ * Used to retrieve Java-set string values in native code
+ * Pre-set values include:
+ * <ul>
+ * <li> STORAGE_ROOT: The full path to the external storage device (SD card)
+ * </ul>
+ * Gets the specified key value from the app local value list
+ * @param buffer The buffer to receive the value's string value
+ * @param bufferLength the size of buffer in bytes
+ * @param The name of the value to retrieve
+ */
+void NvUtilGetLocalAppValue(char *buffer, int bufferLength, const char *name);
+
+/**
+ * Used to verify Java-set string values in native code
+ * @param name The name of the value to verify
+ * @return true if the value exists, false if not
+ */
+bool NvUtilHasLocalAppValue(const char *name);
+
+/**
+ * Used to share string values between native and Java code
+ * Sets the specified key value in the app local value list
+ * @param name The key to set the value of
+ * @param value The value
+ */
+void NvUtilSetLocalAppValue(const char *name, const char *value);
+
+/**
+ * A JNI-accessible version of NvUtil::getParameter. This function is used to get the parameters
+ * used to start the Activity via, for example:
+ * <pre>
+ * adb shell am start -a android.intent.action.MAIN -n
+ * com.nvidia.devtech.water/com.nvidia.devtech.water.Water -e param1 1 -e param2 2
+ * </pre>
+ * Where "param1" and "param2" are the parameter names and "1" and "2" are the parameter values.
+ *
+ * @param buffer The buffer to receive the parameter's string value
+ * @param bufferLength the size of buffer in bytes
+ * @param The name of the parameter to retrieve
+ */
+void NvUtilGetParameter(char *buffer, int bufferLength, const char *parameter);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_color.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_color.h
new file mode 100644
index 00000000..b9347529
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_color.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_COLOR_H
+#define _QT3DS_COLOR_H
+
+/** @file nv_color.h
+ Simple abstraction for RGBA colors as parameters to various libraries/functions.
+*/
+
+/** Base type for a single color channel (8-bit unsigned). */
+typedef unsigned char NvPCColor8;
+
+//#define NV_COLOR_BREAKOLD
+#ifdef NV_COLOR_BREAKOLD // uses a struct to break backwards-compat and accidental uses
+
+typedef struct
+{
+ NvPCColor8 r;
+ NvPCColor8 g;
+ NvPCColor8 b;
+ NvPCColor8 a;
+} NvPackedColor;
+
+static const NvPackedColor gnvpcwhite = { 255, 255, 255, 255 };
+static const NvPackedColor gnvpcblack = { 0, 0, 0, 255 };
+
+#define NV_PACKED_COLOR(r, g, b, a) \
+ { \
+ (NvPCColor8)(r), (NvPCColor8)(g), (NvPCColor8)(b), (NvPCColor8)(a) \
+ }
+
+#define NV_PC_PREDEF_WHITE gnvpcwhite
+#define NV_PC_PREDEF_BLACK gnvpcblack
+
+#define NV_PC_RED(c) (c.r)
+#define NV_PC_GREEN(c) (c.g)
+#define NV_PC_BLUE(c) (c.b)
+#define NV_PC_ALPHA(c) (c.a)
+
+#define NV_PC_PACK_UINT(c) (*(unsigned int *)(&(c)))
+
+#define NV_PC_EQUAL(x, y) ((x).r == (y).r && (x).g == (y).g && (x).b == (y).b && (x).a == (y).a)
+
+#else /* code that doesn't break old pass-as-uint stuff */
+
+/** Main type declaration for a packed 4-color construct. */
+typedef unsigned int NvPackedColor;
+
+/** A macro to build a packed color, passing in RGBA as four 8-bit integer values. */
+#define NV_PACKED_COLOR(r, g, b, a) \
+ ((NvPackedColor)(((((int)(a)) & 0xFF) << 24) | ((((int)(b)) & 0xFF) << 16) \
+ | ((((int)(g)) & 0xFF) << 8) | ((((int)(r)) & 0xFF))))
+
+/** A predefined constant for WHITE. */
+#define NV_PC_PREDEF_WHITE NV_PACKED_COLOR(0xFF, 0xFF, 0xFF, 0xFF)
+/** A predefined constant for BLACK. */
+#define NV_PC_PREDEF_BLACK NV_PACKED_COLOR(0x00, 0x00, 0x00, 0xFF)
+
+/** A macro for 'extracting' the red value from an NvPackedColor. */
+#define NV_PC_RED(c) ((c >> 0) & 0xff)
+/** A macro for 'extracting' the green value from an NvPackedColor. */
+#define NV_PC_GREEN(c) ((c >> 8) & 0xff)
+/** A macro for 'extracting' the blue value from an NvPackedColor. */
+#define NV_PC_BLUE(c) ((c >> 16) & 0xff)
+/** A macro for 'extracting' the alpha value from an NvPackedColor. */
+#define NV_PC_ALPHA(c) ((c >> 24) & 0xff)
+
+/** A macro requesting the packed color repacked into a 32-bit unsigned int.
+ This is a no-op for the color-as-uint approach.
+*/
+#define NV_PC_PACK_UINT(c) (c)
+/** A macro for testing the equality of two NvPackedColors. */
+#define NV_PC_EQUAL(x, y) (x == y)
+#endif
+
+/** A macro for mapping a single packed color channel into its floating point [0,1] rep. */
+#define NV_PC_TO_FLOAT(c) (c / 255.0f)
+
+#endif /*_QT3DS_COLOR_H*/
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_debug.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_debug.h
new file mode 100644
index 00000000..2559dd6f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_debug.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_DEBUG_H
+#define __INCLUDED_QT3DS_DEBUG_H
+
+#define CT_ASSERT(tag, cond) enum { COMPILE_TIME_ASSERT__##tag = 1 / (cond) }
+
+#define dimof(x) (sizeof(x) / sizeof(x[0]))
+#include <android/log.h>
+
+#define DBG_DETAILED 0
+
+#if 0
+
+ // the detailed prefix can be customised by setting DBG_DETAILED_PREFIX. See
+ // below as a reference.
+ // NOTE: fmt is the desired format string and must be in the prefix.
+ //#ifndef DBG_DETAILED_PREFIX
+ // #define DBG_DETAILED_PREFIX "%s, %s, line %d: " fmt, __FILE__, __FUNCTION__, __LINE__,
+ //#endif
+ //#define DEBUG_D_(fmt, args...)
+ //#define DEBUG_D(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, (DBG_DETAILED_PREFIX) ## args)
+
+#else
+
+#ifdef STRINGIFY
+#pragma push_macro("STRINGIFY")
+#undef STRINGIFY
+#define STRINGIFYPUSHED_____
+#endif
+#define STRINGIFY(x) #x
+
+// debug macro, includes file name function name and line number
+#define TO(x) typeof(x)
+#define DEBUG_D_(file, line, fmt, args...) \
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, file ", %s, line(" STRINGIFY(line) "): " fmt, \
+ __FUNCTION__, ##args)
+#define DEBUG_D(fmt, args...) DEBUG_D_(__FILE__, __LINE__, fmt, ##args)
+
+#ifdef STRINGIFYPUSHED_____
+#undef STRINGIFYPUSHED_____
+#pragma pop_macro("STRINGIFY")
+#endif
+
+#endif
+
+// basic debug macro
+#define DEBUG_(fmt, args...) (__android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args))
+
+// Debug macro that can be switched to spew a file name,
+// function and line number using DEBUG_DETAILED
+#if DBG_DETAILED == 1
+#define DEBUG(fmt, args...) DEBUG_D(fmt, ##args)
+#else
+#define DEBUG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args)
+#endif
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_global.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_global.h
new file mode 100644
index 00000000..9d23d45f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_global.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_GLOBAL_H
+#define __INCLUDED_QT3DS_GLOBAL_H
+
+#include "nv_types.h"
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/NvVec.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/NvVec.h
new file mode 100644
index 00000000..4e5b09ce
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/NvVec.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_VEC_H
+#define INCLUDED_QT3DS_MATH_CPP_VEC_H
+
+#include "misc.h"
+
+struct _NvVec3
+{
+ union {
+ struct
+ {
+ float x, y, z;
+ };
+ float v[3];
+ };
+};
+
+struct NvVec3 : public _NvVec3
+{
+ NvVec3() { zero(); }
+
+ NvVec3(float x, float y, float z)
+ {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ }
+
+ NvVec3(NvVec3 const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ v[2] = that.v[2];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ v[2] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec3 &operator+=(NvVec3 const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ v[2] += that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator-=(NvVec3 const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ v[2] -= that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ v[2] *= s;
+ return *this;
+ }
+
+ NvVec3 &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ v[2] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec3 const &a, NvVec3 const &b)
+{
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+inline NvVec3 operator+(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a)
+{
+
+ return NvVec3(-a.v[0], -a.v[1], -a.v[2]);
+}
+
+inline NvVec3 operator*(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] * s, a.v[1] * s, a.v[2] * s);
+}
+
+inline NvVec3 operator*(float s, NvVec3 const &a)
+{
+
+ return NvVec3(s * a.v[0], s * a.v[1], s * a.v[2]);
+}
+
+inline NvVec3 operator/(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] / s, a.v[1] / s, a.v[2] / s);
+}
+
+inline float magnitude(NvVec3 const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec3 normalize(NvVec3 const &v)
+{
+ float l = magnitude(v);
+ return NvVec3(v[0] / l, v[1] / l, v[2] / l);
+}
+
+inline NvVec3 cross(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[1] * b.v[2] - a.v[2] * b.v[1], a.v[2] * b.v[0] - a.v[0] * b.v[2],
+ a.v[0] * b.v[1] - a.v[1] * b.v[0]);
+}
+
+inline bool operator==(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] == b.v[0] && a.v[1] == b.v[1] && a.v[2] == b.v[2]);
+}
+
+inline bool operator!=(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] != b.v[0] || a.v[1] != b.v[1] || a.v[2] != b.v[2]);
+}
+
+struct NvVec2f
+{
+ union {
+ struct
+ {
+ float x, y;
+ float v[2];
+ };
+ };
+
+ NvVec2f() { zero(); }
+
+ NvVec2f(float x, float y)
+ {
+ v[0] = x;
+ v[1] = y;
+ }
+
+ NvVec2f(NvVec2f const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec2f &operator+=(NvVec2f const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator-=(NvVec2f const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ return *this;
+ }
+
+ NvVec2f &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a[0] * b[0] + a[1] * b[1];
+}
+
+inline NvVec2f operator+(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] + b.v[0], a.v[1] + b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] - b.v[0], a.v[1] - b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a)
+{
+
+ return NvVec2f(-a.v[0], -a.v[1]);
+}
+
+inline NvVec2f operator*(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] * s, a.v[1] * s);
+}
+
+inline NvVec2f operator*(float s, NvVec2f const &a)
+{
+
+ return NvVec2f(s * a.v[0], s * a.v[1]);
+}
+
+inline NvVec2f operator/(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] / s, a.v[1] / s);
+}
+
+inline float magnitude(NvVec2f const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec2f normalize(NvVec2f const &v)
+{
+ float l = dot(v, v);
+ return NvVec2f(v[0] / l, v[1] / l);
+}
+
+inline float cross(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a.v[0] * b.v[1] - b.v[0] * a.v[1];
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/misc.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/misc.h
new file mode 100644
index 00000000..983410f3
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/misc.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_MISC_H
+#define INCLUDED_QT3DS_MATH_CPP_MISC_H
+
+inline bool nvIsPowerOfTwo(unsigned int i)
+{
+ return (i & (i - 1)) == 0;
+}
+
+inline float nvDegToRadf(float d)
+{
+ return d * 3.14159265358979323846f / 180.0f;
+}
+
+inline float nvRadToDegf(float r)
+{
+ return r * 180.0f / 3.14159265358979323846f;
+}
+
+/*
+ 'mod' differs from '%' in that it behaves correctly when either the
+ numerator or denominator is negative.
+*/
+
+inline int nvMod(int n, int d)
+{
+ int m = n % d;
+ return (((m < 0) && (d > 0)) || ((m > 0) && (d < 0))) ? (m + d) : m;
+}
+
+inline int nvAbs(int n)
+{
+ if (n < 0)
+ return -n;
+ return n;
+}
+
+inline int nvSign(int n)
+{
+ if (n > 0)
+ return 1;
+ if (n < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ This returns the smallest amplitude value x such that
+ nvMod(b + x, m) == a
+*/
+
+inline int nvDifMod(int a, int b, int m)
+{
+
+ int x1 = a - b;
+ int x2 = (x1 > 0) ? x1 - m : x1 + m;
+ return (nvAbs(x1) < nvAbs(x2)) ? x1 : x2;
+}
+
+inline float nvWrapf(float a, float min, float max)
+{
+
+ assert(max > min);
+
+ float d = max - min;
+ float s = a - min;
+ float q = s / d;
+ float m = q - floorf(q);
+ return m * d + min;
+}
+
+inline float nvClampf(float a, float min, float max)
+{
+ return (a < min) ? min : ((a > max) ? max : a);
+}
+
+inline int nvClampi(int i, int min, int max)
+{
+ return (i < min) ? min : ((i > max) ? max : i);
+}
+
+inline float nvGaussian(float x, float s)
+{
+ float c = s * sqrtf(2.0f * 3.14159265358979323846f);
+ return expf(-(x * x) / (2.0f * s * s)) / c;
+}
+
+inline float nvLerpf(float a, float b, float t)
+{
+ return a * (1.0f - t) + b * t;
+}
+
+inline float nvEasef(float t)
+{
+
+ float t_2 = t * t;
+ float t_3 = t_2 * t;
+ return 3.0f * t_2 - 2.0f * t_3;
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.cpp b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.cpp
new file mode 100644
index 00000000..b83cb39e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_math.h"
+
+static const double a = 16807.0;
+static const double m = 2147483647.0;
+
+static double nextSeed(double seed)
+{
+ double t = a * seed;
+ return t - m * (double)((int)(t / m));
+}
+
+GLfloat NvRandf()
+{
+ static double seed = 1.0;
+ seed = nextSeed(seed);
+ return (GLfloat)(seed * (1 / m));
+}
+
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime)
+{
+ // kdGetTimeUST is never supposed to decrease (i.e. that
+ // means it can't wrap, either. IIRC, it will wrap in
+ // 593 years). So we ignore that option...
+
+ // Used for frame-to-frame diffs, this will fit in 32b
+ // as long as the times are < ~4.3s apart
+ long long int diffTime = newTime - oldTime;
+
+ // Need to find a better way to do this.
+ // However, I believe we will be uSec precise (not run
+ // out of mantissa bits for uSecs) as long as the diff
+ // is < ~16s (1e-6 * (2^24))
+ return ((GLfloat)diffTime) / 1.0e9f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.h
new file mode 100644
index 00000000..2ef7bba0
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_math.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_MATH_H
+#define _QT3DS_MATH_H
+
+#include <QtGui/qopengl.h>
+
+GLfloat NvRandf();
+
+/* These are the recommended "safer" ways to use GLfloat for time */
+
+/* Returns the seconds between the two given times */
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime);
+
+#define QT3DS_MILISECS_TO_UST(ms) ((long long int)(ms)*1000000)
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.cpp b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.cpp
new file mode 100644
index 00000000..e208ac31
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.cpp
@@ -0,0 +1,1030 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_matrix.h"
+
+int NvDifferentMatsf(GLfloat a[4][4], const GLfloat b[4][4])
+{
+ return ((&a[3][3] < &b[0][0]) || (&b[3][3] < &a[0][0]));
+}
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+}
+
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+}
+
+GLfloat NvVecLengthf(const GLfloat v[3])
+{
+ return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+}
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3])
+{
+ GLfloat const l = NvVecLengthf(v);
+ r[0] = v[0] / l;
+ r[1] = v[1] / l;
+ r[2] = v[2] / l;
+}
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] + b[0];
+ r[1] = a[1] + b[1];
+ r[2] = a[2] + b[2];
+}
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+ r[2] = a[2] - b[2];
+}
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ GLfloat t[3];
+
+ t[0] = a[1] * b[2] - a[2] * b[1];
+ t[1] = a[2] * b[0] - a[0] * b[2];
+ t[2] = a[0] * b[1] - a[1] * b[0];
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+}
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ GLfloat inv_w = 1.0f / (m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3]);
+
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * inv_w;
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * inv_w;
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * inv_w;
+}
+
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * a[3];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * a[3];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * a[3];
+ r[3] = m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3] * a[3];
+}
+
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2];
+}
+
+static void NvMultMat3x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2];
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x4f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2] + a[3][0] * b[0][3];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2] + a[3][1] * b[0][3];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2] + a[3][2] * b[0][3];
+ r[0][3] = a[0][3] * b[0][0] + a[1][3] * b[0][1] + a[2][3] * b[0][2] + a[3][3] * b[0][3];
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2] + a[3][0] * b[1][3];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2] + a[3][1] * b[1][3];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2] + a[3][2] * b[1][3];
+ r[1][3] = a[0][3] * b[1][0] + a[1][3] * b[1][1] + a[2][3] * b[1][2] + a[3][3] * b[1][3];
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2] + a[3][0] * b[2][3];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2] + a[3][1] * b[2][3];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2] + a[3][2] * b[2][3];
+ r[2][3] = a[0][3] * b[2][0] + a[1][3] * b[2][1] + a[2][3] * b[2][2] + a[3][3] * b[2][3];
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0] * b[3][3];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1] * b[3][3];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2] * b[3][3];
+ r[3][3] = a[0][3] * b[3][0] + a[1][3] * b[3][1] + a[2][3] * b[3][2] + a[3][3] * b[3][3];
+}
+
+void NvMultMatf(GLfloat result[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((a[0][3] == 0.0f) && (a[1][3] == 0.0f) && (a[2][3] == 0.0f) && (a[2][3] == 1.0f)
+ && (b[0][3] == 0.0f) && (b[1][3] == 0.0f) && (b[2][3] == 0.0f) && (b[2][3] == 1.0f)) {
+ if ((a[3][0] == 0.0f) && (a[3][1] == 0.0f) && (a[3][2] == 0.0f) && (b[3][0] == 0.0f)
+ && (b[3][1] == 0.0f) && (b[3][2] == 0.0f)) {
+ NvMultMat3x3f(r, a, b);
+ } else {
+ NvMultMat4x3f(r, a, b);
+ }
+ } else {
+ NvMultMat4x4f(r, a, b);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+static void NvInvMat3x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ /* x */
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ /* y */
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ /* z */
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x4f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] * m[3][3] + m[0][0] * m[1][2] * m[2][3] * m[3][1]
+ + m[0][0] * m[1][3] * m[2][1] * m[3][2] + m[0][1] * m[1][0] * m[2][3] * m[3][2]
+ + m[0][1] * m[1][2] * m[2][0] * m[3][3] + m[0][1] * m[1][3] * m[2][2] * m[3][0]
+ + m[0][2] * m[1][0] * m[2][1] * m[3][3] + m[0][2] * m[1][1] * m[2][3] * m[3][0]
+ + m[0][2] * m[1][3] * m[2][0] * m[3][1] + m[0][3] * m[1][0] * m[2][2] * m[3][1]
+ + m[0][3] * m[1][1] * m[2][0] * m[3][2] + m[0][3] * m[1][2] * m[2][1] * m[3][0]
+ + -m[0][0] * m[1][1] * m[2][3] * m[3][2] + -m[0][0] * m[1][2] * m[2][1] * m[3][3]
+ + -m[0][0] * m[1][3] * m[2][2] * m[3][1] + -m[0][1] * m[1][0] * m[2][2] * m[3][3]
+ + -m[0][1] * m[1][2] * m[2][3] * m[3][0] + -m[0][1] * m[1][3] * m[2][0] * m[3][2]
+ + -m[0][2] * m[1][0] * m[2][3] * m[3][1] + -m[0][2] * m[1][1] * m[2][0] * m[3][3]
+ + -m[0][2] * m[1][3] * m[2][1] * m[3][0] + -m[0][3] * m[1][0] * m[2][1] * m[3][2]
+ + -m[0][3] * m[1][1] * m[2][2] * m[3][0] + -m[0][3] * m[1][2] * m[2][0] * m[3][1];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] * m[3][3] + m[1][2] * m[2][3] * m[3][1]
+ + m[1][3] * m[2][1] * m[3][2] + -m[1][1] * m[2][3] * m[3][2]
+ + -m[1][2] * m[2][1] * m[3][3] + -m[1][3] * m[2][2] * m[3][1])
+ / d;
+
+ r[0][1] = (m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3]
+ + m[0][3] * m[2][2] * m[3][1] + -m[0][1] * m[2][2] * m[3][3]
+ + -m[0][2] * m[2][3] * m[3][1] + -m[0][3] * m[2][1] * m[3][2])
+ / d;
+
+ r[0][2] = (m[0][1] * m[1][2] * m[3][3] + m[0][2] * m[1][3] * m[3][1]
+ + m[0][3] * m[1][1] * m[3][2] + -m[0][1] * m[1][3] * m[3][2]
+ + -m[0][2] * m[1][1] * m[3][3] + -m[0][3] * m[1][2] * m[3][1])
+ / d;
+
+ r[0][3] = (m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3]
+ + m[0][3] * m[1][2] * m[2][1] + -m[0][1] * m[1][2] * m[2][3]
+ + -m[0][2] * m[1][3] * m[2][1] + -m[0][3] * m[1][1] * m[2][2])
+ / d;
+
+ r[1][0] = (m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3]
+ + m[1][3] * m[2][2] * m[3][0] + -m[1][0] * m[2][2] * m[3][3]
+ + -m[1][2] * m[2][3] * m[3][0] + -m[1][3] * m[2][0] * m[3][2])
+ / d;
+
+ r[1][1] = (m[0][0] * m[2][2] * m[3][3] + m[0][2] * m[2][3] * m[3][0]
+ + m[0][3] * m[2][0] * m[3][2] + -m[0][0] * m[2][3] * m[3][2]
+ + -m[0][2] * m[2][0] * m[3][3] + -m[0][3] * m[2][2] * m[3][0])
+ / d;
+
+ r[1][2] = (m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3]
+ + m[0][3] * m[1][2] * m[3][0] + -m[0][0] * m[1][2] * m[3][3]
+ + -m[0][2] * m[1][3] * m[3][0] + -m[0][3] * m[1][0] * m[3][2])
+ / d;
+
+ r[1][3] = (m[0][0] * m[1][2] * m[2][3] + m[0][2] * m[1][3] * m[2][0]
+ + m[0][3] * m[1][0] * m[2][2] + -m[0][0] * m[1][3] * m[2][2]
+ + -m[0][2] * m[1][0] * m[2][3] + -m[0][3] * m[1][2] * m[2][0])
+ / d;
+
+ r[2][0] = (m[1][0] * m[2][1] * m[3][3] + m[1][1] * m[2][3] * m[3][0]
+ + m[1][3] * m[2][0] * m[3][1] + -m[1][0] * m[2][3] * m[3][1]
+ + -m[1][1] * m[2][0] * m[3][3] + -m[1][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][1] =
+ (-m[0][0] * m[2][1] * m[3][3] + -m[0][1] * m[2][3] * m[3][0] + -m[0][3] * m[2][0] * m[3][1]
+ + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] + m[0][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][2] = (m[0][0] * m[1][1] * m[3][3] + m[0][1] * m[1][3] * m[3][0]
+ + m[0][3] * m[1][0] * m[3][1] + -m[0][0] * m[1][3] * m[3][1]
+ + -m[0][1] * m[1][0] * m[3][3] + -m[0][3] * m[1][1] * m[3][0])
+ / d;
+
+ r[2][3] = (m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3]
+ + m[0][3] * m[1][1] * m[2][0] + -m[0][1] * m[1][3] * m[2][0]
+ + -m[0][3] * m[1][0] * m[2][1] + -m[0][0] * m[1][1] * m[2][3])
+ / d;
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = (m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1]
+ + -m[0][1] * m[1][0] * m[2][2] + -m[0][2] * m[1][1] * m[2][0])
+ / d;
+}
+
+void NvInvMatf(GLfloat result[4][4], const GLfloat m[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((m[0][3] == 0.0f) && (m[1][3] == 0.0f) && (m[2][3] == 0.0f) && (m[2][3] == 1.0f)) {
+ if ((m[3][0] == 0.0f) && (m[3][1] == 0.0f) && (m[3][2] == 0.0f)) {
+ NvInvMat3x3f(r, m);
+ } else {
+ NvInvMat4x3f(r, m);
+ }
+ } else {
+ NvInvMat4x4f(r, m);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildIdentityMatf(GLfloat r[4][4])
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = x;
+ r[3][1] = y;
+ r[3][2] = z;
+ r[3][3] = 1.0f;
+}
+
+void NvMultTranslateMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y,
+ GLfloat z)
+{
+ GLfloat r[4][4]; /*temporary storage for result */
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[0][0] * x + m[1][0] * y + m[2][0] * z + m[3][0];
+ r[3][1] = m[0][1] * x + m[1][1] * y + m[2][1] * z + m[3][1];
+ r[3][2] = m[0][2] * x + m[1][2] * y + m[2][2] * z + m[3][2];
+ r[3][3] = m[0][3] * x + m[1][3] * y + m[2][3] * z + m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = x;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = y;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = z;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultScaleMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * x;
+ r[0][1] = m[0][1] * x;
+ r[0][2] = m[0][2] * x;
+ r[0][3] = m[0][3] * x;
+
+ r[1][0] = m[1][0] * y;
+ r[1][1] = m[1][1] * y;
+ r[1][2] = m[1][2] * y;
+ r[1][3] = m[1][3] * y;
+
+ r[2][0] = m[2][0] * z;
+ r[2][1] = m[2][1] * z;
+ r[2][2] = m[2][2] * z;
+ r[2][3] = m[2][3] * z;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = c;
+ r[1][2] = s;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = -s;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = 0.0f;
+ r[0][2] = -s;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = s;
+ r[2][1] = 0.0f;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = s;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = -s;
+ r[1][1] = c;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultRotXRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0] * c + m[2][0] * s;
+ r[1][1] = m[1][1] * c + m[2][1] * s;
+ r[1][2] = m[1][2] * c + m[2][2] * s;
+ r[1][3] = m[1][3] * c + m[2][3] * s;
+
+ r[2][0] = m[1][0] * -s + m[2][0] * c;
+ r[2][1] = m[1][1] * -s + m[2][1] * c;
+ r[2][2] = m[1][2] * -s + m[2][2] * c;
+ r[2][3] = m[1][3] * -s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotYRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[2][0] * -s;
+ r[0][1] = m[0][1] * c + m[2][1] * -s;
+ r[0][2] = m[0][2] * c + m[2][2] * -s;
+ r[0][3] = m[0][3] * c + m[2][3] * -s;
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[0][0] * s + m[2][0] * c;
+ r[2][1] = m[0][1] * s + m[2][1] * c;
+ r[2][2] = m[0][2] * s + m[2][2] * c;
+ r[2][3] = m[0][3] * s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotZRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[1][0] * s;
+ r[0][1] = m[0][1] * c + m[1][1] * s;
+ r[0][2] = m[0][2] * c + m[1][2] * s;
+ r[0][3] = m[0][3] * c + m[1][3] * s;
+
+ r[1][0] = m[0][0] * -s + m[1][0] * c;
+ r[1][1] = m[0][1] * -s + m[1][1] * c;
+ r[1][2] = m[0][2] * -s + m[1][2] * c;
+ r[1][3] = m[0][3] * -s + m[1][3] * c;
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotRadMatf(GLfloat result[4][4], const GLfloat axis[3], GLfloat radians)
+{
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ /* build a matrix from the quat */
+
+ result[0][0] = 1.0f - 2.0f * (j * j + k * k);
+ result[0][1] = 2.0f * (i * j + r * k);
+ result[0][2] = 2.0f * (i * k - r * j);
+ result[0][3] = 0.0f;
+
+ result[1][0] = 2.0f * (i * j - r * k);
+ result[1][1] = 1.0f - 2.0f * (i * i + k * k);
+ result[1][2] = 2.0f * (j * k + r * i);
+ result[1][3] = 0.0f;
+
+ result[2][0] = 2.0f * (i * k + r * j);
+ result[2][1] = 2.0f * (j * k - r * i);
+ result[2][2] = 1.0f - 2.0f * (i * i + j * j);
+ result[2][3] = 0.0f;
+
+ result[3][0] = 0.0f;
+ result[3][1] = 0.0f;
+ result[3][2] = 0.0f;
+ result[3][3] = 1.0f;
+}
+
+void NvMultRotRadMatf(GLfloat result[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians)
+{
+ GLfloat r[4][4];
+
+ {
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat const dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ {
+ /* build a matrix from the quat */
+
+ GLfloat const a00 = 1.0f - 2.0f * (j * j + k * k);
+ GLfloat const a01 = 2.0f * (i * j + r * k);
+ GLfloat const a02 = 2.0f * (i * k - r * j);
+
+ GLfloat const a10 = 2.0f * (i * j - r * k);
+ GLfloat const a11 = 1.0f - 2.0f * (i * i + k * k);
+ GLfloat const a12 = 2.0f * (j * k + r * i);
+
+ GLfloat const a20 = 2.0f * (i * k + r * j);
+ GLfloat const a21 = 2.0f * (j * k - r * i);
+ GLfloat const a22 = 1.0f - 2.0f * (i * i + j * j);
+
+ result[0][0] = m[0][0] * a00 + m[1][0] * a01 + m[2][0] * a02;
+ result[0][1] = m[0][1] * a00 + m[1][1] * a01 + m[2][1] * a02;
+ result[0][2] = m[0][2] * a00 + m[1][2] * a01 + m[2][2] * a02;
+ result[0][3] = m[0][3] * a00 + m[1][3] * a01 + m[2][3] * a02;
+
+ result[1][0] = m[0][0] * a10 + m[1][0] * a11 + m[2][0] * a12;
+ result[1][1] = m[0][1] * a10 + m[1][1] * a11 + m[2][1] * a12;
+ result[1][2] = m[0][2] * a10 + m[1][2] * a11 + m[2][2] * a12;
+ result[1][3] = m[0][3] * a10 + m[1][3] * a11 + m[2][3] * a12;
+
+ result[2][0] = m[0][0] * a20 + m[1][0] * a21 + m[2][0] * a22;
+ result[2][1] = m[0][1] * a20 + m[1][1] * a21 + m[2][1] * a22;
+ result[2][2] = m[0][2] * a20 + m[1][2] * a21 + m[2][2] * a22;
+ result[2][3] = m[0][3] * a20 + m[1][3] * a21 + m[2][3] * a22;
+
+ result[3][0] = m[3][0];
+ result[3][1] = m[3][1];
+ result[3][2] = m[3][2];
+ result[3][3] = m[3][3];
+ }
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotXRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotYRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotZRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotXRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotYRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotZRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees)
+{
+ NvBuildRotRadMatf(r, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees)
+{
+ NvMultRotRadMatf(r, m, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3])
+{
+ GLfloat ev[3];
+ GLfloat z[3];
+ GLfloat x_tmp[3];
+ GLfloat x[3];
+ GLfloat y[3];
+
+ NvSubVecf(ev, eye, obj);
+
+ NvNormalizeVecf(z, ev);
+
+ NvCrossProductf(x_tmp, up, z);
+
+ NvNormalizeVecf(x, x_tmp);
+
+ NvCrossProductf(y, z, x);
+
+ r[0][0] = x[0];
+ r[0][1] = y[0];
+ r[0][2] = z[0];
+ r[0][3] = 0.0f;
+
+ r[1][0] = x[1];
+ r[1][1] = y[1];
+ r[1][2] = z[1];
+ r[1][3] = 0.0f;
+
+ r[2][0] = x[2];
+ r[2][1] = y[2];
+ r[2][2] = z[2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = -x[0] * eye[0] + -x[1] * eye[1] + -x[2] * eye[2];
+ r[3][1] = -y[0] * eye[0] + -y[1] * eye[1] + -y[2] * eye[2];
+ r[3][2] = -z[0] * eye[0] + -z[1] * eye[1] + -z[2] * eye[2];
+ r[3][3] = 1.0f;
+}
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const m00 = znear * 2.0f / (right - left);
+ GLfloat const m11 = znear * 2.0f / (top - bottom);
+ GLfloat const m22 = -(zfar + znear) / (zfar - znear);
+
+ GLfloat const m20 = (right + left) / (right - left);
+ GLfloat const m21 = (top + bottom) / (top - bottom);
+
+ GLfloat const m32 = -(2.0f * zfar * znear) / (zfar - znear);
+ GLfloat const m23 = -1.0f;
+
+ r[0][0] = m00;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = m11;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = m20;
+ r[2][1] = m21;
+ r[2][2] = m22;
+ r[2][3] = m23;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = m32;
+ r[3][3] = 0.0f;
+}
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+ GLfloat const sz = -2.0f / (zfar - znear);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+ GLfloat const tz = -(zfar + znear) / (zfar - znear);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = sz;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = tz;
+ r[3][3] = 1.0f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.h
new file mode 100644
index 00000000..5f567f06
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_matrix.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MATRIX_H
+#define INCLUDED_MATRIX_H
+
+#include <QtGui/qopengl.h>
+
+#include <math.h>
+#include <assert.h>
+
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4]);
+
+/* vector utilities */
+
+GLfloat NvVecLengthf(const GLfloat v[3]);
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3]);
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4]);
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+
+/* matrix utilities */
+
+void NvMultMatf(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4]);
+
+void NvInvMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+
+/* matrix building utilities */
+
+void NvBuildIdentityMatf(GLfloat r[4][4]);
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees);
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees);
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians);
+
+void NvBuildRotRadMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat radians);
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3]);
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top);
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+/* matrix concatenation utilities */
+
+void NvMultTranslateMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+void NvMultScaleMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees);
+
+void NvMultRotXRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotYRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotZRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+
+void NvMultRotRadMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.cpp b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.cpp
new file mode 100644
index 00000000..e66420c6
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_quat.h"
+#include <stdlib.h>
+#ifdef _INTEGRITYPLATFORM
+#include <string.h>
+#else
+#include <memory.h>
+#endif
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4])
+{
+ memcpy(r, q, 4 * sizeof(GLfloat));
+}
+
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4])
+{
+ // Assumes that the quaternion is normalized!
+ GLfloat x2 = q[0] * 2.0f;
+ GLfloat y2 = q[1] * 2.0f;
+ GLfloat z2 = q[2] * 2.0f;
+ GLfloat xSq2 = x2 * q[0];
+ GLfloat ySq2 = y2 * q[1];
+ GLfloat zSq2 = z2 * q[2];
+ GLfloat xy2 = x2 * q[1];
+ GLfloat xz2 = x2 * q[2];
+ GLfloat xw2 = x2 * q[3];
+ GLfloat yz2 = y2 * q[2];
+ GLfloat yw2 = y2 * q[3];
+ GLfloat zw2 = z2 * q[3];
+
+ /* Matrix is
+ * | 1 - 2y^2 - 2z^2 2xy - 2zw 2xz + 2yw |
+ * | 2xy + 2zw 1 - 2x^2 - 2z^2 2yz - 2xw |
+ * | 2xz - 2yw 2yz + 2xw 1 - 2x^2 - 2y^2 |
+ */
+ r[0][0] = 1.0f - ySq2 - zSq2;
+ r[0][1] = xy2 - zw2;
+ r[0][2] = xz2 + yw2;
+
+ r[1][0] = xy2 + zw2;
+ r[1][1] = 1.0f - xSq2 - zSq2;
+ r[1][2] = yz2 - xw2;
+
+ r[2][0] = xz2 - yw2;
+ r[2][1] = yz2 + xw2;
+ r[2][2] = 1.0f - xSq2 - ySq2;
+}
+
+void NvQuatIdentity(GLfloat r[4])
+{
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = 1.0f;
+}
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3])
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = axis[0] * sina;
+ r[1] = axis[1] * sina;
+ r[2] = axis[2] * sina;
+ r[3] = cosa;
+}
+
+void NvQuatX(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = sina;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatY(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = sina;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatZ(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = sina;
+ r[3] = cosa;
+}
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatY(h, heading);
+ NvQuatX(p, pitch);
+ NvQuatZ(ro, roll);
+
+ NvQuatMult(r, h, p);
+ NvQuatMult(r, ro, r);
+}
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatZ(ro, roll);
+ NvQuatX(p, pitch);
+ NvQuatY(h, heading);
+
+ NvQuatMult(r, p, h);
+ NvQuatMult(r, r, ro);
+}
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4])
+{
+ return q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3];
+}
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4])
+{
+ const GLfloat q1x = q1[0];
+ const GLfloat q1y = q1[1];
+ const GLfloat q1z = q1[2];
+ const GLfloat q1w = q1[3];
+ const GLfloat q2x = q2[0];
+ const GLfloat q2y = q2[1];
+ const GLfloat q2z = q2[2];
+ const GLfloat q2w = q2[3];
+
+ r[0] = q1y * q2z - q2y * q1z + q1w * q2x + q2w * q1x;
+ r[1] = q1z * q2x - q2z * q1x + q1w * q2y + q2w * q1y;
+ r[2] = q1x * q2y - q2x * q1y + q1w * q2z + q2w * q1z;
+ r[3] = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
+}
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t)
+{
+ GLfloat omt = 1.0f - t;
+
+ if (NvQuatDot(q1, q2) < 0.0f) {
+ r[0] = -q1[0] * omt + q2[0] * t;
+ r[1] = -q1[1] * omt + q2[1] * t;
+ r[2] = -q1[2] * omt + q2[2] * t;
+ r[3] = -q1[3] * omt + q2[3] * t;
+ } else {
+ r[0] = q1[0] * omt + q2[0] * t;
+ r[1] = q1[1] * omt + q2[1] * t;
+ r[2] = q1[2] * omt + q2[2] * t;
+ r[3] = q1[3] * omt + q2[3] * t;
+ }
+
+ NvQuatNormalize(r, r);
+}
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4])
+{
+ GLfloat invLength = 1.0f / sqrtf(NvQuatDot(q, q));
+
+ r[0] = invLength * q[0];
+ r[1] = invLength * q[1];
+ r[2] = invLength * q[2];
+ r[3] = invLength * q[3];
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.h
new file mode 100644
index 00000000..2e97c717
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_math/nv_quat.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QUAT_H
+#define INCLUDED_QUAT_H
+
+#include <QtGui/qopengl.h>
+
+#include <math.h>
+#include <assert.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4]);
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4]);
+
+void NvQuatIdentity(GLfloat r[4]);
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3]);
+
+void NvQuatX(GLfloat r[4], GLfloat radians);
+
+void NvQuatY(GLfloat r[4], GLfloat radians);
+
+void NvQuatZ(GLfloat r[4], GLfloat radians);
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t);
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4]);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_types.h b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_types.h
new file mode 100644
index 00000000..1d1b0300
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/Qt3DSLibs/nv_types.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_TYPES_H
+#define __INCLUDED_QT3DS_TYPES_H
+
+typedef unsigned char NvU8; // 0 to 255
+typedef unsigned short NvU16; // 0 to 65535
+typedef unsigned int NvU32; // 0 to 4294967295
+typedef unsigned long long NvU64; // 0 to 18446744073709551615
+typedef signed char NvS8; // -128 to 127
+typedef signed short NvS16; // -32768 to 32767
+typedef signed int NvS32; // -2147483648 to 2147483647
+typedef signed long long NvS64; // 2^-63 to 2^63-1
+
+// Explicitly sized floats
+typedef float NvF32; // IEEE Single Precision (S1E8M23)
+typedef double NvF64; // IEEE Double Precision (S1E11M52)
+
+// Boolean type
+#define QT3DS_FALSE 0
+#define QT3DS_TRUE 1
+typedef NvU8 NvBool;
+
+// Result of sizeof operator
+typedef unsigned long NvSize;
+
+// Type large enough to hold a relative file offset
+typedef long NvOffset;
+
+// Base NULL type.
+#define QT3DS_NULL 0
+
+// Error related
+typedef enum {
+ NvError_Success = 0,
+ NvError_NotSupported,
+ NvError_NotInitialized,
+ NvError_BadParameter,
+ NvError_InsufficientMemory,
+ NvError_NoEntries,
+ NvError_UnknownError,
+} NvError;
+
+#if 1 // defined(_DEBUG) // !!!!TBD TODO
+#define NvAssert(c)
+#else
+#define NvAssert(c) ((void)((c) ? 0 : (NvHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+// Other standardized typedefs
+typedef NvU64 NvUST; // U64 unadjusted system time value
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.abc b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.abc
new file mode 100644
index 00000000..f7e3c2f6
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.abc
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.dds b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.dds
new file mode 100644
index 00000000..5bde760b
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_256.dds
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.abc b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.abc
new file mode 100644
index 00000000..2ff78757
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.abc
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.dds b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.dds
new file mode 100644
index 00000000..f9e76d94
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/assets/courier+lucida_512.dds
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/assets/font.frag b/src/Runtime/Source/PlatformSpecific/Linux/assets/font.frag
new file mode 100644
index 00000000..e4673cf8
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/assets/font.frag
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+uniform sampler2D fontTex;
+
+varying lowp vec4 col_var;
+varying lowp vec2 tex_var;
+
+void main()
+{
+ gl_FragColor = texture2D(fontTex, tex_var).a * col_var;
+}
+
diff --git a/src/Runtime/Source/PlatformSpecific/Linux/assets/font.vert b/src/Runtime/Source/PlatformSpecific/Linux/assets/font.vert
new file mode 100644
index 00000000..9f307a2f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Linux/assets/font.vert
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// this is set from higher level. think of it as the upper model matrix
+uniform mat4 pixelToClipMat;
+
+uniform vec4 col_uni;
+
+attribute vec2 pos_attr;
+attribute vec2 tex_attr;
+attribute vec4 col_attr;
+
+varying vec4 col_var;
+varying vec2 tex_var;
+
+void main()
+{
+ // account for translation and rotation of the primitive into [-1,1] spatial default.
+ gl_Position = pixelToClipMat * vec4(pos_attr.x, pos_attr.y, 0, 1);
+
+ col_var = col_attr * col_uni;
+ tex_var = tex_attr;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_color.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_color.h
new file mode 100644
index 00000000..b9347529
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_color.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_COLOR_H
+#define _QT3DS_COLOR_H
+
+/** @file nv_color.h
+ Simple abstraction for RGBA colors as parameters to various libraries/functions.
+*/
+
+/** Base type for a single color channel (8-bit unsigned). */
+typedef unsigned char NvPCColor8;
+
+//#define NV_COLOR_BREAKOLD
+#ifdef NV_COLOR_BREAKOLD // uses a struct to break backwards-compat and accidental uses
+
+typedef struct
+{
+ NvPCColor8 r;
+ NvPCColor8 g;
+ NvPCColor8 b;
+ NvPCColor8 a;
+} NvPackedColor;
+
+static const NvPackedColor gnvpcwhite = { 255, 255, 255, 255 };
+static const NvPackedColor gnvpcblack = { 0, 0, 0, 255 };
+
+#define NV_PACKED_COLOR(r, g, b, a) \
+ { \
+ (NvPCColor8)(r), (NvPCColor8)(g), (NvPCColor8)(b), (NvPCColor8)(a) \
+ }
+
+#define NV_PC_PREDEF_WHITE gnvpcwhite
+#define NV_PC_PREDEF_BLACK gnvpcblack
+
+#define NV_PC_RED(c) (c.r)
+#define NV_PC_GREEN(c) (c.g)
+#define NV_PC_BLUE(c) (c.b)
+#define NV_PC_ALPHA(c) (c.a)
+
+#define NV_PC_PACK_UINT(c) (*(unsigned int *)(&(c)))
+
+#define NV_PC_EQUAL(x, y) ((x).r == (y).r && (x).g == (y).g && (x).b == (y).b && (x).a == (y).a)
+
+#else /* code that doesn't break old pass-as-uint stuff */
+
+/** Main type declaration for a packed 4-color construct. */
+typedef unsigned int NvPackedColor;
+
+/** A macro to build a packed color, passing in RGBA as four 8-bit integer values. */
+#define NV_PACKED_COLOR(r, g, b, a) \
+ ((NvPackedColor)(((((int)(a)) & 0xFF) << 24) | ((((int)(b)) & 0xFF) << 16) \
+ | ((((int)(g)) & 0xFF) << 8) | ((((int)(r)) & 0xFF))))
+
+/** A predefined constant for WHITE. */
+#define NV_PC_PREDEF_WHITE NV_PACKED_COLOR(0xFF, 0xFF, 0xFF, 0xFF)
+/** A predefined constant for BLACK. */
+#define NV_PC_PREDEF_BLACK NV_PACKED_COLOR(0x00, 0x00, 0x00, 0xFF)
+
+/** A macro for 'extracting' the red value from an NvPackedColor. */
+#define NV_PC_RED(c) ((c >> 0) & 0xff)
+/** A macro for 'extracting' the green value from an NvPackedColor. */
+#define NV_PC_GREEN(c) ((c >> 8) & 0xff)
+/** A macro for 'extracting' the blue value from an NvPackedColor. */
+#define NV_PC_BLUE(c) ((c >> 16) & 0xff)
+/** A macro for 'extracting' the alpha value from an NvPackedColor. */
+#define NV_PC_ALPHA(c) ((c >> 24) & 0xff)
+
+/** A macro requesting the packed color repacked into a 32-bit unsigned int.
+ This is a no-op for the color-as-uint approach.
+*/
+#define NV_PC_PACK_UINT(c) (c)
+/** A macro for testing the equality of two NvPackedColors. */
+#define NV_PC_EQUAL(x, y) (x == y)
+#endif
+
+/** A macro for mapping a single packed color channel into its floating point [0,1] rep. */
+#define NV_PC_TO_FLOAT(c) (c / 255.0f)
+
+#endif /*_QT3DS_COLOR_H*/
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_debug.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_debug.h
new file mode 100644
index 00000000..2559dd6f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_debug.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_DEBUG_H
+#define __INCLUDED_QT3DS_DEBUG_H
+
+#define CT_ASSERT(tag, cond) enum { COMPILE_TIME_ASSERT__##tag = 1 / (cond) }
+
+#define dimof(x) (sizeof(x) / sizeof(x[0]))
+#include <android/log.h>
+
+#define DBG_DETAILED 0
+
+#if 0
+
+ // the detailed prefix can be customised by setting DBG_DETAILED_PREFIX. See
+ // below as a reference.
+ // NOTE: fmt is the desired format string and must be in the prefix.
+ //#ifndef DBG_DETAILED_PREFIX
+ // #define DBG_DETAILED_PREFIX "%s, %s, line %d: " fmt, __FILE__, __FUNCTION__, __LINE__,
+ //#endif
+ //#define DEBUG_D_(fmt, args...)
+ //#define DEBUG_D(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, (DBG_DETAILED_PREFIX) ## args)
+
+#else
+
+#ifdef STRINGIFY
+#pragma push_macro("STRINGIFY")
+#undef STRINGIFY
+#define STRINGIFYPUSHED_____
+#endif
+#define STRINGIFY(x) #x
+
+// debug macro, includes file name function name and line number
+#define TO(x) typeof(x)
+#define DEBUG_D_(file, line, fmt, args...) \
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, file ", %s, line(" STRINGIFY(line) "): " fmt, \
+ __FUNCTION__, ##args)
+#define DEBUG_D(fmt, args...) DEBUG_D_(__FILE__, __LINE__, fmt, ##args)
+
+#ifdef STRINGIFYPUSHED_____
+#undef STRINGIFYPUSHED_____
+#pragma pop_macro("STRINGIFY")
+#endif
+
+#endif
+
+// basic debug macro
+#define DEBUG_(fmt, args...) (__android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args))
+
+// Debug macro that can be switched to spew a file name,
+// function and line number using DEBUG_DETAILED
+#if DBG_DETAILED == 1
+#define DEBUG(fmt, args...) DEBUG_D(fmt, ##args)
+#else
+#define DEBUG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args)
+#endif
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_global.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_global.h
new file mode 100644
index 00000000..9d23d45f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_global.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_GLOBAL_H
+#define __INCLUDED_QT3DS_GLOBAL_H
+
+#include "nv_types.h"
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/NvVec.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/NvVec.h
new file mode 100644
index 00000000..4e5b09ce
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/NvVec.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_VEC_H
+#define INCLUDED_QT3DS_MATH_CPP_VEC_H
+
+#include "misc.h"
+
+struct _NvVec3
+{
+ union {
+ struct
+ {
+ float x, y, z;
+ };
+ float v[3];
+ };
+};
+
+struct NvVec3 : public _NvVec3
+{
+ NvVec3() { zero(); }
+
+ NvVec3(float x, float y, float z)
+ {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ }
+
+ NvVec3(NvVec3 const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ v[2] = that.v[2];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ v[2] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec3 &operator+=(NvVec3 const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ v[2] += that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator-=(NvVec3 const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ v[2] -= that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ v[2] *= s;
+ return *this;
+ }
+
+ NvVec3 &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ v[2] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec3 const &a, NvVec3 const &b)
+{
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+inline NvVec3 operator+(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a)
+{
+
+ return NvVec3(-a.v[0], -a.v[1], -a.v[2]);
+}
+
+inline NvVec3 operator*(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] * s, a.v[1] * s, a.v[2] * s);
+}
+
+inline NvVec3 operator*(float s, NvVec3 const &a)
+{
+
+ return NvVec3(s * a.v[0], s * a.v[1], s * a.v[2]);
+}
+
+inline NvVec3 operator/(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] / s, a.v[1] / s, a.v[2] / s);
+}
+
+inline float magnitude(NvVec3 const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec3 normalize(NvVec3 const &v)
+{
+ float l = magnitude(v);
+ return NvVec3(v[0] / l, v[1] / l, v[2] / l);
+}
+
+inline NvVec3 cross(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[1] * b.v[2] - a.v[2] * b.v[1], a.v[2] * b.v[0] - a.v[0] * b.v[2],
+ a.v[0] * b.v[1] - a.v[1] * b.v[0]);
+}
+
+inline bool operator==(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] == b.v[0] && a.v[1] == b.v[1] && a.v[2] == b.v[2]);
+}
+
+inline bool operator!=(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] != b.v[0] || a.v[1] != b.v[1] || a.v[2] != b.v[2]);
+}
+
+struct NvVec2f
+{
+ union {
+ struct
+ {
+ float x, y;
+ float v[2];
+ };
+ };
+
+ NvVec2f() { zero(); }
+
+ NvVec2f(float x, float y)
+ {
+ v[0] = x;
+ v[1] = y;
+ }
+
+ NvVec2f(NvVec2f const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec2f &operator+=(NvVec2f const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator-=(NvVec2f const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ return *this;
+ }
+
+ NvVec2f &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a[0] * b[0] + a[1] * b[1];
+}
+
+inline NvVec2f operator+(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] + b.v[0], a.v[1] + b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] - b.v[0], a.v[1] - b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a)
+{
+
+ return NvVec2f(-a.v[0], -a.v[1]);
+}
+
+inline NvVec2f operator*(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] * s, a.v[1] * s);
+}
+
+inline NvVec2f operator*(float s, NvVec2f const &a)
+{
+
+ return NvVec2f(s * a.v[0], s * a.v[1]);
+}
+
+inline NvVec2f operator/(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] / s, a.v[1] / s);
+}
+
+inline float magnitude(NvVec2f const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec2f normalize(NvVec2f const &v)
+{
+ float l = dot(v, v);
+ return NvVec2f(v[0] / l, v[1] / l);
+}
+
+inline float cross(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a.v[0] * b.v[1] - b.v[0] * a.v[1];
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/misc.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/misc.h
new file mode 100644
index 00000000..983410f3
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/misc.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_MISC_H
+#define INCLUDED_QT3DS_MATH_CPP_MISC_H
+
+inline bool nvIsPowerOfTwo(unsigned int i)
+{
+ return (i & (i - 1)) == 0;
+}
+
+inline float nvDegToRadf(float d)
+{
+ return d * 3.14159265358979323846f / 180.0f;
+}
+
+inline float nvRadToDegf(float r)
+{
+ return r * 180.0f / 3.14159265358979323846f;
+}
+
+/*
+ 'mod' differs from '%' in that it behaves correctly when either the
+ numerator or denominator is negative.
+*/
+
+inline int nvMod(int n, int d)
+{
+ int m = n % d;
+ return (((m < 0) && (d > 0)) || ((m > 0) && (d < 0))) ? (m + d) : m;
+}
+
+inline int nvAbs(int n)
+{
+ if (n < 0)
+ return -n;
+ return n;
+}
+
+inline int nvSign(int n)
+{
+ if (n > 0)
+ return 1;
+ if (n < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ This returns the smallest amplitude value x such that
+ nvMod(b + x, m) == a
+*/
+
+inline int nvDifMod(int a, int b, int m)
+{
+
+ int x1 = a - b;
+ int x2 = (x1 > 0) ? x1 - m : x1 + m;
+ return (nvAbs(x1) < nvAbs(x2)) ? x1 : x2;
+}
+
+inline float nvWrapf(float a, float min, float max)
+{
+
+ assert(max > min);
+
+ float d = max - min;
+ float s = a - min;
+ float q = s / d;
+ float m = q - floorf(q);
+ return m * d + min;
+}
+
+inline float nvClampf(float a, float min, float max)
+{
+ return (a < min) ? min : ((a > max) ? max : a);
+}
+
+inline int nvClampi(int i, int min, int max)
+{
+ return (i < min) ? min : ((i > max) ? max : i);
+}
+
+inline float nvGaussian(float x, float s)
+{
+ float c = s * sqrtf(2.0f * 3.14159265358979323846f);
+ return expf(-(x * x) / (2.0f * s * s)) / c;
+}
+
+inline float nvLerpf(float a, float b, float t)
+{
+ return a * (1.0f - t) + b * t;
+}
+
+inline float nvEasef(float t)
+{
+
+ float t_2 = t * t;
+ float t_3 = t_2 * t;
+ return 3.0f * t_2 - 2.0f * t_3;
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.cpp b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.cpp
new file mode 100644
index 00000000..b83cb39e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_math.h"
+
+static const double a = 16807.0;
+static const double m = 2147483647.0;
+
+static double nextSeed(double seed)
+{
+ double t = a * seed;
+ return t - m * (double)((int)(t / m));
+}
+
+GLfloat NvRandf()
+{
+ static double seed = 1.0;
+ seed = nextSeed(seed);
+ return (GLfloat)(seed * (1 / m));
+}
+
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime)
+{
+ // kdGetTimeUST is never supposed to decrease (i.e. that
+ // means it can't wrap, either. IIRC, it will wrap in
+ // 593 years). So we ignore that option...
+
+ // Used for frame-to-frame diffs, this will fit in 32b
+ // as long as the times are < ~4.3s apart
+ long long int diffTime = newTime - oldTime;
+
+ // Need to find a better way to do this.
+ // However, I believe we will be uSec precise (not run
+ // out of mantissa bits for uSecs) as long as the diff
+ // is < ~16s (1e-6 * (2^24))
+ return ((GLfloat)diffTime) / 1.0e9f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.h
new file mode 100644
index 00000000..e777e409
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_math.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_MATH_H
+#define _QT3DS_MATH_H
+
+#include <OpenGL/gl.h>
+
+GLfloat NvRandf();
+
+/* These are the recommended "safer" ways to use GLfloat for time */
+
+/* Returns the seconds between the two given times */
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime);
+
+#define QT3DS_MILISECS_TO_UST(ms) ((long long int)(ms)*1000000)
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.cpp b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.cpp
new file mode 100644
index 00000000..e208ac31
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.cpp
@@ -0,0 +1,1030 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_matrix.h"
+
+int NvDifferentMatsf(GLfloat a[4][4], const GLfloat b[4][4])
+{
+ return ((&a[3][3] < &b[0][0]) || (&b[3][3] < &a[0][0]));
+}
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+}
+
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+}
+
+GLfloat NvVecLengthf(const GLfloat v[3])
+{
+ return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+}
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3])
+{
+ GLfloat const l = NvVecLengthf(v);
+ r[0] = v[0] / l;
+ r[1] = v[1] / l;
+ r[2] = v[2] / l;
+}
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] + b[0];
+ r[1] = a[1] + b[1];
+ r[2] = a[2] + b[2];
+}
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+ r[2] = a[2] - b[2];
+}
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ GLfloat t[3];
+
+ t[0] = a[1] * b[2] - a[2] * b[1];
+ t[1] = a[2] * b[0] - a[0] * b[2];
+ t[2] = a[0] * b[1] - a[1] * b[0];
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+}
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ GLfloat inv_w = 1.0f / (m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3]);
+
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * inv_w;
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * inv_w;
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * inv_w;
+}
+
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * a[3];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * a[3];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * a[3];
+ r[3] = m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3] * a[3];
+}
+
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2];
+}
+
+static void NvMultMat3x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2];
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x4f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2] + a[3][0] * b[0][3];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2] + a[3][1] * b[0][3];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2] + a[3][2] * b[0][3];
+ r[0][3] = a[0][3] * b[0][0] + a[1][3] * b[0][1] + a[2][3] * b[0][2] + a[3][3] * b[0][3];
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2] + a[3][0] * b[1][3];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2] + a[3][1] * b[1][3];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2] + a[3][2] * b[1][3];
+ r[1][3] = a[0][3] * b[1][0] + a[1][3] * b[1][1] + a[2][3] * b[1][2] + a[3][3] * b[1][3];
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2] + a[3][0] * b[2][3];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2] + a[3][1] * b[2][3];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2] + a[3][2] * b[2][3];
+ r[2][3] = a[0][3] * b[2][0] + a[1][3] * b[2][1] + a[2][3] * b[2][2] + a[3][3] * b[2][3];
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0] * b[3][3];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1] * b[3][3];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2] * b[3][3];
+ r[3][3] = a[0][3] * b[3][0] + a[1][3] * b[3][1] + a[2][3] * b[3][2] + a[3][3] * b[3][3];
+}
+
+void NvMultMatf(GLfloat result[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((a[0][3] == 0.0f) && (a[1][3] == 0.0f) && (a[2][3] == 0.0f) && (a[2][3] == 1.0f)
+ && (b[0][3] == 0.0f) && (b[1][3] == 0.0f) && (b[2][3] == 0.0f) && (b[2][3] == 1.0f)) {
+ if ((a[3][0] == 0.0f) && (a[3][1] == 0.0f) && (a[3][2] == 0.0f) && (b[3][0] == 0.0f)
+ && (b[3][1] == 0.0f) && (b[3][2] == 0.0f)) {
+ NvMultMat3x3f(r, a, b);
+ } else {
+ NvMultMat4x3f(r, a, b);
+ }
+ } else {
+ NvMultMat4x4f(r, a, b);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+static void NvInvMat3x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ /* x */
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ /* y */
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ /* z */
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x4f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] * m[3][3] + m[0][0] * m[1][2] * m[2][3] * m[3][1]
+ + m[0][0] * m[1][3] * m[2][1] * m[3][2] + m[0][1] * m[1][0] * m[2][3] * m[3][2]
+ + m[0][1] * m[1][2] * m[2][0] * m[3][3] + m[0][1] * m[1][3] * m[2][2] * m[3][0]
+ + m[0][2] * m[1][0] * m[2][1] * m[3][3] + m[0][2] * m[1][1] * m[2][3] * m[3][0]
+ + m[0][2] * m[1][3] * m[2][0] * m[3][1] + m[0][3] * m[1][0] * m[2][2] * m[3][1]
+ + m[0][3] * m[1][1] * m[2][0] * m[3][2] + m[0][3] * m[1][2] * m[2][1] * m[3][0]
+ + -m[0][0] * m[1][1] * m[2][3] * m[3][2] + -m[0][0] * m[1][2] * m[2][1] * m[3][3]
+ + -m[0][0] * m[1][3] * m[2][2] * m[3][1] + -m[0][1] * m[1][0] * m[2][2] * m[3][3]
+ + -m[0][1] * m[1][2] * m[2][3] * m[3][0] + -m[0][1] * m[1][3] * m[2][0] * m[3][2]
+ + -m[0][2] * m[1][0] * m[2][3] * m[3][1] + -m[0][2] * m[1][1] * m[2][0] * m[3][3]
+ + -m[0][2] * m[1][3] * m[2][1] * m[3][0] + -m[0][3] * m[1][0] * m[2][1] * m[3][2]
+ + -m[0][3] * m[1][1] * m[2][2] * m[3][0] + -m[0][3] * m[1][2] * m[2][0] * m[3][1];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] * m[3][3] + m[1][2] * m[2][3] * m[3][1]
+ + m[1][3] * m[2][1] * m[3][2] + -m[1][1] * m[2][3] * m[3][2]
+ + -m[1][2] * m[2][1] * m[3][3] + -m[1][3] * m[2][2] * m[3][1])
+ / d;
+
+ r[0][1] = (m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3]
+ + m[0][3] * m[2][2] * m[3][1] + -m[0][1] * m[2][2] * m[3][3]
+ + -m[0][2] * m[2][3] * m[3][1] + -m[0][3] * m[2][1] * m[3][2])
+ / d;
+
+ r[0][2] = (m[0][1] * m[1][2] * m[3][3] + m[0][2] * m[1][3] * m[3][1]
+ + m[0][3] * m[1][1] * m[3][2] + -m[0][1] * m[1][3] * m[3][2]
+ + -m[0][2] * m[1][1] * m[3][3] + -m[0][3] * m[1][2] * m[3][1])
+ / d;
+
+ r[0][3] = (m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3]
+ + m[0][3] * m[1][2] * m[2][1] + -m[0][1] * m[1][2] * m[2][3]
+ + -m[0][2] * m[1][3] * m[2][1] + -m[0][3] * m[1][1] * m[2][2])
+ / d;
+
+ r[1][0] = (m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3]
+ + m[1][3] * m[2][2] * m[3][0] + -m[1][0] * m[2][2] * m[3][3]
+ + -m[1][2] * m[2][3] * m[3][0] + -m[1][3] * m[2][0] * m[3][2])
+ / d;
+
+ r[1][1] = (m[0][0] * m[2][2] * m[3][3] + m[0][2] * m[2][3] * m[3][0]
+ + m[0][3] * m[2][0] * m[3][2] + -m[0][0] * m[2][3] * m[3][2]
+ + -m[0][2] * m[2][0] * m[3][3] + -m[0][3] * m[2][2] * m[3][0])
+ / d;
+
+ r[1][2] = (m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3]
+ + m[0][3] * m[1][2] * m[3][0] + -m[0][0] * m[1][2] * m[3][3]
+ + -m[0][2] * m[1][3] * m[3][0] + -m[0][3] * m[1][0] * m[3][2])
+ / d;
+
+ r[1][3] = (m[0][0] * m[1][2] * m[2][3] + m[0][2] * m[1][3] * m[2][0]
+ + m[0][3] * m[1][0] * m[2][2] + -m[0][0] * m[1][3] * m[2][2]
+ + -m[0][2] * m[1][0] * m[2][3] + -m[0][3] * m[1][2] * m[2][0])
+ / d;
+
+ r[2][0] = (m[1][0] * m[2][1] * m[3][3] + m[1][1] * m[2][3] * m[3][0]
+ + m[1][3] * m[2][0] * m[3][1] + -m[1][0] * m[2][3] * m[3][1]
+ + -m[1][1] * m[2][0] * m[3][3] + -m[1][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][1] =
+ (-m[0][0] * m[2][1] * m[3][3] + -m[0][1] * m[2][3] * m[3][0] + -m[0][3] * m[2][0] * m[3][1]
+ + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] + m[0][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][2] = (m[0][0] * m[1][1] * m[3][3] + m[0][1] * m[1][3] * m[3][0]
+ + m[0][3] * m[1][0] * m[3][1] + -m[0][0] * m[1][3] * m[3][1]
+ + -m[0][1] * m[1][0] * m[3][3] + -m[0][3] * m[1][1] * m[3][0])
+ / d;
+
+ r[2][3] = (m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3]
+ + m[0][3] * m[1][1] * m[2][0] + -m[0][1] * m[1][3] * m[2][0]
+ + -m[0][3] * m[1][0] * m[2][1] + -m[0][0] * m[1][1] * m[2][3])
+ / d;
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = (m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1]
+ + -m[0][1] * m[1][0] * m[2][2] + -m[0][2] * m[1][1] * m[2][0])
+ / d;
+}
+
+void NvInvMatf(GLfloat result[4][4], const GLfloat m[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((m[0][3] == 0.0f) && (m[1][3] == 0.0f) && (m[2][3] == 0.0f) && (m[2][3] == 1.0f)) {
+ if ((m[3][0] == 0.0f) && (m[3][1] == 0.0f) && (m[3][2] == 0.0f)) {
+ NvInvMat3x3f(r, m);
+ } else {
+ NvInvMat4x3f(r, m);
+ }
+ } else {
+ NvInvMat4x4f(r, m);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildIdentityMatf(GLfloat r[4][4])
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = x;
+ r[3][1] = y;
+ r[3][2] = z;
+ r[3][3] = 1.0f;
+}
+
+void NvMultTranslateMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y,
+ GLfloat z)
+{
+ GLfloat r[4][4]; /*temporary storage for result */
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[0][0] * x + m[1][0] * y + m[2][0] * z + m[3][0];
+ r[3][1] = m[0][1] * x + m[1][1] * y + m[2][1] * z + m[3][1];
+ r[3][2] = m[0][2] * x + m[1][2] * y + m[2][2] * z + m[3][2];
+ r[3][3] = m[0][3] * x + m[1][3] * y + m[2][3] * z + m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = x;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = y;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = z;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultScaleMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * x;
+ r[0][1] = m[0][1] * x;
+ r[0][2] = m[0][2] * x;
+ r[0][3] = m[0][3] * x;
+
+ r[1][0] = m[1][0] * y;
+ r[1][1] = m[1][1] * y;
+ r[1][2] = m[1][2] * y;
+ r[1][3] = m[1][3] * y;
+
+ r[2][0] = m[2][0] * z;
+ r[2][1] = m[2][1] * z;
+ r[2][2] = m[2][2] * z;
+ r[2][3] = m[2][3] * z;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = c;
+ r[1][2] = s;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = -s;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = 0.0f;
+ r[0][2] = -s;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = s;
+ r[2][1] = 0.0f;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = s;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = -s;
+ r[1][1] = c;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultRotXRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0] * c + m[2][0] * s;
+ r[1][1] = m[1][1] * c + m[2][1] * s;
+ r[1][2] = m[1][2] * c + m[2][2] * s;
+ r[1][3] = m[1][3] * c + m[2][3] * s;
+
+ r[2][0] = m[1][0] * -s + m[2][0] * c;
+ r[2][1] = m[1][1] * -s + m[2][1] * c;
+ r[2][2] = m[1][2] * -s + m[2][2] * c;
+ r[2][3] = m[1][3] * -s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotYRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[2][0] * -s;
+ r[0][1] = m[0][1] * c + m[2][1] * -s;
+ r[0][2] = m[0][2] * c + m[2][2] * -s;
+ r[0][3] = m[0][3] * c + m[2][3] * -s;
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[0][0] * s + m[2][0] * c;
+ r[2][1] = m[0][1] * s + m[2][1] * c;
+ r[2][2] = m[0][2] * s + m[2][2] * c;
+ r[2][3] = m[0][3] * s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotZRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[1][0] * s;
+ r[0][1] = m[0][1] * c + m[1][1] * s;
+ r[0][2] = m[0][2] * c + m[1][2] * s;
+ r[0][3] = m[0][3] * c + m[1][3] * s;
+
+ r[1][0] = m[0][0] * -s + m[1][0] * c;
+ r[1][1] = m[0][1] * -s + m[1][1] * c;
+ r[1][2] = m[0][2] * -s + m[1][2] * c;
+ r[1][3] = m[0][3] * -s + m[1][3] * c;
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotRadMatf(GLfloat result[4][4], const GLfloat axis[3], GLfloat radians)
+{
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ /* build a matrix from the quat */
+
+ result[0][0] = 1.0f - 2.0f * (j * j + k * k);
+ result[0][1] = 2.0f * (i * j + r * k);
+ result[0][2] = 2.0f * (i * k - r * j);
+ result[0][3] = 0.0f;
+
+ result[1][0] = 2.0f * (i * j - r * k);
+ result[1][1] = 1.0f - 2.0f * (i * i + k * k);
+ result[1][2] = 2.0f * (j * k + r * i);
+ result[1][3] = 0.0f;
+
+ result[2][0] = 2.0f * (i * k + r * j);
+ result[2][1] = 2.0f * (j * k - r * i);
+ result[2][2] = 1.0f - 2.0f * (i * i + j * j);
+ result[2][3] = 0.0f;
+
+ result[3][0] = 0.0f;
+ result[3][1] = 0.0f;
+ result[3][2] = 0.0f;
+ result[3][3] = 1.0f;
+}
+
+void NvMultRotRadMatf(GLfloat result[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians)
+{
+ GLfloat r[4][4];
+
+ {
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat const dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ {
+ /* build a matrix from the quat */
+
+ GLfloat const a00 = 1.0f - 2.0f * (j * j + k * k);
+ GLfloat const a01 = 2.0f * (i * j + r * k);
+ GLfloat const a02 = 2.0f * (i * k - r * j);
+
+ GLfloat const a10 = 2.0f * (i * j - r * k);
+ GLfloat const a11 = 1.0f - 2.0f * (i * i + k * k);
+ GLfloat const a12 = 2.0f * (j * k + r * i);
+
+ GLfloat const a20 = 2.0f * (i * k + r * j);
+ GLfloat const a21 = 2.0f * (j * k - r * i);
+ GLfloat const a22 = 1.0f - 2.0f * (i * i + j * j);
+
+ result[0][0] = m[0][0] * a00 + m[1][0] * a01 + m[2][0] * a02;
+ result[0][1] = m[0][1] * a00 + m[1][1] * a01 + m[2][1] * a02;
+ result[0][2] = m[0][2] * a00 + m[1][2] * a01 + m[2][2] * a02;
+ result[0][3] = m[0][3] * a00 + m[1][3] * a01 + m[2][3] * a02;
+
+ result[1][0] = m[0][0] * a10 + m[1][0] * a11 + m[2][0] * a12;
+ result[1][1] = m[0][1] * a10 + m[1][1] * a11 + m[2][1] * a12;
+ result[1][2] = m[0][2] * a10 + m[1][2] * a11 + m[2][2] * a12;
+ result[1][3] = m[0][3] * a10 + m[1][3] * a11 + m[2][3] * a12;
+
+ result[2][0] = m[0][0] * a20 + m[1][0] * a21 + m[2][0] * a22;
+ result[2][1] = m[0][1] * a20 + m[1][1] * a21 + m[2][1] * a22;
+ result[2][2] = m[0][2] * a20 + m[1][2] * a21 + m[2][2] * a22;
+ result[2][3] = m[0][3] * a20 + m[1][3] * a21 + m[2][3] * a22;
+
+ result[3][0] = m[3][0];
+ result[3][1] = m[3][1];
+ result[3][2] = m[3][2];
+ result[3][3] = m[3][3];
+ }
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotXRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotYRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotZRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotXRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotYRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotZRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees)
+{
+ NvBuildRotRadMatf(r, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees)
+{
+ NvMultRotRadMatf(r, m, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3])
+{
+ GLfloat ev[3];
+ GLfloat z[3];
+ GLfloat x_tmp[3];
+ GLfloat x[3];
+ GLfloat y[3];
+
+ NvSubVecf(ev, eye, obj);
+
+ NvNormalizeVecf(z, ev);
+
+ NvCrossProductf(x_tmp, up, z);
+
+ NvNormalizeVecf(x, x_tmp);
+
+ NvCrossProductf(y, z, x);
+
+ r[0][0] = x[0];
+ r[0][1] = y[0];
+ r[0][2] = z[0];
+ r[0][3] = 0.0f;
+
+ r[1][0] = x[1];
+ r[1][1] = y[1];
+ r[1][2] = z[1];
+ r[1][3] = 0.0f;
+
+ r[2][0] = x[2];
+ r[2][1] = y[2];
+ r[2][2] = z[2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = -x[0] * eye[0] + -x[1] * eye[1] + -x[2] * eye[2];
+ r[3][1] = -y[0] * eye[0] + -y[1] * eye[1] + -y[2] * eye[2];
+ r[3][2] = -z[0] * eye[0] + -z[1] * eye[1] + -z[2] * eye[2];
+ r[3][3] = 1.0f;
+}
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const m00 = znear * 2.0f / (right - left);
+ GLfloat const m11 = znear * 2.0f / (top - bottom);
+ GLfloat const m22 = -(zfar + znear) / (zfar - znear);
+
+ GLfloat const m20 = (right + left) / (right - left);
+ GLfloat const m21 = (top + bottom) / (top - bottom);
+
+ GLfloat const m32 = -(2.0f * zfar * znear) / (zfar - znear);
+ GLfloat const m23 = -1.0f;
+
+ r[0][0] = m00;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = m11;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = m20;
+ r[2][1] = m21;
+ r[2][2] = m22;
+ r[2][3] = m23;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = m32;
+ r[3][3] = 0.0f;
+}
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+ GLfloat const sz = -2.0f / (zfar - znear);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+ GLfloat const tz = -(zfar + znear) / (zfar - znear);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = sz;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = tz;
+ r[3][3] = 1.0f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.h
new file mode 100644
index 00000000..0709f117
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_matrix.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MATRIX_H
+#define INCLUDED_MATRIX_H
+
+#include <OpenGL/gl.h>
+#include <math.h>
+#include <assert.h>
+
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4]);
+
+/* vector utilities */
+
+GLfloat NvVecLengthf(const GLfloat v[3]);
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3]);
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4]);
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+
+/* matrix utilities */
+
+void NvMultMatf(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4]);
+
+void NvInvMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+
+/* matrix building utilities */
+
+void NvBuildIdentityMatf(GLfloat r[4][4]);
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees);
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees);
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians);
+
+void NvBuildRotRadMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat radians);
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3]);
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top);
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+/* matrix concatenation utilities */
+
+void NvMultTranslateMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+void NvMultScaleMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees);
+
+void NvMultRotXRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotYRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotZRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+
+void NvMultRotRadMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.cpp b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.cpp
new file mode 100644
index 00000000..ec497941
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_quat.h"
+#include <stdlib.h>
+#include <memory.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4])
+{
+ memcpy(r, q, 4 * sizeof(GLfloat));
+}
+
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4])
+{
+ // Assumes that the quaternion is normalized!
+ GLfloat x2 = q[0] * 2.0f;
+ GLfloat y2 = q[1] * 2.0f;
+ GLfloat z2 = q[2] * 2.0f;
+ GLfloat xSq2 = x2 * q[0];
+ GLfloat ySq2 = y2 * q[1];
+ GLfloat zSq2 = z2 * q[2];
+ GLfloat xy2 = x2 * q[1];
+ GLfloat xz2 = x2 * q[2];
+ GLfloat xw2 = x2 * q[3];
+ GLfloat yz2 = y2 * q[2];
+ GLfloat yw2 = y2 * q[3];
+ GLfloat zw2 = z2 * q[3];
+
+ /* Matrix is
+ * | 1 - 2y^2 - 2z^2 2xy - 2zw 2xz + 2yw |
+ * | 2xy + 2zw 1 - 2x^2 - 2z^2 2yz - 2xw |
+ * | 2xz - 2yw 2yz + 2xw 1 - 2x^2 - 2y^2 |
+ */
+ r[0][0] = 1.0f - ySq2 - zSq2;
+ r[0][1] = xy2 - zw2;
+ r[0][2] = xz2 + yw2;
+
+ r[1][0] = xy2 + zw2;
+ r[1][1] = 1.0f - xSq2 - zSq2;
+ r[1][2] = yz2 - xw2;
+
+ r[2][0] = xz2 - yw2;
+ r[2][1] = yz2 + xw2;
+ r[2][2] = 1.0f - xSq2 - ySq2;
+}
+
+void NvQuatIdentity(GLfloat r[4])
+{
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = 1.0f;
+}
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3])
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = axis[0] * sina;
+ r[1] = axis[1] * sina;
+ r[2] = axis[2] * sina;
+ r[3] = cosa;
+}
+
+void NvQuatX(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = sina;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatY(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = sina;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatZ(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = sina;
+ r[3] = cosa;
+}
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatY(h, heading);
+ NvQuatX(p, pitch);
+ NvQuatZ(ro, roll);
+
+ NvQuatMult(r, h, p);
+ NvQuatMult(r, ro, r);
+}
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatZ(ro, roll);
+ NvQuatX(p, pitch);
+ NvQuatY(h, heading);
+
+ NvQuatMult(r, p, h);
+ NvQuatMult(r, r, ro);
+}
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4])
+{
+ return q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3];
+}
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4])
+{
+ const GLfloat q1x = q1[0];
+ const GLfloat q1y = q1[1];
+ const GLfloat q1z = q1[2];
+ const GLfloat q1w = q1[3];
+ const GLfloat q2x = q2[0];
+ const GLfloat q2y = q2[1];
+ const GLfloat q2z = q2[2];
+ const GLfloat q2w = q2[3];
+
+ r[0] = q1y * q2z - q2y * q1z + q1w * q2x + q2w * q1x;
+ r[1] = q1z * q2x - q2z * q1x + q1w * q2y + q2w * q1y;
+ r[2] = q1x * q2y - q2x * q1y + q1w * q2z + q2w * q1z;
+ r[3] = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
+}
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t)
+{
+ GLfloat omt = 1.0f - t;
+
+ if (NvQuatDot(q1, q2) < 0.0f) {
+ r[0] = -q1[0] * omt + q2[0] * t;
+ r[1] = -q1[1] * omt + q2[1] * t;
+ r[2] = -q1[2] * omt + q2[2] * t;
+ r[3] = -q1[3] * omt + q2[3] * t;
+ } else {
+ r[0] = q1[0] * omt + q2[0] * t;
+ r[1] = q1[1] * omt + q2[1] * t;
+ r[2] = q1[2] * omt + q2[2] * t;
+ r[3] = q1[3] * omt + q2[3] * t;
+ }
+
+ NvQuatNormalize(r, r);
+}
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4])
+{
+ GLfloat invLength = 1.0f / sqrtf(NvQuatDot(q, q));
+
+ r[0] = invLength * q[0];
+ r[1] = invLength * q[1];
+ r[2] = invLength * q[2];
+ r[3] = invLength * q[3];
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.h
new file mode 100644
index 00000000..2afdcb71
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_math/nv_quat.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QUAT_H
+#define INCLUDED_QUAT_H
+
+#include <OpenGL/gl.h>
+#include <math.h>
+#include <assert.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4]);
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4]);
+
+void NvQuatIdentity(GLfloat r[4]);
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3]);
+
+void NvQuatX(GLfloat r[4], GLfloat radians);
+
+void NvQuatY(GLfloat r[4], GLfloat radians);
+
+void NvQuatZ(GLfloat r[4], GLfloat radians);
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t);
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4]);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_types.h b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_types.h
new file mode 100644
index 00000000..1d1b0300
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/Qt3DSLibs/nv_types.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_TYPES_H
+#define __INCLUDED_QT3DS_TYPES_H
+
+typedef unsigned char NvU8; // 0 to 255
+typedef unsigned short NvU16; // 0 to 65535
+typedef unsigned int NvU32; // 0 to 4294967295
+typedef unsigned long long NvU64; // 0 to 18446744073709551615
+typedef signed char NvS8; // -128 to 127
+typedef signed short NvS16; // -32768 to 32767
+typedef signed int NvS32; // -2147483648 to 2147483647
+typedef signed long long NvS64; // 2^-63 to 2^63-1
+
+// Explicitly sized floats
+typedef float NvF32; // IEEE Single Precision (S1E8M23)
+typedef double NvF64; // IEEE Double Precision (S1E11M52)
+
+// Boolean type
+#define QT3DS_FALSE 0
+#define QT3DS_TRUE 1
+typedef NvU8 NvBool;
+
+// Result of sizeof operator
+typedef unsigned long NvSize;
+
+// Type large enough to hold a relative file offset
+typedef long NvOffset;
+
+// Base NULL type.
+#define QT3DS_NULL 0
+
+// Error related
+typedef enum {
+ NvError_Success = 0,
+ NvError_NotSupported,
+ NvError_NotInitialized,
+ NvError_BadParameter,
+ NvError_InsufficientMemory,
+ NvError_NoEntries,
+ NvError_UnknownError,
+} NvError;
+
+#if 1 // defined(_DEBUG) // !!!!TBD TODO
+#define NvAssert(c)
+#else
+#define NvAssert(c) ((void)((c) ? 0 : (NvHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+// Other standardized typedefs
+typedef NvU64 NvUST; // U64 unadjusted system time value
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.abc b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.abc
new file mode 100644
index 00000000..f7e3c2f6
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.abc
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.dds b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.dds
new file mode 100644
index 00000000..5bde760b
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_256.dds
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.abc b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.abc
new file mode 100644
index 00000000..2ff78757
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.abc
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.dds b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.dds
new file mode 100644
index 00000000..f9e76d94
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/assets/courier+lucida_512.dds
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/assets/font.frag b/src/Runtime/Source/PlatformSpecific/Macos/assets/font.frag
new file mode 100644
index 00000000..e4673cf8
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/assets/font.frag
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+uniform sampler2D fontTex;
+
+varying lowp vec4 col_var;
+varying lowp vec2 tex_var;
+
+void main()
+{
+ gl_FragColor = texture2D(fontTex, tex_var).a * col_var;
+}
+
diff --git a/src/Runtime/Source/PlatformSpecific/Macos/assets/font.vert b/src/Runtime/Source/PlatformSpecific/Macos/assets/font.vert
new file mode 100644
index 00000000..9f307a2f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Macos/assets/font.vert
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// this is set from higher level. think of it as the upper model matrix
+uniform mat4 pixelToClipMat;
+
+uniform vec4 col_uni;
+
+attribute vec2 pos_attr;
+attribute vec2 tex_attr;
+attribute vec4 col_attr;
+
+varying vec4 col_var;
+varying vec2 tex_var;
+
+void main()
+{
+ // account for translation and rotation of the primitive into [-1,1] spatial default.
+ gl_Position = pixelToClipMat * vec4(pos_attr.x, pos_attr.y, 0, 1);
+
+ col_var = col_attr * col_uni;
+ tex_var = tex_attr;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_color.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_color.h
new file mode 100644
index 00000000..b9347529
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_color.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_COLOR_H
+#define _QT3DS_COLOR_H
+
+/** @file nv_color.h
+ Simple abstraction for RGBA colors as parameters to various libraries/functions.
+*/
+
+/** Base type for a single color channel (8-bit unsigned). */
+typedef unsigned char NvPCColor8;
+
+//#define NV_COLOR_BREAKOLD
+#ifdef NV_COLOR_BREAKOLD // uses a struct to break backwards-compat and accidental uses
+
+typedef struct
+{
+ NvPCColor8 r;
+ NvPCColor8 g;
+ NvPCColor8 b;
+ NvPCColor8 a;
+} NvPackedColor;
+
+static const NvPackedColor gnvpcwhite = { 255, 255, 255, 255 };
+static const NvPackedColor gnvpcblack = { 0, 0, 0, 255 };
+
+#define NV_PACKED_COLOR(r, g, b, a) \
+ { \
+ (NvPCColor8)(r), (NvPCColor8)(g), (NvPCColor8)(b), (NvPCColor8)(a) \
+ }
+
+#define NV_PC_PREDEF_WHITE gnvpcwhite
+#define NV_PC_PREDEF_BLACK gnvpcblack
+
+#define NV_PC_RED(c) (c.r)
+#define NV_PC_GREEN(c) (c.g)
+#define NV_PC_BLUE(c) (c.b)
+#define NV_PC_ALPHA(c) (c.a)
+
+#define NV_PC_PACK_UINT(c) (*(unsigned int *)(&(c)))
+
+#define NV_PC_EQUAL(x, y) ((x).r == (y).r && (x).g == (y).g && (x).b == (y).b && (x).a == (y).a)
+
+#else /* code that doesn't break old pass-as-uint stuff */
+
+/** Main type declaration for a packed 4-color construct. */
+typedef unsigned int NvPackedColor;
+
+/** A macro to build a packed color, passing in RGBA as four 8-bit integer values. */
+#define NV_PACKED_COLOR(r, g, b, a) \
+ ((NvPackedColor)(((((int)(a)) & 0xFF) << 24) | ((((int)(b)) & 0xFF) << 16) \
+ | ((((int)(g)) & 0xFF) << 8) | ((((int)(r)) & 0xFF))))
+
+/** A predefined constant for WHITE. */
+#define NV_PC_PREDEF_WHITE NV_PACKED_COLOR(0xFF, 0xFF, 0xFF, 0xFF)
+/** A predefined constant for BLACK. */
+#define NV_PC_PREDEF_BLACK NV_PACKED_COLOR(0x00, 0x00, 0x00, 0xFF)
+
+/** A macro for 'extracting' the red value from an NvPackedColor. */
+#define NV_PC_RED(c) ((c >> 0) & 0xff)
+/** A macro for 'extracting' the green value from an NvPackedColor. */
+#define NV_PC_GREEN(c) ((c >> 8) & 0xff)
+/** A macro for 'extracting' the blue value from an NvPackedColor. */
+#define NV_PC_BLUE(c) ((c >> 16) & 0xff)
+/** A macro for 'extracting' the alpha value from an NvPackedColor. */
+#define NV_PC_ALPHA(c) ((c >> 24) & 0xff)
+
+/** A macro requesting the packed color repacked into a 32-bit unsigned int.
+ This is a no-op for the color-as-uint approach.
+*/
+#define NV_PC_PACK_UINT(c) (c)
+/** A macro for testing the equality of two NvPackedColors. */
+#define NV_PC_EQUAL(x, y) (x == y)
+#endif
+
+/** A macro for mapping a single packed color channel into its floating point [0,1] rep. */
+#define NV_PC_TO_FLOAT(c) (c / 255.0f)
+
+#endif /*_QT3DS_COLOR_H*/
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_config/nv_config.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_config/nv_config.h
new file mode 100644
index 00000000..fb0b88af
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_config/nv_config.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef _QT3DS_CONFIG_H
+#define _QT3DS_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <KD/kd.h>
+
+/** \file nv_config.h
+ Support for block-based text config files.
+
+ Supports:
+ <ul>
+ <li> C-style comment blocks
+ <li> C++-style comment lines
+ <li> Line continuation via backslash
+ <li> Linux, Mac and Windows line endings
+ <li> Arrays of tokens, broken out by line
+ <li> Tokens are split by commas and whitespace
+ <li> Quoted string tokens containing any characters
+ </ul>
+ */
+
+/** The in-memory representation of a loaded config file.
+
+ This opaque data structure is passed by pointer to all of the
+ configuration functions and represents the loaded configuration
+ file. Once loaded, there is no mutable persistent state in this
+ object. It is passed as const to all functions
+*/
+typedef struct NvConfigData NvConfigData;
+
+/** The representation of a sub-range of lines in a config file.
+
+ This structure is application-readable and mutable, and is used to
+ represent a subset of the lines in a config file. Generally, these
+ ranges represent delineated blocks in the config file. Special versions
+ of many of the config file functions take data ranges instead of
+ entire config files
+
+ @see NvConfigFindDelimitedBlock()
+*/
+typedef struct NvConfigDataRange
+{
+ /** A reference to the "parent" config file for this range */
+ NvConfigData *data;
+ /** The first line of the range (inclusive) */
+ KDint startLine;
+ /** The last line of the range (inclusive) */
+ KDint endLine;
+} NvConfigDataRange;
+
+/** Creates a config data object that represents an existing config file
+
+ @return A pointer to the allocated config data, or NULL if the file cannot
+ be found or does not conform to the basic config file format
+ @param filename The path of the config file to be loaded
+ @see NvConfigFree()
+*/
+NvConfigData *NvConfigCreateFromFile(const KDchar *filename);
+
+/** Creates a config data object from an-in memory string
+
+ Useful when the config file is loaded from a larger, packed data file,
+ or generated on-the-fly in the application. Note that the code does not
+ automatically handle NULL-terminated strings
+
+ @return A pointer to the allocated config data, or NULL if the string
+ does not conform to the basic config file format
+ @param fileBuffer A pointer to the start of the string of config data
+ @param fileSize The length of the string in characters
+ @see NvConfigFree()
+*/
+NvConfigData *NvConfigCreateFromBuffer(const KDchar *fileBuffer, KDint fileSize);
+
+/** Deletes an existing config file data object
+
+ @param data A pointer to the data object to delete
+*/
+void NvConfigFree(NvConfigData *data);
+
+/** Returns the number of token-bearing lines in the config data object.
+
+ This does not count merged lines, comment lines, or whitespace. This
+ value is one greater than the maximum valid line index in the file
+
+ @return The line count
+ @param data A pointer to the data object
+*/
+KDint NvConfigGetLineCount(const NvConfigData *data);
+
+/** Returns the number of tokens in the indexed line
+
+ @return The token count
+ @param data A pointer to the data object
+ @param line The line whose count is to be returned. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @see NvConfigGetLineCount
+*/
+KDint NvConfigGetTokenCount(const NvConfigData *data, KDint line);
+
+/** Returns a NULL-terminated string token at the given line and token index
+
+ The parameters are unchecked.
+
+ @return A non-mutable token pointer for the referenced token
+ @param data A pointer to the data object
+ @param line The line whose token is to be returned. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @param token The token index of the token to be returned. This parameter must
+ be at least 0 and must be less than the token count of the line
+ @see NvConfigGetLineCount
+ @see NvConfigGetTokenCount
+*/
+const KDchar *NvConfigGetToken(const NvConfigData *data, KDint line, KDint token);
+
+/** Returns the string token converted to an integer
+
+ Returns the string token at the given line and token index converted to an integer.
+ The parameters are unchecked, and the string token is assumed to be convertible to
+ an integer value.
+
+ @return The integer value of the referenced token
+ @param data A pointer to the data object
+ @param line The line whose token is to be returned. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @param token The token index of the token to be returned. This parameter must
+ be at least 0 and must be less than the token count of the line
+ @see NvConfigGetLineCount
+ @see NvConfigGetTokenCount
+*/
+KDint NvConfigGetIntToken(const NvConfigData *data, KDint line, KDint token);
+
+/** Returns the string token converted to a floating-point value
+
+ Returns the string token at the given line and token index converted to a
+ floating-point number. The parameters are unchecked, and the string token
+ is assumed to be convertible to a real value.
+
+ @return The floating-point value of the referenced token
+ @param data A pointer to the data object
+ @param line The line whose token is to be returned. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @param token The token index of the token to be returned. This parameter must
+ be at least 0 and must be less than the token count of the line
+ @see NvConfigGetLineCount
+ @see NvConfigGetTokenCount
+*/
+KDfloat32 NvConfigGetFloatToken(const NvConfigData *data, KDint line, KDint token);
+
+/** Returns the count of lines in the config data whose leading token
+ matches a given string
+
+ The search starts at the indicated line and continues to the end of the file
+
+ @return The count of matching lines
+ @param data A pointer to the data object
+ @param name The string to be matched (case-sensitive)
+ @param startLine The line at which the search should start. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @see NvConfigGetLineCount
+*/
+KDint NvConfigCountMatchingLines(const NvConfigData *data, const KDchar *name, KDint startLine);
+
+/** Returns the count of lines in the subrange of the config data
+ whose leading token matches a given string
+
+ The search is run only in the given subrange of the file
+
+ @return The count of matching lines
+ @param range A pointer to the subrange of the data object
+ @param name The string to be matched (case-sensitive)
+*/
+KDint NvConfigCountMatchingLinesInRange(const NvConfigDataRange *range, const KDchar *name);
+
+/** Returns the index of the first line in the config data (at or after
+ the given start line) whose leading token matches a given string
+
+ The search starts at the indicated line and continues to the end of the
+ file
+
+ @return The index of the first matching line, or -1 if no match
+ @param data A pointer to the data object
+ @param name The string to be matched (case-sensitive)
+ @param startLine The line at which the search should start. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @see NvConfigGetLineCount
+*/
+KDint NvConfigFindMatchingLine(const NvConfigData *data, const KDchar *name, KDint startLine);
+
+/** Returns the index of the first line in the subrange of the config data
+ whose leading token matches a given string
+
+ The search is run only in the given subrange of the file
+
+ @return The index of the first matching line, or -1 if no match
+ @param range A pointer to the subrange of the data object
+ @param name The string to be matched (case-sensitive)
+*/
+KDint NvConfigFindMatchingLineInRange(const NvConfigDataRange *range, const KDchar *name);
+
+/** Finds a matching token-delimited block in the file and returns it as a subrange.
+
+ Searches for a token-delimited open/close block in the given line range.
+ If the nested parameter is true, then additional nested open/close blocks
+ are tracked and the returned block is the one that properly closes the
+ given open block. If the nested flag is false, then the open/close are
+ treated like C-comments, and the first closing token found is returned
+
+ @return KD_TRUE if a block with both an open and a close token is found,
+ KD_FALSE otherwise
+ @param data A pointer to the data object
+ @param openText The string token to be matched as the start of a block.
+ (case-sensitive) Only the leading token of each line is tested
+ @param closeText The string token to be matched as the end of a block.
+ (case-sensitive) Only the leading token of each line is tested
+ @param nested If KD_TRUE, C-bracket-style nesting is used to determine
+ which end token is matched. If KD_FALSE, C-comment-style flat matching
+ is used to match the end token.
+ @param startLine The index of the first line to search (inclusive)
+ @param endLine The index of the last line to search (inclusive)
+ @param range Output: A pointer to the subrange of the data object. This
+ should be a pointer to an allocated struct
+*/
+KDboolean NvConfigFindDelimitedBlock(const NvConfigData *data, const KDchar *openText,
+ const KDchar *closeText, KDboolean nested, KDint startLine,
+ KDint endLine, NvConfigDataRange *range);
+
+/** Returns the index of the first matching token in the given line
+
+ Returns the index of the first token on the given line (if any) that
+ matches the given string.
+
+ @return The index of the matching string token in the line, or else -1 if
+ the token is not found in the line
+ @param data A pointer to the data object
+ @param token The string to be matched (case-sensitive)
+ @param line The line to search. This parameter must
+ be at least 0 and must be less than the line count of the object
+ @see NvConfigGetLineCount
+*/
+KDint NvConfigFindMatchingTokenInLine(const NvConfigData *data, const KDchar *token, KDint line);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_debug.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_debug.h
new file mode 100644
index 00000000..2559dd6f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_debug.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_DEBUG_H
+#define __INCLUDED_QT3DS_DEBUG_H
+
+#define CT_ASSERT(tag, cond) enum { COMPILE_TIME_ASSERT__##tag = 1 / (cond) }
+
+#define dimof(x) (sizeof(x) / sizeof(x[0]))
+#include <android/log.h>
+
+#define DBG_DETAILED 0
+
+#if 0
+
+ // the detailed prefix can be customised by setting DBG_DETAILED_PREFIX. See
+ // below as a reference.
+ // NOTE: fmt is the desired format string and must be in the prefix.
+ //#ifndef DBG_DETAILED_PREFIX
+ // #define DBG_DETAILED_PREFIX "%s, %s, line %d: " fmt, __FILE__, __FUNCTION__, __LINE__,
+ //#endif
+ //#define DEBUG_D_(fmt, args...)
+ //#define DEBUG_D(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, (DBG_DETAILED_PREFIX) ## args)
+
+#else
+
+#ifdef STRINGIFY
+#pragma push_macro("STRINGIFY")
+#undef STRINGIFY
+#define STRINGIFYPUSHED_____
+#endif
+#define STRINGIFY(x) #x
+
+// debug macro, includes file name function name and line number
+#define TO(x) typeof(x)
+#define DEBUG_D_(file, line, fmt, args...) \
+ __android_log_print(ANDROID_LOG_DEBUG, MODULE, file ", %s, line(" STRINGIFY(line) "): " fmt, \
+ __FUNCTION__, ##args)
+#define DEBUG_D(fmt, args...) DEBUG_D_(__FILE__, __LINE__, fmt, ##args)
+
+#ifdef STRINGIFYPUSHED_____
+#undef STRINGIFYPUSHED_____
+#pragma pop_macro("STRINGIFY")
+#endif
+
+#endif
+
+// basic debug macro
+#define DEBUG_(fmt, args...) (__android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args))
+
+// Debug macro that can be switched to spew a file name,
+// function and line number using DEBUG_DETAILED
+#if DBG_DETAILED == 1
+#define DEBUG(fmt, args...) DEBUG_D(fmt, ##args)
+#else
+#define DEBUG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MODULE, fmt, ##args)
+#endif
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_global.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_global.h
new file mode 100644
index 00000000..9d23d45f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_global.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_GLOBAL_H
+#define __INCLUDED_QT3DS_GLOBAL_H
+
+#include "nv_types.h"
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/NvVec.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/NvVec.h
new file mode 100644
index 00000000..4e5b09ce
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/NvVec.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_VEC_H
+#define INCLUDED_QT3DS_MATH_CPP_VEC_H
+
+#include "misc.h"
+
+struct _NvVec3
+{
+ union {
+ struct
+ {
+ float x, y, z;
+ };
+ float v[3];
+ };
+};
+
+struct NvVec3 : public _NvVec3
+{
+ NvVec3() { zero(); }
+
+ NvVec3(float x, float y, float z)
+ {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ }
+
+ NvVec3(NvVec3 const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ v[2] = that.v[2];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ v[2] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 3) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec3 &operator+=(NvVec3 const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ v[2] += that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator-=(NvVec3 const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ v[2] -= that.v[2];
+ return *this;
+ }
+
+ NvVec3 &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ v[2] *= s;
+ return *this;
+ }
+
+ NvVec3 &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ v[2] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec3 const &a, NvVec3 const &b)
+{
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+inline NvVec3 operator+(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]);
+}
+
+inline NvVec3 operator-(NvVec3 const &a)
+{
+
+ return NvVec3(-a.v[0], -a.v[1], -a.v[2]);
+}
+
+inline NvVec3 operator*(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] * s, a.v[1] * s, a.v[2] * s);
+}
+
+inline NvVec3 operator*(float s, NvVec3 const &a)
+{
+
+ return NvVec3(s * a.v[0], s * a.v[1], s * a.v[2]);
+}
+
+inline NvVec3 operator/(NvVec3 const &a, float s)
+{
+
+ return NvVec3(a.v[0] / s, a.v[1] / s, a.v[2] / s);
+}
+
+inline float magnitude(NvVec3 const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec3 normalize(NvVec3 const &v)
+{
+ float l = magnitude(v);
+ return NvVec3(v[0] / l, v[1] / l, v[2] / l);
+}
+
+inline NvVec3 cross(NvVec3 const &a, NvVec3 const &b)
+{
+
+ return NvVec3(a.v[1] * b.v[2] - a.v[2] * b.v[1], a.v[2] * b.v[0] - a.v[0] * b.v[2],
+ a.v[0] * b.v[1] - a.v[1] * b.v[0]);
+}
+
+inline bool operator==(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] == b.v[0] && a.v[1] == b.v[1] && a.v[2] == b.v[2]);
+}
+
+inline bool operator!=(NvVec3 const &a, NvVec3 const &b)
+{
+ return (a.v[0] != b.v[0] || a.v[1] != b.v[1] || a.v[2] != b.v[2]);
+}
+
+struct NvVec2f
+{
+ union {
+ struct
+ {
+ float x, y;
+ float v[2];
+ };
+ };
+
+ NvVec2f() { zero(); }
+
+ NvVec2f(float x, float y)
+ {
+ v[0] = x;
+ v[1] = y;
+ }
+
+ NvVec2f(NvVec2f const &that)
+ {
+ v[0] = that.v[0];
+ v[1] = that.v[1];
+ }
+
+ inline void zero()
+ {
+ v[0] = 0.0f;
+ v[1] = 0.0f;
+ }
+
+ inline float &operator[](int i)
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ inline float const &operator[](int i) const
+ {
+ assert((i < 2) && (i >= 0));
+ return v[i];
+ }
+
+ NvVec2f &operator+=(NvVec2f const &that)
+ {
+ v[0] += that.v[0];
+ v[1] += that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator-=(NvVec2f const &that)
+ {
+ v[0] -= that.v[0];
+ v[1] -= that.v[1];
+ return *this;
+ }
+
+ NvVec2f &operator*=(float s)
+ {
+ v[0] *= s;
+ v[1] *= s;
+ return *this;
+ }
+
+ NvVec2f &operator/=(float s)
+ {
+ v[0] /= s;
+ v[1] /= s;
+ return *this;
+ }
+};
+
+inline float dot(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a[0] * b[0] + a[1] * b[1];
+}
+
+inline NvVec2f operator+(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] + b.v[0], a.v[1] + b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return NvVec2f(a.v[0] - b.v[0], a.v[1] - b.v[1]);
+}
+
+inline NvVec2f operator-(NvVec2f const &a)
+{
+
+ return NvVec2f(-a.v[0], -a.v[1]);
+}
+
+inline NvVec2f operator*(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] * s, a.v[1] * s);
+}
+
+inline NvVec2f operator*(float s, NvVec2f const &a)
+{
+
+ return NvVec2f(s * a.v[0], s * a.v[1]);
+}
+
+inline NvVec2f operator/(NvVec2f const &a, float s)
+{
+
+ return NvVec2f(a.v[0] / s, a.v[1] / s);
+}
+
+inline float magnitude(NvVec2f const &v)
+{
+ return sqrtf(dot(v, v));
+}
+
+inline NvVec2f normalize(NvVec2f const &v)
+{
+ float l = dot(v, v);
+ return NvVec2f(v[0] / l, v[1] / l);
+}
+
+inline float cross(NvVec2f const &a, NvVec2f const &b)
+{
+
+ return a.v[0] * b.v[1] - b.v[0] * a.v[1];
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/misc.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/misc.h
new file mode 100644
index 00000000..983410f3
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/misc.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QT3DS_MATH_CPP_MISC_H
+#define INCLUDED_QT3DS_MATH_CPP_MISC_H
+
+inline bool nvIsPowerOfTwo(unsigned int i)
+{
+ return (i & (i - 1)) == 0;
+}
+
+inline float nvDegToRadf(float d)
+{
+ return d * 3.14159265358979323846f / 180.0f;
+}
+
+inline float nvRadToDegf(float r)
+{
+ return r * 180.0f / 3.14159265358979323846f;
+}
+
+/*
+ 'mod' differs from '%' in that it behaves correctly when either the
+ numerator or denominator is negative.
+*/
+
+inline int nvMod(int n, int d)
+{
+ int m = n % d;
+ return (((m < 0) && (d > 0)) || ((m > 0) && (d < 0))) ? (m + d) : m;
+}
+
+inline int nvAbs(int n)
+{
+ if (n < 0)
+ return -n;
+ return n;
+}
+
+inline int nvSign(int n)
+{
+ if (n > 0)
+ return 1;
+ if (n < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ This returns the smallest amplitude value x such that
+ nvMod(b + x, m) == a
+*/
+
+inline int nvDifMod(int a, int b, int m)
+{
+
+ int x1 = a - b;
+ int x2 = (x1 > 0) ? x1 - m : x1 + m;
+ return (nvAbs(x1) < nvAbs(x2)) ? x1 : x2;
+}
+
+inline float nvWrapf(float a, float min, float max)
+{
+
+ assert(max > min);
+
+ float d = max - min;
+ float s = a - min;
+ float q = s / d;
+ float m = q - floorf(q);
+ return m * d + min;
+}
+
+inline float nvClampf(float a, float min, float max)
+{
+ return (a < min) ? min : ((a > max) ? max : a);
+}
+
+inline int nvClampi(int i, int min, int max)
+{
+ return (i < min) ? min : ((i > max) ? max : i);
+}
+
+inline float nvGaussian(float x, float s)
+{
+ float c = s * sqrtf(2.0f * 3.14159265358979323846f);
+ return expf(-(x * x) / (2.0f * s * s)) / c;
+}
+
+inline float nvLerpf(float a, float b, float t)
+{
+ return a * (1.0f - t) + b * t;
+}
+
+inline float nvEasef(float t)
+{
+
+ float t_2 = t * t;
+ float t_3 = t_2 * t;
+ return 3.0f * t_2 - 2.0f * t_3;
+}
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.cpp b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.cpp
new file mode 100644
index 00000000..b83cb39e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_math.h"
+
+static const double a = 16807.0;
+static const double m = 2147483647.0;
+
+static double nextSeed(double seed)
+{
+ double t = a * seed;
+ return t - m * (double)((int)(t / m));
+}
+
+GLfloat NvRandf()
+{
+ static double seed = 1.0;
+ seed = nextSeed(seed);
+ return (GLfloat)(seed * (1 / m));
+}
+
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime)
+{
+ // kdGetTimeUST is never supposed to decrease (i.e. that
+ // means it can't wrap, either. IIRC, it will wrap in
+ // 593 years). So we ignore that option...
+
+ // Used for frame-to-frame diffs, this will fit in 32b
+ // as long as the times are < ~4.3s apart
+ long long int diffTime = newTime - oldTime;
+
+ // Need to find a better way to do this.
+ // However, I believe we will be uSec precise (not run
+ // out of mantissa bits for uSecs) as long as the diff
+ // is < ~16s (1e-6 * (2^24))
+ return ((GLfloat)diffTime) / 1.0e9f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.h
new file mode 100644
index 00000000..cf2d8b30
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_math.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QT3DS_MATH_H
+#define _QT3DS_MATH_H
+
+#include <GLES2/gl2.h>
+
+GLfloat NvRandf();
+
+/* These are the recommended "safer" ways to use GLfloat for time */
+
+/* Returns the seconds between the two given times */
+GLfloat NvClockDiffInSecs(long long int newTime, long long int oldTime);
+
+#define QT3DS_MILISECS_TO_UST(ms) ((long long int)(ms)*1000000)
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.cpp b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.cpp
new file mode 100644
index 00000000..e208ac31
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.cpp
@@ -0,0 +1,1030 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_matrix.h"
+
+int NvDifferentMatsf(GLfloat a[4][4], const GLfloat b[4][4])
+{
+ return ((&a[3][3] < &b[0][0]) || (&b[3][3] < &a[0][0]));
+}
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+}
+
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4])
+{
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+}
+
+GLfloat NvVecLengthf(const GLfloat v[3])
+{
+ return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+}
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3])
+{
+ GLfloat const l = NvVecLengthf(v);
+ r[0] = v[0] / l;
+ r[1] = v[1] / l;
+ r[2] = v[2] / l;
+}
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] + b[0];
+ r[1] = a[1] + b[1];
+ r[2] = a[2] + b[2];
+}
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+ r[2] = a[2] - b[2];
+}
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3])
+{
+ GLfloat t[3];
+
+ t[0] = a[1] * b[2] - a[2] * b[1];
+ t[1] = a[2] * b[0] - a[0] * b[2];
+ t[2] = a[0] * b[1] - a[1] * b[0];
+
+ r[0] = t[0];
+ r[1] = t[1];
+ r[2] = t[2];
+}
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ GLfloat inv_w = 1.0f / (m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3]);
+
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * inv_w;
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * inv_w;
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * inv_w;
+}
+
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0] * a[3];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1] * a[3];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2] * a[3];
+ r[3] = m[0][3] * a[0] + m[1][3] * a[1] + m[2][3] * a[2] + m[3][3] * a[3];
+}
+
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3])
+{
+ r[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2];
+ r[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2];
+ r[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2];
+}
+
+static void NvMultMat3x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x3f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
+ r[0][3] = 0.0f;
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
+ r[1][3] = 0.0f;
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2];
+ r[3][3] = 1.0f;
+}
+
+static void NvMultMat4x4f(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ assert(NvDifferentMatsf(r, a) && NvDifferentMatsf(r, b));
+
+ r[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2] + a[3][0] * b[0][3];
+ r[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2] + a[3][1] * b[0][3];
+ r[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2] + a[3][2] * b[0][3];
+ r[0][3] = a[0][3] * b[0][0] + a[1][3] * b[0][1] + a[2][3] * b[0][2] + a[3][3] * b[0][3];
+
+ r[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2] + a[3][0] * b[1][3];
+ r[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2] + a[3][1] * b[1][3];
+ r[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2] + a[3][2] * b[1][3];
+ r[1][3] = a[0][3] * b[1][0] + a[1][3] * b[1][1] + a[2][3] * b[1][2] + a[3][3] * b[1][3];
+
+ r[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2] + a[3][0] * b[2][3];
+ r[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2] + a[3][1] * b[2][3];
+ r[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2] + a[3][2] * b[2][3];
+ r[2][3] = a[0][3] * b[2][0] + a[1][3] * b[2][1] + a[2][3] * b[2][2] + a[3][3] * b[2][3];
+
+ r[3][0] = a[0][0] * b[3][0] + a[1][0] * b[3][1] + a[2][0] * b[3][2] + a[3][0] * b[3][3];
+ r[3][1] = a[0][1] * b[3][0] + a[1][1] * b[3][1] + a[2][1] * b[3][2] + a[3][1] * b[3][3];
+ r[3][2] = a[0][2] * b[3][0] + a[1][2] * b[3][1] + a[2][2] * b[3][2] + a[3][2] * b[3][3];
+ r[3][3] = a[0][3] * b[3][0] + a[1][3] * b[3][1] + a[2][3] * b[3][2] + a[3][3] * b[3][3];
+}
+
+void NvMultMatf(GLfloat result[4][4], const GLfloat a[4][4], const GLfloat b[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((a[0][3] == 0.0f) && (a[1][3] == 0.0f) && (a[2][3] == 0.0f) && (a[2][3] == 1.0f)
+ && (b[0][3] == 0.0f) && (b[1][3] == 0.0f) && (b[2][3] == 0.0f) && (b[2][3] == 1.0f)) {
+ if ((a[3][0] == 0.0f) && (a[3][1] == 0.0f) && (a[3][2] == 0.0f) && (b[3][0] == 0.0f)
+ && (b[3][1] == 0.0f) && (b[3][2] == 0.0f)) {
+ NvMultMat3x3f(r, a, b);
+ } else {
+ NvMultMat4x3f(r, a, b);
+ }
+ } else {
+ NvMultMat4x4f(r, a, b);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+static void NvInvMat3x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x3f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1] + -m[0][1] * m[1][0] * m[2][2]
+ + -m[0][2] * m[1][1] * m[2][0];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / d;
+ r[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / d;
+ r[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / d;
+ r[0][3] = 0.0f;
+
+ r[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / d;
+ r[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / d;
+ r[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / d;
+ r[1][3] = 0.0f;
+
+ r[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / d;
+ r[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / d;
+ r[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / d;
+ r[2][3] = 0.0f;
+
+ /* x */
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ /* y */
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ /* z */
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = 1.0f;
+}
+
+static void NvInvMat4x4f(GLfloat r[4][4], const GLfloat m[4][4])
+{
+ GLfloat d = m[0][0] * m[1][1] * m[2][2] * m[3][3] + m[0][0] * m[1][2] * m[2][3] * m[3][1]
+ + m[0][0] * m[1][3] * m[2][1] * m[3][2] + m[0][1] * m[1][0] * m[2][3] * m[3][2]
+ + m[0][1] * m[1][2] * m[2][0] * m[3][3] + m[0][1] * m[1][3] * m[2][2] * m[3][0]
+ + m[0][2] * m[1][0] * m[2][1] * m[3][3] + m[0][2] * m[1][1] * m[2][3] * m[3][0]
+ + m[0][2] * m[1][3] * m[2][0] * m[3][1] + m[0][3] * m[1][0] * m[2][2] * m[3][1]
+ + m[0][3] * m[1][1] * m[2][0] * m[3][2] + m[0][3] * m[1][2] * m[2][1] * m[3][0]
+ + -m[0][0] * m[1][1] * m[2][3] * m[3][2] + -m[0][0] * m[1][2] * m[2][1] * m[3][3]
+ + -m[0][0] * m[1][3] * m[2][2] * m[3][1] + -m[0][1] * m[1][0] * m[2][2] * m[3][3]
+ + -m[0][1] * m[1][2] * m[2][3] * m[3][0] + -m[0][1] * m[1][3] * m[2][0] * m[3][2]
+ + -m[0][2] * m[1][0] * m[2][3] * m[3][1] + -m[0][2] * m[1][1] * m[2][0] * m[3][3]
+ + -m[0][2] * m[1][3] * m[2][1] * m[3][0] + -m[0][3] * m[1][0] * m[2][1] * m[3][2]
+ + -m[0][3] * m[1][1] * m[2][2] * m[3][0] + -m[0][3] * m[1][2] * m[2][0] * m[3][1];
+
+ assert(NvDifferentMatsf(r, m));
+
+ r[0][0] = (m[1][1] * m[2][2] * m[3][3] + m[1][2] * m[2][3] * m[3][1]
+ + m[1][3] * m[2][1] * m[3][2] + -m[1][1] * m[2][3] * m[3][2]
+ + -m[1][2] * m[2][1] * m[3][3] + -m[1][3] * m[2][2] * m[3][1])
+ / d;
+
+ r[0][1] = (m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3]
+ + m[0][3] * m[2][2] * m[3][1] + -m[0][1] * m[2][2] * m[3][3]
+ + -m[0][2] * m[2][3] * m[3][1] + -m[0][3] * m[2][1] * m[3][2])
+ / d;
+
+ r[0][2] = (m[0][1] * m[1][2] * m[3][3] + m[0][2] * m[1][3] * m[3][1]
+ + m[0][3] * m[1][1] * m[3][2] + -m[0][1] * m[1][3] * m[3][2]
+ + -m[0][2] * m[1][1] * m[3][3] + -m[0][3] * m[1][2] * m[3][1])
+ / d;
+
+ r[0][3] = (m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3]
+ + m[0][3] * m[1][2] * m[2][1] + -m[0][1] * m[1][2] * m[2][3]
+ + -m[0][2] * m[1][3] * m[2][1] + -m[0][3] * m[1][1] * m[2][2])
+ / d;
+
+ r[1][0] = (m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3]
+ + m[1][3] * m[2][2] * m[3][0] + -m[1][0] * m[2][2] * m[3][3]
+ + -m[1][2] * m[2][3] * m[3][0] + -m[1][3] * m[2][0] * m[3][2])
+ / d;
+
+ r[1][1] = (m[0][0] * m[2][2] * m[3][3] + m[0][2] * m[2][3] * m[3][0]
+ + m[0][3] * m[2][0] * m[3][2] + -m[0][0] * m[2][3] * m[3][2]
+ + -m[0][2] * m[2][0] * m[3][3] + -m[0][3] * m[2][2] * m[3][0])
+ / d;
+
+ r[1][2] = (m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3]
+ + m[0][3] * m[1][2] * m[3][0] + -m[0][0] * m[1][2] * m[3][3]
+ + -m[0][2] * m[1][3] * m[3][0] + -m[0][3] * m[1][0] * m[3][2])
+ / d;
+
+ r[1][3] = (m[0][0] * m[1][2] * m[2][3] + m[0][2] * m[1][3] * m[2][0]
+ + m[0][3] * m[1][0] * m[2][2] + -m[0][0] * m[1][3] * m[2][2]
+ + -m[0][2] * m[1][0] * m[2][3] + -m[0][3] * m[1][2] * m[2][0])
+ / d;
+
+ r[2][0] = (m[1][0] * m[2][1] * m[3][3] + m[1][1] * m[2][3] * m[3][0]
+ + m[1][3] * m[2][0] * m[3][1] + -m[1][0] * m[2][3] * m[3][1]
+ + -m[1][1] * m[2][0] * m[3][3] + -m[1][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][1] =
+ (-m[0][0] * m[2][1] * m[3][3] + -m[0][1] * m[2][3] * m[3][0] + -m[0][3] * m[2][0] * m[3][1]
+ + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] + m[0][3] * m[2][1] * m[3][0])
+ / d;
+
+ r[2][2] = (m[0][0] * m[1][1] * m[3][3] + m[0][1] * m[1][3] * m[3][0]
+ + m[0][3] * m[1][0] * m[3][1] + -m[0][0] * m[1][3] * m[3][1]
+ + -m[0][1] * m[1][0] * m[3][3] + -m[0][3] * m[1][1] * m[3][0])
+ / d;
+
+ r[2][3] = (m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3]
+ + m[0][3] * m[1][1] * m[2][0] + -m[0][1] * m[1][3] * m[2][0]
+ + -m[0][3] * m[1][0] * m[2][1] + -m[0][0] * m[1][1] * m[2][3])
+ / d;
+
+ r[3][0] = (m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2]
+ + m[1][2] * m[2][1] * m[3][0] + -m[1][0] * m[2][1] * m[3][2]
+ + -m[1][1] * m[2][2] * m[3][0] + -m[1][2] * m[2][0] * m[3][1])
+ / d;
+
+ r[3][1] = (m[0][0] * m[2][1] * m[3][2] + m[0][1] * m[2][2] * m[3][0]
+ + m[0][2] * m[2][0] * m[3][1] + -m[0][0] * m[2][2] * m[3][1]
+ + -m[0][1] * m[2][0] * m[3][2] + -m[0][2] * m[2][1] * m[3][0])
+ / d;
+
+ r[3][2] = (m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2]
+ + m[0][2] * m[1][1] * m[3][0] + -m[0][0] * m[1][1] * m[3][2]
+ + -m[0][1] * m[1][2] * m[3][0] + -m[0][2] * m[1][0] * m[3][1])
+ / d;
+
+ r[3][3] = (m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
+ + m[0][2] * m[1][0] * m[2][1] + -m[0][0] * m[1][2] * m[2][1]
+ + -m[0][1] * m[1][0] * m[2][2] + -m[0][2] * m[1][1] * m[2][0])
+ / d;
+}
+
+void NvInvMatf(GLfloat result[4][4], const GLfloat m[4][4])
+{
+ /*
+ Use a temporary matrix for the result and copy the temporary
+ into the result when finished. Doing this instead of writing
+ the result directly guarantees that the routine will work even
+ if the result overlaps one or more of the arguments in
+ memory.
+ */
+
+ GLfloat r[4][4];
+
+ if ((m[0][3] == 0.0f) && (m[1][3] == 0.0f) && (m[2][3] == 0.0f) && (m[2][3] == 1.0f)) {
+ if ((m[3][0] == 0.0f) && (m[3][1] == 0.0f) && (m[3][2] == 0.0f)) {
+ NvInvMat3x3f(r, m);
+ } else {
+ NvInvMat4x3f(r, m);
+ }
+ } else {
+ NvInvMat4x4f(r, m);
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildIdentityMatf(GLfloat r[4][4])
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = x;
+ r[3][1] = y;
+ r[3][2] = z;
+ r[3][3] = 1.0f;
+}
+
+void NvMultTranslateMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y,
+ GLfloat z)
+{
+ GLfloat r[4][4]; /*temporary storage for result */
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[0][0] * x + m[1][0] * y + m[2][0] * z + m[3][0];
+ r[3][1] = m[0][1] * x + m[1][1] * y + m[2][1] * z + m[3][1];
+ r[3][2] = m[0][2] * x + m[1][2] * y + m[2][2] * z + m[3][2];
+ r[3][3] = m[0][3] * x + m[1][3] * y + m[2][3] * z + m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+ r[0][0] = x;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = y;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = z;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultScaleMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z)
+{
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * x;
+ r[0][1] = m[0][1] * x;
+ r[0][2] = m[0][2] * x;
+ r[0][3] = m[0][3] * x;
+
+ r[1][0] = m[1][0] * y;
+ r[1][1] = m[1][1] * y;
+ r[1][2] = m[1][2] * y;
+ r[1][3] = m[1][3] * y;
+
+ r[2][0] = m[2][0] * z;
+ r[2][1] = m[2][1] * z;
+ r[2][2] = m[2][2] * z;
+ r[2][3] = m[2][3] * z;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = 1.0f;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = c;
+ r[1][2] = s;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = -s;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = 0.0f;
+ r[0][2] = -s;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = 1.0f;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = s;
+ r[2][1] = 0.0f;
+ r[2][2] = c;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ r[0][0] = c;
+ r[0][1] = s;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = -s;
+ r[1][1] = c;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvMultRotXRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0];
+ r[0][1] = m[0][1];
+ r[0][2] = m[0][2];
+ r[0][3] = m[0][3];
+
+ r[1][0] = m[1][0] * c + m[2][0] * s;
+ r[1][1] = m[1][1] * c + m[2][1] * s;
+ r[1][2] = m[1][2] * c + m[2][2] * s;
+ r[1][3] = m[1][3] * c + m[2][3] * s;
+
+ r[2][0] = m[1][0] * -s + m[2][0] * c;
+ r[2][1] = m[1][1] * -s + m[2][1] * c;
+ r[2][2] = m[1][2] * -s + m[2][2] * c;
+ r[2][3] = m[1][3] * -s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotYRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[2][0] * -s;
+ r[0][1] = m[0][1] * c + m[2][1] * -s;
+ r[0][2] = m[0][2] * c + m[2][2] * -s;
+ r[0][3] = m[0][3] * c + m[2][3] * -s;
+
+ r[1][0] = m[1][0];
+ r[1][1] = m[1][1];
+ r[1][2] = m[1][2];
+ r[1][3] = m[1][3];
+
+ r[2][0] = m[0][0] * s + m[2][0] * c;
+ r[2][1] = m[0][1] * s + m[2][1] * c;
+ r[2][2] = m[0][2] * s + m[2][2] * c;
+ r[2][3] = m[0][3] * s + m[2][3] * c;
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvMultRotZRadMatf(GLfloat result[4][4], const GLfloat m[4][4], GLfloat radians)
+{
+
+ GLfloat const s = sinf(radians);
+ GLfloat const c = cosf(radians);
+
+ GLfloat r[4][4];
+
+ r[0][0] = m[0][0] * c + m[1][0] * s;
+ r[0][1] = m[0][1] * c + m[1][1] * s;
+ r[0][2] = m[0][2] * c + m[1][2] * s;
+ r[0][3] = m[0][3] * c + m[1][3] * s;
+
+ r[1][0] = m[0][0] * -s + m[1][0] * c;
+ r[1][1] = m[0][1] * -s + m[1][1] * c;
+ r[1][2] = m[0][2] * -s + m[1][2] * c;
+ r[1][3] = m[0][3] * -s + m[1][3] * c;
+
+ r[2][0] = m[2][0];
+ r[2][1] = m[2][1];
+ r[2][2] = m[2][2];
+ r[2][3] = m[2][3];
+
+ r[3][0] = m[3][0];
+ r[3][1] = m[3][1];
+ r[3][2] = m[3][2];
+ r[3][3] = m[3][3];
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotRadMatf(GLfloat result[4][4], const GLfloat axis[3], GLfloat radians)
+{
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ /* build a matrix from the quat */
+
+ result[0][0] = 1.0f - 2.0f * (j * j + k * k);
+ result[0][1] = 2.0f * (i * j + r * k);
+ result[0][2] = 2.0f * (i * k - r * j);
+ result[0][3] = 0.0f;
+
+ result[1][0] = 2.0f * (i * j - r * k);
+ result[1][1] = 1.0f - 2.0f * (i * i + k * k);
+ result[1][2] = 2.0f * (j * k + r * i);
+ result[1][3] = 0.0f;
+
+ result[2][0] = 2.0f * (i * k + r * j);
+ result[2][1] = 2.0f * (j * k - r * i);
+ result[2][2] = 1.0f - 2.0f * (i * i + j * j);
+ result[2][3] = 0.0f;
+
+ result[3][0] = 0.0f;
+ result[3][1] = 0.0f;
+ result[3][2] = 0.0f;
+ result[3][3] = 1.0f;
+}
+
+void NvMultRotRadMatf(GLfloat result[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians)
+{
+ GLfloat r[4][4];
+
+ {
+ /* build a quat first */
+
+ GLfloat i, j, k, r;
+
+ /* should be */
+ GLfloat const dst_l = sinf(radians / 2.0f);
+
+ /* actually is */
+ GLfloat const src_l = sqrtf(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
+
+ if (src_l <= KD_FLT_EPSILON) {
+ i = 0.0f;
+ j = 0.0f;
+ k = 0.0f;
+ r = 1.0f;
+ } else {
+ GLfloat const s = dst_l / src_l;
+ i = axis[0] * s;
+ j = axis[1] * s;
+ k = axis[2] * s;
+ r = cosf(radians / 2.0f);
+ }
+
+ {
+ /* build a matrix from the quat */
+
+ GLfloat const a00 = 1.0f - 2.0f * (j * j + k * k);
+ GLfloat const a01 = 2.0f * (i * j + r * k);
+ GLfloat const a02 = 2.0f * (i * k - r * j);
+
+ GLfloat const a10 = 2.0f * (i * j - r * k);
+ GLfloat const a11 = 1.0f - 2.0f * (i * i + k * k);
+ GLfloat const a12 = 2.0f * (j * k + r * i);
+
+ GLfloat const a20 = 2.0f * (i * k + r * j);
+ GLfloat const a21 = 2.0f * (j * k - r * i);
+ GLfloat const a22 = 1.0f - 2.0f * (i * i + j * j);
+
+ result[0][0] = m[0][0] * a00 + m[1][0] * a01 + m[2][0] * a02;
+ result[0][1] = m[0][1] * a00 + m[1][1] * a01 + m[2][1] * a02;
+ result[0][2] = m[0][2] * a00 + m[1][2] * a01 + m[2][2] * a02;
+ result[0][3] = m[0][3] * a00 + m[1][3] * a01 + m[2][3] * a02;
+
+ result[1][0] = m[0][0] * a10 + m[1][0] * a11 + m[2][0] * a12;
+ result[1][1] = m[0][1] * a10 + m[1][1] * a11 + m[2][1] * a12;
+ result[1][2] = m[0][2] * a10 + m[1][2] * a11 + m[2][2] * a12;
+ result[1][3] = m[0][3] * a10 + m[1][3] * a11 + m[2][3] * a12;
+
+ result[2][0] = m[0][0] * a20 + m[1][0] * a21 + m[2][0] * a22;
+ result[2][1] = m[0][1] * a20 + m[1][1] * a21 + m[2][1] * a22;
+ result[2][2] = m[0][2] * a20 + m[1][2] * a21 + m[2][2] * a22;
+ result[2][3] = m[0][3] * a20 + m[1][3] * a21 + m[2][3] * a22;
+
+ result[3][0] = m[3][0];
+ result[3][1] = m[3][1];
+ result[3][2] = m[3][2];
+ result[3][3] = m[3][3];
+ }
+ }
+
+ NvCopyMatf(result, r);
+}
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotXRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotYRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees)
+{
+ NvBuildRotZRadMatf(r, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotXRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotYRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees)
+{
+ NvMultRotZRadMatf(r, m, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees)
+{
+ NvBuildRotRadMatf(r, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees)
+{
+ NvMultRotRadMatf(r, m, axis, degrees * KD_DEG_TO_RAD_F);
+}
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3])
+{
+ GLfloat ev[3];
+ GLfloat z[3];
+ GLfloat x_tmp[3];
+ GLfloat x[3];
+ GLfloat y[3];
+
+ NvSubVecf(ev, eye, obj);
+
+ NvNormalizeVecf(z, ev);
+
+ NvCrossProductf(x_tmp, up, z);
+
+ NvNormalizeVecf(x, x_tmp);
+
+ NvCrossProductf(y, z, x);
+
+ r[0][0] = x[0];
+ r[0][1] = y[0];
+ r[0][2] = z[0];
+ r[0][3] = 0.0f;
+
+ r[1][0] = x[1];
+ r[1][1] = y[1];
+ r[1][2] = z[1];
+ r[1][3] = 0.0f;
+
+ r[2][0] = x[2];
+ r[2][1] = y[2];
+ r[2][2] = z[2];
+ r[2][3] = 0.0f;
+
+ r[3][0] = -x[0] * eye[0] + -x[1] * eye[1] + -x[2] * eye[2];
+ r[3][1] = -y[0] * eye[0] + -y[1] * eye[1] + -y[2] * eye[2];
+ r[3][2] = -z[0] * eye[0] + -z[1] * eye[1] + -z[2] * eye[2];
+ r[3][3] = 1.0f;
+}
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const m00 = znear * 2.0f / (right - left);
+ GLfloat const m11 = znear * 2.0f / (top - bottom);
+ GLfloat const m22 = -(zfar + znear) / (zfar - znear);
+
+ GLfloat const m20 = (right + left) / (right - left);
+ GLfloat const m21 = (top + bottom) / (top - bottom);
+
+ GLfloat const m32 = -(2.0f * zfar * znear) / (zfar - znear);
+ GLfloat const m23 = -1.0f;
+
+ r[0][0] = m00;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = m11;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = m20;
+ r[2][1] = m21;
+ r[2][2] = m22;
+ r[2][3] = m23;
+
+ r[3][0] = 0.0f;
+ r[3][1] = 0.0f;
+ r[3][2] = m32;
+ r[3][3] = 0.0f;
+}
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = 1.0f;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = 0.0f;
+ r[3][3] = 1.0f;
+}
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar)
+{
+ GLfloat const sx = 2.0f / (right - left);
+ GLfloat const sy = 2.0f / (top - bottom);
+ GLfloat const sz = -2.0f / (zfar - znear);
+
+ GLfloat const tx = -(right + left) / (right - left);
+ GLfloat const ty = -(top + bottom) / (top - bottom);
+ GLfloat const tz = -(zfar + znear) / (zfar - znear);
+
+ r[0][0] = sx;
+ r[0][1] = 0.0f;
+ r[0][2] = 0.0f;
+ r[0][3] = 0.0f;
+
+ r[1][0] = 0.0f;
+ r[1][1] = sy;
+ r[1][2] = 0.0f;
+ r[1][3] = 0.0f;
+
+ r[2][0] = 0.0f;
+ r[2][1] = 0.0f;
+ r[2][2] = sz;
+ r[2][3] = 0.0f;
+
+ r[3][0] = tx;
+ r[3][1] = ty;
+ r[3][2] = tz;
+ r[3][3] = 1.0f;
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.h
new file mode 100644
index 00000000..2a8e186e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_matrix.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MATRIX_H
+#define INCLUDED_MATRIX_H
+
+#include <GLES2/gl2.h>
+#include <math.h>
+#include <assert.h>
+
+#define KD_FLT_EPSILON 1.19209290E-07F
+#define KD_DEG_TO_RAD_F 0.0174532924F
+#define KD_RAD_TO_DEG_F 57.2957802F
+
+void NvCopyMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+void NvExtract3x3Matf(GLfloat r[3][3], const GLfloat m[4][4]);
+
+/* vector utilities */
+
+GLfloat NvVecLengthf(const GLfloat v[3]);
+
+void NvNormalizeVecf(GLfloat r[3], const GLfloat v[3]);
+
+void NvAddVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvSubVecf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvCrossProductf(GLfloat r[3], const GLfloat a[3], const GLfloat b[3]);
+
+void NvTransformPointf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+void NvTransformHomPointf(GLfloat r[4], const GLfloat m[4][4], const GLfloat a[4]);
+void NvTransformVecf(GLfloat r[3], const GLfloat m[4][4], const GLfloat a[3]);
+
+/* matrix utilities */
+
+void NvMultMatf(GLfloat r[4][4], const GLfloat a[4][4], const GLfloat b[4][4]);
+
+void NvInvMatf(GLfloat r[4][4], const GLfloat m[4][4]);
+
+/* matrix building utilities */
+
+void NvBuildIdentityMatf(GLfloat r[4][4]);
+
+void NvBuildTranslateMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildScaleMatf(GLfloat r[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvBuildRotXDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotYDegMatf(GLfloat r[4][4], GLfloat degrees);
+void NvBuildRotZDegMatf(GLfloat r[4][4], GLfloat degrees);
+
+void NvBuildRotDegMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat degrees);
+
+void NvBuildRotXRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotYRadMatf(GLfloat r[4][4], GLfloat radians);
+void NvBuildRotZRadMatf(GLfloat r[4][4], GLfloat radians);
+
+void NvBuildRotRadMatf(GLfloat r[4][4], const GLfloat axis[3], GLfloat radians);
+
+void NvBuildLookatMatf(GLfloat r[4][4], const GLfloat eye[3], const GLfloat obj[3],
+ const GLfloat up[3]);
+
+void NvBuildFrustumMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+void NvBuildOrtho2Matf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top);
+
+void NvBuildOrthoMatf(GLfloat r[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat znear, GLfloat zfar);
+
+/* matrix concatenation utilities */
+
+void NvMultTranslateMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+void NvMultScaleMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat x, GLfloat y, GLfloat z);
+
+void NvMultRotXDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotYDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+void NvMultRotZDegMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat degrees);
+
+void NvMultRotDegMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat degrees);
+
+void NvMultRotXRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotYRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+void NvMultRotZRadMatf(GLfloat r[4][4], const GLfloat m[4][4], GLfloat radians);
+
+void NvMultRotRadMatf(GLfloat r[4][4], const GLfloat m[4][4], const GLfloat axis[3],
+ GLfloat radians);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.cpp b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.cpp
new file mode 100644
index 00000000..9626eb8c
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nv_quat.h"
+#include <stdlib.h>
+#include <string.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4])
+{
+ memcpy(r, q, 4 * sizeof(GLfloat));
+}
+
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4])
+{
+ // Assumes that the quaternion is normalized!
+ GLfloat x2 = q[0] * 2.0f;
+ GLfloat y2 = q[1] * 2.0f;
+ GLfloat z2 = q[2] * 2.0f;
+ GLfloat xSq2 = x2 * q[0];
+ GLfloat ySq2 = y2 * q[1];
+ GLfloat zSq2 = z2 * q[2];
+ GLfloat xy2 = x2 * q[1];
+ GLfloat xz2 = x2 * q[2];
+ GLfloat xw2 = x2 * q[3];
+ GLfloat yz2 = y2 * q[2];
+ GLfloat yw2 = y2 * q[3];
+ GLfloat zw2 = z2 * q[3];
+
+ /* Matrix is
+ * | 1 - 2y^2 - 2z^2 2xy - 2zw 2xz + 2yw |
+ * | 2xy + 2zw 1 - 2x^2 - 2z^2 2yz - 2xw |
+ * | 2xz - 2yw 2yz + 2xw 1 - 2x^2 - 2y^2 |
+ */
+ r[0][0] = 1.0f - ySq2 - zSq2;
+ r[0][1] = xy2 - zw2;
+ r[0][2] = xz2 + yw2;
+
+ r[1][0] = xy2 + zw2;
+ r[1][1] = 1.0f - xSq2 - zSq2;
+ r[1][2] = yz2 - xw2;
+
+ r[2][0] = xz2 - yw2;
+ r[2][1] = yz2 + xw2;
+ r[2][2] = 1.0f - xSq2 - ySq2;
+}
+
+void NvQuatIdentity(GLfloat r[4])
+{
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = 1.0f;
+}
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3])
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = axis[0] * sina;
+ r[1] = axis[1] * sina;
+ r[2] = axis[2] * sina;
+ r[3] = cosa;
+}
+
+void NvQuatX(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = sina;
+ r[1] = 0.0f;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatY(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = sina;
+ r[2] = 0.0f;
+ r[3] = cosa;
+}
+
+void NvQuatZ(GLfloat r[4], GLfloat radians)
+{
+ GLfloat cosa = cosf(radians * 0.5f);
+ GLfloat sina = sinf(radians * 0.5f);
+
+ r[0] = 0.0f;
+ r[1] = 0.0f;
+ r[2] = sina;
+ r[3] = cosa;
+}
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatY(h, heading);
+ NvQuatX(p, pitch);
+ NvQuatZ(ro, roll);
+
+ NvQuatMult(r, h, p);
+ NvQuatMult(r, ro, r);
+}
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll)
+{
+ GLfloat h[4], p[4], ro[4];
+
+ NvQuatZ(ro, roll);
+ NvQuatX(p, pitch);
+ NvQuatY(h, heading);
+
+ NvQuatMult(r, p, h);
+ NvQuatMult(r, r, ro);
+}
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4])
+{
+ return q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3];
+}
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4])
+{
+ const GLfloat q1x = q1[0];
+ const GLfloat q1y = q1[1];
+ const GLfloat q1z = q1[2];
+ const GLfloat q1w = q1[3];
+ const GLfloat q2x = q2[0];
+ const GLfloat q2y = q2[1];
+ const GLfloat q2z = q2[2];
+ const GLfloat q2w = q2[3];
+
+ r[0] = q1y * q2z - q2y * q1z + q1w * q2x + q2w * q1x;
+ r[1] = q1z * q2x - q2z * q1x + q1w * q2y + q2w * q1y;
+ r[2] = q1x * q2y - q2x * q1y + q1w * q2z + q2w * q1z;
+ r[3] = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
+}
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t)
+{
+ GLfloat omt = 1.0f - t;
+
+ if (NvQuatDot(q1, q2) < 0.0f) {
+ r[0] = -q1[0] * omt + q2[0] * t;
+ r[1] = -q1[1] * omt + q2[1] * t;
+ r[2] = -q1[2] * omt + q2[2] * t;
+ r[3] = -q1[3] * omt + q2[3] * t;
+ } else {
+ r[0] = q1[0] * omt + q2[0] * t;
+ r[1] = q1[1] * omt + q2[1] * t;
+ r[2] = q1[2] * omt + q2[2] * t;
+ r[3] = q1[3] * omt + q2[3] * t;
+ }
+
+ NvQuatNormalize(r, r);
+}
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4])
+{
+ GLfloat invLength = 1.0f / sqrtf(NvQuatDot(q, q));
+
+ r[0] = invLength * q[0];
+ r[1] = invLength * q[1];
+ r[2] = invLength * q[2];
+ r[3] = invLength * q[3];
+}
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.h
new file mode 100644
index 00000000..688c30a7
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_math/nv_quat.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_QUAT_H
+#define INCLUDED_QUAT_H
+
+#include <GLES2/gl2.h>
+#include <math.h>
+#include <assert.h>
+
+void NvQuatCopy(GLfloat r[4], const GLfloat q[4]);
+void NvQuatConvertTo3x3Mat(GLfloat r[3][3], const GLfloat q[4]);
+
+void NvQuatIdentity(GLfloat r[4]);
+
+void NvQuatFromAngleAxis(GLfloat r[4], GLfloat radians, const GLfloat axis[3]);
+
+void NvQuatX(GLfloat r[4], GLfloat radians);
+
+void NvQuatY(GLfloat r[4], GLfloat radians);
+
+void NvQuatZ(GLfloat r[4], GLfloat radians);
+
+void NvQuatFromEuler(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+void NvQuatFromEulerReverse(GLfloat r[4], GLfloat heading, GLfloat pitch, GLfloat roll);
+
+GLfloat NvQuatDot(const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatMult(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4]);
+
+void NvQuatNLerp(GLfloat r[4], const GLfloat q1[4], const GLfloat q2[4], GLfloat t);
+
+void NvQuatNormalize(GLfloat r[4], const GLfloat q[4]);
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_types.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_types.h
new file mode 100644
index 00000000..1d1b0300
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/nv_types.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009-2011 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __INCLUDED_QT3DS_TYPES_H
+#define __INCLUDED_QT3DS_TYPES_H
+
+typedef unsigned char NvU8; // 0 to 255
+typedef unsigned short NvU16; // 0 to 65535
+typedef unsigned int NvU32; // 0 to 4294967295
+typedef unsigned long long NvU64; // 0 to 18446744073709551615
+typedef signed char NvS8; // -128 to 127
+typedef signed short NvS16; // -32768 to 32767
+typedef signed int NvS32; // -2147483648 to 2147483647
+typedef signed long long NvS64; // 2^-63 to 2^63-1
+
+// Explicitly sized floats
+typedef float NvF32; // IEEE Single Precision (S1E8M23)
+typedef double NvF64; // IEEE Double Precision (S1E11M52)
+
+// Boolean type
+#define QT3DS_FALSE 0
+#define QT3DS_TRUE 1
+typedef NvU8 NvBool;
+
+// Result of sizeof operator
+typedef unsigned long NvSize;
+
+// Type large enough to hold a relative file offset
+typedef long NvOffset;
+
+// Base NULL type.
+#define QT3DS_NULL 0
+
+// Error related
+typedef enum {
+ NvError_Success = 0,
+ NvError_NotSupported,
+ NvError_NotInitialized,
+ NvError_BadParameter,
+ NvError_InsufficientMemory,
+ NvError_NoEntries,
+ NvError_UnknownError,
+} NvError;
+
+#if 1 // defined(_DEBUG) // !!!!TBD TODO
+#define NvAssert(c)
+#else
+#define NvAssert(c) ((void)((c) ? 0 : (NvHandleAssertion(#c, __FILE__, __LINE__), 0)))
+#endif
+
+// Other standardized typedefs
+typedef NvU64 NvUST; // U64 unadjusted system time value
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/qt3ds_launcher_defs.h b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/qt3ds_launcher_defs.h
new file mode 100644
index 00000000..6577fb4a
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/Qt3DSLibs/qt3ds_launcher_defs.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* TAGRELEASE: public */
+
+#ifndef _QT3DSLAUNCHERDEFS_H
+#define _QT3DSLAUNCHERDEFS_H
+
+/* Applications should call kdSetWindowPropertyiv with
+ * KD_WINDOWPROPERTY_APP_ID_QT3DS as the pname
+ * and one of the ID's below as the param
+ * Or else define their own in the range starting with
+ * KD_APP_ID_USER_BASE_QT3DS
+ * call must be made _prior_ to window realize
+ */
+
+/* Need to define an NV internal KD property range - defining to a fixed value for now */
+/* But this window property is unused in the current KD spec */
+#define KD_WINDOWPROPERTY_APP_ID_QT3DS 0x1000
+
+#define KD_APP_ID_UNKNOWN_QT3DS 0
+#define KD_APP_ID_KEYBOARD_QT3DS 1 /* QT3DS RESERVED */
+#define KD_APP_ID_CONTACTS_QT3DS 2 /* QT3DS RESERVED */
+#define KD_APP_ID_MESSAGING_QT3DS 3 /* QT3DS RESERVED */
+#define KD_APP_ID_EMAIL_QT3DS 4 /* QT3DS RESERVED */
+#define KD_APP_ID_IM_QT3DS 5 /* QT3DS RESERVED */
+#define KD_APP_ID_PHONEDIALER_QT3DS 6 /* QT3DS RESERVED */
+#define KD_APP_ID_GAME_QT3DS 7
+#define KD_APP_ID_ADDRESSBOOK_QT3DS 8 /* Assigned to NV addrbook demo */
+#define KD_APP_ID_MUSICPLAYER_QT3DS 9 /* Assigned to NV mediaplayer demo */
+#define KD_APP_ID_SMS_QT3DS 10 /* QT3DS RESERVED */
+#define KD_APP_ID_IMAGEBROWSER_QT3DS 11 /* Assigned to NV photoviewer demo */
+#define KD_APP_ID_MAP_QT3DS 12 /* QT3DS RESERVED */
+#define KD_APP_ID_HOME_QT3DS 13 /* Assigned to NV launcher_gui home screen */
+#define KD_APP_ID_CALENDAR_QT3DS 14 /* QT3DS RESERVED */
+#define KD_APP_ID_VIDEO_QT3DS 15 /* Assigned to NV videoplayer demo */
+#define KD_APP_ID_WIDGETS_QT3DS 16 /* QT3DS RESERVED */
+#define KD_APP_ID_CAMERA_QT3DS 19 /* QT3DS RESERVED */
+#define KD_APP_ID_MEDIAWALL_QT3DS 20 /* QT3DS RESERVED */
+#define KD_APP_ID_OPERA_QT3DS 21 /* QT3DS RESERVED */
+#define KD_APP_ID_YOUTUBE_QT3DS 22 /* QT3DS RESERVED */
+#define KD_APP_ID_VISION_QT3DS 23 /* QT3DS RESERVED */
+#define KD_APP_ID_USER_BASE_QT3DS 1024 /* Base of app-reserved */
+
+/* starting orientation support */
+#define KD_WINDOWPROPERTY_ORIENTATION_QT3DS 0x1001
+
+#define KD_WINDOWPROPERTY_STATUSBAR_QT3DS 0x1002
+#define KD_STATUSBAR_HIDEALL_QT3DS 0x0000
+#define KD_STATUSBAR_SHOWBAR_QT3DS 0x0001
+#define KD_STATUSBAR_SHOWBG_QT3DS 0x0002 /* not set as state, just for mask */
+#define KD_STATUSBAR_SHOWALL_QT3DS 0x0003 /* this is showbar+showbg in bits...*/
+
+#define KD_WINDOWPROPERTY_PROCESS_ID_QT3DS 0x1003
+
+/* App-level KD state - if this exists and is nonzero, then the app is */
+/* Running in the launcher */
+
+#define KD_STATE_LAUNCHER_ACTIVE_QT3DS 0x11001
+
+/* Part of GL_NV_log_textures extension */
+/* Not currently supported in external release */
+#define GL_LOG_TEXTURES_QT3DS 0x85FF
+#define GL_LOG_TEXTURES_ZONE_QT3DS 0x85FE
+
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/UICViewer/Resource.h b/src/Runtime/Source/PlatformSpecific/Windows/UICViewer/Resource.h
new file mode 100644
index 00000000..58c9336e
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/UICViewer/Resource.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define IDI_ICON1 103
+#define IDI_ICON2 105
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 106
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.abc b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.abc
new file mode 100644
index 00000000..f7e3c2f6
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.abc
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.dds b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.dds
new file mode 100644
index 00000000..5bde760b
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_256.dds
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.abc b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.abc
new file mode 100644
index 00000000..2ff78757
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.abc
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.dds b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.dds
new file mode 100644
index 00000000..f9e76d94
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/assets/courier+lucida_512.dds
Binary files differ
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/assets/font.frag b/src/Runtime/Source/PlatformSpecific/Windows/assets/font.frag
new file mode 100644
index 00000000..e4673cf8
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/assets/font.frag
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+uniform sampler2D fontTex;
+
+varying lowp vec4 col_var;
+varying lowp vec2 tex_var;
+
+void main()
+{
+ gl_FragColor = texture2D(fontTex, tex_var).a * col_var;
+}
+
diff --git a/src/Runtime/Source/PlatformSpecific/Windows/assets/font.vert b/src/Runtime/Source/PlatformSpecific/Windows/assets/font.vert
new file mode 100644
index 00000000..9f307a2f
--- /dev/null
+++ b/src/Runtime/Source/PlatformSpecific/Windows/assets/font.vert
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// this is set from higher level. think of it as the upper model matrix
+uniform mat4 pixelToClipMat;
+
+uniform vec4 col_uni;
+
+attribute vec2 pos_attr;
+attribute vec2 tex_attr;
+attribute vec4 col_attr;
+
+varying vec4 col_var;
+varying vec2 tex_var;
+
+void main()
+{
+ // account for translation and rotation of the primitive into [-1,1] spatial default.
+ gl_Position = pixelToClipMat * vec4(pos_attr.x, pos_attr.y, 0, 1);
+
+ col_var = col_attr * col_uni;
+ tex_var = tex_attr;
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/AutoDeallocatorAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/AutoDeallocatorAllocator.h
new file mode 100644
index 00000000..5cbbc8bb
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/AutoDeallocatorAllocator.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_FOUNDATION_AUTO_DEALLOCATOR_ALLOCATOR_H
+#define QT3DS_FOUNDATION_AUTO_DEALLOCATOR_ALLOCATOR_H
+#pragma once
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ using eastl::make_pair;
+ using eastl::pair;
+
+ struct SSAutoDeallocatorAllocator : public NVAllocatorCallback
+ {
+ NVAllocatorCallback &m_Allocator;
+ nvhash_map<void *, size_t> m_Allocations;
+ SSAutoDeallocatorAllocator(NVFoundationBase &inFnd)
+ : m_Allocator(inFnd.getAllocator())
+ , m_Allocations(inFnd.getAllocator(), "SSAutoDeallocatorAllocator::m_Allocations")
+ {
+ }
+
+ SSAutoDeallocatorAllocator(NVAllocatorCallback &inAlloc)
+ : m_Allocator(inAlloc)
+ , m_Allocations(inAlloc, "SSAutoDeallocatorAllocator::m_Allocations")
+ {
+ }
+
+ // Automatically deallocates everything that hasn't already been deallocated.
+ ~SSAutoDeallocatorAllocator() { deallocateAllAllocations(); }
+
+ void deallocateAllAllocations()
+ {
+ for (nvhash_map<void *, size_t>::iterator iter = m_Allocations.begin(),
+ end = m_Allocations.end();
+ iter != end; ++iter)
+ m_Allocator.deallocate(iter->first);
+ m_Allocations.clear();
+ }
+
+ void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ int flags = 0) override
+ {
+ void *value = m_Allocator.allocate(size, typeName, filename, line, flags);
+ m_Allocations.insert(make_pair(value, size));
+ return value;
+ }
+
+ void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ size_t alignment, size_t alignmentOffset) override
+ {
+ void *value =
+ m_Allocator.allocate(size, typeName, filename, line, alignment, alignmentOffset);
+ m_Allocations.insert(make_pair(value, size));
+ return value;
+ }
+ void deallocate(void *ptr) override
+ {
+ nvhash_map<void *, size_t>::iterator iter = m_Allocations.find(ptr);
+ QT3DS_ASSERT(iter != m_Allocations.end());
+ m_Allocator.deallocate(iter->first);
+ m_Allocations.erase(iter);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/ConvertUTF.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/ConvertUTF.h
new file mode 100644
index 00000000..14b88c7c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/ConvertUTF.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Header file.
+
+ Several funtions are included here, forming a complete set of
+ conversions between the three formats. UTF-7 is not included
+ here, but is handled in a separate source file.
+
+ Each of these routines takes pointers to input buffers and output
+ buffers. The input buffers are const.
+
+ Each routine converts the text between *sourceStart and sourceEnd,
+ putting the result into the buffer between *targetStart and
+ targetEnd. Note: the end pointers are *after* the last item: e.g.
+ *(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+ and if not, whether the problem was in the source or target buffers.
+ (Only the first encountered problem is indicated.)
+
+ After the conversion, *sourceStart and *targetStart are both
+ updated to point to the end of last text successfully converted in
+ the respective buffers.
+
+ Input parameters:
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
+
+ These conversion functions take a ConversionFlags argument. When this
+ flag is set to strict, both irregular sequences and isolated surrogates
+ will cause an error. When the flag is set to lenient, both irregular
+ sequences and isolated surrogates are converted.
+
+ Whether the flag is strict or lenient, all illegal sequences will cause
+ an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+ or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ must check for illegal sequences.
+
+ When the flag is set to lenient, characters over 0x10FFFF are converted
+ to the replacement character; otherwise (when the flag is set to strict)
+ they constitute an error.
+
+ Output parameters:
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
+
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+/* ---------------------------------------------------------------------
+ The following 4 definitions are compiler-specific.
+ The C standard does not guarantee that wchar_t has at least
+ 16 bits, so wchar_t is no less portable than unsigned short!
+ All should be unsigned values to avoid sign extension during
+ bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned int UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
+
+/* Some fundamental constants */
+
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+typedef enum {
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+} ConversionResult;
+
+typedef enum { strictConversion = 0, lenientConversion } ConversionFlags;
+
+/* This is for C++ and does no harm in C */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ConversionResult ConvertUTF8toUTF16(const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF8(const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF32(const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF16(const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags);
+
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/FastAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/FastAllocator.h
new file mode 100644
index 00000000..c296bcb6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/FastAllocator.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSContainers.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ /**
+ * Allocator that allocates slabs of a certain size and objects then
+ * get allocated from those slabs. This allocator is designed to reset,
+ * meaning every frame you can call reset and the objects get freed but
+ * not destructed. This allocator does not call destructors!!
+ */
+ template <QT3DSU32 alignmentInBytes = 4, QT3DSU32 slabSize = 8192>
+ struct SFastAllocator : NVAllocatorCallback
+ {
+ ForwardingAllocator m_Allocator;
+ nvvector<QT3DSU8 *> m_Slabs;
+ QT3DSU32 m_Offset;
+
+ enum {
+ SlabSize = slabSize,
+ };
+
+ static size_t getSlabSize() { return slabSize; }
+
+ SFastAllocator(NVAllocatorCallback &alloc, const char *memName)
+ : m_Allocator(alloc, memName)
+ , m_Slabs(alloc, "SFastAllocator::m_Slabs")
+ , m_Offset(0)
+ {
+ }
+
+ ~SFastAllocator()
+ {
+ for (QT3DSU32 idx = 0, end = m_Slabs.size(); idx < end; ++idx)
+ m_Allocator.deallocate(m_Slabs[idx]);
+ m_Slabs.clear();
+ m_Offset = 0;
+ }
+ void *allocate(size_t inSize, const char *inFile, int inLine, int inFlags = 0)
+ {
+ (void)inFlags;
+ if (inSize > slabSize) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ QT3DSU32 misalign = m_Offset % alignmentInBytes;
+ if (misalign)
+ m_Offset = m_Offset + (alignmentInBytes - misalign);
+
+ QT3DSU32 currentSlab = m_Offset / slabSize;
+ QT3DSU32 slabOffset = m_Offset % slabSize;
+ QT3DSU32 amountLeftInSlab = slabSize - slabOffset;
+ if (inSize > amountLeftInSlab) {
+ ++currentSlab;
+ slabOffset = 0;
+ m_Offset = currentSlab * slabSize;
+ }
+ while (currentSlab >= m_Slabs.size()) {
+ m_Slabs.push_back((QT3DSU8 *)m_Allocator.allocate(slabSize, inFile, inLine));
+ }
+ QT3DSU8 *data = m_Slabs[currentSlab] + slabOffset;
+ // This would indicate the underlying allocator isn't handing back aligned memory.
+ QT3DS_ASSERT(reinterpret_cast<size_t>(data) % alignmentInBytes == 0);
+ m_Offset += (QT3DSU32)inSize;
+ return data;
+ }
+ void *allocate(size_t size, const char * /*typeName*/, const char *filename, int line,
+ int flags = 0) override
+ {
+ return allocate(size, filename, line, flags);
+ }
+ void *allocate(size_t size, const char * /*typeName*/, const char *filename, int line,
+ size_t alignment, size_t /*alignmentOffset*/) override
+ {
+ QT3DS_ASSERT(alignment == alignmentInBytes);
+ if (alignment == alignmentInBytes)
+ return allocate(size, filename, line);
+ return NULL;
+ }
+ // only reset works with deallocation
+ void deallocate(void *) override {}
+ void reset() { m_Offset = 0; }
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/FileTools.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/FileTools.h
new file mode 100644
index 00000000..9b275aad
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/FileTools.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_FILE_TOOLS_H
+#define QT3DS_FOUNDATION_FILE_TOOLS_H
+
+#include "EASTL/string.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/StringTable.h"
+#include "foundation/IOStreams.h"
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
+
+namespace qt3ds {
+namespace foundation {
+
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TStr;
+
+ class CFileTools
+ {
+ public:
+ // Normalizes all slashes to be windows-like
+ static void NormalizePath(TStr &ioPath);
+ static void NormalizePath(eastl::string &ioPath);
+
+ // This is kind of the opposite of the 'NormalizePath' methods above in
+ // that it forces usage of unix style directory separators rather than
+ // windows separators. In addition, the path here can be a file path or
+ // a qrc URL string. This function will eventually be refactored away
+ // when we've converted to using Qt's file system abstraction throughout
+ // the code base and use QUrl's throughout instead of raw strings to
+ // represent resources.
+ static QString NormalizePathForQtUsage(const QString &path);
+
+ static void CombineBaseAndRelative(const char8_t *inBase, const char8_t *inRelative,
+ TStr &outString);
+ static void CombineBaseAndRelative(const char8_t *inBase, const char8_t *inRelative,
+ eastl::string &outString);
+
+ // inBase and inRelative will get normalized
+ // This algorithm changes based on the platform. On windows it is not case sensitive, on
+ // not-windows it is.
+ static void GetRelativeFromBase(TStr &inBase, TStr &inRelative, TStr &outString);
+ static void GetRelativeFromBase(eastl::string &inBase, eastl::string &inRelative,
+ eastl::string &outString);
+
+ // A remapped path is a file path that starts with a '.' or a '/'. GetRelativeFromBase
+ // *always*
+ // places a '.' or a '/' at the front of the path, so if you *know* the path came from
+ // GetRelativeFromBase then you also know this function returns true of GetRelativeFromBase
+ // actually generated a path that needs CombineBaseAndRelative.
+ static bool RequiresCombineBaseAndRelative(const char8_t *inPath);
+
+ // Search/replace so that all slashes are unix-like but only on non-windows platforms
+ // Assumes the incoming path has been normalized
+ static void ToPlatformPath(TStr &ioPath);
+ static void ToPlatformPath(eastl::string &ioPath);
+
+ static CRegisteredString RemapPathToBinaryFormat(TStr &inPath, TStr &inPresentationDir,
+ TStr &ioWorkspaceStr,
+ IStringTable &inStringTable);
+ static CRegisteredString RemapPathFromBinaryFormat(CRegisteredString inPath,
+ const char8_t *inPresDir,
+ TStr &ioWorkspaceStr,
+ const CStrTableOrDataRef &inRef,
+ IStringTable &inStringTable);
+ // I
+ static void GetDirectory(eastl::string &ioPath);
+ static bool DirectoryExists(const char8_t *inPath);
+ static void GetExtension(const char8_t *inPath, eastl::string &outExt);
+ static void Split(const char8_t *inPath, eastl::string &outDir, eastl::string &outFileStem,
+ eastl::string &outExtension);
+
+ // Only implemented for windows. Does not return '.' and '..' special entries
+ // inPath is mangled in a platform specific way
+ static void GetDirectoryEntries(const eastl::string &inPath,
+ eastl::vector<eastl::string> &outFiles);
+
+ static bool CreateDir(const eastl::string &inPath, bool inRecurse = true);
+
+ // Given a/b.txt, we will end up with a/dirName/b.txt
+ static void AppendDirectoryInPathToFile(eastl::string &ioPath, const char8_t *dirName);
+ static void RemoveLastDirectoryInPathToFile(eastl::string &ioPath);
+
+ static void SetExtension(eastl::string &ioPath, const char8_t *inExt);
+
+ static bool FileExists(const char8_t *inPath);
+ static eastl::string GetFileOrAssetPath(const char8_t *inPath);
+ static void SetStreamPosition(QIODevice& device, qint64 inOffset,
+ qt3ds::foundation::SeekPosition::Enum inEnum);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/IOStreams.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/IOStreams.h
new file mode 100644
index 00000000..855e5209
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/IOStreams.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_IO_STREAMS_H
+#define QT3DS_FOUNDATION_IO_STREAMS_H
+
+#include "EABase/eabase.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSMath.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Utils.h"
+#include "foundation/Qt3DSRefCounted.h"
+
+#include <QFile>
+#include <QString>
+
+namespace qt3ds {
+class NVFoundationBase;
+
+namespace foundation {
+
+ class IOutStream
+ {
+ protected:
+ virtual ~IOutStream() {}
+ public:
+ virtual bool Write(NVConstDataRef<QT3DSU8> data) = 0;
+ void WriteWithLen(NVConstDataRef<QT3DSU8> data)
+ {
+ Write(data.size());
+ Write(data);
+ }
+ template <typename TDataType>
+ void Write(const TDataType &type)
+ {
+ Write(toU8ConstDataRef(type));
+ }
+ template <typename TDataType>
+ void Write(const TDataType *data, QT3DSU32 numItems)
+ {
+ Write(toU8ConstDataRef(data, numItems));
+ }
+ void Write(const wchar_t *data)
+ {
+ if (data == NULL)
+ data = L"";
+ // Write the null character at the end of the string.
+ // This just makes reading and debugging a lot less error prone.
+ // at the expense of 2 bytes.
+ Write(data, (QT3DSU32)StrLen(data) + 1);
+ }
+ template <typename TDataType>
+ void WriteWithLen(const TDataType *data, QT3DSU32 numItems)
+ {
+ WriteWithLen(toU8ConstDataRef(data, numItems));
+ }
+ };
+
+ class IInStream
+ {
+ protected:
+ virtual ~IInStream() {}
+ public:
+ // Semantics are precisely that you return the amount read
+ virtual QT3DSU32 Read(NVDataRef<QT3DSU8> data) = 0;
+
+ QT3DSU32 SafeRead(NVDataRef<QT3DSU8> data)
+ {
+ QT3DSU32 amountRead = Read(data);
+ QT3DS_ASSERT(amountRead == data.size());
+ if (amountRead < data.size())
+ intrinsics::memZero(data.begin() + amountRead, data.size() - amountRead);
+ return amountRead;
+ }
+ QT3DSU32 ReadWithLen(NVDataRef<QT3DSU8> data)
+ {
+ QT3DSU32 len = 0;
+ Read(len);
+ return SafeRead(toDataRef(data.begin(), len));
+ }
+ template <typename TDataType>
+ QT3DSU32 Read(TDataType &type)
+ {
+ return SafeRead(toU8DataRef(type));
+ }
+ template <typename TDataType>
+ QT3DSU32 Read(TDataType *data, QT3DSU32 numItems)
+ {
+ return SafeRead(toU8DataRef(data, numItems));
+ }
+ };
+
+ struct SeekPosition
+ {
+ enum Enum {
+ Unknown,
+ Begin,
+ Current,
+ End,
+ };
+ };
+
+ class ISeekable
+ {
+ protected:
+ virtual ~ISeekable() {}
+ public:
+ virtual void SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inEnum) = 0;
+ virtual QT3DSI64 GetPosition() const = 0;
+ virtual QT3DSI64 GetLength() const
+ {
+ ISeekable &seekable(const_cast<ISeekable &>(*this));
+ QT3DSI64 currentPos(GetPosition());
+ seekable.SetPosition(0, SeekPosition::End);
+ QT3DSI64 retval(GetPosition());
+ seekable.SetPosition(currentPos, SeekPosition::Begin);
+ return retval;
+ }
+ };
+
+ class ISeekableIOStream : public IInStream, public IOutStream, public ISeekable
+ {
+ };
+
+ struct FileOpenFlagValues
+ {
+ enum Enum {
+ Open = 1, // Without this flag, function fails if file exists
+ Truncate = 1 << 1, // Truncate the file so an immediate close will empty it.
+ Create = 1 << 2,
+ Write = 1 << 3,
+ };
+ };
+
+ typedef NVFlags<FileOpenFlagValues::Enum, int> FileOpenFlags;
+
+ static inline FileOpenFlags FileReadFlags() { return FileOpenFlags(FileOpenFlagValues::Open); }
+
+ static inline FileOpenFlags FileWriteFlags()
+ {
+ return FileOpenFlags(FileOpenFlagValues::Create | FileOpenFlagValues::Open
+ | FileOpenFlagValues::Write | FileOpenFlagValues::Truncate);
+ }
+ static inline FileOpenFlags FileAppendFlags()
+ {
+ return FileOpenFlags(FileOpenFlagValues::Create | FileOpenFlagValues::Open
+ | FileOpenFlagValues::Write);
+ }
+
+ class CFileSeekableIOStream : public ISeekableIOStream
+ {
+ protected:
+ QFile m_File;
+
+ public:
+ // Enabling append also enables reading from the file while being able to
+ // write to it.
+ CFileSeekableIOStream(const char *inFile, FileOpenFlags inFlags);
+#ifdef WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+ CFileSeekableIOStream(const wchar_t *inFile, FileOpenFlags inFlags);
+#endif
+
+ CFileSeekableIOStream(const char16_t *inFile, FileOpenFlags inFlags);
+ CFileSeekableIOStream(const QString &inFIle, FileOpenFlags inFlags);
+ virtual ~CFileSeekableIOStream();
+ virtual bool IsOpen();
+ void SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inEnum) override;
+ QT3DSI64 GetPosition() const override;
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override;
+ bool Write(NVConstDataRef<QT3DSU8> data) override;
+
+ private:
+ void openFile(const QString &path, FileOpenFlags inFlags);
+ };
+
+ class CMemorySeekableIOStream : public ISeekableIOStream
+ {
+ protected:
+ NVAllocatorCallback &m_Allocator;
+ const char *m_AllocationName;
+ QT3DSU8 *m_Data;
+ QT3DSU32 m_Size;
+ QT3DSU32 m_Offset;
+ QT3DSU32 m_Capacity;
+
+ public:
+ CMemorySeekableIOStream(NVAllocatorCallback &inAlloc, const char *inAllocName);
+ virtual ~CMemorySeekableIOStream();
+ void SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inEnum) override;
+ QT3DSI64 GetPosition() const override { return m_Offset; }
+ QT3DSI64 GetLength() const override { return m_Size; }
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override;
+ bool Write(NVConstDataRef<QT3DSU8> data) override;
+
+ // Add in the standard container functions
+ QT3DSU8 *begin() { return m_Data; }
+ QT3DSU8 *end() { return m_Data + m_Size; }
+ const QT3DSU8 *begin() const { return m_Data; }
+ const QT3DSU8 *end() const { return m_Data + m_Size; }
+ void clear()
+ {
+ m_Offset = 0;
+ m_Size = 0;
+ }
+ QT3DSU32 size() const { return m_Size; }
+ void reserve(QT3DSU32 inNewSize);
+ void resize(QT3DSU32 inNewSize)
+ {
+ reserve(inNewSize);
+ m_Size = inNewSize;
+ }
+ };
+
+ // Simple, one way input stream.
+ struct SMemoryInStream : public IInStream
+ {
+ const QT3DSU8 *m_Begin;
+ const QT3DSU8 *m_End;
+ SMemoryInStream(const QT3DSU8 *b, const QT3DSU8 *e)
+ : m_Begin(b)
+ , m_End(e)
+ {
+ }
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ size_t available = m_End - m_Begin;
+ size_t requested = data.size();
+ size_t amount = NVMin(available, requested);
+ qt3ds::intrinsics::memCopy(data.mData, m_Begin, (QT3DSU32)amount);
+ m_Begin += amount;
+ return (QT3DSU32)amount;
+ }
+ };
+
+ class WriteBufferedOutStream : public IOutStream, public NVRefCounted
+ {
+ public:
+ virtual IOutStream &wrappedStream() = 0;
+ virtual void flush() = 0;
+
+ static NVScopedRefCounted<WriteBufferedOutStream>
+ Create(NVFoundationBase &fnd, IOutStream &stream, QT3DSU32 totalBufferSize = 128 * 1024);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/LICENSE_CONVERTUTF.TXT b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/LICENSE_CONVERTUTF.TXT
new file mode 100644
index 00000000..254acdfe
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/LICENSE_CONVERTUTF.TXT
@@ -0,0 +1,19 @@
+Copyright 2001-2004 Unicode, Inc.
+
+Disclaimer
+
+This source code is provided as is by Unicode, Inc. No claims are
+made as to fitness for any particular purpose. No warranties of any
+kind are expressed or implied. The recipient agrees to determine
+applicability of information provided. If this file has been
+purchased on magnetic or optical media from Unicode, Inc., the
+sole remedy for any claim will be exchange of defective media
+within 90 days of receipt.
+
+Limitations on Rights to Redistribute This Code
+
+Unicode, Inc. hereby grants the right to freely use the information
+supplied in this file in the creation of products supporting the
+Unicode Standard, and to make copies of this file in any form
+for internal or external distribution as long as this notice
+remains attached.
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/PoolingAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/PoolingAllocator.h
new file mode 100644
index 00000000..9d939fdc
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/PoolingAllocator.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_FOUNDATION_POOLING_ALLOCATOR_H
+#define QT3DS_FOUNDATION_POOLING_ALLOCATOR_H
+#pragma once
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "foundation/Qt3DSMutex.h"
+
+// Pooling allocator. Not designed for small allocations
+// starting at 64 bytes and up to 4 K, allocator uses pools.
+// Above that, uses default allocator. THis object is absolutely not threadsafe.
+// This addes 8 bytes to each allocation in order to safely track the allocation size.
+// There is no strict requirement to deallocate; this allocator automatically deallocates
+// anything allocated through it.
+namespace qt3ds {
+namespace foundation {
+ struct SPoolingAllocator : public NVAllocatorCallback
+ {
+ typedef Mutex TMutexType;
+ typedef Mutex::ScopedLock TLockType;
+
+ NVAllocatorCallback &m_Allocator;
+ TMutexType m_Mutex;
+
+ struct SAllocationTag
+ {
+ QT3DSU32 m_Tag;
+ size_t m_Size;
+ SAllocationTag(size_t inSize = 0)
+ : m_Tag(0xAB5534CD)
+ , m_Size(inSize)
+ {
+ }
+ };
+
+ template <size_t TObjSize>
+ struct SPoolObj
+ {
+ QT3DSU32 m_Buffer[TObjSize / 4];
+ SPoolObj() {}
+ };
+#define ITERATE_POOLING_ALLOCATOR_POOL_SIZES \
+ HANDLE_POOLING_ALLOCATOR_POOL_SIZE(64) \
+ HANDLE_POOLING_ALLOCATOR_POOL_SIZE(128) \
+ HANDLE_POOLING_ALLOCATOR_POOL_SIZE(256) \
+ HANDLE_POOLING_ALLOCATOR_POOL_SIZE(512) \
+ HANDLE_POOLING_ALLOCATOR_POOL_SIZE(1024)
+
+#define HANDLE_POOLING_ALLOCATOR_POOL_SIZE(sz) \
+ Pool<SPoolObj<sz>, ForwardingAllocator, 4> m_Pool##sz;
+ ITERATE_POOLING_ALLOCATOR_POOL_SIZES
+#undef HANDLE_POOLING_ALLOCATOR_POOL_SIZE
+
+ SSAutoDeallocatorAllocator m_LargeAllocator;
+
+#define HANDLE_POOLING_ALLOCATOR_POOL_SIZE(sz) \
+ , m_Pool##sz(ForwardingAllocator(inAllocator, "PoolingAllocatorPool"))
+
+ SPoolingAllocator(NVAllocatorCallback &inAllocator)
+ : m_Allocator(inAllocator)
+ , m_Mutex(inAllocator) ITERATE_POOLING_ALLOCATOR_POOL_SIZES
+ , m_LargeAllocator(inAllocator)
+ {
+ }
+#undef HANDLE_POOLING_ALLOCATOR_POOL_SIZE
+
+ void *doAllocateFromPool(size_t size)
+ {
+ TLockType locker(m_Mutex);
+
+#define HANDLE_POOLING_ALLOCATOR_POOL_SIZE(sz) \
+ if (size <= sz) \
+ return m_Pool##sz.allocate(__FILE__, __LINE__);
+ ITERATE_POOLING_ALLOCATOR_POOL_SIZES
+#undef HANDLE_POOLING_ALLOCATOR_POOL_SIZE
+
+ return m_LargeAllocator.allocate(size, "largetype", __FILE__, __LINE__, 0);
+ }
+
+ void *doAllocate(size_t size)
+ {
+ size += sizeof(SAllocationTag);
+ SAllocationTag *tag = reinterpret_cast<SAllocationTag *>(doAllocateFromPool(size));
+ new (tag) SAllocationTag(size);
+ QT3DSU8 *data = reinterpret_cast<QT3DSU8 *>(tag);
+ return data + sizeof(SAllocationTag);
+ }
+
+ void *allocate(size_t size, const char * /*typeName*/, const char * /*filename*/,
+ int /*line*/, int /*flags*/ = 0) override
+ {
+ return doAllocate(size);
+ }
+
+ void *allocate(size_t size, const char * /*typeName*/, const char * /*filename*/,
+ int /*line*/, size_t /*alignment*/, size_t /*alignmentOffset*/) override
+ {
+ return doAllocate(size);
+ }
+
+ /**
+ \brief Frees memory previously allocated by allocate().
+
+ <b>Threading:</b> This function should be thread safe as it can be called in the context of
+ the user thread
+ and physics processing thread(s).
+
+ \param ptr Memory to free.
+ */
+ void deallocate(void *ptr) override
+ {
+ TLockType locker(m_Mutex);
+
+ // Deallocate on null is fine.
+ if (ptr == NULL)
+ return;
+
+ SAllocationTag tempTag;
+ QT3DSU8 *dataPtr = reinterpret_cast<QT3DSU8 *>(ptr);
+ SAllocationTag *theTag =
+ reinterpret_cast<SAllocationTag *>(dataPtr - sizeof(SAllocationTag));
+ if (theTag->m_Tag != tempTag.m_Tag) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ size_t size = theTag->m_Size;
+
+ // We add this offset at allocation time
+ ptr = dataPtr - sizeof(SAllocationTag);
+
+#define HANDLE_POOLING_ALLOCATOR_POOL_SIZE(sz) \
+ if (size <= sz) { \
+ m_Pool##sz.deallocate(ptr); \
+ return; \
+ }
+ ITERATE_POOLING_ALLOCATOR_POOL_SIZES
+#undef HANDLE_POOLING_ALLOCATOR_POOL_SIZE
+ m_LargeAllocator.deallocate(ptr);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/PreAllocatedAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/PreAllocatedAllocator.h
new file mode 100644
index 00000000..aea03577
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/PreAllocatedAllocator.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_PRE_ALLOCATED_ALLOCATOR_H
+#define QT3DS_RENDER_PRE_ALLOCATED_ALLOCATOR_H
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ // Ignores deallocate calls if they originate withing the pre-allocation block
+ struct SPreAllocatedAllocator : public NVAllocatorCallback
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVDataRef<QT3DSU8> m_PreAllocatedBlock;
+ bool m_OwnsMemory; // then we attempt to deallocate on destruction
+
+ SPreAllocatedAllocator(NVAllocatorCallback &inAllocator)
+ : m_Allocator(inAllocator)
+ , m_OwnsMemory(false)
+ {
+ }
+
+ SPreAllocatedAllocator(NVAllocatorCallback &inAllocator, NVDataRef<QT3DSU8> inData,
+ bool inOwnsMemory)
+ : m_Allocator(inAllocator)
+ , m_PreAllocatedBlock(inData)
+ , m_OwnsMemory(inOwnsMemory)
+ {
+ }
+
+ virtual ~SPreAllocatedAllocator()
+ {
+ if (m_OwnsMemory)
+ m_Allocator.deallocate(m_PreAllocatedBlock.begin());
+ }
+
+ void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ int flags = 0) override
+ {
+ return m_Allocator.allocate(size, typeName, filename, line, flags);
+ }
+
+ void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ size_t alignment, size_t alignmentOffset) override
+ {
+ return m_Allocator.allocate(size, typeName, filename, line, alignment, alignmentOffset);
+ }
+
+ void deallocate(void *ptr) override
+ {
+ if (!ptr)
+ return;
+ if (ptr < m_PreAllocatedBlock.begin() || ptr >= m_PreAllocatedBlock.end())
+ m_Allocator.deallocate(ptr);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DS.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DS.h
new file mode 100644
index 00000000..041923c3
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DS.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_H
+#define QT3DS_H
+#include "EABase/eabase.h"
+#include "foundation/Qt3DSPreprocessor.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSAssert.h"
+
+namespace eastl {
+}
+
+namespace qt3ds {
+class NVEmpty
+{
+};
+class QT3DSMat33;
+class QT3DSMat44;
+class QT3DSVec2;
+class QT3DSVec3;
+class QT3DSVec4;
+class NVTransform;
+
+#if !defined QT3DS_DONT_PRAGMA_WARNINGS && defined EA_COMPILER_MSVC
+#pragma warning(disable : 4512) // assignment operator not generated
+#endif
+
+#define QT3DS_SIGN_BITMASK 0x80000000
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocator.h
new file mode 100644
index 00000000..cdbbe5f9
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocator.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSALLOCATOR_H
+#define QT3DS_FOUNDATION_PSALLOCATOR_H
+
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+
+#if (defined(QT3DS_WINDOWS) | defined(QT3DS_X360))
+#include <typeinfo.h>
+#endif
+#if (defined(QT3DS_APPLE))
+#include <typeinfo>
+#endif
+
+#include <new>
+
+// Allocation macros going through user allocator
+#define QT3DS_ALLOC(alloc, n, name) alloc.allocate(n, name, __FILE__, __LINE__)
+#define QT3DS_ALLOC_TEMP(alloc, n, name) QT3DS_ALLOC(n, name)
+#define QT3DS_FREE(alloc, x) alloc.deallocate(x)
+#define QT3DS_FREE_AND_RESET(x) \
+{ \
+ QT3DS_FREE(x); \
+ x = 0; \
+ }
+
+// The following macros support plain-old-types and classes derived from UserAllocated.
+#define QT3DS_NEW(alloc, T) new (QT3DS_ALLOC(alloc, sizeof(T), #T)) T
+#define QT3DS_NEW_TEMP(alloc, T) QT3DS_NEW(alloc, T)
+#define QT3DS_DELETE_POD(x) \
+{ \
+ QT3DS_FREE(x); \
+ x = 0; \
+ }
+
+namespace qt3ds {
+namespace foundation {
+template <typename TObjType>
+inline void NVDelete(NVAllocatorCallback &alloc, TObjType *item)
+{
+ if (item) {
+ item->~TObjType();
+ alloc.deallocate(item);
+ }
+}
+}
+}
+
+//! placement new macro to make it easy to spot bad use of 'new'
+#define QT3DS_PLACEMENT_NEW(p, T) new (p) T
+
+// Don't use inline for alloca !!!
+#ifdef QT3DS_WINDOWS
+#include <malloc.h>
+#define NVAlloca(x) _alloca(x)
+#elif defined(QT3DS_LINUX) || defined(QT3DS_ANDROID) || defined(QT3DS_QNX)
+#if defined(__INTEGRITY)
+#include <alloca.h>
+#else
+#include <malloc.h>
+#endif
+#define NVAlloca(x) alloca(x)
+#elif defined(QT3DS_PSP2)
+#include <alloca.h>
+#define NVAlloca(x) alloca(x)
+#elif defined(QT3DS_APPLE)
+#include <stdlib.h>
+#include <alloca.h>
+#define NVAlloca(x) alloca(x)
+#elif defined(QT3DS_PS3)
+#include <alloca.h>
+#define NVAlloca(x) alloca(x)
+#elif defined(QT3DS_X360)
+#include <malloc.h>
+#define NVAlloca(x) _alloca(x)
+#elif defined(QT3DS_WII)
+#include <alloca.h>
+#define NVAlloca(x) alloca(x)
+#endif
+
+namespace qt3ds {
+namespace foundation {
+/*
+ * Bootstrap allocator using malloc/free.
+ * Don't use unless your objects get allocated before foundation is initialized.
+ */
+class RawAllocator
+{
+public:
+ RawAllocator(const char * = 0) {}
+ void *allocate(size_t size, const char *, int)
+ {
+#if defined(QT3DS_APPLE)
+ // malloc returns valid pointer for size==0, no need to check
+ return malloc(size);
+#else
+ // malloc returns valid pointer for size==0, no need to check
+ return ::malloc(size);
+#endif
+ }
+ void deallocate(void *ptr)
+ {
+#if defined(QT3DS_APPLE)
+ free(ptr);
+#else
+ // free(0) is guaranteed to have no side effect, no need to check
+ ::free(ptr);
+#endif
+ }
+};
+
+struct ForwardingAllocator
+{
+ NVAllocatorCallback *mAllocator;
+ const char *mTypeName;
+ ForwardingAllocator(const char *typeName)
+ : mTypeName(typeName)
+ {
+ }
+ ForwardingAllocator(NVAllocatorCallback &alloc, const char *typeName)
+ : mAllocator(&alloc)
+ , mTypeName(typeName)
+ {
+ }
+ ForwardingAllocator(NVAllocatorCallback *alloc = NULL)
+ : mAllocator(alloc)
+ , mTypeName("__error__")
+ {
+ QT3DS_ASSERT(false);
+ }
+ ForwardingAllocator(const ForwardingAllocator &other)
+ : mAllocator(other.mAllocator)
+ , mTypeName(other.mTypeName)
+ {
+ }
+ ForwardingAllocator &operator=(const ForwardingAllocator &other)
+ {
+ mAllocator = other.mAllocator;
+ mTypeName = other.mTypeName;
+ return *this;
+ }
+ bool operator==(const ForwardingAllocator &other) const
+ {
+ return mAllocator == other.mAllocator;
+ }
+ NVAllocatorCallback &getAllocator() { return *mAllocator; }
+ // flags are unused
+ void *allocate(size_t size, const char *filename, int line, int flags = 0)
+ {
+ return getAllocator().allocate(size, mTypeName, filename, line, flags);
+ }
+ void *allocate(size_t size, const char *filename, int line, size_t alignment,
+ size_t alignmentOffset)
+ {
+ return getAllocator().allocate(size, mTypeName, filename, line, alignment,
+ alignmentOffset);
+ }
+ void deallocate(void *ptr, size_t) { getAllocator().deallocate(ptr); }
+ void deallocate(void *ptr) { getAllocator().deallocate(ptr); }
+};
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocatorCallback.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocatorCallback.h
new file mode 100644
index 00000000..ebbf8198
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAllocatorCallback.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_ALLOCATOR_CALLBACK_H
+#define QT3DS_FOUNDATION_QT3DS_ALLOCATOR_CALLBACK_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DS.h"
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/**
+\brief Abstract base class for an application defined memory allocator that can be used by the NV
+library.
+
+\note The SDK state should not be modified from within any allocation/free function.
+
+<b>Threading:</b> All methods of this class should be thread safe as it can be called from the user
+thread
+or the physics processing thread(s).
+*/
+
+class NVAllocatorCallback
+{
+public:
+ /**
+ \brief destructor
+ */
+ virtual ~NVAllocatorCallback() {}
+
+ /**
+ \brief Allocates size bytes of memory, which must be 16-byte aligned.
+
+ This method should never return NULL. If you run out of memory, then
+ you should terminate the app or take some other appropriate action.
+
+ <b>Threading:</b> This function should be thread safe as it can be called in the context of the
+ user thread
+ and physics processing thread(s).
+
+ \param size Number of bytes to allocate.
+ \param typeName Name of the datatype that is being allocated
+ \param filename The source file which allocated the memory
+ \param line The source line which allocated the memory
+ \return The allocated block of memory.
+ */
+ virtual void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ int flags = 0) = 0;
+ virtual void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ size_t alignment, size_t alignmentOffset) = 0;
+
+ /**
+ \brief Frees memory previously allocated by allocate().
+
+ <b>Threading:</b> This function should be thread safe as it can be called in the context of the
+ user thread
+ and physics processing thread(s).
+
+ \param ptr Memory to free.
+ */
+ virtual void deallocate(void *ptr) = 0;
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAssert.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAssert.h
new file mode 100644
index 00000000..09b52c1c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAssert.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_ASSERT_H
+#define QT3DS_ASSERT_H
+#include "EABase/eabase.h"
+#include "EABase/config/eacompiler.h"
+#include "EABase/config/eacompilertraits.h"
+#include "EABase/config/eaplatform.h"
+#include "foundation/Qt3DSPreprocessor.h"
+
+#ifdef EA_PLATFORM_WINDOWS
+
+#include <stdio.h>
+#include <crtdbg.h>
+
+extern void __debugbreak();
+#ifndef QT3DS_DOXYGEN
+
+namespace qt3ds {
+#endif
+QT3DS_INLINE void NVAssert(const char *exp, const char *file, int line, bool *ignore)
+{
+// printf("Assertion failed: %s, file %s, line %d\n", exp, file, line);
+#ifdef _DEBUG
+ if (ignore != NULL) {
+ int reportType = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_REPORT_MODE);
+ // PH: _CrtDbgReport returns -1 on error, 0 on 'ignore', 1 on 'retry'. Hitting 'abort' will
+ // terminate the process immediately.
+ // If the mode is not 'Window', we just always break.
+ *ignore = *ignore || ((reportType == _CRTDBG_MODE_WNDW)
+ && (_CrtDbgReport(_CRT_ASSERT, file, line, NULL, "%s", exp) == 0));
+ }
+
+ if (ignore == NULL || !*ignore)
+#else
+ QT3DS_FORCE_PARAMETER_REFERENCE(exp);
+ QT3DS_FORCE_PARAMETER_REFERENCE(file);
+ QT3DS_FORCE_PARAMETER_REFERENCE(line);
+ QT3DS_FORCE_PARAMETER_REFERENCE(ignore);
+#endif
+ __debugbreak();
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+#ifdef __CUDACC__
+#define QT3DS_ASSERT(exp) ((void)0)
+#define QT3DS_ALWAYS_ASSERT_MESSAGE(exp) ((void)0)
+#else
+#ifndef NDEBUG
+#define QT3DS_ASSERT(exp) \
+ { \
+ static bool ignore = false; \
+ (void)((!!(exp)) || (qt3ds::NVAssert(#exp, __FILE__, __LINE__, &ignore), false)); \
+ }
+#define QT3DS_ALWAYS_ASSERT_MESSAGE(exp) \
+ { \
+ static bool ignore = false; \
+ (void)((qt3ds::NVAssert(#exp, __FILE__, __LINE__, &ignore), false)); \
+ }
+#else
+#define QT3DS_ASSERT(exp) ((void)0)
+#define QT3DS_ALWAYS_ASSERT_MESSAGE(exp) ((void)0)
+#endif
+#endif
+
+#elif defined(QT3DS_PS3)
+#include "foundation/ps3/NVPS3Assert.h"
+
+#else // Force the user to define the NVAssert function
+namespace qt3ds {
+void NVAssert(const char *exp, const char *file, int line, bool *ignore);
+}
+#ifdef __CUDACC__
+#define QT3DS_ASSERT(exp) ((void)0)
+#define QT3DS_ALWAYS_ASSERT_MESSAGE(exp) ((void)0)
+#else
+#ifndef NDEBUG
+#define QT3DS_ASSERT(exp) \
+ { \
+ static bool ignore = false; \
+ (void)((!!(exp)) || (qt3ds::NVAssert(#exp, __FILE__, __LINE__, &ignore), false)); \
+ }
+#define QT3DS_ALWAYS_ASSERT_MESSAGE(exp) \
+ { \
+ static bool ignore = false; \
+ (void)((qt3ds::NVAssert(#exp, __FILE__, __LINE__, &ignore), false)); \
+ }
+#else
+#define QT3DS_ASSERT(exp) ((void)0)
+#define QT3DS_ALWAYS_ASSERT_MESSAGE(exp) ((void)0)
+#endif
+#endif
+#endif
+
+#define QT3DS_ALWAYS_ASSERT() QT3DS_ASSERT(0)
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAtomic.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAtomic.h
new file mode 100644
index 00000000..b0f7fe53
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSAtomic.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSATOMIC_H
+#define QT3DS_FOUNDATION_PSATOMIC_H
+
+#include "foundation/Qt3DS.h"
+
+namespace qt3ds {
+namespace foundation {
+ /* set *dest equal to val. Return the old value of *dest */
+ QT3DS_FOUNDATION_API QT3DSI32 atomicExchange(volatile QT3DSI32 *dest, QT3DSI32 val);
+
+ /* if *dest == comp, replace with exch. Return original value of *dest */
+ QT3DS_FOUNDATION_API QT3DSI32 atomicCompareExchange(volatile QT3DSI32 *dest, QT3DSI32 exch, QT3DSI32 comp);
+
+ /* if *dest == comp, replace with exch. Return original value of *dest */
+ QT3DS_FOUNDATION_API void *atomicCompareExchangePointer(volatile void **dest, void *exch,
+ void *comp);
+
+ /* increment the specified location. Return the incremented value */
+ QT3DS_FOUNDATION_API QT3DSI32 atomicIncrement(volatile QT3DSI32 *val);
+
+ /* decrement the specified location. Return the decremented value */
+ QT3DS_FOUNDATION_API QT3DSI32 atomicDecrement(volatile QT3DSI32 *val);
+
+ /* add delta to *val. Return the new value */
+ QT3DS_FOUNDATION_API QT3DSI32 atomicAdd(volatile QT3DSI32 *val, QT3DSI32 delta);
+
+ /* compute the maximum of dest and val. Return the new value */
+ QT3DS_FOUNDATION_API QT3DSI32 atomicMax(volatile QT3DSI32 *val, QT3DSI32 val2);
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBasicTemplates.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBasicTemplates.h
new file mode 100644
index 00000000..f14c7b32
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBasicTemplates.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSBASICTEMPLATES_H
+#define QT3DS_FOUNDATION_PSBASICTEMPLATES_H
+
+#include "foundation/Qt3DS.h"
+
+namespace qt3ds {
+namespace foundation {
+ template <typename A>
+ struct Equal
+ {
+ bool operator()(const A &a, const A &b) const { return a == b; }
+ };
+
+ template <typename A>
+ struct Less
+ {
+ bool operator()(const A &a, const A &b) const { return a < b; }
+ };
+
+ template <typename A>
+ struct Greater
+ {
+ bool operator()(const A &a, const A &b) const { return a > b; }
+ };
+
+ template <class F, class S>
+ class Pair
+ {
+ public:
+ F first;
+ S second;
+ Pair()
+ : first(F())
+ , second(S())
+ {
+ }
+ Pair(const F &f, const S &s)
+ : first(f)
+ , second(s)
+ {
+ }
+ Pair(const Pair &p)
+ : first(p.first)
+ , second(p.second)
+ {
+ }
+ // CN - fix for /.../Qt3DSBasicTemplates.h(61) : warning C4512: 'nv::foundation::Pair<F,S>' :
+ // assignment operator could not be generated
+ Pair &operator=(const Pair &p)
+ {
+ first = p.first;
+ second = p.second;
+ return *this;
+ }
+ bool operator==(const Pair &p) const { return first == p.first && second == p.second; }
+ };
+
+ template <unsigned int A>
+ struct LogTwo
+ {
+ static const unsigned int value = LogTwo<(A >> 1)>::value + 1;
+ };
+ template <>
+ struct LogTwo<1>
+ {
+ static const unsigned int value = 0;
+ };
+
+ template <typename T>
+ struct UnConst
+ {
+ typedef T Type;
+ };
+ template <typename T>
+ struct UnConst<const T>
+ {
+ typedef T Type;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBounds3.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBounds3.h
new file mode 100644
index 00000000..fda4a6d4
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBounds3.h
@@ -0,0 +1,443 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_BOUNDS3_H
+#define QT3DS_FOUNDATION_QT3DS_BOUNDS3_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSTransform.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DSMat44.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+typedef QT3DSVec3 TNVBounds2BoxPoints[8];
+
+/**
+\brief Class representing 3D range or axis aligned bounding box.
+
+Stored as minimum and maximum extent corners. Alternate representation
+would be center and dimensions.
+May be empty or nonempty. If not empty, minimum <= maximum has to hold.
+*/
+class NVBounds3
+{
+public:
+ /**
+ \brief Default constructor, not performing any initialization for performance reason.
+ \remark Use empty() function below to construct empty bounds.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3() {}
+
+ /**
+ \brief Construct from two bounding points
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3(const QT3DSVec3 &minimum, const QT3DSVec3 &maximum);
+
+ /**
+ \brief Return empty bounds.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 empty();
+
+ /**
+ \brief returns the AABB containing v0 and v1.
+ \param v0 first point included in the AABB.
+ \param v1 second point included in the AABB.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 boundsOfPoints(const QT3DSVec3 &v0,
+ const QT3DSVec3 &v1);
+
+ /**
+ \brief returns the AABB from center and extents vectors.
+ \param center Center vector
+ \param extent Extents vector
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 centerExtents(const QT3DSVec3 &center,
+ const QT3DSVec3 &extent);
+
+ /**
+ \brief Construct from center, extent, and (not necessarily orthogonal) basis
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 basisExtent(const QT3DSVec3 &center,
+ const QT3DSMat33 &basis,
+ const QT3DSVec3 &extent);
+
+ /**
+ \brief Construct from pose and extent
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 poseExtent(const NVTransform &pose,
+ const QT3DSVec3 &extent);
+
+ /**
+ \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
+ \param[in] matrix Transform to apply, can contain scaling as well
+ \param[in] bounds The bounds to transform.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 transform(const QT3DSMat33 &matrix,
+ const NVBounds3 &bounds);
+
+ /**
+ \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
+ \param[in] transform Transform to apply, can contain scaling as well
+ \param[in] bounds The bounds to transform.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 transform(const NVTransform &transform,
+ const NVBounds3 &bounds);
+
+ /**
+ \brief Sets empty to true
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void setEmpty();
+
+ /**
+ \brief Sets infinite bounds
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void setInfinite();
+
+ /**
+ \brief expands the volume to include v
+ \param v Point to expand to.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void include(const QT3DSVec3 &v);
+
+ /**
+ \brief expands the volume to include b.
+ \param b Bounds to perform union with.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void include(const NVBounds3 &b);
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isEmpty() const;
+
+ /**
+ \brief indicates whether the intersection of this and b is empty or not.
+ \param b Bounds to test for intersection.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool intersects(const NVBounds3 &b) const;
+
+ /**
+ \brief computes the 1D-intersection between two AABBs, on a given axis.
+ \param a the other AABB
+ \param axis the axis (0, 1, 2)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool intersects1D(const NVBounds3 &a, QT3DSU32 axis) const;
+
+ /**
+ \brief indicates if these bounds contain v.
+ \param v Point to test against bounds.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool contains(const QT3DSVec3 &v) const;
+
+ /**
+ \brief checks a box is inside another box.
+ \param box the other AABB
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isInside(const NVBounds3 &box) const;
+
+ /**
+ \brief returns the center of this axis aligned box.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getCenter() const;
+
+ /**
+ \brief get component of the box's center along a given axis
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float getCenter(QT3DSU32 axis) const;
+
+ /**
+ \brief get component of the box's extents along a given axis
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float getExtents(QT3DSU32 axis) const;
+
+ /**
+ \brief returns the dimensions (width/height/depth) of this axis aligned box.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getDimensions() const;
+
+ /**
+ \brief returns the extents, which are half of the width/height/depth.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getExtents() const;
+
+ /**
+ \brief scales the AABB.
+ \param scale Factor to scale AABB by.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void scale(QT3DSF32 scale);
+
+ /**
+ fattens the AABB in all 3 dimensions by the given distance.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void fatten(NVReal distance);
+
+ /**
+ checks that the AABB values are not NaN
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite() const;
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void expand(TNVBounds2BoxPoints &outPoints) const;
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void transform(const QT3DSMat44 &inMatrix);
+
+ QT3DSVec3 minimum, maximum;
+};
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3::NVBounds3(const QT3DSVec3 &minimum, const QT3DSVec3 &maximum)
+ : minimum(minimum)
+ , maximum(maximum)
+{
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 NVBounds3::empty()
+{
+ return NVBounds3(QT3DSVec3(QT3DS_MAX_REAL), QT3DSVec3(-QT3DS_MAX_REAL));
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::isFinite() const
+{
+ return minimum.isFinite() && maximum.isFinite();
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 NVBounds3::boundsOfPoints(const QT3DSVec3 &v0,
+ const QT3DSVec3 &v1)
+{
+ return NVBounds3(v0.minimum(v1), v0.maximum(v1));
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 NVBounds3::centerExtents(const QT3DSVec3 &center,
+ const QT3DSVec3 &extent)
+{
+ return NVBounds3(center - extent, center + extent);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::basisExtent(const QT3DSVec3 &center,
+ const QT3DSMat33 &basis,
+ const QT3DSVec3 &extent)
+{
+ // extended basis vectors
+ QT3DSVec3 c0 = basis.column0 * extent.x;
+ QT3DSVec3 c1 = basis.column1 * extent.y;
+ QT3DSVec3 c2 = basis.column2 * extent.z;
+
+ QT3DSVec3 w;
+ // find combination of base vectors that produces max. distance for each component = sum of
+ // abs()
+ w.x = NVAbs(c0.x) + NVAbs(c1.x) + NVAbs(c2.x);
+ w.y = NVAbs(c0.y) + NVAbs(c1.y) + NVAbs(c2.y);
+ w.z = NVAbs(c0.z) + NVAbs(c1.z) + NVAbs(c2.z);
+
+ return NVBounds3(center - w, center + w);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::poseExtent(const NVTransform &pose,
+ const QT3DSVec3 &extent)
+{
+ return basisExtent(pose.p, QT3DSMat33(pose.q), extent);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::setEmpty()
+{
+ minimum = QT3DSVec3(QT3DS_MAX_REAL);
+ maximum = QT3DSVec3(-QT3DS_MAX_REAL);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::setInfinite()
+{
+ minimum = QT3DSVec3(-QT3DS_MAX_REAL);
+ maximum = QT3DSVec3(QT3DS_MAX_REAL);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::include(const QT3DSVec3 &v)
+{
+ QT3DS_ASSERT(isFinite());
+ minimum = minimum.minimum(v);
+ maximum = maximum.maximum(v);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::include(const NVBounds3 &b)
+{
+ QT3DS_ASSERT(isFinite());
+ minimum = minimum.minimum(b.minimum);
+ maximum = maximum.maximum(b.maximum);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::isEmpty() const
+{
+ QT3DS_ASSERT(isFinite());
+ // Consistency condition for (Min, Max) boxes: minimum < maximum
+ return minimum.x > maximum.x || minimum.y > maximum.y || minimum.z > maximum.z;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::intersects(const NVBounds3 &b) const
+{
+ QT3DS_ASSERT(isFinite() && b.isFinite());
+ return !(b.minimum.x > maximum.x || minimum.x > b.maximum.x || b.minimum.y > maximum.y
+ || minimum.y > b.maximum.y || b.minimum.z > maximum.z || minimum.z > b.maximum.z);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::intersects1D(const NVBounds3 &a, QT3DSU32 axis) const
+{
+ QT3DS_ASSERT(isFinite() && a.isFinite());
+ return maximum[axis] >= a.minimum[axis] && a.maximum[axis] >= minimum[axis];
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::contains(const QT3DSVec3 &v) const
+{
+ QT3DS_ASSERT(isFinite());
+
+ return !(v.x < minimum.x || v.x > maximum.x || v.y < minimum.y || v.y > maximum.y
+ || v.z < minimum.z || v.z > maximum.z);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::isInside(const NVBounds3 &box) const
+{
+ QT3DS_ASSERT(isFinite() && box.isFinite());
+ if (box.minimum.x > minimum.x)
+ return false;
+ if (box.minimum.y > minimum.y)
+ return false;
+ if (box.minimum.z > minimum.z)
+ return false;
+ if (box.maximum.x < maximum.x)
+ return false;
+ if (box.maximum.y < maximum.y)
+ return false;
+ if (box.maximum.z < maximum.z)
+ return false;
+ return true;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 NVBounds3::getCenter() const
+{
+ QT3DS_ASSERT(isFinite());
+ return (minimum + maximum) * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float NVBounds3::getCenter(QT3DSU32 axis) const
+{
+ QT3DS_ASSERT(isFinite());
+ return (minimum[axis] + maximum[axis]) * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float NVBounds3::getExtents(QT3DSU32 axis) const
+{
+ QT3DS_ASSERT(isFinite());
+ return (maximum[axis] - minimum[axis]) * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 NVBounds3::getDimensions() const
+{
+ QT3DS_ASSERT(isFinite());
+ return maximum - minimum;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 NVBounds3::getExtents() const
+{
+ QT3DS_ASSERT(isFinite());
+ return getDimensions() * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::scale(QT3DSF32 scale)
+{
+ QT3DS_ASSERT(isFinite());
+ *this = centerExtents(getCenter(), getExtents() * scale);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::fatten(NVReal distance)
+{
+ QT3DS_ASSERT(isFinite());
+ minimum.x -= distance;
+ minimum.y -= distance;
+ minimum.z -= distance;
+
+ maximum.x += distance;
+ maximum.y += distance;
+ maximum.z += distance;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::transform(const QT3DSMat33 &matrix,
+ const NVBounds3 &bounds)
+{
+ QT3DS_ASSERT(bounds.isFinite());
+ return bounds.isEmpty() ? bounds : NVBounds3::basisExtent(matrix * bounds.getCenter(), matrix,
+ bounds.getExtents());
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::transform(const NVTransform &transform,
+ const NVBounds3 &bounds)
+{
+ QT3DS_ASSERT(bounds.isFinite());
+ return bounds.isEmpty() ? bounds
+ : NVBounds3::basisExtent(transform.transform(bounds.getCenter()),
+ QT3DSMat33(transform.q), bounds.getExtents());
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::expand(TNVBounds2BoxPoints &outPoints) const
+{
+ if (isEmpty()) {
+ for (QT3DSU32 idx = 0; idx < 8; ++idx)
+ outPoints[idx] = QT3DSVec3(0, 0, 0);
+ } else {
+ // Min corner of box
+ outPoints[0] = QT3DSVec3(minimum[0], minimum[1], minimum[2]);
+ outPoints[1] = QT3DSVec3(maximum[0], minimum[1], minimum[2]);
+ outPoints[2] = QT3DSVec3(minimum[0], maximum[1], minimum[2]);
+ outPoints[3] = QT3DSVec3(minimum[0], minimum[1], maximum[2]);
+
+ // Max corner of box
+ outPoints[4] = QT3DSVec3(maximum[0], maximum[1], maximum[2]);
+ outPoints[5] = QT3DSVec3(minimum[0], maximum[1], maximum[2]);
+ outPoints[6] = QT3DSVec3(maximum[0], minimum[1], maximum[2]);
+ outPoints[7] = QT3DSVec3(maximum[0], maximum[1], minimum[2]);
+ }
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::transform(const QT3DSMat44 &inMatrix)
+{
+ if (!isEmpty()) {
+ TNVBounds2BoxPoints thePoints;
+ expand(thePoints);
+ setEmpty();
+ for (QT3DSU32 idx = 0; idx < 8; ++idx)
+ include(inMatrix.transform(thePoints[idx]));
+ }
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_BOUNDS3_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBroadcastingAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBroadcastingAllocator.h
new file mode 100644
index 00000000..dc6ae7b5
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSBroadcastingAllocator.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_BROADCASTING_ALLOCATOR_H
+#define QT3DS_FOUNDATION_QT3DS_BROADCASTING_ALLOCATOR_H
+
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+/** \addtogroup foundation
+ @{
+*/
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/**
+\brief Abstract listener class that listens to allocation and deallocation events from the
+ foundation memory system.
+
+<b>Threading:</b> All methods of this class should be thread safe as it can be called from the user
+thread
+or the physics processing thread(s).
+*/
+class NVAllocationListener
+{
+protected:
+ virtual ~NVAllocationListener() {}
+
+public:
+ /**
+ \brief callback when memory is allocated.
+ \param size Size of the allocation in bytes.
+ \param typeName Type this data is being allocated for.
+ \param filename File the allocation came from.
+ \param line the allocation came from.
+ \param allocatedMemory memory that will be returned from the allocation.
+ */
+ virtual void onAllocation(size_t size, const char *typeName, const char *filename, int line,
+ void *allocatedMemory) = 0;
+
+ /**
+ /brief callback when memory is deallocated.
+ /param allocatedMemory memory just before allocation.
+ */
+ virtual void onDeallocation(void *allocatedMemory) = 0;
+};
+
+/**
+\brief Abstract base class for an application defined memory allocator that allows an external
+listener
+to audit the memory allocations.
+
+<b>Threading:</b> Register/deregister are *not* threadsafe!!!
+You need to be sure multiple threads are using this allocator when you are adding
+new listeners.
+*/
+class NVBroadcastingAllocator : public NVAllocatorCallback
+{
+protected:
+ virtual ~NVBroadcastingAllocator() {}
+
+public:
+ /**
+ \brief Register an allocation listener. This object will be notified whenever an
+ allocation happens.
+
+ <b>Threading:</b>Not threadsafe if you are allocating and deallocating in another
+ thread using this allocator.
+ */
+ virtual void registerAllocationListener(NVAllocationListener &inListener) = 0;
+ /**
+ \brief Deregister an allocation listener. This object will no longer receive
+ notifications upon allocation.
+
+ <b>Threading:</b>Not threadsafe if you are allocating and deallocating in another
+ thread using this allocator.
+ */
+ virtual void deregisterAllocationListener(NVAllocationListener &inListener) = 0;
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_BROADCASTING_ALLOCATOR_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSContainers.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSContainers.h
new file mode 100644
index 00000000..de86d856
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSContainers.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef QT3DS_CONTAINERS_H
+#define QT3DS_CONTAINERS_H
+#include "foundation/Qt3DS.h"
+#include "EASTL/vector.h"
+#include "EASTL/hash_map.h"
+#include "EASTL/hash_set.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename T>
+ class nvvector : public eastl::vector<T, ForwardingAllocator>
+ {
+ typedef eastl::vector<T, ForwardingAllocator> base_type;
+
+ public:
+ using base_type::data;
+ using base_type::size;
+
+ nvvector(NVAllocatorCallback &inAllocator, const char *inTypeName)
+ : eastl::vector<T, ForwardingAllocator>(ForwardingAllocator(inAllocator, inTypeName))
+ {
+ }
+ nvvector(const nvvector<T> &inOther)
+ : eastl::vector<T, ForwardingAllocator>(inOther)
+ {
+ }
+ nvvector<T> &operator=(const nvvector<T> &inOther)
+ {
+ eastl::vector<T, ForwardingAllocator>::operator=(inOther);
+ return *this;
+ }
+ operator NVConstDataRef<T>() const { return NVConstDataRef<T>(data(), size()); }
+ operator NVDataRef<T>() { return NVDataRef<T>(data(), size()); }
+ };
+
+ template <typename TKey, typename TValue, typename THash = eastl::hash<TKey>,
+ typename TPredicate = eastl::equal_to<TKey>>
+ class nvhash_map : public eastl::hash_map<TKey, TValue, THash, TPredicate, ForwardingAllocator>
+ {
+ typedef eastl::hash_map<TKey, TValue, THash, TPredicate, ForwardingAllocator> base_type;
+
+ public:
+ using base_type::find;
+ using base_type::end;
+
+ nvhash_map(NVAllocatorCallback &inAllocator, const char *inTypeName)
+ : eastl::hash_map<TKey, TValue, THash, TPredicate, ForwardingAllocator>(
+ ForwardingAllocator(inAllocator, inTypeName))
+ {
+ }
+ nvhash_map(const nvhash_map<TKey, TValue, THash, TPredicate> &inOther)
+ : eastl::hash_map<TKey, TValue, THash, TPredicate, ForwardingAllocator>(inOther)
+ {
+ }
+ nvhash_map<TKey, TValue, THash, TPredicate> &
+ operator=(const nvhash_map<TKey, TValue, THash, TPredicate> &inOther)
+ {
+ eastl::hash_map<TKey, TValue, THash, TPredicate, ForwardingAllocator>::operator=(
+ inOther);
+ return *this;
+ }
+ bool contains(const TKey &inKey) const { return find(inKey) != end(); }
+ };
+
+ template <typename TKey, typename THash = eastl::hash<TKey>,
+ typename TPredicate = eastl::equal_to<TKey>>
+ class nvhash_set : public eastl::hash_set<TKey, THash, TPredicate, ForwardingAllocator>
+ {
+ typedef eastl::hash_set<TKey, THash, TPredicate, ForwardingAllocator> base_type;
+
+ public:
+ using base_type::find;
+ using base_type::end;
+
+ nvhash_set(NVAllocatorCallback &inAllocator, const char *inTypeName)
+ : eastl::hash_set<TKey, THash, TPredicate, ForwardingAllocator>(
+ ForwardingAllocator(inAllocator, inTypeName))
+ {
+ }
+ nvhash_set(const nvhash_map<TKey, THash, TPredicate> &inOther)
+ : eastl::hash_set<TKey, THash, TPredicate, ForwardingAllocator>(inOther)
+ {
+ }
+ nvhash_set<TKey, THash, TPredicate> &
+ operator=(const nvhash_set<TKey, THash, TPredicate> &inOther)
+ {
+ eastl::hash_set<TKey, THash, TPredicate, ForwardingAllocator>::operator=(inOther);
+ return *this;
+ }
+ bool contains(const TKey &inKey) const { return find(inKey) != end(); }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDataRef.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDataRef.h
new file mode 100644
index 00000000..ad860cef
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDataRef.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_DATA_REF_H
+#define QT3DS_FOUNDATION_DATA_REF_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename TDataType>
+ struct NVConstDataRef
+ {
+ const TDataType *mData;
+ QT3DSU32 mSize;
+
+ NVConstDataRef(const TDataType *inData, QT3DSU32 inSize)
+ : mData(inData)
+ , mSize(inSize)
+ {
+ }
+ NVConstDataRef()
+ : mData(0)
+ , mSize(0)
+ {
+ }
+
+ QT3DSU32 size() const { return mSize; }
+
+ const TDataType *begin() const { return mData; }
+ const TDataType *end() const { return mData + mSize; }
+
+ const TDataType &operator[](QT3DSU32 index) const
+ {
+ QT3DS_ASSERT(index < mSize);
+ return mData[index];
+ }
+ };
+
+ template <typename TDataType>
+ inline NVConstDataRef<TDataType> toConstDataRef(const TDataType &type)
+ {
+ return NVConstDataRef<TDataType>(&type, 1);
+ }
+
+ template <typename TDataType>
+ inline NVConstDataRef<QT3DSU8> toU8ConstDataRef(const TDataType &type)
+ {
+ return NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(&type), sizeof(TDataType));
+ }
+
+ template <typename TDataType>
+ inline NVConstDataRef<TDataType> toConstDataRef(const TDataType *type, QT3DSU32 count)
+ {
+ return NVConstDataRef<TDataType>(type, count);
+ }
+
+ template <typename TDataType>
+ inline NVConstDataRef<QT3DSU8> toU8ConstDataRef(const TDataType *type, QT3DSU32 count)
+ {
+ return NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(type),
+ sizeof(TDataType) * count);
+ }
+
+ template <typename TDataType>
+ struct NVDataRef
+ {
+ TDataType *mData;
+ QT3DSU32 mSize;
+
+ NVDataRef(TDataType *inData, QT3DSU32 inSize)
+ : mData(inData)
+ , mSize(inSize)
+ {
+ }
+ NVDataRef()
+ : mData(0)
+ , mSize(0)
+ {
+ }
+ QT3DSU32 size() const { return mSize; }
+
+ TDataType *begin() { return mData; }
+ TDataType *end() { return mData + mSize; }
+
+ TDataType *begin() const { return mData; }
+ TDataType *end() const { return mData + mSize; }
+
+ TDataType &operator[](QT3DSU32 index)
+ {
+ QT3DS_ASSERT(index < mSize);
+ return mData[index];
+ }
+
+ const TDataType &operator[](QT3DSU32 index) const
+ {
+ QT3DS_ASSERT(index < mSize);
+ return mData[index];
+ }
+
+ operator NVConstDataRef<TDataType>() const
+ {
+ return NVConstDataRef<TDataType>(mData, mSize);
+ }
+ };
+
+ template <typename TDataType>
+ inline NVDataRef<TDataType> toDataRef(TDataType &type)
+ {
+ return NVDataRef<TDataType>(&type, 1);
+ }
+
+ template <typename TDataType>
+ inline NVDataRef<QT3DSU8> toU8DataRef(TDataType &type)
+ {
+ return NVDataRef<QT3DSU8>(reinterpret_cast<QT3DSU8 *>(&type), sizeof(TDataType));
+ }
+
+ template <typename TDataType>
+ inline NVDataRef<TDataType> toDataRef(TDataType *type, QT3DSU32 count)
+ {
+ return NVDataRef<TDataType>(type, count);
+ }
+
+ template <typename TDataType>
+ inline NVDataRef<QT3DSU8> toU8DataRef(TDataType *type, QT3DSU32 count)
+ {
+ return NVDataRef<QT3DSU8>(reinterpret_cast<QT3DSU8 *>(type), sizeof(TDataType) * count);
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDiscriminatedUnion.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDiscriminatedUnion.h
new file mode 100644
index 00000000..1957eb23
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSDiscriminatedUnion.h
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_DISCRIMINATED_UNION_H
+#define QT3DS_FOUNDATION_DISCRIMINATED_UNION_H
+#include "Qt3DSAssert.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSUnionCast.h"
+
+#ifdef WIN32
+#pragma warning(disable : 4100)
+#endif
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename TUnionTraits, int TBufferSize>
+ class DiscriminatedUnion
+ {
+ public:
+ typedef DiscriminatedUnion<TUnionTraits, TBufferSize> TThisType;
+ typedef TUnionTraits TTraits;
+ typedef typename TTraits::TIdType TIdType;
+
+ protected:
+ char m_Data[TBufferSize];
+ // Id type must include a no-data type.
+ TIdType m_DataType;
+
+ public:
+ DiscriminatedUnion() { TTraits::defaultConstruct(m_Data, m_DataType); }
+
+ DiscriminatedUnion(const TThisType &inOther)
+ : m_DataType(inOther.m_DataType)
+ {
+ TTraits::copyConstruct(m_Data, inOther.m_Data, m_DataType);
+ }
+
+ template <typename TDataType>
+ DiscriminatedUnion(const TDataType &inType)
+ {
+ TTraits::copyConstruct(m_Data, m_DataType, inType);
+ }
+
+ ~DiscriminatedUnion() { TTraits::destruct(m_Data, m_DataType); }
+
+ TThisType &operator=(const TThisType &inType)
+ {
+ if (this != &inType) {
+ TTraits::destruct(m_Data, m_DataType);
+ m_DataType = inType.m_DataType;
+ TTraits::copyConstruct(m_Data, inType.m_Data, inType.m_DataType);
+ }
+ return *this;
+ }
+
+ typename TTraits::TIdType getType() const { return m_DataType; }
+
+ template <typename TDataType>
+ const TDataType *getDataPtr() const
+ {
+ return TTraits::template getDataPtr<TDataType>(m_Data, m_DataType);
+ }
+
+ template <typename TDataType>
+ TDataType *getDataPtr()
+ {
+ return TTraits::template getDataPtr<TDataType>(m_Data, m_DataType);
+ }
+
+ template <typename TDataType>
+ TDataType getData() const
+ {
+ const TDataType *dataPtr = getDataPtr<TDataType>();
+ if (dataPtr)
+ return *dataPtr;
+ QT3DS_ASSERT(false);
+ return TDataType();
+ }
+
+ bool operator==(const TThisType &inOther) const
+ {
+ return m_DataType == inOther.m_DataType
+ && TTraits::areEqual(m_Data, inOther.m_Data, m_DataType);
+ }
+
+ bool operator!=(const TThisType &inOther) const
+ {
+ return m_DataType != inOther.m_DataType
+ || TTraits::areEqual(m_Data, inOther.m_Data, m_DataType) == false;
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ TRetType visit(TVisitorType inVisitor)
+ {
+ return TTraits::template visit<TRetType>(m_Data, m_DataType, inVisitor);
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ TRetType visit(TVisitorType inVisitor) const
+ {
+ return TTraits::template visit<TRetType>(m_Data, m_DataType, inVisitor);
+ }
+ };
+
+ // Helper system to enable quicker and correct construction of union traits types
+
+ struct CopyConstructVisitor
+ {
+ const char *m_Src;
+ CopyConstructVisitor(const char *inSrc)
+ : m_Src(inSrc)
+ {
+ }
+
+ template <typename TDataType>
+ void operator()(TDataType &inDst)
+ {
+ new (&inDst) TDataType(*NVUnionCast<const TDataType *>(m_Src));
+ }
+ void operator()() { QT3DS_ASSERT(false); }
+ };
+
+ template <typename TDataType>
+ struct DestructTraits
+ {
+ void destruct(TDataType &inType) { inType.~TDataType(); }
+ };
+
+ // Until compilers improve a bit, you need this for POD types else you get
+ // unused parameter warnings.
+ template <>
+ struct DestructTraits<QT3DSU8>
+ {
+ void destruct(QT3DSU8 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSI8>
+ {
+ void destruct(QT3DSI8 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSU16>
+ {
+ void destruct(QT3DSU16 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSI16>
+ {
+ void destruct(QT3DSI16 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSU32>
+ {
+ void destruct(QT3DSU32 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSI32>
+ {
+ void destruct(QT3DSI32 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSU64>
+ {
+ void destruct(QT3DSU64 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSI64>
+ {
+ void destruct(QT3DSI64 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSF32>
+ {
+ void destruct(QT3DSF32 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSF64>
+ {
+ void destruct(QT3DSF64 &) {}
+ };
+ template <>
+ struct DestructTraits<bool>
+ {
+ void destruct(bool &) {}
+ };
+ template <>
+ struct DestructTraits<void *>
+ {
+ void destruct(void *&) {}
+ };
+#ifdef __INTEGRITY
+ template <>
+ struct DestructTraits<QT3DSVec2>
+ {
+ void destruct(QT3DSVec2 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSVec3>
+ {
+ void destruct(QT3DSVec3 &) {}
+ };
+#endif
+
+ struct DestructVisitor
+ {
+ template <typename TDataType>
+ void operator()(TDataType &inDst)
+ {
+ DestructTraits<TDataType>().destruct(inDst);
+ }
+ void operator()() { QT3DS_ASSERT(false); }
+ };
+
+ template <typename TDataType>
+ struct EqualVisitorTraits
+ {
+ bool operator()(const TDataType &lhs, const TDataType &rhs) { return lhs == rhs; }
+ };
+
+ struct EqualVisitor
+ {
+ const char *m_Rhs;
+ EqualVisitor(const char *rhs)
+ : m_Rhs(rhs)
+ {
+ }
+ template <typename TDataType>
+ bool operator()(const TDataType &lhs)
+ {
+ const TDataType &rhs(*NVUnionCast<const TDataType *>(m_Rhs));
+ return EqualVisitorTraits<TDataType>()(lhs, rhs);
+ }
+ bool operator()()
+ {
+ QT3DS_ASSERT(false);
+ return true;
+ }
+ };
+
+ template <typename TBase, QT3DSU32 TBufferSize>
+ struct DiscriminatedUnionGenericBase : public TBase
+ {
+ typedef typename TBase::TIdType TIdType;
+
+ static void zeroBuf(char *outDst) { qt3ds::intrinsics::memZero(outDst, TBufferSize); }
+
+ static void defaultConstruct(char *outDst, TIdType &outType)
+ {
+ zeroBuf(outDst);
+ outType = TBase::getNoDataId();
+ }
+
+ template <typename TDataType>
+ static void copyConstruct(char *outDst, TIdType &outType, const TDataType &inSrc)
+ {
+ zeroBuf(outDst);
+ StaticAssert<sizeof(TDataType) <= TBufferSize>::valid_expression();
+ outType = TBase::template getType<TDataType>();
+ new (outDst) TDataType(inSrc);
+ }
+
+ static void copyConstruct(char *inDst, const char *inSrc, TIdType inType)
+ {
+ if (inType == TBase::getNoDataId())
+ zeroBuf(inDst);
+ else
+ TBase::template visit<void>(inDst, inType, CopyConstructVisitor(inSrc));
+ }
+
+ static void destruct(char *inDst, TIdType inType)
+ {
+ if (inType != TBase::getNoDataId())
+ TBase::template visit<void>(inDst, inType, DestructVisitor());
+ zeroBuf(inDst);
+ }
+
+ template <typename TDataType>
+ static const TDataType *getDataPtr(const char *inData, const TIdType &inType)
+ {
+ if (TBase::template getType<TDataType>() == inType)
+ return NVUnionCast<const TDataType *>(inData);
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ template <typename TDataType>
+ static TDataType *getDataPtr(char *inData, const TIdType &inType)
+ {
+ if (TBase::template getType<TDataType>() == inType)
+ return NVUnionCast<TDataType *>(inData);
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ static bool areEqual(const char *inLhs, const char *inRhs, TIdType inType)
+ {
+ if (inType != TBase::getNoDataId())
+ return TBase::template visit<bool>(inLhs, inType, EqualVisitor(inRhs));
+ else
+ return true;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFPU.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFPU.h
new file mode 100644
index 00000000..e4a47f0c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFPU.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSFPU_H
+#define QT3DS_FOUNDATION_PSFPU_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSUnionCast.h"
+
+// unsigned integer representation of a floating-point value.
+#ifdef QT3DS_PS3
+QT3DS_FORCE_INLINE unsigned int QT3DS_IR(const float x)
+{
+ return qt3ds::NVUnionCast<unsigned int, float>(x);
+}
+#else
+#define QT3DS_IR(x) ((QT3DSU32 &)(x))
+#endif
+
+// signed integer representation of a floating-point value.
+#ifdef QT3DS_PS3
+QT3DS_FORCE_INLINE int QT3DS_SIR(const float x)
+{
+ return qt3ds::NVUnionCast<int, float>(x);
+}
+#else
+#define QT3DS_SIR(x) ((QT3DSI32 &)(x))
+#endif
+
+// Floating-point representation of a integer value.
+#ifdef QT3DS_PS3
+QT3DS_FORCE_INLINE float QT3DS_FR(const unsigned int x)
+{
+ return qt3ds::NVUnionCast<float, unsigned int>(x);
+}
+#else
+#define QT3DS_FR(x) ((QT3DSF32 &)(x))
+#endif
+
+#ifdef QT3DS_PS3
+QT3DS_FORCE_INLINE float *QT3DS_FPTR(unsigned int *x)
+{
+ return qt3ds::NVUnionCast<float *, unsigned int *>(x);
+}
+
+QT3DS_FORCE_INLINE float *QT3DS_FPTR(int *x)
+{
+ return qt3ds::NVUnionCast<float *, int *>(x);
+}
+#else
+#define QT3DS_FPTR(x) ((QT3DSF32 *)(x))
+#endif
+
+#define QT3DS_SIGN_BITMASK 0x80000000
+
+namespace qt3ds {
+namespace foundation {
+class QT3DS_FOUNDATION_API FPUGuard
+{
+public:
+ FPUGuard(); // set fpu control word for PhysX
+ ~FPUGuard(); // restore fpu control word
+private:
+ QT3DSU32 mControlWords[8];
+};
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFastIPC.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFastIPC.h
new file mode 100644
index 00000000..800c3dfd
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFastIPC.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FAST_IPC_H
+#define QT3DS_FAST_IPC_H
+
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSIPC.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ NVIPC *createFastIPC(
+ NVIPC::ErrorCode &errorCode, // error code return if creation fails
+ NVIPC::ConnectionType connectionType =
+ NVIPC::CT_CLIENT_OR_SERVER, // how to establish the connection
+ const char *mappingObject = "Global\\FastIPC", // Name of communications channel
+ QT3DSU32 serverRingBufferSize = 1024 * 4, // buffer size for outgoing server messages.
+ QT3DSU32 clientRingBufferSize = 1024 * 4, // buffer size for incoming client messages.
+ bool allowLongMessages = true,
+ bool bufferSends = false,
+ QT3DSU32 maxBufferSendSize = 1024 * 8); // True if we want to buffer sends, if true, then
+ // pumpSendBuffers should be called by the send thread.
+
+ void releaseFastIPC(NVIPC *f);
+
+}; // end of namespace
+}; // end of namespace
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFlags.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFlags.h
new file mode 100644
index 00000000..765f386f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFlags.h
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_FLAGS_H
+#define QT3DS_FOUNDATION_QT3DS_FLAGS_H
+
+/** \addtogroup foundation
+ @{
+*/
+
+#include "foundation/Qt3DS.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+/**
+\brief Container for bitfield flag variables associated with a specific enum type.
+
+This allows for type safe manipulation for bitfields.
+
+<h3>Example</h3>
+ // enum that defines each bit...
+ struct MyEnum
+ {
+ enum Enum
+ {
+ eMAN = 1,
+ eBEAR = 2,
+ ePIG = 4,
+ };
+ };
+
+ // implements some convenient global operators.
+ QT3DS_FLAGS_OPERATORS(MyEnum::Enum, QT3DSU8);
+
+ NVFlags<MyEnum::Enum, QT3DSU8> myFlags;
+ myFlags |= MyEnum::eMAN;
+ myFlags |= MyEnum::eBEAR | MyEnum::ePIG;
+ if(myFlags & MyEnum::eBEAR)
+ {
+ doSomething();
+ }
+*/
+template <typename enumtype, typename storagetype = QT3DSU32>
+class NVFlags
+{
+public:
+ QT3DS_INLINE explicit NVFlags(const NVEmpty &) {}
+ QT3DS_INLINE NVFlags(void);
+ QT3DS_INLINE NVFlags(enumtype e);
+ QT3DS_INLINE NVFlags(const NVFlags<enumtype, storagetype> &f);
+ QT3DS_INLINE explicit NVFlags(storagetype b);
+
+ QT3DS_INLINE bool operator==(enumtype e) const;
+ QT3DS_INLINE bool operator==(const NVFlags<enumtype, storagetype> &f) const;
+ QT3DS_INLINE bool operator==(bool b) const;
+ QT3DS_INLINE bool operator!=(enumtype e) const;
+ QT3DS_INLINE bool operator!=(const NVFlags<enumtype, storagetype> &f) const;
+
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator=(enumtype e);
+
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator|=(enumtype e);
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator|=(const NVFlags<enumtype, storagetype> &f);
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator|(enumtype e) const;
+ QT3DS_INLINE NVFlags<enumtype, storagetype>
+ operator|(const NVFlags<enumtype, storagetype> &f) const;
+
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator&=(enumtype e);
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator&=(const NVFlags<enumtype, storagetype> &f);
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator&(enumtype e) const;
+ QT3DS_INLINE NVFlags<enumtype, storagetype>
+ operator&(const NVFlags<enumtype, storagetype> &f) const;
+
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator^=(enumtype e);
+ QT3DS_INLINE NVFlags<enumtype, storagetype> &operator^=(const NVFlags<enumtype, storagetype> &f);
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator^(enumtype e) const;
+ QT3DS_INLINE NVFlags<enumtype, storagetype>
+ operator^(const NVFlags<enumtype, storagetype> &f) const;
+
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator~(void)const;
+
+ QT3DS_INLINE operator bool(void) const;
+ QT3DS_INLINE operator QT3DSU8(void) const;
+ QT3DS_INLINE operator QT3DSU16(void) const;
+ QT3DS_INLINE operator QT3DSU32(void) const;
+
+ QT3DS_INLINE void clear(enumtype e);
+
+ QT3DS_INLINE void clearOrSet(bool value, enumtype enumVal);
+
+public:
+ friend QT3DS_INLINE NVFlags<enumtype, storagetype> operator&(enumtype a,
+ NVFlags<enumtype, storagetype> &b)
+ {
+ NVFlags<enumtype, storagetype> out;
+ out.mBits = a & b.mBits;
+ return out;
+ }
+
+private:
+ storagetype mBits;
+};
+
+#define QT3DS_FLAGS_OPERATORS(enumtype, storagetype) \
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator|(enumtype a, enumtype b) \
+{ \
+ NVFlags<enumtype, storagetype> r(a); \
+ r |= b; \
+ return r; \
+} \
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator&(enumtype a, enumtype b) \
+{ \
+ NVFlags<enumtype, storagetype> r(a); \
+ r &= b; \
+ return r; \
+} \
+ QT3DS_INLINE NVFlags<enumtype, storagetype> operator~(enumtype a) \
+{ \
+ return ~NVFlags<enumtype, storagetype>(a); \
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::NVFlags(void)
+{
+ mBits = 0;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::NVFlags(enumtype e)
+{
+ mBits = static_cast<storagetype>(e);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::NVFlags(const NVFlags<enumtype, storagetype> &f)
+{
+ mBits = f.mBits;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::NVFlags(storagetype b)
+{
+ mBits = b;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE bool NVFlags<enumtype, storagetype>::operator==(enumtype e) const
+{
+ return mBits == static_cast<storagetype>(e);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE bool NVFlags<enumtype, storagetype>::
+operator==(const NVFlags<enumtype, storagetype> &f) const
+{
+ return mBits == f.mBits;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE bool NVFlags<enumtype, storagetype>::operator==(bool b) const
+{
+ return ((bool)*this) == b;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE bool NVFlags<enumtype, storagetype>::operator!=(enumtype e) const
+{
+ return mBits != static_cast<storagetype>(e);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE bool NVFlags<enumtype, storagetype>::
+operator!=(const NVFlags<enumtype, storagetype> &f) const
+{
+ return mBits != f.mBits;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::operator=(enumtype e)
+{
+ mBits = static_cast<storagetype>(e);
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::operator|=(enumtype e)
+{
+ mBits |= static_cast<storagetype>(e);
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::
+operator|=(const NVFlags<enumtype, storagetype> &f)
+{
+ mBits |= f.mBits;
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::operator|(enumtype e) const
+{
+ NVFlags<enumtype, storagetype> out(*this);
+ out |= e;
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::
+operator|(const NVFlags<enumtype, storagetype> &f) const
+{
+ NVFlags<enumtype, storagetype> out(*this);
+ out |= f;
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::operator&=(enumtype e)
+{
+ mBits &= static_cast<storagetype>(e);
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::
+operator&=(const NVFlags<enumtype, storagetype> &f)
+{
+ mBits &= f.mBits;
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::operator&(enumtype e) const
+{
+ NVFlags<enumtype, storagetype> out = *this;
+ out.mBits &= static_cast<storagetype>(e);
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::
+operator&(const NVFlags<enumtype, storagetype> &f) const
+{
+ NVFlags<enumtype, storagetype> out = *this;
+ out.mBits &= f.mBits;
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::operator^=(enumtype e)
+{
+ mBits ^= static_cast<storagetype>(e);
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> &NVFlags<enumtype, storagetype>::
+operator^=(const NVFlags<enumtype, storagetype> &f)
+{
+ mBits ^= f.mBits;
+ return *this;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::operator^(enumtype e) const
+{
+ NVFlags<enumtype, storagetype> out = *this;
+ out.mBits ^= static_cast<storagetype>(e);
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::
+operator^(const NVFlags<enumtype, storagetype> &f) const
+{
+ NVFlags<enumtype, storagetype> out = *this;
+ out.mBits ^= f.mBits;
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype> NVFlags<enumtype, storagetype>::operator~(void)const
+{
+ NVFlags<enumtype, storagetype> out;
+ out.mBits = ~mBits;
+ return out;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::operator bool(void) const
+{
+ return mBits ? true : false;
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::operator QT3DSU8(void) const
+{
+ return static_cast<QT3DSU8>(mBits);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::operator QT3DSU16(void) const
+{
+ return static_cast<QT3DSU16>(mBits);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE NVFlags<enumtype, storagetype>::operator QT3DSU32(void) const
+{
+ return static_cast<QT3DSU32>(mBits);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE void NVFlags<enumtype, storagetype>::clear(enumtype e)
+{
+ mBits &= ~static_cast<storagetype>(e);
+}
+
+template <typename enumtype, typename storagetype>
+QT3DS_INLINE void NVFlags<enumtype, storagetype>::clearOrSet(bool value, enumtype enumVal)
+{
+ if (value)
+ this->operator|=(enumVal);
+ else
+ clear(enumVal);
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // #ifndef QT3DS_FOUNDATION_QT3DS_FLAGS_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFoundation.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFoundation.h
new file mode 100644
index 00000000..6657d4f6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSFoundation.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_FOUNDATION_H
+#define QT3DS_FOUNDATION_QT3DS_FOUNDATION_H
+
+/** \addtogroup foundation
+ @{
+*/
+
+#include <stdarg.h>
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSVersionNumber.h"
+#include "foundation/Qt3DSLogging.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+class NVAllocatorCallback;
+class NVProfilingZone;
+class NVBroadcastingAllocator;
+
+class NVFoundationBase
+{
+public:
+ /**
+ retrieves the current allocator.
+ */
+ virtual NVBroadcastingAllocator &getAllocator() const = 0;
+};
+
+namespace foundation {
+template <typename TObjType>
+inline void NVDelete(NVFoundationBase &alloc, TObjType *item)
+{
+ NVDelete(alloc.getAllocator(), item);
+}
+}
+
+/**
+\brief Foundation SDK singleton class.
+
+You need to have an instance of this class to instance the higher level SDKs.
+*/
+class QT3DS_FOUNDATION_API NVFoundation : public NVFoundationBase
+{
+public:
+ virtual void addRef() = 0;
+ /**
+ \brief Destroys the instance it is called on.
+
+ The operation will fail, if there are still modules referencing the foundation object. Release
+ all dependent modules prior
+ to calling this method.
+
+ @see NVCreateFoundation()
+ */
+ virtual void release() = 0;
+
+ /**
+ Retrieves the allocator this object was created with.
+ */
+ virtual NVAllocatorCallback &getAllocatorCallback() const = 0;
+
+protected:
+ virtual ~NVFoundation() {}
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/**
+\brief Creates an instance of the foundation class
+
+\param version Version number we are expecting (should be QT3DS_FOUNDATION_VERSION)
+\param allocator User supplied interface for allocating memory(see #NVAllocatorCallback)
+\return Foundation instance on success, NULL if operation failed
+
+@see NVFoundation
+*/
+
+QT3DS_C_EXPORT QT3DS_FOUNDATION_API qt3ds::NVFoundation *QT3DS_CALL_CONV NVCreateFoundation(
+ qt3ds::QT3DSU32 version, qt3ds::NVAllocatorCallback &allocator);
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_FOUNDATION_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIPC.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIPC.h
new file mode 100644
index 00000000..9bcea1af
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIPC.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_IPC_H
+#define QT3DS_IPC_H
+
+#include "foundation/Qt3DS.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ class NVIPC
+ {
+ public:
+ enum ConnectionType {
+ CT_CLIENT, // start up as a client, will succeed even if the server has not yet been
+ // found.
+ CT_CLIENT_REQUIRE_SERVER, // start up as a client, but only if the server already
+ // exists.
+ CT_SERVER, // will start up as a server, will fail if an existing server is already
+ // open.
+ CT_CLIENT_OR_SERVER, // connect as either a client or server, don't care who is created
+ // first.
+ CT_LAST
+ };
+
+ enum ErrorCode {
+ EC_OK, // no error.
+ EC_FAIL, // generic failure.
+ EC_SERVER_ALREADY_EXISTS, // couldn't create a server, because the server already
+ // exists.
+ EC_CLIENT_ALREADY_EXISTS, // couldn't create a client, because an existing client is
+ // already registered.
+ EC_CLIENT_SERVER_ALREADY_EXISTS, // both the client and server channels are already used
+ EC_SERVER_NOT_FOUND, // client opened with a required server, which was not found.
+ EC_BUFFER_MISSMATCH, // the reserved buffers for client/server do not match up.
+ EC_MAPFILE_CREATE, // failed to create the shared memory map file.
+ EC_MAPFILE_VIEW, // failed to map the memory view of he
+ // communications errors.
+ EC_SEND_DATA_EXCEEDS_MAX_BUFFER, // trying to send more data than can even fit in the
+ // sednd buffe.
+ EC_SEND_DATA_TOO_LARGE, // the data we tried to send exceeds the available room int the
+ // output ring buffer.
+ EC_SEND_BUFFER_FULL, // the send buffer is completely full.
+ EC_SEND_FROM_WRONG_THREAD, // Tried to do a send from a different thread
+ EC_RECEIVE_FROM_WRONG_THREAD, // Tried to do a recieve from a different thread
+ EC_NO_RECEIVE_PENDING, // tried to acknowledge a receive but none was pending.
+ };
+
+ virtual bool pumpPendingSends(void) = 0; // give up a time slice to pending sends; returns
+ // true if there are still pends sending.
+ virtual ErrorCode sendData(const void *data, QT3DSU32 data_len, bool bufferIfFull) = 0;
+ virtual const void *receiveData(QT3DSU32 &data_len) = 0;
+ virtual ErrorCode receiveAcknowledge(void) = 0; // acknowledge that we have processed the
+ // incoming message and can advance the read
+ // buffer.
+
+ virtual bool isServer(void) const = 0; // returns true if we are opened as a server.
+
+ virtual bool haveConnection(void) const = 0;
+
+ virtual bool canSend(QT3DSU32 len) = 0; // return true if we can send a message of this size.
+
+ virtual void release(void) = 0;
+
+ protected:
+ virtual ~NVIPC(void){}
+ };
+}; // end of namespace
+}; // end of namespace
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIndexableLinkedList.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIndexableLinkedList.h
new file mode 100644
index 00000000..ff36b42a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIndexableLinkedList.h
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_INDEXABLE_LINKED_LIST_H
+#define QT3DS_FOUNDATION_INDEXABLE_LINKED_LIST_H
+#include "foundation/Qt3DSPool.h"
+
+namespace qt3ds {
+namespace foundation {
+ // Set of helper functions for manipulation of lists that are
+ // somewhat indexable but also amenable to using a pool structure.
+ template <typename TNodeType, typename TObjType, QT3DSU32 TObjCount>
+ struct IndexableLinkedList
+ {
+ typedef TNodeType SNode;
+
+ typedef Pool<SNode, ForwardingAllocator> TPoolType;
+
+ static TObjType &Create(SNode *&inInitialNode, QT3DSU32 &ioCurrentCount, TPoolType &ioPool)
+ {
+ QT3DSU32 idx = ioCurrentCount;
+ ++ioCurrentCount;
+ QT3DSU32 numGroups = (ioCurrentCount + TObjCount - 1) / TObjCount;
+ QT3DSU32 localIdx = idx % TObjCount;
+
+ SNode *theCurrentNode = inInitialNode;
+ for (QT3DSU32 idx = 0, end = numGroups; idx < end; ++idx) {
+ if (idx == 0) {
+ if (theCurrentNode == NULL)
+ inInitialNode = ioPool.construct(__FILE__, __LINE__);
+
+ theCurrentNode = inInitialNode;
+ } else {
+ if (theCurrentNode->m_NextNode == NULL)
+ theCurrentNode->m_NextNode = ioPool.construct(__FILE__, __LINE__);
+ theCurrentNode = theCurrentNode->m_NextNode;
+ }
+ }
+ return theCurrentNode->m_Data[localIdx];
+ }
+
+ static void CreateAll(SNode *&inInitialNode, QT3DSU32 inCount, TPoolType &ioPool)
+ {
+ QT3DSU32 numGroups = (inCount + TObjCount - 1) / TObjCount;
+ SNode *lastNode = NULL;
+ for (QT3DSU32 idx = 0, end = numGroups; idx < end; ++idx) {
+ SNode *nextNode = ioPool.construct(__FILE__, __LINE__);
+ if (idx == 0)
+ inInitialNode = nextNode;
+ else
+ lastNode->m_NextNode = nextNode;
+ lastNode = nextNode;
+ }
+ }
+
+ static void DeleteList(SNode *&inInitialNode, TPoolType &ioPool)
+ {
+ SNode *theNode = inInitialNode;
+ inInitialNode = NULL;
+ while (theNode) {
+ SNode *theNext = theNode->m_NextNode;
+ theNode->m_NextNode = NULL;
+ ioPool.deallocate(theNode);
+ theNode = theNext;
+ }
+ }
+
+ // Performs no checking, so you need to have already allocated what you need.
+ static const TObjType &GetObjAtIdx(const SNode *inInitialNode, QT3DSU32 inIdx)
+ {
+ QT3DSU32 groupIdx = inIdx / TObjCount;
+ QT3DSU32 localIdx = inIdx % TObjCount;
+ for (QT3DSU32 idx = 0; idx < groupIdx; ++idx)
+ inInitialNode = inInitialNode->m_NextNode;
+ return inInitialNode->m_Data[inIdx];
+ }
+
+ static TObjType &GetObjAtIdx(SNode *inInitialNode, QT3DSU32 inIdx)
+ {
+ QT3DSU32 groupIdx = inIdx / TObjCount;
+ QT3DSU32 localIdx = inIdx % TObjCount;
+ for (QT3DSU32 idx = 0; idx < groupIdx; ++idx)
+ inInitialNode = inInitialNode->m_NextNode;
+ return inInitialNode->m_Data[localIdx];
+ }
+
+ struct SIteratorType
+ {
+ QT3DSU32 m_Idx;
+ QT3DSU32 m_Count;
+ SNode *m_Node;
+
+ SIteratorType()
+ : m_Idx(0)
+ , m_Count(0)
+ , m_Node(NULL)
+ {
+ }
+ SIteratorType(const SIteratorType &iter)
+ : m_Idx(iter.m_Idx)
+ , m_Count(iter.m_Count)
+ , m_Node(iter.m_Node)
+ {
+ }
+ SIteratorType(SNode *inNode, QT3DSU32 inCount, QT3DSU32 inIdx)
+ : m_Idx(inIdx)
+ , m_Count(inCount)
+ , m_Node(inNode)
+ {
+ }
+
+ bool operator==(const SIteratorType &iter) const { return m_Idx == iter.m_Idx; }
+
+ bool operator!=(const SIteratorType &iter) const { return m_Idx != iter.m_Idx; }
+
+ TObjType &operator*()
+ {
+ QT3DSU32 localIdx = m_Idx % TObjCount;
+ return m_Node->m_Data[localIdx];
+ }
+
+ SIteratorType &operator++()
+ {
+ ++m_Idx;
+ if ((m_Idx % TObjCount) == 0)
+ m_Node = m_Node->m_NextNode;
+
+ return *this;
+ }
+ };
+
+ struct SConstIteratorType
+ {
+ QT3DSU32 m_Idx;
+ QT3DSU32 m_Count;
+ const SNode *m_Node;
+
+ SConstIteratorType()
+ : m_Idx(0)
+ , m_Count(0)
+ , m_Node(NULL)
+ {
+ }
+ SConstIteratorType(const SIteratorType &iter)
+ : m_Idx(iter.m_Idx)
+ , m_Count(iter.m_Count)
+ , m_Node(iter.m_Node)
+ {
+ }
+ SConstIteratorType(const SConstIteratorType &iter)
+ : m_Idx(iter.m_Idx)
+ , m_Count(iter.m_Count)
+ , m_Node(iter.m_Node)
+ {
+ }
+ SConstIteratorType(const SNode *inNode, QT3DSU32 inCount, QT3DSU32 inIdx)
+ : m_Idx(inIdx)
+ , m_Count(inCount)
+ , m_Node(inNode)
+ {
+ }
+
+ bool operator==(const SConstIteratorType &iter) const { return m_Idx == iter.m_Idx; }
+
+ bool operator!=(const SConstIteratorType &iter) const { return m_Idx != iter.m_Idx; }
+
+ const TObjType &operator*()
+ {
+ QT3DSU32 localIdx = m_Idx % TObjCount;
+ return m_Node->m_Data[localIdx];
+ }
+
+ SConstIteratorType &operator++()
+ {
+ ++m_Idx;
+ if ((m_Idx % TObjCount) == 0)
+ m_Node = m_Node->m_NextNode;
+
+ return *this;
+ }
+ };
+
+ typedef SIteratorType iterator;
+ typedef SConstIteratorType const_iterator;
+
+ static iterator begin(SNode *inInitialNode, QT3DSU32 inItemCount)
+ {
+ return SIteratorType(inInitialNode, inItemCount, 0);
+ }
+
+ static iterator end(SNode * /*inInitialNode*/, QT3DSU32 inItemCount)
+ {
+ return SIteratorType(NULL, inItemCount, inItemCount);
+ }
+
+ static const_iterator begin(const SNode *inInitialNode, QT3DSU32 inItemCount)
+ {
+ return SConstIteratorType(inInitialNode, inItemCount, 0);
+ }
+
+ static const_iterator end(const SNode * /*inInitialNode*/, QT3DSU32 inItemCount)
+ {
+ return SConstIteratorType(NULL, inItemCount, inItemCount);
+ }
+
+ struct SNodeIteratorType
+ {
+ SNode *m_Node;
+
+ SNodeIteratorType()
+ : m_Node(NULL)
+ {
+ }
+ SNodeIteratorType(const SNodeIteratorType &iter)
+ : m_Node(iter.m_Node)
+ {
+ }
+ SNodeIteratorType(SNode *inNode)
+ : m_Node(inNode)
+ {
+ }
+
+ bool operator==(const SNodeIteratorType &iter) const { return m_Node == iter.m_Node; }
+
+ bool operator!=(const SNodeIteratorType &iter) const { return m_Node != iter.m_Node; }
+
+ TNodeType &operator*() { return *m_Node; }
+
+ SNodeIteratorType &operator++()
+ {
+ if (m_Node)
+ m_Node = m_Node->m_NextNode;
+
+ return *this;
+ }
+ };
+
+ typedef SNodeIteratorType node_iterator;
+ static node_iterator node_begin(SNode *inFirstNode) { return node_iterator(inFirstNode); }
+ static node_iterator node_end(SNode * /*inFirstNode*/) { return node_iterator(NULL); }
+
+ // Iterates through the number of nodes required for a given count of objects
+ struct SCountIteratorType
+ {
+ QT3DSU32 m_Idx;
+ QT3DSU32 m_Count;
+
+ SCountIteratorType()
+ : m_Idx(0)
+ , m_Count(0)
+ {
+ }
+ SCountIteratorType(const SCountIteratorType &iter)
+ : m_Idx(iter.m_Idx)
+ , m_Count(iter.m_Count)
+ {
+ }
+ SCountIteratorType(QT3DSU32 idx, QT3DSU32 count)
+ : m_Idx(idx)
+ , m_Count(count)
+ {
+ }
+
+ bool operator==(const SCountIteratorType &iter) const { return m_Idx == iter.m_Idx; }
+
+ bool operator!=(const SCountIteratorType &iter) const { return m_Idx != iter.m_Idx; }
+
+ SCountIteratorType &operator++()
+ {
+ m_Idx = NVMin(m_Idx + TObjCount, m_Count);
+ return *this;
+ }
+ };
+
+ typedef SCountIteratorType count_iterator;
+ static count_iterator count_begin(QT3DSU32 count) { return SCountIteratorType(0, count); }
+ static count_iterator count_end(QT3DSU32 count) { return SCountIteratorType(count, count); }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIntrinsics.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIntrinsics.h
new file mode 100644
index 00000000..1d6ac7a5
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSIntrinsics.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_INTRINSICS_H
+#define QT3DS_FOUNDATION_QT3DS_INTRINSICS_H
+
+#include "foundation/Qt3DSPreprocessor.h"
+
+#if defined QT3DS_WINDOWS || defined QT3DS_WIN8ARM
+#include "windows/Qt3DSWindowsIntrinsics.h"
+#elif defined QT3DS_X360
+#include "xbox360/NVXbox360Intrinsics.h"
+#elif (defined QT3DS_LINUX || defined QT3DS_ANDROID || defined QT3DS_APPLE || defined QT3DS_QNX)
+#include "linux/Qt3DSLinuxIntrinsics.h"
+#elif defined QT3DS_PS3
+#include "ps3/NVPS3Intrinsics.h"
+#elif defined QT3DS_PSP2
+#include "psp2/NVPSP2Intrinsics.h"
+#else
+#error "Platform not supported!"
+#endif
+
+#endif // QT3DS_FOUNDATION_QT3DS_INTRINSICS_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveLinkedList.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveLinkedList.h
new file mode 100644
index 00000000..da90e120
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveLinkedList.h
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_INVASIVE_LINKED_LIST_H
+#define QT3DS_FOUNDATION_INVASIVE_LINKED_LIST_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSContainers.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ // Base linked list without an included head or tail member.
+ template <typename TObjType, typename TObjHeadOp, typename TObjTailOp>
+ struct SInvasiveLinkListBase
+ {
+ TObjType *tail(TObjType *inObj)
+ {
+ if (inObj)
+ return TObjTailOp().get(inObj);
+ return NULL;
+ }
+
+ TObjType *head(TObjType *inObj)
+ {
+ if (inObj)
+ return TObjHeadOp().get(inObj);
+ return NULL;
+ }
+
+ const TObjType *tail(const TObjType *inObj)
+ {
+ if (inObj)
+ return TObjTailOp().get(inObj);
+ return NULL;
+ }
+
+ const TObjType *head(const TObjType *inObj)
+ {
+ if (inObj)
+ return TObjHeadOp().get(inObj);
+ return NULL;
+ }
+
+ void remove(TObjType &inObj)
+ {
+ TObjHeadOp theHeadOp;
+ TObjTailOp theTailOp;
+ TObjType *theHead = theHeadOp.get(inObj);
+ TObjType *theTail = theTailOp.get(inObj);
+ if (theHead)
+ theTailOp.set(*theHead, theTail);
+ if (theTail)
+ theHeadOp.set(*theTail, theHead);
+ theHeadOp.set(inObj, NULL);
+ theTailOp.set(inObj, NULL);
+ }
+
+ void insert_after(TObjType &inPosition, TObjType &inObj)
+ {
+ TObjTailOp theTailOp;
+ TObjType *theHead = &inPosition;
+ TObjType *theTail = theTailOp.get(inPosition);
+ insert(theHead, theTail, inObj);
+ }
+
+ void insert_before(TObjType &inPosition, TObjType &inObj)
+ {
+ TObjHeadOp theHeadOp;
+ TObjType *theHead = theHeadOp.get(inPosition);
+ TObjType *theTail = &inPosition;
+ insert(theHead, theTail, inObj);
+ }
+
+ void insert(TObjType *inHead, TObjType *inTail, TObjType &inObj)
+ {
+ TObjHeadOp theHeadOp;
+ TObjTailOp theTailOp;
+ if (inHead)
+ theTailOp.set(*inHead, &inObj);
+ if (inTail)
+ theHeadOp.set(*inTail, &inObj);
+ theHeadOp.set(inObj, inHead);
+ theTailOp.set(inObj, inTail);
+ }
+ };
+
+ template <typename TObjType, typename TObjTailOp>
+ struct SLinkedListIterator
+ {
+ typedef SLinkedListIterator<TObjType, TObjTailOp> TMyType;
+ TObjType *m_Obj;
+ SLinkedListIterator(TObjType *inObj = NULL)
+ : m_Obj(inObj)
+ {
+ }
+
+ bool operator!=(const TMyType &inIter) const { return m_Obj != inIter.m_Obj; }
+ bool operator==(const TMyType &inIter) const { return m_Obj == inIter.m_Obj; }
+
+ TMyType &operator++()
+ {
+ if (m_Obj)
+ m_Obj = TObjTailOp().get(*m_Obj);
+ return *this;
+ }
+
+ TMyType &operator++(int)
+ {
+ TMyType retval(*this);
+ ++(*this);
+ return retval;
+ }
+
+ TObjType &operator*() { return *m_Obj; }
+ TObjType *operator->() { return m_Obj; }
+ };
+
+ // Used for singly linked list where
+ // items have either no head or tail ptr.
+ template <typename TObjType>
+ struct SNullOp
+ {
+ void set(TObjType &, TObjType *) {}
+ TObjType *get(const TObjType &) { return NULL; }
+ };
+
+ template <typename TObjType, typename TObjTailOp>
+ struct InvasiveSingleLinkedList
+ : public SInvasiveLinkListBase<TObjType, SNullOp<TObjType>, TObjTailOp>
+ {
+ typedef InvasiveSingleLinkedList<TObjType, TObjTailOp> TMyType;
+ typedef SInvasiveLinkListBase<TObjType, SNullOp<TObjType>, TObjTailOp> TBaseType;
+ typedef SLinkedListIterator<TObjType, TObjTailOp> iterator;
+ typedef iterator const_iterator;
+ TObjType *m_Head;
+ InvasiveSingleLinkedList()
+ : m_Head(NULL)
+ {
+ }
+ InvasiveSingleLinkedList(const TMyType &inOther)
+ : m_Head(inOther.m_Head)
+ {
+ }
+ TMyType &operator=(const TMyType &inOther)
+ {
+ m_Head = inOther.m_Head;
+ return *this;
+ }
+
+ TObjType &front() const { return *m_Head; }
+
+ void push_front(TObjType &inObj)
+ {
+ if (m_Head != NULL)
+ TBaseType::insert_before(*m_Head, inObj);
+ m_Head = &inObj;
+ }
+
+ void push_back(TObjType &inObj)
+ {
+ if (m_Head == NULL)
+ m_Head = &inObj;
+ else {
+ TObjType *lastObj = NULL;
+ for (iterator iter = begin(), endIter = end(); iter != endIter; ++iter)
+ lastObj = &(*iter);
+
+ QT3DS_ASSERT(lastObj);
+ if (lastObj)
+ TObjTailOp().set(*lastObj, &inObj);
+ }
+ }
+
+ void remove(TObjType &inObj)
+ {
+ if (m_Head == &inObj)
+ m_Head = TObjTailOp().get(inObj);
+ TBaseType::remove(inObj);
+ }
+
+ bool empty() const { return m_Head == NULL; }
+
+ iterator begin() { return iterator(m_Head); }
+ iterator end() { return iterator(NULL); }
+
+ const_iterator begin() const { return iterator(m_Head); }
+ const_iterator end() const { return iterator(NULL); }
+ };
+
+ template <typename TObjType, typename TObjHeadOp, typename TObjTailOp>
+ struct InvasiveLinkedList : public SInvasiveLinkListBase<TObjType, TObjHeadOp, TObjTailOp>
+ {
+ typedef InvasiveLinkedList<TObjType, TObjHeadOp, TObjTailOp> TMyType;
+ typedef SInvasiveLinkListBase<TObjType, TObjHeadOp, TObjTailOp> TBaseType;
+ typedef SLinkedListIterator<TObjType, TObjTailOp> iterator;
+ typedef iterator const_iterator;
+ typedef SLinkedListIterator<TObjType, TObjHeadOp> reverse_iterator;
+ typedef reverse_iterator const_reverse_iterator;
+
+ TObjType *m_Head;
+ TObjType *m_Tail;
+
+ InvasiveLinkedList()
+ : m_Head(NULL)
+ , m_Tail(NULL)
+ {
+ }
+ InvasiveLinkedList(const TMyType &inOther)
+ : m_Head(inOther.m_Head)
+ , m_Tail(inOther.m_Tail)
+ {
+ }
+ TMyType &operator=(const TMyType &inOther)
+ {
+ m_Head = inOther.m_Head;
+ m_Tail = inOther.m_Tail;
+ return *this;
+ }
+
+ TObjType &front() const
+ {
+ QT3DS_ASSERT(m_Head);
+ return *m_Head;
+ }
+ TObjType &back() const
+ {
+ QT3DS_ASSERT(m_Tail);
+ return *m_Tail;
+ }
+
+ TObjType *front_ptr() const { return m_Head; }
+ TObjType *back_ptr() const { return m_Tail; }
+
+ void push_front(TObjType &inObj)
+ {
+ if (m_Head != NULL)
+ TBaseType::insert_before(*m_Head, inObj);
+ m_Head = &inObj;
+
+ if (m_Tail == NULL)
+ m_Tail = &inObj;
+ }
+
+ void push_back(TObjType &inObj)
+ {
+ if (m_Tail != NULL)
+ TBaseType::insert_after(*m_Tail, inObj);
+ m_Tail = &inObj;
+
+ if (m_Head == NULL)
+ m_Head = &inObj;
+ }
+
+ void remove(TObjType &inObj)
+ {
+ if (m_Head == &inObj)
+ m_Head = TObjTailOp().get(inObj);
+ if (m_Tail == &inObj)
+ m_Tail = TObjHeadOp().get(inObj);
+
+ TBaseType::remove(inObj);
+ }
+
+ bool empty() const { return m_Head == NULL; }
+
+ iterator begin() { return iterator(m_Head); }
+ iterator end() { return iterator(NULL); }
+
+ const_iterator begin() const { return iterator(m_Head); }
+ const_iterator end() const { return iterator(NULL); }
+
+ reverse_iterator rbegin() { return reverse_iterator(m_Tail); }
+ reverse_iterator rend() { return reverse_iterator(NULL); }
+
+ const_reverse_iterator rbegin() const { return reverse_iterator(m_Tail); }
+ const_reverse_iterator rend() const { return reverse_iterator(NULL); }
+ };
+
+// Macros to speed up the definitely of invasive linked lists.
+#define DEFINE_INVASIVE_SINGLE_LIST(type) \
+ struct S##type; \
+ struct S##type##NextOp \
+ { \
+ S##type *get(S##type &s); \
+ const S##type *get(const S##type &s) const; \
+ void set(S##type &inItem, S##type *inNext); \
+ }; \
+ typedef InvasiveSingleLinkedList<S##type, S##type##NextOp> T##type##List;
+
+#define DEFINE_INVASIVE_LIST(type) \
+ struct S##type; \
+ struct S##type##NextOp \
+ { \
+ S##type *get(S##type &s); \
+ const S##type *get(const S##type &s) const; \
+ void set(S##type &inItem, S##type *inNext); \
+ }; \
+ struct S##type##PreviousOp \
+ { \
+ S##type *get(S##type &s); \
+ const S##type *get(const S##type &s) const; \
+ void set(S##type &inItem, S##type *inNext); \
+ }; \
+ typedef InvasiveLinkedList<S##type, S##type##PreviousOp, S##type##NextOp> T##type##List;
+
+#define IMPLEMENT_INVASIVE_LIST(type, prevMember, nextMember) \
+ inline S##type *S##type##NextOp::get(S##type &s) { return s.nextMember; } \
+ inline const S##type *S##type##NextOp::get(const S##type &s) const { return s.nextMember; } \
+ inline void S##type##NextOp::set(S##type &inItem, S##type *inNext) \
+ { \
+ inItem.nextMember = inNext; \
+ } \
+ inline S##type *S##type##PreviousOp::get(S##type &s) { return s.prevMember; } \
+ inline const S##type *S##type##PreviousOp::get(const S##type &s) const \
+ { \
+ return s.prevMember; \
+ } \
+ inline void S##type##PreviousOp::set(S##type &inItem, S##type *inNext) \
+ { \
+ inItem.prevMember = inNext; \
+ }
+
+#define IMPLEMENT_INVASIVE_SINGLE_LIST(type, nextMember) \
+ inline S##type *S##type##NextOp::get(S##type &s) { return s.nextMember; } \
+ inline const S##type *S##type##NextOp::get(const S##type &s) const { return s.nextMember; } \
+ inline void S##type##NextOp::set(S##type &inItem, S##type *inNext) \
+ { \
+ inItem.nextMember = inNext; \
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveSet.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveSet.h
new file mode 100644
index 00000000..772a2308
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSInvasiveSet.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_INVASIVE_SET_H
+#define QT3DS_FOUNDATION_INVASIVE_SET_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSContainers.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename TObjectType, typename TGetSetIndexOp, typename TSetSetIndexOp>
+ class InvasiveSet
+ {
+ nvvector<TObjectType *> mSet;
+
+ InvasiveSet(const InvasiveSet &other);
+ InvasiveSet &operator=(const InvasiveSet &other);
+
+ public:
+ InvasiveSet(NVAllocatorCallback &callback, const char *allocName)
+ : mSet(callback, allocName)
+ {
+ }
+
+ bool insert(TObjectType &inObject)
+ {
+ QT3DSU32 currentIdx = TGetSetIndexOp()(inObject);
+ if (currentIdx == QT3DS_MAX_U32) {
+ TSetSetIndexOp()(inObject, mSet.size());
+ mSet.push_back(&inObject);
+ return true;
+ }
+ return false;
+ }
+
+ bool remove(TObjectType &inObject)
+ {
+ QT3DSU32 currentIdx = TGetSetIndexOp()(inObject);
+ if (currentIdx != QT3DS_MAX_U32) {
+ TObjectType *theEnd = mSet.back();
+ TObjectType *theObj = &inObject;
+ if (theEnd != theObj) {
+ TSetSetIndexOp()(*theEnd, currentIdx);
+ mSet[currentIdx] = theEnd;
+ }
+ mSet.pop_back();
+ TSetSetIndexOp()(inObject, QT3DS_MAX_U32);
+ return true;
+ }
+ return false;
+ }
+
+ bool contains(TObjectType &inObject) { return TGetSetIndexOp()(inObject) != QT3DS_MAX_U32; }
+
+ void clear()
+ {
+ for (QT3DSU32 idx = 0; idx < mSet.size(); ++idx)
+ TSetSetIndexOp()(*(mSet[idx]), QT3DS_MAX_U32);
+ mSet.clear();
+ }
+
+ TObjectType *operator[](QT3DSU32 idx) { return mSet[idx]; }
+ const TObjectType *operator[](QT3DSU32 idx) const { return mSet[idx]; }
+ QT3DSU32 size() const { return mSet.size(); }
+ TObjectType **begin() { return mSet.begin(); }
+ TObjectType **end() { return mSet.end(); }
+ const TObjectType **begin() const { return mSet.begin(); }
+ const TObjectType **end() const { return mSet.end(); }
+ const TObjectType *back() const { return mSet.back(); }
+ TObjectType *back() { return mSet.back(); }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSLogging.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSLogging.h
new file mode 100644
index 00000000..894583ab
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSLogging.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_ERRORS_H
+#define QT3DS_FOUNDATION_QT3DS_ERRORS_H
+
+#include <QDebug>
+
+// This is defined in: src/Authoring/Studio/English.lproj/Strings/Strings.h
+// which gets pulled into the precompiled header stdafx.h by the windows build
+// and conflicts with private member variables used in Qt.
+#undef placeholder
+
+#include <QLoggingCategory>
+
+namespace qt3ds {
+
+Q_DECLARE_LOGGING_CATEGORY(GL_ERROR)
+Q_DECLARE_LOGGING_CATEGORY(INVALID_PARAMETER)
+Q_DECLARE_LOGGING_CATEGORY(INVALID_OPERATION)
+Q_DECLARE_LOGGING_CATEGORY(OUT_OF_MEMORY)
+Q_DECLARE_LOGGING_CATEGORY(INTERNAL_ERROR)
+Q_DECLARE_LOGGING_CATEGORY(PERF_WARNING)
+Q_DECLARE_LOGGING_CATEGORY(PERF_INFO)
+Q_DECLARE_LOGGING_CATEGORY(TRACE_INFO)
+Q_DECLARE_LOGGING_CATEGORY(WARNING)
+
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat33.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat33.h
new file mode 100644
index 00000000..6fa69eb5
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat33.h
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_MAT33_H
+#define QT3DS_FOUNDATION_QT3DS_MAT33_H
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSQuat.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+/*!
+\brief 3x3 matrix class
+
+Some clarifications, as there have been much confusion about matrix formats etc in the past.
+
+Short:
+- Matrix have base vectors in columns (vectors are column matrices, 3x1 matrices).
+- Matrix is physically stored in column major format
+- Matrices are concaternated from left
+
+Long:
+Given three base vectors a, b and c the matrix is stored as
+
+|a.x b.x c.x|
+|a.y b.y c.y|
+|a.z b.z c.z|
+
+Vectors are treated as columns, so the vector v is
+
+|x|
+|y|
+|z|
+
+And matrices are applied _before_ the vector (pre-multiplication)
+v' = M*v
+
+|x'| |a.x b.x c.x| |x| |a.x*x + b.x*y + c.x*z|
+|y'| = |a.y b.y c.y| * |y| = |a.y*x + b.y*y + c.y*z|
+|z'| |a.z b.z c.z| |z| |a.z*x + b.z*y + c.z*z|
+
+
+Physical storage and indexing:
+To be compatible with popular 3d rendering APIs (read D3d and OpenGL)
+the physical indexing is
+
+|0 3 6|
+|1 4 7|
+|2 5 8|
+
+index = column*3 + row
+
+which in C++ translates to M[column][row]
+
+The mathematical indexing is M_row,column and this is what is used for _-notation
+so _12 is 1st row, second column and operator(row, column)!
+
+@see QT3DSMat44
+
+*/
+class QT3DSMat33
+{
+public:
+ //! Default constructor
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33() {}
+
+ //! Construct from three base vectors
+ QT3DS_CUDA_CALLABLE QT3DSMat33(const QT3DSVec3 &col0, const QT3DSVec3 &col1, const QT3DSVec3 &col2)
+ : column0(col0)
+ , column1(col1)
+ , column2(col2)
+ {
+ }
+
+ //! Construct from float[9]
+ QT3DS_CUDA_CALLABLE explicit QT3DS_INLINE QT3DSMat33(NVReal values[])
+ : column0(values[0], values[1], values[2])
+ , column1(values[3], values[4], values[5])
+ , column2(values[6], values[7], values[8])
+ {
+ }
+
+ //! Construct from a quaternion
+ QT3DS_CUDA_CALLABLE explicit QT3DS_FORCE_INLINE QT3DSMat33(const QT3DSQuat &q)
+ {
+ const NVReal x = q.x;
+ const NVReal y = q.y;
+ const NVReal z = q.z;
+ const NVReal w = q.w;
+
+ const NVReal x2 = x + x;
+ const NVReal y2 = y + y;
+ const NVReal z2 = z + z;
+
+ const NVReal xx = x2 * x;
+ const NVReal yy = y2 * y;
+ const NVReal zz = z2 * z;
+
+ const NVReal xy = x2 * y;
+ const NVReal xz = x2 * z;
+ const NVReal xw = x2 * w;
+
+ const NVReal yz = y2 * z;
+ const NVReal yw = y2 * w;
+ const NVReal zw = z2 * w;
+
+ column0 = QT3DSVec3(1.0f - yy - zz, xy + zw, xz - yw);
+ column1 = QT3DSVec3(xy - zw, 1.0f - xx - zz, yz + xw);
+ column2 = QT3DSVec3(xz + yw, yz - xw, 1.0f - xx - yy);
+ }
+
+ //! Copy constructor
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33(const QT3DSMat33 &other)
+ : column0(other.column0)
+ , column1(other.column1)
+ , column2(other.column2)
+ {
+ }
+
+ //! Assignment operator
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSMat33 &operator=(const QT3DSMat33 &other)
+ {
+ column0 = other.column0;
+ column1 = other.column1;
+ column2 = other.column2;
+ return *this;
+ }
+
+ //! Set to identity matrix
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE static QT3DSMat33 createIdentity()
+ {
+ return QT3DSMat33(QT3DSVec3(1, 0, 0), QT3DSVec3(0, 1, 0), QT3DSVec3(0, 0, 1));
+ }
+
+ //! Set to zero matrix
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE static QT3DSMat33 createZero()
+ {
+ return QT3DSMat33(QT3DSVec3(0.0f), QT3DSVec3(0.0f), QT3DSVec3(0.0f));
+ }
+
+ //! Construct from diagonal, off-diagonals are zero.
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE static QT3DSMat33 createDiagonal(const QT3DSVec3 &d)
+ {
+ return QT3DSMat33(QT3DSVec3(d.x, 0.0f, 0.0f), QT3DSVec3(0.0f, d.y, 0.0f), QT3DSVec3(0.0f, 0.0f, d.z));
+ }
+
+ //! Get transposed matrix
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSMat33 getTranspose() const
+ {
+ const QT3DSVec3 v0(column0.x, column1.x, column2.x);
+ const QT3DSVec3 v1(column0.y, column1.y, column2.y);
+ const QT3DSVec3 v2(column0.z, column1.z, column2.z);
+
+ return QT3DSMat33(v0, v1, v2);
+ }
+
+ //! Get the real inverse
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 getInverse() const
+ {
+ const NVReal det = getDeterminant();
+ QT3DSMat33 inverse;
+
+ if (det != 0) {
+ const NVReal invDet = 1.0f / det;
+
+ inverse.column0[0] = invDet * (column1[1] * column2[2] - column2[1] * column1[2]);
+ inverse.column0[1] = invDet * -(column0[1] * column2[2] - column2[1] * column0[2]);
+ inverse.column0[2] = invDet * (column0[1] * column1[2] - column0[2] * column1[1]);
+
+ inverse.column1[0] = invDet * -(column1[0] * column2[2] - column1[2] * column2[0]);
+ inverse.column1[1] = invDet * (column0[0] * column2[2] - column0[2] * column2[0]);
+ inverse.column1[2] = invDet * -(column0[0] * column1[2] - column0[2] * column1[0]);
+
+ inverse.column2[0] = invDet * (column1[0] * column2[1] - column1[1] * column2[0]);
+ inverse.column2[1] = invDet * -(column0[0] * column2[1] - column0[1] * column2[0]);
+ inverse.column2[2] = invDet * (column0[0] * column1[1] - column1[0] * column0[1]);
+
+ return inverse;
+ } else {
+ return createIdentity();
+ }
+ }
+
+ //! Get determinant
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal getDeterminant() const
+ {
+ return column0.dot(column1.cross(column2));
+ }
+
+ //! Unary minus
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 operator-() const
+ {
+ return QT3DSMat33(-column0, -column1, -column2);
+ }
+
+ //! Add
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 operator+(const QT3DSMat33 &other) const
+ {
+ return QT3DSMat33(column0 + other.column0, column1 + other.column1, column2 + other.column2);
+ }
+
+ //! Subtract
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 operator-(const QT3DSMat33 &other) const
+ {
+ return QT3DSMat33(column0 - other.column0, column1 - other.column1, column2 - other.column2);
+ }
+
+ //! Scalar multiplication
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 operator*(NVReal scalar) const
+ {
+ return QT3DSMat33(column0 * scalar, column1 * scalar, column2 * scalar);
+ }
+
+ friend QT3DSMat33 operator*(NVReal, const QT3DSMat33 &);
+
+ //! Matrix vector multiplication (returns 'this->transform(vec)')
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 operator*(const QT3DSVec3 &vec) const { return transform(vec); }
+
+ //! Matrix multiplication
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSMat33 operator*(const QT3DSMat33 &other) const
+ {
+ // Rows from this <dot> columns from other
+ // column0 = transform(other.column0) etc
+ return QT3DSMat33(transform(other.column0), transform(other.column1),
+ transform(other.column2));
+ }
+
+ // a <op>= b operators
+
+ //! Equals-add
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 &operator+=(const QT3DSMat33 &other)
+ {
+ column0 += other.column0;
+ column1 += other.column1;
+ column2 += other.column2;
+ return *this;
+ }
+
+ //! Equals-sub
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 &operator-=(const QT3DSMat33 &other)
+ {
+ column0 -= other.column0;
+ column1 -= other.column1;
+ column2 -= other.column2;
+ return *this;
+ }
+
+ //! Equals scalar multiplication
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 &operator*=(NVReal scalar)
+ {
+ column0 *= scalar;
+ column1 *= scalar;
+ column2 *= scalar;
+ return *this;
+ }
+
+ //! Element access, mathematical way!
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal operator()(unsigned int row, unsigned int col) const
+ {
+ return (*this)[col][row];
+ }
+
+ //! Element access, mathematical way!
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal &operator()(unsigned int row, unsigned int col)
+ {
+ return (*this)[col][row];
+ }
+
+ // Transform etc
+
+ //! Transform vector by matrix, equal to v' = M*v
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 transform(const QT3DSVec3 &other) const
+ {
+ return column0 * other.x + column1 * other.y + column2 * other.z;
+ }
+
+ //! Transform vector by matrix transpose, v' = M^t*v
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 transformTranspose(const QT3DSVec3 &other) const
+ {
+ return QT3DSVec3(column0.dot(other), column1.dot(other), column2.dot(other));
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const NVReal *front() const { return &column0.x; }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 &operator[](int num) { return (&column0)[num]; }
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const QT3DSVec3 &operator[](int num) const
+ {
+ return (&column0)[num];
+ }
+
+ // Data, see above for format!
+
+ QT3DSVec3 column0, column1, column2; // the three base vectors
+};
+
+// implementation from Qt3DSQuat.h
+QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat::QT3DSQuat(const QT3DSMat33 &m)
+{
+ NVReal tr = m(0, 0) + m(1, 1) + m(2, 2), h;
+ if (tr >= 0) {
+ h = NVSqrt(tr + 1);
+ w = NVReal(0.5) * h;
+ h = NVReal(0.5) / h;
+
+ x = (m(2, 1) - m(1, 2)) * h;
+ y = (m(0, 2) - m(2, 0)) * h;
+ z = (m(1, 0) - m(0, 1)) * h;
+ } else {
+ int i = 0;
+ if (m(1, 1) > m(0, 0))
+ i = 1;
+ if (m(2, 2) > m(i, i))
+ i = 2;
+ switch (i) {
+ case 0:
+ h = NVSqrt((m(0, 0) - (m(1, 1) + m(2, 2))) + 1);
+ x = NVReal(0.5) * h;
+ h = NVReal(0.5) / h;
+
+ y = (m(0, 1) + m(1, 0)) * h;
+ z = (m(2, 0) + m(0, 2)) * h;
+ w = (m(2, 1) - m(1, 2)) * h;
+ break;
+ case 1:
+ h = NVSqrt((m(1, 1) - (m(2, 2) + m(0, 0))) + 1);
+ y = NVReal(0.5) * h;
+ h = NVReal(0.5) / h;
+
+ z = (m(1, 2) + m(2, 1)) * h;
+ x = (m(0, 1) + m(1, 0)) * h;
+ w = (m(0, 2) - m(2, 0)) * h;
+ break;
+ case 2:
+ h = NVSqrt((m(2, 2) - (m(0, 0) + m(1, 1))) + 1);
+ z = NVReal(0.5) * h;
+ h = NVReal(0.5) / h;
+
+ x = (m(2, 0) + m(0, 2)) * h;
+ y = (m(1, 2) + m(2, 1)) * h;
+ w = (m(1, 0) - m(0, 1)) * h;
+ break;
+ default: // Make compiler happy
+ x = y = z = w = 0;
+ break;
+ }
+ }
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_MAT33_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat44.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat44.h
new file mode 100644
index 00000000..53a66e2b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMat44.h
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_MAT44_H
+#define QT3DS_FOUNDATION_QT3DS_MAT44_H
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSQuat.h"
+#include "foundation/Qt3DSVec4.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DSTransform.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/*!
+\brief 4x4 matrix class
+
+This class is layout-compatible with D3D and OpenGL matrices. More notes on layout are given in the QT3DSMat33
+Graphics matrices always (by which I mean DX and OpenGL) have the rotation basis vectors stored contiguously
+in 0-2, 3-5, 6-8 and the the translation stored contiguously in 12-14. However, DX calls this row major and GL calls it column-major.
+http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html
+
+you can blat these directly into GL (or DX)
+
+--Dilip Sequeira
+
+@see QT3DSMat33 NVTransform
+*/
+
+class QT3DSMat44
+{
+public:
+ //! Default constructor
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44() {}
+
+ //! Construct from four 4-vectors
+ QT3DS_CUDA_CALLABLE QT3DSMat44(const QT3DSVec4 &col0, const QT3DSVec4 &col1, const QT3DSVec4 &col2,
+ const QT3DSVec4 &col3)
+ : column0(col0)
+ , column1(col1)
+ , column2(col2)
+ , column3(col3)
+ {
+ }
+
+ //! Construct from three base vectors and a translation
+ QT3DS_CUDA_CALLABLE QT3DSMat44(const QT3DSVec3 &column0, const QT3DSVec3 &column1, const QT3DSVec3 &column2,
+ const QT3DSVec3 &column3)
+ : column0(column0, 0)
+ , column1(column1, 0)
+ , column2(column2, 0)
+ , column3(column3, 1)
+ {
+ }
+
+ //! Construct from float[16]
+ explicit QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44(NVReal values[])
+ : column0(values[0], values[1], values[2], values[3])
+ , column1(values[4], values[5], values[6], values[7])
+ , column2(values[8], values[9], values[10], values[11])
+ , column3(values[12], values[13], values[14], values[15])
+ {
+ }
+
+ //! Construct from a quaternion
+ explicit QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44(const QT3DSQuat &q)
+ {
+ const NVReal x = q.x;
+ const NVReal y = q.y;
+ const NVReal z = q.z;
+ const NVReal w = q.w;
+
+ const NVReal x2 = x + x;
+ const NVReal y2 = y + y;
+ const NVReal z2 = z + z;
+
+ const NVReal xx = x2 * x;
+ const NVReal yy = y2 * y;
+ const NVReal zz = z2 * z;
+
+ const NVReal xy = x2 * y;
+ const NVReal xz = x2 * z;
+ const NVReal xw = x2 * w;
+
+ const NVReal yz = y2 * z;
+ const NVReal yw = y2 * w;
+ const NVReal zw = z2 * w;
+
+ column0 = QT3DSVec4(1.0f - yy - zz, xy + zw, xz - yw, 0.0f);
+ column1 = QT3DSVec4(xy - zw, 1.0f - xx - zz, yz + xw, 0.0f);
+ column2 = QT3DSVec4(xz + yw, yz - xw, 1.0f - xx - yy, 0.0f);
+ column3 = QT3DSVec4(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ //! Construct from a diagonal vector
+ explicit QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44(const QT3DSVec4 &diagonal)
+ : column0(diagonal.x, 0.0f, 0.0f, 0.0f)
+ , column1(0.0f, diagonal.y, 0.0f, 0.0f)
+ , column2(0.0f, 0.0f, diagonal.z, 0.0f)
+ , column3(0.0f, 0.0f, 0.0f, diagonal.w)
+ {
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DSMat44(const QT3DSMat33 &orientation, const QT3DSVec3 &position)
+ : column0(orientation.column0, 0.0f)
+ , column1(orientation.column1, 0.0f)
+ , column2(orientation.column2, 0.0f)
+ , column3(position, 1)
+ {
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DSMat44(const NVTransform &t) { *this = QT3DSMat44(QT3DSMat33(t.q), t.p); }
+
+ //! Copy constructor
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44(const QT3DSMat44 &other)
+ : column0(other.column0)
+ , column1(other.column1)
+ , column2(other.column2)
+ , column3(other.column3)
+ {
+ }
+
+ //! Assignment operator
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE const QT3DSMat44 &operator=(const QT3DSMat44 &other)
+ {
+ column0 = other.column0;
+ column1 = other.column1;
+ column2 = other.column2;
+ column3 = other.column3;
+ return *this;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE static QT3DSMat44 createIdentity()
+ {
+ return QT3DSMat44(QT3DSVec4(1.0f, 0.0f, 0.0f, 0.0f), QT3DSVec4(0.0f, 1.0f, 0.0f, 0.0f),
+ QT3DSVec4(0.0f, 0.0f, 1.0f, 0.0f), QT3DSVec4(0.0f, 0.0f, 0.0f, 1.0f));
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE static QT3DSMat44 createZero()
+ {
+ return QT3DSMat44(QT3DSVec4(0.0f), QT3DSVec4(0.0f), QT3DSVec4(0.0f), QT3DSVec4(0.0f));
+ }
+
+ //! Get transposed matrix
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 getTranspose() const
+ {
+ return QT3DSMat44(QT3DSVec4(column0.x, column1.x, column2.x, column3.x),
+ QT3DSVec4(column0.y, column1.y, column2.y, column3.y),
+ QT3DSVec4(column0.z, column1.z, column2.z, column3.z),
+ QT3DSVec4(column0.w, column1.w, column2.w, column3.w));
+ }
+
+ //! Unary minus
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 operator-() const
+ {
+ return QT3DSMat44(-column0, -column1, -column2, -column3);
+ }
+
+ //! Add
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 operator+(const QT3DSMat44 &other) const
+ {
+ return QT3DSMat44(column0 + other.column0, column1 + other.column1, column2 + other.column2,
+ column3 + other.column3);
+ }
+
+ //! Subtract
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 operator-(const QT3DSMat44 &other) const
+ {
+ return QT3DSMat44(column0 - other.column0, column1 - other.column1, column2 - other.column2,
+ column3 - other.column3);
+ }
+
+ //! Scalar multiplication
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 operator*(NVReal scalar) const
+ {
+ return QT3DSMat44(column0 * scalar, column1 * scalar, column2 * scalar, column3 * scalar);
+ }
+
+ friend QT3DSMat44 operator*(NVReal, const QT3DSMat44 &);
+
+ //! Matrix multiplication
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 operator*(const QT3DSMat44 &other) const
+ {
+ // Rows from this <dot> columns from other
+ // column0 = transform(other.column0) etc
+ return QT3DSMat44(transform(other.column0), transform(other.column1), transform(other.column2),
+ transform(other.column3));
+ }
+
+ // a <op>= b operators
+
+ //! Equals-add
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 &operator+=(const QT3DSMat44 &other)
+ {
+ column0 += other.column0;
+ column1 += other.column1;
+ column2 += other.column2;
+ column3 += other.column3;
+ return *this;
+ }
+
+ //! Equals-sub
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 &operator-=(const QT3DSMat44 &other)
+ {
+ column0 -= other.column0;
+ column1 -= other.column1;
+ column2 -= other.column2;
+ column3 -= other.column3;
+ return *this;
+ }
+
+ //! Equals scalar multiplication
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 &operator*=(NVReal scalar)
+ {
+ column0 *= scalar;
+ column1 *= scalar;
+ column2 *= scalar;
+ column3 *= scalar;
+ return *this;
+ }
+
+ //! Element access, mathematical way!
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal operator()(unsigned int row, unsigned int col) const
+ {
+ return (*this)[col][row];
+ }
+
+ //! Element access, mathematical way!
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal &operator()(unsigned int row, unsigned int col)
+ {
+ return (*this)[col][row];
+ }
+
+ //! Transform vector by matrix, equal to v' = M*v
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 transform(const QT3DSVec4 &other) const
+ {
+ return column0 * other.x + column1 * other.y + column2 * other.z + column3 * other.w;
+ }
+
+ //! Transform vector by matrix, equal to v' = M*v
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 transform(const QT3DSVec3 &other) const
+ {
+ return transform(QT3DSVec4(other, 1)).getXYZ();
+ }
+
+ //! Rotate vector by matrix, equal to v' = M*v
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 rotate(const QT3DSVec4 &other) const
+ {
+ return column0 * other.x + column1 * other.y + column2 * other.z; // + column3*0;
+ }
+
+ //! Rotate vector by matrix, equal to v' = M*v
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 rotate(const QT3DSVec3 &other) const
+ {
+ return rotate(QT3DSVec4(other, 1)).getXYZ();
+ }
+
+ /**
+* Shamelessly pulled from gl-matrix.js
+ * Rotates a matrix by the given angle around the specified axis
+*
+* @param angle Angle (in radians) to rotate
+* @param axis vec3 representing the axis to rotate around
+*/
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool rotate(QT3DSF32 angleRadians, QT3DSVec3 axis)
+ {
+ QT3DSF32 x = axis[0], y = axis[1], z = axis[2], len = x * x + y * y + z * z, s, c, t, a00, a01,
+ a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, b00, b01, b02, b10, b11, b12, b20,
+ b21, b22;
+
+ if (!len) {
+ return false;
+ }
+ if (len != 1.0f) {
+ len = 1 / (NVSqrt(len));
+ x *= len;
+ y *= len;
+ z *= len;
+ }
+
+ s = NVSin(angleRadians);
+ c = NVCos(angleRadians);
+ t = 1 - c;
+
+ QT3DSF32 *dataPtr(front());
+
+// inverse algorithm was written for row-major matrixes.
+#define mat(idx) dataPtr[idx]
+
+ a00 = mat(0);
+ a01 = mat(1);
+ a02 = mat(2);
+ a03 = mat(3);
+ a10 = mat(4);
+ a11 = mat(5);
+ a12 = mat(6);
+ a13 = mat(7);
+ a20 = mat(8);
+ a21 = mat(9);
+ a22 = mat(10);
+ a23 = mat(11);
+#undef mat
+
+ // Construct the elements of the rotation matrix
+ b00 = x * x * t + c;
+ b01 = y * x * t + z * s;
+ b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s;
+ b11 = y * y * t + c;
+ b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s;
+ b21 = y * z * t - x * s;
+ b22 = z * z * t + c;
+
+// Perform rotation-specific matrix multiplication
+
+#define dest(idx) dataPtr[idx]
+
+ dest(0) = a00 * b00 + a10 * b01 + a20 * b02;
+ dest(1) = a01 * b00 + a11 * b01 + a21 * b02;
+ dest(2) = a02 * b00 + a12 * b01 + a22 * b02;
+ dest(3) = a03 * b00 + a13 * b01 + a23 * b02;
+
+ dest(4) = a00 * b10 + a10 * b11 + a20 * b12;
+ dest(5) = a01 * b10 + a11 * b11 + a21 * b12;
+ dest(6) = a02 * b10 + a12 * b11 + a22 * b12;
+ dest(7) = a03 * b10 + a13 * b11 + a23 * b12;
+
+ dest(8) = a00 * b20 + a10 * b21 + a20 * b22;
+ dest(9) = a01 * b20 + a11 * b21 + a21 * b22;
+ dest(10) = a02 * b20 + a12 * b21 + a22 * b22;
+ dest(11) = a03 * b20 + a13 * b21 + a23 * b22;
+
+#undef dest
+
+ return true;
+ };
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 getBasis(int num) const
+ {
+ QT3DS_ASSERT(num >= 0 && num < 3);
+ return (&column0)[num].getXYZ();
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 getPosition() const { return column3.getXYZ(); }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE void setPosition(const QT3DSVec3 &position)
+ {
+ column3.x = position.x;
+ column3.y = position.y;
+ column3.z = position.z;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal *front() { return &column0.x; }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const NVReal *front() const { return &column0.x; }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec4 &operator[](int num) { return (&column0)[num]; }
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const QT3DSVec4 &operator[](int num) const
+ {
+ return (&column0)[num];
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE void scale(const QT3DSVec4 &p)
+ {
+ column0 *= p.x;
+ column1 *= p.y;
+ column2 *= p.z;
+ column3 *= p.w;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 inverseRT(void) const
+ {
+ QT3DSVec3 r0(column0.x, column1.x, column2.x), r1(column0.y, column1.y, column2.y),
+ r2(column0.z, column1.z, column2.z);
+
+ return QT3DSMat44(r0, r1, r2, -(r0 * column3.x + r1 * column3.y + r2 * column3.z));
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat44 getInverse(void) const
+ {
+ // inverse algorithm was written for row-major matrixes.
+ const QT3DSF32 *myPtr(front());
+#define mat(idx) myPtr[idx]
+
+ QT3DSF32 a00 = mat(0), a01 = mat(1), a02 = mat(2), a03 = mat(3), a10 = mat(4), a11 = mat(5),
+ a12 = mat(6), a13 = mat(7), a20 = mat(8), a21 = mat(9), a22 = mat(10), a23 = mat(11),
+ a30 = mat(12), a31 = mat(13), a32 = mat(14), a33 = mat(15),
+#undef mat
+
+ b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32,
+
+ d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06), invDet;
+
+ // Calculate the determinant
+ if (!d) {
+ QT3DS_ASSERT(false);
+ return QT3DSMat44::createIdentity();
+ }
+ invDet = 1 / d;
+
+ QT3DSMat44 retval;
+ QT3DSF32 *destPtr = retval.front();
+
+#define dest(idx) destPtr[idx]
+ dest(0) = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
+ dest(1) = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
+ dest(2) = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
+ dest(3) = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
+ dest(4) = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
+ dest(5) = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
+ dest(6) = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
+ dest(7) = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
+ dest(8) = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
+ dest(9) = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
+ dest(10) = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
+ dest(11) = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
+ dest(12) = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
+ dest(13) = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
+ dest(14) = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
+ dest(15) = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
+#undef dest
+
+ return retval;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool isFinite() const
+ {
+ return column0.isFinite() && column1.isFinite() && column2.isFinite() && column3.isFinite();
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 getUpper3x3() const
+ {
+ return QT3DSMat33(column0.getXYZ(), column1.getXYZ(), column2.getXYZ());
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSMat33 getUpper3x3InverseTranspose() const
+ {
+ return getUpper3x3().getInverse().getTranspose();
+ }
+
+ // Data, see above for format!
+
+ QT3DSVec4 column0, column1, column2, column3; // the four base vectors
+};
+
+// implementation from Qt3DSTransform.h
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform::NVTransform(const QT3DSMat44 &m)
+{
+ QT3DSVec3 column0 = QT3DSVec3(m.column0.x, m.column0.y, m.column0.z);
+ QT3DSVec3 column1 = QT3DSVec3(m.column1.x, m.column1.y, m.column1.z);
+ QT3DSVec3 column2 = QT3DSVec3(m.column2.x, m.column2.y, m.column2.z);
+
+ q = QT3DSQuat(QT3DSMat33(column0, column1, column2));
+ p = QT3DSVec3(m.column3.x, m.column3.y, m.column3.z);
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_MAT44_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMath.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMath.h
new file mode 100644
index 00000000..931852e7
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMath.h
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_MATH_H
+#define QT3DS_FOUNDATION_QT3DS_MATH_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include <math.h>
+#include <float.h>
+#include <stdlib.h>
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSAssert.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+// constants
+static const NVReal NVPi = NVReal(3.141592653589793);
+static const NVReal NVHalfPi = NVReal(1.57079632679489661923);
+static const NVReal NVTwoPi = NVReal(6.28318530717958647692);
+static const NVReal NVInvPi = NVReal(0.31830988618379067154);
+
+/**
+\brief The return value is the greater of the two specified values.
+*/
+template <class T>
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE T NVMax(T a, T b)
+{
+ return a < b ? b : a;
+}
+
+//! overload for float to use fsel on xbox
+template <>
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float NVMax(float a, float b)
+{
+ return intrinsics::selectMax(a, b);
+}
+
+/**
+\brief The return value is the lesser of the two specified values.
+*/
+template <class T>
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE T NVMin(T a, T b)
+{
+ return a < b ? a : b;
+}
+
+template <>
+//! overload for float to use fsel on xbox
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float NVMin(float a, float b)
+{
+ return intrinsics::selectMin(a, b);
+}
+
+/*
+Many of these are just implemented as QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE calls to the C lib right now,
+but later we could replace some of them with some approximations or more
+clever stuff.
+*/
+
+/**
+\brief abs returns the absolute value of its argument.
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVAbs(QT3DSF32 a)
+{
+ return intrinsics::abs(a);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVEquals(QT3DSF32 a, QT3DSF32 b, QT3DSF32 epsilon)
+{
+ return (NVAbs(a - b) < epsilon);
+}
+
+/**
+\brief abs returns the absolute value of its argument.
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVAbs(QT3DSF64 a)
+{
+ return ::fabs(a);
+}
+
+/**
+\brief abs returns the absolute value of its argument.
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSI32 NVAbs(QT3DSI32 a)
+{
+ return ::abs(a);
+}
+
+/**
+\brief Clamps v to the range [hi,lo]
+*/
+template <class T>
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE T NVClamp(T v, T lo, T hi)
+{
+ QT3DS_ASSERT(lo <= hi);
+ return NVMin(hi, NVMax(lo, v));
+}
+
+//! \brief Square root.
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVSqrt(QT3DSF32 a)
+{
+ return intrinsics::sqrt(a);
+}
+
+//! \brief Square root.
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVSqrt(QT3DSF64 a)
+{
+ return ::sqrt(a);
+}
+
+//! \brief reciprocal square root.
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVRecipSqrt(QT3DSF32 a)
+{
+ return intrinsics::recipSqrt(a);
+}
+
+//! \brief reciprocal square root.
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVRecipSqrt(QT3DSF64 a)
+{
+ return 1 / ::sqrt(a);
+}
+
+//!trigonometry -- all angles are in radians.
+
+//! \brief Sine of an angle ( <b>Unit:</b> Radians )
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVSin(QT3DSF32 a)
+{
+ return intrinsics::sin(a);
+}
+
+//! \brief Sine of an angle ( <b>Unit:</b> Radians )
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVSin(QT3DSF64 a)
+{
+ return ::sin(a);
+}
+
+//! \brief Cosine of an angle (<b>Unit:</b> Radians)
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVCos(QT3DSF32 a)
+{
+ return intrinsics::cos(a);
+}
+
+//! \brief Cosine of an angle (<b>Unit:</b> Radians)
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVCos(QT3DSF64 a)
+{
+ return ::cos(a);
+}
+
+/**
+\brief Tangent of an angle.
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVTan(QT3DSF32 a)
+{
+ return QT3DSF32(::tan(a));
+}
+
+/**
+\brief Tangent of an angle.
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVTan(QT3DSF64 a)
+{
+ return ::tan(a);
+}
+
+/**
+\brief Arcsine.
+Returns angle between -PI/2 and PI/2 in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVAsin(QT3DSF32 f)
+{
+ return QT3DSF32(::asin(NVClamp(f, -1.0f, 1.0f)));
+}
+
+/**
+\brief Arcsine.
+Returns angle between -PI/2 and PI/2 in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVAsin(QT3DSF64 f)
+{
+ return ::asin(NVClamp(f, -1.0, 1.0));
+}
+
+/**
+\brief Arccosine.
+Returns angle between 0 and PI in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVAcos(QT3DSF32 f)
+{
+ return QT3DSF32(::acos(NVClamp(f, -1.0f, 1.0f)));
+}
+
+/**
+\brief Arccosine.
+Returns angle between 0 and PI in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVAcos(QT3DSF64 f)
+{
+ return ::acos(NVClamp(f, -1.0, 1.0));
+}
+
+/**
+\brief ArcTangent.
+Returns angle between -PI/2 and PI/2 in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVAtan(QT3DSF32 a)
+{
+ return QT3DSF32(::atan(a));
+}
+
+/**
+\brief ArcTangent.
+Returns angle between -PI/2 and PI/2 in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVAtan(QT3DSF64 a)
+{
+ return ::atan(a);
+}
+
+/**
+\brief Arctangent of (x/y) with correct sign.
+Returns angle between -PI and PI in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVAtan2(QT3DSF32 x, QT3DSF32 y)
+{
+ return QT3DSF32(::atan2(x, y));
+}
+
+/**
+\brief Arctangent of (x/y) with correct sign.
+Returns angle between -PI and PI in radians
+<b>Unit:</b> Radians
+*/
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 NVAtan2(QT3DSF64 x, QT3DSF64 y)
+{
+ return ::atan2(x, y);
+}
+
+//! \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc.
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVIsFinite(QT3DSF32 f)
+{
+ return intrinsics::isFinite(f);
+}
+
+//! \brief returns true if the passed number is a finite floating point number as opposed to INF, NAN, etc.
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVIsFinite(QT3DSF64 f)
+{
+ return intrinsics::isFinite(f);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVFloor(QT3DSF32 a)
+{
+ return ::floorf(a);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVExp(QT3DSF32 a)
+{
+ return ::expf(a);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVCeil(QT3DSF32 a)
+{
+ return ::ceilf(a);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVSign(QT3DSF32 a)
+{
+ return qt3ds::intrinsics::sign(a);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 NVPow(QT3DSF32 x, QT3DSF32 y)
+{
+ return ::powf(x, y);
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_MATH_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMathUtils.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMathUtils.h
new file mode 100644
index 00000000..b98488b1
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMathUtils.h
@@ -0,0 +1,569 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSMATHUTILS_H
+#define QT3DS_FOUNDATION_PSMATHUTILS_H
+
+#include "foundation/Qt3DSTransform.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include <stdlib.h>
+
+// General guideline is: if it's an abstract math function, it belongs here.
+// If it's a math function where the inputs have specific semantics (e.g.
+// separateSwingTwist) it doesn't.
+
+namespace qt3ds {
+namespace foundation {
+ using namespace intrinsics;
+ /**
+ \brief sign returns the sign of its argument. The sign of zero is undefined.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 sign(const QT3DSF32 a) { return sign(a); }
+
+ /**
+ \brief sign returns the sign of its argument. The sign of zero is undefined.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 sign(const QT3DSF64 a) { return (a >= 0.0) ? 1.0 : -1.0; }
+
+ /**
+ \brief sign returns the sign of its argument. The sign of zero is undefined.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSI32 sign(const QT3DSI32 a) { return (a >= 0) ? 1 : -1; }
+
+ /**
+ \brief Returns true if the two numbers are within eps of each other.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool equals(const QT3DSF32 a, const QT3DSF32 b, const QT3DSF32 eps)
+ {
+ return (NVAbs(a - b) < eps);
+ }
+
+ /**
+ \brief Returns true if the two numbers are within eps of each other.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool equals(const QT3DSF64 a, const QT3DSF64 b, const QT3DSF64 eps)
+ {
+ return (NVAbs(a - b) < eps);
+ }
+
+ /**
+ \brief The floor function returns a floating-point value representing the largest integer that
+ is less than or equal to x.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 floor(const QT3DSF32 a) { return floatFloor(a); }
+
+ /**
+ \brief The floor function returns a floating-point value representing the largest integer that
+ is less than or equal to x.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 floor(const QT3DSF64 a) { return ::floor(a); }
+
+ /**
+ \brief The ceil function returns a single value representing the smallest integer that is
+ greater than or equal to x.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 ceil(const QT3DSF32 a) { return ::ceilf(a); }
+
+ /**
+ \brief The ceil function returns a double value representing the smallest integer that is
+ greater than or equal to x.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 ceil(const QT3DSF64 a) { return ::ceil(a); }
+
+ /**
+ \brief mod returns the floating-point remainder of x / y.
+
+ If the value of y is 0.0, mod returns a quiet NaN.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 mod(const QT3DSF32 x, const QT3DSF32 y)
+ {
+ return (QT3DSF32)::fmod(x, y);
+ }
+
+ /**
+ \brief mod returns the floating-point remainder of x / y.
+
+ If the value of y is 0.0, mod returns a quiet NaN.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 mod(const QT3DSF64 x, const QT3DSF64 y)
+ {
+ return ::fmod(x, y);
+ }
+
+ /**
+ \brief Square.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 sqr(const QT3DSF32 a) { return a * a; }
+
+ /**
+ \brief Square.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 sqr(const QT3DSF64 a) { return a * a; }
+
+ /**
+ \brief Calculates x raised to the power of y.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 pow(const QT3DSF32 x, const QT3DSF32 y)
+ {
+ return ::powf(x, y);
+ }
+
+ /**
+ \brief Calculates x raised to the power of y.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 pow(const QT3DSF64 x, const QT3DSF64 y) { return ::pow(x, y); }
+
+ /**
+ \brief Calculates e^n
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 exp(const QT3DSF32 a) { return QT3DSF32(::exp(a)); }
+ /**
+
+ \brief Calculates e^n
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 exp(const QT3DSF64 a) { return ::exp(a); }
+
+ /**
+ \brief Calculates logarithms.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 logE(const QT3DSF32 a) { return QT3DSF32(::log(a)); }
+
+ /**
+ \brief Calculates logarithms.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 logE(const QT3DSF64 a) { return ::log(a); }
+
+ /**
+ \brief Calculates logarithms.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 log2(const QT3DSF32 a)
+ {
+ return QT3DSF32(::log(a)) / 0.693147180559945309417f;
+ }
+
+ /**
+ \brief Calculates logarithms.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 log2(const QT3DSF64 a)
+ {
+ return ::log(a) / 0.693147180559945309417;
+ }
+
+ /**
+ \brief Calculates logarithms.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 log10(const QT3DSF32 a) { return (QT3DSF32)::log10(a); }
+
+ /**
+ \brief Calculates logarithms.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 log10(const QT3DSF64 a) { return ::log10(a); }
+
+ /**
+ \brief Converts degrees to radians.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 degToRad(const QT3DSF32 a)
+ {
+ return (QT3DSF32)0.01745329251994329547 * a;
+ }
+
+ /**
+ \brief Converts degrees to radians.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 degToRad(const QT3DSF64 a)
+ {
+ return (QT3DSF64)0.01745329251994329547 * a;
+ }
+
+ /**
+ \brief Converts radians to degrees.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 radToDeg(const QT3DSF32 a)
+ {
+ return (QT3DSF32)57.29577951308232286465 * a;
+ }
+
+ /**
+ \brief Converts radians to degrees.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF64 radToDeg(const QT3DSF64 a)
+ {
+ return (QT3DSF64)57.29577951308232286465 * a;
+ }
+
+ //! \brief compute sine and cosine at the same time. There is a 'fsincos' on PC that we probably want to use here
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void sincos(const QT3DSF32 radians, QT3DSF32 &sin, QT3DSF32 &cos)
+ {
+ /* something like:
+ _asm fld Local
+ _asm fsincos
+ _asm fstp LocalCos
+ _asm fstp LocalSin
+ */
+ sin = NVSin(radians);
+ cos = NVCos(radians);
+ }
+
+ /**
+ \brief uniform random number in [a,b]
+ */
+ QT3DS_FORCE_INLINE QT3DSI32 rand(const QT3DSI32 a, const QT3DSI32 b)
+ {
+ return a + (QT3DSI32)(::rand() % (b - a + 1));
+ }
+
+ /**
+ \brief uniform random number in [a,b]
+ */
+ QT3DS_FORCE_INLINE QT3DSF32 rand(const QT3DSF32 a, const QT3DSF32 b)
+ {
+ return a + (b - a) * ::rand() / RAND_MAX;
+ }
+
+ //! \brief return angle between two vectors in radians
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSF32 angle(const QT3DSVec3 &v0, const QT3DSVec3 &v1)
+ {
+ const QT3DSF32 cos = v0.dot(v1); // |v0|*|v1|*Cos(Angle)
+ const QT3DSF32 sin = (v0.cross(v1)).magnitude(); // |v0|*|v1|*Sin(Angle)
+ return NVAtan2(sin, cos);
+ }
+
+ //! If possible use instead fsel on the dot product /*fsel(d.dot(p),onething,anotherthing);*/
+ //! Compares orientations (more readable, user-friendly function)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool sameDirection(const QT3DSVec3 &d, const QT3DSVec3 &p)
+ {
+ return d.dot(p) >= 0.0f;
+ }
+
+ //! Checks 2 values have different signs
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE IntBool differentSign(NVReal f0, NVReal f1)
+ {
+ union {
+ QT3DSU32 u;
+ NVReal f;
+ } u1, u2;
+ u1.f = f0;
+ u2.f = f1;
+ return (u1.u ^ u2.u) & QT3DS_SIGN_BITMASK;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSMat33 star(const QT3DSVec3 &v)
+ {
+ return QT3DSMat33(QT3DSVec3(0, v.z, -v.y), QT3DSVec3(-v.z, 0, v.x), QT3DSVec3(v.y, -v.x, 0));
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 log(const QT3DSQuat &q)
+ {
+ const NVReal s = q.getImaginaryPart().magnitude();
+ if (s < 1e-12)
+ return QT3DSVec3(0.0f);
+ // force the half-angle to have magnitude <= pi/2
+ NVReal halfAngle = q.w < 0 ? NVAtan2(-s, -q.w) : NVAtan2(s, q.w);
+ QT3DS_ASSERT(halfAngle >= -NVPi / 2 && halfAngle <= NVPi / 2);
+
+ return q.getImaginaryPart().getNormalized() * 2 * halfAngle;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat exp(const QT3DSVec3 &v)
+ {
+ const NVReal m = v.magnitudeSquared();
+ return m < 1e-24 ? QT3DSQuat::createIdentity() : QT3DSQuat(NVSqrt(m), v * NVRecipSqrt(m));
+ }
+
+ // quat to rotate v0 t0 v1
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat rotationArc(const QT3DSVec3 &v0, const QT3DSVec3 &v1)
+ {
+ const QT3DSVec3 cross = v0.cross(v1);
+ const NVReal d = v0.dot(v1);
+ if (d <= -0.99999f)
+ return (NVAbs(v0.x) < 0.1f ? QT3DSQuat(0.0f, v0.z, -v0.y, 0.0f)
+ : QT3DSQuat(v0.y, -v0.x, 0.0, 0.0))
+ .getNormalized();
+
+ const NVReal s = NVSqrt((1 + d) * 2), r = 1 / s;
+
+ return QT3DSQuat(cross.x * r, cross.y * r, cross.z * r, s * 0.5f).getNormalized();
+ }
+
+ //! Computes the maximum delta to another transform
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal maxComponentDelta(const NVTransform &t0,
+ const NVTransform &t1)
+ {
+ NVReal delta = NVAbs(t0.p.x - t1.p.x);
+ delta = NVMax(delta, NVAbs(t0.p.y - t1.p.y));
+ delta = NVMax(delta, NVAbs(t0.p.z - t1.p.z));
+ delta = NVMax(delta, NVAbs(t0.q.x - t1.q.x));
+ delta = NVMax(delta, NVAbs(t0.q.y - t1.q.y));
+ delta = NVMax(delta, NVAbs(t0.q.z - t1.q.z));
+ delta = NVMax(delta, NVAbs(t0.q.w - t1.q.w));
+
+ return delta;
+ }
+
+ /**
+ \brief returns largest axis
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSU32 largestAxis(const QT3DSVec3 &v)
+ {
+ QT3DSU32 m = v.y > v.x ? 1 : 0;
+ return v.z > v[m] ? 2 : m;
+ }
+
+ /**
+ \brief returns axis with smallest absolute value
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSU32 closestAxis(const QT3DSVec3 &v)
+ {
+ QT3DSU32 m = NVAbs(v.y) > NVAbs(v.x) ? 1 : 0;
+ return NVAbs(v.z) > NVAbs(v[m]) ? 2 : m;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSU32 closestAxis(const QT3DSVec3 &v, QT3DSU32 &j, QT3DSU32 &k)
+ {
+ // find largest 2D plane projection
+ const QT3DSF32 absNV = NVAbs(v.x);
+ const QT3DSF32 absNy = NVAbs(v.y);
+ const QT3DSF32 absNz = NVAbs(v.z);
+
+ QT3DSU32 m = 0; // x biggest axis
+ j = 1;
+ k = 2;
+ if (absNy > absNV && absNy > absNz) {
+ // y biggest
+ j = 2;
+ k = 0;
+ m = 1;
+ } else if (absNz > absNV) {
+ // z biggest
+ j = 0;
+ k = 1;
+ m = 2;
+ }
+ return m;
+ }
+
+ /*!
+ Extend an edge along its length by a factor
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void makeFatEdge(QT3DSVec3 &p0, QT3DSVec3 &p1, NVReal fatCoeff)
+ {
+ QT3DSVec3 delta = p1 - p0;
+
+ const NVReal m = delta.magnitude();
+ if (m > 0.0f) {
+ delta *= fatCoeff / m;
+ p0 -= delta;
+ p1 += delta;
+ }
+ }
+
+ //! Compute point as combination of barycentric coordinates
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 computeBarycentricPoint(const QT3DSVec3 &p0,
+ const QT3DSVec3 &p1,
+ const QT3DSVec3 &p2, NVReal u,
+ NVReal v)
+ {
+ // This seems to confuse the compiler...
+ // return (1.0f - u - v)*p0 + u*p1 + v*p2;
+ const QT3DSF32 w = 1.0f - u - v;
+ return QT3DSVec3(w * p0.x + u * p1.x + v * p2.x, w * p0.y + u * p1.y + v * p2.y,
+ w * p0.z + u * p1.z + v * p2.z);
+ }
+
+ // generates a pair of quaternions (swing, twist) such that in = swing * twist, with
+ // swing.x = 0
+ // twist.y = twist.z = 0, and twist is a unit quat
+ QT3DS_FORCE_INLINE void separateSwingTwist(const QT3DSQuat &q, QT3DSQuat &swing, QT3DSQuat &twist)
+ {
+ twist = q.x != 0.0f ? QT3DSQuat(q.x, 0, 0, q.w).getNormalized() : QT3DSQuat::createIdentity();
+ swing = q * twist.getConjugate();
+ }
+
+ // generate two tangent vectors to a given normal
+ QT3DS_FORCE_INLINE void normalToTangents(const QT3DSVec3 &normal, QT3DSVec3 &tangent0, QT3DSVec3 &tangent1)
+ {
+ tangent0 = NVAbs(normal.x) < 0.70710678f ? QT3DSVec3(0, -normal.z, normal.y)
+ : QT3DSVec3(-normal.y, normal.x, 0);
+ tangent0.normalize();
+ tangent1 = normal.cross(tangent0);
+ }
+
+ // todo: what is this function doing?
+ QT3DS_FOUNDATION_API QT3DSQuat computeQuatFromNormal(const QT3DSVec3 &n);
+
+ /**
+ \brief computes a oriented bounding box around the scaled basis.
+ \param basis Input = skewed basis, Output = (normalized) orthogonal basis.
+ \return Bounding box extent.
+ */
+ QT3DS_FOUNDATION_API QT3DSVec3 optimizeBoundingBox(QT3DSMat33 &basis);
+
+ QT3DS_FOUNDATION_API QT3DSQuat slerp(const NVReal t, const QT3DSQuat &left, const QT3DSQuat &right);
+
+ QT3DS_INLINE QT3DSVec3 ellipseClamp(const QT3DSVec3 &point, const QT3DSVec3 &radii)
+ {
+ // This function need to be implemented in the header file because
+ // it is included in a spu shader program.
+
+ // finds the closest point on the ellipse to a given point
+
+ // (p.y, p.z) is the input point
+ // (e.y, e.z) are the radii of the ellipse
+
+ // lagrange multiplier method with Newton/Halley hybrid root-finder.
+ // see http://www.geometrictools.com/Documentation/DistancePointToEllipse2.pdf
+ // for proof of Newton step robustness and initial estimate.
+ // Halley converges much faster but sometimes overshoots - when that happens we take
+ // a newton step instead
+
+ // converges in 1-2 iterations where D&C works well, and it's good with 4 iterations
+ // with any ellipse that isn't completely crazy
+
+ const QT3DSU32 MAX_ITERATIONS = 20;
+ const NVReal convergenceThreshold = 1e-4f;
+
+ // iteration requires first quadrant but we recover generality later
+
+ QT3DSVec3 q(0, NVAbs(point.y), NVAbs(point.z));
+ const NVReal tinyEps =
+ (NVReal)(1e-6f); // very close to minor axis is numerically problematic but trivial
+ if (radii.y >= radii.z) {
+ if (q.z < tinyEps)
+ return QT3DSVec3(0, point.y > 0 ? radii.y : -radii.y, 0);
+ } else {
+ if (q.y < tinyEps)
+ return QT3DSVec3(0, 0, point.z > 0 ? radii.z : -radii.z);
+ }
+
+ QT3DSVec3 denom, e2 = radii.multiply(radii), eq = radii.multiply(q);
+
+ // we can use any initial guess which is > maximum(-e.y^2,-e.z^2) and for which f(t) is > 0.
+ // this guess works well near the axes, but is weak along the diagonals.
+
+ NVReal t = NVMax(eq.y - e2.y, eq.z - e2.z);
+
+ for (QT3DSU32 i = 0; i < MAX_ITERATIONS; i++) {
+ denom = QT3DSVec3(0, 1 / (t + e2.y), 1 / (t + e2.z));
+ QT3DSVec3 denom2 = eq.multiply(denom);
+
+ QT3DSVec3 fv = denom2.multiply(denom2);
+ NVReal f = fv.y + fv.z - 1;
+
+ // although in exact arithmetic we are guaranteed f>0, we can get here
+ // on the first iteration via catastrophic cancellation if the point is
+ // very close to the origin. In that case we just behave as if f=0
+
+ if (f < convergenceThreshold)
+ return e2.multiply(point).multiply(denom);
+
+ NVReal df = fv.dot(denom) * -2.0f;
+ t = t - f / df;
+ }
+
+ // we didn't converge, so clamp what we have
+ QT3DSVec3 r = e2.multiply(point).multiply(denom);
+ return r * NVRecipSqrt(sqr(r.y / radii.y) + sqr(r.z / radii.z));
+ }
+
+ QT3DS_INLINE NVReal tanHalf(NVReal sin, NVReal cos) { return sin / (1 + cos); }
+
+ QT3DS_INLINE QT3DSQuat quatFromTanQVector(const QT3DSVec3 &v)
+ {
+ NVReal v2 = v.dot(v);
+ if (v2 < 1e-12f)
+ return QT3DSQuat::createIdentity();
+ NVReal d = 1 / (1 + v2);
+ return QT3DSQuat(v.x * 2, v.y * 2, v.z * 2, 1 - v2) * d;
+ }
+
+ QT3DS_FORCE_INLINE QT3DSVec3 cross100(const QT3DSVec3 &b) { return QT3DSVec3(0.0f, -b.z, b.y); }
+ QT3DS_FORCE_INLINE QT3DSVec3 cross010(const QT3DSVec3 &b) { return QT3DSVec3(b.z, 0.0f, -b.x); }
+ QT3DS_FORCE_INLINE QT3DSVec3 cross001(const QT3DSVec3 &b) { return QT3DSVec3(-b.y, b.x, 0.0f); }
+
+ QT3DS_INLINE void decomposeVector(QT3DSVec3 &normalCompo, QT3DSVec3 &tangentCompo,
+ const QT3DSVec3 &outwardDir, const QT3DSVec3 &outwardNormal)
+ {
+ normalCompo = outwardNormal * (outwardDir.dot(outwardNormal));
+ tangentCompo = outwardDir - normalCompo;
+ }
+
+ //! \brief Return (i+1)%3
+ // Avoid variable shift for XBox:
+ // QT3DS_INLINE QT3DSU32 NV::getNextIndex3(QT3DSU32 i) { return (1<<i) & 3;
+ // }
+ QT3DS_INLINE QT3DSU32 getNextIndex3(QT3DSU32 i) { return (i + 1 + (i >> 1)) & 3; }
+
+ QT3DS_INLINE QT3DSMat33 rotFrom2Vectors(const QT3DSVec3 &from, const QT3DSVec3 &to)
+ {
+ // See bottom of
+ // http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/index.htm
+
+ // Early exit if to = from
+ if ((from - to).magnitudeSquared() < 1e-4f)
+ return QT3DSMat33::createIdentity();
+
+ // Early exit if to = -from
+ if ((from + to).magnitudeSquared() < 1e-4f)
+ return QT3DSMat33::createDiagonal(QT3DSVec3(1.0f, -1.0f, -1.0f));
+
+ QT3DSVec3 n = from.cross(to);
+
+ NVReal C = from.dot(to), S = NVSqrt(1 - C * C), CC = 1 - C;
+
+ NVReal xx = n.x * n.x, yy = n.y * n.y, zz = n.z * n.z, xy = n.x * n.y, yz = n.y * n.z,
+ xz = n.x * n.z;
+
+ QT3DSMat33 R;
+
+ R(0, 0) = 1 + CC * (xx - 1);
+ R(0, 1) = -n.z * S + CC * xy;
+ R(0, 2) = n.y * S + CC * xz;
+
+ R(1, 0) = n.z * S + CC * xy;
+ R(1, 1) = 1 + CC * (yy - 1);
+ R(1, 2) = -n.x * S + CC * yz;
+
+ R(2, 0) = -n.y * S + CC * xz;
+ R(2, 1) = n.x * S + CC * yz;
+ R(2, 2) = 1 + CC * (zz - 1);
+
+ return R;
+ }
+
+ QT3DS_FOUNDATION_API void integrateTransform(const NVTransform &curTrans, const QT3DSVec3 &linvel,
+ const QT3DSVec3 &angvel, NVReal timeStep,
+ NVTransform &result);
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMemoryBuffer.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMemoryBuffer.h
new file mode 100644
index 00000000..bee2f0c2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMemoryBuffer.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_MEMORYBUFFER_H
+#define QT3DS_FOUNDATION_MEMORYBUFFER_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSIntrinsics.h"
+
+#ifdef __INTEGRITY
+#define __restrict
+#endif
+
+namespace qt3ds {
+namespace foundation {
+ using namespace intrinsics;
+
+ template <typename TAllocator = ForwardingAllocator>
+ class MemoryBuffer : public TAllocator
+ {
+ QT3DSU8 *mBegin;
+ QT3DSU8 *mEnd;
+ QT3DSU8 *mCapacityEnd;
+
+ public:
+ MemoryBuffer(const TAllocator &inAlloc = TAllocator())
+ : TAllocator(inAlloc)
+ , mBegin(0)
+ , mEnd(0)
+ , mCapacityEnd(0)
+ {
+ }
+ ~MemoryBuffer()
+ {
+ if (mBegin)
+ TAllocator::deallocate(mBegin);
+ }
+ QT3DSU32 size() const { return static_cast<QT3DSU32>(mEnd - mBegin); }
+ QT3DSU32 capacity() const { return static_cast<QT3DSU32>(mCapacityEnd - mBegin); }
+ QT3DSU8 *begin() { return mBegin; }
+ QT3DSU8 *end() { return mEnd; }
+ const QT3DSU8 *begin() const { return mBegin; }
+ const QT3DSU8 *end() const { return mEnd; }
+ void clear() { mEnd = mBegin; }
+ void write(QT3DSU8 inValue) { *growBuf(1) = inValue; }
+
+ template <typename TDataType>
+ void write(const TDataType &inValue)
+ {
+ const QT3DSU8 *__restrict readPtr = reinterpret_cast<const QT3DSU8 *>(&inValue);
+ QT3DSU8 *__restrict writePtr = growBuf(sizeof(TDataType));
+ for (QT3DSU32 idx = 0; idx < sizeof(TDataType); ++idx)
+ writePtr[idx] = readPtr[idx];
+ }
+
+ template <typename TDataType>
+ void write(const TDataType *inValue, QT3DSU32 inLength)
+ {
+ using namespace qt3ds::intrinsics;
+ if (inValue && inLength) {
+ QT3DSU32 writeSize = inLength * sizeof(TDataType);
+ memCopy(growBuf(writeSize), inValue, writeSize);
+ }
+ if (inLength && !inValue) {
+ QT3DS_ASSERT(false);
+ // You can't not write something, because that will cause
+ // the receiving end to crash.
+ QT3DSU32 writeSize = inLength * sizeof(TDataType);
+ for (QT3DSU32 idx = 0; idx < writeSize; ++idx)
+ write((QT3DSU8)0);
+ }
+ }
+
+ void writeStrided(const QT3DSU8 *__restrict inData, QT3DSU32 inItemSize, QT3DSU32 inLength,
+ QT3DSU32 inStride)
+ {
+ if (inStride == 0 || inStride == inItemSize)
+ write(inData, inLength * inItemSize);
+ else if (inData && inLength) {
+ QT3DSU32 writeSize = inLength * inItemSize;
+ QT3DSU8 *__restrict writePtr = growBuf(writeSize);
+ for (QT3DSU32 idx = 0; idx < inLength;
+ ++idx, writePtr += inItemSize, inData += inStride)
+ memCopy(writePtr, inData, inItemSize);
+ }
+ }
+ QT3DSU8 *growBuf(QT3DSU32 inAmount)
+ {
+ QT3DSU32 offset = size();
+ QT3DSU32 newSize = offset + inAmount;
+ reserve(newSize);
+ mEnd += inAmount;
+ return mBegin + offset;
+ }
+ void writeZeros(QT3DSU32 inAmount)
+ {
+ QT3DSU32 offset = size();
+ growBuf(inAmount);
+ qt3ds::foundation::memZero(begin() + offset, inAmount);
+ }
+ void align(QT3DSU32 inAmount)
+ {
+ QT3DSU32 leftover = size() % inAmount;
+ if (leftover)
+ writeZeros(inAmount - leftover);
+ }
+ void reserve(QT3DSU32 newSize)
+ {
+ using namespace qt3ds::intrinsics;
+ QT3DSU32 currentSize = size();
+ if (newSize && newSize >= capacity()) {
+ QT3DSU32 newDataSize = newSize * 2;
+ if (newDataSize > 8192)
+ newDataSize = (QT3DSU32)((QT3DSU32)newSize * 1.2f);
+ QT3DSU8 *newData =
+ static_cast<QT3DSU8 *>(TAllocator::allocate(newDataSize, __FILE__, __LINE__));
+ if (mBegin) {
+ memCopy(newData, mBegin, currentSize);
+ TAllocator::deallocate(mBegin);
+ }
+ mBegin = newData;
+ mEnd = mBegin + currentSize;
+ mCapacityEnd = mBegin + newDataSize;
+ }
+ }
+ operator NVDataRef<QT3DSU8>() { return NVDataRef<QT3DSU8>(begin(), size()); }
+ operator NVConstDataRef<QT3DSU8>() const { return NVConstDataRef<QT3DSU8>(begin(), size()); }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMutex.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMutex.h
new file mode 100644
index 00000000..48876230
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSMutex.h
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSMUTEX_H
+#define QT3DS_FOUNDATION_PSMUTEX_H
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSNoCopy.h"
+
+/*
+ * This <new> inclusion is a best known fix for gcc 4.4.1 error:
+ * Creating object file for apex/src/NVAllocator.cpp ...
+ * In file included from apex/include/Qt3DSFoundation.h:30,
+ * from apex/src/NVAllocator.cpp:26:
+ * apex/include/Qt3DSMutex.h: In constructor 'nv::foundation::MutexT<Alloc>::MutexT(const Alloc&)':
+ * apex/include/Qt3DSMutex.h:92: error: no matching function for call to 'operator new(unsigned int,
+ * qt3ds::foundation::MutexImpl*&)'
+ * <built-in>:0: note: candidates are: void* operator new(unsigned int)
+ */
+#include <new>
+
+namespace qt3ds {
+namespace foundation {
+ class QT3DS_FOUNDATION_API MutexImpl
+ {
+ public:
+ /**
+ The constructor for Mutex creates a mutex. It is initially unlocked.
+ */
+ MutexImpl();
+
+ /**
+ The destructor for Mutex deletes the mutex.
+ */
+ ~MutexImpl();
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method blocks until the mutex is
+ unlocked.
+ */
+ bool lock();
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method returns false without blocking.
+ */
+ bool trylock();
+
+ /**
+ Release (unlock) the mutex.
+ */
+ bool unlock();
+
+ /**
+ Size of this class.
+ */
+ static const QT3DSU32 size;
+ };
+
+ class Mutex
+ {
+ public:
+ class ScopedLock : private NoCopy
+ {
+ Mutex &mMutex;
+
+ public:
+ QT3DS_INLINE ScopedLock(Mutex &mutex)
+ : mMutex(mutex)
+ {
+ mMutex.lock();
+ }
+ QT3DS_INLINE ~ScopedLock() { mMutex.unlock(); }
+ };
+
+ /**
+ The constructor for Mutex creates a mutex. It is initially unlocked.
+ */
+ Mutex(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ mImpl = (MutexImpl *)QT3DS_ALLOC(alloc, MutexImpl::size, "MutexImpl");
+ QT3DS_PLACEMENT_NEW(mImpl, MutexImpl)();
+ }
+
+ /**
+ The destructor for Mutex deletes the mutex.
+ */
+ ~Mutex()
+ {
+ mImpl->~MutexImpl();
+ QT3DS_FREE(mAllocator, mImpl);
+ }
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method blocks until the mutex is
+ unlocked.
+ */
+ bool lock() const { return mImpl->lock(); }
+
+ /**
+ Acquire (lock) the mutex. If the mutex is already locked
+ by another thread, this method returns false without blocking.
+ */
+ bool trylock() const { return mImpl->trylock(); }
+
+ /**
+ Release (unlock) the mutex.
+ */
+ bool unlock() const { return mImpl->unlock(); }
+
+ private:
+ NVAllocatorCallback &mAllocator;
+ MutexImpl *mImpl;
+ };
+
+ class QT3DS_FOUNDATION_API ReadWriteLock : private NoCopy
+ {
+ public:
+ ReadWriteLock(NVAllocatorCallback &alloc);
+ ~ReadWriteLock();
+
+ void lockReader();
+ void lockWriter();
+
+ void unlockReader();
+ void unlockWriter();
+
+ private:
+ class ReadWriteLockImpl *mImpl;
+ };
+
+ class ScopedReadLock : private NoCopy
+ {
+ public:
+ QT3DS_INLINE ScopedReadLock(ReadWriteLock &lock)
+ : mLock(lock)
+ {
+ mLock.lockReader();
+ }
+ QT3DS_INLINE ~ScopedReadLock() { mLock.unlockReader(); }
+
+ private:
+ ReadWriteLock &mLock;
+ };
+
+ class ScopedWriteLock : private NoCopy
+ {
+ public:
+ QT3DS_INLINE ScopedWriteLock(ReadWriteLock &lock)
+ : mLock(lock)
+ {
+ mLock.lockWriter();
+ }
+ QT3DS_INLINE ~ScopedWriteLock() { mLock.unlockWriter(); }
+
+ private:
+ ReadWriteLock &mLock;
+ };
+
+/*
+ * Use this type of lock for mutex behaviour that must operate on SPU and PPU
+ * On non-PS3 platforms, it is implemented using Mutex
+ */
+#ifndef QT3DS_PS3
+
+ class AtomicLock : private NoCopy
+ {
+ Mutex mMutex;
+
+ public:
+ AtomicLock(NVAllocatorCallback &alloc)
+ : mMutex(alloc)
+ {
+ }
+
+ bool lock() { return mMutex.lock(); }
+
+ bool trylock() { return mMutex.trylock(); }
+
+ bool unlock() { return mMutex.unlock(); }
+ };
+
+ class AtomicLockCopy
+ {
+ AtomicLock *pLock;
+
+ public:
+ AtomicLockCopy()
+ : pLock(NULL)
+ {
+ }
+
+ AtomicLockCopy &operator=(AtomicLock &lock)
+ {
+ pLock = &lock;
+ return *this;
+ }
+
+ bool lock() { return pLock->lock(); }
+
+ bool trylock() { return pLock->trylock(); }
+
+ bool unlock() { return pLock->unlock(); }
+ };
+#else
+ struct AtomicLockImpl
+ {
+ QT3DS_ALIGN(128, QT3DSU32 m_Lock);
+ QT3DSI32 m_LockId;
+ QT3DSU32 m_LockCount;
+
+ AtomicLockImpl();
+ };
+ class AtomicLock //: private NoCopy
+ {
+ friend class AtomicLockCopy;
+ AtomicLockImpl *m_pImpl;
+
+ public:
+ AtomicLock();
+
+ ~AtomicLock();
+
+ bool lock();
+
+ bool trylock();
+
+ bool unlock();
+ };
+
+ // if an AtomicLock is copied and then the copy goes out of scope, it'll delete the atomic
+ // primitive
+ // (just a 128-byte aligned int) and cause a crash when it tries to delete it again
+ // This class just uses the atomic primitive without releasing it in the end.
+
+ class AtomicLockCopy
+ {
+ AtomicLockImpl *m_pImpl;
+
+ public:
+ AtomicLockCopy()
+ : m_pImpl(NULL)
+ {
+ }
+
+ AtomicLockCopy(const AtomicLock &lock)
+ : m_pImpl(lock.m_pImpl)
+ {
+ }
+
+ ~AtomicLockCopy() {}
+
+ AtomicLockCopy &operator=(const AtomicLock &lock)
+ {
+ m_pImpl = lock.m_pImpl;
+ return *this;
+ }
+
+ bool lock();
+
+ bool trylock();
+
+ bool unlock();
+ };
+#endif
+
+#ifndef QT3DS_PS3
+
+ class AtomicRwLock : private NoCopy
+ {
+ ReadWriteLock m_Lock;
+
+ public:
+ AtomicRwLock(NVAllocatorCallback &alloc)
+ : m_Lock(alloc)
+ {
+ }
+
+ void lockReader() { m_Lock.lockReader(); }
+ void lockWriter() { m_Lock.lockWriter(); }
+
+ bool tryLockReader()
+ {
+ // Todo - implement this
+ m_Lock.lockReader();
+ return true;
+ }
+
+ void unlockReader() { m_Lock.unlockReader(); }
+ void unlockWriter() { m_Lock.unlockWriter(); }
+ };
+#else
+
+ struct AtomicRwLockImpl
+ {
+ QT3DS_ALIGN(128, volatile QT3DSU32 m_Lock);
+ QT3DS_ALIGN(128, volatile QT3DSU32 m_ReadCounter);
+ QT3DSI32 m_LockId;
+ QT3DSU32 m_LockCount;
+
+ AtomicRwLockImpl();
+ };
+
+ class AtomicRwLock : private NoCopy
+ {
+ AtomicRwLockImpl *m_pImpl;
+
+ public:
+ AtomicRwLock();
+
+ ~AtomicRwLock();
+
+ void lockReader();
+
+ bool tryLockReader();
+
+ void lockWriter();
+
+ void unlockReader();
+
+ void unlockWriter();
+ };
+
+#endif
+
+ class ScopedAtomicLock : private NoCopy
+ {
+ QT3DS_INLINE ScopedAtomicLock(AtomicLock &lock)
+ : mLock(lock)
+ {
+ mLock.lock();
+ }
+ QT3DS_INLINE ~ScopedAtomicLock() { mLock.unlock(); }
+
+ private:
+ AtomicLock &mLock;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSNoCopy.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSNoCopy.h
new file mode 100644
index 00000000..817f5e19
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSNoCopy.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSNOCOPY_H
+#define QT3DS_FOUNDATION_PSNOCOPY_H
+
+#include "foundation/Qt3DS.h"
+
+namespace qt3ds {
+namespace foundation {
+ class NoCopy
+ {
+ NoCopy(const NoCopy &c);
+ NoCopy &operator=(const NoCopy &c);
+
+ public:
+ NoCopy() {}
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSOption.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSOption.h
new file mode 100644
index 00000000..18d6c3b2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSOption.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_OPTION_H
+#define QT3DS_FOUNDATION_OPTION_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ struct Empty
+ {
+ };
+
+ template <typename TDataType>
+ class Option
+ {
+ TDataType mData;
+ bool mHasValue;
+
+ public:
+ Option(const TDataType &data)
+ : mData(data)
+ , mHasValue(true)
+ {
+ }
+ Option(const Empty &)
+ : mHasValue(false)
+ {
+ }
+ Option()
+ : mHasValue(false)
+ {
+ }
+ Option(const Option &other)
+ : mData(other.mData)
+ , mHasValue(other.mHasValue)
+ {
+ }
+ Option &operator=(const Option &other)
+ {
+ mData = other.mData;
+ mHasValue = other.mHasValue;
+ return *this;
+ }
+
+ bool isEmpty() const { return !mHasValue; }
+ void setEmpty() { mHasValue = false; }
+ bool hasValue() const { return mHasValue; }
+
+ const TDataType &getValue() const
+ {
+ QT3DS_ASSERT(mHasValue);
+ return mData;
+ }
+ TDataType &getValue()
+ {
+ QT3DS_ASSERT(mHasValue);
+ return mData;
+ }
+ TDataType &unsafeGetValue() { return mData; }
+
+ operator const TDataType &() const { return getValue(); }
+ operator TDataType &() { return getValue(); }
+
+ const TDataType *operator->() const { return &getValue(); }
+ TDataType *operator->() { return &getValue(); }
+
+ const TDataType &operator*() const { return getValue(); }
+ TDataType &operator*() { return getValue(); }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPerfTimer.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPerfTimer.h
new file mode 100644
index 00000000..c63091c0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPerfTimer.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PERFTIMER_H
+#define QT3DS_FOUNDATION_PERFTIMER_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSTime.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ class IPerfTimer : public NVRefCounted
+ {
+ protected:
+ virtual ~IPerfTimer() {}
+ public:
+ // amount is in counter frequency units
+ virtual void Update(const char *inTag, QT3DSU64 inAmount) = 0;
+ // Dump current summation of timer data.
+ virtual void OutputTimerData(QT3DSU32 inFrameCount = 0) = 0;
+ virtual void ResetTimerData() = 0;
+
+ static IPerfTimer &CreatePerfTimer(NVFoundationBase &inFoundation);
+ };
+
+ // Specialize this struct to get the perf timer in different contexts.
+ template <typename TTimerProvider>
+ struct STimerProvider
+ {
+ static IPerfTimer &getPerfTimer(TTimerProvider &inProvider)
+ {
+ return inProvider.getPerfTimer();
+ }
+ };
+
+ template <typename TTimerProvider>
+ IPerfTimer &getPerfTimer(TTimerProvider &inProvider)
+ {
+ return STimerProvider<TTimerProvider>::getPerfTimer(inProvider);
+ }
+
+ struct SStackPerfTimer
+ {
+ IPerfTimer *m_Timer;
+ QT3DSU64 m_Start;
+ const char *m_Id;
+
+ SStackPerfTimer(IPerfTimer &destination, const char *inId)
+ : m_Timer(&destination)
+ , m_Start(Time::getCurrentCounterValue())
+ , m_Id(inId)
+ {
+ }
+
+ SStackPerfTimer(IPerfTimer *destination, const char *inId)
+ : m_Timer(destination)
+ , m_Start(Time::getCurrentCounterValue())
+ , m_Id(inId)
+ {
+ }
+
+ ~SStackPerfTimer()
+ {
+ if (m_Timer) {
+ QT3DSU64 theStop = Time::getCurrentCounterValue();
+ QT3DSU64 theAmount = theStop - m_Start;
+ m_Timer->Update(m_Id, theAmount);
+ }
+ }
+ };
+}
+}
+
+#define QT3DS_FOUNDATION_PERF_SCOPED_TIMER(context, name) \
+ SStackPerfTimer __perfTimer(getPerfTimer(context), #name);
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPlane.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPlane.h
new file mode 100644
index 00000000..378c3bc9
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPlane.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_PLANE_H
+#define QT3DS_FOUNDATION_QT3DS_PLANE_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSMath.h"
+#include "foundation/Qt3DSVec3.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/**
+\brief Representation of a plane.
+
+ Plane equation used: n.dot(v) + d = 0
+*/
+class NVPlane
+{
+public:
+ /**
+ \brief Constructor
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane() {}
+
+ /**
+ \brief Constructor from a normal and a distance
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane(NVReal nx, NVReal ny, NVReal nz, NVReal distance)
+ : n(nx, ny, nz)
+ , d(distance)
+ {
+ }
+
+ /**
+ \brief Constructor from a normal and a distance
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane(const QT3DSVec3 &normal, NVReal distance)
+ : n(normal)
+ , d(distance)
+ {
+ }
+
+ /**
+ \brief Constructor from a point on the plane and a normal
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane(const QT3DSVec3 &point, const QT3DSVec3 &normal)
+ : n(normal)
+ , d(-point.dot(n)) // p satisfies normal.dot(p) + d = 0
+ {
+ }
+
+ /**
+ \brief Constructor from three points
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane(const QT3DSVec3 &p0, const QT3DSVec3 &p1, const QT3DSVec3 &p2)
+ {
+ n = (p1 - p0).cross(p2 - p0).getNormalized();
+ d = -p0.dot(n);
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal distance(const QT3DSVec3 &p) const { return p.dot(n) + d; }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool contains(const QT3DSVec3 &p) const
+ {
+ return NVAbs(distance(p)) < (1.0e-7f);
+ }
+
+ /**
+ \brief projects p into the plane
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 project(const QT3DSVec3 &p) const
+ {
+ return p - n * distance(p);
+ }
+
+ /**
+ \brief find an arbitrary point in the plane
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 pointInPlane() const { return -n * d; }
+
+ /**
+ \brief equivalent plane with unit normal
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void normalize()
+ {
+ NVReal denom = 1.0f / n.magnitude();
+ n *= denom;
+ d *= denom;
+ }
+
+ QT3DSVec3 n; //!< The normal to the plane
+ NVReal d; //!< The distance from the origin
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPool.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPool.h
new file mode 100644
index 00000000..5bd07f86
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPool.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_POOL_H
+#define QT3DS_POOL_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSMath.h" //NVMax
+#include "EASTL/vector.h"
+
+namespace qt3ds {
+namespace foundation {
+ // Pool of fixed size objects.
+ template <typename TObjType, typename TAllocator = EASTLAllocatorType,
+ QT3DSU32 alignmentInBytes = 4, QT3DSU32 slabSize = 4096>
+ class Pool
+ {
+ protected:
+ TAllocator mAllocator;
+ struct Link
+ {
+ Link *mNext;
+ Link(Link *next = NULL)
+ : mNext(next)
+ {
+ }
+ };
+ eastl::vector<void *, TAllocator> mSlabs;
+ Link *mFreeList;
+
+ public:
+ Pool(const TAllocator &alloc = TAllocator())
+ : mAllocator(alloc)
+ , mSlabs(alloc)
+ , mFreeList(NULL)
+ {
+ StaticAssert<sizeof(TObjType) < slabSize>::valid_expression();
+ }
+ ~Pool()
+ {
+ for (QT3DSU32 idx = 0, end = mSlabs.size(); idx < end; ++idx)
+ mAllocator.deallocate(mSlabs[idx], slabSize);
+ mSlabs.clear();
+ mFreeList = NULL;
+ }
+ void appendToFreeList(Link *inLink)
+ {
+ inLink->mNext = mFreeList;
+ mFreeList = inLink;
+ }
+ void appendSlabToFreeList(void *slab)
+ {
+ QT3DSU8 *newMem = reinterpret_cast<QT3DSU8 *>(slab);
+ QT3DSU32 objSize = (QT3DSU32)qt3ds::NVMax(sizeof(TObjType), sizeof(Link));
+ // align the memory correctly
+ if (objSize % alignmentInBytes)
+ objSize += alignmentInBytes - (objSize % alignmentInBytes);
+
+ QT3DSU32 numObjsInSlab = slabSize / objSize;
+ for (QT3DSU32 idx = 0; idx < numObjsInSlab; ++idx) {
+ QT3DSU8 *objPtr = newMem + idx * objSize;
+ appendToFreeList(reinterpret_cast<Link *>(objPtr));
+ }
+ }
+ void allocateSlab(const char *file, int line)
+ {
+ QT3DSU32 objSize = (QT3DSU32)NVMax(sizeof(TObjType), sizeof(Link));
+ // align the memory correctly
+ if (objSize % alignmentInBytes)
+ objSize += alignmentInBytes - (objSize % alignmentInBytes);
+
+ QT3DSU8 *newMem = (QT3DSU8 *)mAllocator.allocate(slabSize, file, line);
+ if (newMem == NULL)
+ return; // out of mem, bad error
+ mSlabs.push_back(newMem);
+ appendSlabToFreeList(newMem);
+ }
+
+ void *allocate(const char *file, int line)
+ {
+ if (!mFreeList)
+ allocateSlab(file, line);
+
+ if (mFreeList) {
+ Link *retval = mFreeList;
+ mFreeList = retval->mNext;
+ return retval;
+ }
+
+ return NULL;
+ }
+
+ void deallocate(void *inPtr)
+ {
+#if _DEBUG
+ // Ensure inPtr came from a known slab.
+ bool found = false;
+ for (QT3DSU32 idx = 0, end = mSlabs.size(); idx < end && !found; ++idx) {
+ QT3DSU8 *slabMem = reinterpret_cast<QT3DSU8 *>(mSlabs[idx]);
+ QT3DSU8 *slabEnd = slabMem + slabSize;
+ QT3DSU8 *memPtr = reinterpret_cast<QT3DSU8 *>(inPtr);
+
+ if (memPtr >= mSlabs[idx] && memPtr < slabEnd)
+ found = true;
+ }
+ QT3DS_ASSERT(found);
+#endif
+ appendToFreeList(reinterpret_cast<Link *>(inPtr));
+ }
+
+ template <typename TArg1, typename TArg2>
+ TObjType *construct(const TArg1 &arg1, const TArg2 &arg2, const char *file, int line)
+ {
+ TObjType *newMem = (TObjType *)allocate(file, line);
+ return new (newMem) TObjType(arg1, arg2);
+ }
+
+ template <typename TArg1>
+ TObjType *construct(const TArg1 &arg1, const char *file, int line)
+ {
+ TObjType *newMem = (TObjType *)allocate(file, line);
+ return new (newMem) TObjType(arg1);
+ }
+
+ TObjType *construct(const char *file, int line)
+ {
+ TObjType *newMem = (TObjType *)allocate(file, line);
+ return new (newMem) TObjType();
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPreprocessor.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPreprocessor.h
new file mode 100644
index 00000000..2fd7680d
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSPreprocessor.h
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_PREPROCESSOR_H
+#define QT3DS_FOUNDATION_QT3DS_PREPROCESSOR_H
+
+#include <stddef.h>
+/** \addtogroup foundation
+ @{
+*/
+
+/**
+List of preprocessor defines used to configure the SDK
+- NDEBUG/_DEBUG: enable asserts (exactly one needs to be defined)
+- QT3DS_CHECKED: enable run time checks, mostly unused or equiv. to _DEBUG
+- QT3DS_SUPPORT_VISUAL_DEBUGGER: ...
+- AG_PERFMON: ...
+*/
+
+/**
+Compiler define
+*/
+#ifdef _MSC_VER
+#define QT3DS_VC
+#if _MSC_VER >= 1600
+#define QT3DS_VC10
+#elif _MSC_VER >= 1500
+#define QT3DS_VC9
+#elif _MSC_VER >= 1400
+#define QT3DS_VC8
+#elif _MSC_VER >= 1300
+#define QT3DS_VC7
+#else
+#define QT3DS_VC6
+#endif
+#elif __GNUC__ || __SNC__
+#define QT3DS_GNUC
+#elif defined(__MWERKS__)
+#define QT3DS_CW
+#elif defined(__ghs__)
+#define QT3DS_GHS
+#else
+#error "Unknown compiler"
+#endif
+
+/**
+Platform define
+*/
+#ifdef QT3DS_VC
+#ifdef _M_IX86
+#define QT3DS_X86
+#define QT3DS_WINDOWS
+#elif defined(_M_X64)
+#define QT3DS_X64
+#define QT3DS_WINDOWS
+#elif defined(_M_PPC)
+#define QT3DS_PPC
+#define QT3DS_X360
+#define QT3DS_VMX
+#elif defined(_M_ARM)
+#define QT3DS_ARM
+#define QT3DS_WIN8ARM
+#define QT3DS_ARM_NEON
+#else
+#error "Unknown platform"
+#endif
+#elif defined QT3DS_GNUC
+#ifdef __CELLOS_LV2__
+#define QT3DS_PS3
+#define QT3DS_VMX
+#elif defined(__arm__)
+#define QT3DS_ARM
+#if defined(__SNC__)
+#define QT3DS_PSP2
+#endif
+#if defined(__ARM_PCS_VFP)
+#define QT3DS_ARM_HARDFP
+#else
+#define QT3DS_ARM_SOFTFP
+#endif
+#elif defined(__aarch64__)
+#define QT3DS_ARM
+#elif defined(__i386__)
+#define QT3DS_X86
+#define QT3DS_VMX
+#elif defined(__x86_64__)
+#define QT3DS_X64
+#elif defined(__ppc__)
+#define QT3DS_PPC
+#elif defined(__ppc64__)
+#define QT3DS_PPC
+#define QT3DS_PPC64
+//# elif defined(__aarch64__)
+//# define QT3DS_ARM_64
+#else
+#error "Unknown platform"
+#endif
+#if defined(ANDROID)
+#define QT3DS_ANDROID
+#elif defined(__linux__)
+#define QT3DS_LINUX
+#elif defined(__APPLE__)
+#define QT3DS_APPLE
+#if defined(__arm__)
+#define QT3DS_APPLE_IOS
+#endif
+#elif defined(__CYGWIN__)
+#define QT3DS_CYGWIN
+#define QT3DS_LINUX
+#elif defined(__QNX__)
+#define QT3DS_QNX
+#else
+#error "Unkown OS"
+#endif
+#elif defined QT3DS_CW
+#if defined(__PPCGEKKO__)
+#if defined(RVL)
+#define QT3DS_WII
+#else
+#define QT3DS_GC
+#endif
+#else
+#error "Unknown platform"
+#endif
+#elif defined QT3DS_GHS
+#define QT3DS_LINUX // INTEGRITY deviations flagged with __INTEGRITY
+#if defined(__arm__) || defined(__aarch64__) || defined(__ARM64__)
+#define QT3DS_ARM
+#endif
+#endif
+
+/**
+DLL export macros
+*/
+#ifndef QT3DS_C_EXPORT
+#define QT3DS_C_EXPORT extern "C"
+#endif
+
+/**
+Define API function declaration
+
+QT3DS_FOUNDATION_EXPORTS - used by the DLL library (PhysXCommon) to export the API
+QT3DS_FOUNDATION_NO_EXPORTS - exists because there are windows configurations where
+ the QT3DS_FOUNDATION_API is linked through standard
+static linking
+no definition - this will allow DLLs and libraries to use the exported API from PhysXCommon
+
+*/
+#if defined(QT3DS_WINDOWS) && !defined(__CUDACC__)
+#if defined QT3DS_FOUNDATION_EXPORTS
+#define QT3DS_FOUNDATION_API __declspec(dllexport)
+#elif defined QT3DS_FOUNDATION_NO_EXPORTS
+#define QT3DS_FOUNDATION_API
+#else
+#define QT3DS_FOUNDATION_API __declspec(dllimport)
+#endif
+#else
+#define QT3DS_FOUNDATION_API
+#endif
+
+/**
+Calling convention
+*/
+#ifndef QT3DS_CALL_CONV
+#if defined QT3DS_WINDOWS
+#define QT3DS_CALL_CONV __cdecl
+#else
+#define QT3DS_CALL_CONV
+#endif
+#endif
+
+/**
+Pack macros - disabled on SPU because they are not supported
+*/
+#if defined(QT3DS_VC)
+#define QT3DS_PUSH_PACK_DEFAULT __pragma(pack(push, 8))
+#define QT3DS_POP_PACK __pragma(pack(pop))
+#elif defined(QT3DS_GNUC) && !defined(__SPU__)
+#define QT3DS_PUSH_PACK_DEFAULT _Pragma("pack(push, 8)")
+#define QT3DS_POP_PACK _Pragma("pack(pop)")
+#else
+#define QT3DS_PUSH_PACK_DEFAULT
+#define QT3DS_POP_PACK
+#endif
+
+/**
+Inline macro
+*/
+#if defined(QT3DS_WINDOWS) || defined(QT3DS_X360)
+#define QT3DS_INLINE inline
+#pragma inline_depth(255)
+#else
+#define QT3DS_INLINE inline
+#endif
+
+/**
+Force inline macro
+*/
+#if defined(QT3DS_VC)
+#define QT3DS_FORCE_INLINE __forceinline
+#elif defined(QT3DS_LINUX) \
+ || defined(QT3DS_QNX) // Workaround; Fedora Core 3 do not agree with force inline and NVcPool
+#define QT3DS_FORCE_INLINE inline
+#elif defined(QT3DS_GNUC)
+#define QT3DS_FORCE_INLINE inline __attribute__((always_inline))
+#else
+#define QT3DS_FORCE_INLINE inline
+#endif
+
+/**
+Noinline macro
+*/
+#if defined QT3DS_WINDOWS
+#define QT3DS_NOINLINE __declspec(noinline)
+#elif defined(QT3DS_GNUC)
+#define QT3DS_NOINLINE __attribute__((noinline))
+#else
+#define QT3DS_NOINLINE
+#endif
+
+/*! restrict macro */
+#if __CUDACC__
+#define QT3DS_RESTRICT __restrict__
+#elif defined(QT3DS_GNUC) || defined(QT3DS_VC)
+#define QT3DS_RESTRICT __restrict
+#elif defined(QT3DS_CW) && __STDC_VERSION__ >= 199901L
+#define QT3DS_RESTRICT restrict
+#else
+#define QT3DS_RESTRICT
+#endif
+
+#if defined(QT3DS_WINDOWS) || defined(QT3DS_X360)
+#define QT3DS_NOALIAS __declspec(noalias)
+#else
+#define QT3DS_NOALIAS
+#endif
+
+/**
+Alignment macros
+
+QT3DS_ALIGN_PREFIX and QT3DS_ALIGN_SUFFIX can be used for type alignment instead of aligning individual
+variables as follows:
+QT3DS_ALIGN_PREFIX(16)
+struct A {
+...
+} QT3DS_ALIGN_SUFFIX(16);
+This declaration style is parsed correctly by Visual Assist.
+
+*/
+#ifndef QT3DS_ALIGN
+#if defined(QT3DS_VC)
+#define QT3DS_ALIGN(alignment, decl) __declspec(align(alignment)) decl
+#define QT3DS_ALIGN_PREFIX(alignment) __declspec(align(alignment))
+#define QT3DS_ALIGN_SUFFIX(alignment)
+#elif defined(QT3DS_GNUC)
+#define QT3DS_ALIGN(alignment, decl) decl __attribute__((aligned(alignment)))
+#define QT3DS_ALIGN_PREFIX(alignment)
+#define QT3DS_ALIGN_SUFFIX(alignment) __attribute__((aligned(alignment)))
+#elif defined(QT3DS_CW)
+#define QT3DS_ALIGN(alignment, decl) decl __attribute__((aligned(alignment)))
+#define QT3DS_ALIGN_PREFIX(alignment)
+#define QT3DS_ALIGN_SUFFIX(alignment) __attribute__((aligned(alignment)))
+#else
+#define QT3DS_ALIGN(alignment, decl)
+#define QT3DS_ALIGN_PREFIX(alignment)
+#define QT3DS_ALIGN_SUFFIX(alignment)
+#endif
+#endif
+
+/**
+Deprecated marco
+*/
+#if 0 // set to 1 to create warnings for deprecated functions
+#define QT3DS_DEPRECATED __declspec(deprecated)
+#else
+#define QT3DS_DEPRECATED
+#endif
+
+// VC6 no '__FUNCTION__' workaround
+#if defined QT3DS_VC6 && !defined __FUNCTION__
+#define __FUNCTION__ "Undefined"
+#endif
+
+/**
+General defines
+*/
+
+// Assertion type
+template <bool b>
+struct StaticAssert
+{
+};
+// Specialisation with member function
+template <>
+struct StaticAssert<true>
+{
+public:
+ static void valid_expression(){}
+};
+
+// static assert
+#define QT3DS_COMPILE_TIME_ASSERT(exp) typedef char NVCompileTimeAssert_Dummy[(exp) ? 1 : -1]
+
+#ifdef QT3DS_GNUC
+#define QT3DS_OFFSET_OF(X, Y) __builtin_offsetof(X, Y)
+#else
+#define QT3DS_OFFSET_OF(X, Y) offsetof(X, Y)
+#endif
+
+// avoid unreferenced parameter warning (why not just disable it?)
+// PT: or why not just omit the parameter's name from the declaration????
+#define QT3DS_FORCE_PARAMETER_REFERENCE(_P) (void)(_P);
+#define QT3DS_UNUSED(_P) QT3DS_FORCE_PARAMETER_REFERENCE(_P)
+
+// check that exactly one of NDEBUG and _DEBUG is defined
+#if !(defined NDEBUG ^ defined _DEBUG)
+#error Exactly one of NDEBUG and _DEBUG needs to be defined by preprocessor
+#endif
+
+// make sure QT3DS_CHECKED is defined in all _DEBUG configurations as well
+#if !defined(QT3DS_CHECKED) && _DEBUG
+#define QT3DS_CHECKED
+#endif
+
+#ifdef __CUDACC__
+#define QT3DS_CUDA_CALLABLE __host__ __device__
+#else
+#define QT3DS_CUDA_CALLABLE
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_PREPROCESSOR_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSQuat.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSQuat.h
new file mode 100644
index 00000000..2792f977
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSQuat.h
@@ -0,0 +1,381 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_QUAT_H
+#define QT3DS_FOUNDATION_QT3DS_QUAT_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSVec3.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/**
+\brief This is a quaternion class. For more information on quaternion mathematics
+consult a mathematics source on complex numbers.
+
+*/
+
+class QT3DSQuat
+{
+public:
+ /**
+ \brief Default constructor, does not do any initialization.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat() {}
+
+ /**
+ \brief Constructor. Take note of the order of the elements!
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat(NVReal nx, NVReal ny, NVReal nz, NVReal nw)
+ : x(nx)
+ , y(ny)
+ , z(nz)
+ , w(nw)
+ {
+ }
+
+ /**
+ \brief Creates from angle-axis representation.
+
+ Axis must be normalized!
+
+ Angle is in radians!
+
+ <b>Unit:</b> Radians
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat(NVReal angleRadians, const QT3DSVec3 &unitAxis)
+ {
+ QT3DS_ASSERT(NVAbs(1.0f - unitAxis.magnitude()) < 1e-3f);
+ const NVReal a = angleRadians * 0.5f;
+ const NVReal s = NVSin(a);
+ w = NVCos(a);
+ x = unitAxis.x * s;
+ y = unitAxis.y * s;
+ z = unitAxis.z * s;
+ }
+
+ /**
+ \brief Copy ctor.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat(const QT3DSQuat &v)
+ : x(v.x)
+ , y(v.y)
+ , z(v.z)
+ , w(v.w)
+ {
+ }
+
+ /**
+ \brief Creates from orientation matrix.
+
+ \param[in] m Rotation matrix to extract quaternion from.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE explicit QT3DSQuat(const QT3DSMat33 &m); /* defined in Qt3DSMat33.h */
+
+ /**
+ \brief returns true if all elements are finite (not NAN or INF, etc.)
+ */
+ QT3DS_CUDA_CALLABLE bool isFinite() const
+ {
+ return NVIsFinite(x) && NVIsFinite(y) && NVIsFinite(z) && NVIsFinite(w);
+ }
+
+ /**
+ \brief returns true if finite and magnitude is close to unit
+ */
+
+ QT3DS_CUDA_CALLABLE bool isUnit() const
+ {
+ const NVReal unitTolerance = NVReal(1e-4);
+ return isFinite() && NVAbs(magnitude() - 1) < unitTolerance;
+ }
+
+ /**
+ \brief returns true if finite and magnitude is reasonably close to unit to allow for some
+ accumulation of error vs isValid
+ */
+
+ QT3DS_CUDA_CALLABLE bool isSane() const
+ {
+ const NVReal unitTolerance = NVReal(1e-2);
+ return isFinite() && NVAbs(magnitude() - 1) < unitTolerance;
+ }
+
+ /**
+ \brief converts this quaternion to angle-axis representation
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE void toRadiansAndUnitAxis(NVReal &angle, QT3DSVec3 &axis) const
+ {
+ const NVReal quatEpsilon = (NVReal(1.0e-8f));
+ const NVReal s2 = x * x + y * y + z * z;
+ if (s2 < quatEpsilon * quatEpsilon) // can't extract a sensible axis
+ {
+ angle = 0;
+ axis = QT3DSVec3(1, 0, 0);
+ } else {
+ const NVReal s = NVRecipSqrt(s2);
+ axis = QT3DSVec3(x, y, z) * s;
+ angle = w < quatEpsilon ? NVPi : NVAtan2(s2 * s, w) * 2;
+ }
+ }
+
+ /**
+ \brief Gets the angle between this quat and the identity quaternion.
+
+ <b>Unit:</b> Radians
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal getAngle() const { return NVAcos(w) * NVReal(2); }
+
+ /**
+ \brief Gets the angle between this quat and the argument
+
+ <b>Unit:</b> Radians
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal getAngle(const QT3DSQuat &q) const
+ {
+ return NVAcos(dot(q)) * NVReal(2);
+ }
+
+ /**
+ \brief This is the squared 4D vector length, should be 1 for unit quaternions.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal magnitudeSquared() const
+ {
+ return x * x + y * y + z * z + w * w;
+ }
+
+ /**
+ \brief returns the scalar product of this and other.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal dot(const QT3DSQuat &v) const
+ {
+ return x * v.x + y * v.y + z * v.z + w * v.w;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat getNormalized() const
+ {
+ const NVReal s = 1.0f / magnitude();
+ return QT3DSQuat(x * s, y * s, z * s, w * s);
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE float magnitude() const { return NVSqrt(magnitudeSquared()); }
+
+ // modifiers:
+ /**
+ \brief maps to the closest unit quaternion.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal normalize() // convert this QT3DSQuat to a unit quaternion
+ {
+ const NVReal mag = magnitude();
+ if (mag) {
+ const NVReal imag = NVReal(1) / mag;
+
+ x *= imag;
+ y *= imag;
+ z *= imag;
+ w *= imag;
+ }
+ return mag;
+ }
+
+ /*
+ \brief returns the conjugate.
+
+ \note for unit quaternions, this is the inverse.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat getConjugate() const { return QT3DSQuat(-x, -y, -z, w); }
+
+ /*
+ \brief returns imaginary part.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 getImaginaryPart() const { return QT3DSVec3(x, y, z); }
+
+ /** brief computes rotation of x-axis */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getBasisVector0() const
+ {
+ // return rotate(QT3DSVec3(1,0,0));
+ const QT3DSF32 x2 = x * 2.0f;
+ const QT3DSF32 w2 = w * 2.0f;
+ return QT3DSVec3((w * w2) - 1.0f + x * x2, (z * w2) + y * x2, (-y * w2) + z * x2);
+ }
+
+ /** brief computes rotation of y-axis */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getBasisVector1() const
+ {
+ // return rotate(QT3DSVec3(0,1,0));
+ const QT3DSF32 y2 = y * 2.0f;
+ const QT3DSF32 w2 = w * 2.0f;
+ return QT3DSVec3((-z * w2) + x * y2, (w * w2) - 1.0f + y * y2, (x * w2) + z * y2);
+ }
+
+ /** brief computes rotation of z-axis */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getBasisVector2() const
+ {
+ // return rotate(QT3DSVec3(0,0,1));
+ const QT3DSF32 z2 = z * 2.0f;
+ const QT3DSF32 w2 = w * 2.0f;
+ return QT3DSVec3((y * w2) + x * z2, (-x * w2) + y * z2, (w * w2) - 1.0f + z * z2);
+ }
+
+ /**
+ rotates passed vec by this (assumed unitary)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const QT3DSVec3 rotate(const QT3DSVec3 &v) const
+ // QT3DS_CUDA_CALLABLE QT3DS_INLINE const QT3DSVec3 rotate(const QT3DSVec3& v) const
+ {
+ const QT3DSF32 vx = 2.0f * v.x;
+ const QT3DSF32 vy = 2.0f * v.y;
+ const QT3DSF32 vz = 2.0f * v.z;
+ const QT3DSF32 w2 = w * w - 0.5f;
+ const QT3DSF32 dot2 = (x * vx + y * vy + z * vz);
+ return QT3DSVec3((vx * w2 + (y * vz - z * vy) * w + x * dot2),
+ (vy * w2 + (z * vx - x * vz) * w + y * dot2),
+ (vz * w2 + (x * vy - y * vx) * w + z * dot2));
+ /*
+ const QT3DSVec3 qv(x,y,z);
+ return (v*(w*w-0.5f) + (qv.cross(v))*w + qv*(qv.dot(v)))*2;
+ */
+ }
+
+ /**
+ inverse rotates passed vec by this (assumed unitary)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const QT3DSVec3 rotateInv(const QT3DSVec3 &v) const
+ // QT3DS_CUDA_CALLABLE QT3DS_INLINE const QT3DSVec3 rotateInv(const QT3DSVec3& v) const
+ {
+ const QT3DSF32 vx = 2.0f * v.x;
+ const QT3DSF32 vy = 2.0f * v.y;
+ const QT3DSF32 vz = 2.0f * v.z;
+ const QT3DSF32 w2 = w * w - 0.5f;
+ const QT3DSF32 dot2 = (x * vx + y * vy + z * vz);
+ return QT3DSVec3((vx * w2 - (y * vz - z * vy) * w + x * dot2),
+ (vy * w2 - (z * vx - x * vz) * w + y * dot2),
+ (vz * w2 - (x * vy - y * vx) * w + z * dot2));
+ // const QT3DSVec3 qv(x,y,z);
+ // return (v*(w*w-0.5f) - (qv.cross(v))*w + qv*(qv.dot(v)))*2;
+ }
+
+ /**
+ \brief Assignment operator
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat &operator=(const QT3DSQuat &p)
+ {
+ x = p.x;
+ y = p.y;
+ z = p.z;
+ w = p.w;
+ return *this;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat &operator*=(const QT3DSQuat &q)
+ {
+ const NVReal tx = w * q.x + q.w * x + y * q.z - q.y * z;
+ const NVReal ty = w * q.y + q.w * y + z * q.x - q.z * x;
+ const NVReal tz = w * q.z + q.w * z + x * q.y - q.x * y;
+
+ w = w * q.w - q.x * x - y * q.y - q.z * z;
+ x = tx;
+ y = ty;
+ z = tz;
+
+ return *this;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat &operator+=(const QT3DSQuat &q)
+ {
+ x += q.x;
+ y += q.y;
+ z += q.z;
+ w += q.w;
+ return *this;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat &operator-=(const QT3DSQuat &q)
+ {
+ x -= q.x;
+ y -= q.y;
+ z -= q.z;
+ w -= q.w;
+ return *this;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat &operator*=(const NVReal s)
+ {
+ x *= s;
+ y *= s;
+ z *= s;
+ w *= s;
+ return *this;
+ }
+
+ /** quaternion multiplication */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat operator*(const QT3DSQuat &q) const
+ {
+ return QT3DSQuat(w * q.x + q.w * x + y * q.z - q.y * z, w * q.y + q.w * y + z * q.x - q.z * x,
+ w * q.z + q.w * z + x * q.y - q.x * y, w * q.w - x * q.x - y * q.y - z * q.z);
+ }
+
+ /** quaternion addition */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat operator+(const QT3DSQuat &q) const
+ {
+ return QT3DSQuat(x + q.x, y + q.y, z + q.z, w + q.w);
+ }
+
+ /** quaternion subtraction */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat operator-() const { return QT3DSQuat(-x, -y, -z, -w); }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat operator-(const QT3DSQuat &q) const
+ {
+ return QT3DSQuat(x - q.x, y - q.y, z - q.z, w - q.w);
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSQuat operator*(NVReal r) const
+ {
+ return QT3DSQuat(x * r, y * r, z * r, w * r);
+ }
+
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSQuat createIdentity() { return QT3DSQuat(0, 0, 0, 1); }
+
+ /** the quaternion elements */
+ NVReal x, y, z, w;
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_QUAT_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSRefCounted.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSRefCounted.h
new file mode 100644
index 00000000..b500b5fc
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSRefCounted.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_REFCOUNTED_H
+#define QT3DS_FOUNDATION_QT3DS_REFCOUNTED_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSNoCopy.h"
+
+namespace qt3ds {
+namespace foundation {
+ /**
+ Marker class for objects that have a release method that is expected
+ to destroy or release the object.
+ */
+ class NVReleasable
+ {
+ protected:
+ virtual ~NVReleasable() {}
+ public:
+ virtual void release() = 0;
+ };
+
+ template <typename TObjType>
+ inline void NVSafeRelease(TObjType *&item)
+ {
+ if (item) {
+ item->release();
+ item = NULL;
+ }
+ }
+
+ /**Scoped pointer that releases its data
+ when it is being destroyed*/
+ template <typename TObjType>
+ struct NVScopedReleasable : public NoCopy
+ {
+ TObjType *mPtr;
+ NVScopedReleasable()
+ : mPtr(NULL)
+ {
+ }
+ NVScopedReleasable(TObjType *item)
+ : mPtr(item)
+ {
+ }
+ NVScopedReleasable(TObjType &item)
+ : mPtr(&item)
+ {
+ }
+ ~NVScopedReleasable() { NVSafeRelease(mPtr); }
+
+ NVScopedReleasable &operator=(TObjType *inItem)
+ {
+ if (inItem != mPtr) {
+ if (mPtr)
+ mPtr->release();
+ mPtr = inItem;
+ }
+ return *this;
+ }
+
+ NVScopedReleasable &operator=(const NVScopedReleasable<TObjType> inItem)
+ {
+ QT3DS_ASSERT(false);
+ // try to do the right thing.
+ mPtr = inItem.mPtr;
+ const_cast<NVScopedReleasable<TObjType> &>(inItem).mPtr = NULL;
+ return *this;
+ }
+
+ TObjType *forget_unsafe()
+ {
+ mPtr = NULL;
+ return mPtr;
+ }
+
+ TObjType *operator->() { return mPtr; }
+ const TObjType *operator->() const { return mPtr; }
+ TObjType &operator*() { return *mPtr; }
+ const TObjType &operator*() const { return *mPtr; }
+ operator TObjType *() { return mPtr; }
+ operator const TObjType *() const { return mPtr; }
+ };
+
+ // Marker class for objects that are ref counted.
+ class NVRefCounted : public NVReleasable
+ {
+ public:
+ virtual void addRef() = 0;
+ };
+
+/**Helpers to make implementing ref counted objects as concise as possible*/
+#define QT3DS_IMPLEMENT_REF_COUNT_RELEASE(alloc) \
+ QT3DSI32 value = atomicDecrement(&mRefCount); \
+ if (value <= 0) \
+ NVDelete(alloc, this);
+
+#define QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(alloc) \
+ void addRef() { atomicIncrement(&mRefCount); } \
+ void release() { QT3DS_IMPLEMENT_REF_COUNT_RELEASE(alloc); }
+
+
+#define QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(alloc) \
+ void addRef() override { atomicIncrement(&mRefCount); } \
+ void release() override { QT3DS_IMPLEMENT_REF_COUNT_RELEASE(alloc); }
+
+ /**Safe function that checks for null before addrefing the object*/
+ template <typename TObjType>
+ inline TObjType *NVSafeAddRef(TObjType *item)
+ {
+ if (item) {
+ item->addRef();
+ }
+ return item;
+ }
+
+ /**Scoped pointer that addref's its data upon acquisition and releases its data
+ when it is being destroyed*/
+ template <typename TObjType>
+ struct NVScopedRefCounted
+ {
+ TObjType *mPtr;
+ ~NVScopedRefCounted() { NVSafeRelease(mPtr); }
+ NVScopedRefCounted(TObjType *item = NULL)
+ : mPtr(item)
+ {
+ NVSafeAddRef(mPtr);
+ }
+ NVScopedRefCounted(TObjType &item)
+ : mPtr(&item)
+ {
+ NVSafeAddRef(mPtr);
+ }
+ NVScopedRefCounted(const NVScopedRefCounted<TObjType> &other)
+ : mPtr(const_cast<TObjType *>(other.mPtr))
+ {
+ NVSafeAddRef(mPtr);
+ }
+ NVScopedRefCounted<TObjType> &operator=(const NVScopedRefCounted<TObjType> &other)
+ {
+ if (other.mPtr != mPtr) {
+ NVSafeRelease(mPtr);
+ mPtr = const_cast<TObjType *>(other.mPtr);
+ NVSafeAddRef(mPtr);
+ }
+ return *this;
+ }
+ TObjType *forget_unsafe()
+ {
+ mPtr = NULL;
+ return mPtr;
+ }
+
+ TObjType *operator->() { return mPtr; }
+ const TObjType *operator->() const { return mPtr; }
+ TObjType &operator*() { return *mPtr; }
+ const TObjType &operator*() const { return *mPtr; }
+ operator TObjType *() { return mPtr; }
+ operator const TObjType *() const { return mPtr; }
+ bool operator==(NVScopedRefCounted<TObjType> &inOther) const
+ {
+ return mPtr == inOther.mPtr;
+ }
+ bool operator!=(NVScopedRefCounted<TObjType> &inOther) const
+ {
+ return mPtr != inOther.mPtr;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSemaphore.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSemaphore.h
new file mode 100644
index 00000000..f58bb6e0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSemaphore.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSSEMAPHORE_H
+#define QT3DS_FOUNDATION_PSSEMAPHORE_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+namespace qt3ds {
+namespace foundation {
+ class QT3DS_FOUNDATION_API Semaphore
+ {
+ public:
+ static const QT3DSU32 waitForever = 0xffffffff;
+
+ Semaphore(NVAllocatorCallback &alloc, QT3DSU32 initialCount, QT3DSU32 maxCount);
+
+ ~Semaphore();
+
+ /**Decrements (locks) the semaphore. If the semaphore's value is greater than zero,
+ * then the decrement proceeds, and the function returns, immediately. Otherwise
+ * Wait for at most the given number of ms. Returns true if the Semaphore is signaled.
+ * Semaphore::waitForever will block forever or until the semaphore is signaled.
+ */
+
+ bool wait(QT3DSU32 milliseconds = waitForever);
+
+ /** increments (unlocks) the semaphore */
+
+ void post();
+
+ private:
+ class SemaphoreImpl *mImpl;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSimpleTypes.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSimpleTypes.h
new file mode 100644
index 00000000..d73be064
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSimpleTypes.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_QT3DS_SIMPLE_TYPES_H
+#define QT3DS_FOUNDATION_QT3DS_SIMPLE_TYPES_H
+
+/** \addtogroup foundation
+ @{
+*/
+
+// Platform specific types:
+// Design note: Its OK to use int for general loop variables and temps.
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSPreprocessor.h"
+#include "EABase/eabase.h"
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif //#ifndef QT3DS_DOXYGEN
+
+typedef uint8_t QT3DSU8;
+typedef int8_t QT3DSI8;
+typedef uint16_t QT3DSU16;
+typedef int16_t QT3DSI16;
+typedef uint32_t QT3DSU32;
+typedef int32_t QT3DSI32;
+typedef uint64_t QT3DSU64;
+typedef int64_t QT3DSI64;
+typedef float QT3DSF32;
+typedef double QT3DSF64;
+typedef QT3DSI32 IntBool;
+
+struct QT3DSF16
+{
+ QT3DSU16 mData;
+};
+
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSI8) == 1);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSU8) == 1);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSI16) == 2);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSU16) == 2);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSI32) == 4);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSU32) == 4);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSI64) == 8);
+QT3DS_COMPILE_TIME_ASSERT(sizeof(QT3DSU64) == 8);
+
+// Type ranges
+#define QT3DS_MAX_I8 127 // maximum possible sbyte value, 0x7f
+#define QT3DS_MIN_I8 (-128) // minimum possible sbyte value, 0x80
+#define QT3DS_MAX_U8 255U // maximum possible ubyte value, 0xff
+#define QT3DS_MIN_U8 0 // minimum possible ubyte value, 0x00
+#define QT3DS_MAX_I16 32767 // maximum possible sword value, 0x7fff
+#define QT3DS_MIN_I16 (-32768) // minimum possible sword value, 0x8000
+#define QT3DS_MAX_U16 65535U // maximum possible uword value, 0xffff
+#define QT3DS_MIN_U16 0 // minimum possible uword value, 0x0000
+#define QT3DS_MAX_I32 2147483647 // maximum possible sdword value, 0x7fffffff
+#define QT3DS_MIN_I32 (-2147483647 - 1) // minimum possible sdword value, 0x80000000
+#define QT3DS_MAX_U32 4294967295U // maximum possible udword value, 0xffffffff
+#define QT3DS_MIN_U32 0 // minimum possible udword value, 0x00000000
+#define QT3DS_MAX_F32 3.4028234663852885981170418348452e+38F
+// maximum possible float value
+#define QT3DS_MAX_F64 DBL_MAX // maximum possible double value
+
+#define QT3DS_ENV_F32 FLT_EPSILON // maximum relative error of float rounding
+#define QT3DS_ENV_F64 DBL_EPSILON // maximum relative error of double rounding
+
+#ifndef QT3DS_FOUNDATION_USE_F64
+
+typedef QT3DSF32 NVReal;
+
+#define QT3DS_MAX_REAL QT3DS_MAX_F32
+#define QT3DS_ENV_REAL QT3DS_ENV_F32
+#define QT3DS_NORMALIZATION_EPSILON NVReal(1e-20f)
+
+#else
+
+typedef QT3DSF64 NVReal;
+
+#define QT3DS_MAX_REAL QT3DS_MAX_F64
+#define QT3DS_ENV_REAL QT3DS_ENV_F64
+#define QT3DS_NORMALIZATION_EPSILON NVReal(1e-180)
+
+#endif
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_SIMPLE_TYPES_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSStringTokenizer.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSStringTokenizer.h
new file mode 100644
index 00000000..5229babd
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSStringTokenizer.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_STRING_TOKENIZER_H
+#define QT3DS_FOUNDATION_STRING_TOKENIZER_H
+
+#include "EASTL/string.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename TStrType>
+ class QT3DS_FOUNDATION_API StringTokenizer
+ {
+ typedef typename eastl::basic_string<TStrType>::size_type size_t;
+
+ public:
+ StringTokenizer(const eastl::basic_string<TStrType> &inString,
+ const eastl::basic_string<TStrType> &inToken)
+ {
+ eastl::basic_string<TStrType> mStr = inString;
+ eastl::basic_string<TStrType> theTempString = inString.substr(0, inToken.length());
+
+ while (inToken.length() && theTempString.compare(inToken) == 0) {
+ mStr = mStr.substr(inToken.length());
+ theTempString = mStr.substr(0, inToken.length());
+ }
+
+ theTempString = mStr.substr(mStr.length() - 1 - inToken.length());
+ while (theTempString.compare(inToken) == 0) {
+ mStr = mStr.substr(0, mStr.length() - inToken.length());
+ theTempString = mStr.substr(mStr.length() - 1 - inToken.length());
+ }
+
+ m_OriginalString = mStr;
+ m_Token = inToken;
+ m_Index = 0;
+ }
+
+ eastl::basic_string<TStrType> GetCurrentPartition()
+ {
+ eastl::basic_string<TStrType> theReturnString;
+ if (m_Index != eastl::basic_string<TStrType>::npos) {
+ size_t theCurrentTokenIndex = m_OriginalString.find(m_Token, m_Index);
+ if (theCurrentTokenIndex == eastl::basic_string<TStrType>::npos) {
+ theReturnString = m_OriginalString.substr(m_Index);
+ } else {
+ theReturnString =
+ m_OriginalString.substr(m_Index, theCurrentTokenIndex - m_Index);
+ }
+ }
+
+ return theReturnString;
+ }
+
+ bool HasNextPartition() { return m_Index != eastl::basic_string<TStrType>::npos; }
+
+ void operator++()
+ {
+ if (m_Index != eastl::basic_string<TStrType>::npos) {
+ size_t theCurrentTokenIndex = m_OriginalString.find(m_Token, m_Index);
+ if (theCurrentTokenIndex == eastl::basic_string<TStrType>::npos) {
+ m_Index = eastl::basic_string<TStrType>::npos;
+ } else {
+ m_Index = theCurrentTokenIndex + m_Token.length();
+ if (m_Index > m_OriginalString.length())
+ m_Index = eastl::basic_string<TStrType>::npos;
+ }
+ }
+ }
+
+ private:
+ size_t m_Index;
+ eastl::basic_string<TStrType> m_Token;
+ eastl::basic_string<TStrType> m_OriginalString;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSync.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSync.h
new file mode 100644
index 00000000..a36afaeb
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSync.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSSYNC_H
+#define QT3DS_FOUNDATION_PSSYNC_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+namespace qt3ds {
+namespace foundation {
+ class QT3DS_FOUNDATION_API Sync
+ {
+ public:
+ static const QT3DSU32 waitForever = 0xffffffff;
+
+ Sync(NVAllocatorCallback &alloc);
+
+ ~Sync();
+
+ /** Wait on the object for at most the given number of ms. Returns
+ * true if the object is signaled. Sync::waitForever will block forever
+ * or until the object is signaled.
+ */
+
+ bool wait(QT3DSU32 milliseconds = waitForever);
+
+ /** Signal the synchronization object, waking all threads waiting on it */
+
+ void set();
+
+ /** Reset the synchronization object */
+
+ void reset();
+
+ private:
+ class SyncImpl *mImpl;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSystem.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSystem.h
new file mode 100644
index 00000000..84ca87d1
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSSystem.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef QT3DS_FOUNDATION_SYSTEM_H
+#define QT3DS_FOUNDATION_SYSTEM_H
+
+#include "foundation/Qt3DS.h"
+
+namespace qt3ds {
+namespace foundation {
+ class QT3DS_FOUNDATION_API System
+ {
+ public:
+ static const char *g_OS;
+ static const char *g_Processor;
+ static const char *g_BitWidth;
+ static const char *g_FloatingPointModel;
+ static const char *g_GPUType;
+ static const char *g_DLLExtension;
+ static const char *getPlatformStr();
+ static const char *getPlatformGLStr();
+
+ private:
+ System();
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSThread.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSThread.h
new file mode 100644
index 00000000..84e169d6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSThread.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSTHREAD_H
+#define QT3DS_FOUNDATION_PSTHREAD_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSFoundation.h"
+
+// dsequeira: according to existing comment here (David Black would be my guess)
+// "This is useful to reduce bus contention on tight spin locks. And it needs
+// to be a macro as the xenon compiler often ignores even __forceinline." What's not
+// clear is why a pause function needs inlining...? (TODO: check with XBox team)
+
+// todo: these need to go somewhere else
+
+#if defined(QT3DS_WINDOWS)
+#define NVSpinLockPause() __asm pause
+#elif defined(QT3DS_X360)
+#define NVSpinLockPause() __asm nop
+#elif defined(QT3DS_LINUX) || defined(QT3DS_ANDROID) || defined(QT3DS_APPLE) || defined(QT3DS_QNX)
+#define NVSpinLockPause() asm("nop")
+#elif defined(QT3DS_PS3)
+#define NVSpinLockPause() asm("nop") // don't know if it's correct yet...
+#define QT3DS_TLS_MAX_SLOTS 64
+#elif defined(QT3DS_WII)
+#define NVSpinLockPause() asm { nop } // don't know if it's correct yet...
+#endif
+
+namespace qt3ds {
+namespace foundation {
+ struct ThreadPriority // todo: put in some other header file
+ {
+ enum Enum {
+ /**
+ \brief High priority
+ */
+ eHIGH = 0,
+
+ /**
+ \brief Above Normal priority
+ */
+ eABOVE_NORMAL = 1,
+
+ /**
+ \brief Normal/default priority
+ */
+ eNORMAL = 2,
+
+ /**
+ \brief Below Normal priority
+ */
+ eBELOW_NORMAL = 3,
+
+ /**
+ \brief Low priority.
+ */
+ eLOW = 4,
+
+ eFORCE_DWORD = 0xffFFffFF
+ };
+ };
+
+ /**
+ Thread abstraction API
+ */
+
+ class QT3DS_FOUNDATION_API Thread
+ {
+ public:
+ static const QT3DSU32 DEFAULT_STACK_SIZE;
+ typedef size_t Id; // space for a pointer or an integer
+ typedef void *(*ExecuteFn)(void *);
+
+ static Id getId();
+
+ /**
+ Construct (but do not start) the thread object. Executes in the context
+ of the spawning thread
+ */
+
+ Thread(NVFoundationBase &foundation);
+
+ /**
+ Construct and start the the thread, passing the given arg to the given fn. (pthread style)
+ */
+
+ Thread(NVFoundationBase &foundation, ExecuteFn fn, void *arg);
+
+ /**
+ Deallocate all resources associated with the thread. Should be called in the
+ context of the spawning thread.
+ */
+
+ virtual ~Thread();
+
+ /**
+ start the thread running. Called in the context of the spawning thread.
+ */
+
+ void start(QT3DSU32 stackSize);
+
+ /**
+ Violently kill the current thread. Blunt instrument, not recommended since
+ it can leave all kinds of things unreleased (stack, memory, mutexes...) Should
+ be called in the context of the spawning thread.
+ */
+
+ void kill();
+
+ /**
+ The virtual execute() method is the user defined function that will
+ run in the new thread. Called in the context of the spawned thread.
+ */
+
+ virtual void execute(void);
+
+ /**
+ stop the thread. Signals the spawned thread that it should stop, so the
+ thread should check regularly
+ */
+
+ void signalQuit();
+
+ /**
+ Wait for a thread to stop. Should be called in the context of the spawning
+ thread. Returns false if the thread has not been started.
+ */
+
+ bool waitForQuit();
+
+ /**
+ check whether the thread is signalled to quit. Called in the context of the
+ spawned thread.
+ */
+
+ bool quitIsSignalled();
+
+ /**
+ Cleanly shut down this thread. Called in the context of the spawned thread.
+ */
+ void quit();
+
+ /**
+ Change the affinity mask for this thread.
+ On Xbox360, sets the hardware thread to the first non-zero bit.
+
+ Returns previous mask if successful, or zero on failure
+ */
+ virtual QT3DSU32 setAffinityMask(QT3DSU32 mask);
+
+ static ThreadPriority::Enum getPriority(Id threadId);
+
+ /** Set thread priority. */
+ void setPriority(ThreadPriority::Enum prio);
+
+ /** set the thread's name */
+ void setName(const char *name);
+
+ /** Put the current thread to sleep for the given number of milliseconds */
+ static void sleep(QT3DSU32 ms);
+
+ /** Yield the current thread's slot on the CPU */
+ static void yield();
+
+ private:
+ class ThreadImpl *mImpl;
+ };
+
+ QT3DS_FOUNDATION_API QT3DSU32 TlsAlloc();
+ QT3DS_FOUNDATION_API void TlsFree(QT3DSU32 index);
+ QT3DS_FOUNDATION_API void *TlsGet(QT3DSU32 index);
+ QT3DS_FOUNDATION_API QT3DSU32 TlsSet(QT3DSU32 index, void *value);
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTime.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTime.h
new file mode 100644
index 00000000..955bd7e0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTime.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSTIME_H
+#define QT3DS_FOUNDATION_PSTIME_H
+
+#include "foundation/Qt3DS.h"
+
+#if defined(QT3DS_LINUX) || defined(QT3DS_ANDROID) || defined(QT3DS_QNX)
+#include <time.h>
+#endif
+
+namespace qt3ds {
+namespace foundation {
+
+ struct CounterFrequencyToTensOfNanos
+ {
+ QT3DSU64 mNumerator;
+ QT3DSU64 mDenominator;
+ CounterFrequencyToTensOfNanos(QT3DSU64 inNum, QT3DSU64 inDenom)
+ : mNumerator(inNum)
+ , mDenominator(inDenom)
+ {
+ }
+
+ // quite slow.
+ QT3DSU64 toTensOfNanos(QT3DSU64 inCounter) const
+ {
+ return (inCounter * mNumerator) / mDenominator;
+ }
+ };
+
+ class QT3DS_FOUNDATION_API Time
+ {
+ public:
+ typedef double Second;
+ static const QT3DSU64 sNumTensOfNanoSecondsInASecond = 100000000;
+ // This is supposedly guaranteed to not change after system boot
+ // regardless of processors, speedstep, etc.
+ static const CounterFrequencyToTensOfNanos sCounterFreq;
+
+ static CounterFrequencyToTensOfNanos getCounterFrequency();
+
+ static QT3DSU64 getCurrentCounterValue();
+
+ // SLOW!!
+ // Thar be a 64 bit divide in thar!
+ static QT3DSU64 getCurrentTimeInTensOfNanoSeconds()
+ {
+ QT3DSU64 ticks = getCurrentCounterValue();
+ return sCounterFreq.toTensOfNanos(ticks);
+ }
+
+ Time();
+ Second getElapsedSeconds();
+ Second peekElapsedSeconds();
+ Second getLastTime() const;
+
+ private:
+#if defined(QT3DS_LINUX) || defined(QT3DS_ANDROID) || defined(QT3DS_APPLE) || defined(QT3DS_PSP2) \
+ || defined(QT3DS_QNX)
+ Second mLastTime;
+#else
+ QT3DSI64 mTickCount;
+#endif
+ };
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTransform.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTransform.h
new file mode 100644
index 00000000..0fee0a81
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSTransform.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_TRANSFORM_H
+#define QT3DS_FOUNDATION_QT3DS_TRANSFORM_H
+/** \addtogroup foundation
+ @{
+*/
+
+#include "foundation/Qt3DSQuat.h"
+#include "foundation/Qt3DSPlane.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/*!
+\brief class representing a rigid euclidean transform as a quaternion and a vector
+*/
+
+class NVTransform
+{
+public:
+ QT3DSQuat q;
+ QT3DSVec3 p;
+
+ //#define PXTRANSFORM_DEFAULT_CONSTRUCT_NAN
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform()
+#ifdef PXTRANSFORM_DEFAULT_CONSTRUCT_IDENTITY
+ : q(0, 0, 0, 1)
+ , p(0, 0, 0)
+#elif defined(PXTRANSFORM_DEFAULT_CONSTRUCT_NAN)
+#define invalid NVSqrt(-1.0f)
+ : q(invalid, invalid, invalid, invalid)
+ , p(invalid, invalid, invalid)
+#undef invalid
+#endif
+ {
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE explicit NVTransform(const QT3DSVec3 &position)
+ : q(0, 0, 0, 1)
+ , p(position)
+ {
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE explicit NVTransform(const QT3DSQuat &orientation)
+ : q(orientation)
+ , p(0, 0, 0)
+ {
+ QT3DS_ASSERT(orientation.isSane());
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform(const QT3DSVec3 &p0, const QT3DSQuat &q0)
+ : q(q0)
+ , p(p0)
+ {
+ QT3DS_ASSERT(q0.isSane());
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE explicit NVTransform(const QT3DSMat44 &m); // defined in Qt3DSMat44.h
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform operator*(const NVTransform &x) const
+ {
+ QT3DS_ASSERT(x.isSane());
+ return transform(x);
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform getInverse() const
+ {
+ QT3DS_ASSERT(isFinite());
+ return NVTransform(q.rotateInv(-p), q.getConjugate());
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 transform(const QT3DSVec3 &input) const
+ {
+ QT3DS_ASSERT(isFinite());
+ return q.rotate(input) + p;
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 transformInv(const QT3DSVec3 &input) const
+ {
+ QT3DS_ASSERT(isFinite());
+ return q.rotateInv(input - p);
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 rotate(const QT3DSVec3 &input) const
+ {
+ QT3DS_ASSERT(isFinite());
+ return q.rotate(input);
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 rotateInv(const QT3DSVec3 &input) const
+ {
+ QT3DS_ASSERT(isFinite());
+ return q.rotateInv(input);
+ }
+
+ //! Transform transform to parent (returns compound transform: first src, then *this)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform transform(const NVTransform &src) const
+ {
+ QT3DS_ASSERT(src.isSane());
+ QT3DS_ASSERT(isSane());
+ // src = [srct, srcr] -> [r*srct + t, r*srcr]
+ return NVTransform(q.rotate(src.p) + p, q * src.q);
+ }
+
+ /**
+ \brief returns true if finite and q is a unit quaternion
+ */
+
+ QT3DS_CUDA_CALLABLE bool isValid() const { return p.isFinite() && q.isFinite() && q.isUnit(); }
+
+ /**
+ \brief returns true if finite and quat magnitude is reasonably close to unit to allow for some
+ accumulation of error vs isValid
+ */
+
+ QT3DS_CUDA_CALLABLE bool isSane() const { return isFinite() && q.isSane(); }
+
+ /**
+ \brief returns true if all elems are finite (not NAN or INF, etc.)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite() const { return p.isFinite() && q.isFinite(); }
+
+ //! Transform transform from parent (returns compound transform: first src, then this->inverse)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVTransform transformInv(const NVTransform &src) const
+ {
+ QT3DS_ASSERT(src.isSane());
+ QT3DS_ASSERT(isFinite());
+ // src = [srct, srcr] -> [r^-1*(srct-t), r^-1*srcr]
+ QT3DSQuat qinv = q.getConjugate();
+ return NVTransform(qinv.rotate(src.p - p), qinv * src.q);
+ }
+
+ QT3DS_CUDA_CALLABLE static QT3DS_FORCE_INLINE NVTransform createIdentity()
+ {
+ return NVTransform(QT3DSVec3(0));
+ }
+
+ /**
+ \brief transform plane
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane transform(const NVPlane &plane) const
+ {
+ QT3DSVec3 transformedNormal = rotate(plane.n);
+ return NVPlane(transformedNormal, plane.d - p.dot(transformedNormal));
+ }
+
+ /**
+ \brief inverse-transform plane
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVPlane inverseTransform(const NVPlane &plane) const
+ {
+ QT3DSVec3 transformedNormal = rotateInv(plane.n);
+ return NVPlane(transformedNormal, plane.d + p.dot(plane.n));
+ }
+};
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_TRANSFORM_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUnionCast.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUnionCast.h
new file mode 100644
index 00000000..a3d03555
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUnionCast.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_UNION_CAST_H
+#define QT3DS_FOUNDATION_QT3DS_UNION_CAST_H
+
+#include "foundation/Qt3DSPreprocessor.h"
+
+/** \addtogroup foundation
+@{
+*/
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+template <class A, class B>
+QT3DS_FORCE_INLINE A NVUnionCast(B b)
+{
+ union AB {
+ AB(B bb)
+ : _b(bb)
+ {
+ }
+ B _b;
+ A _a;
+ } u(b);
+ return u._a;
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUtilities.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUtilities.h
new file mode 100644
index 00000000..cb9ae6a2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSUtilities.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_PSUTILITIES_H
+#define QT3DS_FOUNDATION_PSUTILITIES_H
+
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSIntrinsics.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ // PT: checked casts
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSU16 to16(QT3DSU32 value)
+ {
+ QT3DS_ASSERT(value <= 0xffff);
+ return QT3DSU16(value);
+ }
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSU8 to8(QT3DSU16 value)
+ {
+ QT3DS_ASSERT(value <= 0xff);
+ return QT3DSU8(value);
+ }
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSU8 to8(QT3DSU32 value)
+ {
+ QT3DS_ASSERT(value <= 0xff);
+ return QT3DSU8(value);
+ }
+
+ template <class T>
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE void swap(T &x, T &y)
+ {
+// crash with optimizations enabled, ticket in Sony
+#ifdef QT3DS_PSP2
+#pragma control % push O = 0
+#endif
+ T tmp = x;
+ x = y;
+ y = tmp;
+#ifdef QT3DS_PSP2
+#pragma control % pop O
+#endif
+ }
+
+ /*!
+Get number of elements in array
+*/
+ template <typename T, size_t N>
+ char (&ArraySizeHelper(T (&array)[N]))[N];
+#define QT3DS_ARRAY_SIZE(_array) (sizeof(qt3ds::foundation::ArraySizeHelper(_array)))
+
+ /*!
+Sort two elements using operator<
+
+On return x will be the smaller of the two
+*/
+ template <class T>
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void order(T &x, T &y)
+ {
+ if (y < x)
+ swap(x, y);
+ }
+
+ // most architectures can do predication on real comparisons, and on VMX, it matters
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void order(NVReal &x, NVReal &y)
+ {
+ NVReal newX = NVMin(x, y);
+ NVReal newY = NVMax(x, y);
+ x = newX;
+ y = newY;
+ }
+
+ /*!
+ Sort two elements using operator< and also keep order
+ of any extra data
+ */
+ template <class T, class E1>
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void order(T &x, T &y, E1 &xe1, E1 &ye1)
+ {
+ if (y < x) {
+ swap(x, y);
+ swap(xe1, ye1);
+ }
+ }
+
+ QT3DS_INLINE void debugBreak()
+ {
+#if defined(QT3DS_WINDOWS)
+ __debugbreak();
+#elif defined(QT3DS_LINUX) || defined(QT3DS_ANDROID) || defined(QT3DS_QNX)
+ asm("int $3");
+#elif defined(QT3DS_GNUC)
+ __builtin_trap();
+#else
+ QT3DS_ASSERT(false);
+#endif
+ }
+
+ bool checkValid(const float &);
+ bool checkValid(const QT3DSVec3 &);
+ bool checkValid(const QT3DSQuat &);
+ bool checkValid(const QT3DSMat33 &);
+ bool checkValid(const NVTransform &);
+ bool checkValid(const char *);
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSI32 getPadding2(size_t value, QT3DSU32 alignment)
+ {
+ const QT3DSI32 mask = alignment - 1;
+ const QT3DSI32 overhead = QT3DSI32(value) & mask;
+ return (alignment - overhead) & mask;
+ }
+
+ // PT: "After doing a dcbz128, there is a delay of about 140 cycles before writes to that cache
+ // line can proceed without stalling.
+ // This is much faster than an L2 cache miss, but for ideal performance, it is best to avoid
+ // this stall by doing the cache-line
+ // zeroing a few cache lines ahead of where you are writing."
+ QT3DS_FORCE_INLINE void invalidateCache(void *QT3DS_RESTRICT voidPtr, QT3DSI32 size)
+ {
+#ifdef QT3DS_X360
+ QT3DSU8 *QT3DS_RESTRICT ptr = reinterpret_cast<QT3DSU8 *>(voidPtr);
+ const QT3DSI32 padding = getPadding2(size_t(ptr), 128);
+ const QT3DSI32 sizeToCover = size - padding;
+ if (sizeToCover >= 128) {
+ QT3DSU8 *ptr128 = ptr + padding;
+ QT3DSU32 nb128 = sizeToCover / 128;
+ while (nb128--) {
+ // NV::memZero128(ptr128);
+ qt3ds::foundation::memZero128(ptr128);
+ ptr128 += 128;
+ }
+ }
+#else
+ (void)voidPtr;
+ (void)size;
+#endif
+ }
+
+ // equivalent to std::max_element
+ template <typename T>
+ inline const T *maxElement(const T *first, const T *last)
+ {
+ const T *m = first;
+ for (const T *it = first + 1; it < last; ++it)
+ if (*m < *it)
+ m = it;
+
+ return m;
+ }
+
+} // namespace foundation
+} // namespace qt3ds
+
+#define QT3DS_STRINGIZE_HELPER(X) #X
+#define QT3DS_STRINGIZE(X) QT3DS_STRINGIZE_HELPER(X)
+
+#define QT3DS_CONCAT_HELPER(X, Y) X##Y
+#define QT3DS_CONCAT(X, Y) QT3DS_CONCAT_HELPER(X, Y)
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec2.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec2.h
new file mode 100644
index 00000000..0d86c915
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec2.h
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_VEC2_H
+#define QT3DS_FOUNDATION_QT3DS_VEC2_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSMath.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/**
+\brief 2 Element vector class.
+
+This is a vector class with public data members.
+This is not nice but it has become such a standard that hiding the xy data members
+makes it difficult to reuse external code that assumes that these are public in the library.
+The vector class can be made to use float or double precision by appropriately defining NVReal.
+This has been chosen as a cleaner alternative to a template class.
+*/
+class QT3DSVec2
+{
+public:
+ /**
+ \brief default constructor leaves data uninitialized.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2() {}
+
+ /**
+ \brief Assigns scalar parameter to all elements.
+
+ Useful to initialize to zero or one.
+
+ \param[in] a Value to assign to elements.
+ */
+ explicit QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2(NVReal a)
+ : x(a)
+ , y(a)
+ {
+ }
+
+ /**
+ \brief Initializes from 2 scalar parameters.
+
+ \param[in] nx Value to initialize X component.
+ \param[in] ny Value to initialize Y component.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2(NVReal nx, NVReal ny)
+ : x(nx)
+ , y(ny)
+ {
+ }
+
+ /**
+ \brief Copy ctor.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2(const QT3DSVec2 &v)
+ : x(v.x)
+ , y(v.y)
+ {
+ }
+
+ // Operators
+
+ /**
+ \brief Assignment operator
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 &operator=(const QT3DSVec2 &p)
+ {
+ x = p.x;
+ y = p.y;
+ return *this;
+ }
+
+ /**
+ \brief element access
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal &operator[](int index)
+ {
+ QT3DS_ASSERT(index >= 0 && index <= 1);
+ return (&x)[index];
+ }
+
+ /**
+ \brief element access
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const NVReal &operator[](int index) const
+ {
+ QT3DS_ASSERT(index >= 0 && index <= 1);
+ return (&x)[index];
+ }
+
+ /**
+ \brief returns true if the two vectors are exactly equal.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool operator==(const QT3DSVec2 &v) const
+ {
+ return x == v.x && y == v.y;
+ }
+
+ /**
+ \brief returns true if the two vectors are not exactly equal.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool operator!=(const QT3DSVec2 &v) const
+ {
+ return x != v.x || y != v.y;
+ }
+
+ /**
+ \brief tests for exact zero vector
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isZero() const { return x == 0.0f && y == 0.0f; }
+
+ /**
+ \brief returns true if all 2 elems of the vector are finite (not NAN or INF, etc.)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool isFinite() const { return NVIsFinite(x) && NVIsFinite(y); }
+
+ /**
+ \brief is normalized - used by API parameter validation
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isNormalized() const
+ {
+ const float unitTolerance = NVReal(1e-4);
+ return isFinite() && NVAbs(magnitude() - 1) < unitTolerance;
+ }
+
+ /**
+ \brief returns the squared magnitude
+
+ Avoids calling NVSqrt()!
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal magnitudeSquared() const { return x * x + y * y; }
+
+ /**
+ \brief returns the magnitude
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal magnitude() const { return NVSqrt(magnitudeSquared()); }
+
+ /**
+ \brief negation
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 operator-() const { return QT3DSVec2(-x, -y); }
+
+ /**
+ \brief vector addition
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 operator+(const QT3DSVec2 &v) const
+ {
+ return QT3DSVec2(x + v.x, y + v.y);
+ }
+
+ /**
+ \brief vector difference
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 operator-(const QT3DSVec2 &v) const
+ {
+ return QT3DSVec2(x - v.x, y - v.y);
+ }
+
+ /**
+ \brief scalar post-multiplication
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 operator*(NVReal f) const
+ {
+ return QT3DSVec2(x * f, y * f);
+ }
+
+ /**
+ \brief scalar division
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 operator/(NVReal f) const
+ {
+ f = NVReal(1) / f; // PT: inconsistent notation with operator /=
+ return QT3DSVec2(x * f, y * f);
+ }
+
+ /**
+ \brief vector addition
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 &operator+=(const QT3DSVec2 &v)
+ {
+ x += v.x;
+ y += v.y;
+ return *this;
+ }
+
+ /**
+ \brief vector difference
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 &operator-=(const QT3DSVec2 &v)
+ {
+ x -= v.x;
+ y -= v.y;
+ return *this;
+ }
+
+ /**
+ \brief scalar multiplication
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 &operator*=(NVReal f)
+ {
+ x *= f;
+ y *= f;
+ return *this;
+ }
+ /**
+ \brief scalar division
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 &operator/=(NVReal f)
+ {
+ f = 1.0f / f; // PT: inconsistent notation with operator /
+ x *= f;
+ y *= f;
+ return *this;
+ }
+
+ /**
+ \brief returns the scalar product of this and other.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal dot(const QT3DSVec2 &v) const { return x * v.x + y * v.y; }
+
+ /** return a unit vector */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 getNormalized() const
+ {
+ const NVReal m = magnitudeSquared();
+ return m > 0 ? *this * NVRecipSqrt(m) : QT3DSVec2(0, 0);
+ }
+
+ /**
+ \brief normalizes the vector in place
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal normalize()
+ {
+ const NVReal m = magnitude();
+ if (m > 0)
+ *this /= m;
+ return m;
+ }
+
+ /**
+ \brief a[i] * b[i], for all i.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 multiply(const QT3DSVec2 &a) const
+ {
+ return QT3DSVec2(x * a.x, y * a.y);
+ }
+
+ /**
+ \brief element-wise minimum
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 minimum(const QT3DSVec2 &v) const
+ {
+ return QT3DSVec2(NVMin(x, v.x), NVMin(y, v.y));
+ }
+
+ /**
+ \brief returns MIN(x, y);
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float minElement() const { return NVMin(x, y); }
+
+ /**
+ \brief element-wise maximum
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec2 maximum(const QT3DSVec2 &v) const
+ {
+ return QT3DSVec2(NVMax(x, v.x), NVMax(y, v.y));
+ }
+
+ /**
+ \brief returns MAX(x, y);
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float maxElement() const { return NVMax(x, y); }
+
+ NVReal x, y;
+};
+
+QT3DS_CUDA_CALLABLE static QT3DS_FORCE_INLINE QT3DSVec2 operator*(NVReal f, const QT3DSVec2 &v)
+{
+ return QT3DSVec2(f * v.x, f * v.y);
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_VEC2_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec3.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec3.h
new file mode 100644
index 00000000..24ab8231
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec3.h
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_VEC3_H
+#define QT3DS_FOUNDATION_QT3DS_VEC3_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSMath.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+/**
+\brief 3 Element vector class.
+
+This is a vector class with public data members.
+This is not nice but it has become such a standard that hiding the xyz data members
+makes it difficult to reuse external code that assumes that these are public in the library.
+The vector class can be made to use float or double precision by appropriately defining NVReal.
+This has been chosen as a cleaner alternative to a template class.
+*/
+class QT3DSVec3
+{
+public:
+ /**
+ \brief default constructor leaves data uninitialized.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3() {}
+
+ /**
+ \brief Assigns scalar parameter to all elements.
+
+ Useful to initialize to zero or one.
+
+ \param[in] a Value to assign to elements.
+ */
+ explicit QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3(NVReal a)
+ : x(a)
+ , y(a)
+ , z(a)
+ {
+ }
+
+ /**
+ \brief Initializes from 3 scalar parameters.
+
+ \param[in] nx Value to initialize X component.
+ \param[in] ny Value to initialize Y component.
+ \param[in] nz Value to initialize Z component.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3(NVReal nx, NVReal ny, NVReal nz)
+ : x(nx)
+ , y(ny)
+ , z(nz)
+ {
+ }
+
+ /**
+ \brief Copy ctor.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3(const QT3DSVec3 &v)
+ : x(v.x)
+ , y(v.y)
+ , z(v.z)
+ {
+ }
+
+ // Operators
+
+ /**
+ \brief Assignment operator
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 &operator=(const QT3DSVec3 &p)
+ {
+ x = p.x;
+ y = p.y;
+ z = p.z;
+ return *this;
+ }
+
+ /**
+ \brief element access
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal &operator[](int index)
+ {
+ QT3DS_ASSERT(index >= 0 && index <= 2);
+ return (&x)[index];
+ }
+
+ /**
+ \brief element access
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE const NVReal &operator[](int index) const
+ {
+ QT3DS_ASSERT(index >= 0 && index <= 2);
+ return (&x)[index];
+ }
+
+ /**
+ \brief returns true if the two vectors are exactly equal.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool operator==(const QT3DSVec3 &v) const
+ {
+ return x == v.x && y == v.y && z == v.z;
+ }
+
+ /**
+ \brief returns true if the two vectors are not exactly equal.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool operator!=(const QT3DSVec3 &v) const
+ {
+ return x != v.x || y != v.y || z != v.z;
+ }
+
+ /**
+ \brief tests for exact zero vector
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isZero() const
+ {
+ return x == 0.0f && y == 0.0f && z == 0.0f;
+ }
+
+ /**
+ \brief returns true if all 3 elems of the vector are finite (not NAN or INF, etc.)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool isFinite() const
+ {
+ return NVIsFinite(x) && NVIsFinite(y) && NVIsFinite(z);
+ }
+
+ /**
+ \brief is normalized - used by API parameter validation
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isNormalized() const
+ {
+ const float unitTolerance = NVReal(1e-4);
+ return isFinite() && NVAbs(magnitude() - 1) < unitTolerance;
+ }
+
+ /**
+ \brief returns the squared magnitude
+
+ Avoids calling NVSqrt()!
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal magnitudeSquared() const
+ {
+ return x * x + y * y + z * z;
+ }
+
+ /**
+ \brief returns the magnitude
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal magnitude() const { return NVSqrt(magnitudeSquared()); }
+
+ /**
+ \brief negation
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 operator-() const { return QT3DSVec3(-x, -y, -z); }
+
+ /**
+ \brief vector addition
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 operator+(const QT3DSVec3 &v) const
+ {
+ return QT3DSVec3(x + v.x, y + v.y, z + v.z);
+ }
+
+ /**
+ \brief vector difference
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 operator-(const QT3DSVec3 &v) const
+ {
+ return QT3DSVec3(x - v.x, y - v.y, z - v.z);
+ }
+
+ /**
+ \brief scalar post-multiplication
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 operator*(NVReal f) const
+ {
+ return QT3DSVec3(x * f, y * f, z * f);
+ }
+
+ /**
+ \brief scalar division
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 operator/(NVReal f) const
+ {
+ f = NVReal(1) / f; // PT: inconsistent notation with operator /=
+ return QT3DSVec3(x * f, y * f, z * f);
+ }
+
+ /**
+ \brief vector addition
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 &operator+=(const QT3DSVec3 &v)
+ {
+ x += v.x;
+ y += v.y;
+ z += v.z;
+ return *this;
+ }
+
+ /**
+ \brief vector difference
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 &operator-=(const QT3DSVec3 &v)
+ {
+ x -= v.x;
+ y -= v.y;
+ z -= v.z;
+ return *this;
+ }
+
+ /**
+ \brief scalar multiplication
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 &operator*=(NVReal f)
+ {
+ x *= f;
+ y *= f;
+ z *= f;
+ return *this;
+ }
+ /**
+ \brief scalar division
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 &operator/=(NVReal f)
+ {
+ f = 1.0f / f; // PT: inconsistent notation with operator /
+ x *= f;
+ y *= f;
+ z *= f;
+ return *this;
+ }
+
+ /**
+ \brief returns the scalar product of this and other.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal dot(const QT3DSVec3 &v) const
+ {
+ return x * v.x + y * v.y + z * v.z;
+ }
+
+ /**
+ \brief cross product
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 cross(const QT3DSVec3 &v) const
+ {
+ return QT3DSVec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
+ }
+
+ /** return a unit vector */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getNormalized() const
+ {
+ const NVReal m = magnitudeSquared();
+ return m > 0 ? *this * NVRecipSqrt(m) : QT3DSVec3(0, 0, 0);
+ }
+
+ /**
+ \brief normalizes the vector in place
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal normalize()
+ {
+ const NVReal m = magnitude();
+ if (m > 0)
+ *this /= m;
+ return m;
+ }
+
+ /**
+ \brief normalizes the vector in place. Does nothing if vector magnitude is under
+ QT3DS_NORMALIZATION_EPSILON.
+ Returns vector magnitude if >= QT3DS_NORMALIZATION_EPSILON and 0.0f otherwise.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal normalizeSafe()
+ {
+ const NVReal mag = magnitude();
+ if (mag < QT3DS_NORMALIZATION_EPSILON)
+ return 0.0f;
+ *this *= NVReal(1) / mag;
+ return mag;
+ }
+
+ /**
+ \brief normalizes the vector in place. Asserts if vector magnitude is under
+ QT3DS_NORMALIZATION_EPSILON.
+ returns vector magnitude.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVReal normalizeFast()
+ {
+ const NVReal mag = magnitude();
+ QT3DS_ASSERT(mag >= QT3DS_NORMALIZATION_EPSILON);
+ *this *= NVReal(1) / mag;
+ return mag;
+ }
+
+ /**
+ \brief a[i] * b[i], for all i.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 multiply(const QT3DSVec3 &a) const
+ {
+ return QT3DSVec3(x * a.x, y * a.y, z * a.z);
+ }
+
+ /**
+ \brief element-wise minimum
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 minimum(const QT3DSVec3 &v) const
+ {
+ return QT3DSVec3(NVMin(x, v.x), NVMin(y, v.y), NVMin(z, v.z));
+ }
+
+ /**
+ \brief returns MIN(x, y, z);
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float minElement() const { return NVMin(x, NVMin(y, z)); }
+
+ /**
+ \brief element-wise maximum
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 maximum(const QT3DSVec3 &v) const
+ {
+ return QT3DSVec3(NVMax(x, v.x), NVMax(y, v.y), NVMax(z, v.z));
+ }
+
+ /**
+ \brief returns MAX(x, y, z);
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float maxElement() const { return NVMax(x, NVMax(y, z)); }
+
+ NVReal x, y, z;
+};
+
+QT3DS_CUDA_CALLABLE static QT3DS_FORCE_INLINE QT3DSVec3 operator*(NVReal f, const QT3DSVec3 &v)
+{
+ return QT3DSVec3(f * v.x, f * v.y, f * v.z);
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_VEC3_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec4.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec4.h
new file mode 100644
index 00000000..acccd48c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVec4.h
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_VEC4_H
+#define QT3DS_FOUNDATION_QT3DS_VEC4_H
+/** \addtogroup foundation
+@{
+*/
+#include "foundation/Qt3DSMath.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSAssert.h"
+
+/**
+\brief 4 Element vector class.
+
+This is a vector class with public data members.
+This is not nice but it has become such a standard that hiding the xyz data members
+makes it difficult to reuse external code that assumes that these are public in the library.
+The vector class can be made to use float or double precision by appropriately defining NVReal.
+This has been chosen as a cleaner alternative to a template class.
+*/
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+class QT3DSVec4
+{
+public:
+ /**
+ \brief default constructor leaves data uninitialized.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4() {}
+
+ /**
+ \brief Assigns scalar parameter to all elements.
+
+ Useful to initialize to zero or one.
+
+ \param[in] a Value to assign to elements.
+ */
+ explicit QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4(NVReal a)
+ : x(a)
+ , y(a)
+ , z(a)
+ , w(a)
+ {
+ }
+
+ /**
+ \brief Initializes from 3 scalar parameters.
+
+ \param[in] nx Value to initialize X component.
+ \param[in] ny Value to initialize Y component.
+ \param[in] nz Value to initialize Z component.
+ \param[in] nw Value to initialize W component.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4(NVReal nx, NVReal ny, NVReal nz, NVReal nw)
+ : x(nx)
+ , y(ny)
+ , z(nz)
+ , w(nw)
+ {
+ }
+
+ /**
+ \brief Initializes from 3 scalar parameters.
+
+ \param[in] v Value to initialize the X, Y, and Z components.
+ \param[in] nw Value to initialize W component.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4(const QT3DSVec3 &v, NVReal nw)
+ : x(v.x)
+ , y(v.y)
+ , z(v.z)
+ , w(nw)
+ {
+ }
+
+ /**
+ \brief Initializes from an array of scalar parameters.
+
+ \param[in] v Value to initialize with.
+ */
+ explicit QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4(const NVReal v[])
+ : x(v[0])
+ , y(v[1])
+ , z(v[2])
+ , w(v[3])
+ {
+ }
+
+ /**
+ \brief Copy ctor.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4(const QT3DSVec4 &v)
+ : x(v.x)
+ , y(v.y)
+ , z(v.z)
+ , w(v.w)
+ {
+ }
+
+ // Operators
+
+ /**
+ \brief Assignment operator
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 &operator=(const QT3DSVec4 &p)
+ {
+ x = p.x;
+ y = p.y;
+ z = p.z;
+ w = p.w;
+ return *this;
+ }
+
+ /**
+ \brief element access
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal &operator[](int index)
+ {
+ QT3DS_ASSERT(index >= 0 && index <= 3);
+ return (&x)[index];
+ }
+
+ /**
+ \brief element access
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE const NVReal &operator[](int index) const
+ {
+ QT3DS_ASSERT(index >= 0 && index <= 3);
+ return (&x)[index];
+ }
+
+ /**
+ \brief returns true if the two vectors are exactly equal.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool operator==(const QT3DSVec4 &v) const
+ {
+ return x == v.x && y == v.y && z == v.z && w == v.w;
+ }
+
+ /**
+ \brief returns true if the two vectors are not exactly equal.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool operator!=(const QT3DSVec4 &v) const
+ {
+ return x != v.x || y != v.y || z != v.z || w != v.w;
+ }
+
+ /**
+ \brief tests for exact zero vector
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool isZero() const { return x == 0 && y == 0 && z == 0 && w == 0; }
+
+ /**
+ \brief returns true if all 3 elems of the vector are finite (not NAN or INF, etc.)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool isFinite() const
+ {
+ return NVIsFinite(x) && NVIsFinite(y) && NVIsFinite(z) && NVIsFinite(w);
+ }
+
+ /**
+ \brief is normalized - used by API parameter validation
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE bool isNormalized() const
+ {
+ const float unitTolerance = NVReal(1e-4);
+ return isFinite() && NVAbs(magnitude() - 1) < unitTolerance;
+ }
+
+ /**
+ \brief returns the squared magnitude
+
+ Avoids calling NVSqrt()!
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal magnitudeSquared() const
+ {
+ return x * x + y * y + z * z + w * w;
+ }
+
+ /**
+ \brief returns the magnitude
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal magnitude() const { return NVSqrt(magnitudeSquared()); }
+
+ /**
+ \brief negation
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 operator-() const { return QT3DSVec4(-x, -y, -z, -w); }
+
+ /**
+ \brief vector addition
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 operator+(const QT3DSVec4 &v) const
+ {
+ return QT3DSVec4(x + v.x, y + v.y, z + v.z, w + v.w);
+ }
+
+ /**
+ \brief vector difference
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 operator-(const QT3DSVec4 &v) const
+ {
+ return QT3DSVec4(x - v.x, y - v.y, z - v.z, w - v.w);
+ }
+
+ /**
+ \brief scalar post-multiplication
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 operator*(NVReal f) const
+ {
+ return QT3DSVec4(x * f, y * f, z * f, w * f);
+ }
+
+ /**
+ \brief scalar division
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 operator/(NVReal f) const
+ {
+ f = NVReal(1) / f;
+ return QT3DSVec4(x * f, y * f, z * f, w * f);
+ }
+
+ /**
+ \brief vector addition
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 &operator+=(const QT3DSVec4 &v)
+ {
+ x += v.x;
+ y += v.y;
+ z += v.z;
+ w += v.w;
+ return *this;
+ }
+
+ /**
+ \brief vector difference
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 &operator-=(const QT3DSVec4 &v)
+ {
+ x -= v.x;
+ y -= v.y;
+ z -= v.z;
+ w -= v.w;
+ return *this;
+ }
+
+ /**
+ \brief scalar multiplication
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 &operator*=(NVReal f)
+ {
+ x *= f;
+ y *= f;
+ z *= f;
+ w *= f;
+ return *this;
+ }
+ /**
+ \brief scalar division
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 &operator/=(NVReal f)
+ {
+ f = 1.0f / f;
+ x *= f;
+ y *= f;
+ z *= f;
+ w *= f;
+ return *this;
+ }
+
+ /**
+ \brief returns the scalar product of this and other.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal dot(const QT3DSVec4 &v) const
+ {
+ return x * v.x + y * v.y + z * v.z + w * v.w;
+ }
+
+ /** return a unit vector */
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 getNormalized() const
+ {
+ NVReal m = magnitudeSquared();
+ return m > 0 ? *this * NVRecipSqrt(m) : QT3DSVec4(0, 0, 0, 0);
+ }
+
+ /**
+ \brief normalizes the vector in place
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE NVReal normalize()
+ {
+ NVReal m = magnitude();
+ if (m > 0)
+ *this /= m;
+ return m;
+ }
+
+ /**
+ \brief a[i] * b[i], for all i.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 multiply(const QT3DSVec4 &a) const
+ {
+ return QT3DSVec4(x * a.x, y * a.y, z * a.z, w * a.w);
+ }
+
+ /**
+ \brief element-wise minimum
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 minimum(const QT3DSVec4 &v) const
+ {
+ return QT3DSVec4(NVMin(x, v.x), NVMin(y, v.y), NVMin(z, v.z), NVMin(w, v.w));
+ }
+
+ /**
+ \brief element-wise maximum
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec4 maximum(const QT3DSVec4 &v) const
+ {
+ return QT3DSVec4(NVMax(x, v.x), NVMax(y, v.y), NVMax(z, v.z), NVMax(w, v.w));
+ }
+
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE QT3DSVec3 getXYZ() const { return QT3DSVec3(x, y, z); }
+
+ /**
+ \brief set vector elements to zero
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_INLINE void setZero() { x = y = z = w = NVReal(0); }
+
+ NVReal x, y, z, w;
+};
+
+QT3DS_CUDA_CALLABLE static QT3DS_INLINE QT3DSVec4 operator*(NVReal f, const QT3DSVec4 &v)
+{
+ return QT3DSVec4(f * v.x, f * v.y, f * v.z, f * v.w);
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_VEC4_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVersionNumber.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVersionNumber.h
new file mode 100644
index 00000000..5942ef72
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Qt3DSVersionNumber.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+VersionNumbers: The combination of these
+numbers uniquely identifies the API, and should
+be incremented when the SDK API changes. This may
+include changes to file formats.
+
+This header is included in the main SDK header files
+so that the entire SDK and everything that builds on it
+is completely rebuilt when this file changes. Thus,
+this file is not to include a frequently changing
+build number. See BuildNumber.h for that.
+
+Each of these three values should stay below 255 because
+sometimes they are stored in a byte.
+*/
+/** \addtogroup foundation
+ @{
+*/
+#ifndef QT3DS_FOUNDATION_QT3DS_VERSION_NUMBER_H
+#define QT3DS_FOUNDATION_QT3DS_VERSION_NUMBER_H
+
+#define QT3DS_FOUNDATION_VERSION_MAJOR 3
+#define QT3DS_FOUNDATION_VERSION_MINOR 3
+#define QT3DS_FOUNDATION_VERSION_BUGFIX 0
+
+/**
+The constant QT3DS_FOUNDATION_VERSION is used when creating certain PhysX module objects.
+This is to ensure that the application is using the same header version as the library was built
+with.
+*/
+#define QT3DS_FOUNDATION_VERSION \
+ ((QT3DS_FOUNDATION_VERSION_MAJOR << 24) + (QT3DS_FOUNDATION_VERSION_MINOR << 16) \
+ + (QT3DS_FOUNDATION_VERSION_BUGFIX << 8) + 0)
+
+#endif // QT3DS_FOUNDATION_QT3DS_VERSION_NUMBER_H
+
+/** @} */
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/SerializationTypes.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/SerializationTypes.h
new file mode 100644
index 00000000..c7fe5ce7
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/SerializationTypes.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_SERIALIZATION_TYPES_H
+#define QT3DS_RENDER_SERIALIZATION_TYPES_H
+#include "EASTL/hash_map.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "foundation/Qt3DSContainers.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ struct SStrRemapMap : public nvhash_map<char8_t *, QT3DSU32>
+ {
+ typedef nvhash_map<char8_t *, QT3DSU32> TBaseType;
+ SStrRemapMap(NVAllocatorCallback &inAlloc, const char *inName)
+ : TBaseType(inAlloc, inName)
+ {
+ }
+ };
+
+ struct SPtrOffsetMap : public nvhash_map<const void *, QT3DSU32>
+ {
+ typedef nvhash_map<const void *, QT3DSU32> TBaseType;
+ SPtrOffsetMap(NVAllocatorCallback &inAlloc, const char *inName)
+ : TBaseType(inAlloc, inName)
+ {
+ }
+ };
+
+ struct SWriteBuffer : public MemoryBuffer<>
+ {
+ SWriteBuffer(NVAllocatorCallback &inAlloc, const char *inName)
+ : MemoryBuffer<>(ForwardingAllocator(inAlloc, inName))
+ {
+ }
+ };
+
+ // Simple data reader that mimics a string
+ struct SDataReader
+ {
+ QT3DSU8 *m_CurrentPtr;
+ QT3DSU8 *m_EndPtr;
+ SDataReader(QT3DSU8 *inStartPtr, QT3DSU8 *inEndPtr)
+ : m_CurrentPtr(inStartPtr)
+ , m_EndPtr(inEndPtr)
+ {
+ }
+
+ template <typename TDataType>
+ TDataType *Load()
+ {
+ if ((m_CurrentPtr + sizeof(TDataType)) > m_EndPtr) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ TDataType *theType = reinterpret_cast<TDataType *>(m_CurrentPtr);
+ m_CurrentPtr += sizeof(TDataType);
+ return theType;
+ }
+
+ template <typename TDataType>
+ void MemCopy(TDataType *dt, QT3DSU32 count)
+ {
+ if (count) {
+ QT3DSU32 loadSize = count * sizeof(TDataType);
+ QT3DSU32 amountLeft = (QT3DSU32)(m_EndPtr - m_CurrentPtr);
+ QT3DSU32 amountLoaded = NVMin(loadSize, amountLeft);
+ memCopy(dt, m_CurrentPtr, amountLoaded);
+ m_CurrentPtr += amountLoaded;
+ if (amountLoaded < loadSize) {
+ QT3DS_ASSERT(false);
+ QT3DSU8 *rawPtr = (QT3DSU8 *)dt;
+ rawPtr += amountLoaded;
+ size_t leftover = loadSize - amountLoaded;
+ // zeroing things out at least is an attempt to provide ordered
+ // data that may prevent a crash in some cases.
+ memZero(rawPtr, (QT3DSU32)leftover);
+ }
+ }
+ }
+
+ // Don't make a habit of using this a lot.
+ template <typename TDataType>
+ TDataType &LoadRef()
+ {
+ TDataType *retval = Load<TDataType>();
+ if (!retval)
+ QT3DS_ASSERT(false);
+ return *retval;
+ }
+
+ void Align(size_t alignment)
+ {
+ size_t offset = (size_t)(m_CurrentPtr);
+ if (offset % alignment)
+ m_CurrentPtr += (alignment - (offset % alignment));
+ }
+
+ void Align() { Align(sizeof(void *)); }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Socket.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Socket.h
new file mode 100644
index 00000000..f561ab83
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Socket.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_SOCKET_H
+#define QT3DS_FOUNDATION_SOCKET_H
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+
+namespace qt3ds {
+
+class NVFoundationBase;
+namespace foundation {
+
+ class SocketStream : public IInStream, public IOutStream, public NVRefCounted
+ {
+ public:
+ // set timeout for write and blocking read operations
+ // Setting to zero makes all operations nonblocking.
+ virtual void setTimeout(QT3DSU32 milliseconds) = 0;
+ virtual QT3DSU32 nonBlockingRead(NVDataRef<QT3DSU8> ioBuffer) = 0;
+ virtual bool connected() = 0;
+ virtual void shutdown() = 0;
+
+ // Useful to testing systems without going into the issues that a network connection can
+ // cause.
+ static NVScopedRefCounted<SocketStream>
+ CreateFileStream(NVFoundationBase &fnd, const char *fname, FileOpenFlags flags);
+ };
+
+ class SocketServer : public NVRefCounted
+ {
+ public:
+ virtual int port() = 0;
+ virtual void setTimeout(QT3DSU32 milliseconds) = 0;
+ virtual NVScopedRefCounted<SocketStream> nextClient() = 0;
+ };
+
+ class SocketSystem : public NVRefCounted
+ {
+ public:
+ // timeout of 0 means wait forever
+ virtual NVScopedRefCounted<SocketStream>
+ createStream(const char *host, QT3DSI32 port, QT3DSU32 timeoutMilliseconds = 10000) = 0;
+ virtual NVScopedRefCounted<SocketServer> createServer(QT3DSI32 port) = 0;
+
+ static NVScopedRefCounted<SocketSystem> createSocketSystem(NVFoundationBase &fnd);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StrConvertUTF.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StrConvertUTF.h
new file mode 100644
index 00000000..e5548840
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StrConvertUTF.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef QT3DS_RENDER_STR_CONVERT_UTF_H
+#define QT3DS_RENDER_STR_CONVERT_UTF_H
+#include <EASTL/string.h>
+#include "foundation/ConvertUTF.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ using namespace qt3ds;
+ template <typename TSrcType>
+ struct ConverterType
+ {
+ };
+ template <>
+ struct ConverterType<char8_t>
+ {
+ typedef UTF8 TConverterType;
+ };
+ template <>
+ struct ConverterType<char16_t>
+ {
+ typedef UTF16 TConverterType;
+ };
+ template <>
+ struct ConverterType<char32_t>
+ {
+ typedef UTF32 TConverterType;
+ };
+
+ template <QT3DSU32 TWCharSize>
+ struct WCharType
+ {
+ };
+
+ template <>
+ struct WCharType<2>
+ {
+ typedef char16_t TCharType;
+ };
+
+ template <>
+ struct WCharType<4>
+ {
+ typedef char32_t TCharType;
+ };
+
+ typedef WCharType<sizeof(wchar_t)> TWCharEASTLConverter;
+
+ template <typename TSrcType, typename TDestType>
+ struct UTFConversionSelector
+ {
+ };
+
+ template <>
+ struct UTFConversionSelector<char8_t, char16_t>
+ {
+ static ConversionResult Convert(const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd,
+ ConversionFlags flags)
+ {
+ return ConvertUTF8toUTF16(sourceStart, sourceEnd, targetStart, targetEnd, flags);
+ }
+ };
+
+ template <>
+ struct UTFConversionSelector<char8_t, char32_t>
+ {
+ static ConversionResult Convert(const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd,
+ ConversionFlags flags)
+ {
+ return ConvertUTF8toUTF32(sourceStart, sourceEnd, targetStart, targetEnd, flags);
+ }
+ };
+ template <>
+ struct UTFConversionSelector<char16_t, char8_t>
+ {
+ static ConversionResult Convert(const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
+ {
+ return ConvertUTF16toUTF8(sourceStart, sourceEnd, targetStart, targetEnd, flags);
+ }
+ };
+ template <>
+ struct UTFConversionSelector<char16_t, char32_t>
+ {
+ static ConversionResult Convert(const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd,
+ ConversionFlags flags)
+ {
+ return ConvertUTF16toUTF32(sourceStart, sourceEnd, targetStart, targetEnd, flags);
+ }
+ };
+ template <>
+ struct UTFConversionSelector<char32_t, char8_t>
+ {
+ static ConversionResult Convert(const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
+ {
+ return ConvertUTF32toUTF8(sourceStart, sourceEnd, targetStart, targetEnd, flags);
+ }
+ };
+ template <>
+ struct UTFConversionSelector<char32_t, char16_t>
+ {
+ static ConversionResult Convert(const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd,
+ ConversionFlags flags)
+ {
+ return ConvertUTF32toUTF16(sourceStart, sourceEnd, targetStart, targetEnd, flags);
+ }
+ };
+
+ // Convert into an EASTL string type.
+ // inSrcLen may be zero in which case we analyze the string looking for the zero element.
+ template <typename TSrcType, typename TDestType, typename TAllocType>
+ bool ConvertUTF(const TSrcType *inSrc, size_t inSrcLen,
+ eastl::basic_string<TDestType, TAllocType> &outString)
+ {
+ typedef typename ConverterType<TDestType>::TConverterType TDestUTFType;
+ typedef typename ConverterType<TSrcType>::TConverterType TSrcUTFType;
+ if (inSrc == 0 || *inSrc == 0) {
+ outString.clear();
+ return true;
+ }
+
+ if (inSrcLen == 0) {
+ // empty loop intentional.
+ for (const TSrcType *ptr = inSrc; ptr && *ptr; ++ptr, ++inSrcLen) {
+ }
+ }
+
+ typename eastl::basic_string<TDestType, TAllocType>::size_type capacity =
+ outString.capacity();
+ if (capacity == 0)
+ outString.resize((QT3DSU32)inSrcLen * 2);
+ else
+ outString.resize(capacity);
+
+ ConversionResult theConversionResult(conversionOK);
+ TDestUTFType *writePtr = NULL;
+ do {
+ writePtr = reinterpret_cast<TDestUTFType *>(const_cast<TDestType *>(outString.data()));
+ TDestUTFType *writeEnd(writePtr + outString.size());
+ const TSrcUTFType *readPtr(reinterpret_cast<const TSrcUTFType *>(inSrc));
+ const TSrcUTFType *readEnd = readPtr + inSrcLen;
+ theConversionResult = UTFConversionSelector<TSrcType, TDestType>::Convert(
+ &readPtr, readEnd, &writePtr, writeEnd, lenientConversion);
+ if (theConversionResult == targetExhausted) {
+ capacity = outString.capacity() * 2;
+ outString.resize(capacity);
+ }
+ } while (theConversionResult == targetExhausted);
+
+ if (theConversionResult == conversionOK) {
+ TDestUTFType *writeStart =
+ reinterpret_cast<TDestUTFType *>(const_cast<TDestType *>(outString.data()));
+ outString.resize((QT3DSU32)(writePtr - writeStart));
+ return true;
+ } else {
+ outString.clear();
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ }
+
+#ifdef WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+
+ template <typename TDestType, typename TAllocType>
+ bool ConvertWideUTF(const wchar_t *inSrc, size_t inSrcLen,
+ eastl::basic_string<TDestType, TAllocType> &outString)
+ {
+ return ConvertUTF((const TWCharEASTLConverter::TCharType *)inSrc, inSrcLen, outString);
+ }
+
+#endif
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversion.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversion.h
new file mode 100644
index 00000000..a55ebb3e
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversion.h
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_STRING_CONVERSION_H
+#define QT3DS_FOUNDATION_STRING_CONVERSION_H
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Utils.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ // Template base class so that we can convert items to and from char* and wchar_t*
+ // representations
+ template <typename TDataType>
+ struct StringConversion
+ {
+ bool force_compile_error;
+ };
+
+ // Write the char8_t but exlude the null terminator
+ // Meant to write data model values.
+ // Memory buffer contains a non-null-terminated
+ // char8_t string
+ struct Char8TWriter
+ {
+ MemoryBuffer<ForwardingAllocator> &m_Buffer;
+ Char8TWriter(MemoryBuffer<ForwardingAllocator> &buf)
+ : m_Buffer(buf)
+ {
+ }
+ void Write(const char8_t *value, QT3DSU32 len = 0)
+ {
+ if (isTrivial(value))
+ return;
+ if (len == 0)
+ len = (QT3DSU32)StrLen(value);
+ m_Buffer.write(value, len);
+ }
+ void Write(char8_t value) { m_Buffer.write(value); }
+ void Write(bool value) { Write(value ? "True" : "False"); }
+
+ // Takes care of long and float
+ template <typename TDataType>
+ void Write(TDataType value)
+ {
+ char8_t buf[256];
+ QT3DSU32 numWritten =
+ StringConversion<TDataType>().ToStr(value, NVDataRef<char8_t>(buf, 256));
+ if (numWritten)
+ Write((const char8_t *)buf);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TDataType>
+ void Write(NVConstDataRef<TDataType> values, QT3DSU32 grouping = 6, QT3DSU32 tabCount = 0)
+ {
+ for (QT3DSU32 idx = 0; idx < values.size(); ++idx) {
+ if (idx) {
+ if ((idx % grouping) == 0) {
+ Write((char8_t)'\n');
+ for (QT3DSU32 tabIdx = 0; tabIdx < tabCount; ++tabIdx)
+ Write((char8_t)'\t');
+ } else
+ Write((char8_t)' ');
+ }
+ Write(values[idx]);
+ }
+ }
+
+ void Write(NVConstDataRef<char8_t> values, QT3DSU32 ignored = 6)
+ {
+ (void)ignored;
+ if (values.size() && values[0] != 0) {
+ QT3DSU32 lastItem = values.size() - 1;
+ if (values[lastItem] == 0)
+ --lastItem;
+ Write(values.begin(), lastItem + 1);
+ }
+ }
+ };
+
+ inline bool IsWhite(char8_t value)
+ {
+ return value == '\n' || value == '\r' || value == ' ' || value == '\t';
+ }
+
+ // skip until we find whitespace.
+ inline char8_t *FindNextWhitespace(char8_t *input)
+ {
+ if (input == NULL)
+ return input;
+ char8_t *marker = input;
+ // Empty loop intentional
+ for (; *marker && !IsWhite(*marker); ++marker)
+ ;
+ return marker;
+ }
+
+ // skip until we find something that isn't whitespace.
+ inline char8_t *FindNextNonWhitespace(char8_t *input)
+ {
+ if (input == NULL)
+ return input;
+ char8_t *marker = input;
+ // Empty loop intentional
+ for (; *marker && IsWhite(*marker); ++marker)
+ ;
+ return marker;
+ }
+
+ // Reading is destructive in the case of floating point lists, so we may
+ // destroy the incoming string.
+ // We are assuming the string is null-terminated at end ptr.
+ struct Char8TReader
+ {
+ char8_t *m_StartPtr;
+ // Buffer used for temp storage
+ MemoryBuffer<ForwardingAllocator> &m_Buffer;
+ Char8TReader(char8_t *sp, MemoryBuffer<ForwardingAllocator> &buf)
+ : m_StartPtr(sp)
+ , m_Buffer(buf)
+ {
+ }
+ void Read(const char8_t *&outPtr) { outPtr = m_StartPtr; }
+
+ template <typename TDataType>
+ void Read(TDataType &data)
+ {
+ bool success = StringConversion<TDataType>().StrTo(m_StartPtr, data);
+ QT3DS_ASSERT(success);
+ (void)success;
+ }
+ // Destructive operation because we can't trust
+ // strtod to do the right thing. On windows, for long strings,
+ // it calls strlen every operation thus leading to basically N^2
+ // behavior
+ template <typename TDataType>
+ void ReadRef(NVDataRef<TDataType> data)
+ {
+ QT3DSU32 idx = 0;
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr);
+ for (; idx < data.size() && m_StartPtr && *m_StartPtr; ++idx) {
+ char8_t *nextPtr = FindNextWhitespace(m_StartPtr);
+ if (nextPtr && *nextPtr)
+ *nextPtr = 0;
+ else
+ nextPtr = NULL;
+ StringConversion<TDataType>().StrTo(m_StartPtr, data[idx]);
+ m_StartPtr = nextPtr;
+ if (m_StartPtr)
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr + 1);
+ }
+ QT3DS_ASSERT(idx == data.size());
+ }
+
+ void ReadBuffer(NVConstDataRef<char8_t> &outBuffer)
+ {
+ if (m_StartPtr && *m_StartPtr) {
+ QT3DSU32 len = (QT3DSU32)strlen(m_StartPtr);
+ outBuffer = NVConstDataRef<char8_t>(m_StartPtr, len + 1);
+ }
+ }
+
+ // Destructive operation because we can't trust
+ // strtod to do the right thing. On windows, for long strings,
+ // it calls strlen every operation thus leading to basically N^2
+ // behavior
+ template <typename TDataType>
+ void ReadBuffer(NVConstDataRef<TDataType> &outBuffer)
+ {
+ m_Buffer.clear();
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr);
+ while (m_StartPtr && *m_StartPtr) {
+ char8_t *nextPtr = FindNextWhitespace(m_StartPtr);
+ if (nextPtr && *nextPtr)
+ *nextPtr = 0;
+ else
+ nextPtr = NULL;
+ TDataType temp;
+ StringConversion<TDataType>().StrTo(m_StartPtr, temp);
+ m_Buffer.write(temp);
+ m_StartPtr = nextPtr;
+ if (m_StartPtr)
+ m_StartPtr = FindNextNonWhitespace(m_StartPtr + 1);
+ }
+ QT3DSU32 numItems = m_Buffer.size() / sizeof(TDataType);
+ if (numItems)
+ outBuffer = NVConstDataRef<TDataType>((TDataType *)m_Buffer.begin(), numItems);
+ else
+ outBuffer = NVConstDataRef<TDataType>();
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversionImpl.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversionImpl.h
new file mode 100644
index 00000000..c49c14b4
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringConversionImpl.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_STRING_CONVERSION_IMPL_H
+#define QT3DS_FOUNDATION_STRING_CONVERSION_IMPL_H
+#include "foundation/StringConversion.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "EABase/eabase.h"
+#include "foundation/StringTable.h"
+#include "foundation/Utils.h"
+#include "stdlib.h"
+#include "stdio.h" //snprintf
+
+#if !defined EA_PLATFORM_WINDOWS
+#define _snprintf snprintf
+#endif
+
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct StringConversion<bool>
+ {
+ QT3DSU32 ToStr(bool item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ _snprintf(buffer.begin(), buffer.size(), "%s", item ? "True" : "False"));
+ }
+ bool StrTo(const char8_t *buffer, bool &item)
+ {
+ if (AreEqualCaseless(buffer, "True"))
+ item = true;
+ else
+ item = false;
+ return true;
+ }
+ };
+
+ template <>
+ struct StringConversion<QT3DSU8>
+ {
+ QT3DSU32 ToStr(QT3DSU8 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ _snprintf(buffer.begin(), buffer.size(), "%hu", static_cast<QT3DSU16>(item)));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU8 &item)
+ {
+ item = static_cast<QT3DSU8>(strtoul(buffer, NULL, 10));
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSI8>
+ {
+ QT3DSU32 ToStr(QT3DSI8 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ _snprintf(buffer.begin(), buffer.size(), "%hd", static_cast<QT3DSI16>(item)));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI8 &item)
+ {
+ item = static_cast<QT3DSI8>(strtol(buffer, NULL, 10));
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSU16>
+ {
+ QT3DSU32 ToStr(QT3DSU16 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%hu", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU16 &item)
+ {
+ item = static_cast<QT3DSU16>(strtoul(buffer, NULL, 10));
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSI16>
+ {
+ QT3DSU32 ToStr(QT3DSI16 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%hd", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI16 &item)
+ {
+ item = static_cast<QT3DSI16>(strtol(buffer, NULL, 10));
+ return true;
+ }
+ };
+
+ template <>
+ struct StringConversion<QT3DSU32>
+ {
+ QT3DSU32 ToStr(QT3DSU32 item, NVDataRef<char8_t> buffer)
+ {
+ // hope the buffer is big enough...
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%u", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU32 &item)
+ {
+ item = strtoul(buffer, NULL, 10);
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSI32>
+ {
+ QT3DSU32 ToStr(QT3DSI32 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%d", (int)item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI32 &item)
+ {
+ item = strtol(buffer, NULL, 10);
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSU64>
+ {
+ QT3DSU32 ToStr(QT3DSU64 item, NVDataRef<char8_t> buffer)
+ {
+#ifdef _WIN32
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%I64u", item));
+#else
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%lu", item));
+#endif
+ }
+ bool StrTo(const char8_t *buffer, QT3DSU64 &item)
+ {
+ item = strtoul(buffer, NULL, 10);
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSI64>
+ {
+ QT3DSU32 ToStr(QT3DSI64 item, NVDataRef<char8_t> buffer)
+ {
+#ifdef _WIN32
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%I64d", item));
+#else
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%ld", item));
+#endif
+ }
+ bool StrTo(const char8_t *buffer, QT3DSI64 &item)
+ {
+ item = strtol(buffer, NULL, 10);
+ return true;
+ }
+ };
+ template <>
+ struct StringConversion<QT3DSF32>
+ {
+ QT3DSU32 ToStr(QT3DSF32 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(
+ _snprintf(buffer.begin(), buffer.size(), "%g", static_cast<QT3DSF64>(item)));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSF32 &item)
+ {
+ item = (QT3DSF32)strtod(buffer, NULL);
+ return true;
+ }
+ };
+
+ template <>
+ struct StringConversion<QT3DSF64>
+ {
+ QT3DSU32 ToStr(QT3DSF64 item, NVDataRef<char8_t> buffer)
+ {
+ return static_cast<QT3DSU32>(_snprintf(buffer.begin(), buffer.size(), "%g", item));
+ }
+ bool StrTo(const char8_t *buffer, QT3DSF64 &item)
+ {
+ item = strtod(buffer, NULL);
+ return true;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringTable.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringTable.h
new file mode 100644
index 00000000..39e3adcf
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/StringTable.h
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_STRING_TABLE_H
+#define QT3DS_RENDER_STRING_TABLE_H
+
+#if defined(_WIN32) || defined(__QNXNTO__)
+#include <wchar.h>
+#ifndef WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+#define WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+#endif
+#endif
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "EASTL/functional.h"
+#include "EABase/eabase.h" //char16_t definition
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSOption.h"
+
+namespace qt3ds {
+namespace foundation {
+ typedef char8_t UICBChar;
+ typedef const char8_t *UICBCharPtr;
+ class IStringTable;
+
+ // Serialization types, NVRenderSerializationTypes.h
+ struct SStrRemapMap;
+ struct SWriteBuffer;
+
+ class CRegisteredString;
+
+ // Discriminated union of either data ref or str table
+ // used so clients can test serialization without actually saving
+ // the string table out and rebooting the entire system.
+ class CStrTableOrDataRef
+ {
+ Option<NVDataRef<QT3DSU8>> m_DataRef;
+ IStringTable *m_StrTable;
+
+ public:
+ CStrTableOrDataRef()
+ : m_StrTable(NULL)
+ {
+ }
+ CStrTableOrDataRef(NVDataRef<QT3DSU8> inData)
+ : m_DataRef(inData)
+ {
+ }
+ CStrTableOrDataRef(IStringTable &inStrTable)
+ : m_StrTable(&inStrTable)
+ {
+ }
+ CStrTableOrDataRef(const CStrTableOrDataRef &inOther)
+ : m_DataRef(inOther.m_DataRef)
+ , m_StrTable(inOther.m_StrTable)
+ {
+ }
+ CStrTableOrDataRef &operator=(const CStrTableOrDataRef &inOther)
+ {
+ m_DataRef = inOther.m_DataRef;
+ m_StrTable = inOther.m_StrTable;
+ return *this;
+ }
+ bool HasStrTable() const { return m_StrTable != NULL; }
+ bool HasDataRef() const { return m_DataRef.hasValue(); }
+ NVDataRef<QT3DSU8> GetDataRef() const { return *m_DataRef; }
+ IStringTable *GetStringTable() const
+ {
+ QT3DS_ASSERT(m_StrTable);
+ return m_StrTable;
+ }
+ };
+
+ // String that can only be constructed from strings in the string table.
+ // These strings are valid utf-8 strings
+ class CRegisteredString
+ {
+ UICBCharPtr m_String;
+
+ public:
+ CRegisteredString()
+ : m_String("")
+ {
+ }
+ CRegisteredString(const CRegisteredString &inOther)
+ : m_String(inOther.m_String)
+ {
+ }
+ CRegisteredString &operator=(const CRegisteredString &inOther)
+ {
+ m_String = inOther.m_String;
+ return *this;
+ }
+
+ bool operator==(const CRegisteredString &inStr) const { return m_String == inStr.m_String; }
+ // If you use this in a real map then you will get them sorted roughly by the correct
+ // order.
+ bool operator<(const char *inStr) const
+ {
+ // Ensure non-null strings to strcmp.
+ const char *myStr = m_String ? m_String : "";
+ inStr = inStr ? inStr : "";
+ int answer;
+ while (*myStr && *inStr) {
+ answer = *inStr - *myStr;
+ if (answer)
+ return answer < 0;
+ ++myStr;
+ ++inStr;
+ }
+ answer = *inStr - *myStr;
+ return answer < 0;
+ }
+ size_t hash() const { return eastl::hash<size_t>()(reinterpret_cast<size_t>(m_String)); }
+ operator UICBCharPtr() const { return c_str(); }
+ UICBCharPtr c_str() const { return m_String ? m_String : ""; }
+ bool IsValid() const { return m_String && *m_String; }
+
+ // If this string is in the map, changes it to the map value.
+ void Remap(const SStrRemapMap &inMap);
+
+ void Remap(const IStringTable &inTable);
+
+ // Using m_String as an offset, if possible remap into
+ // inDataPtr's block of memory
+ void Remap(NVDataRef<QT3DSU8> inDataPtr);
+
+ void Remap(const CStrTableOrDataRef &inRef)
+ {
+ if (inRef.HasDataRef())
+ Remap(inRef.GetDataRef());
+ else if (inRef.HasStrTable())
+ Remap(*inRef.GetStringTable());
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static CRegisteredString ISwearThisHasBeenRegistered(UICBCharPtr str)
+ {
+ CRegisteredString retval;
+ retval.m_String = str;
+ return retval;
+ }
+ };
+
+ class IStringTable;
+
+ class CStringHandle
+ {
+ QT3DSU32 m_Data;
+
+ CStringHandle(QT3DSU32 hdl)
+ : m_Data(hdl)
+ {
+ }
+
+ public:
+ CStringHandle()
+ : m_Data(0)
+ {
+ }
+ CStringHandle(const CStringHandle &other)
+ : m_Data(other.m_Data)
+ {
+ }
+ CStringHandle &operator=(const CStringHandle &other)
+ {
+ m_Data = other.m_Data;
+ return *this;
+ }
+ bool IsValid() const { return m_Data != 0; }
+ QT3DSU32 handle() const { return m_Data; }
+ inline const char8_t *c_str(IStringTable &strTable) const;
+ operator QT3DSU32() const { return m_Data; }
+ static CStringHandle ISwearThisHasBeenRegistered(QT3DSU32 strHandle)
+ {
+ return CStringHandle(strHandle);
+ }
+ };
+
+ // String table stores strings in utf-8 format and does valid utf-16,utf-32 -> utf-8
+ // also converts utf8 -> either utf-32 or utf-16, depending on sizeof( wchar_t ) if
+ // requested.
+ // UICStrConvertUTF.h
+ // Also generates offsets that are consistent so clients can convert their strings
+ // to offsets during save and convert from offset to string during load regardless
+ // of if they load before or after this table.
+ class IStringTable : public NVRefCounted
+ {
+ public:
+ // default state is for multithreaded access to be disabled.
+ // remember to implement in CNullStringManager in UICTestPresentation.hxx
+ virtual void EnableMultithreadedAccess() = 0;
+ virtual void DisableMultithreadedAccess() = 0;
+
+ virtual CRegisteredString RegisterStr(UICBCharPtr str) = 0;
+ // utf-16->utf-8
+ virtual CRegisteredString RegisterStr(const char16_t *str) = 0;
+ // utf-32->utf-8
+ virtual CRegisteredString RegisterStr(const char32_t *str) = 0;
+
+ virtual CStringHandle GetHandle(UICBCharPtr str) = 0;
+ virtual CRegisteredString HandleToStr(QT3DSU32 strHandle) = 0;
+
+ virtual CRegisteredString RegisterStr(const wchar_t *str) = 0;
+
+ virtual const wchar_t *GetWideStr(UICBCharPtr src) = 0;
+ virtual const wchar_t *GetWideStr(const wchar_t *str) = 0;
+
+ UICBCharPtr GetNarrowStr(const wchar_t *src) { return RegisterStr(src); }
+ UICBCharPtr GetNarrowStr(UICBCharPtr src) { return RegisterStr(src); }
+
+ // The string table maintains a map that will tell clients where their strings will be
+ // in terms of offsets into the data that the string table writes.
+ // This map will change each time a new string is added to the string table.
+ // Conversion from string -> data offset.
+ virtual const SStrRemapMap &GetRemapMap() = 0;
+
+ virtual NVAllocatorCallback &GetAllocator() = 0;
+
+ // Save to a block of memory. It is up the callers to deallocate using allocator
+ // from GetAllocator(). Returns a remap map that takes existing strings and changes their
+ // address such that they are offsets into the block of memory where this object
+ // started saving. Returns a map that converts registered strings into offsets of the
+ // written buffer.
+ virtual void Save(SWriteBuffer &ioBuffer) const = 0;
+
+ // Load all the strings from inMemory. inMemory is not freed by this object
+ // Finally, you will need to take inMemory and call remap on all strings
+ // from offsets back into their correct address into inMemory.
+ virtual void Load(qt3ds::foundation::NVDataRef<QT3DSU8> inMemory) = 0;
+
+ static IStringTable &CreateStringTable(NVAllocatorCallback &alloc);
+ };
+
+ inline const char8_t *CStringHandle::c_str(IStringTable &strTable) const
+ {
+ return strTable.HandleToStr(m_Data);
+ }
+}
+}
+
+// eastl extensions to allow easy hashtable creation using string table strings.
+namespace eastl {
+
+template <>
+struct hash<qt3ds::foundation::CRegisteredString>
+{
+ size_t operator()(const qt3ds::foundation::CRegisteredString &str) const { return str.hash(); }
+};
+
+template <>
+struct equal_to<qt3ds::foundation::CRegisteredString>
+{
+ bool operator()(const qt3ds::foundation::CRegisteredString &lhs,
+ const qt3ds::foundation::CRegisteredString &rhs) const
+ {
+ return lhs == rhs;
+ }
+};
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/TaggedPointer.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/TaggedPointer.h
new file mode 100644
index 00000000..aa227250
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/TaggedPointer.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_TAGGED_POINTER_H
+#define QT3DS_FOUNDATION_TAGGED_POINTER_H
+#include "foundation/StringTable.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename TDataType>
+ struct SPointerTag
+ {
+ /* Expected API for runtime RTTI
+ static CRegisteredString GetTag() { return g_dtype_specific_string; }
+ */
+ };
+
+ // A pointer tagged with an identifier so we can have generic
+ // user data that is still somewhat typesafe.
+ struct STaggedPointer
+ {
+ void *m_UserData;
+ CRegisteredString m_Tag;
+ STaggedPointer()
+ : m_UserData(NULL)
+ {
+ }
+
+ STaggedPointer(void *inUserData, CRegisteredString inTag)
+ : m_UserData(inUserData)
+ , m_Tag(inTag)
+ {
+ }
+
+ template <typename TDataType>
+ STaggedPointer(TDataType *inType)
+ : m_UserData(reinterpret_cast<void *>(inType))
+ , m_Tag(SPointerTag<TDataType>::GetTag())
+ {
+ }
+
+ template <typename TDataType>
+ TDataType *DynamicCast() const
+ {
+ if (m_Tag == SPointerTag<TDataType>::GetTag())
+ return reinterpret_cast<TDataType *>(m_UserData);
+ return NULL;
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/ThreadSafeQueue.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/ThreadSafeQueue.h
new file mode 100644
index 00000000..462b6d49
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/ThreadSafeQueue.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_FOUNDATION_THREAD_SAFE_QUEUE_H
+#define QT3DS_FOUNDATION_THREAD_SAFE_QUEUE_H
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSemaphore.h"
+#include "EASTL/vector.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <typename TObjType, typename TAllocator = EASTLAllocatorType>
+ class ThreadSafeQueue
+ {
+ public:
+ static const QT3DSU32 MaxQueue = 0xffffffff;
+
+ protected:
+ eastl::vector<TObjType, TAllocator> mQueue;
+ Semaphore mGetSemaphore;
+ Semaphore mPutSemaphore;
+ Mutex mMutex;
+ const QT3DSU32 mMaxCount;
+
+ public:
+ ThreadSafeQueue(NVAllocatorCallback &alloc, QT3DSU32 maxCount = MaxQueue)
+ : mMutex(alloc)
+ , mGetSemaphore(alloc, 0, maxCount)
+ , mPutSemaphore(alloc, maxCount, maxCount)
+ , mMaxCount(maxCount)
+ {
+ mQueue.clear();
+ }
+
+ bool push(const TObjType &obj, QT3DSU32 milliseconds = MaxQueue)
+ {
+ if (mPutSemaphore.wait(milliseconds)) {
+ Mutex::ScopedLock __locker(mMutex);
+ mQueue.push_back(obj);
+ mGetSemaphore.post();
+ return true;
+ }
+ return false;
+ }
+
+ bool pop(TObjType &obj, QT3DSU32 milliseconds = 0)
+ {
+ if (mGetSemaphore.wait(milliseconds)) {
+ Mutex::ScopedLock __locker(mMutex);
+ obj = mQueue.back();
+ mQueue.pop_back();
+ mPutSemaphore.post();
+ return true;
+ }
+ return false;
+ }
+
+ bool isFull()
+ {
+ Mutex::ScopedLock __locker(mMutex);
+ return mQueue.size() >= mMaxCount;
+ }
+
+ bool isEmpty()
+ {
+ Mutex::ScopedLock __locker(mMutex);
+ return mQueue.size() == 0;
+ }
+
+ void clear()
+ {
+ Mutex::ScopedLock __locker(mMutex);
+ while (!mQueue.empty()) {
+ if (mGetSemaphore.wait(MaxQueue)) {
+ mQueue.pop_back();
+ mPutSemaphore.post();
+ }
+ }
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/TrackingAllocator.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/TrackingAllocator.h
new file mode 100644
index 00000000..caee7c8c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/TrackingAllocator.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_ALLOCATOR_H
+#define QT3DS_RENDER_ALLOCATOR_H
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSMutex.h"
+#include "EASTL/hash_map.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSLogging.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ // The simplest allocator. Performs no alignment nor memory checking.
+ struct MallocAllocator : public NVAllocatorCallback
+ {
+ void *allocate(size_t size, const char *, const char *, int, int = 0) override
+ {
+ return malloc(size);
+ }
+ void *allocate(size_t size, const char *, const char *, int, size_t, size_t) override
+ {
+ return malloc(size);
+ }
+ void deallocate(void *ptr) override { free(ptr); }
+ };
+
+ struct MemInfo
+ {
+ size_t size;
+ void *originalAddress;
+ const char *name;
+ const char *file;
+ int line;
+ MemInfo(size_t _size = 0, void *addr = 0, const char *_name = "", const char *_file = "",
+ int _line = 0)
+ : size(_size)
+ , originalAddress(addr)
+ , name(_name)
+ , file(_file)
+ , line(_line)
+ {
+ }
+ };
+
+ struct FileAndLine
+ {
+ const char *mFile;
+ QT3DSU32 mLine;
+ FileAndLine(const char *f, QT3DSU32 l)
+ : mFile(f)
+ , mLine(l)
+ {
+ }
+ };
+} // namespace foundation
+} // namespace qt3ds
+
+namespace eastl {
+template <>
+struct hash<qt3ds::foundation::FileAndLine>
+{
+ size_t operator()(const qt3ds::foundation::FileAndLine &fl) const
+ {
+ return hash<const void *>()((const void *)fl.mFile) ^ hash<int>()(fl.mLine);
+ }
+};
+
+template <>
+struct equal_to<qt3ds::foundation::FileAndLine>
+{
+ bool operator()(const qt3ds::foundation::FileAndLine &fl1,
+ const qt3ds::foundation::FileAndLine &fl2) const
+ {
+ size_t fl1File(reinterpret_cast<size_t>(fl1.mFile));
+ size_t fl2File(reinterpret_cast<size_t>(fl2.mFile));
+
+ return fl1File == fl2File && fl1.mLine == fl2.mLine;
+ }
+};
+}
+
+namespace qt3ds {
+namespace foundation {
+
+ struct MemInfoAndCount : MemInfo
+ {
+ QT3DSU32 mCount;
+ QT3DSU64 mTotalBytes;
+ MemInfoAndCount(const MemInfo &info)
+ : MemInfo(info)
+ , mCount(1)
+ , mTotalBytes(info.size)
+ {
+ }
+ void increment(const MemInfo &otherInfo)
+ {
+ ++mCount;
+ mTotalBytes += otherInfo.size;
+ }
+ };
+
+ typedef nvhash_map<FileAndLine, MemInfoAndCount> TFileAndLineMemHash;
+
+ class AllocationCheckPrinter
+ {
+ protected:
+ virtual ~AllocationCheckPrinter() {}
+ public:
+ virtual void printMissing(const MemInfoAndCount &item) = 0;
+ virtual void printIncorrectCount(const MemInfoAndCount &later,
+ const MemInfoAndCount &earlier) = 0;
+ };
+
+ // All allocations are 16 byte aligned.
+ // Prints out unallocated memory at destruction.
+ class CAllocator : public NVAllocatorCallback
+ {
+ public:
+ typedef Mutex TMutexType;
+ typedef Mutex::ScopedLock TLockType;
+ typedef nvhash_map<void *, MemInfo> PtrToInfoMap;
+
+ private:
+ MallocAllocator mAlloc;
+ PtrToInfoMap mAllocations;
+ PtrToInfoMap mStoredAllocations;
+ TMutexType mMutex;
+
+ public:
+ CAllocator()
+ : mAllocations(mAlloc, "MemInfo")
+ , mStoredAllocations(mAlloc, "MemInfo")
+ , mMutex(mAlloc)
+ {
+ }
+ virtual ~CAllocator()
+ {
+ QT3DS_ASSERT(mAllocations.size() == 0);
+ MemInfo info;
+ for (PtrToInfoMap::iterator iter = mAllocations.begin(), end = mAllocations.end();
+ iter != end; ++iter) {
+ info = iter->second;
+ qCCritical(INTERNAL_ERROR, "!!Outstanding allocation of %lu bytes from %s::%d, %s",
+ info.size, info.file, info.line, info.name ? info.name : "");
+ }
+ QT3DS_UNUSED(info);
+ }
+ void *allocate(size_t size, const char *tn, const char *fl, int ln, int flags) override
+ {
+ QT3DS_ASSERT(size);
+ if (size) {
+ size += 15;
+ TLockType locker(mMutex);
+ void *original = mAlloc.allocate(size, tn, fl, ln, flags);
+ size_t temp = (size_t)original;
+ temp = (temp + 15) & (~15);
+ void *retval = (void *)temp;
+ mAllocations.insert(eastl::make_pair(retval, MemInfo(size, original, tn, fl, ln)));
+ return retval;
+ }
+ return NULL;
+ }
+ void *allocate(size_t size, const char *tn, const char *fl, int ln, size_t, size_t) override
+ {
+ return allocate(size, tn, fl, ln, 0);
+ }
+ void deallocate(void *ptr) override
+ {
+ if (ptr) {
+ TLockType locker(mMutex);
+ PtrToInfoMap::iterator entry(mAllocations.find(ptr));
+ if (entry != mAllocations.end()) {
+ mAlloc.deallocate(entry->second.originalAddress);
+ mAllocations.erase(ptr);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ const PtrToInfoMap &getOutstandingAllocations() const { return mAllocations; }
+ static void convert(const CAllocator::PtrToInfoMap &map, TFileAndLineMemHash &fl)
+ {
+ for (CAllocator::PtrToInfoMap::const_iterator iter = map.begin(), end = map.end();
+ iter != end; ++iter) {
+ const MemInfo &info(iter->second);
+ FileAndLine flKey(info.file, info.line);
+ TFileAndLineMemHash::const_iterator find(fl.find(flKey));
+ if (find == fl.end())
+ fl.insert(eastl::make_pair(flKey, MemInfoAndCount(info)));
+ else
+ const_cast<MemInfoAndCount &>(find->second).increment(info);
+ }
+ }
+ static void copyMap(const CAllocator::PtrToInfoMap &map1, CAllocator::PtrToInfoMap &map2)
+ {
+ for (CAllocator::PtrToInfoMap::const_iterator iter = map1.begin(), end = map1.end();
+ iter != end; ++iter) {
+ map2.insert(eastl::make_pair(iter->first, iter->second));
+ }
+ }
+
+ static void printDiffs(const TFileAndLineMemHash &fl1, const TFileAndLineMemHash &fl2,
+ AllocationCheckPrinter &printer)
+ {
+ using namespace std;
+ for (TFileAndLineMemHash::const_iterator iter = fl1.begin(), end = fl1.end();
+ iter != end; ++iter) {
+ TFileAndLineMemHash::const_iterator entry = fl2.find(iter->first);
+ if (entry != fl2.end()) {
+ printer.printMissing(iter->second);
+ } else if (iter->second.mCount > entry->second.mCount) {
+ printer.printIncorrectCount(iter->second, entry->second);
+ }
+ }
+ }
+
+ void printAllocationDiff(AllocationCheckPrinter &printer)
+ {
+ TFileAndLineMemHash map1fl(mAlloc, "printAllocationDiff");
+ TFileAndLineMemHash map2fl(mAlloc, "printAllocationDiff");
+ convert(mStoredAllocations, map1fl);
+ convert(mAllocations, map2fl);
+ printDiffs(map2fl, map1fl, printer);
+ }
+ void storeAllocations()
+ {
+ mStoredAllocations.clear();
+ copyMap(mAllocations, mStoredAllocations);
+ }
+ bool hasStoredAllocations() { return mStoredAllocations.size() > 0; }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Utils.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Utils.h
new file mode 100644
index 00000000..f41a5fc0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/Utils.h
@@ -0,0 +1,382 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_UTILS_H
+#define QT3DS_RENDER_UTILS_H
+#include "EASTL/hash_map.h"
+#include "EASTL/hash_set.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSMath.h"
+#include <ctype.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ // Defined in IStringTable.cpp
+ extern const char16_t *char16EmptyStr;
+ extern const char32_t *char32EmptyStr;
+
+ inline const char *nonNull(const char *src) { return src == NULL ? "" : src; }
+ inline bool isTrivial(const char *str) { return str == NULL || *str == 0; }
+ inline const char16_t *nonNull(const char16_t *src)
+ {
+ return src == NULL ? char16EmptyStr : src;
+ }
+ inline bool isTrivial(const char16_t *str) { return str == NULL || *str == 0; }
+ inline const char32_t *nonNull(const char32_t *src)
+ {
+ return src == NULL ? char32EmptyStr : src;
+ }
+ inline bool isTrivial(const char32_t *str) { return str == NULL || *str == 0; }
+
+ // Note this is safe to call on null strings.
+ template <typename TCharType>
+ inline QT3DSU32 StrLen(const TCharType *inType)
+ {
+ QT3DSU32 retval = 0;
+ while (inType && *inType) {
+ ++retval;
+ ++inType;
+ }
+ return retval;
+ }
+
+ template <typename TCharType>
+ inline QT3DSI32 Compare(const TCharType *inLhs, const TCharType *inRhs)
+ {
+ inLhs = nonNull(inLhs);
+ inRhs = nonNull(inRhs);
+ while (*inLhs && *inRhs) {
+ QT3DSI32 diff = *inLhs - *inRhs;
+ if (diff)
+ return diff;
+ ++inLhs;
+ ++inRhs;
+ }
+ return *inLhs - *inRhs;
+ }
+
+ template <typename TCharType>
+ inline QT3DSI32 CompareCaseless(const TCharType *inLhs, const TCharType *inRhs)
+ {
+ inLhs = nonNull(inLhs);
+ inRhs = nonNull(inRhs);
+ while (*inLhs && *inRhs) {
+ QT3DSI32 diff = tolower(*inLhs) - tolower(*inRhs);
+ if (diff)
+ return diff;
+ ++inLhs;
+ ++inRhs;
+ }
+ return *inLhs - *inRhs;
+ }
+
+ template <typename TCharType>
+ inline QT3DSI32 CompareNChars(const TCharType *inLhs, const TCharType *inRhs, QT3DSU32 inNumChars)
+ {
+ inLhs = nonNull(inLhs);
+ inRhs = nonNull(inRhs);
+ while (*inLhs && *inRhs && inNumChars) {
+ QT3DSI32 diff = *inLhs - *inRhs;
+ if (diff)
+ return diff;
+ ++inLhs;
+ ++inRhs;
+ --inNumChars;
+ }
+ if (inNumChars)
+ return *inLhs - *inRhs;
+ return 0;
+ }
+
+ template <typename TCharType>
+ bool AreEqual(const TCharType *inLhs, const TCharType *inRhs)
+ {
+ return Compare(inLhs, inRhs) == 0;
+ }
+
+ template <typename TCharType>
+ bool AreEqualCaseless(const TCharType *inLhs, const TCharType *inRhs)
+ {
+ return CompareCaseless(inLhs, inRhs) == 0;
+ }
+
+ inline QT3DSU32 IsBitSetInBitmap(NVConstDataRef<QT3DSU32> bitmap, QT3DSU32 entryIndex)
+ {
+ QT3DSU32 bitMapIndex = entryIndex / 32;
+ QT3DSU32 bitIndex = entryIndex % 32;
+ QT3DSU32 shouldApply = 0;
+ if (bitMapIndex < bitmap.mSize)
+ shouldApply = (1 << bitIndex) & bitmap[bitMapIndex];
+ return shouldApply;
+ }
+
+ inline void SetBitInBitmap(nvvector<QT3DSU32> &bitmap, QT3DSU32 entryIndex)
+ {
+ QT3DSU32 bitMapIndex = entryIndex / 32;
+ QT3DSU32 bitIndex = entryIndex % 32;
+ while (bitmap.size() <= bitMapIndex)
+ bitmap.push_back(0);
+ bitmap[bitMapIndex] |= (QT3DSU32)(1 << bitIndex);
+ }
+ inline void UnsetBitInBitmap(nvvector<QT3DSU32> &bitmap, QT3DSU32 entryIndex)
+ {
+ QT3DSU32 bitMapIndex = entryIndex / 32;
+ QT3DSU32 bitIndex = entryIndex % 32;
+ if (bitMapIndex < bitmap.size())
+ bitmap[bitMapIndex] &= ~((QT3DSU32)(1 << bitIndex));
+ }
+
+#define CHECK_CONDITION_AND_RETURN_FALSE(cond, errorType, message) \
+ if (cond) { \
+ m_Foundation.error(errorType, message); \
+ QT3DS_ASSERT(false); \
+ return false; \
+ }
+// Returns false if the property type doesn't match the incoming type.
+#define CHECK_CONDITION_AND_RETURN(cond, errorType, message) \
+ if (cond) { \
+ m_Foundation.error(errorType, message); \
+ QT3DS_ASSERT(false); \
+ }
+
+#define UICBASE_FOREACH(varname, stop) for (QT3DSU32 varname = 0, end = stop; varname < end; ++varname)
+
+ template <typename TKeyType, typename TValueType, typename THashType, typename TPredicate,
+ typename TBufType, typename TOperator>
+ QT3DSU32 GetMapKeysOp(const eastl::hash_map<TKeyType, TValueType, THashType, TPredicate,
+ ForwardingAllocator> &map,
+ TBufType *buffer, QT3DSU32 bufSize, QT3DSU32 startIdx, TOperator op)
+ {
+ QT3DSU32 numItems = static_cast<QT3DSU32>(map.size());
+ if (numItems == 0 || bufSize == 0)
+ return 0;
+
+ startIdx = NVMin(numItems - 1, startIdx);
+ QT3DSU32 retval = 0;
+ for (typename eastl::hash_map<TKeyType, TValueType, THashType, TPredicate,
+ ForwardingAllocator>::const_iterator iter = map.begin(),
+ end = map.end();
+ iter != end && bufSize; ++iter) {
+ if (startIdx)
+ --startIdx;
+ else {
+ buffer[retval] = op(iter->first);
+ --bufSize;
+ ++retval;
+ }
+ }
+ return retval;
+ }
+
+ struct IdOp
+ {
+ template <typename TDataType>
+ TDataType operator()(const TDataType &item)
+ {
+ return item;
+ }
+ };
+
+ template <typename TKeyType, typename TValueType, typename THashType, typename TPredicateType>
+ QT3DSU32
+ GetMapKeys(const eastl::hash_map<TKeyType, TValueType, THashType, ForwardingAllocator> &map,
+ TKeyType *buffer, QT3DSU32 bufSize, QT3DSU32 startIdx)
+ {
+ return GetMapKeysOp(map, buffer, bufSize, startIdx, IdOp());
+ }
+
+ struct DerefOp
+ {
+ template <typename TDataType>
+ TDataType operator()(const TDataType *item)
+ {
+ return *item;
+ }
+ };
+
+ template <typename TKeyType, typename TValueType, typename THashType, typename TPredicateType,
+ typename TAllocatorType, typename TBufType, typename TOp>
+ QT3DSU32 GetMapValues(
+ const eastl::hash_map<TKeyType, TValueType, THashType, TPredicateType, TAllocatorType> &map,
+ TBufType *buffer, QT3DSU32 bufSize, QT3DSU32 startIdx, TOp op)
+ {
+ QT3DSU32 numItems = static_cast<QT3DSU32>(map.size());
+ if (numItems == 0 || bufSize == 0)
+ return 0;
+
+ startIdx = NVMin(numItems - 1, startIdx);
+ QT3DSU32 retval = 0;
+ for (typename eastl::hash_map<TKeyType, TValueType, THashType, TPredicateType,
+ TAllocatorType>::const_iterator iter = map.begin(),
+ end = map.end();
+ iter != end && bufSize; ++iter) {
+ if (startIdx)
+ --startIdx;
+ else {
+ buffer[retval] = op(iter->second);
+ --bufSize;
+ ++retval;
+ }
+ }
+ return retval;
+ }
+
+ template <typename TValueType, typename TBufType>
+ QT3DSU32 GetArrayEntries(const nvvector<TValueType> &data, TBufType *buffer, QT3DSU32 bufSize,
+ QT3DSU32 startIdx)
+ {
+ QT3DSU32 numItems = static_cast<QT3DSU32>(data.size());
+ if (numItems == 0 || bufSize == 0)
+ return 0;
+
+ startIdx = NVMin(numItems - 1, startIdx);
+ QT3DSU32 available = NVMin(numItems - startIdx, bufSize);
+ UICBASE_FOREACH(idx, available)
+ buffer[idx] = data[idx + startIdx];
+ return available;
+ }
+
+ template <typename TValueType, typename TBufType>
+ QT3DSU32 GetDataRefEntries(const NVDataRef<TValueType> &data, TBufType *buffer, QT3DSU32 bufSize,
+ QT3DSU32 startIdx)
+ {
+ QT3DSU32 numItems = static_cast<QT3DSU32>(data.size());
+ if (numItems == 0 || bufSize == 0)
+ return 0;
+
+ startIdx = NVMin(numItems - 1, startIdx);
+ QT3DSU32 available = NVMin(numItems - startIdx, bufSize);
+ UICBASE_FOREACH(idx, available)
+ buffer[idx] = data.mData[idx + startIdx];
+ return available;
+ }
+
+ template <typename TValueType, typename TBufType>
+ QT3DSU32 GetDataRefEntries(const NVConstDataRef<TValueType> &data, TBufType *buffer, QT3DSU32 bufSize,
+ QT3DSU32 startIdx)
+ {
+ QT3DSU32 numItems = static_cast<QT3DSU32>(data.size());
+ if (numItems == 0 || bufSize == 0)
+ return 0;
+
+ startIdx = NVMin(numItems - 1, startIdx);
+ QT3DSU32 available = NVMin(numItems - startIdx, bufSize);
+ UICBASE_FOREACH(idx, available)
+ buffer[idx] = data.mData[idx + startIdx];
+ return available;
+ }
+
+ template <typename TKeyType, typename THashType, typename TPredicate, typename TAllocator>
+ QT3DSU32 GetHashSetEntries(eastl::hash_set<TKeyType, THashType, TPredicate, TAllocator> &data,
+ TKeyType *buffer, QT3DSU32 bufSize, QT3DSU32 startIdx)
+ {
+ QT3DSU32 numItems = static_cast<QT3DSU32>(data.size());
+ if (numItems == 0 || bufSize == 0)
+ return 0;
+ startIdx = NVMin(numItems - 1, startIdx);
+ QT3DSU32 available = NVMin(numItems - startIdx, bufSize);
+ QT3DSU32 idx = 0;
+ for (typename eastl::hash_set<TKeyType, THashType, TPredicate, TAllocator>::const_iterator
+ iter = data.begin(),
+ end = data.end();
+ iter != end && idx < available; ++iter, ++idx) {
+ if (startIdx) {
+ --startIdx;
+ continue;
+ }
+ buffer[idx] = *iter;
+ }
+ return available;
+ }
+
+ template <typename TDataType>
+ void memCopyT(TDataType *dest, const TDataType *src, QT3DSU32 size)
+ {
+ memCopy(dest, src, size * sizeof(TDataType));
+ }
+
+ template <typename TDataType>
+ NVDataRef<TDataType> PtrAtOffset(QT3DSU8 *baseData, QT3DSU32 offset, QT3DSU32 byteSize)
+ {
+ return NVDataRef<TDataType>(byteSize ? (TDataType *)(baseData + offset) : NULL,
+ byteSize / sizeof(TDataType));
+ }
+
+ struct char_hasher
+ {
+ size_t operator()(const char *item) const { return eastl::hash<const char8_t *>()(item); }
+ };
+
+ struct char_equal_to
+ {
+ bool operator()(const char *lhs, const char *rhs) const
+ {
+ if (lhs == NULL)
+ lhs = "";
+ if (rhs == NULL)
+ rhs = "";
+ return strcmp(lhs, rhs) == 0;
+ }
+ };
+
+ struct wide_char_hasher
+ {
+ size_t operator()(const char16_t *item) const
+ {
+ return eastl::hash<const char16_t *>()(item);
+ }
+ };
+
+ struct wide_char_equal_to
+ {
+ bool operator()(const char16_t *lhs, const char16_t *rhs) const
+ {
+ if (lhs == NULL)
+ lhs = reinterpret_cast<const char16_t *>(L"");
+ if (rhs == NULL)
+ rhs = reinterpret_cast<const char16_t *>(L"");
+ while (*lhs && *rhs) {
+ int answer = *lhs - *rhs;
+ if (answer)
+ return false;
+ ++lhs;
+ ++rhs;
+ }
+ return *lhs == *rhs;
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/XML.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/XML.h
new file mode 100644
index 00000000..360bfdd7
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/XML.h
@@ -0,0 +1,680 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_FOUNDATION_XML_H
+#define QT3DS_FOUNDATION_XML_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "foundation/StringConversion.h" //Conversion between string and various datatypes.
+#include "foundation/Qt3DSFlags.h"
+#include "EASTL/algorithm.h"
+#include "foundation/IOStreams.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ class IStringTable;
+
+ class IDOMFactory;
+
+ class IInStream;
+ class IOutStream;
+ struct SDOMAttribute;
+ struct SDOMElement;
+ struct SNamespacePairNode;
+
+ typedef const char8_t *TXMLCharPtr;
+
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TXMLStr;
+
+ // When the factor is destroyed, all elements and attributes are destroyed.
+ class IDOMFactory : public NVRefCounted
+ {
+ protected:
+ virtual ~IDOMFactory() {}
+ public:
+ // Str does not need to be null terminated.
+ virtual void AppendStrBuf(TXMLCharPtr str, QT3DSU32 len) = 0;
+ // Null terminate what is there and return the buffer.
+ // This pointer needs to be persistent.
+ virtual TXMLCharPtr FinalizeStrBuf() = 0;
+ virtual void IgnoreStrBuf() = 0;
+
+ virtual SDOMAttribute *NextAttribute(CRegisteredString name, TXMLCharPtr val,
+ CRegisteredString ns = CRegisteredString(),
+ int inLine = 0) = 0;
+ virtual SDOMElement *NextElement(CRegisteredString name,
+ CRegisteredString ns = CRegisteredString(),
+ int inLine = 0) = 0;
+ virtual SNamespacePairNode *NextNSPairNode(CRegisteredString ns,
+ CRegisteredString abbr) = 0;
+
+ TXMLCharPtr RegisterValue(TXMLCharPtr inValue);
+
+ virtual NVScopedRefCounted<IStringTable> GetStringTable() = 0;
+ virtual NVAllocatorCallback &GetAllocator() = 0;
+
+ static NVScopedRefCounted<IDOMFactory>
+ CreateDOMFactory(NVAllocatorCallback &inAllocator,
+ NVScopedRefCounted<IStringTable> inStrTable);
+ };
+
+ struct SDOMAttribute
+ {
+ CRegisteredString m_Namespace;
+ CRegisteredString m_Name;
+ const char8_t *m_Value;
+ SDOMAttribute *m_NextAttribute;
+ SDOMAttribute *m_PreviousAttribute;
+ int m_Line;
+ SDOMAttribute()
+ : m_Value(NULL)
+ , m_NextAttribute(NULL)
+ , m_PreviousAttribute(NULL)
+ , m_Line(0)
+ {
+ }
+
+ SDOMAttribute(CRegisteredString inName, CRegisteredString inNs, const char8_t *inValue,
+ int line)
+ : m_Namespace(inNs)
+ , m_Name(inName)
+ , m_Value(inValue)
+ , m_NextAttribute(NULL)
+ , m_PreviousAttribute(NULL)
+ , m_Line(line)
+ {
+ }
+
+ bool Value(const char8_t *&outValue)
+ {
+ outValue = m_Value;
+ return true;
+ }
+
+ template <typename TDataType>
+ bool Value(TDataType &outValue)
+ {
+ StringConversion<TDataType>().StrTo(m_Value, outValue);
+ return true;
+ }
+ };
+
+ struct SNextAttOp
+ {
+ SDOMAttribute *get(SDOMAttribute &inAtt) { return inAtt.m_NextAttribute; }
+ const SDOMAttribute *get(const SDOMAttribute &inAtt) { return inAtt.m_NextAttribute; }
+ void set(SDOMAttribute &inAtt, SDOMAttribute *next) { inAtt.m_NextAttribute = next; }
+ };
+ struct SPrevAttOp
+ {
+ SDOMAttribute *get(SDOMAttribute &inAtt) { return inAtt.m_PreviousAttribute; }
+ const SDOMAttribute *get(const SDOMAttribute &inAtt) { return inAtt.m_PreviousAttribute; }
+ void set(SDOMAttribute &inAtt, SDOMAttribute *prev) { inAtt.m_PreviousAttribute = prev; }
+ };
+
+ typedef InvasiveLinkedList<SDOMAttribute, SPrevAttOp, SNextAttOp> TAttributeList;
+
+ struct SNamespacePair
+ {
+ CRegisteredString m_Namespace;
+ CRegisteredString m_Abbreviation;
+ SNamespacePair(CRegisteredString ns = CRegisteredString(),
+ CRegisteredString abbr = CRegisteredString())
+ : m_Namespace(ns)
+ , m_Abbreviation(abbr)
+ {
+ }
+ };
+
+ struct SNamespacePairNode : public SNamespacePair
+ {
+ SNamespacePairNode *m_NextNode;
+ SNamespacePairNode(const SNamespacePair &inSrc = SNamespacePair())
+ : SNamespacePair(inSrc)
+ , m_NextNode(NULL)
+ {
+ }
+ };
+
+ // Simplified dom element. All it has is one character value and list of attributes
+ // and children. So you can't mix elements and character data like you can in
+ // full xml, but this simplifies parsing.
+ struct SDOMElement
+ {
+ struct SNextElemOp
+ {
+ SDOMElement *get(SDOMElement &elem) { return elem.m_NextSibling; }
+ const SDOMElement *get(const SDOMElement &elem) { return elem.m_NextSibling; }
+ void set(SDOMElement &elem, SDOMElement *next) { elem.m_NextSibling = next; }
+ };
+ struct SPrevElemOp
+ {
+ SDOMElement *get(SDOMElement &elem) { return elem.m_PreviousSibling; }
+ const SDOMElement *get(const SDOMElement &elem) { return elem.m_PreviousSibling; }
+ void set(SDOMElement &elem, SDOMElement *prev) { elem.m_PreviousSibling = prev; }
+ };
+ typedef InvasiveLinkedList<SDOMElement, SPrevElemOp, SNextElemOp> TElementChildList;
+
+ CRegisteredString m_Namespace;
+ CRegisteredString m_Name;
+ const char8_t *m_Value;
+ SDOMElement *m_Parent;
+ SDOMElement *m_NextSibling;
+ SDOMElement *m_PreviousSibling;
+ TAttributeList m_Attributes;
+ TElementChildList m_Children;
+ int m_Line;
+
+ SDOMElement()
+ : m_Value(NULL)
+ , m_Parent(NULL)
+ , m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ , m_Line(0)
+ {
+ }
+
+ SDOMElement(CRegisteredString name, CRegisteredString ns, int inLine)
+ : m_Namespace(ns)
+ , m_Name(name)
+ , m_Value(NULL)
+ , m_Parent(NULL)
+ , m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ , m_Line(inLine)
+ {
+ }
+
+ void AppendChild(SDOMElement &inElem, SDOMElement *inPos = NULL)
+ {
+ if (inElem.m_Parent)
+ inElem.m_Parent->RemoveChild(inElem);
+ inElem.m_Parent = this;
+ if (inPos) {
+ QT3DS_ASSERT(inPos->m_Parent == this);
+ m_Children.insert_after(*inPos, inElem);
+ } else
+ m_Children.push_back(inElem);
+ }
+
+ void PrependChild(SDOMElement &inElem, SDOMElement *inPos = NULL)
+ {
+ if (inElem.m_Parent)
+ inElem.m_Parent->RemoveChild(inElem);
+ inElem.m_Parent = this;
+ if (inPos) {
+ QT3DS_ASSERT(inPos->m_Parent == this);
+ m_Children.insert_before(*inPos, inElem);
+ } else
+ m_Children.push_front(inElem);
+ }
+
+ void RemoveChild(SDOMElement &inElem)
+ {
+ if (inElem.m_Parent == this) {
+ m_Children.remove(inElem);
+ } else {
+ if (inElem.m_Parent) {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ SDOMElement *FindNext(CRegisteredString inName, Option<CRegisteredString> inNamespace,
+ TElementChildList::iterator iter)
+ {
+ for (TElementChildList::iterator end(NULL); iter != end; ++iter) {
+ if (inName.IsValid() == false || inName == iter->m_Name) {
+ if (inNamespace.hasValue() == false || *inNamespace == iter->m_Namespace)
+ return &(*iter);
+ }
+ }
+ return NULL;
+ }
+ // Search starts just *after inStartPos if provided
+ SDOMElement *FindChild(CRegisteredString inName, Option<CRegisteredString> inNamespace,
+ SDOMElement *inStartPos = NULL)
+ {
+ TElementChildList::iterator iter = m_Children.begin();
+ if (inStartPos) {
+ QT3DS_ASSERT(inStartPos->m_Parent == this);
+ iter = TElementChildList::iterator(inStartPos->m_NextSibling);
+ }
+ return FindNext(inName, inNamespace, iter);
+ }
+ // Search starts just *after inStartPos if provided
+ SDOMElement *FindSibling(CRegisteredString inName, Option<CRegisteredString> inNamespace)
+ {
+ TElementChildList::iterator iter(m_NextSibling);
+ return FindNext(inName, inNamespace, iter);
+ }
+
+ SDOMAttribute *FindAttribute(CRegisteredString inName,
+ Option<CRegisteredString> inNamespace)
+ {
+ for (TAttributeList::iterator iter = m_Attributes.begin(), end = m_Attributes.end();
+ iter != end; ++iter) {
+ if (iter->m_Name == inName) {
+ if (inNamespace.hasValue() == false || *inNamespace == iter->m_Namespace)
+ return &(*iter);
+ }
+ }
+ return NULL;
+ }
+
+ template <typename TDataType>
+ bool AttValue(CRegisteredString inName, Option<CRegisteredString> inNamespace,
+ TDataType &outValue)
+ {
+ SDOMAttribute *att = FindAttribute(inName, inNamespace);
+ if (att)
+ return att->Value(outValue);
+ return false;
+ }
+
+ QT3DSU32 GetNumChildren(CRegisteredString inName,
+ Option<CRegisteredString> inNamespace = Empty()) const
+ {
+ QT3DSU32 count = 0;
+ if (inName.IsValid() == false) {
+ // empty loop intentional
+ for (TElementChildList::iterator iter = m_Children.begin(), end = m_Children.end();
+ iter != end; ++iter, ++count)
+ ;
+ } else {
+ for (TElementChildList::iterator iter = m_Children.begin(), end = m_Children.end();
+ iter != end; ++iter) {
+ if (iter->m_Name == inName
+ && (inNamespace.isEmpty() || iter->m_Namespace == *inNamespace))
+ ++count;
+ }
+ }
+ return count;
+ }
+
+ void SetAttributeValue(CRegisteredString inName, Option<CRegisteredString> inNamespace,
+ TXMLCharPtr inValue, IDOMFactory &inFactory, int inLine)
+ {
+ SDOMAttribute *att = FindAttribute(inName, inNamespace);
+ if (att) {
+ att->m_Value = inFactory.RegisterValue(inValue);
+ } else {
+ m_Attributes.push_back(*inFactory.NextAttribute(
+ inName, inValue, inNamespace.unsafeGetValue(), inLine));
+ }
+ }
+
+ void RemoveAttribute(CRegisteredString nm, Option<CRegisteredString> inNamespace)
+ {
+ SDOMAttribute *theAttribute = FindAttribute(nm, inNamespace);
+ if (theAttribute)
+ m_Attributes.remove(*theAttribute);
+ }
+ };
+
+ struct SReaderScope
+ {
+ SDOMElement *m_Element;
+ SDOMAttribute *m_Attribute;
+ SReaderScope(SDOMElement *inElem = NULL, SDOMAttribute *inAtt = NULL)
+ : m_Element(inElem)
+ , m_Attribute(inAtt)
+ {
+ }
+ };
+
+ class IDOMReader : public NVRefCounted
+ {
+ protected:
+ virtual ~IDOMReader() {}
+ public:
+ // Stack object to save the reader's state.
+ struct Scope
+ {
+ IDOMReader &m_Reader;
+ Scope(IDOMReader &reader)
+ : m_Reader(reader)
+ {
+ m_Reader.PushScope();
+ }
+ Scope(NVScopedRefCounted<IDOMReader> reader)
+ : m_Reader(*reader)
+ {
+ m_Reader.PushScope();
+ }
+ ~Scope() { m_Reader.PopScope(); }
+ };
+
+ // Parse buffer
+ MemoryBuffer<ForwardingAllocator> m_TempBuf;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+
+ IDOMReader(NVAllocatorCallback &inAlloc, NVScopedRefCounted<IStringTable> inStringTable)
+ : m_TempBuf(ForwardingAllocator(inAlloc, "IDOMReader::m_TempBuf"))
+ , m_StringTable(inStringTable)
+ {
+ }
+
+ NVScopedRefCounted<IStringTable> GetStringTable() { return m_StringTable; }
+
+ // Pushing scope saves your state so no matter where you are when
+ // you next pop scope, you come back to the same state.
+ virtual void PushScope() = 0;
+ virtual void PopScope() = 0;
+
+ // Sometimes pushing and popping scope isn't enough and you need
+ // somewhat random access to scope.
+ // This scope does not remember the current attribute.
+ virtual SReaderScope GetScope() = 0;
+ virtual void SetScope(SReaderScope inScope) = 0;
+ // Return an attribute whose value is *not* registered with the string table.
+ // You can't hold onto this value for any length of time, but when you need to
+ // immediately convert to a different value this is the most efficient way.
+ virtual bool UnregisteredAtt(TXMLCharPtr name, TXMLCharPtr &outValue,
+ TXMLCharPtr ns = NULL) = 0;
+ // Return an attribute whose value *is* registered with the string table.
+ virtual bool Att(TXMLCharPtr name, CRegisteredString &outValue, TXMLCharPtr ns = NULL) = 0;
+ virtual SDOMAttribute *GetFirstAttribute() = 0;
+ virtual SDOMAttribute *GetNextAttribute() = 0;
+ virtual QT3DSU32 CountChildren(TXMLCharPtr childName = NULL, TXMLCharPtr ns = NULL) = 0;
+ virtual bool MoveToFirstChild(TXMLCharPtr childName = NULL, TXMLCharPtr ns = NULL) = 0;
+ virtual bool MoveToNextSibling(TXMLCharPtr siblingName = NULL, TXMLCharPtr ns = NULL) = 0;
+ // Leave element means go to its parent.
+ virtual void Leave() = 0;
+ virtual SDOMElement *GetElement() const = 0;
+ CRegisteredString GetElementName() const
+ {
+ SDOMElement *elem = GetElement();
+ if (elem)
+ return elem->m_Name;
+ return CRegisteredString();
+ }
+
+ // Value is the concatentated text node values inside the element
+ virtual bool Value(TXMLCharPtr &outValue) = 0;
+
+ // Get the element this reader was created with
+ virtual SDOMElement *GetTopElement() = 0;
+
+ bool Att(TXMLCharPtr name, TXMLStr &outValue)
+ {
+ TXMLCharPtr temp;
+ if (UnregisteredAtt(name, temp)) {
+ outValue.assign(temp);
+ return true;
+ }
+ return false;
+ }
+
+ template <typename TDataType>
+ bool Att(TXMLCharPtr name, TDataType &outValue)
+ {
+ TXMLCharPtr temp;
+ if (UnregisteredAtt(name, temp)) {
+ StringConversion<TDataType>().StrTo(temp, outValue);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool ChildValue(TXMLCharPtr name, TXMLCharPtr &value)
+ {
+ if (MoveToFirstChild(name)) {
+ Value(value);
+ Leave();
+ return true;
+ }
+ return false;
+ }
+
+ bool RegisteredChildValue(TXMLCharPtr name, TXMLCharPtr &value)
+ {
+ if (MoveToFirstChild(name)) {
+ RegisteredValue(value);
+ Leave();
+ return true;
+ }
+ return false;
+ }
+ bool RegisteredValue(TXMLCharPtr &outValue)
+ {
+ bool retval = Value(outValue);
+ if (retval)
+ outValue = m_StringTable->RegisterStr(outValue);
+ return retval;
+ }
+
+ template <typename TDataType>
+ bool Value(TDataType &outValue)
+ {
+ TXMLCharPtr value;
+ if (Value(value)) {
+ StringConversion<TDataType>().StrTo(value, outValue);
+ return true;
+ }
+ return false;
+ }
+
+ // IDOMReader implementations
+ template <typename TDataType>
+ bool ValueList(NVDataRef<TDataType> data)
+ {
+ const char8_t *value;
+ if (Value(value)) {
+ Char8TReader reader(const_cast<char8_t *>(value), m_TempBuf);
+ reader.ReadRef(data);
+ }
+ return true;
+ }
+
+ // Destructive operation because we can't trust
+ // strtod to do the right thing. On windows, for long strings,
+ // it calls strlen every operation thus leading to basically N^2
+ // behavior
+ template <typename TDataType>
+ NVConstDataRef<TDataType> ChildValueList(TXMLCharPtr listName)
+ {
+ NVConstDataRef<TDataType> retval;
+ TXMLCharPtr childValue = NULL;
+ if (ChildValue(listName, childValue)) {
+ Char8TReader reader(const_cast<char8_t *>(childValue), m_TempBuf);
+ reader.ReadBuffer(retval);
+ }
+ return retval;
+ }
+
+ template <typename TSerializer>
+ void Serialize(const char8_t *elemName, TSerializer &serializer,
+ const char8_t *inNamespace = NULL)
+ {
+ IDOMReader::Scope __theScope(*this);
+ if (MoveToFirstChild(elemName, inNamespace)) {
+ serializer.Serialize(*this);
+ }
+ }
+ // Optionally hold on to the factory to keep our elements in memory as long as we are.
+ static NVScopedRefCounted<IDOMReader> CreateDOMReader(
+ NVAllocatorCallback &inAlloc, SDOMElement &inRootElement,
+ NVScopedRefCounted<IStringTable> inStringTable,
+ NVScopedRefCounted<IDOMFactory> inFactory = NVScopedRefCounted<IDOMFactory>());
+ };
+
+ // Write out data in an xml-like fasion without specifying exactly
+ // where that data is being written.
+ class IDOMWriter : public NVRefCounted
+ {
+ protected:
+ virtual ~IDOMWriter() {}
+ public:
+ // Control the element scope.
+ struct Scope
+ {
+ IDOMWriter &m_Writer;
+ Scope(IDOMWriter &writer, TXMLCharPtr inElemName, TXMLCharPtr inNamespace = NULL)
+ : m_Writer(writer)
+ {
+ m_Writer.Begin(inElemName, inNamespace);
+ }
+ ~Scope() { m_Writer.End(); }
+ };
+
+ char8_t m_NarrowBuf[256];
+
+ // There tend to be two types of elements.
+ // Containers (<a>\n\t<b/><b/>\n</a>)
+ // and Values <b>onetwothree</b>
+ virtual void Begin(TXMLCharPtr inElemName, TXMLCharPtr inNamespace = NULL,
+ int inLine = 0) = 0;
+ // Attributes. They may be sorted just before write
+ virtual void Att(TXMLCharPtr name, TXMLCharPtr value, TXMLCharPtr inNamespace = NULL,
+ int inLine = 0) = 0;
+ virtual void Value(TXMLCharPtr value) = 0;
+ virtual void End() = 0;
+ virtual void RemoveCurrent() = 0;
+ virtual void RemoveAttribute(TXMLCharPtr inItem, TXMLCharPtr inNamespace = NULL) = 0;
+ // Get the number of tabs required to line up the next line
+ // with the opening of the previous line
+ virtual QT3DSU32 GetTabs() = 0;
+ virtual SDOMElement *GetTopElement() = 0;
+ virtual NVScopedRefCounted<IDOMFactory> GetFactory() = 0;
+ // Move this item before this sibling. Function does not rearrange the
+ // tree in any major way and will not work if inItem and inSibling aren't
+ // siblings.
+ virtual void MoveBefore(TXMLCharPtr inItem, TXMLCharPtr inSibling,
+ TXMLCharPtr inNamespace = NULL) = 0;
+ virtual NVAllocatorCallback &GetAllocator() = 0;
+
+ virtual void ChildValue(TXMLCharPtr name, TXMLCharPtr value, TXMLCharPtr inNamespace = NULL)
+ {
+ Begin(name, inNamespace);
+ Value(value);
+ End();
+ }
+
+ TXMLCharPtr ToStr(char8_t val)
+ {
+ m_NarrowBuf[0] = val;
+ m_NarrowBuf[1] = 0;
+ return m_NarrowBuf;
+ }
+
+ template <typename TDataType>
+ TXMLCharPtr ToStr(TDataType val)
+ {
+ StringConversion<TDataType>().ToStr(val, NVDataRef<char8_t>(m_NarrowBuf, 256));
+ return m_NarrowBuf;
+ }
+
+ void Att(TXMLCharPtr name, const TXMLStr &inValue, TXMLCharPtr inNamespace = NULL)
+ {
+ return Att(name, inValue.c_str(), inNamespace);
+ }
+
+ template <typename TData>
+ void Att(TXMLCharPtr name, TData value, TXMLCharPtr inNamespace = NULL)
+ {
+ Att(name, ToStr(value), inNamespace);
+ }
+
+ template <typename TSerializer>
+ void Serialize(const char8_t *elemName, TSerializer &serializer,
+ TXMLCharPtr inNamespace = NULL)
+ {
+ IDOMWriter::Scope __theScope(*this, elemName, inNamespace);
+ serializer.Serialize(*this);
+ }
+
+ NVScopedRefCounted<IDOMReader> CreateDOMReader()
+ {
+ NVScopedRefCounted<IDOMFactory> theFactory(GetFactory());
+ return IDOMReader::CreateDOMReader(GetAllocator(), *GetTopElement(),
+ theFactory->GetStringTable(), theFactory);
+ }
+
+ // Note that the default method of creating a writer also creates a reader; they can
+ // both manipulation the DOM hierarch.
+ static eastl::pair<NVScopedRefCounted<IDOMWriter>, NVScopedRefCounted<IDOMReader>>
+ CreateDOMWriter(NVScopedRefCounted<IDOMFactory> inFactory, SDOMElement &inRootElement,
+ NVScopedRefCounted<IStringTable> inStringTable);
+
+ static eastl::pair<NVScopedRefCounted<IDOMWriter>, NVScopedRefCounted<IDOMReader>>
+ CreateDOMWriter(NVAllocatorCallback &inAlloc, const char8_t *inTopElemName,
+ NVScopedRefCounted<IStringTable> inStringTable,
+ const char8_t *inNamespace = NULL)
+ {
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(inAlloc, inStringTable));
+ SDOMElement *theRoot =
+ theFactory->NextElement(theFactory->GetStringTable()->RegisterStr(inTopElemName),
+ theFactory->GetStringTable()->RegisterStr(inNamespace));
+ return CreateDOMWriter(theFactory, *theRoot, inStringTable);
+ }
+ };
+
+ class CXmlErrorHandler
+ {
+ protected:
+ virtual ~CXmlErrorHandler() {}
+ public:
+ virtual void OnXmlError(TXMLCharPtr errorName, int line, int column) = 0;
+ };
+
+ class CDOMSerializer
+ {
+ public:
+ static void WriteXMLHeader(IOutStream &inStream);
+
+ // Write out the elements. These pairs will be used in order to abbreviate namespaces with
+ // nicer abbreviations.
+ // Any namespaces not found in those pairs will get auto-generated abbreviations
+ // The document will be assumed to be in the namespace that has no abbreviation.
+ // For fragments or snippets, it is better to avoid writing out the namespace declarations
+ static void
+ Write(NVAllocatorCallback &inAlloc, SDOMElement &inElement, IOutStream &inStream,
+ IStringTable &inStrTable,
+ NVConstDataRef<SNamespacePair> inNamespaces = NVConstDataRef<SNamespacePair>(),
+ bool inTrimEmptyElements = true, QT3DSU32 inTabs = 0, bool inWriteNamespaces = true);
+
+ // Returns a pair of the namespace pair nodes and the dom element. The ns pair nodes allow
+ // us to at least keep the same abbreviations
+ // used if namespace are used.
+ static eastl::pair<SNamespacePairNode *, SDOMElement *>
+ Read(IDOMFactory &inFactory, IInStream &inStream, CXmlErrorHandler *inErrorHandler = NULL);
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/LICENSE.TXT b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/LICENSE.TXT
new file mode 100644
index 00000000..f40caef8
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/LICENSE.TXT
@@ -0,0 +1,7 @@
+ Copyright (c) 2001 Intel Corporation.
+
+Permition is granted to use, copy, distribute and prepare derivative works
+of this library for any purpose and without fee, provided, that the above
+copyright notice and this statement appear in all copies.
+Intel makes no representations about the suitability of this library for
+any purpose, and specifically disclaims all warranties.
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxAoS.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxAoS.h
new file mode 100644
index 00000000..6bcb4406
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxAoS.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_LINUX_AOS_H
+#define QT3DS_LINUX_AOS_H
+
+// no includes here! this file should be included from NVcVecMath.h only!!!
+
+#if !COMPILE_VECTOR_INTRINSICS
+#error Vector intrinsics should not be included when using scalar implementation.
+#endif
+
+// only SSE compatible platforms should reach this
+// likely to be split up when we add NEON support.
+#include <xmmintrin.h>
+
+typedef union UnionM128 {
+ UnionM128() {}
+ UnionM128(__m128 in) { m128 = in; }
+
+ UnionM128(__m128i in) { m128i = in; }
+
+ operator __m128() { return m128; }
+
+ operator const __m128() const { return m128; }
+
+ float m128_f32[4];
+ __int8_t m128_i8[16];
+ __int16_t m128_i16[8];
+ __int32_t m128_i32[4];
+ __int64_t m128_i64[2];
+ __uint16_t m128_u16[8];
+ __uint32_t m128_u32[4];
+ __uint64_t m128_u64[2];
+ __m128 m128;
+ __m128i m128i;
+} UnionM128;
+
+typedef __m128 FloatV;
+typedef __m128 Vec3V;
+typedef __m128 Vec4V;
+typedef __m128 BoolV;
+typedef __m128 QuatV;
+// typedef __m128 VecU32V;
+// typedef __m128 VecI32V;
+// typedef __m128 VecU16V;
+// typedef __m128 VecI16V;
+// typedef __m128 VecU8V;
+typedef UnionM128 VecU32V;
+typedef UnionM128 VecI32V;
+typedef UnionM128 VecU16V;
+typedef UnionM128 VecI16V;
+typedef UnionM128 VecU8V;
+
+#define FloatVArg FloatV &
+#define Vec3VArg Vec3V &
+#define Vec4VArg Vec4V &
+#define BoolVArg BoolV &
+#define VecU32VArg VecU32V &
+#define VecI32VArg VecI32V &
+#define VecU16VArg VecU16V &
+#define VecI16VArg VecI16V &
+#define VecU8VArg VecU8V &
+#define QuatVArg QuatV &
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat33V
+{
+ Mat33V() {}
+ Mat33V(const Vec3V &c0, const Vec3V &c1, const Vec3V &c2)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ {
+ }
+ Vec3V QT3DS_ALIGN(16, col0);
+ Vec3V QT3DS_ALIGN(16, col1);
+ Vec3V QT3DS_ALIGN(16, col2);
+} QT3DS_ALIGN_SUFFIX(16);
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat34V
+{
+ Mat34V() {}
+ Mat34V(const Vec3V &c0, const Vec3V &c1, const Vec3V &c2, const Vec3V &c3)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ , col3(c3)
+ {
+ }
+ Vec3V QT3DS_ALIGN(16, col0);
+ Vec3V QT3DS_ALIGN(16, col1);
+ Vec3V QT3DS_ALIGN(16, col2);
+ Vec3V QT3DS_ALIGN(16, col3);
+} QT3DS_ALIGN_SUFFIX(16);
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat43V
+{
+ Mat43V() {}
+ Mat43V(const Vec4V &c0, const Vec4V &c1, const Vec4V &c2)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ {
+ }
+ Vec4V QT3DS_ALIGN(16, col0);
+ Vec4V QT3DS_ALIGN(16, col1);
+ Vec4V QT3DS_ALIGN(16, col2);
+} QT3DS_ALIGN_SUFFIX(16);
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat44V
+{
+ Mat44V() {}
+ Mat44V(const Vec4V &c0, const Vec4V &c1, const Vec4V &c2, const Vec4V &c3)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ , col3(c3)
+ {
+ }
+ Vec4V QT3DS_ALIGN(16, col0);
+ Vec4V QT3DS_ALIGN(16, col1);
+ Vec4V QT3DS_ALIGN(16, col2);
+ Vec4V QT3DS_ALIGN(16, col3);
+} QT3DS_ALIGN_SUFFIX(16);
+
+#endif // QT3DS_LINUX_AOS_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxFile.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxFile.h
new file mode 100644
index 00000000..1369735f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxFile.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_LINUX_FILE_H
+#define QT3DS_FOUNDATION_QT3DS_LINUX_FILE_H
+
+#include "foundation/Qt3DS.h"
+#include <stdio.h>
+
+namespace qt3ds {
+namespace foundation {
+ QT3DS_INLINE int fopen_s(FILE **_File, const char *_Filename, const char *_Mode)
+ {
+ FILE *fp = ::fopen(_Filename, _Mode);
+ return fp ? *_File = fp, 0 : -1;
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxInlineAoS.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxInlineAoS.h
new file mode 100644
index 00000000..0443ba90
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxInlineAoS.h
@@ -0,0 +1,2666 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// Copyright (c) 2001 Intel Corporation.
+//
+// Permition is granted to use, copy, distribute and prepare derivative works
+// of this library for any purpose and without fee, provided, that the above
+// copyright notice and this statement appear in all copies.
+// Intel makes no representations about the suitability of this library for
+// any purpose, and specifically disclaims all warranties.
+// See LEGAL.TXT for all the legal information.
+//
+
+#ifndef QT3DS_LINUX_INLINE_AOS_H
+#define QT3DS_LINUX_INLINE_AOS_H
+
+#if !COMPILE_VECTOR_INTRINSICS
+#error Vector intrinsics should not be included when using scalar implementation.
+#endif
+
+// Remove this define when all platforms use simd solver.
+#define QT3DS_SUPPORT_SIMD
+
+#define _QT3DS_FPCLASS_SNAN 0x0001 /* signaling NaN */
+#define _QT3DS_FPCLASS_QNAN 0x0002 /* quiet NaN */
+#define _QT3DS_FPCLASS_NINF 0x0004 /* negative infinity */
+#define _QT3DS_FPCLASS_PINF 0x0200 /* positive infinity */
+
+QT3DS_FORCE_INLINE __m128 m128_I2F(__m128i n)
+{
+ return _mm_castsi128_ps(n);
+}
+QT3DS_FORCE_INLINE __m128i m128_F2I(__m128 n)
+{
+ return _mm_castps_si128(n);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAllTrue4_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return moveMask == (0xf);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAnyTrue4_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return moveMask != (0x0);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAllTrue3_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return (moveMask & 0x7) == (0x7);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAnyTrue3_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return (moveMask & 0x7) != (0x0);
+}
+
+/////////////////////////////////////////////////////////////////////
+////FUNCTIONS USED ONLY FOR ASSERTS IN VECTORISED IMPLEMENTATIONS
+/////////////////////////////////////////////////////////////////////
+
+QT3DS_FORCE_INLINE QT3DSU32 FiniteTestEq(const Vec4V a, const Vec4V b)
+{
+ // This is a bit of a bodge.
+ //_mm_comieq_ss returns 1 if either value is nan so we need to re-cast a and b with true encoded
+ //as a non-nan number.
+ // There must be a better way of doing this in sse.
+ const BoolV one = FOne();
+ const BoolV zero = FZero();
+ const BoolV a1 = V4Sel(a, one, zero);
+ const BoolV b1 = V4Sel(b, one, zero);
+ return (_mm_comieq_ss(a1, b1) && _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(1, 1, 1, 1)),
+ _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(1, 1, 1, 1)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(2, 2, 2, 2)),
+ _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(2, 2, 2, 2)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(3, 3, 3, 3)),
+ _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(3, 3, 3, 3))));
+}
+
+QT3DS_FORCE_INLINE bool isValidFloatV(const FloatV a)
+{
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3))));
+}
+
+QT3DS_FORCE_INLINE bool isValidVec3V(const Vec3V a)
+{
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)), FZero()) ? true : false);
+}
+
+QT3DS_FORCE_INLINE bool isFiniteFloatV(const FloatV a)
+{
+ const QT3DSU32 badNumber =
+ (_QT3DS_FPCLASS_SNAN | _QT3DS_FPCLASS_QNAN | _QT3DS_FPCLASS_NINF | _QT3DS_FPCLASS_PINF);
+ const FloatV vBadNum = FloatV_From_F32((QT3DSF32 &)badNumber);
+ const BoolV vMask = BAnd(vBadNum, a);
+ return FiniteTestEq(vMask, BFFFF()) == 1;
+}
+
+QT3DS_FORCE_INLINE bool isFiniteVec3V(const Vec3V a)
+{
+ const QT3DSU32 badNumber =
+ (_QT3DS_FPCLASS_SNAN | _QT3DS_FPCLASS_QNAN | _QT3DS_FPCLASS_NINF | _QT3DS_FPCLASS_PINF);
+ const Vec3V vBadNum = Vec3V_From_F32((QT3DSF32 &)badNumber);
+ const BoolV vMask = BAnd(BAnd(vBadNum, a), BTTTF());
+ return FiniteTestEq(vMask, BFFFF()) == 1;
+}
+
+QT3DS_FORCE_INLINE bool isFiniteVec4V(const Vec4V a)
+{
+ /*Vec4V a;
+ QT3DS_ALIGN(16, QT3DSF32 f[4]);
+ F32Array_Aligned_From_Vec4V(a, f);
+ return NVIsFinite(f[0])
+ && NVIsFinite(f[1])
+ && NVIsFinite(f[2])
+ && NVIsFinite(f[3]);*/
+
+ const QT3DSU32 badNumber =
+ (_QT3DS_FPCLASS_SNAN | _QT3DS_FPCLASS_QNAN | _QT3DS_FPCLASS_NINF | _QT3DS_FPCLASS_PINF);
+ const Vec4V vBadNum = Vec4V_From_F32((QT3DSF32 &)badNumber);
+ const BoolV vMask = BAnd(vBadNum, a);
+
+ return FiniteTestEq(vMask, BFFFF()) == 1;
+}
+
+QT3DS_FORCE_INLINE bool hasZeroElementinFloatV(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FloatV_From_F32(0.0f))
+ ? true
+ : false);
+}
+
+QT3DS_FORCE_INLINE bool hasZeroElementInVec3V(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FloatV_From_F32(0.0f))
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FloatV_From_F32(0.0f))
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FloatV_From_F32(0.0f)));
+}
+
+QT3DS_FORCE_INLINE bool hasZeroElementInVec4V(const Vec4V a)
+{
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FloatV_From_F32(0.0f))
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FloatV_From_F32(0.0f))
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FloatV_From_F32(0.0f))
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)), FloatV_From_F32(0.0f)));
+}
+
+/////////////////////////////////////////////////////////////////////
+////VECTORISED FUNCTION IMPLEMENTATIONS
+/////////////////////////////////////////////////////////////////////
+
+QT3DS_FORCE_INLINE FloatV FloatV_From_F32(const QT3DSF32 f)
+{
+ return (_mm_load1_ps(&f));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_F32(const QT3DSF32 f)
+{
+ return _mm_set_ps(0.0f, f, f, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_F32(const QT3DSF32 f)
+{
+ return (_mm_load1_ps(&f));
+}
+
+QT3DS_FORCE_INLINE BoolV BoolV_From_Bool32(const bool f)
+{
+ const QT3DSU32 i = -(QT3DSI32)f;
+ return _mm_load1_ps((float *)&i);
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_NVVec3_Aligned(const QT3DSVec3 &f)
+{
+ VECMATHAOS_ASSERT(0 == ((size_t)&f & 0x0f));
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_NVVec3(const QT3DSVec3 &f)
+{
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_NVVec3_WUndefined(const QT3DSVec3 &f)
+{
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V v)
+{
+ return V4SetW(v, V4Zero());
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f)
+{
+ return f; // ok if it is implemented as the same type.
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_NVVec3_WUndefined(const QT3DSVec3 &f)
+{
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Mat33V Mat33V_From_NVMat33(const QT3DSMat33 &m)
+{
+ return Mat33V(Vec3V_From_NVVec3(m.column0), Vec3V_From_NVVec3(m.column1),
+ Vec3V_From_NVVec3(m.column2));
+}
+
+QT3DS_FORCE_INLINE void NVMat33_From_Mat33V(const Mat33V &m, QT3DSMat33 &out)
+{
+ QT3DS_ASSERT((size_t(&out) & 15) == 0);
+ NVVec3_From_Vec3V(m.col0, out.column0);
+ NVVec3_From_Vec3V(m.col1, out.column1);
+ NVVec3_From_Vec3V(m.col2, out.column2);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_F32Array_Aligned(const QT3DSF32 *const f)
+{
+ VECMATHAOS_ASSERT(0 == ((QT3DSU64)f & 0x0f));
+ return (_mm_load_ps(f));
+}
+
+QT3DS_FORCE_INLINE void F32Array_Aligned_From_Vec4V(Vec4V a, QT3DSF32 *f)
+{
+ VECMATHAOS_ASSERT(0 == ((QT3DSU64)f & 0x0f));
+ _mm_store_ps(f, a);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_F32Array(const QT3DSF32 *const f)
+{
+ return (_mm_loadu_ps(f));
+}
+
+QT3DS_FORCE_INLINE BoolV BoolV_From_Bool32Array(const bool *const f)
+{
+ const QT3DS_ALIGN(16, QT3DSU32) b[4] = { -(QT3DSI32)f[0], -(QT3DSI32)f[1], -(QT3DSI32)f[2], -(QT3DSI32)f[3] };
+ return _mm_load1_ps((float *)&b);
+}
+
+QT3DS_FORCE_INLINE QT3DSF32 NVF32_From_FloatV(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ QT3DSF32 f;
+ _mm_store_ss(&f, a);
+ return f;
+}
+
+QT3DS_FORCE_INLINE void NVF32_From_FloatV(const FloatV a, QT3DSF32 *QT3DS_RESTRICT f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ _mm_store_ss(f, a);
+}
+
+QT3DS_FORCE_INLINE void NVVec3Aligned_From_Vec3V(const Vec3V a, QT3DSVec3 &f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(0 == ((int)&a & 0x0F));
+ VECMATHAOS_ASSERT(0 == ((int)&f & 0x0F));
+ QT3DS_ALIGN(16, QT3DSF32) f2[4];
+ _mm_store_ps(f2, a);
+ f = QT3DSVec3(f2[0], f2[1], f2[2]);
+}
+
+QT3DS_FORCE_INLINE void NVVec3_From_Vec3V(const Vec3V a, QT3DSVec3 &f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(0 == ((int)&a & 0x0F));
+ QT3DS_ALIGN(16, QT3DSF32) f2[4];
+ _mm_store_ps(f2, a);
+ f = QT3DSVec3(f2[0], f2[1], f2[2]);
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualFloatV(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return (_mm_comieq_ss(a, b) != 0);
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualVec3V(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return V3AllEq(a, b) != 0;
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualVec4V(const Vec4V a, const Vec4V b)
+{
+ return V4AllEq(a, b) != 0;
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualBoolV(const BoolV a, const BoolV b)
+{
+ return BAllTrue4_R(VecI32V_IsEq(a, b)) != 0;
+}
+
+#define VECMATH_AOS_EPSILON (1e-3f)
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsNearEqualFloatV(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ const FloatV c = FSub(a, b);
+ const FloatV minError = FloatV_From_F32(-VECMATH_AOS_EPSILON);
+ const FloatV maxError = FloatV_From_F32(VECMATH_AOS_EPSILON);
+ return (_mm_comigt_ss(c, minError) && _mm_comilt_ss(c, maxError));
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsNearEqualVec3V(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ const Vec3V c = V3Sub(a, b);
+ const Vec3V minError = Vec3V_From_F32(-VECMATH_AOS_EPSILON);
+ const Vec3V maxError = Vec3V_From_F32(VECMATH_AOS_EPSILON);
+ return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxError));
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsNearEqualVec4V(const Vec4V a, const Vec4V b)
+{
+ const Vec4V c = V4Sub(a, b);
+ const Vec4V minError = Vec4V_From_F32(-VECMATH_AOS_EPSILON);
+ const Vec4V maxError = Vec4V_From_F32(VECMATH_AOS_EPSILON);
+ return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), maxError));
+}
+
+//////////////////////////////////
+// FLOATV
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE FloatV FZero()
+{
+ return FloatV_From_F32(0.0f);
+}
+
+QT3DS_FORCE_INLINE FloatV FOne()
+{
+ return FloatV_From_F32(1.0f);
+}
+
+QT3DS_FORCE_INLINE FloatV FHalf()
+{
+ return FloatV_From_F32(0.5f);
+}
+
+QT3DS_FORCE_INLINE FloatV FEps()
+{
+ return FloatV_From_F32(QT3DS_ENV_REAL);
+}
+
+QT3DS_FORCE_INLINE FloatV FEps6()
+{
+ return FloatV_From_F32(1e-6f);
+}
+
+QT3DS_FORCE_INLINE FloatV FMax()
+{
+ return FloatV_From_F32(QT3DS_MAX_REAL);
+}
+
+QT3DS_FORCE_INLINE FloatV FNegMax()
+{
+ return FloatV_From_F32(-QT3DS_MAX_REAL);
+}
+
+QT3DS_FORCE_INLINE FloatV IZero()
+{
+ const QT3DSU32 zero = 0;
+ return _mm_load1_ps((QT3DSF32 *)&zero);
+}
+
+QT3DS_FORCE_INLINE FloatV IOne()
+{
+ const QT3DSU32 one = 1;
+ return _mm_load1_ps((QT3DSF32 *)&one);
+}
+
+QT3DS_FORCE_INLINE FloatV ITwo()
+{
+ const QT3DSU32 two = 2;
+ return _mm_load1_ps((QT3DSF32 *)&two);
+}
+
+QT3DS_FORCE_INLINE FloatV IThree()
+{
+ const QT3DSU32 three = 3;
+ return _mm_load1_ps((QT3DSF32 *)&three);
+}
+
+QT3DS_FORCE_INLINE FloatV IFour()
+{
+ QT3DSU32 four = 4;
+ return _mm_load1_ps((QT3DSF32 *)&four);
+}
+
+QT3DS_FORCE_INLINE FloatV FNeg(const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return _mm_sub_ps(_mm_setzero_ps(), f);
+}
+
+QT3DS_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_add_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_sub_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE FloatV FRecip(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return _mm_rcp_ps(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FRecipFast(const FloatV a)
+{
+ return FRecip(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FRsqrt(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return _mm_rsqrt_ps(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FSqrt(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return _mm_sqrt_ps(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FRsqrtFast(const FloatV a)
+{
+ return FRsqrt(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidFloatV(c));
+ return FAdd(FMul(a, b), c);
+}
+
+QT3DS_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidFloatV(c));
+ return FSub(c, FMul(a, b));
+}
+
+QT3DS_FORCE_INLINE FloatV FAbs(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ QT3DS_ALIGN(16, const QT3DSU32) absMask[4] = { 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF };
+ return _mm_and_ps(a, _mm_load_ps((QT3DSF32 *)absMask));
+}
+
+QT3DS_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(_VecMathTests::allElementsEqualBoolV(c, BTTTT())
+ || _VecMathTests::allElementsEqualBoolV(c, BFFFF()));
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
+}
+
+QT3DS_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_cmpgt_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_cmpge_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_max_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_min_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(minV));
+ VECMATHAOS_ASSERT(isValidFloatV(maxV));
+ return FMax(FMin(a, maxV), minV);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FAllGrtr(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return (_mm_comigt_ss(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FAllGrtrOrEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+
+ return (_mm_comige_ss(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FAllEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+
+ return (_mm_comieq_ss(a, b));
+}
+
+QT3DS_FORCE_INLINE FloatV FRound(const FloatV a)
+{
+ // return _mm_round_ps(a, 0x0);
+ const Vec3V half = Vec3V_From_F32(0.5f);
+ const Vec3V aPlusHalf = V3Add(a, half);
+ __m128i tmp = _mm_cvttps_epi32(aPlusHalf);
+ return _mm_cvtepi32_ps(tmp);
+}
+
+QT3DS_FORCE_INLINE FloatV FSin(const FloatV a)
+{
+ // Vec4V V1, V2, V3, V5, V7, V9, V11, V13, V15, V17, V19, V21, V23;
+ // Vec4V S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11;
+ FloatV Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const FloatV twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const FloatV tmp = FMul(a, twoPi);
+ const FloatV b = FRound(tmp);
+ const FloatV V1 = FNegMulSub(twoPi, b, a);
+
+ // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
+ // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
+ const FloatV V2 = FMul(V1, V1);
+ const FloatV V3 = FMul(V2, V1);
+ const FloatV V5 = FMul(V3, V2);
+ const FloatV V7 = FMul(V5, V2);
+ const FloatV V9 = FMul(V7, V2);
+ const FloatV V11 = FMul(V9, V2);
+ const FloatV V13 = FMul(V11, V2);
+ const FloatV V15 = FMul(V13, V2);
+ const FloatV V17 = FMul(V15, V2);
+ const FloatV V19 = FMul(V17, V2);
+ const FloatV V21 = FMul(V19, V2);
+ const FloatV V23 = FMul(V21, V2);
+
+ const Vec4V sinCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients0.f);
+ const Vec4V sinCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients1.f);
+ const Vec4V sinCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients2.f);
+
+ const FloatV S1 = V4GetY(sinCoefficients0);
+ const FloatV S2 = V4GetZ(sinCoefficients0);
+ const FloatV S3 = V4GetW(sinCoefficients0);
+ const FloatV S4 = V4GetX(sinCoefficients1);
+ const FloatV S5 = V4GetY(sinCoefficients1);
+ const FloatV S6 = V4GetZ(sinCoefficients1);
+ const FloatV S7 = V4GetW(sinCoefficients1);
+ const FloatV S8 = V4GetX(sinCoefficients2);
+ const FloatV S9 = V4GetY(sinCoefficients2);
+ const FloatV S10 = V4GetZ(sinCoefficients2);
+ const FloatV S11 = V4GetW(sinCoefficients2);
+
+ Result = FMulAdd(S1, V3, V1);
+ Result = FMulAdd(S2, V5, Result);
+ Result = FMulAdd(S3, V7, Result);
+ Result = FMulAdd(S4, V9, Result);
+ Result = FMulAdd(S5, V11, Result);
+ Result = FMulAdd(S6, V13, Result);
+ Result = FMulAdd(S7, V15, Result);
+ Result = FMulAdd(S8, V17, Result);
+ Result = FMulAdd(S9, V19, Result);
+ Result = FMulAdd(S10, V21, Result);
+ Result = FMulAdd(S11, V23, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE FloatV FCos(const FloatV a)
+{
+ // XMVECTOR V1, V2, V4, V6, V8, V10, V12, V14, V16, V18, V20, V22;
+ // XMVECTOR C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11;
+ FloatV Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const FloatV twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const FloatV tmp = FMul(a, twoPi);
+ const FloatV b = FRound(tmp);
+ const FloatV V1 = FNegMulSub(twoPi, b, a);
+
+ // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
+ // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
+ const FloatV V2 = FMul(V1, V1);
+ const FloatV V4 = FMul(V2, V2);
+ const FloatV V6 = FMul(V4, V2);
+ const FloatV V8 = FMul(V4, V4);
+ const FloatV V10 = FMul(V6, V4);
+ const FloatV V12 = FMul(V6, V6);
+ const FloatV V14 = FMul(V8, V6);
+ const FloatV V16 = FMul(V8, V8);
+ const FloatV V18 = FMul(V10, V8);
+ const FloatV V20 = FMul(V10, V10);
+ const FloatV V22 = FMul(V12, V10);
+
+ const Vec4V cosCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients0.f);
+ const Vec4V cosCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients1.f);
+ const Vec4V cosCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients2.f);
+
+ const FloatV C1 = V4GetY(cosCoefficients0);
+ const FloatV C2 = V4GetZ(cosCoefficients0);
+ const FloatV C3 = V4GetW(cosCoefficients0);
+ const FloatV C4 = V4GetX(cosCoefficients1);
+ const FloatV C5 = V4GetY(cosCoefficients1);
+ const FloatV C6 = V4GetZ(cosCoefficients1);
+ const FloatV C7 = V4GetW(cosCoefficients1);
+ const FloatV C8 = V4GetX(cosCoefficients2);
+ const FloatV C9 = V4GetY(cosCoefficients2);
+ const FloatV C10 = V4GetZ(cosCoefficients2);
+ const FloatV C11 = V4GetW(cosCoefficients2);
+
+ Result = FMulAdd(C1, V2, V4One());
+ Result = FMulAdd(C2, V4, Result);
+ Result = FMulAdd(C3, V6, Result);
+ Result = FMulAdd(C4, V8, Result);
+ Result = FMulAdd(C5, V10, Result);
+ Result = FMulAdd(C6, V12, Result);
+ Result = FMulAdd(C7, V14, Result);
+ Result = FMulAdd(C8, V16, Result);
+ Result = FMulAdd(C9, V18, Result);
+ Result = FMulAdd(C10, V20, Result);
+ Result = FMulAdd(C11, V22, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max)
+{
+ const BoolV ffff = BFFFF();
+ const BoolV c = BOr(FIsGrtr(a, max), FIsGrtr(min, a));
+ return !BAllEq(c, ffff);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FInBounds(const FloatV a, const FloatV min, const FloatV max)
+{
+ const BoolV tttt = BTTTT();
+ const BoolV c = BAnd(FIsGrtrOrEq(a, min), FIsGrtrOrEq(max, a));
+ return BAllEq(c, tttt);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FOutOfBounds(const FloatV a, const FloatV bounds)
+{
+ return FOutOfBounds(a, FNeg(bounds), bounds);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FInBounds(const FloatV a, const FloatV bounds)
+{
+ return FInBounds(a, FNeg(bounds), bounds);
+}
+
+//////////////////////////////////
+// VEC3V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec3V V3Splat(const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ const __m128 zero = FloatV_From_F32(0.0f);
+ const __m128 fff0 = _mm_move_ss(f, zero);
+ return _mm_shuffle_ps(fff0, fff0, _MM_SHUFFLE(0, 1, 2, 3));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(x));
+ VECMATHAOS_ASSERT(isValidFloatV(y));
+ VECMATHAOS_ASSERT(isValidFloatV(z));
+ // static on zero causes compiler crash on x64 debug_opt
+ const __m128 zero = FloatV_From_F32(0.0f);
+ const __m128 xy = _mm_move_ss(x, y);
+ const __m128 z0 = _mm_move_ss(zero, z);
+
+ return _mm_shuffle_ps(xy, z0, _MM_SHUFFLE(1, 0, 0, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3UnitX()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) x[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
+ const __m128 x128 = _mm_load_ps(x);
+ return x128;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3UnitY()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) y[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
+ const __m128 y128 = _mm_load_ps(y);
+ return y128;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3UnitZ()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) z[4] = { 0.0f, 0.0f, 1.0f, 0.0f };
+ const __m128 z128 = _mm_load_ps(z);
+ return z128;
+}
+
+QT3DS_FORCE_INLINE FloatV V3GetX(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE FloatV V3GetY(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
+}
+
+QT3DS_FORCE_INLINE FloatV V3GetZ(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V3Sel(BFTTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V3Sel(BTFTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V3Sel(BTTFT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 0, 3, 0));
+ return V3SetY(r, V3GetX(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 1, 3, 1));
+ return V3SetY(r, V3GetY(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 2, 3, 2));
+ return V3SetY(r, V3GetZ(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Zero()
+{
+ return Vec3V_From_F32(0.0f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Eps()
+{
+ return Vec3V_From_F32(QT3DS_ENV_REAL);
+}
+QT3DS_FORCE_INLINE Vec3V V3One()
+{
+ return Vec3V_From_F32(1.0f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Neg(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_sub_ps(_mm_setzero_ps(), f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_add_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_sub_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ const __m128 one = Vec3V_From_F32(1.0f);
+ const __m128 tttf = BTTTF();
+ const __m128 b1 = V3Sel(tttf, b, one);
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ const __m128 one = Vec3V_From_F32(1.0f);
+ const __m128 tttf = BTTTF();
+ const __m128 b1 = V3Sel(tttf, b, one);
+ return _mm_mul_ps(a, _mm_rcp_ps(b1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Recip(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = Vec3V_From_F32(0.0f);
+ const __m128 tttf = BTTTF();
+ const __m128 recipA = _mm_rcp_ps(a);
+ return V3Sel(tttf, recipA, zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a)
+{
+ return V3Recip(a);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = Vec3V_From_F32(0.0f);
+ const __m128 tttf = BTTTF();
+ const __m128 recipA = _mm_rsqrt_ps(a);
+ return V3Sel(tttf, recipA, zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a)
+{
+ return V3Rsqrt(a);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Add(V3Scale(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Sub(c, V3Scale(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Add(V3Mul(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Sub(c, V3Scale(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Abs(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Max(
+ a, V3Neg(a)); // sw/physx/shared/reviewed/3/feature/sdk/include/windows/Qt3DSWindowsInlineAoS.h
+}
+
+QT3DS_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ //__m128 dot1 = _mm_mul_ps(a, b);
+ ////w,z,y,x
+ //__m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2,1,0,3)); //z,y,x,w
+ //__m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1,0,3,2)); //y,x,w,z
+ //__m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0,3,2,1)); //x,w,z,y
+ // return _mm_add_ps(_mm_add_ps(shuf2, shuf3), _mm_add_ps(dot1,shuf1));
+
+ __m128 dot1 = _mm_mul_ps(a, b);
+ __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 0, 0, 0)); // z,y,x,w
+ __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 1, 1, 1)); // y,x,w,z
+ __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 2, 2, 2)); // x,w,z,y
+ return _mm_add_ps(_mm_add_ps(shuf2, shuf3), shuf1);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ __m128 l1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
+ __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
+ __m128 r1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
+ __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
+ return _mm_sub_ps(_mm_mul_ps(l1, l2), _mm_mul_ps(r1, r2));
+}
+
+QT3DS_FORCE_INLINE FloatV V3Length(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_sqrt_ps(V3Dot(a, a));
+}
+
+QT3DS_FORCE_INLINE FloatV V3LengthSq(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Dot(a, a);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Normalize(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Scale(a, _mm_rsqrt_ps(V3Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NormalizeFast(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Scale(a, _mm_rsqrt_ps(V3Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = FloatV_From_F32(0.0f);
+ const __m128 length = V3Length(a);
+ const __m128 isGreaterThanZero = FIsGrtr(length, zero);
+ return V3Sel(isGreaterThanZero, V3ScaleInv(a, length), zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
+}
+
+QT3DS_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_cmpgt_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_cmpge_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_max_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_min_ps(a, b);
+}
+
+// Extract the maximum value from a
+QT3DS_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a)
+{
+ const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
+ const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
+
+ return _mm_max_ps(_mm_max_ps(shuf1, shuf2), shuf3);
+}
+
+// Extract the maximum value from a
+QT3DS_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a)
+{
+ const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
+ const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
+
+ return _mm_min_ps(_mm_min_ps(shuf1, shuf2), shuf3);
+}
+
+// return (a >= 0.0f) ? 1.0f : -1.0f;
+QT3DS_FORCE_INLINE Vec3V V3Sign(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 one = V3One();
+ const __m128 none = V3Neg(one);
+ return V3Sel(V3IsGrtrOrEq(a, zero), one, none);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(minV));
+ VECMATHAOS_ASSERT(isValidVec3V(maxV));
+ return V3Max(V3Min(a, maxV), minV);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3AllGrtr(const Vec3V a, const Vec3V b)
+{
+ return BAllTrue3_R(V4IsGrtr(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b)
+{
+ return BAllTrue3_R(V4IsGrtrOrEq(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3AllEq(const Vec3V a, const Vec3V b)
+{
+ return BAllTrue3_R(V4IsEq(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Round(const Vec3V a)
+{
+ // return _mm_round_ps(a, 0x0);
+ const Vec3V half = Vec3V_From_F32(0.5f);
+ const Vec3V aPlusHalf = V3Add(a, half);
+ __m128i tmp = _mm_cvttps_epi32(aPlusHalf);
+ return _mm_cvtepi32_ps(tmp);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Sin(const Vec3V a)
+{
+ // Vec4V V1, V2, V3, V5, V7, V9, V11, V13, V15, V17, V19, V21, V23;
+ // Vec4V S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11;
+ Vec3V Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const Vec3V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec3V tmp = V3Mul(a, twoPi);
+ const Vec3V b = V3Round(tmp);
+ const Vec3V V1 = V3NegMulSub(twoPi, b, a);
+
+ // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
+ // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
+ const Vec3V V2 = V3Mul(V1, V1);
+ const Vec3V V3 = V3Mul(V2, V1);
+ const Vec3V V5 = V3Mul(V3, V2);
+ const Vec3V V7 = V3Mul(V5, V2);
+ const Vec3V V9 = V3Mul(V7, V2);
+ const Vec3V V11 = V3Mul(V9, V2);
+ const Vec3V V13 = V3Mul(V11, V2);
+ const Vec3V V15 = V3Mul(V13, V2);
+ const Vec3V V17 = V3Mul(V15, V2);
+ const Vec3V V19 = V3Mul(V17, V2);
+ const Vec3V V21 = V3Mul(V19, V2);
+ const Vec3V V23 = V3Mul(V21, V2);
+
+ const Vec4V sinCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients0.f);
+ const Vec4V sinCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients1.f);
+ const Vec4V sinCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients2.f);
+
+ const FloatV S1 = V4GetY(sinCoefficients0);
+ const FloatV S2 = V4GetZ(sinCoefficients0);
+ const FloatV S3 = V4GetW(sinCoefficients0);
+ const FloatV S4 = V4GetX(sinCoefficients1);
+ const FloatV S5 = V4GetY(sinCoefficients1);
+ const FloatV S6 = V4GetZ(sinCoefficients1);
+ const FloatV S7 = V4GetW(sinCoefficients1);
+ const FloatV S8 = V4GetX(sinCoefficients2);
+ const FloatV S9 = V4GetY(sinCoefficients2);
+ const FloatV S10 = V4GetZ(sinCoefficients2);
+ const FloatV S11 = V4GetW(sinCoefficients2);
+
+ Result = V3MulAdd(S1, V3, V1);
+ Result = V3MulAdd(S2, V5, Result);
+ Result = V3MulAdd(S3, V7, Result);
+ Result = V3MulAdd(S4, V9, Result);
+ Result = V3MulAdd(S5, V11, Result);
+ Result = V3MulAdd(S6, V13, Result);
+ Result = V3MulAdd(S7, V15, Result);
+ Result = V3MulAdd(S8, V17, Result);
+ Result = V3MulAdd(S9, V19, Result);
+ Result = V3MulAdd(S10, V21, Result);
+ Result = V3MulAdd(S11, V23, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Cos(const Vec3V a)
+{
+ // XMVECTOR V1, V2, V4, V6, V8, V10, V12, V14, V16, V18, V20, V22;
+ // XMVECTOR C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11;
+ Vec3V Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const Vec3V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec3V tmp = V3Mul(a, twoPi);
+ const Vec3V b = V3Round(tmp);
+ const Vec3V V1 = V3NegMulSub(twoPi, b, a);
+
+ // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
+ // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
+ const Vec3V V2 = V3Mul(V1, V1);
+ const Vec3V V4 = V3Mul(V2, V2);
+ const Vec3V V6 = V3Mul(V4, V2);
+ const Vec3V V8 = V3Mul(V4, V4);
+ const Vec3V V10 = V3Mul(V6, V4);
+ const Vec3V V12 = V3Mul(V6, V6);
+ const Vec3V V14 = V3Mul(V8, V6);
+ const Vec3V V16 = V3Mul(V8, V8);
+ const Vec3V V18 = V3Mul(V10, V8);
+ const Vec3V V20 = V3Mul(V10, V10);
+ const Vec3V V22 = V3Mul(V12, V10);
+
+ const Vec4V cosCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients0.f);
+ const Vec4V cosCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients1.f);
+ const Vec4V cosCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients2.f);
+
+ const FloatV C1 = V4GetY(cosCoefficients0);
+ const FloatV C2 = V4GetZ(cosCoefficients0);
+ const FloatV C3 = V4GetW(cosCoefficients0);
+ const FloatV C4 = V4GetX(cosCoefficients1);
+ const FloatV C5 = V4GetY(cosCoefficients1);
+ const FloatV C6 = V4GetZ(cosCoefficients1);
+ const FloatV C7 = V4GetW(cosCoefficients1);
+ const FloatV C8 = V4GetX(cosCoefficients2);
+ const FloatV C9 = V4GetY(cosCoefficients2);
+ const FloatV C10 = V4GetZ(cosCoefficients2);
+ const FloatV C11 = V4GetW(cosCoefficients2);
+
+ Result = V3MulAdd(C1, V2, V4One());
+ Result = V3MulAdd(C2, V4, Result);
+ Result = V3MulAdd(C3, V6, Result);
+ Result = V3MulAdd(C4, V8, Result);
+ Result = V3MulAdd(C5, V10, Result);
+ Result = V3MulAdd(C6, V12, Result);
+ Result = V3MulAdd(C7, V14, Result);
+ Result = V3MulAdd(C8, V16, Result);
+ Result = V3MulAdd(C9, V18, Result);
+ Result = V3MulAdd(C10, V20, Result);
+ Result = V3MulAdd(C11, V22, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a)
+{
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 2, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a)
+{
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 1, 0));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a)
+{
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 2, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 0, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1)
+{
+ return _mm_shuffle_ps(v1, v0, _MM_SHUFFLE(3, 1, 2, 3));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1)
+{
+ return _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(3, 0, 3, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1)
+{
+ // There must be a better way to do this.
+ Vec3V v2 = V3Zero();
+ FloatV y1 = V3GetY(v1);
+ FloatV x0 = V3GetX(v0);
+ v2 = V3SetX(v2, y1);
+ return V3SetY(v2, x0);
+}
+
+QT3DS_FORCE_INLINE FloatV V3SumElems(const Vec3V a)
+{
+ __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); // z,y,x,w
+ __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); // y,x,w,z
+ __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); // x,w,z,y
+ return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max)
+{
+ const BoolV ffff = BFFFF();
+ const BoolV c = BOr(V3IsGrtr(a, max), V3IsGrtr(min, a));
+ return !BAllEq(c, ffff);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max)
+{
+ const BoolV tttt = BTTTT();
+ const BoolV c = BAnd(V3IsGrtrOrEq(a, min), V3IsGrtrOrEq(max, a));
+ return BAllEq(c, tttt);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds)
+{
+ return V3OutOfBounds(a, V3Neg(bounds), bounds);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3InBounds(const Vec3V a, const Vec3V bounds)
+{
+ return V3InBounds(a, V3Neg(bounds), bounds);
+}
+
+//////////////////////////////////
+// VEC4V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec4V V4Splat(const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Merge(const FloatV *const floatVArray)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[0]));
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[1]));
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[2]));
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[3]));
+ __m128 xw = _mm_move_ss(floatVArray[1], floatVArray[0]); // y, y, y, x
+ __m128 yz = _mm_move_ss(floatVArray[2], floatVArray[3]); // z, z, z, w
+ return (_mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z,
+ const FloatVArg w)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(x));
+ VECMATHAOS_ASSERT(isValidFloatV(y));
+ VECMATHAOS_ASSERT(isValidFloatV(z));
+ VECMATHAOS_ASSERT(isValidFloatV(w));
+ __m128 xw = _mm_move_ss(y, x); // y, y, y, x
+ __m128 yz = _mm_move_ss(z, w); // z, z, z, w
+ return (_mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitW()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) w[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ const __m128 w128 = _mm_load_ps(w);
+ return w128;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitX()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) x[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
+ const __m128 x128 = _mm_load_ps(x);
+ return x128;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitY()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) y[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
+ const __m128 y128 = _mm_load_ps(y);
+ return y128;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitZ()
+{
+ const QT3DS_ALIGN(16, QT3DSF32) z[4] = { 0.0f, 0.0f, 1.0f, 0.0f };
+ const __m128 z128 = _mm_load_ps(z);
+ return z128;
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetW(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3));
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetX(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetY(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetZ(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BTTTF(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BFTTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BTFTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BTTFT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Zero()
+{
+ return Vec4V_From_F32(0.0f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4One()
+{
+ return Vec4V_From_F32(1.0f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V4Eps()
+{
+ return Vec3V_From_F32(QT3DS_ENV_REAL);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Neg(const Vec4V f)
+{
+ return _mm_sub_ps(_mm_setzero_ps(), f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b)
+{
+ return _mm_add_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b)
+{
+ return _mm_sub_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b)
+{
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b)
+{
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b)
+{
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b)
+{
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Recip(const Vec4V a)
+{
+ return _mm_rcp_ps(a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a)
+{
+ return V4Recip(a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a)
+{
+ return _mm_rsqrt_ps(a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a)
+{
+ return V4Rsqrt(a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return V4Add(V4Scale(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return V4Sub(c, V4Scale(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c)
+{
+ return V4Add(V4Scale(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c)
+{
+ return V4Sub(c, V4Scale(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Abs(const Vec4V a)
+{
+ return V4Max(a, V3Neg(a));
+}
+
+QT3DS_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b)
+{
+ __m128 dot1 = _mm_mul_ps(a, b); // x,y,z,w
+ __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 1, 0, 3)); // w,x,y,z
+ __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 0, 3, 2)); // z,w,x,y
+ __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 3, 2, 1)); // y,z,w,x
+ return _mm_add_ps(_mm_add_ps(shuf2, shuf3), _mm_add_ps(dot1, shuf1));
+}
+
+QT3DS_FORCE_INLINE FloatV V4Length(const Vec4V a)
+{
+ return _mm_sqrt_ps(V4Dot(a, a));
+}
+
+QT3DS_FORCE_INLINE FloatV V4LengthSq(const Vec4V a)
+{
+ return V4Dot(a, a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Normalize(const Vec4V a)
+{
+ return V4ScaleInv(a, _mm_sqrt_ps(V4Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a)
+{
+ return V4ScaleInvFast(a, _mm_sqrt_ps(V4Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a)
+{
+ const __m128 zero = FloatV_From_F32(0.0f);
+ const __m128 length = V4Length(a);
+ const __m128 isGreaterThanZero = FIsGrtr(length, zero);
+ return V4Sel(isGreaterThanZero, V4ScaleInv(a, length), zero);
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b)
+{
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b)
+{
+ return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b)
+{
+ return _mm_cmpgt_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b)
+{
+ return _mm_cmpge_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b)
+{
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V4Max(const Vec4V a, const Vec4V b)
+{
+ return _mm_max_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b)
+{
+ return _mm_min_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a)
+{
+ __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3));
+ __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2));
+ __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1));
+
+ return _mm_max_ps(_mm_max_ps(a, shuf1), _mm_max_ps(shuf2, shuf3));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV)
+{
+ return V4Max(V4Min(a, maxV), minV);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V4AllGrtr(const Vec4V a, const Vec4V b)
+{
+ return BAllTrue4_R(V4IsGrtr(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b)
+{
+ return BAllTrue4_R(V4IsGrtrOrEq(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V4AllEq(const Vec4V a, const Vec4V b)
+{
+ return BAllTrue4_R(V4IsEq(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Round(const Vec4V a)
+{
+ // return _mm_round_ps(a, 0x0);
+ const Vec3V half = Vec3V_From_F32(0.5f);
+ const Vec3V aPlusHalf = V3Add(a, half);
+ __m128i tmp = _mm_cvttps_epi32(aPlusHalf);
+ return _mm_cvtepi32_ps(tmp);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Sin(const Vec4V a)
+{
+ // Vec4V V1, V2, V3, V5, V7, V9, V11, V13, V15, V17, V19, V21, V23;
+ // Vec4V S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11;
+ Vec4V Result;
+
+ const Vec4V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec4V tmp = V4Mul(a, twoPi);
+ const Vec4V b = V4Round(tmp);
+ const Vec4V V1 = V4NegMulSub(twoPi, b, a);
+
+ // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
+ // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
+ const Vec4V V2 = V4Mul(V1, V1);
+ const Vec4V V3 = V4Mul(V2, V1);
+ const Vec4V V5 = V4Mul(V3, V2);
+ const Vec4V V7 = V4Mul(V5, V2);
+ const Vec4V V9 = V4Mul(V7, V2);
+ const Vec4V V11 = V4Mul(V9, V2);
+ const Vec4V V13 = V4Mul(V11, V2);
+ const Vec4V V15 = V4Mul(V13, V2);
+ const Vec4V V17 = V4Mul(V15, V2);
+ const Vec4V V19 = V4Mul(V17, V2);
+ const Vec4V V21 = V4Mul(V19, V2);
+ const Vec4V V23 = V4Mul(V21, V2);
+
+ const Vec4V sinCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients0.f);
+ const Vec4V sinCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients1.f);
+ const Vec4V sinCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients2.f);
+
+ const FloatV S1 = V4GetY(sinCoefficients0);
+ const FloatV S2 = V4GetZ(sinCoefficients0);
+ const FloatV S3 = V4GetW(sinCoefficients0);
+ const FloatV S4 = V4GetX(sinCoefficients1);
+ const FloatV S5 = V4GetY(sinCoefficients1);
+ const FloatV S6 = V4GetZ(sinCoefficients1);
+ const FloatV S7 = V4GetW(sinCoefficients1);
+ const FloatV S8 = V4GetX(sinCoefficients2);
+ const FloatV S9 = V4GetY(sinCoefficients2);
+ const FloatV S10 = V4GetZ(sinCoefficients2);
+ const FloatV S11 = V4GetW(sinCoefficients2);
+
+ Result = V4MulAdd(S1, V3, V1);
+ Result = V4MulAdd(S2, V5, Result);
+ Result = V4MulAdd(S3, V7, Result);
+ Result = V4MulAdd(S4, V9, Result);
+ Result = V4MulAdd(S5, V11, Result);
+ Result = V4MulAdd(S6, V13, Result);
+ Result = V4MulAdd(S7, V15, Result);
+ Result = V4MulAdd(S8, V17, Result);
+ Result = V4MulAdd(S9, V19, Result);
+ Result = V4MulAdd(S10, V21, Result);
+ Result = V4MulAdd(S11, V23, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Cos(const Vec4V a)
+{
+ // XMVECTOR V1, V2, V4, V6, V8, V10, V12, V14, V16, V18, V20, V22;
+ // XMVECTOR C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11;
+ Vec4V Result;
+
+ const Vec4V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec4V tmp = V4Mul(a, twoPi);
+ const Vec4V b = V4Round(tmp);
+ const Vec4V V1 = V4NegMulSub(twoPi, b, a);
+
+ // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
+ // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
+ const Vec4V V2 = V4Mul(V1, V1);
+ const Vec4V V4 = V4Mul(V2, V2);
+ const Vec4V V6 = V4Mul(V4, V2);
+ const Vec4V V8 = V4Mul(V4, V4);
+ const Vec4V V10 = V4Mul(V6, V4);
+ const Vec4V V12 = V4Mul(V6, V6);
+ const Vec4V V14 = V4Mul(V8, V6);
+ const Vec4V V16 = V4Mul(V8, V8);
+ const Vec4V V18 = V4Mul(V10, V8);
+ const Vec4V V20 = V4Mul(V10, V10);
+ const Vec4V V22 = V4Mul(V12, V10);
+
+ const Vec4V cosCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients0.f);
+ const Vec4V cosCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients1.f);
+ const Vec4V cosCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients2.f);
+
+ const FloatV C1 = V4GetY(cosCoefficients0);
+ const FloatV C2 = V4GetZ(cosCoefficients0);
+ const FloatV C3 = V4GetW(cosCoefficients0);
+ const FloatV C4 = V4GetX(cosCoefficients1);
+ const FloatV C5 = V4GetY(cosCoefficients1);
+ const FloatV C6 = V4GetZ(cosCoefficients1);
+ const FloatV C7 = V4GetW(cosCoefficients1);
+ const FloatV C8 = V4GetX(cosCoefficients2);
+ const FloatV C9 = V4GetY(cosCoefficients2);
+ const FloatV C10 = V4GetZ(cosCoefficients2);
+ const FloatV C11 = V4GetW(cosCoefficients2);
+
+ Result = V4MulAdd(C1, V2, V4One());
+ Result = V4MulAdd(C2, V4, Result);
+ Result = V4MulAdd(C3, V6, Result);
+ Result = V4MulAdd(C4, V8, Result);
+ Result = V4MulAdd(C5, V10, Result);
+ Result = V4MulAdd(C6, V12, Result);
+ Result = V4MulAdd(C7, V14, Result);
+ Result = V4MulAdd(C8, V16, Result);
+ Result = V4MulAdd(C9, V18, Result);
+ Result = V4MulAdd(C10, V20, Result);
+ Result = V4MulAdd(C11, V22, Result);
+
+ return Result;
+}
+
+//////////////////////////////////
+// VEC4V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE BoolV BFFFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0, 0, 0 };
+ const __m128 ffff = _mm_load_ps((float *)&f);
+ return ffff;
+}
+
+QT3DS_FORCE_INLINE BoolV BFFFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0, 0, 0xFFFFFFFF };
+ const __m128 ffft = _mm_load_ps((float *)&f);
+ return ffft;
+}
+
+QT3DS_FORCE_INLINE BoolV BFFTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0, 0xFFFFFFFF, 0 };
+ const __m128 fftf = _mm_load_ps((float *)&f);
+ return fftf;
+}
+
+QT3DS_FORCE_INLINE BoolV BFFTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 fftt = _mm_load_ps((float *)&f);
+ return fftt;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0xFFFFFFFF, 0, 0 };
+ const __m128 ftff = _mm_load_ps((float *)&f);
+ return ftff;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0xFFFFFFFF, 0, 0xFFFFFFFF };
+ const __m128 ftft = _mm_load_ps((float *)&f);
+ return ftft;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0xFFFFFFFF, 0xFFFFFFFF, 0 };
+ const __m128 fttf = _mm_load_ps((float *)&f);
+ return fttf;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 fttt = _mm_load_ps((float *)&f);
+ return fttt;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0, 0, 0 };
+ const __m128 tfff = _mm_load_ps((float *)&f);
+ return tfff;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0, 0, 0xFFFFFFFF };
+ const __m128 tfft = _mm_load_ps((float *)&f);
+ return tfft;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0, 0xFFFFFFFF, 0 };
+ const __m128 tftf = _mm_load_ps((float *)&f);
+ return tftf;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 tftt = _mm_load_ps((float *)&f);
+ return tftt;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0, 0 };
+ const __m128 ttff = _mm_load_ps((float *)&f);
+ return ttff;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0, 0xFFFFFFFF };
+ const __m128 ttft = _mm_load_ps((float *)&f);
+ return ttft;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0 };
+ const __m128 tttf = _mm_load_ps((float *)&f);
+ return tttf;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 tttt = _mm_load_ps((float *)&f);
+ return tttt;
+}
+
+QT3DS_FORCE_INLINE BoolV BXMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0xFFFFFFFF, 0, 0, 0 };
+ const __m128 tfff = _mm_load_ps((float *)&f);
+ return tfff;
+}
+
+QT3DS_FORCE_INLINE BoolV BYMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0xFFFFFFFF, 0, 0 };
+ const __m128 ftff = _mm_load_ps((float *)&f);
+ return ftff;
+}
+
+QT3DS_FORCE_INLINE BoolV BZMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0, 0xFFFFFFFF, 0 };
+ const __m128 fftf = _mm_load_ps((float *)&f);
+ return fftf;
+}
+
+QT3DS_FORCE_INLINE BoolV BWMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32) f[4] = { 0, 0, 0, 0xFFFFFFFF };
+ const __m128 ffft = _mm_load_ps((float *)&f);
+ return ffft;
+}
+
+QT3DS_FORCE_INLINE BoolV BGetX(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE BoolV BGetY(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
+}
+
+QT3DS_FORCE_INLINE BoolV BGetZ(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
+}
+
+QT3DS_FORCE_INLINE BoolV BGetW(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3));
+}
+
+QT3DS_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b)
+{
+ return (_mm_and_ps(a, b));
+}
+
+QT3DS_FORCE_INLINE BoolV BNot(const BoolV a)
+{
+ const BoolV bAllTrue(BTTTT());
+ return _mm_xor_ps(a, bAllTrue);
+}
+
+QT3DS_FORCE_INLINE BoolV BAndNot(const BoolV a, const BoolV b)
+{
+ return (_mm_andnot_ps(a, b));
+}
+
+QT3DS_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b)
+{
+ return (_mm_or_ps(a, b));
+}
+
+QT3DS_FORCE_INLINE BoolV BAllTrue4(const BoolV a)
+{
+ const BoolV bTmp = _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3)));
+ return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE BoolV BAnyTrue4(const BoolV a)
+{
+ const BoolV bTmp = _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3)));
+ return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE BoolV BAllTrue3(const BoolV a)
+{
+ const BoolV bTmp = _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
+ return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE BoolV BAnyTrue3(const BoolV a)
+{
+ const BoolV bTmp = _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
+ return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAllEq(const BoolV a, const BoolV b)
+{
+ const BoolV bTest = m128_I2F(_mm_cmpeq_epi32(m128_F2I(a), m128_F2I(b)));
+ return BAllTrue4_R(bTest);
+}
+
+//////////////////////////////////
+// MAT33V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec3V M33MulV3(const Mat33V &a, const Vec3V b)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ const Vec3V v0 = V3Scale(a.col0, x);
+ const Vec3V v1 = V3Scale(a.col1, y);
+ const Vec3V v2 = V3Scale(a.col2, z);
+ const Vec3V v0PlusV1 = V3Add(v0, v1);
+ return V3Add(v0PlusV1, v2);
+}
+
+QT3DS_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V &a, const Vec3V b)
+{
+ const FloatV x = V3Dot(a.col0, b);
+ const FloatV y = V3Dot(a.col1, b);
+ const FloatV z = V3Dot(a.col2, b);
+ return V3Merge(x, y, z);
+}
+
+QT3DS_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V &A, const Vec3V b, const Vec3V c)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ Vec3V result = V3MulAdd(A.col0, x, c);
+ result = V3MulAdd(A.col1, y, result);
+ return V3MulAdd(A.col2, z, result);
+}
+
+QT3DS_FORCE_INLINE Mat33V M33MulM33(const Mat33V &a, const Mat33V &b)
+{
+ return Mat33V(M33MulV3(a, b.col0), M33MulV3(a, b.col1), M33MulV3(a, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Add(const Mat33V &a, const Mat33V &b)
+{
+ return Mat33V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Inverse(const Mat33V &a)
+{
+ const BoolV tfft = BTFFT();
+ const BoolV tttf = BTTTF();
+ const FloatV zero = FloatV_From_F32(0.0f);
+ const Vec3V cross01 = V3Cross(a.col0, a.col1);
+ const Vec3V cross12 = V3Cross(a.col1, a.col2);
+ const Vec3V cross20 = V3Cross(a.col2, a.col0);
+ const FloatV dot = V3Dot(cross01, a.col2);
+ const FloatV invDet = _mm_rcp_ps(dot);
+ const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01);
+ const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01);
+ Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20);
+ colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0));
+ const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2));
+ const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0));
+ const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd));
+ const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0));
+ const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0));
+ const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd));
+
+ return Mat33V(_mm_mul_ps(colInv0, invDet), _mm_mul_ps(colInv1, invDet),
+ _mm_mul_ps(colInv2, invDet));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Trnsps(const Mat33V &a)
+{
+ return Mat33V(V3Merge(V3GetX(a.col0), V3GetX(a.col1), V3GetX(a.col2)),
+ V3Merge(V3GetY(a.col0), V3GetY(a.col1), V3GetY(a.col2)),
+ V3Merge(V3GetZ(a.col0), V3GetZ(a.col1), V3GetZ(a.col2)));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Identity()
+{
+ return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ());
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Sub(const Mat33V &a, const Mat33V &b)
+{
+ return Mat33V(V3Sub(a.col0, b.col0), V3Sub(a.col1, b.col1), V3Sub(a.col2, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Neg(const Mat33V &a)
+{
+ return Mat33V(V3Neg(a.col0), V3Neg(a.col1), V3Neg(a.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Abs(const Mat33V &a)
+{
+ return Mat33V(V3Abs(a.col0), V3Abs(a.col1), V3Abs(a.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V PromoteVec3V(const Vec3V v)
+{
+ const BoolV bTFFF = BTFFF();
+ const BoolV bFTFF = BFTFF();
+ const BoolV bFFTF = BTFTF();
+
+ const Vec3V zero = V3Zero();
+
+ return Mat33V(V3Sel(bTFFF, v, zero), V3Sel(bFTFF, v, zero), V3Sel(bFFTF, v, zero));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg d)
+{
+ const FloatV x = V3Mul(V3UnitX(), d);
+ const FloatV y = V3Mul(V3UnitY(), d);
+ const FloatV z = V3Mul(V3UnitZ(), d);
+ return Mat33V(x, y, z);
+}
+
+//////////////////////////////////
+// MAT34V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec3V M34MulV3(const Mat34V &a, const Vec3V b)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ const Vec3V v0 = V3Scale(a.col0, x);
+ const Vec3V v1 = V3Scale(a.col1, y);
+ const Vec3V v2 = V3Scale(a.col2, z);
+ const Vec3V v0PlusV1 = V3Add(v0, v1);
+ const Vec3V v0PlusV1Plusv2 = V3Add(v0PlusV1, v2);
+ return (V3Add(v0PlusV1Plusv2, a.col3));
+}
+
+QT3DS_FORCE_INLINE Vec3V M34Mul33V3(const Mat34V &a, const Vec3V b)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ const Vec3V v0 = V3Scale(a.col0, x);
+ const Vec3V v1 = V3Scale(a.col1, y);
+ const Vec3V v2 = V3Scale(a.col2, z);
+ const Vec3V v0PlusV1 = V3Add(v0, v1);
+ return V3Add(v0PlusV1, v2);
+}
+
+QT3DS_FORCE_INLINE Vec3V M34TrnspsMul33V3(const Mat34V &a, const Vec3V b)
+{
+ const FloatV x = V3Dot(a.col0, b);
+ const FloatV y = V3Dot(a.col1, b);
+ const FloatV z = V3Dot(a.col2, b);
+ return V3Merge(x, y, z);
+}
+
+QT3DS_FORCE_INLINE Mat34V M34MulM34(const Mat34V &a, const Mat34V &b)
+{
+ return Mat34V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2),
+ M34MulV3(a, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat33V M34MulM33(const Mat34V &a, const Mat33V &b)
+{
+ return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M34Mul33MM34(const Mat34V &a, const Mat34V &b)
+{
+ return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat34V M34Add(const Mat34V &a, const Mat34V &b)
+{
+ return Mat34V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2),
+ V3Add(a.col3, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat34V M34InverseV(const Mat34V &a)
+{
+ Mat34V aInv;
+ const BoolV tfft = BTFFT();
+ const BoolV tttf = BTTTF();
+ const FloatV zero = FloatV_From_F32(0.0f);
+ const Vec3V cross01 = V3Cross(a.col0, a.col1);
+ const Vec3V cross12 = V3Cross(a.col1, a.col2);
+ const Vec3V cross20 = V3Cross(a.col2, a.col0);
+ const FloatV dot = V3Dot(cross01, a.col2);
+ const FloatV invDet = _mm_rcp_ps(dot);
+ const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01);
+ const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01);
+ Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20);
+ colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0));
+ const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2));
+ const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0));
+ const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd));
+ const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0));
+ const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0));
+ const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd));
+ aInv.col0 = _mm_mul_ps(colInv0, invDet);
+ aInv.col1 = _mm_mul_ps(colInv1, invDet);
+ aInv.col2 = _mm_mul_ps(colInv2, invDet);
+ aInv.col3 = M34Mul33V3(aInv, V3Neg(a.col3));
+ return aInv;
+}
+
+QT3DS_FORCE_INLINE Mat33V M34Trnsps33(const Mat34V &a)
+{
+ return Mat33V(V3Merge(V3GetX(a.col0), V3GetX(a.col1), V3GetX(a.col2)),
+ V3Merge(V3GetY(a.col0), V3GetY(a.col1), V3GetY(a.col2)),
+ V3Merge(V3GetZ(a.col0), V3GetZ(a.col1), V3GetZ(a.col2)));
+}
+
+//////////////////////////////////
+// MAT44V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec4V M44MulV4(const Mat44V &a, const Vec4V b)
+{
+ const FloatV x = V4GetX(b);
+ const FloatV y = V4GetY(b);
+ const FloatV z = V4GetZ(b);
+ const FloatV w = V4GetW(b);
+
+ const Vec4V v0 = V4Scale(a.col0, x);
+ const Vec4V v1 = V4Scale(a.col1, y);
+ const Vec4V v2 = V4Scale(a.col2, z);
+ const Vec4V v3 = V4Scale(a.col3, w);
+ const Vec4V v0PlusV1 = V4Add(v0, v1);
+ const Vec4V v0PlusV1Plusv2 = V4Add(v0PlusV1, v2);
+ return (V4Add(v0PlusV1Plusv2, v3));
+}
+
+QT3DS_FORCE_INLINE Vec4V M44TrnspsMulV4(const Mat44V &a, const Vec4V b)
+{
+ QT3DS_ALIGN(16, FloatV)
+ dotProdArray[4] = { V4Dot(a.col0, b), V4Dot(a.col1, b), V4Dot(a.col2, b), V4Dot(a.col3, b) };
+ return V4Merge(dotProdArray);
+}
+
+QT3DS_FORCE_INLINE Mat44V M44MulM44(const Mat44V &a, const Mat44V &b)
+{
+ return Mat44V(M44MulV4(a, b.col0), M44MulV4(a, b.col1), M44MulV4(a, b.col2),
+ M44MulV4(a, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat44V M44Add(const Mat44V &a, const Mat44V &b)
+{
+ return Mat44V(V4Add(a.col0, b.col0), V4Add(a.col1, b.col1), V4Add(a.col2, b.col2),
+ V4Add(a.col3, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat44V M44Trnsps(const Mat44V &a)
+{
+ const Vec4V v0 = _mm_unpacklo_ps(a.col0, a.col2);
+ const Vec4V v1 = _mm_unpackhi_ps(a.col0, a.col2);
+ const Vec4V v2 = _mm_unpacklo_ps(a.col1, a.col3);
+ const Vec4V v3 = _mm_unpackhi_ps(a.col1, a.col3);
+ return Mat44V(_mm_unpacklo_ps(v0, v2), _mm_unpackhi_ps(v0, v2), _mm_unpacklo_ps(v1, v3),
+ _mm_unpackhi_ps(v1, v3));
+}
+
+QT3DS_FORCE_INLINE Mat44V M44Inverse(const Mat44V &a)
+{
+ __m128 minor0, minor1, minor2, minor3;
+ __m128 row0, row1, row2, row3;
+ __m128 det, tmp1;
+
+ tmp1 = FloatV_From_F32(0.0f);
+ row1 = FloatV_From_F32(0.0f);
+ row3 = FloatV_From_F32(0.0f);
+
+ row0 = a.col0;
+ row1 = _mm_shuffle_ps(a.col1, a.col1, _MM_SHUFFLE(1, 0, 3, 2));
+ row2 = a.col2;
+ row3 = _mm_shuffle_ps(a.col3, a.col3, _MM_SHUFFLE(1, 0, 3, 2));
+
+ tmp1 = _mm_mul_ps(row2, row3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor0 = _mm_mul_ps(row1, tmp1);
+ minor1 = _mm_mul_ps(row0, tmp1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor0 = _mm_sub_ps(_mm_mul_ps(row1, tmp1), minor0);
+ minor1 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor1);
+ minor1 = _mm_shuffle_ps(minor1, minor1, 0x4E);
+
+ tmp1 = _mm_mul_ps(row1, row2);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor0 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor0);
+ minor3 = _mm_mul_ps(row0, tmp1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row3, tmp1));
+ minor3 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor3);
+ minor3 = _mm_shuffle_ps(minor3, minor3, 0x4E);
+
+ tmp1 = _mm_mul_ps(_mm_shuffle_ps(row1, row1, 0x4E), row3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ row2 = _mm_shuffle_ps(row2, row2, 0x4E);
+ minor0 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor0);
+ minor2 = _mm_mul_ps(row0, tmp1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row2, tmp1));
+ minor2 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor2);
+ minor2 = _mm_shuffle_ps(minor2, minor2, 0x4E);
+
+ tmp1 = _mm_mul_ps(row0, row1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor2 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor2);
+ minor3 = _mm_sub_ps(_mm_mul_ps(row2, tmp1), minor3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor2 = _mm_sub_ps(_mm_mul_ps(row3, tmp1), minor2);
+ minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row2, tmp1));
+
+ tmp1 = _mm_mul_ps(row0, row3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row2, tmp1));
+ minor2 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor2);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor1 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor1);
+ minor2 = _mm_sub_ps(minor2, _mm_mul_ps(row1, tmp1));
+
+ tmp1 = _mm_mul_ps(row0, row2);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor1 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor1);
+ minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row1, tmp1));
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row3, tmp1));
+ minor3 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor3);
+
+ det = _mm_mul_ps(row0, minor0);
+ det = _mm_add_ps(_mm_shuffle_ps(det, det, 0x4E), det);
+ det = _mm_add_ss(_mm_shuffle_ps(det, det, 0xB1), det);
+ tmp1 = _mm_rcp_ss(det);
+#if 0
+ det = _mm_sub_ss(_mm_add_ss(tmp1, tmp1), _mm_mul_ss(det, _mm_mul_ss(tmp1, tmp1)));
+ det = _mm_shuffle_ps(det, det, 0x00);
+#else
+ det = _mm_shuffle_ps(tmp1, tmp1, _MM_SHUFFLE(0, 0, 0, 0));
+#endif
+
+ minor0 = _mm_mul_ps(det, minor0);
+ minor1 = _mm_mul_ps(det, minor1);
+ minor2 = _mm_mul_ps(det, minor2);
+ minor3 = _mm_mul_ps(det, minor3);
+ Mat44V invTrans(minor0, minor1, minor2, minor3);
+ return M44Trnsps(invTrans);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_XYZW(QT3DSF32 x, QT3DSF32 y, QT3DSF32 z, QT3DSF32 w)
+{
+ return _mm_set_ps(w, z, y, x);
+}
+
+// AP: work in progress - use proper SSE intrinsics where possible
+QT3DS_FORCE_INLINE VecU16V V4U32PK(VecU32V a, VecU32V b)
+{
+ VecU16V result;
+ result.m128_u16[0] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[0], 0, 0xFFFF));
+ result.m128_u16[1] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[1], 0, 0xFFFF));
+ result.m128_u16[2] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[2], 0, 0xFFFF));
+ result.m128_u16[3] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[3], 0, 0xFFFF));
+ result.m128_u16[4] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[0], 0, 0xFFFF));
+ result.m128_u16[5] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[1], 0, 0xFFFF));
+ result.m128_u16[6] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[2], 0, 0xFFFF));
+ result.m128_u16[7] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[3], 0, 0xFFFF));
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b)
+{
+ return m128_I2F(_mm_or_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b)
+{
+ return m128_I2F(_mm_and_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b)
+{
+ return m128_I2F(_mm_andnot_si128(m128_F2I(b), m128_F2I(a)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16Or(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_or_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16And(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_and_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16Andc(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_andnot_si128(m128_F2I(b), m128_F2I(a)));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_From_I32(const QT3DSI32 i)
+{
+ return (_mm_load1_ps((QT3DSF32 *)&i));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_From_I32Array(const QT3DSI32 *i)
+{
+ return _mm_loadu_ps((QT3DSF32 *)i);
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_From_I32Array_Aligned(const QT3DSI32 *i)
+{
+ return _mm_load_ps((QT3DSF32 *)i);
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_add_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_sub_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_cmpgt_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_cmpeq_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Zero()
+{
+ return V4Zero();
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Merge(const VecI32VArg a, const VecI32VArg b, const VecI32VArg c,
+ const VecI32VArg d)
+{
+ return V4Merge(a, b, c, d);
+}
+
+template <int a>
+QT3DS_FORCE_INLINE VecI32V V4ISplat()
+{
+ VecI32V result;
+ result.m128_i32[0] = a;
+ result.m128_i32[1] = a;
+ result.m128_i32[2] = a;
+ result.m128_i32[3] = a;
+ return result;
+}
+
+QT3DS_FORCE_INLINE void V4U16StoreAligned(VecU16V val, VecU16V *address)
+{
+ *address = val;
+}
+
+QT3DS_FORCE_INLINE void V4U32StoreAligned(VecU32V val, VecU32V *address)
+{
+ *address = val;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4LoadAligned(Vec4V *addr)
+{
+ return *addr;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4LoadUnaligned(Vec4V *addr)
+{
+ return Vec4V_From_F32Array((float *)addr);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b)
+{
+ VecU32V result32(a);
+ result32 = V4U32Andc(result32, b);
+ return Vec4V(result32);
+}
+
+QT3DS_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b)
+{
+ return V4IsGrtr(a, b);
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16LoadAligned(VecU16V *addr)
+{
+ return *addr;
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16LoadUnaligned(VecU16V *addr)
+{
+ return *addr;
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16CompareGt(VecU16V a, VecU16V b)
+{
+ // _mm_cmpgt_epi16 doesn't work for unsigned values unfortunately
+ // return m128_I2F(_mm_cmpgt_epi16(m128_F2I(a), m128_F2I(b)));
+ VecU16V result;
+ result.m128_u16[0] = (a).m128_u16[0] > (b).m128_u16[0];
+ result.m128_u16[1] = (a).m128_u16[1] > (b).m128_u16[1];
+ result.m128_u16[2] = (a).m128_u16[2] > (b).m128_u16[2];
+ result.m128_u16[3] = (a).m128_u16[3] > (b).m128_u16[3];
+ result.m128_u16[4] = (a).m128_u16[4] > (b).m128_u16[4];
+ result.m128_u16[5] = (a).m128_u16[5] > (b).m128_u16[5];
+ result.m128_u16[6] = (a).m128_u16[6] > (b).m128_u16[6];
+ result.m128_u16[7] = (a).m128_u16[7] > (b).m128_u16[7];
+ return result;
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a)
+{
+ Vec4V result = Vec4V_From_XYZW(QT3DSF32(a.m128_u32[0]), QT3DSF32(a.m128_u32[1]), QT3DSF32(a.m128_u32[2]),
+ QT3DSF32(a.m128_u32[3]));
+ return result;
+}
+
+template <int index>
+QT3DS_FORCE_INLINE VecU32V V4U32SplatElement(VecU32V a)
+{
+ VecU32V result;
+ result.m128_u32[0] = result.m128_u32[1] = result.m128_u32[2] = result.m128_u32[3] =
+ a.m128_u32[index];
+ return result;
+}
+
+template <int index>
+QT3DS_FORCE_INLINE Vec4V V4SplatElement(Vec4V a)
+{
+ float *data = (float *)&a;
+ return Vec4V_From_F32(data[index]);
+}
+
+template <int index>
+QT3DS_FORCE_INLINE VecU16V V4U16SplatElement(VecU16V a)
+{
+ VecU16V result;
+ for (int i = 0; i < 8; i++)
+ result.m128_u16[i] = a.m128_u16[index];
+ return result;
+}
+
+template <int imm>
+QT3DS_FORCE_INLINE VecI16V V4I16SplatImmediate()
+{
+ VecI16V result;
+ result.m128_i16[0] = imm;
+ result.m128_i16[1] = imm;
+ result.m128_i16[2] = imm;
+ result.m128_i16[3] = imm;
+ result.m128_i16[4] = imm;
+ result.m128_i16[5] = imm;
+ result.m128_i16[6] = imm;
+ result.m128_i16[7] = imm;
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16SubtractModulo(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_sub_epi16(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16AddModulo(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_add_epi16(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U16GetLo16(VecU16V a)
+{
+ VecU32V result;
+ result.m128_u32[0] = a.m128_u16[0];
+ result.m128_u32[1] = a.m128_u16[2];
+ result.m128_u32[2] = a.m128_u16[4];
+ result.m128_u32[3] = a.m128_u16[6];
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U16GetHi16(VecU16V a)
+{
+ VecU32V result;
+ result.m128_u32[0] = a.m128_u16[1];
+ result.m128_u32[1] = a.m128_u16[3];
+ result.m128_u32[2] = a.m128_u16[5];
+ result.m128_u32[3] = a.m128_u16[7];
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU32V VecU32V_From_XYZW(QT3DSU32 x, QT3DSU32 y, QT3DSU32 z, QT3DSU32 w)
+{
+ VecU32V result;
+ result.m128_u32[0] = x;
+ result.m128_u32[1] = y;
+ result.m128_u32[2] = z;
+ result.m128_u32[3] = w;
+ return result;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Ceil(const Vec4V in)
+{
+ UnionM128 a(in);
+ return Vec4V_From_XYZW(NVCeil(a.m128_f32[0]), NVCeil(a.m128_f32[1]), NVCeil(a.m128_f32[2]),
+ NVCeil(a.m128_f32[3]));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Floor(const Vec4V in)
+{
+ UnionM128 a(in);
+ return Vec4V_From_XYZW(NVFloor(a.m128_f32[0]), NVFloor(a.m128_f32[1]), NVFloor(a.m128_f32[2]),
+ NVFloor(a.m128_f32[3]));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4ConvertToU32VSaturate(const Vec4V in, QT3DSU32 power)
+{
+ QT3DS_ASSERT(power == 0 && "Non-zero power not supported in convertToU32VSaturate");
+ QT3DS_FORCE_PARAMETER_REFERENCE(power); // prevent warning in release builds
+ QT3DSF32 ffffFFFFasFloat = QT3DSF32(0xFFFF0000);
+ UnionM128 a(in);
+ VecU32V result;
+ result.m128_u32[0] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[0], 0.0f, ffffFFFFasFloat));
+ result.m128_u32[1] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[1], 0.0f, ffffFFFFasFloat));
+ result.m128_u32[2] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[2], 0.0f, ffffFFFFasFloat));
+ result.m128_u32[3] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[3], 0.0f, ffffFFFFasFloat));
+ return result;
+}
+
+#endif // QT3DS_LINUX_INLINE_AOS_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxIntrinsics.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxIntrinsics.h
new file mode 100644
index 00000000..70974609
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxIntrinsics.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_LINUX_INTRINSICS_H
+#define QT3DS_FOUNDATION_QT3DS_LINUX_INTRINSICS_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+
+#if !(defined QT3DS_LINUX || defined QT3DS_ANDROID || defined QT3DS_APPLE || defined QT3DS_QNX)
+#error "This file should only be included by Linux builds!!"
+#endif
+
+#include <cmath>
+#include <math.h>
+#include <float.h>
+#include <string.h>
+
+namespace qt3ds {
+namespace intrinsics {
+ //! \brief platform-specific absolute value
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float abs(float a) { return ::fabs(a); }
+
+ //! \brief platform-specific select float
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float fsel(float a, float b, float c)
+ {
+ return (a >= 0.0f) ? b : c;
+ }
+
+ //! \brief platform-specific sign
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float sign(float a) { return (a >= 0.0f) ? 1.0f : -1.0f; }
+
+ //! \brief platform-specific reciprocal
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recip(float a) { return 1.0f / a; }
+
+ //! \brief platform-specific reciprocal estimate
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recipFast(float a) { return 1.0f / a; }
+
+ //! \brief platform-specific square root
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float sqrt(float a) { return ::sqrtf(a); }
+
+ //! \brief platform-specific reciprocal square root
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recipSqrt(float a) { return 1.0f / ::sqrtf(a); }
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recipSqrtFast(float a) { return 1.0f / ::sqrtf(a); }
+
+ //! \brief platform-specific sine
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float sin(float a) { return ::sinf(a); }
+
+ //! \brief platform-specific cosine
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float cos(float a) { return ::cosf(a); }
+
+ //! \brief platform-specific minimum
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float selectMin(float a, float b) { return a < b ? a : b; }
+
+ //! \brief platform-specific maximum
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float selectMax(float a, float b) { return a > b ? a : b; }
+
+ //! \brief platform-specific finiteness check (not INF or NAN)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite(float a) { return std::isfinite(a); }
+
+ //! \brief platform-specific finiteness check (not INF or NAN)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite(double a) { return std::isfinite(a); }
+ QT3DS_FORCE_INLINE void memoryBarrier()
+ {
+#if 0 //!defined (QT3DS_ARM)
+ smp_mb();
+#endif
+ }
+
+ /*!
+ Return the index of the highest set bit. Undefined for zero arg.
+ */
+ QT3DS_INLINE QT3DSU32 highestSetBitUnsafe(QT3DSU32 v)
+ {
+
+ // http://graphics.stanford.edu/~seander/bithacks.html
+ static const QT3DSU32 MultiplyDeBruijnBitPosition[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
+ 11, 14, 16, 18, 22, 25, 3, 30,
+ 8, 12, 20, 28, 15, 17, 24, 7,
+ 19, 27, 23, 6, 26, 5, 4, 31 };
+
+ v |= v >> 1; // first round up to one less than a power of 2
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+
+ return MultiplyDeBruijnBitPosition[(QT3DSU32)(v * 0x07C4ACDDU) >> 27];
+ }
+
+ /*!
+ Return the index of the highest set bit. Undefined for zero arg.
+ */
+ QT3DS_INLINE QT3DSI32 lowestSetBitUnsafe(QT3DSU32 v)
+ {
+ // http://graphics.stanford.edu/~seander/bithacks.html
+ static const QT3DSU32 MultiplyDeBruijnBitPosition[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
+ 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7,
+ 26, 12, 18, 6, 11, 5, 10, 9 };
+ QT3DSI32 w = v;
+ return MultiplyDeBruijnBitPosition[(QT3DSU32)((w & -w) * 0x077CB531U) >> 27];
+ }
+
+ /*!
+ Returns the index of the highest set bit. Undefined for zero arg.
+ */
+ QT3DS_INLINE QT3DSU32 countLeadingZeros(QT3DSU32 v)
+ {
+ QT3DSI32 result = 0;
+#ifdef _INTEGRITYPLATFORM
+ QT3DSU32 testBit = (1U << 31);
+#else
+ QT3DSU32 testBit = (1 << 31);
+#endif
+ while ((v & testBit) == 0 && testBit != 0)
+ result++, testBit >>= 1;
+ return result;
+ }
+
+ /*!
+ Sets \c count bytes starting at \c dst to zero.
+ */
+ QT3DS_FORCE_INLINE void *memZero(void *QT3DS_RESTRICT dest, QT3DSU32 count)
+ {
+ return memset(dest, 0, count);
+ }
+
+ /*!
+ Sets \c count bytes starting at \c dst to \c c.
+ */
+ QT3DS_FORCE_INLINE void *memSet(void *QT3DS_RESTRICT dest, QT3DSI32 c, QT3DSU32 count)
+ {
+ return memset(dest, c, count);
+ }
+
+ /*!
+ Copies \c count bytes from \c src to \c dst. User memMove if regions overlap.
+ */
+ QT3DS_FORCE_INLINE void *memCopy(void *QT3DS_RESTRICT dest, const void *QT3DS_RESTRICT src, QT3DSU32 count)
+ {
+ return memcpy(dest, src, count);
+ }
+
+ /*!
+ Copies \c count bytes from \c src to \c dst. Supports overlapping regions.
+ */
+ QT3DS_FORCE_INLINE void *memMove(void *QT3DS_RESTRICT dest, const void *QT3DS_RESTRICT src, QT3DSU32 count)
+ {
+ return memmove(dest, src, count);
+ }
+
+ /*!
+ Set 128B to zero starting at \c dst+offset. Must be aligned.
+ */
+ QT3DS_FORCE_INLINE void memZero128(void *QT3DS_RESTRICT dest, QT3DSU32 offset = 0)
+ {
+ QT3DS_ASSERT(((size_t(dest) + offset) & 0x7f) == 0);
+ memSet((char *QT3DS_RESTRICT)dest + offset, 0, 128);
+ }
+
+ /*!
+ Prefetch aligned 128B around \c ptr+offset.
+ */
+ QT3DS_FORCE_INLINE void prefetch128(const void *, QT3DSU32 = 0) {}
+
+ /*!
+ Prefetch \c count bytes starting at \c ptr.
+ */
+ QT3DS_FORCE_INLINE void prefetch(const void *ptr, QT3DSU32 count = 0)
+ {
+ for (QT3DSU32 i = 0; i <= count; i += 128)
+ prefetch128(ptr, i);
+ }
+
+ //! \brief platform-specific floor
+ QT3DS_FORCE_INLINE float floatFloor(float x) { return ::floorf(x); }
+} // namespace intrinsics
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxString.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxString.h
new file mode 100644
index 00000000..a4645f2b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxString.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_LINUX_STRING_H
+#define QT3DS_FOUNDATION_QT3DS_LINUX_STRING_H
+
+#include "foundation/Qt3DS.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#pragma warning(push)
+#pragma warning(disable : 4995 4996)
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+QT3DS_INLINE void NVStrcpy(char *dest, size_t size, const char *src)
+{
+ ::strncpy(dest, src, size);
+}
+
+QT3DS_INLINE int NVStrcat(char *dest, size_t size, const char *src)
+{
+ ::strcat(dest, src);
+ return 0;
+}
+QT3DS_INLINE int NVVsprintf(char *dest, size_t size, const char *src, va_list arg)
+{
+ int r = ::vsprintf(dest, src, arg);
+
+ return r;
+}
+QT3DS_INLINE int NVStricmp(const char *str, const char *str1)
+{
+ return (::strcasecmp(str, str1));
+}
+
+namespace string {
+
+ QT3DS_INLINE void strcpy(char *dest, size_t size, const char *src) { ::strcpy(dest, src); }
+ QT3DS_INLINE void strcat(char *dest, size_t size, const char *src) { ::strcat(dest, src); }
+ // QT3DS_INLINE int strcasecmp(const char *str, const char *str1) {return(::strcasecmp(str,
+ // str1));}
+ QT3DS_INLINE QT3DSI32 stricmp(const char *str, const char *str1) { return (::strcasecmp(str, str1)); }
+ QT3DS_INLINE QT3DSI32 strnicmp(const char *str, const char *str1, size_t len)
+ {
+ return (::strncasecmp(str, str1, len));
+ }
+
+ QT3DS_INLINE QT3DSI32 strncat_s(char *dstBfr, size_t dstSize, const char *srcBfr, size_t numCpy)
+ {
+ if (!dstBfr || !srcBfr || !dstSize)
+ return -1;
+
+ size_t len = strlen(dstBfr);
+
+ if (len >= dstSize)
+ return -1;
+
+ size_t remain = dstSize - len - 1;
+ size_t transfer = remain > numCpy ? numCpy : remain;
+ ::memmove(dstBfr + len, srcBfr, transfer);
+ dstBfr[len + transfer] = '\0';
+ return numCpy <= remain ? 0 : -1;
+ }
+
+ QT3DS_INLINE QT3DSI32 _vsnprintf(char *dest, size_t size, const char *src, va_list arg)
+ {
+ QT3DSI32 r = ::vsnprintf(dest, size, src, arg);
+
+ return r;
+ }
+ QT3DS_INLINE QT3DSI32 vsprintf(char *dest, size_t size, const char *src, va_list arg)
+ {
+ QT3DSI32 r = ::vsprintf(dest, src, arg);
+
+ return r;
+ }
+ QT3DS_INLINE int vsprintf_s(char *dest, size_t size, const char *src, va_list arg)
+ {
+ int r = ::vsprintf(dest, src, arg);
+
+ return r;
+ }
+
+ QT3DS_INLINE int sprintf_s(char *_DstBuf, size_t _DstSize, const char *_Format, ...)
+ {
+ if (_DstBuf == NULL || _Format == NULL) {
+ return -1;
+ }
+
+ va_list arg;
+ va_start(arg, _Format);
+ int r = ::vsprintf(_DstBuf, _Format, arg);
+ va_end(arg);
+
+ return r;
+ }
+
+ QT3DS_INLINE QT3DSI32 sprintf(char *_DstBuf, size_t _DstSize, const char *_Format, ...)
+ {
+ va_list arg;
+ va_start(arg, _Format);
+ QT3DSI32 r = ::vsprintf(_DstBuf, _Format, arg);
+ va_end(arg);
+
+ return r;
+ }
+
+ QT3DS_INLINE int strncpy_s(char *strDest, size_t sizeInBytes, const char *strSource, size_t count)
+ {
+ if (strDest == NULL || strSource == NULL || sizeInBytes == 0) {
+ return -1;
+ }
+
+ if (sizeInBytes < count) {
+ strDest[0] = 0;
+ return -1;
+ }
+
+ ::strncpy(strDest, strSource, count);
+ return 0;
+ }
+
+ QT3DS_INLINE void strcpy_s(char *dest, size_t size, const char *src)
+ {
+ ::strncpy(dest, src, size);
+ }
+
+ QT3DS_INLINE int strcat_s(char *dest, size_t size, const char *src)
+ {
+ ::strcat(dest, src);
+ return 0;
+ }
+
+ QT3DS_INLINE QT3DSI32 sscanf(const char *buffer, const char *format, ...)
+ {
+ va_list arg;
+ va_start(arg, format);
+ QT3DSI32 r = ::sscanf(buffer, format, arg);
+ va_end(arg);
+
+ return r;
+ };
+
+ QT3DS_INLINE void strlwr(char *str)
+ {
+ while (*str) {
+ if (*str >= 'A' && *str <= 'Z')
+ *str += 32;
+ str++;
+ }
+ }
+
+ QT3DS_INLINE void strupr(char *str)
+ {
+ while (*str) {
+ if (*str >= 'a' && *str <= 'z')
+ *str -= 32;
+ str++;
+ }
+ }
+
+} // namespace string
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+#pragma warning(pop)
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxTrigConstants.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxTrigConstants.h
new file mode 100644
index 00000000..120dec78
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/Qt3DSLinuxTrigConstants.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_LINUX_TRIG_CONSTANTS_H
+#define QT3DS_LINUX_TRIG_CONSTANTS_H
+
+//#define QT3DS_GLOBALCONST extern const __declspec(selectany)
+
+#define QT3DS_GLOBALCONST extern const __attribute__((weak))
+
+QT3DS_ALIGN_PREFIX(16)
+struct QT3DS_VECTORF32
+{
+ float f[4];
+};
+
+#define QT3DS_PI 3.141592654f
+#define QT3DS_2PI 6.283185307f
+#define QT3DS_1DIVPI 0.318309886f
+#define QT3DS_1DIV2PI 0.159154943f
+#define QT3DS_PIDIV2 1.570796327f
+#define QT3DS_PIDIV4 0.785398163f
+
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinCoefficients0 = { 1.0f, -0.166666667f, 8.333333333e-3f,
+ -1.984126984e-4f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinCoefficients1 = { 2.755731922e-6f, -2.505210839e-8f,
+ 1.605904384e-10f, -7.647163732e-13f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinCoefficients2 = { 2.811457254e-15f, -8.220635247e-18f,
+ 1.957294106e-20f, -3.868170171e-23f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosCoefficients0 = { 1.0f, -0.5f, 4.166666667e-2f,
+ -1.388888889e-3f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosCoefficients1 = { 2.480158730e-5f, -2.755731922e-7f,
+ 2.087675699e-9f, -1.147074560e-11f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosCoefficients2 = { 4.779477332e-14f, -1.561920697e-16f,
+ 4.110317623e-19f, -8.896791392e-22f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanCoefficients0 = { 1.0f, 0.333333333f, 0.133333333f,
+ 5.396825397e-2f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanCoefficients1 = { 2.186948854e-2f, 8.863235530e-3f,
+ 3.592128167e-3f, 1.455834485e-3f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanCoefficients2 = { 5.900274264e-4f, 2.391290764e-4f,
+ 9.691537707e-5f, 3.927832950e-5f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinCoefficients0 = { -0.05806367563904f, -0.41861972469416f,
+ 0.22480114791621f, 2.17337241360606f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinCoefficients1 = { 0.61657275907170f, 4.29696498283455f,
+ -1.18942822255452f, -6.53784832094831f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinCoefficients2 = { -1.36926553863413f, -4.48179294237210f,
+ 1.41810672941833f, 5.48179257935713f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanCoefficients0 = { 1.0f, 0.333333334f, 0.2f, 0.142857143f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanCoefficients1 = { 1.111111111e-1f, 9.090909091e-2f,
+ 7.692307692e-2f, 6.666666667e-2f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanCoefficients2 = { 5.882352941e-2f, 5.263157895e-2f,
+ 4.761904762e-2f, 4.347826087e-2f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinEstCoefficients = { 1.0f, -1.66521856991541e-1f,
+ 8.199913018755e-3f, -1.61475937228e-4f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosEstCoefficients = { 1.0f, -4.95348008918096e-1f,
+ 3.878259962881e-2f, -9.24587976263e-4f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanEstCoefficients = { 2.484f, -1.954923183e-1f, 2.467401101f,
+ QT3DS_1DIVPI };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanEstCoefficients = { 7.689891418951e-1f, 1.104742493348f,
+ 8.661844266006e-1f, QT3DS_PIDIV2 };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinEstCoefficients = { -1.36178272886711f, 2.37949493464538f,
+ -8.08228565650486e-1f,
+ 2.78440142746736e-1f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinEstConstants = { 1.00000011921f, QT3DS_PIDIV2, 0.0f, 0.0f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXPiConstants0 = { QT3DS_PI, QT3DS_2PI, QT3DS_1DIVPI, QT3DS_1DIV2PI };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXReciprocalTwoPi = { QT3DS_1DIV2PI, QT3DS_1DIV2PI, QT3DS_1DIV2PI,
+ QT3DS_1DIV2PI };
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/qt_attribution.json b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/qt_attribution.json
new file mode 100644
index 00000000..3c3bed6b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/linux/qt_attribution.json
@@ -0,0 +1,10 @@
+{
+ "Id": "qt3dslinuxinlineaos",
+ "Name": "Qt3DSLinuxInlineAoS",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio, Runtime component.",
+
+ "License": "Other",
+ "LicenseFile": "LICENSE.TXT",
+ "Copyright": "Copyright (c) 2001 Intel Corporation."
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/qt_attribution.json b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/qt_attribution.json
new file mode 100644
index 00000000..067cced8
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/qt_attribution.json
@@ -0,0 +1,10 @@
+{
+ "Id": "convertutf",
+ "Name": "ConvertUTF",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio, Studio and Runtime components.",
+
+ "License": "Other",
+ "LicenseFile": "LICENSE_CONVERTUTF.TXT",
+ "Copyright": "Copyright 2001-2004 Unicode, Inc."
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/LICENSE.TXT b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/LICENSE.TXT
new file mode 100644
index 00000000..f40caef8
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/LICENSE.TXT
@@ -0,0 +1,7 @@
+ Copyright (c) 2001 Intel Corporation.
+
+Permition is granted to use, copy, distribute and prepare derivative works
+of this library for any purpose and without fee, provided, that the above
+copyright notice and this statement appear in all copies.
+Intel makes no representations about the suitability of this library for
+any purpose, and specifically disclaims all warranties.
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsAoS.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsAoS.h
new file mode 100644
index 00000000..c654ec79
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsAoS.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_WINDOWS_AOS_H
+#define QT3DS_WINDOWS_AOS_H
+
+// no includes here! this file should be included from NVcVecMath.h only!!!
+
+#if !COMPILE_VECTOR_INTRINSICS
+#error Vector intrinsics should not be included when using scalar implementation.
+#endif
+
+typedef __m128 FloatV;
+typedef __m128 Vec3V;
+typedef __m128 Vec4V;
+typedef __m128 BoolV;
+typedef __m128 VecU32V;
+typedef __m128 VecI32V;
+typedef __m128 VecU16V;
+typedef __m128 VecI16V;
+typedef __m128 VecU8V;
+typedef __m128 QuatV;
+
+#define FloatVArg FloatV &
+#define Vec3VArg Vec3V &
+#define Vec4VArg Vec4V &
+#define BoolVArg BoolV &
+#define VecU32VArg VecU32V &
+#define VecI32VArg VecI32V &
+#define VecU16VArg VecU16V &
+#define VecI16VArg VecI16V &
+#define VecU8VArg VecU8V &
+#define QuatVArg QuatV &
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat33V
+{
+ Mat33V() {}
+ Mat33V(const Vec3V &c0, const Vec3V &c1, const Vec3V &c2)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ {
+ }
+ Vec3V QT3DS_ALIGN(16, col0);
+ Vec3V QT3DS_ALIGN(16, col1);
+ Vec3V QT3DS_ALIGN(16, col2);
+} QT3DS_ALIGN_SUFFIX(16);
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat34V
+{
+ Mat34V() {}
+ Mat34V(const Vec3V &c0, const Vec3V &c1, const Vec3V &c2, const Vec3V &c3)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ , col3(c3)
+ {
+ }
+ Vec3V QT3DS_ALIGN(16, col0);
+ Vec3V QT3DS_ALIGN(16, col1);
+ Vec3V QT3DS_ALIGN(16, col2);
+ Vec3V QT3DS_ALIGN(16, col3);
+} QT3DS_ALIGN_SUFFIX(16);
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat43V
+{
+ Mat43V() {}
+ Mat43V(const Vec4V &c0, const Vec4V &c1, const Vec4V &c2)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ {
+ }
+ Vec4V QT3DS_ALIGN(16, col0);
+ Vec4V QT3DS_ALIGN(16, col1);
+ Vec4V QT3DS_ALIGN(16, col2);
+} QT3DS_ALIGN_SUFFIX(16);
+
+QT3DS_ALIGN_PREFIX(16)
+struct Mat44V
+{
+ Mat44V() {}
+ Mat44V(const Vec4V &c0, const Vec4V &c1, const Vec4V &c2, const Vec4V &c3)
+ : col0(c0)
+ , col1(c1)
+ , col2(c2)
+ , col3(c3)
+ {
+ }
+ Vec4V QT3DS_ALIGN(16, col0);
+ Vec4V QT3DS_ALIGN(16, col1);
+ Vec4V QT3DS_ALIGN(16, col2);
+ Vec4V QT3DS_ALIGN(16, col3);
+} QT3DS_ALIGN_SUFFIX(16);
+
+#endif // QT3DS_WINDOWS_AOS_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsFile.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsFile.h
new file mode 100644
index 00000000..6c232a54
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsFile.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_WINDOWS_FILE_H
+#define QT3DS_FOUNDATION_QT3DS_WINDOWS_FILE_H
+
+#include "foundation/Qt3DS.h"
+
+#include <stdio.h>
+
+namespace qt3ds {
+namespace foundation {
+ QT3DS_INLINE errno_t fopen_s(FILE **_File, const char *_Filename, const char *_Mode)
+ {
+ return ::fopen_s(_File, _Filename, _Mode);
+ };
+
+} // namespace foundation
+} // namespace qt3ds
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInclude.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInclude.h
new file mode 100644
index 00000000..f01c9f1a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInclude.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOWSINCLUDE_H
+#define WINDOWSINCLUDE_H
+
+#include "foundation/Qt3DS.h"
+
+#ifndef _WIN32
+#error "This file should only be included by Windows builds!!"
+#endif
+
+#ifdef _WINDOWS_ // windows already included
+#error "Only include windows.h through this file!!"
+#endif
+
+// We only support >= Windows XP, and we need this for critical section and
+#define _WIN32_WINNT 0x0500
+
+// turn off as much as we can for windows. All we really need is the thread functions(critical
+// sections/Interlocked* etc)
+#define NOGDICAPMASKS
+#define NOVIRTUALKEYCODES
+#define NOWINMESSAGES
+#define NOWINSTYLES
+#define NOSYSMETRICS
+#define NOMENUS
+#define NOICONS
+#define NOKEYSTATES
+#define NOSYSCOMMANDS
+#define NORASTEROPS
+#define NOSHOWWINDOW
+#define NOATOM
+#define NOCLIPBOARD
+#define NOCOLOR
+#define NOCTLMGR
+#define NODRAWTEXT
+#define NOGDI
+#define NOUSER
+#define NONLS
+#define NOMB
+#define NOMEMMGR
+#define NOMETAFILE
+#define NOMSG
+#define NOOPENFILE
+#define NOSCROLL
+#define NOSERVICE
+#define NOSOUND
+#define NOTEXTMETRIC
+#define NOWH
+#define NOWINOFFSETS
+#define NOCOMM
+#define NOKANJI
+#define NOHELP
+#define NOPROFILER
+#define NODEFERWINDOWPOS
+#define NOMCX
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+#ifdef QT3DS_SUPPORT_SSE
+#include <xmmintrin.h>
+#endif
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInlineAoS.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInlineAoS.h
new file mode 100644
index 00000000..60c57894
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsInlineAoS.h
@@ -0,0 +1,2715 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// Copyright (c) 2001 Intel Corporation.
+//
+// Permition is granted to use, copy, distribute and prepare derivative works
+// of this library for any purpose and without fee, provided, that the above
+// copyright notice and this statement appear in all copies.
+// Intel makes no representations about the suitability of this library for
+// any purpose, and specifically disclaims all warranties.
+// See LEGAL.TXT for all the legal information.
+//
+
+#ifndef QT3DS_WINDOWS_INLINE_AOS_H
+#define QT3DS_WINDOWS_INLINE_AOS_H
+
+#if !COMPILE_VECTOR_INTRINSICS
+#error Vector intrinsics should not be included when using scalar implementation.
+#endif
+
+// Remove this define when all platforms use simd solver.
+#define QT3DS_SUPPORT_SIMD
+
+QT3DS_FORCE_INLINE __m128 m128_I2F(__m128i n)
+{
+ return _mm_castsi128_ps(n);
+}
+QT3DS_FORCE_INLINE __m128i m128_F2I(__m128 n)
+{
+ return _mm_castps_si128(n);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAllTrue4_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return moveMask == (0xf);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAnyTrue4_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return moveMask != (0x0);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAllTrue3_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return (moveMask & 0x7) == (0x7);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAnyTrue3_R(const BoolV a)
+{
+ const QT3DSI32 moveMask = _mm_movemask_ps(a);
+ return (moveMask & 0x7) != (0x0);
+}
+
+/////////////////////////////////////////////////////////////////////
+////FUNCTIONS USED ONLY FOR ASSERTS IN VECTORISED IMPLEMENTATIONS
+/////////////////////////////////////////////////////////////////////
+
+QT3DS_FORCE_INLINE QT3DSU32 FiniteTestEq(const Vec4V a, const Vec4V b)
+{
+ // This is a bit of a bodge.
+ //_mm_comieq_ss returns 1 if either value is nan so we need to re-cast a and b with true encoded
+ //as a non-nan number.
+ // There must be a better way of doing this in sse.
+ const BoolV one = FOne();
+ const BoolV zero = FZero();
+ const BoolV a1 = V4Sel(a, one, zero);
+ const BoolV b1 = V4Sel(b, one, zero);
+ return (_mm_comieq_ss(a1, b1) && _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(1, 1, 1, 1)),
+ _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(1, 1, 1, 1)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(2, 2, 2, 2)),
+ _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(2, 2, 2, 2)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a1, a1, _MM_SHUFFLE(3, 3, 3, 3)),
+ _mm_shuffle_ps(b1, b1, _MM_SHUFFLE(3, 3, 3, 3))));
+}
+
+QT3DS_FORCE_INLINE bool isValidFloatV(const FloatV a)
+{
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)))
+ && _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3))));
+}
+
+QT3DS_FORCE_INLINE bool isValidVec3V(const Vec3V a)
+{
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)), FZero()) ? true : false);
+}
+
+QT3DS_FORCE_INLINE bool isFiniteFloatV(const FloatV a)
+{
+ const QT3DSU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF);
+ const FloatV vBadNum = FloatV_From_F32((QT3DSF32 &)badNumber);
+ const BoolV vMask = BAnd(vBadNum, a);
+ return FiniteTestEq(vMask, BFFFF()) == 1;
+}
+
+QT3DS_FORCE_INLINE bool isFiniteVec3V(const Vec3V a)
+{
+ const QT3DSU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF);
+ const Vec3V vBadNum = Vec3V_From_F32((QT3DSF32 &)badNumber);
+ const BoolV vMask = BAnd(BAnd(vBadNum, a), BTTTF());
+ return FiniteTestEq(vMask, BFFFF()) == 1;
+}
+
+QT3DS_FORCE_INLINE bool isFiniteVec4V(const Vec4V a)
+{
+ /*Vec4V a;
+ QT3DS_ALIGN(16, QT3DSF32 f[4]);
+ F32Array_Aligned_From_Vec4V(a, f);
+ return NVIsFinite(f[0])
+ && NVIsFinite(f[1])
+ && NVIsFinite(f[2])
+ && NVIsFinite(f[3]);*/
+
+ const QT3DSU32 badNumber = (_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF);
+ const Vec4V vBadNum = Vec4V_From_F32((QT3DSF32 &)badNumber);
+ const BoolV vMask = BAnd(vBadNum, a);
+
+ return FiniteTestEq(vMask, BFFFF()) == 1;
+}
+
+QT3DS_FORCE_INLINE bool hasZeroElementinFloatV(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero()) ? true : false);
+}
+
+QT3DS_FORCE_INLINE bool hasZeroElementInVec3V(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero())
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FZero())
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FZero()));
+}
+
+QT3DS_FORCE_INLINE bool hasZeroElementInVec4V(const Vec4V a)
+{
+ return (_mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)), FZero())
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)), FZero())
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)), FZero())
+ || _mm_comieq_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)), FZero()));
+}
+
+/////////////////////////////////////////////////////////////////////
+////VECTORISED FUNCTION IMPLEMENTATIONS
+/////////////////////////////////////////////////////////////////////
+
+QT3DS_FORCE_INLINE FloatV FloatV_From_F32(const QT3DSF32 f)
+{
+ return (_mm_load1_ps(&f));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_F32(const QT3DSF32 f)
+{
+ return _mm_set_ps(0.0f, f, f, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_F32(const QT3DSF32 f)
+{
+ return (_mm_load1_ps(&f));
+}
+
+QT3DS_FORCE_INLINE BoolV BoolV_From_Bool32(const bool f)
+{
+ const QT3DSU32 i = -(QT3DSI32)f;
+ return _mm_load1_ps((float *)&i);
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_NVVec3_Aligned(const QT3DSVec3 &f)
+{
+ VECMATHAOS_ASSERT(0 == ((size_t)&f & 0x0f));
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_NVVec3(const QT3DSVec3 &f)
+{
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_NVVec3_WUndefined(const QT3DSVec3 &f)
+{
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_Vec4V(Vec4V v)
+{
+ return V4SetW(v, V4Zero());
+}
+
+QT3DS_FORCE_INLINE Vec3V Vec3V_From_F32Array_Aligned(const QT3DSF32 *const f)
+{
+ VECMATHAOS_ASSERT(0 == ((QT3DSU64)f & 0x0f));
+ return (_mm_load_ps(f));
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_Vec3V(Vec3V f)
+{
+ return f; // ok if it is implemented as the same type.
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_NVVec3_WUndefined(const QT3DSVec3 &f)
+{
+ return (_mm_set_ps(0.0f, f.z, f.y, f.x));
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_F32Array_Aligned(const QT3DSF32 *const f)
+{
+ VECMATHAOS_ASSERT(0 == ((QT3DSU64)f & 0x0f));
+ return (_mm_load_ps(f));
+}
+
+QT3DS_FORCE_INLINE void F32Array_Aligned_From_Vec4V(const Vec4V a, QT3DSF32 *f)
+{
+ VECMATHAOS_ASSERT(0 == ((QT3DSU64)f & 0x0f));
+ _mm_store_ps(f, a);
+}
+
+QT3DS_FORCE_INLINE void NVU32Array_Aligned_From_BoolV(const BoolV a, QT3DSU32 *f)
+{
+ VECMATHAOS_ASSERT(0 == ((QT3DSU64)f & 0x0f));
+ _mm_store_ps((QT3DSF32 *)f, a);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_F32Array(const QT3DSF32 *const f)
+{
+ return (_mm_loadu_ps(f));
+}
+
+QT3DS_FORCE_INLINE BoolV BoolV_From_Bool32Array(const bool *const f)
+{
+ const QT3DS_ALIGN(16, QT3DSU32 b[4]) = { -(QT3DSI32)f[0], -(QT3DSI32)f[1], -(QT3DSI32)f[2], -(QT3DSI32)f[3] };
+ return _mm_load1_ps((float *)&b);
+}
+
+QT3DS_FORCE_INLINE QT3DSF32 NVF32_From_FloatV(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ QT3DSF32 f;
+ _mm_store_ss(&f, a);
+ return f;
+}
+
+QT3DS_FORCE_INLINE void NVF32_From_FloatV(const FloatV a, QT3DSF32 *QT3DS_RESTRICT f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ _mm_store_ss(f, a);
+}
+
+QT3DS_FORCE_INLINE void NVVec3Aligned_From_Vec3V(const Vec3V a, QT3DSVec3 &f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(0 == ((int)&a & 0x0F));
+ VECMATHAOS_ASSERT(0 == ((int)&f & 0x0F));
+ QT3DS_ALIGN(16, QT3DSF32 f2[4]);
+ _mm_store_ps(f2, a);
+ f = QT3DSVec3(f2[0], f2[1], f2[2]);
+}
+
+QT3DS_FORCE_INLINE void Store_From_BoolV(const BoolV b, QT3DSU32 *b2)
+{
+ _mm_store_ss((QT3DSF32 *)b2, b);
+}
+
+QT3DS_FORCE_INLINE void NVVec3_From_Vec3V(const Vec3V a, QT3DSVec3 &f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(0 == ((int)&a & 0x0F));
+ QT3DS_ALIGN(16, QT3DSF32 f2[4]);
+ _mm_store_ps(f2, a);
+ f = QT3DSVec3(f2[0], f2[1], f2[2]);
+}
+
+QT3DS_FORCE_INLINE Mat33V Mat33V_From_NVMat33(const QT3DSMat33 &m)
+{
+ return Mat33V(Vec3V_From_NVVec3(m.column0), Vec3V_From_NVVec3(m.column1),
+ Vec3V_From_NVVec3(m.column2));
+}
+
+QT3DS_FORCE_INLINE void NVMat33_From_Mat33V(const Mat33V &m, QT3DSMat33 &out)
+{
+ QT3DS_ASSERT((size_t(&out) & 15) == 0);
+ NVVec3_From_Vec3V(m.col0, out.column0);
+ NVVec3_From_Vec3V(m.col1, out.column1);
+ NVVec3_From_Vec3V(m.col2, out.column2);
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualFloatV(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return (_mm_comieq_ss(a, b) != 0);
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualVec3V(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return V3AllEq(a, b) != 0;
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualVec4V(const Vec4V a, const Vec4V b)
+{
+ return V4AllEq(a, b) != 0;
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsEqualBoolV(const BoolV a, const BoolV b)
+{
+ return BAllTrue4_R(VecI32V_IsEq(a, b)) != 0;
+}
+
+#define VECMATH_AOS_EPSILON (1e-3f)
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsNearEqualFloatV(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ const FloatV c = FSub(a, b);
+ static const FloatV minError = FloatV_From_F32(-VECMATH_AOS_EPSILON);
+ static const FloatV maxError = FloatV_From_F32(VECMATH_AOS_EPSILON);
+ return (_mm_comigt_ss(c, minError) && _mm_comilt_ss(c, maxError));
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsNearEqualVec3V(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ const Vec3V c = V3Sub(a, b);
+ static const Vec3V minError = Vec3V_From_F32(-VECMATH_AOS_EPSILON);
+ static const Vec3V maxError = Vec3V_From_F32(VECMATH_AOS_EPSILON);
+ return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxError));
+}
+
+QT3DS_FORCE_INLINE bool _VecMathTests::allElementsNearEqualVec4V(const Vec4V a, const Vec4V b)
+{
+ const Vec4V c = V4Sub(a, b);
+ static const Vec4V minError = Vec4V_From_F32(-VECMATH_AOS_EPSILON);
+ static const Vec4V maxError = Vec4V_From_F32(VECMATH_AOS_EPSILON);
+ return (_mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2)), maxError)
+ && _mm_comigt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), minError)
+ && _mm_comilt_ss(_mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)), maxError));
+}
+
+//////////////////////////////////
+// FLOATV
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE FloatV FZero()
+{
+ return FloatV_From_F32(0.0f);
+}
+
+QT3DS_FORCE_INLINE FloatV FOne()
+{
+ return FloatV_From_F32(1.0f);
+}
+
+QT3DS_FORCE_INLINE FloatV FHalf()
+{
+ return FloatV_From_F32(0.5f);
+}
+
+QT3DS_FORCE_INLINE FloatV FEps()
+{
+ return FloatV_From_F32(QT3DS_ENV_REAL);
+}
+
+QT3DS_FORCE_INLINE FloatV FEps6()
+{
+ return FloatV_From_F32(1e-6f);
+}
+
+QT3DS_FORCE_INLINE FloatV FMax()
+{
+ return FloatV_From_F32(QT3DS_MAX_REAL);
+}
+
+QT3DS_FORCE_INLINE FloatV FNegMax()
+{
+ return FloatV_From_F32(-QT3DS_MAX_REAL);
+}
+
+QT3DS_FORCE_INLINE FloatV IZero()
+{
+ const QT3DSU32 zero = 0;
+ return _mm_load1_ps((QT3DSF32 *)&zero);
+}
+
+QT3DS_FORCE_INLINE FloatV IOne()
+{
+ const QT3DSU32 one = 1;
+ return _mm_load1_ps((QT3DSF32 *)&one);
+}
+
+QT3DS_FORCE_INLINE FloatV ITwo()
+{
+ const QT3DSU32 two = 2;
+ return _mm_load1_ps((QT3DSF32 *)&two);
+}
+
+QT3DS_FORCE_INLINE FloatV IThree()
+{
+ const QT3DSU32 three = 3;
+ return _mm_load1_ps((QT3DSF32 *)&three);
+}
+
+QT3DS_FORCE_INLINE FloatV IFour()
+{
+ QT3DSU32 four = 4;
+ return _mm_load1_ps((QT3DSF32 *)&four);
+}
+
+QT3DS_FORCE_INLINE FloatV FNeg(const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return _mm_sub_ps(_mm_setzero_ps(), f);
+}
+
+QT3DS_FORCE_INLINE FloatV FAdd(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_add_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FSub(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_sub_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FMul(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FDiv(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FDivFast(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE FloatV FRecip(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return _mm_div_ps(FOne(), a);
+}
+
+QT3DS_FORCE_INLINE FloatV FRecipFast(const FloatV a)
+{
+ return _mm_rcp_ps(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FRsqrt(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return _mm_div_ps(FOne(), _mm_sqrt_ps(a));
+}
+
+QT3DS_FORCE_INLINE FloatV FSqrt(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ return _mm_sqrt_ps(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FRsqrtFast(const FloatV a)
+{
+ return _mm_rsqrt_ps(a);
+}
+
+QT3DS_FORCE_INLINE FloatV FScaleAdd(const FloatV a, const FloatV b, const FloatV c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidFloatV(c));
+ return FAdd(FMul(a, b), c);
+}
+
+QT3DS_FORCE_INLINE FloatV FNegScaleSub(const FloatV a, const FloatV b, const FloatV c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidFloatV(c));
+ return FSub(c, FMul(a, b));
+}
+
+QT3DS_FORCE_INLINE FloatV FAbs(const FloatV a)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ QT3DS_ALIGN(16, const static QT3DSU32 absMask[4]) = { 0x7fFFffFF, 0x7fFFffFF, 0x7fFFffFF,
+ 0x7fFFffFF };
+ return _mm_and_ps(a, _mm_load_ps((QT3DSF32 *)absMask));
+}
+
+QT3DS_FORCE_INLINE FloatV FSel(const BoolV c, const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(_VecMathTests::allElementsEqualBoolV(c, BTTTT())
+ || _VecMathTests::allElementsEqualBoolV(c, BFFFF()));
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
+}
+
+QT3DS_FORCE_INLINE BoolV FIsGrtr(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_cmpgt_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV FIsGrtrOrEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_cmpge_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV FIsEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FMax(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_max_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FMin(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_min_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE FloatV FClamp(const FloatV a, const FloatV minV, const FloatV maxV)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(minV));
+ VECMATHAOS_ASSERT(isValidFloatV(maxV));
+ return FMax(FMin(a, maxV), minV);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FAllGrtr(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return (_mm_comigt_ss(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FAllGrtrOrEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+
+ return (_mm_comige_ss(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FAllEq(const FloatV a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+
+ return (_mm_comieq_ss(a, b));
+}
+
+QT3DS_FORCE_INLINE FloatV FRound(const FloatV a)
+{
+ // return _mm_round_ps(a, 0x0);
+ const Vec3V half = Vec3V_From_F32(0.5f);
+ const Vec3V aPlusHalf = V3Add(a, half);
+ __m128i tmp = _mm_cvttps_epi32(aPlusHalf);
+ return _mm_cvtepi32_ps(tmp);
+}
+
+QT3DS_FORCE_INLINE FloatV FSin(const FloatV a)
+{
+ // Vec4V V1, V2, V3, V5, V7, V9, V11, V13, V15, V17, V19, V21, V23;
+ // Vec4V S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11;
+ FloatV Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const FloatV twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const FloatV tmp = FMul(a, twoPi);
+ const FloatV b = FRound(tmp);
+ const FloatV V1 = FNegMulSub(twoPi, b, a);
+
+ // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
+ // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
+ const FloatV V2 = FMul(V1, V1);
+ const FloatV V3 = FMul(V2, V1);
+ const FloatV V5 = FMul(V3, V2);
+ const FloatV V7 = FMul(V5, V2);
+ const FloatV V9 = FMul(V7, V2);
+ const FloatV V11 = FMul(V9, V2);
+ const FloatV V13 = FMul(V11, V2);
+ const FloatV V15 = FMul(V13, V2);
+ const FloatV V17 = FMul(V15, V2);
+ const FloatV V19 = FMul(V17, V2);
+ const FloatV V21 = FMul(V19, V2);
+ const FloatV V23 = FMul(V21, V2);
+
+ const Vec4V sinCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients0.f);
+ const Vec4V sinCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients1.f);
+ const Vec4V sinCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients2.f);
+
+ const FloatV S1 = V4GetY(sinCoefficients0);
+ const FloatV S2 = V4GetZ(sinCoefficients0);
+ const FloatV S3 = V4GetW(sinCoefficients0);
+ const FloatV S4 = V4GetX(sinCoefficients1);
+ const FloatV S5 = V4GetY(sinCoefficients1);
+ const FloatV S6 = V4GetZ(sinCoefficients1);
+ const FloatV S7 = V4GetW(sinCoefficients1);
+ const FloatV S8 = V4GetX(sinCoefficients2);
+ const FloatV S9 = V4GetY(sinCoefficients2);
+ const FloatV S10 = V4GetZ(sinCoefficients2);
+ const FloatV S11 = V4GetW(sinCoefficients2);
+
+ Result = FMulAdd(S1, V3, V1);
+ Result = FMulAdd(S2, V5, Result);
+ Result = FMulAdd(S3, V7, Result);
+ Result = FMulAdd(S4, V9, Result);
+ Result = FMulAdd(S5, V11, Result);
+ Result = FMulAdd(S6, V13, Result);
+ Result = FMulAdd(S7, V15, Result);
+ Result = FMulAdd(S8, V17, Result);
+ Result = FMulAdd(S9, V19, Result);
+ Result = FMulAdd(S10, V21, Result);
+ Result = FMulAdd(S11, V23, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE FloatV FCos(const FloatV a)
+{
+ // XMVECTOR V1, V2, V4, V6, V8, V10, V12, V14, V16, V18, V20, V22;
+ // XMVECTOR C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11;
+ FloatV Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const FloatV twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const FloatV tmp = FMul(a, twoPi);
+ const FloatV b = FRound(tmp);
+ const FloatV V1 = FNegMulSub(twoPi, b, a);
+
+ // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
+ // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
+ const FloatV V2 = FMul(V1, V1);
+ const FloatV V4 = FMul(V2, V2);
+ const FloatV V6 = FMul(V4, V2);
+ const FloatV V8 = FMul(V4, V4);
+ const FloatV V10 = FMul(V6, V4);
+ const FloatV V12 = FMul(V6, V6);
+ const FloatV V14 = FMul(V8, V6);
+ const FloatV V16 = FMul(V8, V8);
+ const FloatV V18 = FMul(V10, V8);
+ const FloatV V20 = FMul(V10, V10);
+ const FloatV V22 = FMul(V12, V10);
+
+ const Vec4V cosCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients0.f);
+ const Vec4V cosCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients1.f);
+ const Vec4V cosCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients2.f);
+
+ const FloatV C1 = V4GetY(cosCoefficients0);
+ const FloatV C2 = V4GetZ(cosCoefficients0);
+ const FloatV C3 = V4GetW(cosCoefficients0);
+ const FloatV C4 = V4GetX(cosCoefficients1);
+ const FloatV C5 = V4GetY(cosCoefficients1);
+ const FloatV C6 = V4GetZ(cosCoefficients1);
+ const FloatV C7 = V4GetW(cosCoefficients1);
+ const FloatV C8 = V4GetX(cosCoefficients2);
+ const FloatV C9 = V4GetY(cosCoefficients2);
+ const FloatV C10 = V4GetZ(cosCoefficients2);
+ const FloatV C11 = V4GetW(cosCoefficients2);
+
+ Result = FMulAdd(C1, V2, V4One());
+ Result = FMulAdd(C2, V4, Result);
+ Result = FMulAdd(C3, V6, Result);
+ Result = FMulAdd(C4, V8, Result);
+ Result = FMulAdd(C5, V10, Result);
+ Result = FMulAdd(C6, V12, Result);
+ Result = FMulAdd(C7, V14, Result);
+ Result = FMulAdd(C8, V16, Result);
+ Result = FMulAdd(C9, V18, Result);
+ Result = FMulAdd(C10, V20, Result);
+ Result = FMulAdd(C11, V22, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FOutOfBounds(const FloatV a, const FloatV min, const FloatV max)
+{
+ const BoolV ffff = BFFFF();
+ const BoolV c = BOr(FIsGrtr(a, max), FIsGrtr(min, a));
+ return !BAllEq(c, ffff);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FInBounds(const FloatV a, const FloatV min, const FloatV max)
+{
+ const BoolV tttt = BTTTT();
+ const BoolV c = BAnd(FIsGrtrOrEq(a, min), FIsGrtrOrEq(max, a));
+ return BAllEq(c, tttt);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FOutOfBounds(const FloatV a, const FloatV bounds)
+{
+ return FOutOfBounds(a, FNeg(bounds), bounds);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 FInBounds(const FloatV a, const FloatV bounds)
+{
+ return FInBounds(a, FNeg(bounds), bounds);
+}
+
+//////////////////////////////////
+// VEC3V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec3V V3Splat(const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ const __m128 zero = V3Zero();
+ const __m128 fff0 = _mm_move_ss(f, zero);
+ return _mm_shuffle_ps(fff0, fff0, _MM_SHUFFLE(0, 1, 2, 3));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(x));
+ VECMATHAOS_ASSERT(isValidFloatV(y));
+ VECMATHAOS_ASSERT(isValidFloatV(z));
+ // static on zero causes compiler crash on x64 debug_opt
+ const __m128 zero = V3Zero();
+ const __m128 xy = _mm_move_ss(x, y);
+ const __m128 z0 = _mm_move_ss(zero, z);
+
+ return _mm_shuffle_ps(xy, z0, _MM_SHUFFLE(1, 0, 0, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3UnitX()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 x[4]) = { 1.0f, 0.0f, 0.0f, 0.0f };
+ const __m128 x128 = _mm_load_ps(x);
+ return x128;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3UnitY()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 y[4]) = { 0.0f, 1.0f, 0.0f, 0.0f };
+ const __m128 y128 = _mm_load_ps(y);
+ return y128;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3UnitZ()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 z[4]) = { 0.0f, 0.0f, 1.0f, 0.0f };
+ const __m128 z128 = _mm_load_ps(z);
+ return z128;
+}
+
+QT3DS_FORCE_INLINE FloatV V3GetX(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE FloatV V3GetY(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
+}
+
+QT3DS_FORCE_INLINE FloatV V3GetZ(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3SetX(const Vec3V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V3Sel(BFTTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3SetY(const Vec3V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V3Sel(BTFTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3SetZ(const Vec3V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V3Sel(BTTFT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ColX(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 0, 3, 0));
+ return V3SetY(r, V3GetX(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ColY(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 1, 3, 1));
+ return V3SetY(r, V3GetY(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ColZ(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ Vec3V r = _mm_shuffle_ps(a, c, _MM_SHUFFLE(3, 2, 3, 2));
+ return V3SetY(r, V3GetZ(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Zero()
+{
+ return Vec3V_From_F32(0.0f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3One()
+{
+ return Vec3V_From_F32(1.0f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Eps()
+{
+ return Vec3V_From_F32(QT3DS_ENV_REAL);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Neg(const Vec3V f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(f));
+ return _mm_sub_ps(_mm_setzero_ps(), f);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Add(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_add_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Sub(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_sub_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Scale(const Vec3V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Mul(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ScaleInv(const Vec3V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Div(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ // why are these here?
+ // static const __m128 one=V3One();
+ // static const __m128 tttf=BTTTF();
+ // const __m128 b1=V3Sel(tttf,b,one);
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ScaleInvFast(const Vec3V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3DivFast(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ const __m128 one = V3One();
+ const __m128 tttf = BTTTF();
+ const __m128 b1 = V3Sel(tttf, b, one);
+ return _mm_mul_ps(a, _mm_rcp_ps(b1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Recip(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 tttf = BTTTF();
+ const __m128 recipA = _mm_div_ps(V3One(), a);
+ return V3Sel(tttf, recipA, zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3RecipFast(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 tttf = BTTTF();
+ const __m128 recipA = _mm_rcp_ps(a);
+ return V3Sel(tttf, recipA, zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Rsqrt(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 tttf = BTTTF();
+ const __m128 recipA = _mm_div_ps(V3One(), _mm_sqrt_ps(a));
+ return V3Sel(tttf, recipA, zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3RsqrtFast(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 tttf = BTTTF();
+ const __m128 recipA = _mm_rsqrt_ps(a);
+ return V3Sel(tttf, recipA, zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3ScaleAdd(const Vec3V a, const FloatV b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Add(V3Scale(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NegScaleSub(const Vec3V a, const FloatV b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Sub(c, V3Scale(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3MulAdd(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Add(V3Mul(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NegMulSub(const Vec3V a, const Vec3V b, const Vec3V c)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ VECMATHAOS_ASSERT(isValidVec3V(c));
+ return V3Sub(c, V3Mul(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Abs(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Max(a, V3Neg(a));
+}
+
+QT3DS_FORCE_INLINE FloatV V3Dot(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ __m128 dot1 = _mm_mul_ps(a, b); // w,z,y,x
+ //__m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2,1,0,3)); //z,y,x,w
+ //__m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1,0,3,2)); //y,x,w,z
+ //__m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0,3,2,1)); //x,w,z,y
+ // return _mm_add_ps(_mm_add_ps(shuf2, shuf3), _mm_add_ps(dot1,shuf1));
+
+ __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 0, 0, 0)); // z,y,x,w
+ __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 1, 1, 1)); // y,x,w,z
+ __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 2, 2, 2)); // x,w,z,y
+ return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Cross(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ __m128 l1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
+ __m128 l2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
+ __m128 r1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2)); // z,x,y,w
+ __m128 r2 = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); // y,z,x,w
+ return _mm_sub_ps(_mm_mul_ps(l1, l2), _mm_mul_ps(r1, r2));
+}
+
+QT3DS_FORCE_INLINE FloatV V3Length(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_sqrt_ps(V3Dot(a, a));
+}
+
+QT3DS_FORCE_INLINE FloatV V3LengthSq(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Dot(a, a);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Normalize(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(V3Dot(a, a) != FZero())
+ return V3ScaleInv(a, _mm_sqrt_ps(V3Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NormalizeFast(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return V3Mul(a, _mm_rsqrt_ps(V3Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3NormalizeSafe(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 eps = V3Eps();
+ const __m128 length = V3Length(a);
+ const __m128 isGreaterThanZero = FIsGrtr(length, eps);
+ return V3Sel(isGreaterThanZero, V3ScaleInv(a, length), zero);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Sel(const BoolV c, const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
+}
+
+QT3DS_FORCE_INLINE BoolV V3IsGrtr(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_cmpgt_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V3IsGrtrOrEq(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_cmpge_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V3IsEq(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Max(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_max_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Min(const Vec3V a, const Vec3V b)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(b));
+ return _mm_min_ps(a, b);
+}
+
+// Extract the maximum value from a
+QT3DS_FORCE_INLINE FloatV V3ExtractMax(const Vec3V a)
+{
+ const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
+ const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
+
+ return _mm_max_ps(_mm_max_ps(shuf1, shuf2), shuf3);
+}
+
+// Extract the maximum value from a
+QT3DS_FORCE_INLINE FloatV V3ExtractMin(const Vec3V a)
+{
+ const __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1));
+ const __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2));
+
+ return _mm_min_ps(_mm_min_ps(shuf1, shuf2), shuf3);
+}
+
+//// if(a > 0.0f) return 1.0f; else if a == 0.f return 0.f, else return -1.f;
+// QT3DS_FORCE_INLINE Vec3V V3MathSign(const Vec3V a)
+//{
+// VECMATHAOS_ASSERT(isValidVec3V(a));
+//
+// const __m128i ai = _mm_cvtps_epi32(a);
+// const __m128i bi = _mm_cvtps_epi32(V3Neg(a));
+// const __m128 aa = _mm_cvtepi32_ps(_mm_srai_epi32(ai, 31));
+// const __m128 bb = _mm_cvtepi32_ps(_mm_srai_epi32(bi, 31));
+// return _mm_or_ps(aa, bb);
+//}
+
+// return (a >= 0.0f) ? 1.0f : -1.0f;
+QT3DS_FORCE_INLINE Vec3V V3Sign(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ const __m128 zero = V3Zero();
+ const __m128 one = V3One();
+ const __m128 none = V3Neg(one);
+ return V3Sel(V3IsGrtrOrEq(a, zero), one, none);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Clamp(const Vec3V a, const Vec3V minV, const Vec3V maxV)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(minV));
+ VECMATHAOS_ASSERT(isValidVec3V(maxV));
+ return V3Max(V3Min(a, maxV), minV);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3AllGrtr(const Vec3V a, const Vec3V b)
+{
+ return BAllTrue3_R(V4IsGrtr(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3AllGrtrOrEq(const Vec3V a, const Vec3V b)
+{
+ return BAllTrue3_R(V4IsGrtrOrEq(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3AllEq(const Vec3V a, const Vec3V b)
+{
+ return BAllTrue3_R(V4IsEq(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Round(const Vec3V a)
+{
+ // return _mm_round_ps(a, 0x0);
+ const Vec3V half = Vec3V_From_F32(0.5f);
+ const Vec3V aPlusHalf = V3Add(a, half);
+ const __m128i tmp = _mm_cvttps_epi32(aPlusHalf);
+ return _mm_cvtepi32_ps(tmp);
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Sin(const Vec3V a)
+{
+ // Vec4V V1, V2, V3, V5, V7, V9, V11, V13, V15, V17, V19, V21, V23;
+ // Vec4V S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11;
+ Vec3V Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const Vec3V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec3V tmp = V3Mul(a, twoPi);
+ const Vec3V b = V3Round(tmp);
+ const Vec3V V1 = V3NegMulSub(twoPi, b, a);
+
+ // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
+ // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
+ const Vec3V V2 = V3Mul(V1, V1);
+ const Vec3V V3 = V3Mul(V2, V1);
+ const Vec3V V5 = V3Mul(V3, V2);
+ const Vec3V V7 = V3Mul(V5, V2);
+ const Vec3V V9 = V3Mul(V7, V2);
+ const Vec3V V11 = V3Mul(V9, V2);
+ const Vec3V V13 = V3Mul(V11, V2);
+ const Vec3V V15 = V3Mul(V13, V2);
+ const Vec3V V17 = V3Mul(V15, V2);
+ const Vec3V V19 = V3Mul(V17, V2);
+ const Vec3V V21 = V3Mul(V19, V2);
+ const Vec3V V23 = V3Mul(V21, V2);
+
+ const Vec4V sinCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients0.f);
+ const Vec4V sinCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients1.f);
+ const Vec4V sinCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients2.f);
+
+ const FloatV S1 = V4GetY(sinCoefficients0);
+ const FloatV S2 = V4GetZ(sinCoefficients0);
+ const FloatV S3 = V4GetW(sinCoefficients0);
+ const FloatV S4 = V4GetX(sinCoefficients1);
+ const FloatV S5 = V4GetY(sinCoefficients1);
+ const FloatV S6 = V4GetZ(sinCoefficients1);
+ const FloatV S7 = V4GetW(sinCoefficients1);
+ const FloatV S8 = V4GetX(sinCoefficients2);
+ const FloatV S9 = V4GetY(sinCoefficients2);
+ const FloatV S10 = V4GetZ(sinCoefficients2);
+ const FloatV S11 = V4GetW(sinCoefficients2);
+
+ Result = V3MulAdd(S1, V3, V1);
+ Result = V3MulAdd(S2, V5, Result);
+ Result = V3MulAdd(S3, V7, Result);
+ Result = V3MulAdd(S4, V9, Result);
+ Result = V3MulAdd(S5, V11, Result);
+ Result = V3MulAdd(S6, V13, Result);
+ Result = V3MulAdd(S7, V15, Result);
+ Result = V3MulAdd(S8, V17, Result);
+ Result = V3MulAdd(S9, V19, Result);
+ Result = V3MulAdd(S10, V21, Result);
+ Result = V3MulAdd(S11, V23, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Cos(const Vec3V a)
+{
+ // XMVECTOR V1, V2, V4, V6, V8, V10, V12, V14, V16, V18, V20, V22;
+ // XMVECTOR C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11;
+ Vec3V Result;
+
+ // Modulo the range of the given angles such that -XM_PI <= Angles < XM_PI
+ const Vec3V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec3V tmp = V3Mul(a, twoPi);
+ const Vec3V b = V3Round(tmp);
+ const Vec3V V1 = V3NegMulSub(twoPi, b, a);
+
+ // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
+ // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
+ const Vec3V V2 = V3Mul(V1, V1);
+ const Vec3V V4 = V3Mul(V2, V2);
+ const Vec3V V6 = V3Mul(V4, V2);
+ const Vec3V V8 = V3Mul(V4, V4);
+ const Vec3V V10 = V3Mul(V6, V4);
+ const Vec3V V12 = V3Mul(V6, V6);
+ const Vec3V V14 = V3Mul(V8, V6);
+ const Vec3V V16 = V3Mul(V8, V8);
+ const Vec3V V18 = V3Mul(V10, V8);
+ const Vec3V V20 = V3Mul(V10, V10);
+ const Vec3V V22 = V3Mul(V12, V10);
+
+ const Vec4V cosCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients0.f);
+ const Vec4V cosCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients1.f);
+ const Vec4V cosCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients2.f);
+
+ const FloatV C1 = V4GetY(cosCoefficients0);
+ const FloatV C2 = V4GetZ(cosCoefficients0);
+ const FloatV C3 = V4GetW(cosCoefficients0);
+ const FloatV C4 = V4GetX(cosCoefficients1);
+ const FloatV C5 = V4GetY(cosCoefficients1);
+ const FloatV C6 = V4GetZ(cosCoefficients1);
+ const FloatV C7 = V4GetW(cosCoefficients1);
+ const FloatV C8 = V4GetX(cosCoefficients2);
+ const FloatV C9 = V4GetY(cosCoefficients2);
+ const FloatV C10 = V4GetZ(cosCoefficients2);
+ const FloatV C11 = V4GetW(cosCoefficients2);
+
+ Result = V3MulAdd(C1, V2, V4One());
+ Result = V3MulAdd(C2, V4, Result);
+ Result = V3MulAdd(C3, V6, Result);
+ Result = V3MulAdd(C4, V8, Result);
+ Result = V3MulAdd(C5, V10, Result);
+ Result = V3MulAdd(C6, V12, Result);
+ Result = V3MulAdd(C7, V14, Result);
+ Result = V3MulAdd(C8, V16, Result);
+ Result = V3MulAdd(C9, V18, Result);
+ Result = V3MulAdd(C10, V20, Result);
+ Result = V3MulAdd(C11, V22, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermYZZ(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 2, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermXYX(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 1, 0));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermYZX(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a))
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermZXY(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 0, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermZZY(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 1, 2, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3PermYXX(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 0, 1));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Perm_Zero_1Z_0Y(const Vec3V v0, const Vec3V v1)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v0));
+ VECMATHAOS_ASSERT(isValidVec3V(v1));
+ return _mm_shuffle_ps(v1, v0, _MM_SHUFFLE(3, 1, 2, 3));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Perm_0Z_Zero_1X(const Vec3V v0, const Vec3V v1)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v0));
+ VECMATHAOS_ASSERT(isValidVec3V(v1));
+ return _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(3, 0, 3, 2));
+}
+
+QT3DS_FORCE_INLINE Vec3V V3Perm_1Y_0X_Zero(const Vec3V v0, const Vec3V v1)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v0));
+ VECMATHAOS_ASSERT(isValidVec3V(v1));
+ // There must be a better way to do this.
+ Vec3V v2 = V3Zero();
+ FloatV y1 = V3GetY(v1);
+ FloatV x0 = V3GetX(v0);
+ v2 = V3SetX(v2, y1);
+ return V3SetY(v2, x0);
+}
+
+QT3DS_FORCE_INLINE FloatV V3SumElems(const Vec3V a)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+
+ __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)); // z,y,x,w
+ __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)); // y,x,w,z
+ __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)); // x,w,z,y
+ return _mm_add_ps(_mm_add_ps(shuf1, shuf2), shuf3);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3OutOfBounds(const Vec3V a, const Vec3V min, const Vec3V max)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(min));
+ VECMATHAOS_ASSERT(isValidVec3V(max));
+ const BoolV ffff = BFFFF();
+ const BoolV c = BOr(V3IsGrtr(a, max), V3IsGrtr(min, a));
+ return !BAllEq(c, ffff);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3InBounds(const Vec3V a, const Vec3V min, const Vec3V max)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(a));
+ VECMATHAOS_ASSERT(isValidVec3V(min));
+ VECMATHAOS_ASSERT(isValidVec3V(max));
+ const BoolV tttt = BTTTT();
+ const BoolV c = BAnd(V3IsGrtrOrEq(a, min), V3IsGrtrOrEq(max, a));
+ return BAllEq(c, tttt);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3OutOfBounds(const Vec3V a, const Vec3V bounds)
+{
+ return V3OutOfBounds(a, V3Neg(bounds), bounds);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V3InBounds(const Vec3V a, const Vec3V bounds)
+{
+ return V3InBounds(a, V3Neg(bounds), bounds);
+}
+
+//////////////////////////////////
+// VEC4V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec4V V4Splat(const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ // return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0,0,0,0));
+ return f;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Merge(const FloatV *const floatVArray)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[0]));
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[1]));
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[2]));
+ VECMATHAOS_ASSERT(isValidFloatV(floatVArray[3]));
+ __m128 xw = _mm_move_ss(floatVArray[1], floatVArray[0]); // y, y, y, x
+ __m128 yz = _mm_move_ss(floatVArray[2], floatVArray[3]); // z, z, z, w
+ return (_mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Merge(const FloatVArg x, const FloatVArg y, const FloatVArg z,
+ const FloatVArg w)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(x));
+ VECMATHAOS_ASSERT(isValidFloatV(y));
+ VECMATHAOS_ASSERT(isValidFloatV(z));
+ VECMATHAOS_ASSERT(isValidFloatV(w));
+ __m128 xw = _mm_move_ss(y, x); // y, y, y, x
+ __m128 yz = _mm_move_ss(z, w); // z, z, z, w
+ return (_mm_shuffle_ps(xw, yz, _MM_SHUFFLE(0, 2, 1, 0)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitW()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 w[4]) = { 0.0f, 0.0f, 0.0f, 1.0f };
+ const __m128 w128 = _mm_load_ps(w);
+ return w128;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitX()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 x[4]) = { 1.0f, 0.0f, 0.0f, 0.0f };
+ const __m128 x128 = _mm_load_ps(x);
+ return x128;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitY()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 y[4]) = { 0.0f, 1.0f, 0.0f, 0.0f };
+ const __m128 y128 = _mm_load_ps(y);
+ return y128;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4UnitZ()
+{
+ const QT3DS_ALIGN(16, QT3DSF32 z[4]) = { 0.0f, 0.0f, 1.0f, 0.0f };
+ const __m128 z128 = _mm_load_ps(z);
+ return z128;
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetW(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3));
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetX(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetY(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
+}
+
+QT3DS_FORCE_INLINE FloatV V4GetZ(const Vec4V f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetW(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BTTTF(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetX(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BFTTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetY(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BTFTT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4SetZ(const Vec4V v, const FloatV f)
+{
+ VECMATHAOS_ASSERT(isValidVec3V(v));
+ VECMATHAOS_ASSERT(isValidFloatV(f));
+ return V4Sel(BTTFT(), v, f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Zero()
+{
+ return Vec4V_From_F32(0.0f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4One()
+{
+ return Vec4V_From_F32(1.0f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Eps()
+{
+ return Vec4V_From_F32(QT3DS_ENV_REAL);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Neg(const Vec4V f)
+{
+ return _mm_sub_ps(_mm_setzero_ps(), f);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Add(const Vec4V a, const Vec4V b)
+{
+ return _mm_add_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Sub(const Vec4V a, const Vec4V b)
+{
+ return _mm_sub_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Scale(const Vec4V a, const FloatV b)
+{
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Mul(const Vec4V a, const Vec4V b)
+{
+ return _mm_mul_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4ScaleInv(const Vec4V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Div(const Vec4V a, const Vec4V b)
+{
+ return _mm_div_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4ScaleInvFast(const Vec4V a, const FloatV b)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4DivFast(const Vec4V a, const Vec4V b)
+{
+ return _mm_mul_ps(a, _mm_rcp_ps(b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Recip(const Vec4V a)
+{
+ return _mm_div_ps(V4One(), a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4RecipFast(const Vec4V a)
+{
+ return _mm_rcp_ps(a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Rsqrt(const Vec4V a)
+{
+ return _mm_div_ps(V4One(), _mm_sqrt_ps(a));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4RsqrtFast(const Vec4V a)
+{
+ return _mm_rsqrt_ps(a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4ScaleAdd(const Vec4V a, const FloatV b, const Vec4V c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return V4Add(V4Scale(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NegScaleSub(const Vec4V a, const FloatV b, const Vec4V c)
+{
+ VECMATHAOS_ASSERT(isValidFloatV(b));
+ return V4Sub(c, V4Scale(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4MulAdd(const Vec4V a, const Vec4V b, const Vec4V c)
+{
+ return V4Add(V4Mul(a, b), c);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NegMulSub(const Vec4V a, const Vec4V b, const Vec4V c)
+{
+ return V4Sub(c, V4Mul(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Abs(const Vec4V a)
+{
+ return V4Max(a, V4Neg(a));
+}
+
+QT3DS_FORCE_INLINE FloatV V4Dot(const Vec4V a, const Vec4V b)
+{
+ __m128 dot1 = _mm_mul_ps(a, b); // x,y,z,w
+ __m128 shuf1 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(2, 1, 0, 3)); // w,x,y,z
+ __m128 shuf2 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(1, 0, 3, 2)); // z,w,x,y
+ __m128 shuf3 = _mm_shuffle_ps(dot1, dot1, _MM_SHUFFLE(0, 3, 2, 1)); // y,z,w,x
+ return _mm_add_ps(_mm_add_ps(shuf2, shuf3), _mm_add_ps(dot1, shuf1));
+}
+
+QT3DS_FORCE_INLINE FloatV V4Length(const Vec4V a)
+{
+ return _mm_sqrt_ps(V4Dot(a, a));
+}
+
+QT3DS_FORCE_INLINE FloatV V4LengthSq(const Vec4V a)
+{
+ return V4Dot(a, a);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Normalize(const Vec4V a)
+{
+ VECMATHAOS_ASSERT(V4Dot(a, a) != FZero())
+ return V4ScaleInv(a, _mm_sqrt_ps(V4Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NormalizeFast(const Vec4V a)
+{
+ return V4ScaleInvFast(a, _mm_sqrt_ps(V4Dot(a, a)));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4NormalizeSafe(const Vec4V a)
+{
+ const __m128 zero = FZero();
+ const __m128 eps = V3Eps();
+ const __m128 length = V4Length(a);
+ const __m128 isGreaterThanZero = V4IsGrtr(length, eps);
+ return V4Sel(isGreaterThanZero, V4ScaleInv(a, length), zero);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Sel(const BoolV c, const Vec4V a, const Vec4V b)
+{
+ return _mm_or_ps(_mm_andnot_ps(c, b), _mm_and_ps(c, a));
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsGrtr(const Vec4V a, const Vec4V b)
+{
+ return _mm_cmpgt_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsGrtrOrEq(const Vec4V a, const Vec4V b)
+{
+ return _mm_cmpge_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsEq(const Vec4V a, const Vec4V b)
+{
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE BoolV V4IsEqU32(const VecU32V a, const VecU32V b)
+{
+ return _mm_cmpeq_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec3V V4Max(const Vec4V a, const Vec4V b)
+{
+ return _mm_max_ps(a, b);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Min(const Vec4V a, const Vec4V b)
+{
+ return _mm_min_ps(a, b);
+}
+
+// Extract the maximum value from a
+QT3DS_FORCE_INLINE FloatV V4ExtractMax(const Vec4V a)
+{
+ __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3));
+ __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2));
+ __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1));
+
+ return _mm_max_ps(_mm_max_ps(a, shuf1), _mm_max_ps(shuf2, shuf3));
+}
+
+// Extract the maximum value from a
+QT3DS_FORCE_INLINE FloatV V4ExtractMin(const Vec4V a)
+{
+ __m128 shuf1 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 1, 0, 3));
+ __m128 shuf2 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 0, 3, 2));
+ __m128 shuf3 = _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 3, 2, 1));
+
+ return _mm_min_ps(_mm_min_ps(a, shuf1), _mm_min_ps(shuf2, shuf3));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Clamp(const Vec4V a, const Vec4V minV, const Vec4V maxV)
+{
+ return V4Max(V4Min(a, maxV), minV);
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V4AllGrtr(const Vec4V a, const Vec4V b)
+{
+ return BAllTrue4_R(V4IsGrtr(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V4AllGrtrOrEq(const Vec4V a, const Vec4V b)
+{
+ return BAllTrue4_R(V4IsGrtrOrEq(a, b));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 V4AllEq(const Vec4V a, const Vec4V b)
+{
+ return BAllTrue4_R(V4IsEq(a, b));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Round(const Vec4V a)
+{
+ // return _mm_round_ps(a, 0x0);
+ const Vec3V half = Vec3V_From_F32(0.5f);
+ const Vec3V aPlusHalf = V3Add(a, half);
+ __m128i tmp = _mm_cvttps_epi32(aPlusHalf);
+ return _mm_cvtepi32_ps(tmp);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Sin(const Vec4V a)
+{
+ // Vec4V V1, V2, V3, V5, V7, V9, V11, V13, V15, V17, V19, V21, V23;
+ // Vec4V S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11;
+ Vec4V Result;
+
+ const Vec4V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec4V tmp = V4Mul(a, twoPi);
+ const Vec4V b = V4Round(tmp);
+ const Vec4V V1 = V4NegMulSub(twoPi, b, a);
+
+ // sin(V) ~= V - V^3 / 3! + V^5 / 5! - V^7 / 7! + V^9 / 9! - V^11 / 11! + V^13 / 13! -
+ // V^15 / 15! + V^17 / 17! - V^19 / 19! + V^21 / 21! - V^23 / 23! (for -PI <= V < PI)
+ const Vec4V V2 = V4Mul(V1, V1);
+ const Vec4V V3 = V4Mul(V2, V1);
+ const Vec4V V5 = V4Mul(V3, V2);
+ const Vec4V V7 = V4Mul(V5, V2);
+ const Vec4V V9 = V4Mul(V7, V2);
+ const Vec4V V11 = V4Mul(V9, V2);
+ const Vec4V V13 = V4Mul(V11, V2);
+ const Vec4V V15 = V4Mul(V13, V2);
+ const Vec4V V17 = V4Mul(V15, V2);
+ const Vec4V V19 = V4Mul(V17, V2);
+ const Vec4V V21 = V4Mul(V19, V2);
+ const Vec4V V23 = V4Mul(V21, V2);
+
+ const Vec4V sinCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients0.f);
+ const Vec4V sinCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients1.f);
+ const Vec4V sinCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXSinCoefficients2.f);
+
+ const FloatV S1 = V4GetY(sinCoefficients0);
+ const FloatV S2 = V4GetZ(sinCoefficients0);
+ const FloatV S3 = V4GetW(sinCoefficients0);
+ const FloatV S4 = V4GetX(sinCoefficients1);
+ const FloatV S5 = V4GetY(sinCoefficients1);
+ const FloatV S6 = V4GetZ(sinCoefficients1);
+ const FloatV S7 = V4GetW(sinCoefficients1);
+ const FloatV S8 = V4GetX(sinCoefficients2);
+ const FloatV S9 = V4GetY(sinCoefficients2);
+ const FloatV S10 = V4GetZ(sinCoefficients2);
+ const FloatV S11 = V4GetW(sinCoefficients2);
+
+ Result = V4MulAdd(S1, V3, V1);
+ Result = V4MulAdd(S2, V5, Result);
+ Result = V4MulAdd(S3, V7, Result);
+ Result = V4MulAdd(S4, V9, Result);
+ Result = V4MulAdd(S5, V11, Result);
+ Result = V4MulAdd(S6, V13, Result);
+ Result = V4MulAdd(S7, V15, Result);
+ Result = V4MulAdd(S8, V17, Result);
+ Result = V4MulAdd(S9, V19, Result);
+ Result = V4MulAdd(S10, V21, Result);
+ Result = V4MulAdd(S11, V23, Result);
+
+ return Result;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Cos(const Vec4V a)
+{
+ // XMVECTOR V1, V2, V4, V6, V8, V10, V12, V14, V16, V18, V20, V22;
+ // XMVECTOR C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11;
+ Vec4V Result;
+
+ const Vec4V twoPi = Vec4V_From_F32Array_Aligned(g_PXReciprocalTwoPi.f);
+ const Vec4V tmp = V4Mul(a, twoPi);
+ const Vec4V b = V4Round(tmp);
+ const Vec4V V1 = V4NegMulSub(twoPi, b, a);
+
+ // cos(V) ~= 1 - V^2 / 2! + V^4 / 4! - V^6 / 6! + V^8 / 8! - V^10 / 10! + V^12 / 12! -
+ // V^14 / 14! + V^16 / 16! - V^18 / 18! + V^20 / 20! - V^22 / 22! (for -PI <= V < PI)
+ const Vec4V V2 = V4Mul(V1, V1);
+ const Vec4V V4 = V4Mul(V2, V2);
+ const Vec4V V6 = V4Mul(V4, V2);
+ const Vec4V V8 = V4Mul(V4, V4);
+ const Vec4V V10 = V4Mul(V6, V4);
+ const Vec4V V12 = V4Mul(V6, V6);
+ const Vec4V V14 = V4Mul(V8, V6);
+ const Vec4V V16 = V4Mul(V8, V8);
+ const Vec4V V18 = V4Mul(V10, V8);
+ const Vec4V V20 = V4Mul(V10, V10);
+ const Vec4V V22 = V4Mul(V12, V10);
+
+ const Vec4V cosCoefficients0 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients0.f);
+ const Vec4V cosCoefficients1 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients1.f);
+ const Vec4V cosCoefficients2 = Vec4V_From_F32Array_Aligned(g_PXCosCoefficients2.f);
+
+ const FloatV C1 = V4GetY(cosCoefficients0);
+ const FloatV C2 = V4GetZ(cosCoefficients0);
+ const FloatV C3 = V4GetW(cosCoefficients0);
+ const FloatV C4 = V4GetX(cosCoefficients1);
+ const FloatV C5 = V4GetY(cosCoefficients1);
+ const FloatV C6 = V4GetZ(cosCoefficients1);
+ const FloatV C7 = V4GetW(cosCoefficients1);
+ const FloatV C8 = V4GetX(cosCoefficients2);
+ const FloatV C9 = V4GetY(cosCoefficients2);
+ const FloatV C10 = V4GetZ(cosCoefficients2);
+ const FloatV C11 = V4GetW(cosCoefficients2);
+
+ Result = V4MulAdd(C1, V2, V4One());
+ Result = V4MulAdd(C2, V4, Result);
+ Result = V4MulAdd(C3, V6, Result);
+ Result = V4MulAdd(C4, V8, Result);
+ Result = V4MulAdd(C5, V10, Result);
+ Result = V4MulAdd(C6, V12, Result);
+ Result = V4MulAdd(C7, V14, Result);
+ Result = V4MulAdd(C8, V16, Result);
+ Result = V4MulAdd(C9, V18, Result);
+ Result = V4MulAdd(C10, V20, Result);
+ Result = V4MulAdd(C11, V22, Result);
+
+ return Result;
+}
+
+//////////////////////////////////
+// BoolV
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE BoolV BFFFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0, 0, 0 };
+ const __m128 ffff = _mm_load_ps((float *)&f);
+ return ffff;
+}
+
+QT3DS_FORCE_INLINE BoolV BFFFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0, 0, 0xFFFFFFFF };
+ const __m128 ffft = _mm_load_ps((float *)&f);
+ return ffft;
+}
+
+QT3DS_FORCE_INLINE BoolV BFFTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0, 0xFFFFFFFF, 0 };
+ const __m128 fftf = _mm_load_ps((float *)&f);
+ return fftf;
+}
+
+QT3DS_FORCE_INLINE BoolV BFFTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 fftt = _mm_load_ps((float *)&f);
+ return fftt;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0xFFFFFFFF, 0, 0 };
+ const __m128 ftff = _mm_load_ps((float *)&f);
+ return ftff;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0xFFFFFFFF, 0, 0xFFFFFFFF };
+ const __m128 ftft = _mm_load_ps((float *)&f);
+ return ftft;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0xFFFFFFFF, 0xFFFFFFFF, 0 };
+ const __m128 fttf = _mm_load_ps((float *)&f);
+ return fttf;
+}
+
+QT3DS_FORCE_INLINE BoolV BFTTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 fttt = _mm_load_ps((float *)&f);
+ return fttt;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0, 0, 0 };
+ const __m128 tfff = _mm_load_ps((float *)&f);
+ return tfff;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0, 0, 0xFFFFFFFF };
+ const __m128 tfft = _mm_load_ps((float *)&f);
+ return tfft;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0, 0xFFFFFFFF, 0 };
+ const __m128 tftf = _mm_load_ps((float *)&f);
+ return tftf;
+}
+
+QT3DS_FORCE_INLINE BoolV BTFTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 tftt = _mm_load_ps((float *)&f);
+ return tftt;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTFF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0, 0 };
+ const __m128 ttff = _mm_load_ps((float *)&f);
+ return ttff;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTFT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0, 0xFFFFFFFF };
+ const __m128 ttft = _mm_load_ps((float *)&f);
+ return ttft;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTTF()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0 };
+ const __m128 tttf = _mm_load_ps((float *)&f);
+ return tttf;
+}
+
+QT3DS_FORCE_INLINE BoolV BTTTT()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+ const __m128 tttt = _mm_load_ps((float *)&f);
+ return tttt;
+}
+
+QT3DS_FORCE_INLINE BoolV BXMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0xFFFFFFFF, 0, 0, 0 };
+ const __m128 tfff = _mm_load_ps((float *)&f);
+ return tfff;
+}
+
+QT3DS_FORCE_INLINE BoolV BYMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0xFFFFFFFF, 0, 0 };
+ const __m128 ftff = _mm_load_ps((float *)&f);
+ return ftff;
+}
+
+QT3DS_FORCE_INLINE BoolV BZMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0, 0xFFFFFFFF, 0 };
+ const __m128 fftf = _mm_load_ps((float *)&f);
+ return fftf;
+}
+
+QT3DS_FORCE_INLINE BoolV BWMask()
+{
+ const QT3DS_ALIGN(16, QT3DSU32 f[4]) = { 0, 0, 0, 0xFFFFFFFF };
+ const __m128 ffft = _mm_load_ps((float *)&f);
+ return ffft;
+}
+
+QT3DS_FORCE_INLINE BoolV BGetX(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(0, 0, 0, 0));
+}
+
+QT3DS_FORCE_INLINE BoolV BGetY(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(1, 1, 1, 1));
+}
+
+QT3DS_FORCE_INLINE BoolV BGetZ(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(2, 2, 2, 2));
+}
+
+QT3DS_FORCE_INLINE BoolV BGetW(const BoolV f)
+{
+ return _mm_shuffle_ps(f, f, _MM_SHUFFLE(3, 3, 3, 3));
+}
+
+QT3DS_FORCE_INLINE BoolV BAnd(const BoolV a, const BoolV b)
+{
+ return (_mm_and_ps(a, b));
+}
+
+QT3DS_FORCE_INLINE BoolV BNot(const BoolV a)
+{
+ const BoolV bAllTrue(BTTTT());
+ return _mm_xor_ps(a, bAllTrue);
+}
+
+QT3DS_FORCE_INLINE BoolV BAndNot(const BoolV a, const BoolV b)
+{
+ return (_mm_andnot_ps(a, b));
+}
+
+QT3DS_FORCE_INLINE BoolV BOr(const BoolV a, const BoolV b)
+{
+ return (_mm_or_ps(a, b));
+}
+
+QT3DS_FORCE_INLINE BoolV BAllTrue4(const BoolV a)
+{
+ const BoolV bTmp = _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3)));
+ return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE BoolV BAnyTrue4(const BoolV a)
+{
+ const BoolV bTmp = _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 2, 3)));
+ return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE BoolV BAllTrue3(const BoolV a)
+{
+ const BoolV bTmp = _mm_and_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
+ return _mm_and_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE BoolV BAnyTrue3(const BoolV a)
+{
+ const BoolV bTmp = _mm_or_ps(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 1, 0, 1)),
+ _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
+ return _mm_or_ps(_mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(0, 0, 0, 0)),
+ _mm_shuffle_ps(bTmp, bTmp, _MM_SHUFFLE(1, 1, 1, 1)));
+}
+
+QT3DS_FORCE_INLINE QT3DSU32 BAllEq(const BoolV a, const BoolV b)
+{
+ const BoolV bTest = m128_I2F(_mm_cmpeq_epi32(m128_F2I(a), m128_F2I(b)));
+ return BAllTrue4_R(bTest);
+}
+
+//////////////////////////////////
+// MAT33V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec3V M33MulV3(const Mat33V &a, const Vec3V b)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ const Vec3V v0 = V3Scale(a.col0, x);
+ const Vec3V v1 = V3Scale(a.col1, y);
+ const Vec3V v2 = V3Scale(a.col2, z);
+ const Vec3V v0PlusV1 = V3Add(v0, v1);
+ return V3Add(v0PlusV1, v2);
+}
+
+QT3DS_FORCE_INLINE Vec3V M33TrnspsMulV3(const Mat33V &a, const Vec3V b)
+{
+ const FloatV x = V3Dot(a.col0, b);
+ const FloatV y = V3Dot(a.col1, b);
+ const FloatV z = V3Dot(a.col2, b);
+ return V3Merge(x, y, z);
+}
+
+QT3DS_FORCE_INLINE Vec3V M33MulV3AddV3(const Mat33V &A, const Vec3V b, const Vec3V c)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ Vec3V result = V3MulAdd(A.col0, x, c);
+ result = V3MulAdd(A.col1, y, result);
+ return V3MulAdd(A.col2, z, result);
+}
+
+QT3DS_FORCE_INLINE Mat33V M33MulM33(const Mat33V &a, const Mat33V &b)
+{
+ return Mat33V(M33MulV3(a, b.col0), M33MulV3(a, b.col1), M33MulV3(a, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Add(const Mat33V &a, const Mat33V &b)
+{
+ return Mat33V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Sub(const Mat33V &a, const Mat33V &b)
+{
+ return Mat33V(V3Sub(a.col0, b.col0), V3Sub(a.col1, b.col1), V3Sub(a.col2, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Neg(const Mat33V &a)
+{
+ return Mat33V(V3Neg(a.col0), V3Neg(a.col1), V3Neg(a.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Abs(const Mat33V &a)
+{
+ return Mat33V(V3Abs(a.col0), V3Abs(a.col1), V3Abs(a.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Inverse(const Mat33V &a)
+{
+ const BoolV tfft = BTFFT();
+ const BoolV tttf = BTTTF();
+ const FloatV zero = V3Zero();
+ const Vec3V cross01 = V3Cross(a.col0, a.col1);
+ const Vec3V cross12 = V3Cross(a.col1, a.col2);
+ const Vec3V cross20 = V3Cross(a.col2, a.col0);
+ const FloatV dot = V3Dot(cross01, a.col2);
+ const FloatV invDet = _mm_rcp_ps(dot);
+ const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01);
+ const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01);
+ Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20);
+ colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0));
+ const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2));
+ const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0));
+ const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd));
+ const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0));
+ const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0));
+ const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd));
+
+ return Mat33V(_mm_mul_ps(colInv0, invDet), _mm_mul_ps(colInv1, invDet),
+ _mm_mul_ps(colInv2, invDet));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Trnsps(const Mat33V &a)
+{
+ return Mat33V(V3Merge(V3GetX(a.col0), V3GetX(a.col1), V3GetX(a.col2)),
+ V3Merge(V3GetY(a.col0), V3GetY(a.col1), V3GetY(a.col2)),
+ V3Merge(V3GetZ(a.col0), V3GetZ(a.col1), V3GetZ(a.col2)));
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Identity()
+{
+ return Mat33V(V3UnitX(), V3UnitY(), V3UnitZ());
+}
+
+QT3DS_FORCE_INLINE Mat33V M33Diagonal(const Vec3VArg d)
+{
+ const FloatV x = V3Mul(V3UnitX(), d);
+ const FloatV y = V3Mul(V3UnitY(), d);
+ const FloatV z = V3Mul(V3UnitZ(), d);
+ return Mat33V(x, y, z);
+}
+
+//////////////////////////////////
+// MAT34V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec3V M34MulV3(const Mat34V &a, const Vec3V b)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ const Vec3V v0 = V3Scale(a.col0, x);
+ const Vec3V v1 = V3Scale(a.col1, y);
+ const Vec3V v2 = V3Scale(a.col2, z);
+ const Vec3V v0PlusV1 = V3Add(v0, v1);
+ const Vec3V v0PlusV1Plusv2 = V3Add(v0PlusV1, v2);
+ return (V3Add(v0PlusV1Plusv2, a.col3));
+}
+
+QT3DS_FORCE_INLINE Vec3V M34Mul33V3(const Mat34V &a, const Vec3V b)
+{
+ const FloatV x = V3GetX(b);
+ const FloatV y = V3GetY(b);
+ const FloatV z = V3GetZ(b);
+ const Vec3V v0 = V3Scale(a.col0, x);
+ const Vec3V v1 = V3Scale(a.col1, y);
+ const Vec3V v2 = V3Scale(a.col2, z);
+ const Vec3V v0PlusV1 = V3Add(v0, v1);
+ return V3Add(v0PlusV1, v2);
+}
+
+QT3DS_FORCE_INLINE Vec3V M34TrnspsMul33V3(const Mat34V &a, const Vec3V b)
+{
+ const FloatV x = V3Dot(a.col0, b);
+ const FloatV y = V3Dot(a.col1, b);
+ const FloatV z = V3Dot(a.col2, b);
+ return V3Merge(x, y, z);
+}
+
+QT3DS_FORCE_INLINE Mat34V M34MulM34(const Mat34V &a, const Mat34V &b)
+{
+ return Mat34V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2),
+ M34MulV3(a, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat33V M34MulM33(const Mat34V &a, const Mat33V &b)
+{
+ return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat33V M34Mul33MM34(const Mat34V &a, const Mat34V &b)
+{
+ return Mat33V(M34Mul33V3(a, b.col0), M34Mul33V3(a, b.col1), M34Mul33V3(a, b.col2));
+}
+
+QT3DS_FORCE_INLINE Mat34V M34Add(const Mat34V &a, const Mat34V &b)
+{
+ return Mat34V(V3Add(a.col0, b.col0), V3Add(a.col1, b.col1), V3Add(a.col2, b.col2),
+ V3Add(a.col3, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat34V M34Inverse(const Mat34V &a)
+{
+ Mat34V aInv;
+ const BoolV tfft = BTFFT();
+ const BoolV tttf = BTTTF();
+ const FloatV zero = V3Zero();
+ const Vec3V cross01 = V3Cross(a.col0, a.col1);
+ const Vec3V cross12 = V3Cross(a.col1, a.col2);
+ const Vec3V cross20 = V3Cross(a.col2, a.col0);
+ const FloatV dot = V3Dot(cross01, a.col2);
+ const FloatV invDet = _mm_rcp_ps(dot);
+ const Vec3V mergeh = _mm_unpacklo_ps(cross12, cross01);
+ const Vec3V mergel = _mm_unpackhi_ps(cross12, cross01);
+ Vec3V colInv0 = _mm_unpacklo_ps(mergeh, cross20);
+ colInv0 = _mm_or_ps(_mm_andnot_ps(tttf, zero), _mm_and_ps(tttf, colInv0));
+ const Vec3V zppd = _mm_shuffle_ps(mergeh, cross20, _MM_SHUFFLE(3, 0, 0, 2));
+ const Vec3V pbwp = _mm_shuffle_ps(cross20, mergeh, _MM_SHUFFLE(3, 3, 1, 0));
+ const Vec3V colInv1 = _mm_or_ps(_mm_andnot_ps(BTFFT(), pbwp), _mm_and_ps(BTFFT(), zppd));
+ const Vec3V xppd = _mm_shuffle_ps(mergel, cross20, _MM_SHUFFLE(3, 0, 0, 0));
+ const Vec3V pcyp = _mm_shuffle_ps(cross20, mergel, _MM_SHUFFLE(3, 1, 2, 0));
+ const Vec3V colInv2 = _mm_or_ps(_mm_andnot_ps(tfft, pcyp), _mm_and_ps(tfft, xppd));
+ aInv.col0 = _mm_mul_ps(colInv0, invDet);
+ aInv.col1 = _mm_mul_ps(colInv1, invDet);
+ aInv.col2 = _mm_mul_ps(colInv2, invDet);
+ aInv.col3 = M34Mul33V3(aInv, V3Neg(a.col3));
+ return aInv;
+}
+
+QT3DS_FORCE_INLINE Mat33V M34Trnsps33(const Mat34V &a)
+{
+ return Mat33V(V3Merge(V3GetX(a.col0), V3GetX(a.col1), V3GetX(a.col2)),
+ V3Merge(V3GetY(a.col0), V3GetY(a.col1), V3GetY(a.col2)),
+ V3Merge(V3GetZ(a.col0), V3GetZ(a.col1), V3GetZ(a.col2)));
+}
+
+//////////////////////////////////
+// MAT44V
+//////////////////////////////////
+
+QT3DS_FORCE_INLINE Vec4V M44MulV4(const Mat44V &a, const Vec4V b)
+{
+ const FloatV x = V4GetX(b);
+ const FloatV y = V4GetY(b);
+ const FloatV z = V4GetZ(b);
+ const FloatV w = V4GetW(b);
+
+ const Vec4V v0 = V4Scale(a.col0, x);
+ const Vec4V v1 = V4Scale(a.col1, y);
+ const Vec4V v2 = V4Scale(a.col2, z);
+ const Vec4V v3 = V4Scale(a.col3, w);
+ const Vec4V v0PlusV1 = V4Add(v0, v1);
+ const Vec4V v0PlusV1Plusv2 = V4Add(v0PlusV1, v2);
+ return (V4Add(v0PlusV1Plusv2, v3));
+}
+
+QT3DS_FORCE_INLINE Vec4V M44TrnspsMulV4(const Mat44V &a, const Vec4V b)
+{
+ QT3DS_ALIGN(16, FloatV dotProdArray[4]) = { V4Dot(a.col0, b), V4Dot(a.col1, b), V4Dot(a.col2, b),
+ V4Dot(a.col3, b) };
+ return V4Merge(dotProdArray);
+}
+
+QT3DS_FORCE_INLINE Mat44V M44MulM44(const Mat44V &a, const Mat44V &b)
+{
+ return Mat44V(M44MulV4(a, b.col0), M44MulV4(a, b.col1), M44MulV4(a, b.col2),
+ M44MulV4(a, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat44V M44Add(const Mat44V &a, const Mat44V &b)
+{
+ return Mat44V(V4Add(a.col0, b.col0), V4Add(a.col1, b.col1), V4Add(a.col2, b.col2),
+ V4Add(a.col3, b.col3));
+}
+
+QT3DS_FORCE_INLINE Mat44V M44Trnsps(const Mat44V &a)
+{
+ const Vec4V v0 = _mm_unpacklo_ps(a.col0, a.col2);
+ const Vec4V v1 = _mm_unpackhi_ps(a.col0, a.col2);
+ const Vec4V v2 = _mm_unpacklo_ps(a.col1, a.col3);
+ const Vec4V v3 = _mm_unpackhi_ps(a.col1, a.col3);
+ return Mat44V(_mm_unpacklo_ps(v0, v2), _mm_unpackhi_ps(v0, v2), _mm_unpacklo_ps(v1, v3),
+ _mm_unpackhi_ps(v1, v3));
+}
+
+// The original code as provided by Intel in
+// "Streaming SIMD Extensions - Inverse of 4x4 Matrix"
+// (ftp://download.intel.com/design/pentiumiii/sml/24504301.pdf)
+QT3DS_FORCE_INLINE Mat44V M44Inverse(const Mat44V &a)
+{
+ __m128 minor0, minor1, minor2, minor3;
+ __m128 row0, row1, row2, row3;
+ __m128 det, tmp1;
+
+ tmp1 = V4Zero();
+ row1 = V4Zero();
+ row3 = V4Zero();
+
+ row0 = a.col0;
+ row1 = _mm_shuffle_ps(a.col1, a.col1, _MM_SHUFFLE(1, 0, 3, 2));
+ row2 = a.col2;
+ row3 = _mm_shuffle_ps(a.col3, a.col3, _MM_SHUFFLE(1, 0, 3, 2));
+
+ tmp1 = _mm_mul_ps(row2, row3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor0 = _mm_mul_ps(row1, tmp1);
+ minor1 = _mm_mul_ps(row0, tmp1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor0 = _mm_sub_ps(_mm_mul_ps(row1, tmp1), minor0);
+ minor1 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor1);
+ minor1 = _mm_shuffle_ps(minor1, minor1, 0x4E);
+
+ tmp1 = _mm_mul_ps(row1, row2);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor0 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor0);
+ minor3 = _mm_mul_ps(row0, tmp1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row3, tmp1));
+ minor3 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor3);
+ minor3 = _mm_shuffle_ps(minor3, minor3, 0x4E);
+
+ tmp1 = _mm_mul_ps(_mm_shuffle_ps(row1, row1, 0x4E), row3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ row2 = _mm_shuffle_ps(row2, row2, 0x4E);
+ minor0 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor0);
+ minor2 = _mm_mul_ps(row0, tmp1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row2, tmp1));
+ minor2 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor2);
+ minor2 = _mm_shuffle_ps(minor2, minor2, 0x4E);
+
+ tmp1 = _mm_mul_ps(row0, row1);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor2 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor2);
+ minor3 = _mm_sub_ps(_mm_mul_ps(row2, tmp1), minor3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor2 = _mm_sub_ps(_mm_mul_ps(row3, tmp1), minor2);
+ minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row2, tmp1));
+
+ tmp1 = _mm_mul_ps(row0, row3);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row2, tmp1));
+ minor2 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor2);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor1 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor1);
+ minor2 = _mm_sub_ps(minor2, _mm_mul_ps(row1, tmp1));
+
+ tmp1 = _mm_mul_ps(row0, row2);
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
+ minor1 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor1);
+ minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row1, tmp1));
+ tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
+ minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row3, tmp1));
+ minor3 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor3);
+
+ det = _mm_mul_ps(row0, minor0);
+ det = _mm_add_ps(_mm_shuffle_ps(det, det, 0x4E), det);
+ det = _mm_add_ss(_mm_shuffle_ps(det, det, 0xB1), det);
+ tmp1 = _mm_rcp_ss(det);
+#if 0
+ det = _mm_sub_ss(_mm_add_ss(tmp1, tmp1), _mm_mul_ss(det, _mm_mul_ss(tmp1, tmp1)));
+ det = _mm_shuffle_ps(det, det, 0x00);
+#else
+ det = _mm_shuffle_ps(tmp1, tmp1, _MM_SHUFFLE(0, 0, 0, 0));
+#endif
+
+ minor0 = _mm_mul_ps(det, minor0);
+ minor1 = _mm_mul_ps(det, minor1);
+ minor2 = _mm_mul_ps(det, minor2);
+ minor3 = _mm_mul_ps(det, minor3);
+ Mat44V invTrans(minor0, minor1, minor2, minor3);
+ return M44Trnsps(invTrans);
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_XYZW(QT3DSF32 x, QT3DSF32 y, QT3DSF32 z, QT3DSF32 w)
+{
+ return _mm_set_ps(w, z, y, x);
+}
+
+// AP: work in progress - use proper SSE intrinsics where possible
+QT3DS_FORCE_INLINE VecU16V V4U32PK(VecU32V a, VecU32V b)
+{
+ VecU16V result;
+ result.m128_u16[0] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[0], 0, 0xFFFF));
+ result.m128_u16[1] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[1], 0, 0xFFFF));
+ result.m128_u16[2] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[2], 0, 0xFFFF));
+ result.m128_u16[3] = QT3DSU16(NVClamp<QT3DSU32>((a).m128_u32[3], 0, 0xFFFF));
+ result.m128_u16[4] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[0], 0, 0xFFFF));
+ result.m128_u16[5] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[1], 0, 0xFFFF));
+ result.m128_u16[6] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[2], 0, 0xFFFF));
+ result.m128_u16[7] = QT3DSU16(NVClamp<QT3DSU32>((b).m128_u32[3], 0, 0xFFFF));
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U32or(VecU32V a, VecU32V b)
+{
+ return m128_I2F(_mm_or_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U32and(VecU32V a, VecU32V b)
+{
+ return m128_I2F(_mm_and_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U32Andc(VecU32V a, VecU32V b)
+{
+ return m128_I2F(_mm_andnot_si128(m128_F2I(b), m128_F2I(a)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16Or(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_or_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16And(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_and_si128(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16Andc(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_andnot_si128(m128_F2I(b), m128_F2I(a)));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_From_I32(const QT3DSI32 i)
+{
+ return (_mm_load1_ps((QT3DSF32 *)&i));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_From_I32Array(const QT3DSI32 *i)
+{
+ return _mm_loadu_ps((QT3DSF32 *)i);
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_From_I32Array_Aligned(const QT3DSI32 *i)
+{
+ return _mm_load_ps((QT3DSF32 *)i);
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Add(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_add_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Sub(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_sub_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE BoolV VecI32V_IsGrtr(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_cmpgt_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE BoolV VecI32V_IsEq(const VecI32VArg a, const VecI32VArg b)
+{
+ return m128_I2F(_mm_cmpeq_epi32(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Zero()
+{
+ return V4Zero();
+}
+
+QT3DS_FORCE_INLINE VecI32V VecI32V_Merge(const VecI32VArg a, const VecI32VArg b, const VecI32VArg c,
+ const VecI32VArg d)
+{
+ return V4Merge(a, b, c, d);
+}
+
+template <int a>
+QT3DS_FORCE_INLINE VecI32V V4ISplat()
+{
+ VecI32V result;
+ result.m128_i32[0] = a;
+ result.m128_i32[1] = a;
+ result.m128_i32[2] = a;
+ result.m128_i32[3] = a;
+ return result;
+}
+
+QT3DS_FORCE_INLINE void V4U16StoreAligned(VecU16V val, VecU16V *address)
+{
+ *address = val;
+}
+
+QT3DS_FORCE_INLINE void V4U32StoreAligned(VecU32V val, VecU32V *address)
+{
+ *address = val;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4LoadAligned(Vec4V *addr)
+{
+ return *addr;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4LoadUnaligned(Vec4V *addr)
+{
+ return Vec4V_From_F32Array((float *)addr);
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Andc(const Vec4V a, const VecU32V b)
+{
+ VecU32V result32(a);
+ result32 = V4U32Andc(result32, b);
+ return Vec4V(result32);
+}
+
+QT3DS_FORCE_INLINE VecU32V V4IsGrtrV32u(const Vec4V a, const Vec4V b)
+{
+ return V4IsGrtr(a, b);
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16LoadAligned(VecU16V *addr)
+{
+ return *addr;
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16LoadUnaligned(VecU16V *addr)
+{
+ return *addr;
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16CompareGt(VecU16V a, VecU16V b)
+{
+ // _mm_cmpgt_epi16 doesn't work for unsigned values unfortunately
+ // return m128_I2F(_mm_cmpgt_epi16(m128_F2I(a), m128_F2I(b)));
+ VecU16V result;
+ result.m128_u16[0] = (a).m128_u16[0] > (b).m128_u16[0];
+ result.m128_u16[1] = (a).m128_u16[1] > (b).m128_u16[1];
+ result.m128_u16[2] = (a).m128_u16[2] > (b).m128_u16[2];
+ result.m128_u16[3] = (a).m128_u16[3] > (b).m128_u16[3];
+ result.m128_u16[4] = (a).m128_u16[4] > (b).m128_u16[4];
+ result.m128_u16[5] = (a).m128_u16[5] > (b).m128_u16[5];
+ result.m128_u16[6] = (a).m128_u16[6] > (b).m128_u16[6];
+ result.m128_u16[7] = (a).m128_u16[7] > (b).m128_u16[7];
+ return result;
+}
+
+QT3DS_FORCE_INLINE Vec4V Vec4V_From_VecU32V(VecU32V a)
+{
+ Vec4V result = Vec4V_From_XYZW(QT3DSF32(a.m128_u32[0]), QT3DSF32(a.m128_u32[1]), QT3DSF32(a.m128_u32[2]),
+ QT3DSF32(a.m128_u32[3]));
+ return result;
+}
+
+template <int index>
+QT3DS_FORCE_INLINE VecU32V V4U32SplatElement(VecU32V a)
+{
+ VecU32V result;
+ result.m128_u32[0] = result.m128_u32[1] = result.m128_u32[2] = result.m128_u32[3] =
+ a.m128_u32[index];
+ return result;
+}
+
+template <int index>
+QT3DS_FORCE_INLINE Vec4V V4SplatElement(Vec4V a)
+{
+ float *data = (float *)&a;
+ return Vec4V_From_F32(data[index]);
+}
+
+template <int index>
+QT3DS_FORCE_INLINE VecU16V V4U16SplatElement(VecU16V a)
+{
+ VecU16V result = a; // AM: initializing to avoid nonsensical warning 4701 here with VC10.
+ for (int i = 0; i < 8; i++)
+ result.m128_u16[i] = a.m128_u16[index];
+ return result;
+}
+
+template <int imm>
+QT3DS_FORCE_INLINE VecI16V V4I16SplatImmediate()
+{
+ VecI16V result;
+ result.m128_i16[0] = imm;
+ result.m128_i16[1] = imm;
+ result.m128_i16[2] = imm;
+ result.m128_i16[3] = imm;
+ result.m128_i16[4] = imm;
+ result.m128_i16[5] = imm;
+ result.m128_i16[6] = imm;
+ result.m128_i16[7] = imm;
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16SubtractModulo(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_sub_epi16(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU16V V4U16AddModulo(VecU16V a, VecU16V b)
+{
+ return m128_I2F(_mm_add_epi16(m128_F2I(a), m128_F2I(b)));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U16GetLo16(VecU16V a)
+{
+ VecU32V result;
+ result.m128_u32[0] = a.m128_u16[0];
+ result.m128_u32[1] = a.m128_u16[2];
+ result.m128_u32[2] = a.m128_u16[4];
+ result.m128_u32[3] = a.m128_u16[6];
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU32V V4U16GetHi16(VecU16V a)
+{
+ VecU32V result;
+ result.m128_u32[0] = a.m128_u16[1];
+ result.m128_u32[1] = a.m128_u16[3];
+ result.m128_u32[2] = a.m128_u16[5];
+ result.m128_u32[3] = a.m128_u16[7];
+ return result;
+}
+
+QT3DS_FORCE_INLINE VecU32V VecU32V_From_XYZW(QT3DSU32 x, QT3DSU32 y, QT3DSU32 z, QT3DSU32 w)
+{
+ VecU32V result;
+ result.m128_u32[0] = x;
+ result.m128_u32[1] = y;
+ result.m128_u32[2] = z;
+ result.m128_u32[3] = w;
+ return result;
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Ceil(const Vec4V a)
+{
+ return Vec4V_From_XYZW(NVCeil(a.m128_f32[0]), NVCeil(a.m128_f32[1]), NVCeil(a.m128_f32[2]),
+ NVCeil(a.m128_f32[3]));
+}
+
+QT3DS_FORCE_INLINE Vec4V V4Floor(const Vec4V a)
+{
+ return Vec4V_From_XYZW(NVFloor(a.m128_f32[0]), NVFloor(a.m128_f32[1]), NVFloor(a.m128_f32[2]),
+ NVFloor(a.m128_f32[3]));
+}
+
+QT3DS_FORCE_INLINE VecU32V V4ConvertToU32VSaturate(const Vec4V a, QT3DSU32 power)
+{
+ QT3DS_ASSERT(power == 0 && "Non-zero power not supported in convertToU32VSaturate");
+ QT3DS_FORCE_PARAMETER_REFERENCE(power); // prevent warning in release builds
+ QT3DSF32 ffffFFFFasFloat = QT3DSF32(0xFFFF0000);
+ VecU32V result;
+ result.m128_u32[0] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[0], 0.0f, ffffFFFFasFloat));
+ result.m128_u32[1] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[1], 0.0f, ffffFFFFasFloat));
+ result.m128_u32[2] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[2], 0.0f, ffffFFFFasFloat));
+ result.m128_u32[3] = QT3DSU32(NVClamp<QT3DSF32>((a).m128_f32[3], 0.0f, ffffFFFFasFloat));
+ return result;
+}
+
+#endif // QT3DS_WINDOWS_INLINE_AOS_H
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsIntrinsics.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsIntrinsics.h
new file mode 100644
index 00000000..d124c6af
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsIntrinsics.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_WINDOWS_INTRINSICS_H
+#define QT3DS_FOUNDATION_QT3DS_WINDOWS_INTRINSICS_H
+
+#include "foundation/Qt3DS.h"
+
+#if !defined QT3DS_WINDOWS && !defined QT3DS_WIN8ARM
+#error "This file should only be included by Windows builds!!"
+#endif
+
+#include <math.h>
+#include <float.h>
+#include <intrin.h>
+#include <string.h>
+#include "foundation/Qt3DSAssert.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+namespace intrinsics {
+#endif
+
+ //! \brief platform-specific absolute value
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float abs(float a) { return float(::fabs(a)); }
+
+ //! \brief platform-specific select float
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float fsel(float a, float b, float c)
+ {
+ return (a >= 0.0f) ? b : c;
+ }
+
+ //! \brief platform-specific sign
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float sign(float a) { return (a >= 0.0f) ? 1.0f : -1.0f; }
+
+ //! \brief platform-specific reciprocal
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recip(float a) { return 1.0f / a; }
+
+ //! \brief platform-specific square root
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float sqrt(float a) { return ::sqrtf(a); }
+
+ //! \brief platform-specific reciprocal square root
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recipSqrt(float a) { return 1.0f / ::sqrtf(a); }
+
+ //! \brief platform-specific sine
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float sin(float a) { return ::sinf(a); }
+
+ //! \brief platform-specific cosine
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float cos(float a) { return ::cosf(a); }
+
+ //! \brief platform-specific minimum
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float selectMin(float a, float b) { return a < b ? a : b; }
+
+ //! \brief platform-specific maximum
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float selectMax(float a, float b) { return a > b ? a : b; }
+
+ //! \brief platform-specific finiteness check (not INF or NAN)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite(float a)
+ {
+#ifdef __CUDACC__
+ return isfinite(a) ? true : false;
+#else
+ return (0 == ((_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF) & _fpclass(a)));
+#endif
+ }
+
+ //! \brief platform-specific finiteness check (not INF or NAN)
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite(double a)
+ {
+#ifdef __CUDACC__
+ return isfinite(a) ? true : false;
+#else
+ return (0 == ((_FPCLASS_SNAN | _FPCLASS_QNAN | _FPCLASS_NINF | _FPCLASS_PINF) & _fpclass(a)));
+#endif
+ }
+ /*
+* Implements a memory barrier
+*/
+ QT3DS_FORCE_INLINE void memoryBarrier()
+ {
+ _ReadWriteBarrier();
+ /* long Barrier;
+ __asm {
+ xchg Barrier, eax
+ }*/
+ }
+
+ /*!
+ Returns the index of the highest set bit. Not valid for zero arg.
+ */
+ QT3DS_FORCE_INLINE QT3DSU32 highestSetBitUnsafe(QT3DSU32 v)
+ {
+ unsigned long retval;
+ _BitScanReverse(&retval, v);
+ return retval;
+ }
+
+ /*!
+ Returns the index of the highest set bit. Undefined for zero arg.
+ */
+ QT3DS_FORCE_INLINE QT3DSU32 lowestSetBitUnsafe(QT3DSU32 v)
+ {
+ unsigned long retval;
+ _BitScanForward(&retval, v);
+ return retval;
+ }
+
+ /*!
+ Returns the number of leading zeros in v. Returns 32 for v=0.
+ */
+ QT3DS_FORCE_INLINE QT3DSU32 countLeadingZeros(QT3DSU32 v)
+ {
+ if (v) {
+ unsigned long bsr = (unsigned long)-1;
+ _BitScanReverse(&bsr, v);
+ return 31 - bsr;
+ } else
+ return 32;
+ }
+
+ /*!
+ Sets \c count bytes starting at \c dst to zero.
+ */
+ QT3DS_FORCE_INLINE void *memZero(void *QT3DS_RESTRICT dest, QT3DSU32 count)
+ {
+ return memset(dest, 0, count);
+ }
+
+ /*!
+ Sets \c count bytes starting at \c dst to \c c.
+ */
+ QT3DS_FORCE_INLINE void *memSet(void *QT3DS_RESTRICT dest, QT3DSI32 c, QT3DSU32 count)
+ {
+ return memset(dest, c, count);
+ }
+
+ /*!
+ Copies \c count bytes from \c src to \c dst. User memMove if regions overlap.
+ */
+ QT3DS_FORCE_INLINE void *memCopy(void *QT3DS_RESTRICT dest, const void *QT3DS_RESTRICT src, QT3DSU32 count)
+ {
+ return memcpy(dest, src, count);
+ }
+
+ /*!
+ Copies \c count bytes from \c src to \c dst. Supports overlapping regions.
+ */
+ QT3DS_FORCE_INLINE void *memMove(void *QT3DS_RESTRICT dest, const void *QT3DS_RESTRICT src, QT3DSU32 count)
+ {
+ return memmove(dest, src, count);
+ }
+
+ /*!
+ Set 128B to zero starting at \c dst+offset. Must be aligned.
+ */
+ QT3DS_FORCE_INLINE void memZero128(void *QT3DS_RESTRICT dest, QT3DSU32 offset = 0)
+ {
+ QT3DS_ASSERT(((size_t(dest) + offset) & 0x7f) == 0);
+ memSet((char *QT3DS_RESTRICT)dest + offset, 0, 128);
+ }
+
+ /*!
+ Prefetch aligned 128B around \c ptr+offset.
+ */
+ QT3DS_FORCE_INLINE void prefetch128(const void *ptr, QT3DSU32 offset = 0)
+ {
+#ifdef QT3DS_WINDOWS
+ _mm_prefetch(((const char *)ptr + offset), _MM_HINT_T0);
+#endif
+ }
+
+ /*!
+ Prefetch \c count bytes starting at \c ptr.
+ */
+ QT3DS_FORCE_INLINE void prefetch(const void *ptr, QT3DSU32 count = 0)
+ {
+ for (QT3DSU32 i = 0; i <= count; i += 128)
+ prefetch128(ptr, i);
+ }
+
+ //! \brief platform-specific reciprocal
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recipFast(float a) { return 1.0f / a; }
+
+ //! \brief platform-specific fast reciprocal square root
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float recipSqrtFast(float a) { return 1.0f / ::sqrtf(a); }
+
+ //! \brief platform-specific floor
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float floatFloor(float x) { return ::floorf(x); }
+
+#ifndef QT3DS_DOXYGEN
+} // namespace intrinsics
+} // namespace qt3ds
+#endif
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsString.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsString.h
new file mode 100644
index 00000000..8d5fcd31
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsString.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_WINDOWS_STRING_H
+#define QT3DS_FOUNDATION_QT3DS_WINDOWS_STRING_H
+
+#include "foundation/Qt3DS.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#pragma warning(push)
+#pragma warning(disable : 4995 4996)
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+QT3DS_INLINE void NVStrcpy(char *dest, size_t size, const char *src)
+{
+ ::strcpy_s(dest, size, src);
+}
+QT3DS_INLINE void NVStrcat(char *dest, size_t size, const char *src)
+{
+ ::strcat_s(dest, size, src);
+}
+QT3DS_INLINE QT3DSI32 NVVsprintf(char *dest, size_t size, const char *src, va_list arg)
+{
+ QT3DSI32 r = ::vsprintf_s(dest, size, src, arg);
+
+ return r;
+}
+QT3DS_INLINE QT3DSI32 NVStricmp(const char *str, const char *str1)
+{
+ return (::_stricmp(str, str1));
+}
+
+namespace string {
+ QT3DS_INLINE QT3DSI32 stricmp(const char *str, const char *str1) { return (::_stricmp(str, str1)); }
+ QT3DS_INLINE QT3DSI32 strnicmp(const char *str, const char *str1, size_t len)
+ {
+ return (::_strnicmp(str, str1, len));
+ }
+ QT3DS_INLINE QT3DSI32 strncat_s(char *a, QT3DSI32 b, const char *c, size_t d)
+ {
+ return (::strncat_s(a, b, c, d));
+ }
+ QT3DS_INLINE QT3DSI32 strncpy_s(char *strDest, size_t sizeInBytes, const char *strSource,
+ size_t count)
+ {
+ return (::strncpy_s(strDest, sizeInBytes, strSource, count));
+ }
+ QT3DS_INLINE void strcpy_s(char *dest, size_t size, const char *src)
+ {
+ ::strcpy_s(dest, size, src);
+ }
+ QT3DS_INLINE void strcat_s(char *dest, size_t size, const char *src)
+ {
+ ::strcat_s(dest, size, src);
+ }
+ QT3DS_INLINE QT3DSI32 _vsnprintf(char *dest, size_t size, const char *src, va_list arg)
+ {
+ QT3DSI32 r = ::_vsnprintf(dest, size, src, arg);
+
+ return r;
+ }
+ QT3DS_INLINE QT3DSI32 vsprintf_s(char *dest, size_t size, const char *src, va_list arg)
+ {
+ QT3DSI32 r = ::vsprintf_s(dest, size, src, arg);
+
+ return r;
+ }
+
+ QT3DS_INLINE QT3DSI32 sprintf_s(char *_DstBuf, size_t _DstSize, const char *_Format, ...)
+ {
+ va_list arg;
+ va_start(arg, _Format);
+ QT3DSI32 r = ::vsprintf_s(_DstBuf, _DstSize, _Format, arg);
+ va_end(arg);
+
+ return r;
+ }
+ QT3DS_INLINE QT3DSI32 sscanf_s(const char *buffer, const char *format, ...)
+ {
+ va_list arg;
+ va_start(arg, format);
+ QT3DSI32 r = ::sscanf_s(buffer, format, arg);
+ va_end(arg);
+
+ return r;
+ };
+
+ QT3DS_INLINE void strlwr(char *str)
+ {
+ while (*str) {
+ if (*str >= 'A' && *str <= 'Z')
+ *str += 32;
+ str++;
+ }
+ }
+
+ QT3DS_INLINE void strupr(char *str)
+ {
+ while (*str) {
+ if (*str >= 'a' && *str <= 'z')
+ *str -= 32;
+ str++;
+ }
+ }
+
+} // namespace string
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+#pragma warning(pop)
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsTrigConstants.h b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsTrigConstants.h
new file mode 100644
index 00000000..e3da844c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/Qt3DSWindowsTrigConstants.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_WINDOWS_TRIG_CONSTANTS_H
+#define QT3DS_WINDOWS_TRIG_CONSTANTS_H
+
+#define QT3DS_GLOBALCONST extern const __declspec(selectany)
+
+__declspec(align(16)) struct QT3DS_VECTORF32
+{
+ float f[4];
+};
+
+#define QT3DS_PI 3.141592654f
+#define QT3DS_2PI 6.283185307f
+#define QT3DS_1DIVPI 0.318309886f
+#define QT3DS_1DIV2PI 0.159154943f
+#define QT3DS_PIDIV2 1.570796327f
+#define QT3DS_PIDIV4 0.785398163f
+
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinCoefficients0 = { 1.0f, -0.166666667f, 8.333333333e-3f,
+ -1.984126984e-4f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinCoefficients1 = { 2.755731922e-6f, -2.505210839e-8f,
+ 1.605904384e-10f, -7.647163732e-13f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinCoefficients2 = { 2.811457254e-15f, -8.220635247e-18f,
+ 1.957294106e-20f, -3.868170171e-23f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosCoefficients0 = { 1.0f, -0.5f, 4.166666667e-2f,
+ -1.388888889e-3f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosCoefficients1 = { 2.480158730e-5f, -2.755731922e-7f,
+ 2.087675699e-9f, -1.147074560e-11f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosCoefficients2 = { 4.779477332e-14f, -1.561920697e-16f,
+ 4.110317623e-19f, -8.896791392e-22f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanCoefficients0 = { 1.0f, 0.333333333f, 0.133333333f,
+ 5.396825397e-2f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanCoefficients1 = { 2.186948854e-2f, 8.863235530e-3f,
+ 3.592128167e-3f, 1.455834485e-3f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanCoefficients2 = { 5.900274264e-4f, 2.391290764e-4f,
+ 9.691537707e-5f, 3.927832950e-5f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinCoefficients0 = { -0.05806367563904f, -0.41861972469416f,
+ 0.22480114791621f, 2.17337241360606f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinCoefficients1 = { 0.61657275907170f, 4.29696498283455f,
+ -1.18942822255452f, -6.53784832094831f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinCoefficients2 = { -1.36926553863413f, -4.48179294237210f,
+ 1.41810672941833f, 5.48179257935713f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanCoefficients0 = { 1.0f, 0.333333334f, 0.2f, 0.142857143f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanCoefficients1 = { 1.111111111e-1f, 9.090909091e-2f,
+ 7.692307692e-2f, 6.666666667e-2f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanCoefficients2 = { 5.882352941e-2f, 5.263157895e-2f,
+ 4.761904762e-2f, 4.347826087e-2f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXSinEstCoefficients = { 1.0f, -1.66521856991541e-1f,
+ 8.199913018755e-3f, -1.61475937228e-4f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXCosEstCoefficients = { 1.0f, -4.95348008918096e-1f,
+ 3.878259962881e-2f, -9.24587976263e-4f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXTanEstCoefficients = { 2.484f, -1.954923183e-1f, 2.467401101f,
+ QT3DS_1DIVPI };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXATanEstCoefficients = { 7.689891418951e-1f, 1.104742493348f,
+ 8.661844266006e-1f, QT3DS_PIDIV2 };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinEstCoefficients = { -1.36178272886711f, 2.37949493464538f,
+ -8.08228565650486e-1f,
+ 2.78440142746736e-1f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXASinEstConstants = { 1.00000011921f, QT3DS_PIDIV2, 0.0f, 0.0f };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXPiConstants0 = { QT3DS_PI, QT3DS_2PI, QT3DS_1DIVPI, QT3DS_1DIV2PI };
+QT3DS_GLOBALCONST QT3DS_VECTORF32 g_PXReciprocalTwoPi = { QT3DS_1DIV2PI, QT3DS_1DIV2PI, QT3DS_1DIV2PI,
+ QT3DS_1DIV2PI };
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/qt_attribution.json b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/qt_attribution.json
new file mode 100644
index 00000000..e0310cfa
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Include/foundation/windows/qt_attribution.json
@@ -0,0 +1,10 @@
+{
+ "Id": "qt3dswindowsaos",
+ "Name": "Qt3DSWindowsAoS",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio, Runtime component.",
+
+ "License": "Other",
+ "LicenseFile": "LICENSE.TXT",
+ "Copyright": "Copyright (c) 2001 Intel Corporation."
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/ConvertUTF.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/ConvertUTF.cpp
new file mode 100644
index 00000000..14017948
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/ConvertUTF.cpp
@@ -0,0 +1,657 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+* Copyright 2001-2004 Unicode, Inc.
+*
+* Disclaimer
+*
+* This source code is provided as is by Unicode, Inc. No claims are
+* made as to fitness for any particular purpose. No warranties of any
+* kind are expressed or implied. The recipient agrees to determine
+* applicability of information provided. If this file has been
+* purchased on magnetic or optical media from Unicode, Inc., the
+* sole remedy for any claim will be exchange of defective media
+* within 90 days of receipt.
+*
+* Limitations on Rights to Redistribute This Code
+*
+* Unicode, Inc. hereby grants the right to freely use the information
+* supplied in this file in the creation of products supporting the
+* Unicode Standard, and to make copies of this file in any form
+* for internal or external distribution as long as this notice
+* remains attached.
+*/
+
+/* ---------------------------------------------------------------------
+ Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Sept 2001: fixed const & error conditions per
+ mods suggested by S. Parent & A. Lillich.
+ June 2002: Tim Dodd added detection and handling of incomplete
+ source sequences, enhanced error detection, added casts
+ to eliminate compiler warnings.
+ July 2003: slight mods to back out aggressive FFFE detection.
+ Jan 2004: updated switches in from-UTF8 conversions.
+ Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+ See the header file "ConvertUTF.h" for complete documentation.
+------------------------------------------------------------------------ */
+
+#include "foundation/ConvertUTF.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4365) // warnings on conversion from unsigned int to int
+#endif
+
+#ifdef CVTUTF_DEBUG
+#include <stdio.h>
+#endif
+
+static const int halfShift = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+#define false 0
+#define true 1
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16(const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF32 *source = *sourceStart;
+ UTF16 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved
+ * values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_LEGAL_UTF32) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ --source; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF32(const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF16 *source = *sourceStart;
+ UTF32 *target = *targetStart;
+ UTF32 ch, ch2;
+ while (source < sourceEnd) {
+ const UTF16 *oldSource =
+ source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START)
+ + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ *target++ = ch;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+#ifdef CVTUTF_DEBUG
+ if (result == sourceIllegal) {
+ fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
+ fflush(stderr);
+ }
+#endif
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
+};
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
+ */
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "isLegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF8(const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF16 *source = *sourceStart;
+ UTF8 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16 *oldSource =
+ source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START)
+ + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) {
+ bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) {
+ bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) {
+ bytesToWrite = 3;
+ } else if (ch < (UTF32)0x110000) {
+ bytesToWrite = 4;
+ } else {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns false. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static Boolean isLegalUTF8(const UTF8 *source, int length)
+{
+ UTF8 a;
+ const UTF8 *srcptr = source + length;
+ switch (length) {
+ default:
+ return false;
+ /* Everything else falls through when "true"... */
+ case 4:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
+ return false;
+ case 3:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
+ return false;
+ case 2:
+ if ((a = (*--srcptr)) > 0xBF)
+ return false;
+
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0:
+ if (a < 0xA0)
+ return false;
+ break;
+ case 0xED:
+ if (a > 0x9F)
+ return false;
+ break;
+ case 0xF0:
+ if (a < 0x90)
+ return false;
+ break;
+ case 0xF4:
+ if (a > 0x8F)
+ return false;
+ break;
+ default:
+ if (a < 0x80)
+ return false;
+ }
+
+ case 1:
+ if (*source >= 0x80 && *source < 0xC2)
+ return false;
+ }
+ if (*source > 0xF4)
+ return false;
+ return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd)
+{
+ int length = trailingBytesForUTF8[*source] + 1;
+ if (source + length > sourceEnd) {
+ return false;
+ }
+ return isLegalUTF8(source, length);
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16(const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF8 *source = *sourceStart;
+ UTF16 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5:
+ ch += *source++;
+ ch <<= 6; /* remember, illegal UTF-8 */
+ case 4:
+ ch += *source++;
+ ch <<= 6; /* remember, illegal UTF-8 */
+ case 3:
+ ch += *source++;
+ ch <<= 6;
+ case 2:
+ ch += *source++;
+ ch <<= 6;
+ case 1:
+ ch += *source++;
+ ch <<= 6;
+ case 0:
+ ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead + 1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead + 1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF32 *source = *sourceStart;
+ UTF8 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (UTF32)0x80) {
+ bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) {
+ bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) {
+ bytesToWrite = 3;
+ } else if (ch <= UNI_MAX_LEGAL_UTF32) {
+ bytesToWrite = 4;
+ } else {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
+{
+ ConversionResult result = conversionOK;
+ const UTF8 *source = *sourceStart;
+ UTF32 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5:
+ ch += *source++;
+ ch <<= 6;
+ case 4:
+ ch += *source++;
+ ch <<= 6;
+ case 3:
+ ch += *source++;
+ ch <<= 6;
+ case 2:
+ ch += *source++;
+ ch <<= 6;
+ case 1:
+ ch += *source++;
+ ch <<= 6;
+ case 0:
+ ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up the source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead + 1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = ch;
+ }
+ } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+ Note A.
+ The fall-through switches in UTF-8 reading code save a
+ temp variable, some decrements & conditionals. The switches
+ are equivalent to the following loop:
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
+ In UTF-8 writing code, the switches on "bytesToWrite" are
+ similarly unrolled loops.
+
+ --------------------------------------------------------------------- */
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/EASTL_new.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/EASTL_new.cpp
new file mode 100644
index 00000000..a65e9256
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/EASTL_new.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// we have some build dependencies which forces us to include
+// this on linux to recognize malloc
+#include <stdio.h>
+#include <stdarg.h>
+#if defined(_LINUX) || (_MACOSX) || (__ANDROID__)
+#include <stdlib.h>
+#endif
+
+#ifdef _MSC_VER
+#endif
+#include "EASTL/allocator.h"
+
+void *operator new[](size_t size, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+
+void *operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+// EASTL also wants us to define this (see string.h line 197)
+int Vsnprintf8(char8_t *pDestination, size_t n, const char8_t *pFormat, va_list arguments)
+{
+#ifdef _MSC_VER
+ return _vsnprintf(pDestination, n, pFormat, arguments);
+#else
+ return vsnprintf(pDestination, n, pFormat, arguments);
+#endif
+}
+int Vsnprintf16(char8_t *pDestination, size_t n, const char16_t *pFormat, va_list arguments)
+{
+#ifdef _MSC_VER
+ return _vsnprintf(pDestination, n, (char *)pFormat, arguments);
+#else
+ return vsnprintf(pDestination, n, (char *)pFormat, arguments);
+#endif
+}
+int Vsnprintf32(char8_t *pDestination, size_t n, const char32_t *pFormat, va_list arguments)
+{
+#ifdef _MSC_VER
+ return _vsnprintf(pDestination, n, (char *)pFormat, arguments);
+#else
+ return vsnprintf(pDestination, n, (char *)pFormat, arguments);
+#endif
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/FileTools.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/FileTools.cpp
new file mode 100644
index 00000000..cceaef03
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/FileTools.cpp
@@ -0,0 +1,553 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/FileTools.h"
+#include "foundation/Utils.h"
+#include <string.h>
+#
+#ifdef EA_PLATFORM_WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else // posix
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#endif
+#include <QDir>
+#include <QFile>
+#include <QUrl>
+
+using namespace qt3ds::foundation;
+
+namespace {
+// State machine where you can add a character
+// and it will tell you how many characters to erase
+struct SPathStateMachine
+{
+ struct States
+ {
+ enum Enum {
+ NoState = 0, // Don't care
+ Slash, // Last char was either a forward or backward slash
+ Period, // Last char was a period
+ TwoPeriods, // Last two characters were periods
+ };
+ };
+ struct Actions
+ {
+ enum Enum {
+ NoAction = 0,
+ DeleteBack1Slash,
+ DeleteBack2Slashes,
+ };
+ };
+
+ States::Enum m_State;
+
+ SPathStateMachine()
+ : m_State(States::NoState)
+ {
+ }
+
+ Actions::Enum AnalyzeChar(char32_t inChar)
+ {
+ switch (inChar) {
+ case '\\':
+ case '/':
+ switch (m_State) {
+ case States::NoState:
+ m_State = States::Slash;
+ break;
+ case States::Period:
+ m_State = States::Slash;
+ return Actions::DeleteBack1Slash;
+
+ case States::TwoPeriods:
+ m_State = States::Slash;
+ return Actions::DeleteBack2Slashes;
+ case States::Slash:
+ return Actions::DeleteBack1Slash;
+ }
+ break;
+ case '.':
+ switch (m_State) {
+ case States::Slash:
+ case States::NoState:
+ m_State = States::Period;
+ break;
+ case States::Period:
+ m_State = States::TwoPeriods;
+ break;
+ case States::TwoPeriods:
+ break;
+ }
+ break;
+ default:
+ m_State = States::NoState;
+ break;
+ }
+ return Actions::NoAction;
+ }
+};
+
+template <typename TStrType>
+inline bool DoDeleteBack1Slash(TStr::size_type &idx, TStrType &ioPath)
+{
+ TStr::size_type slashLoc = ioPath.rfind('/', idx - 1);
+ if ((slashLoc != TStr::npos) && (slashLoc > 2)
+ // and the next *two* characters aren't both dots.
+ && ((ioPath[slashLoc - 1] != '.') || (ioPath[slashLoc - 2] != '.'))) {
+
+ ioPath.erase(ioPath.begin() + slashLoc, ioPath.begin() + idx);
+ idx = slashLoc;
+ return true;
+ }
+ return false;
+}
+
+template <typename TStrType>
+void NormalizePathT(TStrType &ioPath)
+{
+ TStr::size_type pathLen = ioPath.size();
+ SPathStateMachine theStateMachine;
+ for (TStr::size_type idx = 0; idx < pathLen; ++idx) {
+ char8_t &currentChar = ioPath[idx];
+ if (currentChar == '\\')
+ currentChar = '/';
+ SPathStateMachine::Actions::Enum action = theStateMachine.AnalyzeChar(currentChar);
+ switch (action) {
+ case SPathStateMachine::Actions::DeleteBack2Slashes:
+ if (DoDeleteBack1Slash(idx, ioPath))
+ DoDeleteBack1Slash(idx, ioPath);
+ pathLen = ioPath.size();
+ break;
+
+ case SPathStateMachine::Actions::DeleteBack1Slash:
+ DoDeleteBack1Slash(idx, ioPath);
+ pathLen = ioPath.size();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+bool IsAbsolute(const char8_t *inPath, size_t inLen)
+{
+ if (inLen > 2 && inPath[1] == ':')
+ return true;
+ else if (inLen > 1 && (inPath[0] == '\\' || inPath[0] == '/'))
+ return true;
+ return false;
+}
+
+template <typename TStrType>
+void CombineBaseAndRelativeT(const char8_t *inBase, const char8_t *inRelative, TStrType &outString)
+{
+ if (IsAbsolute(inRelative, StrLen(inRelative))) {
+ outString.assign(nonNull(inRelative));
+ } else {
+ if (inRelative && *inRelative) {
+ if (inRelative[0] == '#')
+ outString.assign(inRelative);
+ else {
+ if (IsAbsolute(inRelative, strlen(inRelative))) {
+ outString.assign(inRelative);
+ } else {
+ outString = inBase ? inBase : "";
+ if (outString.size())
+ outString.append("/");
+ outString.append(inRelative ? inRelative : (const char8_t *)L"");
+ }
+ NormalizePathT(outString);
+ }
+ }
+ }
+}
+
+template <typename TStrType>
+void GetRelativeFromBaseT(TStrType &inBaseStr, TStrType &inRelativeStr, TStrType &outString)
+{
+ outString.clear();
+ NormalizePathT(inBaseStr);
+ NormalizePathT(inRelativeStr);
+ if (inBaseStr.size() == 0) {
+ outString.assign(inRelativeStr.c_str());
+ return;
+ }
+ if (inRelativeStr.size() == 0) {
+ outString.clear();
+ return;
+ }
+ // find longest common string
+ const char8_t *inBase = inBaseStr.c_str();
+ const char8_t *baseEnd = inBaseStr.c_str() + inBaseStr.size();
+ const char8_t *inRelative = inRelativeStr.c_str();
+ size_t relativeLen = inRelativeStr.size();
+ const char8_t *relativeEnd = inRelative + relativeLen;
+
+ for (; inRelative < relativeEnd && inBase < baseEnd && *inRelative == *inBase;
+ ++inRelative, ++inBase)
+ ;
+
+ // They had nothing in common.
+ if (inBase == inBaseStr.c_str()) {
+ outString.assign(inRelativeStr.c_str());
+ return;
+ }
+
+ if (inRelative && (*inRelative == '\\' || *inRelative == '/'))
+ ++inRelative;
+
+ const char *common = inBase;
+ if (common == NULL || *common == 0) {
+ outString.assign("./");
+ outString.append(inRelative);
+ NormalizePathT(outString);
+ return;
+ }
+ // Backtrack to the nearest slash.
+ while (*common && *common != '\\' && *common != '/')
+ --common;
+
+ bool foundNonSlash = false;
+ for (; common != baseEnd; ++common) {
+ if (*common != '\\' && *common != '/') {
+ if (foundNonSlash == false)
+ outString.append("..\\");
+ foundNonSlash = true;
+ } else
+ foundNonSlash = false;
+ }
+ if (inRelative < relativeEnd) {
+ if (outString.size() == 0)
+ outString.assign("./");
+ outString.append(inRelative);
+ }
+ NormalizePathT(outString);
+}
+}
+
+void CFileTools::NormalizePath(TStr &ioPath)
+{
+ NormalizePathT(ioPath);
+}
+
+void CFileTools::NormalizePath(eastl::string &ioPath)
+{
+ NormalizePathT(ioPath);
+}
+
+QString CFileTools::NormalizePathForQtUsage(const QString &path)
+{
+ // The path here can be a file path or a qrc URL string. In the future
+ // we should pass around QUrl throughout this code path.
+ QString filePath = path;
+
+ // Replace all occurrences of '\' with '/' as these windows directory
+ // separators can be hardcoded into the UIP files. Qt uses unix separator
+ // as universal sep. I'm not using QDir::fromNativeSeparators as this can
+ // be a noop on unix.
+ filePath.replace('\\', '/');
+
+ filePath = QDir::cleanPath(filePath);
+ QUrl fileUrl = QUrl(filePath);
+ if (fileUrl.scheme() == QStringLiteral("qrc"))
+ return filePath.mid(3);
+ else
+ return filePath;
+}
+
+void CFileTools::CombineBaseAndRelative(const char8_t *inBase, const char8_t *inRelative,
+ TStr &outString)
+{
+ CombineBaseAndRelativeT(inBase, inRelative, outString);
+}
+
+void CFileTools::CombineBaseAndRelative(const char8_t *inBase, const char8_t *inRelative,
+ eastl::string &outString)
+{
+ CombineBaseAndRelativeT(inBase, inRelative, outString);
+}
+
+void CFileTools::GetRelativeFromBase(TStr &inBaseStr, TStr &inRelativeStr, TStr &outString)
+{
+ GetRelativeFromBaseT(inBaseStr, inRelativeStr, outString);
+}
+
+void CFileTools::GetRelativeFromBase(eastl::string &inBaseStr, eastl::string &inRelativeStr,
+ eastl::string &outString)
+{
+ GetRelativeFromBaseT(inBaseStr, inRelativeStr, outString);
+}
+
+bool CFileTools::RequiresCombineBaseAndRelative(const char8_t *inPath)
+{
+ if (inPath && *inPath)
+ return inPath[0] == '.';
+ return false;
+}
+
+template <typename TStrType>
+void ToPlatformPathT(TStrType &outString)
+{
+#ifndef EA_PLATFORM_WINDOWS
+ for (TStr::size_type pos = outString.find('\\'); pos != TStr::npos;
+ pos = outString.find('\\', pos + 1))
+ outString.replace(outString.begin() + pos, outString.begin() + pos + 1, "/");
+#else
+ (void)outString;
+#endif
+}
+
+void CFileTools::ToPlatformPath(TStr &outString)
+{
+ ToPlatformPathT(outString);
+}
+
+void CFileTools::ToPlatformPath(eastl::string &outString)
+{
+ ToPlatformPathT(outString);
+}
+
+CRegisteredString CFileTools::RemapPathToBinaryFormat(TStr &inPath, TStr &inPresentationDir,
+ TStr &ioWorkspaceStr,
+ IStringTable &inStringTable)
+{
+ GetRelativeFromBase(inPresentationDir, inPath, ioWorkspaceStr);
+ CRegisteredString theNewStr = inStringTable.RegisterStr(ioWorkspaceStr.c_str());
+ theNewStr.Remap(inStringTable.GetRemapMap());
+ return theNewStr;
+}
+
+CRegisteredString CFileTools::RemapPathFromBinaryFormat(CRegisteredString inPath,
+ const char8_t *inPresDir,
+ TStr &ioWorkspaceStr,
+ const CStrTableOrDataRef &inRef,
+ IStringTable &inStringTable)
+{
+ inPath.Remap(inRef);
+ if (RequiresCombineBaseAndRelative(inPath.c_str())) {
+ CombineBaseAndRelative(inPresDir, inPath, ioWorkspaceStr);
+ return inStringTable.RegisterStr(ioWorkspaceStr.c_str());
+ }
+ return inPath;
+}
+
+void CFileTools::GetDirectory(eastl::string &ioPath)
+{
+ eastl::string::size_type theSlashPos = ioPath.find_last_of("\\/");
+ if (theSlashPos == eastl::string::npos) {
+ ioPath.clear();
+ return;
+ }
+ ioPath.resize(theSlashPos);
+}
+
+bool CFileTools::DirectoryExists(const char8_t *inPath)
+{
+#ifdef EA_PLATFORM_WINDOWS
+ DWORD theAtts = GetFileAttributesA(inPath);
+ return theAtts != INVALID_FILE_ATTRIBUTES && (theAtts & FILE_ATTRIBUTE_DIRECTORY);
+#else // Posix style check for directory
+ int status;
+ struct stat st_buf;
+ status = stat(inPath, &st_buf);
+ if (status == 0 && S_ISDIR(st_buf.st_mode))
+ return true;
+ return false;
+#endif
+}
+
+bool CFileTools::FileExists(const char8_t *inPath)
+{
+#ifdef EA_PLATFORM_WINDOWS
+ DWORD theAtts = GetFileAttributesA(inPath);
+ return theAtts != INVALID_FILE_ATTRIBUTES;
+#else // Posix style check for directory
+ int status;
+ struct stat st_buf;
+ status = stat(inPath, &st_buf);
+ if (status == 0)
+ return true;
+ return false;
+#endif
+}
+
+eastl::string CFileTools::GetFileOrAssetPath(const char8_t *inPath)
+{
+ QFile tmp(inPath);
+ if (tmp.exists())
+ return inPath;
+ return eastl::string("assets:/") + inPath;
+}
+
+void CFileTools::SetStreamPosition(QIODevice& device, qint64 inOffset,
+ qt3ds::foundation::SeekPosition::Enum inEnum)
+{
+ if (inEnum == qt3ds::foundation::SeekPosition::Begin)
+ device.seek(inOffset);
+ else if (inEnum == qt3ds::foundation::SeekPosition::Current)
+ device.seek(device.pos() + inOffset);
+ else if (inEnum == qt3ds::foundation::SeekPosition::End)
+ device.seek(device.size() + inOffset);
+}
+
+void CFileTools::GetExtension(const char8_t *inPath, eastl::string &outExt)
+{
+ outExt.assign(nonNull(inPath));
+ size_t dotPos = outExt.find_last_of('.');
+ if (dotPos != eastl::string::npos)
+ outExt.erase(outExt.begin(), outExt.begin() + dotPos + 1);
+}
+
+void CFileTools::Split(const char8_t *inPath, eastl::string &outDir, eastl::string &outFileStem,
+ eastl::string &outExtension)
+{
+ outDir.assign(nonNull(inPath));
+ NormalizePath(outDir);
+ outFileStem = outDir;
+ GetDirectory(outDir);
+ size_t lenDiff = outFileStem.size() - outDir.size();
+ if (lenDiff > 0) {
+ if (outDir.size())
+ outFileStem = outFileStem.substr(outDir.size() + 1);
+
+ eastl::string::size_type lastDot = outFileStem.find_last_of('.');
+ if (lastDot != eastl::string::npos) {
+ outExtension = outFileStem.substr(lastDot + 1);
+ outFileStem.resize(lastDot);
+ }
+ }
+}
+
+#ifdef EA_PLATFORM_WINDOWS
+void CFileTools::GetDirectoryEntries(const eastl::string &inPath,
+ eastl::vector<eastl::string> &outFiles)
+{
+ if (inPath.size() == 0)
+ return;
+ eastl::string tempPath(inPath);
+ NormalizePath(tempPath);
+ for (eastl::string::size_type pos = tempPath.find_first_of('/'); pos != eastl::string::npos;
+ pos = tempPath.find_first_of('/', pos + 1))
+ tempPath[pos] = '\\';
+ if (tempPath.back() != '\\')
+ tempPath.append("\\");
+ tempPath.append(1, '*');
+ WIN32_FIND_DATAA ffd;
+ HANDLE hFind = FindFirstFileA(tempPath.c_str(), &ffd);
+ outFiles.clear();
+ if (INVALID_HANDLE_VALUE == hFind)
+ return;
+
+ do {
+ if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
+ continue;
+ outFiles.push_back(eastl::string(ffd.cFileName));
+ } while (FindNextFileA(hFind, &ffd) != 0);
+}
+#else
+void CFileTools::GetDirectoryEntries(const eastl::string &inPath,
+ eastl::vector<eastl::string> &outFiles)
+{
+ if (inPath.size() == 0)
+ return;
+ eastl::string tempPath(inPath);
+ NormalizePath(tempPath);
+ struct dirent *dent;
+ DIR *srcdir = opendir(tempPath.c_str());
+ if (srcdir) {
+ while ((dent = readdir(srcdir)) != NULL) {
+ if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
+ continue;
+ outFiles.push_back(eastl::string(dent->d_name));
+ }
+ closedir(srcdir);
+ }
+}
+#endif
+
+bool CFileTools::CreateDir(const eastl::string &inPath, bool inRecurse)
+{
+ if (DirectoryExists(inPath.c_str()))
+ return true;
+
+ eastl::string temp(inPath);
+ GetDirectory(temp);
+ if (temp.size() && !DirectoryExists(temp.c_str())) {
+ if (inRecurse)
+ CreateDir(temp, inRecurse);
+ else
+ return false;
+ }
+
+#ifdef EA_PLATFORM_WINDOWS
+ BOOL result = CreateDirectoryA(inPath.c_str(), NULL);
+ return result != 0;
+#else
+ int result = mkdir(inPath.c_str(), 0777);
+ return result == 0;
+#endif
+}
+
+void CFileTools::AppendDirectoryInPathToFile(eastl::string &ioPath, const char8_t *dirName)
+{
+ eastl::string::size_type lastSlash = ioPath.find_last_of("\\/");
+ if (lastSlash != eastl::string::npos) {
+ if (dirName == NULL)
+ dirName = ""; // avoid crashes on null strings
+ ioPath.insert(lastSlash + 1, "/");
+ ioPath.insert(lastSlash + 1, dirName);
+ } else {
+ ioPath.insert(0, "/");
+ ioPath.insert(0, dirName);
+ }
+}
+
+void CFileTools::RemoveLastDirectoryInPathToFile(eastl::string &ioPath)
+{
+ eastl::string::size_type lastSlash = ioPath.find_last_of("\\/");
+ if (lastSlash != eastl::string::npos) {
+ eastl::string::size_type secondToLastSlash = ioPath.find_last_of("\\/", lastSlash - 1);
+ if (secondToLastSlash != eastl::string::npos)
+ ioPath = ioPath.erase(secondToLastSlash, lastSlash - secondToLastSlash);
+ }
+}
+
+void CFileTools::SetExtension(eastl::string &ioPath, const char8_t *inExt)
+{
+ eastl::string::size_type thePos = ioPath.find_last_of(".");
+ if (thePos != eastl::string::npos) {
+ ++thePos;
+ ioPath = ioPath.replace(thePos, ioPath.size() - thePos, inExt);
+ }
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/IOStreams.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/IOStreams.cpp
new file mode 100644
index 00000000..f1adfbc0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/IOStreams.cpp
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/IOStreams.h"
+#include "foundation/FileTools.h"
+#include "foundation/StrConvertUTF.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSThread.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+
+using namespace qt3ds::foundation;
+
+#ifndef _WIN32
+
+inline int _fseeki64(FILE *inFile, int64_t pos, int seekFlags)
+{
+ return fseek(inFile, (int32_t)pos, seekFlags);
+}
+
+inline int64_t _ftelli64(FILE *inFile)
+{
+ return ftell(inFile);
+}
+
+#endif
+
+CFileSeekableIOStream::CFileSeekableIOStream(const char *inFileName, FileOpenFlags inFlags)
+{
+ openFile(QString(inFileName), inFlags);
+}
+
+#ifdef WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+
+CFileSeekableIOStream::CFileSeekableIOStream(const wchar_t *inFileName, FileOpenFlags inFlags)
+{
+ openFile(QString::fromWCharArray(inFileName), inFlags);
+}
+
+#endif
+
+CFileSeekableIOStream::CFileSeekableIOStream(const char16_t *inWideName, FileOpenFlags inFlags)
+{
+ openFile(QString::fromUtf16(inWideName), inFlags);
+}
+
+CFileSeekableIOStream::CFileSeekableIOStream(const QString &inFIle, FileOpenFlags inFlags)
+{
+ openFile(inFIle, inFlags);
+}
+
+void CFileSeekableIOStream::openFile(const QString &path, FileOpenFlags inFlags)
+{
+ if (path.isEmpty())
+ return;
+
+ QIODevice::OpenMode fileFlags = QIODevice::ReadOnly;
+ if (inFlags & FileOpenFlagValues::Write)
+ fileFlags = QIODevice::ReadWrite;
+ if (inFlags & FileOpenFlagValues::Truncate)
+ fileFlags |= QIODevice::Truncate;
+
+ m_File.setFileName(CFileTools::NormalizePathForQtUsage(path));
+ if (!m_File.open(fileFlags)) {
+ qCCritical(INTERNAL_ERROR) << "failed to open file"
+ << path << "with error" << m_File.errorString();
+ QT3DS_ASSERT(false);
+ }
+}
+
+CFileSeekableIOStream::~CFileSeekableIOStream()
+{
+ m_File.close();
+}
+
+bool CFileSeekableIOStream::IsOpen()
+{
+ return m_File.isOpen();
+}
+
+void CFileSeekableIOStream::SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inEnum)
+{
+ if (inOffset > QT3DS_MAX_I32 || inOffset < QT3DS_MIN_I32) {
+ qCCritical(INVALID_OPERATION, "Attempt to seek further than platform allows");
+ QT3DS_ASSERT(false);
+ return;
+ } else {
+ CFileTools::SetStreamPosition(m_File, inOffset, inEnum);
+ }
+}
+
+QT3DSI64 CFileSeekableIOStream::GetPosition() const
+{
+ return m_File.pos();
+}
+
+QT3DSU32 CFileSeekableIOStream::Read(NVDataRef<QT3DSU8> data)
+{
+ return m_File.read((char *)data.begin(), data.size());
+}
+
+bool CFileSeekableIOStream::Write(NVConstDataRef<QT3DSU8> data)
+{
+ if (!m_File.isOpen()) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ qint64 numBytes = m_File.write((char*)data.begin(), data.size());
+ return numBytes == data.size();
+}
+
+CMemorySeekableIOStream::CMemorySeekableIOStream(NVAllocatorCallback &inAlloc,
+ const char *inAllocName)
+ : m_Allocator(inAlloc)
+ , m_AllocationName(inAllocName)
+ , m_Data(NULL)
+ , m_Size(0)
+ , m_Offset(0)
+ , m_Capacity(0)
+{
+}
+
+CMemorySeekableIOStream::~CMemorySeekableIOStream()
+{
+ if (m_Data)
+ m_Allocator.deallocate(m_Data);
+ m_Data = NULL;
+ m_Size = 0;
+ m_Capacity = 0;
+ m_Offset = 0;
+}
+
+void CMemorySeekableIOStream::SetPosition(QT3DSI64 inOffset, SeekPosition::Enum inEnum)
+{
+ QT3DSI64 startPos = 0;
+
+ switch (inEnum) {
+ case SeekPosition::Begin:
+ startPos = 0;
+ break;
+ case SeekPosition::Current:
+ startPos = m_Offset;
+ break;
+ case SeekPosition::End:
+ startPos = m_Size;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ startPos += inOffset;
+ if (m_Size == 0 && inOffset != 0) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (startPos < 0) {
+ QT3DS_ASSERT(false);
+ startPos = 0;
+ }
+ if (startPos >= m_Size && startPos != 0) {
+ QT3DS_ASSERT(false);
+ startPos = m_Size - 1;
+ }
+ m_Offset = static_cast<QT3DSU32>(startPos);
+}
+
+QT3DSU32 CMemorySeekableIOStream::Read(NVDataRef<QT3DSU8> data)
+{
+ if (m_Data == NULL)
+ return 0;
+ QT3DSU32 amountLeft = m_Size - m_Offset;
+ QT3DSU32 numBytes = NVMin(amountLeft, data.size());
+ intrinsics::memCopy(data.begin(), m_Data + m_Offset, numBytes);
+ m_Offset += numBytes;
+ return numBytes;
+}
+
+bool CMemorySeekableIOStream::Write(NVConstDataRef<QT3DSU8> data)
+{
+ reserve(data.size() + m_Offset);
+ intrinsics::memCopy(m_Data + m_Offset, data.begin(), data.size());
+ m_Offset += data.size();
+ m_Size = NVMax(m_Size, m_Offset);
+ return true;
+}
+
+void CMemorySeekableIOStream::reserve(QT3DSU32 inNewSize)
+{
+ if (inNewSize > m_Capacity) {
+ if (inNewSize < 100000)
+ inNewSize *= 2;
+ QT3DSU8 *newData =
+ (QT3DSU8 *)m_Allocator.allocate(inNewSize, m_AllocationName, __FILE__, __LINE__);
+ if (m_Size) {
+ intrinsics::memCopy(newData, m_Data, m_Size);
+ m_Allocator.deallocate(m_Data);
+ }
+ m_Data = newData;
+ m_Capacity = inNewSize;
+ }
+}
+
+namespace {
+
+struct WriteBufferedStreamImpl;
+struct WriteBufferThread : public Thread
+{
+ // When a buffer is available
+ WriteBufferedStreamImpl &m_Impl;
+ WriteBufferThread(NVFoundationBase &fnd, WriteBufferedStreamImpl &i)
+ : Thread(fnd)
+ , m_Impl(i)
+ {
+ setName("WriteBufferThread");
+ }
+ void execute() override;
+};
+
+#ifdef _WIN32
+#pragma warning(disable : 4355)
+#endif
+/* Double buffered stream implementation with a sending thread constantly
+ * pulling data from the main thread and writing it out to socket.
+ */
+struct WriteBufferedStreamImpl : public WriteBufferedOutStream
+{
+ NVFoundationBase &m_Foundation;
+ IOutStream &m_Stream;
+ MemoryBuffer<> m_Buf1;
+ MemoryBuffer<> m_Buf2;
+ MemoryBuffer<> *m_CurrentBuffer;
+ MemoryBuffer<> *m_WriteBuffer;
+ QT3DSU32 m_BufferSize;
+ volatile bool m_StreamValid;
+ Mutex m_BufferLock;
+ Sync m_DataAvailable;
+ Sync m_WriteFinished;
+ WriteBufferThread m_Thread;
+ QT3DSI32 mRefCount;
+
+ WriteBufferedStreamImpl(NVFoundationBase &fnd, QT3DSU32 totalBufSize, IOutStream &s)
+ : m_Foundation(fnd)
+ , m_Stream(s)
+ , m_Buf1(ForwardingAllocator(fnd.getAllocator(), "WriteBufferedStreamImpl::buffer"))
+ , m_Buf2(ForwardingAllocator(fnd.getAllocator(), "WriteBufferedStreamImpl::buffer"))
+ , m_CurrentBuffer(&m_Buf1)
+ , m_WriteBuffer(NULL)
+ , m_BufferSize(totalBufSize / 2)
+ , m_StreamValid(true)
+ , m_BufferLock(fnd.getAllocator())
+ , m_DataAvailable(fnd.getAllocator())
+ , m_WriteFinished(fnd.getAllocator())
+ , m_Thread(fnd, *this)
+ , mRefCount(0)
+ {
+ m_Buf1.reserve(m_BufferSize);
+ m_Buf2.reserve(m_BufferSize);
+ }
+ ~WriteBufferedStreamImpl()
+ {
+ m_Thread.signalQuit();
+ m_DataAvailable.set();
+ m_Thread.waitForQuit();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ while (data.size() && m_StreamValid) {
+ QT3DSU32 currentBufferSize;
+ QT3DSU32 amountCanWrite;
+ {
+ Mutex::ScopedLock locker(m_BufferLock);
+ currentBufferSize = m_CurrentBuffer->size();
+ amountCanWrite = NVMin(data.size(), m_BufferSize - currentBufferSize);
+ m_CurrentBuffer->write(data.begin(), amountCanWrite);
+ currentBufferSize += amountCanWrite;
+ }
+ m_DataAvailable.set();
+ if (currentBufferSize == m_BufferSize) {
+ m_WriteFinished.wait();
+ m_WriteFinished.reset();
+ // Blocking call if we are already sending data.
+ data = NVConstDataRef<QT3DSU8>(data.begin() + amountCanWrite,
+ data.size() - amountCanWrite);
+ }
+ }
+ return m_StreamValid;
+ }
+
+ IOutStream &wrappedStream() override { return m_Stream; }
+
+ QT3DSU32 getTotalBufferSize()
+ {
+ Mutex::ScopedLock locker(m_BufferLock);
+ QT3DSU32 retval = m_CurrentBuffer->size();
+ if (m_WriteBuffer)
+ retval += m_WriteBuffer->size();
+ return retval;
+ }
+
+ QT3DSU32 getWriteBufferSize()
+ {
+ Mutex::ScopedLock locker(m_BufferLock);
+ if (m_WriteBuffer)
+ return m_WriteBuffer->size();
+ return 0;
+ }
+
+ void flush() override
+ {
+ while (getTotalBufferSize()) {
+ m_WriteFinished.wait();
+ m_WriteFinished.reset();
+ }
+ }
+};
+
+void WriteBufferThread::execute()
+{
+ while (!quitIsSignalled()) {
+ m_Impl.m_DataAvailable.wait();
+
+ if (!quitIsSignalled() && m_Impl.m_StreamValid) {
+ m_Impl.m_DataAvailable.reset();
+ {
+ Mutex::ScopedLock locker(m_Impl.m_BufferLock);
+ m_Impl.m_WriteBuffer = m_Impl.m_CurrentBuffer;
+ m_Impl.m_CurrentBuffer =
+ m_Impl.m_CurrentBuffer == &m_Impl.m_Buf1 ? &m_Impl.m_Buf2 : &m_Impl.m_Buf1;
+ QT3DS_ASSERT(m_Impl.m_WriteBuffer != m_Impl.m_CurrentBuffer);
+ }
+ NVConstDataRef<QT3DSU8> dataBuffer(*m_Impl.m_WriteBuffer);
+ if (dataBuffer.size()) {
+ m_Impl.m_StreamValid = m_Impl.m_Stream.Write(dataBuffer);
+ {
+ Mutex::ScopedLock locker(m_Impl.m_BufferLock);
+ m_Impl.m_WriteBuffer->clear();
+ m_Impl.m_WriteBuffer = NULL;
+ }
+ }
+ m_Impl.m_WriteFinished.set();
+ }
+ }
+ quit();
+}
+}
+
+NVScopedRefCounted<WriteBufferedOutStream>
+WriteBufferedOutStreamCreate(NVFoundationBase &fnd, IOutStream &stream, QT3DSU32 totalBufferSize)
+{
+ return QT3DS_NEW(fnd.getAllocator(), WriteBufferedStreamImpl)(fnd, totalBufferSize, stream);
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/LICENCE_SOCKET.TXT b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/LICENCE_SOCKET.TXT
new file mode 100644
index 00000000..9b9ab805
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/LICENCE_SOCKET.TXT
@@ -0,0 +1,20 @@
+LuaSocket 3.0 license
+Copyright (C) 2004-2013 Diego Nehab
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSFoundation.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSFoundation.cpp
new file mode 100644
index 00000000..8687cd69
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSFoundation.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSFoundation.h"
+
+#include "foundation/Qt3DSQuat.h"
+#include "foundation/Qt3DSThread.h"
+#include "foundation/Qt3DSUtilities.h"
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSLogging.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "EASTL/hash_map.h"
+
+#include <stdio.h>
+#ifdef _WIN32
+#pragma warning(disable : 4996) // intentionally suppressing this warning message
+#endif
+namespace qt3ds {
+namespace foundation {
+ using namespace intrinsics;
+ union TempAllocatorChunk;
+
+ class NVAllocatorListenerManager;
+
+ class QT3DS_FOUNDATION_API Foundation : public NVFoundation
+ {
+
+ Foundation(NVAllocatorCallback &alloc);
+ ~Foundation();
+
+ public:
+ void addRef() override;
+ void release() override;
+
+ // factory
+ static Foundation *createInstance(QT3DSU32 version, NVAllocatorCallback &alloc);
+
+ NVBroadcastingAllocator &getAllocator() const override { return mAllocator; }
+ NVAllocatorCallback &getAllocatorCallback() const override;
+ NVAllocatorCallback &getCheckedAllocator() { return mAllocator; }
+
+ private:
+ class AlignCheckAllocator : public NVBroadcastingAllocator
+ {
+ static const QT3DSU32 MaxListenerCount = 5;
+
+ public:
+ AlignCheckAllocator(NVAllocatorCallback &originalAllocator)
+ : mAllocator(originalAllocator)
+ , mListenerCount(0)
+ {
+ }
+
+ void deallocate(void *ptr) override
+ {
+ // So here, for performance reasons I don't grab the mutex.
+ // The listener array is very rarely changing; for most situations
+ // only at startup. So it is unlikely that using the mutex
+ // will help a lot but it could have serious perf implications.
+ QT3DSU32 theCount = mListenerCount;
+ for (QT3DSU32 idx = 0; idx < theCount; ++idx)
+ mListeners[idx]->onDeallocation(ptr);
+ mAllocator.deallocate(ptr);
+ }
+ void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ int flags) override;
+ void *allocate(size_t size, const char *typeName, const char *filename, int line,
+ size_t alignment, size_t alignmentOffset) override;
+ NVAllocatorCallback &getBaseAllocator() const { return mAllocator; }
+ void registerAllocationListener(NVAllocationListener &inListener) override
+ {
+ QT3DS_ASSERT(mListenerCount < MaxListenerCount);
+ if (mListenerCount < MaxListenerCount) {
+ mListeners[mListenerCount] = &inListener;
+ ++mListenerCount;
+ }
+ }
+ void deregisterAllocationListener(NVAllocationListener &inListener) override
+ {
+ for (QT3DSU32 idx = 0; idx < mListenerCount; ++idx) {
+ if (mListeners[idx] == &inListener) {
+ mListeners[idx] = mListeners[mListenerCount - 1];
+ --mListenerCount;
+ break;
+ }
+ }
+ }
+
+ private:
+ NVAllocatorCallback &mAllocator;
+ // I am not sure about using a NVArray here.
+ // For now, this is fine.
+ NVAllocationListener *mListeners[MaxListenerCount];
+ volatile QT3DSU32 mListenerCount;
+ };
+
+ mutable AlignCheckAllocator mAllocator;
+ QT3DSU32 mRefCount;
+ Mutex mRefCountMutex;
+ };
+
+ Foundation::Foundation(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ , mRefCount(0)
+ , mRefCountMutex(alloc)
+
+ {
+ }
+
+ Foundation::~Foundation() {}
+
+ NVAllocatorCallback &Foundation::getAllocatorCallback() const
+ {
+ return mAllocator.getBaseAllocator();
+ }
+
+ Foundation *Foundation::createInstance(QT3DSU32 version, NVAllocatorCallback &alloc)
+ {
+ if (version != QT3DS_FOUNDATION_VERSION) {
+ qCCritical(INVALID_PARAMETER, "Wrong version: foundation version is %d, tried to create %d",
+ QT3DS_FOUNDATION_VERSION, version);
+ return 0;
+ }
+ Foundation *mInstance = NULL;
+
+ if (!mInstance) {
+ // if we don't assign this here, the Foundation object can't create member
+ // subobjects which require the allocator
+
+ mInstance = reinterpret_cast<Foundation *>(
+ alloc.allocate(sizeof(Foundation), "Foundation", __FILE__, __LINE__));
+
+ if (mInstance) {
+ QT3DS_PLACEMENT_NEW(mInstance, Foundation)(alloc);
+
+ QT3DS_ASSERT(mInstance->mRefCount == 0);
+
+ return mInstance;
+ } else {
+ qCCritical(INTERNAL_ERROR, "Memory allocation for foundation object failed.");
+ }
+ } else {
+ qCCritical(
+ INVALID_OPERATION,
+ "Foundation object exists already. Only one instance per process can be created.");
+ }
+
+ return 0;
+ }
+
+ void Foundation::addRef()
+ {
+ mRefCountMutex.lock();
+ ++mRefCount;
+ mRefCountMutex.unlock();
+ }
+
+ void Foundation::release()
+ {
+ mRefCountMutex.lock();
+ if (mRefCount)
+ --mRefCount;
+ QT3DSU32 refCount = mRefCount;
+ mRefCountMutex.unlock();
+ if (!refCount) {
+ NVAllocatorCallback &alloc = mAllocator.getBaseAllocator();
+ this->~Foundation();
+ alloc.deallocate(this);
+ }
+ }
+
+ void *Foundation::AlignCheckAllocator::allocate(size_t size, const char *typeName,
+ const char *filename, int line, int)
+ {
+ void *addr = mAllocator.allocate(size, typeName, filename, line);
+
+ if (!addr)
+ qFatal("User allocator returned NULL.");
+
+ if (!(reinterpret_cast<size_t>(addr) & 15)) {
+ // Same comment as before in the allocation system.
+ // We don't lock the listener array mutex because of an assumption
+ // where the listener array is rarely changing.
+ QT3DSU32 theCount = mListenerCount;
+ for (QT3DSU32 idx = 0; idx < theCount; ++idx)
+ mListeners[idx]->onAllocation(size, typeName, filename, line, addr);
+ return addr;
+ }
+
+ qFatal("Allocations for qt3ds::foundation must be 16-byte aligned.");
+ return 0;
+ }
+
+ void *Foundation::AlignCheckAllocator::allocate(size_t size, const char *typeName,
+ const char *filename, int line,
+ size_t /*alignment*/,
+ size_t /*alignmentOffset*/)
+ {
+ return allocate(size, typeName, filename, line, 0);
+ }
+
+} // namespace foundation
+} // namespace qt3ds
+
+qt3ds::NVFoundation *NVCreateFoundation(qt3ds::QT3DSU32 version, qt3ds::NVAllocatorCallback &allocator)
+{
+ return qt3ds::foundation::Foundation::createInstance(version, allocator);
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSLogging.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSLogging.cpp
new file mode 100644
index 00000000..257b39b2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSLogging.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSLogging.h"
+
+namespace qt3ds {
+
+Q_LOGGING_CATEGORY(GL_ERROR, "qt3ds.gl_error")
+Q_LOGGING_CATEGORY(INVALID_PARAMETER, "qt3ds.invalid_parameter")
+Q_LOGGING_CATEGORY(INVALID_OPERATION, "qt3ds.invalid_operation")
+Q_LOGGING_CATEGORY(OUT_OF_MEMORY, "qt3ds.out_of_memory")
+Q_LOGGING_CATEGORY(INTERNAL_ERROR, "qt3ds.internal_error")
+Q_LOGGING_CATEGORY(PERF_WARNING, "qt3ds.perf_warning")
+Q_LOGGING_CATEGORY(PERF_INFO, "qt3ds.perf_info")
+Q_LOGGING_CATEGORY(TRACE_INFO, "qt3ds.trace_info")
+Q_LOGGING_CATEGORY(WARNING, "qt3ds.warning")
+
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSMathUtils.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSMathUtils.cpp
new file mode 100644
index 00000000..7eee7405
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSMathUtils.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSMathUtils.h"
+#include "foundation/Qt3DSUtilities.h"
+#include "foundation/Qt3DSMat33.h"
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::intrinsics;
+
+QT3DSQuat qt3ds::foundation::computeQuatFromNormal(const QT3DSVec3 &n)
+{
+ // parallel or anti-parallel
+ if (n.x > 0.9999f) {
+ // parallel
+ return QT3DSQuat::createIdentity();
+ } else if (n.x < -0.9999f) {
+ // anti-parallel
+ // contactQuaternion.fromAngleAxisFast(PXD_PI, Vector3(0.0f, 1.0f, 0.0f));
+ return QT3DSQuat(0.0f, 1.0f, 0.0f, 0.0f);
+ } else {
+ QT3DSVec3 rotVec(0.0f, -n.z, n.y);
+
+ // Convert to quat
+ NVReal angle = rotVec.magnitude();
+ rotVec *= 1.0f / angle;
+ // if(angle > 1.0f) angle = 1.0f;
+ angle = selectMin(angle, 1.0f);
+
+ // djs: injudiciously imbecilic use of trig functions, good thing Adam is going to trample
+ // this path like a
+ // frustrated rhinoceros in mating season
+
+ angle = NVAsin(angle);
+
+ // if(n.x < 0)
+ // angle = NVPi - angle;
+ angle = fsel(n.x, angle, NVPi - angle);
+
+ return QT3DSQuat(angle, rotVec);
+ }
+}
+
+/**
+\brief computes a oriented bounding box around the scaled basis.
+\param basis Input = skewed basis, Output = (normalized) orthogonal basis.
+\return Bounding box extent.
+*/
+QT3DSVec3 qt3ds::foundation::optimizeBoundingBox(QT3DSMat33 &basis)
+{
+ QT3DSVec3 *QT3DS_RESTRICT vec = &basis[0]; // PT: don't copy vectors if not needed...
+
+ // PT: since we store the magnitudes to memory, we can avoid the FCMNV afterwards
+ QT3DSVec3 magnitude(vec[0].magnitudeSquared(), vec[1].magnitudeSquared(),
+ vec[2].magnitudeSquared());
+
+// find indices sorted by magnitude
+#ifdef QT3DS_X360
+ int i = (QT3DSU32 &)(magnitude[1]) > (QT3DSU32 &)(magnitude[0]) ? 1 : 0;
+ int j = (QT3DSU32 &)(magnitude[2]) > (QT3DSU32 &)(magnitude[1 - i]) ? 2 : 1 - i;
+#else
+ int i = magnitude[1] > magnitude[0] ? 1 : 0;
+ int j = magnitude[2] > magnitude[1 - i] ? 2 : 1 - i;
+#endif
+ const int k = 3 - i - j;
+#ifdef QT3DS_X360
+ if ((QT3DSU32 &)(magnitude[i]) < (QT3DSU32 &)(magnitude[j]))
+#else
+ if (magnitude[i] < magnitude[j])
+#endif
+ swap(i, j);
+
+ // ortho-normalize basis
+
+ NVReal invSqrt = NVRecipSqrt(magnitude[i]);
+ magnitude[i] *= invSqrt;
+ vec[i] *= invSqrt; // normalize the first axis
+ NVReal dotij = vec[i].dot(vec[j]);
+ NVReal dotik = vec[i].dot(vec[k]);
+ magnitude[i] += NVAbs(dotij) + NVAbs(dotik); // elongate the axis by projection of the other two
+ vec[j] -= vec[i] * dotij; // orthogonize the two remaining axii relative to vec[i]
+ vec[k] -= vec[i] * dotik;
+
+ magnitude[j] = vec[j].normalize();
+ NVReal dotjk = vec[j].dot(vec[k]);
+ magnitude[j] += NVAbs(dotjk); // elongate the axis by projection of the other one
+ vec[k] -= vec[j] * dotjk; // orthogonize vec[k] relative to vec[j]
+
+ magnitude[k] = vec[k].normalize();
+
+ return magnitude;
+}
+
+QT3DSQuat qt3ds::foundation::slerp(const NVReal t, const QT3DSQuat &left, const QT3DSQuat &right)
+{
+ const NVReal quatEpsilon = (NVReal(1.0e-8f));
+
+ NVReal cosine = left.dot(right);
+ NVReal sign = NVReal(1);
+ if (cosine < 0) {
+ cosine = -cosine;
+ sign = NVReal(-1);
+ }
+
+ NVReal sine = NVReal(1) - cosine * cosine;
+
+ if (sine >= quatEpsilon * quatEpsilon) {
+ sine = NVSqrt(sine);
+ const NVReal angle = NVAtan2(sine, cosine);
+ const NVReal i_sin_angle = NVReal(1) / sine;
+
+ const NVReal leftw = NVSin(angle * (NVReal(1) - t)) * i_sin_angle;
+ const NVReal rightw = NVSin(angle * t) * i_sin_angle * sign;
+
+ return left * leftw + right * rightw;
+ }
+
+ return left;
+}
+
+void qt3ds::foundation::integrateTransform(const NVTransform &curTrans, const QT3DSVec3 &linvel,
+ const QT3DSVec3 &angvel, NVReal timeStep, NVTransform &result)
+{
+ result.p = curTrans.p + linvel * timeStep;
+
+ // from void NVsDynamicsContext::integrateAtomPose(NVsRigidBody* atom, Cm::BitMap
+ // &shapeChangedMap) const:
+ // Integrate the rotation using closed form quaternion integrator
+ NVReal w = angvel.magnitudeSquared();
+
+ if (w != 0.0f) {
+ w = NVSqrt(w);
+ if (w != 0.0f) {
+ const NVReal v = timeStep * w * 0.5f;
+ const NVReal q = NVCos(v);
+ const NVReal s = NVSin(v) / w;
+
+ const QT3DSVec3 pqr = angvel * s;
+ const QT3DSQuat quatVel(pqr.x, pqr.y, pqr.z, 0);
+ QT3DSQuat out; // need to have temporary, otherwise we may overwrite input if &curTrans ==
+ // &result.
+ out = quatVel * curTrans.q;
+ out.x += curTrans.q.x * q;
+ out.y += curTrans.q.y * q;
+ out.z += curTrans.q.z * q;
+ out.w += curTrans.q.w * q;
+ result.q = out;
+ return;
+ }
+ }
+ // orientation stays the same - convert from quat to matrix:
+ result.q = curTrans.q;
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSPerfTimer.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSPerfTimer.cpp
new file mode 100644
index 00000000..06fb5d38
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSPerfTimer.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "EASTL/hash_map.h"
+#include "EASTL/string.h"
+#include "EASTL/vector.h"
+#include "EASTL/sort.h"
+
+using namespace qt3ds::foundation;
+using namespace qt3ds;
+
+namespace {
+struct STimerEntry
+{
+ QT3DSU64 m_Total;
+ QT3DSU64 m_Max;
+ QT3DSU32 m_UpdateCount;
+ CRegisteredString m_Tag;
+ size_t m_Order;
+
+ STimerEntry(CRegisteredString tag, size_t order)
+ : m_Total(0)
+ , m_Max(0)
+ , m_UpdateCount(0)
+ , m_Tag(tag)
+ , m_Order(order)
+ {
+ }
+ void Update(QT3DSU64 increment)
+ {
+ m_Total += increment;
+ m_Max = increment > m_Max ? increment : m_Max;
+ ++m_UpdateCount;
+ }
+
+ void Output(NVFoundationBase &fnd, QT3DSU32 inFramesPassed)
+ {
+ Q_UNUSED(fnd)
+ if (m_Total) {
+ QT3DSU64 tensNanos = Time::sCounterFreq.toTensOfNanos(m_Total);
+ QT3DSU64 maxNanos = Time::sCounterFreq.toTensOfNanos(m_Max);
+
+ double milliseconds = tensNanos / 100000.0;
+ double maxMilliseconds = maxNanos / 100000.0;
+ if (inFramesPassed == 0)
+ qCWarning(WARNING, PERF_INFO, "%s - %fms", m_Tag.c_str(), milliseconds);
+ else {
+ milliseconds /= inFramesPassed;
+ qCWarning(WARNING, PERF_INFO, "%s - %fms/frame-total %fms-max %u hits",
+ m_Tag.c_str(), milliseconds, maxMilliseconds, m_UpdateCount);
+ }
+ }
+ }
+
+ void Reset()
+ {
+ m_Total = 0;
+ m_Max = 0;
+ m_UpdateCount = 0;
+ }
+
+ bool operator<(const STimerEntry &other) const { return m_Order < other.m_Order; }
+};
+struct SPerfTimer : public IPerfTimer
+{
+ typedef eastl::hash_map<CRegisteredString, STimerEntry> THashMapType;
+ NVFoundationBase &m_Foundation;
+ // This object needs its own string table because it is used during the binary load process with
+ // the application string table gets booted up.
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ THashMapType m_Entries;
+ eastl::vector<STimerEntry> m_PrintEntries;
+ Mutex m_Mutex;
+ QT3DSI32 mRefCount;
+
+ SPerfTimer(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ , m_StringTable(IStringTable::CreateStringTable(fnd.getAllocator()))
+ , m_Mutex(fnd.getAllocator())
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ void Update(const char *inId, QT3DSU64 inAmount) override
+ {
+ Mutex::ScopedLock __locker(m_Mutex);
+ CRegisteredString theStr(m_StringTable->RegisterStr(inId));
+ THashMapType::iterator theFind =
+ m_Entries.insert(eastl::make_pair(theStr, STimerEntry(theStr, m_Entries.size()))).first;
+ theFind->second.Update(inAmount);
+ }
+
+ // Dump current summation of timer data.
+ void OutputTimerData(QT3DSU32 inFramesPassed = 0) override
+ {
+ Mutex::ScopedLock __locker(m_Mutex);
+ m_PrintEntries.clear();
+ for (THashMapType::iterator iter = m_Entries.begin(), end = m_Entries.end(); iter != end;
+ ++iter) {
+ m_PrintEntries.push_back(iter->second);
+ iter->second.Reset();
+ }
+
+ eastl::sort(m_PrintEntries.begin(), m_PrintEntries.end());
+
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)m_PrintEntries.size(); idx < end; ++idx) {
+ m_PrintEntries[idx].Output(m_Foundation, inFramesPassed);
+ }
+ }
+
+ void ResetTimerData() override
+ {
+ Mutex::ScopedLock __locker(m_Mutex);
+ for (THashMapType::iterator iter = m_Entries.begin(), end = m_Entries.end(); iter != end;
+ ++iter) {
+ iter->second.Reset();
+ }
+ }
+
+ virtual void ClearPerfKeys()
+ {
+ Mutex::ScopedLock __locker(m_Mutex);
+ m_Entries.clear();
+ }
+};
+}
+
+IPerfTimer &IPerfTimer::CreatePerfTimer(NVFoundationBase &fnd)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SPerfTimer)(fnd);
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSSystem.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSSystem.cpp
new file mode 100644
index 00000000..73b03084
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Qt3DSSystem.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSSystem.h"
+#include "foundation/Qt3DSPreprocessor.h"
+#include "EASTL/string.h"
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+
+#if defined(QT3DS_ANDROID)
+const char *qt3ds::foundation::System::g_OS = "android";
+const char *qt3ds::foundation::System::g_DLLExtension = ".so";
+#elif defined(QT3DS_APPLE)
+const char *qt3ds::foundation::System::g_OS = "osx";
+const char *qt3ds::foundation::System::g_DLLExtension = ".dylib";
+#elif defined(QT3DS_LINUX)
+const char *qt3ds::foundation::System::g_OS = "linux";
+const char *qt3ds::foundation::System::g_DLLExtension = ".so";
+#elif defined(QT3DS_QNX)
+const char *qt3ds::foundation::System::g_OS = "qnx";
+const char *qt3ds::foundation::System::g_DLLExtension = ".so";
+#elif defined(QT3DS_WINDOWS)
+const char *qt3ds::foundation::System::g_OS = "windows";
+const char *qt3ds::foundation::System::g_DLLExtension = ".dll";
+#else
+#error "Unknown Operating System"
+#endif
+
+#if defined(QT3DS_X86)
+const char *qt3ds::foundation::System::g_Processor = "x86";
+const char *qt3ds::foundation::System::g_BitWidth = "32";
+const char *qt3ds::foundation::System::g_FloatingPointModel = "";
+#elif defined(QT3DS_X64)
+const char *qt3ds::foundation::System::g_Processor = "x64";
+const char *qt3ds::foundation::System::g_BitWidth = "64";
+const char *qt3ds::foundation::System::g_FloatingPointModel = "";
+#elif defined(QT3DS_ARM)
+#if defined(__aarch64__) || defined(__ARM64__)
+const char *qt3ds::foundation::System::g_Processor = "arm";
+const char *qt3ds::foundation::System::g_BitWidth = "64";
+const char *qt3ds::foundation::System::g_FloatingPointModel = "softfp";
+#else
+const char *qt3ds::foundation::System::g_Processor = "arm";
+const char *qt3ds::foundation::System::g_BitWidth = "32";
+#if defined(QT3DS_ARM_HARDFP)
+const char *qt3ds::foundation::System::g_FloatingPointModel = "hardfp";
+#elif defined(QT3DS_ARM_SOFTFP)
+const char *qt3ds::foundation::System::g_FloatingPointModel = "softfp";
+#else
+#error "Unknown floating point model!"
+#endif
+#endif
+#else
+#error "Unknown Platform"
+#endif
+
+#if defined(QT3DS_ARM)
+#if defined(UIC_GRAPHICS_API_GLES2)
+const char *qt3ds::foundation::System::g_GPUType = "gles2";
+#elif defined(UIC_GRAPHICS_API_GL)
+const char *qt3ds::foundation::System::g_GPUType = "gl";
+#elif defined(UIC_GRAPHICS_API_GLES3)
+const char *qt3ds::foundation::System::g_GPUType = "gles3";
+#else
+#error \
+ "Must define a GPU type for arm platforms (UIC_GRAPHICS_API_GLES2, UIC_GRAPHICS_API_GLES3, UIC_GRAPHICS_API_GL)"
+#endif
+#elif defined(QT3DS_X86)
+const char *qt3ds::foundation::System::g_GPUType = "";
+#elif defined(QT3DS_X64)
+const char *qt3ds::foundation::System::g_GPUType = "";
+#else
+#error "Must define a processor type (QT3DS_ARM or QT3DS_X86)"
+#endif
+
+namespace {
+static const unsigned SYSTEM_STR_SIZE = 100;
+void SystemAppendString(eastl::string &str, const char *delim, const char *string)
+{
+ if (string && *string) {
+ str.append(delim);
+ str.append(string);
+ }
+}
+}
+const char *System::getPlatformStr()
+{
+ static char text[SYSTEM_STR_SIZE];
+ {
+ eastl::string str(g_Processor);
+ SystemAppendString(str, "_", g_BitWidth);
+ SystemAppendString(str, "_", g_FloatingPointModel);
+ SystemAppendString(str, "_", g_OS);
+ strcpy(text, str.c_str());
+ }
+ return text;
+}
+
+const char *System::getPlatformGLStr()
+{
+ static char text[SYSTEM_STR_SIZE];
+ {
+ eastl::string str(g_Processor);
+ SystemAppendString(str, "_", g_BitWidth);
+ SystemAppendString(str, "_", g_FloatingPointModel);
+ SystemAppendString(str, "_", g_GPUType);
+ SystemAppendString(str, "_", g_OS);
+ strcpy(text, str.c_str());
+ }
+ return text;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Socket.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Socket.cpp
new file mode 100644
index 00000000..df00e606
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/Socket.cpp
@@ -0,0 +1,472 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+LuaSocket 3.0 license
+Copyright � 2004-2013 Diego Nehab
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#include "foundation/Socket.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+
+#if defined QT3DS_WINDOWS || defined QT3DS_WIN8ARM
+#include "windows/SocketImpl.h"
+#else
+#include "linux/SocketImpl.h"
+#endif
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::foundation::socketimpl;
+
+namespace {
+
+#if defined QT3DS_WINDOWS || defined QT3DS_WIN8ARM
+/*-------------------------------------------------------------------------*\
+* Some systems do not provide this so that we provide our own. It's not
+* marvelously fast, but it works just fine.
+\*-------------------------------------------------------------------------*/
+int inet_aton(const char *cp, struct in_addr *inp)
+{
+ unsigned int a = 0, b = 0, c = 0, d = 0;
+ int n = 0, r;
+ unsigned long int addr = 0;
+ r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n);
+ if (r == 0 || n == 0)
+ return 0;
+ cp += n;
+ if (*cp)
+ return 0;
+ if (a > 255 || b > 255 || c > 255 || d > 255)
+ return 0;
+ if (inp) {
+ addr += a;
+ addr <<= 8;
+ addr += b;
+ addr <<= 8;
+ addr += c;
+ addr <<= 8;
+ addr += d;
+ inp->s_addr = htonl(addr);
+ }
+ return 1;
+}
+#endif
+
+/*-------------------------------------------------------------------------*\
+* Tries to connect to remote address (address, port)
+\*-------------------------------------------------------------------------*/
+int inet_tryconnect(p_socket ps, const char *address, unsigned short port, QT3DSU32 tm, SA *remoteAddr)
+{
+ struct sockaddr_in remote;
+ int err;
+ memset(&remote, 0, sizeof(remote));
+ remote.sin_family = AF_INET;
+ remote.sin_port = htons(port);
+ if (strcmp(address, "*")) {
+ if (!inet_aton(address, &remote.sin_addr)) {
+ struct hostent *hp = NULL;
+ struct in_addr **addr;
+ err = socket_gethostbyname(address, &hp);
+ if (err != IO_DONE)
+ return err;
+ addr = (struct in_addr **)hp->h_addr_list;
+ memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr));
+ }
+ } else
+ remote.sin_family = AF_UNSPEC;
+ if (remoteAddr)
+ memcpy(remoteAddr, &remote, sizeof(remote));
+ err = socket_connect(ps, (SA *)&remote, sizeof(remote), tm);
+ return err;
+}
+
+/*-------------------------------------------------------------------------*\
+* Tries to bind socket to (address, port)
+\*-------------------------------------------------------------------------*/
+int inet_trybind(p_socket ps, const char *address, unsigned short port)
+{
+ struct sockaddr_in local;
+ int err;
+ memset(&local, 0, sizeof(local));
+ /* address is either wildcard or a valid ip address */
+ local.sin_addr.s_addr = htonl(INADDR_ANY);
+ local.sin_port = htons(port);
+ local.sin_family = AF_INET;
+ if (strcmp(address, "*") && !inet_aton(address, &local.sin_addr)) {
+ struct hostent *hp = NULL;
+ struct in_addr **addr;
+ err = socket_gethostbyname(address, &hp);
+ if (err != IO_DONE)
+ return err;
+ addr = (struct in_addr **)hp->h_addr_list;
+ memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
+ }
+ err = socket_bind(ps, (SA *)&local, sizeof(local));
+ if (err != IO_DONE)
+ socket_destroy(ps);
+ return err;
+}
+
+static bool is_socket_error(int errcode)
+{
+ return errcode != IO_DONE && errcode != IO_TIMEOUT;
+}
+
+const char *generalized_strerror(int err)
+{
+ if (err <= 0)
+ return io_strerror(err);
+ else
+ return socket_strerror(err);
+}
+
+struct SocketSystemCore : public NVRefCounted
+{
+ NVFoundationBase &m_Foundation;
+ QT3DSI32 mRefCount;
+ SocketSystemCore(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+ ~SocketSystemCore() { socket_close(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ static NVScopedRefCounted<SocketSystemCore> Create(NVFoundationBase &fnd)
+ {
+ int success = socket_open();
+ if (!success) {
+ qCCritical(INVALID_OPERATION, "Failed to initialize network subsystem");
+ return NVScopedRefCounted<SocketSystemCore>();
+ }
+ return QT3DS_NEW(fnd.getAllocator(), SocketSystemCore)(fnd);
+ }
+};
+
+struct SocketStreamImpl : public SocketStream
+{
+ NVScopedRefCounted<SocketSystemCore> m_SocketCore;
+ NVFoundationBase &m_Foundation;
+ t_socket m_Socket;
+ SA m_Destination;
+ bool m_Connected;
+ QT3DSU32 m_Timeout;
+ QT3DSI32 mRefCount;
+ SocketStreamImpl(SocketSystemCore &core, NVFoundationBase &fnd, t_socket s, SA dest)
+ : m_SocketCore(core)
+ , m_Foundation(fnd)
+ , m_Socket(s)
+ , m_Destination(dest)
+ , m_Connected(true)
+ , m_Timeout(10000)
+ , mRefCount(0)
+ {
+ // We use wait functions in order to block.
+ socket_setnonblocking(&m_Socket);
+ }
+
+ ~SocketStreamImpl()
+ {
+ shutdown();
+ socket_destroy(&m_Socket);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ void setTimeout(QT3DSU32 milliseconds) override { m_Timeout = milliseconds; }
+
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ if (m_Connected == false)
+ return false;
+
+ size_t totalSent = 0;
+ const char *writePtr(reinterpret_cast<const char *>(data.begin()));
+ size_t amountLeft = data.size();
+ do {
+
+ size_t amountSent = 0;
+ int errcode =
+ socket_send(&m_Socket, writePtr + totalSent, amountLeft, &amountSent, m_Timeout);
+
+ if (is_socket_error(errcode)) {
+ m_Connected = false;
+ qCWarning(WARNING, "Networking error during send: %s", generalized_strerror(errcode));
+ return false;
+ }
+ totalSent += amountSent;
+ amountLeft -= amountSent;
+ } while (amountLeft);
+ return true;
+ }
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ if (m_Connected == false)
+ return 0;
+ size_t amountReceived = 0;
+ int errcode = socket_recv(&m_Socket, reinterpret_cast<char *>(data.begin()), data.size(),
+ &amountReceived, m_Timeout);
+ if (is_socket_error(errcode)) {
+ m_Connected = false;
+ qCWarning(WARNING, "Networking error during receive: %s", generalized_strerror(errcode));
+ return false;
+ }
+ return static_cast<QT3DSU32>(amountReceived);
+ }
+
+ QT3DSU32 nonBlockingRead(NVDataRef<QT3DSU8> data) override
+ {
+ if (m_Connected == false)
+ return 0;
+ size_t amountReceived = 0;
+ int errcode = socket_recv(&m_Socket, reinterpret_cast<char *>(data.begin()), data.size(),
+ &amountReceived, 0);
+ if (is_socket_error(errcode)) {
+ m_Connected = false;
+ qCWarning(WARNING, "Networking error during receive: %s",
+ generalized_strerror(errcode));
+ return false;
+ }
+ return static_cast<QT3DSU32>(amountReceived);
+ }
+
+ bool connected() override { return m_Connected; }
+
+ void shutdown() override
+ {
+ if (m_Connected) {
+ socket_shutdown(&m_Socket, 2);
+ m_Connected = false;
+ }
+ }
+};
+
+struct FileSocketStreamImpl : public SocketStream
+{
+ NVFoundationBase &m_Foundation;
+ CFileSeekableIOStream m_Stream;
+ FileOpenFlags m_FileFlags;
+ bool m_Connected;
+ QT3DSI32 mRefCount;
+
+ FileSocketStreamImpl(NVFoundationBase &fnd, const char *fname, FileOpenFlags fileFlags)
+ : m_Foundation(fnd)
+ , m_Stream(fname, fileFlags)
+ , m_FileFlags(fileFlags)
+ , m_Connected(false)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ bool IsOpen() { return m_Connected && m_Stream.IsOpen(); }
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ if (IsOpen()) {
+ QT3DSU32 retval = m_Stream.Read(data);
+ if (retval < data.size())
+ m_Connected = false;
+ return retval;
+ }
+
+ return 0;
+ }
+
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ bool canWrite = m_FileFlags & FileOpenFlagValues::Write;
+ if (IsOpen() && canWrite) {
+ m_Stream.Write(data);
+ return true;
+ }
+ return false;
+ }
+
+ void setTimeout(QT3DSU32) override {}
+
+ QT3DSU32 nonBlockingRead(NVDataRef<QT3DSU8> data) override { return Read(data); }
+
+ bool connected() override { return m_Connected; }
+
+ void shutdown() override { m_Connected = false; }
+};
+
+struct SocketServerImpl : public SocketServer
+{
+ NVScopedRefCounted<SocketSystemCore> m_SocketCore;
+ NVFoundationBase &m_Foundation;
+ t_socket m_Socket;
+ int m_Port;
+ QT3DSU32 m_Timeout;
+ QT3DSI32 mRefCount;
+ SocketServerImpl(SocketSystemCore &core, NVFoundationBase &fnd, t_socket s, int port)
+ : m_SocketCore(core)
+ , m_Foundation(fnd)
+ , m_Socket(s)
+ , m_Port(port)
+ , m_Timeout(10000)
+ , mRefCount(0)
+ {
+ }
+
+ ~SocketServerImpl() { socket_destroy(&m_Socket); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ int port() override { return m_Port; }
+
+ void setTimeout(QT3DSU32 milliseconds) override { m_Timeout = milliseconds; }
+
+ NVScopedRefCounted<SocketStream> nextClient() override
+ {
+ SA daddr;
+ memset(&daddr, 0, sizeof(daddr));
+ t_socket new_socket;
+ int errcode = socket_accept(&m_Socket, &new_socket, NULL, NULL, m_Timeout);
+
+ if (is_socket_error(errcode)) {
+ return NVScopedRefCounted<SocketStream>();
+ } else if (errcode == IO_DONE) {
+ return QT3DS_NEW(m_Foundation.getAllocator(),
+ SocketStreamImpl)(*m_SocketCore, m_Foundation, new_socket, daddr);
+ }
+ return NVScopedRefCounted<SocketStream>();
+ }
+};
+
+struct SocketSystemImpl : public SocketSystem
+{
+ NVScopedRefCounted<SocketSystemCore> m_SocketCore;
+ NVFoundationBase &m_Foundation;
+ QT3DSI32 mRefCount;
+ SocketSystemImpl(SocketSystemCore &core, NVFoundationBase &fnd)
+ : m_SocketCore(core)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+
+ {
+ }
+ ~SocketSystemImpl() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ NVScopedRefCounted<SocketStream> createStream(const char *host, QT3DSI32 port,
+ QT3DSU32 timeoutMilliseconds) override
+ {
+ t_socket newSocket(SOCKET_INVALID);
+ int errcode = socket_create(&newSocket, PF_INET, SOCK_STREAM, 0);
+ if (is_socket_error(errcode)) {
+ qCWarning(WARNING, "Error during connect: %s", generalized_strerror(errcode));
+ return NVScopedRefCounted<SocketStream>();
+ }
+ SA remoteAddr;
+ memset(&remoteAddr, 0, sizeof(SA));
+ errcode = inet_tryconnect(&newSocket, host, (unsigned short)port, timeoutMilliseconds,
+ &remoteAddr);
+ if (is_socket_error(errcode)) {
+ qCWarning(WARNING, "Error during connect: %s", generalized_strerror(errcode));
+ return NVScopedRefCounted<SocketStream>();
+ } else if (errcode == IO_DONE) {
+ return QT3DS_NEW(m_Foundation.getAllocator(),
+ SocketStreamImpl)(*m_SocketCore, m_Foundation, newSocket, remoteAddr);
+ }
+ return NVScopedRefCounted<SocketStream>();
+ }
+
+ NVScopedRefCounted<SocketServer> createServer(QT3DSI32 port) override
+ {
+ t_socket newSocket(SOCKET_INVALID);
+ int errcode = socket_create(&newSocket, PF_INET, SOCK_STREAM, 0);
+ if (is_socket_error(errcode)) {
+ qCWarning(WARNING, "Error during create server create socket: %s",
+ generalized_strerror(errcode));
+ return NVScopedRefCounted<SocketServer>();
+ }
+ errcode = inet_trybind(&newSocket, "*", (unsigned short)port);
+ if (is_socket_error(errcode)) {
+ qCWarning(WARNING, "Error during create server bind: %s",
+ generalized_strerror(errcode));
+ return NVScopedRefCounted<SocketServer>();
+ } else if (errcode == IO_DONE) {
+ errcode = socket_listen(&newSocket, 10);
+ if (errcode == IO_DONE) {
+ return QT3DS_NEW(m_Foundation.getAllocator(),
+ SocketServerImpl)(*m_SocketCore, m_Foundation, newSocket, port);
+ } else
+ qCWarning(WARNING, "Error during create server listen: %s",
+ generalized_strerror(errcode));
+ }
+ return NVScopedRefCounted<SocketServer>();
+ }
+};
+}
+
+NVScopedRefCounted<SocketStream>
+SocketStream::CreateFileStream(NVFoundationBase &fnd, const char *fname, FileOpenFlags flags)
+{
+ return QT3DS_NEW(fnd.getAllocator(), FileSocketStreamImpl)(fnd, fname, flags);
+}
+
+NVScopedRefCounted<SocketSystem> SocketSystem::createSocketSystem(NVFoundationBase &fnd)
+{
+ NVScopedRefCounted<SocketSystemCore> theCore = SocketSystemCore::Create(fnd);
+ if (theCore) {
+ return QT3DS_NEW(fnd.getAllocator(), SocketSystemImpl)(*theCore, fnd);
+ }
+ return NVScopedRefCounted<SocketSystem>();
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/StringTable.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/StringTable.cpp
new file mode 100644
index 00000000..cc1274de
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/StringTable.cpp
@@ -0,0 +1,670 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Utils.h"
+#include "EASTL/string.h"
+#include "EASTL/sort.h"
+#include "foundation/StrConvertUTF.h"
+#include "foundation/PreAllocatedAllocator.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/Qt3DSMutex.h"
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace eastl;
+
+namespace eastl {
+struct SCharAndHash
+{
+ const char8_t *m_Data;
+ size_t m_Hash;
+ // Cache the generated hash code.
+ SCharAndHash(const char8_t *inData)
+ : m_Data(inData)
+ , m_Hash(eastl::hash<const char8_t *>()(inData))
+ {
+ }
+ SCharAndHash()
+ : m_Data(NULL)
+ , m_Hash(0)
+ {
+ }
+ operator const char *() const { return m_Data; }
+};
+template <>
+struct hash<SCharAndHash>
+{
+ size_t operator()(const SCharAndHash &inItem) const { return inItem.m_Hash; }
+};
+
+template <>
+struct equal_to<SCharAndHash>
+{
+ bool operator()(const SCharAndHash &inLhs, const SCharAndHash &inRhs) const
+ {
+ return char_equal_to()(inLhs.m_Data, inRhs.m_Data);
+ }
+};
+}
+
+void CRegisteredString::Remap(const IStringTable &inTable)
+{
+ Remap(const_cast<IStringTable &>(inTable).GetRemapMap());
+}
+
+void CRegisteredString::Remap(const SStrRemapMap &inMap)
+{
+ if (IsValid()) {
+ SStrRemapMap::const_iterator theIter = inMap.find((char8_t *)m_String);
+ if (theIter != inMap.end())
+ m_String = reinterpret_cast<const char8_t *>(theIter->second);
+ else {
+ QT3DS_ASSERT(false);
+ // Ensure a failure here doesn't *guarantee* a crash somewhere else.
+ m_String = NULL;
+ }
+ } else {
+ // Indicates an invalid string.
+ m_String = reinterpret_cast<const char8_t *>(QT3DS_MAX_U32);
+ }
+}
+
+void CRegisteredString::Remap(NVDataRef<QT3DSU8> inDataPtr)
+{
+ size_t theOffset = reinterpret_cast<size_t>(m_String);
+ if (theOffset >= QT3DS_MAX_U32)
+ m_String = "";
+ else {
+ if (theOffset < inDataPtr.size())
+ m_String = reinterpret_cast<char8_t *>(inDataPtr.begin() + theOffset);
+ else {
+ QT3DS_ASSERT(false);
+ m_String = "";
+ }
+ }
+}
+
+namespace {
+
+const char16_t g_char16EmptyStr[] = { 0, 0, 0, 0 };
+const char32_t g_char32EmptyStr[] = { 0, 0, 0, 0 };
+
+typedef eastl::basic_string<char8_t, ForwardingAllocator> TNarrowStr;
+typedef eastl::basic_string<TWCharEASTLConverter::TCharType, ForwardingAllocator> TWideStr;
+
+inline bool isTrivialWide(const wchar_t *str)
+{
+ return str == NULL || *str == 0;
+}
+
+QT3DSU8 *AlignPointer(QT3DSU8 *inStart, QT3DSU8 *inPtr)
+{
+ QT3DSU32 alignment = sizeof(void *);
+ size_t numBytes = (size_t)(inPtr - inStart);
+ QT3DS_ASSERT(inStart < inPtr);
+ if (numBytes % alignment)
+ inPtr += alignment - (numBytes % alignment);
+ return inPtr;
+}
+
+QT3DSU32 Align(QT3DSU32 inValue)
+{
+ QT3DSU32 alignment = sizeof(void *);
+ QT3DSU32 leftover = inValue % alignment;
+ if (leftover)
+ inValue += alignment - leftover;
+ return inValue;
+}
+
+// Structure that is written out to the file.
+// Directly after this is the string character data.
+// TWideStr& inConvertStr
+struct SStringFileData
+{
+ QT3DSU32 m_StartOffset;
+ QT3DSU32 m_StrLen;
+ QT3DSU32 m_Handle;
+ char8_t *m_Str;
+ SStringFileData(QT3DSU32 len, QT3DSU32 off, QT3DSU32 handle, char8_t *data)
+ : m_StartOffset(off)
+ , m_StrLen(len)
+ , m_Handle(handle)
+ , m_Str(data)
+ {
+ }
+ SStringFileData()
+ : m_StartOffset(0)
+ , m_StrLen(0)
+ , m_Handle(0)
+ , m_Str(NULL)
+ {
+ }
+ void Deallocate(NVAllocatorCallback &inAlloc)
+ {
+ inAlloc.deallocate(m_Str);
+ m_Str = NULL;
+ }
+ const char8_t *GetNarrow() { return m_Str; }
+ operator CRegisteredString() const
+ {
+ return CRegisteredString::ISwearThisHasBeenRegistered(m_Str);
+ }
+ QT3DSU32 EndOffset() const { return m_StartOffset + m_StrLen; }
+
+ // Used only for the lower bound operation to find a given object by offset.
+ bool operator<(const SStringFileData &inOther) const
+ {
+ return m_StartOffset < inOther.m_StartOffset;
+ }
+};
+
+struct SCharAndHandle
+{
+ const char8_t *m_Data;
+ QT3DSU32 m_Handle;
+ SCharAndHandle()
+ : m_Data(NULL)
+ , m_Handle(0)
+ {
+ }
+ SCharAndHandle(const char8_t *data, QT3DSU32 hdl)
+ : m_Data(data)
+ , m_Handle(hdl)
+ {
+ }
+ operator const char *() const { return m_Data; }
+};
+
+struct SStringFileHeader
+{
+ QT3DSU32 m_NumStrings;
+ QT3DSU32 m_NextHandleValue;
+ // offset to the items of fixed size. Variable sized data is stored
+ // up front.
+ QT3DSU32 m_FixedBufferOffset;
+ SStringFileHeader()
+ : m_NumStrings(0)
+ , m_NextHandleValue(0)
+ , m_FixedBufferOffset(0)
+ {
+ }
+
+ SStringFileHeader(QT3DSU32 ns, QT3DSU32 hv, QT3DSU32 fbo)
+ : m_NumStrings(ns)
+ , m_NextHandleValue(hv)
+ , m_FixedBufferOffset(fbo)
+ {
+ }
+};
+
+// This is the core of the string table.
+struct SStringFileDataList
+{
+ typedef nvhash_map<SCharAndHash, SCharAndHandle> TMapType;
+ typedef nvhash_map<QT3DSU32, const char8_t *> THandleMapType;
+
+ mutable SPreAllocatedAllocator m_Allocator;
+
+ // When we load from a file, we get a these items
+ NVConstDataRef<SStringFileData> m_DataBlock;
+ NVConstDataRef<eastl::pair<size_t, QT3DSU32>> m_HashDataBlockOffset;
+ NVConstDataRef<eastl::pair<QT3DSU32, QT3DSU32>> m_HandleDataBlockOffset;
+
+ // When we are running normally, this items get mangled
+ nvvector<SStringFileData> m_AppendedStrings;
+
+protected:
+ // Built roughly on demand
+ SStrRemapMap m_StrRemapMap;
+ TMapType m_HashToStrMap;
+ THandleMapType m_HandleToStrMap;
+ QT3DSU32 m_NextHandleValue;
+
+public:
+ SStringFileDataList(NVAllocatorCallback &inAlloc)
+ : m_Allocator(inAlloc)
+ , m_AppendedStrings(inAlloc, "StringTable::m_AppendedStrings")
+ , m_StrRemapMap(inAlloc, "StringTable::m_StrRemapMap")
+ , m_HashToStrMap(inAlloc, "StringTable::m_HashToStrMap")
+ , m_HandleToStrMap(inAlloc, "StringTable::m_HashToStrMap")
+ , m_NextHandleValue(1)
+ {
+ }
+ ~SStringFileDataList()
+ {
+ for (QT3DSU32 idx = 0, end = m_AppendedStrings.size(); idx < end; ++idx)
+ m_AppendedStrings[idx].Deallocate(m_Allocator);
+ }
+
+ SStrRemapMap &GetRemapMap()
+ {
+ if (m_StrRemapMap.empty()) {
+ for (QT3DSU32 idx = 0, end = m_DataBlock.size(); idx < end; ++idx)
+ m_StrRemapMap.insert(
+ eastl::make_pair(m_DataBlock[idx].m_Str, m_DataBlock[idx].m_StartOffset));
+ for (QT3DSU32 idx = 0, end = m_AppendedStrings.size(); idx < end; ++idx)
+ m_StrRemapMap.insert(eastl::make_pair(m_AppendedStrings[idx].m_Str,
+ m_AppendedStrings[idx].m_StartOffset));
+ }
+ return m_StrRemapMap;
+ }
+
+ struct SHashPairComparator
+ {
+ bool operator()(const eastl::pair<size_t, QT3DSU32> &lhs,
+ const eastl::pair<size_t, QT3DSU32> &rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+ };
+
+ struct SHandlePairComparator
+ {
+ bool operator()(const eastl::pair<QT3DSU32, QT3DSU32> &lhs,
+ const eastl::pair<QT3DSU32, QT3DSU32> &rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+ };
+
+ SCharAndHandle DoFindStr(SCharAndHash hashCode)
+ {
+ if (isTrivial(hashCode.m_Data))
+ return SCharAndHandle();
+ TMapType::iterator theFind = m_HashToStrMap.find(hashCode);
+ if (theFind == m_HashToStrMap.end()) {
+ SCharAndHandle newStr = FindStrByHash(hashCode);
+ if (!newStr.m_Data)
+ newStr = Append(hashCode);
+
+ // It may not be obvious why we have to reset the data member.
+ // we have to do this so the hashtable keys don't change if the user isn't
+ // passing in a persistent string.
+ hashCode.m_Data = newStr;
+
+ theFind = m_HashToStrMap.insert(eastl::make_pair(hashCode, newStr)).first;
+ m_HandleToStrMap.insert(eastl::make_pair(theFind->second.m_Handle, newStr));
+ }
+ return theFind->second;
+ }
+
+ const CRegisteredString FindStr(SCharAndHash hashCode)
+ {
+ SCharAndHandle result = DoFindStr(hashCode);
+ if (result.m_Data)
+ return CRegisteredString::ISwearThisHasBeenRegistered(result.m_Data);
+ return CRegisteredString();
+ }
+
+ const CStringHandle FindStrHandle(SCharAndHash hashCode)
+ {
+ SCharAndHandle result = DoFindStr(hashCode);
+ return CStringHandle::ISwearThisHasBeenRegistered(result.m_Handle);
+ }
+
+ const CRegisteredString FindStrByHandle(QT3DSU32 handle)
+ {
+ if (handle == 0)
+ return CRegisteredString();
+
+ THandleMapType::iterator theFind = m_HandleToStrMap.find(handle);
+ if (theFind == m_HandleToStrMap.end()) {
+ const char8_t *newStr = FindStrByHandleData(handle);
+ if (!newStr)
+ return CRegisteredString();
+ theFind = m_HandleToStrMap.insert(eastl::make_pair(handle, newStr)).first;
+ }
+ return CRegisteredString::ISwearThisHasBeenRegistered(theFind->second);
+ }
+
+ void Save(SWriteBuffer &ioBuffer) const
+ {
+ // Buffer should be aligned before we get to it.
+ QT3DS_ASSERT(ioBuffer.size() % sizeof(void *) == 0);
+
+ QT3DSU32 numStrs = Size();
+ size_t bufferBegin = ioBuffer.size();
+ SStringFileHeader theHeader;
+ ioBuffer.write(theHeader);
+ QT3DSU32 startOffset = ioBuffer.size();
+
+ eastl::vector<eastl::pair<size_t, QT3DSU32>> hashToStringIndex;
+ eastl::vector<eastl::pair<QT3DSU32, QT3DSU32>> handleToStringIndex;
+ hashToStringIndex.reserve(numStrs);
+ handleToStringIndex.reserve(numStrs);
+ WriteStringBlockData(m_DataBlock.begin(), m_DataBlock.end(), ioBuffer, hashToStringIndex,
+ handleToStringIndex);
+ WriteStringBlockData(m_AppendedStrings.data(),
+ m_AppendedStrings.data() + m_AppendedStrings.size(), ioBuffer,
+ hashToStringIndex, handleToStringIndex);
+ ioBuffer.align(4);
+
+ QT3DSU32 fixedOffset = ioBuffer.size() - startOffset;
+ WriteStringBlock(m_DataBlock.begin(), m_DataBlock.end(), ioBuffer);
+ WriteStringBlock(m_AppendedStrings.data(),
+ m_AppendedStrings.data() + m_AppendedStrings.size(), ioBuffer);
+
+ // sort by hash code so we can do binary lookups later.
+ eastl::sort(hashToStringIndex.begin(), hashToStringIndex.end(), SHashPairComparator());
+ ioBuffer.write(hashToStringIndex.data(), (QT3DSU32)hashToStringIndex.size());
+
+ eastl::sort(handleToStringIndex.begin(), handleToStringIndex.end(),
+ SHandlePairComparator());
+ ioBuffer.write(handleToStringIndex.data(), (QT3DSU32)handleToStringIndex.size());
+
+ SStringFileHeader *fixedOffsetPtr =
+ reinterpret_cast<SStringFileHeader *>(ioBuffer.begin() + bufferBegin);
+ *fixedOffsetPtr = SStringFileHeader(numStrs, m_NextHandleValue, fixedOffset);
+ }
+
+ void Load(NVDataRef<QT3DSU8> inMemory)
+ {
+ QT3DS_ASSERT(m_AppendedStrings.empty());
+ m_Allocator.m_PreAllocatedBlock = inMemory;
+ m_Allocator.m_OwnsMemory = false;
+ SDataReader theReader(inMemory.begin(), inMemory.end());
+ SStringFileHeader theHeader = theReader.LoadRef<SStringFileHeader>();
+ QT3DSU32 numStrs = theHeader.m_NumStrings;
+ m_NextHandleValue = theHeader.m_NextHandleValue;
+ QT3DSU32 fixedOffset = theHeader.m_FixedBufferOffset;
+ theReader.m_CurrentPtr += fixedOffset;
+ m_DataBlock = NVConstDataRef<SStringFileData>(
+ reinterpret_cast<const SStringFileData *>(theReader.m_CurrentPtr), numStrs);
+ theReader.m_CurrentPtr += sizeof(SStringFileData) * numStrs;
+
+ m_HashDataBlockOffset = NVConstDataRef<eastl::pair<size_t, QT3DSU32>>(
+ reinterpret_cast<const eastl::pair<size_t, QT3DSU32> *>(theReader.m_CurrentPtr), numStrs);
+ theReader.m_CurrentPtr += sizeof(eastl::pair<size_t, QT3DSU32>) * numStrs;
+
+ m_HandleDataBlockOffset = NVConstDataRef<eastl::pair<QT3DSU32, QT3DSU32>>(
+ reinterpret_cast<const eastl::pair<QT3DSU32, QT3DSU32> *>(theReader.m_CurrentPtr), numStrs);
+
+ for (QT3DSU32 idx = 0, end = m_DataBlock.size(); idx < end; ++idx) {
+ SStringFileData &theData = const_cast<SStringFileData &>(m_DataBlock[idx]);
+ theData.m_Str = reinterpret_cast<char8_t *>(inMemory.mData + theData.m_StartOffset);
+ }
+ }
+
+protected:
+ // When we load from a file, we do not put every string into the hash because building
+ // hashtables takes
+ // time. We only put them into the hash on demand; this avoids building a giant hashtable upon
+ // load.
+ // and since in general we do not need to lookup all hash values again it avoids building the
+ // hashtable
+ // in general.
+ SCharAndHandle FindStrByHash(SCharAndHash hashCode) const
+ {
+ const eastl::pair<size_t, QT3DSU32> *iter =
+ eastl::lower_bound(m_HashDataBlockOffset.begin(), m_HashDataBlockOffset.end(),
+ eastl::make_pair(hashCode.m_Hash, (QT3DSU32)0), SHashPairComparator());
+
+ for (; iter != m_HashDataBlockOffset.end() && iter->first == hashCode.m_Hash; ++iter) {
+ if (AreEqual(m_DataBlock[iter->second].m_Str, hashCode.m_Data))
+ return SCharAndHandle(m_DataBlock[iter->second].m_Str,
+ m_DataBlock[iter->second].m_Handle);
+ }
+ return SCharAndHandle();
+ }
+
+ const char8_t *FindStrByHandleData(QT3DSU32 handle) const
+ {
+ const eastl::pair<QT3DSU32, QT3DSU32> *iter =
+ eastl::lower_bound(m_HandleDataBlockOffset.begin(), m_HandleDataBlockOffset.end(),
+ eastl::make_pair(handle, (QT3DSU32)0), SHandlePairComparator());
+
+ if (iter != m_HandleDataBlockOffset.end() && iter->first == handle
+ && m_DataBlock[iter->second].m_Handle == handle)
+ return m_DataBlock[iter->second].m_Str;
+ return NULL;
+ }
+
+ void WriteStringBlockData(const SStringFileData *begin, const SStringFileData *end,
+ SWriteBuffer &ioBuffer,
+ eastl::vector<eastl::pair<size_t, QT3DSU32>> &ioHashToStringIndex,
+ eastl::vector<eastl::pair<QT3DSU32, QT3DSU32>> &ioHandleToStringIndex) const
+ {
+ for (const SStringFileData *iter = begin; iter != end; ++iter) {
+ size_t idx = ioHashToStringIndex.size();
+ SCharAndHash theHash(iter->m_Str);
+ ioHashToStringIndex.push_back(eastl::make_pair(theHash.m_Hash, (QT3DSU32)idx));
+ ioHandleToStringIndex.push_back(eastl::make_pair(iter->m_Handle, (QT3DSU32)idx));
+ ioBuffer.write(iter->m_Str, iter->m_StrLen);
+ }
+ }
+
+ void WriteStringBlock(const SStringFileData *begin, const SStringFileData *end,
+ SWriteBuffer &ioBuffer) const
+ {
+ for (const SStringFileData *iter = begin; iter != end; ++iter)
+ ioBuffer.write(*iter);
+ }
+
+ SCharAndHandle Append(SCharAndHash inStrHash)
+ {
+ if (isTrivial(inStrHash.m_Data))
+ return SCharAndHandle();
+
+ const char8_t *inStr(inStrHash.m_Data);
+ QT3DSU32 len = (QT3DSU32)strlen(inStr) + 1;
+ char8_t *newStr = (char8_t *)m_Allocator.allocate(len, "StringData", __FILE__, __LINE__);
+ memCopy(newStr, inStr, len);
+
+ // We write the number of strings to the file just after the header.
+ QT3DSU32 theOffset = sizeof(SStringFileHeader);
+ if (Size())
+ theOffset = Back().EndOffset();
+
+ QT3DSU32 handleValue = m_NextHandleValue;
+ ++m_NextHandleValue;
+ m_AppendedStrings.push_back(SStringFileData(len, theOffset, handleValue, newStr));
+
+ // Only add to the str map if necessary because building it could be expensive.
+ if (m_StrRemapMap.empty() == false)
+ m_StrRemapMap.insert(eastl::make_pair(newStr, theOffset));
+
+ return SCharAndHandle(newStr, handleValue);
+ }
+ // precondition is that size != 0
+ const SStringFileData &Back() const
+ {
+ QT3DS_ASSERT(Size());
+
+ if (m_AppendedStrings.size()) {
+ return m_AppendedStrings.back();
+ } else {
+ return m_DataBlock[m_DataBlock.size() - 1];
+ }
+ }
+
+ QT3DSU32 Size() const { return static_cast<QT3DSU32>(m_AppendedStrings.size() + m_DataBlock.size()); }
+};
+
+struct SStringTableMutexScope
+{
+ Mutex *m_Mutex;
+ SStringTableMutexScope(Mutex *inM)
+ : m_Mutex(inM)
+ {
+ if (m_Mutex)
+ m_Mutex->lock();
+ }
+ ~SStringTableMutexScope()
+ {
+ if (m_Mutex)
+ m_Mutex->unlock();
+ }
+};
+
+#define STRING_TABLE_MULTITHREADED_METHOD SStringTableMutexScope __locker(m_MultithreadMutex)
+
+class StringTable : public IStringTable
+{
+ typedef nvhash_map<SCharAndHash, QT3DSU32> TMapType;
+ typedef nvhash_map<CRegisteredString, TWideStr> TNarrowToWideMapType;
+ SStringFileDataList m_FileData;
+ NVAllocatorCallback &m_Allocator;
+ TNarrowToWideMapType m_StrWideMap;
+ volatile QT3DSI32 mRefCount; // fnd's naming convention
+ eastl::basic_string<char8_t, ForwardingAllocator> m_ConvertBuffer;
+ TWideStr m_WideConvertBuffer;
+ Mutex m_MultithreadMutexBacker;
+ Mutex *m_MultithreadMutex;
+ // Data that will be written out to the file.
+
+public:
+ StringTable(NVAllocatorCallback &alloc)
+ : m_FileData(alloc)
+ , m_Allocator(m_FileData.m_Allocator)
+ , m_StrWideMap(alloc, "StringTable::m_StrWideMap")
+ , mRefCount(0)
+ , m_ConvertBuffer(ForwardingAllocator(alloc, "StringTable::m_ConvertBuffer"))
+ , m_WideConvertBuffer(ForwardingAllocator(alloc, "StringTable::m_WideConvertBuffer"))
+ , m_MultithreadMutexBacker(alloc)
+ , m_MultithreadMutex(NULL)
+ {
+ }
+
+ virtual ~StringTable() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_FileData.m_Allocator.m_Allocator)
+
+ void EnableMultithreadedAccess() override { m_MultithreadMutex = &m_MultithreadMutexBacker; }
+
+ void DisableMultithreadedAccess() override { m_MultithreadMutex = NULL; }
+
+ CRegisteredString RegisterStr(UICBCharPtr str) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ if (isTrivial(str))
+ return CRegisteredString();
+ return m_FileData.FindStr(str);
+ }
+
+ // utf-16->utf-8
+ CRegisteredString RegisterStr(const char16_t *str) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ ConvertUTF(str, 0, m_ConvertBuffer);
+ return RegisterStr(m_ConvertBuffer.c_str());
+ }
+ // utf-32->utf-8
+ CRegisteredString RegisterStr(const char32_t *str) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ ConvertUTF(str, 0, m_ConvertBuffer);
+ return RegisterStr(m_ConvertBuffer.c_str());
+ }
+
+ CRegisteredString RegisterStr(const wchar_t *str) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ if (isTrivialWide(str))
+ return CRegisteredString();
+ ConvertUTF(reinterpret_cast<const TWCharEASTLConverter::TCharType *>(str), 0,
+ m_ConvertBuffer);
+ return RegisterStr(m_ConvertBuffer.c_str());
+ }
+
+ CStringHandle GetHandle(UICBCharPtr str) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ return m_FileData.FindStrHandle(str);
+ }
+
+ CRegisteredString HandleToStr(QT3DSU32 strHandle) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ return m_FileData.FindStrByHandle(strHandle);
+ }
+
+ const wchar_t *GetWideStr(CRegisteredString theStr)
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ eastl::pair<TNarrowToWideMapType::iterator, bool> pair_iter = m_StrWideMap.insert(
+ eastl::make_pair(theStr, TWideStr(ForwardingAllocator(m_Allocator, "WideString"))));
+ if (pair_iter.second)
+ ConvertUTF(theStr.c_str(), 0, pair_iter.first->second);
+ return reinterpret_cast<const wchar_t *>(pair_iter.first->second.c_str());
+ }
+
+ const wchar_t *GetWideStr(UICBCharPtr src) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ if (isTrivial(src))
+ return L"";
+ return GetWideStr(RegisterStr(src));
+ }
+
+ const wchar_t *GetWideStr(const wchar_t *str) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ if (isTrivialWide(str))
+ return L"";
+ ConvertUTF(reinterpret_cast<const TWCharEASTLConverter::TCharType *>(str), 0,
+ m_ConvertBuffer);
+ return GetWideStr(RegisterStr(m_ConvertBuffer.c_str()));
+ }
+
+ const SStrRemapMap &GetRemapMap() override { return m_FileData.GetRemapMap(); }
+
+ NVAllocatorCallback &GetAllocator() override { return m_FileData.m_Allocator.m_Allocator; }
+
+ // Save to a block of memory. It is up the callers to deallocate using allocator
+ // from GetAllocator(). Returns a remap map that takes existing strings and changes their
+ // address such that they are offsets into the block of memory where this object
+ // started saving. Returns a map that converts registered strings into offsets of the
+ // written buffer.
+ void Save(SWriteBuffer &ioBuffer) const override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ m_FileData.Save(ioBuffer);
+ }
+
+ // Load all the strings from inMemory. inMemory is not freed by this object
+ // Finally, you will need to take inMemory and call remap on all strings
+ // from offsets back into their correct address into inMemory.
+ void Load(qt3ds::foundation::NVDataRef<QT3DSU8> inMemory) override
+ {
+ STRING_TABLE_MULTITHREADED_METHOD;
+ m_FileData.Load(inMemory);
+ }
+};
+}
+
+const char16_t *char16EmptyStr = g_char16EmptyStr;
+const char32_t *char32EmptyStr = g_char32EmptyStr;
+
+IStringTable &IStringTable::CreateStringTable(NVAllocatorCallback &alloc)
+{
+ return *QT3DS_NEW(alloc, StringTable)(alloc);
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/XML.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/XML.cpp
new file mode 100644
index 00000000..8db06511
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/XML.cpp
@@ -0,0 +1,1008 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/XML.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "foundation/IOStreams.h"
+#include "foundation/StringConversionImpl.h"
+#include "foundation/StrConvertUTF.h"
+#include "foundation/StringTable.h"
+#include "foundation/Utils.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/hash_map.h"
+#include "utf8.h"
+
+#ifdef QT3DS_VC
+#include <windows.h> //output debug string
+#endif
+
+#include <QtCore/qxmlstream.h>
+
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::intrinsics;
+
+typedef char XML_Char;
+
+namespace {
+
+const QT3DSU16 g_BOMMarker = (QT3DSU16)0xFEFF;
+
+// Some DOM parsing operations are destructive. If you need
+// them to not be destructive, then we need to modify
+// the reader. Specifically parsing lists of floats, due
+// to a bug in strtod, is destructive.
+struct SDOMReader : public IDOMReader
+{
+ SReaderScope m_TopElement;
+ eastl::vector<SReaderScope> m_ScopeStack;
+ NVScopedRefCounted<IDOMFactory> m_Factory;
+ volatile QT3DSI32 mRefCount;
+
+ SDOMReader(NVAllocatorCallback &inAlloc, SDOMElement &te, NVScopedRefCounted<IStringTable> s,
+ NVScopedRefCounted<IDOMFactory> inFactory)
+ : IDOMReader(inAlloc, s)
+ , m_TopElement(&te)
+ , m_Factory(inFactory)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Factory->GetAllocator())
+
+ SDOMElement *Current() const { return m_TopElement.m_Element; }
+
+ void PushScope() override { m_ScopeStack.push_back(SReaderScope(m_TopElement)); }
+
+ void PopScope() override
+ {
+ if (m_ScopeStack.size()) {
+ m_TopElement = m_ScopeStack.back();
+ m_ScopeStack.pop_back();
+ } else
+ m_TopElement = SReaderScope();
+ }
+
+ SReaderScope GetScope() override { return m_TopElement; }
+
+ void SetScope(SReaderScope inScope) override { m_TopElement = inScope; }
+
+ SDOMElement *GetElement() const override { return m_TopElement.m_Element; }
+
+ Option<CRegisteredString> RegisterNS(TXMLCharPtr ns)
+ {
+ if (ns) {
+ return m_StringTable->RegisterStr(ns);
+ }
+ return Empty();
+ }
+
+ bool UnregisteredAtt(TXMLCharPtr name, TXMLCharPtr &outValue, TXMLCharPtr ns = NULL) override
+ {
+ outValue = "";
+ SDOMElement *current(Current());
+ if (current) {
+ return current->AttValue(m_StringTable->RegisterStr(name), RegisterNS(ns), outValue);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ bool Att(TXMLCharPtr name, CRegisteredString &outValue, TXMLCharPtr ns = NULL) override
+ {
+ const char8_t *unregValue = NULL;
+ if (UnregisteredAtt(name, unregValue, ns)) {
+ outValue = m_StringTable->RegisterStr(unregValue);
+ return true;
+ }
+ return false;
+ }
+
+ QT3DSU32 CountChildren(TXMLCharPtr childName = NULL, TXMLCharPtr ns = NULL) override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ return elem->GetNumChildren(m_StringTable->RegisterStr(childName), RegisterNS(ns));
+ }
+
+ SDOMAttribute *CurrentAtt()
+ {
+ if (m_TopElement.m_Attribute)
+ return m_TopElement.m_Attribute;
+ return NULL;
+ }
+
+ SDOMAttribute *GetFirstAttribute() override
+ {
+ if (m_TopElement.m_Element)
+ m_TopElement.m_Attribute = m_TopElement.m_Element->m_Attributes.m_Head;
+ return m_TopElement.m_Attribute;
+ }
+
+ SDOMAttribute *GetNextAttribute() override
+ {
+ if (m_TopElement.m_Attribute)
+ m_TopElement.m_Attribute = m_TopElement.m_Attribute->m_NextAttribute;
+ return CurrentAtt();
+ }
+
+ bool MoveToFirstChild(TXMLCharPtr childName = NULL, TXMLCharPtr ns = NULL) override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ SDOMElement *child = elem->FindChild(m_StringTable->RegisterStr(childName), RegisterNS(ns));
+ if (child != NULL) {
+ m_TopElement = child;
+ return true;
+ }
+ return false;
+ }
+
+ bool MoveToNextSibling(TXMLCharPtr childName = NULL, TXMLCharPtr ns = NULL) override
+ {
+ SDOMElement *elem = Current();
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ SDOMElement *nextSibling =
+ elem->FindSibling(m_StringTable->RegisterStr(childName), RegisterNS(ns));
+ if (nextSibling) {
+ m_TopElement = nextSibling;
+ return true;
+ }
+ return false;
+ }
+ // Leave element means go to its parent.
+ void Leave() override
+ {
+ QT3DS_ASSERT(m_TopElement.m_Element);
+ if (m_TopElement.m_Element)
+ m_TopElement = m_TopElement.m_Element->m_Parent;
+ }
+
+ bool Value(TXMLCharPtr &outValue) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ outValue = current->m_Value;
+ return true;
+ }
+
+ SDOMElement *GetTopElement() override
+ {
+ SDOMElement *current(Current());
+ while (current && current->m_Parent)
+ current = current->m_Parent;
+ return current;
+ }
+
+ virtual NVScopedRefCounted<IDOMFactory> GetFactory() { return m_Factory; }
+};
+
+struct SDOMWriter : public IDOMWriter, public SDOMReader
+{
+ NVScopedRefCounted<IDOMFactory> m_FactoryPtr;
+ IDOMFactory &m_Factory;
+
+ SDOMWriter(NVScopedRefCounted<IDOMFactory> inDOMFactory,
+ NVScopedRefCounted<IStringTable> inStringTable, SDOMElement &inTopElem)
+ : SDOMReader(inDOMFactory->GetAllocator(), inTopElem, inStringTable, *inDOMFactory)
+ , m_FactoryPtr(inDOMFactory)
+ , m_Factory(*inDOMFactory)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Factory.GetAllocator())
+
+ void Begin(TXMLCharPtr inElemName, TXMLCharPtr inNamespace = NULL, int inLine = 0) override
+ {
+ if (!m_TopElement.m_Element) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SDOMElement *current(Current());
+ SDOMElement *newElement(m_Factory.NextElement(m_StringTable->RegisterStr(inElemName),
+ m_StringTable->RegisterStr(inNamespace),
+ inLine));
+ current->AppendChild(*newElement);
+ m_TopElement = newElement;
+ }
+
+ void Att(TXMLCharPtr name, TXMLCharPtr value, TXMLCharPtr ns, int inLine) override
+ {
+ if (!m_TopElement.m_Element) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_TopElement.m_Element->SetAttributeValue(m_StringTable->RegisterStr(name), RegisterNS(ns),
+ value, m_Factory, inLine);
+ }
+
+ void Value(TXMLCharPtr value) override
+ {
+ if (!m_TopElement.m_Element) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (value == NULL)
+ value = "";
+ size_t len = strlen(value);
+ m_Factory.AppendStrBuf(value, (QT3DSU32)len);
+ m_TopElement.m_Element->m_Value = m_Factory.FinalizeStrBuf();
+ }
+
+ void End() override
+ {
+ if (!m_TopElement.m_Element) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ Leave();
+ }
+ void RemoveCurrent() override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (current->m_Parent) {
+ m_TopElement = current->m_Parent;
+ m_TopElement.m_Element->RemoveChild(*current);
+ }
+ }
+ void RemoveAttribute(TXMLCharPtr inItem, TXMLCharPtr inNamespace) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ current->RemoveAttribute(m_StringTable->RegisterStr(inItem), RegisterNS(inNamespace));
+ }
+
+ void MoveBefore(TXMLCharPtr inItem, TXMLCharPtr inSibling, TXMLCharPtr inNs = NULL) override
+ {
+ SDOMElement *current(Current());
+ if (!current) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ SDOMElement *theItem =
+ current->FindChild(m_StringTable->RegisterStr(inItem), RegisterNS(inNs));
+ SDOMElement *theSibling =
+ current->FindChild(m_StringTable->RegisterStr(inSibling), RegisterNS(inNs));
+ QT3DS_ASSERT(theItem && theSibling);
+ if (theItem && theSibling)
+ current->PrependChild(*theItem, theSibling);
+ }
+
+ // If current has no parent, then we are at the top
+ // of the tree and we should return 0. Or if there is no
+ // current.
+ // If there is one parent, we should return 1.
+ QT3DSU32 GetTabs() override
+ {
+ QT3DSU32 retval = 0;
+ SDOMElement *current(Current());
+ do {
+ if (current)
+ current = current->m_Parent;
+ if (current)
+ ++retval;
+ } while (current);
+ return retval;
+ }
+
+ SDOMElement *GetTopElement() override { return SDOMReader::GetTopElement(); }
+
+ NVScopedRefCounted<IDOMFactory> GetFactory() override { return m_FactoryPtr; }
+
+ NVAllocatorCallback &GetAllocator() override { return m_Factory.GetAllocator(); }
+};
+
+struct SimpleXmlWriter
+{
+
+ struct SNameNS
+ {
+ TXMLCharPtr name;
+ TXMLCharPtr ns;
+ SNameNS(TXMLCharPtr _name = NULL, TXMLCharPtr _ns = NULL)
+ : name(_name)
+ , ns(_ns)
+ {
+ }
+ };
+ IOutStream &m_Stream;
+ eastl::vector<eastl::pair<SNameNS, bool>> m_OpenElements;
+ bool m_ElementOpen;
+ char8_t m_PrintBuf[256];
+ QT3DSU32 m_Tabs;
+ eastl::basic_string<char8_t, ForwardingAllocator> m_Buffer;
+
+ SimpleXmlWriter(NVAllocatorCallback &inAlloc, IOutStream &stream, QT3DSU32 inTabs = 0)
+ : m_Stream(stream)
+ , m_ElementOpen(false)
+ , m_Tabs(inTabs)
+ , m_Buffer(ForwardingAllocator(inAlloc, "SimpleXMLWriter::m_Buffer"))
+ {
+ }
+
+ void Write(const SNameNS &data)
+ {
+ if (data.ns && *data.ns) {
+ Write(data.ns);
+ Write(':');
+ }
+ Write(data.name);
+ }
+
+ void Write(const char8_t *data, QT3DSU32 inLen = 0)
+ {
+ if (!isTrivial(data)) {
+ if (inLen == 0)
+ inLen = StrLen(data);
+ m_Stream.Write(data, inLen);
+ }
+ }
+ void BeginWrite() { m_Buffer.clear(); }
+ void WriteTemp(char8_t data) { m_Buffer.append(1, data); }
+ void WriteTemp(const char8_t *data) { m_Buffer.append(data); }
+ void EndWrite() { Write(reinterpret_cast<const char8_t *>(m_Buffer.c_str()), m_Buffer.size()); }
+ void Write(char8_t data) { m_Stream.Write(data); }
+ void Tabs()
+ {
+ UICBASE_FOREACH(idx, (m_OpenElements.size() + m_Tabs))
+ Write('\t');
+ }
+ void Close(bool newline)
+ {
+ if (m_ElementOpen) {
+ Write(">");
+ if (newline)
+ Write('\n');
+ }
+ m_ElementOpen = false;
+ }
+ void Begin(TXMLCharPtr name, TXMLCharPtr ns)
+ {
+ Close(true);
+ Tabs();
+ Write('<');
+ SNameNS theName(name, ns);
+ Write(theName);
+ m_OpenElements.push_back(eastl::pair<SNameNS, bool>(theName, false));
+ m_ElementOpen = true;
+ }
+ TXMLCharPtr ToStr(char8_t val)
+ {
+ m_PrintBuf[0] = val;
+ m_PrintBuf[1] = 0;
+ return m_PrintBuf;
+ }
+ template <typename TDataType>
+ TXMLCharPtr ToStr(TDataType val)
+ {
+ StringConversion<TDataType>().ToStr(val, NVDataRef<char8_t>(m_PrintBuf, 256));
+ return m_PrintBuf;
+ }
+ void Att(TXMLCharPtr name, TXMLCharPtr ns, TXMLCharPtr value)
+ {
+ QT3DS_ASSERT(m_ElementOpen);
+ Write(' ');
+ Write(SNameNS(name, ns));
+
+ Write("=\"");
+ size_t valueLen = strlen(nonNull(value));
+ TXMLCharPtr start = value;
+ TXMLCharPtr end = value + valueLen;
+ TXMLCharPtr last = start;
+ uint32_t item = 0;
+ // Write out the data escaping unicode values where necessary
+ // I am using utf8::internal because it returns an error code and does not through
+ // exceptions; we don't always know the system we are running on will support or handle
+ // exceptions gracefully.
+ for (utf8::internal::utf_error err_code = utf8::internal::validate_next(start, end, item);
+ last != end && err_code == utf8::internal::UTF8_OK;
+ err_code = utf8::internal::validate_next(start, end, item)) {
+ switch (item) {
+ case '\r':
+ break;
+ case '\n':
+ Write("&#10;");
+ break;
+ case '\t':
+ Write("&#09;");
+ break;
+ case '<':
+ Write("&lt;");
+ break;
+ case '>':
+ Write("&gt;");
+ break;
+ case '"':
+ Write("&quot;");
+ break;
+ case '&':
+ Write("&amp;");
+ break;
+ default:
+ m_Stream.Write(NVConstDataRef<QT3DSU8>((const QT3DSU8 *)last, (QT3DSU32)(start - last)));
+ break;
+ }
+ last = start;
+ }
+ Write("\"");
+ }
+ template <typename TData>
+ void Att(TXMLCharPtr name, TXMLCharPtr ns, TData value)
+ {
+ Att(name, ns, ToStr(value));
+ }
+
+ void Value(TXMLCharPtr value)
+ {
+ if (!isTrivial(value)) {
+ Close(false);
+ size_t valueLen = strlen(nonNull(value));
+ TXMLCharPtr start = value;
+ TXMLCharPtr end = value + valueLen;
+ TXMLCharPtr last = start;
+ uint32_t item = 0;
+ // Write out the data escaping unicode values where necessary
+ for (utf8::internal::utf_error err_code =
+ utf8::internal::validate_next(start, end, item);
+ last != end && err_code == utf8::internal::UTF8_OK;
+ err_code = utf8::internal::validate_next(start, end, item)) {
+ switch (item) {
+ case '<':
+ Write("&lt;");
+ break;
+ case '>':
+ Write("&gt;");
+ break;
+ case '&':
+ Write("&amp;");
+ break;
+ default:
+ m_Stream.Write(NVConstDataRef<QT3DSU8>((const QT3DSU8 *)last, (QT3DSU32)(start - last)));
+ break;
+ }
+ last = start;
+ }
+ m_OpenElements.back().second = true;
+ }
+ }
+ void ChildValue(TXMLCharPtr name, TXMLCharPtr ns, TXMLCharPtr value)
+ {
+ Begin(name, ns);
+ Value(value);
+ End();
+ }
+ void End(bool newlineAfterClose = true)
+ {
+ QT3DS_ASSERT(m_OpenElements.size());
+ eastl::pair<SNameNS, bool> topElem = m_OpenElements.back();
+ m_OpenElements.pop_back();
+ if (m_ElementOpen)
+ Write("/>");
+ else {
+ if (topElem.second == false)
+ Tabs();
+ Write("</");
+ Write(topElem.first);
+ Write(">");
+ }
+ m_ElementOpen = false;
+ if (newlineAfterClose == true)
+ Write('\n');
+ }
+};
+
+struct DOMParser
+{
+ IDOMFactory &m_Factory;
+ SDOMElement *m_TopElement;
+ SDOMElement *m_FirstElement;
+ char8_t m_nsSeparator;
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+ TStrType m_NSBuffer;
+ TStrType m_NameBuffer;
+ CRegisteredString m_RegName;
+ CRegisteredString m_RegNS;
+ SNamespacePairNode *m_FirstPair;
+ SNamespacePairNode *m_LastPair;
+ QXmlStreamReader *m_XMLParser;
+
+ DOMParser(IDOMFactory &factory, QXmlStreamReader &parser, char8_t nsSeparator)
+ : m_Factory(factory)
+ , m_FirstElement(NULL)
+ , m_nsSeparator(nsSeparator)
+ , m_NSBuffer(ForwardingAllocator(factory.GetAllocator(), "DOMParser::m_NSBuffer"))
+ , m_NameBuffer(ForwardingAllocator(factory.GetAllocator(), "DOMParser::m_NameBuffer"))
+ , m_FirstPair(NULL)
+ , m_LastPair(NULL)
+ , m_XMLParser(&parser)
+ {
+ }
+
+ void ParseName(const XML_Char *name)
+ {
+ m_NSBuffer.assign(name);
+ eastl::string::size_type pos = m_NSBuffer.find(m_nsSeparator);
+ if (pos != TStrType::npos) {
+ m_NameBuffer.assign(m_NSBuffer.c_str() + pos + 1);
+ m_NSBuffer.resize(pos);
+ } else {
+ m_NameBuffer = m_NSBuffer;
+ m_NSBuffer.clear();
+ // Find the namespace with no abbreviation.
+ for (SNamespacePairNode *theNode = m_FirstPair; theNode;
+ theNode = theNode->m_NextNode) {
+ if (theNode->m_Abbreviation.IsValid() == false)
+ m_NSBuffer.assign(theNode->m_Namespace.c_str());
+ }
+ }
+ m_RegName = m_Factory.GetStringTable()->RegisterStr(m_NameBuffer.c_str());
+ m_RegNS = m_Factory.GetStringTable()->RegisterStr(m_NSBuffer.c_str());
+ }
+
+ struct SimpleXmlErrorHandler : public CXmlErrorHandler
+ {
+ void OnXmlError(TXMLCharPtr errorName, int line, int column) override
+ {
+ char8_t buffer[1024];
+ _snprintf(buffer, 1024, "%s(%d): Xml Error %s on line %d, column %d", __FILE__,
+ __LINE__, errorName, line, column);
+#ifdef QT3DS_VC
+ OutputDebugStringA(buffer);
+#endif
+ printf("%s\n", buffer);
+ }
+ };
+
+ template <QT3DSU32 THeaderLen>
+ struct SHeaderInStream : public IInStream
+ {
+ QT3DSU8 m_Header[THeaderLen];
+ IInStream &m_InStream;
+ QT3DSU32 m_BytesRead;
+
+ SHeaderInStream(IInStream &inStream)
+ : m_InStream(inStream)
+ , m_BytesRead(0)
+ {
+ }
+ bool readHeader()
+ {
+ QT3DSU32 amountRead = m_InStream.Read(NVDataRef<QT3DSU8>(m_Header, THeaderLen));
+ return amountRead == THeaderLen;
+ }
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ if (data.size() == 0)
+ return 0;
+ QT3DSU8 *writePtr(data.begin());
+ QT3DSU32 amountToRead(data.size());
+ QT3DSU32 amountRead = 0;
+ if (m_BytesRead < THeaderLen) {
+ QT3DSU32 headerLeft = NVMin(THeaderLen - m_BytesRead, amountToRead);
+ memCopy(writePtr, m_Header + m_BytesRead, headerLeft);
+ writePtr += headerLeft;
+ amountToRead -= headerLeft;
+ amountRead += headerLeft;
+ }
+ if (amountToRead)
+ amountRead += m_InStream.Read(NVDataRef<QT3DSU8>(writePtr, amountToRead));
+ m_BytesRead += amountRead;
+ return amountRead;
+ }
+ };
+
+ static eastl::pair<SNamespacePairNode *, SDOMElement *>
+ ParseXMLFile(IDOMFactory &factory, IInStream &inStream, CXmlErrorHandler *handler = NULL)
+ {
+ SimpleXmlErrorHandler simpleHandler;
+ if (handler == NULL)
+ handler = &simpleHandler;
+
+ // look for BOM (Byte-Order-Marker) in the file
+ // if found, pass in UTF-16 as the format. else
+ // pass in UTF-8 as the format.
+ SHeaderInStream<sizeof(g_BOMMarker)> theInStream(inStream);
+ if (theInStream.readHeader() == false) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ QT3DSU16 theHeaderData;
+ memCopy(&theHeaderData, theInStream.m_Header, sizeof(g_BOMMarker));
+
+ char8_t nsSeparator = '$';
+
+ if (theHeaderData == g_BOMMarker)
+ qFatal("UTF-16 files not supported");
+
+ QXmlStreamReader sreader;
+ DOMParser domParser(factory, sreader, nsSeparator);
+ QT3DSU8 dataBuf[2048];
+ QT3DSU32 amountRead = 0;
+ do {
+ amountRead = theInStream.Read(toDataRef(dataBuf, 2048));
+ if (amountRead) {
+ QByteArray tmp = QByteArray::fromRawData((char*)dataBuf,amountRead);
+ sreader.addData(tmp);
+ }
+ } while (amountRead > 0);
+ while (!sreader.atEnd()) {
+ QXmlStreamReader::TokenType token = sreader.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ domParser.m_Factory.IgnoreStrBuf();
+ domParser.ParseName((TXMLCharPtr)sreader.name().toUtf8().data());
+ int line = sreader.lineNumber();
+ SDOMElement *newElem =
+ domParser.m_Factory.NextElement(domParser.m_RegName, domParser.m_RegNS, line);
+ if (domParser.m_FirstElement == NULL) {
+ domParser.m_FirstElement = newElem;
+ domParser.m_TopElement = newElem;
+ } else {
+ domParser.m_TopElement->AppendChild(*newElem);
+ domParser.m_TopElement = newElem;
+ }
+ const QXmlStreamAttributes& attributes = sreader.attributes();
+ for (auto attrib : attributes) {
+ domParser.ParseName((TXMLCharPtr)attrib.name().toUtf8().data());
+ SDOMAttribute *att =
+ domParser.m_Factory.NextAttribute(domParser.m_RegName,
+ (TXMLCharPtr)attrib.value()
+ .toUtf8().data(),
+ domParser.m_RegNS, line);
+ newElem->m_Attributes.push_back(*att);
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ QByteArray text = sreader.text().toUtf8();
+ domParser.m_Factory.AppendStrBuf(text.data(), text.length());
+ } else if (token == QXmlStreamReader::EndElement) {
+ domParser.m_TopElement->m_Value = domParser.m_Factory.FinalizeStrBuf();
+ domParser.m_TopElement = domParser.m_TopElement->m_Parent;
+ }
+
+ if (sreader.hasError()) {
+ TXMLCharPtr error = (TXMLCharPtr)sreader.errorString().toUtf8().data();
+ handler->OnXmlError(error, sreader.lineNumber(), sreader.columnNumber());
+ return nullptr;
+ }
+
+ }
+ return eastl::make_pair(domParser.m_FirstPair, domParser.m_FirstElement);
+ }
+};
+
+class SimpleDomFactory : public IDOMFactory
+{
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TNarrowStr;
+ NVAllocatorCallback &m_Allocator;
+ Pool<SDOMElement> m_ElementPool;
+ Pool<SDOMAttribute> m_AttributePool;
+ Pool<SNamespacePairNode> m_NamespaceNodePool;
+ eastl::vector<char8_t *> m_BigStrings;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ TNarrowStr m_StringBuilder;
+ volatile QT3DSI32 mRefCount;
+
+public:
+ SimpleDomFactory(NVAllocatorCallback &alloc, NVScopedRefCounted<IStringTable> strt)
+ : m_Allocator(alloc)
+ , m_StringTable(strt)
+ , m_StringBuilder(ForwardingAllocator(alloc, "SimpleDomFactory::m_StringBuilder"))
+ , mRefCount(0)
+ {
+ }
+
+ ~SimpleDomFactory()
+ {
+ UICBASE_FOREACH(idx, m_BigStrings.size())
+ m_Allocator.deallocate(m_BigStrings[idx]);
+ m_BigStrings.clear();
+ }
+
+ NVAllocatorCallback &GetAllocator() override { return m_Allocator; }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Allocator)
+
+ TXMLCharPtr RegisterStr(TXMLCharPtr str)
+ {
+ if (str == NULL || *str == 0)
+ return "";
+ return m_StringTable->RegisterStr(str);
+ }
+
+ virtual void Release() { delete this; }
+ void AppendStrBuf(TXMLCharPtr str, QT3DSU32 len) override
+ {
+ if (len && *str) {
+ m_StringBuilder.append(str, str + len);
+ }
+ }
+
+ // Null terminate what is there and return the buffer.
+ // This pointer needs to be persistent.
+ TXMLCharPtr FinalizeStrBuf() override
+ {
+ if (m_StringBuilder.size() == 0)
+ return "";
+ QT3DSU32 len = m_StringBuilder.size() + 1;
+ QT3DSU32 numBytes = len * sizeof(char8_t);
+ char8_t *newMem =
+ (char8_t *)m_Allocator.allocate(numBytes, "DOMFactory::ValueStr", __FILE__, __LINE__);
+ memCopy(newMem, m_StringBuilder.c_str(), numBytes);
+ m_BigStrings.push_back(newMem);
+ m_StringBuilder.clear();
+ return newMem;
+ }
+ void IgnoreStrBuf() override { m_StringBuilder.clear(); }
+
+ SDOMAttribute *NextAttribute(CRegisteredString name, TXMLCharPtr val,
+ CRegisteredString ns, int inLine) override
+ {
+ TXMLCharPtr v(RegisterValue(val));
+ SDOMAttribute *att = (SDOMAttribute *)m_AttributePool.allocate(__FILE__, __LINE__);
+ new (att) SDOMAttribute(name, ns, v, inLine);
+ return att;
+ }
+
+ SDOMElement *NextElement(CRegisteredString name, CRegisteredString ns, int inLine) override
+ {
+ IgnoreStrBuf();
+ SDOMElement *elem = (SDOMElement *)(m_ElementPool.allocate(__FILE__, __LINE__));
+ new (elem) SDOMElement(name, ns, inLine);
+ return elem;
+ }
+
+ SNamespacePairNode *NextNSPairNode(CRegisteredString ns, CRegisteredString abbr) override
+ {
+ return m_NamespaceNodePool.construct(SNamespacePair(ns, abbr), __FILE__, __LINE__);
+ }
+
+ NVScopedRefCounted<IStringTable> GetStringTable() override { return m_StringTable; }
+};
+}
+
+NVScopedRefCounted<IDOMReader>
+IDOMReader::CreateDOMReader(NVAllocatorCallback &inAlloc, SDOMElement &inRootElement,
+ NVScopedRefCounted<IStringTable> inStringTable,
+ NVScopedRefCounted<IDOMFactory> inFactory)
+{
+ return QT3DS_NEW(inAlloc, SDOMReader)(inAlloc, inRootElement, inStringTable, inFactory);
+}
+
+eastl::pair<NVScopedRefCounted<IDOMWriter>, NVScopedRefCounted<IDOMReader>>
+IDOMWriter::CreateDOMWriter(NVScopedRefCounted<IDOMFactory> inFactory, SDOMElement &inRootElement,
+ NVScopedRefCounted<IStringTable> inStringTable)
+{
+ NVScopedRefCounted<SDOMWriter> writer(
+ QT3DS_NEW(inFactory->GetAllocator(), SDOMWriter)(inFactory, inStringTable, inRootElement));
+ return eastl::make_pair(writer.mPtr, writer.mPtr);
+}
+
+TXMLCharPtr IDOMFactory::RegisterValue(TXMLCharPtr inValue)
+{
+ if (isTrivial(inValue))
+ return "";
+ IgnoreStrBuf();
+ AppendStrBuf(inValue, (QT3DSU32)strlen(inValue));
+ return FinalizeStrBuf();
+}
+
+NVScopedRefCounted<IDOMFactory>
+IDOMFactory::CreateDOMFactory(NVAllocatorCallback &inAlloc,
+ NVScopedRefCounted<IStringTable> inStrTable)
+{
+ return QT3DS_NEW(inAlloc, SimpleDomFactory)(inAlloc, inStrTable);
+}
+
+void CDOMSerializer::WriteXMLHeader(IOutStream &inStream)
+{
+ const char8_t *header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+ QT3DSU32 len = (QT3DSU32)strlen(header);
+ inStream.Write(header, len);
+}
+
+// Lexigraphically sort the attributes.
+struct SAttributeComparator
+{
+ bool operator()(const SDOMAttribute *lhs, const SDOMAttribute *rhs)
+ {
+ int nsCmp = strcmp(lhs->m_Namespace, rhs->m_Namespace);
+ if (nsCmp)
+ return nsCmp < 0;
+
+ return strcmp(lhs->m_Name, rhs->m_Name) < 0;
+ }
+};
+
+typedef eastl::vector<SDOMAttribute *, ForwardingAllocator> TAttVector;
+typedef eastl::hash_map<CRegisteredString, CRegisteredString, eastl::hash<CRegisteredString>,
+ eastl::equal_to<CRegisteredString>, ForwardingAllocator>
+ TNSMap;
+
+CRegisteredString GetOrCreateNamespaceAbbr(NVAllocatorCallback &inAlloc, CRegisteredString theNs,
+ TNSMap &inNamespace, TNSMap &inReverseNamespaces,
+ IStringTable &inStrTable, bool &outCreated)
+{
+ CRegisteredString abbr;
+ if (theNs.IsValid()) {
+ TNSMap::iterator nsIter = inNamespace.find(theNs);
+ if (nsIter != inNamespace.end()) {
+ abbr = nsIter->second;
+ outCreated = false;
+ } else {
+ eastl::basic_string<char8_t, ForwardingAllocator> theStr(
+ ForwardingAllocator(inAlloc, "nsBuilderString"));
+ theStr.assign("a");
+ eastl::basic_string<char8_t, ForwardingAllocator> theNsStr(
+ ForwardingAllocator(inAlloc, "nsBuilderString"));
+ CRegisteredString theNS = inStrTable.RegisterStr(theStr.c_str());
+ while (inReverseNamespaces.find(theNS) != inReverseNamespaces.end()) {
+ for (int idx = 0;
+ idx < 26 && inReverseNamespaces.find(theNS) == inReverseNamespaces.end();
+ ++idx) {
+ theNsStr = theStr;
+ theNsStr.append(1, (char8_t)('a' + idx));
+ theNS = inStrTable.RegisterStr(theNsStr.c_str());
+ }
+ theStr.append(1, 'a');
+ }
+ inNamespace.insert(eastl::make_pair(theNs, theNS));
+ abbr = theNS;
+ outCreated = true;
+ }
+ }
+ return abbr;
+}
+
+// Write an element with attributes sorted by name so a file diff is effective.
+void WriteElement(NVAllocatorCallback &inAlloc, SDOMElement &inElement, SimpleXmlWriter &inWriter,
+ TAttVector &inAttSorter, TNSMap &inNamespace, TNSMap &inReverseNamespaces,
+ IStringTable &inStrTable, bool inTrimEmptyElems, bool inWriteXMLNS)
+{
+ inAttSorter.clear();
+
+ // We decided that we don't want attribute sorting; the code that adds attributes needs
+ // to be consistent.
+ // This element doesn't add anything to the system in this case.
+ if (inTrimEmptyElems && inElement.m_Attributes.empty() && inElement.m_Children.empty()
+ && isTrivial(inElement.m_Value))
+ return;
+
+ for (TAttributeList::iterator iter = inElement.m_Attributes.begin(),
+ end = inElement.m_Attributes.end();
+ iter != end; ++iter)
+ inAttSorter.push_back(&(*iter));
+
+ // Find the namespace for the element
+ bool createdAbbr = false;
+ CRegisteredString abbr = GetOrCreateNamespaceAbbr(inAlloc, inElement.m_Namespace, inNamespace,
+ inReverseNamespaces, inStrTable, createdAbbr);
+
+ inWriter.Begin(inElement.m_Name, abbr);
+ eastl::basic_string<char8_t, ForwardingAllocator> theStr(
+ ForwardingAllocator(inAlloc, "nsBuilderString"));
+ if (inWriteXMLNS) {
+ for (TNSMap::iterator iter = inNamespace.begin(), end = inNamespace.end(); iter != end;
+ ++iter) {
+ theStr.assign("xmlns");
+ if (iter->second.IsValid()) {
+ theStr.append(1, ':');
+ theStr.append(iter->second.c_str());
+ }
+ inWriter.Att(theStr.c_str(), NULL, iter->first.c_str());
+ }
+ } else if (createdAbbr) {
+ theStr.assign("xmlns:");
+ theStr.append(abbr.c_str());
+ inWriter.Att(theStr.c_str(), NULL, inElement.m_Namespace.c_str());
+ }
+
+ const char8_t *theLastAttName = 0;
+ const char8_t *theLastAttNamespace = 0;
+ for (QT3DSU32 idx = 0, end = inAttSorter.size(); idx < end; ++idx) {
+ SDOMAttribute *theAtt(inAttSorter[idx]);
+ if (theAtt->m_Name != theLastAttName || theAtt->m_Namespace != theLastAttNamespace) {
+ abbr = GetOrCreateNamespaceAbbr(inAlloc, theAtt->m_Namespace, inNamespace,
+ inReverseNamespaces, inStrTable, createdAbbr);
+ if (createdAbbr) {
+ theStr.assign("xmlns:");
+ theStr.append(abbr.c_str());
+ inWriter.Att(theStr.c_str(), NULL, inElement.m_Namespace.c_str());
+ }
+
+ inWriter.Att(theAtt->m_Name, abbr, theAtt->m_Value);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ theLastAttName = theAtt->m_Name;
+ theLastAttNamespace = theAtt->m_Namespace;
+ }
+ // Elements can either have children or values but not both at this point.
+ if (inElement.m_Children.empty() == false) {
+ for (SDOMElement::TElementChildList::iterator iter = inElement.m_Children.begin(),
+ end = inElement.m_Children.end();
+ iter != end; ++iter)
+ WriteElement(inAlloc, *iter, inWriter, inAttSorter, inNamespace, inReverseNamespaces,
+ inStrTable, inTrimEmptyElems, false);
+
+ inWriter.End();
+ } else {
+ if (!isTrivial(inElement.m_Value))
+ inWriter.Value(inElement.m_Value);
+
+ inWriter.End();
+ }
+}
+
+void CDOMSerializer::Write(NVAllocatorCallback &inAlloc, SDOMElement &inElement,
+ IOutStream &inStream, IStringTable &inStrTable,
+ NVConstDataRef<SNamespacePair> inNamespaces, bool inTrimEmptyElements,
+ QT3DSU32 inTabs, bool inWriteNamespaces)
+{
+ TAttVector theAttSorter(ForwardingAllocator(inAlloc, "CDOMSerializer::AttributeList"));
+ TNSMap theNamespaces(ForwardingAllocator(inAlloc, "CDOMSerializer::NamespaceMap"));
+ TNSMap theReverseNamespaces(ForwardingAllocator(inAlloc, "CDOMSerializer::NamespaceMap"));
+ for (QT3DSU32 idx = 0, end = inNamespaces.size(); idx < end; ++idx) {
+ theNamespaces.insert(
+ eastl::make_pair(inNamespaces[idx].m_Namespace, inNamespaces[idx].m_Abbreviation));
+ theReverseNamespaces.insert(
+ eastl::make_pair(inNamespaces[idx].m_Abbreviation, inNamespaces[idx].m_Namespace));
+ }
+ SimpleXmlWriter writer(inAlloc, inStream, inTabs);
+ WriteElement(inAlloc, inElement, writer, theAttSorter, theNamespaces, theReverseNamespaces,
+ inStrTable, inTrimEmptyElements, inWriteNamespaces);
+}
+
+eastl::pair<SNamespacePairNode *, SDOMElement *>
+CDOMSerializer::Read(IDOMFactory &inFactory, IInStream &inStream, CXmlErrorHandler *inErrorHandler)
+{
+ return DOMParser::ParseXMLFile(inFactory, inStream, inErrorHandler);
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxAtomic.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxAtomic.cpp
new file mode 100644
index 00000000..f0045dd9
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxAtomic.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAtomic.h"
+#ifdef __QNX__
+#include <atomic.h>
+#endif
+#ifdef __INTEGRITY
+#include <QtCore/qmutex.h>
+#endif
+
+#define PAUSE() asm("nop")
+
+namespace qt3ds {
+namespace foundation {
+#ifdef __QNX__
+ QT3DSI32 atomicIncrement(volatile QT3DSI32 *val)
+ {
+ atomic_add((volatile unsigned *)val, 1);
+ return *val;
+ }
+
+ QT3DSI32 atomicDecrement(volatile QT3DSI32 *val)
+ {
+ atomic_sub((volatile unsigned *)val, 1);
+ return *val;
+ }
+#elif defined (__INTEGRITY)
+ // TestAndSet and AtomicModify take in volatile Address* leading to overflow error if used
+
+ QT3DSI32 atomicCompareExchange(volatile QT3DSI32 *dest, QT3DSI32 exch, QT3DSI32 comp)
+ {
+ static QMutex mutex;
+ QMutexLocker lock(&mutex);
+ QT3DSI32 ret = *dest;
+ *dest = (*dest == comp) ? exch : ret;
+ return ret;
+ }
+
+ QT3DSI32 atomicIncrement(volatile QT3DSI32 *val)
+ {
+ static QMutex mutex;
+ QMutexLocker lock(&mutex);
+ return ++(*val);
+ }
+
+ QT3DSI32 atomicDecrement(volatile QT3DSI32 *val)
+ {
+ static QMutex mutex;
+ QMutexLocker lock(&mutex);
+ return --(*val);
+ }
+#else
+ void *atomicCompareExchangePointer(volatile void **dest, void *exch, void *comp)
+ {
+ return __sync_val_compare_and_swap((void **)dest, comp, exch);
+ }
+
+ QT3DSI32 atomicCompareExchange(volatile QT3DSI32 *dest, QT3DSI32 exch, QT3DSI32 comp)
+ {
+ return __sync_val_compare_and_swap(dest, comp, exch);
+ }
+
+ QT3DSI32 atomicIncrement(volatile QT3DSI32 *val) { return __sync_add_and_fetch(val, 1); }
+
+ QT3DSI32 atomicDecrement(volatile QT3DSI32 *val) { return __sync_sub_and_fetch(val, 1); }
+
+ QT3DSI32 atomicAdd(volatile QT3DSI32 *val, QT3DSI32 delta) { return __sync_add_and_fetch(val, delta); }
+
+ QT3DSI32 atomicMax(volatile QT3DSI32 *val, QT3DSI32 val2)
+ {
+ QT3DSI32 oldVal, newVal;
+
+ do {
+ PAUSE();
+ oldVal = *val;
+
+ if (val2 > oldVal)
+ newVal = val2;
+ else
+ newVal = oldVal;
+
+ } while (atomicCompareExchange(val, newVal, oldVal) != oldVal);
+
+ return *val;
+ }
+
+ QT3DSI32 atomicExchange(volatile QT3DSI32 *val, QT3DSI32 val2)
+ {
+ QT3DSI32 newVal, oldVal;
+
+ do {
+ PAUSE();
+ oldVal = *val;
+ newVal = val2;
+ } while (atomicCompareExchange(val, newVal, oldVal) != oldVal);
+
+ return newVal;
+ }
+#endif
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxFPU.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxFPU.cpp
new file mode 100644
index 00000000..c3eae215
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxFPU.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/Qt3DSFPU.h"
+#include <fenv.h>
+
+QT3DS_COMPILE_TIME_ASSERT(8 * sizeof(qt3ds::QT3DSU32) >= sizeof(fenv_t));
+
+qt3ds::foundation::FPUGuard::FPUGuard()
+{
+#ifdef __CYGWIN__
+#pragma message "FPUGuard::FPUGuard() is not implemented"
+#else
+ fegetenv(reinterpret_cast<fenv_t *>(mControlWords));
+ fesetenv(FE_DFL_ENV);
+#endif
+}
+
+qt3ds::foundation::FPUGuard::~FPUGuard()
+{
+#ifdef __CYGWIN__
+#pragma message "FPUGuard::~FPUGuard() is not implemented"
+#else
+ fesetenv(reinterpret_cast<fenv_t *>(mControlWords));
+#endif
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxMutex.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxMutex.cpp
new file mode 100644
index 00000000..bbc55829
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxMutex.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAtomic.h"
+
+#include <pthread.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ namespace {
+ pthread_mutex_t *getMutex(MutexImpl *impl)
+ {
+ return reinterpret_cast<pthread_mutex_t *>(impl);
+ }
+ }
+
+ MutexImpl::MutexImpl()
+ {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(getMutex(this), &attr);
+ pthread_mutexattr_destroy(&attr);
+ }
+
+ MutexImpl::~MutexImpl() { pthread_mutex_destroy(getMutex(this)); }
+
+ bool MutexImpl::lock() { return !pthread_mutex_lock(getMutex(this)); }
+
+ bool MutexImpl::trylock() { return !pthread_mutex_trylock(getMutex(this)); }
+
+ bool MutexImpl::unlock() { return !pthread_mutex_unlock(getMutex(this)); }
+
+ const QT3DSU32 MutexImpl::size = sizeof(pthread_mutex_t);
+
+ class ReadWriteLockImpl
+ {
+ public:
+ ReadWriteLockImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ pthread_mutex_t mutex;
+ volatile int readerCounter;
+ };
+
+ ReadWriteLock::ReadWriteLock(NVAllocatorCallback &alloc)
+ {
+ mImpl = QT3DS_NEW(alloc, ReadWriteLockImpl)(alloc);
+
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mImpl->mutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+
+ mImpl->readerCounter = 0;
+ }
+
+ ReadWriteLock::~ReadWriteLock()
+ {
+ pthread_mutex_destroy(&mImpl->mutex);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ void ReadWriteLock::lockReader()
+ {
+ pthread_mutex_lock(&mImpl->mutex);
+
+ atomicIncrement(&mImpl->readerCounter);
+
+ pthread_mutex_unlock(&mImpl->mutex);
+ }
+
+ void ReadWriteLock::lockWriter()
+ {
+ pthread_mutex_lock(&mImpl->mutex);
+
+ while (mImpl->readerCounter != 0)
+ ;
+ }
+
+ void ReadWriteLock::unlockReader() { atomicDecrement(&mImpl->readerCounter); }
+
+ void ReadWriteLock::unlockWriter() { pthread_mutex_unlock(&mImpl->mutex); }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSemaphore.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSemaphore.cpp
new file mode 100644
index 00000000..90aab79a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSemaphore.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSSemaphore.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ class SemaphoreImpl
+ {
+ public:
+ SemaphoreImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ QT3DSU32 count;
+ QT3DSU32 maxCount;
+ };
+
+ struct NVLinuxScopeLock
+ {
+ NVLinuxScopeLock(pthread_mutex_t &m)
+ : mMutex(m)
+ {
+ pthread_mutex_lock(&mMutex);
+ }
+
+ ~NVLinuxScopeLock() { pthread_mutex_unlock(&mMutex); }
+ private:
+ pthread_mutex_t &mMutex;
+ };
+
+ Semaphore::Semaphore(NVAllocatorCallback &alloc, QT3DSU32 initialCount, QT3DSU32 maxCount)
+ {
+ mImpl = QT3DS_NEW(alloc, SemaphoreImpl)(alloc);
+ int status = pthread_mutex_init(&mImpl->mutex, 0);
+ QT3DS_ASSERT(!status);
+ status = pthread_cond_init(&mImpl->cond, 0);
+ QT3DS_ASSERT(!status);
+ mImpl->count = initialCount;
+ mImpl->maxCount = maxCount;
+ QT3DS_ASSERT(initialCount <= maxCount);
+ }
+
+ Semaphore::~Semaphore()
+ {
+ pthread_cond_destroy(&mImpl->cond);
+ pthread_mutex_destroy(&mImpl->mutex);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ bool Semaphore::wait(QT3DSU32 milliseconds)
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+
+ if (mImpl->count > 0) {
+ mImpl->count--;
+ return true;
+ }
+
+ if (milliseconds == 0) {
+ return false;
+ }
+
+ if (milliseconds == QT3DSU32(-1)) {
+ int status = pthread_cond_wait(&mImpl->cond, &mImpl->mutex);
+ QT3DS_ASSERT(!status);
+ (void)status;
+ } else {
+ timespec ts;
+ timeval tp;
+ gettimeofday(&tp, NULL);
+ QT3DSU32 sec = milliseconds / 1000;
+ QT3DSU32 usec = (milliseconds - 1000 * sec) * 1000;
+
+ // sschirm: taking into account that us might accumulate to a second
+ // otherwise the pthread_cond_timedwait complains on osx.
+ usec = tp.tv_usec + usec;
+ QT3DSU32 div_sec = usec / 1000000;
+ QT3DSU32 rem_usec = usec - div_sec * 1000000;
+
+ ts.tv_sec = tp.tv_sec + sec + div_sec;
+ ts.tv_nsec = rem_usec * 1000;
+
+ int ierr = pthread_cond_timedwait(&mImpl->cond, &mImpl->mutex, &ts);
+ QT3DS_ASSERT((ierr == 0) || (ierr == ETIMEDOUT));
+ (void)ierr;
+ return false;
+ }
+
+ return true;
+ }
+
+ void Semaphore::post()
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ mImpl->count++;
+ if (mImpl->count > mImpl->maxCount)
+ mImpl->count = mImpl->maxCount;
+ else {
+ pthread_cond_broadcast(&mImpl->cond);
+ }
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSync.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSync.cpp
new file mode 100644
index 00000000..52f9d7ab
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxSync.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ class SyncImpl
+ {
+ public:
+ SyncImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ volatile bool is_set;
+ };
+
+ struct NVLinuxScopeLock
+ {
+ NVLinuxScopeLock(pthread_mutex_t &m)
+ : mMutex(m)
+ {
+ pthread_mutex_lock(&mMutex);
+ }
+
+ ~NVLinuxScopeLock() { pthread_mutex_unlock(&mMutex); }
+ private:
+ pthread_mutex_t &mMutex;
+ };
+
+ Sync::Sync(NVAllocatorCallback &alloc)
+ {
+ mImpl = QT3DS_NEW(alloc, SyncImpl)(alloc);
+ int status = pthread_mutex_init(&mImpl->mutex, 0);
+ QT3DS_ASSERT(!status);
+ status = pthread_cond_init(&mImpl->cond, 0);
+ QT3DS_ASSERT(!status);
+ mImpl->is_set = false;
+ }
+
+ Sync::~Sync()
+ {
+ pthread_cond_destroy(&mImpl->cond);
+ pthread_mutex_destroy(&mImpl->mutex);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ void Sync::reset()
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ mImpl->is_set = false;
+ }
+
+ void Sync::set()
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ if (!mImpl->is_set) {
+ mImpl->is_set = true;
+ pthread_cond_broadcast(&mImpl->cond);
+ }
+ }
+
+ bool Sync::wait(QT3DSU32 ms)
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ if (!mImpl->is_set) {
+ if (ms == QT3DSU32(-1)) {
+ int status = pthread_cond_wait(&mImpl->cond, &mImpl->mutex);
+ QT3DS_ASSERT(!status);
+ (void)status;
+ } else {
+ timespec ts;
+ timeval tp;
+ gettimeofday(&tp, NULL);
+ QT3DSU32 sec = ms / 1000;
+ QT3DSU32 usec = (ms - 1000 * sec) * 1000;
+
+ // sschirm: taking into account that us might accumulate to a second
+ // otherwise the pthread_cond_timedwait complains on osx.
+ usec = tp.tv_usec + usec;
+ QT3DSU32 div_sec = usec / 1000000;
+ QT3DSU32 rem_usec = usec - div_sec * 1000000;
+
+ ts.tv_sec = tp.tv_sec + sec + div_sec;
+ ts.tv_nsec = rem_usec * 1000;
+
+ int ierr = pthread_cond_timedwait(&mImpl->cond, &mImpl->mutex, &ts);
+ QT3DS_ASSERT((ierr == 0) || (ierr == ETIMEDOUT));
+ (void)ierr;
+ }
+ }
+ return mImpl->is_set;
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxThread.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxThread.cpp
new file mode 100644
index 00000000..fa6e069e
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxThread.cpp
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSThread.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#if !defined(QT3DS_APPLE) && !defined(ANDROID) && !defined(__CYGWIN__) && !defined(__QNX__) && !defined(__INTEGRITY)
+#include <bits/local_lim.h> // PTHREAD_STACK_MIN
+#endif
+#include <stdio.h>
+#include <pthread.h>
+#if !defined(__QNX__) && !defined(__INTEGRITY)
+#include <unistd.h>
+#include <sys/syscall.h>
+#if !defined(QT3DS_APPLE)
+#include <asm/unistd.h>
+#include <sys/resource.h>
+#endif
+#endif
+
+#define NVSpinLockPause() asm("nop")
+
+namespace qt3ds {
+namespace foundation {
+ using namespace intrinsics;
+
+ typedef enum { _NVThreadNotStarted, _NVThreadStarted, _NVThreadStopped } NVThreadState;
+
+ class ThreadImpl
+ {
+ public:
+ ThreadImpl(NVFoundationBase &foundation)
+ : mFoundation(foundation)
+ {
+ }
+ NVFoundationBase &mFoundation;
+ Thread::ExecuteFn fn;
+ void *arg;
+ volatile QT3DSI32 quitNow;
+ volatile QT3DSI32 threadStarted;
+ NVThreadState state;
+
+ pthread_t thread;
+ pid_t tid;
+ };
+
+ void *NVThreadStart(void *arg);
+
+ Thread::Id Thread::getId() { return Id(pthread_self()); }
+
+ Thread::Thread(NVFoundationBase &foundation)
+ {
+ mImpl = QT3DS_NEW(foundation.getAllocator(), ThreadImpl)(foundation);
+ mImpl->thread = 0;
+ mImpl->tid = 0;
+ mImpl->state = _NVThreadNotStarted;
+ mImpl->quitNow = 0;
+ mImpl->threadStarted = 0;
+ mImpl->fn = NULL;
+ mImpl->arg = NULL;
+ }
+
+ Thread::Thread(NVFoundationBase &foundation, Thread::ExecuteFn fn, void *arg)
+ {
+ mImpl = (ThreadImpl *)QT3DS_NEW(foundation.getAllocator(), ThreadImpl)(foundation);
+ mImpl->thread = 0;
+ mImpl->tid = 0;
+ mImpl->state = _NVThreadNotStarted;
+ mImpl->quitNow = 0;
+ mImpl->threadStarted = 0;
+ mImpl->fn = fn;
+ mImpl->arg = arg;
+
+ start(0);
+ }
+
+ Thread::~Thread()
+ {
+ if (mImpl->state == _NVThreadStarted)
+ kill();
+ QT3DS_FREE(mImpl->mFoundation.getAllocator(), mImpl);
+ }
+
+ void Thread::start(QT3DSU32 stackSize)
+ {
+ if (mImpl->state != _NVThreadNotStarted)
+ return;
+
+ if (stackSize == 0)
+ stackSize = DEFAULT_STACK_SIZE;
+
+#if defined(PTHREAD_STACK_MIN) && !defined(ANDROID)
+ if (stackSize < PTHREAD_STACK_MIN) {
+ qCWarning(WARNING, "Thread::start(): stack size was set below PTHREAD_STACK_MIN");
+ stackSize = PTHREAD_STACK_MIN;
+ }
+#endif
+
+ pthread_attr_t attr;
+ int status = pthread_attr_init(&attr);
+ QT3DS_ASSERT(!status);
+
+ status = pthread_attr_setstacksize(&attr, stackSize);
+ QT3DS_ASSERT(!status);
+ status = pthread_create(&mImpl->thread, &attr, NVThreadStart, this);
+ QT3DS_ASSERT(!status);
+
+#ifndef __QNX__
+ // wait for thread to startup and write out TID
+ // otherwise TID dependent calls like setAffinity will fail.
+ while (atomicCompareExchange(&(mImpl->threadStarted), 1, 1) == 0)
+ yield();
+#endif
+
+ mImpl->state = _NVThreadStarted;
+
+ status = pthread_attr_destroy(&attr);
+ QT3DS_ASSERT(!status);
+ }
+
+ static void setTid(ThreadImpl &threadImpl)
+ {
+#ifndef __QNX__
+// query TID
+#ifdef QT3DS_APPLE
+ threadImpl.tid = syscall(SYS_gettid);
+#elif defined(__INTEGRITY)
+ pthread_t ptid = pthread_self();
+ uint64_t threadId = 0;
+ memcpy(&threadId, &ptid, std::min(sizeof(threadId), sizeof(ptid)));
+ threadImpl.tid = threadId;
+#else
+ threadImpl.tid = syscall(__NR_gettid);
+#endif
+
+ // notify/unblock parent thread
+ atomicCompareExchange(&(threadImpl.threadStarted), 1, 0);
+#else
+ QT3DS_ASSERT(false);
+#endif
+ }
+
+ void *NVThreadStart(void *arg)
+ {
+ // run execute from base class to run gettid in the new thread's context
+ ((Thread *)arg)->Thread::execute();
+ return 0;
+ }
+
+ void Thread::execute(void)
+ {
+ // run setTid in thread's context
+ setTid(*mImpl);
+
+ // then run either the passed in function or execute from the derived class.
+ if (mImpl->fn)
+ (*mImpl->fn)(mImpl->arg);
+ else
+ this->execute();
+ }
+
+ void Thread::signalQuit() { atomicIncrement(&(mImpl->quitNow)); }
+
+ bool Thread::waitForQuit()
+ {
+ if (mImpl->state == _NVThreadNotStarted)
+ return false;
+
+ pthread_join(mImpl->thread, NULL);
+ return true;
+ }
+
+ bool Thread::quitIsSignalled()
+ {
+#ifndef __QNX__
+ return atomicCompareExchange(&(mImpl->quitNow), 0, 0) != 0;
+#else
+ // Hope for memory locking on the arm.
+ return mImpl->quitNow != 0;
+#endif
+ }
+
+ void Thread::quit()
+ {
+ mImpl->state = _NVThreadStopped;
+ pthread_exit(0);
+ }
+
+ void Thread::kill()
+ {
+#ifndef ANDROID
+ if (mImpl->state == _NVThreadStarted)
+ pthread_cancel(mImpl->thread);
+ mImpl->state = _NVThreadStopped;
+#else
+ qCWarning(WARNING, "Thread::kill() called, but is not implemented");
+#endif
+ }
+
+ void Thread::sleep(QT3DSU32 ms)
+ {
+ timespec sleepTime;
+ QT3DSU32 remainder = ms % 1000;
+ sleepTime.tv_sec = ms - remainder;
+ sleepTime.tv_nsec = remainder * 1000000L;
+
+ while (nanosleep(&sleepTime, &sleepTime) == -1)
+ continue;
+ }
+
+ void Thread::yield() { sched_yield(); }
+
+ QT3DSU32 Thread::setAffinityMask(QT3DSU32 mask)
+ {
+ // Same as windows impl if mask is zero
+ if (!mask)
+ return 0;
+
+#ifndef __QNX__
+ QT3DSU64 prevMask = 0;
+
+// Apple doesn't support syscall with getaffinity and setaffinity
+#if !defined(QT3DS_APPLE) && !defined(__INTEGRITY)
+ QT3DSI32 errGet = syscall(__NR_sched_getaffinity, mImpl->tid, sizeof(prevMask), &prevMask);
+ if (errGet < 0)
+ return 0;
+
+ QT3DSI32 errSet = syscall(__NR_sched_setaffinity, mImpl->tid, sizeof(mask), &mask);
+ if (errSet != 0)
+ return 0;
+#endif
+
+ return QT3DSU32(prevMask);
+#else
+ QT3DS_ASSERT(false);
+ return 0;
+#endif
+ }
+
+ void Thread::setName(const char *name)
+ {
+#if (defined(ANDROID) && (__ANDROID_API__ > 8))
+ pthread_setname_np(mImpl->thread, name);
+#else
+// not implemented because most unix APIs expect setName()
+// to be called from the thread's context. Example see next comment:
+
+// this works only with the current thread and can rename
+// the main process if used in the wrong context:
+// prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name) ,0,0,0);
+#endif
+ }
+
+#if !defined(QT3DS_APPLE) && !defined(__INTEGRITY)
+ static ThreadPriority::Enum convertPriorityFromLinux(QT3DSU32 inPrio, int policy)
+ {
+ QT3DS_COMPILE_TIME_ASSERT(ThreadPriority::eLOW > ThreadPriority::eHIGH);
+ QT3DS_COMPILE_TIME_ASSERT(ThreadPriority::eHIGH == 0);
+
+ int maxL = sched_get_priority_max(policy);
+ int minL = sched_get_priority_min(policy);
+ int rangeL = maxL - minL;
+ int rangeNV = ThreadPriority::eLOW - ThreadPriority::eHIGH;
+
+ // case for default scheduler policy
+ if (rangeL == 0)
+ return ThreadPriority::eNORMAL;
+
+ float floatPrio = (float(maxL - inPrio) * float(rangeNV)) / float(rangeL);
+
+ return ThreadPriority::Enum(int(roundf(floatPrio)));
+ }
+
+ static int convertPriorityToLinux(ThreadPriority::Enum inPrio, int policy)
+ {
+ int maxL = sched_get_priority_max(policy);
+ int minL = sched_get_priority_min(policy);
+ int rangeL = maxL - minL;
+ int rangeNV = ThreadPriority::eLOW - ThreadPriority::eHIGH;
+
+ // case for default scheduler policy
+ if (rangeL == 0)
+ return 0;
+
+ float floatPrio = (float(ThreadPriority::eLOW - inPrio) * float(rangeL)) / float(rangeNV);
+
+ return minL + int(roundf(floatPrio));
+ }
+#endif
+
+ void Thread::setPriority(ThreadPriority::Enum val)
+ {
+#if !defined(QT3DS_APPLE) && !defined(__INTEGRITY)
+ int policy;
+ sched_param s_param;
+ pthread_getschedparam(mImpl->thread, &policy, &s_param);
+ s_param.sched_priority = convertPriorityToLinux(val, policy);
+ pthread_setschedparam(mImpl->thread, policy, &s_param);
+#endif
+ }
+
+ ThreadPriority::Enum Thread::getPriority(Id pthread)
+ {
+#if !defined(QT3DS_APPLE) && !defined(__INTEGRITY)
+ int policy;
+ sched_param s_param;
+ int ret = pthread_getschedparam(pthread_t(pthread), &policy, &s_param);
+ if (ret == 0)
+ return convertPriorityFromLinux(s_param.sched_priority, policy);
+ else
+ return ThreadPriority::eNORMAL;
+#else
+ return ThreadPriority::eNORMAL;
+#endif
+ }
+
+ QT3DSU32 TlsAlloc()
+ {
+#if !defined(__INTEGRITY)
+ pthread_key_t key;
+ int status = pthread_key_create(&key, NULL);
+ QT3DS_ASSERT(!status);
+ (void)status;
+ return (QT3DSU32)key;
+#else
+ QT3DS_ASSERT(false);
+ return 0;
+#endif
+ }
+
+ void TlsFree(QT3DSU32 index)
+ {
+ int status = pthread_key_delete((pthread_key_t)index);
+ QT3DS_ASSERT(!status);
+ (void)status;
+ }
+
+ void *TlsGet(QT3DSU32 index) { return (void *)pthread_getspecific((pthread_key_t)index); }
+
+ QT3DSU32 TlsSet(QT3DSU32 index, void *value)
+ {
+ int status = pthread_setspecific((pthread_key_t)index, value);
+ QT3DS_ASSERT(!status);
+ return !status;
+ }
+
+ // DM: On Linux x86-32, without implementation-specific restrictions
+ // the default stack size for a new thread should be 2 megabytes (kernel.org).
+ // NOTE: take care of this value on other architecutres!
+ const QT3DSU32 Thread::DEFAULT_STACK_SIZE = 1 << 21;
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxTime.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxTime.cpp
new file mode 100644
index 00000000..6b3e93e4
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/Qt3DSLinuxTime.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSTime.h"
+
+#include <time.h>
+#include <sys/time.h>
+
+#if defined QT3DS_APPLE
+#include <mach/mach_time.h>
+#endif
+
+// Use real-time high-precision timer.
+#ifndef QT3DS_APPLE
+#define CLOCKID CLOCK_REALTIME
+#endif
+
+namespace qt3ds {
+namespace foundation {
+
+ const CounterFrequencyToTensOfNanos Time::sCounterFreq = Time::getCounterFrequency();
+
+ static Time::Second getTimeSeconds()
+ {
+ static struct timeval _tv;
+ gettimeofday(&_tv, NULL);
+ return double(_tv.tv_sec) + double(_tv.tv_usec) * 0.000001;
+ }
+
+ Time::Time() { mLastTime = getTimeSeconds(); }
+
+ Time::Second Time::getElapsedSeconds()
+ {
+ Time::Second curTime = getTimeSeconds();
+ Time::Second diff = curTime - mLastTime;
+ mLastTime = curTime;
+ return diff;
+ }
+
+ Time::Second Time::peekElapsedSeconds()
+ {
+ Time::Second curTime = getTimeSeconds();
+ Time::Second diff = curTime - mLastTime;
+ return diff;
+ }
+
+ Time::Second Time::getLastTime() const { return mLastTime; }
+
+#ifdef QT3DS_APPLE
+ CounterFrequencyToTensOfNanos Time::getCounterFrequency()
+ {
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+ // sschirm: some code in the PhysX samples assumes that
+ // CounterFrequencyToTensOfNanos::mDenominator is #ticks/second
+ // which is bad since it ignores the numenator. This is a temporary fix
+ // with the same setup as windows
+ // return CounterFrequencyToTensOfNanos( info.numer, info.denom*10 );
+ return CounterFrequencyToTensOfNanos(sNumTensOfNanoSecondsInASecond,
+ info.denom * 1000000000 / info.numer);
+ }
+
+ QT3DSU64 Time::getCurrentCounterValue() { return mach_absolute_time(); }
+
+#else
+
+ CounterFrequencyToTensOfNanos Time::getCounterFrequency()
+ {
+ return CounterFrequencyToTensOfNanos(1, 10);
+ }
+
+ QT3DSU64 Time::getCurrentCounterValue()
+ {
+ struct timespec mCurrTimeInt;
+ clock_gettime(CLOCKID, &mCurrTimeInt);
+ // Convert to nanos as this doesn't cause a large divide here
+ return (static_cast<QT3DSU64>(mCurrTimeInt.tv_sec) * 1000000000)
+ + (static_cast<QT3DSU64>(mCurrTimeInt.tv_nsec));
+ }
+#endif
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/SocketImpl.h b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/SocketImpl.h
new file mode 100644
index 00000000..4c3fcb73
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/linux/SocketImpl.h
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef FOUNDATION_LINUX_SOCKET_IMPL_H
+#define FOUNDATION_LINUX_SOCKET_IMPL_H
+#pragma once
+
+/*=========================================================================*\
+* BSD include files
+\*=========================================================================*/
+/* error codes */
+#include <errno.h>
+/* close function */
+#include <unistd.h>
+/* fnctnl function and associated constants */
+#include <fcntl.h>
+/* struct sockaddr */
+#include <sys/types.h>
+/* socket function */
+#include <sys/socket.h>
+/* struct timeval */
+#include <sys/time.h>
+/* gethostbyname and gethostbyaddr functions */
+#include <netdb.h>
+/* sigpipe handling */
+#include <signal.h>
+/* IP stuff*/
+#include <netinet/in.h>
+#include <arpa/inet.h>
+/* TCP options (nagle algorithm disable) */
+#include <netinet/tcp.h>
+
+namespace qt3ds {
+namespace foundation {
+ namespace socketimpl {
+ // Functions take from lua socket implementation. Note that it has an MIT license.
+
+ enum {
+ IO_DONE = 0, /* operation completed successfully */
+ IO_TIMEOUT = -1, /* operation timed out */
+ IO_CLOSED = -2, /* the connection has been closed */
+ IO_UNKNOWN = -3
+ };
+
+ /*-------------------------------------------------------------------------*\
+ * I/O error strings
+ \*-------------------------------------------------------------------------*/
+ const char *io_strerror(int err)
+ {
+ switch (err) {
+ case IO_DONE:
+ return NULL;
+ case IO_CLOSED:
+ return "closed";
+ case IO_TIMEOUT:
+ return "timeout";
+ default:
+ return "unknown error";
+ }
+ }
+
+ typedef int t_socket;
+ typedef t_socket *p_socket;
+ typedef struct sockaddr SA;
+
+#define SOCKET_INVALID (-1)
+
+#define WAITFD_R 1
+#define WAITFD_W 2
+#define WAITFD_C (WAITFD_R | WAITFD_W)
+
+ int socket_waitfd(p_socket ps, int sw, QT3DSU32 tm)
+ {
+ int ret;
+ fd_set rfds, wfds, *rp, *wp;
+ struct timeval tv, *tp = NULL;
+ if (tm == 0)
+ return IO_TIMEOUT; /* optimize timeout == 0 case */
+ if (tm < QT3DS_MAX_U32) {
+ // shoule consider max timeout specially by setting tp = NULL
+ // or you get invalid argument errno = 22
+ tv.tv_sec = (int)(tm / 1000);
+ QT3DSU32 leftover = tm % 1000;
+ tv.tv_usec = (int)(leftover * 100000);
+ tp = &tv;
+ }
+ do {
+ /* must set bits within loop, because select may have modifed them */
+ rp = wp = NULL;
+ if (sw & WAITFD_R) {
+ FD_ZERO(&rfds);
+ FD_SET(*ps, &rfds);
+ rp = &rfds;
+ }
+ if (sw & WAITFD_W) {
+ FD_ZERO(&wfds);
+ FD_SET(*ps, &wfds);
+ wp = &wfds;
+ }
+ ret = select(*ps + 1, rp, wp, NULL, tp);
+ } while (ret == -1 && errno == EINTR);
+ if (ret == -1)
+ return errno;
+ if (ret == 0)
+ return IO_TIMEOUT;
+ if (sw == WAITFD_C && FD_ISSET(*ps, &rfds))
+ return IO_CLOSED;
+ return IO_DONE;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Initializes module
+ \*-------------------------------------------------------------------------*/
+ int socket_open(void)
+ {
+ /* instals a handler to ignore sigpipe or it will crash us */
+ signal(SIGPIPE, SIG_IGN);
+ return 1;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Close module
+ \*-------------------------------------------------------------------------*/
+ int socket_close(void) { return 1; }
+
+ /*-------------------------------------------------------------------------*\
+ * Put socket into blocking mode
+ \*-------------------------------------------------------------------------*/
+ void socket_setblocking(p_socket ps)
+ {
+ int flags = fcntl(*ps, F_GETFL, 0);
+ flags &= (~(O_NONBLOCK));
+ fcntl(*ps, F_SETFL, flags);
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Put socket into non-blocking mode
+ \*-------------------------------------------------------------------------*/
+ void socket_setnonblocking(p_socket ps)
+ {
+ int flags = fcntl(*ps, F_GETFL, 0);
+ flags |= O_NONBLOCK;
+ fcntl(*ps, F_SETFL, flags);
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Close and inutilize socket
+ \*-------------------------------------------------------------------------*/
+ void socket_destroy(p_socket ps)
+ {
+ if (*ps != SOCKET_INVALID) {
+ socket_setblocking(ps);
+ close(*ps);
+ *ps = SOCKET_INVALID;
+ }
+ }
+ /*-------------------------------------------------------------------------*\
+ *
+ \*-------------------------------------------------------------------------*/
+ void socket_shutdown(p_socket ps, int how)
+ {
+ socket_setblocking(ps);
+ shutdown(*ps, how);
+ socket_setnonblocking(ps);
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Creates and sets up a socket
+ \*-------------------------------------------------------------------------*/
+ int socket_create(p_socket ps, int domain, int type, int protocol)
+ {
+ *ps = socket(domain, type, protocol);
+ if (*ps != SOCKET_INVALID)
+ return IO_DONE;
+ else
+ return errno;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ *
+ \*-------------------------------------------------------------------------*/
+ int socket_listen(p_socket ps, int backlog)
+ {
+ int err = IO_DONE;
+ socket_setblocking(ps);
+ if (listen(*ps, backlog))
+ err = errno;
+ socket_setnonblocking(ps);
+ return err;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Binds or returns error message
+ \*-------------------------------------------------------------------------*/
+ int socket_bind(p_socket ps, SA *addr, socklen_t len)
+ {
+ int err = IO_DONE;
+ socket_setblocking(ps);
+ if (bind(*ps, addr, len) < 0)
+ err = errno;
+ socket_setnonblocking(ps);
+ return err;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Connects or returns error message
+ \*-------------------------------------------------------------------------*/
+ int socket_connect(p_socket ps, SA *addr, socklen_t len, QT3DSU32 tm)
+ {
+ int err;
+ /* avoid calling on closed sockets */
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ /* call connect until done or failed without being interrupted */
+ do
+ if (connect(*ps, addr, len) == 0)
+ return IO_DONE;
+ while ((err = errno) == EINTR);
+ /* if connection failed immediately, return error code */
+ if (err != EINPROGRESS && err != EAGAIN)
+ return err;
+ /* zero timeout case optimization */
+ if (tm == 0)
+ return IO_TIMEOUT;
+ /* wait until we have the result of the connection attempt or timeout */
+ err = socket_waitfd(ps, WAITFD_C, tm);
+ if (err == IO_CLOSED) {
+ if (recv(*ps, (char *)&err, 0, 0) == 0)
+ return IO_DONE;
+ else
+ return errno;
+ } else
+ return err;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Accept with timeout
+ \*-------------------------------------------------------------------------*/
+ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, QT3DSU32 tm)
+ {
+ SA daddr;
+ socklen_t dlen = sizeof(daddr);
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ if (!addr)
+ addr = &daddr;
+ if (!len)
+ len = &dlen;
+ for (;;) {
+ int err;
+ if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID)
+ return IO_DONE;
+ err = errno;
+ if (err == EINTR)
+ continue;
+ if (err != EAGAIN && err != ECONNABORTED)
+ return err;
+ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE)
+ return err;
+ }
+ /* can't reach here */
+ return IO_UNKNOWN;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Send with timeout
+ \*-------------------------------------------------------------------------*/
+ int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, QT3DSU32 tm)
+ {
+ int err;
+ *sent = 0;
+ /* avoid making system calls on closed sockets */
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ /* loop until we send something or we give up on error */
+ for (;;) {
+ long put = (long)send(*ps, data, count, 0);
+ /* if we sent anything, we are done */
+ if (put > 0) {
+ *sent = put;
+ return IO_DONE;
+ }
+ err = errno;
+ /* send can't really return 0, but EPIPE means the connection was closed */
+ if (put == 0 || err == EPIPE)
+ return IO_CLOSED;
+ /* we call was interrupted, just try again */
+ if (err == EINTR)
+ continue;
+ /* if failed fatal reason, report error */
+ if (err != EAGAIN)
+ return err;
+ /* wait until we can send something or we timeout */
+ if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE)
+ return err;
+ }
+ /* can't reach here */
+ return IO_UNKNOWN;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Receive with timeout
+ \*-------------------------------------------------------------------------*/
+ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, QT3DSU32 tm)
+ {
+ int err;
+ *got = 0;
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ for (;;) {
+ long taken = (long)recv(*ps, data, count, 0);
+ if (taken > 0) {
+ *got = taken;
+ return IO_DONE;
+ }
+ err = errno;
+ if (taken == 0)
+ return IO_CLOSED;
+ if (err == EINTR)
+ continue;
+ if (err != EAGAIN)
+ return err;
+ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE)
+ return err;
+ }
+ return IO_UNKNOWN;
+ }
+
+ int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp)
+ {
+ *hp = gethostbyaddr(addr, len, AF_INET);
+ if (*hp)
+ return IO_DONE;
+ else if (h_errno)
+ return h_errno;
+ else if (errno)
+ return errno;
+ else
+ return IO_UNKNOWN;
+ }
+
+ int socket_gethostbyname(const char *addr, struct hostent **hp)
+ {
+ *hp = gethostbyname(addr);
+ if (*hp)
+ return IO_DONE;
+ else if (h_errno)
+ return h_errno;
+ else if (errno)
+ return errno;
+ else
+ return IO_UNKNOWN;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Error translation functions
+ * Make sure important error messages are standard
+ \*-------------------------------------------------------------------------*/
+ const char *socket_hoststrerror(int err)
+ {
+ if (err <= 0)
+ return io_strerror(err);
+ switch (err) {
+ case HOST_NOT_FOUND:
+ return "host not found";
+ default:
+ return hstrerror(err);
+ }
+ }
+
+ const char *socket_strerror(int err)
+ {
+ if (err <= 0)
+ return io_strerror(err);
+ switch (err) {
+ case EADDRINUSE:
+ return "address already in use";
+ case EISCONN:
+ return "already connected";
+ case EACCES:
+ return "permission denied";
+ case ECONNREFUSED:
+ return "connection refused";
+ case ECONNABORTED:
+ return "closed";
+ case ECONNRESET:
+ return "closed";
+ case ETIMEDOUT:
+ return "timeout";
+ default:
+ return strerror(errno);
+ }
+ }
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixAtomic.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixAtomic.cpp
new file mode 100644
index 00000000..c1ac3965
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixAtomic.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2001-2004 NovodeX AG.
+** Copyright (C) 2004-2008 AGEIA Technologies, Inc.
+** Copyright (C) 2008-2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAtomic.h"
+
+#define PAUSE() asm("nop")
+
+namespace qt3ds {
+namespace foundation {
+
+ void *atomicCompareExchangePointer(volatile void **dest, void *exch, void *comp)
+ {
+ return __sync_val_compare_and_swap((void **)dest, comp, exch);
+ }
+
+ QT3DSI32 atomicCompareExchange(volatile QT3DSI32 *dest, QT3DSI32 exch, QT3DSI32 comp)
+ {
+ return __sync_val_compare_and_swap(dest, comp, exch);
+ }
+
+ QT3DSI32 atomicIncrement(volatile QT3DSI32 *val) { return __sync_add_and_fetch(val, 1); }
+
+ QT3DSI32 atomicDecrement(volatile QT3DSI32 *val) { return __sync_sub_and_fetch(val, 1); }
+
+ QT3DSI32 atomicAdd(volatile QT3DSI32 *val, QT3DSI32 delta) { return __sync_add_and_fetch(val, delta); }
+
+ QT3DSI32 atomicMax(volatile QT3DSI32 *val, QT3DSI32 val2)
+ {
+ QT3DSI32 oldVal, newVal;
+
+ do {
+ PAUSE();
+ oldVal = *val;
+
+ if (val2 > oldVal)
+ newVal = val2;
+ else
+ newVal = oldVal;
+
+ } while (atomicCompareExchange(val, newVal, oldVal) != oldVal);
+
+ return *val;
+ }
+
+ QT3DSI32 atomicExchange(volatile QT3DSI32 *val, QT3DSI32 val2)
+ {
+ QT3DSI32 newVal, oldVal;
+
+ do {
+ PAUSE();
+ oldVal = *val;
+ newVal = val2;
+ } while (atomicCompareExchange(val, newVal, oldVal) != oldVal);
+
+ return oldVal;
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixFPU.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixFPU.cpp
new file mode 100644
index 00000000..59c9850d
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixFPU.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2001-2004 NovodeX AG.
+** Copyright (C) 2004-2008 AGEIA Technologies, Inc.
+** Copyright (C) 2008-2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSFPU.h"
+#include <fenv.h>
+
+#if !(defined(__CYGWIN__) || defined(PX_ANDROID))
+QT3DS_COMPILE_TIME_ASSERT(8 * sizeof(qt3ds::QT3DSU32) >= sizeof(fenv_t));
+#endif
+
+qt3ds::foundation::FPUGuard::FPUGuard()
+{
+#if defined(__CYGWIN__)
+#pragma message "FPUGuard::FPUGuard() is not implemented"
+#elif defined(PX_ANDROID)
+// not supported unless ARM_HARD_FLOAT is enabled.
+#else
+ fegetenv(reinterpret_cast<fenv_t *>(mControlWords));
+ fesetenv(FE_DFL_ENV);
+#endif
+}
+
+qt3ds::foundation::FPUGuard::~FPUGuard()
+{
+#if defined(__CYGWIN__)
+#pragma message "FPUGuard::~FPUGuard() is not implemented"
+#elif defined(PX_ANDROID)
+// not supported unless ARM_HARD_FLOAT is enabled.
+#else
+ fesetenv(reinterpret_cast<fenv_t *>(mControlWords));
+#endif
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixMutex.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixMutex.cpp
new file mode 100644
index 00000000..bbc55829
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixMutex.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAtomic.h"
+
+#include <pthread.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ namespace {
+ pthread_mutex_t *getMutex(MutexImpl *impl)
+ {
+ return reinterpret_cast<pthread_mutex_t *>(impl);
+ }
+ }
+
+ MutexImpl::MutexImpl()
+ {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(getMutex(this), &attr);
+ pthread_mutexattr_destroy(&attr);
+ }
+
+ MutexImpl::~MutexImpl() { pthread_mutex_destroy(getMutex(this)); }
+
+ bool MutexImpl::lock() { return !pthread_mutex_lock(getMutex(this)); }
+
+ bool MutexImpl::trylock() { return !pthread_mutex_trylock(getMutex(this)); }
+
+ bool MutexImpl::unlock() { return !pthread_mutex_unlock(getMutex(this)); }
+
+ const QT3DSU32 MutexImpl::size = sizeof(pthread_mutex_t);
+
+ class ReadWriteLockImpl
+ {
+ public:
+ ReadWriteLockImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ pthread_mutex_t mutex;
+ volatile int readerCounter;
+ };
+
+ ReadWriteLock::ReadWriteLock(NVAllocatorCallback &alloc)
+ {
+ mImpl = QT3DS_NEW(alloc, ReadWriteLockImpl)(alloc);
+
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mImpl->mutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+
+ mImpl->readerCounter = 0;
+ }
+
+ ReadWriteLock::~ReadWriteLock()
+ {
+ pthread_mutex_destroy(&mImpl->mutex);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ void ReadWriteLock::lockReader()
+ {
+ pthread_mutex_lock(&mImpl->mutex);
+
+ atomicIncrement(&mImpl->readerCounter);
+
+ pthread_mutex_unlock(&mImpl->mutex);
+ }
+
+ void ReadWriteLock::lockWriter()
+ {
+ pthread_mutex_lock(&mImpl->mutex);
+
+ while (mImpl->readerCounter != 0)
+ ;
+ }
+
+ void ReadWriteLock::unlockReader() { atomicDecrement(&mImpl->readerCounter); }
+
+ void ReadWriteLock::unlockWriter() { pthread_mutex_unlock(&mImpl->mutex); }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSemaphore.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSemaphore.cpp
new file mode 100644
index 00000000..90aab79a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSemaphore.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSSemaphore.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ class SemaphoreImpl
+ {
+ public:
+ SemaphoreImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ QT3DSU32 count;
+ QT3DSU32 maxCount;
+ };
+
+ struct NVLinuxScopeLock
+ {
+ NVLinuxScopeLock(pthread_mutex_t &m)
+ : mMutex(m)
+ {
+ pthread_mutex_lock(&mMutex);
+ }
+
+ ~NVLinuxScopeLock() { pthread_mutex_unlock(&mMutex); }
+ private:
+ pthread_mutex_t &mMutex;
+ };
+
+ Semaphore::Semaphore(NVAllocatorCallback &alloc, QT3DSU32 initialCount, QT3DSU32 maxCount)
+ {
+ mImpl = QT3DS_NEW(alloc, SemaphoreImpl)(alloc);
+ int status = pthread_mutex_init(&mImpl->mutex, 0);
+ QT3DS_ASSERT(!status);
+ status = pthread_cond_init(&mImpl->cond, 0);
+ QT3DS_ASSERT(!status);
+ mImpl->count = initialCount;
+ mImpl->maxCount = maxCount;
+ QT3DS_ASSERT(initialCount <= maxCount);
+ }
+
+ Semaphore::~Semaphore()
+ {
+ pthread_cond_destroy(&mImpl->cond);
+ pthread_mutex_destroy(&mImpl->mutex);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ bool Semaphore::wait(QT3DSU32 milliseconds)
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+
+ if (mImpl->count > 0) {
+ mImpl->count--;
+ return true;
+ }
+
+ if (milliseconds == 0) {
+ return false;
+ }
+
+ if (milliseconds == QT3DSU32(-1)) {
+ int status = pthread_cond_wait(&mImpl->cond, &mImpl->mutex);
+ QT3DS_ASSERT(!status);
+ (void)status;
+ } else {
+ timespec ts;
+ timeval tp;
+ gettimeofday(&tp, NULL);
+ QT3DSU32 sec = milliseconds / 1000;
+ QT3DSU32 usec = (milliseconds - 1000 * sec) * 1000;
+
+ // sschirm: taking into account that us might accumulate to a second
+ // otherwise the pthread_cond_timedwait complains on osx.
+ usec = tp.tv_usec + usec;
+ QT3DSU32 div_sec = usec / 1000000;
+ QT3DSU32 rem_usec = usec - div_sec * 1000000;
+
+ ts.tv_sec = tp.tv_sec + sec + div_sec;
+ ts.tv_nsec = rem_usec * 1000;
+
+ int ierr = pthread_cond_timedwait(&mImpl->cond, &mImpl->mutex, &ts);
+ QT3DS_ASSERT((ierr == 0) || (ierr == ETIMEDOUT));
+ (void)ierr;
+ return false;
+ }
+
+ return true;
+ }
+
+ void Semaphore::post()
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ mImpl->count++;
+ if (mImpl->count > mImpl->maxCount)
+ mImpl->count = mImpl->maxCount;
+ else {
+ pthread_cond_broadcast(&mImpl->cond);
+ }
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSync.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSync.cpp
new file mode 100644
index 00000000..52f9d7ab
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixSync.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+namespace qt3ds {
+namespace foundation {
+
+ class SyncImpl
+ {
+ public:
+ SyncImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ volatile bool is_set;
+ };
+
+ struct NVLinuxScopeLock
+ {
+ NVLinuxScopeLock(pthread_mutex_t &m)
+ : mMutex(m)
+ {
+ pthread_mutex_lock(&mMutex);
+ }
+
+ ~NVLinuxScopeLock() { pthread_mutex_unlock(&mMutex); }
+ private:
+ pthread_mutex_t &mMutex;
+ };
+
+ Sync::Sync(NVAllocatorCallback &alloc)
+ {
+ mImpl = QT3DS_NEW(alloc, SyncImpl)(alloc);
+ int status = pthread_mutex_init(&mImpl->mutex, 0);
+ QT3DS_ASSERT(!status);
+ status = pthread_cond_init(&mImpl->cond, 0);
+ QT3DS_ASSERT(!status);
+ mImpl->is_set = false;
+ }
+
+ Sync::~Sync()
+ {
+ pthread_cond_destroy(&mImpl->cond);
+ pthread_mutex_destroy(&mImpl->mutex);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ void Sync::reset()
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ mImpl->is_set = false;
+ }
+
+ void Sync::set()
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ if (!mImpl->is_set) {
+ mImpl->is_set = true;
+ pthread_cond_broadcast(&mImpl->cond);
+ }
+ }
+
+ bool Sync::wait(QT3DSU32 ms)
+ {
+ NVLinuxScopeLock lock(mImpl->mutex);
+ if (!mImpl->is_set) {
+ if (ms == QT3DSU32(-1)) {
+ int status = pthread_cond_wait(&mImpl->cond, &mImpl->mutex);
+ QT3DS_ASSERT(!status);
+ (void)status;
+ } else {
+ timespec ts;
+ timeval tp;
+ gettimeofday(&tp, NULL);
+ QT3DSU32 sec = ms / 1000;
+ QT3DSU32 usec = (ms - 1000 * sec) * 1000;
+
+ // sschirm: taking into account that us might accumulate to a second
+ // otherwise the pthread_cond_timedwait complains on osx.
+ usec = tp.tv_usec + usec;
+ QT3DSU32 div_sec = usec / 1000000;
+ QT3DSU32 rem_usec = usec - div_sec * 1000000;
+
+ ts.tv_sec = tp.tv_sec + sec + div_sec;
+ ts.tv_nsec = rem_usec * 1000;
+
+ int ierr = pthread_cond_timedwait(&mImpl->cond, &mImpl->mutex, &ts);
+ QT3DS_ASSERT((ierr == 0) || (ierr == ETIMEDOUT));
+ (void)ierr;
+ }
+ }
+ return mImpl->is_set;
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixTime.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixTime.cpp
new file mode 100644
index 00000000..58eadcb6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/macosx/Qt3DSUnixTime.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2001-2004 NovodeX AG.
+** Copyright (C) 2004-2008 AGEIA Technologies, Inc.
+** Copyright (C) 2008-2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSTime.h"
+
+#include <time.h>
+#include <sys/time.h>
+
+#if defined QT3DS_APPLE
+#include <mach/mach_time.h>
+#endif
+
+// Use real-time high-precision timer.
+#ifndef QT3DS_APPLE
+#define CLOCKID CLOCK_REALTIME
+#endif
+
+namespace qt3ds {
+namespace foundation {
+
+ const CounterFrequencyToTensOfNanos Time::sCounterFreq = Time::getCounterFrequency();
+
+ static Time::Second getTimeSeconds()
+ {
+ static struct timeval _tv;
+ gettimeofday(&_tv, NULL);
+ return double(_tv.tv_sec) + double(_tv.tv_usec) * 0.000001;
+ }
+
+ Time::Time() { mLastTime = getTimeSeconds(); }
+
+ Time::Second Time::getElapsedSeconds()
+ {
+ Time::Second curTime = getTimeSeconds();
+ Time::Second diff = curTime - mLastTime;
+ mLastTime = curTime;
+ return diff;
+ }
+
+ Time::Second Time::peekElapsedSeconds()
+ {
+ Time::Second curTime = getTimeSeconds();
+ Time::Second diff = curTime - mLastTime;
+ return diff;
+ }
+
+ Time::Second Time::getLastTime() const { return mLastTime; }
+
+#ifdef QT3DS_APPLE
+ CounterFrequencyToTensOfNanos Time::getCounterFrequency()
+ {
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+ // mach_absolute_time * (info.numer/info.denom) is in units of nano seconds
+ return CounterFrequencyToTensOfNanos(info.numer, info.denom * 10);
+ }
+
+ QT3DSU64 Time::getCurrentCounterValue() { return mach_absolute_time(); }
+
+#else
+
+ CounterFrequencyToTensOfNanos Time::getCounterFrequency()
+ {
+ return CounterFrequencyToTensOfNanos(1, 10);
+ }
+
+ PxU64 Time::getCurrentCounterValue()
+ {
+ struct timespec mCurrTimeInt;
+ clock_gettime(CLOCKID, &mCurrTimeInt);
+ // Convert to nanos as this doesn't cause a large divide here
+ return (static_cast<PxU64>(mCurrTimeInt.tv_sec) * 1000000000)
+ + (static_cast<PxU64>(mCurrTimeInt.tv_nsec));
+ }
+#endif
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/qt_attribution.json b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/qt_attribution.json
new file mode 100644
index 00000000..dd58b0b6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/qt_attribution.json
@@ -0,0 +1,11 @@
+{
+ "Id": "socket",
+ "Name": "Socket",
+ "QDocModule": "qt3dstudio",
+ "QtUsage": "Used by Qt3DStudio, Runtime component.",
+
+ "License": "MIT license",
+ "LicenseId": "MIT",
+ "LicenseFile": "LICENCE_SOCKET.TXT",
+ "Copyright": "Copyright (C) 2004-2013 Diego Nehab."
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsAtomic.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsAtomic.cpp
new file mode 100644
index 00000000..4f95d3dd
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsAtomic.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/windows/Qt3DSWindowsInclude.h"
+#include "foundation/Qt3DSAtomic.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ QT3DSI32 atomicExchange(volatile QT3DSI32 *val, QT3DSI32 val2)
+ {
+ return (QT3DSI32)InterlockedExchange((volatile LONG *)val, (LONG)val2);
+ }
+
+ QT3DSI32 atomicCompareExchange(volatile QT3DSI32 *dest, QT3DSI32 exch, QT3DSI32 comp)
+ {
+ return (QT3DSI32)InterlockedCompareExchange((volatile LONG *)dest, exch, comp);
+ }
+
+ void *atomicCompareExchangePointer(volatile void **dest, void *exch, void *comp)
+ {
+ return InterlockedCompareExchangePointer((volatile PVOID *)dest, exch, comp);
+ }
+
+ QT3DSI32 atomicIncrement(volatile QT3DSI32 *val)
+ {
+ return (QT3DSI32)InterlockedIncrement((volatile LONG *)val);
+ }
+
+ QT3DSI32 atomicDecrement(volatile QT3DSI32 *val)
+ {
+ return (QT3DSI32)InterlockedDecrement((volatile LONG *)val);
+ }
+
+ QT3DSI32 atomicAdd(volatile QT3DSI32 *val, QT3DSI32 delta)
+ {
+ LONG newValue, oldValue;
+ do {
+ oldValue = *val;
+ newValue = oldValue + delta;
+ } while (InterlockedCompareExchange((volatile LONG *)val, newValue, oldValue) != oldValue);
+
+ return newValue;
+ }
+
+ QT3DSI32 atomicMax(volatile QT3DSI32 *val, QT3DSI32 val2)
+ {
+ // Could do this more efficiently in asm...
+
+ LONG newValue, oldValue;
+
+ do {
+ oldValue = *val;
+
+ if (val2 > oldValue)
+ newValue = val2;
+ else
+ newValue = oldValue;
+
+ } while (InterlockedCompareExchange((volatile LONG *)val, newValue, oldValue) != oldValue);
+
+ return newValue;
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsFPU.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsFPU.cpp
new file mode 100644
index 00000000..a809026f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsFPU.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "foundation/Qt3DSFPU.h"
+#include "float.h"
+
+#ifdef QT3DS_X64
+#define _MCW_ALL _MCW_DN | _MCW_EM | _MCW_RC
+#else
+#define _MCW_ALL _MCW_DN | _MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC
+#endif
+
+qt3ds::foundation::FPUGuard::FPUGuard()
+{
+// default plus FTZ and DAZ
+#ifdef QT3DS_WINDOWS
+#ifdef QT3DS_X64
+ _controlfp_s(mControlWords, _CW_DEFAULT | _DN_FLUSH, _MCW_ALL);
+#else
+ __control87_2(_CW_DEFAULT | _DN_FLUSH, _MCW_ALL, mControlWords, mControlWords + 1);
+#endif
+#endif
+}
+
+qt3ds::foundation::FPUGuard::~FPUGuard()
+{
+#ifdef QT3DS_WINDOWS
+#ifdef QT3DS_X64
+ _controlfp_s(mControlWords, *mControlWords, _MCW_ALL);
+#else
+ __control87_2(mControlWords[0], _MCW_ALL, mControlWords, 0);
+ __control87_2(mControlWords[1], _MCW_ALL, 0, mControlWords + 1);
+#endif
+#endif
+}
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsMutex.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsMutex.cpp
new file mode 100644
index 00000000..c5fef09f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsMutex.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/windows/Qt3DSWindowsInclude.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSAssert.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ namespace {
+ CRITICAL_SECTION *getMutex(MutexImpl *impl)
+ {
+ return reinterpret_cast<CRITICAL_SECTION *>(impl);
+ }
+ }
+
+ MutexImpl::MutexImpl() { InitializeCriticalSection(getMutex(this)); }
+
+ MutexImpl::~MutexImpl() { DeleteCriticalSection(getMutex(this)); }
+
+ bool MutexImpl::lock()
+ {
+ EnterCriticalSection(getMutex(this));
+ return true;
+ }
+
+ bool MutexImpl::trylock() { return TryEnterCriticalSection(getMutex(this)) != 0; }
+
+ bool MutexImpl::unlock()
+ {
+ LeaveCriticalSection(getMutex(this));
+ return true;
+ }
+
+ const QT3DSU32 MutexImpl::size = sizeof(CRITICAL_SECTION);
+
+ class ReadWriteLockImpl
+ {
+ public:
+ ReadWriteLockImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ HANDLE hReaderEvent;
+ HANDLE hMutex;
+ CRITICAL_SECTION writerMutex;
+ LONG counter; // count the number of readers in the lock.
+ LONG recursionCounter; // handle recursive writer locking
+ };
+
+ ReadWriteLock::ReadWriteLock(NVAllocatorCallback &alloc)
+ {
+ mImpl = QT3DS_NEW(alloc, ReadWriteLockImpl)(alloc);
+
+ mImpl->hReaderEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ QT3DS_ASSERT(mImpl->hReaderEvent != NULL);
+
+ mImpl->hMutex = CreateEvent(NULL, FALSE, TRUE, NULL);
+ QT3DS_ASSERT(mImpl->hMutex != NULL);
+
+ InitializeCriticalSection(&mImpl->writerMutex);
+ mImpl->counter = -1;
+ mImpl->recursionCounter = 0;
+ }
+
+ ReadWriteLock::~ReadWriteLock()
+ {
+ if (mImpl->hReaderEvent != NULL) {
+ CloseHandle(mImpl->hReaderEvent);
+ }
+
+ if (mImpl->hMutex != NULL) {
+ CloseHandle(mImpl->hMutex);
+ }
+
+ DeleteCriticalSection(&mImpl->writerMutex);
+
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ void ReadWriteLock::lockReader()
+ {
+ if (InterlockedIncrement(&mImpl->counter) == 0) {
+ WaitForSingleObject(mImpl->hMutex, INFINITE);
+ SetEvent(mImpl->hReaderEvent);
+ }
+
+ WaitForSingleObject(mImpl->hReaderEvent, INFINITE);
+ }
+
+ void ReadWriteLock::lockWriter()
+ {
+ EnterCriticalSection(&mImpl->writerMutex);
+
+ // we may already have the global mutex(really an event so we have to handle recursion
+ // ourselves)
+ if (++mImpl->recursionCounter == 1) {
+ WaitForSingleObject(mImpl->hMutex, INFINITE);
+ }
+ }
+
+ void ReadWriteLock::unlockReader()
+ {
+ if (InterlockedDecrement(&mImpl->counter) < 0) {
+ ResetEvent(mImpl->hReaderEvent);
+ SetEvent(mImpl->hMutex);
+ }
+ }
+
+ void ReadWriteLock::unlockWriter()
+ {
+ if (--mImpl->recursionCounter == 0) {
+ SetEvent(mImpl->hMutex);
+ }
+
+ LeaveCriticalSection(&mImpl->writerMutex);
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSemaphore.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSemaphore.cpp
new file mode 100644
index 00000000..bb14c104
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSemaphore.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/windows/Qt3DSWindowsInclude.h"
+#include "foundation/Qt3DSSemaphore.h"
+#include "foundation/Qt3DSAllocator.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ class SemaphoreImpl
+ {
+ public:
+ SemaphoreImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ HANDLE handle;
+ };
+
+ Semaphore::Semaphore(NVAllocatorCallback &alloc, QT3DSU32 initialCount, QT3DSU32 maxCount)
+ {
+ mImpl = QT3DS_NEW(alloc, SemaphoreImpl)(alloc);
+ mImpl->handle = CreateSemaphore(0, initialCount, maxCount, (LPCTSTR)NULL);
+ }
+
+ Semaphore::~Semaphore()
+ {
+ CloseHandle(mImpl->handle);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ bool Semaphore::wait(QT3DSU32 milliseconds)
+ {
+ if (milliseconds == -1)
+ milliseconds = INFINITE;
+
+ return WaitForSingleObject(mImpl->handle, milliseconds) == WAIT_OBJECT_0 ? true : false;
+ }
+
+ void Semaphore::post() { ReleaseSemaphore(mImpl->handle, 1, (LPLONG)NULL); }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSync.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSync.cpp
new file mode 100644
index 00000000..49667e94
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsSync.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/windows/Qt3DSWindowsInclude.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSAllocator.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ class SyncImpl
+ {
+ public:
+ SyncImpl(NVAllocatorCallback &alloc)
+ : mAllocator(alloc)
+ {
+ }
+ NVAllocatorCallback &mAllocator;
+ HANDLE handle;
+ };
+
+ Sync::Sync(NVAllocatorCallback &alloc)
+ {
+ mImpl = QT3DS_NEW(alloc, SyncImpl)(alloc);
+ mImpl->handle = CreateEvent(0, true, false, 0);
+ }
+
+ Sync::~Sync()
+ {
+ CloseHandle(mImpl->handle);
+ QT3DS_FREE(mImpl->mAllocator, mImpl);
+ }
+
+ void Sync::reset() { ResetEvent(mImpl->handle); }
+
+ void Sync::set() { SetEvent(mImpl->handle); }
+
+ bool Sync::wait(QT3DSU32 milliseconds)
+ {
+ if (milliseconds == -1)
+ milliseconds = INFINITE;
+
+ return WaitForSingleObject(mImpl->handle, milliseconds) == WAIT_OBJECT_0 ? true : false;
+ }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsThread.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsThread.cpp
new file mode 100644
index 00000000..c48a99da
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsThread.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/windows/Qt3DSWindowsInclude.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSThread.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+// an exception for setting the thread name in microsoft debuggers
+#define QT3DS_MS_VC_EXCEPTION 0x406D1388
+
+namespace qt3ds {
+namespace foundation {
+
+// struct for naming a thread in the debugger
+#pragma pack(push, 8)
+
+ typedef struct tagTHREADNAME_INFO
+ {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+ } THREADNAME_INFO;
+
+#pragma pack(pop)
+
+ namespace {
+
+ DWORD WINAPI NVThreadStart(LPVOID arg)
+ {
+ ((Thread *)arg)->execute();
+ return 0;
+ }
+ }
+
+ class ThreadImpl
+ {
+ public:
+ enum State { NotStarted, Started, Stopped };
+ ThreadImpl(NVFoundationBase &foundation)
+ : mFoundation(foundation)
+ {
+ }
+ NVFoundationBase &mFoundation;
+ HANDLE thread;
+ LONG quitNow; // Should be 32bit aligned on SMP systems.
+ State state;
+ DWORD threadID;
+
+ Thread::ExecuteFn fn;
+ void *arg;
+ };
+
+ Thread::Id Thread::getId() { return static_cast<Id>(GetCurrentThreadId()); }
+
+ Thread::Thread(NVFoundationBase &foundation)
+ {
+ mImpl = (ThreadImpl *)QT3DS_NEW(foundation.getAllocator(), ThreadImpl)(foundation);
+ mImpl->thread = NULL;
+ mImpl->state = ThreadImpl::NotStarted;
+ mImpl->quitNow = 0;
+ }
+
+ Thread::Thread(NVFoundationBase &foundation, ExecuteFn fn, void *arg)
+ {
+ mImpl = (ThreadImpl *)QT3DS_NEW(foundation.getAllocator(), ThreadImpl)(foundation);
+ mImpl->thread = NULL;
+ mImpl->state = ThreadImpl::NotStarted;
+ mImpl->quitNow = 0;
+ mImpl->fn = fn;
+ mImpl->arg = arg;
+
+ start(0);
+ }
+
+ Thread::~Thread()
+ {
+ if (mImpl->state == ThreadImpl::Started)
+ kill();
+ CloseHandle(mImpl->thread);
+ QT3DS_FREE(mImpl->mFoundation.getAllocator(), mImpl);
+ }
+
+ void Thread::start(QT3DSU32 stackSize)
+ {
+ if (mImpl->state != ThreadImpl::NotStarted)
+ return;
+ mImpl->state = ThreadImpl::Started;
+
+ mImpl->thread =
+ CreateThread(NULL, stackSize, NVThreadStart, (LPVOID)this, 0, &mImpl->threadID);
+ }
+
+ void Thread::signalQuit() { InterlockedIncrement(&(mImpl->quitNow)); }
+
+ bool Thread::waitForQuit()
+ {
+ if (mImpl->state == ThreadImpl::NotStarted)
+ return false;
+
+ WaitForSingleObject(mImpl->thread, INFINITE);
+ return true;
+ }
+
+ bool Thread::quitIsSignalled()
+ {
+ return InterlockedCompareExchange(&(mImpl->quitNow), 0, 0) != 0;
+ }
+
+ void Thread::quit()
+ {
+ mImpl->state = ThreadImpl::Stopped;
+ ExitThread(0);
+ }
+
+ void Thread::kill()
+ {
+ if (mImpl->state == ThreadImpl::Started)
+ TerminateThread(mImpl->thread, 0);
+ mImpl->state = ThreadImpl::Stopped;
+ }
+
+ void Thread::sleep(QT3DSU32 ms) { Sleep(ms); }
+
+ void Thread::yield() { SwitchToThread(); }
+
+ void Thread::execute(void) { (*mImpl->fn)(mImpl->arg); }
+
+ QT3DSU32 Thread::setAffinityMask(QT3DSU32 mask)
+ {
+ return mask ? (QT3DSU32)SetThreadAffinityMask(mImpl->thread, mask) : 0;
+ }
+
+ void Thread::setName(const char *name)
+ {
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = name;
+ info.dwThreadID = mImpl->threadID;
+ info.dwFlags = 0;
+
+ // C++ Exceptions are disabled for this project, but SEH is not (and cannot be)
+ // http://stackoverflow.com/questions/943087/what-exactly-will-happen-if-i-disable-c-exceptions-in-a-project
+ __try {
+ RaiseException(QT3DS_MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
+ (ULONG_PTR *)&info);
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ // this runs if not attached to a debugger (thus not really naming the thread)
+ }
+ }
+
+ void Thread::setPriority(ThreadPriority::Enum prio)
+ {
+ switch (prio) {
+ case ThreadPriority::eHIGH:
+ SetThreadPriority(mImpl->thread, THREAD_PRIORITY_HIGHEST);
+ break;
+ case ThreadPriority::eABOVE_NORMAL:
+ SetThreadPriority(mImpl->thread, THREAD_PRIORITY_ABOVE_NORMAL);
+ break;
+ case ThreadPriority::eNORMAL:
+ SetThreadPriority(mImpl->thread, THREAD_PRIORITY_NORMAL);
+ break;
+ case ThreadPriority::eBELOW_NORMAL:
+ SetThreadPriority(mImpl->thread, THREAD_PRIORITY_BELOW_NORMAL);
+ break;
+ case ThreadPriority::eLOW:
+ SetThreadPriority(mImpl->thread, THREAD_PRIORITY_LOWEST);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ThreadPriority::Enum Thread::getPriority(Id threadId)
+ {
+ ThreadPriority::Enum retval = ThreadPriority::eLOW;
+ int priority = GetThreadPriority((HANDLE)threadId);
+ StaticAssert<(THREAD_PRIORITY_HIGHEST > THREAD_PRIORITY_ABOVE_NORMAL)>::valid_expression();
+ if (priority >= THREAD_PRIORITY_HIGHEST)
+ retval = ThreadPriority::eHIGH;
+ else if (priority >= THREAD_PRIORITY_ABOVE_NORMAL)
+ retval = ThreadPriority::eABOVE_NORMAL;
+ else if (priority >= THREAD_PRIORITY_NORMAL)
+ retval = ThreadPriority::eNORMAL;
+ else if (priority >= THREAD_PRIORITY_BELOW_NORMAL)
+ retval = ThreadPriority::eBELOW_NORMAL;
+ return retval;
+ }
+
+ QT3DSU32 TlsAlloc()
+ {
+ DWORD rv = ::TlsAlloc();
+ QT3DS_ASSERT(rv != TLS_OUT_OF_INDEXES);
+ return (QT3DSU32)rv;
+ }
+
+ void TlsFree(QT3DSU32 index) { ::TlsFree(index); }
+
+ void *TlsGet(QT3DSU32 index) { return ::TlsGetValue(index); }
+
+ QT3DSU32 TlsSet(QT3DSU32 index, void *value) { return ::TlsSetValue(index, value); }
+
+ const QT3DSU32 Thread::DEFAULT_STACK_SIZE = 1048576;
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsTime.cpp b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsTime.cpp
new file mode 100644
index 00000000..9215d642
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/Qt3DSWindowsTime.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSTime.h"
+#include "foundation/windows/Qt3DSWindowsInclude.h"
+
+namespace {
+::qt3ds::QT3DSI64 getTimeTicks()
+{
+ LARGE_INTEGER a;
+ QueryPerformanceCounter(&a);
+ return a.QuadPart;
+}
+
+double getTickDuration()
+{
+ LARGE_INTEGER a;
+ QueryPerformanceFrequency(&a);
+ return 1.0f / double(a.QuadPart);
+}
+
+double sTickDuration = getTickDuration();
+} // namespace
+
+namespace qt3ds {
+namespace foundation {
+
+ const CounterFrequencyToTensOfNanos Time::sCounterFreq = Time::getCounterFrequency();
+
+ CounterFrequencyToTensOfNanos Time::getCounterFrequency()
+ {
+ LARGE_INTEGER freq;
+ QueryPerformanceFrequency(&freq);
+ return CounterFrequencyToTensOfNanos(Time::sNumTensOfNanoSecondsInASecond, freq.QuadPart);
+ }
+
+ QT3DSU64 Time::getCurrentCounterValue()
+ {
+ LARGE_INTEGER ticks;
+ QueryPerformanceCounter(&ticks);
+ return ticks.QuadPart;
+ }
+
+ Time::Time()
+ : mTickCount(0)
+ {
+ getElapsedSeconds();
+ }
+
+ Time::Second Time::getElapsedSeconds()
+ {
+ QT3DSI64 lastTickCount = mTickCount;
+ mTickCount = getTimeTicks();
+ return (mTickCount - lastTickCount) * sTickDuration;
+ }
+
+ Time::Second Time::peekElapsedSeconds()
+ {
+ return (getTimeTicks() - mTickCount) * sTickDuration;
+ }
+
+ Time::Second Time::getLastTime() const { return mTickCount * sTickDuration; }
+
+} // namespace foundation
+} // namespace qt3ds
diff --git a/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/SocketImpl.h b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/SocketImpl.h
new file mode 100644
index 00000000..f72203bd
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSFoundation/Source/foundation/windows/SocketImpl.h
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+LuaSocket 3.0 license
+Copyright � 2004-2013 Diego Nehab
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef FOUNDATION_WINDOWS_SOCKET_IMPL_H
+#define FOUNDATION_WINDOWS_SOCKET_IMPL_H
+#pragma once
+#include <winsock.h>
+#pragma warning(disable : 4127)
+#pragma warning(disable : 4702)
+
+namespace qt3ds {
+namespace foundation {
+ namespace socketimpl {
+
+ // Functions take from lua socket implementation. Note that it has an MIT license.
+
+ enum {
+ IO_DONE = 0, /* operation completed successfully */
+ IO_TIMEOUT = -1, /* operation timed out */
+ IO_CLOSED = -2, /* the connection has been closed */
+ IO_UNKNOWN = -3
+ };
+
+ /*-------------------------------------------------------------------------*\
+ * I/O error strings
+ \*-------------------------------------------------------------------------*/
+ const char *io_strerror(int err)
+ {
+ switch (err) {
+ case IO_DONE:
+ return NULL;
+ case IO_CLOSED:
+ return "closed";
+ case IO_TIMEOUT:
+ return "timeout";
+ default:
+ return "unknown error";
+ }
+ }
+
+ typedef int socklen_t;
+ typedef SOCKET t_socket;
+ typedef t_socket *p_socket;
+ typedef struct sockaddr SA;
+
+#define SOCKET_INVALID (INVALID_SOCKET)
+
+ static const char *wstrerror(int err)
+ {
+ switch (err) {
+ case WSAEINTR:
+ return "Interrupted function call";
+ case WSAEACCES:
+ return "Permission denied";
+ case WSAEFAULT:
+ return "Bad address";
+ case WSAEINVAL:
+ return "Invalid argument";
+ case WSAEMFILE:
+ return "Too many open files";
+ case WSAEWOULDBLOCK:
+ return "Resource temporarily unavailable";
+ case WSAEINPROGRESS:
+ return "Operation now in progress";
+ case WSAEALREADY:
+ return "Operation already in progress";
+ case WSAENOTSOCK:
+ return "Socket operation on nonsocket";
+ case WSAEDESTADDRREQ:
+ return "Destination address required";
+ case WSAEMSGSIZE:
+ return "Message too long";
+ case WSAEPROTOTYPE:
+ return "Protocol wrong type for socket";
+ case WSAENOPROTOOPT:
+ return "Bad protocol option";
+ case WSAEPROTONOSUPPORT:
+ return "Protocol not supported";
+ case WSAESOCKTNOSUPPORT:
+ return "Socket type not supported";
+ case WSAEOPNOTSUPP:
+ return "Operation not supported";
+ case WSAEPFNOSUPPORT:
+ return "Protocol family not supported";
+ case WSAEAFNOSUPPORT:
+ return "Address family not supported by protocol family";
+ case WSAEADDRINUSE:
+ return "Address already in use";
+ case WSAEADDRNOTAVAIL:
+ return "Cannot assign requested address";
+ case WSAENETDOWN:
+ return "Network is down";
+ case WSAENETUNREACH:
+ return "Network is unreachable";
+ case WSAENETRESET:
+ return "Network dropped connection on reset";
+ case WSAECONNABORTED:
+ return "Software caused connection abort";
+ case WSAECONNRESET:
+ return "Connection reset by peer";
+ case WSAENOBUFS:
+ return "No buffer space available";
+ case WSAEISCONN:
+ return "Socket is already connected";
+ case WSAENOTCONN:
+ return "Socket is not connected";
+ case WSAESHUTDOWN:
+ return "Cannot send after socket shutdown";
+ case WSAETIMEDOUT:
+ return "Connection timed out";
+ case WSAECONNREFUSED:
+ return "Connection refused";
+ case WSAEHOSTDOWN:
+ return "Host is down";
+ case WSAEHOSTUNREACH:
+ return "No route to host";
+ case WSAEPROCLIM:
+ return "Too many processes";
+ case WSASYSNOTREADY:
+ return "Network subsystem is unavailable";
+ case WSAVERNOTSUPPORTED:
+ return "Winsock.dll version out of range";
+ case WSANOTINITIALISED:
+ return "Successful WSAStartup not yet performed";
+ case WSAEDISCON:
+ return "Graceful shutdown in progress";
+ case WSAHOST_NOT_FOUND:
+ return "Host not found";
+ case WSATRY_AGAIN:
+ return "Nonauthoritative host not found";
+ case WSANO_RECOVERY:
+ return "Nonrecoverable name lookup error";
+ case WSANO_DATA:
+ return "Valid name, no data record of requested type";
+ default:
+ return "Unknown error";
+ }
+ }
+
+ const char *socket_strerror(int err)
+ {
+ switch (err) {
+ case WSAEADDRINUSE:
+ return "address already in use";
+ case WSAECONNREFUSED:
+ return "connection refused";
+ case WSAEISCONN:
+ return "already connected";
+ case WSAEACCES:
+ return "permission denied";
+ case WSAECONNABORTED:
+ return "closed";
+ case WSAECONNRESET:
+ return "closed";
+ case WSAETIMEDOUT:
+ return "timeout";
+ default:
+ return wstrerror(err);
+ }
+ }
+
+ int socket_open(void)
+ {
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(2, 0);
+ int err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0)
+ return 0;
+ if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
+ && (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
+ WSACleanup();
+ return 0;
+ }
+ return 1;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Close module
+ \*-------------------------------------------------------------------------*/
+ int socket_close(void)
+ {
+ WSACleanup();
+ return 1;
+ }
+
+/*-------------------------------------------------------------------------*\
+* Wait for readable/writable/connected socket with timeout
+\*-------------------------------------------------------------------------*/
+#define WAITFD_R 1
+#define WAITFD_W 2
+#define WAITFD_E 4
+#define WAITFD_C (WAITFD_E | WAITFD_W)
+
+ static int socket_waitfd(p_socket ps, int sw, QT3DSU32 timeoutMilliseconds)
+ {
+ int ret;
+ fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
+ struct timeval tv, *tp = NULL;
+ if (timeoutMilliseconds == 0)
+ return IO_TIMEOUT; /* optimize timeout == 0 case */
+ if (sw & WAITFD_R) {
+ FD_ZERO(&rfds);
+ FD_SET(*ps, &rfds);
+ rp = &rfds;
+ }
+ if (sw & WAITFD_W) {
+ FD_ZERO(&wfds);
+ FD_SET(*ps, &wfds);
+ wp = &wfds;
+ }
+ if (sw & WAITFD_C) {
+ FD_ZERO(&efds);
+ FD_SET(*ps, &efds);
+ ep = &efds;
+ }
+ if (timeoutMilliseconds >= 0.0) {
+ tv.tv_sec = (int)(timeoutMilliseconds / 1000);
+ QT3DSU32 leftover = timeoutMilliseconds % 1000;
+ tv.tv_usec = (int)(leftover * 100000);
+ tp = &tv;
+ }
+ ret = select(0, rp, wp, ep, tp);
+ if (ret == -1)
+ return WSAGetLastError();
+ if (ret == 0)
+ return IO_TIMEOUT;
+ if (sw == WAITFD_C && FD_ISSET(*ps, &efds))
+ return IO_CLOSED;
+ return IO_DONE;
+ }
+
+ static int socket_send(p_socket ps, const char *data, size_t count, size_t *sent,
+ QT3DSU32 timeoutMilliseconds)
+ {
+ int err;
+ *sent = 0;
+ /* avoid making system calls on closed sockets */
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ /* loop until we send something or we give up on error */
+ for (;;) {
+ /* try to send something */
+ int put = send(*ps, data, (int)count, 0);
+ /* if we sent something, we are done */
+ if (put > 0) {
+ *sent = put;
+ return IO_DONE;
+ }
+ /* deal with failure */
+ err = WSAGetLastError();
+ /* we can only proceed if there was no serious error */
+ if (err != WSAEWOULDBLOCK)
+ return err;
+ /* avoid busy wait */
+ if ((err = socket_waitfd(ps, WAITFD_W, timeoutMilliseconds)) != IO_DONE)
+ return err;
+ }
+ /* can't reach here */
+ return IO_UNKNOWN;
+ }
+ /*-------------------------------------------------------------------------*\
+ * Receive with timeout
+ \*-------------------------------------------------------------------------*/
+ static int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
+ QT3DSU32 timeoutMilliseconds)
+ {
+ int err;
+ *got = 0;
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ for (;;) {
+ int taken = recv(*ps, data, (int)count, 0);
+ if (taken > 0) {
+ *got = taken;
+ return IO_DONE;
+ }
+ if (taken == 0)
+ return IO_CLOSED;
+ err = WSAGetLastError();
+ if (err != WSAEWOULDBLOCK)
+ return err;
+ if ((err = socket_waitfd(ps, WAITFD_R, timeoutMilliseconds)) != IO_DONE)
+ return err;
+ }
+ return IO_UNKNOWN;
+ }
+
+ void socket_setblocking(p_socket ps)
+ {
+ u_long argp = 0;
+ ioctlsocket(*ps, FIONBIO, &argp);
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Put socket into non-blocking mode
+ \*-------------------------------------------------------------------------*/
+ void socket_setnonblocking(p_socket ps)
+ {
+ u_long argp = 1;
+ ioctlsocket(*ps, FIONBIO, &argp);
+ }
+
+ int socket_listen(p_socket ps, int backlog)
+ {
+ int err = IO_DONE;
+ socket_setblocking(ps);
+ if (listen(*ps, backlog) < 0)
+ err = WSAGetLastError();
+ socket_setnonblocking(ps);
+ return err;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Accept with timeout
+ \*-------------------------------------------------------------------------*/
+ static int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, QT3DSU32 tm)
+ {
+ SA daddr;
+ socklen_t dlen = sizeof(daddr);
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ if (!addr)
+ addr = &daddr;
+ if (!len)
+ len = &dlen;
+ for (;;) {
+ int err;
+ /* try to get client socket */
+ if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID)
+ return IO_DONE;
+ /* find out why we failed */
+ err = WSAGetLastError();
+ /* if we failed because there was no connectoin, keep trying */
+ if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED)
+ return err;
+ /* call select to avoid busy wait */
+ if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE)
+ return err;
+ }
+ /* can't reach here */
+ return IO_UNKNOWN;
+ }
+
+ int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp)
+ {
+ *hp = gethostbyaddr(addr, len, AF_INET);
+ if (*hp)
+ return IO_DONE;
+ else
+ return WSAGetLastError();
+ }
+
+ int socket_gethostbyname(const char *addr, struct hostent **hp)
+ {
+ *hp = gethostbyname(addr);
+ if (*hp)
+ return IO_DONE;
+ else
+ return WSAGetLastError();
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Error translation functions
+ \*-------------------------------------------------------------------------*/
+ const char *socket_hoststrerror(int err)
+ {
+ if (err <= 0)
+ return io_strerror(err);
+ switch (err) {
+ case WSAHOST_NOT_FOUND:
+ return "host not found";
+ default:
+ return wstrerror(err);
+ }
+ }
+ /*-------------------------------------------------------------------------*\
+ * Close and inutilize socket
+ \*-------------------------------------------------------------------------*/
+ void socket_destroy(p_socket ps)
+ {
+ if (*ps != SOCKET_INVALID) {
+ socket_setblocking(ps); /* close can take a long time on WIN32 */
+ closesocket(*ps);
+ *ps = SOCKET_INVALID;
+ }
+ }
+
+ /*-------------------------------------------------------------------------*\
+ *
+ \*-------------------------------------------------------------------------*/
+ void socket_shutdown(p_socket ps, int how)
+ {
+ socket_setblocking(ps);
+ shutdown(*ps, how);
+ }
+
+ int socket_create(p_socket ps, int domain, int type, int protocol)
+ {
+ *ps = socket(domain, type, protocol);
+ if (*ps != SOCKET_INVALID)
+ return IO_DONE;
+ else
+ return WSAGetLastError();
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Connects or returns error message
+ \*-------------------------------------------------------------------------*/
+ int socket_connect(p_socket ps, SA *addr, socklen_t len, QT3DSU32 tm)
+ {
+ int err;
+ /* don't call on closed socket */
+ if (*ps == SOCKET_INVALID)
+ return IO_CLOSED;
+ /* ask system to connect */
+ if (connect(*ps, addr, len) == 0)
+ return IO_DONE;
+ /* make sure the system is trying to connect */
+ err = WSAGetLastError();
+ if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS)
+ return err;
+ /* zero timeout case optimization */
+ if (tm == 0)
+ return IO_TIMEOUT;
+ /* we wait until something happens */
+ err = socket_waitfd(ps, WAITFD_C, tm);
+ if (err == IO_CLOSED) {
+ int len = sizeof(err);
+ /* give windows time to set the error (yes, disgusting) */
+ Sleep(10);
+ /* find out why we failed */
+ getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
+ /* we KNOW there was an error. if 'why' is 0, we will return
+ * "unknown error", but it's not really our fault */
+ return err > 0 ? err : IO_UNKNOWN;
+ } else
+ return err;
+ }
+
+ /*-------------------------------------------------------------------------*\
+ * Binds or returns error message
+ \*-------------------------------------------------------------------------*/
+ int socket_bind(p_socket ps, SA *addr, socklen_t len)
+ {
+ int err = IO_DONE;
+ socket_setblocking(ps);
+ if (bind(*ps, addr, len) < 0)
+ err = WSAGetLastError();
+ socket_setnonblocking(ps);
+ return err;
+ }
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderClearColorExample.cpp b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderClearColorExample.cpp
new file mode 100644
index 00000000..f67cf717
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderClearColorExample.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRenderExample.h"
+#include "foundation/Qt3DSVec4.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+namespace {
+class ClearColor : public NVRenderExample
+{
+ NVRenderContext &m_Context;
+
+public:
+ ClearColor(NVRenderContext &ctx)
+ : m_Context(ctx)
+ {
+ }
+ virtual void drawFrame(double currentSeconds)
+ {
+ // Apply this value immediately but track it so that a later pop will in fact
+ // restore this value.
+ if (currentSeconds < 1)
+ m_Context.SetClearColor(QT3DSVec4(.8f, .0f, .0f, 1.f));
+ else if (currentSeconds < 2)
+ m_Context.SetClearColor(QT3DSVec4(0.f, .0f, 1.f, 1.f));
+ else
+ m_Context.SetClearColor(QT3DSVec4(0.f, 1.0f, 1.f, 1.f));
+ m_Context.Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+ }
+ virtual QT3DSU32 getRuntimeInSeconds() { return 2; }
+ virtual void release() { NVDelete(m_Context.GetFoundation(), this); }
+};
+}
+
+// QT3DS_RENDER_REGISTER_EXAMPLE( ClearColor ); \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.cpp b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.cpp
new file mode 100644
index 00000000..d866cda0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.cpp
@@ -0,0 +1,491 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRenderExample.h"
+#include "render/NvRenderBaseTypes.h"
+#include "render_util/NVRenderAllocator.h"
+#include "render_util/NVRenderErrorStream.h"
+#include "render_util/NVRenderUtils.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSTime.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSMath.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static TExampleCreateFunc gCreateFuncs[128];
+
+TExampleCreateFunc *NVRenderExampleFactory::mExampleCreators = gCreateFuncs;
+QT3DSU32 NVRenderExampleFactory::mMaxCreators = 128;
+QT3DSU32 NVRenderExampleFactory::mNumCreators = 0;
+namespace {
+NVRenderErrorStream g_errorStream;
+NVRenderAllocator g_allocator(g_errorStream);
+NVFoundation *g_foundation(NULL);
+NVRenderContext *g_renderContext(NULL);
+NVRenderExample *g_example(NULL);
+QT3DSI32 g_exampleIdx(0);
+Time::Second g_runTime;
+Time g_timer;
+}
+
+bool NVRenderExampleFactory::nextExample()
+{
+ if (g_example)
+ g_example->release();
+ g_example = 0;
+ if (g_exampleIdx < (int)mNumCreators) {
+ g_example = mExampleCreators[g_exampleIdx](*g_renderContext);
+ ++g_exampleIdx;
+ g_runTime = g_example->getRuntimeInSeconds();
+ g_timer = Time();
+ return true;
+ }
+ return false;
+}
+
+void NVRenderExampleFactory::beginExamples()
+{
+ g_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, g_allocator, g_errorStream);
+ g_renderContext =
+ &NVRenderContext::CreateGL(*g_foundation, NVRenderContextType(NVRenderContextValues::GL2));
+ nextExample();
+}
+bool NVRenderExampleFactory::update()
+{
+ Time::Second currentTime = g_timer.peekElapsedSeconds();
+ if (currentTime > g_runTime)
+ nextExample();
+ if (g_example)
+ g_example->drawFrame(currentTime);
+
+ return g_example != NULL;
+}
+
+void NVRenderExampleFactory::endExamples()
+{
+ g_exampleIdx = mNumCreators;
+ nextExample();
+ if (g_renderContext)
+ g_renderContext->release();
+ if (g_foundation)
+ g_foundation->release();
+
+ g_renderContext = NULL;
+ g_foundation = NULL;
+}
+
+namespace qt3ds {
+namespace render {
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // Math stuff
+
+ int eq(float a, float b)
+ {
+ float diff = a - b;
+ if (diff < 0) {
+ diff = -diff;
+ }
+ return diff <= eps;
+ }
+
+ //
+ // Matrix functions, since GLES 2.x doesn't provide them
+ //
+
+ void NvGl2DemoMatrixIdentity(float m[16])
+ {
+ memset(m, 0, sizeof(float) * 16);
+ m[4 * 0 + 0] = m[4 * 1 + 1] = m[4 * 2 + 2] = m[4 * 3 + 3] = 1.0;
+ }
+
+ int NvGl2DemoMatrixEquals(float a[16], float b[16])
+ {
+ int i;
+ for (i = 0; i < 16; ++i)
+ if (!eq(a[i], b[i]))
+ return 0;
+
+ return 1;
+ }
+
+ void NvGl2DemoMatrixTranspose(float m[16])
+ {
+ int i, j;
+ float t;
+ for (i = 1; i < 4; ++i)
+ for (j = 0; j < i; ++j) {
+ t = m[4 * i + j];
+ m[4 * i + j] = m[4 * j + i];
+ m[4 * j + i] = t;
+ }
+ }
+
+ void NvGl2DemoMatrixMultiply(float m0[16], float m1[16])
+ {
+ int r, c, i;
+ for (r = 0; r < 4; r++) {
+ float m[4] = { 0.0, 0.0, 0.0, 0.0 };
+ for (c = 0; c < 4; c++) {
+ for (i = 0; i < 4; i++) {
+ m[c] += m0[4 * i + r] * m1[4 * c + i];
+ }
+ }
+ for (c = 0; c < 4; c++) {
+ m0[4 * c + r] = m[c];
+ }
+ }
+ }
+
+ void NvGl2DemoMatrixMultiply_4x4_3x3(float m0[16], float m1[9])
+ {
+ int r, c, i;
+ for (r = 0; r < 4; r++) {
+ float m[3] = { 0.0, 0.0, 0.0 };
+ for (c = 0; c < 3; c++) {
+ for (i = 0; i < 3; i++) {
+ m[c] += m0[4 * i + r] * m1[3 * c + i];
+ }
+ }
+ for (c = 0; c < 3; c++) {
+ m0[4 * c + r] = m[c];
+ }
+ }
+ }
+
+ void NvGl2DemoMatrixMultiply_3x3(float m0[9], float m1[9])
+ {
+ int r, c, i;
+ for (r = 0; r < 3; r++) {
+ float m[3] = { 0.0, 0.0, 0.0 };
+ for (c = 0; c < 3; c++) {
+ for (i = 0; i < 3; i++) {
+ m[c] += m0[3 * i + r] * m1[3 * c + i];
+ }
+ }
+ for (c = 0; c < 3; c++) {
+ m0[3 * c + r] = m[c];
+ }
+ }
+ }
+
+ void NvGl2DemoMatrixFrustum(float m[16], float l, float r, float b, float t, float n, float f)
+ {
+ float m1[16];
+ float rightMinusLeftInv, topMinusBottomInv, farMinusNearInv, twoNear;
+
+ rightMinusLeftInv = 1.0f / (r - l);
+ topMinusBottomInv = 1.0f / (t - b);
+ farMinusNearInv = 1.0f / (f - n);
+ twoNear = 2.0f * n;
+
+ m1[0] = twoNear * rightMinusLeftInv;
+ m1[1] = 0.0f;
+ m1[2] = 0.0f;
+ m1[3] = 0.0f;
+
+ m1[4] = 0.0f;
+ m1[5] = twoNear * topMinusBottomInv;
+ m1[6] = 0.0f;
+ m1[7] = 0.0f;
+
+ m1[8] = (r + l) * rightMinusLeftInv;
+ m1[9] = (t + b) * topMinusBottomInv;
+ m1[10] = -(f + n) * farMinusNearInv;
+ m1[11] = -1.0f;
+
+ m1[12] = 0.0f;
+ m1[13] = 0.0f;
+ m1[14] = -(twoNear * f) * farMinusNearInv;
+ m1[15] = 0.0f;
+
+ NvGl2DemoMatrixMultiply(m, m1);
+ }
+
+ void NvGl2DemoMatrixOrtho(float m[16], float l, float r, float b, float t, float n, float f)
+ {
+ float m1[16];
+ float rightMinusLeftInv, topMinusBottomInv, farMinusNearInv;
+
+ rightMinusLeftInv = 1.0f / (r - l);
+ topMinusBottomInv = 1.0f / (t - b);
+ farMinusNearInv = 1.0f / (f - n);
+
+ m1[0] = 2.0f * rightMinusLeftInv;
+ m1[1] = 0.0f;
+ m1[2] = 0.0f;
+ m1[3] = 0.0f;
+
+ m1[4] = 0.0f;
+ m1[5] = 2.0f * topMinusBottomInv;
+ m1[6] = 0.0f;
+ m1[7] = 0.0f;
+
+ m1[8] = 0.0f;
+ m1[9] = 0.0f;
+ m1[10] = -2.0f * farMinusNearInv;
+ m1[11] = 0.0f;
+
+ m1[12] = -(r + l) * rightMinusLeftInv;
+ m1[13] = -(t + b) * topMinusBottomInv;
+ m1[14] = -(f + n) * farMinusNearInv;
+ m1[15] = 1.0f;
+
+ NvGl2DemoMatrixMultiply(m, m1);
+ }
+
+ void NvGl2DemoMatrixTranslate(float m[16], float x, float y, float z)
+ {
+ float m1[16];
+ NvGl2DemoMatrixIdentity(m1);
+
+ m1[4 * 3 + 0] = x;
+ m1[4 * 3 + 1] = y;
+ m1[4 * 3 + 2] = z;
+
+ NvGl2DemoMatrixMultiply(m, m1);
+ }
+
+ void NvGl2DemoMatrixRotate_create3x3(float m[9], float theta, float x, float y, float z)
+ {
+ float len = (float)sqrtf(x * x + y * y + z * z);
+ float u0 = x / len;
+ float u1 = y / len;
+ float u2 = z / len;
+ float rad = (float)(theta / 180 * NVPi);
+ float c = (float)cosf(rad);
+ float s = (float)sinf(rad);
+ m[3 * 0 + 0] = u0 * u0 + c * (1 - u0 * u0) + s * 0;
+ m[3 * 0 + 1] = u0 * u1 + c * (0 - u0 * u1) + s * u2;
+ m[3 * 0 + 2] = u0 * u2 + c * (0 - u0 * u2) - s * u1;
+
+ m[3 * 1 + 0] = u1 * u0 + c * (0 - u1 * u0) - s * u2;
+ m[3 * 1 + 1] = u1 * u1 + c * (1 - u1 * u1) + s * 0;
+ m[3 * 1 + 2] = u1 * u2 + c * (0 - u1 * u2) + s * u0;
+
+ m[3 * 2 + 0] = u2 * u0 + c * (0 - u2 * u0) + s * u1;
+ m[3 * 2 + 1] = u2 * u1 + c * (0 - u2 * u1) - s * u0;
+ m[3 * 2 + 2] = u2 * u2 + c * (1 - u2 * u2) + s * 0;
+ }
+
+ void NvGl2DemoMatrixRotate(float m[16], float theta, float x, float y, float z)
+ {
+ float r[9];
+ NvGl2DemoMatrixRotate_create3x3(r, theta, x, y, z);
+ NvGl2DemoMatrixMultiply_4x4_3x3(m, r);
+ }
+
+ void NvGl2DemoMatrixRotate_3x3(float m[9], float theta, float x, float y, float z)
+ {
+ float r[9];
+ NvGl2DemoMatrixRotate_create3x3(r, theta, x, y, z);
+ NvGl2DemoMatrixMultiply_3x3(m, r);
+ }
+
+ float NvGl2DemoMatrixDeterminant(float m[16])
+ {
+ return m[4 * 0 + 3] * m[4 * 1 + 2] * m[4 * 2 + 1] * m[4 * 3 + 0]
+ - m[4 * 0 + 2] * m[4 * 1 + 3] * m[4 * 2 + 1] * m[4 * 3 + 0]
+ - m[4 * 0 + 3] * m[4 * 1 + 1] * m[4 * 2 + 2] * m[4 * 3 + 0]
+ + m[4 * 0 + 1] * m[4 * 1 + 3] * m[4 * 2 + 2] * m[4 * 3 + 0]
+ + m[4 * 0 + 2] * m[4 * 1 + 1] * m[4 * 2 + 3] * m[4 * 3 + 0]
+ - m[4 * 0 + 1] * m[4 * 1 + 2] * m[4 * 2 + 3] * m[4 * 3 + 0]
+ - m[4 * 0 + 3] * m[4 * 1 + 2] * m[4 * 2 + 0] * m[4 * 3 + 1]
+ + m[4 * 0 + 2] * m[4 * 1 + 3] * m[4 * 2 + 0] * m[4 * 3 + 1]
+ + m[4 * 0 + 3] * m[4 * 1 + 0] * m[4 * 2 + 2] * m[4 * 3 + 1]
+ - m[4 * 0 + 0] * m[4 * 1 + 3] * m[4 * 2 + 2] * m[4 * 3 + 1]
+ - m[4 * 0 + 2] * m[4 * 1 + 0] * m[4 * 2 + 3] * m[4 * 3 + 1]
+ + m[4 * 0 + 0] * m[4 * 1 + 2] * m[4 * 2 + 3] * m[4 * 3 + 1]
+ + m[4 * 0 + 3] * m[4 * 1 + 1] * m[4 * 2 + 0] * m[4 * 3 + 2]
+ - m[4 * 0 + 1] * m[4 * 1 + 3] * m[4 * 2 + 0] * m[4 * 3 + 2]
+ - m[4 * 0 + 3] * m[4 * 1 + 0] * m[4 * 2 + 1] * m[4 * 3 + 2]
+ + m[4 * 0 + 0] * m[4 * 1 + 3] * m[4 * 2 + 1] * m[4 * 3 + 2]
+ + m[4 * 0 + 1] * m[4 * 1 + 0] * m[4 * 2 + 3] * m[4 * 3 + 2]
+ - m[4 * 0 + 0] * m[4 * 1 + 1] * m[4 * 2 + 3] * m[4 * 3 + 2]
+ - m[4 * 0 + 2] * m[4 * 1 + 1] * m[4 * 2 + 0] * m[4 * 3 + 3]
+ + m[4 * 0 + 1] * m[4 * 1 + 2] * m[4 * 2 + 0] * m[4 * 3 + 3]
+ + m[4 * 0 + 2] * m[4 * 1 + 0] * m[4 * 2 + 1] * m[4 * 3 + 3]
+ - m[4 * 0 + 0] * m[4 * 1 + 2] * m[4 * 2 + 1] * m[4 * 3 + 3]
+ - m[4 * 0 + 1] * m[4 * 1 + 0] * m[4 * 2 + 2] * m[4 * 3 + 3]
+ + m[4 * 0 + 0] * m[4 * 1 + 1] * m[4 * 2 + 2] * m[4 * 3 + 3];
+ }
+
+ void NvGl2DemoMatrixInverse(float m[16])
+ {
+ float a[16];
+ float det;
+ int i;
+ float b[16], e[16];
+
+ a[4 * 0 + 0] = m[4 * 1 + 2] * m[4 * 2 + 3] * m[4 * 3 + 1]
+ - m[4 * 1 + 3] * m[4 * 2 + 2] * m[4 * 3 + 1]
+ + m[4 * 1 + 3] * m[4 * 2 + 1] * m[4 * 3 + 2]
+ - m[4 * 1 + 1] * m[4 * 2 + 3] * m[4 * 3 + 2]
+ - m[4 * 1 + 2] * m[4 * 2 + 1] * m[4 * 3 + 3]
+ + m[4 * 1 + 1] * m[4 * 2 + 2] * m[4 * 3 + 3];
+ a[4 * 0 + 1] = m[4 * 0 + 3] * m[4 * 2 + 2] * m[4 * 3 + 1]
+ - m[4 * 0 + 2] * m[4 * 2 + 3] * m[4 * 3 + 1]
+ - m[4 * 0 + 3] * m[4 * 2 + 1] * m[4 * 3 + 2]
+ + m[4 * 0 + 1] * m[4 * 2 + 3] * m[4 * 3 + 2]
+ + m[4 * 0 + 2] * m[4 * 2 + 1] * m[4 * 3 + 3]
+ - m[4 * 0 + 1] * m[4 * 2 + 2] * m[4 * 3 + 3];
+ a[4 * 0 + 2] = m[4 * 0 + 2] * m[4 * 1 + 3] * m[4 * 3 + 1]
+ - m[4 * 0 + 3] * m[4 * 1 + 2] * m[4 * 3 + 1]
+ + m[4 * 0 + 3] * m[4 * 1 + 1] * m[4 * 3 + 2]
+ - m[4 * 0 + 1] * m[4 * 1 + 3] * m[4 * 3 + 2]
+ - m[4 * 0 + 2] * m[4 * 1 + 1] * m[4 * 3 + 3]
+ + m[4 * 0 + 1] * m[4 * 1 + 2] * m[4 * 3 + 3];
+ a[4 * 0 + 3] = m[4 * 0 + 3] * m[4 * 1 + 2] * m[4 * 2 + 1]
+ - m[4 * 0 + 2] * m[4 * 1 + 3] * m[4 * 2 + 1]
+ - m[4 * 0 + 3] * m[4 * 1 + 1] * m[4 * 2 + 2]
+ + m[4 * 0 + 1] * m[4 * 1 + 3] * m[4 * 2 + 2]
+ + m[4 * 0 + 2] * m[4 * 1 + 1] * m[4 * 2 + 3]
+ - m[4 * 0 + 1] * m[4 * 1 + 2] * m[4 * 2 + 3];
+ a[4 * 1 + 0] = m[4 * 1 + 3] * m[4 * 2 + 2] * m[4 * 3 + 0]
+ - m[4 * 1 + 2] * m[4 * 2 + 3] * m[4 * 3 + 0]
+ - m[4 * 1 + 3] * m[4 * 2 + 0] * m[4 * 3 + 2]
+ + m[4 * 1 + 0] * m[4 * 2 + 3] * m[4 * 3 + 2]
+ + m[4 * 1 + 2] * m[4 * 2 + 0] * m[4 * 3 + 3]
+ - m[4 * 1 + 0] * m[4 * 2 + 2] * m[4 * 3 + 3];
+ a[4 * 1 + 1] = m[4 * 0 + 2] * m[4 * 2 + 3] * m[4 * 3 + 0]
+ - m[4 * 0 + 3] * m[4 * 2 + 2] * m[4 * 3 + 0]
+ + m[4 * 0 + 3] * m[4 * 2 + 0] * m[4 * 3 + 2]
+ - m[4 * 0 + 0] * m[4 * 2 + 3] * m[4 * 3 + 2]
+ - m[4 * 0 + 2] * m[4 * 2 + 0] * m[4 * 3 + 3]
+ + m[4 * 0 + 0] * m[4 * 2 + 2] * m[4 * 3 + 3];
+ a[4 * 1 + 2] = m[4 * 0 + 3] * m[4 * 1 + 2] * m[4 * 3 + 0]
+ - m[4 * 0 + 2] * m[4 * 1 + 3] * m[4 * 3 + 0]
+ - m[4 * 0 + 3] * m[4 * 1 + 0] * m[4 * 3 + 2]
+ + m[4 * 0 + 0] * m[4 * 1 + 3] * m[4 * 3 + 2]
+ + m[4 * 0 + 2] * m[4 * 1 + 0] * m[4 * 3 + 3]
+ - m[4 * 0 + 0] * m[4 * 1 + 2] * m[4 * 3 + 3];
+ a[4 * 1 + 3] = m[4 * 0 + 2] * m[4 * 1 + 3] * m[4 * 2 + 0]
+ - m[4 * 0 + 3] * m[4 * 1 + 2] * m[4 * 2 + 0]
+ + m[4 * 0 + 3] * m[4 * 1 + 0] * m[4 * 2 + 2]
+ - m[4 * 0 + 0] * m[4 * 1 + 3] * m[4 * 2 + 2]
+ - m[4 * 0 + 2] * m[4 * 1 + 0] * m[4 * 2 + 3]
+ + m[4 * 0 + 0] * m[4 * 1 + 2] * m[4 * 2 + 3];
+ a[4 * 2 + 0] = m[4 * 1 + 1] * m[4 * 2 + 3] * m[4 * 3 + 0]
+ - m[4 * 1 + 3] * m[4 * 2 + 1] * m[4 * 3 + 0]
+ + m[4 * 1 + 3] * m[4 * 2 + 0] * m[4 * 3 + 1]
+ - m[4 * 1 + 0] * m[4 * 2 + 3] * m[4 * 3 + 1]
+ - m[4 * 1 + 1] * m[4 * 2 + 0] * m[4 * 3 + 3]
+ + m[4 * 1 + 0] * m[4 * 2 + 1] * m[4 * 3 + 3];
+ a[4 * 2 + 1] = m[4 * 0 + 3] * m[4 * 2 + 1] * m[4 * 3 + 0]
+ - m[4 * 0 + 1] * m[4 * 2 + 3] * m[4 * 3 + 0]
+ - m[4 * 0 + 3] * m[4 * 2 + 0] * m[4 * 3 + 1]
+ + m[4 * 0 + 0] * m[4 * 2 + 3] * m[4 * 3 + 1]
+ + m[4 * 0 + 1] * m[4 * 2 + 0] * m[4 * 3 + 3]
+ - m[4 * 0 + 0] * m[4 * 2 + 1] * m[4 * 3 + 3];
+ a[4 * 2 + 2] = m[4 * 0 + 1] * m[4 * 1 + 3] * m[4 * 3 + 0]
+ - m[4 * 0 + 3] * m[4 * 1 + 1] * m[4 * 3 + 0]
+ + m[4 * 0 + 3] * m[4 * 1 + 0] * m[4 * 3 + 1]
+ - m[4 * 0 + 0] * m[4 * 1 + 3] * m[4 * 3 + 1]
+ - m[4 * 0 + 1] * m[4 * 1 + 0] * m[4 * 3 + 3]
+ + m[4 * 0 + 0] * m[4 * 1 + 1] * m[4 * 3 + 3];
+ a[4 * 2 + 3] = m[4 * 0 + 3] * m[4 * 1 + 1] * m[4 * 2 + 0]
+ - m[4 * 0 + 1] * m[4 * 1 + 3] * m[4 * 2 + 0]
+ - m[4 * 0 + 3] * m[4 * 1 + 0] * m[4 * 2 + 1]
+ + m[4 * 0 + 0] * m[4 * 1 + 3] * m[4 * 2 + 1]
+ + m[4 * 0 + 1] * m[4 * 1 + 0] * m[4 * 2 + 3]
+ - m[4 * 0 + 0] * m[4 * 1 + 1] * m[4 * 2 + 3];
+ a[4 * 3 + 0] = m[4 * 1 + 2] * m[4 * 2 + 1] * m[4 * 3 + 0]
+ - m[4 * 1 + 1] * m[4 * 2 + 2] * m[4 * 3 + 0]
+ - m[4 * 1 + 2] * m[4 * 2 + 0] * m[4 * 3 + 1]
+ + m[4 * 1 + 0] * m[4 * 2 + 2] * m[4 * 3 + 1]
+ + m[4 * 1 + 1] * m[4 * 2 + 0] * m[4 * 3 + 2]
+ - m[4 * 1 + 0] * m[4 * 2 + 1] * m[4 * 3 + 2];
+ a[4 * 3 + 1] = m[4 * 0 + 1] * m[4 * 2 + 2] * m[4 * 3 + 0]
+ - m[4 * 0 + 2] * m[4 * 2 + 1] * m[4 * 3 + 0]
+ + m[4 * 0 + 2] * m[4 * 2 + 0] * m[4 * 3 + 1]
+ - m[4 * 0 + 0] * m[4 * 2 + 2] * m[4 * 3 + 1]
+ - m[4 * 0 + 1] * m[4 * 2 + 0] * m[4 * 3 + 2]
+ + m[4 * 0 + 0] * m[4 * 2 + 1] * m[4 * 3 + 2];
+ a[4 * 3 + 2] = m[4 * 0 + 2] * m[4 * 1 + 1] * m[4 * 3 + 0]
+ - m[4 * 0 + 1] * m[4 * 1 + 2] * m[4 * 3 + 0]
+ - m[4 * 0 + 2] * m[4 * 1 + 0] * m[4 * 3 + 1]
+ + m[4 * 0 + 0] * m[4 * 1 + 2] * m[4 * 3 + 1]
+ + m[4 * 0 + 1] * m[4 * 1 + 0] * m[4 * 3 + 2]
+ - m[4 * 0 + 0] * m[4 * 1 + 1] * m[4 * 3 + 2];
+ a[4 * 3 + 3] = m[4 * 0 + 1] * m[4 * 1 + 2] * m[4 * 2 + 0]
+ - m[4 * 0 + 2] * m[4 * 1 + 1] * m[4 * 2 + 0]
+ + m[4 * 0 + 2] * m[4 * 1 + 0] * m[4 * 2 + 1]
+ - m[4 * 0 + 0] * m[4 * 1 + 2] * m[4 * 2 + 1]
+ - m[4 * 0 + 1] * m[4 * 1 + 0] * m[4 * 2 + 2]
+ + m[4 * 0 + 0] * m[4 * 1 + 1] * m[4 * 2 + 2];
+
+ det = NvGl2DemoMatrixDeterminant(m);
+
+ for (i = 0; i < 16; ++i)
+ a[i] /= det;
+
+ NvGl2DemoMatrixIdentity(e);
+
+ NvGl2DemoMatrixCopy(b, m);
+ NvGl2DemoMatrixMultiply(b, a);
+
+ NvGl2DemoMatrixCopy(m, a);
+ }
+
+ void NvGl2DemoMatrixCopy(float dest[16], float src[16])
+ {
+ memcpy(dest, src, 16 * sizeof(float));
+ }
+
+ void NvGl2DemoMatrixPrint(float a[16])
+ {
+ int i, j;
+
+ for (i = 0; i < 4; ++i)
+ for (j = 0; j < 4; ++j)
+ printf("%f%c", a[4 * i + j], j == 3 ? '\n' : ' ');
+ }
+
+ void NvGl2DemoMatrixVectorMultiply(float m[16], float v[4])
+ {
+ float res[4];
+ int i, j;
+
+ for (i = 0; i < 4; ++i) {
+ res[i] = 0;
+ for (j = 0; j < 4; ++j)
+ res[i] += m[i * 4 + j] * v[j];
+ }
+
+ memcpy(v, res, sizeof(res));
+ }
+}
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.h b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.h
new file mode 100644
index 00000000..79bfd911
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExample.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_EXAMPLE_H
+#define QT3DS_RENDER_EXAMPLE_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/NvRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContext;
+
+ class NVRenderExample
+ {
+ protected:
+ virtual ~NVRenderExample() {}
+ public:
+ virtual void drawFrame(double currentSeconds) = 0;
+ virtual QT3DSU32 getRuntimeInSeconds() { return 5; }
+ virtual void handleKeypress(int /*keypress*/) {}
+ virtual void release() = 0;
+ };
+
+ typedef NVRenderExample *(*TExampleCreateFunc)(NVRenderContext &context);
+
+ struct NVRenderExampleFactory
+ {
+ static TExampleCreateFunc *mExampleCreators;
+ static QT3DSU32 mMaxCreators;
+ static QT3DSU32 mNumCreators;
+
+ static void addCreator(TExampleCreateFunc creator)
+ {
+ if (mNumCreators < mMaxCreators) {
+ mExampleCreators[mNumCreators] = creator;
+ ++mNumCreators;
+ } else
+ QT3DS_ASSERT(false);
+ }
+
+ // Assuming that the render context is egl
+ // Relies on the global structures defined in demo common
+ // to figure out window state.
+ static bool nextExample();
+ static void beginExamples();
+ static bool update();
+ static void endExamples();
+ };
+
+ template <typename TExample>
+ struct NVRenderExampleCreator
+ {
+
+ static NVRenderExample *createExample(NVRenderContext &context)
+ {
+ return QT3DS_NEW(context.GetFoundation().getAllocator(), TExample)(context);
+ }
+ NVRenderExampleCreator() { NVRenderExampleFactory::addCreator(createExample); }
+ };
+
+#define QT3DS_RENDER_REGISTER_EXAMPLE(dtype) static NVRenderExampleCreator<dtype> dtype##Creator
+
+#define eps 1e-4
+
+ int eq(float a, float b);
+
+ // Matrix functions
+ void NvGl2DemoMatrixIdentity(float m[16]);
+ int NvGl2DemoMatrixEquals(float a[16], float b[16]);
+ void NvGl2DemoMatrixTranspose(float m[16]);
+ void NvGl2DemoMatrixMultiply(float m0[16], float m1[16]);
+ void NvGl2DemoMatrixMultiply_4x4_3x3(float m0[16], float m1[9]);
+ void NvGl2DemoMatrixMultiply_3x3(float m0[9], float m1[9]);
+ void NvGl2DemoMatrixFrustum(float m[16], float l, float r, float b, float t, float n, float f);
+ void NvGl2DemoMatrixOrtho(float m[16], float l, float r, float b, float t, float n, float f);
+ void NvGl2DemoMatrixTranslate(float m[16], float x, float y, float z);
+ void NvGl2DemoMatrixRotate_create3x3(float m[9], float theta, float x, float y, float z);
+ void NvGl2DemoMatrixRotate(float m[16], float theta, float x, float y, float z);
+ void NvGl2DemoMatrixRotate_3x3(float m[9], float theta, float x, float y, float z);
+
+ float NvGl2DemoMatrixDeterminant(float m[16]);
+ void NvGl2DemoMatrixInverse(float m[16]);
+ void NvGl2DemoMatrixCopy(float dest[16], float src[16]);
+
+ void NvGl2DemoMatrixPrint(float a[16]);
+
+ void NvGl2DemoMatrixVectorMultiply(float m[16], float v[4]);
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.cpp b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.cpp
new file mode 100644
index 00000000..efae6f5e
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRenderExampleTools.h"
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render_util/NVRenderUtils.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSVec4.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct BoxFace
+{
+ QT3DSVec3 positions[4];
+ QT3DSVec3 normal;
+};
+
+static const BoxFace g_BoxFaces[] = {
+ { // Z+
+ QT3DSVec3(-1, -1, 1), QT3DSVec3(-1, 1, 1), QT3DSVec3(1, 1, 1), QT3DSVec3(1, -1, 1), QT3DSVec3(0, 0, 1) },
+ { // X+
+ QT3DSVec3(1, -1, 1), QT3DSVec3(1, 1, 1), QT3DSVec3(1, 1, -1), QT3DSVec3(1, -1, -1), QT3DSVec3(1, 0, 0) },
+ { // Z-
+ QT3DSVec3(1, -1, -1), QT3DSVec3(1, 1, -1), QT3DSVec3(-1, 1, -1), QT3DSVec3(-1, -1, -1),
+ QT3DSVec3(0, 0, -1) },
+ { // X-
+ QT3DSVec3(-1, -1, -1), QT3DSVec3(-1, 1, -1), QT3DSVec3(-1, 1, 1), QT3DSVec3(-1, -1, 1),
+ QT3DSVec3(-1, 0, 0) },
+ { // Y+
+ QT3DSVec3(-1, 1, 1), QT3DSVec3(-1, 1, -1), QT3DSVec3(1, 1, -1), QT3DSVec3(1, 1, 1), QT3DSVec3(0, 1, 0) },
+ { // Y-
+ QT3DSVec3(-1, -1, -1), QT3DSVec3(-1, -1, 1), QT3DSVec3(1, -1, 1), QT3DSVec3(1, -1, -1), QT3DSVec3(0, -1, 0) }
+};
+
+static const QT3DSVec3 g_BoxUVs[] = {
+ QT3DSVec3(0, 1, 0), QT3DSVec3(0, 0, 0), QT3DSVec3(1, 0, 0), QT3DSVec3(1, 1, 0),
+};
+
+void NVRenderExampleTools::createBox(NVRenderContext &context,
+ NVRenderVertexBuffer *&outVertexBuffer,
+ NVRenderIndexBuffer *&outIndexBuffer, bool releaseMemory)
+{
+ const QT3DSU32 numVerts = 24;
+ const QT3DSU32 numIndices = 36;
+ QT3DSVec3 extents = QT3DSVec3(1, 1, 1);
+
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_norm", NVRenderComponentTypes::QT3DSF32, 3, 3 * sizeof(QT3DSF32)),
+ NVRenderVertexBufferEntry("attr_uv", NVRenderComponentTypes::QT3DSF32, 2, 6 * sizeof(QT3DSF32)),
+ };
+
+ QT3DSU32 bufStride = 8 * sizeof(QT3DSF32);
+ QT3DSU32 bufSize = bufStride * numVerts;
+ outVertexBuffer = context.CreateVertexBuffer(
+ NVRenderBufferUsageType::Static, NVConstDataRef<NVRenderVertexBufferEntry>(entries, 3), 0,
+ releaseMemory ? 0 : bufSize);
+ QT3DS_ASSERT(bufStride == outVertexBuffer->GetStride());
+ NVDataRef<QT3DSU8> vertData;
+ if (releaseMemory)
+ vertData = NVDataRef<QT3DSU8>(
+ (QT3DSU8 *)QT3DS_ALLOC(context.GetFoundation().getAllocator(), bufSize, "VertexBufferData"),
+ bufSize);
+ else
+ vertData = outVertexBuffer->LockBuffer(bufSize);
+ QT3DSU8 *positions = (QT3DSU8 *)vertData.begin();
+ QT3DSU8 *normals = positions + 3 * sizeof(QT3DSF32);
+ QT3DSU8 *uvs = normals + 3 * sizeof(QT3DSF32);
+
+ for (QT3DSU32 i = 0; i < 6; i++) {
+ const BoxFace &bf = g_BoxFaces[i];
+ for (QT3DSU32 j = 0; j < 4; j++) {
+ QT3DSVec3 &p = *(QT3DSVec3 *)positions;
+ positions = ((QT3DSU8 *)positions) + bufStride;
+ QT3DSVec3 &n = *(QT3DSVec3 *)normals;
+ normals = ((QT3DSU8 *)normals) + bufStride;
+ QT3DSF32 *uv = (QT3DSF32 *)uvs;
+ uvs = ((QT3DSU8 *)uvs) + bufStride;
+ n = bf.normal;
+ p = bf.positions[j].multiply(extents);
+ uv[0] = g_BoxUVs[j].x;
+ uv[1] = g_BoxUVs[j].y;
+ }
+ }
+
+ if (releaseMemory) {
+ outVertexBuffer->SetBuffer(vertData, false);
+ context.GetFoundation().getAllocator().deallocate(vertData.begin());
+ } else
+ outVertexBuffer->UnlockBuffer();
+
+ bufSize = numIndices * sizeof(QT3DSU16);
+ outIndexBuffer =
+ context.CreateIndexBuffer(NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU16,
+ releaseMemory ? 0 : bufSize);
+ NVDataRef<QT3DSU8> indexData;
+ if (releaseMemory)
+ indexData = NVDataRef<QT3DSU8>(
+ (QT3DSU8 *)QT3DS_ALLOC(context.GetFoundation().getAllocator(), bufSize, "IndexData"),
+ bufSize);
+ else
+ indexData = outIndexBuffer->LockBuffer(bufSize);
+ QT3DSU16 *indices = reinterpret_cast<QT3DSU16 *>(indexData.begin());
+ for (QT3DSU8 i = 0; i < 6; i++) {
+ const QT3DSU16 base = i * 4;
+ *(indices++) = base + 0;
+ *(indices++) = base + 1;
+ *(indices++) = base + 2;
+ *(indices++) = base + 0;
+ *(indices++) = base + 2;
+ *(indices++) = base + 3;
+ }
+ if (releaseMemory) {
+ outIndexBuffer->SetBuffer(indexData, false);
+ context.GetFoundation().getAllocator().deallocate(indexData.begin());
+ } else
+ outIndexBuffer->UnlockBuffer();
+}
+
+namespace {
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, len);
+}
+
+static void dumpShaderOutput(NVRenderContext &ctx,
+ const NVRenderVertFragCompilationResult &compResult)
+{
+ if (!isTrivial(compResult.mFragCompilationOutput)) {
+ ctx.GetFoundation().error(QT3DS_WARN, "Frag output:\n%s", compResult.mFragCompilationOutput);
+ }
+ if (!isTrivial(compResult.mVertCompilationOutput)) {
+ ctx.GetFoundation().error(QT3DS_WARN, "Vert output:\n%s", compResult.mVertCompilationOutput);
+ }
+ if (!isTrivial(compResult.mLinkOutput)) {
+ ctx.GetFoundation().error(QT3DS_WARN, "Link output:\n%s", compResult.mLinkOutput);
+ }
+}
+
+NVRenderVertFragShader *compileAndDump(NVRenderContext &ctx, const char *name,
+ const char *vertShader, const char *fragShader)
+{
+ NVRenderVertFragCompilationResult compResult =
+ ctx.CompileSource(name, toRef(vertShader), toRef(fragShader));
+ dumpShaderOutput(ctx, compResult);
+ return compResult.mShader;
+}
+}
+
+NVRenderVertFragShader *NVRenderExampleTools::createSimpleShader(NVRenderContext &ctx)
+{
+ return compileAndDump(ctx, "SimpleShader", getSimpleVertShader(), getSimpleFragShader());
+}
+
+NVRenderVertFragShader *NVRenderExampleTools::createSimpleShaderTex(NVRenderContext &ctx)
+{
+ return compileAndDump(ctx, "SimpleShader", getSimpleVertShader(), getSimpleFragShaderTex());
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.h b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.h
new file mode 100644
index 00000000..5b402868
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderExampleTools.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_EXAMPLE_TOOLS_H
+#define QT3DS_RENDER_EXAMPLE_TOOLS_H
+#include "Qt3DSRenderExample.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderExampleTools
+ {
+ public:
+ static const char *getSimpleVertShader()
+ {
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "attribute vec3 attr_norm; // Vertex pos\n"
+ "attribute vec2 attr_uv; // UV coords\n"
+ "varying vec4 color_to_add;\n"
+ "varying vec2 uv_coords;\n"
+ "void main()\n"
+ "{\n"
+ "gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "color_to_add.xyz = attr_norm * attr_norm;\n"
+ "color_to_add.a = 1.0;\n"
+ "uv_coords = attr_uv;\n"
+ "}\n";
+ }
+
+ static const char *getSimpleFragShader()
+ {
+ return "precision mediump sampler2D;\n"
+ "precision mediump float;\n"
+ "varying vec4 color_to_add;\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor=color_to_add;\n"
+ "}\n";
+ }
+
+ static const char *getSimpleFragShaderTex()
+ {
+ return "precision mediump sampler2D;\n"
+ "precision mediump float;\n"
+ "uniform sampler2D image0;\n"
+ "varying vec2 uv_coords;\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor=vec4(texture2D( image0, uv_coords ).xyz, 1.0 );\n"
+ "}\n";
+ }
+
+ static void createBox(NVRenderContext &context, NVRenderVertexBuffer *&outVertexBuffer,
+ NVRenderIndexBuffer *&outIndexBuffer, bool releaseMemory = true);
+ static NVRenderVertFragShader *createSimpleShader(NVRenderContext &context);
+ static NVRenderVertFragShader *createSimpleShaderTex(NVRenderContext &context);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderRenderToTextureExample.cpp b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderRenderToTextureExample.cpp
new file mode 100644
index 00000000..e2cb4149
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderRenderToTextureExample.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRenderExample.h"
+#include "Qt3DSRenderExampleTools.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "foundation/Qt3DSVec4.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+namespace {
+struct ShaderArgs
+{
+ float mvp[16];
+ NVRenderTexture2DPtr texture;
+ NVRenderVertFragShaderPtr shader;
+ ShaderArgs() {}
+};
+class RenderToTexture : public NVRenderExample
+{
+ NVRenderContext &m_Context;
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ // Simple shader
+ NVScopedRefCounted<NVRenderVertFragShader> mSimpleShader;
+ // Simple shader with texture lookup.
+ NVScopedRefCounted<NVRenderVertFragShader> mSimpleShaderTex;
+
+ NVScopedRefCounted<NVRenderFrameBuffer> mFrameBuffer;
+ NVScopedRefCounted<NVRenderTexture2D> mColorBuffer;
+ NVScopedRefCounted<NVRenderTexture2D> mDepthBuffer;
+
+ NVRenderHandle mGroupId;
+ QT3DSU32 mFBWidth;
+ QT3DSU32 mFBHeight;
+
+ ShaderArgs mShaderArgs;
+ float frus[16];
+ float model[16];
+ float rot[9];
+
+public:
+ RenderToTexture(NVRenderContext &context)
+ : m_Context(context)
+ , mFBWidth(400)
+ , mFBHeight(400)
+ {
+ NVRenderExampleTools::createBox(m_Context, mVertexBuffer.mPtr, mIndexBuffer.mPtr);
+ mVertexBuffer->addRef();
+ mIndexBuffer->addRef();
+ mSimpleShader = NVRenderExampleTools::createSimpleShader(m_Context);
+ mSimpleShaderTex = NVRenderExampleTools::createSimpleShaderTex(m_Context);
+ // If you don't want the depth buffer information back out of the system, then you can
+ // do this.
+ // mDepthBuffer = m_Context.CreateRenderBuffer( NVRenderRenderBufferFormats::Depth16,
+ // mFBWidth, mFBHeight );
+
+ mDepthBuffer = m_Context.CreateTexture2D();
+ mDepthBuffer->SetTextureData(NVDataRef<QT3DSU8>(), 0, mFBWidth, mFBHeight,
+ NVRenderTextureFormats::Depth16);
+ mColorBuffer = m_Context.CreateTexture2D();
+ mColorBuffer->SetTextureData(NVDataRef<QT3DSU8>(), 0, mFBWidth, mFBHeight,
+ NVRenderTextureFormats::RGBA8);
+ if (mDepthBuffer.mPtr && mColorBuffer.mPtr) {
+ // Creating objects tends to Bind them to their active state hooks.
+ // So to protect the rest of the system against what they are doing (if we care), we
+ // need
+ // to push the current state
+ // Auto-binds the framebuffer.
+ mFrameBuffer = m_Context.CreateFrameBuffer();
+ mFrameBuffer->Attach(NVRenderFrameBufferAttachments::Color0, *mColorBuffer.mPtr);
+ mFrameBuffer->Attach(NVRenderFrameBufferAttachments::Depth, *mDepthBuffer.mPtr);
+ QT3DS_ASSERT(mFrameBuffer->IsComplete());
+
+ m_Context.SetRenderTarget(NULL);
+ }
+ mColorBuffer->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ mColorBuffer->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ m_Context.SetVertexBuffer(mVertexBuffer);
+ m_Context.SetIndexBuffer(mIndexBuffer);
+ m_Context.SetDepthTestEnabled(true);
+ m_Context.SetDepthWriteEnabled(true);
+ m_Context.SetClearColor(QT3DSVec4(.3f));
+ // Setup various matrici
+ NvGl2DemoMatrixIdentity(model);
+ NvGl2DemoMatrixIdentity(frus);
+ NvGl2DemoMatrixFrustum(frus, -1, 1, -1, 1, 1, 10);
+ NvGl2DemoMatrixTranslate(model, 0, 0, -4);
+ mShaderArgs.texture = mColorBuffer.mPtr;
+ }
+ void setupMVP(QT3DSVec3 translation)
+ {
+ float *mvp(mShaderArgs.mvp);
+ memCopy(mvp, frus, 16 * sizeof(float));
+ NvGl2DemoMatrixMultiply(mvp, model);
+ NvGl2DemoMatrixTranslate(mvp, translation.x, translation.y, translation.z);
+ NvGl2DemoMatrixMultiply_4x4_3x3(mvp, rot);
+ }
+ void DrawIndexedArrays(QT3DSVec3 translation)
+ {
+ setupMVP(translation);
+ m_Context.SetActiveShader(mShaderArgs.shader);
+ mShaderArgs.shader->Bind();
+ mShaderArgs.shader->SetPropertyValue("mat_mvp",
+ *reinterpret_cast<QT3DSMat44 *>(mShaderArgs.mvp));
+ mShaderArgs.shader->SetPropertyValue("image0", mShaderArgs.texture);
+ m_Context.Draw(NVRenderDrawMode::Triangles, mIndexBuffer->GetNumIndices(), 0);
+ }
+
+ virtual void drawFrame(double currentSeconds)
+ {
+ NvGl2DemoMatrixRotate_create3x3(rot, (float)currentSeconds * 50, .707f, .707f, 0);
+ NVRenderClearFlags clearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth);
+ // render to frame buffer
+ {
+ NVRenderContextScopedProperty<NVRenderFrameBufferPtr> __framebuffer(
+ m_Context, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget,
+ mFrameBuffer);
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ m_Context, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport,
+ NVRenderRect(0, 0, mFBWidth, mFBHeight));
+ NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ m_Context, &NVRenderContext::GetClearColor, &NVRenderContext::SetClearColor,
+ QT3DSVec4(.6f));
+ m_Context.Clear(clearFlags);
+ mShaderArgs.shader = mSimpleShader;
+ DrawIndexedArrays(QT3DSVec3(0.f));
+ }
+ m_Context.Clear(clearFlags);
+ mShaderArgs.texture = mColorBuffer;
+ mShaderArgs.shader = mSimpleShaderTex;
+
+ DrawIndexedArrays(QT3DSVec3(-2.f, 0.f, 0.f));
+
+ mShaderArgs.texture = mDepthBuffer;
+ DrawIndexedArrays(QT3DSVec3(2.f, 0.f, 0.f));
+ }
+ virtual QT3DSU32 getRuntimeInSeconds()
+ {
+ return mSimpleShader.mPtr && mSimpleShaderTex.mPtr ? 5 : 0;
+ }
+ virtual void release() { NVDelete(m_Context.GetFoundation(), this); }
+};
+}
+
+QT3DS_RENDER_REGISTER_EXAMPLE(RenderToTexture); \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderSpinningCubeExample.cpp b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderSpinningCubeExample.cpp
new file mode 100644
index 00000000..807f0821
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Examples/Qt3DSRenderSpinningCubeExample.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRenderExample.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "render/NVRenderVertFragShader.h"
+#include "render_util/NVRenderUtils.h"
+#include "Qt3DSRenderExampleTools.h"
+#include "foundation/Qt3DSMat44.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+#pragma warning(disable : 4189)
+#pragma warning(disable : 4100)
+
+namespace {
+
+struct ShaderArguments
+{
+ QT3DSMat44 mMatrix;
+};
+
+class SpinningCube : public NVRenderExample
+{
+ NVRenderContext &m_Context;
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderVertFragShader> mShader;
+ NVRenderHandle mShaderArgGroupId;
+ float frus[16];
+ float model[16];
+ float rot[9];
+
+public:
+ SpinningCube(NVRenderContext &ctx)
+ : m_Context(ctx)
+ {
+ NVRenderExampleTools::createBox(ctx, mVertexBuffer.mPtr, mIndexBuffer.mPtr, false);
+ mVertexBuffer->addRef();
+ mIndexBuffer->addRef();
+ mShader = NVRenderExampleTools::createSimpleShader(ctx);
+ ctx.SetViewport(NVRenderRect(0, 0, 400, 400));
+ // These properties will get applied just before render no matter what
+ // so we can just use the default settings here.
+ ctx.SetVertexBuffer(mVertexBuffer);
+ ctx.SetIndexBuffer(mIndexBuffer);
+ if (mShader) {
+ ctx.SetActiveShader(mShader);
+ }
+ ctx.SetDepthTestEnabled(true);
+ ctx.SetDepthWriteEnabled(true);
+ NvGl2DemoMatrixIdentity(model);
+ NvGl2DemoMatrixIdentity(frus);
+ NvGl2DemoMatrixFrustum(frus, -1, 1, -1, 1, 1, 10);
+ NvGl2DemoMatrixTranslate(model, 0, 0, -4);
+ }
+ virtual void drawFrame(double currentSeconds)
+ {
+ NvGl2DemoMatrixRotate_create3x3(rot, (float)currentSeconds * 50, .707f, .707f, 0);
+ float mvp[16];
+ NvGl2DemoMatrixIdentity(mvp);
+ NvGl2DemoMatrixMultiply(mvp, frus);
+ NvGl2DemoMatrixMultiply(mvp, model);
+ NvGl2DemoMatrixMultiply_4x4_3x3(mvp, rot);
+
+ NVConstDataRef<QT3DSU8> instance((QT3DSU8 *)mvp, 16 * sizeof(float));
+ m_Context.Clear(
+ NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+ mShader->SetPropertyValue("mat_mvp", *reinterpret_cast<QT3DSMat44 *>(mvp));
+ m_Context.Draw(NVRenderDrawMode::Triangles, mIndexBuffer->GetNumIndices(), 0);
+ }
+ virtual QT3DSU32 getRuntimeInSeconds() { return mShader.mPtr ? 5 : 0; }
+ virtual void release() { NVDelete(m_Context.GetFoundation(), this); }
+};
+}
+QT3DS_RENDER_REGISTER_EXAMPLE(SpinningCube); \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAtomicCounterBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAtomicCounterBuffer.h
new file mode 100644
index 00000000..3dd21e20
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAtomicCounterBuffer.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_ATOMIC_COUNTER_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_ATOMIC_COUNTER_BUFFER_H
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Utils.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderDataBuffer.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ // forward declaration
+ class NVRenderContextImpl;
+ class AtomicCounterBufferEntry;
+
+ typedef nvhash_map<CRegisteredString, AtomicCounterBufferEntry *>
+ TRenderAtomiCounterBufferEntryMap;
+
+ ///< Constant (uniform) buffer representation
+ class NVRenderAtomicCounterBuffer : public NVRenderDataBuffer
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] bufferName Name of the buffer. Must match the name used in programs
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return.
+ */
+ NVRenderAtomicCounterBuffer(NVRenderContextImpl &context, CRegisteredString bufferName,
+ size_t size, NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data);
+
+ ///< destructor
+ virtual ~NVRenderAtomicCounterBuffer();
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief bind the buffer to a shader program
+ *
+ * @param[in] index Index of the constant buffer within the program
+ *
+ * @return no return.
+ */
+ virtual void BindToShaderProgram(QT3DSU32 index);
+
+ /**
+ * @brief update the buffer to hardware
+ *
+ * @return no return.
+ */
+ virtual void Update();
+
+ /**
+ * @brief update a piece of memory directly within the storage buffer
+ *
+ * Note: When you use this function you should know what you are doing.
+ * The memory layout within C++ must exactly match the memory layout in the
+ *shader.
+ * We use std140 (430) layout which guarantees a specific layout behavior across
+ *all HW vendors.
+ * How the memory layout is computed can be found in the GL spec.
+ *
+ * @param[in] offset offset into storage buffer
+ * @param[in] data pointer to data
+ *
+ * @return no return
+ */
+ void UpdateData(QT3DSI32 offset, NVDataRef<QT3DSU8> data);
+
+ /**
+ * @brief add a parameter to the atomic counter buffer
+ *
+ * @param[in] name Name of the parameter (must match the name in the shader
+ * program)
+ * @param[in] offset Offset in bytes into the buffer
+ *
+ * @return no return
+ */
+ void AddParam(CRegisteredString name, QT3DSU32 offset);
+
+ /**
+ * @brief Check if the buffer contains this param
+ *
+ * @param[in] name Name of the parameter (must match the name in the shader
+ * program)
+ *
+ * @return no return
+ */
+ bool ContainsParam(CRegisteredString name);
+
+ /**
+ * @brief get the buffer name
+ *
+ * @return the buffer name
+ */
+ CRegisteredString GetBufferName() const { return m_Name; }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const override
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+
+ /**
+ * @brief create a NVRenderAtomicCounterBuffer object
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return the buffer object or NULL
+ */
+ static NVRenderAtomicCounterBuffer *Create(NVRenderContextImpl &context,
+ const char *bufferName,
+ NVRenderBufferUsageType::Enum usageType,
+ size_t size, NVConstDataRef<QT3DSU8> bufferData);
+
+ private:
+ CRegisteredString m_Name; ///< buffer name
+ TRenderAtomiCounterBufferEntryMap
+ m_AtomicCounterBufferEntryMap; ///< holds the entries of a atomic counter buffer
+ bool m_Dirty; ///< true if buffer is dirty
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAttribLayout.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAttribLayout.h
new file mode 100644
index 00000000..da801c8e
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderAttribLayout.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_ATTRIB_LAYOUT_H
+#define QT3DS_RENDER_ATTRIB_LAYOUT_H
+
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Utils.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ // forward declarations
+ class NVRenderContextImpl;
+ class NVRenderBackend;
+
+ ///< this class handles the vertex attribute layout setup
+ class NVRenderAttribLayout : public NVRefCounted
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] attribs Pointer to attribute list
+ *
+ * @return No return.
+ */
+ NVRenderAttribLayout(NVRenderContextImpl &context,
+ NVConstDataRef<NVRenderVertexBufferEntry> attribs);
+ ///< destructor
+ ~NVRenderAttribLayout();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendAttribLayoutObject GetAttribLayoutHandle() const
+ {
+ return m_AttribLayoutHandle;
+ }
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+
+ NVRenderBackend::NVRenderBackendAttribLayoutObject
+ m_AttribLayoutHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderBaseTypes.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderBaseTypes.h
new file mode 100644
index 00000000..eb19be66
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderBaseTypes.h
@@ -0,0 +1,2050 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_TYPES_H
+#define QT3DS_RENDER_QT3DS_RENDER_TYPES_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSMath.h"
+#include "foundation/Qt3DSVec2.h"
+
+namespace qt3ds {
+
+namespace render {
+using namespace foundation;
+
+#define QT3DS_RENDER_ITERATE_COMPONENT_TYPES \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSU8) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSI8) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSU16) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSI16) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSU32) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSI32) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSU64) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSI64) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSF16) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSF32) \
+ QT3DS_RENDER_HANDLE_COMPONENT_TYPE(QT3DSF64)
+
+struct NVRenderComponentTypes
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_COMPONENT_TYPE(x) x,
+ QT3DS_RENDER_ITERATE_COMPONENT_TYPES
+#undef QT3DS_RENDER_HANDLE_COMPONENT_TYPE
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_COMPONENT_TYPE(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_COMPONENT_TYPES
+ #undef QT3DS_RENDER_HANDLE_COMPONENT_TYPE
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+
+ static qt3ds::QT3DSU32 getSizeofType(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_COMPONENT_TYPE(x) \
+ case x: \
+ return sizeof(qt3ds::x);
+ QT3DS_RENDER_ITERATE_COMPONENT_TYPES
+ #undef QT3DS_RENDER_HANDLE_COMPONENT_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+};
+
+/**
+ Define a set of compile-time trait classes that map the enumerations
+ to actual compile time types and sizeof so we can deal with the enumeration
+ in generic ways.
+ */
+template <NVRenderComponentTypes::Enum TraitType>
+struct NVRenderComponentTraits
+{
+ bool force_compile_error;
+};
+
+/**
+ Define a compile time mapping from datatype to enumeration. Not that if you
+ use this with a type that isn't a component type you will get a compilation
+ error.
+ */
+template <typename TDataType>
+struct NVRenderComponentTypeToTypeMap
+{
+ bool force_compile_error;
+};
+
+#define QT3DS_RENDER_HANDLE_COMPONENT_TYPE(x) \
+ template <> \
+ struct NVRenderComponentTraits<NVRenderComponentTypes::x> \
+{ \
+ typedef x TComponentType; \
+ QT3DSU8 mComponentSize; \
+ NVRenderComponentTraits<NVRenderComponentTypes::x>() \
+ : mComponentSize(sizeof(x)) \
+{ \
+} \
+}; \
+ template <> \
+ struct NVRenderComponentTypeToTypeMap<x> \
+{ \
+ NVRenderComponentTypes::Enum m_ComponentType; \
+ NVRenderComponentTypeToTypeMap<x>() \
+ : m_ComponentType(NVRenderComponentTypes::x) \
+{ \
+} \
+};
+
+QT3DS_RENDER_ITERATE_COMPONENT_TYPES;
+
+#undef QT3DS_RENDER_HANDLE_COMPONENT_TYPE
+
+// Map at compile time from component type to datatype;
+template <typename TDataType>
+inline NVRenderComponentTypes::Enum getComponentTypeForType()
+{
+ return NVRenderComponentTypeToTypeMap<TDataType>().m_ComponentType;
+}
+
+struct NVRenderContextValues
+{
+ enum Enum {
+ GLES2 = 1 << 0,
+ GL2 = 1 << 1,
+ GLES3 = 1 << 2,
+ GL3 = 1 << 3,
+ GLES3PLUS = 1 << 4,
+ GL4 = 1 << 5,
+ NullContext = 1 << 6,
+ };
+};
+
+typedef NVFlags<NVRenderContextValues::Enum, QT3DSU32> NVRenderContextType;
+
+struct NVRenderClearValues
+{
+ enum Enum {
+ Color = 1 << 0,
+ Depth = 1 << 1,
+ Stencil = 1 << 3,
+ Coverage = 1 << 4,
+ };
+};
+
+typedef NVFlags<NVRenderClearValues::Enum, QT3DSU32> NVRenderClearFlags;
+
+struct NVRenderQueryType
+{
+ enum Enum {
+ Unknown = 0,
+ Samples, ///< samples query object
+ Timer, ///< timer query object
+ };
+};
+
+struct NVRenderQueryResultType
+{
+ enum Enum {
+ Unknown = 0,
+ ResultAvailable, ///< Check if query result is available
+ Result, ///< Get actual result
+ };
+};
+
+struct NVRenderSyncType
+{
+ enum Enum {
+ Unknown = 0,
+ GpuCommandsComplete, ///< sync to Gpu commands finished
+ };
+};
+
+struct NVRenderSyncValues
+{
+ enum Enum {
+ Unknown = 0, ///< for future usage
+ };
+};
+
+typedef NVFlags<NVRenderSyncValues::Enum, QT3DSU32> NVRenderSyncFlags;
+
+struct NVRenderCommandFlushValues
+{
+ enum Enum {
+ SyncFlushCommands = 0, ///< sync for flushing command
+ };
+};
+
+typedef NVFlags<NVRenderCommandFlushValues::Enum, QT3DSU32> NVRenderCommandFlushFlags;
+
+struct NVRenderBufferBindValues
+{
+ enum Enum {
+ Unknown = 0,
+ Vertex = 1 << 0, ///< Bind as vertex buffer
+ Index = 1 << 1, ///< Bind as index buffer
+ Constant = 1 << 2, ///< Bind as constant buffer
+ Storage = 1 << 3, ///< Bind as shader storage buffer
+ Atomic_Counter = 1 << 4, ///< Bind as atomic counter buffer
+ Draw_Indirect = 1 << 5, ///< Bind as draw indirect buffer
+ };
+};
+
+typedef NVFlags<NVRenderBufferBindValues::Enum, QT3DSU32> NVRenderBufferBindFlags;
+
+struct NVRenderBufferUsageType
+{
+ enum Enum {
+ Unknown = 0,
+ Static, ///< Rarely updated
+ Dynamic, ///< Most likely updated every frame
+ };
+};
+
+struct NVRenderImageAccessType
+{
+ enum Enum {
+ Unknown = 0,
+ Read, ///< Read only access
+ Write, ///< Write only access
+ ReadWrite, ///< Read and write access
+ };
+};
+
+struct NVRenderBufferAccessTypeValues
+{
+ enum Enum {
+ Unknown = 0,
+ Read = 1 << 0, ///< Read access
+ Write = 1 << 1, ///< Write access
+ Invalid = 1 << 2, ///< No sync
+ InvalidRange = 1 << 3, ///< No sync
+
+ };
+};
+
+typedef NVFlags<NVRenderBufferAccessTypeValues::Enum, QT3DSU32> NVRenderBufferAccessFlags;
+
+///< defines a barrier of ordering the memory transactions to a command relative to those issued
+///before the barrier
+struct NVRenderBufferBarrierValues
+{
+ enum Enum {
+ Unknown = 0,
+ VertexAttribArray = 1 << 0, ///< Barrier for vertex attributes sourced from a buffer
+ ElementArray = 1 << 1, ///< Barrier for indices sourced from a buffer
+ UniformBuffer = 1 << 2, ///< Barrier for shader uniforms sourced from a buffer
+ TextureFetch = 1 << 3, ///< Barrier for texture fetches within shaders
+ ShaderImageAccess = 1 << 4, ///< Barrier for image access using load / store
+ CommandBuffer = 1 << 5, ///< Barrier for indirect drawing
+ PixelBuffer = 1 << 6, ///< Barrier for pixel buffer access
+ TextureUpdate = 1 << 7, ///< Barrier for texture writes
+ BufferUpdate = 1 << 8, ///< Barrier for buffer writes
+ Framebuffer = 1 << 9, ///< Barrier for framebuffer writes
+ TransformFeedback = 1 << 10, ///< Barrier for transform feedback writes
+ AtomicCounter = 1 << 11, ///< Barrier for atomic counter writes
+ ShaderStorage = 1 << 12, ///< Barrier for shader storage blocks writes
+ All = 0xFFFF, ///< Barrier for all of the above
+ };
+};
+
+typedef NVFlags<NVRenderBufferBarrierValues::Enum, QT3DSU32> NVRenderBufferBarrierFlags;
+
+#define QT3DS_RENDER_ITERATE_RENDERBUFFER_FORMATS \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(RGBA4) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(RGB565) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(RGBA5551) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(Depth16) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(Depth24) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(Depth32) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(StencilIndex8) \
+ QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(CoverageNV)
+
+struct NVRenderRenderBufferFormats
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(x) x,
+ QT3DS_RENDER_ITERATE_RENDERBUFFER_FORMATS
+#undef QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_RENDERBUFFER_FORMATS
+ #undef QT3DS_RENDER_HANDLE_RENDERBUFFER_FORMAT
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_TEXTURE_FORMATS \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R16) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R16F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R32I) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R32UI) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R32F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RG8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGBA8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGB8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(SRGB8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(SRGB8A8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGB565) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGBA5551) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(Alpha8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(Luminance8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(Luminance16) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(LuminanceAlpha8) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGBA16F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RG16F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RG32F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGB32F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGBA32F) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R11G11B10) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGB9E5) \
+ QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGBA_DXT1) \
+ QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGB_DXT1) \
+ QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGBA_DXT3) \
+ QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGBA_DXT5) \
+ QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(Depth16) \
+ QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(Depth24) \
+ QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(Depth32) \
+ QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(Depth24Stencil8)
+
+struct NVRenderTextureFormats
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(x) x,
+#define QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(x) x,
+#define QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(x) x,
+ QT3DS_RENDER_ITERATE_TEXTURE_FORMATS
+#undef QT3DS_RENDER_HANDLE_TEXTURE_FORMAT
+#undef QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT
+#undef QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT
+ };
+
+ static bool isUncompressedTextureFormat(NVRenderTextureFormats::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(x) \
+ case NVRenderTextureFormats::x: \
+ return true;
+#define QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(x)
+#define QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(x)
+ QT3DS_RENDER_ITERATE_TEXTURE_FORMATS
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_GL_QT3DS_DEPTH_TEXTURE_FORMAT
+ default:
+ break;
+ }
+ return false;
+ }
+
+ static bool isCompressedTextureFormat(NVRenderTextureFormats::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(x)
+#define QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(x) \
+ case NVRenderTextureFormats::x: \
+ return true;
+#define QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(x)
+ QT3DS_RENDER_ITERATE_TEXTURE_FORMATS
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_GL_QT3DS_DEPTH_TEXTURE_FORMAT
+ default:
+ break;
+ }
+ return false;
+ }
+
+ static bool isDepthTextureFormat(NVRenderTextureFormats::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(x)
+#define QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(x)
+#define QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(x) \
+ case NVRenderTextureFormats::x: \
+ return true;
+ QT3DS_RENDER_ITERATE_TEXTURE_FORMATS
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_GL_QT3DS_DEPTH_TEXTURE_FORMAT
+ default:
+ break;
+ }
+ return false;
+ }
+
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(x) \
+ case x: \
+ return #x;
+#define QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(x) \
+ case x: \
+ return #x;
+#define QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_TEXTURE_FORMATS
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT
+ #undef QT3DS_RENDER_HANDLE_DEPTH_TEXTURE_FORMAT
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+
+ static QT3DSU32 getSizeofFormat(Enum value)
+ {
+ switch (value) {
+ case R8:
+ return 1;
+ case R16F:
+ return 2;
+ case R16:
+ return 2;
+ case R32I:
+ return 4;
+ case R32F:
+ return 4;
+ case RGBA8:
+ return 4;
+ case RGB8:
+ return 3;
+ case RGB565:
+ return 2;
+ case RGBA5551:
+ return 2;
+ case Alpha8:
+ return 1;
+ case Luminance8:
+ return 1;
+ case LuminanceAlpha8:
+ return 1;
+ case Depth16:
+ return 2;
+ case Depth24:
+ return 3;
+ case Depth32:
+ return 4;
+ case Depth24Stencil8:
+ return 4;
+ case RGB9E5:
+ return 4;
+ case SRGB8:
+ return 3;
+ case SRGB8A8:
+ return 4;
+ case RGBA16F:
+ return 8;
+ case RG16F:
+ return 4;
+ case RG32F:
+ return 8;
+ case RGBA32F:
+ return 16;
+ case RGB32F:
+ return 12;
+ case R11G11B10:
+ return 4;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static QT3DSU32 getNumberOfComponent(Enum value)
+ {
+ switch (value) {
+ case R8:
+ return 1;
+ case R16F:
+ return 1;
+ case R16:
+ return 1;
+ case R32I:
+ return 1;
+ case R32F:
+ return 1;
+ case RGBA8:
+ return 4;
+ case RGB8:
+ return 3;
+ case RGB565:
+ return 3;
+ case RGBA5551:
+ return 4;
+ case Alpha8:
+ return 1;
+ case Luminance8:
+ return 1;
+ case LuminanceAlpha8:
+ return 2;
+ case Depth16:
+ return 1;
+ case Depth24:
+ return 1;
+ case Depth32:
+ return 1;
+ case Depth24Stencil8:
+ return 2;
+ case RGB9E5:
+ return 3;
+ case SRGB8:
+ return 3;
+ case SRGB8A8:
+ return 4;
+ case RGBA16F:
+ return 4;
+ case RG16F:
+ return 2;
+ case RG32F:
+ return 2;
+ case RGBA32F:
+ return 4;
+ case RGB32F:
+ return 3;
+ case R11G11B10:
+ return 3;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static void decodeToFloat(void *inPtr, QT3DSU32 byteOfs, float *outPtr,
+ NVRenderTextureFormats::Enum inFmt)
+ {
+ outPtr[0] = 0.0f;
+ outPtr[1] = 0.0f;
+ outPtr[2] = 0.0f;
+ outPtr[3] = 0.0f;
+ QT3DSU8 *src = reinterpret_cast<QT3DSU8 *>(inPtr);
+ // float divisor; // If we want to support RGBD?
+ switch (inFmt) {
+ case Alpha8:
+ outPtr[0] = ((float)src[byteOfs]) / 255.0f;
+ break;
+
+ case Luminance8:
+ case LuminanceAlpha8:
+ case R8:
+ case RG8:
+ case RGB8:
+ case RGBA8:
+ case SRGB8:
+ case SRGB8A8:
+ // NOTE : RGBD Hack here for reference. Not meant for installation.
+ // divisor = (NVRenderTextureFormats::getSizeofFormat(inFmt) == 4) ?
+ // ((float)src[byteOfs+3]) / 255.0f : 1.0f;
+ for (QT3DSU32 i = 0; i < NVRenderTextureFormats::getSizeofFormat(inFmt); ++i) {
+ float val = ((float)src[byteOfs + i]) / 255.0f;
+ outPtr[i] = (i < 3) ? powf(val, 0.4545454545f) : val;
+ // Assuming RGBA8 actually means RGBD (which is stupid, I know)
+ // if ( NVRenderTextureFormats::getSizeofFormat(inFmt) == 4 ) { outPtr[i] /=
+ // divisor; }
+ }
+ // outPtr[3] = divisor;
+ break;
+
+ case R32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ break;
+ case RG32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
+ break;
+ case RGBA32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
+ outPtr[2] = reinterpret_cast<float *>(src + byteOfs)[2];
+ outPtr[3] = reinterpret_cast<float *>(src + byteOfs)[3];
+ break;
+ case RGB32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
+ outPtr[2] = reinterpret_cast<float *>(src + byteOfs)[2];
+ break;
+
+ case R16F:
+ case RG16F:
+ case RGBA16F:
+ for (QT3DSU32 i = 0; i < (NVRenderTextureFormats::getSizeofFormat(inFmt) >> 1); ++i) {
+ // NOTE : This only works on the assumption that we don't have any denormals,
+ // Infs or NaNs.
+ // Every pixel in our source image should be "regular"
+ QT3DSU16 h = reinterpret_cast<QT3DSU16 *>(src + byteOfs)[i];
+ QT3DSU32 sign = (h & 0x8000) << 16;
+ QT3DSU32 exponent = (((((h & 0x7c00) >> 10) - 15) + 127) << 23);
+ QT3DSU32 mantissa = ((h & 0x3ff) << 13);
+ QT3DSU32 result = sign | exponent | mantissa;
+
+ if (h == 0 || h == 0x8000) {
+ result = 0;
+ } // Special case for zero and negative zero
+ qt3ds::intrinsics::memCopy(reinterpret_cast<QT3DSU32 *>(outPtr) + i, &result, 4);
+ }
+ break;
+
+ case R11G11B10:
+ // place holder
+ QT3DS_ASSERT(false);
+ break;
+
+ default:
+ outPtr[0] = 0.0f;
+ outPtr[1] = 0.0f;
+ outPtr[2] = 0.0f;
+ outPtr[3] = 0.0f;
+ break;
+ }
+ }
+
+ static void encodeToPixel(float *inPtr, void *outPtr, QT3DSU32 byteOfs,
+ NVRenderTextureFormats::Enum inFmt)
+ {
+ QT3DSU8 *dest = reinterpret_cast<QT3DSU8 *>(outPtr);
+ switch (inFmt) {
+ case NVRenderTextureFormats::Alpha8:
+ dest[byteOfs] = QT3DSU8(inPtr[0] * 255.0f);
+ break;
+
+ case Luminance8:
+ case LuminanceAlpha8:
+ case R8:
+ case RG8:
+ case RGB8:
+ case RGBA8:
+ case SRGB8:
+ case SRGB8A8:
+ for (QT3DSU32 i = 0; i < NVRenderTextureFormats::getSizeofFormat(inFmt); ++i) {
+ inPtr[i] = (inPtr[i] > 1.0f) ? 1.0f : inPtr[i];
+ if (i < 3)
+ dest[byteOfs + i] = QT3DSU8(powf(inPtr[i], 2.2f) * 255.0f);
+ else
+ dest[byteOfs + i] = QT3DSU8(inPtr[i] * 255.0f);
+ }
+ break;
+
+ case R32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ break;
+ case RG32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
+ break;
+ case RGBA32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
+ reinterpret_cast<float *>(dest + byteOfs)[2] = inPtr[2];
+ reinterpret_cast<float *>(dest + byteOfs)[3] = inPtr[3];
+ break;
+ case RGB32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
+ reinterpret_cast<float *>(dest + byteOfs)[2] = inPtr[2];
+ break;
+
+ case R16F:
+ case RG16F:
+ case RGBA16F:
+ for (QT3DSU32 i = 0; i < (NVRenderTextureFormats::getSizeofFormat(inFmt) >> 1); ++i) {
+ // NOTE : This also has the limitation of not handling infs, NaNs and
+ // denormals, but it should be
+ // sufficient for our purposes.
+ if (inPtr[i] > 65519.0f) {
+ inPtr[i] = 65519.0f;
+ }
+ if (fabs(inPtr[i]) < 6.10352E-5f) {
+ inPtr[i] = 0.0f;
+ }
+ QT3DSU32 f = reinterpret_cast<QT3DSU32 *>(inPtr)[i];
+ QT3DSU32 sign = (f & 0x80000000) >> 16;
+ QT3DSI32 exponent = (f & 0x7f800000) >> 23;
+ QT3DSU32 mantissa = (f >> 13) & 0x3ff;
+ exponent = exponent - 112;
+ if (exponent > 31) {
+ exponent = 31;
+ }
+ if (exponent < 0) {
+ exponent = 0;
+ }
+ exponent = exponent << 10;
+ reinterpret_cast<QT3DSU16 *>(dest + byteOfs)[i] =
+ QT3DSU16(sign | exponent | mantissa);
+ }
+ break;
+
+ case R11G11B10:
+ // place holder
+ QT3DS_ASSERT(false);
+ break;
+
+ default:
+ dest[byteOfs] = 0;
+ dest[byteOfs + 1] = 0;
+ dest[byteOfs + 2] = 0;
+ dest[byteOfs + 3] = 0;
+ break;
+ }
+ }
+};
+
+struct NVRenderTextureTargetType
+{
+ enum Enum {
+ Unknown = 0,
+ Texture2D,
+ Texture2D_MS,
+ Texture2D_Array,
+ TextureCube,
+ TextureCubePosX,
+ TextureCubeNegX,
+ TextureCubePosY,
+ TextureCubeNegY,
+ TextureCubePosZ,
+ TextureCubeNegZ,
+ };
+};
+
+struct NVRenderTextureUnit
+{
+ enum Enum {
+ TextureUnit_0 = 0,
+ TextureUnit_1,
+ TextureUnit_2,
+ TextureUnit_3,
+ TextureUnit_4,
+ TextureUnit_5,
+ TextureUnit_6,
+ TextureUnit_7,
+ TextureUnit_8,
+ TextureUnit_9,
+ TextureUnit_10,
+ TextureUnit_11,
+ TextureUnit_12,
+ TextureUnit_13,
+ TextureUnit_14,
+ TextureUnit_15,
+ TextureUnit_16,
+ TextureUnit_17,
+ TextureUnit_18,
+ TextureUnit_19,
+ TextureUnit_20,
+ TextureUnit_21,
+ TextureUnit_22,
+ TextureUnit_23,
+ TextureUnit_24,
+ TextureUnit_25,
+ TextureUnit_26,
+ TextureUnit_27,
+ TextureUnit_28,
+ TextureUnit_29,
+ TextureUnit_30,
+ TextureUnit_31
+ };
+};
+
+struct NVRenderTextureCompareMode
+{
+ enum Enum { Unknown = 0, NoCompare, CompareToRef };
+};
+
+struct NVRenderTextureSwizzleMode
+{
+ enum Enum { NoSwizzle = 0, L8toR8, A8toR8, L8A8toRG8, L16toR16 };
+};
+
+#define QT3DS_RENDER_ITERATE_BOOL_OP \
+ QT3DS_RENDER_HANDLE_BOOL_OP(Never) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(Less) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(LessThanOrEqual) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(Equal) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(NotEqual) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(Greater) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(GreaterThanOrEqual) \
+ QT3DS_RENDER_HANDLE_BOOL_OP(AlwaysTrue)
+
+struct NVRenderTextureCompareOp
+{
+ enum Enum {
+#define QT3DS_RENDER_HANDLE_BOOL_OP(x) x,
+ QT3DS_RENDER_ITERATE_BOOL_OP
+#undef QT3DS_RENDER_HANDLE_BOOL_OP
+ };
+};
+
+#define QT3DS_RENDER_ITERATE_TEXTURE_FILTER_OP \
+ QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP(Nearest) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP(Linear) \
+ QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(NearestMipmapNearest) \
+ QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(LinearMipmapNearest) \
+ QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(NearestMipmapLinear) \
+ QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(LinearMipmapLinear)
+
+struct NVRenderTextureMinifyingOp
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP(x) x,
+#define QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(x) x,
+ QT3DS_RENDER_ITERATE_TEXTURE_FILTER_OP
+#undef QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP
+#undef QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP
+ };
+ const char *toString(NVRenderTextureMinifyingOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP(x) \
+ case x: \
+ return #x;
+#define QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_TEXTURE_FILTER_OP
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+struct NVRenderTextureMagnifyingOp
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP(x) x,
+#define QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(x)
+ QT3DS_RENDER_ITERATE_TEXTURE_FILTER_OP
+#undef QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP
+#undef QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP
+ };
+ const char *toString(NVRenderTextureMinifyingOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP(x) \
+ case x: \
+ return #x;
+#define QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP(x)
+ QT3DS_RENDER_ITERATE_TEXTURE_FILTER_OP
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_MINIFYING_OP
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_FILTER_OP
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_TEXTURE_WRAP_OP \
+ QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP(ClampToEdge) \
+ QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP(MirroredRepeat) \
+ QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP(Repeat)
+
+struct NVRenderTextureCoordOp
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP(x) x,
+ QT3DS_RENDER_ITERATE_TEXTURE_WRAP_OP
+#undef QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP
+ };
+ const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_TEXTURE_WRAP_OP
+ #undef QT3DS_RENDER_HANDLE_TEXTURE_WRAP_OP
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_HINT \
+ QT3DS_RENDER_HANDLE_HINT(Fastest) \
+ QT3DS_RENDER_HANDLE_HINT(Nicest) \
+ QT3DS_RENDER_HANDLE_HINT(Unspecified)
+
+struct NVRenderHint
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_HINT(x) x,
+ QT3DS_RENDER_ITERATE_HINT
+#undef QT3DS_RENDER_HANDLE_HINT
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_HINT(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_HINT
+ #undef QT3DS_RENDER_HANDLE_HINT
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+class NVRenderImplemented
+{
+protected:
+ virtual ~NVRenderImplemented() {}
+public:
+ // Get the handle that binds us to the implementation.
+ // For instance, return the GLuint that came back from
+ // glGenTextures.
+ virtual const void *GetImplementationHandle() const = 0;
+};
+
+struct NVRenderVertexBufferEntry
+{
+ const char *m_Name;
+ /** Datatype of the this entry points to in the buffer */
+ NVRenderComponentTypes::Enum m_ComponentType;
+ /** Number of components of each data member. 1,2,3, or 4. Don't be stupid.*/
+ QT3DSU32 m_NumComponents;
+ /** Offset from the beginning of the buffer of the first item */
+ QT3DSU32 m_FirstItemOffset;
+ /** Attribute input slot used for this entry*/
+ QT3DSU32 m_InputSlot;
+
+ NVRenderVertexBufferEntry(const char *nm, NVRenderComponentTypes::Enum type,
+ QT3DSU32 numComponents, QT3DSU32 firstItemOffset = 0,
+ QT3DSU32 inputSlot = 0)
+ : m_Name(nm)
+ , m_ComponentType(type)
+ , m_NumComponents(numComponents)
+ , m_FirstItemOffset(firstItemOffset)
+ , m_InputSlot(inputSlot)
+ {
+ }
+
+ NVRenderVertexBufferEntry()
+ : m_Name(NULL)
+ , m_ComponentType(NVRenderComponentTypes::Unknown)
+ , m_NumComponents(0)
+ , m_FirstItemOffset(0)
+ , m_InputSlot(0)
+ {
+ }
+
+ NVRenderVertexBufferEntry(const NVRenderVertexBufferEntry &inOther)
+ : m_Name(inOther.m_Name)
+ , m_ComponentType(inOther.m_ComponentType)
+ , m_NumComponents(inOther.m_NumComponents)
+ , m_FirstItemOffset(inOther.m_FirstItemOffset)
+ , m_InputSlot(inOther.m_InputSlot)
+ {
+ }
+
+ NVRenderVertexBufferEntry &operator=(const NVRenderVertexBufferEntry &inOther)
+ {
+ if (this != &inOther) {
+ m_Name = inOther.m_Name;
+ m_ComponentType = inOther.m_ComponentType;
+ m_NumComponents = inOther.m_NumComponents;
+ m_FirstItemOffset = inOther.m_FirstItemOffset;
+ m_InputSlot = inOther.m_InputSlot;
+ }
+ return *this;
+ }
+};
+
+class NVRenderShaderProgram;
+
+typedef NVConstDataRef<QT3DSI8> TConstI8Ref;
+
+struct NVRenderVertFragCompilationResult
+{
+ const char *mShaderName;
+
+ NVRenderShaderProgram *mShader; ///< contains the program
+
+ NVRenderVertFragCompilationResult()
+ : mShaderName("")
+ , mShader(NULL)
+ {
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_FRAMEBUFFER_ATTACHMENTS \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color0) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color1) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color2) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color3) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color4) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color5) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color6) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Color7) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Depth) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(Stencil) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(DepthStencil) \
+ QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(CoverageNV)
+
+struct NVRenderFrameBufferAttachments
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT(x) x,
+ QT3DS_RENDER_ITERATE_FRAMEBUFFER_ATTACHMENTS
+#undef QT3DS_RENDER_HANDLE_FRAMEBUFFER_ATTACHMENT
+ LastAttachment,
+ };
+};
+
+struct NVRenderDrawMode
+{
+ enum Enum {
+ Unknown = 0,
+ Points,
+ LineStrip,
+ LineLoop,
+ Lines,
+ TriangleStrip,
+ TriangleFan,
+ Triangles,
+ Patches,
+ };
+};
+
+struct NVRenderTextureCubeFaces
+{
+ enum Enum {
+ InvalidFace = 0,
+ CubePosX = 1,
+ CubeNegX,
+ CubePosY,
+ CubeNegY,
+ CubePosZ,
+ CubeNegZ,
+ };
+};
+
+// enums match the NV path extensions
+struct NVRenderPathCommands
+{
+ enum Enum {
+ Close = 0,
+ MoveTo = 2,
+ CubicCurveTo = 12,
+ };
+};
+
+struct NVRenderPathFontTarget
+{
+ enum Enum {
+ StandardFont = 0,
+ SystemFont = 1,
+ FileFont = 2,
+ };
+};
+
+struct NVRenderPathMissingGlyphs
+{
+ enum Enum {
+ SkipMissing = 0,
+ UseMissing = 1,
+ };
+};
+
+struct NVRenderPathFontStyleValues
+{
+ enum Enum {
+ Bold = 1 << 0,
+ Italic = 1 << 1,
+ };
+};
+
+typedef NVFlags<NVRenderPathFontStyleValues::Enum, QT3DSU32> NVRenderPathFontStyleFlags;
+
+struct NVRenderPathReturnValues
+{
+ enum Enum {
+ FontGlypsAvailable = 0,
+ FontTargetUnavailable = 1,
+ FontUnavailable = 2,
+ FontUnintelligible = 3,
+ InvalidEnum = 4,
+ OutOfMemory = 5,
+ };
+};
+
+struct NVRenderPathFormatType
+{
+ enum Enum {
+ Byte = 1,
+ UByte,
+ Short,
+ UShort,
+ Int,
+ Uint,
+ Float,
+ Utf8,
+ Utf16,
+ Bytes2,
+ Bytes3,
+ Bytes4,
+ };
+};
+
+struct NVRenderPathGlyphFontMetricValues
+{
+ enum Enum {
+ GlyphWidth = 1 << 0,
+ GlyphHeight = 1 << 1,
+ GlyphHorizontalBearingX = 1 << 2,
+ GlyphHorizontalBearingY = 1 << 3,
+ GlyphHorizontalBearingAdvance = 1 << 4,
+ GlyphVerticalBearingX = 1 << 5,
+ GlyphVerticalBearingY = 1 << 6,
+ GlyphVerticalBearingAdvance = 1 << 7,
+ GlyphHasKerning = 1 << 8,
+
+ FontXMinBounds = 1 << 9,
+ FontYMinBounds = 1 << 10,
+ FontXMaxBounds = 1 << 11,
+ FontYMaxBounds = 1 << 12,
+ FontUnitsPerEm = 1 << 13,
+ FontAscender = 1 << 14,
+ FontDescender = 1 << 15,
+ FontHeight = 1 << 16,
+ FontMaxAdvanceWidth = 1 << 17,
+ FontMaxAdvanceHeight = 1 << 18,
+ FontUnderlinePosition = 1 << 19,
+ FontUnderlineThickness = 1 << 20,
+ FontHasKerning = 1 << 21,
+ FontNumGlyphIndices = 1 << 22,
+ };
+};
+
+typedef NVFlags<NVRenderPathGlyphFontMetricValues::Enum, QT3DSU32>
+NVRenderPathGlyphFontMetricFlags;
+
+struct NVRenderPathListMode
+{
+ enum Enum {
+ AccumAdjacentPairs = 1,
+ AdjacentPairs,
+ FirstToRest,
+ };
+};
+
+struct NVRenderPathFillMode
+{
+ enum Enum {
+ Fill = 1,
+ CountUp,
+ CountDown,
+ Invert,
+ };
+};
+
+struct NVRenderPathCoverMode
+{
+ enum Enum {
+ ConvexHull = 1,
+ BoundingBox,
+ BoundingBoxOfBoundingBox,
+ PathFillCover,
+ PathStrokeCover,
+ };
+};
+
+struct NVRenderPathTransformType
+{
+ enum Enum {
+ NoTransform = 0,
+ TranslateX,
+ TranslateY,
+ Translate2D,
+ Translate3D,
+ Affine2D,
+ Affine3D,
+ TransposeAffine2D,
+ TransposeAffine3D,
+ };
+};
+
+#define QT3DS_RENDER_ITERATE_WINDING \
+ QT3DS_RENDER_HANDLE_WINDING(Clockwise) \
+ QT3DS_RENDER_HANDLE_WINDING(CounterClockwise)
+
+struct NVRenderWinding
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_WINDING(x) x,
+ QT3DS_RENDER_ITERATE_WINDING
+#undef QT3DS_RENDER_HANDLE_WINDING
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_WINDING(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_WINDING
+ #undef QT3DS_RENDER_HANDLE_WINDING
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_RENDER_STATE \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(Blend) \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(CullFace) \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(DepthTest) \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(StencilTest) \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(ScissorTest) \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(DepthWrite) \
+ QT3DS_RENDER_HANDLE_RENDER_STATE(Multisample)
+
+struct NVRenderState
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_RENDER_STATE(x) x,
+ QT3DS_RENDER_ITERATE_RENDER_STATE
+#undef QT3DS_RENDER_HANDLE_RENDER_STATE
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_RENDER_STATE(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_RENDER_STATE
+ #undef QT3DS_RENDER_HANDLE_RENDER_STATE
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_BLEND_FUNC \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(Zero) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(One) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(SrcColor) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(OneMinusSrcColor) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(DstColor) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(OneMinusDstColor) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(SrcAlpha) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(OneMinusSrcAlpha) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(DstAlpha) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(OneMinusDstAlpha) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(ConstantColor) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(OneMinusConstantColor) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(ConstantAlpha) \
+ QT3DS_RENDER_HANDLE_BLEND_FUNC(OneMinusConstantAlpha) \
+ QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC(SrcAlphaSaturate)
+
+struct NVRenderSrcBlendFunc
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_BLEND_FUNC(x) x,
+#define QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC(x) x,
+ QT3DS_RENDER_ITERATE_BLEND_FUNC
+#undef QT3DS_RENDER_HANDLE_BLEND_FUNC
+#undef QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC
+ };
+
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_BLEND_FUNC(x) \
+ case x: \
+ return #x;
+#define QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_BLEND_FUNC
+ #undef QT3DS_RENDER_HANDLE_BLEND_FUNC
+ #undef QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+struct NVRenderDstBlendFunc
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_BLEND_FUNC(x) x,
+#define QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC(x)
+ QT3DS_RENDER_ITERATE_BLEND_FUNC
+#undef QT3DS_RENDER_HANDLE_BLEND_FUNC
+#undef QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC
+ };
+
+ static const char *toString(Enum value)
+ {
+ return NVRenderSrcBlendFunc::toString((NVRenderSrcBlendFunc::Enum)value);
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_BLEND_EQUATION \
+ QT3DS_RENDER_HANDLE_BLEND_EQUATION(Add) \
+ QT3DS_RENDER_HANDLE_BLEND_EQUATION(Subtract) \
+ QT3DS_RENDER_HANDLE_BLEND_EQUATION(ReverseSubtract) \
+ QT3DS_RENDER_HANDLE_BLEND_EQUATION(Overlay) \
+ QT3DS_RENDER_HANDLE_BLEND_EQUATION(ColorBurn) \
+ QT3DS_RENDER_HANDLE_BLEND_EQUATION(ColorDodge)
+
+struct NVRenderBlendEquation
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_BLEND_EQUATION(x) x,
+ QT3DS_RENDER_ITERATE_BLEND_EQUATION
+#undef QT3DS_RENDER_HANDLE_BLEND_EQUATION
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_BLEND_EQUATION(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_BLEND_EQUATION
+ #undef QT3DS_RENDER_HANDLE_BLEND_EQUATION
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_FACES \
+ QT3DS_RENDER_HANDLE_FACES(Front) \
+ QT3DS_RENDER_HANDLE_FACES(Back) \
+ QT3DS_RENDER_HANDLE_FACES(FrontAndBack)
+
+struct NVRenderFaces
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_FACES(x) x,
+ QT3DS_RENDER_ITERATE_FACES
+#undef QT3DS_RENDER_HANDLE_FACES
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_FACES(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_FACES
+ #undef QT3DS_RENDER_HANDLE_FACES
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_READ_FACES \
+ QT3DS_RENDER_HANDLE_READ_FACES(Front) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Back) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color0) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color1) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color2) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color3) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color4) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color5) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color6) \
+ QT3DS_RENDER_HANDLE_READ_FACES(Color7)
+
+struct NVReadFaces
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_READ_FACES(x) x,
+ QT3DS_RENDER_ITERATE_READ_FACES
+#undef QT3DS_RENDER_HANDLE_READ_FACES
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_READ_FACES(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_READ_FACES
+ #undef QT3DS_RENDER_HANDLE_READ_FACES
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+struct NVRenderBoolOp
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_BOOL_OP(x) x,
+ QT3DS_RENDER_ITERATE_BOOL_OP
+#undef QT3DS_RENDER_HANDLE_BOOL_OP
+ };
+
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_BOOL_OP(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_BOOL_OP
+ #undef QT3DS_RENDER_HANDLE_BOOL_OP
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+#define QT3DS_RENDER_ITERATE_STENCIL_OP \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(Keep) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(Zero) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(Replace) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(Increment) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(IncrementWrap) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(Decrement) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(DecrementWrap) \
+ QT3DS_RENDER_HANDLE_STENCIL_OP(Invert)
+
+struct NVRenderStencilOp
+{
+ enum Enum {
+ Unknown = 0,
+#define QT3DS_RENDER_HANDLE_STENCIL_OP(x) x,
+ QT3DS_RENDER_ITERATE_STENCIL_OP
+#undef QT3DS_RENDER_HANDLE_STENCIL_OP
+ };
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_STENCIL_OP(x) \
+ case x: \
+ return #x;
+ QT3DS_RENDER_ITERATE_STENCIL_OP
+ #undef QT3DS_RENDER_HANDLE_STENCIL_OP
+ default:
+ break;
+ }
+ return "Unknown";
+ }
+};
+
+struct NVRenderBlendFunctionArgument
+{
+ NVRenderSrcBlendFunc::Enum m_SrcRGB;
+ NVRenderDstBlendFunc::Enum m_DstRGB;
+ NVRenderSrcBlendFunc::Enum m_SrcAlpha;
+ NVRenderDstBlendFunc::Enum m_DstAlpha;
+
+ NVRenderBlendFunctionArgument(NVRenderSrcBlendFunc::Enum srcRGB,
+ NVRenderDstBlendFunc::Enum dstRGB,
+ NVRenderSrcBlendFunc::Enum srcAlpha,
+ NVRenderDstBlendFunc::Enum dstAlpha)
+ : m_SrcRGB(srcRGB)
+ , m_DstRGB(dstRGB)
+ , m_SrcAlpha(srcAlpha)
+ , m_DstAlpha(dstAlpha)
+ {
+ }
+
+ // Default blend system premultiplies values.
+ NVRenderBlendFunctionArgument()
+ : m_SrcRGB(NVRenderSrcBlendFunc::SrcAlpha)
+ , m_DstRGB(NVRenderDstBlendFunc::OneMinusSrcAlpha)
+ , m_SrcAlpha(NVRenderSrcBlendFunc::One)
+ , m_DstAlpha(NVRenderDstBlendFunc::OneMinusSrcAlpha)
+ {
+ }
+};
+
+struct NVRenderBlendEquationArgument
+{
+ NVRenderBlendEquation::Enum m_RGBEquation;
+ NVRenderBlendEquation::Enum m_AlphaEquation;
+
+ NVRenderBlendEquationArgument(NVRenderBlendEquation::Enum rgb,
+ NVRenderBlendEquation::Enum alpha)
+ : m_RGBEquation(rgb)
+ , m_AlphaEquation(alpha)
+ {
+ }
+ NVRenderBlendEquationArgument()
+ : m_RGBEquation(NVRenderBlendEquation::Add)
+ , m_AlphaEquation(NVRenderBlendEquation::Add)
+ {
+ }
+};
+
+struct NVRenderStencilOperationArgument
+{
+ NVRenderStencilOp::Enum m_StencilFail; // What happens when stencil test fails.
+ // These values assume the stencil passed
+ NVRenderStencilOp::Enum
+ m_DepthFail; // What happens when the stencil passes but depth test fail.
+ NVRenderStencilOp::Enum m_DepthPass; // What happens when the stencil and depth tests pass.
+
+ NVRenderStencilOperationArgument(NVRenderStencilOp::Enum fail,
+ NVRenderStencilOp::Enum depthFail,
+ NVRenderStencilOp::Enum depthPass)
+ : m_StencilFail(fail)
+ , m_DepthFail(depthFail)
+ , m_DepthPass(depthPass)
+ {
+ }
+ NVRenderStencilOperationArgument()
+ : m_StencilFail(NVRenderStencilOp::Keep)
+ , m_DepthFail(NVRenderStencilOp::Keep)
+ , m_DepthPass(NVRenderStencilOp::Keep)
+ {
+ }
+ NVRenderStencilOperationArgument(const NVRenderStencilOperationArgument &StencilOp)
+ : m_StencilFail(StencilOp.m_StencilFail)
+ , m_DepthFail(StencilOp.m_DepthFail)
+ , m_DepthPass(StencilOp.m_DepthPass)
+ {
+ }
+
+ NVRenderStencilOperationArgument &operator=(const NVRenderStencilOperationArgument &rhs)
+ {
+ // Check for self-assignment!
+ if (this == &rhs)
+ return *this;
+
+ m_StencilFail = rhs.m_StencilFail;
+ m_DepthFail = rhs.m_DepthFail;
+ m_DepthPass = rhs.m_DepthPass;
+
+ return *this;
+ }
+
+ bool operator==(const NVRenderStencilOperationArgument &other) const
+ {
+ return (m_StencilFail == other.m_StencilFail && m_DepthFail == other.m_DepthFail
+ && m_DepthPass == other.m_DepthPass);
+ }
+};
+
+// see glStencilFuncSeparate
+struct NVRenderStencilFunctionArgument
+{
+ NVRenderBoolOp::Enum m_Function;
+ QT3DSU32 m_ReferenceValue;
+ QT3DSU32 m_Mask;
+
+ NVRenderStencilFunctionArgument(NVRenderBoolOp::Enum function, QT3DSU32 referenceValue,
+ QT3DSU32 mask)
+ : m_Function(function)
+ , m_ReferenceValue(referenceValue)
+ , m_Mask(mask)
+ {
+ }
+ NVRenderStencilFunctionArgument()
+ : m_Function(NVRenderBoolOp::AlwaysTrue)
+ , m_ReferenceValue(0)
+ , m_Mask((QT3DSU32)-1)
+ {
+ }
+ NVRenderStencilFunctionArgument(const NVRenderStencilFunctionArgument &StencilFunc)
+ : m_Function(StencilFunc.m_Function)
+ , m_ReferenceValue(StencilFunc.m_ReferenceValue)
+ , m_Mask(StencilFunc.m_Mask)
+ {
+ }
+
+ NVRenderStencilFunctionArgument &operator=(const NVRenderStencilFunctionArgument &rhs)
+ {
+ // Check for self-assignment!
+ if (this == &rhs)
+ return *this;
+
+ m_Function = rhs.m_Function;
+ m_ReferenceValue = rhs.m_ReferenceValue;
+ m_Mask = rhs.m_Mask;
+
+ return *this;
+ }
+
+ bool operator==(const NVRenderStencilFunctionArgument &other) const
+ {
+ return (m_Function == other.m_Function && m_ReferenceValue == other.m_ReferenceValue
+ && m_Mask == other.m_Mask);
+ }
+};
+
+class NVRenderFrameBuffer;
+class NVRenderVertexBuffer;
+class NVRenderIndexBuffer;
+class NVRenderShaderProgram;
+class NVRenderProgramPipeline;
+class NVRenderTextureBase;
+class NVRenderTexture2D;
+class NVRenderTexture2DArray;
+class NVRenderTextureCube;
+class NVRenderImage2D;
+class NVRenderDataBuffer;
+class NVRenderAttribLayout;
+class NVRenderInputAssembler;
+
+typedef NVRenderFrameBuffer *NVRenderFrameBufferPtr;
+typedef NVRenderVertexBuffer *NVRenderVertexBufferPtr;
+typedef NVRenderIndexBuffer *NVRenderIndexBufferPtr;
+typedef NVRenderTexture2D *NVRenderTexture2DPtr;
+typedef NVRenderTexture2DArray *NVRenderTexture2DArrayPtr;
+typedef NVRenderTextureCube *NVRenderTextureCubePtr;
+typedef NVRenderImage2D *NVRenderImage2DPtr;
+typedef NVRenderDataBuffer *NVRenderDataBufferPtr;
+typedef const char *NVRenderConstCharPtr;
+typedef bool QT3DSRenderBool;
+typedef NVRenderShaderProgram *NVRenderShaderProgramPtr;
+typedef NVDataRef<QT3DSU32> NVU32List;
+typedef NVDataRef<const char *> NVConstCharPtrList;
+
+template <typename TDataType>
+struct NVRenderRectT
+{
+ typedef TDataType TRectType;
+ TDataType m_X;
+ TDataType m_Y;
+ TDataType m_Width;
+ TDataType m_Height;
+ NVRenderRectT(TDataType x, TDataType y, TDataType w, TDataType h)
+ : m_X(x)
+ , m_Y(y)
+ , m_Width(w)
+ , m_Height(h)
+ {
+ }
+ NVRenderRectT()
+ : m_X(0)
+ , m_Y(0)
+ , m_Width(0)
+ , m_Height(0)
+ {
+ }
+ bool operator==(const NVRenderRectT<TDataType> &inOther) const
+ {
+ return m_X == inOther.m_X && m_Y == inOther.m_Y && m_Width == inOther.m_Width
+ && m_Height == inOther.m_Height;
+ }
+ bool operator!=(const NVRenderRectT<TDataType> &inOther) const
+ {
+ return !(*this == inOther);
+ }
+ TDataType GetRightExtent() const { return m_X + m_Width; }
+ TDataType GetBottomExtent() const { return m_Y + m_Height; }
+ // Ensure this rect is inside the bounds of the other rect
+ void EnsureInBounds(const NVRenderRectT<TDataType> &inOther)
+ {
+ TDataType rightExtent = qt3ds::NVMin(GetRightExtent(), inOther.GetRightExtent());
+ TDataType bottomExtent = qt3ds::NVMin(GetBottomExtent(), inOther.GetBottomExtent());
+ m_X = qt3ds::NVMax(m_X, inOther.m_X);
+ m_Y = qt3ds::NVMax(m_Y, inOther.m_Y);
+ m_Width = NVMax(static_cast<TDataType>(0), rightExtent - m_X);
+ m_Height = NVMax(static_cast<TDataType>(0), bottomExtent - m_Y);
+ }
+};
+
+// Render rects are setup to be in the coordinate space of the gl viewport,
+// so x, y are left, bottom with increasing units going to the right and
+// up respectively.
+struct NVRenderRect : public NVRenderRectT<QT3DSI32>
+{
+ typedef NVRenderRectT<QT3DSI32> TBase;
+ NVRenderRect(QT3DSI32 x, QT3DSI32 y, QT3DSI32 w, QT3DSI32 h)
+ : TBase(x, y, w, h)
+ {
+ }
+ NVRenderRect()
+ : TBase()
+ {
+ }
+};
+
+struct NVRenderRectF : public NVRenderRectT<QT3DSF32>
+{
+ typedef NVRenderRectT<QT3DSF32> TBase;
+ NVRenderRectF(QT3DSF32 x, QT3DSF32 y, QT3DSF32 w, QT3DSF32 h)
+ : TBase(x, y, w, h)
+ {
+ }
+ NVRenderRectF()
+ : TBase()
+ {
+ }
+ NVRenderRectF(const NVRenderRect &inRect)
+ : TBase((QT3DSF32)inRect.m_X, (QT3DSF32)inRect.m_Y, (QT3DSF32)inRect.m_Width,
+ (QT3DSF32)inRect.m_Height)
+ {
+ }
+ NVRenderRect ToIntegerRect() const
+ {
+ return NVRenderRect((QT3DSI32)m_X, (QT3DSI32)m_Y, (QT3DSU32)(m_Width + .5f),
+ (QT3DSU32)(m_Height + .5f));
+ }
+ QT3DSVec2 BottomLeft() const { return QT3DSVec2(m_X, m_Y); }
+ QT3DSVec2 Center() const
+ {
+ QT3DSVec2 halfDims = HalfDims();
+ return QT3DSVec2(m_X + halfDims.x, m_Y + halfDims.y);
+ }
+ QT3DSVec2 HalfDims() const { return QT3DSVec2(m_Width / 2.0f, m_Height / 2.0f); }
+ // Normalized coordinates are in the range of -1,1 where -1 is the left, bottom edges
+ // and 1 is the top,right edges.
+ QT3DSVec2 AbsoluteToNormalizedCoordinates(QT3DSVec2 absoluteCoordinates) const
+ {
+ QT3DSVec2 relativeCoords(ToRectRelative(absoluteCoordinates));
+ return RelativeToNormalizedCoordinates(relativeCoords);
+ };
+
+ QT3DSVec2 RelativeToNormalizedCoordinates(QT3DSVec2 rectRelativeCoords) const
+ {
+ QT3DSVec2 halfDims(HalfDims());
+ QT3DSVec2 retval((rectRelativeCoords.x / halfDims.x) - 1.0f,
+ (rectRelativeCoords.y / halfDims.y) - 1.0f);
+ return retval;
+ }
+
+ // Take coordinates in global space and move local space where 0,0 is the center
+ // of the rect but return value in pixels, not in normalized -1,1 range
+ QT3DSVec2 ToNormalizedRectRelative(QT3DSVec2 absoluteCoordinates) const
+ {
+ // normalize them
+ QT3DSVec2 relativeCoords(ToRectRelative(absoluteCoordinates));
+ QT3DSVec2 halfDims(HalfDims());
+ QT3DSVec2 normalized((relativeCoords.x / halfDims.x) - 1.0f,
+ (relativeCoords.y / halfDims.y) - 1.0f);
+ return QT3DSVec2(normalized.x * halfDims.x, normalized.y * halfDims.y);
+ }
+
+ // Return coordinates in pixels but relative to this rect.
+ QT3DSVec2 ToRectRelative(QT3DSVec2 absoluteCoordinates) const
+ {
+ return QT3DSVec2(absoluteCoordinates.x - m_X, absoluteCoordinates.y - m_Y);
+ }
+
+ QT3DSVec2 ToAbsoluteCoords(QT3DSVec2 inRelativeCoords) const
+ {
+ return QT3DSVec2(inRelativeCoords.x + m_X, inRelativeCoords.y + m_Y);
+ }
+};
+
+template <typename TDataType>
+struct NVRenderGenericVec2
+{
+ TDataType x;
+ TDataType y;
+ NVRenderGenericVec2(TDataType _x, TDataType _y)
+ : x(_x)
+ , y(_y)
+ {
+ }
+ NVRenderGenericVec2() {}
+ bool operator==(const NVRenderGenericVec2 &inOther) const
+ {
+ return x == inOther.x && y == inOther.y;
+ }
+};
+
+template <typename TDataType>
+struct NVRenderGenericVec3
+{
+ TDataType x;
+ TDataType y;
+ TDataType z;
+ NVRenderGenericVec3(TDataType _x, TDataType _y, TDataType _z)
+ : x(_x)
+ , y(_y)
+ , z(_z)
+ {
+ }
+ NVRenderGenericVec3() {}
+ bool operator==(const NVRenderGenericVec3 &inOther) const
+ {
+ return x == inOther.x && y == inOther.y && z == inOther.z;
+ }
+};
+
+template <typename TDataType>
+struct NVRenderGenericVec4
+{
+ TDataType x;
+ TDataType y;
+ TDataType z;
+ TDataType w;
+ NVRenderGenericVec4(TDataType _x, TDataType _y, TDataType _z, TDataType _w)
+ : x(_x)
+ , y(_y)
+ , z(_z)
+ , w(_w)
+ {
+ }
+ NVRenderGenericVec4() {}
+ bool operator==(const NVRenderGenericVec4 &inOther) const
+ {
+ return x == inOther.x && y == inOther.y && z == inOther.z && w == inOther.w;
+ }
+};
+
+#define DECLARE_GENERIC_VECTOR_TYPE(type, numElems) \
+ typedef NVRenderGenericVec##numElems<type> type##_##numElems
+DECLARE_GENERIC_VECTOR_TYPE(bool, 2);
+DECLARE_GENERIC_VECTOR_TYPE(bool, 3);
+DECLARE_GENERIC_VECTOR_TYPE(bool, 4);
+DECLARE_GENERIC_VECTOR_TYPE(QT3DSU32, 2);
+DECLARE_GENERIC_VECTOR_TYPE(QT3DSU32, 3);
+DECLARE_GENERIC_VECTOR_TYPE(QT3DSU32, 4);
+DECLARE_GENERIC_VECTOR_TYPE(QT3DSI32, 2);
+DECLARE_GENERIC_VECTOR_TYPE(QT3DSI32, 3);
+DECLARE_GENERIC_VECTOR_TYPE(QT3DSI32, 4);
+
+#define ITERATE_QT3DS_SHADER_DATA_TYPES \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSI32) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSI32_2) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSI32_3) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSI32_4) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSRenderBool) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(bool_2) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(bool_3) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(bool_4) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSF32) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSVec2) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSVec3) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSVec4) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSU32) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSU32_2) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSU32_3) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSU32_4) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSMat33) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(QT3DSMat44) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(NVRenderTexture2DPtr) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(NVRenderTexture2DArrayPtr) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(NVRenderTextureCubePtr) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(NVRenderImage2DPtr) \
+ HANDLE_QT3DS_SHADER_DATA_TYPE(NVRenderDataBufferPtr)
+
+struct NVRenderShaderDataTypes
+{
+ enum Enum {
+ Unknown = 0,
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(type) type,
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ };
+};
+
+template <typename TDataType>
+struct NVDataTypeToShaderDataTypeMap
+{
+};
+
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(type) \
+ template <> \
+ struct NVDataTypeToShaderDataTypeMap<type> \
+{ \
+ static NVRenderShaderDataTypes::Enum GetType() { return NVRenderShaderDataTypes::type; } \
+};
+ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+
+template <>
+struct NVDataTypeToShaderDataTypeMap<NVConstDataRef<QT3DSMat44>>
+{
+ static NVRenderShaderDataTypes::Enum GetType() { return NVRenderShaderDataTypes::QT3DSMat44; }
+};
+
+struct NVRenderShaderTypeValue
+{
+ enum Enum {
+ Unknown = 1 << 0,
+ Vertex = 1 << 1,
+ Fragment = 1 << 2,
+ TessControl = 1 << 3,
+ TessEvaluation = 1 << 4,
+ Geometry = 1 << 5
+ };
+};
+
+typedef NVFlags<NVRenderShaderTypeValue::Enum, QT3DSU32> NVRenderShaderTypeFlags;
+
+struct NVRenderTextureTypeValue
+{
+ enum Enum {
+ Unknown = 0,
+ Diffuse,
+ Specular,
+ Environment,
+ Bump,
+ Normal,
+ Displace,
+ Emissive,
+ Emissive2,
+ Anisotropy,
+ Translucent,
+ LightmapIndirect,
+ LightmapRadiosity,
+ LightmapShadow
+ };
+
+ static const char *toString(NVRenderTextureTypeValue::Enum value)
+ {
+ switch (value) {
+ case Unknown:
+ return "Unknown";
+ case Diffuse:
+ return "Diffuse";
+ case Specular:
+ return "Specular";
+ case Environment:
+ return "Environment";
+ case Bump:
+ return "Bump";
+ case Normal:
+ return "Normal";
+ case Displace:
+ return "Displace";
+ case Emissive:
+ return "Emissive";
+ case Emissive2:
+ return "Emissive2";
+ case Anisotropy:
+ return "Anisotropy";
+ case Translucent:
+ return "Translucent";
+ case LightmapIndirect:
+ return "LightmapIndirect";
+ case LightmapRadiosity:
+ return "LightmapRadiosity";
+ case LightmapShadow:
+ return "LightmapShadow";
+ default:
+ return "Unknown";
+ }
+ }
+};
+
+#define ITERATE_QT3DS_READ_PIXEL_FORMATS \
+ HANDLE_QT3DS_READ_PIXEL_FORMAT(Alpha8) \
+ HANDLE_QT3DS_READ_PIXEL_FORMAT(RGB565) \
+ HANDLE_QT3DS_READ_PIXEL_FORMAT(RGB8) \
+ HANDLE_QT3DS_READ_PIXEL_FORMAT(RGBA4444) \
+ HANDLE_QT3DS_READ_PIXEL_FORMAT(RGBA5551) \
+ HANDLE_QT3DS_READ_PIXEL_FORMAT(RGBA8)
+
+struct NVRenderReadPixelFormats
+{
+ enum Enum {
+ Unknown = 0,
+#define HANDLE_QT3DS_READ_PIXEL_FORMAT(format) format,
+ ITERATE_QT3DS_READ_PIXEL_FORMATS
+#undef HANDLE_QT3DS_READ_PIXEL_FORMAT
+ };
+};
+
+// Now for scoped property access.
+template <typename TBaseType, typename TDataType>
+struct NVRenderGenericScopedProperty
+{
+ typedef void (TBaseType::*TSetter)(TDataType inType);
+ typedef TDataType (TBaseType::*TGetter)() const;
+
+ TBaseType &m_Context;
+ TSetter m_Setter;
+ TDataType m_InitialValue;
+ NVRenderGenericScopedProperty(TBaseType &ctx, TGetter getter, TSetter setter)
+ : m_Context(ctx)
+ , m_Setter(setter)
+ , m_InitialValue(((ctx).*getter)())
+ {
+ }
+ NVRenderGenericScopedProperty(TBaseType &ctx, TGetter getter, TSetter setter,
+ const TDataType &inNewValue)
+ : m_Context(ctx)
+ , m_Setter(setter)
+ , m_InitialValue(((ctx).*getter)())
+ {
+ ((m_Context).*m_Setter)(inNewValue);
+ }
+ ~NVRenderGenericScopedProperty() { ((m_Context).*m_Setter)(m_InitialValue); }
+};
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderComputeShader.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderComputeShader.h
new file mode 100644
index 00000000..1ab36bc0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderComputeShader.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_COMPUTE_SHADER_H
+#define QT3DS_RENDER_COMPUTE_SHADER_H
+
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderShader.h"
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ ///< This class represents a compute shader
+ class NVRenderComputeShader : public NVRenderShader
+ {
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] source Pointer to shader source code
+ * @param[in] binaryProgram true if this is a binary program
+ *
+ * @return No return.
+ */
+ NVRenderComputeShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram);
+
+ /// @brief destructor
+ ~NVRenderComputeShader();
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ bool IsValid() override { return (m_ShaderHandle != NULL); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendComputeShaderObject GetShaderHandle()
+ {
+ return m_ShaderHandle;
+ }
+
+ private:
+ NVRenderBackend::NVRenderBackendComputeShaderObject
+ m_ShaderHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderConstantBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderConstantBuffer.h
new file mode 100644
index 00000000..3d5af34c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderConstantBuffer.h
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_CONSTANT_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_CONSTANT_BUFFER_H
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Utils.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderDataBuffer.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ // forward declaration
+ class NVRenderContextImpl;
+ class ConstantBufferParamEntry;
+ class NVRenderShaderProgram;
+
+ typedef nvhash_map<CRegisteredString, ConstantBufferParamEntry *> TRenderConstantBufferEntryMap;
+
+ ///< Constant (uniform) buffer representation
+ class NVRenderConstantBuffer : public NVRenderDataBuffer
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] bufferName Name of the buffer. Must match the name used in programs
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return.
+ */
+ NVRenderConstantBuffer(NVRenderContextImpl &context, CRegisteredString bufferName,
+ size_t size, NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data);
+
+ ///< destructor
+ virtual ~NVRenderConstantBuffer();
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief bind the buffer to a shader program
+ *
+ * @param[in] inShader Pointer to active program
+ * @param[in] blockIndex Index of the constant block within the program
+ * @param[in] binding Binding point of constant buffer
+ *
+ * @return no return.
+ */
+ virtual void BindToShaderProgram(NVRenderShaderProgram *inShader, QT3DSU32 blockIndex,
+ QT3DSU32 binding);
+
+ /**
+ * @brief update the buffer to hardware
+ *
+ * @return no return.
+ */
+ virtual void Update();
+
+ /**
+ * @brief setup constant buffer
+ *
+ * @param[in] pProgram Pointer to the shader program
+ * @param[in] index Index of the constant buffer within the program
+ * @param[in] bufSize Size of the constant buffer
+ * @param[in] paramCount Parameter entry count of the constant buffer
+ *
+ * @return return if successful
+ */
+ bool SetupBuffer(NVRenderShaderProgram *pProgram, QT3DSI32 index, QT3DSI32 bufSize,
+ QT3DSI32 paramCount);
+
+ /**
+ * @brief add a parameter to the constant buffer
+ *
+ * @param[in] name Name of the parameter (must match the name in the shader
+ * program)
+ * @param[in] type Type of the parameter like Mat44
+ * @param[in] count One or size of array
+ *
+ * @return no return
+ */
+ void AddParam(CRegisteredString name, NVRenderShaderDataTypes::Enum type, QT3DSI32 count);
+
+ /**
+ * @brief update a parameter in the constant buffer
+ *
+ * @param[in] name Name of the parameter (must match the name in the shader
+ * program)
+ * @param[in] value New value
+ *
+ * @return no return
+ */
+ void UpdateParam(const char *name, NVDataRef<QT3DSU8> value);
+
+ /**
+ * @brief update a piece of memory directly within the constant buffer
+ *
+ * Note: When you use this function you should know what you are doing.
+ * The memory layout within C++ must exactly match the memory layout in the
+ *shader.
+ * We use std140 layout which guarantees a specific layout behavior across all
+ *HW vendors.
+ * How the memory layout is computed can be found in the GL spec.
+ *
+ * @param[in] offset offset into constant buffer
+ * @param[in] data pointer to new data
+ *
+ * @return no return
+ */
+ void UpdateRaw(QT3DSI32 offset, NVDataRef<QT3DSU8> data);
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const override
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+
+ /**
+ * @brief create a NVRenderConstantBuffer object
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return the backend object handle.
+ */
+ static NVRenderConstantBuffer *Create(NVRenderContextImpl &context, const char *bufferName,
+ NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData);
+
+ /**
+ * @brief get the buffer name
+ *
+ * @return the buffer name
+ */
+ CRegisteredString GetBufferName() const { return m_Name; }
+
+ private:
+ /**
+ * @brief Create a parameter entry
+ *
+ * @param[in] name Name of the parameter (must match the name in the shader
+ * program)
+ * @param[in] type Type of the parameter like Mat44
+ * @param[in] count One or size of array
+ * @param[in] offset Offset of the parameter in the memory buffer
+ *
+ * @return return new Entry
+ */
+ ConstantBufferParamEntry *createParamEntry(CRegisteredString name,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count,
+ QT3DSI32 offset);
+
+ /**
+ * @brief get size of a uniform type
+ *
+ * @param[in] type type of uniform
+ *
+ * @return return uniform size
+ */
+ QT3DSI32
+ getUniformTypeSize(NVRenderShaderDataTypes::Enum type);
+
+ /**
+ * @brief allocate the shadow buffer
+ *
+ * @param[in] size size of buffer
+ *
+ * @return return true on success
+ */
+ bool allocateShadowBuffer(QT3DSU32 size);
+
+ /**
+ * @brief update a certain range of the buffer to hardware
+ *
+ * @return no return.
+ */
+ virtual void UpdateRange();
+
+ private:
+ CRegisteredString m_Name; ///< buffer name
+ TRenderConstantBufferEntryMap
+ m_ConstantBufferEntryMap; ///< holds the entries of a constant buffer
+ QT3DSU32 m_CurrentOffset; ///< holds the current offset
+ QT3DSU32 m_CurrentSize; ///< holds the current size
+ bool m_HWBufferInitialized; ///< true if the hardware version of the buffer is initialized
+ bool m_Dirty; ///< true if buffer is dirty
+ QT3DSU32 m_RangeStart; ///< start offset of the range to update
+ QT3DSU32 m_RangeEnd; ///< size of the range to update
+ QT3DSI32 m_MaxBlockSize; ///< maximum size for a single constant buffer
+ NVDataRef<QT3DSU8> m_ShadowCopy; ///< host copy of the data in the GPU
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h
new file mode 100644
index 00000000..34b2eb73
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderContext.h
@@ -0,0 +1,1045 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_CONTEXT_H
+#define QT3DS_RENDER_CONTEXT_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "render/glg/Qt3DSGLImplObjects.h"
+#include "render/backends/gl/Qt3DSRenderBackendGL3.h"
+#include "render/backends/gl/Qt3DSRenderBackendGL4.h"
+#include "render/backends/software/Qt3DSRenderBackendNULL.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "render/Qt3DSRenderConstantBuffer.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "render/Qt3DSRenderDepthStencilState.h"
+#include "render/Qt3DSRenderRasterizerState.h"
+#include "render/Qt3DSRenderDrawable.h"
+#include "render/Qt3DSRenderInputAssembler.h"
+#include "render/Qt3DSRenderAttribLayout.h"
+#include "render/Qt3DSRenderImageTexture.h"
+#include "render/Qt3DSRenderOcclusionQuery.h"
+#include "render/Qt3DSRenderTimerQuery.h"
+#include "render/Qt3DSRenderSync.h"
+#include "render/Qt3DSRenderTexture2DArray.h"
+#include "render/Qt3DSRenderTextureCube.h"
+#include "render/Qt3DSRenderStorageBuffer.h"
+#include "render/Qt3DSRenderAtomicCounterBuffer.h"
+#include "render/Qt3DSRenderDrawIndirectBuffer.h"
+#include "render/Qt3DSRenderProgramPipeline.h"
+#include "render/Qt3DSRenderPathRender.h"
+#include "render/Qt3DSRenderPathSpecification.h"
+#include "render/Qt3DSRenderPathFontSpecification.h"
+#include "render/Qt3DSRenderPathFontText.h"
+
+#include <QSurfaceFormat>
+
+// When SW fallback is defined we can support (some) object/layer advanced blend modes. If defined,
+// the HW implementation is still preperred if available through extensions. SW fallback can't be
+// used in custom shaders.
+#define ADVANCED_BLEND_SW_FALLBACK
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ struct NVRenderShaderProgramBinaryType
+ {
+ enum Enum {
+ Unknown = 0,
+ NVBinary = 1,
+ };
+ };
+
+ // context dirty flags
+ struct NVRenderContextDirtyValues
+ {
+ enum Enum {
+ InputAssembler = 1 << 0,
+ };
+ };
+
+ typedef NVFlags<NVRenderContextDirtyValues::Enum, QT3DSU32> NVRenderContextDirtyFlags;
+ typedef nvhash_map<CRegisteredString, NVRenderConstantBuffer *> TContextConstantBufferMap;
+ typedef nvhash_map<CRegisteredString, NVRenderStorageBuffer *> TContextStorageBufferMap;
+ typedef nvhash_map<CRegisteredString, NVRenderAtomicCounterBuffer *>
+ TContextAtomicCounterBufferMap;
+ typedef nvhash_map<NVRenderBackend::NVRenderBackendBufferObject, NVRenderDrawIndirectBuffer *>
+ TContextDrawIndirectBufferMap;
+ typedef nvhash_map<NVRenderBackend::NVRenderBackendDepthStencilStateObject,
+ NVRenderDepthStencilState *>
+ TContextDepthStencilStateMap;
+ typedef nvhash_map<NVRenderBackend::NVRenderBackendRasterizerStateObject,
+ NVRenderRasterizerState *>
+ TContextRasterizerStateMap;
+ typedef nvhash_map<NVRenderBackend::NVRenderBackendTextureObject, NVRenderTexture2DArray *>
+ TContextTex2DArrayToImpMap;
+ typedef nvhash_map<NVRenderBackend::NVRenderBackendTextureObject, NVRenderTextureCube *>
+ TContextTexCubeToImpMap;
+ typedef nvhash_map<NVRenderBackend::NVRenderBackendTextureObject, NVRenderImage2D *>
+ TContextImage2DToImpMap;
+ typedef nvhash_map<CRegisteredString, NVRenderPathFontSpecification *>
+ TContextPathFontSpecificationMap;
+
+ class NVRenderContext : public NVRefCounted, public NVRenderDrawable
+ {
+ public:
+ virtual NVRenderContextType GetRenderContextType() const = 0;
+ virtual bool AreMultisampleTexturesSupported() const = 0;
+ virtual bool GetConstantBufferSupport() const = 0;
+ virtual void getMaxTextureSize(QT3DSU32 &oWidth, QT3DSU32 &oHeight) = 0;
+ virtual const char *GetShadingLanguageVersion() = 0;
+ // Get the bit depth of the currently bound depth buffer.
+ virtual QT3DSU32 GetDepthBits() const = 0;
+ virtual QT3DSU32 GetStencilBits() const = 0;
+ virtual bool
+ GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::Enum inCap) const = 0;
+ virtual bool AreDXTImagesSupported() const = 0;
+ virtual bool IsDepthStencilSupported() const = 0;
+ virtual bool IsFpRenderTargetSupported() const = 0;
+ virtual bool IsTessellationSupported() const = 0;
+ virtual bool IsGeometryStageSupported() const = 0;
+ virtual bool IsComputeSupported() const = 0;
+ virtual bool IsSampleQuerySupported() const = 0;
+ virtual bool IsTimerQuerySupported() const = 0;
+ virtual bool IsCommandSyncSupported() const = 0;
+ virtual bool IsTextureArraySupported() const = 0;
+ virtual bool IsStorageBufferSupported() const = 0;
+ virtual bool IsAtomicCounterBufferSupported() const = 0;
+ virtual bool IsShaderImageLoadStoreSupported() const = 0;
+ virtual bool IsProgramPipelineSupported() const = 0;
+ virtual bool IsPathRenderingSupported() const = 0;
+ virtual bool IsBlendCoherencySupported() const = 0;
+ virtual bool IsAdvancedBlendHwSupported() const = 0;
+ virtual bool IsAdvancedBlendHwSupportedKHR() const = 0;
+
+ virtual void SetDefaultRenderTarget(QT3DSU64 targetID) = 0;
+ virtual void SetDefaultDepthBufferBitCount(QT3DSI32 depthBits) = 0;
+
+ virtual NVRenderDepthStencilState *
+ CreateDepthStencilState(bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc,
+ bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack) = 0;
+
+ virtual NVRenderRasterizerState *CreateRasterizerState(QT3DSF32 depthBias, QT3DSF32 depthScale,
+ NVRenderFaces::Enum cullFace) = 0;
+
+ virtual NVRenderVertexBuffer *
+ CreateVertexBuffer(NVRenderBufferUsageType::Enum usageType, size_t size, QT3DSU32 stride = 0,
+ NVConstDataRef<QT3DSU8> bufferData = NVConstDataRef<QT3DSU8>()) = 0;
+ virtual NVRenderVertexBuffer *GetVertexBuffer(const void *implementationHandle) = 0;
+
+ virtual NVRenderIndexBuffer *
+ CreateIndexBuffer(NVRenderBufferUsageType::Enum usageType,
+ NVRenderComponentTypes::Enum componentType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData = NVConstDataRef<QT3DSU8>()) = 0;
+ virtual NVRenderIndexBuffer *GetIndexBuffer(const void *implementationHandle) = 0;
+
+ virtual NVRenderConstantBuffer *
+ CreateConstantBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) = 0;
+ virtual NVRenderConstantBuffer *GetConstantBuffer(CRegisteredString bufferName) = 0;
+
+ virtual NVRenderStorageBuffer *
+ CreateStorageBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData, NVRenderDataBuffer *pBuffer) = 0;
+ virtual NVRenderStorageBuffer *GetStorageBuffer(CRegisteredString bufferName) = 0;
+
+ virtual NVRenderAtomicCounterBuffer *
+ CreateAtomicCounterBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) = 0;
+ virtual NVRenderAtomicCounterBuffer *
+ GetAtomicCounterBuffer(CRegisteredString bufferName) = 0;
+ virtual NVRenderAtomicCounterBuffer *
+ GetAtomicCounterBufferByParam(CRegisteredString paramName) = 0;
+
+ virtual NVRenderDrawIndirectBuffer *
+ CreateDrawIndirectBuffer(qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) = 0;
+ virtual NVRenderDrawIndirectBuffer *GetDrawIndirectBuffer(
+ NVRenderBackend::NVRenderBackendBufferObject implementationHandle) = 0;
+
+ virtual void SetMemoryBarrier(NVRenderBufferBarrierFlags barriers) = 0;
+
+ virtual NVRenderOcclusionQuery *CreateOcclusionQuery() = 0;
+ virtual NVRenderTimerQuery *CreateTimerQuery() = 0;
+ virtual NVRenderSync *CreateSync() = 0;
+
+ virtual NVRenderTexture2D *CreateTexture2D() = 0;
+ virtual NVRenderTexture2D *GetTexture2D(const void *implementationHandle) = 0;
+ virtual NVRenderBackend *GetBackend() = 0;
+
+ virtual NVRenderTexture2DArray *CreateTexture2DArray() = 0;
+
+ virtual NVRenderTextureCube *CreateTextureCube() = 0;
+
+ virtual NVRenderImage2D *CreateImage2D(NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess) = 0;
+
+ virtual NVRenderRenderBuffer *
+ CreateRenderBuffer(NVRenderRenderBufferFormats::Enum bufferFormat, QT3DSU32 width,
+ QT3DSU32 height) = 0;
+ virtual NVRenderRenderBuffer *GetRenderBuffer(const void *implementationHandle) = 0;
+ // Create a new frame buffer and set the current render target to that frame buffer.
+ virtual NVRenderFrameBuffer *CreateFrameBuffer() = 0;
+ virtual NVRenderFrameBuffer *GetFrameBuffer(const void *implementationHandle) = 0;
+
+ virtual NVRenderAttribLayout *
+ CreateAttributeLayout(NVConstDataRef<NVRenderVertexBufferEntry> attribs) = 0;
+
+ virtual NVRenderInputAssembler *
+ CreateInputAssembler(NVRenderAttribLayout *attribLayout,
+ NVConstDataRef<NVRenderVertexBuffer *> buffers,
+ const NVRenderIndexBuffer *indexBuffer, NVConstDataRef<QT3DSU32> strides,
+ NVConstDataRef<QT3DSU32> offsets,
+ NVRenderDrawMode::Enum primType = NVRenderDrawMode::Triangles,
+ QT3DSU32 patchVertexCount = 1) = 0;
+ virtual void SetInputAssembler(NVRenderInputAssembler *inputAssembler) = 0;
+
+ virtual NVRenderVertFragCompilationResult CompileSource(
+ const char *shaderName, NVConstDataRef<QT3DSI8> vertShader,
+ NVConstDataRef<QT3DSI8> fragShader,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource = NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> tessEvaluationShaderSource = NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> geometryShaderSource = NVConstDataRef<QT3DSI8>(),
+ bool separateProgram = false,
+ NVRenderShaderProgramBinaryType::Enum type = NVRenderShaderProgramBinaryType::Unknown,
+ bool binaryProgram = false) = 0;
+
+ // You must figure out inVertLen and inFragLen yourself, this object doesn't do that.
+ NVRenderVertFragCompilationResult
+ CompileSource(const char *shaderName, const char *vertShader, QT3DSU32 inVertLen,
+ const char *fragShader, QT3DSU32 inFragLen, const char * = NULL,
+ QT3DSU32 inTCLen = 0, const char *tessEvaluationShaderSource = NULL,
+ QT3DSU32 inTELen = 0, const char *geometryShaderSource = NULL, QT3DSU32 inGSLen = 0,
+ bool separableProgram = false);
+
+ virtual NVRenderVertFragCompilationResult
+ CompileBinary(const char *shaderName, NVRenderShaderProgramBinaryType::Enum type,
+ NVDataRef<QT3DSI8> vertShader, NVDataRef<QT3DSI8> fragShader,
+ NVDataRef<QT3DSI8> tessControlShaderSource = NVDataRef<QT3DSI8>(),
+ NVDataRef<QT3DSI8> tessEvaluationShaderSource = NVDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> geometryShaderSource = NVConstDataRef<QT3DSI8>()) = 0;
+
+ virtual NVRenderVertFragCompilationResult
+ CompileComputeSource(const char *shaderName, NVConstDataRef<QT3DSI8> computeShaderSource) = 0;
+
+ virtual NVRenderShaderProgram *GetShaderProgram(const void *implementationHandle) = 0;
+
+ virtual NVRenderProgramPipeline *CreateProgramPipeline() = 0;
+
+ virtual NVRenderPathSpecification *CreatePathSpecification() = 0;
+ virtual NVRenderPathRender *CreatePathRender(size_t range = 1) = 0;
+ virtual void SetPathProjectionMatrix(const QT3DSMat44 inPathProjection) = 0;
+ virtual void SetPathModelViewMatrix(const QT3DSMat44 inPathModelview) = 0;
+ virtual void SetPathStencilDepthOffset(QT3DSF32 inSlope, QT3DSF32 inBias) = 0;
+ virtual void SetPathCoverDepthFunc(NVRenderBoolOp::Enum inFunc) = 0;
+
+ virtual NVRenderPathFontSpecification *
+ CreatePathFontSpecification(CRegisteredString fontName) = 0;
+ virtual NVRenderPathFontItem *CreatePathFontItem() = 0;
+
+ // Specific setters for the guaranteed-to-exist context properties to set them as fast as
+ // possible.
+ // Note that this bypasses the property manage so push/pop will have no effect (unless you
+ // set these already
+ // once after a push using the property manager.
+ virtual void SetClearColor(QT3DSVec4 inClearColor) = 0;
+ virtual QT3DSVec4 GetClearColor() const = 0;
+
+ virtual void SetBlendFunction(NVRenderBlendFunctionArgument inFunctions) = 0;
+ virtual NVRenderBlendFunctionArgument GetBlendFunction() const = 0;
+
+ virtual void SetBlendEquation(NVRenderBlendEquationArgument inEquations) = 0;
+ virtual NVRenderBlendEquationArgument GetBlendEquation() const = 0;
+
+ virtual void SetCullingEnabled(bool inEnabled) = 0;
+ virtual bool IsCullingEnabled() const = 0;
+
+ virtual void SetDepthFunction(NVRenderBoolOp::Enum inFunction) = 0;
+ virtual qt3ds::render::NVRenderBoolOp::Enum GetDepthFunction() const = 0;
+
+ virtual void SetBlendingEnabled(bool inEnabled) = 0;
+ virtual bool IsBlendingEnabled() const = 0;
+
+ virtual void SetDepthWriteEnabled(bool inEnabled) = 0;
+ virtual bool IsDepthWriteEnabled() const = 0;
+
+ virtual void SetDepthTestEnabled(bool inEnabled) = 0;
+ virtual bool IsDepthTestEnabled() const = 0;
+
+ virtual void SetDepthStencilState(NVRenderDepthStencilState *inDepthStencilState) = 0;
+ virtual void SetStencilTestEnabled(bool inEnabled) = 0;
+ virtual bool IsStencilTestEnabled() const = 0;
+
+ virtual void SetRasterizerState(NVRenderRasterizerState *inRasterizerState) = 0;
+
+ virtual void SetScissorTestEnabled(bool inEnabled) = 0;
+ virtual bool IsScissorTestEnabled() const = 0;
+
+ virtual void SetScissorRect(NVRenderRect inRect) = 0;
+ virtual NVRenderRect GetScissorRect() const = 0;
+
+ virtual void SetViewport(NVRenderRect inViewport) = 0;
+ virtual NVRenderRect GetViewport() const = 0;
+
+ virtual void SetColorWritesEnabled(bool inEnabled) = 0;
+ virtual bool IsColorWritesEnabled() const = 0;
+
+ virtual void SetMultisampleEnabled(bool inEnabled) = 0;
+ virtual bool IsMultisampleEnabled() const = 0;
+
+ // Used during layer rendering because we can't set the *actual* viewport to what it should
+ // be due to hardware problems.
+ // Set during begin render.
+ static QT3DSMat44
+ ApplyVirtualViewportToProjectionMatrix(const QT3DSMat44 &inProjection,
+ const NVRenderRectF &inViewport,
+ const NVRenderRectF &inVirtualViewport);
+
+ virtual void SetRenderTarget(NVRenderFrameBuffer *inBuffer) = 0;
+ virtual void SetReadTarget(NVRenderFrameBuffer *inBuffer) = 0;
+ virtual NVRenderFrameBuffer *GetRenderTarget() const = 0;
+
+ virtual void SetActiveShader(NVRenderShaderProgram *inShader) = 0;
+ virtual NVRenderShaderProgram *GetActiveShader() const = 0;
+
+ virtual void SetActiveProgramPipeline(NVRenderProgramPipeline *inProgramPipeline) = 0;
+ virtual NVRenderProgramPipeline *GetActiveProgramPipeline() const = 0;
+
+ virtual void DispatchCompute(NVRenderShaderProgram *inShader, QT3DSU32 numGroupsX,
+ QT3DSU32 numGroupsY, QT3DSU32 numGroupsZ) = 0;
+
+ // Push the entire set of properties.
+ virtual void PushPropertySet() = 0;
+ // Pop the entire set of properties, potentially forcing the values
+ // to opengl. Will set the hardware state to whatever at the time of push.
+ virtual void PopPropertySet(bool inForceSetProperties) = 0;
+
+ // Ensure the hardware state matches the state we expect.
+ virtual void ResetBlendState() = 0;
+
+ // Draw buffers are what the system will render to.. Applies to the current render context.
+ //-1 means none, else the integer is assumed to be an index past the draw buffer index.
+ // This applies only to the currently bound framebuffer.
+ virtual void SetDrawBuffers(NVConstDataRef<QT3DSI32> inDrawBufferSet) = 0;
+ virtual void SetReadBuffer(NVReadFaces::Enum inReadFace) = 0;
+
+ virtual void ReadPixels(NVRenderRect inRect, NVRenderReadPixelFormats::Enum inFormat,
+ NVDataRef<QT3DSU8> inWriteBuffer) = 0;
+
+ // Return the property manager for this render context
+ // virtual NVRenderPropertyManager& GetPropertyManager() = 0;
+ // Clear the current render target
+ virtual void Clear(NVRenderClearFlags flags) = 0;
+ // Clear this framebuffer without changing the active frame buffer
+ virtual void Clear(NVRenderFrameBuffer &framebuffer, NVRenderClearFlags flags) = 0;
+ // copy framebuffer content between read target and render target
+ virtual void BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter) = 0;
+
+ // Render, applying these immediate property values just before render. The hardware
+ // properties are tracked for push/pop
+ // but the shader properties are just set on the active shader *after* the hardware
+ // properties have been set. The shader properties are not tracked for push/pop.
+ // This call is meant to come directly before each draw call to setup the last bit of state
+ // before the draw operation. Note that there isn't another way to set the immedate
+ // property values for a given shader because it isn't clear which shader is active
+ // when the properties are getting set.
+ void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset) override = 0;
+
+ /**
+ * @brief Draw the current active vertex buffer using an indirect buffer
+ * This means the setup of the draw call is stored in a buffer bound to
+ * NVRenderBufferBindValues::Draw_Indirect
+ *
+ * @param[in] drawMode Draw mode (Triangles, ....)
+ * @param[in] indirect Offset into a indirect drawing setup buffer
+ *
+ * @return no return.
+ */
+ virtual void DrawIndirect(NVRenderDrawMode::Enum drawMode, QT3DSU32 offset) = 0;
+
+ virtual NVFoundationBase &GetFoundation() = 0;
+ virtual qt3ds::foundation::IStringTable &GetStringTable() = 0;
+ virtual NVAllocatorCallback &GetAllocator() = 0;
+
+ virtual QSurfaceFormat format() const = 0;
+
+ static NVRenderContext &CreateGL(NVFoundationBase &foundation, IStringTable &inStringTable,
+ const QSurfaceFormat &format);
+
+ static NVRenderContext &CreateNULL(NVFoundationBase &foundation,
+ IStringTable &inStringTable);
+ };
+
+ // Now for scoped property access.
+ template <typename TDataType>
+ struct NVRenderContextScopedProperty
+ : public NVRenderGenericScopedProperty<NVRenderContext, TDataType>
+ {
+ typedef typename NVRenderGenericScopedProperty<NVRenderContext, TDataType>::TGetter TGetter;
+ typedef typename NVRenderGenericScopedProperty<NVRenderContext, TDataType>::TSetter TSetter;
+ NVRenderContextScopedProperty(NVRenderContext &ctx, TGetter getter, TSetter setter)
+ : NVRenderGenericScopedProperty<NVRenderContext, TDataType>(ctx, getter, setter)
+ {
+ }
+ NVRenderContextScopedProperty(NVRenderContext &ctx, TGetter getter, TSetter setter,
+ const TDataType &inNewValue)
+ : NVRenderGenericScopedProperty<NVRenderContext, TDataType>(ctx, getter, setter,
+ inNewValue)
+ {
+ }
+ };
+
+/**
+ * A Render Context implementation class
+ *
+ */
+
+#define ITERATE_HARDWARE_CONTEXT_PROPERTIES \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(RenderTarget, FrameBuffer) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(ActiveShader, ActiveShader) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(ActiveProgramPipeline, ActiveProgramPipeline) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(InputAssembler, InputAssembler) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(BlendFunction, BlendFunction) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(CullingEnabled, CullingEnabled) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(DepthFunction, DepthFunction) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(BlendingEnabled, BlendingEnabled) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(DepthWriteEnabled, DepthWriteEnabled) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(DepthTestEnabled, DepthTestEnabled) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(StencilTestEnabled, StencilTestEnabled) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(ScissorTestEnabled, ScissorTestEnabled) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(ScissorRect, ScissorRect) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(Viewport, Viewport) \
+ HANDLE_CONTEXT_HARDWARE_PROPERTY(ClearColor, ClearColor)
+
+ // forward declarations
+
+ class NVRenderContextImpl : public NVRenderContext, public NoCopy
+ {
+ public:
+ // these variables represent the current hardware state of the render context.
+ SNVGLHardPropertyContext m_HardwarePropertyContext;
+
+ private:
+ NVScopedRefCounted<NVRenderBackend> m_backend; ///< pointer to our render backend
+ NVRenderContextDirtyFlags m_DirtyFlags; ///< context dirty flags
+
+ NVRenderBackend::NVRenderBackendRenderTargetObject
+ m_DefaultOffscreenRenderTarget; ///< this is a special target set from outside if we
+ ///never render to a window directly (GL only)
+ QT3DSI32 m_DephBits; ///< this is the depth bits count of the default window render target
+ QT3DSI32 m_StencilBits; ///< this is the stencil bits count of the default window render target
+
+ protected:
+ volatile QT3DSI32 mRefCount;
+ NVFoundationBase &m_Foundation;
+ qt3ds::foundation::IStringTable &m_StringTable;
+
+ nvhash_map<const void *, NVRenderVertexBuffer *> m_VertToImpMap;
+ nvhash_map<const void *, NVRenderIndexBuffer *> m_IndexToImpMap;
+ TContextConstantBufferMap m_ConstantToImpMap;
+ TContextStorageBufferMap m_StorageToImpMap;
+ TContextAtomicCounterBufferMap m_AtomicCounterToImpMap;
+ TContextDrawIndirectBufferMap m_DrawIndirectToImpMap;
+ TContextDepthStencilStateMap m_DepthStencilStateToImpMap;
+ TContextRasterizerStateMap m_RasterizerStateToImpMap;
+ TContextPathFontSpecificationMap m_PathFontSpecToImpMap;
+
+ nvhash_map<const void *, NVRenderTexture2D *> m_Tex2DToImpMap;
+ TContextTex2DArrayToImpMap m_Tex2DArrayToImpMap;
+ TContextTexCubeToImpMap m_TexCubeToImpMap;
+ TContextImage2DToImpMap m_Image2DtoImpMap;
+ nvhash_map<const void *, NVRenderShaderProgram *> m_ShaderToImpMap;
+ nvhash_map<const void *, NVRenderRenderBuffer *> m_RenderBufferToImpMap;
+ nvhash_map<const void *, NVRenderFrameBuffer *> m_FrameBufferToImpMap;
+ QT3DSU32 m_MaxTextureUnits;
+ QT3DSU32 m_NextTextureUnit;
+ QT3DSU32 m_MaxConstantBufferUnits;
+ QT3DSU32 m_NextConstantBufferUnit;
+
+ nvvector<SNVGLHardPropertyContext> m_PropertyStack;
+
+ void DoSetClearColor(QT3DSVec4 inClearColor)
+ {
+ m_HardwarePropertyContext.m_ClearColor = inClearColor;
+ m_backend->SetClearColor(&inClearColor);
+ }
+
+ void DoSetBlendFunction(NVRenderBlendFunctionArgument inFunctions)
+ {
+ QT3DSI32_4 values;
+ m_HardwarePropertyContext.m_BlendFunction = inFunctions;
+
+ m_backend->SetBlendFunc(inFunctions);
+ }
+
+ void DoSetBlendEquation(NVRenderBlendEquationArgument inEquations)
+ {
+ QT3DSI32_4 values;
+ m_HardwarePropertyContext.m_BlendEquation = inEquations;
+
+ m_backend->SetBlendEquation(inEquations);
+ }
+
+ void DoSetCullingEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_CullingEnabled = inEnabled;
+ m_backend->SetRenderState(inEnabled, NVRenderState::CullFace);
+ }
+
+ void DoSetDepthFunction(qt3ds::render::NVRenderBoolOp::Enum inFunction)
+ {
+ m_HardwarePropertyContext.m_DepthFunction = inFunction;
+ m_backend->SetDepthFunc(inFunction);
+ }
+
+ void DoSetBlendingEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_BlendingEnabled = inEnabled;
+ m_backend->SetRenderState(inEnabled, NVRenderState::Blend);
+ }
+
+ void DoSetColorWritesEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_ColorWritesEnabled = inEnabled;
+ m_backend->SetColorWrites(inEnabled, inEnabled, inEnabled, inEnabled);
+ }
+
+ void DoSetMultisampleEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_MultisampleEnabled = inEnabled;
+ m_backend->SetMultisample(inEnabled);
+ }
+
+ void DoSetDepthWriteEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_DepthWriteEnabled = inEnabled;
+ m_backend->SetDepthWrite(inEnabled);
+ }
+
+ void DoSetDepthTestEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_DepthTestEnabled = inEnabled;
+ m_backend->SetRenderState(inEnabled, NVRenderState::DepthTest);
+ }
+
+ void DoSetStencilTestEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_StencilTestEnabled = inEnabled;
+ m_backend->SetRenderState(inEnabled, NVRenderState::StencilTest);
+ }
+
+ void DoSetScissorTestEnabled(bool inEnabled)
+ {
+ m_HardwarePropertyContext.m_ScissorTestEnabled = inEnabled;
+ m_backend->SetRenderState(inEnabled, NVRenderState::ScissorTest);
+ }
+
+ void DoSetScissorRect(NVRenderRect inRect)
+ {
+ m_HardwarePropertyContext.m_ScissorRect = inRect;
+ m_backend->SetScissorRect(inRect);
+ }
+
+ void DoSetViewport(NVRenderRect inViewport)
+ {
+ m_HardwarePropertyContext.m_Viewport = inViewport;
+ m_backend->SetViewportRect(inViewport);
+ }
+
+ // Circular dependencies between shader constants and shader programs preclude
+ // implementation in header
+ void DoSetActiveShader(NVRenderShaderProgram *inShader);
+ void DoSetActiveProgramPipeline(NVRenderProgramPipeline *inProgramPipeline);
+
+ void DoSetInputAssembler(NVRenderInputAssembler *inAssembler)
+ {
+ m_HardwarePropertyContext.m_InputAssembler = inAssembler;
+ m_DirtyFlags |= NVRenderContextDirtyValues::InputAssembler;
+ }
+
+ void DoSetRenderTarget(NVRenderFrameBuffer *inBuffer)
+ {
+ if (inBuffer)
+ m_backend->SetRenderTarget(inBuffer->GetFrameBuffertHandle());
+ else
+ m_backend->SetRenderTarget(m_DefaultOffscreenRenderTarget);
+
+ m_HardwarePropertyContext.m_FrameBuffer = inBuffer;
+ }
+
+ void DoSetReadTarget(NVRenderFrameBuffer *inBuffer)
+ {
+ if (inBuffer)
+ m_backend->SetReadTarget(inBuffer->GetFrameBuffertHandle());
+ else
+ m_backend->SetReadTarget(NVRenderBackend::NVRenderBackendRenderTargetObject(NULL));
+ }
+
+ bool BindShaderToInputAssembler(const NVRenderInputAssembler *inputAssembler,
+ NVRenderShaderProgram *shader);
+ bool ApplyPreDrawProperties();
+ void OnPostDraw();
+
+ public:
+ NVRenderContextImpl(NVFoundationBase &fnd, NVRenderBackend &inBackend,
+ IStringTable &inStrTable);
+ virtual ~NVRenderContextImpl();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation);
+
+ NVRenderBackend *GetBackend() override { return m_backend; }
+
+ void getMaxTextureSize(QT3DSU32 &oWidth, QT3DSU32 &oHeight) override;
+
+ const char *GetShadingLanguageVersion() override
+ {
+ return m_backend->GetShadingLanguageVersion();
+ }
+
+ NVRenderContextType GetRenderContextType() const override
+ {
+ return m_backend->GetRenderContextType();
+ }
+
+ QT3DSU32 GetDepthBits() const override
+ {
+ // only query this if a framebuffer is bound
+ if (m_HardwarePropertyContext.m_FrameBuffer)
+ return m_backend->GetDepthBits();
+ else
+ return m_DephBits;
+ }
+
+ QT3DSU32 GetStencilBits() const override
+ {
+ // only query this if a framebuffer is bound
+ if (m_HardwarePropertyContext.m_FrameBuffer)
+ return m_backend->GetStencilBits();
+ else
+ return m_StencilBits;
+ }
+
+ bool GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::Enum inCap) const override
+ {
+ return m_backend->GetRenderBackendCap(inCap);
+ }
+
+ bool AreMultisampleTexturesSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::MsTexture);
+ }
+
+ bool GetConstantBufferSupport() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::ConstantBuffer);
+ }
+
+ bool AreDXTImagesSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::DxtImages);
+ }
+
+ bool IsDepthStencilSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::DepthStencilTexture);
+ }
+
+ bool IsFpRenderTargetSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::FpRenderTarget);
+ }
+
+ bool IsTessellationSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::Tessellation);
+ }
+
+ bool IsGeometryStageSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::Geometry);
+ }
+
+ bool IsComputeSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::Compute);
+ }
+
+ bool IsSampleQuerySupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::SampleQuery);
+ }
+
+ bool IsTimerQuerySupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::TimerQuery);
+ }
+
+ bool IsCommandSyncSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::CommandSync);
+ }
+ bool IsTextureArraySupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::TextureArray);
+ }
+ bool IsStorageBufferSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::StorageBuffer);
+ }
+ bool IsAtomicCounterBufferSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::AtomicCounterBuffer);
+ }
+ bool IsShaderImageLoadStoreSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::ShaderImageLoadStore);
+ }
+ bool IsProgramPipelineSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::ProgramPipeline);
+ }
+ bool IsPathRenderingSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::PathRendering);
+ }
+ // Are blend modes really supported in HW?
+ bool IsAdvancedBlendHwSupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::AdvancedBlend);
+ }
+ bool IsAdvancedBlendHwSupportedKHR() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::AdvancedBlendKHR);
+ }
+ bool IsBlendCoherencySupported() const override
+ {
+ return GetRenderBackendCap(NVRenderBackend::NVRenderBackendCaps::BlendCoherency);
+ }
+
+ void SetDefaultRenderTarget(QT3DSU64 targetID) override
+ {
+ m_DefaultOffscreenRenderTarget =
+ (NVRenderBackend::NVRenderBackendRenderTargetObject)targetID;
+ }
+
+ void SetDefaultDepthBufferBitCount(QT3DSI32 depthBits) override { m_DephBits = depthBits; }
+
+ virtual NVRenderDepthStencilState *
+ CreateDepthStencilState(bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc,
+ bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack) override;
+ void SetDepthStencilState(NVRenderDepthStencilState *inDepthStencilState) override;
+ virtual void StateDestroyed(NVRenderDepthStencilState &state);
+
+ NVRenderRasterizerState *CreateRasterizerState(QT3DSF32 depthBias, QT3DSF32 depthScale,
+ NVRenderFaces::Enum cullFace) override;
+ void SetRasterizerState(NVRenderRasterizerState *inRasterizerState) override;
+ virtual void StateDestroyed(NVRenderRasterizerState &state);
+
+ NVRenderVertexBuffer *CreateVertexBuffer(NVRenderBufferUsageType::Enum usageType,
+ size_t size, QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> bufferData) override;
+ NVRenderVertexBuffer *GetVertexBuffer(const void *implementationHandle) override;
+ virtual void BufferDestroyed(NVRenderVertexBuffer &buffer);
+
+ virtual NVRenderIndexBuffer *
+ CreateIndexBuffer(qt3ds::render::NVRenderBufferUsageType::Enum usageType,
+ qt3ds::render::NVRenderComponentTypes::Enum componentType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) override;
+ NVRenderIndexBuffer *GetIndexBuffer(const void *implementationHandle) override;
+ virtual void BufferDestroyed(NVRenderIndexBuffer &buffer);
+
+ virtual NVRenderConstantBuffer *
+ CreateConstantBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) override;
+ NVRenderConstantBuffer *GetConstantBuffer(CRegisteredString bufferName) override;
+ virtual void BufferDestroyed(NVRenderConstantBuffer &buffer);
+
+ virtual QT3DSU32 GetNextConstantBufferUnit();
+
+ virtual NVRenderStorageBuffer *
+ CreateStorageBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData, NVRenderDataBuffer *pBuffer) override;
+ NVRenderStorageBuffer *GetStorageBuffer(CRegisteredString bufferName) override;
+ virtual void BufferDestroyed(NVRenderStorageBuffer &buffer);
+
+ virtual NVRenderAtomicCounterBuffer *
+ CreateAtomicCounterBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) override;
+ NVRenderAtomicCounterBuffer *GetAtomicCounterBuffer(CRegisteredString bufferName) override;
+ virtual NVRenderAtomicCounterBuffer *
+ GetAtomicCounterBufferByParam(CRegisteredString paramName) override;
+ virtual void BufferDestroyed(NVRenderAtomicCounterBuffer &buffer);
+
+ virtual NVRenderDrawIndirectBuffer *
+ CreateDrawIndirectBuffer(qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData) override;
+ virtual NVRenderDrawIndirectBuffer *
+ GetDrawIndirectBuffer(NVRenderBackend::NVRenderBackendBufferObject implementationHandle) override;
+ virtual void BufferDestroyed(NVRenderDrawIndirectBuffer &buffer);
+
+ void SetMemoryBarrier(NVRenderBufferBarrierFlags barriers) override;
+
+ NVRenderOcclusionQuery *CreateOcclusionQuery() override;
+ NVRenderTimerQuery *CreateTimerQuery() override;
+ NVRenderSync *CreateSync() override;
+
+ NVRenderTexture2D *CreateTexture2D() override;
+ NVRenderTexture2D *GetTexture2D(const void *implementationHandle) override;
+ virtual void TextureDestroyed(NVRenderTexture2D &buffer);
+
+ NVRenderTexture2DArray *CreateTexture2DArray() override;
+ virtual void TextureDestroyed(NVRenderTexture2DArray &buffer);
+
+ NVRenderTextureCube *CreateTextureCube() override;
+ virtual void TextureDestroyed(NVRenderTextureCube &buffer);
+
+ virtual QT3DSU32 GetNextTextureUnit();
+
+ NVRenderImage2D *CreateImage2D(NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess) override;
+ virtual void ImageDestroyed(NVRenderImage2D &buffer);
+
+ virtual NVRenderRenderBuffer *
+ CreateRenderBuffer(NVRenderRenderBufferFormats::Enum bufferFormat, QT3DSU32 width,
+ QT3DSU32 height) override;
+ NVRenderRenderBuffer *GetRenderBuffer(const void *implementationHandle) override;
+ virtual void RenderBufferDestroyed(NVRenderRenderBuffer &buffer);
+
+ NVRenderFrameBuffer *CreateFrameBuffer() override;
+ NVRenderFrameBuffer *GetFrameBuffer(const void *implementationHandle) override;
+ virtual void FrameBufferDestroyed(NVRenderFrameBuffer &fb);
+
+ virtual NVRenderAttribLayout *
+ CreateAttributeLayout(NVConstDataRef<NVRenderVertexBufferEntry> attribs) override;
+ NVRenderInputAssembler *CreateInputAssembler(
+ NVRenderAttribLayout *attribLayout, NVConstDataRef<NVRenderVertexBuffer *> buffers,
+ const NVRenderIndexBuffer *indexBuffer, NVConstDataRef<QT3DSU32> strides,
+ NVConstDataRef<QT3DSU32> offsets, NVRenderDrawMode::Enum primType, QT3DSU32 patchVertexCount) override;
+ void SetInputAssembler(NVRenderInputAssembler *inputAssembler) override;
+
+ NVRenderVertFragCompilationResult CompileSource(
+ const char *shaderName, NVConstDataRef<QT3DSI8> vertShader,
+ NVConstDataRef<QT3DSI8> fragShader,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource = NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> tessEvaluationShaderSource = NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> geometryShaderSource = NVConstDataRef<QT3DSI8>(),
+ bool separateProgram = false,
+ NVRenderShaderProgramBinaryType::Enum type = NVRenderShaderProgramBinaryType::Unknown,
+ bool binaryProgram = false) override;
+
+ virtual NVRenderVertFragCompilationResult
+ CompileBinary(const char *shaderName, NVRenderShaderProgramBinaryType::Enum type,
+ NVDataRef<QT3DSI8> vertShader, NVDataRef<QT3DSI8> fragShader,
+ NVDataRef<QT3DSI8> tessControlShaderSource = NVDataRef<QT3DSI8>(),
+ NVDataRef<QT3DSI8> tessEvaluationShaderSource = NVDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> geometryShaderSource = NVConstDataRef<QT3DSI8>()) override;
+
+ virtual NVRenderVertFragCompilationResult
+ CompileComputeSource(const char *shaderName, NVConstDataRef<QT3DSI8> computeShaderSource) override;
+
+ NVRenderShaderProgram *GetShaderProgram(const void *implementationHandle) override;
+ virtual void ShaderDestroyed(NVRenderShaderProgram &shader);
+
+ NVRenderProgramPipeline *CreateProgramPipeline() override;
+ NVRenderPathSpecification *CreatePathSpecification() override;
+ NVRenderPathRender *CreatePathRender(size_t range = 1) override;
+ void SetPathProjectionMatrix(const QT3DSMat44 inPathProjection) override;
+ void SetPathModelViewMatrix(const QT3DSMat44 inPathModelview) override;
+ void SetPathStencilDepthOffset(QT3DSF32 inSlope, QT3DSF32 inBias) override;
+ void SetPathCoverDepthFunc(NVRenderBoolOp::Enum inFunc) override;
+
+ virtual NVRenderPathFontSpecification *
+ CreatePathFontSpecification(CRegisteredString fontName) override;
+ virtual void ReleasePathFontSpecification(NVRenderPathFontSpecification &inPathSpec);
+ NVRenderPathFontItem *CreatePathFontItem() override;
+
+ void SetClearColor(QT3DSVec4 inClearColor) override;
+ QT3DSVec4 GetClearColor() const override { return m_HardwarePropertyContext.m_ClearColor; }
+
+ void SetBlendFunction(NVRenderBlendFunctionArgument inFunctions) override;
+ NVRenderBlendFunctionArgument GetBlendFunction() const override
+ {
+ return m_HardwarePropertyContext.m_BlendFunction;
+ }
+
+ void SetBlendEquation(NVRenderBlendEquationArgument inEquations) override;
+ NVRenderBlendEquationArgument GetBlendEquation() const override
+ {
+ return m_HardwarePropertyContext.m_BlendEquation;
+ };
+
+ void SetCullingEnabled(bool inEnabled) override;
+ bool IsCullingEnabled() const override { return m_HardwarePropertyContext.m_CullingEnabled; }
+
+ void SetDepthFunction(qt3ds::render::NVRenderBoolOp::Enum inFunction) override;
+ qt3ds::render::NVRenderBoolOp::Enum GetDepthFunction() const override
+ {
+ return m_HardwarePropertyContext.m_DepthFunction;
+ }
+
+ void SetBlendingEnabled(bool inEnabled) override;
+ bool IsBlendingEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_BlendingEnabled;
+ }
+
+ void SetDepthWriteEnabled(bool inEnabled) override;
+ bool IsDepthWriteEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_DepthWriteEnabled;
+ }
+ void SetDepthTestEnabled(bool inEnabled) override;
+ bool IsDepthTestEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_DepthTestEnabled;
+ }
+
+ void SetStencilTestEnabled(bool inEnabled) override;
+ bool IsStencilTestEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_StencilTestEnabled;
+ }
+
+ void SetScissorTestEnabled(bool inEnabled) override;
+ bool IsScissorTestEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_ScissorTestEnabled;
+ }
+ void SetScissorRect(NVRenderRect inRect) override;
+ NVRenderRect GetScissorRect() const override
+ {
+ return m_HardwarePropertyContext.m_ScissorRect;
+ }
+
+ void SetViewport(NVRenderRect inViewport) override;
+ NVRenderRect GetViewport() const override { return m_HardwarePropertyContext.m_Viewport; }
+
+ void SetColorWritesEnabled(bool inEnabled) override;
+ bool IsColorWritesEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_ColorWritesEnabled;
+ }
+
+ void SetMultisampleEnabled(bool inEnabled) override;
+ bool IsMultisampleEnabled() const override
+ {
+ return m_HardwarePropertyContext.m_MultisampleEnabled;
+ }
+
+ void SetActiveShader(NVRenderShaderProgram *inShader) override;
+ NVRenderShaderProgram *GetActiveShader() const override
+ {
+ return m_HardwarePropertyContext.m_ActiveShader;
+ }
+
+ void SetActiveProgramPipeline(NVRenderProgramPipeline *inProgramPipeline) override;
+ NVRenderProgramPipeline *GetActiveProgramPipeline() const override
+ {
+ return m_HardwarePropertyContext.m_ActiveProgramPipeline;
+ }
+
+ void DispatchCompute(NVRenderShaderProgram *inShader, QT3DSU32 numGroupsX,
+ QT3DSU32 numGroupsY, QT3DSU32 numGroupsZ) override;
+
+ void SetDrawBuffers(NVConstDataRef<QT3DSI32> inDrawBufferSet) override;
+ void SetReadBuffer(NVReadFaces::Enum inReadFace) override;
+
+ void ReadPixels(NVRenderRect inRect, NVRenderReadPixelFormats::Enum inFormat,
+ NVDataRef<QT3DSU8> inWriteBuffer) override;
+
+ void SetRenderTarget(NVRenderFrameBuffer *inBuffer) override;
+ void SetReadTarget(NVRenderFrameBuffer *inBuffer) override;
+ NVRenderFrameBuffer *GetRenderTarget() const override
+ {
+ return m_HardwarePropertyContext.m_FrameBuffer;
+ }
+
+ void ResetBlendState() override;
+
+ // Push the entire set of properties.
+ void PushPropertySet() override { m_PropertyStack.push_back(m_HardwarePropertyContext); }
+
+ // Pop the entire set of properties, potentially forcing the values
+ // to opengl.
+ void PopPropertySet(bool inForceSetProperties) override;
+
+ // clear current bound render target
+ void Clear(NVRenderClearFlags flags) override;
+ // clear passed in rendertarget
+ void Clear(NVRenderFrameBuffer &fb, NVRenderClearFlags flags) override;
+
+ // copy framebuffer content between read target and render target
+ void BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter) override;
+
+ void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset) override;
+ void DrawIndirect(NVRenderDrawMode::Enum drawMode, QT3DSU32 offset) override;
+
+ NVFoundationBase &GetFoundation() override { return m_Foundation; }
+ qt3ds::foundation::IStringTable &GetStringTable() override { return m_StringTable; }
+ NVAllocatorCallback &GetAllocator() override { return m_Foundation.getAllocator(); }
+ QSurfaceFormat format() const override
+ {
+ return m_backend->format();
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDataBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDataBuffer.h
new file mode 100644
index 00000000..579e2361
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDataBuffer.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_DATA_BUFFER_H
+#define QT3DS_RENDER_DATA_BUFFER_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+ class NVRenderBackend;
+
+ ///< Base class
+ class NVRenderDataBuffer : public NVRefCounted, public NVRenderImplemented
+ {
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBufferUsageType::Enum m_UsageType; ///< usage type
+ NVRenderBufferBindFlags m_BindFlags; ///< bind flags
+ NVDataRef<QT3DSU8> m_BufferData; ///< buffer data pointer
+ QT3DSU32 m_BufferCapacity; ///< size of internal backup buffer (m_BufferData)
+ size_t m_BufferSize; ///< size of buffer
+ bool m_OwnsData; ///< true when we own m_BufferData
+ bool m_Mapped; ///< true when locked for reading or writing to m_BufferData
+ NVRenderBackend::NVRenderBackendBufferObject m_BufferHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] bindFlags Where to binf this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ *application.
+ *
+ * @return No return.
+ */
+ NVRenderDataBuffer(NVRenderContextImpl &context, NVFoundationBase &fnd, size_t size,
+ NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usageType, NVDataRef<QT3DSU8> data);
+
+ virtual ~NVRenderDataBuffer();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ /**
+ * @brief Get Buffer usage type
+ *
+ * @return Return usage tyoe
+ */
+ virtual NVRenderBufferUsageType::Enum GetBufferUsageType() const
+ {
+ return m_UsageType;
+ }
+
+ /**
+ * @brief Get Buffer usage type
+ * Should be overwritten
+ *
+ * @return Return usage tyoe
+ */
+ virtual NVRenderBufferBindFlags GetBufferBindings() const { return m_BindFlags; }
+
+ /**
+ * @brief Return buffer size in byte
+ *
+ * @return Return size
+ */
+ virtual QT3DSU32 Size() { return (QT3DSU32)m_BufferSize; }
+
+ /**
+ * @brief Get a pointer to the foundation
+ *
+ * @return pointer to foundation
+ */
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ virtual void Bind() = 0;
+
+ /**
+ * @brief Map the buffer
+ * Mapped buffers cannot be used for rendering
+ *
+ * @return Return mapped pointer to data
+ */
+ virtual NVDataRef<QT3DSU8> MapBuffer();
+
+ /**
+ * @brief Map a range of a buffer
+ * Mapped buffers cannot be used for rendering
+ *
+ * @param[in] offset Offset in bytes into the buffer
+ * @param[in] size Range in bytes to map
+ * @param[in] flags Buffer access flags
+ *
+ * @return Return mapped pointer to data
+ */
+ virtual NVDataRef<QT3DSU8> MapBufferRange(size_t offset, size_t size,
+ NVRenderBufferAccessFlags flags);
+
+ /**
+ * @brief Unmap the buffer
+ * This updates the data to the hardware
+ *
+ * @return no return
+ */
+ virtual void UnmapBuffer();
+
+ /**
+ * @brief constructor
+ *
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ * @param[in] ownsMemory If true data will be owned by this object and can therefore be
+ * released
+ *
+ * @return No return.
+ */
+ virtual void UpdateBuffer(NVConstDataRef<QT3DSU8> data, bool ownsMemory = false);
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const = 0;
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override = 0;
+
+ private:
+ void releaseMemory();
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDepthStencilState.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDepthStencilState.h
new file mode 100644
index 00000000..e6b31981
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDepthStencilState.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_DEPTH_STENCIL_STATE_H
+#define QT3DS_RENDER_DEPTH_STENCIL_STATE_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+
+ // currently this handles only stencil state
+ class NVRenderDepthStencilState : public NVRefCounted
+ {
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBackend::NVRenderBackendDepthStencilStateObject
+ m_StateHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] enableDepth enable depth test
+ * @param[in] depthMask enable depth writes
+ * @param[in] depthFunc depth compare function
+ * @param[in] enableStencil enable stencil test
+ * @param[in] stencilFuncFront stencil setup front faces
+ * @param[in] stencilFuncBack stencil setup back faces
+ * @param[in] depthStencilOpFront depth/stencil operations front faces
+ * @param[in] depthStencilOpBack depth/stencil operations back faces
+ *
+ * @return No return.
+ */
+ NVRenderDepthStencilState(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc,
+ bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack);
+
+ virtual ~NVRenderDepthStencilState();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ ///< various get functions
+ const NVRenderStencilFunctionArgument GetStencilFunc(NVRenderFaces::Enum face) const
+ {
+ return (face == NVRenderFaces::Back) ? m_StencilFuncBack : m_StencilFuncFront;
+ }
+ const NVRenderStencilOperationArgument GetStencilOp(NVRenderFaces::Enum face) const
+ {
+ return (face == NVRenderFaces::Back) ? m_DepthStencilOpBack : m_DepthStencilOpFront;
+ }
+ NVRenderBoolOp::Enum GetDepthFunc() const { return m_DepthFunc; }
+ bool GetDepthEnabled() const { return m_DepthEnabled; }
+ bool GetStencilEnabled() const { return m_StencilEnabled; }
+ bool GetDepthMask() const { return m_DepthMask; }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendDepthStencilStateObject
+ GetDepthStencilObjectHandle()
+ {
+ return m_StateHandle;
+ }
+
+ static NVRenderDepthStencilState *
+ Create(NVRenderContextImpl &context, bool enableDepth, bool depthMask,
+ NVRenderBoolOp::Enum depthFunc, bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack);
+
+ private:
+ bool m_DepthEnabled; ///< depth test enabled
+ bool m_DepthMask; ///< depth writes enabled
+ NVRenderBoolOp::Enum m_DepthFunc; ///< depth comparison func
+ bool m_StencilEnabled; ///< stencil test enabled
+ NVRenderStencilFunctionArgument m_StencilFuncFront; ///< stencil setup front faces
+ NVRenderStencilFunctionArgument m_StencilFuncBack; ///< stencil setup back faces
+ NVRenderStencilOperationArgument
+ m_DepthStencilOpFront; ///< depth stencil operation front faces
+ NVRenderStencilOperationArgument
+ m_DepthStencilOpBack; ///< depth stencil operation back faces
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawIndirectBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawIndirectBuffer.h
new file mode 100644
index 00000000..81cd59d1
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawIndirectBuffer.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_DRAW_INDIRECT_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_DRAW_INDIRECT_BUFFER_H
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Utils.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderDataBuffer.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ // forward declaration
+ class NVRenderContextImpl;
+
+ struct DrawArraysIndirectCommand
+ {
+ QT3DSU32 count;
+ QT3DSU32 primCount;
+ QT3DSU32 first;
+ QT3DSU32 baseInstance;
+ };
+
+ struct DrawElementsIndirectCommand
+ {
+ QT3DSU32 count;
+ QT3DSU32 primCount;
+ QT3DSU32 firstIndex;
+ QT3DSU32 baseVertex;
+ QT3DSU32 baseInstance;
+ };
+
+ ///< Constant (uniform) buffer representation
+ class NVRenderDrawIndirectBuffer : public NVRenderDataBuffer
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return.
+ */
+ NVRenderDrawIndirectBuffer(NVRenderContextImpl &context, size_t size,
+ NVRenderBufferUsageType::Enum usageType, NVDataRef<QT3DSU8> data);
+
+ ///< destructor
+ virtual ~NVRenderDrawIndirectBuffer();
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief update the buffer to hardware
+ *
+ * @return no return.
+ */
+ virtual void Update();
+
+ /**
+ * @brief update a piece of memory directly within the storage buffer
+ *
+ * Note: When you use this function you should know what you are doing.
+ * The memory layout within C++ must exactly match the memory layout in the
+ *shader.
+ * We use std140 (430) layout which guarantees a specific layout behavior across
+ *all HW vendors.
+ * How the memory layout is computed can be found in the GL spec.
+ *
+ * @param[in] offset offset into storage buffer
+ * @param[in] data pointer to data
+ *
+ * @return no return
+ */
+ void UpdateData(QT3DSI32 offset, NVDataRef<QT3DSU8> data);
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const override
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+
+ /**
+ * @brief create a NVRenderDrawIndirectBuffer object
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return the buffer object or NULL
+ */
+ static NVRenderDrawIndirectBuffer *Create(NVRenderContextImpl &context,
+ NVRenderBufferUsageType::Enum usageType,
+ size_t size, NVConstDataRef<QT3DSU8> bufferData);
+
+ private:
+ bool m_Dirty; ///< true if buffer is dirty
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawable.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawable.h
new file mode 100644
index 00000000..0f78aacc
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderDrawable.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_DRAWABLE_H
+#define QT3DS_RENDER_QT3DS_RENDER_DRAWABLE_H
+#include "Qt3DSRenderBaseTypes.h"
+
+namespace qt3ds {
+namespace render {
+ class NVRenderDrawable
+ {
+ protected:
+ virtual ~NVRenderDrawable() {}
+
+ public:
+ /**
+ * Draw using this object.
+ * offset is in num elements, not in number of bytes
+ * because the various different draw functions differ in what datatype
+ * offset is (gl drawarrays vs gl drawindexedarras).
+ */
+ virtual void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset) = 0;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFragmentShader.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFragmentShader.h
new file mode 100644
index 00000000..f661605c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFragmentShader.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_FRAGMENT_SHADER_H
+#define QT3DS_RENDER_FRAGMENT_SHADER_H
+
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderShader.h"
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ ///< This class represents a fragment shader
+ class NVRenderFragmentShader : public NVRenderShader
+ {
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] source Pointer to shader source code
+ * @param[in] binaryProgram true if this is a binary program
+ *
+ * @return No return.
+ */
+ NVRenderFragmentShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram);
+
+ /// @brief destructor
+ ~NVRenderFragmentShader();
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ bool IsValid() override { return (m_ShaderHandle != NULL); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendFragmentShaderObject GetShaderHandle()
+ {
+ return m_ShaderHandle;
+ }
+
+ private:
+ NVRenderBackend::NVRenderBackendFragmentShaderObject
+ m_ShaderHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFrameBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFrameBuffer.h
new file mode 100644
index 00000000..1882a27d
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderFrameBuffer.h
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_FRAME_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_FRAME_BUFFER_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+ class NVRenderTexture2D;
+ class NVRenderRenderBuffer;
+ class NVRenderTexture2DArray;
+ class NVRenderTextureCube;
+
+ class NVRenderTextureOrRenderBuffer
+ {
+ NVRenderTexture2D *m_Texture2D;
+ NVRenderTexture2DArray *m_Texture2DArray;
+ NVRenderTextureCube *m_TextureCube;
+ NVRenderRenderBuffer *m_RenderBuffer;
+
+ public:
+ NVRenderTextureOrRenderBuffer(NVRenderTexture2D &texture)
+ : m_Texture2D(&texture)
+ , m_Texture2DArray(NULL)
+ , m_TextureCube(NULL)
+ , m_RenderBuffer(NULL)
+ {
+ }
+ NVRenderTextureOrRenderBuffer(NVRenderRenderBuffer &render)
+ : m_Texture2D(NULL)
+ , m_Texture2DArray(NULL)
+ , m_TextureCube(NULL)
+ , m_RenderBuffer(&render)
+ {
+ }
+ NVRenderTextureOrRenderBuffer(NVRenderTexture2DArray &textureArray)
+ : m_Texture2D(NULL)
+ , m_Texture2DArray(&textureArray)
+ , m_TextureCube(NULL)
+ , m_RenderBuffer(NULL)
+ {
+ }
+ NVRenderTextureOrRenderBuffer(NVRenderTextureCube &textureCube)
+ : m_Texture2D(NULL)
+ , m_Texture2DArray(NULL)
+ , m_TextureCube(&textureCube)
+ , m_RenderBuffer(NULL)
+ {
+ }
+ NVRenderTextureOrRenderBuffer()
+ : m_Texture2D(NULL)
+ , m_Texture2DArray(NULL)
+ , m_TextureCube(NULL)
+ , m_RenderBuffer(NULL)
+ {
+ }
+ NVRenderTextureOrRenderBuffer(const NVRenderTextureOrRenderBuffer &other)
+ : m_Texture2D(other.m_Texture2D)
+ , m_Texture2DArray(other.m_Texture2DArray)
+ , m_TextureCube(other.m_TextureCube)
+ , m_RenderBuffer(other.m_RenderBuffer)
+ {
+ }
+ NVRenderTextureOrRenderBuffer &operator=(const NVRenderTextureOrRenderBuffer &other)
+ {
+ if (this != &other) {
+ m_Texture2D = const_cast<NVRenderTexture2D *>(other.m_Texture2D);
+ m_Texture2DArray = const_cast<NVRenderTexture2DArray *>(other.m_Texture2DArray);
+ m_RenderBuffer = const_cast<NVRenderRenderBuffer *>(other.m_RenderBuffer);
+ m_TextureCube = const_cast<NVRenderTextureCube *>(other.m_TextureCube);
+ }
+ return *this;
+ }
+
+ bool HasTexture2D() const { return m_Texture2D != NULL; }
+ bool HasTexture2DArray() const { return m_Texture2DArray != NULL; }
+ bool HasTextureCube() const { return m_TextureCube != NULL; }
+ bool HasRenderBuffer() const { return m_RenderBuffer != NULL; }
+
+ NVRenderTexture2D *GetTexture2D() const
+ {
+ QT3DS_ASSERT(HasTexture2D());
+ return m_Texture2D;
+ }
+ NVRenderTexture2DArray *GetTexture2DArray() const
+ {
+ QT3DS_ASSERT(HasTexture2DArray());
+ return m_Texture2DArray;
+ }
+ NVRenderTextureCube *GetTextureCube() const
+ {
+ QT3DS_ASSERT(HasTextureCube());
+ return m_TextureCube;
+ }
+ NVRenderRenderBuffer *GetRenderBuffer() const
+ {
+ QT3DS_ASSERT(HasRenderBuffer());
+ return m_RenderBuffer;
+ }
+ };
+
+ class NVRenderFrameBuffer : public NVRefCounted, public NVRenderImplemented
+ {
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+
+ NVRenderTextureOrRenderBuffer
+ m_Attachments[NVRenderFrameBufferAttachments::LastAttachment]; ///< attachments array
+ NVRenderBackend::NVRenderBackendRenderTargetObject
+ m_BufferHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderFrameBuffer(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ /// destructor
+ virtual ~NVRenderFrameBuffer();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ /**
+ * @brief query attachment
+ *
+ *
+ * @return buffer format
+ */
+ virtual NVRenderTextureOrRenderBuffer
+ GetAttachment(NVRenderFrameBufferAttachments::Enum attachment);
+
+ /**
+ * @brief Attach a render or texture buffer to a render target
+ * For texture attachments we use always level 0
+ *
+ * @param[in] attachment Attachment point (e.g. COLOR0, DEPTH...)
+ * @param[in] buffer Contains a pointer to the attachment
+ * @param[in] target Attachment texture target
+ *
+ * @return no return
+ */
+ virtual void
+ Attach(NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderTextureOrRenderBuffer buffer,
+ NVRenderTextureTargetType::Enum target = NVRenderTextureTargetType::Texture2D);
+
+ /**
+ * @brief Attach a particular layer of the texture 2D array to a render target
+ *
+ * @param[in] attachment Attachment point (e.g. COLOR0, DEPTH...)
+ * @param[in] buffer Pointer to the Texture Array which contains the
+ * layers
+ * @param[in] layer The index to the layer that will be attached to the
+ * target
+ * @param[in] level Mip level of the texture that will be attached
+ * (default 0)
+ *
+ * @return no return
+ */
+ virtual void AttachLayer(NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderTextureOrRenderBuffer buffer, QT3DSI32 layer,
+ QT3DSI32 level = 0);
+
+ /**
+ * @brief Attach a particular face of the texture cubemap to a render target
+ *
+ * @param[in] attachment Attachment point (e.g. COLOR0, DEPTH...)
+ * @param[in] buffer Pointer to the Texture Array which contains the
+ * layers
+ * @param[in] face The face of the cubemap that will be attached to the
+ * target
+ * @param[in] level Mip level of the texture that will be attached
+ * (default 0)
+ *
+ * @return no return
+ */
+ virtual void AttachFace(NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderTextureOrRenderBuffer buffer,
+ NVRenderTextureCubeFaces::Enum face);
+
+ /**
+ * @brief Check that this framebuffer is complete and can be rendered to.
+ *
+ *
+ * @return true if complete
+ */
+ virtual bool IsComplete();
+
+ /**
+ * @brief query if framebuffer has any attachment
+ *
+ * @return true if any attachment
+ */
+ virtual bool HasAnyAttachment() { return (m_AttachmentBits != 0); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendRenderTargetObject GetFrameBuffertHandle()
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<const void *>(m_BufferHandle);
+ }
+
+ /**
+ * @brief static creator function
+ *
+ * @param[in] context Pointer to context
+ *
+ * @return a pointer to framebuffer object.
+ */
+ static NVRenderFrameBuffer *Create(NVRenderContextImpl &context);
+
+ private:
+ /**
+ * @brief releaes an attached object
+ *
+ * @return which target we released
+ */
+ NVRenderTextureTargetType::Enum releaseAttachment(NVRenderFrameBufferAttachments::Enum idx);
+
+ QT3DSU32 m_AttachmentBits; ///< holds flags for current attached buffers
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderGeometryShader.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderGeometryShader.h
new file mode 100644
index 00000000..2a643cfc
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderGeometryShader.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_GEOMETRY_SHADER_H
+#define QT3DS_RENDER_GEOMETRY_SHADER_H
+
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderShader.h"
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ ///< This class represents a vertex shader
+ class NVRenderGeometryShader : public NVRenderShader
+ {
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] source Pointer to shader source code
+ * @param[in] binaryProgram true if this is a binary program
+ *
+ * @return No return.
+ */
+ NVRenderGeometryShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram);
+
+ /// @brief destructor
+ ~NVRenderGeometryShader();
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ bool IsValid() override { return (m_ShaderHandle != NULL); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendGeometryShaderObject GetShaderHandle()
+ {
+ return m_ShaderHandle;
+ }
+
+ private:
+ NVRenderBackend::NVRenderBackendGeometryShaderObject
+ m_ShaderHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderImageTexture.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderImageTexture.h
new file mode 100644
index 00000000..8b3469b0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderImageTexture.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_IMAGE_TEXTURE_H
+#define QT3DS_RENDER_QT3DS_RENDER_IMAGE_TEXTURE_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+ class NVRenderTexture2D;
+
+ // a wrapper class for NVRenderTexture2D
+ // to use with compute shaders and load / store image shaders
+
+ class NVRenderImage2D : public NVRefCounted
+ {
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderTexture2D *m_Texture2D; ///< pointer to texture
+ QT3DSI32 m_TextureUnit; ///< texture unit this texture should use
+ NVRenderImageAccessType::Enum
+ m_AccessType; ///< texture / image access type ( read, write, read_write )
+ QT3DSU32 m_TextureLevel; ///< texture level we use for this image
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] inTexture Pointer to a NVRenderTexture2D object
+ * @param[in] inAccess Image access type ( read, write, read_write )
+ *
+ * @return No return.
+ */
+ NVRenderImage2D(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTexture2D *inTexture, NVRenderImageAccessType::Enum inAccess);
+
+ virtual ~NVRenderImage2D();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief Set the access rights within the shader.
+ * Can be read, write or read_write.
+ *
+ * @param[in] inAccess Image access type ( read, write, read_write )
+ *
+ * @return No return.
+ */
+ virtual void SetAccessType(NVRenderImageAccessType::Enum inAccess)
+ {
+ m_AccessType = inAccess;
+ }
+
+ /**
+ * @brief Set the texture level we use for this image
+ *
+ * @param[in] inLevel texture level ( must be in range of max levels )
+ *
+ * @return No return.
+ */
+ virtual void SetTextureLevel(QT3DSI32 inLevel);
+
+ /**
+ * @brief Get texture unit used
+ *
+ *
+ * @return texture unit bound to.
+ */
+ virtual QT3DSU32 GetTextureUnit() const { return m_TextureUnit; }
+
+ /**
+ * @brief Bind a texture for shader access
+ *
+ * @param[in] unit The binding point
+ *
+ * @return No return.
+ */
+ virtual void Bind(QT3DSU32 unit);
+
+ /**
+ * @brief get the backend object handle
+ * here we return the handle from the wrapped texture
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendTextureObject GetTextureObjectHandle();
+
+ /**
+ * @brief static creation function
+ *
+ * @param[in] context Pointer to context
+ * @param[in] inTexture Pointer to a NVRenderTexture2D object
+ * @param[in] inAccess Image access type ( read, write, read_write )
+ *
+ * @return No return.
+ */
+ static NVRenderImage2D *Create(NVRenderContextImpl &context, NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderIndexBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderIndexBuffer.h
new file mode 100644
index 00000000..6b9c4711
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderIndexBuffer.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_INDEX_BUFFER_H
+#define QT3DS_RENDER_INDEX_BUFFER_H
+#include "render/Qt3DSRenderDataBuffer.h"
+#include "render/Qt3DSRenderDrawable.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+
+ class NVRenderIndexBuffer : public NVRenderDataBuffer, public NVRenderDrawable
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] componentType Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return.
+ */
+ NVRenderIndexBuffer(NVRenderContextImpl &context, size_t size,
+ NVRenderComponentTypes::Enum componentType,
+ NVRenderBufferUsageType::Enum usageType, NVDataRef<QT3DSU8> data);
+
+ ///< destruvtor
+ ~NVRenderIndexBuffer();
+
+ /**
+ * @brief get the component type (QT3DSU8, QT3DSU16)
+ *
+ * @return the component type
+ */
+ virtual NVRenderComponentTypes::Enum GetComponentType() const { return m_ComponentType; }
+
+ /**
+ * @brief get the index count
+ *
+ * @return actual index count
+ */
+ virtual QT3DSU32 GetNumIndices() const;
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief draw the buffer
+ *
+ * @param[in] drawMode draw mode (e.g Triangles...)
+ * @param[in] count vertex count
+ * @param[in] offset start offset in byte
+ *
+ * @return no return.
+ */
+ void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset) override;
+
+ /**
+ * @brief draw the buffer via indirec draw buffer setup
+ *
+ * @param[in] drawMode draw mode (e.g Triangles...)
+ * @param[in] offset byte offset into the bound drawIndirectBuffer see
+ * NVRenderDrawIndirectBuffer
+ *
+ * @return no return.
+ */
+ virtual void DrawIndirect(NVRenderDrawMode::Enum drawMode, QT3DSU32 offset);
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const override
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+
+ static NVRenderIndexBuffer *Create(NVRenderContextImpl &context,
+ NVRenderBufferUsageType::Enum usageType,
+ NVRenderComponentTypes::Enum componentType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData);
+
+ private:
+ NVRenderComponentTypes::Enum m_ComponentType; ///< component type (QT3DSU8, QT3DSU16)
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderInputAssembler.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderInputAssembler.h
new file mode 100644
index 00000000..adac4c42
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderInputAssembler.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_INPUT_ASSEMBLER_H
+#define QT3DS_RENDER_INPUT_ASSEMBLER_H
+
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Utils.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ // forward declarations
+ class NVRenderContextImpl;
+ class NVRenderBackend;
+ class NVRenderAttribLayout;
+
+ ///< this class handles the vertex attribute layout setup
+ class NVRenderInputAssembler : public NVRefCounted
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * NOTE: The limit for buffers count is currently 16
+ *
+ * @param[in] context Pointer to context
+ * @param[in] attribLayout Pointer to NVRenderAttribLayout object
+ * @param[in] buffers list of vertex buffers
+ * @param[in] indexBuffer pointer to index buffer. Can be NULL
+ * @param[in] strides list of strides of the buffer
+ * @param[in] offsets list of offsets into the buffer
+ * @param[in] primType primitive type used for drawing
+ * @param[in] patchVertexCount if primitive is "Patch" this is the vertex count for a
+ *single patch
+ *
+ * @return No return.
+ */
+ NVRenderInputAssembler(NVRenderContextImpl &context, NVRenderAttribLayout *attribLayout,
+ NVConstDataRef<NVRenderVertexBuffer *> buffers,
+ const NVRenderIndexBuffer *indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets,
+ NVRenderDrawMode::Enum primType = NVRenderDrawMode::Triangles,
+ QT3DSU32 patchVertexCount = 1);
+ ///< destructor
+ ~NVRenderInputAssembler();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendInputAssemblerObject GetInputAssemblerHandle() const
+ {
+ return m_InputAssemblertHandle;
+ }
+
+ /**
+ * @brief get the attached index buffer
+ *
+ * @return the index buffer
+ */
+ const NVRenderIndexBuffer *GetIndexBuffer() { return m_IndexBuffer; }
+
+ /**
+ * @brief get the index count of the attached index buffer (if any)
+ *
+ * @return the index buffer count
+ */
+ QT3DSU32 GetIndexCount() const;
+
+ /**
+ * @brief get the vertex count of the buffer
+ * Note this makes only sense if we have a single
+ * interleaved buffer
+ *
+ * @return the vertex buffer count
+ */
+ QT3DSU32 GetVertexCount() const;
+
+ /**
+ * @brief get the primitive type used for drawing
+ *
+ * @return primitive type
+ */
+ NVRenderDrawMode::Enum GetPrimitiveType() const { return m_PrimitiveType; }
+
+ /**
+ * @brief set the per vertex patch count
+ *
+ * @return none
+ */
+ void SetPatchVertexCount(QT3DSU32 count)
+ {
+ if (count != m_PatchVertexCount) {
+ // clamp to 1;
+ m_PatchVertexCount = (count == 0) ? 1 : count;
+ ;
+ m_Backend->SetPatchVertexCount(m_InputAssemblertHandle, m_PatchVertexCount);
+ }
+ }
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+
+ NVRenderAttribLayout *m_AttribLayout; ///< pointer to attribute layout
+ nvvector<NVRenderVertexBuffer *> m_VertexBuffers; ///< vertex buffers
+ const NVRenderIndexBuffer *m_IndexBuffer; ///< index buffer
+ NVConstDataRef<NVRenderBackend::NVRenderBackendBufferObject>
+ m_VertexbufferHandles; ///< opaque vertex buffer backend handles
+
+ NVRenderBackend::NVRenderBackendInputAssemblerObject
+ m_InputAssemblertHandle; ///< opaque backend handle
+ NVRenderDrawMode::Enum m_PrimitiveType; ///< primitive type used for drawing
+ QT3DSU32 m_PatchVertexCount; ///< vertex count if primitive type is patch
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderOcclusionQuery.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderOcclusionQuery.h
new file mode 100644
index 00000000..04f64e97
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderOcclusionQuery.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_OCCLUSION_QUERY_H
+#define QT3DS_RENDER_OCCLUSION_QUERY_H
+
+#include "render/Qt3DSRenderQueryBase.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+
+ class NVRenderOcclusionQuery : public NVRenderQueryBase
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderOcclusionQuery(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ ///< destructor
+ ~NVRenderOcclusionQuery();
+
+ /**
+ * @brief Get query type
+ *
+ * @return Return query type
+ */
+ NVRenderQueryType::Enum GetQueryType() const override
+ {
+ return NVRenderQueryType::Samples;
+ }
+
+ /**
+ * @brief Get a pointer to the foundation
+ *
+ * @return pointer to foundation
+ */
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ /**
+ * @brief begin a query
+ *
+ * @return no return.
+ */
+ void Begin() override;
+
+ /**
+ * @brief end a query
+ *
+ * @return no return.
+ */
+ void End() override;
+
+ /**
+ * @brief Get the result of a query
+ *
+ * @param[out] params Contains result of query regarding query type
+ *
+ * @return no return.
+ */
+ void GetResult(QT3DSU32 *params) override;
+
+ /**
+ * @brief query if a result is available
+ *
+ *
+ * @return true if available.
+ */
+ virtual bool GetResultAvailable();
+
+ /*
+ * @brief static creation function
+ *
+ * * @return a occlusion query object on success
+ */
+ static NVRenderOcclusionQuery *Create(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontSpecification.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontSpecification.h
new file mode 100644
index 00000000..dad3f6bb
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontSpecification.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/ #pragma once
+#ifndef QT3DS_RENDER_PATH_FONT_SPECIFICATION_H
+#define QT3DS_RENDER_PATH_FONT_SPECIFICATION_H
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/StringTable.h"
+#include "EASTL/string.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+ namespace qt3ds
+{
+ namespace render {
+
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+ class NVRenderPathRender;
+ class NVRenderPathFontItem;
+
+ class NVRenderPathFontSpecification : public NVRefCounted
+ {
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ volatile QT3DSI32
+ mRefCount; ///< Using foundations' naming convention to ease implementation
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] fontName Name of font ( may include path
+ * )
+ *
+ * @return No return.
+ */
+ NVRenderPathFontSpecification(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ CRegisteredString fontName);
+
+ /// @NVRenderPathSpecification destructor
+ ~NVRenderPathFontSpecification();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief Load numGlyphs glyphs from specified font file
+ *
+ * @param[in] pathBase Base of path objects
+ * @param[in] fontName Name of font ( may include path
+ * )
+ * @param[in] numGlyphs Glyph count
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes character string
+ *
+ * @return No return
+ */
+ virtual void LoadPathGlyphs(const char *fontName, NVRenderPathFormatType::Enum type);
+
+ /**
+ * @brief Render a stencil fill pass for fonts
+ *
+ * @param[in] inPathFontSpec Pointer to NVRenderPathFontSpecification
+ *
+ * @return no return
+ */
+ void StencilFillPathInstanced(NVRenderPathFontItem &inPathFontItem);
+
+ /**
+ * @brief Render a cover fill pass for fonts
+ *
+ * @param[in] inPathFontSpec Pointer to NVRenderPathFontSpecification
+ *
+ * @return no return
+ */
+ void CoverFillPathInstanced(NVRenderPathFontItem &inPathFontItem);
+
+ /**
+ * @brief get type for font path set
+ *
+ * @return path font type
+ */
+ NVRenderPathFormatType::Enum GetPathFontType() { return m_Type; }
+
+ /**
+ * @brief get font glyph count
+ *
+ * @return get glyph count
+ */
+ QT3DSU32 GetFontGlyphsCount() { return m_NumFontGlyphs; }
+
+ /**
+ * @brief get spacing for char set
+ *
+ * @return spacing array
+ */
+ QT3DSF32 GetEmScale() const { return m_EmScale; }
+
+ /**
+ * @brief Get font name
+ *
+ * @return name set
+ */
+ CRegisteredString GetFontName() const { return m_FontName; }
+
+ private:
+ QT3DSU32 m_NumFontGlyphs; ///< glyph count of the entire font set
+ QT3DSF32 m_EmScale; ///< true type scale
+ NVRenderPathFormatType::Enum m_Type; ///< type ( byte, int,... )
+ NVRenderPathTransformType::Enum m_TransformType; ///< transform type default 2D
+ CRegisteredString m_FontName; ///< Name of Font
+ NVRenderBackend::NVRenderBackendPathObject
+ m_PathRenderHandle; ///< opaque backend handle
+
+ private:
+ /**
+ * @brief Get size of type
+ *
+ * @param[in] type type ( byte, int,... )
+ *
+ * @return true if successful
+ */
+ QT3DSU32 getSizeofType(NVRenderPathFormatType::Enum type);
+
+ public:
+ static NVRenderPathFontSpecification *
+ CreatePathFontSpecification(NVRenderContextImpl &context, CRegisteredString fontName);
+ };
+ }
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontText.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontText.h
new file mode 100644
index 00000000..a1d103ac
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathFontText.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/ #pragma once
+#ifndef QT3DS_RENDER_PATH_FONT_TEXT_H
+#define QT3DS_RENDER_PATH_FONT_TEXT_H
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "EASTL/string.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+ namespace qt3ds
+{
+ namespace render {
+
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+ class NVRenderPathFontSpecification;
+
+ class NVRenderPathFontItem : public NVRefCounted
+ {
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32
+ mRefCount; ///< Using foundations' naming convention to ease implementation
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderPathFontItem(NVFoundationBase &fnd);
+
+ /// @NVRenderPathFontItem destructor
+ ~NVRenderPathFontItem();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief Setup text
+ *
+ * @param[in] glyphCount number of glyphs
+ * @param[in] glyphIDs array of glyhp ID's
+ * @param[in] type type ( byte, int,... )
+ * @param[in] posArray array of glyhp positions
+ * @param[in] pixelBound pixel boundary
+ * @param[in] logicalBound logical boundary
+ * @param[in] emScale true type scale
+ *
+ * @return No return.
+ */
+ void InitTextItem(size_t glyphCount, const QT3DSU32 *glyphIDs,
+ NVRenderPathFormatType::Enum type, QT3DSF32 *posArray, QT3DSVec2 pixelBound,
+ QT3DSVec2 logicalBound, QT3DSF32 emScale);
+
+ /**
+ * @brief get glyph count
+ *
+ * @return get glyph count
+ */
+ size_t GetGlyphsCount() { return m_NumGlyphs; }
+
+ /**
+ * @brief get spacing for char set
+ *
+ * @return spacing array
+ */
+ const QT3DSF32 *GetSpacing() { return m_TranslateXY; }
+
+ /**
+ * @brief get name set
+ *
+ * @return name set
+ */
+ const void *GetGlyphIDs() { return (void *)m_GlyphIDs; }
+
+ /**
+ * @brief Get Y bound of font metric
+ *
+ * @return transform matrix
+ */
+ const QT3DSMat44 GetTransform();
+
+ private:
+ /**
+ * @brief Get size of type
+ *
+ * @param[in] type type ( byte, int,... )
+ *
+ * @return true if successful
+ */
+ QT3DSU32 getSizeofType(NVRenderPathFormatType::Enum type);
+
+ private:
+ size_t m_NumGlyphs; ///< glyph count
+ QT3DSU32 *m_GlyphIDs; ///< array glyph ID's
+ QT3DSF32 *
+ m_TranslateXY; ///< pointer to arrray for character advance information like kerning
+ QT3DSMat44 m_ModelMatrix; ///< Matrix which converts from font space to box space
+
+ public:
+ static NVRenderPathFontItem *CreatePathFontItem(NVRenderContextImpl &context);
+ };
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathRender.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathRender.h
new file mode 100644
index 00000000..c261ca31
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathRender.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_PATH_RENDER_H
+#define QT3DS_RENDER_PATH_RENDER_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "foundation/Qt3DSBounds3.h"
+#include <EASTL/string.h>
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+ class NVRenderPathSpecification;
+ class NVRenderPathFontSpecification;
+
+ ///< A program pipeline is a collection of a multiple programs (vertex, fragment, geometry,....)
+ class NVRenderPathRender : public NVRefCounted
+ {
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] range Number of internal objects
+ *
+ * @return No return.
+ */
+ NVRenderPathRender(NVRenderContextImpl &context, NVFoundationBase &fnd, size_t range);
+
+ /// @brief destructor
+ ~NVRenderPathRender();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendPathObject GetPathHandle() { return m_PathRenderHandle; }
+
+ // The render context can create a path specification object.
+ void SetPathSpecification(NVRenderPathSpecification &inCommandBuffer);
+
+ NVBounds3 GetPathObjectBoundingBox();
+ NVBounds3 GetPathObjectFillBox();
+ NVBounds3 GetPathObjectStrokeBox();
+
+ void SetStrokeWidth(QT3DSF32 inStrokeWidth);
+ QT3DSF32 GetStrokeWidth() const;
+
+ void StencilStroke();
+ void StencilFill();
+
+ /**
+ * @brief static create function
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] range Number of internal objects
+ *
+ * @return the backend object handle.
+ */
+ static NVRenderPathRender *Create(NVRenderContextImpl &context, size_t range);
+
+ private:
+ NVRenderBackend::NVRenderBackendPathObject m_PathRenderHandle; ///< opaque backend handle
+ size_t m_Range; ///< range of internal objects
+ QT3DSF32 m_StrokeWidth;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathSpecification.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathSpecification.h
new file mode 100644
index 00000000..7c6faeda
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderPathSpecification.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_PATH_SPECIFICATION_H
+#define QT3DS_RENDER_PATH_SPECIFICATION_H
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ class NVRenderPathSpecification : public NVRefCounted
+ {
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderPathSpecification(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ /// @NVRenderPathSpecification destructor
+ ~NVRenderPathSpecification();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief reset commands and coordiantes
+ *
+ * @return No return.
+ */
+ virtual void Reset();
+
+ /**
+ * @brief add new move to command
+ *
+ * @param[in] inPoint Coordinate
+ *
+ * @return No return.
+ */
+ virtual void MoveTo(QT3DSVec2 inPoint);
+
+ /**
+ * @brief add new cubic curve command
+ *
+ * @param[in] inC1 control point 1
+ * @param[in] inC2 control point 2
+ * @param[in] inDest final point
+ *
+ * @return No return.
+ */
+ virtual void CubicCurveTo(QT3DSVec2 inC1, QT3DSVec2 inC2, QT3DSVec2 inDest);
+
+ /**
+ * @brief add new close command
+ *
+ *
+ * @return No return.
+ */
+ virtual void ClosePath();
+
+ /**
+ * @brief Get path command list
+ *
+ *
+ * @return path commands
+ */
+ virtual NVConstDataRef<QT3DSU8> GetPathCommands() { return m_PathCommands; }
+
+ /**
+ * @brief Get path coordinates list
+ *
+ *
+ * @return path coordinates
+ */
+ virtual NVConstDataRef<QT3DSF32> GetPathCoords() { return m_PathCoords; }
+
+ private:
+ nvvector<QT3DSU8> m_PathCommands;
+ nvvector<QT3DSF32> m_PathCoords;
+
+ /**
+ * @brief add a new point to the coordinates
+ *
+ * @param[in] inPoint Coordinate
+ *
+ * @return No return.
+ */
+ void P(QT3DSVec2 inData);
+
+ public:
+ static NVRenderPathSpecification *CreatePathSpecification(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderProgramPipeline.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderProgramPipeline.h
new file mode 100644
index 00000000..79c30c87
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderProgramPipeline.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_PROGRAM_PIPLINE_H
+#define QT3DS_RENDER_PROGRAM_PIPLINE_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include <EASTL/string.h>
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+ class NVRenderShaderProgram;
+
+ ///< A program pipeline is a collection of a multiple programs (vertex, fragment, geometry,....)
+ class NVRenderProgramPipeline : public NVRefCounted
+ {
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderProgramPipeline(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ /// @brief destructor
+ ~NVRenderProgramPipeline();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief Query if pipeline is valid
+ *
+ * @return True if valid.
+ */
+ bool IsValid();
+
+ /**
+ * @brief enable / disable a program stage in the pipeline
+ *
+ * @param[in] pProgram Pointer to program. If NULL stage will be disabled
+ * @param[in] flags Flags to which stage this program is bound to. Can more than
+ * one stage
+ *
+ * @return no return.
+ */
+ void SetProgramStages(NVRenderShaderProgram *pProgram, NVRenderShaderTypeFlags flags);
+
+ /**
+ * @brief Make the program pipeline active
+ *
+ * @return True if valid.
+ */
+ void Bind();
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendProgramPipeline GetShaderHandle()
+ {
+ return m_ProgramPipelineHandle;
+ }
+
+ /**
+ * @brief get the vertex stage program
+ *
+ * @return the backend object handle.
+ */
+ NVRenderShaderProgram *GetVertexStage() { return m_VertexProgram; }
+
+ private:
+ NVRenderBackend::NVRenderBackendProgramPipeline
+ m_ProgramPipelineHandle; ///< opaque backend handle
+
+ NVRenderShaderProgram
+ *m_Program; ///< for non separable programs this contains the entire program
+ NVRenderShaderProgram
+ *m_VertexProgram; ///< for separable programs this contains the vertex program
+ NVRenderShaderProgram
+ *m_FragmentProgram; ///< for separable programs this contains the fragment program
+ NVRenderShaderProgram *m_TessControlProgram; ///< for separable programs this contains the
+ ///tessellation control program
+ NVRenderShaderProgram *m_TessEvalProgram; ///< for separable programs this contains the
+ ///tessellation evaluation program
+ NVRenderShaderProgram
+ *m_GeometryProgram; ///< for separable programs this contains the geometry program
+ NVRenderShaderProgram
+ *m_ComputProgram; ///< for separable programs this contains the compute program
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderQueryBase.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderQueryBase.h
new file mode 100644
index 00000000..7a7ead87
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderQueryBase.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QUERY_BASE_H
+#define QT3DS_RENDER_QUERY_BASE_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+ class NVRenderBackend;
+
+ ///< Base class
+ class NVRenderQueryBase : public NVRefCounted
+ {
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBackend::NVRenderBackendQueryObject m_QueryHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderQueryBase(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ virtual ~NVRenderQueryBase();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief Get query type
+ *
+ * @return Return query type
+ */
+ virtual NVRenderQueryType::Enum GetQueryType() const = 0;
+
+ /**
+ * @brief Get a pointer to the foundation
+ *
+ * @return pointer to foundation
+ */
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ /**
+ * @brief begin a query
+ *
+ * @return no return.
+ */
+ virtual void Begin() = 0;
+
+ /**
+ * @brief end a query
+ *
+ * @return no return.
+ */
+ virtual void End() = 0;
+
+ /**
+ * @brief Get the result of a query
+ *
+ * @param[out] params Contains result of query regarding query type
+ *
+ * @return no return.
+ */
+ virtual void GetResult(QT3DSU32 *params) = 0;
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendQueryObject GetQuerytHandle() const
+ {
+ return m_QueryHandle;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRasterizerState.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRasterizerState.h
new file mode 100644
index 00000000..9b71ae42
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRasterizerState.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_RASTERIZER_STATE_H
+#define QT3DS_RENDER_RASTERIZER_STATE_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+
+ // currently this handles only stencil state
+ class NVRenderRasterizerState : public NVRefCounted
+ {
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBackend::NVRenderBackendRasterizerStateObject
+ m_StateHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] depthBias depth bias
+ * @param[in] depthScale depth multiplicator
+ * @param[in] cullFace which face to cull front or back
+ *
+ * @return No return.
+ */
+ NVRenderRasterizerState(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ QT3DSF32 depthBias, QT3DSF32 depthScale, NVRenderFaces::Enum cullFace);
+
+ virtual ~NVRenderRasterizerState();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendRasterizerStateObject GetRasterizerObjectHandle()
+ {
+ return m_StateHandle;
+ }
+
+ static NVRenderRasterizerState *Create(NVRenderContextImpl &context, QT3DSF32 depthBias,
+ QT3DSF32 depthScale, NVRenderFaces::Enum cullFace);
+
+ private:
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRenderBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRenderBuffer.h
new file mode 100644
index 00000000..41f4068a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderRenderBuffer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_RENDER_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_RENDER_BUFFER_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+ class NVRenderContextImpl;
+
+ struct NVRenderRenderBufferDimensions
+ {
+ QT3DSU32 m_Width; ///< buffer width
+ QT3DSU32 m_Height; ///< buffer height
+
+ NVRenderRenderBufferDimensions(QT3DSU32 w, QT3DSU32 h)
+ : m_Width(w)
+ , m_Height(h)
+ {
+ }
+ NVRenderRenderBufferDimensions()
+ : m_Width(0)
+ , m_Height(0)
+ {
+ }
+ };
+
+ class NVRenderRenderBuffer : public NVRefCounted, public NVRenderImplemented
+ {
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ QT3DSU32 m_Width; ///< buffer width
+ QT3DSU32 m_Height; ///< buffer height
+ NVRenderRenderBufferFormats::Enum m_StorageFormat; ///< buffer storage format
+
+ NVRenderBackend::NVRenderBackendRenderbufferObject
+ m_BufferHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] format Renderbuffer format
+ * @param[in] width Renderbuffer width
+ * @param[in] height Renderbuffer height
+ *
+ * @return No return.
+ */
+ NVRenderRenderBuffer(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderRenderBufferFormats::Enum format, QT3DSU32 width, QT3DSU32 height);
+
+ /// destructor
+ virtual ~NVRenderRenderBuffer();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ /**
+ * @brief query buffer format
+ *
+ *
+ * @return buffer format
+ */
+ virtual NVRenderRenderBufferFormats::Enum GetStorageFormat() const
+ {
+ return m_StorageFormat;
+ }
+
+ /**
+ * @brief query buffer dimension
+ *
+ *
+ * @return NVRenderRenderBufferDimensions object
+ */
+ virtual NVRenderRenderBufferDimensions GetDimensions() const
+ {
+ return NVRenderRenderBufferDimensions(m_Width, m_Height);
+ }
+
+ /**
+ * @brief constructor
+ *
+ * @param[in] inDimensions A dimension object
+ *
+ * @return buffer format
+ */
+ virtual void SetDimensions(const NVRenderRenderBufferDimensions &inDimensions);
+
+ /**
+ * @brief static creator function
+ *
+ * @param[in] context Pointer to context
+ * @param[in] format Renderbuffer format
+ * @param[in] width Renderbuffer width
+ * @param[in] height Renderbuffer height
+ *
+ * @return No return.
+ */
+ static NVRenderRenderBuffer *Create(NVRenderContextImpl &context,
+ NVRenderRenderBufferFormats::Enum format, QT3DSU32 width,
+ QT3DSU32 height);
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendRenderbufferObject GetRenderBuffertHandle()
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSampler.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSampler.h
new file mode 100644
index 00000000..77d3f008
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSampler.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_SAMPLER_H
+#define QT3DS_RENDER_QT3DS_RENDER_SAMPLER_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+
+ class NVRenderTextureSampler
+ {
+ public:
+ NVRenderTextureMinifyingOp::Enum m_MinFilter;
+ NVRenderTextureMagnifyingOp::Enum m_MagFilter;
+ NVRenderTextureCoordOp::Enum m_WrapS;
+ NVRenderTextureCoordOp::Enum m_WrapT;
+ NVRenderTextureCoordOp::Enum m_WrapR;
+ NVRenderTextureSwizzleMode::Enum m_SwizzleMode;
+ QT3DSF32 m_MinLod;
+ QT3DSF32 m_MaxLod;
+ QT3DSF32 m_LodBias;
+ NVRenderTextureCompareMode::Enum m_CompareMode;
+ NVRenderTextureCompareOp::Enum m_CompareOp;
+ QT3DSF32 m_Anisotropy;
+ QT3DSF32 m_BorderColor[4];
+
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] minFilter Texture min filter
+ * @param[in] magFilter Texture mag filter
+ * @param[in] wrapS Texture coord generation for S
+ * @param[in] wrapT Texture coord generation for T
+ * @param[in] wrapR Texture coord generation for R
+ * @param[in] swizzleMode Texture swizzle mode
+ * @param[in] minLod Texture min level of detail
+ * @param[in] maxLod Texture max level of detail
+ * @param[in] lodBias Texture level of detail bias (unused)
+ * @param[in] compareMode Texture compare mode
+ * @param[in] compareFunc Texture compare function
+ * @param[in] anisoFilter Aniso filter value [1.0, 16.0]
+ * @param[in] borderColor Texture border color float[4] (unused)
+ *
+ * @return No return.
+ */
+ NVRenderTextureSampler(
+ NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear,
+ NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear,
+ NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle,
+ QT3DSF32 minLod = -1000.0, QT3DSF32 maxLod = 1000.0, QT3DSF32 lodBias = 0.0,
+ NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare,
+ NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual,
+ QT3DSF32 anisotropy = 1.0, QT3DSF32 *borderColor = NULL);
+
+ /**
+ * @brief destructor
+ *
+ */
+ virtual ~NVRenderTextureSampler();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendSamplerObject GetSamplerHandle() const
+ {
+ return m_SamplerHandle;
+ }
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBackend::NVRenderBackendSamplerObject m_SamplerHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShader.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShader.h
new file mode 100644
index 00000000..8d0a62c4
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShader.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_SHADER_H
+#define QT3DS_RENDER_SHADER_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include <EASTL/string.h>
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ ///< A shader program is an object composed of a multiple shaders (vertex, fragment,
+ ///geometry,....)
+ class NVRenderShader
+ {
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVConstDataRef<QT3DSI8> m_Source; ///< shader source code
+ bool m_Binary; ///< true for binary programs
+ eastl::string m_ErrorMessage; ///< contains the error message if linking fails
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , m_Backend(context.GetBackend())
+ , m_Source(source)
+ , m_Binary(binaryProgram)
+ {
+ }
+
+ /// @brief destructor
+ ~NVRenderShader(){}
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ virtual bool IsValid() = 0;
+
+ /**
+ * @brief Get Error Message
+ *
+ * @param[out] messageLength Pointer to error string
+ * @param[out] messageLength Size of error meesage
+ *
+ * @return no return
+ */
+ virtual void GetErrorMessage(QT3DSI32 *messageLength, const char *errorMessage)
+ {
+ // Since we do not have any error message just generate a generic one
+ if (m_Binary)
+ m_ErrorMessage = "Binary shader compilation failed";
+
+ *messageLength = m_ErrorMessage.size();
+ errorMessage = m_ErrorMessage.c_str();
+ }
+
+ /**
+ * @brief Get Error Message
+ *
+ *
+ * @return error message.
+ */
+ virtual const char *GetErrorMessage()
+ {
+ if (m_Binary)
+ m_ErrorMessage = "Binary shader compilation failed";
+
+ return m_ErrorMessage.c_str();
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h
new file mode 100644
index 00000000..ffbbda72
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderConstant.h
@@ -0,0 +1,400 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_SHADER_CONSTANT_H
+#define QT3DS_RENDER_SHADER_CONSTANT_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DSMat44.h"
+#include "EASTL/string.h"
+#include "EASTL/utility.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ ///< forward declarations
+ class NVRenderContextImpl;
+ class NVRenderConstantBuffer;
+
+ ///< A shader constant belongs to a program
+ class NVRenderShaderConstantBase
+ {
+ public:
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ CRegisteredString m_Name; ///< register constant name
+ QT3DSI32 m_Location; ///< constant index
+ QT3DSI32 m_ElementCount; ///< constant element count for arrays
+ NVRenderShaderDataTypes::Enum m_Type; ///< constant type
+ QT3DSI32 m_Binding; ///< sampler/imnage binding point
+
+ public:
+ NVRenderShaderConstantBase(NVRenderBackend *backend, CRegisteredString name, QT3DSI32 location,
+ QT3DSI32 elementCount, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 binding)
+ : m_Backend(backend)
+ , m_Name(name)
+ , m_Location(location)
+ , m_ElementCount(elementCount)
+ , m_Type(type)
+ , m_Binding(binding)
+ {
+ }
+
+ NVRenderShaderDataTypes::Enum GetShaderConstantType() const { return m_Type; }
+
+ virtual void Release() = 0;
+ };
+
+ ///< A general class for shader types
+ template <typename TDataType>
+ class NVRenderShaderConstant : public NVRenderShaderConstantBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ TDataType m_Value; ///< constant value
+
+ public:
+ NVRenderShaderConstant(NVRenderBackend *backend, CRegisteredString name, QT3DSI32 location,
+ QT3DSI32 elementCount, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 binding, NVFoundationBase &allocator)
+ : NVRenderShaderConstantBase(backend, name, location, elementCount, type, binding)
+ , m_Foundation(allocator)
+ {
+ memset(&m_Value, 0, sizeof(TDataType));
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override { NVDelete(GetFoundation().getAllocator(), this); }
+ };
+
+ ///< A specialized class for textures
+ template <>
+ class NVRenderShaderConstant<NVRenderTexture2DPtr> : public NVRenderShaderConstantBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSU32 m_Value; ///< constant value
+
+ public:
+ NVRenderShaderConstant(NVRenderBackend *backend, CRegisteredString name, QT3DSI32 location,
+ QT3DSI32 elementCount, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 binding, NVFoundationBase &allocator)
+ : NVRenderShaderConstantBase(backend, name, location, elementCount, type, binding)
+ , m_Foundation(allocator)
+ {
+ m_Value = QT3DS_MAX_U32;
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override { NVDelete(GetFoundation().getAllocator(), this); }
+ };
+
+ ///< A specialized class for texture arrays
+ template <>
+ class NVRenderShaderConstant<NVRenderTexture2DArrayPtr> : public NVRenderShaderConstantBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSU32 m_Value; ///< constant value
+
+ public:
+ NVRenderShaderConstant(NVRenderBackend *backend, CRegisteredString name, QT3DSI32 location,
+ QT3DSI32 elementCount, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 binding, NVFoundationBase &allocator)
+ : NVRenderShaderConstantBase(backend, name, location, elementCount, type, binding)
+ , m_Foundation(allocator)
+ {
+ m_Value = QT3DS_MAX_U32;
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override { NVDelete(GetFoundation().getAllocator(), this); }
+ };
+
+ ///< A specialized class for cubemap textures
+ template <>
+ class NVRenderShaderConstant<NVRenderTextureCubePtr> : public NVRenderShaderConstantBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSU32 m_Value; ///< constant value
+
+ public:
+ NVRenderShaderConstant(NVRenderBackend *backend, CRegisteredString name, QT3DSI32 location,
+ QT3DSI32 elementCount, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 binding, NVFoundationBase &allocator)
+ : NVRenderShaderConstantBase(backend, name, location, elementCount, type, binding)
+ , m_Foundation(allocator)
+ {
+ m_Value = QT3DS_MAX_U32;
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override { NVDelete(GetFoundation().getAllocator(), this); }
+ };
+
+ ///< A specialized class for texture image buffer
+ template <>
+ class NVRenderShaderConstant<NVRenderImage2DPtr> : public NVRenderShaderConstantBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSU32 m_Value; ///< constant value
+
+ public:
+ NVRenderShaderConstant(NVRenderBackend *backend, CRegisteredString name, QT3DSI32 location,
+ QT3DSI32 elementCount, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 binding, NVFoundationBase &allocator)
+ : NVRenderShaderConstantBase(backend, name, location, elementCount, type, binding)
+ , m_Foundation(allocator)
+ {
+ m_Value = QT3DS_MAX_U32;
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override { NVDelete(GetFoundation().getAllocator(), this); }
+ };
+
+ ///< Base for any buffer ( constant, texture, ... ) which is used by this program
+ class NVRenderShaderBufferBase
+ {
+ public:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ CRegisteredString m_Name; ///< buffer name
+ QT3DSU32 m_Location; ///< program buffer block location
+ QT3DSU32 m_Binding; ///< program buffer binding
+ QT3DSI32 m_Size; ///< buffer size
+
+ public:
+ NVRenderShaderBufferBase(NVRenderContextImpl &context, CRegisteredString name,
+ QT3DSI32 location, QT3DSI32 binding, QT3DSI32 size)
+ : m_Context(context)
+ , m_Name(name)
+ , m_Location(location)
+ , m_Binding(binding)
+ , m_Size(size)
+ {
+ }
+
+ virtual void Release() = 0;
+
+ virtual void Validate(NVRenderShaderProgram *inShader) = 0;
+ virtual void BindToPorgram(NVRenderShaderProgram *inShader) = 0;
+ virtual void Update() = 0;
+ };
+
+ class NVRenderShaderConstantBuffer : public NVRenderShaderBufferBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSI32 m_ParamCount; ///< count of parameters contained in the constant buffer
+ NVRenderConstantBuffer *m_pCB; ///< pointer to constant buffer
+
+ public:
+ NVRenderShaderConstantBuffer(NVRenderContextImpl &context, CRegisteredString name,
+ QT3DSU32 location, QT3DSI32 binding, QT3DSI32 size, QT3DSI32 count,
+ NVRenderConstantBuffer *pCB, NVFoundationBase &allocator)
+ : NVRenderShaderBufferBase(context, name, location, binding, size)
+ , m_Foundation(allocator)
+ , m_ParamCount(count)
+ , m_pCB(pCB)
+ {
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override
+ {
+ if (m_pCB)
+ m_pCB->release();
+
+ NVDelete(GetFoundation().getAllocator(), this);
+ }
+
+ void Validate(NVRenderShaderProgram *inShader) override
+ {
+ // A constant buffer might not be set at first call
+ // due to the fact that they are compiled from a cache file
+ // Now it must exists.
+ if (m_pCB)
+ return;
+
+ NVRenderConstantBuffer *cb = m_Context.GetConstantBuffer(m_Name);
+ if (cb) {
+ cb->SetupBuffer(inShader, m_Location, m_Size, m_ParamCount);
+ cb->addRef();
+ m_pCB = cb;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void Update() override
+ {
+ if (m_pCB)
+ m_pCB->Update();
+ }
+
+ void BindToPorgram(NVRenderShaderProgram *inShader) override
+ {
+ if (m_pCB)
+ m_pCB->BindToShaderProgram(inShader, m_Location, m_Binding);
+ }
+ };
+
+ class NVRenderShaderStorageBuffer : public NVRenderShaderBufferBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSI32 m_ParamCount; ///< count of parameters contained in the constant buffer
+ NVRenderStorageBuffer *m_pSB; ///< pointer to storage buffer
+
+ public:
+ NVRenderShaderStorageBuffer(NVRenderContextImpl &context, CRegisteredString name,
+ QT3DSU32 location, QT3DSI32 binding, QT3DSI32 size, QT3DSI32 count,
+ NVRenderStorageBuffer *pSB, NVFoundationBase &allocator)
+ : NVRenderShaderBufferBase(context, name, location, binding, size)
+ , m_Foundation(allocator)
+ , m_ParamCount(count)
+ , m_pSB(pSB)
+ {
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override
+ {
+ if (m_pSB)
+ m_pSB->release();
+
+ NVDelete(GetFoundation().getAllocator(), this);
+ }
+
+ void Validate(NVRenderShaderProgram * /*inShader*/) override
+ {
+ // A constant buffer might not be set at first call
+ // due to the fact that they are compile from a cache file
+ // Now it must exists.
+ if (m_pSB)
+ return;
+
+ NVRenderStorageBuffer *sb = m_Context.GetStorageBuffer(m_Name);
+ if (sb) {
+ sb->addRef();
+ m_pSB = sb;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void Update() override
+ {
+ if (m_pSB)
+ m_pSB->Update();
+ }
+
+ void BindToPorgram(NVRenderShaderProgram * /*inShader*/) override
+ {
+ if (m_pSB)
+ m_pSB->BindToShaderProgram(m_Location);
+ }
+ };
+
+ class NVRenderShaderAtomicCounterBuffer : public NVRenderShaderBufferBase
+ {
+ public:
+ NVFoundationBase &m_Foundation; ///< allocator
+ QT3DSI32 m_ParamCount; ///< count of parameters contained in the constant buffer
+ NVRenderAtomicCounterBuffer *m_pAcB; ///< pointer to atomic counter buffer
+
+ public:
+ NVRenderShaderAtomicCounterBuffer(NVRenderContextImpl &context, CRegisteredString name,
+ QT3DSU32 location, QT3DSI32 binding, QT3DSI32 size, QT3DSI32 count,
+ NVRenderAtomicCounterBuffer *pAcB,
+ NVFoundationBase &allocator)
+ : NVRenderShaderBufferBase(context, name, location, binding, size)
+ , m_Foundation(allocator)
+ , m_ParamCount(count)
+ , m_pAcB(pAcB)
+ {
+ }
+
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ void Release() override
+ {
+ if (m_pAcB)
+ m_pAcB->release();
+
+ NVDelete(GetFoundation().getAllocator(), this);
+ }
+
+ void Validate(NVRenderShaderProgram * /*inShader*/) override
+ {
+ // A constant buffer might not be set at first call
+ // due to the fact that they are compile from a cache file
+ // Now it must exists.
+ if (m_pAcB)
+ return;
+
+ NVRenderAtomicCounterBuffer *acb = m_Context.GetAtomicCounterBuffer(m_Name);
+ if (acb) {
+ acb->addRef();
+ m_pAcB = acb;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void Update() override
+ {
+ if (m_pAcB)
+ m_pAcB->Update();
+ }
+
+ void BindToPorgram(NVRenderShaderProgram * /*inShader*/) override
+ {
+ if (m_pAcB)
+ m_pAcB->BindToShaderProgram(m_Location);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h
new file mode 100644
index 00000000..73e123c1
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderShaderProgram.h
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_SHADER_PROGRAM_H
+#define QT3DS_RENDER_SHADER_PROGRAM_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderShaderConstant.h"
+#include "EASTL/string.h"
+#include "EASTL/utility.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ ///< forward declarations
+ class NVRenderContextImpl;
+ class NVRenderVertexShader;
+ class NVRenderFragmentShader;
+ class NVRenderTessControlShader;
+ class NVRenderTessEvaluationShader;
+ class NVRenderGeometryShader;
+ class NVRenderShaderConstantBase;
+ class NVRenderShaderBufferBase;
+ class NVRenderComputeShader;
+
+ typedef nvhash_map<CRegisteredString, NVRenderShaderConstantBase *> TShaderConstantMap;
+ typedef nvhash_map<CRegisteredString, NVRenderShaderBufferBase *> TShaderBufferMap;
+
+ ///< A shader program is an object composed of a multiple shaders (vertex, fragment,
+ ///geometry,....)
+ class NVRenderShaderProgram : public NVRefCounted
+ {
+ public:
+ struct ProgramType
+ {
+ enum Enum { Graphics, Compute };
+ };
+
+ private:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ const char *m_ProgramName; /// Name of the program
+ NVRenderBackend::NVRenderBackendShaderProgramObject
+ m_ProgramHandle; ///< opaque backend handle
+ TShaderConstantMap m_Constants; ///< map of shader constants
+ TShaderBufferMap m_ShaderBuffers; ///< map of shader buffers
+ ProgramType::Enum m_ProgramType; ///< shader type
+ eastl::string m_ErrorMessage; ///< contains the error message if linking fails
+
+ /**
+ * @brief create vertex shader
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] vertexShaderSource Fragment shader source code
+ * @param[in] binaryProgram True if binary program
+ *
+ * @return pointer to vertex shader object
+ */
+ static Option<NVRenderVertexShader *>
+ createVertexShader(NVRenderContextImpl &context, NVConstDataRef<QT3DSI8> vertexShaderSource,
+ bool binaryProgram = false);
+
+ /**
+ * @brief create fragment shader
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fragmentShaderSource Fragment shader source code
+ * @param[in] binaryProgram True if binary program
+ *
+ * @return pointer to fragment shader object
+ */
+ static Option<NVRenderFragmentShader *>
+ createFragmentShader(NVRenderContextImpl &context,
+ NVConstDataRef<QT3DSI8> fragmentShaderSource, bool binaryProgram = false);
+
+ /**
+ * @brief create tesselation control shader
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] tessControlShaderSource Tessellation control shader source code
+ * @param[in] binaryProgram True if binary program
+ *
+ * @return pointer to tessellation control shader
+ */
+ static Option<NVRenderTessControlShader *>
+ createTessControlShader(NVRenderContextImpl &context,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource,
+ bool binaryProgram = false);
+
+ /**
+ * @brief create tesselation evaluation shader
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] tessEvaluationShaderSource Tessellation evaluation shader source code
+ * @param[in] binaryProgram True if binary program
+ *
+ * @return pointer to tessellation evaluation shader
+ */
+ static Option<NVRenderTessEvaluationShader *>
+ createTessEvaluationShader(NVRenderContextImpl &context,
+ NVConstDataRef<QT3DSI8> tessEvaluationShaderSource,
+ bool binaryProgram = false);
+
+ /**
+ * @brief create geometry shader
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] geometryShaderSource Geometry shader source code
+ * @param[in] binaryProgram True if binary program
+ *
+ * @return pointer to geometry shader
+ */
+ static Option<NVRenderGeometryShader *>
+ createGeometryShader(NVRenderContextImpl &context,
+ NVConstDataRef<QT3DSI8> geometryShaderSource, bool binaryProgram = false);
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] programName Pointer to string of program name
+ * @param[in] separableProgram True if this is a separable program
+ *
+ * @return No return.
+ */
+ NVRenderShaderProgram(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ const char *programName, bool separableProgram);
+
+ /// destructor
+ ~NVRenderShaderProgram();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief attach a shader to the program
+ *
+ * @param[in] pShader Pointer to shader object
+ *
+ * @return No return.
+ */
+ template <typename TShaderObject>
+ void Attach(TShaderObject *pShader);
+
+ /**
+ * @brief detach a shader from the program
+ *
+ * @param[in] pShader Pointer to shader object
+ *
+ * @return No return.
+ */
+ template <typename TShaderObject>
+ void Detach(TShaderObject *pShader);
+
+ /**
+ * @brief link a program
+ *
+ *
+ * @return true if succesfuly linked.
+ */
+ bool Link();
+
+ /**
+ * @brief set a shader type
+ *
+ * @param[in] type shader type ( graphics or compute )
+ *
+ * @return No return.
+ */
+ void SetProgramType(ProgramType::Enum type) { m_ProgramType = type; }
+ ProgramType::Enum GetProgramType() const { return m_ProgramType; }
+
+ /**
+ * @brief Get Error Message
+ *
+ * @param[out] messageLength Pointer to error string
+ * @param[out] messageLength Size of error meesage
+ *
+ * @return no return.
+ */
+ void GetErrorMessage(QT3DSI32 *messageLength, const char *errorMessage);
+
+ /**
+ * @brief Get Error Message
+ *
+ *
+ * @return error message.
+ */
+ const char *GetErrorMessage();
+
+ /**
+ * @brief Query constant class
+ *
+ * @param[in] constantName Pointer to constant name
+ *
+ * @return return a pointer to a constant class.
+ */
+ NVRenderShaderConstantBase *GetShaderConstant(const char *constantName);
+
+ /**
+ * @brief Query a shader buffer (constant, ... )
+ *
+ * @param[in] bufferName Pointer to constant name
+ *
+ * @return return a pointer to a constant class.
+ */
+ NVRenderShaderBufferBase *GetShaderBuffer(const char *bufferName);
+
+ // concrete set functions
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, QT3DSI32 inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSI32_2 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSI32_3 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSI32_4 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, QT3DSRenderBool inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const bool_2 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const bool_3 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const bool_4 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSF32 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSVec2 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSVec3 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSVec4 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSU32 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSU32_2 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSU32_3 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSU32_4 &inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSMat33 &inValue,
+ const QT3DSI32 inCount, bool inTranspose = false);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, const QT3DSMat44 &inValue,
+ const QT3DSI32 inCount, bool inTranspose = false);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const NVConstDataRef<QT3DSMat44> inValue, const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, NVRenderTexture2D *inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ NVRenderTexture2DArray *inValue, const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, NVRenderTextureCube *inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, NVRenderImage2D *inValue,
+ const QT3DSI32 inCount);
+ void SetConstantValue(NVRenderShaderConstantBase *inConstant, NVRenderDataBuffer *inValue,
+ const QT3DSI32 inCount);
+
+ /**
+ * @brief Template to set constant value via name
+ *
+ * @param[in] inConstantName Pointer to constant name
+ * @param[in] inValue Pointer to data
+ * @param[in] inCount Number of elements (array count)
+ *
+ * @return return a pointer to a constant class.
+ */
+ template <typename TDataType>
+ void SetPropertyValue(const char *inConstantName, const TDataType &inValue,
+ const QT3DSI32 inCount = 1)
+ {
+ NVRenderShaderConstantBase *theConstant = GetShaderConstant(inConstantName);
+
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ SetConstantValue(theConstant, inValue, inCount);
+ } else {
+ // Types don't match or property not found
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ /**
+ * @brief Template to set constant value shader constant object
+ *
+ * @param[in] inConstant Pointer shader constant object
+ * @param[in] inValue Pointer to data
+ * @param[in] inCount Number of elements (array count)
+ *
+ * @return return a pointer to a constant class.
+ */
+ template <typename TDataType>
+ void SetPropertyValue(NVRenderShaderConstantBase *inConstant, const TDataType &inValue,
+ const QT3DSI32 inCount = 1)
+ {
+ if (inConstant) {
+ if (inConstant->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ SetConstantValue(inConstant, inValue, inCount);
+ } else {
+ // Types don't match or property not found
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ virtual void BindComputeInput(NVRenderDataBuffer *inBuffer, QT3DSU32 inIndex);
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendShaderProgramObject GetShaderProgramHandle() const
+ {
+ return m_ProgramHandle;
+ }
+
+ /**
+ * @brief get the context object
+ *
+ * @return context which this shader belongs to.
+ */
+ NVRenderContextImpl &GetRenderContext();
+
+ /**
+ * @brief Create a shader program
+ *
+ * @param[in] context Pointer to context
+ * @param[in] programName Name of the program
+ * @param[in] vertShaderSource Vertex shader source code
+ * @param[in] fragShaderSource Fragment shader source code
+ * @param[in] tessControlShaderSource tessellation control shader source code
+ * @param[in] tessEvaluationShaderSource tessellation evaluation shader source code
+ * @param[in] separateProgram True if this will we a separate
+ * program
+ * @param[in] type Binary program type
+ * @param[in] binaryProgram True if program is binary
+ *
+ * @return a render result
+ */
+ static NVRenderVertFragCompilationResult Create(
+ NVRenderContextImpl &context, const char *programName,
+ NVConstDataRef<QT3DSI8> vertShaderSource, NVConstDataRef<QT3DSI8> fragShaderSource,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource = NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> tessEvaluationShaderSource = NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8> geometryShaderSource = NVConstDataRef<QT3DSI8>(),
+ bool separateProgram = false,
+ NVRenderShaderProgramBinaryType::Enum type = NVRenderShaderProgramBinaryType::Unknown,
+ bool binaryProgram = false);
+
+ /**
+ * @brief Create a compute shader program
+ *
+ * @param[in] context Pointer to context
+ * @param[in] programName Name of the program
+ * @param[in] computeShaderSource Compute shader source code
+ *
+ * @return a render result
+ */
+ static NVRenderVertFragCompilationResult
+ CreateCompute(NVRenderContextImpl &context, const char *programName,
+ NVConstDataRef<QT3DSI8> computeShaderSource);
+ };
+
+ // Helper class to cache the lookup of shader properties and apply them quickly in a typesafe
+ // way.
+ template <typename TDataType>
+ struct NVRenderCachedShaderProperty
+ {
+ NVRenderShaderProgram *m_Shader; ///< pointer to shader program
+ NVRenderShaderConstantBase *m_Constant; ///< poiner to shader constant object
+
+ NVRenderCachedShaderProperty(const char *inConstantName, NVRenderShaderProgram &inShader)
+ : m_Shader(&inShader)
+ , m_Constant(NULL)
+ {
+ NVRenderShaderConstantBase *theConstant = inShader.GetShaderConstant(inConstantName);
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ m_Constant = theConstant;
+ } else {
+ // Property types do not match, this probably indicates that the shader changed
+ // while the
+ // code creating this object did not change.
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ NVRenderCachedShaderProperty()
+ : m_Shader(NULL)
+ , m_Constant(NULL)
+ {
+ }
+
+ void Set(const TDataType &inValue)
+ {
+ if (m_Constant)
+ m_Shader->SetPropertyValue(m_Constant, inValue);
+ }
+
+ bool IsValid() const { return m_Constant != 0; }
+ };
+
+ // Helper class to cache the lookup of shader properties and apply them quickly in a typesafe
+ // way.
+ template <typename TDataType>
+ struct NVRenderCachedShaderBuffer
+ {
+ NVRenderShaderProgram *m_Shader; ///< pointer to shader program
+ TDataType m_ShaderBuffer; ///< poiner to shader buffer object
+
+ NVRenderCachedShaderBuffer(const char *inShaderBufferName, NVRenderShaderProgram &inShader)
+ : m_Shader(&inShader)
+ , m_ShaderBuffer(NULL)
+ {
+ TDataType theShaderBuffer =
+ static_cast<TDataType>(inShader.GetShaderBuffer(inShaderBufferName));
+ if (theShaderBuffer) {
+ m_ShaderBuffer = theShaderBuffer;
+ }
+ }
+ NVRenderCachedShaderBuffer()
+ : m_Shader(NULL)
+ , m_ShaderBuffer(NULL)
+ {
+ }
+
+ void Set()
+ {
+ if (m_ShaderBuffer) {
+ m_ShaderBuffer->Validate(m_Shader);
+ m_ShaderBuffer->Update();
+ m_ShaderBuffer->BindToPorgram(m_Shader);
+ }
+ }
+
+ bool IsValid() const { return m_ShaderBuffer != 0; }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderStorageBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderStorageBuffer.h
new file mode 100644
index 00000000..fefe6b08
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderStorageBuffer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_STORAGE_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_STORAGE_BUFFER_H
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Utils.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderDataBuffer.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ // forward declaration
+ class NVRenderContextImpl;
+ class NVRenderVertexBuffer;
+
+ ///< Constant (uniform) buffer representation
+ class NVRenderStorageBuffer : public NVRenderDataBuffer
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] bufferName Name of the buffer. Must match the name used in programs
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ * @param[in] pBuffer Pointer to the buffer
+ *
+ * @return No return.
+ */
+ NVRenderStorageBuffer(NVRenderContextImpl &context, CRegisteredString bufferName,
+ size_t size, NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data, NVRenderDataBuffer *pBuffer = NULL);
+
+ ///< destructor
+ virtual ~NVRenderStorageBuffer();
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief bind the buffer to a shader program
+ *
+ * @param[in] index Index of the constant buffer within the program
+ *
+ * @return no return.
+ */
+ virtual void BindToShaderProgram(QT3DSU32 index);
+
+ /**
+ * @brief update the buffer to hardware
+ *
+ * @return no return.
+ */
+ virtual void Update();
+
+ /**
+ * @brief update a piece of memory directly within the storage buffer
+ *
+ * Note: When you use this function you should know what you are doing.
+ * The memory layout within C++ must exactly match the memory layout in the
+ *shader.
+ * We use std140 (430) layout which guarantees a specific layout behavior across
+ *all HW vendors.
+ * How the memory layout is computed can be found in the GL spec.
+ *
+ * @param[in] offset offset into storage buffer
+ * @param[in] data pointer to data
+ *
+ * @return no return
+ */
+ void UpdateData(QT3DSI32 offset, NVDataRef<QT3DSU8> data);
+
+ /**
+ * @brief get the buffer name
+ *
+ * @return the buffer name
+ */
+ CRegisteredString GetBufferName() const { return m_Name; }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const override
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+
+ /**
+ * @brief create a NVRenderStorageBuffer object
+ *
+ * @param[in] context Pointer to context
+ * @param[in] size Size of the buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return the buffer object or NULL
+ */
+ static NVRenderStorageBuffer *Create(NVRenderContextImpl &context, const char *bufferName,
+ NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData,
+ NVRenderDataBuffer *pBuffer);
+
+ private:
+ CRegisteredString m_Name; ///< buffer name
+ NVRenderDataBuffer *m_WrappedBuffer; ///< pointer to wrapped buffer
+ bool m_Dirty; ///< true if buffer is dirty
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSync.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSync.h
new file mode 100644
index 00000000..9dfeb28a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderSync.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_SYNC_H
+#define QT3DS_RENDER_SYNC_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+ class NVRenderBackend;
+
+ ///< Base class
+ class NVRenderSync : public NVRefCounted
+ {
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBackend::NVRenderBackendSyncObject m_SyncHandle; ///< opaque backend handle
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderSync(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ virtual ~NVRenderSync();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ /**
+ * @brief Get sync type
+ *
+ * @return Return query type
+ */
+ virtual NVRenderSyncType::Enum GetSyncType() const
+ {
+ return NVRenderSyncType::GpuCommandsComplete;
+ }
+
+ /**
+ * @brief Get a pointer to the foundation
+ *
+ * @return pointer to foundation
+ */
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ /**
+ * @brief Create a sync object and place it in command stream.
+ * Note every syncobject can only be used once.
+ * This function creates a new sync object on ever call
+ * and deletes the previous one
+ *
+ * @return no return.
+ */
+ virtual void Sync();
+
+ /**
+ * @brief Wait for a sync to be signaled
+ * Note this blocks until the sync is signaled
+ *
+ * @return no return.
+ */
+ virtual void Wait();
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendSyncObject GetSyncHandle() const
+ {
+ return m_SyncHandle;
+ }
+
+ /*
+ * @brief static creation function
+ *
+ * @return a sync object on success
+ */
+ static NVRenderSync *Create(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTessellationShader.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTessellationShader.h
new file mode 100644
index 00000000..b69e56b1
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTessellationShader.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_TESSELLATION_SHADER_H
+#define QT3DS_RENDER_TESSELLATION_SHADER_H
+
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderShader.h"
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ ///< This class represents a tessellation control shader
+ class NVRenderTessControlShader : public NVRenderShader
+ {
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] source Pointer to shader source code
+ * @param[in] binaryProgram true if this is a binary program
+ *
+ * @return No return.
+ */
+ NVRenderTessControlShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram);
+
+ /// @brief destructor
+ ~NVRenderTessControlShader();
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ bool IsValid() override { return (m_ShaderHandle != NULL); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendTessControlShaderObject GetShaderHandle()
+ {
+ return m_ShaderHandle;
+ }
+
+ private:
+ NVRenderBackend::NVRenderBackendTessControlShaderObject
+ m_ShaderHandle; ///< opaque backend handle
+ };
+
+ ///< This class represents a tessellation evaluation shader
+ class NVRenderTessEvaluationShader : public NVRenderShader
+ {
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] source Pointer to shader source code
+ * @param[in] binaryProgram true if this is a binary program
+ *
+ * @return No return.
+ */
+ NVRenderTessEvaluationShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram);
+
+ /// @brief destructor
+ ~NVRenderTessEvaluationShader();
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ bool IsValid() override { return (m_ShaderHandle != NULL); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendTessEvaluationShaderObject GetShaderHandle()
+ {
+ return m_ShaderHandle;
+ }
+
+ private:
+ NVRenderBackend::NVRenderBackendTessEvaluationShaderObject
+ m_ShaderHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2D.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2D.h
new file mode 100644
index 00000000..29c7c1b4
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2D.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_TEXTURE_2D_H
+#define QT3DS_RENDER_QT3DS_RENDER_TEXTURE_2D_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "render/Qt3DSRenderTextureBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+ class NVRenderTextureSampler;
+
+ class NVRenderTexture2D : public NVRenderTextureBase, public NVRenderImplemented
+ {
+
+ private:
+ QT3DSU32 m_Width; ///< texture width
+ QT3DSU32 m_Height; ///< texture height
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] texTarget Texture target
+ *
+ * @return No return.
+ */
+ NVRenderTexture2D(
+ NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget = NVRenderTextureTargetType::Texture2D);
+
+ virtual ~NVRenderTexture2D();
+
+ // Get the texture details for mipmap level 0 if it was set.
+ STextureDetails GetTextureDetails() const override;
+
+ /**
+ * @brief Create GL texture object and upload data
+ *
+ * @param[in] newBuffer Texture data for level 0
+ * @param[in] inMipLevel Texture level count
+ * @param[in] width Texture width
+ * @param[in] height Texture height
+ * @param[in] format Texture data format
+ * @param[in] formaInternal Texture internal format
+ *
+ * @return No return.
+ */
+ virtual void SetTextureData(
+ NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum format,
+ NVRenderTextureFormats::Enum formaInternal = NVRenderTextureFormats::Unknown);
+
+ /**
+ * @brief Create memory storage for a texture object
+ * This create a texture storage which is immutable in size and format
+ * Use this for textures used within compute shaders
+ *
+ * @param[in] inLevels Texture level count
+ * @param[in] width Texture width
+ * @param[in] height Texture height
+ * @param[in] formaInternal Texture internal format
+ * @param[in] format Texture data format of dataBuffer
+ * @param[in] dataBuffer Texture data for level 0
+ *
+ * @return No return.
+ */
+ virtual void
+ SetTextureStorage(QT3DSU32 inLevels, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum formaInternal,
+ NVRenderTextureFormats::Enum format = NVRenderTextureFormats::Unknown,
+ NVDataRef<QT3DSU8> dataBuffer = NVDataRef<QT3DSU8>());
+
+ virtual void SetTextureDataMultisample(QT3DSU32 sampleCount, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum format);
+
+ bool IsMultisampleTexture() const override
+ {
+ return (m_TexTarget == NVRenderTextureTargetType::Texture2D_MS);
+ }
+ QT3DSU32 GetSampleCount() const override { return m_SampleCount; }
+ bool IsImmutableTexture() const override { return m_Immutable; }
+
+ // Update a sub-rect of the image. newBuffer is expected to be a continguous subrect of the
+ // image.
+ virtual void SetTextureSubData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel, QT3DSU32 inXOffset,
+ QT3DSU32 inYOffset, QT3DSU32 inSubImageWidth,
+ QT3DSU32 inSubImageHeight, NVRenderTextureFormats::Enum format);
+ // Generate a set of mipmaps from mipLevel( 0 ). Uses the graphis layer to do this if
+ // possible
+ // glGenerateMipmap
+ virtual void GenerateMipmaps(NVRenderHint::Enum genType = NVRenderHint::Nicest);
+
+ /**
+ * @brief Bind a texture for shader access
+ *
+ *
+ * @return No return.
+ */
+ void Bind() override;
+
+ QT3DSU32 GetNumMipmaps() override { return m_MaxMipLevel; }
+
+ /**
+ * @brief Query if texture needs coordinate swizzle
+ *
+ * @return texture swizzle mode
+ */
+ NVRenderTextureSwizzleMode::Enum GetTextureSwizzleMode() override
+ {
+ // if our backend supports hardware texture swizzle then there is no need for a shader
+ // swizzle
+ return (m_Backend->GetRenderBackendCap(
+ NVRenderBackend::NVRenderBackendCaps::TexSwizzle))
+ ? NVRenderTextureSwizzleMode::NoSwizzle
+ : m_Backend->GetTextureSwizzleMode(m_Format);
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_TextureHandle);
+ }
+
+ static NVRenderTexture2D *Create(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2DArray.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2DArray.h
new file mode 100644
index 00000000..d77c8fef
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTexture2DArray.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_TEXTURE_2D_ARRAY_H
+#define QT3DS_RENDER_QT3DS_RENDER_TEXTURE_2D_ARRAY_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "render/Qt3DSRenderTextureBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+ class NVRenderTextureSampler;
+
+ class NVRenderTexture2DArray : public NVRenderTextureBase
+ {
+ private:
+ QT3DSU32 m_Width; ///< texture width
+ QT3DSU32 m_Height; ///< texture height
+ QT3DSU32 m_Slices; ///< texture slices
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] texTarget Texture target
+ *
+ * @return No return.
+ */
+ NVRenderTexture2DArray(
+ NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget = NVRenderTextureTargetType::Texture2D_Array);
+
+ virtual ~NVRenderTexture2DArray();
+
+ /**
+ * @brief constructor
+ *
+ * @param[in] newBuffer Pointer to pixel buffer
+ * @param[in] inMipLevel Pointer to foundation
+ * @param[in] width Texture target
+ * @param[in] height Texture target
+ * @param[in] slices Texture target
+ * @param[in] format Texture target
+ *
+ * @return No return.
+ */
+ void SetTextureData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel, QT3DSU32 width, QT3DSU32 height,
+ QT3DSU32 slices, NVRenderTextureFormats::Enum format);
+
+ // Get the texture details for mipmap level 0 if it was set.
+ STextureDetails GetTextureDetails() const override;
+
+ /**
+ * @brief Bind a texture for shader access
+ *
+ *
+ * @return No return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief create a texture array object
+ *
+ *
+ * @ return a texture array object
+ */
+ static NVRenderTexture2DArray *Create(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureBase.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureBase.h
new file mode 100644
index 00000000..872a634e
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureBase.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_TEXTURE_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_TEXTURE_BUFFER_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+ class NVRenderTextureSampler;
+
+ struct STextureDetails
+ {
+ QT3DSU32 m_Width;
+ QT3DSU32 m_Height;
+ QT3DSU32 m_Depth;
+ QT3DSU32 m_SampleCount;
+ NVRenderTextureFormats::Enum m_Format;
+
+ STextureDetails(QT3DSU32 w, QT3DSU32 h, QT3DSU32 d, QT3DSU32 samples, NVRenderTextureFormats::Enum f)
+ : m_Width(w)
+ , m_Height(h)
+ , m_Depth(d)
+ , m_SampleCount(samples)
+ , m_Format(f)
+ {
+ }
+ STextureDetails()
+ : m_Width(0)
+ , m_Height(0)
+ , m_Depth(0)
+ , m_SampleCount(1)
+ , m_Format(NVRenderTextureFormats::Unknown)
+ {
+ }
+ };
+
+ class NVRenderTextureBase : public NVRefCounted
+ {
+
+ protected:
+ NVRenderContextImpl &m_Context; ///< pointer to context
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ volatile QT3DSI32 mRefCount; ///< Using foundations' naming convention to ease implementation
+ NVRenderBackend *m_Backend; ///< pointer to backend
+ NVRenderBackend::NVRenderBackendTextureObject m_TextureHandle; ///< opaque backend handle
+ QT3DSU32 m_TextureUnit; ///< texture unit this texture should use
+ bool m_SamplerParamsDirty; ///< true if sampler state is dirty
+ bool m_TexStateDirty; ///< true if texture object state is dirty
+ QT3DSU32 m_SampleCount; ///< texture height
+ NVRenderTextureFormats::Enum m_Format; ///< texture format
+ NVRenderTextureTargetType::Enum m_TexTarget; ///< texture target
+ NVRenderTextureSampler *m_Sampler; ///< current texture sampler state
+ QT3DSI32 m_BaseLevel; ///< minimum lod specified
+ QT3DSI32 m_MaxLevel; ///< maximum lod specified
+ QT3DSU32 m_MaxMipLevel; ///< highest mip level
+ bool m_Immutable; ///< true if this is a immutable texture ( size and format )
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] texTarget Texture target
+ *
+ * @return No return.
+ */
+ NVRenderTextureBase(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget);
+
+ virtual ~NVRenderTextureBase();
+
+ // define refcount functions
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation)
+
+ virtual void SetMinFilter(NVRenderTextureMinifyingOp::Enum value);
+ virtual void SetMagFilter(NVRenderTextureMagnifyingOp::Enum value);
+
+ virtual void SetBaseLevel(QT3DSI32 value);
+ virtual void SetMaxLevel(QT3DSI32 value);
+
+ virtual void SetTextureWrapS(NVRenderTextureCoordOp::Enum value);
+ virtual void SetTextureWrapT(NVRenderTextureCoordOp::Enum value);
+
+ virtual void SetTextureCompareMode(NVRenderTextureCompareMode::Enum value);
+ virtual void SetTextureCompareFunc(NVRenderTextureCompareOp::Enum value);
+
+ virtual void SetTextureUnit(QT3DSU32 unit) { m_TextureUnit = unit; }
+ virtual QT3DSU32 GetTextureUnit() const { return m_TextureUnit; }
+
+ // Get the texture details for mipmap level 0 if it was set.
+ virtual STextureDetails GetTextureDetails() const = 0;
+
+ virtual bool IsMultisampleTexture() const
+ {
+ return (m_TexTarget == NVRenderTextureTargetType::Texture2D_MS);
+ }
+ virtual QT3DSU32 GetSampleCount() const { return m_SampleCount; }
+ virtual bool IsImmutableTexture() const { return m_Immutable; }
+
+ /**
+ * @brief Bind a texture for shader access
+ *
+ *
+ * @return No return.
+ */
+ virtual void Bind() = 0;
+
+ virtual QT3DSU32 GetNumMipmaps() { return m_MaxMipLevel; }
+
+ /**
+ * @brief Query if texture needs coordinate swizzle
+ *
+ * @return texture swizzle mode
+ */
+ virtual NVRenderTextureSwizzleMode::Enum GetTextureSwizzleMode()
+ {
+ // if our backend supports hardware texture swizzle then there is no need for a shader
+ // swizzle
+ return (m_Backend->GetRenderBackendCap(
+ NVRenderBackend::NVRenderBackendCaps::TexSwizzle))
+ ? NVRenderTextureSwizzleMode::NoSwizzle
+ : m_Backend->GetTextureSwizzleMode(m_Format);
+ }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendTextureObject GetTextureObjectHandle()
+ {
+ return m_TextureHandle;
+ }
+
+ protected:
+ void applyTexParams();
+ void applyTexSwizzle();
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureCube.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureCube.h
new file mode 100644
index 00000000..7310d44d
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTextureCube.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_TEXTURE_CUBE_H
+#define QT3DS_RENDER_QT3DS_RENDER_TEXTURE_CUBE_H
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "render/Qt3DSRenderTextureBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderContextImpl;
+ class NVRenderTextureSampler;
+
+ class NVRenderTextureCube : public NVRenderTextureBase
+ {
+ private:
+ QT3DSU32 m_Width; ///< texture width (per face)
+ QT3DSU32 m_Height; ///< texture height (per face)
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] texTarget Texture target
+ *
+ * @return No return.
+ */
+ NVRenderTextureCube(
+ NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget = NVRenderTextureTargetType::TextureCube);
+
+ virtual ~NVRenderTextureCube();
+
+ /**
+ * @brief constructor
+ *
+ * @param[in] newBuffer Pointer to pixel buffer
+ * @param[in] inMipLevel Pointer to foundation
+ * @param[in] width Texture target
+ * @param[in] height Texture target
+ * @param[in] slices Texture target
+ * @param[in] format Texture target
+ *
+ * @return No return.
+ */
+ void SetTextureData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel,
+ NVRenderTextureCubeFaces::Enum inFace, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum format);
+
+ // Get the texture details for mipmap level 0 if it was set.
+ STextureDetails GetTextureDetails() const override;
+
+ /**
+ * @brief Bind a texture for shader access
+ *
+ *
+ * @return No return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief create a texture array object
+ *
+ *
+ * @ return a texture array object
+ */
+ static NVRenderTextureCube *Create(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTimerQuery.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTimerQuery.h
new file mode 100644
index 00000000..f909f374
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderTimerQuery.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_TIMER_QUERY_H
+#define QT3DS_RENDER_TIMER_QUERY_H
+
+#include "render/Qt3DSRenderQueryBase.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+
+ class NVRenderTimerQuery : public NVRenderQueryBase
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] fnd Pointer to foundation
+ *
+ * @return No return.
+ */
+ NVRenderTimerQuery(NVRenderContextImpl &context, NVFoundationBase &fnd);
+
+ ///< destructor
+ ~NVRenderTimerQuery();
+
+ /**
+ * @brief Get query type
+ *
+ * @return Return query type
+ */
+ NVRenderQueryType::Enum GetQueryType() const override
+ {
+ return NVRenderQueryType::Timer;
+ }
+
+ /**
+ * @brief Get a pointer to the foundation
+ *
+ * @return pointer to foundation
+ */
+ NVFoundationBase &GetFoundation() { return m_Foundation; }
+
+ /**
+ * @brief begin a query
+ *
+ * @return no return.
+ */
+ void Begin() override;
+
+ /**
+ * @brief end a query
+ *
+ * @return no return.
+ */
+ void End() override;
+
+ /**
+ * @brief Get the result of a query
+ *
+ * @param[out] params Contains result of query regarding query type
+ *
+ * @return no return.
+ */
+ void GetResult(QT3DSU32 *params) override;
+
+ /**
+ * @brief Get the result of a query
+ *
+ * @param[out] params Contains result of query regarding query type
+ *
+ * @return no return.
+ */
+ virtual void GetResult(QT3DSU64 *params);
+
+ /**
+ * @brief Places an absolute timer query into the render queue
+ * The result can be queried with GetResult
+ *
+ * @return no return.
+ */
+ virtual void SetTimerQuery();
+
+ /*
+ * @brief static creation function
+ *
+ * * @return a timer query object on success
+ */
+ static NVRenderTimerQuery *Create(NVRenderContextImpl &context);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexBuffer.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexBuffer.h
new file mode 100644
index 00000000..914afe27
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexBuffer.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_QT3DS_RENDER_VERTEX_BUFFER_H
+#define QT3DS_RENDER_QT3DS_RENDER_VERTEX_BUFFER_H
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Utils.h"
+#include "render/Qt3DSRenderDrawable.h"
+#include "render/Qt3DSRenderDataBuffer.h"
+
+namespace qt3ds {
+namespace render {
+
+ // forward declaration
+ class NVRenderContextImpl;
+
+ ///< Vertex buffer representation
+ class NVRenderVertexBuffer : public NVRenderDataBuffer
+ {
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to context
+ * @param[in] entries Vertex buffer attribute layout entries
+ * @param[in] size Size of the buffer
+ * @param[in] bindFlags Where to binf this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ *application.
+ *
+ * @return No return.
+ */
+ NVRenderVertexBuffer(NVRenderContextImpl &context, size_t size, QT3DSU32 stride,
+ NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usageType, NVDataRef<QT3DSU8> data);
+
+ ///< destructor
+ virtual ~NVRenderVertexBuffer();
+
+ /**
+ * @brief return vertex data stride
+ *
+ * @return data stride.
+ */
+ virtual QT3DSU32 GetStride() const { return m_Stride; }
+
+ /**
+ * @brief get vertex count
+ *
+ * @return vertex count
+ */
+ virtual QT3DSU32 GetNumVertexes() const
+ {
+ QT3DS_ASSERT((m_BufferCapacity % m_Stride) == 0);
+ return m_BufferCapacity / m_Stride;
+ }
+
+ /**
+ * @brief bind the buffer bypasses the context state
+ *
+ * @return no return.
+ */
+ void Bind() override;
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ NVRenderBackend::NVRenderBackendBufferObject GetBuffertHandle() const override
+ {
+ return m_BufferHandle;
+ }
+
+ // this will be obsolete
+ const void *GetImplementationHandle() const override
+ {
+ return reinterpret_cast<void *>(m_BufferHandle);
+ }
+
+ // No stride means that stride is calculated from the size of last entry found via entry
+ // offset
+ // Leaves this buffer temporarily bound.
+ static NVRenderVertexBuffer *Create(NVRenderContextImpl &context,
+ NVRenderBufferUsageType::Enum usageType, size_t size,
+ QT3DSU32 stride, NVConstDataRef<QT3DSU8> bufferData);
+
+ private:
+ QT3DSU32 m_Stride; ///< veretex data stride
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexShader.h b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexShader.h
new file mode 100644
index 00000000..0a96045b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/Qt3DSRenderVertexShader.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_VERTEX_SHADER_H
+#define QT3DS_RENDER_VERTEX_SHADER_H
+
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderShader.h"
+
+namespace qt3ds {
+namespace render {
+ using namespace foundation;
+
+ class NVRenderContextImpl;
+
+ ///< This class represents a vertex shader
+ class NVRenderVertexShader : public NVRenderShader
+ {
+
+ public:
+ /**
+ * @brief constructor
+ *
+ * @param[in] context Pointer to render context
+ * @param[in] fnd Pointer to foundation
+ * @param[in] source Pointer to shader source code
+ * @param[in] binaryProgram true if this is a binary program
+ *
+ * @return No return.
+ */
+ NVRenderVertexShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram);
+
+ /// @brief destructor
+ ~NVRenderVertexShader();
+
+ /**
+ * @brief Query if shader compiled succesfuly
+ *
+ * @return True if shader is valid.
+ */
+ bool IsValid() override { return (m_ShaderHandle != NULL); }
+
+ /**
+ * @brief get the backend object handle
+ *
+ * @return the backend object handle.
+ */
+ virtual NVRenderBackend::NVRenderBackendVertexShaderObject GetShaderHandle()
+ {
+ return m_ShaderHandle;
+ }
+
+ private:
+ NVRenderBackend::NVRenderBackendVertexShaderObject
+ m_ShaderHandle; ///< opaque backend handle
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h
new file mode 100644
index 00000000..00811539
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/Qt3DSRenderBackend.h
@@ -0,0 +1,2239 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_H
+#define QT3DS_RENDER_BACKEND_H
+
+/// @file Qt3DSRenderBackend.h
+/// NVRender backend definition.
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSNoCopy.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSBounds3.h"
+#include <EASTL/string.h>
+
+#include <QtGui/qsurfaceformat.h>
+
+namespace qt3ds {
+namespace render {
+
+#define HandleToID_cast(staticType, dynamicType, handle) \
+ static_cast<staticType>(reinterpret_cast<dynamicType>(handle))
+
+ class NVRenderBackend : public NVRefCounted, public NoCopy
+ {
+
+ public:
+ /// opaque buffer object handle
+ typedef struct _NVRenderBackendBufferObject *NVRenderBackendBufferObject;
+ /// opaque attribute layout object handle
+ typedef struct _NVRenderBackendAttribLayoutObject *NVRenderBackendAttribLayoutObject;
+ /// opaque input assembler object handle
+ typedef struct _NVRenderBackendInputAssemblerObject *NVRenderBackendInputAssemblerObject;
+ /// opaque texture object handle
+ typedef struct _NVRenderBackendTextureObject *NVRenderBackendTextureObject;
+ /// opaque sampler object handle
+ typedef struct _NVRenderBackendSamplerObject *NVRenderBackendSamplerObject;
+ /// opaque renderbuffer object handle
+ typedef struct _NVRenderBackendRenderbufferObject *NVRenderBackendRenderbufferObject;
+ /// opaque framebuffer object handle
+ typedef struct _NVRenderBackendRenderTargetObject *NVRenderBackendRenderTargetObject;
+ /// opaque vertex shader object handle
+ typedef struct _NVRenderBackendVertexShaderObject *NVRenderBackendVertexShaderObject;
+ /// opaque fragment shader object handle
+ typedef struct _NVRenderBackendFragmentShaderObject *NVRenderBackendFragmentShaderObject;
+ /// opaque tesselation control shader object handle
+ typedef struct _NVRenderBackendTessControlShaderObject
+ *NVRenderBackendTessControlShaderObject;
+ /// opaque tesselation evaluation shader object handle
+ typedef struct _NVRenderBackendTessEvaluationShaderObject
+ *NVRenderBackendTessEvaluationShaderObject;
+ /// opaque geometry shader object handle
+ typedef struct _NVRenderBackendGeometryShaderObject *NVRenderBackendGeometryShaderObject;
+ /// opaque compute shader object handle
+ typedef struct _NVRenderBackendComputeShaderObject *NVRenderBackendComputeShaderObject;
+ /// opaque shader program object handle
+ typedef struct _NVRenderBackendShaderProgramObject *NVRenderBackendShaderProgramObject;
+ /// opaque depth stencil state object handle
+ typedef struct _NVRenderBackendDepthStencilStateObject
+ *NVRenderBackendDepthStencilStateObject;
+ /// opaque rasterizer state object handle
+ typedef struct _NVRenderBackendRasterizerStateObject *NVRenderBackendRasterizerStateObject;
+ /// opaque query object handle
+ typedef struct _NVRenderBackendQueryObject *NVRenderBackendQueryObject;
+ /// opaque sync object handle
+ typedef struct _NVRenderBackendSyncObject *NVRenderBackendSyncObject;
+ /// opaque sync object handle
+ typedef struct _NVRenderBackendProgramPipeline *NVRenderBackendProgramPipeline;
+ /// opaque sync object handle
+ typedef struct _NVRenderBackendPathObject *NVRenderBackendPathObject;
+
+ // backend capability caps
+ typedef struct
+ {
+ enum Enum {
+ ConstantBuffer, ///< Constant buffer support query
+ DepthStencilTexture, ///< depth stencil texture format suport query
+ DxtImages, ///< DXT image support query
+ FpRenderTarget, ///< render to floating point target support query
+ MsTexture, ///< Multisample texture support query
+ TexSwizzle, ///< Texture swizzle support query
+ FastBlits, ///< Hardware supports fast blits
+ Tessellation, ///< Hardware supports tessellation
+ Compute, ///< Hardware supports compute shader
+ Geometry, ///< Hardware supports geometry shader
+ SampleQuery, ///< Hardware supports query calls of type samples
+ TimerQuery, ///< Hardware supports query calls of type timer
+ CommandSync, ///< Hardware supports command sync object
+ TextureArray, ///< Hardware supports texture arrays
+ StorageBuffer, ///< Hardware supports shader storage buffers
+ AtomicCounterBuffer, ///< Hardware supports atomic counter buffers
+ ShaderImageLoadStore, ///< Hardware supports shader image load store operations
+ ProgramPipeline, ///< Driver supports separate programs
+ PathRendering, ///< Driver support path rendering
+ AdvancedBlend, ///< Driver supports advanced blend modes
+ BlendCoherency, ///< Hardware supports blend coherency
+ gpuShader5, // for high precision sampling
+ AdvancedBlendKHR, ///< Driver supports advanced blend modes
+ };
+ } NVRenderBackendCaps;
+
+ // backend queries
+ typedef struct
+ {
+ enum Enum {
+ MaxTextureSize, ///< Return max supported texture size
+ MaxTextureArrayLayers, ///< Return max supported layer count for texture arrays
+ MaxConstantBufferSlots, ///< Return max supported constant buffe slots for a single
+ ///shader stage
+ MaxConstantBufferBlockSize ///< Return max supported size for a single constant
+ ///buffer block
+ };
+ } NVRenderBackendQuery;
+
+ /// backend interface
+
+ /**
+ * @brief get the backend type
+ *
+ * @return true backend type
+ */
+ virtual NVRenderContextType GetRenderContextType() const = 0;
+
+ /**
+ * @brief get the version of the shading language
+ * @return version string, must be copied by clients to be retained.
+ */
+ virtual const char *GetShadingLanguageVersion() = 0;
+
+ /**
+ * @brief get maximum supported texture image units that
+ * can be used to access texture maps from the vertex shader and the fragment processor
+ *combined.
+ *
+ * @return max texture size
+ */
+ virtual QT3DSU32 GetMaxCombinedTextureUnits() = 0;
+
+ /**
+ * @brief query Backend capabilities
+ *
+ * @param[in] inCap CAPS flag to query
+ * @ConstantBuffer, @DepthStencilTexture, ...
+ *
+ * @return true if supported
+ */
+ virtual bool GetRenderBackendCap(NVRenderBackendCaps::Enum inCap) const = 0;
+
+ /**
+ * @brief query Backend values
+ *
+ * @param[in] inQuery Query flag to get value for
+ * @MaxTextureSize, @MaxTextureArrayLayers,
+ *...
+ * @param[in/out] params the query result is stored here
+ *
+ * @return no return
+ */
+ virtual void GetRenderBackendValue(NVRenderBackendQuery::Enum inQuery,
+ QT3DSI32 *params) const = 0;
+
+ /**
+ * @brief query for bit depth of the depth buffer
+ *
+ * @return depth buffer bitplanes
+ */
+ virtual QT3DSU32 GetDepthBits() const = 0;
+
+ /**
+ * @brief query for bit depth of the stencil buffer
+ *
+ * @return stencil buffer bitplanes
+ */
+ virtual QT3DSU32 GetStencilBits() const = 0;
+
+ /*
+ * @brief set a backend rende state
+ *
+ * @param[in] bEnable enable/disable state
+ * @param[in] value type of state
+ *
+ * @return no return
+ */
+ virtual void SetRenderState(bool bEnable, const NVRenderState::Enum value) = 0;
+
+ /**
+ * @brief get a backend rende state
+ *
+ * @param[in] value type of state
+ *
+ * @return true if state enabled otherwise false
+ */
+ virtual bool GetRenderState(const NVRenderState::Enum value) = 0;
+
+ /**
+ * @brief get current depth function
+ *
+ * @return active depth function
+ */
+ virtual NVRenderBoolOp::Enum GetDepthFunc() = 0;
+
+ /**
+ * @brief create a depth stencil state object
+ *
+ * @param[in] enableDepth enable depth test
+ * @param[in] depthMask enable depth writes
+ * @param[in] depthFunc depth compare function
+ * @param[in] enableStencil enable stencil test
+ * @param[in] stencilFuncFront stencil setup front faces
+ * @param[in] stencilFuncBack stencil setup back faces
+ * @param[in] depthStencilOpFront depth/stencil operations front faces
+ * @param[in] depthStencilOpBack depth/stencil operations back faces
+ *
+ * @return opaque handle to state object
+ */
+ virtual NVRenderBackendDepthStencilStateObject
+ CreateDepthStencilState(bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc,
+ bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack) = 0;
+
+ /**
+ * @brief release a depth stencil state object
+ *
+ * @param[in] depthStencilState pointer to state object
+ *
+ * @return none
+ */
+ virtual void
+ ReleaseDepthStencilState(NVRenderBackendDepthStencilStateObject depthStencilState) = 0;
+
+ /**
+ * @brief create a rasterizer state object
+ *
+ * @param[in] depthBias any othe value than 0 enables depth bias
+ * @param[in] depthScale any othe value than 0 enables depth scale
+ * @param[in] cullFace select face to cull front or back
+ *
+ * @return opaque handle to state object
+ */
+ virtual NVRenderBackendRasterizerStateObject
+ CreateRasterizerState(QT3DSF32 depthBias, QT3DSF32 depthScale, NVRenderFaces::Enum cullFace) = 0;
+
+ /**
+ * @brief release a rasterizer state object
+ *
+ * @param[in] rasterizerState pointer to state object
+ *
+ * @return none
+ */
+ virtual void
+ ReleaseRasterizerState(NVRenderBackendRasterizerStateObject rasterizerState) = 0;
+
+ /**
+ * @brief set depth stencil state
+ *
+ * @param[in] depthStencilState pointer to state object
+ *
+ * @return none
+ */
+ virtual void
+ SetDepthStencilState(NVRenderBackendDepthStencilStateObject depthStencilState) = 0;
+
+ /**
+ * @brief set rasterizer state
+ *
+ * @param[in] rasterizerState pointer to state object
+ *
+ * @return none
+ */
+ virtual void SetRasterizerState(NVRenderBackendRasterizerStateObject rasterizerState) = 0;
+
+ /**
+ * @brief set current depth function
+ *
+ * @param[in] func type of function
+ *
+ * @return no return
+ */
+ virtual void SetDepthFunc(const NVRenderBoolOp::Enum func) = 0;
+
+ /**
+ * @brief query if depth write is enabled
+ *
+ * @return true if enabled
+ */
+ virtual bool GetDepthWrite() = 0;
+
+ /**
+ * @brief enable / disable depth writes
+ *
+ * @param[in] bEnable true for enable
+ *
+ * @return no return
+ */
+ virtual void SetDepthWrite(bool bEnable) = 0;
+
+ /**
+ * @brief enable / disable color channel writes
+ *
+ * @param[in] bRed true for enable red channel
+ * @param[in] bGreen true for enable green channel
+ * @param[in] bBlue true for enable blue channel
+ * @param[in] bAlpha true for enable alpha channel
+ *
+ * @return no return
+ */
+ virtual void SetColorWrites(bool bRed, bool bGreen, bool bBlue, bool bAlpha) = 0;
+
+ /**
+ * @brief enable / disable multisample rendering
+ *
+ * @param[in] bEnable true for enable
+ *
+ * @return no return
+ */
+ virtual void SetMultisample(bool bEnable) = 0;
+
+ /**
+ * @brief query blend functions
+ *
+ * @param[out] pBlendFuncArg blending functions
+ *
+ * @return no return
+ */
+ virtual void GetBlendFunc(NVRenderBlendFunctionArgument *pBlendFuncArg) = 0;
+
+ /**
+ * @brief set blend functions
+ *
+ * @param[in] pBlendFuncArg blending functions
+ *
+ * @return no return
+ */
+ virtual void SetBlendFunc(const NVRenderBlendFunctionArgument &blendFuncArg) = 0;
+
+ /**
+ * @brief set blend equation
+ *
+ * @param[in] pBlendEquArg blending equation
+ *
+ * @return no return
+ */
+ virtual void SetBlendEquation(const NVRenderBlendEquationArgument &pBlendEquArg) = 0;
+
+ /**
+ * @brief guarantee blend coherency
+ *
+ *
+ * @return no return
+ */
+ virtual void SetBlendBarrier(void) = 0;
+
+ /**
+ * @brief query scissor rectangle
+ *
+ * @param[out] pRect contains scissor rect
+ *
+ * @return no return
+ */
+ virtual void GetScissorRect(NVRenderRect *pRect) = 0;
+
+ /**
+ * @brief set scissor rectangle
+ *
+ * @param[out] pRect contains scissor rect
+ *
+ * @return no return
+ */
+ virtual void SetScissorRect(const NVRenderRect &rect) = 0;
+
+ /**
+ * @brief query viewport rectangle
+ *
+ * @param[out] pRect contains viewport rect
+ *
+ * @return no return
+ */
+ virtual void GetViewportRect(NVRenderRect *pRect) = 0;
+
+ /**
+ * @brief set viewport rectangle
+ *
+ * @param[out] pRect contains viewport rect
+ *
+ * @return no return
+ */
+ virtual void SetViewportRect(const NVRenderRect &rect) = 0;
+
+ /**
+ * @brief query viewport rectangle
+ *
+ * @param[in] clearColor clear color
+ *
+ * @return no return
+ */
+ virtual void SetClearColor(const QT3DSVec4 *pClearColor) = 0;
+
+ /**
+ * @brief query viewport rectangle
+ *
+ * @param[in] flags clear flags
+ *
+ * @return no return
+ */
+ virtual void Clear(NVRenderClearFlags flags) = 0;
+
+ /**
+ * @brief create a buffer object
+ *
+ * @param[in] size Size of the buffer
+ * @param[in] bindFlags Where to bind this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ *application.
+ *
+ * @return The created buffer object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendBufferObject CreateBuffer(size_t size,
+ NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usage,
+ const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief bind a buffer object
+ *
+ * @param[in] bo Pointer to buffer object
+ * @param[in] bindFlags Where to bind this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ *
+ * @return no return.
+ */
+ virtual void BindBuffer(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags) = 0;
+
+ /**
+ * @brief Release a single buffer object
+ *
+ * @param[in] bo Pointer to buffer object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseBuffer(NVRenderBackendBufferObject bo) = 0;
+
+ /**
+ * @brief update a whole buffer object
+ *
+ * @param[in] bo Pointer to buffer object
+ * @param[in] bindFlags Where to bind this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ * @param[in] size Size of the data buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ *application.
+ *
+ * @return no return.
+ */
+ virtual void UpdateBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags,
+ size_t size, NVRenderBufferUsageType::Enum usage,
+ const void *data) = 0;
+
+ /**
+ * @brief update a range of a buffer object
+ *
+ * @param[in] bo Pointer to buffer object
+ * @param[in] bindFlags Where to bind this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ * @param[in] size Size of the data buffer
+ * @param[in] usage Usage of the buffer (e.g. static, dynamic...)
+ * @param[in] data A pointer to the buffer data that is allocated by the
+ *application.
+ *
+ * @return no return.
+ */
+ virtual void UpdateBufferRange(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags, size_t offset,
+ size_t size, const void *data) = 0;
+
+ /**
+ * @brief Get a pointer to the buffer data ( GL(ES) >= 3 only )
+ *
+ * @param[in] bo Pointer to buffer object
+ * @param[in] bindFlags Where to bind this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ * @param[in] offset Byte offset into the data buffer
+ * @param[in] length Byte length of mapping size
+ * @param[in] access Access of the buffer (e.g. read, write, ...)
+ *
+ * @return pointer to mapped data or null.
+ */
+ virtual void *MapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags,
+ size_t offset, size_t length,
+ NVRenderBufferAccessFlags accessFlags) = 0;
+
+ /**
+ * @brief Unmap a previously mapped buffer ( GL(ES) >= 3 only )
+ * This functions transfers the content to the hardware buffer
+ *
+ * @param[in] bo Pointer to buffer object
+ * @param[in] bindFlags Where to bind this buffer (e.g. vertex, index, ...)
+ * For OpenGL this should be a single
+ *value
+ *
+ * @return true if successful
+ */
+ virtual bool UnmapBuffer(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags) = 0;
+
+ /**
+ * @brief Set a memory barrier
+ *
+ * @param[in] barriers Flags for barriers
+ *
+ * @return no return.
+ */
+ virtual void SetMemoryBarrier(NVRenderBufferBarrierFlags barriers) = 0;
+
+ /**
+ * @brief create a query object
+ *
+ * @return The created query object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendQueryObject CreateQuery() = 0;
+
+ /**
+ * @brief delete query objects
+ *
+ * @param[in] qo Handle to query object
+ *
+ * @return no return
+ */
+ virtual void ReleaseQuery(NVRenderBackendQueryObject qo) = 0;
+
+ /**
+ * @brief Start query recording
+ *
+ * @param[in] qo Handle to query object
+ * @param[in] type Type of query
+ *
+ * @return no return
+ */
+ virtual void BeginQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) = 0;
+
+ /**
+ * @brief End query recording
+ *
+ * @param[in] qo Handle to query object
+ * @param[in] type Type of query
+ *
+ * @return no return
+ */
+ virtual void EndQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) = 0;
+
+ /**
+ * @brief Get a query result
+ *
+ * @param[in] qo Handle to query object
+ * @param[in] type Type of query
+ * @param[out] params Contains result of query regarding query type
+ *
+ * @return no return
+ */
+ virtual void GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType, QT3DSU32 *params) = 0;
+
+ /**
+ * @brief Get a query result
+ *
+ * @param[in] qo Handle to query object
+ * @param[in] type Type of query
+ * @param[out] params Contains result of query regarding query type 64 bit returns
+ *
+ * @return no return
+ */
+ virtual void GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType, QT3DSU64 *params) = 0;
+
+ /**
+ * @brief Record the GPU time using the query object
+ *
+ * @param[in] qo Handle to query object
+ *
+ * @return no return
+ */
+ virtual void SetQueryTimer(NVRenderBackendQueryObject qo) = 0;
+
+ /**
+ * @brief create a sync object and place it in the command queue
+ *
+ * @param[in] tpye Type to sync
+ * @param[in] syncFlags Currently unused
+ *
+ * @return The created sync object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendSyncObject CreateSync(NVRenderSyncType::Enum tpye,
+ NVRenderSyncFlags syncFlags) = 0;
+
+ /**
+ * @brief delete sync object
+ *
+ * @param[in] so Handle to sync object
+ *
+ * @return no return
+ */
+ virtual void ReleaseSync(NVRenderBackendSyncObject so) = 0;
+
+ /**
+ * @brief wait for sync object to be signaled
+ *
+ * @param[in] so Handle to sync object
+ * @param[in] syncFlags Currently unused
+ * @param[in] timeout Currently ignored
+ *
+ * @return no return
+ */
+ virtual void WaitSync(NVRenderBackendSyncObject so, NVRenderCommandFlushFlags syncFlags,
+ QT3DSU64 timeout) = 0;
+
+ /**
+ * @brief create a render target object
+ *
+ *
+ * @return The created render target object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendRenderTargetObject CreateRenderTarget() = 0;
+
+ /**
+ * @brief Release a single render target object
+ *
+ * @param[in] rto Pointer to render target object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseRenderTarget(NVRenderBackendRenderTargetObject rto) = 0;
+
+ /**
+ * @brief Attach a renderbuffer object to the framebuffer
+ *
+ * @param[in] rto Pointer to render target object
+ * @param[in] attachment Attachment point (e.g COLOR0, DEPTH)
+ * @param[in] rbo Pointer to renderbuffer object
+ *
+ * @return no return.
+ */
+ virtual void RenderTargetAttach(NVRenderBackendRenderTargetObject rto,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendRenderbufferObject rbo) = 0;
+
+ /**
+ * @brief Attach a texture object to the render target
+ *
+ * @param[in] rto Pointer to render target object
+ * @param[in] attachment Attachment point (e.g COLOR0, DEPTH)
+ * @param[in] to Pointer to texture object
+ * @param[in] target Attachment texture target
+ *
+ * @return no return.
+ */
+ virtual void RenderTargetAttach(
+ NVRenderBackendRenderTargetObject rto, NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target = NVRenderTextureTargetType::Texture2D) = 0;
+
+ /**
+ * @brief Attach a texture object to the render target
+ *
+ * @param[in] rto Pointer to render target object
+ * @param[in] attachment Attachment point (e.g COLOR0, DEPTH)
+ * @param[in] to Pointer to texture object
+ * @param[in] level Texture mip level
+ * @param[in] layer Texture layer or slice
+ *
+ * @return no return.
+ */
+ virtual void RenderTargetAttach(NVRenderBackendRenderTargetObject rto,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to, QT3DSI32 level,
+ QT3DSI32 layer) = 0;
+
+ /**
+ * @brief Make a render target active
+ *
+ * @param[in] rto Pointer to render target object
+ *
+ * @return no return.
+ */
+ virtual void SetRenderTarget(NVRenderBackendRenderTargetObject rto) = 0;
+
+ /**
+ * @brief Check if a render target is ready for render
+ *
+ * @param[in] rto Pointer to render target object
+ *
+ * @return true if usable.
+ */
+ virtual bool RenderTargetIsValid(NVRenderBackendRenderTargetObject rto) = 0;
+
+ /**
+ * @brief Make a render target active for reading
+ *
+ * @param[in] rto Pointer to render target object
+ *
+ * @return no return.
+ */
+ virtual void SetReadTarget(NVRenderBackendRenderTargetObject rto) = 0;
+
+ /**
+ * @brief Set active buffers for drawing
+ *
+ * @param[in] rto Pointer to render target object
+ * @param[in] inDrawBufferSet Pointer to array of enabled render targets
+ *
+ * @return no return.
+ */
+ virtual void SetDrawBuffers(NVRenderBackendRenderTargetObject rto,
+ NVConstDataRef<QT3DSI32> inDrawBufferSet) = 0;
+
+ /**
+ * @brief Set active buffer for reading
+ *
+ * @param[in] rto Pointer to render target object
+ * @param[in] inReadFace Buffer to read from
+ *
+ * @return no return.
+ */
+ virtual void SetReadBuffer(NVRenderBackendRenderTargetObject rto,
+ NVReadFaces::Enum inReadFace) = 0;
+
+ /**
+ * @brief Copy framebuffer attachments. Source is set with SetReadTarget dest with
+ * SetRenderTarget
+ *
+ * @param[in] srcX0 Lower left X coord of source rectangle
+ * @param[in] srcY0 Lower left Y coord of source rectangle
+ * @param[in] srcX1 Upper right X coord of source rectangle
+ * @param[in] srcY1 Upper right Y coord of source rectangle
+ * @param[in] dstX0 Lower left X coord of dest rectangle
+ * @param[in] dstY0 Lower left Y coord of dest rectangle
+ * @param[in] dstX1 Upper right X coord of dest rectangle
+ * @param[in] dstY1 Upper right Y coord of dest rectangle
+ * @param[in] inDrawBufferSet pointer to array of enabled render targets
+ * @param[in] filter Copy filter method (NEAREST or LINEAR)
+ *
+ * @return no return.
+ */
+ virtual void BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter) = 0;
+
+ /**
+ * @brief create a render buffer object
+ *
+ * @param[in] storageFormat Format of the buffer
+ * @param[in] width Buffer with
+ * @param[in] height Buffer height
+ *
+ * @return The created render buffer object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendRenderbufferObject
+ CreateRenderbuffer(NVRenderRenderBufferFormats::Enum storageFormat, size_t width,
+ size_t height) = 0;
+
+ /**
+ * @brief Release a single renderbuffer object
+ *
+ * @param[in] bo Pointer to renderbuffer object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseRenderbuffer(NVRenderBackendRenderbufferObject rbo) = 0;
+
+ /**
+ * @brief resize a render buffer object
+ *
+ * @param[in] storageFormat Format of the buffer
+ * @param[in] width Buffer with
+ * @param[in] height Buffer height
+ *
+ * @return True on success
+ */
+ virtual bool ResizeRenderbuffer(NVRenderBackendRenderbufferObject rbo,
+ NVRenderRenderBufferFormats::Enum storageFormat,
+ size_t width, size_t height) = 0;
+
+ /**
+ * @brief create a texture object
+ *
+ * @return The created texture object or NULL if the creation failed..
+ */
+ virtual NVRenderBackendTextureObject CreateTexture() = 0;
+
+ /**
+ * @brief set texture data for a 2D texture
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] level Texture mip level
+ * @param[in] internalFormat format of the texture
+ * @param[in] width texture width
+ * @param[in] height texture height
+ * @param[in] border border
+ * @param[in] format format of provided pixel data
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width,
+ size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief set texture data for the face of a Cube map
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target face
+ * @param[in] level Texture mip level
+ * @param[in] internalFormat format of the texture
+ * @param[in] width texture width
+ * @param[in] height texture height
+ * @param[in] border border
+ * @param[in] format format of provided pixel data
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetTextureDataCubeFace(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief create a storage for a 2D texture including mip levels
+ * Note that this makes texture immutable in size and format
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] levels Texture mip level count
+ * @param[in] internalFormat format of the texture
+ * @param[in] width texture width
+ * @param[in] height texture height
+ *
+ * @return No return
+ */
+ virtual void CreateTextureStorage2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 levels,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height) = 0;
+
+ /**
+ * @brief set texture sub data for a 2D texture
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] level Texture mip level
+ * @param[in] xOffset Texture x offset
+ * @param[in] yOffset Texture y offset
+ * @param[in] width Texture width
+ * @param[in] height Texture height
+ * @param[in] border border
+ * @param[in] format format of texture
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetTextureSubData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ QT3DSI32 xOffset, QT3DSI32 yOffset, size_t width, size_t height,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief set compressed texture data for a 2D texture
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] level Texture mip level
+ * @param[in] internalFormat format of the texture
+ * @param[in] width texture width
+ * @param[in] height texture height
+ * @param[in] border border
+ * @param[in] imageSize image size in bytes located at hostPtr
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetCompressedTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height, QT3DSI32 border,
+ size_t imageSize, const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief set compressed texture data for a Cubemap face
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] level Texture mip level
+ * @param[in] internalFormat format of the texture
+ * @param[in] width texture width
+ * @param[in] height texture height
+ * @param[in] border border
+ * @param[in] imageSize image size in bytes located at hostPtr
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetCompressedTextureDataCubeFace(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ size_t imageSize, const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief set compressed texture sub data for a 2D texture
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] level Texture mip level
+ * @param[in] xOffset Texture x offset
+ * @param[in] yOffset Texture y offset
+ * @param[in] width texture width
+ * @param[in] height texture height
+ * @param[in] format format of provided pixel data
+ * @param[in] imageSize image size in bytes located at hostPtr
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetCompressedTextureSubData2D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ QT3DSI32 xOffset, QT3DSI32 yOffset, size_t width, size_t height,
+ NVRenderTextureFormats::Enum format, size_t imageSize, const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief establish a multisampled 2D texture
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D MS
+ * @param[in] samples Textures sample count
+ * @param[in] internalFormat Format of the texture
+ * @param[in] width Texture width
+ * @param[in] height Texture height
+ * @param[in] bool Fixed sample locations
+ *
+ * @return No return
+ */
+ virtual void SetMultisampledTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ size_t samples,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height,
+ bool fixedsamplelocations) = 0;
+
+ /**
+ * @brief set texture data for a 3D texture or 2D texture array
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] level Texture mip level
+ * @param[in] internalFormat format of the texture
+ * @param[in] width texture width
+ * @param[in] height texture height
+ * @param[in] depth texture depth or slice count
+ * @param[in] border border
+ * @param[in] format format of provided pixel data
+ * @param[in] hostPtr A pointer to the buffer data that is allocated by the
+ * application.
+ *
+ * @return No return
+ */
+ virtual void SetTextureData3D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width,
+ size_t height, size_t depth, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) = 0;
+
+ /**
+ * @brief generate mipmap levels
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Texture target 2D,...
+ * @param[in] hint How to generate mips (Nicest)
+ *
+ * @return No return
+ */
+ virtual void GenerateMipMaps(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderHint::Enum genType) = 0;
+
+ /**
+ * @brief bind a texture object
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] target Where to bind this texture (e.g. 2D, 3D, ...)
+ * @param[in] unit Which unit to bind this texture
+ *
+ * @return no return.
+ */
+ virtual void BindTexture(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 unit) = 0;
+
+ /**
+ * @brief bind a image/texture object
+ *
+ * @param[in] to Pointer to texture object
+ * @param[in] unit Which unit to bind this texture
+ * @param[in] level Which level to bind
+ * @param[in] layered Bind layered texture (cube map, array,... )
+ * @param[in] level Specify layer. Only valid of layered=false.
+ * @param[in] access Access mode ( read, write, read-write )
+ * @param[in] format Texture format must be compatible with Image format
+ *
+ * @return no return.
+ */
+ virtual void BindImageTexture(NVRenderBackendTextureObject to, QT3DSU32 unit, QT3DSI32 level,
+ bool layered, QT3DSI32 layer,
+ NVRenderImageAccessType::Enum accessFlags,
+ NVRenderTextureFormats::Enum format) = 0;
+
+ /**
+ * @brief Release a single texture object
+ *
+ * @param[in] to Pointer to buffer object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseTexture(NVRenderBackendTextureObject to) = 0;
+
+ /**
+ * @brief query texture swizzle mode
+ * This is mainly for luminance, alpha replacement with R8 formats
+ *
+ * @param[in] inFormat input texture format to check
+ *
+ * @return texture swizzle mode
+ */
+ virtual NVRenderTextureSwizzleMode::Enum
+ GetTextureSwizzleMode(const NVRenderTextureFormats::Enum inFormat) const = 0;
+
+ /**
+ * @ brief create a sampler
+ *
+ * @param[in] minFilter Texture min filter
+ * @param[in] magFilter Texture mag filter
+ * @param[in] wrapS Texture coord generation for S
+ * @param[in] wrapT Texture coord generation for T
+ * @param[in] wrapR Texture coord generation for R
+ * @param[in] minLod Texture min level of detail
+ * @param[in] maxLod Texture max level of detail
+ * @param[in] lodBias Texture level of detail example
+ * @param[in] compareMode Texture compare mode
+ * @param[in] compareFunc Texture compare function
+ * @param[in] anisoFilter Aniso filter value [1.0, 16.0]
+ * @param[in] borderColor Texture border color float[4]
+ *
+ * @return The created sampler object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendSamplerObject CreateSampler(
+ NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear,
+ NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear,
+ NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge,
+ QT3DSI32 minLod = -1000, QT3DSI32 maxLod = 1000, QT3DSF32 lodBias = 0.0,
+ NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare,
+ NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual,
+ QT3DSF32 anisotropy = 1.0, QT3DSF32 *borderColor = NULL) = 0;
+
+ /**
+ * @ brief update a sampler
+ *
+ * @param[in] so Pointer to sampler object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] minFilter Texture min filter
+ * @param[in] magFilter Texture mag filter
+ * @param[in] wrapS Texture coord generation for S
+ * @param[in] wrapT Texture coord generation for T
+ * @param[in] wrapR Texture coord generation for R
+ * @param[in] minLod Texture min level of detail
+ * @param[in] maxLod Texture max level of detail
+ * @param[in] lodBias Texture level of detail bias (unused)
+ * @param[in] compareMode Texture compare mode
+ * @param[in] compareFunc Texture compare function
+ * @param[in] anisoFilter Aniso filter value [1.0, 16.0]
+ * @param[in] borderColor Texture border color float[4] (unused)
+ *
+ * @return No return
+ */
+ virtual void UpdateSampler(
+ NVRenderBackendSamplerObject so, NVRenderTextureTargetType::Enum target,
+ NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear,
+ NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear,
+ NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge,
+ QT3DSF32 minLod = -1000.0, QT3DSF32 maxLod = 1000.0, QT3DSF32 lodBias = 0.0,
+ NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare,
+ NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual,
+ QT3DSF32 anisotropy = 1.0, QT3DSF32 *borderColor = NULL) = 0;
+
+ /**
+ * @ brief Update a textures swizzle mode
+ *
+ * @param[in] so Pointer to texture object
+ * @param[in] target Texture target 2D, 3D
+ * @param[in] swizzleMode Texture swizzle mode
+ *
+ * @return No return
+ */
+ virtual void UpdateTextureSwizzle(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderTextureSwizzleMode::Enum swizzleMode) = 0;
+
+ /**
+ * @ brief Update state belonging to a texture object
+ *
+ * @param[in] so Pointer to texture object
+ * @param[in] target Texture target 2D, 3D, Cube
+ * @param[in] baseLevel Texture base level
+ * @param[in] maxLevel Texture max level
+ *
+ * @return No return
+ */
+ virtual void UpdateTextureObject(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSI32 baseLevel,
+ QT3DSI32 maxLevel) = 0;
+
+ /**
+ * @brief Release a single sampler object
+ *
+ * @param[in] so Pointer to sampler object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseSampler(NVRenderBackendSamplerObject so) = 0;
+
+ /**
+ * @brief create a attribute layout object
+ *
+ * @param[in] attribs Array off vertex attributes.
+ *
+ * @return The created attribute layout object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendAttribLayoutObject
+ CreateAttribLayout(NVConstDataRef<NVRenderVertexBufferEntry> attribs) = 0;
+
+ /**
+ * @brief Release a attribute layoutr object
+ *
+ * @param[in] ao Pointer to attribute layout object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseAttribLayout(NVRenderBackendAttribLayoutObject ao) = 0;
+
+ /**
+ * @brief create a input assembler object
+ *
+ * @param[in] attribLayout Pointer to NVRenderBackendAttribLayoutObject object
+ * @param[in] buffers list of vertex buffers
+ * @param[in] indexBuffer index buffer object
+ * @param[in] strides list of strides of the buffer
+ * @param[in] offsets list of offsets into the buffer
+ * @param[in] patchVertexCount vertext count for a patch. Only valid for patch primitives
+ *
+ * @return The created input assembler object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendInputAssemblerObject
+ CreateInputAssembler(NVRenderBackendAttribLayoutObject attribLayout,
+ NVConstDataRef<NVRenderBackendBufferObject> buffers,
+ const NVRenderBackendBufferObject indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets,
+ QT3DSU32 patchVertexCount) = 0;
+
+ /**
+ * @brief Release a input assembler object
+ *
+ * @param[in] iao Pointer to attribute layout object
+ *
+ * @return no return.
+ */
+ virtual void ReleaseInputAssembler(NVRenderBackendInputAssemblerObject iao) = 0;
+
+ /**
+ * @brief Set a input assembler object.
+ * This setup the render engine vertex assmebly
+ *
+ * @param[in] iao Pointer to attribute layout object
+ * @param[in] po Pointer program object
+ *
+ * @return false if it fails.
+ */
+ virtual bool SetInputAssembler(NVRenderBackendInputAssemblerObject iao,
+ NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief Set the per patch vertex count
+ *
+ * @param[in] iao Pointer to attribute layout object
+ * @param[in] count Count of vertices per patch
+ *
+ * @return false if it fails.
+ */
+ virtual void SetPatchVertexCount(NVRenderBackendInputAssemblerObject iao, QT3DSU32 count) = 0;
+
+ /**
+ * @brief create a vertex shader object
+ *
+ * @param[in] source Pointer to shader source
+ * @param[in/out] errorMessage Pointer to copy the error message
+ * @param[in] binary True if the source is actually a binary program
+ *
+ * @return The created vertex shader object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendVertexShaderObject CreateVertexShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage,
+ bool binary) = 0;
+
+ /**
+ * @brief release a vertex shader object
+ *
+ * @param[in] vso Pointer to vertex shader object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseVertexShader(NVRenderBackendVertexShaderObject vso) = 0;
+
+ /**
+ * @brief create a fragment shader object
+ *
+ * @param[in] source Pointer to shader source
+ * @param[in/out] errorMessage Pointer to copy the error message
+ * @param[in] binary True if the source is actually a binary program
+ *
+ * @return The created vertex shader object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendFragmentShaderObject
+ CreateFragmentShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) = 0;
+
+ /**
+ * @brief release a fragment shader object
+ *
+ * @param[in] vso Pointer to fragment shader object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseFragmentShader(NVRenderBackendFragmentShaderObject fso) = 0;
+
+ /**
+ * @brief create a tessellation control shader object
+ *
+ * @param[in] source Pointer to shader source
+ * @param[in/out] errorMessage Pointer to copy the error message
+ * @param[in] binary True if the source is actually a binary program
+ *
+ * @return The created tessellation control shader object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendTessControlShaderObject
+ CreateTessControlShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) = 0;
+
+ /**
+ * @brief release a tessellation control shader object
+ *
+ * @param[in] tcso Pointer to tessellation control shader object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseTessControlShader(NVRenderBackendTessControlShaderObject tcso) = 0;
+
+ /**
+ * @brief create a tessellation evaluation shader object
+ *
+ * @param[in] source Pointer to shader source
+ * @param[in/out] errorMessage Pointer to copy the error message
+ * @param[in] binary True if the source is actually a binary program
+ *
+ * @return The created tessellation evaluation shader object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendTessEvaluationShaderObject
+ CreateTessEvaluationShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) = 0;
+
+ /**
+ * @brief release a tessellation evaluation shader object
+ *
+ * @param[in] tcso Pointer to tessellation evaluation shader object
+ *
+ * @return No Return.
+ */
+ virtual void
+ ReleaseTessEvaluationShader(NVRenderBackendTessEvaluationShaderObject teso) = 0;
+
+ /**
+ * @brief create a geometry shader object
+ *
+ * @param[in] source Pointer to shader source
+ * @param[in/out] errorMessage Pointer to copy the error message
+ * @param[in] binary True if the source is actually a binary program
+ *
+ * @return The created geometry shader object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendGeometryShaderObject
+ CreateGeometryShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) = 0;
+
+ /**
+ * @brief release a geometry shader object
+ *
+ * @param[in] tcso Pointer to geometry shader object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseGeometryShader(NVRenderBackendGeometryShaderObject gso) = 0;
+
+ /**
+ * @brief create a compute shader object
+ *
+ * @param[in] source Pointer to shader source
+ * @param[in/out] errorMessage Pointer to copy the error message
+ * @param[in] binary True if the source is actually a binary program
+ *
+ * @return The created compute shader object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendComputeShaderObject CreateComputeShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage,
+ bool binary) = 0;
+
+ /**
+ * @brief release a compute shader object
+ *
+ * @param[in] cso Pointer to compute shader object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseComputeShader(NVRenderBackendComputeShaderObject cso) = 0;
+
+ /**
+ * @brief attach a vertex shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] vso Pointer to vertex shader object
+ *
+ * @return No Return.
+ */
+ virtual void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendVertexShaderObject vso) = 0;
+
+ /**
+ * @brief detach a vertex shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] vso Pointer to vertex shader object
+ *
+ * @return No Return.
+ */
+ virtual void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendVertexShaderObject vso) = 0;
+
+ /**
+ * @brief attach a fragment shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] fso Pointer to fragment shader object
+ *
+ * @return No Return.
+ */
+ virtual void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendFragmentShaderObject fso) = 0;
+
+ /**
+ * @brief detach a fragment shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] fso Pointer to fragment shader object
+ *
+ * @return No Return.
+ */
+ virtual void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendFragmentShaderObject fso) = 0;
+
+ /**
+ * @brief attach a tessellation control shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] tcso Pointer to tessellation control shader object
+ *
+ * @return No Return.
+ */
+ virtual void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessControlShaderObject tcso) = 0;
+
+ /**
+ * @brief detach a tessellation control shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] tcso Pointer to tessellation control shader object
+ *
+ * @return No Return.
+ */
+ virtual void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessControlShaderObject tcso) = 0;
+
+ /**
+ * @brief attach a tessellation evaluation shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] teso Pointer to tessellation evaluation shader object
+ *
+ * @return No Return.
+ */
+ virtual void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessEvaluationShaderObject teso) = 0;
+
+ /**
+ * @brief detach a tessellation evaluation shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] teso Pointer to tessellation evaluation shader object
+ *
+ * @return No Return.
+ */
+ virtual void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessEvaluationShaderObject teso) = 0;
+
+ /**
+ * @brief attach a geometry shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] teso Pointer to geometry shader object
+ *
+ * @return No Return.
+ */
+ virtual void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendGeometryShaderObject gso) = 0;
+
+ /**
+ * @brief detach a geometry shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] teso Pointer to geometry shader object
+ *
+ * @return No Return.
+ */
+ virtual void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendGeometryShaderObject gso) = 0;
+
+ /**
+ * @brief attach a compute shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] cso Pointer to compute shader object
+ *
+ * @return No Return.
+ */
+ virtual void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendComputeShaderObject cso) = 0;
+
+ /**
+ * @brief detach a compute shader object to a program object
+ *
+ * @param[in] po Pointer to program object
+ * @param[in] cso Pointer to compute shader object
+ *
+ * @return No Return.
+ */
+ virtual void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendComputeShaderObject cso) = 0;
+
+ /**
+ * @brief create a shader program object
+ *
+ * @param[in] isSeparable Tell the backend that this program is separable
+ *
+ * @return The created shader program object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendShaderProgramObject CreateShaderProgram(bool isSeparable) = 0;
+
+ /**
+ * @brief release a shader program object
+ *
+ * @param[in] po Pointer to shader program object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseShaderProgram(NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief link a shader program object
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in/out] errorMessage Pointer to copy the error message
+ *
+ * @return True if program is succesful linked.
+ */
+ virtual bool LinkProgram(NVRenderBackendShaderProgramObject po,
+ eastl::string &errorMessage) = 0;
+
+ /**
+ * @brief Make a program current
+ *
+ * @param[in] po Pointer to shader program object
+ *
+ * @return No return
+ */
+ virtual void SetActiveProgram(NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief create a program pipeline object
+ *
+ *
+ * @return The created program pipeline object or NULL if the creation failed.
+ */
+ virtual NVRenderBackendProgramPipeline CreateProgramPipeline() = 0;
+
+ /**
+ * @brief release a program pipeline object
+ *
+ * @param[in] ppo Pointer to program pipeline object
+ *
+ * @return No Return.
+ */
+ virtual void ReleaseProgramPipeline(NVRenderBackendProgramPipeline ppo) = 0;
+
+ /**
+ * @brief Make a program pipeline current
+ *
+ * @param[in] ppo Pointer to program pipeline object
+ *
+ * @return No return
+ */
+ virtual void SetActiveProgramPipeline(NVRenderBackendProgramPipeline ppo) = 0;
+
+ /**
+ * @brief Make a program stage active for this pipeline
+ *
+ * @param[in] ppo Pointer to program pipeline object
+ * @param[in] flags Shader stage flags to which this po is bound to
+ * @param[in] po Pointer to shader program object
+ *
+ * @return No return
+ */
+ virtual void SetProgramStages(NVRenderBackendProgramPipeline ppo,
+ NVRenderShaderTypeFlags flags,
+ NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief Runs a compute program
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] numGroupsX The number of work groups to be launched in the X
+ * dimension
+ * @param[in] numGroupsY The number of work groups to be launched in the Y
+ * dimension
+ * @param[in] numGroupsZ The number of work groups to be launched in the Z
+ * dimension
+ *
+ * @return No return
+ */
+ virtual void DispatchCompute(NVRenderBackendShaderProgramObject po, QT3DSU32 numGroupsX,
+ QT3DSU32 numGroupsY, QT3DSU32 numGroupsZ) = 0;
+
+ /**
+ * @brief Query constant count for a program object
+ *
+ * @param[in] po Pointer to shader program object
+ *
+ * @return Return active constant count
+ */
+ virtual QT3DSI32 GetConstantCount(NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief Query constant buffer count for a program object
+ *
+ * @param[in] po Pointer to shader program object
+ *
+ * @return Return active constant buffer count
+ */
+ virtual QT3DSI32 GetConstantBufferCount(NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief Query constant information by ID
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] id Constant ID
+ * @param[in] bufSize Max char for nameBuf
+ * @param[out] numElem Usually one unless for arrays
+ * @param[out] type Constant data type (QT3DSVec4, QT3DSVec3,...)
+ * @param[out] binding Unit binding point for samplers and images
+ * @param[out] nameBuf Name of the constant
+ *
+ * @return Return current constant location or -1 if not found
+ */
+ virtual QT3DSI32 GetConstantInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 bufSize, QT3DSI32 *numElem,
+ NVRenderShaderDataTypes::Enum *type, QT3DSI32 *binding,
+ char *nameBuf) = 0;
+
+ /**
+ * @brief Query constant buffer information by ID
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] id Constant buffer ID
+ * @param[in] nameBufSize Size of nameBuf
+ * @param[out] paramCount Count ot parameter contained in the buffer
+ * @param[out] bufferSize Data size of the constant buffer
+ * @param[out] length Actual characters written
+ * @param[out] nameBuf Receives the name of the buffer
+ *
+ * @return Return current constant buffer location or -1 if not found
+ */
+ virtual QT3DSI32 GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length,
+ char *nameBuf) = 0;
+
+ /**
+ * @brief Query constant buffer param indices
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] id Constant buffer ID
+ * @param[out] indices Receives the indices of the uniforms within the
+ * constant buffer
+ *
+ * @return no return value
+ */
+ virtual void GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSI32 *indices) = 0;
+
+ /**
+ * @brief Query constant buffer param info by indices
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] count Number of indices
+ * @param[in] indices The indices of the uniforms within the constant
+ * buffer
+ * @param[out] type Array of param types ( float ,int, ...)
+ * @param[out] size Array of param size
+ * @param[out] offset Array of param offsets within the constant buffer
+ *
+ * @return no return value
+ */
+ virtual void GetConstantBufferParamInfoByIndices(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 count, QT3DSU32 *indices, QT3DSI32 *type,
+ QT3DSI32 *size, QT3DSI32 *offset) = 0;
+
+ /**
+ * @brief Bind program constant block
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] blockIndex Constant block index returned by
+ * GetConstantBufferInfoByID
+ * @param[in] binding Block binding location which should be the same as index
+ * in ProgramSetConstantBlock
+ *
+ * @return No return
+ */
+ virtual void ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 blockIndex, QT3DSU32 binding) = 0;
+
+ /**
+ * @brief Bind constant buffer for usage in the current active shader program
+ *
+ * @param[in] index Constant ID
+ * @param[in] bo Pointer to constant buffer object
+ *
+ * @return No return
+ */
+ virtual void ProgramSetConstantBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) = 0;
+
+ /**
+ * @brief Query storage buffer count for a program object
+ *
+ * @param[in] po Pointer to shader program object
+ *
+ * @return Return active storage buffer count
+ */
+ virtual QT3DSI32 GetStorageBufferCount(NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief Query storage buffer information by ID
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] id Storage buffer ID
+ * @param[in] nameBufSize Size of nameBuf
+ * @param[out] paramCount Count of parameter contained in the buffer
+ * @param[out] bufferSize Data size of the constant buffer
+ * @param[out] length Actual characters written
+ * @param[out] nameBuf Receives the name of the buffer
+ *
+ * @return Return current storage buffer binding or -1 if not found
+ */
+ virtual QT3DSI32 GetStorageBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length, char *nameBuf) = 0;
+
+ /**
+ * @brief Bind a storage buffer for usage in the current active shader program
+ *
+ * @param[in] index Constant ID
+ * @param[in] bo Pointer to storage buffer object
+ *
+ * @return No return
+ */
+ virtual void ProgramSetStorageBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) = 0;
+
+ /**
+ * @brief Query atomic counter buffer count for a program object
+ *
+ * @param[in] po Pointer to shader program object
+ *
+ * @return Return active atomic buffer count
+ */
+ virtual QT3DSI32 GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject po) = 0;
+
+ /**
+ * @brief Query atomic counter buffer information by ID
+ *
+ * @param[in] po Pointer to shader program object
+ * @param[in] id Storage buffer ID
+ * @param[in] nameBufSize Size of nameBuf
+ * @param[out] paramCount Count of parameter contained in the buffer
+ * @param[out] bufferSize Data size of the constant buffer
+ * @param[out] length Actual characters written
+ * @param[out] nameBuf Receives the name of the buffer
+ *
+ * @return Return current storage buffer binding or -1 if not found
+ */
+ virtual QT3DSI32 GetAtomicCounterBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length,
+ char *nameBuf) = 0;
+
+ /**
+ * @brief Bind a atomic counter buffer for usage in the current active shader program
+ *
+ * @param[in] index Constant ID
+ * @param[in] bo Pointer to atomic counter buffer object
+ *
+ * @return No return
+ */
+ virtual void ProgramSetAtomicCounterBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) = 0;
+
+ /**
+ * @brief Set constant value
+ *
+ * @param[in] po Pointer program object
+ * @param[in] id Constant ID
+ * @param[in] type Constant data type (QT3DSVec4, QT3DSVec3,...)
+ * @param[in] count Element count
+ * @param[in] value Pointer to constant value
+ * @param[in] transpose Transpose a matrix
+ *
+ * @return No return
+ */
+ virtual void SetConstantValue(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count,
+ const void *value, bool transpose = false) = 0;
+
+ /**
+ * @brief Draw the current active vertex buffer
+ *
+ * @param[in] drawMode Draw mode (Triangles, ....)
+ * @param[in] start Start vertex
+ * @param[in] count Vertex count
+ *
+ * @return no return.
+ */
+ virtual void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 start, QT3DSU32 count) = 0;
+
+ /**
+ * @brief Draw the current active vertex buffer using an indirect buffer
+ * This means the setup of the draw call is stored in a buffer bound to
+ * NVRenderBufferBindValues::Draw_Indirect
+ *
+ * @param[in] drawMode Draw mode (Triangles, ....)
+ * @param[in] indirect Offset into a indirect drawing setup buffer
+ *
+ * @return no return.
+ */
+ virtual void DrawIndirect(NVRenderDrawMode::Enum drawMode, const void *indirect) = 0;
+
+ /**
+ * @brief Draw the current active index buffer
+ *
+ * @param[in] drawMode Draw mode (Triangles, ....)
+ * @param[in] count Index count
+ * @param[in] type Index type (QT3DSU16, QT3DSU8)
+ * @param[in] indices Pointer to index buffer. In the case of buffer objects
+ * this is an offset into the active index buffer
+ *object.
+ *
+ * @return no return.
+ */
+ virtual void DrawIndexed(NVRenderDrawMode::Enum drawMode, QT3DSU32 count,
+ NVRenderComponentTypes::Enum type, const void *indices) = 0;
+
+ /**
+ * @brief Draw the current active index buffer using an indirect buffer
+ * This means the setup of the draw call is stored in a buffer bound to
+ * NVRenderBufferBindValues::Draw_Indirect
+ *
+ * @param[in] drawMode Draw mode (Triangles, ....)
+ * @param[in] type Index type (QT3DSU16, QT3DSU8)
+ * @param[in] indices Offset into a indirect drawing setup buffer
+ *
+ * @return no return.
+ */
+ virtual void DrawIndexedIndirect(NVRenderDrawMode::Enum drawMode,
+ NVRenderComponentTypes::Enum type,
+ const void *indirect) = 0;
+
+ /**
+ * @brief Read a pixel rectangle from render target (from bottom left)
+ *
+ * @param[in] rto Pointer to render target object
+ * @param[in] x Windows X start coord
+ * @param[in] y Windows Y start coord
+ * @param[in] width Read width dim
+ * @param[in] height Read height dim
+ * @param[out] pixels Returned pixel data
+ *
+ * @return No return
+ */
+ virtual void ReadPixel(NVRenderBackendRenderTargetObject rto, QT3DSI32 x, QT3DSI32 y, QT3DSI32 width,
+ QT3DSI32 height, NVRenderReadPixelFormats::Enum inFormat,
+ void *pixels) = 0;
+
+ /**
+ * @brief Create a NV path render object
+ *
+ * @param[in] range Number of internal objects
+ *
+ * @return return path object on success or NULL
+ */
+ virtual NVRenderBackendPathObject CreatePathNVObject(size_t range) = 0;
+
+ /**
+ * @brief Relase a NV path render object
+ *
+ * @param[in] po Created path object
+ * @param[in] range Number of internal objects
+ *
+ * @return return path object on success or NULL
+ */
+ virtual void ReleasePathNVObject(NVRenderBackendPathObject po, size_t range) = 0;
+
+ /**
+ * @brief Set the path commands and data.
+ *
+ * @param[in] inPathObject Pointer to NV path object
+ * @param[in] inPathCommands vector of path commands ( moveTo,... )
+ * @param[in] inPathCoords vector of path coords
+ *
+ * @return No return
+ */
+ virtual void SetPathSpecification(NVRenderBackendPathObject inPathObject,
+ NVConstDataRef<QT3DSU8> inPathCommands,
+ NVConstDataRef<QT3DSF32> inPathCoords) = 0;
+
+ /**
+ * @brief Get Bounds of the path object
+ *
+ * @param[in] inPathObject Pointer to NV path object
+ *
+ * @return return bounds
+ */
+ virtual NVBounds3 GetPathObjectBoundingBox(NVRenderBackendPathObject inPathObject) = 0;
+ virtual NVBounds3 GetPathObjectFillBox(NVRenderBackendPathObject inPathObject) = 0;
+ virtual NVBounds3 GetPathObjectStrokeBox(NVRenderBackendPathObject inPathObject) = 0;
+
+ /**
+ * @brief Set stroke width. Defaults to 0 if unset.
+ *
+ * @param[in] inPathObject Pointer to NV path object
+ *
+ * @return No return
+ */
+ virtual void SetStrokeWidth(NVRenderBackendPathObject inPathObject,
+ QT3DSF32 inStrokeWidth) = 0;
+
+ /**
+ * @brief Path transform commands
+ *
+ * @param[in] inPathObject Pointer to NV path object
+ *
+ * @return No return
+ */
+ virtual void SetPathProjectionMatrix(const QT3DSMat44 inPathProjection) = 0;
+ virtual void SetPathModelViewMatrix(const QT3DSMat44 inPathModelview) = 0;
+
+ /**
+ * @brief Path stencil pass operations
+ *
+ * @param[in] inPathObject Pointer to NV path object
+ *
+ * @return No return
+ */
+ virtual void StencilStrokePath(NVRenderBackendPathObject inPathObject) = 0;
+ virtual void StencilFillPath(NVRenderBackendPathObject inPathObject) = 0;
+
+ /**
+ * @brief Does a instanced stencil fill pass
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] fillMode Fille mode
+ * @param[in] stencilMask Stencil mask
+ * @param[in] transformType Transforming glyphs
+ * @param[in] transformValues Pointer to array of transforms
+ *
+ * @return No return
+ */
+ virtual void StencilFillPathInstanced(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathFormatType::Enum type,
+ const void *charCodes, NVRenderPathFillMode::Enum fillMode, QT3DSU32 stencilMask,
+ NVRenderPathTransformType::Enum transformType, const QT3DSF32 *transformValues) = 0;
+
+ /**
+ * @brief Does a instanced stencil stroke pass
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] stencilRef Stencil reference
+ * @param[in] stencilMask Stencil mask
+ * @param[in] transformType Transforming glyphs
+ * @param[in] transformValues Pointer to array of transforms
+ *
+ * @return No return
+ */
+ virtual void StencilStrokePathInstancedN(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes, QT3DSI32 stencilRef,
+ QT3DSU32 stencilMask,
+ NVRenderPathTransformType::Enum transformType,
+ const QT3DSF32 *transformValues) = 0;
+
+ /**
+ * @brief Does a instanced cover fill pass
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] coverMode Cover mode
+ * @param[in] transformType Transforming glyphs
+ * @param[in] transformValues Pointer to array of transforms
+ *
+ * @return No return
+ */
+ virtual void CoverFillPathInstanced(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes,
+ NVRenderPathCoverMode::Enum coverMode,
+ NVRenderPathTransformType::Enum transformType,
+ const QT3DSF32 *transformValues) = 0;
+
+ /**
+ * @brief Does a instanced cover stroke pass
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] coverMode Cover mode
+ * @param[in] transformType Transforming glyphs
+ * @param[in] transformValues Pointer to array of transforms
+ *
+ * @return No return
+ */
+ virtual void CoverStrokePathInstanced(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes,
+ NVRenderPathCoverMode::Enum coverMode,
+ NVRenderPathTransformType::Enum transformType,
+ const QT3DSF32 *transformValues) = 0;
+
+ /**
+ * @brief Path stencil and depth offset
+ *
+ * @param[in] inSlope slope
+ * @param[in] inBias bias
+ *
+ * @return No return
+ */
+ virtual void SetPathStencilDepthOffset(QT3DSF32 inSlope, QT3DSF32 inBias) = 0;
+
+ /**
+ * @brief Path cover function
+ *
+ * @param[in] inDepthFunction depth function
+ *
+ * @return No return
+ */
+ virtual void SetPathCoverDepthFunc(NVRenderBoolOp::Enum inDepthFunction) = 0;
+
+ /**
+ * @brief Load glyphs
+ *
+ * @param[in] po Base of path objects
+ * @param[in] fontTarget System font, or application font,...
+ * @param[in] fontName Name of font ( may include path )
+ * @param[in] fontStyle Bold or italic
+ * @param[in] numGlyphs Glyph count
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] handleMissingGlyphs skip or use
+ * @param[in] pathParameterTemplate template
+ * @param[in] emScale scale ( true type scale e.g. 2048 )
+ *
+ * @return No return
+ */
+ virtual void LoadPathGlyphs(NVRenderBackendPathObject po,
+ NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle, size_t numGlyphs,
+ NVRenderPathFormatType::Enum type, const void *charCodes,
+ NVRenderPathMissingGlyphs::Enum handleMissingGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate,
+ QT3DSF32 emScale) = 0;
+
+ /**
+ * @brief Load indexed font set
+ *
+ * @param[in] po Base of path objects
+ * @param[in] fontTarget System font, or application font,...
+ * @param[in] fontName Name of font ( may include path )
+ * @param[in] fontStyle Bold or italic
+ * @param[in] firstGlyphIndex First glyph
+ * @param[in] numGlyphs Glyph count
+ * @param[in] pathParameterTemplate template
+ * @param[in] emScale scale ( true type scale e.g. 2048 )
+ *
+ * @return return load status
+ */
+ virtual NVRenderPathReturnValues::Enum
+ LoadPathGlyphsIndexed(NVRenderBackendPathObject po, NVRenderPathFontTarget::Enum fontTarget,
+ const void *fontName, NVRenderPathFontStyleFlags fontStyle,
+ QT3DSU32 firstGlyphIndex, size_t numGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale) = 0;
+
+ /**
+ * @brief Load indexed font set
+ *
+ * @param[in] fontTarget System font, or application font,...
+ * @param[in] fontName Name of font ( may include path )
+ * @param[in] fontStyle Bold or italic
+ * @param[in] pathParameterTemplate template
+ * @param[in] emScale scale ( true type scale e.g. 2048 )
+ * @param[out] po contains glyph count
+ *
+ * @return returnr base path object
+ */
+ virtual NVRenderBackendPathObject
+ LoadPathGlyphsIndexedRange(NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale,
+ QT3DSU32 *count) = 0;
+
+ /**
+ * @brief Load font set
+ *
+ * @param[in] po Base of path objects
+ * @param[in] fontTarget System font, or application font,...
+ * @param[in] fontName Name of font ( may include path )
+ * @param[in] fontStyle Bold or italic
+ * @param[in] firstGlyph First glyph
+ * @param[in] numGlyphs Glyph count
+ * @param[in] handleMissingGlyphs skip or use
+ * @param[in] pathParameterTemplate template
+ * @param[in] emScale scale ( true type scale e.g. 2048 )
+ *
+ * @return No return
+ */
+ virtual void LoadPathGlyphRange(NVRenderBackendPathObject po,
+ NVRenderPathFontTarget::Enum fontTarget,
+ const void *fontName, NVRenderPathFontStyleFlags fontStyle,
+ QT3DSU32 firstGlyph, size_t numGlyphs,
+ NVRenderPathMissingGlyphs::Enum handleMissingGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate,
+ QT3DSF32 emScale) = 0;
+
+ /**
+ * @brief Query font metrics
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] metricQueryMask Qeury bit mask
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] stride scale ( true type scale e.g. 2048 )
+ * @param[out] metrics Filled with font metric values
+ *
+ * @return No return
+ */
+ virtual void GetPathMetrics(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathGlyphFontMetricFlags metricQueryMask,
+ NVRenderPathFormatType::Enum type, const void *charCodes,
+ size_t stride, QT3DSF32 *metrics) = 0;
+
+ /**
+ * @brief Query font metrics
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] metricQueryMask Qeury bit mask
+ * @param[in] stride scale ( true type scale e.g. 2048 )
+ * @param[out] metrics Filled with font metric values
+ *
+ * @return No return
+ */
+ virtual void GetPathMetricsRange(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathGlyphFontMetricFlags metricQueryMask,
+ size_t stride, QT3DSF32 *metrics) = 0;
+
+ /**
+ * @brief Query path spacing
+ *
+ * @param[in] po Base of path objects
+ * @param[in] numPaths Number path objects
+ * @param[in] pathListMode How to compute spacing
+ * @param[in] type type ( byte, int,... )
+ * @param[in] charCodes charachter string
+ * @param[in] advanceScale
+ * @param[in] kerningScale
+ * @param[in] transformType
+ * @param[out] metrics Filled with font metric values
+ *
+ * @return No return
+ */
+ virtual void GetPathSpacing(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathListMode::Enum pathListMode,
+ NVRenderPathFormatType::Enum type, const void *charCodes,
+ QT3DSF32 advanceScale, QT3DSF32 kerningScale,
+ NVRenderPathTransformType::Enum transformType,
+ QT3DSF32 *spacing) = 0;
+
+ virtual QSurfaceFormat format() const = 0;
+
+ protected:
+ /// struct for what the backend supports
+ typedef struct NVRenderBackendSupport
+ {
+ union {
+ struct
+ {
+ bool bDXTImagesSupported : 1; ///< compressed images supported
+ bool bAnistropySupported : 1; ///< anistropic filtering supported
+ bool bTextureSwizzleSupported : 1; ///< texture swizzle supported
+ bool bDepthStencilSupported : 1; ///< depth stencil textures are supported
+ bool bFPRenderTargetsSupported : 1; ///< floating point render targets are
+ ///supported
+ bool bConstantBufferSupported : 1; ///< Constant (uniform) buffers are supported
+ bool bMsTextureSupported : 1; ///< Multisample textures are esupported
+ bool bFastBlitsSupported : 1; ///< The hardware supports fast memor blits
+ bool bTessellationSupported : 1; ///< Hardware supports tessellation
+ bool bComputeSupported : 1; ///< Hardware supports compute shader
+ bool bGeometrySupported : 1; ///< Hardware supports geometry shader
+ bool bTimerQuerySupported : 1; ///< Hardware supports timer queries
+ bool bProgramInterfaceSupported : 1; ///< API supports program interface queries
+ bool bStorageBufferSupported : 1; ///< Shader storage buffers are supported
+ bool
+ bAtomicCounterBufferSupported : 1; ///< Atomic counter buffers are supported
+ bool bShaderImageLoadStoreSupported : 1; ///< Shader image load / store
+ ///operations are supported
+ bool bProgramPipelineSupported : 1; ///< Driver supports separate programs
+ bool bNVPathRenderingSupported : 1; ///< Driver NV path rendering
+ bool bNVAdvancedBlendSupported : 1; ///< Advanced blend modes supported
+ bool bNVBlendCoherenceSupported : 1; ///< Advanced blend done coherently
+ ///supported
+ bool bGPUShader5ExtensionSupported : 1;
+ bool bKHRAdvancedBlendSupported : 1; ///< Advanced blend modes supported
+ bool bKHRBlendCoherenceSupported : 1; ///< Advanced blend done coherently
+ } bits;
+
+ QT3DSU32 u32Values;
+ } caps;
+ } NVRenderBackendSupportBits;
+
+ NVRenderBackendSupportBits m_backendSupport; ///< holds the backend support bits
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h
new file mode 100644
index 00000000..4fae0a46
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLExtensions.h
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSOPENGLEXTENSIONS_H
+#define QT3DSOPENGLEXTENSIONS_H
+
+#include <QtOpenGLExtensions/QtOpenGLExtensions>
+
+/* Some OpenGL extensions that are not (yet) found in Qt's OpenGL extensions.
+ * These should be auto-generated and added to QtOpenGLExtensions module */
+class Qt3DSOpenGLExtensionsPrivate : public QAbstractOpenGLExtensionPrivate
+{
+public:
+ void (QOPENGLF_APIENTRYP BlendBarrierNV)();
+ GLenum (QOPENGLF_APIENTRYP PathGlyphIndexArrayNV)(
+ GLuint, GLenum, const void*, GLbitfield, GLuint, GLsizei, GLuint,
+ GLfloat);
+ GLenum (QOPENGLF_APIENTRYP PathGlyphIndexRangeNV)(
+ GLenum, const void*, GLbitfield, GLuint, GLfloat, GLuint[2]);
+
+#if defined(QT_OPENGL_ES)
+ void (QOPENGLF_APIENTRYP PatchParameteriEXT)(GLenum, GLint);
+ void (QOPENGLF_APIENTRYP QueryCounterEXT)(GLuint, GLenum);
+ void (QOPENGLF_APIENTRYP GetQueryObjectui64vEXT)(GLuint, GLenum,
+ GLuint64 *);
+ GLuint (QOPENGLF_APIENTRYP GenPathsNV)(GLsizei);
+ void (QOPENGLF_APIENTRYP DeletePathsNV)(GLuint, GLsizei);
+ void (QOPENGLF_APIENTRYP PathCommandsNV)(GLuint, GLsizei, const GLubyte *,
+ GLsizei, GLenum, const void *);
+ void (QOPENGLF_APIENTRYP PathGlyphsNV)(GLuint, GLenum, const void *,
+ GLbitfield, GLsizei, GLenum, const void *, GLenum, GLuint, GLfloat);
+ void (QOPENGLF_APIENTRYP PathGlyphRangeNV)(GLuint, GLenum, const void *,
+ GLbitfield, GLuint, GLsizei, GLenum, GLuint, GLfloat);
+ void (QOPENGLF_APIENTRYP PathParameterfNV)(GLuint, GLenum, GLfloat);
+ void (QOPENGLF_APIENTRYP PathStencilDepthOffsetNV)(GLfloat, GLfloat);
+ void (QOPENGLF_APIENTRYP StencilFillPathNV)(GLuint, GLenum, GLuint);
+ void (QOPENGLF_APIENTRYP StencilStrokePathNV)(GLuint, GLint, GLuint);
+ void (QOPENGLF_APIENTRYP StencilFillPathInstancedNV)(GLsizei, GLenum,
+ const void *, GLuint, GLenum, GLuint, GLenum, const GLfloat *);
+ void (QOPENGLF_APIENTRYP StencilStrokePathInstancedNV)(GLsizei, GLenum,
+ const void *, GLuint, GLint, GLuint, GLenum, const GLfloat *);
+ void (QOPENGLF_APIENTRYP PathCoverDepthFuncNV)(GLenum);
+ void (QOPENGLF_APIENTRYP CoverFillPathInstancedNV)(GLsizei, GLenum,
+ const void *, GLuint, GLenum, GLenum, const GLfloat *);
+ void (QOPENGLF_APIENTRYP CoverStrokePathInstancedNV)(GLsizei, GLenum,
+ const void *, GLuint, GLenum, GLenum, const GLfloat *);
+ void (QOPENGLF_APIENTRYP GetPathParameterfvNV)(GLuint, GLenum, GLfloat *);
+ void (QOPENGLF_APIENTRYP GetPathMetricsNV)(GLbitfield, GLsizei, GLenum,
+ const void *, GLuint, GLsizei, GLfloat *);
+ void (QOPENGLF_APIENTRYP GetPathMetricRangeNV)(GLbitfield, GLuint, GLsizei,
+ GLsizei, GLfloat *);
+ void (QOPENGLF_APIENTRYP GetPathSpacingNV)(GLenum, GLsizei, GLenum,
+ const void *, GLuint, GLfloat, GLfloat, GLenum, GLfloat *);
+#endif
+};
+
+class Qt3DSOpenGLExtensions : public QAbstractOpenGLExtension
+{
+public:
+ Qt3DSOpenGLExtensions();
+
+ bool initializeOpenGLFunctions() override;
+
+ void glBlendBarrierNV();
+ GLenum glPathGlyphIndexArrayNV(GLuint firstPathName, GLenum fontTarget,
+ const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex,
+ GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+ GLenum glPathGlyphIndexRangeNV(GLenum fontTarget, const void *fontName,
+ GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale,
+ GLuint baseAndCount[2]);
+
+protected:
+ Q_DECLARE_PRIVATE(Qt3DSOpenGLExtensions)
+};
+
+inline void Qt3DSOpenGLExtensions::glBlendBarrierNV()
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->BlendBarrierNV();
+}
+
+inline GLenum Qt3DSOpenGLExtensions::glPathGlyphIndexArrayNV(
+ GLuint firstPathName, GLenum fontTarget, const void *fontName,
+ GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs,
+ GLuint pathParameterTemplate, GLfloat emScale)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ return d->PathGlyphIndexArrayNV(firstPathName, fontTarget, fontName,
+ fontStyle, firstGlyphIndex, numGlyphs, pathParameterTemplate, emScale);
+}
+
+inline GLenum Qt3DSOpenGLExtensions::glPathGlyphIndexRangeNV(GLenum fontTarget,
+ const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate,
+ GLfloat emScale, GLuint baseAndCount[2])
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ return d->PathGlyphIndexRangeNV(fontTarget, fontName, fontStyle,
+ pathParameterTemplate, emScale, baseAndCount);
+}
+
+#if defined(QT_OPENGL_ES)
+class Qt3DSOpenGLES2Extensions : public Qt3DSOpenGLExtensions
+{
+public:
+ Qt3DSOpenGLES2Extensions();
+
+ // tesselation shader
+ void glPatchParameteriEXT(GLenum pname, GLint value);
+
+ // timer
+ void glQueryCounterEXT(GLuint id, GLenum target);
+ void glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *params);
+
+ // nv paths
+
+ GLuint glGenPathsNV(GLsizei range);
+ void glDeletePathsNV(GLuint path, GLsizei range);
+ void glPathCommandsNV(GLuint path, GLsizei numCommands,
+ const GLubyte *commands, GLsizei numCoords, GLenum coordType,
+ const void *coords);
+ void glPathGlyphsNV(GLuint firstPathName, GLenum fontTarget,
+ const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs,
+ GLenum type, const void *charcodes, GLenum handleMissingGlyphs,
+ GLuint pathParameterTemplate, GLfloat emScale);
+ void glPathGlyphRangeNV(GLuint firstPathName, GLenum fontTarget,
+ const void *fontName, GLbitfield fontStyle, GLuint firstGlyph,
+ GLsizei numGlyphs, GLenum handleMissingGlyphs,
+ GLuint pathParameterTemplate, GLfloat emScale);
+ void glPathParameterfNV(GLuint path, GLenum pname, GLfloat value);
+ void glPathStencilDepthOffsetNV(GLfloat factor, GLfloat units);
+ void glStencilFillPathNV(GLuint path, GLenum fillMode, GLuint mask);
+ void glStencilStrokePathNV(GLuint path, GLint reference, GLuint mask);
+ void glStencilFillPathInstancedNV(GLsizei numPaths, GLenum pathNameType,
+ const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask,
+ GLenum transformType, const GLfloat *transformValues);
+ void glStencilStrokePathInstancedNV(GLsizei numPaths, GLenum pathNameType,
+ const void *paths, GLuint pathBase, GLint reference, GLuint mask,
+ GLenum transformType, const GLfloat *transformValues);
+ void glPathCoverDepthFuncNV(GLenum func);
+ void glCoverFillPathInstancedNV(GLsizei numPaths, GLenum pathNameType,
+ const void *paths, GLuint pathBase, GLenum coverMode,
+ GLenum transformType, const GLfloat *transformValues);
+ void glCoverStrokePathInstancedNV(GLsizei numPaths, GLenum pathNameType,
+ const void *paths, GLuint pathBase, GLenum coverMode,
+ GLenum transformType, const GLfloat *transformValues);
+ void glGetPathParameterfvNV(GLuint path, GLenum pname, GLfloat *value);
+ void glGetPathMetricsNV(GLbitfield metricQueryMask, GLsizei numPaths,
+ GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride,
+ GLfloat *metrics);
+ void glGetPathMetricRangeNV(GLbitfield metricQueryMask,
+ GLuint firstPathName, GLsizei numPaths, GLsizei stride,
+ GLfloat *metrics);
+ void glGetPathSpacingNV(GLenum pathListMode, GLsizei numPaths,
+ GLenum pathNameType, const void *paths, GLuint pathBase,
+ GLfloat advanceScale, GLfloat kerningScale, GLenum transformType,
+ GLfloat *returnedSpacing);
+
+ bool initializeOpenGLFunctions() Q_DECL_FINAL;
+};
+
+inline void Qt3DSOpenGLES2Extensions::glPatchParameteriEXT(GLenum pname,
+ GLint value)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PatchParameteriEXT(pname, value);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glQueryCounterEXT(GLuint id,
+ GLenum target)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->QueryCounterEXT(id, target);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glGetQueryObjectui64vEXT(GLuint id,
+ GLenum pname, GLuint64 *params)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->GetQueryObjectui64vEXT(id, pname, params);
+}
+
+inline GLuint Qt3DSOpenGLES2Extensions::glGenPathsNV(GLsizei range)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ return d->GenPathsNV(range);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glDeletePathsNV(GLuint path,
+ GLsizei range)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->DeletePathsNV(path, range);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glPathCommandsNV(GLuint path,
+ GLsizei numCommands, const GLubyte *commands, GLsizei numCoords,
+ GLenum coordType, const void *coords)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PathCommandsNV(path, numCommands, commands, numCoords, coordType,
+ coords);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glPathGlyphsNV(GLuint firstPathName,
+ GLenum fontTarget, const void *fontName, GLbitfield fontStyle,
+ GLsizei numGlyphs, GLenum type, const void *charcodes,
+ GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PathGlyphsNV(firstPathName, fontTarget, fontName, fontStyle, numGlyphs,
+ type, charcodes, handleMissingGlyphs, pathParameterTemplate, emScale);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glPathGlyphRangeNV(GLuint firstPathName,
+ GLenum fontTarget, const void *fontName, GLbitfield fontStyle,
+ GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs,
+ GLuint pathParameterTemplate, GLfloat emScale)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PathGlyphRangeNV(firstPathName, fontTarget, fontName, fontStyle,
+ firstGlyph, numGlyphs, handleMissingGlyphs, pathParameterTemplate,
+ emScale);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glPathParameterfNV(GLuint path,
+ GLenum pname, GLfloat value)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PathParameterfNV(path, pname, value);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glPathStencilDepthOffsetNV(GLfloat factor,
+ GLfloat units)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PathStencilDepthOffsetNV(factor, units);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glStencilFillPathNV(GLuint path,
+ GLenum fillMode, GLuint mask)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->StencilFillPathNV(path, fillMode, mask);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glStencilStrokePathNV(GLuint path,
+ GLint reference, GLuint mask)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->StencilStrokePathNV(path, reference, mask);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glStencilFillPathInstancedNV(
+ GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase,
+ GLenum fillMode, GLuint mask, GLenum transformType,
+ const GLfloat *transformValues)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->StencilFillPathInstancedNV(numPaths, pathNameType, paths, pathBase,
+ fillMode, mask, transformType, transformValues);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glStencilStrokePathInstancedNV(
+ GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase,
+ GLint reference, GLuint mask, GLenum transformType,
+ const GLfloat *transformValues)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->StencilStrokePathInstancedNV(numPaths, pathNameType, paths, pathBase,
+ reference, mask, transformType, transformValues);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glPathCoverDepthFuncNV(GLenum func)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->PathCoverDepthFuncNV(func);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glCoverFillPathInstancedNV(
+ GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase,
+ GLenum coverMode, GLenum transformType, const GLfloat *transformValues)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->CoverFillPathInstancedNV(numPaths, pathNameType, paths, pathBase,
+ coverMode, transformType, transformValues);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glCoverStrokePathInstancedNV(
+ GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase,
+ GLenum coverMode, GLenum transformType, const GLfloat *transformValues)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->CoverStrokePathInstancedNV(numPaths, pathNameType, paths, pathBase,
+ coverMode, transformType, transformValues);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glGetPathParameterfvNV(GLuint path,
+ GLenum pname, GLfloat *value)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->GetPathParameterfvNV(path, pname, value);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glGetPathMetricsNV(
+ GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType,
+ const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->GetPathMetricsNV(metricQueryMask, numPaths, pathNameType, paths,
+ pathBase, stride, metrics);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glGetPathMetricRangeNV(
+ GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths,
+ GLsizei stride, GLfloat *metrics)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->GetPathMetricRangeNV(metricQueryMask, firstPathName, numPaths, stride,
+ metrics);
+}
+
+inline void Qt3DSOpenGLES2Extensions::glGetPathSpacingNV(GLenum pathListMode,
+ GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase,
+ GLfloat advanceScale, GLfloat kerningScale, GLenum transformType,
+ GLfloat *returnedSpacing)
+{
+ Q_D(Qt3DSOpenGLExtensions);
+ d->GetPathSpacingNV(pathListMode, numPaths, pathNameType, paths, pathBase,
+ advanceScale, kerningScale, transformType, returnedSpacing);
+}
+
+#endif // QT_OPENGL_ES
+
+#endif // QT3DSOPENGLEXTENSIONS_H
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h
new file mode 100644
index 00000000..2cbc8b6a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLPrefix.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSOPENGLPREFIX_H
+#define QT3DSOPENGLPREFIX_H
+
+#include <QtGui/qtguiglobal.h>
+#if defined(QT_OPENGL_ES)
+#define GL_GLEXT_PROTOTYPES
+// We require a minimum of GLES 3.1 for Qt3DStudio when building against a
+// non-desktop OpenGL target
+#if defined(QT_OPENGL_ES_3_2)
+#include <GLES3/gl32.h>
+#else
+#include <GLES3/gl31.h>
+#endif
+// Adding this to ensure that platform version of gl2ext.h is included
+// before Qt's qopengles2ext.h which is missing symbols we need
+#include <GLES2/gl2ext.h>
+#endif
+
+#endif // QT3DSOPENGLPREFIX_H
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLTokens.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLTokens.h
new file mode 100644
index 00000000..3a4a1ef6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLTokens.h
@@ -0,0 +1,398 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSOPENGLTOKENS_H
+#define QT3DSOPENGLTOKENS_H
+
+/**
+ * This is our general internal to GL type conversion routines
+ * Add defines which are not in standard GL(ext) header but in GL2(ext)
+ * The define are the same with different names
+ * Expectation is the NVIDIA defines (need for compile)
+ */
+#ifndef GL_NVIDIA_PLATFORM_BINARY_NV
+#define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
+#endif
+
+#if defined(__APPLE__) || defined(ANDROID) || defined(__INTEGRITY)
+#ifndef GL_DEPTH_COMPONENT24
+#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
+#endif
+#ifndef GL_DEPTH_COMPONENT32
+#define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES
+#endif
+
+/**
+_* tessellation_shader defines
+ */
+#ifndef GL_TESS_EVALUATION_SHADER
+#define GL_TESS_EVALUATION_SHADER GL_TESS_EVALUATION_SHADER_EXT
+#endif
+#ifndef GL_TESS_CONTROL_SHADER
+#define GL_TESS_CONTROL_SHADER GL_TESS_CONTROL_SHADER_EXT
+#endif
+#ifndef GL_PATCHES
+#define GL_PATCHES GL_PATCHES_EXT
+#endif
+#ifndef GL_PATCH_VERTICES
+#define GL_PATCH_VERTICES GL_PATCH_VERTICES_EXT
+#endif
+#ifndef GL_TESS_CONTROL_SHADER_BIT
+#define GL_TESS_CONTROL_SHADER_BIT GL_TESS_CONTROL_SHADER_BIT_EXT
+#endif
+#ifndef GL_TESS_EVALUATION_SHADER_BIT
+#define GL_TESS_EVALUATION_SHADER_BIT GL_TESS_EVALUATION_SHADER_BIT_EXT
+#endif
+
+/**
+ * sample shading extension
+ */
+#ifndef GL_SAMPLE_SHADING
+#define GL_SAMPLE_SHADING GL_SAMPLE_SHADING_OES
+#endif
+#ifndef GL_MIN_SAMPLE_SHADING_VALUE
+#define GL_MIN_SAMPLE_SHADING_VALUE GL_MIN_SAMPLE_SHADING_VALUE_OES
+#endif
+
+/**
+ * Timer query extension
+ */
+#ifndef GL_TIME_ELAPSED
+#define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT
+#endif
+#ifndef GL_TIMESTAMP
+#define GL_TIMESTAMP GL_TIMESTAMP_EXT
+#endif
+
+/**
+ * compute shader
+ */
+#ifndef GL_IMAGE_2D
+#define GL_IMAGE_2D 0x904D
+#endif
+
+/**
+ * texture formats ( make build happy )
+ */
+#ifndef GL_R16
+#define GL_R16 0x822A
+#endif
+
+#endif // __APPLE__ || ANDROID || __INTEGRITY
+
+#if defined(__APPLE__) || defined(ANDROID)
+
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+#define GL_BLEND_OVERLAP_NV 0x9281
+#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define GL_BLUE_NV 0x1905
+#define GL_COLORBURN_NV 0x929A
+#define GL_COLORDODGE_NV 0x9299
+#define GL_CONJOINT_NV 0x9284
+#define GL_CONTRAST_NV 0x92A1
+#define GL_DARKEN_NV 0x9297
+#define GL_DIFFERENCE_NV 0x929E
+#define GL_DISJOINT_NV 0x9283
+#define GL_DST_ATOP_NV 0x928F
+#define GL_DST_IN_NV 0x928B
+#define GL_DST_NV 0x9287
+#define GL_DST_OUT_NV 0x928D
+#define GL_DST_OVER_NV 0x9289
+#define GL_EXCLUSION_NV 0x92A0
+#define GL_GREEN_NV 0x1904
+#define GL_HARDLIGHT_NV 0x929B
+#define GL_HARDMIX_NV 0x92A9
+#define GL_HSL_COLOR_NV 0x92AF
+#define GL_HSL_HUE_NV 0x92AD
+#define GL_HSL_LUMINOSITY_NV 0x92B0
+#define GL_HSL_SATURATION_NV 0x92AE
+#define GL_INVERT_OVG_NV 0x92B4
+#define GL_INVERT_RGB_NV 0x92A3
+#define GL_LIGHTEN_NV 0x9298
+#define GL_LINEARBURN_NV 0x92A5
+#define GL_LINEARDODGE_NV 0x92A4
+#define GL_LINEARLIGHT_NV 0x92A7
+#define GL_MINUS_CLAMPED_NV 0x92B3
+#define GL_MINUS_NV 0x929F
+#define GL_MULTIPLY_NV 0x9294
+#define GL_OVERLAY_NV 0x9296
+#define GL_PINLIGHT_NV 0x92A8
+#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define GL_PLUS_CLAMPED_NV 0x92B1
+#define GL_PLUS_DARKER_NV 0x9292
+#define GL_PLUS_NV 0x9291
+#define GL_RED_NV 0x1903
+#define GL_SCREEN_NV 0x9295
+#define GL_SOFTLIGHT_NV 0x929C
+#define GL_SRC_ATOP_NV 0x928E
+#define GL_SRC_IN_NV 0x928A
+#define GL_SRC_NV 0x9286
+#define GL_SRC_OUT_NV 0x928C
+#define GL_SRC_OVER_NV 0x9288
+#define GL_UNCORRELATED_NV 0x9282
+#define GL_VIVIDLIGHT_NV 0x92A6
+#define GL_XOR_NV 0x1506
+#endif /* GL_NV_blend_equation_advanced */
+
+#ifndef GL_SHADER_STORAGE_BUFFER
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#endif
+
+#ifndef GL_ATOMIC_COUNTER_BUFFER
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#endif
+
+#ifndef GL_ALL_BARRIER_BITS
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#endif
+
+#ifndef GL_SHADER_STORAGE_BARRIER_BIT
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#endif
+
+#ifndef GL_UNSIGNED_INT_ATOMIC_COUNTER
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#endif
+
+#ifndef GL_UNSIGNED_INT_IMAGE_2D
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#endif
+
+
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_ROUNDED_RECT_NV 0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define GL_ROUNDED_RECT2_NV 0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define GL_ROUNDED_RECT4_NV 0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define GL_ROUNDED_RECT8_NV 0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define GL_RELATIVE_RECT_NV 0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define GL_FONT_UNAVAILABLE_NV 0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define GL_CONIC_CURVE_TO_NV 0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define GL_2_BYTES_NV 0x1407
+#define GL_3_BYTES_NV 0x1408
+#define GL_4_BYTES_NV 0x1409
+#define GL_EYE_LINEAR_NV 0x2400
+#define GL_OBJECT_LINEAR_NV 0x2401
+#define GL_CONSTANT_NV 0x8576
+#define GL_PATH_PROJECTION_NV 0x1701
+#define GL_PATH_MODELVIEW_NV 0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV 0x936D
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_SHADER_STORAGE_BLOCK
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#endif
+
+#ifndef GL_ACTIVE_RESOURCES
+#define GL_ACTIVE_RESOURCES 0x92F5
+#endif
+
+#ifndef GL_BUFFER_BINDING
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#endif
+
+#ifndef GL_UNIFORM
+#define GL_UNIFORM 0x92E1
+#endif
+
+#ifndef GL_COMPUTE_SHADER
+#define GL_COMPUTE_SHADER 0x91B9
+#endif
+
+#endif // __APPLE__ || ANDROID
+
+#endif // QT3DSOPENGLTOKENS_H
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h
new file mode 100644
index 00000000..ebfb20c2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSOpenGLUtil.h
@@ -0,0 +1,1932 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSOPENGLUTIL_H
+#define QT3DSOPENGLUTIL_H
+
+#include "render/backends/gl/Qt3DSOpenGLPrefix.h"
+#include "render/backends/gl/Qt3DSOpenGLTokens.h"
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLExtraFunctions>
+
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSVec4.h"
+#include "foundation/Qt3DSFoundation.h"
+
+// The actual binding to the hardware the does some minor conversions between gles and
+// the nv render enumeration types
+namespace qt3ds {
+namespace render {
+
+#define QT3DS_RENDER_ITERATE_QT3DS_GL_COLOR_FUNC \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ZERO, Zero) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE, One) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_SRC_COLOR, SrcColor) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE_MINUS_SRC_COLOR, OneMinusSrcColor) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_DST_COLOR, DstColor) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE_MINUS_DST_COLOR, OneMinusDstColor) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_SRC_ALPHA, SrcAlpha) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE_MINUS_SRC_ALPHA, OneMinusSrcAlpha) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_DST_ALPHA, DstAlpha) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE_MINUS_DST_ALPHA, OneMinusDstAlpha) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_CONSTANT_COLOR, ConstantColor) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE_MINUS_CONSTANT_COLOR, OneMinusConstantColor) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_CONSTANT_ALPHA, ConstantAlpha) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(GL_ONE_MINUS_CONSTANT_ALPHA, OneMinusConstantAlpha) \
+ QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY(GL_SRC_ALPHA_SATURATE, SrcAlphaSaturate)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_RENDER_FACE \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE(GL_FRONT, Front) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE(GL_BACK, Back) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE(GL_FRONT_AND_BACK, FrontAndBack)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_RENDER_WINDING \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_WINDING(GL_CW, Clockwise) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_WINDING(GL_CCW, CounterClockwise)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_BOOL_OP \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_NEVER, Never) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_LESS, Less) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_EQUAL, Equal) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_LEQUAL, LessThanOrEqual) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_GREATER, Greater) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_NOTEQUAL, NotEqual) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_GEQUAL, GreaterThanOrEqual) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(GL_ALWAYS, AlwaysTrue)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_HINT \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_HINT(GL_FASTEST, Fastest) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_HINT(GL_NICEST, Nicest) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_HINT(GL_DONT_CARE, Unspecified)
+
+#define QT3DS_RENDER_ITERATE_QT3DS_GL_STENCIL_OP \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_KEEP, Keep) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_ZERO, Zero) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_REPLACE, Replace) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_INCR, Increment) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_INCR_WRAP, IncrementWrap) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_DECR, Decrement) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_DECR_WRAP, DecrementWrap) \
+ QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(GL_INVERT, Invert)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_BUFFER_COMPONENT_TYPES \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(GL_UNSIGNED_BYTE, QT3DSU8) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(GL_BYTE, QT3DSI8) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(GL_UNSIGNED_SHORT, QT3DSU16) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(GL_SHORT, QT3DSI16) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(GL_UNSIGNED_INT, QT3DSU32) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE_ALIAS(GL_INT, QT3DSI32) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(GL_FLOAT, QT3DSF32)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_BUFFER_USAGE_TYPE \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BUFFER_USAGE_TYPE(GL_STATIC_DRAW, Static) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_BUFFER_USAGE_TYPE(GL_DYNAMIC_DRAW, Dynamic)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_SCALE_OP \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP(GL_NEAREST, Nearest) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP(GL_LINEAR, Linear) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(GL_NEAREST_MIPMAP_NEAREST, NearestMipmapNearest) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(GL_LINEAR_MIPMAP_NEAREST, LinearMipmapNearest) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(GL_NEAREST_MIPMAP_LINEAR, NearestMipmapLinear) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(GL_LINEAR_MIPMAP_LINEAR, LinearMipmapLinear)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_WRAP_OP \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP(GL_CLAMP_TO_EDGE, ClampToEdge) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP(GL_MIRRORED_REPEAT, MirroredRepeat) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP(GL_REPEAT, Repeat)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_SHADER_UNIFORM_TYPES \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_FLOAT, QT3DSF32) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_FLOAT_VEC2, QT3DSVec2) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_FLOAT_VEC3, QT3DSVec3) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_FLOAT_VEC4, QT3DSVec4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_INT, QT3DSI32) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_INT_VEC2, QT3DSI32_2) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_INT_VEC3, QT3DSI32_3) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_INT_VEC4, QT3DSI32_4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_BOOL, QT3DSRenderBool) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_BOOL_VEC2, bool_2) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_BOOL_VEC3, bool_3) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_BOOL_VEC4, bool_4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_UNSIGNED_INT, QT3DSU32) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_UNSIGNED_INT_VEC2, QT3DSU32_2) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_UNSIGNED_INT_VEC3, QT3DSU32_3) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_UNSIGNED_INT_VEC4, QT3DSU32_4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_FLOAT_MAT3, QT3DSMat33) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_FLOAT_MAT4, QT3DSMat44) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_SAMPLER_2D, NVRenderTexture2DPtr) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_SAMPLER_2D_ARRAY, NVRenderTexture2DArrayPtr) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_SAMPLER_CUBE, NVRenderTextureCubePtr) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(GL_IMAGE_2D, NVRenderImage2DPtr)
+// cube Sampler and mat22 unsupported
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_SHADER_ATTRIB_TYPES \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT, QT3DSF32, 1) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_VEC2, QT3DSF32, 2) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_VEC3, QT3DSF32, 3) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_VEC4, QT3DSF32, 4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_MAT2, QT3DSF32, 4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_MAT3, QT3DSF32, 9) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(GL_FLOAT_MAT4, QT3DSF32, 16)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_FORMATS \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGBA4, RGBA4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGB565, RGB565) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_RGB5_A1, RGBA5551) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT16, Depth16) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT24, Depth24) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_DEPTH_COMPONENT32, Depth32) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(GL_STENCIL_INDEX8, StencilIndex8)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_ATTACHMENTS \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color0, 0) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color1, 1) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color2, 2) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color3, 3) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color4, 4) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color5, 5) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color6, 6) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(Color7, 7) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT(GL_DEPTH_ATTACHMENT, Depth) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT(GL_STENCIL_ATTACHMENT, Stencil) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT(GL_DEPTH_STENCIL_ATTACHMENT, DepthStencil)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_CLEAR_FLAGS \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS(GL_COLOR_BUFFER_BIT, Color) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS(GL_DEPTH_BUFFER_BIT, Depth) \
+ QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS(GL_STENCIL_BUFFER_BIT, Stencil)
+
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_COVERAGE_FORMATS
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_COVERAGE_ATTACHMENTS
+#define QT3DS_RENDER_ITERATE_GL_QT3DS_CLEAR_COVERAGE_FLAGS
+
+ static bool IsGlEsContext(NVRenderContextType inContextType)
+ {
+ NVRenderContextType esContextTypes(NVRenderContextValues::GLES2
+ | NVRenderContextValues::GLES3
+ | NVRenderContextValues::GLES3PLUS);
+
+ if ((inContextType & esContextTypes))
+ return true;
+
+ return false;
+ }
+
+ struct GLConversion
+ {
+ GLConversion()
+ { }
+
+ static const char *processGLError(GLenum error)
+ {
+ const char *errorString = "";
+ switch (error) {
+#define stringiseError(error) \
+ case error: \
+ errorString = #error; \
+ break
+ stringiseError(GL_NO_ERROR);
+ stringiseError(GL_INVALID_ENUM);
+ stringiseError(GL_INVALID_VALUE);
+ stringiseError(GL_INVALID_OPERATION);
+ stringiseError(GL_INVALID_FRAMEBUFFER_OPERATION);
+ stringiseError(GL_OUT_OF_MEMORY);
+#undef stringiseError
+ default:
+ errorString = "Unknown GL error";
+ break;
+ }
+ return errorString;
+ }
+
+ static NVRenderSrcBlendFunc::Enum fromGLToSrcBlendFunc(QT3DSI32 value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(srcVal, enumVal) \
+ case srcVal: \
+ return NVRenderSrcBlendFunc::enumVal;
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY(srcVal, enumVal) \
+ case srcVal: \
+ return NVRenderSrcBlendFunc::enumVal;
+ QT3DS_RENDER_ITERATE_QT3DS_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY
+ default:
+ QT3DS_ASSERT(false);
+ return NVRenderSrcBlendFunc::Unknown;
+ }
+ }
+
+ static GLenum fromSrcBlendFuncToGL(NVRenderSrcBlendFunc::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(srcVal, enumVal) \
+ case NVRenderSrcBlendFunc::enumVal: \
+ return srcVal;
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY(srcVal, enumVal) \
+ case NVRenderSrcBlendFunc::enumVal: \
+ return srcVal;
+ QT3DS_RENDER_ITERATE_QT3DS_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY
+ default:
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ }
+
+ static NVRenderDstBlendFunc::Enum fromGLToDstBlendFunc(QT3DSI32 value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(srcVal, enumVal) \
+ case srcVal: \
+ return NVRenderDstBlendFunc::enumVal;
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY(srcVal, enumVal)
+ QT3DS_RENDER_ITERATE_QT3DS_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY
+ default:
+ QT3DS_ASSERT(false);
+ return NVRenderDstBlendFunc::Unknown;
+ }
+ }
+
+ static GLenum fromDstBlendFuncToGL(NVRenderDstBlendFunc::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC(srcVal, enumVal) \
+ case NVRenderDstBlendFunc::enumVal: \
+ return srcVal;
+#define QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY(srcVal, enumVal)
+ QT3DS_RENDER_ITERATE_QT3DS_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC
+#undef QT3DS_RENDER_HANDLE_GL_COLOR_FUNC_SRC_ONLY
+ default:
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ }
+
+ static GLenum fromBlendEquationToGL(NVRenderBlendEquation::Enum value,
+ bool nvAdvancedBlendSupported,
+ bool khrAdvancedBlendSupported)
+ {
+ switch (value) {
+ case NVRenderBlendEquation::Add:
+ return GL_FUNC_ADD;
+ case NVRenderBlendEquation::Subtract:
+ return GL_FUNC_SUBTRACT;
+ case NVRenderBlendEquation::ReverseSubtract:
+ return GL_FUNC_REVERSE_SUBTRACT;
+ default:
+ QT3DS_ASSERT(nvAdvancedBlendSupported || khrAdvancedBlendSupported);
+ break;
+ }
+
+ if (nvAdvancedBlendSupported) {
+ switch (value) {
+ case NVRenderBlendEquation::Overlay:
+ return GL_OVERLAY_NV;
+ case NVRenderBlendEquation::ColorBurn:
+ return GL_COLORBURN_NV;
+ case NVRenderBlendEquation::ColorDodge:
+ return GL_COLORDODGE_NV;
+ default:
+ break;
+ }
+ }
+
+ // TODO: Why aren't these defined?
+#ifndef __APPLE__
+ if (khrAdvancedBlendSupported) {
+ switch (value) {
+ case NVRenderBlendEquation::Overlay:
+ return GL_OVERLAY_KHR;
+ case NVRenderBlendEquation::ColorBurn:
+ return GL_COLORBURN_KHR;
+ case NVRenderBlendEquation::ColorDodge:
+ return GL_COLORDODGE_KHR;
+ default:
+ break;
+ }
+ }
+#endif
+
+ QT3DS_ASSERT(false);
+ return GL_FUNC_ADD;
+ }
+
+ static NVRenderFaces::Enum fromGLToFaces(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE(x, y) \
+ case x: \
+ return NVRenderFaces::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDER_FACE
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderFaces::Unknown;
+ }
+
+ static GLenum fromFacesToGL(NVRenderFaces::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE(x, y) \
+ case NVRenderFaces::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDER_FACE
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_FACE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVReadFaces::Enum fromGLToReadFaces(GLenum value)
+ {
+ switch (value) {
+ case GL_FRONT:
+ return NVReadFaces::Front;
+ case GL_BACK:
+ return NVReadFaces::Back;
+ case GL_COLOR_ATTACHMENT0:
+ return NVReadFaces::Color0;
+ case GL_COLOR_ATTACHMENT1:
+ return NVReadFaces::Color1;
+ case GL_COLOR_ATTACHMENT2:
+ return NVReadFaces::Color2;
+ case GL_COLOR_ATTACHMENT3:
+ return NVReadFaces::Color3;
+ case GL_COLOR_ATTACHMENT4:
+ return NVReadFaces::Color4;
+ case GL_COLOR_ATTACHMENT5:
+ return NVReadFaces::Color5;
+ case GL_COLOR_ATTACHMENT6:
+ return NVReadFaces::Color6;
+ case GL_COLOR_ATTACHMENT7:
+ return NVReadFaces::Color7;
+
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVReadFaces::Unknown;
+ }
+
+ static GLenum fromReadFacesToGL(NVReadFaces::Enum value)
+ {
+ switch (value) {
+ case NVReadFaces::Front:
+ return GL_FRONT;
+ case NVReadFaces::Back:
+ return GL_BACK;
+ case NVReadFaces::Color0:
+ return GL_COLOR_ATTACHMENT0;
+ case NVReadFaces::Color1:
+ return GL_COLOR_ATTACHMENT1;
+ case NVReadFaces::Color2:
+ return GL_COLOR_ATTACHMENT2;
+ case NVReadFaces::Color3:
+ return GL_COLOR_ATTACHMENT3;
+ case NVReadFaces::Color4:
+ return GL_COLOR_ATTACHMENT4;
+ case NVReadFaces::Color5:
+ return GL_COLOR_ATTACHMENT5;
+ case NVReadFaces::Color6:
+ return GL_COLOR_ATTACHMENT6;
+ case NVReadFaces::Color7:
+ return GL_COLOR_ATTACHMENT7;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderWinding::Enum fromGLToWinding(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_WINDING(x, y) \
+ case x: \
+ return NVRenderWinding::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDER_WINDING
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_WINDING
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderWinding::Unknown;
+ }
+
+ static GLenum fromWindingToGL(NVRenderWinding::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_WINDING(x, y) \
+ case NVRenderWinding::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDER_WINDING
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_RENDER_WINDING
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderBoolOp::Enum fromGLToBoolOp(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(x, y) \
+ case x: \
+ return NVRenderBoolOp::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BOOL_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderBoolOp::Unknown;
+ }
+
+ static GLenum fromBoolOpToGL(NVRenderBoolOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(x, y) \
+ case NVRenderBoolOp::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BOOL_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderHint::Enum fromGLToHint(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_HINT(x, y) \
+ case x: \
+ return NVRenderHint::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_HINT
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_HINT
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderHint::Unknown;
+ }
+
+ static GLenum fromHintToGL(NVRenderHint::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_HINT(x, y) \
+ case NVRenderHint::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_HINT
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_HINT
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderStencilOp::Enum fromGLToStencilOp(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(x, y) \
+ case x: \
+ return NVRenderStencilOp::y;
+ QT3DS_RENDER_ITERATE_QT3DS_GL_STENCIL_OP
+#undef QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return NVRenderStencilOp::Unknown;
+ }
+
+ static GLenum fromStencilOpToGL(NVRenderStencilOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP(x, y) \
+ case NVRenderStencilOp::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_QT3DS_GL_STENCIL_OP
+#undef QT3DS_RENDER_HANDLE_QT3DS_GL_STENCIL_OP
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderComponentTypes::Enum fromGLToBufferComponentTypes(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(x, y) \
+ case x: \
+ return NVRenderComponentTypes::y;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE_ALIAS(x, y)
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BUFFER_COMPONENT_TYPES
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE_ALIAS
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderComponentTypes::Unknown;
+ }
+
+ static GLenum fromBufferComponentTypesToGL(NVRenderComponentTypes::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE(x, y) \
+ case NVRenderComponentTypes::y: \
+ return x;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE_ALIAS(x, y) \
+ case NVRenderComponentTypes::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BUFFER_COMPONENT_TYPES
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_COMPONENT_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static GLenum fromIndexBufferComponentsTypesToGL(NVRenderComponentTypes::Enum value)
+ {
+ switch (value) {
+ case NVRenderComponentTypes::QT3DSU8:
+ return GL_UNSIGNED_BYTE;
+ case NVRenderComponentTypes::QT3DSU16:
+ return GL_UNSIGNED_SHORT;
+ case NVRenderComponentTypes::QT3DSU32:
+ return GL_UNSIGNED_INT;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static GLenum fromBindBufferFlagsToGL(NVRenderBufferBindFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLenum retval = GL_INVALID_ENUM;
+ if (value & NVRenderBufferBindValues::Vertex)
+ retval = GL_ARRAY_BUFFER;
+ else if (value & NVRenderBufferBindValues::Index)
+ retval = GL_ELEMENT_ARRAY_BUFFER;
+ else if (value & NVRenderBufferBindValues::Constant)
+ retval = GL_UNIFORM_BUFFER;
+ else if (value & NVRenderBufferBindValues::Storage)
+ retval = GL_SHADER_STORAGE_BUFFER;
+ else if (value & NVRenderBufferBindValues::Atomic_Counter)
+ retval = GL_ATOMIC_COUNTER_BUFFER;
+ else if (value & NVRenderBufferBindValues::Draw_Indirect)
+ retval = GL_DRAW_INDIRECT_BUFFER;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+ }
+
+ static NVRenderBufferBindFlags fromGLToBindBufferFlags(GLenum value)
+ {
+ QT3DSU32 retval = 0;
+
+ if (value == GL_ARRAY_BUFFER)
+ retval |= NVRenderBufferBindValues::Vertex;
+ else if (value == GL_ELEMENT_ARRAY_BUFFER)
+ retval |= NVRenderBufferBindValues::Index;
+ else if (value == GL_UNIFORM_BUFFER)
+ retval |= NVRenderBufferBindValues::Constant;
+ else if (value == GL_SHADER_STORAGE_BUFFER)
+ retval |= NVRenderBufferBindValues::Storage;
+ else if (value == GL_ATOMIC_COUNTER_BUFFER)
+ retval |= NVRenderBufferBindValues::Atomic_Counter;
+ else if (value == GL_DRAW_INDIRECT_BUFFER)
+ retval |= NVRenderBufferBindValues::Draw_Indirect;
+ else
+ QT3DS_ASSERT(false);
+
+ return NVRenderBufferBindFlags(retval);
+ }
+
+ static NVRenderBufferUsageType::Enum fromGLToBufferUsageType(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_BUFFER_USAGE_TYPE(x, y) \
+ case x: \
+ return NVRenderBufferUsageType::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BUFFER_USAGE_TYPE
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_BUFFER_USAGE_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderBufferUsageType::Unknown;
+ }
+
+ static GLenum fromBufferUsageTypeToGL(NVRenderBufferUsageType::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_BUFFER_USAGE_TYPE(x, y) \
+ case NVRenderBufferUsageType::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BUFFER_USAGE_TYPE
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_BUFFER_USAGE_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static GLenum fromQueryTypeToGL(NVRenderQueryType::Enum type)
+ {
+ GLenum retval = GL_INVALID_ENUM;
+ if (type == NVRenderQueryType::Samples)
+ retval = GL_ANY_SAMPLES_PASSED;
+ else if (type == NVRenderQueryType::Timer)
+ retval = GL_TIME_ELAPSED;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+ }
+
+ static GLenum fromQueryResultTypeToGL(NVRenderQueryResultType::Enum type)
+ {
+ GLenum retval = GL_INVALID_ENUM;
+ if (type == NVRenderQueryResultType::ResultAvailable)
+ retval = GL_QUERY_RESULT_AVAILABLE;
+ else if (type == NVRenderQueryResultType::Result)
+ retval = GL_QUERY_RESULT;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+ }
+
+ static GLenum fromSyncTypeToGL(NVRenderSyncType::Enum type)
+ {
+ GLenum retval = GL_INVALID_ENUM;
+ if (type == NVRenderSyncType::GpuCommandsComplete)
+ retval = GL_SYNC_GPU_COMMANDS_COMPLETE;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+ }
+
+ static NVRenderTextureFormats::Enum
+ replaceDeprecatedTextureFormat(NVRenderContextType type, NVRenderTextureFormats::Enum value,
+ NVRenderTextureSwizzleMode::Enum &swizzleMode)
+ {
+ NVRenderContextType deprecatedContextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+ NVRenderTextureFormats::Enum newValue = value;
+ swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+
+ if (!(type & deprecatedContextFlags)) {
+ switch (value) {
+ case NVRenderTextureFormats::Luminance8:
+ newValue = NVRenderTextureFormats::R8;
+ swizzleMode = NVRenderTextureSwizzleMode::L8toR8;
+ break;
+ case NVRenderTextureFormats::LuminanceAlpha8:
+ newValue = NVRenderTextureFormats::RG8;
+ swizzleMode = NVRenderTextureSwizzleMode::L8A8toRG8;
+ break;
+ case NVRenderTextureFormats::Alpha8:
+ newValue = NVRenderTextureFormats::R8;
+ swizzleMode = NVRenderTextureSwizzleMode::A8toR8;
+ break;
+ case NVRenderTextureFormats::Luminance16:
+ newValue = NVRenderTextureFormats::R16;
+ swizzleMode = NVRenderTextureSwizzleMode::L16toR16;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return newValue;
+ }
+
+ static void
+ NVRenderConvertSwizzleModeToGL(const NVRenderTextureSwizzleMode::Enum swizzleMode,
+ GLint glSwizzle[4])
+ {
+ switch (swizzleMode) {
+ case NVRenderTextureSwizzleMode::L16toR16:
+ case NVRenderTextureSwizzleMode::L8toR8:
+ glSwizzle[0] = GL_RED;
+ glSwizzle[1] = GL_RED;
+ glSwizzle[2] = GL_RED;
+ glSwizzle[3] = GL_ONE;
+ break;
+ case NVRenderTextureSwizzleMode::L8A8toRG8:
+ glSwizzle[0] = GL_RED;
+ glSwizzle[1] = GL_RED;
+ glSwizzle[2] = GL_RED;
+ glSwizzle[3] = GL_GREEN;
+ break;
+ case NVRenderTextureSwizzleMode::A8toR8:
+ glSwizzle[0] = GL_ZERO;
+ glSwizzle[1] = GL_ZERO;
+ glSwizzle[2] = GL_ZERO;
+ glSwizzle[3] = GL_RED;
+ break;
+ case NVRenderTextureSwizzleMode::NoSwizzle:
+ default:
+ glSwizzle[0] = GL_RED;
+ glSwizzle[1] = GL_GREEN;
+ glSwizzle[2] = GL_BLUE;
+ glSwizzle[3] = GL_ALPHA;
+ break;
+ }
+ }
+
+ static bool fromUncompressedTextureFormatToGL(NVRenderContextType type,
+ NVRenderTextureFormats::Enum value,
+ GLenum &outFormat, GLenum &outDataType,
+ GLenum &outInternalFormat)
+ {
+ switch (value) {
+ case NVRenderTextureFormats::R8:
+ outFormat = GL_RED;
+ outInternalFormat = GL_R8;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::RG8:
+ outFormat = GL_RG;
+ outInternalFormat = GL_RG8;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::RGBA8:
+ outFormat = GL_RGBA;
+ outInternalFormat = GL_RGBA8;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::RGB8:
+ outFormat = GL_RGB;
+ outInternalFormat = GL_RGB8;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::RGB565:
+ outFormat = GL_RGB;
+ outInternalFormat = GL_RGB8;
+ outDataType = GL_UNSIGNED_SHORT_5_6_5;
+ return true;
+ case NVRenderTextureFormats::RGBA5551:
+ outFormat = GL_RGBA;
+ outInternalFormat = GL_RGBA8;
+ outDataType = GL_UNSIGNED_SHORT_5_5_5_1;
+ return true;
+ case NVRenderTextureFormats::Alpha8:
+ outFormat = GL_ALPHA;
+ outInternalFormat = GL_ALPHA;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::Luminance8:
+ outFormat = GL_LUMINANCE;
+ outInternalFormat = GL_LUMINANCE;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::LuminanceAlpha8:
+ outFormat = GL_LUMINANCE_ALPHA;
+ outInternalFormat = GL_LUMINANCE_ALPHA;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::Luminance16:
+#if defined(QT_OPENGL_ES)
+ outFormat = GL_LUMINANCE16F_EXT;
+ outInternalFormat = GL_LUMINANCE16F_EXT;
+#else
+ outFormat = GL_LUMINANCE;
+ outInternalFormat = GL_LUMINANCE;
+#endif
+ outDataType = GL_UNSIGNED_INT;
+ return true;
+ default:
+ break;
+ }
+
+ NVRenderContextType contextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+ // check extented texture formats
+ if (!(type & contextFlags)) {
+ switch (value) {
+ case NVRenderTextureFormats::R16: {
+ if (IsGlEsContext(type)) {
+ outFormat = GL_RED_INTEGER;
+ outInternalFormat = GL_R16UI;
+ } else {
+ outFormat = GL_RED;
+ outInternalFormat = GL_R16;
+ }
+ outDataType = GL_UNSIGNED_SHORT;
+ return true;
+ }
+ case NVRenderTextureFormats::R16F:
+ outFormat = GL_RED;
+ outInternalFormat = GL_R16F;
+ outDataType = GL_HALF_FLOAT;
+ return true;
+ case NVRenderTextureFormats::R32UI:
+ outFormat = GL_RED_INTEGER;
+ outInternalFormat = GL_R32UI;
+ outDataType = GL_UNSIGNED_INT;
+ return true;
+ case NVRenderTextureFormats::R32F:
+ outFormat = GL_RED;
+ outInternalFormat = GL_R32F;
+ outDataType = GL_FLOAT;
+ return true;
+ case NVRenderTextureFormats::RGBA16F:
+ outFormat = GL_RGBA;
+ outInternalFormat = GL_RGBA16F;
+ outDataType = GL_HALF_FLOAT;
+ return true;
+ case NVRenderTextureFormats::RG16F:
+ outFormat = GL_RG;
+ outInternalFormat = GL_RG16F;
+ outDataType = GL_HALF_FLOAT;
+ return true;
+ case NVRenderTextureFormats::RG32F:
+ outFormat = GL_RG;
+ outInternalFormat = GL_RG32F;
+ outDataType = GL_FLOAT;
+ return true;
+ case NVRenderTextureFormats::RGBA32F:
+ outFormat = GL_RGBA;
+ outInternalFormat = GL_RGBA32F;
+ outDataType = GL_FLOAT;
+ return true;
+ case NVRenderTextureFormats::RGB32F:
+ outFormat = GL_RGB;
+ outInternalFormat = GL_RGB32F;
+ outDataType = GL_FLOAT;
+ return true;
+ case NVRenderTextureFormats::R11G11B10:
+ outFormat = GL_RGB;
+ outInternalFormat = GL_R11F_G11F_B10F;
+ outDataType = GL_UNSIGNED_INT_10F_11F_11F_REV;
+ return true;
+ case NVRenderTextureFormats::RGB9E5:
+ outFormat = GL_RGB;
+ outInternalFormat = GL_RGB9_E5;
+ outDataType = GL_UNSIGNED_INT_5_9_9_9_REV;
+ return true;
+ case NVRenderTextureFormats::SRGB8:
+ outFormat = GL_RGB;
+ outInternalFormat = GL_SRGB8;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ case NVRenderTextureFormats::SRGB8A8:
+ outFormat = GL_RGBA;
+ outInternalFormat = GL_SRGB8_ALPHA8;
+ outDataType = GL_UNSIGNED_BYTE;
+ return true;
+ default:
+ break;
+ }
+ }
+
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ static GLenum fromCompressedTextureFormatToGL(NVRenderTextureFormats::Enum value)
+ {
+ switch (value) {
+ case NVRenderTextureFormats::RGBA_DXT1:
+ return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case NVRenderTextureFormats::RGB_DXT1:
+ return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ case NVRenderTextureFormats::RGBA_DXT3:
+ return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ case NVRenderTextureFormats::RGBA_DXT5:
+ return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static bool fromDepthTextureFormatToGL(NVRenderContextType type,
+ NVRenderTextureFormats::Enum value,
+ GLenum &outFormat, GLenum &outDataType,
+ GLenum &outInternalFormat)
+ {
+ NVRenderContextType theContextFlags(NVRenderContextValues::GLES2
+ | NVRenderContextValues::GL2);
+
+ bool supportDepth24 = !(type & theContextFlags);
+ bool supportDepth32f = !(type & theContextFlags);
+ bool supportDepth24Stencil8 = !(type & theContextFlags);
+
+ switch (value) {
+ case NVRenderTextureFormats::Depth16:
+ outFormat = GL_DEPTH_COMPONENT;
+ outInternalFormat = GL_DEPTH_COMPONENT16;
+ outDataType = GL_UNSIGNED_SHORT;
+ return true;
+ case NVRenderTextureFormats::Depth24:
+ outFormat = GL_DEPTH_COMPONENT;
+ outInternalFormat = (supportDepth24) ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16;
+ outDataType = (supportDepth24) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+ return true;
+ case NVRenderTextureFormats::Depth32:
+ outFormat = GL_DEPTH_COMPONENT;
+ outInternalFormat =
+ (supportDepth32f) ? GL_DEPTH_COMPONENT32F : GL_DEPTH_COMPONENT16;
+ outDataType = (supportDepth32f) ? GL_FLOAT : GL_UNSIGNED_SHORT;
+ return true;
+ case NVRenderTextureFormats::Depth24Stencil8:
+ outFormat = (supportDepth24Stencil8) ? GL_DEPTH_STENCIL : GL_DEPTH_COMPONENT;
+ outInternalFormat =
+ (supportDepth24Stencil8) ? GL_DEPTH24_STENCIL8 : GL_DEPTH_COMPONENT16;
+ outDataType = (supportDepth24Stencil8) ? GL_UNSIGNED_INT_24_8 : GL_UNSIGNED_SHORT;
+ return true;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ static GLenum fromTextureTargetToGL(NVRenderTextureTargetType::Enum value)
+ {
+ GLenum retval = 0;
+ if (value == NVRenderTextureTargetType::Texture2D)
+ retval = GL_TEXTURE_2D;
+ else if (value == NVRenderTextureTargetType::Texture2D_MS)
+ retval = GL_TEXTURE_2D_MULTISAMPLE;
+ else if (value == NVRenderTextureTargetType::Texture2D_Array)
+ retval = GL_TEXTURE_2D_ARRAY;
+ else if (value == NVRenderTextureTargetType::TextureCube)
+ retval = GL_TEXTURE_CUBE_MAP;
+ else if (value == NVRenderTextureTargetType::TextureCubeNegX)
+ retval = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+ else if (value == NVRenderTextureTargetType::TextureCubePosX)
+ retval = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ else if (value == NVRenderTextureTargetType::TextureCubeNegY)
+ retval = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ else if (value == NVRenderTextureTargetType::TextureCubePosY)
+ retval = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+ else if (value == NVRenderTextureTargetType::TextureCubeNegZ)
+ retval = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ else if (value == NVRenderTextureTargetType::TextureCubePosZ)
+ retval = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+ }
+
+ static NVRenderTextureTargetType::Enum fromGLToTextureTarget(GLenum value)
+ {
+ NVRenderTextureTargetType::Enum retval = NVRenderTextureTargetType::Unknown;
+
+ if (value == GL_TEXTURE_2D)
+ retval = NVRenderTextureTargetType::Texture2D;
+ else if (value == GL_TEXTURE_2D_MULTISAMPLE)
+ retval = NVRenderTextureTargetType::Texture2D_MS;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+ }
+
+ static GLenum fromTextureUnitToGL(NVRenderTextureUnit::Enum value)
+ {
+ QT3DSU32 v = value;
+ GLenum retval = GL_TEXTURE0;
+ retval = GL_TEXTURE0 + v;
+
+ return retval;
+ }
+
+ static GLenum fromGLToTextureUnit(GLenum value)
+ {
+ QT3DS_ASSERT(value > GL_TEXTURE0);
+
+ QT3DSU32 v = value - GL_TEXTURE0;
+ NVRenderTextureUnit::Enum retval =
+ NVRenderTextureUnit::Enum(NVRenderTextureUnit::TextureUnit_0 + v);
+
+ return retval;
+ }
+
+ static GLenum fromTextureMinifyingOpToGL(NVRenderTextureMinifyingOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP(x, y) \
+ case NVRenderTextureMinifyingOp::y: \
+ return x;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(x, y) \
+ case NVRenderTextureMinifyingOp::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderTextureMinifyingOp::Enum fromGLToTextureMinifyingOp(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP(x, y) \
+ case x: \
+ return NVRenderTextureMinifyingOp::y;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(x, y) \
+ case x: \
+ return NVRenderTextureMinifyingOp::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderTextureMinifyingOp::Unknown;
+ }
+
+ static GLenum fromTextureMagnifyingOpToGL(NVRenderTextureMagnifyingOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP(x, y) \
+ case NVRenderTextureMagnifyingOp::y: \
+ return x;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(x, y)
+ QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderTextureMagnifyingOp::Enum fromGLToTextureMagnifyingOp(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP(x, y) \
+ case x: \
+ return NVRenderTextureMagnifyingOp::y;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP(x, y)
+ QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_SCALE_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_MINIFYING_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderTextureMagnifyingOp::Unknown;
+ }
+
+ static GLenum fromTextureCoordOpToGL(NVRenderTextureCoordOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP(x, y) \
+ case NVRenderTextureCoordOp::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_WRAP_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderTextureCoordOp::Enum fromGLToTextureCoordOp(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP(x, y) \
+ case x: \
+ return NVRenderTextureCoordOp::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_TEXTURE_WRAP_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_TEXTURE_WRAP_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderTextureCoordOp::Unknown;
+ }
+
+ static GLenum fromTextureCompareModeToGL(NVRenderTextureCompareMode::Enum value)
+ {
+ switch (value) {
+ case NVRenderTextureCompareMode::NoCompare:
+ return GL_NONE;
+ case NVRenderTextureCompareMode::CompareToRef:
+ return GL_COMPARE_REF_TO_TEXTURE;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return NVRenderTextureCompareMode::Unknown;
+ }
+
+ static GLenum fromGLToTextureCompareMode(GLenum value)
+ {
+ switch (value) {
+ case GL_NONE:
+ return NVRenderTextureCompareMode::NoCompare;
+ case GL_COMPARE_REF_TO_TEXTURE:
+ return NVRenderTextureCompareMode::CompareToRef;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return GL_INVALID_ENUM;
+ }
+
+ static GLenum fromTextureCompareFuncToGL(NVRenderTextureCompareOp::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP(x, y) \
+ case NVRenderTextureCompareOp::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_BOOL_OP
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_BOOL_OP
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static GLenum fromImageFormatToGL(NVRenderTextureFormats::Enum value)
+ {
+ switch (value) {
+ case NVRenderTextureFormats::R8:
+ return GL_R8;
+ case NVRenderTextureFormats::R32I:
+ return GL_R32I;
+ case NVRenderTextureFormats::R32UI:
+ return GL_R32UI;
+ case NVRenderTextureFormats::R32F:
+ return GL_R32F;
+ case NVRenderTextureFormats::RGBA8:
+ return GL_RGBA8;
+ case NVRenderTextureFormats::SRGB8A8:
+ return GL_RGBA8_SNORM;
+ case NVRenderTextureFormats::RG16F:
+ return GL_RG16F;
+ case NVRenderTextureFormats::RGBA16F:
+ return GL_RGBA16F;
+ case NVRenderTextureFormats::RGBA32F:
+ return GL_RGBA32F;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return GL_INVALID_ENUM;
+ }
+
+ static GLenum fromImageAccessToGL(NVRenderImageAccessType::Enum value)
+ {
+ switch (value) {
+ case NVRenderImageAccessType::Read:
+ return GL_READ_ONLY;
+ case NVRenderImageAccessType::Write:
+ return GL_WRITE_ONLY;
+ case NVRenderImageAccessType::ReadWrite:
+ return GL_READ_WRITE;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return GL_INVALID_ENUM;
+ }
+
+ static GLbitfield fromBufferAccessBitToGL(NVRenderBufferAccessFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLbitfield retval = 0;
+
+ if (value & NVRenderBufferAccessTypeValues::Read)
+ retval |= GL_MAP_READ_BIT;
+ if (value & NVRenderBufferAccessTypeValues::Write)
+ retval |= GL_MAP_WRITE_BIT;
+ if (value & NVRenderBufferAccessTypeValues::Invalid)
+ retval |= GL_MAP_INVALIDATE_BUFFER_BIT;
+ if (value & NVRenderBufferAccessTypeValues::InvalidRange)
+ retval |= GL_MAP_INVALIDATE_RANGE_BIT;
+
+ QT3DS_ASSERT(retval);
+ return retval;
+ }
+
+ static GLbitfield fromMemoryBarrierFlagsToGL(NVRenderBufferBarrierFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLbitfield retval = 0;
+
+ if (value & NVRenderBufferBarrierValues::AtomicCounter)
+ retval |= GL_ATOMIC_COUNTER_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::BufferUpdate)
+ retval |= GL_BUFFER_UPDATE_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::CommandBuffer)
+ retval |= GL_COMMAND_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::ElementArray)
+ retval |= GL_ELEMENT_ARRAY_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::Framebuffer)
+ retval |= GL_FRAMEBUFFER_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::PixelBuffer)
+ retval |= GL_PIXEL_BUFFER_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::ShaderImageAccess)
+ retval |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::ShaderStorage)
+ retval |= GL_SHADER_STORAGE_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::TextureFetch)
+ retval |= GL_TEXTURE_FETCH_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::TextureUpdate)
+ retval |= GL_TEXTURE_UPDATE_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::TransformFeedback)
+ retval |= GL_TRANSFORM_FEEDBACK_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::UniformBuffer)
+ retval |= GL_UNIFORM_BARRIER_BIT;
+ if (value & NVRenderBufferBarrierValues::VertexAttribArray)
+ retval |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
+
+ QT3DS_ASSERT(retval);
+ return retval;
+ }
+
+ static GLbitfield fromShaderTypeFlagsToGL(NVRenderShaderTypeFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLbitfield retval = 0;
+
+ if (value & NVRenderShaderTypeValue::Vertex)
+ retval |= GL_VERTEX_SHADER_BIT;
+ if (value & NVRenderShaderTypeValue::Fragment)
+ retval |= GL_FRAGMENT_SHADER_BIT;
+ if (value & NVRenderShaderTypeValue::TessControl)
+ retval |= GL_TESS_CONTROL_SHADER_BIT;
+ if (value & NVRenderShaderTypeValue::TessEvaluation)
+ retval |= GL_TESS_EVALUATION_SHADER_BIT;
+ if (value & NVRenderShaderTypeValue::Geometry)
+#if defined(QT_OPENGL_ES)
+ retval |= GL_GEOMETRY_SHADER_BIT_EXT;
+#else
+ retval |= GL_GEOMETRY_SHADER_BIT;
+#endif
+
+ QT3DS_ASSERT(retval || !value);
+ return retval;
+ }
+
+ static GLenum fromPropertyDataTypesToShaderGL(NVRenderShaderDataTypes::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(gl, nv) \
+ case NVRenderShaderDataTypes::nv: \
+ return gl;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_SHADER_UNIFORM_TYPES
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderShaderDataTypes::Enum fromShaderGLToPropertyDataTypes(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES(gl, nv) \
+ case gl: \
+ return NVRenderShaderDataTypes::nv;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_SHADER_UNIFORM_TYPES
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_UNIFORM_TYPES
+ case GL_SAMPLER_2D_SHADOW:
+ return NVRenderShaderDataTypes::NVRenderTexture2DPtr;
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return NVRenderShaderDataTypes::QT3DSU32;
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ return NVRenderShaderDataTypes::NVRenderImage2DPtr;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderShaderDataTypes::Unknown;
+ }
+
+ static GLenum fromComponentTypeAndNumCompsToAttribGL(NVRenderComponentTypes::Enum compType,
+ QT3DSU32 numComps)
+ {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(gl, ct, nc) \
+ if (compType == NVRenderComponentTypes::ct && numComps == nc) \
+ return gl;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_SHADER_ATTRIB_TYPES
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static void fromAttribGLToComponentTypeAndNumComps(
+ GLenum enumVal, NVRenderComponentTypes::Enum &outCompType, QT3DSU32 &outNumComps)
+ {
+ switch (enumVal) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES(gl, ct, nc) \
+ case gl: \
+ outCompType = NVRenderComponentTypes::ct; \
+ outNumComps = nc; \
+ return;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_SHADER_ATTRIB_TYPES
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_SHADER_ATTRIB_TYPES
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ outCompType = NVRenderComponentTypes::Unknown;
+ outNumComps = 0;
+ }
+
+ static GLenum
+ fromRenderBufferFormatsToRenderBufferGL(NVRenderRenderBufferFormats::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(gl, nv) \
+ case NVRenderRenderBufferFormats::nv: \
+ return gl;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_FORMATS
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_COVERAGE_FORMATS
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderRenderBufferFormats::Enum
+ fromRenderBufferGLToRenderBufferFormats(GLenum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT(gl, nv) \
+ case gl: \
+ return NVRenderRenderBufferFormats::nv;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_FORMATS
+ QT3DS_RENDER_ITERATE_GL_QT3DS_RENDERBUFFER_COVERAGE_FORMATS
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_RENDERBUFFER_FORMAT
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderRenderBufferFormats::Unknown;
+ }
+
+ static GLenum fromFramebufferAttachmentsToGL(NVRenderFrameBufferAttachments::Enum value)
+ {
+ switch (value) {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(x, idx) \
+ case NVRenderFrameBufferAttachments::x: \
+ return GL_COLOR_ATTACHMENT0 + idx;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT(x, y) \
+ case NVRenderFrameBufferAttachments::y: \
+ return x;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_ATTACHMENTS
+ QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_COVERAGE_ATTACHMENTS
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderFrameBufferAttachments::Unknown;
+ }
+
+ static NVRenderFrameBufferAttachments::Enum fromGLToFramebufferAttachments(GLenum value)
+ {
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT(x, idx) \
+ if (value == GL_COLOR_ATTACHMENT0 + idx) \
+ return NVRenderFrameBufferAttachments::x;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT(x, y) \
+ if (value == x) \
+ return NVRenderFrameBufferAttachments::y;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_ATTACHMENTS
+ QT3DS_RENDER_ITERATE_GL_QT3DS_FRAMEBUFFER_COVERAGE_ATTACHMENTS
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_COLOR_ATTACHMENT
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_FRAMEBUFFER_ATTACHMENT
+ QT3DS_ASSERT(false);
+ return NVRenderFrameBufferAttachments::Unknown;
+ }
+
+ static GLbitfield fromClearFlagsToGL(NVRenderClearFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLbitfield retval = 0;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS(gl, nv) \
+ if ((value & NVRenderClearValues::nv)) \
+ retval |= gl;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_CLEAR_FLAGS
+ QT3DS_RENDER_ITERATE_GL_QT3DS_CLEAR_COVERAGE_FLAGS
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS
+ return retval;
+ }
+
+ static NVRenderClearFlags fromGLToClearFlags(GLbitfield value)
+ {
+ QT3DSU32 retval = 0;
+#define QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS(gl, nv) \
+ if ((value & gl)) \
+ retval |= NVRenderClearValues::nv;
+ QT3DS_RENDER_ITERATE_GL_QT3DS_CLEAR_FLAGS
+ QT3DS_RENDER_ITERATE_GL_QT3DS_CLEAR_COVERAGE_FLAGS
+#undef QT3DS_RENDER_HANDLE_GL_QT3DS_CLEAR_FLAGS
+ return NVRenderClearFlags(retval);
+ }
+
+ static GLenum fromDrawModeToGL(NVRenderDrawMode::Enum value, bool inTesselationSupported)
+ {
+ switch (value) {
+ case NVRenderDrawMode::Points:
+ return GL_POINTS;
+ case NVRenderDrawMode::Lines:
+ return GL_LINES;
+ case NVRenderDrawMode::LineStrip:
+ return GL_LINE_STRIP;
+ case NVRenderDrawMode::LineLoop:
+ return GL_LINE_LOOP;
+ case NVRenderDrawMode::TriangleStrip:
+ return GL_TRIANGLE_STRIP;
+ case NVRenderDrawMode::TriangleFan:
+ return GL_TRIANGLE_FAN;
+ case NVRenderDrawMode::Triangles:
+ return GL_TRIANGLES;
+ case NVRenderDrawMode::Patches:
+ return (inTesselationSupported) ? GL_PATCHES : GL_TRIANGLES;
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return GL_INVALID_ENUM;
+ }
+
+ static NVRenderDrawMode::Enum fromGLToDrawMode(GLenum value)
+ {
+ switch (value) {
+ case GL_POINTS:
+ return NVRenderDrawMode::Points;
+ case GL_LINES:
+ return NVRenderDrawMode::Lines;
+ case GL_LINE_STRIP:
+ return NVRenderDrawMode::LineStrip;
+ case GL_LINE_LOOP:
+ return NVRenderDrawMode::LineLoop;
+ case GL_TRIANGLE_STRIP:
+ return NVRenderDrawMode::TriangleStrip;
+ case GL_TRIANGLE_FAN:
+ return NVRenderDrawMode::TriangleFan;
+ case GL_TRIANGLES:
+ return NVRenderDrawMode::Triangles;
+ case GL_PATCHES:
+ return NVRenderDrawMode::Patches;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderDrawMode::Unknown;
+ }
+
+ static GLenum fromRenderStateToGL(NVRenderState::Enum value)
+ {
+ switch (value) {
+ case NVRenderState::Blend:
+ return GL_BLEND;
+ case NVRenderState::CullFace:
+ return GL_CULL_FACE;
+ case NVRenderState::DepthTest:
+ return GL_DEPTH_TEST;
+ case NVRenderState::Multisample:
+#if defined(QT_OPENGL_ES)
+ return GL_MULTISAMPLE_EXT;
+#else
+ return GL_MULTISAMPLE;
+#endif
+ case NVRenderState::StencilTest:
+ return GL_STENCIL_TEST;
+ case NVRenderState::ScissorTest:
+ return GL_SCISSOR_TEST;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ static NVRenderState::Enum fromGLToRenderState(GLenum value)
+ {
+ switch (value) {
+ case GL_BLEND:
+ return NVRenderState::Blend;
+ case GL_CULL_FACE:
+ return NVRenderState::CullFace;
+ case GL_DEPTH_TEST:
+ return NVRenderState::DepthTest;
+#if defined(QT_OPENGL_ES)
+ case GL_MULTISAMPLE_EXT:
+#else
+ case GL_MULTISAMPLE:
+#endif
+ return NVRenderState::Multisample;
+ case GL_STENCIL_TEST:
+ return NVRenderState::StencilTest;
+ case GL_SCISSOR_TEST:
+ return NVRenderState::ScissorTest;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NVRenderState::Unknown;
+ }
+
+ static bool fromReadPixelsToGlFormatAndType(NVRenderReadPixelFormats::Enum inReadPixels,
+ GLuint *outFormat, GLuint *outType)
+ {
+ switch (inReadPixels) {
+ case NVRenderReadPixelFormats::Alpha8:
+ *outFormat = GL_ALPHA;
+ *outType = GL_UNSIGNED_BYTE;
+ break;
+ case NVRenderReadPixelFormats::RGB565:
+ *outFormat = GL_RGB;
+ *outType = GL_UNSIGNED_SHORT_5_6_5;
+ case NVRenderReadPixelFormats::RGB8:
+ *outFormat = GL_RGB;
+ *outType = GL_UNSIGNED_BYTE;
+ break;
+ case NVRenderReadPixelFormats::RGBA4444:
+ *outFormat = GL_RGBA;
+ *outType = GL_UNSIGNED_SHORT_4_4_4_4;
+ break;
+ case NVRenderReadPixelFormats::RGBA5551:
+ *outFormat = GL_RGBA;
+ *outType = GL_UNSIGNED_SHORT_5_5_5_1;
+ break;
+ case NVRenderReadPixelFormats::RGBA8:
+ *outFormat = GL_RGBA;
+ *outType = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ *outFormat = 0;
+ *outType = 0;
+ QT3DS_ASSERT(false);
+ return false;
+ };
+
+ return true;
+ }
+
+ static GLenum fromPathFillModeToGL(NVRenderPathFillMode::Enum inMode)
+ {
+ GLenum glFillMode;
+
+ switch (inMode) {
+ case NVRenderPathFillMode::Fill:
+ glFillMode = GL_PATH_FILL_MODE_NV;
+ break;
+ case NVRenderPathFillMode::CountUp:
+ glFillMode = GL_COUNT_UP_NV;
+ break;
+ case NVRenderPathFillMode::CountDown:
+ glFillMode = GL_COUNT_DOWN_NV;
+ break;
+ case NVRenderPathFillMode::Invert:
+ glFillMode = GL_INVERT;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ glFillMode = GL_PATH_FILL_MODE_NV;
+ break;
+ }
+
+ return glFillMode;
+ }
+
+ static GLenum fromPathFontTargetToGL(NVRenderPathFontTarget::Enum inFontTarget)
+ {
+ GLenum glFontTarget;
+
+ switch (inFontTarget) {
+ case NVRenderPathFontTarget::StandardFont:
+ glFontTarget = GL_STANDARD_FONT_NAME_NV;
+ break;
+ case NVRenderPathFontTarget::SystemFont:
+ glFontTarget = GL_SYSTEM_FONT_NAME_NV;
+ break;
+ case NVRenderPathFontTarget::FileFont:
+ glFontTarget = GL_FILE_NAME_NV;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ glFontTarget = GL_STANDARD_FONT_NAME_NV;
+ break;
+ }
+
+ return glFontTarget;
+ }
+
+ static NVRenderPathReturnValues::Enum fromGLToPathFontReturn(GLenum inReturnValue)
+ {
+ NVRenderPathReturnValues::Enum returnValue;
+
+ switch (inReturnValue) {
+ case GL_FONT_GLYPHS_AVAILABLE_NV:
+ returnValue = NVRenderPathReturnValues::FontGlypsAvailable;
+ break;
+ case GL_FONT_TARGET_UNAVAILABLE_NV:
+ returnValue = NVRenderPathReturnValues::FontTargetUnavailable;
+ break;
+ case GL_FONT_UNAVAILABLE_NV:
+ returnValue = NVRenderPathReturnValues::FontUnavailable;
+ break;
+ case GL_FONT_UNINTELLIGIBLE_NV:
+ returnValue = NVRenderPathReturnValues::FontUnintelligible;
+ break;
+ case GL_INVALID_ENUM:
+ case GL_INVALID_VALUE:
+ returnValue = NVRenderPathReturnValues::InvalidEnum;
+ break;
+ case GL_OUT_OF_MEMORY:
+ returnValue = NVRenderPathReturnValues::OutOfMemory;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ returnValue = NVRenderPathReturnValues::FontTargetUnavailable;
+ break;
+ }
+
+ return returnValue;
+ }
+
+ static GLenum fromPathMissingGlyphsToGL(NVRenderPathMissingGlyphs::Enum inHandleGlyphs)
+ {
+ GLenum glMissingGlyphs;
+
+ switch (inHandleGlyphs) {
+ case NVRenderPathMissingGlyphs::SkipMissing:
+ glMissingGlyphs = GL_SKIP_MISSING_GLYPH_NV;
+ break;
+ case NVRenderPathMissingGlyphs::UseMissing:
+ glMissingGlyphs = GL_USE_MISSING_GLYPH_NV;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ glMissingGlyphs = GL_SKIP_MISSING_GLYPH_NV;
+ break;
+ }
+
+ return glMissingGlyphs;
+ }
+
+ static GLenum fromPathListModeToGL(NVRenderPathListMode::Enum inListMode)
+ {
+ GLenum glListMode;
+
+ switch (inListMode) {
+ case NVRenderPathListMode::AccumAdjacentPairs:
+ glListMode = GL_ACCUM_ADJACENT_PAIRS_NV;
+ break;
+ case NVRenderPathListMode::AdjacentPairs:
+ glListMode = GL_ADJACENT_PAIRS_NV;
+ break;
+ case NVRenderPathListMode::FirstToRest:
+ glListMode = GL_FIRST_TO_REST_NV;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ glListMode = GL_ACCUM_ADJACENT_PAIRS_NV;
+ break;
+ }
+
+ return glListMode;
+ }
+
+ static GLenum fromPathCoverModeToGL(NVRenderPathCoverMode::Enum inMode)
+ {
+ GLenum glCoverMode;
+
+ switch (inMode) {
+ case NVRenderPathCoverMode::ConvexHull:
+ glCoverMode = GL_CONVEX_HULL_NV;
+ break;
+ case NVRenderPathCoverMode::BoundingBox:
+ glCoverMode = GL_BOUNDING_BOX_NV;
+ break;
+ case NVRenderPathCoverMode::BoundingBoxOfBoundingBox:
+ glCoverMode = GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV;
+ break;
+ case NVRenderPathCoverMode::PathFillCover:
+ glCoverMode = GL_PATH_FILL_COVER_MODE_NV;
+ break;
+ case NVRenderPathCoverMode::PathStrokeCover:
+ glCoverMode = GL_PATH_STROKE_COVER_MODE_NV;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ glCoverMode = GL_BOUNDING_BOX_NV;
+ break;
+ }
+
+ return glCoverMode;
+ }
+
+ static GLenum fromPathTypeToGL(NVRenderPathFormatType::Enum value)
+ {
+ switch (value) {
+ case NVRenderPathFormatType::Byte:
+ return GL_BYTE;
+ case NVRenderPathFormatType::UByte:
+ return GL_UNSIGNED_BYTE;
+ case NVRenderPathFormatType::Short:
+ return GL_SHORT;
+ case NVRenderPathFormatType::UShort:
+ return GL_UNSIGNED_SHORT;
+ case NVRenderPathFormatType::Int:
+ return GL_INT;
+ case NVRenderPathFormatType::Uint:
+ return GL_UNSIGNED_INT;
+#if !defined(QT_OPENGL_ES)
+ case NVRenderPathFormatType::Bytes2:
+ return GL_2_BYTES_NV;
+ case NVRenderPathFormatType::Bytes3:
+ return GL_3_BYTES_NV;
+ case NVRenderPathFormatType::Bytes4:
+ return GL_4_BYTES_NV;
+#endif
+ case NVRenderPathFormatType::Utf8:
+ return GL_UTF8_NV;
+ case NVRenderPathFormatType::Utf16:
+ return GL_UTF16_NV;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return GL_UNSIGNED_BYTE;
+ }
+
+ static GLbitfield fromPathFontStyleToGL(NVRenderPathFontStyleFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLbitfield retval = 0;
+
+ if (value & NVRenderPathFontStyleValues::Bold)
+ retval |= GL_BOLD_BIT_NV;
+ if (value & NVRenderPathFontStyleValues::Italic)
+ retval |= GL_ITALIC_BIT_NV;
+
+ QT3DS_ASSERT(retval || !value);
+ return retval;
+ }
+
+ static GLenum fromPathTransformToGL(NVRenderPathTransformType::Enum value)
+ {
+ switch (value) {
+ case NVRenderPathTransformType::NoTransform:
+ return GL_NONE;
+ case NVRenderPathTransformType::TranslateX:
+ return GL_TRANSLATE_X_NV;
+ case NVRenderPathTransformType::TranslateY:
+ return GL_TRANSLATE_Y_NV;
+ case NVRenderPathTransformType::Translate2D:
+ return GL_TRANSLATE_2D_NV;
+ case NVRenderPathTransformType::Translate3D:
+ return GL_TRANSLATE_3D_NV;
+ case NVRenderPathTransformType::Affine2D:
+ return GL_AFFINE_2D_NV;
+ case NVRenderPathTransformType::Affine3D:
+ return GL_AFFINE_3D_NV;
+ case NVRenderPathTransformType::TransposeAffine2D:
+ return GL_TRANSPOSE_AFFINE_2D_NV;
+ case NVRenderPathTransformType::TransposeAffine3D:
+ return GL_TRANSPOSE_AFFINE_3D_NV;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return GL_UNSIGNED_BYTE;
+ }
+
+ static GLbitfield fromPathMetricQueryFlagsToGL(NVRenderPathGlyphFontMetricFlags flags)
+ {
+ QT3DSU32 value = flags;
+ GLbitfield retval = 0;
+
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphWidth)
+ retval |= GL_GLYPH_WIDTH_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphHeight)
+ retval |= GL_GLYPH_HEIGHT_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphHorizontalBearingX)
+ retval |= GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphHorizontalBearingY)
+ retval |= GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphHorizontalBearingAdvance)
+ retval |= GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphVerticalBearingX)
+ retval |= GL_GLYPH_VERTICAL_BEARING_X_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphVerticalBearingY)
+ retval |= GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphVerticalBearingAdvance)
+ retval |= GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::GlyphHasKerning)
+ retval |= GL_GLYPH_HAS_KERNING_BIT_NV;
+
+ if (value & NVRenderPathGlyphFontMetricValues::FontXMinBounds)
+ retval |= GL_FONT_X_MIN_BOUNDS_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontYMinBounds)
+ retval |= GL_FONT_Y_MIN_BOUNDS_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontXMaxBounds)
+ retval |= GL_FONT_X_MAX_BOUNDS_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontYMaxBounds)
+ retval |= GL_FONT_Y_MAX_BOUNDS_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontUnitsPerEm)
+ retval |= GL_FONT_UNITS_PER_EM_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontAscender)
+ retval |= GL_FONT_ASCENDER_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontDescender)
+ retval |= GL_FONT_DESCENDER_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontHeight)
+ retval |= GL_FONT_HEIGHT_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontMaxAdvanceWidth)
+ retval |= GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontMaxAdvanceHeight)
+ retval |= GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontUnderlinePosition)
+ retval |= GL_FONT_UNDERLINE_POSITION_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontMaxAdvanceWidth)
+ retval |= GL_FONT_UNDERLINE_THICKNESS_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontHasKerning)
+ retval |= GL_FONT_HAS_KERNING_BIT_NV;
+ if (value & NVRenderPathGlyphFontMetricValues::FontNumGlyphIndices)
+ retval |= GL_FONT_NUM_GLYPH_INDICES_BIT_NV;
+
+ QT3DS_ASSERT(retval || !value);
+ return retval;
+ }
+ };
+}
+}
+
+#endif // QT3DSOPENGLUTIL_H
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h
new file mode 100644
index 00000000..088a279f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL3.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_GL3_H
+#define QT3DS_RENDER_BACKEND_GL3_H
+
+/// @file Qt3DSRenderBackendGL3.h
+/// NVRender OpenGL 3 backend definition.
+
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/gl/Qt3DSRenderBackendGLBase.h"
+#include "render/backends/gl/Qt3DSOpenGLExtensions.h"
+
+#include <QtGui/QOpenGLExtraFunctions>
+#include <QtOpenGLExtensions/QtOpenGLExtensions>
+
+namespace qt3ds {
+namespace render {
+
+ ///< forward declaration
+ class NVRenderBackendMiscStateGL;
+
+ using namespace foundation;
+
+ class NVRenderBackendGL3Impl : public NVRenderBackendGLBase
+ {
+ public:
+ /// constructor
+ NVRenderBackendGL3Impl(NVFoundationBase &fnd,
+ qt3ds::foundation::IStringTable &stringTable,
+ const QSurfaceFormat &format);
+ /// destructor
+ virtual ~NVRenderBackendGL3Impl();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ public:
+ QT3DSU32 GetDepthBits() const override;
+ QT3DSU32 GetStencilBits() const override;
+ void GenerateMipMaps(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderHint::Enum genType) override;
+
+ void SetMultisampledTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ size_t samples,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height,
+ bool fixedsamplelocations) override;
+
+ void SetTextureData3D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width,
+ size_t height, size_t depth, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) override;
+
+ void UpdateSampler(
+ NVRenderBackendSamplerObject so, NVRenderTextureTargetType::Enum target,
+ NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear,
+ NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear,
+ NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge,
+ QT3DSF32 minLod = -1000.0, QT3DSF32 maxLod = 1000.0, QT3DSF32 lodBias = 0.0,
+ NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare,
+ NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual,
+ QT3DSF32 anisotropy = 1.0, QT3DSF32 *borderColor = NULL) override;
+
+ void UpdateTextureObject(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSI32 baseLevel,
+ QT3DSI32 maxLevel) override;
+
+ void UpdateTextureSwizzle(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderTextureSwizzleMode::Enum swizzleMode) override;
+
+ bool SetInputAssembler(NVRenderBackendInputAssemblerObject iao,
+ NVRenderBackendShaderProgramObject po) override;
+
+ void SetDrawBuffers(NVRenderBackendRenderTargetObject rto,
+ NVConstDataRef<QT3DSI32> inDrawBufferSet) override;
+ void SetReadBuffer(NVRenderBackendRenderTargetObject rto,
+ NVReadFaces::Enum inReadFace) override;
+
+ void RenderTargetAttach(NVRenderBackendRenderTargetObject rto,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to, QT3DSI32 level, QT3DSI32 layer) override;
+ void SetReadTarget(NVRenderBackendRenderTargetObject rto) override;
+
+ void BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter) override;
+
+ void *MapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags,
+ size_t offset, size_t length,
+ NVRenderBufferAccessFlags accessFlags) override;
+ bool UnmapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags) override;
+
+ QT3DSI32 GetConstantBufferCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length, char *nameBuf) override;
+ void GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSI32 *indices) override;
+ void GetConstantBufferParamInfoByIndices(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 count, QT3DSU32 *indices, QT3DSI32 *type,
+ QT3DSI32 *size, QT3DSI32 *offset) override;
+ void ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 blockIndex, QT3DSU32 binding) override;
+ void ProgramSetConstantBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override;
+
+ NVRenderBackendQueryObject CreateQuery() override;
+ void ReleaseQuery(NVRenderBackendQueryObject qo) override;
+ void BeginQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) override;
+ void EndQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) override;
+ void GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType, QT3DSU32 *params) override;
+ void GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType, QT3DSU64 *params) override;
+ void SetQueryTimer(NVRenderBackendQueryObject qo) override;
+
+ NVRenderBackendSyncObject CreateSync(NVRenderSyncType::Enum tpye,
+ NVRenderSyncFlags syncFlags) override;
+ void ReleaseSync(NVRenderBackendSyncObject so) override;
+ void WaitSync(NVRenderBackendSyncObject so, NVRenderCommandFlushFlags syncFlags,
+ QT3DSU64 timeout) override;
+
+ protected:
+ NVRenderBackendMiscStateGL *m_pCurrentMiscState; ///< this holds the current misc state
+#if defined(QT_OPENGL_ES)
+ Qt3DSOpenGLES2Extensions *m_qt3dsExtensions;
+#else
+ QOpenGLExtension_ARB_timer_query *m_timerExtension;
+ QOpenGLExtension_ARB_tessellation_shader *m_tessellationShader;
+ QOpenGLExtension_ARB_texture_multisample *m_multiSample;
+ Qt3DSOpenGLExtensions *m_qt3dsExtensions;
+#endif
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL4.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL4.h
new file mode 100644
index 00000000..bfdc03b7
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGL4.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_GL4_H
+#define QT3DS_RENDER_BACKEND_GL4_H
+
+/// @file Qt3DSRenderBackendGL4.h
+/// NVRender OpenGL 4 backend definition.
+
+#include "foundation/Qt3DSAtomic.h"
+#include "render/backends/gl/Qt3DSRenderBackendGL3.h"
+
+namespace qt3ds {
+namespace render {
+
+ using namespace foundation;
+
+ class NVRenderBackendGL4Impl : public NVRenderBackendGL3Impl
+ {
+ public:
+ /// constructor
+ NVRenderBackendGL4Impl(NVFoundationBase &fnd,
+ qt3ds::foundation::IStringTable &stringTable,
+ const QSurfaceFormat &format);
+ /// destructor
+ virtual ~NVRenderBackendGL4Impl();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ public:
+ void DrawIndirect(NVRenderDrawMode::Enum drawMode, const void *indirect) override;
+ void DrawIndexedIndirect(NVRenderDrawMode::Enum drawMode,
+ NVRenderComponentTypes::Enum type, const void *indirect) override;
+
+ void CreateTextureStorage2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 levels,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height) override;
+
+ void SetMultisampledTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ size_t samples,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height,
+ bool fixedsamplelocations) override;
+
+ void SetConstantValue(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count, const void *value,
+ bool transpose) override;
+
+ void SetPatchVertexCount(NVRenderBackendInputAssemblerObject iao, QT3DSU32 count) override;
+ virtual NVRenderBackendTessControlShaderObject
+ CreateTessControlShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) override;
+ virtual NVRenderBackendTessEvaluationShaderObject
+ CreateTessEvaluationShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) override;
+ virtual NVRenderBackendGeometryShaderObject
+ CreateGeometryShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) override;
+
+ QT3DSI32 GetStorageBufferCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetStorageBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length, char *nameBuf) override;
+ void ProgramSetStorageBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override;
+
+ QT3DSI32 GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetAtomicCounterBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length,
+ char *nameBuf) override;
+ void ProgramSetAtomicCounterBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override;
+
+ void SetMemoryBarrier(NVRenderBufferBarrierFlags barriers) override;
+ void BindImageTexture(NVRenderBackendTextureObject to, QT3DSU32 unit, QT3DSI32 level,
+ bool layered, QT3DSI32 layer,
+ NVRenderImageAccessType::Enum access,
+ NVRenderTextureFormats::Enum format) override;
+
+ virtual NVRenderBackendComputeShaderObject
+ CreateComputeShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) override;
+ void DispatchCompute(NVRenderBackendShaderProgramObject po, QT3DSU32 numGroupsX,
+ QT3DSU32 numGroupsY, QT3DSU32 numGroupsZ) override;
+
+ NVRenderBackendProgramPipeline CreateProgramPipeline() override;
+ void ReleaseProgramPipeline(NVRenderBackendProgramPipeline ppo) override;
+ void SetActiveProgramPipeline(NVRenderBackendProgramPipeline ppo) override;
+ void SetProgramStages(NVRenderBackendProgramPipeline ppo,
+ NVRenderShaderTypeFlags flags,
+ NVRenderBackendShaderProgramObject po) override;
+
+ void SetBlendEquation(const NVRenderBlendEquationArgument &pBlendEquArg) override;
+ void SetBlendBarrier(void) override;
+
+ NVRenderBackendPathObject CreatePathNVObject(size_t range) override;
+ void SetPathSpecification(NVRenderBackendPathObject inPathObject,
+ NVConstDataRef<QT3DSU8> inPathCommands,
+ NVConstDataRef<QT3DSF32> inPathCoords) override;
+ NVBounds3 GetPathObjectBoundingBox(NVRenderBackendPathObject inPathObject) override;
+ NVBounds3 GetPathObjectFillBox(NVRenderBackendPathObject inPathObject) override;
+ NVBounds3 GetPathObjectStrokeBox(NVRenderBackendPathObject inPathObject) override;
+ void SetStrokeWidth(NVRenderBackendPathObject inPathObject, QT3DSF32 inStrokeWidth) override;
+
+ void SetPathProjectionMatrix(const QT3DSMat44 inPathProjection) override;
+ void SetPathModelViewMatrix(const QT3DSMat44 inPathModelview) override;
+ void SetPathStencilDepthOffset(QT3DSF32 inSlope, QT3DSF32 inBias) override;
+ void SetPathCoverDepthFunc(NVRenderBoolOp::Enum inDepthFunction) override;
+ void StencilStrokePath(NVRenderBackendPathObject inPathObject) override;
+ void StencilFillPath(NVRenderBackendPathObject inPathObject) override;
+ void ReleasePathNVObject(NVRenderBackendPathObject po, size_t range) override;
+
+ void StencilFillPathInstanced(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathFormatType::Enum type,
+ const void *charCodes, NVRenderPathFillMode::Enum fillMode, QT3DSU32 stencilMask,
+ NVRenderPathTransformType::Enum transformType, const QT3DSF32 *transformValues) override;
+ void StencilStrokePathInstancedN(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes, QT3DSI32 stencilRef,
+ QT3DSU32 stencilMask,
+ NVRenderPathTransformType::Enum transformType,
+ const QT3DSF32 *transformValues) override;
+ void CoverFillPathInstanced(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes,
+ NVRenderPathCoverMode::Enum coverMode,
+ NVRenderPathTransformType::Enum transformType,
+ const QT3DSF32 *transformValues) override;
+ void CoverStrokePathInstanced(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes,
+ NVRenderPathCoverMode::Enum coverMode,
+ NVRenderPathTransformType::Enum transformType,
+ const QT3DSF32 *transformValues) override;
+ void LoadPathGlyphs(NVRenderBackendPathObject po,
+ NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle, size_t numGlyphs,
+ NVRenderPathFormatType::Enum type, const void *charCodes,
+ NVRenderPathMissingGlyphs::Enum handleMissingGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale) override;
+ virtual NVRenderPathReturnValues::Enum
+ LoadPathGlyphsIndexed(NVRenderBackendPathObject po, NVRenderPathFontTarget::Enum fontTarget,
+ const void *fontName, NVRenderPathFontStyleFlags fontStyle,
+ QT3DSU32 firstGlyphIndex, size_t numGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale) override;
+ virtual NVRenderBackendPathObject
+ LoadPathGlyphsIndexedRange(NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale,
+ QT3DSU32 *count) override;
+ void LoadPathGlyphRange(NVRenderBackendPathObject po,
+ NVRenderPathFontTarget::Enum fontTarget,
+ const void *fontName, NVRenderPathFontStyleFlags fontStyle,
+ QT3DSU32 firstGlyph, size_t numGlyphs,
+ NVRenderPathMissingGlyphs::Enum handleMissingGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate,
+ QT3DSF32 emScale) override;
+ void GetPathMetrics(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathGlyphFontMetricFlags metricQueryMask,
+ NVRenderPathFormatType::Enum type, const void *charCodes,
+ size_t stride, QT3DSF32 *metrics) override;
+ void GetPathMetricsRange(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathGlyphFontMetricFlags metricQueryMask,
+ size_t stride, QT3DSF32 *metrics) override;
+ void GetPathSpacing(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathListMode::Enum pathListMode,
+ NVRenderPathFormatType::Enum type, const void *charCodes,
+ QT3DSF32 advanceScale, QT3DSF32 kerningScale,
+ NVRenderPathTransformType::Enum transformType, QT3DSF32 *spacing) override;
+ private:
+#if !defined(QT_OPENGL_ES)
+ QOpenGLExtension_NV_path_rendering *m_nvPathRendering;
+ QOpenGLExtension_EXT_direct_state_access *m_directStateAccess;
+#endif
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h
new file mode 100644
index 00000000..6cde45ef
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendGLBase.h
@@ -0,0 +1,522 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_GL_BASE_H
+#define QT3DS_RENDER_BACKEND_GL_BASE_H
+
+/// @file Qt3DSRenderBackendGLBase.h
+/// NVRender OpenGL Core backend definition.
+
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/StringTable.h"
+#include "render/backends/Qt3DSRenderBackend.h"
+#include "render/backends/gl/Qt3DSOpenGLUtil.h"
+#include <EASTL/string.h>
+
+#include <QtGui/QSurfaceFormat>
+#include <QtGui/QOpenGLFunctions>
+#include <QtOpenGLExtensions/QtOpenGLExtensions>
+
+#define NVRENDER_BACKEND_UNUSED(arg) (void)arg;
+
+namespace qt3ds {
+namespace render {
+
+ ///< forward declaration
+ class NVRenderBackendRasterizerStateGL;
+ class NVRenderBackendDepthStencilStateGL;
+
+ using namespace foundation;
+
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TContextStr;
+
+ class NVRenderBackendGLBase : public NVRenderBackend
+ {
+ public:
+ /// constructor
+ NVRenderBackendGLBase(NVFoundationBase &fnd,
+ qt3ds::foundation::IStringTable &stringTable,
+ const QSurfaceFormat &format);
+ /// destructor
+ virtual ~NVRenderBackendGLBase();
+
+ public:
+ /// API Interface
+ NVRenderContextType GetRenderContextType() const override;
+ bool isESCompatible() const;
+
+ const char *GetShadingLanguageVersion() override;
+ /// get implementation depended values
+ QT3DSU32 GetMaxCombinedTextureUnits() override;
+ bool GetRenderBackendCap(NVRenderBackendCaps::Enum inCap) const override;
+ QT3DSU32 GetDepthBits() const override;
+ QT3DSU32 GetStencilBits() const override;
+ void GetRenderBackendValue(NVRenderBackendQuery::Enum inQuery, QT3DSI32 *params) const override;
+
+ /// state get/set functions
+ void SetRenderState(bool bEnable, const NVRenderState::Enum value) override;
+ bool GetRenderState(const NVRenderState::Enum value) override;
+ virtual NVRenderBackendDepthStencilStateObject
+ CreateDepthStencilState(bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc,
+ bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack) override;
+ virtual void
+ ReleaseDepthStencilState(NVRenderBackendDepthStencilStateObject inDepthStencilState) override;
+ virtual NVRenderBackendRasterizerStateObject
+ CreateRasterizerState(QT3DSF32 depthBias, QT3DSF32 depthScale, NVRenderFaces::Enum cullFace) override;
+ void ReleaseRasterizerState(NVRenderBackendRasterizerStateObject rasterizerState) override;
+ virtual void
+ SetDepthStencilState(NVRenderBackendDepthStencilStateObject inDepthStencilState) override;
+ void SetRasterizerState(NVRenderBackendRasterizerStateObject rasterizerState) override;
+ NVRenderBoolOp::Enum GetDepthFunc() override;
+ void SetDepthFunc(const NVRenderBoolOp::Enum func) override;
+ bool GetDepthWrite() override;
+ void SetDepthWrite(bool bEnable) override;
+ void SetColorWrites(bool bRed, bool bGreen, bool bBlue, bool bAlpha) override;
+ void SetMultisample(bool bEnable) override;
+ void GetBlendFunc(NVRenderBlendFunctionArgument *pBlendFuncArg) override;
+ void SetBlendFunc(const NVRenderBlendFunctionArgument &blendFuncArg) override;
+ void SetBlendEquation(const NVRenderBlendEquationArgument &pBlendEquArg) override;
+ void SetBlendBarrier(void) override;
+ void GetScissorRect(NVRenderRect *pRect) override;
+ void SetScissorRect(const NVRenderRect &rect) override;
+ void GetViewportRect(NVRenderRect *pRect) override;
+ void SetViewportRect(const NVRenderRect &rect) override;
+
+ void SetClearColor(const QT3DSVec4 *pClearColor) override;
+ void Clear(NVRenderClearFlags flags) override;
+
+ /// resource handling
+ NVRenderBackendBufferObject CreateBuffer(size_t size,
+ NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usage,
+ const void *hostPtr = NULL) override;
+ void BindBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags) override;
+ void ReleaseBuffer(NVRenderBackendBufferObject bo) override;
+ void UpdateBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags,
+ size_t size, NVRenderBufferUsageType::Enum usage,
+ const void *data) override;
+ void UpdateBufferRange(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags, size_t offset,
+ size_t size, const void *data) override;
+ void *MapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags,
+ size_t offset, size_t length,
+ NVRenderBufferAccessFlags accessFlags) override;
+ bool UnmapBuffer(NVRenderBackendBufferObject bo, NVRenderBufferBindFlags bindFlags) override;
+ void SetMemoryBarrier(NVRenderBufferBarrierFlags barriers) override;
+
+ NVRenderBackendQueryObject CreateQuery() override;
+ void ReleaseQuery(NVRenderBackendQueryObject qo) override;
+ void BeginQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) override;
+ void EndQuery(NVRenderBackendQueryObject qo, NVRenderQueryType::Enum type) override;
+ void GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType, QT3DSU32 *params) override;
+ void GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType, QT3DSU64 *params) override;
+ void SetQueryTimer(NVRenderBackendQueryObject qo) override;
+
+ NVRenderBackendSyncObject CreateSync(NVRenderSyncType::Enum tpye,
+ NVRenderSyncFlags syncFlags) override;
+ void ReleaseSync(NVRenderBackendSyncObject so) override;
+ void WaitSync(NVRenderBackendSyncObject so, NVRenderCommandFlushFlags syncFlags,
+ QT3DSU64 timeout) override;
+
+ NVRenderBackendRenderTargetObject CreateRenderTarget() override;
+ void ReleaseRenderTarget(NVRenderBackendRenderTargetObject rto) override;
+ void RenderTargetAttach(NVRenderBackendRenderTargetObject rto,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendRenderbufferObject rbo) override;
+ void RenderTargetAttach(
+ NVRenderBackendRenderTargetObject rto, NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target = NVRenderTextureTargetType::Texture2D) override;
+ void RenderTargetAttach(NVRenderBackendRenderTargetObject rto,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to, QT3DSI32 level, QT3DSI32 layer) override;
+ void SetRenderTarget(NVRenderBackendRenderTargetObject rto) override;
+ bool RenderTargetIsValid(NVRenderBackendRenderTargetObject rto) override;
+
+ virtual NVRenderBackendRenderbufferObject
+ CreateRenderbuffer(NVRenderRenderBufferFormats::Enum storageFormat, size_t width,
+ size_t height) override;
+ void ReleaseRenderbuffer(NVRenderBackendRenderbufferObject rbo) override;
+ bool ResizeRenderbuffer(NVRenderBackendRenderbufferObject rbo,
+ NVRenderRenderBufferFormats::Enum storageFormat,
+ size_t width, size_t height) override;
+
+ NVRenderBackendTextureObject CreateTexture() override;
+ void BindTexture(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 unit) override;
+ void BindImageTexture(NVRenderBackendTextureObject to, QT3DSU32 unit, QT3DSI32 level,
+ bool layered, QT3DSI32 layer,
+ NVRenderImageAccessType::Enum access,
+ NVRenderTextureFormats::Enum format) override;
+ void ReleaseTexture(NVRenderBackendTextureObject to) override;
+ void SetTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width,
+ size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) override;
+ void SetTextureDataCubeFace(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) override;
+ void CreateTextureStorage2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 levels,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height) override;
+ void SetTextureSubData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ QT3DSI32 xOffset, QT3DSI32 yOffset, size_t width, size_t height,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) override;
+ void SetCompressedTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height, QT3DSI32 border,
+ size_t imageSize, const void *hostPtr = NULL) override;
+ void SetCompressedTextureDataCubeFace(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height, QT3DSI32 border,
+ size_t imageSize, const void *hostPtr = NULL) override;
+ void SetCompressedTextureSubData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ QT3DSU32 level, QT3DSI32 xOffset, QT3DSI32 yOffset,
+ size_t width, size_t height,
+ NVRenderTextureFormats::Enum format,
+ size_t imageSize, const void *hostPtr = NULL) override;
+ void SetMultisampledTextureData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ size_t samples,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height,
+ bool fixedsamplelocations) override = 0;
+
+ void SetTextureData3D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width,
+ size_t height, size_t depth, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr = NULL) override;
+
+ void GenerateMipMaps(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderHint::Enum genType) override;
+
+ virtual NVRenderTextureSwizzleMode::Enum
+ GetTextureSwizzleMode(const NVRenderTextureFormats::Enum inFormat) const override;
+
+ NVRenderBackendSamplerObject CreateSampler(
+ NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear,
+ NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear,
+ NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge,
+ QT3DSI32 minLod = -1000, QT3DSI32 maxLod = 1000, QT3DSF32 lodBias = 0.0,
+ NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare,
+ NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual,
+ QT3DSF32 anisotropy = 1.0, QT3DSF32 *borderColor = NULL) override;
+
+ void UpdateSampler(
+ NVRenderBackendSamplerObject so, NVRenderTextureTargetType::Enum target,
+ NVRenderTextureMinifyingOp::Enum minFilter = NVRenderTextureMinifyingOp::Linear,
+ NVRenderTextureMagnifyingOp::Enum magFilter = NVRenderTextureMagnifyingOp::Linear,
+ NVRenderTextureCoordOp::Enum wrapS = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapT = NVRenderTextureCoordOp::ClampToEdge,
+ NVRenderTextureCoordOp::Enum wrapR = NVRenderTextureCoordOp::ClampToEdge,
+ QT3DSF32 minLod = -1000.0, QT3DSF32 maxLod = 1000.0, QT3DSF32 lodBias = 0.0,
+ NVRenderTextureCompareMode::Enum compareMode = NVRenderTextureCompareMode::NoCompare,
+ NVRenderTextureCompareOp::Enum compareFunc = NVRenderTextureCompareOp::LessThanOrEqual,
+ QT3DSF32 anisotropy = 1.0, QT3DSF32 *borderColor = NULL) override;
+
+ void UpdateTextureObject(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSI32 baseLevel,
+ QT3DSI32 maxLevel) override;
+
+ void UpdateTextureSwizzle(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderTextureSwizzleMode::Enum swizzleMode) override;
+
+ void ReleaseSampler(NVRenderBackendSamplerObject so) override;
+
+ virtual NVRenderBackendAttribLayoutObject
+ CreateAttribLayout(NVConstDataRef<NVRenderVertexBufferEntry> attribs) override;
+ void ReleaseAttribLayout(NVRenderBackendAttribLayoutObject ao) override;
+
+ virtual NVRenderBackendInputAssemblerObject
+ CreateInputAssembler(NVRenderBackendAttribLayoutObject attribLayout,
+ NVConstDataRef<NVRenderBackendBufferObject> buffers,
+ const NVRenderBackendBufferObject indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets,
+ QT3DSU32 patchVertexCount) override;
+ void ReleaseInputAssembler(NVRenderBackendInputAssemblerObject iao) override;
+
+ bool SetInputAssembler(NVRenderBackendInputAssemblerObject iao,
+ NVRenderBackendShaderProgramObject po) override = 0;
+ void SetPatchVertexCount(NVRenderBackendInputAssemblerObject, QT3DSU32) override
+ {
+ QT3DS_ASSERT(false);
+ }
+
+ // shader
+ virtual NVRenderBackendVertexShaderObject
+ CreateVertexShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) override;
+ virtual NVRenderBackendFragmentShaderObject
+ CreateFragmentShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) override;
+ virtual NVRenderBackendTessControlShaderObject
+ CreateTessControlShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) override;
+ virtual NVRenderBackendTessEvaluationShaderObject
+ CreateTessEvaluationShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage,
+ bool binary) override;
+ virtual NVRenderBackendGeometryShaderObject
+ CreateGeometryShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) override;
+ virtual NVRenderBackendComputeShaderObject
+ CreateComputeShader(NVConstDataRef<QT3DSI8> source, eastl::string &errorMessage, bool binary) override;
+ void ReleaseVertexShader(NVRenderBackendVertexShaderObject vso) override;
+ void ReleaseFragmentShader(NVRenderBackendFragmentShaderObject fso) override;
+ void ReleaseTessControlShader(NVRenderBackendTessControlShaderObject tcso) override;
+ void ReleaseTessEvaluationShader(NVRenderBackendTessEvaluationShaderObject teso) override;
+ void ReleaseGeometryShader(NVRenderBackendGeometryShaderObject gso) override;
+ void ReleaseComputeShader(NVRenderBackendComputeShaderObject cso) override;
+ void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendVertexShaderObject vso) override;
+ void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendFragmentShaderObject fso) override;
+ void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessControlShaderObject tcso) override;
+ void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessEvaluationShaderObject teso) override;
+ void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendGeometryShaderObject gso) override;
+ void AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendComputeShaderObject cso) override;
+ void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendVertexShaderObject vso) override;
+ void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendFragmentShaderObject fso) override;
+ void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessControlShaderObject tcso) override;
+ void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessEvaluationShaderObject teso) override;
+ void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendGeometryShaderObject gso) override;
+ void DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendComputeShaderObject cso) override;
+ NVRenderBackendShaderProgramObject CreateShaderProgram(bool isSeparable) override;
+ void ReleaseShaderProgram(NVRenderBackendShaderProgramObject po) override;
+ bool LinkProgram(NVRenderBackendShaderProgramObject po,
+ eastl::string &errorMessage) override;
+ void SetActiveProgram(NVRenderBackendShaderProgramObject po) override;
+ void DispatchCompute(NVRenderBackendShaderProgramObject po, QT3DSU32 numGroupsX,
+ QT3DSU32 numGroupsY, QT3DSU32 numGroupsZ) override;
+ NVRenderBackendProgramPipeline CreateProgramPipeline() override;
+ void ReleaseProgramPipeline(NVRenderBackendProgramPipeline po) override;
+ void SetActiveProgramPipeline(NVRenderBackendProgramPipeline po) override;
+ void SetProgramStages(NVRenderBackendProgramPipeline ppo,
+ NVRenderShaderTypeFlags flags,
+ NVRenderBackendShaderProgramObject po) override;
+
+ // uniforms
+ QT3DSI32 GetConstantCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetConstantInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 bufSize, QT3DSI32 *numElem,
+ NVRenderShaderDataTypes::Enum *type, QT3DSI32 *binding,
+ char *nameBuf) override;
+ void SetConstantValue(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count,
+ const void *value, bool transpose) override;
+
+ // uniform buffers
+ QT3DSI32 GetConstantBufferCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length, char *nameBuf) override;
+ void GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSI32 *indices) override;
+ void GetConstantBufferParamInfoByIndices(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 count, QT3DSU32 *indices, QT3DSI32 *type,
+ QT3DSI32 *size, QT3DSI32 *offset) override;
+ void ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 blockIndex, QT3DSU32 binding) override;
+ void ProgramSetConstantBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override;
+
+ // storage buffers
+ QT3DSI32 GetStorageBufferCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetStorageBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length, char *nameBuf) override;
+ void ProgramSetStorageBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override;
+
+ // atomic counter buffers
+ QT3DSI32 GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject po) override;
+ QT3DSI32 GetAtomicCounterBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length,
+ char *nameBuf) override;
+ void ProgramSetAtomicCounterBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo) override;
+
+ /// draw calls
+ void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 start, QT3DSU32 count) override;
+ void DrawIndirect(NVRenderDrawMode::Enum drawMode, const void *indirect) override;
+ void DrawIndexed(NVRenderDrawMode::Enum drawMode, QT3DSU32 count,
+ NVRenderComponentTypes::Enum type, const void *indices) override;
+ void DrawIndexedIndirect(NVRenderDrawMode::Enum drawMode,
+ NVRenderComponentTypes::Enum type, const void *indirect) override;
+
+ // read calls
+ void ReadPixel(NVRenderBackendRenderTargetObject rto, QT3DSI32 x, QT3DSI32 y, QT3DSI32 width,
+ QT3DSI32 height, NVRenderReadPixelFormats::Enum inFormat, void *pixels) override;
+
+ // NV path rendering
+ NVRenderBackendPathObject CreatePathNVObject(size_t range) override;
+ // Pathing requires gl4 backend.
+ void SetPathSpecification(NVRenderBackendPathObject, NVConstDataRef<QT3DSU8>,
+ NVConstDataRef<QT3DSF32>) override
+ {
+ }
+
+ ///< Bounds of the fill and stroke
+ NVBounds3 GetPathObjectBoundingBox(NVRenderBackendPathObject /*inPathObject*/) override
+ {
+ return NVBounds3();
+ }
+ NVBounds3 GetPathObjectFillBox(NVRenderBackendPathObject /*inPathObject*/) override
+ {
+ return NVBounds3();
+ }
+ NVBounds3 GetPathObjectStrokeBox(NVRenderBackendPathObject /*inPathObject*/) override
+ {
+ return NVBounds3();
+ }
+
+ /**
+ * Defaults to 0 if unset.
+ */
+ void SetStrokeWidth(NVRenderBackendPathObject /*inPathObject*/, QT3DSF32) override {}
+ void SetPathProjectionMatrix(const QT3DSMat44 /*inPathProjection*/) override {}
+ void SetPathModelViewMatrix(const QT3DSMat44 /*inPathModelview*/) override {}
+ void SetPathStencilDepthOffset(QT3DSF32 /*inSlope*/, QT3DSF32 /*inBias*/) override {}
+ void SetPathCoverDepthFunc(NVRenderBoolOp::Enum /*inDepthFunction*/) override {}
+ void StencilStrokePath(NVRenderBackendPathObject /*inPathObject*/) override {}
+ void StencilFillPath(NVRenderBackendPathObject /*inPathObject*/) override {}
+ void ReleasePathNVObject(NVRenderBackendPathObject po, size_t range) override;
+
+ void LoadPathGlyphs(NVRenderBackendPathObject, NVRenderPathFontTarget::Enum,
+ const void *, NVRenderPathFontStyleFlags, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathMissingGlyphs::Enum, NVRenderBackendPathObject,
+ QT3DSF32) override;
+ virtual NVRenderPathReturnValues::Enum
+ LoadPathGlyphsIndexed(NVRenderBackendPathObject po, NVRenderPathFontTarget::Enum fontTarget,
+ const void *fontName, NVRenderPathFontStyleFlags fontStyle,
+ QT3DSU32 firstGlyphIndex, size_t numGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale) override;
+ virtual NVRenderBackendPathObject
+ LoadPathGlyphsIndexedRange(NVRenderPathFontTarget::Enum, const void *,
+ NVRenderPathFontStyleFlags,
+ NVRenderBackend::NVRenderBackendPathObject, QT3DSF32, QT3DSU32 *) override;
+ void LoadPathGlyphRange(NVRenderBackendPathObject, NVRenderPathFontTarget::Enum,
+ const void *, NVRenderPathFontStyleFlags, QT3DSU32, size_t,
+ NVRenderPathMissingGlyphs::Enum, NVRenderBackendPathObject,
+ QT3DSF32) override;
+ void GetPathMetrics(NVRenderBackendPathObject, size_t,
+ NVRenderPathGlyphFontMetricFlags, NVRenderPathFormatType::Enum,
+ const void *, size_t, QT3DSF32 *) override;
+ void GetPathMetricsRange(NVRenderBackendPathObject, size_t,
+ NVRenderPathGlyphFontMetricFlags, size_t, QT3DSF32 *) override;
+ void GetPathSpacing(NVRenderBackendPathObject, size_t, NVRenderPathListMode::Enum,
+ NVRenderPathFormatType::Enum, const void *, QT3DSF32, QT3DSF32,
+ NVRenderPathTransformType::Enum, QT3DSF32 *) override;
+
+ void StencilFillPathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathFillMode::Enum, QT3DSU32,
+ NVRenderPathTransformType::Enum, const QT3DSF32 *) override;
+ void StencilStrokePathInstancedN(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *, QT3DSI32,
+ QT3DSU32, NVRenderPathTransformType::Enum,
+ const QT3DSF32 *) override;
+ void CoverFillPathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathCoverMode::Enum,
+ NVRenderPathTransformType::Enum, const QT3DSF32 *) override;
+ void CoverStrokePathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathCoverMode::Enum,
+ NVRenderPathTransformType::Enum, const QT3DSF32 *) override;
+
+ QSurfaceFormat format() const override
+ {
+ return m_format;
+ }
+
+ protected:
+ virtual NVFoundationBase &GetFoundation() { return m_Foundation; }
+ virtual bool compileSource(GLuint shaderID, NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary);
+ virtual const char *getVersionString();
+ virtual const char *getVendorString();
+ virtual const char *geRendererString();
+
+ virtual void setAndInspectHardwareCaps();
+
+ protected:
+ volatile QT3DSI32 mRefCount; ///< reference count
+ NVFoundationBase &m_Foundation; ///< Foundation class for allocations and other base things
+ NVScopedRefCounted<qt3ds::foundation::IStringTable>
+ m_StringTable; ///< pointer to a string table
+ GLConversion m_Conversion; ///< Class for conversion from base type to GL types
+ nvvector<TContextStr> m_Extensions; ///< contains the OpenGL extension string
+ QT3DSI32 m_MaxAttribCount; ///< Maximum attributes which can be used
+ nvvector<GLenum> m_DrawBuffersArray; ///< Contains the drawbuffer enums
+ QSurfaceFormat m_format;
+
+ NVRenderBackendRasterizerStateGL
+ *m_pCurrentRasterizerState; ///< this holds the current rasterizer state
+ NVRenderBackendDepthStencilStateGL
+ *m_pCurrentDepthStencilState; ///< this holds the current depth stencil state
+
+ void checkGLError() const;
+ QOpenGLFunctions *m_glFunctions;
+ QOpenGLExtraFunctions *m_glExtraFunctions;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h
new file mode 100644
index 00000000..a2d927e0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_INPUT_ASSEMBLER_GL_H
+#define QT3DS_RENDER_BACKEND_INPUT_ASSEMBLER_GL_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StringTable.h"
+#include "foundation/Utils.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace qt3ds {
+namespace render {
+
+ struct NVRenderBackendLayoutEntryGL
+ {
+ CRegisteredString m_AttribName; ///< must be the same name as used in the vertex shader
+ QT3DSU8 m_Normalize; ///< normalize parameter
+ QT3DSU32 m_AttribIndex; ///< attribute index
+ QT3DSU32 m_Type; ///< GL vertex format type @sa GL_FLOAT, GL_INT
+ QT3DSU32 m_NumComponents; ///< component count. max 4
+ QT3DSU32 m_InputSlot; ///< Input slot where to fetch the data from
+ QT3DSU32 m_Offset; ///< offset in byte
+ };
+
+ ///< this class handles the vertex attribute layout setup
+ class NVRenderBackendAttributeLayoutGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendAttributeLayoutGL(NVDataRef<NVRenderBackendLayoutEntryGL> entries,
+ QT3DSU32 maxInputSlot)
+ : m_LayoutAttribEntries(entries)
+ , m_MaxInputSlot(maxInputSlot)
+ {
+ }
+ ///< destructor
+ ~NVRenderBackendAttributeLayoutGL(){}
+
+ NVRenderBackendLayoutEntryGL *getEntryByName(CRegisteredString entryName) const
+ {
+ UICBASE_FOREACH(idx, m_LayoutAttribEntries.size())
+ {
+ if (m_LayoutAttribEntries[idx].m_AttribName == entryName)
+ return &m_LayoutAttribEntries.mData[idx];
+ }
+ return NULL;
+ }
+
+ Option<NVRenderBackendLayoutEntryGL> getEntryByAttribIndex(QT3DSU32 attribIndex) const
+ {
+ UICBASE_FOREACH(idx, m_LayoutAttribEntries.size())
+ {
+ if (m_LayoutAttribEntries[idx].m_AttribIndex == attribIndex)
+ return m_LayoutAttribEntries[idx];
+ }
+ return Empty();
+ }
+
+ NVDataRef<NVRenderBackendLayoutEntryGL>
+ m_LayoutAttribEntries; ///< vertex attribute layout entries
+ QT3DSU32 m_MaxInputSlot; ///< max used input slot
+ };
+
+ ///< this class handles the input assembler setup
+ class NVRenderBackendInputAssemblerGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendInputAssemblerGL(
+ NVFoundationBase &fnd, NVRenderBackendAttributeLayoutGL *attribLayout,
+ NVConstDataRef<NVRenderBackend::NVRenderBackendBufferObject> buffers,
+ const NVRenderBackend::NVRenderBackendBufferObject indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets, QT3DSU32 patchVertexCount)
+ : m_Foundation(fnd)
+ , m_attribLayout(attribLayout)
+ , m_VertexbufferHandles(buffers)
+ , m_IndexbufferHandle(indexBuffer)
+ , m_VaoID(0)
+ , m_cachedShaderHandle(0)
+ , m_PatchVertexCount(patchVertexCount)
+ {
+ QT3DSU32 *strideMem = (QT3DSU32 *)QT3DS_ALLOC(fnd.getAllocator(), strides.mSize * sizeof(QT3DSU32),
+ "BackendAttributeLayoutGL:m_strides");
+ QT3DSU32 *offsetMem = (QT3DSU32 *)QT3DS_ALLOC(fnd.getAllocator(), strides.mSize * sizeof(QT3DSU32),
+ "BackendAttributeLayoutGL:m_strides");
+ // copy offsets and strides
+ UICBASE_FOREACH(idx, strides.size())
+ {
+ strideMem[idx] = strides.mData[idx];
+ offsetMem[idx] = offsets.mData[idx];
+ }
+
+ m_strides = toDataRef(strideMem, strides.size());
+ m_offsets = toDataRef(offsetMem, offsets.size());
+ }
+ ///< destructor
+ ~NVRenderBackendInputAssemblerGL()
+ {
+ QT3DS_FREE(m_Foundation.getAllocator(), m_strides.mData);
+ QT3DS_FREE(m_Foundation.getAllocator(), m_offsets.mData);
+ };
+
+ NVFoundationBase &m_Foundation; ///< pointer to foundation
+ NVRenderBackendAttributeLayoutGL *m_attribLayout; ///< pointer to attribute layout
+ NVConstDataRef<NVRenderBackend::NVRenderBackendBufferObject>
+ m_VertexbufferHandles; ///< opaque vertex buffer backend handles
+ NVRenderBackend::NVRenderBackendBufferObject
+ m_IndexbufferHandle; ///< opaque index buffer backend handles
+ QT3DSU32 m_VaoID; ///< this is only used if GL version is greater or equal 3
+ QT3DSU32 m_cachedShaderHandle; ///< this is the shader id which was last used with this object
+ QT3DSU32 m_PatchVertexCount; ///< vertex count for a single patch primitive
+ NVDataRef<QT3DSU32> m_strides; ///< buffer strides
+ NVDataRef<QT3DSU32> m_offsets; ///< buffer offsets
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h
new file mode 100644
index 00000000..3a74a8e3
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_RENDER_STATE_OBJECTS_GL_H
+#define QT3DS_RENDER_BACKEND_RENDER_STATE_OBJECTS_GL_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Utils.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace qt3ds {
+namespace render {
+
+ ///< this class handles the shader input variables
+ class NVRenderBackendDepthStencilStateGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendDepthStencilStateGL(bool enableDepth, bool depthMask,
+ NVRenderBoolOp::Enum depthFunc, bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack)
+ : m_DepthEnable(enableDepth)
+ , m_DepthMask(depthMask)
+ , m_DepthFunc(depthFunc)
+ , m_StencilEnable(enableStencil)
+ , m_StencilFuncFront(stencilFuncFront)
+ , m_StencilFuncBack(stencilFuncBack)
+ , m_DepthStencilOpFront(depthStencilOpFront)
+ , m_DepthStencilOpBack(depthStencilOpBack)
+ {
+ }
+
+ ///< constructor
+ NVRenderBackendDepthStencilStateGL()
+ : m_DepthEnable(true)
+ , m_DepthMask(true)
+ , m_DepthFunc(NVRenderBoolOp::LessThanOrEqual)
+ , m_StencilEnable(false)
+ {
+ }
+
+ ///< destructor
+ ~NVRenderBackendDepthStencilStateGL(){}
+
+ ///< assignement
+ NVRenderBackendDepthStencilStateGL &operator=(const NVRenderBackendDepthStencilStateGL &rhs)
+ {
+ // Check for self-assignment!
+ if (this == &rhs)
+ return *this;
+
+ m_DepthEnable = rhs.m_DepthEnable;
+ m_DepthMask = rhs.m_DepthMask;
+ m_DepthFunc = rhs.m_DepthFunc;
+ m_StencilEnable = rhs.m_StencilEnable;
+ m_StencilFuncFront = rhs.m_StencilFuncFront;
+ m_StencilFuncBack = rhs.m_StencilFuncBack;
+ m_DepthStencilOpFront = rhs.m_DepthStencilOpFront;
+ m_DepthStencilOpBack = rhs.m_DepthStencilOpBack;
+
+ return *this;
+ }
+
+ bool operator==(const NVRenderBackendDepthStencilStateGL &other) const
+ {
+ return (m_DepthEnable == other.m_DepthEnable && m_DepthMask == other.m_DepthMask
+ && m_DepthFunc == other.m_DepthFunc && m_StencilEnable == other.m_StencilEnable
+ && m_StencilFuncFront == other.m_StencilFuncFront
+ && m_StencilFuncBack == other.m_StencilFuncBack
+ && m_DepthStencilOpFront == other.m_DepthStencilOpFront
+ && m_DepthStencilOpBack == other.m_DepthStencilOpBack);
+ }
+
+ bool m_DepthEnable; ///< depth test enabled
+ bool m_DepthMask; ///< enable / disable depth writes
+ NVRenderBoolOp::Enum m_DepthFunc; ///< depth comparison func
+ bool m_StencilEnable; ///< enable disable stencil test
+ NVRenderStencilFunctionArgument m_StencilFuncFront; ///< stencil setup for front faces
+ NVRenderStencilFunctionArgument m_StencilFuncBack; ///< stencil setup for back faces
+ NVRenderStencilOperationArgument
+ m_DepthStencilOpFront; ///< depth stencil operation for front faces
+ NVRenderStencilOperationArgument
+ m_DepthStencilOpBack; ///< depth stencil operation for back faces
+ };
+
+ class NVRenderBackendMiscStateGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendMiscStateGL()
+ : m_PatchVertexCount(1)
+ {
+ }
+
+ QT3DSU32 m_PatchVertexCount; ///< vertex count for a single patch primitive
+ };
+
+ class NVRenderBackendRasterizerStateGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendRasterizerStateGL(QT3DSF32 depthBias, QT3DSF32 depthScale,
+ NVRenderFaces::Enum cullFace)
+ : m_DepthBias(depthBias)
+ , m_DepthScale(depthScale)
+ , m_CullFace(cullFace)
+ {
+ }
+ ///< constructor
+ NVRenderBackendRasterizerStateGL()
+ : m_DepthBias(0.0)
+ , m_DepthScale(0.0)
+ , m_CullFace(NVRenderFaces::Back)
+ {
+ }
+
+ NVRenderBackendRasterizerStateGL &operator=(const NVRenderBackendRasterizerStateGL &rhs)
+ {
+ // Check for self-assignment!
+ if (this == &rhs)
+ return *this;
+
+ m_DepthBias = rhs.m_DepthBias;
+ m_DepthScale = rhs.m_DepthScale;
+ m_CullFace = rhs.m_CullFace;
+
+ return *this;
+ }
+
+ bool operator==(const NVRenderBackendRasterizerStateGL &other) const
+ {
+ return (m_DepthBias == other.m_DepthBias && m_DepthScale == other.m_DepthScale
+ && m_CullFace == other.m_CullFace);
+ }
+
+ QT3DSF32 m_DepthBias; ///< depth bias
+ QT3DSF32 m_DepthScale; ///< mulitply constant
+ NVRenderFaces::Enum m_CullFace; ///< cull face front or back
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h
new file mode 100644
index 00000000..03fd6b32
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_SHADER_PROGRAM_GL_H
+#define QT3DS_RENDER_BACKEND_SHADER_PROGRAM_GL_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Utils.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace qt3ds {
+namespace render {
+
+ struct NVRenderBackendShaderInputEntryGL
+ {
+ CRegisteredString m_AttribName; ///< must be the same name as used in the vertex shader
+ QT3DSU32 m_AttribLocation; ///< attribute index
+ QT3DSU32 m_Type; ///< GL vertex format type @sa GL_FLOAT, GL_INT
+ QT3DSU32 m_NumComponents; ///< component count. max 4
+ };
+
+ ///< this class handles the shader input variables
+ class NVRenderBackendShaderInputGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendShaderInputGL(NVDataRef<NVRenderBackendShaderInputEntryGL> entries)
+ : m_ShaderInputEntries(entries)
+ {
+ }
+ ///< destructor
+ ~NVRenderBackendShaderInputGL(){}
+
+ NVRenderBackendShaderInputEntryGL *getEntryByName(CRegisteredString entryName) const
+ {
+ UICBASE_FOREACH(idx, m_ShaderInputEntries.size())
+ {
+ if (m_ShaderInputEntries[idx].m_AttribName == entryName)
+ return &m_ShaderInputEntries.mData[idx];
+ }
+ return NULL;
+ }
+
+ Option<NVRenderBackendShaderInputEntryGL>
+ getEntryByAttribLocation(QT3DSU32 attribLocation) const
+ {
+ UICBASE_FOREACH(idx, m_ShaderInputEntries.size())
+ {
+ if (m_ShaderInputEntries[idx].m_AttribLocation == attribLocation)
+ return m_ShaderInputEntries[idx];
+ }
+ return Empty();
+ }
+
+ NVDataRef<NVRenderBackendShaderInputEntryGL> m_ShaderInputEntries; ///< shader input entries
+ };
+
+ ///< this class represents the internals of a GL program
+ class NVRenderBackendShaderProgramGL
+ {
+ public:
+ ///< constructor
+ NVRenderBackendShaderProgramGL(QT3DSU32 programID)
+ : m_ProgramID(programID)
+ , m_shaderInput(NULL)
+ {
+ }
+
+ ///< destructor
+ ~NVRenderBackendShaderProgramGL(){}
+
+ QT3DSU32 m_ProgramID; ///< this is the OpenGL object ID
+ NVRenderBackendShaderInputGL *m_shaderInput; ///< pointer to shader input object
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h b/src/Runtime/Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h
new file mode 100644
index 00000000..397ecfb1
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/backends/software/Qt3DSRenderBackendNULL.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_BACKEND_NULL_H
+#define QT3DS_RENDER_BACKEND_NULL_H
+#include "render/backends/Qt3DSRenderBackend.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderBackendNULL : public NVRenderBackend
+ {
+ public:
+ static NVRenderBackend &CreateBackend(NVFoundationBase &foundation);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Qt3DSRender/Include/render/glg/Qt3DSGLImplObjects.h b/src/Runtime/Source/Qt3DSRender/Include/render/glg/Qt3DSGLImplObjects.h
new file mode 100644
index 00000000..28f246fd
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Include/render/glg/Qt3DSGLImplObjects.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef QT3DS_RENDER_GL_IMPL_OBJECTS_H
+#define QT3DS_RENDER_GL_IMPL_OBJECTS_H
+#include "render/backends/gl/Qt3DSOpenGLUtil.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSContainers.h"
+
+namespace qt3ds {
+namespace render {
+
+ // The set of all properties as they are currently set in hardware.
+ struct SNVGLHardPropertyContext
+ {
+ NVRenderFrameBuffer *m_FrameBuffer;
+ NVRenderShaderProgram *m_ActiveShader;
+ NVRenderProgramPipeline *m_ActiveProgramPipeline;
+ NVRenderInputAssembler *m_InputAssembler;
+ NVRenderBlendFunctionArgument m_BlendFunction;
+ NVRenderBlendEquationArgument m_BlendEquation;
+ bool m_CullingEnabled;
+ NVRenderBoolOp::Enum m_DepthFunction;
+ bool m_BlendingEnabled;
+ bool m_DepthWriteEnabled;
+ bool m_DepthTestEnabled;
+ bool m_StencilTestEnabled;
+ bool m_ScissorTestEnabled;
+ bool m_ColorWritesEnabled;
+ bool m_MultisampleEnabled;
+ NVRenderRect m_ScissorRect;
+ NVRenderRect m_Viewport;
+ QT3DSVec4 m_ClearColor;
+
+ SNVGLHardPropertyContext()
+ : m_FrameBuffer(NULL)
+ , m_ActiveShader(NULL)
+ , m_ActiveProgramPipeline(NULL)
+ , m_InputAssembler(NULL)
+ , m_CullingEnabled(true)
+ , m_DepthFunction(NVRenderBoolOp::Less)
+ , m_BlendingEnabled(true)
+ , m_DepthWriteEnabled(true)
+ , m_DepthTestEnabled(true)
+ , m_StencilTestEnabled(false)
+ , m_ScissorTestEnabled(true)
+ , m_ColorWritesEnabled(true)
+ , m_MultisampleEnabled(false)
+ , m_ClearColor(0, 0, 0, 1)
+ {
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAtomicCounterBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAtomicCounterBuffer.cpp
new file mode 100644
index 00000000..272c3e8c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAtomicCounterBuffer.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderAtomicCounterBuffer.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+namespace qt3ds {
+namespace render {
+
+ ///< struct handling a constant buffer entry
+ class AtomicCounterBufferEntry
+ {
+ public:
+ CRegisteredString m_Name; ///< parameter Name
+ QT3DSI32 m_Offset; ///< offset into the memory buffer
+
+ AtomicCounterBufferEntry(CRegisteredString name, QT3DSI32 offset)
+ : m_Name(name)
+ , m_Offset(offset)
+ {
+ }
+ };
+
+ NVRenderAtomicCounterBuffer::NVRenderAtomicCounterBuffer(
+ NVRenderContextImpl &context, CRegisteredString bufferName, size_t size,
+ NVRenderBufferUsageType::Enum usageType, NVDataRef<QT3DSU8> data)
+ : NVRenderDataBuffer(context, context.GetFoundation(), size,
+ NVRenderBufferBindValues::Storage, usageType, data)
+ , m_Name(bufferName)
+ , m_AtomicCounterBufferEntryMap(
+ m_Foundation.getAllocator(),
+ "NVRenderAtomicCounterBuffer::m_AtomicCounterBufferEntryMap")
+ , m_Dirty(true)
+ {
+ QT3DS_ASSERT(context.IsStorageBufferSupported());
+ }
+
+ NVRenderAtomicCounterBuffer::~NVRenderAtomicCounterBuffer()
+ {
+ for (TRenderAtomiCounterBufferEntryMap::iterator
+ iter = m_AtomicCounterBufferEntryMap.begin(),
+ end = m_AtomicCounterBufferEntryMap.end();
+ iter != end; ++iter) {
+ NVDelete(m_Foundation.getAllocator(), iter->second);
+ }
+
+ m_AtomicCounterBufferEntryMap.clear();
+
+ m_Context.BufferDestroyed(*this);
+ }
+
+ void NVRenderAtomicCounterBuffer::Bind()
+ {
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to Bind a locked buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ m_Backend->BindBuffer(m_BufferHandle, m_BindFlags);
+ }
+
+ void NVRenderAtomicCounterBuffer::BindToShaderProgram(QT3DSU32 index)
+ {
+ m_Backend->ProgramSetAtomicCounterBuffer(index, m_BufferHandle);
+ }
+
+ void NVRenderAtomicCounterBuffer::Update()
+ {
+ // we only update the buffer if it is dirty and we actually have some data
+ if (m_Dirty && m_BufferData.size()) {
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, m_BufferData.size(), m_UsageType,
+ m_BufferData.begin());
+ m_Dirty = false;
+ }
+ }
+
+ void NVRenderAtomicCounterBuffer::UpdateData(QT3DSI32 offset, NVDataRef<QT3DSU8> data)
+ {
+ // we only update the buffer if we something
+ if (data.size())
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, data.size(), m_UsageType,
+ data.begin() + offset);
+ }
+
+ void NVRenderAtomicCounterBuffer::AddParam(CRegisteredString name, QT3DSU32 offset)
+ {
+ if (m_AtomicCounterBufferEntryMap.find(name) == m_AtomicCounterBufferEntryMap.end()) {
+ AtomicCounterBufferEntry *newEntry =
+ QT3DS_NEW(m_Foundation.getAllocator(), AtomicCounterBufferEntry)(name, offset);
+
+ if (newEntry)
+ m_AtomicCounterBufferEntryMap.insert(eastl::make_pair(name, newEntry));
+ } else {
+ // no duplicated entries
+ return;
+ }
+ }
+
+ bool NVRenderAtomicCounterBuffer::ContainsParam(CRegisteredString name)
+ {
+ if (m_AtomicCounterBufferEntryMap.find(name) != m_AtomicCounterBufferEntryMap.end())
+ return true;
+ else
+ return false;
+ }
+
+ NVRenderAtomicCounterBuffer *
+ NVRenderAtomicCounterBuffer::Create(NVRenderContextImpl &context, const char *bufferName,
+ NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVFoundationBase &fnd(context.GetFoundation());
+ NVRenderAtomicCounterBuffer *retval = NULL;
+
+ if (context.IsAtomicCounterBufferSupported()) {
+ CRegisteredString theBufferName(context.GetStringTable().RegisterStr(bufferName));
+ QT3DSU32 bufSize = sizeof(NVRenderAtomicCounterBuffer);
+ QT3DSU8 *newMem = (QT3DSU8 *)QT3DS_ALLOC(fnd.getAllocator(), bufSize, "AtomicCounterBuffer");
+ retval = new (newMem) NVRenderAtomicCounterBuffer(
+ context, theBufferName, size, usageType,
+ toDataRef(const_cast<QT3DSU8 *>(bufferData.begin()), bufferData.size()));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAttribLayout.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAttribLayout.cpp
new file mode 100644
index 00000000..42641a04
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderAttribLayout.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderAttribLayout.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ ///< constructor
+ NVRenderAttribLayout::NVRenderAttribLayout(NVRenderContextImpl &context,
+ NVConstDataRef<NVRenderVertexBufferEntry> attribs)
+ : m_Context(context)
+ , m_Foundation(context.GetFoundation())
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ {
+ m_AttribLayoutHandle = m_Backend->CreateAttribLayout(attribs);
+ QT3DS_ASSERT(m_AttribLayoutHandle);
+ }
+
+ ///< destructor
+ NVRenderAttribLayout::~NVRenderAttribLayout()
+ {
+ if (m_AttribLayoutHandle) {
+ m_Backend->ReleaseAttribLayout(m_AttribLayoutHandle);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderComputeShader.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderComputeShader.cpp
new file mode 100644
index 00000000..01aef473
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderComputeShader.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderComputeShader.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderComputeShader::NVRenderComputeShader(NVRenderContextImpl &context,
+ NVFoundationBase &fnd, NVConstDataRef<QT3DSI8> source,
+ bool binaryProgram)
+ : NVRenderShader(context, fnd, source, binaryProgram)
+ , m_ShaderHandle(NULL)
+ {
+ m_ShaderHandle = m_Backend->CreateComputeShader(source, m_ErrorMessage, binaryProgram);
+ }
+
+ NVRenderComputeShader::~NVRenderComputeShader()
+ {
+ if (m_ShaderHandle) {
+ m_Backend->ReleaseComputeShader(m_ShaderHandle);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp
new file mode 100644
index 00000000..33c8f271
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderConstantBuffer.cpp
@@ -0,0 +1,421 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderConstantBuffer.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+namespace qt3ds {
+namespace render {
+
+ ///< struct handling a constant buffer entry
+ class ConstantBufferParamEntry
+ {
+ public:
+ CRegisteredString m_Name; ///< parameter Name
+ NVRenderShaderDataTypes::Enum m_Type; ///< parameter type
+ QT3DSI32 m_Count; ///< one or array size
+ QT3DSI32 m_Offset; ///< offset into the memory buffer
+
+ ConstantBufferParamEntry(CRegisteredString name, NVRenderShaderDataTypes::Enum type,
+ QT3DSI32 count, QT3DSI32 offset)
+ : m_Name(name)
+ , m_Type(type)
+ , m_Count(count)
+ , m_Offset(offset)
+ {
+ }
+ };
+
+ NVRenderConstantBuffer::NVRenderConstantBuffer(NVRenderContextImpl &context,
+ CRegisteredString bufferName, size_t size,
+ NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data)
+ : NVRenderDataBuffer(context, context.GetFoundation(), size,
+ NVRenderBufferBindValues::Constant, usageType, NVDataRef<QT3DSU8>())
+ , m_Name(bufferName)
+ , m_ConstantBufferEntryMap(m_Foundation.getAllocator(),
+ "NVRenderConstantBuffer::m_ConstantBufferEntryMap")
+ , m_CurrentOffset(0)
+ , m_CurrentSize(0)
+ , m_HWBufferInitialized(false)
+ , m_Dirty(true)
+ , m_RangeStart(0)
+ , m_RangeEnd(0)
+ , m_MaxBlockSize(0)
+ {
+ QT3DS_ASSERT(context.GetConstantBufferSupport());
+
+ m_Backend->GetRenderBackendValue(
+ NVRenderBackend::NVRenderBackendQuery::MaxConstantBufferBlockSize, &m_MaxBlockSize);
+
+ if (size && data.size() && size == data.size()) {
+ QT3DS_ASSERT(size < (QT3DSU32)m_MaxBlockSize);
+ if (allocateShadowBuffer(data.size())) {
+ memcpy(m_ShadowCopy.begin(), data.begin(), data.size());
+ }
+ }
+ }
+
+ NVRenderConstantBuffer::~NVRenderConstantBuffer()
+ {
+ // chekc if we should release memory
+ if (m_ShadowCopy.size()) {
+ m_Foundation.getAllocator().deallocate(m_ShadowCopy.begin());
+ }
+
+ m_ShadowCopy = NVDataRef<QT3DSU8>();
+
+ for (TRenderConstantBufferEntryMap::iterator iter = m_ConstantBufferEntryMap.begin(),
+ end = m_ConstantBufferEntryMap.end();
+ iter != end; ++iter) {
+ NVDelete(m_Foundation.getAllocator(), iter->second);
+ }
+
+ m_ConstantBufferEntryMap.clear();
+
+ m_Context.BufferDestroyed(*this);
+ }
+
+ void NVRenderConstantBuffer::Bind()
+ {
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to Bind a locked buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ m_Backend->BindBuffer(m_BufferHandle, m_BindFlags);
+ }
+
+ void NVRenderConstantBuffer::BindToShaderProgram(NVRenderShaderProgram *inShader,
+ QT3DSU32 blockIndex, QT3DSU32 binding)
+ {
+ if ((QT3DSI32)binding == -1) {
+ binding = m_Context.GetNextConstantBufferUnit();
+ m_Backend->ProgramSetConstantBlock(inShader->GetShaderProgramHandle(), blockIndex,
+ binding);
+ }
+
+ m_Backend->ProgramSetConstantBuffer(binding, m_BufferHandle);
+ }
+
+ bool NVRenderConstantBuffer::SetupBuffer(NVRenderShaderProgram *pProgram, QT3DSI32 index,
+ QT3DSI32 bufSize, QT3DSI32 paramCount)
+ {
+ bool bSuccess = false;
+
+ if (!m_HWBufferInitialized) {
+ // allocate shadow buffer
+ QT3DSU8 *newMem = (QT3DSU8 *)m_Foundation.getAllocator().allocate(
+ bufSize, "NVRenderConstantBuffer", __FILE__, __LINE__);
+ if (!newMem)
+ return false;
+
+ // allocate temp buffers to hold constant buffer information
+ QT3DSI32 *theIndices = NULL, *theTypes = NULL, *theSizes = NULL, *theOffsets = NULL;
+ theIndices = (QT3DSI32 *)QT3DS_ALLOC(m_Foundation.getAllocator(), paramCount * sizeof(QT3DSI32),
+ "NVRenderConstantBuffer");
+ if (!theIndices)
+ goto fail;
+ theTypes = (QT3DSI32 *)QT3DS_ALLOC(m_Foundation.getAllocator(), paramCount * sizeof(QT3DSI32),
+ "NVRenderConstantBuffer");
+ if (!theTypes)
+ goto fail;
+ theSizes = (QT3DSI32 *)QT3DS_ALLOC(m_Foundation.getAllocator(), paramCount * sizeof(QT3DSI32),
+ "NVRenderConstantBuffer");
+ if (!theSizes)
+ goto fail;
+ theOffsets = (QT3DSI32 *)QT3DS_ALLOC(m_Foundation.getAllocator(), paramCount * sizeof(QT3DSI32),
+ "NVRenderConstantBuffer");
+ if (!theOffsets)
+ goto fail;
+
+ bSuccess = true;
+
+ // get indices for the individal constant buffer entries
+ m_Backend->GetConstantBufferParamIndices(pProgram->GetShaderProgramHandle(), index,
+ theIndices);
+
+ // get constant buffer uniform information
+ m_Backend->GetConstantBufferParamInfoByIndices(pProgram->GetShaderProgramHandle(),
+ paramCount, (QT3DSU32 *)theIndices,
+ theTypes, theSizes, theOffsets);
+
+ // get the names of the uniforms
+ char nameBuf[512];
+ QT3DSI32 elementCount, binding;
+ NVRenderShaderDataTypes::Enum type;
+
+ UICBASE_FOREACH(idx, paramCount)
+ {
+ m_Backend->GetConstantInfoByID(pProgram->GetShaderProgramHandle(), theIndices[idx],
+ 512, &elementCount, &type, &binding, nameBuf);
+ // check if we already have this entry
+ CRegisteredString theName(m_Context.GetStringTable().RegisterStr(nameBuf));
+ TRenderConstantBufferEntryMap::iterator entry =
+ m_ConstantBufferEntryMap.find(theName);
+ if (entry != m_ConstantBufferEntryMap.end()) {
+ ConstantBufferParamEntry *pParam = entry->second;
+ // copy content
+ if (m_ShadowCopy.size())
+ memcpy(newMem + theOffsets[idx],
+ m_ShadowCopy.begin() + entry->second->m_Offset,
+ entry->second->m_Count * getUniformTypeSize(pParam->m_Type));
+
+ pParam->m_Offset = theOffsets[idx];
+ QT3DS_ASSERT(type == pParam->m_Type);
+ QT3DS_ASSERT(elementCount == pParam->m_Count);
+ } else {
+ // create one
+ m_ConstantBufferEntryMap.insert(eastl::make_pair(
+ theName,
+ createParamEntry(theName, (NVRenderShaderDataTypes::Enum)theTypes[idx],
+ theSizes[idx], theOffsets[idx])));
+ }
+ }
+
+ // release previous one
+ if (m_ShadowCopy.size()) {
+ m_Foundation.getAllocator().deallocate(m_ShadowCopy.begin());
+ }
+ // set new one
+ m_ShadowCopy = NVDataRef<QT3DSU8>(newMem, bufSize);
+
+ m_HWBufferInitialized = true;
+
+ fail:
+ if (theIndices)
+ QT3DS_FREE(m_Foundation.getAllocator(), theIndices);
+ if (theTypes)
+ QT3DS_FREE(m_Foundation.getAllocator(), theTypes);
+ if (theSizes)
+ QT3DS_FREE(m_Foundation.getAllocator(), theSizes);
+ if (theOffsets)
+ QT3DS_FREE(m_Foundation.getAllocator(), theOffsets);
+
+ } else {
+ // some sanity checks
+ bSuccess = true;
+ bSuccess &= (m_ShadowCopy.size() <= (QT3DSU32)bufSize);
+ }
+
+ return bSuccess;
+ }
+
+ void NVRenderConstantBuffer::Update()
+ {
+ // we only update the buffer if the buffer is already on hardware
+ // and if it is dirty
+ if (m_Dirty && m_HWBufferInitialized) {
+ if (m_RangeEnd == 0)
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, m_ShadowCopy.size(),
+ m_UsageType, m_ShadowCopy.begin());
+ else
+ UpdateRange();
+
+ m_Dirty = false;
+ m_RangeStart = m_RangeEnd = 0;
+ }
+ }
+
+ void NVRenderConstantBuffer::UpdateRange()
+ {
+ if ((m_RangeStart + m_RangeEnd) > m_ShadowCopy.size()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ m_Backend->UpdateBufferRange(m_BufferHandle, m_BindFlags, m_RangeStart,
+ m_RangeEnd - m_RangeStart,
+ m_ShadowCopy.begin() + m_RangeStart);
+ }
+
+ void NVRenderConstantBuffer::AddParam(CRegisteredString name,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count)
+ {
+ if (m_ConstantBufferEntryMap.find(name) == m_ConstantBufferEntryMap.end()) {
+ ConstantBufferParamEntry *newEntry =
+ QT3DS_NEW(m_Foundation.getAllocator(), ConstantBufferParamEntry)(name, type, count,
+ m_CurrentOffset);
+
+ if (newEntry)
+ m_ConstantBufferEntryMap.insert(eastl::make_pair(name, newEntry));
+ } else {
+ // no duplicated entries
+ return;
+ }
+
+ // compute new current buffer size and offset
+ QT3DSI32 constantSize = getUniformTypeSize(type) * count;
+ m_CurrentSize += constantSize;
+ m_CurrentOffset += constantSize;
+ }
+
+ void NVRenderConstantBuffer::UpdateParam(const char *inName, NVDataRef<QT3DSU8> value)
+ {
+ // allocate space if not done yet
+ // NOTE this gets reallocated once we get the real constant buffer size from a program
+ if (!m_ShadowCopy.size()) {
+ // allocate shadow buffer
+ if (!allocateShadowBuffer(m_CurrentSize))
+ return;
+ }
+
+ CRegisteredString theName(m_Context.GetStringTable().RegisterStr(inName));
+ TRenderConstantBufferEntryMap::iterator entry = m_ConstantBufferEntryMap.find(theName);
+ if (entry != m_ConstantBufferEntryMap.end()) {
+ if (!memcmp(m_ShadowCopy.begin() + entry->second->m_Offset, value.begin(),
+ entry->second->m_Count * getUniformTypeSize(entry->second->m_Type))) {
+ return;
+ }
+ memcpy(m_ShadowCopy.begin() + entry->second->m_Offset, value.begin(),
+ entry->second->m_Count * getUniformTypeSize(entry->second->m_Type));
+ m_Dirty = true;
+ }
+ }
+
+ void NVRenderConstantBuffer::UpdateRaw(QT3DSI32 offset, NVDataRef<QT3DSU8> data)
+ {
+ // allocate space if yet done
+ if (!m_ShadowCopy.size()) {
+ // allocate shadow buffer
+ if (!allocateShadowBuffer(data.size()))
+ return;
+ }
+
+ QT3DS_ASSERT((offset + data.size()) < (QT3DSU32)m_MaxBlockSize);
+
+ // we do not initialize anything when this is used
+ m_HWBufferInitialized = true;
+
+ // we do not allow resize once allocated
+ if ((offset + data.size()) > m_ShadowCopy.size())
+ return;
+
+ // copy data
+ if (!memcmp(m_ShadowCopy.begin() + offset, data.begin(), data.size())) {
+ return;
+ }
+ memcpy(m_ShadowCopy.begin() + offset, data.begin(), data.size());
+
+ // update start
+ m_RangeStart = (m_Dirty) ? (m_RangeStart > (QT3DSU32)offset) ? offset : m_RangeStart : offset;
+ m_RangeEnd = (offset + data.size() > m_RangeEnd) ? offset + data.size() : m_RangeEnd;
+
+ m_Dirty = true;
+ }
+
+ ConstantBufferParamEntry *NVRenderConstantBuffer::createParamEntry(
+ CRegisteredString name, NVRenderShaderDataTypes::Enum type, QT3DSI32 count, QT3DSI32 offset)
+ {
+ ConstantBufferParamEntry *newEntry = QT3DS_NEW(
+ m_Foundation.getAllocator(), ConstantBufferParamEntry)(name, type, count, offset);
+
+ return newEntry;
+ }
+
+ QT3DSI32
+ NVRenderConstantBuffer::getUniformTypeSize(NVRenderShaderDataTypes::Enum type)
+ {
+ switch (type) {
+ case NVRenderShaderDataTypes::QT3DSF32:
+ return sizeof(QT3DSF32);
+ case NVRenderShaderDataTypes::QT3DSI32:
+ return sizeof(QT3DSI32);
+ case NVRenderShaderDataTypes::QT3DSI32_2:
+ return sizeof(QT3DSI32) * 2;
+ case NVRenderShaderDataTypes::QT3DSI32_3:
+ return sizeof(QT3DSI32) * 3;
+ case NVRenderShaderDataTypes::QT3DSI32_4:
+ return sizeof(QT3DSI32) * 4;
+ case NVRenderShaderDataTypes::QT3DSU32:
+ return sizeof(QT3DSU32);
+ case NVRenderShaderDataTypes::QT3DSU32_2:
+ return sizeof(QT3DSU32) * 2;
+ case NVRenderShaderDataTypes::QT3DSU32_3:
+ return sizeof(QT3DSU32) * 3;
+ case NVRenderShaderDataTypes::QT3DSU32_4:
+ return sizeof(QT3DSU32) * 4;
+ case NVRenderShaderDataTypes::QT3DSVec2:
+ return sizeof(QT3DSF32) * 2;
+ case NVRenderShaderDataTypes::QT3DSVec3:
+ return sizeof(QT3DSF32) * 3;
+ case NVRenderShaderDataTypes::QT3DSVec4:
+ return sizeof(QT3DSF32) * 4;
+ case NVRenderShaderDataTypes::QT3DSMat33:
+ return sizeof(QT3DSF32) * 9;
+ case NVRenderShaderDataTypes::QT3DSMat44:
+ return sizeof(QT3DSF32) * 16;
+ default:
+ QT3DS_ASSERT(!"Unhandled type in NVRenderConstantBuffer::getUniformTypeSize");
+ break;
+ }
+
+ return 0;
+ }
+
+ bool NVRenderConstantBuffer::allocateShadowBuffer(QT3DSU32 size)
+ {
+ // allocate shadow buffer
+ QT3DSU8 *newMem = (QT3DSU8 *)m_Foundation.getAllocator().allocate(size, "NVRenderConstantBuffer",
+ __FILE__, __LINE__);
+ if (!newMem)
+ return false;
+
+ m_ShadowCopy = NVDataRef<QT3DSU8>(newMem, size);
+
+ m_BufferCapacity = size;
+
+ return true;
+ }
+
+ NVRenderConstantBuffer *NVRenderConstantBuffer::Create(NVRenderContextImpl &context,
+ const char *bufferName,
+ NVRenderBufferUsageType::Enum usageType,
+ size_t size,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVFoundationBase &fnd(context.GetFoundation());
+ NVRenderConstantBuffer *retval = NULL;
+
+ if (context.GetConstantBufferSupport()) {
+ CRegisteredString theBufferName(context.GetStringTable().RegisterStr(bufferName));
+ QT3DSU32 cbufSize = sizeof(NVRenderConstantBuffer);
+ QT3DSU8 *newMem = (QT3DSU8 *)QT3DS_ALLOC(fnd.getAllocator(), cbufSize, "ConstantBuffer");
+ retval = new (newMem) NVRenderConstantBuffer(
+ context, theBufferName, size, usageType,
+ toDataRef(const_cast<QT3DSU8 *>(bufferData.begin()), bufferData.size()));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderContext.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderContext.cpp
new file mode 100644
index 00000000..4e81c539
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderContext.cpp
@@ -0,0 +1,1105 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSMat44.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Utils.h"
+#include "EASTL/set.h"
+#include "EASTL/utility.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace eastl;
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderContextImpl::NVRenderContextImpl(NVFoundationBase &fnd, NVRenderBackend &inBackend,
+ IStringTable &inStrTable)
+ : m_backend(inBackend)
+ , m_DirtyFlags(0)
+ , m_DefaultOffscreenRenderTarget((NVRenderBackend::NVRenderBackendRenderTargetObject)NULL)
+ , m_DephBits(16)
+ , m_StencilBits(8)
+ , mRefCount(0)
+ , m_Foundation(fnd)
+ , m_StringTable(inStrTable)
+ , m_VertToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_VertToImpMap")
+ , m_IndexToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_IndexToImpMap")
+ , m_ConstantToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_ConstantToImpMap")
+ , m_StorageToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_StorageToImpMap")
+ , m_AtomicCounterToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_AtomicCounterToImpMap")
+ , m_DrawIndirectToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_DrawIndirectToImpMap")
+ , m_DepthStencilStateToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_DepthStencilStateToImpMap")
+ , m_RasterizerStateToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_RasterizerStateToImpMap")
+ , m_PathFontSpecToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_RasterizerStateToImpMap")
+ , m_Tex2DToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_Tex2DToImpMap")
+ , m_Tex2DArrayToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_Tex2DArrayToImpMap")
+ , m_TexCubeToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_TexCubeToImpMap")
+ , m_Image2DtoImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_Image2DtoImpMap")
+ , m_ShaderToImpMap(m_Foundation.getAllocator(), "NVRenderContextImpl::m_ShaderToImpMap")
+ , m_RenderBufferToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_RenderBufferToImpMap")
+ , m_FrameBufferToImpMap(m_Foundation.getAllocator(),
+ "NVRenderContextImpl::m_FrameBufferToImpMap")
+ , m_NextTextureUnit(1)
+ , m_NextConstantBufferUnit(1)
+ , m_PropertyStack(m_Foundation.getAllocator(), "NVRenderContextImpl::m_PropertyStack")
+ {
+
+ m_StringTable.addRef();
+
+ m_MaxTextureUnits = m_backend->GetMaxCombinedTextureUnits();
+ m_MaxConstantBufferUnits = 16; // need backend query
+
+ // get initial state
+ memZero(&m_HardwarePropertyContext, sizeof(m_HardwarePropertyContext));
+
+ // get default blending functions
+ m_backend->GetBlendFunc(&m_HardwarePropertyContext.m_BlendFunction);
+ // set default blend euqation
+ m_HardwarePropertyContext.m_BlendEquation.m_RGBEquation = NVRenderBlendEquation::Add;
+ m_HardwarePropertyContext.m_BlendEquation.m_AlphaEquation = NVRenderBlendEquation::Add;
+ // default state
+ m_HardwarePropertyContext.m_CullingEnabled =
+ m_backend->GetRenderState(NVRenderState::CullFace);
+ m_HardwarePropertyContext.m_DepthFunction = m_backend->GetDepthFunc();
+ m_HardwarePropertyContext.m_BlendingEnabled =
+ m_backend->GetRenderState(NVRenderState::Blend);
+ m_HardwarePropertyContext.m_DepthWriteEnabled = m_backend->GetDepthWrite();
+ m_HardwarePropertyContext.m_DepthTestEnabled =
+ m_backend->GetRenderState(NVRenderState::DepthTest);
+ m_HardwarePropertyContext.m_ScissorTestEnabled =
+ m_backend->GetRenderState(NVRenderState::ScissorTest);
+ m_backend->GetScissorRect(&m_HardwarePropertyContext.m_ScissorRect);
+ m_backend->GetViewportRect(&m_HardwarePropertyContext.m_Viewport);
+ }
+
+ NVRenderContextImpl::~NVRenderContextImpl()
+ {
+ m_StringTable.release();
+ QT3DS_ASSERT(m_VertToImpMap.size() == 0);
+ m_VertToImpMap.clear();
+ QT3DS_ASSERT(m_IndexToImpMap.size() == 0);
+ m_IndexToImpMap.clear();
+ QT3DS_ASSERT(m_ConstantToImpMap.size() == 0);
+ m_ConstantToImpMap.clear();
+ QT3DS_ASSERT(m_StorageToImpMap.size() == 0);
+ m_StorageToImpMap.clear();
+ QT3DS_ASSERT(m_DepthStencilStateToImpMap.size() == 0);
+ m_DepthStencilStateToImpMap.clear();
+ QT3DS_ASSERT(m_RasterizerStateToImpMap.size() == 0);
+ m_RasterizerStateToImpMap.clear();
+ QT3DS_ASSERT(m_PathFontSpecToImpMap.size() == 0);
+ m_PathFontSpecToImpMap.clear();
+ QT3DS_ASSERT(m_Tex2DToImpMap.size() == 0);
+ m_Tex2DToImpMap.clear();
+ QT3DS_ASSERT(m_Tex2DArrayToImpMap.size() == 0);
+ m_Tex2DArrayToImpMap.clear();
+ QT3DS_ASSERT(m_Image2DtoImpMap.size() == 0);
+ m_Image2DtoImpMap.clear();
+ QT3DS_ASSERT(m_ShaderToImpMap.size() == 0);
+ m_ShaderToImpMap.clear();
+ QT3DS_ASSERT(m_RenderBufferToImpMap.size() == 0);
+ m_RenderBufferToImpMap.clear();
+ QT3DS_ASSERT(m_FrameBufferToImpMap.size() == 0);
+ m_FrameBufferToImpMap.clear();
+
+ m_backend = NULL;
+ }
+
+ void NVRenderContextImpl::getMaxTextureSize(QT3DSU32 &oWidth, QT3DSU32 &oHeight)
+ {
+ QT3DSI32 theMaxTextureSize = 0;
+ m_backend->GetRenderBackendValue(NVRenderBackend::NVRenderBackendQuery::MaxTextureSize,
+ &theMaxTextureSize);
+
+ oWidth = (QT3DSU32)theMaxTextureSize;
+ oHeight = (QT3DSU32)theMaxTextureSize;
+ }
+
+ NVRenderDepthStencilState *NVRenderContextImpl::CreateDepthStencilState(
+ bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc, bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack)
+ {
+ NVRenderDepthStencilState *state = NVRenderDepthStencilState::Create(
+ *this, enableDepth, depthMask, depthFunc, enableStencil, stencilFuncFront,
+ stencilFuncBack, depthStencilOpFront, depthStencilOpBack);
+ if (state)
+ m_DepthStencilStateToImpMap.insert(
+ make_pair(state->GetDepthStencilObjectHandle(), state));
+
+ return state;
+ }
+
+ void NVRenderContextImpl::SetDepthStencilState(NVRenderDepthStencilState *inDepthStencilState)
+ {
+ if (inDepthStencilState) {
+ m_backend->SetDepthStencilState(inDepthStencilState->GetDepthStencilObjectHandle());
+ // currently we have a mixture therefore we need to update the context state
+ SetDepthFunction(inDepthStencilState->GetDepthFunc());
+ SetDepthWriteEnabled(inDepthStencilState->GetDepthMask());
+ SetDepthTestEnabled(inDepthStencilState->GetDepthEnabled());
+ SetStencilTestEnabled(inDepthStencilState->GetStencilEnabled());
+ }
+ }
+
+ void NVRenderContextImpl::StateDestroyed(NVRenderDepthStencilState &state)
+ {
+ m_DepthStencilStateToImpMap.erase(state.GetDepthStencilObjectHandle());
+ }
+
+ NVRenderRasterizerState *
+ NVRenderContextImpl::CreateRasterizerState(QT3DSF32 depthBias, QT3DSF32 depthScale,
+ NVRenderFaces::Enum cullFace)
+ {
+ NVRenderRasterizerState *state =
+ NVRenderRasterizerState::Create(*this, depthBias, depthScale, cullFace);
+ if (state)
+ m_RasterizerStateToImpMap.insert(make_pair(state->GetRasterizerObjectHandle(), state));
+
+ return state;
+ }
+
+ void NVRenderContextImpl::SetRasterizerState(NVRenderRasterizerState *inRasterizerState)
+ {
+ if (inRasterizerState)
+ m_backend->SetRasterizerState(inRasterizerState->GetRasterizerObjectHandle());
+ }
+
+ void NVRenderContextImpl::StateDestroyed(NVRenderRasterizerState &state)
+ {
+ m_RasterizerStateToImpMap.erase(state.GetRasterizerObjectHandle());
+ }
+
+ NVRenderVertexBuffer *
+ NVRenderContextImpl::CreateVertexBuffer(NVRenderBufferUsageType::Enum usageType, size_t size,
+ QT3DSU32 stride, NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderVertexBuffer *buffer =
+ NVRenderVertexBuffer::Create(*this, usageType, size, stride, bufferData);
+ if (buffer)
+ m_VertToImpMap.insert(make_pair(buffer->GetImplementationHandle(), buffer));
+ return buffer;
+ }
+
+ NVRenderVertexBuffer *NVRenderContextImpl::GetVertexBuffer(const void *implementationHandle)
+ {
+ nvhash_map<const void *, NVRenderVertexBuffer *>::const_iterator entry =
+ m_VertToImpMap.find(implementationHandle);
+ if (entry != m_VertToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::BufferDestroyed(NVRenderVertexBuffer &buffer)
+ {
+ m_VertToImpMap.erase(buffer.GetImplementationHandle());
+ }
+
+ NVRenderIndexBuffer *
+ NVRenderContextImpl::CreateIndexBuffer(qt3ds::render::NVRenderBufferUsageType::Enum usageType,
+ qt3ds::render::NVRenderComponentTypes::Enum componentType,
+ size_t size, NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderIndexBuffer *buffer =
+ NVRenderIndexBuffer::Create(*this, usageType, componentType, size, bufferData);
+
+ if (buffer) {
+ m_IndexToImpMap.insert(make_pair(buffer->GetImplementationHandle(), buffer));
+ }
+
+ return buffer;
+ }
+
+ NVRenderIndexBuffer *NVRenderContextImpl::GetIndexBuffer(const void *implementationHandle)
+ {
+ const nvhash_map<const void *, NVRenderIndexBuffer *>::iterator entry =
+ m_IndexToImpMap.find(implementationHandle);
+ if (entry != m_IndexToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::BufferDestroyed(NVRenderIndexBuffer &buffer)
+ {
+ m_IndexToImpMap.erase(buffer.GetImplementationHandle());
+ }
+
+ NVRenderConstantBuffer *
+ NVRenderContextImpl::CreateConstantBuffer(const char *bufferName,
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType,
+ size_t size, NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderConstantBuffer *buffer =
+ NVRenderConstantBuffer::Create(*this, bufferName, usageType, size, bufferData);
+
+ if (buffer) {
+ m_ConstantToImpMap.insert(make_pair(buffer->GetBufferName(), buffer));
+ }
+
+ return buffer;
+ }
+
+ NVRenderConstantBuffer *NVRenderContextImpl::GetConstantBuffer(CRegisteredString bufferName)
+ {
+ TContextConstantBufferMap::iterator entry = m_ConstantToImpMap.find(bufferName);
+ if (entry != m_ConstantToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::BufferDestroyed(NVRenderConstantBuffer &buffer)
+ {
+ m_ConstantToImpMap.erase(buffer.GetBufferName());
+ }
+
+ QT3DSU32 NVRenderContextImpl::GetNextConstantBufferUnit()
+ {
+ QT3DSU32 retval = m_NextConstantBufferUnit;
+ ++m_NextConstantBufferUnit;
+ // Too many texture units for a single draw call.
+ if (retval >= m_MaxConstantBufferUnits) {
+ QT3DS_ASSERT(false);
+ retval = retval % m_MaxConstantBufferUnits;
+ }
+ return retval;
+ }
+
+ NVRenderStorageBuffer *NVRenderContextImpl::CreateStorageBuffer(
+ const char *bufferName, qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData, NVRenderDataBuffer *pBuffer)
+ {
+ NVRenderStorageBuffer *buffer =
+ NVRenderStorageBuffer::Create(*this, bufferName, usageType, size, bufferData, pBuffer);
+
+ if (buffer) {
+ m_StorageToImpMap.insert(make_pair(buffer->GetBufferName(), buffer));
+ }
+
+ return buffer;
+ }
+
+ NVRenderStorageBuffer *NVRenderContextImpl::GetStorageBuffer(CRegisteredString bufferName)
+ {
+ TContextStorageBufferMap::iterator entry = m_StorageToImpMap.find(bufferName);
+ if (entry != m_StorageToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::BufferDestroyed(NVRenderStorageBuffer &buffer)
+ {
+ m_StorageToImpMap.erase(buffer.GetBufferName());
+ }
+
+ NVRenderAtomicCounterBuffer *NVRenderContextImpl::CreateAtomicCounterBuffer(
+ const char *bufferName, qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderAtomicCounterBuffer *buffer =
+ NVRenderAtomicCounterBuffer::Create(*this, bufferName, usageType, size, bufferData);
+
+ if (buffer) {
+ m_AtomicCounterToImpMap.insert(make_pair(buffer->GetBufferName(), buffer));
+ }
+
+ return buffer;
+ }
+
+ NVRenderAtomicCounterBuffer *
+ NVRenderContextImpl::GetAtomicCounterBuffer(CRegisteredString bufferName)
+ {
+ TContextAtomicCounterBufferMap::iterator entry = m_AtomicCounterToImpMap.find(bufferName);
+ if (entry != m_AtomicCounterToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ NVRenderAtomicCounterBuffer *
+ NVRenderContextImpl::GetAtomicCounterBufferByParam(CRegisteredString paramName)
+ {
+ // iterate through all atomic counter buffers
+ for (TContextAtomicCounterBufferMap::iterator iter = m_AtomicCounterToImpMap.begin(),
+ end = m_AtomicCounterToImpMap.end();
+ iter != end; ++iter) {
+ if (iter->second && iter->second->ContainsParam(paramName))
+ return iter->second;
+ }
+
+ return NULL;
+ }
+
+ void NVRenderContextImpl::BufferDestroyed(NVRenderAtomicCounterBuffer &buffer)
+ {
+ m_AtomicCounterToImpMap.erase(buffer.GetBufferName());
+ }
+
+ NVRenderDrawIndirectBuffer *NVRenderContextImpl::CreateDrawIndirectBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderDrawIndirectBuffer *buffer =
+ NVRenderDrawIndirectBuffer::Create(*this, usageType, size, bufferData);
+
+ if (buffer) {
+ m_DrawIndirectToImpMap.insert(make_pair(buffer->GetBuffertHandle(), buffer));
+ }
+
+ return buffer;
+ }
+
+ NVRenderDrawIndirectBuffer *NVRenderContextImpl::GetDrawIndirectBuffer(
+ NVRenderBackend::NVRenderBackendBufferObject implementationHandle)
+ {
+ TContextDrawIndirectBufferMap::iterator entry =
+ m_DrawIndirectToImpMap.find(implementationHandle);
+ if (entry != m_DrawIndirectToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::BufferDestroyed(NVRenderDrawIndirectBuffer &buffer)
+ {
+ m_DrawIndirectToImpMap.erase(buffer.GetBuffertHandle());
+ }
+
+ void NVRenderContextImpl::SetMemoryBarrier(NVRenderBufferBarrierFlags barriers)
+ {
+ m_backend->SetMemoryBarrier(barriers);
+ }
+
+ NVRenderOcclusionQuery *NVRenderContextImpl::CreateOcclusionQuery()
+ {
+ NVRenderOcclusionQuery *theQuery = NVRenderOcclusionQuery::Create(*this);
+
+ return theQuery;
+ }
+
+ NVRenderTimerQuery *NVRenderContextImpl::CreateTimerQuery()
+ {
+ NVRenderTimerQuery *theQuery = NVRenderTimerQuery::Create(*this);
+
+ return theQuery;
+ }
+
+ NVRenderSync *NVRenderContextImpl::CreateSync()
+ {
+ NVRenderSync *theSync = NVRenderSync::Create(*this);
+
+ return theSync;
+ }
+
+ NVRenderTexture2D *NVRenderContextImpl::CreateTexture2D()
+ {
+ NVRenderTexture2D *retval = NVRenderTexture2D::Create(*this);
+ if (retval)
+ m_Tex2DToImpMap.insert(make_pair(retval->GetImplementationHandle(), retval));
+ return retval;
+ }
+
+ NVRenderTexture2DArray *NVRenderContextImpl::CreateTexture2DArray()
+ {
+ NVRenderTexture2DArray *retval = NVRenderTexture2DArray::Create(*this);
+ if (retval)
+ m_Tex2DArrayToImpMap.insert(make_pair(retval->GetTextureObjectHandle(), retval));
+
+ return retval;
+ }
+
+ NVRenderTextureCube *NVRenderContextImpl::CreateTextureCube()
+ {
+ NVRenderTextureCube *retval = NVRenderTextureCube::Create(*this);
+ if (retval)
+ m_TexCubeToImpMap.insert(make_pair(retval->GetTextureObjectHandle(), retval));
+
+ return retval;
+ }
+
+ NVRenderTexture2D *NVRenderContextImpl::GetTexture2D(const void *implementationHandle)
+ {
+ const nvhash_map<const void *, NVRenderTexture2D *>::iterator entry =
+ m_Tex2DToImpMap.find(implementationHandle);
+ if (entry != m_Tex2DToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::TextureDestroyed(NVRenderTexture2D &buffer)
+ {
+ m_Tex2DToImpMap.erase(buffer.GetImplementationHandle());
+ // We would like to find and catch any situations where this texture is being used
+ // but that would require some real work that we don't want to do right now.
+ }
+
+ void NVRenderContextImpl::TextureDestroyed(NVRenderTexture2DArray &buffer)
+ {
+ m_Tex2DArrayToImpMap.erase(buffer.GetTextureObjectHandle());
+ }
+
+ void NVRenderContextImpl::TextureDestroyed(NVRenderTextureCube &buffer)
+ {
+ m_TexCubeToImpMap.erase(buffer.GetTextureObjectHandle());
+ }
+
+ NVRenderImage2D *NVRenderContextImpl::CreateImage2D(NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess)
+ {
+ NVRenderImage2D *retval = NVRenderImage2D::Create(*this, inTexture, inAccess);
+ if (retval)
+ m_Image2DtoImpMap.insert(make_pair(retval->GetTextureObjectHandle(), retval));
+
+ return retval;
+ }
+
+ void NVRenderContextImpl::ImageDestroyed(NVRenderImage2D &image)
+ {
+ m_Image2DtoImpMap.erase(image.GetTextureObjectHandle());
+ }
+
+ // IF this texture isn't on a texture unit, put it on one.
+ // If it is on a texture unit, mark it as the most recently used texture.
+ QT3DSU32 NVRenderContextImpl::GetNextTextureUnit()
+ {
+ QT3DSU32 retval = m_NextTextureUnit;
+ ++m_NextTextureUnit;
+ // Too many texture units for a single draw call.
+ if (retval >= m_MaxTextureUnits) {
+ QT3DS_ASSERT(false);
+ retval = retval % m_MaxTextureUnits;
+ }
+ return retval;
+ }
+
+ NVRenderRenderBuffer *
+ NVRenderContextImpl::CreateRenderBuffer(NVRenderRenderBufferFormats::Enum bufferFormat,
+ QT3DSU32 width, QT3DSU32 height)
+ {
+ NVRenderRenderBuffer *retval =
+ NVRenderRenderBuffer::Create(*this, bufferFormat, width, height);
+ if (retval != NULL)
+ m_RenderBufferToImpMap.insert(make_pair(retval->GetImplementationHandle(), retval));
+ return retval;
+ }
+
+ NVRenderRenderBuffer *NVRenderContextImpl::GetRenderBuffer(const void *implementationHandle)
+ {
+ const nvhash_map<const void *, NVRenderRenderBuffer *>::iterator entry =
+ m_RenderBufferToImpMap.find(implementationHandle);
+ if (entry != m_RenderBufferToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::RenderBufferDestroyed(NVRenderRenderBuffer &buffer)
+ {
+ m_RenderBufferToImpMap.erase(buffer.GetImplementationHandle());
+ }
+
+ NVRenderFrameBuffer *NVRenderContextImpl::CreateFrameBuffer()
+ {
+ NVRenderFrameBuffer *retval = NVRenderFrameBuffer::Create(*this);
+ if (retval != NULL)
+ m_FrameBufferToImpMap.insert(make_pair(retval->GetImplementationHandle(), retval));
+ return retval;
+ }
+
+ NVRenderFrameBuffer *NVRenderContextImpl::GetFrameBuffer(const void *implementationHandle)
+ {
+ const nvhash_map<const void *, NVRenderFrameBuffer *>::iterator entry =
+ m_FrameBufferToImpMap.find(implementationHandle);
+ if (entry != m_FrameBufferToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::FrameBufferDestroyed(NVRenderFrameBuffer &fb)
+ {
+ m_FrameBufferToImpMap.erase(fb.GetImplementationHandle());
+ if (m_HardwarePropertyContext.m_FrameBuffer == &fb)
+ m_HardwarePropertyContext.m_FrameBuffer = NULL;
+ }
+
+ NVRenderAttribLayout *
+ NVRenderContextImpl::CreateAttributeLayout(NVConstDataRef<NVRenderVertexBufferEntry> attribs)
+ {
+ return QT3DS_NEW(GetFoundation().getAllocator(), NVRenderAttribLayout)(*this, attribs);
+ }
+
+ NVRenderInputAssembler *NVRenderContextImpl::CreateInputAssembler(
+ NVRenderAttribLayout *attribLayout, NVConstDataRef<NVRenderVertexBuffer *> buffers,
+ const NVRenderIndexBuffer *indexBuffer, NVConstDataRef<QT3DSU32> strides,
+ NVConstDataRef<QT3DSU32> offsets, NVRenderDrawMode::Enum primType, QT3DSU32 patchVertexCount)
+ {
+ return QT3DS_NEW(GetFoundation().getAllocator(),
+ NVRenderInputAssembler)(*this, attribLayout, buffers, indexBuffer, strides,
+ offsets, primType, patchVertexCount);
+ }
+
+ void NVRenderContextImpl::SetInputAssembler(NVRenderInputAssembler *inputAssembler)
+ {
+ if (m_HardwarePropertyContext.m_InputAssembler != inputAssembler) {
+ DoSetInputAssembler(inputAssembler);
+ }
+ }
+
+ NVRenderVertFragCompilationResult NVRenderContextImpl::CompileSource(
+ const char *shaderName, NVConstDataRef<QT3DSI8> vertShader, NVConstDataRef<QT3DSI8> fragShader,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource,
+ NVConstDataRef<QT3DSI8> tessEvaluationShaderSource, NVConstDataRef<QT3DSI8> geometryShaderSource,
+ bool separateProgram, NVRenderShaderProgramBinaryType::Enum type, bool binaryProgram)
+ {
+ NVRenderVertFragCompilationResult result = NVRenderShaderProgram::Create(
+ *this, shaderName, vertShader, fragShader, tessControlShaderSource,
+ tessEvaluationShaderSource, geometryShaderSource, separateProgram, type, binaryProgram);
+
+ if (result.mShader != NULL)
+ m_ShaderToImpMap.insert(
+ make_pair(result.mShader->GetShaderProgramHandle(), result.mShader));
+
+ return result;
+ }
+
+ NVRenderVertFragCompilationResult NVRenderContextImpl::CompileBinary(
+ const char *shaderName, NVRenderShaderProgramBinaryType::Enum type,
+ NVDataRef<QT3DSI8> vertShader, NVDataRef<QT3DSI8> fragShader,
+ NVDataRef<QT3DSI8> tessControlShaderSource, NVDataRef<QT3DSI8> tessEvaluationShaderSource,
+ NVConstDataRef<QT3DSI8> geometryShaderSource)
+ {
+#ifndef _MACOSX
+ NVRenderVertFragCompilationResult result = NVRenderShaderProgram::Create(
+ *this, shaderName, vertShader, fragShader, tessControlShaderSource,
+ tessEvaluationShaderSource, geometryShaderSource, false, type, true);
+
+ if (result.mShader != NULL)
+ m_ShaderToImpMap.insert(
+ make_pair(result.mShader->GetShaderProgramHandle(), result.mShader));
+
+ return result;
+#else
+ QT3DS_ASSERT(false);
+ return NVRenderVertFragCompilationResult();
+#endif
+ }
+
+ NVRenderVertFragCompilationResult
+ NVRenderContextImpl::CompileComputeSource(const char *shaderName,
+ NVConstDataRef<QT3DSI8> computeShaderSource)
+ {
+ NVRenderVertFragCompilationResult result =
+ NVRenderShaderProgram::CreateCompute(*this, shaderName, computeShaderSource);
+
+ if (result.mShader != NULL)
+ m_ShaderToImpMap.insert(
+ make_pair(result.mShader->GetShaderProgramHandle(), result.mShader));
+
+ return result;
+ }
+
+ NVRenderShaderProgram *NVRenderContextImpl::GetShaderProgram(const void *implementationHandle)
+ {
+ const nvhash_map<const void *, NVRenderShaderProgram *>::iterator entry =
+ m_ShaderToImpMap.find(implementationHandle);
+ if (entry != m_ShaderToImpMap.end())
+ return entry->second;
+ return NULL;
+ }
+
+ void NVRenderContextImpl::ShaderDestroyed(NVRenderShaderProgram &shader)
+ {
+ m_ShaderToImpMap.erase(shader.GetShaderProgramHandle());
+ if (m_HardwarePropertyContext.m_ActiveShader == &shader)
+ SetActiveShader(NULL);
+ }
+
+ NVRenderProgramPipeline *NVRenderContextImpl::CreateProgramPipeline()
+ {
+ return QT3DS_NEW(GetFoundation().getAllocator(), NVRenderProgramPipeline)(*this,
+ GetFoundation());
+ }
+
+ NVRenderPathSpecification *NVRenderContextImpl::CreatePathSpecification()
+ {
+ return NVRenderPathSpecification::CreatePathSpecification(*this);
+ }
+
+ NVRenderPathRender *NVRenderContextImpl::CreatePathRender(size_t range)
+ {
+ return NVRenderPathRender::Create(*this, range);
+ }
+
+ void NVRenderContextImpl::SetPathProjectionMatrix(const QT3DSMat44 inPathProjection)
+ {
+ m_backend->SetPathProjectionMatrix(inPathProjection);
+ }
+
+ void NVRenderContextImpl::SetPathModelViewMatrix(const QT3DSMat44 inPathModelview)
+ {
+ m_backend->SetPathModelViewMatrix(inPathModelview);
+ }
+
+ void NVRenderContextImpl::SetPathStencilDepthOffset(QT3DSF32 inSlope, QT3DSF32 inBias)
+ {
+ m_backend->SetPathStencilDepthOffset(inSlope, inBias);
+ }
+ void NVRenderContextImpl::SetPathCoverDepthFunc(NVRenderBoolOp::Enum inFunc)
+ {
+ m_backend->SetPathCoverDepthFunc(inFunc);
+ }
+
+ NVRenderPathFontSpecification *
+ NVRenderContextImpl::CreatePathFontSpecification(CRegisteredString fontName)
+ {
+ // first check if it already exists
+ nvhash_map<CRegisteredString, NVRenderPathFontSpecification *>::const_iterator entry =
+ m_PathFontSpecToImpMap.find(fontName);
+ if (entry != m_PathFontSpecToImpMap.end())
+ return entry->second;
+
+ // if not create new one
+ NVRenderPathFontSpecification *pPathFontSpec =
+ NVRenderPathFontSpecification::CreatePathFontSpecification(*this, fontName);
+
+ if (pPathFontSpec)
+ m_PathFontSpecToImpMap.insert(make_pair(fontName, pPathFontSpec));
+
+ return pPathFontSpec;
+ }
+
+ void
+ NVRenderContextImpl::ReleasePathFontSpecification(NVRenderPathFontSpecification &inPathSpec)
+ {
+ m_PathFontSpecToImpMap.erase(inPathSpec.GetFontName());
+ }
+
+ NVRenderPathFontItem *NVRenderContextImpl::CreatePathFontItem()
+ {
+ // if not create new one
+ return NVRenderPathFontItem::CreatePathFontItem(*this);
+ }
+
+ void NVRenderContextImpl::SetClearColor(QT3DSVec4 inClearColor)
+ {
+ if (m_HardwarePropertyContext.m_ClearColor != inClearColor)
+ DoSetClearColor(inClearColor);
+ }
+
+ void NVRenderContextImpl::SetBlendFunction(NVRenderBlendFunctionArgument inFunctions)
+ {
+ if (memcmp(&inFunctions, &m_HardwarePropertyContext.m_BlendFunction,
+ sizeof(NVRenderBlendFunctionArgument))) {
+ DoSetBlendFunction(inFunctions);
+ }
+ }
+
+ void NVRenderContextImpl::SetBlendEquation(NVRenderBlendEquationArgument inEquations)
+ {
+ if (memcmp(&inEquations, &m_HardwarePropertyContext.m_BlendEquation,
+ sizeof(NVRenderBlendEquationArgument))) {
+ DoSetBlendEquation(inEquations);
+ }
+ }
+
+ void NVRenderContextImpl::SetCullingEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_CullingEnabled) {
+ DoSetCullingEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetDepthFunction(qt3ds::render::NVRenderBoolOp::Enum inFunction)
+ {
+ if (inFunction != m_HardwarePropertyContext.m_DepthFunction) {
+ DoSetDepthFunction(inFunction);
+ }
+ }
+
+ void NVRenderContextImpl::SetBlendingEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_BlendingEnabled) {
+ DoSetBlendingEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetColorWritesEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_ColorWritesEnabled) {
+ DoSetColorWritesEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetDepthWriteEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_DepthWriteEnabled) {
+ m_HardwarePropertyContext.m_DepthWriteEnabled = inEnabled;
+ m_backend->SetRenderState(inEnabled, NVRenderState::DepthWrite);
+ }
+ }
+
+ void NVRenderContextImpl::SetDepthTestEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_DepthTestEnabled) {
+ DoSetDepthTestEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetMultisampleEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_MultisampleEnabled) {
+ DoSetMultisampleEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetStencilTestEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_StencilTestEnabled) {
+ DoSetStencilTestEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetScissorTestEnabled(bool inEnabled)
+ {
+ if (inEnabled != m_HardwarePropertyContext.m_ScissorTestEnabled) {
+ DoSetScissorTestEnabled(inEnabled);
+ }
+ }
+
+ void NVRenderContextImpl::SetScissorRect(NVRenderRect inRect)
+ {
+ if (memcmp(&inRect, &m_HardwarePropertyContext.m_ScissorRect, sizeof(NVRenderRect))) {
+ DoSetScissorRect(inRect);
+ }
+ }
+
+ void NVRenderContextImpl::SetViewport(NVRenderRect inViewport)
+ {
+ if (memcmp(&inViewport, &m_HardwarePropertyContext.m_Viewport, sizeof(NVRenderRect))) {
+ DoSetViewport(inViewport);
+ }
+ }
+
+ void NVRenderContextImpl::SetActiveShader(NVRenderShaderProgram *inShader)
+ {
+ if (inShader != m_HardwarePropertyContext.m_ActiveShader)
+ DoSetActiveShader(inShader);
+ }
+
+ void NVRenderContextImpl::SetActiveProgramPipeline(NVRenderProgramPipeline *inProgramPipeline)
+ {
+ if (inProgramPipeline != m_HardwarePropertyContext.m_ActiveProgramPipeline)
+ DoSetActiveProgramPipeline(inProgramPipeline);
+ }
+
+ void NVRenderContextImpl::DispatchCompute(NVRenderShaderProgram *inShader, QT3DSU32 numGroupsX,
+ QT3DSU32 numGroupsY, QT3DSU32 numGroupsZ)
+ {
+ QT3DS_ASSERT(inShader);
+
+ if (inShader != m_HardwarePropertyContext.m_ActiveShader)
+ DoSetActiveShader(inShader);
+
+ m_backend->DispatchCompute(inShader->GetShaderProgramHandle(), numGroupsX, numGroupsY,
+ numGroupsZ);
+
+ OnPostDraw();
+ }
+
+ void NVRenderContextImpl::SetDrawBuffers(NVConstDataRef<QT3DSI32> inDrawBufferSet)
+ {
+ m_backend->SetDrawBuffers(
+ (m_HardwarePropertyContext.m_FrameBuffer)
+ ? m_HardwarePropertyContext.m_FrameBuffer->GetFrameBuffertHandle()
+ : NULL,
+ inDrawBufferSet);
+ }
+
+ void NVRenderContextImpl::SetReadBuffer(NVReadFaces::Enum inReadFace)
+ {
+ // currently NULL which means the read target must be set with setReadTarget
+ m_backend->SetReadBuffer(NULL, inReadFace);
+ }
+
+ void NVRenderContextImpl::ReadPixels(NVRenderRect inRect,
+ NVRenderReadPixelFormats::Enum inFormat,
+ NVDataRef<QT3DSU8> inWriteBuffer)
+ {
+ // NULL means read from current render target
+ m_backend->ReadPixel(NULL, inRect.m_X, inRect.m_Y, inRect.m_Width, inRect.m_Height,
+ inFormat, (void *)inWriteBuffer.begin());
+ }
+
+ void NVRenderContextImpl::SetRenderTarget(NVRenderFrameBuffer *inBuffer)
+ {
+ if (inBuffer != m_HardwarePropertyContext.m_FrameBuffer) {
+ DoSetRenderTarget(inBuffer);
+ }
+ }
+
+ void NVRenderContextImpl::SetReadTarget(NVRenderFrameBuffer *inBuffer)
+ {
+ if (inBuffer != m_HardwarePropertyContext.m_FrameBuffer) {
+ DoSetReadTarget(inBuffer);
+ }
+ }
+
+ void NVRenderContextImpl::ResetBlendState()
+ {
+ QT3DSI32_4 values;
+
+ m_backend->SetRenderState(m_HardwarePropertyContext.m_BlendingEnabled,
+ NVRenderState::Blend);
+ const NVRenderBlendFunctionArgument &theBlendArg(m_HardwarePropertyContext.m_BlendFunction);
+ m_backend->SetBlendFunc(theBlendArg);
+ }
+
+ // Pop the entire set of properties, potentially forcing the values
+ // to opengl.
+ void NVRenderContextImpl::PopPropertySet(bool inForceSetProperties)
+ {
+ if (!m_PropertyStack.empty()) {
+ SNVGLHardPropertyContext &theTopContext(m_PropertyStack.back());
+ if (inForceSetProperties) {
+#define HANDLE_CONTEXT_HARDWARE_PROPERTY(setterName, propName) \
+ DoSet##setterName(theTopContext.m_##propName);
+
+ ITERATE_HARDWARE_CONTEXT_PROPERTIES
+
+#undef HANDLE_CONTEXT_HARDWARE_PROPERTY
+ } else {
+#define HANDLE_CONTEXT_HARDWARE_PROPERTY(setterName, propName) \
+ Set##setterName(theTopContext.m_##propName);
+
+ ITERATE_HARDWARE_CONTEXT_PROPERTIES
+
+#undef HANDLE_CONTEXT_HARDWARE_PROPERTY
+ }
+ m_PropertyStack.pop_back();
+ }
+ }
+
+ void NVRenderContextImpl::Clear(NVRenderClearFlags flags)
+ {
+ if ((flags & NVRenderClearValues::Depth)
+ && m_HardwarePropertyContext.m_DepthWriteEnabled == false) {
+ QT3DS_ASSERT(false);
+ SetDepthWriteEnabled(true);
+ }
+ m_backend->Clear(flags);
+ }
+
+ void NVRenderContextImpl::Clear(NVRenderFrameBuffer &fb, NVRenderClearFlags flags)
+ {
+ NVRenderFrameBuffer *previous = m_HardwarePropertyContext.m_FrameBuffer;
+ if (previous != &fb)
+ SetRenderTarget(&fb);
+
+ Clear(flags);
+
+ if (previous != &fb)
+ SetRenderTarget(previous);
+ }
+
+ void NVRenderContextImpl::BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter)
+ {
+ m_backend->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, flags,
+ filter);
+ }
+
+ bool
+ NVRenderContextImpl::BindShaderToInputAssembler(const NVRenderInputAssembler *inputAssembler,
+ NVRenderShaderProgram *shader)
+ {
+ // setup the input assembler object
+ return m_backend->SetInputAssembler(inputAssembler->GetInputAssemblerHandle(),
+ shader->GetShaderProgramHandle());
+ }
+
+ bool NVRenderContextImpl::ApplyPreDrawProperties()
+ {
+ // Get the currently bound vertex and shader
+ NVRenderInputAssembler *inputAssembler = this->m_HardwarePropertyContext.m_InputAssembler;
+ NVRenderShaderProgram *shader = this->m_HardwarePropertyContext.m_ActiveShader;
+
+ // we could render through a program pipline
+ if (shader == NULL && this->m_HardwarePropertyContext.m_ActiveProgramPipeline)
+ shader = this->m_HardwarePropertyContext.m_ActiveProgramPipeline->GetVertexStage();
+
+ if (inputAssembler == NULL || shader == NULL) {
+ qCCritical(INVALID_OPERATION,
+ "Attempting to render no valid shader or input assembler setup");
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ return BindShaderToInputAssembler(inputAssembler, shader);
+ }
+
+ void NVRenderContextImpl::OnPostDraw()
+ {
+ // reset input assembler binding
+ m_backend->SetInputAssembler(NULL, 0);
+ // Texture unit 0 is used for setting up and loading textures.
+ // Bugs happen if we load a texture then setup the sampler.
+ // Then we load another texture. Because when loading we use texture unit 0,
+ // the render bindings for the first texture are blown away.
+ // Again, for this reason, texture unit 0 is reserved for loading textures.
+ m_NextTextureUnit = 1;
+ m_NextConstantBufferUnit = 0;
+ }
+
+ void NVRenderContextImpl::Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset)
+ {
+ if (!ApplyPreDrawProperties())
+ return;
+
+ NVRenderIndexBuffer *theIndexBuffer = const_cast<NVRenderIndexBuffer *>(
+ m_HardwarePropertyContext.m_InputAssembler->GetIndexBuffer());
+ if (theIndexBuffer == NULL)
+ m_backend->Draw(drawMode, offset, count);
+ else
+ theIndexBuffer->Draw(drawMode, count, offset);
+
+ OnPostDraw();
+ }
+
+ void NVRenderContextImpl::DrawIndirect(NVRenderDrawMode::Enum drawMode, QT3DSU32 offset)
+ {
+ if (!ApplyPreDrawProperties())
+ return;
+
+ NVRenderIndexBuffer *theIndexBuffer = const_cast<NVRenderIndexBuffer *>(
+ m_HardwarePropertyContext.m_InputAssembler->GetIndexBuffer());
+ if (theIndexBuffer == NULL)
+ m_backend->DrawIndirect(drawMode, (const void *)offset);
+ else
+ theIndexBuffer->DrawIndirect(drawMode, offset);
+
+ OnPostDraw();
+ }
+
+ QT3DSMat44
+ NVRenderContext::ApplyVirtualViewportToProjectionMatrix(const QT3DSMat44 &inProjection,
+ const NVRenderRectF &inViewport,
+ const NVRenderRectF &inVirtualViewport)
+ {
+ if (inVirtualViewport == inViewport)
+ return inProjection;
+ // Run conversion to floating point once.
+ NVRenderRectF theVirtualViewport(inVirtualViewport);
+ NVRenderRectF theViewport(inViewport);
+ if (theVirtualViewport.m_Width == 0 || theVirtualViewport.m_Height == 0
+ || theViewport.m_Width == 0 || theViewport.m_Height == 0) {
+ QT3DS_ASSERT(false);
+ return inProjection;
+ }
+ QT3DSMat44 theScaleTransMat(QT3DSMat44::createIdentity());
+ QT3DSF32 theHeightDiff = theViewport.m_Height - theVirtualViewport.m_Height;
+ QT3DSF32 theViewportOffY = theVirtualViewport.m_Y - theViewport.m_Y;
+ QT3DSVec2 theCameraOffsets = QT3DSVec2(theVirtualViewport.m_Width - theViewport.m_Width
+ + (theVirtualViewport.m_X - theViewport.m_X) * 2.0f,
+ theHeightDiff + (theViewportOffY - theHeightDiff) * 2.0f);
+ QT3DSVec2 theCameraScale = QT3DSVec2(theVirtualViewport.m_Width / theViewport.m_Width,
+ theVirtualViewport.m_Height / theViewport.m_Height);
+
+ QT3DSVec3 theTranslation(theCameraOffsets.x / theViewport.m_Width,
+ theCameraOffsets.y / theViewport.m_Height, 0);
+ theScaleTransMat.column3[0] = theTranslation.x;
+ theScaleTransMat.column3[1] = theTranslation.y;
+ theScaleTransMat.column0[0] = theCameraScale.x;
+ theScaleTransMat.column1[1] = theCameraScale.y;
+
+ return theScaleTransMat * inProjection;
+ }
+
+ NVRenderVertFragCompilationResult NVRenderContext::CompileSource(
+ const char *shaderName, const char *vertShader, QT3DSU32 inVertLen, const char *fragShader,
+ QT3DSU32 inFragLen, const char *tessControlShaderSource, QT3DSU32 inTCLen,
+ const char *tessEvaluationShaderSource, QT3DSU32 inTELen, const char *geometryShaderSource,
+ QT3DSU32 inGSLen, bool separableProgram)
+ {
+ return CompileSource(
+ shaderName, NVConstDataRef<QT3DSI8>((const QT3DSI8 *)vertShader, inVertLen),
+ NVConstDataRef<QT3DSI8>((const QT3DSI8 *)fragShader, inFragLen),
+ NVConstDataRef<QT3DSI8>((const QT3DSI8 *)tessControlShaderSource, inTCLen),
+ NVConstDataRef<QT3DSI8>((const QT3DSI8 *)tessEvaluationShaderSource, inTELen),
+ NVConstDataRef<QT3DSI8>((const QT3DSI8 *)geometryShaderSource, inGSLen), separableProgram);
+ }
+
+ void NVRenderContextImpl::DoSetActiveShader(NVRenderShaderProgram *inShader)
+ {
+ m_HardwarePropertyContext.m_ActiveShader = NULL;
+ if (inShader)
+ m_backend->SetActiveProgram(inShader->GetShaderProgramHandle());
+ else {
+ m_backend->SetActiveProgram(NULL);
+ }
+ m_HardwarePropertyContext.m_ActiveShader = inShader;
+ }
+
+ void NVRenderContextImpl::DoSetActiveProgramPipeline(NVRenderProgramPipeline *inProgramPipeline)
+ {
+ if (inProgramPipeline) {
+ // invalid any bound shader
+ DoSetActiveShader(NULL);
+ inProgramPipeline->Bind();
+ } else
+ m_backend->SetActiveProgramPipeline(NULL);
+
+ m_HardwarePropertyContext.m_ActiveProgramPipeline = inProgramPipeline;
+ }
+
+ NVRenderContext &NVRenderContext::CreateNULL(NVFoundationBase &foundation,
+ IStringTable &inStringTable)
+ {
+ NVRenderContext *retval = NULL;
+
+ // create backend
+ NVScopedRefCounted<IStringTable> theStringTable(inStringTable);
+ NVScopedRefCounted<NVRenderBackend> theBackend =
+ NVRenderBackendNULL::CreateBackend(foundation);
+ retval = QT3DS_NEW(foundation.getAllocator(), NVRenderContextImpl)(foundation, *theBackend,
+ *theStringTable);
+ return *retval;
+ }
+}
+} // end namespace
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDataBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDataBuffer.cpp
new file mode 100644
index 00000000..b00b0af0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDataBuffer.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderDataBuffer.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSFoundation.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderDataBuffer::NVRenderDataBuffer(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ size_t size, NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_UsageType(usageType)
+ , m_BindFlags(bindFlags)
+ , m_BufferData(data)
+ , m_BufferCapacity(data.size())
+ , m_BufferSize(size)
+ , m_OwnsData(false)
+ , m_Mapped(false)
+ {
+ m_BufferHandle =
+ m_Backend->CreateBuffer(size, bindFlags, usageType, (const void *)m_BufferData.begin());
+ }
+
+ NVRenderDataBuffer::~NVRenderDataBuffer()
+ {
+ if (m_BufferHandle) {
+ m_Backend->ReleaseBuffer(m_BufferHandle);
+ }
+ m_BufferHandle = 0;
+
+ releaseMemory();
+ }
+
+ void NVRenderDataBuffer::releaseMemory()
+ {
+ // chekc if we should release memory
+ if (m_BufferData.size() && m_OwnsData) {
+ m_Foundation.getAllocator().deallocate(m_BufferData.begin());
+ }
+
+ m_BufferData = NVDataRef<QT3DSU8>();
+ m_OwnsData = false;
+ }
+
+ NVDataRef<QT3DSU8> NVRenderDataBuffer::MapBuffer()
+ {
+ // don't map twice
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to map a mapped buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ QT3DSU8 *pData = (QT3DSU8 *)m_Backend->MapBuffer(
+ m_BufferHandle, m_BindFlags, 0, m_BufferSize,
+ NVRenderBufferAccessFlags(NVRenderBufferAccessTypeValues::Read
+ | NVRenderBufferAccessTypeValues::Write));
+
+ releaseMemory();
+ m_BufferData = toDataRef(const_cast<QT3DSU8 *>(pData), (QT3DSU32)m_BufferSize);
+ m_BufferCapacity = (QT3DSU32)m_BufferSize;
+ m_OwnsData = false;
+
+ // currently we return a reference to the system memory
+ m_Mapped = true;
+ return m_BufferData;
+ }
+
+ NVDataRef<QT3DSU8> NVRenderDataBuffer::MapBufferRange(size_t offset, size_t size,
+ NVRenderBufferAccessFlags flags)
+ {
+ // don't map twice
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to map a mapped buffer");
+ QT3DS_ASSERT(false);
+ }
+ // don't map out of range
+ if ((m_BufferSize < (offset + size)) || (size == 0)) {
+ qCCritical(INVALID_OPERATION, "Attempting to map out of buffer range");
+ QT3DS_ASSERT(false);
+ }
+
+ QT3DSU8 *pData =
+ (QT3DSU8 *)m_Backend->MapBuffer(m_BufferHandle, m_BindFlags, offset, size, flags);
+
+ releaseMemory();
+ m_BufferData = toDataRef(const_cast<QT3DSU8 *>(pData), (QT3DSU32)size);
+ m_BufferCapacity = (QT3DSU32)size;
+ m_OwnsData = false;
+
+ // currently we return a reference to the system memory
+ m_Mapped = true;
+ return m_BufferData;
+ }
+
+ void NVRenderDataBuffer::UnmapBuffer()
+ {
+ if (m_Mapped) {
+ // update hardware
+ m_Backend->UnmapBuffer(m_BufferHandle, m_BindFlags);
+ m_Mapped = false;
+ releaseMemory();
+ }
+ }
+
+ void NVRenderDataBuffer::UpdateBuffer(NVConstDataRef<QT3DSU8> data, bool ownsMemory)
+ {
+ // don't update a mapped buffer
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to update a mapped buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ releaseMemory();
+
+ m_BufferData = toDataRef(const_cast<QT3DSU8 *>(data.begin()), data.size());
+ m_BufferCapacity = data.mSize;
+ m_OwnsData = ownsMemory;
+ // update hardware
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, m_BufferCapacity, m_UsageType,
+ (const void *)m_BufferData.begin());
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDepthStencilState.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDepthStencilState.cpp
new file mode 100644
index 00000000..3ea47e23
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDepthStencilState.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderDepthStencilState.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderDepthStencilState::NVRenderDepthStencilState(
+ NVRenderContextImpl &context, NVFoundationBase &fnd, bool enableDepth, bool depthMask,
+ NVRenderBoolOp::Enum depthFunc, bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_DepthEnabled(enableDepth)
+ , m_DepthMask(depthMask)
+ , m_DepthFunc(depthFunc)
+ , m_StencilEnabled(enableStencil)
+ , m_StencilFuncFront(stencilFuncFront)
+ , m_StencilFuncBack(stencilFuncBack)
+ , m_DepthStencilOpFront(depthStencilOpFront)
+ , m_DepthStencilOpBack(depthStencilOpBack)
+ {
+ // create backend handle
+ m_StateHandle = m_Backend->CreateDepthStencilState(
+ enableDepth, depthMask, depthFunc, enableStencil, stencilFuncFront, stencilFuncBack,
+ depthStencilOpFront, depthStencilOpBack);
+ }
+
+ NVRenderDepthStencilState::~NVRenderDepthStencilState()
+ {
+ if (m_StateHandle) {
+ m_Context.StateDestroyed(*this);
+ m_Backend->ReleaseDepthStencilState(m_StateHandle);
+ }
+ }
+
+ NVRenderDepthStencilState *
+ NVRenderDepthStencilState::Create(NVRenderContextImpl &context, bool enableDepth,
+ bool depthMask, NVRenderBoolOp::Enum depthFunc,
+ bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack)
+ {
+ return QT3DS_NEW(context.GetFoundation().getAllocator(), NVRenderDepthStencilState)(
+ context, context.GetFoundation(), enableDepth, depthMask, depthFunc, enableStencil,
+ stencilFuncFront, stencilFuncBack, depthStencilOpFront, depthStencilOpBack);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDrawIndirectBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDrawIndirectBuffer.cpp
new file mode 100644
index 00000000..9940003f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderDrawIndirectBuffer.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderDrawIndirectBuffer.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderDrawIndirectBuffer::NVRenderDrawIndirectBuffer(NVRenderContextImpl &context,
+ size_t size,
+ NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data)
+ : NVRenderDataBuffer(context, context.GetFoundation(), size,
+ NVRenderBufferBindValues::Draw_Indirect, usageType, data)
+ , m_Dirty(true)
+ {
+ }
+
+ NVRenderDrawIndirectBuffer::~NVRenderDrawIndirectBuffer() { m_Context.BufferDestroyed(*this); }
+
+ void NVRenderDrawIndirectBuffer::Bind()
+ {
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to Bind a locked buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ m_Backend->BindBuffer(m_BufferHandle, m_BindFlags);
+ }
+
+ void NVRenderDrawIndirectBuffer::Update()
+ {
+ // we only update the buffer if it is dirty and we actually have some data
+ if (m_Dirty && m_BufferData.size()) {
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, m_BufferData.size(), m_UsageType,
+ m_BufferData.begin());
+ m_Dirty = false;
+ }
+ }
+
+ void NVRenderDrawIndirectBuffer::UpdateData(QT3DSI32 offset, NVDataRef<QT3DSU8> data)
+ {
+ // we only update the buffer if we something
+ if (data.size())
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, data.size(), m_UsageType,
+ data.begin() + offset);
+ }
+
+ NVRenderDrawIndirectBuffer *
+ NVRenderDrawIndirectBuffer::Create(NVRenderContextImpl &context,
+ NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVFoundationBase &fnd(context.GetFoundation());
+ NVRenderDrawIndirectBuffer *retval = NULL;
+
+ // these are the context flags which do not support this drawing mode
+ NVRenderContextType noDrawIndirectSupported(
+ NVRenderContextValues::GL2 | NVRenderContextValues::GLES2 | NVRenderContextValues::GL3
+ | NVRenderContextValues::GLES3);
+ NVRenderContextType ctxType = context.GetRenderContextType();
+
+ if (!(ctxType & noDrawIndirectSupported)) {
+ QT3DSU32 bufSize = sizeof(NVRenderDrawIndirectBuffer);
+ QT3DSU8 *newMem = (QT3DSU8 *)QT3DS_ALLOC(fnd.getAllocator(), bufSize, "DrawIndirectBuffer");
+ retval = new (newMem) NVRenderDrawIndirectBuffer(
+ context, size, usageType,
+ toDataRef(const_cast<QT3DSU8 *>(bufferData.begin()), bufferData.size()));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFragmentShader.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFragmentShader.cpp
new file mode 100644
index 00000000..e2f31f1b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFragmentShader.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderFragmentShader.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderFragmentShader::NVRenderFragmentShader(NVRenderContextImpl &context,
+ NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram)
+ : NVRenderShader(context, fnd, source, binaryProgram)
+ , m_ShaderHandle(NULL)
+ {
+ m_ShaderHandle = m_Backend->CreateFragmentShader(source, m_ErrorMessage, binaryProgram);
+ }
+
+ NVRenderFragmentShader::~NVRenderFragmentShader()
+ {
+ if (m_ShaderHandle) {
+ m_Backend->ReleaseFragmentShader(m_ShaderHandle);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFrameBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFrameBuffer.cpp
new file mode 100644
index 00000000..26114841
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderFrameBuffer.cpp
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderFrameBuffer::NVRenderFrameBuffer(NVRenderContextImpl &context, NVFoundationBase &fnd)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_BufferHandle(NULL)
+ , m_AttachmentBits(0)
+ {
+ m_BufferHandle = m_Backend->CreateRenderTarget();
+ QT3DS_ASSERT(m_BufferHandle);
+ }
+
+ NVRenderFrameBuffer::~NVRenderFrameBuffer()
+ {
+ m_Context.FrameBufferDestroyed(*this);
+ m_Backend->ReleaseRenderTarget(m_BufferHandle);
+ m_BufferHandle = 0;
+ m_AttachmentBits = 0;
+
+ // release attachments
+ UICBASE_FOREACH(idx, (QT3DSU32)NVRenderFrameBufferAttachments::LastAttachment)
+ {
+ if ((NVRenderFrameBufferAttachments::Enum)idx
+ != NVRenderFrameBufferAttachments::DepthStencil
+ || m_Context.IsDepthStencilSupported())
+ releaseAttachment((NVRenderFrameBufferAttachments::Enum)idx);
+ }
+ }
+
+ inline void CheckAttachment(NVRenderContext &ctx,
+ NVRenderFrameBufferAttachments::Enum attachment)
+ {
+#ifdef _DEBUG
+ QT3DS_ASSERT(attachment != NVRenderFrameBufferAttachments::DepthStencil
+ || ctx.IsDepthStencilSupported());
+#endif
+ (void)ctx;
+ (void)attachment;
+ }
+
+ NVRenderTextureTargetType::Enum
+ NVRenderFrameBuffer::releaseAttachment(NVRenderFrameBufferAttachments::Enum idx)
+ {
+ NVRenderTextureTargetType::Enum target = NVRenderTextureTargetType::Unknown;
+
+ NVRenderTextureOrRenderBuffer Attach = m_Attachments[idx];
+ if (Attach.HasTexture2D()) {
+ target = (Attach.GetTexture2D()->IsMultisampleTexture())
+ ? NVRenderTextureTargetType::Texture2D_MS
+ : NVRenderTextureTargetType::Texture2D;
+ Attach.GetTexture2D()->release();
+ } else if (Attach.HasTexture2DArray()) {
+ target = (Attach.GetTexture2DArray()->IsMultisampleTexture())
+ ? NVRenderTextureTargetType::Texture2D_MS
+ : NVRenderTextureTargetType::Texture2D_Array;
+ Attach.GetTexture2DArray()->release();
+ } else if (Attach.HasTextureCube()) {
+ target = (Attach.GetTextureCube()->IsMultisampleTexture())
+ ? NVRenderTextureTargetType::Texture2D_MS
+ : NVRenderTextureTargetType::TextureCube;
+ Attach.GetTextureCube()->release();
+ } else if (Attach.HasRenderBuffer())
+ Attach.GetRenderBuffer()->release();
+
+ CheckAttachment(m_Context, idx);
+ m_Attachments[idx] = NVRenderTextureOrRenderBuffer();
+
+ m_AttachmentBits &= ~(1 << idx);
+
+ return target;
+ }
+
+ NVRenderTextureOrRenderBuffer
+ NVRenderFrameBuffer::GetAttachment(NVRenderFrameBufferAttachments::Enum attachment)
+ {
+ if (attachment == NVRenderFrameBufferAttachments::Unknown
+ || attachment > NVRenderFrameBufferAttachments::LastAttachment) {
+ qCCritical(INVALID_PARAMETER, "Attachment out of range");
+ return NVRenderTextureOrRenderBuffer();
+ }
+ CheckAttachment(m_Context, attachment);
+ return m_Attachments[attachment];
+ }
+
+ void NVRenderFrameBuffer::Attach(NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderTextureOrRenderBuffer buffer,
+ NVRenderTextureTargetType::Enum target)
+ {
+ if (attachment == NVRenderFrameBufferAttachments::Unknown
+ || attachment > NVRenderFrameBufferAttachments::LastAttachment) {
+ qCCritical(INVALID_PARAMETER, "Attachment out of range");
+ return;
+ }
+
+ // early out
+ // if there is nothing to detach
+ if (!buffer.HasTexture2D() && !buffer.HasRenderBuffer() && !buffer.HasTexture2DArray()
+ && !(m_AttachmentBits & (1 << attachment)))
+ return;
+
+ CheckAttachment(m_Context, attachment);
+ // Ensure we are the bound framebuffer
+ m_Context.SetRenderTarget(this);
+
+ // release previous attachments
+ NVRenderTextureTargetType::Enum theRelTarget = releaseAttachment(attachment);
+
+ if (buffer.HasTexture2D()) {
+ // On the same attachment point there could be a something attached with a different
+ // target MSAA <--> NoMSAA
+ if (theRelTarget != NVRenderTextureTargetType::Unknown && theRelTarget != target)
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ NVRenderBackend::NVRenderBackendTextureObject(NULL),
+ theRelTarget);
+
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ buffer.GetTexture2D()->GetTextureObjectHandle(), target);
+ buffer.GetTexture2D()->addRef();
+ m_AttachmentBits |= (1 << attachment);
+ } else if (buffer.HasTexture2DArray()) {
+ // On the same attachment point there could be a something attached with a different
+ // target MSAA <--> NoMSAA
+ if (theRelTarget != NVRenderTextureTargetType::Unknown && theRelTarget != target)
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ NVRenderBackend::NVRenderBackendTextureObject(NULL),
+ theRelTarget);
+
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ buffer.GetTexture2D()->GetTextureObjectHandle(), target);
+ buffer.GetTexture2DArray()->addRef();
+ m_AttachmentBits |= (1 << attachment);
+ } else if (buffer.HasRenderBuffer()) {
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ buffer.GetRenderBuffer()->GetRenderBuffertHandle());
+ buffer.GetRenderBuffer()->addRef();
+ m_AttachmentBits |= (1 << attachment);
+ } else if (theRelTarget == NVRenderTextureTargetType::Unknown) {
+ // detach renderbuffer
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ NVRenderBackend::NVRenderBackendRenderbufferObject(NULL));
+ } else {
+ // detach texture
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ NVRenderBackend::NVRenderBackendTextureObject(NULL),
+ theRelTarget);
+ }
+ m_Attachments[attachment] = buffer;
+ }
+
+ void NVRenderFrameBuffer::AttachLayer(NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderTextureOrRenderBuffer buffer, QT3DSI32 layer,
+ QT3DSI32 level)
+ {
+ if (attachment == NVRenderFrameBufferAttachments::Unknown
+ || attachment > NVRenderFrameBufferAttachments::LastAttachment) {
+ qCCritical(INVALID_PARAMETER, "Attachment out of range");
+ return;
+ }
+
+ // This function is only used for attaching a layer
+ // If texture exists probably something is wrong
+ if (!buffer.HasTexture2DArray()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ CheckAttachment(m_Context, attachment);
+ // Ensure we are the bound framebuffer
+ m_Context.SetRenderTarget(this);
+
+ // release previous attachments
+ NVRenderTextureTargetType::Enum theRelTarget = releaseAttachment(attachment);
+
+ // On the same attachment point there could be a something attached with a different target
+ // MSAA <--> NoMSAA
+ if (theRelTarget != NVRenderTextureTargetType::Unknown
+ && theRelTarget != NVRenderTextureTargetType::Texture2D_Array)
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ NVRenderBackend::NVRenderBackendTextureObject(NULL),
+ theRelTarget);
+
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ buffer.GetTexture2DArray()->GetTextureObjectHandle(), level,
+ layer);
+ buffer.GetTexture2DArray()->addRef();
+ m_AttachmentBits |= (1 << attachment);
+
+ m_Attachments[attachment] = buffer;
+ }
+
+ void NVRenderFrameBuffer::AttachFace(NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderTextureOrRenderBuffer buffer,
+ NVRenderTextureCubeFaces::Enum face)
+ {
+ if (attachment == NVRenderFrameBufferAttachments::Unknown
+ || attachment > NVRenderFrameBufferAttachments::LastAttachment) {
+ qCCritical(INVALID_PARAMETER, "Attachment out of range");
+ return;
+ }
+
+ if (face == NVRenderTextureCubeFaces::InvalidFace) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ CheckAttachment(m_Context, attachment);
+ // Ensure we are the bound framebuffer
+ m_Context.SetRenderTarget(this);
+
+ // release previous attachments
+ NVRenderTextureTargetType::Enum attachTarget = static_cast<NVRenderTextureTargetType::Enum>(
+ (int)NVRenderTextureTargetType::TextureCube + (int)face);
+ NVRenderTextureTargetType::Enum theRelTarget = releaseAttachment(attachment);
+
+ // If buffer has no texture cube, this call is used to detach faces.
+ // If release target is not cube, there is something else attached to that
+ // attachment point, so we want to release that first. E.g (MSAA <--> NoMSAA)
+ if (theRelTarget == NVRenderTextureTargetType::TextureCube && !buffer.HasTextureCube()) {
+ theRelTarget = attachTarget;
+ attachTarget = NVRenderTextureTargetType::Unknown;
+ } else if (theRelTarget == NVRenderTextureTargetType::TextureCube) {
+ theRelTarget = NVRenderTextureTargetType::Unknown;
+ }
+ if (theRelTarget != NVRenderTextureTargetType::Unknown) {
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ NVRenderBackend::NVRenderBackendTextureObject(NULL),
+ theRelTarget);
+ }
+
+ if (attachTarget != NVRenderTextureTargetType::Unknown) {
+ m_Backend->RenderTargetAttach(m_BufferHandle, attachment,
+ buffer.GetTextureCube()->GetTextureObjectHandle(),
+ attachTarget);
+ buffer.GetTextureCube()->addRef();
+ m_AttachmentBits |= (1 << attachment);
+ }
+
+ m_Attachments[attachment] = buffer;
+ }
+
+ bool NVRenderFrameBuffer::IsComplete()
+ {
+ // Ensure we are the bound framebuffer
+ m_Context.SetRenderTarget(this);
+
+ return m_Backend->RenderTargetIsValid(m_BufferHandle);
+ }
+}
+}
+
+qt3ds::render::NVRenderFrameBuffer *
+qt3ds::render::NVRenderFrameBuffer::Create(NVRenderContextImpl &context)
+{
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderFrameBuffer)(context, context.GetFoundation());
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderGeometryShader.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderGeometryShader.cpp
new file mode 100644
index 00000000..50567287
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderGeometryShader.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderGeometryShader.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderGeometryShader::NVRenderGeometryShader(NVRenderContextImpl &context,
+ NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram)
+ : NVRenderShader(context, fnd, source, binaryProgram)
+ , m_ShaderHandle(NULL)
+ {
+ m_ShaderHandle = m_Backend->CreateGeometryShader(source, m_ErrorMessage, binaryProgram);
+ }
+
+ NVRenderGeometryShader::~NVRenderGeometryShader()
+ {
+ if (m_ShaderHandle) {
+ m_Backend->ReleaseGeometryShader(m_ShaderHandle);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderImageTexture.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderImageTexture.cpp
new file mode 100644
index 00000000..e987cc31
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderImageTexture.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderImageTexture.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderImage2D::NVRenderImage2D(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_Texture2D(inTexture)
+ , m_TextureUnit(QT3DS_MAX_U32)
+ , m_AccessType(inAccess)
+ , m_TextureLevel(0)
+ {
+ inTexture->addRef();
+ }
+
+ NVRenderImage2D::~NVRenderImage2D()
+ {
+ m_Context.ImageDestroyed(*this);
+ m_Texture2D->release();
+ }
+
+ void NVRenderImage2D::SetTextureLevel(QT3DSI32 inLevel)
+ {
+ if (m_Texture2D && m_Texture2D->GetNumMipmaps() >= (QT3DSU32)inLevel) {
+ m_TextureLevel = inLevel;
+ }
+ }
+
+ void NVRenderImage2D::Bind(QT3DSU32 unit)
+ {
+ if (unit == -1)
+ m_TextureUnit = m_Context.GetNextTextureUnit();
+ else
+ m_TextureUnit = unit;
+
+ STextureDetails theDetails(m_Texture2D->GetTextureDetails());
+
+ // note it is the callers responsibility that the texture format is supported by the compute
+ // shader
+ m_Backend->BindImageTexture(m_Texture2D->GetTextureObjectHandle(), m_TextureUnit,
+ m_TextureLevel, false, 0, m_AccessType, theDetails.m_Format);
+ }
+
+ NVRenderBackend::NVRenderBackendTextureObject NVRenderImage2D::GetTextureObjectHandle()
+ {
+ return m_Texture2D->GetTextureObjectHandle();
+ }
+
+ NVRenderImage2D *NVRenderImage2D::Create(NVRenderContextImpl &context,
+ NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess)
+ {
+ if (inTexture)
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderImage2D)(context, context.GetFoundation(), inTexture, inAccess);
+ else
+ return NULL;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderIndexBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderIndexBuffer.cpp
new file mode 100644
index 00000000..37f56bd2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderIndexBuffer.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/StringTable.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderIndexBuffer::NVRenderIndexBuffer(NVRenderContextImpl &context, size_t size,
+ NVRenderComponentTypes::Enum componentType,
+ NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data)
+ : NVRenderDataBuffer(context, context.GetFoundation(), size,
+ NVRenderBufferBindValues::Index, usageType, data)
+ , m_ComponentType(componentType)
+ {
+ }
+
+ NVRenderIndexBuffer::~NVRenderIndexBuffer() { m_Context.BufferDestroyed(*this); }
+
+ QT3DSU32 NVRenderIndexBuffer::GetNumIndices() const
+ {
+ QT3DSU32 dtypeSize = NVRenderComponentTypes::getSizeofType(m_ComponentType);
+ return m_BufferCapacity / dtypeSize;
+ }
+
+ void NVRenderIndexBuffer::Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset)
+ {
+ m_Backend->DrawIndexed(
+ drawMode, count, m_ComponentType,
+ (const void *)(offset * NVRenderComponentTypes::getSizeofType(m_ComponentType)));
+ }
+
+ void NVRenderIndexBuffer::DrawIndirect(NVRenderDrawMode::Enum drawMode, QT3DSU32 offset)
+ {
+ m_Backend->DrawIndexedIndirect(drawMode, m_ComponentType, (const void *)offset);
+ }
+
+ void NVRenderIndexBuffer::Bind()
+ {
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to Bind a locked buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ m_Backend->BindBuffer(m_BufferHandle, m_BindFlags);
+ }
+
+ NVRenderIndexBuffer *NVRenderIndexBuffer::Create(NVRenderContextImpl &context,
+ NVRenderBufferUsageType::Enum usageType,
+ NVRenderComponentTypes::Enum componentType,
+ size_t size, NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVFoundationBase &fnd(context.GetFoundation());
+ if (componentType != NVRenderComponentTypes::QT3DSU32
+ && componentType != NVRenderComponentTypes::QT3DSU16
+ && componentType != NVRenderComponentTypes::QT3DSU8) {
+ qCCritical(INVALID_PARAMETER, "Invalid component type for index buffer");
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ QT3DSU32 ibufSize = sizeof(NVRenderIndexBuffer);
+ QT3DSU8 *baseMem = (QT3DSU8 *)QT3DS_ALLOC(fnd.getAllocator(), ibufSize, "IndexBuffer");
+ NVRenderIndexBuffer *retval = new (baseMem) NVRenderIndexBuffer(
+ context, size, componentType, usageType,
+ toDataRef(const_cast<QT3DSU8 *>(bufferData.begin()), bufferData.size()));
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderInputAssembler.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderInputAssembler.cpp
new file mode 100644
index 00000000..cd804cbf
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderInputAssembler.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderInputAssembler.h"
+#include "render/Qt3DSRenderAttribLayout.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ ///< constructor
+ NVRenderInputAssembler::NVRenderInputAssembler(
+ NVRenderContextImpl &context, NVRenderAttribLayout *attribLayout,
+ NVConstDataRef<NVRenderVertexBuffer *> buffers, const NVRenderIndexBuffer *indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets,
+ NVRenderDrawMode::Enum primType, QT3DSU32 patchVertexCount)
+ : m_Context(context)
+ , m_Foundation(context.GetFoundation())
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_AttribLayout(attribLayout)
+ , m_VertexBuffers(context.GetAllocator(), "m_VertexBuffers")
+ , m_IndexBuffer(indexBuffer)
+ , m_PrimitiveType(primType)
+ , m_PatchVertexCount(patchVertexCount)
+ {
+ // we cannot currently attach more than 16 vertex buffers
+ QT3DS_ASSERT(buffers.size() < 16);
+ // if primitive is "Patch" we need a patch per vertex count > 0
+ QT3DS_ASSERT(m_PrimitiveType != NVRenderDrawMode::Patches || m_PatchVertexCount > 1);
+
+ QT3DSU32 entrySize = sizeof(NVRenderBackend::NVRenderBackendBufferObject) * buffers.size();
+ NVRenderBackend::NVRenderBackendBufferObject *bufferHandle =
+ (NVRenderBackend::NVRenderBackendBufferObject *)QT3DS_ALLOC(
+ m_Foundation.getAllocator(), entrySize, "NVRenderInputAssembler");
+ // setup vertex buffer backend handle array
+ UICBASE_FOREACH(idx, buffers.size())
+ {
+ m_VertexBuffers.push_back(buffers.mData[idx]);
+ bufferHandle[idx] = buffers.mData[idx]->GetBuffertHandle();
+ };
+
+ m_VertexbufferHandles = toConstDataRef(bufferHandle, buffers.size());
+
+ m_InputAssemblertHandle = m_Backend->CreateInputAssembler(
+ m_AttribLayout->GetAttribLayoutHandle(), m_VertexbufferHandles,
+ (m_IndexBuffer) ? m_IndexBuffer->GetBuffertHandle() : NULL, strides, offsets,
+ patchVertexCount);
+
+ attribLayout->addRef();
+ }
+
+ ///< destructor
+ NVRenderInputAssembler::~NVRenderInputAssembler()
+ {
+ m_AttribLayout->release();
+
+ if (m_InputAssemblertHandle) {
+ m_Backend->ReleaseInputAssembler(m_InputAssemblertHandle);
+ }
+
+ QT3DS_FREE(m_Foundation.getAllocator(), (void *)m_VertexbufferHandles.mData);
+ }
+
+ QT3DSU32 NVRenderInputAssembler::GetIndexCount() const
+ {
+ return (m_IndexBuffer) ? m_IndexBuffer->GetNumIndices() : 0;
+ }
+
+ QT3DSU32 NVRenderInputAssembler::GetVertexCount() const
+ {
+ // makes only sense if we have a single vertex buffer
+ QT3DS_ASSERT(m_VertexBuffers.size() == 1);
+
+ return m_VertexBuffers[0]->GetNumVertexes();
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderOcclusionQuery.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderOcclusionQuery.cpp
new file mode 100644
index 00000000..d1b62d4c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderOcclusionQuery.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderOcclusionQuery.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/StringTable.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderOcclusionQuery::NVRenderOcclusionQuery(NVRenderContextImpl &context,
+ NVFoundationBase &fnd)
+ : NVRenderQueryBase(context, fnd)
+ {
+ }
+
+ NVRenderOcclusionQuery::~NVRenderOcclusionQuery() {}
+
+ void NVRenderOcclusionQuery::Begin()
+ {
+ m_Backend->BeginQuery(m_QueryHandle, NVRenderQueryType::Samples);
+ }
+
+ void NVRenderOcclusionQuery::End()
+ {
+ m_Backend->EndQuery(m_QueryHandle, NVRenderQueryType::Samples);
+ }
+
+ void NVRenderOcclusionQuery::GetResult(QT3DSU32 *params)
+ {
+ m_Backend->GetQueryResult(m_QueryHandle, NVRenderQueryResultType::Result, params);
+ }
+
+ bool NVRenderOcclusionQuery::GetResultAvailable()
+ {
+ QT3DSU32 param;
+
+ m_Backend->GetQueryResult(m_QueryHandle, NVRenderQueryResultType::ResultAvailable, &param);
+
+ return (param == 1);
+ }
+
+ NVRenderOcclusionQuery *NVRenderOcclusionQuery::Create(NVRenderContextImpl &context)
+ {
+ if (!context.IsSampleQuerySupported())
+ return NULL;
+
+ NVRenderOcclusionQuery *retval =
+ QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderOcclusionQuery)(context, context.GetFoundation());
+
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontSpecification.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontSpecification.cpp
new file mode 100644
index 00000000..3e9276aa
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontSpecification.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderPathFontSpecification.h"
+#include "render/Qt3DSRenderPathFontText.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderPathFontSpecification::NVRenderPathFontSpecification(NVRenderContextImpl &context,
+ NVFoundationBase &fnd,
+ CRegisteredString fontName)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , m_Backend(context.GetBackend())
+ , mRefCount(0)
+ , m_NumFontGlyphs(0)
+ , m_EmScale(2048) // 2048 is default true type scale
+ , m_Type(NVRenderPathFormatType::UByte)
+ , m_TransformType(NVRenderPathTransformType::Translate2D)
+ , m_FontName(fontName)
+ {
+ }
+
+ NVRenderPathFontSpecification::~NVRenderPathFontSpecification()
+ {
+ m_Context.ReleasePathFontSpecification(*this);
+ }
+
+ void NVRenderPathFontSpecification::LoadPathGlyphs(const char *fontName,
+ NVRenderPathFormatType::Enum type)
+ {
+ // check if we already created it
+ if (m_NumFontGlyphs)
+ return;
+
+ m_Type = type;
+
+ // create fonts based on the input
+ m_PathRenderHandle = m_Backend->LoadPathGlyphsIndexedRange(
+ NVRenderPathFontTarget::FileFont, fontName, NVRenderPathFontStyleFlags(), 0, m_EmScale,
+ &m_NumFontGlyphs);
+
+ // Fallback in case the previuos call fails
+ // This is a no-op if the previous call succeeds
+ // Note that sans is an inbuild driver font
+ if (!m_PathRenderHandle) {
+ m_PathRenderHandle = m_Backend->LoadPathGlyphsIndexedRange(
+ NVRenderPathFontTarget::SystemFont, "Arial", NVRenderPathFontStyleFlags(), 0,
+ m_EmScale, &m_NumFontGlyphs);
+ }
+
+ // we should have some glyphs
+ QT3DS_ASSERT(m_NumFontGlyphs);
+ }
+
+ void
+ NVRenderPathFontSpecification::StencilFillPathInstanced(NVRenderPathFontItem &inPathFontItem)
+ {
+ const void *glyphIDs = inPathFontItem.GetGlyphIDs();
+ const QT3DSF32 *spacing = inPathFontItem.GetSpacing();
+ if (!glyphIDs || !spacing || !inPathFontItem.GetGlyphsCount()) {
+ QT3DS_ASSERT(false || !inPathFontItem.GetGlyphsCount());
+ return;
+ }
+
+ m_Backend->StencilFillPathInstanced(m_PathRenderHandle, inPathFontItem.GetGlyphsCount(),
+ m_Type, glyphIDs, NVRenderPathFillMode::Fill, 0xFF,
+ m_TransformType, spacing);
+ }
+
+ void NVRenderPathFontSpecification::CoverFillPathInstanced(NVRenderPathFontItem &inPathFontItem)
+ {
+ const void *glyphIDs = inPathFontItem.GetGlyphIDs();
+ const QT3DSF32 *spacing = inPathFontItem.GetSpacing();
+ if (!glyphIDs || !spacing || !inPathFontItem.GetGlyphsCount()) {
+ QT3DS_ASSERT(false || !inPathFontItem.GetGlyphsCount());
+ return;
+ }
+
+ m_Backend->CoverFillPathInstanced(
+ m_PathRenderHandle, inPathFontItem.GetGlyphsCount(), m_Type, glyphIDs,
+ NVRenderPathCoverMode::BoundingBoxOfBoundingBox, m_TransformType, spacing);
+ }
+
+ QT3DSU32
+ NVRenderPathFontSpecification::getSizeofType(NVRenderPathFormatType::Enum type)
+ {
+ switch (type) {
+ case NVRenderPathFormatType::Byte:
+ return sizeof(QT3DSI8);
+ case NVRenderPathFormatType::UByte:
+ return sizeof(QT3DSU8);
+ case NVRenderPathFormatType::Bytes2:
+ return sizeof(QT3DSU16);
+ case NVRenderPathFormatType::Uint:
+ return sizeof(QT3DSU32);
+ case NVRenderPathFormatType::Utf8:
+ return sizeof(QT3DSU32);
+ default:
+ QT3DS_ASSERT(false);
+ return 1;
+ }
+ }
+
+ NVRenderPathFontSpecification *
+ NVRenderPathFontSpecification::CreatePathFontSpecification(NVRenderContextImpl &context,
+ CRegisteredString fontName)
+ {
+ QT3DS_ASSERT(context.IsPathRenderingSupported());
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderPathFontSpecification)(context, context.GetFoundation(), fontName);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontText.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontText.cpp
new file mode 100644
index 00000000..aeaad13c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathFontText.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderPathFontText.h"
+#include "render/Qt3DSRenderPathFontSpecification.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderPathRender.h"
+
+namespace qt3ds {
+namespace render {
+
+ // see NVprSDK for explanation
+ // Math from page 54-56 of "Digital Image Warping" by George Wolberg,
+ // though credited to Paul Heckert's "Fundamentals of Texture
+ // Mapping and Image Warping" 1989 Master's thesis.
+ static QT3DSMat33 mapSquareToQuad(QT3DSVec2 inSquare[4])
+ {
+ QT3DSMat33 ret;
+
+ QT3DSVec2 d1(inSquare[1] - inSquare[2]);
+ QT3DSVec2 d2(inSquare[3] - inSquare[2]);
+ QT3DSVec2 d3(inSquare[0] - inSquare[1] + inSquare[2] - inSquare[3]);
+
+ QT3DSF32 denom = d1.x * d2.y - d2.x * d1.y;
+ if (denom == 0.0) {
+ return QT3DSMat33::createIdentity();
+ }
+
+ ret[2][0] = (d3.x * d2.y - d2.x * d3.y) / denom;
+ ret[2][1] = (d1.x * d3.y - d3.x * d1.y) / denom;
+ ret[2][2] = 1.0;
+ ret[0][0] = inSquare[1].x - inSquare[0].x + ret[2][0] * inSquare[1].x;
+ ret[1][0] = inSquare[1].y - inSquare[0].y + ret[2][0] * inSquare[1].y;
+ ret[0][1] = inSquare[3].x - inSquare[0].x + ret[2][1] * inSquare[3].x;
+ ret[1][1] = inSquare[3].y - inSquare[0].y + ret[2][1] * inSquare[3].y;
+ ret[0][2] = inSquare[0].x;
+ ret[1][2] = inSquare[0].y;
+
+ return ret;
+ }
+
+ static QT3DSMat33 mapQuadToSquare(QT3DSVec2 inSquare[4])
+ {
+ return mapSquareToQuad(inSquare).getInverse();
+ }
+
+ static QT3DSMat33 mapQuadToQuad(QT3DSVec2 fromSquare[4], QT3DSVec2 toSquare[4])
+ {
+ return (mapSquareToQuad(toSquare) * mapQuadToSquare(fromSquare));
+ }
+
+ static QT3DSMat44 mapBoxToQuad(QT3DSVec4 inBox, QT3DSVec2 inSquare[4])
+ {
+ QT3DSVec2 fromSquare[4] = { QT3DSVec2(inBox.x, inBox.y), QT3DSVec2(inBox.z, inBox.y),
+ QT3DSVec2(inBox.z, inBox.w), QT3DSVec2(inBox.x, inBox.w) };
+
+ QT3DSMat33 ret = mapQuadToQuad(fromSquare, inSquare);
+
+ return QT3DSMat44(ret.column0, ret.column1, ret.column2, QT3DSVec3(0.0, 0.0, 0.0));
+ }
+
+ NVRenderPathFontItem::NVRenderPathFontItem(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ , mRefCount(0)
+ , m_NumGlyphs(0)
+ , m_GlyphIDs(NULL)
+ , m_TranslateXY(NULL)
+ {
+ }
+
+ NVRenderPathFontItem::~NVRenderPathFontItem()
+ {
+ if (m_TranslateXY)
+ QT3DS_FREE(m_Foundation.getAllocator(), m_TranslateXY);
+ if (m_GlyphIDs)
+ QT3DS_FREE(m_Foundation.getAllocator(), m_GlyphIDs);
+ }
+
+ void NVRenderPathFontItem::InitTextItem(size_t glyphCount, const QT3DSU32 *glyphIDs,
+ NVRenderPathFormatType::Enum type, QT3DSF32 *posArray,
+ QT3DSVec2 pixelBound, QT3DSVec2 logicalBound, QT3DSF32 emScale)
+ {
+ m_NumGlyphs = glyphCount;
+
+ // allocate glyphs array
+ if (m_GlyphIDs)
+ QT3DS_FREE(m_Foundation.getAllocator(), m_GlyphIDs);
+
+ // allocate position array
+ if (m_TranslateXY)
+ QT3DS_FREE(m_Foundation.getAllocator(), m_TranslateXY);
+
+ m_GlyphIDs = (QT3DSU32 *)QT3DS_ALLOC(m_Foundation.getAllocator(),
+ glyphCount * getSizeofType(type), "NVRenderPathFontItem");
+ m_TranslateXY =
+ (QT3DSF32 *)QT3DS_ALLOC(m_Foundation.getAllocator(), 2 * (glyphCount + 1) * sizeof(QT3DSF32),
+ "NVRenderPathFontItem");
+
+ if (!m_GlyphIDs || !m_TranslateXY)
+ return;
+
+ QT3DSU32 *pTheGlyphIDs = (QT3DSU32 *)m_GlyphIDs;
+ QT3DSU32 *pInGlyphs = (QT3DSU32 *)glyphIDs;
+
+ /// copy glyphs array
+ for (size_t i = 0; i < glyphCount; i++) {
+ pTheGlyphIDs[i] = pInGlyphs[i];
+ }
+
+ // copy position array
+ // we copy what we got from our layout system
+ if (posArray != NULL) {
+ for (size_t i = 0, k = 0; i < glyphCount * 2; i += 2, k++) {
+ m_TranslateXY[i] = posArray[i] * emScale;
+ m_TranslateXY[i + 1] = posArray[i + 1] * emScale;
+ }
+ }
+
+ // setup transform
+ QT3DSVec2 square[4] = { QT3DSVec2(0.0, 0.0), QT3DSVec2(pixelBound.x, 0.0),
+ QT3DSVec2(pixelBound.x, pixelBound.y), QT3DSVec2(0.0, pixelBound.y) };
+ QT3DSVec4 box(0.0, 0.0, logicalBound.x * emScale, logicalBound.y * emScale);
+
+ m_ModelMatrix = mapBoxToQuad(box, square);
+ }
+
+ const QT3DSMat44 NVRenderPathFontItem::GetTransform()
+ {
+ return QT3DSMat44(QT3DSVec4(m_ModelMatrix[0][0], m_ModelMatrix[1][0], 0.0, m_ModelMatrix[2][0]),
+ QT3DSVec4(m_ModelMatrix[0][1], m_ModelMatrix[1][1], 0.0, m_ModelMatrix[2][1]),
+ QT3DSVec4(0.0, 0.0, 1.0, 0.0),
+ QT3DSVec4(m_ModelMatrix[0][2], m_ModelMatrix[1][2], 0.0, m_ModelMatrix[2][2]));
+ }
+
+ QT3DSU32
+ NVRenderPathFontItem::getSizeofType(NVRenderPathFormatType::Enum type)
+ {
+ switch (type) {
+ case NVRenderPathFormatType::Byte:
+ return sizeof(QT3DSI8);
+ case NVRenderPathFormatType::UByte:
+ return sizeof(QT3DSU8);
+ case NVRenderPathFormatType::Bytes2:
+ return sizeof(QT3DSU16);
+ case NVRenderPathFormatType::Uint:
+ return sizeof(QT3DSU32);
+ case NVRenderPathFormatType::Utf8:
+ return sizeof(QT3DSU32);
+ default:
+ QT3DS_ASSERT(false);
+ return 1;
+ }
+ }
+
+ NVRenderPathFontItem *NVRenderPathFontItem::CreatePathFontItem(NVRenderContextImpl &context)
+ {
+ QT3DS_ASSERT(context.IsPathRenderingSupported());
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderPathFontItem)(context.GetFoundation());
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathRender.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathRender.cpp
new file mode 100644
index 00000000..42982498
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathRender.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderPathRender.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderPathSpecification.h"
+#include "render/Qt3DSRenderPathFontSpecification.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderPathRender::NVRenderPathRender(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ size_t range)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , m_Backend(context.GetBackend())
+ , mRefCount(0)
+ , m_StrokeWidth(0.0f)
+ {
+ m_Range = range;
+ m_PathRenderHandle = m_Backend->CreatePathNVObject(range);
+ }
+
+ NVRenderPathRender::~NVRenderPathRender()
+ {
+ if (m_PathRenderHandle) {
+ m_Backend->ReleasePathNVObject(m_PathRenderHandle, m_Range);
+ }
+ }
+
+ void NVRenderPathRender::SetPathSpecification(NVRenderPathSpecification &inCommandBuffer)
+ {
+ m_Backend->SetPathSpecification(m_PathRenderHandle, inCommandBuffer.GetPathCommands(),
+ inCommandBuffer.GetPathCoords());
+ }
+
+ NVBounds3 NVRenderPathRender::GetPathObjectBoundingBox()
+ {
+ return m_Backend->GetPathObjectBoundingBox(m_PathRenderHandle);
+ }
+
+ NVBounds3 NVRenderPathRender::GetPathObjectFillBox()
+ {
+ return m_Backend->GetPathObjectFillBox(m_PathRenderHandle);
+ }
+
+ NVBounds3 NVRenderPathRender::GetPathObjectStrokeBox()
+ {
+ return m_Backend->GetPathObjectStrokeBox(m_PathRenderHandle);
+ }
+
+ void NVRenderPathRender::SetStrokeWidth(QT3DSF32 inStrokeWidth)
+ {
+ if (inStrokeWidth != m_StrokeWidth) {
+ m_StrokeWidth = inStrokeWidth;
+ m_Backend->SetStrokeWidth(m_PathRenderHandle, inStrokeWidth);
+ }
+ }
+
+ QT3DSF32 NVRenderPathRender::GetStrokeWidth() const { return m_StrokeWidth; }
+
+ void NVRenderPathRender::StencilStroke() { m_Backend->StencilStrokePath(m_PathRenderHandle); }
+
+ void NVRenderPathRender::StencilFill() { m_Backend->StencilFillPath(m_PathRenderHandle); }
+
+ NVRenderPathRender *NVRenderPathRender::Create(NVRenderContextImpl &context, size_t range)
+ {
+ if (!context.IsPathRenderingSupported())
+ return NULL;
+
+ NVRenderPathRender *retval =
+ QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderPathRender)(context, context.GetFoundation(), range);
+
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathSpecification.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathSpecification.cpp
new file mode 100644
index 00000000..f4b26f11
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderPathSpecification.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderPathSpecification.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderPathSpecification::NVRenderPathSpecification(NVRenderContextImpl &context,
+ NVFoundationBase &fnd)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , m_Backend(context.GetBackend())
+ , mRefCount(0)
+ , m_PathCommands(fnd.getAllocator(), "m_PathCommands")
+ , m_PathCoords(fnd.getAllocator(), "m_PathCoords")
+ {
+ }
+
+ NVRenderPathSpecification::~NVRenderPathSpecification() {}
+
+ void NVRenderPathSpecification::Reset()
+ {
+ m_PathCommands.clear();
+ m_PathCoords.clear();
+ }
+
+ void NVRenderPathSpecification::P(QT3DSVec2 inData)
+ {
+ m_PathCoords.push_back(inData.x);
+ m_PathCoords.push_back(inData.y);
+ }
+
+ void NVRenderPathSpecification::MoveTo(QT3DSVec2 inPoint)
+ {
+ // we should actually query the backend for command converesion
+ // but will we support any other pather render system than nv path?
+ StaticAssert<NVRenderPathCommands::MoveTo == 0x02>::valid_expression();
+
+ m_PathCommands.push_back(NVRenderPathCommands::MoveTo);
+ P(inPoint);
+ }
+
+ void NVRenderPathSpecification::CubicCurveTo(QT3DSVec2 inC1, QT3DSVec2 inC2, QT3DSVec2 inDest)
+ {
+ // we should actually query the backend for command converesion
+ // but will we support any other pather render system than nv path?
+ StaticAssert<NVRenderPathCommands::CubicCurveTo == 0x0C>::valid_expression();
+
+ m_PathCommands.push_back(NVRenderPathCommands::CubicCurveTo);
+ P(inC1);
+ P(inC2);
+ P(inDest);
+ }
+
+ void NVRenderPathSpecification::ClosePath()
+ {
+ // we should actually query the backend for command converesion
+ // but will we support any other pather render system than nv path?
+ StaticAssert<NVRenderPathCommands::Close == 0x00>::valid_expression();
+
+ m_PathCommands.push_back(NVRenderPathCommands::Close);
+ }
+
+ NVRenderPathSpecification *
+ NVRenderPathSpecification::CreatePathSpecification(NVRenderContextImpl &context)
+ {
+ QT3DS_ASSERT(context.IsPathRenderingSupported());
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderPathSpecification)(context, context.GetFoundation());
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderProgramPipeline.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderProgramPipeline.cpp
new file mode 100644
index 00000000..b0a9f271
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderProgramPipeline.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderProgramPipeline.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderProgramPipeline::NVRenderProgramPipeline(NVRenderContextImpl &context,
+ NVFoundationBase &fnd)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , m_Backend(context.GetBackend())
+ , mRefCount(0)
+ , m_Program(NULL)
+ , m_VertexProgram(NULL)
+ , m_FragmentProgram(NULL)
+ , m_TessControlProgram(NULL)
+ , m_TessEvalProgram(NULL)
+ , m_GeometryProgram(NULL)
+ , m_ComputProgram(NULL)
+ {
+ m_ProgramPipelineHandle = m_Backend->CreateProgramPipeline();
+ }
+
+ NVRenderProgramPipeline::~NVRenderProgramPipeline()
+ {
+ if (m_ProgramPipelineHandle) {
+ m_Backend->ReleaseProgramPipeline(m_ProgramPipelineHandle);
+ }
+
+ if (m_VertexProgram)
+ m_VertexProgram->release();
+ if (m_FragmentProgram)
+ m_FragmentProgram->release();
+ if (m_TessControlProgram)
+ m_TessControlProgram->release();
+ if (m_TessEvalProgram)
+ m_TessEvalProgram->release();
+ if (m_GeometryProgram)
+ m_GeometryProgram->release();
+ }
+
+ bool NVRenderProgramPipeline::IsValid() { return (m_ProgramPipelineHandle != NULL); }
+
+ void NVRenderProgramPipeline::SetProgramStages(NVRenderShaderProgram *inProgram,
+ NVRenderShaderTypeFlags flags)
+ {
+ bool bDirty = false;
+
+ if (flags & NVRenderShaderTypeValue::Vertex && inProgram != m_VertexProgram) {
+ if (m_VertexProgram)
+ m_VertexProgram->release();
+ if (inProgram)
+ inProgram->addRef();
+ m_VertexProgram = inProgram;
+ bDirty = true;
+ }
+ if (flags & NVRenderShaderTypeValue::Fragment && inProgram != m_FragmentProgram) {
+ if (m_FragmentProgram)
+ m_FragmentProgram->release();
+ if (inProgram)
+ inProgram->addRef();
+ m_FragmentProgram = inProgram;
+ bDirty = true;
+ }
+ if (flags & NVRenderShaderTypeValue::TessControl && inProgram != m_TessControlProgram) {
+ if (m_TessControlProgram)
+ m_TessControlProgram->release();
+ if (inProgram)
+ inProgram->addRef();
+ m_TessControlProgram = inProgram;
+ bDirty = true;
+ }
+ if (flags & NVRenderShaderTypeValue::TessEvaluation && inProgram != m_TessEvalProgram) {
+ if (m_TessEvalProgram)
+ m_TessEvalProgram->release();
+ if (inProgram)
+ inProgram->addRef();
+ m_TessEvalProgram = inProgram;
+ bDirty = true;
+ }
+ if (flags & NVRenderShaderTypeValue::Geometry && inProgram != m_GeometryProgram) {
+ if (m_GeometryProgram)
+ m_GeometryProgram->release();
+ if (inProgram)
+ inProgram->addRef();
+ m_GeometryProgram = inProgram;
+ bDirty = true;
+ }
+
+ if (bDirty) {
+ m_Backend->SetProgramStages(m_ProgramPipelineHandle, flags,
+ (inProgram) ? inProgram->GetShaderProgramHandle() : NULL);
+ }
+ }
+
+ void NVRenderProgramPipeline::Bind()
+ {
+ m_Backend->SetActiveProgramPipeline(m_ProgramPipelineHandle);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderQueryBase.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderQueryBase.cpp
new file mode 100644
index 00000000..f13bc499
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderQueryBase.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderQueryBase.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSFoundation.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderQueryBase::NVRenderQueryBase(NVRenderContextImpl &context, NVFoundationBase &fnd)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ {
+ m_QueryHandle = m_Backend->CreateQuery();
+ }
+
+ NVRenderQueryBase::~NVRenderQueryBase()
+ {
+ if (m_QueryHandle)
+ m_Backend->ReleaseQuery(m_QueryHandle);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRasterizerState.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRasterizerState.cpp
new file mode 100644
index 00000000..e7daf7f4
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRasterizerState.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderRasterizerState.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderRasterizerState::NVRenderRasterizerState(NVRenderContextImpl &context,
+ NVFoundationBase &fnd, QT3DSF32 depthBias,
+ QT3DSF32 depthScale, NVRenderFaces::Enum cullFace)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ {
+ // create backend handle
+ m_StateHandle = m_Backend->CreateRasterizerState(depthBias, depthScale, cullFace);
+ }
+
+ NVRenderRasterizerState::~NVRenderRasterizerState()
+ {
+ if (m_StateHandle) {
+ m_Backend->ReleaseRasterizerState(m_StateHandle);
+ m_Context.StateDestroyed(*this);
+ }
+ }
+
+ NVRenderRasterizerState *NVRenderRasterizerState::Create(NVRenderContextImpl &context,
+ QT3DSF32 depthBias, QT3DSF32 depthScale,
+ NVRenderFaces::Enum cullFace)
+ {
+ return QT3DS_NEW(context.GetFoundation().getAllocator(), NVRenderRasterizerState)(
+ context, context.GetFoundation(), depthBias, depthScale, cullFace);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRenderBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRenderBuffer.cpp
new file mode 100644
index 00000000..b682bc1b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderRenderBuffer.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSFoundation.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderRenderBuffer::NVRenderRenderBuffer(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderRenderBufferFormats::Enum format,
+ QT3DSU32 width, QT3DSU32 height)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_Width(width)
+ , m_Height(height)
+ , m_StorageFormat(format)
+ , m_BufferHandle(NULL)
+ {
+ SetDimensions(NVRenderRenderBufferDimensions(width, height));
+ }
+
+ NVRenderRenderBuffer::~NVRenderRenderBuffer()
+ {
+ m_Context.RenderBufferDestroyed(*this);
+ m_Backend->ReleaseRenderbuffer(m_BufferHandle);
+ m_BufferHandle = 0;
+ }
+
+ void NVRenderRenderBuffer::SetDimensions(const NVRenderRenderBufferDimensions &inDimensions)
+ {
+ QT3DSU32 maxWidth, maxHeight;
+ m_Width = inDimensions.m_Width;
+ m_Height = inDimensions.m_Height;
+
+ // get max size and clamp to max value
+ m_Context.getMaxTextureSize(maxWidth, maxHeight);
+ if (m_Width > maxWidth || m_Height > maxHeight) {
+ qCCritical(INVALID_OPERATION, "Width or height is greater than max texture size (%d, %d)",
+ maxWidth, maxHeight);
+ m_Width = NVMin(m_Width, maxWidth);
+ m_Height = NVMin(m_Height, maxHeight);
+ }
+
+ bool success = true;
+
+ if (m_BufferHandle == NULL)
+ m_BufferHandle = m_Backend->CreateRenderbuffer(m_StorageFormat, m_Width, m_Height);
+ else
+ success =
+ m_Backend->ResizeRenderbuffer(m_BufferHandle, m_StorageFormat, m_Width, m_Height);
+
+ if (m_BufferHandle == NULL || !success) {
+ // We could try smaller sizes
+ QT3DS_ASSERT(false);
+ qCCritical(INTERNAL_ERROR, "Unable to create render buffer %s, %dx%d",
+ NVRenderRenderBufferFormats::toString(m_StorageFormat), m_Width,
+ m_Height);
+ }
+ }
+}
+}
+
+qt3ds::render::NVRenderRenderBuffer *
+qt3ds::render::NVRenderRenderBuffer::Create(NVRenderContextImpl &context,
+ NVRenderRenderBufferFormats::Enum format, QT3DSU32 width,
+ QT3DSU32 height)
+{
+ NVRenderRenderBuffer *retval = NULL;
+ if (width == 0 || height == 0) {
+ qCCritical(INVALID_PARAMETER, "Invalid renderbuffer width or height");
+ return retval;
+ }
+
+ retval = QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderRenderBuffer)(context, context.GetFoundation(), format, width, height);
+
+ return retval;
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSampler.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSampler.cpp
new file mode 100644
index 00000000..b02fc615
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSampler.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderSampler.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTextureSampler::NVRenderTextureSampler(
+ NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureMinifyingOp::Enum minFilter, NVRenderTextureMagnifyingOp::Enum magFilter,
+ NVRenderTextureCoordOp::Enum wrapS, NVRenderTextureCoordOp::Enum wrapT,
+ NVRenderTextureCoordOp::Enum wrapR, NVRenderTextureSwizzleMode::Enum swizzleMode,
+ QT3DSF32 minLod, QT3DSF32 maxLod, QT3DSF32 lodBias, NVRenderTextureCompareMode::Enum compareMode,
+ NVRenderTextureCompareOp::Enum compareFunc, QT3DSF32 anisotropy, QT3DSF32 *borderColor)
+ : m_MinFilter(minFilter)
+ , m_MagFilter(magFilter)
+ , m_WrapS(wrapS)
+ , m_WrapT(wrapT)
+ , m_WrapR(wrapR)
+ , m_SwizzleMode(swizzleMode)
+ , m_MinLod(minLod)
+ , m_MaxLod(maxLod)
+ , m_LodBias(lodBias)
+ , m_CompareMode(compareMode)
+ , m_CompareOp(compareFunc)
+ , m_Anisotropy(anisotropy)
+ , m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_SamplerHandle(NULL)
+ {
+ // create backend handle
+ m_SamplerHandle = m_Backend->CreateSampler();
+
+ if (borderColor) {
+ m_BorderColor[0] = borderColor[0];
+ m_BorderColor[1] = borderColor[1];
+ m_BorderColor[2] = borderColor[2];
+ m_BorderColor[3] = borderColor[3];
+ }
+ }
+
+ NVRenderTextureSampler::~NVRenderTextureSampler()
+ {
+ if (m_SamplerHandle)
+ m_Backend->ReleaseSampler(m_SamplerHandle);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderShaderProgram.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderShaderProgram.cpp
new file mode 100644
index 00000000..6adc98cd
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderShaderProgram.cpp
@@ -0,0 +1,1168 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderVertexShader.h"
+#include "render/Qt3DSRenderFragmentShader.h"
+#include "render/Qt3DSRenderTessellationShader.h"
+#include "render/Qt3DSRenderGeometryShader.h"
+#include "render/Qt3DSRenderComputeShader.h"
+#include "render/Qt3DSRenderImageTexture.h"
+
+namespace qt3ds {
+namespace render {
+
+ template <typename TDataType>
+ struct ShaderConstantApplier
+ {
+ bool force_compile_error;
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSI32>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSI32 &inValue,
+ QT3DSI32 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSI32_2>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSI32_2 &inValue,
+ QT3DSI32_2 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue.x);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSI32_3>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSI32_3 &inValue,
+ QT3DSI32_3 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue.x);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSI32_4>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSI32_4 &inValue,
+ QT3DSI32_4 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue.x);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSRenderBool>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type,
+ const QT3DSRenderBool inValue, QT3DSRenderBool &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<bool_2>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const bool_2 &inValue,
+ bool_2 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<bool_3>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const bool_3 &inValue,
+ bool_3 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<bool_4>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const bool_4 &inValue,
+ bool_4 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSF32>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSF32 &inValue,
+ QT3DSF32 &oldValue)
+ {
+ if (count > 1 || !(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSVec2>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSVec2 &inValue,
+ QT3DSVec2 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSVec3>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSVec3 &inValue,
+ QT3DSVec3 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSVec4>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSVec4 &inValue,
+ QT3DSVec4 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSU32>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSU32 &inValue,
+ QT3DSU32 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSU32_2>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSU32_2 &inValue,
+ QT3DSU32_2 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue.x);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSU32_3>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSU32_3 &inValue,
+ QT3DSU32_3 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue.x);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSU32_4>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSU32_4 &inValue,
+ QT3DSU32_4 &oldValue)
+ {
+ if (!(inValue == oldValue)) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ &inValue.x);
+ oldValue = inValue;
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSMat33>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSMat33 inValue,
+ QT3DSMat33 &, bool inTranspose)
+ {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ inValue.front(), inTranspose);
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<QT3DSMat44>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type, const QT3DSMat44 inValue,
+ QT3DSMat44 &, bool inTranspose)
+ {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ inValue.front(), inTranspose);
+ }
+
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type,
+ NVConstDataRef<QT3DSMat44> inValue, QT3DSMat44 &, bool inTranspose)
+ {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type, count,
+ reinterpret_cast<const GLfloat *>(inValue.begin()),
+ inTranspose);
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<NVRenderTexture2DPtr>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type,
+ NVRenderTexture2DPtr inValue, QT3DSU32 &oldValue)
+ {
+ if (inValue) {
+ NVRenderTexture2D *texObj = reinterpret_cast<NVRenderTexture2D *>(inValue);
+ texObj->Bind();
+ QT3DSU32 texUnit = texObj->GetTextureUnit();
+ if (texUnit != oldValue) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type,
+ count, &texUnit);
+ oldValue = texUnit;
+ }
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<NVRenderTexture2DArrayPtr>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type,
+ NVRenderTexture2DArrayPtr inValue, QT3DSU32 &oldValue)
+ {
+ if (inValue) {
+ NVRenderTexture2DArray *texObj =
+ reinterpret_cast<NVRenderTexture2DArray *>(inValue);
+ texObj->Bind();
+ QT3DSU32 texUnit = texObj->GetTextureUnit();
+ if (texUnit != oldValue) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type,
+ count, &texUnit);
+ oldValue = texUnit;
+ }
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<NVRenderTextureCubePtr>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type,
+ NVRenderTextureCubePtr inValue, QT3DSU32 &oldValue)
+ {
+ if (inValue) {
+ NVRenderTextureCube *texObj = reinterpret_cast<NVRenderTextureCube *>(inValue);
+ texObj->Bind();
+ QT3DSU32 texUnit = texObj->GetTextureUnit();
+ if (texUnit != oldValue) {
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type,
+ count, &texUnit);
+ oldValue = texUnit;
+ }
+ }
+ }
+ };
+
+ template <>
+ struct ShaderConstantApplier<NVRenderImage2DPtr>
+ {
+ void ApplyConstant(NVRenderShaderProgram *program, NVRenderBackend *backend, QT3DSI32 location,
+ QT3DSI32 count, NVRenderShaderDataTypes::Enum type,
+ NVRenderImage2DPtr inValue, QT3DSU32 &oldValue, QT3DSI32 binding)
+ {
+ if (inValue) {
+ NVRenderImage2D *imgObj = reinterpret_cast<NVRenderImage2D *>(inValue);
+ imgObj->Bind(binding);
+ QT3DSU32 texUnit = imgObj->GetTextureUnit();
+ if (texUnit != oldValue) {
+ // on ES we need a explicit binding value
+ QT3DS_ASSERT(backend->GetRenderContextType() != NVRenderContextValues::GLES3PLUS
+ || binding != -1);
+ // this is not allowed on ES 3+ for image types
+ if (backend->GetRenderContextType() != NVRenderContextValues::GLES3PLUS)
+ backend->SetConstantValue(program->GetShaderProgramHandle(), location, type,
+ count, &texUnit);
+
+ oldValue = texUnit;
+ }
+ }
+ }
+ };
+
+ NVRenderShaderProgram::NVRenderShaderProgram(NVRenderContextImpl &context,
+ NVFoundationBase &fnd, const char *programName,
+ bool separableProgram)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_ProgramName(programName)
+ , m_ProgramHandle(NULL)
+ , m_Constants(context.GetFoundation().getAllocator(), "NVRenderShaderProgram::m_Constants")
+ , m_ShaderBuffers(context.GetFoundation().getAllocator(),
+ "NVRenderShaderProgram::m_ShaderBuffers")
+ , m_ProgramType(ProgramType::Graphics)
+ {
+ m_ProgramHandle = m_Backend->CreateShaderProgram(separableProgram);
+
+ QT3DS_ASSERT(m_ProgramHandle);
+ }
+
+ NVRenderShaderProgram::~NVRenderShaderProgram()
+ {
+ m_Context.ShaderDestroyed(*this);
+
+ if (m_ProgramHandle)
+ m_Backend->ReleaseShaderProgram(m_ProgramHandle);
+
+ for (TShaderConstantMap::iterator iter = m_Constants.begin(), end = m_Constants.end();
+ iter != end; ++iter) {
+ iter->second->Release();
+ }
+
+ m_Constants.clear();
+
+ for (TShaderBufferMap::iterator iter = m_ShaderBuffers.begin(), end = m_ShaderBuffers.end();
+ iter != end; ++iter) {
+ iter->second->Release();
+ }
+
+ m_ShaderBuffers.clear();
+
+ m_ProgramHandle = NULL;
+ }
+
+ template <typename TShaderObject>
+ void NVRenderShaderProgram::Attach(TShaderObject *pShader)
+ {
+ m_Backend->AttachShader(m_ProgramHandle, pShader->GetShaderHandle());
+ }
+
+ template <typename TShaderObject>
+ void NVRenderShaderProgram::Detach(TShaderObject *pShader)
+ {
+ m_Backend->DetachShader(m_ProgramHandle, pShader->GetShaderHandle());
+ }
+
+ static NVRenderShaderConstantBase *
+ ShaderConstantFactory(NVRenderBackend *backend, CRegisteredString inName,
+ NVFoundationBase &alloc, QT3DSI32 uniLoc, QT3DSI32 elementCount,
+ NVRenderShaderDataTypes::Enum inConstantType, QT3DSI32 binding)
+ {
+ switch (inConstantType) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(nv) \
+ case NVRenderShaderDataTypes::nv: \
+ return QT3DS_NEW(alloc.getAllocator(), NVRenderShaderConstant<nv>)( \
+ backend, inName, uniLoc, elementCount, inConstantType, binding, alloc);
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ template <typename TShaderBufferType, typename TBufferDataType>
+ static NVRenderShaderBufferBase *
+ ShaderBufferFactory(NVRenderContextImpl &context, CRegisteredString inName,
+ NVFoundationBase &alloc, QT3DSI32 cbLoc, QT3DSI32 cbBinding, QT3DSI32 cbSize,
+ QT3DSI32 cbCount, TBufferDataType *pBuffer)
+ {
+ return QT3DS_NEW(alloc.getAllocator(), TShaderBufferType)(context, inName, cbLoc, cbBinding,
+ cbSize, cbCount, pBuffer, alloc);
+ }
+
+ bool NVRenderShaderProgram::Link()
+ {
+ bool success = m_Backend->LinkProgram(m_ProgramHandle, m_ErrorMessage);
+
+ if (success) {
+ char nameBuf[512];
+ QT3DSI32 location, elementCount, binding;
+ NVRenderShaderDataTypes::Enum type;
+
+ QT3DSI32 constantCount = m_Backend->GetConstantCount(m_ProgramHandle);
+
+ UICBASE_FOREACH(idx, constantCount)
+ {
+ location = m_Backend->GetConstantInfoByID(m_ProgramHandle, idx, 512, &elementCount,
+ &type, &binding, nameBuf);
+
+ if (location != -1) {
+ CRegisteredString theName(m_Context.GetStringTable().RegisterStr(nameBuf));
+
+ m_Constants.insert(eastl::make_pair(
+ theName,
+ ShaderConstantFactory(m_Backend, theName, m_Context.GetFoundation(),
+ location, elementCount, type, binding)));
+ }
+ }
+
+ // next query constant buffers info
+ QT3DSI32 length, bufferSize, paramCount;
+ QT3DSI32 constantBufferCount = m_Backend->GetConstantBufferCount(m_ProgramHandle);
+ UICBASE_FOREACH(idx, constantBufferCount)
+ {
+ location = m_Backend->GetConstantBufferInfoByID(
+ m_ProgramHandle, idx, 512, &paramCount, &bufferSize, &length, nameBuf);
+
+ if (location != -1) {
+ CRegisteredString theName(m_Context.GetStringTable().RegisterStr(nameBuf));
+
+ // find constant buffer in our DB
+ NVRenderConstantBuffer *cb = m_Context.GetConstantBuffer(theName);
+ if (cb) {
+ cb->SetupBuffer(this, location, bufferSize, paramCount);
+ cb->addRef();
+ }
+
+ m_ShaderBuffers.insert(eastl::make_pair(
+ theName,
+ ShaderBufferFactory<NVRenderShaderConstantBuffer, NVRenderConstantBuffer>(
+ m_Context, theName, m_Context.GetFoundation(), location, -1, bufferSize,
+ paramCount, cb)));
+ }
+ }
+
+ // next query storage buffers
+ QT3DSI32 storageBufferCount = m_Backend->GetStorageBufferCount(m_ProgramHandle);
+ UICBASE_FOREACH(idx, storageBufferCount)
+ {
+ location = m_Backend->GetStorageBufferInfoByID(
+ m_ProgramHandle, idx, 512, &paramCount, &bufferSize, &length, nameBuf);
+
+ if (location != -1) {
+ CRegisteredString theName(m_Context.GetStringTable().RegisterStr(nameBuf));
+
+ // find constant buffer in our DB
+ NVRenderStorageBuffer *sb = m_Context.GetStorageBuffer(theName);
+ if (sb) {
+ sb->addRef();
+ }
+
+ m_ShaderBuffers.insert(eastl::make_pair(
+ theName,
+ ShaderBufferFactory<NVRenderShaderStorageBuffer, NVRenderStorageBuffer>(
+ m_Context, theName, m_Context.GetFoundation(), location, -1, bufferSize,
+ paramCount, sb)));
+ }
+ }
+
+ // next query atomic counter buffers
+ QT3DSI32 atomicBufferCount = m_Backend->GetAtomicCounterBufferCount(m_ProgramHandle);
+ UICBASE_FOREACH(idx, atomicBufferCount)
+ {
+ location = m_Backend->GetAtomicCounterBufferInfoByID(
+ m_ProgramHandle, idx, 512, &paramCount, &bufferSize, &length, nameBuf);
+
+ if (location != -1) {
+ CRegisteredString theName(m_Context.GetStringTable().RegisterStr(nameBuf));
+
+ // find atomic counter buffer in our DB
+ // The buffer itself is not used in the program itself.
+ // Instead uniform variables are used but the interface to set the value is like
+ // for buffers.
+ // This is a bit insane but that is how it is.
+ // The theName variable contains the uniform name associated with an atomic
+ // counter buffer.
+ // We get the actual buffer name by searching for this uniform name
+ // See NVRenderTestAtomicCounterBuffer.cpp how the setup works
+ NVRenderAtomicCounterBuffer *acb =
+ m_Context.GetAtomicCounterBufferByParam(theName);
+ if (acb) {
+ acb->addRef();
+
+ m_ShaderBuffers.insert(eastl::make_pair(
+ acb->GetBufferName(),
+ ShaderBufferFactory<NVRenderShaderAtomicCounterBuffer,
+ NVRenderAtomicCounterBuffer>(
+ m_Context, acb->GetBufferName(), m_Context.GetFoundation(),
+ location, -1, bufferSize, paramCount, acb)));
+ }
+ }
+ }
+ }
+
+ return success;
+ }
+
+ void NVRenderShaderProgram::GetErrorMessage(QT3DSI32 *messageLength, const char *errorMessage)
+ {
+ *messageLength = m_ErrorMessage.size();
+ errorMessage = m_ErrorMessage.c_str();
+ }
+
+ const char *NVRenderShaderProgram::GetErrorMessage() { return m_ErrorMessage.c_str(); }
+
+ NVRenderShaderConstantBase *NVRenderShaderProgram::GetShaderConstant(const char *constantName)
+ {
+ TShaderConstantMap::iterator theIter =
+ m_Constants.find(m_Context.GetStringTable().RegisterStr(constantName));
+
+ if (theIter != m_Constants.end()) {
+ NVRenderShaderConstantBase *theConstant =
+ static_cast<NVRenderShaderConstantBase *>(theIter->second);
+ return theConstant;
+ }
+
+ return NULL;
+ }
+
+ NVRenderShaderBufferBase *NVRenderShaderProgram::GetShaderBuffer(const char *bufferName)
+ {
+ TShaderBufferMap::iterator theIter =
+ m_ShaderBuffers.find(m_Context.GetStringTable().RegisterStr(bufferName));
+
+ if (theIter != m_ShaderBuffers.end()) {
+ return theIter->second;
+ }
+
+ return NULL;
+ }
+
+ NVRenderContextImpl &NVRenderShaderProgram::GetRenderContext() { return m_Context; }
+
+ template <typename TDataType>
+ void SetConstantValueOfType(NVRenderShaderProgram *program,
+ NVRenderShaderConstantBase *inConstantBase,
+ const TDataType &inValue, const QT3DSI32 inCount)
+ {
+ if (inConstantBase == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ QT3DS_ASSERT(inConstantBase->m_ElementCount >= inCount);
+
+ if (inConstantBase->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ NVRenderShaderConstant<TDataType> *inConstant =
+ static_cast<NVRenderShaderConstant<TDataType> *>(inConstantBase);
+ ShaderConstantApplier<TDataType>().ApplyConstant(
+ program, inConstant->m_Backend, inConstant->m_Location, inCount, inConstant->m_Type,
+ inValue, inConstant->m_Value);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TDataType>
+ void SetSamplerConstantValueOfType(NVRenderShaderProgram *program,
+ NVRenderShaderConstantBase *inConstantBase,
+ const TDataType &inValue, const QT3DSI32 inCount)
+ {
+ if (inConstantBase == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ QT3DS_ASSERT(inConstantBase->m_ElementCount >= inCount);
+
+ if (inConstantBase->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ NVRenderShaderConstant<TDataType> *inConstant =
+ static_cast<NVRenderShaderConstant<TDataType> *>(inConstantBase);
+ ShaderConstantApplier<TDataType>().ApplyConstant(
+ program, inConstant->m_Backend, inConstant->m_Location, inCount, inConstant->m_Type,
+ inValue, inConstant->m_Value, inConstant->m_Binding);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TDataType>
+ void SetMatrixConstantValueOfType(NVRenderShaderProgram *program,
+ NVRenderShaderConstantBase *inConstantBase,
+ const TDataType &inValue, const QT3DSI32 inCount,
+ bool inTranspose)
+ {
+ if (inConstantBase == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ QT3DS_ASSERT(inConstantBase->m_ElementCount >= inCount);
+
+ if (inConstantBase->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ NVRenderShaderConstant<TDataType> *inConstant =
+ static_cast<NVRenderShaderConstant<TDataType> *>(inConstantBase);
+ ShaderConstantApplier<TDataType>().ApplyConstant(
+ program, inConstant->m_Backend, inConstant->m_Location, inCount, inConstant->m_Type,
+ inValue, inConstant->m_Value, inTranspose);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TDataType>
+ void SetMatrixConstantValueOfType(NVRenderShaderProgram *program,
+ NVRenderShaderConstantBase *inConstantBase,
+ const NVConstDataRef<TDataType> inValue,
+ const QT3DSI32 /*inCount*/, bool inTranspose)
+ {
+ if (inConstantBase == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ QT3DS_ASSERT(inConstantBase->m_ElementCount >= (QT3DSI32)inValue.size());
+
+ if (inConstantBase->GetShaderConstantType()
+ == NVDataTypeToShaderDataTypeMap<TDataType>::GetType()) {
+ NVRenderShaderConstant<TDataType> *inConstant =
+ static_cast<NVRenderShaderConstant<TDataType> *>(inConstantBase);
+ ShaderConstantApplier<TDataType>().ApplyConstant(
+ program, inConstant->m_Backend, inConstant->m_Location, inValue.size(),
+ inConstant->m_Type, inValue, inConstant->m_Value, inTranspose);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ QT3DSI32 inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSI32_2 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSI32_3 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSI32_4 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ QT3DSRenderBool inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const bool_2 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const bool_3 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const bool_4 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSF32 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSVec2 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSVec3 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSVec4 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSU32 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSU32_2 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSU32_3 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSU32_4 &inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSMat33 &inValue, const QT3DSI32 inCount,
+ bool inTranspose)
+ {
+ SetMatrixConstantValueOfType(this, inConstant, inValue, inCount, inTranspose);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const QT3DSMat44 &inValue, const QT3DSI32 inCount,
+ bool inTranspose)
+ {
+ SetMatrixConstantValueOfType(this, inConstant, inValue, inCount, inTranspose);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ const NVConstDataRef<QT3DSMat44> inValue,
+ const QT3DSI32 inCount)
+ {
+ SetMatrixConstantValueOfType(this, inConstant, inValue, inCount, false);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ NVRenderTexture2D *inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ NVRenderTexture2DArray *inValue,
+ const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ NVRenderTextureCube *inValue, const QT3DSI32 inCount)
+ {
+ SetConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *inConstant,
+ NVRenderImage2D *inValue, const QT3DSI32 inCount)
+ {
+ SetSamplerConstantValueOfType(this, inConstant, inValue, inCount);
+ }
+ void NVRenderShaderProgram::SetConstantValue(NVRenderShaderConstantBase *, NVRenderDataBuffer *,
+ const QT3DSI32)
+ {
+ // this is merely a dummy right now
+ }
+
+ void NVRenderShaderProgram::BindComputeInput(NVRenderDataBuffer *inBuffer, QT3DSU32 inIndex)
+ {
+ NVRenderBackend::NVRenderBackendBufferObject obj(NULL);
+ if (inBuffer)
+ obj = inBuffer->GetBuffertHandle();
+ m_Backend->ProgramSetStorageBuffer(inIndex, obj);
+ }
+
+ namespace {
+ void WriteErrorMessage(NVFoundationBase &fnd, const char *tag, const char *message)
+ {
+ Q_UNUSED(fnd)
+ eastl::string messageData(nonNull(message));
+ eastl::vector<eastl::string> lines;
+ for (eastl::string::size_type pos = messageData.find('\n'); pos != eastl::string::npos;
+ pos = messageData.find('\n')) {
+ eastl::string line = messageData.substr(0, pos);
+ messageData.erase(messageData.begin(), messageData.begin() + pos + 1);
+ if (line.size())
+ qCCritical(INVALID_OPERATION, "%s: %s", tag, line.c_str());
+ }
+ }
+ }
+
+ Option<NVRenderVertexShader *> NVRenderShaderProgram::createVertexShader(
+ NVRenderContextImpl &context, NVConstDataRef<QT3DSI8> vertexShaderSource, bool binaryProgram)
+ {
+ if (vertexShaderSource.size() == 0)
+ return Empty();
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderVertexShader(context, context.GetFoundation(), vertexShaderSource,
+ binaryProgram));
+ }
+
+ Option<NVRenderFragmentShader *> NVRenderShaderProgram::createFragmentShader(
+ NVRenderContextImpl &context, NVConstDataRef<QT3DSI8> fragmentShaderSource, bool binaryProgram)
+ {
+ if (fragmentShaderSource.size() == 0)
+ return Empty();
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderFragmentShader(context, context.GetFoundation(), fragmentShaderSource,
+ binaryProgram));
+ }
+
+ Option<NVRenderTessControlShader *>
+ NVRenderShaderProgram::createTessControlShader(NVRenderContextImpl &context,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource,
+ bool binaryProgram)
+ {
+ if (tessControlShaderSource.size() == 0)
+ return Empty();
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderTessControlShader(context, context.GetFoundation(),
+ tessControlShaderSource, binaryProgram));
+ }
+
+ Option<NVRenderTessEvaluationShader *>
+ NVRenderShaderProgram::createTessEvaluationShader(NVRenderContextImpl &context,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource,
+ bool binaryProgram)
+ {
+ if (tessControlShaderSource.size() == 0)
+ return Empty();
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderTessEvaluationShader(context, context.GetFoundation(),
+ tessControlShaderSource, binaryProgram));
+ }
+
+ Option<NVRenderGeometryShader *> NVRenderShaderProgram::createGeometryShader(
+ NVRenderContextImpl &context, NVConstDataRef<QT3DSI8> geometryShaderSource, bool binaryProgram)
+ {
+ if (geometryShaderSource.size() == 0)
+ return Empty();
+
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderGeometryShader(context, context.GetFoundation(), geometryShaderSource,
+ binaryProgram));
+ }
+
+ NVRenderVertFragCompilationResult NVRenderShaderProgram::Create(
+ NVRenderContextImpl &context, const char *programName,
+ NVConstDataRef<QT3DSI8> vertShaderSource, NVConstDataRef<QT3DSI8> fragShaderSource,
+ NVConstDataRef<QT3DSI8> tessControlShaderSource,
+ NVConstDataRef<QT3DSI8> tessEvaluationShaderSource, NVConstDataRef<QT3DSI8> geometryShaderSource,
+ bool separateProgram, NVRenderShaderProgramBinaryType::Enum type, bool binaryProgram)
+ {
+ NVRenderVertFragCompilationResult result;
+ NVRenderShaderProgram *pProgram = NULL;
+ bool bProgramIsValid = false;
+
+ result.mShaderName = programName;
+
+ // our minimum requirement is a vertex and a fragment shader or geometry shader
+ // if we should treat it as a separate program we don't care
+ if (!separateProgram
+ && (vertShaderSource.size() == 0
+ || (fragShaderSource.size() == 0 && geometryShaderSource.size() == 0))) {
+ qCCritical(INVALID_PARAMETER,
+ "Vertex or fragment (geometry) source have 0 length");
+ QT3DS_ASSERT(false);
+ return result;
+ }
+
+ if (binaryProgram && type != NVRenderShaderProgramBinaryType::NVBinary) {
+ qCCritical(INVALID_PARAMETER, "Unrecoginzed binary format");
+ QT3DS_ASSERT(false);
+ return result;
+ }
+
+ // first create and compile shader
+ Option<NVRenderVertexShader *> vtxShader =
+ createVertexShader(context, vertShaderSource, binaryProgram);
+ Option<NVRenderFragmentShader *> fragShader =
+ createFragmentShader(context, fragShaderSource, binaryProgram);
+ Option<NVRenderTessControlShader *> tcShader =
+ createTessControlShader(context, tessControlShaderSource, binaryProgram);
+ Option<NVRenderTessEvaluationShader *> teShader =
+ createTessEvaluationShader(context, tessEvaluationShaderSource, binaryProgram);
+ Option<NVRenderGeometryShader *> geShader =
+ createGeometryShader(context, geometryShaderSource, binaryProgram);
+
+ bool vertexValid = (vtxShader.hasValue()) ? vtxShader.getValue()->IsValid() : true;
+ bool fragValid = (fragShader.hasValue()) ? fragShader.getValue()->IsValid() : true;
+ bool tcValid = (tcShader.hasValue()) ? tcShader.getValue()->IsValid() : true;
+ bool teValid = (teShader.hasValue()) ? teShader.getValue()->IsValid() : true;
+ bool geValid = (geShader.hasValue()) ? geShader.getValue()->IsValid() : true;
+
+ if (vertexValid && fragValid && tcValid && teValid && geValid) {
+ // shaders were succesfuly created
+ pProgram = QT3DS_NEW(context.GetFoundation().getAllocator(), NVRenderShaderProgram)(
+ context, context.GetFoundation(), programName, separateProgram);
+
+ if (pProgram) {
+ // attach programs
+ if (vtxShader.hasValue() && vtxShader.getValue()->IsValid())
+ pProgram->Attach(vtxShader.getValue());
+ if (fragShader.hasValue() && fragShader.getValue()->IsValid())
+ pProgram->Attach(fragShader.getValue());
+ if (tcShader.hasValue() && tcShader.getValue()->IsValid())
+ pProgram->Attach(tcShader.getValue());
+ if (teShader.hasValue() && teShader.getValue()->IsValid())
+ pProgram->Attach(teShader.getValue());
+ if (geShader.hasValue() && geShader.getValue()->IsValid())
+ pProgram->Attach(geShader.getValue());
+
+ // link program
+ bProgramIsValid = pProgram->Link();
+ }
+ }
+
+ // if anything went wrong print out
+ if (!vertexValid || !fragValid || !tcValid || !teValid || !geValid || !bProgramIsValid) {
+ NVFoundationBase &foundation(context.GetFoundation());
+
+ if (!vertexValid) {
+ qCCritical(INTERNAL_ERROR, "Failed to generate vertex shader!!");
+ qCCritical(INTERNAL_ERROR, "Vertex source:\n%s",
+ nonNull((const char *)vertShaderSource.begin()));
+ WriteErrorMessage(foundation, "Vertex compilation output:",
+ vtxShader.getValue()->GetErrorMessage());
+ }
+
+ if (!fragValid) {
+ qCCritical(INTERNAL_ERROR, "Failed to generate fragment shader!!");
+ qCCritical(INTERNAL_ERROR, "Fragment source:\n%s",
+ nonNull((const char *)fragShaderSource.begin()));
+ WriteErrorMessage(foundation, "Fragment compilation output:",
+ fragShader.getValue()->GetErrorMessage());
+ }
+
+ if (!tcValid) {
+ qCCritical(INTERNAL_ERROR,
+ "Failed to generate tessellation control shader!!");
+ qCCritical(INTERNAL_ERROR, "Tessellation control source:\n%s",
+ nonNull((const char *)tessControlShaderSource.begin()));
+ WriteErrorMessage(foundation, "Tessellation control compilation output:",
+ tcShader.getValue()->GetErrorMessage());
+ }
+
+ if (!teValid) {
+ qCCritical(INTERNAL_ERROR,
+ "Failed to generate tessellation evaluation shader!!");
+ qCCritical(INTERNAL_ERROR, "Tessellation evaluation source:\n%s",
+ nonNull((const char *)tessEvaluationShaderSource.begin()));
+ WriteErrorMessage(foundation, "Tessellation evaluation compilation output:",
+ teShader.getValue()->GetErrorMessage());
+ }
+
+ if (!geValid) {
+ qCCritical(INTERNAL_ERROR, "Failed to generate geometry shader!!");
+ qCCritical(INTERNAL_ERROR, "Geometry source:\n%s",
+ nonNull((const char *)geometryShaderSource.begin()));
+ WriteErrorMessage(foundation, "Geometry compilation output:",
+ geShader.getValue()->GetErrorMessage());
+ }
+
+ if (!bProgramIsValid && pProgram) {
+ qCCritical(INTERNAL_ERROR, "Failed to link program!!");
+ WriteErrorMessage(foundation, "Program link output:", pProgram->GetErrorMessage());
+
+ // delete program
+ QT3DS_FREE(context.GetFoundation().getAllocator(), pProgram);
+ pProgram = NULL;
+ }
+ }
+
+ // clean up
+ if (vtxShader.hasValue()) {
+ if (bProgramIsValid && vtxShader.getValue()->IsValid())
+ pProgram->Detach(vtxShader.getValue());
+ QT3DS_FREE(context.GetFoundation().getAllocator(), vtxShader.getValue());
+ }
+ if (fragShader.hasValue()) {
+ if (bProgramIsValid && fragShader.getValue()->IsValid())
+ pProgram->Detach(fragShader.getValue());
+ QT3DS_FREE(context.GetFoundation().getAllocator(), fragShader.getValue());
+ }
+ if (tcShader.hasValue()) {
+ if (bProgramIsValid && tcShader.getValue()->IsValid())
+ pProgram->Detach(tcShader.getValue());
+ QT3DS_FREE(context.GetFoundation().getAllocator(), tcShader.getValue());
+ }
+ if (teShader.hasValue()) {
+ if (bProgramIsValid && teShader.getValue()->IsValid())
+ pProgram->Detach(teShader.getValue());
+ QT3DS_FREE(context.GetFoundation().getAllocator(), teShader.getValue());
+ }
+ if (geShader.hasValue()) {
+ if (bProgramIsValid && geShader.getValue()->IsValid())
+ pProgram->Detach(geShader.getValue());
+ QT3DS_FREE(context.GetFoundation().getAllocator(), geShader.getValue());
+ }
+
+ // set program
+ result.mShader = pProgram;
+
+ return result;
+ }
+
+ NVRenderVertFragCompilationResult
+ NVRenderShaderProgram::CreateCompute(NVRenderContextImpl &context, const char *programName,
+ NVConstDataRef<QT3DSI8> computeShaderSource)
+ {
+ NVRenderVertFragCompilationResult result;
+ NVRenderShaderProgram *pProgram = NULL;
+ bool bProgramIsValid = true;
+
+ result.mShaderName = programName;
+
+ // check source
+ if (computeShaderSource.size() == 0) {
+ qCCritical(INVALID_PARAMETER, "compute source has 0 length");
+ QT3DS_ASSERT(false);
+ return result;
+ }
+
+ NVRenderComputeShader computeShader(context, context.GetFoundation(), computeShaderSource,
+ false);
+
+ if (computeShader.IsValid()) {
+ // shaders were succesfuly created
+ pProgram = QT3DS_NEW(context.GetFoundation().getAllocator(), NVRenderShaderProgram)(
+ context, context.GetFoundation(), programName, false);
+
+ if (pProgram) {
+ // attach programs
+ pProgram->Attach(&computeShader);
+
+ // link program
+ bProgramIsValid = pProgram->Link();
+
+ // set program type
+ pProgram->SetProgramType(ProgramType::Compute);
+ }
+ }
+
+ // if anything went wrong print out
+ if (!computeShader.IsValid() || !bProgramIsValid) {
+ NVFoundationBase &foundation(context.GetFoundation());
+
+ if (!computeShader.IsValid()) {
+ qCCritical(INTERNAL_ERROR, "Failed to generate compute shader!!");
+ qCCritical(INTERNAL_ERROR, "Vertex source:\n%s",
+ nonNull((const char *)computeShaderSource.begin()));
+ WriteErrorMessage(foundation, "Compute shader compilation output:",
+ computeShader.GetErrorMessage());
+ }
+ }
+
+ // set program
+ result.mShader = pProgram;
+
+ return result;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderStorageBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderStorageBuffer.cpp
new file mode 100644
index 00000000..6dd269a0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderStorageBuffer.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderStorageBuffer.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderStorageBuffer::NVRenderStorageBuffer(NVRenderContextImpl &context,
+ CRegisteredString bufferName, size_t size,
+ NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data, NVRenderDataBuffer *pBuffer)
+ : NVRenderDataBuffer(context, context.GetFoundation(), size,
+ NVRenderBufferBindValues::Storage, usageType, data)
+ , m_Name(bufferName)
+ , m_WrappedBuffer(pBuffer)
+ , m_Dirty(true)
+ {
+ QT3DS_ASSERT(context.IsStorageBufferSupported());
+
+ if (pBuffer)
+ pBuffer->addRef();
+ }
+
+ NVRenderStorageBuffer::~NVRenderStorageBuffer()
+ {
+ if (m_WrappedBuffer)
+ m_WrappedBuffer->release();
+
+ m_Context.BufferDestroyed(*this);
+ }
+
+ void NVRenderStorageBuffer::Bind()
+ {
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to Bind a locked buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ if (m_WrappedBuffer)
+ m_WrappedBuffer->Bind();
+ else
+ m_Backend->BindBuffer(m_BufferHandle, m_BindFlags);
+ }
+
+ void NVRenderStorageBuffer::BindToShaderProgram(QT3DSU32 index)
+ {
+ m_Backend->ProgramSetStorageBuffer(
+ index, (m_WrappedBuffer) ? m_WrappedBuffer->GetBuffertHandle() : m_BufferHandle);
+ }
+
+ void NVRenderStorageBuffer::Update()
+ {
+ // we only update the buffer if it is dirty and we actually have some data
+ if (m_Dirty && m_BufferData.size()) {
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, m_BufferData.size(), m_UsageType,
+ m_BufferData.begin());
+ m_Dirty = false;
+ }
+ }
+
+ void NVRenderStorageBuffer::UpdateData(QT3DSI32 offset, NVDataRef<QT3DSU8> data)
+ {
+ // we only update the buffer if it is not just a wrapper
+ if (!m_WrappedBuffer)
+ m_Backend->UpdateBuffer(m_BufferHandle, m_BindFlags, data.size(), m_UsageType,
+ data.begin() + offset);
+ }
+
+ NVRenderStorageBuffer *
+ NVRenderStorageBuffer::Create(NVRenderContextImpl &context, const char *bufferName,
+ NVRenderBufferUsageType::Enum usageType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData, NVRenderDataBuffer *pBuffer)
+ {
+ NVFoundationBase &fnd(context.GetFoundation());
+ NVRenderStorageBuffer *retval = NULL;
+
+ if (context.IsStorageBufferSupported()) {
+ CRegisteredString theBufferName(context.GetStringTable().RegisterStr(bufferName));
+ QT3DSU32 cbufSize = sizeof(NVRenderStorageBuffer);
+ QT3DSU8 *newMem = (QT3DSU8 *)QT3DS_ALLOC(fnd.getAllocator(), cbufSize, "StorageBuffer");
+ retval = new (newMem) NVRenderStorageBuffer(
+ context, theBufferName, size, usageType,
+ toDataRef(const_cast<QT3DSU8 *>(bufferData.begin()), bufferData.size()), pBuffer);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSync.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSync.cpp
new file mode 100644
index 00000000..02d153a6
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderSync.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderSync.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSFoundation.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderSync::NVRenderSync(NVRenderContextImpl &context, NVFoundationBase &fnd)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_SyncHandle(NULL)
+ {
+ }
+
+ NVRenderSync::~NVRenderSync()
+ {
+ if (m_SyncHandle)
+ m_Backend->ReleaseSync(m_SyncHandle);
+ }
+
+ void NVRenderSync::Sync()
+ {
+ // On every sync call we need to create a new sync object
+ // A sync object can only be used once
+
+ // First delete the old object
+ // We can safely do this because it is actually not deleted until
+ // it is unused
+ if (m_SyncHandle)
+ m_Backend->ReleaseSync(m_SyncHandle);
+
+ m_SyncHandle =
+ m_Backend->CreateSync(NVRenderSyncType::GpuCommandsComplete, NVRenderSyncFlags());
+ }
+
+ void NVRenderSync::Wait()
+ {
+ // wait until the sync object is signaled or a timeout happens
+ if (m_SyncHandle)
+ m_Backend->WaitSync(m_SyncHandle, NVRenderCommandFlushFlags(), 0);
+ }
+
+ NVRenderSync *NVRenderSync::Create(NVRenderContextImpl &context)
+ {
+ if (!context.IsCommandSyncSupported())
+ return NULL;
+
+ NVRenderSync *retval = QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderSync)(context, context.GetFoundation());
+
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTessellationShader.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTessellationShader.cpp
new file mode 100644
index 00000000..7a0fd897
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTessellationShader.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderTessellationShader.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTessControlShader::NVRenderTessControlShader(NVRenderContextImpl &context,
+ NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source,
+ bool binaryProgram)
+ : NVRenderShader(context, fnd, source, binaryProgram)
+ , m_ShaderHandle(NULL)
+ {
+ m_ShaderHandle = m_Backend->CreateTessControlShader(source, m_ErrorMessage, binaryProgram);
+ }
+
+ NVRenderTessControlShader::~NVRenderTessControlShader()
+ {
+ if (m_ShaderHandle) {
+ m_Backend->ReleaseTessControlShader(m_ShaderHandle);
+ }
+ }
+
+ NVRenderTessEvaluationShader::NVRenderTessEvaluationShader(NVRenderContextImpl &context,
+ NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source,
+ bool binaryProgram)
+ : NVRenderShader(context, fnd, source, binaryProgram)
+ , m_ShaderHandle(NULL)
+ {
+ m_ShaderHandle =
+ m_Backend->CreateTessEvaluationShader(source, m_ErrorMessage, binaryProgram);
+ }
+
+ NVRenderTessEvaluationShader::~NVRenderTessEvaluationShader()
+ {
+ if (m_ShaderHandle) {
+ m_Backend->ReleaseTessEvaluationShader(m_ShaderHandle);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2D.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2D.cpp
new file mode 100644
index 00000000..0fe61e6c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2D.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderSampler.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTexture2D::NVRenderTexture2D(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget)
+ : NVRenderTextureBase(context, fnd, texTarget)
+ , m_Width(0)
+ , m_Height(0)
+ {
+ }
+
+ NVRenderTexture2D::~NVRenderTexture2D() { m_Context.TextureDestroyed(*this); }
+
+ STextureDetails NVRenderTexture2D::GetTextureDetails() const
+ {
+ return STextureDetails(m_Width, m_Height, 0, m_SampleCount, m_Format);
+ }
+
+ void NVRenderTexture2D::SetTextureData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel, QT3DSU32 width,
+ QT3DSU32 height, NVRenderTextureFormats::Enum format,
+ NVRenderTextureFormats::Enum formatDest)
+ {
+ QT3DS_ASSERT(m_TextureHandle);
+
+ // check if we should compress this texture
+
+ if (inMipLevel == 0) {
+ m_Width = width;
+ m_Height = height;
+ m_Format = format;
+
+ // We re-use textures and this might have been a MSAA texture before
+ // for resue we must completely destroy the texture object and create a new one
+ // The same is true for immutable textures
+ if (m_TexTarget == NVRenderTextureTargetType::Texture2D_MS || m_Immutable) {
+ m_Backend->ReleaseTexture(m_TextureHandle);
+ m_TexTarget = NVRenderTextureTargetType::Texture2D;
+ m_SampleCount = 1;
+ m_TextureHandle = m_Backend->CreateTexture();
+ }
+
+ if (NVRenderTextureFormats::isCompressedTextureFormat(formatDest)) {
+ bool compress = NVRenderTextureFormats::isUncompressedTextureFormat(format);
+ bool appropriateSizes = ((width % 4) || (height % 4)) == false;
+
+ // we only compress multiple of 4 textures
+ if (compress && !appropriateSizes)
+ compress = false;
+
+ if (compress) {
+ // This seems like a very dubious line here. If we are compressing then the
+ // image
+ // is really 1/4 the width and height? - CN
+ m_Width = width / 4;
+ m_Height = height / 4;
+ m_Format = formatDest;
+ }
+ } else if (NVRenderTextureFormats::isUncompressedTextureFormat(formatDest)) {
+ m_Format = formatDest;
+ }
+ }
+
+ if (m_MaxMipLevel < inMipLevel) {
+ m_MaxMipLevel = inMipLevel;
+ }
+
+ // get max size and check value
+ QT3DSU32 maxWidth, maxHeight;
+ m_Context.getMaxTextureSize(maxWidth, maxHeight);
+ if (width > maxWidth || height > maxHeight) {
+ qCCritical(INVALID_OPERATION, "Width or height is greater than max texture size (%d, %d)",
+ maxWidth, maxHeight);
+ }
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(format)
+ || NVRenderTextureFormats::isDepthTextureFormat(format)) {
+ m_Backend->SetTextureData2D(m_TextureHandle, m_TexTarget, inMipLevel, m_Format, width,
+ height, 0, format, newBuffer.begin());
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(format)) {
+ m_Backend->SetCompressedTextureData2D(m_TextureHandle, m_TexTarget, inMipLevel, format,
+ width, height, 0, newBuffer.size(),
+ newBuffer.begin());
+ }
+ // Set our texture parameters to a default that will look the best
+ if (inMipLevel > 0)
+ SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
+ }
+
+ void NVRenderTexture2D::SetTextureStorage(QT3DSU32 inLevels, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum formaInternal,
+ NVRenderTextureFormats::Enum format,
+ NVDataRef<QT3DSU8> dataBuffer)
+ {
+ QT3DS_ASSERT(m_TextureHandle);
+
+ if (!m_Context.IsShaderImageLoadStoreSupported()) {
+ qCCritical(INVALID_OPERATION, "The extension Shader_Image_Load_Store is not supported");
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ m_Width = width;
+ m_Height = height;
+ m_Format = formaInternal;
+ if (format == NVRenderTextureFormats::Unknown)
+ format = formaInternal;
+
+ // get max size and check value
+ QT3DSU32 maxWidth, maxHeight;
+ m_Context.getMaxTextureSize(maxWidth, maxHeight);
+ if (width > maxWidth || height > maxHeight) {
+ qCCritical(INVALID_OPERATION, "Width or height is greater than max texture size (%d, %d)",
+ maxWidth, maxHeight);
+ }
+
+ if (inLevels < 1) {
+ qCCritical(INVALID_PARAMETER, "inLevels is less than 1 (%d)", inLevels);
+ }
+
+ m_MaxMipLevel = inLevels - 1; // we count from 0
+
+ // only uncompressed formats are supported and no depth
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(formaInternal)) {
+ m_Backend->CreateTextureStorage2D(m_TextureHandle, m_TexTarget, inLevels, formaInternal,
+ width, height);
+
+ m_Immutable = true;
+ m_TexTarget = NVRenderTextureTargetType::Texture2D;
+
+ if (dataBuffer.size() > 0)
+ m_Backend->SetTextureSubData2D(m_TextureHandle, m_TexTarget, 0, 0, 0, width, height,
+ format, dataBuffer.begin());
+
+ if (inLevels > 1)
+ SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
+ }
+ }
+
+ void NVRenderTexture2D::SetTextureDataMultisample(QT3DSU32 sampleCount, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum format)
+ {
+ QT3DS_ASSERT(m_TextureHandle);
+ QT3DS_ASSERT(m_MaxMipLevel == 0);
+
+ m_TexTarget = NVRenderTextureTargetType::Texture2D_MS;
+
+ QT3DSU32 maxWidth, maxHeight;
+ m_Context.getMaxTextureSize(maxWidth, maxHeight);
+ if (width > maxWidth || height > maxHeight) {
+ qCCritical(INVALID_OPERATION, "Width or height is greater than max texture size (%d, %d)",
+ maxWidth, maxHeight);
+ }
+
+ QT3DS_ASSERT(NVRenderTextureFormats::isUncompressedTextureFormat(format)
+ || NVRenderTextureFormats::isDepthTextureFormat(format));
+
+ m_Backend->SetMultisampledTextureData2D(m_TextureHandle, m_TexTarget, sampleCount, format,
+ width, height, true);
+
+ m_Width = width;
+ m_Height = height;
+ m_SampleCount = sampleCount;
+ m_Format = format;
+ }
+
+ void NVRenderTexture2D::SetTextureSubData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel,
+ QT3DSU32 inXOffset, QT3DSU32 inYOffset, QT3DSU32 width,
+ QT3DSU32 height, NVRenderTextureFormats::Enum format)
+ {
+ QT3DS_ASSERT(m_TextureHandle);
+
+ if (!NVRenderTextureFormats::isUncompressedTextureFormat(format)) {
+ qCCritical(INVALID_PARAMETER, "Cannot set sub data for depth or compressed formats");
+ QT3DS_ASSERT(false);
+ return;
+ }
+ QT3DSU32 subRectStride = width * NVRenderTextureFormats::getSizeofFormat(format);
+ if (newBuffer.size() < subRectStride * height) {
+ qCCritical(INVALID_PARAMETER, "Invalid sub rect buffer size");
+ QT3DS_ASSERT(false);
+ return;
+ }
+ // nop
+ if (width == 0 || height == 0)
+ return;
+
+ if (inXOffset + width > m_Width || inYOffset + height > m_Height) {
+ qCCritical(INVALID_PARAMETER, "Sub rect outside existing image bounds");
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ // not handled yet
+ QT3DS_ASSERT(!NVRenderTextureFormats::isDepthTextureFormat(format));
+
+ m_Backend->SetTextureSubData2D(m_TextureHandle, m_TexTarget, inMipLevel, inXOffset,
+ inYOffset, width, height, format, newBuffer.begin());
+ }
+
+ void NVRenderTexture2D::GenerateMipmaps(NVRenderHint::Enum genType)
+ {
+ applyTexParams();
+ m_Backend->GenerateMipMaps(m_TextureHandle, m_TexTarget, genType);
+ QT3DSU32 maxDim = (m_Width >= m_Height) ? m_Width : m_Height;
+ m_MaxMipLevel = static_cast<QT3DSU32>(logf((float)maxDim) / logf(2.0f));
+ // we never create more level than m_MaxLevel
+ m_MaxMipLevel = qt3ds::NVMin(m_MaxMipLevel, (QT3DSU32)m_MaxLevel);
+ }
+
+ void NVRenderTexture2D::Bind()
+ {
+ m_TextureUnit = m_Context.GetNextTextureUnit();
+
+ m_Backend->BindTexture(m_TextureHandle, m_TexTarget, m_TextureUnit);
+
+ applyTexParams();
+ applyTexSwizzle();
+ }
+
+ NVRenderTexture2D *NVRenderTexture2D::Create(NVRenderContextImpl &context)
+ {
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderTexture2D)(context, context.GetFoundation());
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2DArray.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2DArray.cpp
new file mode 100644
index 00000000..fc0dfa45
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTexture2DArray.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderSampler.h"
+#include "render/Qt3DSRenderTexture2DArray.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTexture2DArray::NVRenderTexture2DArray(NVRenderContextImpl &context,
+ NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget)
+ : NVRenderTextureBase(context, fnd, texTarget)
+ , m_Width(0)
+ , m_Height(0)
+ , m_Slices(0)
+ {
+ }
+
+ NVRenderTexture2DArray::~NVRenderTexture2DArray() { m_Context.TextureDestroyed(*this); }
+
+ void NVRenderTexture2DArray::SetTextureData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel,
+ QT3DSU32 width, QT3DSU32 height, QT3DSU32 slices,
+ NVRenderTextureFormats::Enum format)
+ {
+ QT3DS_ASSERT(m_TextureHandle);
+
+ if (inMipLevel == 0) {
+ m_Width = width;
+ m_Height = height;
+ m_Slices = slices;
+ m_Format = format;
+ m_MaxMipLevel = inMipLevel;
+ }
+
+ if (m_MaxMipLevel < inMipLevel) {
+ m_MaxMipLevel = inMipLevel;
+ }
+
+ // get max size and check value
+ QT3DSI32 theMaxLayerSize, theMaxSize;
+ m_Backend->GetRenderBackendValue(NVRenderBackend::NVRenderBackendQuery::MaxTextureSize,
+ &theMaxSize);
+ m_Backend->GetRenderBackendValue(
+ NVRenderBackend::NVRenderBackendQuery::MaxTextureArrayLayers, &theMaxLayerSize);
+ if (width > (QT3DSU32)theMaxSize || height > (QT3DSU32)theMaxSize
+ || slices > (QT3DSU32)theMaxLayerSize) {
+ qCCritical(INVALID_OPERATION,
+ "Width or height or Slices is greater than max texture size (%d, %d, %d)",
+ theMaxSize, theMaxSize, theMaxLayerSize);
+ }
+
+ // currently we do not support compressed texture arrays
+ QT3DS_ASSERT(NVRenderTextureFormats::isUncompressedTextureFormat(format)
+ || NVRenderTextureFormats::isDepthTextureFormat(format));
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(format)
+ || NVRenderTextureFormats::isDepthTextureFormat(format)) {
+ m_Backend->SetTextureData3D(m_TextureHandle, m_TexTarget, inMipLevel, m_Format, width,
+ height, slices, 0, format, newBuffer.begin());
+ }
+
+ // Set our texture parameters to a default that will look the best
+ if (inMipLevel > 0)
+ SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
+ }
+
+ STextureDetails NVRenderTexture2DArray::GetTextureDetails() const
+ {
+ return STextureDetails(m_Width, m_Height, m_Slices, m_SampleCount, m_Format);
+ }
+
+ void NVRenderTexture2DArray::Bind()
+ {
+ m_TextureUnit = m_Context.GetNextTextureUnit();
+
+ m_Backend->BindTexture(m_TextureHandle, m_TexTarget, m_TextureUnit);
+
+ applyTexParams();
+ applyTexSwizzle();
+ }
+
+ NVRenderTexture2DArray *NVRenderTexture2DArray::Create(NVRenderContextImpl &context)
+ {
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderTexture2DArray)(context, context.GetFoundation());
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureBase.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureBase.cpp
new file mode 100644
index 00000000..d055d72c
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureBase.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderSampler.h"
+#include "render/Qt3DSRenderTextureBase.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTextureBase::NVRenderTextureBase(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget)
+ : m_Context(context)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ , m_Backend(context.GetBackend())
+ , m_TextureHandle(NULL)
+ , m_TextureUnit(QT3DS_MAX_U32)
+ , m_SamplerParamsDirty(true)
+ , m_TexStateDirty(false)
+ , m_SampleCount(1)
+ , m_Format(NVRenderTextureFormats::Unknown)
+ , m_TexTarget(texTarget)
+ , m_BaseLevel(0)
+ , m_MaxLevel(1000)
+ , m_MaxMipLevel(0)
+ , m_Immutable(false)
+ {
+ m_TextureHandle = m_Backend->CreateTexture();
+ m_Sampler = QT3DS_NEW(m_Context.GetFoundation().getAllocator(),
+ NVRenderTextureSampler)(context, context.GetFoundation());
+ }
+
+ NVRenderTextureBase::~NVRenderTextureBase()
+ {
+ if (m_Sampler)
+ QT3DS_FREE(m_Context.GetFoundation().getAllocator(), m_Sampler);
+ if (m_TextureHandle)
+ m_Backend->ReleaseTexture(m_TextureHandle);
+ }
+
+ void NVRenderTextureBase::SetBaseLevel(QT3DSI32 value)
+ {
+ if (m_BaseLevel != value) {
+ m_BaseLevel = value;
+ m_TexStateDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetMaxLevel(QT3DSI32 value)
+ {
+ if (m_MaxLevel != value) {
+ m_MaxLevel = value;
+ m_TexStateDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetMinFilter(NVRenderTextureMinifyingOp::Enum value)
+ {
+ if (m_Sampler->m_MinFilter != value) {
+ m_Sampler->m_MinFilter = value;
+ m_SamplerParamsDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetMagFilter(NVRenderTextureMagnifyingOp::Enum value)
+ {
+ if (m_Sampler->m_MagFilter != value) {
+ m_Sampler->m_MagFilter = value;
+ m_SamplerParamsDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetTextureWrapS(NVRenderTextureCoordOp::Enum value)
+ {
+ if (m_Sampler->m_WrapS != value) {
+ m_Sampler->m_WrapS = value;
+ m_SamplerParamsDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetTextureWrapT(NVRenderTextureCoordOp::Enum value)
+ {
+ if (m_Sampler->m_WrapT != value) {
+ m_Sampler->m_WrapT = value;
+ m_SamplerParamsDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetTextureCompareMode(NVRenderTextureCompareMode::Enum value)
+ {
+ if (m_Sampler->m_CompareMode != value) {
+ m_Sampler->m_CompareMode = value;
+ m_SamplerParamsDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::SetTextureCompareFunc(NVRenderTextureCompareOp::Enum value)
+ {
+ if (m_Sampler->m_CompareOp != value) {
+ m_Sampler->m_CompareOp = value;
+ m_SamplerParamsDirty = true;
+ }
+ }
+
+ void NVRenderTextureBase::applyTexParams()
+ {
+ if (m_SamplerParamsDirty) {
+ m_Backend->UpdateSampler(m_Sampler->GetSamplerHandle(), m_TexTarget,
+ m_Sampler->m_MinFilter, m_Sampler->m_MagFilter,
+ m_Sampler->m_WrapS, m_Sampler->m_WrapT, m_Sampler->m_WrapR,
+ m_Sampler->m_MinLod, m_Sampler->m_MaxLod, m_Sampler->m_LodBias,
+ m_Sampler->m_CompareMode, m_Sampler->m_CompareOp);
+
+ m_SamplerParamsDirty = false;
+ }
+
+ if (m_TexStateDirty) {
+ m_Backend->UpdateTextureObject(m_TextureHandle, m_TexTarget, m_BaseLevel, m_MaxLevel);
+ m_TexStateDirty = false;
+ }
+ }
+
+ void NVRenderTextureBase::applyTexSwizzle()
+ {
+ NVRenderTextureSwizzleMode::Enum theSwizzleMode =
+ m_Backend->GetTextureSwizzleMode(m_Format);
+ if (theSwizzleMode != m_Sampler->m_SwizzleMode) {
+ m_Sampler->m_SwizzleMode = theSwizzleMode;
+ m_Backend->UpdateTextureSwizzle(m_TextureHandle, m_TexTarget, theSwizzleMode);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureCube.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureCube.cpp
new file mode 100644
index 00000000..0919daf3
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTextureCube.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/vector.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderSampler.h"
+#include "render/Qt3DSRenderTextureCube.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTextureCube::NVRenderTextureCube(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVRenderTextureTargetType::Enum texTarget)
+ : NVRenderTextureBase(context, fnd, texTarget)
+ , m_Width(0)
+ , m_Height(0)
+ {
+ }
+
+ NVRenderTextureCube::~NVRenderTextureCube() { m_Context.TextureDestroyed(*this); }
+
+ void NVRenderTextureCube::SetTextureData(NVDataRef<QT3DSU8> newBuffer, QT3DSU8 inMipLevel,
+ NVRenderTextureCubeFaces::Enum inFace, QT3DSU32 width,
+ QT3DSU32 height, NVRenderTextureFormats::Enum format)
+ {
+ QT3DS_ASSERT(m_TextureHandle);
+ QT3DS_ASSERT(inFace != NVRenderTextureCubeFaces::InvalidFace);
+
+ if (inMipLevel == 0) {
+ m_Width = width;
+ m_Height = height;
+ m_Format = format;
+ m_MaxMipLevel = inMipLevel;
+ }
+
+ if (m_MaxMipLevel < inMipLevel) {
+ m_MaxMipLevel = inMipLevel;
+ }
+
+ // get max size and check value
+ QT3DSI32 theMaxSize;
+ m_Backend->GetRenderBackendValue(NVRenderBackend::NVRenderBackendQuery::MaxTextureSize,
+ &theMaxSize);
+ if (width > (QT3DSU32)theMaxSize || height > (QT3DSU32)theMaxSize) {
+ qCCritical(INVALID_OPERATION, "Width or height is greater than max texture size (%d, %d)",
+ theMaxSize, theMaxSize);
+ }
+
+ NVRenderTextureTargetType::Enum outTarget =
+ static_cast<NVRenderTextureTargetType::Enum>((int)m_TexTarget + (int)inFace);
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(format)
+ || NVRenderTextureFormats::isDepthTextureFormat(format)) {
+ m_Backend->SetTextureDataCubeFace(m_TextureHandle, outTarget, inMipLevel, format, width,
+ height, 0, format, newBuffer.begin());
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(format)) {
+ m_Backend->SetCompressedTextureDataCubeFace(m_TextureHandle, outTarget, inMipLevel,
+ format, width, height, 0, newBuffer.size(),
+ newBuffer.begin());
+ }
+
+ // Set our texture parameters to a default that will look the best
+ if (inMipLevel > 0)
+ SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
+ }
+
+ STextureDetails NVRenderTextureCube::GetTextureDetails() const
+ {
+ return STextureDetails(m_Width, m_Height, 6, m_SampleCount, m_Format);
+ }
+
+ void NVRenderTextureCube::Bind()
+ {
+ m_TextureUnit = m_Context.GetNextTextureUnit();
+
+ m_Backend->BindTexture(m_TextureHandle, m_TexTarget, m_TextureUnit);
+
+ applyTexParams();
+ applyTexSwizzle();
+ }
+
+ NVRenderTextureCube *NVRenderTextureCube::Create(NVRenderContextImpl &context)
+ {
+ return QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderTextureCube)(context, context.GetFoundation());
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTimerQuery.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTimerQuery.cpp
new file mode 100644
index 00000000..4184436a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderTimerQuery.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderTimerQuery.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/StringTable.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderTimerQuery::NVRenderTimerQuery(NVRenderContextImpl &context, NVFoundationBase &fnd)
+ : NVRenderQueryBase(context, fnd)
+ {
+ }
+
+ NVRenderTimerQuery::~NVRenderTimerQuery() {}
+
+ void NVRenderTimerQuery::Begin()
+ {
+ m_Backend->BeginQuery(m_QueryHandle, NVRenderQueryType::Timer);
+ }
+
+ void NVRenderTimerQuery::End() { m_Backend->EndQuery(m_QueryHandle, NVRenderQueryType::Timer); }
+
+ void NVRenderTimerQuery::GetResult(QT3DSU32 *params)
+ {
+ m_Backend->GetQueryResult(m_QueryHandle, NVRenderQueryResultType::Result, params);
+ }
+
+ void NVRenderTimerQuery::GetResult(QT3DSU64 *params)
+ {
+ m_Backend->GetQueryResult(m_QueryHandle, NVRenderQueryResultType::Result, params);
+ }
+
+ void NVRenderTimerQuery::SetTimerQuery() { m_Backend->SetQueryTimer(m_QueryHandle); }
+
+ NVRenderTimerQuery *NVRenderTimerQuery::Create(NVRenderContextImpl &context)
+ {
+ if (!context.IsTimerQuerySupported())
+ return NULL;
+
+ NVRenderTimerQuery *retval = QT3DS_NEW(context.GetFoundation().getAllocator(),
+ NVRenderTimerQuery)(context, context.GetFoundation());
+
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexBuffer.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexBuffer.cpp
new file mode 100644
index 00000000..89d6204e
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexBuffer.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderVertexBuffer::NVRenderVertexBuffer(NVRenderContextImpl &context, size_t size,
+ QT3DSU32 stride, NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usageType,
+ NVDataRef<QT3DSU8> data)
+ : NVRenderDataBuffer(context, context.GetFoundation(), size, bindFlags, usageType, data)
+ , m_Stride(stride)
+ {
+ QT3DS_ASSERT(m_Stride);
+ }
+
+ NVRenderVertexBuffer::~NVRenderVertexBuffer() { m_Context.BufferDestroyed(*this); }
+
+ void NVRenderVertexBuffer::Bind()
+ {
+ if (m_Mapped) {
+ qCCritical(INVALID_OPERATION, "Attempting to Bind a locked buffer");
+ QT3DS_ASSERT(false);
+ }
+
+ m_Backend->BindBuffer(m_BufferHandle, m_BindFlags);
+ }
+
+ NVRenderVertexBuffer *NVRenderVertexBuffer::Create(NVRenderContextImpl &context,
+ NVRenderBufferUsageType::Enum usageType,
+ size_t size, QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVFoundationBase &fnd(context.GetFoundation());
+
+ QT3DSU32 vbufSize = sizeof(NVRenderVertexBuffer);
+ QT3DSU8 *newMem = (QT3DSU8 *)QT3DS_ALLOC(fnd.getAllocator(), vbufSize, "VertexBuffer");
+ NVRenderVertexBuffer *retval = new (newMem) NVRenderVertexBuffer(
+ context, size, stride, NVRenderBufferBindValues::Vertex, usageType,
+ toDataRef(const_cast<QT3DSU8 *>(bufferData.begin()), bufferData.size()));
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexShader.cpp b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexShader.cpp
new file mode 100644
index 00000000..3a53ad50
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/Qt3DSRenderVertexShader.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderVertexShader.h"
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderVertexShader::NVRenderVertexShader(NVRenderContextImpl &context, NVFoundationBase &fnd,
+ NVConstDataRef<QT3DSI8> source, bool binaryProgram)
+ : NVRenderShader(context, fnd, source, binaryProgram)
+ , m_ShaderHandle(NULL)
+ {
+ m_ShaderHandle = m_Backend->CreateVertexShader(source, m_ErrorMessage, binaryProgram);
+ }
+
+ NVRenderVertexShader::~NVRenderVertexShader()
+ {
+ if (m_ShaderHandle) {
+ m_Backend->ReleaseVertexShader(m_ShaderHandle);
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp
new file mode 100644
index 00000000..71c4e41a
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSOpenGLExtensions.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/backends/gl/Qt3DSOpenGLExtensions.h"
+
+Qt3DSOpenGLExtensions::Qt3DSOpenGLExtensions()
+ : QAbstractOpenGLExtension(*(new Qt3DSOpenGLExtensionsPrivate))
+{
+}
+
+bool Qt3DSOpenGLExtensions::initializeOpenGLFunctions()
+{
+ if (isInitialized())
+ return true;
+
+ QT_PREPEND_NAMESPACE(QOpenGLContext) *context =
+ QT_PREPEND_NAMESPACE(QOpenGLContext)::currentContext();
+ if (!context) {
+ qWarning("A current OpenGL context is required to resolve functions");
+ return false;
+ }
+
+ Q_D(Qt3DSOpenGLExtensions);
+
+ d->BlendBarrierNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)()>(
+ context->getProcAddress("glBlendBarrierNV"));
+ d->PathGlyphIndexArrayNV = reinterpret_cast<GLenum (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, const void*, GLbitfield, GLuint, GLsizei, GLuint,
+ GLfloat)>(
+ context->getProcAddress("glPathGlyphIndexArrayNV"));
+ d->PathGlyphIndexRangeNV = reinterpret_cast<GLenum (QOPENGLF_APIENTRYP)(
+ GLenum, const void*, GLbitfield, GLuint, GLfloat, GLuint[2])>(
+ context->getProcAddress("glPathGlyphIndexRangeNV"));
+ QAbstractOpenGLExtension::initializeOpenGLFunctions();
+ return true;
+}
+
+#if defined(QT_OPENGL_ES)
+Qt3DSOpenGLES2Extensions::Qt3DSOpenGLES2Extensions()
+{
+}
+
+bool Qt3DSOpenGLES2Extensions::initializeOpenGLFunctions()
+{
+ if (isInitialized())
+ return true;
+
+ QT_PREPEND_NAMESPACE(QOpenGLContext) *context =
+ QT_PREPEND_NAMESPACE(QOpenGLContext)::currentContext();
+ if (!context) {
+ qWarning("A current OpenGL context is required to resolve functions");
+ return false;
+ }
+
+ Q_D(Qt3DSOpenGLExtensions);
+
+#if defined(QT_OPENGL_ES)
+ d->PatchParameteriEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLenum, GLint)>(
+ context->getProcAddress("glPatchParameteriEXT"));
+ d->QueryCounterEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum)>(
+ context->getProcAddress("glQueryCounterEXT"));
+ d->GetQueryObjectui64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, GLuint64 *)>(
+ context->getProcAddress("glGetQueryObjectui64vEXT"));
+ d->GenPathsNV = reinterpret_cast<GLuint (QOPENGLF_APIENTRYP)(
+ GLsizei)>(
+ context->getProcAddress("glGenPathsNV"));
+ d->DeletePathsNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLsizei)>(
+ context->getProcAddress("glDeletePathsNV"));
+ d->PathCommandsNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLsizei, const GLubyte *, GLsizei, GLenum, const void *)>(
+ context->getProcAddress("glPathCommandsNV"));
+ d->PathGlyphsNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, const void *, GLbitfield, GLsizei, GLenum, const void *,
+ GLenum, GLuint, GLfloat)>(
+ context->getProcAddress("glPathGlyphsNV"));
+ d->PathGlyphRangeNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, const void *, GLbitfield, GLuint, GLsizei, GLenum,
+ GLuint, GLfloat)>(
+ context->getProcAddress("glPathGlyphRangeNV"));
+ d->PathParameterfNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, GLfloat)>(
+ context->getProcAddress("glPathParameterfNV"));
+ d->PathStencilDepthOffsetNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLfloat, GLfloat)>(
+ context->getProcAddress("glPathStencilDepthOffsetNV"));
+ d->StencilFillPathNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, GLuint)>(
+ context->getProcAddress("glStencilFillPathNV"));
+ d->StencilStrokePathNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLint, GLuint)>(
+ context->getProcAddress("glStencilStrokePathNV"));
+ d->StencilFillPathInstancedNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLsizei, GLenum, const void *, GLuint, GLenum, GLuint, GLenum,
+ const GLfloat *)>(
+ context->getProcAddress("glStencilFillPathInstancedNV"));
+ d->StencilStrokePathInstancedNV
+ = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei, GLenum,
+ const void *, GLuint, GLint, GLuint, GLenum, const GLfloat *)>(
+ context->getProcAddress("glStencilStrokePathInstancedNV"));
+ d->PathCoverDepthFuncNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLenum func)>(
+ context->getProcAddress("glPathCoverDepthFuncNV"));
+ d->CoverFillPathInstancedNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLsizei, GLenum, const void *, GLuint, GLenum, GLenum,
+ const GLfloat *)>(
+ context->getProcAddress("glCoverFillPathInstancedNV"));
+ d->CoverStrokePathInstancedNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLsizei, GLenum, const void *, GLuint, GLenum, GLenum,
+ const GLfloat *)>(
+ context->getProcAddress("glCoverStrokePathInstancedNV"));
+ d->GetPathParameterfvNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLuint, GLenum, GLfloat *)>(
+ context->getProcAddress("glGetPathParameterfvNV"));
+ d->GetPathMetricsNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLbitfield, GLsizei, GLenum, const void *, GLuint, GLsizei, GLfloat *)>(
+ context->getProcAddress("glGetPathMetricsNV"));
+ d->GetPathMetricRangeNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLbitfield, GLuint, GLsizei, GLsizei, GLfloat *)>(
+ context->getProcAddress("glGetPathMetricRangeNV"));
+ d->GetPathSpacingNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
+ GLenum, GLsizei, GLenum, const void *, GLuint, GLfloat, GLfloat, GLenum,
+ GLfloat *)>(
+ context->getProcAddress("glGetPathSpacingNV"));
+#endif
+ Qt3DSOpenGLExtensions::initializeOpenGLFunctions();
+ return true;
+}
+#endif // QT_OPENGL_ES
diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp
new file mode 100644
index 00000000..c8a99cb2
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL3.cpp
@@ -0,0 +1,771 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/backends/gl/Qt3DSRenderBackendGL3.h"
+#include "render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h"
+#include "render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h"
+#include "render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h"
+
+#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; checkGLError();
+
+#if defined(QT_OPENGL_ES)
+#define GL_CALL_TIMER_EXT(x) m_qt3dsExtensions->x; checkGLError();
+#define GL_CALL_TESSELATION_EXT(x) m_qt3dsExtensions->x; checkGLError();
+#else
+#define GL_CALL_TIMER_EXT(x) m_timerExtension->x; checkGLError();
+#define GL_CALL_TESSELATION_EXT(x) m_tessellationShader->x; checkGLError();
+#define GL_CALL_MULTISAMPLE_EXT(x) m_multiSample->x; checkGLError();
+#endif
+
+namespace qt3ds {
+namespace render {
+
+ /// constructor
+ NVRenderBackendGL3Impl::NVRenderBackendGL3Impl(NVFoundationBase &fnd,
+ qt3ds::foundation::IStringTable &stringTable,
+ const QSurfaceFormat &format)
+ : NVRenderBackendGLBase(fnd, stringTable, format)
+ {
+ eastl::string exts3tc("GL_EXT_texture_compression_s3tc");
+ eastl::string extsAniso("GL_EXT_texture_filter_anisotropic");
+ eastl::string extsTexSwizzle("GL_ARB_texture_swizzle");
+ eastl::string extsAstcHDR("GL_KHR_texture_compression_astc_hdr");
+ eastl::string extsAstcLDR("GL_KHR_texture_compression_astc_ldr");
+ eastl::string extsFPRenderTarget("GL_EXT_color_buffer_float");
+ eastl::string extsTimerQuery("GL_EXT_timer_query");
+ eastl::string extsGpuShader5("EXT_gpu_shader5");
+
+ const char *languageVersion = GetShadingLanguageVersion();
+ qCInfo(TRACE_INFO, "GLSL version: %s", languageVersion);
+
+ eastl::string apiVersion(getVersionString());
+ qCInfo(TRACE_INFO, "GL version: %s", apiVersion.c_str());
+
+ eastl::string apiVendor(getVendorString());
+ qCInfo(TRACE_INFO, "HW vendor: %s", apiVendor.c_str());
+
+ eastl::string apiRenderer(geRendererString());
+ qCInfo(TRACE_INFO, "Vendor renderer: %s", apiRenderer.c_str());
+
+ // clear support bits
+ m_backendSupport.caps.u32Values = 0;
+
+ // get extension count
+ GLint numExtensions = 0;
+ GL_CALL_EXTRA_FUNCTION(glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions));
+
+ eastl::string extensionBuffer;
+
+ for (QT3DSI32 i = 0; i < numExtensions; i++) {
+ char *extensionString = (char *)GL_CALL_EXTRA_FUNCTION(glGetStringi(GL_EXTENSIONS, i));
+ const TContextStr::value_type *thePtr =
+ reinterpret_cast<TContextStr::value_type *>(extensionString);
+ m_Extensions.push_back(
+ TContextStr(ForwardingAllocator(m_Foundation.getAllocator(), "ExtensionStr")));
+ m_Extensions.back().assign(thePtr);
+
+ if (extensionBuffer.size())
+ extensionBuffer.append(" ");
+ extensionBuffer.append(extensionString);
+
+ // search for extension
+ if (!m_backendSupport.caps.bits.bDXTImagesSupported
+ && exts3tc.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bDXTImagesSupported = true;
+ } else if (!m_backendSupport.caps.bits.bAnistropySupported
+ && extsAniso.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bAnistropySupported = true;
+ } else if (!m_backendSupport.caps.bits.bFPRenderTargetsSupported
+ && extsFPRenderTarget.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bFPRenderTargetsSupported = true;
+ } else if (!m_backendSupport.caps.bits.bTimerQuerySupported
+ && extsTimerQuery.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bTimerQuerySupported = true;
+ } else if (!m_backendSupport.caps.bits.bGPUShader5ExtensionSupported
+ && extsGpuShader5.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bGPUShader5ExtensionSupported = true;
+ }
+
+ }
+
+ qCInfo(TRACE_INFO, "OpenGL extensions: %s", extensionBuffer.c_str());
+
+ // texture swizzle is always true
+ m_backendSupport.caps.bits.bTextureSwizzleSupported = true;
+ // depthstencil renderbuffer support is always true
+ m_backendSupport.caps.bits.bDepthStencilSupported = true;
+ // constant buffers support is always true
+ m_backendSupport.caps.bits.bConstantBufferSupported = true;
+
+ if (!isESCompatible()) {
+ // render to float textures is always supported on none ES systems which support >=GL3
+ m_backendSupport.caps.bits.bFPRenderTargetsSupported = true;
+ // multisampled texture is always supported on none ES systems which support >=GL3
+ m_backendSupport.caps.bits.bMsTextureSupported = true;
+ // timer queries are always supported on none ES systems which support >=GL3
+ m_backendSupport.caps.bits.bTimerQuerySupported = true;
+ }
+
+ // query hardware
+ GL_CALL_EXTRA_FUNCTION(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_MaxAttribCount));
+
+ // internal state tracker
+ m_pCurrentMiscState = QT3DS_NEW(m_Foundation.getAllocator(), NVRenderBackendMiscStateGL)();
+
+ // finally setup caps based on device
+ setAndInspectHardwareCaps();
+
+ // Initialize extensions
+#if defined(QT_OPENGL_ES)
+ m_qt3dsExtensions = new Qt3DSOpenGLES2Extensions;
+ m_qt3dsExtensions->initializeOpenGLFunctions();
+#else
+ m_timerExtension = new QOpenGLExtension_ARB_timer_query;
+ m_timerExtension->initializeOpenGLFunctions();
+ m_tessellationShader = new QOpenGLExtension_ARB_tessellation_shader;
+ m_tessellationShader->initializeOpenGLFunctions();
+ m_multiSample = new QOpenGLExtension_ARB_texture_multisample;
+ m_multiSample->initializeOpenGLFunctions();
+ m_qt3dsExtensions = new Qt3DSOpenGLExtensions;
+ m_qt3dsExtensions->initializeOpenGLFunctions();
+#endif
+ }
+ /// destructor
+ NVRenderBackendGL3Impl::~NVRenderBackendGL3Impl()
+ {
+ if (m_pCurrentMiscState)
+ NVDelete(m_Foundation.getAllocator(), m_pCurrentMiscState);
+#if !defined(QT_OPENGL_ES)
+ if (m_timerExtension)
+ delete m_timerExtension;
+ if (m_tessellationShader)
+ delete m_tessellationShader;
+ if (m_multiSample)
+ delete m_multiSample;
+#endif
+ if (m_qt3dsExtensions)
+ delete m_qt3dsExtensions;
+ }
+
+ void NVRenderBackendGL3Impl::SetMultisampledTextureData2D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, size_t samples,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height,
+ bool fixedsamplelocations)
+ {
+// Not supported by ES 3 yet
+#if defined(QT_OPENGL_ES)
+ NVRENDER_BACKEND_UNUSED(to);
+ NVRENDER_BACKEND_UNUSED(target);
+ NVRENDER_BACKEND_UNUSED(samples);
+ NVRENDER_BACKEND_UNUSED(internalFormat);
+ NVRENDER_BACKEND_UNUSED(width);
+ NVRENDER_BACKEND_UNUSED(height);
+ NVRENDER_BACKEND_UNUSED(fixedsamplelocations);
+#else
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
+
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
+ internalFormat, swizzleMode);
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ GLConversion::fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+ else if (NVRenderTextureFormats::isDepthTextureFormat(internalFormat))
+ m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+
+ GL_CALL_MULTISAMPLE_EXT(glTexImage2DMultisample(glTarget, (GLsizei)samples, glInternalFormat,
+ (GLsizei)width, (GLsizei)height, fixedsamplelocations));
+
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
+#endif
+ }
+
+ void NVRenderBackendGL3Impl::SetTextureData3D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, size_t depth,
+ QT3DSI32 border, NVRenderTextureFormats::Enum format, const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
+ bool conversionRequired = format != internalFormat;
+
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
+ internalFormat, swizzleMode);
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+
+ if (conversionRequired) {
+ GLenum dummy;
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, dummy);
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) {
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+ glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(format))
+ m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+
+ GL_CALL_EXTRA_FUNCTION(glTexImage3D(glTarget, level, glInternalFormat, (GLsizei)width, (GLsizei)height,
+ (GLsizei)depth, border, glformat, gltype, hostPtr));
+
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ void NVRenderBackendGL3Impl::UpdateSampler(
+ NVRenderBackendSamplerObject /* so */, NVRenderTextureTargetType::Enum target,
+ NVRenderTextureMinifyingOp::Enum minFilter, NVRenderTextureMagnifyingOp::Enum magFilter,
+ NVRenderTextureCoordOp::Enum wrapS, NVRenderTextureCoordOp::Enum wrapT,
+ NVRenderTextureCoordOp::Enum wrapR, QT3DSF32 minLod, QT3DSF32 maxLod, QT3DSF32 lodBias,
+ NVRenderTextureCompareMode::Enum compareMode, NVRenderTextureCompareOp::Enum compareFunc,
+ QT3DSF32 anisotropy, QT3DSF32 *borderColor)
+ {
+
+ // Satisfy the compiler
+ // These are not available in GLES 3 and we don't use them right now
+ QT3DS_ASSERT(lodBias == 0.0);
+ QT3DS_ASSERT(!borderColor);
+ NVRENDER_BACKEND_UNUSED(lodBias);
+ NVRENDER_BACKEND_UNUSED(borderColor);
+
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MIN_FILTER,
+ m_Conversion.fromTextureMinifyingOpToGL(minFilter)));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAG_FILTER,
+ m_Conversion.fromTextureMagnifyingOpToGL(magFilter)));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_S,
+ m_Conversion.fromTextureCoordOpToGL(wrapS)));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_T,
+ m_Conversion.fromTextureCoordOpToGL(wrapT)));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_R,
+ m_Conversion.fromTextureCoordOpToGL(wrapR)));
+ GL_CALL_EXTRA_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MIN_LOD, minLod));
+ GL_CALL_EXTRA_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MAX_LOD, maxLod));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_COMPARE_MODE,
+ m_Conversion.fromTextureCompareModeToGL(compareMode)));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_COMPARE_FUNC,
+ m_Conversion.fromTextureCompareFuncToGL(compareFunc)));
+
+ if (m_backendSupport.caps.bits.bAnistropySupported) {
+ GL_CALL_EXTRA_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy));
+ }
+ }
+
+ void NVRenderBackendGL3Impl::UpdateTextureObject(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ QT3DSI32 baseLevel, QT3DSI32 maxLevel)
+ {
+ NVRENDER_BACKEND_UNUSED(to);
+
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_BASE_LEVEL, baseLevel));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAX_LEVEL, maxLevel));
+ }
+
+ void NVRenderBackendGL3Impl::UpdateTextureSwizzle(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderTextureSwizzleMode::Enum swizzleMode)
+ {
+ NVRENDER_BACKEND_UNUSED(to);
+ if (m_backendSupport.caps.bits.bTextureSwizzleSupported) {
+ GLint glSwizzle[4];
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ m_Conversion.NVRenderConvertSwizzleModeToGL(swizzleMode, glSwizzle);
+#if defined(QT_OPENGL_ES)
+ // since ES3 spec has no GL_TEXTURE_SWIZZLE_RGBA set it separately
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_R, glSwizzle[0]));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_G, glSwizzle[1]));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_B, glSwizzle[2]));
+ GL_CALL_EXTRA_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_SWIZZLE_A, glSwizzle[3]));
+#else
+ GL_CALL_EXTRA_FUNCTION(glTexParameteriv(glTarget, GL_TEXTURE_SWIZZLE_RGBA, glSwizzle));
+#endif
+ }
+ }
+
+ QT3DSU32
+ NVRenderBackendGL3Impl::GetDepthBits() const
+ {
+ QT3DSI32 depthBits;
+ GL_CALL_EXTRA_FUNCTION(glGetFramebufferAttachmentParameteriv(
+ GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depthBits));
+
+ return depthBits;
+ }
+
+ QT3DSU32
+ NVRenderBackendGL3Impl::GetStencilBits() const
+ {
+ QT3DSI32 stencilBits;
+ GL_CALL_EXTRA_FUNCTION(glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
+ &stencilBits));
+
+ return stencilBits;
+ }
+
+ void NVRenderBackendGL3Impl::GenerateMipMaps(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderHint::Enum /*genType*/)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
+ GL_CALL_EXTRA_FUNCTION(glGenerateMipmap(glTarget));
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ bool NVRenderBackendGL3Impl::SetInputAssembler(NVRenderBackendInputAssemblerObject iao,
+ NVRenderBackendShaderProgramObject po)
+ {
+ if (iao == NULL) {
+ // unbind and return;
+ GL_CALL_EXTRA_FUNCTION(glBindVertexArray(0));
+ return true;
+ }
+
+ NVRenderBackendInputAssemblerGL *inputAssembler = (NVRenderBackendInputAssemblerGL *)iao;
+ NVRenderBackendAttributeLayoutGL *attribLayout = inputAssembler->m_attribLayout;
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+ NVDataRef<NVRenderBackendShaderInputEntryGL> shaderAttribBuffer;
+ if (pProgram->m_shaderInput)
+ shaderAttribBuffer = pProgram->m_shaderInput->m_ShaderInputEntries;
+
+ if ((attribLayout->m_LayoutAttribEntries.size() < shaderAttribBuffer.size())
+ || (inputAssembler->m_VertexbufferHandles.size() <= attribLayout->m_MaxInputSlot)) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ if (inputAssembler->m_VaoID == 0) {
+ // generate vao
+ GL_CALL_EXTRA_FUNCTION(glGenVertexArrays(1, &inputAssembler->m_VaoID));
+ QT3DS_ASSERT(inputAssembler->m_VaoID);
+ }
+
+ // set patch parameter count if changed
+ if (m_backendSupport.caps.bits.bTessellationSupported
+ && m_pCurrentMiscState->m_PatchVertexCount != inputAssembler->m_PatchVertexCount) {
+ m_pCurrentMiscState->m_PatchVertexCount = inputAssembler->m_PatchVertexCount;
+#if defined(QT_OPENGL_ES)
+ GL_CALL_TESSELATION_EXT(glPatchParameteriEXT(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount));
+#else
+ GL_CALL_TESSELATION_EXT(glPatchParameteri(GL_PATCH_VERTICES, inputAssembler->m_PatchVertexCount));
+#endif
+ }
+
+ if (inputAssembler->m_cachedShaderHandle != programID) {
+ GL_CALL_EXTRA_FUNCTION(glBindVertexArray(inputAssembler->m_VaoID));
+ inputAssembler->m_cachedShaderHandle = programID;
+
+ UICBASE_FOREACH(idx, shaderAttribBuffer.size())
+ {
+ const NVRenderBackendShaderInputEntryGL &attrib(shaderAttribBuffer[idx]);
+ NVRenderBackendLayoutEntryGL *entry =
+ attribLayout->getEntryByName(attrib.m_AttribName);
+
+ if (entry) {
+ NVRenderBackendLayoutEntryGL &entryData(*entry);
+ if (entryData.m_Type != attrib.m_Type
+ || entryData.m_NumComponents != attrib.m_NumComponents) {
+ qCCritical(INVALID_OPERATION, "Attrib %s doesn't match vertex layout",
+ attrib.m_AttribName.c_str());
+ QT3DS_ASSERT(false);
+ return false;
+ } else {
+ entryData.m_AttribIndex = attrib.m_AttribLocation;
+ }
+ } else {
+ qCWarning(WARNING, "Failed to Bind attribute %s", attrib.m_AttribName.c_str());
+ }
+ }
+
+ // disable max possible used first
+ // this is currently sufficient since we always re-arrange input attributes from 0
+ for (QT3DSU32 i = 0; i < attribLayout->m_LayoutAttribEntries.size(); i++) {
+ GL_CALL_EXTRA_FUNCTION(glDisableVertexAttribArray(i));
+ }
+
+ // setup all attribs
+ UICBASE_FOREACH(idx, shaderAttribBuffer.size())
+ {
+ NVRenderBackendLayoutEntryGL *entry =
+ attribLayout->getEntryByName(shaderAttribBuffer[idx].m_AttribName);
+ if (entry) {
+ const NVRenderBackendLayoutEntryGL &entryData(*entry);
+ GLuint id = HandleToID_cast(
+ GLuint, size_t,
+ inputAssembler->m_VertexbufferHandles.mData[entryData.m_InputSlot]);
+ GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ARRAY_BUFFER, id));
+ GL_CALL_EXTRA_FUNCTION(glEnableVertexAttribArray(entryData.m_AttribIndex));
+ GLuint offset = inputAssembler->m_offsets[entryData.m_InputSlot];
+ GLuint stride = inputAssembler->m_strides[entryData.m_InputSlot];
+ GL_CALL_EXTRA_FUNCTION(glVertexAttribPointer(
+ entryData.m_AttribIndex, entryData.m_NumComponents, GL_FLOAT, GL_FALSE,
+ stride, (const void *)(entryData.m_Offset + offset)));
+
+ } else {
+ GL_CALL_EXTRA_FUNCTION(glDisableVertexAttribArray(idx));
+ }
+ }
+
+ // setup index buffer.
+ if (inputAssembler->m_IndexbufferHandle) {
+ GL_CALL_EXTRA_FUNCTION(glBindBuffer(
+ GL_ELEMENT_ARRAY_BUFFER,
+ HandleToID_cast(GLuint, size_t, inputAssembler->m_IndexbufferHandle)));
+ } else {
+ GL_CALL_EXTRA_FUNCTION(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+ }
+ } else {
+ GL_CALL_EXTRA_FUNCTION(glBindVertexArray(inputAssembler->m_VaoID));
+ }
+#ifdef _DEBUG
+ if (inputAssembler->m_VaoID) {
+ UICBASE_FOREACH(idx, shaderAttribBuffer.size())
+ {
+ const NVRenderBackendShaderInputEntryGL &attrib(shaderAttribBuffer[idx]);
+ NVRenderBackendLayoutEntryGL *entry =
+ attribLayout->getEntryByName(attrib.m_AttribName);
+
+ if (entry) {
+ NVRenderBackendLayoutEntryGL &entryData(*entry);
+ if (entryData.m_Type != attrib.m_Type
+ || entryData.m_NumComponents != attrib.m_NumComponents
+ || entryData.m_AttribIndex != attrib.m_AttribLocation) {
+ qCCritical(INVALID_OPERATION, "Attrib %s doesn't match vertex layout",
+ attrib.m_AttribName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ qCWarning(WARNING, "Failed to Bind attribute %s", attrib.m_AttribName.c_str());
+ }
+ }
+ }
+#endif // _DEBUG
+
+ return true;
+ }
+
+ void NVRenderBackendGL3Impl::SetDrawBuffers(NVRenderBackendRenderTargetObject rto,
+ NVConstDataRef<QT3DSI32> inDrawBufferSet)
+ {
+ NVRENDER_BACKEND_UNUSED(rto);
+
+ m_DrawBuffersArray.clear();
+
+ for (QT3DSU32 idx = 0, end = inDrawBufferSet.size(); idx < end; ++idx) {
+ if (inDrawBufferSet[idx] < 0)
+ m_DrawBuffersArray.push_back(GL_NONE);
+ else
+ m_DrawBuffersArray.push_back(GL_COLOR_ATTACHMENT0 + inDrawBufferSet[idx]);
+ }
+
+ GL_CALL_EXTRA_FUNCTION(glDrawBuffers((int)m_DrawBuffersArray.size(), m_DrawBuffersArray.data()));
+ }
+
+ void NVRenderBackendGL3Impl::SetReadBuffer(NVRenderBackendRenderTargetObject rto,
+ NVReadFaces::Enum inReadFace)
+ {
+ NVRENDER_BACKEND_UNUSED(rto);
+
+ GL_CALL_EXTRA_FUNCTION(glReadBuffer(m_Conversion.fromReadFacesToGL(inReadFace)));
+ }
+
+ void NVRenderBackendGL3Impl::RenderTargetAttach(NVRenderBackendRenderTargetObject,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to, QT3DSI32 level,
+ QT3DSI32 layer)
+ {
+ // rto must be the current render target
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+
+ GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
+
+ GL_CALL_EXTRA_FUNCTION(glFramebufferTextureLayer(GL_FRAMEBUFFER, glAttach, texID, level, layer))
+ }
+
+ void NVRenderBackendGL3Impl::SetReadTarget(NVRenderBackendRenderTargetObject rto)
+ {
+ GLuint fboID = HandleToID_cast(GLuint, size_t, rto);
+
+ GL_CALL_EXTRA_FUNCTION(glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID));
+ }
+
+ void NVRenderBackendGL3Impl::BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter)
+ {
+ GL_CALL_EXTRA_FUNCTION(glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ m_Conversion.fromClearFlagsToGL(flags),
+ m_Conversion.fromTextureMagnifyingOpToGL(filter)));
+ }
+
+ void *NVRenderBackendGL3Impl::MapBuffer(NVRenderBackendBufferObject,
+ NVRenderBufferBindFlags bindFlags, size_t offset,
+ size_t length, NVRenderBufferAccessFlags accessFlags)
+ {
+ void *ret = NULL;
+ ret = GL_CALL_EXTRA_FUNCTION(glMapBufferRange(m_Conversion.fromBindBufferFlagsToGL(bindFlags), offset,
+ length, m_Conversion.fromBufferAccessBitToGL(accessFlags)));
+
+ return ret;
+ }
+
+ bool NVRenderBackendGL3Impl::UnmapBuffer(NVRenderBackendBufferObject,
+ NVRenderBufferBindFlags bindFlags)
+ {
+ GLboolean ret;
+
+ ret = GL_CALL_EXTRA_FUNCTION(glUnmapBuffer(m_Conversion.fromBindBufferFlagsToGL(bindFlags)));
+
+ return (ret) ? true : false;
+ }
+
+ QT3DSI32 NVRenderBackendGL3Impl::GetConstantBufferCount(NVRenderBackendShaderProgramObject po)
+ {
+ QT3DS_ASSERT(po);
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GLint numUniformBuffers;
+ GL_CALL_EXTRA_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBuffers));
+
+ return numUniformBuffers;
+ }
+
+ QT3DSI32
+ NVRenderBackendGL3Impl::GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize,
+ QT3DSI32 *paramCount, QT3DSI32 *bufferSize,
+ QT3DSI32 *length, char *nameBuf)
+ {
+ QT3DS_ASSERT(po);
+ QT3DS_ASSERT(length);
+ QT3DS_ASSERT(nameBuf);
+
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+ GLuint blockIndex = GL_INVALID_INDEX;
+
+ GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockName(programID, id, nameBufSize, length, nameBuf));
+
+ if (*length > 0) {
+ blockIndex = GL_CALL_EXTRA_FUNCTION(glGetUniformBlockIndex(programID, nameBuf));
+ if (blockIndex != GL_INVALID_INDEX) {
+ GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, blockIndex,
+ GL_UNIFORM_BLOCK_DATA_SIZE, bufferSize));
+ GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, blockIndex,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, paramCount));
+ }
+ }
+
+ return blockIndex;
+ }
+
+ void
+ NVRenderBackendGL3Impl::GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSI32 *indices)
+ {
+ QT3DS_ASSERT(po);
+ QT3DS_ASSERT(indices);
+
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ if (indices) {
+ GL_CALL_EXTRA_FUNCTION(glGetActiveUniformBlockiv(programID, id,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices));
+ }
+ }
+
+ void NVRenderBackendGL3Impl::GetConstantBufferParamInfoByIndices(
+ NVRenderBackendShaderProgramObject po, QT3DSU32 count, QT3DSU32 *indices, QT3DSI32 *type,
+ QT3DSI32 *size, QT3DSI32 *offset)
+ {
+ QT3DS_ASSERT(po);
+ QT3DS_ASSERT(count);
+ QT3DS_ASSERT(indices);
+
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ if (count && indices) {
+ if (type) {
+ GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, count, indices, GL_UNIFORM_TYPE, type));
+ // convert to UIC types
+ UICBASE_FOREACH(idx, count)
+ {
+ type[idx] = m_Conversion.fromShaderGLToPropertyDataTypes(type[idx]);
+ }
+ }
+ if (size) {
+ GL_CALL_EXTRA_FUNCTION(glGetActiveUniformsiv(programID, count, indices, GL_UNIFORM_SIZE, size));
+ }
+ if (offset) {
+ GL_CALL_EXTRA_FUNCTION(
+ glGetActiveUniformsiv(programID, count, indices, GL_UNIFORM_OFFSET, offset));
+ }
+ }
+ }
+
+ void NVRenderBackendGL3Impl::ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 blockIndex, QT3DSU32 binding)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GL_CALL_EXTRA_FUNCTION(glUniformBlockBinding(programID, blockIndex, binding));
+ }
+
+ void NVRenderBackendGL3Impl::ProgramSetConstantBuffer(QT3DSU32 index,
+ NVRenderBackendBufferObject bo)
+ {
+ QT3DS_ASSERT(bo);
+
+ GLuint bufID = HandleToID_cast(GLuint, size_t, bo);
+ GL_CALL_EXTRA_FUNCTION(glBindBufferBase(GL_UNIFORM_BUFFER, index, bufID));
+ }
+
+ NVRenderBackend::NVRenderBackendQueryObject NVRenderBackendGL3Impl::CreateQuery()
+ {
+ QT3DSU32 glQueryID = 0;
+
+ GL_CALL_EXTRA_FUNCTION(glGenQueries(1, &glQueryID));
+
+ return (NVRenderBackendQueryObject)glQueryID;
+ }
+
+ void NVRenderBackendGL3Impl::ReleaseQuery(NVRenderBackendQueryObject qo)
+ {
+ GLuint queryID = HandleToID_cast(GLuint, size_t, qo);
+
+ GL_CALL_EXTRA_FUNCTION(glDeleteQueries(1, &queryID));
+ }
+
+ void NVRenderBackendGL3Impl::BeginQuery(NVRenderBackendQueryObject qo,
+ NVRenderQueryType::Enum type)
+ {
+ GLuint queryID = HandleToID_cast(GLuint, size_t, qo);
+
+ GL_CALL_EXTRA_FUNCTION(glBeginQuery(m_Conversion.fromQueryTypeToGL(type), queryID));
+ }
+
+ void NVRenderBackendGL3Impl::EndQuery(NVRenderBackendQueryObject, NVRenderQueryType::Enum type)
+ {
+ GL_CALL_EXTRA_FUNCTION(glEndQuery(m_Conversion.fromQueryTypeToGL(type)));
+ }
+
+ void NVRenderBackendGL3Impl::GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType,
+ QT3DSU32 *params)
+ {
+ GLuint queryID = HandleToID_cast(GLuint, size_t, qo);
+
+ if (params)
+ GL_CALL_EXTRA_FUNCTION(glGetQueryObjectuiv(
+ queryID, m_Conversion.fromQueryResultTypeToGL(resultType), params));
+ }
+
+ void NVRenderBackendGL3Impl::GetQueryResult(NVRenderBackendQueryObject qo,
+ NVRenderQueryResultType::Enum resultType,
+ QT3DSU64 *params)
+ {
+ if (m_backendSupport.caps.bits.bTimerQuerySupported) {
+ GLuint queryID = HandleToID_cast(GLuint, size_t, qo);
+
+ if (params)
+#if defined(QT_OPENGL_ES)
+ GL_CALL_TIMER_EXT(glGetQueryObjectui64vEXT(
+ queryID, m_Conversion.fromQueryResultTypeToGL(resultType), params));
+#else
+ GL_CALL_TIMER_EXT(glGetQueryObjectui64v(
+ queryID, m_Conversion.fromQueryResultTypeToGL(resultType), params));
+#endif
+ }
+ }
+
+ void NVRenderBackendGL3Impl::SetQueryTimer(NVRenderBackendQueryObject qo)
+ {
+ if (m_backendSupport.caps.bits.bTimerQuerySupported) {
+ GLuint queryID = HandleToID_cast(GLuint, size_t, qo);
+#if defined(QT_OPENGL_ES)
+ GL_CALL_TIMER_EXT(glQueryCounterEXT(queryID, GL_TIMESTAMP));
+#else
+ GL_CALL_TIMER_EXT(glQueryCounter(queryID, GL_TIMESTAMP));
+#endif
+ }
+ }
+
+ NVRenderBackend::NVRenderBackendSyncObject
+ NVRenderBackendGL3Impl::CreateSync(NVRenderSyncType::Enum syncType, NVRenderSyncFlags)
+ {
+ GLsync syncID = 0;
+
+ syncID = GL_CALL_EXTRA_FUNCTION(glFenceSync(m_Conversion.fromSyncTypeToGL(syncType), 0));
+
+ return NVRenderBackendSyncObject(syncID);
+ }
+
+ void NVRenderBackendGL3Impl::ReleaseSync(NVRenderBackendSyncObject so)
+ {
+ GLsync syncID = (GLsync)so;
+
+ GL_CALL_EXTRA_FUNCTION(glDeleteSync(syncID));
+ }
+
+ void NVRenderBackendGL3Impl::WaitSync(NVRenderBackendSyncObject so, NVRenderCommandFlushFlags,
+ QT3DSU64)
+ {
+ GLsync syncID = (GLsync)so;
+
+ GL_CALL_EXTRA_FUNCTION(glWaitSync(syncID, 0, GL_TIMEOUT_IGNORED));
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp
new file mode 100644
index 00000000..ef383f6d
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGL4.cpp
@@ -0,0 +1,827 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/backends/gl/Qt3DSRenderBackendGL4.h"
+#include "render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h"
+#include "render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h"
+
+#define NVRENDER_BACKEND_UNUSED(arg) (void)arg;
+
+#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; checkGLError();
+
+#if defined(QT_OPENGL_ES)
+#define GL_CALL_NVPATH_EXT(x) m_qt3dsExtensions->x; checkGLError();
+#define GL_CALL_QT3DS_EXT(x) m_qt3dsExtensions->x; checkGLError();
+#else
+#define GL_CALL_NVPATH_EXT(x) m_nvPathRendering->x; checkGLError();
+#define GL_CALL_DIRECTSTATE_EXT(x) m_directStateAccess->x; checkGLError();
+#define GL_CALL_QT3DS_EXT(x) m_qt3dsExtensions->x; checkGLError();
+#endif
+
+namespace qt3ds {
+namespace render {
+
+ /// constructor
+ NVRenderBackendGL4Impl::NVRenderBackendGL4Impl(NVFoundationBase &fnd,
+ qt3ds::foundation::IStringTable &stringTable,
+ const QSurfaceFormat &format)
+ : NVRenderBackendGL3Impl(fnd, stringTable, format)
+ {
+ eastl::string extTess("GL_ARB_tessellation_shader");
+ eastl::string extGeometry("GL_EXT_geometry_shader4");
+ eastl::string arbCompute("GL_ARB_compute_shader");
+ eastl::string arbStorageBuffer("GL_ARB_shader_storage_buffer_object");
+ eastl::string arbAtomicCounterBuffer("GL_ARB_shader_atomic_counters");
+ eastl::string arbProgInterface("GL_ARB_program_interface_query");
+ eastl::string arbShaderImageLoadStore("GL_ARB_shader_image_load_store");
+ eastl::string nvPathRendering("GL_NV_path_rendering");
+ eastl::string nvBlendAdvanced("GL_NV_blend_equation_advanced");
+ eastl::string khrBlendAdvanced("GL_KHR_blend_equation_advanced");
+ eastl::string nvBlendAdvancedCoherent("GL_NV_blend_equation_advanced_coherent");
+ eastl::string khrBlendAdvancedCoherent("GL_KHR_blend_equation_advanced_coherent");
+
+ eastl::string apiVersion(getVersionString());
+ qCInfo(TRACE_INFO, "GL version: %s", apiVersion.c_str());
+
+ // get extension count
+ GLint numExtensions = 0;
+ GL_CALL_EXTRA_FUNCTION(glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions));
+
+ for (QT3DSI32 i = 0; i < numExtensions; i++) {
+ char *extensionString = (char *)GL_CALL_EXTRA_FUNCTION(glGetStringi(GL_EXTENSIONS, i));
+
+ // search for extension
+ if (!m_backendSupport.caps.bits.bTessellationSupported
+ && extTess.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bTessellationSupported = true;
+ } else if (!m_backendSupport.caps.bits.bComputeSupported
+ && arbCompute.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bComputeSupported = true;
+ } else if (!m_backendSupport.caps.bits.bGeometrySupported
+ && extGeometry.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bGeometrySupported = true;
+ } else if (!m_backendSupport.caps.bits.bStorageBufferSupported
+ && arbStorageBuffer.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bStorageBufferSupported = true;
+ } else if (!m_backendSupport.caps.bits.bAtomicCounterBufferSupported
+ && arbAtomicCounterBuffer.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bAtomicCounterBufferSupported = true;
+ } else if (!m_backendSupport.caps.bits.bProgramInterfaceSupported
+ && arbProgInterface.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bProgramInterfaceSupported = true;
+ } else if (!m_backendSupport.caps.bits.bShaderImageLoadStoreSupported
+ && arbShaderImageLoadStore.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bShaderImageLoadStoreSupported = true;
+ } else if (!m_backendSupport.caps.bits.bNVPathRenderingSupported
+ && nvPathRendering.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bNVPathRenderingSupported = true;
+ } else if (!m_backendSupport.caps.bits.bNVAdvancedBlendSupported
+ && nvBlendAdvanced.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bNVAdvancedBlendSupported = true;
+ } else if (!m_backendSupport.caps.bits.bNVBlendCoherenceSupported
+ && nvBlendAdvancedCoherent.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bNVBlendCoherenceSupported = true;
+ } else if (!m_backendSupport.caps.bits.bKHRAdvancedBlendSupported
+ && khrBlendAdvanced.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bKHRAdvancedBlendSupported = true;
+ } else if (!m_backendSupport.caps.bits.bKHRBlendCoherenceSupported
+ && khrBlendAdvancedCoherent.compare(extensionString) == 0) {
+ m_backendSupport.caps.bits.bKHRBlendCoherenceSupported = true;
+ }
+ }
+
+ // always true for GL4.1 and GLES 3.1 devices
+ m_backendSupport.caps.bits.bMsTextureSupported = true;
+ m_backendSupport.caps.bits.bProgramPipelineSupported = true;
+
+ if (!isESCompatible()) {
+ // TODO: investigate GL 4.0 support
+ // we expect minimum GL 4.1 context anything beyond is handeled via extensions
+ // Tessellation is always supported on none ES systems which support >=GL4
+ m_backendSupport.caps.bits.bTessellationSupported = true;
+ // geometry shader is always supported on none ES systems which support >=GL4 ( actually
+ // 3.2 already )
+ m_backendSupport.caps.bits.bGeometrySupported = true;
+ } else {
+ // always true for GLES 3.1 devices
+ m_backendSupport.caps.bits.bComputeSupported = true;
+ m_backendSupport.caps.bits.bProgramInterfaceSupported = true;
+ m_backendSupport.caps.bits.bStorageBufferSupported = true;
+ m_backendSupport.caps.bits.bAtomicCounterBufferSupported = true;
+ m_backendSupport.caps.bits.bShaderImageLoadStoreSupported = true;
+ }
+
+#if !defined(QT_OPENGL_ES)
+ // Initialize extensions
+ m_nvPathRendering = QT3DS_NEW(m_Foundation.getAllocator(), QOpenGLExtension_NV_path_rendering)();
+ m_nvPathRendering->initializeOpenGLFunctions();
+ m_directStateAccess = QT3DS_NEW(m_Foundation.getAllocator(), QOpenGLExtension_EXT_direct_state_access)();
+ m_directStateAccess->initializeOpenGLFunctions();
+#endif
+ }
+
+ /// destructor
+ NVRenderBackendGL4Impl::~NVRenderBackendGL4Impl()
+ {
+#if !defined(QT_OPENGL_ES)
+ if (m_nvPathRendering)
+ NVDelete(m_Foundation.getAllocator(), m_nvPathRendering);
+ if (m_directStateAccess)
+ NVDelete(m_Foundation.getAllocator(), m_directStateAccess);
+#endif
+ }
+
+ void NVRenderBackendGL4Impl::DrawIndirect(NVRenderDrawMode::Enum drawMode, const void *indirect)
+ {
+ GL_CALL_EXTRA_FUNCTION(
+ glDrawArraysIndirect(m_Conversion.fromDrawModeToGL(
+ drawMode, m_backendSupport.caps.bits.bTessellationSupported),
+ indirect));
+ }
+
+ void NVRenderBackendGL4Impl::DrawIndexedIndirect(NVRenderDrawMode::Enum drawMode,
+ NVRenderComponentTypes::Enum type,
+ const void *indirect)
+ {
+ GL_CALL_EXTRA_FUNCTION(glDrawElementsIndirect(
+ m_Conversion.fromDrawModeToGL(drawMode,
+ m_backendSupport.caps.bits.bTessellationSupported),
+ m_Conversion.fromIndexBufferComponentsTypesToGL(type), indirect));
+ }
+
+ void NVRenderBackendGL4Impl::CreateTextureStorage2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ QT3DSU32 levels,
+ NVRenderTextureFormats::Enum internalFormat,
+ size_t width, size_t height)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
+
+ // up to now compressed is not supported
+ QT3DS_ASSERT(NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat));
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+ GLConversion::fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+
+ GL_CALL_EXTRA_FUNCTION(
+ glTexStorage2D(glTarget, levels, glInternalFormat, (GLsizei)width, (GLsizei)height));
+
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ void NVRenderBackendGL4Impl::SetMultisampledTextureData2D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, size_t samples,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height,
+ bool fixedsamplelocations)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_EXTRA_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
+
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
+ internalFormat, swizzleMode);
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ GLConversion::fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+ else if (NVRenderTextureFormats::isDepthTextureFormat(internalFormat))
+ m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+ GL_CALL_EXTRA_FUNCTION(glTexStorage2DMultisample(glTarget, (GLsizei)samples, glInternalFormat,
+ (GLsizei)width, (GLsizei)height,
+ fixedsamplelocations));
+
+ GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ NVRenderBackend::NVRenderBackendTessControlShaderObject
+ NVRenderBackendGL4Impl::CreateTessControlShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_TESS_CONTROL_SHADER));
+
+ if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
+ GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
+ shaderID = 0;
+ }
+
+ return (NVRenderBackend::NVRenderBackendTessControlShaderObject)shaderID;
+ }
+
+ NVRenderBackend::NVRenderBackendTessEvaluationShaderObject
+ NVRenderBackendGL4Impl::CreateTessEvaluationShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_TESS_EVALUATION_SHADER));
+
+ if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
+ GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
+ shaderID = 0;
+ }
+
+ return (NVRenderBackend::NVRenderBackendTessEvaluationShaderObject)shaderID;
+ }
+
+ NVRenderBackend::NVRenderBackendGeometryShaderObject
+ NVRenderBackendGL4Impl::CreateGeometryShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+#if defined(QT_OPENGL_ES)
+ GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_GEOMETRY_SHADER_EXT));
+#else
+ GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_GEOMETRY_SHADER));
+#endif
+ if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
+ GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
+ shaderID = 0;
+ }
+
+ return (NVRenderBackend::NVRenderBackendGeometryShaderObject)shaderID;
+ }
+
+ void NVRenderBackendGL4Impl::SetPatchVertexCount(NVRenderBackendInputAssemblerObject iao,
+ QT3DSU32 count)
+ {
+ QT3DS_ASSERT(iao);
+ QT3DS_ASSERT(count);
+ NVRenderBackendInputAssemblerGL *inputAssembler = (NVRenderBackendInputAssemblerGL *)iao;
+ inputAssembler->m_PatchVertexCount = count;
+ }
+
+ void NVRenderBackendGL4Impl::SetMemoryBarrier(NVRenderBufferBarrierFlags barriers)
+ {
+ GL_CALL_EXTRA_FUNCTION(glMemoryBarrier(m_Conversion.fromMemoryBarrierFlagsToGL(barriers)));
+ }
+
+ void NVRenderBackendGL4Impl::BindImageTexture(NVRenderBackendTextureObject to, QT3DSU32 unit,
+ QT3DSI32 level, bool layered, QT3DSI32 layer,
+ NVRenderImageAccessType::Enum access,
+ NVRenderTextureFormats::Enum format)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+
+ GL_CALL_EXTRA_FUNCTION(glBindImageTexture(unit, texID, level, layered, layer,
+ m_Conversion.fromImageAccessToGL(access),
+ m_Conversion.fromImageFormatToGL(format)));
+ }
+
+ QT3DSI32 NVRenderBackendGL4Impl::GetStorageBufferCount(NVRenderBackendShaderProgramObject po)
+ {
+ GLint numStorageBuffers = 0;
+ QT3DS_ASSERT(po);
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ if (m_backendSupport.caps.bits.bProgramInterfaceSupported)
+ GL_CALL_EXTRA_FUNCTION(glGetProgramInterfaceiv(programID, GL_SHADER_STORAGE_BLOCK,
+ GL_ACTIVE_RESOURCES, &numStorageBuffers));
+ return numStorageBuffers;
+ }
+
+ QT3DSI32
+ NVRenderBackendGL4Impl::GetStorageBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length,
+ char *nameBuf)
+ {
+ GLint bufferIndex = GL_INVALID_INDEX;
+
+ QT3DS_ASSERT(po);
+ QT3DS_ASSERT(length);
+ QT3DS_ASSERT(nameBuf);
+ QT3DS_ASSERT(bufferSize);
+ QT3DS_ASSERT(paramCount);
+
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ if (m_backendSupport.caps.bits.bProgramInterfaceSupported) {
+ GL_CALL_EXTRA_FUNCTION(glGetProgramResourceName(programID, GL_SHADER_STORAGE_BLOCK, id, nameBufSize,
+ length, nameBuf));
+
+ if (*length > 0) {
+#define QUERY_COUNT 3
+ GLsizei actualCount;
+ GLenum props[QUERY_COUNT] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE,
+ GL_NUM_ACTIVE_VARIABLES };
+ GLint params[QUERY_COUNT];
+ GL_CALL_EXTRA_FUNCTION(glGetProgramResourceiv(programID, GL_SHADER_STORAGE_BLOCK, id,
+ QUERY_COUNT, props, QUERY_COUNT, &actualCount,
+ params));
+
+ QT3DS_ASSERT(actualCount == QUERY_COUNT);
+
+ bufferIndex = params[0];
+ *bufferSize = params[1];
+ *paramCount = params[2];
+ }
+ }
+ return bufferIndex;
+ }
+
+ void NVRenderBackendGL4Impl::ProgramSetStorageBuffer(QT3DSU32 index,
+ NVRenderBackendBufferObject bo)
+ {
+ GL_CALL_EXTRA_FUNCTION(
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, HandleToID_cast(GLuint, size_t, bo)));
+ }
+
+ QT3DSI32 NVRenderBackendGL4Impl::GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject po)
+ {
+ GLint numAtomicCounterBuffers = 0;
+ QT3DS_ASSERT(po);
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ if (m_backendSupport.caps.bits.bProgramInterfaceSupported)
+ GL_CALL_EXTRA_FUNCTION(glGetProgramInterfaceiv(programID, GL_ATOMIC_COUNTER_BUFFER,
+ GL_ACTIVE_RESOURCES, &numAtomicCounterBuffers));
+ return numAtomicCounterBuffers;
+ }
+
+ QT3DSI32
+ NVRenderBackendGL4Impl::GetAtomicCounterBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize,
+ QT3DSI32 *paramCount, QT3DSI32 *bufferSize,
+ QT3DSI32 *length, char *nameBuf)
+ {
+ GLint bufferIndex = GL_INVALID_INDEX;
+
+ QT3DS_ASSERT(po);
+ QT3DS_ASSERT(length);
+ QT3DS_ASSERT(nameBuf);
+ QT3DS_ASSERT(bufferSize);
+ QT3DS_ASSERT(paramCount);
+
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ if (m_backendSupport.caps.bits.bProgramInterfaceSupported) {
+ {
+#define QUERY_COUNT 3
+ GLsizei actualCount;
+ GLenum props[QUERY_COUNT] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE,
+ GL_NUM_ACTIVE_VARIABLES };
+ GLint params[QUERY_COUNT];
+ GL_CALL_EXTRA_FUNCTION(glGetProgramResourceiv(programID, GL_ATOMIC_COUNTER_BUFFER, id,
+ QUERY_COUNT, props, QUERY_COUNT, &actualCount,
+ params));
+
+ QT3DS_ASSERT(actualCount == QUERY_COUNT);
+
+ bufferIndex = params[0];
+ *bufferSize = params[1];
+ *paramCount = params[2];
+
+ GLenum props1[1] = { GL_ATOMIC_COUNTER_BUFFER_INDEX };
+ GL_CALL_EXTRA_FUNCTION(glGetProgramResourceiv(programID, GL_UNIFORM, id, 1, props1, 1,
+ &actualCount, params));
+
+ QT3DS_ASSERT(actualCount == 1);
+
+ *nameBuf = '\0';
+ GL_CALL_EXTRA_FUNCTION(glGetProgramResourceName(programID, GL_UNIFORM, params[0], nameBufSize,
+ length, nameBuf));
+ }
+ }
+ return bufferIndex;
+ }
+
+ void NVRenderBackendGL4Impl::ProgramSetAtomicCounterBuffer(QT3DSU32 index,
+ NVRenderBackendBufferObject bo)
+ {
+ GL_CALL_EXTRA_FUNCTION(
+ glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, index, HandleToID_cast(GLuint, size_t, bo)));
+ }
+
+ void NVRenderBackendGL4Impl::SetConstantValue(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count,
+ const void *value, bool transpose)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GLenum glType = m_Conversion.fromPropertyDataTypesToShaderGL(type);
+
+ switch (glType) {
+ case GL_FLOAT:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform1fv(programID, id, count, (GLfloat *)value));
+ break;
+ case GL_FLOAT_VEC2:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform2fv(programID, id, count, (GLfloat *)value));
+ break;
+ case GL_FLOAT_VEC3:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform3fv(programID, id, count, (GLfloat *)value));
+ break;
+ case GL_FLOAT_VEC4:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform4fv(programID, id, count, (GLfloat *)value));
+ break;
+ case GL_INT:
+ case GL_BOOL:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform1iv(programID, id, count, (GLint *)value));
+ break;
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform2iv(programID, id, count, (GLint *)value));
+ break;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform3iv(programID, id, count, (GLint *)value));
+ break;
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform4iv(programID, id, count, (GLint *)value));
+ break;
+ case GL_FLOAT_MAT3:
+ GL_CALL_EXTRA_FUNCTION(
+ glProgramUniformMatrix3fv(programID, id, count, transpose, (GLfloat *)value));
+ break;
+ case GL_FLOAT_MAT4:
+ GL_CALL_EXTRA_FUNCTION(
+ glProgramUniformMatrix4fv(programID, id, count, transpose, (GLfloat *)value));
+ break;
+ case GL_IMAGE_2D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_CUBE: {
+ GLint sampler = *(GLint *)value;
+ GL_CALL_EXTRA_FUNCTION(glProgramUniform1i(programID, id, sampler));
+ } break;
+ default:
+ qCCritical(INTERNAL_ERROR, "Unknown shader type format %d", type);
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ NVRenderBackend::NVRenderBackendComputeShaderObject
+ NVRenderBackendGL4Impl::CreateComputeShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ GLuint shaderID = m_glExtraFunctions->glCreateShader(GL_COMPUTE_SHADER);
+
+ if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
+ GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
+ shaderID = 0;
+ }
+
+ return (NVRenderBackend::NVRenderBackendComputeShaderObject)shaderID;
+ }
+
+ void NVRenderBackendGL4Impl::DispatchCompute(NVRenderBackendShaderProgramObject,
+ QT3DSU32 numGroupsX, QT3DSU32 numGroupsY,
+ QT3DSU32 numGroupsZ)
+ {
+ GL_CALL_EXTRA_FUNCTION(glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ));
+ }
+
+ NVRenderBackend::NVRenderBackendProgramPipeline NVRenderBackendGL4Impl::CreateProgramPipeline()
+ {
+ GLuint pipeline;
+ GL_CALL_EXTRA_FUNCTION(glGenProgramPipelines(1, &pipeline));
+
+ return NVRenderBackend::NVRenderBackendProgramPipeline(pipeline);
+ }
+
+ void NVRenderBackendGL4Impl::ReleaseProgramPipeline(NVRenderBackendProgramPipeline ppo)
+ {
+ GLuint pipeline = HandleToID_cast(GLuint, size_t, ppo);
+ GL_CALL_EXTRA_FUNCTION(glDeleteProgramPipelines(1, &pipeline));
+ }
+
+ void NVRenderBackendGL4Impl::SetActiveProgramPipeline(NVRenderBackendProgramPipeline ppo)
+ {
+ GLuint pipeline = HandleToID_cast(GLuint, size_t, ppo);
+
+ GL_CALL_EXTRA_FUNCTION(glBindProgramPipeline(pipeline));
+ }
+
+ void NVRenderBackendGL4Impl::SetProgramStages(NVRenderBackendProgramPipeline ppo,
+ NVRenderShaderTypeFlags flags,
+ NVRenderBackendShaderProgramObject po)
+ {
+ GLuint pipeline = HandleToID_cast(GLuint, size_t, ppo);
+ GLuint programID = 0;
+
+ if (po) {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ programID = static_cast<GLuint>(pProgram->m_ProgramID);
+ }
+
+ GL_CALL_EXTRA_FUNCTION(
+ glUseProgramStages(pipeline, m_Conversion.fromShaderTypeFlagsToGL(flags), programID));
+ }
+
+ void NVRenderBackendGL4Impl::SetBlendEquation(const NVRenderBlendEquationArgument &pBlendEquArg)
+ {
+ if (m_backendSupport.caps.bits.bNVAdvancedBlendSupported ||
+ m_backendSupport.caps.bits.bKHRAdvancedBlendSupported)
+ GL_CALL_EXTRA_FUNCTION(glBlendEquation(m_Conversion.fromBlendEquationToGL(
+ pBlendEquArg.m_RGBEquation, m_backendSupport.caps.bits.bNVAdvancedBlendSupported,
+ m_backendSupport.caps.bits.bKHRAdvancedBlendSupported)));
+ }
+
+ void NVRenderBackendGL4Impl::SetBlendBarrier(void)
+ {
+ if (m_backendSupport.caps.bits.bNVAdvancedBlendSupported)
+ GL_CALL_QT3DS_EXT(glBlendBarrierNV());
+ }
+
+ NVRenderBackend::NVRenderBackendPathObject
+ NVRenderBackendGL4Impl::CreatePathNVObject(size_t range)
+ {
+ GLuint pathID = GL_CALL_NVPATH_EXT(glGenPathsNV((GLsizei)range));
+
+ return NVRenderBackend::NVRenderBackendPathObject(pathID);
+ }
+ void NVRenderBackendGL4Impl::SetPathSpecification(NVRenderBackendPathObject inPathObject,
+ NVConstDataRef<QT3DSU8> inPathCommands,
+ NVConstDataRef<QT3DSF32> inPathCoords)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, inPathObject);
+ GL_CALL_NVPATH_EXT(glPathCommandsNV(pathID, inPathCommands.size(), inPathCommands.begin(),
+ inPathCoords.size(), GL_FLOAT, inPathCoords.begin()));
+ }
+
+ NVBounds3
+ NVRenderBackendGL4Impl::GetPathObjectBoundingBox(NVRenderBackendPathObject inPathObject)
+ {
+ float data[4];
+ GL_CALL_NVPATH_EXT(glGetPathParameterfvNV(
+ HandleToID_cast(GLuint, size_t, inPathObject),
+ GL_PATH_OBJECT_BOUNDING_BOX_NV, data));
+ return NVBounds3(QT3DSVec3(data[0], data[1], 0.0f), QT3DSVec3(data[2], data[3], 0.0f));
+ }
+
+ NVBounds3 NVRenderBackendGL4Impl::GetPathObjectFillBox(NVRenderBackendPathObject inPathObject)
+ {
+ float data[4];
+ GL_CALL_NVPATH_EXT(glGetPathParameterfvNV(
+ HandleToID_cast(GLuint, size_t, inPathObject),
+ GL_PATH_FILL_BOUNDING_BOX_NV, data));
+ return NVBounds3(QT3DSVec3(data[0], data[1], 0.0f), QT3DSVec3(data[2], data[3], 0.0f));
+ }
+
+ NVBounds3 NVRenderBackendGL4Impl::GetPathObjectStrokeBox(NVRenderBackendPathObject inPathObject)
+ {
+ float data[4];
+ GL_CALL_NVPATH_EXT(glGetPathParameterfvNV(
+ HandleToID_cast(GLuint, size_t, inPathObject),
+ GL_PATH_STROKE_BOUNDING_BOX_NV, data));
+ return NVBounds3(QT3DSVec3(data[0], data[1], 0.0f), QT3DSVec3(data[2], data[3], 0.0f));
+ }
+
+ void NVRenderBackendGL4Impl::SetStrokeWidth(NVRenderBackendPathObject inPathObject,
+ QT3DSF32 inStrokeWidth)
+ {
+ GL_CALL_NVPATH_EXT(glPathParameterfNV(HandleToID_cast(GLuint, size_t, inPathObject),
+ GL_PATH_STROKE_WIDTH_NV, inStrokeWidth));
+ }
+
+ void NVRenderBackendGL4Impl::SetPathProjectionMatrix(const QT3DSMat44 inPathProjection)
+ {
+#if defined(QT_OPENGL_ES)
+ NVRENDER_BACKEND_UNUSED(inPathProjection);
+#else
+ GL_CALL_DIRECTSTATE_EXT(glMatrixLoadfEXT(GL_PROJECTION, inPathProjection.front()));
+#endif
+ }
+
+ void NVRenderBackendGL4Impl::SetPathModelViewMatrix(const QT3DSMat44 inPathModelview)
+ {
+#if defined(QT_OPENGL_ES)
+ NVRENDER_BACKEND_UNUSED(inPathModelview);
+#else
+ GL_CALL_DIRECTSTATE_EXT(glMatrixLoadfEXT(GL_MODELVIEW, inPathModelview.front()));
+#endif
+ }
+
+ void NVRenderBackendGL4Impl::SetPathStencilDepthOffset(QT3DSF32 inSlope, QT3DSF32 inBias)
+ {
+ GL_CALL_NVPATH_EXT(glPathStencilDepthOffsetNV(inSlope, inBias));
+ }
+
+ void NVRenderBackendGL4Impl::SetPathCoverDepthFunc(NVRenderBoolOp::Enum inDepthFunction)
+ {
+ GL_CALL_NVPATH_EXT(glPathCoverDepthFuncNV(m_Conversion.fromBoolOpToGL(inDepthFunction)));
+ }
+
+ void NVRenderBackendGL4Impl::StencilStrokePath(NVRenderBackendPathObject inPathObject)
+ {
+ GL_CALL_NVPATH_EXT(glStencilStrokePathNV(HandleToID_cast(GLuint, size_t, inPathObject), 0x1, (GLuint)~0));
+ }
+
+ void NVRenderBackendGL4Impl::StencilFillPath(NVRenderBackendPathObject inPathObject)
+ {
+ GL_CALL_NVPATH_EXT(glStencilFillPathNV(HandleToID_cast(GLuint, size_t, inPathObject),
+ GL_COUNT_UP_NV, (GLuint)~0));
+ }
+
+ void NVRenderBackendGL4Impl::ReleasePathNVObject(NVRenderBackendPathObject po, size_t range)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glDeletePathsNV(pathID, (GLsizei)range));
+ }
+
+ void NVRenderBackendGL4Impl::StencilFillPathInstanced(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathFormatType::Enum type,
+ const void *charCodes, NVRenderPathFillMode::Enum fillMode, QT3DSU32 stencilMask,
+ NVRenderPathTransformType::Enum transformType, const QT3DSF32 *transformValues)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glStencilFillPathInstancedNV(
+ (GLsizei)numPaths, m_Conversion.fromPathTypeToGL(type), charCodes, pathID,
+ m_Conversion.fromPathFillModeToGL(fillMode), stencilMask,
+ m_Conversion.fromPathTransformToGL(transformType), transformValues));
+ }
+
+ void NVRenderBackendGL4Impl::StencilStrokePathInstancedN(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathFormatType::Enum type,
+ const void *charCodes, QT3DSI32 stencilRef, QT3DSU32 stencilMask,
+ NVRenderPathTransformType::Enum transformType, const QT3DSF32 *transformValues)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glStencilStrokePathInstancedNV(
+ (GLsizei)numPaths, m_Conversion.fromPathTypeToGL(type), charCodes, pathID, stencilRef,
+ stencilMask, m_Conversion.fromPathTransformToGL(transformType), transformValues));
+ }
+
+ void NVRenderBackendGL4Impl::CoverFillPathInstanced(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathFormatType::Enum type,
+ const void *charCodes, NVRenderPathCoverMode::Enum coverMode,
+ NVRenderPathTransformType::Enum transformType, const QT3DSF32 *transformValues)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glCoverFillPathInstancedNV(
+ (GLsizei)numPaths, m_Conversion.fromPathTypeToGL(type), charCodes, pathID,
+ m_Conversion.fromPathCoverModeToGL(coverMode),
+ m_Conversion.fromPathTransformToGL(transformType), transformValues));
+ }
+
+ void NVRenderBackendGL4Impl::CoverStrokePathInstanced(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathFormatType::Enum type,
+ const void *charCodes, NVRenderPathCoverMode::Enum coverMode,
+ NVRenderPathTransformType::Enum transformType, const QT3DSF32 *transformValues)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glCoverStrokePathInstancedNV(
+ (GLsizei)numPaths, m_Conversion.fromPathTypeToGL(type), charCodes, pathID,
+ m_Conversion.fromPathCoverModeToGL(coverMode),
+ m_Conversion.fromPathTransformToGL(transformType), transformValues));
+ }
+
+ void NVRenderBackendGL4Impl::LoadPathGlyphs(
+ NVRenderBackendPathObject po, NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle, size_t numGlyphs, NVRenderPathFormatType::Enum type,
+ const void *charCodes, NVRenderPathMissingGlyphs::Enum handleMissingGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+ GLuint pathTemplateID = (pathParameterTemplate == NULL)
+ ? ~0
+ : HandleToID_cast(GLuint, size_t, pathParameterTemplate);
+
+ GL_CALL_NVPATH_EXT(glPathGlyphsNV(pathID, m_Conversion.fromPathFontTargetToGL(fontTarget), fontName,
+ m_Conversion.fromPathFontStyleToGL(fontStyle), (GLsizei)numGlyphs,
+ m_Conversion.fromPathTypeToGL(type), charCodes,
+ m_Conversion.fromPathMissingGlyphsToGL(handleMissingGlyphs),
+ pathTemplateID, emScale));
+ }
+
+ NVRenderPathReturnValues::Enum NVRenderBackendGL4Impl::LoadPathGlyphsIndexed(
+ NVRenderBackendPathObject po, NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle, QT3DSU32 firstGlyphIndex, size_t numGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+ GLuint pathTemplateID = (pathParameterTemplate == NULL)
+ ? ~0
+ : HandleToID_cast(GLuint, size_t, pathParameterTemplate);
+ GLenum glRet = 0;
+
+ glRet = GL_CALL_QT3DS_EXT(glPathGlyphIndexArrayNV(
+ pathID, m_Conversion.fromPathFontTargetToGL(fontTarget), fontName,
+ m_Conversion.fromPathFontStyleToGL(fontStyle), firstGlyphIndex,
+ (GLsizei)numGlyphs, pathTemplateID, emScale));
+
+ return m_Conversion.fromGLToPathFontReturn(glRet);
+ }
+
+ NVRenderBackend::NVRenderBackendPathObject NVRenderBackendGL4Impl::LoadPathGlyphsIndexedRange(
+ NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle, NVRenderBackendPathObject pathParameterTemplate,
+ QT3DSF32 emScale, QT3DSU32 *count)
+ {
+ GLuint pathTemplateID = (pathParameterTemplate == NULL)
+ ? ~0
+ : HandleToID_cast(GLuint, size_t, pathParameterTemplate);
+ GLenum glRet = 0;
+ GLuint baseAndCount[2] = { 0, 0 };
+
+ glRet = GL_CALL_QT3DS_EXT(glPathGlyphIndexRangeNV(m_Conversion.fromPathFontTargetToGL(fontTarget),
+ fontName,
+ m_Conversion.fromPathFontStyleToGL(fontStyle),
+ pathTemplateID, emScale, baseAndCount));
+
+ if (count)
+ *count = baseAndCount[1];
+
+ return NVRenderBackend::NVRenderBackendPathObject(baseAndCount[0]);
+ }
+
+ void NVRenderBackendGL4Impl::LoadPathGlyphRange(
+ NVRenderBackendPathObject po, NVRenderPathFontTarget::Enum fontTarget, const void *fontName,
+ NVRenderPathFontStyleFlags fontStyle, QT3DSU32 firstGlyph, size_t numGlyphs,
+ NVRenderPathMissingGlyphs::Enum handleMissingGlyphs,
+ NVRenderBackendPathObject pathParameterTemplate, QT3DSF32 emScale)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+ GLuint pathTemplateID = (pathParameterTemplate == NULL)
+ ? ~0
+ : HandleToID_cast(GLuint, size_t, pathParameterTemplate);
+
+ GL_CALL_NVPATH_EXT(glPathGlyphRangeNV(
+ pathID, m_Conversion.fromPathFontTargetToGL(fontTarget), fontName,
+ m_Conversion.fromPathFontStyleToGL(fontStyle), firstGlyph, (GLsizei)numGlyphs,
+ m_Conversion.fromPathMissingGlyphsToGL(handleMissingGlyphs), pathTemplateID, emScale));
+ }
+
+ void NVRenderBackendGL4Impl::GetPathMetrics(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathGlyphFontMetricFlags metricQueryMask,
+ NVRenderPathFormatType::Enum type,
+ const void *charCodes, size_t stride,
+ QT3DSF32 *metrics)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glGetPathMetricsNV(m_Conversion.fromPathMetricQueryFlagsToGL(metricQueryMask),
+ (GLsizei)numPaths, m_Conversion.fromPathTypeToGL(type),
+ charCodes, pathID, (GLsizei)stride, metrics));
+ }
+
+ void
+ NVRenderBackendGL4Impl::GetPathMetricsRange(NVRenderBackendPathObject po, size_t numPaths,
+ NVRenderPathGlyphFontMetricFlags metricQueryMask,
+ size_t stride, QT3DSF32 *metrics)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glGetPathMetricRangeNV(m_Conversion.fromPathMetricQueryFlagsToGL(metricQueryMask),
+ pathID, (GLsizei)numPaths, (GLsizei)stride, metrics));
+ }
+
+ void NVRenderBackendGL4Impl::GetPathSpacing(
+ NVRenderBackendPathObject po, size_t numPaths, NVRenderPathListMode::Enum pathListMode,
+ NVRenderPathFormatType::Enum type, const void *charCodes, QT3DSF32 advanceScale,
+ QT3DSF32 kerningScale, NVRenderPathTransformType::Enum transformType, QT3DSF32 *spacing)
+ {
+ GLuint pathID = HandleToID_cast(GLuint, size_t, po);
+
+ GL_CALL_NVPATH_EXT(glGetPathSpacingNV(m_Conversion.fromPathListModeToGL(pathListMode),
+ (GLsizei)numPaths, m_Conversion.fromPathTypeToGL(type),
+ charCodes, pathID, advanceScale, kerningScale,
+ m_Conversion.fromPathTransformToGL(transformType), spacing));
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp
new file mode 100644
index 00000000..ee496c61
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderBackendGLBase.cpp
@@ -0,0 +1,2160 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render/backends/gl/Qt3DSRenderBackendGLBase.h"
+#include "render/backends/gl/Qt3DSRenderBackendInputAssemblerGL.h"
+#include "render/backends/gl/Qt3DSRenderBackendShaderProgramGL.h"
+#include "render/backends/gl/Qt3DSRenderBackendRenderStatesGL.h"
+#include "foundation/StringTable.h"
+
+#define GL_CALL_FUNCTION(x) m_glFunctions->x; checkGLError();
+#define GL_CALL_EXTRA_FUNCTION(x) m_glExtraFunctions->x; checkGLError();
+
+namespace qt3ds {
+namespace render {
+
+ /// constructor
+ NVRenderBackendGLBase::NVRenderBackendGLBase(NVFoundationBase &fnd,
+ qt3ds::foundation::IStringTable &stringTable,
+ const QSurfaceFormat &format)
+ : mRefCount(0)
+ , m_Foundation(fnd)
+ , m_StringTable(stringTable)
+ , m_Conversion()
+ , m_Extensions(m_Foundation.getAllocator(), "NVRenderBackendGLBase::m_Extensions")
+ , m_MaxAttribCount(0)
+ , m_DrawBuffersArray(m_Foundation.getAllocator(),
+ "NVRenderBackendGLBase::m_DrawBuffersArray")
+ , m_format(format)
+ {
+ m_glFunctions = new QOpenGLFunctions;
+ m_glFunctions->initializeOpenGLFunctions();
+ m_glExtraFunctions = new QOpenGLExtraFunctions;
+ m_glExtraFunctions->initializeOpenGLFunctions();
+
+ // internal state tracker
+ m_pCurrentRasterizerState =
+ QT3DS_NEW(m_Foundation.getAllocator(), NVRenderBackendRasterizerStateGL)();
+ m_pCurrentDepthStencilState =
+ QT3DS_NEW(m_Foundation.getAllocator(), NVRenderBackendDepthStencilStateGL)();
+ }
+ /// destructor
+ NVRenderBackendGLBase::~NVRenderBackendGLBase()
+ {
+ if (m_pCurrentRasterizerState)
+ NVDelete(m_Foundation.getAllocator(), m_pCurrentRasterizerState);
+ if (m_pCurrentDepthStencilState)
+ NVDelete(m_Foundation.getAllocator(), m_pCurrentDepthStencilState);
+ if (m_glFunctions)
+ delete m_glFunctions;
+ if (m_glExtraFunctions)
+ delete m_glExtraFunctions;
+ }
+
+ NVRenderContextType NVRenderBackendGLBase::GetRenderContextType() const
+ {
+ if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
+ if (m_format.majorVersion() == 2)
+ return NVRenderContextValues::GLES2;
+
+ if (m_format.majorVersion() == 3) {
+ if (m_format.minorVersion() >= 1)
+ return NVRenderContextValues::GLES3PLUS;
+ else
+ return NVRenderContextValues::GLES3;
+ }
+ } else if (m_format.majorVersion() == 2) {
+ return NVRenderContextValues::GL2;
+ } else if (m_format.majorVersion() == 3) {
+ return NVRenderContextValues::GL3;
+ } else if (m_format.majorVersion() == 4) {
+ return NVRenderContextValues::GL4;
+ }
+
+ return NVRenderContextValues::NullContext;
+ }
+
+ bool NVRenderBackendGLBase::isESCompatible() const
+ {
+ return m_format.renderableType() == QSurfaceFormat::OpenGLES;
+ }
+
+ const char *NVRenderBackendGLBase::GetShadingLanguageVersion()
+ {
+ const char *retval = (const char *)GL_CALL_FUNCTION(
+ glGetString(GL_SHADING_LANGUAGE_VERSION));
+ if (retval == NULL)
+ return "";
+
+ return retval;
+ }
+
+ QT3DSU32
+ NVRenderBackendGLBase::GetMaxCombinedTextureUnits()
+ {
+ QT3DSI32 maxUnits;
+ GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits));
+ return maxUnits;
+ }
+
+ bool NVRenderBackendGLBase::GetRenderBackendCap(
+ NVRenderBackend::NVRenderBackendCaps::Enum inCap) const
+ {
+ bool bSupported = false;
+
+ switch (inCap) {
+ case NVRenderBackendCaps::FpRenderTarget:
+ bSupported = m_backendSupport.caps.bits.bFPRenderTargetsSupported;
+ break;
+ case NVRenderBackendCaps::DepthStencilTexture:
+ bSupported = m_backendSupport.caps.bits.bDepthStencilSupported;
+ break;
+ case NVRenderBackendCaps::ConstantBuffer:
+ bSupported = m_backendSupport.caps.bits.bConstantBufferSupported;
+ break;
+ case NVRenderBackendCaps::DxtImages:
+ bSupported = m_backendSupport.caps.bits.bDXTImagesSupported;
+ break;
+ case NVRenderBackendCaps::MsTexture:
+ bSupported = m_backendSupport.caps.bits.bMsTextureSupported;
+ break;
+ case NVRenderBackendCaps::TexSwizzle:
+ bSupported = m_backendSupport.caps.bits.bTextureSwizzleSupported;
+ break;
+ case NVRenderBackendCaps::FastBlits:
+ bSupported = m_backendSupport.caps.bits.bFastBlitsSupported;
+ break;
+ case NVRenderBackendCaps::Tessellation:
+ bSupported = m_backendSupport.caps.bits.bTessellationSupported;
+ break;
+ case NVRenderBackendCaps::Compute:
+ bSupported = m_backendSupport.caps.bits.bComputeSupported;
+ break;
+ case NVRenderBackendCaps::Geometry:
+ bSupported = m_backendSupport.caps.bits.bGeometrySupported;
+ break;
+ case NVRenderBackendCaps::SampleQuery: {
+ // On the following context sample query is not supported
+ NVRenderContextType noSamplesQuerySupportedContextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+ NVRenderContextType ctxType = GetRenderContextType();
+ bSupported = !(ctxType & noSamplesQuerySupportedContextFlags);
+ } break;
+ case NVRenderBackendCaps::TimerQuery:
+ bSupported = m_backendSupport.caps.bits.bTimerQuerySupported;
+ break;
+ case NVRenderBackendCaps::CommandSync: {
+ // On the following context sync objects are not supported
+ NVRenderContextType noSyncObjectSupportedContextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+ NVRenderContextType ctxType = GetRenderContextType();
+ bSupported = !(ctxType & noSyncObjectSupportedContextFlags);
+ } break;
+ case NVRenderBackendCaps::TextureArray: {
+ // On the following context texture arrays are not supported
+ NVRenderContextType noTextureArraySupportedContextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+ NVRenderContextType ctxType = GetRenderContextType();
+ bSupported = !(ctxType & noTextureArraySupportedContextFlags);
+ } break;
+ case NVRenderBackendCaps::StorageBuffer:
+ bSupported = m_backendSupport.caps.bits.bStorageBufferSupported;
+ break;
+ case NVRenderBackendCaps::AtomicCounterBuffer:
+ bSupported = m_backendSupport.caps.bits.bAtomicCounterBufferSupported;
+ break;
+ case NVRenderBackendCaps::ShaderImageLoadStore:
+ bSupported = m_backendSupport.caps.bits.bShaderImageLoadStoreSupported;
+ break;
+ case NVRenderBackendCaps::ProgramPipeline:
+ bSupported = m_backendSupport.caps.bits.bProgramPipelineSupported;
+ break;
+ case NVRenderBackendCaps::PathRendering:
+ bSupported = m_backendSupport.caps.bits.bNVPathRenderingSupported;
+ break;
+ case NVRenderBackendCaps::AdvancedBlend:
+ bSupported = m_backendSupport.caps.bits.bNVAdvancedBlendSupported |
+ m_backendSupport.caps.bits.bKHRAdvancedBlendSupported;
+ break;
+ case NVRenderBackendCaps::AdvancedBlendKHR:
+ bSupported = m_backendSupport.caps.bits.bKHRAdvancedBlendSupported;
+ break;
+ case NVRenderBackendCaps::BlendCoherency:
+ bSupported = m_backendSupport.caps.bits.bNVBlendCoherenceSupported |
+ m_backendSupport.caps.bits.bKHRBlendCoherenceSupported;
+ break;
+ case NVRenderBackendCaps::gpuShader5:
+ bSupported = m_backendSupport.caps.bits.bGPUShader5ExtensionSupported;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ bSupported = false;
+ break;
+ }
+
+ return bSupported;
+ }
+
+ void NVRenderBackendGLBase::GetRenderBackendValue(NVRenderBackendQuery::Enum inQuery,
+ QT3DSI32 *params) const
+ {
+ if (params) {
+ switch (inQuery) {
+ case NVRenderBackendQuery::MaxTextureSize:
+ GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_TEXTURE_SIZE, params));
+ break;
+ case NVRenderBackendQuery::MaxTextureArrayLayers: {
+ NVRenderContextType noTextureArraySupportedContextFlags(
+ NVRenderContextValues::GL2 | NVRenderContextValues::GLES2);
+ NVRenderContextType ctxType = GetRenderContextType();
+ if (!(ctxType & noTextureArraySupportedContextFlags)) {
+ GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, params));
+ } else {
+ *params = 0;
+ }
+ } break;
+ case NVRenderBackendQuery::MaxConstantBufferSlots: {
+ NVRenderContextType noConstantBufferSupportedContextFlags(
+ NVRenderContextValues::GL2 | NVRenderContextValues::GLES2);
+ NVRenderContextType ctxType = GetRenderContextType();
+ if (!(ctxType & noConstantBufferSupportedContextFlags)) {
+ GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, params));
+ } else {
+ *params = 0;
+ }
+ } break;
+ case NVRenderBackendQuery::MaxConstantBufferBlockSize: {
+ NVRenderContextType noConstantBufferSupportedContextFlags(
+ NVRenderContextValues::GL2 | NVRenderContextValues::GLES2);
+ NVRenderContextType ctxType = GetRenderContextType();
+ if (!(ctxType & noConstantBufferSupportedContextFlags)) {
+ GL_CALL_FUNCTION(glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, params));
+ } else {
+ *params = 0;
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ *params = 0;
+ break;
+ }
+ }
+ }
+
+ QT3DSU32
+ NVRenderBackendGLBase::GetDepthBits() const
+ {
+ QT3DSI32 depthBits;
+ GL_CALL_FUNCTION(glGetIntegerv(GL_DEPTH_BITS, &depthBits));
+ return depthBits;
+ }
+
+ QT3DSU32
+ NVRenderBackendGLBase::GetStencilBits() const
+ {
+ QT3DSI32 stencilBits;
+ GL_CALL_FUNCTION(glGetIntegerv(GL_STENCIL_BITS, &stencilBits));
+ return stencilBits;
+ }
+
+ void NVRenderBackendGLBase::SetMultisample(bool bEnable)
+ {
+ QT3DS_ASSERT(m_backendSupport.caps.bits.bMsTextureSupported || !bEnable);
+ // For GL ES explicit multisample enabling is not needed
+ // and does not exist
+ NVRenderContextType noMsaaEnableContextFlags(NVRenderContextValues::GLES2
+ | NVRenderContextValues::GLES3
+ | NVRenderContextValues::GLES3PLUS);
+ NVRenderContextType ctxType = GetRenderContextType();
+ if (!(ctxType & noMsaaEnableContextFlags)) {
+ SetRenderState(bEnable, NVRenderState::Multisample);
+ }
+ }
+
+ void NVRenderBackendGLBase::SetRenderState(bool bEnable, const NVRenderState::Enum value)
+ {
+ if (value == NVRenderState::DepthWrite) {
+ GL_CALL_FUNCTION(glDepthMask(bEnable));
+ } else {
+ if (bEnable) {
+ GL_CALL_FUNCTION(glEnable(m_Conversion.fromRenderStateToGL(value)));
+ } else {
+ GL_CALL_FUNCTION(glDisable(m_Conversion.fromRenderStateToGL(value)));
+ }
+ }
+ }
+
+ NVRenderBackend::NVRenderBackendDepthStencilStateObject
+ NVRenderBackendGLBase::CreateDepthStencilState(
+ bool enableDepth, bool depthMask, NVRenderBoolOp::Enum depthFunc, bool enableStencil,
+ NVRenderStencilFunctionArgument &stencilFuncFront,
+ NVRenderStencilFunctionArgument &stencilFuncBack,
+ NVRenderStencilOperationArgument &depthStencilOpFront,
+ NVRenderStencilOperationArgument &depthStencilOpBack)
+ {
+ NVRenderBackendDepthStencilStateGL *retval =
+ QT3DS_NEW(m_Foundation.getAllocator(), NVRenderBackendDepthStencilStateGL)(
+ enableDepth, depthMask, depthFunc, enableStencil, stencilFuncFront, stencilFuncBack,
+ depthStencilOpFront, depthStencilOpBack);
+
+ return (NVRenderBackend::NVRenderBackendDepthStencilStateObject)retval;
+ }
+
+ void NVRenderBackendGLBase::ReleaseDepthStencilState(
+ NVRenderBackendDepthStencilStateObject inDepthStencilState)
+ {
+ NVRenderBackendDepthStencilStateGL *inputState =
+ (NVRenderBackendDepthStencilStateGL *)inDepthStencilState;
+ if (inputState)
+ NVDelete(m_Foundation.getAllocator(), inputState);
+ }
+
+ NVRenderBackend::NVRenderBackendRasterizerStateObject
+ NVRenderBackendGLBase::CreateRasterizerState(QT3DSF32 depthBias, QT3DSF32 depthScale,
+ NVRenderFaces::Enum cullFace)
+ {
+ NVRenderBackendRasterizerStateGL *retval =
+ QT3DS_NEW(m_Foundation.getAllocator(),
+ NVRenderBackendRasterizerStateGL)(depthBias, depthScale, cullFace);
+
+ return (NVRenderBackend::NVRenderBackendRasterizerStateObject)retval;
+ }
+
+ void NVRenderBackendGLBase::ReleaseRasterizerState(
+ NVRenderBackendRasterizerStateObject rasterizerState)
+ {
+ NVRenderBackendRasterizerStateGL *inputState =
+ (NVRenderBackendRasterizerStateGL *)rasterizerState;
+ if (inputState)
+ NVDelete(m_Foundation.getAllocator(), inputState);
+ }
+
+ void NVRenderBackendGLBase::SetDepthStencilState(
+ NVRenderBackendDepthStencilStateObject inDepthStencilState)
+ {
+ NVRenderBackendDepthStencilStateGL *inputState =
+ (NVRenderBackendDepthStencilStateGL *)inDepthStencilState;
+ if (inputState && !(*m_pCurrentDepthStencilState == *inputState)) {
+ // we check on a per single state base
+ if (inputState->m_DepthEnable != m_pCurrentDepthStencilState->m_DepthEnable) {
+ SetRenderState(inputState->m_DepthEnable, NVRenderState::DepthTest);
+ m_pCurrentDepthStencilState->m_DepthEnable = inputState->m_DepthEnable;
+ }
+ if (inputState->m_StencilEnable != m_pCurrentDepthStencilState->m_StencilEnable) {
+ SetRenderState(inputState->m_StencilEnable, NVRenderState::StencilTest);
+ m_pCurrentDepthStencilState->m_StencilEnable = inputState->m_StencilEnable;
+ }
+
+ if (inputState->m_DepthMask != m_pCurrentDepthStencilState->m_DepthMask) {
+ GL_CALL_FUNCTION(glDepthMask(inputState->m_DepthMask));
+ m_pCurrentDepthStencilState->m_DepthMask = inputState->m_DepthMask;
+ }
+
+ if (inputState->m_DepthFunc != m_pCurrentDepthStencilState->m_DepthFunc) {
+ GL_CALL_FUNCTION(glDepthFunc(m_Conversion.fromBoolOpToGL(inputState->m_DepthFunc)));
+ m_pCurrentDepthStencilState->m_DepthFunc = inputState->m_DepthFunc;
+ }
+
+ if (!(inputState->m_DepthStencilOpFront
+ == m_pCurrentDepthStencilState->m_DepthStencilOpFront)) {
+ GL_CALL_FUNCTION(glStencilOpSeparate(
+ GL_FRONT,
+ m_Conversion.fromStencilOpToGL(inputState->m_DepthStencilOpFront.m_StencilFail),
+ m_Conversion.fromStencilOpToGL(inputState->m_DepthStencilOpFront.m_DepthFail),
+ m_Conversion.fromStencilOpToGL(inputState->m_DepthStencilOpFront.m_DepthPass)));
+ m_pCurrentDepthStencilState->m_DepthStencilOpFront =
+ inputState->m_DepthStencilOpFront;
+ }
+
+ if (!(inputState->m_DepthStencilOpBack
+ == m_pCurrentDepthStencilState->m_DepthStencilOpBack)) {
+ GL_CALL_FUNCTION(glStencilOpSeparate(
+ GL_BACK,
+ m_Conversion.fromStencilOpToGL(inputState->m_DepthStencilOpBack.m_StencilFail),
+ m_Conversion.fromStencilOpToGL(inputState->m_DepthStencilOpBack.m_DepthFail),
+ m_Conversion.fromStencilOpToGL(inputState->m_DepthStencilOpBack.m_DepthPass)));
+ m_pCurrentDepthStencilState->m_DepthStencilOpBack =
+ inputState->m_DepthStencilOpBack;
+ }
+
+ if (!(inputState->m_StencilFuncFront
+ == m_pCurrentDepthStencilState->m_StencilFuncFront)) {
+ GL_CALL_FUNCTION(glStencilFuncSeparate(
+ GL_FRONT,
+ m_Conversion.fromBoolOpToGL(inputState->m_StencilFuncFront.m_Function),
+ inputState->m_StencilFuncFront.m_ReferenceValue,
+ inputState->m_StencilFuncFront.m_Mask));
+ m_pCurrentDepthStencilState->m_StencilFuncFront = inputState->m_StencilFuncFront;
+ }
+
+ if (!(inputState->m_StencilFuncBack
+ == m_pCurrentDepthStencilState->m_StencilFuncBack)) {
+ GL_CALL_FUNCTION(glStencilFuncSeparate(
+ GL_BACK, m_Conversion.fromBoolOpToGL(inputState->m_StencilFuncBack.m_Function),
+ inputState->m_StencilFuncBack.m_ReferenceValue,
+ inputState->m_StencilFuncBack.m_Mask));
+ m_pCurrentDepthStencilState->m_StencilFuncBack = inputState->m_StencilFuncBack;
+ }
+ }
+ }
+
+ void
+ NVRenderBackendGLBase::SetRasterizerState(NVRenderBackendRasterizerStateObject rasterizerState)
+ {
+ NVRenderBackendRasterizerStateGL *inputState =
+ (NVRenderBackendRasterizerStateGL *)rasterizerState;
+ if (inputState && !(*m_pCurrentRasterizerState == *inputState)) {
+ // store current state
+ *m_pCurrentRasterizerState = *inputState;
+
+ if (m_pCurrentRasterizerState->m_DepthBias != 0.0
+ || m_pCurrentRasterizerState->m_DepthScale != 0.0) {
+ GL_CALL_FUNCTION(glEnable(GL_POLYGON_OFFSET_FILL));
+ } else {
+ GL_CALL_FUNCTION(glDisable(GL_POLYGON_OFFSET_FILL));
+ }
+
+ GL_CALL_FUNCTION(glPolygonOffset(m_pCurrentRasterizerState->m_DepthBias,
+ m_pCurrentRasterizerState->m_DepthScale));
+
+ GL_CALL_FUNCTION(
+ glCullFace(m_Conversion.fromFacesToGL(m_pCurrentRasterizerState->m_CullFace)));
+ }
+ }
+
+ bool NVRenderBackendGLBase::GetRenderState(const NVRenderState::Enum value)
+ {
+ bool enabled = GL_CALL_FUNCTION(glIsEnabled(m_Conversion.fromRenderStateToGL(value)));
+ return enabled;
+ }
+
+ NVRenderBoolOp::Enum NVRenderBackendGLBase::GetDepthFunc()
+ {
+ QT3DSI32 value;
+ GL_CALL_FUNCTION(glGetIntegerv(GL_DEPTH_FUNC, &value));
+ return m_Conversion.fromGLToBoolOp(value);
+ }
+
+ void NVRenderBackendGLBase::SetDepthFunc(const NVRenderBoolOp::Enum func)
+ {
+ GL_CALL_FUNCTION(glDepthFunc(m_Conversion.fromBoolOpToGL(func)));
+ }
+
+ bool NVRenderBackendGLBase::GetDepthWrite()
+ {
+ QT3DSI32 value;
+ GL_CALL_FUNCTION(glGetIntegerv(GL_DEPTH_WRITEMASK, (GLint *)&value));
+ return value ? true : false;
+ }
+
+ void NVRenderBackendGLBase::SetDepthWrite(bool bEnable) { GL_CALL_FUNCTION(glDepthMask(bEnable)); }
+
+ void NVRenderBackendGLBase::SetColorWrites(bool bRed, bool bGreen, bool bBlue, bool bAlpha)
+ {
+ GL_CALL_FUNCTION(glColorMask(bRed, bGreen, bBlue, bAlpha));
+ }
+
+ void NVRenderBackendGLBase::GetBlendFunc(NVRenderBlendFunctionArgument *pBlendFuncArg)
+ {
+ QT3DS_ASSERT(pBlendFuncArg);
+ QT3DSI32_4 values;
+
+ GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_SRC_RGB, (GLint *)&values.x));
+ GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint *)&values.y));
+ GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_DST_RGB, (GLint *)&values.z));
+ GL_CALL_FUNCTION(glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint *)&values.w));
+
+ pBlendFuncArg->m_SrcRGB = m_Conversion.fromGLToSrcBlendFunc(values.x);
+ pBlendFuncArg->m_SrcAlpha = m_Conversion.fromGLToSrcBlendFunc(values.y);
+ pBlendFuncArg->m_DstRGB = m_Conversion.fromGLToDstBlendFunc(values.z);
+ pBlendFuncArg->m_DstAlpha = m_Conversion.fromGLToDstBlendFunc(values.w);
+ }
+
+ void NVRenderBackendGLBase::SetBlendFunc(const NVRenderBlendFunctionArgument &blendFuncArg)
+ {
+ QT3DSI32_4 values;
+
+ values.x = m_Conversion.fromSrcBlendFuncToGL(blendFuncArg.m_SrcRGB);
+ values.y = m_Conversion.fromDstBlendFuncToGL(blendFuncArg.m_DstRGB);
+ values.z = m_Conversion.fromSrcBlendFuncToGL(blendFuncArg.m_SrcAlpha);
+ values.w = m_Conversion.fromDstBlendFuncToGL(blendFuncArg.m_DstAlpha);
+
+ GL_CALL_FUNCTION(glBlendFuncSeparate(values.x, values.y, values.z, values.w));
+ }
+
+ void NVRenderBackendGLBase::SetBlendEquation(const NVRenderBlendEquationArgument &)
+ {
+ // needs GL4 / GLES 3.1
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::SetBlendBarrier()
+ {
+ // needs GL4 / GLES 3.1
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GetScissorRect(NVRenderRect *pRect)
+ {
+ QT3DS_ASSERT(pRect);
+ GL_CALL_FUNCTION(glGetIntegerv(GL_SCISSOR_BOX, (GLint *)pRect));
+ }
+
+ void NVRenderBackendGLBase::SetScissorRect(const NVRenderRect &rect)
+ {
+ GL_CALL_FUNCTION(glScissor(rect.m_X, rect.m_Y, rect.m_Width, rect.m_Height));
+ }
+
+ void NVRenderBackendGLBase::GetViewportRect(NVRenderRect *pRect)
+ {
+ QT3DS_ASSERT(pRect);
+ GL_CALL_FUNCTION(glGetIntegerv(GL_VIEWPORT, (GLint *)pRect));
+ }
+
+ void NVRenderBackendGLBase::SetViewportRect(const NVRenderRect &rect)
+ {
+ GL_CALL_FUNCTION(glViewport(rect.m_X, rect.m_Y, rect.m_Width, rect.m_Height););
+ }
+
+ void NVRenderBackendGLBase::SetClearColor(const QT3DSVec4 *pClearColor)
+ {
+ QT3DS_ASSERT(pClearColor);
+
+ GL_CALL_FUNCTION(glClearColor(pClearColor->x, pClearColor->y,
+ pClearColor->z, pClearColor->w));
+ }
+
+ void NVRenderBackendGLBase::Clear(NVRenderClearFlags flags)
+ {
+ GL_CALL_FUNCTION(glClear(m_Conversion.fromClearFlagsToGL(flags)));
+ }
+
+ NVRenderBackend::NVRenderBackendBufferObject
+ NVRenderBackendGLBase::CreateBuffer(size_t size, NVRenderBufferBindFlags bindFlags,
+ NVRenderBufferUsageType::Enum usage, const void *hostPtr)
+ {
+ GLuint bufID = 0;
+
+ GL_CALL_FUNCTION(glGenBuffers(1, &bufID));
+
+ if (bufID && size) {
+ GLenum target = m_Conversion.fromBindBufferFlagsToGL(bindFlags);
+ if (target != GL_INVALID_ENUM) {
+ GL_CALL_FUNCTION(glBindBuffer(target, bufID));
+ GL_CALL_FUNCTION(glBufferData(target, size, hostPtr,
+ m_Conversion.fromBufferUsageTypeToGL(usage)));
+ } else {
+ GL_CALL_FUNCTION(glDeleteBuffers(1, &bufID));
+ bufID = 0;
+ qCCritical(GL_ERROR, GLConversion::processGLError(target));
+ }
+ }
+
+ return (NVRenderBackend::NVRenderBackendBufferObject)bufID;
+ }
+
+ void NVRenderBackendGLBase::BindBuffer(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags)
+ {
+ GLuint bufID = HandleToID_cast(GLuint, size_t, bo);
+ GL_CALL_FUNCTION(glBindBuffer(m_Conversion.fromBindBufferFlagsToGL(bindFlags), bufID));
+ }
+
+ void NVRenderBackendGLBase::ReleaseBuffer(NVRenderBackendBufferObject bo)
+ {
+ GLuint bufID = HandleToID_cast(GLuint, size_t, bo);
+ GL_CALL_FUNCTION(glDeleteBuffers(1, &bufID));
+ }
+
+ void NVRenderBackendGLBase::UpdateBuffer(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags, size_t size,
+ NVRenderBufferUsageType::Enum usage, const void *data)
+ {
+ GLuint bufID = HandleToID_cast(GLuint, size_t, bo);
+ GLenum target = m_Conversion.fromBindBufferFlagsToGL(bindFlags);
+ GL_CALL_FUNCTION(glBindBuffer(target, bufID));
+ GL_CALL_FUNCTION(glBufferData(target, size, data, m_Conversion.fromBufferUsageTypeToGL(usage)));
+ }
+
+ void NVRenderBackendGLBase::UpdateBufferRange(NVRenderBackendBufferObject bo,
+ NVRenderBufferBindFlags bindFlags, size_t offset,
+ size_t size, const void *data)
+ {
+ GLuint bufID = HandleToID_cast(GLuint, size_t, bo);
+ GLenum target = m_Conversion.fromBindBufferFlagsToGL(bindFlags);
+ GL_CALL_FUNCTION(glBindBuffer(target, bufID));
+ GL_CALL_FUNCTION(glBufferSubData(target, offset, size, data));
+ }
+
+ void *NVRenderBackendGLBase::MapBuffer(NVRenderBackendBufferObject, NVRenderBufferBindFlags,
+ size_t, size_t, NVRenderBufferAccessFlags)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+
+ return NULL;
+ }
+
+ bool NVRenderBackendGLBase::UnmapBuffer(NVRenderBackendBufferObject, NVRenderBufferBindFlags)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+
+ return true;
+ }
+
+ void NVRenderBackendGLBase::SetMemoryBarrier(NVRenderBufferBarrierFlags)
+ {
+ // needs GL 4 context
+ QT3DS_ASSERT(false);
+ }
+
+ NVRenderBackend::NVRenderBackendQueryObject NVRenderBackendGLBase::CreateQuery()
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+
+ return NVRenderBackendQueryObject(0);
+ }
+
+ void NVRenderBackendGLBase::ReleaseQuery(NVRenderBackendQueryObject)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::BeginQuery(NVRenderBackendQueryObject, NVRenderQueryType::Enum)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::EndQuery(NVRenderBackendQueryObject, NVRenderQueryType::Enum)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GetQueryResult(NVRenderBackendQueryObject,
+ NVRenderQueryResultType::Enum, QT3DSU32 *)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GetQueryResult(NVRenderBackendQueryObject,
+ NVRenderQueryResultType::Enum, QT3DSU64 *)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::SetQueryTimer(NVRenderBackendQueryObject)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ NVRenderBackend::NVRenderBackendSyncObject
+ NVRenderBackendGLBase::CreateSync(NVRenderSyncType::Enum, NVRenderSyncFlags)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+
+ return NVRenderBackendSyncObject(0);
+ }
+
+ void NVRenderBackendGLBase::ReleaseSync(NVRenderBackendSyncObject)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::WaitSync(NVRenderBackendSyncObject, NVRenderCommandFlushFlags,
+ QT3DSU64)
+ {
+ // needs GL 3 context
+ QT3DS_ASSERT(false);
+ }
+
+ NVRenderBackend::NVRenderBackendRenderTargetObject NVRenderBackendGLBase::CreateRenderTarget()
+ {
+ GLuint fboID = 0;
+
+ GL_CALL_FUNCTION(glGenFramebuffers(1, &fboID));
+
+ return (NVRenderBackend::NVRenderBackendRenderTargetObject)fboID;
+ }
+
+ void NVRenderBackendGLBase::ReleaseRenderTarget(NVRenderBackendRenderTargetObject rto)
+ {
+ GLuint fboID = HandleToID_cast(GLuint, size_t, rto);
+
+ if (fboID) {
+ GL_CALL_FUNCTION(glDeleteFramebuffers(1, &fboID));
+ }
+ }
+
+ void NVRenderBackendGLBase::RenderTargetAttach(NVRenderBackendRenderTargetObject /* rto */,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendRenderbufferObject rbo)
+ {
+ // rto must be the current render target
+ GLuint rbID = HandleToID_cast(GLuint, size_t, rbo);
+
+ GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
+
+ GL_CALL_FUNCTION(glFramebufferRenderbuffer(GL_FRAMEBUFFER, glAttach, GL_RENDERBUFFER, rbID));
+ }
+
+ void NVRenderBackendGLBase::RenderTargetAttach(NVRenderBackendRenderTargetObject /* rto */,
+ NVRenderFrameBufferAttachments::Enum attachment,
+ NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target)
+ {
+ // rto must be the current render target
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+
+ QT3DS_ASSERT(target == NVRenderTextureTargetType::Texture2D
+ || m_backendSupport.caps.bits.bMsTextureSupported);
+
+ GLenum glAttach = GLConversion::fromFramebufferAttachmentsToGL(attachment);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+
+ GL_CALL_FUNCTION(glFramebufferTexture2D(GL_FRAMEBUFFER, glAttach, glTarget, texID, 0))
+ }
+
+ void NVRenderBackendGLBase::RenderTargetAttach(NVRenderBackendRenderTargetObject,
+ NVRenderFrameBufferAttachments::Enum,
+ NVRenderBackendTextureObject, QT3DSI32, QT3DSI32)
+ {
+ // Needs GL3 or GLES 3
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::SetRenderTarget(NVRenderBackendRenderTargetObject rto)
+ {
+ GLuint fboID = HandleToID_cast(GLuint, size_t, rto);
+
+ GL_CALL_FUNCTION(glBindFramebuffer(GL_FRAMEBUFFER, fboID));
+ }
+
+ bool NVRenderBackendGLBase::RenderTargetIsValid(NVRenderBackendRenderTargetObject /* rto */)
+ {
+ // rto must be the current render target
+ GLenum completeStatus = GL_CALL_FUNCTION(glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ switch (completeStatus) {
+#define HANDLE_INCOMPLETE_STATUS(x) \
+ case x: \
+ qCCritical(INTERNAL_ERROR, "Framebuffer is not complete: %s", #x); \
+ return false;
+ HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
+ HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS)
+ HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
+ HANDLE_INCOMPLETE_STATUS(GL_FRAMEBUFFER_UNSUPPORTED)
+#undef HANDLE_INCOMPLETE_STATUS
+ }
+ return true;
+ }
+
+ NVRenderBackend::NVRenderBackendRenderbufferObject
+ NVRenderBackendGLBase::CreateRenderbuffer(NVRenderRenderBufferFormats::Enum storageFormat,
+ size_t width, size_t height)
+ {
+ GLuint bufID = 0;
+
+ GL_CALL_FUNCTION(glGenRenderbuffers(1, &bufID));
+ GL_CALL_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID));
+ GL_CALL_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER,
+ GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat),
+ (GLsizei)width, (GLsizei)height));
+
+ // check for error
+ GLenum error = m_glFunctions->glGetError();
+ if (error != GL_NO_ERROR) {
+ qCCritical(GL_ERROR, GLConversion::processGLError(error));
+ QT3DS_ASSERT(false);
+ GL_CALL_FUNCTION(glDeleteRenderbuffers(1, &bufID));
+ bufID = 0;
+ }
+
+ GL_CALL_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+
+ return (NVRenderBackend::NVRenderBackendRenderbufferObject)bufID;
+ }
+
+ void NVRenderBackendGLBase::ReleaseRenderbuffer(NVRenderBackendRenderbufferObject rbo)
+ {
+ GLuint bufID = HandleToID_cast(GLuint, size_t, rbo);
+
+ if (bufID) {
+ GL_CALL_FUNCTION(glDeleteRenderbuffers(1, &bufID));
+ }
+ }
+
+ bool NVRenderBackendGLBase::ResizeRenderbuffer(NVRenderBackendRenderbufferObject rbo,
+ NVRenderRenderBufferFormats::Enum storageFormat,
+ size_t width, size_t height)
+ {
+ bool success = true;
+ GLuint bufID = HandleToID_cast(GLuint, size_t, rbo);
+
+ QT3DS_ASSERT(bufID);
+
+ GL_CALL_FUNCTION(glBindRenderbuffer(GL_RENDERBUFFER, bufID));
+ GL_CALL_FUNCTION(glRenderbufferStorage(GL_RENDERBUFFER,
+ GLConversion::fromRenderBufferFormatsToRenderBufferGL(storageFormat),
+ (GLsizei)width, (GLsizei)height));
+
+ // check for error
+ GLenum error = m_glFunctions->glGetError();
+ if (error != GL_NO_ERROR) {
+ qCCritical(GL_ERROR, GLConversion::processGLError(error));
+ QT3DS_ASSERT(false);
+ success = false;
+ }
+
+ return success;
+ }
+
+ NVRenderBackend::NVRenderBackendTextureObject NVRenderBackendGLBase::CreateTexture()
+ {
+ GLuint texID = 0;
+
+ GL_CALL_FUNCTION(glGenTextures(1, &texID));
+
+ return (NVRenderBackend::NVRenderBackendTextureObject)texID;
+ }
+
+ void NVRenderBackendGLBase::BindTexture(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target, QT3DSU32 unit)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0 + unit));
+ GL_CALL_FUNCTION(glBindTexture(m_Conversion.fromTextureTargetToGL(target), texID));
+ }
+
+ void NVRenderBackendGLBase::BindImageTexture(NVRenderBackendTextureObject, QT3DSU32, QT3DSI32, bool,
+ QT3DSI32, NVRenderImageAccessType::Enum,
+ NVRenderTextureFormats::Enum)
+ {
+ // needs GL 4 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::ReleaseTexture(NVRenderBackendTextureObject to)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GL_CALL_FUNCTION(glDeleteTextures(1, &texID));
+ }
+
+ void NVRenderBackendGLBase::SetTextureData2D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format, const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
+ bool conversionRequired = format != internalFormat;
+
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
+ internalFormat, swizzleMode);
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+
+ if (conversionRequired) {
+ GLenum dummy;
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, dummy);
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) {
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+ glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(format))
+ m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+
+ GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width, (GLsizei)height,
+ border, glformat, gltype, hostPtr));
+
+ GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ // This will look very SetTextureData2D, but the target for glBindTexture will be different from
+ // the target for
+ // glTexImage2D.
+ void NVRenderBackendGLBase::SetTextureDataCubeFace(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format, const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GLenum glTexTarget =
+ m_Conversion.fromTextureTargetToGL(NVRenderTextureTargetType::TextureCube);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTexTarget, texID));
+ bool conversionRequired = format != internalFormat;
+
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
+ internalFormat, swizzleMode);
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
+ glformat, gltype, glInternalFormat);
+
+ if (conversionRequired) {
+ GLenum dummy;
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, dummy);
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) {
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+ glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(format))
+ m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+
+ GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width, (GLsizei)height,
+ border, glformat, gltype, hostPtr));
+
+ GL_CALL_FUNCTION(glBindTexture(glTexTarget, 0));
+ }
+
+ void NVRenderBackendGLBase::CreateTextureStorage2D(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32,
+ NVRenderTextureFormats::Enum, size_t, size_t)
+ {
+ // you need GL 4.2 or GLES 3.1
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::SetTextureSubData2D(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ QT3DSU32 level, QT3DSI32 xOffset, QT3DSI32 yOffset,
+ size_t width, size_t height,
+ NVRenderTextureFormats::Enum format,
+ const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
+
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ format = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(), format,
+ swizzleMode);
+
+ GLenum glformat = 0, glInternalFormat = 0, gltype = 0;
+ m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
+ gltype, glInternalFormat);
+ GL_CALL_FUNCTION(glTexSubImage2D(glTarget, level, xOffset, yOffset, (GLsizei)width,
+ (GLsizei)height, glformat, gltype, hostPtr));
+
+ GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ void NVRenderBackendGLBase::SetCompressedTextureData2D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ size_t imageSize, const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
+
+ GLenum glformat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
+ GL_CALL_FUNCTION(glCompressedTexImage2D(glTarget, level, glformat, (GLsizei)width,
+ (GLsizei)height, border, (GLsizei)imageSize, hostPtr));
+
+ GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ void NVRenderBackendGLBase::SetCompressedTextureDataCubeFace(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ size_t imageSize, const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GLenum glTexTarget =
+ m_Conversion.fromTextureTargetToGL(NVRenderTextureTargetType::TextureCube);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTexTarget, texID));
+
+ GLenum glformat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
+ GL_CALL_FUNCTION(glCompressedTexImage2D(glTarget, level, glformat, (GLsizei)width,
+ (GLsizei)height, border, (GLsizei)imageSize, hostPtr));
+
+ GL_CALL_FUNCTION(glBindTexture(glTexTarget, 0));
+ }
+
+ void NVRenderBackendGLBase::SetCompressedTextureSubData2D(
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ QT3DSI32 xOffset, QT3DSI32 yOffset, size_t width, size_t height,
+ NVRenderTextureFormats::Enum format, size_t imageSize, const void *hostPtr)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
+
+ GLenum glformat = m_Conversion.fromCompressedTextureFormatToGL(format);
+ GL_CALL_FUNCTION(glCompressedTexSubImage2D(glTarget, level, xOffset, yOffset, (GLsizei)width,
+ (GLsizei)height, glformat, (GLsizei)imageSize,
+ hostPtr));
+
+ GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ void NVRenderBackendGLBase::SetTextureData3D(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32,
+ NVRenderTextureFormats::Enum, size_t, size_t,
+ size_t, QT3DSI32, NVRenderTextureFormats::Enum,
+ const void *)
+ {
+ // needs GL3 or GLES3
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GenerateMipMaps(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderHint::Enum genType)
+ {
+ GLuint texID = HandleToID_cast(GLuint, size_t, to);
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+ GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
+ GL_CALL_FUNCTION(glBindTexture(glTarget, texID));
+
+ GLenum glValue = GLConversion::fromHintToGL(genType);
+ GL_CALL_FUNCTION(glHint(GL_GENERATE_MIPMAP_HINT, glValue));
+ GL_CALL_FUNCTION(glGenerateMipmap(glTarget));
+
+ GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
+ }
+
+ NVRenderTextureSwizzleMode::Enum
+ NVRenderBackendGLBase::GetTextureSwizzleMode(const NVRenderTextureFormats::Enum inFormat) const
+ {
+ NVRenderTextureSwizzleMode::Enum swizzleMode = NVRenderTextureSwizzleMode::NoSwizzle;
+ m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(), inFormat, swizzleMode);
+
+ return swizzleMode;
+ }
+
+ NVRenderBackend::NVRenderBackendSamplerObject NVRenderBackendGLBase::CreateSampler(
+ NVRenderTextureMinifyingOp::Enum minFilter, NVRenderTextureMagnifyingOp::Enum magFilter,
+ NVRenderTextureCoordOp::Enum wrapS, NVRenderTextureCoordOp::Enum wrapT,
+ NVRenderTextureCoordOp::Enum wrapR, QT3DSI32 minLod, QT3DSI32 maxLod, QT3DSF32 lodBias,
+ NVRenderTextureCompareMode::Enum compareMode, NVRenderTextureCompareOp::Enum compareFunc,
+ QT3DSF32 anisotropy, QT3DSF32 *borderColor)
+ {
+ // Satisfy the compiler
+ // We don"t setup the state here for GL
+ // but we need to pass on the variables here
+ // to satisfy the interface
+ NVRENDER_BACKEND_UNUSED(minFilter);
+ NVRENDER_BACKEND_UNUSED(magFilter);
+ NVRENDER_BACKEND_UNUSED(wrapS);
+ NVRENDER_BACKEND_UNUSED(wrapT);
+ NVRENDER_BACKEND_UNUSED(wrapR);
+ NVRENDER_BACKEND_UNUSED(minLod);
+ NVRENDER_BACKEND_UNUSED(maxLod);
+ NVRENDER_BACKEND_UNUSED(lodBias);
+ NVRENDER_BACKEND_UNUSED(compareMode);
+ NVRENDER_BACKEND_UNUSED(compareFunc);
+ NVRENDER_BACKEND_UNUSED(anisotropy);
+ NVRENDER_BACKEND_UNUSED(borderColor);
+
+ // return a dummy handle
+ return (NVRenderBackend::NVRenderBackendSamplerObject)0x0001;
+ }
+
+ void NVRenderBackendGLBase::UpdateSampler(
+ NVRenderBackendSamplerObject /* so */, NVRenderTextureTargetType::Enum target,
+ NVRenderTextureMinifyingOp::Enum minFilter, NVRenderTextureMagnifyingOp::Enum magFilter,
+ NVRenderTextureCoordOp::Enum wrapS, NVRenderTextureCoordOp::Enum wrapT,
+ NVRenderTextureCoordOp::Enum wrapR, QT3DSF32 minLod, QT3DSF32 maxLod, QT3DSF32 lodBias,
+ NVRenderTextureCompareMode::Enum compareMode, NVRenderTextureCompareOp::Enum compareFunc,
+ QT3DSF32 anisotropy, QT3DSF32 *borderColor)
+ {
+ // Satisfy the compiler
+ // These are not available in GLES 2 and we don't use them right now
+ NVRENDER_BACKEND_UNUSED(wrapR);
+ NVRENDER_BACKEND_UNUSED(lodBias);
+ NVRENDER_BACKEND_UNUSED(minLod);
+ NVRENDER_BACKEND_UNUSED(maxLod);
+ NVRENDER_BACKEND_UNUSED(compareMode);
+ NVRENDER_BACKEND_UNUSED(compareFunc);
+ NVRENDER_BACKEND_UNUSED(borderColor);
+
+ GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
+
+ GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MIN_FILTER,
+ m_Conversion.fromTextureMinifyingOpToGL(minFilter)));
+ GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_MAG_FILTER,
+ m_Conversion.fromTextureMagnifyingOpToGL(magFilter)));
+ GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_S,
+ m_Conversion.fromTextureCoordOpToGL(wrapS)));
+ GL_CALL_FUNCTION(glTexParameteri(glTarget, GL_TEXTURE_WRAP_T,
+ m_Conversion.fromTextureCoordOpToGL(wrapT)));
+ if (m_backendSupport.caps.bits.bAnistropySupported) {
+ GL_CALL_FUNCTION(glTexParameterf(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy));
+ }
+ }
+
+ void NVRenderBackendGLBase::UpdateTextureObject(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ QT3DSI32 baseLevel, QT3DSI32 maxLevel)
+ {
+ NVRENDER_BACKEND_UNUSED(to);
+ NVRENDER_BACKEND_UNUSED(target);
+ NVRENDER_BACKEND_UNUSED(baseLevel);
+ NVRENDER_BACKEND_UNUSED(maxLevel);
+ }
+
+ void NVRenderBackendGLBase::UpdateTextureSwizzle(NVRenderBackendTextureObject to,
+ NVRenderTextureTargetType::Enum target,
+ NVRenderTextureSwizzleMode::Enum swizzleMode)
+ {
+ NVRENDER_BACKEND_UNUSED(to);
+ NVRENDER_BACKEND_UNUSED(target);
+
+ // Nothing to do here still might be called
+ QT3DS_ASSERT(swizzleMode == NVRenderTextureSwizzleMode::NoSwizzle);
+
+ NVRENDER_BACKEND_UNUSED(swizzleMode);
+ }
+
+ void NVRenderBackendGLBase::ReleaseSampler(NVRenderBackendSamplerObject so)
+ {
+ GLuint samplerID = HandleToID_cast(GLuint, size_t, so);
+ if (!samplerID)
+ return;
+ // otherwise nothing to do
+ }
+
+ NVRenderBackend::NVRenderBackendAttribLayoutObject
+ NVRenderBackendGLBase::CreateAttribLayout(NVConstDataRef<NVRenderVertexBufferEntry> attribs)
+ {
+ QT3DSU32 attribLayoutSize = sizeof(NVRenderBackendAttributeLayoutGL);
+ QT3DSU32 entrySize = sizeof(NVRenderBackendLayoutEntryGL) * attribs.size();
+ QT3DSU8 *newMem = (QT3DSU8 *)QT3DS_ALLOC(m_Foundation.getAllocator(), attribLayoutSize + entrySize,
+ "BackendAttributeLayoutGL");
+ NVDataRef<NVRenderBackendLayoutEntryGL> entryRef =
+ PtrAtOffset<NVRenderBackendLayoutEntryGL>(newMem, attribLayoutSize, entrySize);
+ QT3DSU32 maxInputSlot = 0;
+
+ // copy data
+ UICBASE_FOREACH(idx, attribs.size())
+ {
+ entryRef[idx].m_AttribName = m_StringTable->RegisterStr(attribs.mData[idx].m_Name);
+ entryRef[idx].m_Normalize = 0;
+ entryRef[idx].m_AttribIndex = 0; // will be set later
+ entryRef[idx].m_Type = m_Conversion.fromComponentTypeAndNumCompsToAttribGL(
+ attribs.mData[idx].m_ComponentType, attribs.mData[idx].m_NumComponents);
+ entryRef[idx].m_NumComponents = attribs.mData[idx].m_NumComponents;
+ entryRef[idx].m_InputSlot = attribs.mData[idx].m_InputSlot;
+ entryRef[idx].m_Offset = attribs.mData[idx].m_FirstItemOffset;
+
+ if (maxInputSlot < entryRef[idx].m_InputSlot)
+ maxInputSlot = entryRef[idx].m_InputSlot;
+ }
+
+ NVRenderBackendAttributeLayoutGL *retval =
+ new (newMem) NVRenderBackendAttributeLayoutGL(entryRef, maxInputSlot);
+
+ return (NVRenderBackend::NVRenderBackendAttribLayoutObject)retval;
+ }
+
+ void NVRenderBackendGLBase::ReleaseAttribLayout(NVRenderBackendAttribLayoutObject ao)
+ {
+ NVRenderBackendAttributeLayoutGL *attribLayout = (NVRenderBackendAttributeLayoutGL *)ao;
+
+ NVDelete(m_Foundation.getAllocator(), attribLayout);
+ };
+
+ NVRenderBackend::NVRenderBackendInputAssemblerObject
+ NVRenderBackendGLBase::CreateInputAssembler(NVRenderBackendAttribLayoutObject attribLayout,
+ NVConstDataRef<NVRenderBackendBufferObject> buffers,
+ const NVRenderBackendBufferObject indexBuffer,
+ NVConstDataRef<QT3DSU32> strides,
+ NVConstDataRef<QT3DSU32> offsets,
+ QT3DSU32 patchVertexCount)
+ {
+ NVRenderBackendAttributeLayoutGL *attribLayoutGL =
+ (NVRenderBackendAttributeLayoutGL *)attribLayout;
+
+ NVRenderBackendInputAssemblerGL *retval = QT3DS_NEW(m_Foundation.getAllocator(),
+ NVRenderBackendInputAssemblerGL)(
+ m_Foundation, attribLayoutGL, buffers, indexBuffer, strides, offsets, patchVertexCount);
+
+ return (NVRenderBackend::NVRenderBackendInputAssemblerObject)retval;
+ }
+
+ void NVRenderBackendGLBase::ReleaseInputAssembler(NVRenderBackendInputAssemblerObject iao)
+ {
+ NVRenderBackendInputAssemblerGL *inputAssembler = (NVRenderBackendInputAssemblerGL *)iao;
+ NVDelete(m_Foundation.getAllocator(), inputAssembler);
+ }
+
+ bool NVRenderBackendGLBase::compileSource(GLuint shaderID, NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ GLint shaderSourceSize = static_cast<GLint>(source.size());
+ const char *shaderSourceData = (const char *)source.begin();
+ GLint shaderStatus = GL_TRUE;
+
+ if (!binary) {
+
+ GL_CALL_FUNCTION(glShaderSource(shaderID, 1, &shaderSourceData, &shaderSourceSize));
+ GL_CALL_FUNCTION(glCompileShader(shaderID));
+
+ GLint logLen;
+ GL_CALL_FUNCTION(glGetShaderiv(shaderID, GL_COMPILE_STATUS, &shaderStatus));
+ GL_CALL_FUNCTION(glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLen));
+
+ // Check if some log exists. We also write warnings here
+ // Should at least contain more than the null termination
+ if (logLen > 2) {
+ errorMessage.resize(logLen + 1);
+
+ GLint lenWithoutNull;
+ GL_CALL_FUNCTION(glGetShaderInfoLog(shaderID, logLen, &lenWithoutNull,
+ (char *)errorMessage.c_str()));
+ }
+ } else {
+ GL_CALL_FUNCTION(glShaderBinary(1, &shaderID, GL_NVIDIA_PLATFORM_BINARY_NV, shaderSourceData,
+ shaderSourceSize));
+ GLenum binaryError = m_glFunctions->glGetError();
+ if (binaryError != GL_NO_ERROR) {
+ shaderStatus = GL_FALSE;
+ qCCritical(GL_ERROR, GLConversion::processGLError(binaryError));
+ }
+ }
+
+ return (shaderStatus == GL_TRUE);
+ }
+
+ NVRenderBackend::NVRenderBackendVertexShaderObject
+ NVRenderBackendGLBase::CreateVertexShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ GLuint shaderID = GL_CALL_FUNCTION(glCreateShader(GL_VERTEX_SHADER));
+
+ if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ shaderID = 0;
+ }
+
+ return (NVRenderBackend::NVRenderBackendVertexShaderObject)shaderID;
+ }
+
+ NVRenderBackend::NVRenderBackendFragmentShaderObject
+ NVRenderBackendGLBase::CreateFragmentShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ GLuint shaderID = GL_CALL_FUNCTION(glCreateShader(GL_FRAGMENT_SHADER));
+
+ if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ shaderID = 0;
+ }
+
+ return (NVRenderBackend::NVRenderBackendFragmentShaderObject)shaderID;
+ }
+
+ NVRenderBackend::NVRenderBackendTessControlShaderObject
+ NVRenderBackendGLBase::CreateTessControlShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ // needs GL 4 or GLES EXT_tessellation_shader support
+ NVRENDER_BACKEND_UNUSED(source);
+ NVRENDER_BACKEND_UNUSED(errorMessage);
+ NVRENDER_BACKEND_UNUSED(binary);
+
+ QT3DS_ASSERT(false);
+
+ return (NVRenderBackend::NVRenderBackendTessControlShaderObject)0;
+ }
+
+ NVRenderBackend::NVRenderBackendTessEvaluationShaderObject
+ NVRenderBackendGLBase::CreateTessEvaluationShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ // needs GL 4 or GLES EXT_tessellation_shader support
+ NVRENDER_BACKEND_UNUSED(source);
+ NVRENDER_BACKEND_UNUSED(errorMessage);
+ NVRENDER_BACKEND_UNUSED(binary);
+
+ QT3DS_ASSERT(false);
+
+ return (NVRenderBackend::NVRenderBackendTessEvaluationShaderObject)0;
+ }
+
+ NVRenderBackend::NVRenderBackendGeometryShaderObject
+ NVRenderBackendGLBase::CreateGeometryShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ // needs GL 4 or GLES EXT_geometry_shader support
+ NVRENDER_BACKEND_UNUSED(source);
+ NVRENDER_BACKEND_UNUSED(errorMessage);
+ NVRENDER_BACKEND_UNUSED(binary);
+
+ QT3DS_ASSERT(false);
+
+ return (NVRenderBackend::NVRenderBackendGeometryShaderObject)0;
+ }
+
+ NVRenderBackend::NVRenderBackendComputeShaderObject
+ NVRenderBackendGLBase::CreateComputeShader(NVConstDataRef<QT3DSI8> source,
+ eastl::string &errorMessage, bool binary)
+ {
+ // needs GL 4.3 or GLES3.1 support
+ NVRENDER_BACKEND_UNUSED(source);
+ NVRENDER_BACKEND_UNUSED(errorMessage);
+ NVRENDER_BACKEND_UNUSED(binary);
+
+ QT3DS_ASSERT(false);
+
+ return (NVRenderBackend::NVRenderBackendComputeShaderObject)0;
+ }
+
+ void NVRenderBackendGLBase::ReleaseVertexShader(NVRenderBackendVertexShaderObject vso)
+ {
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, vso);
+
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ }
+
+ void NVRenderBackendGLBase::ReleaseFragmentShader(NVRenderBackendFragmentShaderObject fso)
+ {
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, fso);
+
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ }
+
+ void
+ NVRenderBackendGLBase::ReleaseTessControlShader(NVRenderBackendTessControlShaderObject tcso)
+ {
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, tcso);
+
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ }
+
+ void NVRenderBackendGLBase::ReleaseTessEvaluationShader(
+ NVRenderBackendTessEvaluationShaderObject teso)
+ {
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, teso);
+
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ }
+
+ void NVRenderBackendGLBase::ReleaseGeometryShader(NVRenderBackendGeometryShaderObject gso)
+ {
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, gso);
+
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ }
+
+ void NVRenderBackendGLBase::ReleaseComputeShader(NVRenderBackendComputeShaderObject cso)
+ {
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, cso);
+
+ GL_CALL_FUNCTION(glDeleteShader(shaderID));
+ }
+
+ void NVRenderBackendGLBase::AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendVertexShaderObject vso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, vso);
+
+ GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendFragmentShaderObject fso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, fso);
+
+ GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessControlShaderObject tcso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, tcso);
+
+ GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessEvaluationShaderObject teso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, teso);
+
+ GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendGeometryShaderObject gso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, gso);
+
+ GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::AttachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendComputeShaderObject cso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, cso);
+
+ GL_CALL_FUNCTION(glAttachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendVertexShaderObject vso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, vso);
+
+ GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendFragmentShaderObject fso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, fso);
+
+ GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessControlShaderObject tcso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, tcso);
+
+ GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendTessEvaluationShaderObject teso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, teso);
+
+ GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendGeometryShaderObject gso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, gso);
+
+ GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ void NVRenderBackendGLBase::DetachShader(NVRenderBackendShaderProgramObject po,
+ NVRenderBackendComputeShaderObject cso)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint shaderID = HandleToID_cast(GLuint, size_t, cso);
+
+ GL_CALL_FUNCTION(glDetachShader(static_cast<GLuint>(pProgram->m_ProgramID), shaderID));
+ }
+
+ NVRenderBackend::NVRenderBackendShaderProgramObject
+ NVRenderBackendGLBase::CreateShaderProgram(bool isSeparable)
+ {
+ NVRenderBackendShaderProgramGL *theProgram = NULL;
+ GLuint programID = GL_CALL_FUNCTION(glCreateProgram());
+
+ if (programID) {
+ theProgram =
+ QT3DS_NEW(m_Foundation.getAllocator(), NVRenderBackendShaderProgramGL)(programID);
+
+ if (!theProgram) {
+ GL_CALL_FUNCTION(glDeleteProgram(programID));
+ } else if (isSeparable && m_backendSupport.caps.bits.bProgramPipelineSupported) {
+ GL_CALL_EXTRA_FUNCTION(glProgramParameteri(programID, GL_PROGRAM_SEPARABLE, GL_TRUE));
+ }
+ }
+
+ return (NVRenderBackend::NVRenderBackendShaderProgramObject)theProgram;
+ }
+
+ void NVRenderBackendGLBase::ReleaseShaderProgram(NVRenderBackendShaderProgramObject po)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GL_CALL_FUNCTION(glDeleteProgram(programID));
+
+ if (pProgram->m_shaderInput) {
+ NVDelete(m_Foundation.getAllocator(), pProgram->m_shaderInput);
+ pProgram->m_shaderInput = NULL;
+ }
+
+ NVDelete(m_Foundation.getAllocator(), pProgram);
+ }
+
+ bool NVRenderBackendGLBase::LinkProgram(NVRenderBackendShaderProgramObject po,
+ eastl::string &errorMessage)
+ {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GL_CALL_FUNCTION(glLinkProgram(programID));
+
+ GLint linkStatus, logLen;
+ GL_CALL_FUNCTION(glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus));
+ GL_CALL_FUNCTION(glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLen));
+
+ // if succesfuly linked get the attribute information
+ if (linkStatus) {
+ // release old stuff
+ if (pProgram->m_shaderInput) {
+ NVDelete(m_Foundation.getAllocator(), pProgram->m_shaderInput);
+ pProgram->m_shaderInput = NULL;
+ }
+
+ GLint numAttribs;
+ GL_CALL_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_ATTRIBUTES, &numAttribs));
+
+ if (numAttribs) {
+ NVRenderBackendShaderInputEntryGL *tempShaderInputEntry =
+ (NVRenderBackendShaderInputEntryGL *)QT3DS_ALLOC(
+ m_Foundation.getAllocator(),
+ sizeof(NVRenderBackendShaderInputEntryGL) * m_MaxAttribCount,
+ "BackendShaderInputEntryGL");
+
+ GLint maxLength;
+ GL_CALL_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength));
+ QT3DSI8 *nameBuf =
+ (QT3DSI8 *)QT3DS_ALLOC(m_Foundation.getAllocator(), maxLength, "LinkProgram");
+
+ // fill in data
+ QT3DSU32 count = 0;
+ UICBASE_FOREACH(idx, numAttribs)
+ {
+ GLint size = 0;
+ GLenum glType;
+ NVRenderComponentTypes::Enum compType = NVRenderComponentTypes::Unknown;
+ QT3DSU32 numComps = 0;
+
+ GL_CALL_FUNCTION(glGetActiveAttrib(programID, idx, maxLength, NULL, &size, &glType,
+ (char *)nameBuf));
+ // Skip anything named with gl_
+ if (memcmp(nameBuf, "gl_", 3) == 0)
+ continue;
+
+ m_Conversion.fromAttribGLToComponentTypeAndNumComps(glType, compType, numComps);
+
+ tempShaderInputEntry[count].m_AttribName =
+ m_StringTable->RegisterStr((char *)nameBuf);
+ tempShaderInputEntry[count].m_AttribLocation =
+ GL_CALL_FUNCTION(glGetAttribLocation(programID, (char *)nameBuf));
+ tempShaderInputEntry[count].m_Type = glType;
+ tempShaderInputEntry[count].m_NumComponents = numComps;
+
+ ++count;
+ }
+
+ // Now allocate space for the actuall entries
+ QT3DSU32 shaderInputSize = sizeof(NVRenderBackendShaderInputGL);
+ QT3DSU32 entrySize = sizeof(NVRenderBackendShaderInputEntryGL) * count;
+ QT3DSU8 *newMem =
+ (QT3DSU8 *)QT3DS_ALLOC(m_Foundation.getAllocator(), shaderInputSize + entrySize,
+ "BackendShaderInputEntryGL");
+ NVDataRef<NVRenderBackendShaderInputEntryGL> entryRef =
+ PtrAtOffset<NVRenderBackendShaderInputEntryGL>(newMem, shaderInputSize,
+ entrySize);
+ // fill data
+ UICBASE_FOREACH(idx, count)
+ {
+ entryRef[idx].m_AttribName = tempShaderInputEntry[idx].m_AttribName;
+ entryRef[idx].m_AttribLocation = tempShaderInputEntry[idx].m_AttribLocation;
+ entryRef[idx].m_Type = tempShaderInputEntry[idx].m_Type;
+ entryRef[idx].m_NumComponents = tempShaderInputEntry[idx].m_NumComponents;
+ }
+
+ // placement new
+ NVRenderBackendShaderInputGL *shaderInput =
+ new (newMem) NVRenderBackendShaderInputGL(entryRef);
+ // set the pointer
+ pProgram->m_shaderInput = shaderInput;
+
+ QT3DS_FREE(m_Foundation.getAllocator(), nameBuf);
+ QT3DS_FREE(m_Foundation.getAllocator(), tempShaderInputEntry);
+ }
+ }
+
+ // Check if some log exists. We also write warnings here
+ // Should at least contain more than the null termination
+ if (logLen > 2) {
+ errorMessage.resize(logLen + 1);
+
+ GLint lenWithoutNull;
+ GL_CALL_FUNCTION(glGetProgramInfoLog(programID, logLen, &lenWithoutNull,
+ (char *)errorMessage.c_str()));
+ }
+
+ return (linkStatus == GL_TRUE);
+ }
+
+ void NVRenderBackendGLBase::SetActiveProgram(NVRenderBackendShaderProgramObject po)
+ {
+ GLuint programID = 0;
+
+ if (po) {
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ programID = static_cast<GLuint>(pProgram->m_ProgramID);
+ }
+
+ GL_CALL_FUNCTION(glUseProgram(programID));
+ }
+
+ NVRenderBackend::NVRenderBackendProgramPipeline NVRenderBackendGLBase::CreateProgramPipeline()
+ {
+ // needs GL 4 context
+ QT3DS_ASSERT(false);
+ return NVRenderBackend::NVRenderBackendProgramPipeline(0);
+ }
+
+ void NVRenderBackendGLBase::ReleaseProgramPipeline(NVRenderBackendProgramPipeline)
+ {
+ // needs GL 4 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::SetActiveProgramPipeline(NVRenderBackendProgramPipeline)
+ {
+ // needs GL 4 context
+ //TODO: should be fixed?
+ // QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::SetProgramStages(NVRenderBackendProgramPipeline,
+ NVRenderShaderTypeFlags,
+ NVRenderBackendShaderProgramObject)
+ {
+ // needs GL 4 context
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::DispatchCompute(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32,
+ QT3DSU32)
+ {
+ // needs GL 4 context
+ QT3DS_ASSERT(false);
+ }
+
+ QT3DSI32 NVRenderBackendGLBase::GetConstantCount(NVRenderBackendShaderProgramObject po)
+ {
+ QT3DS_ASSERT(po);
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GLint numUniforms;
+ GL_CALL_FUNCTION(glGetProgramiv(programID, GL_ACTIVE_UNIFORMS, &numUniforms));
+
+ return numUniforms;
+ }
+
+ QT3DSI32 NVRenderBackendGLBase::GetConstantBufferCount(NVRenderBackendShaderProgramObject po)
+ {
+ // needs GL3 and above
+ NVRENDER_BACKEND_UNUSED(po);
+
+ return 0;
+ }
+
+ QT3DSI32
+ NVRenderBackendGLBase::GetConstantInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 bufSize, QT3DSI32 *numElem,
+ NVRenderShaderDataTypes::Enum *type, QT3DSI32 *binding,
+ char *nameBuf)
+ {
+ QT3DS_ASSERT(po);
+ NVRenderBackendShaderProgramGL *pProgram = (NVRenderBackendShaderProgramGL *)po;
+ GLuint programID = static_cast<GLuint>(pProgram->m_ProgramID);
+
+ GLenum glType;
+ GL_CALL_FUNCTION(glGetActiveUniform(programID, id, bufSize, NULL, numElem, &glType, nameBuf));
+ *type = m_Conversion.fromShaderGLToPropertyDataTypes(glType);
+
+ QT3DSI32 uniformLoc = GL_CALL_FUNCTION(glGetUniformLocation(programID, nameBuf));
+
+ // get unit binding point
+ *binding = -1;
+ if (uniformLoc != -1 && (glType == GL_IMAGE_2D || glType == GL_UNSIGNED_INT_IMAGE_2D
+ || glType == GL_UNSIGNED_INT_ATOMIC_COUNTER)) {
+ GL_CALL_FUNCTION(glGetUniformiv(programID, uniformLoc, binding));
+ }
+
+ return uniformLoc;
+ }
+
+ QT3DSI32
+ NVRenderBackendGLBase::GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length,
+ char *nameBuf)
+ {
+ // needs GL3 and above
+ NVRENDER_BACKEND_UNUSED(po);
+ NVRENDER_BACKEND_UNUSED(id);
+ NVRENDER_BACKEND_UNUSED(nameBufSize);
+ NVRENDER_BACKEND_UNUSED(paramCount);
+ NVRENDER_BACKEND_UNUSED(bufferSize);
+ NVRENDER_BACKEND_UNUSED(length);
+ NVRENDER_BACKEND_UNUSED(nameBuf);
+
+ QT3DS_ASSERT(false);
+
+ return -1;
+ }
+
+ void NVRenderBackendGLBase::GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSI32 *indices)
+ {
+ // needs GL3 and above
+ NVRENDER_BACKEND_UNUSED(po);
+ NVRENDER_BACKEND_UNUSED(id);
+ NVRENDER_BACKEND_UNUSED(indices);
+
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GetConstantBufferParamInfoByIndices(
+ NVRenderBackendShaderProgramObject po, QT3DSU32 count, QT3DSU32 *indices, QT3DSI32 *type,
+ QT3DSI32 *size, QT3DSI32 *offset)
+ {
+ // needs GL3 and above
+ NVRENDER_BACKEND_UNUSED(po);
+ NVRENDER_BACKEND_UNUSED(count);
+ NVRENDER_BACKEND_UNUSED(indices);
+ NVRENDER_BACKEND_UNUSED(type);
+ NVRENDER_BACKEND_UNUSED(size);
+ NVRENDER_BACKEND_UNUSED(offset);
+
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::ProgramSetConstantBlock(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 blockIndex, QT3DSU32 binding)
+ {
+ // needs GL3 and above
+ NVRENDER_BACKEND_UNUSED(po);
+ NVRENDER_BACKEND_UNUSED(blockIndex);
+ NVRENDER_BACKEND_UNUSED(binding);
+
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::ProgramSetConstantBuffer(QT3DSU32 index,
+ NVRenderBackendBufferObject bo)
+ {
+ // needs GL3 and above
+ NVRENDER_BACKEND_UNUSED(index);
+ NVRENDER_BACKEND_UNUSED(bo);
+
+ QT3DS_ASSERT(false);
+ }
+
+ QT3DSI32 NVRenderBackendGLBase::GetStorageBufferCount(NVRenderBackendShaderProgramObject po)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(po);
+
+ return 0;
+ }
+
+ QT3DSI32
+ NVRenderBackendGLBase::GetStorageBufferInfoByID(NVRenderBackendShaderProgramObject po, QT3DSU32 id,
+ QT3DSU32 nameBufSize, QT3DSI32 *paramCount,
+ QT3DSI32 *bufferSize, QT3DSI32 *length, char *nameBuf)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(po);
+ NVRENDER_BACKEND_UNUSED(id);
+ NVRENDER_BACKEND_UNUSED(nameBufSize);
+ NVRENDER_BACKEND_UNUSED(paramCount);
+ NVRENDER_BACKEND_UNUSED(bufferSize);
+ NVRENDER_BACKEND_UNUSED(length);
+ NVRENDER_BACKEND_UNUSED(nameBuf);
+
+ QT3DS_ASSERT(false);
+
+ return -1;
+ }
+
+ void NVRenderBackendGLBase::ProgramSetStorageBuffer(QT3DSU32 index, NVRenderBackendBufferObject bo)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(index);
+ NVRENDER_BACKEND_UNUSED(bo);
+ }
+
+ QT3DSI32 NVRenderBackendGLBase::GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject po)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(po);
+
+ return 0;
+ }
+
+ QT3DSI32
+ NVRenderBackendGLBase::GetAtomicCounterBufferInfoByID(NVRenderBackendShaderProgramObject po,
+ QT3DSU32 id, QT3DSU32 nameBufSize,
+ QT3DSI32 *paramCount, QT3DSI32 *bufferSize,
+ QT3DSI32 *length, char *nameBuf)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(po);
+ NVRENDER_BACKEND_UNUSED(id);
+ NVRENDER_BACKEND_UNUSED(nameBufSize);
+ NVRENDER_BACKEND_UNUSED(paramCount);
+ NVRENDER_BACKEND_UNUSED(bufferSize);
+ NVRENDER_BACKEND_UNUSED(length);
+ NVRENDER_BACKEND_UNUSED(nameBuf);
+
+ QT3DS_ASSERT(false);
+
+ return -1;
+ }
+
+ void NVRenderBackendGLBase::ProgramSetAtomicCounterBuffer(QT3DSU32 index,
+ NVRenderBackendBufferObject bo)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(index);
+ NVRENDER_BACKEND_UNUSED(bo);
+ }
+
+ void NVRenderBackendGLBase::SetConstantValue(NVRenderBackendShaderProgramObject, QT3DSU32 id,
+ NVRenderShaderDataTypes::Enum type, QT3DSI32 count,
+ const void *value, bool transpose)
+ {
+ GLenum glType = m_Conversion.fromPropertyDataTypesToShaderGL(type);
+
+ switch (glType) {
+ case GL_FLOAT:
+ GL_CALL_FUNCTION(glUniform1fv(id, count, (GLfloat *)value));
+ break;
+ case GL_FLOAT_VEC2:
+ GL_CALL_FUNCTION(glUniform2fv(id, count, (GLfloat *)value));
+ break;
+ case GL_FLOAT_VEC3:
+ GL_CALL_FUNCTION(glUniform3fv(id, count, (GLfloat *)value));
+ break;
+ case GL_FLOAT_VEC4:
+ GL_CALL_FUNCTION(glUniform4fv(id, count, (GLfloat *)value));
+ break;
+ case GL_INT:
+ case GL_BOOL:
+ GL_CALL_FUNCTION(glUniform1iv(id, count, (GLint *)value));
+ break;
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ GL_CALL_FUNCTION(glUniform2iv(id, count, (GLint *)value));
+ break;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ GL_CALL_FUNCTION(glUniform3iv(id, count, (GLint *)value));
+ break;
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ GL_CALL_FUNCTION(glUniform4iv(id, count, (GLint *)value));
+ break;
+ case GL_FLOAT_MAT3:
+ GL_CALL_FUNCTION(glUniformMatrix3fv(id, count, transpose, (GLfloat *)value));
+ break;
+ case GL_FLOAT_MAT4:
+ GL_CALL_FUNCTION(glUniformMatrix4fv(id, count, transpose, (GLfloat *)value));
+ break;
+ case GL_IMAGE_2D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_CUBE: {
+ GLint sampler = *(GLint *)value;
+ GL_CALL_FUNCTION(glUniform1i(id, sampler));
+ } break;
+ default:
+ qCCritical(INTERNAL_ERROR, "Unknown shader type format %d", type);
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ void NVRenderBackendGLBase::Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 start, QT3DSU32 count)
+ {
+ GL_CALL_FUNCTION(glDrawArrays(m_Conversion.fromDrawModeToGL(
+ drawMode, m_backendSupport.caps.bits.bTessellationSupported),
+ start, count));
+ }
+
+ void NVRenderBackendGLBase::DrawIndirect(NVRenderDrawMode::Enum drawMode, const void *indirect)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(drawMode);
+ NVRENDER_BACKEND_UNUSED(indirect);
+ }
+
+ void NVRenderBackendGLBase::DrawIndexed(NVRenderDrawMode::Enum drawMode, QT3DSU32 count,
+ NVRenderComponentTypes::Enum type, const void *indices)
+ {
+ GL_CALL_FUNCTION(glDrawElements(m_Conversion.fromDrawModeToGL(
+ drawMode, m_backendSupport.caps.bits.bTessellationSupported),
+ count, m_Conversion.fromIndexBufferComponentsTypesToGL(type),
+ indices));
+ }
+
+ void NVRenderBackendGLBase::DrawIndexedIndirect(NVRenderDrawMode::Enum drawMode,
+ NVRenderComponentTypes::Enum type,
+ const void *indirect)
+ {
+ // needs GL4 and above
+ NVRENDER_BACKEND_UNUSED(drawMode);
+ NVRENDER_BACKEND_UNUSED(type);
+ NVRENDER_BACKEND_UNUSED(indirect);
+ }
+
+ void NVRenderBackendGLBase::ReadPixel(NVRenderBackendRenderTargetObject /* rto */, QT3DSI32 x,
+ QT3DSI32 y, QT3DSI32 width, QT3DSI32 height,
+ NVRenderReadPixelFormats::Enum inFormat, void *pixels)
+ {
+ GLuint glFormat;
+ GLuint glType;
+ if (m_Conversion.fromReadPixelsToGlFormatAndType(inFormat, &glFormat, &glType)) {
+ GL_CALL_FUNCTION(glReadPixels(x, y, width, height, glFormat, glType, pixels));
+ }
+ }
+
+ NVRenderBackend::NVRenderBackendPathObject NVRenderBackendGLBase::CreatePathNVObject(size_t)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+
+ return NVRenderBackend::NVRenderBackendPathObject(0);
+ }
+
+ void NVRenderBackendGLBase::ReleasePathNVObject(NVRenderBackendPathObject, size_t)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::LoadPathGlyphs(NVRenderBackendPathObject,
+ NVRenderPathFontTarget::Enum, const void *,
+ NVRenderPathFontStyleFlags, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathMissingGlyphs::Enum,
+ NVRenderBackendPathObject, QT3DSF32)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::LoadPathGlyphRange(NVRenderBackendPathObject,
+ NVRenderPathFontTarget::Enum, const void *,
+ NVRenderPathFontStyleFlags, QT3DSU32, size_t,
+ NVRenderPathMissingGlyphs::Enum,
+ NVRenderBackendPathObject, QT3DSF32)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ NVRenderPathReturnValues::Enum NVRenderBackendGLBase::LoadPathGlyphsIndexed(
+ NVRenderBackendPathObject, NVRenderPathFontTarget::Enum, const void *,
+ NVRenderPathFontStyleFlags, QT3DSU32, size_t, NVRenderBackendPathObject, QT3DSF32)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ return NVRenderPathReturnValues::FontUnavailable;
+ }
+
+ NVRenderBackend::NVRenderBackendPathObject NVRenderBackendGLBase::LoadPathGlyphsIndexedRange(
+ NVRenderPathFontTarget::Enum, const void *, NVRenderPathFontStyleFlags,
+ NVRenderBackend::NVRenderBackendPathObject, QT3DSF32, QT3DSU32 *)
+ {
+ return NVRenderBackendPathObject(0);
+ }
+
+ void NVRenderBackendGLBase::GetPathMetrics(NVRenderBackendPathObject, size_t,
+ NVRenderPathGlyphFontMetricFlags,
+ NVRenderPathFormatType::Enum, const void *, size_t,
+ QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GetPathMetricsRange(NVRenderBackendPathObject, size_t,
+ NVRenderPathGlyphFontMetricFlags, size_t,
+ QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::GetPathSpacing(NVRenderBackendPathObject, size_t,
+ NVRenderPathListMode::Enum,
+ NVRenderPathFormatType::Enum, const void *, QT3DSF32,
+ QT3DSF32, NVRenderPathTransformType::Enum, QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::StencilFillPathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathFillMode::Enum, QT3DSU32,
+ NVRenderPathTransformType::Enum,
+ const QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::StencilStrokePathInstancedN(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum,
+ const void *, QT3DSI32, QT3DSU32,
+ NVRenderPathTransformType::Enum,
+ const QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::CoverFillPathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathCoverMode::Enum,
+ NVRenderPathTransformType::Enum,
+ const QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ void NVRenderBackendGLBase::CoverStrokePathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathCoverMode::Enum,
+ NVRenderPathTransformType::Enum,
+ const QT3DSF32 *)
+ {
+ // Needs GL 4 backend
+ QT3DS_ASSERT(false);
+ }
+
+ ///< private calls
+ const char *NVRenderBackendGLBase::getVersionString()
+ {
+ const char *retval = (const char *)GL_CALL_FUNCTION(glGetString(GL_VERSION));
+ if (retval == NULL)
+ return "";
+
+ return retval;
+ }
+
+ const char *NVRenderBackendGLBase::getVendorString()
+ {
+ const char *retval = (const char *)GL_CALL_FUNCTION(glGetString(GL_VENDOR));
+ if (retval == NULL)
+ return "";
+
+ return retval;
+ }
+
+ const char *NVRenderBackendGLBase::geRendererString()
+ {
+ const char *retval = (const char *)GL_CALL_FUNCTION(glGetString(GL_RENDERER));
+ if (retval == NULL)
+ return "";
+
+ return retval;
+ }
+
+ /**
+ * @brief This function inspects the various strings to setup
+ * HW capabilities of the device.
+ * We can do a lot of smart things here based on GL version
+ * renderer string and vendor.
+ *
+ * @return No return
+ */
+ void NVRenderBackendGLBase::setAndInspectHardwareCaps()
+ {
+ eastl::string apiVersion(getVersionString());
+ qCInfo(TRACE_INFO, "GL version: %s", apiVersion.c_str());
+
+ // we assume all GLES versions running on mobile with shared memory
+ // this means framebuffer blits are slow and should be optimized or avoided
+ if (apiVersion.find("OpenGL ES") == eastl::string::npos) {
+ // no ES device
+ m_backendSupport.caps.bits.bFastBlitsSupported = true;
+ }
+ }
+
+ void NVRenderBackendGLBase::checkGLError() const
+ {
+#if !defined(NDEBUG) || defined(_DEBUG)
+ GLenum error = m_glFunctions->glGetError();
+ if (error != GL_NO_ERROR) {
+ qCCritical(GL_ERROR) << GLConversion::processGLError(error);
+ QT3DS_ASSERT(false);
+ }
+#endif
+ }
+
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp
new file mode 100644
index 00000000..ec0445b3
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/backends/gl/Qt3DSRenderContextGL.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foundation/Qt3DSMat44.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Utils.h"
+#include "EASTL/set.h"
+#include "EASTL/utility.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace eastl;
+
+namespace qt3ds {
+namespace render {
+
+ NVRenderContext &NVRenderContext::CreateGL(NVFoundationBase &foundation,
+ IStringTable &inStringTable,
+ const QSurfaceFormat &format)
+ {
+ NVRenderContext *retval = NULL;
+
+ QT3DS_ASSERT(format.majorVersion() >= 2);
+
+ // create backend
+ NVScopedRefCounted<IStringTable> theStringTable(inStringTable);
+ NVScopedRefCounted<NVRenderBackend> theBackend;
+ bool isES = format.renderableType() == QSurfaceFormat::OpenGLES;
+ if (format.majorVersion() == 3 && format.minorVersion() >= 1 && !isES) {
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(foundation,
+ *theStringTable,
+ format);
+ } else if (format.majorVersion() == 4
+ || (isES && format.majorVersion() == 3 && format.minorVersion() >= 1)) {
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL4Impl)(foundation,
+ *theStringTable,
+ format);
+ } else {
+ QT3DS_ASSERT(false);
+ qCCritical(INTERNAL_ERROR) << "Can't find a suitable OpenGL version for" << format;
+ }
+
+
+ retval = QT3DS_NEW(foundation.getAllocator(), NVRenderContextImpl)(foundation, *theBackend,
+ *theStringTable);
+
+ return *retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp b/src/Runtime/Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp
new file mode 100644
index 00000000..af93e928
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSRender/Source/backends/software/Qt3DSRenderBackendNULL.cpp
@@ -0,0 +1,588 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "render/backends/software/Qt3DSRenderBackendNULL.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+
+#include <QSurfaceFormat>
+
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+using namespace qt3ds;
+
+namespace {
+struct SNullBackend : public NVRenderBackend
+{
+ NVFoundationBase &m_Foundation;
+ QT3DSI32 mRefCount;
+
+ SNullBackend(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ /// backend interface
+
+ NVRenderContextType GetRenderContextType() const override
+ {
+ return NVRenderContextValues::NullContext;
+ }
+ const char *GetShadingLanguageVersion() override { return ""; }
+ QT3DSU32 GetMaxCombinedTextureUnits() override { return 32; }
+ bool GetRenderBackendCap(NVRenderBackendCaps::Enum) const override { return false; }
+ void GetRenderBackendValue(NVRenderBackendQuery::Enum inQuery, QT3DSI32 *params) const override
+ {
+ if (params) {
+ switch (inQuery) {
+ case NVRenderBackendQuery::MaxTextureSize:
+ *params = 4096;
+ break;
+ case NVRenderBackendQuery::MaxTextureArrayLayers:
+ *params = 0;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ *params = 0;
+ break;
+ }
+ }
+ }
+ QT3DSU32 GetDepthBits() const override { return 16; }
+ QT3DSU32 GetStencilBits() const override { return 0; }
+ void SetRenderState(bool, const NVRenderState::Enum) override {}
+ bool GetRenderState(const NVRenderState::Enum) override { return false; }
+ virtual NVRenderBackendDepthStencilStateObject
+ CreateDepthStencilState(bool, bool, NVRenderBoolOp::Enum, bool,
+ NVRenderStencilFunctionArgument &, NVRenderStencilFunctionArgument &,
+ NVRenderStencilOperationArgument &, NVRenderStencilOperationArgument &) override
+ {
+ return NVRenderBackendDepthStencilStateObject(1);
+ }
+ void ReleaseDepthStencilState(NVRenderBackendDepthStencilStateObject) override {}
+ NVRenderBackendRasterizerStateObject CreateRasterizerState(QT3DSF32, QT3DSF32,
+ NVRenderFaces::Enum) override
+ {
+ return NVRenderBackendRasterizerStateObject(1);
+ }
+ void ReleaseRasterizerState(NVRenderBackendRasterizerStateObject) override {}
+ void SetDepthStencilState(NVRenderBackendDepthStencilStateObject) override {}
+ void SetRasterizerState(NVRenderBackendRasterizerStateObject) override {}
+ NVRenderBoolOp::Enum GetDepthFunc() override { return NVRenderBoolOp::Equal; }
+ void SetDepthFunc(const NVRenderBoolOp::Enum) override {}
+ bool GetDepthWrite() override { return false; }
+
+ void SetDepthWrite(bool) override {}
+ void SetColorWrites(bool, bool, bool, bool) override {}
+ void SetMultisample(bool) override {}
+ void GetBlendFunc(NVRenderBlendFunctionArgument *) override {}
+ void SetBlendFunc(const NVRenderBlendFunctionArgument &) override {}
+ void SetBlendEquation(const NVRenderBlendEquationArgument &) override {}
+ void SetBlendBarrier(void) override {}
+ void GetScissorRect(NVRenderRect *) override {}
+ void SetScissorRect(const NVRenderRect &) override {}
+ void GetViewportRect(NVRenderRect *) override {}
+ void SetViewportRect(const NVRenderRect &) override {}
+ void SetClearColor(const QT3DSVec4 *) override {}
+ void Clear(NVRenderClearFlags) override {}
+ NVRenderBackendBufferObject CreateBuffer(size_t, NVRenderBufferBindFlags,
+ NVRenderBufferUsageType::Enum, const void *) override
+ {
+ return NVRenderBackendBufferObject(1);
+ }
+ void BindBuffer(NVRenderBackendBufferObject, NVRenderBufferBindFlags) override {}
+ void ReleaseBuffer(NVRenderBackendBufferObject) override {}
+
+ void UpdateBuffer(NVRenderBackendBufferObject, NVRenderBufferBindFlags, size_t,
+ NVRenderBufferUsageType::Enum, const void *) override
+ {
+ }
+ void UpdateBufferRange(NVRenderBackendBufferObject, NVRenderBufferBindFlags, size_t, size_t,
+ const void *) override
+ {
+ }
+ void *MapBuffer(NVRenderBackendBufferObject, NVRenderBufferBindFlags, size_t, size_t,
+ NVRenderBufferAccessFlags) override
+ {
+ return NULL;
+ }
+ bool UnmapBuffer(NVRenderBackendBufferObject, NVRenderBufferBindFlags) override { return true; }
+ void SetMemoryBarrier(NVRenderBufferBarrierFlags) override {}
+ NVRenderBackendQueryObject CreateQuery() override { return NVRenderBackendQueryObject(1); }
+ void ReleaseQuery(NVRenderBackendQueryObject) override {}
+ void BeginQuery(NVRenderBackendQueryObject, NVRenderQueryType::Enum) override {}
+ void EndQuery(NVRenderBackendQueryObject, NVRenderQueryType::Enum) override {}
+ void GetQueryResult(NVRenderBackendQueryObject, NVRenderQueryResultType::Enum,
+ QT3DSU32 *) override {}
+ void GetQueryResult(NVRenderBackendQueryObject, NVRenderQueryResultType::Enum,
+ QT3DSU64 *) override {}
+ void SetQueryTimer(NVRenderBackendQueryObject) override {}
+ NVRenderBackendSyncObject CreateSync(NVRenderSyncType::Enum, NVRenderSyncFlags) override
+ {
+ return NVRenderBackendSyncObject(1);
+ };
+ void ReleaseSync(NVRenderBackendSyncObject) override {}
+ void WaitSync(NVRenderBackendSyncObject, NVRenderCommandFlushFlags, QT3DSU64) override {}
+ NVRenderBackendRenderTargetObject CreateRenderTarget() override
+ {
+ return NVRenderBackendRenderTargetObject(1);
+ }
+ void ReleaseRenderTarget(NVRenderBackendRenderTargetObject) override {}
+ void RenderTargetAttach(NVRenderBackendRenderTargetObject,
+ NVRenderFrameBufferAttachments::Enum,
+ NVRenderBackendRenderbufferObject) override
+ {
+ }
+ void RenderTargetAttach(NVRenderBackendRenderTargetObject,
+ NVRenderFrameBufferAttachments::Enum,
+ NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum) override
+ {
+ }
+ void RenderTargetAttach(NVRenderBackendRenderTargetObject,
+ NVRenderFrameBufferAttachments::Enum,
+ NVRenderBackendTextureObject, QT3DSI32, QT3DSI32) override
+ {
+ }
+ void SetRenderTarget(NVRenderBackendRenderTargetObject) override {}
+ bool RenderTargetIsValid(NVRenderBackendRenderTargetObject) override { return false; }
+ void SetReadTarget(NVRenderBackendRenderTargetObject) override {}
+ void SetDrawBuffers(NVRenderBackendRenderTargetObject, NVConstDataRef<QT3DSI32>) override {}
+ void SetReadBuffer(NVRenderBackendRenderTargetObject, NVReadFaces::Enum) override {}
+
+ void BlitFramebuffer(QT3DSI32, QT3DSI32, QT3DSI32, QT3DSI32, QT3DSI32, QT3DSI32, QT3DSI32, QT3DSI32,
+ NVRenderClearFlags, NVRenderTextureMagnifyingOp::Enum) override
+ {
+ }
+ NVRenderBackendRenderbufferObject CreateRenderbuffer(NVRenderRenderBufferFormats::Enum,
+ size_t, size_t) override
+ {
+ return NVRenderBackendRenderbufferObject(1);
+ }
+ void ReleaseRenderbuffer(NVRenderBackendRenderbufferObject) override {}
+
+ bool ResizeRenderbuffer(NVRenderBackendRenderbufferObject,
+ NVRenderRenderBufferFormats::Enum, size_t, size_t) override
+ {
+ return false;
+ }
+ NVRenderBackendTextureObject CreateTexture() override { return NVRenderBackendTextureObject(1); }
+
+ void SetTextureData2D(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum,
+ QT3DSU32, NVRenderTextureFormats::Enum, size_t, size_t, QT3DSI32,
+ NVRenderTextureFormats::Enum, const void *) override
+ {
+ }
+ void SetTextureDataCubeFace(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32,
+ NVRenderTextureFormats::Enum, size_t, size_t, QT3DSI32,
+ NVRenderTextureFormats::Enum, const void *) override
+ {
+ }
+ void CreateTextureStorage2D(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32,
+ NVRenderTextureFormats::Enum, size_t, size_t) override
+ {
+ }
+ void SetTextureSubData2D(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum,
+ QT3DSU32, QT3DSI32, QT3DSI32, size_t, size_t,
+ NVRenderTextureFormats::Enum, const void *) override
+ {
+ }
+ void SetCompressedTextureData2D(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32,
+ NVRenderTextureFormats::Enum, size_t, size_t, QT3DSI32,
+ size_t, const void *) override
+ {
+ }
+ void SetCompressedTextureDataCubeFace(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32,
+ NVRenderTextureFormats::Enum, size_t, size_t,
+ QT3DSI32, size_t, const void *) override
+ {
+ }
+ void SetCompressedTextureSubData2D(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, QT3DSU32, QT3DSI32, QT3DSI32,
+ size_t, size_t, NVRenderTextureFormats::Enum, size_t,
+ const void *) override
+ {
+ }
+ void SetMultisampledTextureData2D(NVRenderBackendTextureObject,
+ NVRenderTextureTargetType::Enum, size_t,
+ NVRenderTextureFormats::Enum, size_t, size_t, bool) override
+ {
+ }
+ void SetTextureData3D(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum,
+ QT3DSU32, NVRenderTextureFormats::Enum, size_t, size_t, size_t,
+ QT3DSI32, NVRenderTextureFormats::Enum, const void *) override
+ {
+ }
+ void GenerateMipMaps(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum,
+ NVRenderHint::Enum) override
+ {
+ }
+ void BindTexture(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum, QT3DSU32) override
+ {
+ }
+ void BindImageTexture(NVRenderBackendTextureObject, QT3DSU32, QT3DSI32, bool, QT3DSI32,
+ NVRenderImageAccessType::Enum, NVRenderTextureFormats::Enum) override
+ {
+ }
+ void ReleaseTexture(NVRenderBackendTextureObject) override {}
+
+ virtual NVRenderTextureSwizzleMode::Enum
+ GetTextureSwizzleMode(const NVRenderTextureFormats::Enum) const override
+ {
+ return NVRenderTextureSwizzleMode::NoSwizzle;
+ }
+
+ virtual NVRenderBackendSamplerObject
+ CreateSampler(NVRenderTextureMinifyingOp::Enum, NVRenderTextureMagnifyingOp::Enum,
+ NVRenderTextureCoordOp::Enum, NVRenderTextureCoordOp::Enum,
+ NVRenderTextureCoordOp::Enum, QT3DSI32, QT3DSI32, QT3DSF32,
+ NVRenderTextureCompareMode::Enum, NVRenderTextureCompareOp::Enum, QT3DSF32, QT3DSF32 *) override
+ {
+ return NVRenderBackendSamplerObject(1);
+ }
+
+ void UpdateSampler(NVRenderBackendSamplerObject, NVRenderTextureTargetType::Enum,
+ NVRenderTextureMinifyingOp::Enum, NVRenderTextureMagnifyingOp::Enum,
+ NVRenderTextureCoordOp::Enum, NVRenderTextureCoordOp::Enum,
+ NVRenderTextureCoordOp::Enum, QT3DSF32, QT3DSF32, QT3DSF32,
+ NVRenderTextureCompareMode::Enum, NVRenderTextureCompareOp::Enum,
+ QT3DSF32, QT3DSF32 *) override
+ {
+ }
+
+ void UpdateTextureObject(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum,
+ QT3DSI32, QT3DSI32) override
+ {
+ }
+
+ void UpdateTextureSwizzle(NVRenderBackendTextureObject, NVRenderTextureTargetType::Enum,
+ NVRenderTextureSwizzleMode::Enum) override
+ {
+ }
+
+ void ReleaseSampler(NVRenderBackendSamplerObject) override {}
+
+ virtual NVRenderBackendAttribLayoutObject
+ CreateAttribLayout(NVConstDataRef<NVRenderVertexBufferEntry>) override
+ {
+ return NVRenderBackendAttribLayoutObject(1);
+ }
+
+ void ReleaseAttribLayout(NVRenderBackendAttribLayoutObject) override {}
+
+ NVRenderBackendInputAssemblerObject CreateInputAssembler(
+ NVRenderBackendAttribLayoutObject, NVConstDataRef<NVRenderBackendBufferObject>,
+ const NVRenderBackendBufferObject, NVConstDataRef<QT3DSU32>, NVConstDataRef<QT3DSU32>, QT3DSU32) override
+ {
+ return NVRenderBackendInputAssemblerObject(1);
+ }
+ void ReleaseInputAssembler(NVRenderBackendInputAssemblerObject) override {}
+ bool SetInputAssembler(NVRenderBackendInputAssemblerObject,
+ NVRenderBackendShaderProgramObject) override
+ {
+ return false;
+ }
+ void SetPatchVertexCount(NVRenderBackendInputAssemblerObject, QT3DSU32) override {}
+ NVRenderBackendVertexShaderObject CreateVertexShader(NVConstDataRef<QT3DSI8>,
+ eastl::string &, bool) override
+ {
+ return NVRenderBackendVertexShaderObject(1);
+ }
+ void ReleaseVertexShader(NVRenderBackendVertexShaderObject) override {}
+ NVRenderBackendFragmentShaderObject CreateFragmentShader(NVConstDataRef<QT3DSI8>,
+ eastl::string &, bool) override
+ {
+ return NVRenderBackendFragmentShaderObject(1);
+ }
+ void ReleaseFragmentShader(NVRenderBackendFragmentShaderObject) override {}
+ NVRenderBackendTessControlShaderObject CreateTessControlShader(NVConstDataRef<QT3DSI8>,
+ eastl::string &, bool) override
+ {
+ return NVRenderBackendTessControlShaderObject(1);
+ }
+ void ReleaseTessControlShader(NVRenderBackendTessControlShaderObject) override {}
+ virtual NVRenderBackendTessEvaluationShaderObject
+ CreateTessEvaluationShader(NVConstDataRef<QT3DSI8>, eastl::string &, bool) override
+ {
+ return NVRenderBackendTessEvaluationShaderObject(1);
+ }
+ void ReleaseTessEvaluationShader(NVRenderBackendTessEvaluationShaderObject) override {}
+ NVRenderBackendGeometryShaderObject CreateGeometryShader(NVConstDataRef<QT3DSI8>,
+ eastl::string &, bool) override
+ {
+ return NVRenderBackendGeometryShaderObject(1);
+ }
+ void ReleaseGeometryShader(NVRenderBackendGeometryShaderObject) override {}
+ NVRenderBackendComputeShaderObject CreateComputeShader(NVConstDataRef<QT3DSI8>,
+ eastl::string &, bool) override
+ {
+ return NVRenderBackendComputeShaderObject(1);
+ }
+ void ReleaseComputeShader(NVRenderBackendComputeShaderObject) override {}
+ void AttachShader(NVRenderBackendShaderProgramObject, NVRenderBackendVertexShaderObject) override
+ {
+ }
+ void AttachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendFragmentShaderObject) override
+ {
+ }
+ void AttachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendTessControlShaderObject) override
+ {
+ }
+ void AttachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendTessEvaluationShaderObject) override
+ {
+ }
+ void AttachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendGeometryShaderObject) override
+ {
+ }
+ void AttachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendComputeShaderObject) override
+ {
+ }
+ void DetachShader(NVRenderBackendShaderProgramObject, NVRenderBackendVertexShaderObject) override
+ {
+ }
+ void DetachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendFragmentShaderObject) override
+ {
+ }
+ void DetachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendTessControlShaderObject) override
+ {
+ }
+ void DetachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendTessEvaluationShaderObject) override
+ {
+ }
+ void DetachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendGeometryShaderObject) override
+ {
+ }
+ void DetachShader(NVRenderBackendShaderProgramObject,
+ NVRenderBackendComputeShaderObject) override
+ {
+ }
+ NVRenderBackendShaderProgramObject CreateShaderProgram(bool) override
+ {
+ return NVRenderBackendShaderProgramObject(1);
+ }
+ void ReleaseShaderProgram(NVRenderBackendShaderProgramObject) override {}
+ NVRenderBackendProgramPipeline CreateProgramPipeline() override
+ {
+ return NVRenderBackendProgramPipeline(1);
+ }
+ void ReleaseProgramPipeline(NVRenderBackendProgramPipeline) override {}
+
+ bool LinkProgram(NVRenderBackendShaderProgramObject, eastl::string &) override { return false; }
+ void SetActiveProgram(NVRenderBackendShaderProgramObject) override {}
+ void SetActiveProgramPipeline(NVRenderBackendProgramPipeline) override {}
+ void SetProgramStages(NVRenderBackendProgramPipeline, NVRenderShaderTypeFlags,
+ NVRenderBackendShaderProgramObject) override {}
+ void DispatchCompute(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32, QT3DSU32) override {}
+ QT3DSI32 GetConstantCount(NVRenderBackendShaderProgramObject) override { return 0; }
+ QT3DSI32 GetConstantBufferCount(NVRenderBackendShaderProgramObject) override { return 0; }
+ QT3DSI32 GetConstantInfoByID(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32, QT3DSI32 *,
+ NVRenderShaderDataTypes::Enum *, QT3DSI32 *, char *) override
+ {
+ return 0;
+ }
+
+ QT3DSI32 GetConstantBufferInfoByID(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32,
+ QT3DSI32 *, QT3DSI32 *, QT3DSI32 *, char *) override
+ {
+ return 0;
+ }
+
+ void GetConstantBufferParamIndices(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSI32 *) override
+ {
+ }
+ void GetConstantBufferParamInfoByIndices(NVRenderBackendShaderProgramObject, QT3DSU32,
+ QT3DSU32 *, QT3DSI32 *, QT3DSI32 *, QT3DSI32 *) override {}
+ void ProgramSetConstantBlock(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32) override {}
+ void ProgramSetConstantBuffer(QT3DSU32, NVRenderBackendBufferObject) override {}
+
+ QT3DSI32 GetStorageBufferCount(NVRenderBackendShaderProgramObject) override { return 0; };
+ QT3DSI32 GetStorageBufferInfoByID(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32,
+ QT3DSI32 *, QT3DSI32 *, QT3DSI32 *, char *) override
+ {
+ return -1;
+ }
+ void ProgramSetStorageBuffer(QT3DSU32, NVRenderBackendBufferObject) override {}
+
+ QT3DSI32 GetAtomicCounterBufferCount(NVRenderBackendShaderProgramObject) override { return 0; }
+ QT3DSI32 GetAtomicCounterBufferInfoByID(NVRenderBackendShaderProgramObject, QT3DSU32, QT3DSU32,
+ QT3DSI32 *, QT3DSI32 *, QT3DSI32 *, char *) override
+ {
+ return -1;
+ };
+ void ProgramSetAtomicCounterBuffer(QT3DSU32, NVRenderBackendBufferObject) override {}
+
+ void SetConstantValue(NVRenderBackendShaderProgramObject, QT3DSU32,
+ NVRenderShaderDataTypes::Enum, QT3DSI32, const void *, bool) override
+ {
+ }
+
+ void Draw(NVRenderDrawMode::Enum, QT3DSU32, QT3DSU32) override {}
+ void DrawIndirect(NVRenderDrawMode::Enum, const void *) override {}
+
+ void DrawIndexed(NVRenderDrawMode::Enum, QT3DSU32, NVRenderComponentTypes::Enum,
+ const void *) override
+ {
+ }
+ void DrawIndexedIndirect(NVRenderDrawMode::Enum, NVRenderComponentTypes::Enum,
+ const void *) override
+ {
+ }
+
+ void ReadPixel(NVRenderBackendRenderTargetObject, QT3DSI32, QT3DSI32, QT3DSI32, QT3DSI32,
+ NVRenderReadPixelFormats::Enum, void *) override
+ {
+ }
+
+ NVRenderBackendPathObject CreatePathNVObject(size_t) override
+ {
+ return NVRenderBackendPathObject(1);
+ };
+ void SetPathSpecification(NVRenderBackendPathObject, NVConstDataRef<QT3DSU8>,
+ NVConstDataRef<QT3DSF32>) override
+ {
+ }
+
+ ///< Bounds of the fill and stroke
+ NVBounds3 GetPathObjectBoundingBox(NVRenderBackendPathObject /*inPathObject*/) override
+ {
+ return NVBounds3();
+ }
+ NVBounds3 GetPathObjectFillBox(NVRenderBackendPathObject /*inPathObject*/) override
+ {
+ return NVBounds3();
+ }
+ NVBounds3 GetPathObjectStrokeBox(NVRenderBackendPathObject /*inPathObject*/) override
+ {
+ return NVBounds3();
+ }
+
+ /**
+ * Defaults to 0 if unset.
+ */
+ void SetStrokeWidth(NVRenderBackendPathObject /*inPathObject*/, QT3DSF32) override {}
+ void SetPathProjectionMatrix(const QT3DSMat44 /*inPathProjection*/) override {}
+ void SetPathModelViewMatrix(const QT3DSMat44 /*inPathModelview*/) override {}
+
+ void SetPathStencilDepthOffset(QT3DSF32 /*inSlope*/, QT3DSF32 /*inBias*/) override {}
+ void SetPathCoverDepthFunc(NVRenderBoolOp::Enum /*inDepthFunction*/) override {}
+ void StencilStrokePath(NVRenderBackendPathObject /*inPathObject*/) override {}
+ void StencilFillPath(NVRenderBackendPathObject /*inPathObject*/) override {}
+ void ReleasePathNVObject(NVRenderBackendPathObject, size_t) override {}
+
+ void LoadPathGlyphs(NVRenderBackendPathObject, NVRenderPathFontTarget::Enum,
+ const void *, NVRenderPathFontStyleFlags, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathMissingGlyphs::Enum, NVRenderBackendPathObject, QT3DSF32) override
+ {
+ }
+ virtual NVRenderPathReturnValues::Enum
+ LoadPathGlyphsIndexed(NVRenderBackendPathObject, NVRenderPathFontTarget::Enum, const void *,
+ NVRenderPathFontStyleFlags, QT3DSU32, size_t, NVRenderBackendPathObject,
+ QT3DSF32) override
+ {
+ return NVRenderPathReturnValues::FontUnavailable;
+ }
+ NVRenderBackendPathObject LoadPathGlyphsIndexedRange(NVRenderPathFontTarget::Enum,
+ const void *,
+ NVRenderPathFontStyleFlags,
+ NVRenderBackendPathObject, QT3DSF32,
+ QT3DSU32 *) override
+ {
+ return NVRenderBackendPathObject(1);
+ }
+ void LoadPathGlyphRange(NVRenderBackendPathObject, NVRenderPathFontTarget::Enum,
+ const void *, NVRenderPathFontStyleFlags, QT3DSU32, size_t,
+ NVRenderPathMissingGlyphs::Enum, NVRenderBackendPathObject,
+ QT3DSF32) override
+ {
+ }
+ void GetPathMetrics(NVRenderBackendPathObject, size_t, NVRenderPathGlyphFontMetricFlags,
+ NVRenderPathFormatType::Enum, const void *, size_t, QT3DSF32 *) override
+ {
+ }
+ void GetPathMetricsRange(NVRenderBackendPathObject, size_t,
+ NVRenderPathGlyphFontMetricFlags, size_t, QT3DSF32 *) override
+ {
+ }
+ void GetPathSpacing(NVRenderBackendPathObject, size_t, NVRenderPathListMode::Enum,
+ NVRenderPathFormatType::Enum, const void *, QT3DSF32, QT3DSF32,
+ NVRenderPathTransformType::Enum, QT3DSF32 *) override
+ {
+ }
+
+ void StencilFillPathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathFillMode::Enum, QT3DSU32,
+ NVRenderPathTransformType::Enum, const QT3DSF32 *) override
+ {
+ }
+ void StencilStrokePathInstancedN(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *, QT3DSI32,
+ QT3DSU32, NVRenderPathTransformType::Enum, const QT3DSF32 *) override
+ {
+ }
+ void CoverFillPathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathCoverMode::Enum,
+ NVRenderPathTransformType::Enum, const QT3DSF32 *) override
+ {
+ }
+ void CoverStrokePathInstanced(NVRenderBackendPathObject, size_t,
+ NVRenderPathFormatType::Enum, const void *,
+ NVRenderPathCoverMode::Enum,
+ NVRenderPathTransformType::Enum, const QT3DSF32 *) override
+ {
+ }
+ QSurfaceFormat format() const override
+ {
+ return QSurfaceFormat();
+ }
+};
+}
+
+NVRenderBackend &NVRenderBackendNULL::CreateBackend(NVFoundationBase &foundation)
+{
+ return *QT3DS_NEW(foundation.getAllocator(), SNullBackend)(foundation);
+}
diff --git a/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateConfig.h b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateConfig.h
new file mode 100644
index 00000000..0252d1f7
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateConfig.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#ifdef _WIN32
+#if defined QT3DS_STATE_EXPORTS
+#define QT3DS_STATE_API __declspec(dllexport)
+#elif defined QT3DS_STATE_NO_EXPORTS
+#define QT3DS_STATE_API
+#else
+#define QT3DS_STATE_API __declspec(dllimport)
+#endif
+#else
+#define QT3DS_STATE_API
+#endif
diff --git a/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateEngine.h b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateEngine.h
new file mode 100644
index 00000000..64118554
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateEngine.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "foundation/Qt3DSRefCounted.h"
+
+#include "Qt3DSStateConfig.h"
+
+namespace qt3ds {
+
+class NVFoundation;
+
+namespace foundation {
+ class IStringTable;
+}
+}
+
+namespace Q3DStudio {
+class ITimeProvider;
+}
+
+namespace uic {
+namespace state {
+
+ class IInputStreamFactory;
+
+ class INDDStateEngine
+ {
+ public:
+ enum EStateEvent {
+ STATE_EVENT_UNKNOWN = 0,
+ STATE_EVENT_STATE_ENTER,
+ STATE_EVENT_STATE_EXIT,
+ STATE_EVENT_TRANSITION,
+ };
+ class IStateEventHandler
+ {
+ public:
+ virtual ~IStateEventHandler() {}
+ virtual void OnEvent() = 0;
+ };
+ class IStateEventHandlerConnection : public qt3ds::foundation::NVRefCounted
+ {
+ protected:
+ virtual ~IStateEventHandlerConnection() {}
+ public:
+ };
+
+ typedef qt3ds::foundation::NVScopedRefCounted<IStateEventHandlerConnection>
+ TStateEventHandlerConnectionPtr;
+
+ public:
+ virtual ~INDDStateEngine() {}
+
+ virtual bool Load(const char *inApplicationPath) = 0;
+ virtual bool Step() = 0;
+ virtual TStateEventHandlerConnectionPtr
+ RegisterEventHandler(EStateEvent inEvent, const char *inEventId,
+ IStateEventHandler &inHandler) = 0;
+ virtual void FireEvent(const char *inEventName, unsigned long long inDelay,
+ const char *inCancelId, bool inIsExternal = true) = 0;
+ virtual void FireEvent(const char *inEventName, bool inIsExternal = true) = 0;
+ virtual void CancelEvent(const char *inCancelId) = 0;
+
+ QT3DS_STATE_API static INDDStateEngine *
+ Create(qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> inFoundation,
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> inStringTable,
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory>
+ inInputStreamFactory,
+ Q3DStudio::ITimeProvider &inTimeProvider);
+
+ QT3DS_STATE_API static INDDStateEngine *Create();
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateInputStreamFactory.h b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateInputStreamFactory.h
new file mode 100644
index 00000000..11552f42
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateInputStreamFactory.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/string.h"
+
+#include "Qt3DSStateConfig.h"
+
+namespace uic {
+namespace state {
+
+ class IRefCountedInputStream : public qt3ds::foundation::ISeekableIOStream,
+ public qt3ds::foundation::NVRefCounted
+ {
+ protected:
+ virtual ~IRefCountedInputStream() {}
+ };
+
+ // This class is threadsafe.
+ class IInputStreamFactory : public qt3ds::foundation::NVRefCounted
+ {
+ protected:
+ virtual ~IInputStreamFactory() {}
+ public:
+ // These directories must have a '/' on them
+ virtual void AddSearchDirectory(const char8_t *inDirectory) = 0;
+ virtual IRefCountedInputStream *GetStreamForFile(const char8_t *inFilename,
+ bool inQuiet = false) = 0;
+ // Return a path for this file. Returns true if GetStreamForFile would return a valid
+ // stream.
+ // else returns false
+ virtual bool GetPathForFile(const char8_t *inFilename, eastl::string &outFile,
+ bool inQuiet = false) = 0;
+
+ // Create an input stream factory using this foundation and an platform-optional app
+ // directory
+ // on android the app directory has no effect; use use the assets bundled with the APK file.
+ QT3DS_STATE_API static IInputStreamFactory &Create(qt3ds::NVFoundationBase &inFoundation);
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateScriptBridge.h b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateScriptBridge.h
new file mode 100644
index 00000000..06b0e04f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Include/Qt3DSStateScriptBridge.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+#include "UICLuaIncludes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICTypes.h"
+
+struct lua_State;
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace uic {
+namespace state {
+
+ class INDDStateApplication;
+
+ namespace debugger {
+ class IMultiProtocolSocket;
+ }
+
+ //==============================================================================
+ /**
+ * @interface IScriptBridge
+ * @brief Callback and load interface for a script engine.
+ */
+
+ // class CScriptEngineCallFunctionArgRetriever
+ //{
+ // public:
+ // CScriptEngineCallFunctionArgRetriever( const char *inArguments ): m_ArgumentString(
+ //inArguments ) {}
+ // virtual ~CScriptEngineCallFunctionArgRetriever() {}
+ // // Retrieve argument
+ // // Return value: -1 error; otherwise it indicates argument count
+ // virtual int RetrieveArgument( lua_State *inState );
+ // virtual eastl::string GetArgDescription();
+ // protected:
+ // const char *m_ArgumentString;
+ //};
+
+ class INDDStateScriptBridge : public qt3ds::foundation::NVRefCounted
+ {
+ //==============================================================================
+ // Methods
+ //==============================================================================
+ public: // Construction
+ virtual ~INDDStateScriptBridge() {}
+
+ public: // thread
+ // After this call all public functions are protected by a mutex
+ virtual void EnableMultithreadedAccess() = 0;
+ // After this call all public functions are not threadsafe.
+ virtual void DisableMultithreadedAccess() = 0;
+
+ public: // Settings
+ virtual void SetApplication(uic::state::INDDStateApplication &inApplication) = 0;
+
+ public: // Binary preloading
+ // Starts preloading scripts offline. This sets m_LuaState to NULL until after
+ // EndPreloadScripts
+ // This function is only used for binary loading, eg, .uiab
+ // virtual void BeginPreloadScripts( const eastl::vector<const char*>& inScripts,
+ // uic::render::IThreadPool& inThreadPool, const char* inProjectDir ) = 0;
+ // This function is blocking if m_LuaState == NULL, which only holds during binary loading
+ // virtual void EndPreloadScripts() = 0;
+ // Fast loading support
+ // get the set of loaded scripts relative file names
+ // This has the side effect of writing out the loaded scripts to
+ // projectDir/binary/compiledlua.bin, only used for binary save
+ virtual eastl::vector<eastl::string> GetLoadedScripts() = 0;
+
+ public: // Scripts
+ virtual Q3DStudio::INT32
+ InitializeApplicationBehavior(const char *inProjectRelativePath) = 0;
+
+ public: // Script functions and Callbacks
+ // Call a member function inFnName from self table whose script index is given by inApp
+ virtual void ExecuteApplicationScriptFunction(Q3DStudio::INT32 inApp,
+ const char *inFnName) = 0;
+ // virtual void CallFunction( const char* behavior, const char* handler,
+ // CScriptEngineCallFunctionArgRetriever &inArgRetriever ) = 0;
+
+ public: // Miscellaneous
+ // use lua_register to register a global function, this is useful to call from outside
+ virtual void AddGlobalFunction(const Q3DStudio::CHAR *inFunctionName,
+ lua_CFunction inFunction) = 0;
+ // virtual void
+ // EnableDebugging(uic::state::debugger::IMultiProtocolSocket& socket ) = 0;
+ // virtual void EnableProfiling() = 0;
+ virtual void StepGC() = 0;
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateApplication.h b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateApplication.h
new file mode 100644
index 00000000..4e842921
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateApplication.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICTypes.h"
+
+namespace uic {
+namespace state {
+
+ class INDDStateApplication : public qt3ds::foundation::NVRefCounted
+ {
+ public:
+ virtual ~INDDStateApplication() {}
+
+ virtual double GetMillisecondsSinceLastFrame() = 0;
+ virtual Q3DStudio::INT32 GetFrameCount() = 0;
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateContext.h b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateContext.h
new file mode 100644
index 00000000..3142c119
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateContext.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "Qt3DSStateInputStreamFactory.h"
+#include "Qt3DSStateFactory.h"
+
+namespace Q3DStudio {
+class ITimeProvider;
+}
+
+namespace uic {
+namespace state {
+
+ class INDDStateFactory;
+
+ struct SNDDStateContext : public qt3ds::foundation::NVRefCounted
+ {
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> m_Foundation;
+ qt3ds::NVAllocatorCallback &m_Allocator;
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> m_StringTable;
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory> m_InputStreamFactory;
+ Q3DStudio::ITimeProvider &m_TimeProvider;
+ qt3ds::foundation::NVScopedRefCounted<INDDStateFactory> m_Factory;
+ eastl::string m_ProjectDir;
+ volatile qt3ds::QT3DSI32 mRefCount;
+
+ SNDDStateContext(
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> inFoundation,
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> inStringTable,
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory>
+ inInputStreamFactory,
+ Q3DStudio::ITimeProvider &inTimeProvider, const char *inProjectDir)
+ : m_Foundation(inFoundation)
+ , m_Allocator(m_Foundation->getAllocatorCallback())
+ , m_StringTable(inStringTable)
+ , m_InputStreamFactory(inInputStreamFactory)
+ , m_TimeProvider(inTimeProvider)
+ , m_Factory(0)
+ , m_ProjectDir(inProjectDir)
+ , mRefCount(0)
+ {
+ m_Factory = INDDStateFactory::Create(*this);
+ }
+ virtual ~SNDDStateContext()
+ {
+ qCDebug (qt3ds::TRACE_INFO) << "SNDDStateContext destructing";
+ }
+
+ void addRef() override { qt3ds::foundation::atomicIncrement(&mRefCount); }
+ void release() override
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ QT3DS_IMPLEMENT_REF_COUNT_RELEASE(m_Allocator);
+ }
+
+ qt3ds::NVAllocatorCallback &GetAllocator() { return m_Allocator; }
+ qt3ds::foundation::IStringTable &GetStringTable() { return *m_StringTable; }
+ const char *GetProjectDir() { return m_ProjectDir.c_str(); }
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateFactory.h b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateFactory.h
new file mode 100644
index 00000000..1482d11d
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateFactory.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "foundation/Qt3DSRefCounted.h"
+
+namespace uic {
+namespace state {
+ class IVisualStateContext;
+}
+}
+
+namespace uic {
+namespace evt {
+ class IEventSystem;
+}
+}
+
+namespace qt3ds {
+class NVFoundationBase;
+namespace foundation {
+ class IStringTable;
+ class IPerfTimer;
+ class CRegisteredString;
+}
+}
+
+namespace Q3DStudio {
+class ITimeProvider;
+}
+
+namespace uic {
+namespace state {
+
+ struct SNDDStateContext;
+ class INDDStateScriptBridge;
+ class IInputStreamFactory;
+ class INDDStateApplication;
+ class IVisualStateInterpreterFactory;
+ class IStateInterpreter;
+
+ class INDDStateFactory : public qt3ds::foundation::NVRefCounted
+ {
+ public:
+ class IStateInterpreterCreateCallback
+ {
+ public:
+ virtual ~IStateInterpreterCreateCallback() {}
+ virtual void OnCreate(const qt3ds::foundation::CRegisteredString &inId,
+ IStateInterpreter &inStateInterpreter) = 0;
+ };
+ virtual uic::state::INDDStateScriptBridge &GetScriptEngine() = 0;
+ virtual uic::state::IVisualStateContext &GetVisualStateContext() = 0;
+ virtual uic::evt::IEventSystem &GetEventSystem() = 0;
+ virtual qt3ds::NVFoundationBase &GetFoundation() = 0;
+ virtual qt3ds::foundation::IStringTable &GetStringTable() = 0;
+ virtual Q3DStudio::ITimeProvider &GetTimeProvider() = 0;
+ virtual uic::state::IInputStreamFactory &GetInputStreamFactory() = 0;
+
+ virtual uic::state::INDDStateApplication *GetApplication() = 0;
+ virtual void SetApplication(uic::state::INDDStateApplication *inApplication) = 0;
+ virtual void SetStateInterpreterCreateCallback(
+ IStateInterpreterCreateCallback &inStateInterpreterCreateCallback) = 0;
+
+ static INDDStateFactory &Create(SNDDStateContext &inContext);
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateLuaEngine.h b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateLuaEngine.h
new file mode 100644
index 00000000..f9b324f0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/InternalInclude/Qt3DSStateLuaEngine.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Studio Includes
+//==============================================================================
+#include "UICIScriptBridge.h"
+#include "EASTL/map.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSMutex.h"
+#include "UICIComponentManager.h"
+#include "Qt3DSStateContext.h"
+
+#include "Qt3DSStateScriptBridge.h"
+
+namespace Q3DStudio {
+class ITimeProvider;
+}
+
+namespace uic {
+namespace state {
+
+ struct SNDDStateContext;
+ class IStateInterpreter;
+
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+ typedef void (*TLuaLibraryLoader)(lua_State *);
+
+ //==============================================================================
+ // Global Lua Library Loader
+ //==============================================================================
+ extern TLuaLibraryLoader LoadLuaLibraries;
+
+ class INDDStateLuaEngine : public INDDStateScriptBridge
+ {
+ public:
+ virtual ~INDDStateLuaEngine() {}
+
+ public: // Public functions but not functions on the script bridge
+ virtual uic::state::IStateInterpreter *
+ CreateStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodelFunction) = 0;
+ virtual void PreInitialize() = 0;
+ virtual void Initialize() = 0;
+ virtual void Shutdown(qt3ds::NVFoundationBase &inFoundation) = 0;
+
+ public:
+ static INDDStateLuaEngine *Create(uic::state::SNDDStateContext &inContext);
+ };
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateEngine.cpp b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateEngine.cpp
new file mode 100644
index 00000000..566ebffa
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateEngine.cpp
@@ -0,0 +1,1135 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSStateEngine.h"
+
+#include <cassert>
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
+#include "foundation/XML.h"
+#include "foundation/FileTools.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSTime.h"
+
+#include "UICKernelTypes.h"
+#include "UICStateVisualBindingContext.h"
+#include "UICTypes.h"
+#include "UICTimer.h"
+#include "UICStateInterpreter.h"
+#include "EventPollingSystem.h"
+
+#include "Qt3DSStateContext.h"
+#include "Qt3DSStateFactory.h"
+#include "Qt3DSStateLuaEngine.h"
+#include "Qt3DSStateApplication.h"
+
+namespace {
+
+using namespace uic::state;
+using qt3ds::NVFoundationBase;
+using qt3ds::foundation::NVConstDataRef;
+using qt3ds::foundation::IDOMReader;
+using qt3ds::foundation::CFileTools;
+using qt3ds::foundation::Time;
+
+struct AssetValueTypes
+{
+ enum Enum {
+ NoAssetValue = 0,
+ SCXML,
+ Behavior,
+ };
+};
+
+struct SAssetBase
+{
+ CRegisteredString m_Id;
+ CRegisteredString m_Src;
+ SAssetBase(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inSrc = CRegisteredString())
+ : m_Id(inId)
+ , m_Src(inSrc)
+ {
+ }
+ bool operator==(const SAssetBase &inOther) const
+ {
+ return m_Id == inOther.m_Id && m_Src == inOther.m_Src;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ item.Remap(m_Id);
+ item.Remap(m_Src);
+ }
+};
+
+struct SSCXMLAsset : public SAssetBase
+{
+ CRegisteredString m_Datamodel;
+ SSCXMLAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(),
+ CRegisteredString inDatamodel = CRegisteredString())
+ : SAssetBase(inId, inRelPath)
+ , m_Datamodel(inDatamodel)
+ {
+ }
+ bool operator==(const SSCXMLAsset &inOther) const
+ {
+ return SAssetBase::operator==(inOther) && m_Datamodel == inOther.m_Datamodel;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ SAssetBase::Remap(item);
+ item.Remap(m_Datamodel);
+ }
+};
+
+struct SBehaviorAsset : public SAssetBase
+{
+ Q3DStudio::INT32 m_Handle;
+ SBehaviorAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(), Q3DStudio::INT32 inHandle = 0)
+ : SAssetBase(inId, inRelPath)
+ , m_Handle(inHandle)
+ {
+ }
+ bool operator==(const SBehaviorAsset &inOther) const
+ {
+ return SAssetBase::operator==(inOther) && m_Handle == inOther.m_Handle;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ m_Handle = -1;
+ SAssetBase::Remap(item);
+ }
+};
+}
+
+namespace qt3ds {
+namespace foundation {
+ template <>
+ struct DestructTraits<SSCXMLAsset>
+ {
+ void destruct(SSCXMLAsset &) {}
+ };
+ template <>
+ struct DestructTraits<SBehaviorAsset>
+ {
+ void destruct(SBehaviorAsset &) {}
+ };
+}
+}
+
+namespace {
+
+template <typename TDataType>
+struct SAssetValueTypeMap
+{
+};
+
+struct SAssetValueUnionTraits
+{
+ typedef AssetValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(SSCXMLAsset),
+ };
+
+ static TIdType getNoDataId() { return AssetValueTypes::NoAssetValue; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SAssetValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case AssetValueTypes::SCXML:
+ return inVisitor(*NVUnionCast<SSCXMLAsset *>(inData));
+ case AssetValueTypes::Behavior:
+ return inVisitor(*NVUnionCast<SBehaviorAsset *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case AssetValueTypes::NoAssetValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case AssetValueTypes::SCXML:
+ return inVisitor(*NVUnionCast<const SSCXMLAsset *>(inData));
+ case AssetValueTypes::Behavior:
+ return inVisitor(*NVUnionCast<const SBehaviorAsset *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case AssetValueTypes::NoAssetValue:
+ return inVisitor();
+ }
+ }
+};
+
+template <>
+struct SAssetValueTypeMap<SSCXMLAsset>
+{
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::SCXML; }
+};
+template <>
+struct SAssetValueTypeMap<SBehaviorAsset>
+{
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::Behavior; }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SAssetValueUnionTraits,
+ SAssetValueUnionTraits::TBufferSize>,
+ SAssetValueUnionTraits::TBufferSize>
+ TAssetValueUnionType;
+
+struct SAssetValue : public TAssetValueUnionType
+{
+ SAssetValue() {}
+
+ SAssetValue(const SAssetValue &inOther)
+ : TAssetValueUnionType(static_cast<const TAssetValueUnionType &>(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SAssetValue(const TDataType &inDt)
+ : TAssetValueUnionType(inDt)
+ {
+ }
+
+ SAssetValue &operator=(const SAssetValue &inOther)
+ {
+ TAssetValueUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SAssetValue &inOther) const
+ {
+ return TAssetValueUnionType::operator==(inOther);
+ }
+ bool operator!=(const SAssetValue &inOther) const
+ {
+ return TAssetValueUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == AssetValueTypes::NoAssetValue; }
+
+ CRegisteredString GetSource()
+ {
+ if (empty())
+ return CRegisteredString();
+ return reinterpret_cast<SAssetBase *>(m_Data)->m_Src;
+ }
+};
+
+struct SRefCountedAssetValue : public SAssetValue
+{
+ NVFoundationBase &m_Foundation;
+ QT3DSI32 mRefCount;
+ SRefCountedAssetValue(NVFoundationBase &fnd)
+ : SAssetValue()
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SAssetValue &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SBehaviorAsset &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SSCXMLAsset &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+};
+
+struct SAppXMLErrorHandler : public qt3ds::foundation::CXmlErrorHandler
+{
+ NVFoundationBase &m_Foundation;
+ const char8_t *m_FilePath;
+ SAppXMLErrorHandler(NVFoundationBase &fnd, const char8_t *filePath)
+ : m_Foundation(fnd)
+ , m_FilePath(filePath)
+ {
+ }
+
+ void OnXmlError(TXMLCharPtr errorName, int line, int /*column*/) override
+ {
+ qCCritical(INVALID_OPERATION, m_FilePath, line, "%s", errorName);
+ }
+};
+
+// State event handler
+struct SStateEventHandlerKey
+{
+ SStateEventHandlerKey(INDDStateEngine::EStateEvent inEvent,
+ const qt3ds::foundation::CRegisteredString &inEventId)
+ : m_Event(inEvent)
+ , m_EventId(inEventId)
+ {
+ }
+ INDDStateEngine::EStateEvent m_Event;
+ qt3ds::foundation::CRegisteredString m_EventId;
+ bool operator<(const SStateEventHandlerKey &inArg) const
+ {
+ if (m_Event != inArg.m_Event)
+ return m_Event < inArg.m_Event;
+ return m_EventId < inArg.m_EventId;
+ }
+};
+struct SStateCallbackConnection;
+typedef eastl::multimap<SStateEventHandlerKey, SStateCallbackConnection *> TStateEventHandlerMap;
+
+struct SStateInterpreterResource;
+
+struct SStateCallbackConnection : public INDDStateEngine::IStateEventHandlerConnection
+{
+ NVAllocatorCallback &m_Alloc;
+ SStateInterpreterResource *m_StateInterpreterResource;
+ INDDStateEngine::IStateEventHandler &m_Handler;
+
+ volatile QT3DSI32 mRefCount;
+
+ SStateCallbackConnection(NVAllocatorCallback &inAlloc,
+ SStateInterpreterResource &inStateInterpreterResource,
+ INDDStateEngine::IStateEventHandler &inHandler)
+ : m_Alloc(inAlloc)
+ , m_StateInterpreterResource(&inStateInterpreterResource)
+ , m_Handler(inHandler)
+ , mRefCount(0)
+ {
+ }
+ virtual ~SStateCallbackConnection();
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Alloc)
+};
+
+struct SStateInterpreterEventHandler : public uic::state::IStateInterpreterEventHandler
+{
+public:
+ SStateInterpreterResource &m_StateInterpreterResource;
+
+ SStateInterpreterEventHandler(SStateInterpreterResource &inStateInterpreterResource)
+ : m_StateInterpreterResource(inStateInterpreterResource)
+ {
+ }
+
+ virtual ~SStateInterpreterEventHandler() {}
+
+ void OnInterpreterEvent(uic::state::InterpreterEventTypes::Enum inEvent,
+ qt3ds::foundation::CRegisteredString inEventId) override;
+};
+
+struct SStateEventHandlersWithLock
+{
+ SStateEventHandlersWithLock(qt3ds::NVAllocatorCallback &inAllocator)
+ : m_HandlersLock(inAllocator)
+ {
+ }
+ TStateEventHandlerMap m_StateEventHandlers;
+ qt3ds::foundation::Mutex m_HandlersLock;
+};
+
+struct SStateInterpreterResource : public qt3ds::foundation::NVRefCounted
+{
+public:
+ qt3ds::NVAllocatorCallback &m_Allocator;
+ uic::state::IStateInterpreter *m_StateInterpreter;
+
+private:
+ SStateEventHandlersWithLock m_StateEventHandlersWithLock;
+
+public:
+ SStateInterpreterEventHandler *m_StateInterpreterEventHandler;
+ uic::state::TSignalConnectionPtr m_SignalConnection;
+
+ volatile QT3DSI32 mRefCount;
+
+ SStateInterpreterResource(qt3ds::NVAllocatorCallback &inAllocator)
+ : m_Allocator(inAllocator)
+ , m_StateInterpreter(0)
+ , m_StateEventHandlersWithLock(m_Allocator)
+ , m_StateInterpreterEventHandler(0)
+ , m_SignalConnection(0)
+ , mRefCount(0)
+ {
+ m_StateInterpreterEventHandler = QT3DS_NEW(m_Allocator, SStateInterpreterEventHandler)(*this);
+ }
+ virtual ~SStateInterpreterResource()
+ {
+ m_StateInterpreter = 0;
+ m_SignalConnection = 0;
+ SStateInterpreterEventHandler *theStateInterpreterEventHandler =
+ m_StateInterpreterEventHandler;
+ m_StateInterpreterEventHandler = 0;
+ NVDelete(m_Allocator, theStateInterpreterEventHandler);
+ {
+ qt3ds::foundation::Mutex::ScopedLock theLock(m_StateEventHandlersWithLock.m_HandlersLock);
+ for (TStateEventHandlerMap::iterator
+ theIter = m_StateEventHandlersWithLock.m_StateEventHandlers.begin(),
+ theEnd = m_StateEventHandlersWithLock.m_StateEventHandlers.end();
+ theIter != theEnd; ++theIter)
+ theIter->second->m_StateInterpreterResource = 0;
+ }
+ }
+
+ void DeleteHandlerByConnection(SStateCallbackConnection &inConnection)
+ {
+ qt3ds::foundation::Mutex::ScopedLock theLock(m_StateEventHandlersWithLock.m_HandlersLock);
+ TStateEventHandlerMap &theStateEventHandlers =
+ m_StateEventHandlersWithLock.m_StateEventHandlers;
+ for (TStateEventHandlerMap::iterator theIter = theStateEventHandlers.begin(),
+ theEnd = theStateEventHandlers.end();
+ theIter != theEnd;) {
+ if (theIter->second == &inConnection)
+ theStateEventHandlers.erase(theIter++);
+ else
+ ++theIter;
+ }
+ }
+
+ bool InsertConnection(const SStateEventHandlerKey &inKey,
+ SStateCallbackConnection &inConnection)
+ {
+ qt3ds::foundation::Mutex::ScopedLock theLock(m_StateEventHandlersWithLock.m_HandlersLock);
+ eastl::pair<TStateEventHandlerMap::iterator, bool> theResult =
+ m_StateEventHandlersWithLock.m_StateEventHandlers.insert(
+ eastl::make_pair<SStateEventHandlerKey, SStateCallbackConnection *>(inKey,
+ &inConnection));
+ return theResult.second;
+ }
+
+ void TriggerCallbackOnEvent(uic::state::InterpreterEventTypes::Enum inEvent,
+ const qt3ds::foundation::CRegisteredString &inEventId)
+ {
+ qt3ds::foundation::Mutex::ScopedLock theLock(m_StateEventHandlersWithLock.m_HandlersLock);
+ eastl::pair<TStateEventHandlerMap::iterator, TStateEventHandlerMap::iterator> theRange =
+ m_StateEventHandlersWithLock.m_StateEventHandlers.equal_range(
+ SStateEventHandlerKey((INDDStateEngine::EStateEvent)inEvent, inEventId));
+ for (TStateEventHandlerMap::iterator theIter = theRange.first; theIter != theRange.second;
+ ++theIter)
+ theIter->second->m_Handler.OnEvent();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+};
+
+SStateCallbackConnection::~SStateCallbackConnection()
+{
+ if (m_StateInterpreterResource) {
+ m_StateInterpreterResource->DeleteHandlerByConnection(*this);
+ }
+}
+
+void SStateInterpreterEventHandler::OnInterpreterEvent(
+ uic::state::InterpreterEventTypes::Enum inEvent, qt3ds::foundation::CRegisteredString inEventId)
+{
+ qCDebug (qt3ds::TRACE_INFO) << "SStateInterpreterEventHandler: OnInterpreterEvent: event type: "
+ << inEvent << " event ID: " << inEventId.c_str();
+ m_StateInterpreterResource.TriggerCallbackOnEvent(inEvent, inEventId);
+}
+
+typedef eastl::map<qt3ds::foundation::CRegisteredString,
+ qt3ds::foundation::NVScopedRefCounted<SStateInterpreterResource>>
+ TStateInterpreterResourceMap;
+
+struct SStateInterpreterCreateCallback
+ : public uic::state::INDDStateFactory::IStateInterpreterCreateCallback
+{
+public:
+ TStateInterpreterResourceMap &m_StateInterpreterResourceMap;
+ SStateInterpreterCreateCallback(TStateInterpreterResourceMap &inStateInterpreterResourceMap)
+ : m_StateInterpreterResourceMap(inStateInterpreterResourceMap)
+ {
+ }
+ virtual ~SStateInterpreterCreateCallback() {}
+ void OnCreate(const qt3ds::foundation::CRegisteredString &inId,
+ uic::state::IStateInterpreter &inStateInterpreter) override
+ {
+ TStateInterpreterResourceMap::iterator thePos = m_StateInterpreterResourceMap.find(inId);
+ if (thePos == m_StateInterpreterResourceMap.end()) {
+ qCCritical(qt3ds::TRACE_INFO)
+ << "SStateInterpreterCreateCallback::OnCreate: Interpreter ID not found";
+ return;
+ }
+ thePos->second->m_StateInterpreter = &inStateInterpreter;
+ thePos->second->m_SignalConnection = inStateInterpreter.RegisterEventHandler(
+ *thePos->second->m_StateInterpreterEventHandler);
+ }
+};
+
+struct SApp : public uic::state::INDDStateApplication
+{
+public:
+ typedef nvvector<eastl::pair<CRegisteredString, NVScopedRefCounted<SRefCountedAssetValue>>>
+ TIdAssetList;
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<SRefCountedAssetValue>> TIdAssetMap;
+
+ SNDDStateContext &m_Context;
+ TStateInterpreterResourceMap &m_StateInterpreters;
+ TIdAssetList m_OrderedAssets;
+ TIdAssetMap m_AssetMap;
+ nvvector<eastl::pair<SBehaviorAsset, bool>> m_Behaviors;
+ Q3DStudio::INT32 m_FrameCount;
+ QT3DSU64 m_LastFrameStartTime;
+ QT3DSU64 m_ThisFrameStartTime;
+ double m_MillisecondsSinceLastFrame;
+ bool m_IsLoaded;
+
+ QT3DSI32 mRefCount;
+
+ SApp(SNDDStateContext &inContext, TStateInterpreterResourceMap &inStateInterpreters)
+ : m_Context(inContext)
+ , m_StateInterpreters(inStateInterpreters)
+ , m_OrderedAssets(m_Context.GetAllocator(), "SApp::m_OrderedAssets")
+ , m_AssetMap(m_Context.GetAllocator(), "SApp::m_AssetMap")
+ , m_Behaviors(m_Context.GetAllocator(), "SApp::m_Behaviors")
+ , m_FrameCount(0)
+ , m_LastFrameStartTime(0)
+ , m_ThisFrameStartTime(0)
+ , m_MillisecondsSinceLastFrame(0)
+ , m_IsLoaded(false)
+ , mRefCount(0)
+ {
+ }
+ virtual ~SApp()
+ {
+ qCDebug (qt3ds::TRACE_INFO) << "SApp: destructing";
+ }
+
+ double GetMillisecondsSinceLastFrame() override { return m_MillisecondsSinceLastFrame; }
+
+ Q3DStudio::INT32 GetFrameCount() override { return m_FrameCount; }
+
+ CRegisteredString RegisterStr(const char8_t *inStr)
+ {
+ return m_Context.GetStringTable().RegisterStr(inStr);
+ }
+
+ bool LoadUIA(IDOMReader &inReader, NVFoundationBase &fnd)
+ {
+ m_IsLoaded = false;
+ NVConstDataRef<uic::state::SElementReference> theStateReferences;
+ {
+ IDOMReader::Scope __preparseScope(inReader);
+ theStateReferences =
+ m_Context.m_Factory->GetVisualStateContext().PreParseDocument(inReader);
+ }
+ {
+ IDOMReader::Scope __assetsScope(inReader);
+ if (!inReader.MoveToFirstChild("assets")) {
+ qCCritical(INVALID_OPERATION, "UIA input xml doesn't contain <assets> tag; load failed");
+ return m_IsLoaded;
+ }
+
+ eastl::string pathString;
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __assetScope(inReader);
+ const char8_t *itemId("");
+ inReader.UnregisteredAtt("id", itemId);
+ const char8_t *src = "";
+ inReader.UnregisteredAtt("src", src);
+ pathString.clear();
+ if (!isTrivial(src))
+ CFileTools::CombineBaseAndRelative(m_Context.GetProjectDir(), src, pathString);
+
+ const char8_t *assetName = inReader.GetElementName();
+ if (AreEqual(assetName, "statemachine")) {
+ const char8_t *dm = "";
+ inReader.UnregisteredAtt("datamodel", dm);
+ LoadSCXML(itemId, src, dm, false);
+ RegisterAsset(
+ SSCXMLAsset(RegisterStr(itemId), RegisterStr(src), RegisterStr(dm)));
+ } else if (AreEqual(assetName, "behavior")) {
+ SBehaviorAsset theAsset(RegisterStr(itemId), RegisterStr(src), 0);
+ RegisterAsset(theAsset);
+ } else {
+ qCWarning(WARNING, "Unrecognized <assets> child %s", assetName);
+ }
+ }
+ } // end assets scope
+
+ {
+ IDOMReader::Scope __machineScope(inReader);
+ m_Context.m_Factory->GetVisualStateContext().LoadVisualStateMapping(inReader);
+ }
+
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ SAssetValue &theAsset = *m_OrderedAssets[idx].second;
+ eastl::string thePathStr;
+ CFileTools::CombineBaseAndRelative(m_Context.GetProjectDir(), theAsset.GetSource(),
+ thePathStr);
+ switch (theAsset.getType()) {
+ case AssetValueTypes::Behavior: {
+ SBehaviorAsset &theBehaviorAsset = *theAsset.getDataPtr<SBehaviorAsset>();
+ Q3DStudio::INT32 scriptId =
+ m_Context.m_Factory->GetScriptEngine().InitializeApplicationBehavior(
+ theBehaviorAsset.m_Src);
+ if (scriptId == 0)
+ qCCritical(INVALID_OPERATION, "Unable to load application behavior %s",
+ theBehaviorAsset.m_Src.c_str());
+ else {
+ theBehaviorAsset.m_Handle = scriptId;
+ m_Behaviors.push_back(eastl::make_pair(theBehaviorAsset, false));
+ }
+ } break;
+ // SCXML, NoAssetValue do not need processing here
+ default:
+ break;
+ }
+ }
+ m_IsLoaded = true;
+ return m_IsLoaded;
+ }
+
+ bool LoadSCXML(const char *inId, const char *inSourcePath, const char *inDatamodel,
+ bool inIsStandalone = true)
+ {
+ if (inIsStandalone)
+ m_IsLoaded = false;
+
+ m_Context.m_Factory->GetVisualStateContext().LoadStateMachine(inId, inSourcePath,
+ nonNull(inDatamodel));
+ m_StateInterpreters.insert(
+ eastl::make_pair<qt3ds::foundation::CRegisteredString,
+ qt3ds::foundation::NVScopedRefCounted<SStateInterpreterResource>>(
+ RegisterStr(inId), QT3DS_NEW(m_Context.GetAllocator(),
+ SStateInterpreterResource)(m_Context.GetAllocator())));
+
+ if (inIsStandalone) {
+ m_IsLoaded = true;
+ return m_IsLoaded;
+ } else
+ return true;
+ }
+
+ bool IsLoaded() { return m_IsLoaded; }
+
+ void Update()
+ {
+ if (!IsLoaded()) {
+ qCCritical(qt3ds::TRACE_INFO) << "CNDDStateEngine: Application not loaded";
+ return;
+ }
+ m_ThisFrameStartTime = qt3ds::foundation::Time::getCurrentCounterValue();
+ if (m_LastFrameStartTime) {
+ QT3DSU64 durationSinceLastFrame = m_ThisFrameStartTime - m_LastFrameStartTime;
+ m_MillisecondsSinceLastFrame =
+ qt3ds::foundation::Time::sCounterFreq.toTensOfNanos(durationSinceLastFrame)
+ * (1.0 / 100000.0);
+ } else
+ m_MillisecondsSinceLastFrame = 0;
+
+ // if ( m_ProtocolSocket ) m_ProtocolSocket->MessagePump();
+ ++m_FrameCount;
+
+ // Update any state systems
+ m_Context.m_Factory->GetVisualStateContext().Initialize();
+
+ // First off, update any application level behaviors.
+ INDDStateScriptBridge &theScriptEngine = m_Context.m_Factory->GetScriptEngine();
+ for (QT3DSU32 idx = 0, end = m_Behaviors.size(); idx < end; ++idx) {
+ eastl::pair<SBehaviorAsset, bool> &entry(m_Behaviors[idx]);
+ if (!entry.second) {
+ entry.second = true;
+ theScriptEngine.ExecuteApplicationScriptFunction(entry.first.m_Handle,
+ "onInitialize");
+ }
+ }
+
+ // Start any state systems
+ m_Context.m_Factory->GetVisualStateContext().Start();
+
+ for (QT3DSU32 idx = 0, end = m_Behaviors.size(); idx < end; ++idx) {
+ eastl::pair<SBehaviorAsset, bool> &entry(m_Behaviors[idx]);
+ theScriptEngine.ExecuteApplicationScriptFunction(entry.first.m_Handle, "onUpdate");
+ }
+
+ m_Context.m_Factory->GetVisualStateContext().Update();
+
+ // if ( m_ProtocolSocket ) {
+ // m_ProtocolSocket->MessagePump();
+ // if ( m_ProtocolSocket->Connected() == false )
+ // exit( 0 );
+ //}
+
+ // if ( m_ProtocolSocket ) m_ProtocolSocket->MessagePump();
+
+ if (!m_Context.m_Factory->GetEventSystem().GetAndClearEventFetchedFlag())
+ m_Context.m_Factory->GetEventSystem().PurgeEvents(); // GetNextEvents of event system
+ // has not been called in this
+ // round, so clear events to avoid
+ // events to be piled up
+
+ // QT3DSU64 updateEndTime = qt3ds::foundation::Time::getCurrentCounterValue();
+ // QT3DSU64 updateDuration = updateEndTime - m_ThisFrameStartTime;
+ // double millis = qt3ds::foundation::Time::sCounterFreq.toTensOfNanos( updateDuration ) * (1.0
+ // / 100000);
+
+ //(void)millis;
+
+ /*if ( millis > 30.0 )
+ {
+ m_CoreFactory->GetFoundation().error( NVErrorCode::eDEBUG_INFO, __FILE__, __LINE__,
+ "UIC Long Frame: %3.2fms", millis );
+ //Useful for figuring out where the frame time comes from.
+ m_CoreFactory->GetPerfTimer().OutputTimerData();
+
+ }
+ else*/
+ // m_CoreFactory->GetPerfTimer().ResetTimerData();
+
+ fflush(stdout);
+ m_LastFrameStartTime = m_ThisFrameStartTime;
+
+ theScriptEngine.StepGC();
+ }
+
+ template <typename TAssetType>
+ void RegisterAsset(const TAssetType &inAsset)
+ {
+ NVScopedRefCounted<SRefCountedAssetValue> theValue(QT3DS_NEW(
+ m_Context.GetAllocator(), SRefCountedAssetValue)(*m_Context.m_Foundation, inAsset));
+ if (inAsset.m_Id.IsValid()) {
+ m_AssetMap.insert(eastl::make_pair(inAsset.m_Id, theValue));
+ }
+
+ m_OrderedAssets.push_back(eastl::make_pair(inAsset.m_Id, theValue));
+ }
+
+ void addRef() override { atomicIncrement(&mRefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0) {
+ NVDelete(m_Context.GetAllocator(), this);
+ }
+ }
+};
+
+class CNDDStateEngine : public uic::state::INDDStateEngine
+{
+public:
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> m_Foundation;
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> m_StringTable;
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory> m_InputStreamFactory;
+ Q3DStudio::ITimeProvider &m_TimeProvider;
+
+ qt3ds::foundation::NVScopedRefCounted<SNDDStateContext> m_Context;
+ qt3ds::foundation::NVScopedRefCounted<SApp> m_App;
+ eastl::string m_FileName;
+
+ bool m_Verbose;
+
+ TStateInterpreterResourceMap m_StateInterpreters;
+ SStateInterpreterCreateCallback m_StateInterpreterCreateCallback;
+
+ CNDDStateEngine(
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> inFoundation,
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> inStringTable,
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory> inInputStreamFactory,
+ Q3DStudio::ITimeProvider &inTimeProvider);
+ virtual ~CNDDStateEngine();
+
+ bool Load(const char *inApplicationPath) override;
+ bool Step() override;
+ virtual TStateEventHandlerConnectionPtr
+ RegisterEventHandler(EStateEvent inEvent, const char *inEventId, IStateEventHandler &inHandler) override;
+ virtual TStateEventHandlerConnectionPtr RegisterEventHandler(EStateEvent inEvent,
+ const char *inEventId,
+ IStateEventHandler &inHandler,
+ const char *inMachineId);
+ void FireEvent(const char *inEventName, unsigned long long inDelay,
+ const char *inCancelId, bool inIsExternal) override;
+ virtual void FireEvent(const char *inEventName, unsigned long long inDelay,
+ const char *inCancelId, bool inIsExternal, const char *inMachineId);
+ void FireEvent(const char *inEventName, bool inIsExternal) override;
+ virtual void FireEvent(const char *inEventName, bool inIsExternal, const char *inMachineId);
+ void CancelEvent(const char *inCancelId) override;
+ virtual void CancelEvent(const char *inCancelId, const char *inMachineId);
+
+ bool ShouldEnableHeavyLogging() { return m_Verbose; }
+};
+
+
+CNDDStateEngine::CNDDStateEngine(
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> inFoundation,
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> inStringTable,
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory> inInputStreamFactory,
+ Q3DStudio::ITimeProvider &inTimeProvider)
+ : m_Foundation(inFoundation)
+ , m_StringTable(inStringTable)
+ , m_InputStreamFactory(inInputStreamFactory)
+ , m_TimeProvider(inTimeProvider)
+ , m_Context(0)
+ , m_App(0)
+ , m_Verbose(true)
+ , m_StateInterpreterCreateCallback(m_StateInterpreters)
+{
+}
+
+CNDDStateEngine::~CNDDStateEngine()
+{
+ qCDebug (qt3ds::TRACE_INFO) << "CNDDStateEngine destructing";
+ m_App = 0;
+ m_Context = 0;
+}
+
+bool CNDDStateEngine::Load(const char *inApplicationPath)
+{
+ qCDebug (qt3ds::TRACE_INFO) << "CNDDStateEngine: Load";
+
+ // SStackPerfTimer __loadTimer( m_CoreFactory->GetPerfTimer(), "Application: Begin Load" );
+ //(void)inCommandLine;
+
+ m_StateInterpreters.clear();
+ m_App = 0;
+ m_Context = 0;
+
+ eastl::string directory;
+ eastl::string filename;
+ eastl::string extension;
+ CFileTools::Split(inApplicationPath, directory, filename, extension);
+ eastl::string projectDirectory(directory);
+ size_t binaryPos = projectDirectory.rfind("binary");
+ if (binaryPos != eastl::string::npos && binaryPos >= projectDirectory.size() - 7)
+ CFileTools::GetDirectory(projectDirectory);
+
+ m_Context = QT3DS_NEW(m_Foundation->getAllocator(),
+ SNDDStateContext)(m_Foundation, m_StringTable, m_InputStreamFactory,
+ m_TimeProvider, projectDirectory.c_str());
+ m_Context->m_Factory->SetStateInterpreterCreateCallback(m_StateInterpreterCreateCallback);
+
+ m_Context->m_InputStreamFactory->AddSearchDirectory(projectDirectory.c_str());
+ NVFoundationBase &fnd(*m_Foundation);
+ // m_CommandLineSettings.Parse( inCommandLine );
+
+ m_FileName = filename;
+ bool retval = false;
+ if (extension.comparei("scxml") == 0) {
+ m_App = QT3DS_NEW(fnd.getAllocator(), SApp)(*m_Context, m_StateInterpreters);
+ m_Context->m_Factory->SetApplication(m_App);
+ retval = m_App->LoadSCXML("logic_main", (filename + "." + extension).c_str(), "");
+ }
+ // else if ( extension.comparei( "uia" ) == 0 )
+ //{
+ // //ConnectDebugger();
+ // CFileSeekableIOStream inputStream( inApplicationPath, FileReadFlags() );
+ // if ( inputStream.IsOpen() )
+ // {
+ // NVScopedRefCounted<IStringTable> strTable( IStringTable::CreateStringTable(
+ //fnd.getAllocator() ) );
+ // NVScopedRefCounted<IDOMFactory> domFactory( IDOMFactory::CreateDOMFactory(
+ //fnd.getAllocator(), strTable ) );
+ // SAppXMLErrorHandler errorHandler( fnd, inApplicationPath );
+ // eastl::pair<SNamespacePairNode*, SDOMElement*> readResult = CDOMSerializer::Read(
+ //*domFactory, inputStream, &errorHandler );
+ // if ( !readResult.second ) {
+ // fnd.error( QT3DS_INVALID_PARAMETER, "%s doesn't appear to be valid xml", inApplicationPath
+ //);
+ // }
+ // else {
+ // m_App = QT3DS_NEW( fnd.getAllocator(), SApp )( *m_Context, m_StateInterpreters
+ //);
+ // m_Context->m_Factory->SetApplication( m_App );
+
+ // NVScopedRefCounted<IDOMReader> domReader = IDOMReader::CreateDOMReader(
+ //fnd.getAllocator(), *readResult.second, strTable, domFactory );
+ // retval = m_App->LoadUIA( *domReader, fnd );
+ // }
+ // }
+ // else
+ // {
+ // fnd.error( QT3DS_INVALID_PARAMETER, "Unable to open input file %s", inApplicationPath
+ //);
+ // }
+ //}
+ // else if ( extension.comparei( "uiab" ) == 0 )
+ //{
+ // retval = loadbinary( infilepath );
+ //}
+ else {
+ QT3DS_ASSERT(false);
+ }
+ m_Context->m_Factory->GetScriptEngine();
+ return retval;
+}
+
+bool CNDDStateEngine::Step()
+{
+ if (!m_App) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine: Application not initialized "
+ << "may due to unsuccessful load";
+ return false;
+ }
+ m_App->Update();
+ return true;
+}
+
+INDDStateEngine::TStateEventHandlerConnectionPtr
+CNDDStateEngine::RegisterEventHandler(EStateEvent inEvent, const char *inEventId,
+ IStateEventHandler &inHandler)
+{
+ return RegisterEventHandler(inEvent, inEventId, inHandler, "logic_main");
+}
+
+INDDStateEngine::TStateEventHandlerConnectionPtr
+CNDDStateEngine::RegisterEventHandler(EStateEvent inEvent, const char *inEventId,
+ IStateEventHandler &inHandler, const char *inMachineId)
+{
+ TStateInterpreterResourceMap::iterator thePos =
+ m_StateInterpreters.find(m_StringTable->RegisterStr(inMachineId));
+ if (thePos == m_StateInterpreters.end()) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::RegisterEventHandler: "
+ << "Cannot find state machine " << inMachineId;
+ return 0;
+ }
+ SStateInterpreterResource *theStateInterpreterResource = thePos->second;
+ if (!theStateInterpreterResource) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::RegisterEventHandler: "
+ << "Find null state machine " << inMachineId;
+ return 0;
+ }
+ SStateCallbackConnection *theConnection =
+ QT3DS_NEW(m_Foundation->getAllocator(), SStateCallbackConnection)(
+ m_Foundation->getAllocator(), *theStateInterpreterResource, inHandler);
+ theStateInterpreterResource->InsertConnection(
+ SStateEventHandlerKey(inEvent, m_StringTable->RegisterStr(inEventId)), *theConnection);
+ return theConnection;
+}
+
+void CNDDStateEngine::FireEvent(const char *inEventName, unsigned long long inDelay,
+ const char *inCancelId, bool inIsExternal)
+{
+ FireEvent(inEventName, inDelay, inCancelId, inIsExternal, "logic_main");
+}
+
+void CNDDStateEngine::FireEvent(const char *inEventName, unsigned long long inDelay,
+ const char *inCancelId, bool inIsExternal, const char *inMachineId)
+{
+ if (!inEventName || !inCancelId || !inMachineId) {
+ qCCritical (qt3ds::INVALID_PARAMETER) << "CNDDStateEngine::FireEvent: null parameter";
+ return;
+ }
+ TStateInterpreterResourceMap::iterator thePos =
+ m_StateInterpreters.find(m_StringTable->RegisterStr(inMachineId));
+ if (thePos == m_StateInterpreters.end()) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: Cannot find state machine " << inMachineId;
+ return;
+ }
+ SStateInterpreterResource *theStateInterpreterResource = thePos->second;
+ if (!theStateInterpreterResource) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: Find null state machine " << inMachineId;
+ return;
+ }
+ uic::state::IStateInterpreter *theStateInterpreter =
+ theStateInterpreterResource->m_StateInterpreter;
+ if (!theStateInterpreter) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: State interpreter not ready";
+ return;
+ }
+ theStateInterpreter->QueueEvent(inEventName, (qt3ds::QT3DSU64)inDelay,
+ m_StringTable->RegisterStr(inCancelId), inIsExternal);
+}
+
+void CNDDStateEngine::FireEvent(const char *inEventName, bool inIsExternal)
+{
+ FireEvent(inEventName, inIsExternal, "logic_main");
+}
+
+void CNDDStateEngine::FireEvent(const char *inEventName, bool inIsExternal, const char *inMachineId)
+{
+ if (!inEventName || !inMachineId) {
+ qCCritical (qt3ds::INVALID_PARAMETER) << "CNDDStateEngine::FireEvent: null parameter";
+ return;
+ }
+ TStateInterpreterResourceMap::iterator thePos =
+ m_StateInterpreters.find(m_StringTable->RegisterStr(inMachineId));
+ if (thePos == m_StateInterpreters.end()) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: Cannot find state machine " << inMachineId;
+ return;
+ }
+ SStateInterpreterResource *theStateInterpreterResource = thePos->second;
+ if (!theStateInterpreterResource) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: Find null state machine " << inMachineId;
+ return;
+ }
+ uic::state::IStateInterpreter *theStateInterpreter =
+ theStateInterpreterResource->m_StateInterpreter;
+ if (!theStateInterpreter) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: State interpreter not ready";
+ return;
+ }
+ theStateInterpreter->QueueEvent(inEventName, inIsExternal);
+}
+
+void CNDDStateEngine::CancelEvent(const char *inCancelId)
+{
+ CancelEvent(inCancelId, "logic_main");
+}
+
+void CNDDStateEngine::CancelEvent(const char *inCancelId, const char *inMachineId)
+{
+ if (!inCancelId || !inMachineId) {
+ qCCritical (qt3ds::INVALID_PARAMETER) << "CNDDStateEngine::FireEvent: null parameter";
+ return;
+ }
+ TStateInterpreterResourceMap::iterator thePos =
+ m_StateInterpreters.find(m_StringTable->RegisterStr(inMachineId));
+ if (thePos == m_StateInterpreters.end()) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: Cannot find state machine " << inMachineId;
+ return;
+ }
+ SStateInterpreterResource *theStateInterpreterResource = thePos->second;
+ if (!theStateInterpreterResource) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: Find null state machine " << inMachineId;
+ return;
+ }
+ uic::state::IStateInterpreter *theStateInterpreter =
+ theStateInterpreterResource->m_StateInterpreter;
+ if (!theStateInterpreter) {
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "CNDDStateEngine::FireEvent: State interpreter not ready";
+ return;
+ }
+ theStateInterpreter->CancelEvent(m_StringTable->RegisterStr(inCancelId));
+}
+}
+
+namespace {
+
+class SUICFNDTimer : public Q3DStudio::ITimeProvider
+{
+ Q3DStudio::INT64 GetCurrentTimeMicroSeconds() override
+ {
+ return qt3ds::foundation::Time::getCurrentTimeInTensOfNanoSeconds() / 100;
+ }
+};
+
+qt3ds::foundation::MallocAllocator g_BaseAllocator;
+
+class CNDDStateEngineDefault : public uic::state::INDDStateEngine
+{
+public:
+ qt3ds::foundation::CAllocator m_Allocator;
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> m_Foundation;
+ SUICFNDTimer m_TimeProvider;
+ CNDDStateEngine &m_RealEngine;
+
+ CNDDStateEngineDefault()
+ : m_Allocator()
+ , m_Foundation(NVCreateFoundation(QT3DS_FOUNDATION_VERSION, m_Allocator))
+ , m_RealEngine(*QT3DS_NEW(m_Foundation->getAllocator(), CNDDStateEngine)(
+ m_Foundation, &qt3ds::foundation::IStringTable::CreateStringTable(m_Allocator),
+ &uic::state::IInputStreamFactory::Create(*m_Foundation), m_TimeProvider))
+ {
+ }
+ virtual ~CNDDStateEngineDefault() { NVDelete(m_Foundation->getAllocator(), &m_RealEngine); }
+
+ bool Load(const char *inApplicationPath) override
+ {
+ return m_RealEngine.Load(inApplicationPath);
+ }
+ bool Step() override { return m_RealEngine.Step(); }
+ virtual TStateEventHandlerConnectionPtr
+ RegisterEventHandler(EStateEvent inEvent, const char *inEventId, IStateEventHandler &inHandler) override
+ {
+ return m_RealEngine.RegisterEventHandler(inEvent, inEventId, inHandler);
+ }
+ void FireEvent(const char *inEventName, unsigned long long inDelay,
+ const char *inCancelId, bool inIsExternal = true) override
+ {
+ m_RealEngine.FireEvent(inEventName, inDelay, inCancelId, inIsExternal);
+ }
+ void FireEvent(const char *inEventName, bool inIsExternal = true) override
+ {
+ m_RealEngine.FireEvent(inEventName, inIsExternal);
+ }
+ void CancelEvent(const char *inCancelId) override { m_RealEngine.CancelEvent(inCancelId); }
+};
+}
+
+namespace uic {
+namespace state {
+
+ INDDStateEngine *INDDStateEngine::Create(
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> inFoundation,
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> inStringTable,
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IInputStreamFactory> inInputStreamFactory,
+ Q3DStudio::ITimeProvider &inTimeProvider)
+ {
+ return QT3DS_NEW(inFoundation->getAllocator(), CNDDStateEngine)(
+ inFoundation, inStringTable, inInputStreamFactory, inTimeProvider);
+ }
+
+ INDDStateEngine *INDDStateEngine::Create() { return new CNDDStateEngineDefault(); }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateFactory.cpp b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateFactory.cpp
new file mode 100644
index 00000000..c889c15f
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateFactory.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSStateFactory.h"
+
+#include "cstdio"
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+#include "UICTypes.h"
+#include "UICKernelTypes.h"
+#include "Qt3DSStateLuaEngine.h"
+#include "EventPollingSystem.h"
+#include "EventSystem.h"
+#include "UICStateVisualBindingContext.h"
+#include "UICStateVisualBindingContextValues.h"
+#include "UICStateScriptContext.h"
+
+#include "Qt3DSStateInputStreamFactory.h"
+#include "Qt3DSStateContext.h"
+
+namespace {
+
+class CNDDStateFactory;
+struct SVisualStateHandler : public uic::state::IVisualStateInterpreterFactory,
+ public uic::state::IVisualStateCommandHandler
+{
+ qt3ds::NVAllocatorCallback &m_Allocator;
+ CNDDStateFactory &m_Factory;
+ uic::state::INDDStateFactory::IStateInterpreterCreateCallback *m_StateInterpreterCreateCallback;
+ qt3ds::QT3DSI32 mRefCount;
+
+public:
+ SVisualStateHandler(qt3ds::NVAllocatorCallback &alloc, CNDDStateFactory &inFactory)
+ : m_Allocator(alloc)
+ , m_Factory(inFactory)
+ , m_StateInterpreterCreateCallback(0)
+ , mRefCount(0)
+ {
+ }
+ void
+ SetStateInterpreterCreateCallback(uic::state::INDDStateFactory::IStateInterpreterCreateCallback
+ &inStateInterpreterCreateCallback)
+ {
+ m_StateInterpreterCreateCallback = &inStateInterpreterCreateCallback;
+ }
+
+ void addRef() override { qt3ds::foundation::atomicIncrement(&mRefCount); }
+ void release() override
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ QT3DS_IMPLEMENT_REF_COUNT_RELEASE(m_Allocator);
+ }
+
+ uic::state::IStateInterpreter *OnNewStateMachine(const char8_t *inPath,
+ const char8_t *inId,
+ const char8_t *inDatamodelFunction) override;
+
+ void Handle(const uic::state::SVisualStateCommand &inCommand,
+ uic::state::IScriptContext &inScriptContext) override;
+};
+
+class CNDDStateFactory : public uic::state::INDDStateFactory
+{
+public:
+ uic::state::SNDDStateContext &m_Context;
+ qt3ds::foundation::NVScopedRefCounted<uic::state::INDDStateLuaEngine> m_ScriptBridge;
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IVisualStateContext> m_VisualStateContext;
+ qt3ds::foundation::NVScopedRefCounted<uic::evt::IEventSystem> m_EventSystem;
+ uic::state::INDDStateApplication *m_Application;
+ SVisualStateHandler *m_VisualStateHandler;
+ uic::state::INDDStateFactory::IStateInterpreterCreateCallback *m_StateInterpreterCreateCallback;
+
+ qt3ds::QT3DSI32 m_RefCount;
+
+ CNDDStateFactory(uic::state::SNDDStateContext &inContext)
+ : m_Context(inContext)
+ , m_ScriptBridge(0)
+ , m_VisualStateContext(0)
+ , m_EventSystem(0)
+ , m_Application(0)
+ , m_VisualStateHandler(0)
+ , m_StateInterpreterCreateCallback(0)
+ , m_RefCount(0)
+ {
+ }
+
+ ~CNDDStateFactory()
+ {
+ qCDebug (qt3ds::TRACE_INFO) << "CNDDStateFactory destructing";
+ using namespace Q3DStudio;
+ // Release the visual state context.
+ m_VisualStateContext = 0;
+ // Release the event system, it must be released before script engine
+ m_EventSystem = NULL;
+ m_ScriptBridge->Shutdown(*m_Context.m_Foundation);
+ }
+
+ void addRef() override { qt3ds::foundation::atomicIncrement(&m_RefCount); }
+
+ void release() override
+ {
+ qt3ds::foundation::atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVDelete(m_Context.GetAllocator(), this);
+ }
+ }
+
+ uic::state::INDDStateScriptBridge &GetScriptEngine() override
+ {
+ if (m_ScriptBridge == NULL) {
+ m_ScriptBridge = uic::state::INDDStateLuaEngine::Create(m_Context);
+ m_ScriptBridge->PreInitialize();
+ }
+ return *m_ScriptBridge;
+ }
+
+ uic::state::IVisualStateContext &GetVisualStateContext() override
+ {
+ if (!m_VisualStateContext) {
+ m_VisualStateContext = uic::state::IVisualStateContext::Create(
+ *m_Context.m_Foundation, m_Context.GetStringTable());
+ SVisualStateHandler *newHandle =
+ QT3DS_NEW(m_Context.m_Foundation->getAllocator(),
+ SVisualStateHandler)(m_Context.m_Foundation->getAllocator(), *this);
+ if (m_StateInterpreterCreateCallback)
+ newHandle->SetStateInterpreterCreateCallback(*m_StateInterpreterCreateCallback);
+ m_VisualStateContext->SetCommandHandler(newHandle);
+ m_VisualStateContext->SetInterpreterFactory(newHandle);
+ }
+ return *m_VisualStateContext;
+ }
+ uic::evt::IEventSystem &GetEventSystem() override
+ {
+ if (!m_EventSystem) {
+ m_EventSystem = uic::evt::IEventSystem::Create(*m_Context.m_Foundation);
+ }
+ return *m_EventSystem;
+ }
+ qt3ds::foundation::IStringTable &GetStringTable() override { return m_Context.GetStringTable(); }
+ qt3ds::NVFoundationBase &GetFoundation() override { return *m_Context.m_Foundation.mPtr; }
+ Q3DStudio::ITimeProvider &GetTimeProvider() override { return m_Context.m_TimeProvider; }
+ uic::state::IInputStreamFactory &GetInputStreamFactory() override
+ {
+ return *m_Context.m_InputStreamFactory;
+ }
+
+ uic::state::INDDStateApplication *GetApplication() override { return m_Application; }
+ void SetApplication(uic::state::INDDStateApplication *inApplication) override
+ {
+ m_Application = inApplication;
+ if (inApplication) {
+ GetScriptEngine();
+ m_ScriptBridge->SetApplication(*inApplication);
+ // Most of the script bridge lua functions will hard crash if
+ // the initialization happens before the application is set.
+ // This keeps the errors in lua-land instead of in crashing ui composer.
+ m_ScriptBridge->Initialize();
+ }
+ }
+ void SetStateInterpreterCreateCallback(
+ IStateInterpreterCreateCallback &inStateInterpreterCreateCallback) override
+ {
+ m_StateInterpreterCreateCallback = &inStateInterpreterCreateCallback;
+ if (m_VisualStateHandler)
+ m_VisualStateHandler->SetStateInterpreterCreateCallback(
+ inStateInterpreterCreateCallback);
+ }
+};
+
+uic::state::IStateInterpreter *
+SVisualStateHandler::OnNewStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodelFunction)
+{
+ uic::state::IStateInterpreter *theInterpreter =
+ m_Factory.m_ScriptBridge->CreateStateMachine(inPath, inId, inDatamodelFunction);
+ if (m_StateInterpreterCreateCallback)
+ m_StateInterpreterCreateCallback->OnCreate(
+ m_Factory.m_Context.GetStringTable().RegisterStr(inId), *theInterpreter);
+ return theInterpreter;
+}
+
+void SVisualStateHandler::Handle(const uic::state::SVisualStateCommand &inCommand,
+ uic::state::IScriptContext &inScriptContext)
+{
+ (void)inCommand;
+ (void)inScriptContext;
+}
+}
+
+namespace uic {
+namespace state {
+
+ INDDStateFactory &INDDStateFactory::Create(SNDDStateContext &inContext)
+ {
+ return *QT3DS_NEW(inContext.m_Foundation->getAllocator(), CNDDStateFactory)(inContext);
+ }
+}
+}
diff --git a/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateInputStreamFactory.cpp b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateInputStreamFactory.cpp
new file mode 100644
index 00000000..40b15fa0
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateInputStreamFactory.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSStateInputStreamFactory.h"
+
+#include "stdio.h"
+
+#include "foundation/Qt3DSLogging.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/string.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSMutex.h"
+#include <QFile>
+
+using namespace uic::state;
+using qt3ds::foundation::CFileTools;
+
+namespace {
+
+using qt3ds::foundation::atomicIncrement;
+using qt3ds::foundation::atomicDecrement;
+using qt3ds::QT3DSI32;
+
+struct SInputStream : public IRefCountedInputStream
+{
+ qt3ds::NVFoundationBase &m_Foundation;
+ eastl::string m_Path;
+ QFile m_File;
+ volatile qt3ds::QT3DSI32 mRefCount;
+
+ SInputStream(qt3ds::NVFoundationBase &inFoundation, const eastl::string &inPath)
+ : m_Foundation(inFoundation)
+ , m_Path(inPath)
+ , m_File(inPath.c_str())
+ , mRefCount(0)
+ {
+ m_File.open(QIODevice::ReadOnly);
+ }
+ virtual ~SInputStream()
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ qt3ds::QT3DSU32 Read(qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> data) override
+ {
+ return m_File.read((char *)data.begin(), data.size());
+ }
+
+ bool Write(qt3ds::foundation::NVConstDataRef<qt3ds::QT3DSU8> /*data*/) override
+ {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ void SetPosition(qt3ds::QT3DSI64 inOffset, qt3ds::foundation::SeekPosition::Enum inEnum) override
+ {
+ if (inOffset > QT3DS_MAX_I32 || inOffset < QT3DS_MIN_I32) {
+ qCCritical(qt3ds::INVALID_OPERATION, "Attempt to seek further than platform allows");
+ QT3DS_ASSERT(false);
+ return;
+ } else {
+ CFileTools::SetStreamPosition(m_File, inOffset, inEnum);
+ }
+ }
+ qt3ds::QT3DSI64 GetPosition() const override
+ {
+ return m_File.pos();
+ }
+
+ static SInputStream *OpenFile(const char8_t *inPath, qt3ds::NVFoundationBase &inFoundation)
+ {
+ eastl::string finalPath = CFileTools::GetFileOrAssetPath(inPath);
+ QFile tmp(finalPath.c_str());
+ if (tmp.exists())
+ return QT3DS_NEW(inFoundation.getAllocator(), SInputStream)(inFoundation, finalPath);
+ return NULL;
+ }
+};
+
+typedef eastl::basic_string<char8_t, qt3ds::foundation::ForwardingAllocator> TStrType;
+struct SFactory : public IInputStreamFactory
+{
+ qt3ds::NVFoundationBase &m_Foundation;
+ volatile qt3ds::QT3DSI32 mRefCount;
+ TStrType m_SearchString;
+ qt3ds::foundation::nvvector<TStrType> m_SearchPaths;
+ TStrType m_TempAddSearch;
+
+ qt3ds::foundation::Mutex m_Mutex;
+ typedef qt3ds::foundation::Mutex::ScopedLock TScopedLock;
+
+ SFactory(qt3ds::NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_SearchString(qt3ds::foundation::ForwardingAllocator(inFoundation.getAllocator(),
+ "SFactory::m_SearchString"))
+ , m_SearchPaths(inFoundation.getAllocator(), "SFactory::m_SearchPaths")
+ , m_TempAddSearch(qt3ds::foundation::ForwardingAllocator(inFoundation.getAllocator(),
+ "SFactory::m_TempAddSearch"))
+ , m_Mutex(inFoundation.getAllocator())
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void AddSearchDirectory(const char8_t *inDirectory) override
+ {
+ TScopedLock __factoryLocker(m_Mutex);
+ if (inDirectory && *inDirectory) {
+ bool foundPath = false;
+ m_TempAddSearch.assign(inDirectory);
+ qt3ds::foundation::CFileTools::NormalizePath(m_TempAddSearch);
+ for (qt3ds::QT3DSU32 idx = 0, end = m_SearchPaths.size(); idx < end && foundPath == false;
+ ++idx) {
+ foundPath = m_SearchPaths[idx].compare(m_TempAddSearch.c_str()) == 0;
+ }
+ if (!foundPath) {
+ qCInfo(qt3ds::TRACE_INFO, "Adding search path: %s", inDirectory);
+ m_SearchPaths.push_back(m_TempAddSearch);
+ }
+ }
+ }
+ void AttemptCFileOpen()
+ {
+ qCInfo(qt3ds::TRACE_INFO, "attempting C file api for %s", m_SearchString.c_str());
+ FILE *theTest = fopen(m_SearchString.c_str(), "rb");
+ if (theTest) {
+ qCInfo(qt3ds::TRACE_INFO, "C file api succeeded for %s", m_SearchString.c_str());
+ fclose(theTest);
+ } else {
+ qCInfo(qt3ds::TRACE_INFO, "C file api failed for %s", m_SearchString.c_str());
+ }
+ }
+
+ // Remove the ./ from the relative path as this allows APK lookup to succeed
+ static void CheckRelative(TStrType &ioStr)
+ {
+ if (ioStr.find("./") == 0)
+ ioStr.erase(ioStr.begin(), ioStr.begin() + 2);
+ }
+
+ IRefCountedInputStream *GetStreamForFile(const char8_t *inFilename, bool inQuiet) override
+ {
+ TScopedLock __factoryLocker(m_Mutex);
+ SInputStream *theFile = NULL;
+ for (qt3ds::QT3DSU32 idx = 0, end = m_SearchPaths.size() + 1; theFile == NULL && idx < end;
+ ++idx) {
+ if (idx) {
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(m_SearchPaths[idx - 1].c_str(),
+ inFilename, m_SearchString);
+ } else {
+ m_SearchString.assign(inFilename);
+ }
+ qt3ds::foundation::CFileTools::ToPlatformPath(m_SearchString);
+ CheckRelative(m_SearchString);
+ theFile = SInputStream::OpenFile(m_SearchString.c_str(), m_Foundation);
+ }
+ if (theFile) {
+ qCInfo(qt3ds::TRACE_INFO, "file %s resolved to: %s", inFilename, m_SearchString.c_str());
+ } else {
+ if (inQuiet == false) {
+ // Print extensive debugging information.
+ qCWarning(qt3ds::WARNING, "Failed to find file: %s", inFilename);
+ qCWarning(qt3ds::WARNING, "Searched paths: %s", inFilename);
+ m_SearchString.assign(inFilename);
+ qt3ds::foundation::CFileTools::ToPlatformPath(m_SearchString);
+ qCWarning(qt3ds::WARNING, "%s", m_SearchString.c_str());
+ for (qt3ds::QT3DSU32 idx = 0, end = m_SearchPaths.size(); idx < end; ++idx) {
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(m_SearchPaths[idx].c_str(),
+ inFilename, m_SearchString);
+ qt3ds::foundation::CFileTools::ToPlatformPath(m_SearchString);
+ CheckRelative(m_SearchString);
+ if (m_SearchString.compare(inFilename) != 0)
+ qCWarning(qt3ds::WARNING, "%s", m_SearchString.c_str());
+ }
+ }
+ }
+ return theFile;
+ }
+
+ bool GetPathForFile(const char8_t *inFilename, eastl::string &outFile,
+ bool inQuiet = false) override
+ {
+ qt3ds::foundation::NVScopedRefCounted<IRefCountedInputStream> theStream =
+ GetStreamForFile(inFilename, inQuiet);
+ if (theStream) {
+ SInputStream *theRealStream = static_cast<SInputStream *>(theStream.mPtr);
+ outFile = theRealStream->m_Path;
+ return true;
+ }
+ return false;
+ }
+};
+}
+
+IInputStreamFactory &IInputStreamFactory::Create(qt3ds::NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SFactory)(inFoundation);
+}
diff --git a/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateLuaEngine.cpp b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateLuaEngine.cpp
new file mode 100644
index 00000000..3099466b
--- /dev/null
+++ b/src/Runtime/Source/Qt3DSState/Source/Qt3DSStateLuaEngine.cpp
@@ -0,0 +1,1573 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSStateLuaEngine.h"
+#include "UICFileStream.h"
+#include "UICDataLogger.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSLogging.h"
+#include "foundation/Qt3DSSystem.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICStateLuaScriptContext.h"
+#include "UICStateDebugger.h"
+#include "EventPollingSystemLuaBinding.h"
+#include "UICHash.h"
+
+#include "EASTL/vector.h"
+#include <sys/stat.h>
+
+#include "UICStateDebugStreams.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "UICLuaDebugger.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICParametersSystem.h"
+#include "UICTypes.h"
+
+#include "Qt3DSStateInputStreamFactory.h"
+#include "Qt3DSStateApplication.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace {
+
+using qt3ds::foundation::atomicIncrement;
+using qt3ds::foundation::atomicDecrement;
+using qt3ds::foundation::CFileTools;
+using qt3ds::QT3DSI32;
+using qt3ds::QT3DSU32;
+using Q3DStudio::BOOL;
+using Q3DStudio::INT32;
+using Q3DStudio::INT8;
+using Q3DStudio::CHAR;
+using Q3DStudio::CHash;
+
+#if defined(_DEBUG) || (_PROFILE)
+#define Q3DStudio_LOG_EVENT(S) // something
+#else
+#define Q3DStudio_LOG_EVENT(S)
+#endif
+
+// forward declaration of exported lua global functions
+namespace __SLuaEngineImpl_Static_Global_Lua_Exporter_Declaration__ {
+ static int Output(lua_State *inLuaState);
+ static int GetElapsedTime(lua_State *inLuaState);
+ static int GetDirectory(lua_State *inLuaState);
+ static int ParseSCXML(lua_State *inLuaState);
+ static int GetSCXMLInterpreter(lua_State *inLuaState);
+ static int GetEventSystem(lua_State *inLuaState);
+ static int GetMillisecondsSinceLastFrame(lua_State *inLuaState);
+}
+
+using namespace __SLuaEngineImpl_Static_Global_Lua_Exporter_Declaration__;
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+// for unique addresses to be used as keys for Lua Registry
+const Q3DStudio::INT32 KEY_PRESENTATION = 1;
+const Q3DStudio::INT32 KEY_BEHAVIORS = 2;
+const Q3DStudio::INT32 KEY_EVENTDATA_LIST = 4;
+const Q3DStudio::INT32 KEY_CHANGEDATA_LIST = 5;
+const Q3DStudio::INT32 KEY_CALLBACKS = 6;
+const Q3DStudio::INT32 KEY_REGISTEREDCALLBACKS = 7;
+
+const char *KEY_ELEMENT = "element";
+const char *KEY_SELF = "self";
+const char *KEY_SCRIPT_INDEX = "__scriptIndex";
+const char *KEY_ONINITIALIZE = "onInitialize";
+const char *KEY_ONACTIVATE = "onActivate";
+const char *KEY_ONDEACTIVATE = "onDeactivate";
+const char *KEY_ONUPDATE = "onUpdate";
+
+struct SLuaEngineImpl;
+namespace __SLuaEngineImpl_Basic_Structs__ {
+ struct SLuaEngineListener : public uic::state::debugger::ILuaSideListener
+ {
+ qt3ds::NVFoundationBase &m_Foundation;
+ SLuaEngineImpl &m_Engine;
+ qt3ds::QT3DSI32 m_RefCount;
+ SLuaEngineListener(qt3ds::NVFoundationBase &fnd, SLuaEngineImpl &eng)
+ : m_Foundation(fnd)
+ , m_Engine(eng)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() { qt3ds::foundation::atomicIncrement(&m_RefCount); }
+ void release()
+ {
+ qt3ds::foundation::atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0)
+ qt3ds::foundation::NVDelete(m_Foundation, this);
+ }
+
+ void OnBreak() override;
+ };
+
+ struct SLuaPerfEvent
+ {
+ qt3ds::QT3DSU64 m_Time;
+ eastl::string m_Name;
+ };
+
+ struct SLuaFunctionResult
+ {
+ BOOL m_HasFunction;
+ BOOL m_PCallError;
+ SLuaFunctionResult()
+ : m_HasFunction(false)
+ , m_PCallError(false)
+ {
+ }
+ SLuaFunctionResult(BOOL inHS, BOOL inPC)
+ : m_HasFunction(inHS)
+ , m_PCallError(inPC)
+ {
+ }
+ };
+
+ struct SLuaStackScope
+ {
+ lua_State *m_LuaState;
+ int m_Top;
+ SLuaStackScope(lua_State *s)
+ : m_LuaState(s)
+ , m_Top(lua_gettop(s))
+ {
+ }
+ ~SLuaStackScope() { lua_settop(m_LuaState, m_Top); }
+ };
+
+ struct LuaScopedLock
+ {
+ qt3ds::foundation::Mutex *m_Mutex;
+
+ LuaScopedLock(qt3ds::foundation::Mutex *mtx)
+ : m_Mutex(mtx)
+ {
+ if (m_Mutex)
+ m_Mutex->lock();
+ }
+
+ ~LuaScopedLock()
+ {
+ if (m_Mutex)
+ m_Mutex->unlock();
+ }
+ };
+
+ struct SUserFile
+ {
+ FILE *m_File;
+ bool m_EOF;
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IRefCountedInputStream> m_InputStream;
+ eastl::vector<char8_t> m_Buffer;
+
+ SUserFile()
+ : m_File(0)
+ , m_EOF(true)
+ {
+ }
+ SUserFile(FILE *f)
+ : m_File(f)
+ , m_EOF(false)
+ {
+ }
+ SUserFile(uic::state::IRefCountedInputStream &stream)
+ : m_File(0)
+ , m_InputStream(stream)
+ , m_EOF(false)
+ {
+ }
+ ~SUserFile()
+ {
+ if (m_File)
+ fclose(m_File);
+ }
+
+ size_t read(void *buffer, size_t len)
+ {
+ size_t retval = 0;
+ char *writeBuffer = (char *)buffer;
+ if (m_Buffer.size()) {
+ qt3ds::QT3DSU32 amount = qt3ds::NVMin((qt3ds::QT3DSU32)m_Buffer.size(), (qt3ds::QT3DSU32)len);
+ memcpy(writeBuffer, m_Buffer.data(), amount);
+ m_Buffer.erase(m_Buffer.begin(), m_Buffer.begin() + amount);
+ writeBuffer += amount;
+ len -= amount;
+ retval += amount;
+ }
+ if (len) {
+ qt3ds::QT3DSU32 amountRead = 0;
+ if (m_InputStream)
+ amountRead = m_InputStream->Read(
+ qt3ds::foundation::toDataRef((qt3ds::QT3DSU8 *)writeBuffer, (qt3ds::QT3DSU32)len));
+ else if (m_File)
+ amountRead = (qt3ds::QT3DSU32)fread(writeBuffer, 1, len, m_File);
+
+ retval += amountRead;
+ m_EOF = amountRead == 0;
+ }
+ return retval;
+ }
+
+ void unget(int c)
+ {
+ if (c != EOF)
+ m_Buffer.push_back((char8_t)c);
+ }
+
+ bool eof() const { return m_EOF; }
+
+ static bool is_white(char d) { return d == '\n' || d == ' ' || d == '\r' || d == '\t'; }
+
+ // read till not white, discarding everything that is white
+ void read_till_not_white()
+ {
+ char data = ' ';
+ while (!eof() && is_white(data)) {
+ read(&data, 1);
+ }
+ if (!eof())
+ m_Buffer.push_back(data);
+ }
+
+ // read till we find whitespace or eof
+ void read_till_white()
+ {
+ char data = '1';
+ while (!eof() && is_white(data) == false) {
+ read(&data, 1);
+ m_Buffer.push_back(data);
+ }
+ }
+
+ int read_number(float &outNum)
+ {
+ outNum = 0;
+ // read in whitespace till we have data
+ // then read till we get whitespace or eof
+ read_till_not_white();
+ read_till_white();
+ if (m_Buffer.size() > 0) {
+ // now add a null character
+ m_Buffer.push_back(0);
+ double d = strtod(m_Buffer.data(), 0);
+ // get rid of null character
+ m_Buffer.resize(m_Buffer.size() - 1);
+ if (!eof())
+ m_Buffer.erase(m_Buffer.begin(), m_Buffer.begin() + m_Buffer.size() - 1);
+ else
+ m_Buffer.clear();
+ outNum = static_cast<float>(d);
+ return 1;
+ }
+ return 0;
+ }
+ };
+}
+using namespace __SLuaEngineImpl_Basic_Structs__;
+#define LUA_ENGINE_MULTITHREAD_PROTECT_METHOD LuaScopedLock __locker(m_MultithreadedMutex);
+
+// int CScriptEngineCallFunctionArgRetriever::RetrieveArgument( lua_State *inState )
+//{
+// int theRet = 0;
+// if ( m_ArgumentString && *m_ArgumentString )
+// {
+// eastl::string temp( m_ArgumentString );
+// temp.insert( 0, "return " );
+// if ( luaL_loadstring( inState, temp.c_str() ) != 0 )
+// {
+// theRet = -1;
+// }
+// else
+// {
+// theRet = lua_pcall( inState, 0, 1, 0 ) ? -1 : 1;
+// }
+// }
+// return theRet;
+//}
+//
+// eastl::string CScriptEngineCallFunctionArgRetriever::GetArgDescription()
+//{
+// eastl::string temp( m_ArgumentString );
+// temp.insert( 0, "return " );
+// return temp;
+//}
+
+namespace {
+ uic::state::IInputStreamFactory *g_InputStreamFactory;
+
+ void *lua_user_fopen(const char *filename, const char *mode, char *absfilename)
+ {
+ Q3DStudio_UNREFERENCED_PARAMETER(mode);
+ // Ensure this isn't a shared library of sorts.
+ /*size_t len = strlen( filename );
+ if ( len > 2 )
+ {
+ size_t end = len - 3;
+ const char* ext = filename + end;
+ //Do not use the abstraction for shared libraries or dlls.
+ if ( strcmp( ext, "dll" ) == 0
+ || strcmp( ext, ".so" ) == 0
+ || strcmp( ext, "lib" ) == 0 )
+ {
+ FILE* testFile = fopen( filename, mode );
+ if ( testFile )
+ {
+ return new SUserFile( testFile );
+ }
+ return 0;
+ }
+ }*/
+ uic::state::IRefCountedInputStream *stream =
+ g_InputStreamFactory->GetStreamForFile(filename, true);
+ if (stream) {
+ if (absfilename) {
+ eastl::string tempStr;
+ if (g_InputStreamFactory->GetPathForFile(filename, tempStr)) {
+ strcpy(absfilename, tempStr.c_str());
+ }
+ }
+ return new SUserFile(*stream);
+ }
+
+ return 0;
+ }
+
+ int lua_user_fclose(void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ delete theFile;
+ return 0;
+ }
+
+ int lua_user_getc(void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile) {
+ char8_t temp;
+ int numRead = (int)theFile->read(&temp, 1);
+ if (numRead == 1)
+ return temp;
+ }
+ return -1;
+ }
+ int lua_user_ungetc(int c, void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ theFile->unget(c);
+ return 0;
+ }
+
+ char *lua_user_fgets(char *ptr, int count, void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile && theFile->read(ptr, count))
+ return ptr;
+ return 0;
+ }
+
+ size_t lua_user_fread(void *ptr, size_t size, size_t count, void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ size_t amount = size * count;
+ if (theFile)
+ return theFile->read(ptr, amount);
+ return 0;
+ }
+
+ int lua_user_ferror(void *) { return 0; }
+
+ int lua_user_feof(void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ return theFile->eof();
+ return 0;
+ }
+
+ int lua_user_fread_number(void *file, lua_Number *d)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ return theFile->read_number(*d);
+ return 0;
+ }
+
+ void lua_user_clearerr(void *) { (void)0; }
+}
+
+namespace {
+
+ enum EPathType { eLuaPath, eCPath };
+ const char *const sm_PathType[] = { "path", "cpath" };
+ const char *const sm_PathTypeExtension[] = {
+ "lua",
+#ifdef _WIN32
+ "dll",
+#else
+ "so"
+#endif
+ };
+ static void AppendLuaPackagePath(lua_State *state, const eastl::string &inPath,
+ EPathType inPathType)
+ {
+ if (state == 0)
+ return;
+ SLuaStackScope __selfScope(state);
+ lua_getglobal(state, "package");
+ lua_getfield(state, -1, sm_PathType[inPathType]);
+ eastl::string cur_path(lua_tostring(state, -1));
+ cur_path.append(";");
+ cur_path.append(inPath.c_str());
+ cur_path.append("/?.");
+ cur_path.append(sm_PathTypeExtension[inPathType]);
+ lua_pop(state, 1);
+ lua_pushstring(state, cur_path.c_str());
+ lua_setfield(state, -2, sm_PathType[inPathType]);
+ }
+
+ static void AppendAdditionalLuaPackagePath(lua_State *state, const eastl::string &inPath)
+ {
+ AppendLuaPackagePath(state, inPath, eCPath);
+
+ eastl::string scriptsDir;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(inPath.c_str(), "scripts", scriptsDir);
+ AppendLuaPackagePath(state, scriptsDir, eCPath);
+
+ // Add in additional search directory for specific platform
+ eastl::string scriptsPlatformDir;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(
+ scriptsDir.c_str(), qt3ds::foundation::System::getPlatformStr(), scriptsPlatformDir);
+ AppendLuaPackagePath(state, scriptsPlatformDir, eCPath);
+ }
+}
+
+namespace {
+
+ static int WriteLuaData(lua_State *, const void *p, size_t sz, void *ud)
+ {
+ qt3ds::foundation::MemoryBuffer<> &theWriter =
+ *reinterpret_cast<qt3ds::foundation::MemoryBuffer<> *>(ud);
+ theWriter.write((const qt3ds::QT3DSU8 *)p, (qt3ds::QT3DSU32)sz);
+ return 0;
+ }
+
+ static void *MemoryAllocator(void *inUserData, void *inPointer, size_t inOldSize,
+ size_t inNewSize)
+ {
+ Q3DStudio_UNREFERENCED_PARAMETER(inUserData);
+
+ if (inNewSize == 0) {
+ Q3DStudio_free(inPointer, INT8, inOldSize);
+ return 0;
+ } else
+ return Q3DStudio_reallocate_desc(inPointer, INT8, inOldSize, inNewSize, "Lua");
+ }
+
+ static void GetLoadedBuffersTable(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "loadedbuffers");
+ if (lua_isnil(inLuaState, -1)) {
+ lua_pop(inLuaState, 1);
+ lua_newtable(inLuaState);
+ lua_pushvalue(inLuaState, -1);
+ lua_setfield(inLuaState, LUA_REGISTRYINDEX, "loadedbuffers");
+ }
+ }
+
+ // static int ErrorChannel( lua_State* inLuaState )
+ //{
+ // NVLog( NVLOGLEVEL_ERROR, "Lua", "ErrorChannel", "%s", lua_tostring( inLuaState, -1 ) );
+ // lua_pop( inLuaState, 1 );
+ // return 0;
+ //}
+
+ static int EnsureScriptIsLoaded(lua_State *inLuaState, const char *inRelativePath,
+ const char *inBasePath, eastl::string &scriptBuffer
+ //, qt3ds::foundation::IPerfTimer& inPerfTimer
+ ,
+ uic::state::IInputStreamFactory &inStreamFactory,
+ eastl::vector<char8_t> &inLoadVec)
+ {
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(inBasePath, inRelativePath,
+ scriptBuffer);
+ qt3ds::foundation::CFileTools::ToPlatformPath(scriptBuffer);
+ int theError = 0;
+ // The lua system expects file to begin with @.
+ scriptBuffer.insert(scriptBuffer.begin(), '@');
+ const char *theFullPath = scriptBuffer.c_str();
+ GetLoadedBuffersTable(inLuaState);
+ lua_getfield(inLuaState, -1, inRelativePath);
+ if (lua_isnil(inLuaState, -1)) {
+ // SStackPerfTimer __perfTimer( inPerfTimer, "Load Lua File" );
+ lua_pop(inLuaState, 1);
+ uic::state::IInputStreamFactory &theFactory(inStreamFactory);
+ qt3ds::foundation::NVScopedRefCounted<uic::state::IRefCountedInputStream> theStream =
+ theFactory.GetStreamForFile(inRelativePath, true);
+
+ inLoadVec.clear();
+ if (theStream) {
+ qt3ds::QT3DSU8 buf[1024];
+ for (size_t amount = theStream->Read(qt3ds::foundation::toDataRef(buf, 1024)); amount;
+ amount = theStream->Read(qt3ds::foundation::toDataRef(buf, 1024)))
+ inLoadVec.insert(inLoadVec.end(), (char8_t *)buf, (char8_t *)buf + amount);
+ }
+ if (inLoadVec.empty() == false) {
+ // Load the Lua script
+ theError = luaL_loadbuffer(inLuaState, static_cast<const char *>(&inLoadVec[0]),
+ static_cast<size_t>(inLoadVec.size()), theFullPath);
+ lua_pushvalue(inLuaState, -1);
+ lua_setfield(inLuaState, -3, inRelativePath);
+ lua_insert(inLuaState, -2);
+ lua_pop(inLuaState, 1);
+ } else {
+ lua_pop(inLuaState, 1);
+ theError = -1;
+ }
+ }
+ return theError;
+ }
+}
+
+eastl::vector<eastl::string> g_AdditionalSharedLibraryPaths;
+uic::state::TLuaLibraryLoader LoadLuaLibraries =
+ luaL_openlibs; ///< Defaults to open all lua libraries
+lua_user_file_io g_engine_file_io;
+lua_Alloc g_engine_alloc = MemoryAllocator;
+
+struct SLuaEngineImpl : public uic::state::INDDStateLuaEngine
+{
+ typedef eastl::vector<eastl::string> TStringList;
+ uic::state::SNDDStateContext &m_Context;
+ lua_State *m_LuaState;
+
+ uic::state::INDDStateApplication *m_Application;
+
+ INT32 m_CallbackIndex;
+
+ INT32 m_ServerPort; ///<port number of remote debugger
+ eastl::string m_ScriptString;
+ eastl::string m_ServerIP;
+ qt3ds::foundation::NVScopedRefCounted<uic::state::debugger::ILuaDebugger> m_LuaDebugger;
+ qt3ds::foundation::NVScopedRefCounted<SLuaEngineListener> m_LuaListener;
+
+ lua_State *m_PreloadState;
+ TStringList m_PreloadScripts;
+ qt3ds::foundation::Sync m_PreloadSync;
+ eastl::string m_PreloadProjectDir;
+ qt3ds::foundation::Mutex m_PreloadMutex;
+ qt3ds::foundation::Mutex *m_MultithreadedMutex;
+
+ eastl::vector<char8_t> m_LoadVec;
+ bool m_LuaPathInitialized;
+ qt3ds::QT3DSI32 mRefCount;
+
+ qt3ds::QT3DSU32 m_PerfStackIndex;
+ eastl::string m_PerfNameBuilder;
+ bool m_ProfileActive;
+ eastl::vector<SLuaPerfEvent> m_PerfStack;
+
+ SLuaEngineImpl(uic::state::SNDDStateContext &inContext);
+ virtual ~SLuaEngineImpl();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Context.GetAllocator())
+
+ // functions from IScriptBridge
+ void EnableMultithreadedAccess() override;
+ void DisableMultithreadedAccess() override;
+
+ void SetApplication(uic::state::INDDStateApplication &inApplication) override;
+
+ // virtual void BeginPreloadScripts( const eastl::vector<const char*>& inScripts,
+ //uic::render::IThreadPool& inThreadPool, const char* inProjectDir );
+ // virtual void EndPreloadScripts();
+ eastl::vector<eastl::string> GetLoadedScripts() override;
+
+ Q3DStudio::INT32 InitializeApplicationBehavior(const char *inProjectRelativePath) override;
+
+ void ExecuteApplicationScriptFunction(Q3DStudio::INT32 inApp, const char *inFnName) override;
+ // virtual void CallFunction( const char* behavior, const char* handler,
+ //CScriptEngineCallFunctionArgRetriever &inArgRetriever );
+
+ void AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction) override;
+ // virtual void EnableDebugging(uic::state::debugger::IMultiProtocolSocket& socket
+ //);
+ // virtual void EnableProfiling();
+ void StepGC() override;
+
+ // functions from CLuaEngine
+ uic::state::IStateInterpreter *CreateStateMachine(const char8_t *inPath,
+ const char8_t *inId,
+ const char8_t *inDatamodelFunction) override;
+ void PreInitialize() override;
+ void Initialize() override;
+ void Shutdown(qt3ds::NVFoundationBase &inFoundation) override;
+
+ // local functions
+ // SLuaFunctionResult CallFunction( const Q3DStudio::INT32 inScriptIndex, const CHAR*
+ // inFunctionName );
+ void PrepareToLoadFile();
+ int PCall(int argcount, int retcount, int errorIndex);
+ void OnBreak();
+};
+
+namespace __SLuaEngineImpl_Static_Calls__ {
+ // static void PreloadFunctionCall( void* inEngine )
+ //{
+ // SLuaEngineImpl* theEngine = reinterpret_cast<SLuaEngineImpl*>( inEngine );
+ // eastl::vector<char8_t> loadBuffer;
+ // eastl::string pathBuffer;
+ // SStackPerfTimer __perfTimer(
+ //theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer(), "Preload Lua Data" );
+ // {
+ // //First attempt to load all compiled lua scripts.
+ // eastl::string theLuaBinFile = theEngine->m_PreloadProjectDir;
+ // CFileTools::CombineBaseAndRelative( theEngine->m_PreloadProjectDir.c_str(),
+ //"binary/compiledlua.bin", theLuaBinFile );
+ // NVScopedRefCounted<uic::render::IRefCountedInputStream> theBinFile
+ // =
+ //theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetInputStreamFactory().GetStreamForFile(
+ //theLuaBinFile.c_str() );
+ // if ( theBinFile )
+ // {
+ // theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetFoundation().error( QT3DS_INFO,
+ //"Lua - Found binary file, loading scripts" );
+ // eastl::vector<eastl::pair<eastl::string, QT3DSU32> > theDirectory;
+ // QT3DSU32 numDirFiles = 0;
+ // theBinFile->Read( numDirFiles );
+ // theDirectory.resize( numDirFiles );
+ // for ( QT3DSU32 idx = 0, end = numDirFiles; idx < end; ++idx )
+ // {
+ // QT3DSU32 strLen = 0;
+ // theBinFile->Read( strLen );
+ // theDirectory[idx].first.resize( strLen );
+ // theBinFile->Read( (QT3DSU8*)&theDirectory[idx].first[0], strLen );
+ // theBinFile->Read( theDirectory[idx].second );
+ // }
+ // QT3DSU32 binSectionSize = 0;
+ // theBinFile->Read( binSectionSize );
+ // eastl::vector<char8_t> theData;
+ // theData.resize( binSectionSize );
+ // theBinFile->Read( theData.data(), binSectionSize );
+ // SLuaStackScope theScope( theEngine->m_PreloadState );
+ // GetLoadedBuffersTable(theEngine->m_PreloadState);
+ // for ( QT3DSU32 idx = 0, end = numDirFiles; idx < end; ++idx )
+ // {
+ // eastl::pair<eastl::string,QT3DSU32> dirEntry = theDirectory[idx];
+ // QT3DSU32 entrySize = 0;
+ // if ( idx < end - 1 )
+ // entrySize = theDirectory[idx+1].second - dirEntry.second;
+ // else
+ // entrySize = binSectionSize - dirEntry.second;
+ // qt3ds::foundation::CFileTools::CombineBaseAndRelative(
+ //theEngine->m_PreloadProjectDir.c_str(), dirEntry.first.c_str(), pathBuffer );
+ // qt3ds::foundation::CFileTools::ToPlatformPath( pathBuffer );
+ // pathBuffer.insert( 0, "@" );
+ //
+ // luaL_loadbuffer( theEngine->m_PreloadState, static_cast<const char*>(
+ //&theData[dirEntry.second] ),
+ // entrySize, pathBuffer.c_str() );
+ // lua_setfield( theEngine->m_PreloadState, -2, dirEntry.first.c_str()
+ //);
+ // }
+ // }
+ // }
+
+ // for ( QT3DSU32 idx = 0, end = theEngine->m_PreloadScripts.size(); idx < end; ++idx )
+ // {
+ // SLuaStackScope theScope( theEngine->m_PreloadState );
+ // EnsureScriptIsLoaded( theEngine->m_PreloadState,
+ //theEngine->m_PreloadScripts[idx].c_str()
+ // , theEngine->m_PreloadProjectDir.c_str()
+ // , pathBuffer
+ // ,
+ //theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer()
+ // ,
+ //theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetInputStreamFactory()
+ // , loadBuffer );
+ // }
+ // theEngine->m_PreloadSync.set();
+ //}
+
+ // static void ProfileHook( lua_State* inLuaState, lua_Debug* ar )
+ //{
+ // //First check if valid function
+ // //We only profile pure lua code.
+ // lua_Debug stackInfo;
+ // if ( lua_getstack( inLuaState, 0, &stackInfo ) && lua_getinfo( inLuaState, "nSl", &stackInfo
+ //) )
+ // {
+ // bool validFunction = ( ar->event == LUA_HOOKCALL || ar->event == LUA_HOOKRET )
+ // && !qt3ds::foundation::isTrivial( stackInfo.source
+ //)
+ // && stackInfo.source[0] == '@';
+
+ // if ( !validFunction ) return;
+ //
+ // lua_getfield( inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine" );
+ // SLuaEngineImpl* theEngine = (SLuaEngineImpl*)( lua_touserdata( inLuaState, -1 ) );
+ // lua_pop( inLuaState, 1 );
+ // theEngine->m_PerfNameBuilder.assign( stackInfo.source + 1 );
+ // eastl::string::size_type slashPos = theEngine->m_PerfNameBuilder.find_last_of( "\\/"
+ //);
+ // if ( slashPos != eastl::string::npos )
+ // theEngine->m_PerfNameBuilder.erase( theEngine->m_PerfNameBuilder.begin(),
+ //theEngine->m_PerfNameBuilder.begin() + slashPos + 1 );
+ // theEngine->m_PerfNameBuilder.append( ":" );
+ // char buf[24];
+ // sprintf( buf, "%d", stackInfo.linedefined );
+ // theEngine->m_PerfNameBuilder.append( buf );
+ // size_t currentPerfStackSize = theEngine->m_PerfStack.size();
+ // if ( ar->event == LUA_HOOKCALL )
+ // {
+ // while ( theEngine->m_PerfStackIndex >= currentPerfStackSize )
+ // {
+ // theEngine->m_PerfStack.push_back( SLuaPerfEvent() );
+ // ++currentPerfStackSize;
+ // }
+
+ // SLuaPerfEvent& backEvent =
+ //theEngine->m_PerfStack[theEngine->m_PerfStackIndex];
+ // ++theEngine->m_PerfStackIndex;
+ // backEvent.m_Time = qt3ds::foundation::Time::getCurrentCounterValue();
+ // backEvent.m_Name.assign( theEngine->m_PerfNameBuilder );
+ // }
+ // else
+ // {
+
+ // if ( theEngine->m_ApplicationCore != 0
+ // && theEngine->m_PerfStackIndex > 0
+ // && theEngine->m_PerfStackIndex <= currentPerfStackSize )
+ // {
+ // qt3ds::foundation::IPerfTimer& theTimer =
+ //theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ // SLuaPerfEvent& backEvent = theEngine->m_PerfStack[theEngine->m_PerfStackIndex -
+ //1];
+ // -- theEngine->m_PerfStackIndex;
+ // theTimer.Update( backEvent.m_Name.c_str(),
+ //qt3ds::foundation::Time::getCurrentCounterValue() - backEvent.m_Time );
+ // }
+ // }
+ // }
+ //}
+}
+using namespace __SLuaEngineImpl_Static_Calls__;
+
+namespace __SLuaEngineImpl_Basic_Structs__ {
+ // void SLuaEngineListener::OnBreak()
+ //{
+ // m_Engine.OnBreak();
+ //}
+}
+//==============================================================================
+/**
+ * Constructor
+ */
+SLuaEngineImpl::SLuaEngineImpl(uic::state::SNDDStateContext &inContext)
+ : m_Context(inContext)
+ , m_LuaState(0)
+ , m_Application(0)
+ , m_ServerPort(0)
+ , m_CallbackIndex(0)
+ , m_LuaPathInitialized(false)
+ , m_PreloadState(0)
+ , m_PreloadSync(m_Context.GetAllocator())
+ , m_PreloadMutex(m_Context.GetAllocator())
+ , m_MultithreadedMutex(0)
+ , m_PerfStackIndex(0)
+ , m_ProfileActive(false)
+ , mRefCount(0)
+{
+ m_LuaState = lua_newstate(g_engine_alloc, 0);
+ Q3DStudio_ASSERT(m_LuaState);
+
+ lua_gc(m_LuaState, LUA_GCSTOP, 0);
+
+ // Override this function pointer for customization of loading of lua libraries.
+ // Default uses luaL_openlibs which opens all libraries found in linit.c
+ LoadLuaLibraries(m_LuaState);
+
+ lua_newtable(m_LuaState);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // Reg(1) = BehaviorsT
+
+ // Reg(5) = Global functions temporary parking lot for registerForEvent and registerForChange
+ lua_newtable(m_LuaState);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS);
+
+ // Callbacks table for callbacks sent from script.
+ lua_newtable(m_LuaState);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX, KEY_REGISTEREDCALLBACKS);
+
+ lua_pushlightuserdata(m_LuaState, this);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+
+ lua_getglobal(m_LuaState, "math"); // 2 = "math" table
+ lua_pushstring(m_LuaState, "randomseed"); // 3 = "randomseed"
+ lua_rawget(m_LuaState, -2); // 3 = math.randomseed function
+ lua_pushinteger(m_LuaState,
+ static_cast<INT32>(m_Context.m_TimeProvider.GetCurrentTimeMicroSeconds()));
+ lua_pcall(m_LuaState, 1, 0, 0); // [size = 2]
+
+ lua_settop(m_LuaState, 0);
+
+ memset(&g_engine_file_io, 0, sizeof(_lua_user_file_io));
+
+ g_engine_file_io.user_fopen = lua_user_fopen;
+ g_engine_file_io.user_fclose = lua_user_fclose;
+ g_engine_file_io.user_getc = lua_user_getc;
+ g_engine_file_io.user_ungetc = lua_user_ungetc;
+ g_engine_file_io.user_fgets = lua_user_fgets;
+ g_engine_file_io.user_fread = lua_user_fread;
+ g_engine_file_io.user_ferror = lua_user_ferror;
+ g_engine_file_io.user_feof = lua_user_feof;
+ g_engine_file_io.user_fread_double = lua_user_fread_number;
+ g_engine_file_io.user_clearerr = lua_user_clearerr;
+}
+
+SLuaEngineImpl::~SLuaEngineImpl()
+{
+ qCDebug (qt3ds::TRACE_INFO) << "SLuaEngineImpl: destructing";
+}
+
+//==============================================================================
+/**
+ * ****************Inherited virtual functions from IScriptBridge **************
+ */
+//=============================================================================
+void SLuaEngineImpl::EnableMultithreadedAccess()
+{
+ m_MultithreadedMutex = &m_PreloadMutex;
+}
+
+void SLuaEngineImpl::DisableMultithreadedAccess()
+{
+ m_MultithreadedMutex = 0;
+}
+
+void SLuaEngineImpl::SetApplication(uic::state::INDDStateApplication &inApplication)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ m_Application = &inApplication;
+ lua_pushlightuserdata(m_LuaState, m_Application);
+ lua_setglobal(m_LuaState, "UICApplication");
+}
+
+// Starts preloading scripts offline. This sets m_LuaState to NULL until after EndPreloadScripts to
+// avoid multithreaded lua state access. Some calls may be queued till EndPreloadScripts
+// void SLuaEngineImpl::BeginPreloadScripts( const eastl::vector<const char*>& inScripts,
+// uic::render::IThreadPool& inThreadPool, const char* inProjDir )
+//{
+// m_PreloadScripts.assign( inScripts.begin(), inScripts.end() );
+// m_PreloadState = m_LuaState;
+// m_LuaState = 0;
+// m_PreloadProjectDir.assign( inProjDir );
+// m_PreloadSync.reset();
+// inThreadPool.AddTask( this, PreloadFunctionCall, 0 );
+//}
+
+// Ends preload, restores m_LuaState.
+// void SLuaEngineImpl::EndPreloadScripts()
+//{
+// qt3ds::foundation::Mutex::ScopedLock __locker( m_PreloadMutex );
+// if ( m_LuaState == 0 )
+// {
+// m_PreloadSync.wait();
+// m_LuaState = m_PreloadState;
+// m_PreloadState = 0;
+// }
+//}
+
+// Fast loading support; on save get the set of loaded scripts
+eastl::vector<eastl::string> SLuaEngineImpl::GetLoadedScripts()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ eastl::vector<eastl::string> retval;
+ SLuaStackScope theScope(m_LuaState);
+ GetLoadedBuffersTable(m_LuaState);
+ QT3DS_ASSERT(lua_type(m_LuaState, -1) == LUA_TTABLE);
+ lua_pushnil(m_LuaState);
+ eastl::vector<eastl::pair<eastl::string, QT3DSU32>> theDirectory;
+ qt3ds::foundation::MemoryBuffer<> theBuffer(
+ qt3ds::foundation::ForwardingAllocator(m_Context.GetAllocator(), "LuaBinaryData"));
+ while (lua_next(m_LuaState, -2)) {
+ // dup the key
+ lua_pushvalue(m_LuaState, -2);
+ const char *relativeFileName = lua_tostring(m_LuaState, -1);
+ retval.push_back(relativeFileName);
+ // pop the key
+ lua_pop(m_LuaState, 1);
+ // Dump the function
+ theDirectory.push_back(eastl::make_pair(retval.back(), (QT3DSU32)theBuffer.size()));
+ lua_dump(m_LuaState, WriteLuaData, &theBuffer);
+ // pop the value
+ lua_pop(m_LuaState, 1);
+ }
+ eastl::string tempStr;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(m_Context.GetProjectDir(), "binary",
+ tempStr);
+ qt3ds::foundation::CFileTools::CreateDir(tempStr.c_str());
+ tempStr.append("/compiledlua.bin");
+ qt3ds::foundation::CFileSeekableIOStream theStream(tempStr.c_str(),
+ qt3ds::foundation::FileWriteFlags());
+ if (theStream.IsOpen() == false) {
+ qCCritical(qt3ds::INTERNAL_ERROR, "Unable to open lua binary file");
+ QT3DS_ASSERT(false);
+ }
+ qt3ds::foundation::IOutStream &theOutStream(theStream);
+ theOutStream.Write((QT3DSU32)theDirectory.size());
+ for (QT3DSU32 idx = 0, end = theDirectory.size(); idx < end; ++idx) {
+ eastl::pair<eastl::string, QT3DSU32> &theEntry(theDirectory[idx]);
+ QT3DSU32 theStrLen = (QT3DSU32)theEntry.first.size();
+ if (theStrLen)
+ ++theStrLen;
+ theOutStream.Write(theStrLen);
+ if (theStrLen)
+ theOutStream.Write(theEntry.first.c_str(), theStrLen);
+ theOutStream.Write(theEntry.second);
+ }
+ theOutStream.Write((QT3DSU32)theBuffer.size());
+ theOutStream.Write(theBuffer.begin(), (QT3DSU32)theBuffer.size());
+ return retval;
+}
+
+Q3DStudio::INT32 SLuaEngineImpl::InitializeApplicationBehavior(const char *inRelativePath)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope __topScope(m_LuaState);
+ PrepareToLoadFile();
+ eastl::string scriptBuffer;
+ int loadError =
+ EnsureScriptIsLoaded(m_LuaState, inRelativePath, m_Context.GetProjectDir(), scriptBuffer
+ //, m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer()
+ ,
+ *m_Context.m_InputStreamFactory, m_LoadVec);
+ if (loadError) {
+ const char *errorMsg = lua_tostring(m_LuaState, -1);
+ qCCritical(qt3ds::INVALID_PARAMETER, "Failed to load lua file: %s: %s",
+ inRelativePath, errorMsg);
+ return 0;
+ }
+ Q3DStudio::INT32 theScriptIndex = 0;
+ {
+ SLuaStackScope __selfScope(m_LuaState);
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // 1 = BehaviorsT
+ lua_newtable(m_LuaState); // 2 = self
+
+ lua_pushvalue(m_LuaState, -1); // dup the table
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, KEY_SELF); // 2 = self
+
+ lua_pushvalue(m_LuaState, -1); // dup the table
+ theScriptIndex = luaL_ref(m_LuaState, -3); // Add a new script into the behaviors table.
+
+ lua_pushinteger(m_LuaState, theScriptIndex);
+ lua_setfield(m_LuaState, -2, KEY_SCRIPT_INDEX);
+
+ lua_pushstring(m_LuaState, inRelativePath);
+ lua_setfield(m_LuaState, -2, "__scriptpath__");
+ }
+
+ int pcallError = PCall(0, 0, 0);
+ if (pcallError) {
+ const char *errorMsg = lua_tostring(m_LuaState, -1);
+ qCCritical(qt3ds::INVALID_PARAMETER, "Failed to load lua file: %s: %s",
+ inRelativePath, errorMsg);
+ return 0;
+ }
+ return theScriptIndex;
+}
+
+void SLuaEngineImpl::ExecuteApplicationScriptFunction(Q3DStudio::INT32 inApp, const char *inFnName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope __topScope(m_LuaState);
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS);
+ lua_rawgeti(m_LuaState, -1, inApp);
+ int selfIndex = lua_gettop(m_LuaState);
+ if (!lua_istable(m_LuaState, -1)) {
+ qCCritical(qt3ds::INVALID_OPERATION, "Lua object index appears to be invalid");
+ return;
+ }
+ lua_getfield(m_LuaState, -1, inFnName);
+ if (lua_isfunction(m_LuaState, -1)) {
+ // IPerfTimer* theTimer = 0;
+ // const char* thePerfName = "";
+ // if ( m_ApplicationCore )
+ //{
+ // lua_getfield( m_LuaState, -2, "__scriptpath__" );
+ // if ( lua_isstring( m_LuaState, -1 ) )
+ // {
+ // m_ScriptString.clear();
+ // m_ScriptString.assign( lua_tostring( m_LuaState, -1 ) );
+ // m_ScriptString.append( " - " );
+ // m_ScriptString.append( inFnName );
+ // thePerfName = m_ScriptString.c_str();
+ // theTimer = &m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ // }
+ // lua_pop( m_LuaState, 1 );
+ //}
+ // SStackPerfTimer __scriptTimer( theTimer, thePerfName );
+ // push the self element
+ lua_pushvalue(m_LuaState, -2);
+ lua_pushvalue(m_LuaState, -1); // dup that
+ lua_setglobal(m_LuaState, KEY_SELF); // set the global self element (WAT)
+
+ int pcallError = PCall(1, 0, 0);
+ if (pcallError) {
+ const char *errorStr = lua_tostring(m_LuaState, -1);
+ qCCritical(qt3ds::INVALID_OPERATION,
+ "Lua object call %s failed: %s. disabling further calls",
+ inFnName, errorStr);
+ lua_pushnil(m_LuaState);
+ lua_setfield(m_LuaState, selfIndex, inFnName);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Add a new global function to my lua_State. This is useful to call from the outside.
+ */
+void SLuaEngineImpl::AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction)
+{
+ if (m_LuaState) {
+ lua_register(m_LuaState, inFunctionName, inFunction);
+ }
+}
+
+// void SLuaEngineImpl::EnableDebugging(uic::state::debugger::IMultiProtocolSocket& socket)
+//{
+// LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+// using namespace uic::state::debugger;
+// QT3DS_ASSERT( m_ApplicationCore );
+// NVScopedRefCounted<uic::state::debugger::IMultiProtocolSocketStream> theStream
+// = socket.CreateProtocol(
+//uic::state::debugger::ILuaArchitectDebugServer::LuaProtocolName(), 0 );
+// m_LuaListener = QT3DS_NEW( m_Foundation.getAllocator(), SLuaEngineListener)( m_Foundation,
+//*this );
+//
+// m_LuaDebugger = uic::state::debugger::ILuaDebugger::CreateLuaSideDebugger(
+// m_ApplicationCore->GetRuntimeFactoryCore().GetFoundation()
+// , *theStream
+// , m_LuaState
+// , m_ApplicationCore->GetRuntimeFactoryCore().GetStringTable()
+// , m_ApplicationCore->GetProjectDirectory().c_str()
+// , m_LuaListener.mPtr );
+//}
+
+// void SLuaEngineImpl::EnableProfiling()
+//{
+// LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+// lua_sethook( m_LuaState, ProfileHook, LUA_MASKCALL | LUA_MASKRET, 0 );
+//}
+
+void SLuaEngineImpl::StepGC()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ // IPerfTimer* theTimer = 0;
+ // if ( m_ApplicationCore )
+ // theTimer = &m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ // SStackPerfTimer __timer( theTimer, "CLuaEngine::StepGC" );
+ lua_gc(m_LuaState, LUA_GCSTEP, 5);
+}
+//==============================================================================
+/**
+ * ****************End of IScriptBridge functions **************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * ****************Inherited virtual functions from CLuaEngine **************
+ */
+//=============================================================================
+uic::state::IStateInterpreter *
+SLuaEngineImpl::CreateStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodelFunction)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope __topScope(m_LuaState);
+ // This assertion is key. Without it, somewhere in below a setField function gets called on
+ // something that isn't
+ // a table and the program blinks out of existance.
+ if (__topScope.m_Top != 0) {
+ qFatal("CLuaEngine::CreateStateMachine called when lua stack is not at zero; aborting");
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ lua_pushcfunction(m_LuaState, ParseSCXML);
+ eastl::string fullPath;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(m_Context.GetProjectDir(), inPath, fullPath);
+ lua_pushstring(m_LuaState, fullPath.c_str());
+ uic::state::IStateInterpreter *theInterpreter = 0;
+ int error = PCall(1, 1, 0);
+ if (error) {
+ qCCritical(qt3ds::INVALID_OPERATION, "Failed to load scxml file: %s",
+ lua_tostring(m_LuaState, -1));
+ } else {
+ lua_insert(m_LuaState, 1);
+ lua_settop(m_LuaState, 1);
+ int isTable = lua_istable(m_LuaState, 1);
+ QT3DS_ASSERT(isTable);
+ (void)isTable;
+ // shove it in the global table under its path. We will get to this again in a second
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1);
+ lua_newtable(m_LuaState);
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ }
+ lua_pushvalue(m_LuaState, -2);
+ lua_setfield(m_LuaState, -2, inId);
+ lua_pop(m_LuaState, 1); // pop the machine table
+
+ // The state machine should still be top of the stack.
+ // if ( !qt3ds::foundation::isTrivial( inDatamodelFunction ) )
+ {
+ int theNewTop = lua_gettop(m_LuaState);
+ eastl::string evalStr("return ");
+ evalStr.append(inDatamodelFunction);
+ luaL_loadstring(m_LuaState, evalStr.c_str());
+ int failure = PCall(0, 1, 0);
+ if (failure) {
+ const char *error = lua_tostring(m_LuaState, -1);
+ qCCritical (qt3ds::INVALID_OPERATION)
+ << "LuaEngine: Unable to initialize datamodel, "
+ << inDatamodelFunction << " " << error;
+ lua_settop(m_LuaState, theNewTop);
+ } else {
+ // Hmm, now to get the item the function returned to be below the string in the
+ // stack.
+ // And clear off the stack from there.
+ lua_insert(m_LuaState, theNewTop + 1);
+ lua_settop(m_LuaState, theNewTop + 1);
+ }
+ }
+ // If all that worked then we should have the state machine and the datatable on the stack
+ // and only those two on the stack.
+ // At which point we can call start, which will pop everything off the stack
+ uic::state::ILuaScriptContext::Initialize(m_LuaState, inId);
+ // Now get the interpreter from the map so we can get its value
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ lua_getfield(m_LuaState, -1, inId);
+ theInterpreter = uic::state::ILuaScriptContext::GetInterpreterFromBindings(m_LuaState);
+ }
+ return theInterpreter;
+}
+
+// Functions that will not crash if the lua engine has no application or if the presentations
+// are in an indeterminate state.
+void SLuaEngineImpl::PreInitialize()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ lua_register(m_LuaState, "output", Output);
+ lua_register(m_LuaState, "getEventSystem", GetEventSystem);
+}
+//==============================================================================
+/**
+ * Register the set of global Lua functions
+ */
+void SLuaEngineImpl::Initialize()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ lua_register(m_LuaState, "getElapsedTime", GetElapsedTime);
+ lua_register(m_LuaState, "getDirectory", GetDirectory);
+ lua_register(m_LuaState, "getStateMachine", GetSCXMLInterpreter);
+ lua_register(m_LuaState, "getMillisecondsSinceLastFrame", GetMillisecondsSinceLastFrame);
+}
+
+void SLuaEngineImpl::Shutdown(qt3ds::NVFoundationBase &inFoundation)
+{
+ qCInfo(qt3ds::TRACE_INFO, "Lua engine Begin Exit");
+ // EndPreloadScripts();
+ {
+ qt3ds::foundation::Mutex::ScopedLock __locker(m_PreloadMutex);
+ DisableMultithreadedAccess();
+ }
+ lua_close(m_LuaState);
+ m_LuaState = 0;
+
+ g_InputStreamFactory = 0;
+ lua_set_file_io(0);
+
+ qCInfo(qt3ds::TRACE_INFO, "Lua engine End Exit");
+}
+
+//==============================================================================
+/**
+ * ************************End of CLuaEngine functions ************************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * *******************Local functions ************************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * Helper function to call the lua functions in the self table
+ * @param inScriptIndex the script index to get the self table
+ * @param inFunctionName the lua function to call
+ * @return true if the function is called, false if otherwise
+ */
+// SLuaFunctionResult SLuaEngineImpl::CallFunction( INT32 inScriptIndex, const CHAR* inFunctionName
+// )
+//{
+// LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+// PerfLogLuaEvent1( DATALOGGER_CALLLUAFUNCTION );
+//
+// int theTop = lua_gettop( m_LuaState );
+//
+// lua_pushcfunction( m_LuaState, ErrorChannel ); // Top + 1
+//= error handler
+//
+// lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS ); // Top + 2 =
+//BehaviorsT
+//
+// lua_rawgeti( m_LuaState, -1, inScriptIndex ); // Top + 3
+//= ScriptT
+// BOOL theFunctionFlag = FALSE;
+// BOOL thePCallError = TRUE;
+// if ( lua_istable( m_LuaState, -1 ) )
+// {
+// thePCallError = FALSE;
+// lua_getfield( m_LuaState, -1, inFunctionName ); //
+//Top + 4 = OnXXX function, if there's one
+//
+// theFunctionFlag = lua_isfunction( m_LuaState, -1 );
+// if ( theFunctionFlag )
+//// if it is a function, call it
+// {
+// const char* thePerfName = "";
+// IPerfTimer* theTimer = 0;
+// if ( m_ApplicationCore )
+// {
+// lua_getfield( m_LuaState, -2, "__scriptpath__" );
+// if ( lua_isstring( m_LuaState, -1 ) )
+// {
+// m_ScriptString.clear();
+// m_ScriptString.assign( lua_tostring( m_LuaState, -1 ) );
+// m_ScriptString.append( " - " );
+// m_ScriptString.append( inFunctionName );
+// thePerfName = m_ScriptString.c_str();
+// theTimer =
+//&m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+// }
+// }
+// SStackPerfTimer __scriptTimer( theTimer, thePerfName );
+// lua_pop( m_LuaState, 1 );
+// lua_pushlstring( m_LuaState, KEY_SELF, LENGTH_KEY_SELF ); // Top + 5
+//= 'self'
+// lua_pushvalue( m_LuaState, -3 );
+//// Top + 6 = ScriptT
+// lua_rawset( m_LuaState, LUA_GLOBALSINDEX );
+//// [size = Top + 4]
+//
+// lua_pushvalue( m_LuaState, -2 );// Top + 5 = ScriptT
+//
+// int error = PCall( 1, 0, theTop + 1 ); //
+//[size = Top + 3]
+// if ( error )
+// thePCallError = TRUE;
+// }
+// }
+//
+// lua_settop( m_LuaState, theTop );
+//
+// return SLuaFunctionResult( theFunctionFlag, thePCallError );
+//}
+
+void SLuaEngineImpl::PrepareToLoadFile()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ if (m_LuaPathInitialized == false) {
+ m_LuaPathInitialized = true;
+ eastl::string projectDir(m_Context.GetProjectDir());
+ qt3ds::foundation::CFileTools::ToPlatformPath(projectDir);
+
+ eastl::string subdir = qt3ds::foundation::System::getPlatformStr();
+ lua_State *state = m_LuaState != 0 ? m_LuaState : m_PreloadState;
+ // this block of code so far is only used by android
+ if (!g_AdditionalSharedLibraryPaths.empty()) {
+ for (eastl::vector<eastl::string>::iterator iter =
+ g_AdditionalSharedLibraryPaths.begin();
+ iter != g_AdditionalSharedLibraryPaths.end(); iter++) {
+ const eastl::string &additionalPathRef = *iter;
+ AppendAdditionalLuaPackagePath(state, additionalPathRef);
+ }
+ }
+
+ // eastl::string scriptsDir;
+ // CFileTools::CombineBaseAndRelative( projectDir.c_str(), "scripts", scriptsDir );
+ // AppendLuaPackagePath( state, scriptsDir, eLuaPath);
+ // AppendLuaPackagePath( state, scriptsDir, eCPath);
+
+ // Add in additional search directory for specific platform
+ eastl::string scriptsPlatformDir;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(".\\scripts", subdir.c_str(),
+ scriptsPlatformDir);
+ qt3ds::foundation::CFileTools::ToPlatformPath(scriptsPlatformDir);
+ AppendLuaPackagePath(state, scriptsPlatformDir, eCPath);
+ }
+}
+
+int SLuaEngineImpl::PCall(int argcount, int retcount, int errorIndex)
+{
+ bool wasProfiling = m_ProfileActive;
+ m_ProfileActive = true;
+ if (!wasProfiling)
+ m_PerfStackIndex = 0;
+ int retval = lua_pcall(m_LuaState, argcount, retcount, errorIndex);
+ m_ProfileActive = wasProfiling;
+ return retval;
+}
+
+// void SLuaEngineImpl::OnBreak()
+//{
+// uic::state::debugger::IDebugger& theDebugger = m_ApplicationCore->GetStateDebugger();
+// theDebugger.OnExternalBreak();
+//}
+
+//==============================================================================
+/**
+ * ************************End of local functions ************************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * *******************exported global Lua functions definition********************
+ */
+//=============================================================================
+namespace __SLuaEngineImpl_Static_Global_Lua_Exporter_Declaration__ {
+ using namespace Q3DStudio;
+
+ SLuaEngineImpl *GetLuaEngineFromLua(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ return theEngine;
+ }
+
+ int Output(lua_State *inLuaState)
+ {
+ Q3DStudio::INT32 theTop = lua_gettop(inLuaState);
+ QString theString = "";
+
+ for (Q3DStudio::INT32 theCounter = 1; theCounter <= theTop; ++theCounter) {
+ lua_getglobal(inLuaState, "tostring");
+ lua_pushvalue(inLuaState, theCounter);
+ if (lua_pcall(inLuaState, 1, 1, 0))
+ theString.append("output: Error while calling 'tostring'.");
+ else {
+ const Q3DStudio::CHAR *theResult = lua_tostring(inLuaState, -1);
+ if (theResult)
+ theString.append(theResult);
+ else
+ theString.append("output: 'tostring' must return a string to 'output'");
+ }
+
+ if ((theCounter + 1) <= theTop)
+ theString.append("\n");
+ }
+
+ qCInfo (qt3ds::TRACE_INFO) << "Lua: " << theString.toLatin1().constData();
+
+ lua_settop(inLuaState, 0);
+
+ return 0;
+ }
+
+ //==============================================================================
+ /**
+ * Gets the elapsed time since the start of the presentation. If element isn't
+ * a component, it walks up the tree to find one that is.
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 2 - the elapsed time in seconds and the real world time that were
+ * pushed on the stack
+ */
+ int GetElapsedTime(lua_State *inLuaState)
+ {
+ SLuaEngineImpl *theLuaEngine = GetLuaEngineFromLua(inLuaState);
+ if (theLuaEngine) {
+ Q3DStudio::INT64 theMicroSeconds =
+ theLuaEngine->m_Context.m_TimeProvider.GetCurrentTimeMicroSeconds();
+ double theSeconds = (double)theMicroSeconds / 1000.0 / 1000.0;
+ lua_pushnumber(inLuaState, (lua_Number)(theSeconds));
+ return 1;
+ }
+ return 0;
+ }
+
+ const THashValue HASH_DIRECTORY_PROJECT = CHash::HashString("project");
+ const THashValue HASH_DIRECTORY_SCRIPTS = CHash::HashString("scripts");
+ const THashValue HASH_DIRECTORY_PLUGINS = CHash::HashString("plugins");
+ const THashValue HASH_DIRECTORY_SCRIPTS_PLATFORM = CHash::HashString("scripts-platform");
+ const THashValue HASH_DIRECTORY_PLUGINS_PLATFORM = CHash::HashString("plugins-platform");
+
+ int GetDirectory(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ if (theEngine) {
+ eastl::string sub;
+ int argc = lua_gettop(inLuaState);
+ const Q3DStudio::CHAR *directoryName =
+ argc > 0 ? luaL_checkstring(inLuaState, 1) : "project";
+ THashValue directoryHash = CHash::HashString(directoryName);
+ if (directoryHash == HASH_DIRECTORY_PROJECT)
+ sub.clear();
+ else if (directoryHash == HASH_DIRECTORY_SCRIPTS)
+ sub.assign("scripts");
+ else if (directoryHash == HASH_DIRECTORY_PLUGINS)
+ sub.assign("plugins");
+ else if (directoryHash == HASH_DIRECTORY_SCRIPTS_PLATFORM)
+ sub.assign("scripts/").append(qt3ds::foundation::System::getPlatformStr());
+ else {
+ qCCritical (qt3ds::TRACE_INFO) << "getDirectory wasn't passed an recognized string";
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+ eastl::string dir(theEngine->m_Context.GetProjectDir());
+ if (!sub.empty())
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(dir.c_str(), sub.c_str(), dir);
+ CFileTools::ToPlatformPath(dir);
+ lua_pushstring(inLuaState, dir.c_str());
+ } else
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+
+ int ParseSCXML(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+
+ uic::state::debugger::IDebugger *theDebugger = 0;
+ // if ( theEngine )
+ //{
+ // theDebugger = &theEngine->m_Application->GetStateDebugger();
+ //}
+ return uic::state::ILuaScriptContext::ParseSCXML(inLuaState, theDebugger,
+ *theEngine->m_Context.m_Foundation,
+ theEngine->m_Context.GetStringTable());
+ }
+
+ int GetSCXMLInterpreter(lua_State *inLuaState)
+ {
+ const char *path = lua_tostring(inLuaState, -1);
+ if (!path) {
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+ // shove it in the global table under its path. We will get to this again in a second
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ if (lua_isnil(inLuaState, -1))
+ return 1;
+
+ lua_getfield(inLuaState, -1, path);
+ return 1;
+ }
+
+ int GetEventSystem(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_event_system");
+ if (!lua_istable(inLuaState, -1)) {
+ lua_pop(inLuaState, 1);
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ uic::evt::IEventSystem &theEventSystem =
+ theEngine->m_Context.m_Factory->GetEventSystem();
+ uic::evt::SLuaEventPollerBinding::WrapEventPoller(inLuaState, theEventSystem);
+ lua_pushvalue(inLuaState, -1);
+ lua_setfield(inLuaState, LUA_REGISTRYINDEX, "uic_event_system");
+ }
+ return 1;
+ }
+
+ int GetMillisecondsSinceLastFrame(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ if (theEngine) {
+ lua_pushnumber(inLuaState, theEngine->m_Application->GetMillisecondsSinceLastFrame());
+ return 1;
+ }
+ return 0;
+ }
+}
+//==============================================================================
+/**
+ * *******************end of exported global Lua functions definitions************
+ */
+//=============================================================================
+}
+
+//==============================================================================
+/**
+ * *******************static functions from INDDStateLuaEngine ************************
+ */
+//=============================================================================
+//==============================================================================
+namespace uic {
+namespace state {
+ INDDStateLuaEngine *INDDStateLuaEngine::Create(SNDDStateContext &inContext)
+ {
+ return QT3DS_NEW(inContext.GetAllocator(), SLuaEngineImpl)(inContext);
+ }
+}
+}
+//==============================================================================
+/**
+ * *******************end of static functions from CLuaEngine ******************
+ */
+//=============================================================================
diff --git a/src/Runtime/Source/Runtime/Include/RuntimePrefix.h b/src/Runtime/Source/Runtime/Include/RuntimePrefix.h
new file mode 100644
index 00000000..4d6baf28
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/RuntimePrefix.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "render/backends/gl/Qt3DSOpenGLPrefix.h"
+
+#ifdef _WIN32
+//==============================================================================
+// DISABLED WARNINGS
+//
+// Note that most of these warnings are tuned off by default by the compiler
+// even at warning level 4. Using option /Wall turns on all warnings and makes
+// even standard Microsoft include files cry. We had to turn off these or
+// turn off warnings individually for each standard include file which was
+// too much work. Point is that /Wall is like Warning Level 5 and this brings
+// it down to about Warning level 4.5, still way above /W4.
+//#pragma warning( disable : 4189 ) // local variable is initialized but not referenced
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+#pragma warning(disable : 4511) // copy constructor could not be generated
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#pragma warning(disable : 4514) // unreferenced inline function has been removed
+#pragma warning(disable : 4619) // #pragma warning : there is no warning number '4619' (in string.h)
+#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy
+ // constructor is inaccessible
+#pragma warning(disable : 4626) // assignment operator could not be generated because a base class
+ // assignment operator is inaccessible
+#pragma warning( \
+ disable : 4668) // not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+#pragma warning(disable : 4826) // Conversion from 'const void *' to 'void *' is sign-extended
+#pragma warning(disable : 4996) // _snprintf' was declared deprecated
+#pragma warning(disable : 4711) // function selected for automatic inline expansion
+#pragma warning(disable : 4710) // function not inlined
+#pragma warning( \
+ disable : 4738) // storing 32-bit float result in memory, possible loss of performance
+
+#pragma warning(disable : 4640) // construction of local static object is not thread-safe
+#pragma warning(disable : 4127) // conditional expression is constant
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif //_WIN32
+
+//==============================================================================
+// STD INCLUDES - Standard includes MUST come first
+#include <stdlib.h> // Standard functions
+#include <stdio.h> // File and IO
+#ifndef _INTEGRITYPLATFORM
+#include <memory.h> // memset, memcpy
+#endif
+#include <string.h> // strlen
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#include <stdint.h>
+
+#define UNREFERENCED_PARAMETER(theParam) theParam;
+#endif
+
+//==============================================================================
+// ROOT INCLUDES FOR FRAMEWORK
+//==============================================================================
+#include "UICTypes.h"
+#include "UICPlatformSpecific.h"
+#include "UICAssert.h"
+#include "UICMacros.h"
+#include "UICConfig.h"
+#include "UICMemorySettings.h"
+#include "UICMemory.h"
+#include "UICFrameworkTypes.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTimer.h"
+#include "UICIScene.h"
+#include "UICSyncPrimitive.h"
+#include "foundation/Qt3DSRefCounted.h" //scoped releasable auto ptr.
+#include "EASTL/hash_map.h"
+#include "EASTL/string.h"
diff --git a/src/Runtime/Source/Runtime/Include/UICActivationManager.h b/src/Runtime/Source/Runtime/Include/UICActivationManager.h
new file mode 100644
index 00000000..6ca5eecf
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICActivationManager.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_ACTIVATION_MANAGER_H
+#define UIC_ACTIVATION_MANAGER_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Utils.h"
+#include "UICKernelTypes.h"
+#include "UICMetadata.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICTimePolicy.h"
+
+namespace Q3DStudio {
+struct IComponentTimeOverrideFinishedCallback;
+struct SComponentTimePolicyOverride;
+class CPresentation;
+}
+
+namespace qt3ds {
+namespace foundation {
+ class IPerfTimer;
+}
+}
+
+namespace uic {
+namespace render {
+ class IThreadPool;
+}
+}
+
+namespace uic {
+namespace runtime {
+ using namespace qt3ds::foundation;
+ using namespace qt3ds;
+ using Q3DStudio::CTimePolicy;
+ using Q3DStudio::SComponentTimePolicyOverride;
+ using Q3DStudio::IComponentTimeOverrideFinishedCallback;
+ using Q3DStudio::CPresentation;
+ using Q3DStudio::TTimeUnit;
+ using uic::render::IThreadPool;
+
+ class IActivationManager;
+
+ typedef element::SElement &TActivityItem;
+ typedef element::SElement *TActivityItemPtr;
+
+ typedef eastl::pair<element::SElement *, QT3DSU32> TElementAndSortKey;
+
+ typedef NVConstDataRef<TElementAndSortKey> TActivityItemBuffer;
+
+ // Items can have user active and time active. Time active is controlled by this object
+ // but user active can be set. An item is only active if it both actives are true.
+ // Inactive items have completely inactive children.
+ class IActivityZone
+ {
+ protected:
+ virtual ~IActivityZone() {}
+ public:
+ virtual Q3DStudio::CPresentation &GetPresentation() = 0;
+
+ // Items activated this cycle
+ virtual TActivityItemBuffer GetActivatedItems() = 0;
+ // Items deactivated this cycle
+ virtual TActivityItemBuffer GetDeactivatedItems() = 0;
+ // All active items that are script enabled.
+ virtual TActivityItemBuffer GetScriptItems() = 0;
+
+ // Inactive zones don't update their item lists when the manager updates.
+ virtual void SetZoneActive(bool inActive) = 0;
+ virtual bool IsZoneActive() = 0;
+
+ virtual void AddActivityItems(TActivityItem root) = 0;
+
+ // Get the time policy that is owned by this element.
+ virtual CTimePolicy *GetOwnedTimePolicy(TActivityItem item) = 0;
+ // Get the local time for this element. This is the time the animation system should see
+ virtual TTimeUnit GetItemLocalTime(TActivityItem item) = 0;
+ // Get the local time if this isn't independent, else get the time context time for the
+ // component.
+ virtual TTimeUnit GetItemComponentTime(TActivityItem item) = 0;
+
+ virtual SComponentTimePolicyOverride *
+ GetOrCreateItemComponentOverride(TActivityItem item, float inMultiplier,
+ TTimeUnit inEndTime,
+ IComponentTimeOverrideFinishedCallback *inCallback) = 0;
+
+ // If this item is independent, return this item.
+ // else get time parent of my parent.
+ virtual TActivityItemPtr GetItemTimeParent(TActivityItem item) = 0;
+
+ bool IsIndependent(TActivityItem item) { return GetOwnedTimePolicy(item) != NULL; }
+
+ // Any time the item has script flag changes after its initial creation.
+ // Note that this flag cannot change due to slide changes, it can only change due
+ // to something that had a script error and thus is disabled.
+ virtual void UpdateItemScriptStatus(TActivityItem item) = 0;
+
+ // If the start, end, or explicit active flags change *outside* of a slide change.
+ virtual void UpdateItemInfo(TActivityItem item) = 0;
+ virtual bool GetItemUserActive(TActivityItem item) = 0;
+
+ // Callback when the slide changes, the time context needs to be rebuilt in this case.
+ virtual void OnSlideChange(TActivityItem item) = 0;
+
+ virtual bool GetItemTimeActive(TActivityItem item) = 0;
+
+ virtual void BeginUpdate(QT3DSI64 inGlobalTime, IPerfTimer &inPerfTimer,
+ IThreadPool &inThreadPool) = 0;
+ virtual bool IsUpdating() = 0;
+ virtual void EndUpdate() = 0;
+
+ virtual void GoToTime(TActivityItem item, TTimeUnit inTime) = 0;
+ };
+
+ class IActivityZoneManager : public NVRefCounted
+ {
+ protected:
+ virtual ~IActivityZoneManager() {}
+ public:
+ virtual IActivityZone &CreateActivityZone(Q3DStudio::CPresentation &inPresentation) = 0;
+
+ static IActivityZoneManager &CreateActivityZoneManager(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable);
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICAnimationSystem.h b/src/Runtime/Source/Runtime/Include/UICAnimationSystem.h
new file mode 100644
index 00000000..54a0f79d
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICAnimationSystem.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_ANIMATION_SYSTEM_H
+#define UIC_ANIMATION_SYSTEM_H
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSRefCounted.h"
+
+#pragma once
+namespace qt3ds {
+namespace foundation {
+ class IOutStream;
+}
+}
+
+namespace uic {
+namespace runtime {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+
+ namespace element {
+ struct SElement;
+ }
+ class IElementAllocator;
+
+ class IAnimationSystem : public NVRefCounted
+ {
+ public:
+ virtual QT3DSI32 CreateAnimationTrack(element::SElement &inElement, QT3DSU32 inPropertyName,
+ bool inDynamic) = 0;
+ virtual void AddKey(QT3DSF32 inTime, QT3DSF32 inValue, QT3DSF32 inC1Time, QT3DSF32 inC1Value,
+ QT3DSF32 inC2Time, QT3DSF32 inC2Value) = 0;
+ virtual void Update() = 0;
+ virtual void SetActive(QT3DSI32 inTrackId, bool inActive) = 0;
+ virtual void UpdateDynamicKey(QT3DSI32 inTrackId) = 0;
+
+ virtual void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream,
+ IElementAllocator &inElementAllocator) = 0;
+ virtual void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData, size_t inElementOffset) = 0;
+
+ static IAnimationSystem &CreateAnimationSystem(NVFoundationBase &inFoundation);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICApplication.h b/src/Runtime/Source/Runtime/Include/UICApplication.h
new file mode 100644
index 00000000..1c5e4c66
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICApplication.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_APPLICATION_H
+#define UIC_APPLICATION_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Utils.h"
+#include "UICKernelTypes.h"
+#include "UICMetadata.h"
+
+namespace Q3DStudio {
+class IRuntimeFactory;
+class IRuntimeFactoryCore;
+class CRuntime;
+class CPresentation;
+class CInputEngine;
+class IAudioPlayer;
+}
+
+namespace uic {
+namespace state {
+namespace debugger {
+class IDebugger;
+class ISceneGraphRuntimeDebugger;
+}
+}
+}
+
+namespace uic {
+class UICAssetVisitor;
+namespace runtime {
+using namespace qt3ds::foundation;
+using namespace qt3ds;
+
+class IElementAllocator;
+class IActivityZoneManager;
+
+class CAppStr : public eastl::basic_string<char8_t, ForwardingAllocator>
+{
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TBase;
+
+public:
+ CAppStr(NVAllocatorCallback &alloc, const char8_t *inStr = NULL);
+ CAppStr(const CAppStr &inOther);
+ CAppStr();
+ CAppStr &operator=(const CAppStr &inOther);
+};
+
+class IApplication;
+
+class IAppRunnable : public NVRefCounted
+{
+public:
+ virtual void Run() = 0;
+};
+
+class IApplicationCore : public NVRefCounted
+{
+public:
+ // threadsafe call.
+ virtual void QueueForMainThread(IAppRunnable &inRunnable) = 0;
+
+ // The directory that contains the executable and the root resource path
+ virtual CRegisteredString GetApplicationDirectory() const = 0;
+ // Directory that contained the UIA file.
+ virtual CRegisteredString GetProjectDirectory() const = 0;
+ // Directory where we will copy shared object files to before we load them.
+ // This is specifically for android and the case where the place where the project exists
+ // is not always the place where we can load the project.
+ virtual CRegisteredString GetDllDir() const = 0;
+ virtual void SetDllDir(const char *inDllDir) = 0;
+ virtual Q3DStudio::THashValue HashString(const char *inStr) = 0;
+ virtual const char *ReverseHash(Q3DStudio::THashValue theValue) = 0;
+
+ virtual Q3DStudio::IRuntimeMetaData &GetMetaData() = 0;
+ // Element handles are unique across all presentations.
+ virtual Q3DStudio::TElement *GetElementByHandle(Q3DStudio::UINT32 inHandle) = 0;
+ // Passing in NULL gets you zero as the return handle.
+ virtual Q3DStudio::UINT32 GetHandleForElement(Q3DStudio::TElement *inElement) = 0;
+
+ virtual Q3DStudio::IRuntimeFactoryCore &GetRuntimeFactoryCore() = 0;
+ virtual void HideFPS(bool flag) = 0;
+
+ virtual uic::state::debugger::ISceneGraphRuntimeDebugger &GetSceneGraphDebugger() = 0;
+ virtual uic::state::debugger::IDebugger &GetStateDebugger() = 0;
+ virtual IActivityZoneManager &GetActivityZoneManager() = 0;
+ virtual IElementAllocator &GetElementAllocator() = 0;
+
+ // Debugging is disabled by default.
+ // This is expected be be called before load and will not immediately connect.
+ // until we have a valid presentation directory (which is required for the debug system
+ // at the other end of the connection).
+ // listen - either list for a connection else actively connect to a server.
+ // inServer - if listen is false, then the server addr to connect to. Ignored if server is
+ // true
+ // inPort - If listen is false, the port on server to connect to, else port to open up
+ // socket on.
+ virtual void EnableDebugging(bool inListen = false, const char8_t *inServer = NULL,
+ int inPort = 0) = 0;
+
+ // State machine is enabled by default
+ // Disable state machine is meant to disable internal statemachine, but may plug in an
+ // external statemachine
+ virtual void DisableStateMachine() = 0;
+
+ // nonblocking call to begin loading, loads uia file alone and returns.
+ virtual bool BeginLoad(const char8_t *inFilePath) = 0;
+ // blocking call to end all loading threads and such/wait till finished
+ virtual void EndLoad() = 0;
+ // Will EndLoad cause nontrivial blocking.
+ // Runs any queued runnables.
+ virtual bool HasCompletedLoading() = 0;
+
+ virtual void setAssetVisitor(uic::UICAssetVisitor *) = 0;
+
+ // will force loading to end if endLoad hasn't been called yet. Will fire off loading
+ // of resources that need to be uploaded to opengl. Maintains reference to runtime factory
+ virtual IApplication &CreateApplication(Q3DStudio::CInputEngine &inInputEngine,
+ Q3DStudio::IAudioPlayer *inAudioPlayer,
+ Q3DStudio::IRuntimeFactory &inFactory) = 0;
+
+ // maintains reference to runtime factory core. AppDir is where the executable is located;
+ // the system will expect res directory
+ // next to executable.
+ static IApplicationCore &CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
+ const char8_t *inApplicationDirectory);
+ static bool isPickingEvent(Q3DStudio::TEventCommandHash event);
+};
+
+class IApplication : public IApplicationCore
+{
+public:
+ virtual Q3DStudio::IRuntimeFactory &GetRuntimeFactory() const = 0;
+
+ virtual void SetFrameCount(Q3DStudio::INT32 inFrameCount) = 0;
+ virtual Q3DStudio::INT32 GetFrameCount() = 0;
+
+ // Allow overriding the global wall time. This way animations can be
+ // advanced at an arbitrary rate when rendering offscreen. Set to 0 to
+ // disable (the default).
+ virtual void SetTimeMilliSecs(Q3DStudio::INT64 inMilliSecs) = 0;
+
+ virtual Q3DStudio::INT64 GetTimeMilliSecs() = 0;
+ virtual void ResetTime() = 0;
+
+ // Setup during UpdateAndRender. Returns 0 for first frame.
+ virtual double GetMillisecondsSinceLastFrame() = 0;
+
+ virtual Q3DStudio::CInputEngine &GetInputEngine() = 0;
+
+ // Saves to presentationdir/binary/stem.uiab
+ // Saves all presentations and all scene data.
+ virtual void SaveBinary() = 0;
+
+ virtual Q3DStudio::CPresentation *GetPrimaryPresentation() = 0;
+
+ virtual Q3DStudio::CPresentation *GetPresentationById(const char8_t *inId) = 0;
+
+ // Update all the presentations and render them. Called exactly once per frame.
+ virtual void UpdateAndRender() = 0;
+
+ virtual bool IsApplicationDirty() = 0;
+
+ virtual void MarkApplicationDirty() = 0;
+
+ virtual Q3DStudio::IAudioPlayer &GetAudioPlayer() = 0;
+};
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Runtime/Include/UICApplicationValues.h b/src/Runtime/Source/Runtime/Include/UICApplicationValues.h
new file mode 100644
index 00000000..03914d4a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICApplicationValues.h
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#include "UICApplication.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+
+class UICAssetVisitor
+{
+public:
+ virtual void visit(const char *path) = 0;
+ virtual void visit(const char *type, const char *id, const char *src, const char *args) = 0;
+};
+
+namespace runtime {
+
+ using qt3ds::foundation::CRegisteredString;
+
+ struct AssetValueTypes
+ {
+ enum Enum {
+ NoAssetValue = 0,
+ Presentation,
+ SCXML,
+ RenderPlugin,
+ Behavior,
+ QmlPresentation,
+ };
+ };
+ struct SAssetBase
+ {
+ CRegisteredString m_Id;
+ CRegisteredString m_Src;
+ CRegisteredString m_Args;
+ SAssetBase(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inSrc = CRegisteredString(),
+ CRegisteredString inArgs = CRegisteredString())
+ : m_Id(inId)
+ , m_Src(inSrc)
+ , m_Args(inArgs)
+ {
+ }
+ bool operator==(const SAssetBase &inOther) const
+ {
+ return m_Id == inOther.m_Id && m_Src == inOther.m_Src
+ && m_Args == inOther.m_Args;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ item.Remap(m_Id);
+ item.Remap(m_Src);
+ item.Remap(m_Args);
+ }
+ virtual const char *Type() const
+ {
+ return nullptr;
+ }
+ };
+
+ struct SPresentationAsset : public SAssetBase
+ {
+ Q3DStudio::CPresentation *m_Presentation;
+ bool m_Active;
+
+ SPresentationAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(),
+ Q3DStudio::CPresentation *inPresentation = NULL)
+ : SAssetBase(inId, inRelPath, CRegisteredString())
+ , m_Presentation(inPresentation)
+ , m_Active(true)
+ {
+ }
+
+ bool operator==(const SPresentationAsset &inOther) const
+ {
+ return SAssetBase::operator==(inOther) && m_Presentation == inOther.m_Presentation
+ && m_Active == inOther.m_Active;
+ }
+
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ m_Presentation = NULL;
+ SAssetBase::Remap(item);
+ }
+ const char *Type() const override
+ {
+ return "presentation";
+ }
+ };
+
+ struct SSCXMLAsset : public SAssetBase
+ {
+ CRegisteredString m_Datamodel;
+ SSCXMLAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(),
+ CRegisteredString inDatamodel = CRegisteredString())
+ : SAssetBase(inId, inRelPath, CRegisteredString())
+ , m_Datamodel(inDatamodel)
+ {
+ }
+ bool operator==(const SSCXMLAsset &inOther) const
+ {
+ return SAssetBase::operator==(inOther) && m_Datamodel == inOther.m_Datamodel;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ SAssetBase::Remap(item);
+ item.Remap(m_Datamodel);
+ }
+ const char *Type() const override
+ {
+ return "scxml";
+ }
+ };
+
+ struct SRenderPluginAsset : public SAssetBase
+ {
+ SRenderPluginAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(),
+ CRegisteredString inArgs = CRegisteredString())
+ : SAssetBase(inId, inRelPath, inArgs)
+ {
+ }
+ const char *Type() const override
+ {
+ return "renderplugin";
+ }
+ };
+
+ struct SQmlPresentationAsset : public SAssetBase
+ {
+ SQmlPresentationAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(),
+ CRegisteredString inArgs = CRegisteredString())
+ : SAssetBase(inId, inRelPath, inArgs)
+ {
+ }
+ const char *Type() const override
+ {
+ return "presentation-qml";
+ }
+ };
+
+ struct SBehaviorAsset : public SAssetBase
+ {
+ Q3DStudio::INT32 m_Handle;
+ SBehaviorAsset(CRegisteredString inId = CRegisteredString(),
+ CRegisteredString inRelPath = CRegisteredString(),
+ Q3DStudio::INT32 inHandle = 0)
+ : SAssetBase(inId, inRelPath, CRegisteredString())
+ , m_Handle(inHandle)
+ {
+ }
+ bool operator==(const SBehaviorAsset &inOther) const
+ {
+ return SAssetBase::operator==(inOther) && m_Handle == inOther.m_Handle;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &item)
+ {
+ m_Handle = -1;
+ SAssetBase::Remap(item);
+ }
+ const char *Type() const override
+ {
+ return "behaviour";
+ }
+ };
+}
+}
+
+namespace qt3ds {
+namespace foundation {
+ template <>
+ struct DestructTraits<uic::runtime::SPresentationAsset>
+ {
+ void destruct(uic::runtime::SPresentationAsset &) {}
+ };
+ template <>
+ struct DestructTraits<uic::runtime::SSCXMLAsset>
+ {
+ void destruct(uic::runtime::SSCXMLAsset &) {}
+ };
+ template <>
+ struct DestructTraits<uic::runtime::SRenderPluginAsset>
+ {
+ void destruct(uic::runtime::SRenderPluginAsset &) {}
+ };
+ template <>
+ struct DestructTraits<uic::runtime::SBehaviorAsset>
+ {
+ void destruct(uic::runtime::SBehaviorAsset &) {}
+ };
+}
+}
+
+namespace uic {
+namespace runtime {
+
+ // Force compile error if unsupported datatype requested
+ template <typename TDataType>
+ struct SAssetValueTypeMap
+ {
+ };
+
+ template <>
+ struct SAssetValueTypeMap<SPresentationAsset>
+ {
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::Presentation; }
+ };
+ template <>
+ struct SAssetValueTypeMap<SSCXMLAsset>
+ {
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::SCXML; }
+ };
+ template <>
+ struct SAssetValueTypeMap<SRenderPluginAsset>
+ {
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::RenderPlugin; }
+ };
+ template <>
+ struct SAssetValueTypeMap<SQmlPresentationAsset>
+ {
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::QmlPresentation; }
+ };
+ template <>
+ struct SAssetValueTypeMap<SBehaviorAsset>
+ {
+ static AssetValueTypes::Enum GetType() { return AssetValueTypes::Behavior; }
+ };
+
+ struct SAssetValueUnionTraits
+ {
+ typedef AssetValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(SPresentationAsset),
+ };
+
+ static TIdType getNoDataId() { return AssetValueTypes::NoAssetValue; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SAssetValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case AssetValueTypes::Presentation:
+ return inVisitor(*NVUnionCast<SPresentationAsset *>(inData));
+ case AssetValueTypes::SCXML:
+ return inVisitor(*NVUnionCast<SSCXMLAsset *>(inData));
+ case AssetValueTypes::RenderPlugin:
+ return inVisitor(*NVUnionCast<SRenderPluginAsset *>(inData));
+ case AssetValueTypes::Behavior:
+ return inVisitor(*NVUnionCast<SBehaviorAsset *>(inData));
+ case AssetValueTypes::QmlPresentation:
+ return inVisitor(*NVUnionCast<SQmlPresentationAsset*>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case AssetValueTypes::NoAssetValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case AssetValueTypes::Presentation:
+ return inVisitor(*NVUnionCast<const SPresentationAsset *>(inData));
+ case AssetValueTypes::SCXML:
+ return inVisitor(*NVUnionCast<const SSCXMLAsset *>(inData));
+ case AssetValueTypes::RenderPlugin:
+ return inVisitor(*NVUnionCast<const SRenderPluginAsset *>(inData));
+ case AssetValueTypes::Behavior:
+ return inVisitor(*NVUnionCast<const SBehaviorAsset *>(inData));
+ case AssetValueTypes::QmlPresentation:
+ return inVisitor(*NVUnionCast<const SQmlPresentationAsset *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case AssetValueTypes::NoAssetValue:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SAssetValueUnionTraits,
+ SAssetValueUnionTraits::TBufferSize>,
+ SAssetValueUnionTraits::TBufferSize>
+ TAssetValueUnionType;
+
+ struct SAssetValue : public TAssetValueUnionType
+ {
+ SAssetValue() {}
+
+ SAssetValue(const SAssetValue &inOther)
+ : TAssetValueUnionType(static_cast<const TAssetValueUnionType &>(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SAssetValue(const TDataType &inDt)
+ : TAssetValueUnionType(inDt)
+ {
+ }
+
+ SAssetValue &operator=(const SAssetValue &inOther)
+ {
+ TAssetValueUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SAssetValue &inOther) const
+ {
+ return TAssetValueUnionType::operator==(inOther);
+ }
+ bool operator!=(const SAssetValue &inOther) const
+ {
+ return TAssetValueUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == AssetValueTypes::NoAssetValue; }
+
+ CRegisteredString GetSource()
+ {
+ if (empty())
+ return CRegisteredString();
+ return reinterpret_cast<SAssetBase *>(m_Data)->m_Src;
+ }
+ };
+}
+}
diff --git a/src/Runtime/Source/Runtime/Include/UICAttributeHashes.h b/src/Runtime/Source/Runtime/Include/UICAttributeHashes.h
new file mode 100644
index 00000000..8458f0f0
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICAttributeHashes.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AUTOGENERATED CODE
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// Run the AttributeHashes project to regenerate this file from Attributehashes.txt list
+
+/// Key for the CElement attribute-value pair
+enum EAttribute {
+ ATTRIBUTE_NAME = 0x02B79D95, // name
+ ATTRIBUTE_TYPE = 0x005F9806, // type
+ ATTRIBUTE_OPACITY = 0x0191C315, // opacity
+ ATTRIBUTE_STARTTIME = 0x010A57B1, // starttime
+ ATTRIBUTE_ENDTIME = 0x003BF5F8, // endtime
+ ATTRIBUTE_SOURCEPATH = 0x0009EA60, // sourcepath
+ ATTRIBUTE_IMPORTID = 0x008F7900, // importid
+ ATTRIBUTE_EYEBALL = 0x02F454F0, // eyeball
+ ATTRIBUTE_POSITION = 0x00E9B7D7, // position
+ ATTRIBUTE_POSITION_X = 0x027C230D, // position.x
+ ATTRIBUTE_POSITION_Y = 0x027D234C, // position.y
+ ATTRIBUTE_POSITION_Z = 0x027E238B, // position.z
+ ATTRIBUTE_ROTATION = 0x03E51862, // rotation
+ ATTRIBUTE_ROTATION_X = 0x0239EE18, // rotation.x
+ ATTRIBUTE_ROTATION_Y = 0x023AEE57, // rotation.y
+ ATTRIBUTE_ROTATION_Z = 0x023BEE96, // rotation.z
+ ATTRIBUTE_SCALE = 0x01012856, // scale
+ ATTRIBUTE_SCALE_X = 0x0065440C, // scale.x
+ ATTRIBUTE_SCALE_Y = 0x0066444B, // scale.y
+ ATTRIBUTE_SCALE_Z = 0x0067448A, // scale.z
+ ATTRIBUTE_PIVOT = 0x009E907E, // pivot
+ ATTRIBUTE_PIVOT_X = 0x03811834, // pivot.x
+ ATTRIBUTE_PIVOT_Y = 0x03821873, // pivot.y
+ ATTRIBUTE_PIVOT_Z = 0x038318B2, // pivot.z
+ ATTRIBUTE_ROTATIONORDER = 0x03CE5F70, // rotationorder
+ ATTRIBUTE_ORIENTATION = 0x001A90B0, // orientation
+ ATTRIBUTE_TESSELLATION = 0x0335861F, // tessellation
+ ATTRIBUTE_EDGETESS = 0x023933D2, // edgetess
+ ATTRIBUTE_INNERTESS = 0x01529259, // innertess
+ ATTRIBUTE_ORTHOGRAPHIC = 0x0244BB70, // orthographic
+ ATTRIBUTE_CLIPNEAR = 0x0068FF28, // clipnear
+ ATTRIBUTE_CLIPFAR = 0x037EF699, // clipfar
+ ATTRIBUTE_FOV = 0x00D60213, // fov
+ ATTRIBUTE_SCALEMODE = 0x01FD2FD3, // scalemode
+ ATTRIBUTE_SCALEANCHOR = 0x02CFCF41, // scaleanchor
+ ATTRIBUTE_BRIGHTNESS = 0x0230D3AF, // brightness
+ ATTRIBUTE_LINEARFADE = 0x0104E9FF, // linearfade
+ ATTRIBUTE_EXPFADE = 0x006B9267, // expfade
+ ATTRIBUTE_LIGHTTYPE = 0x0033F1D0, // lighttype
+ ATTRIBUTE_SCOPE = 0x0258D0CC, // scope
+ ATTRIBUTE_LIGHTDIFFUSE = 0x01246FD4, // lightdiffuse
+ ATTRIBUTE_LIGHTDIFFUSE_R = 0x035AAB10, // lightdiffuse.r
+ ATTRIBUTE_LIGHTDIFFUSE_G = 0x034FA85B, // lightdiffuse.g
+ ATTRIBUTE_LIGHTDIFFUSE_B = 0x034AA720, // lightdiffuse.b
+ ATTRIBUTE_LIGHTAMBIENT_R = 0x0179AD1A, // lightambient.r
+ ATTRIBUTE_LIGHTAMBIENT = 0x00DA56DE, // lightambient
+ ATTRIBUTE_LIGHTAMBIENT_G = 0x016EAA65, // lightambient.g
+ ATTRIBUTE_LIGHTAMBIENT_B = 0x0169A92A, // lightambient.b
+ ATTRIBUTE_LIGHTSPECULAR = 0x03E39A07, // lightspecular
+ ATTRIBUTE_LIGHTSPECULAR_R = 0x0241EBC3, // lightspecular.r
+ ATTRIBUTE_LIGHTSPECULAR_G = 0x0236E90E, // lightspecular.g
+ ATTRIBUTE_LIGHTSPECULAR_B = 0x0231E7D3, // lightspecular.b
+ ATTRIBUTE_AREAWIDTH = 0x005A8BE7, // areawidth
+ ATTRIBUTE_AREAHEIGHT = 0x00334D2C, // areaheight
+ ATTRIBUTE_CASTSHADOW = 0x0335FD81, // castshadow
+ ATTRIBUTE_SHDWBIAS = 0x0125E79F, // shdwbias
+ ATTRIBUTE_SHDWFACTOR = 0x01B11BE9, // shdwfactor
+ ATTRIBUTE_SHDWMAPRES = 0x01E53834, // shdwmapres
+ ATTRIBUTE_SHDWMAPFAR = 0x019A30FD, // shdwmapfar
+ ATTRIBUTE_SHDWFILTER = 0x0176E1E0, // shdwfilter
+ ATTRIBUTE_LIGHTMAPINDIRECT = 0x004F1D6C, // lightmapindirect
+ ATTRIBUTE_LIGHTMAPRADIOSITY = 0x00AC7C50, // lightmapradiosity
+ ATTRIBUTE_LIGHTMAPSHADOW = 0x00191F3A, // lightmapshadow
+ ATTRIBUTE_IBLPROBE = 0x0039FD03, // iblprobe
+ ATTRIBUTE_SHADERLIGHTING = 0x0068A84F, // shaderlighting
+ ATTRIBUTE_EMISSIVEPOWER = 0x03D6F9F2, // emissivepower
+ ATTRIBUTE_EMISSIVECOLOR = 0x00B7AC94, // emissivecolor
+ ATTRIBUTE_EMISSIVECOLOR_R = 0x039B87D0, // emissivecolor.r
+ ATTRIBUTE_EMISSIVECOLOR_G = 0x0390851B, // emissivecolor.g
+ ATTRIBUTE_EMISSIVECOLOR_B = 0x038B83E0, // emissivecolor.b
+ ATTRIBUTE_DIFFUSE = 0x0105521E, // diffuse
+ ATTRIBUTE_DIFFUSE_R = 0x015B085A, // diffuse.r
+ ATTRIBUTE_DIFFUSE_G = 0x015005A5, // diffuse.g
+ ATTRIBUTE_DIFFUSE_B = 0x014B046A, // diffuse.b
+ ATTRIBUTE_SPECULARMAP = 0x034CD047, // specularmap
+ ATTRIBUTE_SPECULARMODEL = 0x039EBE5A, // specularmodel
+ ATTRIBUTE_SPECULARTINT = 0x03535E02, // speculartint
+ ATTRIBUTE_SPECULARTINT_R = 0x0399623E, // speculartint.r
+ ATTRIBUTE_SPECULARTINT_G = 0x038E5F89, // speculartint.g
+ ATTRIBUTE_SPECULARTINT_B = 0x03895E4E, // speculartint.b
+ ATTRIBUTE_IOR = 0x00667354, // ior
+ ATTRIBUTE_FRESNELPOWER = 0x022178B6, // fresnelPower
+ ATTRIBUTE_SPECULARAMOUNT = 0x01144425, // specularamount
+ ATTRIBUTE_SPECULARROUGHNESS = 0x03925653, // specularroughness
+ ATTRIBUTE_BLENDMODE = 0x01923A6C, // blendmode
+ ATTRIBUTE_CULLING = 0x03C539F0, // culling
+ ATTRIBUTE_ZBUFFERWRITE = 0x03E19B3B, // zbufferwrite
+ ATTRIBUTE_DIFFUSEMAP = 0x00FF8126, // diffusemap
+ ATTRIBUTE_DIFFUSEMAP2 = 0x0038D4A8, // diffusemap2
+ ATTRIBUTE_DIFFUSEMAP3 = 0x0039D4E7, // diffusemap3
+ ATTRIBUTE_SPECULARREFLECTION = 0x006B4C12, // specularreflection
+ ATTRIBUTE_OPACITYMAP = 0x00DA796F, // opacitymap
+ ATTRIBUTE_EMISSIVEMAP = 0x00F6427B, // emissivemap
+ ATTRIBUTE_EMISSIVEMAP2 = 0x03476893, // emissivemap2
+ ATTRIBUTE_BUMPMAP = 0x024EE11A, // bumpmap
+ ATTRIBUTE_BUMPAMOUNT = 0x01BC4192, // bumpamount
+ ATTRIBUTE_NORMALMAP = 0x03BD578B, // normalmap
+ ATTRIBUTE_DISPLACEMENTMAP = 0x01BCD1FB, // displacementmap
+ ATTRIBUTE_DISPLACEAMOUNT = 0x01EC1EAF, // displaceamount
+ ATTRIBUTE_TRANSLUCENCYMAP = 0x01D8F015, // translucencymap
+ ATTRIBUTE_TRANSLUCENTFALLOFF = 0x0097E985, // translucentfalloff
+ ATTRIBUTE_DIFFUSELIGHTWRAP = 0x038F6522, // diffuselightwrap
+ ATTRIBUTE_REFERENCEDMATERIAL = 0x035FDA80, // referencedmaterial
+ ATTRIBUTE_ROTATIONUV = 0x012E3A61, // rotationuv
+ ATTRIBUTE_POSITIONU = 0x01D05AB4, // positionu
+ ATTRIBUTE_POSITIONV = 0x01D15AF3, // positionv
+ ATTRIBUTE_SCALEU = 0x001409F5, // scaleu
+ ATTRIBUTE_SCALEV = 0x00150A34, // scalev
+ ATTRIBUTE_PIVOTU = 0x03F8ABCD, // pivotu
+ ATTRIBUTE_PIVOTV = 0x03F9AC0C, // pivotv
+ ATTRIBUTE_TILINGMODEHORZ = 0x02562203, // tilingmodehorz
+ ATTRIBUTE_TILINGMODEVERT = 0x03F92B21, // tilingmodevert
+ ATTRIBUTE_MAPPINGTYPE = 0x02CA9058, // mappingtype
+ ATTRIBUTE_MAPPINGMODE = 0x002715CF, // mappingmode
+ ATTRIBUTE_SUBPRESENTATION = 0x03CA7426, // subpresentation
+ ATTRIBUTE_URI = 0x00296894, // uri
+ ATTRIBUTE_TRANSPARENT = 0x0316BA2E, // transparent
+ ATTRIBUTE_PROGRESSIVEAA = 0x019F1955, // progressiveaa
+ ATTRIBUTE_MULTISAMPLEAA = 0x013D29FD, // multisampleaa
+ ATTRIBUTE_TEMPORALAA = 0x00212AFE, // temporalaa
+ ATTRIBUTE_BLENDTYPE = 0x0035B4F5, // blendtype
+ ATTRIBUTE_HORZFIELDS = 0x02B8A818, // horzfields
+ ATTRIBUTE_LEFT = 0x0196B9B9, // left
+ ATTRIBUTE_LEFTUNITS = 0x02F9D2D8, // leftunits
+ ATTRIBUTE_WIDTH = 0x00C4D65A, // width
+ ATTRIBUTE_WIDTHUNITS = 0x01D7DF77, // widthunits
+ ATTRIBUTE_RIGHT = 0x039EAB44, // right
+ ATTRIBUTE_RIGHTUNITS = 0x0357EF0D, // rightunits
+ ATTRIBUTE_VERTFIELDS = 0x03462436, // vertfields
+ ATTRIBUTE_TOP = 0x002F6B0B, // top
+ ATTRIBUTE_TOPUNITS = 0x03D58806, // topunits
+ ATTRIBUTE_HEIGHT = 0x00CE9F79, // height
+ ATTRIBUTE_HEIGHTUNITS = 0x00C91D18, // heightunits
+ ATTRIBUTE_BOTTOM = 0x00F4EE75, // bottom
+ ATTRIBUTE_BOTTOMUNITS = 0x0174091C, // bottomunits
+ ATTRIBUTE_AOSTRENGTH = 0x010F7ED1, // aostrength
+ ATTRIBUTE_AODISTANCE = 0x01DC349D, // aodistance
+ ATTRIBUTE_AOSOFTNESS = 0x02CCDC71, // aosoftness
+ ATTRIBUTE_AOBIAS = 0x01818219, // aobias
+ ATTRIBUTE_AOSAMPLERATE = 0x0039B568, // aosamplerate
+ ATTRIBUTE_AODITHER = 0x0274316C, // aodither
+ ATTRIBUTE_SHADOWSTRENGTH = 0x0039ED5F, // shadowstrength
+ ATTRIBUTE_SHADOWDIST = 0x038213FA, // shadowdist
+ ATTRIBUTE_SHADOWSOFTNESS = 0x01F74AFF, // shadowsoftness
+ ATTRIBUTE_SHADOWBIAS = 0x02CB3EA7, // shadowbias
+ ATTRIBUTE_LIGHTPROBE = 0x02D47DC6, // lightprobe
+ ATTRIBUTE_PROBEBRIGHT = 0x029DC5B6, // probebright
+ ATTRIBUTE_FASTIBL = 0x02559509, // fastibl
+ ATTRIBUTE_PROBEHORIZON = 0x014DAAF5, // probehorizon
+ ATTRIBUTE_PROBEFOV = 0x03D66903, // probefov
+ ATTRIBUTE_LIGHTPROBE2 = 0x00430008, // lightprobe2
+ ATTRIBUTE_PROBE2FADE = 0x02ED0742, // probe2fade
+ ATTRIBUTE_PROBE2WINDOW = 0x016B224E, // probe2window
+ ATTRIBUTE_PROBE2POS = 0x024B0C0E, // probe2pos
+ ATTRIBUTE_DISABLEDEPTHTEST = 0x000B8353, // disabledepthtest
+ ATTRIBUTE_DISABLEDEPTHPREPASS = 0x02AE1EA7, // disabledepthprepass
+ ATTRIBUTE_TEXTCOLOR = 0x02D9114A, // textcolor
+ ATTRIBUTE_TEXTCOLOR_R = 0x00E9F186, // textcolor.r
+ ATTRIBUTE_TEXTCOLOR_G = 0x00DEEED1, // textcolor.g
+ ATTRIBUTE_TEXTCOLOR_B = 0x00D9ED96, // textcolor.b
+ ATTRIBUTE_SIZE = 0x00F2C81F, // size
+ ATTRIBUTE_FONT = 0x03412331, // font
+ ATTRIBUTE_TRACKING = 0x02A25049, // tracking
+ ATTRIBUTE_LEADING = 0x016A6BDA, // leading
+ ATTRIBUTE_RENDERSTYLE = 0x03567B85, // renderstyle
+ ATTRIBUTE_TEXTSTRING = 0x01124062, // textstring
+ ATTRIBUTE_BACKCOLOR_R = 0x0290CCE0, // backcolor.r
+ ATTRIBUTE_BACKCOLOR_G = 0x0285CA2B, // backcolor.g
+ ATTRIBUTE_BACKCOLOR_B = 0x0280C8F0, // backcolor.b
+ ATTRIBUTE_TEXTTYPE = 0x0240ADD9, // texttype
+ ATTRIBUTE_USEBACKCOLOR = 0x0243BACB, // usebackcolor
+ ATTRIBUTE_WORDWRAP = 0x0134B04C, // wordwrap
+ ATTRIBUTE_HORZSCROLL = 0x005B3CC4, // horzscroll
+ ATTRIBUTE_HORZALIGN = 0x00BA002A, // horzalign
+ ATTRIBUTE_VERTSCROLL = 0x00E8B8E2, // vertscroll
+ ATTRIBUTE_VERTALIGN = 0x03759C8C, // vertalign
+ ATTRIBUTE_BOXHEIGHT = 0x0079AF8E, // boxheight
+ ATTRIBUTE_BOXWIDTH = 0x016B7105, // boxwidth
+ ATTRIBUTE_REMOTESTRINGSOURCE = 0x025DFEEE, // remotestringsource
+ ATTRIBUTE_CACHEDTEXTSTRING = 0x0095DBA0, // cachedtextstring
+ ATTRIBUTE_ENABLEACCELERATEDFONT = 0x0053A92D, // enableacceleratedfont
+ ATTRIBUTE_BEHAVIORSCRIPTS = 0x01DF916A, // BehaviorScripts
+ ATTRIBUTE_UICCUSTOMOBJTYPE = 0x029F1BCF, // UICCustomObjType
+ ATTRIBUTE_BGCOLORENABLE = 0x0021EE1F, // bgcolorenable
+ ATTRIBUTE_BACKGROUND = 0x006AA932, // background
+ ATTRIBUTE_BACKGROUNDCOLOR_R = 0x02AF0767, // backgroundcolor.r
+ ATTRIBUTE_BACKGROUNDCOLOR_G = 0x02A404B2, // backgroundcolor.g
+ ATTRIBUTE_BACKGROUNDCOLOR_B = 0x029F0377, // backgroundcolor.b
+ ATTRIBUTE_PATHTYPE = 0x02D2A5E1, // pathtype
+ ATTRIBUTE_LINEARERROR = 0x0378A51D, // linearerror
+ ATTRIBUTE_EDGETESSAMOUNT = 0x02577E3A, // edgetessamount
+ ATTRIBUTE_INNERTESSAMOUNT = 0x0027A241, // innertessamount
+ ATTRIBUTE_BEGINCAP = 0x03373D37, // begincap
+ ATTRIBUTE_BEGINCAPOFFSET = 0x01FEFE64, // begincapoffset
+ ATTRIBUTE_BEGINCAPOPACITY = 0x02C2761E, // begincapopacity
+ ATTRIBUTE_BEGINCAPWIDTH = 0x0102BDE3, // begincapwidth
+ ATTRIBUTE_ENDCAP = 0x00ADB3A9, // endcap
+ ATTRIBUTE_ENDCAPOFFSET = 0x0382A9D6, // endcapoffset
+ ATTRIBUTE_ENDCAPOPACITY = 0x019BA72C, // endcapopacity
+ ATTRIBUTE_ENDCAPWIDTH = 0x03A315F1, // endcapwidth
+ ATTRIBUTE_PAINTSTYLE = 0x03ADEC8D, // paintstyle
+ ATTRIBUTE_CLOSED = 0x01807034, // closed
+ ATTRIBUTE_INCOMINGANGLE = 0x03890AB3, // incomingangle
+ ATTRIBUTE_INCOMINGDISTANCE = 0x005EB2A5, // incomingdistance
+ ATTRIBUTE_OUTGOINGDISTANCE = 0x017C597F, // outgoingdistance
+ ATTRIBUTE_PARTICLETYPE = 0x01C01260, // particletype
+ ATTRIBUTE_MAXPARTICLES = 0x00BE66B7, // maxparticles
+ ATTRIBUTE_PARTICLESIZE = 0x02534279, // particlesize
+ ATTRIBUTE_LIFETIME = 0x0033D297, // lifetime
+ ATTRIBUTE_QT_IO = 0x01F29712, // qt.io
+}; // enum EAttribute
+
+#define AK_STRING_QT_IO "qt.io"
+
+/// Function providing reverse hash lookup
+const char *GetAttributeString(const EAttribute inAttribute);
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICAttributeHashes.txt b/src/Runtime/Source/Runtime/Include/UICAttributeHashes.txt
new file mode 100644
index 00000000..a50f2211
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICAttributeHashes.txt
@@ -0,0 +1,226 @@
+name
+type
+opacity
+
+starttime
+endtime
+
+sourcepath
+importid
+eyeball
+position
+position.x
+position.y
+position.z
+rotation
+rotation.x
+rotation.y
+rotation.z
+scale
+scale.x
+scale.y
+scale.z
+pivot
+pivot.x
+pivot.y
+pivot.z
+rotationorder
+orientation
+tessellation
+edgetess
+innertess
+
+orthographic
+clipnear
+clipfar
+fov
+scalemode
+scaleanchor
+
+brightness
+linearfade
+expfade
+lighttype
+scope
+lightdiffuse
+lightdiffuse.r
+lightdiffuse.g
+lightdiffuse.b
+lightambient.r
+lightambient
+lightambient.g
+lightambient.b
+lightspecular
+lightspecular.r
+lightspecular.g
+lightspecular.b
+areawidth
+areaheight
+castshadow
+shdwbias
+shdwfactor
+shdwmapres
+shdwmapfar
+shdwfilter
+
+lightmapindirect
+lightmapradiosity
+lightmapshadow
+
+iblprobe
+
+shaderlighting
+emissivepower
+emissivecolor
+emissivecolor.r
+emissivecolor.g
+emissivecolor.b
+diffuse
+diffuse.r
+diffuse.g
+diffuse.b
+specularmap
+specularmodel
+speculartint
+speculartint.r
+speculartint.g
+speculartint.b
+ior
+fresnelPower
+specularamount
+specularroughness
+blendmode
+culling
+zbufferwrite
+diffusemap
+diffusemap2
+diffusemap3
+specularreflection
+opacitymap
+emissivemap
+emissivemap2
+bumpmap
+bumpamount
+normalmap
+displacementmap
+displaceamount
+translucencymap
+translucentfalloff
+diffuselightwrap
+referencedmaterial
+
+rotationuv
+positionu
+positionv
+scaleu
+scalev
+pivotu
+pivotv
+tilingmodehorz
+tilingmodevert
+mappingtype
+mappingmode
+subpresentation
+uri
+
+transparent
+progressiveaa
+multisampleaa
+temporalaa
+blendtype
+horzfields
+left
+leftunits
+width
+widthunits
+right
+rightunits
+vertfields
+top
+topunits
+height
+heightunits
+bottom
+bottomunits
+aostrength
+aodistance
+aosoftness
+aobias
+aosamplerate
+aodither
+shadowstrength
+shadowdist
+shadowsoftness
+shadowbias
+lightprobe
+probebright
+fastibl
+probehorizon
+probefov
+lightprobe2
+probe2fade
+probe2window
+probe2pos
+disabledepthtest
+disabledepthprepass
+
+textcolor
+textcolor.r
+textcolor.g
+textcolor.b
+size
+font
+tracking
+leading
+renderstyle
+textstring
+backcolor.r
+backcolor.g
+backcolor.b
+texttype
+usebackcolor
+wordwrap
+horzscroll
+horzalign
+vertscroll
+vertalign
+boxheight
+boxwidth
+remotestringsource
+cachedtextstring
+enableacceleratedfont
+
+BehaviorScripts
+UICCustomObjType
+
+bgcolorenable
+background
+backgroundcolor.r
+backgroundcolor.g
+backgroundcolor.b
+
+pathtype
+linearerror
+edgetessamount
+innertessamount
+begincap
+begincapoffset
+begincapopacity
+begincapwidth
+endcap
+endcapoffset
+endcapopacity
+endcapwidth
+paintstyle
+closed
+
+incomingangle
+incomingdistance
+outgoingdistance
+
+particletype
+maxparticles
+particlesize
+lifetime
+
+
diff --git a/src/Runtime/Source/Runtime/Include/UICBinarySerializationHelper.h b/src/Runtime/Source/Runtime/Include/UICBinarySerializationHelper.h
new file mode 100644
index 00000000..5cf63b41
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICBinarySerializationHelper.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UIC_BINARY_SERIALIZATION_HELPER_H
+#define UIC_BINARY_SERIALIZATION_HELPER_H
+#pragma once
+#include "foundation/Qt3DSIndexableLinkedList.h"
+#include "foundation/SerializationTypes.h"
+
+namespace uic {
+namespace runtime {
+
+ template <typename TListType, typename TNodeType>
+ inline void SaveIndexableList(TNodeType *inFirstNode, SWriteBuffer &ioBuffer)
+ {
+ for (typename TListType::node_iterator iter = TListType::node_begin(inFirstNode),
+ end_iter = TListType::node_end(inFirstNode);
+ iter != end_iter; ++iter) {
+ ioBuffer.write(*iter);
+ }
+ }
+
+ template <typename TListType, typename TNodeType>
+ inline void LoadIndexableList(TNodeType *&ioFirstNode, QT3DSU32 inItemCount, SDataReader &ioReader)
+ {
+ ioFirstNode = NULL;
+ TNodeType *lastNode = NULL;
+ for (typename TListType::count_iterator iter = TListType::count_begin(inItemCount),
+ end_iter = TListType::count_end(inItemCount);
+ iter != end_iter; ++iter) {
+ TNodeType *theNode = ioReader.Load<TNodeType>();
+ if (lastNode == NULL)
+ ioFirstNode = theNode;
+ else
+ lastNode->m_NextNode = theNode;
+ lastNode = theNode;
+ }
+ if (lastNode != NULL)
+ lastNode->m_NextNode = NULL;
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Runtime/Include/UICBinarySerializer.h b/src/Runtime/Source/Runtime/Include/UICBinarySerializer.h
new file mode 100644
index 00000000..d999aa26
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICBinarySerializer.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace foundation {
+ class IPerfTimer;
+ class Mutex;
+}
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+using namespace qt3ds::foundation;
+class CPresentation;
+class CFlow;
+
+//==============================================================================
+/**
+ * Binary load / save
+ */
+class IBinarySerializer : public NVReleasable
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ // Binary save is taken care of duruing the saving of the flow assets. Binary load,
+ // however, can happen in a deferred fasion and so needs to be exported.
+ virtual BOOL BinaryLoad(CPresentation *inPresentation, size_t inElementMemoryOffset,
+ qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> inData,
+ qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> inStringTableData,
+ qt3ds::foundation::IPerfTimer &inPerfTimer) = 0;
+ virtual void BinarySave(CPresentation *inPresentation) = 0;
+
+public: // Creation function
+ static IBinarySerializer &Create();
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICBinarySerializerImpl.h b/src/Runtime/Source/Runtime/Include/UICBinarySerializerImpl.h
new file mode 100644
index 00000000..12ee50be
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICBinarySerializerImpl.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICBinarySerializer.h"
+#include "foundation/Qt3DSFoundation.h"
+
+namespace uic {
+namespace runtime {
+ class IAnimationSystem;
+ class ISlideSystem;
+ class ILogicSystem;
+ class IParametersSystem;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+class CElementBuilder;
+class CAnimationBuilder;
+class CParametersBuilder;
+class CSlideBuilder;
+class CFileStream;
+
+//==============================================================================
+/**
+ * Binary load / save
+ */
+class CBinarySerializer : public IBinarySerializer
+{
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CBinarySerializer();
+ ~CBinarySerializer();
+
+public: // Binary save / load
+ void BinarySave(CPresentation *inPresentation) override;
+ BOOL BinaryLoad(CPresentation *inPresentation, size_t inElementMemoryOffset,
+ qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> inPresData,
+ qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> inStringTableData,
+ qt3ds::foundation::IPerfTimer &inPerfTimer) override;
+
+public: //
+ void release() override { delete this; }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICCommandEventTypes.h b/src/Runtime/Source/Runtime/Include/UICCommandEventTypes.h
new file mode 100644
index 00000000..514a8430
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICCommandEventTypes.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICHash.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Commands
+//==============================================================================
+
+// Command types are 31-bit hash instead of 32-bit
+// The 1 bit flag is being used to differentiate between a Command and an Event
+// Commands trigger execution, both commands and events can trigger logic
+
+// Asset
+const TEventCommandHash COMMAND_SETPROPERTY = CHash::HashEventCommand("COMMAND_SETPROPERTY");
+const TEventCommandHash COMMAND_FIREEVENT = CHash::HashEventCommand("COMMAND_FIREEVENT");
+const TEventCommandHash COMMAND_SCRIPTLET = CHash::HashEventCommand("COMMAND_SCRIPTLET");
+const TEventCommandHash COMMAND_PLAYSOUND = CHash::HashEventCommand("COMMAND_PLAYSOUND");
+const TEventCommandHash COMMAND_EMITSIGNAL = CHash::HashEventCommand("COMMAND_EMITSIGNAL");
+
+// Time
+const TEventCommandHash COMMAND_PLAY = CHash::HashEventCommand("COMMAND_PLAY");
+const TEventCommandHash COMMAND_PAUSE = CHash::HashEventCommand("COMMAND_PAUSE");
+const TEventCommandHash COMMAND_GOTOTIME = CHash::HashEventCommand("COMMAND_GOTOTIME");
+const TEventCommandHash COMMAND_GOTOTIMELABEL = CHash::HashEventCommand("COMMAND_GOTOTIMELABEL");
+
+// Slide
+const TEventCommandHash COMMAND_GOTOSLIDE = CHash::HashEventCommand("COMMAND_GOTOSLIDE");
+const TEventCommandHash COMMAND_GOTOSLIDENAME = CHash::HashEventCommand("COMMAND_GOTOSLIDENAME");
+const TEventCommandHash COMMAND_GOTONEXTSLIDE = CHash::HashEventCommand("COMMAND_GOTONEXTSLIDE");
+const TEventCommandHash COMMAND_GOTOPREVIOUSSLIDE =
+ CHash::HashEventCommand("COMMAND_GOTOPREVIOUSSLIDE");
+const TEventCommandHash COMMAND_BACKSLIDE = CHash::HashEventCommand("COMMAND_BACKSLIDE");
+
+// Behavior
+const TEventCommandHash COMMAND_CUSTOMACTION = CHash::HashEventCommand("COMMAND_CUSTOMACTION");
+const TEventCommandHash COMMAND_CUSTOMCALLBACK = CHash::HashEventCommand("COMMAND_CALLBACK");
+//==============================================================================
+// Events
+//==============================================================================
+
+// Slide Events
+const TEventCommandHash EVENT_ONSLIDEENTER = CHash::HashEventCommand("onSlideEnter");
+const TEventCommandHash EVENT_ONSLIDEEXIT = CHash::HashEventCommand("onSlideExit");
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICComponentManager.h b/src/Runtime/Source/Runtime/Include/UICComponentManager.h
new file mode 100644
index 00000000..b78be6d7
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICComponentManager.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICIComponentManager.h"
+#include "EASTL/hash_map.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+class CTimePolicy;
+class CPresentation;
+struct SComponentTimePolicyOverride
+{
+ TElement *m_Element;
+ FLOAT m_TimeMultiplier;
+ TTimeUnit m_EndTime;
+ IComponentTimeOverrideFinishedCallback *m_TimeCallback;
+ SComponentTimePolicyOverride(TElement *inElement, FLOAT inMultiplier, TTimeUnit inEndTime,
+ IComponentTimeOverrideFinishedCallback *inCallback)
+ : m_Element(inElement)
+ , m_TimeMultiplier(inMultiplier)
+ , m_EndTime(inEndTime)
+ , m_TimeCallback(inCallback)
+ {
+ }
+ // Returns the local time and a boolean indicating if we have reached the end.
+ // Implemented in UICTimePolicy.cpp so that I can compare the CTimePolicy::ComputeTime method
+ // with
+ // SComponentTimePolicyOverride::ComputLocalTime method
+ eastl::pair<BOOL, TTimeUnit> ComputeLocalTime(CTimePolicy &inTimePolicy,
+ TTimeUnit inGlobalTime);
+ // Implemented in UICTimePolicy.cpp
+ void SetTime(CTimePolicy &inTimePolicy, TTimeUnit inLocalTime);
+};
+
+typedef eastl::hash_map<TElement *, SComponentGotoSlideData> TComponentGotoSlideDataMap;
+typedef eastl::hash_map<TElement *, Q3DStudio::INT32> TComponentIntMap;
+
+//==============================================================================
+/**
+ * The Component Manager is a factory and container of all components
+ * within the presentation.
+ */
+class CComponentManager : public IComponentManager
+{
+ CPresentation &m_Presentation;
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CComponentManager(IPresentation &inPresentation);
+
+public: // Slide
+ void GotoSlideIndex(TElement *inComponent, const SComponentGotoSlideData &inGotoData,
+ BOOL inSlideExit = true) override;
+ void GotoSlideName(TElement *inComponent, const TStringHash inSlideHashName) override;
+ void GoToBackSlide(TElement *inComponent) override;
+ void GoToNextSlide(TElement *inComponent, const INT32 inDecrement = 1) override;
+ void GoToPreviousSlide(TElement *inComponent, const INT32 inDecrement = 1) override;
+ void PlaythroughToSlide(TElement *inComponent);
+
+ UINT8 GetSlideCount(TElement *inComponent) override;
+ UINT8 GetCurrentSlide(TElement *inComponent) override;
+ const CHAR *GetCurrentSlideName(TElement *inComponent) override;
+
+ void OnElementDeactivated(TElement *inElement) override;
+
+ void SetComponentTimeOverride(TElement *inElement, TTimeUnit inEndTime, FLOAT inInterpolation,
+ IComponentTimeOverrideFinishedCallback *inCallback) override;
+
+ // Allows multiple gotoslide command operating on the same element to work correctly.
+ // This API is meant to fix a scenario where gotoslide is called multiple times in a frame
+ // on the same component. This isn't avoidable in some cases without very complex scene logic.
+
+ // later calls override earlier calls
+ void SetupComponentGotoSlideCommand(TElement *inElement,
+ const SComponentGotoSlideData &inSlide) override;
+ bool HasComponentGotoSlideCommand(TElement *inElement) override;
+ SComponentGotoSlideData GetComponentGotoSlideCommand(TElement *inElement) override;
+ void ReleaseComponentGotoSlideCommand(TElement *inElement) override;
+
+public: // Time
+ void GoToTime(TElement *inComponent, const TTimeUnit inTime) override;
+ void SetPause(TElement *inComponent, const BOOL inPause) override;
+ void SetTimePolicy(TElement *inComponent, const TTimeUnit inLoopDuration,
+ const UINT32 inRepetitions, const BOOL inPingPong, const BOOL inPlayThrough) override;
+
+ TTimeUnit ComputeComponentLocalTime(TElement *inComponent, const TTimeUnit inGlobalTime);
+ BOOL GetPause(TElement *inComponent) override;
+ BOOL GetPlayBackDirection(TElement *inComponent) override;
+
+protected: // Promotion
+ TComponent *GetComponent(TElement *inElement) override;
+
+private:
+ // Disabled Copy Construction
+ CComponentManager(const CComponentManager &);
+ CComponentManager &operator=(const CComponentManager &);
+
+ TComponentGotoSlideDataMap m_ComponentInitialSlideMap;
+ TComponentGotoSlideDataMap m_ComponentGotoSlideMap;
+ TComponentIntMap m_PlaythroughOverrideMap;
+
+ //==============================================================================
+ // Friends
+ //==============================================================================
+ friend class CSlideBuilder;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICElementSystem.h b/src/Runtime/Source/Runtime/Include/UICElementSystem.h
new file mode 100644
index 00000000..a46d70e5
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICElementSystem.h
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef UIC_ELEMENT_SYSTEM_H
+#define UIC_ELEMENT_SYSTEM_H
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Utils.h"
+#include "foundation/StringTable.h"
+#include "UICKernelTypes.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSInvasiveSet.h"
+#include "UICMetadata.h"
+
+// The uic runtime element system contains the element graph and the data in the element
+// graph.
+
+namespace Q3DStudio {
+// class CPresentation;
+class IPresentation;
+class CTimePolicy;
+}
+
+namespace qt3ds {
+namespace foundation {
+ class IInStream;
+ class IOutStream;
+}
+}
+
+namespace uic {
+namespace runtime {
+ using namespace qt3ds::foundation;
+ using namespace qt3ds;
+ class IActivityZone;
+ namespace element {
+ struct SPropertyDesc
+ {
+ CRegisteredString m_Name;
+ Q3DStudio::EAttributeType m_Type;
+ SPropertyDesc()
+ : m_Type(Q3DStudio::ATTRIBUTETYPE_NONE)
+ {
+ }
+ SPropertyDesc(CRegisteredString inStr, Q3DStudio::EAttributeType inType)
+ : m_Name(inStr)
+ , m_Type(inType)
+ {
+ }
+ QT3DSU32 GetNameHash() const; // CHash::HashAttribute
+ Q3DStudio::SAttributeKey GetAttributeKey() const;
+ };
+
+ struct STypeDesc
+ {
+ CRegisteredString m_TypeName;
+ CRegisteredString m_SubtypeName;
+ // Properties are sorted so that we can quickly create new type descriptions
+ // when necessary.
+ NVConstDataRef<SPropertyDesc> m_Properties;
+ eastl::vector<SPropertyDesc> m_DynamicProperties;
+
+ private:
+ QT3DSU32 m_HashValue; // Cached hash value for this type descriptor
+ public:
+ STypeDesc()
+ : m_HashValue(0)
+ {
+ }
+ bool operator==(const STypeDesc &inOther) const;
+ // Q3DStudio::CHash::HashAttribute
+ Option<QT3DSU32> FindProperty(QT3DSU32 inNameHash) const;
+ Option<QT3DSU32> FindProperty(CRegisteredString inName) const;
+ Option<QT3DSU32> FindDynamicProperty(QT3DSU32 inNameHash) const;
+ void SetHashValue();
+ QT3DSU32 HashCode() const { return m_HashValue; }
+ };
+
+ struct SActivationManagerNodeFlagValues
+ {
+ enum Enum {
+ TimeActive = 1 << 1,
+ TempTimeActive = 1 << 4,
+ ParticipatesInTimeGraph = 1 << 5,
+ Script = 1 << 6,
+ ChildDirty = 1 << 7,
+ };
+ };
+
+ struct SActivationManagerNodeFlags : public NVFlags<SActivationManagerNodeFlagValues::Enum>
+ {
+ bool IsTimeActive() const
+ {
+ return operator&(SActivationManagerNodeFlagValues::TimeActive);
+ }
+ void SetTimeActive(bool active)
+ {
+ clearOrSet(active, SActivationManagerNodeFlagValues::TimeActive);
+ }
+
+ bool IsTempTimeActive() const
+ {
+ return operator&(SActivationManagerNodeFlagValues::TempTimeActive);
+ }
+ void SetTempTimeActive(bool value)
+ {
+ clearOrSet(value, SActivationManagerNodeFlagValues::TempTimeActive);
+ }
+
+ // Is this item in the activation manager's scripts list.
+ bool HasScript() const { return operator&(SActivationManagerNodeFlagValues::Script); }
+ void SetHasScript(bool value)
+ {
+ clearOrSet(value, SActivationManagerNodeFlagValues::Script);
+ }
+
+ bool IsChildDirty() const
+ {
+ return operator&(SActivationManagerNodeFlagValues::ChildDirty);
+ }
+ void SetChildDirty() { clearOrSet(true, SActivationManagerNodeFlagValues::ChildDirty); }
+ void ClearChildDirty()
+ {
+ clearOrSet(false, SActivationManagerNodeFlagValues::ChildDirty);
+ }
+ };
+
+ struct SElement;
+
+ struct SActivationManagerNode
+ {
+ // IT may seem wasteful to always have start,end time on the node. We need to do this
+ // however
+ // in order to transmit information down the timeline at times. Furthermore the
+ // activation manager
+ // is free to mangle these times as it sees fit; unlike the attribute start,end time.
+ QT3DSU32 m_StartTime;
+ QT3DSU32 m_StopTime;
+ // Used by the activation manager specifically.
+ QT3DSU32 m_DirtyIndex;
+
+ // If m_Flags.IsIndependent(), first child is implicitly zero and instead
+ // this records the time context index assocated with this element node.
+ // Else this records the first child index.
+ // These could perhaps be moved to the element flags except it breaks some isolation and
+ // it just doesn't seem worth it.
+ SActivationManagerNodeFlags m_Flags;
+
+ SActivationManagerNode()
+ : m_StartTime(QT3DS_MAX_U32)
+ , m_StopTime(QT3DS_MAX_U32)
+ , m_DirtyIndex(QT3DS_MAX_U32)
+ {
+ }
+ };
+
+ struct SElementFlag : public NVFlags<Q3DStudio::EElementFlag, QT3DSU16>
+ {
+ void SetDirty(bool inDirty) { clearOrSet(inDirty, Q3DStudio::ELEMENTFLAG_DIRTY); }
+ bool IsDirty() const { return this->operator&(Q3DStudio::ELEMENTFLAG_DIRTY); }
+
+ bool IsComponent() const { return this->operator&(Q3DStudio::ELEMENTFLAG_COMPONENT); }
+
+ void SetExplicitActive(bool inValue)
+ {
+ clearOrSet(inValue, Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE);
+ }
+ bool IsExplicitActive() const
+ {
+ return this->operator&(Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE);
+ }
+
+ void SetActive(bool inValue)
+ {
+ clearOrSet(inValue, Q3DStudio::ELEMENTFLAG_GLOBALACTIVE);
+ }
+ bool IsActive() const { return this->operator&(Q3DStudio::ELEMENTFLAG_GLOBALACTIVE); }
+
+ void SetPickEnabled(bool inValue)
+ {
+ clearOrSet(inValue, Q3DStudio::ELEMENTFLAG_PICKENABLED);
+ }
+ bool IsPickEnabled() const
+ {
+ return this->operator&(Q3DStudio::ELEMENTFLAG_PICKENABLED);
+ }
+
+ void SetPlayThrough(bool inValue)
+ {
+ clearOrSet(inValue, Q3DStudio::ELEMENTFLAG_PLAYTHROUGH);
+ }
+ bool IsPlayThrough() const
+ {
+ return this->operator&(Q3DStudio::ELEMENTFLAG_PLAYTHROUGH);
+ }
+
+ void SetScriptCallbacks(bool inValue)
+ {
+ clearOrSet(inValue, Q3DStudio::ELEMENTFLAG_SCRIPTCALLBACKS);
+ }
+ bool HasScriptCallbacks() const
+ {
+ return this->operator&(Q3DStudio::ELEMENTFLAG_SCRIPTCALLBACKS);
+ }
+
+ bool HasStartEndTime() const
+ {
+ return this->operator&(Q3DStudio::ELEMENTFLAG_TIMELINE);
+ }
+ };
+
+ typedef eastl::pair<SPropertyDesc, Q3DStudio::UVariant *> TPropertyDescAndValuePtr;
+ typedef eastl::pair<SPropertyDesc, const Q3DStudio::UVariant *>
+ TPropertyDescAndConstValuePtr;
+ typedef eastl::pair<SPropertyDesc, Q3DStudio::UVariant> TPropertyDescAndValue;
+ // There is probably some balance here between number of values in a group
+ // and number of groups. A heuristic of a large application would tell you
+ // the optimum number of values to groups.
+ struct SPropertyValueGroup
+ {
+ enum {
+ NumValues = 4,
+ };
+ Q3DStudio::UVariant m_Data[4];
+ SPropertyValueGroup *m_NextNode;
+ SPropertyValueGroup()
+ : m_NextNode(NULL)
+ {
+ for (QT3DSU32 idx = 0; idx < NumValues; ++idx)
+ m_Data[idx].m_INT32 = 0;
+ }
+ };
+
+ struct SElement
+ {
+ CRegisteredString m_Name; // const, do not set after creation.
+ CRegisteredString m_Path;
+ const STypeDesc *m_TypeDescription; ///< static information created on load time
+ // The property values are in order described in the type description.
+ SPropertyValueGroup *m_PropertyValues;
+ // dynamic section
+ STypeDesc *m_DynamicTypeDescription; ///< we may create this on the fly
+ SPropertyValueGroup *m_DynamicPropertyValues;
+
+ protected:
+ SElementFlag m_Flags; // Setting these changes things.
+ public:
+ QT3DSU32 m_Handle;
+ QT3DSU32 m_ScriptID; ///< Superfluous, could use handle to link to script representation
+ QT3DSU32 m_Depth; ///< Distance from this node to the root of the graph.
+ SElement *m_Parent; ///< Parent element in activity graph
+ SElement *m_Sibling; ///< Next sibling element in activity graph
+ SElement *m_Child; ///< First child element in activity graph
+ void *m_Association; ///< Link to associated asset in scene
+ Q3DStudio::IPresentation *m_BelongedPresentation;
+ SActivationManagerNode m_ActivationManagerNode;
+
+ SElement(const STypeDesc &inDesc)
+ : m_TypeDescription(&inDesc)
+ , m_PropertyValues(NULL)
+ , m_DynamicTypeDescription(NULL)
+ , m_DynamicPropertyValues(NULL)
+ , m_Handle(0)
+ , m_ScriptID(0)
+ , m_Depth(0)
+ , m_Parent(NULL)
+ , m_Sibling(NULL)
+ , m_Child(NULL)
+ , m_Association(NULL)
+ , m_BelongedPresentation(NULL)
+ {
+ }
+ QT3DSU32 GetHandle() const { return m_Handle; }
+ const STypeDesc &GetTypeDescription() const { return *m_TypeDescription; }
+ void SetTypeDescription(const STypeDesc *inDesc) { m_TypeDescription = inDesc; }
+ // Q3DStudio::CHash::HashString
+ QT3DSU32 GetNameHash() const;
+ const SPropertyValueGroup *GetFirstPropertyGroup() const { return m_PropertyValues; }
+ void SetFirstPropertyGroup(SPropertyValueGroup *inGroup) { m_PropertyValues = inGroup; }
+
+ SPropertyValueGroup *&UnsafeGetFirstPropertyGroup() { return m_PropertyValues; }
+
+ // In general, use these accessors for attributes, especially setting values.
+ // The other accessors are fast paths that do not:
+ // 1. Set dirty flags
+ // 2. Notify the activation zone of changes if setting start,end time.
+ // 3. Notify any other subsystems.
+ bool GetAttribute(QT3DSU32 inHashName, Q3DStudio::UVariant &outValue) const;
+ // Triggers updating various subcomponents based on attribute key.
+ void SetAttribute(const Q3DStudio::TAttributeHash inKey,
+ const Q3DStudio::UVariant inValue);
+ // Triggers updating various subcomponents without requiring a new property lookup.
+ void SetAttribute(TPropertyDescAndValuePtr inKey, const Q3DStudio::UVariant inNewValue);
+
+ // Q3DStudio::CHash::HashAttribute
+ Option<QT3DSU32> FindPropertyIndex(QT3DSU32 inNameHash) const;
+ Option<QT3DSU32> FindPropertyIndex(CRegisteredString inName) const;
+
+ Option<QT3DSU32> FindDynamicPropertyIndex(QT3DSU32 inNameHash) const;
+
+ QT3DSU32 GetNumProperties() const;
+ QT3DSU32 GetAttributeCount() const { return GetNumProperties(); }
+
+ QT3DSU32 GetNumDynamicProperties() const;
+ QT3DSU32 GetDynamicAttributeCount() const { return GetNumDynamicProperties(); }
+
+ // Note that if you set a value then this object is dirty.
+ // Bypasses special checks in setAttribute. In general, use setAttribute.
+ Option<TPropertyDescAndValuePtr> GetPropertyByIndex(QT3DSU32 inIdx);
+ Option<TPropertyDescAndConstValuePtr> GetPropertyByIndex(QT3DSU32 inIdx) const;
+
+ Option<TPropertyDescAndValuePtr> GetDynamicPropertyByIndex(QT3DSU32 inIdx);
+
+ Q3DStudio::UVariant *FindPropertyValue(QT3DSU32 inNameHash)
+ {
+ Option<QT3DSU32> idx = FindPropertyIndex(inNameHash);
+ if (idx.hasValue()) {
+ Option<TPropertyDescAndValuePtr> theVal = GetPropertyByIndex(idx);
+ if (theVal.hasValue())
+ return theVal->second;
+ }
+ return NULL;
+ }
+ const Q3DStudio::UVariant *FindPropertyValue(QT3DSU32 inNameHash) const
+ {
+ Option<QT3DSU32> idx = FindPropertyIndex(inNameHash);
+ if (idx.hasValue()) {
+ Option<TPropertyDescAndConstValuePtr> theVal = GetPropertyByIndex(idx);
+ if (theVal.hasValue())
+ return theVal->second;
+ }
+ return NULL;
+ }
+ Q3DStudio::UVariant *FindPropertyValue(CRegisteredString inNameHash)
+ {
+ Option<QT3DSU32> idx = FindPropertyIndex(inNameHash);
+ if (idx.hasValue()) {
+ Option<TPropertyDescAndValuePtr> theVal = GetPropertyByIndex(idx);
+ if (theVal.hasValue())
+ return theVal->second;
+ }
+ return NULL;
+ }
+
+ const Q3DStudio::UVariant *FindPropertyValue(CRegisteredString inNameHash) const
+ {
+ Option<QT3DSU32> idx = FindPropertyIndex(inNameHash);
+ if (idx.hasValue()) {
+ Option<TPropertyDescAndConstValuePtr> theVal = GetPropertyByIndex(idx);
+ if (theVal.hasValue())
+ return theVal->second;
+ }
+ return NULL;
+ }
+
+ Option<TPropertyDescAndValuePtr> FindProperty(QT3DSU32 inNameHash)
+ {
+ Option<QT3DSU32> idx = FindPropertyIndex(inNameHash);
+ if (idx.hasValue())
+ return GetPropertyByIndex(*idx);
+ return Empty();
+ }
+
+ Option<TPropertyDescAndValuePtr> FindDynamicProperty(QT3DSU32 inNameHash)
+ {
+ Option<QT3DSU32> idx = FindDynamicPropertyIndex(inNameHash);
+ if (idx.hasValue())
+ return GetDynamicPropertyByIndex(*idx);
+
+ return Empty();
+ }
+
+ SElement *GetParent() { return m_Parent; }
+ const SElement *GetParent() const { return m_Parent; }
+ SElement *GetSibling() { return m_Sibling; }
+ const SElement *GetSibling() const { return m_Sibling; }
+ SElement *GetChild() { return m_Child; }
+ const SElement *GetChild() const { return m_Child; }
+ CRegisteredString GetType() const { return m_TypeDescription->m_TypeName; }
+ bool IsComponent() const { return m_Flags.IsComponent(); }
+
+ Q3DStudio::IPresentation *GetBelongedPresentation() { return m_BelongedPresentation; }
+ void SetBelongedPresentation(Q3DStudio::IPresentation &inPresentation)
+ {
+ m_BelongedPresentation = &inPresentation;
+ }
+
+ // Set flags bypassing the dirty system *and* updates to the activity zone.
+ // do not do this unless you are sure you do not want any side effects.
+ SElementFlag &Flags() { return m_Flags; }
+
+ // User flag that is set and is persistent
+ void SetExplicitActive(bool inValue)
+ {
+ SetFlag(Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE, inValue);
+ }
+ bool IsExplicitActive() const { return m_Flags.IsExplicitActive(); }
+
+ // Flag set by the activity manager.
+ void SetActive(bool inValue) { SetFlag(Q3DStudio::ELEMENTFLAG_GLOBALACTIVE, inValue); }
+ bool GetActive() const { return m_Flags.IsActive(); }
+
+ void SetPickEnabled(bool inValue)
+ {
+ SetFlag(Q3DStudio::ELEMENTFLAG_PICKENABLED, inValue);
+ }
+ bool IsPickEnabled() const { return m_Flags.IsPickEnabled(); }
+
+ void SetPlayThrough(bool inValue)
+ {
+ SetFlag(Q3DStudio::ELEMENTFLAG_PLAYTHROUGH, inValue);
+ }
+ bool IsPlayThrough() const { return m_Flags.IsPlayThrough(); }
+
+ void SetScriptCallbacks(bool inValue)
+ {
+ SetFlag(Q3DStudio::ELEMENTFLAG_SCRIPTCALLBACKS, inValue);
+ }
+ bool HasScriptCallbacks() const { return m_Flags.HasScriptCallbacks(); }
+
+ bool IsDirty() const { return m_Flags.IsDirty(); }
+
+ bool GetFlag(Q3DStudio::EElementFlag inFlag) const { return m_Flags.operator&(inFlag); }
+
+ void SetDirty();
+ void SetFlag(Q3DStudio::EElementFlag inFlag, bool inValue);
+ void SetFlag(Q3DStudio::EElementFlag inFlag, int inValue)
+ {
+ SetFlag(inFlag, inValue ? true : false);
+ }
+ uic::runtime::IActivityZone &GetActivityZone() const;
+ bool HasActivityZone() const;
+ // Floating point number differences above this trigger a setDirty call.
+ static float SmallestDifference() { return 0.000001f; }
+ SElement &GetComponentParent();
+ const SElement &GetComponentParent() const;
+ SElement *FindChild(QT3DSU32 inNameHash);
+ // Get the time of my first noncomponent child or
+ // my time if I am not a component.
+ Q3DStudio::TTimeUnit GetInnerTime() const;
+ // Get the time I am animating at.
+ Q3DStudio::TTimeUnit GetOuterTime() const;
+ bool IsDescendent(SElement &inPossibleParent) const;
+ void *GetAssociation() const { return m_Association; }
+ void SetAssociation(void *inAssoc) { m_Association = inAssoc; }
+ QT3DSU32 GetUncachedDepth() const
+ {
+ if (m_Parent)
+ return m_Parent->GetUncachedDepth() + 1;
+ return 0;
+ }
+ void SetDepth() { m_Depth = GetUncachedDepth(); }
+ QT3DSU32 Depth() const { return m_Depth; }
+
+ bool IsUserActive() const;
+
+ bool IsIndependent() const;
+
+ bool IsGlobalActive() const;
+ // This may require a mutex to be held.
+ void SetGlobalActive(bool active);
+
+ bool IsTimeActive() const
+ {
+ if (m_Parent != NULL)
+ return m_ActivationManagerNode.m_Flags.IsTimeActive();
+ return true;
+ }
+
+ bool DoesParticipateInTimeGraph() const { return m_Flags.HasStartEndTime(); }
+
+ bool IsGlobalActive(bool inParentActive) const
+ {
+ bool ta = IsTimeActive();
+ bool ua = IsUserActive();
+
+ return ta && ua && inParentActive;
+ }
+ };
+
+ struct SGetElementNodeDirtyIndex
+ {
+ QT3DSU32 operator()(const SElement &inNode)
+ {
+ return inNode.m_ActivationManagerNode.m_DirtyIndex;
+ }
+ };
+ struct SSetElementNodeDirtyIndex
+ {
+ void operator()(SElement &inNode, QT3DSU32 val)
+ {
+ inNode.m_ActivationManagerNode.m_DirtyIndex = val;
+ }
+ };
+
+ struct SActivationManagerNodeDirtyList
+ : public InvasiveSet<SElement, SGetElementNodeDirtyIndex, SSetElementNodeDirtyIndex>
+ {
+ typedef InvasiveSet<SElement, SGetElementNodeDirtyIndex, SSetElementNodeDirtyIndex>
+ TBaseType;
+ SActivationManagerNodeDirtyList(NVAllocatorCallback &callback)
+ : TBaseType(callback, "SActivationManagerNodeDirtyList")
+ {
+ }
+ };
+
+ struct SComponent : public SElement
+ {
+ Q3DStudio::SAlignedTimeUnit m_BeginTime;
+ Q3DStudio::SAlignedTimeUnit m_Duration;
+
+ // Slide related
+ QT3DSU8 m_SlideCount; ///< Number of slides starting from base index
+ QT3DSU8 m_CurrentSlide; ///< Current slide number
+ QT3DSU8 m_PreviousSlide; ///< Previous slide number
+ SComponent(const STypeDesc &inDesc)
+ : SElement(inDesc)
+ , m_SlideCount(0)
+ , m_CurrentSlide(0)
+ , m_PreviousSlide(0)
+ {
+ }
+
+ QT3DSU8 GetCurrentSlide() const { return m_CurrentSlide; }
+ void SetCurrentSlide(QT3DSU8 inSlide)
+ {
+ m_PreviousSlide = m_CurrentSlide;
+ m_CurrentSlide = inSlide;
+ }
+ QT3DSU8 GetSlideCount() const { return m_SlideCount; }
+ QT3DSU8 GetPreviousSlide() const { return m_PreviousSlide; }
+ bool GetPaused() const;
+ bool GetPlayBackDirection() const;
+ Q3DStudio::CTimePolicy &GetTimePolicy();
+ const Q3DStudio::CTimePolicy &GetTimePolicy() const;
+ };
+ }
+ // Global store of all elements, values.
+ class IElementAllocator : public NVRefCounted
+ {
+ public:
+ // Performs coalesing of element types so that there are the least number of type
+ // descriptions
+ // Certain properties, like name, eyeball, are never in the property description.
+ virtual element::SElement &
+ CreateElement(CRegisteredString inName, CRegisteredString inType,
+ CRegisteredString inSubType,
+ NVConstDataRef<element::TPropertyDescAndValue> inPropertyDescriptions,
+ Q3DStudio::IPresentation *inPresentation, element::SElement *inParent,
+ bool inIsComponent) = 0;
+
+ virtual void ReleaseElement(element::SElement &inElement, bool inRecurse) = 0;
+
+ virtual Option<element::TPropertyDescAndValuePtr>
+ CreateDynamicProperty(Q3DStudio::IRuntimeMetaData &theMetaData, element::SElement &element,
+ CRegisteredString inName) = 0;
+
+ virtual element::SElement *FindElementByHandle(QT3DSU32 inElementHandle) = 0;
+ // Saving out the type descriptors and elements. Note that we save all roots in dfs order
+ // so that on load
+ // the graph is dfs although I do not think it matters. We save all elements at once so
+ // that we can
+ // have cross-presentation element references work out correctly. This is a rather large
+ // change
+ // from the older system which saved elements in presentation-specific groups.
+ // Unfortunately with this design
+ // a given address needs a presentation to distinguish it because on load each presentation
+ // will have a separate
+ // load address. So in the new system we save all elements into one section thus
+ // cross-presentation element references
+ // work correctly.
+ virtual void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream,
+ NVDataRef<element::SElement *> inRoots) = 0;
+ virtual Option<eastl::pair<NVDataRef<element::SElement *>, size_t>>
+ LoadBinaryData(NVDataRef<QT3DSU8> inLoadData, NVDataRef<QT3DSU8> inStringTableData) = 0;
+ // Returns an element pointer that when added to the return value of load will be a valid
+ // element.
+ virtual element::SElement *
+ GetRemappedElementAddress(element::SElement *inElement) const = 0;
+ virtual const element::STypeDesc *
+ GetRemappedTypeDescAddress(const element::STypeDesc *inTypeDesc) const = 0;
+ // If load is successful, then returns an address that can be added to elements and the root
+ // element.
+
+ static IElementAllocator &CreateElementAllocator(NVFoundationBase &inFoundation,
+ IStringTable &inStringTable);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Runtime/Include/UICEvent.h b/src/Runtime/Source/Runtime/Include/UICEvent.h
new file mode 100644
index 00000000..269549e4
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICEvent.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICKernelTypes.h"
+#include "UICElementSystem.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+/// Common structure used as both Events and Commands
+struct SEventCommand
+{
+ TElement *m_Target; ///< The target of this action
+ TEventCommandHash m_Type; ///< Type of action to perform
+ UVariant m_Arg1; ///< Argument 1
+ UVariant m_Arg2; ///< Argument 2
+ UINT8 m_Arg1Type; ///< EAttributeType for arg1 variant
+ UINT8 m_Arg2Type; ///< EAttributeType for arg2 variant
+
+ BOOL m_IsEvent : 1; ///< This is an Event or Command
+ BOOL m_BubbleUp : 1; ///< Bubble up to scene parent (2.4.2: theEvent:stopPropagation)
+ BOOL m_BubbleDown : 1; ///< Bubble down to scene children (2.4.2: theEvent:stopPropagation)
+ BOOL m_Done : 1; ///< Stop further handling (2.4.3: theEvent:stopImmediatePropagation)
+
+ UINT8 m_Unused; ///< (padding)
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICEventCallbacks.h b/src/Runtime/Source/Runtime/Include/UICEventCallbacks.h
new file mode 100644
index 00000000..4a54f9bf
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICEventCallbacks.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "UICEvent.h"
+#include "UICMemory.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef void (*TEventCallback)(void *inContextData, SEventCommand &ioEvent);
+
+//==============================================================================
+/**
+ * Manages the various events callbacks in the system. It fires the
+ * registered callbacks when an event was triggered.
+ */
+class CEventCallbacks
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+protected:
+ struct SCallbackEntry
+ {
+ TEventCallback m_Function; ///< Callback function pointer
+ void *m_ContextData; ///< User data
+ };
+ typedef CArray<SCallbackEntry> TCallbackList; ///< Array of callbacks regisgtered
+
+ struct SEventCallbackEntry
+ {
+ SEventCallbackEntry()
+ : m_EventHash(0)
+ {
+ }
+ ~SEventCallbackEntry() {}
+
+ TEventCommandHash m_EventHash; ///< The event of interest
+ TCallbackList m_Callbacks; ///< List of callbacks listening to this event
+
+ private: // Disabled Copy Construction
+ SEventCallbackEntry(const SEventCallbackEntry &);
+ SEventCallbackEntry &operator=(const SEventCallbackEntry &);
+ };
+ typedef CArray<SEventCallbackEntry *> TEventCallbacksList; ///< Array of events with callback
+
+ struct SElementCallbackEntry
+ {
+ SElementCallbackEntry()
+ : m_Element(NULL)
+ {
+ }
+ ~SElementCallbackEntry()
+ {
+ FOR_ARRAY(SEventCallbackEntry *, theEntry, m_EventEntries)
+ Q3DStudio_delete(*theEntry, SEventCallbackEntry);
+ }
+
+ TElement *m_Element; ///< Element to monitor for event
+ TEventCallbacksList m_EventEntries; ///< List of events listened on this element
+
+ private: // Disabled Copy Construction
+ SElementCallbackEntry(const SElementCallbackEntry &);
+ SElementCallbackEntry &operator=(const SElementCallbackEntry &);
+ };
+ typedef CArray<SElementCallbackEntry *>
+ TElementCallbacksList; ///< Array of elements with callbacks
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ TElementCallbacksList m_EventCallbacksList; ///< List of event callbacks
+ TCallbackList m_CallbackList;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CEventCallbacks();
+ ~CEventCallbacks();
+
+public: // Registration
+ void RegisterCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData);
+ BOOL UnregisterCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData, BOOL &outLast);
+ void UnregisterAllCallbacks();
+
+public: // Operation
+ void FireCallbacks(SEventCommand &ioEvent);
+
+protected:
+ void PerformCallbacks(TCallbackList &inCallbackList, SEventCommand &ioEvent);
+
+private: // Disabled Copy Construction
+ CEventCallbacks(const CEventCallbacks &);
+ CEventCallbacks &operator=(const CEventCallbacks &);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICFrameworkTypes.h b/src/Runtime/Source/Runtime/Include/UICFrameworkTypes.h
new file mode 100644
index 00000000..a22812d2
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICFrameworkTypes.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTypes.h"
+#include "UICArray.h"
+#include "UICVector3.h"
+#include "UICMatrix.h"
+#include "UICBoundingBox.h"
+#include "UICKernelTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICIComponentManager.h b/src/Runtime/Source/Runtime/Include/UICIComponentManager.h
new file mode 100644
index 00000000..121270ff
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICIComponentManager.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICTimePolicy.h"
+#include "foundation/Qt3DSOption.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+namespace uic {
+namespace runtime {
+ namespace element {
+ struct TElement;
+ struct TComponent;
+ }
+}
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+struct IComponentTimeOverrideFinishedCallback
+{
+protected:
+ virtual ~IComponentTimeOverrideFinishedCallback() {}
+public:
+ virtual void OnTimeFinished() = 0;
+ virtual void Release() = 0;
+};
+
+typedef qt3ds::foundation::Option<TimePolicyModes::Enum> TTimePolicyModeOption;
+typedef qt3ds::foundation::Option<INT32> TInt32Option;
+typedef qt3ds::foundation::Option<unsigned long> TULongOption;
+typedef qt3ds::foundation::Option<bool> TBoolOption;
+
+struct SComponentGotoSlideData
+{
+ INT32 m_Slide;
+ TTimePolicyModeOption m_Mode;
+ //-2 means previous, -1 means next, 1-N means slide
+ TInt32Option m_PlaythroughTo;
+ TULongOption m_StartTime;
+ FLOAT m_Rate;
+ bool m_Reverse;
+ TBoolOption m_Paused;
+
+ // No mode means use the mode in the slide data.
+ SComponentGotoSlideData(INT32 inSlide = 0,
+ TTimePolicyModeOption inMode = TTimePolicyModeOption(),
+ TInt32Option inPlayThrough = TInt32Option(),
+ TULongOption inStartTime = TULongOption(), FLOAT inRate = 1.0f,
+ bool inReverse = false, TBoolOption inPaused = TBoolOption())
+ : m_Slide(inSlide)
+ , m_Mode(inMode)
+ , m_PlaythroughTo(inPlayThrough)
+ , m_StartTime(inStartTime)
+ , m_Rate(inRate)
+ , m_Reverse(inReverse)
+ , m_Paused(inPaused)
+ {
+ }
+};
+
+//==============================================================================
+/**
+ * @interface IComponentManager
+ * Base interface of the container of all the components in the presentation.
+ * This specify the basic operations required to implement a Component manager
+ * object that works well with the kernel.
+ */
+class IComponentManager
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~IComponentManager() {}
+
+public: // Promotion
+ virtual TComponent *GetComponent(TElement *inElement) = 0;
+
+public: // Slides
+ virtual void GotoSlideIndex(TElement *inComponent, const SComponentGotoSlideData &inGotoData,
+ BOOL inSlideExit = true) = 0;
+ virtual void GotoSlideName(TElement *inComponent, const TStringHash inSlideHashName) = 0;
+ virtual void GoToBackSlide(TElement *inComponent) = 0;
+ virtual void GoToNextSlide(TElement *inComponent, const INT32 inDecrement = 1) = 0;
+ virtual void GoToPreviousSlide(TElement *inComponent, const INT32 inDecrement = 1) = 0;
+
+ virtual UINT8 GetSlideCount(TElement *inComponent) = 0;
+ virtual UINT8 GetCurrentSlide(TElement *inComponent) = 0;
+ virtual const CHAR *GetCurrentSlideName(TElement *inComponent) = 0;
+
+ virtual void OnElementDeactivated(TElement *inElement) = 0;
+
+ virtual void SetComponentTimeOverride(TElement *inElement, TTimeUnit inEndTime,
+ FLOAT inInterpolation,
+ IComponentTimeOverrideFinishedCallback *inCallback) = 0;
+
+ virtual void SetupComponentGotoSlideCommand(TElement *inElement,
+ const SComponentGotoSlideData &inGotoSlideData) = 0;
+ virtual bool HasComponentGotoSlideCommand(TElement *inElement) = 0;
+ virtual SComponentGotoSlideData GetComponentGotoSlideCommand(TElement *inElement) = 0;
+ virtual void ReleaseComponentGotoSlideCommand(TElement *inElement) = 0;
+
+public: // Time
+ virtual void GoToTime(TElement *inComponent, const TTimeUnit inTime) = 0;
+ virtual void SetPause(TElement *inComponent, const BOOL inPause) = 0;
+ virtual void SetTimePolicy(TElement *inComponent, const TTimeUnit inLoopDuration,
+ const UINT32 inRepetitions, const BOOL inPingPong,
+ const BOOL inPlayThrough) = 0;
+
+ virtual BOOL GetPause(TElement *inComponent) = 0;
+ virtual BOOL GetPlayBackDirection(TElement *inComponent) = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICIInputSystem.h b/src/Runtime/Source/Runtime/Include/UICIInputSystem.h
new file mode 100644
index 00000000..0d75bd8f
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICIInputSystem.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "UICInputEngine.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Input system interface
+ */
+class IInputSystem : public CInputEngine
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~IInputSystem() {}
+
+public: // Processing
+ virtual void UpdateInput() = 0;
+ virtual void ProcessInput() = 0;
+
+protected: // Input System handler
+ virtual void CheckMouseEvent() = 0;
+ virtual void CheckKeyboardEvent() = 0;
+ virtual void CheckJoystickEvent() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICIScene.h b/src/Runtime/Source/Runtime/Include/UICIScene.h
new file mode 100644
index 00000000..cb985f7b
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICIScene.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "UICBoundingBox.h"
+namespace uic {
+namespace render {
+ class IImageLoadListener;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IPresentation;
+class RuntimeMatrix;
+struct SPickFrame;
+
+//==============================================================================
+/**
+* @interface IScene
+*
+* Runtime interface to the renderer's representation of a presentation. Scenes are
+* created by the SceneManager and rendered via a lower level rendering system.
+*/
+struct STextSizes
+{
+ INT32 m_Width;
+ INT32 m_Height;
+ STextSizes()
+ : m_Width(0)
+ , m_Height(0)
+ {
+ }
+ STextSizes(INT32 w, INT32 h)
+ : m_Width(w)
+ , m_Height(h)
+ {
+ }
+};
+
+struct SMousePosition
+{
+ INT32 m_X;
+ INT32 m_Y;
+ SMousePosition(INT32 x, INT32 y)
+ : m_X(x)
+ , m_Y(y)
+ {
+ }
+ SMousePosition()
+ : m_X(0)
+ , m_Y(0)
+ {
+ }
+};
+
+struct SCameraRect
+{
+ float m_Left;
+ float m_Top;
+ float m_Right;
+ float m_Bottom;
+ SCameraRect(float l = 0.0f, float t = 0.0f, float r = 0.0f, float b = 0.0f)
+ : m_Left(l)
+ , m_Top(t)
+ , m_Right(r)
+ , m_Bottom(b)
+ {
+ }
+
+ bool IsValid() const { return fabs(m_Right - m_Left) > 0.0f; }
+};
+
+class IScene
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+protected:
+ virtual ~IScene() {}
+
+public: // Base Interface
+ virtual IPresentation &GetPresentation() = 0;
+
+ virtual void SetUserData(void *inUserData) = 0;
+ virtual void *GetUserData() = 0;
+
+ // virtual void Clone( TElementList& inElements, TElementList& inElementClones, TElement*
+ // inNewParent = NULL ) = 0;
+ virtual void CalculateGlobalTransform(TElement *inElement, RuntimeMatrix &outTransform) = 0;
+ virtual void SetLocalTransformMatrix(TElement *inElement, const RuntimeMatrix &inTransform) = 0;
+ // Get bounding box in global space
+ virtual CBoundingBox GetBoundingBox(TElement *inElement, bool inSelfOnly) = 0;
+ // Get bounding box in local space.
+ virtual CBoundingBox GetLocalBoundingBox(TElement *inElement, bool inSelfOnly) = 0;
+
+ // The final argument, inHasTransparency has 3 possible values,
+ // 0 for no transparency, 1 for hasTransparency, -1 for unknown
+ virtual void SetTextureData(TElement *inElement, const unsigned char *inBuffer,
+ INT32 inBufferLength, INT32 inWidth, INT32 inHeight,
+ qt3ds::render::NVRenderTextureFormats::Enum inFormat,
+ INT32 inHasTransparency = -1) = 0;
+
+ virtual bool CreateOrSetMeshData(const char *inPathStr, unsigned char *vertData,
+ unsigned int numVerts, unsigned int vertStride,
+ unsigned int *indexData, unsigned int numIndices,
+ qt3ds::NVBounds3 &objBounds) = 0;
+
+ virtual STextSizes MeasureText(TElement *inElement, const char *inTextStr) = 0;
+
+ virtual STextSizes GetPresentationDesignDimensions() = 0;
+ // If the rect's right - left == 0.0, this method failed. Possibly because the layer is just
+ // direct-rendering
+ // a sub-presentation.
+ virtual SCameraRect GetCameraBounds(TElement &inElement) = 0;
+
+ virtual void PositionToScreen(TElement &inElement, qt3ds::QT3DSVec3 &inPos,
+ qt3ds::QT3DSVec3 &outScreen) = 0;
+ virtual void ScreenToPosition(TElement &inElement, qt3ds::QT3DSVec3 &inScreen,
+ qt3ds::QT3DSVec3 &outPos) = 0;
+
+ // This is the best place for now...
+ virtual void GetImageInfoFromRenderEngine(TElement *inElement, INT32 &ioWidth,
+ INT32 &ioHeight) = 0;
+
+ virtual qt3ds::foundation::CRegisteredString RegisterStr(const char *inStr) = 0;
+
+ virtual Q3DStudio::INT32
+ LoadImageBatch(qt3ds::foundation::CRegisteredString *inFullPaths, INT32 inNumPaths,
+ qt3ds::foundation::CRegisteredString inDefaultImage,
+ uic::render::IImageLoadListener *inLoadCallback = NULL) = 0;
+
+ virtual SMousePosition WindowToPresentation(const SMousePosition &inWindowPos) = 0;
+
+ virtual void RegisterOffscreenRenderer(const char *inKey) = 0;
+
+ virtual void Release() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICIScriptBridge.h b/src/Runtime/Source/Runtime/Include/UICIScriptBridge.h
new file mode 100644
index 00000000..14682e9c
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICIScriptBridge.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICIComponentManager.h"
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+#include "UICLuaIncludes.h"
+#include "foundation/Qt3DSRefCounted.h"
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace uic {
+namespace runtime {
+ class IApplication;
+ class IApplicationCore;
+}
+}
+namespace uic {
+namespace state {
+ namespace debugger {
+ class IMultiProtocolSocket;
+ }
+}
+}
+namespace uic {
+namespace render {
+ class IThreadPool;
+}
+}
+
+struct lua_State;
+
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+struct SEventCommand;
+class IPresentation;
+
+//==============================================================================
+/**
+ * @interface IScriptBridge
+ * @brief Callback and load interface for a script engine.
+ */
+
+class ILuaScriptTableProvider
+{
+protected:
+ virtual ~ILuaScriptTableProvider() {}
+public:
+ virtual void CreateTable(lua_State *inState) = 0;
+};
+
+struct SScriptEngineGotoSlideArgs
+{
+ TTimePolicyModeOption m_Mode;
+ //-2 means previous, -1 means next, 1-N means slide
+ const char *m_PlaythroughTo;
+ TULongOption m_StartTime;
+ FLOAT m_Rate;
+ bool m_Reverse;
+ TBoolOption m_Paused;
+ SScriptEngineGotoSlideArgs()
+ : m_PlaythroughTo(NULL)
+ , m_Rate(1.0f)
+ , m_Reverse(false)
+ {
+ }
+};
+
+class CScriptEngineCallFunctionArgRetriever
+{
+public:
+ CScriptEngineCallFunctionArgRetriever(const char *inArguments)
+ : m_ArgumentString(inArguments)
+ {
+ }
+ virtual ~CScriptEngineCallFunctionArgRetriever() {}
+ // Retrieve argument
+ // Return value: -1 error; otherwise it indicates argument count
+ virtual int RetrieveArgument(lua_State *inState);
+ virtual eastl::string GetArgDescription();
+
+protected:
+ const char *m_ArgumentString;
+};
+
+class IScriptBridge : public qt3ds::foundation::NVRefCounted
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~IScriptBridge() {}
+
+public: // thread
+ // After this call all public functions are protected by a mutex
+ virtual void EnableMultithreadedAccess() = 0;
+ // After this call all public functions are not threadsafe.
+ virtual void DisableMultithreadedAccess() = 0;
+
+public: // Settings
+ virtual void SetApplicationCore(uic::runtime::IApplicationCore &inApplication) = 0;
+ virtual void SetApplication(uic::runtime::IApplication &inApplication) = 0;
+
+public: // Binary preloading
+ // Starts preloading scripts offline. This sets m_LuaState to NULL until after
+ // EndPreloadScripts
+ // This function is only used for binary loading, eg, .uiab
+ virtual void BeginPreloadScripts(const eastl::vector<const char *> &inScripts,
+ uic::render::IThreadPool &inThreadPool,
+ const char *inProjectDir) = 0;
+ // This function is blocking if m_LuaState == NULL, which only holds during binary loading
+ virtual void EndPreloadScripts() = 0;
+ // Fast loading support
+ // get the set of loaded scripts relative file names
+ // This has the side effect of writing out the loaded scripts to
+ // projectDir/binary/compiledlua.bin, only used for binary save
+ virtual eastl::vector<eastl::string> GetLoadedScripts() = 0;
+
+public: // Scripts
+ // Both loads lua script, create an self table -> scriptIndex in a behaviors table
+ // LoadScript goes further by registering scriptIndex->inPresentation, and inOwner->m_ScriptID=
+ // scriptIndex
+ virtual void LoadScript(IPresentation *inPresentation, TElement *inOwner,
+ const CHAR *inName) = 0;
+ virtual Q3DStudio::INT32 InitializeApplicationBehavior(const char *inProjectRelativePath) = 0;
+
+public: // Script functions and Callbacks
+ virtual void ProcessFrameCallbacks(IPresentation *inPresentation) = 0;
+ // Call a member function inFnName from self table whose script index is given by inApp
+ virtual void ExecuteApplicationScriptFunction(Q3DStudio::INT32 inApp, const char *inFnName) = 0;
+ virtual void CallFunction(const char *behavior, const char *handler,
+ CScriptEngineCallFunctionArgRetriever &inArgRetriever) = 0;
+
+public: // Custom Actions
+ virtual void ProcessSignal(IPresentation *inPresentation,
+ const SEventCommand &inCommand) = 0;
+ virtual void ProcessCustomActions(IPresentation *inPresentation,
+ const SEventCommand &inCommand) = 0;
+ virtual void ProcessCustomCallback(IPresentation *inPresentation,
+ const SEventCommand &inCommand) = 0;
+
+public: // Elements
+ // Use inProvider to create a new table and associate with inElement: currently a render plugin
+ // element
+ // this mimics render plugin as an behaviour element
+ virtual void SetTableForElement(TElement &inElement, ILuaScriptTableProvider &inProvider) = 0;
+ virtual void SetAttribute(const char *element, const char *attName, const char *value) = 0;
+ virtual void FireEvent(const char *element, const char *evtName) = 0;
+
+public: // Components
+ virtual void GotoSlide(const char *component, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs) = 0;
+ virtual void GotoSlideRelative(const char *component, bool inNextSlide, bool inWrap,
+ const SScriptEngineGotoSlideArgs &inArgs) = 0;
+
+public: // Presentation
+ virtual void SetPresentationAttribute(const char *presId, const char *attName,
+ const char *attValue) = 0;
+
+public: // Multimedia
+ virtual bool PlaySoundFile(const char *soundPath) = 0;
+
+public: // Miscellaneous
+ virtual void EnableDebugging(uic::state::debugger::IMultiProtocolSocket &socket) = 0;
+ virtual void EnableProfiling() = 0;
+ virtual void StepGC() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICIStateful.h b/src/Runtime/Source/Runtime/Include/UICIStateful.h
new file mode 100644
index 00000000..d18a9534
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICIStateful.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICArray.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+class IStatefulStackBase
+{
+public:
+ virtual void PushState() = 0;
+ virtual void PopState() = 0;
+};
+
+template <typename T>
+class IStatefulStack : public IStatefulStackBase
+{
+public:
+ IStatefulStack(T &inStateProperty)
+ : m_StateProperty(inStateProperty)
+ {
+ }
+
+ virtual ~IStatefulStack(){};
+
+public:
+ virtual void PushState() { m_States.Push(m_StateProperty); }
+ virtual void PopState() { m_StateProperty = m_States.Pop(); }
+
+protected:
+ T &m_StateProperty;
+ CArray<T> m_States;
+};
+
+} // namespace Q3DStudio \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICIText.h b/src/Runtime/Source/Runtime/Include/UICIText.h
new file mode 100644
index 00000000..c4694fe2
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICIText.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CWorld;
+class CRenderStateManager;
+
+class IText
+{
+public: // Text update
+ virtual void Update(CWorld &inWorld, CVector3 &outBoxMin, CVector3 &outBoxMax) = 0;
+ virtual void Apply(CRenderStateManager &inRenderStateManager) = 0;
+ static IText *GetIText(INT32 inAssociation);
+};
+
+} // namespace Q3DStudio \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICInputDefs.h b/src/Runtime/Source/Runtime/Include/UICInputDefs.h
new file mode 100644
index 00000000..447e424b
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICInputDefs.h
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Mouse button state flags
+ * There is some discrepancy between mouse state and mouse events.
+ *
+ * Mouse button state refers to the actual state of the button as captured
+ * by the input engine. The logical states are: up, pressed, down and released.
+ *
+ * Mouse events are generated by Kernel (in CKernel::SetPickFrame), and current
+ * support is only for pressed and released. This translates to the respective
+ * MOUSE_DOWN and MOUSE_UP.
+ *
+ * Therefore, a mapping would be:
+ * STATE_MOUSE_PRESSED -> EVENT_MOUSE_DOWN
+ * STATE_MOUSE_RELEASED -> EVENT_MOUSE_UP
+ * STATE_MOUSE_UP -> No corresponding event
+ * STATE_MOUSE_DOWN -> No corresponding event
+ *
+ */
+enum EMouseInputFlags {
+ NO_INPUT = 0,
+ //
+ LMOUSE_PRESSED = 1 << 0,
+ LMOUSE_RELEASED = 1 << 1,
+ MMOUSE_PRESSED = 1 << 2,
+ MMOUSE_RELEASED = 1 << 3,
+ RMOUSE_PRESSED = 1 << 4,
+ RMOUSE_RELEASED = 1 << 5,
+ //
+ LMOUSE_DOWN = 1 << 6,
+ LMOUSE_UP = 1 << 7,
+ MMOUSE_DOWN = 1 << 8,
+ MMOUSE_UP = 1 << 9,
+ RMOUSE_DOWN = 1 << 10,
+ RMOUSE_UP = 1 << 11,
+ MOUSEBUTTONCOUNT = 3, // left, middle, right - could potentially have more mouse buttons
+
+ HSCROLLWHEEL = 1 << 12,
+ VSCROLLWHEEL = 1 << 13,
+};
+
+//==============================================================================
+/**
+ * Key code/index to SInputFrame::m_KeyStates
+ */
+// enum EKeyCode
+//{
+// KEY_NOKEY = 0x00,
+// KEY_ESCAPE,
+// KEY_1,
+// KEY_2,
+// KEY_3,
+// KEY_4,
+// KEY_5,
+// KEY_6,
+// KEY_7,
+// KEY_8,
+// KEY_9,
+// KEY_0,
+// KEY_MINUS, /* - on main keyboard */
+// KEY_EQUALS,
+// KEY_BACK, /* backspace */
+// KEY_TAB,
+// KEY_Q,
+// KEY_W,
+// KEY_E,
+// KEY_R,
+// KEY_T,
+// KEY_Y,
+// KEY_U,
+// KEY_I,
+// KEY_O,
+// KEY_P,
+// KEY_LBRACKET,
+// KEY_RBRACKET,
+// KEY_RETURN, /* Enter on main keyboard */
+// KEY_LCONTROL,
+// KEY_A,
+// KEY_S,
+// KEY_D,
+// KEY_F,
+// KEY_G,
+// KEY_H,
+// KEY_J,
+// KEY_K,
+// KEY_L,
+// KEY_SEMICOLON,
+// KEY_APOSTROPHE,
+// KEY_GRAVE, /* accent grave */
+// KEY_LSHIFT,
+// KEY_BACKSLASH,
+// KEY_Z,
+// KEY_X,
+// KEY_C,
+// KEY_V,
+// KEY_B,
+// KEY_N,
+// KEY_M,
+// KEY_COMMA,
+// KEY_PERIOD, /* . on main keyboard */
+// KEY_SLASH, /* / on main keyboard */
+// KEY_RSHIFT,
+// KEY_MULTIPLY, /* * on numeric keypad */
+// KEY_LMENU, /* left Alt */
+// KEY_SPACE,
+// KEY_CAPITAL,
+// KEY_F1,
+// KEY_F2,
+// KEY_F3,
+// KEY_F4,
+// KEY_F5,
+// KEY_F6,
+// KEY_F7,
+// KEY_F8,
+// KEY_F9,
+// KEY_F10,
+// KEY_NUMLOCK,
+// KEY_SCROLL, /* Scroll Lock */
+// KEY_NUMPAD7,
+// KEY_NUMPAD8,
+// KEY_NUMPAD9,
+// KEY_SUBTRACT, /* - on numeric keypad */
+// KEY_NUMPAD4,
+// KEY_NUMPAD5,
+// KEY_NUMPAD6,
+// KEY_ADD, /* + on numeric keypad */
+// KEY_NUMPAD1,
+// KEY_NUMPAD2,
+// KEY_NUMPAD3,
+// KEY_NUMPAD0,
+// KEY_DECIMAL, /* . on numeric keypad */
+// KEY_OEM_102, /* <> or \| on RT 102-key keyboard (Non-U.S.) */
+// KEY_F11,
+// KEY_F12,
+// KEY_F13, /* (NEC PC98) */
+// KEY_F14, /* (NEC PC98) */
+// KEY_F15, /* (NEC PC98) */
+// KEY_KANA, /* (Japanese keyboard) */
+// KEY_ABNT_C1, /* /? on Brazilian keyboard */
+// KEY_CONVERT, /* (Japanese keyboard) */
+// KEY_NOCONVERT, /* (Japanese keyboard) */
+// KEY_YEN, /* (Japanese keyboard) */
+// KEY_ABNT_C2, /* Numpad . on Brazilian keyboard */
+// KEY_NUMPADEQUALS, /* = on numeric keypad (NEC PC98) */
+// KEY_PREVTRACK, /* Previous Track
+// (DIK_CIRCUMFLEX on Japanese keyboard) */
+// KEY_AT, /* (NEC PC98) */
+// KEY_COLON, /* (NEC PC98) */
+// KEY_UNDERLINE, /* (NEC PC98) */
+// KEY_KANJI, /* (Japanese keyboard) */
+// KEY_STOP, /* (NEC PC98) */
+// KEY_AX, /* (Japan AX) */
+// KEY_UNLABELED, /* (J3100) */
+// KEY_NEXTTRACK, /* Next Track */
+// KEY_NUMPADENTER, /* Enter on numeric keypad */
+// KEY_RCONTROL,
+// KEY_MUTE, /* Mute */
+// KEY_CALCULATOR, /* Calculator */
+// KEY_PLAYPAUSE, /* Play / Pause */
+// KEY_MEDIASTOP, /* Media Stop */
+// KEY_VOLUMEDOWN, /* Volume - */
+// KEY_VOLUMEUP, /* Volume + */
+// KEY_WEBHOME, /* Web home */
+// KEY_NUMPADPERIOD, /* . on numeric keypad (NEC PC98) */
+// KEY_DIVIDE, /* / on numeric keypad */
+// KEY_SYSRQ,
+// KEY_RMENU, /* right Alt */
+// KEY_PAUSE, /* Pause */
+// KEY_HOME, /* Home on arrow keypad */
+// KEY_UP, /* UpArrow on arrow keypad */
+// KEY_PRIOR, /* PgUp on arrow keypad */
+// KEY_LEFT, /* LeftArrow on arrow keypad */
+// KEY_RIGHT, /* RightArrow on arrow keypad */
+// KEY_END, /* End on arrow keypad */
+// KEY_DOWN, /* DownArrow on arrow keypad */
+// KEY_NEXT, /* PgDn on arrow keypad */
+// KEY_INSERT, /* Insert on arrow keypad */
+// KEY_DELETE, /* Delete on arrow keypad */
+// KEY_LWIN, /* Left Windows key */
+// KEY_RWIN, /* Right Windows key */
+// KEY_APPS, /* AppMenu key */
+// KEY_POWER, /* System Power */
+// KEY_SLEEP, /* System Sleep */
+// KEY_WAKE, /* System Wake */
+// KEY_WEBSEARCH, /* Web Search */
+// KEY_WEBFAVORITES, /* Web Favorites */
+// KEY_WEBREFRESH, /* Web Refresh */
+// KEY_WEBSTOP, /* Web Stop */
+// KEY_WEBFORWARD, /* Web Forward */
+// KEY_WEBBACK, /* Web Back */
+// KEY_MYCOMPUTER, /* My Computer */
+// KEY_MAIL, /* Mail */
+// KEY_MEDIASELECT, /* Media Select */
+// //
+// KEY_TOTAL_COUNT
+//};
+
+typedef enum _EKeyCode {
+ KEY_NOKEY = 0,
+ KEY_ESCAPE,
+ KEY_1,
+ KEY_2,
+ KEY_3,
+ KEY_4,
+ KEY_5,
+ KEY_6,
+ KEY_7,
+ KEY_8,
+ KEY_9,
+ KEY_0,
+ KEY_SUBTRACT,
+ KEY_EQUALS,
+ KEY_BACK,
+ KEY_TAB,
+ KEY_Q,
+ KEY_W,
+ KEY_E,
+ KEY_R,
+ KEY_T,
+ KEY_Y,
+ KEY_U,
+ KEY_I,
+ KEY_O,
+ KEY_P,
+ KEY_LBRACKET,
+ KEY_RBRACKET,
+ KEY_RETURN,
+ KEY_LCONTROL,
+ KEY_A, // 30
+ KEY_S,
+ KEY_D,
+ KEY_F,
+ KEY_G,
+ KEY_H,
+ KEY_J,
+ KEY_K,
+ KEY_L,
+ KEY_SEMICOLON,
+ KEY_APOSTROPHE, // 40
+ KEY_GRAVE,
+ KEY_LSHIFT,
+ KEY_BACKSLASH,
+ KEY_Z,
+ KEY_X,
+ KEY_C,
+ KEY_V,
+ KEY_B,
+ KEY_N,
+ KEY_M,
+ KEY_COMMA,
+ KEY_PERIOD,
+ KEY_SLASH,
+ KEY_RSHIFT,
+ KEY_MULTIPLY,
+ KEY_LALT,
+ KEY_SPACE,
+ KEY_CAPITAL,
+ KEY_F1,
+ KEY_F2, // 60
+ KEY_F3,
+ KEY_F4,
+ KEY_F5,
+ KEY_F6,
+ KEY_F7,
+ KEY_F8,
+ KEY_F9,
+ KEY_F10,
+ KEY_NUMLOCK,
+ KEY_SCROLL, // 70
+ KEY_NUMPAD7,
+ KEY_NUMPAD8,
+ KEY_NUMPAD9,
+ KEY_NUMPADSUBTRACT,
+ KEY_NUMPAD4,
+ KEY_NUMPAD5,
+ KEY_NUMPAD6,
+ KEY_NUMPADADD,
+ KEY_NUMPAD1,
+ KEY_NUMPAD2, // 80
+ KEY_NUMPAD3,
+ KEY_NUMPAD0,
+ KEY_NUMPADDECIMAL,
+ KEY_NOOP,
+ KEY_ZENKAKUHANKAKU,
+ KEY_102ND,
+ KEY_F11,
+ KEY_F12,
+ KEY_F13,
+ KEY_F14, // 90
+ KEY_HIRAGANA,
+ KEY_HENKAN,
+ KEY_KATAKANAHIRAGANA,
+ KEY_MUHENKAN,
+ KEY_KPJPCOMMA,
+ KEY_NUMPADENTER,
+ KEY_RCONTROL,
+ KEY_NUMPADDIVIDE,
+ KEY_PRINTSCREEN,
+ KEY_RALT, // 100
+ KEY_LINEFEED,
+ KEY_HOME,
+ KEY_UP,
+ KEY_PGUP,
+ KEY_LEFT,
+ KEY_RIGHT,
+ KEY_END,
+ KEY_DOWN,
+ KEY_PGDN,
+ KEY_INSERT, // 110
+ KEY_DELETE,
+ KEY_MACRO,
+ KEY_MUTE,
+ KEY_VOLUMEDOWN,
+ KEY_VOLUMEUP,
+ KEY_POWER,
+ KEY_KPEQUAL,
+ KEY_KPPLUSMINUS,
+ KEY_PAUSE,
+ KEY_SCALE,
+ KEY_TOTAL_COUNT
+} EKeyCode;
+
+//==============================================================================
+/**
+ * Keyboard modifier flags
+ */
+enum EKeyboardModifierFlags {
+ MODIFIER_NONE = 0,
+ MODIFIER_SHIFT = 1 << 0,
+ MODIFIER_CTRL = 1 << 1,
+ MODIFIER_ALT = 1 << 2,
+ MODIFIER_KEYDOWN = 1 << 3, ///< One or more key is down
+};
+
+//==============================================================================
+/**
+ * Button codes
+ */
+enum EButtonCodes {
+ BUTTON_A = 0,
+ BUTTON_B,
+ BUTTON_X,
+ BUTTON_Y,
+ BUTTON_L1,
+ BUTTON_R1,
+ BUTTON_THUMBL,
+ BUTTON_THUMBR,
+ BUTTON_SELECT,
+ BUTTON_START,
+ BUTTON_MODE,
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_LEFT,
+ BUTTON_RIGHT,
+ BUTTON_CENTER,
+ BUTTON_ENTER,
+ BUTTON_TOTAL_COUNT
+};
+
+//==============================================================================
+/**
+ * Axis codes
+ */
+enum EAxisCodes {
+ AXIS_X = 0,
+ AXIS_Y,
+ AXIS_Z,
+ AXIS_RZ,
+ AXIS_HAT_X,
+ AXIS_HAT_Y,
+ AXIS_LTRIGGER,
+ AXIS_RTRIGGER,
+ AXIS_TOTAL_COUNT
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICInputEngine.h b/src/Runtime/Source/Runtime/Include/UICInputEngine.h
new file mode 100644
index 00000000..aa83bd26
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICInputEngine.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICKernelTypes.h"
+#include "UICPickFrame.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSDataRef.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace uic {
+namespace runtime {
+ class IApplication;
+}
+}
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRuntime;
+union UVariant;
+class CInputEventProvider;
+
+//==============================================================================
+/**
+* @class CInputEngine
+* @brief The basic input engine
+*/
+class CInputEngine
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ SInputFrame m_InputFrame; ///< The data describing the input state
+ eastl::vector<eastl::pair<float, float>> m_PickInput;
+ bool m_BeginPickInput;
+ uic::runtime::IApplication *m_Application; ///< The Runtime object
+ qt3ds::foundation::NVScopedRefCounted<CInputEventProvider>
+ m_InputEventProvider; ///< The event provider for keyboard
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ typedef qt3ds::foundation::NVConstDataRef<const eastl::pair<float, float>> TPickInputList;
+ CInputEngine();
+ virtual ~CInputEngine();
+
+public: // Runtime interfaces
+ void SetApplication(uic::runtime::IApplication *inApplication);
+
+public:
+ // Access
+ virtual SInputFrame &GetInputFrame();
+ virtual SKeyInputFrame &GetKeyInputFrame();
+
+ // Setters
+ // Multitouch is handled by using BeginPickInput, SetPickInput (several times), and EndPickInput
+ // pairs.
+ // The assumption here is that the pick input is static until changed. So to clear it you need
+ // a
+ // begin, end pair without any other pieces.
+ virtual void BeginPickInput();
+ virtual void SetPickInput(FLOAT inX, FLOAT inY, BOOL inValid = true);
+ virtual void EndPickInput();
+ virtual TPickInputList GetPickInput() const;
+ virtual void SetPickFlags(INT32 inFlags);
+ virtual void SetKeyState(INT32 inKeyCode, BOOL inDown);
+ virtual void SetButtonState(INT32 inButtonCode, BOOL inDown);
+ virtual void SetScrollValue(INT32 inFlags, INT16 value);
+ virtual void SetModifierFlag(INT32 inFlag);
+
+ // Keyboard hook
+ virtual void HandleKeyboard(INT32 inKeyCode, INT32 inPressed, INT32 inRepeat = 0);
+
+ // Other input
+ virtual void HandleButton(INT32 inButtonCode, INT32 inPressed, INT32 inRepeat = 0);
+ virtual void HandleAxis(INT32 inAxisCode, FLOAT inValue);
+
+ // Helpers
+ // virtual INT32 ConvertKeyCode( INT32 inKeyCode, BOOL inShift );
+ // TODO: SK - To quickly restore functionality, but this is should be in tegra-specific project.
+ virtual void ClearInputFrame();
+ virtual BOOL TranslateEvent(const CHAR *inEvent);
+
+ void MarkApplicationDirty();
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICInputEventTypes.h b/src/Runtime/Source/Runtime/Include/UICInputEventTypes.h
new file mode 100644
index 00000000..bdf6a03a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICInputEventTypes.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICHash.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+// Mouse events
+const TEventCommandHash ON_MOUSEOVER = CHash::HashEventCommand("onMouseOver");
+const TEventCommandHash ON_MOUSEOUT = CHash::HashEventCommand("onMouseOut");
+const TEventCommandHash ON_GROUPEDMOUSEOVER = CHash::HashEventCommand("onGroupedMouseOver");
+const TEventCommandHash ON_GROUPEDMOUSEOUT = CHash::HashEventCommand("onGroupedMouseOut");
+
+// Crude hack to pretend mouse events are gesture events, since gesture events are all you
+// can specify in studio.
+// TODO: Fix properly, preferably by bringing back gesture support
+const TEventCommandHash ON_MOUSEDOWN = CHash::HashEventCommand("onPressureDown");
+const TEventCommandHash ON_MOUSEUP = CHash::HashEventCommand("onPressureUp");
+const TEventCommandHash ON_MOUSECLICK = CHash::HashEventCommand("onTap");
+const TEventCommandHash ON_MOUSEDBLCLICK = CHash::HashEventCommand("onDoubleTap");
+//const TEventCommandHash ON_MOUSEDOWN = CHash::HashEventCommand("onMouseDown");
+//const TEventCommandHash ON_MOUSEUP = CHash::HashEventCommand("onMouseUp");
+//const TEventCommandHash ON_MOUSECLICK = CHash::HashEventCommand("onMouseClick");
+//const TEventCommandHash ON_MOUSEDBLCLICK = CHash::HashEventCommand("onMouseDblClick");
+
+const TEventCommandHash ON_MIDDLEMOUSEDOWN = CHash::HashEventCommand("onMiddleMouseDown");
+const TEventCommandHash ON_MIDDLEMOUSEUP = CHash::HashEventCommand("onMiddleMouseUp");
+const TEventCommandHash ON_MIDDLEMOUSECLICK = CHash::HashEventCommand("onMiddleMouseClick");
+const TEventCommandHash ON_MIDDLEDBLMOUSECLICK = CHash::HashEventCommand("onMiddleMouseDblClick");
+
+const TEventCommandHash ON_RIGHTMOUSEDOWN = CHash::HashEventCommand("onRightMouseDown");
+const TEventCommandHash ON_RIGHTMOUSEUP = CHash::HashEventCommand("onRightMouseUp");
+const TEventCommandHash ON_RIGHTMOUSECLICK = CHash::HashEventCommand("onRightMouseClick");
+const TEventCommandHash ON_RIGHTDBLMOUSECLICK = CHash::HashEventCommand("onRightMouseDblClick");
+
+const TEventCommandHash ON_HORIZONTALSCROLLWHEEL =
+ CHash::HashEventCommand("onHorizontalScrollWheel");
+const TEventCommandHash ON_VERTICALSCROLLWHEEL = CHash::HashEventCommand("onVerticalScrollWheel");
+
+const TEventCommandHash ON_KEYUP =
+ CHash::HashEventCommand("onKeyUp"); ///< Studio's keyboard event string
+const TEventCommandHash ON_KEYDOWN =
+ CHash::HashEventCommand("onKeyDown"); ///< Studio's keyboard event string
+const TEventCommandHash ON_KEYREPEAT =
+ CHash::HashEventCommand("onKeyRepeat"); ///< Studio's keyboard event string
+
+const TEventCommandHash ON_BUTTONUP = CHash::HashEventCommand("onButtonUp");
+const TEventCommandHash ON_BUTTONDOWN = CHash::HashEventCommand("onButtonDown");
+const TEventCommandHash ON_BUTTONREPEAT = CHash::HashEventCommand("onButtonRepeat");
+
+const TEventCommandHash ON_AXISMOVED = CHash::HashEventCommand("onAxisMoved");
+
+// Used by UIContract
+const TEventCommandHash ON_LEFT = CHash::HashEventCommand("onLeft");
+const TEventCommandHash ON_RIGHT = CHash::HashEventCommand("onRight");
+const TEventCommandHash ON_UP = CHash::HashEventCommand("onUp");
+const TEventCommandHash ON_DOWN = CHash::HashEventCommand("onDown");
+const TEventCommandHash ON_BACK = CHash::HashEventCommand("onBack");
+const TEventCommandHash ON_SELECT = CHash::HashEventCommand("onSelect");
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICInputFrame.h b/src/Runtime/Source/Runtime/Include/UICInputFrame.h
new file mode 100644
index 00000000..be44cad8
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICInputFrame.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICPlatformSpecific.h"
+#include "UICInputDefs.h"
+
+#include <EASTL/map.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Input structure defining the values for keyboard input
+ */
+struct SKeyInputFrame
+{
+ UINT16 m_ModifierFlags; ///< Keyboard modifier state flags
+ typedef eastl::map<INT32, UINT16> MAP_KEYCODE_COUNT;
+ MAP_KEYCODE_COUNT
+ m_KeyStates; ///< Keycode map representing number of frames since the keys are down
+ ///< 0 - up, 255 - down for more than 254 frames
+
+ SKeyInputFrame()
+ : m_ModifierFlags(MODIFIER_NONE)
+ {
+ }
+
+ UINT16 GetKeyCount(INT32 inKeyCode)
+ {
+ MAP_KEYCODE_COUNT::iterator theIter = m_KeyStates.find(inKeyCode);
+ return theIter != m_KeyStates.end() ? theIter->second : 0;
+ }
+};
+
+//==============================================================================
+/**
+ * Input structure defining the values fed into input processing
+ */
+struct SInputFrame
+{
+ SKeyInputFrame m_KeyInputFrame; ///< Data for keyboard input
+
+ typedef eastl::map<INT32, UINT16> MAP_BUTTONCODE_COUNT;
+ MAP_BUTTONCODE_COUNT m_ButtonStates;
+
+ FLOAT m_AxisStates[AXIS_TOTAL_COUNT];
+
+ FLOAT m_PickX; ///< Horizontal screen location
+ FLOAT m_PickY; ///< Vertical screen location
+
+ INT32 m_MouseFlags; ///< Mouse button state flags
+
+ // SK - gesture-specific variables should NOT be in core runtime, its tegra-specific
+ INT32 m_GestureID; ///< a running counter/unique-id
+ INT32 m_GestureKind; ///< Gesture state flags
+
+ /* different gestures will interpret as different values. could be:
+ * DRAG: delta position
+ * FLICK: velocities
+ * ZOOM: second finger or quantized delta */
+ INT16 m_DeltaX;
+ INT16 m_DeltaY;
+
+ BOOL m_PickValid; ///< X and Y are valid inputs
+ INT16 m_ScrollValue; //< Value of scrollwheel scrolled
+
+ CHAR m_Padding[1];
+
+ SInputFrame()
+ : m_PickX(0)
+ , m_PickY(0)
+ , m_MouseFlags(NO_INPUT)
+ , m_GestureID(0)
+ , m_GestureKind(0)
+ , m_DeltaX(0)
+ , m_DeltaY(0)
+ , m_PickValid(false)
+ {
+ Q3DStudio_memset(m_AxisStates, 0, sizeof(m_AxisStates));
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICKernelTypes.h b/src/Runtime/Source/Runtime/Include/UICKernelTypes.h
new file mode 100644
index 00000000..879b134a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICKernelTypes.h
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICArray.h"
+
+namespace uic {
+namespace runtime {
+ namespace element {
+ struct SElement;
+ struct SComponent;
+ }
+}
+}
+
+namespace Q3DStudio {
+typedef uic::runtime::element::SElement TElement;
+typedef uic::runtime::element::SComponent TComponent;
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CString;
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef CArray<TElement *> TElementList; ///< Dynamic list of CElements
+typedef CArray<const CString *> TEventList; ///< Dynamic list of CStrings
+typedef CArray<INT32> TAssociationList; ///< Dynamic list of IDs used for the association process
+
+typedef UINT32 TEventCommandHash; ///< Value from CHash::Hash31
+typedef UINT32 TStringHash; ///< Value from CHash::Hash
+typedef UINT32 TAttributeHash; ///< Value from CHash::Hash27
+typedef UINT32 THashValue; ///< 32 bit value indicating a hash
+
+//==============================================================================
+// Enumerations
+//==============================================================================
+
+/// Each attribute knows the type of its value and uses 4 bits for this enum
+enum EAttributeType {
+ ATTRIBUTETYPE_NONE = 0,
+ ATTRIBUTETYPE_INT32,
+ ATTRIBUTETYPE_HASH,
+ ATTRIBUTETYPE_FLOAT,
+ ATTRIBUTETYPE_BOOL,
+ ATTRIBUTETYPE_STRING,
+ ATTRIBUTETYPE_POINTER,
+ ATTRIBUTETYPE_ELEMENTREF,
+ ATTRIBUTETYPE_DATADRIVEN_PARENT,
+ ATTRIBUTETYPE_DATADRIVEN_CHILD,
+ ATTRIBUTETYPE_FLOAT3,
+ ATTRIBUTETYPECOUNT
+};
+
+/// Elements represent various types of objects
+enum EElementType {
+ ELEMENTTYPE_UNKNOWN = 0,
+ ELEMENTTYPE_NODE,
+ ELEMENTTYPE_CAMERA,
+ ELEMENTTYPE_LIGHT,
+ ELEMENTTYPE_TEXT,
+ ELEMENTTYPE_MATERIAL,
+ ELEMENTTYPE_TEXTURE,
+ ELEMENTTYPE_COMPONENT,
+ ELEMENTTYPE_BEHAVIOR,
+ ELEMENTTYPE_PATH,
+ ELEMENTTYPE_PATHANCHORPOINT,
+ ELEMENTTYPE_SUBPATH,
+ ELEMENTTYPECOUNT
+};
+
+//==============================================================================
+// Enumerations
+//==============================================================================
+
+/// Various bit flags packed into a single 16bit space.
+enum EElementFlag {
+ // Persistent flags (set only at creation)
+ ELEMENTFLAG_COMPONENT = 1, ///< Element is a component
+ ELEMENTFLAG_TIMELINE = 1 << 1, ///< Element has start time and duration attributes
+ ELEMENTFLAG_CLONE = 1 << 2, ///< Element is a clone
+ ELEMENTFLAG_ATTRIBUTELOCK =
+ 1 << 3, ///< No more attributes can be added (always true during runtime)
+
+ // Configuration flags (seldom changed)
+ ELEMENTFLAG_SCRIPTCALLBACKS = 1
+ << 4, ///< At least one script has requested notify on onActivate, onDeactivate, onUpdate
+ ELEMENTFLAG_SCRIPTINITIALIZE = 1
+ << 5, ///< At least one script has requested notify on onInitialize
+ ELEMENTFLAG_REGISTEREDFORATTRIBUTECHANGE = 1 << 6, ///< Element monitored for attribute change
+ ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK = 1 << 7, ///< Element registered for event callbacks
+ ELEMENTFLAG_PICKENABLED = 1 << 8, ///< At least one script or action has registered for mouse
+ ///events based on this element
+
+ // Runtime flags
+ ELEMENTFLAG_GLOBALACTIVE =
+ 1 << 9, ///< Combination active flag based on explicit, time and parent active
+ ELEMENTFLAG_EXPLICITACTIVE = 1 << 10, ///< Explicit On/Off switch on each element
+ ELEMENTFLAG_PLAYTHROUGH = 1 << 11, ///< Playthrough slides enabled if this is a component
+ ELEMENTFLAG_DIRTY = 1 << 12, ///< Attributes or user visible flags have changed
+
+ // Flags used by the activation manager
+ ELEMENTFLAG_AMGR_TIMEACTIVE = 1 << 13, ///< Is the element alive according to time information
+};
+
+// Four byte aligned time unit structure.
+struct SAlignedTimeUnit
+{
+ UINT32 m_LowWord;
+ UINT32 m_HighWord;
+
+ SAlignedTimeUnit() {}
+ SAlignedTimeUnit(const TTimeUnit &inUnit);
+ SAlignedTimeUnit(const SAlignedTimeUnit &inOther)
+ : m_LowWord(inOther.m_LowWord)
+ , m_HighWord(inOther.m_HighWord)
+ {
+ }
+ SAlignedTimeUnit &operator=(const SAlignedTimeUnit &inOther)
+ {
+ m_LowWord = inOther.m_LowWord;
+ m_HighWord = inOther.m_HighWord;
+ return *this;
+ }
+ operator TTimeUnit() const;
+
+ void operator-=(const TTimeUnit &inTime);
+ void operator%=(const TTimeUnit &inTime);
+};
+
+//==============================================================================
+// Defines
+//==============================================================================
+#define Q3DStudio_ATTRIBUTEKEYBITS 26 /* Number of bits to store attributes index */
+#define Q3DStudio_ATTRIBUTEKEYMASK 0x03ffffff /* Bit mask covering 26 bits */
+
+//==============================================================================
+// Structs
+//==============================================================================
+
+/// Each element has a number of attributes associated with it - This is the key.
+struct SAttributeKey
+{
+ TAttributeHash m_Hash : Q3DStudio_ATTRIBUTEKEYBITS; ///< hash of attribute name
+ TAttributeHash m_Type : 4; ///< Attribute type such as INT32, FLOAT, STRING
+ TAttributeHash m_Dirty : 1; ///< Dirty bit signalling that the attribute value has been modified
+ TAttributeHash
+ m_DontOptimize : 1; ///< Used by the exporter/optimizer to flag attributes as un-optimizable
+
+ void Convert(const UINT32 &inKey)
+ {
+ m_Hash = inKey & Q3DStudio_ATTRIBUTEKEYMASK;
+ m_Type = (inKey & 0x3c000000) >> Q3DStudio_ATTRIBUTEKEYBITS;
+ m_Dirty = (inKey & 0x40000000) >> (Q3DStudio_ATTRIBUTEKEYBITS + 4);
+ m_DontOptimize = (inKey & 0x80000000) >> (Q3DStudio_ATTRIBUTEKEYBITS + 5);
+ }
+};
+
+/// The structure to store a memory pool for clones.
+/// The actual data pool will start at the address after these 8 bytes.
+struct SClone
+{
+ SClone *m_Next; ///< Pointer to the next block of memory
+ UINT32 m_Size; ///< Size of the current block of memory
+};
+
+//==============================================================================
+// Unions
+//==============================================================================
+
+/// Each element has a number of attributes associated with it - This is the value.
+union UVariant {
+ INT32 m_INT32; ///< Integer representation
+ FLOAT m_FLOAT; ///< Float representation
+ THashValue m_Hash; ///< Explicit hash representation
+ UINT32 m_StringHandle; ///< Handle into the IStringTable member of the presentation
+ void *m_VoidPointer; ///< Generic data Pointer
+ UINT32 m_ElementHandle; ///< Element handle. Resolve using IApplication object.
+ FLOAT m_FLOAT3[3]; ///< Vector 3 representation
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLogicSystem.h b/src/Runtime/Source/Runtime/Include/UICLogicSystem.h
new file mode 100644
index 00000000..a9d23f2a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLogicSystem.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_LOGIC_SYSTEM_H
+#define UIC_LOGIC_SYSTEM_H
+#include "UICElementSystem.h"
+
+namespace uic {
+namespace runtime {
+
+ class ILogicSystem : public NVRefCounted
+ {
+ public:
+ // returns the action id
+ virtual QT3DSI32 AddAction(element::SElement &inTrigger,
+ Q3DStudio::TEventCommandHash inEventNameHash,
+ element::SElement *inTarget, element::SElement *inOwner,
+ Q3DStudio::TEventCommandHash inType, Q3DStudio::UVariant inArg1,
+ Q3DStudio::UVariant inArg2, bool inActive) = 0;
+
+ virtual void OnEvent(Q3DStudio::TEventCommandHash inEventName, element::SElement &inTarget,
+ Q3DStudio::IPresentation &inPresentation) const = 0;
+ virtual void SetActive(QT3DSI32 inActionIndex, bool inActive,
+ IElementAllocator &inElemAllocator) = 0;
+
+ virtual void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) = 0;
+ virtual void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData) = 0;
+
+ static ILogicSystem &CreateLogicSystem(NVFoundationBase &inFnd);
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaAxis.h b/src/Runtime/Source/Runtime/Include/UICLuaAxis.h
new file mode 100644
index 00000000..829e2df6
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaAxis.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+class CLuaAxis
+{
+protected:
+ CLuaAxis(){} // Hide constructor
+
+public:
+ static void RegisterLibrary(lua_State *inLuaState);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaButton.h b/src/Runtime/Source/Runtime/Include/UICLuaButton.h
new file mode 100644
index 00000000..765842d9
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaButton.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+class CLuaButton
+{
+protected:
+ CLuaButton(){} // Hide constructor
+
+public:
+ static void RegisterLibrary(lua_State *inLuaState);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaColor.h b/src/Runtime/Source/Runtime/Include/UICLuaColor.h
new file mode 100644
index 00000000..53b98b6a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaColor.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CColor;
+
+//==============================================================================
+/**
+ * The "Color" type for implementation for Lua
+ */
+class CLuaColor
+{
+protected: // Construction
+ CLuaColor();
+ CLuaColor(const CLuaColor &);
+ CLuaColor &operator=(const CLuaColor &);
+ ~CLuaColor();
+
+public: // Color Registration
+ static void RegisterLibrary(lua_State *inLuaState);
+
+protected: // Creation / Initialization
+ static int Create(lua_State *inLuaState);
+ static int GetValue(lua_State *inLuaState);
+ static int SetValue(lua_State *inLuaState);
+ static int SetColor(lua_State *inLuaState);
+ static int Set(lua_State *inLuaState);
+
+protected: // Operators
+ static int Equals(lua_State *inLuaState);
+
+protected: // Format
+ static int ToString(lua_State *inLuaState);
+
+public:
+ static CColor &CreateColor(lua_State *inLuaState);
+ static CColor &CheckColor(lua_State *inLuaState, const INT32 inIndex = 1);
+
+protected: // Hidden Helpers
+ static UINT8 GetColorValue(lua_State *inLuaState, const INT32 inIndex);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaCommandHelper.h b/src/Runtime/Source/Runtime/Include/UICLuaCommandHelper.h
new file mode 100644
index 00000000..397b136d
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaCommandHelper.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+#include "UICIComponentManager.h"
+#include "UICLuaEngine.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CPresentation;
+class IElementManager;
+
+//==============================================================================
+/**
+ * Helper class handling command operations
+ */
+class CLuaCommandHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CLuaCommandHelper();
+ CLuaCommandHelper(const CLuaCommandHelper &);
+ CLuaCommandHelper &operator=(const CLuaCommandHelper &);
+ virtual ~CLuaCommandHelper();
+
+public: // Lua Global Functions
+ static int Play(lua_State *inLuaState);
+ static int Pause(lua_State *inLuaState);
+ static int GoToTime(lua_State *inLuaState);
+ static int GoToSlide(lua_State *inLuaState);
+ static int GoToNextSlide(lua_State *inLuaState);
+ static int GoToPreviousSlide(lua_State *inLuaState);
+ static int GoToBackSlide(lua_State *inLuaState);
+
+ static bool SetupGotoSlideCommand(TElement &inElement, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs);
+ static bool SetupGotoSlideCommand(TElement &inElement, Q3DStudio::INT32 inSlide,
+ const SScriptEngineGotoSlideArgs &inArgs);
+
+protected: // Static Hidden Helpers
+ static TElement *FireCommand(lua_State *inLuaState, TEventCommandHash inCommand);
+
+public: // Static Helpers
+ static TElement *GetComponentParent(TElement *inParent);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaElementHelper.h b/src/Runtime/Source/Runtime/Include/UICLuaElementHelper.h
new file mode 100644
index 00000000..6c075b06
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaElementHelper.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+namespace uic {
+namespace runtime {
+ class IApplication;
+}
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+class IPresentation;
+//==============================================================================
+/**
+ * Helper class handling element operations
+ */
+class CLuaElementHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CLuaElementHelper();
+ CLuaElementHelper(const CLuaElementHelper &);
+ CLuaElementHelper &operator=(const CLuaElementHelper &);
+ virtual ~CLuaElementHelper();
+
+public: // Lua Global Functions
+ static TElement *GetElement(uic::runtime::IApplication &inApplication,
+ IPresentation *inDefaultPresentation, const char *inPath,
+ TElement *inStartElement = NULL);
+ static int GetElement(lua_State *inLuaState);
+ static int GetElementType(lua_State *inLuaState);
+ static int GetAttribute(lua_State *inLuaState);
+ static int SetAttribute(lua_State *inLuaState);
+ // Set attribute, expecting the attribute value to be top of the stack.
+ static bool SetAttribute(lua_State *inLuaState, TElement *inElement, const char *inAttribute,
+ bool inDelay);
+ static int HasAttribute(lua_State *inLuaState);
+ static int GetChildren(lua_State *inLuaState);
+ static int GetCurrentSlide(lua_State *inLuaState);
+ static int GetTime(lua_State *inLuaState);
+ static int CalculateBoundingBox(lua_State *inLuaState);
+ static int CalculateGlobalTransform(lua_State *inLuaState);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaEngine.h b/src/Runtime/Source/Runtime/Include/UICLuaEngine.h
new file mode 100644
index 00000000..e598159d
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaEngine.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Studio Includes
+//==============================================================================
+#include "UICIScriptBridge.h"
+#include "EASTL/map.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICIComponentManager.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSMutex.h"
+
+namespace uic {
+namespace state {
+ class IStateInterpreter;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CPresentation;
+class ITimeProvider;
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef void (*TLuaLibraryLoader)(lua_State *);
+
+//==============================================================================
+// Global Lua Library Loader
+//==============================================================================
+extern TLuaLibraryLoader LoadLuaLibraries;
+
+extern const INT32 KEY_PRESENTATION;
+extern const INT32 KEY_BEHAVIORS;
+extern const INT32 KEY_EVENTDATA_LIST;
+extern const INT32 KEY_CHANGEDATA_LIST;
+extern const INT32 KEY_CALLBACKS;
+extern const INT32 KEY_REGISTEREDCALLBACKS;
+
+extern const THashValue HASH_ONINITIALIZE;
+extern const THashValue HASH_ONACTIVATE;
+extern const THashValue HASH_ONDEACTIVATE;
+extern const THashValue HASH_ONUPDATE;
+
+extern const UINT32 LENGTH_KEY_ELEMENT;
+extern const UINT32 LENGTH_KEY_SELF;
+extern const UINT32 LENGTH_KEY_SCRIPT_INDEX;
+extern const UINT32 LENGTH_KEY_ONINITIALIZE;
+extern const UINT32 LENGTH_KEY_ONACTIVATE;
+extern const UINT32 LENGTH_KEY_ONDEACTIVATE;
+extern const UINT32 LENGTH_KEY_ONUPDDATE;
+
+class CLuaEngine : public IScriptBridge
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ struct SCallbackData
+ {
+ INT32 m_FunctionReference; ///< The Lua function to call when it occurs
+ TElement *m_TargetElement; ///< The source element where the event is going to occur
+
+ /* The behavior element that the lua code is executing from. May be null in the case of
+ * application behaviors */
+ TElement *m_SelfElement;
+ THashValue m_EventAttributeHash; ///< The event hash or the attribute hash
+ lua_State *m_LuaState; ///< The associated lua state
+ INT16 m_Global; ///< Is the function a global function or it resides in self
+ INT16 m_ScriptIndex; ///< The associated script index if the function is a local function
+ };
+
+ typedef CArray<SCallbackData *> TCallbackDataList;
+
+ virtual ~CLuaEngine() {}
+
+public: // Public functions but not functions on the script bridge
+ virtual uic::state::IStateInterpreter *
+ CreateStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodelFunction) = 0;
+ virtual void PreInitialize() = 0;
+ virtual void Initialize() = 0;
+ virtual void Shutdown(qt3ds::NVFoundationBase &inFoundation) = 0;
+ // use lua_register to register a global function, this is useful to call from outside
+ virtual void AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction) = 0;
+
+public: // Static Helpers
+ static void FreeCallbackData(SCallbackData *inData);
+ static CPresentation *GetCurrentPresentation(lua_State *inLuaState);
+ static void SetAdditionalSharedLibraryPath(const eastl::string &inAdditionalSharedLibraryPath);
+ static CLuaEngine *Create(qt3ds::NVFoundationBase &inFoundation, ITimeProvider &inTimeProvider);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaEventHelper.h b/src/Runtime/Source/Runtime/Include/UICLuaEventHelper.h
new file mode 100644
index 00000000..6bf077bd
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaEventHelper.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Studio Includes
+//==============================================================================
+#include "UICLuaEngine.h"
+#include "UICEvent.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Helper class handling event operations
+ */
+class CLuaEventHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CLuaEventHelper();
+ CLuaEventHelper(const CLuaEventHelper &);
+ CLuaEventHelper &operator=(const CLuaEventHelper &);
+ virtual ~CLuaEventHelper();
+
+public: // Lua Global Functions
+ static int FireEvent(lua_State *inLuaState);
+ static int RegisterForEvent(lua_State *inLuaState);
+ static int UnRegisterForEvent(lua_State *inLuaState);
+ // static int RegisterForChange( lua_State* inLuaState );
+ // static int UnRegisterForChange( lua_State* inLuaState );
+
+protected: // Callbacks
+ static void EventCallback(void *inContextData, SEventCommand &ioEvent);
+ static void ChangeCallback(const SAttributeKey &inAttributeKey, UVariant inOldValue,
+ UVariant inNewValue, void *inContextData);
+
+protected: // Helper
+ static INT32 FindCallbackData(lua_State *inLuaState, CLuaEngine::TCallbackDataList *inDataList,
+ CLuaEngine::SCallbackData *inCriteria,
+ const INT32 inFunctionIndex);
+ static void EventRegistration(lua_State *inLuaState, const INT32 inRegister);
+ // static void ChangeRegistration( lua_State* inLuaState, const INT32 inRegister
+ // );
+ static BOOL IsFunctionInSelfTable(lua_State *inLuaState, const INT32 inFunctionIndex,
+ const INT32 inSelfIndex);
+ static void PushSelfOnTop(lua_State *inLuaState, const INT32 inSelfIndex);
+ static TElement *GetSelfElement(lua_State *inLuaState, const INT32 inSelfIndex);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaHelper.h b/src/Runtime/Source/Runtime/Include/UICLuaHelper.h
new file mode 100644
index 00000000..c1e2fc79
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaHelper.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+namespace qt3ds {
+namespace foundation {
+ class IStringTable;
+}
+}
+
+namespace uic {
+namespace runtime {
+ class IApplication;
+}
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+//==============================================================================
+/**
+ * Helper class for lua operations
+ */
+class CLuaHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CLuaHelper();
+ CLuaHelper(const CLuaHelper &);
+ CLuaHelper &operator=(const CLuaHelper &);
+ virtual ~CLuaHelper();
+
+public: // Lua Global Functions
+ static UINT8 GetArgument(lua_State *inLuaState, INT32 inIndex, UVariant &outValue,
+ qt3ds::foundation::IStringTable &strTable,
+ uic::runtime::IApplication &application);
+
+ static INT32 PushArgument(lua_State *inLuaState, const UINT8 inType, UVariant &inValue,
+ qt3ds::foundation::IStringTable &strTable,
+ uic::runtime::IApplication &application);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaIncludes.h b/src/Runtime/Source/Runtime/Include/UICLuaIncludes.h
new file mode 100644
index 00000000..d50e6e53
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaIncludes.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaKeyboard.h b/src/Runtime/Source/Runtime/Include/UICLuaKeyboard.h
new file mode 100644
index 00000000..c939849d
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaKeyboard.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+class CLuaKeyboard
+{
+protected:
+ CLuaKeyboard(){} // Hide constructor
+
+public:
+ static void RegisterLibrary(lua_State *inLuaState);
+ static int GetKeyState(lua_State *inLuaState);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaMatrix.h b/src/Runtime/Source/Runtime/Include/UICLuaMatrix.h
new file mode 100644
index 00000000..b12eae03
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaMatrix.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeMatrix;
+
+//==============================================================================
+/**
+ * The "Matrix" type for implementation for Lua
+ */
+class CLuaMatrix
+{
+protected: // Construction
+ CLuaMatrix();
+ CLuaMatrix(const CLuaMatrix &);
+ CLuaMatrix &operator=(const CLuaMatrix &);
+ ~CLuaMatrix();
+
+public: // Matrix Registration
+ static void RegisterLibrary(lua_State *inLuaState);
+
+protected: // Creation / Initialization
+ static int Create(lua_State *inLuaState);
+ static int GetValue(lua_State *inLuaState);
+ static int SetValue(lua_State *inLuaState);
+ static int SetMatrix(lua_State *inLuaState);
+ static int Set(lua_State *inLuaState);
+ static int SetScale(lua_State *inLuaState);
+ static int SetRotate(lua_State *inLuaState);
+ static int SetTranslate(lua_State *inLuaState);
+
+protected: // Operators
+ static int Equals(lua_State *inLuaState);
+
+protected: // Functions
+ static int Identity(lua_State *inLuaState);
+ static int Invert(lua_State *inLuaState);
+ static int IsIdentity(lua_State *inLuaState);
+ static int Multiply(lua_State *inLuaState);
+ static int Scale(lua_State *inLuaState);
+ static int Translate(lua_State *inLuaState);
+ static int Rotate(lua_State *inLuaState);
+ static int Transpose(lua_State *inLuaState);
+
+protected: // Format
+ static int ToString(lua_State *inLuaState);
+
+protected: // Hidden Helpers
+ static RuntimeMatrix &CreateMatrix(lua_State *inLuaState);
+
+public: // Helpers
+ static RuntimeMatrix &CheckMatrix(lua_State *inLuaState, const INT32 inIndex = 1);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaRotation.h b/src/Runtime/Source/Runtime/Include/UICLuaRotation.h
new file mode 100644
index 00000000..78601e2c
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaRotation.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CRotation;
+class RuntimeVector3;
+
+//==============================================================================
+/**
+ * The "Rotation" type for implementation for Lua
+ */
+class CLuaRotation
+{
+protected: // Construction
+ CLuaRotation();
+ CLuaRotation(const CLuaRotation &);
+ CLuaRotation &operator=(const CLuaRotation &);
+ ~CLuaRotation();
+
+public: // Rotation Registration
+ static void RegisterLibrary(lua_State *inLuaState);
+
+protected: // Creation / Initialization
+ static int Create(lua_State *inLuaState);
+ static int GetValue(lua_State *inLuaState);
+ static int SetValue(lua_State *inLuaState);
+ static int SetRotation(lua_State *inLuaState);
+ static int Set(lua_State *inLuaState);
+
+protected: // Operators
+ static int Add(lua_State *inLuaState);
+ static int AddNew(lua_State *inLuaState);
+ static int Subtract(lua_State *inLuaState);
+ static int SubtractNew(lua_State *inLuaState);
+ static int Scale(lua_State *inLuaState);
+ static int ScaleNew(lua_State *inLuaState);
+ static int Equals(lua_State *inLuaState);
+
+protected: // Functions
+ static int LookAt(lua_State *inLuaState);
+
+protected: // Format
+ static int ToString(lua_State *inLuaState);
+
+protected: // Hidden Helpers
+ static RuntimeVector3 &CreateRotation(lua_State *inLuaState);
+ static RuntimeVector3 &CheckRotation(lua_State *inLuaState, const INT32 inIndex = 1);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaSceneHelper.h b/src/Runtime/Source/Runtime/Include/UICLuaSceneHelper.h
new file mode 100644
index 00000000..257ae076
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaSceneHelper.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Helper class handling scene related operations
+ */
+class CLuaSceneHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CLuaSceneHelper();
+ CLuaSceneHelper(const CLuaSceneHelper &);
+ CLuaSceneHelper &operator=(const CLuaSceneHelper &);
+ virtual ~CLuaSceneHelper();
+
+public: // Lua Global Functions
+ static int CalculateGlobalOpacity(lua_State *inLuaState);
+ static int CalculateBoundingBox(lua_State *inLuaState);
+ static int CalculateLocalBoundingBox(lua_State *inLuaState);
+ static int CalculateGlobalTransform(lua_State *inLuaState);
+ // static int Clone( lua_State* inLuaState );
+ static int GetImageInfo(lua_State *inLuaState);
+ static int SetLocalTransformMatrix(lua_State *inLuaState);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICLuaVector.h b/src/Runtime/Source/Runtime/Include/UICLuaVector.h
new file mode 100644
index 00000000..e35c0be1
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICLuaVector.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Lua Includes
+//==============================================================================
+#include "UICLuaIncludes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeVector3;
+
+//==============================================================================
+/**
+ * The "Vector" type implementation for Lua
+ */
+class CLuaVector
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ static const CHAR *STRING_VECTOR_TYPE;
+ static const CHAR *STRING_VECTOR_CLASS;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+protected: // Construction
+ CLuaVector();
+ CLuaVector(const CLuaVector &);
+ CLuaVector &operator=(const CLuaVector &);
+ ~CLuaVector();
+
+public: // Vector Registration
+ static void RegisterLibrary(lua_State *inLuaState);
+
+protected: // Creation / Initialization
+ static int Create(lua_State *inLuaState);
+ static int GetValue(lua_State *inLuaState);
+ static int SetValue(lua_State *inLuaState);
+ static int SetVector(lua_State *inLuaState);
+ static int Set(lua_State *inLuaState);
+
+protected: // Operators
+ static int Add(lua_State *inLuaState);
+ static int AddNew(lua_State *inLuaState);
+ static int Subtract(lua_State *inLuaState);
+ static int SubtractNew(lua_State *inLuaState);
+ static int Scale(lua_State *inLuaState);
+ static int ScaleNew(lua_State *inLuaState);
+ static int Equals(lua_State *inLuaState);
+ static int DotProduct(lua_State *inLuaState);
+ static int CrossProduct(lua_State *inLuaState);
+
+protected: // Functions
+ static int Normalize(lua_State *inLuaState);
+ static int Length(lua_State *inLuaState);
+ static int LengthSquared(lua_State *inLuaState);
+ static int Distance(lua_State *inLuaState);
+ static int DistanceSquared(lua_State *inLuaState);
+ static int MinVector(lua_State *inLuaState);
+ static int MaxVector(lua_State *inLuaState);
+ static int Linear(lua_State *inLuaState);
+ static int Transform(lua_State *inLuaState);
+
+protected: // Format
+ static int ToString(lua_State *inLuaState);
+
+public: // Helpers
+ static RuntimeVector3 &CheckVector(lua_State *inLuaState, const INT32 inIndex = 1);
+ static RuntimeVector3 &CreateVector(lua_State *inLuaState);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICOutputMemoryStream.h b/src/Runtime/Source/Runtime/Include/UICOutputMemoryStream.h
new file mode 100644
index 00000000..462ed5f7
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICOutputMemoryStream.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICHash.h"
+#ifdef _WIN32
+#pragma warning(push)
+#pragma warning(disable : 4820) // X bytes padding added after data member
+#pragma warning( \
+ disable : 4061) // enumerator X in switch of enum Y is not explicitly handled by a case label
+#pragma warning(disable : 4062) // enumerator X in switch of enum Y is not handled
+#pragma warning(disable : 4548) // xlocale warnings
+#pragma warning( \
+ disable : 4738) // storing 32-bit float result in memory, possible loss of performance
+#endif
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Class
+//==============================================================================
+class COutputMemoryStream
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ std::vector<UINT8> m_Data;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ COutputMemoryStream();
+ virtual ~COutputMemoryStream();
+
+public: // Access
+ void Reset();
+ UINT32 GetSize() const;
+ const UINT8 *GetData() const;
+
+public: // Output
+ void WriteStringHash(const CHAR *inItem);
+ void WriteEventCommandHash(const CHAR *inItem);
+
+public: // Operators
+ COutputMemoryStream &operator<<(const COutputMemoryStream &inStream);
+ COutputMemoryStream &operator<<(const std::string &inString);
+ COutputMemoryStream &operator<<(const EAttributeType inType);
+
+ //==============================================================================
+ // Template Methods
+ //==============================================================================
+public:
+ template <typename T>
+ COutputMemoryStream &operator<<(const T &inItem)
+ {
+ size_t theSize = sizeof(T);
+ const UINT8 *thePtr = reinterpret_cast<const UINT8 *>(&inItem);
+ for (size_t theCounter = 0; theCounter < theSize; ++theCounter) {
+ m_Data.push_back(*thePtr);
+ ++thePtr;
+ }
+ return *this;
+ }
+
+ template <typename T>
+ void SetData(const T &inItem, UINT32 inByteOffset)
+ {
+ UINT8 *theSourcePtr = &m_Data[inByteOffset];
+ size_t theSize = sizeof(T);
+ const UINT8 *thePtr = reinterpret_cast<const UINT8 *>(&inItem);
+ for (size_t theCounter = 0; theCounter < theSize; ++theCounter) {
+ *theSourcePtr = *thePtr;
+ ++thePtr;
+ ++theSourcePtr;
+ }
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICParametersSystem.h b/src/Runtime/Source/Runtime/Include/UICParametersSystem.h
new file mode 100644
index 00000000..9fc8051a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICParametersSystem.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_PARAMETERS_SYSTEM_H
+#define UIC_PARAMETERS_SYSTEM_H
+#pragma once
+#include "UICKernelTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/utility.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+namespace foundation {
+ class IOutStream;
+}
+}
+
+namespace uic {
+namespace runtime {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+
+ typedef eastl::pair<QT3DSU32, Q3DStudio::UVariant> TIdValuePair;
+
+ class IParametersSystem : public NVRefCounted
+ {
+ public:
+ virtual QT3DSI32 CreateParameterGroup() = 0;
+ virtual void AddParameter(QT3DSI32 inGroup, QT3DSU32 inNameHash, Q3DStudio::UVariant inParam) = 0;
+
+ virtual QT3DSU32 GetNumParameters(QT3DSI32 inGroupId) const = 0;
+ virtual TIdValuePair GetParameter(QT3DSI32 inGroupId, QT3DSU32 inIndex) const = 0;
+
+ virtual void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) = 0;
+ virtual void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData) = 0;
+
+ static IParametersSystem &CreateParametersSystem(NVFoundationBase &inFoundation);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/Runtime/Include/UICPickFrame.h b/src/Runtime/Source/Runtime/Include/UICPickFrame.h
new file mode 100644
index 00000000..9019bc39
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICPickFrame.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICInputFrame.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IPresentation;
+
+//==============================================================================
+/**
+ * Reporting structure describing a complete mouse pick including initial
+ * mouse XY screen position, which element was hit, UV point of hit, global
+ * intersection point and more.
+ */
+struct SPickFrame
+{
+ SInputFrame m_InputFrame; ///< Input values to process
+
+ FLOAT m_PickOrigin[3]; ///< 3D pick ray start
+ FLOAT m_PickDirection[3]; ///< 3D pick ray direction
+
+ FLOAT m_LocalHit[2]; ///< 2D pick ray intersection
+ FLOAT m_SquaredDistance; ///< Distance from camera to intersection
+ TElement *m_Model; ///< Element picked
+ // IPresentation* m_SubPresentation; ///< The picked element has a subpresentation
+
+ BOOL m_ResultValid; ///< Model found - Whole structure is valid
+ INT8 m_Unused[3]; ///< Padding
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICPresentation.h b/src/Runtime/Source/Runtime/Include/UICPresentation.h
new file mode 100644
index 00000000..98cb34b7
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICPresentation.h
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "RuntimePrefix.h"
+#include "UICIPresentation.h"
+#include "UICPresentationFrameData.h"
+#include "UICAnimationSystem.h"
+#include "UICCircularArray.h"
+#include "UICEventCallbacks.h"
+#include "UICTimePolicy.h"
+#include "EASTL/hash_map.h"
+#include "foundation/StringTable.h"
+#include "UICComponentManager.h"
+
+#include <QObject>
+
+class QPresentationSignalProxy : public QObject
+{
+ Q_OBJECT
+Q_SIGNALS:
+ void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
+ void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
+};
+
+namespace uic {
+namespace runtime {
+ class IApplication;
+ class IActivityZone;
+}
+}
+
+namespace uic {
+namespace render {
+ class ILoadedBuffer;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+//==============================================================================
+/**
+ * Intelligent representation of a Studio presentation.
+ */
+class CPresentation : public IPresentation
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ QString m_Name; ///< Name of ths presentation
+ QString m_FilePath; ///< The full path from which this presentation was loaded
+ uic::runtime::IApplication *m_Application; ///< Runtime object
+ IScene *m_Scene; ///< Connection to the associated scene (render) for this presentation
+ uic::runtime::IActivityZone *m_ActivityZone; ///< Controls element active status.
+ TElement *m_RootElement;
+
+ CPresentationFrameData m_FrameData; ///< Storage of data of the current frame
+ CCircularArray<SEventCommand> m_EventCommandQueue; ///< The Event/Command integrated queue
+ bool m_IsProcessingEventCommandQueue;
+ CEventCallbacks m_EventCallbacks; ///< Handles event callbacks on registered elements
+ SPresentationSize m_Size; ///< Native width, height and mode exported from Studio
+
+ qt3ds::foundation::NVScopedRefCounted<uic::render::ILoadedBuffer>
+ m_LoadedBuffer; ///< Reference to loaded data when loading from binary.
+
+ CComponentManager m_ComponentManager;
+ qt3ds::foundation::NVScopedRefCounted<ISlideSystem>
+ m_SlideSystem; ///< Container and factory of all logics
+ qt3ds::foundation::NVScopedRefCounted<ILogicSystem>
+ m_LogicSystem; ///< Container and factory of all logics
+ qt3ds::foundation::NVScopedRefCounted<IAnimationSystem>
+ m_AnimationSystem; ///< Container and factory of all animation tracks
+ qt3ds::foundation::NVScopedRefCounted<IParametersSystem>
+ m_ParametersSystem; ///< Container and factory of all custom actions
+
+ TTimeUnit m_Offset;
+ TTimeUnit m_LocalTime;
+ TTimeUnit m_PreviousGlobalTime;
+ bool m_Paused;
+ bool m_OffsetInvalid;
+ bool m_Active;
+
+ typedef eastl::hash_map<TElement *, qt3ds::foundation::CRegisteredString> TElemStringMap;
+ TElemStringMap m_ElementPathMap;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CPresentation(const CHAR *inName, uic::runtime::IApplication *inRuntime);
+ virtual ~CPresentation();
+
+public: // Execution
+ void Initialize();
+ // Clear dirty elements
+ void ClearDirtyList() override;
+ // Run events
+ void PreUpdate(const TTimeUnit inGlobalTime) override;
+ // update element graph
+ void BeginUpdate() override;
+ // end update element graph
+ void EndUpdate() override;
+ // Run behaviors.
+ void PostUpdate(const TTimeUnit inGlobalTime) override;
+
+public: // Bridge Control
+ IScene *GetScene() const override;
+ IScriptBridge *GetScriptBridge() override;
+ IScriptBridge *GetScriptBridgeQml() override;
+ void SetScene(IScene *inScene) override;
+
+ void SetActivityZone(uic::runtime::IActivityZone *inZone);
+ uic::runtime::IActivityZone *GetActivityZone() override { return m_ActivityZone; }
+ void SetActive(bool inValue);
+ bool GetActive() const;
+ TElement *GetRoot() override { return m_RootElement; }
+ void SetRoot(TElement &inRoot) override { m_RootElement = &inRoot; }
+
+public: // Commands and Events
+ void FireEvent(const SEventCommand &inEvent);
+ void FireEvent(const TEventCommandHash inEventType, TElement *inTarget,
+ const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
+ const EAttributeType inType2 = ATTRIBUTETYPE_NONE) override;
+ void FireCommand(const TEventCommandHash inCommandType, TElement *inTarget,
+ const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
+ const EAttributeType inType2 = ATTRIBUTETYPE_NONE) override;
+ void FlushEventCommandQueue(void) override;
+ void ProcessEvent(SEventCommand &inEvent) override;
+
+ QPresentationSignalProxy *signalProxy();
+
+public: // Event Callbacks
+ void RegisterEventCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData) override;
+ BOOL UnregisterEventCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData) override;
+
+protected: // Execution Helper Methods
+ void ProcessAllCallbacks();
+ BOOL ProcessEventCommandQueue();
+ void ProcessEvent(SEventCommand &ioEvent, INT32 &ioEventCount);
+ void ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventCount);
+ void ProcessCommand(const SEventCommand &inCommand);
+
+public: // Managers
+ IComponentManager &GetComponentManager() override;
+ ISlideSystem &GetSlideSystem() override;
+ IAnimationSystem &GetAnimationSystem() override;
+ ILogicSystem &GetLogicSystem() override;
+ IParametersSystem &GetParametersSystem() override;
+ qt3ds::foundation::IStringTable &GetStringTable() override;
+ uic::runtime::IApplication &GetApplication() override
+ {
+ QT3DS_ASSERT(m_Application);
+ return *m_Application;
+ }
+ void SetLoadedBuffer(uic::render::ILoadedBuffer &inBuffer);
+
+ void SetElementPath(TElement &inElement, const char8_t *inPath) override;
+ qt3ds::foundation::CRegisteredString GetElementPath(TElement &inElement) override;
+
+public: // Helpers
+ CPresentationFrameData &GetFrameData() override;
+ TTimeUnit GetTime() { return m_LocalTime; }
+
+public: // Hooks and callbacks
+ void OnPresentationLoaded() override;
+
+public: // Configuration access
+ SPresentationSize GetSize() const override;
+ BOOL GetPause() const;
+ const CHAR *GetName() const;
+ const CHAR *GetScenePath() const;
+
+ void SetSize(const SPresentationSize &inSize) override;
+ void SetPause(const BOOL inPause);
+ void SetHide(const BOOL inHide);
+ void SetUpdateLock(const BOOL inLockUpdate);
+ void SetVCAA(const BOOL inVCAA);
+
+public: // Full file path
+ void SetFilePath(const CHAR *inPath) override;
+ QString GetFilePath() override;
+
+private: // Disabled Copy Construction
+ CPresentation(CPresentation &);
+ CPresentation &operator=(const CPresentation &);
+private:
+ QPresentationSignalProxy m_SignalProxy;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICPresentationFrameData.h b/src/Runtime/Source/Runtime/Include/UICPresentationFrameData.h
new file mode 100644
index 00000000..332cc84a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICPresentationFrameData.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Presentation update cycle data storage class.
+ *
+ * This is the data collected from the Presentation on each frame. Other subsystems
+ * or external system uses these data to perform their specific operation
+ */
+class CPresentationFrameData
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ TElementList m_DirtyList; ///< List of elements with modified attributes
+ TElementList m_TraversalList; ///< List of active elements
+ TElementList m_ScriptsList; ///< List of elements where scripts are active
+ TElementList
+ m_ActivationList; ///< List of elements whose global active flips from false to true
+ TElementList
+ m_DeactivationList; ///< List of elements whose global active flops from true to false
+ // TElementList m_SlideExitList; ///< List of components that exits their
+ // slides
+ // TElementList m_SlideEnterList; ///< List of components that enters their
+ // slides
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CPresentationFrameData();
+ void Reserve(const INT32 inElementCount);
+
+public: // Data Management
+ void Reset();
+
+ TElementList &GetDirtyList() { return m_DirtyList; }
+ TElementList &GetTraversalList() { return m_TraversalList; }
+ TElementList &GetScriptsList() { return m_ScriptsList; }
+ TElementList &GetActivationList() { return m_ActivationList; }
+ TElementList &GetDeactivationList() { return m_DeactivationList; }
+ // TElementList& GetSlideExitList( ) { return m_SlideExitList;
+ // }
+ // TElementList& GetSlideEnterList( ) { return m_SlideEnterList; }
+
+private: // Disabled Copy Construction
+ CPresentationFrameData(const CPresentationFrameData &);
+ CPresentationFrameData &operator=(const CPresentationFrameData &);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICQmlElementHelper.h b/src/Runtime/Source/Runtime/Include/UICQmlElementHelper.h
new file mode 100644
index 00000000..ed82af78
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICQmlElementHelper.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UICQMLELEMENTHELPER_H
+#define UICQMLELEMENTHELPER_H
+
+#include "UICApplication.h"
+#include "UICPresentation.h"
+#include "UICKernelTypes.h"
+
+namespace Q3DStudio {
+//==============================================================================
+/**
+* Helper class handling element operations
+*/
+class CQmlElementHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CQmlElementHelper();
+ virtual ~CQmlElementHelper();
+
+public: // Lua Global Functions
+ static TElement *GetElement(uic::runtime::IApplication &inApplication,
+ IPresentation *inDefaultPresentation, const char *inPath,
+ TElement *inStartElement = NULL);
+
+ // Set attribute
+ static bool SetAttribute(TElement *inElement, const char *inAttribute, const void *value,
+ bool inDelay);
+ // Get attribute
+ static bool GetAttribute(TElement *inElement, const char *inAttribute, void *value);
+};
+}
+
+#endif // UICQMLELEMENTHELPER_H
diff --git a/src/Runtime/Source/Runtime/Include/UICQmlEngine.h b/src/Runtime/Source/Runtime/Include/UICQmlEngine.h
new file mode 100644
index 00000000..fccce025
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICQmlEngine.h
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-20016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef UIC_QML_ENGINE_H
+#define UIC_QML_ENGINE_H
+
+#include "UICIScriptBridge.h"
+#include "UICIComponentManager.h"
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSMutex.h"
+#include "UICTimer.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+
+namespace Q3DStudio {
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef void (*TScriptCallback)(void *inUserData);
+
+//==============================================================================
+// Defines
+//==============================================================================
+#define SCRIPT_ON_INITIALIZE 1
+#define SCRIPT_ON_UPDATE 2
+
+//==============================================================================
+// Forwards
+//==============================================================================
+struct SEventCommand;
+class IPresentation;
+
+//==============================================================================
+/**
+* Manages the various events callbacks in the system. It fires the
+* registered callbacks when an event was triggered.
+*/
+class CScriptCallbacks
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+protected:
+ struct SScriptCallbackEntry
+ {
+ SScriptCallbackEntry() {}
+ ~SScriptCallbackEntry() {}
+
+ TScriptCallback m_Function; ///< Callback function pointer
+ void *m_UserData; ///< User data
+ Q3DStudio::UINT32
+ m_CallbackType; ///< callback type. determines when and/or how often it is called
+ bool m_Processed; ///< Only used if the callback is of
+
+ private: // Disabled Copy Construction
+ SScriptCallbackEntry(const SScriptCallbackEntry &);
+ SScriptCallbackEntry &operator=(const SScriptCallbackEntry &);
+ };
+ typedef CArray<SScriptCallbackEntry *> TCallbackList; ///< Array of callbacks regisgtered
+
+ struct SFrameCallbackEntry
+ {
+ SFrameCallbackEntry() {}
+ ~SFrameCallbackEntry()
+ {
+ FOR_ARRAY(SScriptCallbackEntry *, theEntry, m_Callbacks)
+ Q3DStudio_delete(*theEntry, SScriptCallbackEntry);
+ }
+
+ TCallbackList m_Callbacks; ///< List of callbacks listening to this event
+
+ private: // Disabled Copy Construction
+ SFrameCallbackEntry(const SFrameCallbackEntry &);
+ SFrameCallbackEntry &operator=(const SFrameCallbackEntry &);
+ };
+
+ typedef CArray<SFrameCallbackEntry *> TFrameCallbacksList; ///< Array of frame callbacks
+
+public: // Construction
+ CScriptCallbacks();
+ ~CScriptCallbacks();
+
+ bool RegisterCallback(Q3DStudio::UINT32 callbackType, const TScriptCallback inCallback,
+ void *inUserData);
+ void UnregisterCallback(Q3DStudio::UINT32 callbackType, const TScriptCallback inCallback);
+
+ void ProcessCallbacks();
+
+private:
+ TFrameCallbacksList m_CallbackList;
+
+private: // Disabled Copy Construction
+ CScriptCallbacks(const CScriptCallbacks &);
+ CScriptCallbacks &operator=(const CScriptCallbacks &);
+};
+
+class CQmlEngine : public IScriptBridge
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~CQmlEngine() {}
+
+public: // Public functions but not functions on the script bridge
+ /**
+ * @brief Peek a custom action from the queue
+ *
+ * @param[out] outElement Target Element
+ * @param[out] outSignal Signal Name
+ *
+ * @return true if signal available
+ */
+ virtual bool PeekSignal(TElement *&outElement, char *&outName) = 0;
+
+ /**
+ * @brief Select a slide by index
+ *
+ * @param[in] component Component Name
+ * @param[in] slideIndex Slide index
+ * @param[in] inArgs Arguemnts for slide switch
+ *
+ * @return none
+ */
+ virtual void GotoSlideIndex(const char *component, const Q3DStudio::INT32 slideIndex,
+ const SScriptEngineGotoSlideArgs &inArgs) = 0;
+
+ virtual bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName) = 0;
+
+ /**
+ * @brief Go to specified time
+ *
+ * @param[in] component Component Name
+ * @param[in] time New time
+ *
+ * @return none
+ */
+ virtual void GotoTime(const char *component, const Q3DStudio::FLOAT time) = 0;
+
+ /**
+ * @brief Return values of an attribute
+ *
+ * @param[in] element Element Name
+ * @param[in] attName Attribute name
+ * @param[out] value Attribute value
+ *
+ * @return none
+ */
+ virtual bool GetAttribute(const char *element, const char *attName, char *value) = 0;
+
+ /**
+ * @brief Register a callback
+ *
+ * @param[in] callbackType callback type
+* @param[in] inCallback pointer to callback
+* @param[in] inUserData pointer to user data
+ *
+ * @return true on success
+ */
+ virtual bool RegisterCallback(Q3DStudio::UINT32 callbackType, const TScriptCallback inCallback,
+ void *inUserData) = 0;
+
+ /**
+ * @brief Shutdown QML engine
+ *
+ * @param[in] inFoundation Pointer to foundation
+ *
+ * @return no return
+ */
+ virtual void Shutdown(qt3ds::NVFoundationBase &inFoundation) = 0;
+
+ virtual uic::runtime::IApplication *GetApplication() = 0;
+
+public:
+ /**
+ * @brief Create QML engine
+ *
+ * @param[in] inFoundation Pointer to foundation
+ * @param[in] inTimeProvider Pointer to time provider
+ *
+ * @return no return
+ */
+ static CQmlEngine *Create(qt3ds::NVFoundationBase &inFoundation, ITimeProvider &inTimeProvider);
+};
+
+} // namespace Q3DStudio
+
+#endif
diff --git a/src/Runtime/Source/Runtime/Include/UICRuntimeFactory.h b/src/Runtime/Source/Runtime/Include/UICRuntimeFactory.h
new file mode 100644
index 00000000..75376cd7
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICRuntimeFactory.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTimer.h"
+#include "foundation/Qt3DSRefCounted.h"
+namespace uic {
+namespace render {
+ class IInputStreamFactory;
+ class IUICRenderContext;
+ class IUICRenderContextCore;
+}
+}
+
+namespace uic {
+namespace runtime {
+ class IApplication;
+ class IApplicationCore;
+}
+}
+
+namespace uic {
+namespace state {
+ class IVisualStateContext;
+}
+}
+
+namespace uic {
+namespace evt {
+ class IEventSystem;
+}
+}
+
+namespace qt3ds {
+class NVFoundationBase;
+namespace foundation {
+ class IStringTable;
+ class IPerfTimer;
+}
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IScene;
+class CRenderEngine;
+class ISceneManager;
+class IRender;
+class CInputEngine;
+class IScriptBridge;
+class CPresentation;
+class IPresentation;
+class ITimeProvider;
+class ISceneBinaryLoader;
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+
+//==============================================================================
+// Global Factories
+//==============================================================================
+// All of the interfaces available without opengl initialized.
+class IRuntimeFactoryCore : public qt3ds::foundation::NVRefCounted
+{
+public:
+ virtual ISceneBinaryLoader &GetSceneLoader() = 0;
+ virtual IScriptBridge &GetScriptEngine() = 0;
+ virtual IScriptBridge &GetScriptEngineQml() = 0;
+ virtual uic::render::IUICRenderContextCore &GetUICRenderContextCore() = 0;
+ virtual uic::render::IInputStreamFactory &GetInputStreamFactory() = 0;
+ virtual uic::state::IVisualStateContext &GetVisualStateContext() = 0;
+ virtual uic::evt::IEventSystem &GetEventSystem() = 0;
+ virtual ITimeProvider &GetTimeProvider() = 0;
+ virtual qt3ds::NVFoundationBase &GetFoundation() = 0;
+ virtual qt3ds::foundation::IPerfTimer &GetPerfTimer() = 0;
+ virtual qt3ds::foundation::IStringTable &GetStringTable() = 0;
+ virtual void AddSearchPath(const char8_t *inFile) = 0;
+ virtual void SetDllDir(const char *inDir) = 0;
+ virtual uic::runtime::IApplicationCore *GetApplicationCore() = 0;
+ virtual void SetApplicationCore(uic::runtime::IApplicationCore *app) = 0;
+};
+//==============================================================================
+/**
+ * @class CRuntimeFactory
+ * @brief Static class providing default creation methods
+ */
+class IRuntimeFactory : public IRuntimeFactoryCore
+{
+protected:
+ virtual ~IRuntimeFactory() {}
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ virtual ISceneManager &GetSceneManager() = 0;
+ virtual uic::render::IUICRenderContext &GetUICRenderContext() = 0;
+ virtual uic::runtime::IApplication *GetApplication() = 0;
+ virtual void SetApplication(uic::runtime::IApplication *app) = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICSceneManager.h b/src/Runtime/Source/Runtime/Include/UICSceneManager.h
new file mode 100644
index 00000000..f6fa15fd
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICSceneManager.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICPickFrame.h"
+#include "UICIStateful.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICIScene.h"
+
+namespace qt3ds {
+namespace foundation {
+ class IInStream;
+ class IOutStream;
+ class Mutex;
+}
+}
+
+namespace uic {
+namespace render {
+ class IUICRenderContextCore;
+ class ILoadedBuffer;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IScene;
+class IPresentation;
+class CRenderEngine;
+class CRenderEngine;
+class IUIPParser;
+class CFileStream;
+class IRuntimeFactory;
+class IScriptBridge;
+class ISceneManager;
+
+class ISceneBinaryLoader : public qt3ds::foundation::NVRefCounted
+{
+protected:
+ virtual ~ISceneBinaryLoader() {}
+
+public:
+ virtual qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8>
+ BinaryLoadManagerData(qt3ds::foundation::IInStream &inStream, const char *inBinaryDir) = 0;
+
+ // threadsafe
+ // Can be called from any thread
+ virtual bool GetBinaryLoadFileName(eastl::string &inPresentationFilename,
+ eastl::string &outResult) = 0;
+
+ // threadsafe
+ // returns a handle to the loaded object. Return value of zero means error.
+ virtual qt3ds::QT3DSU32 LoadSceneStage1(qt3ds::foundation::CRegisteredString inPresentationDirectory,
+ uic::render::ILoadedBuffer &inData) = 0;
+
+ // threadsafe
+ // still does not require openGL context but has dependency on a few other things.
+ virtual void LoadSceneStage2(qt3ds::QT3DSU32 inSceneHandle, IPresentation &inPresentation,
+ size_t inElementMemoryOffset, IScriptBridge &inBridge) = 0;
+};
+struct FacePositionPlanes
+{
+ enum Enum { XY = 0, YZ, XZ };
+};
+
+//==============================================================================
+/**
+* @class ISceneManager
+* @brief Container class that creates and manages all the Scenes.
+*/
+class ISceneManager : public qt3ds::foundation::NVRefCounted
+{
+protected:
+ virtual ~ISceneManager(){};
+
+public: // Presentations
+ //==============================================================================
+ /**
+ * Load a new scene based on an existing presentation. This will create a new
+ * CScene-based class from the factory method at "CreateScene". To supply
+ * your own class, simply set "CreateScene" to the desired factory method.
+ * After creating the new scene, a load will be triggered.
+ * @param inPresentation the current presentation loaded
+ */
+ virtual IScene *LoadScene(IPresentation *inPresentation, IUIPParser *inParser,
+ IScriptBridge &inBridge) = 0;
+ virtual void LoadRenderPlugin(const CHAR *inAssetIDString, const CHAR *inPath,
+ const CHAR *inArgs) = 0;
+
+ virtual void LoadQmlStreamerPlugin(const CHAR *inAssetIDString) = 0;
+
+ virtual void BinarySaveManagerData(qt3ds::foundation::IOutStream &inStream,
+ const char *inBinaryDir) = 0;
+ // Loading flow data needs to return the string table memory block. This allows
+ // other systems to use remap their string table strings assuming they had mapped them before
+ // serialization. In general this is a horrible hack and abstraction leak but assuming you have
+ // a string
+ // table I guess it isn't too bad.
+ virtual qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8>
+ BinaryLoadManagerData(qt3ds::foundation::IInStream &inStream, const char *inBinaryDir) = 0;
+
+ virtual void BinarySave(Q3DStudio::IScene &inScene) = 0;
+
+public: // Update Cycle
+ virtual BOOL Update() = 0;
+ virtual BOOL RenderPresentation(IPresentation *inPresentation) = 0;
+ virtual void OnViewResize(INT32 inViewWidth, INT32 inViewHeight) = 0;
+ virtual void GetViewSize(INT32 &outWidth, INT32 &outHeight) = 0;
+
+ virtual STextSizes GetDisplayDimensions(Q3DStudio::IPresentation *inPrimaryPresentation) = 0;
+
+public: // Picking
+ virtual Q3DStudio::TElement *UserPick(float mouseX, float mouseY) = 0;
+ virtual SPickFrame AdvancePickFrame(const SInputFrame &inInputFrame) = 0;
+ // Get the relative UV coord position of an element. This matches how mouse picking works where
+ // we pick out
+ virtual qt3ds::foundation::Option<qt3ds::QT3DSVec2>
+ FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
+ qt3ds::foundation::NVDataRef<Q3DStudio::TElement *> inMapperElements,
+ FacePositionPlanes::Enum inPlane) = 0;
+
+ virtual void Release() = 0;
+
+ static ISceneManager &Create(IRuntimeFactory &inFactory, CRenderEngine &inRenderEngine);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/UICSlideSystem.h b/src/Runtime/Source/Runtime/Include/UICSlideSystem.h
new file mode 100644
index 00000000..eebc8415
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICSlideSystem.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "UICElementSystem.h"
+
+namespace Q3DStudio {
+class ILogicManager;
+}
+
+namespace uic {
+namespace runtime {
+ class ILogicSystem;
+ class IAnimationSystem;
+
+ struct SSlideKey
+ {
+ element::SElement *m_Component;
+ QT3DSU32 m_Index;
+ SSlideKey()
+ : m_Component(NULL)
+ , m_Index(0)
+ {
+ }
+ SSlideKey(element::SElement &inElem, QT3DSU32 inIdx)
+ : m_Component(&inElem)
+ , m_Index(inIdx)
+ {
+ }
+
+ bool IsValid() const { return m_Component != NULL; }
+
+ bool operator==(const SSlideKey &inOther) const
+ {
+ return m_Component == inOther.m_Component && m_Index == inOther.m_Index;
+ }
+ };
+
+ struct PlayMode
+ {
+ enum Enum {
+ Looping = 0,
+ StopAtEnd,
+ PingPong,
+ Ping,
+ PlayThroughTo,
+ };
+ };
+
+ struct SSlidePlayInformation
+ {
+ PlayMode::Enum m_PlayMode;
+ bool m_Paused;
+ QT3DSU8 m_PlayThroughTo;
+
+ SSlidePlayInformation()
+ : m_PlayMode(PlayMode::Looping)
+ , m_Paused(false)
+ , m_PlayThroughTo(0xFF)
+ {
+ }
+ };
+
+ struct SSlideAnimAction
+ {
+ QT3DSI32 m_Id;
+ bool m_Active;
+ bool m_IsAnimation;
+ SSlideAnimAction()
+ : m_Id(0)
+ , m_Active(false)
+ , m_IsAnimation(false)
+ {
+ }
+ SSlideAnimAction(QT3DSI32 inId, bool inActive, bool inAnimation)
+ : m_Id(inId)
+ , m_Active(inActive)
+ , m_IsAnimation(inAnimation)
+ {
+ }
+ };
+
+ // Throughout this object, a slide index of 0xFF means invalid slide index.
+ class ISlideSystem : public NVRefCounted
+ {
+ public:
+ static QT3DSU8 InvalidSlideIndex() { return 0xFF; }
+ // Building out a dataset.
+ // Returns the index
+ // This slide is now the active cursor. The rest of the building functions will implicitly
+ // refer
+ // to the last added slide
+ // Playthroughto is either an index of the new slide or -1 meaning no playthough value.
+ virtual QT3DSU32 AddSlide(element::SElement &inComponent, const char8_t *inName,
+ PlayMode::Enum inPlayMode = PlayMode::Looping, bool inPaused = false,
+ QT3DSU8 inPlaythroughTo = InvalidSlideIndex(), QT3DSU32 inMinTime = 0,
+ QT3DSU32 inMaxTime = 0) = 0;
+
+ virtual void SetSlideMaxTime(QT3DSU32 inMaxTime) = 0;
+ virtual void AddSlideElement(element::SElement &inElement, bool inActive) = 0;
+ virtual void AddSlideAttribute(Q3DStudio::SAttributeKey inKey,
+ Q3DStudio::UVariant inValue) = 0;
+ virtual SSlideAnimAction *AddSlideAnimAction(bool inAnimation, QT3DSI32 inIndex,
+ bool inActive) = 0;
+
+ // Using the dataset
+ virtual void InitializeDynamicKeys(SSlideKey inKey,
+ IAnimationSystem &inAnimationSystem) const = 0;
+ virtual void ExecuteSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
+ ILogicSystem &inLogicManager) const = 0;
+ virtual void RollbackSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
+ ILogicSystem &inLogicManager) const = 0;
+ virtual QT3DSU8 FindSlide(element::SElement &inComponent,
+ const char8_t *inSlideName) const = 0;
+ virtual QT3DSU8 FindSlide(element::SElement &inComponent, QT3DSU32 inSlideHashName) const = 0;
+ virtual const char8_t *GetSlideName(SSlideKey inKey) const = 0;
+ virtual QT3DSU8 GetPlaythroughToSlideIndex(SSlideKey inKey) const = 0;
+
+ // Serialization
+ virtual void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) = 0;
+ virtual void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData, NVDataRef<QT3DSU8> inStringTableData,
+ size_t inElementOffset) = 0;
+
+ static ISlideSystem &CreateSlideSystem(NVFoundationBase &inFnd, IStringTable &inStrTable,
+ IElementAllocator &inElemAllocator);
+ };
+}
+} \ No newline at end of file
diff --git a/src/Runtime/Source/Runtime/Include/UICTimePolicy.h b/src/Runtime/Source/Runtime/Include/UICTimePolicy.h
new file mode 100644
index 00000000..6a137196
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/UICTimePolicy.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "foundation/Qt3DSOption.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+struct TimePolicyModes
+{
+ enum Enum {
+ StopAtEnd = 0,
+ Looping,
+ PingPong,
+ Ping,
+ };
+};
+
+//==============================================================================
+/**
+ * Filter time based of parameters such as loop, duration, ping-pong etc.
+ *
+ * The time policy is an agnostic class that transforms time units based on
+ * internal settings and times given to it. Think of it as the minimal
+ * intelligence needed to support the time playback modes we use. It is simply
+ * a function that takes in a source time variable, adjusts it accordingly,
+ * and returns a filtered version.
+ */
+
+QT3DS_ALIGN_PREFIX(4) class CTimePolicy
+{
+ //==============================================================================
+ // Fields and Constants
+ //==============================================================================
+public:
+ const static TTimeUnit FOREVER; ///< Forever repetitions means loop forever, Forever duration
+ ///means infinite duration
+ friend struct SComponentTimePolicyOverride; ///< This class needs to mangle some of our internal
+ ///members to keep everything consistent
+
+protected:
+ // Time policy related ( 20 bytes )
+ unsigned long m_LocalTime; ///< Component current local time; transformed by playmodes
+ unsigned long m_LoopingDuration; ///< Looping duration
+ SAlignedTimeUnit m_Offset; ///< Subtraction modifier
+ FLOAT m_Rate; ///< Time policy rate
+ UINT8 m_TimePadding[12]; ///< Padding to keep the size of the time policy the same.
+
+ UINT8
+ m_TimePolicyMode : 2; ///< Number of durations before halting - FOREVER means infinite reps
+ UINT8 m_Paused : 1; ///< Paused or playing
+ UINT8 m_OffsetInvalid : 1; ///< True if we need to reset our offset
+ UINT8 m_Backward : 1; ///< True if are in 'reverse' mode
+
+ UINT8 m_Unused[3]; ///< (Padding 3 bytes)
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ void Initialize(const TTimeUnit inLoopingDuration = FOREVER,
+ TimePolicyModes::Enum inMode = TimePolicyModes::StopAtEnd);
+ void Initialize(const TTimeUnit inLoopingDuration, UINT32 inRepetitions, BOOL inPingPong);
+
+public: // Access Methods
+ FLOAT GetRate() const { return m_Rate; }
+ void SetRate(float inRate) { m_Rate = inRate; }
+
+ bool IsReverse() const { return m_Backward; }
+ void SetReverse(bool inIsReverse) { m_Backward = inIsReverse ? 1 : 0; }
+
+ TTimeUnit GetTime() const;
+ void SetTime(TTimeUnit inTime);
+
+ TTimeUnit GetLoopingDuration() const;
+ void SetLoopingDuration(const TTimeUnit inTime);
+
+ BOOL GetPaused() const;
+ void SetPaused(const BOOL inPaused);
+
+ BOOL GetPlayBackDirection() const;
+
+public: // Time update
+ // The addendum contains extra parameters used that can be specified in a goto-slide command
+ // in the uia file.
+ BOOL ComputeTime(const TTimeUnit inTime);
+
+private:
+ TTimeUnit InternalGetTime() const;
+
+ BOOL UpdateTime(const TTimeUnit inTime);
+} QT3DS_ALIGN_SUFFIX(4);
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Include/q3dsqmlscript.h b/src/Runtime/Source/Runtime/Include/q3dsqmlscript.h
new file mode 100644
index 00000000..9c2f6b84
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Include/q3dsqmlscript.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSQMLSCRIPT_H
+#define Q3DSQMLSCRIPT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+#include <QtQml/qjsvalue.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qmatrix4x4.h>
+
+#include "UICTypes.h"
+#include "UICKernelTypes.h"
+#include "UICEvent.h"
+
+namespace Q3DStudio {
+class CQmlEngine;
+
+class Q3DSQmlScript : public QObject
+{
+ Q_OBJECT
+public:
+ Q3DSQmlScript(CQmlEngine &api, QObject &object, TElement &element, TElement &parent);
+ ~Q3DSQmlScript();
+
+ void update();
+ void call(const QString &function);
+ void updateProperties();
+ bool hasBehavior(const TElement *behavior);
+
+ Q_INVOKABLE float getDeltaTime();
+ Q_INVOKABLE float getAttribute(const QString &attribute);
+ Q_INVOKABLE void setAttribute(const QString &attribute, const QVariant &value);
+ Q_INVOKABLE void setAttribute(const QString &handle, const QString &attribute,
+ const QVariant &value);
+ Q_INVOKABLE void fireEvent(const QString &event);
+ Q_INVOKABLE void registerForEvent(const QString &event, const QJSValue &function);
+ Q_INVOKABLE void registerForEvent(const QString &handle, const QString &event,
+ const QJSValue &function);
+ Q_INVOKABLE void unregisterForEvent(const QString &event);
+ Q_INVOKABLE void unregisterForEvent(const QString &handle, const QString &event);
+ Q_INVOKABLE QVector2D getMousePosition();
+ Q_INVOKABLE QMatrix4x4 calculateGlobalTransform(const QString &handle = "");
+ Q_INVOKABLE QVector3D lookAt(const QVector3D& target);
+ Q_INVOKABLE QString getParent(const QString& handle = "");
+
+ struct EventData {
+ QJSValue function;
+ };
+
+private:
+ TElement *getElementByPath(const QString &path);
+
+ CQmlEngine &m_api;
+ QObject &m_object;
+ TElement &m_behavior;
+ TElement &m_owner;
+
+ bool m_initialized;
+ bool m_lastActivationState;
+
+ float m_deltaTime;
+ TTimeUnit m_lastTime;
+ struct EventCallbackInfo {
+ TElement *element;
+ TEventCommandHash eventHash;
+ EventData *data;
+ };
+
+ QVector<EventCallbackInfo> m_eventCallbacks;
+};
+}
+
+#endif // Q3DSQMLSCRIPT_H
diff --git a/src/Runtime/Source/Runtime/Source/RuntimePrefix.cpp b/src/Runtime/Source/Runtime/Source/RuntimePrefix.cpp
new file mode 100644
index 00000000..d9ebd84a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/RuntimePrefix.cpp
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
diff --git a/src/Runtime/Source/Runtime/Source/UICActivationManager.cpp b/src/Runtime/Source/Runtime/Source/UICActivationManager.cpp
new file mode 100644
index 00000000..3b6a9c0f
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICActivationManager.cpp
@@ -0,0 +1,1027 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "RuntimePrefix.h"
+#include "UICActivationManager.h"
+#include "UICElementSystem.h"
+#include "UICComponentManager.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSInvasiveSet.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/StringTable.h"
+#include "EASTL/sort.h"
+#include "UICAttributeHashes.h"
+#include "UICPresentation.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSync.h"
+#include "UICRenderThreadPool.h"
+
+using namespace uic::runtime;
+using namespace uic::runtime::element;
+using uic::render::IThreadPool;
+using qt3ds::foundation::Time;
+
+namespace {
+
+typedef nvvector<TElementAndSortKey> TElementAndSortKeyList;
+
+struct STimeEvent
+{
+ enum Type {
+ Start = 0,
+ Stop,
+ };
+
+ Type m_Type;
+ TTimeUnit m_Time;
+ nvvector<SElement *> m_AffectedNodes;
+
+ STimeEvent(Type inType, NVAllocatorCallback &alloc, TTimeUnit inTime)
+ : m_Type(inType)
+ , m_Time(inTime)
+ , m_AffectedNodes(alloc, "TimeEvent")
+ {
+ }
+
+ void Reset()
+ {
+ m_Time = 0;
+ m_AffectedNodes.clear();
+ }
+};
+
+struct STimeEventGreaterThan
+{
+ bool operator()(const STimeEvent *lhs, const STimeEvent *rhs) const
+ {
+ if (lhs->m_Time == rhs->m_Time)
+ return lhs->m_Type > rhs->m_Type;
+
+ return lhs->m_Time > rhs->m_Time;
+ }
+};
+
+struct STimeEventLessThan
+{
+ bool operator()(const STimeEvent *lhs, const STimeEvent *rhs) const
+ {
+ if (lhs->m_Time == rhs->m_Time)
+ return lhs->m_Type < rhs->m_Type;
+
+ return lhs->m_Time < rhs->m_Time;
+ }
+};
+
+typedef nvvector<STimeEvent *> TTimeEventList;
+struct STimeContext;
+typedef NVDataRef<NVScopedRefCounted<STimeContext>> TTimeContextSet;
+
+// Tree navigation
+
+SElement *GetElementNodeFirstChild(SElement &inNode)
+{
+ return inNode.m_Child;
+}
+SElement *GetElementNodeNextSibling(SElement &inNode)
+{
+ return inNode.m_Sibling;
+}
+SElement *GetElementNodeParent(SElement &inNode)
+{
+ return inNode.m_Parent;
+}
+
+struct SScanBufferEntry
+{
+ SElement *m_Node;
+ QT3DSU32 m_StartTime;
+ QT3DSU32 m_EndTime;
+
+ SScanBufferEntry()
+ : m_Node(NULL)
+ , m_StartTime(0)
+ , m_EndTime(QT3DS_MAX_U32)
+ {
+ }
+ SScanBufferEntry(SElement *inNode)
+ : m_Node(inNode)
+ , m_StartTime(0)
+ , m_EndTime(QT3DS_MAX_U32)
+ {
+ }
+ SScanBufferEntry(SElement *inNode, QT3DSU32 start, QT3DSU32 end)
+ : m_Node(inNode)
+ , m_StartTime(start)
+ , m_EndTime(end)
+ {
+ }
+
+ SScanBufferEntry(SElement *inNode, bool inParentActive)
+ : m_Node(inNode)
+ , m_StartTime(inParentActive ? 1 : 0)
+ , m_EndTime(0)
+ {
+ }
+
+ bool IsParentActive() const { return m_StartTime ? true : false; }
+};
+
+typedef nvvector<SScanBufferEntry> TScanBuffer;
+typedef nvvector<SElement *> TElementNodePtrList;
+
+struct SElementIndexPairSorter
+{
+ bool operator()(const eastl::pair<element::SElement *, QT3DSU32> &lhs,
+ const eastl::pair<element::SElement *, QT3DSU32> &rhs) const
+ {
+ return lhs.second < rhs.second;
+ }
+};
+
+struct SElementPtrSort
+{
+ bool operator()(const SElement *lhs, const SElement *rhs)
+ {
+ return lhs->Depth() < rhs->Depth();
+ }
+};
+
+DEFINE_INVASIVE_SINGLE_LIST(TimeContext);
+
+struct STimeContext
+{
+ NVAllocatorCallback &m_Allocator;
+ SComponent &m_Component;
+ CTimePolicy m_TimePolicy;
+ SComponentTimePolicyOverride *m_TimePolicyOverride;
+ TTimeUnit m_CurrentTime;
+ TElementNodePtrList m_Elements;
+ TTimeEventList m_TimeEventBackingStore;
+ TTimeEventList m_TimeEvents;
+ SActivationManagerNodeDirtyList m_DirtyList;
+ QT3DSU32 m_TimeEventBackingStoreIndex;
+ QT3DSI32 mRefCount;
+ STimeContext *m_NextSibling;
+ TTimeContextList m_Children;
+ Mutex &m_ElementAccessMutex;
+ bool m_AllNodesDirty;
+ bool m_TimeDataNeedsUpdate;
+
+ STimeContext(NVAllocatorCallback &alloc, SComponent &inComponent, Mutex &inElementAccessMutex)
+ : m_Allocator(alloc)
+ , m_Component(inComponent)
+ , m_TimePolicyOverride(NULL)
+ , m_CurrentTime(-1)
+ , m_Elements(alloc, "m_Elements")
+ , m_TimeEventBackingStore(alloc, "TimeEventBackingStore")
+ , m_TimeEvents(alloc, "TimeEvents")
+ , m_DirtyList(alloc)
+ , m_TimeEventBackingStoreIndex(0)
+ , mRefCount(0)
+ , m_NextSibling(NULL)
+ , m_ElementAccessMutex(inElementAccessMutex)
+ , m_AllNodesDirty(true)
+ , m_TimeDataNeedsUpdate(true)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+ ~STimeContext()
+ {
+ Reset();
+ for (TTimeEventList::iterator iter = m_TimeEventBackingStore.begin(),
+ end = m_TimeEventBackingStore.end();
+ iter != end; ++iter) {
+ NVDelete(m_Allocator, *iter);
+ }
+
+ m_TimeEventBackingStore.clear();
+ RemoveOverride();
+ }
+
+ void Reset()
+ {
+ for (TTimeEventList::iterator iter = m_TimeEvents.begin(), end = m_TimeEvents.end();
+ iter != end; ++iter)
+ (*iter)->Reset();
+
+ m_TimeEvents.clear();
+ m_TimeEventBackingStoreIndex = 0;
+ m_CurrentTime = -1;
+ m_DirtyList.clear();
+ m_AllNodesDirty = true;
+ m_TimeDataNeedsUpdate = true;
+ }
+
+ STimeEvent &GetTimeEventForTime(TTimeUnit inTime, STimeEvent::Type inType)
+ {
+ TTimeEventList::iterator inserter = m_TimeEvents.end();
+ for (TTimeEventList::iterator iter = m_TimeEvents.begin(), end = m_TimeEvents.end();
+ iter != end && inserter == end; ++iter) {
+ if ((*iter)->m_Time == inTime) {
+ if ((*iter)->m_Type == inType)
+ return **iter;
+ // Start comes before stop
+ if ((*iter)->m_Type == STimeEvent::Stop)
+ inserter = iter;
+ }
+
+ if ((*iter)->m_Time > inTime)
+ inserter = iter;
+ }
+
+ if (m_TimeEventBackingStoreIndex == m_TimeEventBackingStore.size())
+ m_TimeEventBackingStore.push_back(
+ QT3DS_NEW(m_Allocator, STimeEvent)(inType, m_Allocator, inTime));
+
+ STimeEvent *newEvent = m_TimeEventBackingStore[m_TimeEventBackingStoreIndex];
+ ++m_TimeEventBackingStoreIndex;
+
+ newEvent->m_Time = inTime;
+ newEvent->m_Type = inType;
+ newEvent->m_AffectedNodes.clear();
+
+ if (inserter == m_TimeEvents.end())
+ m_TimeEvents.push_back(newEvent);
+ else
+ m_TimeEvents.insert(inserter, newEvent);
+
+ return *newEvent;
+ };
+
+ void UpdateNodeList(nvvector<SElement *> &inList, bool timeActive)
+ {
+ for (QT3DSU32 elemIdx = 0, endIdx = inList.size(); elemIdx < endIdx; ++elemIdx) {
+ SActivationManagerNode &theNode = inList[elemIdx]->m_ActivationManagerNode;
+ if (timeActive != theNode.m_Flags.IsTimeActive()) {
+ theNode.m_Flags.SetTimeActive(timeActive);
+ SetElementDirty(*inList[elemIdx]);
+ }
+ }
+ }
+
+ // Returns true if we have reached the end time.
+ bool CalculateNewTime(TTimeUnit inGlobalTime)
+ {
+ Option<TTimeUnit> theNewTime;
+ if (m_TimePolicyOverride) {
+ SComponentTimePolicyOverride *theOverride = m_TimePolicyOverride;
+ eastl::pair<Q3DStudio::BOOL, TTimeUnit> theEvalResult =
+ theOverride->ComputeLocalTime(m_TimePolicy, inGlobalTime);
+ if (theEvalResult.first && theOverride->m_TimeCallback) {
+ Mutex::ScopedLock __locker(m_ElementAccessMutex);
+ theOverride->m_TimeCallback->OnTimeFinished();
+ theOverride->m_TimeCallback->Release();
+ theOverride->m_TimeCallback = NULL;
+ }
+ return false;
+ } else {
+ Q3DStudio::BOOL theReachedEndTime = m_TimePolicy.ComputeTime(inGlobalTime);
+ if (theReachedEndTime)
+ return true;
+
+ return false;
+ }
+ }
+
+ // There are four conditions this happens:
+ // 1. This object is getting destroyed
+ // 2. A new override is being set.
+ // 3. The compoent switched slides.
+ // 4. The component was deactivated.
+ void RemoveOverride()
+ {
+ if (m_TimePolicyOverride) {
+ if (m_TimePolicyOverride->m_TimeCallback) {
+ Mutex::ScopedLock __locker(m_ElementAccessMutex);
+ m_TimePolicyOverride->m_TimeCallback->Release();
+ m_TimePolicyOverride->m_TimeCallback = NULL;
+ }
+
+ NVDelete(m_Allocator, m_TimePolicyOverride);
+ m_TimePolicyOverride = NULL;
+ }
+ }
+
+ void UpdateLocalTime(TTimeUnit inNewTime, TScanBuffer &inScanBuffer, IActivityZone &inZone)
+ {
+ if (m_TimeDataNeedsUpdate) {
+ BuildTimeContext(inScanBuffer, inZone);
+ }
+
+ TTimeUnit newTime = inNewTime;
+ if (newTime != m_CurrentTime) {
+ SComponent &myNode = m_Component;
+ {
+ Mutex::ScopedLock __locker(m_ElementAccessMutex);
+ myNode.SetDirty();
+ }
+ STimeEvent searchEvent(STimeEvent::Start, m_Allocator, m_CurrentTime);
+ bool forward = newTime > m_CurrentTime;
+ m_CurrentTime = NVMax((TTimeUnit)0, newTime);
+
+ if (forward) {
+ TTimeEventList::iterator iter = eastl::lower_bound(
+ m_TimeEvents.begin(), m_TimeEvents.end(), &searchEvent, STimeEventLessThan());
+
+ for (TTimeEventList::iterator end = m_TimeEvents.end();
+ iter != end && (*iter)->m_Time <= newTime; ++iter) {
+ // Stop only works if the time is greater.
+ // start works if the time is equal.
+ bool isActive = true;
+ if ((*iter)->m_Type == STimeEvent::Stop)
+ isActive = newTime <= (*iter)->m_Time;
+
+ UpdateNodeList((*iter)->m_AffectedNodes, isActive);
+ }
+ } else {
+ searchEvent.m_Type = STimeEvent::Stop;
+ TTimeEventList::reverse_iterator iter =
+ eastl::lower_bound(m_TimeEvents.rbegin(), m_TimeEvents.rend(), &searchEvent,
+ STimeEventGreaterThan());
+
+ for (TTimeEventList::reverse_iterator end = m_TimeEvents.rend();
+ iter != end && (*iter)->m_Time >= newTime; ++iter) {
+ bool isActive = true;
+ if ((*iter)->m_Type == STimeEvent::Start)
+ isActive = newTime >= (*iter)->m_Time;
+
+ UpdateNodeList((*iter)->m_AffectedNodes, isActive);
+ }
+ }
+ }
+ }
+
+ void UpdateNodeElementInformation(SElement &inNode)
+ {
+ Q3DStudio::UVariant attValue;
+ if (inNode.GetAttribute(Q3DStudio::ATTRIBUTE_STARTTIME, attValue))
+ inNode.m_ActivationManagerNode.m_StartTime = (QT3DSU32)attValue.m_INT32;
+
+ if (inNode.GetAttribute(Q3DStudio::ATTRIBUTE_ENDTIME, attValue))
+ inNode.m_ActivationManagerNode.m_StopTime = (QT3DSU32)attValue.m_INT32;
+
+ inNode.m_ActivationManagerNode.m_Flags.SetTimeActive(false);
+ // Note that we don't set the script information here. The reason is that this requires the
+ // script list
+ // and we don't have access to it. Plus it can't change when a slide changes so it is kind
+ // of irrelevant.
+ }
+
+ bool BuildTimeContextElementNode(SElement &inNode, QT3DSU32 inGlobalMin, QT3DSU32 inGlobalMax)
+ {
+ // Note that just because a node itself does not participate in the time graph,
+ // this does not mean that its children do not participate in the time graph.
+ if (inNode.DoesParticipateInTimeGraph()) {
+ UpdateNodeElementInformation(inNode);
+ if (inNode.IsUserActive()) {
+ inGlobalMin = NVMax(inNode.m_ActivationManagerNode.m_StartTime, inGlobalMin);
+ inGlobalMax = NVMin(inNode.m_ActivationManagerNode.m_StopTime, inGlobalMax);
+ if (inGlobalMin < inGlobalMax) {
+ GetTimeEventForTime(inGlobalMin, STimeEvent::Start)
+ .m_AffectedNodes.push_back(&inNode);
+ GetTimeEventForTime(inGlobalMax, STimeEvent::Stop)
+ .m_AffectedNodes.push_back(&inNode);
+ }
+ }
+ } else {
+ inNode.m_ActivationManagerNode.m_Flags.SetTimeActive(true);
+ // Carry global min/max information down so children get setup correctly.
+ inNode.m_ActivationManagerNode.m_StartTime = inGlobalMin;
+ inNode.m_ActivationManagerNode.m_StopTime = inGlobalMax;
+ }
+ // Is it worth looking at children at all
+ return inNode.IsUserActive();
+ }
+
+ void BuildTimeContext(TScanBuffer &inScanBuffer, IActivityZone &inZone)
+ {
+ Mutex::ScopedLock __locker(m_ElementAccessMutex);
+ QT3DS_ASSERT(m_TimeDataNeedsUpdate);
+ m_TimeDataNeedsUpdate = false;
+ SComponent &myNode = m_Component;
+ SElement *theChild = myNode.m_Child;
+ if (theChild == NULL) {
+ return;
+ }
+ inScanBuffer.clear();
+ for (SElement *theChild = myNode.m_Child; theChild; theChild = theChild->m_Sibling) {
+ inScanBuffer.push_back(theChild);
+ }
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)inScanBuffer.size(); idx < end; ++idx) {
+ SScanBufferEntry theEntry(inScanBuffer[idx]);
+ bool careAboutChildren = BuildTimeContextElementNode(
+ *theEntry.m_Node, theEntry.m_StartTime, theEntry.m_EndTime);
+ if (careAboutChildren && theEntry.m_Node->IsComponent() == false) {
+ for (SElement *theChild = theEntry.m_Node->m_Child; theChild;
+ theChild = theChild->m_Sibling) {
+ inScanBuffer.push_back(SScanBufferEntry(
+ theChild, theEntry.m_Node->m_ActivationManagerNode.m_StartTime,
+ theEntry.m_Node->m_ActivationManagerNode.m_StopTime));
+ }
+ end = (QT3DSU32)inScanBuffer.size();
+ }
+ if (theEntry.m_Node->IsComponent())
+ inZone.AddActivityItems(*theEntry.m_Node);
+ }
+ }
+
+ void SetElementDirty(SElement &inNode)
+ {
+ SElement *theComponentParent = &inNode.GetComponentParent();
+ if (inNode.IsComponent() && inNode.m_Parent)
+ theComponentParent = &inNode.m_Parent->GetComponentParent();
+
+ QT3DS_ASSERT(theComponentParent == &m_Component);
+ if (m_AllNodesDirty == false) {
+ // We check independent items every frame anyway so it isn't worth setting them dirty
+ // here.
+ if (inNode.IsIndependent() == false) {
+ m_DirtyList.insert(inNode);
+ }
+
+ // Dirty to root time context. This ensures that if we run an activate scan starting at
+ // a parent
+ // we won't have to re-run the scan at this node because it will not be dirty.
+ // This also makes sure that if we mark all nodes dirty we continue the activate scan
+ // till we hit at least
+ // this node.
+ SElement *theParent = inNode.m_Parent;
+ while (theParent) {
+ if (theParent->IsComponent()
+ || theParent->m_ActivationManagerNode.m_Flags.IsChildDirty())
+ theParent = NULL;
+ else {
+ SActivationManagerNode &theNode = theParent->m_ActivationManagerNode;
+ theNode.m_Flags.SetChildDirty();
+ theParent = theParent->m_Parent;
+ }
+ }
+ }
+ }
+
+ static void UpdateItemScriptStatus(SElement &inNode, bool activeAndHasScript,
+ TElementAndSortKeyList &scriptBuffer)
+ {
+ QT3DSU32 theIndex = inNode.Depth();
+ eastl::pair<element::SElement *, QT3DSU32> theInsertedItem(&inNode, theIndex);
+ if (activeAndHasScript) {
+ if (inNode.m_ActivationManagerNode.m_Flags.HasScript() == false) {
+ scriptBuffer.push_back(theInsertedItem);
+ inNode.m_ActivationManagerNode.m_Flags.SetHasScript(true);
+ }
+ } else {
+ if (inNode.m_ActivationManagerNode.m_Flags.HasScript() == true) {
+ TElementAndSortKeyList::iterator theFind =
+ eastl::find(scriptBuffer.begin(), scriptBuffer.end(), theInsertedItem);
+ if (theFind != scriptBuffer.end())
+ scriptBuffer.erase(theFind);
+ inNode.m_ActivationManagerNode.m_Flags.SetHasScript(false);
+ }
+ }
+ }
+
+ static void HandleActivationChange(SElement &inNode, TElementAndSortKeyList &activateBuffer,
+ TElementAndSortKeyList &deactivateBuffer,
+ TElementAndSortKeyList &scriptBuffer,
+ Mutex &inElementAccessMutex, bool &scriptBufferRequiresSort,
+ bool inIsActive)
+ {
+ Mutex::ScopedLock __locker(inElementAccessMutex);
+ TElementAndSortKey theKey(&inNode, inNode.Depth());
+ if (inIsActive) {
+ activateBuffer.push_back(TElementAndSortKey(theKey));
+ } else {
+ deactivateBuffer.push_back(theKey);
+ }
+
+ if (inNode.Flags().HasScriptCallbacks()) {
+ UpdateItemScriptStatus(inNode, inIsActive, scriptBuffer);
+ scriptBufferRequiresSort = true;
+ }
+ inNode.SetGlobalActive(inIsActive);
+ }
+
+ // Runs once we notice that the item's global active status has changed.
+ // Note we explicitly do not update independent items because those are updated
+ // as the first step of each time context update itself.
+ // We do, however, remove them from the dirty list here.
+ static void RunActivateScan(SElement &inNode, TScanBuffer &inScanBuffer,
+ TElementAndSortKeyList &activateBuffer,
+ TElementAndSortKeyList &deactivateBuffer,
+ TElementAndSortKeyList &scriptBuffer, Mutex &inElementAccessMutex,
+ bool &scriptBufferRequiresSort, bool inRunFullScan)
+ {
+ inScanBuffer.clear();
+
+ // Block used to hide variables to avoid an error.
+ {
+ bool parentActive = true;
+ SElement *theParent = inNode.m_Parent;
+ if (theParent != NULL)
+ parentActive = theParent->IsGlobalActive();
+
+ inScanBuffer.push_back(SScanBufferEntry(&inNode, parentActive));
+ }
+
+ for (QT3DSU32 idx = 0, end = inScanBuffer.size(); idx < end; ++idx) {
+ SScanBufferEntry theEntry(inScanBuffer[idx]);
+ SElement *theScanNode = theEntry.m_Node;
+ QT3DS_ASSERT(theScanNode->IsIndependent() == false);
+ bool parentActive = theEntry.IsParentActive();
+ bool wasActive = theScanNode->IsGlobalActive();
+ bool isActive = theScanNode->IsGlobalActive(parentActive);
+ bool wasChildDirty = theScanNode->m_ActivationManagerNode.m_Flags.IsChildDirty();
+ theScanNode->m_ActivationManagerNode.m_Flags.ClearChildDirty();
+ bool activateChange = isActive != wasActive;
+ bool checkChildren = activateChange || (isActive && (wasChildDirty || inRunFullScan));
+ if (activateChange) {
+ HandleActivationChange(*theScanNode, activateBuffer, deactivateBuffer, scriptBuffer,
+ inElementAccessMutex, scriptBufferRequiresSort, isActive);
+ }
+
+ if (checkChildren && theScanNode->m_Child) {
+ for (SElement *theScanNodeChild = theScanNode->m_Child; theScanNodeChild;
+ theScanNodeChild = theScanNodeChild->m_Sibling) {
+ if (theScanNodeChild->IsIndependent() == false)
+ inScanBuffer.push_back(SScanBufferEntry(theScanNodeChild, isActive));
+ }
+ end = inScanBuffer.size();
+ }
+ }
+ }
+
+ void RunDirtyScan(TScanBuffer &inScanBuffer, TElementNodePtrList &inTempDirtyList,
+ TElementAndSortKeyList &activateBuffer,
+ TElementAndSortKeyList &deactivateBuffer,
+ TElementAndSortKeyList &scriptBuffer, bool &scriptBufferRequiresSort)
+ {
+ if (m_AllNodesDirty == true) {
+ inTempDirtyList.clear();
+ SComponent &myNode = m_Component;
+ for (SElement *theChild = myNode.m_Child; theChild; theChild = theChild->m_Sibling) {
+ // Independent nodes don't need to be in the dirty list.
+ if (theChild->IsIndependent() == false)
+ inTempDirtyList.push_back(theChild);
+ }
+ } else {
+ inTempDirtyList.assign(m_DirtyList.begin(), m_DirtyList.end());
+ // Reset nodes that are dirty to *not* be dirty.
+ m_DirtyList.clear();
+ // We have to sort the dirty list because it may have nodes out of order and the active
+ // algorithm requires parents before children. We use the depth member variable to
+ // achieve this.
+ eastl::sort(inTempDirtyList.begin(), inTempDirtyList.end(), SElementPtrSort());
+ }
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)inTempDirtyList.size(); idx < end; ++idx) {
+ SElement &dirtyNode(*inTempDirtyList[idx]);
+ // This is slightly inefficient in the case where a both a child and parent are in the
+ // dirty list.
+ // This case has got to be extremely rare in practice, however.
+ RunActivateScan(dirtyNode, inScanBuffer, activateBuffer, deactivateBuffer, scriptBuffer,
+ m_ElementAccessMutex, scriptBufferRequiresSort, m_AllNodesDirty);
+ }
+ // Set at end so while debugging you can see if all nodes were dirty on method entry.
+ m_AllNodesDirty = false;
+ }
+
+ bool Update(TTimeUnit inGlobalTime, TScanBuffer &inScanBuffer,
+ TElementNodePtrList &inTempDirtyList, TElementAndSortKeyList &activateBuffer,
+ TElementAndSortKeyList &deactivateBuffer, TElementAndSortKeyList &scriptBuffer,
+ bool &scriptBufferRequiresSort, Q3DStudio::CComponentManager &inComponentManager,
+ IPerfTimer &inPerfTimer, IActivityZone &inZone)
+ {
+ QT3DSU64 start = qt3ds::foundation::Time::getCurrentCounterValue();
+ SComponent &theContextNode = m_Component;
+ bool parentActive = true;
+ SElement *theParent = theContextNode.m_Parent;
+ if (theParent != NULL)
+ parentActive = theParent->IsGlobalActive();
+
+ bool wasActive = theContextNode.IsGlobalActive();
+ bool isActive = theContextNode.IsGlobalActive(parentActive);
+ bool activationChange = isActive != wasActive;
+ inPerfTimer.Update("ActivationManager - Update Initial Vars",
+ qt3ds::foundation::Time::getCurrentCounterValue() - start);
+ if (activationChange) {
+ SStackPerfTimer __timer(inPerfTimer, "ActivationManager - Activation Change");
+ HandleActivationChange(theContextNode, activateBuffer, deactivateBuffer, scriptBuffer,
+ m_ElementAccessMutex, scriptBufferRequiresSort, isActive);
+ m_DirtyList.clear();
+ m_AllNodesDirty = true;
+ if (isActive) {
+ Mutex::ScopedLock __locker(m_ElementAccessMutex);
+ inComponentManager.GotoSlideIndex(&theContextNode, 1, false);
+ } else
+ RemoveOverride();
+ }
+ if (isActive) {
+ SStackPerfTimer __timer(inPerfTimer, "ActivationManager - Update Local Time");
+ bool atEndOfTime = CalculateNewTime(inGlobalTime);
+ if (atEndOfTime) {
+ Mutex::ScopedLock __locker(m_ElementAccessMutex);
+ if (theContextNode.IsPlayThrough())
+ inComponentManager.PlaythroughToSlide(&theContextNode);
+ }
+ // Note the slide may have changed here and thus updated our time policy.
+ // Set time active flags based on time.
+ UpdateLocalTime(m_TimePolicy.GetTime(), inScanBuffer, inZone);
+ }
+ if (isActive || activationChange) {
+ if (m_AllNodesDirty || m_DirtyList.size()) {
+ SStackPerfTimer __timer(inPerfTimer, "ActivationManager - Dirty Scan");
+ RunDirtyScan(inScanBuffer, inTempDirtyList, activateBuffer, deactivateBuffer,
+ scriptBuffer, scriptBufferRequiresSort);
+ }
+ }
+ return isActive || activationChange;
+ }
+
+ void GoToTime(TTimeUnit inTime)
+ {
+ if (m_TimePolicyOverride) {
+ m_TimePolicyOverride->SetTime(m_TimePolicy, inTime);
+ } else {
+ m_TimePolicy.SetTime(inTime);
+ }
+ }
+};
+
+IMPLEMENT_INVASIVE_SINGLE_LIST(TimeContext, m_NextSibling);
+
+struct SActivityZone : public IActivityZone
+{
+ typedef nvhash_map<SElement *, NVScopedRefCounted<STimeContext>> TComponentTimeContextMap;
+ NVFoundationBase &m_Foundation;
+ Q3DStudio::CPresentation &m_Presentation;
+ IStringTable &m_StringTable;
+ nvvector<SElement *> m_RootElements;
+ TComponentTimeContextMap m_TimeContexts;
+ // These could potentially not be sorted but for 7.5 and TZ3 I don't want to risk the
+ // bugs assocated with not producing the exact same output as the original algorithm.
+ TElementAndSortKeyList m_ActivatedItems;
+ TElementAndSortKeyList m_DeactivatedItems;
+
+ // This will always need to be sorted because it is maintained across update calls
+ TElementAndSortKeyList m_ScriptItems;
+
+ // Temporaries used while scanning nodes for various features.
+ TScanBuffer m_ScanBuffer;
+ TElementNodePtrList m_TempDirtyList;
+ nvvector<STimeContext *> m_TimeContextScanBuffer;
+
+ TTimeContextList m_RootContexts;
+ Mutex &m_ElementAccessMutex;
+ Mutex m_UpdateCheckMutex;
+ Sync m_UpdateSync;
+ TTimeUnit m_GlobalTime;
+ IPerfTimer *m_PerfTimer;
+ STypeDesc m_DummyTypeDesc;
+ SComponent m_DummyComponent;
+ STimeContext m_DummyContext;
+ bool m_Active;
+ // True if m_ScriptItems needs to be resorted.
+ bool m_ScriptRequiresSort;
+ bool m_Updating;
+
+ QT3DSI32 mRefCount;
+
+ SActivityZone(NVFoundationBase &inFnd, Q3DStudio::CPresentation &inPres,
+ IStringTable &inStrTable, Mutex &inElementAccessMutex)
+ : m_Foundation(inFnd)
+ , m_Presentation(inPres)
+ , m_StringTable(inStrTable)
+ , m_RootElements(inFnd.getAllocator(), "Elements")
+ , m_TimeContexts(inFnd.getAllocator(), "TimeContexts")
+ , m_ActivatedItems(inFnd.getAllocator(), "m_ActivatedItems")
+ , m_DeactivatedItems(inFnd.getAllocator(), "m_DeactivatedItems")
+ , m_ScriptItems(inFnd.getAllocator(), "m_ScriptItems")
+ , m_ScanBuffer(inFnd.getAllocator(), "m_ScanBuffer")
+ , m_TempDirtyList(inFnd.getAllocator(), "m_TempDirtyList")
+ , m_TimeContextScanBuffer(inFnd.getAllocator(), "m_TimeContextScanBuffer")
+ , m_ElementAccessMutex(inElementAccessMutex)
+ , m_UpdateCheckMutex(inFnd.getAllocator())
+ , m_UpdateSync(inFnd.getAllocator())
+ , m_GlobalTime(0)
+ , m_PerfTimer(NULL)
+ , m_DummyComponent(m_DummyTypeDesc)
+ , m_DummyContext(m_Foundation.getAllocator(), m_DummyComponent, m_ElementAccessMutex)
+ , m_Active(true)
+ , m_ScriptRequiresSort(true)
+ , m_Updating(false)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ Q3DStudio::CPresentation &GetPresentation() override { return m_Presentation; }
+
+ static void SortElementBuffer(nvvector<eastl::pair<element::SElement *, QT3DSU32>> &inBuffer)
+ {
+ eastl::sort(inBuffer.begin(), inBuffer.end(), SElementIndexPairSorter());
+ }
+
+ static void AddElementNodeToBuffer(nvvector<eastl::pair<element::SElement *, QT3DSU32>> &inBuffer,
+ SElement &inNode)
+ {
+ eastl::pair<element::SElement *, QT3DSU32> insertItem(&inNode, inNode.Depth());
+ QT3DS_ASSERT(eastl::find(inBuffer.begin(), inBuffer.end(), insertItem) == inBuffer.end());
+ inBuffer.push_back(insertItem);
+ }
+
+ TActivityItemBuffer GetActivatedItems() override { return m_ActivatedItems; }
+
+ TActivityItemBuffer GetDeactivatedItems() override { return m_DeactivatedItems; }
+ // All active items that are script enabled.
+ TActivityItemBuffer GetScriptItems() override
+ {
+ // Created in a delayed way.
+ if (m_ScriptRequiresSort) {
+ m_ScriptRequiresSort = false;
+ SortElementBuffer(m_ScriptItems);
+ }
+ return m_ScriptItems;
+ }
+
+ void SetZoneActive(bool inActive) override { m_Active = inActive; }
+ bool IsZoneActive() override { return m_Active; }
+
+ SActivationManagerNode *GetElementNodeForElement(TActivityItem item)
+ {
+ return &item.m_ActivationManagerNode;
+ }
+
+ STimeContext &GetItemTimeContext(SElement &inNode)
+ {
+ SElement &theComponent = inNode.GetComponentParent();
+ if (!theComponent.IsComponent()) {
+ QT3DS_ASSERT(false);
+ return m_DummyContext;
+ }
+
+ eastl::pair<TComponentTimeContextMap::iterator, bool> inserter = m_TimeContexts.insert(
+ eastl::make_pair(&theComponent, NVScopedRefCounted<STimeContext>()));
+ if (inserter.second) {
+ inserter.first->second = QT3DS_NEW(m_Foundation.getAllocator(), STimeContext)(
+ m_Foundation.getAllocator(), static_cast<SComponent &>(theComponent),
+ m_ElementAccessMutex);
+ STimeContext &theNewContext = *inserter.first->second;
+ if (theComponent.m_Parent == NULL)
+ m_RootContexts.push_back(theNewContext);
+ else {
+ STimeContext &parentContext = GetItemTimeContext(*theComponent.m_Parent);
+ parentContext.m_Children.push_back(theNewContext);
+ }
+ }
+ return *inserter.first->second.mPtr;
+ }
+
+ void AddActivityItems(TActivityItem inNode) override
+ {
+ if (inNode.m_Parent == NULL)
+ m_RootElements.push_back(&inNode);
+
+ GetItemTimeContext(inNode);
+ }
+
+ CTimePolicy *GetOwnedTimePolicy(TActivityItem item) override
+ {
+ return &GetItemTimeContext(item).m_TimePolicy;
+ }
+
+ virtual SComponentTimePolicyOverride *
+ GetOrCreateItemComponentOverride(TActivityItem item, float inMultiplier, TTimeUnit inEndTime,
+ IComponentTimeOverrideFinishedCallback *inCallback) override
+ {
+ STimeContext &theContext = GetItemTimeContext(item);
+
+ theContext.RemoveOverride();
+ theContext.m_TimePolicyOverride =
+ QT3DS_NEW(m_Foundation.getAllocator(),
+ SComponentTimePolicyOverride)(&item, inMultiplier, inEndTime, inCallback);
+ theContext.m_TimePolicy.SetPaused(false);
+
+ return theContext.m_TimePolicyOverride;
+ }
+
+ // If I am independent, then I am my own time parent.
+ // else travel up the chain till you find an indpendent node.
+ SElement &GetItemTimeParentNode(SElement &inNode)
+ {
+ if (inNode.m_Parent != NULL) {
+ SElement &theParent = *inNode.m_Parent;
+ if (theParent.IsIndependent())
+ return theParent;
+ return GetItemTimeParentNode(theParent);
+ }
+ // All roots are time independent by definition.
+ return inNode;
+ }
+
+ TActivityItemPtr GetItemTimeParent(SElement &inNode) override
+ {
+ return &GetItemTimeParentNode(inNode);
+ }
+
+ void InsertIntoAppropriateDirtyList(SElement &inNode)
+ {
+ // This may need to be faster at some point...
+ GetItemTimeContext(inNode).SetElementDirty(inNode);
+ }
+
+ bool GetItemUserActive(TActivityItem item) override { return item.IsExplicitActive(); }
+
+ void UpdateItemScriptStatus(TActivityItem item) override
+ {
+ if (item.IsGlobalActive()) {
+ STimeContext::UpdateItemScriptStatus(item, item.Flags().HasScriptCallbacks(),
+ m_ScriptItems);
+ m_ScriptRequiresSort = true;
+ }
+ }
+
+ void UpdateItemInfo(TActivityItem item) override { GetItemTimeContext(item).Reset(); }
+
+ // Order of events will be:
+ // 1. On Slide Change
+ // 2. Time Update
+ // 3. On Slide Change
+ // 4. Update Local Time
+ void OnSlideChange(TActivityItem item) override
+ {
+ STimeContext &theContext = GetItemTimeContext(item);
+ // Rebuilding the context sets all the elements dirty.
+ // This takes care of everything *but* the script item changes.
+ theContext.Reset();
+ theContext.RemoveOverride();
+ }
+
+ bool GetItemTimeActive(TActivityItem item) override
+ {
+ SActivationManagerNode *theNode = GetElementNodeForElement(item);
+ if (theNode)
+ return theNode->m_Flags.IsTimeActive();
+ return false;
+ }
+
+ TTimeUnit GetItemLocalTime(TActivityItem item) override
+ {
+ SElement *theElem = &item.GetComponentParent();
+ if (item.IsComponent() && item.m_Parent)
+ theElem = &item.m_Parent->GetComponentParent();
+
+ return GetItemTimeContext(*theElem).m_CurrentTime;
+ }
+
+ TTimeUnit GetItemComponentTime(TActivityItem item) override
+ {
+ return GetItemTimeContext(item).m_CurrentTime;
+ }
+
+ bool IsUpdating() override
+ {
+ Mutex::ScopedLock __locker(m_UpdateCheckMutex);
+ return m_Updating;
+ }
+
+ void EndUpdate() override
+ {
+ m_UpdateSync.reset();
+ while (IsUpdating())
+ m_UpdateSync.wait();
+ }
+
+ void DoUpdate()
+ {
+ SStackPerfTimer __timer(m_PerfTimer, "ActivationManager - DoUpdate");
+ if (m_Active) {
+ // We know that parent elements are added before children.
+ // So we know the time contexts are in an appropriate order, assuming they completely
+ // resolve their results before the next time context runs.
+ Q3DStudio::CComponentManager &theManager =
+ static_cast<Q3DStudio::CComponentManager &>(m_Presentation.GetComponentManager());
+ m_TimeContextScanBuffer.clear();
+
+ for (TTimeContextList::iterator iter = m_RootContexts.begin(),
+ end = m_RootContexts.end();
+ iter != end; ++iter)
+ m_TimeContextScanBuffer.push_back(&(*iter));
+
+ for (QT3DSU32 idx = 0, end = m_TimeContextScanBuffer.size(); idx < end; ++idx) {
+ STimeContext &theContext = *m_TimeContextScanBuffer[idx];
+ bool checkChildren =
+ theContext.Update(m_GlobalTime, m_ScanBuffer, m_TempDirtyList, m_ActivatedItems,
+ m_DeactivatedItems, m_ScriptItems, m_ScriptRequiresSort,
+ theManager, *m_PerfTimer, *this);
+ if (checkChildren) {
+ for (TTimeContextList::iterator timeIter = theContext.m_Children.begin(),
+ timeEnd = theContext.m_Children.end();
+ timeIter != timeEnd; ++timeIter) {
+ m_TimeContextScanBuffer.push_back(&(*timeIter));
+ }
+ end = m_TimeContextScanBuffer.size();
+ }
+ }
+ }
+
+ eastl::sort(m_ActivatedItems.begin(), m_ActivatedItems.end(), SElementIndexPairSorter());
+ eastl::sort(m_DeactivatedItems.begin(), m_DeactivatedItems.end(),
+ SElementIndexPairSorter());
+ Mutex::ScopedLock __locker(m_UpdateCheckMutex);
+ {
+ m_Updating = false;
+ m_UpdateSync.set();
+ }
+ }
+
+ static void UpdateCallback(void *data)
+ {
+ SActivityZone *theZone = reinterpret_cast<SActivityZone *>(data);
+ theZone->DoUpdate();
+ }
+
+ void BeginUpdate(TTimeUnit inGlobalTime, IPerfTimer &inPerfTimer,
+ IThreadPool &inThreadPool) override
+ {
+ // It is expected that an update is not running.
+ m_ActivatedItems.clear();
+ m_DeactivatedItems.clear();
+ m_GlobalTime = inGlobalTime;
+ m_PerfTimer = &inPerfTimer;
+ m_Updating = true;
+ inThreadPool.AddTask(this, UpdateCallback, NULL);
+ }
+
+ void GoToTime(TActivityItem inItem, TTimeUnit inTime) override
+ {
+ GetItemTimeContext(inItem).GoToTime(inTime);
+ }
+};
+
+struct SActivityZoneManager : public IActivityZoneManager
+{
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ // Zones may access the element mutex on destruction *so* it is important that
+ // it is destroyed *after* the zone list.
+ Mutex m_ElementAccessMutex;
+ nvvector<NVScopedRefCounted<SActivityZone>> m_Zones;
+ QT3DSI32 mRefCount;
+
+ SActivityZoneManager(NVFoundationBase &fnd, IStringTable &inStrTable)
+ : m_Foundation(fnd)
+ , m_StringTable(inStrTable)
+ , m_ElementAccessMutex(m_Foundation.getAllocator())
+ , m_Zones(m_Foundation.getAllocator(), "m_Zones")
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ IActivityZone &CreateActivityZone(Q3DStudio::CPresentation &inPresentation) override
+ {
+ m_Zones.push_back(QT3DS_NEW(m_Foundation.getAllocator(), SActivityZone)(
+ m_Foundation, inPresentation, m_StringTable, m_ElementAccessMutex));
+ return *m_Zones.back().mPtr;
+ }
+};
+}
+
+IActivityZoneManager &
+IActivityZoneManager::CreateActivityZoneManager(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SActivityZoneManager)(inFoundation, inStrTable);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICAnimationSystem.cpp b/src/Runtime/Source/Runtime/Source/UICAnimationSystem.cpp
new file mode 100644
index 00000000..3f62bd01
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICAnimationSystem.cpp
@@ -0,0 +1,477 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "RuntimePrefix.h"
+#include "UICTypes.h"
+#include "UICAnimationSystem.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSInvasiveSet.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSPool.h"
+#include "UICElementSystem.h"
+#include "UICCubicRoots.h"
+#include "UICBezierEval.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/IOStreams.h"
+#include "EASTL/sort.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSIndexableLinkedList.h"
+#include "UICBinarySerializationHelper.h"
+
+using namespace uic::runtime;
+using namespace uic::runtime::element;
+
+namespace {
+
+struct SAnimationKey
+{
+ QT3DSF32 m_Time; ///< Time
+ QT3DSF32 m_Value; ///< Value
+ QT3DSF32 m_C1Time; ///< Control 1 time
+ QT3DSF32 m_C1Value; ///< Control 1 value
+ QT3DSF32 m_C2Time; ///< Control 2 time
+ QT3DSF32 m_C2Value; ///< Control 2 value
+ SAnimationKey()
+ : m_Time(0)
+ , m_Value(0)
+ , m_C1Time(0)
+ , m_C1Value(0)
+ , m_C2Time(0)
+ , m_C2Value(0)
+ {
+ }
+
+ SAnimationKey(float time, float val, float c1time, float c1value, float c2time, float c2value)
+ : m_Time(time)
+ , m_Value(val)
+ , m_C1Time(c1time)
+ , m_C1Value(c1value)
+ , m_C2Time(c2time)
+ , m_C2Value(c2value)
+ {
+ }
+};
+
+struct SAnimationKeyNode
+{
+ enum {
+ AnimationKeyArraySize = 4,
+ };
+
+ SAnimationKey m_Data[AnimationKeyArraySize];
+ SAnimationKeyNode *m_NextNode;
+ SAnimationKeyNode()
+ : m_NextNode(NULL)
+ {
+ }
+};
+
+typedef IndexableLinkedList<SAnimationKeyNode, SAnimationKey,
+ SAnimationKeyNode::AnimationKeyArraySize>
+ TAnimationKeyNodeList;
+
+struct SAnimationTrack
+{
+ SElement *m_Element;
+ QT3DSI32 m_Id;
+ QT3DSU32 m_PropertyIndex;
+ QT3DSU32 m_KeyCount;
+ SAnimationKeyNode *m_Keys;
+ QT3DSU32 m_ActiveSetIndex;
+ bool m_Dynamic;
+
+ SAnimationTrack()
+ : m_Element(NULL)
+ , m_Id(0)
+ , m_PropertyIndex(0)
+ , m_KeyCount(0)
+ , m_Keys(NULL)
+ , m_ActiveSetIndex(QT3DS_MAX_U32)
+ , m_Dynamic(false)
+ {
+ }
+ SAnimationTrack(SElement &inElement, QT3DSI32 inId, QT3DSU32 inPropertyIndex, bool inIsDynamic)
+ : m_Element(&inElement)
+ , m_Id(inId)
+ , m_PropertyIndex(inPropertyIndex)
+ , m_KeyCount(0)
+ , m_Keys(NULL)
+ , m_ActiveSetIndex(QT3DS_MAX_U32)
+ , m_Dynamic(inIsDynamic)
+ {
+ }
+};
+
+struct GetAnimationTrackActiveSetIndex
+{
+ QT3DSU32 operator()(const SAnimationTrack &inTrack) const { return inTrack.m_ActiveSetIndex; }
+};
+
+struct SetAnimationTrackActiveSetIndex
+{
+ void operator()(SAnimationTrack &inTrack, QT3DSU32 inIdx) { inTrack.m_ActiveSetIndex = inIdx; }
+};
+
+typedef InvasiveSet<SAnimationTrack, GetAnimationTrackActiveSetIndex,
+ SetAnimationTrackActiveSetIndex>
+ TAnimationTrackActiveSet;
+
+struct SAnimationTrackComparator
+{
+ bool operator()(SAnimationTrack *lhs, SAnimationTrack *rhs) const
+ {
+ return lhs->m_Id < rhs->m_Id;
+ }
+};
+
+struct SAnimSystem : public IAnimationSystem
+{
+ typedef nvhash_map<QT3DSI32, SAnimationTrack *> TAnimationTrackHash;
+
+ NVFoundationBase &m_Foundation;
+ Pool<SAnimationTrack, ForwardingAllocator> m_AnimationTrackPool;
+ Pool<SAnimationKeyNode, ForwardingAllocator> m_AnimationKeyNodePool;
+ TAnimationTrackHash m_Tracks;
+ SAnimationTrack *m_LastInsertedTrack;
+ TAnimationTrackActiveSet m_ActiveSet;
+ NVDataRef<QT3DSU8> m_LoadData;
+ QT3DSI32 m_NextTrackId;
+ QT3DSI32 m_RefCount;
+
+ SAnimSystem(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , m_AnimationTrackPool(
+ ForwardingAllocator(inFoundation.getAllocator(), "AnimationTrackPool"))
+ , m_AnimationKeyNodePool(
+ ForwardingAllocator(inFoundation.getAllocator(), "AnimationKeyNodePool"))
+ , m_Tracks(inFoundation.getAllocator(), "m_Tracks")
+ , m_LastInsertedTrack(NULL)
+ , m_ActiveSet(inFoundation.getAllocator(), "m_ActiveSet")
+ , m_NextTrackId(1)
+ , m_RefCount(0)
+ {
+ }
+
+ static QT3DSI32 IncrementTrackId(QT3DSI32 inTrackId)
+ {
+ ++inTrackId;
+ if (!inTrackId)
+ ++inTrackId;
+ return inTrackId;
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc = m_Foundation.getAllocator();
+ NVDelete(alloc, this);
+ }
+ }
+
+ QT3DSI32 CreateAnimationTrack(element::SElement &inElement, QT3DSU32 inPropertyName,
+ bool inDynamic) override
+ {
+ // first, make sure we can find the property.
+ Option<QT3DSU32> theIndex = inElement.FindPropertyIndex(inPropertyName);
+ Option<TPropertyDescAndValuePtr> theProperty;
+ if (theIndex.hasValue())
+ theProperty = inElement.GetPropertyByIndex(*theIndex);
+
+ if (theProperty.hasValue() == false
+ || theProperty->first.m_Type != Q3DStudio::ATTRIBUTETYPE_FLOAT) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ eastl::pair<TAnimationTrackHash::iterator, bool> inserter;
+ // Find unused track id.
+ for (inserter = m_Tracks.insert(eastl::make_pair(m_NextTrackId, (SAnimationTrack *)NULL));
+ inserter.second == false; m_NextTrackId = IncrementTrackId(m_NextTrackId)) {
+ }
+
+ SAnimationTrack *theNewTrack =
+ reinterpret_cast<SAnimationTrack *>(m_AnimationTrackPool.allocate(__FILE__, __LINE__));
+ new (theNewTrack) SAnimationTrack(inElement, inserter.first->first, *theIndex, inDynamic);
+ inserter.first->second = theNewTrack;
+ m_LastInsertedTrack = theNewTrack;
+ ++m_NextTrackId;
+ return inserter.first->first;
+ }
+
+ SAnimationKey *GetKeyByIndex(QT3DSU32 inIndex, SAnimationTrack &inTrack)
+ {
+ if (inIndex >= inTrack.m_KeyCount)
+ return 0;
+
+ return &TAnimationKeyNodeList::GetObjAtIdx(inTrack.m_Keys, inIndex);
+ }
+
+ SAnimationKey &GetOrCreateKeyByIndex(QT3DSU32 inIndex, SAnimationTrack &inTrack)
+ {
+ if (inIndex < inTrack.m_KeyCount)
+ return *GetKeyByIndex(inIndex, inTrack);
+
+ return TAnimationKeyNodeList::Create(inTrack.m_Keys, inTrack.m_KeyCount,
+ m_AnimationKeyNodePool);
+ }
+
+ void AddKey(QT3DSF32 inTime, QT3DSF32 inValue, QT3DSF32 inC1Time, QT3DSF32 inC1Value,
+ QT3DSF32 inC2Time, QT3DSF32 inC2Value) override
+ {
+ if (m_LastInsertedTrack == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SAnimationKey &theNewKey =
+ GetOrCreateKeyByIndex(m_LastInsertedTrack->m_KeyCount, *m_LastInsertedTrack);
+ theNewKey = SAnimationKey(inTime, inValue, inC1Time, inC1Value, inC2Time, inC2Value);
+ }
+
+ SAnimationTrack *GetAnimationTrack(QT3DSI32 inTrackId)
+ {
+ TAnimationTrackHash::iterator iter = m_Tracks.find(inTrackId);
+ if (iter != m_Tracks.end())
+ return iter->second;
+ return NULL;
+ }
+
+ struct SNextKeyRetVal
+ {
+ SAnimationKeyNode *m_Node;
+ SAnimationKey *m_Start;
+ SAnimationKey *m_End;
+
+ SNextKeyRetVal(SAnimationKeyNode &inNode)
+ : m_Node(&inNode)
+ , m_Start(NULL)
+ , m_End(NULL)
+ {
+ }
+ SNextKeyRetVal(SAnimationKeyNode &inNode, SAnimationKey &inLastKey)
+ : m_Node(&inNode)
+ , m_Start(NULL)
+ , m_End(&inLastKey)
+ {
+ }
+ SNextKeyRetVal(SAnimationKeyNode &inNode, SAnimationKey &inStart, SAnimationKey &inLastKey)
+ : m_Node(&inNode)
+ , m_Start(&inStart)
+ , m_End(&inLastKey)
+ {
+ }
+ SNextKeyRetVal()
+ : m_Node(NULL)
+ , m_Start(NULL)
+ , m_End(NULL)
+ {
+ }
+ };
+
+ SNextKeyRetVal NextKeyIsGreaterThan(TAnimationKeyNodeList::iterator iter, QT3DSF32 inTime)
+ {
+ SAnimationKey *theStartKey = &(*iter);
+ QT3DSU32 nextIdx = iter.m_Idx + 1;
+ if (nextIdx == iter.m_Count)
+ return SNextKeyRetVal(*iter.m_Node, *theStartKey);
+
+ TAnimationKeyNodeList::iterator next = iter;
+ ++next;
+
+ SAnimationKey &nextKey = *next;
+
+ if (nextKey.m_Time >= inTime)
+ return SNextKeyRetVal(*iter.m_Node, *theStartKey, nextKey);
+ return SNextKeyRetVal(*iter.m_Node);
+ }
+
+ QT3DSF32 Evaluate(SAnimationTrack &inTrack, QT3DSF32 inTime)
+ {
+ if (inTrack.m_KeyCount < 2) {
+ if (inTrack.m_KeyCount == 1)
+ return GetKeyByIndex(0, inTrack)->m_Value;
+ return 0.0f;
+ }
+
+ TAnimationKeyNodeList::iterator iter =
+ TAnimationKeyNodeList::begin(inTrack.m_Keys, inTrack.m_KeyCount);
+
+ if ((*iter).m_Time >= inTime) {
+ return (*iter).m_Value;
+ }
+
+ // We know it isn't the first key.
+ SNextKeyRetVal theKeyData;
+ for (theKeyData = NextKeyIsGreaterThan(iter, inTime); theKeyData.m_End == NULL;
+ ++iter, theKeyData = NextKeyIsGreaterThan(iter, inTime)) {
+ }
+
+ if (theKeyData.m_Node == NULL && theKeyData.m_End == NULL) {
+ QT3DS_ASSERT(false);
+ return 0.0f;
+ }
+
+ if (theKeyData.m_Start != NULL) {
+ SAnimationKey &start(*theKeyData.m_Start);
+ SAnimationKey &end(*theKeyData.m_End);
+ return Q3DStudio::EvaluateBezierKeyframe(
+ inTime, start.m_Time, start.m_Value, start.m_C1Time, start.m_C1Value,
+ start.m_C2Time, start.m_C2Value, end.m_Time, end.m_Value);
+ }
+ return theKeyData.m_End->m_Value;
+ }
+
+ void Update() override
+ {
+ for (QT3DSU32 idx = 0, end = m_ActiveSet.size(); idx < end; ++idx) {
+ SAnimationTrack &theTrack = *m_ActiveSet[idx];
+ SElement &theElement = *theTrack.m_Element;
+ QT3DSF32 theTime = static_cast<QT3DSF32>(theElement.GetOuterTime());
+ TPropertyDescAndValuePtr theProperty =
+ *theElement.GetPropertyByIndex(theTrack.m_PropertyIndex);
+ Q3DStudio::UVariant &theValue(*theProperty.second);
+ QT3DSF32 newValue = Evaluate(theTrack, theTime);
+ if (fabs(theValue.m_FLOAT - newValue) > SElement::SmallestDifference()) {
+ theValue.m_FLOAT = newValue;
+ theElement.SetDirty();
+ }
+ }
+ }
+
+ void SetActive(QT3DSI32 inTrackId, bool inActive) override
+ {
+ SAnimationTrack *theTrack = GetAnimationTrack(inTrackId);
+ if (theTrack) {
+ if (inActive)
+ m_ActiveSet.insert(*theTrack);
+ else
+ m_ActiveSet.remove(*theTrack);
+ }
+ }
+ //==============================================================================
+ /**
+ * Recomputes control point values for Studio animation based off of new start
+ * value.
+ * @param inNewStartValue new start value for the keyframe
+ * @param inKeyStart start index of the keyframes
+ */
+ void RecomputeControlPoints(QT3DSF32 inNewStartValue, SAnimationTrack &inTrack)
+ {
+ SAnimationKey &theFirstKey = *GetKeyByIndex(0, inTrack);
+ SAnimationKey &theSecondKey = *GetKeyByIndex(1, inTrack);
+
+ // Determine original control point ratios
+ Q3DStudio::FLOAT theOriginalInterval =
+ (theSecondKey.m_Value - theFirstKey.m_Value) * (1.0f / 3.0f);
+ Q3DStudio::FLOAT theEaseOutRatio = theOriginalInterval != 0.0f
+ ? (theFirstKey.m_C1Value - theFirstKey.m_Value) / theOriginalInterval
+ : 0.0f;
+ Q3DStudio::FLOAT theEaseInRatio = theOriginalInterval != 0.0f
+ ? (theSecondKey.m_Value - theFirstKey.m_C2Value) / theOriginalInterval
+ : 0.0f;
+
+ // Apply ratios based off new start value
+ Q3DStudio::FLOAT theNewInterval = (theSecondKey.m_Value - inNewStartValue) * (1.0f / 3.0f);
+ theFirstKey.m_C1Value = inNewStartValue + (theNewInterval * theEaseOutRatio);
+ theFirstKey.m_C2Value = theSecondKey.m_Value - (theNewInterval * theEaseInRatio);
+ }
+
+ void UpdateDynamicKey(QT3DSI32 inTrackId) override
+ {
+ SAnimationTrack *theTrack = GetAnimationTrack(inTrackId);
+ if (theTrack && theTrack->m_Dynamic) {
+ SAnimationKey *theFirstKey = GetKeyByIndex(0, *theTrack);
+ if (theFirstKey) {
+ Q3DStudio::UVariant *thePropData =
+ theTrack->m_Element->GetPropertyByIndex(theTrack->m_PropertyIndex)->second;
+
+ // Recompute interpolation
+ if (theTrack->m_KeyCount > 1)
+ RecomputeControlPoints(thePropData->m_FLOAT, *theTrack);
+
+ // Update start value
+ theFirstKey->m_Value = thePropData->m_FLOAT;
+ }
+ }
+ }
+
+ void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream,
+ IElementAllocator &inElementAllocator) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriter(m_Foundation.getAllocator(), "WriteBuffer");
+ theWriter.write((QT3DSU32)m_Tracks.size());
+ theWriter.write(m_NextTrackId);
+ nvvector<SAnimationTrack *> tempTrackList(m_Foundation.getAllocator(), "TempTrackList");
+ tempTrackList.reserve(m_Tracks.size());
+ for (TAnimationTrackHash::iterator iter = m_Tracks.begin(), end = m_Tracks.end();
+ iter != end; ++iter)
+ tempTrackList.push_back(iter->second);
+ eastl::sort(tempTrackList.begin(), tempTrackList.end(), SAnimationTrackComparator());
+ for (QT3DSU32 idx = 0, end = tempTrackList.size(); idx < end; ++idx) {
+ SAnimationTrack &theTrack = *tempTrackList[idx];
+ size_t trackOffset = theWriter.size();
+ theWriter.write(theTrack);
+ SaveIndexableList<TAnimationKeyNodeList>(theTrack.m_Keys, theWriter);
+ SAnimationTrack *theWrittenTrack =
+ reinterpret_cast<SAnimationTrack *>(theWriter.begin() + trackOffset);
+ theWrittenTrack->m_Element =
+ inElementAllocator.GetRemappedElementAddress(theWrittenTrack->m_Element);
+ theWrittenTrack->m_ActiveSetIndex = QT3DS_MAX_U32;
+ }
+ ioStream.Write(theWriter.begin(), theWriter.size());
+ }
+
+ void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData, size_t inElementOffset) override
+ {
+ m_LoadData = inLoadData;
+
+ SDataReader theReader(inLoadData.begin(), inLoadData.end());
+ QT3DSU32 numTracks = *theReader.Load<QT3DSU32>();
+ m_NextTrackId = *theReader.Load<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numTracks; idx < end; ++idx) {
+ SAnimationTrack *theTrack = theReader.Load<SAnimationTrack>();
+ theTrack->m_Element = reinterpret_cast<SElement *>(
+ reinterpret_cast<size_t>(theTrack->m_Element) + inElementOffset);
+ m_Tracks.insert(eastl::make_pair(theTrack->m_Id, theTrack));
+
+ LoadIndexableList<TAnimationKeyNodeList>(theTrack->m_Keys, theTrack->m_KeyCount,
+ theReader);
+ }
+ }
+};
+}
+
+IAnimationSystem &IAnimationSystem::CreateAnimationSystem(NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SAnimSystem)(inFoundation);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICApplication.cpp b/src/Runtime/Source/Runtime/Source/UICApplication.cpp
new file mode 100644
index 00000000..aef4f8b6
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICApplication.cpp
@@ -0,0 +1,2499 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// We need a Qt header first here because Qt's metatype system insists that Bool
+// can not be defined first before Qt headers are included and the includes below
+// define Bool by way of Xll/XLib.h via khronos -> egl -> X11
+#include <QImage>
+
+#include "RuntimePrefix.h"
+#include "UICApplication.h"
+#include "UICApplicationValues.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICMemory.h"
+#include "UICRuntimeFactory.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/FileTools.h"
+#include "UICIScriptBridge.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/XML.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSContainers.h"
+#include "EASTL/hash_map.h"
+#include "UICPresentation.h"
+#include "UICInputEventTypes.h"
+#include "UICSceneManager.h"
+#include "UICIScene.h"
+#include "UICInputEngine.h"
+#include "UICStateVisualBindingContext.h"
+#include "UICMetadata.h"
+#include "UICUIPParser.h"
+#include "UICBinarySerializer.h"
+#include "foundation/Socket.h"
+#include "UICStateDebugStreams.h"
+#include "UICSceneGraphDebugger.h"
+#include "UICSceneGraphDebuggerValue.h"
+#include "EventPollingSystem.h"
+#include "UICRenderContext.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/SerializationTypes.h"
+#include "EASTL/sort.h"
+#include "UICRenderBufferLoader.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSync.h"
+#include "UICTextRenderer.h"
+#include "UICRenderThreadPool.h"
+#include "foundation/StringConversionImpl.h"
+#include "UICRenderLoadedTexture.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICActivationManager.h"
+#include "UICRenderer.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICAudioPlayer.h"
+#include "UICElementSystem.h"
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qpair.h>
+
+using namespace uic;
+using namespace uic::runtime;
+using namespace Q3DStudio;
+using uic::state::debugger::ISceneGraphRuntimeDebugger;
+using uic::state::debugger::SSGPropertyChange;
+
+namespace qt3ds {
+namespace foundation {
+template <>
+struct StringConversion<QT3DSVec2>
+{
+ void StrTo(const char8_t *buffer, QT3DSVec2 &item)
+ {
+ char *endPtr = NULL;
+ item.x = (float)strtod(buffer, &endPtr);
+ if (endPtr)
+ item.y = (float)strtod(endPtr, NULL);
+ }
+};
+}
+}
+
+namespace {
+struct SDebugSettings
+{
+ eastl::string m_Server;
+ int m_Port;
+ bool m_Listen;
+ SDebugSettings()
+ : m_Port(0)
+ , m_Listen(false)
+ {
+ }
+};
+
+struct SFrameTimer
+{
+ int m_FrameCount;
+ QT3DSU64 m_FrameTime;
+ SFrameTimer(QT3DSU64 fc = 0)
+ : m_FrameCount(fc)
+ , m_FrameTime(qt3ds::foundation::Time::getCurrentCounterValue())
+ {
+ }
+
+ QT3DSF32 GetElapsedSeconds(QT3DSU64 currentTime) const
+ {
+ QT3DSU64 diff = currentTime - m_FrameTime;
+ QT3DSF32 diffNanos
+ = static_cast<QT3DSF32>(qt3ds::foundation::Time::sCounterFreq.toTensOfNanos(diff));
+ return diffNanos / qt3ds::foundation::Time::sNumTensOfNanoSecondsInASecond;
+ }
+
+ QT3DSF32 GetElapsedSeconds() const
+ {
+ return GetElapsedSeconds(qt3ds::foundation::Time::getCurrentCounterValue());
+ }
+
+ QPair<QT3DSF32, int> GetFPS(int updateFC)
+ {
+ int elapsedFrames = updateFC - m_FrameCount;
+ QT3DSU64 currentTime = qt3ds::foundation::Time::getCurrentCounterValue();
+ QT3DSF32 elapsedSeconds = GetElapsedSeconds(currentTime);
+ QT3DSF32 retval = elapsedFrames / elapsedSeconds;
+ m_FrameCount = updateFC;
+ m_FrameTime = currentTime;
+ return qMakePair(retval, elapsedFrames);
+ }
+};
+
+struct SRefCountedAssetValue : public SAssetValue
+{
+ NVFoundationBase &m_Foundation;
+ QT3DSI32 mRefCount;
+ SRefCountedAssetValue(NVFoundationBase &fnd)
+ : SAssetValue()
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SAssetValue &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SPresentationAsset &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SBehaviorAsset &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SRenderPluginAsset &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ SRefCountedAssetValue(NVFoundationBase &fnd, const SSCXMLAsset &asset)
+ : SAssetValue(asset)
+ , m_Foundation(fnd)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+};
+
+typedef nvhash_map<CRegisteredString, NVScopedRefCounted<SRefCountedAssetValue>> TIdAssetMap;
+typedef nvhash_map<THashValue, CRegisteredString> THashStrMap;
+typedef nvvector<eastl::pair<CRegisteredString, NVScopedRefCounted<SRefCountedAssetValue>>>
+TIdAssetList;
+typedef eastl::pair<QT3DSU32, TElement *> THandleElementPair;
+typedef NVConstDataRef<THandleElementPair> THandleElementDataBuffer;
+typedef nvvector<THandleElementDataBuffer> THandleElementDataBufferList;
+typedef nvhash_map<QT3DSU32, TElement *> THandleElementMap;
+
+struct SHandleElementPairComparator
+{
+ bool operator()(const THandleElementPair &lhs, const THandleElementPair &rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+};
+
+struct SApp;
+
+class IAppLoadContext : public NVRefCounted
+{
+public:
+ virtual void EndLoad() = 0;
+ virtual void OnGraphicsInitialized(IRuntimeFactory &inFactory) = 0;
+ virtual bool HasCompletedLoading() = 0;
+ static IAppLoadContext &CreateXMLLoadContext(
+ SApp &inApp, NVConstDataRef<uic::state::SElementReference> inStateReferences,
+ const char8_t *inScaleMode);
+ static IAppLoadContext &CreateBinaryLoadContext(SApp &inApp,
+ uic::render::ScaleModes::Enum inScaleMode,
+ NVDataRef<QT3DSU8> inStrTableData);
+};
+
+inline float Clamp(float val, float inMin = 0.0f, float inMax = 1.0f)
+{
+ if (val < inMin)
+ return inMin;
+ if (val > inMax)
+ return inMax;
+ return val;
+}
+
+// A set of common settings that may come from the UIA or from the command line.
+// command line settings always override uia settings.
+struct SApplicationSettings
+{
+ Option<bool> m_LayerCacheEnabled;
+ Option<bool> m_LayerGpuProfilingEnabled;
+ Option<bool> m_ShaderCachePersistenceEnabled;
+
+ SApplicationSettings() {}
+
+ template <typename TDataType>
+ static Option<TDataType> Choose(const Option<TDataType> &inCommandLine,
+ const Option<TDataType> &inUIAFile)
+ {
+ if (inCommandLine.hasValue())
+ return inCommandLine;
+ return inUIAFile;
+ }
+
+ SApplicationSettings(const SApplicationSettings &inCommandLine,
+ const SApplicationSettings &inUIAFileSettings)
+ : m_LayerCacheEnabled(
+ Choose(inCommandLine.m_LayerCacheEnabled, inUIAFileSettings.m_LayerCacheEnabled))
+ , m_LayerGpuProfilingEnabled(Choose(inCommandLine.m_LayerGpuProfilingEnabled,
+ inUIAFileSettings.m_LayerGpuProfilingEnabled))
+ , m_ShaderCachePersistenceEnabled(Choose(inCommandLine.m_ShaderCachePersistenceEnabled,
+ inUIAFileSettings.m_ShaderCachePersistenceEnabled))
+ {
+ }
+
+ static const char8_t *LayerCacheName() { return "layer-caching"; }
+ static const char8_t *LayerGpuProfilerName() { return "layer-gpu-profiling"; }
+ static const char8_t *ShaderCacheName() { return "shader-cache-persistence"; }
+
+ void ParseBoolEnableDisableItem(const IDOMReader &inReader, const char8_t *itemName,
+ Option<bool> &itemValue)
+ {
+ const char8_t *inItem;
+ if (const_cast<IDOMReader &>(inReader).UnregisteredAtt(itemName, inItem)) {
+ if (AreEqualCaseless(inItem, "disabled"))
+ itemValue = false;
+ else
+ itemValue = true;
+ }
+ }
+
+ void ParseBoolEnableDisableItem(const eastl::vector<eastl::string> &inCommandLine,
+ const char8_t *itemName, Option<bool> &itemValue)
+ {
+ eastl::string temp;
+ temp.assign("-");
+ temp.append(itemName);
+ for (QT3DSU32 idx = 0, end = inCommandLine.size(); idx < end; ++idx) {
+ if (inCommandLine[idx].find(temp) == 0) {
+ if (inCommandLine[idx].length() == temp.size()) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Unable to parse parameter %s. Please pass =enable|disable as "
+ << "part of the parameter. " << temp.c_str();
+ } else {
+ temp = inCommandLine[idx].substr(temp.size() + 1);
+ eastl::string::size_type start = temp.find_first_of("'\"");
+ if (start != eastl::string::npos)
+ temp.erase(0, start);
+
+ eastl::string::size_type end = temp.find_first_of("'\"");
+ if (end != eastl::string::npos)
+ temp.erase(end);
+ if (AreEqualCaseless(temp.c_str(), "disabled"))
+ itemValue = false;
+ else
+ itemValue = true;
+ qCInfo(qt3ds::INVALID_OPERATION)
+ << "Item " << itemName
+ << (itemValue ? " enabled" : " disabled");
+ }
+ }
+ }
+ }
+
+ template <typename TReaderType>
+ void ParseItems(const TReaderType &inReader)
+ {
+ ParseBoolEnableDisableItem(inReader, LayerCacheName(), m_LayerCacheEnabled);
+ ParseBoolEnableDisableItem(inReader, LayerGpuProfilerName(), m_LayerGpuProfilingEnabled);
+ ParseBoolEnableDisableItem(inReader, ShaderCacheName(), m_ShaderCachePersistenceEnabled);
+ }
+
+ void Parse(IDOMReader &inReader) { ParseItems(inReader); }
+
+ void Parse(const eastl::vector<eastl::string> &inCommandLine) { ParseItems(inCommandLine); }
+
+ struct SOptionSerializer
+ {
+ bool m_HasValue;
+ bool m_Value;
+ QT3DSU8 m_Padding[2];
+ SOptionSerializer(const Option<bool> &inValue = Empty())
+ : m_HasValue(inValue.hasValue())
+ , m_Value(inValue.hasValue() ? *inValue : false)
+ {
+ m_Padding[0] = 0;
+ m_Padding[1] = 0;
+ }
+
+ operator Option<bool>() const
+ {
+ if (m_HasValue)
+ return m_Value;
+ return Empty();
+ }
+ };
+
+ void Save(IOutStream &outStream) const
+ {
+ outStream.Write(SOptionSerializer(m_LayerCacheEnabled));
+ outStream.Write(SOptionSerializer(m_LayerGpuProfilingEnabled));
+ outStream.Write(SOptionSerializer(m_ShaderCachePersistenceEnabled));
+ }
+
+ void Load(IInStream &inStream)
+ {
+ SOptionSerializer s;
+ inStream.Read(s);
+ m_LayerCacheEnabled = s;
+ inStream.Read(s);
+ m_LayerGpuProfilingEnabled = s;
+ inStream.Read(s);
+ m_ShaderCachePersistenceEnabled = s;
+ }
+};
+
+struct SDummyAudioPlayer : public IAudioPlayer
+{
+ virtual ~SDummyAudioPlayer() {}
+ bool PlaySoundFile(const char *inFilePath) override
+ {
+ (void *)inFilePath;
+ qCWarning(qt3ds::TRACE_INFO)
+ << "UICTegraApplication: Unimplemented method IAudioPlayer::PlaySoundFile";
+ return false;
+ }
+} g_DummyAudioPlayer;
+
+struct SAudioPlayerWrapper : public IAudioPlayer
+{
+private:
+ IApplication *m_Application;
+ IAudioPlayer *m_RealPlayer;
+
+public:
+ SAudioPlayerWrapper()
+ : m_Application(0)
+ , m_RealPlayer(&g_DummyAudioPlayer)
+ {
+ }
+ virtual ~SAudioPlayerWrapper() {}
+
+ void SetApplication(IApplication &inApplication) { m_Application = &inApplication; }
+
+ void SetPlayer(IAudioPlayer *inPlayer)
+ {
+ if (inPlayer)
+ m_RealPlayer = inPlayer;
+ else
+ m_RealPlayer = &g_DummyAudioPlayer;
+ }
+
+ bool PlaySoundFile(const char *inFilePath) override
+ {
+ eastl::string theFilePath(nonNull(inFilePath));
+ if (m_RealPlayer != &g_DummyAudioPlayer) {
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(
+ m_Application->GetProjectDirectory().c_str(), inFilePath, theFilePath);
+ }
+ return m_RealPlayer->PlaySoundFile(theFilePath.c_str());
+ }
+};
+
+struct SApp : public IApplication
+{
+
+ NVScopedRefCounted<Q3DStudio::IRuntimeFactoryCore> m_CoreFactory;
+ NVScopedRefCounted<Q3DStudio::IRuntimeFactory> m_RuntimeFactory;
+
+ Q3DStudio::CInputEngine *m_InputEnginePtr;
+ CAppStr m_ApplicationDir;
+ CAppStr m_ProjectDir;
+ Option<SDebugSettings> m_DebugSettings;
+ CAppStr m_InitialPresentationId;
+ CAppStr m_DLLDirectory;
+ TIdAssetMap m_AssetMap;
+ // Keep the assets ordered. This enables the uia order to mean something.
+ TIdAssetList m_OrderedAssets;
+ SPickFrame m_PickFrame;
+ SPickFrame m_MousePickCache;
+ SPickFrame m_MouseOverCache;
+ THashStrMap m_HashStrMap;
+ CTimer m_Timer;
+ Q3DStudio::INT64 m_ManualTime;
+ SFrameTimer m_FrameTimer;
+ Q3DStudio::INT32 m_FrameCount;
+ // the name of the file without extension.
+ eastl::string m_Filename;
+
+ qt3ds::foundation::NVScopedReleasable<IRuntimeMetaData> m_MetaData;
+ nvvector<eastl::pair<SBehaviorAsset, bool>> m_Behaviors;
+ NVScopedRefCounted<SocketSystem> m_SocketSystem;
+ NVScopedRefCounted<SocketStream> m_ServerStream;
+ NVScopedRefCounted<uic::state::debugger::IMultiProtocolSocket> m_ProtocolSocket;
+ NVScopedRefCounted<uic::state::debugger::IDebugger> m_StateDebugger;
+ NVScopedRefCounted<ISceneGraphRuntimeDebugger> m_SceneGraphDebugger;
+ NVScopedRefCounted<IActivityZoneManager> m_ActivityZoneManager;
+ NVScopedRefCounted<IElementAllocator> m_ElementAllocator;
+ nvvector<SSGPropertyChange> m_ChangeBuffer;
+
+ // Handles are loaded sorted but only added to the handle map when needed.
+ nvvector<char8_t> m_LoadBuffer;
+ nvvector<CPresentation *> m_PresentationBuffer;
+ Mutex m_RunnableMutex;
+ nvvector<NVScopedRefCounted<IAppRunnable>> m_ThreadRunnables;
+ nvvector<NVScopedRefCounted<IAppRunnable>> m_MainThreadRunnables;
+ NVScopedRefCounted<IAppLoadContext> m_AppLoadContext;
+ bool m_HideFPS;
+ bool m_DisableState;
+ bool m_ProfileLogging;
+ bool m_LastRenderWasDirty;
+ QT3DSVec2 m_WatermarkCoordinates;
+ QT3DSU64 m_LastFrameStartTime;
+ QT3DSU64 m_ThisFrameStartTime;
+ double m_MillisecondsSinceLastFrame;
+ // We get odd oscillations if we do are too quick to report that the frame wasn't dirty
+ // after input.
+ int m_DirtyCountdown;
+ SApplicationSettings m_UIAFileSettings;
+ eastl::pair<NVDataRef<Q3DStudio::TElement *>, size_t> m_ElementLoadResult;
+
+ SAudioPlayerWrapper m_AudioPlayer;
+
+ UICAssetVisitor *m_visitor;
+
+ QT3DSI32 mRefCount;
+ SApp(Q3DStudio::IRuntimeFactoryCore &inFactory, const char8_t *inAppDir)
+ : m_CoreFactory(inFactory)
+ , m_InputEnginePtr(NULL)
+ , m_ApplicationDir(inFactory.GetFoundation().getAllocator())
+ , m_ProjectDir(inFactory.GetFoundation().getAllocator())
+ , m_InitialPresentationId(inFactory.GetFoundation().getAllocator())
+ , m_DLLDirectory(inFactory.GetFoundation().getAllocator())
+ , m_AssetMap(inFactory.GetFoundation().getAllocator(), "SApp::m_AssetMap")
+ , m_OrderedAssets(inFactory.GetFoundation().getAllocator(), "SApp::m_OrderedAssets")
+ , m_HashStrMap(inFactory.GetFoundation().getAllocator(), "SApp::m_HashStrMap")
+ , m_Timer(inFactory.GetTimeProvider())
+ , m_ManualTime(0)
+ , m_FrameCount(0)
+ , m_Behaviors(inFactory.GetFoundation().getAllocator(), "SApp::m_Behaviors")
+ , m_ActivityZoneManager(IActivityZoneManager::CreateActivityZoneManager(
+ inFactory.GetFoundation(), inFactory.GetStringTable()))
+ , m_ElementAllocator(IElementAllocator::CreateElementAllocator(inFactory.GetFoundation(),
+ inFactory.GetStringTable()))
+ , m_ChangeBuffer(inFactory.GetFoundation().getAllocator(), "SApp::m_ChangeBuffer")
+ , m_LoadBuffer(inFactory.GetFoundation().getAllocator(), "SApp::m_LoadBuffer")
+ , m_PresentationBuffer(inFactory.GetFoundation().getAllocator(),
+ "SApp::m_PresentationBuffer")
+ , m_RunnableMutex(inFactory.GetFoundation().getAllocator())
+ , m_ThreadRunnables(inFactory.GetFoundation().getAllocator(), "SApp::m_ThreadRunnables")
+ , m_MainThreadRunnables(inFactory.GetFoundation().getAllocator(),
+ "SApp::m_MainThreadRunnables")
+ , m_HideFPS(false)
+ , m_DisableState(false)
+ , m_ProfileLogging(false)
+ , m_LastRenderWasDirty(true)
+ , m_WatermarkCoordinates(1.0f, 1.0f)
+ , m_LastFrameStartTime(0)
+ , m_ThisFrameStartTime(0)
+ , m_MillisecondsSinceLastFrame(0)
+ , m_DirtyCountdown(5)
+ , mRefCount(0)
+ , m_visitor(nullptr)
+ {
+ m_AudioPlayer.SetApplication(*this);
+ eastl::string tempStr(inAppDir);
+ CFileTools::NormalizePath(tempStr);
+ m_ApplicationDir.assign(tempStr.c_str());
+
+ Q3DStudio_memset(&m_PickFrame, 0, sizeof(SPickFrame));
+ Q3DStudio_memset(&m_MousePickCache, 0, sizeof(SPickFrame));
+ Q3DStudio_memset(&m_MouseOverCache, 0, sizeof(SPickFrame));
+
+ m_Timer.Start();
+
+ m_CoreFactory->SetApplicationCore(this);
+ m_CoreFactory->GetScriptEngine().SetApplicationCore(*this);
+ m_CoreFactory->GetScriptEngineQml().SetApplicationCore(*this);
+
+ // To make examples & tests load nicely, add qt bin dir into search path.
+ // TODO: Remove this once resources are baked into the library as qrc.
+ QString qtBin = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+ m_CoreFactory->AddSearchPath(qtBin.toLatin1().constData());
+
+ m_CoreFactory->AddSearchPath(tempStr.c_str());
+ }
+
+ ~SApp()
+ {
+ EndLoad();
+ {
+ Mutex::ScopedLock __locker(m_RunnableMutex);
+ m_ThreadRunnables.clear();
+ }
+ // Ensure we stop the timer.
+ HasCompletedLoading();
+ m_CoreFactory->GetScriptEngine().EndPreloadScripts();
+ m_AppLoadContext = NULL;
+
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ SAssetValue &theAsset = *m_OrderedAssets[idx].second;
+ if (theAsset.getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &thePresAsset = *theAsset.getDataPtr<SPresentationAsset>();
+ if (thePresAsset.m_Presentation) {
+ Q3DStudio_delete(thePresAsset.m_Presentation, CPresentation);
+ thePresAsset.m_Presentation = NULL;
+ }
+ }
+ }
+ }
+
+ void setAssetVisitor(uic::UICAssetVisitor *v) override
+ {
+ m_visitor = v;
+ }
+
+ NVDataRef<CPresentation *> GetPresentations()
+ {
+ if (m_PresentationBuffer.empty()) {
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ SAssetValue &theAsset = *m_OrderedAssets[idx].second;
+ if (theAsset.getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &thePresAsset = *theAsset.getDataPtr<SPresentationAsset>();
+ if (thePresAsset.m_Presentation)
+ m_PresentationBuffer.push_back(thePresAsset.m_Presentation);
+ }
+ }
+ }
+ return m_PresentationBuffer;
+ }
+
+ void addRef() override { atomicIncrement(&mRefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0)
+ NVDelete(m_CoreFactory->GetFoundation().getAllocator(), this);
+ }
+
+ void QueueForMainThread(IAppRunnable &inRunnable) override
+ {
+ Mutex::ScopedLock __locker(m_RunnableMutex);
+ m_ThreadRunnables.push_back(inRunnable);
+ }
+
+ // Debugging is disabled by default.
+ void EnableDebugging(bool inListen, const char8_t *inServer = NULL, int inPort = 0) override
+ {
+ SDebugSettings theSettings;
+ theSettings.m_Server.assign(nonNull(inServer));
+ if (theSettings.m_Server.size() == 0)
+ theSettings.m_Server = "localhost";
+ theSettings.m_Port = inPort;
+ if (!inPort)
+ theSettings.m_Port = 8172;
+ theSettings.m_Listen = inListen;
+ m_DebugSettings = theSettings;
+ // Done at load time only.
+ }
+
+ // state machine is enabled by default
+ void DisableStateMachine() override { m_DisableState = true; }
+
+ virtual void EnableProfileLogging()
+ {
+ m_ProfileLogging = true;
+ if (m_RuntimeFactory)
+ m_RuntimeFactory->GetScriptEngine().EnableProfiling();
+ }
+
+ // Verbose logging is disabled by default.
+ virtual void SetVerboseLogging(bool inEnableVerboseLogging)
+ {
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Update rhythm implementations
+ ////////////////////////////////////////////////////////////////////////////
+
+ void SetPickFrame(const SPickFrame &inPickFrame)
+ {
+ // The model has changed, fire enter and exit mouse events
+ if (inPickFrame.m_Model != m_PickFrame.m_Model) {
+ // For determining onGroupedMouseOver/Out:
+ // arg1 = the original onMouseOut model and arg2 = the original onMouseOver model
+ UVariant theMouseOutModel;
+ UVariant theMouseOverModel;
+ theMouseOutModel.m_VoidPointer = m_PickFrame.m_Model;
+ theMouseOverModel.m_VoidPointer = inPickFrame.m_Model;
+
+ // It seems like you would want to 'onMouseOut' before you 'onMouseOver' something new?
+ if (m_PickFrame.m_Model) {
+ m_PickFrame.m_Model->GetBelongedPresentation()->FireEvent(
+ ON_MOUSEOUT, m_PickFrame.m_Model, &theMouseOutModel, &theMouseOverModel,
+ ATTRIBUTETYPE_POINTER, ATTRIBUTETYPE_POINTER);
+ }
+ if (inPickFrame.m_Model) {
+ inPickFrame.m_Model->GetBelongedPresentation()->FireEvent(
+ ON_MOUSEOVER, inPickFrame.m_Model, &theMouseOutModel, &theMouseOverModel,
+ ATTRIBUTETYPE_POINTER, ATTRIBUTETYPE_POINTER);
+ m_MouseOverCache = inPickFrame;
+ }
+ }
+
+ const TEventCommandHash *theEventArray[] = { &ON_MOUSEDOWN, &ON_MOUSEUP,
+ &ON_MIDDLEMOUSEDOWN, &ON_MIDDLEMOUSEUP,
+ &ON_RIGHTMOUSEDOWN, &ON_RIGHTMOUSEUP };
+ const TEventCommandHash *theClickEventArray[] = { &ON_MOUSECLICK, &ON_MIDDLEMOUSECLICK,
+ &ON_RIGHTMOUSECLICK };
+
+ // Click events...
+ // NOTE: This is a fancy way to iterate programatically over all the handled mouse inputs
+ // handled (declared in AKPickFrame.h for now)
+ // we iterate to INPUTBUTTONCOUNT (see comment in AKPickFrame.h) * 2, because we handle
+ // mouse down and up
+ for (QT3DSI32 theMouseEvtIter = 0; theMouseEvtIter < MOUSEBUTTONCOUNT - 1;
+ theMouseEvtIter++) {
+ // we effectively iterate to MOUSEBUTTONCOUNT * 2 (see comment in AKPickFrame.h) to
+ // handle mouse down and up
+ QT3DSI32 theMouseDownFlag = 1 << (theMouseEvtIter * 2);
+ QT3DSI32 theMouseUpFlag = 1 << (theMouseEvtIter * 2 + 1);
+
+ // on*MouseDown
+ // if this frame, the mouse button is down, and last frame it wasn't (new down click)
+ if (inPickFrame.m_Model && inPickFrame.m_InputFrame.m_MouseFlags & theMouseDownFlag
+ && !(m_PickFrame.m_InputFrame.m_MouseFlags & theMouseDownFlag)) {
+ // fire the 'on*MouseDown' event - which is at the even indices since the down
+ // events for each button are before the up
+ inPickFrame.m_Model->GetBelongedPresentation()->FireEvent(
+ *theEventArray[theMouseEvtIter * 2], inPickFrame.m_Model);
+
+ // cache this as the last item we 'onMouseDown' on
+ m_MousePickCache = inPickFrame;
+ }
+
+ // on*MouseUp
+ // if we mouse up on anything, send the event
+ if (inPickFrame.m_InputFrame.m_MouseFlags & theMouseUpFlag) {
+ // fire the 'on*MouseUp' event - odd indices (1,3,5 etc)
+ if (m_MousePickCache.m_Model) {
+ m_MousePickCache.m_Model->GetBelongedPresentation()->FireEvent(
+ *theEventArray[theMouseEvtIter * 2 + 1], m_MousePickCache.m_Model);
+ }
+
+ // on*MouseClick
+ // if we had a up click on the same item we were mouse down on last frame ... we had
+ // a click
+ if (inPickFrame.m_Model && inPickFrame.m_Model == m_MousePickCache.m_Model) {
+ inPickFrame.m_Model->GetBelongedPresentation()->FireEvent(
+ *theClickEventArray[theMouseEvtIter], inPickFrame.m_Model);
+ }
+
+ // clear the stored 'last mouse down' since we just got a mouse up
+ Q3DStudio_memset(&m_MousePickCache, 0, sizeof(SPickFrame));
+ }
+
+ // on*MouseDblClick
+ }
+
+ if (m_MouseOverCache.m_Model) {
+
+ if (inPickFrame.m_InputFrame.m_MouseFlags & VSCROLLWHEEL) {
+ UVariant theScrollValue;
+ theScrollValue.m_INT32 = inPickFrame.m_InputFrame.m_ScrollValue;
+ m_MouseOverCache.m_Model->GetBelongedPresentation()->FireEvent(
+ ON_VERTICALSCROLLWHEEL, m_MouseOverCache.m_Model, &theScrollValue,
+ NULL, ATTRIBUTETYPE_INT32);
+ } else if (inPickFrame.m_InputFrame.m_MouseFlags & HSCROLLWHEEL) {
+ UVariant theScrollValue;
+ theScrollValue.m_INT32 = inPickFrame.m_InputFrame.m_ScrollValue;
+ m_MouseOverCache.m_Model->GetBelongedPresentation()->FireEvent(
+ ON_HORIZONTALSCROLLWHEEL, m_MouseOverCache.m_Model, &theScrollValue,
+ NULL, ATTRIBUTETYPE_INT32);
+ }
+ }
+
+ // Do this last
+ m_PickFrame = inPickFrame;
+ }
+
+ void ClearPresentationDirtyLists()
+ {
+ NVDataRef<CPresentation *> thePresentations(GetPresentations());
+ for (QT3DSU32 idx = 0, end = thePresentations.size(); idx < end; ++idx)
+ thePresentations[idx]->ClearDirtyList();
+ }
+
+ void UpdatePresentations()
+ {
+ SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(), "UpdatePresentations");
+ // Transfer the input frame to the kernel for pick processing
+ // the scene manager now handles the picking on each of its scenes
+ SetPickFrame(m_RuntimeFactory->GetSceneManager().AdvancePickFrame(
+ m_InputEnginePtr->GetInputFrame()));
+ // clear up mouse flag for horizontal and vertical scroll
+ m_InputEnginePtr->GetInputFrame().m_MouseFlags &= !(HSCROLLWHEEL | VSCROLLWHEEL);
+
+ // Update all the presentations.
+ // Animations are advanced based on m_Timer by default, but this can be overridden via
+ // SetTimeMilliSecs().
+ Q3DStudio::INT64 globalTime(GetTimeMilliSecs());
+
+ NVDataRef<CPresentation *> thePresentations(GetPresentations());
+
+ {
+ SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(),
+ "UpdatePresentations - pre update");
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ if (m_OrderedAssets[idx].second->getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &theAsset(
+ *m_OrderedAssets[idx].second->getDataPtr<SPresentationAsset>());
+ CPresentation *thePresentation = theAsset.m_Presentation;
+ if (thePresentation && thePresentation->GetActive())
+ thePresentation->PreUpdate(globalTime);
+ }
+ }
+ }
+ {
+ SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(),
+ "UpdatePresentations - begin update");
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ if (m_OrderedAssets[idx].second->getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &theAsset(
+ *m_OrderedAssets[idx].second->getDataPtr<SPresentationAsset>());
+ CPresentation *thePresentation = theAsset.m_Presentation;
+ if (thePresentation && thePresentation->GetActive())
+ thePresentation->BeginUpdate();
+ }
+ }
+ }
+ {
+ SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(),
+ "UpdatePresentations - end update");
+
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ if (m_OrderedAssets[idx].second->getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &theAsset(
+ *m_OrderedAssets[idx].second->getDataPtr<SPresentationAsset>());
+ CPresentation *thePresentation = theAsset.m_Presentation;
+ if (thePresentation && thePresentation->GetActive())
+ thePresentation->EndUpdate();
+ }
+ }
+ }
+ {
+ SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(),
+ "UpdatePresentations - postupdate");
+
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ if (m_OrderedAssets[idx].second->getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &theAsset(
+ *m_OrderedAssets[idx].second->getDataPtr<SPresentationAsset>());
+ CPresentation *thePresentation = theAsset.m_Presentation;
+ if (thePresentation && thePresentation->GetActive())
+ thePresentation->PostUpdate(globalTime);
+ }
+ }
+ }
+
+ // Run the garbage collection
+ m_CoreFactory->GetScriptEngine().StepGC();
+ }
+
+ void UpdateScenes() { m_RuntimeFactory->GetSceneManager().Update(); }
+
+ void Render()
+ {
+ SStackPerfTimer __updateTimer(m_RuntimeFactory->GetPerfTimer(), "Render");
+ CPresentation *pres = GetPrimaryPresentation();
+ if (pres)
+ m_LastRenderWasDirty = m_RuntimeFactory->GetSceneManager().RenderPresentation(pres);
+ }
+
+ void ResetDirtyCounter() { m_DirtyCountdown = 5; }
+
+ // Update all the presentations and render them.
+ void UpdateAndRender() override
+ {
+ QT3DS_ASSERT(m_AppLoadContext.mPtr == NULL);
+ m_ThisFrameStartTime = qt3ds::foundation::Time::getCurrentCounterValue();
+ if (m_LastFrameStartTime) {
+ QT3DSU64 durationSinceLastFrame = m_ThisFrameStartTime - m_LastFrameStartTime;
+ m_MillisecondsSinceLastFrame =
+ qt3ds::foundation::Time::sCounterFreq.toTensOfNanos(durationSinceLastFrame)
+ * (1.0 / 100000.0);
+ } else {
+ m_MillisecondsSinceLastFrame = 0;
+ }
+
+ if (m_ProtocolSocket)
+ m_ProtocolSocket->MessagePump();
+ ++m_FrameCount;
+
+ // Update any state systems
+ if (!m_DisableState)
+ m_CoreFactory->GetVisualStateContext().Initialize();
+
+ // First off, update any application level behaviors.
+ IScriptBridge &theScriptEngine = m_CoreFactory->GetScriptEngine();
+ for (QT3DSU32 idx = 0, end = m_Behaviors.size(); idx < end; ++idx) {
+ eastl::pair<SBehaviorAsset, bool> &entry(m_Behaviors[idx]);
+ if (!entry.second) {
+ entry.second = true;
+ theScriptEngine.ExecuteApplicationScriptFunction(entry.first.m_Handle,
+ "onInitialize");
+ }
+ }
+
+ // TODO: Initialize presentations
+
+ // Start any state systems
+ if (!m_DisableState)
+ m_CoreFactory->GetVisualStateContext().Start();
+
+ for (QT3DSU32 idx = 0, end = m_Behaviors.size(); idx < end; ++idx) {
+ eastl::pair<SBehaviorAsset, bool> &entry(m_Behaviors[idx]);
+ theScriptEngine.ExecuteApplicationScriptFunction(entry.first.m_Handle, "onUpdate");
+ }
+
+ if (!m_DisableState)
+ m_CoreFactory->GetVisualStateContext().Update();
+
+ UpdatePresentations();
+
+ if (m_ProtocolSocket) {
+ m_ProtocolSocket->MessagePump();
+ if (m_ProtocolSocket->Connected() == false)
+ exit(0);
+ }
+
+ UpdateScenes();
+
+ Render();
+
+ GetSceneGraphDebugger();
+
+ if (m_SceneGraphDebugger->IsConnected()) {
+ NVDataRef<CPresentation *> thePresentations(GetPresentations());
+ size_t thePresentationCount = thePresentations.size();
+ for (QT3DSU32 thePresentationIndex = 0; thePresentationIndex < thePresentationCount;
+ thePresentationIndex++) {
+ CPresentation *thePresentation = thePresentations[thePresentationIndex];
+ Q3DStudio::TElementList &theDirtyList =
+ thePresentation->GetFrameData().GetDirtyList();
+ for (QT3DSU32 idx = 0, end = theDirtyList.GetCount(); idx < end; ++idx) {
+ Q3DStudio::TElement &theElement = *theDirtyList[idx];
+ // Set active
+ m_ChangeBuffer.push_back(SSGPropertyChange());
+ QT3DSI32 active = theElement.GetActive() ? 1 : 0;
+ m_ChangeBuffer.back().m_Hash = CHash::HashAttribute("active");
+ m_ChangeBuffer.back().m_Value = uic::state::debugger::SSGValue(active);
+ for (long attIdx = 0, attEnd = theElement.GetAttributeCount(); attIdx < attEnd;
+ ++attIdx) {
+ Option<uic::runtime::element::TPropertyDescAndValuePtr> theValue =
+ theElement.GetPropertyByIndex(attIdx);
+ m_ChangeBuffer.push_back(SSGPropertyChange());
+ SSGPropertyChange &theChange(m_ChangeBuffer.back());
+ theChange.m_Hash = theValue->first.GetNameHash();
+ Q3DStudio::EAttributeType theAttType = theValue->first.m_Type;
+ switch (theAttType) {
+ case ATTRIBUTETYPE_HASH:
+ case ATTRIBUTETYPE_BOOL:
+ case ATTRIBUTETYPE_INT32:
+ theChange.m_Value =
+ uic::state::debugger::SSGValue(
+ (QT3DSI32)theValue->second->m_INT32);
+ break;
+ case ATTRIBUTETYPE_FLOAT:
+ theChange.m_Value =
+ uic::state::debugger::SSGValue(theValue->second->m_FLOAT);
+ break;
+ case ATTRIBUTETYPE_STRING: {
+ CRegisteredString data = m_CoreFactory->GetStringTable().HandleToStr(
+ theValue->second->m_StringHandle);
+ theChange.m_Value = uic::state::debugger::SSGValue(data);
+ } break;
+ case ATTRIBUTETYPE_POINTER: {
+ void *ptrVal = theValue->second->m_VoidPointer;
+ QT3DSU64 coercedVal = (QT3DSU64)ptrVal;
+ theChange.m_Value = uic::state::debugger::SSGValue(coercedVal);
+ } break;
+ case ATTRIBUTETYPE_ELEMENTREF: {
+ void *ptrVal = GetElementByHandle(theValue->second->m_ElementHandle);
+ QT3DSU64 coercedVal = (QT3DSU64)ptrVal;
+ theChange.m_Value = uic::state::debugger::SSGValue(coercedVal);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ // If this is a component element, we have a few more properties we need to
+ // grab.
+ if (theElement.IsComponent()) {
+ TComponent &theComponent = static_cast<TComponent &>(theElement);
+ QT3DSI32 slide = theComponent.GetCurrentSlide();
+ QT3DSI32 isPaused = theComponent.GetPaused() ? 1 : 0;
+ QT3DSI32 time
+ =(QT3DSI32)thePresentation->GetActivityZone()->GetItemComponentTime(
+ theComponent);
+ m_ChangeBuffer.push_back(
+ SSGPropertyChange(CHash::HashAttribute("slide"), slide));
+ m_ChangeBuffer.push_back(
+ SSGPropertyChange(CHash::HashAttribute("paused"), isPaused));
+ m_ChangeBuffer.push_back(
+ SSGPropertyChange(CHash::HashAttribute("time"), time));
+ }
+ if (m_ChangeBuffer.size()) {
+ m_SceneGraphDebugger->OnPropertyChanged(&theElement, m_ChangeBuffer);
+ m_ChangeBuffer.clear();
+ }
+ }
+ }
+ m_SceneGraphDebugger->EndFrame();
+ }
+
+ m_InputEnginePtr->ClearInputFrame();
+ ClearPresentationDirtyLists();
+
+ if (m_ProtocolSocket)
+ m_ProtocolSocket->MessagePump();
+
+ if (!m_CoreFactory->GetEventSystem().GetAndClearEventFetchedFlag())
+ m_CoreFactory->GetEventSystem().PurgeEvents(); // GetNextEvents of event system has not
+ // been called in this round, so clear
+ // events to avoid events to be piled up
+
+ QT3DSU64 updateEndTime = qt3ds::foundation::Time::getCurrentCounterValue();
+ QT3DSU64 updateDuration = updateEndTime - m_ThisFrameStartTime;
+ double millis
+ = qt3ds::foundation::Time::sCounterFreq.toTensOfNanos(updateDuration)
+ * (1.0 / 100000);
+ if (floor(m_FrameTimer.GetElapsedSeconds()) > 0.0f) {
+ QPair<QT3DSF32, int> fps = m_FrameTimer.GetFPS(m_FrameCount);
+ m_RuntimeFactory->GetUICRenderContext().SetFPS(fps);
+ if (m_ProfileLogging || !m_HideFPS) {
+ qCInfo(PERF_INFO, "Render Statistics: %3.2ffps, frame count %d",
+ fps.first, fps.second);
+ }
+ }
+
+ (void)millis;
+
+ /*if ( millis > 30.0 )
+ {
+ m_CoreFactory->GetFoundation().error( NVErrorCode::eDEBUG_INFO, __FILE__, __LINE__,
+ "UIC Long Frame: %3.2fms", millis );
+ //Useful for figuring out where the frame time comes from.
+ m_CoreFactory->GetPerfTimer().OutputTimerData();
+
+ }
+ else*/
+ m_CoreFactory->GetPerfTimer().ResetTimerData();
+
+ fflush(stdout);
+ m_LastFrameStartTime = m_ThisFrameStartTime;
+ if (m_LastRenderWasDirty)
+ ResetDirtyCounter();
+ else
+ m_DirtyCountdown = NVMax(0, m_DirtyCountdown - 1);
+ }
+
+ // hook this up to -layer-caching.
+ // otherwise it might be hard to measure performance
+ bool IsApplicationDirty() override
+ {
+ return (m_DirtyCountdown > 0);
+ }
+
+ double GetMillisecondsSinceLastFrame() override { return m_MillisecondsSinceLastFrame; }
+
+ void MarkApplicationDirty() override { ResetDirtyCounter(); }
+
+ Q3DStudio::IAudioPlayer &GetAudioPlayer() override { return m_AudioPlayer; }
+ ////////////////////////////////////////////////////////////////////////////////
+ // Generalized save/load
+ ////////////////////////////////////////////////////////////////////////////////
+
+ bool LoadUIP(SPresentationAsset &inAsset,
+ NVConstDataRef<SElementAttributeReference> inExternalReferences)
+ {
+ GetMetaData();
+ eastl::string theFile;
+ CFileTools::CombineBaseAndRelative(GetProjectDirectory().c_str(), inAsset.m_Src.c_str(),
+ theFile);
+ // Check if the file event exists
+ eastl::string fullPath;
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream
+ = m_CoreFactory->GetUICRenderContextCore().GetInputStreamFactory().GetStreamForFile(
+ theFile.c_str());
+ if (theStream) {
+ theStream = NULL;
+ CPresentation *thePresentation
+ = Q3DStudio_new(CPresentation) CPresentation(inAsset.m_Id.c_str(), this);
+ inAsset.m_Presentation = thePresentation;
+ thePresentation->SetFilePath(theFile.c_str());
+ NVScopedReleasable<IUIPParser> theUIPParser(IUIPParser::Create(
+ theFile.c_str(), *m_MetaData,
+ m_CoreFactory->GetInputStreamFactory(),
+ m_CoreFactory->GetStringTable()));
+ Q3DStudio::IScene *newScene = NULL;
+ ISceneGraphRuntimeDebugger &theDebugger = GetSceneGraphDebugger();
+ m_PresentationBuffer.clear();
+ // Map presentation id has to be called before load so that when we send the element
+ // id updates the system can also send the presentationid->id mapping.
+ theDebugger.MapPresentationId(thePresentation, inAsset.m_Id.c_str());
+ if (theUIPParser->Load(*thePresentation, inExternalReferences,
+ GetSceneGraphDebugger())) {
+ // Load the scene graph portion of the scene.
+ newScene = m_RuntimeFactory->GetSceneManager().LoadScene(
+ thePresentation, theUIPParser.mPtr, m_CoreFactory->GetScriptEngine());
+ }
+
+ if (newScene == NULL) {
+ Q3DStudio_delete(thePresentation, CPresentation);
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Unable to load presentation " << theFile.c_str();
+ inAsset.m_Presentation = NULL;
+ return false;
+ } else {
+ if (inAsset.m_Id.IsValid() && m_InitialPresentationId.empty())
+ m_InitialPresentationId.assign(inAsset.m_Id);
+
+ if (inAsset.m_Id.IsValid())
+ newScene->RegisterOffscreenRenderer(inAsset.m_Id);
+ return true;
+ }
+ }
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Unable to load presentation " << theFile.c_str();
+ return false;
+ }
+
+ bool LoadUIA(IDOMReader &inReader, NVFoundationBase &fnd)
+ {
+ NVConstDataRef<uic::state::SElementReference> theStateReferences;
+ {
+ IDOMReader::Scope __preparseScope(inReader);
+ theStateReferences = m_CoreFactory->GetVisualStateContext().PreParseDocument(inReader);
+ }
+ {
+ QT3DSVec2 watermarkCoords(0, 0);
+ if (inReader.Att("watermark-location", watermarkCoords)) {
+ m_WatermarkCoordinates = QT3DSVec2(Clamp(watermarkCoords.x),
+ Clamp(watermarkCoords.y));
+ }
+ m_UIAFileSettings.Parse(inReader);
+ }
+ {
+ IDOMReader::Scope __assetsScope(inReader);
+ if (!inReader.MoveToFirstChild("assets")) {
+ qCCritical(INVALID_OPERATION,
+ "UIA input xml doesn't contain <assets> tag; load failed");
+ return false;
+ }
+
+ eastl::string pathString;
+
+ const char8_t *initialItem = "";
+ inReader.UnregisteredAtt("initial", initialItem);
+ m_InitialPresentationId.clear();
+ if (!isTrivial(initialItem)) {
+ if (initialItem[0] == '#')
+ ++initialItem;
+
+ m_InitialPresentationId.assign(initialItem);
+ }
+ eastl::vector<SElementAttributeReference> theUIPReferences;
+ eastl::string tempString;
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __assetScope(inReader);
+ const char8_t *itemId("");
+ inReader.UnregisteredAtt("id", itemId);
+ const char8_t *src = "";
+ inReader.UnregisteredAtt("src", src);
+ pathString.clear();
+ if (!isTrivial(src))
+ CFileTools::CombineBaseAndRelative(m_ProjectDir.c_str(), src, pathString);
+
+ const char8_t *assetName = inReader.GetElementName();
+ if (AreEqual(assetName, "presentation")) {
+ SPresentationAsset theAsset(RegisterStr(itemId), RegisterStr(src));
+ bool activeFlag;
+ if (inReader.Att("active", activeFlag))
+ theAsset.m_Active = activeFlag;
+ RegisterAsset(theAsset);
+ } else if (AreEqual(assetName, "renderplugin")) {
+ const char8_t *pluginArgs = "";
+ inReader.UnregisteredAtt("args", pluginArgs);
+ RegisterAsset(SRenderPluginAsset(RegisterStr(itemId), RegisterStr(src),
+ RegisterStr(pluginArgs)));
+ } else if (AreEqual(assetName, "statemachine")) {
+ const char8_t *dm = "";
+ inReader.UnregisteredAtt("datamodel", dm);
+ m_CoreFactory->GetVisualStateContext().LoadStateMachine(itemId, src,
+ nonNull(dm));
+ RegisterAsset(
+ SSCXMLAsset(RegisterStr(itemId), RegisterStr(src), RegisterStr(dm)));
+
+ } else if (AreEqual(assetName, "behavior")) {
+ SBehaviorAsset theAsset(RegisterStr(itemId), RegisterStr(src), 0);
+ RegisterAsset(theAsset);
+ } else if (AreEqual(assetName, "presentation-qml")) {
+ const char8_t *args = "";
+ inReader.UnregisteredAtt("args", args);
+ RegisterAsset(SQmlPresentationAsset(RegisterStr(itemId), RegisterStr(src),
+ RegisterStr(args)));
+ } else {
+ qCWarning(WARNING, "Unrecognized <assets> child %s", assetName);
+ }
+ }
+ } // end assets scope
+ const char8_t *initialScaleMode = "";
+ inReader.UnregisteredAtt("scalemode", initialScaleMode);
+
+ {
+ IDOMReader::Scope __machineScope(inReader);
+ m_CoreFactory->GetVisualStateContext().LoadVisualStateMapping(inReader);
+ }
+ m_AppLoadContext
+ = IAppLoadContext::CreateXMLLoadContext(*this, theStateReferences,
+ initialScaleMode);
+ return true;
+ }
+
+ struct SAppXMLErrorHandler : public qt3ds::foundation::CXmlErrorHandler
+ {
+ NVFoundationBase &m_Foundation;
+ const char8_t *m_FilePath;
+ SAppXMLErrorHandler(NVFoundationBase &fnd, const char8_t *filePath)
+ : m_Foundation(fnd)
+ , m_FilePath(filePath)
+ {
+ }
+
+ void OnXmlError(TXMLCharPtr errorName, int line, int /*column*/) override
+ {
+ qCWarning(INVALID_OPERATION, m_FilePath, line, "%s", errorName);
+ }
+ };
+
+ void ConnectDebugger()
+ {
+ NVFoundationBase &fnd(m_CoreFactory->GetFoundation());
+ Q3DStudio::IScriptBridge &theBridge = m_CoreFactory->GetScriptEngine();
+ if (m_DebugSettings.hasValue()) {
+ m_SocketSystem = SocketSystem::createSocketSystem(fnd);
+ if (m_DebugSettings->m_Listen) {
+ // Wait for connection request from debug server
+ qCInfo(TRACE_INFO, "Listening for debug connection on port %d",
+ m_DebugSettings->m_Port);
+ NVScopedRefCounted<SocketServer> theServer
+ = m_SocketSystem->createServer(m_DebugSettings->m_Port);
+ theServer->setTimeout(1000);
+ m_ServerStream = theServer->nextClient();
+ } else {
+ // Attempt to connect to the debug server
+ qCInfo(TRACE_INFO, "Attempt to connect to debug server %s:%d",
+ m_DebugSettings->m_Server.c_str(), m_DebugSettings->m_Port);
+ m_ServerStream = m_SocketSystem->createStream(m_DebugSettings->m_Server.c_str(),
+ m_DebugSettings->m_Port, 1000);
+ }
+ if (m_ServerStream) {
+ m_ServerStream->setTimeout(QT3DS_MAX_U32);
+ // This system declares protocols, we don't listen for new ones.
+ m_ProtocolSocket = uic::state::debugger::IMultiProtocolSocket::CreateProtocolSocket(
+ fnd, *m_ServerStream, m_CoreFactory->GetStringTable(), NULL);
+ if (!m_ProtocolSocket->Initialize()) {
+ m_ProtocolSocket = NULL;
+ m_ServerStream = NULL;
+ m_SocketSystem = NULL;
+ qCWarning(WARNING,
+ "Initialization failed after connection to server, debug server %s:%d",
+ m_DebugSettings->m_Server.c_str(), m_DebugSettings->m_Port);
+
+ } else {
+ using namespace uic::state::debugger;
+ theBridge.EnableDebugging(*m_ProtocolSocket);
+ NVScopedRefCounted<IMultiProtocolSocketStream> socketStream
+ = m_ProtocolSocket->CreateProtocol(
+ CProtocolNames::getSCXMLProtocolName(), NULL);
+ GetStateDebugger().OnServerConnected(*socketStream);
+
+ NVScopedRefCounted<IMultiProtocolSocketStream> theSGStream
+ = m_ProtocolSocket->CreateProtocol(
+ ISceneGraphRuntimeDebugger::GetProtocolName(), NULL);
+ GetSceneGraphDebugger().OnConnection(*theSGStream);
+ theSGStream->SetListener(&GetSceneGraphDebugger());
+ }
+ } else {
+ qCWarning(WARNING, "Failed to connect to debug server %s:%d",
+ m_DebugSettings->m_Server.c_str(), m_DebugSettings->m_Port);
+ }
+ }
+ }
+
+ bool BeginLoad(const char8_t *inFilePath) override
+ {
+ SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(), "Application: Begin Load");
+ eastl::string directory;
+ eastl::string filename;
+ eastl::string extension;
+ CFileTools::Split(inFilePath, directory, filename, extension);
+ eastl::string projectDirectory(directory);
+ size_t binaryPos = projectDirectory.rfind("binary");
+ if (binaryPos != eastl::string::npos && binaryPos >= projectDirectory.size() - 7)
+ CFileTools::GetDirectory(projectDirectory);
+
+ m_ProjectDir.assign(projectDirectory.c_str());
+ m_CoreFactory->AddSearchPath(projectDirectory.c_str());
+
+ // add additional search path
+ QString projectDir = CFileTools::NormalizePathForQtUsage(projectDirectory.c_str());
+ if (!projectDir.startsWith(QStringLiteral(":"))) {
+ eastl::string relativeProjectDir;
+ CFileTools::CombineBaseAndRelative(m_ApplicationDir.c_str(), projectDirectory.c_str(),
+ relativeProjectDir);
+ m_CoreFactory->AddSearchPath(relativeProjectDir.c_str());
+ }
+
+ NVFoundationBase &fnd(m_CoreFactory->GetFoundation());
+
+ if (m_CoreFactory->GetUICRenderContextCore().GetTextRendererCore()) {
+ m_CoreFactory->GetUICRenderContextCore().GetTextRendererCore()->AddProjectFontDirectory(
+ projectDirectory.c_str());
+ m_CoreFactory->GetUICRenderContextCore().GetTextRendererCore()->BeginPreloadFonts(
+ m_CoreFactory->GetUICRenderContextCore().GetThreadPool(),
+ m_CoreFactory->GetUICRenderContextCore().GetPerfTimer());
+ }
+ m_Filename = filename;
+ bool retval = false;
+ if (extension.comparei("uip") == 0) {
+#if !defined(_LINUXPLATFORM) && !defined(_INTEGRITYPLATFORM)
+ ConnectDebugger();
+#endif
+ m_InitialPresentationId.assign(filename.c_str());
+ eastl::string relativePath = "./";
+ relativePath.append(filename);
+ relativePath.append(".");
+ relativePath.append("uip");
+ RegisterAsset(SPresentationAsset(RegisterStr(filename.c_str()),
+ RegisterStr(relativePath.c_str())));
+ m_AppLoadContext = IAppLoadContext::CreateXMLLoadContext(
+ *this, NVDataRef<uic::state::SElementReference>(), "");
+
+ retval = true;
+ } else if (extension.comparei("uia") == 0) {
+#if !defined(_LINUXPLATFORM) && !defined(_INTEGRITYPLATFORM)
+ ConnectDebugger();
+#endif
+ CFileSeekableIOStream inputStream(inFilePath, FileReadFlags());
+ if (inputStream.IsOpen()) {
+ NVScopedRefCounted<IStringTable> strTable(
+ IStringTable::CreateStringTable(fnd.getAllocator()));
+ NVScopedRefCounted<IDOMFactory> domFactory(
+ IDOMFactory::CreateDOMFactory(fnd.getAllocator(), strTable));
+ SAppXMLErrorHandler errorHandler(fnd, inFilePath);
+ eastl::pair<SNamespacePairNode *, SDOMElement *> readResult =
+ CDOMSerializer::Read(*domFactory, inputStream, &errorHandler);
+ if (!readResult.second) {
+ qCCritical(INVALID_PARAMETER, "%s doesn't appear to be valid xml",
+ inFilePath);
+ } else {
+ NVScopedRefCounted<IDOMReader> domReader = IDOMReader::CreateDOMReader(
+ fnd.getAllocator(), *readResult.second, strTable, domFactory);
+ if (m_visitor)
+ m_visitor->visit(inFilePath);
+ retval = LoadUIA(*domReader, fnd);
+ }
+ } else {
+ qCCritical(INVALID_PARAMETER, "Unable to open input file %s", inFilePath);
+ }
+ } else if (extension.comparei("uiab") == 0) {
+ retval = LoadBinary(inFilePath);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+
+ void EndLoad() override
+ {
+ if (m_AppLoadContext)
+ m_AppLoadContext->EndLoad();
+ }
+
+ void RunAllRunnables()
+ {
+ {
+ Mutex::ScopedLock __locker(m_RunnableMutex);
+ m_MainThreadRunnables = m_ThreadRunnables;
+ m_ThreadRunnables.clear();
+ }
+ for (QT3DSU32 idx = 0, end = m_MainThreadRunnables.size(); idx < end; ++idx)
+ m_MainThreadRunnables[idx]->Run();
+ m_MainThreadRunnables.clear();
+ }
+
+ bool HasCompletedLoading() override
+ {
+ RunAllRunnables();
+ if (m_AppLoadContext)
+ return m_AppLoadContext->HasCompletedLoading();
+
+ return true;
+ }
+
+ // will force loading to end if endLoad hasn't been called yet. Will fire off loading
+ // of resources that need to be uploaded to opengl. Maintains reference to runtime factory
+ IApplication &CreateApplication(Q3DStudio::CInputEngine &inInputEngine,
+ Q3DStudio::IAudioPlayer *inAudioPlayer,
+ Q3DStudio::IRuntimeFactory &inFactory) override
+ {
+ {
+ SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(),
+ "Application: Initialize Graphics");
+
+ {
+ SStackPerfTimer __timer(m_CoreFactory->GetPerfTimer(), "Application: EndLoad");
+ EndLoad();
+ }
+ {
+ SStackPerfTimer __timer(m_CoreFactory->GetPerfTimer(),
+ "Application: EndPreloadScripts");
+ m_CoreFactory->GetScriptEngine().EndPreloadScripts();
+ }
+ m_InputEnginePtr = &inInputEngine;
+ m_RuntimeFactory = inFactory;
+
+ {
+ SStackPerfTimer __timer(m_CoreFactory->GetPerfTimer(),
+ "Application: Load Context Graphics Initialized");
+ if (m_AppLoadContext)
+ m_AppLoadContext->OnGraphicsInitialized(inFactory);
+ // Guarantees the end of the multithreaded access to the various components
+ m_AppLoadContext = NULL;
+ }
+
+ {
+ SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(),
+ "Application: End Font Preload");
+ if (m_CoreFactory->GetUICRenderContextCore().GetTextRendererCore())
+ m_CoreFactory->GetUICRenderContextCore()
+ .GetTextRendererCore()
+ ->EndPreloadFonts();
+ }
+
+ RunAllRunnables();
+ // Moving set application to the end ensures that the application load context is not
+ // accessing
+ // the lua state in another thread while we are calling set application. This
+ // apparently may cause
+ // the call to set application to fail miserably.
+ m_RuntimeFactory->SetApplication(this);
+ m_RuntimeFactory->GetScriptEngine().DisableMultithreadedAccess();
+ m_RuntimeFactory->GetStringTable().DisableMultithreadedAccess();
+
+ for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
+ if (m_OrderedAssets[idx].second->getType() == AssetValueTypes::Presentation) {
+ SPresentationAsset &theAsset(
+ *m_OrderedAssets[idx].second->getDataPtr<SPresentationAsset>());
+ CPresentation *thePresentation = theAsset.m_Presentation;
+ if (thePresentation) {
+ SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(),
+ "Application: SetActivityZone");
+ thePresentation->SetActivityZone(
+ &m_ActivityZoneManager->CreateActivityZone(*thePresentation));
+ thePresentation->SetActive(theAsset.m_Active);
+ }
+ }
+ }
+
+ inInputEngine.SetApplication(this);
+ }
+ SApplicationSettings finalSettings(/*m_CommandLineSettings, */m_UIAFileSettings);
+ if (finalSettings.m_LayerCacheEnabled.hasValue()) {
+ inFactory.GetUICRenderContext().GetRenderer().EnableLayerCaching(
+ *finalSettings.m_LayerCacheEnabled);
+ }
+ if (finalSettings.m_LayerGpuProfilingEnabled.hasValue()) {
+ inFactory.GetUICRenderContext().GetRenderer().EnableLayerGpuProfiling(
+ *finalSettings.m_LayerGpuProfilingEnabled);
+ }
+ if (finalSettings.m_ShaderCachePersistenceEnabled.hasValue()
+ && finalSettings.m_ShaderCachePersistenceEnabled.getValue()) {
+ eastl::string binaryDir;
+ CFileTools::CombineBaseAndRelative(this->GetProjectDirectory(), "binary", binaryDir);
+ CFileTools::CreateDir(binaryDir.c_str());
+ inFactory.GetUICRenderContext().GetShaderCache().SetShaderCachePersistenceEnabled(
+ binaryDir.c_str());
+ }
+
+ m_CoreFactory->GetPerfTimer().OutputTimerData();
+ m_RuntimeFactory->GetUICRenderContext().SetWatermarkLocation(m_WatermarkCoordinates);
+
+ m_AudioPlayer.SetPlayer(inAudioPlayer);
+
+ return *this;
+ }
+
+ // Binary Save/Load
+
+ struct SAssetSaveRemapper
+ {
+ const SStrRemapMap &m_Remapper;
+ SAssetSaveRemapper(const SStrRemapMap &rm)
+ : m_Remapper(rm)
+ {
+ }
+ template <typename TDatatype>
+ SAssetValue operator()(const TDatatype &dt)
+ {
+ TDatatype temp(dt);
+ temp.Remap(*this);
+ return temp;
+ }
+ void Remap(CRegisteredString &str) { str.Remap(m_Remapper); }
+
+ SAssetValue operator()() { return SAssetValue(); }
+ };
+
+ void AddElementToHandleBuffer(TElement &inElement, eastl::vector<THandleElementPair> &inBuffer)
+ {
+ inBuffer.push_back(eastl::make_pair(inElement.m_Handle, &inElement));
+ if (inElement.m_Child)
+ AddElementToHandleBuffer(*inElement.m_Child, inBuffer);
+ if (inElement.m_Sibling)
+ AddElementToHandleBuffer(*inElement.m_Sibling, inBuffer);
+ }
+
+ void SaveBinary() override
+ {
+ eastl::string fname;
+ CFileTools::CombineBaseAndRelative(m_ProjectDir.c_str(), "binary", fname);
+ CFileTools::CreateDir(fname, true);
+ // Save out element data into temp buffer to generate correct element offsets used
+ // throughout the next steps.
+ NVDataRef<CPresentation *> thePresentations = GetPresentations();
+ qt3ds::foundation::CMemorySeekableIOStream theElementData(
+ this->m_CoreFactory->GetFoundation().getAllocator(), "ElementSaveData");
+ {
+ eastl::vector<Q3DStudio::TElement *> thePresentationElements;
+
+ // We save must have exactly one element or null ptr per presentation asset. Else the
+ // loading logic gets complicated.
+ for (QT3DSU32 assetIdx = 0, assetEnd = m_OrderedAssets.size(); assetIdx < assetEnd;
+ ++assetIdx) {
+ if (m_OrderedAssets[assetIdx].second
+ && m_OrderedAssets[assetIdx].second->getType()
+ == AssetValueTypes::Presentation) {
+ SPresentationAsset *theAsset =
+ m_OrderedAssets[assetIdx].second->getDataPtr<SPresentationAsset>();
+ if (theAsset->m_Presentation)
+ thePresentationElements.push_back(theAsset->m_Presentation->GetRoot());
+ else
+ thePresentationElements.push_back(NULL);
+ }
+ }
+
+ m_ElementAllocator->SaveBinaryData(
+ theElementData,
+ NVDataRef<Q3DStudio::TElement *>(thePresentationElements.data(),
+ (QT3DSU32)thePresentationElements.size()));
+ }
+
+ // First we have to save all the presentations out because this step can generate new
+ // strings.
+ {
+ Q3DStudio::IBinarySerializer &thePresentationSerializer(
+ Q3DStudio::IBinarySerializer::Create());
+ for (QT3DSU32 presIdx = 0, presEnd = thePresentations.size(); presIdx < presEnd;
+ ++presIdx) {
+ CPresentation &thePresentation = *thePresentations[presIdx];
+ thePresentationSerializer.BinarySave(&thePresentation);
+ IScene *theScene = thePresentation.GetScene();
+ if (theScene)
+ m_RuntimeFactory->GetSceneManager().BinarySave(*theScene);
+ }
+ }
+ // Now no more strings may be generated else they can't be remapped on load.
+ eastl::string binaryDir(fname);
+ fname.append("/");
+ fname.append(m_Filename);
+ fname.append(".uiab");
+ {
+ CFileSeekableIOStream theStream(fname.c_str(), FileWriteFlags());
+ if (!theStream.IsOpen()) {
+ qCCritical(INVALID_OPERATION, "File %s is not writable", fname.c_str());
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ // Save out the loaded scripts first.
+ eastl::vector<eastl::string> loadedScripts =
+ m_CoreFactory->GetScriptEngine().GetLoadedScripts();
+ IOutStream &theOutStream(theStream);
+ {
+ MemoryBuffer<> theBuffer(ForwardingAllocator(
+ m_CoreFactory->GetFoundation().getAllocator(),
+ "scriptsbuffer"));
+ theBuffer.write((QT3DSU32)loadedScripts.size());
+ for (QT3DSU32 idx = 0, end = loadedScripts.size(); idx < end; ++idx) {
+ QT3DSU32 len = (QT3DSU32)loadedScripts[idx].size();
+ if (len) {
+ ++len;
+ theBuffer.write(len);
+ theBuffer.write(loadedScripts[idx].c_str(), len);
+ } else {
+ theBuffer.write(len);
+ }
+ }
+ theOutStream.Write((QT3DSU32)theBuffer.size());
+ theOutStream.Write(theBuffer.begin(), (QT3DSU32)theBuffer.size());
+ }
+
+ m_RuntimeFactory->GetSceneManager().BinarySaveManagerData(theStream, binaryDir.c_str());
+
+ QT3DSU32 primaryIdSize = (QT3DSU32)m_InitialPresentationId.size();
+ if (primaryIdSize)
+ ++primaryIdSize; // include null
+ theOutStream.Write(primaryIdSize);
+ if (primaryIdSize)
+ theOutStream.Write(m_InitialPresentationId.c_str(), primaryIdSize);
+ QT3DSU32 theScaleMode
+ = static_cast<QT3DSU32>(m_RuntimeFactory->GetUICRenderContext().GetScaleMode());
+ theOutStream.Write(theScaleMode);
+ theOutStream.Write(m_WatermarkCoordinates);
+ m_UIAFileSettings.Save(theOutStream);
+
+ MemoryBuffer<> theSaveBuffer(
+ ForwardingAllocator(m_CoreFactory->GetFoundation().getAllocator(),
+ "SaveBuffer"));
+ // Now save our assets.
+ QT3DSU32 assetCount = (QT3DSU32)m_OrderedAssets.size();
+ theSaveBuffer.write(assetCount);
+ const SStrRemapMap &remapMap = m_CoreFactory->GetStringTable().GetRemapMap();
+ // Save the assets in the order they were loaded.
+ for (QT3DSU32 assetIdx = 0, assetEnd = m_OrderedAssets.size(); assetIdx < assetEnd;
+ ++assetIdx) {
+ CRegisteredString temp(m_OrderedAssets[assetIdx].first);
+ temp.Remap(remapMap);
+ theSaveBuffer.write(temp);
+ SAssetValue theValue = m_OrderedAssets[assetIdx].second->visit<SAssetValue>(
+ SAssetSaveRemapper(remapMap));
+ theSaveBuffer.write(theValue);
+ }
+ theOutStream.Write((QT3DSU32)theSaveBuffer.size());
+ theOutStream.Write(theSaveBuffer.begin(), (QT3DSU32)theSaveBuffer.size());
+ m_CoreFactory->GetVisualStateContext().BinarySave(theStream);
+ QT3DSU32 theElemDataSize = (QT3DSU32)theElementData.GetLength();
+ theOutStream.Write(theElemDataSize);
+ theOutStream.Write(theElementData.begin(), theElemDataSize);
+ GetSceneGraphDebugger().BinarySave(theStream);
+ }
+ }
+
+ struct SAssetLoadRemapper
+ {
+ NVDataRef<QT3DSU8> m_Remapper;
+ SAssetLoadRemapper(NVDataRef<QT3DSU8> rm)
+ : m_Remapper(rm)
+ {
+ }
+ template <typename TDatatype>
+ void operator()(TDatatype &dt)
+ {
+ dt.Remap(*this);
+ }
+ void Remap(CRegisteredString &str) { str.Remap(m_Remapper); }
+ void operator()() {}
+ };
+
+ bool LoadBinary(const char *inFilename)
+ {
+ CFileSeekableIOStream theStream(inFilename, FileReadFlags());
+ if (!theStream.IsOpen()) {
+ qCCritical(INVALID_OPERATION, "File %s is not readable", inFilename);
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ {
+ SStackPerfTimer __loadTimer(m_CoreFactory->GetPerfTimer(), "Load UIA");
+
+ eastl::string binaryDir(inFilename);
+ CFileTools::GetDirectory(binaryDir);
+
+ IInStream &theInStream(theStream);
+ QT3DSU32 scriptsDataLen = 0;
+ theInStream.Read(scriptsDataLen);
+ eastl::vector<char8_t> scriptsData;
+ scriptsData.resize(scriptsDataLen);
+ theInStream.Read(scriptsData.data(), scriptsDataLen);
+ eastl::vector<const char *> scripts;
+ {
+ qt3ds::foundation::SDataReader theReader((QT3DSU8 *)scriptsData.data(),
+ (QT3DSU8 *)scriptsData.data()
+ + scriptsDataLen);
+ QT3DSU32 numScripts = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numScripts; idx < end; ++idx) {
+ QT3DSU32 len = theReader.LoadRef<QT3DSU32>();
+ scripts.push_back((const char *)theReader.m_CurrentPtr);
+ theReader.m_CurrentPtr += len;
+ }
+ }
+ // We heavily thread the binary loading process so until we have killed the threading
+ // portion of the loader, we have to
+ // ensure the script engine is multithread-capable.
+ m_CoreFactory->GetScriptEngine().EnableMultithreadedAccess();
+ m_CoreFactory->GetStringTable().EnableMultithreadedAccess();
+ m_CoreFactory->GetScriptEngine().BeginPreloadScripts(
+ scripts, m_CoreFactory->GetUICRenderContextCore().GetThreadPool(),
+ m_ProjectDir.c_str());
+ NVDataRef<QT3DSU8> stringTableData
+ = m_CoreFactory->GetSceneLoader().BinaryLoadManagerData(theInStream,
+ binaryDir.c_str());
+ QT3DSU32 primaryIdSize = 0;
+ theInStream.Read(primaryIdSize);
+ if (primaryIdSize) {
+ m_InitialPresentationId.resize(primaryIdSize);
+ theInStream.Read(&m_InitialPresentationId.at(0), primaryIdSize);
+ m_InitialPresentationId.resize(primaryIdSize - 1);
+ }
+ QT3DSU32 theScaleMode = 0;
+ theInStream.Read(&theScaleMode, 1);
+ uic::render::ScaleModes::Enum theProperScaleMode
+ = static_cast<uic::render::ScaleModes::Enum>(theScaleMode);
+ theInStream.Read(m_WatermarkCoordinates);
+ m_UIAFileSettings.Load(theInStream);
+
+ // Connect the debugger after we load the string table information because connecting
+ // generates new string table strings and the string table itself needs to be in an
+ // empty
+ // state on load else the old strings are invalid.
+#if !defined(_LINUXPLATFORM) && !defined(_INTEGRITYPLATFORM)
+ ConnectDebugger();
+#endif
+ m_AssetMap.clear();
+ m_OrderedAssets.clear();
+ QT3DS_ASSERT(m_Behaviors.empty());
+ QT3DSU32 assetSectionSize = 0;
+ theInStream.Read(assetSectionSize);
+ m_LoadBuffer.resize(assetSectionSize);
+
+ theInStream.Read(m_LoadBuffer.data(), assetSectionSize);
+
+ {
+ qt3ds::foundation::SDataReader theReader(
+ (QT3DSU8 *)m_LoadBuffer.data(), (QT3DSU8 *)m_LoadBuffer.data()
+ + assetSectionSize);
+ QT3DSU32 assetCount = theReader.LoadRef<QT3DSU32>();
+
+ for (QT3DSU32 assetIdx = 0, assetEnd = assetCount; assetIdx < assetEnd;
+ ++assetIdx) {
+ CRegisteredString id = theReader.LoadRef<CRegisteredString>();
+ id.Remap(stringTableData);
+ SAssetValue theAsset = theReader.LoadRef<SAssetValue>();
+ theAsset.visit<void>(SAssetLoadRemapper(stringTableData));
+ NVScopedRefCounted<SRefCountedAssetValue> theRefAsset(
+ QT3DS_NEW(m_CoreFactory->GetFoundation().getAllocator(),
+ SRefCountedAssetValue)(m_CoreFactory->GetFoundation(),
+ theAsset));
+ TIdAssetMap::iterator iter =
+ m_AssetMap.insert(eastl::make_pair(id, theRefAsset)).first;
+ m_OrderedAssets.push_back(eastl::make_pair(iter->first, theRefAsset));
+ }
+ }
+ m_CoreFactory->GetVisualStateContext().BinaryLoad(theInStream, stringTableData);
+ QT3DSU32 theElementSectionSize = 0;
+ theInStream.Read(theElementSectionSize);
+ m_LoadBuffer.resize(theElementSectionSize);
+ theInStream.Read(m_LoadBuffer.data(), theElementSectionSize);
+ // Note that the elements are now all coming from the load buffer; that memory cannot be
+ // reused or released.
+ m_ElementLoadResult = m_ElementAllocator->LoadBinaryData(
+ toDataRef((QT3DSU8 *)m_LoadBuffer.data(), theElementSectionSize),
+ stringTableData);
+ GetSceneGraphDebugger().BinaryLoad(theInStream, stringTableData);
+ m_AppLoadContext = IAppLoadContext::CreateBinaryLoadContext(*this, theProperScaleMode,
+ stringTableData);
+ }
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Getters/Setters
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ CRegisteredString RegisterStr(const char8_t *inStr)
+ {
+ return m_CoreFactory->GetStringTable().RegisterStr(inStr);
+ }
+
+ // The directory that contains the executable and the root resource path
+ CRegisteredString GetApplicationDirectory() const override
+ {
+ return const_cast<SApp &>(*this).m_CoreFactory->GetStringTable().RegisterStr(
+ m_ApplicationDir.c_str());
+ }
+ // Directory that contained the XIF file.
+ CRegisteredString GetProjectDirectory() const override
+ {
+ QT3DS_ASSERT(m_ProjectDir.size());
+ return const_cast<SApp &>(*this).m_CoreFactory->GetStringTable().RegisterStr(
+ m_ProjectDir.c_str());
+ }
+
+ CRegisteredString GetDllDir() const override
+ {
+ if (m_DLLDirectory.size()) {
+ return const_cast<SApp &>(*this).m_CoreFactory->GetStringTable().RegisterStr(
+ m_DLLDirectory.c_str());
+ }
+ return CRegisteredString();
+ }
+
+ void SetDllDir(const char *inDllDir) override
+ {
+ m_DLLDirectory.assign(nonNull(inDllDir));
+ m_CoreFactory->SetDllDir(inDllDir);
+ }
+
+ Q3DStudio::IRuntimeFactory &GetRuntimeFactory() const override { return *m_RuntimeFactory.mPtr; }
+ Q3DStudio::IRuntimeFactoryCore &GetRuntimeFactoryCore() override { return *m_CoreFactory; }
+
+ Q3DStudio::CPresentation *GetPrimaryPresentation() override
+ {
+ return GetPresentationById(m_InitialPresentationId.c_str());
+ }
+
+ Q3DStudio::CPresentation *GetPresentationById(const char8_t *inId) override
+ {
+ if (!isTrivial(inId)) {
+ TIdAssetMap::iterator iter
+ = m_AssetMap.find(m_CoreFactory->GetStringTable().RegisterStr(inId));
+ if (iter != m_AssetMap.end()
+ && iter->second->getType() == AssetValueTypes::Presentation) {
+ return iter->second->getData<SPresentationAsset>().m_Presentation;
+ }
+ }
+ return NULL;
+ }
+
+ template <typename TAssetType>
+ void RegisterAsset(const TAssetType &inAsset)
+ {
+ NVScopedRefCounted<SRefCountedAssetValue> theValue(
+ QT3DS_NEW(m_CoreFactory->GetFoundation().getAllocator(),
+ SRefCountedAssetValue(m_CoreFactory->GetFoundation(), inAsset)));
+ if (inAsset.m_Id.IsValid())
+ m_AssetMap.insert(eastl::make_pair(inAsset.m_Id, theValue));
+
+ m_OrderedAssets.push_back(eastl::make_pair(inAsset.m_Id, theValue));
+
+ if (m_visitor) {
+ m_visitor->visit(inAsset.Type(), inAsset.m_Id.c_str(), inAsset.m_Src.c_str(),
+ inAsset.m_Args.c_str());
+ }
+ }
+
+ THashValue HashString(const char *inStr) override
+ {
+ if (inStr == NULL)
+ inStr = "";
+ THashValue retval = CHash::HashString(inStr);
+ eastl::pair<THashStrMap::iterator, bool> insertResult
+ = m_HashStrMap.insert(eastl::make_pair(retval, CRegisteredString()));
+ if (insertResult.second)
+ insertResult.first->second = m_CoreFactory->GetStringTable().RegisterStr(inStr);
+ return retval;
+ }
+
+ const char *ReverseHash(THashValue theValue) override
+ {
+ THashStrMap::iterator find = m_HashStrMap.find(theValue);
+ if (find != m_HashStrMap.end())
+ return find->second.c_str();
+ return "";
+ }
+
+ void SetFrameCount(Q3DStudio::INT32 inFrameCount) override { m_FrameCount = inFrameCount; }
+
+ Q3DStudio::INT32 GetFrameCount() override { return m_FrameCount; }
+
+ void SetTimeMilliSecs(Q3DStudio::INT64 inMilliSecs) override { m_ManualTime = inMilliSecs; }
+
+ Q3DStudio::INT64 GetTimeMilliSecs() override
+ {
+ return m_ManualTime == 0 ? m_Timer.GetTimeMilliSecs() : m_ManualTime;
+ }
+
+ void ResetTime() override
+ {
+ m_Timer.Reset();
+ m_ManualTime = 0;
+ }
+
+ void HideFPS(bool flag) override { m_HideFPS = flag; }
+
+ Q3DStudio::CInputEngine &GetInputEngine() override
+ {
+ QT3DS_ASSERT(m_InputEnginePtr);
+ return *m_InputEnginePtr;
+ }
+
+ Q3DStudio::IRuntimeMetaData &GetMetaData() override
+ {
+ if (!m_MetaData) {
+ m_MetaData = &IRuntimeMetaData::Create(m_CoreFactory->GetInputStreamFactory());
+ if (!m_MetaData) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "IRuntimeMetaData::Create: Failed to create meta data";
+ }
+ }
+ return *m_MetaData;
+ }
+
+ uic::state::debugger::IDebugger &GetStateDebugger() override
+ {
+ if (!m_StateDebugger)
+ m_StateDebugger = uic::state::debugger::IDebugger::CreateDebugger();
+ return *m_StateDebugger;
+ }
+
+ uic::state::debugger::ISceneGraphRuntimeDebugger &GetSceneGraphDebugger() override
+ {
+ if (!m_SceneGraphDebugger)
+ m_SceneGraphDebugger = uic::state::debugger::ISceneGraphRuntimeDebugger::Create(
+ m_CoreFactory->GetFoundation(), m_CoreFactory->GetStringTable());
+ return *m_SceneGraphDebugger;
+ }
+
+ IActivityZoneManager &GetActivityZoneManager() override { return *m_ActivityZoneManager; }
+
+ IElementAllocator &GetElementAllocator() override { return *m_ElementAllocator; }
+
+ Q3DStudio::UINT32 GetHandleForElement(Q3DStudio::TElement *inElement) override
+ {
+ return inElement->GetHandle();
+ }
+
+ Q3DStudio::TElement *GetElementByHandle(Q3DStudio::UINT32 inHandle) override
+ {
+ return GetElementAllocator().FindElementByHandle(inHandle);
+ }
+};
+
+struct SXMLLoader : public IAppLoadContext
+{
+ SApp &m_App;
+ eastl::string m_ScaleMode;
+ eastl::vector<uic::state::SElementReference> m_References;
+ QT3DSI32 mRefCount;
+
+ SXMLLoader(SApp &inApp, const char8_t *sc, NVConstDataRef<uic::state::SElementReference> refs)
+ : m_App(inApp)
+ , m_ScaleMode(nonNull(sc))
+ , mRefCount(0)
+ {
+ m_References.assign(refs.begin(), refs.end());
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_App.m_CoreFactory->GetFoundation().getAllocator())
+
+ void EndLoad() override {}
+
+ bool HasCompletedLoading() override { return true; }
+
+ void OnGraphicsInitialized(IRuntimeFactory &inFactory) override
+ {
+ eastl::vector<SElementAttributeReference> theUIPReferences;
+ eastl::string tempString;
+ for (QT3DSU32 idx = 0, end = m_App.m_OrderedAssets.size(); idx < end; ++idx) {
+ SAssetValue &theAsset = *m_App.m_OrderedAssets[idx].second;
+ eastl::string thePathStr;
+
+ CFileTools::CombineBaseAndRelative(m_App.GetProjectDirectory().c_str(),
+ theAsset.GetSource(), thePathStr);
+
+ switch (theAsset.getType()) {
+ case AssetValueTypes::Presentation: {
+ SPresentationAsset &thePresentationAsset
+ = *theAsset.getDataPtr<SPresentationAsset>();
+ theUIPReferences.clear();
+ for (QT3DSU32 refIdx = 0, refEnd = m_References.size(); refIdx < refEnd; ++refIdx) {
+ tempString.assign(m_References[refIdx].m_ElementPath.c_str());
+ eastl::string::size_type colonPos = tempString.find_first_of(':');
+ if (colonPos != eastl::string::npos) {
+ tempString = tempString.substr(0, colonPos);
+ if (tempString.compare(thePresentationAsset.m_Id.c_str()) == 0) {
+ SElementAttributeReference newReference(
+ m_References[refIdx].m_ElementPath.c_str() + colonPos + 1,
+ m_References[refIdx].m_Attribute.c_str());
+ theUIPReferences.push_back(newReference);
+ }
+ }
+ }
+
+ if (!m_App.LoadUIP(thePresentationAsset,
+ toConstDataRef(theUIPReferences.data(),
+ (QT3DSU32)theUIPReferences.size()))) {
+ qCCritical(INVALID_OPERATION, "Unable to load presentation %s",
+ thePathStr.c_str());
+ }
+ } break;
+ case AssetValueTypes::Behavior: {
+ SBehaviorAsset &theBehaviorAsset = *theAsset.getDataPtr<SBehaviorAsset>();
+ Q3DStudio::INT32 scriptId
+ = m_App.m_CoreFactory->GetScriptEngine().InitializeApplicationBehavior(
+ theBehaviorAsset.m_Src);
+ if (scriptId == 0) {
+ qCCritical(INVALID_OPERATION, "Unable to load application behavior %s",
+ theBehaviorAsset.m_Src.c_str());
+ } else {
+ theBehaviorAsset.m_Handle = scriptId;
+ m_App.m_Behaviors.push_back(eastl::make_pair(theBehaviorAsset, false));
+ }
+ } break;
+ case AssetValueTypes::RenderPlugin: {
+ SRenderPluginAsset &thePluginAsset = *theAsset.getDataPtr<SRenderPluginAsset>();
+
+ inFactory.GetSceneManager().LoadRenderPlugin(
+ thePluginAsset.m_Id, thePathStr.c_str(), thePluginAsset.m_Args);
+ } break;
+
+ case AssetValueTypes::QmlPresentation: {
+ SQmlPresentationAsset &asset = *theAsset.getDataPtr<SQmlPresentationAsset>();
+ inFactory.GetSceneManager().LoadQmlStreamerPlugin(asset.m_Id);
+ } break;
+ // SCXML, NoAssetValue do not need processing here
+ default:
+ break;
+ }
+ }
+ if (m_ScaleMode.empty() == false) {
+ const char8_t *initialScaleMode(m_ScaleMode.c_str());
+ // Force loading to finish here, just like used to happen.
+ if (AreEqual(initialScaleMode, "center")) {
+ inFactory.GetUICRenderContext().SetScaleMode(uic::render::ScaleModes::ExactSize);
+ } else if (AreEqual(initialScaleMode, "fit")) {
+ inFactory.GetUICRenderContext().SetScaleMode(uic::render::ScaleModes::ScaleToFit);
+ } else if (AreEqual(initialScaleMode, "fill")) {
+ inFactory.GetUICRenderContext().SetScaleMode(uic::render::ScaleModes::ScaleToFill);
+ } else {
+ qCCritical(INVALID_PARAMETER, "Unrecognized scale mode attribute value: ",
+ initialScaleMode);
+ }
+ }
+ }
+
+ virtual void OnFirstRender() {}
+};
+
+struct SLoadingPresentation
+{
+ QT3DSU32 m_SGHandle;
+ QT3DSU64 m_UIBJobId;
+ QT3DSU64 m_UIBSGJobId;
+ SPresentationAsset *m_Asset;
+ CRegisteredString m_UIBPath;
+ CRegisteredString m_UIBSGPath;
+ size_t m_ElementOffset;
+ Q3DStudio::TElement *m_RootElement;
+ NVDataRef<QT3DSU8> m_StringTableData;
+ volatile bool m_Finished;
+ volatile bool m_Error;
+ SLoadingPresentation(SPresentationAsset *inAsset = NULL,
+ CRegisteredString uib = CRegisteredString(),
+ CRegisteredString uibsg = CRegisteredString(), size_t inElementOffset = 0,
+ Q3DStudio::TElement *inRoot = 0,
+ NVDataRef<QT3DSU8> inStringTableData = NVDataRef<QT3DSU8>())
+ : m_SGHandle(0)
+ , m_UIBJobId(0)
+ , m_UIBSGJobId(0)
+ , m_Asset(inAsset)
+ , m_UIBPath(uib)
+ , m_UIBSGPath(uibsg)
+ , m_ElementOffset(inElementOffset)
+ , m_RootElement(inRoot)
+ , m_StringTableData(inStringTableData)
+ , m_Finished(false)
+ , m_Error(false)
+ {
+ }
+ // must be done with mutex held.
+ void CheckForFinished(SApp &inApp)
+ {
+ if (m_Finished == false && m_Error == false) {
+ if (m_Asset->m_Presentation != NULL && m_SGHandle != 0) {
+ m_Finished = true;
+ inApp.m_CoreFactory->GetSceneLoader().LoadSceneStage2(
+ m_SGHandle, *m_Asset->m_Presentation, m_ElementOffset,
+ inApp.m_CoreFactory->GetScriptEngine());
+ // inApp.m_CoreFactory->GetFoundation().error( QT3DS_WARN, "%s is finished",
+ // m_Asset->m_Src.c_str() );
+ }
+ }
+ }
+};
+
+typedef NVDataRef<SLoadingPresentation> TLoadingPresentationBuffer;
+
+struct SUIBLoadedCallback : public uic::render::IBufferLoaderCallback
+{
+ SApp &m_App;
+ TLoadingPresentationBuffer m_LoadingPresentations;
+ Mutex &m_PresentationInitMutex;
+ Q3DStudio::IBinarySerializer &m_BinarySerializer;
+ QT3DSI32 mRefCount;
+
+ SUIBLoadedCallback(SApp &inApp, TLoadingPresentationBuffer inBuffer, Mutex &inPresInitMutex,
+ Q3DStudio::IBinarySerializer &s)
+ : m_App(inApp)
+ , m_LoadingPresentations(inBuffer)
+ , m_PresentationInitMutex(inPresInitMutex)
+ , m_BinarySerializer(s)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_App.m_CoreFactory->GetFoundation().getAllocator())
+
+ eastl::pair<SLoadingPresentation *, QT3DSU32> FindBuffer(CRegisteredString inPath)
+ {
+ SLoadingPresentation *theLoadingPresentation = NULL;
+ QT3DSU32 theLoadBufferIdx;
+ QT3DSU32 end = m_LoadingPresentations.size();
+ for (theLoadBufferIdx = 0; theLoadBufferIdx < end && theLoadingPresentation == NULL;
+ ++theLoadBufferIdx) {
+ if (m_LoadingPresentations[theLoadBufferIdx].m_UIBPath == inPath)
+ theLoadingPresentation = &m_LoadingPresentations[theLoadBufferIdx];
+ }
+ return eastl::make_pair(theLoadingPresentation, theLoadBufferIdx - 1);
+ }
+
+ static void SetPresentation(TElement &inElement, CPresentation &inPresentation)
+ {
+ inElement.SetBelongedPresentation(inPresentation);
+ for (TElement *theChild = inElement.m_Child; theChild; theChild = theChild->m_Sibling)
+ SetPresentation(*theChild, inPresentation);
+ }
+
+ void OnBufferLoaded(uic::render::ILoadedBuffer &inBuffer) override
+ {
+ eastl::pair<SLoadingPresentation *, QT3DSU32> theBufferData = FindBuffer(inBuffer.Path());
+ SLoadingPresentation *theLoadingPresentation = theBufferData.first;
+ if (theLoadingPresentation) {
+ if (theLoadingPresentation->m_Error == false) {
+ m_App.m_CoreFactory->GetScriptEngine().EndPreloadScripts();
+ bool success = false;
+ SPresentationAsset &theAsset(*theLoadingPresentation->m_Asset);
+ {
+ Mutex::ScopedLock __presLock(m_PresentationInitMutex);
+ theAsset.m_Presentation
+ = Q3DStudio_new(CPresentation) CPresentation(theAsset.m_Id.c_str(),
+ &m_App);
+ theAsset.m_Presentation->SetFilePath(inBuffer.Path().c_str());
+ theAsset.m_Presentation->SetRoot(*theLoadingPresentation->m_RootElement);
+ SetPresentation(*theLoadingPresentation->m_RootElement,
+ *theAsset.m_Presentation);
+ Q3DStudio::IBinarySerializer &thePresentationSerializer(m_BinarySerializer);
+ {
+ SStackPerfTimer __perfTimer(m_App.m_CoreFactory->GetPerfTimer(),
+ "Load UIB");
+ success = thePresentationSerializer.BinaryLoad(
+ theAsset.m_Presentation,
+ theLoadingPresentation->m_ElementOffset,
+ inBuffer.Data(),
+ theLoadingPresentation->m_StringTableData,
+ m_App.m_CoreFactory->GetPerfTimer());
+
+ // Keep reference to buffer for the things that are loaded in place.
+ theAsset.m_Presentation->SetLoadedBuffer(inBuffer);
+ }
+ }
+ {
+ SStackPerfTimer __perfTimer(m_App.m_CoreFactory->GetPerfTimer(),
+ "Load Presentation Debug Data");
+ m_App.GetSceneGraphDebugger().BinaryLoadPresentation(
+ theAsset.m_Presentation, theAsset.m_Id.c_str(),
+ theLoadingPresentation->m_ElementOffset);
+ }
+
+ {
+ Mutex::ScopedLock __presLock(m_PresentationInitMutex);
+ theLoadingPresentation->CheckForFinished(m_App);
+ }
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ void SetFailCondition(CRegisteredString inPath)
+ {
+ eastl::pair<SLoadingPresentation *, QT3DSU32> theBufferData = FindBuffer(inPath);
+ if (theBufferData.first)
+ theBufferData.first->m_Error = true;
+ }
+ void OnBufferLoadFailed(CRegisteredString inPath) override { SetFailCondition(inPath); }
+ void OnBufferLoadCancelled(CRegisteredString inPath) override { SetFailCondition(inPath); }
+};
+
+struct SUIBSGLoadedCallback : public uic::render::IBufferLoaderCallback
+{
+ SApp &m_App;
+ TLoadingPresentationBuffer m_LoadingPresentations;
+ Mutex &m_PresentationMutex;
+ QT3DSI32 mRefCount;
+
+ SUIBSGLoadedCallback(SApp &inApp, TLoadingPresentationBuffer inBuffer,
+ Mutex &inPresentationMutex)
+ : m_App(inApp)
+ , m_LoadingPresentations(inBuffer)
+ , m_PresentationMutex(inPresentationMutex)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_App.m_CoreFactory->GetFoundation().getAllocator())
+
+ eastl::pair<SLoadingPresentation *, QT3DSU32> FindBuffer(CRegisteredString inPath)
+ {
+ SLoadingPresentation *theLoadingPresentation = NULL;
+ QT3DSU32 theLoadBufferIdx;
+ QT3DSU32 end = m_LoadingPresentations.size();
+ for (theLoadBufferIdx = 0; theLoadBufferIdx < end && theLoadingPresentation == NULL;
+ ++theLoadBufferIdx) {
+ if (m_LoadingPresentations[theLoadBufferIdx].m_UIBSGPath == inPath)
+ theLoadingPresentation = &m_LoadingPresentations[theLoadBufferIdx];
+ }
+ return eastl::make_pair(theLoadingPresentation, theLoadBufferIdx - 1);
+ }
+
+ void OnBufferLoaded(uic::render::ILoadedBuffer &inBuffer) override
+ {
+ SLoadingPresentation *theLoadingPresentation = FindBuffer(inBuffer.Path()).first;
+
+ if (theLoadingPresentation && theLoadingPresentation->m_Error == false) {
+ QT3DSU32 sgHandle = m_App.m_CoreFactory->GetSceneLoader().LoadSceneStage1(
+ m_App.GetProjectDirectory(), inBuffer);
+
+ {
+ Mutex::ScopedLock __presLock(m_PresentationMutex);
+ theLoadingPresentation->m_SGHandle = sgHandle;
+ m_App.m_CoreFactory->GetScriptEngine().EndPreloadScripts();
+ theLoadingPresentation->CheckForFinished(m_App);
+ }
+ }
+ }
+ void SetFailCondition(CRegisteredString inPath)
+ {
+ eastl::pair<SLoadingPresentation *, QT3DSU32> theBufferData = FindBuffer(inPath);
+ if (theBufferData.first)
+ theBufferData.first->m_Error = true;
+ }
+ void OnBufferLoadFailed(CRegisteredString inPath) override { SetFailCondition(inPath); }
+ void OnBufferLoadCancelled(CRegisteredString inPath) override { SetFailCondition(inPath); }
+};
+
+struct SBinaryLoader : public IAppLoadContext, public IAppRunnable
+{
+ SApp &m_App;
+ uic::render::ScaleModes::Enum m_ScaleMode;
+ Mutex m_PresentationInitMutex;
+ NVScopedRefCounted<SUIBLoadedCallback> m_UIBCallback;
+ NVScopedRefCounted<SUIBSGLoadedCallback> m_UIBSGCallback;
+ Q3DStudio::IBinarySerializer &m_BinarySerializer;
+ eastl::vector<SLoadingPresentation> m_LoadingPresentations;
+ SStackPerfTimer *m_OfflineLoadTimer;
+ QT3DSI32 mRefCount;
+
+ SBinaryLoader(SApp &app, uic::render::ScaleModes::Enum sc, NVDataRef<QT3DSU8> inStringTableData)
+ : m_App(app)
+ , m_ScaleMode(sc)
+ , m_PresentationInitMutex(app.m_CoreFactory->GetFoundation().getAllocator())
+ , m_BinarySerializer(IBinarySerializer::Create())
+ , m_OfflineLoadTimer(
+ new SStackPerfTimer(app.m_CoreFactory->GetPerfTimer(), "Binary Offline Load"))
+ , mRefCount(0)
+ {
+ using uic::render::IBufferLoader;
+ IBufferLoader &theLoader(m_App.m_CoreFactory->GetUICRenderContextCore().GetBufferLoader());
+ eastl::string fullpath, directory, filename, extension, sceneGraphPath, presentationPath;
+ IStringTable &theStringTable(m_App.m_CoreFactory->GetStringTable());
+ for (QT3DSU32 idx = 0, end = app.m_OrderedAssets.size(); idx < end; ++idx) {
+ SAssetValue &theValue = *app.m_OrderedAssets[idx].second;
+ if (theValue.getType() == AssetValueTypes::Presentation) {
+ size_t presentationIndex = m_LoadingPresentations.size();
+ if (presentationIndex < m_App.m_ElementLoadResult.first.size()
+ && m_App.m_ElementLoadResult.first[(QT3DSU32)presentationIndex]) {
+ SPresentationAsset &theAsset = *theValue.getDataPtr<SPresentationAsset>();
+ CFileTools::CombineBaseAndRelative(m_App.GetProjectDirectory().c_str(),
+ theAsset.m_Src, fullpath);
+ m_App.m_CoreFactory->GetSceneLoader().GetBinaryLoadFileName(fullpath,
+ sceneGraphPath);
+ CFileTools::Split(fullpath.c_str(), directory, filename, extension);
+ presentationPath.assign(directory);
+ presentationPath.append("/binary/");
+ presentationPath.append(filename);
+ presentationPath.append(".uib");
+ m_LoadingPresentations.push_back(
+ SLoadingPresentation(
+ &theAsset,
+ theStringTable.RegisterStr(presentationPath.c_str()),
+ theStringTable.RegisterStr(sceneGraphPath.c_str()),
+ m_App.m_ElementLoadResult.second,
+ m_App.m_ElementLoadResult.first[(QT3DSU32)presentationIndex],
+ inStringTableData));
+ }
+ }
+ }
+ if (m_LoadingPresentations.size()) {
+ SLoadingPresentation *beginPtr = m_LoadingPresentations.data();
+ TLoadingPresentationBuffer theBuffer(beginPtr, (QT3DSU32)m_LoadingPresentations.size());
+ m_UIBCallback
+ = QT3DS_NEW(m_App.m_CoreFactory->GetFoundation().getAllocator(),
+ SUIBLoadedCallback)(m_App, theBuffer, m_PresentationInitMutex,
+ m_BinarySerializer);
+
+ m_UIBSGCallback
+ = QT3DS_NEW(m_App.m_CoreFactory->GetFoundation().getAllocator(),
+ SUIBSGLoadedCallback)(m_App, theBuffer, m_PresentationInitMutex);
+ for (QT3DSU32 idx = 0, end = m_LoadingPresentations.size(); idx < end; ++idx) {
+ SLoadingPresentation &thePresentation(m_LoadingPresentations[idx]);
+ thePresentation.m_UIBJobId
+ = theLoader.QueueForLoading(thePresentation.m_UIBPath, m_UIBCallback.mPtr);
+ thePresentation.m_UIBSGJobId
+ = theLoader.QueueForLoading(thePresentation.m_UIBSGPath,
+ m_UIBSGCallback.mPtr);
+ }
+ }
+ m_App.QueueForMainThread(*this);
+ }
+
+ ~SBinaryLoader()
+ {
+ using uic::render::IBufferLoader;
+ NVFoundationBase &theBase = m_App.m_CoreFactory->GetUICRenderContextCore().GetFoundation();
+ IBufferLoader &theLoader(m_App.m_CoreFactory->GetUICRenderContextCore().GetBufferLoader());
+ (void)theBase;
+ // theBase.error( QT3DS_WARN, "Binary Loader -cancel load" );
+ {
+ Mutex::ScopedLock __locker(m_PresentationInitMutex);
+ for (QT3DSU32 idx = 0, end = m_LoadingPresentations.size(); idx < end; ++idx) {
+ SLoadingPresentation &thePresentation(m_LoadingPresentations[idx]);
+
+ if (thePresentation.m_Error == false) {
+ thePresentation.m_Error = true;
+ theLoader.CancelBufferLoad(thePresentation.m_UIBJobId);
+ theLoader.CancelBufferLoad(thePresentation.m_UIBSGJobId);
+ }
+ }
+ }
+
+ // theBase.error( QT3DS_WARN, "Binary Loader -clearing load queue" );
+ // Clear out any remaining buffers before we get destroyed else they will callback to us in
+ // their
+ // destructors causing chaos.
+ while (theLoader.WillLoadedBuffersBeAvailable())
+ theLoader.NextLoadedBuffer();
+
+ // theBase.error( QT3DS_WARN, "Binary Loader load queue cleared" );
+
+ if (m_OfflineLoadTimer)
+ delete m_OfflineLoadTimer;
+ m_OfflineLoadTimer = NULL;
+
+ m_BinarySerializer.release();
+ }
+
+ void addRef() override { atomicIncrement(&mRefCount); }
+ void release() override
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0)
+ NVDelete(m_App.m_CoreFactory->GetFoundation().getAllocator(), this);
+ }
+
+ void EndLoad() override
+ {
+ using uic::render::IBufferLoader;
+ IBufferLoader &theLoader(m_App.m_CoreFactory->GetUICRenderContextCore().GetBufferLoader());
+ while (theLoader.WillLoadedBuffersBeAvailable())
+ theLoader.NextLoadedBuffer();
+ }
+
+ bool HasCompletedLoading() override
+ {
+ bool completed = true;
+ for (QT3DSU32 idx = 0, end = m_LoadingPresentations.size(); idx < end && completed; ++idx) {
+ SLoadingPresentation &thePresentation(m_LoadingPresentations[idx]);
+ completed = thePresentation.m_Error || thePresentation.m_Finished;
+ }
+ if (completed) {
+ if (m_OfflineLoadTimer) {
+ delete m_OfflineLoadTimer;
+ m_OfflineLoadTimer = NULL;
+ }
+ }
+ return completed;
+ }
+
+ void OnGraphicsInitialized(IRuntimeFactory &inRuntimeFactory) override
+ {
+ EndLoad();
+
+ // Ensure we stop the timer.
+ HasCompletedLoading();
+
+ for (QT3DSU32 idx = 0, end = m_LoadingPresentations.size(); idx < end; ++idx) {
+ SLoadingPresentation &thePresentation(m_LoadingPresentations[idx]);
+ if (thePresentation.m_Error) {
+ qFatal("Error detected loading presentation: %s",
+ thePresentation.m_Asset->m_Src.c_str());
+ }
+ if (thePresentation.m_Finished == false) {
+ qFatal("Unfinished presentation: %s",
+ thePresentation.m_Asset->m_Src.c_str());
+ }
+ }
+
+ inRuntimeFactory.GetUICRenderContext().SetScaleMode(m_ScaleMode);
+
+ for (QT3DSU32 idx = 0, end = m_App.m_OrderedAssets.size(); idx < end; ++idx) {
+ if (m_App.m_OrderedAssets[idx].second->getType() == AssetValueTypes::Presentation) {
+ // Register the scenes.
+ SPresentationAsset &thePresentationAsset
+ = *m_App.m_OrderedAssets[idx].second->getDataPtr<SPresentationAsset>();
+ if (thePresentationAsset.m_Presentation
+ && thePresentationAsset.m_Presentation->GetScene()
+ && thePresentationAsset.m_Id.c_str()) {
+ thePresentationAsset.m_Presentation->GetScene()->RegisterOffscreenRenderer(
+ thePresentationAsset.m_Id.c_str());
+ }
+ }
+ }
+ }
+
+ virtual void OnFirstRender() {}
+
+ // IAppRunnable
+ void Run() override
+ {
+ SBinaryLoader &theLoader = *this;
+ theLoader.m_App.m_CoreFactory->GetScriptEngine().EndPreloadScripts();
+ {
+ SStackPerfTimer __perfTimer(theLoader.m_App.m_CoreFactory->GetPerfTimer(),
+ "Application: Initialize application behaviors");
+
+ for (QT3DSU32 idx = 0, end = theLoader.m_App.m_OrderedAssets.size(); idx < end; ++idx) {
+ if (theLoader.m_App.m_OrderedAssets[idx].second->getType()
+ == AssetValueTypes::Behavior) {
+ SBehaviorAsset &theBehaviorAsset =
+ *theLoader.m_App.m_OrderedAssets[idx]
+ .second->getDataPtr<SBehaviorAsset>();
+ SStackPerfTimer __perfTimer(theLoader.m_App.m_CoreFactory->GetPerfTimer(),
+ theBehaviorAsset.m_Src.c_str());
+ Q3DStudio::INT32 scriptId =
+ theLoader.m_App.m_CoreFactory->GetScriptEngine()
+ .InitializeApplicationBehavior(theBehaviorAsset.m_Src);
+ if (scriptId == 0) {
+ qCCritical(INVALID_OPERATION, "Unable to load application behavior %s",
+ theBehaviorAsset.m_Src.c_str());
+ } else {
+ theBehaviorAsset.m_Handle = scriptId;
+ theLoader.m_App.m_Behaviors.push_back(eastl::make_pair(theBehaviorAsset,
+ false));
+ }
+ }
+ }
+ }
+ }
+};
+
+IAppLoadContext &IAppLoadContext::CreateXMLLoadContext(
+ SApp &inApp, NVConstDataRef<uic::state::SElementReference> inStateReferences,
+ const char8_t *inScaleMode)
+{
+ return *QT3DS_NEW(inApp.m_CoreFactory->GetFoundation().getAllocator(),
+ SXMLLoader)(inApp, inScaleMode, inStateReferences);
+}
+
+IAppLoadContext &IAppLoadContext::CreateBinaryLoadContext(SApp &inApp,
+ uic::render::ScaleModes::Enum inScaleMode,
+ NVDataRef<QT3DSU8> inStrTableData)
+{
+ return *QT3DS_NEW(inApp.m_CoreFactory->GetFoundation().getAllocator(),
+ SBinaryLoader)(inApp, inScaleMode, inStrTableData);
+}
+}
+
+CAppStr::CAppStr(NVAllocatorCallback &alloc, const char8_t *inStr)
+ : TBase(inStr, ForwardingAllocator(alloc, "CAppStr"))
+{
+}
+
+CAppStr::CAppStr(const CAppStr &inOther)
+ : TBase(inOther)
+{
+}
+
+CAppStr::CAppStr()
+ : TBase()
+{
+}
+
+CAppStr &CAppStr::operator=(const CAppStr &inOther)
+{
+ TBase::operator=(inOther);
+ return *this;
+}
+
+IApplicationCore &IApplicationCore::CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
+ const char8_t *inApplicationDirectory)
+{
+ return *QT3DS_NEW(inFactory.GetFoundation().getAllocator(), SApp)(inFactory,
+ inApplicationDirectory);
+}
+
+// Checks if the event is one that can cause picking
+bool IApplicationCore::isPickingEvent(TEventCommandHash event)
+{
+ return (event == ON_MOUSEDOWN
+ || event == ON_MOUSEUP
+ || event == ON_MIDDLEMOUSEDOWN
+ || event == ON_MIDDLEMOUSEUP
+ || event == ON_RIGHTMOUSEDOWN
+ || event == ON_RIGHTMOUSEUP
+ || event == ON_MOUSECLICK
+ || event == ON_MIDDLEMOUSECLICK
+ || event == ON_RIGHTMOUSECLICK
+ || event == ON_MOUSEOVER
+ || event == ON_MOUSEOUT
+ || event == ON_GROUPEDMOUSEOVER
+ || event == ON_GROUPEDMOUSEOUT);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICAttributeHashes.cpp b/src/Runtime/Source/Runtime/Source/UICAttributeHashes.cpp
new file mode 100644
index 00000000..8df0ba3b
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICAttributeHashes.cpp
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICAttributeHashes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AUTOGENERATED CODE
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// Run the AttributeHashes project to regenerate this file from Attributehashes.txt list
+
+/// Function providing reverse hash lookup
+const char *GetAttributeString(const EAttribute inAttribute)
+{
+ switch (inAttribute) {
+ case ATTRIBUTE_NAME:
+ return "name";
+ case ATTRIBUTE_TYPE:
+ return "type";
+ case ATTRIBUTE_OPACITY:
+ return "opacity";
+ case ATTRIBUTE_STARTTIME:
+ return "starttime";
+ case ATTRIBUTE_ENDTIME:
+ return "endtime";
+ case ATTRIBUTE_SOURCEPATH:
+ return "sourcepath";
+ case ATTRIBUTE_IMPORTID:
+ return "importid";
+ case ATTRIBUTE_EYEBALL:
+ return "eyeball";
+ case ATTRIBUTE_POSITION:
+ return "position";
+ case ATTRIBUTE_POSITION_X:
+ return "position.x";
+ case ATTRIBUTE_POSITION_Y:
+ return "position.y";
+ case ATTRIBUTE_POSITION_Z:
+ return "position.z";
+ case ATTRIBUTE_ROTATION:
+ return "rotation";
+ case ATTRIBUTE_ROTATION_X:
+ return "rotation.x";
+ case ATTRIBUTE_ROTATION_Y:
+ return "rotation.y";
+ case ATTRIBUTE_ROTATION_Z:
+ return "rotation.z";
+ case ATTRIBUTE_SCALE:
+ return "scale";
+ case ATTRIBUTE_SCALE_X:
+ return "scale.x";
+ case ATTRIBUTE_SCALE_Y:
+ return "scale.y";
+ case ATTRIBUTE_SCALE_Z:
+ return "scale.z";
+ case ATTRIBUTE_PIVOT:
+ return "pivot";
+ case ATTRIBUTE_PIVOT_X:
+ return "pivot.x";
+ case ATTRIBUTE_PIVOT_Y:
+ return "pivot.y";
+ case ATTRIBUTE_PIVOT_Z:
+ return "pivot.z";
+ case ATTRIBUTE_ROTATIONORDER:
+ return "rotationorder";
+ case ATTRIBUTE_ORIENTATION:
+ return "orientation";
+ case ATTRIBUTE_TESSELLATION:
+ return "tessellation";
+ case ATTRIBUTE_EDGETESS:
+ return "edgetess";
+ case ATTRIBUTE_INNERTESS:
+ return "innertess";
+ case ATTRIBUTE_ORTHOGRAPHIC:
+ return "orthographic";
+ case ATTRIBUTE_CLIPNEAR:
+ return "clipnear";
+ case ATTRIBUTE_CLIPFAR:
+ return "clipfar";
+ case ATTRIBUTE_FOV:
+ return "fov";
+ case ATTRIBUTE_SCALEMODE:
+ return "scalemode";
+ case ATTRIBUTE_SCALEANCHOR:
+ return "scaleanchor";
+ case ATTRIBUTE_BRIGHTNESS:
+ return "brightness";
+ case ATTRIBUTE_LINEARFADE:
+ return "linearfade";
+ case ATTRIBUTE_EXPFADE:
+ return "expfade";
+ case ATTRIBUTE_LIGHTTYPE:
+ return "lighttype";
+ case ATTRIBUTE_SCOPE:
+ return "scope";
+ case ATTRIBUTE_LIGHTDIFFUSE:
+ return "lightdiffuse";
+ case ATTRIBUTE_LIGHTDIFFUSE_R:
+ return "lightdiffuse.r";
+ case ATTRIBUTE_LIGHTDIFFUSE_G:
+ return "lightdiffuse.g";
+ case ATTRIBUTE_LIGHTDIFFUSE_B:
+ return "lightdiffuse.b";
+ case ATTRIBUTE_LIGHTAMBIENT_R:
+ return "lightambient.r";
+ case ATTRIBUTE_LIGHTAMBIENT:
+ return "lightambient";
+ case ATTRIBUTE_LIGHTAMBIENT_G:
+ return "lightambient.g";
+ case ATTRIBUTE_LIGHTAMBIENT_B:
+ return "lightambient.b";
+ case ATTRIBUTE_LIGHTSPECULAR:
+ return "lightspecular";
+ case ATTRIBUTE_LIGHTSPECULAR_R:
+ return "lightspecular.r";
+ case ATTRIBUTE_LIGHTSPECULAR_G:
+ return "lightspecular.g";
+ case ATTRIBUTE_LIGHTSPECULAR_B:
+ return "lightspecular.b";
+ case ATTRIBUTE_AREAWIDTH:
+ return "areawidth";
+ case ATTRIBUTE_AREAHEIGHT:
+ return "areaheight";
+ case ATTRIBUTE_CASTSHADOW:
+ return "castshadow";
+ case ATTRIBUTE_SHDWBIAS:
+ return "shdwbias";
+ case ATTRIBUTE_SHDWFACTOR:
+ return "shdwfactor";
+ case ATTRIBUTE_SHDWMAPRES:
+ return "shdwmapres";
+ case ATTRIBUTE_SHDWMAPFAR:
+ return "shdwmapfar";
+ case ATTRIBUTE_SHDWFILTER:
+ return "shdwfilter";
+ case ATTRIBUTE_LIGHTMAPINDIRECT:
+ return "lightmapindirect";
+ case ATTRIBUTE_LIGHTMAPRADIOSITY:
+ return "lightmapradiosity";
+ case ATTRIBUTE_LIGHTMAPSHADOW:
+ return "lightmapshadow";
+ case ATTRIBUTE_IBLPROBE:
+ return "iblprobe";
+ case ATTRIBUTE_SHADERLIGHTING:
+ return "shaderlighting";
+ case ATTRIBUTE_EMISSIVEPOWER:
+ return "emissivepower";
+ case ATTRIBUTE_EMISSIVECOLOR:
+ return "emissivecolor";
+ case ATTRIBUTE_EMISSIVECOLOR_R:
+ return "emissivecolor.r";
+ case ATTRIBUTE_EMISSIVECOLOR_G:
+ return "emissivecolor.g";
+ case ATTRIBUTE_EMISSIVECOLOR_B:
+ return "emissivecolor.b";
+ case ATTRIBUTE_DIFFUSE:
+ return "diffuse";
+ case ATTRIBUTE_DIFFUSE_R:
+ return "diffuse.r";
+ case ATTRIBUTE_DIFFUSE_G:
+ return "diffuse.g";
+ case ATTRIBUTE_DIFFUSE_B:
+ return "diffuse.b";
+ case ATTRIBUTE_SPECULARMAP:
+ return "specularmap";
+ case ATTRIBUTE_SPECULARMODEL:
+ return "specularmodel";
+ case ATTRIBUTE_SPECULARTINT:
+ return "speculartint";
+ case ATTRIBUTE_SPECULARTINT_R:
+ return "speculartint.r";
+ case ATTRIBUTE_SPECULARTINT_G:
+ return "speculartint.g";
+ case ATTRIBUTE_SPECULARTINT_B:
+ return "speculartint.b";
+ case ATTRIBUTE_IOR:
+ return "ior";
+ case ATTRIBUTE_FRESNELPOWER:
+ return "fresnelPower";
+ case ATTRIBUTE_SPECULARAMOUNT:
+ return "specularamount";
+ case ATTRIBUTE_SPECULARROUGHNESS:
+ return "specularroughness";
+ case ATTRIBUTE_BLENDMODE:
+ return "blendmode";
+ case ATTRIBUTE_CULLING:
+ return "culling";
+ case ATTRIBUTE_ZBUFFERWRITE:
+ return "zbufferwrite";
+ case ATTRIBUTE_DIFFUSEMAP:
+ return "diffusemap";
+ case ATTRIBUTE_DIFFUSEMAP2:
+ return "diffusemap2";
+ case ATTRIBUTE_DIFFUSEMAP3:
+ return "diffusemap3";
+ case ATTRIBUTE_SPECULARREFLECTION:
+ return "specularreflection";
+ case ATTRIBUTE_OPACITYMAP:
+ return "opacitymap";
+ case ATTRIBUTE_EMISSIVEMAP:
+ return "emissivemap";
+ case ATTRIBUTE_EMISSIVEMAP2:
+ return "emissivemap2";
+ case ATTRIBUTE_BUMPMAP:
+ return "bumpmap";
+ case ATTRIBUTE_BUMPAMOUNT:
+ return "bumpamount";
+ case ATTRIBUTE_NORMALMAP:
+ return "normalmap";
+ case ATTRIBUTE_DISPLACEMENTMAP:
+ return "displacementmap";
+ case ATTRIBUTE_DISPLACEAMOUNT:
+ return "displaceamount";
+ case ATTRIBUTE_TRANSLUCENCYMAP:
+ return "translucencymap";
+ case ATTRIBUTE_TRANSLUCENTFALLOFF:
+ return "translucentfalloff";
+ case ATTRIBUTE_DIFFUSELIGHTWRAP:
+ return "diffuselightwrap";
+ case ATTRIBUTE_REFERENCEDMATERIAL:
+ return "referencedmaterial";
+ case ATTRIBUTE_ROTATIONUV:
+ return "rotationuv";
+ case ATTRIBUTE_POSITIONU:
+ return "positionu";
+ case ATTRIBUTE_POSITIONV:
+ return "positionv";
+ case ATTRIBUTE_SCALEU:
+ return "scaleu";
+ case ATTRIBUTE_SCALEV:
+ return "scalev";
+ case ATTRIBUTE_PIVOTU:
+ return "pivotu";
+ case ATTRIBUTE_PIVOTV:
+ return "pivotv";
+ case ATTRIBUTE_TILINGMODEHORZ:
+ return "tilingmodehorz";
+ case ATTRIBUTE_TILINGMODEVERT:
+ return "tilingmodevert";
+ case ATTRIBUTE_MAPPINGTYPE:
+ return "mappingtype";
+ case ATTRIBUTE_MAPPINGMODE:
+ return "mappingmode";
+ case ATTRIBUTE_SUBPRESENTATION:
+ return "subpresentation";
+ case ATTRIBUTE_URI:
+ return "uri";
+ case ATTRIBUTE_TRANSPARENT:
+ return "transparent";
+ case ATTRIBUTE_PROGRESSIVEAA:
+ return "progressiveaa";
+ case ATTRIBUTE_MULTISAMPLEAA:
+ return "multisampleaa";
+ case ATTRIBUTE_TEMPORALAA:
+ return "temporalaa";
+ case ATTRIBUTE_BLENDTYPE:
+ return "blendtype";
+ case ATTRIBUTE_HORZFIELDS:
+ return "horzfields";
+ case ATTRIBUTE_LEFT:
+ return "left";
+ case ATTRIBUTE_LEFTUNITS:
+ return "leftunits";
+ case ATTRIBUTE_WIDTH:
+ return "width";
+ case ATTRIBUTE_WIDTHUNITS:
+ return "widthunits";
+ case ATTRIBUTE_RIGHT:
+ return "right";
+ case ATTRIBUTE_RIGHTUNITS:
+ return "rightunits";
+ case ATTRIBUTE_VERTFIELDS:
+ return "vertfields";
+ case ATTRIBUTE_TOP:
+ return "top";
+ case ATTRIBUTE_TOPUNITS:
+ return "topunits";
+ case ATTRIBUTE_HEIGHT:
+ return "height";
+ case ATTRIBUTE_HEIGHTUNITS:
+ return "heightunits";
+ case ATTRIBUTE_BOTTOM:
+ return "bottom";
+ case ATTRIBUTE_BOTTOMUNITS:
+ return "bottomunits";
+ case ATTRIBUTE_AOSTRENGTH:
+ return "aostrength";
+ case ATTRIBUTE_AODISTANCE:
+ return "aodistance";
+ case ATTRIBUTE_AOSOFTNESS:
+ return "aosoftness";
+ case ATTRIBUTE_AOBIAS:
+ return "aobias";
+ case ATTRIBUTE_AOSAMPLERATE:
+ return "aosamplerate";
+ case ATTRIBUTE_AODITHER:
+ return "aodither";
+ case ATTRIBUTE_SHADOWSTRENGTH:
+ return "shadowstrength";
+ case ATTRIBUTE_SHADOWDIST:
+ return "shadowdist";
+ case ATTRIBUTE_SHADOWSOFTNESS:
+ return "shadowsoftness";
+ case ATTRIBUTE_SHADOWBIAS:
+ return "shadowbias";
+ case ATTRIBUTE_LIGHTPROBE:
+ return "lightprobe";
+ case ATTRIBUTE_PROBEBRIGHT:
+ return "probebright";
+ case ATTRIBUTE_FASTIBL:
+ return "fastibl";
+ case ATTRIBUTE_PROBEHORIZON:
+ return "probehorizon";
+ case ATTRIBUTE_PROBEFOV:
+ return "probefov";
+ case ATTRIBUTE_LIGHTPROBE2:
+ return "lightprobe2";
+ case ATTRIBUTE_PROBE2FADE:
+ return "probe2fade";
+ case ATTRIBUTE_PROBE2WINDOW:
+ return "probe2window";
+ case ATTRIBUTE_PROBE2POS:
+ return "probe2pos";
+ case ATTRIBUTE_DISABLEDEPTHTEST:
+ return "disabledepthtest";
+ case ATTRIBUTE_DISABLEDEPTHPREPASS:
+ return "disabledepthprepass";
+ case ATTRIBUTE_TEXTCOLOR:
+ return "textcolor";
+ case ATTRIBUTE_TEXTCOLOR_R:
+ return "textcolor.r";
+ case ATTRIBUTE_TEXTCOLOR_G:
+ return "textcolor.g";
+ case ATTRIBUTE_TEXTCOLOR_B:
+ return "textcolor.b";
+ case ATTRIBUTE_SIZE:
+ return "size";
+ case ATTRIBUTE_FONT:
+ return "font";
+ case ATTRIBUTE_TRACKING:
+ return "tracking";
+ case ATTRIBUTE_LEADING:
+ return "leading";
+ case ATTRIBUTE_RENDERSTYLE:
+ return "renderstyle";
+ case ATTRIBUTE_TEXTSTRING:
+ return "textstring";
+ case ATTRIBUTE_BACKCOLOR_R:
+ return "backcolor.r";
+ case ATTRIBUTE_BACKCOLOR_G:
+ return "backcolor.g";
+ case ATTRIBUTE_BACKCOLOR_B:
+ return "backcolor.b";
+ case ATTRIBUTE_TEXTTYPE:
+ return "texttype";
+ case ATTRIBUTE_USEBACKCOLOR:
+ return "usebackcolor";
+ case ATTRIBUTE_WORDWRAP:
+ return "wordwrap";
+ case ATTRIBUTE_HORZSCROLL:
+ return "horzscroll";
+ case ATTRIBUTE_HORZALIGN:
+ return "horzalign";
+ case ATTRIBUTE_VERTSCROLL:
+ return "vertscroll";
+ case ATTRIBUTE_VERTALIGN:
+ return "vertalign";
+ case ATTRIBUTE_BOXHEIGHT:
+ return "boxheight";
+ case ATTRIBUTE_BOXWIDTH:
+ return "boxwidth";
+ case ATTRIBUTE_REMOTESTRINGSOURCE:
+ return "remotestringsource";
+ case ATTRIBUTE_CACHEDTEXTSTRING:
+ return "cachedtextstring";
+ case ATTRIBUTE_ENABLEACCELERATEDFONT:
+ return "enableacceleratedfont";
+ case ATTRIBUTE_BEHAVIORSCRIPTS:
+ return "BehaviorScripts";
+ case ATTRIBUTE_UICCUSTOMOBJTYPE:
+ return "UICCustomObjType";
+ case ATTRIBUTE_BGCOLORENABLE:
+ return "bgcolorenable";
+ case ATTRIBUTE_BACKGROUND:
+ return "background";
+ case ATTRIBUTE_BACKGROUNDCOLOR_R:
+ return "backgroundcolor.r";
+ case ATTRIBUTE_BACKGROUNDCOLOR_G:
+ return "backgroundcolor.g";
+ case ATTRIBUTE_BACKGROUNDCOLOR_B:
+ return "backgroundcolor.b";
+ case ATTRIBUTE_PATHTYPE:
+ return "pathtype";
+ case ATTRIBUTE_LINEARERROR:
+ return "linearerror";
+ case ATTRIBUTE_EDGETESSAMOUNT:
+ return "edgetessamount";
+ case ATTRIBUTE_INNERTESSAMOUNT:
+ return "innertessamount";
+ case ATTRIBUTE_BEGINCAP:
+ return "begincap";
+ case ATTRIBUTE_BEGINCAPOFFSET:
+ return "begincapoffset";
+ case ATTRIBUTE_BEGINCAPOPACITY:
+ return "begincapopacity";
+ case ATTRIBUTE_BEGINCAPWIDTH:
+ return "begincapwidth";
+ case ATTRIBUTE_ENDCAP:
+ return "endcap";
+ case ATTRIBUTE_ENDCAPOFFSET:
+ return "endcapoffset";
+ case ATTRIBUTE_ENDCAPOPACITY:
+ return "endcapopacity";
+ case ATTRIBUTE_ENDCAPWIDTH:
+ return "endcapwidth";
+ case ATTRIBUTE_PAINTSTYLE:
+ return "paintstyle";
+ case ATTRIBUTE_CLOSED:
+ return "closed";
+ case ATTRIBUTE_INCOMINGANGLE:
+ return "incomingangle";
+ case ATTRIBUTE_INCOMINGDISTANCE:
+ return "incomingdistance";
+ case ATTRIBUTE_OUTGOINGDISTANCE:
+ return "outgoingdistance";
+ case ATTRIBUTE_PARTICLETYPE:
+ return "particletype";
+ case ATTRIBUTE_MAXPARTICLES:
+ return "maxparticles";
+ case ATTRIBUTE_PARTICLESIZE:
+ return "particlesize";
+ case ATTRIBUTE_LIFETIME:
+ return "lifetime";
+ case ATTRIBUTE_QT_IO:
+ return "qt.io";
+ default: {
+ static char s_UnknownHash[16];
+ sprintf(s_UnknownHash, "(0x%08X)", inAttribute);
+ return s_UnknownHash;
+ }
+ }
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICBinarySerializerImpl.cpp b/src/Runtime/Source/Runtime/Source/UICBinarySerializerImpl.cpp
new file mode 100644
index 00000000..50610bc8
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICBinarySerializerImpl.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICBinarySerializerImpl.h"
+#include "UICIPresentation.h"
+#include "UICPresentation.h"
+#include "UICIScriptBridge.h"
+#include "UICAttributeHashes.h"
+#include "UICFileStream.h"
+#include "foundation/IOStreams.h"
+#include "UICCommandEventTypes.h"
+#include "UICSceneManager.h"
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+#include "foundation/FileTools.h"
+#include "UICApplication.h"
+#include "UICRuntimeFactory.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICSlideSystem.h"
+#include "UICLogicSystem.h"
+#include "UICParametersSystem.h"
+
+using qt3ds::foundation::atomicIncrement;
+using qt3ds::foundation::atomicDecrement;
+using qt3ds::QT3DSI32;
+using uic::runtime::ISlideSystem;
+using qt3ds::foundation::SDataReader;
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace {
+
+using namespace qt3ds::foundation;
+using namespace qt3ds;
+using namespace uic::runtime;
+using Q3DStudio::CFileStream;
+
+struct SSerializerDataReadWrapper : public SDataReader
+{
+ SSerializerDataReadWrapper(qt3ds::QT3DSU8 *inBegin, qt3ds::QT3DSU8 *inEnd)
+ : SDataReader(inBegin, inEnd)
+ {
+ }
+
+ template <typename TDataType>
+ void ReadCopy(TDataType &dt)
+ {
+ dt = LoadRef<TDataType>();
+ }
+
+ template <typename TDataType>
+ void ReadRawCopy(TDataType *dt, Q3DStudio::UINT32 inByteCount)
+ {
+ MemCopy((QT3DSU8 *)dt, inByteCount);
+ }
+};
+
+void SaveToBinary(IOutStream &inStream, IAnimationSystem &inSystem, IElementAllocator &inAlloc)
+{
+ inSystem.SaveBinaryData(inStream, inAlloc);
+}
+
+void SaveToBinary(IOutStream &inStream, ILogicSystem &inSystem, IElementAllocator & /*inAlloc*/)
+{
+ inSystem.SaveBinaryData(inStream);
+}
+
+void SaveToBinary(IOutStream &inStream, ISlideSystem &inSystem, IElementAllocator & /*inAlloc*/)
+{
+ inSystem.SaveBinaryData(inStream);
+}
+
+void SaveToBinary(IOutStream &inStream, IParametersSystem &inSystem,
+ IElementAllocator & /*inAlloc*/)
+{
+ inSystem.SaveBinaryData(inStream);
+}
+
+template <typename TSystemType>
+void SaveSystemToBinary(CFileStream &inStream, TSystemType &inSystem,
+ NVFoundationBase &inFoundation, IElementAllocator &inAlloc)
+{
+ qt3ds::foundation::CMemorySeekableIOStream theMemStream(inFoundation.getAllocator(), "SaveData");
+ SaveToBinary(theMemStream, inSystem, inAlloc);
+ inStream.Write((Q3DStudio::UINT32)theMemStream.GetLength());
+ inStream.WriteRaw(theMemStream.begin(), (Q3DStudio::UINT32)theMemStream.GetLength());
+}
+
+void LoadFromBinary(IAnimationSystem &inSystem, NVDataRef<QT3DSU8> inData,
+ NVDataRef<QT3DSU8> /*inStrTable*/, size_t inElemOffset)
+{
+ inSystem.LoadBinaryData(inData, inElemOffset);
+}
+
+void LoadFromBinary(ILogicSystem &inSystem, NVDataRef<QT3DSU8> inData, NVDataRef<QT3DSU8> /*inStrTable*/,
+ size_t /*inElemOffset*/)
+{
+ inSystem.LoadBinaryData(inData);
+}
+
+void LoadFromBinary(ISlideSystem &inSystem, NVDataRef<QT3DSU8> inData, NVDataRef<QT3DSU8> inStrTable,
+ size_t inElemOffset)
+{
+ inSystem.LoadBinaryData(inData, inStrTable, inElemOffset);
+}
+
+void LoadFromBinary(IParametersSystem &inSystem, NVDataRef<QT3DSU8> inData,
+ NVDataRef<QT3DSU8> /*inStrTable*/, size_t /*inElemOffset*/)
+{
+ inSystem.LoadBinaryData(inData);
+}
+
+template <typename TSystemType>
+void LoadSystemFromBinary(SSerializerDataReadWrapper &inWrapper, TSystemType &inSystem,
+ NVDataRef<QT3DSU8> inStrTable, size_t inElemOffset)
+{
+ QT3DSU32 byteCount = inWrapper.LoadRef<QT3DSU32>();
+ NVDataRef<qt3ds::QT3DSU8> theData = toDataRef(inWrapper.m_CurrentPtr, byteCount);
+ inWrapper.m_CurrentPtr += byteCount;
+ LoadFromBinary(inSystem, theData, inStrTable, inElemOffset);
+}
+
+struct SLoadScript
+{
+ uic::runtime::element::SElement *m_Element;
+ QT3DSU32 m_ScriptHandle;
+ SLoadScript()
+ : m_Element(NULL)
+ {
+ }
+ SLoadScript(uic::runtime::element::SElement *inElement, QT3DSU32 inStrHandle)
+ : m_Element(inElement)
+ , m_ScriptHandle(inStrHandle)
+ {
+ }
+};
+
+struct SBinarySerializerAppRunnable : public uic::runtime::IAppRunnable
+{
+ qt3ds::NVFoundationBase &m_Foundation;
+ Q3DStudio::IScriptBridge &m_Bridge;
+ Q3DStudio::CPresentation &m_Presentation;
+ eastl::vector<SLoadScript> m_Scripts;
+ size_t m_ElemOffset;
+ qt3ds::QT3DSI32 mRefCount;
+
+ SBinarySerializerAppRunnable(qt3ds::NVFoundationBase &fnd, Q3DStudio::IScriptBridge &inBridge,
+ Q3DStudio::CPresentation &inPresentation, size_t inElemOffset)
+ : m_Foundation(fnd)
+ , m_Bridge(inBridge)
+ , m_Presentation(inPresentation)
+ , m_ElemOffset(inElemOffset)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void Run() override
+ {
+ using uic::runtime::element::SElement;
+ qt3ds::foundation::IStringTable &theStrTable(m_Presentation.GetStringTable());
+ for (QT3DSU32 idx = 0, end = m_Scripts.size(); idx < end; ++idx) {
+ SElement *theElement = reinterpret_cast<SElement *>(
+ reinterpret_cast<QT3DSU8 *>(m_Scripts[idx].m_Element) + m_ElemOffset);
+ m_Bridge.LoadScript(&m_Presentation, theElement,
+ theStrTable.HandleToStr(m_Scripts[idx].m_ScriptHandle));
+ }
+ }
+};
+
+void SaveScripts(eastl::vector<SLoadScript> &presentationScripts,
+ uic::runtime::element::SElement &inElement, CRegisteredString inSrcPathStr,
+ IElementAllocator &inAlloc)
+{
+ if (inElement.HasScriptCallbacks()) {
+ Q3DStudio::UVariant *theVariant = inElement.FindPropertyValue(inSrcPathStr);
+ if (theVariant) {
+ presentationScripts.push_back(SLoadScript(inAlloc.GetRemappedElementAddress(&inElement),
+ theVariant->m_StringHandle));
+ }
+ }
+ for (element::SElement *theChild = inElement.GetChild(); theChild;
+ theChild = theChild->m_Sibling)
+ SaveScripts(presentationScripts, *theChild, inSrcPathStr, inAlloc);
+}
+}
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CBinarySerializer::CBinarySerializer()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CBinarySerializer::~CBinarySerializer()
+{
+}
+
+void CBinarySerializer::BinarySave(CPresentation *inPresentation)
+{
+ // Serialize Runtime Portion
+ eastl::string thePath(inPresentation->GetFilePath().toLatin1().constData());
+ qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(thePath, "binary");
+ qt3ds::foundation::CFileTools::SetExtension(thePath, "uib");
+ CFileStream theStream(thePath.c_str(), "wb");
+ if (theStream.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ }
+
+ SPresentationSize theSize = inPresentation->GetSize();
+ theStream.Write(theSize.m_Width);
+ theStream.Write(theSize.m_Height);
+ theStream.Write(theSize.m_ScaleMode);
+
+ NVFoundationBase &theFoundation =
+ inPresentation->GetApplication().GetRuntimeFactoryCore().GetFoundation();
+ uic::runtime::IElementAllocator &theAllocator =
+ inPresentation->GetApplication().GetElementAllocator();
+
+ SaveSystemToBinary(theStream, inPresentation->GetAnimationSystem(), theFoundation,
+ theAllocator);
+ SaveSystemToBinary(theStream, inPresentation->GetLogicSystem(), theFoundation, theAllocator);
+ SaveSystemToBinary(theStream, inPresentation->GetSlideSystem(), theFoundation, theAllocator);
+ SaveSystemToBinary(theStream, inPresentation->GetParametersSystem(), theFoundation,
+ theAllocator);
+ eastl::vector<SLoadScript> theScripts;
+ SaveScripts(theScripts, *inPresentation->GetRoot(),
+ inPresentation->GetStringTable().RegisterStr("behaviorscripts"), theAllocator);
+ theStream.Write((QT3DSU32)theScripts.size());
+ if (!theScripts.empty())
+ theStream.WriteRaw(theScripts.data(), theScripts.size() * sizeof(SLoadScript));
+
+ theStream.Close();
+}
+
+BOOL CBinarySerializer::BinaryLoad(CPresentation *inPresentation, size_t inElementMemoryOffset,
+ qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> inPresentationFile,
+ qt3ds::foundation::NVDataRef<qt3ds::QT3DSU8> inStringTableData,
+ qt3ds::foundation::IPerfTimer &inPerfTimer)
+{
+ SSerializerDataReadWrapper theStream(inPresentationFile.begin(), inPresentationFile.end());
+ SPresentationSize theSize;
+ theStream.ReadCopy(theSize.m_Width);
+ theStream.ReadCopy(theSize.m_Height);
+ theStream.ReadCopy(theSize.m_ScaleMode);
+ inPresentation->SetSize(theSize);
+ {
+ SStackPerfTimer __perfTimer(inPerfTimer, "Load UIB - AnimationBuilder");
+ LoadSystemFromBinary(theStream, inPresentation->GetAnimationSystem(), inStringTableData,
+ inElementMemoryOffset);
+ }
+ {
+ SStackPerfTimer __perfTimer(inPerfTimer, "Load UIB - LogicBuilder");
+ LoadSystemFromBinary(theStream, inPresentation->GetLogicSystem(), inStringTableData,
+ inElementMemoryOffset);
+ }
+ {
+ SStackPerfTimer __perfTimer(inPerfTimer, "Load UIB - ParametersBuilder");
+ LoadSystemFromBinary(theStream, inPresentation->GetSlideSystem(), inStringTableData,
+ inElementMemoryOffset);
+ }
+ {
+ SStackPerfTimer __perfTimer(inPerfTimer, "Load UIB - SlideBuilder");
+ LoadSystemFromBinary(theStream, inPresentation->GetParametersSystem(), inStringTableData,
+ inElementMemoryOffset);
+ }
+ QT3DSU32 numScripts = theStream.LoadRef<QT3DSU32>();
+ if (numScripts) {
+ NVFoundationBase &theFoundation(
+ inPresentation->GetApplication().GetRuntimeFactoryCore().GetFoundation());
+ SBinarySerializerAppRunnable &theAppRunnable =
+ *QT3DS_NEW(theFoundation.getAllocator(),
+ SBinarySerializerAppRunnable)(theFoundation, *inPresentation->GetScriptBridge(),
+ *inPresentation, inElementMemoryOffset);
+ theAppRunnable.m_Scripts.resize(numScripts);
+ theStream.ReadRawCopy(theAppRunnable.m_Scripts.data(),
+ theAppRunnable.m_Scripts.size() * sizeof(SLoadScript));
+ inPresentation->GetApplication().QueueForMainThread(theAppRunnable);
+ }
+ return true;
+}
+
+IBinarySerializer &IBinarySerializer::Create()
+{
+ CBinarySerializer &retval = *new CBinarySerializer();
+ return retval;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICComponentManager.cpp b/src/Runtime/Source/Runtime/Source/UICComponentManager.cpp
new file mode 100644
index 00000000..8c9f3335
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICComponentManager.cpp
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICComponentManager.h"
+#include "UICIPresentation.h"
+#include "UICSlideSystem.h"
+#include "UICCommandEventTypes.h"
+#include "UICPresentationFrameData.h"
+#include "UICApplication.h"
+#include "UICActivationManager.h"
+#include "UICPresentation.h"
+
+using uic::runtime::SSlideKey;
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inPresentation reference to its presentation
+ */
+CComponentManager::CComponentManager(IPresentation &inPresentation)
+ : m_Presentation(static_cast<CPresentation &>(inPresentation))
+{
+}
+
+//==============================================================================
+/**
+ * Enforces the contract that slide switching requires a reset to the master
+ * slide (slide 0) before switching to the desired slide index.
+ * Also updates the TComponent's current slide number.
+ * @param inComponent TComponent to set slide on
+ * @param inSlideIndex relative index of the slide to switch to
+ * @param inSlideExit true if exiting the slide, false otherwise
+ */
+void CComponentManager::GotoSlideIndex(TElement *inComponent,
+ const SComponentGotoSlideData &inGotoData,
+ BOOL inSlideExit /*= true*/)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+
+ if (theComponent == NULL) {
+ return;
+ }
+
+ if (inGotoData.m_Slide < 1 || inGotoData.m_Slide >= theComponent->GetSlideCount()) {
+ qCCritical(qt3ds::INVALID_PARAMETER)
+ << "GotoSlide: Index out of range: Index " << inGotoData.m_Slide
+ << " SlideCount: "<< theComponent->GetSlideCount();
+ return;
+ }
+
+ if (theComponent->GetActive() == false) {
+ m_ComponentInitialSlideMap[inComponent] = inGotoData;
+ return;
+ }
+
+ SComponentGotoSlideData theGotoSlideData(inGotoData);
+
+ TComponentGotoSlideDataMap::iterator iter = m_ComponentInitialSlideMap.find(inComponent);
+ if (iter != m_ComponentInitialSlideMap.end()) {
+ theGotoSlideData = iter->second;
+ m_ComponentInitialSlideMap.erase(iter);
+ }
+
+ const UINT8 theCurrentSlideIndex = theComponent->GetCurrentSlide();
+
+ QString elementPath = QString::fromUtf8(inComponent->m_Path.c_str());
+
+ if (inSlideExit) {
+ SEventCommand theEvent = { inComponent, EVENT_ONSLIDEEXIT };
+ theEvent.m_IsEvent = true;
+ m_Presentation.ProcessEvent(theEvent);
+
+ // Signal previous slide change
+ m_Presentation.signalProxy()->SigSlideExited(elementPath, theCurrentSlideIndex,
+ GetCurrentSlideName(inComponent));
+
+ // m_Presentation.FireEvent(EVENT_ONSLIDEEXIT, inComponent);
+ // m_Presentation.FlushEventCommandQueue();
+ }
+
+ // Update dynamic keys to use current values before slide switching, with the exception of
+ // master slides because playback only starts from non-master slides.
+ if (theCurrentSlideIndex > 0) {
+ m_Presentation.GetSlideSystem().InitializeDynamicKeys(
+ SSlideKey(*theComponent, (qt3ds::QT3DSU8)theGotoSlideData.m_Slide),
+ m_Presentation.GetAnimationSystem());
+ // deactivate actions and animation tracks on the current slide.
+ m_Presentation.GetSlideSystem().RollbackSlide(
+ SSlideKey(*inComponent, (qt3ds::QT3DSU8)theCurrentSlideIndex),
+ m_Presentation.GetAnimationSystem(), m_Presentation.GetLogicSystem());
+ } else {
+ m_Presentation.GetSlideSystem().ExecuteSlide(SSlideKey(*inComponent, 0),
+ m_Presentation.GetAnimationSystem(),
+ m_Presentation.GetLogicSystem());
+ }
+ // Execute new slide.
+ m_Presentation.GetSlideSystem().ExecuteSlide(
+ SSlideKey(*inComponent, (qt3ds::QT3DSU8)theGotoSlideData.m_Slide),
+ m_Presentation.GetAnimationSystem(), m_Presentation.GetLogicSystem());
+ CTimePolicy &thePolicy(theComponent->GetTimePolicy());
+ TTimeUnit theLoopingDuration = thePolicy.GetLoopingDuration();
+ if (theGotoSlideData.m_Mode.hasValue()) {
+ inComponent->SetPlayThrough(false);
+ switch (*theGotoSlideData.m_Mode) {
+ case TimePolicyModes::Looping:
+ thePolicy.Initialize(theLoopingDuration, 0, false);
+ break;
+ case TimePolicyModes::PingPong:
+ thePolicy.Initialize(theLoopingDuration, 0, true);
+ break;
+ case TimePolicyModes::StopAtEnd:
+ thePolicy.Initialize(theLoopingDuration, 1, false);
+ break;
+ case TimePolicyModes::Ping:
+ thePolicy.Initialize(theLoopingDuration, 1, true);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ // Update the current index which also updates the back index
+ theComponent->SetCurrentSlide(static_cast<UINT8>(theGotoSlideData.m_Slide));
+ m_PlaythroughOverrideMap.erase(inComponent);
+ if (theGotoSlideData.m_PlaythroughTo.hasValue()) {
+ m_PlaythroughOverrideMap.insert(
+ eastl::make_pair(inComponent, *theGotoSlideData.m_PlaythroughTo));
+ theComponent->SetPlayThrough(true);
+ }
+
+ // Reset time for component to 0
+
+ if (theGotoSlideData.m_Paused.hasValue())
+ thePolicy.SetPaused(*theGotoSlideData.m_Paused);
+
+ thePolicy.SetRate(theGotoSlideData.m_Rate);
+ thePolicy.SetReverse(theGotoSlideData.m_Reverse);
+
+ if (theGotoSlideData.m_StartTime.hasValue())
+ thePolicy.SetTime(*theGotoSlideData.m_StartTime);
+
+ inComponent->SetDirty();
+ m_Presentation.FireEvent(EVENT_ONSLIDEENTER, inComponent);
+ uic::runtime::IActivityZone *theZone = m_Presentation.GetActivityZone();
+ if (theZone)
+ theZone->OnSlideChange(*inComponent);
+
+ // Signal current slide change
+ m_Presentation.signalProxy()->SigSlideEntered(elementPath, GetCurrentSlide(inComponent),
+ GetCurrentSlideName(inComponent));
+}
+
+//==============================================================================
+/**
+ * Sets a component to a specified slide using the slide name hash.
+ * Performs a switch to Slide 0 (master) first, before switching to the
+ * required slide.
+ * @param inComponent reference to the TComponent
+ * @param inSlideHashName hash of the slide to switch to
+ */
+void CComponentManager::GotoSlideName(TElement *inComponent, const TStringHash inSlideHashName)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+ UINT8 theSlideIndex = m_Presentation.GetSlideSystem().FindSlide(*theComponent, inSlideHashName);
+
+ if (theSlideIndex < 1 || theSlideIndex >= theComponent->GetSlideCount()) {
+ const char *slideName = m_Presentation.GetApplication().ReverseHash(inSlideHashName);
+ if (slideName && *slideName)
+ qCCritical(qt3ds::INVALID_PARAMETER) << "GotoSlide: Name not found: " << slideName;
+ else
+ qCCritical(qt3ds::INVALID_PARAMETER) << "GotoSlide: Name not found: " << inSlideHashName;
+
+ } else
+ GotoSlideIndex(inComponent, theSlideIndex);
+}
+
+//==============================================================================
+/**
+ * Return the index of the current slide of the component.
+ * @param inComponent reference to the TComponent
+ * @return the index of current slide
+ */
+UINT8 CComponentManager::GetCurrentSlide(TElement *inComponent)
+{
+ return GetComponent(inComponent)->GetCurrentSlide();
+}
+
+//==============================================================================
+/**
+ * Return the number of slides on a component.
+ * @param inComponent reference to the TComponent
+ * @return the number of slides
+ */
+UINT8 CComponentManager::GetSlideCount(TElement *inComponent)
+{
+ return GetComponent(inComponent)->GetSlideCount();
+}
+
+//==============================================================================
+/**
+ * Performs a switch to the slide following the current slide (current slide + 1).
+ * @param inComponent reference to the TComponent
+ * @param inIncrement slide increment offset
+ */
+void CComponentManager::GoToNextSlide(TElement *inComponent, const INT32 inIncrement)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+ INT32 theNewIndex = Q3DStudio_clamp<INT32>(inIncrement + theComponent->GetCurrentSlide(), 1L,
+ theComponent->GetSlideCount() - 1);
+
+ // Trigger goto to slide only if the next slide is not the current
+ if (theComponent->GetActive()) {
+ if (theNewIndex != theComponent->GetCurrentSlide())
+ GotoSlideIndex(inComponent, theNewIndex);
+ } else {
+ qCCritical(qt3ds::INVALID_PARAMETER)
+ << "Runtime: Attempt to goto slide on an inactive component!";
+ }
+}
+
+//==============================================================================
+/**
+ * Performs a switch to the slide following the current slide (current slide - 1).
+ * @param inComponent reference to the TComponent
+ * @param inDecrement slide decrement offset
+ */
+void CComponentManager::GoToPreviousSlide(TElement *inComponent, const INT32 inDecrement)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+ INT32 theNewIndex = Q3DStudio_clamp<INT32>(theComponent->GetCurrentSlide() - inDecrement, 1L,
+ theComponent->GetSlideCount() - 1);
+
+ // Trigger goto to slide only if the next slide is not the current
+ if (theNewIndex != theComponent->GetCurrentSlide())
+ GotoSlideIndex(inComponent, theNewIndex);
+}
+
+//==============================================================================
+/**
+ * Playthrough to the next slide that is specified.
+ * @param inComponent reference to the TComponent
+ */
+void CComponentManager::PlaythroughToSlide(TElement *inComponent)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+ TComponentIntMap::iterator iter = m_PlaythroughOverrideMap.find(inComponent);
+ INT32 thePlaythroughTo = 0;
+ if (iter != m_PlaythroughOverrideMap.end()) {
+ thePlaythroughTo = iter->second;
+ m_PlaythroughOverrideMap.erase(iter);
+ } else {
+ thePlaythroughTo = m_Presentation.GetSlideSystem().GetPlaythroughToSlideIndex(
+ SSlideKey(*theComponent, (qt3ds::QT3DSU8)theComponent->GetCurrentSlide()));
+ if (thePlaythroughTo == -1) {
+ qCCritical(qt3ds::INVALID_OPERATION) << "Missing slide to play through to";
+ inComponent->SetPlayThrough(
+ false); // clear this flag, so that this is equivalent to a "Stop At End"
+ }
+ }
+
+ if (thePlaythroughTo == -2) {
+ GoToPreviousSlide(inComponent, 1);
+ } else if (thePlaythroughTo == -1) {
+ GoToNextSlide(inComponent, 1);
+ } else {
+ GotoSlideIndex(inComponent, thePlaythroughTo);
+ }
+}
+
+//==============================================================================
+/**
+ * Performs a switch to the previous slide.
+ * @param inComponent reference to the TComponent
+ */
+void CComponentManager::GoToBackSlide(TElement *inComponent)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+ GotoSlideIndex(theComponent, theComponent->GetPreviousSlide());
+}
+
+//==============================================================================
+/**
+ * Set the component's local time using the supplied time.
+ * @param inComponent reference to the TComponent
+ * @param inTime supplied time
+ */
+void CComponentManager::GoToTime(TElement *inComponent, const TTimeUnit inTime)
+{
+ if (inComponent == NULL)
+ return;
+ if (inComponent->GetActive() == false) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Runtime: Attempt to goto time on inactive component!";
+ return;
+ }
+ m_Presentation.GetActivityZone()->GoToTime(*inComponent, inTime);
+ inComponent->SetDirty();
+}
+
+//==============================================================================
+/**
+ * Get the component's playback state
+ * @param inComponent reference to the TComponent
+ * @return true if it's paused, false if it's playing
+ */
+BOOL CComponentManager::GetPause(TElement *inComponent)
+{
+ CTimePolicy &theTimePolicy = GetComponent(inComponent)->GetTimePolicy();
+ return theTimePolicy.GetPaused();
+}
+
+//==============================================================================
+/**
+ * Get the component's ping pong direction
+ * @param inComponent reference to the TComponent
+ * @return true if it's pingponging forward, false if it's pingponging backwards
+ */
+BOOL CComponentManager::GetPlayBackDirection(TElement *inComponent)
+{
+ return GetComponent(inComponent)->GetPlayBackDirection();
+}
+
+//==============================================================================
+/**
+ * Update time policy of the component during each slide execution
+ * @param inComponent reference to the TComponent
+ * @param inLoopDuration loop duration of component at that slide
+ * @param inRepetitions number of repetitions
+ * @param inPingPong if true the component will move with respect to reverse time
+ *sequence
+ * @param inPlayThrough if true the component will continue to execute next slide
+ */
+void CComponentManager::SetTimePolicy(TElement *inComponent, const TTimeUnit inLoopDuration,
+ const UINT32 inRepetitions, const BOOL inPingPong,
+ const BOOL inPlayThrough)
+{
+ CTimePolicy &theTimePolicy = GetComponent(inComponent)->GetTimePolicy();
+ theTimePolicy.Initialize(inLoopDuration, inRepetitions, inPingPong);
+ inComponent->SetPlayThrough(inPlayThrough);
+}
+
+//==============================================================================
+/**
+ * Set the component's playback to either play or pause
+ * @param inComponent reference to the TComponent
+ * @param inPause true = pause, false = play
+ */
+void CComponentManager::SetPause(TElement *inComponent, const BOOL inPause)
+{
+ CTimePolicy &theTimePolicy = GetComponent(inComponent)->GetTimePolicy();
+ BOOL wasPaused = theTimePolicy.GetPaused();
+ theTimePolicy.SetPaused(inPause);
+ if (wasPaused != inPause)
+ inComponent->SetDirty();
+}
+
+//==============================================================================
+/**
+ * Promote from TElement* to TComponent.
+ * @param inElement TElement pointer to be recast as TComponent
+ * @return pointer to the component
+ */
+TComponent *CComponentManager::GetComponent(TElement *inElement)
+{
+ Q3DStudio_ASSERT(inElement->IsComponent());
+ return static_cast<TComponent *>(inElement);
+}
+
+//==============================================================================
+/**
+ * Gets the string name of the current slide.
+ * @param inComponent the component to query for it's current slide name
+ * @return the char buffer storing the name
+ */
+const CHAR *CComponentManager::GetCurrentSlideName(TElement *inComponent)
+{
+ TComponent *theComponent = GetComponent(inComponent);
+ return m_Presentation.GetSlideSystem().GetSlideName(
+ SSlideKey(*theComponent, (qt3ds::QT3DSU8)theComponent->GetCurrentSlide()));
+}
+
+void CComponentManager::OnElementDeactivated(TElement *)
+{
+}
+
+void CComponentManager::SetComponentTimeOverride(TElement *inElement, TTimeUnit inEndTime,
+ FLOAT inInterpolation,
+ IComponentTimeOverrideFinishedCallback *inCallback)
+{
+ if (inElement->IsComponent()) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "ComponentManager: SetComponentTimeOverride called on object that "
+ << "wasn't an element";
+ if (inCallback)
+ inCallback->Release();
+ Q3DStudio_ASSERT(false);
+ return;
+ }
+ // sanitize end time.
+ CTimePolicy &theTimePolicy = GetComponent(inElement)->GetTimePolicy();
+ if (inEndTime < 0)
+ inEndTime = 0;
+ if (inEndTime > theTimePolicy.GetLoopingDuration())
+ inEndTime = theTimePolicy.GetLoopingDuration();
+ m_Presentation.GetActivityZone()->GetOrCreateItemComponentOverride(*inElement, inInterpolation,
+ inEndTime, inCallback);
+
+ // Force the time policy object to respect its own time. If we played through till the end and
+ // sat there for a while
+ // we need the actual time will travel further and further from the time policy's local time.
+ // If we then play backward we
+ // will jump until the offset is synchronized with the actual time.
+ theTimePolicy.SetTime(theTimePolicy.GetTime());
+ inElement->SetDirty();
+}
+
+void CComponentManager::SetupComponentGotoSlideCommand(TElement *inElement,
+ const SComponentGotoSlideData &inSlide)
+{
+ m_ComponentGotoSlideMap[inElement] = inSlide;
+}
+
+bool CComponentManager::HasComponentGotoSlideCommand(TElement *inElement)
+{
+ return m_ComponentGotoSlideMap.find(inElement) != m_ComponentGotoSlideMap.end();
+}
+
+SComponentGotoSlideData CComponentManager::GetComponentGotoSlideCommand(TElement *inElement)
+{
+ TComponentGotoSlideDataMap::iterator iter = m_ComponentGotoSlideMap.find(inElement);
+ if (iter != m_ComponentGotoSlideMap.end())
+ return iter->second;
+ return -1;
+}
+
+void CComponentManager::ReleaseComponentGotoSlideCommand(TElement *inElement)
+{
+ TComponentGotoSlideDataMap::iterator iter = m_ComponentGotoSlideMap.find(inElement);
+ if (iter != m_ComponentGotoSlideMap.end())
+ m_ComponentGotoSlideMap.erase(iter);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICElementSystem.cpp b/src/Runtime/Source/Runtime/Source/UICElementSystem.cpp
new file mode 100644
index 00000000..b4bc5440
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICElementSystem.cpp
@@ -0,0 +1,997 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "RuntimePrefix.h"
+#include "UICElementSystem.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "EASTL/sort.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "UICHash.h"
+#include "UICActivationManager.h"
+#include "UICIPresentation.h"
+#include "UICPresentationFrameData.h"
+#include "UICAttributeHashes.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSIndexableLinkedList.h"
+#include "UICBinarySerializationHelper.h"
+
+using namespace uic::runtime::element;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using namespace qt3ds::intrinsics;
+namespace eastl {
+template <>
+struct hash<STypeDesc>
+{
+ size_t operator()(const STypeDesc &inDesc) const { return inDesc.HashCode(); }
+};
+}
+
+namespace {
+typedef IndexableLinkedList<SPropertyValueGroup, Q3DStudio::UVariant,
+ SPropertyValueGroup::NumValues>
+ TElementPropertyList;
+struct SPropertyDescSorter
+{
+ bool operator()(const TPropertyDescAndValue &lhs, const TPropertyDescAndValue &rhs) const
+ {
+ return strcmp(lhs.first.m_Name.c_str(), rhs.first.m_Name.c_str()) < 0;
+ }
+};
+QT3DSU32 GetNumValueAllocations(const STypeDesc &inTypeDesc)
+{
+ return ((inTypeDesc.m_Properties.size() + SPropertyValueGroup::NumValues - 1)
+ / SPropertyValueGroup::NumValues);
+}
+struct SElementAllocator : public uic::runtime::IElementAllocator
+{
+ typedef Pool<SElement, ForwardingAllocator> TElementPool;
+ typedef Pool<SComponent, ForwardingAllocator> TComponentPool;
+ typedef TElementPropertyList::TPoolType TValuePool;
+ typedef nvhash_map<QT3DSU32, SElement *> THandleElementMap;
+ typedef nvhash_map<SElement *, QT3DSU32> TElementOffsetMap;
+ typedef nvhash_set<STypeDesc> TTypeDescSet;
+ typedef nvhash_map<const STypeDesc *, QT3DSU32> TTypeDescOffsetMap;
+ typedef nvhash_map<QT3DSU32, const STypeDesc *> TOffsetTypeDescMap;
+ typedef nvvector<NVDataRef<QT3DSU8>> TLoadBufferList;
+
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ TElementPool m_Elements;
+ TComponentPool m_Components;
+ TValuePool m_Values;
+ THandleElementMap m_HandleToElements;
+ TElementOffsetMap m_ElementOffsets;
+ TTypeDescOffsetMap m_TypeDescOffsets;
+ TOffsetTypeDescMap m_OffsetsToTypeDescs;
+ TTypeDescSet m_TypeDescriptors;
+ nvvector<TPropertyDescAndValue> m_TempPropertyDescsAndValues;
+ nvvector<SPropertyDesc> m_TempPropertyDescs;
+ nvvector<CRegisteredString> m_IgnoredProperties;
+ // Upon load we allocate a set of buffers
+ nvvector<QT3DSU8> m_LoadBuffer;
+ TLoadBufferList m_AllocatedBuffers;
+ SSAutoDeallocatorAllocator m_AutoAllocator;
+ nvvector<SElement *> m_LoadElements;
+
+ QT3DSU32 m_NextElementHandle;
+
+ eastl::string m_Workspace;
+ eastl::string m_WorkspaceExt;
+
+ QT3DSI32 m_RefCount;
+
+ SElementAllocator(NVFoundationBase &inFoundation, IStringTable &inStrTable)
+ : m_Foundation(inFoundation)
+ , m_StringTable(inStrTable)
+ , m_Elements(ForwardingAllocator(m_Foundation.getAllocator(), "m_Elements"))
+ , m_Components(ForwardingAllocator(m_Foundation.getAllocator(), "m_Components"))
+ , m_Values(ForwardingAllocator(m_Foundation.getAllocator(), "m_Values"))
+ , m_HandleToElements(m_Foundation.getAllocator(), "m_HandleToElements")
+ , m_ElementOffsets(m_Foundation.getAllocator(), "m_ElementOffsets")
+ , m_TypeDescOffsets(m_Foundation.getAllocator(), "m_TypeDescOffsets")
+ , m_OffsetsToTypeDescs(m_Foundation.getAllocator(), "m_OffsetsToTypeDescs")
+ , m_TypeDescriptors(m_Foundation.getAllocator(), "m_TypeDescriptors")
+ , m_TempPropertyDescsAndValues(m_Foundation.getAllocator(), "m_TempPropertyDescsAndValues")
+ , m_TempPropertyDescs(m_Foundation.getAllocator(), "m_TempPropertyDescs")
+ , m_IgnoredProperties(m_Foundation.getAllocator(), "m_IgnoredProperties")
+ , m_LoadBuffer(m_Foundation.getAllocator(), "m_LoadBuffer")
+ , m_AllocatedBuffers(m_Foundation.getAllocator(), "m_AllocatedBuffers")
+ , m_AutoAllocator(inFoundation)
+ , m_LoadElements(inFoundation.getAllocator(), "m_LoadElements")
+ , m_NextElementHandle(1)
+ , m_RefCount(0)
+ {
+ }
+
+ ~SElementAllocator() {}
+
+ void GetIgnoredProperties()
+ {
+ if (m_IgnoredProperties.empty())
+ m_IgnoredProperties.push_back(m_StringTable.RegisterStr("name"));
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Foundation.getAllocator());
+ NVDelete(alloc, this);
+ }
+ }
+
+ SElement &CreateElement(CRegisteredString inName, CRegisteredString inType,
+ CRegisteredString inSubType,
+ NVConstDataRef<TPropertyDescAndValue> inPropertyDescriptions,
+ Q3DStudio::IPresentation *inPresentation, SElement *inParent,
+ bool inIsComponent) override
+ {
+ m_TempPropertyDescsAndValues.clear();
+ m_TempPropertyDescs.clear();
+ bool participatesInTimeGraph = false;
+ GetIgnoredProperties();
+ for (QT3DSU32 idx = 0, end = inPropertyDescriptions.size(); idx < end; ++idx) {
+ QT3DSU32 nameHash = inPropertyDescriptions[idx].first.GetNameHash();
+ if (nameHash == Q3DStudio::ATTRIBUTE_STARTTIME
+ || nameHash == Q3DStudio::ATTRIBUTE_ENDTIME)
+ participatesInTimeGraph = true;
+ if (eastl::find(m_IgnoredProperties.begin(), m_IgnoredProperties.end(),
+ inPropertyDescriptions[idx].first.m_Name)
+ == m_IgnoredProperties.end()) {
+ m_TempPropertyDescsAndValues.push_back(inPropertyDescriptions[idx]);
+ }
+ }
+ eastl::sort(m_TempPropertyDescsAndValues.begin(), m_TempPropertyDescsAndValues.end(),
+ SPropertyDescSorter());
+
+ for (QT3DSU32 idx = 0, end = m_TempPropertyDescsAndValues.size(); idx < end; ++idx) {
+ m_TempPropertyDescs.push_back(m_TempPropertyDescsAndValues[idx].first);
+ }
+
+ STypeDesc theDesc;
+ theDesc.m_TypeName = inType;
+ theDesc.m_SubtypeName = inSubType;
+ theDesc.m_Properties = m_TempPropertyDescs;
+ theDesc.SetHashValue();
+ eastl::pair<TTypeDescSet::iterator, bool> inserter = m_TypeDescriptors.insert(theDesc);
+
+ const STypeDesc &theTypeDesc = *inserter.first;
+ if (inserter.second) {
+ size_t allocSize = theDesc.m_Properties.size() * sizeof(SPropertyDesc);
+ if (allocSize) {
+ SPropertyDesc *newProps = (SPropertyDesc *)m_AutoAllocator.allocate(
+ allocSize, "TypeDescData", __FILE__, __LINE__, 0);
+ memCopy(newProps, theDesc.m_Properties.begin(), (QT3DSU32)allocSize);
+ // Note that this does not change the hash value.
+ const_cast<STypeDesc &>(theTypeDesc).m_Properties =
+ toConstDataRef(newProps, theDesc.m_Properties.size());
+ }
+ }
+
+ SElement *retval = inIsComponent ? m_Components.construct(theTypeDesc, __FILE__, __LINE__)
+ : m_Elements.construct(theTypeDesc, __FILE__, __LINE__);
+ retval->m_BelongedPresentation = inPresentation;
+ retval->m_Name = inName;
+ // children
+ if (inParent) {
+ retval->m_Parent = inParent;
+ if (inParent->m_Child == NULL) {
+ inParent->m_Child = retval;
+ } else {
+ SElement *lastChild = inParent->m_Child;
+ while (lastChild->m_Sibling)
+ lastChild = lastChild->m_Sibling;
+ lastChild->m_Sibling = retval;
+ }
+ }
+ while (FindElementByHandle(m_NextElementHandle)) {
+ ++m_NextElementHandle;
+ if (!m_NextElementHandle)
+ ++m_NextElementHandle;
+ }
+
+ // required flags
+ retval->m_Handle = m_NextElementHandle;
+ if (inIsComponent)
+ retval->Flags().clearOrSet(true, Q3DStudio::ELEMENTFLAG_COMPONENT);
+
+ if (participatesInTimeGraph)
+ retval->Flags().clearOrSet(true, Q3DStudio::ELEMENTFLAG_TIMELINE);
+
+ retval->Flags().clearOrSet(true, Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE);
+
+ retval->SetDepth();
+
+ retval->SetDirty();
+
+ m_HandleToElements.insert(eastl::make_pair(retval->m_Handle, retval));
+
+ // property values;
+ QT3DSU32 propIdx = 0;
+ TElementPropertyList::CreateAll(retval->m_PropertyValues, theTypeDesc.m_Properties.size(),
+ m_Values);
+ for (TElementPropertyList::iterator
+ iter = TElementPropertyList::begin(retval->m_PropertyValues,
+ theTypeDesc.m_Properties.size()),
+ end = TElementPropertyList::end(retval->m_PropertyValues,
+ theTypeDesc.m_Properties.size());
+ iter != end; ++iter, ++propIdx) {
+ (*iter) = m_TempPropertyDescsAndValues[propIdx].second;
+ }
+
+ return *retval;
+ }
+
+ void ReleaseElement(SElement &inElement, bool inRecurse) override
+ {
+ if (inRecurse) {
+ while (inElement.m_Child)
+ ReleaseElement(*inElement.m_Child, true);
+ }
+ // Trim out the element.
+ if (inElement.m_Parent) {
+ SElement *theParent = inElement.m_Parent;
+ if (theParent->m_Child == &inElement)
+ theParent->m_Child = inElement.m_Sibling;
+ else {
+ SElement *thePreviousChild = NULL;
+ // Empty loop to find the previous child
+ for (thePreviousChild = theParent->m_Child;
+ thePreviousChild->m_Sibling != &inElement && thePreviousChild;
+ thePreviousChild = thePreviousChild->m_Sibling) {
+ }
+ if (thePreviousChild)
+ thePreviousChild->m_Sibling = inElement.m_Sibling;
+ }
+ }
+
+ m_HandleToElements.erase(inElement.m_Handle);
+
+ QT3DSU8 *elemAddr = reinterpret_cast<QT3DSU8 *>(&inElement);
+ for (QT3DSU32 idx = 0, end = m_AllocatedBuffers.size(); idx < end; ++idx) {
+ NVDataRef<QT3DSU8> theBuffer(m_AllocatedBuffers[idx]);
+ // Preloaded element, do not release back to element pools
+ if (elemAddr >= theBuffer.begin() && elemAddr < theBuffer.end())
+ return;
+ }
+
+ SPropertyValueGroup *theValueGroup = inElement.m_PropertyValues;
+ while (theValueGroup) {
+ SPropertyValueGroup *currentGroup = theValueGroup;
+ theValueGroup = theValueGroup->m_NextNode;
+ m_Values.deallocate(currentGroup);
+ }
+
+ if (inElement.IsComponent())
+ m_Components.deallocate(&inElement);
+ else
+ m_Elements.deallocate(&inElement);
+ }
+
+ QT3DSI32 GetExtensionIndex(eastl::string &inExt)
+ {
+ QT3DSI32 retVal = 0;
+
+ if (!inExt.compare(".x") || !inExt.compare(".r"))
+ retVal = 0;
+ else if (!inExt.compare(".y") || !inExt.compare(".g"))
+ retVal = 1;
+ if (!inExt.compare(".z") || !inExt.compare(".b"))
+ retVal = 2;
+
+ return retVal;
+ }
+
+ virtual Option<TPropertyDescAndValuePtr>
+ CreateDynamicProperty(Q3DStudio::IRuntimeMetaData &theMetaData, SElement &element,
+ CRegisteredString inName) override
+ {
+ SPropertyDesc *newProp = NULL;
+ m_TempPropertyDescsAndValues.clear();
+ m_TempPropertyDescs.clear();
+
+ // create dynamic descriptor
+ if (!element.m_DynamicTypeDescription) {
+ STypeDesc *theDesc;
+ theDesc = (STypeDesc *)m_AutoAllocator.allocate(sizeof(STypeDesc), "TypeDescData",
+ __FILE__, __LINE__, 0);
+ theDesc->m_TypeName = element.m_TypeDescription->m_TypeName;
+ theDesc->m_SubtypeName = element.m_TypeDescription->m_SubtypeName;
+ theDesc->m_Properties = m_TempPropertyDescs;
+ theDesc->SetHashValue();
+ // we need this palcement new here
+ ::new (theDesc) STypeDesc();
+ element.m_DynamicTypeDescription = const_cast<STypeDesc *>(theDesc);
+ }
+
+ STypeDesc *theTypeDesc = element.m_DynamicTypeDescription;
+
+ // remove the extension that we can find the property
+ QT3DSI32 extIndex = 0;
+ m_Workspace.assign(inName.c_str());
+ eastl::string::size_type theCharPos = m_Workspace.rfind('.');
+ if (theCharPos != eastl::string::npos) {
+ m_WorkspaceExt.assign(m_Workspace, theCharPos, m_Workspace.length());
+ m_Workspace.resize(theCharPos);
+ extIndex = GetExtensionIndex(m_WorkspaceExt);
+ }
+
+ CRegisteredString theWorkSpaceString = m_StringTable.RegisterStr(m_Workspace.c_str());
+ Q3DStudio::ERuntimeDataModelDataType thePropertyType =
+ theMetaData.GetPropertyType(element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+
+ // using separate properties
+ bool separateProperties = theCharPos != eastl::string::npos;
+
+ // single property
+ size_t allocSize = sizeof(SPropertyDesc);
+ if (allocSize) {
+ newProp = (SPropertyDesc *)m_AutoAllocator.allocate(allocSize, "SPropertyDesc",
+ __FILE__, __LINE__, 0);
+
+ newProp->m_Name = inName;
+
+ // convert to appropriate type
+ if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeFloat) {
+ float value = theMetaData.GetPropertyValueFloat(
+ element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+
+ Q3DStudio::UVariant theValue;
+ theValue.m_FLOAT = value;
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_FLOAT), theValue));
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ } else if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeFloat2) {
+ qt3ds::QT3DSVec3 value = theMetaData.GetPropertyValueVector2(
+ element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+
+ Q3DStudio::UVariant theVarValue;
+ theVarValue.m_FLOAT = value[extIndex];
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_FLOAT),
+ theVarValue));
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ } else if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeFloat3) {
+ qt3ds::QT3DSVec3 value = theMetaData.GetPropertyValueVector3(
+ element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+
+ if (separateProperties) {
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+
+ Q3DStudio::UVariant theVarValue;
+ theVarValue.m_FLOAT = value[extIndex];
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_FLOAT),
+ theVarValue));
+ } else {
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT3;
+
+ Q3DStudio::UVariant theVarValue;
+ theVarValue.m_FLOAT3[0] = value[0];
+ theVarValue.m_FLOAT3[1] = value[1];
+ theVarValue.m_FLOAT3[2] = value[2];
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_FLOAT3),
+ theVarValue));
+ }
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ } else if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeLong) {
+ QT3DSI32 value = (QT3DSI32)theMetaData.GetPropertyValueLong(
+ element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_INT32;
+
+ Q3DStudio::UVariant theVarValue;
+ theVarValue.m_INT32 = value;
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_INT32),
+ theVarValue));
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ } else if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeBool) {
+ bool value = theMetaData.GetPropertyValueBool(
+ element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_BOOL;
+
+ Q3DStudio::UVariant theVarValue;
+ theVarValue.m_INT32 = value;
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_BOOL), theVarValue));
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ } else if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeString) {
+ Option<eastl::string> theRuntimeStr = theMetaData.GetPropertyValueString(
+ element.m_TypeDescription->m_TypeName, theWorkSpaceString,
+ element.m_TypeDescription->m_SubtypeName);
+
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_STRING;
+
+ CStringHandle theString = m_StringTable.GetHandle(theRuntimeStr->c_str());
+ Q3DStudio::UVariant theVarValue;
+ theVarValue.m_StringHandle = theString.handle();
+ m_TempPropertyDescsAndValues.push_back(eastl::make_pair(
+ SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_STRING),
+ theVarValue));
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ } else {
+ newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+
+ theTypeDesc->m_DynamicProperties.push_back(*newProp);
+ }
+ }
+
+ // property values;
+ QT3DSU32 newListSize = theTypeDesc->m_DynamicProperties.size() - 1;
+ TElementPropertyList::Create(element.m_DynamicPropertyValues, newListSize, m_Values);
+
+ Q3DStudio::UVariant &propertyValue =
+ TElementPropertyList::GetObjAtIdx(element.m_DynamicPropertyValues, newListSize - 1);
+ propertyValue = m_TempPropertyDescsAndValues[0].second;
+
+ return eastl::make_pair(
+ element.m_DynamicTypeDescription->m_DynamicProperties[newListSize - 1],
+ &TElementPropertyList::GetObjAtIdx(element.m_DynamicPropertyValues, newListSize - 1));
+ }
+
+ SElement *FindElementByHandle(QT3DSU32 inElementHandle) override
+ {
+ THandleElementMap::iterator theFind = m_HandleToElements.find(inElementHandle);
+ if (theFind != m_HandleToElements.end())
+ return theFind->second;
+ return NULL;
+ }
+
+ void SaveDFS(SWriteBuffer &inBuffer, SElement &inElement, nvvector<QT3DSU32> &ioElementOffsets)
+ {
+ ioElementOffsets.push_back(inBuffer.size());
+ m_ElementOffsets.insert(eastl::make_pair(&inElement, inBuffer.size()));
+ if (inElement.IsComponent()) {
+ SComponent &theComponent = static_cast<SComponent &>(inElement);
+ inBuffer.write(theComponent);
+ } else
+ inBuffer.write(inElement);
+ uic::runtime::SaveIndexableList<TElementPropertyList>(
+ inElement.UnsafeGetFirstPropertyGroup(), inBuffer);
+ if (inElement.m_Child)
+ SaveDFS(inBuffer, *inElement.m_Child, ioElementOffsets);
+ if (inElement.m_Sibling)
+ SaveDFS(inBuffer, *inElement.m_Sibling, ioElementOffsets);
+ }
+
+ void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream, NVDataRef<SElement *> inRoots) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriter(m_Foundation.getAllocator(), "WriteBuffer");
+ theWriter.write(m_NextElementHandle);
+ theWriter.write((QT3DSU32)m_TypeDescriptors.size());
+ theWriter.write((QT3DSU32)inRoots.size());
+ // Write out the number of elements in each tree.
+ size_t countOffset = theWriter.size();
+ for (QT3DSU32 idx = 0, end = inRoots.size(); idx < end; ++idx)
+ theWriter.write((QT3DSU32)0);
+ for (TTypeDescSet::const_iterator iter = m_TypeDescriptors.begin(),
+ end = m_TypeDescriptors.end();
+ iter != end; ++iter) {
+ const STypeDesc *theDesc = &(*iter);
+ m_TypeDescOffsets.insert(eastl::make_pair(theDesc, (QT3DSU32)theWriter.size()));
+ STypeDesc theDescriptor = *iter;
+ theDescriptor.m_TypeName.Remap(m_StringTable);
+ theDescriptor.m_SubtypeName.Remap(m_StringTable);
+ theWriter.write(theDescriptor);
+ for (QT3DSU32 propIdx = 0, propEnd = theDescriptor.m_Properties.size(); propIdx < propEnd;
+ ++propIdx) {
+ SPropertyDesc theProp = theDescriptor.m_Properties[propIdx];
+ theProp.m_Name.Remap(m_StringTable);
+ theWriter.write(theProp);
+ }
+ }
+ nvvector<QT3DSU32> theElementOffsets(m_Foundation.getAllocator(), "SaveData");
+ for (QT3DSU32 idx = 0, end = inRoots.size(); idx < end; ++idx) {
+ theElementOffsets.clear();
+ QT3DSU32 numElements = 0;
+ if (inRoots[idx]) {
+ SaveDFS(theWriter, *inRoots[idx], theElementOffsets);
+
+ numElements = (QT3DSU32)theElementOffsets.size();
+
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)theElementOffsets.size(); idx < end; ++idx) {
+ QT3DSU8 *theElemAddr = theWriter.begin() + theElementOffsets[idx];
+ SElement *theElementPtr = reinterpret_cast<SElement *>(theElemAddr);
+ theElementPtr->m_Name.Remap(m_StringTable);
+ theElementPtr->m_Path.Remap(m_StringTable);
+ theElementPtr->SetTypeDescription(
+ GetRemappedTypeDescAddress(&theElementPtr->GetTypeDescription()));
+ theElementPtr->m_Child = GetRemappedElementAddress(theElementPtr->m_Child);
+ theElementPtr->m_Sibling = GetRemappedElementAddress(theElementPtr->m_Sibling);
+ theElementPtr->m_Parent = GetRemappedElementAddress(theElementPtr->m_Parent);
+ theElementPtr->Flags().SetDirty(false);
+ theElementPtr->m_Association = NULL;
+ }
+ }
+ QT3DSU32 *theCountPtr = reinterpret_cast<QT3DSU32 *>(theWriter.begin() + countOffset);
+ theCountPtr[idx] = numElements;
+ }
+ ioStream.Write(theWriter.begin(), theWriter.size());
+ }
+
+ // Returns an element pointer that when added to the return value of load will be a valid
+ // element.
+ SElement *GetRemappedElementAddress(SElement *inElement) const override
+ {
+ if (inElement == NULL)
+ return NULL;
+ TElementOffsetMap::const_iterator iter = m_ElementOffsets.find(inElement);
+ if (iter != m_ElementOffsets.end())
+ return reinterpret_cast<SElement *>(iter->second);
+ return NULL;
+ }
+
+ const STypeDesc *GetRemappedTypeDescAddress(const STypeDesc *inTypeDesc) const override
+ {
+ TTypeDescOffsetMap::const_iterator iter = m_TypeDescOffsets.find((STypeDesc *)inTypeDesc);
+ if (iter != m_TypeDescOffsets.end())
+ return reinterpret_cast<STypeDesc *>(iter->second);
+ return NULL;
+ }
+ const STypeDesc *RemapTypeDesc(const STypeDesc *inOffset)
+ {
+ size_t memoryOffset = reinterpret_cast<size_t>(inOffset);
+ TOffsetTypeDescMap::iterator iter =
+ m_OffsetsToTypeDescs.find(static_cast<QT3DSU32>(memoryOffset));
+ if (iter != m_OffsetsToTypeDescs.end())
+ return iter->second;
+ return NULL;
+ }
+
+ SElement *RemapElement(SElement *inElem, size_t memoryOffset)
+ {
+ if (inElem)
+ return reinterpret_cast<SElement *>(reinterpret_cast<size_t>(inElem) + memoryOffset);
+ return NULL;
+ }
+
+ virtual Option<eastl::pair<NVDataRef<SElement *>, size_t>>
+ LoadBinaryData(NVDataRef<QT3DSU8> inLoadData, NVDataRef<QT3DSU8> inStringTableData) override
+ {
+ // m_LoadBuffer.assign( inLoadData.begin(), inLoadData.end() );
+ // inLoadData = m_LoadBuffer;
+ size_t retval = reinterpret_cast<size_t>(inLoadData.begin());
+ m_AllocatedBuffers.push_back(inLoadData);
+ SDataReader theReader(inLoadData.begin(), inLoadData.end());
+ m_NextElementHandle = *theReader.Load<QT3DSU32>();
+ QT3DSU32 numDescriptors = *theReader.Load<QT3DSU32>();
+ QT3DSU32 numRoots = *theReader.Load<QT3DSU32>();
+ QT3DSU32 *theElemCounts = reinterpret_cast<QT3DSU32 *>(theReader.m_CurrentPtr);
+ theReader.m_CurrentPtr += sizeof(QT3DSU32) * numRoots;
+ for (QT3DSU32 idx = 0, end = numDescriptors; idx < end; ++idx) {
+ QT3DSU32 theOffset = (QT3DSU32)(theReader.m_CurrentPtr - inLoadData.begin());
+ STypeDesc theDesc(*theReader.Load<STypeDesc>());
+ theDesc.m_SubtypeName.Remap(inStringTableData);
+ theDesc.m_TypeName.Remap(inStringTableData);
+ QT3DSU32 numProps = theDesc.m_Properties.mSize;
+ theDesc.m_Properties.mData = reinterpret_cast<SPropertyDesc *>(theReader.m_CurrentPtr);
+ theReader.m_CurrentPtr += numProps * sizeof(SPropertyDesc);
+ for (QT3DSU32 propIdx = 0, propEnd = theDesc.m_Properties.size(); propIdx < propEnd;
+ ++propIdx) {
+ SPropertyDesc &thePropDesc =
+ const_cast<SPropertyDesc &>(theDesc.m_Properties[propIdx]);
+ thePropDesc.m_Name.Remap(inStringTableData);
+ }
+ theDesc.SetHashValue();
+ const STypeDesc *theNewDesc = &(*m_TypeDescriptors.insert(theDesc).first);
+ m_OffsetsToTypeDescs.insert(eastl::make_pair(theOffset, theNewDesc));
+ }
+ for (QT3DSU32 idx = 0, end = numRoots; idx < end; ++idx) {
+ QT3DSU32 theElemCount = theElemCounts[idx];
+ if (theElemCount) {
+ for (QT3DSU32 elemIdx = 0, elemEnd = theElemCount;
+ elemIdx < elemEnd && theReader.m_CurrentPtr < theReader.m_EndPtr; ++elemIdx) {
+ SElement *theElement = reinterpret_cast<SElement *>(theReader.m_CurrentPtr);
+ if (theElement->IsComponent())
+ theReader.m_CurrentPtr += sizeof(SComponent);
+ else
+ theReader.m_CurrentPtr += sizeof(SElement);
+
+ if (!elemIdx)
+ m_LoadElements.push_back(theElement);
+
+ if (theReader.m_CurrentPtr <= theReader.m_EndPtr) {
+ theElement->SetTypeDescription(
+ RemapTypeDesc(&theElement->GetTypeDescription()));
+ theElement->m_Name.Remap(inStringTableData);
+ theElement->m_Path.Remap(inStringTableData);
+ theElement->m_Parent = RemapElement(theElement->m_Parent, retval);
+ theElement->m_Child = RemapElement(theElement->m_Child, retval);
+ theElement->m_Sibling = RemapElement(theElement->m_Sibling, retval);
+ const STypeDesc &theTypeDescription = theElement->GetTypeDescription();
+ uic::runtime::LoadIndexableList<TElementPropertyList>(
+ theElement->UnsafeGetFirstPropertyGroup(),
+ theTypeDescription.m_Properties.size(), theReader);
+ }
+ // This may be the slowest part of loading and may need to be refactored into a
+ // binary search
+ // instead of a hashtable.
+ m_HandleToElements.insert(eastl::make_pair(theElement->m_Handle, theElement));
+ }
+ } else
+ m_LoadElements.push_back(NULL);
+ }
+ return eastl::make_pair(NVDataRef<SElement *>(m_LoadElements), retval);
+ }
+};
+}
+
+bool STypeDesc::operator==(const STypeDesc &inOther) const
+{
+ if (m_TypeName == inOther.m_TypeName && m_SubtypeName == inOther.m_SubtypeName
+ && m_Properties.size() == inOther.m_Properties.size()) {
+ for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
+ const SPropertyDesc &lhs = m_Properties[idx];
+ const SPropertyDesc &rhs = inOther.m_Properties[idx];
+ if (lhs.m_Name != rhs.m_Name || lhs.m_Type != rhs.m_Type)
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+Option<QT3DSU32> STypeDesc::FindProperty(QT3DSU32 inNameHash) const
+{
+ for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
+ const SPropertyDesc &theDesc = m_Properties[idx];
+ if (Q3DStudio::CHash::HashAttribute(theDesc.m_Name) == inNameHash)
+ return idx;
+ }
+ return Empty();
+}
+
+Option<QT3DSU32> STypeDesc::FindProperty(CRegisteredString inName) const
+{
+ for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
+ const SPropertyDesc &theDesc = m_Properties[idx];
+ if (theDesc.m_Name == inName)
+ return idx;
+ }
+ return Empty();
+}
+
+Option<QT3DSU32> STypeDesc::FindDynamicProperty(QT3DSU32 inNameHash) const
+{
+ for (QT3DSU32 idx = 0, end = m_DynamicProperties.size(); idx < end; ++idx) {
+ const SPropertyDesc &theDesc = m_DynamicProperties[idx];
+ if (Q3DStudio::CHash::HashAttribute(theDesc.m_Name) == inNameHash)
+ return idx;
+ }
+ return Empty();
+}
+
+void STypeDesc::SetHashValue()
+{
+ size_t typeDescHash = m_TypeName.hash() ^ m_SubtypeName.hash();
+ for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
+ typeDescHash = typeDescHash ^ m_Properties[idx].m_Name.hash();
+ typeDescHash = typeDescHash ^ eastl::hash<QT3DSU32>()(m_Properties[idx].m_Type);
+ }
+ // TODO check 64 bit compatibility
+ m_HashValue = (QT3DSU32)typeDescHash;
+}
+
+QT3DSU32 SPropertyDesc::GetNameHash() const
+{
+ return Q3DStudio::CHash::HashAttribute(m_Name.c_str());
+}
+
+Q3DStudio::SAttributeKey SPropertyDesc::GetAttributeKey() const
+{
+ Q3DStudio::SAttributeKey retval;
+ memZero(&retval, sizeof(retval));
+ retval.m_Type = m_Type;
+ retval.m_Hash = GetNameHash();
+ return retval;
+}
+
+bool SElement::IsUserActive() const
+{
+ return m_Flags.IsExplicitActive();
+}
+
+bool SElement::IsIndependent() const
+{
+ return IsComponent();
+}
+
+bool SElement::IsGlobalActive() const
+{
+ return GetActive();
+}
+// This may require a mutex to be held.
+void SElement::SetGlobalActive(bool active)
+{
+ SetActive(active);
+}
+
+bool SElement::GetAttribute(QT3DSU32 inHashName, Q3DStudio::UVariant &outValue) const
+{
+ if (inHashName == Q3DStudio::ATTRIBUTE_NAME) {
+ outValue.m_StringHandle = m_BelongedPresentation->GetStringTable().GetHandle(m_Name);
+ return true;
+ }
+ if (inHashName == Q3DStudio::CHash::HashAttribute("path")) {
+ outValue.m_StringHandle = m_BelongedPresentation->GetStringTable().GetHandle(m_Path);
+ return true;
+ }
+ const Q3DStudio::UVariant *valPtr = FindPropertyValue(inHashName);
+ if (valPtr) {
+ outValue = *valPtr;
+ return true;
+ }
+ return false;
+}
+
+void SElement::SetAttribute(const Q3DStudio::TAttributeHash inKey,
+ const Q3DStudio::UVariant inValue)
+{
+ Option<TPropertyDescAndValuePtr> existing = FindProperty(inKey);
+ if (existing.hasValue() == false)
+ return;
+ SetAttribute(*existing, inValue);
+}
+
+void SElement::SetAttribute(TPropertyDescAndValuePtr inKey, const Q3DStudio::UVariant inValue)
+{
+ Q3DStudio::EAttributeType theType = inKey.first.m_Type;
+ Q3DStudio::UVariant *currentValue = inKey.second;
+ QT3DSU32 attHash = inKey.first.GetNameHash();
+ switch (theType) {
+ case Q3DStudio::ATTRIBUTETYPE_FLOAT: // Early return
+ if (fabs(currentValue->m_FLOAT - inValue.m_FLOAT) < SmallestDifference())
+ return;
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_FLOAT3: // Early return
+ if (fabs(currentValue->m_FLOAT3[0] - inValue.m_FLOAT3[0]) < SmallestDifference()
+ && fabs(currentValue->m_FLOAT3[1] - inValue.m_FLOAT3[1]) < SmallestDifference()
+ && fabs(currentValue->m_FLOAT3[2] - inValue.m_FLOAT3[2]) < SmallestDifference()) {
+ return;
+ }
+ break;
+ case Q3DStudio::ATTRIBUTETYPE_STRING:
+ if (currentValue->m_StringHandle == inValue.m_StringHandle)
+ return;
+ break;
+ default: // Early return
+ if (currentValue->m_INT32 == inValue.m_INT32)
+ return;
+ break;
+ }
+ *currentValue = inValue;
+
+ if (Q3DStudio::ATTRIBUTE_EYEBALL == attHash)
+ SetFlag(Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE, inValue.m_INT32 ? true : false);
+
+ if (Q3DStudio::ATTRIBUTE_STARTTIME == attHash || Q3DStudio::ATTRIBUTE_ENDTIME == attHash)
+ GetActivityZone().UpdateItemInfo(*this);
+
+ /*
+ if ( inElement->m_Flags & ELEMENTFLAG_REGISTEREDFORATTRIBUTECHANGE )
+ m_AttributeChangeCallbacks.FireCallbacks( inElement, theAttribute->m_Key,
+ thePreviousValue, inValue );
+ */
+ SetDirty();
+}
+
+// SElement implementation
+QT3DSU32 SElement::GetNameHash() const
+{
+ return Q3DStudio::CHash::HashString(m_Name.c_str());
+}
+
+// Q3DStudio::CHash::HashAttribute
+Option<QT3DSU32> SElement::FindPropertyIndex(QT3DSU32 inNameHash) const
+{
+ return m_TypeDescription->FindProperty(inNameHash);
+}
+
+Option<QT3DSU32> SElement::FindPropertyIndex(CRegisteredString inName) const
+{
+ return m_TypeDescription->FindProperty(inName);
+}
+
+Option<QT3DSU32> SElement::FindDynamicPropertyIndex(QT3DSU32 inNameHash) const
+{
+ if (m_DynamicTypeDescription)
+ return m_DynamicTypeDescription->FindDynamicProperty(inNameHash);
+ else
+ return Empty();
+}
+
+QT3DSU32 SElement::GetNumProperties() const
+{
+ return m_TypeDescription->m_Properties.size();
+}
+
+QT3DSU32 SElement::GetNumDynamicProperties() const
+{
+ if (m_DynamicTypeDescription)
+ return m_DynamicTypeDescription->m_DynamicProperties.size();
+ else
+ return 0;
+}
+
+Option<TPropertyDescAndValuePtr> SElement::GetPropertyByIndex(QT3DSU32 inIdx)
+{
+ if (inIdx < this->m_TypeDescription->m_Properties.size())
+ return eastl::make_pair(m_TypeDescription->m_Properties[inIdx],
+ &TElementPropertyList::GetObjAtIdx(m_PropertyValues, inIdx));
+
+ return Empty();
+}
+
+Option<TPropertyDescAndValuePtr> SElement::GetDynamicPropertyByIndex(QT3DSU32 inIdx)
+{
+ if (inIdx < this->m_DynamicTypeDescription->m_DynamicProperties.size())
+ return eastl::make_pair(m_DynamicTypeDescription->m_DynamicProperties[inIdx],
+ &TElementPropertyList::GetObjAtIdx(m_DynamicPropertyValues, inIdx));
+
+ return Empty();
+}
+
+Option<TPropertyDescAndConstValuePtr> SElement::GetPropertyByIndex(QT3DSU32 inIdx) const
+{
+ Option<TPropertyDescAndValuePtr> retval =
+ const_cast<SElement &>(*this).GetPropertyByIndex(inIdx);
+ if (retval.hasValue())
+ return TPropertyDescAndConstValuePtr(*retval);
+ return Empty();
+}
+
+void SElement::SetDirty()
+{
+ if (!m_Flags.IsDirty()) {
+ m_Flags.SetDirty(true);
+ // The element is dirty, so place it on the frame data dirty list
+ m_BelongedPresentation->GetFrameData().GetDirtyList().Push(this);
+ m_Flags.SetDirty(true);
+ }
+}
+
+void SElement::SetFlag(Q3DStudio::EElementFlag inFlag, bool inValue)
+{
+ bool existing = m_Flags & inFlag;
+ if (existing != inValue && HasActivityZone()) {
+ m_Flags.clearOrSet(inValue, inFlag);
+ if (inFlag == Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE)
+ GetActivityZone().UpdateItemInfo(*this);
+ else if (inFlag == Q3DStudio::ELEMENTFLAG_SCRIPTCALLBACKS)
+ GetActivityZone().UpdateItemScriptStatus(*this);
+ SetDirty();
+ }
+}
+
+bool SElement::HasActivityZone() const
+{
+ return m_BelongedPresentation->GetActivityZone() != NULL;
+}
+
+uic::runtime::IActivityZone &SElement::GetActivityZone() const
+{
+ return *m_BelongedPresentation->GetActivityZone();
+}
+
+SElement &SElement::GetComponentParent()
+{
+ if (IsComponent())
+ return *this;
+
+ SElement *theParent = GetActivityZone().GetItemTimeParent(*this);
+ if (theParent)
+ return *theParent;
+ QT3DS_ASSERT(false);
+ return *this;
+}
+
+const SElement &SElement::GetComponentParent() const
+{
+ return const_cast<SElement *>(this)->GetComponentParent();
+}
+
+SElement *SElement::FindChild(QT3DSU32 inNameHash)
+{
+ for (SElement *theChild = m_Child; theChild; theChild = theChild->m_Sibling) {
+ if (theChild->GetNameHash() == inNameHash)
+ return theChild;
+ }
+ return NULL;
+}
+
+Q3DStudio::TTimeUnit SElement::GetInnerTime() const
+{
+ return GetActivityZone().GetItemComponentTime(const_cast<SElement &>(*this));
+}
+// Get the time I am animating at.
+Q3DStudio::TTimeUnit SElement::GetOuterTime() const
+{
+ return GetActivityZone().GetItemLocalTime(const_cast<SElement &>(*this));
+}
+
+bool SElement::IsDescendent(SElement &inPossibleParent) const
+{
+ if (m_Parent == NULL)
+ return false;
+ if (m_Parent == &inPossibleParent)
+ return true;
+ return m_Parent->IsDescendent(inPossibleParent);
+}
+
+bool SComponent::GetPaused() const
+{
+ return GetTimePolicy().GetPaused();
+}
+
+bool SComponent::GetPlayBackDirection() const
+{
+ return GetTimePolicy().GetPlayBackDirection();
+}
+
+Q3DStudio::CTimePolicy &SComponent::GetTimePolicy()
+{
+ return *GetActivityZone().GetOwnedTimePolicy(*this);
+}
+
+const Q3DStudio::CTimePolicy &SComponent::GetTimePolicy() const
+{
+ return const_cast<SComponent *>(this)->GetTimePolicy();
+}
+
+uic::runtime::IElementAllocator &
+uic::runtime::IElementAllocator::CreateElementAllocator(NVFoundationBase &inFoundation,
+ IStringTable &inStringTable)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SElementAllocator)(inFoundation, inStringTable);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICEventCallbacks.cpp b/src/Runtime/Source/Runtime/Source/UICEventCallbacks.cpp
new file mode 100644
index 00000000..2f97bf91
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICEventCallbacks.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICEventCallbacks.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CEventCallbacks::CEventCallbacks()
+ : m_EventCallbacksList(0, 0, "EventCallbacksList")
+ , m_CallbackList(0, 0, "CallbackList")
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CEventCallbacks::~CEventCallbacks()
+{
+ UnregisterAllCallbacks();
+}
+
+//==============================================================================
+/**
+ * Registers a callback to be triggered when a specific event is fired on an
+ * element.
+ * @param inElement element to monitor
+ * @param inEventHash event hash to monitor
+ * @param inCallback static callback function
+ * @param inContextData arbitary data pointer
+ */
+void CEventCallbacks::RegisterCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData)
+{
+ TEventCallbacksList *theEventCallbackList = NULL;
+
+ // Look for the list of callbacks for this element
+ FOR_ARRAY(SElementCallbackEntry *, theEntry, m_EventCallbacksList)
+ {
+ if (inElement == (*theEntry)->m_Element) {
+ theEventCallbackList = &(*theEntry)->m_EventEntries;
+ break;
+ }
+ }
+
+ // Create a new list of callbacks if it does not already exist
+ if (!theEventCallbackList) {
+ SElementCallbackEntry *theElementCallbackEntry =
+ Q3DStudio_new(SElementCallbackEntry) SElementCallbackEntry();
+ theElementCallbackEntry->m_Element = inElement;
+ m_EventCallbacksList.Push(theElementCallbackEntry);
+ theEventCallbackList = &m_EventCallbacksList.Top()->m_EventEntries;
+ }
+
+ TCallbackList *theElementCallbackList = NULL;
+
+ // Look for the list of callbacks for this event
+ FOR_ARRAY(SEventCallbackEntry *, theEntry, (*theEventCallbackList))
+ {
+ if (inEventHash == (*theEntry)->m_EventHash) {
+ theElementCallbackList = &(*theEntry)->m_Callbacks;
+ break;
+ }
+ }
+
+ // Create a new list of callbacks if it does not already exist
+ if (!theElementCallbackList) {
+ SEventCallbackEntry *theEventCallbackEntry =
+ Q3DStudio_new(SEventCallbackEntry) SEventCallbackEntry();
+ theEventCallbackEntry->m_EventHash = inEventHash;
+ theEventCallbackList->Push(theEventCallbackEntry);
+ theElementCallbackList = &theEventCallbackList->Top()->m_Callbacks;
+ }
+
+ // Insert callback
+ SCallbackEntry theCallbackEntry = { inCallback, inContextData };
+ theElementCallbackList->Push(theCallbackEntry);
+}
+
+//==============================================================================
+/**
+ * Unregisters an event callback.
+ * @param inElement element to monitor
+ * @param inEventHash event hash to monitor
+ * @param inCallback static callback function
+ * @param inContextData arbitary data pointer
+ * @param outLast indicates if element no longer has callbacks registered
+ * @return BOOL true if callback is unregistered successfully
+ */
+BOOL CEventCallbacks::UnregisterCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData,
+ BOOL &outLast)
+{
+ outLast = false;
+
+ TEventCallbacksList *theEventCallbackList = NULL;
+
+ INT32 theEventListIndex = 0;
+ SElementCallbackEntry *theFoundEntry = NULL;
+ FOR_ARRAY(SElementCallbackEntry *, theEntry, m_EventCallbacksList)
+ {
+ if (inElement == (*theEntry)->m_Element) {
+ theFoundEntry = *theEntry;
+ theEventCallbackList = &(*theEntry)->m_EventEntries;
+ break;
+ }
+ ++theEventListIndex;
+ }
+
+ if (!theEventCallbackList)
+ return false;
+
+ TCallbackList *theElementCallbackList = NULL;
+
+ INT32 theElementListIndex = 0;
+ SEventCallbackEntry *theEventCallbackEntry = NULL;
+ FOR_ARRAY(SEventCallbackEntry *, theEntry, (*theEventCallbackList))
+ {
+ if (inEventHash == (*theEntry)->m_EventHash) {
+ theEventCallbackEntry = *theEntry;
+ theElementCallbackList = &(*theEntry)->m_Callbacks;
+ break;
+ }
+ ++theElementListIndex;
+ }
+
+ if (!theElementCallbackList)
+ return false;
+
+ INT32 theCallbackIndex = 0;
+ FOR_ARRAY(SCallbackEntry, theEntry, (*theElementCallbackList))
+ {
+ if (inCallback == theEntry->m_Function && inContextData == theEntry->m_ContextData) {
+ theElementCallbackList->Remove(theCallbackIndex);
+
+ if (theElementCallbackList->GetCount() == 0) {
+ Q3DStudio_delete(theEventCallbackEntry, SEventCallbackEntry);
+ theEventCallbackList->Remove(theElementListIndex);
+ }
+
+ if (theEventCallbackList->GetCount() == 0) {
+ Q3DStudio_delete(theFoundEntry, SElementCallbackEntry);
+ m_EventCallbacksList.Remove(theEventListIndex);
+ outLast = true;
+ }
+
+ return true;
+ }
+ ++theCallbackIndex;
+ }
+
+ return false;
+}
+
+//==============================================================================
+/**
+ * Unregisters all callbacks.
+ */
+void CEventCallbacks::UnregisterAllCallbacks()
+{
+ FOR_ARRAY(SElementCallbackEntry *, theEntry, m_EventCallbacksList)
+ Q3DStudio_delete(*theEntry, SElementCallbackEntry);
+ m_EventCallbacksList.Clear();
+}
+
+//==============================================================================
+/**
+ * Fires event callbacks
+ * @param ioEvent the event that was fired
+ */
+void CEventCallbacks::FireCallbacks(SEventCommand &ioEvent)
+{
+ TEventCallbacksList *theEventCallbackList = NULL;
+
+ // Look for the list of callbacks for this element
+ FOR_ARRAY(SElementCallbackEntry *, theEntry, m_EventCallbacksList)
+ {
+ if (ioEvent.m_Target == (*theEntry)->m_Element) {
+ theEventCallbackList = &(*theEntry)->m_EventEntries;
+ break;
+ }
+ }
+
+ if (!theEventCallbackList)
+ return;
+
+ // Look for the list of callbacks for this event
+ FOR_ARRAY(SEventCallbackEntry *, theEntry, (*theEventCallbackList))
+ {
+ if (ioEvent.m_Type == (*theEntry)->m_EventHash) {
+ PerformCallbacks((*theEntry)->m_Callbacks, ioEvent);
+ break;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Executing a list of callbacks
+ * @param inCallbackList the list of callbacks to invoke
+ * @param ioEvent the event to pass to the callbacks
+ */
+void CEventCallbacks::PerformCallbacks(TCallbackList &inCallbackList, SEventCommand &ioEvent)
+{
+ // As the callbacks can potentially do a register/unregister that would alter the call list,
+ // it is safer to get a clean copy of the call list to iterate through.
+
+ // Clumsy way to do a m_CallbackList = inCallbackList
+ m_CallbackList.Clear(false);
+ m_CallbackList.Reserve(inCallbackList.GetCount());
+ FOR_ARRAY(SCallbackEntry, theEntry, inCallbackList)
+ m_CallbackList.Push(*theEntry);
+
+ // Invoking the callbacks
+ FOR_ARRAY(SCallbackEntry, theEntry, m_CallbackList)
+ theEntry->m_Function(theEntry->m_ContextData, ioEvent);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICInputEngine.cpp b/src/Runtime/Source/Runtime/Source/UICInputEngine.cpp
new file mode 100644
index 00000000..2abc5b46
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICInputEngine.cpp
@@ -0,0 +1,849 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+#include <EASTL/list.h>
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICInputEngine.h"
+#include "UICSceneManager.h"
+#include "UICInputEventTypes.h"
+#include "UICPresentation.h"
+#include "UICApplication.h"
+#include "UICRuntimeFactory.h"
+#include "EventPollingSystem.h"
+#include "foundation/Qt3DSAssert.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+class CInputEventProvider : public uic::evt::IEventProvider
+{
+ int m_RefCount;
+
+public:
+ CInputEventProvider()
+ : m_RefCount(0)
+ {
+ }
+ ~CInputEventProvider()
+ {
+ while (!m_Events.empty()) {
+ delete m_Events.front();
+ m_Events.pop_front();
+ }
+ }
+ struct SEvent
+ {
+ enum EType { TYPE_NONE = 0, TYPE_KEYBOARD, TYPE_BUTTON, TYPE_COUNT };
+ SEvent(EType inType)
+ : m_Type(inType)
+ {
+ }
+ EType m_Type;
+
+ virtual SEvent *Clone() const = 0;
+ virtual SUICEventSystemEvent *GenEventSystemEvent(uic::evt::IEventFactory &inFactory) = 0;
+ };
+ struct SKeyboardEvent : public SEvent
+ {
+ SKeyboardEvent()
+ : SEvent(TYPE_KEYBOARD)
+ , m_KeyCode(KEY_NOKEY)
+ , m_KeyEvent(0)
+ {
+ }
+ SKeyboardEvent(INT32 inKeyCode, UINT32 inKeyEvent)
+ : SEvent(TYPE_KEYBOARD)
+ , m_KeyCode(inKeyCode)
+ , m_KeyEvent(inKeyEvent)
+ {
+ }
+ SEvent *Clone() const override
+ {
+ return new SKeyboardEvent(this->m_KeyCode, this->m_KeyEvent);
+ }
+ SUICEventSystemEvent *GenEventSystemEvent(uic::evt::IEventFactory &inFactory) override
+ {
+ if (m_KeyEvent == ON_KEYDOWN || m_KeyEvent == ON_KEYUP || m_KeyEvent == ON_KEYREPEAT) {
+ SUICEventSystemEvent &theEvent = inFactory.CreateEvent(3);
+ int theIndex = 0;
+ theEvent.m_Data[theIndex].m_Name = inFactory.RegisterStr("category");
+ theEvent.m_Data[theIndex].m_Value.m_Type = EUICEventSystemEventTypesString;
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("kb");
+ ++theIndex;
+ theEvent.m_Data[theIndex].m_Name = inFactory.RegisterStr("code");
+ theEvent.m_Data[theIndex].m_Value.m_Type = EUICEventSystemEventTypesNumber;
+ theEvent.m_Data[theIndex].m_Value.m_Number = m_KeyCode;
+ ++theIndex;
+ theEvent.m_Data[theIndex].m_Name = inFactory.RegisterStr("action");
+ theEvent.m_Data[theIndex].m_Value.m_Type = EUICEventSystemEventTypesString;
+ if (m_KeyEvent == ON_KEYDOWN)
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("down");
+ else if (m_KeyEvent == ON_KEYUP)
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("up");
+ else if (m_KeyEvent == ON_KEYREPEAT)
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("repeat");
+ ++theIndex;
+ return &theEvent;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ INT32 m_KeyCode;
+ UINT32 m_KeyEvent;
+ };
+ struct SButtonEvent : public SEvent
+ {
+ SButtonEvent()
+ : SEvent(TYPE_BUTTON)
+ , m_ButtonCode(BUTTON_TOTAL_COUNT)
+ , m_ButtonEvent(0)
+ {
+ }
+ SButtonEvent(INT32 inButtonCode, UINT32 inButtonEvent)
+ : SEvent(TYPE_BUTTON)
+ , m_ButtonCode(inButtonCode)
+ , m_ButtonEvent(inButtonEvent)
+ {
+ }
+ SEvent *Clone() const override
+ {
+ return new SKeyboardEvent(this->m_ButtonCode, this->m_ButtonEvent);
+ }
+ SUICEventSystemEvent *GenEventSystemEvent(uic::evt::IEventFactory &inFactory) override
+ {
+ if (m_ButtonEvent == ON_BUTTONDOWN || m_ButtonEvent == ON_BUTTONUP
+ || m_ButtonEvent == ON_BUTTONREPEAT) {
+ SUICEventSystemEvent &theEvent = inFactory.CreateEvent(3);
+ int theIndex = 0;
+ theEvent.m_Data[theIndex].m_Name = inFactory.RegisterStr("category");
+ theEvent.m_Data[theIndex].m_Value.m_Type = EUICEventSystemEventTypesString;
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("button");
+ ++theIndex;
+ theEvent.m_Data[theIndex].m_Name = inFactory.RegisterStr("code");
+ theEvent.m_Data[theIndex].m_Value.m_Type = EUICEventSystemEventTypesNumber;
+ theEvent.m_Data[theIndex].m_Value.m_Number = m_ButtonCode;
+ ++theIndex;
+ theEvent.m_Data[theIndex].m_Name = inFactory.RegisterStr("action");
+ theEvent.m_Data[theIndex].m_Value.m_Type = EUICEventSystemEventTypesString;
+ if (m_ButtonEvent == ON_BUTTONDOWN)
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("down");
+ else if (m_ButtonEvent == ON_BUTTONUP)
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("up");
+ else if (m_ButtonEvent == ON_BUTTONREPEAT)
+ theEvent.m_Data[theIndex].m_Value.m_String = inFactory.AllocateStr("repeat");
+ ++theIndex;
+ return &theEvent;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ INT32 m_ButtonCode;
+ UINT32 m_ButtonEvent;
+ };
+ size_t GetNextEvents(uic::evt::IEventFactory &inFactory, SUICEventSystemEvent **outBuffer,
+ size_t inBufLenInEvent) override
+ {
+ size_t theEventCount = 0;
+ while (!m_Events.empty() && inBufLenInEvent--) {
+ SEvent *theBufferedEvent = m_Events.front();
+ SUICEventSystemEvent *theEventSystemEvent =
+ theBufferedEvent->GenEventSystemEvent(inFactory);
+ if (theEventSystemEvent)
+ outBuffer[theEventCount++] = theEventSystemEvent;
+ m_Events.pop_front();
+ }
+ return theEventCount;
+ }
+
+ void addRef() { ++m_RefCount; }
+
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+
+ void Release() override { release(); }
+
+ void AddEvent(const SEvent &inEvent)
+ {
+ SEvent *theEvent = inEvent.Clone();
+ if (theEvent)
+ m_Events.push_back(theEvent);
+ else
+ QT3DS_ASSERT(false);
+ }
+
+private:
+ eastl::list<SEvent *> m_Events;
+};
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CInputEngine::CInputEngine()
+ : m_BeginPickInput(false)
+ , m_Application(NULL)
+ , m_InputEventProvider(NULL)
+{
+ m_InputFrame.m_PickValid = false;
+ m_InputFrame.m_PickX = 0;
+ m_InputFrame.m_PickY = 0;
+
+ // TODO: SK - To quickly restore functionality, but this is should be in tegra-specific project.
+ m_InputFrame.m_DeltaX = 0;
+ m_InputFrame.m_DeltaY = 0;
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CInputEngine::~CInputEngine()
+{
+}
+
+//==============================================================================
+/**
+ * Set the top-level interface of the Runtime object
+ * @param inRuntime the top-level interface of the Runtime object
+ */
+void CInputEngine::SetApplication(uic::runtime::IApplication *inApplication)
+{
+ m_Application = inApplication;
+ // Create this here. If we die before the application does, then the system will crash unless
+ // the application event system is reponsibe for the keyboard provider. Since the provider
+ // never
+ // access back to this object, this is the most sensible relationship. Furthermore if we have
+ // never been given an application, it doesn't make sense to have a keyboard event provider.
+ // In reality, this entire system should be ref counted.
+ m_InputEventProvider = new CInputEventProvider();
+
+ // Add a ref for the event system because it does not add its own ref.
+ m_InputEventProvider->addRef();
+ m_Application->GetRuntimeFactory().GetEventSystem().AddProvider(*m_InputEventProvider);
+ MarkApplicationDirty();
+}
+
+//==============================================================================
+/**
+ * Get the input information for the current frame
+ * @return the SInputFrame that defines the current frame input information
+ */
+SInputFrame &CInputEngine::GetInputFrame()
+{
+ return m_InputFrame;
+}
+
+//==============================================================================
+/**
+ * Return the key input portion of the input frame.
+ */
+SKeyInputFrame &CInputEngine::GetKeyInputFrame()
+{
+ return m_InputFrame.m_KeyInputFrame;
+}
+
+void CInputEngine::BeginPickInput()
+{
+ m_PickInput.clear();
+ m_BeginPickInput = true;
+}
+
+//==============================================================================
+/**
+ * Set the pick information the the input frame structure
+ * @param inX the X value of the pick position
+ * @param inY the Y value of the pick position
+ * @param inValid whether the X and Y value are valid
+ */
+void CInputEngine::SetPickInput(FLOAT inX, FLOAT inY, BOOL inValid /*= true*/)
+{
+ m_InputFrame.m_PickValid = inValid;
+ m_InputFrame.m_PickX = inX;
+ m_InputFrame.m_PickY = inY;
+ m_InputFrame.m_MouseFlags = 0;
+ MarkApplicationDirty();
+ if (m_BeginPickInput && m_PickInput.size() < 1000)
+ m_PickInput.push_back(eastl::make_pair(inX, inY));
+}
+
+void CInputEngine::EndPickInput()
+{
+ m_BeginPickInput = false;
+}
+
+CInputEngine::TPickInputList CInputEngine::GetPickInput() const
+{
+ return qt3ds::foundation::toDataRef(m_PickInput.data(), m_PickInput.size());
+}
+
+//==============================================================================
+/**
+ * Set the mouse button state flag
+ * @param inFlags the current mouse state
+ */
+void CInputEngine::SetPickFlags(INT32 inFlags)
+{
+ m_InputFrame.m_MouseFlags |= inFlags;
+}
+
+//==============================================================================
+/**
+ * Set the keyboard status
+ * @param inKeyCode the identifier of the key
+ * @param inDown identify whether the key is down
+ */
+void CInputEngine::SetKeyState(INT32 inKeyCode, BOOL inDown)
+{
+ if (!inDown)
+ m_InputFrame.m_KeyInputFrame.m_KeyStates.erase(inKeyCode);
+ else {
+ SKeyInputFrame::MAP_KEYCODE_COUNT::iterator theIter =
+ m_InputFrame.m_KeyInputFrame.m_KeyStates.find(inKeyCode);
+ if (theIter == m_InputFrame.m_KeyInputFrame.m_KeyStates.end())
+ m_InputFrame.m_KeyInputFrame.m_KeyStates.insert(
+ eastl::make_pair<INT32, UINT16>(inKeyCode, 1));
+ else if (theIter->second < 255)
+ ++theIter->second;
+ }
+ MarkApplicationDirty();
+}
+
+//==============================================================================
+/**
+ * Set the button status
+ * @param inButtonCode the identifier of the button
+ * @param inDown identify whether the button is down
+ */
+void CInputEngine::SetButtonState(INT32 inButtonCode, BOOL inDown)
+{
+ if (!inDown)
+ m_InputFrame.m_ButtonStates.erase(inButtonCode);
+ else {
+ SInputFrame::MAP_BUTTONCODE_COUNT::iterator theIter =
+ m_InputFrame.m_ButtonStates.find(inButtonCode);
+ if (theIter == m_InputFrame.m_ButtonStates.end())
+ m_InputFrame.m_ButtonStates.insert(eastl::make_pair<INT32, UINT16>(inButtonCode, 1));
+ else if (theIter->second < 255)
+ ++theIter->second;
+ }
+ MarkApplicationDirty();
+}
+
+//==============================================================================
+/**
+ * Set the scroll value
+ * @param inMouseFlag flag to indicate whether this is a vertical or horizontal
+ *scroll
+ * @param inValue value of scroll performed
+ */
+void CInputEngine::SetScrollValue(INT32 inMouseFlag, INT16 inValue)
+{
+ m_InputFrame.m_MouseFlags = inMouseFlag;
+ m_InputFrame.m_ScrollValue = inValue;
+ MarkApplicationDirty();
+}
+//==============================================================================
+/**
+ * Set whether the keyboard is modified
+ * @param inFlag true if the keyboard status is modified
+ */
+void CInputEngine::SetModifierFlag(INT32 inFlag)
+{
+ m_InputFrame.m_KeyInputFrame.m_ModifierFlags |= inFlag;
+}
+
+// Currently unused
+//==============================================================================
+/**
+ * Converts KeyCode in index format to ASCII format.
+ * This will translate upper/lower-case letters too.
+ * @param inKeyCode the index format keycode
+ * @param inShift whether the shift button is pressed
+ * @return the ASCII format keycode
+ */
+// INT32 CInputEngine::ConvertKeyCode( INT32 inKeyCode, BOOL inShift )
+//{
+// static INT32 s_ASCIILowerCase[] =
+// {
+// 0,//KEY_NOKEY = 0x00,
+// 27,//KEY_ESCAPE,
+// '1',//KEY_1,
+// '2',//KEY_2,
+// '3',//KEY_3,
+// '4',//KEY_4,
+// '5',//KEY_5,
+// '6',//KEY_6,
+// '7',//KEY_7,
+// '8',//KEY_8,
+// '9',//KEY_9,
+// '0',//KEY_0,
+// '-',//KEY_MINUS, /* - on main keyboard */
+// '=',//KEY_EQUALS,
+// 8,//KEY_BACK, /* backspace */
+// '\t',//KEY_TAB,
+// 'q',//KEY_Q,
+// 'w',//KEY_W,
+// 'e',//KEY_E,
+// 'r',//KEY_R,
+// 't',//KEY_T,
+// 'y',//KEY_Y,
+// 'u',//KEY_U,
+// 'i',//KEY_I,
+// 'o',//KEY_O,
+// 'p',//KEY_P,
+// '[',//KEY_LBRACKET,
+// ']',//KEY_RBRACKET,
+// '\n',//KEY_RETURN, /* Enter on main keyboard */
+// 0,//KEY_LCONTROL,
+// 'a',//KEY_A,
+// 's',//KEY_S,
+// 'd',//KEY_D,
+// 'f',//KEY_F,
+// 'g',//KEY_G,
+// 'h',//KEY_H,
+// 'j',//KEY_J,
+// 'k',//KEY_K,
+// 'l',//KEY_L,
+// ';',//KEY_SEMICOLON,
+// '\'',//KEY_APOSTROPHE,
+// '`',//KEY_GRAVE, /* accent grave */
+// 0,//KEY_LSHIFT,
+// '\\',//KEY_BACKSLASH,
+// 'z',//KEY_Z,
+// 'x',//KEY_X,
+// 'c',//KEY_C,
+// 'v',//KEY_V,
+// 'b',//KEY_B,
+// 'n',//KEY_N,
+// 'm',//KEY_M,
+// ',',//KEY_COMMA,
+// '.',//KEY_PERIOD, /* . on main keyboard */
+// '/',//KEY_SLASH, /* / on main keyboard */
+// 0,//KEY_RSHIFT,
+// '*',//KEY_MULTIPLY, /* * on numeric keypad */
+// 0,//KEY_LMENU, /* left Alt */
+// ' ',//KEY_SPACE,
+// 0,//KEY_CAPITAL,
+// 0,//KEY_F1,
+// 0,//KEY_F2,
+// 0,//KEY_F3,
+// 0,//KEY_F4,
+// 0,//KEY_F5,
+// 0,//KEY_F6,
+// 0,//KEY_F7,
+// 0,//KEY_F8,
+// 0,//KEY_F9,
+// 0,//KEY_F10,
+// 0,//KEY_NUMLOCK,
+// 0,//KEY_SCROLL, /* Scroll Lock */
+// '7',//KEY_NUMPAD7,
+// '8',//KEY_NUMPAD8,
+// '9',//KEY_NUMPAD9,
+// '-',//KEY_SUBTRACT, /* - on numeric keypad */
+// '4',//KEY_NUMPAD4,
+// '5',//KEY_NUMPAD5,
+// '6',//KEY_NUMPAD6,
+// '+',//KEY_ADD, /* + on numeric keypad */
+// '1',//KEY_NUMPAD1,
+// '2',//KEY_NUMPAD2,
+// '3',//KEY_NUMPAD3,
+// '0',//KEY_NUMPAD0,
+// '.',//KEY_DECIMAL, /* . on numeric keypad */
+// 0,//KEY_OEM_102, /* <> or \| on RT 102-key keyboard (Non-U.S.) */
+// 0,//KEY_F11,
+// 0,//KEY_F12,
+// 0,//KEY_F13, /* (NEC PC98) */
+// 0,//KEY_F14, /* (NEC PC98) */
+// 0,//KEY_F15, /* (NEC PC98) */
+// 0,//KEY_KANA, /* (Japanese keyboard) */
+// 0,//KEY_ABNT_C1, /* /? on Brazilian keyboard */
+// 0,//KEY_CONVERT, /* (Japanese keyboard) */
+// 0,//KEY_NOCONVERT, /* (Japanese keyboard) */
+// 0,//KEY_YEN, /* (Japanese keyboard) */
+// 0,//KEY_ABNT_C2, /* Numpad . on Brazilian keyboard */
+// 0,//KEY_NUMPADEQUALS, /* = on numeric keypad (NEC PC98) */
+// 0,//KEY_PREVTRACK, /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
+// 0,//KEY_AT, /* (NEC PC98) */
+// 0,//KEY_COLON, /* (NEC PC98) */
+// 0,//KEY_UNDERLINE, /* (NEC PC98) */
+// 0,//KEY_KANJI, /* (Japanese keyboard) */
+// 0,//KEY_STOP, /* (NEC PC98) */
+// 0,//KEY_AX, /* (Japan AX) */
+// 0,//KEY_UNLABELED, /* (J3100) */
+// 0,//KEY_NEXTTRACK, /* Next Track */
+// 0,//KEY_NUMPADENTER, /* Enter on numeric keypad */
+// 0,//KEY_RCONTROL,
+// 0,//KEY_MUTE, /* Mute */
+// 0,//KEY_CALCULATOR, /* Calculator */
+// 0,//KEY_PLAYPAUSE, /* Play / Pause */
+// 0,//KEY_MEDIASTOP, /* Media Stop */
+// 0,//KEY_VOLUMEDOWN, /* Volume - */
+// 0,//KEY_VOLUMEUP, /* Volume + */
+// 0,//KEY_WEBHOME, /* Web home */
+// 0,//KEY_NUMPADCOMMA, /* , on numeric keypad (NEC PC98) */
+// 0,//KEY_DIVIDE, /* / on numeric keypad */
+// 0,//KEY_SYSRQ,
+// 0,//KEY_RMENU, /* right Alt */
+// 0,//KEY_PAUSE, /* Pause */
+// 0,//KEY_HOME, /* Home on arrow keypad */
+// 0,//KEY_UP, /* UpArrow on arrow keypad */
+// 0,//KEY_PRIOR, /* PgUp on arrow keypad */
+// 0,//KEY_LEFT, /* LeftArrow on arrow keypad */
+// 0,//KEY_RIGHT, /* RightArrow on arrow keypad */
+// 0,//KEY_END, /* End on arrow keypad */
+// 0,//KEY_DOWN, /* DownArrow on arrow keypad */
+// 0,//KEY_NEXT, /* PgDn on arrow keypad */
+// 0,//KEY_INSERT, /* Insert on arrow keypad */
+// 127,//KEY_DELETE, /* Delete on arrow keypad */
+// 0,//KEY_LWIN, /* Left Windows key */
+// 0,//KEY_RWIN, /* Right Windows key */
+// 0,//KEY_APPS, /* AppMenu key */
+// 0,//KEY_POWER, /* System Power */
+// 0,//KEY_SLEEP, /* System Sleep */
+// 0,//KEY_WAKE, /* System Wake */
+// 0,//KEY_WEBSEARCH, /* Web Search */
+// 0,//KEY_WEBFAVORITES, /* Web Favorites */
+// 0,//KEY_WEBREFRESH, /* Web Refresh */
+// 0,//KEY_WEBSTOP, /* Web Stop */
+// 0,//KEY_WEBFORWARD, /* Web Forward */
+// 0,//KEY_WEBBACK, /* Web Back */
+// 0,//KEY_MYCOMPUTER, /* My Computer */
+// 0,//KEY_MAIL, /* Mail */
+// 0//KEY_MEDIASELECT, /* Media Select */
+// };
+//
+// static INT32 s_ASCIIUpperCase[] =
+// {
+// 0,//KEY_NOKEY = 0x00,
+// 27,//KEY_ESCAPE,
+// '!',//KEY_1,
+// '@',//KEY_2,
+// '#',//KEY_3,
+// '$',//KEY_4,
+// '%',//KEY_5,
+// '^',//KEY_6,
+// '&',//KEY_7,
+// '*',//KEY_8,
+// '(',//KEY_9,
+// ')',//KEY_0,
+// '_',//KEY_MINUS, /* - on main keyboard */
+// '+',//KEY_EQUALS,
+// 8,//KEY_BACK, /* backspace */
+// '\t',//KEY_TAB,
+// 'Q',//KEY_Q,
+// 'W',//KEY_W,
+// 'E',//KEY_E,
+// 'R',//KEY_R,
+// 'T',//KEY_T,
+// 'Y',//KEY_Y,
+// 'U',//KEY_U,
+// 'I',//KEY_I,
+// 'O',//KEY_O,
+// 'P',//KEY_P,
+// '{',//KEY_LBRACKET,
+// '}',//KEY_RBRACKET,
+// '\n',//KEY_RETURN, /* Enter on main keyboard */
+// 0,//KEY_LCONTROL,
+// 'A',//KEY_A,
+// 'S',//KEY_S,
+// 'D',//KEY_D,
+// 'F',//KEY_F,
+// 'G',//KEY_G,
+// 'H',//KEY_H,
+// 'J',//KEY_J,
+// 'K',//KEY_K,
+// 'L',//KEY_L,
+// ':',//KEY_SEMICOLON,
+// '\"',//KEY_APOSTROPHE,
+// '~',//KEY_GRAVE, /* accent grave */
+// 0,//KEY_LSHIFT,
+// '|',//KEY_BACKSLASH,
+// 'Z',//KEY_Z,
+// 'X',//KEY_X,
+// 'C',//KEY_C,
+// 'V',//KEY_V,
+// 'B',//KEY_B,
+// 'N',//KEY_N,
+// 'M',//KEY_M,
+// '<',//KEY_COMMA,
+// '>',//KEY_PERIOD, /* . on main keyboard */
+// '?',//KEY_SLASH, /* / on main keyboard */
+// 0,//KEY_RSHIFT,
+// '*',//KEY_MULTIPLY, /* * on numeric keypad */
+// 0,//KEY_LMENU, /* left Alt */
+// ' ',//KEY_SPACE,
+// 0,//KEY_CAPITAL,
+// 0,//KEY_F1,
+// 0,//KEY_F2,
+// 0,//KEY_F3,
+// 0,//KEY_F4,
+// 0,//KEY_F5,
+// 0,//KEY_F6,
+// 0,//KEY_F7,
+// 0,//KEY_F8,
+// 0,//KEY_F9,
+// 0,//KEY_F10,
+// 0,//KEY_NUMLOCK,
+// 0,//KEY_SCROLL, /* Scroll Lock */
+// '7',//KEY_NUMPAD7,
+// '8',//KEY_NUMPAD8,
+// '9',//KEY_NUMPAD9,
+// '-',//KEY_SUBTRACT, /* - on numeric keypad */
+// '4',//KEY_NUMPAD4,
+// '5',//KEY_NUMPAD5,
+// '6',//KEY_NUMPAD6,
+// '+',//KEY_ADD, /* + on numeric keypad */
+// '1',//KEY_NUMPAD1,
+// '2',//KEY_NUMPAD2,
+// '3',//KEY_NUMPAD3,
+// '0',//KEY_NUMPAD0,
+// '.',//KEY_DECIMAL, /* . on numeric keypad */
+// 0,//KEY_OEM_102, /* <> or \| on RT 102-key keyboard (Non-U.S.) */
+// 0,//KEY_F11,
+// 0,//KEY_F12,
+// 0,//KEY_F13, /* (NEC PC98) */
+// 0,//KEY_F14, /* (NEC PC98) */
+// 0,//KEY_F15, /* (NEC PC98) */
+// 0,//KEY_KANA, /* (Japanese keyboard) */
+// 0,//KEY_ABNT_C1, /* /? on Brazilian keyboard */
+// 0,//KEY_CONVERT, /* (Japanese keyboard) */
+// 0,//KEY_NOCONVERT, /* (Japanese keyboard) */
+// 0,//KEY_YEN, /* (Japanese keyboard) */
+// 0,//KEY_ABNT_C2, /* Numpad . on Brazilian keyboard */
+// 0,//KEY_NUMPADEQUALS, /* = on numeric keypad (NEC PC98) */
+// 0,//KEY_PREVTRACK, /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
+// 0,//KEY_AT, /* (NEC PC98) */
+// 0,//KEY_COLON, /* (NEC PC98) */
+// 0,//KEY_UNDERLINE, /* (NEC PC98) */
+// 0,//KEY_KANJI, /* (Japanese keyboard) */
+// 0,//KEY_STOP, /* (NEC PC98) */
+// 0,//KEY_AX, /* (Japan AX) */
+// 0,//KEY_UNLABELED, /* (J3100) */
+// 0,//KEY_NEXTTRACK, /* Next Track */
+// 0,//KEY_NUMPADENTER, /* Enter on numeric keypad */
+// 0,//KEY_RCONTROL,
+// 0,//KEY_MUTE, /* Mute */
+// 0,//KEY_CALCULATOR, /* Calculator */
+// 0,//KEY_PLAYPAUSE, /* Play / Pause */
+// 0,//KEY_MEDIASTOP, /* Media Stop */
+// 0,//KEY_VOLUMEDOWN, /* Volume - */
+// 0,//KEY_VOLUMEUP, /* Volume + */
+// 0,//KEY_WEBHOME, /* Web home */
+// 0,//KEY_NUMPADCOMMA, /* , on numeric keypad (NEC PC98) */
+// 0,//KEY_DIVIDE, /* / on numeric keypad */
+// 0,//KEY_SYSRQ,
+// 0,//KEY_RMENU, /* right Alt */
+// 0,//KEY_PAUSE, /* Pause */
+// 0,//KEY_HOME, /* Home on arrow keypad */
+// 0,//KEY_UP, /* UpArrow on arrow keypad */
+// 0,//KEY_PRIOR, /* PgUp on arrow keypad */
+// 0,//KEY_LEFT, /* LeftArrow on arrow keypad */
+// 0,//KEY_RIGHT, /* RightArrow on arrow keypad */
+// 0,//KEY_END, /* End on arrow keypad */
+// 0,//KEY_DOWN, /* DownArrow on arrow keypad */
+// 0,//KEY_NEXT, /* PgDn on arrow keypad */
+// 0,//KEY_INSERT, /* Insert on arrow keypad */
+// 127,//KEY_DELETE, /* Delete on arrow keypad */
+// 0,//KEY_LWIN, /* Left Windows key */
+// 0,//KEY_RWIN, /* Right Windows key */
+// 0,//KEY_APPS, /* AppMenu key */
+// 0,//KEY_POWER, /* System Power */
+// 0,//KEY_SLEEP, /* System Sleep */
+// 0,//KEY_WAKE, /* System Wake */
+// 0,//KEY_WEBSEARCH, /* Web Search */
+// 0,//KEY_WEBFAVORITES, /* Web Favorites */
+// 0,//KEY_WEBREFRESH, /* Web Refresh */
+// 0,//KEY_WEBSTOP, /* Web Stop */
+// 0,//KEY_WEBFORWARD, /* Web Forward */
+// 0,//KEY_WEBBACK, /* Web Back */
+// 0,//KEY_MYCOMPUTER, /* My Computer */
+// 0,//KEY_MAIL, /* Mail */
+// 0//KEY_MEDIASELECT, /* Media Select */
+// };
+//
+// if ( inKeyCode < 0 || inKeyCode > KEY_TOTAL_COUNT )
+// return 0;
+//
+// if ( inShift )
+// return s_ASCIIUpperCase[inKeyCode];
+//
+// return s_ASCIILowerCase[inKeyCode];
+//}
+
+//==============================================================================
+/**
+ * Clear the current input frame data, typically after the event has been processed.
+ */
+void CInputEngine::ClearInputFrame()
+{
+ // TODO: SK - To quickly restore functionality, but this is should be in tegra-specific project.
+ m_InputFrame.m_PickValid = false;
+}
+
+//==============================================================================
+/**
+ * Can be more appropriately named and perhaps moved to a COutputEngine class.
+ * to translate event triggered from script back to a "device" event
+ * e.g to simulate clicking on Home button.
+ *
+ * Base class does nothing.
+ */
+BOOL CInputEngine::TranslateEvent(const CHAR *inEvent)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inEvent);
+ return false;
+}
+
+//==============================================================================
+/**
+ * Handle firing of keyboard events when a scancode is received.
+ */
+void CInputEngine::HandleKeyboard(INT32 inKeyCode, INT32 inPressed, INT32 inRepeat)
+{
+ if (inKeyCode >= KEY_TOTAL_COUNT || inKeyCode <= KEY_NOKEY) {
+ qCDebug(qt3ds::TRACE_INFO)
+ << "Input: Key input out of range. key code: " << inKeyCode
+ << " pressed: " << inPressed << " repeat: " << inRepeat;
+ }
+ if (m_Application == NULL)
+ return;
+ MarkApplicationDirty();
+
+ SetKeyState(inKeyCode, inPressed ? true : false);
+
+ CPresentation *theActivePresentation(m_Application->GetPrimaryPresentation());
+ if (theActivePresentation) {
+ TElement *theScene = theActivePresentation->GetRoot();
+ UVariant theKeycode;
+ theKeycode.m_INT32 = inKeyCode;
+
+ TEventCommandHash theEvent;
+ if (inPressed) {
+ UINT16 theKeyCount = m_InputFrame.m_KeyInputFrame.GetKeyCount(inKeyCode);
+ QT3DS_ASSERT(theKeyCount >= 1);
+ if (theKeyCount == 1 && inRepeat == 0)
+ theEvent = ON_KEYDOWN;
+ else
+ theEvent = ON_KEYREPEAT;
+ } else {
+ theEvent = ON_KEYUP;
+ }
+
+ theActivePresentation->FireEvent(theEvent, theScene, &theKeycode, NULL, ATTRIBUTETYPE_INT32,
+ ATTRIBUTETYPE_NONE);
+ if (m_InputEventProvider)
+ m_InputEventProvider->AddEvent(
+ CInputEventProvider::SKeyboardEvent(theKeycode.m_INT32, theEvent));
+ }
+}
+
+//==============================================================================
+/**
+ * Handle button events.
+ */
+void CInputEngine::HandleButton(INT32 inButtonCode, INT32 inPressed, INT32 inRepeat)
+{
+ if (inButtonCode >= BUTTON_TOTAL_COUNT || inButtonCode < 0) {
+ qCDebug(qt3ds::TRACE_INFO)
+ << "Input: Key input out of range. key code: " << inButtonCode
+ << " pressed: " << inPressed << " repeat: " << inRepeat;
+ }
+ if (m_Application == NULL)
+ return;
+ MarkApplicationDirty();
+
+ SetButtonState(inButtonCode, inPressed ? true : false);
+
+ CPresentation *theActivePresentation(m_Application->GetPrimaryPresentation());
+ if (theActivePresentation) {
+ TElement *theScene = theActivePresentation->GetRoot();
+ UVariant theButtonCode;
+ theButtonCode.m_INT32 = inButtonCode;
+
+ TEventCommandHash theEvent;
+ if (inPressed) {
+ if (inRepeat == 0)
+ theEvent = ON_BUTTONDOWN;
+ else
+ theEvent = ON_BUTTONREPEAT;
+ } else {
+ theEvent = ON_BUTTONUP;
+ }
+
+ theActivePresentation->FireEvent(theEvent, theScene, &theButtonCode, NULL,
+ ATTRIBUTETYPE_INT32, ATTRIBUTETYPE_NONE);
+ if (m_InputEventProvider)
+ m_InputEventProvider->AddEvent(
+ CInputEventProvider::SButtonEvent(theButtonCode.m_INT32, theEvent));
+ }
+}
+
+//==============================================================================
+/**
+ * Handle joystick events.
+ */
+void CInputEngine::HandleAxis(INT32 inAxisCode, FLOAT inValue)
+{
+ if (m_Application == NULL)
+ return;
+ MarkApplicationDirty();
+ if (m_InputFrame.m_AxisStates[inAxisCode] != inValue) {
+ m_InputFrame.m_AxisStates[inAxisCode] = inValue;
+
+ CPresentation *theActivePresentation(m_Application->GetPrimaryPresentation());
+ if (theActivePresentation) {
+ TElement *theScene = theActivePresentation->GetRoot();
+ UVariant theAxisCode;
+ theAxisCode.m_INT32 = inAxisCode;
+ UVariant theValue;
+ theValue.m_FLOAT = inValue;
+
+ theActivePresentation->FireEvent(ON_AXISMOVED, theScene, &theAxisCode, &theValue,
+ ATTRIBUTETYPE_INT32, ATTRIBUTETYPE_FLOAT);
+ }
+ }
+}
+
+void CInputEngine::MarkApplicationDirty()
+{
+ if (m_Application)
+ m_Application->MarkApplicationDirty();
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLogicSystem.cpp b/src/Runtime/Source/Runtime/Source/UICLogicSystem.cpp
new file mode 100644
index 00000000..ac749bb2
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLogicSystem.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "RuntimePrefix.h"
+#include "UICLogicSystem.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICIPresentation.h"
+#include "UICApplication.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/IOStreams.h"
+
+using namespace uic::runtime;
+using namespace qt3ds::foundation;
+using namespace qt3ds;
+using namespace uic::runtime::element;
+
+namespace {
+struct SLogicKey
+{
+ QT3DSU32 m_ElementHandle;
+ Q3DStudio::TEventCommandHash m_CommandHash;
+ SLogicKey(QT3DSU32 hdl = 0, Q3DStudio::TEventCommandHash hash = 0)
+ : m_ElementHandle(hdl)
+ , m_CommandHash(hash)
+ {
+ }
+
+ bool operator==(const SLogicKey &other) const
+ {
+ return m_ElementHandle == other.m_ElementHandle && m_CommandHash == other.m_CommandHash;
+ }
+ size_t hash() const
+ {
+ return eastl::hash<QT3DSU32>()(m_ElementHandle) ^ eastl::hash<QT3DSU32>()((QT3DSU32)m_CommandHash);
+ }
+};
+
+struct SLogicData
+{
+ SLogicData *m_NextLogicData;
+ QT3DSU32 m_Owner;
+ QT3DSU32 m_Target;
+ Q3DStudio::TEventCommandHash m_Type;
+ Q3DStudio::UVariant m_Arg1;
+ Q3DStudio::UVariant m_Arg2;
+ QT3DSI32 m_Id;
+ bool m_Active;
+
+ SLogicData()
+ : m_NextLogicData(NULL)
+ , m_Owner(0)
+ , m_Target(0)
+ , m_Type(0)
+ , m_Id(0)
+ , m_Active(false)
+ {
+ m_Arg1.m_INT32 = 0;
+ m_Arg2.m_INT32 = 0;
+ }
+
+ SLogicData(QT3DSU32 owner, QT3DSU32 target, Q3DStudio::TEventCommandHash type, Q3DStudio::UVariant a1,
+ Q3DStudio::UVariant a2, bool active, QT3DSI32 inId)
+ : m_NextLogicData(NULL)
+ , m_Owner(owner)
+ , m_Target(target)
+ , m_Type(type)
+ , m_Arg1(a1)
+ , m_Arg2(a2)
+ , m_Id(inId)
+ , m_Active(active)
+ {
+ }
+};
+
+DEFINE_INVASIVE_SINGLE_LIST(LogicData);
+IMPLEMENT_INVASIVE_SINGLE_LIST(LogicData, m_NextLogicData);
+}
+
+namespace eastl {
+template <>
+struct hash<SLogicKey>
+{
+ size_t operator()(const SLogicKey &inKey) const { return inKey.hash(); }
+};
+}
+
+namespace {
+
+struct SLogicSystem : public ILogicSystem
+{
+ typedef nvhash_map<SLogicKey, TLogicDataList> TLogicKeyHash;
+ typedef nvhash_map<QT3DSI32, SLogicKey> TIdLogicKeyHash;
+ typedef Pool<SLogicData, ForwardingAllocator> TLogicDataPool;
+
+ NVFoundationBase &m_Foundation;
+
+ TLogicKeyHash m_LogicKeys;
+ TIdLogicKeyHash m_IdToLogicKeys;
+ TLogicDataPool m_LogicDataPool;
+ QT3DSI32 m_NextId;
+ NVDataRef<QT3DSU8> m_LoadData;
+
+ QT3DSI32 m_RefCount;
+
+ SLogicSystem(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , m_LogicKeys(inFoundation.getAllocator(), "m_LogicKeys")
+ , m_IdToLogicKeys(inFoundation.getAllocator(), "m_IdToLogicKeys")
+ , m_LogicDataPool(ForwardingAllocator(inFoundation.getAllocator(), "m_LogicDataPool"))
+ , m_NextId(1)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Foundation.getAllocator());
+ NVDelete(alloc, this);
+ }
+ }
+ void IncrementNextId()
+ {
+ ++m_NextId;
+ if (m_NextId == 0)
+ ++m_NextId;
+ }
+ static QT3DSU32 GetHandle(element::SElement *elem)
+ {
+ if (elem)
+ return elem->GetHandle();
+ return 0;
+ }
+ // returns the action id
+ QT3DSI32 AddAction(element::SElement &inTrigger,
+ Q3DStudio::TEventCommandHash inEventNameHash,
+ element::SElement *inTarget, element::SElement *inOwner,
+ Q3DStudio::TEventCommandHash inType, Q3DStudio::UVariant inArg1,
+ Q3DStudio::UVariant inArg2, bool inActive) override
+ {
+ SLogicKey theKey(inTrigger.GetHandle(), inEventNameHash);
+ eastl::pair<TLogicKeyHash::iterator, bool> inserter =
+ m_LogicKeys.insert(eastl::make_pair(theKey, TLogicDataList()));
+
+ eastl::pair<TIdLogicKeyHash::iterator, bool> idInserter;
+ for (idInserter = m_IdToLogicKeys.insert(eastl::make_pair(m_NextId, theKey));
+ idInserter.second == false;
+ idInserter = m_IdToLogicKeys.insert(eastl::make_pair(m_NextId, theKey))) {
+ IncrementNextId();
+ }
+ IncrementNextId();
+
+ SLogicData *theData = m_LogicDataPool.construct(__FILE__, __LINE__);
+ *theData = SLogicData(GetHandle(inOwner), GetHandle(inTarget), inType, inArg1, inArg2,
+ inActive, idInserter.first->first);
+ inserter.first->second.push_back(*theData);
+ return idInserter.first->first;
+ }
+
+ void OnEvent(Q3DStudio::TEventCommandHash inEventName, element::SElement &inTarget,
+ Q3DStudio::IPresentation &inPresentation) const override
+ {
+ SLogicKey theKey(inTarget.GetHandle(), inEventName);
+ TLogicKeyHash::const_iterator iter = m_LogicKeys.find(theKey);
+ if (iter != m_LogicKeys.end()) {
+ uic::runtime::IApplication &theApplication = inPresentation.GetApplication();
+ uic::runtime::IElementAllocator &theElemAllocator =
+ theApplication.GetElementAllocator();
+ for (TLogicDataList::const_iterator listIter = iter->second.begin(),
+ endIter = iter->second.end();
+ listIter != endIter; ++listIter) {
+ if (listIter->m_Active) {
+ inPresentation.FireCommand(
+ listIter->m_Type, theElemAllocator.FindElementByHandle(listIter->m_Target),
+ &listIter->m_Arg1, &listIter->m_Arg2);
+ }
+ }
+ }
+ }
+
+ void SetActive(QT3DSI32 inActionIndex, bool inActive, IElementAllocator &inElemAllocator) override
+ {
+ TIdLogicKeyHash::iterator iter = m_IdToLogicKeys.find(inActionIndex);
+ if (iter != m_IdToLogicKeys.end()) {
+ TLogicKeyHash::iterator logicIter = m_LogicKeys.find(iter->second);
+ if (logicIter != m_LogicKeys.end()) {
+ for (TLogicDataList::iterator listIter = logicIter->second.begin(),
+ listEnd = logicIter->second.end();
+ listIter != listEnd; ++listIter)
+ if (listIter->m_Id == inActionIndex) {
+ listIter->m_Active = inActive;
+ if (IApplicationCore::isPickingEvent(logicIter->first.m_CommandHash)) {
+ SElement *theElement = inElemAllocator.FindElementByHandle(
+ logicIter->first.m_ElementHandle);
+ if (theElement && inActive)
+ theElement->SetFlag(Q3DStudio::ELEMENTFLAG_PICKENABLED, true);
+ }
+ }
+ }
+ }
+ }
+
+ void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriter(m_Foundation.getAllocator(), "WriteBuffer");
+ theWriter.write(m_NextId);
+ theWriter.write((QT3DSU32)m_LogicKeys.size());
+ for (TLogicKeyHash::iterator iter = m_LogicKeys.begin(), end = m_LogicKeys.end();
+ iter != end; ++iter) {
+ if (iter->second.m_Head == NULL)
+ continue;
+
+ theWriter.write(iter->first);
+ QT3DSU32 datumOffset = theWriter.size();
+ theWriter.write((QT3DSU32)0);
+ QT3DSU32 datumCount = 0;
+ for (SLogicData *theDatum = iter->second.m_Head; theDatum;
+ theDatum = theDatum->m_NextLogicData, ++datumCount) {
+ theWriter.write(*theDatum);
+ }
+ QT3DSU32 *countPtr = reinterpret_cast<QT3DSU32 *>(theWriter.begin() + datumOffset);
+ *countPtr = datumCount;
+ }
+ ioStream.Write(theWriter.begin(), theWriter.size());
+ }
+
+ void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData) override
+ {
+ m_LoadData = inLoadData;
+ SDataReader theReader(inLoadData.begin(), inLoadData.end());
+ m_NextId = *theReader.Load<QT3DSI32>();
+ QT3DSU32 numKeys = *theReader.Load<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numKeys; idx < end; ++idx) {
+ SLogicKey theKey = *theReader.Load<SLogicKey>();
+ QT3DSU32 numActions = *theReader.Load<QT3DSU32>();
+ if (numActions == 0)
+ continue;
+
+ TLogicKeyHash::iterator inserter =
+ m_LogicKeys.insert(eastl::make_pair(theKey, TLogicDataList())).first;
+ SLogicData *lastDatum = NULL;
+ for (QT3DSU32 actIdx = 0, actEnd = numActions; actIdx < actEnd; ++actIdx) {
+ SLogicData *nextDatum = theReader.Load<SLogicData>();
+ if (lastDatum == NULL)
+ inserter->second.m_Head = nextDatum;
+ else
+ lastDatum->m_NextLogicData = nextDatum;
+ lastDatum = nextDatum;
+ m_IdToLogicKeys.insert(eastl::make_pair(nextDatum->m_Id, theKey));
+ }
+ if (lastDatum)
+ lastDatum->m_NextLogicData = NULL;
+ }
+ }
+};
+}
+
+ILogicSystem &ILogicSystem::CreateLogicSystem(NVFoundationBase &inFnd)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), SLogicSystem)(inFnd);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaAxis.cpp b/src/Runtime/Source/Runtime/Source/UICLuaAxis.cpp
new file mode 100644
index 00000000..559874f1
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaAxis.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "RuntimePrefix.h"
+#include "UICInputFrame.h"
+#include "UICLuaAxis.h"
+#include "UICPresentation.h"
+#include "UICInputEngine.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+using namespace Q3DStudio;
+
+//==============================================================================
+// Statics
+//==============================================================================
+
+static const char *s_AxisCodeIdentifier[] = {
+ "AXIS_X", "AXIS_Y", "AXIS_Z", "AXIS_RZ",
+ "AXIS_HAT_X", "AXIS_HAT_Y", "AXIS_LTRIGGER", "AXIS_RTRIGGER",
+};
+
+//==============================================================================
+/**
+ * Registers global button codes
+ */
+void CLuaAxis::RegisterLibrary(lua_State *inLuaState)
+{
+ for (long theCount = 0; theCount < AXIS_TOTAL_COUNT; ++theCount) {
+ lua_pushinteger(inLuaState, theCount);
+ lua_setglobal(inLuaState, s_AxisCodeIdentifier[theCount]);
+ }
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaButton.cpp b/src/Runtime/Source/Runtime/Source/UICLuaButton.cpp
new file mode 100644
index 00000000..ce77a105
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaButton.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "RuntimePrefix.h"
+#include "UICInputFrame.h"
+#include "UICLuaButton.h"
+#include "UICPresentation.h"
+#include "UICInputEngine.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+using namespace Q3DStudio;
+
+//==============================================================================
+// Statics
+//==============================================================================
+
+static const char *s_ButtonCodeIdentifier[] = {
+ "BUTTON_A", "BUTTON_B", "BUTTON_X", "BUTTON_Y", "BUTTON_L1", "BUTTON_R1",
+ "BUTTON_THUMBL", "BUTTON_THUMBR", "BUTTON_SELECT", "BUTTON_START", "BUTTON_MODE", "BUTTON_UP",
+ "BUTTON_DOWN", "BUTTON_LEFT", "BUTTON_RIGHT", "BUTTON_CENTER", "BUTTON_ENTER"
+};
+
+//==============================================================================
+/**
+ * Registers global button codes
+ */
+void CLuaButton::RegisterLibrary(lua_State *inLuaState)
+{
+ for (long theCount = 0; theCount < BUTTON_TOTAL_COUNT; ++theCount) {
+ lua_pushinteger(inLuaState, theCount);
+ lua_setglobal(inLuaState, s_ButtonCodeIdentifier[theCount]);
+ }
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaColor.cpp b/src/Runtime/Source/Runtime/Source/UICLuaColor.cpp
new file mode 100644
index 00000000..91a2562e
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaColor.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaColor.h"
+#include "UICColor.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const CHAR *STRING_COLOR_TYPE = "ColorType";
+const CHAR *STRING_COLOR_CLASS = "Color";
+const CHAR *STRING_ERROR_COLOR_VALUE_EXPECTED = "'Color' value (0 - 255) expected";
+const CHAR *STRING_ERROR_COLOR_EXPECTED = "'Color' expected.";
+
+extern const CHAR *STRING_ERROR_WRONG_NUMBER_ARUGMENT;
+extern const CHAR *STRING_ERROR_ACCESS_NON_MEMBER;
+
+//==============================================================================
+/**
+ * Registers the type "Color" in Lua's global name space
+ * @param inLuaState the Lua state, required for interaction with lua
+ */
+void CLuaColor::RegisterLibrary(lua_State *inLuaState)
+{
+ static const luaL_Reg theColorLibrary[] = { { "new", Create }, { NULL, NULL } };
+
+ static const luaL_Reg theColorMethods[] = {
+ { "setColor", SetColor }, { "set", Set }, { "equals", Equals }, { NULL, NULL }
+ };
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ luaL_newmetatable(inLuaState, STRING_COLOR_TYPE); // Create a new metatable for this Color type
+ luaL_register(inLuaState, NULL,
+ theColorMethods); // Registers the additional methods to this metatable
+
+ lua_pushstring(inLuaState,
+ "__index"); // The GetValue to check if it's 'x', 'y' or 'z' when indexed
+ lua_pushcfunction(inLuaState, GetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState,
+ "__newindex"); // The SetValue to check if it's 'x', 'y' or 'z' when new indexed
+ lua_pushcfunction(inLuaState, SetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__tostring"); // Formatting
+ lua_pushcfunction(inLuaState, ToString);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__eq"); // Equality operator '=='
+ lua_pushcfunction(inLuaState, Equals);
+ lua_settable(inLuaState, 1);
+
+ luaL_register(inLuaState, STRING_COLOR_CLASS,
+ theColorLibrary); // register the 'Color' class type with one method 'new'
+
+ lua_settop(inLuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * Creates a new Lua Color object and places it on the top of the Lua stack
+ * 3 ways to create the new color:
+ * 1) Color.new( ) -- a new color with r, g, and b all
+ *initialized to 255 and a initialized to 0
+ * 2) Color.new( inColor ) -- a new color with r, g, b and a all initialized
+ *to the values of inColor
+ * 3) Color.new( inR, inG, inB, inA ) -- a new color with r, g, b and a all initialized to
+ *the values of inR, inG, inB and inA
+ *
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::Create(lua_State *inLuaState)
+{
+ INT32 theTop = lua_gettop(inLuaState);
+
+ CColor &theColor = CreateColor(inLuaState);
+
+ INT32 theOffset = lua_istable(inLuaState, 1) ? 1 : 0;
+
+ if (theTop == 0 + theOffset) {
+ theColor.m_Red = 255;
+ theColor.m_Green = 255;
+ theColor.m_Blue = 255;
+ theColor.m_Alpha = 255;
+ } else if (theTop == 1 + theOffset) {
+ CColor &theSource = CheckColor(inLuaState, 1 + theOffset);
+ theColor = theSource;
+ } else if (theTop == 4 + theOffset) {
+ theColor.m_Red = GetColorValue(inLuaState, 1 + theOffset);
+ theColor.m_Green = GetColorValue(inLuaState, 2 + theOffset);
+ theColor.m_Blue = GetColorValue(inLuaState, 3 + theOffset);
+ theColor.m_Alpha = GetColorValue(inLuaState, 4 + theOffset);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ Q3DStudio_ASSERT(lua_gettop(inLuaState) == theTop + 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the value of red or green or blue or alpha and places it on the top of the lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::GetValue(lua_State *inLuaState)
+{
+ CColor &theColor = CheckColor(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+
+ if (::strcmp(theParam, "r") == 0)
+ lua_pushinteger(inLuaState, theColor.m_Red);
+ else if (::strcmp(theParam, "g") == 0)
+ lua_pushinteger(inLuaState, theColor.m_Green);
+ else if (::strcmp(theParam, "b") == 0)
+ lua_pushinteger(inLuaState, theColor.m_Blue);
+ else if (::strcmp(theParam, "a") == 0)
+ lua_pushinteger(inLuaState, theColor.m_Alpha);
+ else {
+ lua_getmetatable(inLuaState, 1); // gets the metatable of this user type
+ lua_pushvalue(inLuaState, 2); // push the key onto the top of stack
+ lua_rawget(inLuaState, -2); // get the associated function, if any
+
+ if (lua_isnil(inLuaState, -1))
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+ }
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Sets the value of red or green or blue or alpha
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::SetValue(lua_State *inLuaState)
+{
+ CColor &theColor = CheckColor(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+
+ if (::strcmp(theParam, "r") == 0)
+ theColor.m_Red = GetColorValue(inLuaState, 3);
+ else if (::strcmp(theParam, "g") == 0)
+ theColor.m_Green = GetColorValue(inLuaState, 3);
+ else if (::strcmp(theParam, "b") == 0)
+ theColor.m_Blue = GetColorValue(inLuaState, 3);
+ else if (::strcmp(theParam, "a") == 0)
+ theColor.m_Alpha = GetColorValue(inLuaState, 3);
+ else
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Set the vector's value to the value of inColor which is on the top of the
+ * Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::SetColor(lua_State *inLuaState)
+{
+ CColor &theDestination = CheckColor(inLuaState);
+ CColor &theSource = CheckColor(inLuaState, 2);
+
+ theDestination = theSource;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the color's value to the value of inR, inG, inB and inA which are on the top
+ * of the Lua stack respectively
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::Set(lua_State *inLuaState)
+{
+ CColor &theColorA = CheckColor(inLuaState);
+
+ theColorA.m_Red = GetColorValue(inLuaState, 2);
+ theColorA.m_Green = GetColorValue(inLuaState, 3);
+ theColorA.m_Blue = GetColorValue(inLuaState, 4);
+ theColorA.m_Alpha = GetColorValue(inLuaState, 5);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Checks for equality of 2 colors
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::Equals(lua_State *inLuaState)
+{
+ CColor &theColorA = CheckColor(inLuaState, 1);
+ CColor &theColorB = CheckColor(inLuaState, 2);
+
+ BOOL theResult = theColorA.m_Red == theColorB.m_Red && theColorA.m_Green == theColorB.m_Green
+ && theColorA.m_Blue == theColorB.m_Blue && theColorA.m_Alpha == theColorB.m_Alpha;
+
+ lua_pushboolean(inLuaState, theResult);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Formats the Color object into a string and place the string on the top of Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaColor::ToString(lua_State *inLuaState)
+{
+ CColor &theColor = CheckColor(inLuaState);
+
+ lua_pushfstring(inLuaState, "Color: %d, %d, %d, %d", theColor.m_Red, theColor.m_Green,
+ theColor.m_Blue, theColor.m_Alpha);
+
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Helper to check the type of the userdata is of STRING_COLOR_TYPE
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inIndex the index to where on the stack to check
+ * @return the reference to the userdata pointed to by inIndex
+ */
+CColor &CLuaColor::CheckColor(lua_State *inLuaState, const INT32 inIndex)
+{
+ CColor *theColor =
+ reinterpret_cast<CColor *>(luaL_checkudata(inLuaState, inIndex, STRING_COLOR_TYPE));
+ luaL_argcheck(inLuaState, theColor != NULL, 1, STRING_ERROR_COLOR_EXPECTED);
+ return *theColor;
+}
+
+//==============================================================================
+/**
+ * Helper to create a new userdata of STRING_COLOR_TYPE on the top of the stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the reference to the userdata pointed to by inIndex
+ */
+CColor &CLuaColor::CreateColor(lua_State *inLuaState)
+{
+ CColor *theColor = reinterpret_cast<CColor *>(lua_newuserdata(inLuaState, sizeof(CColor)));
+
+ // associate the metatable with CColor
+ luaL_getmetatable(inLuaState, STRING_COLOR_TYPE);
+ lua_setmetatable(inLuaState, -2);
+
+ return *theColor;
+}
+
+//==============================================================================
+/**
+ * Helper to get a color value from the stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inIndex the index to where the color value is on the stack
+ * @return the color value
+ */
+UINT8 CLuaColor::GetColorValue(lua_State *inLuaState, const INT32 inIndex)
+{
+ INT32 theValue = luaL_checkinteger(inLuaState, inIndex);
+ luaL_argcheck(inLuaState, theValue <= 255, 1, STRING_ERROR_COLOR_VALUE_EXPECTED);
+ return static_cast<UINT8>(theValue);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaCommandHelper.cpp b/src/Runtime/Source/Runtime/Source/UICLuaCommandHelper.cpp
new file mode 100644
index 00000000..ae42d9c3
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaCommandHelper.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaCommandHelper.h"
+#include "UICCommandEventTypes.h"
+#include "UICPresentation.h"
+#include "UICDataLogger.h"
+#include "UICApplication.h"
+#include "UICElementSystem.h"
+#include "UICSlideSystem.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CLuaCommandHelper::CLuaCommandHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CLuaCommandHelper::~CLuaCommandHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Start the component time
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::Play(lua_State *inLuaState)
+{
+ lua_pushlightuserdata(inLuaState, FireCommand(inLuaState, COMMAND_PLAY));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Pause the component time
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::Pause(lua_State *inLuaState)
+{
+ lua_pushlightuserdata(inLuaState, FireCommand(inLuaState, COMMAND_PAUSE));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Go to the time specified
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::GoToTime(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_GOTOTIME);
+ lua_pushlightuserdata(inLuaState, FireCommand(inLuaState, COMMAND_GOTOTIME));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Go to the slide specified
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::GoToSlide(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_GOTOSLIDE);
+ FireCommand(inLuaState, COMMAND_GOTOSLIDE);
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Go to the 1 slide after the current slide
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::GoToNextSlide(lua_State *inLuaState)
+{
+ lua_pushlightuserdata(inLuaState, FireCommand(inLuaState, COMMAND_GOTONEXTSLIDE));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Go to the 1 slide before the current slide
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::GoToPreviousSlide(lua_State *inLuaState)
+{
+ lua_pushlightuserdata(inLuaState, FireCommand(inLuaState, COMMAND_GOTOPREVIOUSSLIDE));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Go to the slide before coming to the current slide
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaCommandHelper::GoToBackSlide(lua_State *inLuaState)
+{
+ lua_pushlightuserdata(inLuaState, FireCommand(inLuaState, COMMAND_BACKSLIDE));
+ return 1;
+}
+
+static Option<Q3DStudio::UINT8> FindSlide(TElement &inElement, const char *slideName)
+{
+ IPresentation *thePresentation = inElement.GetBelongedPresentation();
+
+ int theSlideHashName = thePresentation->GetApplication().HashString(slideName);
+ TComponent *theComponent = thePresentation->GetComponentManager().GetComponent(&inElement);
+ UINT8 theSlideIndex =
+ thePresentation->GetSlideSystem().FindSlide(*theComponent, theSlideHashName);
+ if (theSlideIndex >= theComponent->GetSlideCount()) {
+ qt3ds::foundation::CRegisteredString elemPath = thePresentation->GetElementPath(inElement);
+ if (elemPath.IsValid()) {
+ qCCritical(qt3ds::INVALID_PARAMETER)
+ << "LuaCommandHelper: goToSlide: Unable to find slide "
+ << slideName << " on element " << elemPath.c_str();
+ } else {
+ qCCritical(qt3ds::INVALID_PARAMETER)
+ << "LuaCommandHelper: goToSlide: Unable to find slide " << slideName;
+ }
+ return Empty();
+ }
+
+ return theSlideIndex;
+}
+
+bool CLuaCommandHelper::SetupGotoSlideCommand(TElement &inElement, Q3DStudio::INT32 inSlideIndex,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ IPresentation *thePresentation = inElement.GetBelongedPresentation();
+ TElement *theTarget = GetComponentParent(&inElement);
+ SComponentGotoSlideData theSlideData(inSlideIndex);
+ theSlideData.m_Mode = inArgs.m_Mode;
+ theSlideData.m_Paused = inArgs.m_Paused;
+ theSlideData.m_Rate = inArgs.m_Rate;
+ theSlideData.m_Reverse = inArgs.m_Reverse;
+ theSlideData.m_StartTime = inArgs.m_StartTime;
+ // Resolve playthroughto if it has a valid value.
+ if (!isTrivial(inArgs.m_PlaythroughTo)) {
+ if (AreEqual(inArgs.m_PlaythroughTo, "next"))
+ theSlideData.m_PlaythroughTo = -1;
+ else if (AreEqual(inArgs.m_PlaythroughTo, "previous"))
+ theSlideData.m_PlaythroughTo = -2;
+ else {
+ // Find the slide if possible. If not, then just error leave things as they are.
+
+ Option<UINT8> theSlideIndex = FindSlide(inElement, inArgs.m_PlaythroughTo);
+ if (theSlideIndex.hasValue())
+ theSlideData.m_PlaythroughTo = *theSlideIndex;
+ }
+ }
+ thePresentation->GetComponentManager().SetupComponentGotoSlideCommand(theTarget, theSlideData);
+ UVariant theArg1;
+ UVariant theArg2;
+ qt3ds::intrinsics::memZero(&theArg1, sizeof(UVariant));
+ qt3ds::intrinsics::memZero(&theArg2, sizeof(UVariant));
+ thePresentation->FireCommand(COMMAND_GOTOSLIDE, theTarget, &theArg1, &theArg2);
+ return true;
+}
+
+bool CLuaCommandHelper::SetupGotoSlideCommand(TElement &inElement, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ Option<UINT8> theSlideIndex = FindSlide(inElement, slideName);
+ if (theSlideIndex.hasValue())
+ return SetupGotoSlideCommand(inElement, *theSlideIndex, inArgs);
+ return false;
+}
+//==============================================================================
+/**
+ * Fires commands to components
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inCommand the command to fire into the presentation
+ * @return the component that the command was fired upon
+ */
+TElement *CLuaCommandHelper::FireCommand(lua_State *inLuaState, TEventCommandHash inCommand)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_FIRECOMMAND);
+
+ const INT32 ARG_TARGET_ELEMENT = 1;
+ const INT32 ARG_1 = 2;
+
+ luaL_checktype(inLuaState, ARG_TARGET_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theTarget =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_TARGET_ELEMENT));
+ UVariant theArg1;
+ UVariant theArg2;
+
+ IPresentation *thePresentation = theTarget->GetBelongedPresentation();
+ if (theTarget->GetActive()) {
+ if (inCommand == COMMAND_GOTOTIME) {
+ luaL_checktype(inLuaState, ARG_1, LUA_TNUMBER);
+
+ theArg1.m_INT32 = static_cast<INT32>(lua_tonumber(inLuaState, ARG_1) * 1000);
+ // NVLogInfo( "CLuaCommandHelper::FireCommand: GoToTime", "%d", theArg1.m_INT32 );
+ } else if (inCommand == COMMAND_GOTOSLIDE) {
+ TElement *theComponent = GetComponentParent(theTarget);
+ if (lua_isnumber(inLuaState, ARG_1))
+ SetupGotoSlideCommand(*theComponent, lua_tointeger(inLuaState, ARG_1),
+ SScriptEngineGotoSlideArgs());
+ else if (lua_isstring(inLuaState, ARG_1))
+ SetupGotoSlideCommand(*theComponent, lua_tostring(inLuaState, ARG_1),
+ SScriptEngineGotoSlideArgs());
+ else
+ luaL_error(inLuaState, "goToSlide: Invalid type for Argument#2");
+ return theTarget;
+ }
+
+ theTarget = GetComponentParent(theTarget);
+
+ thePresentation->FireCommand(inCommand, theTarget, &theArg1, &theArg2);
+ }
+
+ return theTarget;
+}
+
+//==============================================================================
+/**
+ * Checks if the given element is a component. If it isn't walks up the tree and looks for one.
+ * @param inElementManager the object that manages the elements in the presentation
+ * @param inElement the element to check if it's a component
+ * @return the component
+ */
+TElement *CLuaCommandHelper::GetComponentParent(TElement *inElement)
+{
+ Q3DStudio_ASSERT(inElement);
+ return &inElement->GetComponentParent();
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaElementHelper.cpp b/src/Runtime/Source/Runtime/Source/UICLuaElementHelper.cpp
new file mode 100644
index 00000000..96509876
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaElementHelper.cpp
@@ -0,0 +1,511 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaElementHelper.h"
+#include "UICLuaCommandHelper.h"
+#include "UICLuaEngine.h"
+#include "UICPresentation.h"
+#include "UICAttributeHashes.h"
+#include "UICApplication.h"
+#include "UICCommandEventTypes.h"
+#include "UICRuntimeFactory.h"
+#include "UICElementSystem.h"
+
+#include "UICDataLogger.h"
+
+using namespace qt3ds;
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const char PRESENTATION_DELIMITER = ':';
+const char NODE_DELIMITER = '.';
+const TStringHash RESERVED_THIS = CHash::HashString("this");
+const TStringHash RESERVED_PARENT = CHash::HashString("parent");
+const TStringHash RESERVED_SCENE = CHash::HashString("Scene");
+const TAttributeHash SPECIAL_ATTRIBUTE_EXPLICIT_ACTIVE = CHash::HashAttribute("active");
+const TAttributeHash SPECIAL_ATTRIBUTE_GLOBAL_ACTIVE = CHash::HashAttribute("globalactive");
+const char *STRINGS_ELEMENT_TYPE[] = { "unknown", "node", "camera", "light",
+ "text", "material", "texture", "component",
+ "behavior", "path", "pathanchorpoint", "subpath" };
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CLuaElementHelper::CLuaElementHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CLuaElementHelper::~CLuaElementHelper()
+{
+}
+
+TElement *CLuaElementHelper::GetElement(uic::runtime::IApplication &inApplication,
+ IPresentation *inDefaultPresentation, const char *inPath,
+ TElement *inStartElement)
+{
+ if (inPath == NULL || *inPath == 0)
+ return NULL;
+ const char *thePath(inPath);
+ const char *theSubPath = NULL;
+ IPresentation *thePresentation = NULL;
+ size_t thePathLength = ::strlen(thePath) + 1;
+ char *theToken =
+ Q3DStudio_allocate_desc(CHAR, thePathLength, "Lua:TempPath"); // Temporary token storage
+ // Try to get the specified presentation
+ theSubPath = ::strchr(thePath, PRESENTATION_DELIMITER);
+ TElement *theElement = inStartElement;
+ if (theSubPath != NULL) {
+ UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
+
+ ::strncpy(theToken, thePath, theSubPathLength);
+ theToken[theSubPathLength] = '\0';
+
+ thePath = theSubPath + 1;
+
+ const CHAR *thePresentationName = theToken;
+
+ thePresentation = inApplication.GetPresentationById(thePresentationName);
+ }
+ if (thePresentation == NULL)
+ thePresentation = inDefaultPresentation;
+
+ // Return nil if the inStartElement is not in the specified presentation
+ if (theElement != NULL
+ && (theSubPath == NULL && theElement->GetBelongedPresentation() != thePresentation)) {
+ thePresentation = theElement->GetBelongedPresentation();
+ }
+
+ if (thePresentation == NULL)
+ return NULL;
+
+ TStringHash theName;
+ INT32 theParseCounter = 0;
+
+ while (thePath != NULL && thePath[0] != '\0') {
+ ++theParseCounter;
+
+ // Do some strtok() work here
+ theSubPath = ::strchr(thePath, NODE_DELIMITER);
+ if (theSubPath) {
+ UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
+ Q3DStudio_ASSERT(theSubPathLength < thePathLength);
+
+ ::strncpy(theToken, thePath, theSubPathLength);
+ theToken[theSubPathLength] = '\0';
+
+ thePath = theSubPath + 1;
+ } else {
+ ::strcpy(theToken, thePath);
+ thePath = NULL;
+ }
+
+ // Hash the token and do some element searching
+ theName = CHash::HashString(theToken);
+
+ if (theName == RESERVED_PARENT) {
+ if (theElement)
+ theElement = theElement->GetParent();
+ } else if (theName == RESERVED_THIS) {
+ ;
+ } else {
+ if (theName == RESERVED_SCENE && theParseCounter == 1)
+ theElement =
+ thePresentation->GetRoot(); // theElement is NULL, so using absolute path
+
+ else if (theElement)
+ theElement = theElement->FindChild(theName); // Using relative path
+ }
+
+ if (!theElement)
+ thePath = NULL;
+ } // while
+
+ Q3DStudio_free(theToken, CHAR, thePathLength);
+ return theElement;
+}
+//==============================================================================
+/**
+ * Gets the ElementRef of the element specified in the path
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaElementHelper::GetElement(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_GETELEMENT);
+
+ const INT32 ARG_PATH = 1;
+ const INT32 ARG_START = 2;
+
+ int theStackTop = lua_gettop(inLuaState);
+
+ // Will exit function immediately once any of these luaL_check.. function fails
+ const char *thePath = luaL_checkstring(inLuaState, ARG_PATH);
+ TElement *theElement = NULL;
+ CPresentation *thePresentation = CLuaEngine::GetCurrentPresentation(inLuaState);
+
+ // Parse arguments
+ if (theStackTop == 2) {
+ luaL_checktype(inLuaState, ARG_START, LUA_TLIGHTUSERDATA);
+ theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_START));
+ }
+ lua_getglobal(inLuaState, "UICApplication");
+ uic::runtime::IApplication *theApp =
+ static_cast<uic::runtime::IApplication *>(lua_touserdata(inLuaState, -1));
+
+ if (theApp)
+ theElement = GetElement(*theApp, thePresentation, thePath, theElement);
+
+ if (theElement)
+ lua_pushlightuserdata(inLuaState, theElement);
+ else
+ lua_pushnil(inLuaState);
+
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the element type
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaElementHelper::GetElementType(lua_State *inLuaState)
+{
+ const INT32 ARG_ELEMENT = 1;
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ lua_pushstring(inLuaState, theElement->GetTypeDescription().m_TypeName.c_str());
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the attribute value of the specified element
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaElementHelper::GetAttribute(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_GETATTRIBUTE);
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_ATTRIBUTE_NAME = 2;
+
+ // will exit function immediately once any of these luaL_check.. function fails
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ const char *attName = luaL_checkstring(inLuaState, ARG_ATTRIBUTE_NAME);
+ SAttributeKey theAttributeKey;
+ theAttributeKey.m_Hash = CHash::HashAttribute(attName);
+
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ uic::runtime::IApplication &theApplication = thePresentation->GetApplication();
+
+ if (theAttributeKey.m_Hash == SPECIAL_ATTRIBUTE_GLOBAL_ACTIVE)
+ lua_pushboolean(inLuaState, theElement->GetActive());
+ else if (theAttributeKey.m_Hash == SPECIAL_ATTRIBUTE_EXPLICIT_ACTIVE)
+ lua_pushboolean(inLuaState, theElement->IsExplicitActive());
+ else if (theAttributeKey.m_Hash == Q3DStudio::ATTRIBUTE_NAME) {
+ lua_pushstring(inLuaState, theElement->m_Name.c_str());
+ } else if (theAttributeKey.m_Hash == Q3DStudio::CHash::HashAttribute("path")) {
+ lua_pushstring(inLuaState, theElement->m_Path.c_str());
+ } else {
+ Option<uic::runtime::element::TPropertyDescAndValuePtr> thePropertyInfo =
+ theElement->FindProperty(theAttributeKey.m_Hash);
+ if (thePropertyInfo.hasValue()) {
+ UVariant *theValuePtr = thePropertyInfo->second;
+ switch (thePropertyInfo->first.m_Type) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ lua_pushinteger(inLuaState, theValuePtr->m_INT32);
+ break;
+
+ case ATTRIBUTETYPE_FLOAT:
+ lua_pushnumber(inLuaState, theValuePtr->m_FLOAT);
+ break;
+
+ case ATTRIBUTETYPE_BOOL:
+ lua_pushboolean(inLuaState, theValuePtr->m_INT32 != 0);
+ break;
+
+ case ATTRIBUTETYPE_STRING:
+ lua_pushstring(inLuaState, thePresentation->GetStringTable()
+ .HandleToStr(theValuePtr->m_StringHandle)
+ .c_str());
+ break;
+
+ case ATTRIBUTETYPE_POINTER:
+ lua_pushlightuserdata(inLuaState, theValuePtr->m_VoidPointer);
+ break;
+
+ case ATTRIBUTETYPE_ELEMENTREF:
+ lua_pushlightuserdata(
+ inLuaState, theApplication.GetElementByHandle(theValuePtr->m_ElementHandle));
+ break;
+
+ case ATTRIBUTETYPE_NONE:
+ case ATTRIBUTETYPE_DATADRIVEN_PARENT:
+ case ATTRIBUTETYPE_DATADRIVEN_CHILD:
+ case ATTRIBUTETYPECOUNT:
+ default:
+ luaL_error(inLuaState, "getAttribute: Attribute has no type!");
+ break;
+ }
+ } else
+ luaL_error(inLuaState, "getAttribute: Attribute \"%s\" not found.",
+ lua_tostring(inLuaState, ARG_ATTRIBUTE_NAME));
+ }
+
+ return 1;
+}
+
+bool CLuaElementHelper::SetAttribute(lua_State *inLuaState, TElement *theElement,
+ const char *theAttName, bool inDelay)
+{
+ SAttributeKey theAttributeKey;
+ theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
+
+ // Early out for our single 'read only' attribute
+ if (ATTRIBUTE_URI == theAttributeKey.m_Hash) {
+ // we didn't push anything onto the lua stack
+ return false;
+ }
+
+ const int ARG_VALUE = -1;
+
+ if (theAttributeKey.m_Hash == SPECIAL_ATTRIBUTE_EXPLICIT_ACTIVE) {
+ if (lua_type(inLuaState, ARG_VALUE) != LUA_TBOOLEAN) {
+ qCCritical(INVALID_OPERATION, "setAttribute: expected boolean");
+ return false;
+ }
+ theElement->SetFlag(ELEMENTFLAG_EXPLICITACTIVE,
+ (lua_toboolean(inLuaState, ARG_VALUE) ? true : false));
+ } else {
+ Option<uic::runtime::element::TPropertyDescAndValuePtr> thePropertyInfo =
+ theElement->FindProperty(theAttributeKey.m_Hash);
+ if (thePropertyInfo.hasValue()) {
+ UVariant theNewValue;
+ EAttributeType theAttributeType = thePropertyInfo->first.m_Type;
+ switch (theAttributeType) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ theNewValue.m_INT32 = luaL_checkinteger(inLuaState, ARG_VALUE);
+ break;
+
+ case ATTRIBUTETYPE_FLOAT:
+ theNewValue.m_FLOAT = static_cast<FLOAT>(luaL_checknumber(inLuaState, ARG_VALUE));
+ break;
+
+ case ATTRIBUTETYPE_BOOL:
+ luaL_checktype(inLuaState, ARG_VALUE, LUA_TBOOLEAN);
+ theNewValue.m_INT32 = lua_toboolean(inLuaState, ARG_VALUE) ? 1 : 0;
+ break;
+
+ case ATTRIBUTETYPE_STRING:
+ theNewValue.m_StringHandle =
+ theElement->GetBelongedPresentation()->GetStringTable().GetHandle(
+ luaL_checkstring(inLuaState, ARG_VALUE));
+ break;
+
+ case ATTRIBUTETYPE_POINTER:
+ if (lua_type(inLuaState, ARG_VALUE) != LUA_TLIGHTUSERDATA) {
+ qCCritical(INVALID_OPERATION, "setAttribute: expected light user data");
+ return false;
+ }
+ theNewValue.m_VoidPointer = lua_touserdata(inLuaState, ARG_VALUE);
+ break;
+
+ case ATTRIBUTETYPE_ELEMENTREF:
+ qCCritical(INVALID_OPERATION, "setAttribute: ElementRef attributes are read only.");
+ return false;
+ break;
+
+ case ATTRIBUTETYPE_NONE:
+ case ATTRIBUTETYPE_DATADRIVEN_PARENT:
+ case ATTRIBUTETYPE_DATADRIVEN_CHILD:
+ case ATTRIBUTETYPECOUNT:
+ default:
+ qCCritical(INVALID_OPERATION, "setAttribute: Attribute has no type!");
+ return false;
+ break;
+ }
+ if (inDelay) {
+ UVariant arg1;
+ arg1.m_INT32 = theAttributeKey.m_Hash;
+ theElement->GetBelongedPresentation()->FireCommand(
+ COMMAND_SETPROPERTY, theElement, &arg1, &theNewValue, ATTRIBUTETYPE_HASH,
+ theAttributeType);
+ } else {
+ theElement->SetAttribute(*thePropertyInfo, theNewValue);
+ }
+
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+//==============================================================================
+/**
+ * Sets the attribute value of the specified element
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaElementHelper::SetAttribute(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_SETATTRIBUTE);
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_ATTRIBUTE_NAME = 2;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+ const char *theAttName = luaL_checkstring(inLuaState, ARG_ATTRIBUTE_NAME);
+ if (!SetAttribute(inLuaState, theElement, theAttName, false)) {
+ luaL_error(inLuaState, "setAttribute: Attribute \"%s\" not found.", theAttName);
+ }
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Checks if element has a specific attribute
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaElementHelper::HasAttribute(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_HASATTRIBUTE);
+
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_ATTRIBUTE_NAME = 2;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ SAttributeKey theAttributeKey;
+ theAttributeKey.m_Hash = CHash::HashAttribute(luaL_checkstring(inLuaState, ARG_ATTRIBUTE_NAME));
+
+ UVariant theValue;
+ lua_pushboolean(inLuaState, theElement->GetAttribute(theAttributeKey.m_Hash, theValue));
+
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the children for the specified element
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the table containing all the children that was pushed on the stack
+ */
+int CLuaElementHelper::GetChildren(lua_State *inLuaState)
+{
+ const INT32 ARG_PARENT = 1;
+
+ luaL_checktype(inLuaState, ARG_PARENT, LUA_TLIGHTUSERDATA);
+
+ TElement *theParent = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_PARENT));
+
+ INT32 theIndex = 0;
+ lua_newtable(inLuaState); // Top = New Table
+ int theTop = lua_gettop(inLuaState);
+ for (TElement *theChild = theParent->m_Child; theChild; theChild = theChild->m_Sibling) {
+ lua_pushlightuserdata(inLuaState, theChild); // Top + 1 = theChild
+ lua_rawseti(inLuaState, theTop, ++theIndex);
+ }
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the current slide number of the element. If element isn't a component, it
+ * walks up the tree to find one that is.
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 2 - the slide number and the slide name that was pushed on the stack
+ */
+int CLuaElementHelper::GetCurrentSlide(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_GETCURRENTSLIDE);
+
+ luaL_checktype(inLuaState, 1, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, 1));
+
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ theElement = &theElement->GetComponentParent();
+ int slideNum = thePresentation->GetComponentManager().GetCurrentSlide(theElement);
+ const char *slideName = thePresentation->GetComponentManager().GetCurrentSlideName(theElement);
+ lua_pushinteger(inLuaState, slideNum);
+ lua_pushstring(inLuaState, slideName);
+
+ return 2;
+}
+
+//==============================================================================
+/**
+ * Gets the current time of the element. If element isn't a component, it walks
+ * up the tree to find one that is.
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 3 - the current time of the element in seconds, the pause state and
+ * the pingpong direction that was pushed on the stack
+ */
+int CLuaElementHelper::GetTime(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_GETTIME);
+ luaL_checktype(inLuaState, 1, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, 1));
+
+ lua_pushnumber(inLuaState, theElement->GetInnerTime() / 1000.0f);
+
+ TComponent &theComponent = static_cast<TComponent &>(theElement->GetComponentParent());
+
+ lua_pushboolean(inLuaState, theComponent.GetPaused());
+ lua_pushboolean(inLuaState, theComponent.GetPlayBackDirection());
+
+ return 3;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaEngine.cpp b/src/Runtime/Source/Runtime/Source/UICLuaEngine.cpp
new file mode 100644
index 00000000..994a1e05
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaEngine.cpp
@@ -0,0 +1,3217 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaEngine.h"
+#include "UICPresentation.h"
+#include "UICInputEngine.h"
+#include "UICSceneManager.h"
+#include "UICVector3.h"
+#include "UICColor.h"
+#include "UICLuaElementHelper.h"
+#include "UICLuaEventHelper.h"
+#include "UICLuaCommandHelper.h"
+#include "UICLuaSceneHelper.h"
+#include "UICLuaVector.h"
+#include "UICLuaColor.h"
+#include "UICLuaRotation.h"
+#include "UICLuaMatrix.h"
+#include "UICAttributeHashes.h"
+#include "UICFileStream.h"
+#include "UICDataLogger.h"
+#include "UICLuaKeyboard.h"
+#include "UICLuaButton.h"
+#include "UICLuaAxis.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSSystem.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICStateLuaScriptContext.h"
+#include "UICStateDebugger.h"
+#include "EventPollingSystemLuaBinding.h"
+#include "UICRenderBufferLoader.h"
+#include "UICRenderInputStreamFactory.h"
+
+#include "EASTL/vector.h"
+#include <sys/stat.h>
+#include "UICCommandEventTypes.h"
+#include "UICApplication.h"
+#include "UICRuntimeFactory.h"
+#include "UICStateDebugStreams.h"
+#include "UICRenderContext.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "UICLuaDebugger.h"
+#include "UICRenderThreadPool.h"
+#include "UICRenderImageBatchLoader.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICAudioPlayer.h"
+#include "UICActivationManager.h"
+#include "UICParametersSystem.h"
+
+#include <QtCore/QFileInfo>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+#if defined(_DEBUG) || (_PROFILE)
+#define Q3DStudio_LOG_EVENT(S) // something
+#else
+#define Q3DStudio_LOG_EVENT(S)
+#endif
+
+using uic::runtime::IApplicationCore;
+using uic::runtime::IApplication;
+using namespace qt3ds;
+
+// forward declaration of exported lua global functions
+namespace __SLuaEngineImpl_Static_Global_Lua_Exporter_Declaration__ {
+ static int Output(lua_State *inLuaState);
+ static int GetScreenInformation(lua_State *inLuaState);
+ static int GetElapsedTime(lua_State *inLuaState);
+ static int GetMousePosition(lua_State *inLuaState);
+ static int GetMultitouch(lua_State *inLuaState);
+ static int GetLuaTable(lua_State *inLuaState);
+ static int GetDirectory(lua_State *inLuaState);
+ static int SetTextureData(lua_State *inLuaState);
+ static int TestSetTextureData(lua_State *inLuaState);
+ static int LoadImages(lua_State *inLuaState);
+ static int MeasureText(lua_State *inLuaState);
+ static int PlayToTime(lua_State *inLuaState);
+ static int GetSCXMLInterpreter(lua_State *inLuaState);
+ static int GetEventSystem(lua_State *inLuaState);
+ static int IsPresentationActive(lua_State *inLuaState);
+ static int SetPresentationActive(lua_State *inLuaState);
+ static int GetPresentationSize(lua_State *inLuaState);
+ static int GetDisplayedSize(lua_State *inLuaState);
+ static int GetCameraBounds(lua_State *inLuaState);
+ static int PositionToScreen(lua_State *inLuaState);
+ static int ScreenToPosition(lua_State *inLuaState);
+ static int ElementAt(lua_State *inLuaState);
+ static int FacePosition(lua_State *inLuaState);
+ static int GetMillisecondsSinceLastFrame(lua_State *inLuaState);
+ static int PlaySounds(lua_State *inLuaState);
+ static int CreateMeshBuffer(lua_State *inLuaState);
+}
+
+using namespace __SLuaEngineImpl_Static_Global_Lua_Exporter_Declaration__;
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+// for unique addresses to be used as keys for Lua Registry
+const INT32 KEY_PRESENTATION = 1;
+const INT32 KEY_BEHAVIORS = 2;
+const INT32 KEY_EVENTDATA_LIST = 4;
+const INT32 KEY_CHANGEDATA_LIST = 5;
+const INT32 KEY_CALLBACKS = 6;
+const INT32 KEY_REGISTEREDCALLBACKS = 7;
+
+const char *KEY_ELEMENT = "element";
+const char *KEY_SELF = "self";
+const char *KEY_SCRIPT_INDEX = "__scriptIndex";
+const char *KEY_ONINITIALIZE = "onInitialize";
+const char *KEY_ONACTIVATE = "onActivate";
+const char *KEY_ONDEACTIVATE = "onDeactivate";
+const char *KEY_ONUPDATE = "onUpdate";
+// extern const char* KEY_ONSLIDEEXIT = "onSlideExit";
+// extern const char* KEY_ONSLIDEENTER = "onSlideEnter";
+
+const THashValue HASH_ONINITIALIZE = CHash::HashEventCommand(KEY_ONINITIALIZE);
+const THashValue HASH_ONACTIVATE = CHash::HashEventCommand(KEY_ONACTIVATE);
+const THashValue HASH_ONDEACTIVATE = CHash::HashEventCommand(KEY_ONDEACTIVATE);
+const THashValue HASH_ONUPDATE = CHash::HashEventCommand(KEY_ONUPDATE);
+// extern const THashValue HASH_ONSLIDEEXIT = CHash::HashEventCommand( KEY_ONSLIDEEXIT );
+// extern const THashValue HASH_ONSLIDEENTER = CHash::HashEventCommand( KEY_ONSLIDEENTER );
+
+const UINT32 LENGTH_KEY_ELEMENT = (UINT32)::strlen(KEY_ELEMENT);
+const UINT32 LENGTH_KEY_SELF = (UINT32)::strlen(KEY_SELF);
+const UINT32 LENGTH_KEY_SCRIPT_INDEX = (UINT32)::strlen(KEY_SCRIPT_INDEX);
+const UINT32 LENGTH_KEY_ONINITIALIZE = (UINT32)::strlen(KEY_ONINITIALIZE);
+const UINT32 LENGTH_KEY_ONACTIVATE = (UINT32)::strlen(KEY_ONACTIVATE);
+const UINT32 LENGTH_KEY_ONDEACTIVATE = (UINT32)::strlen(KEY_ONDEACTIVATE);
+const UINT32 LENGTH_KEY_ONUPDDATE = (UINT32)::strlen(KEY_ONUPDATE);
+// extern const UINT32 LENGTH_KEY_ONSLIDEEXIT = ::strlen( KEY_ONSLIDEEXIT );
+// extern const UINT32 LENGTH_KEY_ONSLIDEENTER = ::strlen( KEY_ONSLIDEENTER );
+
+const char *SCALE_MODE_FREE = "Free";
+const char *SCALE_MODE_FIXED = "Fixed";
+const char *SCALE_MODE_ASPECT = "Aspect";
+const char *SCALE_MODE_UNINIT = "Unknown";
+
+const THashValue HASH_PROPERTYNAME_FLOAT = CHash::HashString("float");
+const THashValue HASH_PROPERTYNAME_FLOAT3 = CHash::HashString("float3");
+const THashValue HASH_PROPERTYNAME_LONG = CHash::HashString("long");
+const THashValue HASH_PROPERTYNAME_COLOR4 = CHash::HashString("color4");
+const THashValue HASH_PROPERTYNAME_BOOL = CHash::HashString("bool");
+const THashValue HASH_PROPERTYNAME_STRING = CHash::HashString("string");
+
+struct SLuaEngineImpl;
+namespace __SLuaEngineImpl_Basic_Structs__ {
+ struct SLuaTimeCallback : public IComponentTimeOverrideFinishedCallback
+ {
+ SLuaEngineImpl &m_Engine;
+ CPresentation &m_Presentation;
+ TElement *m_Element;
+ UVariant m_CallbackVariant;
+ INT32 m_CallbackId;
+ bool m_Fired;
+ SLuaTimeCallback(SLuaEngineImpl &inEngine, INT32 inCbackId, CPresentation &inPresentation,
+ TElement *inElement)
+ : m_Engine(inEngine)
+ , m_CallbackId(inCbackId)
+ , m_Presentation(inPresentation)
+ , m_Element(inElement)
+ , m_Fired(false)
+ {
+ }
+ ~SLuaTimeCallback() {}
+
+ void OnTimeFinished() override
+ {
+ m_CallbackVariant.m_INT32 = m_CallbackId;
+ m_Presentation.FireCommand(COMMAND_CUSTOMCALLBACK, m_Element, &m_CallbackVariant);
+ m_Fired = true;
+ }
+
+ void Release() override;
+ };
+
+ struct SImageLoadCallback : public uic::render::IImageLoadListener
+ {
+ NVFoundationBase &m_Foundation;
+ SLuaEngineImpl *m_Engine; // Note the engine may be null in the case of system shutdown.
+ QT3DSU32 m_CallbackId;
+ QT3DSI32 m_RefCount;
+ SImageLoadCallback(NVFoundationBase &fnd, SLuaEngineImpl &inEngine, QT3DSU32 inId)
+ : m_Foundation(fnd)
+ , m_Engine(&inEngine)
+ , m_CallbackId(inId)
+ , m_RefCount(0)
+ {
+ }
+
+ void OnImageLoadComplete(CRegisteredString inPath,
+ uic::render::ImageLoadResult::Enum inResult) override;
+
+ void OnImageBatchComplete(QT3DSU64) override {}
+
+ void addRef() override { qt3ds::foundation::atomicIncrement(&m_RefCount); }
+
+ void release() override;
+ };
+
+ struct SLuaEngineListener : public uic::state::debugger::ILuaSideListener
+ {
+ NVFoundationBase &m_Foundation;
+ SLuaEngineImpl &m_Engine;
+ QT3DSI32 m_RefCount;
+ SLuaEngineListener(NVFoundationBase &fnd, SLuaEngineImpl &eng)
+ : m_Foundation(fnd)
+ , m_Engine(eng)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() { atomicIncrement(&m_RefCount); }
+ void release()
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0)
+ NVDelete(m_Foundation, this);
+ }
+
+ void OnBreak() override;
+ };
+
+ struct SLuaPerfEvent
+ {
+ qt3ds::QT3DSU64 m_Time;
+ eastl::string m_Name;
+ };
+
+ struct SLuaFunctionResult
+ {
+ BOOL m_HasFunction;
+ BOOL m_PCallError;
+ SLuaFunctionResult()
+ : m_HasFunction(false)
+ , m_PCallError(false)
+ {
+ }
+ SLuaFunctionResult(BOOL inHS, BOOL inPC)
+ : m_HasFunction(inHS)
+ , m_PCallError(inPC)
+ {
+ }
+ };
+
+ struct SLuaStackScope
+ {
+ lua_State *m_LuaState;
+ int m_Top;
+ SLuaStackScope(lua_State *s)
+ : m_LuaState(s)
+ , m_Top(lua_gettop(s))
+ {
+ }
+ ~SLuaStackScope() { lua_settop(m_LuaState, m_Top); }
+ };
+
+ struct LuaScopedLock
+ {
+ qt3ds::foundation::Mutex *m_Mutex;
+
+ LuaScopedLock(qt3ds::foundation::Mutex *mtx)
+ : m_Mutex(mtx)
+ {
+ if (m_Mutex)
+ m_Mutex->lock();
+ }
+
+ ~LuaScopedLock()
+ {
+ if (m_Mutex)
+ m_Mutex->unlock();
+ }
+ };
+
+ struct SUserFile
+ {
+ bool m_EOF;
+ FILE *m_File;
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> m_InputStream;
+ eastl::vector<char8_t> m_Buffer;
+
+ SUserFile()
+ : m_File(NULL)
+ , m_EOF(true)
+ {
+ }
+ SUserFile(FILE *f)
+ : m_File(f)
+ , m_EOF(false)
+ {
+ }
+ SUserFile(uic::render::IRefCountedInputStream &stream)
+ : m_File(NULL)
+ , m_InputStream(stream)
+ , m_EOF(false)
+ {
+ }
+ ~SUserFile()
+ {
+ if (m_File)
+ fclose(m_File);
+ }
+
+ size_t read(void *buffer, size_t len)
+ {
+ size_t retval = 0;
+ char *writeBuffer = (char *)buffer;
+ if (m_Buffer.size()) {
+ QT3DSU32 amount = qt3ds::NVMin((QT3DSU32)m_Buffer.size(), (QT3DSU32)len);
+ memcpy(writeBuffer, m_Buffer.data(), amount);
+ m_Buffer.erase(m_Buffer.begin(), m_Buffer.begin() + amount);
+ writeBuffer += amount;
+ len -= amount;
+ retval += amount;
+ }
+ if (len) {
+ qt3ds::QT3DSU32 amountRead = 0;
+ if (m_InputStream)
+ amountRead = m_InputStream->Read(
+ qt3ds::foundation::toDataRef((qt3ds::QT3DSU8 *)writeBuffer, (qt3ds::QT3DSU32)len));
+ else if (m_File)
+ amountRead = (QT3DSU32)fread(writeBuffer, 1, len, m_File);
+
+ retval += amountRead;
+ m_EOF = amountRead == 0;
+ }
+ return retval;
+ }
+
+ void unget(int c)
+ {
+ if (c != EOF)
+ m_Buffer.push_back((char8_t)c);
+ }
+
+ bool eof() const { return m_EOF; }
+
+ static bool is_white(char d) { return d == '\n' || d == ' ' || d == '\r' || d == '\t'; }
+
+ // read till not white, discarding everything that is white
+ void read_till_not_white()
+ {
+ char data = ' ';
+ while (!eof() && is_white(data)) {
+ read(&data, 1);
+ }
+ if (!eof())
+ m_Buffer.push_back(data);
+ }
+
+ // read till we find whitespace or eof
+ void read_till_white()
+ {
+ char data = '1';
+ while (!eof() && is_white(data) == false) {
+ read(&data, 1);
+ m_Buffer.push_back(data);
+ }
+ }
+
+ int read_number(float &outNum)
+ {
+ outNum = 0;
+ // read in whitespace till we have data
+ // then read till we get whitespace or eof
+ read_till_not_white();
+ read_till_white();
+ if (m_Buffer.size() > 0) {
+ // now add a null character
+ m_Buffer.push_back(0);
+ double d = strtod(m_Buffer.data(), NULL);
+ // get rid of null character
+ m_Buffer.resize(m_Buffer.size() - 1);
+ if (!eof())
+ m_Buffer.erase(m_Buffer.begin(), m_Buffer.begin() + m_Buffer.size() - 1);
+ else
+ m_Buffer.clear();
+ outNum = static_cast<float>(d);
+ return 1;
+ }
+ return 0;
+ }
+ };
+}
+using namespace __SLuaEngineImpl_Basic_Structs__;
+#define LUA_ENGINE_MULTITHREAD_PROTECT_METHOD LuaScopedLock __locker(m_MultithreadedMutex);
+
+int CScriptEngineCallFunctionArgRetriever::RetrieveArgument(lua_State *inState)
+{
+ int theRet = 0;
+ if (m_ArgumentString && *m_ArgumentString) {
+ eastl::string temp(m_ArgumentString);
+ temp.insert(0, "return ");
+ if (luaL_loadstring(inState, temp.c_str()) != 0) {
+ theRet = -1;
+ } else {
+ theRet = lua_pcall(inState, 0, 1, 0) ? -1 : 1;
+ }
+ }
+ return theRet;
+}
+
+eastl::string CScriptEngineCallFunctionArgRetriever::GetArgDescription()
+{
+ eastl::string temp(m_ArgumentString);
+ temp.insert(0, "return ");
+ return temp;
+}
+
+namespace {
+ uic::render::IInputStreamFactory *g_InputStreamFactory;
+
+ void *lua_user_fopen(const char *filename, const char *mode, char *absfilename)
+ {
+ Q3DStudio_UNREFERENCED_PARAMETER(mode);
+ // Ensure this isn't a shared library of sorts.
+ /*size_t len = strlen( filename );
+ if ( len > 2 )
+ {
+ size_t end = len - 3;
+ const char* ext = filename + end;
+ //Do not use the abstraction for shared libraries or dlls.
+ if ( strcmp( ext, "dll" ) == 0
+ || strcmp( ext, ".so" ) == 0
+ || strcmp( ext, "lib" ) == 0 )
+ {
+ FILE* testFile = fopen( filename, mode );
+ if ( testFile )
+ {
+ return new SUserFile( testFile );
+ }
+ return NULL;
+ }
+ }*/
+ uic::render::IRefCountedInputStream *stream =
+ g_InputStreamFactory->GetStreamForFile(filename, true);
+ if (stream) {
+ if (absfilename) {
+ QString tempStr;
+ if (g_InputStreamFactory->GetPathForFile(filename, tempStr)) {
+ strcpy(absfilename, tempStr.toUtf8().data());
+ }
+ }
+ return new SUserFile(*stream);
+ }
+
+ return NULL;
+ }
+
+ int lua_user_fclose(void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ delete theFile;
+ return 0;
+ }
+
+ int lua_user_getc(void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile) {
+ char8_t temp;
+ int numRead = (int)theFile->read(&temp, 1);
+ if (numRead == 1)
+ return temp;
+ }
+ return -1;
+ }
+ int lua_user_ungetc(int c, void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ theFile->unget(c);
+ return 0;
+ }
+
+ char *lua_user_fgets(char *ptr, int count, void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile && theFile->read(ptr, count))
+ return ptr;
+ return NULL;
+ }
+
+ size_t lua_user_fread(void *ptr, size_t size, size_t count, void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ size_t amount = size * count;
+ if (theFile)
+ return theFile->read(ptr, amount);
+ return 0;
+ }
+
+ int lua_user_ferror(void *) { return 0; }
+
+ int lua_user_feof(void *file)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ return theFile->eof();
+ return 0;
+ }
+
+ int lua_user_fread_number(void *file, lua_Number *d)
+ {
+ SUserFile *theFile = reinterpret_cast<SUserFile *>(file);
+ if (theFile)
+ return theFile->read_number(*d);
+ return 0;
+ }
+
+ void lua_user_clearerr(void *) { (void)0; }
+}
+
+namespace {
+
+ enum EPathType { eLuaPath, eCPath };
+ const char *const sm_PathType[] = { "path", "cpath" };
+ const char *const sm_PathTypeExtension[] = {
+ "lua",
+#ifdef _WIN32
+ "dll",
+#else
+ "so"
+#endif
+ };
+ static void AppendLuaPackagePath(lua_State *state, const eastl::string &inPath,
+ EPathType inPathType)
+ {
+ if (state == NULL)
+ return;
+ SLuaStackScope __selfScope(state);
+ lua_getglobal(state, "package");
+ lua_getfield(state, -1, sm_PathType[inPathType]);
+ eastl::string cur_path(lua_tostring(state, -1));
+ cur_path.append(";");
+ cur_path.append(inPath.c_str());
+ cur_path.append("/?.");
+ cur_path.append(sm_PathTypeExtension[inPathType]);
+ lua_pop(state, 1);
+ lua_pushstring(state, cur_path.c_str());
+ lua_setfield(state, -2, sm_PathType[inPathType]);
+ }
+
+ static void AppendAdditionalLuaPackagePath(lua_State *state, const eastl::string &inPath)
+ {
+ AppendLuaPackagePath(state, inPath, eCPath);
+
+ eastl::string scriptsDir;
+ CFileTools::CombineBaseAndRelative(inPath.c_str(), "scripts", scriptsDir);
+ AppendLuaPackagePath(state, scriptsDir, eCPath);
+
+ // Add in additional search directory for specific platform
+ eastl::string scriptsPlatformDir;
+ CFileTools::CombineBaseAndRelative(scriptsDir.c_str(), System::getPlatformStr(),
+ scriptsPlatformDir);
+ AppendLuaPackagePath(state, scriptsPlatformDir, eCPath);
+ }
+}
+
+namespace {
+
+ static void MapPresentationToScriptIndex(lua_State *state, IPresentation &pres, int idx)
+ {
+ SLuaStackScope __scope(state);
+ lua_getfield(state, LUA_REGISTRYINDEX, "__script_index_to_presentation");
+ if (lua_isnil(state, -1)) {
+ lua_pop(state, 1);
+ lua_newtable(state);
+ lua_pushvalue(state, -1);
+ lua_setfield(state, LUA_REGISTRYINDEX, "__script_index_to_presentation");
+ }
+ // table is on the top of the stack
+ lua_pushinteger(state, idx); // table key
+ lua_pushlightuserdata(state, &pres); // table value
+ lua_settable(state, -3);
+ }
+
+ static IPresentation *GetPresentationFromScriptIndex(lua_State *state, int idx)
+ {
+ SLuaStackScope __scope(state);
+ lua_getfield(state, LUA_REGISTRYINDEX, "__script_index_to_presentation");
+ if (lua_istable(state, -1)) {
+ lua_pushinteger(state, idx);
+ lua_gettable(state, -2);
+ if (lua_islightuserdata(state, -1))
+ return reinterpret_cast<IPresentation *>(lua_touserdata(state, -1));
+ }
+ return NULL;
+ }
+
+ static int WriteLuaData(lua_State *, const void *p, size_t sz, void *ud)
+ {
+ qt3ds::foundation::MemoryBuffer<> &theWriter =
+ *reinterpret_cast<qt3ds::foundation::MemoryBuffer<> *>(ud);
+ theWriter.write((const QT3DSU8 *)p, (QT3DSU32)sz);
+ return 0;
+ }
+
+ static void *MemoryAllocator(void *inUserData, void *inPointer, size_t inOldSize,
+ size_t inNewSize)
+ {
+ Q3DStudio_UNREFERENCED_PARAMETER(inUserData);
+
+ if (inNewSize == 0) {
+ Q3DStudio_free(inPointer, INT8, inOldSize);
+ return NULL;
+ } else
+ return Q3DStudio_reallocate_desc(inPointer, INT8, inOldSize, inNewSize, "Lua");
+ }
+
+ static void GetLoadedBuffersTable(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "loadedbuffers");
+ if (lua_isnil(inLuaState, -1)) {
+ lua_pop(inLuaState, 1);
+ lua_newtable(inLuaState);
+ lua_pushvalue(inLuaState, -1);
+ lua_setfield(inLuaState, LUA_REGISTRYINDEX, "loadedbuffers");
+ }
+ }
+
+ static int ErrorChannel(lua_State *inLuaState)
+ {
+ qCCritical(qt3ds::INVALID_OPERATION) << "Lua: ErrorChannel: " << lua_tostring(inLuaState, -1);
+ lua_pop(inLuaState, 1);
+ return 0;
+ }
+
+ static int EnsureScriptIsLoaded(lua_State *inLuaState, const char *inRelativePath,
+ const char *inBasePath, eastl::string &scriptBuffer,
+ qt3ds::foundation::IPerfTimer &inPerfTimer,
+ uic::render::IInputStreamFactory &inStreamFactory,
+ eastl::vector<char8_t> &inLoadVec)
+ {
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(inBasePath, inRelativePath,
+ scriptBuffer);
+ qt3ds::foundation::CFileTools::ToPlatformPath(scriptBuffer);
+ int theError = 0;
+ // The lua system expects file to begin with @.
+ scriptBuffer.insert(scriptBuffer.begin(), '@');
+ const char *theFullPath = scriptBuffer.c_str();
+ GetLoadedBuffersTable(inLuaState);
+ lua_getfield(inLuaState, -1, inRelativePath);
+ if (lua_isnil(inLuaState, -1)) {
+ SStackPerfTimer __perfTimer(inPerfTimer, "Load Lua File");
+ lua_pop(inLuaState, 1);
+ uic::render::IInputStreamFactory &theFactory(inStreamFactory);
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream =
+ theFactory.GetStreamForFile(inRelativePath, true);
+
+ inLoadVec.clear();
+ if (theStream) {
+ qt3ds::QT3DSU8 buf[1024];
+ for (size_t amount = theStream->Read(toDataRef(buf, 1024)); amount;
+ amount = theStream->Read(toDataRef(buf, 1024)))
+ inLoadVec.insert(inLoadVec.end(), (char8_t *)buf, (char8_t *)buf + amount);
+ }
+ if (inLoadVec.empty() == false) {
+ // Load the Lua script
+ theError = luaL_loadbuffer(inLuaState, static_cast<const char *>(&inLoadVec[0]),
+ static_cast<size_t>(inLoadVec.size()), theFullPath);
+ lua_pushvalue(inLuaState, -1);
+ lua_setfield(inLuaState, -3, inRelativePath);
+ lua_insert(inLuaState, -2);
+ lua_pop(inLuaState, 1);
+ } else {
+ lua_pop(inLuaState, 1);
+ theError = -1;
+ }
+ }
+ return theError;
+ }
+}
+
+eastl::vector<eastl::string> g_AdditionalSharedLibraryPaths;
+TLuaLibraryLoader LoadLuaLibraries = luaL_openlibs; ///< Defaults to open all lua libraries
+lua_user_file_io g_engine_file_io;
+lua_Alloc g_engine_alloc = MemoryAllocator;
+
+struct SLuaEngineImpl : public CLuaEngine
+{
+ typedef eastl::vector<eastl::string> TStringList;
+ qt3ds::NVFoundationBase &m_Foundation;
+ lua_State *m_LuaState;
+
+ IApplication *m_Application;
+ IApplicationCore *m_ApplicationCore;
+
+ eastl::vector<SImageLoadCallback *> m_ImageLoadingCallbacks;
+ qt3ds::foundation::Pool<SLuaTimeCallback> m_TimeCallbackPool;
+ TCallbackDataList m_EventCallbackDataList; ///< The list of event callback data
+ TCallbackDataList m_ChangeCallbackDataList; ///< The list of change callback data
+ INT32 m_CallbackIndex;
+
+ INT32 m_ServerPort; ///<port number of remote debugger
+ eastl::string m_ScriptString;
+ eastl::string m_ServerIP;
+ NVScopedRefCounted<uic::state::debugger::ILuaDebugger> m_LuaDebugger;
+ NVScopedRefCounted<SLuaEngineListener> m_LuaListener;
+
+ lua_State *m_PreloadState;
+ TStringList m_PreloadScripts;
+ qt3ds::foundation::Sync m_PreloadSync;
+ eastl::string m_PreloadProjectDir;
+ qt3ds::foundation::Mutex m_PreloadMutex;
+ qt3ds::foundation::Mutex *m_MultithreadedMutex;
+
+ eastl::vector<char8_t> m_LoadVec;
+ bool m_LuaPathInitialized;
+ QT3DSI32 mRefCount;
+
+ qt3ds::QT3DSU32 m_PerfStackIndex;
+ eastl::string m_PerfNameBuilder;
+ bool m_ProfileActive;
+ eastl::vector<SLuaPerfEvent> m_PerfStack;
+
+ SLuaEngineImpl(NVFoundationBase &fnd, ITimeProvider &inTimeProvider);
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ // functions from IScriptBridge
+ void EnableMultithreadedAccess() override;
+ void DisableMultithreadedAccess() override;
+
+ void SetApplicationCore(uic::runtime::IApplicationCore &inApplication) override;
+ void SetApplication(uic::runtime::IApplication &inApplication) override;
+
+ void BeginPreloadScripts(const eastl::vector<const char *> &inScripts,
+ uic::render::IThreadPool &inThreadPool,
+ const char *inProjectDir) override;
+ void EndPreloadScripts() override;
+ eastl::vector<eastl::string> GetLoadedScripts() override;
+
+ void LoadScript(IPresentation *inPresentation, TElement *inOwner, const CHAR *inName) override;
+ Q3DStudio::INT32 InitializeApplicationBehavior(const char *inProjectRelativePath) override;
+
+ void ProcessFrameCallbacks(IPresentation *inPresentation) override;
+ void ExecuteApplicationScriptFunction(Q3DStudio::INT32 inApp, const char *inFnName) override;
+ void CallFunction(const char *behavior, const char *handler,
+ CScriptEngineCallFunctionArgRetriever &inArgRetriever) override;
+
+ void ProcessSignal(IPresentation *inPresentation,
+ const SEventCommand &inCommand) override {}
+ void ProcessCustomActions(IPresentation *inPresentation,
+ const SEventCommand &inCommand) override;
+ void ProcessCustomCallback(IPresentation *inPresentation,
+ const SEventCommand &inCommand) override;
+
+ void SetTableForElement(TElement &inElement, ILuaScriptTableProvider &inProvider) override;
+ void SetAttribute(const char *element, const char *attName, const char *value) override;
+ void FireEvent(const char *element, const char *evtName) override;
+
+ void GotoSlide(const char *component, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs) override;
+ void GotoSlideRelative(const char *component, bool inNextSlide, bool inWrap,
+ const SScriptEngineGotoSlideArgs &inArgs) override;
+
+ void SetPresentationAttribute(const char *presId, const char *attName,
+ const char *attValue) override;
+
+ bool PlaySoundFile(const char *soundPath) override;
+
+ void AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction) override;
+ void EnableDebugging(uic::state::debugger::IMultiProtocolSocket &socket) override;
+ void EnableProfiling() override;
+ void StepGC() override;
+
+ // functions from CLuaEngine
+ uic::state::IStateInterpreter *CreateStateMachine(const char8_t *inPath,
+ const char8_t *inId,
+ const char8_t *inDatamodelFunction) override;
+ void PreInitialize() override;
+ void Initialize() override;
+ void Shutdown(qt3ds::NVFoundationBase &inFoundation) override;
+
+ // local functions
+ void ProcessFrameCallbacksHelper(TElementList &inElementList, const CHAR *inFunctionName);
+ SLuaFunctionResult CallFunction(const INT32 inScriptIndex, const CHAR *inFunctionName);
+ void CallElementCallback(TElement &inElement, const CHAR *inFunctionName);
+ INT32 RegisterCallback(lua_State *inLuaState);
+ void ReleaseCallback(INT32 incback);
+ void ReleaseCallback(SLuaTimeCallback &inCallbkac);
+ void PrepareToLoadFile();
+ int PCall(int argcount, int retcount, int errorIndex);
+ void OnBreak();
+ void CallImageLoadComplete(const char *inPath, bool inSucceeded, qt3ds::QT3DSU32 inCallbackId);
+ void CallbackFinished(SImageLoadCallback &inCallback);
+};
+
+namespace __SLuaEngineImpl_Static_Calls__ {
+ static void PreloadFunctionCall(void *inEngine)
+ {
+ SLuaEngineImpl *theEngine = reinterpret_cast<SLuaEngineImpl *>(inEngine);
+ eastl::vector<char8_t> loadBuffer;
+ eastl::string pathBuffer;
+ SStackPerfTimer __perfTimer(
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer(),
+ "Preload Lua Data");
+ {
+ // First attempt to load all compiled lua scripts.
+ eastl::string theLuaBinFile = theEngine->m_PreloadProjectDir;
+ CFileTools::CombineBaseAndRelative(theEngine->m_PreloadProjectDir.c_str(),
+ "binary/compiledlua.bin", theLuaBinFile);
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theBinFile =
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore()
+ .GetInputStreamFactory()
+ .GetStreamForFile(theLuaBinFile.c_str());
+ if (theBinFile) {
+ qCInfo(TRACE_INFO, "Lua - Found binary file, loading scripts");
+ eastl::vector<eastl::pair<eastl::string, QT3DSU32>> theDirectory;
+ QT3DSU32 numDirFiles = 0;
+ theBinFile->Read(numDirFiles);
+ theDirectory.resize(numDirFiles);
+ for (QT3DSU32 idx = 0, end = numDirFiles; idx < end; ++idx) {
+ QT3DSU32 strLen = 0;
+ theBinFile->Read(strLen);
+ theDirectory[idx].first.resize(strLen);
+ theBinFile->Read((QT3DSU8 *)&theDirectory[idx].first[0], strLen);
+ theBinFile->Read(theDirectory[idx].second);
+ }
+ QT3DSU32 binSectionSize = 0;
+ theBinFile->Read(binSectionSize);
+ eastl::vector<char8_t> theData;
+ theData.resize(binSectionSize);
+ theBinFile->Read(theData.data(), binSectionSize);
+ SLuaStackScope theScope(theEngine->m_PreloadState);
+ GetLoadedBuffersTable(theEngine->m_PreloadState);
+ for (QT3DSU32 idx = 0, end = numDirFiles; idx < end; ++idx) {
+ eastl::pair<eastl::string, QT3DSU32> dirEntry = theDirectory[idx];
+ QT3DSU32 entrySize = 0;
+ if (idx < end - 1)
+ entrySize = theDirectory[idx + 1].second - dirEntry.second;
+ else
+ entrySize = binSectionSize - dirEntry.second;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(
+ theEngine->m_PreloadProjectDir.c_str(), dirEntry.first.c_str(), pathBuffer);
+ qt3ds::foundation::CFileTools::ToPlatformPath(pathBuffer);
+ pathBuffer.insert(0, "@");
+
+ luaL_loadbuffer(theEngine->m_PreloadState,
+ static_cast<const char *>(&theData[dirEntry.second]), entrySize,
+ pathBuffer.c_str());
+ lua_setfield(theEngine->m_PreloadState, -2, dirEntry.first.c_str());
+ }
+ }
+ }
+
+ for (QT3DSU32 idx = 0, end = theEngine->m_PreloadScripts.size(); idx < end; ++idx) {
+ SLuaStackScope theScope(theEngine->m_PreloadState);
+ EnsureScriptIsLoaded(
+ theEngine->m_PreloadState, theEngine->m_PreloadScripts[idx].c_str(),
+ theEngine->m_PreloadProjectDir.c_str(), pathBuffer,
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer(),
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetInputStreamFactory(),
+ loadBuffer);
+ }
+ theEngine->m_PreloadSync.set();
+ }
+
+ static void ProfileHook(lua_State *inLuaState, lua_Debug *ar)
+ {
+ // First check if valid function
+ // We only profile pure lua code.
+ lua_Debug stackInfo;
+ if (lua_getstack(inLuaState, 0, &stackInfo) && lua_getinfo(inLuaState, "nSl", &stackInfo)) {
+ bool validFunction = (ar->event == LUA_HOOKCALL || ar->event == LUA_HOOKRET)
+ && !qt3ds::foundation::isTrivial(stackInfo.source) && stackInfo.source[0] == '@';
+
+ if (!validFunction)
+ return;
+
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ theEngine->m_PerfNameBuilder.assign(stackInfo.source + 1);
+ eastl::string::size_type slashPos = theEngine->m_PerfNameBuilder.find_last_of("\\/");
+ if (slashPos != eastl::string::npos)
+ theEngine->m_PerfNameBuilder.erase(theEngine->m_PerfNameBuilder.begin(),
+ theEngine->m_PerfNameBuilder.begin() + slashPos
+ + 1);
+ theEngine->m_PerfNameBuilder.append(":");
+ char buf[24];
+ sprintf(buf, "%d", stackInfo.linedefined);
+ theEngine->m_PerfNameBuilder.append(buf);
+ size_t currentPerfStackSize = theEngine->m_PerfStack.size();
+ if (ar->event == LUA_HOOKCALL) {
+ while (theEngine->m_PerfStackIndex >= currentPerfStackSize) {
+ theEngine->m_PerfStack.push_back(SLuaPerfEvent());
+ ++currentPerfStackSize;
+ }
+
+ SLuaPerfEvent &backEvent = theEngine->m_PerfStack[theEngine->m_PerfStackIndex];
+ ++theEngine->m_PerfStackIndex;
+ backEvent.m_Time = qt3ds::foundation::Time::getCurrentCounterValue();
+ backEvent.m_Name.assign(theEngine->m_PerfNameBuilder);
+ } else {
+
+ if (theEngine->m_ApplicationCore != NULL && theEngine->m_PerfStackIndex > 0
+ && theEngine->m_PerfStackIndex <= currentPerfStackSize) {
+ qt3ds::foundation::IPerfTimer &theTimer =
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ SLuaPerfEvent &backEvent =
+ theEngine->m_PerfStack[theEngine->m_PerfStackIndex - 1];
+ --theEngine->m_PerfStackIndex;
+ theTimer.Update(backEvent.m_Name.c_str(),
+ qt3ds::foundation::Time::getCurrentCounterValue()
+ - backEvent.m_Time);
+ }
+ }
+ }
+ }
+
+ static int ParseSCXML(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+
+ uic::state::debugger::IDebugger *theDebugger = NULL;
+ if (theEngine) {
+ theDebugger = &theEngine->m_Application->GetStateDebugger();
+ }
+ return uic::state::ILuaScriptContext::ParseSCXML(
+ inLuaState, theDebugger, theEngine->m_Foundation,
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetStringTable());
+ }
+}
+using namespace __SLuaEngineImpl_Static_Calls__;
+
+namespace __SLuaEngineImpl_Basic_Structs__ {
+ void SLuaTimeCallback::Release()
+ {
+ if (!m_Fired)
+ m_Engine.ReleaseCallback(m_CallbackId);
+ m_Engine.ReleaseCallback(*this);
+ }
+
+ void SImageLoadCallback::OnImageLoadComplete(CRegisteredString inPath,
+ uic::render::ImageLoadResult::Enum inResult)
+ {
+ if (m_Engine) {
+ m_Engine->CallImageLoadComplete(
+ inPath, inResult == uic::render::ImageLoadResult::Succeeded, m_CallbackId);
+ }
+ }
+
+ void SImageLoadCallback::release()
+ {
+ qt3ds::foundation::atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ if (m_Engine) {
+ m_Engine->ReleaseCallback(m_CallbackId);
+ m_Engine->CallbackFinished(*this);
+ }
+ NVDelete(m_Foundation, this);
+ }
+ }
+
+ void SLuaEngineListener::OnBreak() { m_Engine.OnBreak(); }
+}
+//==============================================================================
+/**
+ * Constructor
+ */
+SLuaEngineImpl::SLuaEngineImpl(NVFoundationBase &fnd, ITimeProvider &inTimeProvider)
+ : m_Foundation(fnd)
+ , m_LuaState(NULL)
+ , m_ServerPort(0)
+ , m_EventCallbackDataList(0, 0, "EventCallbackList")
+ , m_ChangeCallbackDataList(0, 0, "ChangeCallbackList")
+ , m_CallbackIndex(0)
+ , m_Application(NULL)
+ , m_ApplicationCore(NULL)
+ , m_LuaPathInitialized(false)
+ , m_PreloadState(NULL)
+ , m_PreloadSync(fnd.getAllocator())
+ , m_PreloadMutex(fnd.getAllocator())
+ , m_MultithreadedMutex(NULL)
+ , m_PerfStackIndex(0)
+ , m_ProfileActive(false)
+ , mRefCount(0)
+{
+ m_LuaState = lua_newstate(g_engine_alloc, NULL);
+ Q3DStudio_ASSERT(m_LuaState);
+
+ lua_gc(m_LuaState, LUA_GCSTOP, 0);
+
+ // Override this function pointer for customization of loading of lua libraries.
+ // Default uses luaL_openlibs which opens all libraries found in linit.c
+ LoadLuaLibraries(m_LuaState);
+
+ lua_newtable(m_LuaState);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // Reg(1) = BehaviorsT
+
+ lua_pushlightuserdata(m_LuaState, &m_EventCallbackDataList);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX,
+ KEY_EVENTDATA_LIST); // Reg(3) = &m_EventCallbackDataList
+
+ lua_pushlightuserdata(m_LuaState, &m_ChangeCallbackDataList);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX,
+ KEY_CHANGEDATA_LIST); // Reg(4) = &m_ChangeCallbackDataList
+
+ // Reg(5) = Global functions temporary parking lot for registerForEvent and registerForChange
+ lua_newtable(m_LuaState);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS);
+
+ // Callbacks table for callbacks sent from script.
+ lua_newtable(m_LuaState);
+ lua_rawseti(m_LuaState, LUA_REGISTRYINDEX, KEY_REGISTEREDCALLBACKS);
+
+ lua_pushlightuserdata(m_LuaState, this);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+
+ lua_getglobal(m_LuaState, "math"); // 2 = "math" table
+ lua_pushstring(m_LuaState, "randomseed"); // 3 = "randomseed"
+ lua_rawget(m_LuaState, -2); // 3 = math.randomseed function
+ lua_pushinteger(m_LuaState, static_cast<INT32>(inTimeProvider.GetCurrentTimeMicroSeconds()));
+ lua_pcall(m_LuaState, 1, 0, 0); // [size = 2]
+
+ lua_settop(m_LuaState, 0);
+
+ memset(&g_engine_file_io, 0, sizeof(_lua_user_file_io));
+
+ g_engine_file_io.user_fopen = lua_user_fopen;
+ g_engine_file_io.user_fclose = lua_user_fclose;
+ g_engine_file_io.user_getc = lua_user_getc;
+ g_engine_file_io.user_ungetc = lua_user_ungetc;
+ g_engine_file_io.user_fgets = lua_user_fgets;
+ g_engine_file_io.user_fread = lua_user_fread;
+ g_engine_file_io.user_ferror = lua_user_ferror;
+ g_engine_file_io.user_feof = lua_user_feof;
+ g_engine_file_io.user_fread_double = lua_user_fread_number;
+ g_engine_file_io.user_clearerr = lua_user_clearerr;
+}
+
+//==============================================================================
+/**
+ * ****************Inherited virtual functions from IScriptBridge **************
+ */
+//=============================================================================
+void SLuaEngineImpl::EnableMultithreadedAccess()
+{
+ m_MultithreadedMutex = &m_PreloadMutex;
+}
+
+void SLuaEngineImpl::DisableMultithreadedAccess()
+{
+ m_MultithreadedMutex = NULL;
+}
+
+//==============================================================================
+/**
+ * Setting package.loaders[1] = LoadFileForRequire
+ * Changed default Lua behavior and may confusing scriptors, disable it!
+ */
+/*static int LoadFileForRequire( lua_State* inLuaState )
+{
+ lua_getfield( inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine" );
+ CLuaEngine* theEngine = (CLuaEngine*)( lua_touserdata( inLuaState, -1 ) );
+ lua_pop( inLuaState, 1 );
+
+ if ( theEngine )
+ {
+ const char* modname = lua_tostring( inLuaState, -1 );
+ theEngine->m_PreloadProjectDir.assign( "./scripts/" );
+ theEngine->m_PreloadProjectDir.append( nonNull( modname ) );
+ theEngine->m_PreloadProjectDir.append( ".lua" );
+ int error = theEngine->EnsureScriptIsLoaded( inLuaState
+ , theEngine->m_PreloadProjectDir.c_str()
+ , theEngine->m_ApplicationCore->GetProjectDirectory()
+ , theEngine->m_ScriptString
+ , theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer()
+ ,
+theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetInputStreamFactory()
+ , theEngine->m_LoadVec );
+ if ( error == 0 )
+ return 1;
+ }
+
+ lua_pushnil( inLuaState );
+ return 1;
+}*/
+
+void SLuaEngineImpl::SetApplicationCore(uic::runtime::IApplicationCore &inApplication)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ m_ApplicationCore = &inApplication;
+ lua_pushlightuserdata(m_LuaState, m_Application);
+ lua_setglobal(m_LuaState, "UICApplicationCore");
+ g_InputStreamFactory = &m_ApplicationCore->GetRuntimeFactoryCore()
+ .GetUICRenderContextCore()
+ .GetInputStreamFactory();
+ // re-route lua through our file handling system. This allows us to load data from an APK file
+ // directly without needing
+ // some unpack step.
+ lua_set_file_io(&g_engine_file_io);
+ /* See comments for LoadFileForRequire
+ SLuaStackScope __scope( m_LuaState );
+ lua_getglobal( m_LuaState, "table" );
+ lua_getfield( m_LuaState, -1, "insert" );
+ lua_insert( m_LuaState, -2 );
+ lua_pop( m_LuaState, 1 );
+ lua_getglobal( m_LuaState, "package" );
+ if ( lua_istable( m_LuaState, -1 ) )
+ {
+ lua_getfield( m_LuaState, -1, "loaders" );
+ if ( lua_istable( m_LuaState, -1 ) )
+ {
+ int error;
+ lua_insert( m_LuaState, -2 );
+ lua_pop( m_LuaState, 1 );
+ lua_pushnumber( m_LuaState, 1 );
+ lua_pushcfunction( m_LuaState, LoadFileForRequire );
+ error = lua_pcall( m_LuaState, 3, 0, 0 );
+ QT3DS_ASSERT( error == 0 );
+ }
+ }*/
+}
+
+void SLuaEngineImpl::SetApplication(uic::runtime::IApplication &inApplication)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ m_Application = &inApplication;
+ lua_pushlightuserdata(m_LuaState, m_Application);
+ lua_setglobal(m_LuaState, "UICApplication");
+}
+
+// Starts preloading scripts offline. This sets m_LuaState to NULL until after EndPreloadScripts to
+// avoid multithreaded lua state access. Some calls may be queued till EndPreloadScripts
+void SLuaEngineImpl::BeginPreloadScripts(const eastl::vector<const char *> &inScripts,
+ uic::render::IThreadPool &inThreadPool,
+ const char *inProjDir)
+{
+ m_PreloadScripts.assign(inScripts.begin(), inScripts.end());
+ m_PreloadState = m_LuaState;
+ m_LuaState = NULL;
+ m_PreloadProjectDir.assign(inProjDir);
+ m_PreloadSync.reset();
+ inThreadPool.AddTask(this, PreloadFunctionCall, NULL);
+}
+
+// Ends preload, restores m_LuaState.
+void SLuaEngineImpl::EndPreloadScripts()
+{
+ qt3ds::foundation::Mutex::ScopedLock __locker(m_PreloadMutex);
+ if (m_LuaState == NULL) {
+ m_PreloadSync.wait();
+ m_LuaState = m_PreloadState;
+ m_PreloadState = NULL;
+ }
+}
+
+// Fast loading support; on save get the set of loaded scripts
+eastl::vector<eastl::string> SLuaEngineImpl::GetLoadedScripts()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ eastl::vector<eastl::string> retval;
+ SLuaStackScope theScope(m_LuaState);
+ GetLoadedBuffersTable(m_LuaState);
+ QT3DS_ASSERT(lua_type(m_LuaState, -1) == LUA_TTABLE);
+ lua_pushnil(m_LuaState);
+ eastl::vector<eastl::pair<eastl::string, QT3DSU32>> theDirectory;
+ qt3ds::foundation::MemoryBuffer<> theBuffer(ForwardingAllocator(
+ m_ApplicationCore->GetRuntimeFactoryCore().GetFoundation().getAllocator(),
+ "LuaBinaryData"));
+ while (lua_next(m_LuaState, -2)) {
+ // dup the key
+ lua_pushvalue(m_LuaState, -2);
+ const char *relativeFileName = lua_tostring(m_LuaState, -1);
+ retval.push_back(relativeFileName);
+ // pop the key
+ lua_pop(m_LuaState, 1);
+ // Dump the function
+ theDirectory.push_back(eastl::make_pair(retval.back(), (QT3DSU32)theBuffer.size()));
+ lua_dump(m_LuaState, WriteLuaData, &theBuffer);
+ // pop the value
+ lua_pop(m_LuaState, 1);
+ }
+ eastl::string tempStr;
+ CFileTools::CombineBaseAndRelative(m_ApplicationCore->GetProjectDirectory().c_str(), "binary",
+ tempStr);
+ CFileTools::CreateDir(tempStr.c_str());
+ tempStr.append("/compiledlua.bin");
+ qt3ds::foundation::CFileSeekableIOStream theStream(tempStr.c_str(), FileWriteFlags());
+ if (theStream.IsOpen() == false) {
+ qCritical(qt3ds::INTERNAL_ERROR, "Unable to open lua binary file");
+ QT3DS_ASSERT(false);
+ }
+ qt3ds::foundation::IOutStream &theOutStream(theStream);
+ theOutStream.Write((QT3DSU32)theDirectory.size());
+ for (QT3DSU32 idx = 0, end = theDirectory.size(); idx < end; ++idx) {
+ eastl::pair<eastl::string, QT3DSU32> &theEntry(theDirectory[idx]);
+ QT3DSU32 theStrLen = (QT3DSU32)theEntry.first.size();
+ if (theStrLen)
+ ++theStrLen;
+ theOutStream.Write(theStrLen);
+ if (theStrLen)
+ theOutStream.Write(theEntry.first.c_str(), theStrLen);
+ theOutStream.Write(theEntry.second);
+ }
+ theOutStream.Write((QT3DSU32)theBuffer.size());
+ theOutStream.Write(theBuffer.begin(), (QT3DSU32)theBuffer.size());
+ return retval;
+}
+
+//==============================================================================
+/**
+ * Load the lua scripts from the Lua file
+ */
+void SLuaEngineImpl::LoadScript(IPresentation *inPresentation, TElement *inBehavior,
+ const CHAR *inFileName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ qt3ds::foundation::IPerfTimer &thePerfTimer(
+ m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer());
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine: LoadScript");
+ QFileInfo fileInfo(inPresentation->GetFilePath());
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(
+ fileInfo.path().toLatin1().constData(), inFileName, m_ScriptString);
+ qt3ds::foundation::CFileTools::ToPlatformPath(m_ScriptString);
+
+ {
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine: Prepare to load file");
+ PrepareToLoadFile();
+ }
+ int theTop = lua_gettop(m_LuaState);
+ int theError = 0;
+ INT32 theScriptIndex = 0;
+ {
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine: Setup Load Script");
+
+ // The behavior table will stay at index 1 on the stack
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // 1 = BehaviorsT
+
+ // Create a new table for each behavior and set it as the "self" global entry
+ lua_pushlstring(m_LuaState, KEY_SELF, LENGTH_KEY_SELF); // 2 = "self"
+ lua_newtable(m_LuaState); // 3 = new ScriptT
+ lua_rawset(m_LuaState, LUA_GLOBALSINDEX); // [size = 1]
+
+ // Add "self.element" as a valid variable on each table
+ lua_pushlstring(m_LuaState, KEY_SELF, LENGTH_KEY_SELF); // 2 = "self"
+ lua_rawget(m_LuaState, LUA_GLOBALSINDEX); // 2 = ScriptT
+ lua_pushlstring(m_LuaState, KEY_ELEMENT, LENGTH_KEY_ELEMENT); // 3 = "element"
+ lua_pushlightuserdata(m_LuaState, inBehavior); // 4 = ElementRef
+ lua_rawset(m_LuaState, -3); // [size = 2]
+ // Get a reference to our new table and put that table into the behavior table
+ theScriptIndex = luaL_ref(m_LuaState, -2); // [size = 1]
+
+ // puts the script index into the table
+ lua_pushlstring(m_LuaState, KEY_SELF, LENGTH_KEY_SELF); // 2 = "self"
+ lua_rawget(m_LuaState, LUA_GLOBALSINDEX); // 2 = ScriptT
+ lua_pushlstring(m_LuaState, KEY_SCRIPT_INDEX,
+ LENGTH_KEY_SCRIPT_INDEX); // 3 = "__scriptIndex"
+ lua_pushinteger(m_LuaState, theScriptIndex); // 4 = ScriptIndex
+ lua_rawset(m_LuaState, -3); // [size = 2]
+
+ lua_pushstring(m_LuaState, inFileName);
+ lua_setfield(m_LuaState, -2, "__scriptpath__");
+
+ lua_pop(m_LuaState, 1); // [size = 1]
+ }
+
+ MapPresentationToScriptIndex(m_LuaState, *inPresentation, theScriptIndex);
+
+ {
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine: Ensure Lua File Is Loaded");
+
+ QFileInfo fileInfo(inPresentation->GetFilePath());
+ theError = EnsureScriptIsLoaded(
+ m_LuaState, inFileName, fileInfo.path().toLatin1().constData(),
+ m_ScriptString, m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer(),
+ m_ApplicationCore->GetRuntimeFactoryCore().GetInputStreamFactory(), m_LoadVec);
+ }
+
+ const char *theFullPath = m_ScriptString.c_str();
+
+ if (theError != 0) {
+ qCCritical(qt3ds::INVALID_OPERATION) << "Lua: loadfile failed: " << theFullPath;
+ lua_settop(m_LuaState, 0);
+ return;
+ }
+
+ {
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine: Execute Lua File");
+ // Execute the chunk on the stack with "self" pointing to our new table
+ theError = lua_pcall(m_LuaState, 0, 0, 0); // [size = 1]
+ }
+ if (theError != 0) {
+ qCCritical(qt3ds::INVALID_OPERATION) << "pcall failed loading file: "
+ << nonNull(theFullPath) << " " << nonNull(lua_tostring(m_LuaState, -1));
+ lua_settop(m_LuaState, 0);
+ return;
+ }
+
+ lua_settop(m_LuaState, theTop);
+
+ inBehavior->m_ScriptID = theScriptIndex;
+ inBehavior->Flags().clearOrSet(true, ELEMENTFLAG_SCRIPTCALLBACKS);
+ inBehavior->Flags().clearOrSet(true, ELEMENTFLAG_SCRIPTINITIALIZE);
+}
+
+Q3DStudio::INT32 SLuaEngineImpl::InitializeApplicationBehavior(const char *inRelativePath)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope __topScope(m_LuaState);
+ PrepareToLoadFile();
+ eastl::string scriptBuffer;
+ int loadError = EnsureScriptIsLoaded(
+ m_LuaState, inRelativePath, m_ApplicationCore->GetProjectDirectory(), scriptBuffer,
+ m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer(),
+ m_ApplicationCore->GetRuntimeFactoryCore().GetInputStreamFactory(), m_LoadVec);
+ if (loadError) {
+ qCCritical(qt3ds::INVALID_PARAMETER, "Failed to load lua file: %s: %s", inRelativePath,
+ lua_tostring(m_LuaState, -1));
+ return 0;
+ }
+ INT32 theScriptIndex = 0;
+ {
+ SLuaStackScope __selfScope(m_LuaState);
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // 1 = BehaviorsT
+ lua_newtable(m_LuaState); // 2 = self
+
+ lua_pushvalue(m_LuaState, -1); // dup the table
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, KEY_SELF); // 2 = self
+
+ lua_pushvalue(m_LuaState, -1); // dup the table
+ theScriptIndex = luaL_ref(m_LuaState, -3); // Add a new script into the behaviors table.
+
+ lua_pushinteger(m_LuaState, theScriptIndex);
+ lua_setfield(m_LuaState, -2, KEY_SCRIPT_INDEX);
+
+ lua_pushstring(m_LuaState, inRelativePath);
+ lua_setfield(m_LuaState, -2, "__scriptpath__");
+ }
+
+ int pcallError = PCall(0, 0, 0);
+ if (pcallError) {
+ qCCritical(INVALID_PARAMETER, "Failed to load lua file: %s: %s", inRelativePath,
+ lua_tostring(m_LuaState, -1));
+ return 0;
+ }
+ return theScriptIndex;
+}
+
+//==============================================================================
+/**
+ * Signal from the associated presentation that it's time to fire off
+ * any frame callbacks such as onActivation and onUpdate.
+ */
+void SLuaEngineImpl::ProcessFrameCallbacks(IPresentation *inPresentation)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ PerfLogGeneralEvent2(DATALOGGER_PROCESSFRAMECALLBACKS);
+
+ CPresentationFrameData &theFrameData = inPresentation->GetFrameData();
+
+ // Call onSlideExit functions
+ // ProcessSlideCallbacksHelper( theElementManager, theFrameData.GetSlideExitList( ),
+ // KEY_ONSLIDEEXIT );
+
+ // Call onDeactivate functions
+ ProcessFrameCallbacksHelper(theFrameData.GetDeactivationList(), KEY_ONDEACTIVATE);
+
+ // Call onInitialize functions and remove the ELEMENTFLAG_SCRIPTINITIALIZE flag
+ TElementList &theUpdateList = theFrameData.GetScriptsList();
+ FOR_ARRAY(TElement *, theElement, theUpdateList)
+ {
+ if ((*theElement)->GetFlag(ELEMENTFLAG_SCRIPTINITIALIZE)) {
+ CallElementCallback(**theElement, KEY_ONINITIALIZE);
+ (*theElement)->SetFlag(ELEMENTFLAG_SCRIPTINITIALIZE, false);
+ }
+ }
+
+ // Call onActivate functions
+ ProcessFrameCallbacksHelper(theFrameData.GetActivationList(), KEY_ONACTIVATE);
+
+ // Call onUpdate functions
+ ProcessFrameCallbacksHelper(theUpdateList, KEY_ONUPDATE);
+}
+
+void SLuaEngineImpl::ExecuteApplicationScriptFunction(Q3DStudio::INT32 inApp, const char *inFnName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope __topScope(m_LuaState);
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS);
+ lua_rawgeti(m_LuaState, -1, inApp);
+ int selfIndex = lua_gettop(m_LuaState);
+ if (!lua_istable(m_LuaState, -1)) {
+ qCCritical(INVALID_OPERATION, "Lua object index appears to be invalid");
+ return;
+ }
+ lua_getfield(m_LuaState, -1, inFnName);
+ if (lua_isfunction(m_LuaState, -1)) {
+ IPerfTimer *theTimer = NULL;
+ const char *thePerfName = "";
+ if (m_ApplicationCore) {
+ lua_getfield(m_LuaState, -2, "__scriptpath__");
+ if (lua_isstring(m_LuaState, -1)) {
+ m_ScriptString.clear();
+ m_ScriptString.assign(lua_tostring(m_LuaState, -1));
+ m_ScriptString.append(" - ");
+ m_ScriptString.append(inFnName);
+ thePerfName = m_ScriptString.c_str();
+ theTimer = &m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ }
+ lua_pop(m_LuaState, 1);
+ }
+ SStackPerfTimer __scriptTimer(theTimer, thePerfName);
+ // push the self element
+ lua_pushvalue(m_LuaState, -2);
+ lua_pushvalue(m_LuaState, -1); // dup that
+ lua_setglobal(m_LuaState, KEY_SELF); // set the global self element (WAT)
+
+ int pcallError = PCall(1, 0, 0);
+ if (pcallError) {
+ qCCritical(INVALID_OPERATION,
+ "Lua object call %s failed: %s. disabling further calls", inFnName,
+ lua_tostring(m_LuaState, -1));
+ lua_pushnil(m_LuaState);
+ lua_setfield(m_LuaState, selfIndex, inFnName);
+ }
+ }
+}
+
+void SLuaEngineImpl::CallFunction(const char *behavior, const char *handler,
+ CScriptEngineCallFunctionArgRetriever &inArgRetriever)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ int theTop = lua_gettop(m_LuaState);
+ lua_getglobal(m_LuaState, "UICApplication");
+ uic::runtime::IApplication *theApp =
+ static_cast<uic::runtime::IApplication *>(lua_touserdata(m_LuaState, -1));
+ lua_pop(m_LuaState, 1);
+
+ TElement *theBehavior = CLuaElementHelper::GetElement(*theApp, NULL, behavior, NULL);
+ if (theBehavior) {
+ // Ensure that onInitialize has been called.
+ if (theBehavior->GetFlag(ELEMENTFLAG_SCRIPTINITIALIZE)) {
+ CallElementCallback(*theBehavior, KEY_ONINITIALIZE);
+ theBehavior->SetFlag(ELEMENTFLAG_SCRIPTINITIALIZE, false);
+ }
+
+ INT32 theScriptIndex = theBehavior->m_ScriptID;
+ if (theScriptIndex < 1) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::CallFunction: Failed to find script for item: "
+ << behavior << ":" << handler;
+ } else {
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS);
+ lua_rawgeti(m_LuaState, -1, theScriptIndex); // Top + 1 = ScriptT
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, KEY_SELF);
+
+ lua_getfield(m_LuaState, -1, handler); // Top + 2 = custom function, if there's one
+ if (lua_isfunction(m_LuaState, -1)) // if it is a function, call it
+ {
+ const int theFunctionTop = lua_gettop(m_LuaState);
+ int theArgCount = 0;
+ // Setup the global 'self'. Very annoying.
+
+ QT3DS_ASSERT(lua_istable(m_LuaState, -2));
+ lua_pushvalue(m_LuaState, -2);
+ ++theArgCount;
+ QT3DS_ASSERT(lua_istable(m_LuaState, theFunctionTop + theArgCount));
+ int theArgumentStatus = inArgRetriever.RetrieveArgument(m_LuaState);
+ if (theArgumentStatus < 0) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::CallFunction: failed to evaluate behavior "
+ << "function arguments: " << behavior << ":" << handler
+ << ":" << inArgRetriever.GetArgDescription().c_str();
+ } else if (theArgumentStatus > 0) {
+ if (lua_istable(m_LuaState, -1)) {
+ // iterate through the keys and push each value. This allows people to
+ // provide more than
+ // one argument.
+ lua_pushnil(m_LuaState);
+ while (lua_next(m_LuaState, -2) != 0) {
+ ++theArgCount;
+ lua_insert(m_LuaState, theFunctionTop + theArgCount);
+ // lua_pop( m_LuaState, 1 );
+ }
+ } else {
+ ++theArgCount;
+ lua_insert(m_LuaState, theFunctionTop + theArgCount);
+ QT3DS_ASSERT(lua_istable(m_LuaState, theFunctionTop + 1));
+ }
+ }
+ QT3DS_ASSERT(lua_istable(m_LuaState, theFunctionTop + 1));
+ lua_settop(m_LuaState, theFunctionTop + theArgCount);
+ int failure = PCall(theArgCount, 0, 0);
+ if (failure) {
+ const char *error = lua_tostring(m_LuaState, -1);
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::CallFunction: failed to call handler: "
+ << behavior << ":" << handler << ":"
+ << inArgRetriever.GetArgDescription().c_str() << " - " << error;
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::CallFunction: behavior property is not a function"
+ << behavior << ":" << handler;
+ }
+ }
+ } else {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "CLuaEngine::CallFunction: Unable to find behavior "<< behavior;
+ }
+ lua_settop(m_LuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * Handle custom actions
+ * @param inCommand carrier of behavior and parameter
+ *information
+ */
+void SLuaEngineImpl::ProcessCustomActions(IPresentation *inPresentation,
+ const SEventCommand &inCommand)
+{
+ using uic::runtime::TIdValuePair;
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ TElement *theBehavior = inCommand.m_Target; // the element that is a behavior
+
+ CPresentation *thePresentation = (CPresentation *)inPresentation;
+ IParametersSystem &theParametersManager = thePresentation->GetParametersSystem();
+ qt3ds::foundation::IStringTable &theStrTable(thePresentation->GetStringTable());
+
+ INT32 theScriptIndex = theBehavior->m_ScriptID;
+ if (theScriptIndex < 1) {
+ UVariant theLuaScript;
+ QString theWarning = "Attempted to execute unloaded Lua: ";
+
+ if (theBehavior->GetAttribute(ATTRIBUTE_BEHAVIORSCRIPTS, theLuaScript)) {
+ qt3ds::foundation::CRegisteredString theString =
+ thePresentation->GetStringTable().HandleToStr(theLuaScript.m_StringHandle);
+ theWarning.append(theString.c_str());
+ }
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Lua: Unknown script index " << theWarning.toLatin1().constData();
+ return;
+ }
+
+ INT32 theArgumentCount = 1;
+
+ // The start index points to the function name, which is string
+ INT32 theGroupId = inCommand.m_Arg1.m_INT32; // the group id of the parameters group
+ UINT32 theNumParams = theParametersManager.GetNumParameters(theGroupId);
+ if (theNumParams == 0) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ TIdValuePair tempData = theParametersManager.GetParameter(theGroupId, 0);
+
+ if (tempData.first != HASH_PROPERTYNAME_STRING) {
+ Q3DStudio_ASSERT(false);
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Lua: ProcessCustomActions failed to get a param by index!";
+ return;
+ }
+
+ int theTop = lua_gettop(m_LuaState);
+ lua_pushcfunction(m_LuaState, ErrorChannel); // Top + 1 = error handler
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // Top + 2 = BehaviorsT
+ lua_rawgeti(m_LuaState, -1, theScriptIndex); // Top + 3 = ScriptT
+ if (lua_istable(m_LuaState, -1)) {
+ lua_getfield(
+ m_LuaState, -1,
+ theStrTable.HandleToStr(
+ tempData.second.m_StringHandle)); // Top + 4 = custom function, if there's one
+ if (lua_isfunction(m_LuaState, -1)) // if it is a function, call it
+ {
+ lua_pushlstring(m_LuaState, KEY_SELF, LENGTH_KEY_SELF); // Top + 5 = 'self'
+ lua_pushvalue(m_LuaState, -3); // Top + 6 = ScriptT
+ lua_rawset(m_LuaState, LUA_GLOBALSINDEX); // [size = Top + 4]
+
+ lua_pushvalue(m_LuaState, -2); // Top + 5 = ScriptT
+
+ for (UINT32 theIndex = 1; theIndex < theNumParams; ++theIndex) {
+ tempData = theParametersManager.GetParameter(theGroupId, theIndex);
+ if (tempData.first == HASH_PROPERTYNAME_FLOAT) {
+ lua_pushnumber(m_LuaState, tempData.second.m_FLOAT);
+ } else if (tempData.first == HASH_PROPERTYNAME_FLOAT3) {
+ RuntimeVector3 &theVector = CLuaVector::CreateVector(m_LuaState);
+
+ theVector.m_X = tempData.second.m_FLOAT;
+ theVector.m_Y =
+ theParametersManager.GetParameter(theGroupId, ++theIndex).second.m_FLOAT;
+ theVector.m_Z =
+ theParametersManager.GetParameter(theGroupId, ++theIndex).second.m_FLOAT;
+ } else if (tempData.first == HASH_PROPERTYNAME_LONG) {
+ lua_pushinteger(m_LuaState, static_cast<INT32>(tempData.second.m_FLOAT));
+ } else if (tempData.first == HASH_PROPERTYNAME_COLOR4) {
+ CColor &theColor = CLuaColor::CreateColor(m_LuaState);
+
+ theColor.m_Red = static_cast<UINT8>(tempData.second.m_FLOAT);
+ theColor.m_Green = static_cast<UINT8>(
+ theParametersManager.GetParameter(theGroupId, ++theIndex).second.m_FLOAT);
+ theColor.m_Blue = static_cast<UINT8>(
+ theParametersManager.GetParameter(theGroupId, ++theIndex).second.m_FLOAT);
+ theColor.m_Alpha = static_cast<UINT8>(
+ theParametersManager.GetParameter(theGroupId, ++theIndex).second.m_FLOAT);
+ } else if (tempData.first == HASH_PROPERTYNAME_BOOL) {
+ lua_pushboolean(m_LuaState, tempData.second.m_INT32 != 0);
+ } else if (tempData.first == HASH_PROPERTYNAME_STRING) {
+ lua_pushstring(m_LuaState,
+ theStrTable.HandleToStr(tempData.second.m_StringHandle));
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Lua: ProcessCustomAction: Unknown data type: " << tempData.first;
+ }
+ ++theArgumentCount;
+ }
+
+ PCall(theArgumentCount, 0, theTop + 1);
+ }
+ } else {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Lua: Unknown script index: Attempt to execute action on object with no "
+ << "script table registered";
+ }
+
+ lua_settop(m_LuaState, theTop);
+}
+
+void SLuaEngineImpl::ProcessCustomCallback(IPresentation * /*inPresentation*/,
+ const SEventCommand &inCommand)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ int theTop = lua_gettop(m_LuaState);
+ INT32 cbackIdx = inCommand.m_Arg1.m_INT32;
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_REGISTEREDCALLBACKS);
+ lua_pushcfunction(m_LuaState, ErrorChannel);
+ lua_rawgeti(m_LuaState, -2, cbackIdx);
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_settop(m_LuaState, theTop);
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Lua: ProcessCustomCallback: Callback id was nil " << cbackIdx;
+ } else {
+ PCall(0, 0, -2);
+ }
+ ReleaseCallback(cbackIdx);
+ lua_settop(m_LuaState, theTop);
+}
+
+void SLuaEngineImpl::SetTableForElement(TElement &inElement, ILuaScriptTableProvider &inProvider)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ // Called when something that isn't a lua script needs to get set on the element.
+ SLuaStackScope __stackScope(m_LuaState);
+ inProvider.CreateTable(m_LuaState);
+ int new_top = lua_gettop(m_LuaState);
+ if (new_top > __stackScope.m_Top && lua_istable(m_LuaState, -1)) {
+ IPresentation *thePresentation = inElement.GetBelongedPresentation();
+ lua_pushlightuserdata(m_LuaState, &inElement);
+ lua_setfield(m_LuaState, -2, KEY_ELEMENT);
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS);
+ // swap the behaviors table and the provided table so the provided table is TOS.
+ lua_insert(m_LuaState, -2);
+ // dup the provided table so there are two of them
+ lua_pushvalue(m_LuaState, -1);
+ // Get a reference to our new table and put that table into the behavior table
+ INT32 theScriptIndex = luaL_ref(m_LuaState, -3); // [size = 1]
+ // Note that the duplicated table should still be TOS until this
+ lua_pushinteger(m_LuaState, theScriptIndex);
+ lua_setfield(m_LuaState, -2, KEY_SCRIPT_INDEX);
+ MapPresentationToScriptIndex(m_LuaState, *thePresentation, theScriptIndex);
+
+ inElement.m_ScriptID = theScriptIndex;
+ inElement.SetFlag(ELEMENTFLAG_SCRIPTCALLBACKS, true);
+ inElement.SetFlag(ELEMENTFLAG_SCRIPTINITIALIZE, true);
+ }
+}
+
+void SLuaEngineImpl::SetAttribute(const char *element, const char *attName, const char *value)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope theScope(m_LuaState);
+
+ TElement *theTarget = CLuaElementHelper::GetElement(*m_Application, NULL, element, NULL);
+ if (theTarget) {
+ eastl::string temp(value);
+ temp.insert(0, "return ");
+ luaL_loadstring(m_LuaState, temp.c_str());
+ int failure = PCall(0, 1, 0);
+ if (failure) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::SetAttribute: failed to evaluate element setAttribute arguments: "
+ << element << ":" << attName << ":" << temp.c_str();
+ } else {
+ bool success = CLuaElementHelper::SetAttribute(m_LuaState, theTarget, attName, true);
+ if (!success) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::SetAttribute: failed to set attribute on element: "
+ << element << ":" << attName << ":" << temp.c_str();
+ }
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::SetAttribute: failed to find element "
+ << element << " (" << attName << ":" << value << ")";
+ }
+}
+
+void SLuaEngineImpl::FireEvent(const char *element, const char *evtName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope theScope(m_LuaState);
+ TElement *theElement = CLuaElementHelper::GetElement(*m_Application, NULL, element, NULL);
+ if (theElement && theElement->GetActive() == true) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ thePresentation->FireEvent(CHash::HashEventCommand(evtName), theElement);
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::FireEvent: failed to find element: "
+ << element << "(" << evtName << ")";
+ }
+}
+
+void SLuaEngineImpl::GotoSlide(const char *component, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ int theTop = lua_gettop(m_LuaState);
+ lua_getglobal(m_LuaState, "UICApplication");
+ uic::runtime::IApplication *theApp =
+ static_cast<uic::runtime::IApplication *>(lua_touserdata(m_LuaState, -1));
+ lua_pop(m_LuaState, 1);
+
+ TElement *theTarget = CLuaElementHelper::GetElement(*theApp, NULL, component, NULL);
+ if (theTarget) {
+ CLuaCommandHelper::SetupGotoSlideCommand(*theTarget, slideName, inArgs);
+ } else {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "CLuaEngine::GotoSlide: Unable to find component: " << component;
+ }
+ lua_settop(m_LuaState, theTop);
+}
+
+void SLuaEngineImpl::GotoSlideRelative(const char *component, bool inNextSlide, bool inWrap,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope theScope(m_LuaState);
+ TElement *theTarget = CLuaElementHelper::GetElement(*m_Application, NULL, component, NULL);
+ if (theTarget) {
+ theTarget = &theTarget->GetComponentParent();
+ if (theTarget && theTarget->GetActive()) {
+ TComponent *theComponent = static_cast<TComponent *>(theTarget);
+ Q3DStudio::INT32 theSlide = theComponent->GetCurrentSlide();
+ Q3DStudio::INT32 theSlideCount = theComponent->GetSlideCount();
+ theSlide = inNextSlide ? theSlide + 1 : theSlide - 1;
+ if (theSlide < 1) {
+ if (inWrap)
+ theSlide = theSlideCount - 1;
+ else
+ theSlide = 1;
+ } else if (theSlide == theSlideCount) {
+ if (inWrap)
+ theSlide = 1;
+ else
+ theSlide = theSlideCount - 1;
+ }
+ if (theSlide != theComponent->GetCurrentSlide()) {
+ CLuaCommandHelper::SetupGotoSlideCommand(*theTarget, theSlide, inArgs);
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::GotoSlideRelative: Component is not active: "<< component;
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine::GotoSlideRelative: failed to find component: "<< component;
+ }
+}
+
+void SLuaEngineImpl::SetPresentationAttribute(const char *presId, const char *, const char *value)
+{
+ if (isTrivial(presId))
+ return;
+ if (presId[0] == '#')
+ ++presId;
+ CPresentation *thePresentation = m_Application->GetPresentationById(presId);
+ if (thePresentation) {
+ bool active = AreEqualCaseless(nonNull(value), "True");
+ thePresentation->SetActive(active);
+ }
+}
+
+bool SLuaEngineImpl::PlaySoundFile(const char *soundPath)
+{
+ return m_Application->GetAudioPlayer().PlaySoundFile(soundPath);
+}
+
+//==============================================================================
+/**
+ * Add a new global function to my lua_State. This is useful to call from the outside.
+ */
+void SLuaEngineImpl::AddGlobalFunction(const CHAR *inFunctionName, lua_CFunction inFunction)
+{
+ if (m_LuaState) {
+ lua_register(m_LuaState, inFunctionName, inFunction);
+ }
+}
+
+void SLuaEngineImpl::EnableDebugging(uic::state::debugger::IMultiProtocolSocket &socket)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ using namespace uic::state::debugger;
+ QT3DS_ASSERT(m_ApplicationCore);
+ NVScopedRefCounted<uic::state::debugger::IMultiProtocolSocketStream> theStream =
+ socket.CreateProtocol(uic::state::debugger::ILuaArchitectDebugServer::LuaProtocolName(),
+ NULL);
+ m_LuaListener = QT3DS_NEW(m_Foundation.getAllocator(), SLuaEngineListener)(m_Foundation, *this);
+
+ m_LuaDebugger = uic::state::debugger::ILuaDebugger::CreateLuaSideDebugger(
+ m_ApplicationCore->GetRuntimeFactoryCore().GetFoundation(), *theStream, m_LuaState,
+ m_ApplicationCore->GetRuntimeFactoryCore().GetStringTable(),
+ m_ApplicationCore->GetProjectDirectory().c_str(), m_LuaListener.mPtr);
+}
+
+void SLuaEngineImpl::EnableProfiling()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ lua_sethook(m_LuaState, ProfileHook, LUA_MASKCALL | LUA_MASKRET, 0);
+}
+
+void SLuaEngineImpl::StepGC()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ IPerfTimer *theTimer = NULL;
+ if (m_ApplicationCore)
+ theTimer = &m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ SStackPerfTimer __timer(theTimer, "CLuaEngine::StepGC");
+ lua_gc(m_LuaState, LUA_GCSTEP, 5);
+}
+//==============================================================================
+/**
+ * ****************End of IScriptBridge functions **************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * ****************Inherited virtual functions from CLuaEngine **************
+ */
+//=============================================================================
+uic::state::IStateInterpreter *
+SLuaEngineImpl::CreateStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodelFunction)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ SLuaStackScope __topScope(m_LuaState);
+ // This assertion is key. Without it, somewhere in below a setField function gets called on
+ // something that isn't
+ // a table and the program blinks out of existance.
+ if (__topScope.m_Top != 0) {
+ qFatal("CLuaEngine::CreateStateMachine called when lua stack is not at zero; aborting");
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ lua_pushcfunction(m_LuaState, ParseSCXML);
+ eastl::string fullPath;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(m_Application->GetProjectDirectory().c_str(),
+ inPath, fullPath);
+ lua_pushstring(m_LuaState, fullPath.c_str());
+ uic::state::IStateInterpreter *theInterpreter = NULL;
+ int error = PCall(1, 1, 0);
+ if (error) {
+ qCCritical(INVALID_OPERATION, "Failed to load scxml file: %s", lua_tostring(m_LuaState, -1));
+ } else {
+ lua_insert(m_LuaState, 1);
+ lua_settop(m_LuaState, 1);
+ int isTable = lua_istable(m_LuaState, 1);
+ QT3DS_ASSERT(isTable);
+ (void)isTable;
+ // shove it in the global table under its path. We will get to this again in a second
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1);
+ lua_newtable(m_LuaState);
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ }
+ lua_pushvalue(m_LuaState, -2);
+ lua_setfield(m_LuaState, -2, inId);
+ lua_pop(m_LuaState, 1); // pop the machine table
+
+ // The state machine should still be top of the stack.
+ // if ( !qt3ds::foundation::isTrivial( inDatamodelFunction ) )
+ {
+ int theNewTop = lua_gettop(m_LuaState);
+ eastl::string evalStr("return ");
+ evalStr.append(inDatamodelFunction);
+ luaL_loadstring(m_LuaState, evalStr.c_str());
+ int failure = PCall(0, 1, 0);
+ if (failure) {
+ const char *error = lua_tostring(m_LuaState, -1);
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "LuaEngine: Unable to initialize datamodel: "
+ << inDatamodelFunction << ":" << error;
+ lua_settop(m_LuaState, theNewTop);
+ } else {
+ // Hmm, now to get the item the function returned to be below the string in the
+ // stack.
+ // And clear off the stack from there.
+ lua_insert(m_LuaState, theNewTop + 1);
+ lua_settop(m_LuaState, theNewTop + 1);
+ }
+ }
+ // If all that worked then we should have the state machine and the datatable on the stack
+ // and only those two on the stack.
+ // At which point we can call start, which will pop everything off the stack
+ uic::state::ILuaScriptContext::Initialize(m_LuaState, inId);
+ // Now get the interpreter from the map so we can get its value
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ lua_getfield(m_LuaState, -1, inId);
+ theInterpreter = uic::state::ILuaScriptContext::GetInterpreterFromBindings(m_LuaState);
+ }
+ return theInterpreter;
+}
+
+// Functions that will not crash if the lua engine has no application or if the presentations
+// are in an indeterminate state.
+void SLuaEngineImpl::PreInitialize()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ lua_register(m_LuaState, "output", Output);
+ lua_register(m_LuaState, "getEventSystem", GetEventSystem);
+ CLuaVector::RegisterLibrary(m_LuaState);
+ CLuaColor::RegisterLibrary(m_LuaState);
+ CLuaRotation::RegisterLibrary(m_LuaState);
+ CLuaMatrix::RegisterLibrary(m_LuaState);
+ CLuaKeyboard::RegisterLibrary(m_LuaState);
+ CLuaButton::RegisterLibrary(m_LuaState);
+ CLuaAxis::RegisterLibrary(m_LuaState);
+}
+//==============================================================================
+/**
+ * Register the set of global Lua functions
+ */
+void SLuaEngineImpl::Initialize()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ lua_register(m_LuaState, "getElement", CLuaElementHelper::GetElement);
+ lua_register(m_LuaState, "getElementType", CLuaElementHelper::GetElementType);
+ lua_register(m_LuaState, "getAttribute", CLuaElementHelper::GetAttribute);
+ lua_register(m_LuaState, "setAttribute", CLuaElementHelper::SetAttribute);
+ lua_register(m_LuaState, "hasAttribute", CLuaElementHelper::HasAttribute);
+ lua_register(m_LuaState, "getChildren", CLuaElementHelper::GetChildren);
+ lua_register(m_LuaState, "getCurrentSlide", CLuaElementHelper::GetCurrentSlide);
+ lua_register(m_LuaState, "getTime", CLuaElementHelper::GetTime);
+
+ lua_register(m_LuaState, "calculateGlobalOpacity", CLuaSceneHelper::CalculateGlobalOpacity);
+ lua_register(m_LuaState, "calculateBoundingBox", CLuaSceneHelper::CalculateBoundingBox);
+ lua_register(m_LuaState, "calculateLocalBoundingBox",
+ CLuaSceneHelper::CalculateLocalBoundingBox);
+ lua_register(m_LuaState, "calculateGlobalTransform", CLuaSceneHelper::CalculateGlobalTransform);
+ lua_register(m_LuaState, "getImageInfo", CLuaSceneHelper::GetImageInfo);
+ lua_register(m_LuaState, "setLocalTransformMatrix", CLuaSceneHelper::SetLocalTransformMatrix);
+
+ lua_register(m_LuaState, "fireEvent", CLuaEventHelper::FireEvent);
+ lua_register(m_LuaState, "registerForEvent", CLuaEventHelper::RegisterForEvent);
+ lua_register(m_LuaState, "unregisterForEvent", CLuaEventHelper::UnRegisterForEvent);
+ // lua_register( m_LuaState, "registerForChange", CLuaEventHelper::RegisterForChange
+ // );
+ // lua_register( m_LuaState, "unregisterForChange", CLuaEventHelper::UnRegisterForChange
+ // );
+
+ lua_register(m_LuaState, "play", CLuaCommandHelper::Play);
+ lua_register(m_LuaState, "pause", CLuaCommandHelper::Pause);
+ lua_register(m_LuaState, "goToTime", CLuaCommandHelper::GoToTime);
+ lua_register(m_LuaState, "goToSlide", CLuaCommandHelper::GoToSlide);
+ lua_register(m_LuaState, "goToNextSlide", CLuaCommandHelper::GoToNextSlide);
+ lua_register(m_LuaState, "goToPreviousSlide", CLuaCommandHelper::GoToPreviousSlide);
+ lua_register(m_LuaState, "goToBackSlide", CLuaCommandHelper::GoToBackSlide);
+
+ lua_register(m_LuaState, "getScreenInfo", GetScreenInformation);
+ lua_register(m_LuaState, "getElapsedTime", GetElapsedTime);
+ lua_register(m_LuaState, "getMousePosition", GetMousePosition);
+ lua_register(m_LuaState, "getMultitouch", GetMultitouch);
+ lua_register(m_LuaState, "getLuaTable", GetLuaTable);
+ lua_register(m_LuaState, "getDirectory", GetDirectory);
+ lua_register(m_LuaState, "setTextureData", SetTextureData);
+ lua_register(m_LuaState, "testSetTextureData", TestSetTextureData);
+ lua_register(m_LuaState, "measureText", MeasureText);
+ lua_register(m_LuaState, "loadImages", LoadImages);
+ lua_register(m_LuaState, "playToTime", PlayToTime);
+ lua_register(m_LuaState, "getStateMachine", GetSCXMLInterpreter);
+ lua_register(m_LuaState, "getPresentationSize", GetPresentationSize);
+ lua_register(m_LuaState, "getDisplayedSize", GetDisplayedSize);
+ lua_register(m_LuaState, "getCameraBounds", GetCameraBounds);
+ lua_register(m_LuaState, "positionToScreen", PositionToScreen);
+ lua_register(m_LuaState, "screenToPosition", ScreenToPosition);
+ lua_register(m_LuaState, "elementAt", ElementAt);
+ lua_register(m_LuaState, "facePosition", FacePosition);
+ lua_register(m_LuaState, "isPresentationActive", IsPresentationActive);
+ lua_register(m_LuaState, "setPresentationActive", SetPresentationActive);
+ lua_register(m_LuaState, "getMillisecondsSinceLastFrame", GetMillisecondsSinceLastFrame);
+ lua_register(m_LuaState, "playSound", PlaySounds);
+
+ lua_register(m_LuaState, "createMeshBuffer", CreateMeshBuffer);
+}
+
+void SLuaEngineImpl::Shutdown(qt3ds::NVFoundationBase &inFoundation)
+{
+ qCInfo(TRACE_INFO, "Lua engine Begin Exit");
+ EndPreloadScripts();
+ for (int idx = 0, end = m_ImageLoadingCallbacks.size(); idx < end; ++idx) {
+ m_ImageLoadingCallbacks[idx]->m_Engine = NULL;
+ }
+ m_ImageLoadingCallbacks.clear();
+ m_ApplicationCore = NULL;
+ m_Application = NULL;
+ {
+ Mutex::ScopedLock __locker(m_PreloadMutex);
+ DisableMultithreadedAccess();
+ }
+ lua_close(m_LuaState);
+ m_LuaState = NULL;
+
+ g_InputStreamFactory = NULL;
+ lua_set_file_io(NULL);
+
+ FOR_ARRAY(SCallbackData *, theData, m_EventCallbackDataList)
+ FreeCallbackData(*theData);
+
+ FOR_ARRAY(SCallbackData *, theData, m_ChangeCallbackDataList)
+ FreeCallbackData(*theData);
+
+ qCInfo(TRACE_INFO, "Lua engine End Exit");
+}
+
+//==============================================================================
+/**
+ * ************************End of CLuaEngine functions ************************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * *******************Local functions ************************
+ */
+//=============================================================================
+/**
+ * Helper function to call the appropriate frame callbacks
+ * @param inElementManager the manager to get the Script ID from the element
+ * @param inElementList the list of elements to interate through
+ * @param inFunctionName the name of the frame callback function to call
+ */
+void SLuaEngineImpl::ProcessFrameCallbacksHelper(TElementList &inElementList,
+ const CHAR *inFunctionName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ qt3ds::foundation::IPerfTimer &thePerfTimer(
+ m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer());
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine::ProcessFrameCallbacksHelper");
+
+ FOR_ARRAY(TElement *, theElement, inElementList)
+ {
+ if ((*theElement)->GetFlag(ELEMENTFLAG_SCRIPTCALLBACKS))
+ CallElementCallback(**theElement, inFunctionName);
+ }
+}
+
+//==============================================================================
+/**
+ * Helper function to call the lua functions in the self table
+ * @param inScriptIndex the script index to get the self table
+ * @param inFunctionName the lua function to call
+ * @return true if the function is called, false if otherwise
+ */
+SLuaFunctionResult SLuaEngineImpl::CallFunction(INT32 inScriptIndex, const CHAR *inFunctionName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ PerfLogLuaEvent1(DATALOGGER_CALLLUAFUNCTION);
+
+ int theTop = lua_gettop(m_LuaState);
+
+ lua_pushcfunction(m_LuaState, ErrorChannel); // Top + 1 = error handler
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // Top + 2 = BehaviorsT
+
+ lua_rawgeti(m_LuaState, -1, inScriptIndex); // Top + 3 = ScriptT
+ BOOL theFunctionFlag = FALSE;
+ BOOL thePCallError = TRUE;
+ if (lua_istable(m_LuaState, -1)) {
+ thePCallError = FALSE;
+ lua_getfield(m_LuaState, -1, inFunctionName); // Top + 4 = OnXXX function, if there's one
+
+ theFunctionFlag = lua_isfunction(m_LuaState, -1);
+ if (theFunctionFlag) // if it is a function, call it
+ {
+ const char *thePerfName = "";
+ IPerfTimer *theTimer = NULL;
+ if (m_ApplicationCore) {
+ lua_getfield(m_LuaState, -2, "__scriptpath__");
+ if (lua_isstring(m_LuaState, -1)) {
+ m_ScriptString.clear();
+ m_ScriptString.assign(lua_tostring(m_LuaState, -1));
+ m_ScriptString.append(" - ");
+ m_ScriptString.append(inFunctionName);
+ thePerfName = m_ScriptString.c_str();
+ theTimer = &m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer();
+ }
+ }
+ SStackPerfTimer __scriptTimer(theTimer, thePerfName);
+ lua_pop(m_LuaState, 1);
+ lua_pushlstring(m_LuaState, KEY_SELF, LENGTH_KEY_SELF); // Top + 5 = 'self'
+ lua_pushvalue(m_LuaState, -3); // Top + 6 = ScriptT
+ lua_rawset(m_LuaState, LUA_GLOBALSINDEX); // [size = Top + 4]
+
+ lua_pushvalue(m_LuaState, -2); // Top + 5 = ScriptT
+
+ int error = PCall(1, 0, theTop + 1); // [size = Top + 3]
+ if (error)
+ thePCallError = TRUE;
+ }
+ }
+
+ lua_settop(m_LuaState, theTop);
+
+ return SLuaFunctionResult(theFunctionFlag, thePCallError);
+}
+
+void SLuaEngineImpl::CallElementCallback(TElement &inElement, const CHAR *inFunctionName)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ qt3ds::foundation::IPerfTimer &thePerfTimer(
+ m_ApplicationCore->GetRuntimeFactoryCore().GetPerfTimer());
+ SStackPerfTimer __perfTimer(thePerfTimer, "CLuaEngine::CallElementCallback");
+ SLuaFunctionResult theResult = CallFunction(inElement.m_ScriptID, inFunctionName);
+ // If we have the function and there was an error, disable any further callbacks
+ if (theResult.m_HasFunction == TRUE && theResult.m_PCallError == TRUE) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Lua: Script error detected, disabling further callbacks";
+ inElement.SetFlag(ELEMENTFLAG_SCRIPTINITIALIZE, false);
+ inElement.SetFlag(ELEMENTFLAG_SCRIPTCALLBACKS, false);
+
+ }
+}
+
+INT32 SLuaEngineImpl::RegisterCallback(lua_State *inLuaState)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ int argc = lua_gettop(inLuaState);
+ luaL_checktype(inLuaState, -1, LUA_TFUNCTION);
+ lua_rawgeti(inLuaState, LUA_REGISTRYINDEX, KEY_REGISTEREDCALLBACKS);
+ ++m_CallbackIndex;
+ lua_rawgeti(inLuaState, -1, m_CallbackIndex);
+ // check if the value was valid or not. If it was, increment callback idx again
+ while (!lua_isnil(inLuaState, -1)) {
+ lua_pop(inLuaState, 1);
+ ++m_CallbackIndex;
+ lua_rawgeti(inLuaState, -1, m_CallbackIndex);
+ }
+ // pop the nil-check off the stack.
+ lua_pop(inLuaState, 1);
+ // swap the table and the function on the stack.
+ lua_insert(inLuaState, -2);
+ lua_rawseti(inLuaState, -2, m_CallbackIndex);
+ // Pop the table off the stack.
+ lua_pop(inLuaState, 1);
+ int check = lua_gettop(inLuaState);
+ Q3DStudio_ASSERT(check == (argc - 1));
+ (void)argc;
+ (void)check;
+ return m_CallbackIndex;
+}
+
+void SLuaEngineImpl::ReleaseCallback(INT32 inCallback)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ int argc = lua_gettop(m_LuaState);
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_REGISTEREDCALLBACKS);
+ lua_pushnil(m_LuaState);
+ lua_rawseti(m_LuaState, -2, inCallback);
+ lua_pop(m_LuaState, 1);
+ int check = lua_gettop(m_LuaState);
+ Q3DStudio_ASSERT(check == argc);
+ (void)argc;
+ (void)check;
+}
+
+void SLuaEngineImpl::ReleaseCallback(SLuaTimeCallback &inCallback)
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ inCallback.~SLuaTimeCallback();
+ m_TimeCallbackPool.deallocate(&inCallback);
+}
+
+void SLuaEngineImpl::PrepareToLoadFile()
+{
+ LUA_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ if (m_LuaPathInitialized == false) {
+ m_LuaPathInitialized = true;
+ eastl::string applicationDir(m_ApplicationCore->GetApplicationDirectory());
+ CFileTools::ToPlatformPath(applicationDir);
+
+ eastl::string subdir = System::getPlatformStr();
+ lua_State *state = m_LuaState != NULL ? m_LuaState : m_PreloadState;
+ // this block of code so far is only used by android
+ if (!g_AdditionalSharedLibraryPaths.empty()) {
+ for (eastl::vector<eastl::string>::iterator iter =
+ g_AdditionalSharedLibraryPaths.begin();
+ iter != g_AdditionalSharedLibraryPaths.end(); iter++) {
+ const eastl::string &additionalPathRef = *iter;
+ AppendAdditionalLuaPackagePath(state, additionalPathRef);
+ }
+ }
+
+ eastl::string dataCenterPluginDir;
+ CFileTools::CombineBaseAndRelative(applicationDir.c_str(), "Runtime/Plugins/Bindings",
+ dataCenterPluginDir);
+ CFileTools::ToPlatformPath(dataCenterPluginDir);
+ // AppendLuaPackagePath( state, scriptsDir, eLuaPath);
+ AppendLuaPackagePath(state, dataCenterPluginDir, eCPath);
+
+ // Add in additional search directory for specific platform
+ eastl::string scriptsPlatformDir;
+ CFileTools::CombineBaseAndRelative(".\\scripts", subdir.c_str(), scriptsPlatformDir);
+ CFileTools::ToPlatformPath(scriptsPlatformDir);
+ AppendLuaPackagePath(state, scriptsPlatformDir, eCPath);
+ }
+}
+
+int SLuaEngineImpl::PCall(int argcount, int retcount, int errorIndex)
+{
+ bool wasProfiling = m_ProfileActive;
+ m_ProfileActive = true;
+ if (!wasProfiling)
+ m_PerfStackIndex = 0;
+ int retval = lua_pcall(m_LuaState, argcount, retcount, errorIndex);
+ m_ProfileActive = wasProfiling;
+ return retval;
+}
+
+void SLuaEngineImpl::OnBreak()
+{
+ uic::state::debugger::IDebugger &theDebugger = m_ApplicationCore->GetStateDebugger();
+ theDebugger.OnExternalBreak();
+}
+
+void SLuaEngineImpl::CallImageLoadComplete(const char *inPath, bool inSucceeded,
+ qt3ds::QT3DSU32 inCallbackId)
+{
+ int top = lua_gettop(m_LuaState);
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, KEY_REGISTEREDCALLBACKS);
+ lua_rawgeti(m_LuaState, -1, inCallbackId);
+ lua_insert(m_LuaState, -2);
+ // Pop the registeredcallbacks table off the stack.
+ lua_pop(m_LuaState, 1);
+ lua_pushstring(m_LuaState, nonNull(inPath));
+ lua_pushboolean(m_LuaState, inSucceeded ? 1 : 0);
+ int failure = PCall(2, 0, 0);
+ if (failure) {
+ qCCritical(INVALID_OPERATION, "Image loading callback failed: %s", lua_tostring(m_LuaState, -1));
+ }
+ lua_settop(m_LuaState, top);
+}
+
+void SLuaEngineImpl::CallbackFinished(SImageLoadCallback &inCallback)
+{
+ eastl::vector<SImageLoadCallback *>::iterator theFind =
+ eastl::find(m_ImageLoadingCallbacks.begin(), m_ImageLoadingCallbacks.end(), &inCallback);
+ if (theFind != m_ImageLoadingCallbacks.end()) {
+ (*theFind)->m_Engine = NULL;
+ m_ImageLoadingCallbacks.erase(theFind);
+ }
+}
+//==============================================================================
+/**
+ * ************************End of local functions ************************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * *******************static functions from CLuaEngine ************************
+ */
+//=============================================================================
+//==============================================================================
+/**
+ * Frees up the SCallbackData memory properly
+ * @param inData the callback data to free
+ */
+void CLuaEngine::FreeCallbackData(SCallbackData *inData)
+{
+ Q3DStudio_free(inData, CLuaEngine::SCallbackData, 1);
+}
+
+//==============================================================================
+/**
+ * Get the presentation pointer from the lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the Presentation pointer
+ */
+CPresentation *CLuaEngine::GetCurrentPresentation(lua_State *inLuaState)
+{
+ CPresentation *thePresentation = NULL;
+ SLuaStackScope __topScope(inLuaState);
+ lua_pushlstring(inLuaState, KEY_SELF, LENGTH_KEY_SELF); // Top + 1 = "self"
+ lua_rawget(inLuaState, LUA_GLOBALSINDEX); // 2 = ScriptT
+ lua_pushlstring(inLuaState, KEY_SCRIPT_INDEX,
+ LENGTH_KEY_SCRIPT_INDEX); // Top + 2 = "__scriptIndex"
+ lua_rawget(inLuaState, -2); // Top + 2 = script index
+
+ if (lua_isnumber(inLuaState, -1)) {
+ INT32 theScriptIndex = static_cast<INT32>(lua_tointeger(inLuaState, -1));
+ thePresentation = static_cast<CPresentation *>(
+ GetPresentationFromScriptIndex(inLuaState, theScriptIndex));
+ }
+
+ if (thePresentation == NULL) {
+ lua_getglobal(inLuaState, "UICApplication");
+ IApplication *appInterface =
+ reinterpret_cast<IApplication *>(lua_touserdata(inLuaState, -1));
+ if (appInterface != NULL)
+ thePresentation = appInterface->GetPrimaryPresentation();
+ }
+
+ return thePresentation;
+}
+
+void CLuaEngine::SetAdditionalSharedLibraryPath(const eastl::string &inAdditionalSharedLibraryPath)
+{
+ eastl::find(g_AdditionalSharedLibraryPaths.begin(), g_AdditionalSharedLibraryPaths.end(),
+ inAdditionalSharedLibraryPath)
+ == g_AdditionalSharedLibraryPaths.end()
+ ? g_AdditionalSharedLibraryPaths.push_back(inAdditionalSharedLibraryPath)
+ : void(0);
+}
+
+CLuaEngine *CLuaEngine::Create(qt3ds::NVFoundationBase &inFoundation, ITimeProvider &inTimeProvider)
+{
+ return QT3DS_NEW(inFoundation.getAllocator(), SLuaEngineImpl)(inFoundation, inTimeProvider);
+}
+//==============================================================================
+/**
+ * *******************end of static functions from CLuaEngine ******************
+ */
+//=============================================================================
+
+//==============================================================================
+/**
+ * *******************exported global Lua functions definition********************
+ */
+//=============================================================================
+namespace __SLuaEngineImpl_Static_Global_Lua_Exporter_Declaration__ {
+ using namespace Q3DStudio;
+
+ int Output(lua_State *inLuaState)
+ {
+ INT32 theTop = lua_gettop(inLuaState);
+ QString theString = "";
+
+ for (INT32 theCounter = 1; theCounter <= theTop; ++theCounter) {
+ lua_getglobal(inLuaState, "tostring");
+ lua_pushvalue(inLuaState, theCounter);
+ if (lua_pcall(inLuaState, 1, 1, 0))
+ theString.append("output: Error while calling 'tostring'.");
+ else {
+ const CHAR *theResult = lua_tostring(inLuaState, -1);
+ if (theResult)
+ theString.append(theResult);
+ else
+ theString.append("output: 'tostring' must return a string to 'output'");
+ }
+
+ if ((theCounter + 1) <= theTop)
+ theString.append("\n");
+ }
+
+ qCInfo(qt3ds::TRACE_INFO) << "Lua: " << theString.toLatin1().constData();
+
+ lua_settop(inLuaState, 0);
+
+ return 0;
+ }
+
+ //==============================================================================
+ /**
+ * Gets the screen infomation
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 3 - the width, height and scale mode of the presentation are pushed
+ * on the stack in that order
+ */
+ int GetScreenInformation(lua_State *inLuaState)
+ {
+ CPresentation *thePresentation = CLuaEngine::GetCurrentPresentation(inLuaState);
+ uic::runtime::IApplication &theApp = thePresentation->GetApplication();
+
+ INT32 theViewWidth;
+ INT32 theViewHeight;
+ SPresentationSize thePresentationSize = thePresentation->GetSize();
+
+ theApp.GetRuntimeFactory().GetSceneManager().GetViewSize(theViewWidth, theViewHeight);
+
+ switch (thePresentationSize.m_ScaleMode) {
+ case SCALEMODE_FREE:
+ lua_pushinteger(inLuaState, theViewWidth);
+ lua_pushinteger(inLuaState, theViewHeight);
+ lua_pushstring(inLuaState, SCALE_MODE_FREE);
+ break;
+ case SCALEMODE_EXACT:
+ lua_pushinteger(inLuaState, thePresentationSize.m_Width);
+ lua_pushinteger(inLuaState, thePresentationSize.m_Height);
+ lua_pushstring(inLuaState, SCALE_MODE_FIXED);
+ break;
+ case SCALEMODE_ASPECT: {
+ FLOAT theAspectRatio = static_cast<FLOAT>(thePresentationSize.m_Width)
+ / static_cast<FLOAT>(thePresentationSize.m_Height);
+ FLOAT theStudioWidth = theAspectRatio * theViewHeight;
+ FLOAT theStudioHeight = static_cast<FLOAT>(theViewHeight);
+ if (theStudioWidth > theViewWidth) {
+ theStudioWidth = static_cast<FLOAT>(theViewWidth);
+ theStudioHeight = theViewWidth / theAspectRatio;
+ }
+ lua_pushinteger(inLuaState, static_cast<INT32>(theStudioWidth));
+ lua_pushinteger(inLuaState, static_cast<INT32>(theStudioHeight));
+ lua_pushstring(inLuaState, SCALE_MODE_ASPECT);
+ } break;
+ case SCALEMODE_UNKNOWN: // Pass thru
+ default:
+ lua_pushinteger(inLuaState, theViewWidth);
+ lua_pushinteger(inLuaState, theViewHeight);
+ lua_pushnil(inLuaState);
+ break;
+ }
+
+ return 3;
+ }
+
+ //==============================================================================
+ /**
+ * Gets the elapsed time since the start of the presentation. If element isn't
+ * a component, it walks up the tree to find one that is.
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 2 - the elapsed time in seconds and the real world time that were
+ * pushed on the stack
+ */
+ int GetElapsedTime(lua_State *inLuaState)
+ {
+ CPresentation *thePresentation = CLuaEngine::GetCurrentPresentation(inLuaState);
+ IApplication &theApplication = thePresentation->GetApplication();
+
+ TTimeUnit thePresentationTime = thePresentation->GetTime();
+ TTimeUnit theRealWorldTime = theApplication.GetTimeMilliSecs();
+
+ lua_pushnumber(inLuaState, thePresentationTime / 1000.0f);
+ lua_pushnumber(inLuaState, theRealWorldTime / 1000.0f);
+
+ return 2;
+ }
+
+ //==============================================================================
+ /**
+ * Gets the current mouse position in the screen
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 2 - the mouse X and Y in screen pixels that are pushed on the stack
+ */
+ int GetMousePosition(lua_State *inLuaState)
+ {
+ CPresentation *thePresentation = CLuaEngine::GetCurrentPresentation(inLuaState);
+
+ IApplication &theApplication = thePresentation->GetApplication();
+
+ SInputFrame theInput = theApplication.GetInputEngine().GetInputFrame();
+ if (theApplication.GetPrimaryPresentation()) {
+
+ // Only the primary presentation knows the translation from window to screen
+ // coordinates.
+ Q3DStudio::SMousePosition thePresPos =
+ theApplication.GetPrimaryPresentation()->GetScene()->WindowToPresentation(
+ Q3DStudio::SMousePosition(static_cast<INT32>(theInput.m_PickX),
+ static_cast<INT32>(theInput.m_PickY)));
+
+ lua_pushinteger(inLuaState, thePresPos.m_X);
+ lua_pushinteger(inLuaState, thePresPos.m_Y);
+
+ return 2;
+ } else {
+ lua_pushstring(inLuaState, "No primary presentation");
+ lua_error(inLuaState);
+ return 0;
+ }
+ }
+
+ int GetMultitouch(lua_State *inLuaState)
+ {
+ CPresentation *thePresentation = CLuaEngine::GetCurrentPresentation(inLuaState);
+
+ IApplication &theApplication = thePresentation->GetApplication();
+
+ SInputFrame theInput = theApplication.GetInputEngine().GetInputFrame();
+ if (theApplication.GetPrimaryPresentation()) {
+ CInputEngine::TPickInputList theInputs = theApplication.GetInputEngine().GetPickInput();
+ lua_newtable(inLuaState);
+ for (QT3DSU32 idx = 0, end = theInputs.size(); idx < end; ++idx) {
+ lua_newtable(inLuaState);
+ const eastl::pair<float, float> &theInput(theInputs[idx]);
+ // Only the primary presentation knows the translation from window to screen
+ // coordinates.
+ Q3DStudio::SMousePosition thePresPos =
+ theApplication.GetPrimaryPresentation()->GetScene()->WindowToPresentation(
+ Q3DStudio::SMousePosition(static_cast<INT32>(theInput.first),
+ static_cast<INT32>(theInput.second)));
+
+ lua_pushnumber(inLuaState, thePresPos.m_X);
+ lua_setfield(inLuaState, -2, "x");
+ lua_pushinteger(inLuaState, thePresPos.m_Y);
+ lua_setfield(inLuaState, -2, "y");
+ lua_rawseti(inLuaState, -2, idx + 1);
+ }
+
+ return 1;
+ } else {
+ lua_pushstring(inLuaState, "No primary presentation");
+ lua_error(inLuaState);
+ return 0;
+ }
+ }
+
+ int GetLuaTable(lua_State *inLuaState)
+ {
+ luaL_checktype(inLuaState, -1, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, -1));
+
+ if (theElement) {
+ Q3DStudio::INT32 theScriptId = theElement->m_ScriptID;
+
+ lua_rawgeti(inLuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS);
+ lua_rawgeti(inLuaState, -1, theScriptId);
+ } else
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+
+ const THashValue HASH_DIRECTORY_PROJECT = CHash::HashString("project");
+ const THashValue HASH_DIRECTORY_SCRIPTS = CHash::HashString("scripts");
+ const THashValue HASH_DIRECTORY_PLUGINS = CHash::HashString("plugins");
+ const THashValue HASH_DIRECTORY_SCRIPTS_PLATFORM = CHash::HashString("scripts-platform");
+ const THashValue HASH_DIRECTORY_PLUGINS_PLATFORM = CHash::HashString("plugins-platform");
+
+ int GetDirectory(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ if (theEngine && theEngine->m_ApplicationCore) {
+ eastl::string sub;
+ int argc = lua_gettop(inLuaState);
+ const CHAR *directoryName = argc > 0 ? luaL_checkstring(inLuaState, 1) : "project";
+ THashValue directoryHash = CHash::HashString(directoryName);
+ if (directoryHash == HASH_DIRECTORY_PROJECT)
+ sub.clear();
+ else if (directoryHash == HASH_DIRECTORY_SCRIPTS)
+ sub.assign("scripts");
+ else if (directoryHash == HASH_DIRECTORY_PLUGINS)
+ sub.assign("plugins");
+ else if (directoryHash == HASH_DIRECTORY_SCRIPTS_PLATFORM)
+ sub.assign("scripts/").append(System::getPlatformStr());
+ else if (directoryHash == HASH_DIRECTORY_PLUGINS_PLATFORM)
+ sub.assign("plugins/").append(System::getPlatformGLStr());
+ else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "getDirectory wasn't passed an recognized string";
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+ eastl::string dir(theEngine->m_ApplicationCore->GetProjectDirectory());
+ if (!sub.empty())
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(dir.c_str(), sub.c_str(), dir);
+ CFileTools::ToPlatformPath(dir);
+ lua_pushstring(inLuaState, dir.c_str());
+ } else
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+
+ const THashValue HASH_TEXTUREFORMAT_RGB = CHash::HashString("RGB");
+ const THashValue HASH_TEXTUREFORMAT_RGBA = CHash::HashString("RGBA");
+ const THashValue HASH_TEXTUREFORMAT_RGBA16 = CHash::HashString("RGBA16");
+ const THashValue HASH_TEXTUREFORMAT_ALPHA = CHash::HashString("ALPHA");
+ const THashValue HASH_TEXTUREFORMAT_LUMINANCE = CHash::HashString("LUMINANCE");
+ const THashValue HASH_TEXTUREFORMAT_LUMINANCEALPHA = CHash::HashString("LUMINANCE_ALPHA");
+ const THashValue HASH_TEXTUREFORMAT_DXT1 = CHash::HashString("DXT1");
+ const THashValue HASH_TEXTUREFORMAT_DXT3 = CHash::HashString("DXT3");
+ const THashValue HASH_TEXTUREFORMAT_DXT5 = CHash::HashString("DXT5");
+
+ int SetTextureData(lua_State *inLuaState)
+ {
+
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_TEXTUREFORMAT = 2;
+ const INT32 ARG_WIDTH = 3;
+ const INT32 ARG_HEIGHT = 4;
+ const INT32 ARG_TEXTURE_DATA = 5;
+ const INT32 ARG_TEXTURE_LENGTH = 6;
+ const INT32 HAS_TRANSPARENCY = 7;
+
+ INT32 theWidth = 0;
+ INT32 theHeight = 0;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ int argc = lua_gettop(inLuaState);
+ const CHAR *formatName = luaL_checkstring(inLuaState, ARG_TEXTUREFORMAT);
+ theWidth = static_cast<INT32>(luaL_checknumber(inLuaState, ARG_WIDTH));
+ theHeight = static_cast<INT32>(luaL_checknumber(inLuaState, ARG_HEIGHT));
+ TElement *theElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+ // luaL_checktype( inLuaState, ARG_TEXTURE_DATA, LUA_TUSERDATA ); //(userdata expected, got
+ // userdata) wt?????
+ int theLength =
+ argc > 5 ? static_cast<INT32>(luaL_checknumber(inLuaState, ARG_TEXTURE_LENGTH)) : 0;
+ int hasTransparency =
+ argc > 6 ? static_cast<INT32>(luaL_checknumber(inLuaState, HAS_TRANSPARENCY)) : -1;
+
+ if (theElement) {
+ // ensure that format is correct
+ THashValue formatHash = CHash::HashString(formatName);
+ qt3ds::render::NVRenderTextureFormats::Enum theFormat =
+ qt3ds::render::NVRenderTextureFormats::Unknown;
+ if (formatHash == HASH_TEXTUREFORMAT_RGB)
+ theFormat = qt3ds::render::NVRenderTextureFormats::RGB8;
+ else if (formatHash == HASH_TEXTUREFORMAT_RGBA)
+ theFormat = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ else if (formatHash == HASH_TEXTUREFORMAT_RGBA16)
+ theFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F;
+ else if (formatHash == HASH_TEXTUREFORMAT_ALPHA)
+ theFormat = qt3ds::render::NVRenderTextureFormats::Alpha8;
+ else if (formatHash == HASH_TEXTUREFORMAT_LUMINANCE)
+ theFormat = qt3ds::render::NVRenderTextureFormats::Luminance8;
+ else if (formatHash == HASH_TEXTUREFORMAT_LUMINANCEALPHA)
+ theFormat = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8;
+ else if (formatHash == HASH_TEXTUREFORMAT_DXT1)
+ theFormat = qt3ds::render::NVRenderTextureFormats::RGBA_DXT1;
+ else if (formatHash == HASH_TEXTUREFORMAT_DXT3)
+ theFormat = qt3ds::render::NVRenderTextureFormats::RGBA_DXT3;
+ else if (formatHash == HASH_TEXTUREFORMAT_DXT5)
+ theFormat = qt3ds::render::NVRenderTextureFormats::RGBA_DXT5;
+ else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "SetTextureData wasn't passed an texture element";
+ return 0;
+ }
+
+ // start to set the texture data
+ const unsigned char *theBuffer = NULL;
+ theBuffer =
+ reinterpret_cast<unsigned char *>(lua_touserdata(inLuaState, ARG_TEXTURE_DATA));
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ if (thePresentation && thePresentation->GetScene())
+ thePresentation->GetScene()->SetTextureData(theElement, theBuffer, theLength,
+ theWidth, theHeight, theFormat,
+ hasTransparency);
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION) << "SetTextureData wasn't passed an texture element";
+ }
+ // we pushed 0 numbers to lua
+ return 0;
+ }
+
+ int TestSetTextureData(lua_State *inLuaState)
+ {
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, 1));
+
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream =
+ theElement->GetBelongedPresentation()
+ ->GetApplication()
+ .GetRuntimeFactoryCore()
+ .GetInputStreamFactory()
+ .GetStreamForFile("maps/IBL/AcroIBL.raw");
+ if (theStream.mPtr) {
+ QT3DSU32 theLength = 230400;
+ QT3DSU8 theBuffer[230400];
+ QT3DSU32 amountRead = theStream->Read(toDataRef(theBuffer, theLength));
+ QT3DS_ASSERT(amountRead == theLength);
+ (void)amountRead;
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ thePresentation->GetScene()->SetTextureData(theElement, theBuffer, theLength, 320, 240,
+ qt3ds::render::NVRenderTextureFormats::RGB8,
+ false);
+ }
+ return 0;
+ }
+
+ int LoadImages(lua_State *inLuaState)
+ {
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_IMAGES = 2;
+ const INT32 ARG_DEFAULT_IMAGE = 3;
+ const INT32 ARG_CALLBACK = 4;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ luaL_checktype(inLuaState, ARG_IMAGES, LUA_TTABLE);
+ luaL_checktype(inLuaState, ARG_DEFAULT_IMAGE, LUA_TSTRING);
+ if (lua_gettop(inLuaState) == 4)
+ luaL_checktype(inLuaState, ARG_CALLBACK, LUA_TFUNCTION);
+
+ const CHAR *defaultImageStr = luaL_checkstring(inLuaState, ARG_DEFAULT_IMAGE);
+
+ TElement *theElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+ if (theElement == NULL)
+ return 0;
+
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ IScene *theScene(thePresentation->GetScene());
+
+ eastl::vector<qt3ds::foundation::CRegisteredString> theSourcePaths;
+
+ qt3ds::foundation::CRegisteredString theDefaultImageStr(
+ theScene->RegisterStr(defaultImageStr));
+ lua_pushnil(inLuaState);
+ while (lua_next(inLuaState, ARG_IMAGES) != 0) {
+ const char *theValue = luaL_checkstring(inLuaState, -1);
+ if (theValue && *theValue) {
+ theSourcePaths.push_back(theScene->RegisterStr(theValue));
+ }
+ lua_pop(inLuaState, 1);
+ }
+
+ Q3DStudio::INT32 retval = 0;
+
+ uic::render::IImageLoadListener *theListener = NULL;
+ if (lua_gettop(inLuaState) == 4) {
+ SLuaEngineImpl *theEngine =
+ static_cast<SLuaEngineImpl *>(thePresentation->GetScriptBridge());
+ lua_pushvalue(inLuaState, ARG_CALLBACK);
+ INT32 cbackId = theEngine->RegisterCallback(inLuaState);
+ SImageLoadCallback *theTemp =
+ QT3DS_NEW(theEngine->m_Foundation.getAllocator(),
+ SImageLoadCallback)(theEngine->m_Foundation, *theEngine, cbackId);
+ theEngine->m_ImageLoadingCallbacks.push_back(theTemp);
+ theListener = theTemp;
+ }
+
+ if (theSourcePaths.size())
+ retval = theScene->LoadImageBatch(theSourcePaths.data(), theSourcePaths.size(),
+ theDefaultImageStr, theListener);
+
+ lua_pushinteger(inLuaState, retval);
+
+ return 1;
+ }
+
+ int MeasureText(lua_State *inLuaState)
+ {
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_TEXT = 2;
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ int argc = lua_gettop(inLuaState);
+ TElement *theElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ const CHAR *textStr = NULL;
+ if (argc > 1)
+ textStr = luaL_checkstring(inLuaState, ARG_TEXT);
+
+ if (theElement) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ Q3DStudio::STextSizes theDimensions;
+ if (thePresentation && thePresentation->GetScene())
+ theDimensions = thePresentation->GetScene()->MeasureText(theElement, textStr);
+
+ lua_pushinteger(inLuaState, static_cast<INT32>(theDimensions.m_Width));
+ lua_pushinteger(inLuaState, static_cast<INT32>(theDimensions.m_Height));
+ return 2;
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION) << "SetTextureData wasn't passed an texture element";
+ }
+ return 0;
+ }
+
+ int PlayToTime(lua_State *inLuaState)
+ {
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_ENDTIME = 2;
+ const INT32 ARG_INTERPOLATION = 3;
+ const INT32 ARG_CALLBACK = 4;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ luaL_checktype(inLuaState, ARG_ENDTIME, LUA_TNUMBER);
+ luaL_checktype(inLuaState, ARG_INTERPOLATION, LUA_TNUMBER);
+ luaL_checktype(inLuaState, ARG_CALLBACK, LUA_TFUNCTION);
+
+ TElement *theElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+ CPresentation *thePresentation =
+ static_cast<CPresentation *>(theElement->GetBelongedPresentation());
+ SLuaEngineImpl *theEngine =
+ static_cast<SLuaEngineImpl *>(thePresentation->GetScriptBridge());
+ // Push the callback
+ lua_pushvalue(inLuaState, ARG_CALLBACK);
+ INT32 cbackId = theEngine->RegisterCallback(inLuaState);
+ lua_Number endTime = lua_tonumber(inLuaState, ARG_ENDTIME);
+ lua_Number interp = lua_tonumber(inLuaState, ARG_INTERPOLATION);
+ // convert time to milliseconds;
+ endTime *= 1000;
+ TTimeUnit theTime = static_cast<TTimeUnit>(endTime + .5f);
+ SLuaTimeCallback *theCallback =
+ (SLuaTimeCallback *)theEngine->m_TimeCallbackPool.allocate(__FILE__, __LINE__);
+ new (theCallback) SLuaTimeCallback(*theEngine, cbackId, *thePresentation, theElement);
+ thePresentation->GetComponentManager().SetComponentTimeOverride(theElement, theTime, interp,
+ theCallback);
+ return 0;
+ }
+
+ int GetSCXMLInterpreter(lua_State *inLuaState)
+ {
+ const char *path = lua_tostring(inLuaState, -1);
+ if (!path) {
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+ // shove it in the global table under its path. We will get to this again in a second
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_state_machines");
+ if (lua_isnil(inLuaState, -1))
+ return 1;
+
+ lua_getfield(inLuaState, -1, path);
+ return 1;
+ }
+
+ int GetEventSystem(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_event_system");
+ if (!lua_istable(inLuaState, -1)) {
+ lua_pop(inLuaState, 1);
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ uic::evt::IEventSystem &theEventSystem =
+ theEngine->m_ApplicationCore->GetRuntimeFactoryCore().GetEventSystem();
+ uic::evt::SLuaEventPollerBinding::WrapEventPoller(inLuaState, theEventSystem);
+ lua_pushvalue(inLuaState, -1);
+ lua_setfield(inLuaState, LUA_REGISTRYINDEX, "uic_event_system");
+ }
+ return 1;
+ }
+
+ int IsPresentationActive(lua_State *inLuaState)
+ {
+ luaL_checktype(inLuaState, 1, LUA_TSTRING);
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ CPresentation *thePresentation =
+ theEngine->m_Application->GetPresentationById(lua_tostring(inLuaState, 1));
+ if (thePresentation) {
+ lua_pushboolean(inLuaState, (int)thePresentation->GetActive());
+ return 1;
+ }
+ lua_pushstring(inLuaState, "Failed to find presentation");
+ lua_error(inLuaState);
+ return 0;
+ }
+
+ int SetPresentationActive(lua_State *inLuaState)
+ {
+ luaL_checktype(inLuaState, 1, LUA_TSTRING);
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ CPresentation *thePresentation =
+ theEngine->m_Application->GetPresentationById(lua_tostring(inLuaState, 1));
+ if (thePresentation) {
+ int activeBool = lua_toboolean(inLuaState, 2);
+ thePresentation->SetActive(activeBool ? true : false);
+ return 1;
+ }
+ lua_pushstring(inLuaState, "Failed to find presentation");
+ lua_error(inLuaState);
+ return 0;
+ }
+
+ int GetPresentationSize(lua_State *inLuaState)
+ {
+ luaL_checktype(inLuaState, 1, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, 1));
+ if (theElement == NULL) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ if (thePresentation->GetScene()) {
+ STextSizes theSizes = thePresentation->GetScene()->GetPresentationDesignDimensions();
+ lua_pushinteger(inLuaState, theSizes.m_Width);
+ lua_pushinteger(inLuaState, theSizes.m_Height);
+ return 2;
+ }
+ QT3DS_ASSERT(false);
+ return 1;
+ }
+
+ int GetDisplayedSize(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ if (theEngine && theEngine->m_Application) {
+ Q3DStudio::ISceneManager &theManager(
+ theEngine->m_Application->GetRuntimeFactory().GetSceneManager());
+ STextSizes theSizes =
+ theManager.GetDisplayDimensions(theEngine->m_Application->GetPrimaryPresentation());
+ lua_pushinteger(inLuaState, theSizes.m_Width);
+ lua_pushinteger(inLuaState, theSizes.m_Height);
+ return 2;
+ }
+ return 0;
+ }
+
+ int GetCameraBounds(lua_State *inLuaState)
+ {
+ luaL_checktype(inLuaState, 1, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, 1));
+ if (theElement) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ IScene *theScene = thePresentation->GetScene();
+ if (theScene) {
+ Q3DStudio::SCameraRect theRect = theScene->GetCameraBounds(*theElement);
+ if (theRect.IsValid()) {
+ lua_pushnumber(inLuaState, theRect.m_Left);
+ lua_pushnumber(inLuaState, theRect.m_Top);
+ lua_pushnumber(inLuaState, theRect.m_Right);
+ lua_pushnumber(inLuaState, theRect.m_Bottom);
+ return 4;
+ }
+ }
+ }
+ return 0;
+ }
+
+ int PositionToScreen(lua_State *inLuaState)
+ {
+ const INT32 ARG_POSITION = 2;
+ const INT32 ARG_ELEMENT = 1;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+
+ QT3DSVec3 worldPos(0.0f);
+ RuntimeVector3 &theVec = CLuaVector::CheckVector(inLuaState, ARG_POSITION);
+ worldPos = QT3DSVec3(theVec.m_X, theVec.m_Y, theVec.m_Z);
+ TElement *theElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ if (theElement) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ IScene *theScene = thePresentation->GetScene();
+ if (theScene) {
+ qt3ds::QT3DSVec3 outPos(0.0f);
+ theScene->PositionToScreen(*theElement, worldPos, outPos);
+
+ theVec.Set(outPos.x, outPos.y, outPos.z);
+
+ // NOTE -- a zero output is what projection/unproject routines return if it could
+ // not
+ // acquire the appropriate scene data or camera data for this element.
+ if (outPos.isZero()) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "PositionToScreen could not successfully project position";
+ }
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "PositionToScreen was not passed a Node element";
+ }
+ return 0;
+ }
+
+ int ScreenToPosition(lua_State *inLuaState)
+ {
+ const INT32 ARG_SCREEN = 2;
+ const INT32 ARG_ELEMENT = 1;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+
+ QT3DSVec3 screenPos(0.0f);
+ RuntimeVector3 &theVec = CLuaVector::CheckVector(inLuaState, ARG_SCREEN);
+ screenPos = QT3DSVec3(theVec.m_X, theVec.m_Y, theVec.m_Z);
+ TElement *theElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ if (theElement) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ IScene *theScene = thePresentation->GetScene();
+ if (theScene) {
+ qt3ds::QT3DSVec3 outPos(0.0f);
+ theScene->ScreenToPosition(*theElement, screenPos, outPos);
+ theVec.Set(outPos.x, outPos.y, outPos.z);
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "ScreenToPosition was not passed a Node element";
+ }
+ return 0;
+ }
+
+ int ElementAt(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+
+ if (theEngine && theEngine->m_Application) {
+ luaL_checktype(inLuaState, 1, LUA_TNUMBER);
+ luaL_checktype(inLuaState, 2, LUA_TNUMBER);
+
+ float mouseX = lua_tonumber(inLuaState, 1);
+ float mouseY = lua_tonumber(inLuaState, 2);
+
+ Q3DStudio::ISceneManager &theManager =
+ theEngine->m_Application->GetRuntimeFactory().GetSceneManager();
+ Q3DStudio::TElement *retvalElem = theManager.UserPick(mouseX, mouseY);
+
+ if (retvalElem)
+ lua_pushlightuserdata(inLuaState, retvalElem);
+ else
+ lua_pushnil(inLuaState);
+ return 1;
+ }
+
+ return 0;
+ }
+
+ int FacePosition(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+
+ if (theEngine && theEngine->m_Application) {
+ luaL_checktype(inLuaState, 1, LUA_TLIGHTUSERDATA);
+ luaL_checktype(inLuaState, 2, LUA_TNUMBER);
+ luaL_checktype(inLuaState, 3, LUA_TNUMBER);
+ eastl::vector<Q3DStudio::TElement *> theMapperElements;
+ if (lua_gettop(inLuaState) >= 4) {
+ if (!lua_isnil(inLuaState, 4)) {
+ luaL_checktype(inLuaState, 4, LUA_TTABLE);
+ // iterate through the table as if it is an array.
+ int table_len = luaL_getn(inLuaState, 4);
+ for (int idx = 1; idx <= table_len; ++idx) {
+ lua_rawgeti(inLuaState, 4, idx);
+ Q3DStudio::TElement *mapperElem =
+ reinterpret_cast<Q3DStudio::TElement *>(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ theMapperElements.push_back(mapperElem);
+ }
+ }
+ }
+ FacePositionPlanes::Enum theFacePos(FacePositionPlanes::XY);
+ if (lua_gettop(inLuaState) >= 5) {
+ luaL_checktype(inLuaState, 5, LUA_TSTRING);
+ const char *theData = lua_tostring(inLuaState, 5);
+ eastl::string theEData(theData);
+ if (theEData.comparei("XZ") == 0)
+ theFacePos = FacePositionPlanes::XZ;
+ else if (theEData.comparei("YZ") == 0)
+ theFacePos = FacePositionPlanes::YZ;
+ }
+
+ Q3DStudio::TElement *theElem =
+ reinterpret_cast<Q3DStudio::TElement *>(lua_touserdata(inLuaState, 1));
+ float mouseX = lua_tonumber(inLuaState, 2);
+ float mouseY = lua_tonumber(inLuaState, 3);
+ if (theElem == NULL)
+ return 0;
+
+ Q3DStudio::ISceneManager &theManager =
+ theEngine->m_Application->GetRuntimeFactory().GetSceneManager();
+ qt3ds::foundation::Option<qt3ds::QT3DSVec2> relativePos = theManager.FacePosition(
+ *theElem, mouseX, mouseY,
+ NVDataRef<TElement *>(theMapperElements.data(), (QT3DSU32)theMapperElements.size()),
+ theFacePos);
+ if (relativePos.hasValue()) {
+ lua_pushnumber(inLuaState, relativePos->x);
+ lua_pushnumber(inLuaState, relativePos->y);
+ return 2;
+ }
+ }
+ return 0;
+ }
+
+ int GetMillisecondsSinceLastFrame(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ if (theEngine->m_Application) {
+ lua_pushnumber(inLuaState, theEngine->m_Application->GetMillisecondsSinceLastFrame());
+ return 1;
+ }
+ return 0;
+ }
+
+ int PlaySounds(lua_State *inLuaState)
+ {
+ lua_getfield(inLuaState, LUA_REGISTRYINDEX, "uic_lua_engine");
+ SLuaEngineImpl *theEngine = (SLuaEngineImpl *)(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+ bool theResult = false;
+ if (theEngine->m_Application) {
+ luaL_checktype(inLuaState, 1, LUA_TSTRING);
+ const char *thePathC = lua_tostring(inLuaState, 1);
+ eastl::string thePath(thePathC);
+ theResult = theEngine->PlaySoundFile(thePath.c_str());
+ }
+ lua_pushboolean(inLuaState, theResult ? 1 : 0);
+ return 1;
+ }
+
+ int CreateMeshBuffer(lua_State *inLuaState)
+ {
+ const INT32 ARG_MESHNAME = 1;
+ const INT32 ARG_PARENT = 2;
+ const INT32 ARG_VERTEX_DATA = 3;
+ const INT32 ARG_NUM_VERTS = 4;
+ const INT32 ARG_INDEX_DATA = 5;
+ const INT32 ARG_NUM_INDICES = 6;
+ const INT32 ARG_BOUNDS_MIN = 7;
+ const INT32 ARG_BOUNDS_MAX = 8;
+
+ // Get the full element name used for entry into the RenderBufferManager
+ eastl::string theElemName("");
+
+ luaL_checktype(inLuaState, ARG_MESHNAME, LUA_TSTRING);
+ Q3DStudio::TElement *theElem =
+ reinterpret_cast<Q3DStudio::TElement *>(lua_touserdata(inLuaState, ARG_PARENT));
+ if (!theElem) {
+ qCCritical(qt3ds::INVALID_OPERATION) << "CreateMeshBuffer was not passed a parent object";
+ } else {
+ theElemName.append(theElem->m_Path.c_str());
+ theElemName.append(".#");
+ theElemName.append(lua_tostring(inLuaState, ARG_MESHNAME));
+ }
+
+ // assumed that vertex format (for now) is Position + UV + Normal
+ // so the vertex stride is always (3 + 2 + 3) * 4 = 32 bytes
+ QT3DSU8 *vertData = NULL;
+ QT3DSU32 *idxData = NULL;
+
+ vertData = reinterpret_cast<QT3DSU8 *>(lua_touserdata(inLuaState, ARG_VERTEX_DATA));
+ QT3DSU32 numVerts = static_cast<INT32>(luaL_checknumber(inLuaState, ARG_NUM_VERTS));
+
+ idxData = reinterpret_cast<QT3DSU32 *>(lua_touserdata(inLuaState, ARG_INDEX_DATA));
+ QT3DSU32 numIndices = static_cast<INT32>(luaL_checknumber(inLuaState, ARG_NUM_INDICES));
+
+ if ((!vertData) || (!idxData)) {
+ qCCritical(qt3ds::INVALID_OPERATION) << "CreateMeshBuffer was not provided a valid vertex or index buffer!";
+ }
+
+ RuntimeVector3 &theMinVec = CLuaVector::CheckVector(inLuaState, ARG_BOUNDS_MIN);
+ RuntimeVector3 &theMaxVec = CLuaVector::CheckVector(inLuaState, ARG_BOUNDS_MAX);
+
+ qt3ds::NVBounds3 theBounds;
+ theBounds.minimum = qt3ds::QT3DSVec3(theMinVec.m_X, theMinVec.m_Y, theMinVec.m_Z);
+ theBounds.maximum = qt3ds::QT3DSVec3(theMaxVec.m_X, theMaxVec.m_Y, theMaxVec.m_Z);
+
+ bool success = theElem->GetBelongedPresentation()->GetScene()->CreateOrSetMeshData(
+ theElemName.c_str(), vertData, numVerts, 32, idxData, numIndices, theBounds);
+ if (!success)
+ qCCritical(qt3ds::INVALID_OPERATION) << "CreateMeshBuffer failed!";
+
+ return 0;
+ }
+}
+//==============================================================================
+/**
+ * *******************end of exported global Lua functions definitions************
+ */
+//=============================================================================
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaEventHelper.cpp b/src/Runtime/Source/Runtime/Source/UICLuaEventHelper.cpp
new file mode 100644
index 00000000..2e5e839a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaEventHelper.cpp
@@ -0,0 +1,815 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaEventHelper.h"
+#include "UICLuaHelper.h"
+#include "UICLuaEngine.h"
+#include "UICPresentation.h"
+#include "UICDataLogger.h"
+#include "UICHash.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+namespace {
+ static int ErrorChannel(lua_State *inLuaState)
+ {
+ qCritical(qt3ds::INVALID_OPERATION) << "Lua: ErrorChannel: " << lua_tostring(inLuaState, -1);
+ lua_pop(inLuaState, 1);
+ return 0;
+ }
+}
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+extern const INT32 KEY_BEHAVIORS;
+extern const INT32 KEY_EVENTDATA_LIST;
+extern const INT32 KEY_CHANGEDATA_LIST;
+extern const INT32 KEY_CALLBACKS;
+
+extern const char *KEY_ELEMENT;
+extern const char *KEY_SELF;
+extern const char *KEY_SCRIPT_INDEX;
+
+extern const THashValue HASH_ONINITIALIZE;
+extern const THashValue HASH_ONACTIVATE;
+extern const THashValue HASH_ONDEACTIVATE;
+extern const THashValue HASH_ONUPDATE;
+
+extern const UINT32 LENGTH_KEY_ELEMENT;
+extern const UINT32 LENGTH_KEY_SELF;
+extern const UINT32 LENGTH_KEY_SCRIPT_INDEX;
+
+const INT32 EVENTHELPER_REGISTER = 0;
+const INT32 EVENTHELPER_UNREGISTER = 1;
+const CHAR *EVENTHELPER_STRINGS[] = { "registerFor", "unregisterFor" };
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CLuaEventHelper::CLuaEventHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CLuaEventHelper::~CLuaEventHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Fires an event into the presentation
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaEventHelper::FireEvent(lua_State *inLuaState)
+{
+ const INT32 ARG_EVENT = 1;
+ const INT32 ARG_TARGET = 2;
+ const INT32 ARG_ARG1 = 3;
+ const INT32 ARG_ARG2 = 4;
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ const CHAR *theEvent = luaL_checkstring(inLuaState, ARG_EVENT);
+
+ luaL_checktype(inLuaState, ARG_TARGET, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_TARGET));
+
+ UINT8 theArg1Type = 0;
+ UINT8 theArg2Type = 0;
+ UVariant theArg1;
+ UVariant theArg2;
+ qt3ds::foundation::IStringTable &theStrTable(
+ theElement->GetBelongedPresentation()->GetStringTable());
+ uic::runtime::IApplication &theApplication(
+ theElement->GetBelongedPresentation()->GetApplication());
+
+ if (theTop == 3)
+ theArg1Type =
+ CLuaHelper::GetArgument(inLuaState, ARG_ARG1, theArg1, theStrTable, theApplication);
+ else if (theTop == 4) {
+ theArg1Type =
+ CLuaHelper::GetArgument(inLuaState, ARG_ARG1, theArg1, theStrTable, theApplication);
+ theArg2Type =
+ CLuaHelper::GetArgument(inLuaState, ARG_ARG2, theArg2, theStrTable, theApplication);
+ }
+
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ thePresentation->FireEvent(CHash::HashEventCommand(theEvent), theElement,
+ theArg1Type == 0 ? 0 : &theArg1, theArg2Type == 0 ? 0 : &theArg2,
+ static_cast<EAttributeType>(theArg1Type),
+ static_cast<EAttributeType>(theArg2Type));
+
+ lua_settop(inLuaState, 0);
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Register function to receive a callback when an Event occurs
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the return boolean result of the call is pushed on the stack.
+ * true if sucessful, false if otherwise
+ */
+int CLuaEventHelper::RegisterForEvent(lua_State *inLuaState)
+{
+ EventRegistration(inLuaState, EVENTHELPER_REGISTER);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * UnRegister function to receive a callback when an Event occurs
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the return boolean result of the call is pushed on the stack.
+ * true if sucessful, false if otherwise
+ */
+int CLuaEventHelper::UnRegisterForEvent(lua_State *inLuaState)
+{
+ EventRegistration(inLuaState, EVENTHELPER_UNREGISTER);
+ return 1;
+}
+
+#if 0
+//==============================================================================
+/**
+ * Register function to receive a callback when a change on the element occurs
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the return boolean result of the call is pushed on the stack.
+ * true if sucessful, false if otherwise
+ */
+int CLuaEventHelper::RegisterForChange( lua_State* inLuaState )
+{
+ ChangeRegistration( inLuaState, EVENTHELPER_REGISTER );
+ return 1;
+}
+
+//==============================================================================
+/**
+ * UnRegister function to receive a callback when a change on the element occurs
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the return boolean result of the call is pushed on the stack.
+ * true if sucessful, false if otherwise
+ */
+int CLuaEventHelper::UnRegisterForChange( lua_State* inLuaState )
+{
+ ChangeRegistration( inLuaState, EVENTHELPER_UNREGISTER );
+ return 1;
+}
+
+#endif
+
+//==============================================================================
+/**
+ * The callback function for RegisterForEvent
+ * @param inContextData the associated data when the event is registered (
+ *SCallbackData )
+ * @param ioEvent the event that was fired
+ */
+void CLuaEventHelper::EventCallback(void *inContextData, SEventCommand &ioEvent)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_EVENTCALLBACK);
+ CLuaEngine::SCallbackData &theData =
+ *reinterpret_cast<CLuaEngine::SCallbackData *>(inContextData);
+ if (theData.m_SelfElement && !theData.m_SelfElement->GetActive())
+ return;
+
+ INT32 theArgumentCount = 0;
+ lua_State *theLuaState = theData.m_LuaState;
+
+ INT32 theTop = lua_gettop(theLuaState);
+ lua_pushcfunction(theLuaState, ErrorChannel); // Top + 1 = error handler
+ lua_rawgeti(theLuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // Top + 2 = BehaviorsT
+ lua_rawgeti(theLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS); // Top + 3 = CallbackT
+ lua_rawgeti(theLuaState, -1, theData.m_FunctionReference); // Top + 4 = Callback function
+
+ if (!theData.m_Global) {
+ lua_pushlstring(theLuaState, KEY_SELF, LENGTH_KEY_SELF); // Top + 5 = "self"
+ lua_rawgeti(theLuaState, theTop + 2, theData.m_ScriptIndex); // Top + 6 = ScriptT
+ lua_rawset(theLuaState, LUA_GLOBALSINDEX); // [size = Top + 4]
+
+ lua_rawgeti(theLuaState, theTop + 2, theData.m_ScriptIndex); // Top + 5 = ScriptT
+ ++theArgumentCount;
+ } else {
+ lua_pushnil(theLuaState);
+ ++theArgumentCount;
+ }
+
+ lua_pushlightuserdata(theLuaState, ioEvent.m_Target); // 6 or 5 = element ref
+ ++theArgumentCount;
+
+ qt3ds::foundation::IStringTable &theStrTable(
+ ioEvent.m_Target->GetBelongedPresentation()->GetStringTable());
+ uic::runtime::IApplication &theApplication(
+ ioEvent.m_Target->GetBelongedPresentation()->GetApplication());
+
+ theArgumentCount += CLuaHelper::PushArgument(theLuaState, ioEvent.m_Arg1Type, ioEvent.m_Arg1,
+ theStrTable, theApplication);
+ theArgumentCount += CLuaHelper::PushArgument(theLuaState, ioEvent.m_Arg2Type, ioEvent.m_Arg2,
+ theStrTable, theApplication);
+
+ lua_pcall(theLuaState, theArgumentCount, 0, theTop + 1); // [size = 3]
+
+ // Remove whatever stuff on the stack before exiting
+ lua_settop(theLuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * The callback function for RegisterForChange
+ * @param inAttributeKey the attribute that was changed
+ * @param inOldValue the value before the attribute was changed
+ * @param inNewValue the value after the attribute was changed
+ * @param inContextData the associated data when the element is registered (
+ *SCallbackData )
+ */
+void CLuaEventHelper::ChangeCallback(const SAttributeKey &inAttributeKey, UVariant inOldValue,
+ UVariant inNewValue, void *inContextData)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_CHANGECALLBACK);
+ CLuaEngine::SCallbackData &theData =
+ *reinterpret_cast<CLuaEngine::SCallbackData *>(inContextData);
+
+ if (theData.m_SelfElement && !theData.m_SelfElement->GetActive())
+ return;
+
+ // Added to check for property change
+ if (theData.m_EventAttributeHash && theData.m_EventAttributeHash != inAttributeKey.m_Hash)
+ return;
+
+ if (theData.m_TargetElement == NULL)
+ return;
+
+ qt3ds::foundation::IStringTable &theStrTable(
+ theData.m_TargetElement->GetBelongedPresentation()->GetStringTable());
+
+ INT32 theArgumentCount = 0;
+ lua_State *theLuaState = theData.m_LuaState;
+
+ INT32 theTop = lua_gettop(theLuaState);
+ lua_pushcfunction(theLuaState, ErrorChannel); // Top + 1 = error handler
+ lua_rawgeti(theLuaState, LUA_REGISTRYINDEX, KEY_BEHAVIORS); // Top + 2 = BehaviorsT
+ lua_rawgeti(theLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS); // Top + 3 = CallbackT
+ lua_rawgeti(theLuaState, -1, theData.m_FunctionReference); // Top + 4 = Callback function
+
+ if (!theData.m_Global) {
+ lua_pushlstring(theLuaState, KEY_SELF, LENGTH_KEY_SELF); // Top + 5 = "self"
+ lua_rawgeti(theLuaState, theTop + 2, theData.m_ScriptIndex); // Top + 6 = ScriptT
+ lua_rawset(theLuaState, LUA_GLOBALSINDEX); // [size = Top + 4]
+
+ lua_rawgeti(theLuaState, theTop + 2, theData.m_ScriptIndex); // Top + 5 = ScriptT
+ ++theArgumentCount;
+ } else {
+ lua_pushnil(theLuaState);
+ ++theArgumentCount;
+ }
+
+ lua_pushlightuserdata(theLuaState, theData.m_TargetElement); // Top + 6 or 5 = element ref
+ lua_pushinteger(theLuaState,
+ static_cast<INT32>(inAttributeKey.m_Hash)); // Top + 7 or 6 = Attribute hash
+
+ switch (inAttributeKey.m_Type) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ lua_pushinteger(theLuaState, inOldValue.m_INT32); // Top + 8 or 7 = old value
+ lua_pushinteger(theLuaState, inNewValue.m_INT32); // Top + 9 or 8 = new value
+ break;
+
+ case ATTRIBUTETYPE_FLOAT:
+ lua_pushnumber(theLuaState, inOldValue.m_FLOAT); // Top + 8 or 7 = old value
+ lua_pushnumber(theLuaState, inNewValue.m_FLOAT); // Top + 9 or 8 = new value
+ break;
+
+ case ATTRIBUTETYPE_BOOL:
+ lua_pushboolean(theLuaState, inOldValue.m_INT32 != 0); // Top + 8 or 7 = old value
+ lua_pushboolean(theLuaState, inNewValue.m_INT32 != 0); // Top + 9 or 8 = new value
+ break;
+
+ case ATTRIBUTETYPE_STRING:
+ lua_pushstring(theLuaState, theStrTable.HandleToStr(
+ inOldValue.m_StringHandle)); // Top + 8 or 7 = old value
+ lua_pushstring(theLuaState, theStrTable.HandleToStr(
+ inNewValue.m_StringHandle)); // Top + 9 or 8 = new value
+ break;
+
+ case ATTRIBUTETYPE_POINTER:
+ lua_pushlightuserdata(theLuaState, inOldValue.m_VoidPointer); // Top + 8 or 7 = old value
+ lua_pushlightuserdata(theLuaState, inNewValue.m_VoidPointer); // Top + 9 or 8 = new value
+ break;
+
+ default:
+ qCritical(qt3ds::INVALID_OPERATION)
+ << "Callback function received an attribute of unknown type: "
+ << inAttributeKey.m_Type;
+ return;
+ }
+
+ theArgumentCount += 4;
+ lua_pcall(theLuaState, theArgumentCount, 0, theTop + 1);
+
+ // Remove whatever stuff on the stack before exiting
+ lua_settop(theLuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * Finds the Data in the data list
+ * Note: The top of the stack must be ScriptT
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inDataList the data list to look for the data
+ * @param inCriteria the data to look for
+ * @param inFunctionIndex the index to where the function is on the stack
+ * @return the index of the data in the list, -1 if the data is not found
+ */
+INT32 CLuaEventHelper::FindCallbackData(lua_State *inLuaState,
+ CLuaEngine::TCallbackDataList *inDataList,
+ CLuaEngine::SCallbackData *inCriteria,
+ const INT32 inFunctionIndex)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_FINDCALLBACKDATA);
+
+ INT32 theTop = lua_gettop(inLuaState);
+ lua_rawgeti(inLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS); // theTop + 1 = CallbackT
+
+ INT32 theIndex = -1;
+ for (INT32 theCounter = 0; theCounter < inDataList->GetCount(); ++theCounter) {
+ CLuaEngine::SCallbackData *theListData = (*inDataList)[theCounter];
+
+ if (inCriteria->m_TargetElement == theListData->m_TargetElement
+ && inCriteria->m_EventAttributeHash == theListData->m_EventAttributeHash
+ && inCriteria->m_ScriptIndex == theListData->m_ScriptIndex
+ && inCriteria->m_Global == theListData->m_Global) {
+ // Perform function equality check
+ // Get the callback function from the callback table
+ lua_rawgeti(inLuaState, theTop + 1, theListData->m_FunctionReference);
+
+ // compare the function contained in the listData with the incoming function on the
+ // stack
+ if (lua_equal(inLuaState, -1, inFunctionIndex)) {
+ theIndex = theCounter;
+ break;
+ }
+ }
+ }
+
+ lua_settop(inLuaState, theTop);
+
+ return theIndex;
+}
+
+//==============================================================================
+/**
+ * Register or unregister a callback on an event
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inRegister 0 to register the callback, 1 to unregister
+ */
+void CLuaEventHelper::EventRegistration(lua_State *inLuaState, const INT32 inRegister)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_EVENTREGISTRATION);
+ const INT32 ARG_CALLBACK_FUNCTION = 3;
+ const INT32 ARG_EVENT_NAME = 1;
+ const INT32 ARG_TARGET_ELEMENT = 2;
+ const INT32 ARG_SELF_ELEMENT = 4; // optional argument, if not supplied, use the global self
+
+ const CHAR *theEventName = luaL_checkstring(inLuaState, ARG_EVENT_NAME);
+ TEventCommandHash theEventHash = CHash::HashEventCommand(theEventName);
+
+ if (inRegister == EVENTHELPER_REGISTER) {
+ if ((theEventHash == HASH_ONDEACTIVATE) || (theEventHash == HASH_ONINITIALIZE)
+ || (theEventHash == HASH_ONACTIVATE) || (theEventHash == HASH_ONUPDATE)) {
+ // the "output" function
+ lua_getglobal(inLuaState, "output");
+ lua_pushfstring(inLuaState,
+ "ERROR: %sEvent: Auto event [%s] registration is not allowed.",
+ EVENTHELPER_STRINGS[inRegister], theEventName);
+ lua_call(inLuaState, 1, 0);
+ lua_pushboolean(inLuaState, false);
+ return;
+ }
+ }
+
+ INT32 theSelfIndex = (lua_gettop(inLuaState) == ARG_SELF_ELEMENT) ? ARG_SELF_ELEMENT : 0;
+
+ luaL_checktype(inLuaState, ARG_CALLBACK_FUNCTION, LUA_TFUNCTION);
+ luaL_checktype(inLuaState, ARG_TARGET_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theTargetElement =
+ reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_TARGET_ELEMENT));
+
+ lua_rawgeti(inLuaState, LUA_REGISTRYINDEX, KEY_EVENTDATA_LIST);
+ CLuaEngine::TCallbackDataList *theEventDataList =
+ reinterpret_cast<CLuaEngine::TCallbackDataList *>(lua_touserdata(inLuaState, -1));
+ lua_pop(inLuaState, 1);
+
+ // Create the callback context data
+ CLuaEngine::SCallbackData *theData =
+ Q3DStudio_allocate_desc(CLuaEngine::SCallbackData, 1, "Lua:Callback");
+ theData->m_EventAttributeHash = theEventHash;
+ theData->m_TargetElement = theTargetElement;
+ theData->m_LuaState = inLuaState;
+ theData->m_SelfElement = GetSelfElement(inLuaState, theSelfIndex);
+
+ INT32 theError = 0;
+ IPresentation *thePresentation = theTargetElement->GetBelongedPresentation();
+
+ // Check if the function specified is a registered "self" function
+ if (IsFunctionInSelfTable(inLuaState, ARG_CALLBACK_FUNCTION, theSelfIndex)) {
+ // The function is a registered "self" function, so get the script index
+ PushSelfOnTop(inLuaState, theSelfIndex);
+
+ lua_pushlstring(inLuaState, KEY_SCRIPT_INDEX,
+ LENGTH_KEY_SCRIPT_INDEX); // theTop + 2 = "__scriptIndex"
+ lua_rawget(inLuaState, -2); // theTop + 2 = script index
+
+ if (lua_isnumber(inLuaState, -1)) {
+ theData->m_ScriptIndex = static_cast<INT16>(lua_tointeger(inLuaState, -1));
+ theData->m_Global = 0;
+ } else
+ theError = 2;
+ } else {
+ theData->m_ScriptIndex = 0;
+ theData->m_Global = 1;
+ }
+
+ if (!theError) // if there's no error
+ {
+ // Find the callback data
+ INT32 theIndex =
+ FindCallbackData(inLuaState, theEventDataList, theData, ARG_CALLBACK_FUNCTION);
+
+ if (inRegister == EVENTHELPER_REGISTER) // Register
+ {
+ if (theIndex < 0) // register when not found
+ {
+ // create a reference to this function which will be stored in the callback table
+ lua_rawgeti(inLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS); // theTop + 2 = CallbackT
+ lua_pushvalue(inLuaState, ARG_CALLBACK_FUNCTION); // theTop + 3 = Callback function
+ theData->m_FunctionReference = luaL_ref(inLuaState, -2); // [size = theTop + 2]
+
+ thePresentation->RegisterEventCallback(theTargetElement, theEventHash,
+ EventCallback, theData);
+ theEventDataList->Push(theData);
+ } else // an event has already been registered, so unregister it and register again to
+ // maintain the callback order
+ {
+ CLuaEngine::SCallbackData *theRegisteredData = (*theEventDataList)[theIndex];
+ thePresentation->UnregisterEventCallback(theTargetElement, theEventHash,
+ EventCallback, theRegisteredData);
+ thePresentation->RegisterEventCallback(theTargetElement, theEventHash,
+ EventCallback, theRegisteredData);
+ }
+ } else // Unregister
+ {
+ if (theIndex >= 0) // unregister when found
+ {
+ CLuaEngine::SCallbackData *theRegisteredData = (*theEventDataList)[theIndex];
+
+ thePresentation->UnregisterEventCallback(theTargetElement, theEventHash,
+ EventCallback, theRegisteredData);
+ theEventDataList->Remove(theIndex);
+
+ // Unref and remove the function stored in the callback table
+ lua_rawgeti(inLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS); // theTop + 2 = CallbackT
+ luaL_unref(inLuaState, -1, theRegisteredData->m_FunctionReference);
+
+ CLuaEngine::FreeCallbackData(theRegisteredData);
+ CLuaEngine::FreeCallbackData(theData);
+ } else
+ theError = 3;
+ }
+ }
+
+ if (theError) {
+ CLuaEngine::FreeCallbackData(theData);
+
+ // The "output" function
+ lua_getglobal(inLuaState, "output");
+ switch (theError) {
+ // case 1:
+ // lua_pushfstring( inLuaState, "ERROR: %sEvent: Event, callback function and target
+ //element has been registered", EVENTHELPER_STRINGS[inRegister] );
+ // break;
+
+ case 2:
+ lua_pushfstring(inLuaState, "ERROR: %sEvent: Script index not found",
+ EVENTHELPER_STRINGS[inRegister]);
+ break;
+
+ case 3:
+ lua_pushfstring(inLuaState,
+ "WARNING: %sEvent: Attempt to unregister an unregistered event [%s]",
+ EVENTHELPER_STRINGS[inRegister], theEventName);
+ break;
+
+ default: // no errors
+ break;
+ }
+
+ lua_call(inLuaState, 1, 0);
+ }
+
+ lua_pushboolean(inLuaState, theError == 0);
+}
+
+//==============================================================================
+/**
+ * Register or unregister a callback on element attributes changes
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inRegister 0 to register the callback, 1 to unregister
+ */
+/*
+void CLuaEventHelper::ChangeRegistration( lua_State* inLuaState, const INT32 inRegister )
+{
+ PerfLogLuaEvent1( DATALOGGER_LUA_CHANGEREGISTRATION );
+ const INT32 ARG_ATTRIBUTE = 2;
+ const INT32 ARG_TARGET_ELEMENT = 1;
+ INT32 ARG_CALLBACK_FUNCTION = 2;
+
+ luaL_checktype( inLuaState, ARG_TARGET_ELEMENT, LUA_TLIGHTUSERDATA );
+
+ const CHAR* theAttributeString = NULL;
+ INT32 theSelfIndex = 0;
+ INT32 theTop = lua_gettop( inLuaState );
+ if ( theTop >= 3 )
+ {
+ // the 2nd parameter, which is a string attribute is optional, so check if it is
+supplied
+ if ( lua_type( inLuaState, ARG_ATTRIBUTE ) == LUA_TSTRING )
+ {
+ ARG_CALLBACK_FUNCTION = 3;
+ theAttributeString = luaL_checkstring( inLuaState, ARG_ATTRIBUTE );
+ }
+ // the last argument for "self" is optional, and if not supplied, use the global
+self
+ if ( lua_type( inLuaState, theTop ) == LUA_TTABLE )
+ theSelfIndex = theTop;
+ }
+
+ luaL_checktype( inLuaState, ARG_CALLBACK_FUNCTION, LUA_TFUNCTION );
+
+ TElement* theTargetElement = reinterpret_cast<TElement*>( lua_touserdata( inLuaState,
+ARG_TARGET_ELEMENT ) );
+
+ lua_rawgeti( inLuaState, LUA_REGISTRYINDEX, KEY_CHANGEDATA_LIST );
+ CLuaEngine::TCallbackDataList* theChangeDataList =
+reinterpret_cast<CLuaEngine::TCallbackDataList*>( lua_touserdata( inLuaState, -1 ) );
+ lua_pop( inLuaState, 1 );
+
+ CLuaEngine::SCallbackData* theData = Q3DStudio_allocate_desc( CLuaEngine::SCallbackData, 1,
+"Lua:Desc" );
+
+ theData->m_TargetElement = theTargetElement;
+ theData->m_LuaState = inLuaState;
+ if ( theAttributeString )
+ theData->m_EventAttributeHash = CHash::HashAttribute( theAttributeString );
+ else
+ theData->m_EventAttributeHash = 0;
+ theData->m_SelfElement = GetSelfElement( inLuaState, theSelfIndex );
+
+ INT32 theError = 0;
+ CPresentation* thePresentation = theTargetElement->GetBelongedPresentation();
+
+ // Check if the function specified is a registered "self" function
+ if ( IsFunctionInSelfTable( inLuaState, ARG_CALLBACK_FUNCTION, theSelfIndex ) )
+ {
+ // The function is a registered "self" function, so get the script index
+ PushSelfOnTop( inLuaState, theSelfIndex );
+
+ lua_pushlstring( inLuaState, KEY_SCRIPT_INDEX, LENGTH_KEY_SCRIPT_INDEX ); //
+theTop + 2 = "__scriptIndex"
+ lua_rawget( inLuaState, -2 );
+// theTop + 2 = script index
+
+ if ( lua_isnumber( inLuaState, -1 ) )
+ {
+ theData->m_ScriptIndex = static_cast<INT16>( lua_tointeger( inLuaState, -1 )
+);
+ theData->m_Global = 0;
+ }
+ else
+ theError = 2;
+ }
+ else
+ {
+ theData->m_ScriptIndex = 0;
+ theData->m_Global = 1;
+ }
+
+ if ( !theError ) // if there's no error
+ {
+ // Find the callback data
+ INT32 theIndex = FindCallbackData( inLuaState, theChangeDataList, theData,
+ARG_CALLBACK_FUNCTION );
+
+
+ if ( inRegister == EVENTHELPER_REGISTER ) // Register
+ {
+ if ( theIndex < 0 ) // register when not found
+ {
+ // create a reference to this function which will be stored in the
+callback table
+ lua_rawgeti( inLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS );
+// theTop + 2 = CallbackT
+ lua_pushvalue( inLuaState, ARG_CALLBACK_FUNCTION );
+// theTop + 3 = Callback function
+ theData->m_FunctionReference = luaL_ref( inLuaState, -2 );
+// [size = theTop + 2]
+
+ thePresentation->GetElementManager(
+).RegisterAttributeChangeCallback( theTargetElement, ChangeCallback, theData );
+ theChangeDataList->Push( theData );
+ }
+ else // a change has already been registered, so unregister it and register
+again to maintain the callback order
+ {
+ CLuaEngine::SCallbackData* theRegisteredData = ( *theChangeDataList
+)[theIndex];
+ thePresentation->GetElementManager(
+).UnregisterAttributeChangeCallback( theTargetElement, ChangeCallback, theRegisteredData );
+ thePresentation->GetElementManager(
+).RegisterAttributeChangeCallback( theTargetElement, ChangeCallback, theRegisteredData );
+ }
+ }
+ else // Unregister
+ {
+ if ( theIndex >= 0 ) // unregister when found
+ {
+ CLuaEngine::SCallbackData* theRegisteredData = ( *theChangeDataList
+)[theIndex];
+
+ thePresentation->GetElementManager(
+).UnregisterAttributeChangeCallback( theTargetElement, ChangeCallback, theRegisteredData );
+ theChangeDataList->Remove( theIndex );
+
+ // Unref and remove the function stored in the callback table
+ lua_rawgeti( inLuaState, LUA_REGISTRYINDEX, KEY_CALLBACKS );
+// theTop + 2 = CallbackT
+ luaL_unref( inLuaState, -1, theRegisteredData->m_FunctionReference
+);
+
+ CLuaEngine::FreeCallbackData( theRegisteredData );
+ CLuaEngine::FreeCallbackData( theData );
+ }
+ else
+ theError = 3;
+ }
+ }
+
+ if ( theError )
+ {
+ CLuaEngine::FreeCallbackData( theData );
+
+ // the "output" function
+ lua_getglobal( inLuaState, "output" );
+ switch ( theError )
+ {
+ //case 1:
+ // lua_pushfstring( inLuaState, "ERROR: %sChange: Callback function
+and target element has been registered", EVENTHELPER_STRINGS[inRegister] );
+ // break;
+
+ case 2:
+ lua_pushfstring( inLuaState, "ERROR: %sChange: Script index not
+found", EVENTHELPER_STRINGS[inRegister] );
+ break;
+
+ case 3:
+ lua_pushfstring( inLuaState, "WARNING: %sChange: Attempt to
+unregister an unregistered target element [%p]", EVENTHELPER_STRINGS[inRegister], theTargetElement
+);
+ break;
+
+ default:
+ break;
+ }
+
+ lua_call( inLuaState, 1, 0 );
+ }
+
+ lua_pushboolean( inLuaState, theError == 0 );
+}*/
+
+//==============================================================================
+/**
+ * Checks if the function at inFunctionIndex is in the self table which is on the top of the
+ *stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inFunctionIndex index pointing to the function object in the stack
+ * @param inSelfIndex index pointing to the self object in the stack, 0 to use the
+ *global self
+ * @return true if the function is in the self table, false if otherwise
+ */
+BOOL CLuaEventHelper::IsFunctionInSelfTable(lua_State *inLuaState, const INT32 inFunctionIndex,
+ const INT32 inSelfIndex)
+{
+ INT32 theTop = lua_gettop(inLuaState);
+
+ // theTop = "self"
+ PushSelfOnTop(inLuaState, inSelfIndex);
+
+ BOOL theResult = false;
+
+ // Push a nil to start the loop
+ lua_pushnil(inLuaState); // theTop + 2 = nil
+
+ // while there's still item's in the table
+ while (lua_next(inLuaState, -2)) // theTop + 2 = key, theTop + 3 = value
+ {
+ if (lua_equal(inLuaState, -1, inFunctionIndex)) {
+ theResult = true;
+ break;
+ } else
+ lua_pop(inLuaState,
+ 1); // leave the key to seed the next round // [size = theTop + 2]
+ }
+
+ lua_settop(inLuaState, theTop);
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Push "self" as specified by inSelfIndex onto the top of stack. The caller is responsible for
+ *restoring the stack.
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inSelfIndex index pointing to the self object in the stack, 0 to use the
+ *global self
+ * @return true if the function is in the self table, false if otherwise
+ */
+void CLuaEventHelper::PushSelfOnTop(lua_State *inLuaState, const INT32 inSelfIndex)
+{
+ if (inSelfIndex == 0) {
+ lua_pushlstring(inLuaState, KEY_SELF, LENGTH_KEY_SELF);
+ lua_rawget(inLuaState, LUA_ENVIRONINDEX);
+ } else
+ lua_settop(inLuaState, inSelfIndex);
+}
+
+//==============================================================================
+/**
+ * Gets the behavior element ( self.element ) from the current ScriptT
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inSelfIndex index pointing to the self object in the stack, 0 to use the
+ *global self
+ * @return the behavior element pointer
+ */
+TElement *CLuaEventHelper::GetSelfElement(lua_State *inLuaState, const INT32 inSelfIndex)
+{
+ INT32 theTop = lua_gettop(inLuaState);
+
+ if (inSelfIndex == 0) {
+ lua_pushlstring(inLuaState, KEY_SELF, LENGTH_KEY_SELF); // theTop + 1 = "self"
+ lua_rawget(inLuaState, LUA_GLOBALSINDEX); // theTop + 1 = ScriptT
+ } else
+ lua_settop(inLuaState, inSelfIndex);
+
+ lua_pushlstring(inLuaState, KEY_ELEMENT, LENGTH_KEY_ELEMENT); // theTop + 2 = "element"
+ lua_rawget(inLuaState, -2); // theTop + 2 = self.element ( behavior )
+
+ TElement *theSelfElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, -1));
+ lua_settop(inLuaState, theTop);
+ return theSelfElement;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaHelper.cpp b/src/Runtime/Source/Runtime/Source/UICLuaHelper.cpp
new file mode 100644
index 00000000..dbe05b3c
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaHelper.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaHelper.h"
+#include "UICApplication.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CLuaHelper::CLuaHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CLuaHelper::~CLuaHelper()
+{
+}
+
+//==============================================================================
+/**
+ * Push the correct type of the UVariant value onto the Lua stack.
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inType the value type
+ * @param inValue the value to push onto the stack.
+ * @return the number of values pushed onto the stack.
+ */
+INT32 CLuaHelper::PushArgument(lua_State *inLuaState, const UINT8 inType, UVariant &inValue,
+ qt3ds::foundation::IStringTable &strTable,
+ uic::runtime::IApplication &application)
+{
+ INT32 theResult = 1;
+
+ switch (inType) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ lua_pushinteger(inLuaState, inValue.m_INT32);
+ break;
+
+ case ATTRIBUTETYPE_FLOAT:
+ lua_pushnumber(inLuaState, inValue.m_FLOAT);
+ break;
+
+ case ATTRIBUTETYPE_BOOL:
+ lua_pushboolean(inLuaState, inValue.m_INT32 != 0);
+ break;
+
+ case ATTRIBUTETYPE_STRING:
+ lua_pushstring(inLuaState, strTable.HandleToStr(inValue.m_StringHandle));
+ break;
+
+ case ATTRIBUTETYPE_POINTER:
+ lua_pushlightuserdata(inLuaState, inValue.m_VoidPointer);
+ break;
+
+ case ATTRIBUTETYPE_ELEMENTREF:
+ lua_pushlightuserdata(inLuaState, application.GetElementByHandle(inValue.m_ElementHandle));
+ break;
+
+ case ATTRIBUTETYPE_NONE:
+ lua_pushnil(inLuaState);
+ break;
+
+ default:
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Pushed event argument value of unknown type: "<< inType;
+ theResult = 0;
+ break;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Get an argument from the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inIndex the Lua stack index where the argument is
+ * @param outValue the value to store the argument
+ * @return the type of the argument that is retrieved
+ */
+UINT8 CLuaHelper::GetArgument(lua_State *inLuaState, INT32 inIndex, UVariant &outValue,
+ qt3ds::foundation::IStringTable &strTable, uic::runtime::IApplication &)
+{
+ UINT8 theType = ATTRIBUTETYPE_NONE;
+ switch (lua_type(inLuaState, inIndex)) {
+ case LUA_TNUMBER:
+ outValue.m_FLOAT = static_cast<FLOAT>(lua_tonumber(inLuaState, inIndex));
+ theType = ATTRIBUTETYPE_FLOAT;
+ break;
+
+ case LUA_TBOOLEAN:
+ outValue.m_INT32 = lua_toboolean(inLuaState, inIndex) ? 1 : 0;
+ theType = ATTRIBUTETYPE_BOOL;
+ break;
+
+ case LUA_TSTRING:
+ outValue.m_StringHandle = strTable.GetHandle(lua_tostring(inLuaState, inIndex));
+ theType = ATTRIBUTETYPE_STRING;
+ break;
+
+ case LUA_TLIGHTUSERDATA:
+ case LUA_TUSERDATA:
+ outValue.m_VoidPointer = lua_touserdata(inLuaState, inIndex);
+ theType = ATTRIBUTETYPE_POINTER;
+ break;
+
+ case LUA_TNIL:
+ outValue.m_INT32 = 0;
+ theType = ATTRIBUTETYPE_NONE;
+ break;
+
+ default:
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Got event argument value of unknown type: "
+ << lua_type(inLuaState, inIndex);
+ break;
+ }
+
+ return theType;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaKeyboard.cpp b/src/Runtime/Source/Runtime/Source/UICLuaKeyboard.cpp
new file mode 100644
index 00000000..5bcec814
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaKeyboard.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "RuntimePrefix.h"
+#include "UICLuaEngine.h"
+#include "UICInputFrame.h"
+#include "UICLuaKeyboard.h"
+#include "UICPresentation.h"
+#include "UICInputEngine.h"
+#include "UICApplication.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+using namespace Q3DStudio;
+using uic::runtime::IApplication;
+//==============================================================================
+// Statics
+//==============================================================================
+
+// This list needs to be in sync with EKeyCode (AKInputFrame.h)
+// TODO: Maybe auto-gen this in the future
+static const char *s_KeyCodeIdentifier[] = { "KEY_NOKEY",
+ "KEY_ESCAPE",
+ "KEY_1",
+ "KEY_2",
+ "KEY_3",
+ "KEY_4",
+ "KEY_5",
+ "KEY_6",
+ "KEY_7",
+ "KEY_8",
+ "KEY_9",
+ "KEY_0",
+ "KEY_SUBTRACT",
+ "KEY_EQUALS",
+ "KEY_BACK",
+ "KEY_TAB",
+ "KEY_Q",
+ "KEY_W",
+ "KEY_E",
+ "KEY_R",
+ "KEY_T",
+ "KEY_Y",
+ "KEY_U",
+ "KEY_I",
+ "KEY_O",
+ "KEY_P",
+ "KEY_LBRACKET",
+ "KEY_RBRACKET",
+ "KEY_RETURN",
+ "KEY_LCONTROL",
+ "KEY_A",
+ "KEY_S",
+ "KEY_D",
+ "KEY_F",
+ "KEY_G",
+ "KEY_H",
+ "KEY_J",
+ "KEY_K",
+ "KEY_L",
+ "KEY_SEMICOLON",
+ "KEY_APOSTROPHE",
+ "KEY_GRAVE",
+ "KEY_LSHIFT",
+ "KEY_BACKSLASH",
+ "KEY_Z",
+ "KEY_X",
+ "KEY_C",
+ "KEY_V",
+ "KEY_B",
+ "KEY_N",
+ "KEY_M",
+ "KEY_COMMA",
+ "KEY_PERIOD",
+ "KEY_SLASH",
+ "KEY_RSHIFT",
+ "KEY_MULTIPLY",
+ "KEY_LALT",
+ "KEY_SPACE",
+ "KEY_CAPITAL",
+ "KEY_F1",
+ "KEY_F2", // 60
+ "KEY_F3",
+ "KEY_F4",
+ "KEY_F5",
+ "KEY_F6",
+ "KEY_F7",
+ "KEY_F8",
+ "KEY_F9",
+ "KEY_F10",
+ "KEY_NUMLOCK",
+ "KEY_SCROLL", // 70
+ "KEY_NUMPAD7",
+ "KEY_NUMPAD8",
+ "KEY_NUMPAD9",
+ "KEY_NUMPADSUBTRACT",
+ "KEY_NUMPAD4",
+ "KEY_NUMPAD5",
+ "KEY_NUMPAD6",
+ "KEY_NUMPADADD",
+ "KEY_NUMPAD1",
+ "KEY_NUMPAD2", // 80
+ "KEY_NUMPAD3",
+ "KEY_NUMPAD0",
+ "KEY_NUMPADDECIMAL",
+ "KEY_NOOP",
+ "KEY_ZENKAKUHANKAKU",
+ "KEY_102ND",
+ "KEY_F11",
+ "KEY_F12",
+ "KEY_F13",
+ "KEY_F14", // 90
+ "KEY_HIRAGANA",
+ "KEY_HENKAN",
+ "KEY_KATAKANAHIRAGANA",
+ "KEY_MUHENKAN",
+ "KEY_KPJPCOMMA",
+ "KEY_NUMPADENTER",
+ "KEY_RCONTROL",
+ "KEY_NUMPADDIVIDE",
+ "KEY_PRINTSCREEN",
+ "KEY_RALT", // 100
+ "KEY_LINEFEED",
+ "KEY_HOME",
+ "KEY_UP",
+ "KEY_PGUP",
+ "KEY_LEFT",
+ "KEY_RIGHT",
+ "KEY_END",
+ "KEY_DOWN",
+ "KEY_PGDN",
+ "KEY_INSERT", // 110
+ "KEY_DELETE",
+ "KEY_MACRO",
+ "KEY_MUTE",
+ "KEY_VOLUMEDOWN",
+ "KEY_VOLUMEUP",
+ "KEY_POWER",
+ "KEY_KPEQUAL",
+ "KEY_KPPLUSMINUS",
+ "KEY_PAUSE",
+ "KEY_SCALE" };
+
+//==============================================================================
+/**
+ * Registers global keycodes
+ */
+void CLuaKeyboard::RegisterLibrary(lua_State *inLuaState)
+{
+ for (long theCount = 0; theCount < KEY_TOTAL_COUNT; ++theCount) {
+ lua_pushinteger(inLuaState, theCount);
+ lua_setglobal(inLuaState, s_KeyCodeIdentifier[theCount]);
+ }
+
+ // Register the hook function
+ lua_register(inLuaState, "getKeyState", GetKeyState);
+}
+
+//==============================================================================
+/**
+ * Gets the Key Table
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - boolean to indicate if the key is pressed
+ */
+int CLuaKeyboard::GetKeyState(lua_State *inLuaState)
+{
+ const INT32 ARG_KEYCODE = 1;
+
+ luaL_checktype(inLuaState, ARG_KEYCODE, LUA_TNUMBER);
+ long theKeyCode = lua_tointeger(inLuaState, ARG_KEYCODE);
+
+ // Check if the keycode is valid
+ if (theKeyCode >= KEY_TOTAL_COUNT || theKeyCode < KEY_NOKEY) {
+ qCInfo(qt3ds::TRACE_INFO) << "Lua: getKeyState: The keycode you entered is invalid";
+ theKeyCode = KEY_NOKEY;
+ }
+
+ // Check the key state
+ CPresentation *thePresentation = CLuaEngine::GetCurrentPresentation(inLuaState);
+ IApplication &theApplication = thePresentation->GetApplication();
+ SKeyInputFrame theInput = theApplication.GetInputEngine().GetKeyInputFrame();
+
+ lua_pushboolean(inLuaState,
+ KEY_NOKEY ? false : (theInput.GetKeyCount(theKeyCode) > 0 ? true : false));
+
+ return 1;
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaMatrix.cpp b/src/Runtime/Source/Runtime/Source/UICLuaMatrix.cpp
new file mode 100644
index 00000000..a1204d11
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaMatrix.cpp
@@ -0,0 +1,628 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaMatrix.h"
+#include "UICMatrix.h"
+#include "UICVector3.h"
+#include "UICLuaVector.h"
+#include "UICDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const CHAR *STRING_MATRIX_TYPE = "MatrixType";
+const CHAR *STRING_MATRIX_CLASS = "Matrix";
+const CHAR *STRING_ERROR_MATRIX_EXPECTED = "'Matrix' expected.";
+
+extern const CHAR *STRING_ERROR_WRONG_NUMBER_ARUGMENT;
+extern const CHAR *STRING_ERROR_ACCESS_NON_MEMBER;
+
+//==============================================================================
+/**
+ * Registers the type "Matrix" in Lua's global name space
+ * @param inLuaState the Lua state, required for interaction with lua
+ */
+void CLuaMatrix::RegisterLibrary(lua_State *inLuaState)
+{
+ static const luaL_Reg theMatrixLibrary[] = { { "new", Create }, { NULL, NULL } };
+
+ static const luaL_Reg theMatrixMethods[] = { { "setMatrix", SetMatrix },
+ { "set", Set },
+ { "setScale", SetScale },
+ { "setRotate", SetRotate },
+ { "setTranslate", SetTranslate },
+ { "equals", Equals },
+ { "identity", Identity },
+ { "invert", Invert },
+ { "isIdentity", IsIdentity },
+ { "multiply", Multiply },
+ { "scale", Scale },
+ { "translate", Translate },
+ { "rotate", Rotate },
+ { "transpose", Transpose },
+ { NULL, NULL } };
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ luaL_newmetatable(inLuaState,
+ STRING_MATRIX_TYPE); // Create a new metatable for this Matrix type
+ luaL_register(inLuaState, NULL,
+ theMatrixMethods); // Registers the additional methods to this metatable
+
+ lua_pushstring(inLuaState,
+ "__index"); // The GetValue to check if it's 'x', 'y' or 'z' when indexed
+ lua_pushcfunction(inLuaState, GetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState,
+ "__newindex"); // The SetValue to check if it's 'x', 'y' or 'z' when new indexed
+ lua_pushcfunction(inLuaState, SetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__tostring"); // Formatting
+ lua_pushcfunction(inLuaState, ToString);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__eq"); // Equality operator '=='
+ lua_pushcfunction(inLuaState, Equals);
+ lua_settable(inLuaState, 1);
+
+ luaL_register(inLuaState, STRING_MATRIX_CLASS,
+ theMatrixLibrary); // register the 'Matrix' class type with one method 'new'
+
+ lua_settop(inLuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * Creates a new Lua Matrix object and places it on the top of the Lua stack
+ * 3 ways to create the new color:
+ * 1) Matrix.new( ) -- a new identiy matrix
+ * 2) Matrix.new( inMatrix ) -- a new matrix with values set to inMatrix
+ *
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Create(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ RuntimeMatrix &theMatrix = CreateMatrix(inLuaState);
+
+ INT32 theOffset = lua_istable(inLuaState, 1) ? 1 : 0;
+
+ if (theTop == 0 + theOffset)
+ theMatrix.Identity();
+ else if (theTop == 1 + theOffset) {
+ RuntimeMatrix &theSource = CheckMatrix(inLuaState, 1 + theOffset);
+ theMatrix = theSource;
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ Q3DStudio_ASSERT(lua_gettop(inLuaState) == theTop + 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets a value of the matrix and places it on the top of the lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::GetValue(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrix = CheckMatrix(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+ BOOL theError = false;
+ INT32 theRow = -1;
+ INT32 theColumn = -1;
+
+ if (::strlen(theParam) != 3 || theParam[0] != '_')
+ theError = true;
+
+ if (!theError) {
+ theRow = theParam[1] - '1';
+ theColumn = theParam[2] - '1';
+
+ if (theRow < 0 || theRow > 3)
+ theError = true;
+ else if (theColumn < 0 || theColumn > 3)
+ theError = true;
+ }
+
+ if (!theError)
+ lua_pushnumber(inLuaState, theMatrix.Get(theRow, theColumn));
+ else {
+ lua_getmetatable(inLuaState, 1); // gets the metatable of this user type
+ lua_pushvalue(inLuaState, 2); // push the key onto the top of stack
+ lua_rawget(inLuaState, -2); // get the associated function, if any
+
+ if (lua_isnil(inLuaState, -1))
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+ }
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Sets a value of the matrix
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::SetValue(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrix = CheckMatrix(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+ UINT8 theValue = static_cast<UINT8>(luaL_checkinteger(inLuaState, 3));
+ BOOL theError = false;
+ INT32 theRow = -1;
+ INT32 theColumn = -1;
+
+ if (::strlen(theParam) != 3 || theParam[0] != '_')
+ theError = true;
+
+ if (!theError) {
+ theRow = theParam[1] - '1';
+ theColumn = theParam[2] - '1';
+
+ if (theRow < 0 || theRow > 3)
+ theError = true;
+ else if (theColumn < 0 || theColumn > 3)
+ theError = true;
+ }
+
+ if (!theError)
+ theMatrix.Set(theRow, theColumn, theValue);
+ else
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Set the matrix's value to the value of inMatrix which is on the top of the
+ * Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::SetMatrix(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theDestination = CheckMatrix(inLuaState);
+ RuntimeMatrix &theSource = CheckMatrix(inLuaState, 2);
+
+ theDestination = theSource;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the matrix's value to the value of in11, in12, in13, in14, in21, in22, in23, in24
+ * in31, in32, in33, in34, in41, in42, in43 and in44 which are on the top of
+ * the Lua stack respectively
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Set(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+
+ if (lua_gettop(inLuaState) != 17)
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ theMatrixA.Set(0, 0, static_cast<FLOAT>(luaL_checknumber(inLuaState, 2)));
+ theMatrixA.Set(0, 1, static_cast<FLOAT>(luaL_checknumber(inLuaState, 3)));
+ theMatrixA.Set(0, 2, static_cast<FLOAT>(luaL_checknumber(inLuaState, 4)));
+ theMatrixA.Set(0, 3, static_cast<FLOAT>(luaL_checknumber(inLuaState, 5)));
+
+ theMatrixA.Set(1, 0, static_cast<FLOAT>(luaL_checknumber(inLuaState, 6)));
+ theMatrixA.Set(1, 1, static_cast<FLOAT>(luaL_checknumber(inLuaState, 7)));
+ theMatrixA.Set(1, 2, static_cast<FLOAT>(luaL_checknumber(inLuaState, 8)));
+ theMatrixA.Set(1, 3, static_cast<FLOAT>(luaL_checknumber(inLuaState, 9)));
+
+ theMatrixA.Set(2, 0, static_cast<FLOAT>(luaL_checknumber(inLuaState, 10)));
+ theMatrixA.Set(2, 1, static_cast<FLOAT>(luaL_checknumber(inLuaState, 11)));
+ theMatrixA.Set(2, 2, static_cast<FLOAT>(luaL_checknumber(inLuaState, 12)));
+ theMatrixA.Set(2, 3, static_cast<FLOAT>(luaL_checknumber(inLuaState, 13)));
+
+ theMatrixA.Set(3, 0, static_cast<FLOAT>(luaL_checknumber(inLuaState, 14)));
+ theMatrixA.Set(3, 1, static_cast<FLOAT>(luaL_checknumber(inLuaState, 15)));
+ theMatrixA.Set(3, 2, static_cast<FLOAT>(luaL_checknumber(inLuaState, 16)));
+ theMatrixA.Set(3, 3, static_cast<FLOAT>(luaL_checknumber(inLuaState, 17)));
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the matrix's scale portion without affecting the rest
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::SetScale(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ INT32 theTop = lua_gettop(inLuaState);
+
+ if (theTop == 2) {
+ RuntimeVector3 &theScale = CLuaVector::CheckVector(inLuaState, 2);
+ theMatrixA.SetScale(theScale);
+ } else if (theTop == 4) {
+ FLOAT theX = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ FLOAT theY = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ FLOAT theZ = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ RuntimeVector3 theScale(theX, theY, theZ);
+ theMatrixA.SetScale(theScale);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the matrix's rotation portion
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::SetRotate(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ INT32 theTop = lua_gettop(inLuaState);
+
+ if (theTop == 2) {
+ RuntimeVector3 &theRotate = CLuaVector::CheckVector(inLuaState, 2);
+ theMatrixA.SetRotate(theRotate, RuntimeMatrix::ROTATIONORDER_YXZ, 0);
+ } else if (theTop == 4) {
+ FLOAT theX = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ FLOAT theY = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ FLOAT theZ = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ RuntimeVector3 theRotate(theX, theY, theZ);
+ theMatrixA.SetRotate(theRotate, RuntimeMatrix::ROTATIONORDER_YXZ, 0);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the matrix's translate portion without affecting the rest
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::SetTranslate(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ INT32 theTop = lua_gettop(inLuaState);
+
+ if (theTop == 2) {
+ RuntimeVector3 &theTranslate = CLuaVector::CheckVector(inLuaState, 2);
+ theMatrixA.SetTranslate(theTranslate);
+ } else if (theTop == 4) {
+ FLOAT theX = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ FLOAT theY = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ FLOAT theZ = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ RuntimeVector3 theTranslate(theX, theY, theZ);
+ theMatrixA.SetTranslate(theTranslate);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Checks for equality of 2 matrixes
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Equals(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState, 1);
+ RuntimeMatrix &theMatrixB = CheckMatrix(inLuaState, 2);
+
+ lua_pushboolean(inLuaState, theMatrixA == theMatrixB);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Resets the matrix to identity matrix
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Identity(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+
+ theMatrixA.Identity();
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Inverts the matrix placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Invert(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+
+ lua_pushnumber(inLuaState, theMatrixA.Invert());
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Checks if the matrix placed on the top of the Lua stack is an identity matrix
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::IsIdentity(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+
+ lua_pushboolean(inLuaState, theMatrixA.IsIdentity());
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Multiplies the 2 matrixes on the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Multiply(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState, 1);
+ RuntimeMatrix &theMatrixB = CheckMatrix(inLuaState, 2);
+
+ theMatrixA.Multiply(theMatrixB);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Performs additional scaling to the matrix on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Scale(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ INT32 theTop = lua_gettop(inLuaState);
+
+ if (theTop == 2) {
+ RuntimeVector3 &theScale = CLuaVector::CheckVector(inLuaState, 2);
+ theMatrixA.Scale(theScale);
+ } else if (theTop == 4) {
+ FLOAT theX = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ FLOAT theY = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ FLOAT theZ = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ RuntimeVector3 theScale(theX, theY, theZ);
+ theMatrixA.Scale(theScale);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Performs additional translation to the matrix on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Translate(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ INT32 theTop = lua_gettop(inLuaState);
+
+ if (theTop == 2) {
+ RuntimeVector3 &theTranslate = CLuaVector::CheckVector(inLuaState, 2);
+ theMatrixA.Translate(theTranslate);
+ } else if (theTop == 4) {
+ FLOAT theX = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ FLOAT theY = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ FLOAT theZ = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ RuntimeVector3 theTranslate(theX, theY, theZ);
+ theMatrixA.Translate(theTranslate);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Performs additional rotation to the matrix on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Rotate(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ INT32 theTop = lua_gettop(inLuaState);
+ RuntimeMatrix theRotationMatrix;
+
+ if (theTop == 2) {
+ RuntimeVector3 &theEulerAngles = CLuaVector::CheckVector(inLuaState, 2);
+ theRotationMatrix.SetRotate(theEulerAngles, RuntimeMatrix::ROTATIONORDER_YXZ, 0);
+ theMatrixA.Multiply(theRotationMatrix);
+ } else if (theTop == 4) {
+ FLOAT theX = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ FLOAT theY = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ FLOAT theZ = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ RuntimeVector3 theEulerAngles(theX, theY, theZ);
+ theRotationMatrix.SetRotate(theEulerAngles, RuntimeMatrix::ROTATIONORDER_YXZ, 0);
+ theMatrixA.Multiply(theRotationMatrix);
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Flips the matrix elements around the identity diagonal
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::Transpose(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrixA = CheckMatrix(inLuaState);
+ theMatrixA.Transpose();
+
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Formats the Matrix object into a string and place the string on the top of Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaMatrix::ToString(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix &theMatrix = CheckMatrix(inLuaState);
+
+ lua_pushstring(inLuaState, "string");
+ lua_rawget(inLuaState, LUA_GLOBALSINDEX);
+
+ lua_getfield(inLuaState, -1, "format");
+
+ lua_pushstring(inLuaState, "Matrix:\n%8.2f %8.2f %8.2f %8.2f\n%8.2f %8.2f %8.2f %8.2f\n%8.2f "
+ "%8.2f %8.2f %8.2f\n%8.2f %8.2f %8.2f %8.2f");
+
+ for (INT32 theRow = 0; theRow < 4; ++theRow)
+ for (INT32 theCol = 0; theCol < 4; ++theCol)
+ lua_pushnumber(inLuaState, theMatrix.m_Data[theRow][theCol]);
+
+ lua_pcall(inLuaState, 17, 1, 0);
+
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Helper to check the type of the userdata is of STRING_MATRIX_TYPE
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inIndex the index to where on the stack to check
+ * @return the reference to the userdata pointed to by inIndex
+ */
+RuntimeMatrix &CLuaMatrix::CheckMatrix(lua_State *inLuaState, const INT32 inIndex)
+{
+ // PerfLogLuaMathEvent1( DATALOGGER_LUA_MATRIX );
+
+ RuntimeMatrix *theMatrix =
+ reinterpret_cast<RuntimeMatrix *>(luaL_checkudata(inLuaState, inIndex, STRING_MATRIX_TYPE));
+ luaL_argcheck(inLuaState, theMatrix != NULL, 1, STRING_ERROR_MATRIX_EXPECTED);
+ return *theMatrix;
+}
+
+//==============================================================================
+/**
+ * Helper to create a new userdata of STRING_MATRIX_TYPE on the top of the stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the reference to the userdata pointed to by inIndex
+ */
+RuntimeMatrix &CLuaMatrix::CreateMatrix(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_MATRIX);
+
+ RuntimeMatrix *theMatrix = reinterpret_cast<RuntimeMatrix *>(lua_newuserdata(inLuaState, sizeof(RuntimeMatrix)));
+
+ // associate the metatable with CMatrix
+ luaL_getmetatable(inLuaState, STRING_MATRIX_TYPE);
+ lua_setmetatable(inLuaState, -2);
+
+ return *theMatrix;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaRotation.cpp b/src/Runtime/Source/Runtime/Source/UICLuaRotation.cpp
new file mode 100644
index 00000000..2c691f71
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaRotation.cpp
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaRotation.h"
+#include "UICLuaVector.h"
+#include "UICVector3.h"
+#include <math.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const CHAR *STRING_ROTATION_TYPE = "RotationType";
+const CHAR *STRING_ROTATION_CLASS = "Rotation";
+const CHAR *STRING_ERROR_ROTATION_EXPECTED = "'Rotation' expected.";
+
+extern const CHAR *STRING_ERROR_WRONG_NUMBER_ARUGMENT;
+extern const CHAR *STRING_ERROR_ACCESS_NON_MEMBER;
+
+//==============================================================================
+/**
+ * Registers the type "Rotation" in Lua's global name space
+ * @param inLuaState the Lua state, required for interaction with lua
+ */
+void CLuaRotation::RegisterLibrary(lua_State *inLuaState)
+{
+ static const luaL_Reg theRotationLibrary[] = { { "new", Create }, { NULL, NULL } };
+
+ static const luaL_Reg theRotationMethods[] = {
+ { "setRotation", SetRotation }, { "set", Set }, { "add", Add },
+ { "subtract", Subtract }, { "scale", Scale }, { "equals", Equals },
+ { "lookAt", LookAt }, { NULL, NULL }
+ };
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ luaL_newmetatable(inLuaState,
+ STRING_ROTATION_TYPE); // Create a new metatable for this Rotation type
+ luaL_register(inLuaState, NULL,
+ theRotationMethods); // Registers the additional methods to this metatable
+
+ lua_pushstring(inLuaState,
+ "__index"); // The GetValue to check if it's 'x', 'y' or 'z' when indexed
+ lua_pushcfunction(inLuaState, GetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState,
+ "__newindex"); // The SetValue to check if it's 'x', 'y' or 'z' when new indexed
+ lua_pushcfunction(inLuaState, SetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__tostring"); // Formatting
+ lua_pushcfunction(inLuaState, ToString);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__add"); // Addition operator '+'
+ lua_pushcfunction(inLuaState, AddNew);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__sub"); // Subtraction operator '-'
+ lua_pushcfunction(inLuaState, SubtractNew);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__mul"); // Multiplication operator '*'
+ lua_pushcfunction(inLuaState, ScaleNew);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__eq"); // Equality operator '=='
+ lua_pushcfunction(inLuaState, Equals);
+ lua_settable(inLuaState, 1);
+
+ luaL_register(inLuaState, STRING_ROTATION_CLASS,
+ theRotationLibrary); // register the 'Rotation' class type with one method 'new'
+
+ lua_settop(inLuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * Creates a new Lua Rotation object and places it on the top of the Lua stack
+ * 3 ways to create the new rotation:
+ * 1) Rotation.new( ) -- a new rotation with x, y and z all
+ *initialized to 0
+ * 2) Rotation.new( inRotation ) -- a new rotation with x, y and z all initialized
+ *to the values of inRotation
+ * 3) Rotation.new( inX, inY, inZ ) -- a new rotation with x, y and z all initialized to
+ *the values of inX, inY and inZ
+ *
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::Create(lua_State *inLuaState)
+{
+ INT32 theTop = lua_gettop(inLuaState);
+
+ RuntimeVector3 &theRotation = CreateRotation(inLuaState);
+
+ INT32 theOffset = lua_istable(inLuaState, 1) ? 1 : 0;
+
+ if (theTop == 0 + theOffset) {
+ theRotation.m_X = 0.0f;
+ theRotation.m_Y = 0.0f;
+ theRotation.m_Z = 0.0f;
+ } else if (theTop == 1 + theOffset) {
+ RuntimeVector3 &theSource = CheckRotation(inLuaState, 1 + theOffset);
+ theRotation = theSource;
+ } else if (theTop == 3 + theOffset) {
+ theRotation.m_X = static_cast<FLOAT>(luaL_checknumber(inLuaState, 1 + theOffset));
+ theRotation.m_Y = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2 + theOffset));
+ theRotation.m_Z = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3 + theOffset));
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ Q3DStudio_ASSERT(lua_gettop(inLuaState) == theTop + 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the value of x or y or z and places it on the top of the lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::GetValue(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotation = CheckRotation(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+
+ if (::strcmp(theParam, "x") == 0)
+ lua_pushnumber(inLuaState, theRotation.m_X);
+ else if (::strcmp(theParam, "y") == 0)
+ lua_pushnumber(inLuaState, theRotation.m_Y);
+ else if (::strcmp(theParam, "z") == 0)
+ lua_pushnumber(inLuaState, theRotation.m_Z);
+ else {
+ lua_getmetatable(inLuaState, 1); // gets the metatable of this user type
+ lua_pushvalue(inLuaState, 2); // push the key onto the top of stack
+ lua_rawget(inLuaState, -2); // get the associated function, if any
+
+ if (lua_isnil(inLuaState, -1))
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+ }
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Sets the value of x or y or z
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::SetValue(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotation = CheckRotation(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+ FLOAT theValue = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+
+ if (::strcmp(theParam, "x") == 0)
+ theRotation.m_X = theValue;
+ else if (::strcmp(theParam, "y") == 0)
+ theRotation.m_Y = theValue;
+ else if (::strcmp(theParam, "z") == 0)
+ theRotation.m_Z = theValue;
+ else
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Set the rotation's value to the value of inRotation which is on the top of the
+ * Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::SetRotation(lua_State *inLuaState)
+{
+ RuntimeVector3 &theDestination = CheckRotation(inLuaState);
+ RuntimeVector3 &theSource = CheckRotation(inLuaState, 2);
+
+ theDestination = theSource;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the rotation's value to the value of inX, inY and inZ which are on the top
+ * of the Lua stack respectively
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::Set(lua_State *inLuaState)
+{
+ RuntimeVector3 &theDestination = CheckRotation(inLuaState);
+
+ theDestination.m_X = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ theDestination.m_Y = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ theDestination.m_Z = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Adds the 2 rotations on the Lua stack, and stores the result in the first
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::Add(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState, 1); // 1 = Rotation A
+ RuntimeVector3 &theRotationB = CheckRotation(inLuaState, 2); // 2 = Rotation B
+
+ theRotationA += theRotationB;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Adds the 2 vectors on the Lua stack, and stores the result in a new vector
+ * placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::AddNew(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState, 1); // 1 = Rotation A
+ RuntimeVector3 &theRotationB = CheckRotation(inLuaState, 2); // 2 = Rotation B
+ RuntimeVector3 &theResult = CreateRotation(inLuaState);
+
+ theResult = theRotationA + theRotationB;
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Subtracts the 2nd vector on the Lua stack from the 1st, and stores the
+ * result in the first
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::Subtract(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState, 1); // 1 = Rotation A
+ RuntimeVector3 &theRotationB = CheckRotation(inLuaState, 2); // 2 = Rotation B
+
+ theRotationA -= theRotationB;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Subtracts the 2nd vector on the Lua stack from the 1st, and stores the
+ * result in a new vector placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::SubtractNew(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState, 1); // 1 = Rotation A
+ RuntimeVector3 &theRotationB = CheckRotation(inLuaState, 2); // 2 = Rotation B
+ RuntimeVector3 &theResult = CreateRotation(inLuaState);
+
+ theResult = theRotationA - theRotationB;
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Scales the vector with the factor that's placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::Scale(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState);
+ FLOAT theFactor = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+
+ theRotationA *= theFactor;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Scales the vector with the factor that's placed on the top of the Lua stack
+ * and stores the result in a new vector placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::ScaleNew(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState);
+ FLOAT theFactor = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ RuntimeVector3 &theResult = CreateRotation(inLuaState);
+
+ theResult = theRotationA * theFactor;
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Checks for equality of 2 rotations
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::Equals(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState, 1);
+ RuntimeVector3 &theRotationB = CheckRotation(inLuaState, 2);
+
+ lua_pushboolean(inLuaState, theRotationA == theRotationB);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Sets the rotation angles to look at a vector
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::LookAt(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotationA = CheckRotation(inLuaState, 1);
+ RuntimeVector3 &theVector = CLuaVector::CheckVector(inLuaState, 2);
+
+ FLOAT theMag = ::sqrtf(theVector.m_X * theVector.m_X + theVector.m_Z * theVector.m_Z);
+#ifdef _TEGRAPLATFORM
+ FLOAT thePitch = static_cast<FLOAT>(-::atan2((double)theVector.m_Y, (double)theMag));
+ FLOAT theYaw = static_cast<FLOAT>(::atan2((double)theVector.m_X, (double)theVector.m_Z));
+#else
+ FLOAT thePitch = -::atan2f(theVector.m_Y, theMag);
+ FLOAT theYaw = ::atan2f(theVector.m_X, theVector.m_Z);
+#endif
+
+ theRotationA.Set(thePitch, theYaw, 0.0f);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Formats the Rotation object into a string and place the string on the top of Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaRotation::ToString(lua_State *inLuaState)
+{
+ RuntimeVector3 &theRotation = CheckRotation(inLuaState);
+
+ lua_pushfstring(inLuaState, "Rotation: %f, %f, %f", theRotation.m_X, theRotation.m_Y,
+ theRotation.m_Z);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Helper to check the type of the userdata is of STRING_ROTATION_TYPE
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inIndex the index to where on the stack to check
+ * @return the reference to the userdata pointed to by inIndex
+ */
+RuntimeVector3 &CLuaRotation::CheckRotation(lua_State *inLuaState, const INT32 inIndex)
+{
+ RuntimeVector3 *theRotation =
+ reinterpret_cast<RuntimeVector3 *>(luaL_checkudata(inLuaState, inIndex, STRING_ROTATION_TYPE));
+ luaL_argcheck(inLuaState, theRotation != NULL, 1, STRING_ERROR_ROTATION_EXPECTED);
+ return *theRotation;
+}
+
+//==============================================================================
+/**
+ * Helper to create a new userdata of STRING_ROTATION_TYPE on the top of the stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the reference to the userdata pointed to by inIndex
+ */
+RuntimeVector3 &CLuaRotation::CreateRotation(lua_State *inLuaState)
+{
+ RuntimeVector3 *theRotation =
+ reinterpret_cast<RuntimeVector3 *>(lua_newuserdata(inLuaState, sizeof(RuntimeVector3)));
+
+ // associate the metatable with CVector3
+ luaL_getmetatable(inLuaState, STRING_ROTATION_TYPE);
+ lua_setmetatable(inLuaState, -2);
+
+ return *theRotation;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaSceneHelper.cpp b/src/Runtime/Source/Runtime/Source/UICLuaSceneHelper.cpp
new file mode 100644
index 00000000..447361c1
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaSceneHelper.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaSceneHelper.h"
+#include "UICPresentation.h"
+#include "UICAttributeHashes.h"
+#include "UICIScene.h"
+#include "UICLuaVector.h"
+#include "UICLuaMatrix.h"
+#include "UICBoundingBox.h"
+#include "UICMatrix.h"
+#include "UICVector3.h"
+
+#include "UICDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const INT32 RECURSION_LIMIT = 2;
+
+//==============================================================================
+/**
+ * Calculates the global opacity of a given element
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the calculated global opacity that is pushed onto the stack
+ * or nil if what's passed in is not a node in the scene graph.
+ */
+int CLuaSceneHelper::CalculateGlobalOpacity(lua_State *inLuaState)
+{
+ const INT32 ARG_ELEMENT = 1;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ // TODO: Update the code to use the new UICRender's SNode
+ Q3DStudio_ASSERT(false);
+ /*
+ TElement* theElement = reinterpret_cast<TElement*>( lua_touserdata( inLuaState, ARG_ELEMENT ) );
+
+ // Grab the associated asset
+ SAsset* theAsset = reinterpret_cast<SAsset*>( theElement->GetAssociation( ) );
+
+ // Is this really an Element/Asset? (reinterpret_cast is scary)
+ Q3DStudio_ASSERT( theElement->GetType() < Q3DStudio::ELEMENTTYPECOUNT );
+ Q3DStudio_ASSERT( theAsset->m_Type < Q3DStudio::ASSETTYPECOUNT );
+
+ // If the asset is a node, multiply up the chain, otherwise return nil
+ if( theAsset->m_NodeFlag )
+ {
+ FLOAT theOutOpacity = -1;
+ SNode* theNode = static_cast<SNode*>( theAsset );
+ theOutOpacity = theNode->m_LocalOpacity;
+ while ( theNode->m_Parent )
+ {
+ theNode = theNode->m_Parent;
+ theOutOpacity *= theNode->m_LocalOpacity;
+ }
+
+ // The opacities in the scene graph are stored [0,1]
+ theOutOpacity *= 100;
+ lua_pushnumber( inLuaState, theOutOpacity );
+ }
+ else
+ {
+ lua_pushnil( inLuaState );
+ }
+ */
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the bounding box of itself and including all it's children's
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 2 - the min point and the max point of the bounding box was pushed
+ * on the stack
+ */
+int CLuaSceneHelper::CalculateBoundingBox(lua_State *inLuaState)
+{
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_MIN = 2;
+ const INT32 LOCAL_ARG_MAX = 3;
+ const INT32 ARG_CHILDRENFLAG = 4;
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ RuntimeVector3 &theMinVector = CLuaVector::CheckVector(inLuaState, ARG_MIN);
+ RuntimeVector3 &theMaxVector = CLuaVector::CheckVector(inLuaState, LOCAL_ARG_MAX);
+
+ BOOL theOnlySelfFlag = false;
+ if (theTop == 4) {
+ luaL_checktype(inLuaState, ARG_CHILDRENFLAG, LUA_TBOOLEAN);
+ theOnlySelfFlag = lua_toboolean(inLuaState, ARG_CHILDRENFLAG) ? true : false;
+ }
+
+ CBoundingBox theBoundingBox;
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ if (thePresentation->GetScene())
+ theBoundingBox = thePresentation->GetScene()->GetBoundingBox(theElement, theOnlySelfFlag);
+
+ theMinVector = theBoundingBox.GetMin();
+ theMaxVector = theBoundingBox.GetMax();
+
+ lua_pushvalue(inLuaState, ARG_MIN);
+ lua_pushvalue(inLuaState, LOCAL_ARG_MAX);
+
+ return 2;
+}
+
+int CLuaSceneHelper::CalculateLocalBoundingBox(lua_State *inLuaState)
+{
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_MIN = 2;
+ const INT32 LOCAL_ARG_MAX = 3;
+ const INT32 ARG_CHILDRENFLAG = 4;
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ RuntimeVector3 &theMinVector = CLuaVector::CheckVector(inLuaState, ARG_MIN);
+ RuntimeVector3 &theMaxVector = CLuaVector::CheckVector(inLuaState, LOCAL_ARG_MAX);
+
+ BOOL theOnlySelfFlag = false;
+ if (theTop == 4) {
+ luaL_checktype(inLuaState, ARG_CHILDRENFLAG, LUA_TBOOLEAN);
+ theOnlySelfFlag = lua_toboolean(inLuaState, ARG_CHILDRENFLAG) ? true : false;
+ }
+
+ CBoundingBox theBoundingBox;
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ if (thePresentation->GetScene())
+ theBoundingBox =
+ thePresentation->GetScene()->GetLocalBoundingBox(theElement, theOnlySelfFlag);
+
+ theMinVector = theBoundingBox.GetMin();
+ theMaxVector = theBoundingBox.GetMax();
+
+ lua_pushvalue(inLuaState, ARG_MIN);
+ lua_pushvalue(inLuaState, LOCAL_ARG_MAX);
+
+ return 2;
+}
+
+//==============================================================================
+/**
+ * Calculates the global transform of a given element
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the calculated global transform that was pushed onto the stack.
+ */
+int CLuaSceneHelper::CalculateGlobalTransform(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_CALCULATEGLOBALTRANSFORM);
+
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_MATRIX = 2;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ RuntimeMatrix &theGlobalTransform = CLuaMatrix::CheckMatrix(inLuaState, ARG_MATRIX);
+ theGlobalTransform.Identity();
+
+ IScene *theScene = theElement->GetBelongedPresentation()->GetScene();
+
+ // This return a matrix in the right hand coordinate system.
+ theScene->CalculateGlobalTransform(theElement, theGlobalTransform);
+
+ // Change to a left hand coordinate system
+ theGlobalTransform.FlipCoordinateSystem();
+
+ lua_pushvalue(inLuaState, ARG_MATRIX);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the global transform of a given element
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return 1 - the calculated global transform that was pushed onto the stack.
+ */
+int CLuaSceneHelper::SetLocalTransformMatrix(lua_State *inLuaState)
+{
+ PerfLogLuaEvent1(DATALOGGER_LUA_SETLOCALTRANSFORMMATRIX);
+
+ const INT32 ARG_ELEMENT = 1;
+ const INT32 ARG_MATRIX = 2;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ RuntimeMatrix &theLocalTransform = CLuaMatrix::CheckMatrix(inLuaState, ARG_MATRIX);
+
+ IScene *theScene = theElement->GetBelongedPresentation()->GetScene();
+ theScene->SetLocalTransformMatrix(theElement, theLocalTransform);
+
+ lua_pushvalue(inLuaState, ARG_ELEMENT);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Get the image info from the renderer
+ */
+int CLuaSceneHelper::GetImageInfo(lua_State *inLuaState)
+{
+ const INT32 ARG_ELEMENT = 1;
+
+ INT32 theWidth = 0;
+ INT32 theHeight = 0;
+
+ luaL_checktype(inLuaState, ARG_ELEMENT, LUA_TLIGHTUSERDATA);
+ TElement *theElement = reinterpret_cast<TElement *>(lua_touserdata(inLuaState, ARG_ELEMENT));
+
+ if (theElement) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+
+ if (thePresentation && thePresentation->GetScene())
+ thePresentation->GetScene()->GetImageInfoFromRenderEngine(theElement, theWidth,
+ theHeight);
+ else
+ qCCritical(qt3ds::INVALID_OPERATION) << "GetImageInfo failed to get a scene//presentation";
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION) << "GetImageInfo wasn't passed an image element";
+ }
+
+ lua_pushnumber(inLuaState, theWidth);
+ lua_pushnumber(inLuaState, theHeight);
+
+ // we pushed 2 numbers to lua
+ return 2;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICLuaVector.cpp b/src/Runtime/Source/Runtime/Source/UICLuaVector.cpp
new file mode 100644
index 00000000..1e1a0835
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICLuaVector.cpp
@@ -0,0 +1,644 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICLuaVector.h"
+#include "UICVector3.h"
+#include "UICLuaMatrix.h"
+#include "UICDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const CHAR *CLuaVector::STRING_VECTOR_TYPE = "VectorType";
+const CHAR *CLuaVector::STRING_VECTOR_CLASS = "Vector";
+const CHAR *STRING_ERROR_VECTOR_EXPECTED = "'Vector' expected.";
+
+const CHAR *STRING_ERROR_WRONG_NUMBER_ARUGMENT = "Wrong number of arguments given.";
+const CHAR *STRING_ERROR_ACCESS_NON_MEMBER = "Attempt to access a non member.";
+
+//==============================================================================
+/**
+ * Registers the type "Vector" in Lua's global name space
+ * @param inLuaState the Lua state, required for interaction with lua
+ */
+void CLuaVector::RegisterLibrary(lua_State *inLuaState)
+{
+ static const luaL_Reg theVectorLibrary[] = { { "new", Create }, { NULL, NULL } };
+
+ static const luaL_Reg theVectorMethods[] = { { "setVector", SetVector },
+ { "set", Set },
+ { "add", Add },
+ { "subtract", Subtract },
+ { "scale", Scale },
+ { "equals", Equals },
+ { "dot", DotProduct },
+ { "cross", CrossProduct },
+ { "normalize", Normalize },
+ { "length", Length },
+ { "lengthSquared", LengthSquared },
+ { "distance", Distance },
+ { "distanceSquared", DistanceSquared },
+ { "minVector", MinVector },
+ { "maxVector", MaxVector },
+ { "linear", Linear },
+ { "transform", Transform },
+ { NULL, NULL } };
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ luaL_newmetatable(inLuaState,
+ STRING_VECTOR_TYPE); // Create a new metatable for this Vector type
+ luaL_register(inLuaState, NULL,
+ theVectorMethods); // Registers the additional methods to this metatable
+
+ lua_pushstring(inLuaState,
+ "__index"); // The GetValue to check if it's 'x', 'y' or 'z' when indexed
+ lua_pushcfunction(inLuaState, GetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState,
+ "__newindex"); // The SetValue to check if it's 'x', 'y' or 'z' when new indexed
+ lua_pushcfunction(inLuaState, SetValue);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__tostring"); // Formatting
+ lua_pushcfunction(inLuaState, ToString);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__add"); // Addition operator '+'
+ lua_pushcfunction(inLuaState, AddNew);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__sub"); // Subtraction operator '-'
+ lua_pushcfunction(inLuaState, SubtractNew);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__mul"); // Multiplication operator '*'
+ lua_pushcfunction(inLuaState, ScaleNew);
+ lua_settable(inLuaState, 1);
+
+ lua_pushstring(inLuaState, "__eq"); // Equality operator '=='
+ lua_pushcfunction(inLuaState, Equals);
+ lua_settable(inLuaState, 1);
+
+ luaL_register(inLuaState, STRING_VECTOR_CLASS,
+ theVectorLibrary); // register the 'Vector' class type with one method 'new'
+
+ lua_settop(inLuaState, theTop);
+}
+
+//==============================================================================
+/**
+ * Creates a new Lua Vector object and places it on the top of the Lua stack
+ * 3 ways to creat the new vector:
+ * 1) Vector.new( ) -- a new vector with x,y and z all initialized to
+ *0
+ * 2) Vector.new( inVector ) -- a new vector with x,y and z all initialized to the
+ *values of inVector
+ * 3) Vector.new( inX, inY, inZ ) -- a new vector with x,y and z all initialized to the
+ *values of inX, inY and inZ
+ *
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of results pushed to the stack
+ */
+int CLuaVector::Create(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ INT32 theTop = lua_gettop(inLuaState);
+
+ RuntimeVector3 &theVector = CreateVector(inLuaState);
+
+ INT32 theOffset = lua_istable(inLuaState, 1) ? 1 : 0;
+
+ if (theTop == 0 + theOffset) {
+ theVector.m_X = 0.0f;
+ theVector.m_Y = 0.0f;
+ theVector.m_Z = 0.0f;
+ } else if (theTop == 1 + theOffset) {
+ RuntimeVector3 &theSource = CheckVector(inLuaState, 1 + theOffset);
+ theVector = theSource;
+ } else if (theTop == 3 + theOffset) {
+ theVector.m_X = static_cast<FLOAT>(luaL_checknumber(inLuaState, 1 + theOffset));
+ theVector.m_Y = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2 + theOffset));
+ theVector.m_Z = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3 + theOffset));
+ } else
+ luaL_error(inLuaState, STRING_ERROR_WRONG_NUMBER_ARUGMENT);
+
+ Q3DStudio_ASSERT(lua_gettop(inLuaState) == theTop + 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Gets the value of x or y or z and place it on the top of lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::GetValue(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVector = CheckVector(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+
+ if (::strcmp(theParam, "x") == 0)
+ lua_pushnumber(inLuaState, theVector.m_X);
+ else if (::strcmp(theParam, "y") == 0)
+ lua_pushnumber(inLuaState, theVector.m_Y);
+ else if (::strcmp(theParam, "z") == 0)
+ lua_pushnumber(inLuaState, theVector.m_Z);
+ else {
+ lua_getmetatable(inLuaState, 1); // gets the metatable of this user type
+ lua_pushvalue(inLuaState, 2); // push the key onto the top of stack
+ lua_rawget(inLuaState, -2); // get the associated function, if any
+
+ if (lua_isnil(inLuaState, -1))
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+ }
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Sets the value of x or y or z
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::SetValue(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVector = CheckVector(inLuaState);
+ const CHAR *theParam = luaL_checkstring(inLuaState, 2);
+ FLOAT theValue = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+
+ if (::strcmp(theParam, "x") == 0)
+ theVector.m_X = theValue;
+ else if (::strcmp(theParam, "y") == 0)
+ theVector.m_Y = theValue;
+ else if (::strcmp(theParam, "z") == 0)
+ theVector.m_Z = theValue;
+ else
+ luaL_error(inLuaState, STRING_ERROR_ACCESS_NON_MEMBER);
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Set the vector's value to the value of inVector which is on the top of the
+ * Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::SetVector(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theDestination = CheckVector(inLuaState);
+ RuntimeVector3 &theSource = CheckVector(inLuaState, 2);
+
+ theDestination = theSource;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Set the vector's value to the value of inX, inY, inZ which are on the top
+ * of the Lua stack respectively
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Set(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theDestination = CheckVector(inLuaState);
+
+ theDestination.m_X = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ theDestination.m_Y = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+ theDestination.m_Z = static_cast<FLOAT>(luaL_checknumber(inLuaState, 4));
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Adds the 2 vectors on the Lua stack, and stores the result in the first
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Add(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1); // 1 = Vector A
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2); // 2 = Vector B
+
+ theVectorA += theVectorB;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Adds the 2 vectors on the Lua stack, and stores the result in a new vector
+ * placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::AddNew(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1); // 1 = Vector A
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2); // 2 = Vector B
+ RuntimeVector3 &theResult = CreateVector(inLuaState);
+
+ theResult = theVectorA + theVectorB;
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Subtracts the 2nd vector on the Lua stack from the 1st, and stores the
+ * result in the first
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Subtract(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1); // 1 = Vector A
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2); // 2 = Vector B
+
+ theVectorA -= theVectorB;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Subtracts the 2nd vector on the Lua stack from the 1st, and stores the
+ * result in a new vector placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::SubtractNew(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1); // 1 = Vector A
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2); // 2 = Vector B
+ RuntimeVector3 &theResult = CreateVector(inLuaState);
+
+ theResult = theVectorA - theVectorB;
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Scales the vector with the factor that's placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Scale(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState);
+ FLOAT theFactor = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+
+ theVectorA *= theFactor;
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Scales the vector with the factor that's placed on the top of the Lua stack
+ * and stores the result in a new vector placed on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::ScaleNew(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState);
+ FLOAT theFactor = static_cast<FLOAT>(luaL_checknumber(inLuaState, 2));
+ RuntimeVector3 &theResult = CreateVector(inLuaState);
+
+ theResult = theVectorA * theFactor;
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Checks for equality of 2 vectors
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Equals(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ lua_pushboolean(inLuaState, theVectorA == theVectorB);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the dot product of the first vector with the 2nd vector and places
+ * the FLOAT result on the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::DotProduct(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ lua_pushnumber(inLuaState, theVectorA.DotProduct(theVectorB));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the cross product of the first vector with the 2nd vector and
+ * places the Vector result on the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::CrossProduct(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ theVectorA.CrossProduct(theVectorB);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Makes the vector a unit vector
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Normalize(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState);
+
+ theVectorA.Normalize();
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the length (magnitude) of the vector and places the FLOAT result
+ * on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Length(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState);
+
+ lua_pushnumber(inLuaState, theVectorA.Length());
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the squared length (magnitude) of the vector and places the FLOAT
+ * result on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::LengthSquared(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState);
+
+ lua_pushnumber(inLuaState, theVectorA.LengthSquared());
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the distance between 2 vectors and places the FLOAT result
+ * on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Distance(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ lua_pushnumber(inLuaState, theVectorA.Distance(theVectorB));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Calculates the squared distance between 2 vectors and places the FLOAT result
+ * on the top of the Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::DistanceSquared(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ lua_pushnumber(inLuaState, theVectorA.DistanceSquared(theVectorB));
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Modifies the first vector to contain the min values of the 1st and 2nd vectors
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::MinVector(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ theVectorA.Minimize(theVectorB);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Modifies the first vector to contain the max values of the 1st and 2nd vectors
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::MaxVector(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+
+ theVectorA.Maximize(theVectorB);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Modifies the first vector by performing a linear interpolation between the
+ * 1st vector and the 2nd vector
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Linear(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeVector3 &theVectorB = CheckVector(inLuaState, 2);
+ FLOAT theFactor = static_cast<FLOAT>(luaL_checknumber(inLuaState, 3));
+
+ theVectorA.InterpolateLinear(theVectorB, theFactor);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Transform the vector with the matrix on the 2nd position on the stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::Transform(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVectorA = CheckVector(inLuaState, 1);
+ RuntimeMatrix &theMatrixB = CLuaMatrix::CheckMatrix(inLuaState, 2);
+
+ theVectorA.Transform(theMatrixB);
+ lua_pushvalue(inLuaState, 1);
+ return 1;
+}
+//==============================================================================
+/**
+ * Formats the Vector object into a string and place the string on the top of Lua stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the number of items pushed onto the stack
+ */
+int CLuaVector::ToString(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 &theVector = CheckVector(inLuaState);
+
+ lua_pushfstring(inLuaState, "Vector: %f, %f, %f", theVector.m_X, theVector.m_Y, theVector.m_Z);
+
+ return 1;
+}
+
+//==============================================================================
+/**
+ * Helper to check the type of the userdata is of STRING_VECTOR_TYPE
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @param inIndex the index to where on the stack to check
+ * @return the reference to the userdata pointed to by inIndex
+ */
+RuntimeVector3 &CLuaVector::CheckVector(lua_State *inLuaState, const INT32 inIndex)
+{
+ // PerfLogLuaMathEvent1( DATALOGGER_LUA_VECTOR );
+
+ RuntimeVector3 *theVector =
+ reinterpret_cast<RuntimeVector3 *>(luaL_checkudata(inLuaState, inIndex, STRING_VECTOR_TYPE));
+ luaL_argcheck(inLuaState, theVector != NULL, 1, STRING_ERROR_VECTOR_EXPECTED);
+ return *theVector;
+}
+
+//==============================================================================
+/**
+ * Helper to create a new userdata of STRING_VECTOR_TYPE on the top of the stack
+ * @param inLuaState the Lua state, required for interaction with lua
+ * @return the reference to the userdata pointed to by inIndex
+ */
+RuntimeVector3 &CLuaVector::CreateVector(lua_State *inLuaState)
+{
+ PerfLogLuaMathEvent1(DATALOGGER_LUA_VECTOR);
+
+ RuntimeVector3 *theVector =
+ reinterpret_cast<RuntimeVector3 *>(lua_newuserdata(inLuaState, sizeof(RuntimeVector3)));
+
+ // associate the metatable with CVector3
+ luaL_getmetatable(inLuaState, STRING_VECTOR_TYPE);
+ lua_setmetatable(inLuaState, -2);
+
+ return *theVector;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICOutputMemoryStream.cpp b/src/Runtime/Source/Runtime/Source/UICOutputMemoryStream.cpp
new file mode 100644
index 00000000..3e750c31
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICOutputMemoryStream.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICOutputMemoryStream.h"
+#include "UICHash.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * XXX
+ */
+COutputMemoryStream::COutputMemoryStream()
+{
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+COutputMemoryStream::~COutputMemoryStream()
+{
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+void COutputMemoryStream::Reset()
+{
+ m_Data.clear();
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+COutputMemoryStream &COutputMemoryStream::operator<<(const COutputMemoryStream &inStream)
+{
+ size_t theSize = inStream.m_Data.size();
+ for (size_t theCount = 0; theCount < theSize; ++theCount)
+ m_Data.push_back(inStream.m_Data[theCount]);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+void COutputMemoryStream::WriteStringHash(const CHAR *inItem)
+{
+ TStringHash theHash = CHash::HashString(inItem);
+ // DEBUG
+ //{FILE*fp=fopen("hashed.txt","a");if(fp){fprintf(fp,"%ul %s\n",theHash,inItem);fclose(fp);}}
+ operator<<(theHash);
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+void COutputMemoryStream::WriteEventCommandHash(const CHAR *inItem)
+{
+ TStringHash theHash = CHash::HashEventCommand(inItem);
+ // DEBUG
+ //{FILE*fp=fopen("hashed.txt","a");if(fp){fprintf(fp,"%ul %s\n",theHash,inItem);fclose(fp);}}
+ operator<<(theHash);
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+COutputMemoryStream &COutputMemoryStream::operator<<(const std::string &inString)
+{
+ const UINT8 *thePtr = reinterpret_cast<const UINT8 *>(inString.c_str());
+ for (size_t theCounter = 0; theCounter < inString.size(); ++theCounter) {
+ m_Data.push_back(*thePtr);
+ ++thePtr;
+ }
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+COutputMemoryStream &COutputMemoryStream::operator<<(const EAttributeType inType)
+{
+ UINT8 theType = static_cast<UINT8>(inType);
+ m_Data.push_back(theType);
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+UINT32 COutputMemoryStream::GetSize() const
+{
+ return static_cast<UINT32>(m_Data.size());
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+const UINT8 *COutputMemoryStream::GetData() const
+{
+ return &m_Data[0];
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICParametersSystem.cpp b/src/Runtime/Source/Runtime/Source/UICParametersSystem.cpp
new file mode 100644
index 00000000..acb81a7a
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICParametersSystem.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+#include "UICParametersSystem.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSIndexableLinkedList.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/SerializationTypes.h"
+#include "UICBinarySerializationHelper.h"
+#include "foundation/IOStreams.h"
+
+using namespace uic::runtime;
+
+namespace {
+
+struct SParameterGroup
+{
+ enum {
+ NumParametersPerGroup = 4,
+ };
+ TIdValuePair m_Data[NumParametersPerGroup];
+ SParameterGroup *m_NextNode;
+
+ SParameterGroup()
+ : m_NextNode(NULL)
+ {
+ }
+};
+
+struct SParameterGroupEntry
+{
+ QT3DSU32 m_ParameterCount;
+ SParameterGroup *m_FirstGroup;
+ SParameterGroupEntry()
+ : m_ParameterCount(0)
+ , m_FirstGroup(NULL)
+ {
+ }
+};
+
+typedef IndexableLinkedList<SParameterGroup, TIdValuePair, SParameterGroup::NumParametersPerGroup>
+ TParametersList;
+
+struct SParamSystem : public IParametersSystem
+{
+ typedef nvhash_map<QT3DSI32, SParameterGroupEntry> TIdGroupHash;
+
+ NVFoundationBase &m_Foundation;
+ TParametersList::TPoolType m_ParametersPool;
+ TIdGroupHash m_Groups;
+ QT3DSI32 m_NextId;
+ NVDataRef<QT3DSU8> m_LoadData;
+ QT3DSI32 m_RefCount;
+
+ SParamSystem(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ , m_ParametersPool(ForwardingAllocator(fnd.getAllocator(), "ParametersPool"))
+ , m_Groups(fnd.getAllocator(), "m_Groups")
+ , m_NextId(1)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc = m_Foundation.getAllocator();
+ NVDelete(alloc, this);
+ }
+ }
+
+ void IncrementId()
+ {
+ ++m_NextId;
+ if (!m_NextId)
+ ++m_NextId;
+ }
+
+ QT3DSI32 CreateParameterGroup() override
+ {
+ eastl::pair<TIdGroupHash::iterator, bool> inserter =
+ m_Groups.insert(eastl::make_pair(m_NextId, SParameterGroupEntry()));
+ while (inserter.second == false) {
+ IncrementId();
+ inserter = m_Groups.insert(eastl::make_pair(m_NextId, SParameterGroupEntry()));
+ }
+ return inserter.first->first;
+ }
+
+ void AddParameter(QT3DSI32 inGroup, QT3DSU32 inNameHash, Q3DStudio::UVariant inParam) override
+ {
+ TIdGroupHash::iterator iter = m_Groups.find(inGroup);
+ if (iter == m_Groups.end()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ SParameterGroupEntry &theEntry(iter->second);
+ TIdValuePair &thePair = TParametersList::Create(
+ theEntry.m_FirstGroup, theEntry.m_ParameterCount, m_ParametersPool);
+ thePair = eastl::make_pair(inNameHash, inParam);
+ }
+
+ QT3DSU32 GetNumParameters(QT3DSI32 inGroup) const override
+ {
+ TIdGroupHash::const_iterator iter = m_Groups.find(inGroup);
+ if (iter == m_Groups.end()) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ const SParameterGroupEntry &theEntry(iter->second);
+ return theEntry.m_ParameterCount;
+ }
+ TIdValuePair GetParameter(QT3DSI32 inGroup, QT3DSU32 inIndex) const override
+ {
+ Q3DStudio::UVariant dummyValue;
+ dummyValue.m_INT32 = 0;
+ TIdValuePair retval = TIdValuePair(0, dummyValue);
+
+ TIdGroupHash::const_iterator iter = m_Groups.find(inGroup);
+ if (iter == m_Groups.end()) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+
+ const SParameterGroupEntry &theEntry(iter->second);
+
+ if (inIndex < theEntry.m_ParameterCount)
+ return TParametersList::GetObjAtIdx(theEntry.m_FirstGroup, inIndex);
+
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+
+ void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) override
+ {
+ SWriteBuffer theWriter(m_Foundation.getAllocator(), "SaveData");
+ theWriter.write(m_NextId);
+ theWriter.write((QT3DSU32)m_Groups.size());
+
+ for (TIdGroupHash::iterator iter = m_Groups.begin(), end = m_Groups.end(); iter != end;
+ ++iter) {
+ theWriter.write(iter->first);
+ theWriter.write(iter->second);
+ SaveIndexableList<TParametersList>(iter->second.m_FirstGroup, theWriter);
+ }
+ ioStream.Write(theWriter.begin(), theWriter.size());
+ }
+
+ void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData) override
+ {
+ m_LoadData = inLoadData;
+ SDataReader theReader(inLoadData.begin(), inLoadData.end());
+ m_NextId = theReader.LoadRef<QT3DSI32>();
+ QT3DSU32 numGroups = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numGroups; idx < end; ++idx) {
+ QT3DSI32 groupId = theReader.LoadRef<QT3DSI32>();
+ SParameterGroupEntry *theGroup = theReader.Load<SParameterGroupEntry>();
+ LoadIndexableList<TParametersList>(theGroup->m_FirstGroup, theGroup->m_ParameterCount,
+ theReader);
+ m_Groups.insert(eastl::make_pair(groupId, *theGroup));
+ }
+ }
+};
+}
+
+IParametersSystem &IParametersSystem::CreateParametersSystem(NVFoundationBase &fnd)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SParamSystem)(fnd);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICPresentation.cpp b/src/Runtime/Source/Runtime/Source/UICPresentation.cpp
new file mode 100644
index 00000000..4a24253f
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICPresentation.cpp
@@ -0,0 +1,796 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICPresentation.h"
+#include "UICCommandEventTypes.h"
+#include "UICIScriptBridge.h"
+#include "UICInputEventTypes.h"
+#include "UICDataLogger.h"
+#include "UICApplication.h"
+#include "UICRuntimeFactory.h"
+#include "UICLuaCommandHelper.h"
+#include "UICActivationManager.h"
+#include "UICRenderContext.h"
+#include "UICComponentManager.h"
+#include "UICRenderBufferLoader.h"
+#include "UICSlideSystem.h"
+#include "UICLogicSystem.h"
+#include "UICParametersSystem.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+/// Maximum number of Event/Command that can be queued in an Update cycle
+const INT32 Q3DStudio_EVENTCOMMANDQUEUECAPACITY = 512;
+
+/// Limit to prevent infinite loop during queue processing
+const INT32 Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT = Q3DStudio_EVENTCOMMANDQUEUECAPACITY * 10;
+
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4355)
+#endif
+//==============================================================================
+/**
+ * Constructor
+ */
+CPresentation::CPresentation(const CHAR *inName, uic::runtime::IApplication *inApplication)
+ : m_Name(inName)
+ , m_Application(inApplication)
+ , m_Scene(NULL)
+ , m_ActivityZone(NULL)
+ , m_RootElement(NULL)
+ , m_EventCommandQueue(Q3DStudio_EVENTCOMMANDQUEUECAPACITY, "EventCommandQueue")
+ , m_IsProcessingEventCommandQueue(false)
+ , m_ComponentManager(*this)
+ , m_Offset(0)
+ , m_LocalTime(0)
+ , m_PreviousGlobalTime(-1)
+ , m_Paused(false)
+ , m_OffsetInvalid(true)
+ , m_Active(true)
+{
+ m_Size.m_Width = 0;
+ m_Size.m_Height = 0;
+ m_Size.m_ScaleMode = SCALEMODE_UNKNOWN;
+ m_AnimationSystem = IAnimationSystem::CreateAnimationSystem(
+ inApplication->GetRuntimeFactoryCore().GetFoundation());
+ m_SlideSystem =
+ ISlideSystem::CreateSlideSystem(inApplication->GetRuntimeFactoryCore().GetFoundation(),
+ inApplication->GetRuntimeFactoryCore().GetStringTable(),
+ inApplication->GetElementAllocator());
+ m_LogicSystem =
+ ILogicSystem::CreateLogicSystem(inApplication->GetRuntimeFactoryCore().GetFoundation());
+ m_ParametersSystem = IParametersSystem::CreateParametersSystem(
+ inApplication->GetRuntimeFactoryCore().GetFoundation());
+}
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CPresentation::~CPresentation()
+{
+}
+
+//==============================================================================
+/**
+ * Registers an element for notification when events fired on it.
+ * @param inElement target element to monitor
+ * @param inEventHash event hash to register for
+ * @param inCallback static callback function
+ * @param inContextData arbitrary data pointer
+ */
+void CPresentation::RegisterEventCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData)
+{
+ m_EventCallbacks.RegisterCallback(inElement, inEventHash, inCallback, inContextData);
+ inElement->SetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK, true);
+
+ if (uic::runtime::IApplicationCore::isPickingEvent(inEventHash))
+ inElement->SetFlag(ELEMENTFLAG_PICKENABLED, true);
+}
+
+//==============================================================================
+/**
+ * Unregisters a previously registered event callback.
+ * @param inElement target element to monitor
+ * @param inEventHash event hash to register for
+ * @param inCallback static callback function
+ * @param inContextData arbitrary data pointer
+ */
+BOOL CPresentation::UnregisterEventCallback(TElement *inElement,
+ const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData)
+{
+ BOOL theLast = false;
+ BOOL theResult = m_EventCallbacks.UnregisterCallback(inElement, inEventHash, inCallback,
+ inContextData, theLast);
+
+ // Unflag element if there are no longer any callbacks on it
+ if (theLast)
+ inElement->SetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK, false);
+
+ if (uic::runtime::IApplicationCore::isPickingEvent(inEventHash))
+ inElement->SetFlag(ELEMENTFLAG_PICKENABLED, false);
+
+ return theResult;
+}
+
+void CPresentation::ClearDirtyList()
+{
+ FOR_ARRAY(TElement *, theElement, GetFrameData().GetDirtyList())
+ {
+ (*theElement)->Flags().SetDirty(false);
+ }
+ GetFrameData().Reset();
+}
+
+inline void ConvertActivityZoneBufferToElementList(uic::runtime::TActivityItemBuffer inSource,
+ TElementList &outResult)
+{
+ for (qt3ds::QT3DSU32 idx = 0, end = inSource.size(); idx < end; ++idx)
+ outResult.Push(inSource[idx].first);
+}
+
+void CPresentation::PreUpdate(const TTimeUnit inGlobalTime)
+{
+ if (m_OffsetInvalid || m_Paused) {
+ m_OffsetInvalid = false;
+ m_Offset = m_LocalTime - inGlobalTime;
+ } else
+ m_LocalTime = inGlobalTime + m_Offset;
+
+ // Event/Command Processing Stage
+ ProcessEventCommandQueue();
+}
+
+//==============================================================================
+/**
+ * Update the presentation to the current time. This will start triggering the
+ * various stages of the presentation frame rhythm
+ * @param inGlobalTime time at which to update each presentation
+ * @return true if there were events to be processed.
+ */
+void CPresentation::BeginUpdate()
+{
+ // Active Scan Stage
+ if (m_ActivityZone) {
+ m_ActivityZone->BeginUpdate(
+ m_LocalTime, m_Application->GetRuntimeFactory().GetPerfTimer(),
+ m_Application->GetRuntimeFactory().GetUICRenderContext().GetThreadPool());
+ }
+}
+
+void CPresentation::EndUpdate()
+{
+ if (m_ActivityZone) {
+ m_ActivityZone->EndUpdate();
+ CPresentationFrameData &theFrameData = GetFrameData();
+ ConvertActivityZoneBufferToElementList(m_ActivityZone->GetActivatedItems(),
+ theFrameData.GetActivationList());
+ ConvertActivityZoneBufferToElementList(m_ActivityZone->GetDeactivatedItems(),
+ theFrameData.GetDeactivationList());
+ ConvertActivityZoneBufferToElementList(m_ActivityZone->GetScriptItems(),
+ theFrameData.GetScriptsList());
+ }
+
+ if (!m_Paused) {
+ // Animation Track Evaluation Stage
+ m_AnimationSystem->Update();
+ }
+}
+
+void CPresentation::PostUpdate(const TTimeUnit inGlobalTime)
+{
+ if (!m_Paused) {
+ // Callback Stage
+ if (m_Application && m_PreviousGlobalTime != inGlobalTime) {
+ m_Application->GetRuntimeFactoryCore().GetScriptEngine().ProcessFrameCallbacks(this);
+ m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().ProcessFrameCallbacks(this);
+ }
+ }
+
+ m_PreviousGlobalTime = inGlobalTime;
+}
+
+//==============================================================================
+/**
+ * Process the Event/Command queue completely
+ * PostEventCommand is the method that will add new Event/Command to the queue.
+ *
+ * The contract for Event/Command processing:
+ * 1. If an Event or Command is posted during the processing stage, it will be added
+ * to the end of the queue and is guaranteed to be processed in the current cycle.
+ * For example, if an Event (which is processed) triggers a Command to set a model to red,
+ * the model will turn red in the current frame.
+ *
+ * 2. If an Event or Command is posted after the processing stage, such as during the
+ * Callback stage, it will only be processed on the next Update cycle.
+ * For example, if the "turn mode to red" Command is posted in a script callback, the
+ * model will turn red in the next frame.
+ *
+ * 3. If an Event or Command is posted before the processing stage, for example an
+ * external Event posted just before the Update cycle, it will be processed in the current
+ *cycle.
+ * For example, if the "turn mode to red" Command is posted from the game engine prior to
+ * the Update cycle, the model will turn red in the current frame.
+ *
+ * @see PostEventCommand
+ * @return true if there were events that were processed.
+ */
+BOOL CPresentation::ProcessEventCommandQueue()
+{
+ PerfLogGeneralEvent2(DATALOGGER_PROCESSEVENTS);
+
+ m_IsProcessingEventCommandQueue = true;
+
+ BOOL theResult = !m_EventCommandQueue.IsEmpty();
+ INT32 theEventProcessedCount = 0;
+ while (!m_EventCommandQueue.IsEmpty()) {
+ SEventCommand &theEventCommand = m_EventCommandQueue.Top();
+ if (theEventCommand.m_IsEvent)
+ ProcessEvent(theEventCommand, theEventProcessedCount);
+ else
+ ProcessCommand(theEventCommand);
+
+ // Infinite-loop check
+ if (theEventProcessedCount > Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT) {
+ // Breakout policy: Dump remaining Event/Commands
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "ProcessEventCommandQueue exceeded maximum loop count"
+ << "Remaining Event/Commands will be cleared. Event count: "
+ << theEventProcessedCount << "Limit: " << Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT;
+ m_EventCommandQueue.Clear();
+ } else {
+ m_EventCommandQueue.Pop();
+ }
+ }
+
+ m_IsProcessingEventCommandQueue = false;
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Pass incoming event to event consumers immediately
+ * @param ioEvent the incoming event
+ */
+void CPresentation::ProcessEvent(SEventCommand &ioEvent, INT32 &ioEventCount)
+{
+ if (ioEventCount < Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT) {
+ ++ioEventCount;
+ PerfLogPresentationEvent1(DATALOGGER_PROCESSEVENT);
+
+ // Callbacks can change ioEvent's bubbling flags
+ if (ioEvent.m_Target->GetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK)) {
+ m_EventCallbacks.FireCallbacks(ioEvent);
+ }
+
+ // Do an early return if callback do a "stopImmediatePropagation"
+ if (ioEvent.m_Done)
+ return;
+
+ if (ioEvent.m_Target) {
+ // Logic should not be able to change ioEvent's bubbling flags
+ // ...or can it?
+ m_LogicSystem->OnEvent(ioEvent.m_Type, *ioEvent.m_Target, *this);
+ }
+
+ ProcessEventBubbling(ioEvent, ioEventCount);
+ }
+}
+
+//==============================================================================
+/**
+ * Handle event bubbling
+ * @param ioEvent the incoming event
+ */
+void CPresentation::ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventCount)
+{
+ PerfLogPresentationEvent1(DATALOGGER_PROCESSEVENTBUBBLING);
+
+ // Check for onGroupedMouseOver/Out
+ // arg1 = the original onMouseOut model and arg2 = the original onMouseOver model
+ if (ioEvent.m_Type == ON_MOUSEOUT) {
+ // If original onMouseOver model is NULL or not a descendent, fire onGroupedMouseOut
+ TElement *theMouseOverModel = static_cast<TElement *>(ioEvent.m_Arg2.m_VoidPointer);
+ if (!theMouseOverModel || !ioEvent.m_Target->IsDescendent(*theMouseOverModel)) {
+ SEventCommand theEvent = ioEvent;
+ theEvent.m_Type = ON_GROUPEDMOUSEOUT;
+ theEvent.m_BubbleUp = 0; // no bubbling
+ theEvent.m_BubbleDown = 0;
+ FireEvent(theEvent);
+ }
+ // set the original onMouseOver model to the target to make IsDescendent queries less
+ // expensive
+ else if (theMouseOverModel) {
+ ioEvent.m_Arg2.m_VoidPointer = ioEvent.m_Target;
+ }
+ } else if (ioEvent.m_Type == ON_MOUSEOVER) {
+ // If original onMouseOut model is NULL or not a descendent, fire onGroupedMouseOver
+ TElement *theMouseOutModel = static_cast<TElement *>(ioEvent.m_Arg1.m_VoidPointer);
+ if (!theMouseOutModel || !ioEvent.m_Target->IsDescendent(*theMouseOutModel)) {
+ SEventCommand theEvent = ioEvent;
+ theEvent.m_Type = ON_GROUPEDMOUSEOVER;
+ theEvent.m_BubbleUp = 0; // no bubbling
+ theEvent.m_BubbleDown = 0;
+ FireEvent(theEvent);
+ }
+ // set the original onMouseOut model to the target to make IsDescendent queries less
+ // expensive
+ else if (theMouseOutModel) {
+ ioEvent.m_Arg1.m_VoidPointer = ioEvent.m_Target;
+ }
+ }
+
+ // Do NOT bubble up onSlideEnter and onSlideExit events from current component to its parent
+ // scene
+ // since each component has its own slides.
+ if (ioEvent.m_BubbleUp && (ioEvent.m_Target->Flags() & ELEMENTFLAG_COMPONENT)
+ && (ioEvent.m_Type == EVENT_ONSLIDEENTER || ioEvent.m_Type == EVENT_ONSLIDEEXIT)) {
+ ioEvent.m_BubbleUp = FALSE;
+ }
+
+ // Event bubbling
+ if (ioEvent.m_BubbleUp) {
+ TElement *theParent = ioEvent.m_Target->m_Parent;
+ if (theParent) {
+ ioEvent.m_Target = theParent;
+ ProcessEvent(ioEvent, ioEventCount);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Execute command immediately
+ * @param inCommand incoming command structure
+ */
+void CPresentation::ProcessCommand(const SEventCommand &inCommand)
+{
+ PerfLogPresentationEvent1(DATALOGGER_PROCESSCOMMAND);
+
+ // Attributes (Arg1 = key, Arg2 = value)
+ if (inCommand.m_Type == COMMAND_SETPROPERTY) {
+ SAttributeKey theAttributeKey;
+ UINT32 theHash = static_cast<UINT32>(inCommand.m_Arg1.m_Hash);
+ theAttributeKey.Convert(
+ theHash); // Need this conversion to prevent problems arising due to endianess
+ inCommand.m_Target->SetAttribute(theAttributeKey.m_Hash, inCommand.m_Arg2);
+ }
+ // Events (Arg1 = hashed event name)
+ else if (inCommand.m_Type == COMMAND_FIREEVENT)
+ FireEvent(inCommand.m_Arg1.m_Hash, inCommand.m_Target);
+
+ // Time (Arg1 = time)
+ else if (inCommand.m_Type == COMMAND_PLAY)
+ GetComponentManager().SetPause(inCommand.m_Target, false);
+ else if (inCommand.m_Type == COMMAND_PAUSE)
+ GetComponentManager().SetPause(inCommand.m_Target, true);
+ else if (inCommand.m_Type == COMMAND_GOTOTIME)
+ GetComponentManager().GoToTime(inCommand.m_Target, inCommand.m_Arg1.m_INT32);
+
+ // Slide (Arg1 = slide index or slide name)
+ else if (inCommand.m_Type == COMMAND_GOTOSLIDE) {
+ // Goto slide commands are handled differently.
+ IComponentManager &theManager(GetComponentManager());
+ Q3DStudio::SComponentGotoSlideData theGotoSlideData =
+ theManager.GetComponentGotoSlideCommand(inCommand.m_Target);
+ if (theGotoSlideData.m_Slide > 0)
+ theManager.GotoSlideIndex(inCommand.m_Target, theGotoSlideData);
+
+ theManager.ReleaseComponentGotoSlideCommand(inCommand.m_Target);
+ } else if (inCommand.m_Type == COMMAND_GOTOSLIDENAME)
+ GetComponentManager().GotoSlideName(inCommand.m_Target, inCommand.m_Arg1.m_Hash);
+ else if (inCommand.m_Type == COMMAND_GOTONEXTSLIDE)
+ GetComponentManager().GoToNextSlide(inCommand.m_Target);
+ else if (inCommand.m_Type == COMMAND_GOTOPREVIOUSSLIDE)
+ GetComponentManager().GoToPreviousSlide(inCommand.m_Target);
+ else if (inCommand.m_Type == COMMAND_BACKSLIDE)
+ GetComponentManager().GoToBackSlide(inCommand.m_Target);
+
+ // Behavior
+ else if (inCommand.m_Type == COMMAND_CUSTOMACTION)
+ m_Application->GetRuntimeFactoryCore().GetScriptEngineQml()
+ .ProcessCustomActions(this, inCommand);
+ else if (inCommand.m_Type == COMMAND_CUSTOMCALLBACK)
+ m_Application->GetRuntimeFactoryCore().GetScriptEngine().ProcessCustomCallback(this,
+ inCommand);
+ else if (inCommand.m_Type == COMMAND_PLAYSOUND) {
+ CRegisteredString theSoundPathReg = GetStringTable().HandleToStr(inCommand.m_Arg1.m_INT32);
+ if (theSoundPathReg.IsValid()) {
+ const char *theSoundPath = theSoundPathReg.c_str();
+ if (strlen(theSoundPath) > 0)
+ m_Application->GetRuntimeFactoryCore().GetScriptEngine().PlaySoundFile(theSoundPath);
+ }
+ } else if (inCommand.m_Type == COMMAND_EMITSIGNAL) {
+ m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().ProcessSignal(this, inCommand);
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION) << "Command not implemented: " << inCommand.m_Type;
+ }
+}
+
+//==============================================================================
+/**
+ * Put an Event in the queue to be processed later during the Event/Command
+ * processing stage in Update
+ * This method is used by Event-bubbling during ProcessEvent
+ *
+ * @param inEvent the incoming event
+ * @see PostEvent
+ */
+void CPresentation::FireEvent(const SEventCommand &inEvent)
+{
+ SEventCommand &theEventCommand = m_EventCommandQueue.NewEntry();
+
+ theEventCommand = inEvent;
+
+ theEventCommand.m_IsEvent = true;
+}
+
+//==============================================================================
+/**
+ * Put an Event in the queue to be processed later during the Event/Command
+ * processing stage in Update See ProcessEventCommandQueue for more
+ * information on the contract for Event/Command processing.
+ *
+ * @param inEventType the incoming event type
+ * @param inTarget the target for the event
+ * @param inArg1 optional argument #1
+ * @param inArg2 optional argument #2
+ * @param inType1 optional type for argument #1
+ * @param inType2 optional type for argument #2
+ * @see ProcessEventCommandQueue
+ * @see PostEventCommand
+ */
+void CPresentation::FireEvent(const TEventCommandHash inEventType, TElement *inTarget,
+ const UVariant *inArg1, const UVariant *inArg2,
+ const EAttributeType inType1, const EAttributeType inType2)
+{
+
+ SEventCommand theEvent = { inTarget, inEventType };
+
+ theEvent.m_IsEvent = true;
+ theEvent.m_BubbleUp = true;
+
+ theEvent.m_Arg1Type = static_cast<UINT8>(inType1);
+ theEvent.m_Arg2Type = static_cast<UINT8>(inType2);
+
+ if (inArg1)
+ theEvent.m_Arg1 = *inArg1;
+ if (inArg2)
+ theEvent.m_Arg2 = *inArg2;
+
+ m_EventCommandQueue.NewEntry() = theEvent;
+}
+
+//==============================================================================
+/**
+ * Put a Command in the queue to be processed later during the Event/Command
+ * processing stage in Update. See ProcessEventCommandQueue for more information
+ * on the contract for Event/Command processing.
+ *
+ * For cases where the Commands need to be synchronized with the Frame-Rhythm
+ * An example would be calling "SetSlide" in scripts.
+ *
+ * @see ProcessEventCommandQueue
+ * @see PostEventCommand
+ * @param inEventType the incoming command type
+ * @param inTarget the target for the command
+ * @param inArg1 optional argument #1
+ * @param inArg2 optional argument #2
+ * @param inType1 optional type for argument #1
+ * @param inType2 optional type for argument #2
+ */
+void CPresentation::FireCommand(const TEventCommandHash inEventType, TElement *inTarget,
+ const UVariant *inArg1, const UVariant *inArg2,
+ const EAttributeType inType1, const EAttributeType inType2)
+{
+ // Pre-filter gotoslidename commands.
+ if (inEventType == COMMAND_GOTOSLIDENAME) {
+ int theSlideHashName = inArg1->m_INT32;
+ TComponent *theComponent = GetComponentManager().GetComponent(inTarget);
+ UINT8 theSlideIndex = GetSlideSystem().FindSlide(*theComponent, theSlideHashName);
+ // Translate into a slide index command.
+ CLuaCommandHelper::SetupGotoSlideCommand(*inTarget, theSlideIndex,
+ SScriptEngineGotoSlideArgs());
+ } else {
+ SEventCommand theCommand = { inTarget, inEventType };
+
+ theCommand.m_Arg1Type = static_cast<UINT8>(inType1);
+ theCommand.m_Arg2Type = static_cast<UINT8>(inType2);
+
+ if (inArg1)
+ theCommand.m_Arg1 = *inArg1;
+ if (inArg2)
+ theCommand.m_Arg2 = *inArg2;
+
+ m_EventCommandQueue.NewEntry() = theCommand;
+ }
+}
+
+void CPresentation::FlushEventCommandQueue(void)
+{
+ if (!m_IsProcessingEventCommandQueue)
+ ProcessEventCommandQueue();
+}
+
+void CPresentation::ProcessEvent(SEventCommand &inEvent)
+{
+ INT32 theEventProcessedCount = 0;
+ ProcessEvent(inEvent, theEventProcessedCount);
+}
+//==============================================================================
+/**
+ * This method is triggered after the presentation is streamed in. At this point,
+ * all the stores will be loaded up.
+ */
+void CPresentation::OnPresentationLoaded()
+{
+ m_FrameData.Reserve(1000 /*m_ElementManager.GetElementCount( )*/);
+}
+
+//==============================================================================
+/**
+ * Set the full path for this presentation. This can be used by anyone who
+ * knows the presentation to form relative paths.
+ * @param inPath the path to which to set.
+ */
+void CPresentation::SetFilePath(const CHAR *inPath)
+{
+ m_FilePath = inPath;
+}
+
+//==============================================================================
+/**
+ * Gets the full file path for this presentation. This can be used by anyone who
+ * knows the presentation to form relative correct paths.
+ */
+QString CPresentation::GetFilePath()
+{
+ return m_FilePath;
+}
+
+//==============================================================================
+/**
+ * Gets the pause state
+ * @return true if the presentation is paused, false if otherwise
+ */
+BOOL CPresentation::GetPause() const
+{
+ return m_Paused;
+}
+
+//==============================================================================
+/**
+ * Sets the pause state
+ * @param inPause set true to pause, set false if otherwise
+ */
+void CPresentation::SetPause(const BOOL inPause)
+{
+ m_Paused = inPause ? true : false;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Scene
+ */
+void CPresentation::SetScene(IScene *inScene)
+{
+ m_Scene = inScene;
+}
+
+void CPresentation::SetActivityZone(uic::runtime::IActivityZone *inZone)
+{
+ m_ActivityZone = inZone;
+ m_ActivityZone->SetZoneActive(m_Active);
+ TElement *theSceneElement = m_RootElement;
+ uic::runtime::IActivityZone &theZone(*GetActivityZone());
+ // The activity zone requires elements described to it in breadth first search order.
+ theZone.AddActivityItems(*theSceneElement);
+}
+
+void CPresentation::SetActive(bool inValue)
+{
+ m_Active = inValue;
+ m_ActivityZone->SetZoneActive(m_Active);
+}
+
+bool CPresentation::GetActive() const
+{
+ return m_Active;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Scene
+ */
+IScene *CPresentation::GetScene() const
+{
+ return m_Scene;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Script Bridge
+ */
+IScriptBridge *CPresentation::GetScriptBridge()
+{
+ if (m_Application)
+ return &m_Application->GetRuntimeFactoryCore().GetScriptEngine();
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+* Simple manager access: Script Bridge Qml
+*/
+IScriptBridge *CPresentation::GetScriptBridgeQml()
+{
+ if (m_Application)
+ return &m_Application->GetRuntimeFactoryCore().GetScriptEngineQml();
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Component Manager
+ */
+IComponentManager &CPresentation::GetComponentManager()
+{
+ return m_ComponentManager;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Slide Manager
+ */
+ISlideSystem &CPresentation::GetSlideSystem()
+{
+ return *m_SlideSystem;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Animation Manager
+ */
+uic::runtime::IAnimationSystem &CPresentation::GetAnimationSystem()
+{
+ return *m_AnimationSystem;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Logic Manager
+ */
+ILogicSystem &CPresentation::GetLogicSystem()
+{
+ return *m_LogicSystem;
+}
+
+//==============================================================================
+/**
+ * Simple manager access: Params Manager
+ */
+IParametersSystem &CPresentation::GetParametersSystem()
+{
+ return *m_ParametersSystem;
+}
+
+void CPresentation::SetElementPath(TElement &inElement, const char8_t *inPath)
+{
+ CRegisteredString str;
+ if (m_Application)
+ str = m_Application->GetRuntimeFactoryCore().GetStringTable().RegisterStr(
+ qt3ds::foundation::nonNull(inPath));
+
+ if (str.IsValid())
+ m_ElementPathMap.insert(eastl::make_pair(&inElement, str));
+}
+
+qt3ds::foundation::CRegisteredString CPresentation::GetElementPath(TElement &inElement)
+{
+ TElemStringMap::iterator iter = m_ElementPathMap.find(&inElement);
+ if (iter != m_ElementPathMap.end())
+ return iter->second;
+
+ return qt3ds::foundation::CRegisteredString();
+}
+
+qt3ds::foundation::IStringTable &CPresentation::GetStringTable()
+{
+ return GetApplication().GetRuntimeFactoryCore().GetStringTable();
+}
+
+//==============================================================================
+/**
+ * Current frame data stores traversal lists for use later
+ */
+CPresentationFrameData &CPresentation::GetFrameData()
+{
+ return m_FrameData;
+}
+
+void CPresentation::SetLoadedBuffer(uic::render::ILoadedBuffer &inBuffer)
+{
+ m_LoadedBuffer = inBuffer;
+}
+
+//==============================================================================
+/**
+ * Retrieve the name of the presentation. This is actually the file path.
+ * @return the name of this presentation
+ */
+const CHAR *CPresentation::GetName() const
+{
+ return m_Name.toLatin1().constData();
+}
+
+//==============================================================================
+/**
+ * Retrieve the size of the presentation in Studio
+ * @return the size of this presentation
+ */
+SPresentationSize CPresentation::GetSize() const
+{
+ return m_Size;
+}
+
+//==============================================================================
+/**
+ * Set the size of the presentation as reflected in Studio
+ * @param inSize size of presentation ( width, height, scale mode ) in Studio
+ */
+void CPresentation::SetSize(const SPresentationSize &inSize)
+{
+ m_Size = inSize;
+}
+
+QPresentationSignalProxy *CPresentation::signalProxy()
+{
+ return &m_SignalProxy;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICPresentationFrameData.cpp b/src/Runtime/Source/Runtime/Source/UICPresentationFrameData.cpp
new file mode 100644
index 00000000..bce1b55c
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICPresentationFrameData.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICPresentationFrameData.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const FLOAT DIRTY_STORE_RATIO = 0.1f;
+const FLOAT TRAVERSAL_STORE_RATIO = 0.5f;
+const FLOAT ACTIVATION_STORE_RATIO = 0.3f;
+const FLOAT DEACTIVATION_STORE_RATIO = 0.3f;
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CPresentationFrameData::CPresentationFrameData()
+ : m_DirtyList(0, 0, "Frame:DirtyList")
+ , m_TraversalList(0, 0, "Frame:TraversalList")
+ , m_ScriptsList(0, 0, "Frame:ScriptsList")
+ , m_ActivationList(0, 0, "Frame:ActivationList")
+ , m_DeactivationList(0, 0, "Frame:DeactivationList") /*,*/
+// m_SlideExitList( 0, 0, "Frame:SlideExitList" ),
+// m_SlideEnterList( 0, 0, "Frame:SlideEnterList" )
+{
+}
+
+//==============================================================================
+/**
+ * Reserve memory from the memory subsytem to store the various arrays.
+ * @param inElementCount the number of elements loaded
+ */
+void CPresentationFrameData::Reserve(const INT32 /*inElementCount*/)
+{
+}
+
+//==============================================================================
+/**
+ * Clean up the data. This is usually called at the start of the frame rhythm to
+ * clean up the data from previous frame
+ * Memory allocation should be clear by default.
+ * Previous list could be a lot longer than current or future list which means
+ * the appliation is using more memory than needed. The heuristics of both
+ * initialization and runtime freeing is dependent on the presentation.
+ */
+void CPresentationFrameData::Reset()
+{
+ // Keep the capacity of these lists every frame since they have consistent
+ // sizes from frame to frame
+ m_TraversalList.Clear(false);
+ m_ScriptsList.Clear(false);
+
+ // These lists are more sporatic (slide changes) for now, clear them as
+ // above but potential memory saving could occur by calling Clear( true ) instead
+ m_ActivationList.Clear(false);
+ m_DeactivationList.Clear(false);
+
+ // NOTE: When we clear the dirty list, we also must ensure that the elements
+ // themselves are un-dirtied to prepare for the next frame. This is done
+ // by the caller of "CPresentationFrameData::Reset"
+ m_DirtyList.Clear(false);
+
+ // m_SlideExitList.Clear( false );
+ // m_SlideEnterList.Clear( false );
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/UICQmlElementHelper.cpp b/src/Runtime/Source/Runtime/Source/UICQmlElementHelper.cpp
new file mode 100644
index 00000000..2616bf2c
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICQmlElementHelper.cpp
@@ -0,0 +1,310 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICQmlElementHelper.h"
+#include "UICCommandEventTypes.h"
+#include "UICHash.h"
+#include "UICAttributeHashes.h"
+#include "UICElementSystem.h"
+#include "UICRuntimeFactory.h"
+
+using namespace Q3DStudio;
+using namespace qt3ds;
+
+//==============================================================================
+// Constants
+//==============================================================================
+const char PRESENTATION_DELIMITER = ':';
+const char NODE_DELIMITER = '.';
+const TStringHash RESERVED_THIS = CHash::HashString("this");
+const TStringHash RESERVED_PARENT = CHash::HashString("parent");
+const TStringHash RESERVED_SCENE = CHash::HashString("Scene");
+
+//==============================================================================
+/**
+* Constructor
+*/
+CQmlElementHelper::CQmlElementHelper()
+{
+}
+
+//==============================================================================
+/**
+* Destructor
+*/
+CQmlElementHelper::~CQmlElementHelper()
+{
+}
+
+TElement *CQmlElementHelper::GetElement(uic::runtime::IApplication &inApplication,
+ IPresentation *inDefaultPresentation, const char *inPath,
+ TElement *inStartElement)
+{
+ if (inPath == nullptr || *inPath == 0)
+ return nullptr;
+ const char *thePath(inPath);
+ const char *theSubPath = nullptr;
+ IPresentation *thePresentation = nullptr;
+ size_t thePathLength = ::strlen(thePath) + 1;
+ char *theToken =
+ Q3DStudio_allocate_desc(CHAR, thePathLength, "Lua:TempPath"); // Temporary token storage
+ // Try to get the specified presentation
+ theSubPath = ::strchr(thePath, PRESENTATION_DELIMITER);
+ TElement *theElement = inStartElement;
+ if (theSubPath != nullptr) {
+ UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
+
+ ::strncpy(theToken, thePath, theSubPathLength);
+ theToken[theSubPathLength] = '\0';
+
+ thePath = theSubPath + 1;
+
+ const CHAR *thePresentationName = theToken;
+
+ thePresentation = inApplication.GetPresentationById(thePresentationName);
+ }
+ if (thePresentation == nullptr)
+ thePresentation = inDefaultPresentation;
+
+ // Return nil if the inStartElement is not in the specified presentation
+ if (theElement != nullptr
+ && (theSubPath == nullptr && theElement->GetBelongedPresentation() != thePresentation)) {
+ thePresentation = theElement->GetBelongedPresentation();
+ }
+
+ if (thePresentation == nullptr)
+ return nullptr;
+
+ TStringHash theName;
+ INT32 theParseCounter = 0;
+
+ while (thePath != nullptr && thePath[0] != '\0') {
+ ++theParseCounter;
+
+ // Do some strtok() work here
+ theSubPath = ::strchr(thePath, NODE_DELIMITER);
+ if (theSubPath) {
+ UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
+ Q3DStudio_ASSERT(theSubPathLength < thePathLength);
+
+ ::strncpy(theToken, thePath, theSubPathLength);
+ theToken[theSubPathLength] = '\0';
+
+ thePath = theSubPath + 1;
+ } else {
+ ::strcpy(theToken, thePath);
+ thePath = nullptr;
+ }
+
+ // Hash the token and do some element searching
+ theName = CHash::HashString(theToken);
+
+ if (theName == RESERVED_PARENT) {
+ if (theElement)
+ theElement = theElement->GetParent();
+ } else if (theName == RESERVED_THIS) {
+ //Keep the original element if "this" wanted
+ } else {
+ if (theName == RESERVED_SCENE && theParseCounter == 1)
+ theElement =
+ thePresentation->GetRoot(); // theElement is nullptr, so using absolute path
+
+ else if (theElement)
+ theElement = theElement->FindChild(theName); // Using relative path
+ }
+
+ if (!theElement)
+ thePath = nullptr;
+ } // while
+
+ Q3DStudio_free(theToken, CHAR, thePathLength);
+ return theElement;
+}
+
+bool CQmlElementHelper::SetAttribute(TElement *theElement, const char *theAttName,
+ const void *value, bool inDelay)
+{
+ SAttributeKey theAttributeKey;
+ theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
+
+ // Early out for our single 'read only' attribute
+ if (ATTRIBUTE_URI == theAttributeKey.m_Hash) {
+ // we didn't push anything onto the stack
+ return false;
+ }
+
+ // first search if it is a static property
+ Option<uic::runtime::element::TPropertyDescAndValuePtr> thePropertyInfo =
+ theElement->FindProperty(theAttributeKey.m_Hash);
+
+ if (!thePropertyInfo.hasValue()) {
+ // if not search in the dynamic properties
+ thePropertyInfo = theElement->FindDynamicProperty(theAttributeKey.m_Hash);
+ if (!thePropertyInfo.hasValue()) {
+ // create a new dynamic porperty
+ uic::runtime::IElementAllocator &theElemAllocator(
+ theElement->GetBelongedPresentation()->GetApplication().GetElementAllocator());
+ qt3ds::foundation::IStringTable &theStringTable(
+ theElement->GetBelongedPresentation()->GetStringTable());
+ IRuntimeMetaData &theMetaData =
+ theElement->GetBelongedPresentation()->GetApplication().GetMetaData();
+ thePropertyInfo = theElemAllocator.CreateDynamicProperty(
+ theMetaData, *theElement, theStringTable.RegisterStr(theAttName));
+ }
+ }
+
+ if (thePropertyInfo.hasValue()) {
+ UVariant theNewValue;
+ EAttributeType theAttributeType = thePropertyInfo->first.m_Type;
+ switch (theAttributeType) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ theNewValue.m_INT32 = *(INT32 *)value;
+ break;
+
+ case ATTRIBUTETYPE_FLOAT:
+ theNewValue.m_FLOAT = *(FLOAT *)value;
+ break;
+
+ case ATTRIBUTETYPE_BOOL:
+ theNewValue.m_INT32 = *(INT32 *)value;
+ break;
+
+ case ATTRIBUTETYPE_STRING:
+ theNewValue.m_StringHandle =
+ theElement->GetBelongedPresentation()->GetStringTable().GetHandle(
+ (const char *)value);
+ break;
+
+ case ATTRIBUTETYPE_POINTER:
+ qCCritical(INVALID_OPERATION, "setAttribute: pointer attributes not handled.");
+ return false;
+ break;
+
+ case ATTRIBUTETYPE_ELEMENTREF:
+ qCCritical(INVALID_OPERATION, "setAttribute: ElementRef attributes are read only.");
+ return false;
+ break;
+
+ case ATTRIBUTETYPE_FLOAT3: {
+ FLOAT *vec3 = (FLOAT *)value;
+ theNewValue.m_FLOAT3[0] = vec3[0];
+ theNewValue.m_FLOAT3[1] = vec3[1];
+ theNewValue.m_FLOAT3[2] = vec3[2];
+ } break;
+
+ case ATTRIBUTETYPE_NONE:
+ case ATTRIBUTETYPE_DATADRIVEN_PARENT:
+ case ATTRIBUTETYPE_DATADRIVEN_CHILD:
+ case ATTRIBUTETYPECOUNT:
+ default:
+ qCCritical(INVALID_OPERATION, "setAttribute: Attribute has no type!");
+ return false;
+ break;
+ }
+
+ if (inDelay) {
+ UVariant arg1;
+ arg1.m_INT32 = theAttributeKey.m_Hash;
+ theElement->GetBelongedPresentation()->FireCommand(
+ COMMAND_SETPROPERTY, theElement, &arg1, &theNewValue, ATTRIBUTETYPE_HASH,
+ theAttributeType);
+ } else {
+ theElement->SetAttribute(*thePropertyInfo, theNewValue);
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool CQmlElementHelper::GetAttribute(TElement *inElement, const char *inAttribute, void *value)
+{
+ SAttributeKey theAttributeKey;
+ theAttributeKey.m_Hash = CHash::HashAttribute(inAttribute);
+
+ Option<uic::runtime::element::TPropertyDescAndValuePtr> thePropertyInfo =
+ inElement->FindDynamicProperty(theAttributeKey.m_Hash);
+
+ if (thePropertyInfo.hasValue()) {
+ UVariant *theValuePtr = thePropertyInfo->second;
+ EAttributeType theAttributeType = thePropertyInfo->first.m_Type;
+ switch (theAttributeType) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ *(INT32 *)value = theValuePtr->m_INT32;
+ break;
+
+ case ATTRIBUTETYPE_FLOAT:
+ *(FLOAT *)value = theValuePtr->m_FLOAT;
+ break;
+
+ case ATTRIBUTETYPE_BOOL:
+ *(INT32 *)value = (theValuePtr->m_INT32 != 0);
+ break;
+
+ case ATTRIBUTETYPE_STRING:
+ *(char *)value = *inElement->GetBelongedPresentation()
+ ->GetStringTable()
+ .HandleToStr(theValuePtr->m_StringHandle)
+ .c_str();
+ break;
+
+ case ATTRIBUTETYPE_POINTER:
+ qCCritical(INVALID_OPERATION, "setAttribute: pointer attributes not handled.");
+ return false;
+ break;
+
+ case ATTRIBUTETYPE_ELEMENTREF:
+ qCCritical(INVALID_OPERATION, "setAttribute: ElementRef attributes are read only.");
+ return false;
+ break;
+
+ case ATTRIBUTETYPE_FLOAT3: {
+ FLOAT *vec3 = (FLOAT *)value;
+ vec3[0] = theValuePtr->m_FLOAT3[0];
+ vec3[1] = theValuePtr->m_FLOAT3[1];
+ vec3[2] = theValuePtr->m_FLOAT3[2];
+ } break;
+
+ case ATTRIBUTETYPE_NONE:
+ case ATTRIBUTETYPE_DATADRIVEN_PARENT:
+ case ATTRIBUTETYPE_DATADRIVEN_CHILD:
+ case ATTRIBUTETYPECOUNT:
+ default:
+ qCCritical(INVALID_OPERATION, "setAttribute: Attribute has no type!");
+ return false;
+ break;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICQmlEngine.cpp b/src/Runtime/Source/Runtime/Source/UICQmlEngine.cpp
new file mode 100644
index 00000000..175cfd49
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICQmlEngine.cpp
@@ -0,0 +1,851 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICQmlEngine.h"
+#include "UICPresentation.h"
+#include "UICInputEngine.h"
+#include "UICSceneManager.h"
+#include "UICVector3.h"
+#include "UICColor.h"
+#include "UICAttributeHashes.h"
+#include "UICFileStream.h"
+#include "UICDataLogger.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSSystem.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICStateLuaScriptContext.h"
+#include "UICStateDebugger.h"
+#include "EventPollingSystemLuaBinding.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICSlideSystem.h"
+
+#include "EASTL/vector.h"
+#include "EASTL/list.h"
+#include <sys/stat.h>
+#include "UICCommandEventTypes.h"
+#include "UICApplication.h"
+#include "UICRuntimeFactory.h"
+#include "UICStateDebugStreams.h"
+#include "UICRenderContext.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "UICRenderThreadPool.h"
+#include "UICRenderImageBatchLoader.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICAudioPlayer.h"
+#include "UICActivationManager.h"
+#include "UICParametersSystem.h"
+#include "UICQmlElementHelper.h"
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlcomponent.h>
+#include "q3dsqmlscript.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+#if defined(_DEBUG) || (_PROFILE)
+#define Q3DStudio_LOG_EVENT(S) // something
+#else
+#define Q3DStudio_LOG_EVENT(S)
+#endif
+
+using uic::runtime::IApplicationCore;
+using uic::runtime::IApplication;
+using namespace qt3ds;
+
+namespace __SQmlEngineImpl_Basic_Structs__ {
+ struct LuaScopedLock
+ {
+ qt3ds::foundation::Mutex *m_Mutex;
+
+ LuaScopedLock(qt3ds::foundation::Mutex *mtx)
+ : m_Mutex(mtx)
+ {
+ if (m_Mutex)
+ m_Mutex->lock();
+ }
+
+ ~LuaScopedLock()
+ {
+ if (m_Mutex)
+ m_Mutex->unlock();
+ }
+ };
+}
+
+using namespace __SQmlEngineImpl_Basic_Structs__;
+#define QML_ENGINE_MULTITHREAD_PROTECT_METHOD LuaScopedLock __locker(m_MultithreadedMutex);
+
+//==============================================================================
+// Callback handling
+/**
+* Constructor
+*/
+CScriptCallbacks::CScriptCallbacks()
+ : m_CallbackList(0, 0, "CallbackList")
+{
+}
+
+/**
+* Destructor
+*/
+CScriptCallbacks::~CScriptCallbacks()
+{
+ FOR_ARRAY(SFrameCallbackEntry *, theEntry, m_CallbackList)
+ Q3DStudio_delete(*theEntry, SFrameCallbackEntry);
+
+ m_CallbackList.Clear();
+}
+
+bool CScriptCallbacks::RegisterCallback(Q3DStudio::UINT32 callbackType,
+ const TScriptCallback inCallback, void *inUserData)
+{
+ // currently we only support these two types of callbacks
+ if (callbackType != SCRIPT_ON_INITIALIZE && callbackType != SCRIPT_ON_UPDATE) {
+ return false;
+ }
+
+ SFrameCallbackEntry *theFrameCallbackEntry = NULL;
+
+ try {
+ // note we don't care if someone registers the same function twice.
+ theFrameCallbackEntry = Q3DStudio_new(SFrameCallbackEntry) SFrameCallbackEntry();
+
+ if (!theFrameCallbackEntry) {
+ throw "failed to allocated SFrameCallbackEntry";
+ }
+
+ SScriptCallbackEntry *theScriptCallbackEntry =
+ Q3DStudio_new(SScriptCallbackEntry) SScriptCallbackEntry();
+ if (!theScriptCallbackEntry) {
+ throw "failed to allocated SScriptCallbackEntry";
+ }
+
+ theScriptCallbackEntry->m_CallbackType = callbackType;
+ theScriptCallbackEntry->m_Function = inCallback;
+ theScriptCallbackEntry->m_UserData = inUserData;
+ theScriptCallbackEntry->m_Processed = false;
+
+ theFrameCallbackEntry->m_Callbacks.Push(theScriptCallbackEntry);
+
+ m_CallbackList.Push(theFrameCallbackEntry);
+
+ } catch (const char *) {
+ if (theFrameCallbackEntry)
+ Q3DStudio_delete(theFrameCallbackEntry, SFrameCallbackEntry);
+
+ return false;
+ }
+
+ return true;
+}
+
+void CScriptCallbacks::UnregisterCallback(Q3DStudio::UINT32, const TScriptCallback)
+{
+ // not used so far
+}
+
+void CScriptCallbacks::ProcessCallbacks()
+{
+ // Call onInitialize function
+ FOR_ARRAY(SFrameCallbackEntry *, theFrameEntry, m_CallbackList)
+ {
+ FOR_ARRAY(SScriptCallbackEntry *, theEntry, (*theFrameEntry)->m_Callbacks)
+ {
+ if (((*theEntry)->m_CallbackType == SCRIPT_ON_INITIALIZE) && !(*theEntry)->m_Processed
+ && (*theEntry)->m_Function) {
+ (*theEntry)->m_Function((*theEntry)->m_UserData);
+ (*theEntry)->m_Processed = true;
+ }
+ }
+ }
+
+ // Call onUpdate functions
+ FOR_ARRAY(SFrameCallbackEntry *, theFrameEntry, m_CallbackList)
+ {
+ FOR_ARRAY(SScriptCallbackEntry *, theEntry, (*theFrameEntry)->m_Callbacks)
+ {
+ // int type = (*theEntry)->m_CallbackType;
+ if ((*theEntry)->m_CallbackType == SCRIPT_ON_UPDATE && (*theEntry)->m_Function) {
+ (*theEntry)->m_Function((*theEntry)->m_UserData);
+ }
+ }
+ }
+}
+
+//==============================================================================
+//* End of helper class handling element operations
+//==============================================================================
+
+//==============================================================================
+/**
+* Helper class handling command operations
+*/
+class CQmlCommandHelper
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Constructors
+ CQmlCommandHelper();
+ virtual ~CQmlCommandHelper();
+
+public: // static Functions
+ static bool SetupGotoSlideCommand(TElement &inElement, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs);
+ static bool SetupGotoSlideCommand(TElement &inElement, Q3DStudio::INT32 inSlideIndex,
+ const SScriptEngineGotoSlideArgs &inArgs);
+
+protected: // Static Hidden Helpers
+ // static TElement* FireCommand(TEventCommandHash inCommand);
+
+public: // Static Helpers
+ static TElement *GetComponentParent(TElement *inParent);
+};
+
+//==============================================================================
+/**
+* Constructor
+*/
+CQmlCommandHelper::CQmlCommandHelper()
+{
+}
+
+//==============================================================================
+/**
+* Destructor
+*/
+CQmlCommandHelper::~CQmlCommandHelper()
+{
+}
+
+static Option<Q3DStudio::UINT8> FindSlide(TElement &inElement, const char *slideName)
+{
+ IPresentation *thePresentation = inElement.GetBelongedPresentation();
+
+ int theSlideHashName = thePresentation->GetApplication().HashString(slideName);
+ TComponent *theComponent = thePresentation->GetComponentManager().GetComponent(&inElement);
+ UINT8 theSlideIndex =
+ thePresentation->GetSlideSystem().FindSlide(*theComponent, theSlideHashName);
+ if (theSlideIndex >= theComponent->GetSlideCount()) {
+ qt3ds::foundation::CRegisteredString elemPath = thePresentation->GetElementPath(inElement);
+ if (elemPath.IsValid()) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "QMLCommandHelper: goToSlide: Unable to find slide "
+ << slideName <<"on element " << elemPath.c_str();
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "QMLCommandHelper: goToSlide: Unable to find slide "
+ << slideName;
+ }
+ return Empty();
+ }
+
+ return theSlideIndex;
+}
+
+TElement *CQmlCommandHelper::GetComponentParent(TElement *inElement)
+{
+ Q3DStudio_ASSERT(inElement);
+ return &inElement->GetComponentParent();
+}
+
+bool CQmlCommandHelper::SetupGotoSlideCommand(TElement &inElement, Q3DStudio::INT32 inSlideIndex,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ IPresentation *thePresentation = inElement.GetBelongedPresentation();
+ TElement *theTarget = GetComponentParent(&inElement);
+ SComponentGotoSlideData theSlideData(inSlideIndex);
+ theSlideData.m_Mode = inArgs.m_Mode;
+ theSlideData.m_Paused = inArgs.m_Paused;
+ theSlideData.m_Rate = inArgs.m_Rate;
+ theSlideData.m_Reverse = inArgs.m_Reverse;
+ theSlideData.m_StartTime = inArgs.m_StartTime;
+ // Resolve playthroughto if it has a valid value.
+ if (!isTrivial(inArgs.m_PlaythroughTo)) {
+ if (AreEqual(inArgs.m_PlaythroughTo, "next"))
+ theSlideData.m_PlaythroughTo = -1;
+ else if (AreEqual(inArgs.m_PlaythroughTo, "previous"))
+ theSlideData.m_PlaythroughTo = -2;
+ else {
+ // Find the slide if possible. If not, then just error leave things as they are.
+
+ Option<UINT8> theSlideIndex = FindSlide(inElement, inArgs.m_PlaythroughTo);
+ if (theSlideIndex.hasValue())
+ theSlideData.m_PlaythroughTo = *theSlideIndex;
+ }
+ }
+ thePresentation->GetComponentManager().SetupComponentGotoSlideCommand(theTarget, theSlideData);
+ UVariant theArg1;
+ UVariant theArg2;
+ qt3ds::intrinsics::memZero(&theArg1, sizeof(UVariant));
+ qt3ds::intrinsics::memZero(&theArg2, sizeof(UVariant));
+ thePresentation->FireCommand(COMMAND_GOTOSLIDE, theTarget, &theArg1, &theArg2);
+ return true;
+}
+
+bool CQmlCommandHelper::SetupGotoSlideCommand(TElement &inElement, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ Option<UINT8> theSlideIndex = FindSlide(inElement, slideName);
+ if (theSlideIndex.hasValue())
+ return SetupGotoSlideCommand(inElement, *theSlideIndex, inArgs);
+
+ return false;
+}
+
+//==============================================================================
+//* End of helper class handling command operations
+//==============================================================================
+
+struct SEmitSignalData : public NVRefCounted
+{
+ NVAllocatorCallback &m_Alloc;
+ volatile QT3DSI32 mRefCount;
+ INT32 m_SignalNameHandler; ///< The name of the signal to emit
+ TElement *m_TargetElement; ///< The source element where the event is going to occur
+
+ SEmitSignalData(NVAllocatorCallback &alloc, INT32 inSignalName, TElement *inElement)
+ : m_Alloc(alloc)
+ , mRefCount(0)
+ , m_SignalNameHandler(inSignalName)
+ , m_TargetElement(inElement)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Alloc)
+};
+
+class CQmlEngineImpl : public CQmlEngine
+{
+ typedef NVScopedRefCounted<SEmitSignalData> TEmitSignalPtr;
+ typedef eastl::list<TEmitSignalPtr, ForwardingAllocator> TEmitSignalQueue;
+
+ static const int MAX_ACTION_QUEUE_SIZE = 100;
+
+private:
+ qt3ds::NVFoundationBase &m_Foundation;
+ IApplication *m_Application;
+ IApplicationCore *m_ApplicationCore;
+ qt3ds::foundation::Mutex m_PreloadMutex;
+ qt3ds::foundation::Mutex *m_MultithreadedMutex;
+
+ TEmitSignalQueue m_EmitSignalDataList;
+
+ QT3DSI32 mRefCount;
+
+ CScriptCallbacks m_ScriptCallbacks;
+
+ QQmlEngine m_engine;
+ QMap<QString, QQmlComponent *> m_components;
+ QVector<Q3DSQmlScript *> m_scripts;
+
+public:
+ CQmlEngineImpl(NVFoundationBase &fnd, ITimeProvider &inTimeProvider);
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ // functions from IScriptBridge
+ void EnableMultithreadedAccess() override;
+ void DisableMultithreadedAccess() override;
+
+ void SetApplicationCore(uic::runtime::IApplicationCore &inApplication) override;
+ void SetApplication(uic::runtime::IApplication &inApplication) override;
+ uic::runtime::IApplication *GetApplication() override;
+
+ void BeginPreloadScripts(const eastl::vector<const char *> &,
+ uic::render::IThreadPool &, const char *) override {}
+ void EndPreloadScripts() override {}
+ eastl::vector<eastl::string> GetLoadedScripts() override
+ {
+ eastl::vector<eastl::string> retval;
+ return retval;
+ }
+
+ void LoadScript(IPresentation *presentation, TElement *element, const CHAR *path) override;
+ Q3DStudio::INT32 InitializeApplicationBehavior(const char *) override
+ {
+ return -1;
+ }
+
+ void ProcessFrameCallbacks(IPresentation *) override;
+ void ExecuteApplicationScriptFunction(Q3DStudio::INT32, const char *) override {}
+ void CallFunction(const char *, const char *,
+ CScriptEngineCallFunctionArgRetriever &) override {}
+
+ void ProcessSignal(IPresentation *inPresentation,
+ const SEventCommand &inCommand) override;
+ void ProcessCustomActions(IPresentation *inPresentation,
+ const SEventCommand &inCommand) override;
+ void ProcessCustomCallback(IPresentation *, const SEventCommand &) override {}
+
+ void SetTableForElement(TElement &, ILuaScriptTableProvider &) override {}
+ void SetAttribute(const char *element, const char *attName, const char *value) override;
+ bool GetAttribute(const char *element, const char *attName, char *value) override;
+ void FireEvent(const char *element, const char *evtName) override;
+
+ void GotoSlide(const char *component, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs) override;
+ void GotoSlideRelative(const char *, bool, bool, const SScriptEngineGotoSlideArgs &) override;
+
+ void SetPresentationAttribute(const char *, const char *, const char *) override;
+
+ // No need to implement here, as sound playing is done in UICViewerApp
+ bool PlaySoundFile(const char *) override { return false; }
+
+ void EnableDebugging(uic::state::debugger::IMultiProtocolSocket &) override {}
+ void EnableProfiling() override {}
+ void StepGC() override {}
+
+ // functions from CQMLEngine
+ bool PeekSignal(TElement *&outElement, char *&outName) override;
+ void GotoSlideIndex(const char *component, const Q3DStudio::INT32 slideIndex,
+ const SScriptEngineGotoSlideArgs &inArgs) override;
+ bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName) override;
+ void GotoTime(const char *component, const Q3DStudio::FLOAT time) override;
+ bool RegisterCallback(Q3DStudio::UINT32 callbackType, const TScriptCallback inCallback,
+ void *inUserData) override;
+ void Shutdown(qt3ds::NVFoundationBase &inFoundation) override;
+
+private:
+ void createComponent(QQmlComponent *component, TElement *element);
+ TElement *getTarget(const char *component);
+};
+
+CQmlEngineImpl::CQmlEngineImpl(NVFoundationBase &fnd, ITimeProvider &)
+ : m_Foundation(fnd)
+ , m_Application(NULL)
+ , m_ApplicationCore(NULL)
+ , m_PreloadMutex(fnd.getAllocator())
+ , m_MultithreadedMutex(NULL)
+ , m_EmitSignalDataList(
+ ForwardingAllocator(fnd.getAllocator(), "CQmlEngineImpl::m_EmitSignalDataList"))
+ , mRefCount(0)
+{
+}
+
+void CQmlEngineImpl::Shutdown(qt3ds::NVFoundationBase &inFoundation)
+{
+}
+
+void CQmlEngineImpl::EnableMultithreadedAccess()
+{
+ m_MultithreadedMutex = &m_PreloadMutex;
+}
+
+void CQmlEngineImpl::DisableMultithreadedAccess()
+{
+ m_MultithreadedMutex = NULL;
+}
+
+void CQmlEngineImpl::SetApplicationCore(uic::runtime::IApplicationCore &inApplication)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ m_ApplicationCore = &inApplication;
+}
+
+void CQmlEngineImpl::SetApplication(uic::runtime::IApplication &inApplication)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ m_Application = &inApplication;
+}
+
+uic::runtime::IApplication *CQmlEngineImpl::GetApplication()
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ return m_Application;
+}
+
+void CQmlEngineImpl::SetAttribute(const char *element, const char *attName, const char *value)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ TElement *theTarget = getTarget(element);
+ if (theTarget) {
+ bool success = CQmlElementHelper::SetAttribute(theTarget, attName, value, false);
+ if (!success) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::SetAttribute: "
+ << "failed to set attribute on element"
+ << element << ":" << attName << ":" << value;
+ }
+ }
+}
+
+bool CQmlEngineImpl::GetAttribute(const char *element, const char *attName, char *value)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ TElement *theTarget = getTarget(element);
+ if (theTarget) {
+ bool success = CQmlElementHelper::GetAttribute(theTarget, attName, value);
+ if (!success) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::SetAttribute: "
+ << "failed to set attribute on element"
+ << element << ":" << attName << ":" << value;
+ }
+ return success;
+ }
+
+ return false;
+}
+
+void CQmlEngineImpl::LoadScript(IPresentation *presentation, TElement *element, const CHAR *path)
+{
+ QString projectPath(presentation->GetApplication().GetProjectDirectory().c_str());
+ QString sourcePath(projectPath + "/" + path);
+ sourcePath.replace('\\', '/');
+
+ TElement *parent = element->GetParent();
+ if (!parent)
+ return;
+
+ if (!m_components.contains(sourcePath)) {
+ m_components[sourcePath] = new QQmlComponent(&m_engine, QUrl::fromLocalFile(sourcePath),
+ &m_engine);
+ }
+
+ QQmlComponent *component = m_components[sourcePath];
+ if (component->status() == QQmlComponent::Ready) {
+ createComponent(component, element);
+ } else if (component->status() == QQmlComponent::Error) {
+ qWarning() << "Error while loading script"
+ << component->url().toString()
+ << ":" << component->errorString();
+ } else {
+ QObject::connect(component, &QQmlComponent::statusChanged,
+ [this, component, element] (QQmlComponent::Status status) {
+ if (status == QQmlComponent::Ready) {
+ createComponent(component, element);
+ } else {
+ qWarning() << "Error while loading script"
+ << component->url().toString()
+ << ":" << component->errorString();
+ }
+ }
+ );
+ }
+}
+
+void CQmlEngineImpl::FireEvent(const char *element, const char *evtName)
+{
+ TElement *theElement = getTarget(element);
+ if (theElement && theElement->GetActive() == true) {
+ IPresentation *thePresentation = theElement->GetBelongedPresentation();
+ thePresentation->FireEvent(CHash::HashEventCommand(evtName), theElement);
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::FireEvent: "
+ << "failed to find element: "
+ << element << " " << evtName;
+ }
+}
+
+void CQmlEngineImpl::GotoSlide(const char *component, const char *slideName,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ TElement *theTarget = getTarget(component);
+ if (theTarget) {
+ CQmlCommandHelper::SetupGotoSlideCommand(*theTarget, slideName, inArgs);
+ } else {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::GotoSlide: Unable to find component " << component;
+ }
+}
+
+void CQmlEngineImpl::GotoSlideRelative(const char *component, bool inNextSlide, bool inWrap,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ TElement *theTarget = getTarget(component);
+ if (theTarget) {
+ theTarget = &theTarget->GetComponentParent();
+ if (theTarget && theTarget->GetActive()) {
+ TComponent *theComponent = static_cast<TComponent *>(theTarget);
+ Q3DStudio::INT32 theSlide = theComponent->GetCurrentSlide();
+ Q3DStudio::INT32 theSlideCount = theComponent->GetSlideCount();
+ theSlide = inNextSlide ? theSlide + 1 : theSlide - 1;
+ if (theSlide < 1) {
+ if (inWrap)
+ theSlide = theSlideCount - 1;
+ else
+ theSlide = 1;
+ } else if (theSlide == theSlideCount) {
+ if (inWrap)
+ theSlide = 1;
+ else
+ theSlide = theSlideCount - 1;
+ }
+ if (theSlide != theComponent->GetCurrentSlide()) {
+ CQmlCommandHelper::SetupGotoSlideCommand(*theTarget, theSlide, inArgs);
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "QmlEngine::GotoSlideRelative: Component is not active: " << component;
+ }
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "QmlEngine::GotoSlideRelative: failed to find component: " << component;
+ }
+}
+
+void CQmlEngineImpl::SetPresentationAttribute(const char *presId, const char *, const char *value)
+{
+ if (isTrivial(presId))
+ return;
+ if (presId[0] == '#')
+ ++presId;
+ CPresentation *thePresentation = m_Application->GetPresentationById(presId);
+ if (thePresentation) {
+ bool active = AreEqualCaseless(nonNull(value), "True");
+ thePresentation->SetActive(active);
+ }
+}
+
+void CQmlEngineImpl::GotoSlideIndex(const char *component, const Q3DStudio::INT32 slideIndex,
+ const SScriptEngineGotoSlideArgs &inArgs)
+{
+ TElement *theTarget = getTarget(component);
+ if (theTarget) {
+ CQmlCommandHelper::SetupGotoSlideCommand(*theTarget, slideIndex, inArgs);
+ } else {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::GotoSlide: Unable to find component " << component;
+ }
+}
+
+bool CQmlEngineImpl::GetSlideInfo(const char *element, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+
+ TElement *theTarget = getTarget(element);
+ if (theTarget && theTarget->IsComponent()) {
+ IPresentation *thePresentation = theTarget->GetBelongedPresentation();
+ TComponent *theComponent = thePresentation->GetComponentManager().GetComponent(theTarget);
+ currentIndex = int(theComponent->GetCurrentSlide());
+ previousIndex = int(theComponent->GetPreviousSlide());
+ if (currentIndex > 0) {
+ currentName = QString::fromLocal8Bit(
+ thePresentation->GetSlideSystem().GetSlideName(
+ uic::runtime::SSlideKey(*theComponent, QT3DSU32(currentIndex))));
+ } else {
+ currentName.clear();
+ }
+ if (previousIndex > 0) {
+ previousName = QString::fromLocal8Bit(
+ thePresentation->GetSlideSystem().GetSlideName(
+ uic::runtime::SSlideKey(*theComponent, QT3DSU32(previousIndex))));
+ } else {
+ previousName.clear();
+ }
+ return true;
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::GetSlideInfo: Supplied element is not a component " << element;
+ }
+ return false;
+}
+
+void CQmlEngineImpl::GotoTime(const char *component, const Q3DStudio::FLOAT time)
+{
+ TElement *theTarget = getTarget(component);
+ if (theTarget && theTarget->GetActive()) {
+ UVariant theArg1;
+ UVariant theArg2;
+
+ IPresentation *thePresentation = theTarget->GetBelongedPresentation();
+
+ theArg1.m_INT32 = static_cast<INT32>(time * 1000);
+
+ TElement *theParentTarget = &theTarget->GetComponentParent();
+
+ thePresentation->FireCommand(COMMAND_GOTOTIME, theParentTarget, &theArg1, &theArg2);
+ }
+}
+
+bool CQmlEngineImpl::RegisterCallback(Q3DStudio::UINT32 callbackType,
+ const TScriptCallback inCallback, void *inUserData)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ return m_ScriptCallbacks.RegisterCallback(callbackType, inCallback, inUserData);
+}
+
+void CQmlEngineImpl::ProcessFrameCallbacks(IPresentation *)
+{
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ m_ScriptCallbacks.ProcessCallbacks();
+
+ for (Q3DSQmlScript *script : m_scripts)
+ script->update();
+}
+
+void CQmlEngineImpl::ProcessSignal(IPresentation *inPresentation,
+ const SEventCommand &inCommand)
+{
+ using uic::runtime::TIdValuePair;
+ QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
+ TElement *theElement = inCommand.m_Target; // the element that is a behavior
+
+ CPresentation *thePresentation = (CPresentation *)inPresentation;
+ // IParametersSystem& theParametersManager = thePresentation->GetParametersSystem();
+ qt3ds::foundation::IStringTable &theStrTable(thePresentation->GetStringTable());
+
+ CRegisteredString theSignal = theStrTable.HandleToStr(inCommand.m_Arg1.m_INT32);
+
+ if (!theSignal.IsValid() || m_EmitSignalDataList.size() > CQmlEngineImpl::MAX_ACTION_QUEUE_SIZE)
+ return;
+
+ TEmitSignalPtr theTemp = QT3DS_NEW(m_Foundation.getAllocator(), SEmitSignalData)(
+ m_Foundation.getAllocator(), inCommand.m_Arg1.m_INT32, theElement);
+ m_EmitSignalDataList.push_back(theTemp);
+}
+
+
+//==============================================================================
+/**
+* Handle custom actions
+* @param inCommand carrier of command and parameter information
+*/
+void CQmlEngineImpl::ProcessCustomActions(IPresentation *presentation,
+ const SEventCommand &command)
+{
+ TElement *element = command.m_Target;
+ for (Q3DSQmlScript *script : m_scripts) {
+ if (script->hasBehavior(element)) {
+ IParametersSystem &parametersManager
+ = static_cast<CPresentation *>(presentation)->GetParametersSystem();
+ INT32 groupId = command.m_Arg1.m_INT32;
+ UINT32 numParams = parametersManager.GetNumParameters(groupId);
+ if (numParams == 0) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ uic::runtime::TIdValuePair tempData = parametersManager.GetParameter(groupId, 0);
+ if (tempData.first != CHash::HashString("string")) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ CRegisteredString functionName = presentation->GetStringTable().HandleToStr(
+ tempData.second.m_StringHandle);
+ script->call(functionName.c_str());
+ return;
+ }
+ }
+}
+
+bool CQmlEngineImpl::PeekSignal(TElement *&outElement, char *&outName)
+{
+ if (m_EmitSignalDataList.empty())
+ return false;
+
+ NVScopedRefCounted<SEmitSignalData> theAction = m_EmitSignalDataList.front();
+ m_EmitSignalDataList.pop_front();
+
+ outElement = theAction->m_TargetElement;
+ if (outElement) {
+ IPresentation *thePresentation = outElement->GetBelongedPresentation();
+ qt3ds::foundation::IStringTable &theStrTable(thePresentation->GetStringTable());
+ CRegisteredString theSignal = theStrTable.HandleToStr(theAction->m_SignalNameHandler);
+ outName = (char *)theSignal.c_str();
+ } else {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "CQmlEngineImpl::PeekCustomAction: Unable to find element: EmitSignal queue error";
+ outName = NULL;
+ }
+
+ return true;
+}
+
+void CQmlEngineImpl::createComponent(QQmlComponent *component, TElement *element)
+{
+ TElement *parent = element->GetParent();
+ if (!parent)
+ return;
+
+ QQmlContext *context = new QQmlContext(&m_engine, &m_engine);
+ QObject *obj = component->beginCreate(context);
+ if (!obj) {
+ context->deleteLater();
+ return;
+ }
+
+ auto script = new Q3DSQmlScript(*this, *obj, *element, *parent);
+ context->setContextProperty("Qt3ds", script);
+ component->completeCreate();
+
+ script->setParent(component);
+ obj->setParent(script);
+ m_scripts.push_back(script);
+}
+
+TElement *CQmlEngineImpl::getTarget(const char *component) {
+ TElement *target = NULL;
+ QStringList split = QString(component).split(":");
+ if (split.size() > 1) {
+ target = CQmlElementHelper::GetElement(
+ *m_Application,
+ m_Application->GetPresentationById(split.at(0).toStdString().c_str()),
+ split.at(1).toStdString().c_str(), NULL);
+ } else {
+ target = CQmlElementHelper::GetElement(
+ *m_Application,
+ m_Application->GetPrimaryPresentation(),
+ split.at(0).toStdString().c_str(), NULL);
+ }
+ return target;
+}
+
+/**
+* @brief Create QML engine
+*
+* @param[in] inFoundation Pointer to foundation
+* @param[in] inTimeProvider Pointer to time provider
+*
+* @return no return
+*/
+CQmlEngine *CQmlEngine::Create(qt3ds::NVFoundationBase &inFoundation, ITimeProvider &inTimeProvider)
+{
+ return QT3DS_NEW(inFoundation.getAllocator(), CQmlEngineImpl)(inFoundation, inTimeProvider);
+}
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICSlideSystem.cpp b/src/Runtime/Source/Runtime/Source/UICSlideSystem.cpp
new file mode 100644
index 00000000..6e063d4f
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICSlideSystem.cpp
@@ -0,0 +1,628 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "RuntimePrefix.h"
+#include "UICSlideSystem.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICAnimationSystem.h"
+#include "UICLogicSystem.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/IOStreams.h"
+#include "UICHash.h"
+#include "UICTimePolicy.h"
+#include "foundation/Qt3DSIndexableLinkedList.h"
+#include "UICBinarySerializationHelper.h"
+
+using namespace uic::runtime;
+using namespace uic::runtime::element;
+
+namespace {
+struct SSlideAttribute
+{
+ QT3DSU32 m_Index;
+ Q3DStudio::UVariant m_Value;
+ SSlideAttribute()
+ : m_Index(0)
+ {
+ m_Value.m_INT32 = 0;
+ }
+ SSlideAttribute(QT3DSU32 idx, Q3DStudio::UVariant val)
+ : m_Index(idx)
+ , m_Value(val)
+ {
+ }
+};
+
+struct SSlideAttributeNode
+{
+ enum {
+ AttributeCount = 8,
+ };
+
+ SSlideAttribute m_Data[AttributeCount];
+ SSlideAttributeNode *m_NextNode;
+
+ SSlideAttributeNode()
+ : m_NextNode(NULL)
+ {
+ }
+};
+
+typedef IndexableLinkedList<SSlideAttributeNode, SSlideAttribute,
+ SSlideAttributeNode::AttributeCount>
+ TSlideAttributeNodeList;
+
+struct SSlideElement
+{
+ QT3DSU32 m_ElementHandle;
+ QT3DSU32 m_AttributeCount : 31;
+ QT3DSU32 m_Active : 1;
+ SSlideElement *m_NextElement;
+ SSlideAttributeNode *m_AttributeNodes;
+
+ SSlideElement()
+ : m_ElementHandle(0)
+ , m_AttributeCount(0)
+ , m_Active(false)
+ , m_NextElement(NULL)
+ , m_AttributeNodes(NULL)
+ {
+ }
+};
+
+struct SSlideAnimActionNode
+{
+ enum {
+ AnimActionCount = 8,
+ };
+ SSlideAnimAction m_Data[AnimActionCount];
+ SSlideAnimActionNode *m_NextNode;
+ SSlideAnimActionNode()
+ : m_NextNode(NULL)
+ {
+ }
+};
+
+typedef IndexableLinkedList<SSlideAnimActionNode, SSlideAnimAction,
+ SSlideAnimActionNode::AnimActionCount>
+ TSlideAnimActionNodeList;
+
+struct SSlide
+{
+ SSlide *m_NextSlide;
+ CRegisteredString m_Name;
+ QT3DSU32 m_PlayMode : 3;
+ QT3DSU32 m_PlayThroughTo : 8; // OXFF means no playthrough
+ QT3DSU32 m_Paused : 1;
+ QT3DSU32 m_StartTime;
+ QT3DSU32 m_EndTime;
+ QT3DSU32 m_AnimActionCount;
+ SSlideElement *m_FirstElement;
+ SSlideAnimActionNode *m_FirstAnimActionNode;
+
+ SSlide()
+ : m_NextSlide(NULL)
+ , m_PlayMode(PlayMode::StopAtEnd)
+ , m_PlayThroughTo(0xFF)
+ , m_Paused(false)
+ , m_StartTime(0)
+ , m_EndTime(0)
+ , m_AnimActionCount(0)
+ , m_FirstElement(NULL)
+ , m_FirstAnimActionNode(NULL)
+ {
+ }
+
+ void Initialize(CRegisteredString inName, PlayMode::Enum inMode, QT3DSU8 inPlayThrough,
+ bool inPaused, QT3DSU32 inStartTime, QT3DSU32 inEndTime)
+ {
+ m_Name = inName;
+ m_PlayMode = inMode;
+ m_PlayThroughTo = inPlayThrough;
+ m_Paused = inPaused;
+ m_StartTime = inStartTime;
+ m_EndTime = inEndTime;
+ }
+};
+
+struct SSlideSystem : public ISlideSystem
+{
+ typedef nvhash_map<SElement *, SSlide *> TComponentSlideHash;
+ typedef Pool<SSlideAttributeNode, ForwardingAllocator> TAttributeNodePool;
+ typedef Pool<SSlideAnimActionNode, ForwardingAllocator> TSlideAnimActionPool;
+ typedef Pool<SSlideElement, ForwardingAllocator> TSlideElementPool;
+ typedef Pool<SSlide, ForwardingAllocator> TSlidePool;
+
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ IElementAllocator &m_ElementSystem;
+ TAttributeNodePool m_AttributeNodePool;
+ TSlideAnimActionPool m_AnimActionPool;
+ TSlideElementPool m_SlideElements;
+ TSlidePool m_SlidePool;
+ TComponentSlideHash m_Slides;
+
+ SSlide *m_CurrentSlide;
+ SSlideElement *m_CurrentSlideElement;
+
+ NVDataRef<QT3DSU8> m_LoadData;
+
+ QT3DSI32 m_RefCount;
+
+ SSlideSystem(NVFoundationBase &inFnd, IStringTable &inStrTable, IElementAllocator &inAllocator)
+ : m_Foundation(inFnd)
+ , m_StringTable(inStrTable)
+ , m_ElementSystem(inAllocator)
+ , m_AttributeNodePool(ForwardingAllocator(inFnd.getAllocator(), "m_AttributeNodePool"))
+ , m_AnimActionPool(ForwardingAllocator(inFnd.getAllocator(), "m_AnimActionPool"))
+ , m_SlidePool(ForwardingAllocator(inFnd.getAllocator(), "m_SlidePool"))
+ , m_SlideElements(ForwardingAllocator(inFnd.getAllocator(), "m_SlideElements"))
+ , m_Slides(inFnd.getAllocator(), "m_Slides")
+ , m_CurrentSlide(NULL)
+ , m_CurrentSlideElement(NULL)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Foundation.getAllocator());
+ NVDelete(alloc, this);
+ }
+ }
+
+ QT3DSU32 AddSlide(element::SElement &inComponent, const char8_t *inName,
+ PlayMode::Enum inPlayMode, bool inPaused, QT3DSU8 inPlayThroughTo,
+ QT3DSU32 inMinTime, QT3DSU32 inMaxTime) override
+ {
+ eastl::pair<TComponentSlideHash::iterator, bool> inserter =
+ m_Slides.insert(eastl::make_pair(&inComponent, (SSlide *)NULL));
+ SSlide *newSlide = m_SlidePool.construct(__FILE__, __LINE__);
+ QT3DSU32 slideIndex = 0;
+ if (inserter.first->second == NULL) {
+ inserter.first->second = newSlide;
+ } else {
+ SSlide *theSlide = NULL;
+ for (theSlide = inserter.first->second; theSlide->m_NextSlide != NULL;
+ theSlide = theSlide->m_NextSlide) {
+ ++slideIndex;
+ }
+ theSlide->m_NextSlide = newSlide;
+ }
+ m_CurrentSlide = newSlide;
+ newSlide->Initialize(m_StringTable.RegisterStr(inName), inPlayMode, inPlayThroughTo,
+ inPaused, inMinTime, inMaxTime);
+ m_CurrentSlideElement = NULL;
+ if (inComponent.IsComponent()) {
+ SComponent &theComponent = static_cast<SComponent &>(inComponent);
+ theComponent.m_SlideCount++;
+ }
+ return slideIndex;
+ }
+
+ void SetSlideMaxTime(QT3DSU32 inMaxTime) override
+ {
+ if (m_CurrentSlide != NULL)
+ m_CurrentSlide->m_EndTime = inMaxTime;
+ }
+
+ void AddSlideElement(element::SElement &inElement, bool inActive) override
+ {
+ if (m_CurrentSlide != NULL) {
+ SSlideElement *lastSlideElement = m_CurrentSlideElement;
+ m_CurrentSlideElement = m_SlideElements.construct(__FILE__, __LINE__);
+ m_CurrentSlideElement->m_Active = inActive;
+ m_CurrentSlideElement->m_ElementHandle = inElement.GetHandle();
+ if (lastSlideElement == NULL) {
+ QT3DS_ASSERT(m_CurrentSlide->m_FirstElement == NULL);
+ m_CurrentSlide->m_FirstElement = m_CurrentSlideElement;
+ } else {
+ lastSlideElement->m_NextElement = m_CurrentSlideElement;
+ }
+ m_CurrentSlideElement->m_Active = inActive;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ void AddSlideAttribute(Q3DStudio::SAttributeKey inKey, Q3DStudio::UVariant inValue) override
+ {
+ if (m_CurrentSlideElement != NULL) {
+
+ SElement *theElement =
+ m_ElementSystem.FindElementByHandle(m_CurrentSlideElement->m_ElementHandle);
+ Option<QT3DSU32> theIdx = theElement->FindPropertyIndex(inKey.m_Hash);
+ if (theIdx.hasValue() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ QT3DSU32 count = m_CurrentSlideElement->m_AttributeCount;
+ TSlideAttributeNodeList::Create(m_CurrentSlideElement->m_AttributeNodes, count,
+ m_AttributeNodePool) =
+ SSlideAttribute(*theIdx, inValue);
+ m_CurrentSlideElement->m_AttributeCount = count;
+ }
+ }
+
+ SSlideAnimAction *AddSlideAnimAction(bool inAnimation, QT3DSI32 inId, bool inActive) override
+ {
+ if (m_CurrentSlide != NULL) {
+ SSlideAnimAction &theAnimAction = TSlideAnimActionNodeList::Create(
+ m_CurrentSlide->m_FirstAnimActionNode, m_CurrentSlide->m_AnimActionCount,
+ m_AnimActionPool);
+ theAnimAction = SSlideAnimAction((QT3DSI32)inId, inActive, inAnimation);
+ &theAnimAction;
+ }
+
+ return NULL;
+ }
+
+ const SSlide *FindSlide(SSlideKey inKey) const
+ {
+ TComponentSlideHash::const_iterator iter = m_Slides.find(inKey.m_Component);
+ if (iter == m_Slides.end())
+ return NULL;
+
+ SSlide *theSlide = iter->second;
+ for (QT3DSU32 idx = inKey.m_Index; idx; --idx) {
+ if (theSlide)
+ theSlide = theSlide->m_NextSlide;
+ }
+
+ return theSlide;
+ }
+
+ template <typename TOperator>
+ static void IterateSlideAnimActions(const SSlide &inSlide, TOperator inOp)
+ {
+ for (TSlideAnimActionNodeList::const_iterator
+ iter = TSlideAnimActionNodeList::begin(inSlide.m_FirstAnimActionNode,
+ inSlide.m_AnimActionCount),
+ end = TSlideAnimActionNodeList::end(inSlide.m_FirstAnimActionNode,
+ inSlide.m_AnimActionCount);
+ iter != end; ++iter) {
+ inOp(*iter);
+ }
+ }
+
+ template <typename TOperator>
+ static void IterateSlideElementAttributes(const SSlide &inSlide, TOperator inOp,
+ IElementAllocator &inAlloc)
+ {
+ for (SSlideElement *theElement = inSlide.m_FirstElement; theElement;
+ theElement = theElement->m_NextElement) {
+ SElement *theElem = inAlloc.FindElementByHandle(theElement->m_ElementHandle);
+ if (!theElem) {
+ QT3DS_ASSERT(false);
+ } else {
+ if (inOp.handleElementActive(*theElem, theElement->m_Active)) {
+ for (TSlideAttributeNodeList::const_iterator
+ iter = TSlideAttributeNodeList::begin(theElement->m_AttributeNodes,
+ theElement->m_AttributeCount),
+ end = TSlideAttributeNodeList::end(theElement->m_AttributeNodes,
+ theElement->m_AttributeCount);
+ iter != end; ++iter) {
+ inOp.handleElementAttribute(*theElem, *iter);
+ }
+ }
+ }
+ }
+ }
+
+ struct SDynamicKeyOperator
+ {
+ IAnimationSystem &m_AnimationSystem;
+ SDynamicKeyOperator(IAnimationSystem &anim)
+ : m_AnimationSystem(anim)
+ {
+ }
+ void operator()(const SSlideAnimAction &theAction)
+ {
+ if (theAction.m_IsAnimation && theAction.m_Active)
+ m_AnimationSystem.UpdateDynamicKey(theAction.m_Id);
+ }
+ };
+
+ struct SExecuteAnimActionOperator
+ {
+ IElementAllocator &m_ElementAllocator;
+ IAnimationSystem &m_AnimationSystem;
+ ILogicSystem &m_LogicManager;
+ bool m_Invert;
+
+ SExecuteAnimActionOperator(IElementAllocator &inElemAllocator, IAnimationSystem &anim,
+ ILogicSystem &logic, bool inInvert = false)
+ : m_ElementAllocator(inElemAllocator)
+ , m_AnimationSystem(anim)
+ , m_LogicManager(logic)
+ , m_Invert(inInvert)
+ {
+ }
+
+ void operator()(const SSlideAnimAction &theAction)
+ {
+ bool active = theAction.m_Active;
+ if (m_Invert)
+ active = !active;
+ if (theAction.m_IsAnimation)
+ m_AnimationSystem.SetActive(theAction.m_Id, active);
+ else
+ m_LogicManager.SetActive(theAction.m_Id, active, m_ElementAllocator);
+ }
+ };
+
+ struct SElementOperator
+ {
+ bool m_InvertActive;
+ SElementOperator(bool inInvert = false)
+ : m_InvertActive(inInvert)
+ {
+ }
+ bool handleElementActive(SElement &inElement, bool inActive)
+ {
+ if (m_InvertActive)
+ inActive = !inActive;
+ inElement.Flags().SetExplicitActive(inActive);
+
+ if (m_InvertActive)
+ return false;
+
+ return inActive;
+ }
+
+ void handleElementAttribute(SElement &inElement, const SSlideAttribute &inAttribute)
+ {
+ Option<TPropertyDescAndValuePtr> theProperty =
+ inElement.GetPropertyByIndex(inAttribute.m_Index);
+ if (theProperty.hasValue()) {
+ inElement.SetAttribute(*theProperty, inAttribute.m_Value);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ };
+
+ void InitializeDynamicKeys(SSlideKey inKey, IAnimationSystem &inAnimationSystem) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+ if (theSlide != NULL) {
+ IterateSlideAnimActions(*theSlide, SDynamicKeyOperator(inAnimationSystem));
+ }
+ }
+
+ void ExecuteSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
+ ILogicSystem &inLogicManager) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+
+ if (theSlide == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (inKey.m_Component->IsComponent()) {
+ Q3DStudio::TTimeUnit theLoopDuration = theSlide->m_EndTime - theSlide->m_StartTime;
+ SComponent &theComponent = static_cast<SComponent &>(*inKey.m_Component);
+ Q3DStudio::CTimePolicy &thePolicy = theComponent.GetTimePolicy();
+ Q3DStudio::TimePolicyModes::Enum theMode = Q3DStudio::TimePolicyModes::StopAtEnd;
+ switch (theSlide->m_PlayMode) {
+ case PlayMode::Looping:
+ theMode = Q3DStudio::TimePolicyModes::Looping;
+ break;
+ case PlayMode::PingPong:
+ theMode = Q3DStudio::TimePolicyModes::PingPong;
+ break;
+ case PlayMode::Ping:
+ theMode = Q3DStudio::TimePolicyModes::Ping;
+ break;
+
+ case PlayMode::StopAtEnd:
+ case PlayMode::PlayThroughTo:
+ default:
+ theMode = Q3DStudio::TimePolicyModes::StopAtEnd;
+ break;
+ }
+ thePolicy.Initialize(theLoopDuration, theMode);
+ thePolicy.SetPaused(theSlide->m_Paused);
+
+ theComponent.SetPlayThrough(theSlide->m_PlayMode == PlayMode::PlayThroughTo);
+ }
+
+ IterateSlideElementAttributes(*theSlide, SElementOperator(false), m_ElementSystem);
+ IterateSlideAnimActions(*theSlide, SExecuteAnimActionOperator(
+ m_ElementSystem, inAnimationSystem, inLogicManager));
+ }
+
+ void RollbackSlide(SSlideKey inKey, IAnimationSystem &inAnimationSystem,
+ ILogicSystem &inLogicManager) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+
+ if (theSlide == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ IterateSlideElementAttributes(*theSlide, SElementOperator(true), m_ElementSystem);
+ IterateSlideAnimActions(
+ *theSlide,
+ SExecuteAnimActionOperator(m_ElementSystem, inAnimationSystem, inLogicManager, true));
+ }
+
+ QT3DSU8 FindSlide(element::SElement &inComponent, const char8_t *inSlideName) const override
+ {
+ TComponentSlideHash::const_iterator theFindResult = m_Slides.find(&inComponent);
+ if (theFindResult == m_Slides.end()) {
+ QT3DS_ASSERT(false);
+ return 0xFF;
+ }
+ CRegisteredString theRegName = m_StringTable.RegisterStr(inSlideName);
+ QT3DSU8 idx = 0;
+ for (const SSlide *theSlide = theFindResult->second; theSlide;
+ theSlide = theSlide->m_NextSlide, ++idx) {
+ if (theSlide->m_Name == theRegName)
+ return idx;
+ }
+ return 0xFF;
+ }
+
+ QT3DSU8 FindSlide(element::SElement &inComponent, QT3DSU32 inSlideHashName) const override
+ {
+ TComponentSlideHash::const_iterator theFindResult = m_Slides.find(&inComponent);
+ if (theFindResult == m_Slides.end()) {
+ QT3DS_ASSERT(false);
+ return 0xFF;
+ }
+
+ QT3DSU8 idx = 0;
+ for (const SSlide *theSlide = theFindResult->second; theSlide;
+ theSlide = theSlide->m_NextSlide, ++idx) {
+ if (Q3DStudio::CHash::HashString(theSlide->m_Name) == inSlideHashName)
+ return idx;
+ }
+ return 0xFF;
+ }
+
+ const char8_t *GetSlideName(SSlideKey inKey) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+ if (theSlide)
+ return theSlide->m_Name.c_str();
+ QT3DS_ASSERT(false);
+ return "";
+ }
+
+ QT3DSU8 GetPlaythroughToSlideIndex(SSlideKey inKey) const override
+ {
+ const SSlide *theSlide = FindSlide(inKey);
+ if (theSlide)
+ return theSlide->m_PlayThroughTo;
+ QT3DS_ASSERT(false);
+ return 0xFF;
+ }
+
+ void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriter(m_Foundation.getAllocator(), "WriteBuffer");
+ theWriter.write((QT3DSU32)m_Slides.size());
+ for (TComponentSlideHash::iterator iter = m_Slides.begin(), end = m_Slides.end();
+ iter != end; ++iter) {
+ QT3DSU32 handle = iter->first->GetHandle();
+ SSlide *firstSlide = iter->second;
+ theWriter.write(handle);
+ size_t slideCountOffset = (QT3DSU32)theWriter.size();
+ theWriter.write(0);
+ QT3DSU32 slideCount = 0;
+ for (SSlide *theSlide = firstSlide; theSlide;
+ theSlide = theSlide->m_NextSlide, ++slideCount) {
+ size_t theSlideOffset = (QT3DSU32)theWriter.size();
+ theWriter.write(*theSlide);
+ size_t theElementCountOffset = (QT3DSU32)theWriter.size();
+ theWriter.write((QT3DSU32)0);
+ QT3DSU32 theElementCount = 0;
+ for (SSlideElement *theElement = theSlide->m_FirstElement; theElement;
+ theElement = theElement->m_NextElement, ++theElementCount) {
+ theWriter.write(*theElement);
+ SaveIndexableList<TSlideAttributeNodeList>(theElement->m_AttributeNodes,
+ theWriter);
+ }
+
+ SaveIndexableList<TSlideAnimActionNodeList>(theSlide->m_FirstAnimActionNode,
+ theWriter);
+
+ SSlide *theWrittenSlide =
+ reinterpret_cast<SSlide *>(theWriter.begin() + theSlideOffset);
+ theWrittenSlide->m_Name.Remap(m_StringTable);
+ theWrittenSlide->m_FirstAnimActionNode = NULL;
+ theWrittenSlide->m_FirstElement = NULL;
+ QT3DSU32 *theElementCountPtr =
+ reinterpret_cast<QT3DSU32 *>(theWriter.begin() + theElementCountOffset);
+ theElementCountPtr[0] = theElementCount;
+ }
+ QT3DSU32 *theSlideCountPtr =
+ reinterpret_cast<QT3DSU32 *>(theWriter.begin() + slideCountOffset);
+ theSlideCountPtr[0] = slideCount;
+ }
+ ioStream.Write(theWriter.begin(), theWriter.size());
+ }
+
+ void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData, NVDataRef<QT3DSU8> inStringTableData,
+ size_t /*inElementOffset*/) override
+ {
+ m_LoadData = inLoadData;
+
+ SDataReader theReader(inLoadData.begin(), inLoadData.end());
+ QT3DSU32 numComponents = *theReader.Load<QT3DSU32>();
+ for (QT3DSU32 compIdx = 0; compIdx < numComponents; ++compIdx) {
+ QT3DSU32 compHandle = *theReader.Load<QT3DSU32>();
+ SElement *theElement = m_ElementSystem.FindElementByHandle(compHandle);
+ QT3DSU32 numComponentSlides = *theReader.Load<QT3DSU32>();
+ SSlide *lastSlide = NULL;
+ for (QT3DSU32 slideIdx = 0; slideIdx < numComponentSlides; ++slideIdx) {
+ SSlide *theSlide = theReader.Load<SSlide>();
+ if (slideIdx == 0)
+ m_Slides.insert(eastl::make_pair(theElement, theSlide));
+ else
+ lastSlide->m_NextSlide = theSlide;
+
+ lastSlide = theSlide;
+ theSlide->m_Name.Remap(inStringTableData);
+ theSlide->m_NextSlide = NULL;
+ QT3DSU32 elementCount = *theReader.Load<QT3DSU32>();
+ SSlideElement *lastElement = NULL;
+ for (QT3DSU32 elemIdx = 0; elemIdx < elementCount; ++elemIdx) {
+ SSlideElement *theElement = theReader.Load<SSlideElement>();
+ if (elemIdx == 0)
+ theSlide->m_FirstElement = theElement;
+ else
+ lastElement->m_NextElement = theElement;
+ lastElement = theElement;
+ LoadIndexableList<TSlideAttributeNodeList>(
+ theElement->m_AttributeNodes, theElement->m_AttributeCount, theReader);
+ }
+
+ LoadIndexableList<TSlideAnimActionNodeList>(theSlide->m_FirstAnimActionNode,
+ theSlide->m_AnimActionCount, theReader);
+ }
+ }
+ }
+};
+}
+
+ISlideSystem &ISlideSystem::CreateSlideSystem(NVFoundationBase &inFnd, IStringTable &inStrTable,
+ IElementAllocator &inElemAllocator)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), SSlideSystem)(inFnd, inStrTable, inElemAllocator);
+}
diff --git a/src/Runtime/Source/Runtime/Source/UICTimePolicy.cpp b/src/Runtime/Source/Runtime/Source/UICTimePolicy.cpp
new file mode 100644
index 00000000..a1764a63
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/UICTimePolicy.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTimePolicy.h"
+#include "foundation/Qt3DSUnionCast.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "UICComponentManager.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+const TTimeUnit CTimePolicy::FOREVER = 0;
+
+SAlignedTimeUnit::SAlignedTimeUnit(const TTimeUnit &inUnit)
+{
+ StaticAssert<sizeof(SAlignedTimeUnit) == sizeof(TTimeUnit)>::valid_expression();
+ qt3ds::intrinsics::memCopy(this, &inUnit, sizeof(TTimeUnit));
+}
+
+SAlignedTimeUnit::operator TTimeUnit() const
+{
+ TTimeUnit retval;
+ qt3ds::intrinsics::memCopy(&retval, this, sizeof(TTimeUnit));
+ return retval;
+}
+
+void SAlignedTimeUnit::operator-=(const TTimeUnit &inTime)
+{
+ TTimeUnit theThis(*this);
+ theThis -= inTime;
+ *this = SAlignedTimeUnit(theThis);
+}
+
+void SAlignedTimeUnit::operator%=(const TTimeUnit &inTime)
+{
+ TTimeUnit theThis(*this);
+ theThis %= inTime;
+ *this = SAlignedTimeUnit(theThis);
+}
+
+//==============================================================================
+/**
+ * Initialization
+ */
+
+void CTimePolicy::Initialize(const TTimeUnit inLoopingDuration, TimePolicyModes::Enum inMode)
+{
+ m_LocalTime = 0;
+ m_LoopingDuration = (unsigned long)inLoopingDuration;
+ m_TimePolicyMode = inMode;
+ m_Offset = 0;
+ m_Paused = false;
+ m_OffsetInvalid = 1;
+ m_Backward = 0;
+ m_Rate = 1.0f;
+}
+
+void CTimePolicy::Initialize(const TTimeUnit inLoopingDuration /*= FOREVER*/,
+ UINT32 inRepetitions /*= 1*/, BOOL inPingPong /*= false*/)
+{
+ // UINT8 m_Repetitions : 2; ///< Number of traversal ( 0 = forever, 1 = stop at end, 2 =
+ // ping )
+ TimePolicyModes::Enum theMode = TimePolicyModes::StopAtEnd;
+ if (inRepetitions == 1)
+ theMode = TimePolicyModes::StopAtEnd;
+ else if (inRepetitions == 0) {
+ if (inPingPong)
+ theMode = TimePolicyModes::PingPong;
+ else
+ theMode = TimePolicyModes::Looping;
+ } else
+ theMode = TimePolicyModes::Ping;
+
+ Initialize(inLoopingDuration, theMode);
+}
+
+//==============================================================================
+/**
+ * Return the last computed time. This is subjected to playmodes.
+ * @return local time
+ */
+TTimeUnit CTimePolicy::InternalGetTime() const
+{
+ if (m_LocalTime < m_LoopingDuration)
+ return m_LocalTime;
+ else {
+ if (m_LoopingDuration == 0)
+ return m_LocalTime;
+
+ switch (m_TimePolicyMode) {
+ case TimePolicyModes::StopAtEnd:
+ return m_LoopingDuration;
+ case TimePolicyModes::Looping:
+ return m_LocalTime % m_LoopingDuration;
+ case TimePolicyModes::Ping: {
+ unsigned long interval = m_LocalTime / m_LoopingDuration;
+ unsigned long leftover = m_LocalTime % m_LoopingDuration;
+ if (interval == 1)
+ return m_LoopingDuration - leftover;
+ return 0;
+ }
+ case TimePolicyModes::PingPong: {
+ unsigned long interval = m_LocalTime / m_LoopingDuration;
+ unsigned long leftover = m_LocalTime % m_LoopingDuration;
+ if (interval % 2)
+ return m_LoopingDuration - leftover;
+ return leftover;
+ }
+ default:
+ QT3DS_ASSERT(false);
+ return 0;
+ break;
+ }
+ }
+}
+
+TTimeUnit CTimePolicy::GetTime() const
+{
+ TTimeUnit retval = InternalGetTime();
+ // Apply direction and rate.
+ bool isPlayingBack = m_Backward;
+ if (m_Rate < 0)
+ isPlayingBack = !isPlayingBack;
+
+ if (isPlayingBack)
+ retval = m_LoopingDuration - retval;
+ return retval;
+}
+
+static unsigned long clampTime(long inTime, unsigned long inDuration)
+{
+ if (inTime < 0)
+ return 0;
+ if (inTime > (long)inDuration)
+ return inDuration;
+ return (unsigned long)inTime;
+}
+
+//==============================================================================
+/**
+ * Trigger the policy to return inTime next GetTime is called.
+ * This is tricky math and the m_Offset field is being used both normally to
+ * simply change the time and here to calibrate itself next time ComputeTime
+ * is called.
+ * @param inTime time to be returned next ComputeTime
+ */
+void CTimePolicy::SetTime(TTimeUnit inTime)
+{
+
+ bool isPlayingBack = m_Backward;
+ if (m_Rate < 0)
+ isPlayingBack = !isPlayingBack;
+
+ if (isPlayingBack)
+ inTime = m_LoopingDuration - inTime;
+
+ m_OffsetInvalid = 1;
+
+ // Setup m_LocalTime such that it reflects intime.
+ if (m_LoopingDuration == 0) {
+ m_LocalTime = (unsigned long)inTime;
+ return;
+ }
+
+ switch (m_TimePolicyMode) {
+ case TimePolicyModes::StopAtEnd:
+ m_LocalTime = clampTime((long)inTime, m_LoopingDuration);
+ break;
+ case TimePolicyModes::Looping: {
+ long input = (long)inTime;
+ while (input < 0)
+ input += (long)m_LoopingDuration;
+ m_LocalTime = ((unsigned long)input) % m_LoopingDuration;
+ } break;
+ case TimePolicyModes::Ping: {
+ long input = (long)inTime;
+ if (input < 0)
+ input = 0;
+
+ long totalInterval = (long)(m_LoopingDuration * 2);
+ if (input > totalInterval)
+ m_LocalTime = (unsigned long)totalInterval;
+ else
+ m_LocalTime = (unsigned long)input;
+ } break;
+ case TimePolicyModes::PingPong: {
+ long totalInterval = (long)(m_LoopingDuration * 2);
+ long input = (long)inTime;
+ while (input < 0)
+ input += totalInterval;
+ m_LocalTime = (unsigned long)(input % totalInterval);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+}
+
+//==============================================================================
+/**
+ * Retrieves the looping duration.
+ * @see CTimePolicy::SetLoopingDuration( )
+ * @return TTimeUnit looping duration
+ */
+TTimeUnit CTimePolicy::GetLoopingDuration() const
+{
+ return m_LoopingDuration;
+}
+
+//==============================================================================
+/**
+ * Set the looping duration.
+ * Looping duration is defined as the time it takes before stopping, pinging or
+ * looping.
+ * @param inTime looping duration
+ */
+void CTimePolicy::SetLoopingDuration(const TTimeUnit inTime)
+{
+ m_LoopingDuration = (unsigned long)inTime;
+}
+
+//==============================================================================
+/**
+ * Return the paused state.
+ * @return BOOL pause state
+ */
+BOOL CTimePolicy::GetPaused() const
+{
+ return m_Paused;
+}
+
+BOOL CTimePolicy::GetPlayBackDirection() const
+{
+ bool reversePlaybackDirection = m_Backward;
+ if (m_Rate < 0)
+ reversePlaybackDirection = !reversePlaybackDirection;
+
+ bool retval = m_LocalTime < m_LoopingDuration;
+
+ if (reversePlaybackDirection)
+ retval = !retval;
+ return retval;
+}
+
+//==============================================================================
+/**
+ * Sets the paused state
+ * @param inPaused pause state
+ */
+void CTimePolicy::SetPaused(const BOOL inPaused)
+{
+ m_Paused = static_cast<UINT8>(inPaused);
+}
+
+BOOL CTimePolicy::UpdateTime(const TTimeUnit inTime)
+{
+ if (fabs(m_Rate) > .001f)
+ m_LocalTime =
+ static_cast<unsigned long>(((unsigned long)(inTime + m_Offset)) * fabs(m_Rate));
+ // else we are effectively stopped and we can't update the time.
+
+ if (m_LoopingDuration == 0)
+ return FALSE;
+
+ unsigned long maxUsefulDuration = m_LoopingDuration * 2;
+ BOOL retval = 0;
+ switch (m_TimePolicyMode) {
+ case TimePolicyModes::StopAtEnd:
+ if (m_LocalTime > m_LoopingDuration) {
+ retval = 1;
+ m_LocalTime = m_LoopingDuration;
+ }
+ break;
+ case TimePolicyModes::Looping:
+ m_LocalTime = m_LocalTime % m_LoopingDuration;
+ break;
+ case TimePolicyModes::Ping:
+ if (m_LocalTime > maxUsefulDuration) {
+ retval = 1;
+ m_LocalTime = maxUsefulDuration;
+ }
+ break;
+ case TimePolicyModes::PingPong:
+ m_LocalTime = m_LocalTime % maxUsefulDuration;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return retval;
+}
+//==============================================================================
+/**
+ * Compute the local time based off the current global time and the settings
+ * such as duration, repetitions and ping-pong.
+ * @param inTime global time being fed
+ * @return BOOL true if policy has reached it's end time
+ */
+BOOL CTimePolicy::ComputeTime(const TTimeUnit inTime)
+{
+ // Return the last computed time if paused
+ if (m_Paused || m_OffsetInvalid) {
+ // m_LocalTime = inTime + m_Offset;
+ if (fabs(m_Rate) > .001)
+ m_Offset = (TTimeUnit)(m_LocalTime / fabs(m_Rate)) - inTime;
+ else // rate is zero, this should not happen.
+ m_Offset = (TTimeUnit)(m_LocalTime)-inTime;
+ m_OffsetInvalid = 0;
+ return false;
+ }
+ return UpdateTime(inTime);
+}
+
+eastl::pair<BOOL, TTimeUnit>
+SComponentTimePolicyOverride::ComputeLocalTime(CTimePolicy &inTimePolicy, TTimeUnit inGlobalTime)
+{
+ TTimeUnit retval = 0;
+ BOOL finished = FALSE;
+ if (inTimePolicy.m_Paused || inTimePolicy.m_OffsetInvalid) {
+ finished = inTimePolicy.ComputeTime(inGlobalTime);
+ } else {
+ Q3DStudio_ASSERT(m_EndTime <= inTimePolicy.GetLoopingDuration());
+ unsigned long newLocalTime = (unsigned long)(inGlobalTime + inTimePolicy.m_Offset);
+
+ float diff = static_cast<float>(newLocalTime - inTimePolicy.GetTime());
+ diff *= m_TimeMultiplier;
+ float updatedLocalTime = static_cast<float>(inTimePolicy.m_LocalTime) + diff;
+
+ if (updatedLocalTime < 0.0f)
+ updatedLocalTime = 0.0f;
+
+ inTimePolicy.m_LocalTime = static_cast<unsigned long>(updatedLocalTime);
+
+ bool runningBackwards = m_TimeMultiplier < 0;
+
+ if (runningBackwards) {
+ if (inTimePolicy.m_LocalTime <= m_EndTime) {
+ finished = TRUE;
+ inTimePolicy.m_LocalTime = (unsigned long)m_EndTime;
+ }
+ } else // running forwards
+ {
+ if (inTimePolicy.m_LocalTime >= m_EndTime) {
+ finished = TRUE;
+ inTimePolicy.m_LocalTime = (unsigned long)m_EndTime;
+ }
+ }
+ inTimePolicy.m_Offset = inTimePolicy.m_LocalTime - inGlobalTime;
+ }
+ retval = inTimePolicy.GetTime();
+ return eastl::make_pair(finished, retval);
+}
+
+void SComponentTimePolicyOverride::SetTime(CTimePolicy &inTimePolicy, TTimeUnit inLocalTime)
+{
+ if (inLocalTime < 0)
+ inLocalTime = 0;
+ if (m_TimeMultiplier < 0) {
+ if (inLocalTime <= m_EndTime) {
+ inLocalTime = m_EndTime;
+ }
+ } else // running forwards
+ {
+ if (inLocalTime >= m_EndTime) {
+ inLocalTime = m_EndTime;
+ }
+ }
+ inTimePolicy.SetTime(inLocalTime);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/Runtime/Source/q3dsqmlscript.cpp b/src/Runtime/Source/Runtime/Source/q3dsqmlscript.cpp
new file mode 100644
index 00000000..8e754b31
--- /dev/null
+++ b/src/Runtime/Source/Runtime/Source/q3dsqmlscript.cpp
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlscript.h"
+
+#include "UICQmlEngine.h"
+#include "UICElementSystem.h"
+#include "UICApplication.h"
+#include "UICPresentation.h"
+#include "UICInputEngine.h"
+#include "UICInputFrame.h"
+#include "UICQmlElementHelper.h"
+#include "UICHash.h"
+
+using namespace Q3DStudio;
+
+QJSValue argToQJSValue(qt3ds::foundation::IStringTable &strTable,
+ Q3DStudio::UINT8 type, const UVariant &value) {
+ switch (type) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ return QJSValue(value.m_INT32);
+ case ATTRIBUTETYPE_FLOAT:
+ return QJSValue(value.m_FLOAT);
+ case ATTRIBUTETYPE_BOOL:
+ return QJSValue(value.m_INT32 != 0);
+ case ATTRIBUTETYPE_STRING:
+ return QJSValue(strTable.HandleToStr(value.m_StringHandle));
+ case ATTRIBUTETYPE_NONE:
+ return QJSValue();
+ default:
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Pushed event argument value of unknown type: "<< type;
+ }
+ return QJSValue();
+}
+
+void eventCallback(void *contextData, SEventCommand &event)
+{
+ auto data = static_cast<Q3DSQmlScript::EventData *>(contextData);
+ qt3ds::foundation::IStringTable &strTable(
+ event.m_Target->GetBelongedPresentation()->GetStringTable());
+ QJSValue arg1 = argToQJSValue(strTable, event.m_Arg1Type, event.m_Arg1);
+ QJSValue arg2 = argToQJSValue(strTable, event.m_Arg2Type, event.m_Arg2);
+ data->function.call({arg1, arg2});
+}
+
+Q3DSQmlScript::Q3DSQmlScript(CQmlEngine &api, QObject &object,
+ TElement &behavior, TElement &owner)
+ : QObject(nullptr)
+ , m_api(api)
+ , m_object(object)
+ , m_behavior(behavior)
+ , m_owner(owner)
+ , m_initialized(false)
+ , m_lastActivationState(false)
+ , m_deltaTime(0.0f)
+ , m_lastTime(0)
+{
+ updateProperties();
+}
+
+Q3DSQmlScript::~Q3DSQmlScript()
+{
+ for (const EventCallbackInfo &callback : m_eventCallbacks)
+ delete callback.data;
+}
+
+void Q3DSQmlScript::update()
+{
+ updateProperties();
+
+ bool active = m_behavior.GetActive();
+
+ if (active && !m_initialized) {
+ m_initialized = true;
+ call("onInitialize");
+ }
+
+ TTimeUnit time = static_cast<CPresentation *>(m_behavior.GetBelongedPresentation())->GetTime();
+ m_deltaTime = (time - m_lastTime) / 1000.0f;
+ m_lastTime = time;
+
+ if (m_lastActivationState != active) {
+ if (active)
+ call("onActivate");
+ else
+ call("onDeactivate");
+ }
+ m_lastActivationState = active;
+ if (active)
+ call("onUpdate");
+}
+
+void Q3DSQmlScript::call(const QString &function)
+{
+ const QMetaObject *meta = m_object.metaObject();
+ const QString normalized = function + "()";
+ if (meta->indexOfMethod(normalized.toUtf8().constData()) != -1)
+ QMetaObject::invokeMethod(&m_object, function.toUtf8().constData());
+}
+
+void Q3DSQmlScript::updateProperties()
+{
+ using namespace qt3ds::foundation;
+ using namespace uic::runtime::element;
+
+ if (!m_behavior.GetActive())
+ return;
+
+ unsigned int numProperties = m_behavior.GetNumProperties();
+ for (unsigned int i = 0; i < numProperties; ++i) {
+ Option<TPropertyDescAndValuePtr> property = m_behavior.GetPropertyByIndex(i);
+ if (!property.hasValue())
+ break;
+
+ TPropertyDescAndValuePtr value = property.getValue();
+ const char *name = value.first.m_Name.c_str();
+
+ UVariant *valuePtr = value.second;
+ switch (value.first.m_Type) {
+ case ATTRIBUTETYPE_INT32:
+ case ATTRIBUTETYPE_HASH:
+ m_object.setProperty(name, valuePtr->m_INT32);
+ break;
+ case ATTRIBUTETYPE_FLOAT:
+ m_object.setProperty(name, valuePtr->m_FLOAT);
+ break;
+ case ATTRIBUTETYPE_BOOL:
+ m_object.setProperty(name, valuePtr->m_INT32 != 0);
+ break;
+ case ATTRIBUTETYPE_STRING:
+ m_object.setProperty(
+ name,
+ m_behavior.GetBelongedPresentation()->GetStringTable()
+ .HandleToStr(valuePtr->m_StringHandle)
+ .c_str());
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ }
+}
+
+bool Q3DSQmlScript::hasBehavior(const TElement *behavior)
+{
+ return &m_behavior == behavior;
+}
+
+float Q3DSQmlScript::getDeltaTime()
+{
+ return m_deltaTime;
+}
+
+float Q3DSQmlScript::getAttribute(const QString &attribute)
+{
+ if (!m_behavior.GetActive())
+ return 0;
+
+ float floatValue = 0;
+ m_api.GetAttribute(m_owner.m_Path,
+ attribute.toUtf8().constData(),
+ (char *)&floatValue);
+ return floatValue;
+}
+
+void Q3DSQmlScript::setAttribute(const QString &attribute, const QVariant &value)
+{
+ setAttribute("", attribute, value);
+}
+
+void Q3DSQmlScript::setAttribute(const QString &handle, const QString &attribute,
+ const QVariant &value)
+{
+ if (!m_behavior.GetActive())
+ return;
+
+ TElement *element = &m_owner;
+ if (!handle.isEmpty())
+ element = getElementByPath(handle);
+ if (!element)
+ return;
+
+ QByteArray valueStr;
+ float valueFloat;
+
+ const char *valuePtr = nullptr;
+ switch (value.type()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::Double:
+ case QMetaType::Float:
+ valueFloat = value.toFloat();
+ valuePtr = (const char *)&valueFloat;
+ break;
+ case QVariant::String:
+ default:
+ valueStr = value.toString().toUtf8();
+ valuePtr = valueStr.constData();
+ break;
+ }
+
+ m_api.SetAttribute(element->m_Path,
+ attribute.toUtf8().constData(),
+ valuePtr);
+}
+
+void Q3DSQmlScript::fireEvent(const QString &event)
+{
+ if (!m_behavior.GetActive())
+ return;
+ m_api.FireEvent(m_behavior.m_Path, event.toUtf8().constData());
+}
+
+void Q3DSQmlScript::registerForEvent(const QString &event, const QJSValue &function)
+{
+ registerForEvent("", event, function);
+}
+
+void Q3DSQmlScript::registerForEvent(const QString &handle, const QString &event,
+ const QJSValue &function)
+{
+ if (!m_behavior.GetActive())
+ return;
+
+ TElement *element = &m_owner;
+ if (!handle.isEmpty())
+ element = getElementByPath(handle);
+ if (!element)
+ return;
+
+ if (!function.isCallable())
+ return;
+
+ CPresentation *presentation
+ = static_cast<CPresentation *>(m_behavior.GetBelongedPresentation());
+ TEventCommandHash eventHash = CHash::HashEventCommand(event.toUtf8().constData());
+
+ for (auto &&callback : m_eventCallbacks) {
+ if (callback.element == element && callback.eventHash == eventHash)
+ return;
+ }
+
+ EventData *data = new EventData();
+ data->function = function;
+
+ m_eventCallbacks.push_back({element, eventHash, data});
+
+ presentation->RegisterEventCallback(element, eventHash, &eventCallback, data);
+}
+
+void Q3DSQmlScript::unregisterForEvent(const QString &event)
+{
+ unregisterForEvent("", event);
+}
+
+void Q3DSQmlScript::unregisterForEvent(const QString &handle, const QString &event)
+{
+ if (!m_behavior.GetActive())
+ return;
+
+ TElement *element = &m_owner;
+ if (!handle.isEmpty())
+ element = getElementByPath(handle);
+ if (!element)
+ return;
+
+ CPresentation *presentation
+ = static_cast<CPresentation *>(m_behavior.GetBelongedPresentation());
+ TEventCommandHash eventHash = CHash::HashEventCommand(event.toUtf8().constData());
+ EventData *data = nullptr;
+
+ for (int i = 0; i < m_eventCallbacks.size(); ++i) {
+ if (m_eventCallbacks[i].element == element && m_eventCallbacks[i].eventHash == eventHash) {
+ data = m_eventCallbacks[i].data;
+ m_eventCallbacks.erase(m_eventCallbacks.begin() + i);
+ break;
+ }
+ }
+
+ if (data) {
+ presentation->UnregisterEventCallback(element, eventHash, &eventCallback, data);
+ delete data;
+ }
+}
+
+QVector2D Q3DSQmlScript::getMousePosition()
+{
+ CPresentation *presentation
+ = static_cast<CPresentation *>(m_behavior.GetBelongedPresentation());
+ uic::runtime::IApplication &app = presentation->GetApplication();
+
+ SInputFrame input = app.GetInputEngine().GetInputFrame();
+ if (app.GetPrimaryPresentation()) {
+ Q3DStudio::SMousePosition position =
+ app.GetPrimaryPresentation()->GetScene()->WindowToPresentation(
+ Q3DStudio::SMousePosition(static_cast<INT32>(input.m_PickX),
+ static_cast<INT32>(input.m_PickY)));
+
+ return QVector2D(position.m_X, position.m_Y);
+ }
+ return QVector2D(0, 0);
+}
+
+QMatrix4x4 Q3DSQmlScript::calculateGlobalTransform(const QString &handle)
+{
+ TElement *element = &m_owner;
+ if (!handle.isEmpty())
+ element = getElementByPath(handle);
+ if (!element)
+ return QMatrix4x4();
+
+ RuntimeMatrix transform;
+ IScene *scene = element->GetBelongedPresentation()->GetScene();
+ scene->CalculateGlobalTransform(element, transform);
+ transform.FlipCoordinateSystem();
+
+ return QMatrix4x4(&transform.m_Data[0][0]);
+}
+
+QVector3D Q3DSQmlScript::lookAt(const QVector3D& target)
+{
+ RuntimeVector3 rotation;
+
+ FLOAT theMag = ::sqrtf(target.x() * target.x() + target.z() * target.z());
+ FLOAT thePitch = -::atan2f(target.y(), theMag);
+ FLOAT theYaw = ::atan2f(target.x(), target.z());
+
+ rotation.Set(thePitch, theYaw, 0.0f);
+
+ return QVector3D(rotation.m_X, rotation.m_Y, rotation.m_Z);
+}
+
+QString Q3DSQmlScript::getParent(const QString& handle)
+{
+ TElement *element = &m_owner;
+ if (!handle.isEmpty())
+ element = getElementByPath(handle);
+ if (!element)
+ return "";
+
+ TElement *parent = element->GetParent();
+ if (!parent)
+ return "";
+ return parent->m_Path.c_str();
+}
+
+TElement *Q3DSQmlScript::getElementByPath(const QString &path)
+{
+ if (!m_api.GetApplication())
+ return nullptr;
+
+ TElement *element = CQmlElementHelper::GetElement(
+ *m_api.GetApplication(),
+ m_api.GetApplication()->GetPrimaryPresentation(),
+ path.toUtf8().constData(), NULL);
+ return element;
+}
diff --git a/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerCustomMaterialParser.h b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerCustomMaterialParser.h
new file mode 100644
index 00000000..33d2390c
--- /dev/null
+++ b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerCustomMaterialParser.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef DOCUMENTRESOURCEMANAGERCUSTOMMATERIALPARSERH
+#define DOCUMENTRESOURCEMANAGERCUSTOMMATERIALPARSERH
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "UICDMXML.h"
+#include "UICDMDataTypes.h"
+#include "UICDMMetaData.h"
+#include "UICDMWStrOpsImpl.h"
+#include "foundation/StrConvertUTF.h"
+#include <EASTL/string.h>
+#include "UICRenderInputStreamFactory.h"
+
+namespace Q3DStudio {
+struct CCustomMaterialParser
+{
+
+ static bool NavigateToMetadata(std::shared_ptr<UICDM::IDOMReader> inReader)
+ {
+ return inReader->MoveToFirstChild("MetaData");
+ }
+
+ static std::shared_ptr<UICDM::IDOMReader>
+ ParseFile(std::shared_ptr<UICDM::IDOMFactory> inFactory,
+ std::shared_ptr<UICDM::IStringTable> inStringTable, const char8_t *inFileData,
+ UICDM::CXmlErrorHandler &inErrorHandler,
+ uic::render::IInputStreamFactory &inStreamFactory)
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream(
+ inStreamFactory.GetStreamForFile(inFileData));
+ if (!theStream) {
+ QT3DS_ASSERT(0);
+ return std::shared_ptr<UICDM::IDOMReader>();
+ }
+
+ UICDM::SDOMElement *theElem(
+ UICDM::CDOMSerializer::Read(*inFactory, *theStream, &inErrorHandler));
+
+ if (theElem == NULL) {
+ return std::shared_ptr<UICDM::IDOMReader>();
+ } else
+ return UICDM::IDOMReader::CreateDOMReader(*theElem, inStringTable, inFactory);
+ }
+};
+}
+
+#endif
diff --git a/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerLuaParser.h b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerLuaParser.h
new file mode 100644
index 00000000..9d798337
--- /dev/null
+++ b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerLuaParser.h
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef DOCUMENTRESOURCEMANAGERLUAPARSERH
+#define DOCUMENTRESOURCEMANAGERLUAPARSERH
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "UICDMXML.h"
+#include "UICDMDataTypes.h"
+#include "UICDMMetaData.h"
+#include "UICDMWStrOpsImpl.h"
+#include "foundation/StrConvertUTF.h"
+#include <EASTL/string.h>
+#include "UICRenderInputStreamFactory.h"
+
+namespace Q3DStudio {
+namespace LuaParser {
+
+ using namespace UICDM;
+ using namespace std;
+ using namespace Q3DStudio;
+
+ struct SLuaParserContext
+ {
+ const char8_t *m_Data;
+ const char8_t *m_End;
+ QT3DSU32 m_CurrentLineNumber;
+ bool m_FoundBlock;
+ SLuaParserContext(const char8_t *inData, const char8_t *inEnd)
+ : m_Data(inData)
+ , m_End(inEnd)
+ , m_CurrentLineNumber(1)
+ , m_FoundBlock(false)
+ {
+ QT3DS_ASSERT(inData <= inEnd);
+ }
+
+ bool HasMoreInput() const { return m_Data < m_End; }
+
+ wchar_t NextChar()
+ {
+ wchar_t retval = 0;
+ if (HasMoreInput()) {
+ do {
+ retval = *m_Data;
+ ++m_Data;
+ } while (retval == '\r' && HasMoreInput());
+ }
+ if (retval == '\n')
+ ++m_CurrentLineNumber;
+ return retval;
+ }
+
+ void ParseBlockComment(eastl::string &outLines)
+ {
+ const char8_t *firstLineBegin = m_Data;
+ m_FoundBlock = true;
+ do {
+ wchar_t nextChar = NextChar();
+ if (nextChar == ']') {
+ nextChar = NextChar();
+ if (nextChar == ']') {
+ outLines.append(firstLineBegin, 0, uint32_t(m_Data - firstLineBegin - 2));
+ return;
+ }
+ }
+ } while (HasMoreInput());
+ }
+
+ void ParseComment(eastl::string &outLines)
+ {
+ wchar_t nextChar = NextChar();
+ if (nextChar == '[') {
+ nextChar = NextChar();
+ if (nextChar == '[')
+ ParseBlockComment(outLines);
+ }
+ // empty loop intentional
+ for (; nextChar != 0 && nextChar != '\n'; nextChar = NextChar())
+ ;
+ }
+
+ // Pre parse to strip the input we care about from the rest of the file.
+ static void ParseLuaInput(eastl::string &inLuaFile, eastl::string &outLines)
+ {
+ const char8_t *theEnd = inLuaFile.c_str() + inLuaFile.size();
+ SLuaParserContext context(inLuaFile.c_str(), theEnd);
+ int dashCount = 0;
+ // Note that in the specification we state that only the first lua block
+ // comment will be parsed for the behavior information
+ while (context.HasMoreInput() && context.m_FoundBlock == false) {
+ wchar_t nextValue = context.NextChar();
+ if (nextValue == '-') {
+ ++dashCount;
+ if (dashCount == 2) {
+ context.ParseComment(outLines);
+ dashCount = 0;
+ }
+ }
+ }
+ }
+ };
+
+ struct StringInStream : qt3ds::foundation::IInStream
+ {
+ const eastl::string &m_String;
+ QT3DSU32 m_Offset;
+
+ StringInStream(const eastl::string &str)
+ : m_String(str)
+ , m_Offset(0)
+ {
+ }
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ const char *theStart((const char *)m_String.c_str());
+ const char *theEnd(theStart + m_String.size());
+
+ QT3DSU32 amountLeft = QT3DSU32(theEnd - theStart) - m_Offset;
+ QT3DSU32 amountToRead = qt3ds::NVMin(data.size(), amountLeft);
+ qt3ds::intrinsics::memCopy(data.begin(), theStart + m_Offset, amountToRead);
+ m_Offset += amountToRead;
+ return amountToRead;
+ }
+ };
+
+ struct SLuaParser
+ {
+ static std::shared_ptr<IDOMReader>
+ ParseLuaData(std::shared_ptr<IDOMFactory> inFactory,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ eastl::string &inFileData, CXmlErrorHandler &inErrorHandler)
+ {
+ eastl::string theOpenTag("<Behavior>\n");
+ SLuaParserContext::ParseLuaInput(inFileData, theOpenTag);
+ // Ensure we strip the last "--" in case there is any
+ uint32_t theSize = theOpenTag.size();
+ uint32_t theddPos = theOpenTag.rfind("--");
+ if (theddPos == theSize - 2)
+ theOpenTag.erase(theddPos);
+ theOpenTag.append("</Behavior>\n");
+
+ // Replace /r/n with /n because the xml parse will interpret /r/n as two lines thus
+ // leading to incorrect line numbers.
+ for (uint32_t thePos = theOpenTag.find("\r\n"); thePos != eastl::string::npos;
+ thePos = theOpenTag.find("\r\n", thePos))
+ theOpenTag = theOpenTag.replace(thePos, 1, "\n");
+
+ StringInStream theStream(theOpenTag);
+
+ SDOMElement *theElem(CDOMSerializer::Read(*inFactory, theStream, &inErrorHandler));
+ if (theElem == NULL) {
+ return std::shared_ptr<IDOMReader>();
+ } else
+ return IDOMReader::CreateDOMReader(*theElem, inStringTable, inFactory);
+ }
+
+ static wchar_t NarrowToWide(QT3DSU8 inData) { return inData; }
+
+ static std::shared_ptr<IDOMReader>
+ ParseLuaFile(std::shared_ptr<IDOMFactory> inFactory,
+ std::shared_ptr<UICDM::IStringTable> inStringTable,
+ const char8_t *inFileData, CXmlErrorHandler &inErrorHandler,
+ uic::render::IInputStreamFactory &inStreamFactory)
+ {
+ eastl::vector<QT3DSU8> readBuf;
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ eastl::string strConvert;
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream(
+ inStreamFactory.GetStreamForFile(inFileData));
+ if (!theStream) {
+ QT3DS_ASSERT(0);
+ return std::shared_ptr<IDOMReader>();
+ }
+
+ QT3DSU32 readLen = 0;
+ do {
+ uint32_t offset = readBuf.size();
+ readBuf.resize(offset + 4096);
+ readLen = theStream->Read(NVDataRef<QT3DSU8>(&readBuf[0] + offset, 4096));
+ readBuf.resize(offset + readLen);
+ } while (readLen == 4096);
+ }
+ if (readBuf.size() < 2) {
+ QT3DS_ASSERT(false);
+ return std::shared_ptr<IDOMReader>();
+ }
+ eastl::string convertBuf;
+
+ //...sigh..text files.
+ // Everything gets converted to UTF-8
+ // little endian, big endian UTF-16
+ // or ASCII assumed
+ QT3DSU32 dataSize = 0;
+ QT3DSU16 endianIndicator;
+ memcpy(&endianIndicator, &readBuf[0], 2);
+ // Detect LE UTF-16 and copy directly into convert buf
+ if (endianIndicator == (QT3DSU16)0xFEFF) {
+ const char16_t *dataPtr = (const char16_t *)&readBuf[2];
+ dataSize = ((QT3DSU32)readBuf.size() / sizeof(unsigned short)) - 1;
+ qt3ds::foundation::ConvertUTF(dataPtr, dataSize, convertBuf);
+ } else if (endianIndicator == (QT3DSU16)0xFFFE || readBuf[0] == 0) {
+ QT3DS_ASSERT(false);
+ } else {
+ convertBuf.resize(readBuf.size());
+ const char8_t *inPtr = (const char8_t *)readBuf.data();
+ const char8_t *endPtr = inPtr + readBuf.size();
+ convertBuf.assign(inPtr, endPtr);
+ }
+
+ return ParseLuaData(inFactory, inStringTable, convertBuf, inErrorHandler);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerRenderPluginParser.h b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerRenderPluginParser.h
new file mode 100644
index 00000000..ddac71d0
--- /dev/null
+++ b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerRenderPluginParser.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef DOCUMENTRESOURCEMANAGERRENDERPLUGINPARSERH
+#define DOCUMENTRESOURCEMANAGERRENDERPLUGINPARSERH
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "UICDMXML.h"
+#include "UICDMDataTypes.h"
+#include "UICDMMetaData.h"
+#include "UICDMWStrOpsImpl.h"
+#include "foundation/StrConvertUTF.h"
+#include <EASTL/string.h>
+#include "UICRenderInputStreamFactory.h"
+
+namespace Q3DStudio {
+struct CRenderPluginParser
+{
+
+ static bool NavigateToMetadata(std::shared_ptr<UICDM::IDOMReader> inReader)
+ {
+ return inReader->MoveToFirstChild("metadata");
+ }
+
+ static std::shared_ptr<UICDM::IDOMReader>
+ ParseFile(std::shared_ptr<UICDM::IDOMFactory> inFactory,
+ std::shared_ptr<UICDM::IStringTable> inStringTable, const char8_t *inFileData,
+ UICDM::CXmlErrorHandler &inErrorHandler,
+ uic::render::IInputStreamFactory &inStreamFactory)
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> theStream(
+ inStreamFactory.GetStreamForFile(inFileData));
+ if (!theStream) {
+ QT3DS_ASSERT(0);
+ return std::shared_ptr<UICDM::IDOMReader>();
+ }
+
+ UICDM::SDOMElement *theElem(
+ UICDM::CDOMSerializer::Read(*inFactory, *theStream, &inErrorHandler));
+
+ if (theElem == NULL) {
+ return std::shared_ptr<UICDM::IDOMReader>();
+ } else
+ return UICDM::IDOMReader::CreateDOMReader(*theElem, inStringTable, inFactory);
+ }
+};
+}
+
+#endif
diff --git a/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerScriptParser.h b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerScriptParser.h
new file mode 100644
index 00000000..235a168b
--- /dev/null
+++ b/src/Runtime/Source/RuntimeUICDM/Include/DocumentResourceManagerScriptParser.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DOCUMENTRESOURCEMANAGERSCRIPTPARSER_H
+#define DOCUMENTRESOURCEMANAGERSCRIPTPARSER_H
+
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "UICDMXML.h"
+#include "UICDMDataTypes.h"
+#include "UICDMMetaData.h"
+#include "UICRenderInputStreamFactory.h"
+
+namespace Q3DStudio {
+namespace ScriptParser {
+
+ using namespace UICDM;
+ using namespace Q3DStudio;
+
+ struct StringInStream : qt3ds::foundation::IInStream
+ {
+ const QString &m_String;
+ QT3DSU32 m_Offset;
+
+ StringInStream(const QString &str)
+ : m_String(str)
+ , m_Offset(0)
+ {
+ }
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ std::string str = m_String.toUtf8().constData();
+ const char *theStart((const char *)str.c_str());
+ const char *theEnd(theStart + str.size());
+
+ QT3DSU32 amountLeft = QT3DSU32(theEnd - theStart) - m_Offset;
+ QT3DSU32 amountToRead = qt3ds::NVMin(data.size(), amountLeft);
+ qt3ds::intrinsics::memCopy(data.begin(), theStart + m_Offset, amountToRead);
+ m_Offset += amountToRead;
+ return amountToRead;
+ }
+ };
+
+ struct SScriptParser
+ {
+ static std::shared_ptr<IDOMReader>
+ ParseScriptFile(std::shared_ptr<IDOMFactory> factory,
+ std::shared_ptr<UICDM::IStringTable> stringTable,
+ const QString &fullPath, CXmlErrorHandler &errorHandler,
+ uic::render::IInputStreamFactory &streamFactory)
+ {
+ QVector<QT3DSU8> readBuf;
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ eastl::string strConvert;
+ NVScopedRefCounted<uic::render::IRefCountedInputStream> stream(
+ streamFactory.GetStreamForFile(fullPath));
+ if (!stream) {
+ QT3DS_ASSERT(0);
+ return std::shared_ptr<IDOMReader>();
+ }
+
+ QT3DSU32 readLen = 0;
+ do {
+ uint32_t offset = readBuf.size();
+ readBuf.resize(offset + 4096);
+ readLen = stream->Read(NVDataRef<QT3DSU8>(&readBuf[0] + offset, 4096));
+ readBuf.resize(offset + readLen);
+ } while (readLen == 4096);
+ }
+
+ QByteArray byteArray;
+ for (auto &&c : qAsConst(readBuf))
+ byteArray.append(c);
+
+ QString code = QString::fromUtf8(byteArray);
+
+ bool skipXml = false;
+ auto start = code.indexOf("/*[[");
+ if (start == -1)
+ skipXml = true;
+
+ QString tagged("<Behavior>\n");
+ if (!skipXml) {
+ start += 4;
+ auto end = code.indexOf("]]*/", start);
+ if (end == -1)
+ return std::shared_ptr<IDOMReader>();
+
+ QString xml = code.mid(start, end - start).trimmed();
+
+ tagged.append(xml);
+ }
+ tagged.append("</Behavior>\n");
+ tagged.replace("\r\n", "\n");
+
+ StringInStream xmlStream(tagged);
+
+ SDOMElement *element(CDOMSerializer::Read(*factory, xmlStream, &errorHandler));
+ if (element == NULL)
+ return std::shared_ptr<IDOMReader>();
+
+ return IDOMReader::CreateDOMReader(*element, stringTable, factory);
+ }
+ };
+}
+}
+
+#endif // DOCUMENTRESOURCEMANAGERSCRIPTPARSER_H
diff --git a/src/Runtime/Source/RuntimeUICDM/Include/UICMetadata.h b/src/Runtime/Source/RuntimeUICDM/Include/UICMetadata.h
new file mode 100644
index 00000000..f808642f
--- /dev/null
+++ b/src/Runtime/Source/RuntimeUICDM/Include/UICMetadata.h
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSVec3.h"
+#include <EASTL/string.h>
+#include <EASTL/vector.h>
+#include "foundation/StringTable.h"
+#include <memory>
+
+namespace qt3ds {
+namespace foundation {
+}
+}
+
+namespace UICDM {
+class IStringTable;
+struct SMetaDataEffect;
+struct SMetaDataCustomMaterial;
+}
+
+namespace uic {
+namespace render {
+ class IInputStreamFactory;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+using namespace qt3ds::foundation;
+
+//==============================================================================
+// Redifinition of UICDM::DataModelDataType::Value
+//==============================================================================
+enum ERuntimeDataModelDataType {
+ ERuntimeDataModelDataTypeNone,
+ ERuntimeDataModelDataTypeFloat,
+ ERuntimeDataModelDataTypeFloat2,
+ ERuntimeDataModelDataTypeFloat3,
+ ERuntimeDataModelDataTypeLong,
+ ERuntimeDataModelDataTypeString,
+ ERuntimeDataModelDataTypeBool,
+ ERuntimeDataModelDataTypeLong4,
+ ERuntimeDataModelDataTypeStringRef,
+ ERuntimeDataModelDataTypeObjectRef,
+ ERuntimeDataModelDataTypeStringOrInt,
+};
+
+//==============================================================================
+// Redifinition of UICDM::EAdditionalMetaDataType
+//==============================================================================
+enum ERuntimeAdditionalMetaDataType {
+ ERuntimeAdditionalMetaDataTypeNone,
+ ERuntimeAdditionalMetaDataTypeStringList,
+ ERuntimeAdditionalMetaDataTypeRange,
+ ERuntimeAdditionalMetaDataTypeImage,
+ ERuntimeAdditionalMetaDataTypeColor,
+ ERuntimeAdditionalMetaDataTypeRotation,
+ ERuntimeAdditionalMetaDataTypeFont,
+ ERuntimeAdditionalMetaDataTypeFontSize,
+ ERuntimeAdditionalMetaDataTypeMultiLine,
+ ERuntimeAdditionalMetaDataTypeObjectRef,
+ ERuntimeAdditionalMetaDataTypeMesh,
+ ERuntimeAdditionalMetaDataTypeImport,
+ ERuntimeAdditionalMetaDataTypeTexture,
+ ERuntimeAdditionalMetaDataTypeRenderable,
+ ERuntimeAdditionalMetaDataTypePathBuffer,
+ ERuntimeAdditionalMetaDataTypeShadowMapResolution,
+};
+
+typedef eastl::basic_string<char8_t> TRuntimeMetaDataStrType;
+typedef qt3ds::foundation::CRegisteredString TStrTableStr;
+
+struct SAttOrArg
+{
+ TRuntimeMetaDataStrType m_Name;
+ TRuntimeMetaDataStrType m_FormalName;
+ ERuntimeDataModelDataType m_DataType;
+ ERuntimeAdditionalMetaDataType m_MetaType;
+ eastl::vector<TRuntimeMetaDataStrType> m_MetaDataList;
+ eastl::pair<float, float> m_MetaDataRange;
+};
+
+typedef eastl::vector<SAttOrArg> TAttOrArgList;
+struct SHandler
+{
+ TRuntimeMetaDataStrType m_Name;
+ TRuntimeMetaDataStrType m_FormalName;
+ TAttOrArgList m_Arguments;
+};
+
+typedef eastl::vector<SHandler> THandlerList;
+
+struct SVisualEvent
+{
+ TRuntimeMetaDataStrType m_Name;
+ TRuntimeMetaDataStrType m_FormalName;
+};
+
+typedef eastl::vector<SVisualEvent> TVisualEventList;
+
+struct SElementInfo
+{
+ TRuntimeMetaDataStrType m_ClassName;
+ bool m_IsComponent;
+ TAttOrArgList m_Attributes;
+};
+
+//==============================================================================
+/**
+ * @class IRuntimeMetaData
+ * @brief Declare interfaces for querying meta data values
+ */
+class IRuntimeMetaData : public NVReleasable
+{
+
+public:
+ static const char *GetMetaDataDirectory()
+ {
+ return ":/res/DataModelMetadata/en-us/MetaData.xml";
+ }
+ //==============================================================================
+ /**
+ * Check if a property for the specified type or id exists
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value type
+ */
+ virtual bool IsPropertyExist(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value type
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value type
+ */
+ virtual ERuntimeDataModelDataType GetPropertyType(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get additional metadata type
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property meta data type
+ */
+ virtual ERuntimeAdditionalMetaDataType
+ GetAdditionalType(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value as float
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<float> GetPropertyValueFloat(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value as QT3DSVec3
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<qt3ds::QT3DSVec3> GetPropertyValueVector2(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value as QT3DSVec3
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<qt3ds::QT3DSVec3> GetPropertyValueVector3(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value as long
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<qt3ds::QT3DSI32> GetPropertyValueLong(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value as string
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<TRuntimeMetaDataStrType>
+ GetPropertyValueString(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get object ref property value as string
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<TRuntimeMetaDataStrType>
+ GetPropertyValueObjectRef(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get property value as bool
+ * @param inType default object type
+ * @param inProperty the property to query
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param return property value
+ */
+ virtual Option<bool> GetPropertyValueBool(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId = TStrTableStr()) = 0;
+
+ //==============================================================================
+ /**
+ * Get references
+ * @param inType default object type
+ * @param outReferences References of the object
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ */
+ virtual void GetReferences(const char *inType,
+ eastl::vector<TRuntimeMetaDataStrType> &outReferences,
+ const char *inId = NULL) = 0;
+
+ //==============================================================================
+ /**
+ * Check if the property is custom or built in (canonical)
+ * @param inId object id
+ * @param inProperty the property to query
+ */
+ virtual bool IsCustomProperty(const char *inId, const char *inProperty) = 0;
+
+ //==============================================================================
+ /**
+ * Check if the handle is custom or built in (canonical)
+ * @param inId object id
+ * @param inHandlerName the handler name
+ */
+ virtual bool IsCustomHandler(const char *inId, const char *inHandlerName) = 0;
+
+ virtual THandlerList GetCustomHandlers(const char *inId) = 0;
+
+ virtual TVisualEventList GetVisualEvents(const char *inId) = 0;
+
+ virtual SElementInfo LoadElement(const char *clsName, const char *clsRef, const char *inId) = 0;
+
+ virtual TAttOrArgList GetSlideAttributes() = 0;
+
+ //==============================================================================
+ /**
+ * Get the data type and additional type of the custom handler
+ * @param inId object id
+ * @param inHandlerName the handler name
+ * @param inArgumentName the handler argument name
+ * @param outType the type
+ * @param outAdditionalType the additional type
+ */
+ virtual void GetHandlerArgumentType(const char *inId, const char *inHandlerName,
+ const char *inArgumentName,
+ ERuntimeDataModelDataType &outType,
+ ERuntimeAdditionalMetaDataType &outAdditionalType) = 0;
+
+ //==============================================================================
+ /**
+ * Get properties of the object with the given id, with the option of searching the parent or
+ *only specific to this object.
+ * @param inType default object type
+ * @param inId object id. if this value is not trivial, the query is based on inId
+ *instead of inType
+ * @param outProperties the list of property names
+ * @param inSearchParent if true, get the properties defined on the object or its derivation
+ *parents
+ * else, get only the properties defined on the object, not properties
+ *derived from the parent.
+ */
+ virtual void GetInstanceProperties(const char *inType, const char *inId,
+ eastl::vector<TRuntimeMetaDataStrType> &outProperties,
+ bool inSearchParent) = 0;
+
+ //==============================================================================
+ /**
+ * Load Lua File
+ * @param inType type, for example L"Behavior"
+ * @param inId id
+ * @param inName name
+ * @param inSourcePath source path to lua file. It should be absolute path.
+ */
+ virtual bool LoadLuaFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) = 0;
+
+ virtual bool LoadScriptFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) = 0;
+
+ virtual bool LoadEffectXMLFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) = 0;
+
+ virtual bool LoadMaterialXMLFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) = 0;
+
+ virtual bool LoadPluginXMLFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) = 0;
+
+ virtual Option<UICDM::SMetaDataEffect> GetEffectMetaDataBySourcePath(const char *inName) = 0;
+
+ virtual Option<UICDM::SMetaDataCustomMaterial>
+ GetMaterialMetaDataBySourcePath(const char *inSourcePath) = 0;
+
+ virtual std::shared_ptr<UICDM::IStringTable> GetStringTable() = 0;
+
+ virtual TStrTableStr Register(const char *inStr) = 0;
+
+ // Clear data that affects project loading (mainly id->instance map)
+ virtual void ClearPerProjectData() = 0;
+
+public:
+ //==============================================================================
+ /**
+ * Creation function creates an object implements the IRuntimeMetaData interface
+ * This takes an input stream factory because on android the metadata is installed
+ * in the APK file, so we don't have exact access to it on the filesystem.
+ */
+ static IRuntimeMetaData &Create(uic::render::IInputStreamFactory &inInputStreamFactory);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/RuntimeUICDM/Source/UICMetadata.cpp b/src/Runtime/Source/RuntimeUICDM/Source/UICMetadata.cpp
new file mode 100644
index 00000000..10a4822a
--- /dev/null
+++ b/src/Runtime/Source/RuntimeUICDM/Source/UICMetadata.cpp
@@ -0,0 +1,1047 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDMPrefix.h"
+#include "UICMetadata.h"
+#include "SimpleDataCore.h"
+#include "UICDMXML.h"
+#include "foundation/IOStreams.h"
+#include "UICEulerAngles.h"
+#include "UICDMWindowsCompatibility.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "DocumentResourceManagerScriptParser.h"
+#include "DocumentResourceManagerLuaParser.h"
+#include "foundation/StrConvertUTF.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/FileTools.h"
+#include "foundation/TrackingAllocator.h"
+#include "EASTL/hash_map.h"
+#include "DocumentResourceManagerRenderPluginParser.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StringTable.h"
+
+using uic::render::IInputStreamFactory;
+using uic::render::IRefCountedInputStream;
+
+using namespace UICDM;
+using namespace Q3DStudio;
+
+namespace {
+
+
+struct SImportXmlErrorHandler : public CXmlErrorHandler
+{
+ void OnXmlError(TWideXMLCharPtr errorName, int line, int) override
+ {
+ qCCritical(INTERNAL_ERROR) << "XML error:"
+ << QString::fromWCharArray(errorName) << "on line" << line;
+ }
+};
+
+struct SRuntimeMetaDataPropertyInfo
+{
+ ERuntimeDataModelDataType m_DataType;
+ ERuntimeAdditionalMetaDataType m_AdditionalType;
+ Option<SValue> m_Value;
+ bool m_Exist;
+ SRuntimeMetaDataPropertyInfo(ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType,
+ const Option<SValue> &inValue, bool inExist)
+ : m_DataType(inDataType)
+ , m_AdditionalType(inAdditionalType)
+ , m_Value(inValue)
+ , m_Exist(inExist)
+ {
+ }
+ SRuntimeMetaDataPropertyInfo()
+ : m_DataType(ERuntimeDataModelDataTypeNone)
+ , m_AdditionalType(ERuntimeAdditionalMetaDataTypeNone)
+ , m_Exist(false)
+ {
+ }
+};
+
+struct SPropertyKey
+{
+ const char8_t *m_TypeOrId;
+ const char8_t *m_PropertyName;
+
+ // The character pointers are expected to have come from the string table
+ // thus we can safely use their exact pointer addresses for the hash code.
+ SPropertyKey(const char8_t *typeOrId, const char8_t *inPname)
+ : m_TypeOrId(typeOrId)
+ , m_PropertyName(inPname)
+ {
+ }
+ bool operator==(const SPropertyKey &inOther) const
+ {
+ // equality comparison safe since strings are assumed to come from string table.
+ return m_TypeOrId == inOther.m_TypeOrId && m_PropertyName == inOther.m_PropertyName;
+ }
+};
+}
+
+namespace eastl {
+template <>
+struct hash<SPropertyKey>
+{
+ size_t operator()(const SPropertyKey &inKey) const
+ {
+ return reinterpret_cast<size_t>(inKey.m_TypeOrId)
+ ^ reinterpret_cast<size_t>(inKey.m_PropertyName);
+ }
+};
+}
+
+namespace {
+
+//===========================================================================
+/**
+ * @class SRuntimeMetaDataImpl
+ * @brief implements the IRumtimeMetaData interface class
+ */
+struct SRuntimeMetaDataImpl : public IRuntimeMetaData
+{
+
+private:
+ typedef std::map<TCharStr, int> TIdToHandleMap;
+ typedef eastl::hash_map<SPropertyKey, SRuntimeMetaDataPropertyInfo> TPropertyLookupHash;
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+ std::shared_ptr<UICDM::IStringTable> m_StrTable;
+ std::shared_ptr<IDataCore> m_DataCore;
+ std::shared_ptr<IMetaData> m_NewMetaData;
+ std::shared_ptr<SComposerObjectDefinitions> m_Objects;
+ std::vector<TCharStr> m_TempReferences;
+
+ TIdToHandleMap m_IdToHandleMap;
+ // We cache properties by id or by instance so that the same query for the same value
+ // will return an answer instantly instead of calling GetAggregateInstancePropertyByName which
+ // is really
+ // expensive.
+ TPropertyLookupHash m_PropertyLookupHash;
+ IInputStreamFactory &m_InputStreamFactory;
+
+ // Helper to convert char to wchar_t
+ eastl::basic_string<qt3ds::foundation::TWCharEASTLConverter::TCharType> m_Buf[4];
+
+public:
+ static void SimpleUICDMLogger(const char *inMessage)
+ {
+ qCInfo(TRACE_INFO) << SRuntimeMetaDataImpl::SimpleUICDMLogger
+ << inMessage;
+ }
+ //==============================================================================
+ /**
+ * Constructor
+ */
+ SRuntimeMetaDataImpl(IInputStreamFactory &inFactory)
+ : m_InputStreamFactory(inFactory)
+ {
+ // Use this to enable some simple uicdm debug logging. Beware of a *lot* of log output.
+ // g_UICDMDebugLogger = SimpleUICDMLogger;
+ try {
+ // need to pause here to hook up the debugger
+ m_StrTable = UICDM::IStringTable::CreateStringTable();
+ m_DataCore = std::make_shared<CSimpleDataCore>(m_StrTable);
+ m_NewMetaData = IMetaData::CreateNewMetaData(m_DataCore);
+
+ m_Objects = std::make_shared<SComposerObjectDefinitions>(std::ref(*m_DataCore),
+ std::ref(*m_NewMetaData));
+ } catch (UICDM::UICDMError &error) {
+ qCCritical(INTERNAL_ERROR) << "SRuntimeMetaDataImpl UICDMError: "
+ << m_StrTable->GetNarrowStr(error.m_Message);
+ } catch (std::runtime_error &exc) {
+ if (exc.what()) {
+ qCCritical(INTERNAL_ERROR) << "SRuntimeMetaDataImpl std::runtime_error: "
+ << exc.what();
+ } else {
+ qCCritical(INTERNAL_ERROR) << "SRuntimeMetaDataImpl std::runtime_error";
+ }
+ } catch (std::exception &exc) {
+ if (exc.what()) {
+ qCCritical(INTERNAL_ERROR) << "SRuntimeMetaDataImpl std::exception: "
+ << exc.what();
+ } else {
+ qCCritical(INTERNAL_ERROR) << "SRuntimeMetaDataImpl std::exception";
+ }
+ }
+ }
+
+ void Load()
+ {
+ // Create the base types.
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(m_StrTable));
+ const char8_t *theMetaDataPath = GetMetaDataDirectory();
+ NVScopedRefCounted<IRefCountedInputStream> theInStream(
+ m_InputStreamFactory.GetStreamForFile(theMetaDataPath));
+ SDOMElement *topElement = NULL;
+ if (theInStream)
+ topElement = CDOMSerializer::Read(*theFactory, *theInStream);
+ if (topElement) {
+ shared_ptr<IDOMReader> theReader =
+ IDOMReader::CreateDOMReader(*topElement, m_StrTable, theFactory);
+ m_NewMetaData->Load(*theReader);
+
+ } else {
+ qCCritical(INVALID_OPERATION) << "Metadata loading failed", "Failed to find meta data file";
+ // Q3DStudio_ASSERT requires static linkage to UICSystem, which is only used
+ // by UICEngine and UICRuntime
+ // QT3DS_ASSERT requires the qt3ds foundation libraries which are used by all products.
+ QT3DS_ASSERT(false);
+ return;
+ }
+ }
+
+ // Helper to convert wchar_t to eastl::string
+ static inline void ConvertWide(const wchar_t *inType, eastl::string &outStr)
+ {
+ if (inType && *inType)
+ qt3ds::foundation::ConvertUTF(
+ reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(inType),
+ 0, outStr);
+ else
+ outStr.clear();
+ }
+
+ // Helper to convert char to wchar_t
+ const wchar_t *ConvertChar(const char *inName, int inBufferIndex)
+ {
+ if (inName && *inName) {
+ qt3ds::foundation::ConvertUTF(inName, 0, m_Buf[inBufferIndex]);
+ return reinterpret_cast<const wchar_t *>(m_Buf[inBufferIndex].c_str());
+ }
+ return NULL;
+ }
+ inline const wchar_t *Convert0(const char *inName) { return ConvertChar(inName, 0); }
+ inline const wchar_t *Convert1(const char *inName) { return ConvertChar(inName, 1); }
+ inline const wchar_t *Convert2(const char *inName) { return ConvertChar(inName, 2); }
+ inline const wchar_t *Convert3(const char *inName) { return ConvertChar(inName, 3); }
+
+ inline CUICDMInstanceHandle GetInstanceForType(const wchar_t *inType)
+ {
+ return m_Objects->GetInstanceForType(ComposerObjectTypes::Convert(inType));
+ }
+
+ CUICDMInstanceHandle GetInstanceById(const wchar_t *inId)
+ {
+ if (IsTrivial(inId))
+ return 0;
+ if (inId[0] == '#')
+ ++inId;
+
+ TIdToHandleMap::iterator find = m_IdToHandleMap.find(inId);
+ if (find != m_IdToHandleMap.end())
+ return find->second;
+ return 0;
+ }
+
+ virtual bool IsPropertyExist(const wchar_t *inType, const wchar_t *inProperty,
+ const wchar_t *inId)
+ {
+ CUICDMInstanceHandle theInstance =
+ IsTrivial(inId) ? GetInstanceForType(inType) : GetInstanceById(inId);
+ if (theInstance.Valid()) {
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theInstance, inProperty);
+
+ return theProperty.Valid();
+ }
+ return false;
+ }
+
+ ERuntimeDataModelDataType Convert(DataModelDataType::Value inType)
+ {
+ switch (inType) {
+ case DataModelDataType::None:
+ return ERuntimeDataModelDataTypeNone;
+ case DataModelDataType::Float:
+ return ERuntimeDataModelDataTypeFloat;
+ case DataModelDataType::Float2:
+ return ERuntimeDataModelDataTypeFloat2;
+ case DataModelDataType::Float3:
+ return ERuntimeDataModelDataTypeFloat3;
+ case DataModelDataType::Long:
+ return ERuntimeDataModelDataTypeLong;
+ case DataModelDataType::String:
+ return ERuntimeDataModelDataTypeString;
+ case DataModelDataType::Bool:
+ return ERuntimeDataModelDataTypeBool;
+ case DataModelDataType::Long4:
+ return ERuntimeDataModelDataTypeLong4;
+ case DataModelDataType::StringRef:
+ return ERuntimeDataModelDataTypeStringRef;
+ case DataModelDataType::ObjectRef:
+ return ERuntimeDataModelDataTypeObjectRef;
+ case DataModelDataType::StringOrInt:
+ return ERuntimeDataModelDataTypeStringOrInt;
+ default:
+ QT3DS_ASSERT(false);
+ return ERuntimeDataModelDataTypeNone;
+ }
+ }
+
+ virtual ERuntimeDataModelDataType
+ GetPropertyType(const wchar_t *inType, const wchar_t *inProperty, const wchar_t *inId)
+ {
+ CUICDMInstanceHandle theInstance =
+ IsTrivial(inId) ? GetInstanceForType(inType) : GetInstanceById(inId);
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theInstance, inProperty);
+ return Convert(m_DataCore->GetProperty(theProperty).m_Type);
+ }
+
+ ERuntimeAdditionalMetaDataType Convert(AdditionalMetaDataType::Value inType)
+ {
+ switch (inType) {
+ case AdditionalMetaDataType::None:
+ return ERuntimeAdditionalMetaDataTypeNone;
+ case AdditionalMetaDataType::StringList:
+ return ERuntimeAdditionalMetaDataTypeStringList;
+ case AdditionalMetaDataType::Range:
+ return ERuntimeAdditionalMetaDataTypeRange;
+ case AdditionalMetaDataType::Image:
+ return ERuntimeAdditionalMetaDataTypeImage;
+ case AdditionalMetaDataType::Color:
+ return ERuntimeAdditionalMetaDataTypeColor;
+ case AdditionalMetaDataType::Rotation:
+ return ERuntimeAdditionalMetaDataTypeRotation;
+ case AdditionalMetaDataType::Font:
+ return ERuntimeAdditionalMetaDataTypeFont;
+ case AdditionalMetaDataType::FontSize:
+ return ERuntimeAdditionalMetaDataTypeFontSize;
+ case AdditionalMetaDataType::MultiLine:
+ return ERuntimeAdditionalMetaDataTypeMultiLine;
+ case AdditionalMetaDataType::ObjectRef:
+ return ERuntimeAdditionalMetaDataTypeObjectRef;
+ case AdditionalMetaDataType::Mesh:
+ return ERuntimeAdditionalMetaDataTypeMesh;
+ case AdditionalMetaDataType::Import:
+ return ERuntimeAdditionalMetaDataTypeImport;
+ case AdditionalMetaDataType::Texture:
+ return ERuntimeAdditionalMetaDataTypeTexture;
+ case AdditionalMetaDataType::Renderable:
+ return ERuntimeAdditionalMetaDataTypeRenderable;
+ case AdditionalMetaDataType::PathBuffer:
+ return ERuntimeAdditionalMetaDataTypePathBuffer;
+ case AdditionalMetaDataType::ShadowMapResolution:
+ return ERuntimeAdditionalMetaDataTypeShadowMapResolution;
+ default:
+ QT3DS_ASSERT(false);
+ return ERuntimeAdditionalMetaDataTypeNone;
+ }
+ }
+
+ virtual ERuntimeAdditionalMetaDataType
+ GetAdditionalType(const wchar_t *inType, const wchar_t *inProperty, const wchar_t *inId)
+ {
+ CUICDMInstanceHandle theInstance =
+ IsTrivial(inId) ? GetInstanceForType(inType) : GetInstanceById(inId);
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theInstance, inProperty);
+ return Convert(m_NewMetaData->GetAdditionalMetaDataType(theInstance, theProperty));
+ }
+
+ bool GetPropertyValue(const wchar_t *inType, const wchar_t *inProperty, const wchar_t *inId,
+ SValue &outValue)
+ {
+ CUICDMInstanceHandle theInstance =
+ IsTrivial(inId) ? GetInstanceForType(inType) : GetInstanceById(inId);
+ if (theInstance.Valid()) {
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theInstance, inProperty);
+ return m_DataCore->GetInstancePropertyValue(theInstance, theProperty, outValue);
+ } else {
+ eastl::string typeStr;
+ eastl::string propertyStr;
+ eastl::string idStr;
+ ConvertWide(inType, typeStr);
+ ConvertWide(inProperty, propertyStr);
+ ConvertWide(inId, idStr);
+ qCCritical(INVALID_OPERATION) << "GetPropertyValueString: "
+ << typeStr.c_str() << " "
+ << propertyStr.c_str() << " "
+ << idStr.c_str();
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ SRuntimeMetaDataPropertyInfo &FindProperty(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId)
+ {
+ TStrTableStr theTypeOrId = inId.IsValid() ? inId : inType;
+ SPropertyKey theKey(theTypeOrId, inProperty);
+ eastl::pair<TPropertyLookupHash::iterator, bool> theLookup =
+ m_PropertyLookupHash.insert(eastl::make_pair(theKey, SRuntimeMetaDataPropertyInfo()));
+ if (theLookup.second) {
+ const wchar_t *theType(Convert0(inType));
+ const wchar_t *theProperty(Convert1(inProperty));
+ const wchar_t *theId(Convert2(inId));
+ if (IsPropertyExist(theType, theProperty, theId)) {
+ ERuntimeDataModelDataType theDataType(GetPropertyType(theType, theProperty, theId));
+ ERuntimeAdditionalMetaDataType theAdditionalType(
+ GetAdditionalType(theType, theProperty, theId));
+ Option<SValue> theValue;
+ SValue theValueData;
+ if (GetPropertyValue(theType, theProperty, theId, theValueData))
+ theValue = theValueData.toOldSkool();
+ theLookup.first->second =
+ SRuntimeMetaDataPropertyInfo(theDataType, theAdditionalType, theValue, true);
+ }
+ }
+ return theLookup.first->second;
+ }
+
+ bool IsPropertyExist(TStrTableStr inType, TStrTableStr inProperty, TStrTableStr inId) override
+ {
+ return FindProperty(inType, inProperty, inId).m_Exist;
+ }
+
+ ERuntimeDataModelDataType GetPropertyType(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId) override
+ {
+ return FindProperty(inType, inProperty, inId).m_DataType;
+ }
+
+ virtual ERuntimeAdditionalMetaDataType
+ GetAdditionalType(TStrTableStr inType, TStrTableStr inProperty, TStrTableStr inId) override
+ {
+ return FindProperty(inType, inProperty, inId).m_AdditionalType;
+ }
+
+ Option<float> GetPropertyValueFloat(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue())
+ return UICDM::get<float>(*theInfo.m_Value);
+ return Empty();
+ }
+
+ Option<qt3ds::QT3DSVec3> GetPropertyValueVector2(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue()) {
+ SFloat2 theFloat2 = UICDM::get<SFloat2>(*theInfo.m_Value);
+ return qt3ds::QT3DSVec3(theFloat2[0], theFloat2[1], 0);
+ }
+ return Empty();
+ }
+
+ Option<qt3ds::QT3DSVec3> GetPropertyValueVector3(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue()) {
+ SFloat3 theFloat3 = UICDM::get<SFloat3>(*theInfo.m_Value);
+ return qt3ds::QT3DSVec3(theFloat3[0], theFloat3[1], theFloat3[2]);
+ }
+ return Empty();
+ }
+
+ virtual Option<qt3ds::QT3DSI32> GetPropertyValueLong(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue())
+ return UICDM::get<qt3ds::QT3DSI32>(*theInfo.m_Value);
+ return Empty();
+ }
+
+ virtual Option<TRuntimeMetaDataStrType>
+ GetPropertyValueString(TStrTableStr inType, TStrTableStr inProperty, TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue()) {
+ TDataStrPtr theStr = UICDM::get<TDataStrPtr>(*theInfo.m_Value);
+ TRuntimeMetaDataStrType retval;
+ qt3ds::foundation::ConvertUTF(
+ reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(
+ theStr->GetData()),
+ 0, retval);
+ return retval;
+ }
+ return Empty();
+ }
+
+ virtual Option<TRuntimeMetaDataStrType>
+ GetPropertyValueObjectRef(TStrTableStr inType, TStrTableStr inProperty, TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue()) {
+ SObjectRefType theObjectRef = ConvertToObjectRef(*theInfo.m_Value);
+ if (theObjectRef.GetReferenceType() == ObjectReferenceType::Relative) {
+ TDataStrPtr theStr = UICDM::get<TDataStrPtr>(theObjectRef.m_Value);
+ TRuntimeMetaDataStrType retval;
+ qt3ds::foundation::ConvertUTF(
+ reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(
+ theStr->GetData()),
+ 0, retval);
+ return retval;
+ } else // we don't know how to solve absolute reference type
+ {
+ // QT3DS_ASSERT( false );
+ return TRuntimeMetaDataStrType("");
+ }
+ }
+ return Empty();
+ }
+
+ Option<bool> GetPropertyValueBool(TStrTableStr inType, TStrTableStr inProperty,
+ TStrTableStr inId) override
+ {
+ SRuntimeMetaDataPropertyInfo &theInfo(FindProperty(inType, inProperty, inId));
+ if (theInfo.m_Value.hasValue())
+ return UICDM::get<bool>(*theInfo.m_Value);
+ return Empty();
+ }
+
+ virtual void GetReferences(const wchar_t *inType,
+ eastl::vector<TRuntimeMetaDataStrType> &outReferences,
+ const wchar_t *inId)
+ {
+ CUICDMInstanceHandle theInstance =
+ IsTrivial(inId) ? GetInstanceForType(inType) : GetInstanceById(inId);
+
+ if (theInstance.Valid()) {
+ m_TempReferences.clear();
+ m_NewMetaData->GetReferences(theInstance, m_TempReferences);
+ outReferences.resize((uint32_t)m_TempReferences.size());
+ for (uint32_t idx = 0, end = (uint32_t)m_TempReferences.size(); idx < end; ++idx) {
+ qt3ds::foundation::ConvertUTF(m_TempReferences[idx].c_str(),
+ m_TempReferences[idx].size(), outReferences[idx]);
+ }
+ }
+ }
+
+ void GetReferences(const char *inType,
+ eastl::vector<TRuntimeMetaDataStrType> &outReferences,
+ const char *inId) override
+ {
+ GetReferences(Convert0(inType), outReferences, Convert2(inId));
+ }
+
+ virtual bool IsCustomProperty(const wchar_t *inId, const wchar_t *inProperty)
+ {
+ CUICDMInstanceHandle theInstance = GetInstanceById(inId);
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theInstance, inProperty);
+ return m_NewMetaData->IsCustomProperty(theInstance, theProperty);
+ }
+
+ bool IsCustomProperty(const char *inId, const char *inProperty) override
+ {
+ return IsCustomProperty(Convert2(inId), Convert1(inProperty));
+ }
+
+ virtual bool IsCustomHandler(const wchar_t *inId, const wchar_t *inHandlerName)
+ {
+ CUICDMInstanceHandle theInstance = GetInstanceById(inId);
+ CUICDMHandlerHandle theHandle =
+ m_NewMetaData->FindHandlerByName(theInstance, inHandlerName);
+ return m_NewMetaData->IsCustomHandler(theHandle);
+ }
+
+ inline void SetDataType(SAttOrArg &arg, const SMetaPropertyBase &argInfo)
+ {
+ arg.m_DataType = Convert(argInfo.GetDataType());
+ arg.m_MetaType = Convert(argInfo.GetAdditionalType());
+ qt3ds::foundation::ConvertUTF(argInfo.m_Name.c_str(), argInfo.m_Name.size(), arg.m_Name);
+ qt3ds::foundation::ConvertUTF(argInfo.m_FormalName.c_str(), argInfo.m_FormalName.size(),
+ arg.m_FormalName);
+ switch (argInfo.GetAdditionalType()) {
+ case UICDM::AdditionalMetaDataType::StringList: {
+ const eastl::vector<TCharStr> &theData =
+ argInfo.m_MetaDataData.getData<eastl::vector<TCharStr>>();
+ arg.m_MetaDataList.resize(theData.size());
+ for (uint32_t metaIdx = 0, metaEnd = theData.size(); metaIdx < metaEnd; ++metaIdx)
+ qt3ds::foundation::ConvertUTF(theData[metaIdx].c_str(), theData[metaIdx].size(),
+ arg.m_MetaDataList[metaIdx]);
+ } break;
+ case UICDM::AdditionalMetaDataType::Range: {
+ const SMetaDataRange &range = argInfo.m_MetaDataData.getData<SMetaDataRange>();
+ arg.m_MetaDataRange = eastl::make_pair(range.m_Min, range.m_Max);
+ } break;
+ default:
+ break;
+ }
+ }
+
+ THandlerList GetCustomHandlers(const char *inId) override
+ {
+ THandlerList retval;
+ CUICDMInstanceHandle theInstance = GetInstanceById(Convert0(inId));
+ THandlerHandleList handlerList;
+ m_NewMetaData->GetHandlers(theInstance, handlerList);
+ retval.reserve((uint32_t)handlerList.size());
+ for (size_t idx = 0, end = handlerList.size(); idx < end; ++idx) {
+ if (m_NewMetaData->IsCustomHandler(handlerList[idx])) {
+ SHandlerInfo theInfo(m_NewMetaData->GetHandlerInfo(handlerList[idx]));
+ retval.push_back(SHandler());
+ SHandler &handler(retval.back());
+ qt3ds::foundation::ConvertUTF(theInfo.m_Name.c_str(), theInfo.m_Name.size(),
+ handler.m_Name);
+ qt3ds::foundation::ConvertUTF(theInfo.m_FormalName.c_str(),
+ theInfo.m_FormalName.size(), handler.m_FormalName);
+ vector<SMetaDataHandlerArgumentInfo> theArgInfo;
+ m_NewMetaData->GetHandlerArguments(handlerList[idx], theArgInfo);
+ handler.m_Arguments.resize((uint32_t)theArgInfo.size());
+ for (uint32_t argIdx = 0, argEnd = (uint32_t)theArgInfo.size(); argIdx < argEnd;
+ ++argIdx) {
+ const SMetaDataHandlerArgumentInfo &argInfo(theArgInfo[argIdx]);
+ SAttOrArg &arg = handler.m_Arguments[argIdx];
+ SetDataType(arg, argInfo);
+ }
+ }
+ }
+ return retval;
+ }
+
+ TVisualEventList GetVisualEvents(const char *inId) override
+ {
+ TVisualEventList theRetval;
+ CUICDMInstanceHandle theInstance = GetInstanceById(Convert0(inId));
+ TEventHandleList theEventList;
+ m_NewMetaData->GetEvents(theInstance, theEventList);
+ theRetval.reserve((uint32_t)theEventList.size());
+ for (uint32_t idx = 0, end = (uint32_t)theEventList.size(); idx < end; ++idx) {
+ SEventInfo theInfo(m_NewMetaData->GetEventInfo(theEventList[idx]));
+ theRetval.push_back(SVisualEvent());
+ SVisualEvent &theEvent(theRetval.back());
+ qt3ds::foundation::ConvertUTF(theInfo.m_Name.c_str(), theInfo.m_Name.size(),
+ theEvent.m_Name);
+ qt3ds::foundation::ConvertUTF(theInfo.m_FormalName.c_str(), theInfo.m_FormalName.size(),
+ theEvent.m_FormalName);
+ }
+ return theRetval;
+ }
+
+ void MetaPropertiesToAttList(vector<CUICDMMetaDataPropertyHandle> &theProperties,
+ TAttOrArgList &outAtts)
+ {
+ outAtts.reserve((uint32_t)theProperties.size());
+ for (uint32_t idx = 0, end = (uint32_t)theProperties.size(); idx < end; ++idx) {
+ SMetaDataPropertyInfo thePropInfo =
+ m_NewMetaData->GetMetaDataPropertyInfo(theProperties[idx]);
+ outAtts.push_back(SAttOrArg());
+ SAttOrArg &arg(outAtts.back());
+ arg.m_DataType = Convert(thePropInfo.GetDataType());
+ arg.m_MetaType = Convert(thePropInfo.GetAdditionalType());
+ qt3ds::foundation::ConvertUTF(thePropInfo.m_Name.c_str(), thePropInfo.m_Name.size(),
+ arg.m_Name);
+ qt3ds::foundation::ConvertUTF(thePropInfo.m_FormalName.c_str(),
+ thePropInfo.m_FormalName.size(), arg.m_FormalName);
+ SetDataType(arg, thePropInfo);
+ }
+ }
+
+ SElementInfo LoadElement(const char *clsName, const char *clsRef, const char *inId) override
+ {
+ SElementInfo retval;
+ CUICDMInstanceHandle theInstance;
+ CUICDMInstanceHandle parentInstance;
+ if (!qt3ds::foundation::isTrivial(clsRef)) {
+ if (clsRef[0] == '#')
+ ++clsRef;
+ parentInstance = GetInstanceById(Convert0(clsRef));
+ } else {
+ parentInstance = m_NewMetaData->GetCanonicalInstanceForType(Convert0(clsName));
+ }
+ if (parentInstance.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ theInstance = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(theInstance, parentInstance);
+ m_IdToHandleMap.insert(std::make_pair(TCharStr(Convert0(inId)), theInstance));
+ // setup isComponent
+ CUICDMInstanceHandle slideOwner = m_NewMetaData->GetCanonicalInstanceForType(L"SlideOwner");
+ retval.m_IsComponent = m_DataCore->IsInstanceOrDerivedFrom(theInstance, slideOwner);
+ TCharStr type = m_NewMetaData->GetTypeForInstance(theInstance);
+ qt3ds::foundation::ConvertUTF(type.c_str(), type.size(), retval.m_ClassName);
+ vector<CUICDMMetaDataPropertyHandle> theProperties;
+ m_NewMetaData->GetMetaDataProperties(theInstance, theProperties);
+ MetaPropertiesToAttList(theProperties, retval.m_Attributes);
+ return retval;
+ }
+
+ TAttOrArgList GetSlideAttributes() override
+ {
+ TAttOrArgList retval;
+ CUICDMInstanceHandle slideOwner = m_NewMetaData->GetCanonicalInstanceForType(L"Slide");
+ vector<CUICDMMetaDataPropertyHandle> theProperties;
+ m_NewMetaData->GetSpecificMetaDataProperties(slideOwner, theProperties);
+ MetaPropertiesToAttList(theProperties, retval);
+ return retval;
+ }
+
+ bool IsCustomHandler(const char *inId, const char *inHandlerName) override
+ {
+ return IsCustomHandler(Convert0(inId), Convert1(inHandlerName));
+ }
+
+ virtual void GetHandlerArgumentType(const wchar_t *inId, const wchar_t *inHandlerName,
+ const wchar_t *inArgumentName,
+ ERuntimeDataModelDataType &outType,
+ ERuntimeAdditionalMetaDataType &outAdditionalType)
+ {
+ outType = ERuntimeDataModelDataTypeNone;
+ outAdditionalType = ERuntimeAdditionalMetaDataTypeNone;
+
+ CUICDMInstanceHandle theInstance = GetInstanceById(inId);
+ CUICDMHandlerHandle theHandle =
+ m_NewMetaData->FindHandlerByName(theInstance, inHandlerName);
+ Option<SMetaDataHandlerArgumentInfo> theArgMetaData(
+ m_NewMetaData->FindHandlerArgumentByName(theHandle, inArgumentName));
+ if (theArgMetaData.hasValue()) {
+ outType = Convert(theArgMetaData->GetDataType());
+ outAdditionalType = Convert(theArgMetaData->GetAdditionalType());
+ }
+
+ // Check if the type is something that we support
+ QT3DS_ASSERT(outType != ERuntimeDataModelDataTypeNone);
+ }
+
+ void GetHandlerArgumentType(const char *inId, const char *inHandlerName,
+ const char *inArgumentName,
+ ERuntimeDataModelDataType &outType,
+ ERuntimeAdditionalMetaDataType &outAdditionalType) override
+ {
+ GetHandlerArgumentType(Convert0(inId), Convert1(inHandlerName), Convert2(inArgumentName),
+ outType, outAdditionalType);
+ }
+
+ std::shared_ptr<IDOMReader> ParseLuaFile(const wchar_t *inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable)
+ {
+ using namespace LuaParser;
+ std::shared_ptr<UICDM::IStringTable> theStringTable(inStringTable);
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SImportXmlErrorHandler theXmlErrorHandler;
+ qt3ds::foundation::MallocAllocator allocator;
+ eastl::basic_string<char8_t, ForwardingAllocator> convertBuf(
+ ForwardingAllocator(allocator, "Unused"));
+ qt3ds::foundation::ConvertUTF(
+ reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(
+ inFullPathToDocument),
+ 0, convertBuf);
+ qt3ds::foundation::CFileTools::NormalizePath(convertBuf);
+ qt3ds::foundation::CFileTools::ToPlatformPath(convertBuf);
+ std::shared_ptr<IDOMReader> theReaderPtr(
+ SLuaParser::ParseLuaFile(theFactory, inStringTable, convertBuf.c_str(),
+ theXmlErrorHandler, m_InputStreamFactory));
+
+ if (!theReaderPtr)
+ qCCritical(INVALID_OPERATION) << "Failed to open lua file: " << convertBuf.c_str();
+ return theReaderPtr;
+ }
+
+ std::shared_ptr<IDOMReader> ParseScriptFile(const wchar_t *inFullPathToDocument,
+ std::shared_ptr<UICDM::IStringTable> inStringTable)
+ {
+ using namespace ScriptParser;
+ std::shared_ptr<UICDM::IStringTable> theStringTable(inStringTable);
+ std::shared_ptr<IDOMFactory> theFactory(IDOMFactory::CreateDOMFactory(theStringTable));
+ SImportXmlErrorHandler theXmlErrorHandler;
+ const QString path = QString::fromWCharArray(inFullPathToDocument);
+ std::shared_ptr<IDOMReader> theReaderPtr(
+ SScriptParser::ParseScriptFile(theFactory, inStringTable,
+ path,
+ theXmlErrorHandler, m_InputStreamFactory));
+ if (!theReaderPtr)
+ qCCritical(INVALID_OPERATION) << "Failed to open lua file: " << path;
+ return theReaderPtr;
+ }
+
+ CUICDMInstanceHandle CreateAndDeriveInstance(const wchar_t *inType, const wchar_t *inId)
+ {
+ // Make sure that the same id has not been created before
+ TCharStr theId(inId);
+ QT3DS_ASSERT(m_IdToHandleMap.find(theId) == m_IdToHandleMap.end());
+
+ CUICDMInstanceHandle theCanonicalType(m_NewMetaData->GetCanonicalInstanceForType(inType));
+ if (theCanonicalType.Valid() == false) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ CUICDMInstanceHandle theMaster = m_DataCore->CreateInstance();
+ m_DataCore->DeriveInstance(theMaster, theCanonicalType);
+ m_IdToHandleMap.insert(std::make_pair(theId, theMaster));
+ return theMaster;
+ }
+
+ virtual bool LoadLuaFile(const wchar_t *inType, const wchar_t *inId, const wchar_t *inName,
+ const wchar_t *inSourcePath)
+ {
+ // Check if the file with the given id has been loaded before and return immediately
+ TCharStr theId(inId);
+ if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end())
+ return true;
+
+ CUICDMInstanceHandle theMaster = CreateAndDeriveInstance(inType, inId);
+ if (!theMaster.Valid())
+ return false;
+
+ // If we can't parse the lua file, go on.
+ std::shared_ptr<IDOMReader> theLuaPtr =
+ ParseLuaFile(inSourcePath, m_DataCore->GetStringTablePtr());
+ if (theLuaPtr) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ // Now the magic section
+ m_NewMetaData->LoadInstance(*theLuaPtr, theMaster, inName, warnings);
+
+ // Set the name
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theMaster, L"name");
+ m_DataCore->SetInstancePropertyValue(theMaster, theProperty,
+ std::make_shared<CDataStr>(inName));
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual bool LoadScriptFile(const wchar_t *inType, const wchar_t *inId, const wchar_t *inName,
+ const wchar_t *inSourcePath)
+ {
+ TCharStr theId(inId);
+ if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end())
+ return true;
+
+ CUICDMInstanceHandle theMaster = CreateAndDeriveInstance(inType, inId);
+ if (!theMaster.Valid())
+ return false;
+
+ std::shared_ptr<IDOMReader> theScriptPtr =
+ ParseScriptFile(inSourcePath, m_DataCore->GetStringTablePtr());
+ if (theScriptPtr) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ // Now the magic section
+ m_NewMetaData->LoadInstance(*theScriptPtr, theMaster, inName, warnings);
+
+ // Set the name
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theMaster, L"name");
+ m_DataCore->SetInstancePropertyValue(theMaster, theProperty,
+ std::make_shared<CDataStr>(inName));
+ return true;
+ }
+
+ return false;
+ }
+
+ bool LoadLuaFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) override
+ {
+ return LoadLuaFile(Convert0(inType), Convert1(inId), Convert2(inName),
+ Convert3(inSourcePath));
+ }
+
+ bool LoadScriptFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) override
+ {
+ return LoadScriptFile(Convert0(inType), Convert1(inId), Convert2(inName),
+ Convert3(inSourcePath));
+ }
+
+ bool LoadEffectXMLFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) override
+ {
+ const wchar_t *theType(Convert0(inType));
+ const wchar_t *theId(Convert1(inId));
+ const wchar_t *theName(Convert2(inName));
+ if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end())
+ return true;
+
+ CUICDMInstanceHandle theMaster = CreateAndDeriveInstance(theType, theId);
+ if (!theMaster.Valid())
+ return false;
+ NVScopedRefCounted<IRefCountedInputStream> theStream(
+ m_InputStreamFactory.GetStreamForFile(inSourcePath));
+ if (theStream) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ bool success = m_NewMetaData->LoadEffectXMLFromSourcePath(
+ inSourcePath, theMaster, theName, warnings, *theStream);
+ (void)success;
+ QT3DS_ASSERT(success);
+ return success;
+ }
+ return false;
+ }
+
+ bool LoadMaterialXMLFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) override
+ {
+ const wchar_t *theType(Convert0(inType));
+ const wchar_t *theId(Convert1(inId));
+ const wchar_t *theName(Convert2(inName));
+ (void)theName;
+ if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end())
+ return true;
+
+ CUICDMInstanceHandle theMaster = CreateAndDeriveInstance(theType, theId);
+ if (!theMaster.Valid())
+ return false;
+
+ NVScopedRefCounted<IRefCountedInputStream> theStream(
+ m_InputStreamFactory.GetStreamForFile(inSourcePath));
+ if (theStream) {
+ std::vector<SMetaDataLoadWarning> warnings;
+ bool success = m_NewMetaData->LoadMaterialClassFromSourcePath(
+ inSourcePath, theMaster, theId, warnings, *theStream);
+ (void)success;
+ QT3DS_ASSERT(success);
+ return success;
+ }
+ return false;
+ }
+
+ struct PluginErrorHandler : public UICDM::CXmlErrorHandler
+ {
+ void OnXmlError(TWideXMLCharPtr, int, int) override {}
+ };
+
+ bool LoadPluginXMLFile(const char *inType, const char *inId, const char *inName,
+ const char *inSourcePath) override
+ {
+ const wchar_t *theType(Convert0(inType));
+ const wchar_t *theId(Convert1(inId));
+ const wchar_t *theName(Convert2(inName));
+ if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end())
+ return true;
+
+ CUICDMInstanceHandle theMaster = CreateAndDeriveInstance(theType, theId);
+ if (!theMaster.Valid())
+ return false;
+
+ std::shared_ptr<UICDM::IDOMFactory> theFactory =
+ UICDM::IDOMFactory::CreateDOMFactory(m_StrTable);
+
+ PluginErrorHandler dummyHandler;
+ std::shared_ptr<UICDM::IDOMReader> theReader = Q3DStudio::CRenderPluginParser::ParseFile(
+ theFactory, m_StrTable, inSourcePath, dummyHandler, m_InputStreamFactory);
+ if (theReader) {
+ Q3DStudio::CRenderPluginParser::NavigateToMetadata(theReader);
+ std::vector<SMetaDataLoadWarning> theWarnings;
+ m_NewMetaData->LoadInstance(*theReader, theMaster, theName, theWarnings);
+ CUICDMPropertyHandle theProperty =
+ m_DataCore->GetAggregateInstancePropertyByName(theMaster, L"name");
+ m_DataCore->SetInstancePropertyValue(theMaster, theProperty,
+ std::make_shared<CDataStr>(theName));
+ return true;
+ }
+ return false;
+ }
+
+ Option<UICDM::SMetaDataEffect> GetEffectMetaDataBySourcePath(const char *inName) override
+ {
+ return m_NewMetaData->GetEffectBySourcePath(inName);
+ }
+
+ virtual Option<UICDM::SMetaDataCustomMaterial>
+ GetMaterialMetaDataBySourcePath(const char *inName) override
+ {
+ return m_NewMetaData->GetMaterialBySourcePath(inName);
+ }
+
+ virtual void GetInstanceProperties(const wchar_t *inType, const wchar_t *inId,
+ eastl::vector<TRuntimeMetaDataStrType> &outProperties,
+ bool inSearchParent)
+ {
+ // Get the instance handle given the type or id
+ CUICDMInstanceHandle theInstance =
+ IsTrivial(inId) ? GetInstanceForType(inType) : GetInstanceById(inId);
+ if (!theInstance.Valid()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ vector<CUICDMMetaDataPropertyHandle> theProperties;
+ if (inSearchParent)
+ // Get the meta data properties defined on this object or its derivation parents
+ m_NewMetaData->GetMetaDataProperties(theInstance, theProperties);
+ else
+ // Get the meta data properties defined on *only* this object, don't search parents
+ m_NewMetaData->GetSpecificMetaDataProperties(theInstance, theProperties);
+
+ outProperties.clear();
+ // Iterate each property and fill outProperties
+ for (size_t propIdx = 0, propEnd = theProperties.size(); propIdx < propEnd; ++propIdx) {
+ SMetaDataPropertyInfo theInfo(
+ m_NewMetaData->GetMetaDataPropertyInfo(theProperties[propIdx]));
+ outProperties.push_back(TRuntimeMetaDataStrType());
+ qt3ds::foundation::ConvertUTF(theInfo.m_Name.c_str(), 0, outProperties.back());
+ }
+ }
+
+ void GetInstanceProperties(const char *inType, const char *inId,
+ eastl::vector<TRuntimeMetaDataStrType> &outProperties,
+ bool inSearchParent) override
+ {
+ GetInstanceProperties(Convert0(inType), Convert2(inId), outProperties, inSearchParent);
+ }
+
+ std::shared_ptr<UICDM::IStringTable> GetStringTable() override { return m_StrTable; }
+
+ TStrTableStr Register(const char *inStr) override
+ {
+ return m_StrTable->GetRenderStringTable().RegisterStr(inStr);
+ }
+
+ //==============================================================================
+ /**
+ * @Self release
+ */
+ void release() override { delete this; }
+
+ void ClearPerProjectData() override
+ {
+
+ m_IdToHandleMap.clear();
+ m_PropertyLookupHash.clear();
+ }
+
+}; // end of struct SRuntimeMetaDataImpl
+}
+
+IRuntimeMetaData &IRuntimeMetaData::Create(IInputStreamFactory &inInputStreamFactory)
+{
+ SRuntimeMetaDataImpl &retval = *new SRuntimeMetaDataImpl(inInputStreamFactory);
+ retval.Load();
+ return retval;
+}
diff --git a/src/Runtime/Source/System/Include/SystemPrefix.h b/src/Runtime/Source/System/Include/SystemPrefix.h
new file mode 100644
index 00000000..1fba858c
--- /dev/null
+++ b/src/Runtime/Source/System/Include/SystemPrefix.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#ifdef _WIN32
+//==============================================================================
+// DEFINES
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+//==============================================================================
+// DISABLED WARNINGS
+//
+// Note that most of these warnings are tuned off by default by the compiler
+// even at warning level 4. Using option /Wall turns on all warnings and makes
+// even standard Microsoft include files cry. We had to turn off these or
+// turn off warnings individually for each standard include file which was
+// too much work. Point is that /Wall is like Warning Level 5 and this brings
+// it down to about Warning level 4.5, still way above /W4.
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+#pragma warning(disable : 4511) // copy constructor could not be generated
+#pragma warning(disable : 4512) // assignment operator could not be generated
+#pragma warning(disable : 4514) // unreferenced inline function has been removed
+#pragma warning(disable : 4619) // #pragma warning : there is no warning number '4619' (in string.h)
+#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy
+ // constructor is inaccessible
+#pragma warning(disable : 4626) // assignment operator could not be generated because a base class
+ // assignment operator is inaccessible
+#pragma warning(disable : 4826) // Conversion from 'const void *' to 'void *' is sign-extended
+#pragma warning(disable : 4996) // _snprintf' was declared deprecated
+#pragma warning(disable : 4711) // function selected for automatic inline expansion
+#pragma warning(disable : 4710) // function not inlined
+#pragma warning(disable : 4355) // 'this' : used in base member initializer list
+
+#pragma warning(disable : 4640) // construction of local static object is not thread-safe
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning( \
+ disable : 4738) // storing 32-bit float result in memory, possible loss of performance
+#endif //_WIN32
+
+//==============================================================================
+// STD INCLUDES - Standard includes MUST come first
+#include <stdlib.h> // Standard functions
+#include <stdio.h> // File and IO
+#ifndef _INTEGRITYPLATFORM
+#include <memory.h> // memset, memcpy
+#endif
+#include <string.h> // strlen
+#include <math.h> // Bezier math - pow, acos, cos, sqrt
+#include <ctype.h> // _tolower
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#include <stdint.h>
+#endif
+
+//==============================================================================
+// OUR INCLUDES
+#include "UICTypes.h"
+#include "UICPlatformSpecific.h"
+#include "UICAssert.h"
+#include "UICMacros.h"
+#include "UICConfig.h"
+#include "UICMemorySettings.h"
+#include "UICMemory.h"
+#include "UICArray.h"
diff --git a/src/Runtime/Source/System/Include/UICArray.h b/src/Runtime/Source/System/Include/UICArray.h
new file mode 100644
index 00000000..945c9ff3
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICArray.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICMemorySettings.h"
+#include "UICMemory.h"
+#include "UICPlatformSpecific.h"
+
+#ifdef WIN32
+#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy
+ // constructor is inaccessible
+#pragma warning(disable : 4626) // assignment operator could not be generated because a base class
+ // assignment operator is inaccessible
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+#define NVARRAY_NOTFOUND -1
+
+//==============================================================================
+/**
+ * Ordered Collection also knows as a vector.
+ *
+ * Use Reserve or the constructor parameter if you know how many slots
+ * will be needed to prevent frequent reallocations during growth.
+ *
+ * The array grows by DEFAULT_GROWFACTOR aka 20% whenever it overflows. By
+ * setting the factor to 0 it will still clamp to 1 and instead grow the
+ * array by one slot at a time. This is not ideal but given a pooled memory
+ * manager you will not thrash memory too much since you will grow inside
+ * each pool chunk and only reallocate when switching pools.
+ *
+ * Naming of CArray instances are used to enable memory tracking of arrays
+ * that have gone berzerk or less frequently used instances that could be
+ * released after usage.
+ *
+ * The FOR_ARRAY macro is the preferred way to process all array slots.
+ */
+template <class T>
+class CArray
+{
+//==============================================================================
+// Constants
+//==============================================================================
+#define DEFAULT_GROWFACTOR 1.2f
+
+ //==============================================================================
+ // Types
+ //==============================================================================
+public:
+ typedef T TType; ///< Easy access to template type
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CHAR m_Name[32]; ///< Allows easy ID using memory reporting
+ T *m_Data; ///< Allocated memory containing array data
+ INT32 m_Capacity; ///< Max number of slots possible
+ INT32 m_Count; ///< Current number of slots in array
+ FLOAT m_GrowFactor; ///< Factor by which array grows when out of space
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CArray(const INT32 inCapacity = 0, const FLOAT inGrowFactor = DEFAULT_GROWFACTOR,
+ const CHAR *inName = NULL);
+ inline CArray(const CArray<T> &);
+ inline ~CArray();
+
+public: // Management
+ inline void SetName(const CHAR *inName = NULL);
+ inline INT32 GetCount() const;
+ inline INT32 GetCapacity() const;
+ inline void Clear(const BOOL inRelease = true);
+ inline void Reserve(const INT32 inCapacity, const BOOL inExpand = false);
+
+public: // Stack access
+ void Push(const T &inValue);
+ inline const T &Pop();
+ inline const T &Top() const;
+
+public: // Random access
+ inline INT32 GetIndex(const T &inValue) const;
+ inline T &operator[](const INT32 inIndex) const;
+ inline void Remove(const INT32 inIndex);
+
+public: // FOR_ARRAY iteration
+ inline T *Begin() const;
+ inline T *End() const;
+
+private: // Disabled Copy Construction
+ inline CArray<T> &operator=(const CArray<T> &);
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "UICArray.inl"
diff --git a/src/Runtime/Source/System/Include/UICArray.inl b/src/Runtime/Source/System/Include/UICArray.inl
new file mode 100644
index 00000000..a9667fd2
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICArray.inl
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ *
+ * @param inCapacity preallocated number of slots to avoid growth reallocation
+ * @param inGrowFactor factor by which the array grows when out of space
+ * @param inName 32 byte unique identifier for memory tracking
+ */
+template <typename T> inline
+CArray<T>::CArray( const INT32 inCapacity, const FLOAT inGrowFactor, const CHAR* inName ) :
+ m_Data( NULL ),
+ m_Capacity( 0 ),
+ m_Count( 0 ),
+ m_GrowFactor( inGrowFactor )
+{
+ // Disallow negative growth
+ if ( m_GrowFactor < 1.0f )
+ m_GrowFactor = DEFAULT_GROWFACTOR;
+
+ SetName( inName );
+ Reserve( inCapacity );
+}
+
+//==============================================================================
+/**
+ * Berger's Copy Constructor.
+ */
+template <typename T> inline
+CArray<T>::CArray( const CArray<T>& inOther ) :
+ m_Data( NULL ),
+ m_Capacity( 0 ),
+ m_Count( 0 ),
+ m_GrowFactor( inOther.m_GrowFactor )
+{
+ // Disallow negative growth
+ if ( m_GrowFactor < 1.0f )
+ m_GrowFactor = DEFAULT_GROWFACTOR;
+
+ SetName( inOther.m_Name );
+ Reserve( inOther.m_Capacity );
+ FOR_ARRAY( T, theTemp, inOther )
+ {
+ Push( *theTemp );
+ }
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+template <class T> inline
+CArray<T>::~CArray( )
+{
+ Clear( true );
+}
+
+//==============================================================================
+/**
+ * Name an array instance to easily identify it during memory reporting.
+ * @param inName 32 byte unique identifier
+ */
+template <class T> inline
+void CArray<T>::SetName( const CHAR* inName /*= NULL*/ )
+{
+ Q3DStudio_sprintf( m_Name, sizeof( m_Name ), "%s", inName ? inName : "CArray<T>" );
+}
+
+//==============================================================================
+/**
+ * Count is the number of elements in the array.
+ * @return current count of the array
+ */
+template <class T> inline
+INT32 CArray<T>::GetCount( ) const
+{
+ return m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the capacity of the array
+ * Capacity reflects the max count before reallocation happens.
+ * @return capacity of the array
+ */
+template <class T> inline
+INT32 CArray<T>::GetCapacity( ) const
+{
+ return m_Capacity;
+}
+
+//==============================================================================
+/**
+ * Clear the array by reducing the number of elements to zero.
+ *
+ * Using the release flag keeps the memory load low but could be
+ * suboptimal in situations where you are always using roughly the same
+ * number of elements. In that scenario, the array would have to build up
+ * and reallocate up to the same number of elements every time causing
+ * stress on the system. Clearing but keeping the buffer by setting
+ * release to false is optimal in that case.
+ *
+ * @param inRelease true to release memory, false keeps old buffer
+ */
+template <class T> inline
+void CArray<T>::Clear( const BOOL inRelease )
+{
+ m_Count = 0;
+
+ if ( inRelease )
+ {
+ Q3DStudio_free( m_Data, T, m_Capacity );
+ m_Capacity = 0;
+ m_Data = NULL;
+ }
+ else
+ Q3DStudio_memset( m_Data, 0 , sizeof( T ) * m_Capacity );
+}
+
+//==============================================================================
+/**
+ * Allocate enough memory to store T.
+ *
+ * If current memory is not sufficient, new block of memory is allocated and
+ * data in current memory is copied to the new block of memory. Data pointer will
+ * point to the new block of memory and current memory is released.
+ *
+ * @param inCapacity indicate the amount of memory required.
+ * @param inExpand true to not only allocate but also extend array
+ */
+template <class T> inline
+void CArray<T>::Reserve( const INT32 inCapacity, const BOOL inExpand )
+{
+ if ( inCapacity > m_Capacity )
+ {
+ T* theData = Q3DStudio_allocate_desc( T, inCapacity, m_Name );
+ Q3DStudio_memset( theData, 0 , sizeof( T ) * inCapacity );
+ if ( m_Data != NULL )
+ {
+ Q3DStudio_memcpy( theData, m_Data, sizeof( T ) * m_Count );
+ Q3DStudio_free( m_Data, T, m_Capacity );
+ }
+ m_Data = theData;
+ m_Capacity = inCapacity;
+ }
+
+ if ( inExpand )
+ m_Count = inCapacity;
+}
+
+//==============================================================================
+/**
+ * Insert T to the end of the array
+ * @param inValue value of datatype T
+ */
+template <class T> inline
+void CArray<T>::Push( const T& inValue )
+{
+ if ( m_Count == m_Capacity )
+ Reserve( static_cast<INT32>( m_GrowFactor * m_Capacity ) + 1 );
+
+ m_Data[m_Count++] = inValue;
+}
+
+//==============================================================================
+/**
+ * Remove and retrieve T which is at the end of the array
+ * @return value of datatype T
+ */
+template <class T> inline
+const T& CArray<T>::Pop( )
+{
+ return m_Data[--m_Count];
+}
+
+//==============================================================================
+/**
+ * Get T which is at the end of the array
+ * @return reference of value of datatype T
+ */
+template <class T> inline
+const T& CArray<T>::Top( ) const
+{
+ return m_Data[m_Count - 1];
+}
+
+//==============================================================================
+/**
+ * Get index of first element that matches inValue
+ * @return index of element matching T or INDEX_NOTFOUND
+ */
+template <class T> inline
+INT32 CArray<T>::GetIndex( const T& inValue ) const
+{
+ for ( INT32 theIndex = 0; theIndex < m_Count; ++theIndex )
+ if ( inValue == m_Data[theIndex] )
+ return theIndex;
+ return NVARRAY_NOTFOUND;
+}
+
+//==============================================================================
+/**
+ * Get the element at a particular index position of the array.
+ * @note Range checking is only done is debug builds.
+ * @param inIndex the index of the array
+ * @return reference of value of datatype T
+ */
+template <class T> inline
+T& CArray<T>::operator[]( const INT32 inIndex ) const
+{
+ Q3DStudio_ASSERT( inIndex >= 0 && inIndex < m_Capacity );
+ return m_Data[inIndex];
+}
+
+//==============================================================================
+/**
+ * Remove T that resides at a particular index position of the array.
+ * Other T data with higher index value is shifted to occupy the empty slot
+ * created in the removal process.
+ * @param inIndex the index of the array
+ */
+template <class T> inline
+void CArray<T>::Remove( const INT32 inIndex )
+{
+ Q3DStudio_memmove( m_Data + inIndex, m_Data + inIndex + 1, sizeof( T ) * ( m_Count - inIndex - 1 ) );
+ --m_Count;
+}
+
+//==============================================================================
+/**
+ * Get T at the first index of the array.
+ * Mainly used for FOR_ARRAY macro implementation
+ * @return pointer to first value in array
+ */
+template <class T> inline
+T* CArray<T>::Begin( ) const
+{
+ return m_Data;
+}
+
+//==============================================================================
+/**
+ * Get T at the last index of the array.
+ * Mainly used for FOR_ARRAY macro implementation
+ * @return pointer to one beyond last value in array
+ */
+template <class T> inline
+T* CArray<T>::End( ) const
+{
+ return m_Data + m_Count;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICAssert.h b/src/Runtime/Source/System/Include/UICAssert.h
new file mode 100644
index 00000000..ae487564
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICAssert.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "UICTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Static gateway for all asserts.
+ *
+ * By setting your own assert function you can redirect all Runtime asserts.
+ * By default it uses the internal Default method that uses CLog for output
+ * and displays a dialog on Windows PCs.
+ */
+class CAssert
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef void (*TFunction)(const Q3DStudio::CHAR *inAssert, const Q3DStudio::CHAR *inFile,
+ Q3DStudio::INT32 inLine, const Q3DStudio::CHAR *inFunction);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static TFunction s_AssertFunction; ///< Function pointer to active assert function
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Hidden Constructor
+ CAssert();
+
+public: // Static Usage
+ static void Default(const Q3DStudio::CHAR *inAssert, const Q3DStudio::CHAR *inFile,
+ Q3DStudio::INT32 inLine, const Q3DStudio::CHAR *inFunction);
+
+public: // Static Configuration
+ static void SetFunction(TFunction inAssert);
+ static TFunction GetFunction();
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICAudioPlayer.h b/src/Runtime/Source/System/Include/UICAudioPlayer.h
new file mode 100644
index 00000000..3b6f3ef8
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICAudioPlayer.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+namespace Q3DStudio {
+
+class IAudioPlayer
+{
+public:
+ virtual ~IAudioPlayer() {}
+ virtual bool PlaySoundFile(const char *inFilePath) = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICBasicPluginDLL.h b/src/Runtime/Source/System/Include/UICBasicPluginDLL.h
new file mode 100644
index 00000000..63a2d1f6
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICBasicPluginDLL.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+
+#include <QtGlobal>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+// Enums
+//==============================================================================
+typedef enum _EDLLSTATUS { EDLLSTATUS_FAIL = 0, EDLLSTATUS_OK } EDLLSTATUS;
+
+// GetPluginType should return this
+typedef enum _EDLLTYPE {
+ EDLLTYPE_UNKNOWN = 0,
+ EDLLTYPE_RENDERABLE_PLUGIN,
+ EDLLTYPE_CUSTOM_OBJECT,
+} EDLLTYPE;
+
+//==============================================================================
+// Function declarations
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return the plugin type.
+ * @return plugin type
+ */
+typedef long (*PROC_GetPluginType)();
+Q_DECL_EXPORT long GetPluginType();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/Runtime/Source/System/Include/UICBezierEval.h b/src/Runtime/Source/System/Include/UICBezierEval.h
new file mode 100644
index 00000000..252234b3
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICBezierEval.h
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma message( \
+ "AKBezierEval.h -- Changes to this file necessitate rebuilding the studio UICDM project and running the unit tests")
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Generic Bezier parametric curve evaluation at a given parametric value.
+ * @param inP0 control point P0
+ * @param inP1 control point P1
+ * @param inP2 control point P2
+ * @param inP3 control point P3
+ * @param inS the variable
+ * @return the evaluated value on the bezier curve
+ */
+inline FLOAT EvaluateBezierCurve(FLOAT inP0, FLOAT inP1, FLOAT inP2, FLOAT inP3, const FLOAT inS)
+{
+ // Using:
+ // Q(s) = Sum i=0 to 3 ( Pi * Bi,3(s))
+ // where:
+ // Pi is a control point and
+ // Bi,3 is a basis function such that:
+ //
+ // B0,3(s) = (1 - s)^3
+ // B1,3(s) = (3 * s) * (1 - s)^2
+ // B2,3(s) = (3 * s^2) * (1 - s)
+ // B3,3(s) = s^3
+
+ /* FLOAT theSSquared = inS * inS; //
+ t^2
+ FLOAT theSCubed = theSSquared * inS; //
+ t^3
+
+ FLOAT theSDifference = 1 - inS; // (1 -
+ t)
+ FLOAT theSDifferenceSquared = theSDifference * theSDifference; // (1 -
+ t)^2
+ FLOAT theSDifferenceCubed = theSDifferenceSquared * theSDifference; // (1 - t)^3
+
+ FLOAT theFirstTerm = theSDifferenceCubed; // (1 -
+ t)^3
+ FLOAT theSecondTerm = ( 3 * inS ) * theSDifferenceSquared; // (3 * t) * (1
+ - t)^2
+ FLOAT theThirdTerm = ( 3 * theSSquared ) * theSDifference; // (3 * t^2) *
+ (1 - t)
+ FLOAT theFourthTerm = theSCubed; //
+ t^3
+
+ // Q(t) = ( p0 * (1 - t)^3 ) + ( p1 * (3 * t) * (1 - t)^2 ) + ( p2 * (3 * t^2) * (1 - t)
+ ) + ( p3 * t^3 )
+ return ( inP0 * theFirstTerm ) + ( inP1 * theSecondTerm ) + ( inP2 * theThirdTerm ) + (
+ inP3 * theFourthTerm );*/
+
+ FLOAT theFactor = inS * inS;
+ inP1 *= 3 * inS;
+ inP2 *= 3 * theFactor;
+ theFactor *= inS;
+ inP3 *= theFactor;
+
+ theFactor = 1 - inS;
+ inP2 *= theFactor;
+ theFactor *= 1 - inS;
+ inP1 *= theFactor;
+ theFactor *= 1 - inS;
+ inP0 *= theFactor;
+
+ return inP0 + inP1 + inP2 + inP3;
+}
+
+//==============================================================================
+/**
+ * Inverse Bezier parametric curve evaluation to get parametric value for a given output.
+ * This is equal to finding the root(s) of the Bezier cubic equation.
+ * @param inP0 control point P0
+ * @param inP1 control point P1
+ * @param inP2 control point P2
+ * @param inP3 control point P3
+ * @param inX the variable
+ * @return the evaluated value
+ */
+inline FLOAT EvaluateInverseBezierCurve(const FLOAT inP0, const FLOAT inP1, const FLOAT inP2,
+ const FLOAT inP3, const FLOAT inX)
+{
+ FLOAT theResult = 0;
+
+ // Using:
+ // Q(s) = Sum i=0 to 3 ( Pi * Bi,3(s))
+ // where:
+ // Pi is a control point and
+ // Bi,3 is a basis function such that:
+ //
+ // B0,3(s) = (1 - s)^3
+ // B1,3(s) = (3 * s) * (1 - s)^2
+ // B2,3(s) = (3 * s^2) * (1 - s)
+ // B3,3(s) = s^3
+
+ // The Bezier cubic equation:
+ // inX = inP0*(1-s)^3 + inP1*(3*s)*(1-s)^2 + inP2*(3*s^2)*(1-s) + inP3*s^3
+ // = s^3*( -inP0 + 3*inP1 - 3*inP2 +inP3 ) + s^2*( 3*inP0 - 6*inP1 + 3*inP2 ) + s*( -3*inP0
+ // + 3*inP1 ) + inP0
+ // For cubic eqn of the form: c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 = 0
+ FLOAT theConstants[4];
+ theConstants[0] = static_cast<FLOAT>(inP0 - inX);
+ theConstants[1] = static_cast<FLOAT>(-3 * inP0 + 3 * inP1);
+ theConstants[2] = static_cast<FLOAT>(3 * inP0 - 6 * inP1 + 3 * inP2);
+ theConstants[3] = static_cast<FLOAT>(-inP0 + 3 * inP1 - 3 * inP2 + inP3);
+
+ FLOAT theSolution[3] = { 0 };
+
+ if (theConstants[3] == 0) {
+ if (theConstants[2] == 0) {
+ if (theConstants[1] == 0)
+ theResult = 0;
+ else
+ theResult = -theConstants[0] / theConstants[1]; // linear
+ } else {
+ // quadratic
+ INT32 theNumRoots = CCubicRoots::SolveQuadric(theConstants, theSolution);
+ theResult = static_cast<FLOAT>(theSolution[theNumRoots / 2]);
+ }
+ } else {
+ INT32 theNumRoots = CCubicRoots::SolveCubic(theConstants, theSolution);
+ theResult = static_cast<FLOAT>(theSolution[theNumRoots / 3]);
+ }
+
+ return theResult;
+}
+
+inline FLOAT EvaluateBezierKeyframe(FLOAT inTime, FLOAT inTime1, FLOAT inValue1, FLOAT inC1Time,
+ FLOAT inC1Value, FLOAT inC2Time, FLOAT inC2Value, FLOAT inTime2,
+ FLOAT inValue2)
+{
+
+ // The special case of C1Time=0 and C2Time=0 is used to indicate Studio-native animation.
+ // Studio uses a simplified version of the bezier animation where the time control points
+ // are equally spaced between the starting and ending times. This avoids calling the expensive
+ // InverseBezierCurve function to find the right 's' given 't'.
+ FLOAT theParameter;
+ if (inC1Time == 0 && inC2Time == 0) {
+ // Special case signaling that it's ok to treat time as "s"
+ // This is done by assuming that Key1Val,Key1C1,Key1C2,Key2Val (aka P0,P1,P2,P3)
+ // are evenly distributed over time.
+ theParameter = (inTime - inTime1) / (inTime2 - inTime1);
+ } else {
+ // Compute the "s" parameter on the Bezier given the time
+ theParameter = EvaluateInverseBezierCurve(inTime1, inC1Time, inC2Time, inTime2, inTime);
+ if (theParameter <= 0.0f)
+ return inValue1;
+ if (theParameter >= 1.0f)
+ return inValue2;
+ }
+
+ return EvaluateBezierCurve(inValue1, inC1Value, inC2Value, inValue2, theParameter);
+}
+}
diff --git a/src/Runtime/Source/System/Include/UICBoundingBox.h b/src/Runtime/Source/System/Include/UICBoundingBox.h
new file mode 100644
index 00000000..b17dff3c
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICBoundingBox.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICVector3.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeMatrix;
+
+//==============================================================================
+/**
+ * Axis aligned 3D bounding box construction and manipulation.
+ *
+ * Initial construction creates an inverted box signifying an Empty box instead
+ * of an infinitely small box at 0,0,0. Keep this in mind when asking for
+ * Min or max on a box that has had no points added to it.
+ *
+ * Transforming a box simply transforms all eight corners to span a new
+ * axis aligned bounding box. Successive transformations can thus create a
+ * non-optimal box, much larger than needed.
+ */
+class CBoundingBox
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ RuntimeVector3 m_Min; ///< box minimum corner point
+ RuntimeVector3 m_Max; ///< box maximum corner point
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CBoundingBox();
+
+public: // Functions
+ BOOL IsEmpty() const;
+ void SetEmpty();
+ void Add(const RuntimeVector3 &inPoint);
+ void Add(const CBoundingBox &inBox);
+ const RuntimeVector3 &GetMin() const;
+ const RuntimeVector3 &GetMax() const;
+ void Transform(const RuntimeMatrix &inMatrix);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICCircularArray.h b/src/Runtime/Source/System/Include/UICCircularArray.h
new file mode 100644
index 00000000..95062bc5
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICCircularArray.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Circular array. Not growable for now.
+ * The "streamlined" interface acts like a resource pool where construction of
+ * item T is minimized.
+ */
+template <class T>
+class CCircularArray
+{
+ //==============================================================================
+ // Types
+ //==============================================================================
+public:
+ typedef T TType; ///< Easy access to template type
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CHAR m_Name[32]; ///< Allows easy ID if it grows too much
+ T *m_Data; ///< Allocated memory containing array data
+ INT32 m_Capacity; ///< Max number of elements possible
+ INT32 m_Count; ///< Current number of elements in array
+
+ INT32 m_Begin; ///< circular list indices
+ INT32 m_End; ///< circular list indices
+
+ // For 32-bit alignment
+ BOOL m_Full; ///< flag to indicate circular list is full
+ BOOL m_Paddings[3]; ///< Padding
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CCircularArray(const INT32 inCapacity = 0, const CHAR *inName = NULL);
+ inline ~CCircularArray();
+
+public: // Management
+ inline INT32 GetCount() const;
+ inline INT32 GetCapacity() const;
+ inline void Clear(const BOOL inRelease = false);
+ inline void Reserve(const INT32 inCapacity);
+
+public: // Stack access
+ inline T &NewEntry();
+ inline void Pop();
+ inline T &Top();
+
+public: // Status
+ BOOL IsEmpty() const;
+ BOOL IsFull() const;
+
+protected: // Internal methods
+ void Increment(INT32 &outIndex);
+ void Decrement(INT32 &outIndex);
+ void UpdateFullStatus();
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "UICCircularArray.inl"
diff --git a/src/Runtime/Source/System/Include/UICCircularArray.inl b/src/Runtime/Source/System/Include/UICCircularArray.inl
new file mode 100644
index 00000000..0d7f081f
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICCircularArray.inl
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+template <typename T> inline
+CCircularArray<T>::CCircularArray( const INT32 inCapacity, const CHAR* inName ) :
+ m_Data( NULL ),
+ m_Capacity( 0 ),
+ m_Count( 0 ),
+ m_Begin( 0 ),
+ m_End( 0 ),
+ m_Full( false )
+{
+ Q3DStudio_sprintf( m_Name, sizeof( m_Name ), "%s", inName ? inName : "CircularArray" );
+ Reserve( inCapacity );
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+template <class T> inline
+CCircularArray<T>::~CCircularArray( )
+{
+ Clear( true );
+}
+
+//==============================================================================
+/**
+ * Get the number of items in the array
+ * @return the number of items in the array
+ */
+template <class T> inline
+INT32 CCircularArray<T>::GetCount( ) const
+{
+ return m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the capacity of the array
+ * @return the capacity of the array
+ */
+template <class T> inline
+INT32 CCircularArray<T>::GetCapacity( ) const
+{
+ return m_Capacity;
+}
+
+//==============================================================================
+/**
+ * Remove all items from the array
+ * @param inRelease if true, release the allocated memory, if false, reset
+ * parameters back to zero.
+ */
+template <class T> inline
+void CCircularArray<T>::Clear( const BOOL inRelease )
+{
+ m_Count = 0;
+ m_Begin = 0;
+ m_End = 0;
+ m_Full = false;
+
+ if ( inRelease )
+ {
+ Q3DStudio_free( m_Data, T, m_Capacity );
+ m_Capacity = 0;
+ m_Data = NULL;
+ }
+}
+
+//==============================================================================
+/**
+ * Change capacity of the array
+ * Assume no expansion for circular array
+ * @param inCapacity the new capacity to set
+ */
+template <class T> inline
+void CCircularArray<T>::Reserve( const INT32 inCapacity )
+{
+ Q3DStudio_ASSERT( !m_Data );
+ T* theData = Q3DStudio_allocate_desc( T, inCapacity, m_Name );
+ m_Data = theData;
+ m_Capacity = inCapacity;
+}
+
+//==============================================================================
+/**
+ * Create a new uninitialized item at the end of the array.
+ * The returned reference is used to initialize the item.
+ * @return a reference to the item
+ */
+template <class T> inline
+T& CCircularArray<T>::NewEntry( )
+{
+ Q3DStudio_ASSERT( !IsFull( ) );
+ T& theResult = m_Data[m_End];
+ Increment( m_End );
+ UpdateFullStatus( );
+ ++m_Count;
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Remove the top entry from the array
+ */
+template <class T> inline
+void CCircularArray<T>::Pop( )
+{
+ Q3DStudio_ASSERT( !IsEmpty( ) );
+ Increment( m_Begin );
+ m_Full = false;
+ --m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the top item from the
+ * @return a reference to the item
+ */
+template <class T> inline
+T& CCircularArray<T>::Top( )
+{
+ Q3DStudio_ASSERT( !IsEmpty( ) );
+ return m_Data[m_Begin];
+}
+
+//==============================================================================
+/**
+ * Check if the array is empty
+ * @return true if empty, false otherwise.
+ */
+template <class T> inline
+BOOL CCircularArray<T>::IsEmpty( ) const
+{
+ return ( m_Begin == m_End ) && !m_Full;
+}
+
+//==============================================================================
+/**
+ * Check if the array is full
+ * @return true if full, false otherwise.
+ */
+template <class T> inline
+BOOL CCircularArray<T>::IsFull( ) const
+{
+ return m_Full;
+}
+
+//==============================================================================
+/**
+ * Increment index of the array
+ * @param outIndex the index to increment
+ */
+template <class T> inline
+void CCircularArray<T>::Increment( INT32& outIndex )
+{
+ ++outIndex;
+ // circular list wrap-around
+ if ( outIndex >= m_Capacity )
+ outIndex = 0;
+}
+
+//==============================================================================
+/**
+ * Decrement index of the array
+ * @param outIndex the index to decrement
+ */
+template <class T> inline
+void CCircularArray<T>::Decrement( INT32& outIndex )
+{
+ --outIndex;
+ // circular list wrap-around
+ if ( outIndex < 0 )
+ outIndex = m_Capacity - 1;
+}
+
+//==============================================================================
+/**
+ * Update the status of the m_Full flag.
+ * This is an internal method for use ONLY AFTER a item has been added to the array.
+ */
+template <class T> inline
+void CCircularArray<T>::UpdateFullStatus( )
+{
+ m_Full = ( m_End == m_Begin );
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICColor.h b/src/Runtime/Source/System/Include/UICColor.h
new file mode 100644
index 00000000..b917f46b
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICColor.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Express a color and transparency using 32 bits.
+ */
+class CColor
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ union {
+ UINT32 m_Color; ///< 32bit representation of the color
+ struct
+ {
+ UINT8 m_Red; ///< Red component 0-255
+ UINT8 m_Green; ///< Green component 0-255
+ UINT8 m_Blue; ///< Blue component 0-255
+ UINT8 m_Alpha; ///< Transparency component 0-255
+ };
+ };
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CColor(const UINT32 inColor);
+ CColor(const UINT8 inRed = 255, const UINT8 inGreen = 255, const UINT8 inBlue = 255,
+ const UINT8 inAlpha = 255);
+
+public: // Setters
+ void SetColor(const UINT32 inColor) { m_Color = inColor; }
+ void SetRed(const UINT8 inRed) { m_Red = inRed; }
+ void SetGreen(const UINT8 inGreen) { m_Green = inGreen; }
+ void SetBlue(const UINT8 inBlue) { m_Blue = inBlue; }
+ void SetAlpha(const UINT8 inAlpha) { m_Alpha = inAlpha; }
+
+public: // Getters
+ UINT32 GetColor() const { return m_Color; }
+ UINT8 GetRed() const { return m_Red; }
+ UINT8 GetGreen() const { return m_Green; }
+ UINT8 GetBlue() const { return m_Blue; }
+ UINT8 GetAlpha() const { return m_Alpha; }
+
+public: // Utilities
+ void Interpolate(const CColor &inColor1, const CColor &inColor2, const FLOAT inFactor);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICConfig.h b/src/Runtime/Source/System/Include/UICConfig.h
new file mode 100644
index 00000000..563d7c9c
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICConfig.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// This file should only contain macros that configure the build environment
+// and build options.
+//==============================================================================
+#include "UICMemorySettings.h"
+
+/// Number of chars to evaluate when generating a hash from a string.
+/// Verify that hash strings are unique after changing this value.
+#ifndef HASH_LIMIT
+#define HASH_LIMIT 100
+#endif // HASH_LIMIT
+
+/// Define this macro use use sync primitives(mutex/critical sections) when accessing
+/// shared data structures
+#ifndef Q3DStudio_USE_SYNC_PRIMITIVES
+#define Q3DStudio_USE_SYNC_PRIMITIVES 1
+#endif // Q3DStudio_USE_SYNC_PRIMITIVES
diff --git a/src/Runtime/Source/System/Include/UICCubicRoots.h b/src/Runtime/Source/System/Include/UICCubicRoots.h
new file mode 100644
index 00000000..f522aa93
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICCubicRoots.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#pragma message( \
+ "AKCubicRoots.h -- Changes to this file necessitate rebuilding the studio UICDM project and running the unit tests")
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Wrapper class to functions that solve cubic equations.
+ *
+ * The function suite is taken from Graphics Gems:
+ * Roots3And4.c
+ *
+ * Utility functions to find cubic and quartic roots,
+ * coefficients are passed like this:
+ *
+ * c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0
+ *
+ * The functions return the number of non-complex roots and
+ * put the values into the s array.
+ *
+ * Author: Jochen Schwarze (schwarze@isa.de)
+ *
+ * Jan 26, 1990 Version for Graphics Gems
+ * Oct 11, 1990 Fixed sign problem for negative q's in SolveQuartic
+ * (reported by Mark Podlipec),
+ * Old-style function definitions,
+ * IsZero() as a macro
+ * Nov 23, 1990 Some systems do not declare acos() and cbrt() in
+ * <math.h>, though the functions exist in the library.
+ * If large coefficients are used, EQN_EPS should be
+ * reduced considerably (e.g. to 1E-30), results will be
+ * correct but multiple roots might be reported more
+ * than once.
+ */
+class CCubicRoots
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ static INT32 SolveQuadric(FLOAT inConstants[3], FLOAT outSolutions[2]);
+ static INT32 SolveCubic(FLOAT inConstants[4], FLOAT outSolutions[3]);
+ // static int SolveQuartic( FLOAT c[5], FLOAT s[4] );
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICCubicRootsImpl.h b/src/Runtime/Source/System/Include/UICCubicRootsImpl.h
new file mode 100644
index 00000000..72a512b0
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICCubicRootsImpl.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma message( \
+ "AKCubicRootsImpl.h -- Changes to this file necessitate rebuilding the studio UICDM project and running the unit tests")
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants used by the functions
+//==============================================================================
+const FLOAT M_PHI = 3.14159265358979323846f;
+
+/* epsilon surrounding for near zero values */
+const FLOAT EQN_EPS = 1e-9f;
+
+#define ISZERO(x) ((x) > -EQN_EPS && (x) < EQN_EPS)
+
+// cube-root
+#ifndef CUBEROOT
+#define CUBEROOT(x) \
+ ((x) > 0.0 ? static_cast<FLOAT>(pow((x), 1.0f / 3.0f)) \
+ : ((x) < 0.0 ? -static_cast<FLOAT>(pow(-(x), 1.0f / 3.0f)) : 0.0f))
+#endif
+
+//==============================================================================
+/**
+ * Find the root/s to a quadratic equation.
+ *
+ * The equation is of the form: c[2]*x^2 + c[1]*x + c[0] = 0
+ * Note that this will fail if c[2] is zero, or this is a linear equation.
+ *
+ * @param inConstants The array of constants to the equation; see form above
+ * @param outSolutions The array of solutions to the equation
+ * @return the number of solutions for the equation
+ */
+INT32 CCubicRoots::SolveQuadric(FLOAT inConstants[3], FLOAT outSolutions[2])
+{
+#ifdef _PERF_LOG
+ PerfLogMathEvent1 thePerfLog(DATALOGGER_CUBICROOT);
+#endif
+ FLOAT theP, theQ, theD;
+ INT32 theResult = 0;
+
+ /* normal form: x^2 + px + theQ = 0 */
+
+ theP = inConstants[1] / (2 * inConstants[2]);
+ theQ = inConstants[0] / inConstants[2];
+
+ theD = theP * theP - theQ;
+
+ if (ISZERO(theD)) {
+ outSolutions[0] = -theP;
+ theResult = 1;
+ } else if (theD < 0.0f) {
+ theResult = 0;
+ } else if (theD > 0.0f) {
+ FLOAT theSquareRootD = sqrtf(theD);
+
+ outSolutions[0] = theSquareRootD - theP;
+ outSolutions[1] = -theSquareRootD - theP;
+ theResult = 2;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Find the root/s to a cubic equation.
+ *
+ * The equation is of the form: c[3]*x^3 + c[2]*x^2 + c[1]*x + c[0] = 0
+ * Note that this will fail if c[3] is zero, or this is a quadratic equation.
+ *
+ * @param inConstants The array of constants to the equation; see form above
+ * @param outSolutions The array of solutions to the equation
+ * @return the number of solutions for the equation
+ */
+INT32 CCubicRoots::SolveCubic(FLOAT inConstants[4], FLOAT outSolutions[3])
+{
+#ifdef _PERF_LOG
+ PerfLogMathEvent1 thePerfLog(DATALOGGER_CUBICROOT);
+#endif
+
+ INT32 theResult;
+ FLOAT theSubstitute;
+ FLOAT theVariableA, theVariableB, theVariableC;
+ FLOAT theASquared, theVariableP, theVariableQ;
+ FLOAT thePCubed, theVariableD;
+
+ /* normal form: x^3 + Ax^2 + Bx + C = 0 */
+
+ theVariableA = inConstants[2] / inConstants[3];
+ theVariableB = inConstants[1] / inConstants[3];
+ theVariableC = inConstants[0] / inConstants[3];
+
+ /* substitute x = y - A/3 to eliminate quadric term:
+ x^3 +px + q = 0 */
+
+ theASquared = theVariableA * theVariableA;
+ theVariableP = 1.0f / 3.0f * (-1.0f / 3.0f * theASquared + theVariableB);
+ theVariableQ = 1.0f / 2.0f * (2.0f / 27.0f * theVariableA * theASquared
+ - 1.0f / 3.0f * theVariableA * theVariableB + theVariableC);
+
+ /* use Cardano's formula */
+
+ thePCubed = theVariableP * theVariableP * theVariableP;
+ theVariableD = theVariableQ * theVariableQ + thePCubed;
+
+ if (ISZERO(theVariableD)) {
+ if (ISZERO(theVariableQ)) /* one triple solution */
+ {
+ outSolutions[0] = 0;
+ theResult = 1;
+ } else /* one single and one double solution */
+ {
+ FLOAT theVariableU = CUBEROOT(-theVariableQ);
+ outSolutions[0] = 2.0f * theVariableU;
+ outSolutions[1] = -theVariableU;
+ theResult = 2;
+ }
+ } else if (theVariableD < 0.0f) /* Casus irreducibilis: three real solutions */
+ {
+ FLOAT thePhi = 1.0f / 3.0f * static_cast<FLOAT>(acos(-theVariableQ / sqrtf(-thePCubed)));
+ FLOAT theVariableT = 2.0f * sqrtf(-theVariableP);
+
+ outSolutions[0] = theVariableT * static_cast<FLOAT>(cos(thePhi));
+ outSolutions[1] = -theVariableT * static_cast<FLOAT>(cos(thePhi + M_PHI / 3.0f));
+ outSolutions[2] = -theVariableT * static_cast<FLOAT>(cos(thePhi - M_PHI / 3.0f));
+ theResult = 3;
+ } else /* one real solution */
+ {
+ FLOAT theSquareRootD = sqrtf(theVariableD);
+ FLOAT theVariableU = CUBEROOT(theSquareRootD - theVariableQ);
+ FLOAT theVariableV = -CUBEROOT(theSquareRootD + theVariableQ);
+
+ outSolutions[0] = theVariableU + theVariableV;
+ theResult = 1;
+ }
+
+ /* resubstitute */
+ theSubstitute = 1.0f / 3.0f * theVariableA;
+
+ for (INT32 theIndex = 0; theIndex < theResult; ++theIndex)
+ outSolutions[theIndex] -= theSubstitute;
+
+ return theResult;
+}
+
+}; // namespace Q3DStudio \ No newline at end of file
diff --git a/src/Runtime/Source/System/Include/UICDLLManager.h b/src/Runtime/Source/System/Include/UICDLLManager.h
new file mode 100644
index 00000000..d670af2e
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICDLLManager.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+
+#ifdef _PCPLATFORM
+#pragma warning(push, 3)
+#include <windows.h>
+#pragma warning(pop)
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+#ifdef _PCPLATFORM
+typedef HMODULE DLLHANDLE;
+#endif
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+typedef void *DLLHANDLE;
+#endif
+
+typedef struct _SDLLInfo
+{
+ long m_Type; ///< Plugin type
+ DLLHANDLE m_Handle; ///< DLL handle
+
+ _SDLLInfo()
+ : m_Type(0)
+ , m_Handle(NULL)
+
+ {
+ }
+
+} SDLLInfo;
+
+//==============================================================================
+/**
+ * Loads DLLs and queries for DLL functions
+ */
+class CDLLManager
+{
+public:
+ static CDLLManager &GetDLLManager();
+
+protected:
+ CDLLManager();
+ virtual ~CDLLManager();
+
+public:
+ long LoadLibrary(const char *inLibraryPath, long inPluginType);
+ void UnloadLibrary(const long inHandle);
+ void *GetProc(const char *inProcName, long inHandle);
+ template <typename EEnumType>
+ EEnumType GetPluginType(long inHandle);
+ void Cleanup();
+
+protected:
+ void *GetProc(const char *inProcName, const DLLHANDLE inHandle);
+
+protected:
+ CArray<Q3DStudio::SDLLInfo> m_LoadedLibraries;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICDataLogger.h b/src/Runtime/Source/System/Include/UICDataLogger.h
new file mode 100644
index 00000000..9127bdfc
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICDataLogger.h
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _DATA_LOGGER_H_
+#define _DATA_LOGGER_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTypes.h"
+#include "UICDataLoggerEnums.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+typedef TTimeUnit TDataLoggerTimeUnit;
+
+//==============================================================================
+/**
+* The structure that holds all the info we collect
+*/
+struct SPerfLogEntry
+{
+ UINT32 m_EntryEnum : 31;
+ UINT32 m_StartBool : 1;
+
+ TDataLoggerTimeUnit m_Time;
+
+ SPerfLogEntry(UINT32 inEntryEnum, BOOL inStartFlag, TDataLoggerTimeUnit inTime)
+ : m_EntryEnum(inEntryEnum)
+ , m_StartBool(inStartFlag ? 1U : 0U)
+ , m_Time(inTime)
+ {
+ // Make sure our enums never use the high bit
+ Q3DStudio_ASSERT(false == (inEntryEnum & (1 << 31)));
+ }
+};
+
+//==============================================================================
+/**
+* The stack based helper class that wraps the actually logging of start and end messages
+* for use with start/end time logging.
+*/
+template <typename T>
+class CPerfLogPairedEventWrapper
+{
+public:
+ typedef void (*TLogEntryInternal)(UINT32 inEntryEnum, BOOL inStartFlag);
+
+private:
+ UINT32 m_EntryEnum;
+ static TLogEntryInternal m_InternalLogFunc;
+
+private:
+ static void LogEntry(UINT32 inEntryEnum, BOOL inStartFlag);
+
+public:
+ CPerfLogPairedEventWrapper(UINT32 inEntryEnum);
+ ~CPerfLogPairedEventWrapper();
+
+ static void Enable();
+ static void Disable();
+};
+
+//==============================================================================
+/**
+*/
+class CPerfLogPairedEventWrapperDummy
+{
+public:
+ CPerfLogPairedEventWrapperDummy(UINT32 /*inEntryEnum*/) {}
+ ~CPerfLogPairedEventWrapperDummy() {}
+};
+
+// Dummy structs, so we get one 'type' of class per log event
+// so we can turn things on and off
+struct SPerfLogGeneralEvent1
+{
+};
+struct SPerfLogGeneralEvent2
+{
+};
+
+struct SPerfLogLuaEvent1
+{
+};
+struct SPerfLogLuaMathEvent1
+{
+};
+struct SPerfLogRenderEvent1
+{
+};
+struct SPerfLogSceneEvent1
+{
+};
+
+struct SPerfLogMathEvent1
+{
+};
+struct SPerfLogPresentationEvent1
+{
+};
+struct SPerfLogRenderEvent2
+{
+};
+
+// level 0
+// no profiling at all...
+
+// level 1
+typedef CPerfLogPairedEventWrapper<SPerfLogGeneralEvent1>
+ TPerfLogGeneralEvent1; // Frame, update presentations, update scene, render scene
+typedef CPerfLogPairedEventWrapper<SPerfLogGeneralEvent2>
+ TPerfLogGeneralEvent2; // Event processing and manager updates,
+// call lua function, frame and slide callbacks,
+// opaque, transparent, layer render, finalize drawlist and pick
+// level 2
+typedef CPerfLogPairedEventWrapper<SPerfLogLuaEvent1> TPerfLogLuaEvent1; // Specific lua bindings
+typedef CPerfLogPairedEventWrapper<SPerfLogLuaMathEvent1> TPerfLogLuaMathEvent1; // Lua math events
+typedef CPerfLogPairedEventWrapper<SPerfLogRenderEvent1>
+ TPerfLogRenderEvent1; // More detailed rendering
+typedef CPerfLogPairedEventWrapper<SPerfLogSceneEvent1>
+ TPerfLogSceneEvent1; // More detailed scene update
+
+// level 3
+typedef CPerfLogPairedEventWrapper<SPerfLogMathEvent1> TPerfLogMathEvent1; // vector and matrix math
+typedef CPerfLogPairedEventWrapper<SPerfLogPresentationEvent1>
+ TPerfLogPresentationEvent1; // More detailed scene update
+typedef CPerfLogPairedEventWrapper<SPerfLogRenderEvent2> TPerfLogRenderEvent2; //
+
+// Defines
+#ifdef _PERF_LOG
+#define PerfLogGeneralEvent1(inEventID) TPerfLogGeneralEvent1 thePerfLog(inEventID);
+#define PerfLogGeneralEvent2(inEventID) TPerfLogGeneralEvent2 thePerfLog(inEventID);
+
+#define PerfLogLuaEvent1(inEventID) TPerfLogLuaEvent1 thePerfLog(inEventID);
+#define PerfLogLuaMathEvent1(inEventID) TPerfLogLuaMathEvent1 thePerfLog(inEventID);
+#define PerfLogRenderEvent1(inEventID) TPerfLogRenderEvent1 thePerfLog(inEventID);
+#define PerfLogSceneEvent1(inEventID) TPerfLogSceneEvent1 thePerfLog(inEventID);
+
+#define PerfLogMathEvent1(inEventID) TPerfLogMathEvent1 thePerfLog(inEventID);
+#define PerfLogPresentationEvent1(inEventID) TPerfLogPresentationEvent1 thePerfLog(inEventID);
+#define PerfLogRenderEvent2(inEventID) TPerfLogRenderEvent2 thePerfLog(inEventID);
+#else
+#define PerfLogGeneralEvent1(inEventID)
+#define PerfLogGeneralEvent2(inEventID)
+
+#define PerfLogLuaEvent1(inEventID)
+#define PerfLogLuaMathEvent1(inEventID)
+#define PerfLogRenderEvent1(inEventID)
+#define PerfLogSceneEvent1(inEventID)
+
+#define PerfLogMathEvent1(inEventID)
+#define PerfLogPresentationEvent1(inEventID)
+#define PerfLogRenderEvent2(inEventID)
+#endif
+
+//==============================================================================
+/**
+*/
+class CDataLogger
+{
+private:
+ // App level function to write this out to a stream/file... set externally
+ typedef void (*TDataLoggerWriteFunc)(void *inUserData, SPerfLogEntry inEntry);
+ typedef TDataLoggerTimeUnit (*TGetTimeFunc)(void *inUserData);
+
+public:
+ struct SExternalFunctors
+ {
+ void *m_UserData;
+ TDataLoggerWriteFunc m_WriteFunc;
+ TGetTimeFunc m_GetTimeFunc;
+
+ SExternalFunctors()
+ : m_UserData(NULL)
+ , m_WriteFunc(NULL)
+ , m_GetTimeFunc(NULL)
+ {
+ }
+ };
+
+ enum EDataLoggerLevel {
+ LOG_LEVEL_NONE,
+ LOG_LEVEL_1,
+ LOG_LEVEL_2,
+ LOG_LEVEL_3,
+ LOG_LEVEL_INVALID, // use this if you want to selectively enable or disable loggers
+ };
+
+private:
+ static SExternalFunctors m_Functors;
+ static EDataLoggerLevel m_LogLevel;
+ static BOOL m_Enabled;
+
+public:
+ static void SetFunctors(SExternalFunctors inFunctors);
+ static void LogEntry(UINT32 inEntryEnum, BOOL inStartFlag);
+ static void Enable();
+ static void Disable();
+
+ static void SetLogLevel(EDataLoggerLevel inLogLevel);
+};
+
+} // namespace Q3DStudio
+
+#include "UICDataLogger.hpp"
+
+#endif // _DATA_LOGGER_H_
diff --git a/src/Runtime/Source/System/Include/UICDataLogger.hpp b/src/Runtime/Source/System/Include/UICDataLogger.hpp
new file mode 100644
index 00000000..4a6c4d20
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICDataLogger.hpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* Constructor
+*/
+template <typename T>
+CPerfLogPairedEventWrapper<T>::CPerfLogPairedEventWrapper(UINT32 inEntryEnum)
+ : m_EntryEnum(inEntryEnum)
+{
+ if (m_InternalLogFunc)
+ m_InternalLogFunc(m_EntryEnum, true);
+}
+
+//==============================================================================
+/**
+* Destructor
+*/
+template <typename T>
+CPerfLogPairedEventWrapper<T>::~CPerfLogPairedEventWrapper()
+{
+ if (m_InternalLogFunc)
+ m_InternalLogFunc(m_EntryEnum, false);
+}
+
+//==============================================================================
+/**
+* Logger functions
+*/
+template <typename T>
+void CPerfLogPairedEventWrapper<T>::LogEntry(UINT32 inEntryEnum, BOOL inStartFlag)
+{
+ CDataLogger::LogEntry(inEntryEnum, inStartFlag);
+}
+
+//==============================================================================
+/**
+ * Enable logging
+ */
+template <typename T>
+void CPerfLogPairedEventWrapper<T>::Enable()
+{
+ m_InternalLogFunc = LogEntry;
+}
+
+//==============================================================================
+/**
+* Disable logging
+*/
+template <typename T>
+void CPerfLogPairedEventWrapper<T>::Disable()
+{
+ m_InternalLogFunc = NULL;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICDataLoggerEnums.h b/src/Runtime/Source/System/Include/UICDataLoggerEnums.h
new file mode 100644
index 00000000..c30b0eaa
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICDataLoggerEnums.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _DATA_LOGGER_ENUMS_H_
+#define _DATA_LOGGER_ENUMS_H_
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+// TODO ah - for now, these are all specific to paired events. Later we will
+// extend this to support single events which may or may not have timestamps
+// for example, every matrix multiple would log a single event with no time
+enum EDataLoggerEvents {
+ //
+ DATALOGGER_FRAME, /// Time spent in a application frame ( UpdatePresentations, UpdateScenes, and
+ /// Render )
+
+ // DATALOGGER_FRAME
+ // CRuntime
+ DATALOGGER_UPDATEPRESENTATIONS, /// Time spent updating all presentations
+ DATALOGGER_UPDATESCENES, /// Time spent updating all scenes
+ DATALOGGER_RENDERSCENES, /// Time spent rendering all scenes
+
+ // DATALOGGER_UPDATEPRESENTATIONS
+ // CPresentation::Update
+ DATALOGGER_PROCESSEVENTS, /// Time spent in ProcessEventCommandQueue
+ DATALOGGER_ELEMENTMANAGERUPDATE, /// Time spent in CElementManager::Update doing activate and
+ /// deactivate scans
+ DATALOGGER_ANIMATIONMANAGERUPDATE, /// Time spent in CAnimationManager::Update
+ DATALOGGER_PROCESSFRAMECALLBACKS, /// Time spent in CLuaEngine::ProcessFrameCallbacks
+
+ // More detailed presentation update
+ DATALOGGER_PROCESSCOMMAND, /// xxx
+ DATALOGGER_PROCESSEVENT, /// xxx
+ DATALOGGER_PROCESSEVENTBUBBLING, /// xxx
+
+ // CLuaEngine
+ DATALOGGER_SLIDECALLBACKHELPER, /// xxx
+ DATALOGGER_FRAMECALLBACKSHELPER, /// xxx
+ DATALOGGER_CALLLUAFUNCTION, /// xxx
+ DATALOGGER_CALLLUAFUNCTIONONUPDATE, /// xxx
+
+ // DATALOGGER_UPDATESCENES
+ // CScene::Update
+ DATALOGGER_PROCESSDIRTYLIST, /// Time spent in CScene::ProcessDirtyList
+ DATALOGGER_CALCULATETRANSFORM, /// Time spent in CScene::CalculateGlobalTransform
+ DATALOGGER_SCENEUPDATE, /// Time spent in CScene::Update recursion
+
+ // More detailed scene update
+ DATALOGGER_SCANNODEATTRIBUTES, /// Time
+ DATALOGGER_PUSHNODE, /// Time
+
+ // DATALOGGER_RENDERSCENES
+ // CRenderEngine
+ DATALOGGER_RENDERLAYER, /// Time spent rendering the contents of a layer
+ DATALOGGER_RENDEROPAQUE, /// Time spent rendering all opaque items
+ DATALOGGER_RENDERTRANSPARENT, /// Time spent rendering all transparent items
+ DATALOGGER_FINALIZEDRAWLIST, /// Time spent finalizing the draw list
+ DATALOGGER_PICK, /// Time spent in pick code
+
+ // More detailed rendering
+ DATALOGGER_RENDER_SORTDISTANCE, /// asdf
+ DATALOGGER_RENDER_SETOPACITY, /// asdf
+ DATALOGGER_RENDER_DRAWMODEL, /// asdf
+ DATALOGGER_RENDER_DRAWTEXT, /// asdf
+ DATALOGGER_RENDER_CLEARBUFFER, /// asdf
+ DATALOGGER_RENDER_ZWRITEENABLE, /// asdf
+ DATALOGGER_RENDER_CHECKRESIZE, /// asdf
+ DATALOGGER_RENDER_SETATTRIBUTES, /// asdf
+ DATALOGGER_RENDER_TEXTUPDATE, /// asdf
+ DATALOGGER_RENDER_CAMERAUPDATE, /// asdf
+
+ // super specific low level gl calls
+ DATALOGGER_TEXTURESTATE_APPLY, /// asdf
+ DATALOGGER_GEOMETRY_DRAW, /// asdf
+ DATALOGGER_MATERIAL_APPLY, /// asdf
+ DATALOGGER_SETSHADER, /// asdf
+
+ // Lua vector math
+ DATALOGGER_VECTOR, /// asdf
+ DATALOGGER_MATRIX, /// asdf
+ DATALOGGER_CUBICROOT, /// asdf
+
+ // Misc
+ DATALOGGER_LUA_CALCULATEGLOBALTRANSFORM, /// asdf
+ DATALOGGER_LUA_SETLOCALTRANSFORMMATRIX, /// asdf
+ DATALOGGER_LUA_CLONE, /// asdf
+ DATALOGGER_LUA_EVENTREGISTRATION, /// asdf
+ DATALOGGER_LUA_CHANGEREGISTRATION, /// asdf
+ DATALOGGER_LUA_EVENTCALLBACK, /// asdf
+ DATALOGGER_LUA_CHANGECALLBACK, /// asdf
+ DATALOGGER_LUA_FINDCALLBACKDATA, /// asdf
+ DATALOGGER_LUA_SETATTRIBUTE, /// asdf
+ DATALOGGER_LUA_GETATTRIBUTE, /// asdf
+ DATALOGGER_LUA_HASATTRIBUTE, /// asdf
+ DATALOGGER_LUA_GETELEMENT, /// asdf
+
+ DATALOGGER_LUA_GETCURRENTSLIDE, /// asdf
+ DATALOGGER_LUA_GETTIME, /// asdf
+
+ DATALOGGER_LUA_FIRECOMMAND, /// Play, pause, goto time etc
+ DATALOGGER_LUA_GOTOTIME, /// Play
+ DATALOGGER_LUA_GOTOSLIDE, /// Play
+
+ // Lua vector math
+ DATALOGGER_LUA_VECTOR, /// asdf
+ DATALOGGER_LUA_MATRIX, /// asdf
+
+ // Data binding stuff
+ DATALOGGER_LUA_GETRECORD, /// asdf
+ DATALOGGER_LUA_GETRECORDS, /// asdf
+ DATALOGGER_LUA_GETINTERFACE, /// asdf
+ DATALOGGER_LUA_GETRECORDINTERFACE, /// asdf
+ DATALOGGER_LUA_GETFIELDS, /// asdf
+ DATALOGGER_LUA_GETRECORDFIELD, /// asdf
+
+ DATALOGGER_LUA_SCRIPTA, /// asdf
+ DATALOGGER_LUA_SCRIPTB, /// asdf
+ DATALOGGER_LUA_SCRIPTC, /// asdf
+ DATALOGGER_LUA_SCRIPTD, /// asdf
+ DATALOGGER_LUA_SCRIPTE, /// asdf
+ DATALOGGER_LUA_SCRIPTF, /// asdf
+ DATALOGGER_LUA_SCRIPTG, /// asdf
+ DATALOGGER_LUA_SCRIPTH, /// asdf
+ DATALOGGER_LUA_SCRIPTI, /// asdf
+ DATALOGGER_LUA_SCRIPTJ, /// asdf
+ //
+ DATALOGGER_COUNTERTEST, /// Time spent in counter test code
+ DATALOGGER_COUNTERTESTX, /// Time spent in counter test code
+
+ DATALOGGEREVENTCOUNT /// Event count
+};
+
+// CPerfLogPairedEventWrapperx thePerfLog( xxx );
+
+} // namespace Q3DStudio
+
+#endif // _DATA_LOGGER_ENUMS_H_
diff --git a/src/Runtime/Source/System/Include/UICDataLoggerViewer.h b/src/Runtime/Source/System/Include/UICDataLoggerViewer.h
new file mode 100644
index 00000000..b8b7271b
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICDataLoggerViewer.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AKDATALOGGERVIEWER_H_INCLUDED
+#define AKDATALOGGERVIEWER_H_INCLUDED
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTypes.h"
+#include "UICDataLogger.h"
+#include "UICDataLoggerEnums.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+// Helps interpret and analyse data logger entries
+class CDataLoggerViewer
+{
+public:
+ typedef CArray<SPerfLogEntry> TPerfLogEntryList;
+
+public:
+ CDataLoggerViewer(TPerfLogEntryList *inPerfLogEntryList);
+ CDataLoggerViewer(const char *inFilename);
+ virtual ~CDataLoggerViewer();
+
+public:
+ float GetAverageTimeInMsForEntry(enum EDataLoggerEvents inEventType);
+ void ResetPerfLogEntry(enum EDataLoggerEvents inEventType);
+ void ResetAllEntries();
+
+public:
+ static bool ProcessKeyEvent(char inKey, TPerfLogEntryList *inList);
+
+protected:
+ TPerfLogEntryList *m_PerfLogEntryList;
+ bool m_Dispose;
+};
+
+} // namespace NVUI
+
+#endif // AKDATALOGGERVIEWER_H_INCLUDED
diff --git a/src/Runtime/Source/System/Include/UICEGLTimer.h b/src/Runtime/Source/System/Include/UICEGLTimer.h
new file mode 100644
index 00000000..6671ad49
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICEGLTimer.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICTimer.h"
+#include "UICTypes.h"
+
+// You have to include egl before including this file.
+
+typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void);
+typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
+extern EGLuint64NV eglSystemTimeFrequency;
+extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNVProc;
+extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNVProc;
+
+namespace Q3DStudio {
+
+struct SEGLTimeProvider : public Q3DStudio::ITimeProvider
+{
+public:
+ Q3DStudio::INT64 m_TimeFrequency;
+ SEGLTimeProvider()
+ : m_TimeFrequency(0)
+ {
+ }
+ virtual Q3DStudio::INT64 GetCurrentTimeMicroSeconds()
+ {
+ // This can be called before EGL is initialized.
+ if (eglGetSystemTimeFrequencyNVProc == NULL || eglGetSystemTimeNVProc == NULL)
+ return 0;
+
+ if (!m_TimeFrequency) {
+ // Time frequency converts to seconds.
+ m_TimeFrequency = eglGetSystemTimeFrequencyNVProc();
+ // We need it to conver to microseconds
+ m_TimeFrequency = m_TimeFrequency / 1000000ULL;
+ }
+ Q3DStudio::INT64 currentTime = eglGetSystemTimeNVProc();
+ currentTime = currentTime / m_TimeFrequency;
+ return currentTime;
+ }
+};
+} \ No newline at end of file
diff --git a/src/Runtime/Source/System/Include/UICEndian.h b/src/Runtime/Source/System/Include/UICEndian.h
new file mode 100644
index 00000000..f8913a72
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICEndian.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2010 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+#define QT3DS_LITTLE_ENDIAN false
+#define QT3DS_BIG_ENDIAN true
diff --git a/src/Runtime/Source/System/Include/UICEulerAngles.h b/src/Runtime/Source/System/Include/UICEulerAngles.h
new file mode 100644
index 00000000..77476bbc
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICEulerAngles.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+namespace Q3DStudio {
+//==============================================================================
+// Description
+//==============================================================================
+// QuatTypes.h - Basic type declarations
+// by Ken Shoemake, shoemake@graphics.cis.upenn.edu
+// in "Graphics Gems IV", Academic Press, 1994
+typedef struct
+{
+ float x, y, z, w;
+} Quat; /* Quaternion */
+typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
+enum QuatPart { X, Y, Z, W };
+typedef Quat EulerAngles; /* (x,y,z)=ang 1,2,3, w=order code */
+
+#define EulFrmS 0
+#define EulFrmR 1
+#define EulFrm(ord) ((unsigned)(ord)&1)
+#define EulRepNo 0
+#define EulRepYes 1
+#define EulRep(ord) (((unsigned)(ord) >> 1) & 1)
+#define EulParEven 0
+#define EulParOdd 1
+#define EulPar(ord) (((unsigned)(ord) >> 2) & 1)
+#define EulSafe "\000\001\002\000"
+#define EulNext "\001\002\000\001"
+#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord) >> 3) & 3)]))
+#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) == EulParOdd)]))
+#define EulAxK(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) != EulParOdd)]))
+#define EulAxH(ord) ((EulRep(ord) == EulRepNo) ? EulAxK(ord) : EulAxI(ord))
+
+// EulGetOrd unpacks all useful information about order simultaneously.
+#define EulGetOrd(ord, i, j, k, h, n, s, f) \
+ { \
+ unsigned o = ord; \
+ f = o & 1; \
+ o = o >> 1; \
+ s = o & 1; \
+ o = o >> 1; \
+ n = o & 1; \
+ o = o >> 1; \
+ i = EulSafe[o & 3]; \
+ j = EulNext[i + n]; \
+ k = EulNext[i + 1 - n]; \
+ h = s ? k : i; \
+ }
+
+// EulOrd creates an order value between 0 and 23 from 4-tuple choices.
+#define EulOrd(i, p, r, f) (((((((i) << 1) + (p)) << 1) + (r)) << 1) + (f))
+
+// Static axes
+// X = 0, Y = 1, Z = 2 ref QuatPart
+#define EulOrdXYZs EulOrd(0, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdXYXs EulOrd(0, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdXZYs EulOrd(0, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdXZXs EulOrd(0, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdYZXs EulOrd(1, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdYZYs EulOrd(1, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdYXZs EulOrd(1, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdYXYs EulOrd(1, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdZXYs EulOrd(2, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdZXZs EulOrd(2, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdZYXs EulOrd(2, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdZYZs EulOrd(2, EulParOdd, EulRepYes, EulFrmS)
+
+// Rotating axes
+#define EulOrdZYXr EulOrd(0, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdXYXr EulOrd(0, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdYZXr EulOrd(0, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdXZXr EulOrd(0, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdXZYr EulOrd(1, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdYZYr EulOrd(1, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdZXYr EulOrd(1, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdYXYr EulOrd(1, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdYXZr EulOrd(2, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdZXZr EulOrd(2, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdXYZr EulOrd(2, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdZYZr EulOrd(2, EulParOdd, EulRepYes, EulFrmR)
+
+#ifndef M_PI
+#define M_PI 3.1415926535898
+#endif
+
+#define TODEG(x) x = (float)(x * 180 / M_PI);
+#define TORAD(x) x = (float)(x / 180 * M_PI);
+
+class CEulerAngleConverter
+{
+private:
+ char m_OrderInfoBuffer[1024];
+
+public:
+ CEulerAngleConverter();
+ virtual ~CEulerAngleConverter();
+
+public:
+ EulerAngles Eul_(float ai, float aj, float ah, int order);
+ Quat Eul_ToQuat(EulerAngles ea);
+ void Eul_ToHMatrix(EulerAngles ea, HMatrix M);
+ EulerAngles Eul_FromHMatrix(HMatrix M, int order);
+ EulerAngles Eul_FromQuat(Quat q, int order);
+
+ // Debug Stuff
+ const char *DumpOrderInfo();
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICFNDTimer.h b/src/Runtime/Source/System/Include/UICFNDTimer.h
new file mode 100644
index 00000000..f29d5e02
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICFNDTimer.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICTimer.h"
+#include "UICTypes.h"
+#include "foundation/Qt3DSTime.h"
+
+namespace Q3DStudio {
+class SUICFNDTimer : public ITimeProvider
+{
+ Q3DStudio::INT64 GetCurrentTimeMicroSeconds() override
+ {
+ return qt3ds::foundation::Time::getCurrentTimeInTensOfNanoSeconds() / 100;
+ }
+};
+}
diff --git a/src/Runtime/Source/System/Include/UICFile.h b/src/Runtime/Source/System/Include/UICFile.h
new file mode 100644
index 00000000..6c3dd75f
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICFile.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Single overridable exit point for all low level file calls.
+ */
+class CFile
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef enum _E_SEEK {
+ E_SEEK_SET = SEEK_SET,
+ E_SEEK_CUR = SEEK_CUR,
+ E_SEEK_END = SEEK_END
+ } E_SEEK;
+
+ typedef TFile *(*TOpen)(const char *inFileName, const char *inMode);
+ typedef int (*TClose)(TFile *inFile);
+ typedef TFileSize (*TRead)(void *inBuffer, TFileSize inSize, TFileSize inCount, TFile *inFile);
+ typedef TFileSize (*TWrite)(const void *inBuffer, TFileSize inSize, TFileSize inCount,
+ TFile *inFile);
+ typedef long (*TTell)(TFile *inFile);
+ typedef int (*TSeek)(TFile *inFile, long inOffset, int inOrigin);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static TOpen s_Open; ///< function pointer to fopen operation
+ static TClose s_Close; ///< function pointer to fclose operation
+ static TRead s_Read; ///< function pointer to fread operation
+ static TWrite s_Write; ///< function pointer to fwrite operation
+ static TTell s_Tell; ///< function pointer to ftell operation
+ static TSeek s_Seek; ///< function pointer to fseek operation
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Memory override
+ static void SetFileFunctions(const TOpen inOpen, const TClose inClose, const TRead inRead,
+ const TWrite inWrite, const TTell inTell, const TSeek inSeek);
+
+public: // Function access
+ static TOpen Open() { return s_Open; }
+ static TClose Close() { return s_Close; }
+ static TRead Read() { return s_Read; }
+ static TWrite Write() { return s_Write; }
+ static TTell Tell() { return s_Tell; }
+ static TSeek Seek() { return s_Seek; }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICFileStream.h b/src/Runtime/Source/System/Include/UICFileStream.h
new file mode 100644
index 00000000..e0837fbb
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICFileStream.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICIFileStream.h"
+#include "UICArray.h"
+#include "UICEndian.h"
+
+#include <QtCore/QString>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * File stream base class.
+ */
+class CFileStream : public IFileStream
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CFileStream(const CHAR *inFilePath = NULL, const CHAR *inMode = "rb",
+ BOOL inKeepTrying = false);
+ virtual ~CFileStream();
+
+public: // Serializing
+ INT32 ReadRawCopy(void *inDestination, const UINT32 inByteCount) override;
+ INT32 ReadRaw(const void *&inPtr, const UINT32 inByteCount) override;
+ INT32 WriteRaw(const void *inSource, const UINT32 inByteCount) override;
+
+ // Seeking
+ void Offset(const INT32 inOffset) override;
+ TStreamPosition Current() override;
+ void Set(const TStreamPosition &inPosition) override;
+
+public: // File Operation
+ void Open(const CHAR *inFilePath, const CHAR *inMode) override;
+ void Close() override;
+ BOOL IsOpen() const override;
+ const CHAR *GetFilePath() const override;
+
+public: // Endianess
+ void SetEndian(const BOOL inEndian);
+ BOOL GetEndian();
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ TFile *m_FileStream;
+ QString m_FilePath;
+ CArray<UINT8> m_TempBuffer;
+ BOOL m_Endian;
+ BOOL m_KeepTrying;
+ CHAR m_Unused[2]; ///< (padding)
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICFixedArray.h b/src/Runtime/Source/System/Include/UICFixedArray.h
new file mode 100644
index 00000000..befc7ab5
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICFixedArray.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#ifdef _INTEGRITYPLATFORM
+#include <QtCore/QDebug>
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Fixed size Ordered Collection that doesn't support growing.
+ */
+template <class T, int Size>
+class CFixedArray
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef T TType; ///< Easy access to template type
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ T m_Data[Size]; ///< Allocated memory containing array data
+ INT32 m_Capacity; ///< Max number of elements possible
+ INT32 m_Count; ///< Current number of elements in array
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CFixedArray();
+ inline ~CFixedArray();
+
+public: // Management
+ inline void Clear();
+ inline INT32 GetCount() const;
+ inline INT32 GetCapacity() const;
+
+public: // Stack access
+ inline void Push(const T &inValue);
+ inline const T &Pop();
+
+public: // Array access
+ inline T &operator[](const INT32 inIndex);
+ inline void Remove(const INT32 inIndex);
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "UICFixedArray.inl"
diff --git a/src/Runtime/Source/System/Include/UICFixedArray.inl b/src/Runtime/Source/System/Include/UICFixedArray.inl
new file mode 100644
index 00000000..55242243
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICFixedArray.inl
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+template <class T, int Size>
+inline CFixedArray<T, Size>::CFixedArray()
+ : m_Capacity(Size)
+ , m_Count(0)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+template <class T, int Size>
+inline CFixedArray<T, Size>::~CFixedArray()
+{
+}
+
+//==============================================================================
+/**
+ * Remove all elements in the array
+ */
+template <class T, int Size>
+inline void CFixedArray<T, Size>::Clear()
+{
+ m_Count = 0;
+}
+
+//==============================================================================
+/**
+ * Get current count of T in the array
+ * @return current count of the array
+ */
+template <class T, int Size>
+inline INT32 CFixedArray<T, Size>::GetCount() const
+{
+ return m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the capacity of the array
+ * Capacity reflects the allocated memory size
+ * @return capacity of the array
+ */
+template <class T, int Size>
+inline INT32 CFixedArray<T, Size>::GetCapacity() const
+{
+ return m_Capacity;
+}
+
+//==============================================================================
+/**
+ * Insert T to the end of the array
+ * @param inValue value of datatype T
+ */
+template <class T, int Size>
+inline void CFixedArray<T, Size>::Push(const T &inValue)
+{
+ if (m_Count == m_Capacity) {
+ qWarning("Trying to push to many objects onto a CFixedArray", "Capacity=%d", m_Capacity);
+ return;
+ }
+
+ m_Data[m_Count] = inValue;
+ ++m_Count;
+}
+
+//==============================================================================
+/**
+ * Remove and retrieve T which is at the end of the array
+ * @return value of datatype T
+ */
+template <class T, int Size>
+inline const T &CFixedArray<T, Size>::Pop()
+{
+ if (m_Count == 0)
+ return {};
+
+ --m_Count;
+ return m_Data[m_Count];
+}
+
+//==============================================================================
+/**
+ * Get T at a particular index position of the array.
+ * Need to ensure only valid index is allowed
+ * Clear( ) will set the m_counter = 0
+ * @param inIndex the index of the array
+ * @return reference of value of datatype T
+ */
+template <class T, int Size>
+inline T &CFixedArray<T, Size>::operator[](const INT32 inIndex)
+{
+ Q3DStudio_ASSERT(inIndex < m_Capacity);
+
+ return m_Data[inIndex];
+}
+
+//==============================================================================
+/**
+ * Removes a specific entry from the array.
+ * Moves all entries below it up, expensive.
+ * @param inIndex the index of the entry
+ */
+template <class T, int Size>
+inline void CFixedArray<T, Size>::Remove(const INT32 inIndex)
+{
+ Q3DStudio_memmove(m_Data + inIndex, m_Data + inIndex + 1, sizeof(T) * (m_Count - inIndex - 1));
+ --m_Count;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICFunctionWrappers.h b/src/Runtime/Source/System/Include/UICFunctionWrappers.h
new file mode 100644
index 00000000..8fff62de
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICFunctionWrappers.h
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2010 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* Interface for a function wrapper with an associated cost.
+*/
+class IFunctionWrapper
+{
+public:
+ IFunctionWrapper();
+ virtual ~IFunctionWrapper(){}
+
+public:
+ virtual void Execute() = 0;
+ INT32 GetCost();
+ void SetCost(const INT32 inCost);
+
+protected:
+ INT32 m_Cost;
+};
+
+//==============================================================================
+/**
+* 2 arguments function wrapper
+*/
+template <typename TArg1, typename TArg2>
+class CFunctionWrapper2Args : public IFunctionWrapper
+{
+public:
+ typedef void (*TFunction)(TArg1 inArg1, TArg2 inArg2);
+
+public:
+ CFunctionWrapper2Args(TFunction, TArg1 inArg1, TArg2 inArg2);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+};
+
+// Unused
+/*
+template <typename TArg1, typename TArg2, typename TArg3>
+class CFunctionWrapper3Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3 );
+
+ public:
+ CFunctionWrapper3Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+};
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4>
+class CFunctionWrapper4Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4
+);
+
+ public:
+ CFunctionWrapper4Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3, TArg4 inArg4 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+};
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8>
+class CFunctionWrapper8Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4,
+TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8 );
+
+ public:
+ CFunctionWrapper8Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3, TArg4 inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+ TArg5 m_Arg5;
+ TArg6 m_Arg6;
+ TArg7 m_Arg7;
+ TArg8 m_Arg8;
+};
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8, typename TArg9>
+class CFunctionWrapper9Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4,
+TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8, TArg9 inArg9 );
+
+ public:
+ CFunctionWrapper9Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3, TArg4 inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8, TArg9 inArg9 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+ TArg5 m_Arg5;
+ TArg6 m_Arg6;
+ TArg7 m_Arg7;
+ TArg8 m_Arg8;
+ TArg9 m_Arg9;
+};
+*/
+
+//==============================================================================
+/**
+* 1 argument member function wrapper
+*/
+template <typename TObject, typename TReturn, typename TArg1>
+class CMemberFunctionWrapper1Args : public IFunctionWrapper
+{
+public:
+ typedef TReturn (TObject::*TFunction)(TArg1 inArg1);
+
+public:
+ CMemberFunctionWrapper1Args(TObject *inObject, TFunction inFunction, TArg1 inArg1);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TObject *m_Object;
+ TArg1 m_Arg1;
+};
+
+//==============================================================================
+/**
+* 2 argument member function wrapper
+*/
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2>
+class CMemberFunctionWrapper2Args : public IFunctionWrapper
+{
+public:
+ typedef TReturn (TObject::*TFunction)(TArg1 inArg1, TArg2 inArg2);
+
+public:
+ CMemberFunctionWrapper2Args(TObject *inObject, TFunction inFunction, TArg1 inArg1,
+ TArg2 inArg2);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TObject *m_Object;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+};
+
+//==============================================================================
+/**
+* 6 argument member function wrapper
+*/
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2, typename TArg3,
+ typename TArg4, typename TArg5, typename TArg6>
+class CMemberFunctionWrapper6Args : public IFunctionWrapper
+{
+public:
+ typedef TReturn (TObject::*TFunction)(TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4,
+ TArg5 inArg5, TArg6 inArg6);
+
+public:
+ CMemberFunctionWrapper6Args(TObject *inObject, TFunction inFunction, TArg1 inArg1, TArg2 inArg2,
+ TArg3 inArg3, TArg4 inArg4, TArg5 inArg5, TArg6 inArg6);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TObject *m_Object;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+ TArg5 m_Arg5;
+ TArg6 m_Arg6;
+};
+
+// Implementation
+template <typename TArg1, typename TArg2>
+CFunctionWrapper2Args<TArg1, TArg2>::CFunctionWrapper2Args(TFunction inFunction, TArg1 inArg1,
+ TArg2 inArg2)
+ : m_Function(inFunction)
+ , m_Arg1(inArg1)
+ , m_Arg2(inArg2)
+{
+}
+
+template <typename TArg1, typename TArg2>
+void CFunctionWrapper2Args<TArg1, TArg2>::Execute()
+{
+ m_Function(m_Arg1, m_Arg2);
+}
+
+// Unused
+/*
+template <typename TArg1, typename TArg2, typename TArg3>
+CFunctionWrapper3Args<TArg1, TArg2, TArg3>::CFunctionWrapper3Args( TFunction inFunction, TArg1
+inArg1, TArg2 inArg2, TArg3 inArg3 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 )
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3>
+void CFunctionWrapper3Args<TArg1, TArg2, TArg3>::Execute( )
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3 );
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4>
+CFunctionWrapper4Args<TArg1, TArg2, TArg3, TArg4>::CFunctionWrapper4Args( TFunction inFunction,
+TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 ),
+ m_Arg4( inArg4 )
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4>
+void CFunctionWrapper4Args<TArg1, TArg2, TArg3, TArg4>::Execute( )
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3, m_Arg4 );
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8>
+CFunctionWrapper8Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7,
+TArg8>::CFunctionWrapper8Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4
+inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 ),
+ m_Arg4( inArg4 ),
+ m_Arg5( inArg5 ),
+ m_Arg6( inArg6 ),
+ m_Arg7( inArg7 ),
+ m_Arg8( inArg8 )
+
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8>
+void CFunctionWrapper8Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8>::Execute( )
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7, m_Arg8 );
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8, typename TArg9>
+CFunctionWrapper9Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8,
+TArg9>::CFunctionWrapper9Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4
+inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8, TArg9 inArg9 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 ),
+ m_Arg4( inArg4 ),
+ m_Arg5( inArg5 ),
+ m_Arg6( inArg6 ),
+ m_Arg7( inArg7 ),
+ m_Arg8( inArg8 ),
+ m_Arg9( inArg9 )
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8, typename TArg9>
+void CFunctionWrapper9Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9>::Execute(
+)
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7, m_Arg8, m_Arg9 );
+}
+*/
+
+template <typename TObject, typename TReturn, typename TArg1>
+CMemberFunctionWrapper1Args<TObject, TReturn, TArg1>::CMemberFunctionWrapper1Args(
+ TObject *inObject, TFunction inFunction, TArg1 inArg1)
+ : m_Function(inFunction)
+ , m_Object(inObject)
+ , m_Arg1(inArg1)
+{
+}
+
+template <typename TObject, typename TReturn, typename TArg1>
+void CMemberFunctionWrapper1Args<TObject, TReturn, TArg1>::Execute()
+{
+ (m_Object->*m_Function)(m_Arg1);
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2>
+CMemberFunctionWrapper2Args<TObject, TReturn, TArg1, TArg2>::CMemberFunctionWrapper2Args(
+ TObject *inObject, TFunction inFunction, TArg1 inArg1, TArg2 inArg2)
+ : m_Function(inFunction)
+ , m_Object(inObject)
+ , m_Arg1(inArg1)
+ , m_Arg2(inArg2)
+{
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2>
+void CMemberFunctionWrapper2Args<TObject, TReturn, TArg1, TArg2>::Execute()
+{
+ (m_Object->*m_Function)(m_Arg1, m_Arg2);
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2, typename TArg3,
+ typename TArg4, typename TArg5, typename TArg6>
+CMemberFunctionWrapper6Args<TObject, TReturn, TArg1, TArg2, TArg3, TArg4, TArg5,
+ TArg6>::CMemberFunctionWrapper6Args(TObject *inObject,
+ TFunction inFunction, TArg1 inArg1,
+ TArg2 inArg2, TArg3 inArg3,
+ TArg4 inArg4, TArg5 inArg5,
+ TArg6 inArg6)
+ : m_Function(inFunction)
+ , m_Object(inObject)
+ , m_Arg1(inArg1)
+ , m_Arg2(inArg2)
+ , m_Arg3(inArg3)
+ , m_Arg4(inArg4)
+ , m_Arg5(inArg5)
+ , m_Arg6(inArg6)
+{
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2, typename TArg3,
+ typename TArg4, typename TArg5, typename TArg6>
+void CMemberFunctionWrapper6Args<TObject, TReturn, TArg1, TArg2, TArg3, TArg4, TArg5,
+ TArg6>::Execute()
+{
+ (m_Object->*m_Function)(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6);
+}
+}
diff --git a/src/Runtime/Source/System/Include/UICHash.h b/src/Runtime/Source/System/Include/UICHash.h
new file mode 100644
index 00000000..5e7a3544
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICHash.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICConfig.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Utility class transforming a string into a hash value.
+ */
+class CHash
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Static utility
+ //==============================================================================
+ /**
+ * We use the hashing algorithm called "sdbm".
+ *
+ * This algorithm was created from sdbm (a public-domain reimplementation
+ * of ndbm) database library. It was found to do well in scrambling bits,
+ * causing better distribution of the keys and fewer splits. it also happens
+ * to be a good general hashing function with good distribution. the actual
+ * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
+ * is the faster version used in gawk. [there is even a faster, duff-device
+ * version] the magic constant 65599 was picked out of thin air while
+ * experimenting with different constants, and turns out to be a prime. this
+ * is one of the algorithms used in berkeley db (see sleepycat) and elsewhere.
+ *
+ * @param inString the string to hash
+ * @return the hash value
+ */
+ static TStringHash HashString(const CHAR *inString)
+ {
+ TStringHash theHash = 0;
+ INT32 theChar = *inString;
+ INT32 theCount = 0;
+ while (theChar && (theCount < HASH_LIMIT)) {
+ theChar = *inString++;
+ theHash = theChar + (theHash << 6) + (theHash << 16) - theHash;
+ ++theCount;
+ }
+
+ return theHash;
+ }
+
+ //==============================================================================
+ /**
+ * 31-bit hash with MSB set to 0
+ *
+ * @param inString the string to hash
+ * @return the 31-bit hash value
+ */
+ static TEventCommandHash HashEventCommand(const CHAR *inString)
+ {
+ return HashString(inString) & 0x7fffffff;
+ }
+
+ //==============================================================================
+ /**
+ * 26-bit hash with MSBs all set to 0
+ *
+ * @param inString the string to hash
+ * @return the 26-bit hash value
+ */
+ static TAttributeHash HashAttribute(const CHAR *inString)
+ {
+ return HashString(inString) & 0x03ffffff;
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICIFileStream.h b/src/Runtime/Source/System/Include/UICIFileStream.h
new file mode 100644
index 00000000..08d41813
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICIFileStream.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICIStream.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * File stream interface
+ */
+class IFileStream : public IStream
+{
+public:
+ virtual void Open(const CHAR *inFilePath, const CHAR *inMode) = 0;
+ virtual void Close() = 0;
+ virtual BOOL IsOpen() const = 0;
+ virtual const CHAR *GetFilePath() const = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICIStream.h b/src/Runtime/Source/System/Include/UICIStream.h
new file mode 100644
index 00000000..a4c11955
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICIStream.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Pure virtual interface providing the stream for class serialization.
+ */
+class IStream
+{
+ //==============================================================================
+ // Typedef
+ //==============================================================================
+public:
+ typedef INT32 TStreamPosition;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~IStream(){}
+
+public: // Serializing
+ virtual INT32 ReadRawCopy(void *inDestination, const UINT32 inByteCount) = 0;
+ virtual INT32 ReadRaw(const void *&inPtr, const UINT32 inByteCount) = 0;
+ virtual INT32 WriteRaw(const void *inSource, const UINT32 inByteCount) = 0;
+
+ // Seeking
+ virtual void Offset(const INT32 inOffset) = 0;
+ virtual TStreamPosition Current() = 0;
+ virtual void Set(const TStreamPosition &inPosition) = 0;
+
+public: // Template Readers that make a copy
+ template <typename T>
+ INT32 ReadCopy(T &outValue);
+ template <typename T>
+ INT32 ReadArrayCopy(T *outValue, const UINT32 inCount);
+
+public: // Template Readers that access value directly
+ template <typename T>
+ INT32 Read(const T *&inPtr);
+ template <typename T>
+ INT32 ReadArray(const T *&inPtr, UINT32 inCount);
+
+public: // Template Writers
+ template <typename T>
+ INT32 Write(const T &inValue);
+ template <typename T>
+ INT32 WriteArray(const T *inValue, const UINT32 inCount);
+};
+
+/** Notes concerning usage of Read or ReadCopy (and ReadArray and ReadArrayCopy)**/
+/**
+If the value being read fits into 4 bytes (i.e float, int/long), either Read/ReadCopy can be used.
+However, if the read value is going to be accessed frequently (in loops etc), ReadCopy is
+recommended so a copy is available instead of dereferencing.
+
+ReadCopy should be used if the data read is an array or is significantly larger than 4 bytes (like
+vectors or matrixes).
+
+For cases where the value is to be stored in a persistant data structures, ReadCopy should be used.
+
+One important thing about Read/ReadArray, is that the pointer returned is only valid before the next
+Read/ReadyArray is called.
+There is no guarantee that the pointer data will remain unchanged during subsequent calls to
+Read/ReadArray.
+**/
+
+//==============================================================================
+/**
+ * Read and assign a value by copying.
+ */
+template <typename T>
+INT32 IStream::ReadCopy(T &outValue)
+{
+ return ReadRawCopy(&outValue, sizeof(T));
+}
+
+//==============================================================================
+/**
+ * Read and copy data to a preallocated array.
+ */
+template <typename T>
+INT32 IStream::ReadArrayCopy(T *outValue, const UINT32 inCount)
+{
+ return ReadRawCopy(outValue, sizeof(T) * inCount);
+}
+
+//==============================================================================
+/**
+ * Obtain a pointer directly to the data.
+ */
+template <typename T>
+INT32 IStream::Read(const T *&inPtr)
+{
+ return ReadRaw(reinterpret_cast<const void *&>(inPtr), sizeof(T));
+}
+
+//==============================================================================
+/**
+ * Obtain a pointer directly to the array data.
+ */
+template <typename T>
+INT32 IStream::ReadArray(const T *&inPtr, const UINT32 inCount)
+{
+ return ReadRaw(reinterpret_cast<const void *&>(inPtr), sizeof(T) * inCount);
+}
+
+//==============================================================================
+/**
+ * Write a value.
+ */
+template <typename T>
+INT32 IStream::Write(const T &inValue)
+{
+ return WriteRaw(&inValue, sizeof(T));
+}
+
+//==============================================================================
+/**
+ * Write an array of values.
+ */
+template <typename T>
+INT32 IStream::WriteArray(const T *inValue, const UINT32 inCount)
+{
+ return WriteRaw(inValue, sizeof(T) * inCount);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICITimer.h b/src/Runtime/Source/System/Include/UICITimer.h
new file mode 100644
index 00000000..e73fbb95
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICITimer.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * @interface ITimer
+ * The base functionality of the timer used by the Kernel
+ *
+ * Implement this interface per-platform to obtain the required functionality
+ */
+class ITimer
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~ITimer() {}
+
+public: // Operation
+ virtual void Start() = 0;
+ virtual void Stop() = 0;
+ virtual void Reset() = 0;
+ virtual TTimeUnit GetTimeMilliSecs() = 0;
+ virtual TMicroSeconds GetTimeMicroSecs() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMacros.h b/src/Runtime/Source/System/Include/UICMacros.h
new file mode 100644
index 00000000..9233da17
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMacros.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICAssert.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Easy iterations over arrays.
+ * @param array_type element type
+ * @param array_element element variable name getting each entry
+ * @param array_container element array we are traversing
+ */
+#define FOR_ARRAY(array_type, array_element, array_container) \
+ for (array_type *array_element = (array_container).Begin(); \
+ array_element != (array_container).End(); ++array_element)
+
+#define FOR_ARRAY_REVERSE(array_type, array_element, array_container) \
+ for (array_type *array_element = (array_container).End() - 1; \
+ array_element != (array_container).Begin() - 1; --array_element)
+
+//==============================================================================
+/**
+ * Return the smallest of two numbers/objects.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @return a reference, not a copy, to the smallest of the two values
+ */
+template <class T>
+inline const T Q3DStudio_abs(const T &inVal)
+{
+ return inVal >= 0 ? inVal : -inVal;
+}
+
+//==============================================================================
+/**
+ * Return the smallest of two numbers/objects.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @return a reference, not a copy, to the smallest of the two values
+ */
+template <typename T>
+inline const T &Q3DStudio_min(const T &inA, const T &inB)
+{
+ return inA < inB ? inA : inB;
+}
+
+//==============================================================================
+/**
+ * Return the largest of two numbers/objects.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @return a reference, not a copy, to the largest of the two values
+ */
+template <class T>
+inline const T &Q3DStudio_max(const T &inA, const T &inB)
+{
+ return inA > inB ? inA : inB;
+}
+
+//==============================================================================
+/**
+ * Return the smallest of three values.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @param inC a third value to compare
+ * @return a reference, not a copy, to the smallest of the three values
+ */
+template <class T>
+inline const T &Q3DStudio_min3(const T &inA, const T &inB, const T &inC)
+{
+ return inA < inB ? Q3DStudio_min(inA, inC) : Q3DStudio_min(inB, inC);
+}
+
+//==============================================================================
+/**
+ * Return the largest of three values.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @param inC a third value to compare
+ * @return a reference, not a copy, to the largest of the three values
+ */
+template <class T>
+inline const T &Q3DStudio_max3(const T &inA, const T &inB, const T &inC)
+{
+ return inA > inB ? Q3DStudio_max(inA, inC) : Q3DStudio_max(inB, inC);
+}
+
+//==============================================================================
+/**
+ * Make sure a value is in-bounds between two other values.
+ * @param inVal the value to clamp
+ * @param inMin the lowest inclusive value
+ * @param inMax the highest inclusive value
+ * @return a reference to inVal if the value is in bounds,
+ inMin if lower than the minimum value, or
+ inMax if higher than maximum value.
+ */
+template <class T>
+inline const T &Q3DStudio_clamp(const T &inVal, const T &inMin, const T &inMax)
+{
+ if (inVal <= inMin)
+ return inMin;
+ else if (inVal >= inMax)
+ return inMax;
+
+ return inVal;
+}
+
+//==============================================================================
+/**
+ * Return the identified lower and higher values.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @param outMin is assigned to the lower of the two compared values
+ * @param outMax is assigned to the higher of the two compared values
+ */
+template <class T>
+inline void Q3DStudio_minmax(const T &inA, const T &inB, T &outMin, T &outMax)
+{
+ if (inA < inB) {
+ outMin = inA;
+ outMax = inB;
+ } else {
+ outMin = inB;
+ outMax = inA;
+ }
+}
+
+//==============================================================================
+/**
+ * Identify needed parameters that are not currently referenced.
+ */
+#define Q3DStudio_UNREFERENCED_PARAMETER(P) \
+ { \
+ (void)P; \
+ }
+
+//==============================================================================
+/**
+ * Assert
+ */
+#if defined(_DEBUG) || defined(_PROFILE)
+#define Q3DStudio_ASSERT(inExpression) \
+ { \
+ if (!(inExpression)) \
+ Q3DStudio::CAssert::GetFunction()(#inExpression, __FILE__, __LINE__, __FUNCTION__); \
+ }
+#else
+#define Q3DStudio_ASSERT(inExpression) ((void)0)
+#endif // _DEBUG or _PROFILE
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMatrix.h b/src/Runtime/Source/System/Include/UICMatrix.h
new file mode 100644
index 00000000..4ef74420
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMatrix.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeVector3;
+
+//==============================================================================
+/**
+ * A row major matrix for 3D transformation.
+ *
+ * Matrix[row][column]
+@code
+ | 0 1 2 3 | or | 00 01 02 03 | or | Xx Xy Xz w |
+ | 4 5 6 7 | | 10 11 12 13 | | Yx Yy Yz w |
+ | 8 9 A B | | 20 21 22 23 | | Zx Zy Zz w |
+ | C D E F | | 30 31 32 33 | | Tx Ty Tz w |
+@endcode
+ * Rotations are concatenated in the the following order: YXZ
+ * All rotations are clockwise when viewed down the positive axis
+ * towards the origin.
+ */
+class RuntimeMatrix
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+public:
+ enum ERotationOrder {
+ ROTATIONORDER_XYZ = 0,
+ ROTATIONORDER_YZX,
+ ROTATIONORDER_ZXY,
+ ROTATIONORDER_XZY,
+ ROTATIONORDER_YXZ,
+ ROTATIONORDER_ZYX,
+
+ ROTATIONORDER_XYZR,
+ ROTATIONORDER_YZXR,
+ ROTATIONORDER_ZXYR,
+ ROTATIONORDER_XZYR,
+ ROTATIONORDER_YXZR,
+ ROTATIONORDER_ZYXR
+ };
+
+ enum EOrientation { ORIENTATION_LEFT_HANDED = 0, ORIENTATION_RIGHT_HANDED };
+
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ static const RuntimeMatrix IDENTITY; ///< Enabling fast initialization from static identity matrix
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ FLOAT m_Data[4][4]; ///< 16 elements in a 4 x 4
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ RuntimeMatrix(const BOOL inInitializeIdentity = true);
+ RuntimeMatrix(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix(const FLOAT inComponents[4][4]);
+
+public: // Initialization
+ RuntimeMatrix &Zero();
+ RuntimeMatrix &Identity();
+
+ RuntimeMatrix &Set(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix &Set(const FLOAT inComponents[4][4]);
+ RuntimeMatrix &Set(const RuntimeVector3 &inTranslation, const RuntimeVector3 &inRotation, const RuntimeVector3 &inScale,
+ const RuntimeVector3 &inPivot, const UINT8 inRotationOrder,
+ const UINT8 inCoordinateSystem);
+
+ RuntimeMatrix &SetTranslate(const RuntimeVector3 &inTranslate);
+ RuntimeMatrix &SetRotate(const RuntimeVector3 &inRotation, const UINT8 inRotationOrder = ROTATIONORDER_XYZ,
+ const UINT8 inCoordinateSystem = ORIENTATION_LEFT_HANDED);
+ RuntimeMatrix &SetScale(const RuntimeVector3 &inScale);
+
+public: // Functions
+ BOOL IsIdentity() const;
+ BOOL IsAffine() const;
+ RuntimeMatrix &Translate(const RuntimeVector3 &inTranslate);
+ RuntimeMatrix &Scale(const RuntimeVector3 &inScale);
+ RuntimeMatrix &Transpose();
+ FLOAT Invert();
+ RuntimeMatrix &MultiplyAffine(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix &Multiply(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix &FlipCoordinateSystem();
+ RuntimeMatrix &CloneRotation(const RuntimeMatrix &inMatrix, BOOL inMirrorFlag = false);
+ FLOAT SquareDistance(const RuntimeMatrix &inMatrix) const;
+
+public: // Operators
+ RuntimeMatrix &operator=(const RuntimeMatrix &inMatrix);
+ BOOL operator==(const RuntimeMatrix &inMatrix) const;
+ BOOL operator!=(const RuntimeMatrix &inMatrix) const;
+
+public: // Script based accessors
+ inline FLOAT Get(const INT32 inRow, const INT32 inColumn) const
+ {
+ return m_Data[inRow][inColumn];
+ }
+ inline void Set(const INT32 inRow, const INT32 inColumn, const FLOAT inValue)
+ {
+ m_Data[inRow][inColumn] = inValue;
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemory.h b/src/Runtime/Source/System/Include/UICMemory.h
new file mode 100644
index 00000000..42939fdb
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemory.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifndef _INTEGRITYPLATFORM
+#include <memory.h>
+#endif
+#include "UICMemoryHeap.h"
+#include "UICMemoryManager.h"
+#include "UICMemoryFilter.h"
+#include "UICMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Single overridable exit point for all low level memory calls.
+ */
+class CMemory
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef void *(*TMalloc)(size_t inSize);
+ typedef void (*TFree)(void *inPtr);
+ typedef void *(*TRealloc)(void *inPtr, size_t inSize);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static TMalloc s_Malloc; ///< function pointer to malloc operation
+ static TFree s_Free; ///< function pointer to free operation
+ static TRealloc s_Realloc; ///< function pointer to realloc operation
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Memory override
+ static void SetMemoryFunctions(const TMalloc inMalloc, const TFree inFree,
+ const TRealloc inRealloc);
+
+public: // Function access
+ static TMalloc Malloc() { return s_Malloc; }
+ static TFree Free() { return s_Free; }
+ static TRealloc Realloc() { return s_Realloc; }
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Globals
+//==============================================================================
+Q3DStudio::CMemoryManager &GetMemoryManager();
+Q3DStudio::CMemoryHeap &GetMemoryHeap();
+
+//==============================================================================
+// Handlers
+//==============================================================================
+#ifndef Q3DStudio_HANDLER_NEW
+#define Q3DStudio_HANDLER_NEW GetMemoryManager()
+#endif // Q3DStudio_HANDLER_NEW
+
+#ifndef Q3DStudio_HANDLER_ALLOC
+#define Q3DStudio_HANDLER_ALLOC GetMemoryManager()
+#endif // Q3DStudio_HANDLER_ALLOC
+
+#ifndef Q3DStudio_HANDLER_FILTER
+#define Q3DStudio_HANDLER_FILTER GetMemoryManager()
+#endif // Q3DStudio_HANDLER_FILTER
+
+//==============================================================================
+// Q3DStudio new defines
+//==============================================================================
+#undef new
+#undef delete
+
+#ifndef Q3DStudio_new
+#define Q3DStudio_new(type) new (sizeof(type), "class " #type, __FILE__, __LINE__)
+#endif // Q3DStudio_new
+
+#ifndef Q3DStudio_delete
+#define Q3DStudio_delete(ptr, type) \
+ if (ptr) { \
+ reinterpret_cast<type *>(ptr)->~type(); \
+ Q3DStudio_HANDLER_NEW.Free(ptr, sizeof(type)); \
+ }
+#endif // Q3DStudio_delete
+
+#ifndef Q3DStudio_virtual_new
+#define Q3DStudio_virtual_new(type) new ("class " #type, __FILE__, __LINE__)
+#endif // Q3DStudio_virtual_new
+
+#ifndef Q3DStudio_virtual_delete
+#define Q3DStudio_virtual_delete(ptr, type) \
+ if (ptr) { \
+ static_cast<type *>(ptr)->~type(); \
+ Q3DStudio::CMemoryFilter::Free(ptr); \
+ }
+#endif // Q3DStudio_virtual_delete
+
+//==============================================================================
+// Q3DStudio alloc defines
+//==============================================================================
+#ifndef Q3DStudio_allocate
+#define Q3DStudio_allocate(type, count) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Allocate( \
+ static_cast<Q3DStudio::INT32>(sizeof(type) * (count)), #type "[]", __FILE__, __LINE__))
+#endif // Q3DStudio_allocate
+
+#ifndef Q3DStudio_allocate_desc
+#define Q3DStudio_allocate_desc(type, count, desc) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Allocate( \
+ static_cast<Q3DStudio::INT32>(sizeof(type) * (count)), desc, __FILE__, __LINE__))
+#endif // Q3DStudio_allocate_desc
+
+#ifndef Q3DStudio_reallocate
+#define Q3DStudio_reallocate(ptr, type, oldcount, newcount) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Reallocate( \
+ ptr, static_cast<Q3DStudio::INT32>(sizeof(type) * (oldcount)), \
+ static_cast<INT32>(sizeof(type) * (newcount)), #type "[]", __FILE__, __LINE__))
+#endif // Q3DStudio_reallocate
+
+#ifndef Q3DStudio_reallocate_desc
+#define Q3DStudio_reallocate_desc(ptr, type, oldcount, newcount, desc) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Reallocate( \
+ ptr, static_cast<Q3DStudio::INT32>(sizeof(type) * (oldcount)), \
+ static_cast<INT32>(sizeof(type) * (newcount)), desc, __FILE__, __LINE__))
+#endif // Q3DStudio_reallocate_desc
+
+#ifndef Q3DStudio_free
+#define Q3DStudio_free(ptr, type, count) \
+ Q3DStudio_HANDLER_ALLOC.Free(ptr, static_cast<Q3DStudio::INT32>(sizeof(type) * (count)))
+#endif // Q3DStudio_free
+
+//==============================================================================
+// Q3DStudio_new - operator prototypes (5 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, size_t inOfficialSize, const char *inType,
+ const char *inFile, int inLine);
+void operator delete(void *inReportedAddress, size_t inOfficialSize, const char *, const char *,
+ int);
+
+//==============================================================================
+// Q3DStudio_virtual_new and new - operator prototypes (4 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, const char *inType, const char *inFile, int inLine);
+void operator delete(void *inReportedAddress, const char *, const char *, int);
diff --git a/src/Runtime/Source/System/Include/UICMemoryFilter.h b/src/Runtime/Source/System/Include/UICMemoryFilter.h
new file mode 100644
index 00000000..df9367da
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryFilter.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Aggregation interface for legacy calls that don't remember allocation size.
+ *
+ * CMemoryManager and its pools require that the size must be sent along with
+ * any call, including the Free call. Normal memory calls do not require this
+ * information and this filter class is used to intercept these calls and
+ * add a header to each call before forwarded to the manager. This thin class
+ * allows old school calls such as malloc and free to still use the advantages
+ * of a pooled memory system without impacting the cleanliness and memory
+ * footprint of the modern system.
+ */
+class CMemoryFilter
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+protected:
+ const static INT32 FILTER_DOGTAG = 0x1337f1d0;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Allocation Deallocation
+ static void *Allocate(const INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine, const BOOL inClear);
+ static void Free(void *inPointer);
+ static void *Reallocate(void *inPointer, const INT32 inNewSize, const CHAR *inNewType,
+ const CHAR *inFile, const INT32 inLine);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemoryHeap.h b/src/Runtime/Source/System/Include/UICMemoryHeap.h
new file mode 100644
index 00000000..18f15e83
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryHeap.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryProbe.h"
+#include "UICFixedArray.h"
+#include "UICMemorySettings.h"
+
+//==============================================================================
+/**
+ * Low level entry points to the heap.
+ *
+ * Do not call these directly. Use Q3DStudio_new or Q3DStudio_allocate instead since
+ * those use the pools.
+ * @see CMemoryHeap
+ */
+#define Q3DStudio_heap_allocate(size, desc) \
+ Q3DStudio::CMemoryHeap::Allocate(size, desc, __FILE__, __LINE__)
+#define Q3DStudio_heap_reallocate(ptr, oldsize, newsize, newdesc) \
+ Q3DStudio::CMemoryHeap::Reallocate(ptr, oldsize, newsize, newdesc, __FILE__, _LINE__)
+#define Q3DStudio_heap_free(ptr, size) Q3DStudio::CMemoryHeap::Free(ptr, size)
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IStream;
+
+//==============================================================================
+/**
+ * Last memory interface before calls to memory callbacks or OS malloc.
+ *
+ * First of all, don't call this class directy. Use the macros
+ * Q3DStudio_heap_allocate and Q3DStudio_heap_free instead since they fill out file,
+ * line and function parameters for the tracking system.
+ *
+ * This is the single exit point for all heap memory allocations. Change this
+ * code to redirect memory to your own subsystems or add more tracking code to
+ * measure memory usage. Note however that most memory requests during runtime
+ * will never reach this point since memory pools will handle those requests.
+ * Large memory requests and emergency scenarios will still end up here.
+ *
+ * @note This class contains the only three real memory calls in Runtime.
+ */
+class CMemoryHeap
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// Simple memory log entry
+ struct SReportEntry
+ {
+ const void *m_AllocatedPointer; ///< allocated pointer
+ INT32 m_Size; ///< size in bytes
+ const CHAR *m_Description; ///< simple description
+ const CHAR *m_File; ///< filename
+ INT32 m_Line; ///< line number
+ };
+
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef CFixedArray<SReportEntry, Q3DStudio_MEMORY_HEAPTRACKINGSIZE> TMemoryReport;
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static CMemoryProbe s_Probe; ///< Light overall allocation statistics
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ static TMemoryReport s_MemoryReport; ///< Storage for memory logs
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Allocation/Deallocation
+ static void *Allocate(const INT32 inSize, const CHAR *inDescription, const CHAR *inFile,
+ const INT32 inLine);
+ static void Free(void *inPointer, INT32 inSize);
+ static void *Reallocate(void *inPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewDescription, const CHAR *inFile, const INT32 inLine);
+
+public: // Statistics
+ static CMemoryProbe &GetProbe();
+ static TMemoryReport *GetReport();
+
+protected: // Low level memory overview
+ static SReportEntry *FindReport(void *inPointer);
+ static void RemoveReport(void *inPointer);
+
+public: // Report request
+ static void Report(IStream *inStream = NULL);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemoryManager.h b/src/Runtime/Source/System/Include/UICMemoryManager.h
new file mode 100644
index 00000000..b82924db
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryManager.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryPool.h"
+#include "UICMemoryProbe.h"
+#include "UICMemoryTracker.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CMemoryTracker;
+
+//==============================================================================
+/**
+ * Allocation switch-board forwarding requests to pools.
+ *
+ * This is a memory pool hub acting as a complete heap replacement. The number
+ * of pools is hardcoded in Q3DStudio_MEMORY_POOLCOUNT but can be changed with a
+ * recompile. The main manager is created in AKMemory and is preconfigured to
+ * be generous with memory. Tune these values to match your title since
+ * unused chunks are wasteful.
+ *
+ * @note A pool manager survives fine even when not initialized. In this state
+ * it simply forwards each request to the CMemoryHeap. This setup is intentional
+ * to enable the default manager to survive long enough to allow future runtime
+ * initialization based on complexity of the level or presentation being loaded.
+ */
+class CMemoryManager
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// External pool usage information
+ struct SPoolData
+ {
+ CMemoryProbe
+ m_Aligned; ///< Exact sum of memory use (28byte struct in 32byte pool is still 28 here)
+ CMemoryProbe m_Overflow; ///< Failed memory allocation because the pool was full
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CHAR m_Name[32]; ///< Manager identifier for statistics
+ CMemoryPool m_Pool[Q3DStudio_MEMORY_POOLCOUNT]; ///< Actual pool memory objects
+ SPoolData m_ManagerData; ///< Track allocations forwarded to heap because they were too large
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ SPoolData
+ m_PoolData[Q3DStudio_MEMORY_POOLCOUNT]; ///< Trace pools of different sizes with their usage
+ CMemoryProbe::SValue
+ m_Histogram[512]; ///< Allocation histogram if active using Q3DStudio_MEMORY_HEAPTRACKING
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ CMemoryTracker
+ m_LineTracker; ///< Line allocation tracker if active using Q3DStudio_MEMORY_LINETRACKING
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CMemoryManager();
+ CMemoryManager(const CHAR *inName, const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT]);
+ ~CMemoryManager();
+
+public: // Initialization
+ void Initialize(const CHAR *inName, const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT]);
+ void Release();
+
+public: // Allocation and Deallocation
+ void *Allocate(INT32 inSize, const CHAR *inType, const CHAR *inFile, const INT32 inLine);
+ void Free(void *inOldPointer, INT32 inSize);
+ void *Reallocate(void *inOldPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewType, const CHAR *inFile, const INT32 inLine);
+
+protected: // Implementation
+ INT32 FetchPoolIndex(const void *inPointer);
+
+public: // Statistics
+ void Reset();
+ const CHAR *GetName();
+ CMemoryPool &GetPool(const INT32 inPoolIndex);
+ SPoolData *GetPoolData(const INT32 inPoolIndex);
+ SPoolData &GetManagerData();
+ CMemoryProbe GetProbe();
+ CMemoryTracker *GetLineTracker();
+ const CMemoryProbe::SValue *GetHistogram();
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemoryPool.h b/src/Runtime/Source/System/Include/UICMemoryPool.h
new file mode 100644
index 00000000..83bb9047
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryPool.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryProbe.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Managed memory allocation using fixed-size chunks.
+ *
+ * The pool class implements a generic algorithm that favors reusing recently
+ * used memory chunks instead of returning memory continously. Yet, a fresh
+ * pool will always return chunks positioned side by side.
+ *
+ * If a chunk is freed it will be the first to be returned next time a fresh
+ * chunk is new'ed. This makes the cache lines happier. Deleted chunks are
+ * maintained by linking to each other instead of being stored in a separate
+ * memory consuming array.
+ */
+class CMemoryPool
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ INT32 m_ChunkSize; ///< size in bytes of each chunk
+ INT32 m_ChunkCount; ///< number of chunks in pool
+
+ INT8 *m_Ceiling; ///< ceiling memory pointer
+ INT8 *m_Memory; ///< base memory pointer, INT8 for easy pointer arithemtic
+ INT8 *m_Top; ///< edge of free continous memory
+ void *m_Hole; ///< first dis-continous memory chunk if any
+
+ CMemoryProbe m_Probe; ///< call and byte data on pool usage
+ CHAR m_Description[32]; ///< short description of this pool
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CMemoryPool();
+ ~CMemoryPool();
+
+public: // Initialization
+ void Initialize(const CHAR *inName, const INT32 inChunkSize, const INT32 inChunkCount);
+ void Release();
+
+public: // Allocation and Deallocation
+ void *Allocate();
+ void Free(void *inChunk);
+ BOOL IsFull() const;
+ BOOL OwnsChunk(const void *inChunk) const;
+
+protected: // Implementation
+ void *UseTop();
+ void PushHole(void *inChunk);
+ void *PopHole();
+
+public: // Statistics and reports
+ INT32 GetFreeHoles() const;
+ INT32 GetFreeTops() const;
+ INT32 GetFreeChunks() const;
+ INT32 GetChunkSize() const { return m_ChunkSize; }
+ INT32 GetChunkCount() const { return m_ChunkCount; }
+ CMemoryProbe &GetProbe() { return m_Probe; }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemoryProbe.h b/src/Runtime/Source/System/Include/UICMemoryProbe.h
new file mode 100644
index 00000000..a628be0f
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryProbe.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include "UICMacros.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Memory Tracking Enums
+//==============================================================================
+
+/// Track a value - remembering peak and add/del count
+enum EMemoryValue {
+ MEMVALUE_ADDS = 0, ///< For example: allocation call count or bytes allocated
+ MEMVALUE_DELETES, ///< For example: free call count or bytes deallocated
+ MEMVALUE_PEAK, ///< Peak of the current value since the last reset
+ MEMVALUE_CURRENT, ///< Current count
+ MEMVALUECOUNT
+};
+
+/// Differentiate between full session (global) or since last reset (local)
+enum EMemoryScope {
+ MEMSCOPE_RESET = 0, ///< Since last reset
+ MEMSCOPE_GLOBAL, ///< Since process start
+ MEMSCOPECOUNT
+};
+
+//==============================================================================
+/**
+ * Memory allocation counter tracking bytes or calls.
+ *
+ * A probe instance can be placed to track either number of allocations
+ * or the bytes of each allocation. CMemoryManager and CMemoryHeap both
+ * record statistics using this class. 64 bytes.
+ */
+class CMemoryProbe
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ //==============================================================================
+ /**
+ * Intelligent number that tracks current, peak, incr. and decr.
+ *
+ * This value remembers how the amount added, the amount deleted, the highest
+ * value, while keeping a current value. These are used by CMemoryProbe when
+ * tracking memory allocations.
+ */
+ struct SValue
+ {
+ // Fields
+ INT32 m_Value[MEMVALUECOUNT]; ///< Four aspects (add,del,current,peak) we are tracking
+
+ // Methods
+ SValue() { Reset(); }
+ void Reset()
+ {
+ m_Value[MEMVALUE_ADDS] = 0;
+ m_Value[MEMVALUE_DELETES] = 0;
+ m_Value[MEMVALUE_PEAK] = 0;
+ m_Value[MEMVALUE_CURRENT] = 0;
+ }
+
+ void Delete(INT32 inAmount)
+ {
+ Q3DStudio_ASSERT(inAmount >= 0);
+ m_Value[MEMVALUE_DELETES] += inAmount;
+ m_Value[MEMVALUE_CURRENT] -= inAmount;
+ }
+
+ void Add(INT32 inAmount)
+ {
+ Q3DStudio_ASSERT(inAmount >= 0);
+ m_Value[MEMVALUE_ADDS] += inAmount;
+ m_Value[MEMVALUE_CURRENT] += inAmount;
+ m_Value[MEMVALUE_PEAK] =
+ Q3DStudio_max(m_Value[MEMVALUE_PEAK], m_Value[MEMVALUE_CURRENT]);
+ }
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ SValue m_Calls[MEMSCOPECOUNT]; ///< Memory call count
+ SValue m_Bytes[MEMSCOPECOUNT]; ///< Memory allocation amount
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Constructor
+ CMemoryProbe();
+ ~CMemoryProbe();
+
+public: // Operations
+ void Reset();
+ void Allocate(const INT32 inByteAmount);
+ void Free(const INT32 inByteAmount);
+ void Combine(const CMemoryProbe &inProbe);
+
+public: // Accessors
+ INT32 GetCalls(const EMemoryScope inScope, const EMemoryValue inValue) const
+ {
+ return m_Calls[inScope].m_Value[inValue];
+ }
+ INT32 GetBytes(const EMemoryScope inScope, const EMemoryValue inValue) const
+ {
+ return m_Bytes[inScope].m_Value[inValue];
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemorySettings.h b/src/Runtime/Source/System/Include/UICMemorySettings.h
new file mode 100644
index 00000000..03d2d8d2
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemorySettings.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * GlobalMemoryManager constants
+ * NOTE THAT THESE NUMBERS BELOW SHOULD BE ADJUSTED TO FIT YOUR APPLICATION.
+ *
+ * See the Memory Management section in the documentation for guidelines
+ * on memory diagnostics that enable you to optimize these values:
+ */
+
+//==============================================================================
+// Memory Pool Configuration
+//==============================================================================
+
+#ifndef Q3DStudio_MEMORY_POOLCOUNT
+#define Q3DStudio_MEMORY_POOLCOUNT 12
+#endif // Q3DStudio_MEMORY_POOLCOUNT
+
+/// A memory pool has a chunk size that defines he size in bytes of each slot
+/// and a chunk count defining how many slots there are of that size.
+/// The pools below thus has 128 slots of 4 bytes, 256 slots of 8 bytes etc:
+const INT32 g_ChunkSize[Q3DStudio_MEMORY_POOLCOUNT] = { 4, 8, 16, 32, 48, 64,
+ 96, 128, 160, 256, 384, 640 };
+const INT32 g_ChunkCount[Q3DStudio_MEMORY_POOLCOUNT] = { 128, 256, 256, 1536, 128, 128,
+ 256, 64, 32, 32, 32, 32 };
+
+//==============================================================================
+// Memory Settings
+//==============================================================================
+
+/// Define the upper memory limit used by Runtime.
+/// 0 = unlimited
+#ifndef Q3DStudio_MEMORY_LIMIT
+#define Q3DStudio_MEMORY_LIMIT 0
+#endif // Q3DStudio_MEMORY_LIMIT
+
+// Pool sizes and diagnostics are aligned to the required boundary.
+#ifndef Q3DStudio_MEMORY_ALIGNMENT
+#define Q3DStudio_MEMORY_ALIGNMENT 8
+#endif // Q3DStudio_MEMORY_ALIGNMENT
+
+//==============================================================================
+// Memory Diagnostics
+//==============================================================================
+
+/// Note that the simple report is always on. (F1 in Quarterback)
+
+/// CMemoryHeap usage report. (F2 in Quarterback)
+/// Tracks large allocations such as pool buffers, managers and overflows.
+/// Not much overhead since most allocations should be intercepted by pools.
+#ifndef Q3DStudio_MEMORY_HEAPTRACKING
+#define Q3DStudio_MEMORY_HEAPTRACKING 0
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+/// Max number of 20 byte SReportEntry heap entries
+/// Increase this number if you get a log warning but you should really tune
+/// your memory pools to avoid hitting the heap.
+#ifndef Q3DStudio_MEMORY_HEAPTRACKINGSIZE
+#define Q3DStudio_MEMORY_HEAPTRACKINGSIZE 4000
+#endif // Q3DStudio_MEMORY_HEAPTRACKINGSIZE
+
+/// Invasive allocation tracker. (F3 in Quarterback)
+/// Track detailed memory usage per allocation through CMemoryManager by tracking
+/// every Runtime allocation, line by line using __FILE__ and __LINE__.
+/// Note that this adds a 16byte SMemoryInfo to each allocation and thus
+/// changes pool usage.
+/// === Do not tune pools with line tracking enabled! ===
+#ifndef Q3DStudio_MEMORY_LINETRACKING
+#define Q3DStudio_MEMORY_LINETRACKING 0
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+// Hashbin size of entries pointing to SMemoryInfo allocation headers
+#ifndef Q3DStudio_MEMORY_LINETRACKINGSIZE
+#define Q3DStudio_MEMORY_LINETRACKINGSIZE (128 * 1024)
+#endif // Q3DStudio_MEMORY_LINETRACKINGSIZE
+
+/// CMemoryManager pooled memory usage report. (F5-F8 in Quarterback)
+/// Track most used allocation sizes to tune pool sizes and count.
+/// Enabled by default since it allows tracking precise presentation
+/// memory usage without much of an overhead.
+/// It also includes a histogram when showing Reset data (F5,F6)
+#ifndef Q3DStudio_MEMORY_POOLTRACKING
+#ifdef _DEBUG
+#define Q3DStudio_MEMORY_POOLTRACKING 1
+#else
+#define Q3DStudio_MEMORY_POOLTRACKING 0
+#endif
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemoryStatistics.h b/src/Runtime/Source/System/Include/UICMemoryStatistics.h
new file mode 100644
index 00000000..30983ad9
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryStatistics.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryManager.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Static facade to memory statistics and allocation tracking data.
+ *
+ * Use this class to examine the memory state of the system at any point.
+ * Heap, managers and pools are are connected to this point by registering
+ * themselves on creation. Initiate the extraction of the collected data
+ * using this interface.
+ */
+class CMemoryStatistics
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ const static INT32 REPORTSIZE = 256; ///< Max size of single report string
+ const static INT32 MANAGERCOUNT = 5; ///< Fixed number of managers tracked
+ const static INT32 HISTOGRAMCOUNT = 10; ///< Fixed number of managers tracked
+
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// One row of statistics on allocation
+ struct SFactoid
+ {
+ CHAR m_Name[32]; ///< Ascii identifier - manager name or pool description
+ INT32 m_Bytes; ///< Bytes used - full pool size for example - zero if factoid unused
+ INT32 m_Calls; ///< Function calls, i.e number of allocations
+ INT32 m_Used; ///< Discrete chunk usage in percent - 10 used of 200 gives a value 5
+ INT32 m_Align; ///< Packed efficiency in percent - all 24byte structs in 32byte pool give a
+ ///value 75
+ INT32 m_Miss; ///< Allocation misses - due to full pools for example
+ };
+
+ /// Tuple describing one data point in a histogram
+ struct SHistogramScore
+ {
+ INT32 m_Size; ///< Allocation request in bytes
+ INT32 m_Count; ///< Number of allocation requests
+ };
+
+ /// Set of factoids describing a system memory state
+ struct SFactSheet
+ {
+ SFactoid m_HeapState; ///< Heap facts
+ SFactoid m_ManagerState; ///< Combined manager facts
+ SFactoid m_Manager[MANAGERCOUNT]; ///< Individual manager facts
+ SHistogramScore m_Histogram[MANAGERCOUNT][HISTOGRAMCOUNT]; ///< Top allocation requests
+ ///sorted by bytes, global and
+ ///never reset
+ SFactoid m_Pool[MANAGERCOUNT][Q3DStudio_MEMORY_POOLCOUNT]; ///< Individual pool facts
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static INT32 s_Overhead; ///< Memory tracking structures report in here
+ static CMemoryManager
+ *s_PoolManagers[MANAGERCOUNT]; ///< Pointers to all created memory pool managers
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Registration
+ static void AddManager(CMemoryManager *inManager);
+ static void RemoveManager(CMemoryManager *inManager);
+ static INT32 &Overhead();
+
+public: // Access
+ static void Reset();
+ static void GetFacts(SFactSheet &outFacts, const BOOL inPeak = false,
+ const BOOL inGlobal = false);
+ static INT32 GetRequestedBytes(const BOOL inPeak = false);
+ static INT32 GetHeapBytes(const BOOL inPeak = false);
+
+public: // Reporting
+ static void SimpleReport(IStream *inStream = NULL);
+ static void HeapReport(IStream *inStream = NULL);
+ static void PoolReport(const BOOL inPeak = false, const BOOL inGlobal = false,
+ IStream *inStream = NULL);
+ static void LineReport(IStream *inStream = NULL);
+
+ static void FullReport(IStream *inStream = NULL);
+ static void Report(IStream *inStream, const CHAR *inString);
+
+protected: // Utility
+ static void CullHistogram(const CMemoryProbe::SValue *inHistogram, const EMemoryValue inValue,
+ SHistogramScore outResults[HISTOGRAMCOUNT]);
+ static int CompareHeap(const void *arg1, const void *arg2);
+ static int CompareHistogram(const void *arg1, const void *arg2);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICMemoryTracker.h b/src/Runtime/Source/System/Include/UICMemoryTracker.h
new file mode 100644
index 00000000..ee6ce699
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICMemoryTracker.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Low level memory statistics tracking each individual allocation.
+ *
+ * This class is instantiated in each CMemoryManager if tracking is enabled
+ * by setting ENABLE_MEMORY_LINETRACKING to 1 in AKConfig.h for the build
+ * configuration you want.
+ *
+ * Tracking is much more invasive than simple statistics since it records each
+ * individual allocation and deallocation. The overhead can be seen mostly in
+ * the memory load since we store a tracking hashbin of all memory allocation
+ * and a 16 byte SMemoryInfo structure is prepended to each allocation no matter
+ * how small. This mode should be used when debugging memory to track down
+ * individual allocations. It's turned off by default and should stay off
+ * most of the time.
+ *
+ * The tracking information is usually dumped to a comma delimited .csv file
+ * for easy viewing as a spreadsheet of data. This action is initiated by
+ * pressing CTRL-F1 in Quarterback on the PC but can be added to any viewer
+ * by calling CMemoryStatistics::TrackingDump.
+ */
+class CMemoryTracker
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ const static UINT16 TRACKER_DOGTAG = 0xbead; ///< Watch guard value in SMemoryTrackInfo
+
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// 16 bytes of details on each allocation when tracking is enabled
+ struct SMemoryInfo
+ {
+ UINT16 m_DogTag; ///< 0xbead - asserting this to track overwrites
+ INT16 m_Line; ///< line from which the allocation occurred
+ INT32 m_Size; ///< allocation size in bytes
+ const CHAR *m_File; ///< file from which the allocation occurred
+ const CHAR *m_Type; ///< type of allocation, usually class name
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ INT32 m_TrackingOverhead; ///< memory used to track allocations in bytes
+ SMemoryInfo *m_TrackingHashBin[Q3DStudio_MEMORY_LINETRACKINGSIZE]; ///< hash table of all
+ ///tracked allocations
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CMemoryTracker();
+ ~CMemoryTracker();
+
+public: // Tracking
+ void Remember(SMemoryInfo *inData);
+ void Forget(SMemoryInfo *inData);
+
+public: // Reporting
+ INT32 Report(IStream *inStream = NULL);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICPlatformSpecific.h b/src/Runtime/Source/System/Include/UICPlatformSpecific.h
new file mode 100644
index 00000000..3fc34016
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICPlatformSpecific.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#if defined(_PCPLATFORM)
+
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf _snprintf
+#define Q3DStudio_stricmp(inStr1, inStr2) _stricmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) _strnicmp(inStr1, inStr2, inCount)
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy_s(inDest, inSize, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat_s(inDest, inSize, inSource)
+#define Q3DStudio_fopen fopen_s
+#define Q3DStudio_sleepmillisec(inMillisec) Sleep(inMillisec)
+#define Q3DStudio_getpid GetCurrentProcessId
+
+#elif defined(_TEGRAPLATFORM)
+
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf _snprintf
+#define Q3DStudio_stricmp(inStr1, inStr2) _stricmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) _strnicmp(inStr1, inStr2, inCount)
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy_s(inDest, inSize, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat_s(inDest, inSize, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) fopen_s(inFilePtr, inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) Sleep(inMillisec)
+#define Q3DStudio_getpid GetCurrentProcessId
+
+#elif defined(_XENONPLATFORM)
+
+#include <xtl.h>
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+//#define Q3DStudio_memcpy( inDest, inSource, inCount ) XMemCpy( inDest, inSource,
+//static_cast<SIZE_T>( inCount ) )
+//#define Q3DStudio_memset( inDest, inChar, inCount ) XMemSet( inDest, inChar,
+//static_cast<SIZE_T>( inCount ) )
+#define Q3DStudio_sprintf _snprintf
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress) __dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy_s(inDest, inSize, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat_s(inDest, inSize, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) fopen_s(inFilePtr, inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) Sleep(inMillisec)
+#define Q3DStudio_getpid GetCurrentProcessId
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) _strnicmp(inStr1, inStr2, inCount)
+#define Q3DStudio_stricmp(inStr1, inStr2) _stricmp(inStr1, inStr2)
+
+#elif defined(_PS3PLATFORM)
+
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf snprintf
+#define Q3DStudio_tolower std::tolower
+#define Q3DStudio_restrict
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy(inDest, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat(inDest, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) *(inFilePtr) = fopen(inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) \
+ { \
+ struct timespec theSleepTime = { inMillisec / 1000, (inMillisec % 1000) * 1000000 }; \
+ ::nanosleep(&theSleepTime, NULL); \
+ }
+#define Q3DStudio_getpid getpid
+#define Q3DStudio_stricmp(inStr1, inStr2) strcasecmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) strncasecmp(inStr1, inStr2, inCount)
+
+#elif defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#include <time.h>
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf snprintf
+#define Q3DStudio_stricmp(inStr1, inStr2) strcasecmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) strncasecmp(inStr1, inStr2, inCount)
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy(inDest, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat(inDest, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) *(inFilePtr) = fopen(inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) \
+ { \
+ struct timespec theSleepTime = { inMillisec / 1000, (inMillisec % 1000) * 1000000 }; \
+ ::nanosleep(&theSleepTime, NULL); \
+ }
+#define Q3DStudio_getpid getpid
+
+#else
+#error "A platform must be defined"
+#endif
+
+//==============================================================================
+/** @def Q3DStudio_dcbt( inOffset, inAddress )
+ * @brief Data Cache Block Touch - Loads the block of memory containing
+ * the specified address into the data cache.
+ *
+ * A program uses the dcbt instruction to request a cache block fetch before
+ * it is actually needed by the program. This prevents stalls in the pipeline.
+ */
+
+//==============================================================================
+/** @def Q3DStudio_restrict
+ * @brief Cross platform macro for pointer aliasing.
+ *
+ * Performance Implications of Pointer Aliasing
+ *
+ * Doug Cook
+ * Silicon Graphics, Inc.
+ * August, 1997
+ *
+ * Pointer aliasing can have a severe impact on program performance.
+ * Understanding its implications is critical to writing high-performance code.
+ * This document provides a brief introduction to the problem, and suggests
+ * several approaches to solving it through source-code restructuring, compiler
+ * options, and C or C++ language extensions.
+ *
+ * *Aliasing*
+ *
+ * Here's a brief overview of aliasing. Consider the following function:
+ *
+ * void process_data(float *in, float *out, float gain, int nsamps)
+ * {
+ * int i;
+ * for (i = 0; i < nsamps; i++) {
+ * out[i] = in[i] * gain;
+ * }
+ * }
+ *
+ * In C or C++, it is legal for the parameters in and out to point to
+ * overlapping regions in memory. When this happens, in and out are said to be
+ * aliases. When the compiler optimizes the function, it does not in general
+ * know whether in and out are aliases. It must therefore assume that any
+ * store through out can affect the memory pointed to by in, which severely
+ * limits its ability to reorder or parallelize the code (For some simple
+ * cases, the compiler could analyze the entire program to determine that two
+ * pointers cannot be aliases. But in general, it is impossible for the
+ * compiler to determine whether or not two pointers are aliases, so to be
+ * safe, it must assume that they are).
+ */
diff --git a/src/Runtime/Source/System/Include/UICSyncPrimitive.h b/src/Runtime/Source/System/Include/UICSyncPrimitive.h
new file mode 100644
index 00000000..72ec0456
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICSyncPrimitive.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifdef _MSC_VER
+#pragma warning(push, 2)
+#endif //_MSC_VER
+
+#ifdef _PCPLATFORM
+#include <windows.h>
+#elif _XENONPLATFORM
+#include <process.h> // which one we need??
+#include <xtl.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif //_MSC_VER
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+typedef void *TLockPrimitive;
+
+//==============================================================================
+/**
+ * The CSyncPrimitive is a wrapper class to handle syncronization of data
+ * between threads.
+ */
+class CSyncPrimitive
+{
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ TLockPrimitive m_LockHandle;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ CSyncPrimitive();
+ ~CSyncPrimitive();
+
+public:
+ int BeginSync();
+ int EndSync();
+};
+
+//==============================================================================
+/**
+ * Wrap the lock and unlocking of a sync primitive in an easy to use stack
+ * based class.
+ */
+class CSyncGuard
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ CSyncPrimitive &m_Mutex;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private:
+ CSyncGuard(const CSyncGuard &other);
+ CSyncGuard &operator=(const CSyncGuard &other);
+
+public:
+ CSyncGuard(CSyncPrimitive &inMutex)
+ : m_Mutex(inMutex)
+ {
+ m_Mutex.BeginSync();
+ }
+ ~CSyncGuard() { m_Mutex.EndSync(); }
+};
+
+} // namespace Q3DStudio
+
+//===================================================================
+// The application needs to provide these thread primitive functions
+//===================================================================
+
+void AppCreateLockPrimitive(Q3DStudio::TLockPrimitive *inPrimitive);
+void AppDestroyLockPrimitive(Q3DStudio::TLockPrimitive *inPrimitive);
+void AppBeginSync(Q3DStudio::TLockPrimitive inPrimitive);
+void AppEndSync(Q3DStudio::TLockPrimitive inPrimitive); \ No newline at end of file
diff --git a/src/Runtime/Source/System/Include/UICThreadManager.h b/src/Runtime/Source/System/Include/UICThreadManager.h
new file mode 100644
index 00000000..884e9812
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICThreadManager.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include "UICThreadSafeScratchpad.h"
+#include "UICThreadSafeQueue.h"
+#include "UICArray.h"
+
+namespace Q3DStudio {
+//==============================================================================
+// Fields specific to the thread manager
+//==============================================================================
+
+// NOTE: The order that these are defined matters (specifically, the relationship
+// between the struct forward declare, struct definition, and function pointer.
+
+// TODO - ah
+// The interaction between these is not that clear... comment stuff!!
+
+struct SThreadResultItem;
+struct SThreadWorkItem;
+
+typedef CThreadSafeQueue<SThreadWorkItem> TThreadWorkQueue;
+typedef CThreadSafeQueue<SThreadResultItem> TThreadResultQueue;
+
+// The function to call when a work item is 'finished'
+typedef void (*TThreadFinishFunction)(void *inUserData, CThreadSafeScratchPad &inScratchPad);
+
+// This encapsulates a 'result'.
+struct SThreadResultItem
+{
+ void *m_UserData;
+ TThreadFinishFunction m_Function;
+};
+typedef SThreadResultItem (*TThreadWorkFunction)(void *inUserData,
+ CThreadSafeScratchPad &inScratchPad);
+
+struct SThreadWorkItem
+{
+ UINT32 m_WorkItemNameHash; ///< Used to identify a class of work items we can remove them from
+ ///time to time.
+ void *m_UserData;
+ TThreadWorkFunction m_Function;
+};
+
+typedef void *TThreadID;
+typedef void *(*TThreadSpinFunction)(void *inUserData);
+
+//==============================================================================
+/**
+* The thread manager is the interface to create work on other threads and
+* process the completed results. This is done abstractly through work and
+* result items.
+*/
+class CThreadManager
+{
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ CThreadSafeScratchPad m_ScratchPad;
+ TThreadWorkQueue m_WorkQueue;
+ TThreadResultQueue m_ResultsQueue;
+ CArray<TThreadID> m_Threads;
+ INT32 m_WorkItems; // running count
+ volatile BOOL m_Running;
+ BOOL m_Unused[3];
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ CThreadManager(INT32 inThreads);
+ ~CThreadManager();
+
+public: // Interface
+ INT32 Update();
+ void Push(const SThreadWorkItem &inItem);
+ // Remove all work items of a certain class. This returns
+ // an array containing the removed items.
+ void Remove(UINT32 inItemNameHash, CArray<SThreadWorkItem> &ioRemovedItems);
+
+ CThreadSafeScratchPad &GetScratchPad();
+
+private:
+ bool Pop(SThreadResultItem &outItem);
+ static void *ThreadSpinFunction(void *inUserData);
+ void DoWork();
+ void CheckForCompletedWork();
+};
+
+} // namespace Q3DStudio
+
+//===================================================================
+// The application needs to provide these thread primitive functions
+//===================================================================
+
+Q3DStudio::TThreadID AppCreateThread(Q3DStudio::TThreadSpinFunction inFunc, void *inUserData);
+void AppDestroyThread(Q3DStudio::TThreadID inThreadID);
+void AppSleepThread();
diff --git a/src/Runtime/Source/System/Include/UICThreadSafeQueue.h b/src/Runtime/Source/System/Include/UICThreadSafeQueue.h
new file mode 100644
index 00000000..2ca71daf
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICThreadSafeQueue.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICSyncPrimitive.h"
+#include "UICArray.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Thread safe queue that wraps using a sync primitive when it accesses
+ * it's internals.
+ */
+template <typename T>
+class CThreadSafeQueue
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ CSyncPrimitive m_Primitive;
+ CArray<T> m_QueueData;
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ CThreadSafeQueue(const CThreadSafeQueue &other);
+ CThreadSafeQueue &operator=(const CThreadSafeQueue &other);
+
+public:
+ CThreadSafeQueue() {}
+ void Push(const T &inItem);
+ bool Pop(T &outItem);
+ INT32 GetCount();
+
+ //=========================================================================
+ // Remove items that correspond to a given predicate.
+ // The predicate is a functor that takes a const reference and returns either
+ // true or false.
+ template <typename TPredFunc>
+ void Remove(TPredFunc predicate, CArray<T> &ioOutRemovedItems);
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "UICThreadSafeQueue.inl"
diff --git a/src/Runtime/Source/System/Include/UICThreadSafeQueue.inl b/src/Runtime/Source/System/Include/UICThreadSafeQueue.inl
new file mode 100644
index 00000000..84501916
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICThreadSafeQueue.inl
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Safely push an object onto the queue
+ */
+template <typename T>
+inline void CThreadSafeQueue<T>::Push(const T &inItem)
+{
+ CSyncGuard theGuard(m_Primitive);
+ m_QueueData.Push(inItem);
+}
+
+//==============================================================================
+/**
+* Safely pop an object off the queue
+*/
+template <typename T>
+inline bool CThreadSafeQueue<T>::Pop(T &outItem)
+{
+ CSyncGuard theGuard(m_Primitive);
+ if (m_QueueData.GetCount()) {
+ outItem = m_QueueData[0];
+ m_QueueData.Remove(0);
+ return true;
+ }
+ return false;
+}
+
+//==============================================================================
+/**
+ * Get the count queue count
+ */
+template <typename T>
+INT32 CThreadSafeQueue<T>::GetCount()
+{
+ CSyncGuard theGuard(m_Primitive);
+ return m_QueueData.GetCount();
+}
+
+template <typename T>
+template <typename TPredFunc>
+inline void CThreadSafeQueue<T>::Remove(TPredFunc predicate, CArray<T> &ioOutRemovedItems)
+{
+ CSyncGuard theGuard(m_Primitive);
+ for (INT32 index = m_QueueData.GetCount() - 1; index >= 0; --index) {
+ const T &item = m_QueueData[index];
+ if (predicate(item)) {
+ ioOutRemovedItems.Push(item);
+ m_QueueData.Remove(index);
+ }
+ }
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICThreadSafeScratchpad.h b/src/Runtime/Source/System/Include/UICThreadSafeScratchpad.h
new file mode 100644
index 00000000..fb7c0bd0
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICThreadSafeScratchpad.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICSyncPrimitive.h"
+#include "UICArray.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Definition of a scratch pad buffer
+ */
+struct SThreadScratchPadBuffer
+{
+ INT32 m_Size;
+ INT32 m_RequestedSize;
+ CHAR *m_Data;
+};
+
+//==============================================================================
+/**
+ * This class wraps up a simple thread safe buffer manager class. This
+ * has two functions that threaded
+ */
+class CThreadSafeScratchPad
+{
+ //==============================================================================
+ // Private Methods
+ //==============================================================================
+private:
+ CThreadSafeScratchPad(const CThreadSafeScratchPad &other);
+ CThreadSafeScratchPad &operator=(const CThreadSafeScratchPad &other);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ struct SBufferItem
+ {
+ SThreadScratchPadBuffer m_Buffer;
+ BOOL m_InUse;
+ BOOL m_Unused[3];
+ };
+
+ CArray<SBufferItem> m_Buffers;
+ CSyncPrimitive m_Primitive;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ CThreadSafeScratchPad() {}
+ ~CThreadSafeScratchPad();
+
+ // Not a threadsafe call; used for testing purposes.
+ INT32 GetBufferCount() const { return (INT32)m_Buffers.GetCount(); }
+ SThreadScratchPadBuffer GetBuffer(INT32 inMinSize);
+ void ReleaseBuffer(SThreadScratchPadBuffer inBuffer);
+};
+}
+
+#include "UICThreadSafeScratchpad.inl"
diff --git a/src/Runtime/Source/System/Include/UICThreadSafeScratchpad.inl b/src/Runtime/Source/System/Include/UICThreadSafeScratchpad.inl
new file mode 100644
index 00000000..6b26764a
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICThreadSafeScratchpad.inl
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+namespace Q3DStudio
+{
+
+//==============================================================================
+/**
+ * Destructor
+ */
+inline CThreadSafeScratchPad::~CThreadSafeScratchPad()
+{
+ FOR_ARRAY( SBufferItem, theObject, m_Buffers )
+ {
+ free( theObject->m_Buffer.m_Data );
+ }
+ m_Buffers.Clear();
+}
+
+//==============================================================================
+/**
+* Ask the scratch pad that for a to use
+*
+* Possible cases:
+* 1. if there are unused buffers
+ 1.a use the buffer that fits, and wastes the least amount of memory
+ 1.b if no buffers fit, resize the biggest unused buffer
+ 2. if no unused buffers
+ 2.a allocate a new buffer
+*/
+inline SThreadScratchPadBuffer CThreadSafeScratchPad::GetBuffer( INT32 inMinSize )
+{
+ CSyncGuard theGuard( m_Primitive );
+ INT32 theBestIndex = -1;
+ UINT32 theBestIndexWasteSize = static_cast<UINT32>( -1 ); // uint32 max
+
+ INT32 theLargestUnusedBuffer = -1;
+ INT32 theLargestUnusedBufferSize = 0;
+
+ SThreadScratchPadBuffer theReturnBuffer = {0,0};
+
+ if ( inMinSize < 0 )
+ {
+ return theReturnBuffer;
+ }
+
+ INT32 theEnd = m_Buffers.GetCount();
+ for ( INT32 theIndex = 0; theIndex < theEnd; ++theIndex )
+ {
+ SBufferItem& theBufferItem = m_Buffers[theIndex];
+
+ // Unused buffers...
+ if ( false == theBufferItem.m_InUse )
+ {
+ // Best fit unused buffer that will fit the requested size
+ if ( theBufferItem.m_Buffer.m_Size >= inMinSize && static_cast<UINT32>( theBufferItem.m_Buffer.m_Size - inMinSize ) < theBestIndexWasteSize )
+ {
+ theBestIndex = theIndex;
+ theBestIndexWasteSize = static_cast<UINT32>( theBufferItem.m_Buffer.m_Size - inMinSize);
+ }
+ // Biggest unused buffer to resize...
+ else if ( theBufferItem.m_Buffer.m_Size > theLargestUnusedBufferSize )
+ {
+ theLargestUnusedBuffer = theIndex;
+ theLargestUnusedBufferSize = theBufferItem.m_Buffer.m_Size;
+ }
+ }
+ }
+
+
+ // 1.a
+ if ( -1 != theBestIndex )
+ {
+ m_Buffers[theBestIndex].m_InUse = true;
+ theReturnBuffer = m_Buffers[theBestIndex].m_Buffer;
+ }
+ // 1.b
+ else if ( -1 != theLargestUnusedBuffer )
+ {
+ m_Buffers[theLargestUnusedBuffer].m_InUse = true;
+ m_Buffers[theLargestUnusedBuffer].m_Buffer.m_Data =
+ static_cast<CHAR*>( realloc( m_Buffers[theLargestUnusedBuffer].m_Buffer.m_Data,
+ static_cast<size_t>( inMinSize ) )
+ );
+
+ m_Buffers[theLargestUnusedBuffer].m_Buffer.m_Size = inMinSize;
+ theReturnBuffer = m_Buffers[theLargestUnusedBuffer].m_Buffer;
+ }
+ // 2.a
+ else
+ {
+ // Add a new buffer
+ SBufferItem theNewBuffer;
+ theNewBuffer.m_InUse = true;
+ theNewBuffer.m_Buffer.m_Data = static_cast<CHAR*>( malloc( static_cast<size_t>( inMinSize ) ) );
+ theNewBuffer.m_Buffer.m_Size = inMinSize;
+ m_Buffers.Push( theNewBuffer );
+
+ theReturnBuffer = theNewBuffer.m_Buffer;
+ }
+ theReturnBuffer.m_RequestedSize = inMinSize;
+ return theReturnBuffer;
+}
+
+//==============================================================================
+/**
+ * Notify the scratch pad that the buffer is now safe to reuse
+ */
+inline void CThreadSafeScratchPad::ReleaseBuffer( SThreadScratchPadBuffer inBuffer )
+{
+ CSyncGuard theGuard( m_Primitive );
+ if ( inBuffer.m_Data == 0 )
+ return;
+ INT32 theIndex;
+ INT32 theEnd = m_Buffers.GetCount();
+ for ( theIndex = 0; theIndex < theEnd; ++theIndex )
+ {
+ SBufferItem& theBufferItem = m_Buffers[theIndex];
+ if ( theBufferItem.m_Buffer.m_Size == inBuffer.m_Size && theBufferItem.m_Buffer.m_Data == inBuffer.m_Data )
+ {
+ theBufferItem.m_InUse = false;
+ inBuffer.m_RequestedSize = 0;
+ break;
+ }
+ }
+
+ if ( theIndex == theEnd ) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "CThreadSafeScratchPad::ReleaseBuffer: attempting to remove "
+ << "invalid/corrupt buffer. Buffer size: " << inBuffer.m_Size;
+ }
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICTimer.h b/src/Runtime/Source/System/Include/UICTimer.h
new file mode 100644
index 00000000..3d2decfd
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICTimer.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICITimer.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * Time provider interface abstracting time from the usage of time.
+ */
+class ITimeProvider
+{
+protected:
+ virtual ~ITimeProvider() {}
+public:
+ virtual INT64 GetCurrentTimeMicroSeconds() = 0;
+};
+
+// Pause in a way that is completely transparent to the underlying system.
+class CPausingTimeProvider : public ITimeProvider
+{
+ ITimeProvider &m_Provider;
+ INT64 m_PauseOffset;
+ INT64 m_Offset;
+ bool m_Paused;
+
+public:
+ CPausingTimeProvider(ITimeProvider &inProvider)
+ : m_Provider(inProvider)
+ , m_PauseOffset(0)
+ , m_Offset(0)
+ , m_Paused(false)
+ {
+ }
+
+ INT64 GetCurrentTimeMicroSeconds() override
+ {
+ INT64 currentTime = 0;
+ if (m_Paused)
+ currentTime = m_PauseOffset;
+ else
+ currentTime = m_Provider.GetCurrentTimeMicroSeconds();
+
+ return currentTime - m_Offset;
+ }
+
+ void Pause()
+ {
+ if (!m_Paused) {
+ m_Paused = true;
+ m_PauseOffset = m_Provider.GetCurrentTimeMicroSeconds();
+ }
+ }
+
+ void UnPause()
+ {
+ if (m_Paused) {
+ m_Paused = false;
+ INT64 timePaused = m_Provider.GetCurrentTimeMicroSeconds() - m_PauseOffset;
+ m_Offset += timePaused;
+ }
+ }
+
+ bool IsPaused() { return m_Paused; }
+
+ void Reset() { m_PauseOffset = m_Offset = 0; }
+};
+
+//==============================================================================
+/**
+ * @class CTimer
+ * @brief A very simple platform optimized utility class to return lapsed time
+ *
+ * Gets current time based on the time lapsed from the point where timer is started.
+ */
+
+class CTimer : public ITimer
+{
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ ITimeProvider &m_TimeProvider;
+ INT64 m_StartTime;
+ BOOL m_IsRunning; // Whether this timer is running or stopped
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CTimer(ITimeProvider &inProvider);
+
+public: // Operation
+ void Start() override;
+ void Stop() override;
+ void Reset() override;
+ TTimeUnit GetTimeMilliSecs() override;
+ TMicroSeconds GetTimeMicroSecs() override;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICTypes.h b/src/Runtime/Source/System/Include/UICTypes.h
new file mode 100644
index 00000000..6330919c
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICTypes.h
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef bool BOOL; ///< true or false, usually 8 bits
+typedef signed char INT8; ///< A signed 8-bit integer, not a character
+typedef unsigned char UINT8; ///< An unsigned 8-bit integer 0-255, not a character
+typedef signed short INT16; ///< A signed 16-bit integer
+typedef unsigned short UINT16; ///< An unsigned 16-bit integer
+typedef int INT32; ///< A signed 32-bit integer
+typedef unsigned int UINT32; ///< An unsigned 32-bit integer
+typedef float FLOAT; ///< A 32-bit floating point number
+typedef char CHAR; ///< String character, not a number
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+//==============================================================================
+// Max constants and computation
+//==============================================================================
+INT32 Q3DStudio_maxbits(const INT32 inBitCount, const BOOL inUnsigned);
+
+#define AKMAX_INT8 static_cast<INT8>(0x7F)
+#define AKMAX_UINT8 static_cast<UINT8>(0xFF)
+#define AKMAX_INT16 static_cast<INT16>(0x7FFF)
+#define AKMAX_UINT16 static_cast<UINT16>(0xFFFF)
+#define AKMAX_INT32 0x7FFFFFFFL
+#define AKMAX_UINT32 0xFFFFFFFFUL
+
+//==============================================================================
+// Platform specific vectors and matrices
+//==============================================================================
+#if defined(_PCPLATFORM)
+
+typedef FILE TFile;
+typedef size_t TFileSize;
+
+#define Q3DStudio_INT64_C(x) x
+#define Q3DStudio_UINT64_C(x) x
+
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+
+struct VECTOR4
+{
+ union {
+ FLOAT v[4];
+ UINT32 u[4];
+ };
+
+ FLOAT &x() { return v[0]; }
+ FLOAT &y() { return v[1]; }
+ FLOAT &z() { return v[2]; }
+ FLOAT &w() { return v[3]; }
+};
+
+struct MATRIX16
+{
+ union {
+ VECTOR4 v[4];
+ FLOAT m[4][4];
+ FLOAT f[16];
+ };
+
+ FLOAT &_11() { return f[0]; }
+ FLOAT &_12() { return f[1]; }
+ FLOAT &_13() { return f[2]; }
+ FLOAT &_14() { return f[3]; }
+ FLOAT &_21() { return f[4]; }
+ FLOAT &_22() { return f[5]; }
+ FLOAT &_23() { return f[6]; }
+ FLOAT &_24() { return f[7]; }
+ FLOAT &_31() { return f[8]; }
+ FLOAT &_32() { return f[9]; }
+ FLOAT &_33() { return f[10]; }
+ FLOAT &_34() { return f[11]; }
+ FLOAT &_41() { return f[12]; }
+ FLOAT &_42() { return f[13]; }
+ FLOAT &_43() { return f[14]; }
+ FLOAT &_44() { return f[15]; }
+};
+
+#elif defined(_TEGRAPLATFORM)
+
+// TODO: sk - We used both WinCE and OpenKode file system utilities. Using non-OpenKode restores
+// functionality in a hacky way
+// but ultimately sticking to just 1 system would definitely be cleaner.
+typedef FILE TFile;
+typedef size_t TFileSize;
+// typedef KDFile TFile;
+// typedef KDsize TFileSize;
+
+#define Q3DStudio_INT64_C(x) x
+#define Q3DStudio_UINT64_C(x) x
+
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+
+struct VECTOR4
+{
+ union {
+ FLOAT v[4];
+ UINT32 u[4];
+ };
+ FLOAT &x() { return v[0]; }
+ FLOAT &y() { return v[1]; }
+ FLOAT &z() { return v[2]; }
+ FLOAT &w() { return v[3]; }
+};
+
+struct MATRIX16
+{
+ union {
+ VECTOR4 v[4];
+ FLOAT m[4][4];
+ FLOAT f[16];
+ };
+
+ FLOAT &_11() { return f[0]; }
+ FLOAT &_12() { return f[1]; }
+ FLOAT &_13() { return f[2]; }
+ FLOAT &_14() { return f[3]; }
+ FLOAT &_21() { return f[4]; }
+ FLOAT &_22() { return f[5]; }
+ FLOAT &_23() { return f[6]; }
+ FLOAT &_24() { return f[7]; }
+ FLOAT &_31() { return f[8]; }
+ FLOAT &_32() { return f[9]; }
+ FLOAT &_33() { return f[10]; }
+ FLOAT &_34() { return f[11]; }
+ FLOAT &_41() { return f[12]; }
+ FLOAT &_42() { return f[13]; }
+ FLOAT &_43() { return f[14]; }
+ FLOAT &_44() { return f[15]; }
+};
+
+#elif defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+
+typedef FILE TFile;
+typedef size_t TFileSize;
+
+#define Q3DStudio_INT64_C(x) x
+#define Q3DStudio_UINT64_C(x) x
+
+typedef int64_t INT64;
+typedef uint64_t UINT64;
+
+struct VECTOR4
+{
+ union {
+ FLOAT v[4];
+ UINT32 u[4];
+ };
+
+ FLOAT &x() { return v[0]; }
+ FLOAT &y() { return v[1]; }
+ FLOAT &z() { return v[2]; }
+ FLOAT &w() { return v[3]; }
+};
+
+struct MATRIX16
+{
+ union {
+ VECTOR4 v[4];
+ FLOAT m[4][4];
+ FLOAT f[16];
+ };
+
+ FLOAT &_11() { return f[0]; }
+ FLOAT &_12() { return f[1]; }
+ FLOAT &_13() { return f[2]; }
+ FLOAT &_14() { return f[3]; }
+ FLOAT &_21() { return f[4]; }
+ FLOAT &_22() { return f[5]; }
+ FLOAT &_23() { return f[6]; }
+ FLOAT &_24() { return f[7]; }
+ FLOAT &_31() { return f[8]; }
+ FLOAT &_32() { return f[9]; }
+ FLOAT &_33() { return f[10]; }
+ FLOAT &_34() { return f[11]; }
+ FLOAT &_41() { return f[12]; }
+ FLOAT &_42() { return f[13]; }
+ FLOAT &_43() { return f[14]; }
+ FLOAT &_44() { return f[15]; }
+};
+
+#else
+
+#error "A platform must be defined"
+
+#endif
+
+typedef INT64 TMicroSeconds; ///< Time in microseconds
+typedef INT64 TTimeUnit; ///< Time in milliseconds
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Include/UICVector3.h b/src/Runtime/Source/System/Include/UICVector3.h
new file mode 100644
index 00000000..08df028b
--- /dev/null
+++ b/src/Runtime/Source/System/Include/UICVector3.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#ifdef WIN32
+#pragma warning(disable : 4201)
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeMatrix;
+
+//==============================================================================
+/**
+ * 3D vector with automatic notification on change.
+ *
+ * This implementation of a 3D vector along with all the sibling and helper
+ * classes in the geometry section, try to strike a balance between clean code,
+ * ease-of-use and speed. Fields are public and most methods are designed to
+ * give the impression of a very intelligent and capable structure. Heavier
+ * code such as intersections is encouraged to be added externally instead
+ * of here.
+ *
+ * The vector is a member of the geometry classes next to CMatrix and CRotation
+ * @see CMatrix
+ * @see CRotation
+ */
+class RuntimeVector3
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ union {
+ float m[3];
+ struct
+ {
+ float m_X;
+ float m_Y;
+ float m_Z;
+ };
+ };
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ RuntimeVector3();
+ RuntimeVector3(const float inVector[3]);
+ RuntimeVector3(const float inX, const float inY, const float inZ);
+ RuntimeVector3(const RuntimeVector3 &inVector);
+
+public: // Initialization
+ RuntimeVector3 &Set(const float inX, const float inY, const float inZ);
+ RuntimeVector3 &Set(const RuntimeVector3 &inVector);
+
+public: // Functions
+ float DistanceSquared(const RuntimeVector3 &inVector) const;
+ float Distance(const RuntimeVector3 &inVector) const;
+ float LengthSquared() const;
+ float Length() const;
+ float DotProduct(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 &CrossProduct(const RuntimeVector3 &inVector);
+ RuntimeVector3 &Normalize();
+ RuntimeVector3 &Minimize(const RuntimeVector3 &inVector);
+ RuntimeVector3 &Maximize(const RuntimeVector3 &inVector);
+ RuntimeVector3 &InterpolateLinear(const RuntimeVector3 &inDestVector, float inFactor);
+ RuntimeVector3 &Transform(const RuntimeMatrix &inMatrix);
+
+public: // Operators
+ bool operator==(const RuntimeVector3 &inVector) const;
+ bool operator!=(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 operator+(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 operator-(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 operator*(float inFactor) const;
+ RuntimeVector3 &operator=(const RuntimeVector3 &inVector);
+ RuntimeVector3 &operator+=(const RuntimeVector3 &inVector);
+ RuntimeVector3 &operator-=(const RuntimeVector3 &inVector);
+ RuntimeVector3 &operator*=(float inFactor);
+ RuntimeVector3 operator-() const;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/SystemPrefix.cpp b/src/Runtime/Source/System/Source/SystemPrefix.cpp
new file mode 100644
index 00000000..4b631168
--- /dev/null
+++ b/src/Runtime/Source/System/Source/SystemPrefix.cpp
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
diff --git a/src/Runtime/Source/System/Source/UICAssert.cpp b/src/Runtime/Source/System/Source/UICAssert.cpp
new file mode 100644
index 00000000..3ed6cd82
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICAssert.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICAssert.h"
+#include "foundation/Qt3DSLogging.h"
+//==============================================================================
+// Platform Specific Includes
+//==============================================================================
+#if defined(_PCPLATFORM)
+#pragma warning(push, 3)
+#include <Windows.h>
+#include <crtdbg.h>
+#pragma warning(pop)
+#endif // #if defined (_PCPLATFORM)
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Global Variables
+//==============================================================================
+CAssert::TFunction CAssert::s_AssertFunction = CAssert::Default; ///< Default assert function
+
+//==============================================================================
+/**
+ * Default method for asserts
+ */
+void CAssert::Default(const CHAR *inAssert, const CHAR *inFile, INT32 inLine,
+ const CHAR *inFunction)
+{
+ // Use logger to report the string first
+ qCCritical (qt3ds::INTERNAL_ERROR) << "Assertion failed: " << inFile << " " << inLine
+ << " " << inAssert << " " << inFunction;
+
+#if defined(_DEBUG) && defined(_PCPLATFORM)
+ if (_CrtDbgReport(_CRT_ASSERT, inFile, inLine, inFunction, "Assertion Failed") == 1)
+ ::DebugBreak();
+#endif // _DEBUG & _PCPLATFORM
+}
+
+//==============================================================================
+/**
+ * Method for setting the assert function
+ */
+void CAssert::SetFunction(TFunction inAssert)
+{
+ s_AssertFunction = inAssert;
+}
+
+//==============================================================================
+/**
+ * Method for getting the assert function
+ */
+CAssert::TFunction CAssert::GetFunction()
+{
+ return s_AssertFunction;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICBoundingBox.cpp b/src/Runtime/Source/System/Source/UICBoundingBox.cpp
new file mode 100644
index 00000000..9470df4d
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICBoundingBox.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICBoundingBox.h"
+#include "UICMatrix.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor - creates an empty BoundingBox
+ */
+CBoundingBox::CBoundingBox()
+ : m_Min(1.0f, 1.0f, 1.0f)
+ , m_Max(-1.0f, -1.0f, -1.0f)
+{
+}
+
+//==============================================================================
+/**
+ * Make BoundingBox invalid
+ */
+void CBoundingBox::SetEmpty()
+{
+ m_Min.Set(1.0f, 1.0f, 1.0f);
+ m_Max.Set(-1.0f, -1.0f, -1.0f);
+}
+
+//==============================================================================
+/**
+ * Is the BoundingBox empty?
+ * @return true if bounding box is empty, false otherwise
+ */
+BOOL CBoundingBox::IsEmpty() const
+{
+ return (m_Min.m_X > m_Max.m_X);
+}
+
+//==============================================================================
+/**
+ * Add a point to the BoundingBox
+ * @param inPoint a 3D point
+ */
+void CBoundingBox::Add(const RuntimeVector3 &inPoint)
+{
+ if (IsEmpty()) {
+ m_Min = inPoint;
+ m_Max = inPoint;
+ } else {
+ m_Min.Minimize(inPoint);
+ m_Max.Maximize(inPoint);
+ }
+}
+
+//==============================================================================
+/**
+ * Add another BoundingBox to this BoundingBox
+ * @param inBox a 3D BoundingBox
+ */
+void CBoundingBox::Add(const CBoundingBox &inBox)
+{
+ if (!inBox.IsEmpty()) {
+ Add(inBox.GetMin());
+ Add(inBox.GetMax());
+ }
+}
+
+//==============================================================================
+/**
+ * Get the bounding box's smallest position
+ * @return the smallest position of the bounding box
+ */
+const RuntimeVector3 &CBoundingBox::GetMin() const
+{
+ return m_Min;
+}
+
+//==============================================================================
+/**
+ * Get the bounding box's largest position
+ * @return the largest position of the bounding box
+ */
+const RuntimeVector3 &CBoundingBox::GetMax() const
+{
+ return m_Max;
+}
+
+//==============================================================================
+/**
+ * Apply a transform to the BoundingBox
+ * @param inMatrix a 4x4 trasnform matrix
+ */
+void CBoundingBox::Transform(const RuntimeMatrix &inMatrix)
+{
+ // Apply transform to the 8 corners of the BoundingBox and renormalize to majox axes
+ CBoundingBox theTransformedBox;
+ RuntimeVector3 theCorners[8];
+
+ theCorners[0].Set(m_Min.m_X, m_Min.m_Y, m_Min.m_Z);
+ theCorners[1].Set(m_Min.m_X, m_Min.m_Y, m_Max.m_Z);
+ theCorners[2].Set(m_Min.m_X, m_Max.m_Y, m_Min.m_Z);
+ theCorners[3].Set(m_Min.m_X, m_Max.m_Y, m_Max.m_Z);
+ theCorners[4].Set(m_Max.m_X, m_Min.m_Y, m_Min.m_Z);
+ theCorners[5].Set(m_Max.m_X, m_Min.m_Y, m_Max.m_Z);
+ theCorners[6].Set(m_Max.m_X, m_Max.m_Y, m_Min.m_Z);
+ theCorners[7].Set(m_Max.m_X, m_Max.m_Y, m_Max.m_Z);
+
+ for (INT32 theIndex = 0; theIndex < 8; ++theIndex) {
+ theCorners[theIndex].Transform(inMatrix);
+ theTransformedBox.Add(theCorners[theIndex]);
+ }
+ *this = theTransformedBox;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICColor.cpp b/src/Runtime/Source/System/Source/UICColor.cpp
new file mode 100644
index 00000000..c4f3b811
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICColor.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICColor.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inColor 32 bit represenation of the color
+ */
+CColor::CColor(const Q3DStudio::UINT32 inColor)
+ : m_Color(inColor)
+{
+}
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inRed 8 bit represenation of the red component
+ * @param inGreen 8 bit representation of the green component
+ * @param inBlue 8 bit representation of the blue component
+ * @param inAlpha 8 bit representation of the transparency component
+ */
+CColor::CColor(const UINT8 inRed, const UINT8 inGreen, const UINT8 inBlue, const UINT8 inAlpha)
+ : m_Red(inRed)
+ , m_Green(inGreen)
+ , m_Blue(inBlue)
+ , m_Alpha(inAlpha)
+{
+}
+
+//==============================================================================
+/**
+ * Set the color to a blend between the two given colors.
+ * @param inColor1 Color representing factor 0
+ * @param inColor2 Color representing factor 1.0
+ * @param inFactor Blend factor where 0.5 is an even mix of the two colors
+ */
+void CColor::Interpolate(const CColor &inColor1, const CColor &inColor2, const FLOAT inFactor)
+{
+ // m_Red = static_cast<UINT8>( rand() % 256 );//( 1.0f - inFactor ) * inColor1.m_Red +
+ //inFactor * inColor2.m_Red );
+ // m_Green = static_cast<UINT8>( rand() % 256 );//( 1.0f - inFactor ) * inColor1.m_Green +
+ //inFactor * inColor2.m_Green );
+ // m_Blue = static_cast<UINT8>( rand() % 256 );//( 1.0f - inFactor ) * inColor1.m_Blue +
+ //inFactor * inColor2.m_Blue );
+ // m_Alpha = 255;//static_cast<UINT8>( ( 1.0f - inFactor ) * inColor1.m_Alpha + inFactor *
+ //inColor2.m_Alpha );
+
+ m_Red = static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Red + inFactor * inColor2.m_Red);
+ m_Green =
+ static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Green + inFactor * inColor2.m_Green);
+ m_Blue = static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Blue + inFactor * inColor2.m_Blue);
+ m_Alpha =
+ static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Alpha + inFactor * inColor2.m_Alpha);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICCubicRoots.cpp b/src/Runtime/Source/System/Source/UICCubicRoots.cpp
new file mode 100644
index 00000000..876986ef
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICCubicRoots.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICCubicRoots.h"
+#include "UICDataLogger.h"
+#include "UICCubicRootsImpl.h"
diff --git a/src/Runtime/Source/System/Source/UICDLLManager.cpp b/src/Runtime/Source/System/Source/UICDLLManager.cpp
new file mode 100644
index 00000000..cb8cf9c6
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICDLLManager.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SystemPrefix.h"
+#include "UICDLLManager.h"
+#include "UICBasicPluginDLL.h"
+#include <QDebug>
+#ifdef _LINUXPLATFORM
+#include <dlfcn.h>
+#endif
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+ * Comparator for DLL instances.
+ * Compares by plugin type and handle
+ */
+namespace Q3DStudio {
+bool operator==(const _SDLLInfo &inInfo1, const _SDLLInfo &inInfo2)
+{
+ return (inInfo1.m_Type == inInfo2.m_Type) && (inInfo1.m_Handle == inInfo2.m_Handle);
+}
+}
+
+//==============================================================================
+/**
+ * Singleton getter
+ */
+CDLLManager &CDLLManager::GetDLLManager()
+{
+ static CDLLManager theDLLManager = CDLLManager();
+ return theDLLManager;
+}
+
+//==============================================================================
+/**
+ * CTOR
+ */
+CDLLManager::CDLLManager()
+{
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+CDLLManager::~CDLLManager()
+{
+}
+
+//==============================================================================
+/**
+ * Cleanup
+ */
+void CDLLManager::Cleanup()
+{
+ m_LoadedLibraries.Clear(true);
+}
+
+//==============================================================================
+/**
+ * Loads a DLL/shared library given a path to the library plugin and the plugin
+ * type to expect.
+ */
+long CDLLManager::LoadLibrary(const char *inLibraryPath, long inPluginType)
+{
+ long theEmptyIndex = NVARRAY_NOTFOUND;
+#ifdef _PCPLATFORM
+ DLLHANDLE theHandle = ::LoadLibraryA(inLibraryPath);
+#endif
+
+#ifdef _LINUXPLATFORM
+ DLLHANDLE theHandle = ::dlopen(inLibraryPath, RTLD_NOW);
+
+ if (!theHandle) {
+ const char *error = ::dlerror();
+ qWarning() << "Failed to load shared library, error:" << QStringLiteral("%1, full path: %2").arg(error).arg(inLibraryPath);
+ }
+
+#endif
+
+#ifdef _INTEGRITYPLATFORM
+ DLLHANDLE theHandle = 0;
+ qWarning() << "CDLLManager::LoadLibrary handle is zero!";
+#endif
+
+ Q3DStudio_ASSERT(theHandle);
+
+ if (theHandle != NULL) {
+ SDLLInfo theInfo;
+ PROC_GetPluginType theProc =
+ reinterpret_cast<PROC_GetPluginType>(GetProc("GetPluginType", theHandle));
+ Q3DStudio_ASSERT(theProc);
+
+ if (theProc) {
+ theInfo.m_Type = theProc();
+
+ if (theInfo.m_Type == inPluginType) {
+ theEmptyIndex = m_LoadedLibraries.GetIndex(theInfo);
+ theInfo.m_Handle = theHandle;
+
+ if (theEmptyIndex == NVARRAY_NOTFOUND) {
+ m_LoadedLibraries.Push(theInfo);
+ theEmptyIndex = m_LoadedLibraries.GetCount() - 1;
+ } else
+ m_LoadedLibraries[theEmptyIndex] = theInfo;
+ }
+ }
+
+ if (theEmptyIndex == NVARRAY_NOTFOUND) {
+#ifdef _PCPLATFORM
+ ::FreeLibrary(theHandle);
+#endif
+
+#ifdef _LINUXPLATFORM
+ ::dlclose(theHandle);
+#endif
+ }
+ }
+
+ return theEmptyIndex;
+}
+
+//==============================================================================
+/**
+ * Unloads a DLL given a handle
+ */
+void CDLLManager::UnloadLibrary(const long inHandle)
+{
+ if (inHandle >= 0 && inHandle < m_LoadedLibraries.GetCount()) {
+#ifdef _PCPLATFORM
+ ::FreeLibrary(m_LoadedLibraries[inHandle].m_Handle);
+#endif
+
+#ifdef _LINUXPLATFORM
+ ::dlclose(m_LoadedLibraries[inHandle].m_Handle);
+#endif
+
+ m_LoadedLibraries[inHandle] = SDLLInfo();
+ }
+}
+
+//==============================================================================
+/**
+ * Retrieves a DLL proc given the proc name
+ */
+void *CDLLManager::GetProc(const char *inProcName, long inHandle)
+{
+ if (inHandle >= 0 && inHandle < m_LoadedLibraries.GetCount())
+ return GetProc(inProcName, m_LoadedLibraries[inHandle].m_Handle);
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Retrieves a DLL proc fiven the proc name
+ */
+void *CDLLManager::GetProc(const char *inProcName, const DLLHANDLE inHandle)
+{
+#ifdef _PCPLATFORM
+ return ::GetProcAddress(inHandle, inProcName);
+#endif
+
+#ifdef _LINUXPLATFORM
+ return ::dlsym(inHandle, inProcName);
+#endif
+
+#ifdef _INTEGRITYPLATFORM
+ qWarning() << "CDLLManager::GetProc returns NULL!";
+ return NULL;
+#endif
+}
+
+//==============================================================================
+/**
+ * Retrieves the plugin type for the DLL
+ */
+template <typename EEnumType>
+EEnumType CDLLManager::GetPluginType(long inHandle)
+{
+ if (inHandle >= 0 && inHandle < m_LoadedLibraries.GetCount())
+ return static_cast<EEnumType>(m_LoadedLibraries[inHandle].m_Type);
+
+ return 0;
+}
diff --git a/src/Runtime/Source/System/Source/UICDataLogger.cpp b/src/Runtime/Source/System/Source/UICDataLogger.cpp
new file mode 100644
index 00000000..4ef19c9f
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICDataLogger.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+CDataLogger::SExternalFunctors CDataLogger::m_Functors;
+CDataLogger::EDataLoggerLevel CDataLogger::m_LogLevel = CDataLogger::LOG_LEVEL_INVALID;
+BOOL CDataLogger::m_Enabled = false;
+
+// Developers - change out the = NULL to = class::LogEntry to log specific stuff.
+template <>
+TPerfLogGeneralEvent1::TLogEntryInternal TPerfLogGeneralEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogGeneralEvent2::TLogEntryInternal TPerfLogGeneralEvent2::m_InternalLogFunc = NULL;
+
+template <>
+TPerfLogLuaEvent1::TLogEntryInternal TPerfLogLuaEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogLuaMathEvent1::TLogEntryInternal TPerfLogLuaMathEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogRenderEvent1::TLogEntryInternal TPerfLogRenderEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogSceneEvent1::TLogEntryInternal TPerfLogSceneEvent1::m_InternalLogFunc = NULL;
+
+template <>
+TPerfLogMathEvent1::TLogEntryInternal TPerfLogMathEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogPresentationEvent1::TLogEntryInternal TPerfLogPresentationEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogRenderEvent2::TLogEntryInternal TPerfLogRenderEvent2::m_InternalLogFunc = NULL;
+
+//==============================================================================
+/**
+ * Set the application supplied functors to use for getting time and handling
+ * the writing out of data
+ */
+void CDataLogger::SetFunctors(SExternalFunctors inFunctors)
+{
+ m_Functors = inFunctors;
+}
+
+//==============================================================================
+/**
+* Call into the specified functors to make stuff happen
+*/
+void CDataLogger::LogEntry(UINT32 inEntryEnum, BOOL inStartFlag)
+{
+ if (m_Enabled && m_Functors.m_GetTimeFunc && m_Functors.m_WriteFunc && m_Functors.m_UserData) {
+ // Initialize to the correct values
+ SPerfLogEntry theEntry(inEntryEnum, inStartFlag,
+ m_Functors.m_GetTimeFunc(m_Functors.m_UserData));
+ m_Functors.m_WriteFunc(m_Functors.m_UserData, theEntry);
+ }
+}
+
+//==============================================================================
+/**
+* Enable logging
+*/
+void CDataLogger::Enable()
+{
+ SetLogLevel(m_LogLevel);
+ m_Enabled = true;
+}
+
+//==============================================================================
+/**
+* Disable logging
+*/
+void CDataLogger::Disable()
+{
+ m_Enabled = false;
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+void CDataLogger::SetLogLevel(EDataLoggerLevel inLogLevel)
+{
+ switch (inLogLevel) {
+ // No logging
+ case LOG_LEVEL_NONE:
+ TPerfLogGeneralEvent1::Disable();
+ TPerfLogGeneralEvent2::Disable();
+
+ TPerfLogLuaEvent1::Disable();
+ TPerfLogRenderEvent1::Disable();
+ TPerfLogSceneEvent1::Disable();
+
+ TPerfLogMathEvent1::Disable();
+ TPerfLogPresentationEvent1::Disable();
+ TPerfLogRenderEvent2::Disable();
+ break;
+
+ case LOG_LEVEL_3:
+ TPerfLogMathEvent1::Enable();
+ TPerfLogPresentationEvent1::Enable();
+ TPerfLogRenderEvent2::Enable();
+
+ case LOG_LEVEL_2:
+ TPerfLogLuaEvent1::Enable();
+ TPerfLogRenderEvent1::Enable();
+ TPerfLogSceneEvent1::Enable();
+
+ case LOG_LEVEL_1:
+ TPerfLogGeneralEvent1::Enable();
+ TPerfLogGeneralEvent2::Enable();
+ break;
+
+ case LOG_LEVEL_INVALID:
+ default:
+ m_LogLevel = LOG_LEVEL_INVALID;
+ return;
+ break;
+ }
+ m_LogLevel = inLogLevel;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICEulerAngles.cpp b/src/Runtime/Source/System/Source/UICEulerAngles.cpp
new file mode 100644
index 00000000..ec186e6a
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICEulerAngles.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include "UICEulerAngles.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4365) // warnings on conversion from unsigned int to int
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CEulerAngleConverter::CEulerAngleConverter()
+{
+ m_OrderInfoBuffer[0] = '\0';
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CEulerAngleConverter::~CEulerAngleConverter()
+{
+}
+
+//==============================================================================
+/**
+ * Constructs a Euler angle & holds it in a EulerAngles struct
+ * @param theI x rotation ( radians )
+ * @param theJ y rotation ( radians )
+ * @param theH z rotation ( radians )
+ * @param theOrder the order this angle is in namely XYZ( static ), etc.
+ * use the EulOrd**** macros to generate values
+ * 0 to 23 is valid
+ * @return the euler angle
+ */
+EulerAngles CEulerAngleConverter::Eul_(float theI, float theJ, float theH, int theOrder)
+{
+ EulerAngles theEulerAngle;
+ theEulerAngle.x = theI;
+ theEulerAngle.y = theJ;
+ theEulerAngle.z = theH;
+ theEulerAngle.w = (float)theOrder;
+ return theEulerAngle;
+}
+
+//==============================================================================
+/**
+ * Construct quaternion from Euler angles (in radians).
+ * @param theEulerAngle incoming angle( radians )
+ * @return the Quaternion
+ */
+Quat CEulerAngleConverter::Eul_ToQuat(EulerAngles theEulerAngle)
+{
+ Quat theQuaternion;
+ double a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+
+ EulGetOrd((unsigned int)theEulerAngle.w, i, j, k, h, n, s, f);
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+
+ if (n == EulParOdd)
+ theEulerAngle.y = -theEulerAngle.y;
+
+ ti = theEulerAngle.x * 0.5;
+ tj = theEulerAngle.y * 0.5;
+ th = theEulerAngle.z * 0.5;
+
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == EulRepYes) {
+ a[i] = cj * (cs + sc); /* Could speed up with */
+ a[j] = sj * (cc + ss); /* trig identities. */
+ a[k] = sj * (cs - sc);
+ theQuaternion.w = (float)(cj * (cc - ss));
+ } else {
+ a[i] = cj * sc - sj * cs;
+ a[j] = cj * ss + sj * cc;
+ a[k] = cj * cs - sj * sc;
+ theQuaternion.w = (float)(cj * cc + sj * ss);
+ }
+ if (n == EulParOdd)
+ a[j] = -a[j];
+
+ theQuaternion.x = (float)a[X];
+ theQuaternion.y = (float)a[Y];
+ theQuaternion.z = (float)a[Z];
+ return theQuaternion;
+}
+
+//==============================================================================
+/**
+ * Construct matrix from Euler angles (in radians).
+ * @param theEulerAngle incoming angle
+ * @param theMatrix outgoing matrix
+ */
+void CEulerAngleConverter::Eul_ToHMatrix(EulerAngles theEulerAngle, HMatrix theMatrix)
+{
+ double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+ EulGetOrd((unsigned int)theEulerAngle.w, i, j, k, h, n, s, f);
+
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+
+ if (n == EulParOdd) {
+ theEulerAngle.x = -theEulerAngle.x;
+ theEulerAngle.y = -theEulerAngle.y;
+ theEulerAngle.z = -theEulerAngle.z;
+ }
+
+ ti = theEulerAngle.x;
+ tj = theEulerAngle.y;
+ th = theEulerAngle.z;
+
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == EulRepYes) {
+ theMatrix[i][i] = (float)cj;
+ theMatrix[i][j] = (float)(sj * si);
+ theMatrix[i][k] = (float)(sj * ci);
+ theMatrix[j][i] = (float)(sj * sh);
+ theMatrix[j][j] = (float)(-cj * ss + cc);
+ theMatrix[j][k] = (float)(-cj * cs - sc);
+ theMatrix[k][i] = (float)(-sj * ch);
+ theMatrix[k][j] = (float)(cj * sc + cs);
+ theMatrix[k][k] = (float)(cj * cc - ss);
+ } else {
+ theMatrix[i][i] = (float)(cj * ch);
+ theMatrix[i][j] = (float)(sj * sc - cs);
+ theMatrix[i][k] = (float)(sj * cc + ss);
+ theMatrix[j][i] = (float)(cj * sh);
+ theMatrix[j][j] = (float)(sj * ss + cc);
+ theMatrix[j][k] = (float)(sj * cs - sc);
+ theMatrix[k][i] = (float)(-sj);
+ theMatrix[k][j] = (float)(cj * si);
+ theMatrix[k][k] = (float)(cj * ci);
+ }
+
+ theMatrix[W][X] = 0.0;
+ theMatrix[W][Y] = 0.0;
+ theMatrix[W][Z] = 0.0;
+ theMatrix[X][W] = 0.0;
+ theMatrix[Y][W] = 0.0;
+ theMatrix[Z][W] = 0.0;
+ theMatrix[W][W] = 1.0;
+}
+
+//==============================================================================
+/**
+ * Convert matrix to Euler angles (in radians).
+ * @param theMatrix incoming matrix
+ * @param theOrder 0-23, use EulOrd**** to generate this value
+ * @return a set of angles in radians!!!!
+ */
+EulerAngles CEulerAngleConverter::Eul_FromHMatrix(HMatrix theMatrix, int theOrder)
+{
+ EulerAngles theEulerAngle;
+ int i, j, k, h, n, s, f;
+
+ EulGetOrd(theOrder, i, j, k, h, n, s, f);
+ if (s == EulRepYes) {
+ double sy = sqrt(theMatrix[i][j] * theMatrix[i][j] + theMatrix[i][k] * theMatrix[i][k]);
+ if (sy > 16 * FLT_EPSILON) {
+ theEulerAngle.x = (float)(atan2((double)theMatrix[i][j], (double)theMatrix[i][k]));
+ theEulerAngle.y = (float)(atan2((double)sy, (double)theMatrix[i][i]));
+ theEulerAngle.z = (float)(atan2((double)theMatrix[j][i], -(double)theMatrix[k][i]));
+ } else {
+ theEulerAngle.x = (float)(atan2(-(double)theMatrix[j][k], (double)theMatrix[j][j]));
+ theEulerAngle.y = (float)(atan2((double)sy, (double)theMatrix[i][i]));
+ theEulerAngle.z = 0;
+ }
+ } else {
+ double cy = sqrt(theMatrix[i][i] * theMatrix[i][i] + theMatrix[j][i] * theMatrix[j][i]);
+ if (cy > 16 * FLT_EPSILON) {
+ theEulerAngle.x = (float)(atan2((double)theMatrix[k][j], (double)theMatrix[k][k]));
+ theEulerAngle.y = (float)(atan2(-(double)theMatrix[k][i], (double)cy));
+ theEulerAngle.z = (float)(atan2((double)theMatrix[j][i], (double)theMatrix[i][i]));
+ } else {
+ theEulerAngle.x = (float)(atan2(-(double)theMatrix[j][k], (double)theMatrix[j][j]));
+ theEulerAngle.y = (float)(atan2(-(double)theMatrix[k][i], (double)cy));
+ theEulerAngle.z = 0;
+ }
+ }
+
+ if (n == EulParOdd) {
+ theEulerAngle.x = -theEulerAngle.x;
+ theEulerAngle.y = -theEulerAngle.y;
+ theEulerAngle.z = -theEulerAngle.z;
+ }
+
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+ theEulerAngle.w = (float)theOrder;
+ return theEulerAngle;
+}
+
+//==============================================================================
+/**
+ * Convert quaternion to Euler angles (in radians).
+ * @param theQuaternion incoming quaternion
+ * @param theOrder 0-23, use EulOrd**** to generate this value
+ * @return the generated angles ( radians )
+ */
+EulerAngles CEulerAngleConverter::Eul_FromQuat(Quat theQuaternion, int theOrder)
+{
+ HMatrix theMatrix;
+ double Nq = theQuaternion.x * theQuaternion.x + theQuaternion.y * theQuaternion.y
+ + theQuaternion.z * theQuaternion.z + theQuaternion.w * theQuaternion.w;
+ double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
+ double xs = theQuaternion.x * s;
+ double ys = theQuaternion.y * s;
+ double zs = theQuaternion.z * s;
+ double wx = theQuaternion.w * xs;
+ double wy = theQuaternion.w * ys;
+ double wz = theQuaternion.w * zs;
+ double xx = theQuaternion.x * xs;
+ double xy = theQuaternion.x * ys;
+ double xz = theQuaternion.x * zs;
+ double yy = theQuaternion.y * ys;
+ double yz = theQuaternion.y * zs;
+ double zz = theQuaternion.z * zs;
+
+ theMatrix[X][X] = (float)(1.0 - (yy + zz));
+ theMatrix[X][Y] = (float)(xy - wz);
+ theMatrix[X][Z] = (float)(xz + wy);
+ theMatrix[Y][X] = (float)(xy + wz);
+ theMatrix[Y][Y] = (float)(1.0 - (xx + zz));
+ theMatrix[Y][Z] = (float)(yz - wx);
+ theMatrix[Z][X] = (float)(xz - wy);
+ theMatrix[Z][Y] = (float)(yz + wx);
+ theMatrix[Z][Z] = (float)(1.0 - (xx + yy));
+ theMatrix[W][X] = 0.0;
+ theMatrix[W][Y] = 0.0;
+ theMatrix[W][Z] = 0.0;
+ theMatrix[X][W] = 0.0;
+ theMatrix[Y][W] = 0.0;
+ theMatrix[Z][W] = 0.0;
+ theMatrix[W][W] = 1.0;
+
+ return Eul_FromHMatrix(theMatrix, theOrder);
+}
+
+//==============================================================================
+/**
+ * Dump the Order information
+ */
+const char *CEulerAngleConverter::DumpOrderInfo()
+{
+ long theCount = 0;
+ long theOrder[24];
+ char theOrderStr[24][16];
+
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZr");
+
+ theCount = 0;
+ theOrder[theCount++] = EulOrdXYZs;
+ theOrder[theCount++] = EulOrdXYXs;
+ theOrder[theCount++] = EulOrdXZYs;
+ theOrder[theCount++] = EulOrdXZXs;
+ theOrder[theCount++] = EulOrdYZXs;
+ theOrder[theCount++] = EulOrdYZYs;
+ theOrder[theCount++] = EulOrdYXZs;
+ theOrder[theCount++] = EulOrdYXYs;
+ theOrder[theCount++] = EulOrdZXYs;
+ theOrder[theCount++] = EulOrdZXZs;
+ theOrder[theCount++] = EulOrdZYXs;
+ theOrder[theCount++] = EulOrdZYZs;
+
+ theOrder[theCount++] = EulOrdZYXr;
+ theOrder[theCount++] = EulOrdXYXr;
+ theOrder[theCount++] = EulOrdYZXr;
+ theOrder[theCount++] = EulOrdXZXr;
+ theOrder[theCount++] = EulOrdXZYr;
+ theOrder[theCount++] = EulOrdYZYr;
+ theOrder[theCount++] = EulOrdZXYr;
+ theOrder[theCount++] = EulOrdYXYr;
+ theOrder[theCount++] = EulOrdYXZr;
+ theOrder[theCount++] = EulOrdZXZr;
+ theOrder[theCount++] = EulOrdXYZr;
+ theOrder[theCount++] = EulOrdZYZr;
+
+ char theSubBuf[256];
+ m_OrderInfoBuffer[0] = '\0';
+ for (long theIndex = 0; theIndex < 24; ++theIndex) {
+ ::sprintf(theSubBuf, " %16s - %ld\n ", theOrderStr[theIndex], theOrder[theIndex]);
+ ::strcat(m_OrderInfoBuffer, theSubBuf);
+ }
+
+ return m_OrderInfoBuffer;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICFile.cpp b/src/Runtime/Source/System/Source/UICFile.cpp
new file mode 100644
index 00000000..60f60f52
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICFile.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICFile.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// OS level memory routines
+//==============================================================================
+#if defined(_XENONPLATFORM) || defined(_PCPLATFORM) || defined(_PS3PLATFORM) \
+ || defined(_TEGRAPLATFORM) || defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+CFile::TOpen CFile::s_Open = &fopen;
+CFile::TClose CFile::s_Close = &fclose;
+CFile::TRead CFile::s_Read = &fread;
+CFile::TWrite CFile::s_Write = &fwrite;
+CFile::TTell CFile::s_Tell = &ftell;
+CFile::TSeek CFile::s_Seek = &fseek;
+#else
+#error "A platform must be defined"
+#endif
+
+//==============================================================================
+/**
+ * Overrides basic memory allocation/deallocation routines
+ * @param inOpen fopen replacement method
+ * @param inClose fclose replacement method
+ * @param inRead fread replacement method
+ * @param inWrite fwrite replacement method
+ */
+void CFile::SetFileFunctions(const TOpen inOpen, const TClose inClose, const TRead inRead,
+ const TWrite inWrite, const TTell inTell, const TSeek inSeek)
+{
+ s_Open = inOpen;
+ s_Close = inClose;
+ s_Read = inRead;
+ s_Write = inWrite;
+ s_Tell = inTell;
+ s_Seek = inSeek;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICFileStream.cpp b/src/Runtime/Source/System/Source/UICFileStream.cpp
new file mode 100644
index 00000000..08f70e26
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICFileStream.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SystemPrefix.h"
+#include "UICFile.h"
+#include "UICFileStream.h"
+#include "UICThreadManager.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inFilename the file to open
+ * @param inMode the file mode to use
+ */
+CFileStream::CFileStream(const CHAR *inFilePath, const CHAR *inMode, BOOL inKeepTrying)
+ : m_FileStream(NULL)
+ , m_Endian(QT3DS_LITTLE_ENDIAN)
+ , m_KeepTrying(inKeepTrying)
+{
+ m_TempBuffer.Reserve(sizeof(MATRIX16)); // Preallocated some space
+ if (inFilePath)
+ Open(inFilePath, inMode);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CFileStream::~CFileStream()
+{
+ Close();
+}
+
+//==============================================================================
+/**
+ * Open file.
+ * @param inFilename the file to open
+ * @param inMode the file mode ( read/write ) to use
+ */
+void CFileStream::Open(const CHAR *inFilePath, const CHAR *inMode)
+{
+ Close();
+ m_FileStream = CFile::Open()(inFilePath, inMode);
+ while (m_KeepTrying && !m_FileStream) {
+ Q3DStudio_sleepmillisec(10);
+ m_FileStream = CFile::Open()(inFilePath, inMode);
+ }
+
+ if (m_FileStream)
+ m_FilePath = inFilePath;
+}
+
+//==============================================================================
+/**
+ * Close file.
+ */
+void CFileStream::Close()
+{
+ if (m_FileStream) {
+ CFile::Close()(m_FileStream);
+ m_FileStream = NULL;
+ }
+}
+
+//==============================================================================
+/**
+ * Check if there is an opened file.
+ * @return TRUE if opened, FALSE otherwise.
+ */
+BOOL CFileStream::IsOpen() const
+{
+ return m_FileStream != NULL;
+}
+
+//==============================================================================
+/**
+ * Access the source path of a file stream.
+ * @return an empty string if the stream is not open
+ */
+const CHAR *CFileStream::GetFilePath() const
+{
+ return m_FilePath.toLatin1().constData();
+}
+
+//==============================================================================
+/**
+ * Read from stream into memory.
+ * @param outMemory the destination of the read
+ * @param inByteCount the amount to read
+ * @return the number of bytes actually read
+ */
+INT32 CFileStream::ReadRawCopy(void *inDestination, const UINT32 inByteCount)
+{
+ INT32 lastRead = 0;
+ INT32 totalRead = 0;
+ do {
+ if (totalRead) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Failed to read expected amount, retrying, expected "
+ << inByteCount << " bytes, got "<< totalRead <<" bytes";
+ }
+ lastRead = static_cast<INT32>(CFile::Read()(((char *)inDestination) + totalRead, 1,
+ inByteCount - totalRead, m_FileStream));
+ totalRead += lastRead;
+ } while (lastRead && totalRead < (INT32)inByteCount);
+
+ if (totalRead != (INT32)inByteCount) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Failed to read expected amount, retrying, expected "
+ << inByteCount << " bytes, got "<< totalRead <<" bytes";
+
+ // Zero out remaining destination buffer.
+ // This can, in some cases, avoid a crash and allow the system to survive a partial
+ // read.
+ INT32 amountLeft = inByteCount - totalRead;
+ memset(((char *)inDestination) + totalRead, 0, amountLeft);
+ }
+ return totalRead;
+}
+
+//==============================================================================
+/**
+ * Reads data into internal buffer and return the data pointer for it.
+ * @param outMemory pointer to internal data buffer
+ * @param inByteCount the amount to read
+ * @return the number of bytes actually read
+ */
+INT32 CFileStream::ReadRaw(const void *&inPtr, const UINT32 inByteCount)
+{
+ m_TempBuffer.Reserve(static_cast<INT32>(inByteCount));
+ INT32 theReadSize = ReadRawCopy(m_TempBuffer.Begin(), inByteCount);
+ if (theReadSize != (INT32)inByteCount) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Failed to read expected amount, retrying, expected "<< inByteCount
+ << " bytes, got "<< theReadSize <<" bytes";
+ }
+ inPtr = m_TempBuffer.Begin();
+ return theReadSize;
+}
+
+//==============================================================================
+/**
+ * Write from memory to stream.
+ * @param inMemory the buffer to write from
+ * @param inByteCount the amount to write
+ * @return the number of bytes actually written
+ */
+INT32 CFileStream::WriteRaw(const void *inSource, const UINT32 inByteCount)
+{
+ return static_cast<INT32>(CFile::Write()(inSource, 1, inByteCount, m_FileStream));
+}
+
+//==============================================================================
+/**
+ * Offsets the file position by the specified number of bytes
+ */
+void CFileStream::Offset(const INT32 inByteCount)
+{
+ CFile::Seek()(m_FileStream, inByteCount, CFile::E_SEEK_CUR);
+}
+
+//==============================================================================
+/**
+ * Returns the current position of the file stream
+ */
+IStream::TStreamPosition CFileStream::Current()
+{
+ return static_cast<INT32>(CFile::Tell()(m_FileStream));
+}
+
+//==============================================================================
+/**
+ * Sets the stream to the specified position within the file
+ */
+void CFileStream::Set(const TStreamPosition &inPosition)
+{
+ CFile::Seek()(m_FileStream, inPosition, CFile::E_SEEK_SET);
+}
+
+//==============================================================================
+/**
+ * Set the endianess of the file.
+ * @warning endian support not implemented
+ */
+void CFileStream::SetEndian(const BOOL inEndian)
+{
+ m_Endian = inEndian;
+}
+
+//==============================================================================
+/**
+ * Get the endianess of the file.
+ * @warning endian support not implemented
+ */
+BOOL CFileStream::GetEndian()
+{
+ return m_Endian;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICFunctionWrappers.cpp b/src/Runtime/Source/System/Source/UICFunctionWrappers.cpp
new file mode 100644
index 00000000..8fb8ea78
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICFunctionWrappers.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2010 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SystemPrefix.h"
+#include "UICFunctionWrappers.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+* CTOR
+*/
+IFunctionWrapper::IFunctionWrapper()
+ : m_Cost(0)
+{
+}
+
+//==============================================================================
+/**
+* Retrieve the cost associated with this function.
+* Should be zero or greater
+*/
+INT32 IFunctionWrapper::GetCost()
+{
+ return m_Cost;
+}
+
+//==============================================================================
+/**
+* Sets the cost associated with this function.
+*/
+void IFunctionWrapper::SetCost(const INT32 inCost)
+{
+ m_Cost = inCost;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/System/Source/UICMatrix.cpp b/src/Runtime/Source/System/Source/UICMatrix.cpp
new file mode 100644
index 00000000..22dfaea5
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMatrix.cpp
@@ -0,0 +1,897 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMatrix.h"
+#include "UICVector3.h"
+#include "UICEulerAngles.h"
+#include "UICDataLogger.h"
+#include <math.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+FLOAT g_IdentityInit[4][4] = { { 1.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 1.0f } };
+
+const RuntimeMatrix RuntimeMatrix::IDENTITY = RuntimeMatrix(g_IdentityInit);
+extern const FLOAT RUNTIME_EPSILON;
+
+//==============================================================================
+/**
+ * Empty constructor.
+ * Initializes this matrix to the identity matrix.
+ */
+RuntimeMatrix::RuntimeMatrix(const BOOL inInitializeIdentity /*= true*/)
+{
+ if (inInitializeIdentity)
+ Q3DStudio_memcpy(&m_Data, &IDENTITY, sizeof(m_Data));
+}
+
+//==============================================================================
+/**
+ * Copy constructor.
+ * @param inMatrix the source matrix to copy
+ */
+RuntimeMatrix::RuntimeMatrix(const RuntimeMatrix &inMatrix)
+{
+ Q3DStudio_memcpy(&m_Data, &inMatrix.m_Data, sizeof(m_Data));
+}
+
+//==============================================================================
+/**
+ * Assignment constructor.
+ * Initializes the matrix from an array.
+ * @param inComponents an array of 16 values
+ */
+RuntimeMatrix::RuntimeMatrix(const FLOAT inComponents[4][4])
+{
+ if (inComponents)
+ Q3DStudio_memcpy(&m_Data, inComponents, sizeof(m_Data));
+}
+
+//==============================================================================
+/**
+ * Sets this matrix to a NULL matrix with all values at zero.
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Zero()
+{
+ Q3DStudio_memset(&m_Data, 0, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the matrix to the identity matrix.
+ * @return reference to this matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Identity()
+{
+ Q3DStudio_memcpy(&m_Data, &IDENTITY, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Copies the elements from another matrix.
+ * @param inMatrix the source matrix
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Set(const RuntimeMatrix &inMatrix)
+{
+ Q3DStudio_memcpy(&m_Data, &inMatrix.m_Data, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Copies the given components to this matrix.
+ * @param inComponents an array of 16 components
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Set(const FLOAT inComponents[4][4])
+{
+ if (inComponents)
+ Q3DStudio_memcpy(&m_Data, inComponents, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Heavily optimized assignment method. This has the same result as creating
+ * four full 4x4 matrices and multiplying them together.
+ * @todo Look into optimized code.
+ * @param inTranslation translation coordinates
+ * @param inRotation Euler angle rotations
+ * @param inScale scaling dimensions
+ * @param inPivot pivot offset vector
+ * @param inRotationOrder rotation order
+ * @param inCoordinateSystem the coordindate system
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Set(const RuntimeVector3 &inTranslation, const RuntimeVector3 &inRotation,
+ const RuntimeVector3 &inScale, const RuntimeVector3 &inPivot, const UINT8 inRotationOrder,
+ const UINT8 inCoordinateSystem)
+{
+ // *this = m_ScaleMatrix * m_PivotMatrix * m_RotMatrix * m_TransMatrix; // Distributed
+ //original - plain speak
+
+ RuntimeVector3 theScaledPivot;
+ theScaledPivot.m_X = -inPivot.m_X * inScale.m_X;
+ theScaledPivot.m_Y = -inPivot.m_Y * inScale.m_Y;
+ theScaledPivot.m_Z = -inPivot.m_Z * inScale.m_Z;
+
+ // This would take care of rotation in the right order
+ RuntimeMatrix theRotation;
+ theRotation.SetRotate(inRotation, inRotationOrder, inCoordinateSystem);
+
+ Q3DStudio_memcpy(&m_Data, &IDENTITY, sizeof(m_Data));
+ m_Data[0][0] = inScale.m_X;
+ m_Data[1][1] = inScale.m_Y;
+ m_Data[2][2] = inScale.m_Z;
+
+ m_Data[3][0] = theScaledPivot.m_X;
+ m_Data[3][1] = theScaledPivot.m_Y;
+
+ if (inCoordinateSystem == ORIENTATION_LEFT_HANDED)
+ m_Data[3][2] = theScaledPivot.m_Z;
+ else
+ m_Data[3][2] = -theScaledPivot.m_Z;
+
+ MultiplyAffine(theRotation); // This could be optimized to only 9 multiplications instead of 16
+ // if you do them by hand
+
+ m_Data[3][0] += inTranslation.m_X;
+ m_Data[3][1] += inTranslation.m_Y;
+
+ if (inCoordinateSystem == ORIENTATION_LEFT_HANDED)
+ m_Data[3][2] += inTranslation.m_Z;
+ else
+ m_Data[3][2] += -inTranslation.m_Z;
+
+ if (inCoordinateSystem == ORIENTATION_LEFT_HANDED)
+ return FlipCoordinateSystem();
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the translation portion of the matrix without affecting the rest.
+ *
+ * If you want a pure translation matrix you must make sure to start with
+ * the identity matrix.
+ * @param inTranslate a translation vector
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::SetTranslate(const RuntimeVector3 &inTranslate)
+{
+ m_Data[3][0] = inTranslate.m_X;
+ m_Data[3][1] = inTranslate.m_Y;
+ m_Data[3][2] = inTranslate.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the rotation portion of the matrix without affecting the rest.
+ *
+ * FYI: The rotate and scale portions overlap. If you want a pure scale matrix
+ * you must make sure to start with the identity matrix.
+ * @param inRotation a quaternion describing the rotation
+ * @return reference to this modified matrix
+ */
+// CMatrix& CMatrix::SetRotate( const CQuaternion& inRotation )
+//{
+// inRotation.ToMatrix( *this );
+// return *this;
+//}
+
+//==============================================================================
+/**
+ * Sets the rotation portion of the matrix without affecting the rest.
+ *
+ * FYI: The rotate and scale portions overlap. If you want a pure rotation matrix
+ * you must make sure to start with the identity matrix.
+ * @param inRotation Euler angle rotation
+ * @param inRotationOrder rotation order
+ * @param inCoordinateSystem the coordindate system
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::SetRotate(const RuntimeVector3 &inRotation, const UINT8 inRotationOrder,
+ const UINT8 inCoordinateSystem)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+ Q3DStudio_UNREFERENCED_PARAMETER(inCoordinateSystem);
+
+ EulerAngles theEulerAngles;
+ switch (inRotationOrder) {
+ case ROTATIONORDER_XYZ:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdXYZs;
+ break;
+ case ROTATIONORDER_XYZR:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdXYZr;
+ break;
+ case ROTATIONORDER_YZX:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdYZXs;
+ break;
+ case ROTATIONORDER_YZXR:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdYZXr;
+ break;
+ case ROTATIONORDER_ZXY:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdZXYs;
+ break;
+ case ROTATIONORDER_ZXYR:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdZXYr;
+ break;
+ case ROTATIONORDER_XZY:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdXZYs;
+ break;
+ case ROTATIONORDER_XZYR:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdXZYr;
+ break;
+ case ROTATIONORDER_YXZ:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdYXZs;
+ break;
+ case ROTATIONORDER_YXZR:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdYXZr;
+ break;
+ case ROTATIONORDER_ZYX:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdZYXs;
+ break;
+ case ROTATIONORDER_ZYXR:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdZYXr;
+ break;
+ default: // defaults to Studio's rotation type
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdYXZs;
+ break;
+ }
+
+ theEulerAngles.x *= -1;
+ theEulerAngles.y *= -1;
+ theEulerAngles.z *= -1;
+
+ CEulerAngleConverter theConverter;
+ theConverter.Eul_ToHMatrix(theEulerAngles, m_Data);
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the scale portion of the matrix without affecting the rest.
+ *
+ * FYI: The rotate and scale portions overlap. If you want a pure scale matrix
+ * you must make sure to start with the identity matrix.
+ * @param inScale scale vector
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::SetScale(const RuntimeVector3 &inScale)
+{
+ m_Data[0][0] = inScale.m_X;
+ m_Data[1][1] = inScale.m_Y;
+ m_Data[2][2] = inScale.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Check this matrix against the identity matrix.
+ * @return true if this matrix is equivalent to the identity matrix
+ */
+BOOL RuntimeMatrix::IsIdentity() const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ return *this == IDENTITY;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is affine.
+ * An affine matrix has the last row being [ 0 0 0 1 ]
+ * @return true if the matrix is affine
+ */
+BOOL RuntimeMatrix::IsAffine() const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ return m_Data[0][3] == 0 && m_Data[1][3] == 0 && m_Data[2][3] == 0 && m_Data[3][3] == 1.0f;
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include a translation. Equivalent to post-multiplying
+ * this matrix with a transformation matrix derived from the given vector.
+ * @param inTranslation transformation vector applied
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Translate(const RuntimeVector3 &inTranslation)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ m_Data[3][0] += inTranslation.m_X;
+ m_Data[3][1] += inTranslation.m_Y;
+ m_Data[3][2] += inTranslation.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include a rotation. Equivalent to post-multiplying
+ * this matrix with a rotation matrix derived from the given quaternion.
+ * @param inRotation the rotation quaternion applied
+ * @return reference to this modified matrix
+ */
+// CMatrix& CMatrix::Rotate( const CQuaternion& inRotation )
+//{
+// CMatrix theRotation;
+// return MultiplyAffine( inRotation.ToMatrix( theRotation ) );
+//}
+
+//==============================================================================
+/**
+ * Appends the matrix to include scaling. Equivalent to post-multiplying
+ * this matrix with a scale matrix derived from the given vector.
+ * @param inScale the scale vector applied
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Scale(const RuntimeVector3 &inScale)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ m_Data[0][0] *= inScale.m_X;
+ m_Data[0][1] *= inScale.m_X;
+ m_Data[0][2] *= inScale.m_X;
+
+ m_Data[1][0] *= inScale.m_Y;
+ m_Data[1][1] *= inScale.m_Y;
+ m_Data[1][2] *= inScale.m_Y;
+
+ m_Data[2][0] *= inScale.m_Z;
+ m_Data[2][1] *= inScale.m_Z;
+ m_Data[2][2] *= inScale.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Flips the matrix elements around the identity diagonal.
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Transpose()
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theSwap = m_Data[1][0];
+ m_Data[1][0] = m_Data[0][1];
+ m_Data[0][1] = theSwap;
+
+ theSwap = m_Data[2][0];
+ m_Data[2][0] = m_Data[0][2];
+ m_Data[0][2] = theSwap;
+
+ theSwap = m_Data[3][0];
+ m_Data[3][0] = m_Data[0][3];
+ m_Data[0][3] = theSwap;
+
+ theSwap = m_Data[2][1];
+ m_Data[2][1] = m_Data[1][2];
+ m_Data[1][2] = theSwap;
+
+ theSwap = m_Data[3][1];
+ m_Data[3][1] = m_Data[1][3];
+ m_Data[1][3] = theSwap;
+
+ theSwap = m_Data[3][2];
+ m_Data[3][2] = m_Data[2][3];
+ m_Data[2][3] = theSwap;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compute the inverse of a 3D affine matrix; i.e. a matrix with a
+ * dimensionality of 4 where the bottom row has the entries (0, 0, 0, 1).
+ *
+ * This procedure treats the 4 by 4 matrix as a block matrix and
+ * calculates the inverse of one submatrix for a significant performance
+ * improvement over a general procedure that can invert any non-singular matrix:
+@code
+ | | -1 | -1 -1 |
+ | A C | | A -C A |
+ -1 | | | |
+ M = | | = | |
+ | 0 1 | | 0 1 |
+ | | | |
+@endcode
+ * where M is a 4 by 4 matrix,
+ * A is the 3 by 3 upper left submatrix of M,
+ * C is the 3 by 1 upper right submatrix of M.
+ *
+ * @return the determinant of matrix
+ */
+FLOAT RuntimeMatrix::Invert()
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ const FLOAT PRECISIONLIMIT = 1.0e-07f;
+ FLOAT thePositiveDet = 0.0f;
+ FLOAT theNegativeDet = 0.0f;
+ FLOAT theTempDet;
+
+ // Calculate the determinant of submatrix A and determine if the
+ // the matrix is singular as limited by the float precision.
+ theTempDet = m_Data[0][0] * m_Data[1][1] * m_Data[2][2];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m_Data[0][1] * m_Data[1][2] * m_Data[2][0];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m_Data[0][2] * m_Data[1][0] * m_Data[2][1];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m_Data[0][2] * m_Data[1][1] * m_Data[2][0];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m_Data[0][1] * m_Data[1][0] * m_Data[2][2];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m_Data[0][0] * m_Data[1][2] * m_Data[2][1];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ // Is the submatrix A nonsingular? (i.e. there is an inverse?)
+ FLOAT theDeterminant = thePositiveDet + theNegativeDet;
+ if (theDeterminant != 0
+ || ::fabs(theDeterminant / (thePositiveDet - theNegativeDet)) >= PRECISIONLIMIT) {
+ RuntimeMatrix theInverse;
+ FLOAT theInvDeterminant = 1.0f / theDeterminant;
+
+ // Calculate inverse(A) = adj(A) / det(A)
+ theInverse.m_Data[0][0] =
+ (m_Data[1][1] * m_Data[2][2] - m_Data[1][2] * m_Data[2][1]) * theInvDeterminant;
+ theInverse.m_Data[1][0] =
+ -(m_Data[1][0] * m_Data[2][2] - m_Data[1][2] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[2][0] =
+ (m_Data[1][0] * m_Data[2][1] - m_Data[1][1] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[0][1] =
+ -(m_Data[0][1] * m_Data[2][2] - m_Data[0][2] * m_Data[2][1]) * theInvDeterminant;
+ theInverse.m_Data[1][1] =
+ (m_Data[0][0] * m_Data[2][2] - m_Data[0][2] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[2][1] =
+ -(m_Data[0][0] * m_Data[2][1] - m_Data[0][1] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[0][2] =
+ (m_Data[0][1] * m_Data[1][2] - m_Data[0][2] * m_Data[1][1]) * theInvDeterminant;
+ theInverse.m_Data[1][2] =
+ -(m_Data[0][0] * m_Data[1][2] - m_Data[0][2] * m_Data[1][0]) * theInvDeterminant;
+ theInverse.m_Data[2][2] =
+ (m_Data[0][0] * m_Data[1][1] - m_Data[0][1] * m_Data[1][0]) * theInvDeterminant;
+
+ // Calculate -C * inverse(A)
+ theInverse.m_Data[3][0] =
+ -(m_Data[3][0] * theInverse.m_Data[0][0] + m_Data[3][1] * theInverse.m_Data[1][0]
+ + m_Data[3][2] * theInverse.m_Data[2][0]);
+ theInverse.m_Data[3][1] =
+ -(m_Data[3][0] * theInverse.m_Data[0][1] + m_Data[3][1] * theInverse.m_Data[1][1]
+ + m_Data[3][2] * theInverse.m_Data[2][1]);
+ theInverse.m_Data[3][2] =
+ -(m_Data[3][0] * theInverse.m_Data[0][2] + m_Data[3][1] * theInverse.m_Data[1][2]
+ + m_Data[3][2] * theInverse.m_Data[2][2]);
+
+ // assign ourselves to the inverse
+ *this = theInverse;
+ }
+
+ return theDeterminant;
+}
+
+//==============================================================================
+/**
+ * Fast multiplication of two affine 4x4 matrices. No affine pre-check.
+ * @todo MF - Convert to SSE Assembly Code
+ * @param inMatrix the source matrix
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::MultiplyAffine(const RuntimeMatrix &inMatrix)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theMult[4][4];
+
+ theMult[0][0] = m_Data[0][0] * inMatrix.m_Data[0][0] + m_Data[0][1] * inMatrix.m_Data[1][0]
+ + m_Data[0][2] * inMatrix.m_Data[2][0];
+ theMult[0][1] = m_Data[0][0] * inMatrix.m_Data[0][1] + m_Data[0][1] * inMatrix.m_Data[1][1]
+ + m_Data[0][2] * inMatrix.m_Data[2][1];
+ theMult[0][2] = m_Data[0][0] * inMatrix.m_Data[0][2] + m_Data[0][1] * inMatrix.m_Data[1][2]
+ + m_Data[0][2] * inMatrix.m_Data[2][2];
+ theMult[0][3] = 0;
+
+ theMult[1][0] = m_Data[1][0] * inMatrix.m_Data[0][0] + m_Data[1][1] * inMatrix.m_Data[1][0]
+ + m_Data[1][2] * inMatrix.m_Data[2][0];
+ theMult[1][1] = m_Data[1][0] * inMatrix.m_Data[0][1] + m_Data[1][1] * inMatrix.m_Data[1][1]
+ + m_Data[1][2] * inMatrix.m_Data[2][1];
+ theMult[1][2] = m_Data[1][0] * inMatrix.m_Data[0][2] + m_Data[1][1] * inMatrix.m_Data[1][2]
+ + m_Data[1][2] * inMatrix.m_Data[2][2];
+ theMult[1][3] = 0;
+
+ theMult[2][0] = m_Data[2][0] * inMatrix.m_Data[0][0] + m_Data[2][1] * inMatrix.m_Data[1][0]
+ + m_Data[2][2] * inMatrix.m_Data[2][0];
+ theMult[2][1] = m_Data[2][0] * inMatrix.m_Data[0][1] + m_Data[2][1] * inMatrix.m_Data[1][1]
+ + m_Data[2][2] * inMatrix.m_Data[2][1];
+ theMult[2][2] = m_Data[2][0] * inMatrix.m_Data[0][2] + m_Data[2][1] * inMatrix.m_Data[1][2]
+ + m_Data[2][2] * inMatrix.m_Data[2][2];
+ theMult[2][3] = 0;
+
+ theMult[3][0] = m_Data[3][0] * inMatrix.m_Data[0][0] + m_Data[3][1] * inMatrix.m_Data[1][0]
+ + m_Data[3][2] * inMatrix.m_Data[2][0] + inMatrix.m_Data[3][0];
+ theMult[3][1] = m_Data[3][0] * inMatrix.m_Data[0][1] + m_Data[3][1] * inMatrix.m_Data[1][1]
+ + m_Data[3][2] * inMatrix.m_Data[2][1] + inMatrix.m_Data[3][1];
+ theMult[3][2] = m_Data[3][0] * inMatrix.m_Data[0][2] + m_Data[3][1] * inMatrix.m_Data[1][2]
+ + m_Data[3][2] * inMatrix.m_Data[2][2] + inMatrix.m_Data[3][2];
+ theMult[3][3] = 1.0f;
+
+ return Set(theMult);
+}
+
+//==============================================================================
+/**
+ * Standard matrix multiplication
+ * @todo MF - Convert to SSE Assembly Code
+ * @param inMatrix matrix to multiply with
+ */
+RuntimeMatrix &RuntimeMatrix::Multiply(const RuntimeMatrix &inMatrix)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theMult[4][4];
+
+ theMult[0][0] = m_Data[0][0] * inMatrix.m_Data[0][0] + m_Data[1][0] * inMatrix.m_Data[0][1]
+ + m_Data[2][0] * inMatrix.m_Data[0][2] + m_Data[3][0] * inMatrix.m_Data[0][3];
+ theMult[0][1] = m_Data[0][1] * inMatrix.m_Data[0][0] + m_Data[1][1] * inMatrix.m_Data[0][1]
+ + m_Data[2][1] * inMatrix.m_Data[0][2] + m_Data[3][1] * inMatrix.m_Data[0][3];
+ theMult[0][2] = m_Data[0][2] * inMatrix.m_Data[0][0] + m_Data[1][2] * inMatrix.m_Data[0][1]
+ + m_Data[2][2] * inMatrix.m_Data[0][2] + m_Data[3][2] * inMatrix.m_Data[0][3];
+ theMult[0][3] = m_Data[0][3] * inMatrix.m_Data[0][0] + m_Data[1][3] * inMatrix.m_Data[0][1]
+ + m_Data[2][3] * inMatrix.m_Data[0][2] + m_Data[3][3] * inMatrix.m_Data[0][3];
+ theMult[1][0] = m_Data[0][0] * inMatrix.m_Data[1][0] + m_Data[1][0] * inMatrix.m_Data[1][1]
+ + m_Data[2][0] * inMatrix.m_Data[1][2] + m_Data[3][0] * inMatrix.m_Data[1][3];
+ theMult[1][1] = m_Data[0][1] * inMatrix.m_Data[1][0] + m_Data[1][1] * inMatrix.m_Data[1][1]
+ + m_Data[2][1] * inMatrix.m_Data[1][2] + m_Data[3][1] * inMatrix.m_Data[1][3];
+ theMult[1][2] = m_Data[0][2] * inMatrix.m_Data[1][0] + m_Data[1][2] * inMatrix.m_Data[1][1]
+ + m_Data[2][2] * inMatrix.m_Data[1][2] + m_Data[3][2] * inMatrix.m_Data[1][3];
+ theMult[1][3] = m_Data[0][3] * inMatrix.m_Data[1][0] + m_Data[1][3] * inMatrix.m_Data[1][1]
+ + m_Data[2][3] * inMatrix.m_Data[1][2] + m_Data[3][3] * inMatrix.m_Data[1][3];
+ theMult[2][0] = m_Data[0][0] * inMatrix.m_Data[2][0] + m_Data[1][0] * inMatrix.m_Data[2][1]
+ + m_Data[2][0] * inMatrix.m_Data[2][2] + m_Data[3][0] * inMatrix.m_Data[2][3];
+ theMult[2][1] = m_Data[0][1] * inMatrix.m_Data[2][0] + m_Data[1][1] * inMatrix.m_Data[2][1]
+ + m_Data[2][1] * inMatrix.m_Data[2][2] + m_Data[3][1] * inMatrix.m_Data[2][3];
+ theMult[2][2] = m_Data[0][2] * inMatrix.m_Data[2][0] + m_Data[1][2] * inMatrix.m_Data[2][1]
+ + m_Data[2][2] * inMatrix.m_Data[2][2] + m_Data[3][2] * inMatrix.m_Data[2][3];
+ theMult[2][3] = m_Data[0][3] * inMatrix.m_Data[2][0] + m_Data[1][3] * inMatrix.m_Data[2][1]
+ + m_Data[2][3] * inMatrix.m_Data[2][2] + m_Data[3][3] * inMatrix.m_Data[2][3];
+
+ theMult[3][0] = m_Data[0][0] * inMatrix.m_Data[3][0] + m_Data[1][0] * inMatrix.m_Data[3][1]
+ + m_Data[2][0] * inMatrix.m_Data[3][2] + m_Data[3][0] * inMatrix.m_Data[3][3];
+ theMult[3][1] = m_Data[0][1] * inMatrix.m_Data[3][0] + m_Data[1][1] * inMatrix.m_Data[3][1]
+ + m_Data[2][1] * inMatrix.m_Data[3][2] + m_Data[3][1] * inMatrix.m_Data[3][3];
+ theMult[3][2] = m_Data[0][2] * inMatrix.m_Data[3][0] + m_Data[1][2] * inMatrix.m_Data[3][1]
+ + m_Data[2][2] * inMatrix.m_Data[3][2] + m_Data[3][2] * inMatrix.m_Data[3][3];
+ theMult[3][3] = m_Data[0][3] * inMatrix.m_Data[3][0] + m_Data[1][3] * inMatrix.m_Data[3][1]
+ + m_Data[2][3] * inMatrix.m_Data[3][2] + m_Data[3][3] * inMatrix.m_Data[3][3];
+
+ return Set(theMult);
+}
+
+//==============================================================================
+/**
+ * Toggle between left-hand and right-hand coordinate system
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::FlipCoordinateSystem()
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ // rotation conversion
+ m_Data[0][2] *= -1;
+ m_Data[1][2] *= -1;
+ m_Data[2][0] *= -1;
+ m_Data[2][1] *= -1;
+
+ // translation conversion
+ m_Data[3][2] *= -1;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Rotate this matrix to align with the rotation of the specified matrix.
+ *
+ * @param inMatrix the maxtrix we are cloning.
+ * @param inMirrorFlag flag indicating that we should flip the z and face the opposite
+ *direction.
+ * @return This matrix after the rotation.
+ */
+RuntimeMatrix &RuntimeMatrix::CloneRotation(const RuntimeMatrix &inMatrix, BOOL inMirrorFlag /*= false*/)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ // Create the axes
+ RuntimeVector3 theZ(inMatrix.Get(2, 0), inMatrix.Get(2, 1), inMatrix.Get(2, 2));
+ if (inMirrorFlag)
+ theZ *= -1;
+ RuntimeVector3 theY(inMatrix.Get(1, 0), inMatrix.Get(1, 1), inMatrix.Get(1, 2));
+ RuntimeVector3 theX(theY);
+ theX.CrossProduct(theZ);
+
+ // Normalize
+ theX.Normalize();
+ theY.Normalize();
+ theZ.Normalize();
+
+ // Copy it into the matrix
+ m_Data[0][0] = theX.m_X;
+ m_Data[0][1] = theX.m_Y;
+ m_Data[0][2] = theX.m_Z;
+
+ m_Data[1][0] = theY.m_X;
+ m_Data[1][1] = theY.m_Y;
+ m_Data[1][2] = theY.m_Z;
+
+ m_Data[2][0] = theZ.m_X;
+ m_Data[2][1] = theZ.m_Y;
+ m_Data[2][2] = theZ.m_Z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compute the square distance between the position vectors of two transforms.
+ * @param inMatrix the other transform, signifying a global object position for example
+ * @return the square of the "distance" between the two transforms
+ */
+FLOAT RuntimeMatrix::SquareDistance(const RuntimeMatrix &inMatrix) const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theResult = 0;
+ FLOAT theFactor;
+
+ theFactor = m_Data[3][0] - inMatrix.m_Data[3][0];
+ theFactor *= theFactor;
+ theResult += theFactor;
+
+ theFactor = m_Data[3][1] - inMatrix.m_Data[3][1];
+ theFactor *= theFactor;
+ theResult += theFactor;
+
+ theFactor = m_Data[3][2] - inMatrix.m_Data[3][2];
+ theFactor *= theFactor;
+ theResult += theFactor;
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Simple assignment operator.
+ * @param inMatrix new matrix being assigned
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::operator=(const RuntimeMatrix &inMatrix)
+{
+ Q3DStudio_memcpy(&m_Data, &inMatrix.m_Data, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compares this matrix's elements with another matrix's and returns true
+ * if the matrices are equivalent.
+ * @param inMatrix the matrix we are comparing against
+ * @return true if all elements are within EPSILON of each other.
+ */
+BOOL RuntimeMatrix::operator==(const RuntimeMatrix &inMatrix) const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ for (INT32 iRow = 0; iRow < 4; ++iRow) {
+ for (INT32 iCol = 0; iCol < 4; ++iCol) {
+ if (::fabs(m_Data[iRow][iCol] - inMatrix.m_Data[iRow][iCol]) > RUNTIME_EPSILON)
+ return false;
+ }
+ }
+ return true;
+}
+
+//==============================================================================
+/**
+ * Compares this matrix's elements with another matrix's and returns true
+ * if the matrices are not equivalent.
+ * @param inMatrix the matrix we are comparing against
+ * @return true if one or more elements are more than EPSILON from each other
+ */
+BOOL RuntimeMatrix::operator!=(const RuntimeMatrix &inMatrix) const
+{
+ // Reuse same code path..
+ return !(*this == inMatrix);
+}
+
+//==============================================================================
+/**
+ * Standardized conversion to string.
+ * @param outString string becoming a representation for the matrix
+ */
+// void CMatrix::ToString( AK_STRING& outString ) const
+//{
+// INT8 theBuffer[ 256 ];
+//
+// Q3DStudio_sprintf
+// (
+// theBuffer, 255,
+// "%.2f %.2f %.2f %.2f "
+// "%.2f %.2f %.2f %.2f "
+// "%.2f %.2f %.2f %.2f "
+// "%.2f %.2f %.2f %.2f",
+//
+// m_Data.m[ 0 ][ 0 ],
+// m_Data.m[ 0 ][ 1 ],
+// m_Data.m[ 0 ][ 2 ],
+// m_Data.m[ 0 ][ 3 ],
+//
+// m_Data.m[ 1 ][ 0 ],
+// m_Data.m[ 1 ][ 1 ],
+// m_Data.m[ 1 ][ 2 ],
+// m_Data.m[ 1 ][ 3 ],
+//
+// m_Data.m[ 2 ][ 0 ],
+// m_Data.m[ 2 ][ 1 ],
+// m_Data.m[ 2 ][ 2 ],
+// m_Data.m[ 2 ][ 3 ],
+//
+// m_Data.m[ 3 ][ 0 ],
+// m_Data.m[ 3 ][ 1 ],
+// m_Data.m[ 3 ][ 2 ],
+// m_Data.m[ 3 ][ 3 ]
+// );
+//
+// outString = theBuffer;
+//}
+//
+////==============================================================================
+///**
+// * Standardized conversion from string.
+// * @param inString string being a representation for the matrix
+// */
+// void CMatrix::FromString( const AK_STRING& inString )
+//{
+// std::sscanf
+// (
+// inString.c_str( ),
+//
+// "%f %f %f %f "
+// "%f %f %f %f "
+// "%f %f %f %f "
+// "%f %f %f %f",
+//
+// &m_Data.m[ 0 ][ 0 ],
+// &m_Data.m[ 0 ][ 1 ],
+// &m_Data.m[ 0 ][ 2 ],
+// &m_Data.m[ 0 ][ 3 ],
+//
+// &m_Data.m[ 1 ][ 0 ],
+// &m_Data.m[ 1 ][ 1 ],
+// &m_Data.m[ 1 ][ 2 ],
+// &m_Data.m[ 1 ][ 3 ],
+//
+// &m_Data.m[ 2 ][ 0 ],
+// &m_Data.m[ 2 ][ 1 ],
+// &m_Data.m[ 2 ][ 2 ],
+// &m_Data.m[ 2 ][ 3 ],
+//
+// &m_Data.m[ 3 ][ 0 ],
+// &m_Data.m[ 3 ][ 1 ],
+// &m_Data.m[ 3 ][ 2 ],
+// &m_Data.m[ 3 ][ 3 ]
+// );
+//}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemory.cpp b/src/Runtime/Source/System/Source/UICMemory.cpp
new file mode 100644
index 00000000..b1056b3d
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemory.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemory.h"
+
+//==============================================================================
+// OS level memory routines
+//==============================================================================
+Q3DStudio::CMemory::TMalloc Q3DStudio::CMemory::s_Malloc = NULL;
+Q3DStudio::CMemory::TRealloc Q3DStudio::CMemory::s_Realloc = NULL;
+Q3DStudio::CMemory::TFree Q3DStudio::CMemory::s_Free = NULL;
+
+//==============================================================================
+/**
+ * Overrides basic memory allocation/deallocation routines
+ * @param inMalloc memory allocation routine
+ * @param inFree memory deallocation routine
+ * @param inRealloc memory reallocation routine
+ */
+void Q3DStudio::CMemory::SetMemoryFunctions(const TMalloc inMalloc, const TFree inFree,
+ const TRealloc inRealloc)
+{
+ s_Malloc = inMalloc;
+ s_Realloc = inRealloc;
+ s_Free = inFree;
+}
+
+static Q3DStudio::CMemoryManager *s_globalManager = nullptr;
+static Q3DStudio::CMemoryHeap *s_globalHeap = nullptr;
+
+//==============================================================================
+/**
+ * Boot up the pooled memory manager and return it.
+ * @note The manager has to be initialized before use:
+ * GetMemoryManager( ).Initialize( "GlobalManager", g_ChunkSize, g_ChunkCount );
+ * @return Q3DStudio::CMemoryManager reference to the global object
+ */
+Q3DStudio::CMemoryManager &GetMemoryManager()
+{
+ if (!s_globalManager)
+ s_globalManager = new Q3DStudio::CMemoryManager;
+ return *s_globalManager;
+}
+
+//==============================================================================
+/**
+ * Return a reference to the global heap object.
+ * @return Q3DStudio::CMemoryHeap reference to the global object
+ */
+Q3DStudio::CMemoryHeap &GetMemoryHeap()
+{
+ if (!s_globalHeap)
+ s_globalHeap = new Q3DStudio::CMemoryHeap;
+ return *s_globalHeap;
+}
+
+//==============================================================================
+// Q3DStudio_new operator prototypes (5 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, size_t inOfficialSize, const char *inType,
+ const char *inFile, int inLine)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inReportedSize);
+ Q3DStudio_ASSERT(inReportedSize == inOfficialSize);
+
+ return Q3DStudio_HANDLER_NEW.Allocate(static_cast<const Q3DStudio::INT32>(inOfficialSize),
+ inType, inFile, inLine);
+}
+
+//==============================================================================
+/**
+ * Override 'operator delete' in order to track memory usage.
+ *
+ * So what's the use of the overloaded delete with special arguments? There is
+ * actually one case in which it will be called--when an exception is thrown
+ * during object construction. As you might recall, there is a contract implicit
+ * in the language that if an exception happens during the construction of an object,
+ * the memory for this object will be automatically deallocated. It so happens
+ * that during object's construction the compiler is still aware of which version
+ * of operator new was called to allocate memory. It is therefore able to generate
+ * a call to the corresponding version of delete, in case an exception is thrown.
+ * After the successful completion of construction, this information is no longer
+ * available and the compiler has no means to guess which version of global delete
+ * is appropriate for a given object.
+ */
+void operator delete(void *inReportedAddress, size_t inOfficialSize, const char *, const char *,
+ int)
+{
+ Q3DStudio_HANDLER_NEW.Free(inReportedAddress,
+ static_cast<const Q3DStudio::INT32>(inOfficialSize));
+}
+
+//==============================================================================
+// Q3DStudio_virtual_new operators (4 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, const char *inType, const char *inFile, int inLine)
+{
+ return Q3DStudio::CMemoryFilter::Allocate(static_cast<Q3DStudio::INT32>(inReportedSize), inType,
+ inFile, inLine, false);
+}
+
+void operator delete(void *inReportedAddress, const char *, const char *, int)
+{
+ Q3DStudio::CMemoryFilter::Free(inReportedAddress);
+}
diff --git a/src/Runtime/Source/System/Source/UICMemoryFilter.cpp b/src/Runtime/Source/System/Source/UICMemoryFilter.cpp
new file mode 100644
index 00000000..6462f746
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryFilter.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryFilter.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Allocate a chunk of memory and add a header to track it.
+ * @param inSize size of requested memory block, in bytes
+ * @param inType allocation description
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @param inClear true to clear allocated memory to zero
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryFilter::Allocate(const INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine, const BOOL inClear)
+{
+ const INT32 theTotalSize = inSize + Q3DStudio_MEMORY_ALIGNMENT;
+
+ INT32 *theMemory = reinterpret_cast<INT32 *>(
+ Q3DStudio_HANDLER_FILTER.Allocate(theTotalSize, inType, inFile, inLine));
+
+ theMemory[0] = FILTER_DOGTAG;
+ theMemory[1] = theTotalSize;
+
+ if (inClear)
+ Q3DStudio_memset(reinterpret_cast<INT8 *>(theMemory) + Q3DStudio_MEMORY_ALIGNMENT, 0,
+ inSize);
+
+ return reinterpret_cast<INT8 *>(theMemory) + Q3DStudio_MEMORY_ALIGNMENT;
+}
+
+//==============================================================================
+/**
+ * Free a block of memory that was allocated and tagged here.
+ * @param inPointer pointer given in a previous filter allocation
+ */
+void CMemoryFilter::Free(void *inPointer)
+{
+ if (!inPointer)
+ return;
+
+ INT32 *theMemory =
+ reinterpret_cast<INT32 *>(reinterpret_cast<INT8 *>(inPointer) - Q3DStudio_MEMORY_ALIGNMENT);
+
+ // Sanity check: Did we allocate this memory in the first place?
+ // If this throws we may be calling Q3DStudio_virtual_delete on memory that was getten from
+ // Q3DStudio_new
+ Q3DStudio_ASSERT(FILTER_DOGTAG == theMemory[0]);
+ Q3DStudio_HANDLER_FILTER.Free(theMemory, theMemory[1]);
+}
+
+//==============================================================================
+/**
+ * Re-allocate an existing chunk of memory and track it.
+ * @param inPointer pointer given in a previous allocation
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewType new allocation description
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryFilter::Reallocate(void *inPointer, const INT32 inNewSize, const CHAR *inNewType,
+ const CHAR *inFile, const INT32 inLine)
+{
+ INT32 *theNewMemory = NULL;
+ const INT32 theTotalSize = inNewSize + Q3DStudio_MEMORY_ALIGNMENT;
+
+ // Dogtag is not valid if the old pointer is NULL
+ if (inPointer) {
+ INT32 *theOldMemory = reinterpret_cast<INT32 *>(reinterpret_cast<INT8 *>(inPointer)
+ - Q3DStudio_MEMORY_ALIGNMENT);
+ Q3DStudio_ASSERT(FILTER_DOGTAG == theOldMemory[0]);
+ theNewMemory = reinterpret_cast<INT32 *>(Q3DStudio_HANDLER_FILTER.Reallocate(
+ theOldMemory, theOldMemory[1], theTotalSize, inNewType, inFile, inLine));
+ } else {
+ theNewMemory = reinterpret_cast<INT32 *>(
+ Q3DStudio_HANDLER_FILTER.Reallocate(NULL, 0, theTotalSize, inNewType, inFile, inLine));
+ }
+
+ theNewMemory[0] = FILTER_DOGTAG;
+ theNewMemory[1] = theTotalSize;
+ return reinterpret_cast<INT8 *>(theNewMemory) + Q3DStudio_MEMORY_ALIGNMENT;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemoryHeap.cpp b/src/Runtime/Source/System/Source/UICMemoryHeap.cpp
new file mode 100644
index 00000000..82bbb991
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryHeap.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemory.h"
+#include "UICMemoryHeap.h"
+#include "UICMemoryStatistics.h"
+#include "UICIStream.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Static Initialzation
+//==============================================================================
+CMemoryProbe CMemoryHeap::s_Probe;
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+CMemoryHeap::TMemoryReport CMemoryHeap::s_MemoryReport;
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+//==============================================================================
+/**
+ * Allocate a chunk of memory and potentially track it.
+ * @param inSize size of requested memory block, in bytes
+ * @param inDescription allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryHeap::Allocate(const INT32 inSize, const CHAR *inDescription, const CHAR *inFile,
+ const INT32 inLine)
+{
+ // Always track stats and trigger snapshot if this is a new record
+ s_Probe.Allocate(inSize);
+
+ // Check if we are exceeding the max memory limit
+ if (Q3DStudio_MEMORY_LIMIT > 0
+ && s_Probe.GetBytes(Q3DStudio::MEMSCOPE_GLOBAL, Q3DStudio::MEMVALUE_CURRENT)
+ > Q3DStudio_MEMORY_LIMIT) {
+ qCCritical (qt3ds::OUT_OF_MEMORY)
+ << "Q3DStudio_MEMORY_UNIT exceeded " << Q3DStudio_MEMORY_LIMIT;
+ Q3DStudio_ASSERT(false);
+ }
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ void *theAllocatedPtr = CMemory::Malloc()(static_cast<const size_t>(inSize));
+ if (s_MemoryReport.GetCount() < s_MemoryReport.GetCapacity()) {
+ SReportEntry theEntry = { theAllocatedPtr, inSize, inDescription, inFile, inLine };
+ s_MemoryReport.Push(theEntry);
+ } else {
+ static BOOL s_FullWarning = false;
+ if (!s_FullWarning) {
+ qCWarning (qt3ds::TRACE_INFO) << "HeapTracker full. "
+ << "Please increase Q3DStudio_MEMORY_HEAPTRACKINGSIZE("
+ << Q3DStudio_MEMORY_HEAPTRACKINGSIZE << ") "
+ << "to track all allocation and tune your pools to avoid "
+ << "hitting the heap.";
+ s_FullWarning = true;
+ }
+ }
+ return theAllocatedPtr;
+#else
+ Q3DStudio_UNREFERENCED_PARAMETER(inLine);
+ Q3DStudio_UNREFERENCED_PARAMETER(inFile);
+ Q3DStudio_UNREFERENCED_PARAMETER(inDescription);
+
+ return CMemory::Malloc()(static_cast<const size_t>(inSize));
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+//==============================================================================
+/**
+ * Free a block of memory allocated using CMemoryHeap::Allocate
+ * @param inPointer pointer given in a previous allocation
+ * @param inSize size of given memory block, in bytes
+ */
+void CMemoryHeap::Free(void *inPointer, INT32 inSize)
+{
+ // No-Op on NULL
+ if (!inPointer)
+ return;
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ RemoveReport(inPointer);
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ s_Probe.Free(inSize);
+ return CMemory::Free()(inPointer);
+}
+
+//==============================================================================
+/**
+ * Re-allocate an existing chunk of memory and potentially track it.
+ * @param inPointer pointer given in a previous allocation
+ * @param inOldSize size of current memory block, in bytes
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewDescription allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryHeap::Reallocate(void *inPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewDescription, const CHAR *inFile, const INT32 inLine)
+{
+ // Make sure this isn't a new malloc
+ if (!inPointer)
+ return Allocate(inNewSize, inNewDescription, inFile, inLine);
+
+ // Always track stats and record new high if it's a record
+ s_Probe.Allocate(inNewSize);
+ s_Probe.Free(inOldSize);
+
+ // Check if we are exceeding the max memory limit
+ Q3DStudio_ASSERT(Q3DStudio_MEMORY_LIMIT == 0
+ ? true
+ : s_Probe.GetBytes(Q3DStudio::MEMSCOPE_GLOBAL, Q3DStudio::MEMVALUE_CURRENT)
+ < Q3DStudio_MEMORY_LIMIT);
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ RemoveReport(inPointer);
+
+ void *theReallocatedPtr = CMemory::Realloc()(inPointer, static_cast<const size_t>(inNewSize));
+
+ SReportEntry theEntry = { theReallocatedPtr, inNewSize, inNewDescription, inFile, inLine };
+ s_MemoryReport.Push(theEntry);
+
+ return theReallocatedPtr;
+#else
+ return CMemory::Realloc()(inPointer, static_cast<const size_t>(inNewSize));
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieves memory info about a particular allocation
+ * @param inPointer allocated memory
+ * @return SMemoryHeapReportEntry* memory report
+ */
+CMemoryHeap::SReportEntry *CMemoryHeap::FindReport(void *inPointer)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPointer);
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ INT32 theEnd = s_MemoryReport.GetCount();
+ for (INT32 theIndex = 0; theIndex < theEnd; ++theIndex)
+ if (s_MemoryReport[theIndex].m_AllocatedPointer == inPointer)
+ return &s_MemoryReport[theIndex];
+
+ Q3DStudio_ASSERT(false);
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Removes memory info due to a deallocation.
+ * @param inPointer allocated memory
+ */
+void CMemoryHeap::RemoveReport(void *inPointer)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPointer);
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ INT32 theEnd = s_MemoryReport.GetCount();
+ for (INT32 theIndex = 0; theIndex < theEnd; ++theIndex) {
+ if (s_MemoryReport[theIndex].m_AllocatedPointer == inPointer) {
+ s_MemoryReport.Remove(theIndex);
+ return;
+ }
+ }
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+//==============================================================================
+/**
+ * The memory probe records basic heap activity
+ * @return reference to probe
+ */
+CMemoryProbe &CMemoryHeap::GetProbe()
+{
+ return s_Probe;
+}
+
+//==============================================================================
+/**
+ * The report records all heap activity
+ * @return pointer to report if tracking is on, or NULL
+ */
+CMemoryHeap::TMemoryReport *CMemoryHeap::GetReport()
+{
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ return &s_MemoryReport;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemoryManager.cpp b/src/Runtime/Source/System/Source/UICMemoryManager.cpp
new file mode 100644
index 00000000..7ba93137
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryManager.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemory.h"
+#include "UICMemoryManager.h"
+#include "UICMemoryHeap.h"
+#include "UICMemoryProbe.h"
+#include "UICMemoryTracker.h"
+#include "UICMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Create a new empty memory pool manager.
+ *
+ * The manager must be initialized before use or it will forward all requests
+ * to the heap.
+ */
+CMemoryManager::CMemoryManager()
+{
+ // Set default allocations functions if they are not already set
+ if (NULL == CMemory::Malloc())
+ CMemory::SetMemoryFunctions(&malloc, &free, &realloc);
+
+ CMemoryStatistics::AddManager(this);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Q3DStudio_memset(m_Histogram, 0, sizeof(m_Histogram));
+ CMemoryStatistics::Overhead() += sizeof(m_Histogram);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Create a new initialized memory pool manager.
+ *
+ * @param inName short description of manager used in tracker
+ * @param inChunkSize array of values describing the chunk size of each pool
+ * @param inChunkCount array of values describing the number of chunks in each pool
+ */
+CMemoryManager::CMemoryManager(const CHAR *inName,
+ const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT])
+{
+ // Set default allocations functions if they are not already set
+ if (NULL == CMemory::Malloc())
+ CMemory::SetMemoryFunctions(&malloc, &free, &realloc);
+
+ CMemoryStatistics::AddManager(this);
+ Initialize(inName, inChunkSize, inChunkCount);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Q3DStudio_memset(m_Histogram, 0, sizeof(m_Histogram));
+ CMemoryStatistics::Overhead() -= sizeof(m_Histogram);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Release the memory manager and all owned pools.
+ *
+ * Nobody better point to memory in these pool because the it will be
+ * invalid after this.
+ */
+CMemoryManager::~CMemoryManager()
+{
+ CMemoryStatistics::RemoveManager(this);
+ Release();
+}
+
+//==============================================================================
+/**
+ * Configure the pool manager into separate pools of different chunk sizes.
+ *
+ * The chunk size array has to be increasing values such as:
+ * inChunkSize = { 8, 16, 32, 64, 96, 128, 256, 512, 1024 }
+ * but count doesn't:
+ * inChunkCount = { 500, 200, 1000, 200, 200, 100, 250, 50, 20 }
+ *
+ * The global memory manager settings are initialized in AKMemory.h
+ *
+ * @param inName short description of manager used in tracker
+ * @param inChunkSize array of Q3DStudio_MEMORY_POOLCOUNT values describing the chunk size
+ *of each pool
+ * @param inChunkCount array of Q3DStudio_MEMORY_POOLCOUNT values describing the number of
+ *chunks in each pool
+ */
+void CMemoryManager::Initialize(const CHAR *inName,
+ const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT])
+{
+ // Don't initialize more than once
+ Q3DStudio_ASSERT(m_Pool[0].GetChunkCount() == 0);
+ Q3DStudio_sprintf(m_Name, sizeof(m_Name), "%s", inName);
+
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ // Make sure pool are aligned to Q3DStudio_MEMORY_ALIGNMENT or smaller than
+ // Q3DStudio_MEMORY_ALIGNMENT
+ Q3DStudio_ASSERT(inChunkSize[thePoolIndex] < Q3DStudio_MEMORY_ALIGNMENT
+ || (inChunkSize[thePoolIndex] % Q3DStudio_MEMORY_ALIGNMENT) == 0);
+ m_Pool[thePoolIndex].Initialize(inName, inChunkSize[thePoolIndex],
+ inChunkCount[thePoolIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Release all the memory allocated in Initialize - essentially "uninitialize".
+ */
+void CMemoryManager::Release()
+{
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ m_Pool[thePoolIndex].Release();
+}
+
+//==============================================================================
+// ALLOCATION AND DEALLOCATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Fetch a new chunk of memory from the smallest pool possible
+ * @param inSize size of requested memory block, in bytes
+ * @param inType allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryManager::Allocate(INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine)
+{
+ Q3DStudio_ASSERT(inSize >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Histogram[Q3DStudio_min<INT32>(inSize, 511)].Add(1);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ inSize += sizeof(CMemoryTracker::SMemoryInfo); // make room for SMemoryInfo
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ // Find the smallest pool that fits
+ void *thePointer = NULL;
+ INT32 thePoolIndex = 0;
+ while (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ // Does this pool fit?
+ if (inSize <= m_Pool[thePoolIndex].GetChunkSize()) {
+ thePointer = m_Pool[thePoolIndex].Allocate();
+ break;
+ }
+ ++thePoolIndex;
+ }
+
+ // // Record the amount of wasted bytes in this chunk
+ if (thePointer) {
+ // Basic tracking
+ m_ManagerData.m_Aligned.Allocate(inSize);
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_PoolData[thePoolIndex].m_Aligned.Allocate(inSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+ // If not, we go to the heap for now.
+ else {
+ // REFACTOR: Use the next pool size up instead?
+ thePointer = CMemoryHeap::Allocate(inSize, inType, inFile, inLine);
+ m_ManagerData.m_Overflow.Allocate(inSize);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ if (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT)
+ m_PoolData[thePoolIndex].m_Overflow.Allocate(
+ inSize); // Heap allocation due to full memory pool
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ CMemoryTracker::SMemoryInfo *theMemoryInfo =
+ reinterpret_cast<CMemoryTracker::SMemoryInfo *>(thePointer);
+
+ theMemoryInfo->m_DogTag = CMemoryTracker::TRACKER_DOGTAG;
+ theMemoryInfo->m_Line = static_cast<INT16>(inLine);
+ theMemoryInfo->m_Size = static_cast<INT16>(inSize - sizeof(CMemoryTracker::SMemoryInfo));
+ theMemoryInfo->m_File = inFile;
+ theMemoryInfo->m_Type = inType;
+
+ m_LineTracker.Remember(theMemoryInfo);
+ thePointer = reinterpret_cast<CMemoryTracker::SMemoryInfo *>(thePointer) + 1;
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ return thePointer;
+}
+
+//==============================================================================
+/**
+ * Release a chunk of memory.
+ * @param inPointer pointer to memory to be reused
+ * @param inSize size of the memory we are releasing, in bytes
+ */
+void CMemoryManager::Free(void *inPointer, INT32 inSize)
+{
+ if (!inPointer)
+ return;
+
+ Q3DStudio_ASSERT(inSize >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Histogram[Q3DStudio_min<INT32>(inSize, 511)].Delete(1);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ inPointer = reinterpret_cast<CMemoryTracker::SMemoryInfo *>(inPointer) - 1;
+ m_LineTracker.Forget(reinterpret_cast<CMemoryTracker::SMemoryInfo *>(inPointer));
+ inSize += sizeof(CMemoryTracker::SMemoryInfo);
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ // Did we get a valid pool?
+ INT32 thePoolIndex = FetchPoolIndex(inPointer);
+ if (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ m_Pool[thePoolIndex].Free(inPointer);
+ m_ManagerData.m_Aligned.Free(inSize);
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_PoolData[thePoolIndex].m_Aligned.Free(inSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ } else {
+ CMemoryHeap::Free(inPointer, inSize);
+ m_ManagerData.m_Overflow.Free(inSize);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ if (inSize <= m_Pool[Q3DStudio_MEMORY_POOLCOUNT - 1].GetChunkSize())
+ for (thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ if (inSize <= m_Pool[thePoolIndex].GetChunkSize()) {
+ m_PoolData[thePoolIndex].m_Overflow.Free(inSize);
+ // This is driving me crazy -CN.
+ // Q3DStudio_ASSERT( m_PoolData[thePoolIndex].m_Overflow.GetCalls(
+ // MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ) >= 0 );
+ break;
+ }
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+}
+
+//==============================================================================
+/**
+ * Grow the existing memory allocated
+ *
+ * @param inOldPointer pointer given in a previous allocation
+ * @param inOldSize size of current memory block, in bytes
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewType allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryManager::Reallocate(void *inOldPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewType, const CHAR *inFile, const INT32 inLine)
+{
+ Q3DStudio_ASSERT(inOldSize >= 0 && inNewSize >= 0);
+
+ // It's legal to pass NULL as old pointer to realloc
+ if (!inOldPointer)
+ return Allocate(inNewSize, inNewType, inFile, inLine);
+
+ if (inNewSize == 0) {
+ Free(inOldPointer, inOldSize);
+ return NULL;
+ }
+
+ // Get a new bigger chunk and transfer old data to it
+ void *thePointer = Allocate(inNewSize, inNewType, inFile, inLine);
+ Q3DStudio_memcpy(thePointer, inOldPointer, Q3DStudio_min(inOldSize, inNewSize));
+
+ // Release old data
+ Free(inOldPointer, inOldSize);
+ return thePointer;
+}
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Find the pool that owns the given pointer.
+ * @param inPointer pointer to memory to be found
+ * @return INT32 index of pool or Q3DStudio_MEMORY_POOLCOUNT if the chunk can't be found
+ */
+INT32 CMemoryManager::FetchPoolIndex(const void *inPointer)
+{
+ // Find pool that owns the pointer
+ INT32 thePoolIndex = 0;
+ while (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ if (m_Pool[thePoolIndex].OwnsChunk(inPointer))
+ return thePoolIndex;
+ ++thePoolIndex;
+ }
+
+ return Q3DStudio_MEMORY_POOLCOUNT;
+}
+
+//==============================================================================
+// STATISTICS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return the text identifier of the manager
+ * @return the name, max 32 bytes long
+ */
+const CHAR *CMemoryManager::GetName()
+{
+ return m_Name;
+}
+
+//==============================================================================
+/**
+ * Reset all probe statistics
+ */
+void CMemoryManager::Reset()
+{
+ m_ManagerData.m_Aligned.Reset();
+ m_ManagerData.m_Overflow.Reset();
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ m_Pool[thePoolIndex].GetProbe().Reset();
+ m_PoolData[thePoolIndex].m_Aligned.Reset();
+ m_PoolData[thePoolIndex].m_Overflow.Reset();
+ }
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieve a particular memory pool
+ * @param inPoolIndex index of the pool
+ * @return SPoolData& is a reference to the indicated pool data
+ */
+CMemoryPool &CMemoryManager::GetPool(const INT32 inPoolIndex)
+{
+ Q3DStudio_ASSERT(inPoolIndex < Q3DStudio_MEMORY_POOLCOUNT && inPoolIndex >= 0);
+ return m_Pool[inPoolIndex];
+}
+
+//==============================================================================
+/**
+ * Retrieve a particular memory pool
+ * @param inPoolIndex index of the pool
+ * @return SPoolData& is a reference to the indicated pool data
+ */
+CMemoryManager::SPoolData *CMemoryManager::GetPoolData(const INT32 inPoolIndex)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPoolIndex);
+ Q3DStudio_ASSERT(inPoolIndex < Q3DStudio_MEMORY_POOLCOUNT && inPoolIndex >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ return m_PoolData + inPoolIndex;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieve the number of bytes that were allocated on the heap
+ * @return CMemoryProbe as the heap statistics
+ */
+CMemoryManager::SPoolData &CMemoryManager::GetManagerData()
+{
+ return m_ManagerData;
+}
+
+//==============================================================================
+/**
+ * Sum the high level statistics of all the pools.
+ * @return CMemoryProbe as the statistics, calculated on the spot
+ */
+CMemoryProbe CMemoryManager::GetProbe()
+{
+ CMemoryProbe theProbe;
+#if Q3DStudio_MEMORY_POOLTRACKING
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ theProbe.Combine(m_Pool[thePoolIndex].GetProbe());
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theProbe;
+}
+
+//==============================================================================
+/**
+ * Fetch the tracker if enabled by setting Q3DStudio_MEMORY_LINETRACKING
+ * @return CMemoryTracker pointer or NULL
+ */
+CMemoryTracker *CMemoryManager::GetLineTracker()
+{
+#if Q3DStudio_MEMORY_LINETRACKING
+ return &m_LineTracker;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_LINETRACKING
+}
+
+//==============================================================================
+/**
+ * Fetch the histogram if enabled by setting Q3DStudio_MEMORY_HISTOGRAM.
+ * The histogram counts all requested allocations of the specific size.
+ * @return UINT16 array of 512 values, or NULL
+ */
+const CMemoryProbe::SValue *CMemoryManager::GetHistogram()
+{
+#if Q3DStudio_MEMORY_POOLTRACKING
+ return m_Histogram;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemoryPool.cpp b/src/Runtime/Source/System/Source/UICMemoryPool.cpp
new file mode 100644
index 00000000..49b2b343
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryPool.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryPool.h"
+#include "UICMemoryHeap.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Create a new memory pool.
+ *
+ */
+CMemoryPool::CMemoryPool()
+ : m_ChunkSize(0)
+ , m_ChunkCount(0)
+ , m_Ceiling(NULL)
+ , m_Memory(NULL)
+ , m_Top(NULL)
+ , m_Hole(NULL)
+{
+ m_Description[0] = '\0';
+}
+
+//==============================================================================
+/**
+ * Release the memory pool.
+ *
+ * Nobody better point to this pool because it's illegal after this.
+ * We could blast the memory in debug mode to trigger bugs early but most
+ * compilers already do this.
+ */
+CMemoryPool::~CMemoryPool()
+{
+ Release();
+}
+
+//==============================================================================
+/**
+ * Configure the memory pool.
+ *
+ * The pool will allocate inChunkSize * inChunkCount bytes of memory from
+ * the heap using Q3DStudio_new, aligned on 4 byte boundaries.
+ *
+ * @param inName short description of pool - used in tracker
+ * @param inChunkSize size in bytes of each memory block, aka chunk
+ * @param inChunkCount number of chunks the pool holds
+ */
+void CMemoryPool::Initialize(const CHAR *inName, const INT32 inChunkSize, const INT32 inChunkCount)
+{
+ Q3DStudio_ASSERT(!m_Memory);
+
+ // Round up chunk size to the next even pointer size
+ // It needs to be at least pointer size to store the hole linked list
+ INT32 theRoundedChunkSize =
+ static_cast<INT32>(((inChunkSize + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *));
+
+ // Create pool description
+ Q3DStudio_sprintf(m_Description, sizeof(m_Description), "POOL: %s(%dx%d)", inName,
+ theRoundedChunkSize, inChunkCount);
+
+ // Reserve memory pool
+ m_ChunkSize = theRoundedChunkSize;
+ m_ChunkCount = inChunkCount;
+ m_Memory = reinterpret_cast<INT8 *>(
+ Q3DStudio_heap_allocate(m_ChunkSize * m_ChunkCount, m_Description));
+ m_Top = m_Memory;
+ m_Ceiling = m_Memory + m_ChunkSize * m_ChunkCount;
+}
+
+//==============================================================================
+/**
+ * Release all the memory allocated in Initialize - essentially "uninitialize".
+ */
+void CMemoryPool::Release()
+{
+ Q3DStudio_heap_free(m_Memory, m_ChunkSize * m_ChunkCount);
+
+ m_ChunkSize = 0, m_ChunkCount = 0;
+ m_Ceiling = NULL;
+ m_Memory = NULL;
+ m_Top = NULL;
+ m_Hole = NULL;
+}
+
+//==============================================================================
+// ALLOCATION AND DEALLOCATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Fetch a new chunk of memory.
+ *
+ * If there is a pool hole we use that, otherwise feed of the head.
+ * Every alloction is tracked in m_Statistics.
+ * @return a pointer to inChunkSize bytes of usable memory
+ */
+void *CMemoryPool::Allocate()
+{
+ if (m_Hole)
+ return PopHole();
+ else
+ return UseTop();
+}
+
+//==============================================================================
+/**
+ * Release a chunk of memory and track changes in statistics
+ * @param inChunk a pointer to memory to be reused
+ */
+void CMemoryPool::Free(void *inChunk)
+{
+ Q3DStudio_ASSERT(OwnsChunk(inChunk));
+ PushHole(inChunk);
+}
+
+//==============================================================================
+/**
+ * Verify that a pointer is owned by a specific pool
+ * @param inChunk a pointer to be checked
+ * @return BOOL true if the chunk is owned by this pool
+ */
+BOOL CMemoryPool::OwnsChunk(const void *inChunk) const
+{
+#ifdef _DEBUG
+ // Scan all holes to prevent double releasing memory
+ if (!(inChunk >= m_Ceiling || inChunk < m_Memory)) {
+ // No freeing anything above the top?
+ Q3DStudio_ASSERT(inChunk < m_Top);
+
+ // Not freeing any holes?
+ void *theHoleChunk = m_Hole;
+ while (theHoleChunk) {
+ Q3DStudio_ASSERT(inChunk != theHoleChunk);
+ theHoleChunk = reinterpret_cast<void *>(*reinterpret_cast<size_t *>(theHoleChunk));
+ }
+ }
+#endif // DEBUG
+
+ return !(inChunk >= m_Ceiling || inChunk < m_Memory);
+}
+
+//==============================================================================
+/**
+ * Quick check to see if there are chunks available
+ * @return BOOL true if the pool has available chunks
+ */
+BOOL CMemoryPool::IsFull() const
+{
+ return m_Hole == NULL && GetFreeTops() == 0;
+}
+
+//==============================================================================
+/**
+ * Get the total number of free chunks in this pool.
+ * @return INT32 is the nunber of free chunks
+ */
+INT32 CMemoryPool::GetFreeChunks() const
+{
+ return GetFreeTops() + GetFreeHoles();
+}
+
+//==============================================================================
+/**
+ * Get the number of holes in this pool.
+ * @return INT32 is the nunber of holes
+ */
+INT32 CMemoryPool::GetFreeHoles() const
+{
+ INT32 theHoleCounter = 0;
+ void *theHoleChunk = m_Hole;
+
+ // Walk the hole list until there are no more holes
+ while (theHoleChunk) {
+ theHoleChunk = reinterpret_cast<void *>(*reinterpret_cast<size_t *>(theHoleChunk));
+ ++theHoleCounter;
+ }
+
+ return theHoleCounter;
+}
+
+//==============================================================================
+/**
+ * Get the number of chunks left at the top.
+ * @return INT32 is the nunber of continous chunks at the top
+ */
+INT32 CMemoryPool::GetFreeTops() const
+{
+ return static_cast<INT32>((m_Ceiling - m_Top)) / m_ChunkSize;
+}
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return a chunch from the top.
+ *
+ * The top is only used if no pool holes are available.
+ * @return a pointer to the chunk at the top
+ */
+void *CMemoryPool::UseTop()
+{
+ // Out of memory?
+ // This is not assert since it may happen during normal runtime.
+ if (m_Top >= m_Ceiling)
+ return NULL;
+
+ void *theChunk = m_Top;
+ m_Top += m_ChunkSize;
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Probe.Allocate(m_ChunkSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theChunk;
+}
+
+//==============================================================================
+/**
+ * Add a new hole to the pool list.
+ *
+ * The holes are used in a stack-like fashion so the chunk we push in most
+ * recently is the first one to be returned next New call.
+ * The holes are linked by using the first four bytes to point to the next
+ * chunk. We are hijacking them to create a linked list of free chunks.
+ * @param inChunk is the just deleted chunk
+ */
+void CMemoryPool::PushHole(void *inChunk)
+{
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Probe.Free(m_ChunkSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+ // Set the pushed chunk to be the new top hole after we
+ // link the content of the new chunk to the last top.
+ *reinterpret_cast<size_t *>(inChunk) = reinterpret_cast<size_t>(m_Hole);
+ m_Hole = inChunk;
+}
+
+//==============================================================================
+/**
+ * Get the topmost hole as our chunk.
+ *
+ * Return the latest hole and relink the list of holes to the top.
+ * @return void* is the most recently deleted chunk
+ */
+void *CMemoryPool::PopHole()
+{
+ Q3DStudio_ASSERT(m_Hole);
+
+ // Return the old hole as our new chunk after we
+ // set the hole to the second hole in the list.
+ void *theChunk = m_Hole;
+ m_Hole = reinterpret_cast<void *>(*reinterpret_cast<size_t *>(m_Hole));
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Probe.Allocate(m_ChunkSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theChunk;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemoryProbe.cpp b/src/Runtime/Source/System/Source/UICMemoryProbe.cpp
new file mode 100644
index 00000000..e01817d2
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryProbe.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryProbe.h"
+#include "UICMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor - records its size with the statistics class
+ */
+CMemoryProbe::CMemoryProbe()
+{
+ CMemoryStatistics::Overhead() += sizeof(CMemoryProbe);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMemoryProbe::~CMemoryProbe()
+{
+ CMemoryStatistics::Overhead() -= sizeof(CMemoryProbe);
+}
+
+//==============================================================================
+/**
+ * Track the number related to incrementing memory.
+ * @param inByteAmount amount of bytes being allocated
+ */
+void CMemoryProbe::Allocate(const INT32 inByteAmount)
+{
+ if (inByteAmount > 0) {
+ m_Calls[MEMSCOPE_RESET].Add(1);
+ m_Bytes[MEMSCOPE_RESET].Add(inByteAmount);
+
+ m_Calls[MEMSCOPE_GLOBAL].Add(1);
+ m_Bytes[MEMSCOPE_GLOBAL].Add(inByteAmount);
+ }
+}
+
+//==============================================================================
+/**
+ * Track the number related to incrementing memory.
+ * @param inByteAmount amount of bytes being deallocted
+ */
+void CMemoryProbe::Free(const INT32 inByteAmount)
+{
+ Q3DStudio_ASSERT(inByteAmount >= 0);
+ if (inByteAmount > 0) {
+ m_Calls[MEMSCOPE_RESET].Delete(1);
+ m_Bytes[MEMSCOPE_RESET].Delete(inByteAmount);
+
+ m_Calls[MEMSCOPE_GLOBAL].Delete(1);
+ m_Bytes[MEMSCOPE_GLOBAL].Delete(inByteAmount);
+ }
+}
+
+//==============================================================================
+/**
+ * Reset all local statistics. Global values are not reset.
+ */
+void CMemoryProbe::Reset()
+{
+ m_Calls[MEMSCOPE_RESET].Reset();
+ m_Bytes[MEMSCOPE_RESET].Reset();
+}
+
+//==============================================================================
+/**
+ * Helper method for adding statistics used by manager to add pool usage.
+ * @param inProbe is the stats being added
+ */
+void CMemoryProbe::Combine(const CMemoryProbe &inProbe)
+{
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS];
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES];
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK];
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT];
+
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS];
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES];
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK];
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT];
+
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS];
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES];
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK];
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT];
+
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS];
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES];
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK];
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT];
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemoryStatistics.cpp b/src/Runtime/Source/System/Source/UICMemoryStatistics.cpp
new file mode 100644
index 00000000..09ba78df
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryStatistics.cpp
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICIStream.h"
+#include "UICMemoryStatistics.h"
+#include "UICMemoryTracker.h"
+#include "UICMemoryHeap.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Static Fields
+//==============================================================================
+INT32 CMemoryStatistics::s_Overhead = 0;
+CMemoryManager *CMemoryStatistics::s_PoolManagers[MANAGERCOUNT] = { NULL };
+
+//==============================================================================
+// REGISTRATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Add the manager from the static list done automatically on manager construction.
+ * @param inManager the manager we are beginning to track
+ */
+void CMemoryStatistics::AddManager(CMemoryManager *inManager)
+{
+ INT32 theIndex = 0;
+ while (s_PoolManagers[theIndex] && theIndex < MANAGERCOUNT - 1)
+ ++theIndex;
+
+ if (!s_PoolManagers[theIndex]) {
+ s_PoolManagers[theIndex] = inManager;
+ } else {
+ qCWarning(qt3ds::TRACE_INFO)
+ << "Could not add memory manager tracker. Limit: " << MANAGERCOUNT;
+ }
+}
+
+//==============================================================================
+/**
+ * Remove the manager from the static list done automatically on manager deletion.
+ * @param inManager the manager we are ceasing to track
+ */
+void CMemoryStatistics::RemoveManager(CMemoryManager *inManager)
+{
+ INT32 theIndex = 0;
+ while (inManager != s_PoolManagers[theIndex] && theIndex < MANAGERCOUNT - 1)
+ ++theIndex;
+
+ if (inManager == s_PoolManagers[theIndex])
+ s_PoolManagers[theIndex] = NULL;
+}
+
+//==============================================================================
+/**
+ * Read/write access to the static tracking field that keeps tab on how
+ * much memory we are spending _tracking_ memory.
+ * @return reference to the field tracking the overhead in bytes
+ */
+INT32 &CMemoryStatistics::Overhead()
+{
+ return s_Overhead;
+}
+
+//==============================================================================
+// OPERATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Reset all memory probes
+ */
+void CMemoryStatistics::Reset()
+{
+ qCInfo(qt3ds::TRACE_INFO) << "Resetting Memory Statistics";
+ CMemoryHeap::GetProbe().Reset();
+
+ for (INT32 theIndex = 0; theIndex < MANAGERCOUNT; ++theIndex)
+ if (s_PoolManagers[theIndex])
+ s_PoolManagers[theIndex]->Reset();
+}
+
+//==============================================================================
+// ACCESS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Quick access to memory usage of the first memory manager.
+ * @param inPeak is true if you want the peak, false if you want the current state
+ * @return the current explict usage in bytes
+ */
+INT32 CMemoryStatistics::GetRequestedBytes(BOOL inPeak /*=false*/)
+{
+ Q3DStudio_ASSERT(s_PoolManagers[0]);
+
+ EMemoryValue theValue = inPeak ? MEMVALUE_PEAK : MEMVALUE_CURRENT;
+ CMemoryManager::SPoolData &theUsageData = s_PoolManagers[0]->GetManagerData();
+
+ return theUsageData.m_Aligned.GetBytes(MEMSCOPE_RESET, theValue)
+ + theUsageData.m_Overflow.GetBytes(MEMSCOPE_RESET, theValue);
+}
+
+//==============================================================================
+/**
+ * Quick access to heap usage.
+ * @param inPeak is true if you want the peak, false if you want the current state
+ * @return the current heap usage in bytes
+ */
+INT32 CMemoryStatistics::GetHeapBytes(BOOL inPeak /*=false*/)
+{
+ return Q3DStudio::CMemoryHeap::GetProbe().GetBytes(MEMSCOPE_RESET,
+ inPeak ? MEMVALUE_PEAK : MEMVALUE_CURRENT);
+}
+
+//==============================================================================
+/**
+ * Fill out a SFactSheet with memory statistics.
+ * @param outFacts is filled out with factoids showing the system state
+ * @param inPeak is true if you want the peak, false if you want the current state
+ * @param inGlobal is true if you want values since process start, false since last reset
+ */
+void CMemoryStatistics::GetFacts(SFactSheet &outFacts, BOOL inPeak /*= true*/,
+ BOOL inGlobal /*= true*/)
+{
+ INT32 thePresentationBytes = 0;
+ Q3DStudio_UNREFERENCED_PARAMETER(thePresentationBytes);
+ Q3DStudio_memset(&outFacts, 0, sizeof(SFactSheet));
+
+ // Translate flags to enumerations
+ EMemoryScope theScope = inGlobal ? MEMSCOPE_GLOBAL : MEMSCOPE_RESET;
+ EMemoryValue theValue = inPeak ? MEMVALUE_PEAK : MEMVALUE_CURRENT;
+
+ // Capture heap state
+ outFacts.m_HeapState.m_Bytes = CMemoryHeap::GetProbe().GetBytes(theScope, theValue);
+ outFacts.m_HeapState.m_Calls = CMemoryHeap::GetProbe().GetCalls(theScope, theValue);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ INT32 theTotalChunks = 0;
+ INT32 theTotalBytes = 0;
+
+ // Scan all registered pool managers
+ Q3DStudio_sprintf(outFacts.m_ManagerState.m_Name, 32, "All Managers");
+ for (INT32 theManagerIndex = 0; theManagerIndex < MANAGERCOUNT; ++theManagerIndex) {
+ CMemoryManager *theManager = s_PoolManagers[theManagerIndex];
+ SFactoid &theManagerFact = outFacts.m_Manager[theManagerIndex];
+ INT32 theManagerChunks = 0;
+ INT32 theManagerBytes = 0;
+
+ // Ignore empty managers
+ if (!theManager)
+ break;
+
+ // Scan each pool in the manager
+ Q3DStudio_sprintf(theManagerFact.m_Name, 32, " %s", theManager->GetName());
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ CMemoryPool &thePool = theManager->GetPool(thePoolIndex);
+ CMemoryManager::SPoolData *thePoolData = theManager->GetPoolData(thePoolIndex);
+ Q3DStudio_ASSERT(thePoolData);
+
+ SFactoid &thePoolFact = outFacts.m_Pool[theManagerIndex][thePoolIndex];
+ INT32 theUsed = thePool.GetProbe().GetCalls(theScope, theValue);
+ INT32 theAlign = thePoolData->m_Aligned.GetBytes(theScope, theValue);
+
+ // Ignore empty pools
+ if (thePool.GetChunkCount() == 0)
+ break;
+
+ // Extract all the factoids
+ Q3DStudio_sprintf(thePoolFact.m_Name, 32, " %d: %4db x %4d", thePoolIndex,
+ thePool.GetChunkSize(), thePool.GetChunkCount());
+ thePoolFact.m_Bytes = thePool.GetChunkSize() * thePool.GetChunkCount();
+ thePoolFact.m_Calls = thePool.GetProbe().GetCalls(theScope, theValue);
+ thePoolFact.m_Used = 100 * theUsed / thePool.GetChunkCount();
+
+ thePoolFact.m_Align = 100;
+ if (theUsed > 0)
+ thePoolFact.m_Align = 100 * theAlign / (theUsed * thePool.GetChunkSize());
+ thePoolFact.m_Miss = thePoolData->m_Overflow.GetCalls(theScope, theValue);
+
+ thePresentationBytes += theAlign + thePoolData->m_Overflow.GetBytes(theScope, theValue);
+
+ theManagerFact.m_Bytes += thePoolFact.m_Bytes;
+ theManagerFact.m_Calls += thePoolFact.m_Calls;
+ theManagerFact.m_Used += theUsed;
+ theManagerFact.m_Align += theAlign;
+ theManagerFact.m_Miss += thePoolFact.m_Miss;
+
+ outFacts.m_ManagerState.m_Bytes += thePoolFact.m_Bytes;
+ outFacts.m_ManagerState.m_Calls += thePoolFact.m_Calls;
+ outFacts.m_ManagerState.m_Used += theUsed;
+ outFacts.m_ManagerState.m_Align += theAlign;
+ outFacts.m_ManagerState.m_Miss += thePoolFact.m_Miss;
+
+ theManagerChunks += thePool.GetChunkCount();
+ theManagerBytes += theUsed * thePool.GetChunkSize();
+ }
+
+ thePresentationBytes +=
+ theManager->GetManagerData().m_Overflow.GetBytes(theScope, theValue);
+
+ // Both the manager sub-total and grand-total need to track bytes separately
+ // since the percentages can't just be added or averaged. Those totals
+ // are instead weighted and this is the tracking math that does it.
+ theTotalChunks += theManagerChunks;
+ theTotalBytes += theManagerBytes;
+
+ theManagerFact.m_Used = 0;
+ if (theManagerChunks > 0)
+ theManagerFact.m_Used = 100 * theManagerFact.m_Used / theManagerChunks;
+
+ theManagerFact.m_Align = 100;
+ if (theManagerBytes > 0)
+ theManagerFact.m_Align = 100 * theManagerFact.m_Align / theManagerBytes;
+
+ CullHistogram(theManager->GetHistogram(), theValue, outFacts.m_Histogram[theManagerIndex]);
+ }
+
+ // Again this is the grand-total separate percentage computation that has
+ // to be done in the end when all sums have been added.
+ outFacts.m_ManagerState.m_Used = 0;
+ if (theTotalChunks > 0)
+ outFacts.m_ManagerState.m_Used = 100 * outFacts.m_ManagerState.m_Used / theTotalChunks;
+
+ outFacts.m_ManagerState.m_Align = 100;
+ if (theTotalBytes > 0)
+ outFacts.m_ManagerState.m_Align = 100 * outFacts.m_ManagerState.m_Align / theTotalBytes;
+
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+ // return thePresentationBytes;
+}
+
+//==============================================================================
+/**
+ * Find the HISTOGRAMLIMIT highest performers in the histogram.
+ * @param inHistogram array of CMemoryManager::HISTOGRAMCOUNT values
+ * each showing the number of allocation of that bytesize
+ * @param outResults collects the highest points of the histogram
+ */
+void CMemoryStatistics::CullHistogram(const CMemoryProbe::SValue *inHistogram,
+ const EMemoryValue inValue,
+ SHistogramScore outResults[HISTOGRAMCOUNT])
+{
+ // Always clear even if there is no data
+ Q3DStudio_memset(outResults, 0, sizeof(SHistogramScore));
+
+ // Return quickly when no data
+ if (!inHistogram)
+ return;
+
+ // Scan full histogram
+ INT32 theLowestIndex = 0;
+ for (UINT16 theSize = 0; theSize < 512; ++theSize) {
+ // Is this count higher than the lowest recorded count?
+ if (inHistogram[theSize].m_Value[inValue] > outResults[theLowestIndex].m_Count) {
+ outResults[theLowestIndex].m_Count = inHistogram[theSize].m_Value[inValue];
+ outResults[theLowestIndex].m_Size = theSize;
+
+ // Find new low in high score
+ theLowestIndex = 0;
+ for (UINT16 theResult = 1; theResult < HISTOGRAMCOUNT; ++theResult)
+ if (outResults[theResult].m_Count < outResults[theLowestIndex].m_Count)
+ theLowestIndex = theResult;
+ }
+ }
+
+ // Sort histogram - brute force for now so don't call this all the time
+ ::qsort(outResults, 10, sizeof(SHistogramScore), CompareHistogram);
+}
+
+//==============================================================================
+/**
+ * Helper comparison function for CullHistogram
+ */
+int CMemoryStatistics::CompareHistogram(const void *arg1, const void *arg2)
+{
+ return reinterpret_cast<const SHistogramScore *>(arg2)->m_Count
+ - reinterpret_cast<const SHistogramScore *>(arg1)->m_Count;
+}
+
+//==============================================================================
+/**
+ * Helper comparison function for CMemoryStatistics::HeapReport
+ */
+int CMemoryStatistics::CompareHeap(const void *inEntry1, const void *inEntry2)
+{
+ return reinterpret_cast<const CMemoryHeap::SReportEntry *>(inEntry1)->m_Size
+ - reinterpret_cast<const CMemoryHeap::SReportEntry *>(inEntry2)->m_Size;
+}
+
+//==============================================================================
+// REPORTING
+//==============================================================================
+
+//==============================================================================
+/**
+ * Simple memory usage report covering both bytes allocated and call count.
+ * @param inStream the stream we are sending the report or NULL to use logger
+ */
+void CMemoryStatistics::SimpleReport(IStream *inStream /*=NULL*/)
+{
+ CHAR theReportBuffer[REPORTSIZE];
+ CMemoryProbe theProbe;
+
+ // Basic info is always available
+ Report(inStream, "\n --- RUNTIME SIMPLE MEMORY REPORT ---\n");
+
+ // Only the first manager is reported for now
+ Q3DStudio_ASSERT(s_PoolManagers[0]);
+ theProbe = s_PoolManagers[0]->GetManagerData().m_Aligned;
+ theProbe.Combine(s_PoolManagers[0]->GetManagerData().m_Overflow);
+ Report(inStream, "PRESENTATION: Current Peak Alloc Free\n");
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Global:%12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Reset: %12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+
+ // Overflow is memory not serviced by memory pools - removed to make the simple report...
+ // simpler
+ /* theProbe = s_PoolManagers[0]->GetManagerData( ).m_Overflow;
+ Report( inStream, "OVERFLOW:\n" );
+ Q3DStudio_sprintf( theReportBuffer, sizeof( theReportBuffer ),
+ "Global:%12ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)\n",
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_PEAK )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_PEAK ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_ADDS )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_ADDS ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_DELETES )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_DELETES ) );
+ Report( inStream, theReportBuffer );
+ Q3DStudio_sprintf( theReportBuffer, sizeof( theReportBuffer ), "Reset:
+ %12ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)\n",
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_PEAK )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_PEAK ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_ADDS )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_ADDS ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_DELETES )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_DELETES ) );
+ Report( inStream, theReportBuffer );*/
+
+ // All managers share the same heap
+ theProbe = CMemoryHeap::GetProbe();
+ Report(inStream, "HEAP:\n");
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Global:%12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Reset: %12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer), "Tracking overhead: %dk\n",
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ (s_Overhead + sizeof(CMemoryHeap::TMemoryReport)) / 1024);
+#else
+ s_Overhead / 1024);
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ Report(inStream, theReportBuffer);
+}
+
+//==============================================================================
+/**
+ * Output the memory report log.
+ *
+ * The is always watched by a CMemoryProbe that records all activity. Most
+ * individual allocations will not be recorded though since they are handled
+ * by memory pools.
+ *
+ * A probe records three axis of information (value, scope and call/bytes).
+ *
+ * # Value (current,peak,add,del) tracks the current value along with its
+ * peak value, and also separately tracks adds(allocations) and deletes(frees)
+ * such that current = add - del.
+ * # Scope (local,global) tracks values since last reset or dawn of heap.
+ * # Call/Bytes tracks separately bytes and calls so you can distinguish between
+ * many small allocations and a few large.
+ *
+ * @param inStream the stream we are sending the report or NULL to use logger
+ */
+void CMemoryStatistics::HeapReport(IStream *inStream /*=NULL*/)
+{
+ Report(inStream, "\n --- RUNTIME HEAP MEMORY REPORT ---\n");
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ // Detailed info needs Q3DStudio_MEMORY_HEAPTRACKING defined
+ INT32 theCount = CMemoryHeap::GetReport()->GetCount();
+ ::qsort(&CMemoryHeap::GetReport()[0], static_cast<size_t>(theCount),
+ sizeof(CMemoryHeap::SReportEntry), CompareHeap);
+
+ CHAR theReportBuffer[REPORTSIZE];
+ for (INT32 theIndex = 0; theIndex < theCount; ++theIndex) {
+ CMemoryHeap::SReportEntry &theEntry = CMemoryHeap::GetReport()->operator[](theIndex);
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "%3d. %8d bytes - \"%s\" - %s (%d)\n", theIndex, theEntry.m_Size,
+ theEntry.m_Description, theEntry.m_File, theEntry.m_Line);
+ Report(inStream, theReportBuffer);
+ }
+#else
+ Report(inStream, " Unavailable: Q3DStudio_MEMORY_HEAPTRACKING not defined in this build\n");
+#endif
+}
+
+/* Example output of CMemoryStatistics::Report
+
+=POOL= HEAP CALLS USED ALIGN MISSES
+---------------------------------------------------------------
+All Managers 722k 38 72% 19%
+
+ Global 482k
+ 0: 16b x 1024 16k 2182 3% 13%
+ 1: 32b x 2048 64k 4123 96% 9% 38
+ 2: 48b x 512 24k 212 72% 21%
+ 3: 64b x 512 32k 454 11% 3%
+ .
+ 8: 512b x 128 64k 68 64% 22%
+*/
+
+//==============================================================================
+/**
+ * Return a text buffer describing the state of the memory system.
+ */
+void CMemoryStatistics::PoolReport(BOOL inPeak /*= true*/, BOOL inGlobal /*= true*/,
+ IStream *inStream /*=NULL*/)
+{
+ CHAR theLine[256] = { 0 };
+ SFactSheet theFacts;
+
+ GetFacts(theFacts, inPeak, inGlobal);
+
+ Report(inStream, "\n --- RUNTIME POOL MEMORY REPORT ---\n");
+ Q3DStudio_sprintf(theLine, 256,
+ "Mode: %s %s\nTotal Heap: %7dk(%d)\nPresentation: %7dk\n",
+ inGlobal ? "GLOBAL" : "RESET", inPeak ? "PEAK" : "CURRENT",
+ theFacts.m_HeapState.m_Bytes / 1024, theFacts.m_HeapState.m_Calls,
+ GetRequestedBytes(inPeak) / 1024);
+ Report(inStream, theLine);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Report(inStream, "=POOLS= HEAP HITS USED ALIGN MISS"
+ "\n");
+ Report(inStream, "-----------------------------------------------------------------"
+ "\n");
+ Q3DStudio_sprintf(theLine, 256, "All Managers %7dk %8d %5d%% %5d%% %6d"
+ "\n\n",
+ theFacts.m_ManagerState.m_Bytes / 1024, theFacts.m_ManagerState.m_Calls,
+ theFacts.m_ManagerState.m_Used, theFacts.m_ManagerState.m_Align,
+ theFacts.m_ManagerState.m_Miss);
+ Report(inStream, theLine);
+
+ for (INT32 theManagerIndex = 0; theManagerIndex < MANAGERCOUNT; ++theManagerIndex) {
+ SFactoid &theManagerFact = theFacts.m_Manager[theManagerIndex];
+ if (theManagerFact.m_Bytes > 0) {
+ Q3DStudio_sprintf(theLine, 256, "%-20s %7dk %8d %5d%% %5d%% %6d\n",
+ theManagerFact.m_Name, theManagerFact.m_Bytes / 1024,
+ theManagerFact.m_Calls, theManagerFact.m_Used, theManagerFact.m_Align,
+ theManagerFact.m_Miss);
+ Report(inStream, theLine);
+
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT;
+ ++thePoolIndex) {
+ SFactoid &thePoolFact = theFacts.m_Pool[theManagerIndex][thePoolIndex];
+ if (theManagerFact.m_Bytes > 0) {
+ Q3DStudio_sprintf(theLine, 256, "%-20s %7dk %8d %5d%% %5d%% %6d\n",
+ thePoolFact.m_Name, thePoolFact.m_Bytes / 1024,
+ thePoolFact.m_Calls, thePoolFact.m_Used, thePoolFact.m_Align,
+ thePoolFact.m_Miss);
+ Report(inStream, theLine);
+ }
+ }
+
+ // Histogram only valid for Current-Reset
+ if (inGlobal) {
+ Report(inStream, " Histogram: Only available in RESET mode\n");
+ } else {
+ Q3DStudio_sprintf(
+ theLine, 256,
+ " Histogram: 1:%3db(%3d) 2:%3db(%3d) 3:%3db(%3d) 4:%3db(%3d) 5:%3db(%3d)\n",
+ theFacts.m_Histogram[theManagerIndex][0].m_Size,
+ theFacts.m_Histogram[theManagerIndex][0].m_Count,
+ theFacts.m_Histogram[theManagerIndex][1].m_Size,
+ theFacts.m_Histogram[theManagerIndex][1].m_Count,
+ theFacts.m_Histogram[theManagerIndex][2].m_Size,
+ theFacts.m_Histogram[theManagerIndex][2].m_Count,
+ theFacts.m_Histogram[theManagerIndex][3].m_Size,
+ theFacts.m_Histogram[theManagerIndex][3].m_Count,
+ theFacts.m_Histogram[theManagerIndex][4].m_Size,
+ theFacts.m_Histogram[theManagerIndex][4].m_Count);
+ Report(inStream, theLine);
+ Q3DStudio_sprintf(
+ theLine, 256,
+ " 6:%3db(%3d) 7:%3db(%3d) 8:%3db(%3d) 9:%3db(%3d) 10:%3db(%3d)\n",
+ theFacts.m_Histogram[theManagerIndex][5].m_Size,
+ theFacts.m_Histogram[theManagerIndex][5].m_Count,
+ theFacts.m_Histogram[theManagerIndex][6].m_Size,
+ theFacts.m_Histogram[theManagerIndex][6].m_Count,
+ theFacts.m_Histogram[theManagerIndex][7].m_Size,
+ theFacts.m_Histogram[theManagerIndex][7].m_Count,
+ theFacts.m_Histogram[theManagerIndex][8].m_Size,
+ theFacts.m_Histogram[theManagerIndex][8].m_Count,
+ theFacts.m_Histogram[theManagerIndex][9].m_Size,
+ theFacts.m_Histogram[theManagerIndex][9].m_Count);
+ Report(inStream, theLine);
+ }
+ }
+ }
+#else
+ Report(inStream, " Unavailable: Q3DStudio_MEMORY_POOLTRACKING not defined in this build\n");
+#endif
+}
+
+//==============================================================================
+/**
+ * Dump the low-level memory list stored in each manager's hash bin.
+ *
+ * @note Q3DStudio_MEMORY_LINETRACKING has to be set to 1 in AKMemorySettings.h or
+ * the compiler for this method to save out any data.
+ *
+ * @param inStream the stream we are sending the report or NULL to use logger
+ */
+void CMemoryStatistics::LineReport(IStream *inStream /*=NULL*/)
+{
+ Report(inStream, "\n--- RUNTIME LINE MEMORY REPORT ---\n");
+#if Q3DStudio_MEMORY_LINETRACKING
+ Report(inStream, "ADDR, SIZE, TYPE, LINE, FILE, \n");
+
+ INT32 theTotalBytes = 0;
+ for (INT32 theManagerIndex = 0; theManagerIndex < MANAGERCOUNT; ++theManagerIndex)
+ if (s_PoolManagers[theManagerIndex] && s_PoolManagers[theManagerIndex]->GetLineTracker())
+ theTotalBytes += s_PoolManagers[theManagerIndex]->GetLineTracker()->Report(inStream);
+
+ CHAR theTotal[64];
+ theTotal[0] = '\0';
+
+ Q3DStudio_sprintf(theTotal, sizeof(theTotal), "TOTAL: , %8d\n", theTotalBytes);
+ Report(inStream, theTotal);
+#else
+ Report(inStream, " Unavailable: Q3DStudio_MEMORY_LINETRACKING not defined in this build\n");
+#endif // Q3DStudio_MEMORY_LINETRACKING
+}
+
+//==============================================================================
+/**
+ * Output to log or stream if available.
+ * @param inMessage string to be reported
+ * @param inStream stream to be used or output to log if NULL
+ */
+void CMemoryStatistics::Report(IStream *inStream, const CHAR *inMessage)
+{
+ if (inStream)
+ inStream->WriteRaw(inMessage, (INT32)::strlen(inMessage));
+ else
+ qCInfo(qt3ds::TRACE_INFO) << inMessage;
+}
+
+//==============================================================================
+/**
+ * Output full memory report to log or stream if available.
+ * @param inStream stream to be used or output to log if NULL
+ */
+void CMemoryStatistics::FullReport(IStream *inStream /*=NULL*/)
+{
+ SimpleReport(inStream);
+ HeapReport(inStream);
+ LineReport(inStream);
+ PoolReport(false, false, inStream);
+ PoolReport(true, false, inStream);
+ PoolReport(false, true, inStream);
+ PoolReport(true, true, inStream);
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICMemoryTracker.cpp b/src/Runtime/Source/System/Source/UICMemoryTracker.cpp
new file mode 100644
index 00000000..a926cf6c
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICMemoryTracker.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICMemoryTracker.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Construct and reset the tracker.
+ */
+CMemoryTracker::CMemoryTracker()
+ : m_TrackingOverhead(0)
+{
+ Q3DStudio_memset(&m_TrackingHashBin, 0, sizeof(m_TrackingHashBin));
+ CMemoryStatistics::Overhead() += sizeof(m_TrackingHashBin);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMemoryTracker::~CMemoryTracker()
+{
+ CMemoryStatistics::Overhead() -= sizeof(m_TrackingHashBin);
+}
+
+//==============================================================================
+/**
+ * Add information about allocation
+ * @param inPtr contains info about a new allocation
+ */
+void CMemoryTracker::Remember(SMemoryInfo *inPointer)
+{
+ if (inPointer) {
+ // Update global tracking
+ m_TrackingOverhead += sizeof(SMemoryInfo);
+
+ // Locate a suitable hashbin
+ size_t theHashBin =
+ (reinterpret_cast<size_t>(inPointer) >> 2) % Q3DStudio_MEMORY_LINETRACKINGSIZE;
+ size_t theStartHashBin = theHashBin;
+
+ while (m_TrackingHashBin[theHashBin]) {
+ ++theHashBin;
+ if (theHashBin >= Q3DStudio_MEMORY_LINETRACKINGSIZE)
+ theHashBin = 0;
+
+ if (theHashBin == theStartHashBin) {
+ // We've run out of room in the hashbin.
+ // Abort and increase the bin size.
+ qCCritical(qt3ds::OUT_OF_MEMORY)
+ << "Memory Tracker Error: Ran out of room in tracker hashbin "
+ << Q3DStudio_MEMORY_LINETRACKINGSIZE;
+ // exit( -1 );
+ }
+ }
+
+ // Set WatchGuard and store the pointer in the hash bin
+ inPointer->m_DogTag = TRACKER_DOGTAG;
+ m_TrackingHashBin[theHashBin] = inPointer;
+ }
+}
+
+//==============================================================================
+/**
+ * Remove information on an allocation
+ * @param inPtr contains info about the allocation we are releasing
+ */
+void CMemoryTracker::Forget(SMemoryInfo *inPointer)
+{
+ if (inPointer) {
+ // Update global tracking
+ m_TrackingOverhead -= sizeof(SMemoryInfo);
+
+ // Locate the pointer in the hash bin
+ size_t theHashBin = Q3DStudio_max<size_t>(0, (reinterpret_cast<size_t>(inPointer) >> 2)
+ % Q3DStudio_MEMORY_LINETRACKINGSIZE);
+ size_t theStartHashBin = theHashBin;
+
+ while (m_TrackingHashBin[theHashBin] != inPointer) {
+ ++theHashBin;
+ if (theHashBin >= Q3DStudio_MEMORY_LINETRACKINGSIZE)
+ theHashBin = 0;
+
+ if (theHashBin == theStartHashBin) {
+ // We were unable to locate the pointer in the hash bin.
+ // This is really bad, but not catastrophic
+ qCWarning(qt3ds::OUT_OF_MEMORY)
+ << "Memory Tracker Warning. Can't find pointer in tracker hashbin";
+ return;
+ }
+ }
+
+ // Verify watch guard. Something is trashing memory if this call fails.
+ Q3DStudio_ASSERT(m_TrackingHashBin[theHashBin]->m_DogTag == TRACKER_DOGTAG);
+
+ // Clear the pointer from the hash bin
+ m_TrackingHashBin[theHashBin] = NULL;
+ }
+}
+
+//==============================================================================
+/**
+ * Dump the memory list stored in the hash bin.
+ * @param inFileName the report filename or NULL to dump to the logger
+ */
+INT32 CMemoryTracker::Report(IStream *inStream /*=NULL*/)
+{
+ INT32 theTotalBytes = 0;
+ CHAR theLine[256];
+
+ for (INT32 theBinIndex = 0; theBinIndex < Q3DStudio_MEMORY_LINETRACKINGSIZE; ++theBinIndex) {
+ if (m_TrackingHashBin[theBinIndex]) {
+ CMemoryTracker::SMemoryInfo *theInfo = m_TrackingHashBin[theBinIndex];
+
+ Q3DStudio_sprintf(theLine, sizeof(theLine), "0x%p, %8d, %s, %s(%hd)\n", theInfo,
+ theInfo->m_Size, theInfo->m_Type, theInfo->m_File, theInfo->m_Line);
+
+ CMemoryStatistics::Report(inStream, theLine);
+ theTotalBytes += theInfo->m_Size;
+ }
+ }
+
+ return theTotalBytes;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICSyncPrimitive.cpp b/src/Runtime/Source/System/Source/UICSyncPrimitive.cpp
new file mode 100644
index 00000000..cf9bb451
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICSyncPrimitive.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#include "RuntimePrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SystemPrefix.h"
+#include "UICSyncPrimitive.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CSyncPrimitive::CSyncPrimitive()
+ : m_LockHandle(0)
+{
+ AppCreateLockPrimitive(&m_LockHandle);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CSyncPrimitive::~CSyncPrimitive()
+{
+ AppDestroyLockPrimitive(&m_LockHandle);
+}
+
+//==============================================================================
+/**
+ *
+ */
+int CSyncPrimitive::BeginSync()
+{
+ AppBeginSync(m_LockHandle);
+ return 1;
+}
+
+//==============================================================================
+/**
+ *
+ */
+int CSyncPrimitive::EndSync()
+{
+ AppEndSync(m_LockHandle);
+ return 1;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICThreadManager.cpp b/src/Runtime/Source/System/Source/UICThreadManager.cpp
new file mode 100644
index 00000000..3d2645d8
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICThreadManager.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICThreadManager.h"
+
+#ifdef _TEGRAPLATFORM
+#include <Winbase.h.>
+
+// This is to try to throttle background threads to not hog all
+// the cpu while doing work.
+// http://msdn.microsoft.com/en-us/library/aa450618.aspx
+static const INT32 s_ThreadPriority = 252;
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CThreadManager::CThreadManager(INT32 inThreads)
+ : m_WorkItems(0)
+{
+ Q3DStudio_ASSERT(inThreads > 0);
+ m_Running = true;
+ for (INT32 theIter = 0; theIter < inThreads; theIter++) {
+ m_Threads.Push(AppCreateThread(ThreadSpinFunction, this));
+ }
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CThreadManager::~CThreadManager()
+{
+ m_Running = false;
+ for (INT32 theIter = 0; theIter < m_Threads.GetCount(); theIter++) {
+ AppDestroyThread(m_Threads[theIter]);
+ }
+ m_Threads.Clear();
+}
+
+//==============================================================================
+/**
+* Check for completed work and return the number of work items left in the queue
+*/
+INT32 CThreadManager::Update()
+{
+ CheckForCompletedWork();
+ return m_WorkQueue.GetCount();
+}
+
+//==============================================================================
+/**
+ * Push work onto the work queue
+ */
+void CThreadManager::Push(const SThreadWorkItem &inItem)
+{
+ Q3DStudio_ASSERT(inItem.m_UserData && inItem.m_Function);
+ m_WorkQueue.Push(inItem);
+}
+
+struct SItemNameHashPredicate
+{
+ UINT32 m_ItemNameHash;
+ bool operator()(const SThreadWorkItem &inItem)
+ {
+ return inItem.m_WorkItemNameHash == m_ItemNameHash;
+ }
+};
+//==============================================================================
+/**
+ * Remove a list of items currently in the work queue.
+ */
+void CThreadManager::Remove(UINT32 inItemNameHash, CArray<SThreadWorkItem> &ioRemovedItems)
+{
+ SItemNameHashPredicate thePredicate = { inItemNameHash };
+ m_WorkQueue.Remove(thePredicate, ioRemovedItems);
+}
+
+//==============================================================================
+/**
+ * Return a reference to the scratch pad
+ */
+CThreadSafeScratchPad &CThreadManager::GetScratchPad()
+{
+ return m_ScratchPad;
+}
+
+//==============================================================================
+/**
+* Pop completed work off the result queue
+*/
+bool CThreadManager::Pop(SThreadResultItem &outItem)
+{
+ return m_ResultsQueue.Pop(outItem);
+}
+
+//==============================================================================
+/**
+ * The function that created threads call (worker threads)
+ */
+void *CThreadManager::ThreadSpinFunction(void *inUserData)
+{
+#ifdef _TEGRAPLATFORM
+// CeSetThreadPriority( GetCurrentThread(), s_ThreadPriority );
+#endif
+
+ CThreadManager *theThreadManager = reinterpret_cast<CThreadManager *>(inUserData);
+ theThreadManager->DoWork();
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+* The function that created threads spin on (worker threads)
+*/
+void CThreadManager::DoWork()
+{
+ volatile BOOL theRunning = m_Running;
+ while (theRunning) {
+ SThreadWorkItem theWorkItem = { 0 };
+ while (m_WorkQueue.Pop(theWorkItem)) {
+ SThreadResultItem theResultItem =
+ theWorkItem.m_Function(theWorkItem.m_UserData, m_ScratchPad);
+
+ // For now, always ensure we have a valid result item
+ Q3DStudio_ASSERT(theResultItem.m_Function && theResultItem.m_UserData);
+
+ if (theResultItem.m_Function && theResultItem.m_UserData)
+ m_ResultsQueue.Push(theResultItem);
+ }
+ // Sleep after every task..?
+ AppSleepThread();
+
+ theRunning = m_Running;
+ }
+}
+
+//==============================================================================
+/**
+* The function that created threads spin on (main thread)
+*/
+void CThreadManager::CheckForCompletedWork()
+{
+ SThreadResultItem theResultItem = { 0 };
+ while (m_ResultsQueue.Pop(theResultItem)) {
+ theResultItem.m_Function(theResultItem.m_UserData, m_ScratchPad);
+ }
+}
+}
diff --git a/src/Runtime/Source/System/Source/UICTimer.cpp b/src/Runtime/Source/System/Source/UICTimer.cpp
new file mode 100644
index 00000000..47c9605b
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICTimer.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICTimer.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CTimer::CTimer(ITimeProvider &inProvider)
+ : m_TimeProvider(inProvider)
+ , m_IsRunning(false)
+{
+ Start();
+}
+
+//==============================================================================
+/**
+ * Start the timer
+ */
+void CTimer::Start()
+{
+ if (!m_IsRunning)
+ m_StartTime = m_TimeProvider.GetCurrentTimeMicroSeconds();
+ m_IsRunning = true;
+}
+
+//==============================================================================
+/**
+ * Stop the timer
+ */
+void CTimer::Stop()
+{
+ if (m_IsRunning)
+ m_StartTime = m_TimeProvider.GetCurrentTimeMicroSeconds() - m_StartTime;
+
+ m_IsRunning = false;
+}
+
+//==============================================================================
+/**
+ * Reset the timer
+ */
+void CTimer::Reset()
+{
+ if (m_IsRunning)
+ m_StartTime = m_TimeProvider.GetCurrentTimeMicroSeconds();
+ else
+ m_StartTime = 0;
+}
+
+//==============================================================================
+/**
+ * Gets the current time in milliseconds.
+ * @return the current time since timer was started(in miliseconds),
+ * or time when it was stopped
+ */
+TTimeUnit CTimer::GetTimeMilliSecs()
+{
+ return GetTimeMicroSecs() / 1000;
+}
+
+//=============================================================================
+/**
+ * Get the number of usecs elapsed since start was called.
+ * If the timer is running then this will return the time from when start was
+ * called. If the timer is stopped then this will return the amount of time
+ * between the start and last stop.
+ * @return returns the elasped micro second.
+ */
+TMicroSeconds CTimer::GetTimeMicroSecs()
+{
+ if (m_IsRunning)
+ return m_TimeProvider.GetCurrentTimeMicroSeconds() - m_StartTime;
+ else
+ return m_StartTime;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICTypes.cpp b/src/Runtime/Source/System/Source/UICTypes.cpp
new file mode 100644
index 00000000..25d41c8b
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICTypes.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Return 2^inBitCount - 1.
+ * @param inBitCount number of bits available
+ * @param inUnsigned true if all bits are available
+ * @return the higest number the bits can represent
+ */
+INT32 Q3DStudio_maxbits(const INT32 inBitCount, const BOOL inUnsigned)
+{
+ Q3DStudio_ASSERT(inBitCount < 32);
+ if (inUnsigned)
+ return (1 << inBitCount) - 1;
+ else
+ return (1 << (inBitCount - 1)) - 1;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/System/Source/UICVector3.cpp b/src/Runtime/Source/System/Source/UICVector3.cpp
new file mode 100644
index 00000000..5244451b
--- /dev/null
+++ b/src/Runtime/Source/System/Source/UICVector3.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICVector3.h"
+#include "UICMatrix.h"
+#include "UICDataLogger.h"
+#include <math.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+extern const float RUNTIME_EPSILON = 0.0001f;
+const float RUNTIME_SQUARE_EPSILON = 0.000001f;
+
+//==============================================================================
+/**
+ * Simple constructor - creates a NULL vector.
+ */
+RuntimeVector3::RuntimeVector3()
+ : m_X(0.0f)
+ , m_Y(0.0f)
+ , m_Z(0.0f)
+{
+}
+
+//==============================================================================
+/**
+ * Construction from three array value.
+ * @param inVector the source array
+ */
+RuntimeVector3::RuntimeVector3(const float inVector[3])
+ : m_X(inVector[0])
+ , m_Y(inVector[1])
+ , m_Z(inVector[2])
+{
+}
+
+//==============================================================================
+/**
+ * Construction from three coordinates.
+ * @param inX the m_X coordinate
+ * @param inY the m_Y coordinate
+ * @param inZ the m_Z coordinate
+ */
+RuntimeVector3::RuntimeVector3(const float inX, const float inY, const float inZ)
+ : m_X(inX)
+ , m_Y(inY)
+ , m_Z(inZ)
+{
+}
+
+//==============================================================================
+/**
+ * Copy constructor
+ * @param inVector the source vector
+ */
+RuntimeVector3::RuntimeVector3(const RuntimeVector3 &inVector)
+ : m_X(inVector.m_X)
+ , m_Y(inVector.m_Y)
+ , m_Z(inVector.m_Z)
+{
+}
+
+//==============================================================================
+/**
+ * Assignment of coordinates.
+ * @param inX the m_X coordinate
+ * @param inY the m_Y coordinate
+ * @param inZ the m_Z coordinate
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::Set(const float inX, const float inY, const float inZ)
+{
+ m_X = inX;
+ m_Y = inY;
+ m_Z = inZ;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Assignment of coordinates using another vector.
+ * @param inVector the vector to be copied.
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::Set(const RuntimeVector3 &inVector)
+{
+ m_X = inVector.m_X;
+ m_Y = inVector.m_Y;
+ m_Z = inVector.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compare this vector with another. Exact match is not needed but instead
+ * an error of EPSILON is allowed.
+ * @param inVector the vector we are compared with
+ * @return true if the vectors are close to identical
+ * @see EPSILON
+ */
+bool RuntimeVector3::operator==(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+
+ return (::fabsf(m_X - inVector.m_X) < RUNTIME_EPSILON) && (::fabsf(m_Y - inVector.m_Y) < RUNTIME_EPSILON)
+ && (::fabsf(m_Z - inVector.m_Z) < RUNTIME_EPSILON);
+}
+
+//==============================================================================
+/**
+ * Compare this vector with another. Exact match is not needed but instead
+ * an error of EPSILON is allowed.
+ * @param inVector the vector we are compared with
+ * @return true if the vectors are not even close to identical
+ * @see EPSILON
+ */
+bool RuntimeVector3::operator!=(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+
+ return (::fabsf(m_X - inVector.m_X) > RUNTIME_EPSILON) || (::fabsf(m_Y - inVector.m_Y) > RUNTIME_EPSILON)
+ || (::fabsf(m_Z - inVector.m_Z) > RUNTIME_EPSILON);
+}
+
+//==============================================================================
+/**
+ * Add this vector with another but do not modify this vector.
+ * @param inVector the second vector being added
+ * @return a new vector
+ */
+RuntimeVector3 RuntimeVector3::operator+(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+
+ return RuntimeVector3(m_X + inVector.m_X, m_Y + inVector.m_Y, m_Z + inVector.m_Z);
+}
+
+//==============================================================================
+/**
+ * Add two vectors but do not modify this vector.
+ * @param inVector vector being subtracted
+ * @return a new vector
+ */
+RuntimeVector3 RuntimeVector3::operator-(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return RuntimeVector3(m_X - inVector.m_X, m_Y - inVector.m_Y, m_Z - inVector.m_Z);
+}
+
+//==============================================================================
+/**
+ * Get a scaled copy of this vector.
+ * @param inFactor the factor that scales each coordinate
+ * @return a new scaled vector
+ */
+RuntimeVector3 RuntimeVector3::operator*(float inFactor) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return RuntimeVector3(m_X * inFactor, m_Y * inFactor, m_Z * inFactor);
+}
+
+//==============================================================================
+/**
+ * Invert the vector.
+ * @return the inverted copy of this vector
+ */
+RuntimeVector3 RuntimeVector3::operator-() const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return RuntimeVector3(-m_X, -m_Y, -m_Z);
+}
+
+//==============================================================================
+/**
+ * Simple assignment.
+ * @param inVector the new vector
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator=(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ if (&inVector != this) {
+ m_X = inVector.m_X;
+ m_Y = inVector.m_Y;
+ m_Z = inVector.m_Z;
+ }
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Increment this vector.
+ * @param inVector has the coordinates by which this vector will be incremented
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator+=(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X += inVector.m_X;
+ m_Y += inVector.m_Y;
+ m_Z += inVector.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Decrement this vector.
+ * @param inVector has the coordinates by which this vector will be decremented
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator-=(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X -= inVector.m_X;
+ m_Y -= inVector.m_Y;
+ m_Z -= inVector.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Scale this vector by a factor.
+ * @param inFactor the scale factor
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator*=(float inFactor)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X *= inFactor;
+ m_Y *= inFactor;
+ m_Z *= inFactor;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Calculates the squared distance between this vector and another.
+ * This is often used in sorting situations where the real distance isn't needed.
+ * @param inVector vector to which the distance is being calculated
+ * @return the squared distance between vectors
+ */
+float RuntimeVector3::DistanceSquared(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return (m_X - inVector.m_X) * (m_X - inVector.m_X) + (m_Y - inVector.m_Y) * (m_Y - inVector.m_Y)
+ + (m_Z - inVector.m_Z) * (m_Z - inVector.m_Z);
+}
+
+//==============================================================================
+/**
+ * Calculates the distance between this vector and another.
+ * @param inVector vector to which the distance is being calculated
+ * @return the distance between vectors
+ */
+float RuntimeVector3::Distance(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return ::sqrtf((m_X - inVector.m_X) * (m_X - inVector.m_X)
+ + (m_Y - inVector.m_Y) * (m_Y - inVector.m_Y)
+ + (m_Z - inVector.m_Z) * (m_Z - inVector.m_Z));
+}
+
+//==============================================================================
+/**
+ * Calculates the squared length (squared magnitude) of the current vector.
+ * @return the squared length of this vector
+ */
+float RuntimeVector3::LengthSquared() const
+{
+ return m_X * m_X + m_Y * m_Y + m_Z * m_Z;
+}
+
+//==============================================================================
+/**
+ * Calculates the length (magnitude) of the current vector.
+ * @return the length of this vector
+ */
+float RuntimeVector3::Length() const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return ::sqrtf(m_X * m_X + m_Y * m_Y + m_Z * m_Z);
+}
+
+//==============================================================================
+/**
+ * Calculates the dot product of this vector and another.
+ * @param inVector vector measuring with
+ * @return the dot product
+ * @see operator*
+ */
+float RuntimeVector3::DotProduct(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return m_X * inVector.m_X + m_Y * inVector.m_Y + m_Z * inVector.m_Z;
+}
+
+//==============================================================================
+/**
+ * Calculates the cross product of this vector and another and modifies this vector
+ * @param inVector other vector
+ * @return this cross product vector
+ * @see operator%
+ * @see operator%=
+ */
+RuntimeVector3 &RuntimeVector3::CrossProduct(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ float theX = m_Y * inVector.m_Z - m_Z * inVector.m_Y;
+ float theY = m_Z * inVector.m_X - m_X * inVector.m_Z;
+ float theZ = m_X * inVector.m_Y - m_Y * inVector.m_X;
+
+ m_X = theX;
+ m_Y = theY;
+ m_Z = theZ;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Normalizes the current vector making it a unit vector.
+ * The normalized vector is defined to be: V_norm = V / Magnitude(V).
+ * @return this normalized vector
+*/
+RuntimeVector3 &RuntimeVector3::Normalize()
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ float theLengthSquared = LengthSquared();
+ if ((theLengthSquared > RUNTIME_SQUARE_EPSILON) && ::fabsf(theLengthSquared - 1.0f) > RUNTIME_SQUARE_EPSILON) {
+ float theInvLength = 1.0f / ::sqrtf(theLengthSquared);
+ m_X *= theInvLength;
+ m_Y *= theInvLength;
+ m_Z *= theInvLength;
+ }
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the minimum between
+ * this vector and another.
+ * @param inVector vector that whose elements are tested against the
+ * current vector to build the minimum.
+ * @return this minimized vector
+*/
+RuntimeVector3 &RuntimeVector3::Minimize(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X = Q3DStudio_min<float>(m_X, inVector.m_X);
+ m_Y = Q3DStudio_min<float>(m_Y, inVector.m_Y);
+ m_Z = Q3DStudio_min<float>(m_Z, inVector.m_Z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the maximum between
+ * this vector and another.
+ * @param inVector vector that whose elements are tested against the
+ * current vector to build the maximum.
+ * @return this maximized vector
+*/
+RuntimeVector3 &RuntimeVector3::Maximize(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X = Q3DStudio_max<float>(m_X, inVector.m_X);
+ m_Y = Q3DStudio_max<float>(m_Y, inVector.m_Y);
+ m_Z = Q3DStudio_max<float>(m_Z, inVector.m_Z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector by performing a linear interpolation
+ * between the current vector and the given vector.
+ *
+ * If inFactor is 0.0 then this vector remains unchanged. If inFactor is
+ * 1.0 then this vector becomes inDestVector. If inFactor is between 0.0-1.0
+ * then this vector becomes a vector between this old vector and inDestVector
+ * proportionally interpolated based in inFactor. If inFactor is less than 0
+ * or more than 1 then this vector is extrapolated.
+ *
+ * @param inDestVector Second vector for the interpolation
+ * @param inFactor Weight for the interpolation
+ * @return this interpolated vector
+ */
+RuntimeVector3 &RuntimeVector3::InterpolateLinear(const RuntimeVector3 &inDestVector, float inFactor)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X += inFactor * (inDestVector.m_X - m_X);
+ m_Y += inFactor * (inDestVector.m_Y - m_Y);
+ m_Z += inFactor * (inDestVector.m_Z - m_Z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Transforms this vector by the given matrix.
+ *
+ * The matrix is row column of the form Matrix[row][column]:
+@code
+ | m0 m1 m2 w |
+ | m4 m5 m6 w |
+ | m8 m9 m10 w |
+ | tX tY tZ w |
+@endcode
+ * @param inMatrix transform matrix
+ * @return this transformed vector
+ */
+RuntimeVector3 &RuntimeVector3::Transform(const RuntimeMatrix &inMatrix)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ float theX = m_X;
+ float theY = m_Y;
+ float theZ = m_Z;
+
+ m_X = theX * inMatrix.Get(0, 0) + theY * inMatrix.Get(1, 0) + theZ * inMatrix.Get(2, 0);
+ m_Y = theX * inMatrix.Get(0, 1) + theY * inMatrix.Get(1, 1) + theZ * inMatrix.Get(2, 1);
+ m_Z = theX * inMatrix.Get(0, 2) + theY * inMatrix.Get(1, 2) + theZ * inMatrix.Get(2, 2);
+
+ m_X += inMatrix.Get(3, 0);
+ m_Y += inMatrix.Get(3, 1);
+ m_Z += inMatrix.Get(3, 2);
+
+ return *this;
+}
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UICCompiler/Source/UICCompilerMain.cpp b/src/Runtime/Source/UICCompiler/Source/UICCompilerMain.cpp
new file mode 100644
index 00000000..49bb7933
--- /dev/null
+++ b/src/Runtime/Source/UICCompiler/Source/UICCompilerMain.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "render/Qt3DSRenderContext.h"
+#ifdef _WIN32
+#pragma warning(push)
+#pragma warning(disable : 4201)
+#endif
+#include "UICTypes.h"
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+#include "UICRenderRuntimeBinding.h"
+#include "UICApplication.h"
+#include "UICInputEngine.h"
+#include "foundation/FileTools.h"
+#include "UICWindowSystem.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCache.h"
+
+#include <QSurfaceFormat>
+
+using namespace uic::render;
+
+#if defined(_LINUX) || defined(_MACOSX) || defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+namespace qt3ds {
+void NVAssert(const char *exp, const char *file, int line, bool *igonore)
+{
+ qCritical() << "NVAssertion thrown: " << file << " " << line << " " << exp;
+}
+}
+
+#ifndef EASTL_DEBUG_BREAK
+void EASTL_DEBUG_BREAK()
+{
+ qFatal() << "EASTL_DEBUG_BREAK: Assertion blown";
+}
+
+#endif
+#endif
+
+struct SNullTimeProvider : public Q3DStudio::ITimeProvider
+{
+ Q3DStudio::INT64 GetCurrentTimeMicroSeconds() override { return 0; }
+};
+
+struct SNullWindowSystem : public Q3DStudio::IWindowSystem
+{
+ Q3DStudio::SSize GetWindowDimensions() override { return Q3DStudio::SSize(); }
+
+ void SetWindowDimensions(const Q3DStudio::SSize &) override {}
+ // For platforms that support it, we get the egl info for render plugins
+ // Feel free to return NULL.
+ Q3DStudio::SEGLInfo *GetEGLInfo() override { return NULL; }
+
+ // on some systems we allow our default render target to be a offscreen buffer
+ // otherwise return 0;
+ int GetDefaultRenderTargetID() override { return 0; }
+ // returns the depth buffer bit count for the render window
+ // does not really matter here
+ int GetDepthBitCount() override { return 16; }
+};
+
+int main(int c, char **v)
+{
+ QGuiApplication app(c, v);
+
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(4, 3);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ QSurfaceFormat::setDefaultFormat(format);
+
+ QOpenGLContext *context = new QT_PREPEND_NAMESPACE(QOpenGLContext);
+ context->setFormat(format);
+ bool success = context->create();
+ if (!success)
+ qDebug() << "Could not create opengl context";
+
+ QOffscreenSurface *surface = new QOffscreenSurface;
+ surface->setFormat(format);
+ surface->create();
+ context->makeCurrent(surface);
+
+ if (c < 2) {
+ puts("Usage: UICCompiler project.uia\n"
+ "No other usage is appropriate and there are at this time no options\n"
+ "Binary files will be under projectdir/binary/\n"
+ "Similar to if you had run UICViewer project.uia -saveBinary\n"
+ "With the important difference that the shader cache is neither created nor updated");
+ return -1;
+ }
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+
+ eastl::string uiaFile(v[1]);
+
+ eastl::string theApplicationDirectory
+ = QCoreApplication::applicationDirPath().toLatin1().constData();
+ SNullTimeProvider theNullTimeProvider;
+ SNullWindowSystem theNullWindowSystem;
+
+ NVScopedRefCounted<IUICRenderFactoryCore> theRenderFactoryCore =
+ IUICRenderFactoryCore::CreateRenderFactoryCore(theApplicationDirectory.c_str(),
+ theNullWindowSystem, theNullTimeProvider);
+
+ NVScopedRefCounted<IUICRenderFactory> theRenderFactory(
+ theRenderFactoryCore->CreateRenderFactory(QSurfaceFormat::defaultFormat()));
+
+ // Ensure we aren't compiling any shaders.
+ theRenderFactory->GetUICRenderContext().GetShaderCache().SetShaderCompilationEnabled(false);
+ Q3DStudio::CInputEngine theInputEngine;
+
+ NVScopedRefCounted<uic::runtime::IApplicationCore> theAppCore =
+ uic::runtime::IApplicationCore::CreateApplicationCore(*theRenderFactoryCore,
+ theApplicationDirectory.c_str());
+
+ bool loadStarted = theAppCore->BeginLoad(uiaFile.c_str());
+ if (loadStarted) {
+ NVScopedRefCounted<uic::runtime::IApplication> theApp =
+ theAppCore->CreateApplication(theInputEngine, 0, *theRenderFactory);
+ theApp->SaveBinary();
+ return 0;
+ } else {
+ printf("Failed to compile %s\n, please review log output for reason\n", uiaFile.c_str());
+ return -1;
+ }
+}
diff --git a/src/Runtime/Source/UICEvent/Include/EventSystem.h b/src/Runtime/Source/UICEvent/Include/EventSystem.h
new file mode 100644
index 00000000..5ace5445
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Include/EventSystem.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESSAGE_SYSTEM_H
+#define MESSAGE_SYSTEM_H
+#include <cstdlib>
+#include "EventSystemC.h"
+
+namespace uic {
+namespace evt {
+
+ typedef TUICEventSystemStr TEventStr;
+
+ // Factory from the provider's perspective.
+ class IEventFactory
+ {
+ protected:
+ virtual ~IEventFactory() {}
+ public:
+ virtual SUICEventSystemEvent &CreateEvent(int numData) = 0;
+ // Guaranteed to be at least 4K - sizeof(SUICEventSystemEvent)
+ virtual size_t GetMaxNumEventData() = 0;
+ // Guaranteed to be at least 4K
+ virtual size_t GetMaxStrLength() = 0;
+
+ virtual SUICEventSystemRegisteredStr RegisterStr(TEventStr inSrc) = 0;
+ // Null terminates if strlen(inSrc) > getMaxStrLength
+ virtual TEventStr AllocateStr(TEventStr inSrc) = 0;
+ // Returns null if inLength > getMaxStrLength
+ virtual TEventStr AllocateStr(int inLength) = 0;
+ };
+
+ class IEventProvider
+ {
+ protected:
+ virtual ~IEventProvider() {}
+ public:
+ // Return the next N events, placed into the event buffer.
+ virtual size_t GetNextEvents(IEventFactory &inFactory, SUICEventSystemEvent **outBuffer,
+ size_t bufLen) = 0;
+ virtual void Release() = 0;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICEvent/Include/EventSystemC.h b/src/Runtime/Source/UICEvent/Include/EventSystemC.h
new file mode 100644
index 00000000..fed6b8d9
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Include/EventSystemC.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_EVENT_SYSTEM_C_H
+#define UIC_EVENT_SYSTEM_C_H
+#include <stddef.h> //size_t
+
+// Interface we expect plugins to use in order to interace with the event system.
+// This interface is design to avoid using c++ vtables and the C++ abi isn't stable
+// across compilers.
+
+#ifdef _cplusplus
+extern "C" {
+#endif
+
+// Obnoxious long names to void namespace conflicts
+enum EUICEventSystemEventTypes {
+ EUICEventSystemEventTypesNoData = 0,
+ EUICEventSystemEventTypesString = 1,
+ EUICEventSystemEventTypesNumber = 2,
+};
+
+typedef const char *TUICEventSystemStr;
+
+typedef struct _SUICEventSystemEventValue
+{
+ EUICEventSystemEventTypes m_Type;
+ double m_Number;
+ TUICEventSystemStr m_String;
+} SUICEventSystemEventValue;
+
+typedef struct _SUICEventSystemRegisteredStr
+{
+ TUICEventSystemStr m_Data;
+} SUICEventSystemRegisteredStr;
+
+typedef struct _SUICEventSystemEventData
+{
+ SUICEventSystemRegisteredStr m_Name;
+ SUICEventSystemEventValue m_Value;
+} SUICEventSystemEventData;
+
+typedef struct _SUICEventSystemEvent
+{
+ SUICEventSystemEventData *m_Data; // contiguous block of event data.
+ int m_NumData;
+} SUICEventSystemEvent;
+
+typedef SUICEventSystemEvent *(*TUICEventSystemEventFactoryCreateEventFn)(void *inFactory,
+ int numData);
+typedef size_t (*TUICEventSystemEventFactoryMaxNumEventDataFn)(void *inFactory);
+typedef size_t (*TUICEventSystemEventFactoryMaxStrLenFn)(void *inFactory);
+typedef SUICEventSystemRegisteredStr (*TUICEventSystemEventFactoryRegisterStrFn)(
+ void *inFactory, TUICEventSystemStr inStr);
+typedef TUICEventSystemStr (*TUICEventSystemEventFactoryAllocateStrFn)(void *inFactory,
+ TUICEventSystemStr inStr);
+typedef TUICEventSystemStr (*TUICEventSystemEventFactoryAllocateStrLenFn)(void *inFactory, int len);
+
+// Factory from the provider's perspective.
+typedef struct _SUICEventSystemEventFactory
+{
+ void *m_Factory;
+ TUICEventSystemEventFactoryCreateEventFn createEvent;
+ TUICEventSystemEventFactoryMaxNumEventDataFn getMaxNumEventData;
+ TUICEventSystemEventFactoryMaxStrLenFn getMaxStrLength;
+ TUICEventSystemEventFactoryRegisterStrFn registerStr;
+ TUICEventSystemEventFactoryAllocateStrFn allocateStr;
+ TUICEventSystemEventFactoryAllocateStrLenFn allocateStrLen;
+
+} SUICEventSystemEventFactory;
+
+typedef size_t (*TUICEventSystemProviderGetNextEventsFn)(void *inProvider,
+ SUICEventSystemEventFactory inFactory,
+ SUICEventSystemEvent **outBuffer,
+ size_t outBufLen);
+typedef void (*TUICEventSystemProviderReleaseFn)(void *inProvider);
+
+typedef struct _SUICEventSystemEventProvider
+{
+ void *m_Provider;
+ TUICEventSystemProviderGetNextEventsFn getNextEvents;
+ TUICEventSystemProviderReleaseFn release;
+} SUICEventSystemEventProvider;
+
+typedef void (*TUICEventSystemPollerAddProviderFn)(void *inPoller,
+ SUICEventSystemEventProvider inProvider);
+typedef void (*TUICEventSystemPollerRemoveProviderFn)(void *inPoller,
+ SUICEventSystemEventProvider inProvider);
+typedef int (*TUICEventSystemPollerignoreProviderFn)(void *inPoller,
+ SUICEventSystemEventProvider inProvider);
+typedef int (*TUICEventSystemPolleractivateProviderFn)(void *inPoller,
+ SUICEventSystemEventProvider inProvider);
+
+typedef struct _SUICEventSystemEventPoller
+{
+ void *m_Poller;
+ // Providers, once added, will be released by the event poller unless removed
+ TUICEventSystemPollerAddProviderFn addProvider;
+ // Callers are responsible for releasing removed providers.
+ TUICEventSystemPollerRemoveProviderFn removeProvider;
+ TUICEventSystemPollerignoreProviderFn ignoreProvider;
+ TUICEventSystemPolleractivateProviderFn activateProvider;
+
+} SUICEventSystemEventPoller;
+
+extern const char *PROVIDER_TABLE_ENTRY;
+extern const char *POLLER_TABLE_ENTRY;
+
+#ifdef _cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystem.h b/src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystem.h
new file mode 100644
index 00000000..5161e1be
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystem.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EVENT_SYSTEM_H
+#define EVENT_SYSTEM_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "EventSystem.h"
+
+namespace uic {
+namespace evt {
+
+ class CEventProviderRefCounted;
+
+ class IEventSystem : public qt3ds::foundation::NVRefCounted
+ {
+ protected:
+ virtual ~IEventSystem() {}
+ public:
+ // Providers once added are released if the poller goes out of scope.
+ // Adding the same provider twice has no effect.
+ virtual void AddProvider(IEventProvider &inProvider) = 0;
+
+ // removeProvider does not release the provider; callers are expected to release the
+ // provider themselves after calling remove provider. Calling remove provider
+ // with a provider that isn't in the system has no effect.
+ virtual void RemoveProvider(IEventProvider &inProvider) = 0;
+
+ // Ignore events from this provider. Returns true if provider is added.
+ virtual bool IgnoreProvider(IEventProvider &inProvider) = 0;
+
+ // Listen on this provider. Returns true if provider is added.
+ virtual bool ActivateProvider(IEventProvider &inProvider) = 0;
+
+ // Get a set of events from the poller. The poller will simply run through and ask each
+ // provider
+ // for events and then begin returning the set of events.
+ // Note: this interface needs to set the event fetched flag.
+ virtual size_t GetNextEvents(SUICEventSystemEvent **outBuffer, size_t bufLen) = 0;
+
+ // Get the event factory used for this poller.
+ virtual IEventFactory &GetEventFactory() = 0;
+
+ virtual SUICEventSystemEventPoller *GetCInterface() = 0;
+
+ // Get and clear the flag indicates whether GetNextEvents has been called after last call of
+ // this interface
+ // Note: the event fetched flag is set by GetNextEvents
+ virtual bool GetAndClearEventFetchedFlag() = 0;
+
+ // Clear events in event system and events in all providers
+ virtual void PurgeEvents() = 0;
+
+ static IEventSystem &Create(qt3ds::NVFoundationBase &inFoundation);
+ };
+}
+}
+
+#endif // EVENT_SYSTEM_H
diff --git a/src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystemLuaBinding.h b/src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystemLuaBinding.h
new file mode 100644
index 00000000..b15ca070
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/InternalInclude/EventPollingSystemLuaBinding.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EVENT_POLLING_SYSTEM_LUA_BINDING_H
+#define EVENT_POLLING_SYSTEM_LUA_BINDING_H
+struct lua_State;
+
+namespace uic {
+namespace evt {
+
+ class IEventSystem;
+
+ struct SLuaEventPollerBinding
+ {
+ // Returns with an object with on the top of the stack.
+ // The object has two methods, getCInterface and getNextEvents
+ // getCInterface returns userdata that is a pointer to a SUICEventSystemEventPoller (the 'c'
+ // interface).
+ // getNextEvents returns an array of the next events.
+ static void WrapEventPoller(lua_State *inState, IEventSystem &inPoller);
+ };
+}
+}
+
+#endif // EVENT_POLLING_SYSTEM_LUA_BINDING_H
diff --git a/src/Runtime/Source/UICEvent/Source/EventFactory.cpp b/src/Runtime/Source/UICEvent/Source/EventFactory.cpp
new file mode 100644
index 00000000..9ee9071a
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Source/EventFactory.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EventFactory.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/StringTable.h"
+#include "foundation/Utils.h"
+
+using namespace uic::evt;
+
+typedef char TEventChar;
+using qt3ds::QT3DSU32;
+
+class CInitableRegisteredStr : public SUICEventSystemRegisteredStr
+{
+public:
+ CInitableRegisteredStr(const TEventStr inString) { m_Data = inString; }
+};
+
+CFactory &CFactory::Create(qt3ds::NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), CFactory)(inFoundation);
+}
+
+CFactory::CFactory(qt3ds::NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , m_Allocator(inFoundation.getAllocator(), "event factory allocator")
+ , m_StringTable(qt3ds::foundation::IStringTable::CreateStringTable(inFoundation.getAllocator()))
+{
+}
+
+CFactory::~CFactory()
+{
+}
+
+SUICEventSystemEvent &CFactory::CreateEvent(int inNumData)
+{
+ // Ensure num data is in range
+ inNumData = qt3ds::NVMax(0, inNumData);
+ // Ensure we can actually allocate something that big
+ QT3DSU32 dataSize = static_cast<QT3DSU32>(
+ qt3ds::NVMin((size_t)inNumData * sizeof(SUICEventSystemEventData),
+ TEventAllocator::getSlabSize() - sizeof(SUICEventSystemEvent)));
+ // get the actual num data after safety checks.
+ inNumData = (int)(dataSize / sizeof(SUICEventSystemEventData));
+
+ QT3DSU32 allocSize = sizeof(SUICEventSystemEvent) + inNumData * sizeof(SUICEventSystemEventData);
+
+ SUICEventSystemEvent *theEvent = (SUICEventSystemEvent *)m_Allocator.allocate(
+ allocSize, "Event allocation", __FILE__, __LINE__);
+ theEvent->m_NumData = inNumData;
+ theEvent->m_Data = reinterpret_cast<SUICEventSystemEventData *>(((qt3ds::QT3DSU8 *)theEvent)
+ + sizeof(SUICEventSystemEvent));
+
+ // Initialize the event data to zero so that a free event won't cause a calamity.
+ qt3ds::intrinsics::memZero(theEvent->m_Data, dataSize);
+
+ return *theEvent;
+}
+
+size_t CFactory::GetMaxNumEventData()
+{
+ return m_Allocator.getSlabSize() - sizeof(SUICEventSystemEvent);
+}
+
+size_t CFactory::GetMaxStrLength()
+{
+ return m_Allocator.getSlabSize();
+}
+
+void CFactory::ReleaseOutstandingEvents()
+{
+ m_Allocator.reset();
+}
+
+SUICEventSystemRegisteredStr CFactory::RegisterStr(TEventStr inSrc)
+{
+ return CInitableRegisteredStr(m_StringTable->RegisterStr(inSrc));
+}
+
+TEventStr CFactory::AllocateStr(TEventStr inSrc)
+{
+ size_t theSizeInByte = sizeof(TEventChar) * (strlen(qt3ds::foundation::nonNull(inSrc)) + 1);
+ theSizeInByte = qt3ds::NVMin(theSizeInByte, TEventAllocator::getSlabSize());
+
+ TEventChar *theNewString = (TEventChar *)m_Allocator.allocate(
+ theSizeInByte, "uic::evt::CFactory::UnManagedString", __FILE__, __LINE__);
+
+ if (theNewString)
+ memcpy(theNewString, inSrc, theSizeInByte);
+
+ theNewString[theSizeInByte - 1] = 0;
+
+ return theNewString;
+}
+
+TEventStr CFactory::AllocateStr(int inLength)
+{
+ ++inLength;
+ int safeLen = (int)qt3ds::NVMin((size_t)inLength, TEventAllocator::getSlabSize());
+ // Either give the users what they ask for or return nothing.
+ if (safeLen != inLength)
+ return NULL;
+
+ void *retval = m_Allocator.allocate(inLength * sizeof(TEventChar),
+ "uic::evt::CFactory::UnManagedString", __FILE__, __LINE__);
+ qt3ds::intrinsics::memZero(retval, inLength);
+ return (TEventStr)retval;
+}
+
+void CFactory::Release()
+{
+ this->~CFactory();
+ QT3DS_FREE(m_Foundation.getAllocator(), this);
+}
diff --git a/src/Runtime/Source/UICEvent/Source/EventFactory.h b/src/Runtime/Source/UICEvent/Source/EventFactory.h
new file mode 100644
index 00000000..38a98228
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Source/EventFactory.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EVENT_FACTORY_H
+#define EVENT_FACTORY_H
+
+#include "EventSystem.h"
+#include "EventPollingSystem.h"
+
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/FastAllocator.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+namespace foundation {
+ class IStringTable;
+}
+}
+
+namespace uic {
+namespace evt {
+
+ class CEventProviderRefCounted;
+
+ class CFactory : public IEventFactory
+ {
+ private:
+ explicit CFactory(qt3ds::NVFoundationBase &inFoundation);
+ virtual ~CFactory();
+
+ CFactory &operator=(const CFactory &) { return *this; }
+ public:
+ // Interfaces from IEventFactory
+ SUICEventSystemEvent &CreateEvent(int inNumData) override;
+ size_t GetMaxNumEventData() override;
+ size_t GetMaxStrLength() override;
+
+ SUICEventSystemRegisteredStr RegisterStr(TEventStr inSrc) override;
+ // Null terminates if strlen(inSrc) > getMaxStrLength
+ TEventStr AllocateStr(TEventStr inSrc) override;
+
+ // Returns null if inLength > getMaxStrLength
+ TEventStr AllocateStr(int inLength) override;
+
+ void ReleaseOutstandingEvents();
+ void Release();
+
+ static CFactory &Create(qt3ds::NVFoundationBase &inFoundation);
+
+ private:
+ typedef qt3ds::foundation::SFastAllocator<> TEventAllocator;
+
+ qt3ds::NVFoundationBase &m_Foundation;
+ TEventAllocator m_Allocator;
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::foundation::IStringTable> m_StringTable;
+ };
+}
+}
+
+#endif // EVENT_FACTORY_H
diff --git a/src/Runtime/Source/UICEvent/Source/EventPoller.cpp b/src/Runtime/Source/UICEvent/Source/EventPoller.cpp
new file mode 100644
index 00000000..8be89e43
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Source/EventPoller.cpp
@@ -0,0 +1,375 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <EASTL/algorithm.h>
+
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAllocator.h"
+
+#include "EventPoller.h"
+#include "EventFactory.h"
+
+#define MAX_EVENTS 256
+
+using namespace uic::evt;
+using qt3ds::QT3DSU32;
+
+IEventSystem &IEventSystem::Create(qt3ds::NVFoundationBase &inFoundation)
+{
+ return CPoller::Create(inFoundation);
+}
+
+CPoller &CPoller::Create(qt3ds::NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), CPoller)(inFoundation);
+}
+
+CPoller::~CPoller()
+{
+ for (QT3DSU32 idx = 0, end = m_Providers.size(); idx < end; ++idx)
+ m_Providers[idx].first->Release();
+ m_Providers.clear();
+ ReleaseEvents();
+ m_EventFactory.Release();
+}
+
+void CPoller::ReleaseEvents()
+{
+ m_EventFactory.ReleaseOutstandingEvents();
+
+ m_EventList.clear();
+ m_EventIndex = 0;
+}
+
+static void AddProviderFn(void *inPoller, SUICEventSystemEventProvider inProvider)
+{
+ CPoller *thePoller = reinterpret_cast<CPoller *>(inPoller);
+ thePoller->AddProvider(*thePoller->GetOrCreateEventProviderWrapper(inProvider));
+}
+
+static void RemoveProviderFn(void *inPoller, SUICEventSystemEventProvider inProvider)
+{
+ CPoller *thePoller = reinterpret_cast<CPoller *>(inPoller);
+ CPoller::TProvider theProvider = thePoller->GetEventProviderWrapper(inProvider);
+ if (theProvider)
+ thePoller->RemoveProvider(*theProvider);
+ thePoller->ReleaseEventProviderWrapper(inProvider);
+}
+
+static int IgnoreProviderFn(void *inPoller, SUICEventSystemEventProvider inProvider)
+{
+ CPoller *thePoller = reinterpret_cast<CPoller *>(inPoller);
+ CPoller::TProvider theProvider = thePoller->GetEventProviderWrapper(inProvider);
+ if (theProvider)
+ return thePoller->IgnoreProvider(*theProvider);
+ return 0;
+}
+
+static int ActivateProviderFn(void *inPoller, SUICEventSystemEventProvider inProvider)
+{
+ CPoller *thePoller = reinterpret_cast<CPoller *>(inPoller);
+ CPoller::TProvider theProvider = thePoller->GetEventProviderWrapper(inProvider);
+ if (theProvider)
+ return thePoller->ActivateProvider(*theProvider);
+ return 0;
+}
+
+CPoller::CPoller(qt3ds::NVFoundationBase &inFoundation)
+ : mRefCount(0)
+ , m_Foundation(inFoundation)
+ , m_EventFactory(CFactory::Create(inFoundation))
+ , m_Providers(inFoundation.getAllocator(), "CPoller::m_Providers")
+ , m_EventList(inFoundation.getAllocator(), "CPoller::m_EventList")
+ , m_EventIndex(0)
+ , m_EventFetched(false)
+{
+ m_CInterface.m_Poller = this;
+ m_CInterface.addProvider = AddProviderFn;
+ m_CInterface.removeProvider = RemoveProviderFn;
+ m_CInterface.ignoreProvider = IgnoreProviderFn;
+ m_CInterface.activateProvider = ActivateProviderFn;
+}
+
+struct SProviderSearch
+{
+ IEventProvider *m_Provider;
+ SProviderSearch(IEventProvider &inProvider)
+ : m_Provider(&inProvider)
+ {
+ }
+ bool operator()(const eastl::pair<CPoller::TProvider, bool> &item)
+ {
+ return item.first == m_Provider;
+ }
+};
+
+void CPoller::AddProvider(IEventProvider &inProvider)
+{
+ TProviderList::iterator iter =
+ eastl::find_if(m_Providers.begin(), m_Providers.end(), SProviderSearch(inProvider));
+ if (iter == m_Providers.end())
+ m_Providers.push_back(eastl::make_pair(&inProvider, true));
+}
+
+void CPoller::RemoveProvider(IEventProvider &inProvider)
+{
+ TProviderList::iterator thePos =
+ eastl::find_if(m_Providers.begin(), m_Providers.end(), SProviderSearch(inProvider));
+ if (thePos != m_Providers.end())
+ m_Providers.erase(thePos);
+}
+
+bool CPoller::IgnoreProvider(IEventProvider &inProvider)
+{
+ TProviderList::iterator thePos =
+ eastl::find_if(m_Providers.begin(), m_Providers.end(), SProviderSearch(inProvider));
+ if (thePos != m_Providers.end()) {
+ thePos->second = false;
+ return true;
+ }
+ return false;
+}
+
+bool CPoller::ActivateProvider(IEventProvider &inProvider)
+{
+ TProviderList::iterator thePos =
+ eastl::find_if(m_Providers.begin(), m_Providers.end(), SProviderSearch(inProvider));
+ if (thePos != m_Providers.end()) {
+ thePos->second = true;
+ return true;
+ }
+ return false;
+}
+
+SUICEventSystemEvent *CPoller::GetNextEvent(bool inAllowResetBuffer)
+{
+ if (m_EventIndex < m_EventList.size()) {
+ SUICEventSystemEvent *retval = m_EventList[m_EventIndex];
+ ++m_EventIndex;
+ return retval;
+ }
+ if (inAllowResetBuffer) {
+ ReleaseEvents();
+ }
+ size_t theNewEventCount = 0;
+ for (QT3DSU32 idx = 0, end = m_Providers.size(); idx < end; ++idx) {
+ if (m_Providers[idx].second) {
+ SUICEventSystemEvent *evtBuffer[MAX_EVENTS];
+ for (QT3DSU32 numEvents = (QT3DSU32)(m_Providers[idx].first)
+ ->GetNextEvents(m_EventFactory, evtBuffer, MAX_EVENTS);
+ numEvents;
+ numEvents = (QT3DSU32)(m_Providers[idx].first)
+ ->GetNextEvents(m_EventFactory, evtBuffer, MAX_EVENTS)) {
+ m_EventList.insert(m_EventList.end(), evtBuffer, evtBuffer + numEvents);
+ ++theNewEventCount;
+ }
+ }
+ }
+ if (theNewEventCount)
+ return GetNextEvent(inAllowResetBuffer);
+
+ return NULL;
+}
+
+size_t CPoller::GetNextEvents(SUICEventSystemEvent **outBuffer, size_t bufLen)
+{
+ m_EventFetched = true;
+ size_t bufIdx = 0;
+ bool theAllowResetBuffer = true;
+ for (; bufIdx < bufLen; ++bufIdx) {
+ SUICEventSystemEvent *evt = GetNextEvent(theAllowResetBuffer);
+ if (!evt)
+ break;
+ theAllowResetBuffer = false;
+ outBuffer[bufIdx] = evt;
+ }
+ return bufIdx;
+}
+
+IEventFactory &CPoller::GetEventFactory()
+{
+ return m_EventFactory;
+}
+
+SUICEventSystemEventPoller *CPoller::GetCInterface()
+{
+ return &m_CInterface;
+}
+
+bool CPoller::GetAndClearEventFetchedFlag()
+{
+ bool theOld = m_EventFetched;
+ m_EventFetched = false;
+ return theOld;
+}
+
+void CPoller::PurgeEvents()
+{
+ // Get events from providers and drop,
+ // so the providers need not to provide an additional interface for clear events
+ static const size_t EVENTS_NUM_ONCE_CLEAR = 512;
+ SUICEventSystemEvent *theEvents[EVENTS_NUM_ONCE_CLEAR];
+ GetNextEvents(theEvents, EVENTS_NUM_ONCE_CLEAR);
+ ReleaseEvents();
+}
+
+void CPoller::addRef()
+{
+ qt3ds::foundation::atomicIncrement(&mRefCount);
+}
+
+void CPoller::release()
+{
+ qt3ds::QT3DSI32 value = qt3ds::foundation::atomicDecrement(&mRefCount);
+ if (value <= 0) {
+ qt3ds::NVAllocatorCallback &alloc(m_Foundation.getAllocator());
+ this->~CPoller();
+ QT3DS_FREE(alloc, this);
+ }
+}
+
+struct SProviderFinder
+{
+ void *m_Key;
+ SProviderFinder(void *k)
+ : m_Key(k)
+ {
+ }
+ bool operator()(const CPoller::TCEventProviderPair &inPair)
+ {
+ if (inPair.first == m_Key)
+ return true;
+ return false;
+ }
+};
+
+static SUICEventSystemEvent *CreateEventFn(void *inFactory, int numData)
+{
+ IEventFactory *theFactory = reinterpret_cast<IEventFactory *>(inFactory);
+ return &theFactory->CreateEvent(numData);
+}
+
+static size_t MaxNumEventDataFn(void *inFactory)
+{
+ IEventFactory *theFactory = reinterpret_cast<IEventFactory *>(inFactory);
+ return theFactory->GetMaxNumEventData();
+}
+
+static size_t MaxStrLenFn(void *inFactory)
+{
+ IEventFactory *theFactory = reinterpret_cast<IEventFactory *>(inFactory);
+ return theFactory->GetMaxStrLength();
+}
+
+static SUICEventSystemRegisteredStr RegisterStrFn(void *inFactory, TUICEventSystemStr inStr)
+{
+ IEventFactory *theFactory = reinterpret_cast<IEventFactory *>(inFactory);
+ return theFactory->RegisterStr(inStr);
+}
+
+static TUICEventSystemStr AllocateStrFn(void *inFactory, TUICEventSystemStr inStr)
+{
+ IEventFactory *theFactory = reinterpret_cast<IEventFactory *>(inFactory);
+ return theFactory->AllocateStr(inStr);
+}
+
+static TUICEventSystemStr AllocateStrLenFn(void *inFactory, int len)
+{
+ IEventFactory *theFactory = reinterpret_cast<IEventFactory *>(inFactory);
+ return theFactory->AllocateStr(len);
+}
+
+struct SWrappedProvider : public IEventProvider
+{
+ SUICEventSystemEventProvider m_Provider;
+ SWrappedProvider(SUICEventSystemEventProvider prov)
+ : m_Provider(prov)
+ {
+ }
+
+ size_t GetNextEvents(IEventFactory &inFactory, SUICEventSystemEvent **outBuffer,
+ size_t bufLen) override
+ {
+ if (m_Provider.m_Provider) {
+ SUICEventSystemEventFactory theFactory;
+ theFactory.m_Factory = &inFactory;
+ theFactory.createEvent = CreateEventFn;
+ theFactory.getMaxNumEventData = MaxNumEventDataFn;
+ theFactory.getMaxStrLength = MaxStrLenFn;
+ theFactory.registerStr = RegisterStrFn;
+ theFactory.allocateStr = AllocateStrFn;
+ theFactory.allocateStrLen = AllocateStrLenFn;
+ return m_Provider.getNextEvents(m_Provider.m_Provider, theFactory, outBuffer, bufLen);
+ }
+ return 0;
+ }
+
+ void Release() override
+ {
+ if (m_Provider.m_Provider)
+ m_Provider.release(m_Provider.m_Provider);
+ delete this;
+ }
+};
+
+CPoller::TProvider CPoller::GetEventProviderWrapper(SUICEventSystemEventProvider inProvider)
+{
+ TCEventProviderList::iterator iter = eastl::find_if(
+ m_CEventProviders.begin(), m_CEventProviders.end(), SProviderFinder(inProvider.m_Provider));
+ if (iter != m_CEventProviders.end())
+ return iter->second;
+ return TProvider();
+}
+
+CPoller::TProvider CPoller::GetOrCreateEventProviderWrapper(SUICEventSystemEventProvider inProvider)
+{
+ TCEventProviderList::iterator iter = eastl::find_if(
+ m_CEventProviders.begin(), m_CEventProviders.end(), SProviderFinder(inProvider.m_Provider));
+ if (iter == m_CEventProviders.end()) {
+ TProvider retval = new SWrappedProvider(inProvider);
+ m_CEventProviders.push_back(eastl::make_pair(inProvider.m_Provider, retval));
+ return retval;
+ }
+ return iter->second;
+}
+
+void CPoller::ReleaseEventProviderWrapper(SUICEventSystemEventProvider inProvider)
+{
+ TCEventProviderList::iterator iter = eastl::find_if(
+ m_CEventProviders.begin(), m_CEventProviders.end(), SProviderFinder(inProvider.m_Provider));
+ if (iter != m_CEventProviders.end()) {
+ SWrappedProvider &wrappedProvider = static_cast<SWrappedProvider &>(*iter->second);
+ wrappedProvider.m_Provider.m_Provider = NULL;
+ m_CEventProviders.erase(
+ iter); // deletes the wrapper but does not release the wrapped provider.
+ }
+}
diff --git a/src/Runtime/Source/UICEvent/Source/EventPoller.h b/src/Runtime/Source/UICEvent/Source/EventPoller.h
new file mode 100644
index 00000000..5ea5849b
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Source/EventPoller.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EVENT_POLLER_H
+#define EVENT_POLLER_H
+
+#include <EASTL/vector.h>
+
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSContainers.h"
+
+#include "EventSystem.h"
+#include "EventPollingSystem.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace uic {
+namespace evt {
+
+ class CFactory;
+
+ class CPoller : public IEventSystem
+ {
+ public:
+ typedef IEventProvider *TProvider;
+ typedef qt3ds::foundation::nvvector<eastl::pair<TProvider, bool>> TProviderList;
+ typedef qt3ds::foundation::nvvector<SUICEventSystemEvent *> TEventList;
+ typedef eastl::pair<void *, TProvider> TCEventProviderPair;
+ typedef eastl::vector<TCEventProviderPair> TCEventProviderList;
+
+ private:
+ explicit CPoller(qt3ds::NVFoundationBase &inFoundation);
+ virtual ~CPoller();
+
+ public:
+ // Providers once added are released if the poller goes out of scope.
+ void AddProvider(IEventProvider &inProvider) override;
+ void RemoveProvider(IEventProvider &inProvider) override;
+ bool IgnoreProvider(IEventProvider &inProvider) override;
+ bool ActivateProvider(IEventProvider &inProvider) override;
+ size_t GetNextEvents(SUICEventSystemEvent **outBuffer, size_t bufLen) override;
+ IEventFactory &GetEventFactory() override;
+ SUICEventSystemEventPoller *GetCInterface() override;
+ bool GetAndClearEventFetchedFlag() override;
+ void PurgeEvents() override;
+
+ void ReleaseEvents();
+
+ void addRef() override;
+ void release() override;
+
+ TProvider GetEventProviderWrapper(SUICEventSystemEventProvider inProvider);
+ TProvider GetOrCreateEventProviderWrapper(SUICEventSystemEventProvider inProvider);
+ void ReleaseEventProviderWrapper(SUICEventSystemEventProvider inProvider);
+
+ static CPoller &Create(qt3ds::NVFoundationBase &inFoundation);
+
+ private:
+ SUICEventSystemEvent *GetNextEvent(bool inAllowResetBuffer /* = true*/);
+
+ qt3ds::QT3DSI32 mRefCount;
+ qt3ds::NVFoundationBase &m_Foundation;
+ CFactory &m_EventFactory;
+ TProviderList m_Providers;
+ TEventList m_EventList;
+ qt3ds::QT3DSU32 m_EventIndex;
+ SUICEventSystemEventPoller m_CInterface;
+ TCEventProviderList m_CEventProviders;
+ bool m_EventFetched;
+ };
+}
+}
+
+#endif // EVENT_POLLER_H
diff --git a/src/Runtime/Source/UICEvent/Source/EventPollingSystemLuaBinding.cpp b/src/Runtime/Source/UICEvent/Source/EventPollingSystemLuaBinding.cpp
new file mode 100644
index 00000000..65c73372
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Source/EventPollingSystemLuaBinding.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <EASTL/hash_map.h>
+#include <EASTL/vector.h>
+
+#include "UICLuaIncludes.h"
+#include "foundation/Qt3DSMath.h"
+
+#include "EventSystem.h"
+#include "EventPollingSystem.h"
+#include "EventPollingSystemLuaBinding.h"
+
+using namespace uic::evt;
+
+namespace {
+// No need to use static in an anonymous namespace
+
+int GetCInterface(lua_State *inState);
+// Get a set of events from the poller. The poller will simply run through and ask each provider
+// for events and then begin returning the set of events.
+// Parameters:
+// Instance of event system interface
+// Max number of events expected
+// Returns:
+// Array of event objects.
+// Remarks: the number of events returned won't exceed the input count; if there are less events
+// than
+// the input count, less events will be returned; if no event, an empty array will be returned.
+int GetNextEvents(lua_State *inState);
+
+void TranslateEventValue(lua_State *inState, const SUICEventSystemEventValue &theValue)
+{
+ switch (theValue.m_Type) {
+ case EUICEventSystemEventTypesNumber:
+ lua_pushnumber(inState, theValue.m_Number);
+ break;
+ case EUICEventSystemEventTypesString:
+ lua_pushstring(inState, theValue.m_String ? theValue.m_String : "");
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+}
+
+void TranslateEvent(lua_State *inState, SUICEventSystemEvent &theEvent)
+{
+ int top = lua_gettop(inState);
+ // Put the result table of event on top of the lua stack
+ // If the data of the same name occur more than once, they will be packed into an array(table)
+ // in order,
+ // otherwise just a string or number object.
+ lua_newtable(inState); // The result table of event
+ for (int i = 0; i < theEvent.m_NumData; ++i) {
+ const SUICEventSystemEventData &theValue(theEvent.m_Data[i]);
+ const char *theFetchableString(theValue.m_Name.m_Data);
+ lua_getfield(inState, -1, theFetchableString);
+ // Is the string already in the table?
+ if (lua_isnil(inState, -1)) {
+ // no, it is not
+ lua_pop(inState, 1);
+ TranslateEventValue(inState, theValue.m_Value);
+ lua_setfield(inState, -2, theFetchableString);
+ } else {
+ if (!lua_istable(inState, -1)) {
+ // create new table
+ lua_newtable(inState);
+ // move it below the existing value on the stack
+ lua_insert(inState, -2);
+ // set the existing value into the new table at location 1
+ lua_rawseti(inState, -2, 1);
+ // duplicate the table reference on the stack
+ lua_pushvalue(inState, -1);
+ // Set the table as the new value under the string name in the original table.
+ lua_setfield(inState, -3, theFetchableString);
+ // this leaves two tables on the stack, the return value
+ // and the new table.
+ }
+ // table of new values is now on the stack.
+ // Get the length of the value array.
+ int len = static_cast<int>(lua_objlen(inState, -1));
+ // Get the new value
+ TranslateEventValue(inState, theValue.m_Value);
+ lua_rawseti(inState, -2, len + 1);
+ // Leave only the return value on the stack.
+ lua_pop(inState, 1);
+ QT3DS_ASSERT(lua_gettop(inState) == top + 1);
+ QT3DS_ASSERT(lua_istable(inState, -1));
+ }
+ }
+ (void)top;
+}
+
+int GetNextEvents(lua_State *inState)
+{
+ // Parameter:
+ // Poller(C)
+ // number of events expected
+ // Return: an array of events
+ static const size_t MAX_EVENTS_ONCE = 512;
+ int top = lua_gettop(inState);
+
+ luaL_checktype(inState, 1, LUA_TTABLE);
+
+ size_t theMaxCount = MAX_EVENTS_ONCE;
+ if (top == 2) {
+ luaL_checktype(inState, 2, LUA_TNUMBER);
+ int theValue = lua_tointeger(inState, 2);
+ theValue = qt3ds::NVMax(0, theValue);
+ theMaxCount = qt3ds::NVMin(theMaxCount, (size_t)theValue);
+ }
+
+ lua_getfield(inState, 1, POLLER_TABLE_ENTRY);
+ luaL_checktype(inState, -1, LUA_TLIGHTUSERDATA);
+
+ SUICEventSystemEventPoller *thePollerC =
+ (SUICEventSystemEventPoller *)lua_touserdata(inState, -1);
+ IEventSystem *thePoller = 0;
+ lua_newtable(inState);
+ if (!thePollerC || (thePoller = reinterpret_cast<IEventSystem *>(thePollerC->m_Poller)) == 0
+ || theMaxCount <= 0)
+ return 1;
+
+ SUICEventSystemEvent *theEvents[MAX_EVENTS_ONCE];
+ size_t theCount = thePoller->GetNextEvents(theEvents, theMaxCount);
+ for (qt3ds::QT3DSU32 theIndex = 0; theIndex < theCount; ++theIndex) {
+ TranslateEvent(inState, *theEvents[theIndex]);
+ lua_rawseti(inState, -2, theIndex + 1);
+ }
+ return 1;
+}
+
+// int
+// GetCInterface( lua_State* inState )
+//{
+// // Parameter: Poller(C++)
+// // Return: c function table in light user data
+// static const size_t MAX_EVENTS_ONCE = 512;
+// luaL_checktype( inState, 1, LUA_TTABLE );
+// lua_getfield( inState, 1, pollerTableEntry );
+// luaL_checktype( inState, -1, LUA_TLIGHTUSERDATA );
+// IEventSystem *thePoller = (IEventSystem*)lua_touserdata( inState, -1 );
+// if ( thePoller )
+// {
+// lua_pushlightuserdata( inState, thePoller->GetCInterface() );
+// return 1;
+// }
+// return 0;
+//}
+}
+
+void uic::evt::SLuaEventPollerBinding::WrapEventPoller(lua_State *inState, IEventSystem &inPoller)
+{
+ lua_newtable(inState);
+ lua_pushlightuserdata(inState, inPoller.GetCInterface()); // Store the C poller, for Lua will
+ // hand over it to provider factories
+ // directly.
+ lua_setfield(inState, -2, POLLER_TABLE_ENTRY);
+ lua_pushcfunction(inState, GetNextEvents);
+ lua_setfield(inState, -2, "getNextEvents");
+ // lua_pushcfunction( inState, GetCInterface );
+ // lua_setfield( inState, -2, "getCInterface" );
+}
diff --git a/src/Runtime/Source/UICEvent/Source/EventSystemC.cpp b/src/Runtime/Source/UICEvent/Source/EventSystemC.cpp
new file mode 100644
index 00000000..8bfdb81c
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Source/EventSystemC.cpp
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "EventSystemC.h"
+
+const char *PROVIDER_TABLE_ENTRY = "__provider_impl";
+const char *POLLER_TABLE_ENTRY = "__poller_impl"; \ No newline at end of file
diff --git a/src/Runtime/Source/UICEvent/Test/CanProviderDemo.cpp b/src/Runtime/Source/UICEvent/Test/CanProviderDemo.cpp
new file mode 100644
index 00000000..8929bafc
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Test/CanProviderDemo.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <time.h>
+#include <math.h>
+
+#include "CanProviderDemo.h"
+
+CCanProviderDemo::CCanProviderDemo()
+ : m_Frame(0)
+ , m_LastClock(0)
+{
+}
+
+CCanProviderDemo::~CCanProviderDemo()
+{
+}
+
+unsigned short g_VehicleSpeedData[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12, 14, 16,
+ 18, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136,
+ 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 256, 264,
+ 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 392,
+ 400, 408, 416, 424, 432, 440, 448, 456, 462, 468, 474, 480, 486, 492, 498, 504,
+ 510, 516, 522, 528, 534, 540, 546, 552, 558, 564, 570, 576, 582, 588, 594, 600,
+ 606, 612, 618, 624, 630, 636, 642, 648, 654, 660, 666, 672, 678, 684, 690, 696,
+ 702, 708, 714, 720, 726, 732, 738, 744, 750, 756, 762, 768, 774, 780, 786, 792,
+ 798, 804, 810, 816, 820, 824, 828, 832, 836, 840, 844, 848, 852, 856, 860, 864,
+ 868, 872, 876, 880, 884, 888, 892, 896, 900, 904, 908, 912, 916, 920, 924, 928,
+ 932, 936, 940, 944, 948, 952, 956, 960, 964, 968, 972, 976, 980, 984, 988, 992,
+ 996, 1000, 1004, 1008, 1012, 1016, 1020, 1024, 1028, 1032, 1036, 1040, 1044, 1048, 1052, 1056,
+ 1054, 1052, 1050, 1048, 1046, 1044, 1042, 1040, 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024,
+ 1022, 1020, 1018, 1016, 1014, 1012, 1010, 1008, 1006, 1004, 1002, 1000, 998, 996, 994, 992,
+ 990, 988, 986, 984, 982, 980, 978, 976, 974, 972, 970, 968, 966, 964, 962, 960,
+ 958, 956, 954, 952, 950, 948, 946, 944, 942, 940, 938, 936, 934, 932, 930, 928,
+ 926, 924, 922, 920, 918, 916, 914, 912, 910, 908, 906, 904, 902, 900, 898, 896,
+ 894, 892, 890, 888, 886, 884, 882, 880, 878, 876, 874, 872, 870, 868, 866, 864,
+ 862, 860, 858, 856, 854, 852, 850, 848, 846, 844, 842, 840, 838, 836, 834, 832,
+ 830, 828, 826, 824, 822, 820, 818, 816, 823, 830, 837, 844, 851, 858, 865, 872,
+ 879, 886, 893, 900, 907, 914, 921, 928, 935, 942, 949, 956, 963, 970, 977, 984,
+ 991, 998, 1005, 1012, 1019, 1026, 1033, 1040, 1047, 1054, 1061, 1068, 1075, 1082, 1089, 1096,
+ 1103, 1110, 1117, 1124, 1131, 1138, 1145, 1152, 1159, 1166, 1173, 1180, 1187, 1194, 1201, 1208,
+ 1215, 1222, 1229, 1236, 1246, 1256, 1266, 1276, 1286, 1296, 1306, 1316, 1326, 1336, 1346, 1356,
+ 1366, 1376, 1386, 1396, 1406, 1416, 1426, 1436, 1446, 1456, 1466, 1476, 1486, 1496, 1506, 1516,
+ 1526, 1536, 1546, 1556, 1566, 1576, 1586, 1596, 1606, 1616, 1626, 1636, 1646, 1656, 1666, 1676,
+ 1686, 1696, 1706, 1716, 1726, 1736, 1746, 1756, 1766, 1776, 1786, 1796, 1806, 1816, 1826, 1836,
+ 1836, 1836, 1836, 1834, 1832, 1830, 1828, 1826, 1824, 1822, 1820, 1818, 1816, 1814, 1812, 1810,
+ 1808, 1806, 1804, 1802, 1800, 1798, 1796, 1794, 1792, 1790, 1788, 1786, 1784, 1782, 1780, 1778,
+ 1776, 1774, 1772, 1770, 1768, 1766, 1764, 1762, 1760, 1758, 1756, 1754, 1752, 1750, 1748, 1746,
+ 1744, 1742, 1740, 1738, 1736, 1734, 1732, 1730, 1728, 1726, 1724, 1722, 1723, 1724, 1725, 1726,
+ 1728, 1730, 1732, 1734, 1736, 1738, 1740, 1742, 1744, 1746, 1748, 1750, 1753, 1756, 1759, 1762,
+ 1765, 1768, 1771, 1774, 1777, 1780, 1783, 1786, 1789, 1792, 1795, 1798, 1801, 1804, 1807, 1810,
+ 1813, 1816, 1819, 1822, 1825, 1828, 1831, 1834, 1837, 1840, 1843, 1846, 1849, 1852, 1855, 1858,
+ 1861, 1864, 1867, 1870, 1873, 1876, 1879, 1882, 1885, 1888, 1891, 1894, 1897, 1900, 1903, 1906,
+ 1909, 1912, 1915, 1918, 1921, 1924, 1927, 1930, 1933, 1936, 1939, 1942, 1945, 1948, 1951, 1954,
+ 1957, 1960, 1963, 1966, 1969, 1972, 1975, 1978, 1981, 1984, 1987, 1990, 1993, 1996, 1999, 2002,
+ 2005, 2008, 2011, 2014, 2017, 2020, 2023, 2026, 2029, 2032, 2035, 2038, 2041, 2044, 2047, 2050,
+ 2053, 2056, 2059, 2062, 2064, 2066, 2068, 2070, 2072, 2074, 2076, 2078, 2080, 2082, 2084, 2086,
+ 2088, 2090, 2092, 2094, 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, 2112, 2114, 2116, 2118,
+ 2120, 2122, 2124, 2126, 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, 2144, 2146, 2148, 2150,
+ 2152, 2154, 2156, 2158, 2160, 2162, 2164, 2166, 2168, 2170, 2172, 2174, 2176, 2178, 2180, 2182,
+ 2184, 2186, 2188, 2190, 2192, 2194, 2196, 2198, 2200, 2202, 2204, 2206, 2208, 2210, 2212, 2214,
+ 2216, 2218, 2220, 2222, 2224, 2226, 2228, 2230, 2232, 2234, 2236, 2238, 2240, 2242, 2244, 2246,
+ 2248, 2250, 2252, 2254, 2256, 2258, 2260, 2262, 2264, 2266, 2268, 2270, 2272, 2274, 2276, 2278,
+ 2280, 2282, 2284, 2286, 2288, 2290, 2292, 2294, 2296, 2298, 2300, 2302, 2301, 2300, 2299, 2298,
+ 2297, 2296, 2295, 2294, 2293, 2292, 2291, 2290, 2289, 2288, 2287, 2286, 2285, 2284, 2283, 2282,
+ 2281, 2280, 2279, 2278, 2277, 2276, 2275, 2274, 2273, 2272, 2271, 2270, 2269, 2268, 2267, 2266,
+ 2265, 2264, 2263, 2262, 2261, 2260, 2259, 2258, 2257, 2256, 2255, 2254, 2253, 2252, 2251, 2250,
+ 2249, 2248, 2247, 2246, 2245, 2244, 2243, 2242, 2239, 2236, 2233, 2230, 2227, 2224, 2221, 2218,
+ 2215, 2212, 2209, 2206, 2203, 2200, 2197, 2194, 2191, 2188, 2185, 2182, 2179, 2176, 2173, 2170,
+ 2167, 2164, 2161, 2158, 2155, 2152, 2149, 2146, 2143, 2140, 2137, 2134, 2131, 2128, 2125, 2122,
+ 2119, 2116, 2113, 2110, 2107, 2104, 2101, 2098, 2095, 2092, 2089, 2086, 2083, 2080, 2077, 2074,
+ 2071, 2068, 2065, 2062, 2058, 2054, 2050, 2046, 2042, 2038, 2034, 2030, 2026, 2022, 2018, 2014,
+ 2010, 2006, 2001, 1996, 1991, 1986, 1981, 1976, 1971, 1966, 1961, 1956, 1951, 1946, 1941, 1936,
+ 1931, 1926, 1921, 1916, 1911, 1906, 1901, 1896, 1891, 1886, 1881, 1876, 1871, 1866, 1861, 1856,
+ 1851, 1846, 1841, 1836, 1831, 1826, 1821, 1816, 1811, 1806, 1801, 1796, 1791, 1786, 1781, 1776,
+ 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776,
+ 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776,
+ 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776,
+ 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1776, 1779, 1782, 1785, 1788,
+ 1791, 1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1818, 1821, 1824, 1827, 1830, 1833, 1836,
+ 1839, 1842, 1845, 1848, 1851, 1854, 1857, 1860, 1863, 1866, 1869, 1872, 1875, 1878, 1881, 1884,
+ 1887, 1890, 1893, 1896, 1899, 1902, 1905, 1908, 1911, 1914, 1917, 1920, 1923, 1926, 1929, 1932,
+ 1935, 1938, 1941, 1944, 1947, 1950, 1953, 1956, 1958, 1960, 1962, 1964, 1966, 1968, 1970, 1972,
+ 1974, 1976, 1978, 1980, 1982, 1984, 1986, 1988, 1990, 1992, 1994, 1996, 1998, 2000, 2002, 2004,
+ 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022, 2024, 2026, 2028, 2030, 2032, 2034, 2036,
+ 2038, 2040, 2042, 2044, 2046, 2048, 2050, 2052, 2054, 2056, 2058, 2060, 2062, 2064, 2066, 2068,
+ 2070, 2072, 2074, 2076, 2078, 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, 2096, 2098, 2100,
+ 2102, 2104, 2106, 2108, 2110, 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, 2128, 2130, 2132,
+ 2134, 2136, 2138, 2140, 2142, 2144, 2146, 2148, 2150, 2152, 2154, 2156, 2158, 2160, 2162, 2164,
+ 2166, 2168, 2170, 2172, 2174, 2176, 2178, 2180, 2182, 2184, 2186, 2188, 2190, 2192, 2194, 2196,
+ 2198, 2200, 2202, 2204, 2206, 2208, 2210, 2212, 2214, 2216, 2218, 2220, 2222, 2224, 2226, 2228,
+ 2230, 2232, 2234, 2236, 2238, 2240, 2242, 2244, 2246, 2248, 2250, 2252, 2254, 2256, 2258, 2260,
+ 2262, 2264, 2266, 2268, 2270, 2272, 2274, 2276, 2278, 2280, 2282, 2284, 2286, 2288, 2290, 2292,
+ 2294, 2296, 2298, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312,
+ 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328,
+ 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344,
+ 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360,
+ 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2366, 2364, 2362, 2360, 2358, 2356, 2354, 2352,
+ 2350, 2348, 2346, 2344, 2342, 2340, 2338, 2336, 2334, 2332, 2330, 2328, 2326, 2324, 2322, 2320,
+ 2318, 2316, 2314, 2312, 2310, 2308, 2306, 2304, 2302, 2300, 2298, 2296, 2294, 2292, 2290, 2288,
+ 2286, 2284, 2282, 2280, 2278, 2276, 2274, 2272, 2270, 2268, 2266, 2264, 2262, 2260, 2258, 2256,
+ 2254, 2252, 2250, 2248, 2240, 2230, 2220, 2210, 2200, 2190, 2180, 2170, 2160, 2150, 2140, 2130,
+ 2120, 2110, 2100, 2090, 2080, 2070, 2060, 2050, 2040, 2030, 2020, 2010, 2000, 1990, 1980, 1970,
+ 1960, 1950, 1940, 1930, 1920, 1910, 1900, 1890, 1880, 1870, 1860, 1850, 1840, 1830, 1820, 1810,
+ 1800, 1790, 1780, 1770, 1760, 1750, 1740, 1730, 1720, 1710, 1700, 1690, 1680, 1670, 1660, 1650,
+ 1645, 1640, 1635, 1630, 1625, 1620, 1615, 1610, 1605, 1600, 1595, 1590, 1585, 1580, 1575, 1570,
+ 1565, 1560, 1555, 1550, 1545, 1540, 1535, 1530, 1525, 1520, 1515, 1510, 1505, 1500, 1495, 1490,
+ 1485, 1480, 1475, 1470, 1465, 1460, 1455, 1450, 1445, 1440, 1435, 1430, 1425, 1420, 1415, 1410,
+ 1405, 1400, 1395, 1390, 1385, 1380, 1375, 1370, 1365, 1360, 1355, 1350, 1345, 1340, 1335, 1330,
+ 1325, 1320, 1315, 1310, 1305, 1300, 1295, 1290, 1285, 1280, 1275, 1270, 1265, 1260, 1255, 1250,
+ 1245, 1240, 1235, 1230, 1225, 1220, 1215, 1210, 1205, 1200, 1195, 1190, 1185, 1180, 1175, 1170,
+ 1165, 1160, 1155, 1150, 1145, 1140, 1135, 1130, 1125, 1120, 1115, 1110, 1105, 1100, 1090, 1088,
+ 1086, 1084, 1082, 1080, 1078, 1076, 1074, 1072, 1070, 1065, 1060, 1055, 1050, 1045, 1040, 1035,
+ 1030, 1025, 1020, 1015, 1010, 1005, 1000, 995, 990, 985, 980, 975, 970, 965, 960, 955,
+ 950, 945, 940, 935, 930, 925, 920, 915, 910, 905, 900, 895, 890, 885, 880, 875,
+ 870, 865, 860, 855, 850, 845, 840, 835, 830, 825, 820, 815, 810, 805, 800, 795,
+ 790, 785, 780, 775, 772, 769, 766, 763, 760, 757, 754, 751, 748, 745, 742, 739,
+ 736, 733, 730, 727, 724, 721, 718, 715, 712, 709, 706, 703, 700, 697, 694, 691,
+ 688, 685, 682, 679, 676, 673, 670, 667, 664, 661, 658, 655, 652, 649, 646, 643,
+ 640, 637, 634, 631, 628, 625, 622, 619, 616, 613, 610, 607, 604, 601, 598, 595,
+ 597, 599, 601, 603, 605, 607, 609, 611, 613, 615, 617, 619, 621, 623, 625, 627,
+ 629, 631, 633, 635, 637, 639, 641, 643, 645, 647, 649, 651, 653, 655, 657, 659,
+ 661, 663, 665, 667, 669, 671, 673, 675, 677, 679, 681, 683, 685, 687, 689, 691,
+ 693, 695, 697, 699, 701, 703, 705, 707, 709, 711, 713, 715, 715, 715, 715, 715,
+ 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715,
+ 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715,
+ 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715,
+ 715, 715, 715, 715, 715, 715, 715, 715, 710, 705, 700, 695, 690, 685, 680, 675,
+ 670, 665, 660, 655, 650, 645, 640, 635, 630, 625, 620, 615, 610, 605, 600, 595,
+ 590, 585, 580, 575, 570, 565, 560, 555, 550, 545, 540, 535, 530, 525, 520, 515,
+ 510, 505, 500, 495, 490, 485, 480, 475, 470, 465, 460, 455, 450, 445, 440, 435,
+ 430, 425, 420, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439,
+ 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 469, 471,
+ 473, 475, 477, 479, 481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501, 503,
+ 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535,
+ 536, 532, 528, 524, 520, 516, 512, 508, 504, 500, 496, 492, 488, 484, 480, 476,
+ 472, 468, 464, 460, 456, 452, 448, 444, 440, 436, 432, 428, 424, 420, 416, 412,
+ 408, 404, 400, 396, 392, 388, 384, 380, 376, 372, 368, 364, 360, 356, 352, 348,
+ 344, 340, 336, 332, 328, 324, 320, 316, 312, 308, 304, 300, 295, 290, 285, 280,
+ 275, 270, 265, 260, 255, 250, 245, 240, 235, 230, 225, 220, 215, 210, 205, 200,
+ 195, 190, 185, 180, 175, 170, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120,
+ 115, 110, 105, 100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40,
+ 35, 30, 25, 20, 15, 10, 5, 0
+};
+
+SUICEventSystemEvent *CCanProviderDemo::GetNextEvent(IEventFactory &inFactory)
+{
+ clock_t theCurClock = clock();
+ if (theCurClock > m_LastClock
+ && (theCurClock - m_LastClock) / (CLOCKS_PER_SEC / 1000) < 1000 / 6)
+ return 0;
+ m_LastClock = theCurClock;
+ unsigned char theLength = 0;
+ unsigned char theData[8];
+ theData[0] = 81;
+#define SIN_SAMPLE(s, m) ((sin((float)s) / 2 + 0.5) * m)
+ switch (rand() % 2) {
+ case 0:
+ theData[1] = 1;
+ { // Vehicle speed
+ int theIndex = m_Frame % (sizeof(g_VehicleSpeedData) / sizeof(g_VehicleSpeedData[0]));
+ theData[2] = (unsigned short)(g_VehicleSpeedData[theIndex] * 0.06) >> 8;
+ theData[3] = (unsigned char)(g_VehicleSpeedData[theIndex] * 0.06);
+ }
+ {
+ unsigned short theOdo = m_Frame;
+ theData[4] = theOdo >> 8;
+ theData[5] = (unsigned char)theOdo;
+ }
+ theLength = 6;
+ break;
+ case 1:
+ theData[1] = 2;
+ {
+ unsigned short theTrip = m_Frame;
+ theData[2] = theTrip >> 8;
+ theData[3] = (unsigned char)theTrip;
+ }
+ {
+ unsigned short theCoolant = (unsigned char)SIN_SAMPLE(m_Frame / 170, 300);
+ theData[4] = theCoolant >> 8;
+ theData[5] = (unsigned char)theCoolant;
+ }
+ theLength = 6;
+ break;
+ default:
+ return 0;
+ }
+ ++m_Frame;
+ SUICEventSystemEvent &theEvent = inFactory.CreateEvent(9);
+ SUICEventSystemEventData *theCurrentData = theEvent.m_Data;
+ theCurrentData->m_Name = inFactory.RegisterStr("device_type");
+ theCurrentData->m_Value.m_Type = EUICEventSystemEventTypesString;
+ theCurrentData->m_Value.m_String = inFactory.AllocateStr("CAN");
+ ++theCurrentData;
+ theCurrentData->m_Name = inFactory.RegisterStr("id");
+ theCurrentData->m_Value.m_Type = EUICEventSystemEventTypesNumber;
+ theCurrentData->m_Value.m_Number = 101;
+ ++theCurrentData;
+ theCurrentData->m_Name = inFactory.RegisterStr("length");
+ theCurrentData->m_Value.m_Type = EUICEventSystemEventTypesNumber;
+ theCurrentData->m_Value.m_Number = 6;
+ ++theCurrentData;
+ for (int i = 0; i < theLength; ++i) {
+ theCurrentData->m_Name = inFactory.RegisterStr("data");
+ theCurrentData->m_Value.m_Type = EUICEventSystemEventTypesNumber;
+ theCurrentData->m_Value.m_Number = theData[i];
+ ++theCurrentData;
+ }
+
+ return &theEvent;
+}
+
+size_t CCanProviderDemo::GetNextEvents(IEventFactory &inFactory, SUICEventSystemEvent **outBuffer,
+ size_t bufLen)
+{
+ size_t bufIdx = 0;
+ SUICEventSystemEvent *evt = NULL;
+ for (evt = GetNextEvent(inFactory); evt && bufIdx < bufLen;
+ evt = GetNextEvent(inFactory), ++bufIdx)
+ outBuffer[bufIdx] = evt;
+ return bufIdx;
+}
+
+void CCanProviderDemo::Release()
+{
+ delete this;
+}
diff --git a/src/Runtime/Source/UICEvent/Test/CanProviderDemo.h b/src/Runtime/Source/UICEvent/Test/CanProviderDemo.h
new file mode 100644
index 00000000..a1ddc175
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Test/CanProviderDemo.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAN_PROVIDER_DEMO_H
+#define CAN_PROVIDER_DEMO_H
+
+#include <ctime>
+
+#include <EventSystem.h>
+
+using namespace uic::evt;
+
+class CCanProviderDemo : public IEventProvider
+{
+public:
+ CCanProviderDemo();
+ virtual ~CCanProviderDemo();
+
+ SUICEventSystemEvent *GetNextEvent(IEventFactory &inFactory);
+ virtual size_t GetNextEvents(IEventFactory &inFactory, SUICEventSystemEvent **outBuffer,
+ size_t bufLen);
+ virtual void Release();
+
+private:
+ unsigned int m_Frame;
+ clock_t m_LastClock;
+};
+
+#endif // CAN_PROVIDER_DEMO_H
diff --git a/src/Runtime/Source/UICEvent/Test/EventSystemCppTester.cpp b/src/Runtime/Source/UICEvent/Test/EventSystemCppTester.cpp
new file mode 100644
index 00000000..febbe322
--- /dev/null
+++ b/src/Runtime/Source/UICEvent/Test/EventSystemCppTester.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Windows.h>
+#include <iostream>
+#include <ctime>
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/ErrorStream.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSRefCounted.h"
+
+#include "EventSystem.h"
+#include "EventPollingSystem.h"
+
+#include "CanProviderDemo.h"
+#include "UICLuaIncludes.h"
+#include "EventPollingSystemLuaBinding.h"
+
+void TestCPPBindings()
+{
+ srand(clock());
+
+ qt3ds::foundation::SErrorStream errors;
+ qt3ds::foundation::CAllocator allocator(errors);
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> theFoundation =
+ NVCreateFoundation(QT3DS_FOUNDATION_VERSION, allocator, errors);
+
+ qt3ds::foundation::NVScopedRefCounted<IEventSystem> theEventSystem =
+ IEventSystem::Create(*theFoundation);
+
+ const int theProviderCount = 128;
+ uic::evt::IEventProvider *theProviders[theProviderCount];
+ for (int i = 0; i < theProviderCount; ++i) {
+ theProviders[i] = new CCanProviderDemo();
+ theEventSystem->AddProvider(*theProviders[i]);
+ }
+ unsigned long theCount = 0;
+ while (theCount < 500) {
+ SUICEventSystemEvent *evtBuffer[64];
+ size_t numEvents = theEventSystem->GetNextEvents(evtBuffer, 64);
+ for (size_t evtIdx = 0; evtIdx < numEvents; ++evtIdx) {
+ SUICEventSystemEvent *theEvent = evtBuffer[evtIdx];
+ if (theEvent) {
+ std::cout << "************ event " << ++theCount << " received ************"
+ << std::endl;
+ std::cout << "number of data: " << theEvent->m_NumData << std::endl;
+ SUICEventSystemEventData *theData = theEvent->m_Data;
+ for (int i = 0; i < theEvent->m_NumData; ++i) {
+ std::cout << "data " << i << ":\t";
+ if (EUICEventSystemEventTypesString == theData->m_Value.m_Type) {
+ std::cout << theData->m_Value.m_String;
+ } else {
+ std::cout << theData->m_Value.m_Number;
+ }
+ std::cout << std::endl;
+ ++theData;
+ }
+ } else {
+ // std::cout << "xxxxxxxxxxxx no event xxxxxxxxxxxx" << std::endl;
+ }
+ unsigned int theRand = (unsigned int)rand() % 10000;
+ if (theRand < 20) { // Ignore
+ unsigned int theIndex = rand() % theProviderCount;
+ theEventSystem->IgnoreProvider(*theProviders[theIndex]);
+ std::cout << "Ignore " << theIndex << std::endl;
+ } else if (theRand < 35) { // Activate
+ unsigned int theIndex = rand() % theProviderCount;
+ theEventSystem->ActivateProvider(*theProviders[theIndex]);
+ std::cout << "Activate " << theIndex << std::endl;
+ }
+ }
+ }
+}
+
+const char *luaScript =
+ //"require( \"table\" )\n"
+ "registerCANProvider( eventSystem:getCInterface() )\n"
+ "local theCount = 0\n"
+ "while theCount < 500 do\n"
+ " local theEvents = eventSystem:getNextEvents()\n"
+ " for _, theEvent in ipairs( theEvents ) do\n"
+ " output( \"************ event \" .. theCount .. \" received ************\" )\n"
+ " for theName, theValue in pairs( theEvent ) do\n"
+ " output( theName .. \":\" )\n"
+ " if type( theValue ) == \"table\" then\n"
+ " output( table.concat( theValue, \" \" ) )\n"
+ " else\n"
+ " output( \"\" .. theValue )\n"
+ " end\n"
+ " end\n"
+ " theCount = theCount + 1\n"
+ " end\n"
+ "end";
+
+struct SCToCppFactory : public IEventFactory
+{
+ SUICEventSystemEventFactory m_Factory;
+ SCToCppFactory(SUICEventSystemEventFactory inFactory)
+ : m_Factory(inFactory)
+ {
+ }
+
+ virtual SUICEventSystemEvent &CreateEvent(int inNumData)
+ {
+ return *m_Factory.createEvent(m_Factory.m_Factory, inNumData);
+ }
+ virtual size_t GetMaxNumEventData()
+ {
+ return m_Factory.getMaxNumEventData(m_Factory.m_Factory);
+ }
+ virtual size_t GetMaxStrLength() { return m_Factory.getMaxStrLength(m_Factory.m_Factory); }
+
+ virtual SUICEventSystemRegisteredStr RegisterStr(TEventStr inSrc)
+ {
+ return m_Factory.registerStr(m_Factory.m_Factory, inSrc);
+ }
+ // Null terminates if strlen(inSrc) > getMaxStrLength
+ virtual TEventStr AllocateStr(TEventStr inSrc)
+ {
+ return m_Factory.allocateStr(m_Factory.m_Factory, inSrc);
+ }
+
+ // Returns null if inLength > getMaxStrLength
+ virtual TEventStr AllocateStr(int inLength)
+ {
+ return m_Factory.allocateStrLen(m_Factory.m_Factory, inLength);
+ }
+};
+
+static size_t GetNextEventsFn(void *inProvider, SUICEventSystemEventFactory inFactory,
+ SUICEventSystemEvent **outBuffer, size_t outBufLen)
+{
+ IEventProvider *provider = reinterpret_cast<IEventProvider *>(inProvider);
+ SCToCppFactory theFactory(inFactory);
+ return provider->GetNextEvents(theFactory, outBuffer, outBufLen);
+}
+
+static void ReleaseFn(void *inProvider)
+{
+ IEventProvider *provider = reinterpret_cast<IEventProvider *>(inProvider);
+ provider->Release();
+}
+
+static int registerCANProvider(lua_State *inState)
+{
+ luaL_checktype(inState, 1, LUA_TLIGHTUSERDATA);
+ SUICEventSystemEventPoller *thePoller =
+ reinterpret_cast<SUICEventSystemEventPoller *>(lua_touserdata(inState, 1));
+ if (thePoller) {
+ SUICEventSystemEventProvider provider;
+ provider.m_Provider = static_cast<IEventProvider *>(new CCanProviderDemo());
+ provider.getNextEvents = GetNextEventsFn;
+ provider.release = ReleaseFn;
+ thePoller->addProvider(thePoller->m_Poller, provider);
+ }
+ return 0;
+}
+
+static void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
+{
+ (void)ud;
+ (void)osize; /* not used */
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
+ } else
+ return realloc(ptr, nsize);
+}
+
+static int output(lua_State *inState)
+{
+ const char *theStr = lua_tostring(inState, -1);
+ puts(theStr);
+ return 0;
+}
+
+void TestLuaBindings()
+{
+ lua_State *theState = lua_newstate(l_alloc, NULL);
+ luaL_openlibs(theState);
+ lua_pushcfunction(theState, registerCANProvider);
+ lua_setfield(theState, LUA_GLOBALSINDEX, "registerCANProvider");
+
+ qt3ds::foundation::SErrorStream errors;
+ qt3ds::foundation::CAllocator allocator(errors);
+ qt3ds::foundation::NVScopedRefCounted<qt3ds::NVFoundation> theFoundation =
+ NVCreateFoundation(QT3DS_FOUNDATION_VERSION, allocator, errors);
+
+ qt3ds::foundation::NVScopedRefCounted<IEventSystem> theEventSystem =
+ IEventSystem::Create(*theFoundation);
+ SLuaEventPollerBinding::WrapEventPoller(theState, *theEventSystem);
+ lua_setfield(theState, LUA_GLOBALSINDEX, "eventSystem");
+ lua_pushcfunction(theState, output);
+ lua_setfield(theState, LUA_GLOBALSINDEX, "output");
+
+ luaL_loadstring(theState, luaScript);
+ int failure = lua_pcall(theState, 0, 0, 0);
+ if (failure) {
+ const char *errorMsg = lua_tostring(theState, -1);
+ puts(errorMsg);
+ }
+}
+
+int main()
+{
+ // TestCPPBindings();
+ TestLuaBindings();
+ return 0;
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.cpp
new file mode 100644
index 00000000..4d3b1f83
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.cpp
@@ -0,0 +1,473 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderCamera.h"
+#include "UICRenderPresentation.h"
+#include "foundation/Qt3DSVec2.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICTextRenderer.h"
+/*
+#include <Windows.h>
+*/
+
+using namespace uic::render;
+
+namespace {
+
+QT3DSF32 GetAspectRatio(const NVRenderRectF &inViewport)
+{
+ return inViewport.m_Height != 0 ? inViewport.m_Width / inViewport.m_Height : 0.0f;
+}
+
+QT3DSF32 GetAspectRatio(const QT3DSVec2 &inDimensions)
+{
+ return inDimensions.y != 0 ? inDimensions.x / inDimensions.y : 0.0f;
+}
+
+bool IsCameraVerticalAdjust(CameraScaleModes::Enum inMode, QT3DSF32 inDesignAspect,
+ QT3DSF32 inActualAspect)
+{
+ return (inMode == CameraScaleModes::Fit && inActualAspect >= inDesignAspect)
+ || inMode == CameraScaleModes::FitVertical;
+}
+
+bool IsCameraHorizontalAdjust(CameraScaleModes::Enum inMode, QT3DSF32 inDesignAspect,
+ QT3DSF32 inActualAspect)
+{
+ return (inMode == CameraScaleModes::Fit && inActualAspect < inDesignAspect)
+ || inMode == CameraScaleModes::FitHorizontal;
+}
+
+bool IsFitTypeScaleMode(CameraScaleModes::Enum inMode)
+{
+ return inMode == CameraScaleModes::Fit || inMode == CameraScaleModes::FitHorizontal
+ || inMode == CameraScaleModes::FitVertical;
+}
+
+struct SPinCameraResult
+{
+ NVRenderRectF m_Viewport;
+ NVRenderRectF m_VirtualViewport;
+ SPinCameraResult(NVRenderRectF v, NVRenderRectF vv)
+ : m_Viewport(v)
+ , m_VirtualViewport(vv)
+ {
+ }
+};
+// Scale and transform the projection matrix to respect the camera anchor attribute
+// and the scale mode.
+SPinCameraResult PinCamera(const NVRenderRectF &inViewport, QT3DSVec2 inDesignDims,
+ QT3DSMat44 &ioPerspectiveMatrix, CameraScaleModes::Enum inScaleMode,
+ CameraScaleAnchors::Enum inPinLocation)
+{
+ NVRenderRectF viewport(inViewport);
+ NVRenderRectF idealViewport(inViewport.m_X, inViewport.m_Y, inDesignDims.x, inDesignDims.y);
+ QT3DSF32 designAspect = GetAspectRatio(inDesignDims);
+ QT3DSF32 actualAspect = GetAspectRatio(inViewport);
+ if (IsFitTypeScaleMode(inScaleMode)) {
+ idealViewport.m_Width = viewport.m_Width;
+ idealViewport.m_Height = viewport.m_Height;
+ }
+ // We move the viewport such that the left, top of the presentation sits against the left top
+ // edge
+ // We only need to translate in X *if* our actual aspect > design aspect
+ // And then we only need to account for whatever centering would happen.
+
+ bool pinLeft = inPinLocation == CameraScaleAnchors::SouthWest
+ || inPinLocation == CameraScaleAnchors::West
+ || inPinLocation == CameraScaleAnchors::NorthWest;
+ bool pinRight = inPinLocation == CameraScaleAnchors::SouthEast
+ || inPinLocation == CameraScaleAnchors::East
+ || inPinLocation == CameraScaleAnchors::NorthEast;
+ bool pinTop = inPinLocation == CameraScaleAnchors::NorthWest
+ || inPinLocation == CameraScaleAnchors::North
+ || inPinLocation == CameraScaleAnchors::NorthEast;
+ bool pinBottom = inPinLocation == CameraScaleAnchors::SouthWest
+ || inPinLocation == CameraScaleAnchors::South
+ || inPinLocation == CameraScaleAnchors::SouthEast;
+
+ if (inScaleMode == CameraScaleModes::SameSize) {
+ // In this case the perspective transform does not center the view,
+ // it places it in the lower-left of the viewport.
+ QT3DSF32 idealWidth = inDesignDims.x;
+ QT3DSF32 idealHeight = inDesignDims.y;
+ if (pinRight)
+ idealViewport.m_X -= ((idealWidth - inViewport.m_Width));
+ else if (!pinLeft)
+ idealViewport.m_X -= ((idealWidth - inViewport.m_Width) / 2.0f);
+
+ if (pinTop)
+ idealViewport.m_Y -= ((idealHeight - inViewport.m_Height));
+ else if (!pinBottom)
+ idealViewport.m_Y -= ((idealHeight - inViewport.m_Height) / 2.0f);
+ } else {
+ // In this case our perspective matrix will center the view and we need to decenter
+ // it as necessary
+ // if we are wider than we are high
+ if (IsCameraVerticalAdjust(inScaleMode, designAspect, actualAspect)) {
+ if (pinLeft || pinRight) {
+ QT3DSF32 idealWidth = inViewport.m_Height * designAspect;
+ QT3DSI32 halfOffset = (QT3DSI32)((idealWidth - inViewport.m_Width) / 2.0f);
+ halfOffset = pinLeft ? halfOffset : -1 * halfOffset;
+ idealViewport.m_X += halfOffset;
+ }
+ } else {
+ if (pinTop || pinBottom) {
+ QT3DSF32 idealHeight = inViewport.m_Width / designAspect;
+ QT3DSI32 halfOffset = (QT3DSI32)((idealHeight - inViewport.m_Height) / 2.0f);
+ halfOffset = pinBottom ? halfOffset : -1 * halfOffset;
+ idealViewport.m_Y += halfOffset;
+ }
+ }
+ }
+
+ ioPerspectiveMatrix = NVRenderContext::ApplyVirtualViewportToProjectionMatrix(
+ ioPerspectiveMatrix, viewport, idealViewport);
+ return SPinCameraResult(viewport, idealViewport);
+}
+}
+
+SCamera::SCamera()
+ : SNode(GraphObjectTypes::Camera)
+ , m_ClipNear(10)
+ , m_ClipFar(10000)
+ , m_FOV(60)
+ , m_ScaleMode(CameraScaleModes::Fit)
+ , m_ScaleAnchor(CameraScaleAnchors::Center)
+{
+ TORAD(m_FOV);
+ m_Projection = QT3DSMat44::createIdentity();
+ m_Position = QT3DSVec3(0, 0, -600);
+}
+
+// Code for testing
+SCameraGlobalCalculationResult SCamera::CalculateGlobalVariables(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions)
+{
+ bool wasDirty = SNode::CalculateGlobalVariables();
+ return SCameraGlobalCalculationResult(wasDirty,
+ CalculateProjection(inViewport, inDesignDimensions));
+}
+
+bool SCamera::CalculateProjection(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions)
+{
+ bool retval = false;
+ if (m_Flags.IsOrthographic())
+ retval = ComputeFrustumOrtho(inViewport, inDesignDimensions);
+ else
+ retval = ComputeFrustumPerspective(inViewport, inDesignDimensions);
+ if (retval) {
+ QT3DSF32 *writePtr(m_Projection.front());
+ m_FrustumScale.x = writePtr[0];
+ m_FrustumScale.y = writePtr[5];
+ PinCamera(inViewport, inDesignDimensions, m_Projection, m_ScaleMode, m_ScaleAnchor);
+ }
+ return retval;
+}
+
+//==============================================================================
+/**
+ * Compute the projection matrix for a perspective camera
+ * @return true if the computed projection matrix is valid
+ */
+bool SCamera::ComputeFrustumPerspective(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions)
+{
+ m_Projection = QT3DSMat44::createIdentity();
+ QT3DSF32 theAngleInRadians = m_FOV / 2.0f;
+ QT3DSF32 theDeltaZ = m_ClipFar - m_ClipNear;
+ QT3DSF32 theSine = sinf(theAngleInRadians);
+ QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions);
+ QT3DSF32 theAspectRatio = designAspect;
+ if (IsFitTypeScaleMode(m_ScaleMode))
+ theAspectRatio = GetAspectRatio(inViewport);
+
+ if ((theDeltaZ != 0) && (theSine != 0) && (theAspectRatio != 0)) {
+ QT3DSF32 *writePtr(m_Projection.front());
+ writePtr[10] = -(m_ClipFar + m_ClipNear) / theDeltaZ;
+ writePtr[11] = -1;
+ writePtr[14] = -2 * m_ClipNear * m_ClipFar / theDeltaZ;
+ writePtr[15] = 0;
+
+ if (IsCameraVerticalAdjust(m_ScaleMode, designAspect, theAspectRatio)) {
+ QT3DSF32 theCotangent = cosf(theAngleInRadians) / theSine;
+ writePtr[0] = theCotangent / theAspectRatio;
+ writePtr[5] = theCotangent;
+ } else {
+ QT3DSF32 theCotangent = cosf(theAngleInRadians) / theSine;
+ writePtr[0] = theCotangent / designAspect;
+ writePtr[5] = theCotangent * (theAspectRatio / designAspect);
+ }
+ return true;
+ } else {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+}
+
+//==============================================================================
+/**
+ * Compute the projection matrix for a orthographic camera
+ * @return true if the computed projection matrix is valid
+ */
+bool SCamera::ComputeFrustumOrtho(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions)
+{
+ m_Projection = QT3DSMat44::createIdentity();
+
+ QT3DSF32 theDeltaZ = m_ClipFar - m_ClipNear;
+ QT3DSF32 halfWidth = inDesignDimensions.x / 2.0f;
+ QT3DSF32 halfHeight = inDesignDimensions.y / 2.0f;
+ QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions);
+ QT3DSF32 theAspectRatio = designAspect;
+ if (IsFitTypeScaleMode(m_ScaleMode))
+ theAspectRatio = GetAspectRatio(inViewport);
+ if (theDeltaZ != 0) {
+ QT3DSF32 *writePtr(m_Projection.front());
+ writePtr[10] = -2.0f / theDeltaZ;
+ writePtr[11] = 0.0f;
+ writePtr[14] = -(m_ClipNear + m_ClipFar) / theDeltaZ;
+ writePtr[15] = 1.0f;
+ if (IsCameraVerticalAdjust(m_ScaleMode, designAspect, theAspectRatio)) {
+ writePtr[0] = 1.0f / (halfHeight * theAspectRatio);
+ writePtr[5] = 1.0f / halfHeight;
+ } else {
+ writePtr[0] = 1.0f / halfWidth;
+ writePtr[5] = 1.0f / (halfWidth / theAspectRatio);
+ }
+ return true;
+ } else {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+}
+
+QT3DSF32 SCamera::GetOrthographicScaleFactor(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const
+{
+ if (m_ScaleMode == CameraScaleModes::SameSize)
+ return 1.0f;
+ QT3DSMat44 temp(QT3DSMat44::createIdentity());
+ QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions);
+ QT3DSF32 theAspectRatio = GetAspectRatio(inViewport);
+ if (m_ScaleMode == CameraScaleModes::Fit) {
+ if (theAspectRatio >= designAspect) {
+ return inViewport.m_Width < inDesignDimensions.x ? theAspectRatio / designAspect : 1.0f;
+
+ } else {
+ return inViewport.m_Height < inDesignDimensions.y ? designAspect / theAspectRatio
+ : 1.0f;
+ }
+ } else if (m_ScaleMode == CameraScaleModes::FitVertical) {
+ return (QT3DSF32)inDesignDimensions.y / (QT3DSF32)inViewport.m_Height;
+ } else {
+ return (QT3DSF32)inDesignDimensions.x / (QT3DSF32)inViewport.m_Width;
+ }
+}
+
+QT3DSF32 SCamera::GetTextScaleFactor(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const
+{
+ return NVMax(1.0f, 1.0f / GetOrthographicScaleFactor(inViewport, inDesignDimensions));
+}
+
+QT3DSMat33 SCamera::GetLookAtMatrix(const QT3DSVec3 &inUpDir, const QT3DSVec3 &inDirection) const
+{
+ QT3DSVec3 theDirection(inDirection);
+
+ theDirection.normalize();
+
+ const QT3DSVec3 &theUpDir(inUpDir);
+
+ // gram-shmidt orthogonalization
+ QT3DSVec3 theCrossDir(theDirection.cross(theUpDir));
+ theCrossDir.normalize();
+ QT3DSVec3 theFinalDir(theCrossDir.cross(theDirection));
+ theFinalDir.normalize();
+ QT3DSF32 multiplier = 1.0f;
+ if (m_Flags.IsLeftHanded())
+ multiplier = -1.0f;
+
+ QT3DSMat33 theResultMatrix(theCrossDir, theFinalDir, multiplier * theDirection);
+ return theResultMatrix;
+}
+
+void SCamera::LookAt(const QT3DSVec3 &inCameraPos, const QT3DSVec3 &inUpDir, const QT3DSVec3 &inTargetPos)
+{
+ QT3DSVec3 theDirection = inTargetPos - inCameraPos;
+ if (m_Flags.IsLeftHanded())
+ theDirection.z *= -1.0f;
+ m_Rotation = GetRotationVectorFromRotationMatrix(GetLookAtMatrix(inUpDir, theDirection));
+ m_Position = inCameraPos;
+ MarkDirty(uic::render::NodeTransformDirtyFlag::TransformIsDirty);
+}
+
+void SCamera::CalculateViewProjectionMatrix(QT3DSMat44 &outMatrix) const
+{
+ QT3DSMat44 globalInverse = m_GlobalTransform.getInverse();
+ outMatrix = m_Projection * globalInverse;
+}
+
+SCuboidRect SCamera::GetCameraBounds(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const
+{
+ QT3DSMat44 unused(QT3DSMat44::createIdentity());
+ SPinCameraResult theResult =
+ PinCamera(inViewport, inDesignDimensions, unused, m_ScaleMode, m_ScaleAnchor);
+ // find the normalized edges of the view frustum given the renormalization that happens when
+ // pinning the camera.
+ SCuboidRect normalizedCuboid(-1, 1, 1, -1);
+ QT3DSVec2 translation(theResult.m_Viewport.m_X - theResult.m_VirtualViewport.m_X,
+ theResult.m_Viewport.m_Y - theResult.m_VirtualViewport.m_Y);
+ if (m_ScaleMode == CameraScaleModes::SameSize) {
+ // the cuboid ranges are the actual divided by the ideal in this case
+ QT3DSF32 xRange = 2.0f * (theResult.m_Viewport.m_Width / theResult.m_VirtualViewport.m_Width);
+ QT3DSF32 yRange =
+ 2.0f * (theResult.m_Viewport.m_Height / theResult.m_VirtualViewport.m_Height);
+ normalizedCuboid = SCuboidRect(-1, -1 + yRange, -1 + xRange, -1);
+ translation.x /= (theResult.m_VirtualViewport.m_Width / 2.0f);
+ translation.y /= (theResult.m_VirtualViewport.m_Height / 2.0f);
+ normalizedCuboid.Translate(translation);
+ }
+ // fit. This means that two parameters of the normalized cuboid will be -1, 1.
+ else {
+ // In this case our perspective matrix will center the view and we need to decenter
+ // it as necessary
+ QT3DSF32 actualAspect = GetAspectRatio(inViewport);
+ QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions);
+ // if we are wider than we are high
+ QT3DSF32 idealWidth = inViewport.m_Width;
+ QT3DSF32 idealHeight = inViewport.m_Height;
+
+ if (IsCameraVerticalAdjust(m_ScaleMode, designAspect, actualAspect)) {
+ // then we just need to setup the left, right parameters of the cuboid because we know
+ // the top
+ // bottom are -1,1 due to how fit works.
+ idealWidth = (QT3DSF32)ITextRenderer::NextMultipleOf4(
+ (QT3DSU32)(inViewport.m_Height * designAspect + .5f));
+ // halfRange should always be greater than 1.0f.
+ QT3DSF32 halfRange = inViewport.m_Width / idealWidth;
+ normalizedCuboid.m_Left = -halfRange;
+ normalizedCuboid.m_Right = halfRange;
+ translation.x = translation.x / (idealWidth / 2.0f);
+ } else {
+ idealHeight = (QT3DSF32)ITextRenderer::NextMultipleOf4(
+ (QT3DSU32)(inViewport.m_Width / designAspect + .5f));
+ QT3DSF32 halfRange = inViewport.m_Height / idealHeight;
+ normalizedCuboid.m_Bottom = -halfRange;
+ normalizedCuboid.m_Top = halfRange;
+ translation.y = translation.y / (idealHeight / 2.0f);
+ }
+ normalizedCuboid.Translate(translation);
+ }
+ // Given no adjustment in the virtual rect, then this is what we would have.
+
+ return normalizedCuboid;
+}
+
+void SCamera::SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture,
+ QT3DSMat44 &outVP)
+{
+ STextureDetails theDetails(inTexture.GetTextureDetails());
+ SCamera theTempCamera;
+ SetupOrthographicCameraForOffscreenRender(inTexture, outVP, theTempCamera);
+}
+
+void SCamera::SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture,
+ QT3DSMat44 &outVP, SCamera &outCamera)
+{
+ STextureDetails theDetails(inTexture.GetTextureDetails());
+ SCamera theTempCamera;
+ theTempCamera.m_Flags.SetOrthographic(true);
+ theTempCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ QT3DSVec2 theDimensions((QT3DSF32)theDetails.m_Width, (QT3DSF32)theDetails.m_Height);
+ theTempCamera.CalculateGlobalVariables(
+ NVRenderRect(0, 0, theDetails.m_Width, theDetails.m_Height), theDimensions);
+ theTempCamera.CalculateViewProjectionMatrix(outVP);
+ outCamera = theTempCamera;
+}
+
+SRay SCamera::Unproject(const QT3DSVec2 &inViewportRelativeCoords, const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const
+{
+ SRay theRay;
+ QT3DSMat44 tempVal(QT3DSMat44::createIdentity());
+ SPinCameraResult result =
+ PinCamera(inViewport, inDesignDimensions, tempVal, m_ScaleMode, m_ScaleAnchor);
+ QT3DSVec2 globalCoords = inViewport.ToAbsoluteCoords(inViewportRelativeCoords);
+ QT3DSVec2 normalizedCoords =
+ result.m_VirtualViewport.AbsoluteToNormalizedCoordinates(globalCoords);
+ QT3DSVec3 &outOrigin(theRay.m_Origin);
+ QT3DSVec3 &outDir(theRay.m_Direction);
+ QT3DSVec2 inverseFrustumScale(1.0f / m_FrustumScale.x, 1.0f / m_FrustumScale.y);
+ QT3DSVec2 scaledCoords(inverseFrustumScale.x * normalizedCoords.x,
+ inverseFrustumScale.y * normalizedCoords.y);
+
+ if (m_Flags.IsOrthographic()) {
+ outOrigin.x = scaledCoords.x;
+ outOrigin.y = scaledCoords.y;
+ outOrigin.z = 0.0f;
+
+ outDir.x = 0.0f;
+ outDir.y = 0.0f;
+ outDir.z = -1.0f;
+ } else {
+ outOrigin.x = 0.0f;
+ outOrigin.y = 0.0f;
+ outOrigin.z = 0.0f;
+
+ outDir.x = scaledCoords.x;
+ outDir.y = scaledCoords.y;
+ outDir.z = -1.0f;
+ }
+
+ outOrigin = m_GlobalTransform.transform(outOrigin);
+ QT3DSMat33 theNormalMatrix;
+ CalculateNormalMatrix(theNormalMatrix);
+
+ outDir = theNormalMatrix.transform(outDir);
+ outDir.normalize();
+ /*
+ char printBuf[2000];
+ sprintf_s( printBuf, "normCoords %f %f outDir %f %f %f\n"
+ , normalizedCoords.x, normalizedCoords.y, outDir.x, outDir.y, outDir.z );
+ OutputDebugStringA( printBuf );
+ */
+
+ return theRay;
+}
+
+QT3DSVec3 SCamera::UnprojectToPosition(const QT3DSVec3 &inGlobalPos, const SRay &inRay) const
+{
+ QT3DSVec3 theCameraDir = GetDirection();
+ QT3DSVec3 theObjGlobalPos = inGlobalPos;
+ QT3DSF32 theDistance = -1.0f * theObjGlobalPos.dot(theCameraDir);
+ NVPlane theCameraPlane(theCameraDir, theDistance);
+ return inRay.Intersect(theCameraPlane);
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.h
new file mode 100644
index 00000000..432ef873
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderCamera.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CAMERA_H
+#define UIC_RENDER_CAMERA_H
+#include "UICRenderNode.h"
+#include "UICRenderRay.h"
+
+namespace uic {
+namespace render {
+
+ struct SCameraGlobalCalculationResult
+ {
+ bool m_WasDirty;
+ bool m_ComputeFrustumSucceeded;
+ SCameraGlobalCalculationResult(bool inWasDirty, bool inComputeSucceeded = true)
+ : m_WasDirty(inWasDirty)
+ , m_ComputeFrustumSucceeded(inComputeSucceeded)
+ {
+ }
+ };
+
+ struct CameraScaleModes
+ {
+ enum Enum {
+ Fit = 0,
+ SameSize,
+ FitHorizontal,
+ FitVertical,
+ };
+ };
+
+ struct CameraScaleAnchors
+ {
+ enum Enum {
+ Center = 0,
+ North,
+ NorthEast,
+ East,
+ SouthEast,
+ South,
+ SouthWest,
+ West,
+ NorthWest,
+ };
+ };
+
+ struct SCuboidRect
+ {
+ QT3DSF32 m_Left;
+ QT3DSF32 m_Top;
+ QT3DSF32 m_Right;
+ QT3DSF32 m_Bottom;
+ SCuboidRect(QT3DSF32 l = 0.0f, QT3DSF32 t = 0.0f, QT3DSF32 r = 0.0f, QT3DSF32 b = 0.0f)
+ : m_Left(l)
+ , m_Top(t)
+ , m_Right(r)
+ , m_Bottom(b)
+ {
+ }
+ void Translate(QT3DSVec2 inTranslation)
+ {
+ m_Left += inTranslation.x;
+ m_Right += inTranslation.x;
+ m_Top += inTranslation.y;
+ m_Bottom += inTranslation.y;
+ }
+ };
+
+ struct SCamera : public SNode
+ {
+
+ // Setting these variables should set dirty on the camera.
+ QT3DSF32 m_ClipNear;
+ QT3DSF32 m_ClipFar;
+
+ QT3DSF32 m_FOV; // Radians
+
+ QT3DSMat44 m_Projection;
+ CameraScaleModes::Enum m_ScaleMode;
+ CameraScaleAnchors::Enum m_ScaleAnchor;
+ // Record some values from creating the projection matrix
+ // to use during mouse picking.
+ QT3DSVec2 m_FrustumScale;
+
+ SCamera();
+
+ QT3DSMat33 GetLookAtMatrix(const QT3DSVec3 &inUpDir, const QT3DSVec3 &inDirection) const;
+ // Set our position, rotation member variables based on the lookat target
+ // Marks this object as dirty.
+ // Need to test this when the camera's local transform is null.
+ // Assumes parent's local transform is the identity, meaning our local transform is
+ // our global transform.
+ void LookAt(const QT3DSVec3 &inCameraPos, const QT3DSVec3 &inUpDir, const QT3DSVec3 &inTargetPos);
+
+ SCameraGlobalCalculationResult CalculateGlobalVariables(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions);
+ bool CalculateProjection(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions);
+ bool ComputeFrustumOrtho(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions);
+ // Used when rendering the widgets in studio. This scales the widget when in orthographic
+ // mode in order to have
+ // constant size on screen regardless.
+ // Number is always greater than one
+ QT3DSF32 GetOrthographicScaleFactor(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const;
+ bool ComputeFrustumPerspective(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions);
+ // Text may be scaled so that it doesn't appear pixellated when the camera itself is doing
+ // the scaling.
+ QT3DSF32 GetTextScaleFactor(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const;
+
+ void CalculateViewProjectionMatrix(QT3DSMat44 &outMatrix) const;
+
+ // If this is an orthographic camera, the cuboid properties are the distance from the center
+ // point
+ // to the left, top, right, and bottom edges of the view frustum in world units.
+ // If this is a perspective camera, the cuboid properties are the FOV angles
+ // (left,top,right,bottom)
+ // of the view frustum.
+
+ // Return a normalized rect that describes the area the camera is rendering to.
+ // This takes into account the various camera properties (scale mode, scale anchor).
+ SCuboidRect GetCameraBounds(const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const;
+
+ // Setup a camera VP projection for rendering offscreen.
+ static void SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture,
+ QT3DSMat44 &outVP);
+ static void SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture,
+ QT3DSMat44 &outVP, SCamera &outCamera);
+
+ // Unproject a point (x,y) in viewport relative coordinates meaning
+ // left, bottom is 0,0 and values are increasing right,up respectively.
+ SRay Unproject(const QT3DSVec2 &inLayerRelativeMouseCoords, const NVRenderRectF &inViewport,
+ const QT3DSVec2 &inDesignDimensions) const;
+
+ // Unproject a given coordinate to a 3d position that lies on the same camera
+ // plane as inGlobalPos.
+ // Expects CalculateGlobalVariables has been called or doesn't need to be.
+ QT3DSVec3 UnprojectToPosition(const QT3DSVec3 &inGlobalPos, const SRay &inRay) const;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderCustomMaterial.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderCustomMaterial.h
new file mode 100644
index 00000000..5d0c3409
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderCustomMaterial.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CUSTOM_MATERIAL_H
+#define UIC_RENDER_CUSTOM_MATERIAL_H
+#include "UICRender.h"
+#include "UICRenderDynamicObject.h"
+#include "UICRenderImage.h"
+#include "UICRenderLightmaps.h"
+#include "foundation/Qt3DSFlags.h"
+
+namespace uic {
+namespace render {
+
+ // IMPORTANT: These flags matches the key produced by a MDL export file
+ struct SCustomMaterialShaderKeyValues
+ {
+ enum Enum {
+ diffuse = 1 << 0,
+ specular = 1 << 1,
+ glossy = 1 << 2,
+ cutout = 1 << 3,
+ refraction = 1 << 4,
+ transparent = 1 << 5,
+ displace = 1 << 6,
+ volumetric = 1 << 7,
+ transmissive = 1 << 8,
+ };
+ };
+
+ typedef NVFlags<SCustomMaterialShaderKeyValues::Enum, QT3DSU32> SCustomMaterialShaderKeyFlags;
+
+ struct SCustomMaterial : public SDynamicObject
+ {
+ private:
+ // These objects are only created via the dynamic object system.
+ SCustomMaterial(const SCustomMaterial &);
+ SCustomMaterial &operator=(const SCustomMaterial &);
+ SCustomMaterial();
+
+ public:
+ // lightmap section
+ SLightmaps m_Lightmaps;
+ // material section
+ bool m_hasTransparency;
+ bool m_hasRefraction;
+ bool m_hasVolumetricDF;
+ SImage *m_IblProbe;
+ SImage *m_EmissiveMap2;
+ SImage *m_DisplacementMap;
+ QT3DSF32 m_DisplaceAmount; ///< depends on the object size
+
+ SGraphObject *m_NextSibling;
+
+ SCustomMaterialShaderKeyFlags m_ShaderKeyValues; ///< input from MDL files
+ QT3DSU32 m_LayerCount; ///< input from MDL files
+
+ void Initialize(QT3DSU32 inKey, QT3DSU32 inLayerCount)
+ {
+ m_Lightmaps.m_LightmapIndirect = NULL;
+ m_Lightmaps.m_LightmapRadiosity = NULL;
+ m_Lightmaps.m_LightmapShadow = NULL;
+ m_hasTransparency = false;
+ m_hasRefraction = false;
+ m_hasVolumetricDF = false;
+ m_NextSibling = NULL;
+ m_DirtyFlagWithInFrame = m_Flags.IsDirty();
+ m_IblProbe = NULL;
+ m_EmissiveMap2 = NULL;
+ m_DisplacementMap = NULL;
+ m_DisplaceAmount = 0.0;
+ m_ShaderKeyValues = (SCustomMaterialShaderKeyFlags)inKey;
+ m_LayerCount = inLayerCount;
+ }
+
+ bool IsDielectric() const
+ {
+ return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::diffuse;
+ }
+ bool IsSpecularEnabled() const
+ {
+ return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::specular;
+ }
+ bool IsCutOutEnabled() const
+ {
+ return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::cutout;
+ }
+ bool IsVolumetric() const
+ {
+ return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::volumetric;
+ }
+ bool IsTransmissive() const
+ {
+ return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::transmissive;
+ }
+ bool HasLighting() const { return true; }
+
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SDynamicObject::Remap(inRemapper);
+ m_Lightmaps.Remap(inRemapper);
+ inRemapper.Remap(m_IblProbe);
+ inRemapper.RemapMaterial(m_NextSibling);
+ inRemapper.Remap(m_EmissiveMap2);
+ inRemapper.Remap(m_DisplacementMap);
+ }
+
+ // Dirty
+ bool m_DirtyFlagWithInFrame;
+ bool IsDirty() const { return m_Flags.IsDirty() || m_DirtyFlagWithInFrame; }
+ void UpdateDirtyForFrame()
+ {
+ m_DirtyFlagWithInFrame = m_Flags.IsDirty();
+ m_Flags.SetDirty(false);
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.cpp
new file mode 100644
index 00000000..90727033
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderDefaultMaterial.h"
+
+using namespace uic::render;
+
+SDefaultMaterial::SDefaultMaterial()
+ : SGraphObject(GraphObjectTypes::DefaultMaterial)
+ , m_IblProbe(NULL)
+ , m_Lighting(DefaultMaterialLighting::VertexLighting)
+ , m_BlendMode(DefaultMaterialBlendMode::Normal)
+ , m_DiffuseColor(1, 1, 1)
+ , m_EmissivePower(0)
+ , m_EmissiveMap(NULL)
+ , m_EmissiveMap2(NULL)
+ , m_EmissiveColor(1, 1, 1)
+ , m_SpecularReflection(NULL)
+ , m_SpecularMap(NULL)
+ , m_SpecularModel(DefaultMaterialSpecularModel::Default)
+ , m_SpecularTint(1, 1, 1)
+ , m_IOR(.2f)
+ , m_FresnelPower(0.0f)
+ , m_SpecularAmount(0)
+ , m_SpecularRoughness(50)
+ , m_Opacity(1)
+ , m_OpacityMap(NULL)
+ , m_BumpMap(NULL)
+ , m_BumpAmount(0.f)
+ , m_NormalMap(NULL)
+ , m_DisplacementMap(NULL)
+ , m_DisplaceAmount(0.f)
+ , m_TranslucencyMap(NULL)
+ , m_TranslucentFalloff(0.f)
+ , m_DiffuseLightWrap(0.f)
+ , m_NextSibling(NULL)
+ , m_Parent(NULL)
+{
+ m_Lightmaps.m_LightmapIndirect = NULL;
+ m_Lightmaps.m_LightmapRadiosity = NULL;
+ m_Lightmaps.m_LightmapShadow = NULL;
+
+ m_DiffuseMaps[0] = NULL;
+ m_DiffuseMaps[2] = NULL;
+ m_DiffuseMaps[1] = NULL;
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.h
new file mode 100644
index 00000000..8f8371c2
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDefaultMaterial.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_DEFAULT_MATERIAL_H
+#define UIC_RENDER_DEFAULT_MATERIAL_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSVec3.h"
+#include "UICRenderMaterialDirty.h"
+#include "UICRenderLightmaps.h"
+
+namespace uic {
+namespace render {
+ struct DefaultMaterialLighting
+ {
+ enum Enum {
+ NoLighting = 0,
+ VertexLighting,
+ FragmentLighting
+ };
+ };
+ struct DefaultMaterialBlendMode
+ {
+ enum Enum {
+ Normal = 0,
+ Screen,
+ Multiply,
+ Overlay,
+ ColorBurn,
+ ColorDodge
+ };
+ };
+
+ struct DefaultMaterialSpecularModel
+ {
+ enum Enum {
+ Default = 0,
+ KGGX,
+ KWard
+ };
+ };
+
+ struct SImage;
+
+ struct SDefaultMaterial : SGraphObject
+ {
+ CMaterialDirty m_Dirty;
+ // lightmap section
+ SLightmaps m_Lightmaps;
+ // material section
+ SImage *m_IblProbe;
+ DefaultMaterialLighting::Enum m_Lighting; // defaults to vertex
+ DefaultMaterialBlendMode::Enum m_BlendMode; // defaults to normal
+ QT3DSVec3 m_DiffuseColor; // colors are 0-1 normalized
+ SImage *m_DiffuseMaps[3];
+ QT3DSF32 m_EmissivePower; // 0-100, defaults to 0
+ QT3DSVec3 m_EmissiveColor;
+ SImage *m_EmissiveMap;
+ SImage *m_EmissiveMap2;
+ SImage *m_SpecularReflection;
+ SImage *m_SpecularMap;
+ DefaultMaterialSpecularModel::Enum m_SpecularModel;
+ QT3DSVec3 m_SpecularTint;
+ QT3DSF32 m_IOR;
+ QT3DSF32 m_FresnelPower;
+ QT3DSF32 m_SpecularAmount; // 0-??, defaults to 0
+ QT3DSF32 m_SpecularRoughness; // 0-??, defaults to 50
+ QT3DSF32 m_Opacity; // 0-1
+ SImage *m_OpacityMap;
+ SImage *m_BumpMap;
+ QT3DSF32 m_BumpAmount; // 0-??
+ SImage *m_NormalMap;
+ SImage *m_DisplacementMap;
+ QT3DSF32 m_DisplaceAmount; // 0-??
+ SImage *m_TranslucencyMap;
+ QT3DSF32 m_TranslucentFalloff; // 0 - ??
+ QT3DSF32 m_DiffuseLightWrap; // 0 - 1
+ // Materials are stored as a linked list on models.
+ SGraphObject *m_NextSibling;
+ SModel *m_Parent;
+
+ SDefaultMaterial();
+
+ bool IsSpecularEnabled() const { return m_SpecularAmount > .01f; }
+ bool IsFresnelEnabled() const { return m_FresnelPower > 0.0f; }
+ bool HasLighting() const { return m_Lighting != DefaultMaterialLighting::NoLighting; }
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ m_Lightmaps.Remap(inRemapper);
+ inRemapper.Remap(m_IblProbe);
+ inRemapper.Remap(m_DiffuseMaps[0]);
+ inRemapper.Remap(m_DiffuseMaps[1]);
+ inRemapper.Remap(m_DiffuseMaps[2]);
+ inRemapper.Remap(m_EmissiveMap);
+ inRemapper.Remap(m_EmissiveMap2);
+ inRemapper.Remap(m_SpecularReflection);
+ inRemapper.Remap(m_SpecularMap);
+ inRemapper.Remap(m_OpacityMap);
+ inRemapper.Remap(m_BumpMap);
+ inRemapper.Remap(m_NormalMap);
+ inRemapper.Remap(m_DisplacementMap);
+ inRemapper.Remap(m_TranslucencyMap);
+ inRemapper.RemapMaterial(m_NextSibling);
+ inRemapper.Remap(m_Parent);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.cpp
new file mode 100644
index 00000000..3eea8d6f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRender.h"
+#include "UICRenderDynamicObject.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "foundation/FileTools.h"
+#include "UICRenderString.h"
+
+#include <QtCore/qdir.h>
+
+using namespace uic;
+using namespace uic::render;
+
+SDynamicObject::SDynamicObject(GraphObjectTypes::Enum inType, CRegisteredString inObjName,
+ QT3DSU32 inDSByteSize, QT3DSU32 thisObjSize)
+ : SGraphObject(inType)
+ , m_ClassName(inObjName)
+ , m_DataSectionByteSize(inDSByteSize)
+ , m_ThisObjectSize(thisObjSize)
+{
+}
+
+template <typename TDataType>
+void SDynamicObject::SetPropertyValueT(const dynamic::SPropertyDefinition &inDefinition,
+ const TDataType &inValue)
+{
+ if (sizeof(inValue) != inDefinition.m_ByteSize) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ memCopy(GetDataSectionBegin() + inDefinition.m_Offset, &inValue, sizeof(inValue));
+}
+
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ bool inValue)
+{
+ SetPropertyValueT(inDefinition, inValue);
+}
+
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ QT3DSF32 inValue)
+{
+ SetPropertyValueT(inDefinition, inValue);
+}
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ QT3DSF32 inValue, QT3DSU32 inOffset)
+{
+ if (sizeof(QT3DSF32) > (inDefinition.m_ByteSize - inOffset)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ memCopy(GetDataSectionBegin() + inDefinition.m_Offset + inOffset, &inValue, sizeof(inValue));
+}
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const QT3DSVec2 &inValue)
+{
+ SetPropertyValueT(inDefinition, inValue);
+}
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const QT3DSVec3 &inValue)
+{
+ SetPropertyValueT(inDefinition, inValue);
+}
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const QT3DSVec4 &inValue)
+{
+ SetPropertyValueT(inDefinition, inValue);
+}
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ QT3DSI32 inValue)
+{
+ SetPropertyValueT(inDefinition, inValue);
+}
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ CRegisteredString inValue)
+{
+ QT3DS_ASSERT(inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr);
+ SetPropertyValueT(inDefinition, inValue);
+}
+template <typename TStrType>
+void SDynamicObject::SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefinition,
+ const char8_t *inValue, const char8_t *inProjectDir,
+ TStrType &ioWorkspace, IStringTable &inStrTable)
+{
+ if (inValue == NULL)
+ inValue = "";
+ if (inDefinition.m_DataType == NVRenderShaderDataTypes::QT3DSI32) {
+ NVConstDataRef<CRegisteredString> theEnumValues = inDefinition.m_EnumValueNames;
+ for (QT3DSI32 idx = 0, end = (QT3DSI32)theEnumValues.size(); idx < end; ++idx) {
+ if (strcmp(theEnumValues[idx].c_str(), inValue) == 0) {
+ SetPropertyValueT(inDefinition, idx);
+ break;
+ }
+ }
+ } else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ if (inProjectDir == NULL)
+ inProjectDir = "";
+ if (CFileTools::RequiresCombineBaseAndRelative(inValue)) {
+ QString absolute = QDir(inProjectDir).filePath(inValue);
+ ioWorkspace.assign(absolute.toLatin1().constData());
+ SetPropertyValueT(inDefinition, inStrTable.RegisterStr(ioWorkspace.c_str()));
+ // We also adjust the image path in the definition
+ // I could not find a better place
+ inDefinition.m_ImagePath = inStrTable.RegisterStr(ioWorkspace.c_str());
+ } else {
+ SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue));
+ }
+ } else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderImage2DPtr) {
+ SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue));
+ } else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderDataBufferPtr) {
+ SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+}
+
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const char8_t *inValue, const char8_t *inProjectDir,
+ CRenderString &ioWorkspace, IStringTable &inStrTable)
+{
+ SetStrPropertyValueT(const_cast<dynamic::SPropertyDefinition &>(inDefinition), inValue,
+ inProjectDir, ioWorkspace, inStrTable);
+}
+
+void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const char8_t *inValue, const char8_t *inProjectDir,
+ eastl::string &ioWorkspace, IStringTable &inStrTable)
+{
+ SetStrPropertyValueT(const_cast<dynamic::SPropertyDefinition &>(inDefinition), inValue,
+ inProjectDir, ioWorkspace, inStrTable);
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.h
new file mode 100644
index 00000000..35ac9186
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderDynamicObject.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_DYNAMIC_OBJECT_H
+#define UIC_RENDER_DYNAMIC_OBJECT_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "UICRenderNode.h"
+#include "EASTL/string.h"
+
+namespace uic {
+namespace render {
+
+ namespace dynamic {
+ struct SPropertyDefinition;
+ }
+
+ // Dynamic objects are objects that have variable number of properties during runtime.
+ struct SDynamicObject : public SGraphObject
+ {
+ CRegisteredString m_ClassName;
+ NodeFlags m_Flags;
+ QT3DSU32 m_DataSectionByteSize;
+ QT3DSU32 m_ThisObjectSize;
+
+ SDynamicObject(GraphObjectTypes::Enum inType, CRegisteredString inClassName,
+ QT3DSU32 inDSByteSize, QT3DSU32 thisObjSize);
+
+ QT3DSU8 *GetDataSectionBegin()
+ {
+ QT3DSU8 *thisObjectStart = reinterpret_cast<QT3DSU8 *>(this);
+ QT3DSU8 *retval = thisObjectStart + m_ThisObjectSize;
+ QT3DS_ASSERT((reinterpret_cast<size_t>(retval) % 4 == 0));
+ return retval;
+ }
+
+ const QT3DSU8 *GetDataSectionBegin() const
+ {
+ return const_cast<SDynamicObject *>(this)->GetDataSectionBegin();
+ }
+
+ QT3DSU8 *GetDataSectionEnd() { return GetDataSectionBegin() + m_DataSectionByteSize; }
+
+ template <typename TDataType>
+ void SetPropertyValueT(const dynamic::SPropertyDefinition &inDefinition,
+ const TDataType &inType);
+ template <typename TStrType>
+ void SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefinition,
+ const char8_t *inValue, const char8_t *inProjectDir,
+ TStrType &ioWorkspace, IStringTable &inStrTable);
+
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, bool inValue);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, QT3DSF32 inValue);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, QT3DSF32 inValue,
+ QT3DSU32 inOffset);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const QT3DSVec2 &inValue);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const QT3DSVec3 &inValue);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const QT3DSVec4 &inValue);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, QT3DSI32 inValue);
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ CRegisteredString inValue);
+
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const char8_t *inValue, const char8_t *inProjectDir,
+ CRenderString &ioWorkspace, IStringTable &inStrTable);
+
+ void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
+ const char8_t *inValue, const char8_t *inProjectDir,
+ eastl::string &ioWorkspace, IStringTable &inStrTable);
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_ClassName);
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.cpp
new file mode 100644
index 00000000..72b74fd5
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderEffect.h"
+#include "UICRenderEffectSystem.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "UICRenderString.h"
+#include "foundation/FileTools.h"
+
+using namespace uic::render;
+
+void SEffect::Initialize()
+{
+ m_Layer = NULL;
+ m_NextEffect = NULL;
+ m_Context = NULL;
+}
+
+void SEffect::SetActive(bool inActive, IEffectSystem &inManager)
+{
+ if (m_Flags.IsActive() != inActive) {
+ m_Flags.SetActive(inActive);
+ if (m_Context)
+ inManager.ResetEffectFrameData(*m_Context);
+ m_Flags.SetDirty(true);
+ }
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.h
new file mode 100644
index 00000000..4331f2a5
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderEffect.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_EFFECT_H
+#define UIC_RENDER_EFFECT_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "UICRenderNode.h"
+#include "EASTL/string.h"
+#include "UICRenderDynamicObject.h"
+
+namespace uic {
+namespace render {
+ struct SLayer;
+ struct SEffectContext;
+
+ // Effects are post-render effect applied to the layer. There can be more than one of
+ // them and they have completely variable properties.
+ // see IEffectManager in order to create these effects.
+ // The data for the effect immediately follows the effect
+ struct SEffect : public SDynamicObject
+ {
+ private:
+ // These objects are only created via the dynamic object system.
+ SEffect(const SEffect &);
+ SEffect &operator=(const SEffect &);
+ SEffect();
+
+ public:
+ SLayer *m_Layer;
+ SEffect *m_NextEffect;
+ // Opaque pointer to context type implemented by the effect system.
+ // May be null in which case the effect system will generate a new context
+ // the first time it needs to render this effect.
+ SEffectContext *m_Context;
+
+ void Initialize();
+
+ // If our active flag value changes, then we ask the effect manager
+ // to reset our context.
+ void SetActive(bool inActive, IEffectSystem &inSystem);
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SDynamicObject::Remap(inRemapper);
+ inRemapper.Remap(m_Layer);
+ inRemapper.Remap(m_NextEffect);
+ inRemapper.NullPtr(m_Context);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderGraphObject.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderGraphObject.h
new file mode 100644
index 00000000..7f20fd38
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderGraphObject.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_GRAPH_OBJECT_H
+#define UIC_RENDER_GRAPH_OBJECT_H
+#include "UICRender.h"
+#include "UICRenderTaggedPointer.h"
+#include "UICRenderGraphObjectTypes.h"
+
+namespace uic {
+namespace render {
+
+ // Types should be setup on construction. Change the type
+ // at your own risk as the type is used for RTTI purposes.
+ struct SGraphObject
+ {
+ // Id's help debugging the object and are optionally set
+ CRegisteredString m_Id;
+ // Type is used for RTTI purposes down the road.
+ GraphObjectTypes::Enum m_Type;
+ STaggedPointer m_UserData;
+
+ SGraphObject(GraphObjectTypes::Enum inType)
+ : m_Type(inType)
+ {
+ }
+ SGraphObject(const SGraphObject &inCloningObject, NVAllocatorCallback & /*inAllocator*/)
+ : m_Id(inCloningObject.m_Id)
+ , m_Type(inCloningObject.m_Type)
+ {
+ }
+
+ // If you change any detail of the scene graph, or even *breath* on a
+ // scene graph object, you need to bump this binary version so at least
+ // we know if we can load a file or not.
+ static QT3DSU32 GetSceneGraphBinaryVersion() { return 1; }
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ inRemapper.Remap(m_Id);
+ inRemapper.NullPtr(m_UserData.m_UserData);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.cpp
new file mode 100644
index 00000000..fdccc938
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderImage.h"
+#include "UICRenderBufferManager.h"
+#include "UICOffscreenRenderManager.h"
+#include "UICOffscreenRenderKey.h"
+#include "UICRenderPlugin.h"
+#include "UICRenderPluginGraphObject.h"
+
+using namespace uic::render;
+
+SImage::SImage()
+ : SGraphObject(GraphObjectTypes::Image)
+ , m_RenderPlugin(NULL)
+ , m_LastFrameOffscreenRenderer(NULL)
+ , m_Parent(NULL)
+ , m_Scale(1, 1)
+ , m_Pivot(0, 0)
+ , m_Rotation(0)
+ , m_Position(0, 0)
+ , m_MappingMode(ImageMappingModes::Normal)
+ , m_HorizontalTilingMode(NVRenderTextureCoordOp::ClampToEdge)
+ , m_VerticalTilingMode(NVRenderTextureCoordOp::ClampToEdge)
+{
+ m_Flags.SetActive(true);
+ m_Flags.SetDirty(true);
+ m_Flags.SetTransformDirty(true);
+}
+
+static void HandleOffscreenResult(SImage &theImage, SImageTextureData &newImage,
+ SOffscreenRenderResult &theResult, bool &replaceTexture,
+ bool &wasDirty)
+{
+ newImage.m_Texture = theResult.m_Texture;
+ newImage.m_TextureFlags.SetHasTransparency(theResult.m_HasTransparency);
+ newImage.m_TextureFlags.SetPreMultiplied(true);
+ wasDirty = wasDirty || theResult.m_HasChangedSinceLastFrame;
+ theImage.m_LastFrameOffscreenRenderer = theResult.m_Renderer;
+ replaceTexture = true;
+}
+
+bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager,
+ IRenderPluginManager &inPluginManager, bool forIbl)
+{
+
+ bool wasDirty = m_Flags.IsDirty();
+ m_Flags.SetDirty(false);
+ SImageTextureData newImage;
+ bool replaceTexture(false);
+ if (m_RenderPlugin && m_RenderPlugin->m_Flags.IsActive()) {
+ IRenderPluginInstance *theInstance = inPluginManager.GetOrCreateRenderPluginInstance(
+ m_RenderPlugin->m_PluginPath, m_RenderPlugin);
+ if (theInstance) {
+ inRenderManager.MaybeRegisterOffscreenRenderer(theInstance, *theInstance);
+ SOffscreenRenderResult theResult = inRenderManager.GetRenderedItem(theInstance);
+ HandleOffscreenResult(*this, newImage, theResult, replaceTexture, wasDirty);
+ }
+ }
+
+ if (newImage.m_Texture == NULL) {
+ if (m_OffscreenRendererId.IsValid()) {
+ SOffscreenRenderResult theResult =
+ inRenderManager.GetRenderedItem(m_OffscreenRendererId);
+ HandleOffscreenResult(*this, newImage, theResult, replaceTexture, wasDirty);
+ }
+ }
+
+ if (newImage.m_Texture == NULL) {
+ m_LastFrameOffscreenRenderer = NULL;
+ newImage = inBufferManager.LoadRenderImage(m_ImagePath, false, forIbl);
+ replaceTexture = newImage.m_Texture != m_TextureData.m_Texture;
+ }
+
+ if (replaceTexture) {
+ wasDirty = true;
+ m_TextureData = newImage;
+ }
+
+ if (m_Flags.IsTransformDirty()) {
+ wasDirty = true;
+ CalculateTextureTransform();
+ }
+ return wasDirty;
+}
+
+void SImage::CalculateTextureTransform()
+{
+ m_Flags.SetTransformDirty(false);
+
+ m_TextureTransform = QT3DSMat44::createIdentity();
+
+ QT3DSMat44 translation(QT3DSMat44::createIdentity());
+ QT3DSMat44 rotation(QT3DSMat44::createIdentity());
+ QT3DSMat44 scale(QT3DSMat44::createIdentity());
+
+ translation.column3[0] = m_Position.x;
+ translation.column3[1] = m_Position.y;
+ scale.column0[0] = m_Scale.x;
+ scale.column1[1] = m_Scale.y;
+ rotation.rotate(m_Rotation, QT3DSVec3(0, 0, 1));
+
+ // Setup the pivot.
+ m_TextureTransform.column3[0] = m_Pivot.x;
+ m_TextureTransform.column3[1] = m_Pivot.y;
+ m_TextureTransform = m_TextureTransform * rotation;
+ m_TextureTransform = m_TextureTransform * scale;
+ m_TextureTransform = m_TextureTransform * translation;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.h
new file mode 100644
index 00000000..8ee70dc8
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderImage.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_IMAGE_H
+#define UIC_RENDER_IMAGE_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "UICRenderNode.h"
+#include "foundation/Qt3DSVec2.h"
+#include "UICRenderImageTextureData.h"
+#include "EASTL/utility.h"
+
+namespace uic {
+namespace render {
+ class IUICRenderContext;
+ class IOffscreenRenderManager;
+ class IOffscreenRenderer;
+ struct ImageMappingModes
+ {
+ enum Enum {
+ Normal = 0, // UV mapping
+ Environment = 1,
+ LightProbe = 2,
+ };
+ };
+
+ struct SImage : public SGraphObject
+ {
+ // Complete path to the file;
+ //*not* relative to the presentation directory
+ CRegisteredString m_ImagePath;
+ CRegisteredString m_ImageShaderName; ///< for custom materials we don't generate the name
+
+ // Presentation id.
+ CRegisteredString m_OffscreenRendererId; // overrides source path if available
+ SRenderPlugin *m_RenderPlugin; // Overrides everything if available.
+ IOffscreenRenderer *m_LastFrameOffscreenRenderer;
+ SGraphObject *m_Parent;
+
+ SImageTextureData m_TextureData;
+
+ NodeFlags m_Flags; // only dirty, transform dirty, and active apply
+
+ QT3DSVec2 m_Scale;
+ QT3DSVec2 m_Pivot;
+ QT3DSF32 m_Rotation; // Radians.
+ QT3DSVec2 m_Position;
+ ImageMappingModes::Enum m_MappingMode;
+ NVRenderTextureCoordOp::Enum m_HorizontalTilingMode;
+ NVRenderTextureCoordOp::Enum m_VerticalTilingMode;
+
+ // Setting any of the above variables means this object is dirty.
+ // Setting any of the vec2 properties means this object's transform is dirty
+
+ QT3DSMat44 m_TextureTransform;
+
+ SImage();
+ // Renders the sub presentation
+ // Or finds the image.
+ // and sets up the texture transform
+ bool ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager,
+ IRenderPluginManager &pluginManager, bool forIbl = false);
+
+ void CalculateTextureTransform();
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_ImagePath);
+ inRemapper.Remap(m_OffscreenRendererId);
+ // Null out objects that should be null when loading from file.
+ inRemapper.NullPtr(m_LastFrameOffscreenRenderer);
+ inRemapper.NullPtr(m_TextureData.m_Texture);
+ inRemapper.Remap(m_RenderPlugin);
+ inRemapper.Remap(m_Parent);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.cpp
new file mode 100644
index 00000000..b576af6b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderLayer.h"
+#include "UICRenderEffect.h"
+
+using namespace uic::render;
+
+SLayer::SLayer()
+ : SNode(GraphObjectTypes::Layer)
+ , m_Scene(NULL)
+ , m_FirstEffect(NULL)
+ , m_RenderPlugin(NULL)
+ , m_ProgressiveAAMode(AAModeValues::NoAA)
+ , m_MultisampleAAMode(AAModeValues::NoAA)
+ , m_Background(LayerBackground::Transparent)
+ , m_ClearColor(0)
+ , m_BlendType(LayerBlendTypes::Normal)
+ , m_HorizontalFieldValues(HorizontalFieldValues::LeftWidth)
+ , m_Left(0)
+ , m_LeftUnits(LayerUnitTypes::Percent)
+ , m_Width(100.0f)
+ , m_WidthUnits(LayerUnitTypes::Percent)
+ , m_Right(0)
+ , m_RightUnits(LayerUnitTypes::Percent)
+ , m_VerticalFieldValues(VerticalFieldValues::TopHeight)
+ , m_Top(0)
+ , m_TopUnits(LayerUnitTypes::Percent)
+ , m_Height(100.0f)
+ , m_HeightUnits(LayerUnitTypes::Percent)
+ , m_Bottom(0)
+ , m_BottomUnits(LayerUnitTypes::Percent)
+ , m_AoStrength(0)
+ , m_AoDistance(5.0f)
+ , m_AoSoftness(50.0f)
+ , m_AoBias(0)
+ , m_AoSamplerate(2)
+ , m_AoDither(false)
+ , m_ShadowStrength(0)
+ , m_ShadowDist(10)
+ , m_ShadowSoftness(100.0f)
+ , m_ShadowBias(0)
+ , m_LightProbe(NULL)
+ , m_ProbeBright(100.0f)
+ , m_FastIbl(false)
+ , m_ProbeHorizon(-1.0f)
+ , m_ProbeFov(180.0f)
+ , m_LightProbe2(NULL)
+ , m_Probe2Fade(1.0f)
+ , m_Probe2Window(1.0f)
+ , m_Probe2Pos(0.5f)
+ , m_TemporalAAEnabled(false)
+{
+ m_Flags.SetLayerRenderToTarget(true);
+ m_Flags.SetLayerEnableDepthTest(true);
+ m_Flags.SetLayerEnableDepthPrepass(true);
+}
+
+void SLayer::AddEffect(SEffect &inEffect)
+{
+ // Effects need to be rendered in reverse order as described in the file.
+ inEffect.m_NextEffect = m_FirstEffect;
+ m_FirstEffect = &inEffect;
+ inEffect.m_Layer = this;
+}
+
+SEffect *SLayer::GetLastEffect()
+{
+ if (m_FirstEffect) {
+ SEffect *theEffect = m_FirstEffect;
+ // Empty loop intentional
+ for (; theEffect->m_NextEffect; theEffect = theEffect->m_NextEffect) {
+ }
+ QT3DS_ASSERT(theEffect->m_NextEffect == NULL);
+ return theEffect;
+ }
+ return NULL;
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.h
new file mode 100644
index 00000000..36fc64b9
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLayer.h
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_LAYER_H
+#define UIC_RENDER_LAYER_H
+#include "UICRender.h"
+#include "UICRenderNode.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderer.h"
+
+namespace uic {
+namespace render {
+ class IUICRenderContext;
+ struct SPresentation;
+ struct SScene;
+ struct SEffect;
+
+ struct AAModeValues
+ {
+ enum Enum {
+ NoAA = 0,
+ SSAA = 1,
+ X2 = 2,
+ X4 = 4,
+ X8 = 8
+ };
+ };
+
+ struct HorizontalFieldValues
+ {
+ enum Enum {
+ LeftWidth = 0,
+ LeftRight,
+ WidthRight
+ };
+ };
+
+ struct VerticalFieldValues
+ {
+ enum Enum {
+ TopHeight = 0,
+ TopBottom,
+ HeightBottom
+ };
+ };
+
+ struct LayerUnitTypes
+ {
+ enum Enum {
+ Percent = 0,
+ Pixels
+ };
+ };
+
+ struct LayerBackground
+ {
+ enum Enum {
+ Transparent = 0,
+ Unspecified,
+ Color
+ };
+ };
+
+ struct LayerBlendTypes
+ {
+ enum Enum {
+ Normal = 0,
+ Screen,
+ Multiply,
+ Add,
+ Subtract,
+ Overlay,
+ ColorBurn,
+ ColorDodge
+ };
+ };
+
+ // A layer is a special node. It *always* presents its global transform
+ // to children as the identity. It also can optionally have a width or height
+ // different than the overlying context. You can think of layers as the transformation
+ // between a 3d scene graph and a 2D texture.
+ struct SLayer : public SNode
+ {
+ SScene *m_Scene;
+
+ // First effect in a list of effects.
+ SEffect *m_FirstEffect;
+
+ // If a layer has a valid texture path (one that resolves to either a
+ // an on-disk image or a offscreen renderer), then it does not render its
+ // own source path. Instead, it renders the offscreen renderer. Used in this manner,
+ // offscreen renderer's also have the option (if they support it) to render directly to the
+ // render target given a specific viewport (that is also scissored if necessary).
+ qt3ds::foundation::CRegisteredString m_TexturePath;
+
+ SRenderPlugin *m_RenderPlugin; // Overrides texture path if available.
+
+ AAModeValues::Enum m_ProgressiveAAMode;
+ AAModeValues::Enum m_MultisampleAAMode;
+ LayerBackground::Enum m_Background;
+ QT3DSVec3 m_ClearColor;
+
+ LayerBlendTypes::Enum m_BlendType;
+
+ HorizontalFieldValues::Enum m_HorizontalFieldValues;
+ QT3DSF32 m_Left;
+ LayerUnitTypes::Enum m_LeftUnits;
+ QT3DSF32 m_Width;
+ LayerUnitTypes::Enum m_WidthUnits;
+ QT3DSF32 m_Right;
+ LayerUnitTypes::Enum m_RightUnits;
+
+ VerticalFieldValues::Enum m_VerticalFieldValues;
+ QT3DSF32 m_Top;
+ LayerUnitTypes::Enum m_TopUnits;
+ QT3DSF32 m_Height;
+ LayerUnitTypes::Enum m_HeightUnits;
+ QT3DSF32 m_Bottom;
+ LayerUnitTypes::Enum m_BottomUnits;
+
+ // Ambient occlusion
+ QT3DSF32 m_AoStrength;
+ QT3DSF32 m_AoDistance;
+ QT3DSF32 m_AoSoftness;
+ QT3DSF32 m_AoBias;
+ QT3DSI32 m_AoSamplerate;
+ bool m_AoDither;
+
+ // Direct occlusion
+ QT3DSF32 m_ShadowStrength;
+ QT3DSF32 m_ShadowDist;
+ QT3DSF32 m_ShadowSoftness;
+ QT3DSF32 m_ShadowBias;
+
+ // IBL
+ SImage *m_LightProbe;
+ QT3DSF32 m_ProbeBright;
+ bool m_FastIbl;
+ QT3DSF32 m_ProbeHorizon;
+ QT3DSF32 m_ProbeFov;
+ SImage *m_LightProbe2;
+ QT3DSF32 m_Probe2Fade;
+ QT3DSF32 m_Probe2Window;
+ QT3DSF32 m_Probe2Pos;
+
+ bool m_TemporalAAEnabled;
+
+ SLayer();
+
+ void AddEffect(SEffect &inEffect);
+
+ SEffect *GetLastEffect();
+
+ LayerBlendTypes::Enum GetLayerBlend()
+ {
+ return m_BlendType;
+ }
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SNode::Remap(inRemapper);
+ inRemapper.Remap(m_Scene);
+ inRemapper.Remap(m_FirstEffect);
+ inRemapper.Remap(m_TexturePath);
+ inRemapper.Remap(m_RenderPlugin);
+ inRemapper.Remap(m_LightProbe);
+ inRemapper.Remap(m_LightProbe2);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.cpp
new file mode 100644
index 00000000..afbfdc79
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderLight.h"
+
+using namespace uic::render;
+
+SLight::SLight()
+ : SNode(GraphObjectTypes::Light)
+ , m_LightType(RenderLightTypes::Directional)
+ , m_Scope(NULL)
+ , m_DiffuseColor(1, 1, 1)
+ , m_SpecularColor(1, 1, 1)
+ , m_AmbientColor(0, 0, 0)
+ , m_Brightness(100)
+ , m_LinearFade(0)
+ , m_ExponentialFade(0)
+ , m_AreaWidth(0)
+ , m_AreaHeight(0)
+ , m_CastShadow(false)
+ , m_ShadowBias(0.0f)
+ , m_ShadowFactor(5.0f)
+ , m_ShadowMapRes(9)
+ , m_ShadowMapFar(5000.0f)
+ , m_ShadowFilter(35.0f)
+{
+ m_Flags.SetPointLight(0);
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.h
new file mode 100644
index 00000000..f46f0136
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLight.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_LIGHT_H
+#define UIC_RENDER_LIGHT_H
+#include "UICRenderNode.h"
+
+namespace uic {
+namespace render {
+
+ struct RenderLightTypes
+ {
+ enum Enum {
+ Unknown = 0,
+ Directional,
+ Point,
+ Area,
+ };
+ };
+
+ struct SImage;
+
+ struct SLight : public SNode
+ {
+ RenderLightTypes::Enum m_LightType; // Directional
+ SNode *m_Scope;
+ QT3DSVec3 m_DiffuseColor; // colors are 0-1 normalized
+ QT3DSVec3 m_SpecularColor; // colors are 0-1 normalized
+ QT3DSVec3 m_AmbientColor; // colors are 0-1 normalized
+
+ // The variables below are in the same range as Studio
+ // Only valid if node is a point light
+ QT3DSF32 m_Brightness; // 0-200
+ QT3DSF32 m_LinearFade; // 0-200
+ QT3DSF32 m_ExponentialFade; // 0-200
+
+ QT3DSF32 m_AreaWidth; // 0.01-inf
+ QT3DSF32 m_AreaHeight; // 0.01-inf
+
+ bool m_CastShadow; // true if this light produce shadows
+ QT3DSF32 m_ShadowBias; // depth shift to avoid self-shadowing artifacts
+ QT3DSF32 m_ShadowFactor; // Darkening factor for ESMs
+ QT3DSU32 m_ShadowMapRes; // Resolution of shadow map
+ QT3DSF32 m_ShadowMapFar; // Far clip plane for the shadow map
+ QT3DSF32 m_ShadowFilter; // Shadow map filter step size
+
+ // Defaults to directional light
+ SLight();
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SNode::Remap(inRemapper);
+ inRemapper.Remap(m_Scope);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.cpp
new file mode 100644
index 00000000..21ad0548
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderLightmaps.h"
+
+using namespace uic::render;
+
+SLightmaps::SLightmaps()
+ : SGraphObject(GraphObjectTypes::Lightmaps)
+ , m_LightmapIndirect(NULL)
+ , m_LightmapRadiosity(NULL)
+ , m_LightmapShadow(NULL)
+{
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.h
new file mode 100644
index 00000000..c7972bc5
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderLightmaps.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef UIC_RENDER_LIGHTMAPS_H
+#define UIC_RENDER_LIGHTMAPS_H
+
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "foundation/StringTable.h"
+#include "UICRenderer.h"
+#include "UICRenderMaterialDirty.h"
+
+namespace uic {
+namespace render {
+
+ struct MaterialLightmapsUsage
+ {
+ enum Enum {
+ Dynamic = 0,
+ Baked,
+ DynamicAndBaked,
+ };
+ };
+
+ struct SLightmaps : public SGraphObject
+ {
+ CMaterialDirty m_Dirty;
+
+ SImage *m_LightmapIndirect;
+ SImage *m_LightmapRadiosity;
+ SImage *m_LightmapShadow;
+
+ SLightmaps();
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_LightmapIndirect);
+ inRemapper.Remap(m_LightmapRadiosity);
+ inRemapper.Remap(m_LightmapShadow);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderMaterialDirty.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderMaterialDirty.h
new file mode 100644
index 00000000..7b8fc056
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderMaterialDirty.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_MATERIAL_DIRTY_H
+#define UIC_RENDER_MATERIAL_DIRTY_H
+
+namespace uic {
+namespace render {
+ class CMaterialDirty
+ {
+ private:
+ bool m_Dirty;
+ bool m_DirtyFlagWithInFrame;
+
+ public:
+ CMaterialDirty()
+ : m_Dirty(true)
+ , m_DirtyFlagWithInFrame(m_Dirty)
+ {
+ }
+
+ void SetDirty() { m_Dirty = m_DirtyFlagWithInFrame = true; }
+ bool IsDirty() const { return m_Dirty || m_DirtyFlagWithInFrame; }
+ void ClearDirty() { m_DirtyFlagWithInFrame = m_Dirty = false; }
+ void UpdateDirtyForFrame()
+ {
+ m_DirtyFlagWithInFrame = m_Dirty;
+ m_Dirty = false;
+ }
+ };
+}
+}
+
+#endif // UIC_RENDER_MATERIAL_DIRTY_H
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.cpp
new file mode 100644
index 00000000..770d2b4e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderModel.h"
+#include "UICRenderMaterialHelpers.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderMesh.h"
+
+using namespace uic::render;
+
+SModel::SModel()
+ : SNode(GraphObjectTypes::Model)
+ , m_FirstMaterial(NULL)
+ , m_SkeletonRoot(-1)
+ , m_TessellationMode(TessModeValues::NoTess)
+ , m_EdgeTess(1.0)
+ , m_InnerTess(1.0)
+ , m_WireframeMode(false)
+{
+}
+
+void SModel::AddMaterial(SGraphObject &inMaterial)
+{
+ if (m_FirstMaterial == NULL)
+ m_FirstMaterial = &inMaterial;
+ else {
+ SGraphObject *lastMaterial;
+ // empty loop intentional
+ for (lastMaterial = m_FirstMaterial; lastMaterial && GetNextMaterialSibling(lastMaterial);
+ lastMaterial = GetNextMaterialSibling(lastMaterial)) {
+ }
+ SetNextMaterialSibling(*lastMaterial, &inMaterial);
+ }
+ if (inMaterial.m_Type == GraphObjectTypes::DefaultMaterial)
+ static_cast<SDefaultMaterial &>(inMaterial).m_Parent = this;
+}
+
+NVBounds3 SModel::GetModelBounds(IBufferManager &inManager) const
+{
+ NVBounds3 retval;
+ retval.setEmpty();
+ SRenderMesh *theMesh = inManager.LoadMesh(m_MeshPath);
+ if (theMesh) {
+ for (QT3DSU32 idx = 0, end = theMesh->m_Subsets.size(); idx < end; ++idx)
+ retval.include(theMesh->m_Subsets[idx].m_Bounds);
+ }
+ return retval;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.h
new file mode 100644
index 00000000..f7e16054
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderModel.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_MODEL_H
+#define UIC_RENDER_MODEL_H
+
+#include "UICRenderNode.h"
+#include "foundation/StringTable.h"
+#include "UICRenderTessModeValues.h"
+
+namespace uic {
+namespace render {
+
+ struct SDefaultMaterial;
+ class IBufferManager;
+
+ struct SModel : public SNode
+ {
+ // Complete path to the file;
+ //*not* relative to the presentation directory
+ CRegisteredString m_MeshPath;
+ SGraphObject *m_FirstMaterial;
+ QT3DSI32 m_SkeletonRoot;
+ TessModeValues::Enum m_TessellationMode;
+ QT3DSF32 m_EdgeTess;
+ QT3DSF32 m_InnerTess;
+ bool m_WireframeMode;
+
+ SModel();
+
+ void AddMaterial(SGraphObject &inMaterial);
+
+ NVBounds3 GetModelBounds(IBufferManager &inManager) const;
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SNode::Remap(inRemapper);
+ inRemapper.RemapMaterial(m_FirstMaterial);
+ inRemapper.Remap(m_MeshPath);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.cpp
new file mode 100644
index 00000000..1d9f9af0
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.cpp
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderModel.h"
+#include "UICRenderNode.h"
+#include "UICRenderText.h"
+#include "UICRenderer.h"
+#include "UICRenderPathManager.h"
+#include "UICRenderPath.h"
+
+using namespace uic::render;
+
+SNode::SNode(GraphObjectTypes::Enum inGraphObjectType)
+ : SGraphObject(inGraphObjectType)
+ , m_Rotation(0, 0, 0) // Radians
+ , m_Position(0, 0, 0)
+ , m_Scale(1, 1, 1)
+ , m_Pivot(0, 0, 0)
+ , m_RotationOrder(EulOrdYXZs)
+ , m_LocalOpacity(1.0f)
+ , m_GlobalOpacity(1.0f)
+ , m_SkeletonId(-1)
+ , m_Parent(NULL)
+ , m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ , m_FirstChild(NULL)
+ , m_DFSIndex(0)
+{
+ m_Flags.SetDirty(true);
+ m_Flags.SetTransformDirty(true);
+ m_Flags.SetLeftHanded(true);
+ m_Flags.SetActive(true);
+ m_Flags.SetLocallyPickable(true);
+}
+
+SNode::SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator)
+ : SGraphObject(inCloningObject, inAllocator)
+ , m_Rotation(inCloningObject.m_Rotation) // Radians
+ , m_Position(inCloningObject.m_Position)
+ , m_Scale(inCloningObject.m_Scale)
+ , m_Pivot(inCloningObject.m_Pivot)
+ , m_RotationOrder(inCloningObject.m_RotationOrder)
+ , m_LocalOpacity(inCloningObject.m_LocalOpacity)
+ , m_LocalTransform(inCloningObject.m_LocalTransform)
+ , m_GlobalTransform(inCloningObject.m_GlobalTransform)
+ , m_GlobalOpacity(inCloningObject.m_GlobalOpacity)
+ , m_SkeletonId(inCloningObject.m_SkeletonId)
+ , m_Parent(NULL)
+ , m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ , m_FirstChild(NULL)
+ , m_DFSIndex(0)
+{
+ m_Flags.SetDirty(true);
+ m_Flags.SetTransformDirty(true);
+ m_Flags.SetLeftHanded(true);
+ m_Flags.SetActive(true);
+ m_Flags.SetLocallyPickable(true);
+
+ // for ( SNode* theChild = m_FirstChild; theChild != NULL; theChild = theChild->m_NextSibling )
+ //{
+ // SNode* theClonedChild = static_cast<SNode*>( CGraphObjectFactory::CloneGraphObject(
+ //*theChild, inAllocator ) );
+ // AddChild( *theClonedChild );
+ //}
+}
+
+// Sets this object dirty and walks down the graph setting all
+// children who are not dirty to be dirty.
+void SNode::MarkDirty(NodeTransformDirtyFlag::Enum inTransformDirty)
+{
+ if (m_Flags.IsTransformDirty() == false)
+ m_Flags.SetTransformDirty(inTransformDirty != NodeTransformDirtyFlag::TransformNotDirty);
+ if (m_Flags.IsDirty() == false) {
+ m_Flags.SetDirty(true);
+ for (SNode *child = m_FirstChild; child; child = child->m_NextSibling)
+ child->MarkDirty(inTransformDirty);
+ }
+}
+
+// Calculate global transform and opacity
+// Walks up the graph ensure all parents are not dirty so they have
+// valid global transforms.
+
+bool SNode::CalculateGlobalVariables()
+{
+ bool retval = m_Flags.IsDirty();
+ if (retval) {
+ m_Flags.SetDirty(false);
+ if (m_Flags.IsTransformDirty())
+ CalculateLocalTransform();
+ m_GlobalOpacity = m_LocalOpacity;
+ if (m_Parent) {
+ // Layer transforms do not flow down but affect the final layer's rendered
+ // representation.
+ retval = m_Parent->CalculateGlobalVariables() || retval;
+ if (m_Parent->m_Type != GraphObjectTypes::Layer) {
+ m_GlobalOpacity *= m_Parent->m_GlobalOpacity;
+ if (m_Flags.IsIgnoreParentTransform() == false)
+ m_GlobalTransform = m_Parent->m_GlobalTransform * m_LocalTransform;
+ else
+ m_GlobalTransform = m_LocalTransform;
+ } else
+ m_GlobalTransform = m_LocalTransform;
+
+ m_Flags.SetGlobalActive(m_Flags.IsActive() && m_Parent->m_Flags.IsGloballyActive());
+ m_Flags.SetGloballyPickable(m_Flags.IsLocallyPickable()
+ || m_Parent->m_Flags.IsGloballyPickable());
+ } else {
+ m_GlobalTransform = m_LocalTransform;
+ m_Flags.SetGlobalActive(m_Flags.IsActive());
+ m_Flags.SetGloballyPickable(m_Flags.IsLocallyPickable());
+ }
+ }
+ // We always clear dirty in a reasonable manner but if we aren't active
+ // there is no reason to tell the universe if we are dirty or not.
+ return retval && m_Flags.IsActive();
+}
+
+// Create some mapping of euler angles to their axis mapping.
+#define ITERATE_POSSIBLE_EULER_ANGLES \
+ HANDLE_EULER_ANGLE(EulOrdXYZs, X, Y, Z) \
+ HANDLE_EULER_ANGLE(EulOrdXYXs, X, Y, X) \
+ HANDLE_EULER_ANGLE(EulOrdXZYs, X, Z, Y) \
+ HANDLE_EULER_ANGLE(EulOrdXZXs, X, Z, X) \
+ HANDLE_EULER_ANGLE(EulOrdYZXs, Y, Z, X) \
+ HANDLE_EULER_ANGLE(EulOrdYZYs, Y, Z, Y) \
+ HANDLE_EULER_ANGLE(EulOrdYXZs, Y, X, Z) \
+ HANDLE_EULER_ANGLE(EulOrdYXYs, Y, X, Y) \
+ HANDLE_EULER_ANGLE(EulOrdZXYs, Z, X, Y) \
+ HANDLE_EULER_ANGLE(EulOrdZXZs, Z, X, Z) \
+ HANDLE_EULER_ANGLE(EulOrdZYXs, Z, Y, X) \
+ HANDLE_EULER_ANGLE(EulOrdZYZs, Z, Y, Z) \
+ HANDLE_EULER_ANGLE(EulOrdZYXr, Z, Y, X) \
+ HANDLE_EULER_ANGLE(EulOrdXYXr, X, Y, X) \
+ HANDLE_EULER_ANGLE(EulOrdYZXr, Y, Z, X) \
+ HANDLE_EULER_ANGLE(EulOrdXZXr, X, Z, X) \
+ HANDLE_EULER_ANGLE(EulOrdXZYr, X, Z, Y) \
+ HANDLE_EULER_ANGLE(EulOrdYZYr, Y, Z, Y) \
+ HANDLE_EULER_ANGLE(EulOrdZXYr, Z, X, Y) \
+ HANDLE_EULER_ANGLE(EulOrdYXYr, Y, X, Y) \
+ HANDLE_EULER_ANGLE(EulOrdYXZr, Y, X, Z) \
+ HANDLE_EULER_ANGLE(EulOrdZXZr, Z, X, Z) \
+ HANDLE_EULER_ANGLE(EulOrdXYZr, X, Y, Z) \
+ HANDLE_EULER_ANGLE(EulOrdZYZr, Z, Y, Z)
+
+inline EulerAngles RotationAndOrderToShoemake(QT3DSVec3 inRotation, QT3DSU32 inOrder)
+{
+ EulerAngles retval;
+ retval.w = (QT3DSF32)inOrder;
+ int X = 0;
+ int Y = 1;
+ int Z = 2;
+
+ switch (inOrder) {
+#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \
+ case order: \
+ retval.x = -inRotation[xIdx]; \
+ retval.y = -inRotation[yIdx]; \
+ retval.z = -inRotation[zIdx]; \
+ break;
+ ITERATE_POSSIBLE_EULER_ANGLES
+#undef HANDLE_EULER_ANGLE
+ default:
+ QT3DS_ASSERT(false);
+ retval.x = inRotation[X];
+ retval.y = inRotation[Y];
+ retval.z = inRotation[Z];
+ break;
+ }
+ return retval;
+}
+
+QT3DSVec3 SNode::GetRotationVectorFromRotationMatrix(const QT3DSMat33 &inMatrix) const
+{
+ QT3DSMat44 theConvertMatrix(inMatrix, QT3DSVec3(0, 0, 0));
+ if (m_Flags.IsLeftHanded())
+ SNode::FlipCoordinateSystem(theConvertMatrix);
+ uic::render::CEulerAngleConverter theConverter;
+ uic::render::HMatrix *theHMatrix =
+ reinterpret_cast<uic::render::HMatrix *>(theConvertMatrix.front());
+ uic::render::EulerAngles theAngles = theConverter.Eul_FromHMatrix(*theHMatrix, m_RotationOrder);
+ return GetRotationVectorFromEulerAngles(theAngles);
+}
+
+QT3DSVec3 SNode::GetRotationVectorFromEulerAngles(const EulerAngles &inAngles)
+{
+ QT3DSVec3 retval(0, 0, 0);
+ int X = 0;
+ int Y = 1;
+ int Z = 2;
+ switch ((int)inAngles.w) {
+#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \
+ case order: \
+ retval[xIdx] = -inAngles.x; \
+ retval[yIdx] = -inAngles.y; \
+ retval[zIdx] = -inAngles.z; \
+ break;
+ ITERATE_POSSIBLE_EULER_ANGLES
+#undef HANDLE_EULER_ANGLE
+ default:
+ QT3DS_ASSERT(false);
+ retval.x = inAngles.x;
+ retval.y = inAngles.y;
+ retval.z = inAngles.z;
+ break;
+ }
+
+ return retval;
+}
+
+void SNode::CalculateRotationMatrix(QT3DSMat44 &outMatrix) const
+{
+ StaticAssert<sizeof(QT3DSMat44) == sizeof(HMatrix)>::valid_expression();
+ CEulerAngleConverter theConverter;
+ EulerAngles theAngles(RotationAndOrderToShoemake(m_Rotation, (int)m_RotationOrder));
+ HMatrix *theMatrix = reinterpret_cast<HMatrix *>(&outMatrix);
+ theConverter.Eul_ToHMatrix(theAngles, *theMatrix);
+}
+
+void SNode::FlipCoordinateSystem(QT3DSMat44 &inMatrix)
+{
+ QT3DSF32 *writePtr(inMatrix.front());
+ // rotation conversion
+ writePtr[0 * 4 + 2] *= -1;
+ writePtr[1 * 4 + 2] *= -1;
+ writePtr[2 * 4 + 0] *= -1;
+ writePtr[2 * 4 + 1] *= -1;
+
+ // translation conversion
+ writePtr[3 * 4 + 2] *= -1;
+}
+
+void SNode::CalculateLocalTransform()
+{
+ m_Flags.SetTransformDirty(false);
+ bool leftHanded = m_Flags.IsLeftHanded();
+ m_LocalTransform = QT3DSMat44::createIdentity();
+ m_GlobalTransform = m_LocalTransform;
+ QT3DSF32 *writePtr = m_LocalTransform.front();
+ QT3DSVec3 theScaledPivot(-m_Pivot[0] * m_Scale[0], -m_Pivot[1] * m_Scale[1],
+ -m_Pivot[2] * m_Scale[2]);
+ m_LocalTransform.column0[0] = m_Scale[0];
+ m_LocalTransform.column1[1] = m_Scale[1];
+ m_LocalTransform.column2[2] = m_Scale[2];
+
+ writePtr[12] = theScaledPivot[0];
+ writePtr[13] = theScaledPivot[1];
+ if (leftHanded)
+ writePtr[14] = theScaledPivot[2];
+ else
+ writePtr[14] = -theScaledPivot[2];
+
+ QT3DSMat44 theRotationTransform;
+ CalculateRotationMatrix(theRotationTransform);
+ // may need column conversion in here somewhere.
+ m_LocalTransform = theRotationTransform * m_LocalTransform;
+
+ writePtr[12] += m_Position[0];
+ writePtr[13] += m_Position[1];
+ if (leftHanded)
+ writePtr[14] = writePtr[14] + m_Position[2];
+ else
+ writePtr[14] = writePtr[14] - m_Position[2];
+
+ if (leftHanded) {
+ FlipCoordinateSystem(m_LocalTransform);
+ }
+}
+
+void SNode::SetLocalTransformFromMatrix(QT3DSMat44 &inTransform)
+{
+ m_Flags.SetTransformDirty(true);
+
+ // clear pivot
+ m_Pivot[0] = m_Pivot[1] = m_Pivot[2] = 0.0f;
+
+ // set translation
+ m_Position[0] = inTransform[3][0];
+ m_Position[1] = inTransform[3][1];
+ m_Position[2] = inTransform[3][2];
+ // set scale
+ m_Scale[0] = inTransform.column0.magnitude();
+ m_Scale[1] = inTransform.column1.magnitude();
+ m_Scale[2] = inTransform.column2.magnitude();
+
+ // make sure there is no zero value
+ m_Scale[0] = (m_Scale[0] == 0.0) ? 1.0f : m_Scale[0];
+ m_Scale[1] = (m_Scale[1] == 0.0) ? 1.0f : m_Scale[1];
+ m_Scale[2] = (m_Scale[2] == 0.0) ? 1.0f : m_Scale[2];
+
+ // extract rotation by first dividing through scale value
+ float invScaleX = 1.0f / m_Scale[0];
+ float invScaleY = 1.0f / m_Scale[1];
+ float invScaleZ = 1.0f / m_Scale[2];
+
+ inTransform[0][0] *= invScaleX;
+ inTransform[0][1] *= invScaleX;
+ inTransform[0][2] *= invScaleX;
+ inTransform[1][0] *= invScaleY;
+ inTransform[1][1] *= invScaleY;
+ inTransform[1][2] *= invScaleY;
+ inTransform[2][0] *= invScaleZ;
+ inTransform[2][1] *= invScaleZ;
+ inTransform[2][2] *= invScaleZ;
+
+ QT3DSMat33 theRotationMatrix(inTransform.column0.getXYZ(), inTransform.column1.getXYZ(),
+ inTransform.column2.getXYZ());
+ m_Rotation = GetRotationVectorFromRotationMatrix(theRotationMatrix);
+}
+
+void SNode::AddChild(SNode &inChild)
+{
+ if (inChild.m_Parent)
+ inChild.m_Parent->RemoveChild(inChild);
+ inChild.m_Parent = this;
+ if (m_FirstChild == NULL)
+ m_FirstChild = &inChild;
+ else {
+ SNode *lastChild = GetLastChild();
+
+ if (lastChild) {
+ lastChild->m_NextSibling = &inChild;
+ inChild.m_PreviousSibling = lastChild;
+ } else {
+ QT3DS_ASSERT(false); // no last child but first chlid isn't null???
+ }
+ }
+}
+
+void SNode::RemoveChild(SNode &inChild)
+{
+ if (inChild.m_Parent != this) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ for (SNode *child = m_FirstChild; child; child = child->m_NextSibling) {
+ if (child == &inChild) {
+ if (child->m_PreviousSibling)
+ child->m_PreviousSibling->m_NextSibling = child->m_NextSibling;
+ if (child->m_NextSibling)
+ child->m_NextSibling->m_PreviousSibling = child->m_PreviousSibling;
+ child->m_Parent = NULL;
+ if (m_FirstChild == child)
+ m_FirstChild = child->m_NextSibling;
+ child->m_NextSibling = NULL;
+ child->m_PreviousSibling = NULL;
+ return;
+ }
+ }
+ QT3DS_ASSERT(false);
+}
+
+SNode *SNode::GetLastChild()
+{
+ SNode *lastChild = NULL;
+ // empty loop intentional
+ for (lastChild = m_FirstChild; lastChild && lastChild->m_NextSibling;
+ lastChild = lastChild->m_NextSibling) {
+ }
+ return lastChild;
+}
+
+void SNode::RemoveFromGraph()
+{
+ if (m_Parent)
+ m_Parent->RemoveChild(*this);
+
+ m_NextSibling = NULL;
+
+ // Orphan all of my children.
+ SNode *nextSibling = NULL;
+ for (SNode *child = m_FirstChild; child != NULL; child = nextSibling) {
+ child->m_PreviousSibling = NULL;
+ child->m_Parent = NULL;
+ nextSibling = child->m_NextSibling;
+ child->m_NextSibling = NULL;
+ }
+}
+
+NVBounds3 SNode::GetBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ bool inIncludeChildren, IUICRenderNodeFilter *inChildFilter) const
+{
+ NVBounds3 retval;
+ retval.setEmpty();
+ if (inIncludeChildren)
+ retval = GetChildBounds(inManager, inPathManager, inChildFilter);
+
+ if (m_Type == GraphObjectTypes::Model)
+ retval.include(static_cast<const SModel *>(this)->GetModelBounds(inManager));
+ else if (m_Type == GraphObjectTypes::Text)
+ retval.include(static_cast<const SText *>(this)->GetTextBounds());
+ else if (m_Type == GraphObjectTypes::Path)
+ retval.include(inPathManager.GetBounds(*static_cast<const SPath *>(this)));
+ return retval;
+}
+
+NVBounds3 SNode::GetChildBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ IUICRenderNodeFilter *inChildFilter) const
+{
+ NVBounds3 retval;
+ retval.setEmpty();
+ for (SNode *child = m_FirstChild; child != NULL; child = child->m_NextSibling) {
+ if (inChildFilter == NULL || inChildFilter->IncludeNode(*child)) {
+ NVBounds3 childBounds;
+ if (child->m_Flags.IsTransformDirty())
+ child->CalculateLocalTransform();
+ childBounds = child->GetBounds(inManager, inPathManager);
+ if (childBounds.isEmpty() == false) {
+ // Transform the bounds into our local space.
+ childBounds.transform(child->m_LocalTransform);
+ retval.include(childBounds);
+ }
+ }
+ }
+ return retval;
+}
+
+QT3DSVec3 SNode::GetGlobalPos() const
+{
+ return m_GlobalTransform.getPosition();
+}
+
+QT3DSVec3 SNode::GetDirection() const
+{
+ const QT3DSF32 *dataPtr(m_GlobalTransform.front());
+ QT3DSVec3 retval(dataPtr[8], dataPtr[9], dataPtr[10]);
+ retval.normalize();
+ return retval;
+}
+
+QT3DSVec3 SNode::GetScalingCorrectDirection() const
+{
+ QT3DSMat33 theDirMatrix(m_GlobalTransform.getUpper3x3().getInverse().getTranspose());
+ QT3DSVec3 theOriginalDir(0, 0, -1);
+ QT3DSVec3 retval = theDirMatrix.transform(theOriginalDir);
+ retval.normalize();
+ return retval;
+}
+
+QT3DSVec3 SNode::GetGlobalPivot() const
+{
+ QT3DSVec3 retval(m_Position);
+ retval.z *= -1;
+
+ if (m_Parent && m_Parent->m_Type != GraphObjectTypes::Layer)
+ return m_Parent->m_GlobalTransform.transform(retval);
+
+ return retval;
+}
+
+void SNode::CalculateMVPAndNormalMatrix(const QT3DSMat44 &inViewProjection, QT3DSMat44 &outMVP,
+ QT3DSMat33 &outNormalMatrix) const
+{
+ outMVP = inViewProjection * m_GlobalTransform;
+ CalculateNormalMatrix(outNormalMatrix);
+}
+
+void SNode::GetMatrixUpper3x3(QT3DSMat33 &outDest, const QT3DSMat44 &inSrc)
+{
+ outDest.column0 = QT3DSVec3(inSrc.column0[0], inSrc.column0[1], inSrc.column0[2]);
+ outDest.column1 = QT3DSVec3(inSrc.column1[0], inSrc.column1[1], inSrc.column1[2]);
+ outDest.column2 = QT3DSVec3(inSrc.column2[0], inSrc.column2[1], inSrc.column2[2]);
+}
+
+void SNode::CalculateNormalMatrix(QT3DSMat33 &outNormalMatrix) const
+{
+ GetMatrixUpper3x3(outNormalMatrix, m_GlobalTransform);
+ outNormalMatrix = outNormalMatrix.getInverse().getTranspose();
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.h
new file mode 100644
index 00000000..50661b95
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderNode.h
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_NODE_H
+#define UIC_RENDER_NODE_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "foundation/Qt3DSMat44.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSNoCopy.h"
+#include "UICRenderEulerAngles.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+namespace render {
+
+ struct SModel;
+ struct SLight;
+ struct SCamera;
+ struct SText;
+ struct SNode;
+ class IBufferManager;
+
+ class INodeQueue
+ {
+ protected:
+ virtual ~INodeQueue() {}
+ public:
+ virtual void Enqueue(SModel &inModel) = 0;
+ virtual void Enqueue(SLight &inLight) = 0;
+ virtual void Enqueue(SCamera &inCamera) = 0;
+ // virtual void Enqueue( SText& inText ) = 0;
+ };
+
+ struct NodeFlagValues
+ {
+ enum Enum {
+ Dirty = 1,
+ TransformDirty = 1 << 1,
+ Active = 1 << 2, ///< Is this exact object active
+ LeftHanded = 1 << 3,
+ Orthographic = 1 << 4,
+ PointLight = 1 << 5,
+ GlobalActive = 1 << 6, ///< set based in Active and if a parent is active.
+ TextDirty = 1 << 7,
+ LocallyPickable = 1 << 8,
+ GloballyPickable = 1 << 9,
+ LayerEnableDepthTest = 1 << 10,
+ LayerRenderToTarget = 1 << 11, ///< Does this layer render to the normal render target,
+ ///or is it offscreen-only
+ ForceLayerOffscreen = 1 << 12, ///< Forces a layer to always use the offscreen rendering
+ ///mechanism. This can be usefulf or caching purposes.
+ IgnoreParentTransform = 1 << 13,
+ LayerEnableDepthPrePass = 1 << 14, ///< True when we render a depth pass before
+ };
+ };
+
+ struct NodeTransformDirtyFlag
+ {
+ enum Enum {
+ TransformNotDirty,
+ TransformIsDirty,
+ };
+ };
+ struct NodeFlags : public NVFlags<NodeFlagValues::Enum, QT3DSU32>
+ {
+ NodeFlags()
+ : NVFlags<NodeFlagValues::Enum, QT3DSU32>((QT3DSU32)0)
+ {
+ }
+ void ClearOrSet(bool value, NodeFlagValues::Enum enumVal) { clearOrSet(value, enumVal); }
+ void SetActive(bool value) { ClearOrSet(value, NodeFlagValues::Active); }
+ bool IsActive() const { return this->operator&(NodeFlagValues::Active); }
+
+ void SetGlobalActive(bool value) { ClearOrSet(value, NodeFlagValues::GlobalActive); }
+ bool IsGloballyActive() const { return this->operator&(NodeFlagValues::GlobalActive); }
+
+ void SetTransformDirty(bool value) { ClearOrSet(value, NodeFlagValues::TransformDirty); }
+ bool IsTransformDirty() const { return this->operator&(NodeFlagValues::TransformDirty); }
+
+ void SetDirty(bool value) { ClearOrSet(value, NodeFlagValues::Dirty); }
+ bool IsDirty() const { return this->operator&(NodeFlagValues::Dirty); }
+
+ bool IsLeftHanded() const { return this->operator&(NodeFlagValues::LeftHanded); }
+ void SetLeftHanded(bool value) { ClearOrSet(value, NodeFlagValues::LeftHanded); }
+
+ bool IsOrthographic() const { return this->operator&(NodeFlagValues::Orthographic); }
+ void SetOrthographic(bool value) { ClearOrSet(value, NodeFlagValues::Orthographic); }
+
+ bool IsPointLight() const { return this->operator&(NodeFlagValues::PointLight); }
+ void SetPointLight(bool value) { ClearOrSet(value, NodeFlagValues::PointLight); }
+
+ bool IsTextDirty() const { return this->operator&(NodeFlagValues::TextDirty); }
+ void SetTextDirty(bool value) { ClearOrSet(value, NodeFlagValues::TextDirty); }
+
+ bool IsLocallyPickable() const { return this->operator&(NodeFlagValues::LocallyPickable); }
+ void SetLocallyPickable(bool value) { ClearOrSet(value, NodeFlagValues::LocallyPickable); }
+
+ bool IsGloballyPickable() const
+ {
+ return this->operator&(NodeFlagValues::GloballyPickable);
+ }
+ void SetGloballyPickable(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::GloballyPickable);
+ }
+
+ bool IsLayerRenderToTarget() const
+ {
+ return this->operator&(NodeFlagValues::LayerRenderToTarget);
+ }
+ void SetLayerRenderToTarget(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::LayerRenderToTarget);
+ }
+
+ bool IsLayerEnableDepthTest() const
+ {
+ return this->operator&(NodeFlagValues::LayerEnableDepthTest);
+ }
+ void SetLayerEnableDepthTest(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::LayerEnableDepthTest);
+ }
+
+ bool IsForceLayerOffscreen() const
+ {
+ return this->operator&(NodeFlagValues::ForceLayerOffscreen);
+ }
+ void SetForceLayerOffscreen(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::ForceLayerOffscreen);
+ }
+
+ bool IsIgnoreParentTransform() const
+ {
+ return this->operator&(NodeFlagValues::IgnoreParentTransform);
+ }
+ void SetIgnoreParentTransform(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::IgnoreParentTransform);
+ }
+
+ bool IsLayerEnableDepthPrepass() const
+ {
+ return this->operator&(NodeFlagValues::LayerEnableDepthPrePass);
+ }
+ void SetLayerEnableDepthPrepass(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::LayerEnableDepthPrePass);
+ }
+ };
+
+ struct SNode : public SGraphObject
+ {
+ // changing any one of these means you have to
+ // set this object dirty
+ QT3DSVec3 m_Rotation; // Radians
+ QT3DSVec3 m_Position;
+ QT3DSVec3 m_Scale;
+ QT3DSVec3 m_Pivot;
+ QT3DSU32 m_RotationOrder; // UICEulerOrder::EulOrd, defaults YXZs
+
+ // This only sets dirty, not transform dirty
+ // Opacity of 1 means opaque, opacity of zero means transparent.
+ QT3DSF32 m_LocalOpacity;
+
+ // results of clearing dirty.
+ NodeFlags m_Flags;
+ // These end up right handed
+ QT3DSMat44 m_LocalTransform;
+ QT3DSMat44 m_GlobalTransform;
+ QT3DSF32 m_GlobalOpacity;
+ QT3DSI32 m_SkeletonId;
+
+ // node graph members.
+ SNode *m_Parent;
+ SNode *m_NextSibling;
+ SNode *m_PreviousSibling;
+ SNode *m_FirstChild;
+ // Property maintained solely by the render system.
+ // Depth-first-search index assigned and maintained by render system.
+ QT3DSU32 m_DFSIndex;
+
+ SNode(GraphObjectTypes::Enum inType = GraphObjectTypes::Node);
+ SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator);
+ ~SNode() {}
+
+ // Sets this object dirty and walks down the graph setting all
+ // children who are not dirty to be dirty.
+ void MarkDirty(NodeTransformDirtyFlag::Enum inTransformDirty =
+ NodeTransformDirtyFlag::TransformNotDirty);
+
+ void AddChild(SNode &inChild);
+ void RemoveChild(SNode &inChild);
+ SNode *GetLastChild();
+
+ // Remove this node from the graph.
+ // It is no longer the the parent's child lists
+ // and all of its children no longer have a parent
+ // finally they are no longer siblings of each other.
+ void RemoveFromGraph();
+
+ // Calculate global transform and opacity
+ // Walks up the graph ensure all parents are not dirty so they have
+ // valid global transforms.
+ bool CalculateGlobalVariables();
+
+ // Given our rotation order and handedness, calculate the final rotation matrix
+ // Only the upper 3x3 of this matrix is filled in.
+ // If this object is left handed, then you need to call FlipCoordinateSystem
+ // to get a result identical to the result produced in CalculateLocalTransform
+ void CalculateRotationMatrix(QT3DSMat44 &outMatrix) const;
+
+ // Get a rotation vector that would produce the given 3x.3 matrix.
+ // Takes m_RotationOrder and m_Flags.IsLeftHandled into account.
+ // Returns a rotation vector in radians.
+ QT3DSVec3 GetRotationVectorFromRotationMatrix(const QT3DSMat33 &inMatrix) const;
+
+ static QT3DSVec3 GetRotationVectorFromEulerAngles(const EulerAngles &inAngles);
+
+ // Flip a matrix from left-handed to right-handed and vice versa
+ static void FlipCoordinateSystem(QT3DSMat44 &ioMatrix);
+
+ // Force the calculation of the local transform
+ void CalculateLocalTransform();
+
+ /**
+ * @brief setup local tranform from a matrix.
+ * This function decomposes a SRT matrix.
+ * This will fail if this matrix contains non-affine transformations
+ *
+ * @param inTransform[in] input transformation
+ *
+ * @return true backend type
+ */
+ void SetLocalTransformFromMatrix(QT3DSMat44 &inTransform);
+
+ // Get the bounds of us and our children in our local space.
+ NVBounds3 GetBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ bool inIncludeChildren = true,
+ IUICRenderNodeFilter *inChildFilter = NULL) const;
+ NVBounds3 GetChildBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ IUICRenderNodeFilter *inChildFilter = NULL) const;
+ // Assumes CalculateGlobalVariables has already been called.
+ QT3DSVec3 GetGlobalPos() const;
+ QT3DSVec3 GetGlobalPivot() const;
+ // Pulls the 3rd column out of the global transform.
+ QT3DSVec3 GetDirection() const;
+ // Multiplies (0,0,-1) by the inverse transpose of the upper 3x3 of the global transform.
+ // This is correct w/r/t to scaling and which the above getDirection is not.
+ QT3DSVec3 GetScalingCorrectDirection() const;
+
+ // outMVP and outNormalMatrix are returned ready to upload to openGL, meaning they are
+ // row-major.
+ void CalculateMVPAndNormalMatrix(const QT3DSMat44 &inViewProjection, QT3DSMat44 &outMVP,
+ QT3DSMat33 &outNormalMatrix) const;
+
+ // This should be in a utility file somewhere
+ static void GetMatrixUpper3x3(QT3DSMat33 &inDest, const QT3DSMat44 &inSrc);
+ void CalculateNormalMatrix(QT3DSMat33 &outNormalMatrix) const;
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_Parent);
+ inRemapper.Remap(m_FirstChild);
+ inRemapper.Remap(m_NextSibling);
+ inRemapper.Remap(m_PreviousSibling);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.cpp
new file mode 100644
index 00000000..7927a3ac
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderPath.h"
+#include "UICRenderPathSubPath.h"
+
+using namespace uic::render;
+
+void SPath::AddSubPath(SPathSubPath &inSegment)
+{
+ SPathSubPath *lastSegment = NULL;
+ inSegment.m_Path = this;
+ inSegment.m_NextSubPath = NULL;
+ if (m_FirstSubPath) {
+ // find last segment
+ for (lastSegment = m_FirstSubPath; lastSegment && lastSegment->m_NextSubPath;
+ lastSegment = lastSegment->m_NextSubPath)
+ ;
+ lastSegment->m_NextSubPath = &inSegment;
+ } else
+ m_FirstSubPath = &inSegment;
+}
+
+void SPath::ClearSubPaths()
+{
+ SPathSubPath *nextSegment = NULL;
+ for (SPathSubPath *theSegment = m_FirstSubPath; theSegment; theSegment = nextSegment) {
+ nextSegment = theSegment->m_NextSubPath;
+ theSegment->m_Path = NULL;
+ theSegment->m_NextSubPath = NULL;
+ }
+ m_FirstSubPath = NULL;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.h
new file mode 100644
index 00000000..5cf392f3
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPath.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PATH_H
+#define UIC_RENDER_PATH_H
+#include "UICRender.h"
+#include "UICRenderNode.h"
+
+namespace uic {
+namespace render {
+ struct PathCapping
+ {
+ enum Enum {
+ Noner = 0,
+ Taper = 1,
+ };
+ };
+
+ struct PathTypes
+ {
+ enum Enum {
+ Noner = 0,
+ Painted,
+ Geometry,
+ };
+ };
+
+ struct PathPaintStyles
+ {
+ enum Enum {
+ Noner = 0,
+ FilledAndStroked,
+ Filled,
+ Stroked,
+ };
+ };
+
+ struct SPath : public SNode
+ {
+ PathTypes::Enum m_PathType;
+ QT3DSF32 m_Width;
+ QT3DSF32 m_LinearError;
+ QT3DSF32 m_EdgeTessAmount;
+ QT3DSF32 m_InnerTessAmount;
+ PathCapping::Enum m_BeginCapping;
+ QT3DSF32 m_BeginCapOffset;
+ QT3DSF32 m_BeginCapOpacity;
+ QT3DSF32 m_BeginCapWidth;
+ PathCapping::Enum m_EndCapping;
+ QT3DSF32 m_EndCapOffset;
+ QT3DSF32 m_EndCapOpacity;
+ QT3DSF32 m_EndCapWidth;
+ SGraphObject *m_Material;
+ SGraphObject *m_SecondMaterial;
+ // Paths can either be immediate - children attached define path
+ // or they can link to a path buffer that defines the path.
+ SPathSubPath *m_FirstSubPath;
+ CRegisteredString m_PathBuffer;
+ PathPaintStyles::Enum m_PaintStyle;
+
+ bool m_WireframeMode;
+ // Loaded onto the card just as data.
+ SPath()
+ : SNode(GraphObjectTypes::Path)
+ , m_PathType(PathTypes::Geometry)
+ , m_Width(5.0f)
+ , m_LinearError(100.0f)
+ , m_EdgeTessAmount(8.0f)
+ , m_InnerTessAmount(1.0f)
+ , m_BeginCapping(PathCapping::Noner)
+ , m_BeginCapOffset(10.0f)
+ , m_BeginCapOpacity(.2f)
+ , m_BeginCapWidth(0.0f)
+ , m_EndCapping(PathCapping::Noner)
+ , m_EndCapOffset(10.0f)
+ , m_EndCapOpacity(.2f)
+ , m_EndCapWidth(0.0f)
+ , m_Material(NULL)
+ , m_SecondMaterial(NULL)
+ , m_FirstSubPath(NULL)
+ , m_PaintStyle(PathPaintStyles::Stroked)
+ , m_WireframeMode(false)
+ {
+ }
+
+ bool IsStroked() const
+ {
+ return m_PaintStyle == PathPaintStyles::Stroked
+ || m_PaintStyle == PathPaintStyles::FilledAndStroked;
+ }
+
+ bool IsFilled() const
+ {
+ return m_PaintStyle == PathPaintStyles::Filled
+ || m_PaintStyle == PathPaintStyles::FilledAndStroked;
+ }
+
+ void AddMaterial(SGraphObject *inMaterial)
+ {
+ if (m_Material == NULL)
+ m_Material = inMaterial;
+ else
+ m_SecondMaterial = inMaterial;
+ }
+
+ void ClearMaterials()
+ {
+ m_Material = NULL;
+ m_SecondMaterial = NULL;
+ }
+
+ void AddSubPath(SPathSubPath &inSubPath);
+ void ClearSubPaths();
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SNode::Remap(inRemapper);
+ inRemapper.Remap(m_PathBuffer);
+ inRemapper.RemapMaterial(m_Material);
+ inRemapper.RemapMaterial(m_SecondMaterial);
+ inRemapper.Remap(m_FirstSubPath);
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderPathSubPath.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPathSubPath.h
new file mode 100644
index 00000000..f8c4d3f0
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPathSubPath.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PATH_SEGMENT_H
+#define UIC_RENDER_PATH_SEGMENT_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+
+namespace uic {
+namespace render {
+ struct SPathSubPath : public SGraphObject
+ {
+ SPath *m_Path;
+ SPathSubPath *m_NextSubPath;
+ bool m_Closed;
+
+ SPathSubPath()
+ : SGraphObject(GraphObjectTypes::PathSubPath)
+ , m_Path(NULL)
+ , m_NextSubPath(NULL)
+ , m_Closed(false)
+ {
+ }
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_Path);
+ inRemapper.Remap(m_NextSubPath);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.cpp
new file mode 100644
index 00000000..b0590082
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderPresentation.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderContext.h"
+
+using namespace uic::render;
+
+void SPresentation::Render(IUICRenderContext &inContext)
+{
+ if (m_Scene) {
+ NVRenderRect theViewportSize(inContext.GetRenderContext().GetViewport());
+ m_Scene->Render(QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
+ inContext);
+ }
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.h
new file mode 100644
index 00000000..d56bf72a
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderPresentation.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PRESENTATION_H
+#define UIC_RENDER_PRESENTATION_H
+
+#include "foundation/StringTable.h"
+#include "UICRenderGraphObject.h"
+#include "UICRenderScene.h"
+#include "foundation/Qt3DSVec2.h"
+
+namespace uic {
+namespace render {
+
+ struct RenderRotationValues
+ {
+ enum Enum {
+ NoRotation = 0,
+ Clockwise90,
+ Clockwise180,
+ Clockwise270,
+ };
+ };
+
+ struct SPresentation : public SGraphObject
+ {
+ QT3DSVec2 m_PresentationDimensions;
+ RenderRotationValues::Enum m_PresentationRotation;
+ SScene *m_Scene;
+
+ CRegisteredString m_PresentationDirectory;
+
+ SPresentation()
+ : SGraphObject(GraphObjectTypes::Presentation)
+ , m_PresentationDimensions(800, 400)
+ , m_PresentationRotation(RenderRotationValues::NoRotation)
+ , m_Scene(NULL)
+ {
+ }
+
+ SPresentation(QT3DSF32 w, QT3DSF32 h, CRegisteredString presDir)
+ : SGraphObject(GraphObjectTypes::Presentation)
+ , m_PresentationDimensions(w, h)
+ , m_PresentationRotation(RenderRotationValues::NoRotation)
+ , m_Scene(NULL)
+ , m_PresentationDirectory(presDir)
+ {
+ }
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_Scene);
+ inRemapper.Remap(m_PresentationDirectory);
+ }
+
+ void Render(IUICRenderContext &inContext);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderReferencedMaterial.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderReferencedMaterial.h
new file mode 100644
index 00000000..a8063d34
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderReferencedMaterial.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_REFERENCED_MATERIAL_H
+#define UIC_RENDER_REFERENCED_MATERIAL_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+#include "UICRenderMaterialDirty.h"
+
+namespace uic {
+namespace render {
+
+ struct SReferencedMaterial : SGraphObject
+ {
+ CMaterialDirty m_Dirty;
+ SGraphObject *m_ReferencedMaterial;
+ SGraphObject *m_NextSibling;
+ SReferencedMaterial()
+ : SGraphObject(GraphObjectTypes::ReferencedMaterial)
+ , m_ReferencedMaterial(NULL)
+ , m_NextSibling(NULL)
+ {
+ }
+
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.RemapMaterial(m_ReferencedMaterial);
+ inRemapper.RemapMaterial(m_NextSibling);
+ }
+ };
+}
+}
+
+#endif // UIC_RENDER_REFERENCED_MATERIAL_H
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.cpp
new file mode 100644
index 00000000..292c5a45
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRender.h"
+#include "UICRenderScene.h"
+#include "UICRenderLayer.h"
+#include "UICRenderContext.h"
+#include "render/Qt3DSRenderContext.h"
+
+using namespace uic::render;
+
+SScene::SScene()
+ : SGraphObject(GraphObjectTypes::Scene)
+ , m_Presentation(NULL)
+ , m_FirstChild(NULL)
+ , m_ClearColor(0, 0, 0)
+ , m_UseClearColor(true)
+ , m_Dirty(true)
+{
+}
+
+void SScene::AddChild(SLayer &inLayer)
+{
+ if (m_FirstChild == NULL)
+ m_FirstChild = &inLayer;
+ else
+ GetLastChild()->m_NextSibling = &inLayer;
+ inLayer.m_Scene = this;
+}
+
+SLayer *SScene::GetLastChild()
+{
+ // empty loop intentional
+ SLayer *child;
+ for (child = m_FirstChild; child && child->m_NextSibling;
+ child = (SLayer *)child->m_NextSibling) {
+ }
+
+ return child;
+}
+
+bool SScene::PrepareForRender(const QT3DSVec2 &inViewportDimensions, IUICRenderContext &inContext)
+{
+ // We need to iterate through the layers in reverse order and ask them to render.
+ bool wasDirty = m_Dirty;
+ m_Dirty = false;
+ if (m_FirstChild)
+ wasDirty =
+ inContext.GetRenderer().PrepareLayerForRender(*m_FirstChild, inViewportDimensions, true)
+ || wasDirty;
+ return wasDirty;
+}
+
+void SScene::Render(const QT3DSVec2 &inViewportDimensions, IUICRenderContext &inContext,
+ RenderClearCommand inClearColorBuffer)
+{
+ if ((inClearColorBuffer == SScene::ClearIsOptional && m_UseClearColor)
+ || inClearColorBuffer == SScene::AlwaysClear) {
+ QT3DSF32 clearColorAlpha = inContext.IsInSubPresentation() ? 0.0f : 1.0f;
+ QT3DSVec4 clearColor(0.0f, 0.0f, 0.0f, clearColorAlpha);
+ if (m_UseClearColor) {
+ clearColor.x = m_ClearColor.x;
+ clearColor.y = m_ClearColor.y;
+ clearColor.z = m_ClearColor.z;
+ }
+ // Maybe clear and reset to previous clear color after we leave.
+ qt3ds::render::NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ inContext.GetRenderContext(), &NVRenderContext::GetClearColor,
+ &NVRenderContext::SetClearColor, clearColor);
+ inContext.GetRenderContext().Clear(qt3ds::render::NVRenderClearValues::Color);
+ }
+ if (m_FirstChild)
+ inContext.GetRenderer().RenderLayer(*m_FirstChild, inViewportDimensions, m_UseClearColor,
+ m_ClearColor, true);
+}
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.h
new file mode 100644
index 00000000..d8f5b32c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderScene.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SCENE_H
+#define UIC_RENDER_SCENE_H
+#include "UICRender.h"
+#include "foundation/Qt3DSVec3.h"
+#include "UICRenderGraphObject.h"
+
+namespace uic {
+namespace render {
+ struct SLayer;
+ struct SPresentation;
+
+ struct SScene : public SGraphObject
+ {
+ SPresentation *m_Presentation;
+ SLayer *m_FirstChild;
+ QT3DSVec3 m_ClearColor;
+ bool m_UseClearColor;
+ bool m_Dirty;
+
+ enum RenderClearCommand {
+ ClearIsOptional = 0,
+ DoNotClear = 1,
+ AlwaysClear = 2,
+ };
+
+ SScene();
+
+ void AddChild(SLayer &inLayer);
+ SLayer *GetLastChild();
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_Presentation);
+ inRemapper.Remap(m_FirstChild);
+ }
+ // returns true if any of the layers were dirty or if this object was dirty
+ bool PrepareForRender(const QT3DSVec2 &inViewportDimensions, IUICRenderContext &inContext);
+ void Render(const QT3DSVec2 &inViewportDimensions, IUICRenderContext &inContext,
+ RenderClearCommand command = ClearIsOptional);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderText.cpp b/src/Runtime/Source/UICRender/GraphObjects/UICRenderText.cpp
new file mode 100644
index 00000000..3b5acbb7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderText.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderText.h"
+
+using namespace uic::render;
+
+STextRenderInfo::STextRenderInfo()
+ : m_FontSize(24)
+ , m_HorizontalAlignment(TextHorizontalAlignment::Center)
+ , m_VerticalAlignment(TextVerticalAlignment::Middle)
+ , m_Leading(0)
+ , m_Tracking(0)
+ , m_ScaleX(0)
+ , m_ScaleY(0)
+ , m_EnableAcceleratedFont(false)
+{
+}
+
+STextRenderInfo::~STextRenderInfo()
+{
+}
+
+SText::SText()
+ : SNode(GraphObjectTypes::Text)
+ , m_TextColor(1, 1, 1)
+ , m_TextTexture(NULL)
+{
+ m_Bounds.setEmpty();
+}
+
+NVBounds3 SText::GetTextBounds() const
+{
+ NVBounds3 retval;
+ retval.setEmpty();
+ if (m_TextTexture != NULL) {
+ retval.include(m_Bounds);
+ }
+ return retval;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/GraphObjects/UICRenderText.h b/src/Runtime/Source/UICRender/GraphObjects/UICRenderText.h
new file mode 100644
index 00000000..7f2ab701
--- /dev/null
+++ b/src/Runtime/Source/UICRender/GraphObjects/UICRenderText.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TEXT_H
+#define UIC_RENDER_TEXT_H
+#include "UICRender.h"
+#include "UICRenderNode.h"
+#include "UICRenderTextTypes.h"
+
+namespace uic {
+namespace render {
+
+ struct SText : public SNode, public STextRenderInfo
+ {
+ // Change any of these properties and you can expect
+ // that the text will force an expensive re-layer and render.
+ // For these you need to set TextDirty.
+
+ // These properties can change every frame with no additional cost.
+ QT3DSVec3 m_TextColor;
+
+ // Setup and utilized by the rendering system
+ NVRenderTexture2D *m_TextTexture;
+ STextTextureDetails m_TextTextureDetails;
+ // used for nv path rendering
+ NVRenderPathFontItem *m_PathFontItem;
+ NVRenderPathFontSpecification *m_PathFontDetails;
+
+ NVBounds3 m_Bounds;
+
+ SText();
+
+ NVBounds3 GetTextBounds() const;
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SNode::Remap(inRemapper);
+ inRemapper.Remap(m_Text);
+ inRemapper.Remap(m_Font);
+ inRemapper.NullPtr(m_TextTexture);
+ inRemapper.NullPtr(m_PathFontItem);
+ inRemapper.NullPtr(m_PathFontDetails);
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/ANDROID/DynamicLibLoader.h b/src/Runtime/Source/UICRender/Include/ANDROID/DynamicLibLoader.h
new file mode 100644
index 00000000..ad47c506
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/ANDROID/DynamicLibLoader.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "LINUX/DynamicLibLoader.h" \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/LINUX/DynamicLibLoader.h b/src/Runtime/Source/UICRender/Include/LINUX/DynamicLibLoader.h
new file mode 100644
index 00000000..a260c7da
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/LINUX/DynamicLibLoader.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_LINUX_DYNAMIC_LIB_LOADER_H
+#define UIC_LINUX_DYNAMIC_LIB_LOADER_H
+#include <dlfcn.h>
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+namespace uic {
+namespace render {
+ using namespace qt3ds;
+ using namespace qt3ds::render;
+
+ class CLoadedDynamicLibrary
+ {
+ void *m_DLLHandle;
+ CLoadedDynamicLibrary(void *hdl)
+ : m_DLLHandle(hdl)
+ {
+ }
+ CLoadedDynamicLibrary(const CLoadedDynamicLibrary &);
+ CLoadedDynamicLibrary &operator=(const CLoadedDynamicLibrary &);
+
+ public:
+ ~CLoadedDynamicLibrary()
+ {
+ if (m_DLLHandle)
+ {
+#ifndef _INTEGRITYPLATFORM
+ ::dlclose(m_DLLHandle);
+#endif
+ }
+ m_DLLHandle = 0;
+ }
+ void *FindFunction(const char *name)
+ {
+#ifndef _INTEGRITYPLATFORM
+ return ::dlsym(m_DLLHandle, name);
+#else
+ qWarning() << "CLoadedDynamicLibrary::FindFunction returns NULL!";
+ return NULL;
+#endif
+ }
+ static CLoadedDynamicLibrary *Create(const char *inFullDllPath, NVFoundationBase &fnd)
+ {
+#ifndef _INTEGRITYPLATFORM
+ void *hdl = ::dlopen(inFullDllPath, RTLD_NOW);
+ if (hdl == 0) {
+ const char *error = ::dlerror();
+ qCCritical(INVALID_OPERATION, "Failed to load dynamic library %s: %s",
+ inFullDllPath, error);
+ return NULL;
+ }
+ return QT3DS_NEW(fnd.getAllocator(), CLoadedDynamicLibrary)(hdl);
+#else
+ qWarning() << "CLoadedDynamicLibrary::Create returns NULL!";
+ return NULL;
+#endif
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/OSX/DynamicLibLoader.h b/src/Runtime/Source/UICRender/Include/OSX/DynamicLibLoader.h
new file mode 100644
index 00000000..df486c14
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/OSX/DynamicLibLoader.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "LINUX/DynamicLibLoader.h"
diff --git a/src/Runtime/Source/UICRender/Include/QNX/DynamicLibLoader.h b/src/Runtime/Source/UICRender/Include/QNX/DynamicLibLoader.h
new file mode 100644
index 00000000..df486c14
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/QNX/DynamicLibLoader.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "LINUX/DynamicLibLoader.h"
diff --git a/src/Runtime/Source/UICRender/Include/UICOffscreenRenderKey.h b/src/Runtime/Source/UICRender/Include/UICOffscreenRenderKey.h
new file mode 100644
index 00000000..abf2e96b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICOffscreenRenderKey.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_OFFSCREEN_RENDER_KEY_H
+#define UIC_OFFSCREEN_RENDER_KEY_H
+#include "UICRender.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<CRegisteredString>
+ {
+ void destruct(CRegisteredString &) {}
+ };
+}
+}
+
+namespace uic {
+namespace render {
+ struct OffscreenRendererKeyTypes
+ {
+ enum Enum {
+ NoOffscreenRendererKey = 0,
+ RegisteredString,
+ VoidPtr,
+ };
+ };
+
+ template <typename TDType>
+ struct SOffscreenRendererKeyTypeMap
+ {
+ };
+ template <>
+ struct SOffscreenRendererKeyTypeMap<CRegisteredString>
+ {
+ enum { KeyType = OffscreenRendererKeyTypes::RegisteredString };
+ };
+ template <>
+ struct SOffscreenRendererKeyTypeMap<void *>
+ {
+ enum { KeyType = OffscreenRendererKeyTypes::VoidPtr };
+ };
+
+ struct SOffscreenRendererKeyUnionTraits
+ {
+ typedef OffscreenRendererKeyTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(CRegisteredString),
+ };
+
+ static TIdType getNoDataId() { return OffscreenRendererKeyTypes::NoOffscreenRendererKey; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return (TIdType)SOffscreenRendererKeyTypeMap<TDataType>::KeyType;
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case OffscreenRendererKeyTypes::RegisteredString:
+ return inVisitor(*NVUnionCast<CRegisteredString *>(inData));
+ case OffscreenRendererKeyTypes::VoidPtr:
+ return inVisitor(*NVUnionCast<void **>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case OffscreenRendererKeyTypes::NoOffscreenRendererKey:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case OffscreenRendererKeyTypes::RegisteredString:
+ return inVisitor(*NVUnionCast<const CRegisteredString *>(inData));
+ case OffscreenRendererKeyTypes::VoidPtr:
+ return inVisitor(*NVUnionCast<const void **>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case OffscreenRendererKeyTypes::NoOffscreenRendererKey:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SOffscreenRendererKeyUnionTraits,
+ SOffscreenRendererKeyUnionTraits::
+ TBufferSize>,
+ SOffscreenRendererKeyUnionTraits::TBufferSize>
+ TOffscreenRendererKeyUnionType;
+
+ struct SOffscreenRendererKey : public TOffscreenRendererKeyUnionType
+ {
+ typedef TOffscreenRendererKeyUnionType TBase;
+ SOffscreenRendererKey() {}
+ SOffscreenRendererKey(const CRegisteredString &str)
+ : TBase(str)
+ {
+ }
+ SOffscreenRendererKey(void *key)
+ : TBase(key)
+ {
+ }
+ SOffscreenRendererKey(const SOffscreenRendererKey &other)
+ : TBase(static_cast<const TBase &>(other))
+ {
+ }
+ SOffscreenRendererKey &operator=(const SOffscreenRendererKey &other)
+ {
+ TBase::operator=(other);
+ return *this;
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICOffscreenRenderManager.h b/src/Runtime/Source/UICRender/Include/UICOffscreenRenderManager.h
new file mode 100644
index 00000000..99985823
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICOffscreenRenderManager.h
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_OFFSCREEN_RENDER_MANAGER_H
+#define UIC_OFFSCREEN_RENDER_MANAGER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSOption.h"
+#include "UICRenderScene.h"
+#include "UICRenderLayer.h"
+
+namespace uic {
+namespace render {
+ class IResourceManager;
+ struct SUICRenderPickResult;
+ class IGraphObjectPickQuery;
+ struct OffscreenRendererDepthValues
+ {
+ enum Enum {
+ NoDepthBuffer = 0,
+ Depth16, // 16 bit depth buffer
+ Depth24, // 24 bit depth buffer
+ Depth32, // 32 bit depth buffer
+ Depth24Stencil8 // 24 bit depth buffer 8 bit stencil buffer
+ };
+ };
+
+ struct SOffscreenRendererEnvironment
+ {
+ QT3DSU32 m_Width;
+ QT3DSU32 m_Height;
+ NVRenderTextureFormats::Enum m_Format;
+ OffscreenRendererDepthValues::Enum m_Depth;
+ bool m_Stencil;
+ AAModeValues::Enum m_MSAAMode;
+
+ SOffscreenRendererEnvironment()
+ : m_Width(0)
+ , m_Height(0)
+ , m_Format(NVRenderTextureFormats::Unknown)
+ , m_Depth(OffscreenRendererDepthValues::NoDepthBuffer)
+ , m_Stencil(false)
+ , m_MSAAMode(AAModeValues::NoAA)
+ {
+ }
+
+ SOffscreenRendererEnvironment(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inFormat)
+ : m_Width(inWidth)
+ , m_Height(inHeight)
+ , m_Format(inFormat)
+ , m_Depth(OffscreenRendererDepthValues::Depth16)
+ , m_Stencil(false)
+ , m_MSAAMode(AAModeValues::NoAA)
+ {
+ }
+
+ SOffscreenRendererEnvironment(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inFormat,
+ OffscreenRendererDepthValues::Enum inDepth, bool inStencil,
+ AAModeValues::Enum inAAMode)
+ : m_Width(inWidth)
+ , m_Height(inHeight)
+ , m_Format(inFormat)
+ , m_Depth(inDepth)
+ , m_Stencil(inStencil)
+ , m_MSAAMode(inAAMode)
+ {
+ }
+
+ SOffscreenRendererEnvironment(const SOffscreenRendererEnvironment &inOther)
+ : m_Width(inOther.m_Width)
+ , m_Height(inOther.m_Height)
+ , m_Format(inOther.m_Format)
+ , m_Depth(inOther.m_Depth)
+ , m_Stencil(inOther.m_Stencil)
+ , m_MSAAMode(inOther.m_MSAAMode)
+ {
+ }
+ };
+
+ struct SOffscreenRenderFlags
+ {
+ bool m_HasTransparency;
+ bool m_HasChangedSinceLastFrame;
+ SOffscreenRenderFlags()
+ : m_HasTransparency(false)
+ , m_HasChangedSinceLastFrame(false)
+ {
+ }
+
+ SOffscreenRenderFlags(bool transparency, bool hasChanged)
+ : m_HasTransparency(transparency)
+ , m_HasChangedSinceLastFrame(hasChanged)
+ {
+ }
+ };
+
+ class IOffscreenRenderer : public NVRefCounted
+ {
+ protected:
+ virtual ~IOffscreenRenderer() {}
+ public:
+ // Arbitrary const char* returned to indicate the type of this renderer
+ // Can be overloaded to form the basis of an RTTI type system.
+ // Not currently used by the rendering system.
+ virtual CRegisteredString GetOffscreenRendererType() = 0;
+ virtual SOffscreenRendererEnvironment
+ GetDesiredEnvironment(QT3DSVec2 inPresentationScaleFactor) = 0;
+ // Returns true of this object needs to be rendered, false if this object is not dirty
+ virtual SOffscreenRenderFlags
+ NeedsRender(const SOffscreenRendererEnvironment &inEnvironment,
+ QT3DSVec2 inPresentationScaleFactor) = 0;
+ // Returns true if the rendered result image has transparency, or false
+ // if it should be treated as a completely opaque image.
+ // It is the IOffscreenRenderer's job to clear any buffers (color, depth, stencil) that it
+ // needs to. It should not assume that it's buffers are clear;
+ // Sometimes we scale the width and height of the main presentation in order to fit a
+ // window.
+ // If we do so, the scale factor tells the subpresentation renderer how much the system has
+ // scaled.
+ virtual void Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 inPresentationScaleFactor,
+ SScene::RenderClearCommand inColorBufferNeedsClear) = 0;
+
+ // Implementors should implement one of the two interfaces below.
+
+ // If this renderer supports picking that can return graph objects
+ // then return an interface here.
+ virtual IGraphObjectPickQuery *GetGraphObjectPickQuery() = 0;
+
+ // If you *don't* support the GraphObjectPickIterator interface, then you should implement
+ // this interface
+ // The system will just ask you to pick.
+ // If you return true, then we will assume that you swallowed the pick and will continue no
+ // further.
+ // else we will assume you did not and will continue the picking algorithm.
+ virtual bool Pick(const QT3DSVec2 &inMouseCoords, const QT3DSVec2 &inViewportDimensions) = 0;
+ };
+
+ struct SOffscreenRenderResult
+ {
+ NVScopedRefCounted<IOffscreenRenderer> m_Renderer;
+ NVRenderTexture2D *m_Texture;
+ bool m_HasTransparency;
+ bool m_HasChangedSinceLastFrame;
+
+ SOffscreenRenderResult(IOffscreenRenderer &inRenderer, NVRenderTexture2D &inTexture,
+ bool inTrans, bool inDirty)
+ : m_Renderer(&inRenderer)
+ , m_Texture(&inTexture)
+ , m_HasTransparency(inTrans)
+ , m_HasChangedSinceLastFrame(inDirty)
+ {
+ }
+ SOffscreenRenderResult()
+ : m_Renderer(NULL)
+ , m_Texture(NULL)
+ , m_HasTransparency(false)
+ , m_HasChangedSinceLastFrame(false)
+ {
+ }
+ };
+
+ struct SOffscreenRendererKey;
+
+ /**
+ * The offscreen render manager attempts to satisfy requests for a given image under a given
+ *key.
+ * Renderers are throttled such that they render at most once per frame and potentially less
+ *than
+ * that if they don't require a new render.
+ */
+ class IOffscreenRenderManager : public NVRefCounted
+ {
+ protected:
+ virtual ~IOffscreenRenderManager() {}
+ public:
+ // returns true if the renderer has not been registered.
+ // No return value means there was an error registering this id.
+ virtual Option<bool> MaybeRegisterOffscreenRenderer(const SOffscreenRendererKey &inKey,
+ IOffscreenRenderer &inRenderer) = 0;
+ virtual void RegisterOffscreenRenderer(const SOffscreenRendererKey &inKey,
+ IOffscreenRenderer &inRenderer) = 0;
+ virtual bool HasOffscreenRenderer(const SOffscreenRendererKey &inKey) = 0;
+ virtual IOffscreenRenderer *GetOffscreenRenderer(const SOffscreenRendererKey &inKey) = 0;
+ virtual void ReleaseOffscreenRenderer(const SOffscreenRendererKey &inKey) = 0;
+
+ // This doesn't trigger rendering right away. A node is added to the render graph that
+ // points to this item.
+ // Thus rendering is deffered until the graph is run but we promise to render to this
+ // resource.
+ virtual SOffscreenRenderResult GetRenderedItem(const SOffscreenRendererKey &inKey) = 0;
+ // Called by the UICRenderContext, clients don't need to call this.
+ virtual void BeginFrame() = 0;
+ virtual void EndFrame() = 0;
+
+ static IOffscreenRenderManager &
+ CreateOffscreenRenderManager(NVAllocatorCallback &inCallback, IStringTable &inStringTable,
+ IResourceManager &inManager, IUICRenderContext &inContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICOldNBustedRenderPlugin.h b/src/Runtime/Source/UICRender/Include/UICOldNBustedRenderPlugin.h
new file mode 100644
index 00000000..e9ff52cc
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICOldNBustedRenderPlugin.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_OLD_N_BUSTED_RENDER_PLUGIN_H
+#define UIC_OLD_N_BUSTED_RENDER_PLUGIN_H
+
+#include "UICOffscreenRenderManager.h"
+#include "UICRenderContext.h"
+#include "foundation/Qt3DSVec4.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "UICPluginDLL.h"
+
+namespace uic {
+namespace render {
+
+ class COldNBustedPluginRenderer;
+
+ class COldNBustedPluginRenderer : public IOffscreenRenderer
+ {
+ public:
+ IUICRenderContext &m_RenderContext;
+ long m_DLLHandle;
+ volatile QT3DSI32 mRefCount;
+ SOffscreenRendererEnvironment m_LastRenderedEnvironment;
+ CRegisteredString m_OffscreenRendererType;
+
+ PROC_GetDesiredTextureSize m_GetTextureSizeProc;
+ PROC_Render m_RenderProc;
+
+ COldNBustedPluginRenderer(IUICRenderContext &inRenderContext, long inDLLHandle);
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
+
+ SOffscreenRendererEnvironment GetDesiredEnvironment(QT3DSVec2 inPresScale) override;
+ virtual SOffscreenRenderFlags
+ NeedsRender(const SOffscreenRendererEnvironment &inEnvironment, QT3DSVec2 inPresScale) override;
+ void Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext & /*inRenderContext*/
+ ,
+ QT3DSVec2 inPresScale, SScene::RenderClearCommand inClearBuffer) override;
+ IGraphObjectPickQuery *GetGraphObjectPickQuery() override { return NULL; }
+ bool Pick(const QT3DSVec2 & /*inMouseCoords*/, const QT3DSVec2 & /*inViewportDimensions*/) override
+ {
+ return false;
+ }
+ // Used for RTTI purposes so we can safely static-cast an offscreen renderer to a
+ // CPluginRenderer
+ static const char *GetRendererName() { return "Plugin"; }
+ CRegisteredString GetOffscreenRendererType() override { return m_OffscreenRendererType; }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRender.h b/src/Runtime/Source/UICRender/Include/UICRender.h
new file mode 100644
index 00000000..78788f91
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRender.h
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_H
+#define UIC_RENDER_H
+
+namespace qt3ds {
+class NVAllocatorCallback;
+class NVFoundationBase;
+namespace foundation {
+ class CRegisteredString;
+ class IStringTable;
+ class CStrTableOrDataRef;
+ struct SStrRemapMap;
+ struct SWriteBuffer;
+ struct SDataReader;
+ struct SPtrOffsetMap;
+ class IPerfTimer;
+}
+namespace intrinsics {
+}
+namespace render {
+ class NVRenderTexture2D;
+ class NVRenderTexture2DArray;
+ class NVRenderTextureCube;
+ class NVRenderImage2D;
+ class NVRenderFrameBuffer;
+ class NVRenderRenderBuffer;
+ class NVRenderVertexBuffer;
+ class NVRenderIndexBuffer;
+ class NVRenderDrawIndirectBuffer;
+ class NVRenderInputAssembler;
+ class NVRenderAttribLayout;
+ class NVRenderDepthStencilState;
+ class NVRenderContext;
+ class NVRenderConstantBuffer;
+ class NVRenderShaderProgram;
+ class NVRenderShaderConstantBase;
+ struct NVRenderDrawMode;
+ struct NVRenderWinding;
+ struct NVRenderSrcBlendFunc;
+ struct NVRenderBlendEquation;
+ struct NVRenderState;
+ struct NVRenderTextureCoordOp;
+ struct NVRenderTextureMagnifyingOp;
+ struct NVRenderDstBlendFunc;
+ struct NVRenderContextValues;
+ struct NVRenderClearValues;
+ struct NVRenderRect;
+ struct NVRenderRectF;
+ struct NVRenderRenderBufferFormats;
+ struct NVRenderTextureFormats;
+ struct NVRenderTextureSwizzleMode;
+ struct NVRenderFrameBufferAttachments;
+ struct NVRenderRect;
+ struct NVRenderTextureCubeFaces;
+ struct STextureDetails;
+ struct NVRenderShaderDataTypes;
+ class NVRenderTextureOrRenderBuffer;
+ struct NVRenderTextureMinifyingOp;
+ struct NVReadFaces;
+ struct NVRenderVertexBufferEntry;
+ struct NVRenderPtrPtrMap;
+ class NVRenderComputeShader;
+ class NVRenderAttribLayout;
+ struct NVRenderBufferAccessTypeValues;
+ struct NVRenderImageAccessType;
+ struct NVRenderBufferBindValues;
+ struct DrawArraysIndirectCommand;
+ struct NVRenderShaderTypeValue;
+ class NVRenderPathRender;
+ class NVRenderPathSpecification;
+ class NVRenderPathFontSpecification;
+ class NVRenderPathFontItem;
+ struct NVRenderTextureTypeValue;
+ class NVRenderProgramPipeline;
+}
+class NVPlane;
+}
+
+namespace eastl {
+}
+
+namespace uic {
+
+namespace render {
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ using namespace qt3ds::intrinsics;
+ using qt3ds::render::NVRenderTexture2D;
+ using qt3ds::render::NVRenderTexture2DArray;
+ using qt3ds::render::NVRenderTextureCube;
+ using qt3ds::render::NVRenderImage2D;
+ using qt3ds::render::NVRenderFrameBuffer;
+ using qt3ds::render::NVRenderRenderBuffer;
+ using qt3ds::render::NVRenderVertexBuffer;
+ using qt3ds::render::NVRenderIndexBuffer;
+ using qt3ds::render::NVRenderDrawIndirectBuffer;
+ using qt3ds::render::NVRenderInputAssembler;
+ using qt3ds::render::NVRenderAttribLayout;
+ using qt3ds::render::NVRenderDepthStencilState;
+ using qt3ds::render::NVRenderContext;
+ using qt3ds::render::NVRenderConstantBuffer;
+ using qt3ds::render::NVRenderShaderProgram;
+ using qt3ds::render::NVRenderShaderConstantBase;
+ using qt3ds::render::NVRenderDrawMode;
+ using qt3ds::render::NVRenderWinding;
+ using qt3ds::foundation::CRegisteredString;
+ using qt3ds::foundation::IStringTable;
+ using qt3ds::render::NVRenderSrcBlendFunc;
+ using qt3ds::render::NVRenderBlendEquation;
+ using qt3ds::render::NVRenderState;
+ using qt3ds::foundation::IStringTable;
+ using qt3ds::foundation::CRegisteredString;
+ using qt3ds::render::NVRenderTextureCoordOp;
+ using qt3ds::render::NVRenderDstBlendFunc;
+ using qt3ds::render::NVRenderRect;
+ using qt3ds::render::NVRenderRectF;
+ using qt3ds::render::NVRenderRenderBufferFormats;
+ using qt3ds::render::NVRenderTextureFormats;
+ using qt3ds::render::NVRenderTextureSwizzleMode;
+ using qt3ds::render::NVRenderFrameBufferAttachments;
+ using qt3ds::render::NVRenderRect;
+ using qt3ds::render::NVRenderContextValues;
+ using qt3ds::render::NVRenderClearValues;
+ using qt3ds::render::STextureDetails;
+ using qt3ds::render::NVRenderShaderDataTypes;
+ using qt3ds::render::NVRenderTextureMagnifyingOp;
+ using qt3ds::render::NVRenderTextureOrRenderBuffer;
+ using qt3ds::render::NVRenderTextureMinifyingOp;
+ using qt3ds::render::NVReadFaces;
+ using qt3ds::render::NVRenderTextureCubeFaces;
+ using qt3ds::foundation::SStrRemapMap;
+ using qt3ds::foundation::SWriteBuffer;
+ using qt3ds::foundation::SDataReader;
+ using qt3ds::render::NVRenderPtrPtrMap;
+ using qt3ds::foundation::CStrTableOrDataRef;
+ using qt3ds::foundation::SPtrOffsetMap;
+ using qt3ds::foundation::IPerfTimer;
+ using qt3ds::render::NVRenderVertexBufferEntry;
+ using qt3ds::render::NVRenderComputeShader;
+ using qt3ds::render::NVRenderAttribLayout;
+ using qt3ds::render::NVRenderBufferAccessTypeValues;
+ using qt3ds::render::NVRenderImageAccessType;
+ using qt3ds::render::NVRenderBufferBindValues;
+ using qt3ds::render::DrawArraysIndirectCommand;
+ using qt3ds::render::NVRenderShaderTypeValue;
+ using qt3ds::render::NVRenderPathRender;
+ using qt3ds::render::NVRenderPathSpecification;
+ using qt3ds::render::NVRenderPathFontSpecification;
+ using qt3ds::render::NVRenderPathFontItem;
+ using qt3ds::render::NVRenderTextureTypeValue;
+ using qt3ds::render::NVRenderProgramPipeline;
+
+ class IUICRenderContextCore;
+ class IUICRenderContext;
+ class IUICRenderer;
+ class IBufferManager;
+ struct SRenderMesh;
+ class IRenderableObject;
+ class IUICRenderer;
+ class IBufferManager;
+ class IResourceManager;
+ class IOffscreenRenderManager;
+ struct SNode;
+ struct SGraphObject;
+ class ITextRenderer;
+ class ITextRendererCore;
+ class IInputStreamFactory;
+ class IRefCountedInputStream;
+ class IEffectSystem;
+ class IEffectSystemCore;
+ class CRenderString;
+ class IShaderCache;
+ class IUICRenderNodeFilter;
+ class IRenderWidget;
+ class IRenderWidgetContext;
+ struct SShaderVertexCodeGenerator;
+ struct SShaderFragmentCodeGenerator;
+ class IThreadPool;
+ struct SRenderMesh;
+ struct SLoadedTexture;
+ class IImageBatchLoader;
+ class ITextTextureCache;
+ class ITextTextureAtlas;
+ class IRenderPluginInstance;
+ class IRenderPluginClass;
+ class IRenderPluginManager;
+ class IRenderPluginManagerCore;
+ struct SRenderPlugin;
+ class IDynamicObjectSystemCore;
+ class IDynamicObjectSystem;
+ class IDynamicObjectClass;
+ struct SRenderSubset;
+ struct SModel;
+ namespace dynamic {
+ struct SPropertyDefinition;
+ }
+ struct SLight;
+ struct SCamera;
+ struct SCustomMaterial;
+ class ICustomMaterialSystem;
+ class ICustomMaterialSystemCore;
+ struct SLayer;
+ struct SReferencedMaterial;
+ struct SPGGraphObject;
+ class IPixelGraphicsRenderer;
+ class IBufferLoader;
+ struct SEffect;
+ class IRenderList;
+ class IRenderTask;
+ class CResourceTexture2D;
+ class IPathManagerCore;
+ class IPathManager;
+ struct SPath;
+ struct SPathSubPath;
+ class IShaderProgramGenerator;
+ class IShaderStageGenerator;
+ class IDefaultMaterialShaderGenerator;
+ class ICustomMaterialShaderGenerator;
+ struct SRenderableImage;
+ class UICShadowMap;
+ struct SLightmaps;
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderClippingFrustum.h b/src/Runtime/Source/UICRender/Include/UICRenderClippingFrustum.h
new file mode 100644
index 00000000..a0962dfc
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderClippingFrustum.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CLIPPING_PLANE_H
+#define UIC_RENDER_CLIPPING_PLANE_H
+#include "UICRender.h"
+#include "foundation/Qt3DSPlane.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSBounds3.h"
+
+namespace uic {
+namespace render {
+
+ struct BoxEdgeFlagValues
+ {
+ enum Enum {
+ xMax = 1,
+ yMax = 1 << 1,
+ zMax = 1 << 2,
+ };
+ };
+
+ typedef NVFlags<BoxEdgeFlagValues::Enum, QT3DSU8> TRenderBoxEdge;
+
+ // For an intesection test, we only need two points of the bounding box.
+ // There will be a point nearest to the plane, and a point furthest from the plane.
+ // We can derive these points from the plane normal equation.
+ struct SPlaneBoxEdge
+ {
+ TRenderBoxEdge lowerEdge;
+ TRenderBoxEdge upperEdge;
+ };
+
+ struct SClipPlane
+ {
+ QT3DSVec3 normal;
+ QT3DSF32 d;
+ SPlaneBoxEdge mEdges;
+
+ // For intersection tests, we only need to know if the numerator is greater than, equal to,
+ // or less than zero.
+ inline QT3DSF32 distance(const QT3DSVec3 &pt) const { return normal.dot(pt) + d; }
+
+ // Only works if p0 is above the line and p1 is below the plane.
+ inline QT3DSVec3 intersectWithLine(const QT3DSVec3 &p0, const QT3DSVec3 &p1) const
+ {
+ QT3DSVec3 dir = p1 - p0;
+ QT3DSVec3 pointOnPlane = normal * (-d);
+#ifdef _DEBUG
+ QT3DSF32 distanceOfPoint = distance(pointOnPlane);
+ QT3DS_ASSERT(NVAbs(distanceOfPoint) < 0.0001f);
+#endif
+ QT3DSF32 numerator = (pointOnPlane - p0).dot(normal);
+ QT3DSF32 denominator = dir.dot(normal);
+
+ QT3DS_ASSERT(NVAbs(denominator) > .0001f);
+ QT3DSF32 t = (numerator / denominator);
+ QT3DSVec3 retval = p0 + dir * t;
+#ifdef _DEBUG
+ QT3DSF32 retvalDistance = distance(retval);
+ QT3DS_ASSERT(NVAbs(retvalDistance) < .0001f);
+#endif
+ return retval;
+ }
+
+ static inline QT3DSVec3 corner(const NVBounds3 &bounds, TRenderBoxEdge edge)
+ {
+ return QT3DSVec3((edge & BoxEdgeFlagValues::xMax) ? bounds.maximum[0] : bounds.minimum[0],
+ (edge & BoxEdgeFlagValues::yMax) ? bounds.maximum[1] : bounds.minimum[1],
+ (edge & BoxEdgeFlagValues::zMax) ? bounds.maximum[2] : bounds.minimum[2]);
+ }
+
+ // dividing the distance numerator
+
+ // I got this code from osg, but it is in graphics gems
+ // as well.
+ /** intersection test between plane and bounding sphere.
+ return 1 if the bs is completely above plane,
+ return 0 if the bs intersects the plane,
+ return -1 if the bs is completely below the plane.*/
+ inline int intersect(const NVBounds3 &bounds) const
+ {
+ // if lowest point above plane than all above.
+ if (distance(corner(bounds, mEdges.lowerEdge)) > 0.0f)
+ return 1;
+
+ // if highest point is below plane then all below.
+ if (distance(corner(bounds, mEdges.upperEdge)) < 0.0f)
+ return -1;
+
+ // d_lower<=0.0f && d_upper>=0.0f
+ // therefore must be crossing plane.
+ return 0;
+ }
+
+ inline void calculateBBoxEdges()
+ {
+ mEdges.upperEdge = TRenderBoxEdge(
+ static_cast<QT3DSU8>((normal[0] >= 0.0f ? BoxEdgeFlagValues::xMax : 0)
+ | (normal[1] >= 0.0f ? BoxEdgeFlagValues::yMax : 0)
+ | (normal[2] >= 0.0f ? BoxEdgeFlagValues::zMax : 0)));
+
+ mEdges.lowerEdge = TRenderBoxEdge((~((QT3DSU8)mEdges.upperEdge)) & 7);
+ }
+ };
+
+ struct SClippingFrustum
+ {
+ SClipPlane mPlanes[6];
+
+ SClippingFrustum() {}
+
+ SClippingFrustum(const QT3DSMat44 &modelviewprojection, SClipPlane nearPlane);
+
+ bool intersectsWith(const NVBounds3 &bounds) const
+ {
+ for (QT3DSU32 idx = 0; idx < 6; ++idx)
+ if (mPlanes[idx].intersect(bounds) < 0)
+ return false;
+ return true;
+ }
+
+ bool intersectsWith(const QT3DSVec3 &point, QT3DSF32 radius = 0.0f) const
+ {
+ for (QT3DSU32 idx = 0; idx < 6; ++idx)
+ if (mPlanes[idx].distance(point) < radius)
+ return false;
+ return true;
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderContext.h b/src/Runtime/Source/UICRender/Include/UICRenderContext.h
new file mode 100644
index 00000000..77795e85
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderContext.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CONTEXT_H
+#define UIC_RENDER_CONTEXT_H
+#include "UICRender.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "UICRenderPresentation.h"
+#include "UICRenderWindowDimensions.h"
+
+#include <QPair>
+
+namespace uic {
+namespace render {
+ struct ScaleModes
+ {
+ enum Enum {
+ ExactSize = 0, // Ensure the viewport is exactly same size as application
+ ScaleToFit = 1, // Resize viewport keeping aspect ratio
+ ScaleToFill = 2, // Resize viewport to entire window
+ FitSelected = 3, // Resize presentation to fit into viewport
+ };
+ };
+
+ // Part of render context that does not require the render system.
+ class IUICRenderContextCore : public NVRefCounted
+ {
+ public:
+ virtual IStringTable &GetStringTable() = 0;
+ virtual NVFoundationBase &GetFoundation() = 0;
+ virtual NVAllocatorCallback &GetAllocator() = 0;
+ virtual IInputStreamFactory &GetInputStreamFactory() = 0;
+ virtual IThreadPool &GetThreadPool() = 0;
+ virtual IDynamicObjectSystemCore &GetDynamicObjectSystemCore() = 0;
+ virtual ICustomMaterialSystemCore &GetMaterialSystemCore() = 0;
+ virtual IEffectSystemCore &GetEffectSystemCore() = 0;
+ virtual IPerfTimer &GetPerfTimer() = 0;
+ virtual IBufferLoader &GetBufferLoader() = 0;
+ virtual IRenderPluginManagerCore &GetRenderPluginCore() = 0;
+ virtual IPathManagerCore &GetPathManagerCore() = 0;
+ // Text renderers may be provided by clients at runtime.
+ virtual void SetTextRendererCore(ITextRendererCore &inRenderer) = 0;
+ virtual ITextRendererCore *GetTextRendererCore() = 0;
+ // this is our default 2D text onscreen renderer
+ virtual void SetOnscreenTextRendererCore(ITextRendererCore &inRenderer) = 0;
+ virtual ITextRendererCore *GetOnscreenTextRendererCore() = 0;
+ // The render context maintains a reference to this object.
+ virtual IUICRenderContext &CreateRenderContext(NVRenderContext &inContext,
+ const char8_t *inPrimitivesDirectory) = 0;
+
+ static IUICRenderContextCore &Create(NVFoundationBase &fnd, IStringTable &strt);
+ };
+
+ class IUICRenderContext : public NVRefCounted
+ {
+ protected:
+ virtual ~IUICRenderContext() {}
+ public:
+ virtual IStringTable &GetStringTable() = 0;
+ virtual NVFoundationBase &GetFoundation() = 0;
+ virtual NVAllocatorCallback &GetAllocator() = 0;
+ virtual IUICRenderer &GetRenderer() = 0;
+ virtual IBufferManager &GetBufferManager() = 0;
+ virtual IResourceManager &GetResourceManager() = 0;
+ virtual NVRenderContext &GetRenderContext() = 0;
+ virtual IOffscreenRenderManager &GetOffscreenRenderManager() = 0;
+ virtual IInputStreamFactory &GetInputStreamFactory() = 0;
+ virtual IEffectSystem &GetEffectSystem() = 0;
+ virtual IShaderCache &GetShaderCache() = 0;
+ virtual IThreadPool &GetThreadPool() = 0;
+ virtual IImageBatchLoader &GetImageBatchLoader() = 0;
+ virtual IRenderPluginManager &GetRenderPluginManager() = 0;
+ virtual IDynamicObjectSystem &GetDynamicObjectSystem() = 0;
+ virtual ICustomMaterialSystem &GetCustomMaterialSystem() = 0;
+ virtual IPixelGraphicsRenderer &GetPixelGraphicsRenderer() = 0;
+ virtual IPerfTimer &GetPerfTimer() = 0;
+ virtual ITextTextureCache *GetTextureCache() = 0;
+ virtual ITextRenderer *GetTextRenderer() = 0;
+ virtual IRenderList &GetRenderList() = 0;
+ virtual IPathManager &GetPathManager() = 0;
+ virtual IShaderProgramGenerator &GetShaderProgramGenerator() = 0;
+ virtual IDefaultMaterialShaderGenerator &GetDefaultMaterialShaderGenerator() = 0;
+ virtual ICustomMaterialShaderGenerator &GetCustomMaterialShaderGenerator() = 0;
+ // The memory used for the per frame allocator is released as the first step in BeginFrame.
+ // This is useful for short lived objects and datastructures.
+ virtual NVAllocatorCallback &GetPerFrameAllocator() = 0;
+ // Get the number of times EndFrame has been called
+ virtual QT3DSU32 GetFrameCount() = 0;
+
+ // Get fps
+ virtual QPair<QT3DSF32, int> GetFPS() = 0;
+ // Set fps by higher level, etc application
+ virtual void SetFPS(QPair<QT3DSF32, int> inFPS) = 0;
+
+ // Currently there are a few things that need to work differently
+ // in authoring mode vs. runtime. The particle effects, for instance
+ // need to be framerate-independent at runtime but framerate-dependent during
+ // authoring time assuming virtual 16 ms frames.
+ // Defaults to falst.
+ virtual bool IsAuthoringMode() = 0;
+ virtual void SetAuthoringMode(bool inMode) = 0;
+
+ // This one is setup by the runtime binding
+ virtual ITextRenderer *GetOnscreenTextRenderer() = 0;
+ virtual ITextTextureAtlas *GetTextureAtlas() = 0;
+
+ // Sub presentations change the rendering somewhat.
+ virtual bool IsInSubPresentation() = 0;
+ virtual void SetInSubPresentation(bool inValue) = 0;
+ virtual void SetSceneColor(Option<QT3DSVec4> inSceneColor) = 0;
+ virtual void SetMatteColor(Option<QT3DSVec4> inMatteColor) = 0;
+
+ // Render screen aligned 2D text at x,y
+ virtual void RenderText2D(QT3DSF32 x, QT3DSF32 y, qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
+ const char *text) = 0;
+ // render Gpu profiler values
+ virtual void RenderGpuProfilerStats(QT3DSF32 x, QT3DSF32 y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor) = 0;
+
+ // The reason you can set both window dimensions and an overall viewport is that the mouse
+ // needs to be inverted
+ // which requires the window height, and then the rest of the system really requires the
+ // viewport.
+ virtual void SetWindowDimensions(const SWindowDimensions &inWindowDimensions) = 0;
+ virtual SWindowDimensions GetWindowDimensions() = 0;
+
+ // In addition to the window dimensions which really have to be set, you can optionally
+ // set the viewport which will force the entire viewer to render specifically to this
+ // viewport.
+ virtual void SetViewport(Option<NVRenderRect> inViewport) = 0;
+ virtual Option<NVRenderRect> GetViewport() const = 0;
+ virtual NVRenderRect GetContextViewport() const = 0;
+ // Only valid between calls to Begin,End.
+ virtual NVRenderRect GetPresentationViewport() const = 0;
+
+ virtual void SetScaleMode(ScaleModes::Enum inMode) = 0;
+ virtual ScaleModes::Enum GetScaleMode() = 0;
+
+ virtual void SetWireframeMode(bool inEnable) = 0;
+ virtual bool GetWireframeMode() = 0;
+
+ // Once set, the texture is displayed as long as the context is in place.
+ virtual void SetWatermark(NVRenderTexture2D &inTexture) = 0;
+ // default is 1,1
+ virtual void SetWatermarkLocation(QT3DSVec2 inCoordinates) = 0;
+
+ // Return the viewport the system is using to render data to. This gives the the dimensions
+ // of the rendered system. It is dependent on but not equal to the viewport.
+ virtual NVRenderRectF GetDisplayViewport() const = 0;
+
+ // Layers require the current presentation dimensions in order to render.
+ virtual void
+ SetPresentationDimensions(const SWindowDimensions &inPresentationDimensions) = 0;
+ virtual SWindowDimensions GetCurrentPresentationDimensions() const = 0;
+
+ virtual void SetRenderRotation(RenderRotationValues::Enum inRotation) = 0;
+ virtual RenderRotationValues::Enum GetRenderRotation() const = 0;
+
+ virtual QT3DSVec2 GetMousePickViewport() const = 0;
+ virtual QT3DSVec2 GetMousePickMouseCoords(const QT3DSVec2 &inMouseCoords) const = 0;
+
+ // Valid during and just after prepare for render.
+ virtual QT3DSVec2 GetPresentationScaleFactor() const = 0;
+
+ // Steps needed to render:
+ // 1. BeginFrame - sets up new target in render graph
+ // 2. Add everything you need to the render graph
+ // 3. RunRenderGraph - runs the graph, rendering things to main render target
+ // 4. Render any additional stuff to main render target on top of previously rendered
+ // information
+ // 5. EndFrame
+
+ // Clients need to call this every frame in order for various subsystems to release
+ // temporary per-frame allocated objects.
+ // Also sets up the viewport according to SetViewportInfo
+ // and the topmost presentation dimensions. Expects there to be exactly one presentation
+ // dimension pushed at this point.
+ // This also starts a render target in the render graph.
+ virtual void BeginFrame() = 0;
+
+ // This runs through the added tasks in reverse order. This is used to render dependencies
+ // before rendering to the main render target.
+ virtual void RunRenderTasks() = 0;
+ // Now you can render to the main render target if you want to render over the top
+ // of everything.
+ // Next call end frame.
+ virtual void EndFrame() = 0;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialRenderContext.h b/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialRenderContext.h
new file mode 100644
index 00000000..32658678
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialRenderContext.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CUSTOM_MATERIAL_RENDER_CONTEXT_H
+#define UIC_RENDER_CUSTOM_MATERIAL_RENDER_CONTEXT_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSMat44.h"
+#include "foundation/Qt3DSMat33.h"
+#include "UICRenderShaderKeys.h"
+
+namespace uic {
+namespace render {
+
+ struct SLayerRenderData;
+
+ struct SCustomMaterialRenderContext
+ {
+ // The lights and camera will not change per layer,
+ // so that information can be set once for all the shaders.
+ const SLayer &m_Layer;
+ const SLayerRenderData &m_LayerData;
+ NVDataRef<SLight *> m_Lights;
+ const SCamera &m_Camera;
+
+ // Per-object information.
+ const SModel &m_Model;
+ const SRenderSubset &m_Subset;
+ const QT3DSMat44 &m_ModelViewProjection;
+ const QT3DSMat44 &m_ModelMatrix; ///< model to world transformation
+ const QT3DSMat33 &m_NormalMatrix;
+ const SCustomMaterial &m_Material;
+ const NVRenderTexture2D *m_DepthTexture;
+ const NVRenderTexture2D *m_AOTexture;
+ SShaderDefaultMaterialKey m_MaterialKey;
+ SRenderableImage *m_FirstImage;
+
+ SCustomMaterialRenderContext(
+ const SLayer &layer, const SLayerRenderData &data, NVDataRef<SLight *> lights,
+ const SCamera &cam, const SModel &m, const SRenderSubset &subset, const QT3DSMat44 &mvp,
+ const QT3DSMat44 &world, const QT3DSMat33 &nm, const SCustomMaterial &material,
+ const NVRenderTexture2D *depthTex, const NVRenderTexture2D *aoTex,
+ SShaderDefaultMaterialKey inMaterialKey, SRenderableImage *inFirstImage = NULL)
+ : m_Layer(layer)
+ , m_LayerData(data)
+ , m_Lights(lights)
+ , m_Camera(cam)
+ , m_Model(m)
+ , m_Subset(subset)
+ , m_ModelViewProjection(mvp)
+ , m_ModelMatrix(world)
+ , m_NormalMatrix(nm)
+ , m_Material(material)
+ , m_DepthTexture(depthTex)
+ , m_AOTexture(aoTex)
+ , m_MaterialKey(inMaterialKey)
+ , m_FirstImage(inFirstImage)
+ {
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialShaderGenerator.h b/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialShaderGenerator.h
new file mode 100644
index 00000000..f8dc5f0c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialShaderGenerator.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CUSTOM_MATERIAL_SHADER_GENERATOR_H
+#define UIC_RENDER_CUSTOM_MATERIAL_SHADER_GENERATOR_H
+#include "UICRenderMaterialShaderGenerator.h"
+
+namespace uic {
+namespace render {
+
+ class UICShadowMap;
+
+ class ICustomMaterialShaderGenerator : public IMaterialShaderGenerator
+ {
+ public:
+ SImageVariableNames GetImageVariableNames(QT3DSU32 inIdx) override = 0;
+ void GenerateImageUVCoordinates(IShaderStageGenerator &inVertexPipeline, QT3DSU32 idx,
+ QT3DSU32 uvSet, SRenderableImage &image) override = 0;
+
+ // inPipelineName needs to be unique else the shader cache will just return shaders from
+ // different pipelines.
+ NVRenderShaderProgram *GenerateShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override = 0;
+
+ // Also sets the blend function on the render context.
+ virtual void
+ SetMaterialProperties(NVRenderShaderProgram &inProgram, const SGraphObject &inMaterial,
+ const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties) override = 0;
+
+ static ICustomMaterialShaderGenerator &
+ CreateCustomMaterialShaderGenerator(IUICRenderContext &inRenderContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialSystem.h b/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialSystem.h
new file mode 100644
index 00000000..662754ff
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderCustomMaterialSystem.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_CUSTOM_MATERIAL_SYSTEM_H
+#define UIC_RENDER_CUSTOM_MATERIAL_SYSTEM_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "../RendererImpl/UICVertexPipelineImpl.h"
+
+namespace uic {
+namespace render {
+
+ namespace dynamic {
+ struct SCommand; // UICRenderEffectCommands.h
+ }
+
+ struct SCustomMaterialRenderContext;
+
+ class ICustomMaterialSystemCore : public NVRefCounted
+ {
+ public:
+ virtual bool IsMaterialRegistered(CRegisteredString inStr) = 0;
+
+ virtual bool
+ RegisterMaterialClass(CRegisteredString inName,
+ NVConstDataRef<dynamic::SPropertyDeclaration> inProperties) = 0;
+
+ virtual NVConstDataRef<dynamic::SPropertyDefinition>
+ GetCustomMaterialProperties(CRegisteredString inCustomMaterialName) const = 0;
+
+ virtual void SetCustomMaterialRefraction(CRegisteredString inName,
+ bool inHasRefraction) = 0;
+ virtual void SetCustomMaterialTransparency(CRegisteredString inName,
+ bool inHasTransparency) = 0;
+ virtual void SetCustomMaterialAlwaysDirty(CRegisteredString inName,
+ bool inIsAlwaysDirty) = 0;
+ virtual void SetCustomMaterialShaderKey(CRegisteredString inName, QT3DSU32 inShaderKey) = 0;
+ virtual void SetCustomMaterialLayerCount(CRegisteredString inName, QT3DSU32 inLayerCount) = 0;
+ // The custom material commands are the actual commands that run for a given material
+ // effect. The tell the system exactly
+ // explicitly things like bind this shader, bind this render target, apply this property,
+ // run this shader
+ // See UICRenderEffectCommands.h for the list of commands.
+ // These commands are copied into the effect.
+ virtual void SetCustomMaterialCommands(CRegisteredString inName,
+ NVConstDataRef<dynamic::SCommand *> inCommands) = 0;
+
+ virtual void SetMaterialClassShader(CRegisteredString inName, const char8_t *inShaderType,
+ const char8_t *inShaderVersion,
+ const char8_t *inShaderData, bool inHasGeomShader,
+ bool inIsComputeShader) = 0;
+
+ virtual SCustomMaterial *
+ CreateCustomMaterial(CRegisteredString inName,
+ NVAllocatorCallback &inSceneGraphAllocator) = 0;
+
+ virtual void SetPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<CRegisteredString> inNames) = 0;
+
+ virtual void SetPropertyTextureSettings(CRegisteredString inEffectName,
+ CRegisteredString inPropName,
+ CRegisteredString inPropPath,
+ NVRenderTextureTypeValue::Enum inTexType,
+ NVRenderTextureCoordOp::Enum inCoordOp,
+ NVRenderTextureMagnifyingOp::Enum inMagFilterOp,
+ NVRenderTextureMinifyingOp::Enum inMinFilterOp) = 0;
+
+ virtual void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap,
+ const char8_t *inProjectDir) const = 0;
+ virtual void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t *inProjectDir) = 0;
+
+ virtual ICustomMaterialSystem &GetCustomMaterialSystem(IUICRenderContext &inContext) = 0;
+
+ static ICustomMaterialSystemCore &
+ CreateCustomMaterialSystemCore(IUICRenderContextCore &inContext);
+ };
+ // How to handle blend modes?
+ class ICustomMaterialSystem : public ICustomMaterialSystemCore
+ {
+ public:
+ // Returns true if the material is dirty and thus will produce a different render result
+ // than previously. This effects things like progressive AA.
+ virtual bool PrepareForRender(const SModel &inModel, const SRenderSubset &inSubset,
+ SCustomMaterial &inMaterial, bool inClearDirty) = 0;
+
+ virtual bool RenderDepthPrepass(const QT3DSMat44 &inMVP, const SCustomMaterial &inMaterial,
+ const SRenderSubset &inSubset) = 0;
+ virtual void RenderSubset(SCustomMaterialRenderContext &inRenderContext,
+ TShaderFeatureSet inFeatureSet) = 0;
+ virtual void OnMaterialActivationChange(const SCustomMaterial &inMaterial,
+ bool inActive) = 0;
+
+ // get shader name
+ virtual const char *GetShaderName(const SCustomMaterial &inMaterial) = 0;
+ // apply property values
+ virtual void ApplyShaderPropertyValues(const SCustomMaterial &inMaterial,
+ NVRenderShaderProgram &inProgram) = 0;
+ // Called by the uiccontext so this system can clear any per-frame render information.
+ virtual void EndFrame() = 0;
+ };
+
+ struct SCustomMaterialVertexPipeline : public SVertexPipelineImpl
+ {
+ IUICRenderContext *m_UICContext;
+ TessModeValues::Enum m_TessMode;
+
+ SCustomMaterialVertexPipeline(IUICRenderContext *inContext, TessModeValues::Enum inTessMode);
+ void InitializeTessControlShader();
+ void InitializeTessEvaluationShader();
+ void FinalizeTessControlShader();
+ void FinalizeTessEvaluationShader();
+
+ // Responsible for beginning all vertex and fragment generation (void main() { etc).
+ virtual void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) override;
+ // The fragment shader expects a floating point constant, object_opacity to be defined
+ // post this method.
+ virtual void BeginFragmentGeneration() override;
+ // Output variables may be mangled in some circumstances so the shader generation
+ // system needs an abstraction mechanism around this.
+ virtual void AssignOutput(const char8_t *inVarName, const char8_t *inVarValue) override;
+ virtual void GenerateEnvMapReflection() override {}
+ virtual void GenerateViewVector() override {}
+ virtual void GenerateUVCoords(QT3DSU32 inUVSet) override;
+ virtual void GenerateWorldNormal() override;
+ virtual void GenerateObjectNormal() override;
+ virtual void GenerateVarTangentAndBinormal() override;
+ virtual void GenerateWorldPosition() override;
+ // responsible for closing all vertex and fragment generation
+ virtual void EndVertexGeneration() override;
+ virtual void EndFragmentGeneration() override;
+ virtual IShaderStageGenerator &ActiveStage() override;
+ virtual void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override;
+ virtual void DoGenerateUVCoords(QT3DSU32 inUVSet) override;
+ virtual void DoGenerateWorldNormal() override;
+ virtual void DoGenerateObjectNormal() override;
+ virtual void DoGenerateWorldPosition() override;
+ virtual void DoGenerateVarTangentAndBinormal() override;
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h b/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h
new file mode 100644
index 00000000..105ffc64
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderDefaultMaterialShaderGenerator.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_DEFAULT_MATERIAL_SHADER_GENERATOR_H
+#define UIC_RENDER_DEFAULT_MATERIAL_SHADER_GENERATOR_H
+#include "UICRenderMaterialShaderGenerator.h"
+
+namespace uic {
+namespace render {
+
+ class UICShadowMap;
+
+ class IDefaultMaterialVertexPipeline : public IShaderStageGenerator
+ {
+ protected:
+ virtual ~IDefaultMaterialVertexPipeline() {}
+ public:
+ // Responsible for beginning all vertex and fragment generation (void main() { etc).
+ virtual void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) = 0;
+ // The fragment shader expects a floating point constant, object_opacity to be defined
+ // post this method.
+ virtual void BeginFragmentGeneration() = 0;
+ // Output variables may be mangled in some circumstances so the shader generation system
+ // needs an abstraction
+ // mechanism around this.
+ virtual void AssignOutput(const char8_t *inVarName, const char8_t *inVarValueExpr) = 0;
+
+ /**
+ * @brief Generates UV coordinates in shader code
+ *
+ * @param[in] inUVSet index of UV data set
+ *
+ * @return no return
+ */
+ virtual void GenerateUVCoords(QT3DSU32 inUVSet = 0) = 0;
+
+ virtual void GenerateEnvMapReflection() = 0;
+ virtual void GenerateViewVector() = 0;
+
+ // fragment shader expects varying vertex normal
+ // lighting in vertex pipeline expects world_normal
+ virtual void GenerateWorldNormal() = 0; // world_normal in both vert and frag shader
+ virtual void GenerateObjectNormal() = 0; // object_normal in both vert and frag shader
+ virtual void
+ GenerateWorldPosition() = 0; // model_world_position in both vert and frag shader
+ virtual void GenerateVarTangentAndBinormal() = 0;
+
+ virtual bool HasActiveWireframe() = 0; // varEdgeDistance is a valid entity
+
+ // responsible for closing all vertex and fragment generation
+ virtual void EndVertexGeneration() = 0;
+ virtual void EndFragmentGeneration() = 0;
+ };
+
+ class IDefaultMaterialShaderGenerator : public IMaterialShaderGenerator
+ {
+ public:
+ virtual void AddDisplacementImageUniforms(IShaderStageGenerator &inGenerator,
+ QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) = 0;
+ SImageVariableNames GetImageVariableNames(QT3DSU32 inIdx) override = 0;
+ void GenerateImageUVCoordinates(IShaderStageGenerator &inVertexPipeline, QT3DSU32 idx,
+ QT3DSU32 uvSet, SRenderableImage &image) override = 0;
+ // Transforms attr_pos, attr_norm, and attr_uv0.
+ virtual void AddDisplacementMappingForDepthPass(IShaderStageGenerator &inShader) = 0;
+
+ // inPipelineName needs to be unique else the shader cache will just return shaders from
+ // different pipelines.
+ NVRenderShaderProgram *GenerateShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override = 0;
+
+ // Also sets the blend function on the render context.
+ virtual void
+ SetMaterialProperties(NVRenderShaderProgram &inProgram, const SGraphObject &inMaterial,
+ const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties) override = 0;
+
+ static IDefaultMaterialShaderGenerator &
+ CreateDefaultMaterialShaderGenerator(IUICRenderContext &inRenderContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystem.h b/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystem.h
new file mode 100644
index 00000000..c47d05fa
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystem.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_DYNAMIC_OBJECT_SYSTEM_H
+#define UIC_RENDER_DYNAMIC_OBJECT_SYSTEM_H
+#include "UICRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSVec2.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderTessModeValues.h"
+#include "UICRenderGraphObjectTypes.h"
+#include "EASTL/utility.h"
+
+#include <QtCore/qstring.h>
+
+namespace uic {
+namespace render {
+ struct SDynamicObject;
+
+ namespace dynamic {
+
+ struct SCommand;
+
+ struct SPropertyDeclaration
+ {
+ const char8_t *m_Name;
+ // The datatypes map directly to the obvious types *except*
+ // for NVRenderTexture2DPtr. This type will be interpreted as a
+ // CRegisteredString (they are the same binary size)
+ // and will be used to lookup the texture from the buffer manager.
+ NVRenderShaderDataTypes::Enum m_DataType;
+
+ SPropertyDeclaration(const char8_t *inName, NVRenderShaderDataTypes::Enum inDtype)
+ : m_Name(inName)
+ , m_DataType(inDtype)
+ {
+ }
+ SPropertyDeclaration()
+ : m_Name("")
+ , m_DataType(NVRenderShaderDataTypes::Unknown)
+ {
+ }
+ };
+
+ struct SPropertyDefinition
+ {
+ CRegisteredString m_Name;
+
+ //*not* relative to the presentation directory
+ CRegisteredString m_ImagePath;
+ // The datatypes map directly to the obvious types *except*
+ // for NVRenderTexture2DPtr. This type will be interpreted as a
+ // CRegisteredString and will be used to lookup the texture
+ // from the buffer manager.
+ NVRenderShaderDataTypes::Enum m_DataType;
+ // All offsets are relative to the beginning of the SEffect
+ // and are aligned to 4 byte boundaries.
+ QT3DSU32 m_Offset;
+ // Sizeof this datatype.
+ QT3DSU32 m_ByteSize;
+ NVConstDataRef<CRegisteredString> m_EnumValueNames;
+
+ NVRenderTextureTypeValue::Enum
+ m_TexUsageType; ///< texture usage type like diffuse, specular, ...
+ // Applies to both s,t
+ NVRenderTextureCoordOp::Enum m_CoordOp;
+ // Set mag Filter
+ NVRenderTextureMagnifyingOp::Enum m_MagFilterOp;
+ // Set min Filter
+ NVRenderTextureMinifyingOp::Enum m_MinFilterOp;
+ bool m_IsEnumProperty;
+ SPropertyDefinition()
+ : m_DataType(NVRenderShaderDataTypes::Unknown)
+ , m_Offset(0)
+ , m_ByteSize(0)
+ , m_TexUsageType(NVRenderTextureTypeValue::Unknown)
+ , m_CoordOp(NVRenderTextureCoordOp::ClampToEdge)
+ , m_MagFilterOp(NVRenderTextureMagnifyingOp::Linear)
+ , m_MinFilterOp(NVRenderTextureMinifyingOp::Linear)
+ , m_IsEnumProperty(false)
+ {
+ }
+ SPropertyDefinition(CRegisteredString inName, NVRenderShaderDataTypes::Enum inType,
+ QT3DSU32 inOffset, QT3DSU32 inByteSize)
+ : m_Name(inName)
+ , m_DataType(inType)
+ , m_Offset(inOffset)
+ , m_ByteSize(inByteSize)
+ , m_TexUsageType(NVRenderTextureTypeValue::Unknown)
+ , m_CoordOp(NVRenderTextureCoordOp::ClampToEdge)
+ , m_MagFilterOp(NVRenderTextureMagnifyingOp::Linear)
+ , m_MinFilterOp(NVRenderTextureMinifyingOp::Linear)
+ , m_IsEnumProperty(false)
+ {
+ }
+ };
+
+ struct SDynamicShaderProgramFlags : public SShaderCacheProgramFlags
+ {
+ TessModeValues::Enum m_TessMode;
+ bool m_WireframeMode;
+
+ SDynamicShaderProgramFlags()
+ : m_TessMode(TessModeValues::NoTess)
+ , m_WireframeMode(false)
+ {
+ }
+
+ SDynamicShaderProgramFlags(TessModeValues::Enum inTessMode, bool inWireframeMode)
+ : m_TessMode(inTessMode)
+ , m_WireframeMode(inWireframeMode)
+ {
+ }
+
+ static const char *wireframeToString(bool inEnable)
+ {
+ if (inEnable)
+ return "wireframeMode:true";
+ else
+ return "wireframeMode:false";
+ }
+ };
+ }
+
+ class IDynamicObjectClass
+ {
+ protected:
+ virtual ~IDynamicObjectClass() {}
+ public:
+ virtual CRegisteredString GetId() const = 0;
+ virtual NVConstDataRef<dynamic::SPropertyDefinition> GetProperties() const = 0;
+ virtual QT3DSU32 GetPropertySectionByteSize() const = 0;
+ virtual const QT3DSU8 *GetDefaultValueBuffer() const = 0;
+ virtual QT3DSU32 GetBaseObjectSize() const = 0;
+ virtual GraphObjectTypes::Enum GraphObjectType() const = 0;
+ virtual const dynamic::SPropertyDefinition *
+ FindPropertyByName(CRegisteredString inName) const = 0;
+ virtual NVConstDataRef<dynamic::SCommand *> GetRenderCommands() const = 0;
+ virtual bool RequiresDepthTexture() const = 0;
+ virtual void SetRequiresDepthTexture(bool inRequires) = 0;
+ virtual bool RequiresCompilation() const = 0;
+ virtual void SetRequiresCompilation(bool inRequires) = 0;
+ virtual NVRenderTextureFormats::Enum GetOutputTextureFormat() const = 0;
+ };
+
+ class IDynamicObjectSystemCore : public NVRefCounted
+ {
+ protected:
+ virtual ~IDynamicObjectSystemCore() {}
+ public:
+ virtual bool IsRegistered(CRegisteredString inStr) = 0;
+
+ virtual bool Register(CRegisteredString inName,
+ NVConstDataRef<dynamic::SPropertyDeclaration> inProperties,
+ QT3DSU32 inBaseObjectSize, GraphObjectTypes::Enum inGraphObjectType) = 0;
+
+ virtual bool Unregister(CRegisteredString inName) = 0;
+
+ // Set the default value. THis is unnecessary if the default is zero as that is what it is
+ // assumed to be.
+ virtual void SetPropertyDefaultValue(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<QT3DSU8> inDefaultData) = 0;
+
+ virtual void SetPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<CRegisteredString> inNames) = 0;
+
+ virtual NVConstDataRef<CRegisteredString>
+ GetPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName) const = 0;
+
+ virtual NVConstDataRef<dynamic::SPropertyDefinition>
+ GetProperties(CRegisteredString inName) const = 0;
+
+ virtual void SetPropertyTextureSettings(CRegisteredString inName,
+ CRegisteredString inPropName,
+ CRegisteredString inPropPath,
+ NVRenderTextureTypeValue::Enum inTexType,
+ NVRenderTextureCoordOp::Enum inCoordOp,
+ NVRenderTextureMagnifyingOp::Enum inMagFilterOp,
+ NVRenderTextureMinifyingOp::Enum inMinFilterOp) = 0;
+
+ virtual IDynamicObjectClass *GetDynamicObjectClass(CRegisteredString inName) = 0;
+
+ // The effect commands are the actual commands that run for a given effect. The tell the
+ // system exactly
+ // explicitly things like bind this shader, bind this render target, apply this property,
+ // run this shader
+ // See UICRenderEffectCommands.h for the list of commands.
+ // These commands are copied into the effect.
+ virtual void SetRenderCommands(CRegisteredString inClassName,
+ NVConstDataRef<dynamic::SCommand *> inCommands) = 0;
+ virtual NVConstDataRef<dynamic::SCommand *>
+ GetRenderCommands(CRegisteredString inClassName) const = 0;
+
+ virtual SDynamicObject *CreateInstance(CRegisteredString inClassName,
+ NVAllocatorCallback &inSceneGraphAllocator) = 0;
+
+ // scan shader for #includes and insert any found"
+ virtual void InsertShaderHeaderInformation(CRenderString &inShader,
+ const char *inLogPath) = 0;
+
+ // Set the shader data for a given path. Used when a path doesn't correspond to a file but
+ // the data has been
+ // auto-generated. The system will look for data under this path key during the BindShader
+ // effect command.
+ virtual void SetShaderData(CRegisteredString inPath, const char8_t *inData,
+ const char8_t *inShaderType = NULL,
+ const char8_t *inShaderVersion = NULL,
+ bool inHasGeomShader = false,
+ bool inIsComputeShader = false) = 0;
+
+ // Overall save functions for saving the class information out to the binary file.
+ virtual void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap,
+ const char8_t *inProjectDir) const = 0;
+ virtual void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t *inProjectDir) = 0;
+
+ virtual IDynamicObjectSystem &CreateDynamicSystem(IUICRenderContext &rc) = 0;
+
+ static IDynamicObjectSystemCore &CreateDynamicSystemCore(IUICRenderContextCore &rc);
+ };
+
+ typedef eastl::pair<NVScopedRefCounted<NVRenderShaderProgram>,
+ dynamic::SDynamicShaderProgramFlags>
+ TShaderAndFlags;
+
+ class IDynamicObjectSystem : public IDynamicObjectSystemCore
+ {
+ protected:
+ virtual ~IDynamicObjectSystem() {}
+
+ public:
+ virtual TShaderAndFlags
+ GetShaderProgram(CRegisteredString inPath, CRegisteredString inProgramMacro,
+ TShaderFeatureSet inFeatureSet,
+ const dynamic::SDynamicShaderProgramFlags &inFlags,
+ bool inForceCompilation = false) = 0;
+
+ virtual const char8_t *GetShaderSource(CRegisteredString inPath, CRenderString &source) = 0;
+
+ // Will return null in the case where a custom prepass shader isn't needed for this object
+ // If no geom shader, then no depth prepass shader.
+ virtual TShaderAndFlags GetDepthPrepassShader(CRegisteredString inPath,
+ CRegisteredString inProgramMacro,
+ TShaderFeatureSet inFeatureSet) = 0;
+
+ virtual void setShaderCodeLibraryVersion(const QString &version) = 0;
+ virtual QString shaderCodeLibraryVersion() = 0;
+
+ virtual void setShaderCodeLibraryPlatformDirectory(const QString &directory) = 0;
+ virtual QString shaderCodeLibraryPlatformDirectory() = 0;
+
+ static QString GetShaderCodeLibraryDirectory() { return QStringLiteral("res\\effectlib\\"); }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemCommands.h b/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemCommands.h
new file mode 100644
index 00000000..fe23b7cf
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemCommands.h
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_EFFECT_SYSTEM_COMMANDS_H
+#define UIC_RENDER_EFFECT_SYSTEM_COMMANDS_H
+#include "UICRender.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSFlags.h"
+
+namespace uic {
+namespace render {
+ namespace dynamic {
+ using qt3ds::render::NVRenderBufferBarrierFlags;
+
+ struct CommandTypes
+ {
+ enum Enum {
+ Unknown = 0,
+ AllocateBuffer,
+ BindTarget,
+ BindBuffer,
+ BindShader,
+ ApplyInstanceValue,
+ ApplyBufferValue,
+ // Apply the depth buffer as an input texture.
+ ApplyDepthValue,
+ Render, // Render to current FBO
+ ApplyBlending,
+ ApplyRenderState, // apply a render state
+ ApplyBlitFramebuffer,
+ ApplyValue,
+ DepthStencil,
+ LuaCommand,
+ AllocateImage,
+ ApplyImageValue,
+ AllocateDataBuffer,
+ ApplyDataBufferValue,
+ };
+ };
+
+#define UIC_RENDER_EFFECTS_ITERATE_COMMAND_TYPES \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(AllocateBuffer) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(BindTarget) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(BindBuffer) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(BindShader) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyInstanceValue) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyBufferValue) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyDepthValue) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(Render) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyBlending) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyRenderState) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyBlitFramebuffer) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyValue) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(DepthStencil) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(LuaCommand) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(AllocateImage) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyImageValue) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(AllocateDataBuffer) \
+ UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyDataBufferValue)
+
+ // All commands need at least two constructors. One for when they are created that should
+ // setup
+ // all their member variables and one for when we are copying commands from an outside
+ // entity into
+ // the effect system. We have to re-register strings in that case because we can't assume
+ // the outside
+ // entity was using the same string table we are...
+ struct SCommand
+ {
+ CommandTypes::Enum m_Type;
+ SCommand(CommandTypes::Enum inType)
+ : m_Type(inType)
+ {
+ }
+ SCommand()
+ : m_Type(CommandTypes::Unknown)
+ {
+ }
+ // Implemented in UICRenderEffectSystem.cpp
+ static QT3DSU32 GetSizeofCommand(const SCommand &inCommand);
+ static void CopyConstructCommand(QT3DSU8 *inDataBuffer, const SCommand &inCommand,
+ IStringTable &inStrTable);
+ };
+
+ struct AllocateBufferFlagValues
+ {
+ enum Enum {
+ SceneLifetime = 1,
+ };
+ };
+
+ struct SAllocateBufferFlags : public NVFlags<AllocateBufferFlagValues::Enum, QT3DSU32>
+ {
+ SAllocateBufferFlags(QT3DSU32 inValues)
+ : NVFlags<AllocateBufferFlagValues::Enum, QT3DSU32>(inValues)
+ {
+ }
+ SAllocateBufferFlags() {}
+ void SetSceneLifetime(bool inValue)
+ {
+ clearOrSet(inValue, AllocateBufferFlagValues::SceneLifetime);
+ }
+ // If isSceneLifetime is unset the buffer is assumed to be frame lifetime and will be
+ // released after this
+ // render operation.
+ bool IsSceneLifetime() const
+ {
+ return this->operator&(AllocateBufferFlagValues::SceneLifetime);
+ }
+ };
+
+ struct SAllocateBuffer : public SCommand
+ {
+ CRegisteredString m_Name;
+ NVRenderTextureFormats::Enum m_Format;
+ NVRenderTextureMagnifyingOp::Enum m_FilterOp;
+ NVRenderTextureCoordOp::Enum m_TexCoordOp;
+ QT3DSF32 m_SizeMultiplier;
+ SAllocateBufferFlags m_BufferFlags;
+ SAllocateBuffer()
+ : SCommand(CommandTypes::AllocateBuffer)
+ , m_Format(NVRenderTextureFormats::RGBA8)
+ , m_FilterOp(NVRenderTextureMagnifyingOp::Linear)
+ , m_TexCoordOp(NVRenderTextureCoordOp::ClampToEdge)
+ , m_SizeMultiplier(1.0f)
+ {
+ }
+ SAllocateBuffer(CRegisteredString inName, NVRenderTextureFormats::Enum inFormat,
+ NVRenderTextureMagnifyingOp::Enum inFilterOp,
+ NVRenderTextureCoordOp::Enum inCoordOp, QT3DSF32 inMultiplier,
+ SAllocateBufferFlags inFlags)
+ : SCommand(CommandTypes::AllocateBuffer)
+ , m_Name(inName)
+ , m_Format(inFormat)
+ , m_FilterOp(inFilterOp)
+ , m_TexCoordOp(inCoordOp)
+ , m_SizeMultiplier(inMultiplier)
+ , m_BufferFlags(inFlags)
+ {
+ }
+ SAllocateBuffer(const SAllocateBuffer &inOther, IStringTable &inStrTable)
+ : SCommand(CommandTypes::AllocateBuffer)
+ , m_Name(inStrTable.RegisterStr(inOther.m_Name))
+ , m_Format(inOther.m_Format)
+ , m_FilterOp(inOther.m_FilterOp)
+ , m_TexCoordOp(inOther.m_TexCoordOp)
+ , m_SizeMultiplier(inOther.m_SizeMultiplier)
+ , m_BufferFlags(inOther.m_BufferFlags)
+ {
+ }
+ };
+
+ struct SAllocateImage : public SAllocateBuffer
+ {
+ NVRenderImageAccessType::Enum m_Access;
+
+ SAllocateImage()
+ : SAllocateBuffer()
+ , m_Access(NVRenderImageAccessType::ReadWrite)
+ {
+ m_Type = CommandTypes::AllocateImage;
+ }
+ SAllocateImage(CRegisteredString inName, NVRenderTextureFormats::Enum inFormat,
+ NVRenderTextureMagnifyingOp::Enum inFilterOp,
+ NVRenderTextureCoordOp::Enum inCoordOp, QT3DSF32 inMultiplier,
+ SAllocateBufferFlags inFlags, NVRenderImageAccessType::Enum inAccess)
+ : SAllocateBuffer(inName, inFormat, inFilterOp, inCoordOp, inMultiplier, inFlags)
+ , m_Access(inAccess)
+ {
+ m_Type = CommandTypes::AllocateImage;
+ }
+
+ SAllocateImage(const SAllocateImage &inOther, IStringTable &inStrTable)
+ : SAllocateBuffer(inStrTable.RegisterStr(inOther.m_Name), inOther.m_Format,
+ inOther.m_FilterOp, inOther.m_TexCoordOp,
+ inOther.m_SizeMultiplier, inOther.m_BufferFlags)
+ , m_Access(inOther.m_Access)
+ {
+ m_Type = CommandTypes::AllocateImage;
+ }
+ };
+
+ struct SAllocateDataBuffer : public SCommand
+ {
+ CRegisteredString m_Name;
+ NVRenderBufferBindValues::Enum m_DataBufferType;
+ CRegisteredString m_WrapName;
+ NVRenderBufferBindValues::Enum m_DataBufferWrapType;
+ QT3DSF32 m_Size;
+ SAllocateBufferFlags m_BufferFlags;
+
+ SAllocateDataBuffer()
+ : SCommand(CommandTypes::AllocateDataBuffer)
+ {
+ }
+
+ SAllocateDataBuffer(CRegisteredString inName,
+ NVRenderBufferBindValues::Enum inBufferType,
+ CRegisteredString inWrapName,
+ NVRenderBufferBindValues::Enum inBufferWrapType, QT3DSF32 inSize,
+ SAllocateBufferFlags inFlags)
+ : SCommand(CommandTypes::AllocateDataBuffer)
+ , m_Name(inName)
+ , m_DataBufferType(inBufferType)
+ , m_WrapName(inWrapName)
+ , m_DataBufferWrapType(inBufferWrapType)
+ , m_Size(inSize)
+ , m_BufferFlags(inFlags)
+ {
+ }
+
+ SAllocateDataBuffer(const SAllocateDataBuffer &inOther, IStringTable &inStrTable)
+ : SCommand(CommandTypes::AllocateDataBuffer)
+ , m_Name(inStrTable.RegisterStr(inOther.m_Name))
+ , m_DataBufferType(inOther.m_DataBufferType)
+ , m_WrapName(inStrTable.RegisterStr(inOther.m_WrapName))
+ , m_DataBufferWrapType(inOther.m_DataBufferWrapType)
+ , m_Size(inOther.m_Size)
+ , m_BufferFlags(inOther.m_BufferFlags)
+ {
+ }
+ };
+
+ struct SBindTarget : public SCommand
+ {
+ NVRenderTextureFormats::Enum m_OutputFormat;
+
+ SBindTarget(NVRenderTextureFormats::Enum inFormat = NVRenderTextureFormats::RGBA8)
+ : SCommand(CommandTypes::BindTarget)
+ , m_OutputFormat(inFormat)
+ {
+ }
+ SBindTarget(const SBindTarget &inOther, IStringTable &)
+ : SCommand(CommandTypes::BindTarget)
+ , m_OutputFormat(inOther.m_OutputFormat)
+ {
+ }
+ };
+
+ struct SBindBuffer : public SCommand
+ {
+ CRegisteredString m_BufferName;
+ bool m_NeedsClear;
+ SBindBuffer(CRegisteredString inBufName, bool inNeedsClear)
+ : SCommand(CommandTypes::BindBuffer)
+ , m_BufferName(inBufName)
+ , m_NeedsClear(inNeedsClear)
+ {
+ }
+ SBindBuffer(const SBindBuffer &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::BindBuffer)
+ , m_BufferName(inTable.RegisterStr(inOther.m_BufferName))
+ , m_NeedsClear(inOther.m_NeedsClear)
+ {
+ }
+ };
+
+ struct SBindShader : public SCommand
+ {
+ CRegisteredString m_ShaderPath;
+ // One GLSL file can hold multiple shaders in the case of multipass effects.
+ // This makes it significantly easier for authors to reason about the shader
+ // but it means we need to #define a preprocessor token to indicate which
+ // effect we intend to compile at this point.
+ CRegisteredString m_ShaderDefine;
+ SBindShader(CRegisteredString inShaderPath,
+ CRegisteredString inShaderDefine = CRegisteredString())
+ : SCommand(CommandTypes::BindShader)
+ , m_ShaderPath(inShaderPath)
+ , m_ShaderDefine(inShaderDefine)
+ {
+ }
+ SBindShader()
+ : SCommand(CommandTypes::BindShader)
+ {
+ }
+ SBindShader(const SBindShader &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::BindShader)
+ , m_ShaderPath(inTable.RegisterStr(inOther.m_ShaderPath))
+ , m_ShaderDefine(inTable.RegisterStr(inOther.m_ShaderDefine))
+ {
+ }
+ };
+
+ // The value sits immediately after the 'this' object
+ // in memory.
+ // If propertyName is not valid then we attempt to apply all of the effect property values
+ // to the shader, ignoring ones that don't match up.
+ struct SApplyInstanceValue : public SCommand
+ {
+ // Name of value to apply in shader
+ CRegisteredString m_PropertyName;
+ // type of value
+ NVRenderShaderDataTypes::Enum m_ValueType;
+ // offset in the effect data section of value.
+ QT3DSU32 m_ValueOffset;
+ SApplyInstanceValue(CRegisteredString inName, NVRenderShaderDataTypes::Enum inValueType,
+ QT3DSU32 inValueOffset)
+ : SCommand(CommandTypes::ApplyInstanceValue)
+ , m_PropertyName(inName)
+ , m_ValueType(inValueType)
+ , m_ValueOffset(inValueOffset)
+ {
+ }
+ // Default will attempt to apply all effect values to the currently bound shader
+ SApplyInstanceValue()
+ : SCommand(CommandTypes::ApplyInstanceValue)
+ , m_ValueType(NVRenderShaderDataTypes::Unknown)
+ , m_ValueOffset(0)
+ {
+ }
+ SApplyInstanceValue(const SApplyInstanceValue &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyInstanceValue)
+ , m_PropertyName(inTable.RegisterStr(inOther.m_PropertyName))
+ , m_ValueType(inOther.m_ValueType)
+ , m_ValueOffset(inOther.m_ValueOffset)
+ {
+ }
+ };
+
+ struct SApplyValue : public SCommand
+ {
+ CRegisteredString m_PropertyName;
+ NVRenderShaderDataTypes::Enum m_ValueType;
+ NVDataRef<QT3DSU8> m_Value;
+ SApplyValue(CRegisteredString inName, NVRenderShaderDataTypes::Enum inValueType)
+ : SCommand(CommandTypes::ApplyValue)
+ , m_PropertyName(inName)
+ , m_ValueType(inValueType)
+ {
+ }
+ // Default will attempt to apply all effect values to the currently bound shader
+ SApplyValue()
+ : SCommand(CommandTypes::ApplyValue)
+ , m_ValueType(NVRenderShaderDataTypes::Unknown)
+ {
+ }
+
+ SApplyValue(const SApplyValue &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyValue)
+ , m_PropertyName(inTable.RegisterStr(inOther.m_PropertyName))
+ , m_ValueType(inOther.m_ValueType)
+ , m_Value(inOther.m_Value)
+ {
+ }
+ };
+
+ // bind a buffer to a given shader parameter.
+ struct SApplyBufferValue : public SCommand
+ {
+ // If no buffer name is given then the special buffer [source]
+ // is assumed.
+ CRegisteredString m_BufferName;
+ // If no param name is given, the buffer is bound to the
+ // input texture parameter (texture0).
+ CRegisteredString m_ParamName;
+
+ SApplyBufferValue(CRegisteredString bufferName, CRegisteredString shaderParam)
+ : SCommand(CommandTypes::ApplyBufferValue)
+ , m_BufferName(bufferName)
+ , m_ParamName(shaderParam)
+ {
+ }
+ SApplyBufferValue(const SApplyBufferValue &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyBufferValue)
+ , m_BufferName(inTable.RegisterStr(inOther.m_BufferName))
+ , m_ParamName(inTable.RegisterStr(inOther.m_ParamName))
+ {
+ }
+ };
+
+ // bind a buffer to a given shader parameter.
+ struct SApplyImageValue : public SCommand
+ {
+ CRegisteredString m_ImageName; ///< name which the image was allocated
+ CRegisteredString m_ParamName; ///< must match the name in the shader
+ bool m_BindAsTexture; ///< bind image as texture
+ bool m_NeedSync; ///< if true we add a memory barrier before usage
+
+ SApplyImageValue(CRegisteredString bufferName, CRegisteredString shaderParam,
+ bool inBindAsTexture, bool inNeedSync)
+ : SCommand(CommandTypes::ApplyImageValue)
+ , m_ImageName(bufferName)
+ , m_ParamName(shaderParam)
+ , m_BindAsTexture(inBindAsTexture)
+ , m_NeedSync(inNeedSync)
+ {
+ }
+ SApplyImageValue(const SApplyImageValue &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyImageValue)
+ , m_ImageName(inTable.RegisterStr(inOther.m_ImageName))
+ , m_ParamName(inTable.RegisterStr(inOther.m_ParamName))
+ , m_BindAsTexture(inOther.m_BindAsTexture)
+ , m_NeedSync(inOther.m_NeedSync)
+ {
+ }
+ };
+
+ // bind a buffer to a given shader parameter.
+ struct SApplyDataBufferValue : public SCommand
+ {
+ CRegisteredString m_ParamName; ///< must match the name in the shader
+ NVRenderBufferBindValues::Enum m_BindAs; ///< to which target we bind this buffer
+
+ SApplyDataBufferValue(CRegisteredString inShaderParam,
+ NVRenderBufferBindValues::Enum inBufferType)
+ : SCommand(CommandTypes::ApplyDataBufferValue)
+ , m_ParamName(inShaderParam)
+ , m_BindAs(inBufferType)
+ {
+ }
+ SApplyDataBufferValue(const SApplyDataBufferValue &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyDataBufferValue)
+ , m_ParamName(inTable.RegisterStr(inOther.m_ParamName))
+ , m_BindAs(inOther.m_BindAs)
+ {
+ }
+ };
+
+ struct SApplyDepthValue : public SCommand
+ {
+ // If no param name is given, the buffer is bound to the
+ // input texture parameter (texture0).
+ CRegisteredString m_ParamName;
+ SApplyDepthValue(CRegisteredString param)
+ : SCommand(CommandTypes::ApplyDepthValue)
+ , m_ParamName(param)
+ {
+ }
+ SApplyDepthValue(const SApplyDepthValue &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyDepthValue)
+ , m_ParamName(inTable.RegisterStr(inOther.m_ParamName))
+ {
+ }
+ };
+
+ struct SRender : public SCommand
+ {
+ bool m_DrawIndirect;
+ SRender(bool inDrawIndirect)
+ : SCommand(CommandTypes::Render)
+ , m_DrawIndirect(inDrawIndirect)
+ {
+ }
+
+ SRender(const SRender &inOther, IStringTable &)
+ : SCommand(CommandTypes::Render)
+ , m_DrawIndirect(inOther.m_DrawIndirect)
+ {
+ }
+ };
+
+ struct SApplyBlending : public SCommand
+ {
+ NVRenderSrcBlendFunc::Enum m_SrcBlendFunc;
+ NVRenderDstBlendFunc::Enum m_DstBlendFunc;
+
+ SApplyBlending(NVRenderSrcBlendFunc::Enum inSrcBlendFunc,
+ NVRenderDstBlendFunc::Enum inDstBlendFunc)
+ : SCommand(CommandTypes::ApplyBlending)
+ , m_SrcBlendFunc(inSrcBlendFunc)
+ , m_DstBlendFunc(inDstBlendFunc)
+ {
+ }
+
+ SApplyBlending(const SApplyBlending &inOther, IStringTable &)
+ : SCommand(CommandTypes::ApplyBlending)
+ , m_SrcBlendFunc(inOther.m_SrcBlendFunc)
+ , m_DstBlendFunc(inOther.m_DstBlendFunc)
+ {
+ }
+ };
+
+ struct SApplyRenderState : public SCommand
+ {
+ NVRenderState::Enum m_RenderState;
+ bool m_Enabled;
+
+ SApplyRenderState(qt3ds::render::NVRenderState::Enum inRenderStateValue, bool inEnabled)
+ : SCommand(CommandTypes::ApplyRenderState)
+ , m_RenderState(inRenderStateValue)
+ , m_Enabled(inEnabled)
+ {
+ }
+
+ SApplyRenderState(const SApplyRenderState &inOther, IStringTable &)
+ : SCommand(CommandTypes::ApplyRenderState)
+ , m_RenderState(inOther.m_RenderState)
+ , m_Enabled(inOther.m_Enabled)
+ {
+ }
+ };
+
+ struct SApplyBlitFramebuffer : public SCommand
+ {
+ // If no buffer name is given then the special buffer [source]
+ // is assumed. Which is the default render target
+ CRegisteredString m_SourceBufferName;
+ // If no buffer name is given then the special buffer [dest]
+ // is assumed. Which is the default render target
+ CRegisteredString m_DestBufferName;
+
+ SApplyBlitFramebuffer(CRegisteredString inSourceBufferName,
+ CRegisteredString inDestBufferName)
+ : SCommand(CommandTypes::ApplyBlitFramebuffer)
+ , m_SourceBufferName(inSourceBufferName)
+ , m_DestBufferName(inDestBufferName)
+ {
+ }
+
+ SApplyBlitFramebuffer(const SApplyBlitFramebuffer &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::ApplyBlitFramebuffer)
+ , m_SourceBufferName(inTable.RegisterStr(inOther.m_SourceBufferName))
+ , m_DestBufferName(inTable.RegisterStr(inOther.m_DestBufferName))
+ {
+ }
+ };
+
+ struct DepthStencilFlagValues
+ {
+ enum Enum {
+ NoFlagValue = 0,
+ ClearStencil = 1 << 0,
+ ClearDepth = 1 << 1,
+ };
+ };
+
+ struct SDepthStencilFlags : public NVFlags<DepthStencilFlagValues::Enum>
+ {
+ bool HasClearStencil() const { return operator&(DepthStencilFlagValues::ClearStencil); }
+ void SetClearStencil(bool value)
+ {
+ clearOrSet(value, DepthStencilFlagValues::ClearStencil);
+ }
+
+ bool HasClearDepth() const { return operator&(DepthStencilFlagValues::ClearDepth); }
+ void SetClearDepth(bool value)
+ {
+ clearOrSet(value, DepthStencilFlagValues::ClearDepth);
+ }
+ };
+
+ struct SDepthStencil : public SCommand
+ {
+ CRegisteredString m_BufferName;
+ SDepthStencilFlags m_Flags;
+ qt3ds::render::NVRenderStencilOp::Enum m_StencilFailOperation;
+ qt3ds::render::NVRenderStencilOp::Enum m_DepthPassOperation;
+ qt3ds::render::NVRenderStencilOp::Enum m_DepthFailOperation;
+ qt3ds::render::NVRenderBoolOp::Enum m_StencilFunction;
+ QT3DSU32 m_Reference;
+ QT3DSU32 m_Mask;
+
+ SDepthStencil()
+ : SCommand(CommandTypes::DepthStencil)
+ , m_StencilFailOperation(qt3ds::render::NVRenderStencilOp::Keep)
+ , m_DepthPassOperation(qt3ds::render::NVRenderStencilOp::Keep)
+ , m_DepthFailOperation(qt3ds::render::NVRenderStencilOp::Keep)
+ , m_StencilFunction(qt3ds::render::NVRenderBoolOp::Equal)
+ , m_Reference(0)
+ , m_Mask(QT3DS_MAX_U32)
+ {
+ }
+
+ SDepthStencil(CRegisteredString bufName, SDepthStencilFlags flags,
+ qt3ds::render::NVRenderStencilOp::Enum inStencilOp,
+ qt3ds::render::NVRenderStencilOp::Enum inDepthPassOp,
+ qt3ds::render::NVRenderStencilOp::Enum inDepthFailOp,
+ qt3ds::render::NVRenderBoolOp::Enum inStencilFunc, QT3DSU32 value, QT3DSU32 mask)
+ : SCommand(CommandTypes::DepthStencil)
+ , m_BufferName(bufName)
+ , m_Flags(flags)
+ , m_StencilFailOperation(inStencilOp)
+ , m_DepthPassOperation(inDepthPassOp)
+ , m_DepthFailOperation(inDepthFailOp)
+ , m_StencilFunction(inStencilFunc)
+ , m_Reference(value)
+ , m_Mask(mask)
+ {
+ }
+
+ SDepthStencil(const SDepthStencil &inOther, IStringTable &inTable)
+ : SCommand(CommandTypes::DepthStencil)
+ , m_BufferName(inTable.RegisterStr(inOther.m_BufferName))
+ , m_Flags(inOther.m_Flags)
+ , m_StencilFailOperation(inOther.m_StencilFailOperation)
+ , m_DepthPassOperation(inOther.m_DepthPassOperation)
+ , m_DepthFailOperation(inOther.m_DepthFailOperation)
+ , m_StencilFunction(inOther.m_StencilFunction)
+ , m_Reference(inOther.m_Reference)
+ , m_Mask(inOther.m_Mask)
+ {
+ }
+ };
+
+ struct SLuaCommand : public SCommand
+ {
+ CRegisteredString m_LuaScript;
+ SLuaCommand()
+ : SCommand(CommandTypes::LuaCommand)
+ {
+ }
+ SLuaCommand(CRegisteredString ls)
+ : SCommand(CommandTypes::LuaCommand)
+ , m_LuaScript(ls)
+ {
+ }
+ SLuaCommand(const SLuaCommand &cmd, IStringTable &inTable)
+ : SCommand(CommandTypes::LuaCommand)
+ , m_LuaScript(inTable.RegisterStr(cmd.m_LuaScript))
+ {
+ }
+ };
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemUtil.h b/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemUtil.h
new file mode 100644
index 00000000..918e1fc6
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderDynamicObjectSystemUtil.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_DYNAMIC_OBJECT_SYSTEM_UTIL_H
+#define UIC_RENDER_DYNAMIC_OBJECT_SYSTEM_UTIL_H
+#include "UICRender.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "UICRenderString.h"
+
+namespace uic {
+namespace render {
+ namespace dynamic {
+
+ struct SStringLoadRemapper
+ {
+ CStrTableOrDataRef m_StrData;
+ IStringTable &m_StringTable;
+ CRenderString m_PathMapper;
+ const char8_t *m_ProjectDir;
+ SStringLoadRemapper(NVAllocatorCallback &alloc, CStrTableOrDataRef inData,
+ const char8_t *inProjectDir, IStringTable &inStrTable)
+ : m_StrData(inData)
+ , m_StringTable(inStrTable)
+ , m_ProjectDir(inProjectDir)
+ {
+ }
+ void Remap(CRegisteredString &inStr) { inStr.Remap(m_StrData); }
+ };
+
+ struct SStringSaveRemapper
+ {
+ const qt3ds::render::SStrRemapMap &m_Map;
+ CRenderString m_RelativeBuffer;
+ CRenderString m_ProjectDir;
+ CRenderString m_FinalBuffer;
+ IStringTable &m_StringTable;
+ SStringSaveRemapper(NVAllocatorCallback &alloc, const qt3ds::render::SStrRemapMap &map,
+ const char8_t *inProjectDir, IStringTable &inStrTable)
+ : m_Map(map)
+ , m_StringTable(inStrTable)
+ {
+ m_ProjectDir.assign(inProjectDir);
+ }
+ void Remap(CRegisteredString &inStr) { inStr.Remap(m_Map); }
+ };
+
+ inline QT3DSU32 Align(QT3DSU32 inValue)
+ {
+ if (inValue % 4)
+ return inValue + (4 - (inValue % 4));
+ return inValue;
+ }
+
+ inline QT3DSU32 Align8(QT3DSU32 inValue)
+ {
+ if (inValue % 8)
+ return inValue + (8 - (inValue % 8));
+ return inValue;
+ }
+
+ inline qt3ds::QT3DSU32 getSizeofShaderDataType(NVRenderShaderDataTypes::Enum value)
+ {
+ using namespace qt3ds;
+ using namespace qt3ds::render;
+ switch (value) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(x) \
+ case NVRenderShaderDataTypes::x: \
+ return sizeof(x);
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ inline const char *GetShaderDatatypeName(NVRenderShaderDataTypes::Enum inValue)
+ {
+ switch (inValue) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(type) \
+ case NVRenderShaderDataTypes::type: \
+ return #type;
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return "";
+ }
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderEffectSystem.h b/src/Runtime/Source/UICRender/Include/UICRenderEffectSystem.h
new file mode 100644
index 00000000..69e47ecc
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderEffectSystem.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_EFFECT_SYSTEM_H
+#define UIC_RENDER_EFFECT_SYSTEM_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSVec2.h"
+#include "UICRenderDynamicObjectSystem.h"
+
+namespace uic {
+namespace render {
+ struct SEffect;
+ struct SEffectContext;
+ namespace dynamic {
+ struct SCommand; // UICRenderEffectCommands.h
+ }
+
+ struct SEffectRenderArgument
+ {
+ SEffect &m_Effect;
+ NVRenderTexture2D &m_ColorBuffer;
+ // Some effects need the camera near and far ranges.
+ QT3DSVec2 m_CameraClipRange;
+ // Some effects require the depth buffer from the rendering of thelayer
+ // most do not.
+ NVRenderTexture2D *m_DepthTexture;
+ // this is a depth preapass texture we need for some effects like bloom
+ // actually we need the stencil values
+ NVRenderTexture2D *m_DepthStencilBuffer;
+
+ SEffectRenderArgument(SEffect &inEffect, NVRenderTexture2D &inColorBuffer,
+ const QT3DSVec2 &inCameraClipRange,
+ NVRenderTexture2D *inDepthTexture = NULL,
+ NVRenderTexture2D *inDepthBuffer = NULL)
+ : m_Effect(inEffect)
+ , m_ColorBuffer(inColorBuffer)
+ , m_CameraClipRange(inCameraClipRange)
+ , m_DepthTexture(inDepthTexture)
+ , m_DepthStencilBuffer(inDepthBuffer)
+ {
+ }
+ };
+
+ class IEffectSystemCore : public NVRefCounted
+ {
+ public:
+ virtual bool IsEffectRegistered(CRegisteredString inStr) = 0;
+ virtual NVConstDataRef<CRegisteredString> GetRegisteredEffects() = 0;
+ // Register an effect class that uses exactly these commands to render.
+ // Effect properties cannot change after the effect is created because that would invalidate
+ // existing effect instances.
+ // Effect commands, which are stored on the effect class, can change.
+ virtual bool RegisterEffect(CRegisteredString inName,
+ NVConstDataRef<dynamic::SPropertyDeclaration> inProperties) = 0;
+
+ virtual bool UnregisterEffect(CRegisteredString inName) = 0;
+
+ // Shorthand method that creates an effect and auto-generates the effect commands like such:
+ // BindShader(inPathToEffect)
+ // foreach( propdec in inProperties ) ApplyValue( propDecType )
+ // ApplyShader()
+ virtual bool
+ RegisterGLSLEffect(CRegisteredString inName, const char8_t *inPathToEffect,
+ NVConstDataRef<dynamic::SPropertyDeclaration> inProperties) = 0;
+ // Set the default value. THis is unnecessary if the default is zero as that is what it is
+ // assumed to be.
+ virtual void SetEffectPropertyDefaultValue(CRegisteredString inName,
+ CRegisteredString inPropName,
+ NVConstDataRef<QT3DSU8> inDefaultData) = 0;
+ virtual void SetEffectPropertyEnumNames(CRegisteredString inName,
+ CRegisteredString inPropName,
+ NVConstDataRef<CRegisteredString> inNames) = 0;
+ virtual NVConstDataRef<CRegisteredString>
+ GetEffectPropertyEnumNames(CRegisteredString inName,
+ CRegisteredString inPropName) const = 0;
+
+ virtual NVConstDataRef<dynamic::SPropertyDefinition>
+ GetEffectProperties(CRegisteredString inEffectName) const = 0;
+
+ virtual void SetEffectPropertyTextureSettings(
+ CRegisteredString inEffectName, CRegisteredString inPropName,
+ CRegisteredString inPropPath, NVRenderTextureTypeValue::Enum inTexType,
+ NVRenderTextureCoordOp::Enum inCoordOp, NVRenderTextureMagnifyingOp::Enum inMagFilterOp,
+ NVRenderTextureMinifyingOp::Enum inMinFilterOp) = 0;
+
+ // Setting the effect commands also sets this as if there isn't a specific "apply depth
+ // value"
+ // command then this effect does not require the depth texture.
+ // So the setter here is completely optional.
+ virtual void SetEffectRequiresDepthTexture(CRegisteredString inEffectName,
+ bool inValue) = 0;
+ virtual bool DoesEffectRequireDepthTexture(CRegisteredString inEffectName) const = 0;
+
+ virtual void SetEffectRequiresCompilation(CRegisteredString inEffectName,
+ bool inValue) = 0;
+ virtual bool DoesEffectRequireCompilation(CRegisteredString inEffectName) const = 0;
+
+ // The effect commands are the actual commands that run for a given effect. The tell the
+ // system exactly
+ // explicitly things like bind this shader, bind this render target, apply this property,
+ // run this shader
+ // See UICRenderEffectCommands.h for the list of commands.
+ // These commands are copied into the effect.
+ virtual void SetEffectCommands(CRegisteredString inEffectName,
+ NVConstDataRef<dynamic::SCommand *> inCommands) = 0;
+ virtual NVConstDataRef<dynamic::SCommand *>
+ GetEffectCommands(CRegisteredString inEffectName) const = 0;
+
+ // Set the shader data for a given path. Used when a path doesn't correspond to a file but
+ // the data has been
+ // auto-generated. The system will look for data under this path key during the BindShader
+ // effect command.
+ virtual void SetShaderData(CRegisteredString inPath, const char8_t *inData,
+ const char8_t *inShaderType = NULL,
+ const char8_t *inShaderVersion = NULL,
+ bool inHasGeomShader = false,
+ bool inIsComputeShader = false) = 0;
+
+ // An effect instance is just a property bag along with the name of the effect to run.
+ // This instance is what is placed into the object graph.
+ virtual SEffect *CreateEffectInstance(CRegisteredString inEffectName,
+ NVAllocatorCallback &inSceneGraphAllocator) = 0;
+
+ virtual void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap,
+ const char8_t *inProjectDir) const = 0;
+ virtual void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t *inProjectDir) = 0;
+
+ virtual IEffectSystem &GetEffectSystem(IUICRenderContext &context) = 0;
+
+ virtual IResourceManager &GetResourceManager() = 0;
+
+ static IEffectSystemCore &CreateEffectSystemCore(IUICRenderContextCore &context);
+ };
+
+ /**
+ * An effect is essentially a function that takes a image and produces a new image. The source
+ *and dest images
+ * aren't guaranteed to be the same size, the effect may enlarge or shrink the result.
+ * A specialization is when you want the effect to render to the final render target instead of
+ *to a separate image.
+ * In this case the effect cannot enlarge or shrink the final target and it will render to the
+ *destination buffer
+ * using the given MVP.
+ */
+ class IEffectSystem : public IEffectSystemCore
+ {
+ protected:
+ virtual ~IEffectSystem() {}
+
+ public:
+ // Calling release effect context with no context results in no problems.
+ virtual void ReleaseEffectContext(SEffectContext *inEffect) = 0;
+
+ // If the effect has a context you can call this to clear persistent buffers back to their
+ // original value.
+ virtual void ResetEffectFrameData(SEffectContext &inContext) = 0;
+
+ // Render this effect. Returns false in the case the effect wasn't rendered and the render
+ // state
+ // is guaranteed to be the same as before.
+ // The texture returned is allocated using the resource manager, and it is up to the caller
+ // to deallocate it or return it to the temporary pool if items when necessary
+ // Pass in true if you want the result image premultiplied. Most of the functions in the
+ // system
+ // assume non-premultiplied color for images so probably this is false.
+ virtual NVRenderTexture2D *RenderEffect(SEffectRenderArgument inRenderArgument) = 0;
+
+ // Render the effect to the currently bound render target using this MVP and optionally
+ // enabling blending when rendering to the target
+ virtual bool RenderEffect(SEffectRenderArgument inRenderArgument, QT3DSMat44 &inMVP,
+ bool inEnableBlendWhenRenderToTarget) = 0;
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderEulerAngles.h b/src/Runtime/Source/UICRender/Include/UICRenderEulerAngles.h
new file mode 100644
index 00000000..fcc1bab9
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderEulerAngles.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+namespace uic {
+namespace render {
+ //==============================================================================
+ // Description
+ //==============================================================================
+ // QuatTypes.h - Basic type declarations
+ // by Ken Shoemake, shoemake@graphics.cis.upenn.edu
+ // in "Graphics Gems IV", Academic Press, 1994
+ typedef struct
+ {
+ float x, y, z, w;
+ } Quat; /* Quaternion */
+ typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
+ enum QuatPart { X, Y, Z, W };
+ typedef Quat EulerAngles; /* (x,y,z)=ang 1,2,3, w=order code */
+
+#define EulFrmS 0
+#define EulFrmR 1
+#define EulFrm(ord) ((unsigned)(ord)&1)
+#define EulRepNo 0
+#define EulRepYes 1
+#define EulRep(ord) (((unsigned)(ord) >> 1) & 1)
+#define EulParEven 0
+#define EulParOdd 1
+#define EulPar(ord) (((unsigned)(ord) >> 2) & 1)
+#define EulSafe "\000\001\002\000"
+#define EulNext "\001\002\000\001"
+#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord) >> 3) & 3)]))
+#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) == EulParOdd)]))
+#define EulAxK(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) != EulParOdd)]))
+#define EulAxH(ord) ((EulRep(ord) == EulRepNo) ? EulAxK(ord) : EulAxI(ord))
+
+// EulGetOrd unpacks all useful information about order simultaneously.
+#define EulGetOrd(ord, i, j, k, h, n, s, f) \
+ { \
+ unsigned o = ord; \
+ f = o & 1; \
+ o = o >> 1; \
+ s = o & 1; \
+ o = o >> 1; \
+ n = o & 1; \
+ o = o >> 1; \
+ i = EulSafe[o & 3]; \
+ j = EulNext[i + n]; \
+ k = EulNext[i + 1 - n]; \
+ h = s ? k : i; \
+ }
+
+// EulOrd creates an order value between 0 and 23 from 4-tuple choices.
+#define EulOrd(i, p, r, f) (((((((i) << 1) + (p)) << 1) + (r)) << 1) + (f))
+
+// Static axes
+// X = 0, Y = 1, Z = 2 ref QuatPart
+#define EulOrdXYZs EulOrd(0, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdXYXs EulOrd(0, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdXZYs EulOrd(0, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdXZXs EulOrd(0, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdYZXs EulOrd(1, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdYZYs EulOrd(1, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdYXZs EulOrd(1, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdYXYs EulOrd(1, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdZXYs EulOrd(2, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdZXZs EulOrd(2, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdZYXs EulOrd(2, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdZYZs EulOrd(2, EulParOdd, EulRepYes, EulFrmS)
+
+// Rotating axes
+#define EulOrdZYXr EulOrd(0, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdXYXr EulOrd(0, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdYZXr EulOrd(0, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdXZXr EulOrd(0, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdXZYr EulOrd(1, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdYZYr EulOrd(1, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdZXYr EulOrd(1, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdYXYr EulOrd(1, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdYXZr EulOrd(2, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdZXZr EulOrd(2, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdXYZr EulOrd(2, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdZYZr EulOrd(2, EulParOdd, EulRepYes, EulFrmR)
+
+#ifndef M_PI
+#define M_PI 3.1415926535898
+#endif
+
+#define TODEG(x) x = (float)(x * 180 / M_PI);
+#define TORAD(x) x = (float)(x / 180 * M_PI);
+
+ class CEulerAngleConverter
+ {
+ private:
+ char m_OrderInfoBuffer[1024];
+
+ public:
+ CEulerAngleConverter();
+ virtual ~CEulerAngleConverter();
+
+ public:
+ EulerAngles Eul_(float ai, float aj, float ah, int order);
+ Quat Eul_ToQuat(EulerAngles ea);
+ void Eul_ToHMatrix(EulerAngles ea, HMatrix M);
+ EulerAngles Eul_FromHMatrix(HMatrix M, int order);
+ EulerAngles Eul_FromQuat(Quat q, int order);
+
+ // Debug Stuff
+ const char *DumpOrderInfo();
+ };
+}
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectPickQuery.h b/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectPickQuery.h
new file mode 100644
index 00000000..efc46683
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectPickQuery.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_GRAPH_OBJECT_PICK_QUERY_H
+#define UIC_RENDER_GRAPH_OBJECT_PICK_QUERY_H
+
+#include "UICRender.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSMat44.h"
+#include "UICRenderImage.h"
+
+namespace uic {
+namespace render {
+
+ class IOffscreenRenderer;
+
+ struct SUICRenderPickSubResult
+ {
+ IOffscreenRenderer *m_SubRenderer;
+ QT3DSMat44 m_TextureMatrix;
+ NVRenderTextureCoordOp::Enum m_HorizontalTilingMode;
+ NVRenderTextureCoordOp::Enum m_VerticalTilingMode;
+ QT3DSU32 m_ViewportWidth;
+ QT3DSU32 m_ViewportHeight;
+ SUICRenderPickSubResult *m_NextSibling;
+
+ SUICRenderPickSubResult()
+ : m_SubRenderer(NULL)
+ , m_NextSibling(NULL)
+ {
+ }
+ SUICRenderPickSubResult(IOffscreenRenderer &inSubRenderer, QT3DSMat44 inTextureMatrix,
+ NVRenderTextureCoordOp::Enum inHorizontalTilingMode,
+ NVRenderTextureCoordOp::Enum inVerticalTilingMode, QT3DSU32 width,
+ QT3DSU32 height)
+ : m_SubRenderer(&inSubRenderer)
+ , m_TextureMatrix(inTextureMatrix)
+ , m_HorizontalTilingMode(inHorizontalTilingMode)
+ , m_VerticalTilingMode(inVerticalTilingMode)
+ , m_ViewportWidth(width)
+ , m_ViewportHeight(height)
+ , m_NextSibling(NULL)
+ {
+ }
+ };
+
+ struct SUICRenderPickResult
+ {
+ const SGraphObject *m_HitObject;
+ QT3DSF32 m_CameraDistanceSq;
+ // The local coordinates in X,Y UV space where the hit occured
+ QT3DSVec2 m_LocalUVCoords;
+ // The local mouse coordinates will be the same on all of the sub objects.
+ SUICRenderPickSubResult *m_FirstSubObject;
+ // The offscreen renderer that was used to render the scene graph this result was produced
+ // from.
+ IOffscreenRenderer *m_OffscreenRenderer;
+
+ SUICRenderPickResult(const SGraphObject &inHitObject, QT3DSF32 inCameraDistance,
+ const QT3DSVec2 &inLocalUVCoords)
+ : m_HitObject(&inHitObject)
+ , m_CameraDistanceSq(inCameraDistance)
+ , m_LocalUVCoords(inLocalUVCoords)
+ , m_FirstSubObject(NULL)
+ , m_OffscreenRenderer(NULL)
+ {
+ }
+ SUICRenderPickResult()
+ : m_HitObject(NULL)
+ , m_CameraDistanceSq(QT3DS_MAX_F32)
+ , m_LocalUVCoords(0, 0)
+ , m_FirstSubObject(NULL)
+ , m_OffscreenRenderer(NULL)
+ {
+ }
+ };
+
+ class IGraphObjectPickQuery
+ {
+ protected:
+ virtual ~IGraphObjectPickQuery() {}
+
+ public:
+ // Implementors have the option of batching the results to allow fewer virtual calls
+ // or returning one item each pick.
+ // Results are guaranteed to be returned nearest to furthest
+ // If the return value has size of zero then we assume nothing more can be picked and the
+ // pick
+ // is finished.
+ virtual SUICRenderPickResult Pick(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool inPickEverything) = 0;
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectSerializer.h b/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectSerializer.h
new file mode 100644
index 00000000..e7f14b36
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectSerializer.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_GRAPH_OBJECT_SERIALZER_H
+#define UIC_RENDER_GRAPH_OBJECT_SERIALZER_H
+
+#include "UICRender.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace qt3ds {
+class NVFoundationBase;
+}
+
+namespace uic {
+namespace render {
+ struct SPresentation;
+ class IEffectSystem;
+
+ struct SGraphObjectSerializer
+ {
+ // This will save the tree as it exists but clients may wish to save out extra objects in
+ // addtion
+ static void
+ Save(NVFoundationBase &inFoundation, const SPresentation &inPresentation,
+ SWriteBuffer &outSavedData, IDynamicObjectSystem &inDynamicObjectSystem,
+ IPathManager &inPathManager, SPtrOffsetMap &outSceneGraphOffsets,
+ IStringTable &inStringTable,
+ NVDataRef<SGraphObject *> inExtraGraphObjects = NVDataRef<SGraphObject *>());
+
+ // Loading requires a correctly setup effect system because the effects have arbitrary data
+ // and the strings embedded in that data will
+ // require string remapping.
+ static SPresentation *Load(NVDataRef<QT3DSU8> inData, NVDataRef<QT3DSU8> inStrDataBlock,
+ IDynamicObjectSystemCore &inDynamicObjectSystem,
+ IPathManagerCore &inPathManager,
+ NVAllocatorCallback &inAllocator,
+ const char8_t *inProjectDirectory);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectTypes.h b/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectTypes.h
new file mode 100644
index 00000000..ff5f11a1
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderGraphObjectTypes.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_GRAPH_OBJECT_TYPES_H
+#define UIC_RENDER_GRAPH_OBJECT_TYPES_H
+#include "UICRender.h"
+#include "foundation/Qt3DSAssert.h"
+
+namespace uic {
+namespace render {
+
+// If you need a generic switch statement, then these macros will ensure
+// you get all the types the first time.
+#define UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Presentation) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Scene) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Node) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Layer) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Light) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Camera) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Model) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(DefaultMaterial) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Image) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Text) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Effect) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(RenderPlugin) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(CustomMaterial) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(ReferencedMaterial) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(Path) \
+ UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(PathSubPath)
+
+ struct GraphObjectTypes
+ {
+ enum Enum {
+ Unknown = 0,
+ Presentation,
+ Scene,
+ Node,
+ Layer,
+ Light,
+ Camera,
+ Model,
+ DefaultMaterial,
+ Image,
+ Text,
+ Effect,
+ CustomMaterial,
+ RenderPlugin,
+ ReferencedMaterial,
+ Path,
+ PathSubPath,
+ Lightmaps,
+ LastKnownGraphObjectType,
+ };
+
+ static bool IsMaterialType(Enum type)
+ {
+ switch (type) {
+ case ReferencedMaterial:
+ case CustomMaterial:
+ case DefaultMaterial:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static bool IsLightmapType(Enum type)
+ {
+ switch (type) {
+ case Lightmaps:
+ case DefaultMaterial:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static bool IsNodeType(Enum type)
+ {
+ switch (type) {
+ case Node:
+ case Layer:
+ case Light:
+ case Camera:
+ case Model:
+ case Text:
+ case Path:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+ }
+
+ static bool IsRenderableType(Enum type)
+ {
+ switch (type) {
+ case Model:
+ case Text:
+ case Path:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ static bool IsLightCameraType(Enum type)
+ {
+ switch (type) {
+ case Camera:
+ case Light:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+ static const char *GetObjectTypeName(Enum inType)
+ {
+ switch (inType) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case type: \
+ return #type;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return "";
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderImageScaler.h b/src/Runtime/Source/UICRender/Include/UICRenderImageScaler.h
new file mode 100644
index 00000000..ddfe5059
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderImageScaler.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef __IMAGESCALER_H_
+#define __IMAGESCALER_H_
+#include "UICRender.h"
+
+namespace uic {
+namespace render {
+ //==============================================================================
+ // Class
+ //==============================================================================
+ //==============================================================================
+ /**
+ * @class CImageScaler
+ */
+ //==============================================================================
+ class CImageScaler
+ {
+ NVAllocatorCallback &m_Allocator;
+
+ public:
+ //==============================================================================
+ // Methods
+ //==============================================================================
+ enum EScaleMethod {
+ SCALEMETHOD_CROP = -1, // Debug only, not a scaler
+ SCALEMETHOD_POINTSAMPLE = 0,
+ SCALEMETHOD_BILINEAR = 1,
+ };
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+
+ // Access
+
+ public:
+ CImageScaler(NVAllocatorCallback &inAlloc);
+
+ void Scale(EScaleMethod inScaleMethod, unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long inOldHeight, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight, unsigned long inChannels);
+
+ void FastScale(EScaleMethod inScaleMethod, unsigned char *inOldBuffer,
+ unsigned long inOldWidth, unsigned long inOldHeight,
+ unsigned char *&outNewBuffer, unsigned long inNewWidth,
+ unsigned long inNewHeight, unsigned long inChannels);
+
+ void Crop(unsigned char *inOldBuffer, unsigned long inOldWidth, unsigned long inOldHeight,
+ unsigned char *&outNewBuffer, unsigned long inNewWidth, unsigned long inNewHeight,
+ unsigned long inPlanes);
+
+ void Bilinear(unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long inOldHeight, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight, unsigned long inPlanes);
+
+ void FastPointSample(unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long inOldHeight, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight,
+ unsigned long inPlanes);
+
+ unsigned char *AllocateBuffer(long inWidth, long inHeight);
+ void ReleaseBuffer(unsigned char *&ioBuffer);
+ void Resize(unsigned char *inOldBuffer, unsigned long inOldWidth, unsigned long inOldHeight,
+ unsigned char *&outNewBuffer, unsigned long inNewWidth,
+ unsigned long inNewHeight, unsigned long inPlanes);
+
+ // variable numbers of planes, i.e. greyscale, rb, rbg, and rgba or argb
+ // Bilinear algorithms, good for quality
+ void ExpandRowsAndColumns(unsigned char *inBuffer, unsigned long inWidth,
+ unsigned long inHeight, unsigned char *outBuffer,
+ unsigned long inDstWidth, unsigned long inDstHeight,
+ unsigned long inPlanes);
+
+ // The method implemented above, but with some optimizations
+ // specifically, fixed the number of planes at 4
+ // eliminated the new/delete allocations
+ void FastExpandRowsAndColumns(unsigned char *inBuffer, unsigned long inWidth,
+ unsigned long inHeight, unsigned char *outBuffer,
+ unsigned long inDstWidth, unsigned long inDstHeight);
+
+ void ReduceCols(unsigned char *inSrcBuffer, long inSrcWidth, long inSrcHeight,
+ unsigned char *&outDstBuffer, long inDstWidth);
+ void ReduceRows(unsigned char *inSrcBuffer, long inSrcWidth, long inSrcHeight,
+ unsigned char *&outDstBuffer, long inDstHeight);
+ };
+}
+}
+
+#endif // !defined(__IMAGESCALER_H_)
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderImageTextureData.h b/src/Runtime/Source/UICRender/Include/UICRenderImageTextureData.h
new file mode 100644
index 00000000..6aff912b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderImageTextureData.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_IMAGE_TEXTURE_DATA_H
+#define UIC_RENDER_IMAGE_TEXTURE_DATA_H
+#include "UICRender.h"
+#include "foundation/Qt3DSFlags.h"
+
+namespace uic {
+namespace render {
+
+ // forward declararion
+ class UICRenderPrefilterTexture;
+
+ struct ImageTextureFlagValues
+ {
+ enum Enum {
+ HasTransparency = 1,
+ InvertUVCoords = 1 << 1,
+ PreMultiplied = 1 << 2,
+ };
+ };
+
+ struct SImageTextureFlags : public NVFlags<ImageTextureFlagValues::Enum, QT3DSU32>
+ {
+ bool HasTransparency() const
+ {
+ return this->operator&(ImageTextureFlagValues::HasTransparency);
+ }
+ void SetHasTransparency(bool inValue)
+ {
+ clearOrSet(inValue, ImageTextureFlagValues::HasTransparency);
+ }
+
+ bool IsInvertUVCoords() const
+ {
+ return this->operator&(ImageTextureFlagValues::InvertUVCoords);
+ }
+ void SetInvertUVCoords(bool inValue)
+ {
+ clearOrSet(inValue, ImageTextureFlagValues::InvertUVCoords);
+ }
+
+ bool IsPreMultiplied() const
+ {
+ return this->operator&(ImageTextureFlagValues::PreMultiplied);
+ }
+ void SetPreMultiplied(bool inValue)
+ {
+ clearOrSet(inValue, ImageTextureFlagValues::PreMultiplied);
+ }
+ };
+
+ struct SImageTextureData
+ {
+ NVRenderTexture2D *m_Texture;
+ SImageTextureFlags m_TextureFlags;
+ UICRenderPrefilterTexture *m_BSDFMipMap;
+
+ SImageTextureData()
+ : m_Texture(NULL)
+ , m_BSDFMipMap(NULL)
+ {
+ }
+
+ bool operator!=(const SImageTextureData &inOther)
+ {
+ return m_Texture != inOther.m_Texture || m_TextureFlags != inOther.m_TextureFlags
+ || m_BSDFMipMap != inOther.m_BSDFMipMap;
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderInputStreamFactory.h b/src/Runtime/Source/UICRender/Include/UICRenderInputStreamFactory.h
new file mode 100644
index 00000000..daff204e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderInputStreamFactory.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_INPUT_STREAM_FACTORY_H
+#define UIC_RENDER_INPUT_STREAM_FACTORY_H
+#include "UICRender.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "EASTL/string.h"
+
+namespace uic {
+namespace render {
+ class IRefCountedInputStream : public qt3ds::foundation::ISeekableIOStream, public NVRefCounted
+ {
+ protected:
+ virtual ~IRefCountedInputStream() {}
+ };
+ // This class is threadsafe.
+ class IInputStreamFactory : public NVRefCounted
+ {
+ protected:
+ virtual ~IInputStreamFactory() {}
+ public:
+ // These directories must have a '/' on them
+ virtual void AddSearchDirectory(const char8_t *inDirectory) = 0;
+ virtual IRefCountedInputStream *GetStreamForFile(const QString &inFilename,
+ bool inQuiet = false) = 0;
+ // Return a path for this file. Returns true if GetStreamForFile would return a valid
+ // stream.
+ // else returns false
+ virtual bool GetPathForFile(const QString &inFilename, QString &outFile,
+ bool inQuiet = false) = 0;
+
+ // Create an input stream factory using this foundation and an platform-optional app
+ // directory
+ // on android the app directory has no effect; use use the assets bundled with the APK file.
+ static IInputStreamFactory &Create(NVFoundationBase &inFoundation);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderMaterialHelpers.h b/src/Runtime/Source/UICRender/Include/UICRenderMaterialHelpers.h
new file mode 100644
index 00000000..e59e6730
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderMaterialHelpers.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_MATERIAL_HELPERS_H
+#define UIC_RENDER_MATERIAL_HELPERS_H
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderReferencedMaterial.h"
+
+namespace uic {
+namespace render {
+
+ inline bool IsMaterial(SGraphObject &obj)
+ {
+ return obj.m_Type == GraphObjectTypes::CustomMaterial
+ || obj.m_Type == GraphObjectTypes::DefaultMaterial
+ || obj.m_Type == GraphObjectTypes::ReferencedMaterial;
+ }
+
+ inline bool IsMaterial(SGraphObject *obj)
+ {
+ if (obj)
+ return IsMaterial(*obj);
+ return false;
+ }
+
+ inline bool IsImage(SGraphObject &obj) { return obj.m_Type == GraphObjectTypes::Image; }
+
+ inline bool IsImage(SGraphObject *obj)
+ {
+ if (obj)
+ return IsImage(*obj);
+ return false;
+ }
+
+ inline SGraphObject *GetNextMaterialSibling(SGraphObject *obj)
+ {
+ if (obj == NULL)
+ return NULL;
+ if (IsMaterial(obj) == false) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ if (obj->m_Type == GraphObjectTypes::CustomMaterial)
+ return static_cast<SCustomMaterial *>(obj)->m_NextSibling;
+ else if (obj->m_Type == GraphObjectTypes::DefaultMaterial)
+ return static_cast<SDefaultMaterial *>(obj)->m_NextSibling;
+ else
+ return static_cast<SReferencedMaterial *>(obj)->m_NextSibling;
+ }
+
+ inline void SetNextMaterialSibling(SGraphObject &obj, SGraphObject *sibling)
+ {
+ if (IsMaterial(obj) == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (obj.m_Type == GraphObjectTypes::CustomMaterial)
+ static_cast<SCustomMaterial *>(&obj)->m_NextSibling = sibling;
+ else if (obj.m_Type == GraphObjectTypes::DefaultMaterial)
+ static_cast<SDefaultMaterial *>(&obj)->m_NextSibling = sibling;
+ else
+ static_cast<SReferencedMaterial *>(&obj)->m_NextSibling = sibling;
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderMaterialShaderGenerator.h b/src/Runtime/Source/UICRender/Include/UICRenderMaterialShaderGenerator.h
new file mode 100644
index 00000000..b108564f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderMaterialShaderGenerator.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_MATERIAL_SHADER_GENERATOR_H
+#define UIC_RENDER_MATERIAL_SHADER_GENERATOR_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICRenderShaderKeys.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+
+namespace uic {
+namespace render {
+
+// these are our current shader limits
+#define UIC_MAX_NUM_LIGHTS 16
+#define UIC_MAX_NUM_SHADOWS 8
+
+ // note this struct must exactly match the memory layout of the
+ // struct sampleLight.glsllib and sampleArea.glsllib. If you make changes here you need
+ // to adjust the code in sampleLight.glsllib and sampleArea.glsllib as well
+ struct SLightSourceShader
+ {
+ QT3DSVec4 m_position;
+ QT3DSVec4 m_direction; // Specifies the light direction in world coordinates.
+ QT3DSVec4 m_up;
+ QT3DSVec4 m_right;
+ QT3DSVec4 m_diffuse;
+ QT3DSVec4 m_ambient;
+ QT3DSVec4 m_specular;
+ QT3DSF32 m_spotExponent; // Specifies the intensity distribution of the light.
+ QT3DSF32 m_spotCutoff; // Specifies the maximum spread angle of the light.
+ QT3DSF32 m_constantAttenuation; // Specifies the constant light attenuation factor.
+ QT3DSF32 m_linearAttenuation; // Specifies the linear light attenuation factor.
+ QT3DSF32 m_quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ QT3DSF32 m_range; // Specifies the maximum distance of the light influence
+ QT3DSF32 m_width; // Specifies the width of the area light surface.
+ QT3DSF32 m_height; // Specifies the height of the area light surface;
+ QT3DSVec4 m_shadowControls;
+ QT3DSMat44 m_shadowView;
+ QT3DSI32 m_shadowIdx;
+ QT3DSF32 m_padding1[3];
+ };
+
+ struct SLayerGlobalRenderProperties
+ {
+ const SLayer &m_Layer;
+ SCamera &m_Camera;
+ QT3DSVec3 m_CameraDirection;
+ NVDataRef<SLight *> m_Lights;
+ NVDataRef<QT3DSVec3> m_LightDirections;
+ UICShadowMap *m_ShadowMapManager;
+ NVRenderTexture2D *m_DepthTexture;
+ NVRenderTexture2D *m_SSaoTexture;
+ SImage *m_LightProbe;
+ SImage *m_LightProbe2;
+ QT3DSF32 m_ProbeHorizon;
+ QT3DSF32 m_ProbeBright;
+ QT3DSF32 m_Probe2Window;
+ QT3DSF32 m_Probe2Pos;
+ QT3DSF32 m_Probe2Fade;
+ QT3DSF32 m_ProbeFOV;
+
+ SLayerGlobalRenderProperties(const SLayer &inLayer, SCamera &inCamera,
+ QT3DSVec3 inCameraDirection, NVDataRef<SLight *> inLights,
+ NVDataRef<QT3DSVec3> inLightDirections,
+ UICShadowMap *inShadowMapManager,
+ NVRenderTexture2D *inDepthTexture,
+ NVRenderTexture2D *inSSaoTexture, SImage *inLightProbe,
+ SImage *inLightProbe2, QT3DSF32 inProbeHorizon,
+ QT3DSF32 inProbeBright, QT3DSF32 inProbe2Window, QT3DSF32 inProbe2Pos,
+ QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV)
+ : m_Layer(inLayer)
+ , m_Camera(inCamera)
+ , m_CameraDirection(inCameraDirection)
+ , m_Lights(inLights)
+ , m_LightDirections(inLightDirections)
+ , m_ShadowMapManager(inShadowMapManager)
+ , m_DepthTexture(inDepthTexture)
+ , m_SSaoTexture(inSSaoTexture)
+ , m_LightProbe(inLightProbe)
+ , m_LightProbe2(inLightProbe2)
+ , m_ProbeHorizon(inProbeHorizon)
+ , m_ProbeBright(inProbeBright)
+ , m_Probe2Window(inProbe2Window)
+ , m_Probe2Pos(inProbe2Pos)
+ , m_Probe2Fade(inProbe2Fade)
+ , m_ProbeFOV(inProbeFOV)
+ {
+ }
+ };
+
+ class IMaterialShaderGenerator : public NVRefCounted
+ {
+ public:
+ struct SImageVariableNames
+ {
+ const char8_t *m_ImageSampler;
+ const char8_t *m_ImageFragCoords;
+ };
+
+ virtual SImageVariableNames GetImageVariableNames(QT3DSU32 inIdx) = 0;
+ virtual void GenerateImageUVCoordinates(IShaderStageGenerator &inVertexPipeline, QT3DSU32 idx,
+ QT3DSU32 uvSet, SRenderableImage &image) = 0;
+
+ // inPipelineName needs to be unique else the shader cache will just return shaders from
+ // different pipelines.
+ virtual NVRenderShaderProgram *GenerateShader(
+ const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency,
+ const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") = 0;
+
+ // Also sets the blend function on the render context.
+ virtual void
+ SetMaterialProperties(NVRenderShaderProgram &inProgram, const SGraphObject &inMaterial,
+ const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties) = 0;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderMesh.h b/src/Runtime/Source/UICRender/Include/UICRenderMesh.h
new file mode 100644
index 00000000..9705d3c7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderMesh.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_MESH_H
+#define UIC_RENDER_MESH_H
+#include "UICRender.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "render/Qt3DSRenderInputAssembler.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSNoCopy.h"
+
+namespace uic {
+namespace render {
+
+ struct SRenderSubsetBase
+ {
+ QT3DSU32 m_Count;
+ QT3DSU32 m_Offset;
+ NVBounds3 m_Bounds; // Vertex buffer bounds
+ SRenderSubsetBase() {}
+ SRenderSubsetBase(const SRenderSubsetBase &inOther)
+ : m_Count(inOther.m_Count)
+ , m_Offset(inOther.m_Offset)
+ , m_Bounds(inOther.m_Bounds)
+ {
+ }
+
+ SRenderSubsetBase &operator=(const SRenderSubsetBase &inOther)
+ {
+ m_Count = inOther.m_Count;
+ m_Offset = inOther.m_Offset;
+ m_Bounds = inOther.m_Bounds;
+ return *this;
+ }
+ };
+
+ struct SRenderJoint
+ {
+ QT3DSI32 m_JointID;
+ QT3DSI32 m_ParentID;
+ QT3DSF32 m_invBindPose[16];
+ QT3DSF32 m_localToGlobalBoneSpace[16];
+ };
+
+ struct SRenderSubset : public SRenderSubsetBase
+ {
+ NVRenderInputAssembler *m_InputAssembler;
+ NVRenderInputAssembler *m_InputAssemblerDepth;
+ NVRenderInputAssembler
+ *m_InputAssemblerPoints; ///< similar to depth but ignores index buffer.
+ NVRenderVertexBuffer *m_VertexBuffer;
+ NVRenderVertexBuffer
+ *m_PosVertexBuffer; ///< separate position buffer for fast depth path rendering
+ NVRenderIndexBuffer *m_IndexBuffer;
+ NVRenderDrawMode::Enum m_PrimitiveType; ///< primitive type used for drawing
+ QT3DSF32 m_EdgeTessFactor; ///< edge tessellation amount used for tessellation shaders
+ QT3DSF32 m_InnerTessFactor; ///< inner tessellation amount used for tessellation shaders
+ bool m_WireframeMode; ///< true if we should draw the object as wireframe ( currently ony if
+ ///tessellation is enabled )
+ NVConstDataRef<SRenderJoint> m_Joints;
+ CRegisteredString m_Name;
+ nvvector<SRenderSubsetBase> m_SubSubsets;
+
+ SRenderSubset(NVAllocatorCallback &alloc)
+ : m_InputAssembler(NULL)
+ , m_InputAssemblerDepth(NULL)
+ , m_InputAssemblerPoints(NULL)
+ , m_VertexBuffer(NULL)
+ , m_PosVertexBuffer(NULL)
+ , m_IndexBuffer(NULL)
+ , m_PrimitiveType(NVRenderDrawMode::Triangles)
+ , m_EdgeTessFactor(1.0)
+ , m_InnerTessFactor(1.0)
+ , m_WireframeMode(false)
+ , m_SubSubsets(alloc, "SRenderSubset::m_SubSubsets")
+ {
+ }
+ SRenderSubset(const SRenderSubset &inOther)
+ : SRenderSubsetBase(inOther)
+ , m_InputAssembler(inOther.m_InputAssembler)
+ , m_InputAssemblerDepth(inOther.m_InputAssemblerDepth)
+ , m_InputAssemblerPoints(inOther.m_InputAssemblerPoints)
+ , m_VertexBuffer(inOther.m_VertexBuffer)
+ , m_PosVertexBuffer(inOther.m_PosVertexBuffer)
+ , m_IndexBuffer(inOther.m_IndexBuffer)
+ , m_PrimitiveType(inOther.m_PrimitiveType)
+ , m_EdgeTessFactor(inOther.m_EdgeTessFactor)
+ , m_InnerTessFactor(inOther.m_InnerTessFactor)
+ , m_WireframeMode(inOther.m_WireframeMode)
+ , m_Joints(inOther.m_Joints)
+ , m_Name(inOther.m_Name)
+ , m_SubSubsets(inOther.m_SubSubsets)
+ {
+ }
+ // Note that subSubsets is *not* copied.
+ SRenderSubset(NVAllocatorCallback &alloc, const SRenderSubset &inOther,
+ const SRenderSubsetBase &inBase)
+ : SRenderSubsetBase(inBase)
+ , m_InputAssembler(inOther.m_InputAssembler)
+ , m_InputAssemblerDepth(inOther.m_InputAssemblerDepth)
+ , m_InputAssemblerPoints(inOther.m_InputAssemblerPoints)
+ , m_VertexBuffer(inOther.m_VertexBuffer)
+ , m_PosVertexBuffer(inOther.m_PosVertexBuffer)
+ , m_IndexBuffer(inOther.m_IndexBuffer)
+ , m_PrimitiveType(inOther.m_PrimitiveType)
+ , m_EdgeTessFactor(inOther.m_EdgeTessFactor)
+ , m_InnerTessFactor(inOther.m_InnerTessFactor)
+ , m_WireframeMode(inOther.m_WireframeMode)
+ , m_Name(inOther.m_Name)
+ , m_SubSubsets(alloc, "SRenderSubset::m_SubSubsets")
+ {
+ }
+
+ SRenderSubset &operator=(const SRenderSubset &inOther)
+ {
+ if (this != &inOther) {
+ SRenderSubsetBase::operator=(inOther);
+ m_InputAssembler = inOther.m_InputAssembler;
+ m_InputAssemblerDepth = inOther.m_InputAssemblerDepth;
+ m_VertexBuffer = inOther.m_VertexBuffer;
+ m_PosVertexBuffer = inOther.m_PosVertexBuffer;
+ m_IndexBuffer = inOther.m_IndexBuffer;
+ m_PrimitiveType = inOther.m_PrimitiveType;
+ m_EdgeTessFactor = inOther.m_EdgeTessFactor;
+ m_InnerTessFactor = inOther.m_InnerTessFactor;
+ m_WireframeMode = inOther.m_WireframeMode;
+ m_Joints = inOther.m_Joints;
+ m_Name = inOther.m_Name;
+ m_SubSubsets = inOther.m_SubSubsets;
+ }
+ return *this;
+ }
+ };
+
+ struct SRenderMesh : public NoCopy
+ {
+ nvvector<SRenderSubset> m_Subsets;
+ nvvector<SRenderJoint> m_Joints;
+ NVRenderDrawMode::Enum m_DrawMode;
+ NVRenderWinding::Enum m_Winding; // counterclockwise
+ QT3DSU32 m_MeshId; // Id from the file of this mesh.
+
+ SRenderMesh(NVRenderDrawMode::Enum inDrawMode, NVRenderWinding::Enum inWinding,
+ QT3DSU32 inMeshId, NVAllocatorCallback &alloc)
+ : m_Subsets(alloc, "SRenderMesh::m_Subsets")
+ , m_Joints(alloc, "SRenderMesh::Joints")
+ , m_DrawMode(inDrawMode)
+ , m_Winding(inWinding)
+ , m_MeshId(inMeshId)
+ {
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPathManager.h b/src/Runtime/Source/UICRender/Include/UICRenderPathManager.h
new file mode 100644
index 00000000..403bba83
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPathManager.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PATH_MANAGER_H
+#define UIC_RENDER_PATH_MANAGER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "UICRenderShaderCache.h" //TShaderFeatureSet
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSBounds3.h"
+//#include "UICRenderDefaultMaterialShaderGenerator.h" //SLayerGlobalRenderProperties
+
+namespace uic {
+namespace render {
+
+ struct SLayerGlobalRenderProperties;
+
+ struct SPathAnchorPoint
+ {
+ QT3DSVec2 m_Position;
+ QT3DSF32 m_IncomingAngle;
+ QT3DSF32 m_OutgoingAngle;
+ QT3DSF32 m_IncomingDistance;
+ QT3DSF32 m_OutgoingDistance;
+ SPathAnchorPoint() {}
+ SPathAnchorPoint(QT3DSVec2 inPos, QT3DSF32 inAngle, QT3DSF32 outAngle, QT3DSF32 inDis, QT3DSF32 outDis)
+ : m_Position(inPos)
+ , m_IncomingAngle(inAngle)
+ , m_OutgoingAngle(outAngle)
+ , m_IncomingDistance(inDis)
+ , m_OutgoingDistance(outDis)
+ {
+ }
+ };
+
+ class IPathManagerCore : public NVRefCounted
+ {
+ public:
+ // returns the path buffer id
+ //!! Note this call is made from multiple threads simultaneously during binary load.
+ //!! - see UICRenderGraphObjectSerializer.cpp
+ virtual void
+ SetPathSubPathData(const SPathSubPath &inPathSubPath,
+ NVConstDataRef<SPathAnchorPoint> inPathSubPathAnchorPoints) = 0;
+
+ virtual NVDataRef<SPathAnchorPoint>
+ GetPathSubPathBuffer(const SPathSubPath &inPathSubPath) = 0;
+ // Marks the PathSubPath anchor points as dirty. This will mean rebuilding any PathSubPath
+ // context required to render the PathSubPath.
+ virtual NVDataRef<SPathAnchorPoint>
+ ResizePathSubPathBuffer(const SPathSubPath &inPathSubPath, QT3DSU32 inNumAnchors) = 0;
+ virtual NVBounds3 GetBounds(const SPath &inPath) = 0;
+
+ // Helper functions used in various locations
+ // Angles here are in degrees because that is how they are represented in the data.
+ static QT3DSVec2 GetControlPointFromAngleDistance(QT3DSVec2 inPosition, float inAngle,
+ float inDistance);
+
+ // Returns angle in x, distance in y.
+ static QT3DSVec2 GetAngleDistanceFromControlPoint(QT3DSVec2 inPosition, QT3DSVec2 inControlPoint);
+
+ virtual IPathManager &OnRenderSystemInitialize(IUICRenderContext &context) = 0;
+
+ static IPathManagerCore &CreatePathManagerCore(IUICRenderContextCore &inContext);
+ };
+
+ struct SPathRenderContext; // UICRenderPathRenderContext.h
+
+ class IPathManager : public IPathManagerCore
+ {
+ public:
+ // The path segments are next expected to change after this call; changes will be ignored.
+ virtual bool PrepareForRender(const SPath &inPath) = 0;
+
+ virtual void RenderDepthPrepass(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) = 0;
+
+ virtual void RenderShadowMapPass(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) = 0;
+
+ virtual void RenderCubeFaceShadowPass(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) = 0;
+
+ virtual void RenderPath(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) = 0;
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPathMath.h b/src/Runtime/Source/UICRender/Include/UICRenderPathMath.h
new file mode 100644
index 00000000..07ad3f62
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPathMath.h
@@ -0,0 +1,713 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_RENDER_PATH_MATH_H
+#define UIC_RENDER_PATH_MATH_H
+#include "UICRender.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+namespace uic {
+namespace render {
+namespace path {
+// Solve quadratic equation in with a templated real number system.
+template <typename REAL>
+
+int quadratic(REAL b, REAL c, REAL rts[2])
+{
+ int nquad;
+ REAL dis;
+ REAL rtdis;
+
+ dis = b * b - 4 * c;
+ rts[0] = 0;
+ rts[1] = 0;
+ if (b == 0) {
+ if (c == 0) {
+ nquad = 2;
+ } else {
+ if (c < 0) {
+ nquad = 2;
+ rts[0] = sqrt(-c);
+ rts[1] = -rts[0];
+ } else {
+ nquad = 0;
+ }
+ }
+ } else if (c == 0) {
+ nquad = 2;
+ rts[0] = -b;
+ } else if (dis >= 0) {
+ nquad = 2;
+ rtdis = sqrt(dis);
+ if (b > 0)
+ rts[0] = (-b - rtdis) * (1 / REAL(2));
+ else
+ rts[0] = (-b + rtdis) * (1 / REAL(2));
+ if (rts[0] == 0)
+ rts[1] = -b;
+ else
+ rts[1] = c / rts[0];
+ } else {
+ nquad = 0;
+ }
+
+ return (nquad);
+} /* quadratic */
+
+float interest_range[2] = {0, 1};
+
+void cubicInflectionPoint(const QT3DSVec2 cp[4], nvvector<QT3DSF32> &key_point)
+{
+ // Convert control points to cubic monomial polynomial coefficients
+ const QT3DSVec2 A = cp[3] - cp[0] + (cp[1] - cp[2]) * 3.0;
+ const QT3DSVec2 B = (cp[0] - cp[1] * 2.0 + cp[2]) * 3.0, C = (cp[1] - cp[0]) * 3.0;
+ const QT3DSVec2 D = cp[0];
+
+ double a = 3 * (B.x * A.y - A.x * B.y);
+ double b = 3 * (C.x * A.y - C.y * A.x);
+ double c = C.x * B.y - C.y * B.x;
+
+ double roots[2];
+ int solutions;
+ // Is the quadratic really a degenerate line?
+ if (a == 0) {
+ // Is the line really a degenerate point?
+ if (b == 0) {
+ solutions = 0;
+ } else {
+ solutions = 1;
+ roots[0] = c / b;
+ }
+ } else {
+ solutions = quadratic(b / a, c / a, roots);
+ }
+ for (int i = 0; i < solutions; i++) {
+ QT3DSF32 t = static_cast<QT3DSF32>(roots[i]);
+
+ QT3DSVec2 p = ((A * t + B) * t + C) * t + D;
+ if (t >= interest_range[0] && t <= interest_range[1])
+ key_point.push_back(t);
+ // else; Outside range of interest, ignore.
+ }
+}
+
+typedef enum {
+ CT_POINT,
+ CT_LINE,
+ CT_QUADRATIC,
+ CT_CUSP,
+ CT_LOOP,
+ CT_SERPENTINE
+} CurveType;
+
+static inline bool isZero(double v)
+{
+#if 0
+ const double eps = 6e-008;
+
+ if (fabs(v) < eps)
+ return true;
+ else
+ return false;
+#else
+ return v == 0.0;
+#endif
+}
+
+inline QT3DSVec3 crossv1(const QT3DSVec2 &a, const QT3DSVec2 &b)
+{
+ return QT3DSVec3(a[1] - b[1], b[0] - a[0], a[0] * b[1] - a[1] * b[0]);
+}
+
+inline bool sameVertex(const QT3DSVec2 &a, const QT3DSVec2 &b)
+{
+ return (a.x == b.x && a.y == b.y);
+}
+
+inline bool sameVertex(const QT3DSVec3 &a, const QT3DSVec3 &b)
+{
+ return (a.x == b.x && a.y == b.y && a.z == b.z);
+}
+
+// This function "normalizes" the input vector so the larger of its components
+// is in the range [512,1024]. Exploit integer math on the exponent bits to
+// do this without expensive DP exponentiation.
+inline void scaleTo512To1024(QT3DSVec2 &d, int e)
+{
+ union {
+ QT3DSU64 u64;
+ double f64;
+ } x;
+ int ie = 10 - (int)e + 1023;
+ QT3DS_ASSERT(ie > 0);
+ x.u64 = ((QT3DSU64)ie) << 52;
+ d *= static_cast<QT3DSF32>(x.f64);
+}
+
+inline double fastfrexp(double d, int *exponent)
+{
+ union {
+ QT3DSU64 u64;
+ double f64;
+ } x;
+ x.f64 = d;
+ *exponent = (((int)(x.u64 >> 52)) & 0x7ff) - 0x3ff;
+ x.u64 &= (1ULL << 63) - (1ULL << 52);
+ x.u64 |= (0x3ffULL << 52);
+ return x.f64;
+}
+
+QT3DSVec3 CreateVec3(QT3DSVec2 xy, float z)
+{
+ return QT3DSVec3(xy.x, xy.y, z);
+}
+
+QT3DSVec2 GetXY(const QT3DSVec3 &data)
+{
+ return QT3DSVec2(data.x, data.y);
+}
+
+CurveType cubicDoublePoint(const QT3DSVec2 points[4], nvvector<QT3DSF32> &key_point)
+{
+#if 0
+ const QT3DSVec2 AA = points[3] - points[0] + (points[1] - points[2]) * 3.0;
+ const QT3DSVec3 BB = (points[0] - points[1] * 2.0 + points[2]) * 3.0;
+ const QT3DSVec3 CC = (points[1] - points[0]) * 3.0, DD = points[0];
+#endif
+
+ // Assume control points of the cubic curve are A, B, C, and D.
+ const QT3DSVec3 A = CreateVec3(points[0], 1);
+ const QT3DSVec3 B = CreateVec3(points[1], 1);
+ const QT3DSVec3 C = CreateVec3(points[2], 1);
+ const QT3DSVec3 D = CreateVec3(points[3], 1);
+
+ // Compute the discriminant of the roots of
+ // H(s,t) = -36*(d1^2*s^2 - d1*d2*s*t + (d2^2 - d1*d3)*t^2)
+ // where H is the Hessian (the square matrix of second-order
+ // partial derivatives of a function) of I(s,t)
+ // where I(s,t) determine the inflection points of the cubic
+ // Bezier curve C(s,t).
+ //
+ // d1, d2, and d3 functions of the determinants constructed
+ // from the cubic control points.
+ //
+ // Recall dot(a,cross(b,c)) is determinant of a 3x3 matrix
+ // with a, b, c the rows of the matrix.
+ const QT3DSVec3 DC = crossv1(GetXY(D), GetXY(C));
+ const QT3DSVec3 AD = crossv1(GetXY(A), GetXY(D));
+ const QT3DSVec3 BA = crossv1(GetXY(B), GetXY(A));
+
+ const double a1 = A.dot(DC);
+ const double a2 = B.dot(AD);
+ const double a3 = C.dot(BA);
+ const double d1 = a1 - 2 * a2 + 3 * a3;
+ const double d2 = -a2 + 3 * a3;
+ const double d3 = 3 * a3;
+ const double discriminant = (3 * d2 * d2 - 4 * d1 * d3);
+
+ // The sign of the discriminant of I classifies the curbic curve
+ // C into one of 6 classifications:
+ // 1) discriminant>0 ==> serpentine
+ // 2) discriminant=0 ==> cusp
+ // 3) discriminant<0 ==> loop
+
+ // If the discriminant or d1 are almost but not exactly zero, the
+ // result is really noisy unacceptable (k,l,m) interpolation.
+ // If it looks almost like a quadratic or linear case, treat it that way.
+ if (isZero(discriminant) && isZero(d1)) {
+ // Cusp case
+
+ if (isZero(d2)) {
+ // degenerate cases (points, lines, quadratics)...
+ if (isZero(d3)) {
+ if (sameVertex(A, B) && sameVertex(A, C) && sameVertex(A, D))
+ return CT_POINT;
+ else
+ return CT_LINE;
+ } else {
+ return CT_QUADRATIC;
+ }
+ } else {
+ return CT_CUSP;
+ }
+ } else if (discriminant < 0) {
+ // Loop case
+
+ const QT3DSF32 t = static_cast<QT3DSF32>(d2 + sqrt(-discriminant));
+ QT3DSVec2 d = QT3DSVec2(t, static_cast<QT3DSF32>(2 * d1));
+ QT3DSVec2 e = QT3DSVec2(static_cast<QT3DSF32>(2 * (d2 * d2 - d1 * d3)),
+ static_cast<QT3DSF32>(d1 * t));
+
+ // There is the situation where r2=c/t results in division by zero, but
+ // in this case, the two roots represent a double root at zero so
+ // subsitute l for (the otherwise NaN) m in this case.
+ //
+ // This situation can occur when the 1st and 2nd (or 3rd and 4th?)
+ // control point of a cubic Bezier path SubPath are identical.
+ if (e.x == 0 && e.y == 0)
+ e = d;
+
+ // d, e, or both could be very large values. To mitigate the risk of
+ // floating-point overflow in subsequent calculations
+ // scale both vectors to be in the range [768,1024] since their relative
+ // scale of their x & y components is irrelevant.
+
+ // Be careful to divide by a power-of-two to disturb mantissa bits.
+
+ double d_max_mag = NVMax(fabs(d.x), fabs(d.y));
+ int exponent;
+ fastfrexp(d_max_mag, &exponent);
+ scaleTo512To1024(d, exponent);
+
+ double e_max_mag = NVMax(fabs(e.x), fabs(e.y));
+ fastfrexp(e_max_mag, &exponent);
+ scaleTo512To1024(e, exponent);
+
+ const QT3DSVec2 roots = QT3DSVec2(d.x / d.y, e.x / e.y);
+
+ double tt;
+#if 0
+ tt = roots[0];
+ if (tt >= interest_range[0] && tt <= interest_range[1])
+ // key_point.push_back(tt);
+ tt = roots[1];
+ if (tt >= interest_range[0] && tt <= interest_range[1])
+ // key_point.push_back(tt);
+#endif
+ tt = (roots[0] + roots[1]) / 2;
+ if (tt >= interest_range[0] && tt <= interest_range[1])
+ key_point.push_back(static_cast<QT3DSF32>(tt));
+
+ return CT_LOOP;
+ } else {
+ QT3DS_ASSERT(discriminant >= 0);
+ cubicInflectionPoint(points, key_point);
+ if (discriminant > 0) {
+ // Serpentine case
+ return CT_SERPENTINE;
+ } else {
+ // Cusp with inflection at infinity (treat like serpentine)
+ return CT_CUSP;
+ }
+ }
+}
+
+QT3DSVec4 CreateVec4(QT3DSVec2 p1, QT3DSVec2 p2)
+{
+ return QT3DSVec4(p1.x, p1.y, p2.x, p2.y);
+}
+
+QT3DSVec2 lerp(QT3DSVec2 p1, QT3DSVec2 p2, QT3DSF32 distance)
+{
+ return p1 + (p2 - p1) * distance;
+}
+
+QT3DSF32 lerp(QT3DSF32 p1, QT3DSF32 p2, QT3DSF32 distance)
+{
+ return p1 + (p2 - p1) * distance;
+}
+
+// Using first derivative to get tangent.
+// If this equation does not make immediate sense consider that it is the first derivative
+// of the de Casteljau bezier expansion, not the polynomial expansion.
+float TangentAt(float inT, float p1, float c1, float c2, float p2)
+{
+ float a = c1 - p1;
+ float b = c2 - c1 - a;
+ float c = p2 - c2 - a - (2.0f * b);
+ float retval = 3.0f * (a + (2.0f * b * inT) + (c * inT * inT));
+ return retval;
+}
+
+QT3DSVec2 midpoint(QT3DSVec2 p1, QT3DSVec2 p2)
+{
+ return lerp(p1, p2, .5f);
+}
+
+QT3DSF32 LineLength(QT3DSVec2 inStart, QT3DSVec2 inStop)
+{
+ return (inStop - inStart).magnitude();
+}
+
+struct SCubicBezierCurve
+{
+ QT3DSVec2 m_Points[4];
+ SCubicBezierCurve(QT3DSVec2 a1, QT3DSVec2 c1, QT3DSVec2 c2, QT3DSVec2 a2)
+ {
+ m_Points[0] = a1;
+ m_Points[1] = c1;
+ m_Points[2] = c2;
+ m_Points[3] = a2;
+ }
+
+ // Normal is of course orthogonal to the tangent.
+ QT3DSVec2 NormalAt(float inT) const
+ {
+ QT3DSVec2 tangent = QT3DSVec2(
+ TangentAt(inT, m_Points[0].x, m_Points[1].x, m_Points[2].x, m_Points[3].x),
+ TangentAt(inT, m_Points[0].y, m_Points[1].y, m_Points[2].y, m_Points[3].y));
+
+ QT3DSVec2 result(tangent.y, -tangent.x);
+ result.normalize();
+ return result;
+ }
+
+ eastl::pair<SCubicBezierCurve, SCubicBezierCurve> SplitCubicBezierCurve(float inT)
+ {
+ // compute point on curve based on inT
+ // using de Casteljau algorithm
+ QT3DSVec2 p12 = lerp(m_Points[0], m_Points[1], inT);
+ QT3DSVec2 p23 = lerp(m_Points[1], m_Points[2], inT);
+ QT3DSVec2 p34 = lerp(m_Points[2], m_Points[3], inT);
+ QT3DSVec2 p123 = lerp(p12, p23, inT);
+ QT3DSVec2 p234 = lerp(p23, p34, inT);
+ QT3DSVec2 p1234 = lerp(p123, p234, inT);
+
+ return eastl::make_pair(SCubicBezierCurve(m_Points[0], p12, p123, p1234),
+ SCubicBezierCurve(p1234, p234, p34, m_Points[3]));
+ }
+};
+
+#if 0
+ static QT3DSVec2 NormalToLine( QT3DSVec2 startPoint, QT3DSVec2 endPoint )
+ {
+ QT3DSVec2 lineDxDy = endPoint - startPoint;
+ QT3DSVec2 result( lineDxDy.y, -lineDxDy.x );
+ result.normalize();
+ return result;
+ }
+#endif
+
+struct SResultCubic
+{
+ enum Mode {
+ Normal = 0,
+ BeginTaper = 1,
+ EndTaper = 2,
+ };
+ QT3DSVec2 m_P1;
+ QT3DSVec2 m_C1;
+ QT3DSVec2 m_C2;
+ QT3DSVec2 m_P2;
+ // Location in the original data where this cubic is taken from
+ QT3DSU32 m_EquationIndex;
+ QT3DSF32 m_TStart;
+ QT3DSF32 m_TStop;
+ QT3DSF32 m_Length;
+ QT3DSVec2 m_TaperMultiplier; // normally 1, goes to zero at very end of taper if any taper.
+ Mode m_Mode;
+
+ SResultCubic(QT3DSVec2 inP1, QT3DSVec2 inC1, QT3DSVec2 inC2, QT3DSVec2 inP2,
+ QT3DSU32 equationIndex, QT3DSF32 tStart, QT3DSF32 tStop, QT3DSF32 length)
+ : m_P1(inP1)
+ , m_C1(inC1)
+ , m_C2(inC2)
+ , m_P2(inP2)
+ , m_EquationIndex(equationIndex)
+ , m_TStart(tStart)
+ , m_TStop(tStop)
+ , m_Length(length)
+ , m_TaperMultiplier(1.0f, 1.0f)
+ , m_Mode(Normal)
+ {
+ }
+ // Note the vec2 items are *not* initialized in any way here.
+ SResultCubic() {}
+ QT3DSF32 GetP1Width(QT3DSF32 inPathWidth, QT3DSF32 beginTaperWidth, QT3DSF32 endTaperWidth)
+ {
+ return GetPathWidth(inPathWidth, beginTaperWidth, endTaperWidth, 0);
+ }
+
+ QT3DSF32 GetP2Width(QT3DSF32 inPathWidth, QT3DSF32 beginTaperWidth, QT3DSF32 endTaperWidth)
+ {
+ return GetPathWidth(inPathWidth, beginTaperWidth, endTaperWidth, 1);
+ }
+
+ QT3DSF32 GetPathWidth(QT3DSF32 inPathWidth, QT3DSF32 beginTaperWidth, QT3DSF32 endTaperWidth,
+ QT3DSU32 inTaperIndex)
+ {
+ QT3DSF32 retval = inPathWidth;
+ switch (m_Mode) {
+ case BeginTaper:
+ retval = beginTaperWidth * m_TaperMultiplier[inTaperIndex];
+ break;
+ case EndTaper:
+ retval = endTaperWidth * m_TaperMultiplier[inTaperIndex];
+ break;
+ default:
+ break;
+ }
+ return retval;
+ }
+};
+
+void PushLine(nvvector<SResultCubic> &ioResultVec, QT3DSVec2 inStart, QT3DSVec2 inStop,
+ QT3DSU32 inEquationIndex)
+{
+ QT3DSVec2 range = inStop - inStart;
+ ioResultVec.push_back(SResultCubic(inStart, inStart + range * .333f,
+ inStart + range * .666f, inStop, inEquationIndex,
+ 0.0f, 1.0f, LineLength(inStart, inStop)));
+}
+
+struct PathDirtyFlagValues
+{
+ enum Enum {
+ SourceData = 1,
+ PathType = 1 << 1,
+ Width = 1 << 2,
+ BeginTaper = 1 << 3,
+ EndTaper = 1 << 4,
+ CPUError = 1 << 5,
+ };
+};
+
+struct SPathDirtyFlags : public NVFlags<PathDirtyFlagValues::Enum>
+{
+ typedef NVFlags<PathDirtyFlagValues::Enum> TBase;
+ SPathDirtyFlags() {}
+ SPathDirtyFlags(int inFlags)
+ : TBase(static_cast<PathDirtyFlagValues::Enum>(inFlags))
+ {
+ }
+ void Clear()
+ {
+ *this = SPathDirtyFlags();
+ }
+};
+
+struct STaperInformation
+{
+ QT3DSF32 m_CapOffset;
+ QT3DSF32 m_CapOpacity;
+ QT3DSF32 m_CapWidth;
+
+ STaperInformation()
+ : m_CapOffset(0)
+ , m_CapOpacity(0)
+ , m_CapWidth(0)
+ {
+ }
+ STaperInformation(QT3DSF32 capOffset, QT3DSF32 capOpacity, QT3DSF32 capWidth)
+ : m_CapOffset(capOffset)
+ , m_CapOpacity(capOpacity)
+ , m_CapWidth(capWidth)
+ {
+ }
+
+ bool operator==(const STaperInformation &inOther) const
+ {
+ return m_CapOffset == inOther.m_CapOffset && m_CapOpacity == inOther.m_CapOpacity
+ && m_CapWidth == inOther.m_CapWidth;
+ }
+};
+
+template <typename TOptData>
+bool OptionEquals(const Option<TOptData> &lhs, const Option<TOptData> &rhs)
+{
+ if (lhs.hasValue() != rhs.hasValue())
+ return false;
+ if (lhs.hasValue())
+ return lhs.getValue() == rhs.getValue();
+ return true;
+}
+void OuterAdaptiveSubdivideBezierCurve(nvvector<SResultCubic> &ioResultVec,
+ nvvector<QT3DSF32> &keyPointVec,
+ SCubicBezierCurve inCurve, QT3DSF32 inLinearError,
+ QT3DSU32 inEquationIndex);
+
+void AdaptiveSubdivideBezierCurve(nvvector<SResultCubic> &ioResultVec,
+ SCubicBezierCurve &inCurve, QT3DSF32 inLinearError,
+ QT3DSU32 inEquationIndex, QT3DSF32 inTStart, QT3DSF32 inTStop);
+
+// Adaptively subdivide source data to produce m_PatchData.
+void AdaptiveSubdivideSourceData(NVConstDataRef<SPathAnchorPoint> inSourceData,
+ nvvector<SResultCubic> &ioResultVec,
+ nvvector<QT3DSF32> &keyPointVec, QT3DSF32 inLinearError)
+{
+ ioResultVec.clear();
+ if (inSourceData.size() < 2)
+ return;
+ // Assuming no attributes in the source data.
+ QT3DSU32 numEquations = (inSourceData.size() - 1);
+ for (QT3DSU32 idx = 0, end = numEquations; idx < end; ++idx) {
+ const SPathAnchorPoint &beginAnchor = inSourceData[idx];
+ const SPathAnchorPoint &endAnchor = inSourceData[idx + 1];
+
+ QT3DSVec2 anchor1(beginAnchor.m_Position);
+ QT3DSVec2 control1(IPathManagerCore::GetControlPointFromAngleDistance(
+ beginAnchor.m_Position, beginAnchor.m_OutgoingAngle,
+ beginAnchor.m_OutgoingDistance));
+
+ QT3DSVec2 control2(IPathManagerCore::GetControlPointFromAngleDistance(
+ endAnchor.m_Position, endAnchor.m_IncomingAngle,
+ endAnchor.m_IncomingDistance));
+ QT3DSVec2 anchor2(endAnchor.m_Position);
+
+ OuterAdaptiveSubdivideBezierCurve(
+ ioResultVec, keyPointVec,
+ SCubicBezierCurve(anchor1, control1, control2, anchor2), inLinearError, idx);
+ }
+}
+
+// The outer subdivide function topologically analyzes the curve to ensure that
+// the sign of the second derivative does not change, no inflection points.
+// Once that condition is held, then we proceed with a simple adaptive subdivision algorithm
+// until the curve is accurately approximated by a straight line.
+void OuterAdaptiveSubdivideBezierCurve(nvvector<SResultCubic> &ioResultVec,
+ nvvector<QT3DSF32> &keyPointVec,
+ SCubicBezierCurve inCurve, QT3DSF32 inLinearError,
+ QT3DSU32 inEquationIndex)
+{
+ // Step 1, find what type of curve we are dealing with and the inflection points.
+ keyPointVec.clear();
+ CurveType theCurveType = cubicDoublePoint(inCurve.m_Points, keyPointVec);
+
+ QT3DSF32 tStart = 0;
+ switch (theCurveType) {
+ case CT_POINT:
+ ioResultVec.push_back(SResultCubic(inCurve.m_Points[0], inCurve.m_Points[0],
+ inCurve.m_Points[0], inCurve.m_Points[0],
+ inEquationIndex, 0.0f, 1.0f, 0.0f));
+ return; // don't allow further recursion
+ case CT_LINE:
+ PushLine(ioResultVec, inCurve.m_Points[0], inCurve.m_Points[3], inEquationIndex);
+ return; // don't allow further recursion
+ case CT_CUSP:
+ case CT_LOOP:
+ case CT_SERPENTINE: {
+ // Break the curve at the inflection points if there is one. If there aren't
+ // inflection points
+ // the treat as linear (degenerate case that should not happen except in limiting
+ // ranges of floating point accuracy)
+ if (!keyPointVec.empty()) {
+ // It is not clear that the code results in a sorted vector,
+ // or a vector where all values are within the range of 0-1
+ if (keyPointVec.size() > 1)
+ eastl::sort(keyPointVec.begin(), keyPointVec.end());
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)keyPointVec.size();
+ idx < end && keyPointVec[idx] < 1.0f; ++idx) {
+ // We have a list of T values I believe sorted from beginning to end, we
+ // will create a set of bezier curves
+ // Since we split the curves, tValue is relative to tSTart, not 0.
+ QT3DSF32 range = 1.0f - tStart;
+ QT3DSF32 splitPoint = keyPointVec[idx] - tStart;
+ QT3DSF32 tValue = splitPoint / range;
+ if (tValue > 0.0f) {
+ eastl::pair<SCubicBezierCurve, SCubicBezierCurve> newCurves
+ = inCurve.SplitCubicBezierCurve(tValue);
+ AdaptiveSubdivideBezierCurve(ioResultVec, newCurves.first,
+ inLinearError, inEquationIndex, tStart,
+ splitPoint);
+ inCurve = newCurves.second;
+ tStart = splitPoint;
+ }
+ }
+ }
+ }
+ // fallthrough intentional
+ break;
+ // fallthrough intentional
+ case CT_QUADRATIC:
+ break;
+ }
+ AdaptiveSubdivideBezierCurve(ioResultVec, inCurve, inLinearError, inEquationIndex,
+ tStart, 1.0f);
+}
+
+static QT3DSF32 DistanceFromPointToLine(QT3DSVec2 inLineDxDy, QT3DSVec2 lineStart, QT3DSVec2 point)
+{
+ QT3DSVec2 pointToLineStart = lineStart - point;
+ return fabs((inLineDxDy.x * pointToLineStart.y) - (inLineDxDy.y * pointToLineStart.x));
+}
+
+// There are two options here. The first is to just subdivide below a given error
+// tolerance.
+// The second is to fit a quadratic to the curve and then precisely find the length of the
+// quadratic.
+// Obviously we are choosing the subdivide method at this moment but I think the fitting
+// method is probably more robust.
+QT3DSF32 LengthOfBezierCurve(SCubicBezierCurve &inCurve)
+{
+ // Find distance of control points from line. Note that both control points should be
+ // on same side of line else we have a serpentine which should have been removed by topological
+ // analysis.
+ QT3DSVec2 lineDxDy = inCurve.m_Points[3] - inCurve.m_Points[0];
+ QT3DSF32 c1Distance = DistanceFromPointToLine(
+ lineDxDy, inCurve.m_Points[0], inCurve.m_Points[1]);
+ QT3DSF32 c2Distance = DistanceFromPointToLine(
+ lineDxDy, inCurve.m_Points[0], inCurve.m_Points[2]);
+ const float lineTolerance = 100.0f; // error in world coordinates, squared.
+ if (c1Distance > lineTolerance || c2Distance > lineTolerance) {
+ eastl::pair<SCubicBezierCurve, SCubicBezierCurve> subdivCurve
+ = inCurve.SplitCubicBezierCurve(.5f);
+ return LengthOfBezierCurve(subdivCurve.first)
+ + LengthOfBezierCurve(subdivCurve.second);
+ } else {
+ return LineLength(inCurve.m_Points[0], inCurve.m_Points[3]);
+ }
+}
+
+// The assumption here is the the curve type is not cusp, loop, or serpentine.
+// It is either linear or it is a constant curve meaning we can use very simple means to
+// figure out the curvature. There is a possibility to use some math to figure out the point of
+// maximum curvature, where the second derivative will have a max value. This is probably not
+// necessary.
+void AdaptiveSubdivideBezierCurve(nvvector<SResultCubic> &ioResultVec,
+ SCubicBezierCurve &inCurve, QT3DSF32 inLinearError,
+ QT3DSU32 inEquationIndex, QT3DSF32 inTStart, QT3DSF32 inTStop)
+{
+ // Find distance of control points from line. Note that both control points should be
+ // on same side of line else we have a serpentine which should have been removed by topological
+ // analysis.
+ QT3DSVec2 lineDxDy = inCurve.m_Points[3] - inCurve.m_Points[0];
+ QT3DSF32 c1Distance = DistanceFromPointToLine(lineDxDy, inCurve.m_Points[0],
+ inCurve.m_Points[1]);
+ QT3DSF32 c2Distance = DistanceFromPointToLine(lineDxDy, inCurve.m_Points[0],
+ inCurve.m_Points[2]);
+ const float lineTolerance = inLinearError * inLinearError; // error in world coordinates
+ if (c1Distance > lineTolerance || c2Distance > lineTolerance) {
+ eastl::pair<SCubicBezierCurve, SCubicBezierCurve> subdivCurve
+ = inCurve.SplitCubicBezierCurve(.5f);
+ QT3DSF32 halfway = lerp(inTStart, inTStop, .5f);
+ AdaptiveSubdivideBezierCurve(ioResultVec, subdivCurve.first, inLinearError,
+ inEquationIndex, inTStart, halfway);
+ AdaptiveSubdivideBezierCurve(ioResultVec, subdivCurve.second, inLinearError,
+ inEquationIndex, halfway, inTStop);
+ } else {
+ ioResultVec.push_back(SResultCubic(inCurve.m_Points[0], inCurve.m_Points[1],
+ inCurve.m_Points[2], inCurve.m_Points[3],
+ inEquationIndex, inTStart, inTStop,
+ LengthOfBezierCurve(inCurve)));
+ }
+}
+}
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPathRenderContext.h b/src/Runtime/Source/UICRender/Include/UICRenderPathRenderContext.h
new file mode 100644
index 00000000..f1d6344b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPathRenderContext.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PATH_RENDER_CONTEXT_H
+#define UIC_RENDER_PATH_RENDER_CONTEXT_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "UICRenderShaderCache.h" //TShaderFeatureSet
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "UICRenderShaderKeys.h"
+#include "UICRenderableImage.h"
+
+namespace uic {
+namespace render {
+
+ struct SPathRenderContext
+ {
+ // The lights and camera will not change per layer,
+ // so that information can be set once for all the shaders.
+ NVConstDataRef<SLight *> m_Lights;
+ const SCamera &m_Camera;
+
+ // Per-object information.
+ const SPath &m_Path;
+ const QT3DSMat44 &m_ModelViewProjection;
+ const QT3DSMat44 &m_ModelMatrix; ///< model to world transformation
+ const QT3DSMat33 &m_NormalMatrix;
+
+ QT3DSF32 m_Opacity;
+ const SGraphObject &m_Material;
+ SShaderDefaultMaterialKey m_MaterialKey;
+ SRenderableImage *m_FirstImage;
+ QT3DSVec2 m_CameraVec;
+
+ bool m_EnableWireframe;
+ bool m_HasTransparency;
+ bool m_IsStroke;
+
+ SPathRenderContext(NVConstDataRef<SLight *> lights, const SCamera &cam, const SPath &p,
+ const QT3DSMat44 &mvp, const QT3DSMat44 &world, const QT3DSMat33 &nm,
+ QT3DSF32 inOpacity, const SGraphObject &inMaterial,
+ SShaderDefaultMaterialKey inMaterialKey, SRenderableImage *inFirstImage,
+ bool inWireframe, QT3DSVec2 inCameraVec, bool inHasTransparency,
+ bool inIsStroke)
+
+ : m_Lights(lights)
+ , m_Camera(cam)
+ , m_Path(p)
+ , m_ModelViewProjection(mvp)
+ , m_ModelMatrix(world)
+ , m_NormalMatrix(nm)
+ , m_Opacity(inOpacity)
+ , m_Material(inMaterial)
+ , m_MaterialKey(inMaterialKey)
+ , m_FirstImage(inFirstImage)
+ , m_CameraVec(inCameraVec)
+ , m_EnableWireframe(inWireframe)
+ , m_HasTransparency(inHasTransparency)
+ , m_IsStroke(inIsStroke)
+ {
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsRenderer.h b/src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsRenderer.h
new file mode 100644
index 00000000..b7b49e23
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsRenderer.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PIXEL_GRAPHICS_RENDERER_H
+#define UIC_RENDER_PIXEL_GRAPHICS_RENDERER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace uic {
+namespace render {
+
+ // Pixel graphics are graphics described in pixels.
+ // Colors are expected to be non-premultiplied, we use ROP
+ // hardware to do the alpha multiply into the color.
+ class IPixelGraphicsRenderer : public NVRefCounted
+ {
+ public:
+ // Renders the node to the current viewport.
+ virtual void Render(NVConstDataRef<SPGGraphObject *> inObjects) = 0;
+
+ static IPixelGraphicsRenderer &CreateRenderer(IUICRenderContext &ctx, IStringTable &strt);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsTypes.h b/src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsTypes.h
new file mode 100644
index 00000000..cff29d0d
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPixelGraphicsTypes.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PIXEL_GRAPHICS_TYPES_H
+#define UIC_RENDER_PIXEL_GRAPHICS_TYPES_H
+#include "UICRender.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec4.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DSOption.h"
+
+namespace uic {
+namespace render {
+
+ // Vector graphics with no scaling are pixel aligned with 0,0 being the bottom,left of the
+ // screen
+ // with coordinates increasing to the right and up. This is opposite most window systems but it
+ // preserves the normal openGL assumptions about viewports and positive Y going up in general.
+ struct SGTypes
+ {
+ enum Enum {
+ UnknownVGType = 0,
+ Layer,
+ Rect,
+ VertLine,
+ HorzLine,
+ };
+ };
+
+ struct SPGGraphObject
+ {
+ SGTypes::Enum m_Type;
+ SPGGraphObject(SGTypes::Enum inType);
+ };
+
+ struct SPGRect : public SPGGraphObject
+ {
+ QT3DSF32 m_Left;
+ QT3DSF32 m_Top;
+ QT3DSF32 m_Right;
+ QT3DSF32 m_Bottom;
+
+ QT3DSVec4 m_FillColor;
+
+ SPGRect();
+ };
+
+ struct SPGVertLine : public SPGGraphObject
+ {
+ QT3DSF32 m_X;
+ QT3DSF32 m_Top;
+ QT3DSF32 m_Bottom;
+ QT3DSVec4 m_LineColor;
+ void SetPosition(QT3DSF32 val) { m_X = val; }
+ void SetStart(QT3DSF32 val) { m_Bottom = val; }
+ void SetStop(QT3DSF32 val) { m_Top = val; }
+
+ SPGVertLine();
+ };
+
+ struct SPGHorzLine : public SPGGraphObject
+ {
+ QT3DSF32 m_Y;
+ QT3DSF32 m_Left;
+ QT3DSF32 m_Right;
+ QT3DSVec4 m_LineColor;
+ void SetPosition(QT3DSF32 val) { m_Y = val; }
+ void SetStart(QT3DSF32 val) { m_Left = val; }
+ void SetStop(QT3DSF32 val) { m_Right = val; }
+
+ SPGHorzLine();
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPlugin.h b/src/Runtime/Source/UICRender/Include/UICRenderPlugin.h
new file mode 100644
index 00000000..c973a549
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPlugin.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PLUGIN_H
+#define UIC_RENDER_PLUGIN_H
+#include "UICRender.h"
+#include "UICRenderPluginCInterface.h"
+#include "UICOffscreenRenderManager.h"
+#include "EASTL/utility.h"
+
+namespace uic {
+namespace render {
+
+ // UICRenderPluginPropertyValue.h
+ struct SRenderPropertyValueUpdate;
+
+ class IRenderPluginInstance : public IOffscreenRenderer
+ {
+ protected:
+ virtual ~IRenderPluginInstance() {}
+ public:
+ static const char *IRenderPluginOffscreenRendererType() { return "IRenderPluginInstance"; }
+ // If this render plugin has an instance ptr, get it. This is what will be used
+ // in lua whan an element's instance ptr is found.
+ virtual TRenderPluginInstancePtr GetRenderPluginInstance() = 0;
+ virtual void Update(NVConstDataRef<SRenderPropertyValueUpdate> updateBuffer) = 0;
+ virtual IRenderPluginClass &GetPluginClass() = 0;
+ virtual void CreateLuaProxy(lua_State *state) = 0;
+ };
+ struct RenderPluginPropertyValueTypes
+ {
+ enum Enum {
+ NoRenderPluginPropertyValue = 0,
+ Boolean,
+ Long,
+ Float,
+ String,
+ };
+ };
+
+ struct SRenderPluginPropertyTypes
+ {
+ enum Enum {
+ UnknownRenderPluginPropertyType = 0,
+ Float,
+ Vector3,
+ Vector2,
+ Color,
+ Boolean,
+ Long,
+ String,
+ };
+ };
+
+ struct SRenderPluginPropertyDeclaration
+ {
+ CRegisteredString m_Name;
+ SRenderPluginPropertyTypes::Enum m_Type;
+ // Filled in by the class, ignored if set on registered property
+ QT3DSU32 m_StartOffset;
+ SRenderPluginPropertyDeclaration()
+ : m_Type(SRenderPluginPropertyTypes::UnknownRenderPluginPropertyType)
+ {
+ }
+ SRenderPluginPropertyDeclaration(CRegisteredString n, SRenderPluginPropertyTypes::Enum t)
+ : m_Name(n)
+ , m_Type(t)
+ , m_StartOffset(0)
+ {
+ }
+ };
+
+ class IRenderPluginClass : public NVRefCounted
+ {
+ protected:
+ virtual ~IRenderPluginClass() {}
+ public:
+ virtual NVScopedRefCounted<IRenderPluginInstance> CreateInstance() = 0;
+ virtual void RegisterProperty(const SRenderPluginPropertyDeclaration &dec) = 0;
+ virtual NVConstDataRef<SRenderPluginPropertyDeclaration> GetRegisteredProperties() = 0;
+ // The declaration contains an offset
+ virtual SRenderPluginPropertyDeclaration
+ GetPropertyDeclaration(CRegisteredString inPropName) = 0;
+ // From which you can get the property name breakdown
+ virtual eastl::pair<CRegisteredString, RenderPluginPropertyValueTypes::Enum>
+ GetPropertyValueInfo(QT3DSU32 inIndex) = 0;
+ };
+
+ class IRenderPluginManager;
+
+ class IRenderPluginManagerCore : public NVRefCounted
+ {
+ public:
+ virtual void SetDllDir(const char *inDllDir) = 0;
+ virtual void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t *inProjectDir) = 0;
+ virtual IRenderPluginManager &GetRenderPluginManager(NVRenderContext &rc) = 0;
+
+ static IRenderPluginManagerCore &Create(NVFoundationBase &inFoundation,
+ IStringTable &strTable,
+ IInputStreamFactory &inFactory);
+ };
+
+ class IRenderPluginManager : public NVRefCounted
+ {
+ public:
+ virtual IRenderPluginClass *GetRenderPlugin(CRegisteredString inRelativePath) = 0;
+ virtual IRenderPluginClass *GetOrCreateRenderPlugin(CRegisteredString inRelativePath) = 0;
+ // Map a render plugin instance to this key. The instance's lifetime is managed by the
+ // manager so a client does not
+ // need to manage it.
+ virtual IRenderPluginInstance *
+ GetOrCreateRenderPluginInstance(CRegisteredString inRelativePath, void *inKey) = 0;
+
+ virtual void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap,
+ const char8_t *inProjectDir) const = 0;
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPluginCInterface.h b/src/Runtime/Source/UICRender/Include/UICRenderPluginCInterface.h
new file mode 100644
index 00000000..61a6710c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPluginCInterface.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_OBJECT_RENDER_PLUGIN_H
+#define UIC_OBJECT_RENDER_PLUGIN_H
+
+/*
+ * Below are the definitions required in order to write a render plugin for UIComposer.
+ * Please note that calling anything related to opengl is explicitly not allowed except
+ * during either the class gl resource initialization function or during render. Calling into
+ * openGL and especially changing GL state during any other function may produce corrupt
+ *rendering.
+ */
+
+#ifdef _cplusplus
+#extern "C" {
+#endif
+
+enum EUICRenderPluginPropertyTypes {
+ EUICRenderPluginPropertyTypeNone = 0,
+ EUICRenderPluginPropertyTypeLong = 1,
+ EUICRenderPluginPropertyTypeFloat = 2,
+ EUICRenderPluginPropertyTypeCharPtr = 3,
+};
+
+enum EUICRenderPluginDepthTypes {
+ EUICRenderPluginDepthTypeNoDepthBuffer = 0,
+ EUICRenderPluginDepthTypeDepth16, // 16 bit depth buffer
+ EUICRenderPluginDepthTypeDepth24, // 24 bit depth buffer
+ EUICRenderPluginDepthTypeDepth32, // 32 bit depth buffer
+};
+
+enum EUICRenderPluginTextureTypes {
+ EUICRenderPluginTextureTypeNoTexture = 0,
+ EUICRenderPluginTextureTypeRGBA8, // 32 bit format
+ EUICRenderPluginTextureTypeRGB8, // 24 bit format
+ EUICRenderPluginTextureTypeRGB565, // 16 bit format
+ EUICRenderPluginTextureTypeRGBA5551, // 16 bit format
+};
+
+enum EUICRenderPluginColorClearState {
+ EUICRenderPluginColorClearStateClearIsOptional = 0,
+ EUICRenderPluginColorClearStateDoNotClear,
+ EUICRenderPluginColorClearStateAlwaysClear,
+};
+
+enum EUICRenderPluginMSAALevel {
+ EUICRenderPluginMSAALevelNoMSAA = 0, // no MSAA, one also works.
+ EUICRenderPluginMSAALevelTwo = 2, // 2 samples
+ EUICRenderPluginMSAALevelFour = 4, // 4 samples
+ EUICRenderPluginMSAALevelEight = 8, // 8 samples
+};
+
+typedef long TUICBOOL;
+#define UICTRUE 1
+#define UICFALSE 0
+
+#define UIC_CURRENT_RENDER_PLUGIN_API_VERSION 2
+
+typedef void *TRenderPluginInstancePtr;
+typedef void *TRenderPluginClassPtr;
+
+// We will pass the componentized properties to the instance ptr.
+typedef struct _RenderPluginPropertyUpdate
+{
+ const char *m_PropName;
+ enum EUICRenderPluginPropertyTypes m_PropertyType;
+
+ // Is either a float or a long or a const char* depending on the property type.
+ // for specify types of properties, example code would be:
+ // float value = *((float*)&update.m_PropertyValue)
+ // long value = *((long*)&update.m_PropertyValue)
+ // char* value = (char*)update.m_PropertyValue
+ void *m_PropertyValue;
+} TRenderPluginPropertyUpdate;
+
+typedef struct _RenderPluginSurfaceDescription
+{
+ long m_Width;
+ long m_Height;
+ enum EUICRenderPluginDepthTypes m_DepthBuffer;
+ enum EUICRenderPluginTextureTypes m_ColorBuffer;
+ TUICBOOL m_HasStencilBuffer;
+ EUICRenderPluginMSAALevel m_MSAALevel;
+} TRenderPluginSurfaceDescription;
+
+typedef struct _UICVec2
+{
+ float x;
+ float y;
+} TUICVec2;
+
+typedef struct _NeedsRenderResult
+{
+ TUICBOOL HasChangedSinceLastFrame;
+ TUICBOOL HasTransparency;
+} TNeedsRenderResult;
+
+struct lua_State;
+
+/*
+ * Create a new instance object. Typename is the name of the plugin file, so for example
+ * gears.plugin generates 'gears' as a type name.
+ *
+ * Required API function.
+ *
+ */
+typedef TRenderPluginInstancePtr (*TCreateInstanceFunction)(TRenderPluginClassPtr cls,
+ const char *inTypeName);
+
+/*
+ * Implementations should leave a lua_table on top of the stack. This table is then used as the
+ *plugin's behavior
+ * proxy when handlers are called and when the runtime needs the behavior object associated
+ *with an element. This
+ * looks just like a behavior to the runtime so if plugins add functions to the table named
+ *'onInitialize' or
+ * 'onUpdate', these functions will get called just as if the plugin was an actual lua behavior.
+ *
+ * Optional API function.
+ */
+typedef void (*TCreateInstanceLuaProxy)(TRenderPluginClassPtr cls, TRenderPluginInstancePtr insPtr,
+ struct lua_State *state);
+
+/*
+ * Update the plugin instance with a list of property updates. Properties are broken down by
+ *component so for example
+ * a color property named leftColor will be broken down into 'leftColor.r', 'leftColor.g',
+ *'leftColor.b'. Vector
+ * properties are broken down into x,y,z components. The property string has a void* member
+ *that is the actual value
+ * or in a charPtr property's case it is the char*.
+ * Please see the comments for m_PropertyValue member of TRenderPluginPropertyUpdate struct.
+ *
+ * Optional API function.
+ */
+typedef void (*TUpdateInstanceFunction)(TRenderPluginClassPtr cls,
+ TRenderPluginInstancePtr instance,
+ TRenderPluginPropertyUpdate *updates, long numUpdates);
+
+/*
+ * Query used when the plugin is rendering to an image. Should return the desired
+ *specifications of the plugins
+ * render target.
+ * presScaleFactor - the presentation scale factor when the user has requested scale to fit to
+ *be used for the
+ * presentation.
+ *
+ * Required API function.
+ */
+typedef TRenderPluginSurfaceDescription (*TSurfaceQueryFunction)(TRenderPluginClassPtr cls,
+ TRenderPluginInstancePtr instance,
+ TUICVec2 presScaleFactor);
+
+/*
+ * Query used by the rendering system. Should return true if the plugin will render something
+ *different than it did
+ * the last time it rendered. This is used so that we can cache render results and also so that we
+ *can trigger the
+ * progressive AA algorithm in the case where nothing has changed.
+ *
+ * presScaleFactor - the presentation scale factor when the user has requested scale to fit to be
+ *used for the
+ * presentation.
+ *
+ * OpenGL state may be changed in this function.
+ *
+ * Optional API function, returns true by default.
+ */
+typedef TNeedsRenderResult (*TNeedsRenderFunction)(TRenderPluginClassPtr cls,
+ TRenderPluginInstancePtr instance,
+ TRenderPluginSurfaceDescription surface,
+ TUICVec2 presScaleFactor);
+
+/*
+ * Render plugin data.
+ * Do not assume the surface requested is the surface given; for some cases it will be but if
+ *the system has deemed it
+ * appropriate to render the plugin directly to the back buffer then the surface description
+ *presented could differ by
+ * quite a bit.
+ *
+ * presScaleFactor - is the presentation scale factor when the user has requested scale to fit
+ *to be used for the
+ * presentation.
+ * inClearColorBuffer - True if the plugin needs to clear the color buffer (when rendering to
+ *texture) else false
+ * (when rendering to back buffer).
+ *
+ * Function should return 'UICTRUE' the image produced by rendering contains transparency;
+ *either every pixel wasn't
+ * written to or it is desired for the plugin to blend with background objects. Else should
+ *return UICFALSE.
+ *
+ * Required API function.
+ */
+typedef void (*TRenderFunction)(TRenderPluginClassPtr cls, TRenderPluginInstancePtr instance,
+ TRenderPluginSurfaceDescription surface, TUICVec2 presScaleFactor,
+ EUICRenderPluginColorClearState inClearColorBuffer);
+
+/*
+ * Pick - handle a mouse pick into the plugin.
+ * Returns true if the pick was consumed, false otherwise.
+ *
+ * Option API function.
+ */
+typedef TUICBOOL (*TPickFunction)(TRenderPluginClassPtr cls, TRenderPluginInstancePtr instance,
+ TUICVec2 inMouse, TUICVec2 inViewport);
+
+/*
+ * Release a given instance of the plugin.
+ *
+ * Required API function.
+ */
+typedef void (*TReleaseInstanceFunction)(TRenderPluginClassPtr cls,
+ TRenderPluginInstancePtr instance);
+
+/*
+ * Get the plugin API version. This allows the runtime to account for API changes over time or
+ * refuse to load the plugin. Plugins should return UIC_CURRENT_RENDER_PLUGIN_API_VERSION
+ *
+ * Required API function.
+ */
+typedef long (*TGetAPIVersionFunction)(TRenderPluginClassPtr cls);
+
+/*
+ * Initialize the resources for the class. Implementing this allows UIComposer to move
+ * expensive initialization outside of the actual presentation run, thus allowing for
+ * a smoother experience during the presentation at the cost of longer startup times.
+ *
+ * - plugin path is the path to the .plugin xml file so that clients can find resources
+ * specific to their plugin relative to their .plugin file.
+ *
+ * OpenGL state may be changed in this function.
+ *
+ * Optional API function.
+ */
+typedef void (*TInitializeClassGLResourcesFunction)(TRenderPluginClassPtr cls,
+ const char *pluginPath);
+
+/*
+ * Release the class allocated with the create proc provided in the shared library.
+ *
+ * Required API function.
+ */
+typedef void (*TReleaseClassFunction)(TRenderPluginClassPtr cls);
+
+/*
+ * Structure returned form the create class function. Unimplemented functions should be left
+ *NULL.
+ */
+typedef struct _RenderPluginClass
+{
+ TRenderPluginClassPtr m_Class;
+
+ TGetAPIVersionFunction GetRenderPluginAPIVersion;
+ TInitializeClassGLResourcesFunction InitializeClassGLResources;
+ TReleaseClassFunction ReleaseClass;
+
+ TCreateInstanceFunction CreateInstance;
+ TCreateInstanceLuaProxy CreateInstanceLuaProxy;
+ TUpdateInstanceFunction UpdateInstance;
+ TSurfaceQueryFunction QueryInstanceRenderSurface;
+ TNeedsRenderFunction NeedsRenderFunction;
+ TRenderFunction RenderInstance;
+ TPickFunction Pick;
+ TReleaseInstanceFunction ReleaseInstance;
+
+} TRenderPluginClass;
+
+// We look for this function name in the shared library
+#define UIC_RENDER_PLUGIN_CREATE_CLASS_FUNCION_NAME "CreateRenderPlugin"
+
+/*
+ * Function signature we expect mapped to "CreateRenderPlugin". Example code:
+ *
+ extern "C" {
+
+#ifdef _WIN32
+#define PLUGIN_EXPORT_API __declspec(dllexport)
+#else
+#define PLUGIN_EXPORT_API
+#endif
+
+
+
+PLUGIN_EXPORT_API TRenderPluginClass CreateRenderPlugin( const char*)
+{
+ GearClass* classItem = (GearClass*)malloc( sizeof(GearClass) );
+ TRenderPluginClass retval;
+ memset( &retval, 0, sizeof( TRenderPluginClass ) );
+ retval.m_Class = classItem;
+ retval.GetRenderPluginAPIVersion = GetAPIVersion;
+ retval.CreateInstance = CreateInstance;
+ retval.CreateInstanceLuaProxy = CreateInstanceLuaProxy;
+ retval.UpdateInstance = UpdateInstance;
+ retval.QueryInstanceRenderSurface = QuerySurface;
+ retval.RenderInstance = Render;
+ retval.ReleaseInstance = ReleaseInstance;
+ retval.ReleaseClass = ReleaseClass;
+ return retval;
+}
+
+ * Required API function.
+ */
+
+typedef TRenderPluginClass (*TCreateRenderPluginClassFunction)(const char *inTypeName);
+
+#ifdef _cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPluginGraphObject.h b/src/Runtime/Source/UICRender/Include/UICRenderPluginGraphObject.h
new file mode 100644
index 00000000..5d80ab21
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPluginGraphObject.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PLUGIN_GRAPH_OBJECT_H
+#define UIC_RENDER_PLUGIN_GRAPH_OBJECT_H
+#include "UICRender.h"
+#include "UICRenderGraphObject.h"
+namespace uic {
+namespace render {
+
+ struct SRenderPlugin : public SGraphObject
+ {
+ CRegisteredString m_PluginPath;
+ NodeFlags m_Flags;
+
+ SRenderPlugin()
+ : SGraphObject(GraphObjectTypes::RenderPlugin)
+ {
+ }
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.Remap(m_PluginPath);
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderPluginPropertyValue.h b/src/Runtime/Source/UICRender/Include/UICRenderPluginPropertyValue.h
new file mode 100644
index 00000000..96b3dab1
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderPluginPropertyValue.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PLUGIN_PROPERTY_VALUE_H
+#define UIC_RENDER_PLUGIN_PROPERTY_VALUE_H
+#include "UICRender.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "UICRenderPlugin.h"
+
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<CRegisteredString>
+ {
+ void destruct(CRegisteredString &) {}
+ };
+}
+}
+
+namespace uic {
+namespace render {
+
+ template <typename TDatatype>
+ struct SRenderPluginPropertyValueTypeMap
+ {
+ };
+
+ template <>
+ struct SRenderPluginPropertyValueTypeMap<QT3DSI32>
+ {
+ enum { TypeMap = RenderPluginPropertyValueTypes::Long };
+ };
+ template <>
+ struct SRenderPluginPropertyValueTypeMap<QT3DSF32>
+ {
+ enum { TypeMap = RenderPluginPropertyValueTypes::Float };
+ };
+ template <>
+ struct SRenderPluginPropertyValueTypeMap<CRegisteredString>
+ {
+ enum { TypeMap = RenderPluginPropertyValueTypes::String };
+ };
+ template <>
+ struct SRenderPluginPropertyValueTypeMap<bool>
+ {
+ enum { TypeMap = RenderPluginPropertyValueTypes::Boolean };
+ };
+
+ struct SRenderPluginPropertyValueUnionTraits
+ {
+ typedef RenderPluginPropertyValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(CRegisteredString),
+ };
+
+ static TIdType getNoDataId()
+ {
+ return RenderPluginPropertyValueTypes::NoRenderPluginPropertyValue;
+ }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return (TIdType)SRenderPluginPropertyValueTypeMap<TDataType>::TypeMap;
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case RenderPluginPropertyValueTypes::String:
+ return inVisitor(*NVUnionCast<CRegisteredString *>(inData));
+ case RenderPluginPropertyValueTypes::Float:
+ return inVisitor(*NVUnionCast<QT3DSF32 *>(inData));
+ case RenderPluginPropertyValueTypes::Long:
+ return inVisitor(*NVUnionCast<QT3DSI32 *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case RenderPluginPropertyValueTypes::NoRenderPluginPropertyValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case RenderPluginPropertyValueTypes::String:
+ return inVisitor(*NVUnionCast<const CRegisteredString *>(inData));
+ case RenderPluginPropertyValueTypes::Float:
+ return inVisitor(*NVUnionCast<const QT3DSF32 *>(inData));
+ case RenderPluginPropertyValueTypes::Long:
+ return inVisitor(*NVUnionCast<const QT3DSI32 *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case RenderPluginPropertyValueTypes::NoRenderPluginPropertyValue:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SRenderPluginPropertyValueUnionTraits,
+ SRenderPluginPropertyValueUnionTraits::
+ TBufferSize>,
+ SRenderPluginPropertyValueUnionTraits::TBufferSize>
+ TRenderPluginPropertyValueUnionType;
+
+ struct SRenderPluginPropertyValue : public TRenderPluginPropertyValueUnionType
+ {
+ typedef TRenderPluginPropertyValueUnionType TBase;
+ SRenderPluginPropertyValue() {}
+ SRenderPluginPropertyValue(const CRegisteredString &str)
+ : TBase(str)
+ {
+ }
+ SRenderPluginPropertyValue(QT3DSI32 value)
+ : TBase(value)
+ {
+ }
+ SRenderPluginPropertyValue(QT3DSF32 value)
+ : TBase(value)
+ {
+ }
+ SRenderPluginPropertyValue(const SRenderPluginPropertyValue &other)
+ : TBase(static_cast<const TBase &>(other))
+ {
+ }
+ SRenderPluginPropertyValue &operator=(const SRenderPluginPropertyValue &other)
+ {
+ TBase::operator=(other);
+ return *this;
+ }
+ };
+
+ struct SRenderPropertyValueUpdate
+ {
+ // Should be the componentized name, so colors get .r .g .b appended
+ // and vectors get .x .y etc. This interface only updates a component at a time.
+ CRegisteredString m_PropertyName;
+ SRenderPluginPropertyValue m_Value;
+ SRenderPropertyValueUpdate() {}
+ SRenderPropertyValueUpdate(CRegisteredString str, const SRenderPluginPropertyValue &v)
+ : m_PropertyName(str)
+ , m_Value(v)
+ {
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderProfiler.h b/src/Runtime/Source/UICRender/Include/UICRenderProfiler.h
new file mode 100644
index 00000000..6b4d8471
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderProfiler.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PROFILER_H
+#define UIC_RENDER_PROFILER_H
+#include "UICRender.h"
+#include "EASTL/string.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/Qt3DSContainers.h"
+
+namespace uic {
+namespace render {
+
+ /**
+ * Opaque profiling system for rendering.
+ */
+ class IRenderProfiler : public NVRefCounted
+ {
+ public:
+ typedef nvvector<CRegisteredString> TStrIDVec;
+
+ protected:
+ virtual ~IRenderProfiler() {}
+
+ public:
+ /**
+ * @brief start a timer query
+ *
+ * @param[in] nameID Timer ID for tracking
+ * @param[in] absoluteTime If true the absolute GPU is queried
+ * @param[in] sync Do a sync before starting the timer
+ *
+ * @return no return
+ */
+ virtual void StartTimer(CRegisteredString &nameID, bool absoluteTime, bool sync) = 0;
+
+ /**
+ * @brief stop a timer query
+ *
+ * @param[in] nameID Timer ID for tracking
+ *
+ * @return no return
+ */
+ virtual void EndTimer(CRegisteredString &nameID) = 0;
+
+ /**
+ * @brief Get elapsed timer value. Not this is an averaged time over several frames
+ *
+ * @param[in] nameID Timer ID for tracking
+ *
+ * @return no return
+ */
+ virtual QT3DSF64 GetElapsedTime(const CRegisteredString &nameID) const = 0;
+
+ /**
+ * @brief Get ID list of tracked timers
+ *
+ * @return ID list
+ */
+ virtual const TStrIDVec &GetTimerIDs() const = 0;
+
+ /**
+ * @brief add vertex count to current counter
+ *
+ * @return
+ */
+ virtual void AddVertexCount(QT3DSU32 count) = 0;
+
+ /**
+ * @brief get current vertex count and reset
+ *
+ * @return
+ */
+ virtual QT3DSU32 GetAndResetTriangleCount() const = 0;
+
+ static IRenderProfiler &CreateGpuProfiler(NVFoundationBase &inFoundation,
+ IUICRenderContext &inContext,
+ NVRenderContext &inRenderContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderRay.h b/src/Runtime/Source/UICRender/Include/UICRenderRay.h
new file mode 100644
index 00000000..70447f7f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderRay.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_RAY_H
+#define UIC_RENDER_RAY_H
+
+#include "UICRender.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSMat44.h"
+#include "foundation/Qt3DSBounds3.h"
+
+namespace uic {
+namespace render {
+
+ struct SBasisPlanes
+ {
+ enum Enum {
+ XY = 0,
+ YZ,
+ XZ,
+ };
+ };
+
+ struct SRayIntersectionResult
+ {
+ QT3DSF32 m_RayLengthSquared; // Length of the ray in world coordinates for the hit.
+ QT3DSVec2 m_RelXY; // UV coords for further mouse picking against a offscreen-rendered object.
+ SRayIntersectionResult()
+ : m_RayLengthSquared(0)
+ , m_RelXY(0, 0)
+ {
+ }
+ SRayIntersectionResult(QT3DSF32 rl, QT3DSVec2 relxy)
+ : m_RayLengthSquared(rl)
+ , m_RelXY(relxy)
+ {
+ }
+ };
+
+ struct SRay
+ {
+ QT3DSVec3 m_Origin;
+ QT3DSVec3 m_Direction;
+ SRay()
+ : m_Origin(0, 0, 0)
+ , m_Direction(0, 0, 0)
+ {
+ }
+ SRay(const QT3DSVec3 &inOrigin, const QT3DSVec3 &inDirection)
+ : m_Origin(inOrigin)
+ , m_Direction(inDirection)
+ {
+ }
+ // If we are parallel, then no intersection of course.
+ Option<QT3DSVec3> Intersect(const NVPlane &inPlane) const;
+
+ Option<SRayIntersectionResult> IntersectWithAABB(const QT3DSMat44 &inGlobalTransform,
+ const NVBounds3 &inBounds,
+ bool inForceIntersect = false) const;
+
+ Option<QT3DSVec2> GetRelative(const QT3DSMat44 &inGlobalTransform, const NVBounds3 &inBounds,
+ SBasisPlanes::Enum inPlane) const;
+
+ Option<QT3DSVec2> GetRelativeXY(const QT3DSMat44 &inGlobalTransform,
+ const NVBounds3 &inBounds) const
+ {
+ return GetRelative(inGlobalTransform, inBounds, SBasisPlanes::XY);
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderRenderList.h b/src/Runtime/Source/UICRender/Include/UICRenderRenderList.h
new file mode 100644
index 00000000..55d669b2
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderRenderList.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_RENDER_LIST_H
+#define UIC_RENDER_RENDER_LIST_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace uic {
+namespace render {
+
+ class IRenderTask
+ {
+ public:
+ virtual ~IRenderTask() {}
+ virtual void Run() = 0;
+ };
+
+ /**
+ * The render list exists so that dependencies of the main render target can render themselves
+ * completely before the main render target renders. From Maxwell GPU's on, we have a tiled
+ * architecture. This tiling mechanism is sensitive to switching the render target, so we would
+ * really like to render completely to a single render target and then switch. With our layered
+ * render architecture, this is not very feasible unless dependencies render themselves before
+ * the
+ * main set of layers render themselves. Furthermore it benefits the overall software
+ * architecture
+ * to have a distinct split between the prepare for render step and the render step and using
+ * this
+ * render list allows us to avoid some level of repeated tree traversal at the cost of some
+ * minimal
+ * per frame allocation. The rules for using the render list are that you need to add yourself
+ * before
+ * your dependencies do; the list is iterated in reverse during RunRenderTasks. So a layer adds
+ * itself
+ * (if it is going to render offscreen) before it runs through its renderable list to prepare
+ * each object
+ * because it is during the renderable prepare traversale that subpresentations will get added
+ * by
+ * the offscreen render manager.
+ */
+ class IRenderList : public NVRefCounted
+ {
+ public:
+ // Called by the render context, do not call this.
+ virtual void BeginFrame() = 0;
+
+ // Next tell all sub render target rendering systems to add themselves to the render list.
+ // At this point
+ // we agree to *not* have rendered anything, no clears or anything so if you are caching
+ // render state and you detect nothing has changed it may not be necessary to swap egl
+ // buffers.
+ virtual QT3DSU32 AddRenderTask(IRenderTask &inTask) = 0;
+ virtual void DiscardRenderTask(QT3DSU32 inTaskId) = 0;
+ // This runs through the added tasks in reverse order. This is used to render dependencies
+ // before rendering to the main render target.
+ virtual void RunRenderTasks() = 0;
+
+ // We used to use GL state to pass information down the callstack.
+ // I have replaced those calls with this state here because that information
+ // controls how layers size themselves (which is quite a complicated process).
+ virtual void SetScissorTestEnabled(bool enabled) = 0;
+ virtual void SetScissorRect(NVRenderRect rect) = 0;
+ virtual void SetViewport(NVRenderRect rect) = 0;
+ virtual bool IsScissorTestEnabled() const = 0;
+ virtual NVRenderRect GetScissor() const = 0;
+ virtual NVRenderRect GetViewport() const = 0;
+
+ static IRenderList &CreateRenderList(NVFoundationBase &inFnd);
+ };
+
+ // Now for scoped property access.
+ template <typename TDataType>
+ struct SRenderListScopedProperty
+ : public qt3ds::render::NVRenderGenericScopedProperty<IRenderList, TDataType>
+ {
+ typedef qt3ds::render::NVRenderGenericScopedProperty<IRenderList, TDataType> TBaseType;
+ typedef typename TBaseType::TGetter TGetter;
+ typedef typename TBaseType::TSetter TSetter;
+ SRenderListScopedProperty(IRenderList &ctx, TGetter getter, TSetter setter)
+ : TBaseType(ctx, getter, setter)
+ {
+ }
+ SRenderListScopedProperty(IRenderList &ctx, TGetter getter, TSetter setter,
+ const TDataType &inNewValue)
+ : TBaseType(ctx, getter, setter, inNewValue)
+ {
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderRotationHelper.h b/src/Runtime/Source/UICRender/Include/UICRenderRotationHelper.h
new file mode 100644
index 00000000..d95bd829
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderRotationHelper.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_ROTATION_HELPER_H
+#define UIC_RENDER_ROTATION_HELPER_H
+#include "UICRender.h"
+#include "UICRenderNode.h"
+#include "EASTL/utility.h"
+
+namespace uic {
+namespace render {
+ /**
+ * Unfortunately we still use an XYZ-Euler rotation system. This means that identical
+ *rotations
+ * can be represented in various ways. We need to ensure that the value that we write in the
+ * inspector palette are reasonable, however, and to do this we need a least-distance function
+ * from two different xyz tuples.
+ */
+
+ struct SRotationHelper
+ {
+
+ // Attempt to go for negative values intead of large positive ones
+ // Goal is to keep the fabs of the angle low.
+ static QT3DSF32 ToMinimalAngle(QT3DSF32 value)
+ {
+ QT3DSF32 epsilon = (QT3DSF32)M_PI + .001f;
+ while (fabs(value) > epsilon) {
+ QT3DSF32 tpi = (QT3DSF32)(2.0f * M_PI);
+ if (value > 0.0f)
+ value -= tpi;
+ else
+ value += tpi;
+ }
+ return value;
+ }
+
+ /**
+ * Convert an angle to a canonical form. Return this canonical form.
+ *
+ * The canonical form is defined as:
+ * 1. XYZ all positive.
+ * 2. XYZ all less than 360.
+ *
+ * To do this we rely on two identities, the first is that given an angle, adding
+ * (or subtracting) pi from all three components does not change the angle.
+ *
+ * The second is the obvious one that adding or subtracting 2*pi from any single
+ * component does not change the angle.
+ *
+ * Note that this function works in radian space.
+ */
+ static QT3DSVec3 ToCanonicalFormStaticAxis(const QT3DSVec3 &inSrcAngle, QT3DSU32 inRotOrder)
+ {
+ // step 1 - reduce all components to less than 2*pi but greater than 0
+ QT3DSVec3 retval(inSrcAngle);
+ retval.x = ToMinimalAngle(retval.x);
+ retval.y = ToMinimalAngle(retval.y);
+ retval.z = ToMinimalAngle(retval.z);
+
+ // step 2 - if any two components are equal to or greater than pi
+ // then subtract pi from all three, then run two pi reduce again.
+
+ QT3DSU32 greaterThanPiSum = 0;
+ QT3DSF32 pi = (QT3DSF32)M_PI;
+ for (QT3DSU32 idx = 0; idx < 3; ++idx)
+ if (fabs(retval[idx]) >= pi)
+ greaterThanPiSum++;
+
+ if (greaterThanPiSum > 1) {
+ // For this identity to work, the middle axis angle needs to be subtracted from
+ // 180 instead of added to 180 because the previous axis *reversed* it.
+ QT3DSU32 theMiddleAxis = 0;
+
+ switch (inRotOrder) {
+ case EulOrdXYZs:
+ theMiddleAxis = 1;
+ break;
+ case EulOrdXZYs:
+ theMiddleAxis = 2;
+ break;
+ case EulOrdYXZs:
+ theMiddleAxis = 0;
+ break;
+ case EulOrdYZXs:
+ theMiddleAxis = 2;
+ break;
+ case EulOrdZYXs:
+ theMiddleAxis = 1;
+ break;
+ case EulOrdZXYs:
+ theMiddleAxis = 0;
+ break;
+ case EulOrdXYZr:
+ theMiddleAxis = 1;
+ break;
+ case EulOrdXZYr:
+ theMiddleAxis = 2;
+ break;
+ case EulOrdYXZr:
+ theMiddleAxis = 0;
+ break;
+ case EulOrdYZXr:
+ theMiddleAxis = 2;
+ break;
+ case EulOrdZYXr:
+ theMiddleAxis = 1;
+ break;
+ case EulOrdZXYr:
+ theMiddleAxis = 0;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ return inSrcAngle;
+ }
+ for (QT3DSU32 idx = 0; idx < 3; ++idx) {
+ if (idx == theMiddleAxis)
+ retval[idx] = pi - retval[idx];
+ else
+ retval[idx] = retval[idx] > 0.0f ? retval[idx] - pi : retval[idx] + pi;
+ }
+ }
+ return retval;
+ }
+
+ static QT3DSVec3 ToMinimalAngleDiff(const QT3DSVec3 inDiff)
+ {
+ return QT3DSVec3(ToMinimalAngle(inDiff.x), ToMinimalAngle(inDiff.y),
+ ToMinimalAngle(inDiff.z));
+ }
+
+ /**
+ * Given an old angle and a new angle, return an angle has the same rotational value
+ * as the new angle *but* is as close to the old angle as possible.
+ * Works in radian space. This function doesn't currently work for euler angles or
+ * with Euler angles with repeating axis.
+ */
+ static QT3DSVec3 ToNearestAngle(const QT3DSVec3 &inOldAngle, const QT3DSVec3 &inNewAngle,
+ QT3DSU32 inRotOrder)
+ {
+ switch (inRotOrder) {
+ case EulOrdXYZs:
+ case EulOrdXZYs:
+ case EulOrdYXZs:
+ case EulOrdYZXs:
+ case EulOrdZYXs:
+ case EulOrdZXYs:
+ case EulOrdXYZr:
+ case EulOrdXZYr:
+ case EulOrdYXZr:
+ case EulOrdYZXr:
+ case EulOrdZYXr:
+ case EulOrdZXYr: {
+ QT3DSVec3 oldA = ToCanonicalFormStaticAxis(inOldAngle, inRotOrder);
+ QT3DSVec3 newA = ToCanonicalFormStaticAxis(inNewAngle, inRotOrder);
+ QT3DSVec3 diff = newA - oldA;
+ return inOldAngle + ToMinimalAngleDiff(diff);
+ } break;
+ default:
+ return inNewAngle;
+ }
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderShaderCache.h b/src/Runtime/Source/UICRender/Include/UICRenderShaderCache.h
new file mode 100644
index 00000000..bbaefcb9
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderShaderCache.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SHADER_CACHE_H
+#define UIC_RENDER_SHADER_CACHE_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+namespace render {
+ struct ShaderCacheProgramFlagValues
+ {
+ enum Enum {
+ TessellationEnabled = 1 << 0, // tessellation enabled
+ GeometryShaderEnabled = 1 << 1, // geometry shader enabled
+ };
+ };
+ struct SShaderCacheProgramFlags : public NVFlags<ShaderCacheProgramFlagValues::Enum, QT3DSU32>
+ {
+ // tessellation enabled
+ void SetTessellationEnabled(bool inValue)
+ {
+ clearOrSet(inValue, ShaderCacheProgramFlagValues::TessellationEnabled);
+ }
+ bool IsTessellationEnabled() const
+ {
+ return this->operator&(ShaderCacheProgramFlagValues::TessellationEnabled);
+ }
+ // geometry shader enabled
+ void SetGeometryShaderEnabled(bool inValue)
+ {
+ clearOrSet(inValue, ShaderCacheProgramFlagValues::GeometryShaderEnabled);
+ }
+ bool IsGeometryShaderEnabled() const
+ {
+ return this->operator&(ShaderCacheProgramFlagValues::GeometryShaderEnabled);
+ }
+ };
+ // There are a number of macros used to turn on or off various features. This allows those
+ // features
+ // to be propagated into the shader cache's caching mechanism. They will be translated into
+ //#define name value where value is 1 or zero depending on if the feature is enabled or not.
+ struct SShaderPreprocessorFeature
+ {
+ CRegisteredString m_Name;
+ bool m_Enabled;
+ SShaderPreprocessorFeature()
+ : m_Enabled(false)
+ {
+ }
+ SShaderPreprocessorFeature(CRegisteredString name, bool val)
+ : m_Name(name)
+ , m_Enabled(val)
+ {
+ }
+ bool operator<(const SShaderPreprocessorFeature &inOther) const;
+ bool operator==(const SShaderPreprocessorFeature &inOther) const;
+ };
+
+ typedef NVConstDataRef<SShaderPreprocessorFeature> TShaderFeatureSet;
+
+ inline TShaderFeatureSet ShaderCacheNoFeatures() { return TShaderFeatureSet(); }
+
+ // Hash is dependent on the order of the keys; so make sure their order is consistent!!
+ size_t HashShaderFeatureSet(NVConstDataRef<SShaderPreprocessorFeature> inFeatureSet);
+
+ class IShaderCache : public NVRefCounted
+ {
+ protected:
+ virtual ~IShaderCache() {}
+ public:
+ // If directory is nonnull, then we attempt to load any shaders from shadercache.xml in
+ // inDirectory
+ // and save any new ones out to the same file. The shaders are marked by the gl version
+ // used when saving.
+ // If we can't open shadercache.xml from inDirectory for writing (at least), then we still
+ // consider the
+ // shadercache to be disabled.
+ // This call immediately blocks and attempts to load all applicable shaders from the
+ // shadercache.xml file in
+ // the given directory.
+ virtual void SetShaderCachePersistenceEnabled(const char8_t *inDirectory) = 0;
+ virtual bool IsShaderCachePersistenceEnabled() const = 0;
+ // It is up to the caller to ensure that inFeatures contains unique keys.
+ // It is also up the the caller to ensure the keys are ordered in some way.
+ virtual NVRenderShaderProgram *
+ GetProgram(CRegisteredString inKey,
+ NVConstDataRef<SShaderPreprocessorFeature> inFeatures) = 0;
+
+ // Replace an existing program in the cache for the same key with this program.
+ // The shaders returned by *CompileProgram functions can be released by this object
+ // due to ForceCompileProgram or SetProjectDirectory, so clients need to either not
+ // hold on to them or they need to addref/release them to ensure they still have
+ // access to them.
+ // The flags just tell us under what gl state to compile the program in order to hopefully
+ // reduce program compilations.
+ // It is up to the caller to ensure that inFeatures contains unique keys.
+ // It is also up the the caller to ensure the keys are ordered in some way.
+ virtual NVRenderShaderProgram *
+ ForceCompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag,
+ const char8_t *inTessCtrl, const char8_t *inTessEval,
+ const char8_t *inGeom, const SShaderCacheProgramFlags &inFlags,
+ TShaderFeatureSet inFeatures, bool separableProgram) = 0;
+
+ // It is up to the caller to ensure that inFeatures contains unique keys.
+ // It is also up the the caller to ensure the keys are ordered in some way.
+ virtual NVRenderShaderProgram *
+ CompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag,
+ const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom,
+ const SShaderCacheProgramFlags &inFlags, TShaderFeatureSet inFeatures,
+ bool separableProgram = false) = 0;
+
+ // Used to disable any shader compilation during loading. This is used when we are just
+ // interested in going from uia->binary
+ // and we expect to run on a headless server of sorts. See the UICCompiler project for its
+ // only current use case.
+ virtual void SetShaderCompilationEnabled(bool inEnableShaderCompilation) = 0;
+
+ // Upping the shader version invalidates all previous cache files.
+ static QT3DSU32 GetShaderVersion() { return 4; }
+ static const char8_t *GetShaderCacheFileName() { return "shadercache.xml"; }
+
+ static IShaderCache &CreateShaderCache(NVRenderContext &inContext,
+ IInputStreamFactory &inInputStreamFactory,
+ IPerfTimer &inPerfTimer);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGenerator.h b/src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGenerator.h
new file mode 100644
index 00000000..c19ef2ae
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGenerator.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SHADER_CODE_GENERATOR_H
+#define UIC_RENDER_SHADER_CODE_GENERATOR_H
+#include "UICRender.h"
+#include "foundation/Qt3DSContainers.h"
+#include "EASTL/string.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "UICRenderString.h"
+
+namespace uic {
+namespace render {
+
+ struct SEndlType
+ {
+ };
+ extern SEndlType Endl;
+
+ typedef std::basic_string<char> TStrType;
+ typedef eastl::pair<CRegisteredString, CRegisteredString> TParamPair;
+ typedef eastl::pair<CRegisteredString, TParamPair> TConstantBufferParamPair;
+ typedef nvvector<TConstantBufferParamPair> TConstantBufferParamArray;
+ typedef nvhash_map<CRegisteredString, CRegisteredString> TStrTableStrMap;
+
+ struct SShaderCodeGeneratorBase
+ {
+ enum Enum {
+ Unknown = 0,
+ Lighting,
+ ViewVector,
+ WorldNormal,
+ WorldPosition,
+ EnvMapReflection,
+ UVCoords,
+ };
+ IStringTable &m_StringTable;
+ nvhash_set<QT3DSU32> m_Codes; // set of enums we have included.
+ nvhash_set<CRegisteredString> m_Includes;
+ TStrTableStrMap m_Uniforms;
+ TStrTableStrMap m_ConstantBuffers;
+ TConstantBufferParamArray m_ConstantBufferParams;
+ TStrTableStrMap m_Attributes;
+ CRenderString m_FinalShaderBuilder;
+ TStrType m_CodeBuilder;
+ qt3ds::render::NVRenderContextType m_RenderContextType;
+
+ SShaderCodeGeneratorBase(IStringTable &inStringTable, NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType);
+ virtual TStrTableStrMap &GetVaryings() = 0;
+ void Begin();
+ void Append(const char *data);
+ // don't add the newline
+ void AppendPartial(const char *data);
+ void AddConstantBuffer(const char *name, const char *layout);
+ void AddConstantBufferParam(const char *cbName, const char *paramName, const char *type);
+ void AddUniform(const char *name, const char *type);
+ void AddUniform(TStrType &name, const char *type);
+ void AddAttribute(const char *name, const char *type);
+ void AddAttribute(TStrType &name, const char *type);
+ void AddVarying(const char *name, const char *type);
+ void AddVarying(TStrType &name, const char *type);
+ void AddLocalVariable(const char *name, const char *type, int tabCount = 1);
+ void AddLocalVariable(TStrType &name, const char *type, int tabCount = 1);
+ void AddInclude(const char *name);
+ void AddInclude(TStrType &name);
+ bool HasCode(Enum value);
+ void SetCode(Enum value);
+ void SetupWorldPosition();
+ void GenerateViewVector();
+ void GenerateWorldNormal();
+ void GenerateEnvMapReflection(SShaderCodeGeneratorBase &inFragmentShader);
+ void GenerateUVCoords();
+ void GenerateTextureSwizzle(NVRenderTextureSwizzleMode::Enum swizzleMode,
+ eastl::basic_string<char8_t> &texSwizzle,
+ eastl::basic_string<char8_t> &lookupSwizzle);
+ void GenerateShadedWireframeBase();
+ void AddLighting();
+ const char *BuildShaderSource();
+ SShaderCodeGeneratorBase &operator<<(const char *data);
+ SShaderCodeGeneratorBase &operator<<(const TStrType &data);
+ SShaderCodeGeneratorBase &operator<<(const SEndlType & /*data*/);
+
+ protected:
+ virtual void AddShaderItemMap(const char *itemType, const TStrTableStrMap &itemMap);
+ void AddShaderConstantBufferItemMap(const char *itemType, const TStrTableStrMap &cbMap,
+ TConstantBufferParamArray cbParamsArray);
+ };
+
+ struct SShaderVertexCodeGenerator : public SShaderCodeGeneratorBase
+ {
+ TStrTableStrMap m_Varyings;
+ SShaderVertexCodeGenerator(IStringTable &inStringTable, NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType);
+ TStrTableStrMap &GetVaryings() override;
+ };
+
+ struct SShaderTessControlCodeGenerator : public SShaderCodeGeneratorBase
+ {
+ SShaderVertexCodeGenerator &m_VertGenerator;
+ TStrTableStrMap m_Varyings;
+ SShaderTessControlCodeGenerator(SShaderVertexCodeGenerator &vert,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType);
+
+ void AddShaderItemMap(const char *itemType, const TStrTableStrMap &itemMap) override;
+ TStrTableStrMap &GetVaryings() override;
+ };
+
+ struct SShaderTessEvalCodeGenerator : public SShaderCodeGeneratorBase
+ {
+ SShaderTessControlCodeGenerator &m_TessControlGenerator;
+ bool m_hasGeometryStage;
+
+ SShaderTessEvalCodeGenerator(SShaderTessControlCodeGenerator &tc,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType);
+
+ void AddShaderItemMap(const char *itemType, const TStrTableStrMap &itemMap) override;
+ TStrTableStrMap &GetVaryings() override;
+ virtual void SetGeometryStage(bool hasGeometryStage);
+ };
+
+ struct SShaderGeometryCodeGenerator : public SShaderCodeGeneratorBase
+ {
+ SShaderVertexCodeGenerator &m_VertGenerator;
+ bool m_hasTessellationStage;
+
+ SShaderGeometryCodeGenerator(SShaderVertexCodeGenerator &vert, NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType);
+
+ void AddShaderItemMap(const char *itemType, const TStrTableStrMap &itemMap) override;
+ TStrTableStrMap &GetVaryings() override;
+ virtual void SetTessellationStage(bool hasTessellationStage);
+ };
+
+ struct SShaderFragmentCodeGenerator : public SShaderCodeGeneratorBase
+ {
+ SShaderVertexCodeGenerator &m_VertGenerator;
+ SShaderFragmentCodeGenerator(SShaderVertexCodeGenerator &vert, NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType);
+ TStrTableStrMap &GetVaryings() override;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGeneratorV2.h b/src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGeneratorV2.h
new file mode 100644
index 00000000..a7d17eb7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderShaderCodeGeneratorV2.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SHADER_CODE_GENERATOR_V2_H
+#define UIC_RENDER_SHADER_CODE_GENERATOR_V2_H
+#include "UICRenderShaderCodeGenerator.h"
+#include "UICRenderShaderCache.h"
+#include "foundation/Qt3DSFlags.h"
+
+#include <QtCore/qstring.h>
+
+namespace uic {
+namespace render {
+ // So far the generator is only useful for graphics stages,
+ // it doesn't seem useful for compute stages.
+ struct ShaderGeneratorStages
+ {
+ enum Enum {
+ Vertex = 1,
+ TessControl = 1 << 1,
+ TessEval = 1 << 2,
+ Geometry = 1 << 3,
+ Fragment = 1 << 4,
+ StageCount = 5,
+ };
+ };
+
+ typedef NVFlags<ShaderGeneratorStages::Enum, QT3DSU32> TShaderGeneratorStageFlags;
+
+ class IShaderStageGenerator
+ {
+ protected:
+ virtual ~IShaderStageGenerator() {}
+ public:
+ virtual void AddIncoming(const char8_t *name, const char8_t *type) = 0;
+ virtual void AddIncoming(const TStrType &name, const char8_t *type) = 0;
+
+ virtual void AddOutgoing(const char8_t *name, const char8_t *type) = 0;
+ virtual void AddOutgoing(const TStrType &name, const char8_t *type) = 0;
+
+ virtual void AddUniform(const char8_t *name, const char8_t *type) = 0;
+ virtual void AddUniform(const TStrType &name, const char8_t *type) = 0;
+
+ virtual void AddInclude(const char8_t *name) = 0;
+ virtual void AddInclude(const TStrType &name) = 0;
+ virtual void AddInclude(const QString &name) = 0;
+
+ virtual void AddFunction(const QString &functionName) = 0;
+
+ virtual void AddConstantBuffer(const char *name, const char *layout) = 0;
+ virtual void AddConstantBufferParam(const char *cbName, const char *paramName,
+ const char *type) = 0;
+
+ virtual IShaderStageGenerator &operator<<(const char *data) = 0;
+ virtual IShaderStageGenerator &operator<<(const TStrType &data) = 0;
+ virtual IShaderStageGenerator &operator<<(const SEndlType & /*data*/) = 0;
+ virtual void Append(const char *data) = 0;
+ virtual void AppendPartial(const char *data) = 0;
+
+ virtual ShaderGeneratorStages::Enum Stage() const = 0;
+ };
+
+ class IShaderProgramGenerator : public NVRefCounted
+ {
+ public:
+ static TShaderGeneratorStageFlags DefaultFlags()
+ {
+ return TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex
+ | ShaderGeneratorStages::Fragment);
+ }
+ virtual void BeginProgram(TShaderGeneratorStageFlags inEnabledStages = DefaultFlags()) = 0;
+
+ virtual TShaderGeneratorStageFlags GetEnabledStages() const = 0;
+
+ // get the stage or NULL if it has not been created.
+ virtual IShaderStageGenerator *GetStage(ShaderGeneratorStages::Enum inStage) = 0;
+
+ // Implicit call to end program.
+ virtual qt3ds::render::NVRenderShaderProgram *
+ CompileGeneratedShader(const char *inShaderName, const SShaderCacheProgramFlags &inFlags,
+ TShaderFeatureSet inFeatureSet, bool separableProgram = false) = 0;
+
+ qt3ds::render::NVRenderShaderProgram *CompileGeneratedShader(const char *inShaderName,
+ bool separableProgram = false)
+ {
+ return CompileGeneratedShader(inShaderName, SShaderCacheProgramFlags(),
+ TShaderFeatureSet(), separableProgram);
+ }
+
+ static IShaderProgramGenerator &CreateProgramGenerator(IUICRenderContext &inContext);
+
+ static void OutputParaboloidDepthVertex(IShaderStageGenerator &inGenerator);
+ // By convention, the local space result of the TE is stored in vec4 pos local variable.
+ // This function expects such state.
+ static void OutputParaboloidDepthTessEval(IShaderStageGenerator &inGenerator);
+ // Utilities shared among the various different systems.
+ static void OutputParaboloidDepthFragment(IShaderStageGenerator &inGenerator);
+
+ static void OutputCubeFaceDepthVertex(IShaderStageGenerator &inGenerator);
+ static void OutputCubeFaceDepthGeometry(IShaderStageGenerator &inGenerator);
+ static void OutputCubeFaceDepthFragment(IShaderStageGenerator &inGenerator);
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderShaderKeys.h b/src/Runtime/Source/UICRender/Include/UICRenderShaderKeys.h
new file mode 100644
index 00000000..71cf18ba
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderShaderKeys.h
@@ -0,0 +1,796 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SHADER_KEY_H
+#define UIC_RENDER_SHADER_KEY_H
+#include "UICRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "EASTL/string.h"
+#include "foundation/StringConversionImpl.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderTessModeValues.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace uic {
+namespace render {
+ // We have an ever expanding set of properties we like to hash into one or more 32 bit
+ // quantities.
+ // Furthermore we would like this set of properties to be convertable to string
+ // So the shader cache file itself is somewhat human readable/diagnosable.
+ // To do this we create a set of objects that act as properties to the master shader key.
+ // These objects are tallied in order to figure out their actual offset into the shader key's
+ // data store. They are also run through in order to create the string shader cache key.
+
+ struct SShaderKeyPropertyBase
+ {
+ const char *m_Name;
+ QT3DSU32 m_Offset;
+ SShaderKeyPropertyBase(const char *name = "")
+ : m_Name(name)
+ , m_Offset(0)
+ {
+ }
+ QT3DSU32 GetOffset() const { return m_Offset; }
+ void SetOffset(QT3DSU32 of) { m_Offset = of; }
+
+ template <QT3DSU32 TBitWidth>
+ QT3DSU32 GetMaskTemplate() const
+ {
+ QT3DSU32 bit = m_Offset % 32;
+ QT3DSU32 startValue = (1 << TBitWidth) - 1;
+ QT3DSU32 mask = startValue << bit;
+ return mask;
+ }
+
+ QT3DSU32 GetIdx() const { return m_Offset / 32; }
+ protected:
+ void InternalToString(eastl::string &ioStr, const char *inBuffer) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("=");
+ ioStr.append(inBuffer);
+ }
+
+ static void InternalToString(eastl::string &ioStr, const char *name, bool inValue)
+ {
+ if (inValue) {
+ ioStr.append(name);
+ ioStr.append("=");
+ ioStr.append(inValue ? "true" : "false");
+ }
+ }
+ };
+
+ struct SShaderKeyBoolean : public SShaderKeyPropertyBase
+ {
+ enum {
+ BitWidth = 1,
+ };
+
+ SShaderKeyBoolean(const char *name = "")
+ : SShaderKeyPropertyBase(name)
+ {
+ }
+
+ QT3DSU32 GetMask() const { return GetMaskTemplate<BitWidth>(); }
+ void SetValue(NVDataRef<QT3DSU32> inDataStore, bool inValue) const
+ {
+ QT3DSU32 idx = GetIdx();
+ QT3DS_ASSERT(inDataStore.size() > idx);
+ QT3DSU32 mask = GetMask();
+ QT3DSU32 &target = inDataStore[idx];
+ if (inValue == true) {
+ target = target | mask;
+ } else {
+ mask = ~mask;
+ target = target & mask;
+ }
+ }
+
+ bool GetValue(NVConstDataRef<QT3DSU32> inDataStore) const
+ {
+ QT3DSU32 idx = GetIdx();
+ QT3DSU32 mask = GetMask();
+ const QT3DSU32 &target = inDataStore[idx];
+ return (target & mask) ? true : false;
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ bool isHigh = GetValue(inKeySet);
+ InternalToString(ioStr, m_Name, isHigh);
+ }
+ };
+
+ template <QT3DSU32 TBitWidth>
+ struct SShaderKeyUnsigned : public SShaderKeyPropertyBase
+ {
+ enum {
+ BitWidth = TBitWidth,
+ };
+ SShaderKeyUnsigned(const char *name = "")
+ : SShaderKeyPropertyBase(name)
+ {
+ }
+ QT3DSU32 GetMask() const { return GetMaskTemplate<BitWidth>(); }
+ void SetValue(NVDataRef<QT3DSU32> inDataStore, QT3DSU32 inValue) const
+ {
+ QT3DSU32 startValue = (1 << TBitWidth) - 1;
+ // Ensure inValue is within range of bit width.
+ inValue = inValue & startValue;
+ QT3DSU32 bit = m_Offset % 32;
+ QT3DSU32 mask = GetMask();
+ QT3DSU32 idx = GetIdx();
+ inValue = inValue << bit;
+ QT3DSU32 &target = inDataStore[idx];
+ // Get rid of existing value
+ QT3DSU32 inverseMask = ~mask;
+ target = target & inverseMask;
+ target = target | inValue;
+ }
+
+ QT3DSU32 GetValue(NVConstDataRef<QT3DSU32> inDataStore) const
+ {
+ QT3DSU32 idx = GetIdx();
+ QT3DSU32 bit = m_Offset % 32;
+ QT3DSU32 mask = GetMask();
+ const QT3DSU32 &target = inDataStore[idx];
+
+ QT3DSU32 retval = target & mask;
+ retval = retval >> bit;
+ return retval;
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ QT3DSU32 value = GetValue(inKeySet);
+ char buf[64];
+ StringConversion<QT3DSU32>().ToStr(value, toDataRef(buf, 64));
+ InternalToString(ioStr, buf);
+ }
+ };
+
+ struct SShaderKeyTessellation : public SShaderKeyUnsigned<4>
+ {
+ enum TessellationBits {
+ noTessellation = 1 << 0,
+ linearTessellation = 1 << 1,
+ phongTessellation = 1 << 2,
+ npatchTessellation = 1 << 3
+ };
+
+ SShaderKeyTessellation(const char *name = "")
+ : SShaderKeyUnsigned<4>(name)
+ {
+ }
+
+ bool GetBitValue(TessellationBits swizzleBit, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return (GetValue(inKeySet) & swizzleBit) ? true : false;
+ }
+
+ void SetBitValue(TessellationBits swizzleBit, bool inValue, NVDataRef<QT3DSU32> inKeySet)
+ {
+ QT3DSU32 theValue = GetValue(inKeySet);
+ QT3DSU32 mask = swizzleBit;
+ if (inValue) {
+ theValue = theValue | mask;
+ } else {
+ mask = ~mask;
+ theValue = theValue & mask;
+ }
+ SetValue(inKeySet, theValue);
+ }
+
+ void SetTessellationMode(NVDataRef<QT3DSU32> inKeySet, TessModeValues::Enum tessellationMode,
+ bool val)
+ {
+ switch (tessellationMode) {
+ case TessModeValues::NoTess:
+ SetBitValue(noTessellation, val, inKeySet);
+ break;
+ case TessModeValues::TessLinear:
+ SetBitValue(linearTessellation, val, inKeySet);
+ break;
+ case TessModeValues::TessNPatch:
+ SetBitValue(npatchTessellation, val, inKeySet);
+ break;
+ case TessModeValues::TessPhong:
+ SetBitValue(phongTessellation, val, inKeySet);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ bool IsNoTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(noTessellation, inKeySet);
+ }
+ void SetNoTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(noTessellation, val, inKeySet);
+ }
+
+ bool IsLinearTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(linearTessellation, inKeySet);
+ }
+ void SetLinearTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(linearTessellation, val, inKeySet);
+ }
+
+ bool IsNPatchTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(npatchTessellation, inKeySet);
+ }
+ void SetNPatchTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(npatchTessellation, val, inKeySet);
+ }
+
+ bool IsPhongTessellation(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(phongTessellation, inKeySet);
+ }
+ void SetPhongTessellation(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(phongTessellation, val, inKeySet);
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("={");
+ InternalToString(ioStr, "noTessellation", IsNoTessellation(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "linearTessellation", IsLinearTessellation(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "npatchTessellation", IsNPatchTessellation(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "phongTessellation", IsPhongTessellation(inKeySet));
+ ioStr.append("}");
+ }
+ };
+
+ struct SShaderKeyTextureSwizzle : public SShaderKeyUnsigned<5>
+ {
+ enum TextureSwizzleBits {
+ noSwizzle = 1 << 0,
+ L8toR8 = 1 << 1,
+ A8toR8 = 1 << 2,
+ L8A8toRG8 = 1 << 3,
+ L16toR16 = 1 << 4
+ };
+
+ SShaderKeyTextureSwizzle(const char *name = "")
+ : SShaderKeyUnsigned<5>(name)
+ {
+ }
+
+ bool GetBitValue(TextureSwizzleBits swizzleBit, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return (GetValue(inKeySet) & swizzleBit) ? true : false;
+ }
+
+ void SetBitValue(TextureSwizzleBits swizzleBit, bool inValue, NVDataRef<QT3DSU32> inKeySet)
+ {
+ QT3DSU32 theValue = GetValue(inKeySet);
+ QT3DSU32 mask = swizzleBit;
+ if (inValue) {
+ theValue = theValue | mask;
+ } else {
+ mask = ~mask;
+ theValue = theValue & mask;
+ }
+ SetValue(inKeySet, theValue);
+ }
+
+ void SetSwizzleMode(NVDataRef<QT3DSU32> inKeySet, NVRenderTextureSwizzleMode::Enum swizzleMode,
+ bool val)
+ {
+ switch (swizzleMode) {
+ case NVRenderTextureSwizzleMode::NoSwizzle:
+ SetBitValue(noSwizzle, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::L8toR8:
+ SetBitValue(L8toR8, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::A8toR8:
+ SetBitValue(A8toR8, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::L8A8toRG8:
+ SetBitValue(L8A8toRG8, val, inKeySet);
+ break;
+ case NVRenderTextureSwizzleMode::L16toR16:
+ SetBitValue(L16toR16, val, inKeySet);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ bool IsNoSwizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(noSwizzle, inKeySet);
+ }
+ void SetNoSwizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(noSwizzle, val, inKeySet);
+ }
+
+ bool IsL8Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(L8toR8, inKeySet);
+ }
+ void SetL8Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(L8toR8, val, inKeySet);
+ }
+
+ bool IsA8Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(A8toR8, inKeySet);
+ }
+ void SetA8Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(A8toR8, val, inKeySet);
+ }
+
+ bool IsL8A8Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(L8A8toRG8, inKeySet);
+ }
+ void SetL8A8Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(L8A8toRG8, val, inKeySet);
+ }
+
+ bool IsL16Swizzled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(L16toR16, inKeySet);
+ }
+ void SetL16Swizzled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(L16toR16, val, inKeySet);
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("={");
+ InternalToString(ioStr, "noswizzle", IsNoSwizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "l8swizzle", IsL8Swizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "a8swizzle", IsA8Swizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "l8a8swizzle", IsL8A8Swizzled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "l16swizzle", IsL16Swizzled(inKeySet));
+ ioStr.append("}");
+ }
+ };
+
+ struct SShaderKeyImageMap : public SShaderKeyUnsigned<5>
+ {
+ enum ImageMapBits {
+ Enabled = 1 << 0,
+ EnvMap = 1 << 1,
+ LightProbe = 1 << 2,
+ InvertUV = 1 << 3,
+ Premultiplied = 1 << 4,
+ };
+
+ SShaderKeyImageMap(const char *name = "")
+ : SShaderKeyUnsigned<5>(name)
+ {
+ }
+
+ bool GetBitValue(ImageMapBits imageBit, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return (GetValue(inKeySet) & imageBit) ? true : false;
+ }
+
+ void SetBitValue(ImageMapBits imageBit, bool inValue, NVDataRef<QT3DSU32> inKeySet)
+ {
+ QT3DSU32 theValue = GetValue(inKeySet);
+ QT3DSU32 mask = imageBit;
+ if (inValue) {
+ theValue = theValue | mask;
+ } else {
+ mask = ~mask;
+ theValue = theValue & mask;
+ }
+ SetValue(inKeySet, theValue);
+ }
+
+ bool IsEnabled(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(Enabled, inKeySet);
+ }
+ void SetEnabled(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(Enabled, val, inKeySet);
+ }
+
+ bool IsEnvMap(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(EnvMap, inKeySet);
+ }
+ void SetEnvMap(NVDataRef<QT3DSU32> inKeySet, bool val) { SetBitValue(EnvMap, val, inKeySet); }
+
+ bool IsLightProbe(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(LightProbe, inKeySet);
+ }
+ void SetLightProbe(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(LightProbe, val, inKeySet);
+ }
+
+ bool IsInvertUVMap(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(InvertUV, inKeySet);
+ }
+ void SetInvertUVMap(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(InvertUV, val, inKeySet);
+ }
+
+ bool IsPremultiplied(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return GetBitValue(Premultiplied, inKeySet);
+ }
+ void SetPremultiplied(NVDataRef<QT3DSU32> inKeySet, bool val)
+ {
+ SetBitValue(Premultiplied, val, inKeySet);
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("={");
+ InternalToString(ioStr, "enabled", IsEnabled(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "envMap", IsEnvMap(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "lightProbe", IsLightProbe(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "invertUV", IsInvertUVMap(inKeySet));
+ ioStr.append(";");
+ InternalToString(ioStr, "premultiplied", IsPremultiplied(inKeySet));
+ ioStr.append("}");
+ }
+ };
+
+ struct SShaderKeySpecularModel : SShaderKeyUnsigned<2>
+ {
+ SShaderKeySpecularModel(const char *name = "")
+ : SShaderKeyUnsigned<2>(name)
+ {
+ }
+
+ void SetSpecularModel(NVDataRef<QT3DSU32> inKeySet,
+ uic::render::DefaultMaterialSpecularModel::Enum inModel)
+ {
+ SetValue(inKeySet, (QT3DSU32)inModel);
+ }
+
+ uic::render::DefaultMaterialSpecularModel::Enum
+ GetSpecularModel(NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ return static_cast<uic::render::DefaultMaterialSpecularModel::Enum>(GetValue(inKeySet));
+ }
+
+ void ToString(eastl::string &ioStr, NVConstDataRef<QT3DSU32> inKeySet) const
+ {
+ ioStr.append(m_Name);
+ ioStr.append("=");
+ switch (GetSpecularModel(inKeySet)) {
+ case DefaultMaterialSpecularModel::KGGX:
+ ioStr.append("KGGX");
+ break;
+ case DefaultMaterialSpecularModel::KWard:
+ ioStr.append("KWard");
+ break;
+ case DefaultMaterialSpecularModel::Default:
+ ioStr.append("Default");
+ break;
+ }
+ ioStr.append(";");
+ }
+ };
+
+ struct SShaderDefaultMaterialKeyProperties
+ {
+ enum {
+ LightCount = 7,
+ };
+ enum ImageMapNames {
+ DiffuseMap0 = 0,
+ DiffuseMap1,
+ DiffuseMap2,
+ EmissiveMap,
+ EmissiveMap2,
+ SpecularMap,
+ OpacityMap,
+ BumpMap,
+ SpecularAmountMap,
+ NormalMap,
+ DisplacementMap,
+ TranslucencyMap,
+ LightmapIndirect,
+ LightmapRadiosity,
+ LightmapShadow,
+ ImageMapCount
+ };
+
+ SShaderKeyBoolean m_HasLighting;
+ SShaderKeyBoolean m_HasIbl;
+ SShaderKeyUnsigned<3> m_LightCount;
+ SShaderKeyBoolean m_LightFlags[LightCount];
+ SShaderKeyBoolean m_LightAreaFlags[LightCount];
+ SShaderKeyBoolean m_LightShadowFlags[LightCount];
+ SShaderKeyBoolean m_SpecularEnabled;
+ SShaderKeyBoolean m_FresnelEnabled;
+ SShaderKeySpecularModel m_SpecularModel;
+ SShaderKeyImageMap m_ImageMaps[ImageMapCount];
+ SShaderKeyTextureSwizzle m_TextureSwizzle[ImageMapCount];
+ SShaderKeyTessellation m_TessellationMode;
+ SShaderKeyBoolean m_HasSkinning;
+ SShaderKeyBoolean m_WireframeMode;
+
+ SShaderDefaultMaterialKeyProperties()
+ : m_HasLighting("hasLighting")
+ , m_HasIbl("hasIbl")
+ , m_LightCount("lightCount")
+ , m_SpecularEnabled("specularEnabled")
+ , m_FresnelEnabled("fresnelEnabled")
+ , m_SpecularModel("specularModel")
+ , m_TessellationMode("tessellationMode")
+ , m_HasSkinning("hasSkinning")
+ , m_WireframeMode("wireframeMode")
+ {
+ m_LightFlags[0].m_Name = "light0HasPosition";
+ m_LightFlags[1].m_Name = "light1HasPosition";
+ m_LightFlags[2].m_Name = "light2HasPosition";
+ m_LightFlags[3].m_Name = "light3HasPosition";
+ m_LightFlags[4].m_Name = "light4HasPosition";
+ m_LightFlags[5].m_Name = "light5HasPosition";
+ m_LightFlags[6].m_Name = "light6HasPosition";
+ m_LightAreaFlags[0].m_Name = "light0HasArea";
+ m_LightAreaFlags[1].m_Name = "light1HasArea";
+ m_LightAreaFlags[2].m_Name = "light2HasArea";
+ m_LightAreaFlags[3].m_Name = "light3HasArea";
+ m_LightAreaFlags[4].m_Name = "light4HasArea";
+ m_LightAreaFlags[5].m_Name = "light5HasArea";
+ m_LightAreaFlags[6].m_Name = "light6HasArea";
+ m_LightShadowFlags[0].m_Name = "light0HasShadow";
+ m_LightShadowFlags[1].m_Name = "light1HasShadow";
+ m_LightShadowFlags[2].m_Name = "light2HasShadow";
+ m_LightShadowFlags[3].m_Name = "light3HasShadow";
+ m_LightShadowFlags[4].m_Name = "light4HasShadow";
+ m_LightShadowFlags[5].m_Name = "light5HasShadow";
+ m_LightShadowFlags[6].m_Name = "light6HasShadow";
+ m_ImageMaps[0].m_Name = "diffuseMap0";
+ m_ImageMaps[1].m_Name = "diffuseMap1";
+ m_ImageMaps[2].m_Name = "diffuseMap2";
+ m_ImageMaps[3].m_Name = "emissiveMap";
+ m_ImageMaps[4].m_Name = "emissiveMap2";
+ m_ImageMaps[5].m_Name = "specularMap";
+ m_ImageMaps[6].m_Name = "opacityMap";
+ m_ImageMaps[7].m_Name = "bumpMap";
+ m_ImageMaps[8].m_Name = "specularAmountMap";
+ m_ImageMaps[9].m_Name = "normalMap";
+ m_ImageMaps[10].m_Name = "displacementMap";
+ m_ImageMaps[11].m_Name = "translucencyMap";
+ m_ImageMaps[12].m_Name = "lightmapIndirect";
+ m_ImageMaps[13].m_Name = "lightmapRadiosity";
+ m_ImageMaps[14].m_Name = "lightmapShadow";
+ m_TextureSwizzle[0].m_Name = "diffuseMap0_swizzle";
+ m_TextureSwizzle[1].m_Name = "diffuseMap1_swizzle";
+ m_TextureSwizzle[2].m_Name = "diffuseMap2_swizzle";
+ m_TextureSwizzle[3].m_Name = "emissiveMap_swizzle";
+ m_TextureSwizzle[4].m_Name = "emissiveMap2_swizzle";
+ m_TextureSwizzle[5].m_Name = "specularMap_swizzle";
+ m_TextureSwizzle[6].m_Name = "opacityMap_swizzle";
+ m_TextureSwizzle[7].m_Name = "bumpMap_swizzle";
+ m_TextureSwizzle[8].m_Name = "specularAmountMap_swizzle";
+ m_TextureSwizzle[9].m_Name = "normalMap_swizzle";
+ m_TextureSwizzle[10].m_Name = "displacementMap_swizzle";
+ m_TextureSwizzle[11].m_Name = "translucencyMap_swizzle";
+ m_TextureSwizzle[12].m_Name = "lightmapIndirect_swizzle";
+ m_TextureSwizzle[13].m_Name = "lightmapRadiosity_swizzle";
+ m_TextureSwizzle[14].m_Name = "lightmapShadow_swizzle";
+ SetPropertyOffsets();
+ }
+
+ template <typename TVisitor>
+ void VisitProperties(TVisitor &inVisitor)
+ {
+ inVisitor.Visit(m_HasLighting);
+ inVisitor.Visit(m_HasIbl);
+ inVisitor.Visit(m_LightCount);
+
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
+ inVisitor.Visit(m_LightFlags[idx]);
+ }
+
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
+ inVisitor.Visit(m_LightAreaFlags[idx]);
+ }
+
+ for (QT3DSU32 idx = 0, end = LightCount; idx < end; ++idx) {
+ inVisitor.Visit(m_LightShadowFlags[idx]);
+ }
+
+ inVisitor.Visit(m_SpecularEnabled);
+ inVisitor.Visit(m_FresnelEnabled);
+ inVisitor.Visit(m_SpecularModel);
+
+ for (QT3DSU32 idx = 0, end = ImageMapCount; idx < end; ++idx) {
+ inVisitor.Visit(m_ImageMaps[idx]);
+ inVisitor.Visit(m_TextureSwizzle[idx]);
+ }
+
+ inVisitor.Visit(m_TessellationMode);
+ inVisitor.Visit(m_HasSkinning);
+ inVisitor.Visit(m_WireframeMode);
+ }
+
+ struct SOffsetVisitor
+ {
+ QT3DSU32 m_Offset;
+ SOffsetVisitor()
+ : m_Offset(0)
+ {
+ }
+ template <typename TPropType>
+ void Visit(TPropType &inProp)
+ {
+ // if we cross the 32 bit border we just move
+ // to the next dword.
+ // This cost a few extra bits but prevents tedious errors like
+ // loosing shader key bits because they got moved beyond the 32 border
+ QT3DSU32 bit = m_Offset % 32;
+ if (bit + TPropType::BitWidth > 31) {
+ m_Offset += 32 - bit;
+ }
+
+ inProp.SetOffset(m_Offset);
+ m_Offset += TPropType::BitWidth;
+ }
+ };
+
+ void SetPropertyOffsets()
+ {
+ SOffsetVisitor visitor;
+ VisitProperties(visitor);
+ // If this assert fires, then the default material key needs more bits.
+ QT3DS_ASSERT(visitor.m_Offset < 224);
+ }
+ };
+
+ struct SShaderDefaultMaterialKey
+ {
+ enum {
+ DataBufferSize = 7,
+ };
+ QT3DSU32 m_DataBuffer[DataBufferSize];
+ size_t m_FeatureSetHash;
+
+ SShaderDefaultMaterialKey(size_t inFeatureSetHash)
+ : m_FeatureSetHash(inFeatureSetHash)
+ {
+ for (size_t idx = 0; idx < DataBufferSize; ++idx)
+ m_DataBuffer[idx] = 0;
+ }
+
+ SShaderDefaultMaterialKey()
+ : m_FeatureSetHash(0)
+ {
+ for (size_t idx = 0; idx < DataBufferSize; ++idx)
+ m_DataBuffer[idx] = 0;
+ }
+
+ size_t hash() const
+ {
+ size_t retval = 0;
+ for (size_t idx = 0; idx < DataBufferSize; ++idx)
+ retval = retval ^ eastl::hash<QT3DSU32>()(m_DataBuffer[idx]);
+ return retval ^ m_FeatureSetHash;
+ }
+
+ bool operator==(const SShaderDefaultMaterialKey &other) const
+ {
+ bool retval = true;
+ for (size_t idx = 0; idx < DataBufferSize && retval; ++idx)
+ retval = m_DataBuffer[idx] == other.m_DataBuffer[idx];
+ return retval && m_FeatureSetHash == other.m_FeatureSetHash;
+ }
+
+ // Cast operators to make getting properties easier.
+ operator NVDataRef<QT3DSU32>() { return toDataRef(m_DataBuffer, DataBufferSize); }
+
+ operator NVConstDataRef<QT3DSU32>() const
+ {
+ return toConstDataRef(m_DataBuffer, DataBufferSize);
+ }
+
+ struct SStringVisitor
+ {
+ eastl::string &m_Str;
+ NVConstDataRef<QT3DSU32> m_KeyStore;
+ SStringVisitor(eastl::string &s, NVConstDataRef<QT3DSU32> ks)
+ : m_Str(s)
+ , m_KeyStore(ks)
+ {
+ }
+ template <typename TPropType>
+ void Visit(const TPropType &prop)
+ {
+ QT3DSU32 originalSize = m_Str.size();
+ if (m_Str.size())
+ m_Str.append(";");
+ prop.ToString(m_Str, m_KeyStore);
+ // if the only thing we added was the semicolon
+ // then nuke the semicolon
+ if (originalSize && m_Str.size() == originalSize + 1)
+ m_Str.resize(originalSize);
+ }
+ };
+
+ void ToString(eastl::string &ioString,
+ SShaderDefaultMaterialKeyProperties &inProperties) const
+ {
+ SStringVisitor theVisitor(ioString, *this);
+ inProperties.VisitProperties(theVisitor);
+ }
+ };
+}
+}
+
+namespace eastl {
+template <>
+struct hash<uic::render::SShaderDefaultMaterialKey>
+{
+ size_t operator()(const uic::render::SShaderDefaultMaterialKey &key) const
+ {
+ return key.hash();
+ }
+};
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderShadowMap.h b/src/Runtime/Source/UICRender/Include/UICRenderShadowMap.h
new file mode 100644
index 00000000..d37da5b3
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderShadowMap.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SHADOW_MAP_H
+#define UIC_RENDER_SHADOW_MAP_H
+#include "UICRenderContext.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSMat44.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#ifdef _INTEGRITYPLATFORM
+#include "render/Qt3DSRenderTextureCube.h"
+#endif
+
+namespace uic {
+namespace render {
+
+ struct SLayerRenderData;
+
+ struct ShadowMapModes
+ {
+ enum Enum {
+ SSM, ///< standard shadow mapping
+ VSM, ///< variance shadow mapping
+ CUBE, ///< cubemap omnidirectional shadows
+ };
+ };
+
+ struct ShadowFilterValues
+ {
+ enum Enum {
+ NONE = 1 << 0, ///< hard shadows
+ PCF = 1 << 1, ///< Percentage close filtering
+ BLUR = 1 << 2, ///< Gausian Blur
+ };
+ };
+
+ struct SShadowMapEntry
+ {
+ SShadowMapEntry()
+ : m_LightIndex(QT3DS_MAX_U32)
+ , m_ShadowMapMode(ShadowMapModes::SSM)
+ , m_ShadowFilterFlags(ShadowFilterValues::NONE)
+ {
+ }
+
+ SShadowMapEntry(QT3DSU32 index, ShadowMapModes::Enum mode, ShadowFilterValues::Enum filter,
+ NVRenderTexture2D &depthMap, NVRenderTexture2D &depthCopy,
+ NVRenderTexture2D &depthTemp)
+ : m_LightIndex(index)
+ , m_ShadowMapMode(mode)
+ , m_ShadowFilterFlags(filter)
+ , m_DepthMap(depthMap)
+ , m_DepthCopy(depthCopy)
+ , m_DepthCube(NULL)
+ , m_CubeCopy(NULL)
+ , m_DepthRender(depthTemp)
+ {
+ }
+
+ SShadowMapEntry(QT3DSU32 index, ShadowMapModes::Enum mode, ShadowFilterValues::Enum filter,
+ NVRenderTextureCube &depthCube, NVRenderTextureCube &cubeTmp,
+ NVRenderTexture2D &depthTemp)
+ : m_LightIndex(index)
+ , m_ShadowMapMode(mode)
+ , m_ShadowFilterFlags(filter)
+ , m_DepthMap(NULL)
+ , m_DepthCopy(NULL)
+ , m_DepthCube(depthCube)
+ , m_CubeCopy(cubeTmp)
+ , m_DepthRender(depthTemp)
+ {
+ }
+
+ QT3DSU32 m_LightIndex; ///< the light index it belongs to
+ ShadowMapModes::Enum m_ShadowMapMode; ///< shadow map method
+ ShadowFilterValues::Enum m_ShadowFilterFlags; ///< shadow filter mode
+
+ // PKC : Adding the DepthRender buffer allows us to have a depth+stencil format when filling
+ // the shadow maps (depth+stencil is necessary), but use a more compact format for the
+ // actual
+ // shadow map used at shade time. See if it's worth adding.
+ NVScopedRefCounted<NVRenderTexture2D> m_DepthMap; ///< shadow map texture
+ NVScopedRefCounted<NVRenderTexture2D>
+ m_DepthCopy; ///< shadow map buffer used during blur passes
+ NVScopedRefCounted<NVRenderTextureCube> m_DepthCube; ///< shadow cube map
+ NVScopedRefCounted<NVRenderTextureCube>
+ m_CubeCopy; ///< cube map buffer used during the blur passes
+ NVScopedRefCounted<NVRenderTexture2D>
+ m_DepthRender; ///< shadow depth+stencil map used during rendering
+
+ QT3DSMat44 m_LightVP; ///< light view projection matrix
+ QT3DSMat44 m_LightCubeView[6]; ///< light cubemap view matrices
+ QT3DSMat44 m_LightView; ///< light view transform
+ };
+
+ class UICShadowMap : public NVRefCounted
+ {
+ typedef nvvector<SShadowMapEntry> TShadowMapEntryList;
+
+ public:
+ IUICRenderContext &m_UICContext;
+ volatile QT3DSI32 mRefCount;
+
+ public:
+ UICShadowMap(IUICRenderContext &inContext);
+ ~UICShadowMap();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_UICContext.GetAllocator())
+
+ /*
+ * @brief Add a shadow map entry
+ * This creates a new shadow map if it does not exist or changed
+ *
+ * @param[in] index shadow map entry index
+ * @param[in] width shadow map width
+ * @param[in] height shadow map height
+ * @param[in] format shadow map format
+ * @param[in] samples shadow map sample count
+ * @param[in] mode shadow map mode like SSM, VCM
+ * @param[in] filter soft shadow map mode filter like PCF
+ *
+ * @ return no return
+ */
+ void AddShadowMapEntry(QT3DSU32 index, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum format, QT3DSU32 samples,
+ ShadowMapModes::Enum mode, ShadowFilterValues::Enum filter);
+
+ /*
+ * @brief Get a shadow map entry
+ *
+ * @param[in] index shadow map entry index
+ *
+ * @ return shadow map entry or NULL
+ */
+ SShadowMapEntry *GetShadowMapEntry(QT3DSU32 index);
+
+ /*
+ * @brief Get shadow map entry count
+ *
+ * @ return count of shadow map entries
+ */
+ QT3DSU32 GetShadowMapEntryCount() { return m_ShadowMapList.size(); }
+
+ static UICShadowMap *Create(IUICRenderContext &inContext);
+
+ private:
+ TShadowMapEntryList m_ShadowMapList; ///< List of shadow map entries
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderString.h b/src/Runtime/Source/UICRender/Include/UICRenderString.h
new file mode 100644
index 00000000..b9a14f35
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderString.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_STRING_H
+#define UIC_RENDER_STRING_H
+#include "UICRender.h"
+#include <string>
+
+namespace uic {
+namespace render {
+ // can't name this CString else we will conflict a
+ class CRenderString : public std::basic_string<char8_t>
+ {
+ public:
+ typedef std::basic_string<char8_t> TStrType;
+
+ CRenderString()
+ : TStrType()
+ {
+ }
+ CRenderString(const CRenderString &inOther)
+ : TStrType(inOther)
+ {
+ }
+ CRenderString(const TStrType &inOther)
+ : TStrType(inOther)
+ {
+ }
+ CRenderString &operator=(const CRenderString &inOther)
+ {
+ TStrType::operator=(inOther);
+ return *this;
+ }
+ CRenderString &operator=(const char8_t *inOther)
+ {
+ TStrType::operator=(inOther);
+ return *this;
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderSubPresentationHelper.h b/src/Runtime/Source/UICRender/Include/UICRenderSubPresentationHelper.h
new file mode 100644
index 00000000..635e73de
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderSubPresentationHelper.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SUB_PRESENTATION_HELPER_H
+#define UIC_RENDER_SUB_PRESENTATION_HELPER_H
+#include "UICRenderContext.h"
+#include "UICRenderer.h"
+#include "render/Qt3DSRenderContext.h"
+
+namespace uic {
+namespace render {
+
+ // Small helper object to setup the state needed to render a sub presentation
+ // correctly. Sub presentations may have transparency, and if they do then
+ // then need to be rendered with pre multiple alpha disabled. If they don't,
+ // then they need to be rendered with pre-multiply alpha enabled (and have the alpha channel
+ // set to 1
+ struct SSubPresentationHelper
+ {
+ IUICRenderContext &m_RenderContext;
+ SWindowDimensions m_PreviousPresentationDimensions;
+
+ bool m_WasInSubPresentation;
+
+ SSubPresentationHelper(IUICRenderContext &inContext,
+ const SWindowDimensions &inPresDimensions)
+ : m_RenderContext(inContext)
+ , m_PreviousPresentationDimensions(inContext.GetCurrentPresentationDimensions())
+ , m_WasInSubPresentation(inContext.IsInSubPresentation())
+ {
+ m_RenderContext.SetInSubPresentation(true);
+ m_RenderContext.SetPresentationDimensions(inPresDimensions);
+ }
+ ~SSubPresentationHelper()
+ {
+ m_RenderContext.SetInSubPresentation(m_WasInSubPresentation);
+ m_RenderContext.SetPresentationDimensions(m_PreviousPresentationDimensions);
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderSubpresentation.h b/src/Runtime/Source/UICRender/Include/UICRenderSubpresentation.h
new file mode 100644
index 00000000..b9837306
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderSubpresentation.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SUBPRESENTATION_H
+#define UIC_RENDER_SUBPRESENTATION_H
+
+#include "UICOffscreenRenderManager.h"
+#include "UICRenderSubPresentationHelper.h"
+#include "UICRenderPresentation.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace uic {
+namespace render {
+
+ class CSubPresentationRenderer;
+
+ struct CSubPresentationPickQuery : public IGraphObjectPickQuery
+ {
+ CSubPresentationRenderer &m_Renderer;
+
+ CSubPresentationPickQuery(CSubPresentationRenderer &renderer)
+ : m_Renderer(renderer)
+ {
+ }
+ SUICRenderPickResult Pick(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool inPickEverything) override;
+ };
+
+ class CSubPresentationRenderer : public IOffscreenRenderer
+ {
+ public:
+ IUICRenderContext &m_RenderContext;
+ SPresentation &m_Presentation;
+ volatile QT3DSI32 mRefCount;
+ SOffscreenRendererEnvironment m_LastRenderedEnvironment;
+ CSubPresentationPickQuery m_PickQuery;
+ CRegisteredString m_OffscreenRendererType;
+
+ CSubPresentationRenderer(IUICRenderContext &inRenderContext, SPresentation &inPresentation);
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
+
+ SOffscreenRendererEnvironment GetDesiredEnvironment(QT3DSVec2 inPresScale) override;
+ virtual SOffscreenRenderFlags
+ NeedsRender(const SOffscreenRendererEnvironment &inEnvironment, QT3DSVec2 inPresScale) override;
+ void Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext & /*inRenderContext*/
+ ,
+ QT3DSVec2 inPresScale, SScene::RenderClearCommand inClearBuffer) override;
+ IGraphObjectPickQuery *GetGraphObjectPickQuery() override { return &m_PickQuery; }
+ bool Pick(const QT3DSVec2 & /*inMouseCoords*/, const QT3DSVec2 & /*inViewportDimensions*/) override
+ {
+ return false;
+ }
+ // Used for RTTI purposes so we can safely static-cast an offscreen renderer to a
+ // CSubPresentationRenderer
+ static const char *GetRendererName() { return "SubPresentation"; }
+ CRegisteredString GetOffscreenRendererType() override { return m_OffscreenRendererType; }
+
+ SUICRenderPickResult DoGraphQueryPick(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool inPickEverything);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderTaggedPointer.h b/src/Runtime/Source/UICRender/Include/UICRenderTaggedPointer.h
new file mode 100644
index 00000000..83b0a528
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderTaggedPointer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TAGGED_POINTER_H
+#define UIC_RENDER_TAGGED_POINTER_H
+#include "UICRender.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+namespace render {
+
+ // User's will need to define specialize this struct in order
+ // to de-tag a pointer.
+ template <typename TDataType>
+ struct SPointerTag
+ {
+ /* Expected API for runtime RTTI
+ static CRegisteredString GetTag() { return g_dtype_specific_string; }
+ */
+ };
+
+ // A pointer tagged with an identifier so we can have generic
+ // user data that is still somewhat typesafe.
+ struct STaggedPointer
+ {
+ void *m_UserData;
+ QT3DSU32 m_Tag;
+ STaggedPointer()
+ : m_UserData(NULL)
+ , m_Tag(0)
+ {
+ }
+
+ STaggedPointer(void *inUserData, QT3DSU32 inTag)
+ : m_UserData(inUserData)
+ , m_Tag(inTag)
+ {
+ }
+
+ template <typename TDataType>
+ STaggedPointer(TDataType *inType)
+ : m_UserData(reinterpret_cast<void *>(inType))
+ , m_Tag(SPointerTag<TDataType>::GetTag())
+ {
+ }
+
+ template <typename TDataType>
+ TDataType *DynamicCast() const
+ {
+ if (m_Tag == SPointerTag<TDataType>::GetTag())
+ return reinterpret_cast<TDataType *>(m_UserData);
+ return NULL;
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderTessModeValues.h b/src/Runtime/Source/UICRender/Include/UICRenderTessModeValues.h
new file mode 100644
index 00000000..b83fc5ff
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderTessModeValues.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TESS_MODE_VALUES_H
+#define UIC_RENDER_TESS_MODE_VALUES_H
+#include "UICRender.h"
+
+namespace uic {
+namespace render {
+
+ struct SDefaultMaterial;
+ class IBufferManager;
+
+ struct TessModeValues
+ {
+ enum Enum {
+ NoTess = 0,
+ TessLinear = 1,
+ TessPhong = 2,
+ TessNPatch = 3,
+ };
+
+ static const char *toString(Enum value)
+ {
+ switch (value) {
+ case NoTess:
+ return "NoTess";
+ break;
+ case TessLinear:
+ return "TessLinear";
+ break;
+ case TessPhong:
+ return "TessPhong";
+ break;
+ case TessNPatch:
+ return "TessNPatch";
+ break;
+ default:
+ return "NoTess";
+ break;
+ }
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderTextTextureAtlas.h b/src/Runtime/Source/UICRender/Include/UICRenderTextTextureAtlas.h
new file mode 100644
index 00000000..c99253c4
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderTextTextureAtlas.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TEXT_TEXTURE_ATLAS_H
+#define UIC_RENDER_TEXT_TEXTURE_ATLAS_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICRenderText.h"
+#include "EASTL/algorithm.h"
+
+namespace uic {
+namespace render {
+
+ class ITextRenderer;
+
+ typedef eastl::pair<STextTextureAtlasDetails, NVScopedRefCounted<NVRenderTexture2D>>
+ TTextTextureAtlasDetailsAndTexture;
+ typedef eastl::pair<SRenderTextureAtlasDetails, NVScopedRefCounted<NVRenderTexture2D>>
+ TTextRenderAtlasDetailsAndTexture;
+
+ class ITextTextureAtlas : public NVRefCounted
+ {
+ protected:
+ virtual ~ITextTextureAtlas() {}
+ public:
+ virtual TTextRenderAtlasDetailsAndTexture RenderText(const STextRenderInfo &inText) = 0;
+ virtual bool IsInitialized() = 0;
+ virtual TTextTextureAtlasDetailsAndTexture PrepareTextureAtlas() = 0;
+
+ static ITextTextureAtlas &CreateTextureAtlas(NVFoundationBase &inFnd,
+ ITextRenderer &inTextRenderer,
+ NVRenderContext &inRenderContext);
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderTextTextureCache.h b/src/Runtime/Source/UICRender/Include/UICRenderTextTextureCache.h
new file mode 100644
index 00000000..485c540e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderTextTextureCache.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TEXT_TEXTURE_CACHE_H
+#define UIC_RENDER_TEXT_TEXTURE_CACHE_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "UICRenderText.h"
+#include "EASTL/algorithm.h"
+
+namespace uic {
+namespace render {
+
+ class ITextRenderer;
+
+ typedef eastl::pair<NVScopedRefCounted<NVRenderPathFontSpecification>,
+ NVScopedRefCounted<NVRenderPathFontItem>>
+ TPathFontSpecAndPathObject;
+ typedef eastl::pair<STextTextureDetails, NVScopedRefCounted<NVRenderTexture2D>>
+ TTextTextureDetailsAndTexture;
+ typedef eastl::pair<TPathFontSpecAndPathObject, TTextTextureDetailsAndTexture>
+ TTPathObjectAndTexture;
+
+ class ITextTextureCache : public NVRefCounted
+ {
+ protected:
+ virtual ~ITextTextureCache() {}
+ public:
+ virtual TTPathObjectAndTexture RenderText(const STextRenderInfo &inText,
+ QT3DSF32 inScaleFactor) = 0;
+ // We may have one more texture in cache than this byte count, but this will be the limiting
+ // factor.
+ virtual QT3DSU32 GetCacheHighWaterBytes() const = 0;
+ virtual void SetCacheHighWaterBytes(QT3DSU32 inNumBytes) = 0;
+
+ virtual void BeginFrame() = 0;
+ // We need to know the frame rhythm because we can't release anything that was touched this
+ // frame.
+ virtual void EndFrame() = 0;
+
+ static ITextTextureCache &CreateTextureCache(NVFoundationBase &inFnd,
+ ITextRenderer &inTextRenderer,
+ NVRenderContext &inRenderContext);
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderTextTypes.h b/src/Runtime/Source/UICRender/Include/UICRenderTextTypes.h
new file mode 100644
index 00000000..a51501a7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderTextTypes.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TEXT_TYPES_H
+#define UIC_RENDER_TEXT_TYPES_H
+#include "UICRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSVec2.h"
+
+namespace uic {
+namespace render {
+
+ struct TextHorizontalAlignment
+ {
+ enum Enum {
+ Unknown = 0,
+ Left,
+ Center,
+ Right,
+ };
+ };
+
+ struct TextVerticalAlignment
+ {
+ enum Enum {
+ Unknown = 0,
+ Top,
+ Middle,
+ Bottom,
+ };
+ };
+
+ struct STextDimensions
+ {
+ QT3DSU32 m_TextWidth;
+ QT3DSU32 m_TextHeight;
+ STextDimensions(QT3DSU32 w, QT3DSU32 h)
+ : m_TextWidth(w)
+ , m_TextHeight(h)
+ {
+ }
+ STextDimensions()
+ : m_TextWidth(0)
+ , m_TextHeight(0)
+ {
+ }
+ };
+
+ struct STextTextureDetails : public STextDimensions
+ {
+ QT3DSVec2 m_ScaleFactor;
+ bool m_FlipY;
+ STextTextureDetails(QT3DSU32 w, QT3DSU32 h, bool inFlipY, QT3DSVec2 scaleF)
+ : STextDimensions(w, h)
+ , m_ScaleFactor(scaleF)
+ , m_FlipY(inFlipY)
+ {
+ }
+ STextTextureDetails()
+ : m_ScaleFactor(1.0f)
+ , m_FlipY(false)
+ {
+ }
+ };
+
+ struct STextTextureAtlasEntryDetails : public STextDimensions
+ {
+ QT3DSI32 m_X, m_Y;
+ STextTextureAtlasEntryDetails(QT3DSU32 w, QT3DSU32 h, QT3DSI32 x, QT3DSI32 y)
+ : STextDimensions(w, h)
+ , m_X(x)
+ , m_Y(y)
+ {
+ }
+ STextTextureAtlasEntryDetails()
+ : m_X(0)
+ , m_Y(0)
+ {
+ }
+ };
+
+ struct SRenderTextureAtlasDetails
+ {
+ QT3DSU32 m_VertexCount;
+ NVDataRef<QT3DSU8> m_Vertices;
+
+ SRenderTextureAtlasDetails(QT3DSU32 count, NVDataRef<QT3DSU8> inVertices)
+ : m_VertexCount(count)
+ , m_Vertices(inVertices)
+ {
+ }
+ SRenderTextureAtlasDetails()
+ : m_VertexCount(0)
+ , m_Vertices(NVDataRef<QT3DSU8>())
+ {
+ }
+ };
+
+ struct STextTextureAtlasDetails : public STextTextureDetails
+ {
+ QT3DSU32 m_EntryCount;
+ STextTextureAtlasDetails(QT3DSU32 w, QT3DSU32 h, bool inFlipY, QT3DSU32 count)
+ : STextTextureDetails(w, h, inFlipY, QT3DSVec2(1.0f))
+ , m_EntryCount(count)
+ {
+ }
+ STextTextureAtlasDetails()
+ : m_EntryCount(0)
+ {
+ }
+ };
+
+ // Adding/removing a member to this object means you need to update the texture cache code
+ // - UICRenderTextTextureCache.cpp
+
+ struct STextRenderInfo
+ {
+ CRegisteredString m_Text;
+ CRegisteredString m_Font;
+ QT3DSF32 m_FontSize;
+ TextHorizontalAlignment::Enum m_HorizontalAlignment;
+ TextVerticalAlignment::Enum m_VerticalAlignment;
+ QT3DSF32 m_Leading; // space between lines
+ QT3DSF32 m_Tracking; // space between letters
+
+ QT3DSF32 m_ScaleX; // Pixel scale in X
+ QT3DSF32 m_ScaleY; // Pixel scale in Y
+
+ bool m_EnableAcceleratedFont; ///< use NV path rendering
+
+ STextRenderInfo();
+ ~STextRenderInfo();
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderTextureAtlas.h b/src/Runtime/Source/UICRender/Include/UICRenderTextureAtlas.h
new file mode 100644
index 00000000..edc9083e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderTextureAtlas.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_TEXTURE_ATLAS_H
+#define UIC_RENDER_TEXTURE_ATLAS_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "EASTL/algorithm.h"
+
+namespace uic {
+namespace render {
+
+ class ITextRenderer;
+
+ struct STextureAtlasRect
+ {
+
+ STextureAtlasRect()
+ : m_X(0)
+ , m_Y(0)
+ , m_Width(0)
+ , m_Height(0)
+ {
+ }
+
+ STextureAtlasRect(QT3DSI32 x, QT3DSI32 y, QT3DSI32 w, QT3DSI32 h)
+ : m_X(x)
+ , m_Y(y)
+ , m_Width(w)
+ , m_Height(h)
+ {
+ }
+
+ QT3DSI32 m_X;
+ QT3DSI32 m_Y;
+ QT3DSI32 m_Width;
+ QT3DSI32 m_Height;
+
+ // normalized coordinates
+ QT3DSF32 m_NormX;
+ QT3DSF32 m_NormY;
+ QT3DSF32 m_NormWidth;
+ QT3DSF32 m_NormHeight;
+ };
+
+ typedef eastl::pair<STextureAtlasRect, NVDataRef<QT3DSU8>> TTextureAtlasEntryAndBuffer;
+
+ /**
+ * Abstract class of a texture atlas representation
+ */
+ class ITextureAtlas : public NVRefCounted
+ {
+ protected:
+ virtual ~ITextureAtlas() {}
+
+ public:
+ virtual QT3DSI32 GetWidth() const = 0;
+ virtual QT3DSI32 GetHeight() const = 0;
+ virtual QT3DSI32 GetAtlasEntryCount() const = 0;
+ virtual TTextureAtlasEntryAndBuffer GetAtlasEntryByIndex(QT3DSU32 index) = 0;
+
+ virtual STextureAtlasRect AddAtlasEntry(QT3DSI32 width, QT3DSI32 height, QT3DSI32 pitch,
+ QT3DSI32 dataWidth,
+ NVConstDataRef<QT3DSU8> bufferData) = 0;
+ virtual void RelaseEntries() = 0;
+
+ static ITextureAtlas &CreateTextureAtlas(NVFoundationBase &inFnd,
+ NVRenderContext &inRenderContext, QT3DSI32 width,
+ QT3DSI32 height);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderThreadPool.h b/src/Runtime/Source/UICRender/Include/UICRenderThreadPool.h
new file mode 100644
index 00000000..1996f97c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderThreadPool.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_THREAD_POOL_H
+#define UIC_RENDER_THREAD_POOL_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+
+namespace uic {
+namespace render {
+
+ typedef void (*TTaskFunction)(void *inUserData);
+
+ struct TaskStates
+ {
+ enum Enum {
+ UnknownTask = 0,
+ Queued,
+ Running,
+ };
+ };
+
+ struct CancelReturnValues
+ {
+ enum Enum {
+ TaskCanceled = 0,
+ TaskRunning,
+ TaskNotFound,
+ };
+ };
+
+ class IThreadPool : public NVRefCounted
+ {
+ protected:
+ virtual ~IThreadPool() {}
+ public:
+ // Add a task to be run at some point in the future.
+ // Tasks will be run roughly in order they are given.
+ // The returned value is a handle that can be used to query
+ // details about the task
+ // Cancel function will be called if the thread pool is destroyed or
+ // of the task gets canceled.
+ virtual QT3DSU64 AddTask(void *inUserData, TTaskFunction inFunction,
+ TTaskFunction inCancelFunction) = 0;
+ virtual TaskStates::Enum GetTaskState(QT3DSU64 inTaskId) = 0;
+ virtual CancelReturnValues::Enum CancelTask(QT3DSU64 inTaskId) = 0;
+
+ static IThreadPool &CreateThreadPool(NVFoundationBase &inFoundation,
+ QT3DSU32 inNumThreads = 4);
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderUIPLoader.h b/src/Runtime/Source/UICRender/Include/UICRenderUIPLoader.h
new file mode 100644
index 00000000..41853316
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderUIPLoader.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_UIP_LOADER_H
+#define UIC_RENDER_UIP_LOADER_H
+
+#ifdef UIC_RENDER_ENABLE_LOAD_UIP
+
+#include "UICRender.h"
+#include "foundation/StringTable.h"
+#include <EASTL/utility.h>
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderGraphObject.h"
+
+namespace Q3DStudio {
+class IRuntimeMetaData;
+}
+
+namespace UICDM {
+class IDOMReader;
+struct SMetaDataEffect;
+struct SMetaDataCustomMaterial;
+}
+
+namespace uic {
+namespace render {
+
+ class IBufferManager;
+
+ typedef nvhash_map<CRegisteredString, SGraphObject *> TIdObjectMap;
+
+ struct IUIPReferenceResolver
+ {
+ protected:
+ virtual ~IUIPReferenceResolver() {}
+ public:
+ virtual CRegisteredString ResolveReference(CRegisteredString inStart,
+ const char *inReference) = 0;
+ };
+
+ struct SPresentation;
+
+ class IUIPLoader
+ {
+ public:
+ // The reader needs to point to the top of the file, we will search
+ // several objects that exist at the top level of the uip file.
+ // Returns NULL if we were incapable of loading the presentation.
+ static SPresentation *
+ LoadUIPFile(UICDM::IDOMReader &inReader
+ // the full path, including the filename
+ // to the presentation file
+ ,
+ const char8_t *inFullPathToPresentationFile,
+ Q3DStudio::IRuntimeMetaData &inMetaData, IStringTable &inStrTable,
+ NVFoundationBase &inFoundation
+ // Allocator used for the presentation objects themselves
+ // this allows clients to pre-allocate a block of memory just for
+ // the scene graph
+ ,
+ NVAllocatorCallback &inPresentationAllocator
+ // Map of string ids to objects
+ ,
+ TIdObjectMap &ioObjectMap
+ // Buffer manager to load details about the images
+ ,
+ IBufferManager &inBufferManager
+ // To load effects we need the effect system
+ // and the presentation directory
+ ,
+ IEffectSystem &inEffectSystem, const char8_t *inPresentationDir,
+ IRenderPluginManager &inPluginManager, ICustomMaterialSystem &inMaterialSystem,
+ IDynamicObjectSystem &inDynamicSystem, uic::render::IPathManager &inPathManager
+ // Resolve references to objects; this is done by the main uip loader during
+ // its normal mode of operation so we try to reuse that code.
+ ,
+ IUIPReferenceResolver *inResolver
+ // Set some initial values by going to the master slide then slide 1
+ // Useful for quick testing, sort of equivalent to showing the first frame
+ // of a given presentation
+ ,
+ bool setValuesFromSlides = false);
+
+ static void CreateEffectClassFromMetaEffect(CRegisteredString inEffectName,
+ NVFoundationBase &inFoundation,
+ IEffectSystem &inEffectSystem,
+ const UICDM::SMetaDataEffect &inMetaDataEffect,
+ IStringTable &inStrTable);
+
+ static void CreateMaterialClassFromMetaMaterial(
+ CRegisteredString inEffectName, NVFoundationBase &inFoundation,
+ ICustomMaterialSystem &inEffectSystem,
+ const UICDM::SMetaDataCustomMaterial &inMetaDataMaterial, IStringTable &inStrTable);
+ };
+}
+}
+
+#endif
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderUIPSharedTranslation.h b/src/Runtime/Source/UICRender/Include/UICRenderUIPSharedTranslation.h
new file mode 100644
index 00000000..f2fe2f89
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderUIPSharedTranslation.h
@@ -0,0 +1,460 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_UIP_SHARED_TRANSLATION_H
+#define UIC_RENDER_UIP_SHARED_TRANSLATION_H
+#include "UICRenderLight.h"
+#include "UICRenderCamera.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderImage.h"
+#include "UICRenderText.h"
+#include "UICDMWindowsCompatibility.h"
+#include "UICRenderLayer.h"
+#include "UICRenderModel.h"
+#include "UICRenderPath.h"
+#include "UICRenderPresentation.h"
+
+// map from UICDM to UIC::RENDER
+namespace uic {
+namespace render {
+
+ template <typename TEnumType>
+ struct SEnumParseMap
+ {
+ };
+
+ struct SEnumNameMap
+ {
+ QT3DSU32 m_Enum;
+ const wchar_t *m_WideName;
+ const char8_t *m_Name;
+ };
+
+ template <>
+ struct SEnumParseMap<RenderLightTypes::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<DefaultMaterialLighting::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<DefaultMaterialBlendMode::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<ImageMappingModes::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<NVRenderTextureCoordOp::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<TextHorizontalAlignment::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<TextVerticalAlignment::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<AAModeValues::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<LayerBlendTypes::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<RenderRotationValues::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<CameraScaleModes::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<CameraScaleAnchors::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+ template <>
+ struct SEnumParseMap<HorizontalFieldValues::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+ template <>
+ struct SEnumParseMap<VerticalFieldValues::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+ template <>
+ struct SEnumParseMap<LayerUnitTypes::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<LayerBackground::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<DefaultMaterialSpecularModel::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<TessModeValues::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<PathCapping::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<PathTypes::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<PathPaintStyles::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+#define UIC_RENDER_WCHAR_T_XYZs L"XYZ"
+#define UIC_RENDER_WCHAR_T_YZXs L"YZX"
+#define UIC_RENDER_WCHAR_T_ZXYs L"ZXY"
+#define UIC_RENDER_WCHAR_T_XZYs L"XZY"
+#define UIC_RENDER_WCHAR_T_YXZs L"YXZ"
+#define UIC_RENDER_WCHAR_T_ZYXs L"ZYX"
+
+#define UIC_RENDER_WCHAR_T_XYZr L"XYZr"
+#define UIC_RENDER_WCHAR_T_YZXr L"YZXr"
+#define UIC_RENDER_WCHAR_T_ZXYr L"ZXYr"
+#define UIC_RENDER_WCHAR_T_XZYr L"XZYr"
+#define UIC_RENDER_WCHAR_T_YXZr L"YXZr"
+#define UIC_RENDER_WCHAR_T_ZYXr L"ZYXr"
+
+#define UIC_RENDER_CHAR_T_XYZs "XYZ"
+#define UIC_RENDER_CHAR_T_YZXs "YZX"
+#define UIC_RENDER_CHAR_T_ZXYs "ZXY"
+#define UIC_RENDER_CHAR_T_XZYs "XZY"
+#define UIC_RENDER_CHAR_T_YXZs "YXZ"
+#define UIC_RENDER_CHAR_T_ZYXs "ZYX"
+
+#define UIC_RENDER_CHAR_T_XYZr "XYZr"
+#define UIC_RENDER_CHAR_T_YZXr "YZXr"
+#define UIC_RENDER_CHAR_T_ZXYr "ZXYr"
+#define UIC_RENDER_CHAR_T_XZYr "XZYr"
+#define UIC_RENDER_CHAR_T_YXZr "YXZr"
+#define UIC_RENDER_CHAR_T_ZYXr "ZYXr"
+
+ inline QT3DSU32 MapRotationOrder(const wchar_t *inOrderStr)
+ {
+#define MAP_ROTATION_ORDER(name, postfix) \
+ if (wcscmp(inOrderStr, UIC_RENDER_WCHAR_T_##name##postfix) == 0) { \
+ return EulOrd##name##postfix; \
+ }
+ MAP_ROTATION_ORDER(XYZ, s);
+ MAP_ROTATION_ORDER(YZX, s);
+ MAP_ROTATION_ORDER(ZXY, s);
+ MAP_ROTATION_ORDER(XZY, s);
+ MAP_ROTATION_ORDER(YXZ, s);
+ MAP_ROTATION_ORDER(ZYX, s);
+ MAP_ROTATION_ORDER(XYZ, r);
+ MAP_ROTATION_ORDER(YZX, r);
+ MAP_ROTATION_ORDER(ZXY, r);
+ MAP_ROTATION_ORDER(XZY, r);
+ MAP_ROTATION_ORDER(YXZ, r);
+ MAP_ROTATION_ORDER(ZYX, r);
+#undef MAP_ROTATION_ORDER
+ return EulOrdYXZs;
+ }
+
+ inline QT3DSU32 MapRotationOrder(const char8_t *inOrderStr)
+ {
+#define MAP_ROTATION_ORDER(name, postfix) \
+ if (strcmp(inOrderStr, UIC_RENDER_CHAR_T_##name##postfix) == 0) { \
+ return EulOrd##name##postfix; \
+ }
+ MAP_ROTATION_ORDER(XYZ, s);
+ MAP_ROTATION_ORDER(YZX, s);
+ MAP_ROTATION_ORDER(ZXY, s);
+ MAP_ROTATION_ORDER(XZY, s);
+ MAP_ROTATION_ORDER(YXZ, s);
+ MAP_ROTATION_ORDER(ZYX, s);
+ MAP_ROTATION_ORDER(XYZ, r);
+ MAP_ROTATION_ORDER(YZX, r);
+ MAP_ROTATION_ORDER(ZXY, r);
+ MAP_ROTATION_ORDER(XZY, r);
+ MAP_ROTATION_ORDER(YXZ, r);
+ MAP_ROTATION_ORDER(ZYX, r);
+#undef MAP_ROTATION_ORDER
+ return EulOrdYXZs;
+ }
+
+ // the goal is to unify the systems that transfer information into the UICRender library.
+ // There are currently three such systems; the runtime, studio, and the uip loader that loads
+ // uip files
+ // directly into the render library.
+ // To do this, we need to have a mapping between a generic key and a given property on every
+ // object
+ // along with some information about what portion of the object model this property affects.
+
+ struct UICRenderDirtyFlags
+ {
+ enum Enum {
+ Unknown = 0,
+ Dirty = 1 << 0,
+ TransformDirty = 1 << 1,
+ TextDirty = 1 << 2,
+ };
+ };
+
+// Now we build out generic macros with no implementation that list all of the properties
+// on each struct that we care about. We will fill in these macros with implementation later.
+// Each macro will list the property name along with what dirty operation should get marked
+// Global parse tables that list every property used by the system.
+#define ITERATE_UIC_RENDER_SCENE_PROPERTIES \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Scene, ClearColor, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Scene, UseClearColor, Dirty)
+
+#define ITERATE_UIC_RENDER_NODE_PROPERTIES \
+ HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY(Node, Rotation, TransformDirty) \
+ HANDLE_UIC_RENDER_VEC3_RADIAN_PROPERTY(Node, Rotation, TransformDirty) \
+ HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY(Node, Position, TransformDirty) \
+ HANDLE_UIC_RENDER_VEC3_PROPERTY(Node, Position, TransformDirty) \
+ HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY(Node, Scale, TransformDirty) \
+ HANDLE_UIC_RENDER_VEC3_PROPERTY(Node, Scale, TransformDirty) \
+ HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY(Node, Pivot, TransformDirty) \
+ HANDLE_UIC_RENDER_VEC3_PROPERTY(Node, Pivot, TransformDirty) \
+ HANDLE_UIC_RENDER_OPACITY_PROPERTY(Node, LocalOpacity, TransformDirty) \
+ HANDLE_UIC_ROTATION_ORDER_PROPERTY(Node, RotationOrder, TransformDirty) \
+ HANDLE_UIC_NODE_ORIENTATION_PROPERTY(Node, LeftHanded, TransformDirty)
+
+#define ITERATE_UIC_RENDER_LAYER_PROPERTIES \
+ HANDLE_UIC_NODE_FLAGS_INVERSE_PROPERTY(Layer, LayerEnableDepthTest, Dirty) \
+ HANDLE_UIC_NODE_FLAGS_INVERSE_PROPERTY(Layer, LayerEnableDepthPrePass, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, ProgressiveAAMode, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, MultisampleAAMode, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, TemporalAAEnabled, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Layer, ClearColor, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, BlendType, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, Background, Dirty) \
+ HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(Layer, TexturePath, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, HorizontalFieldValues, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Left, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, LeftUnits, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Width, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, WidthUnits, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Right, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, RightUnits, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, VerticalFieldValues, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Top, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, TopUnits, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Height, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, HeightUnits, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Bottom, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Layer, BottomUnits, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, AoStrength, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, AoDistance, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, AoSoftness, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, AoBias, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, AoDither, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ShadowStrength, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ShadowDist, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ShadowSoftness, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ShadowBias, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, LightProbe, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ProbeBright, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, FastIbl, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ProbeHorizon, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, ProbeFov, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, LightProbe2, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Probe2Fade, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Probe2Window, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Layer, Probe2Pos, Dirty)
+
+#define ITERATE_UIC_RENDER_CAMERA_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(Camera, ClipNear, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Camera, ClipFar, Dirty) \
+ HANDLE_UIC_RENDER_RADIAN_PROPERTY(Camera, FOV, Dirty) \
+ HANDLE_UIC_NODE_FLAGS_PROPERTY(Camera, Orthographic, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Camera, ScaleMode, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Camera, ScaleAnchor, Dirty)
+
+#define ITERATE_UIC_RENDER_LIGHT_PROPERTIES \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Light, LightType, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, Scope, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Light, DiffuseColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Light, DiffuseColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Light, SpecularColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Light, SpecularColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Light, AmbientColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Light, AmbientColor, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, Brightness, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, LinearFade, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, ExponentialFade, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, AreaWidth, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, AreaHeight, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, CastShadow, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, ShadowBias, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, ShadowFactor, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, ShadowMapFar, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Light, ShadowFilter, Dirty)
+
+#define ITERATE_UIC_RENDER_MODEL_PROPERTIES \
+ HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(Model, MeshPath, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Model, TessellationMode, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Model, EdgeTess, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Model, InnerTess, Dirty)
+
+#define ITERATE_UIC_RENDER_CUSTOM_MATERIAL_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(MaterialBase, IblProbe, Dirty)
+
+#define ITERATE_UIC_RENDER_LIGHTMAP_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(Lightmaps, LightmapIndirect, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Lightmaps, LightmapRadiosity, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Lightmaps, LightmapShadow, Dirty)
+
+#define ITERATE_UIC_RENDER_MATERIAL_PROPERTIES \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Material, Lighting, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Material, BlendMode, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(MaterialBase, IblProbe, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Material, DiffuseColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Material, DiffuseColor, Dirty) \
+ HANDLE_UIC_RENDER_ARRAY_PROPERTY(Material, DiffuseMaps, 0, Dirty) \
+ HANDLE_UIC_RENDER_ARRAY_PROPERTY(Material, DiffuseMaps, 1, Dirty) \
+ HANDLE_UIC_RENDER_ARRAY_PROPERTY(Material, DiffuseMaps, 2, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, EmissivePower, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Material, EmissiveColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Material, EmissiveColor, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, EmissiveMap, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, EmissiveMap2, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, SpecularReflection, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, SpecularMap, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Material, SpecularModel, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Material, SpecularTint, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Material, SpecularTint, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, FresnelPower, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, IOR, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, SpecularAmount, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, SpecularRoughness, Dirty) \
+ HANDLE_UIC_RENDER_OPACITY_PROPERTY(Material, Opacity, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, OpacityMap, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, BumpMap, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, BumpAmount, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, NormalMap, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, DisplacementMap, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, DisplaceAmount, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, TranslucencyMap, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, TranslucentFalloff, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Material, DiffuseLightWrap, Dirty)
+
+#define ITERATE_UIC_RENDER_REFERENCED_MATERIAL_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(Material, ReferencedMaterial, Dirty)
+
+#define ITERATE_UIC_RENDER_IMAGE_PROPERTIES \
+ HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(Image, ImagePath, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Image, OffscreenRendererId, Dirty) \
+ HANDLE_UIC_RENDER_VEC2_PROPERTY(Image, Scale, TransformDirty) \
+ HANDLE_UIC_RENDER_VEC2_PROPERTY(Image, Pivot, TransformDirty) \
+ HANDLE_UIC_RENDER_RADIAN_PROPERTY(Image, Rotation, TransformDirty) \
+ HANDLE_UIC_RENDER_VEC2_PROPERTY(Image, Position, TransformDirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Image, MappingMode, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Image, HorizontalTilingMode, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Image, VerticalTilingMode, Dirty)
+
+#define ITERATE_UIC_RENDER_TEXT_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(Text, Text, TextDirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Text, Font, TextDirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Text, FontSize, TextDirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Text, HorizontalAlignment, TextDirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Text, VerticalAlignment, TextDirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Text, Leading, TextDirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Text, Tracking, TextDirty) \
+ HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY(Text, TextColor, Dirty) \
+ HANDLE_UIC_RENDER_COLOR_PROPERTY(Text, TextColor, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Text, EnableAcceleratedFont, Dirty)
+
+#define ITERATE_UIC_RENDER_PATH_PROPERTIES \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Path, PathType, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, Width, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, LinearError, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, EdgeTessAmount, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, InnerTessAmount, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Path, BeginCapping, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, BeginCapOffset, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, BeginCapOpacity, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, BeginCapWidth, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Path, EndCapping, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, EndCapOffset, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, EndCapOpacity, Dirty) \
+ HANDLE_UIC_RENDER_PROPERTY(Path, EndCapWidth, Dirty) \
+ HANDLE_UIC_RENDER_ENUM_PROPERTY(Path, PaintStyle, Dirty) \
+ HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(Path, PathBuffer, Dirty)
+
+#define ITERATE_UIC_RENDER_PATH_SUBPATH_PROPERTIES \
+ HANDLE_UIC_RENDER_PROPERTY(SubPath, Closed, Dirty)
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderWidgets.h b/src/Runtime/Source/UICRender/Include/UICRenderWidgets.h
new file mode 100644
index 00000000..7b113f42
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderWidgets.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_WIDGETS_H
+#define UIC_RENDER_WIDGETS_H
+#include "UICRender.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSMat44.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "foundation/Qt3DSVec3.h"
+#include "EASTL/utility.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderIndexBuffer.h"
+#include "UICRenderText.h"
+
+namespace uic {
+namespace render {
+
+ struct SWidgetRenderInformation
+ {
+ // Just the rotation component of the nodeparenttocamera.
+ QT3DSMat33 m_NormalMatrix;
+ // The node parent's global transform multiplied by the inverse camera global transfrom;
+ // basically the MV from model-view-projection
+ QT3DSMat44 m_NodeParentToCamera;
+ // Projection that accounts for layer scaling
+ QT3DSMat44 m_LayerProjection;
+ // Pure camera projection without layer scaling
+ QT3DSMat44 m_PureProjection;
+ // A look at matrix that will rotate objects facing directly up
+ // the Z axis such that the point to the camera.
+ QT3DSMat33 m_LookAtMatrix;
+ // Conversion from world to camera position so world points not in object
+ // local space can be converted to camera space without going through the node's
+ // inverse global transform
+ QT3DSMat44 m_CameraGlobalInverse;
+ // Offset to add to the node's world position in camera space to move to the ideal camera
+ // location so that scale will work. This offset should be added *after* translation into
+ // camera space
+ QT3DSVec3 m_WorldPosOffset;
+ // Position in camera space to center the widget around
+ QT3DSVec3 m_Position;
+ // Scale factor to scale the widget by.
+ QT3DSF32 m_Scale;
+
+ // The camera used to render this object.
+ SCamera *m_Camera;
+ SWidgetRenderInformation(const QT3DSMat33 &inNormal, const QT3DSMat44 &inNodeParentToCamera,
+ const QT3DSMat44 &inLayerProjection, const QT3DSMat44 &inProjection,
+ const QT3DSMat33 &inLookAt, const QT3DSMat44 &inCameraGlobalInverse,
+ const QT3DSVec3 &inWorldPosOffset, const QT3DSVec3 &inPos, QT3DSF32 inScale,
+ SCamera &inCamera)
+ : m_NormalMatrix(inNormal)
+ , m_NodeParentToCamera(inNodeParentToCamera)
+ , m_LayerProjection(inLayerProjection)
+ , m_PureProjection(inProjection)
+ , m_LookAtMatrix(inLookAt)
+ , m_CameraGlobalInverse(inCameraGlobalInverse)
+ , m_WorldPosOffset(inWorldPosOffset)
+ , m_Position(inPos)
+ , m_Scale(inScale)
+ , m_Camera(&inCamera)
+ {
+ }
+ SWidgetRenderInformation()
+ : m_Camera(NULL)
+ {
+ }
+ };
+ typedef eastl::pair<SShaderVertexCodeGenerator &, SShaderFragmentCodeGenerator &>
+ TShaderGeneratorPair;
+
+ struct RenderWidgetModes
+ {
+ enum Enum {
+ Local,
+ Global,
+ };
+ };
+ // Context used to get render data for the widget.
+ class IRenderWidgetContext
+ {
+ protected:
+ virtual ~IRenderWidgetContext() {}
+ public:
+ virtual NVRenderVertexBuffer &
+ GetOrCreateVertexBuffer(CRegisteredString &inStr, QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> bufferData = NVConstDataRef<QT3DSU8>()) = 0;
+ virtual NVRenderIndexBuffer &
+ GetOrCreateIndexBuffer(CRegisteredString &inStr,
+ qt3ds::render::NVRenderComponentTypes::Enum componentType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData = NVConstDataRef<QT3DSU8>()) = 0;
+ virtual NVRenderAttribLayout &
+ CreateAttributeLayout(NVConstDataRef<qt3ds::render::NVRenderVertexBufferEntry> attribs) = 0;
+ virtual NVRenderInputAssembler &
+ GetOrCreateInputAssembler(CRegisteredString &inStr, NVRenderAttribLayout *attribLayout,
+ NVConstDataRef<NVRenderVertexBuffer *> buffers,
+ const NVRenderIndexBuffer *indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets) = 0;
+
+ virtual NVRenderVertexBuffer *GetVertexBuffer(CRegisteredString &inStr) = 0;
+ virtual NVRenderIndexBuffer *GetIndexBuffer(CRegisteredString &inStr) = 0;
+ virtual NVRenderInputAssembler *GetInputAssembler(CRegisteredString &inStr) = 0;
+
+ virtual NVRenderShaderProgram *GetShader(CRegisteredString inStr) = 0;
+ virtual IShaderProgramGenerator &GetProgramGenerator() = 0;
+ // calls compile on the program generator and stores result under this name.
+ virtual NVRenderShaderProgram *CompileAndStoreShader(CRegisteredString inStr) = 0;
+ virtual STextDimensions MeasureText(const STextRenderInfo &inText) = 0;
+ // Render text using a specific MVP
+ virtual void RenderText(const STextRenderInfo &inText, const QT3DSVec3 &inTextColor,
+ const QT3DSVec3 &inBackgroundColor, const QT3DSMat44 &inMVP) = 0;
+ // Given a node and a point in the node's local space (most likely its pivot point), we
+ // return
+ // a normal matrix so you can get the axis out, a transformation from node to camera
+ // a new position and a floating point scale factor so you can render in 1/2 perspective
+ // mode
+ // or orthographic mode if you would like to.
+ virtual SWidgetRenderInformation
+ GetWidgetRenderInformation(SNode &inNode, const QT3DSVec3 &inPos,
+ RenderWidgetModes::Enum inWidgetMode) = 0;
+ };
+
+ class IRenderWidget
+ {
+ protected:
+ virtual ~IRenderWidget() {}
+ SNode *m_Node;
+
+ public:
+ IRenderWidget(SNode &inNode)
+ : m_Node(&inNode)
+ {
+ }
+ IRenderWidget()
+ : m_Node(NULL)
+ {
+ }
+ virtual void Render(IRenderWidgetContext &inWidgetContext,
+ NVRenderContext &inRenderContext) = 0;
+ SNode &GetNode() { return *m_Node; }
+
+ // Pure widgets.
+ static IRenderWidget &CreateBoundingBoxWidget(SNode &inNode, const NVBounds3 &inBounds,
+ const QT3DSVec3 &inColor,
+ NVAllocatorCallback &inAlloc);
+ static IRenderWidget &CreateAxisWidget(SNode &inNode, NVAllocatorCallback &inAlloc);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderWindowDimensions.h b/src/Runtime/Source/UICRender/Include/UICRenderWindowDimensions.h
new file mode 100644
index 00000000..8f328cf1
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderWindowDimensions.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_WINDOW_DIMENSIONS_H
+#define UIC_RENDER_WINDOW_DIMENSIONS_H
+#include "UICRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+
+namespace uic {
+namespace render {
+ struct SWindowDimensions
+ {
+ QT3DSU32 m_Width;
+ QT3DSU32 m_Height;
+ SWindowDimensions(QT3DSU32 w, QT3DSU32 h)
+ : m_Width(w)
+ , m_Height(h)
+ {
+ }
+ SWindowDimensions()
+ : m_Width(0)
+ , m_Height(0)
+ {
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderableImage.h b/src/Runtime/Source/UICRender/Include/UICRenderableImage.h
new file mode 100644
index 00000000..0120c5f3
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderableImage.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDERABLE_IMAGE_H
+#define UIC_RENDERABLE_IMAGE_H
+#include "UICRender.h"
+
+namespace uic {
+namespace render {
+
+ struct ImageMapTypes
+ {
+ enum Enum {
+ Unknown = 0,
+ Diffuse = 1,
+ Opacity = 2,
+ Specular = 3,
+ Emissive = 4,
+ Bump = 5,
+ SpecularAmountMap = 6,
+ Normal = 7,
+ Displacement = 8,
+ Translucency = 9,
+ LightmapIndirect = 10,
+ LightmapRadiosity = 11,
+ LightmapShadow = 12,
+ };
+ };
+
+ /**
+ * Some precomputed information on a given image. When generating a renderable, the shader
+ * generator goes through all the possible images on a material and for each valid image
+ * computes this renderable image and attaches it to the renderable.
+ */
+ struct SRenderableImage
+ {
+ ImageMapTypes::Enum m_MapType;
+ SImage &m_Image;
+ SRenderableImage *m_NextImage;
+ SRenderableImage(ImageMapTypes::Enum inMapType, SImage &inImage)
+ : m_MapType(inMapType)
+ , m_Image(inImage)
+ , m_NextImage(NULL)
+ {
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICRenderer.h b/src/Runtime/Source/UICRender/Include/UICRenderer.h
new file mode 100644
index 00000000..d351e35a
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRenderer.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDERER_H
+#define UIC_RENDERER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSFlags.h"
+#include "EASTL/algorithm.h" //pair
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSVec2.h"
+#include "UICRenderGraphObjectPickQuery.h"
+#include "UICRenderWindowDimensions.h"
+#include "UICRenderCamera.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "UICRenderRay.h"
+
+namespace uic {
+namespace render {
+
+ class IRenderableObject;
+ struct SModel;
+ struct SText;
+ struct SCamera;
+ struct SLight;
+ struct SLayer;
+ class IBufferManager;
+
+ using qt3ds::foundation::NVConstDataRef;
+
+ class IUICRenderNodeFilter
+ {
+ protected:
+ virtual ~IUICRenderNodeFilter() {}
+ public:
+ virtual bool IncludeNode(const SNode &inNode) = 0;
+ };
+ struct SLayerPickSetup
+ {
+ QT3DSMat44 m_ProjectionPreMultiply;
+ QT3DSMat44 m_ViewProjection;
+ NVRenderRect m_ScissorRect;
+ SLayerPickSetup(const QT3DSMat44 &inProjPreMult, const QT3DSMat44 &inVP,
+ const NVRenderRect &inScissor)
+ : m_ProjectionPreMultiply(inProjPreMult)
+ , m_ViewProjection(inVP)
+ , m_ScissorRect(inScissor)
+ {
+ }
+ SLayerPickSetup() {}
+ };
+
+ struct SScaleAndPosition
+ {
+ QT3DSVec3 m_Position;
+ QT3DSF32 m_Scale;
+ SScaleAndPosition(const QT3DSVec3 &inPos, QT3DSF32 inScale)
+ : m_Position(inPos)
+ , m_Scale(inScale)
+ {
+ }
+ SScaleAndPosition() {}
+ };
+
+ class IUICRenderer : public NVRefCounted
+ {
+ protected:
+ virtual ~IUICRenderer() {}
+
+ public:
+ virtual void EnableLayerCaching(bool inEnabled) = 0;
+ virtual bool IsLayerCachingEnabled() const = 0;
+ virtual void EnableLayerGpuProfiling(bool inEnabled) = 0;
+ virtual bool IsLayerGpuProfilingEnabled() const = 0;
+
+ // Get the camera that rendered this node last render
+ virtual SCamera *GetCameraForNode(const SNode &inNode) const = 0;
+ virtual Option<SCuboidRect> GetCameraBounds(const SGraphObject &inObject) = 0;
+ // Called when you have changed the number or order of children of a given node.
+ virtual void ChildrenUpdated(SNode &inParent) = 0;
+ virtual QT3DSF32 GetTextScale(const SText &inText) = 0;
+
+ // The IUICRenderContext calls these, clients should not.
+ virtual void BeginFrame() = 0;
+ virtual void EndFrame() = 0;
+
+ // Setup the vertex and index buffers (but not shader state)
+ // and render the quad. The quad is setup so that its edges
+ // go from -1,1 in x,y and its UV coordinates will map naturally
+ // to an image.
+ virtual void RenderQuad() = 0;
+
+ // Render a given texture to the scene using a given transform.
+ virtual void RenderQuad(const QT3DSVec2 inDimensions, const QT3DSMat44 &inMVP,
+ NVRenderTexture2D &inQuadTexture) = 0;
+
+ // This point rendering works uisng indirect array drawing
+ // This means you need to setup a GPU buffer
+ // which contains the drawing information
+ virtual void RenderPointsIndirect() = 0;
+
+ // Returns true if this layer or a sibling was dirty.
+ virtual bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ bool inRenderSiblings = true) = 0;
+ virtual void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions, bool clear,
+ QT3DSVec3 clearColor, bool inRenderSiblings = true) = 0;
+
+ // Studio option to disable picking against sub renderers. This allows better interaction
+ // in studio.
+ // In pick siblings measn pick the layer siblings; this is the normal behavior.
+ // InPickEverything means ignore the node's pick flags; this allows us to only pick things
+ // that have handlers
+ // in some cases and just pick everything in other things.
+ virtual void PickRenderPlugins(bool inPick) = 0;
+ virtual SUICRenderPickResult Pick(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords, bool inPickSiblings = true,
+ bool inPickEverything = false) = 0;
+
+ // Return the relative hit position, in UV space, of a mouse pick against this object.
+ // We need the node in order to figure out which layer rendered this object.
+ // We need mapper objects if this is a in a subpresentation because we have to know how
+ // to map the mouse coordinates into the subpresentation. So for instance if inNode is in
+ // a subpres then we need to know which image is displaying the subpres in order to map
+ // the mouse coordinates into the subpres's render space.
+ virtual Option<QT3DSVec2> FacePosition(SNode &inNode, NVBounds3 inBounds,
+ const QT3DSMat44 &inGlobalTransform,
+ const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords,
+ NVDataRef<SGraphObject *> inMapperObjects,
+ SBasisPlanes::Enum inIsectPlane) = 0;
+
+ virtual QT3DSVec3 UnprojectToPosition(SNode &inNode, QT3DSVec3 &inPosition,
+ const QT3DSVec2 &inMouseVec) const = 0;
+ virtual QT3DSVec3 UnprojectWithDepth(SNode &inNode, QT3DSVec3 &inPosition,
+ const QT3DSVec3 &inMouseVec) const = 0;
+ virtual QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const = 0;
+
+ // Roughly equivalent of gluPickMatrix, allows users to setup a perspective transform that
+ // will draw some sub component
+ // of the layer. Used in combination with an expected viewport of 0,0,width,height the
+ // viewproj matrix returned will center
+ // around the center of the viewport and render just the part of the layer around this area.
+ // The return value is optional because if the mouse point is completely outside the layer
+ // obviously this method is irrelevant.
+ virtual Option<SLayerPickSetup> GetLayerPickSetup(SLayer &inLayer,
+ const QT3DSVec2 &inMouseCoords,
+ const SWindowDimensions &inPickDims) = 0;
+
+ // Return the layer's viewport rect after the layer's member variables have been applied.
+ // Uses the last rendered viewport rect.
+ virtual Option<NVRenderRectF> GetLayerRect(SLayer &inLayer) = 0;
+ // Testing function to allow clients to render a layer using a custom view project instead
+ // of the one that would be setup
+ // using the layer's camera in conjunction with the layer's position,scale.
+ virtual void RunLayerRender(SLayer &inLayer, const QT3DSMat44 &inViewProjection) = 0;
+
+ // This allocator is cleared every frame on BeginFrame. Objects constructed using this
+ // allocator
+ // Must not need their destructors called. Objects are allocate on 4 byte boundaries using
+ // this allocator
+ // regardless
+ virtual NVAllocatorCallback &GetPerFrameAllocator() = 0;
+
+ // Render the layer's rect onscreen. Will only render one frame, you need to call this
+ // every frame
+ // for this to work and be persistent.
+ virtual void RenderLayerRect(SLayer &inLayer, const QT3DSVec3 &inColor) = 0;
+ // Render widgets are things that are draw on the layer's widget texture which is then
+ // rendered to the
+ // scene's widget texture. You must add them every frame you wish them to be rendered; the
+ // list of
+ // widgets is cleared every frame.
+ virtual void AddRenderWidget(IRenderWidget &inWidget) = 0;
+
+ // Get a scale factor so you can have objects precisely 50 pixels. Note that this scale
+ // factor
+ // only applies to things drawn parallel to the camera plane; If you aren't parallel then
+ // there isn't
+ // a single scale factor that will work.
+ // For perspective-rendered objects, we shift the object forward or backwards along the
+ // vector from the camera
+ // to the object so that we are working in a consistent mathematical space. So if the
+ // camera is orthographic,
+ // you are done.
+ // If the camera is perspective, then this method will tell you want you need to scale
+ // things by to account for
+ // the FOV and also where the origin of the object needs to be to ensure the scale factor is
+ // relevant.
+ virtual SScaleAndPosition GetWorldToPixelScaleFactor(SLayer &inLayer,
+ const QT3DSVec3 &inWorldPoint) = 0;
+ // Called before a layer goes completely out of scope to release any rendering resources
+ // related to the layer.
+ virtual void ReleaseLayerRenderResources(SLayer &inLayer) = 0;
+
+ // render a screen aligned 2D text
+ virtual void RenderText2D(QT3DSF32 x, QT3DSF32 y, qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
+ const char *text) = 0;
+ // render Gpu profiler values
+ virtual void RenderGpuProfilerStats(QT3DSF32 x, QT3DSF32 y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor) = 0;
+
+ // Get the mouse coordinates as they relate to a given layer
+ virtual Option<QT3DSVec2> GetLayerMouseCoords(SLayer &inLayer, const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool forceImageIntersect = false) const = 0;
+
+ static bool IsGlEsContext(qt3ds::render::NVRenderContextType inContextType);
+ static bool IsGlEs3Context(qt3ds::render::NVRenderContextType inContextType);
+ static bool IsGl2Context(qt3ds::render::NVRenderContextType inContextType);
+ static const char *GetGlslVesionString(qt3ds::render::NVRenderContextType inContextType);
+
+ static IUICRenderer &CreateRenderer(IUICRenderContext &inContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/UICRendererUtil.h b/src/Runtime/Source/UICRender/Include/UICRendererUtil.h
new file mode 100644
index 00000000..64dbe11f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICRendererUtil.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDERER_UTIL_H
+#define UIC_RENDERER_UTIL_H
+#include "UICRender.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+namespace uic {
+namespace render {
+ class CRendererUtil
+ {
+ static const QT3DSU32 MAX_SSAA_DIM = 8192; // max render traget size for SSAA mode
+
+ public:
+ static void ResolveMutisampleFBOColorOnly(IResourceManager &inManager,
+ CResourceTexture2D &ioResult,
+ NVRenderContext &inRenderContext, QT3DSU32 inWidth,
+ QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inColorFormat,
+ NVRenderFrameBuffer &inSourceFBO);
+
+ static void ResolveSSAAFBOColorOnly(IResourceManager &inManager,
+ CResourceTexture2D &ioResult, QT3DSU32 outWidth,
+ QT3DSU32 outHeight, NVRenderContext &inRenderContext,
+ QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inColorFormat,
+ NVRenderFrameBuffer &inSourceFBO);
+
+ static void GetSSAARenderSize(QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 &outWidth,
+ QT3DSU32 &outHeight);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Include/UICTextRenderer.h b/src/Runtime/Source/UICRender/Include/UICTextRenderer.h
new file mode 100644
index 00000000..da9632f2
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/UICTextRenderer.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_TEXT_RENDERER_H
+#define UIC_TEXT_RENDERER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/StringTable.h"
+#include "UICRenderTextTypes.h"
+
+namespace uic {
+namespace render {
+
+ struct SRendererFontEntry
+ {
+ CRegisteredString m_FontName;
+ CRegisteredString m_FontFile;
+ SRendererFontEntry() {}
+ SRendererFontEntry(CRegisteredString nm, CRegisteredString file)
+ : m_FontName(nm)
+ , m_FontFile(file)
+ {
+ }
+ };
+
+ class ITextRendererCore : public NVRefCounted
+ {
+ public:
+ // You can have several standard font directories and these will be persistent
+ virtual void AddSystemFontDirectory(const char8_t *inDirectory) = 0;
+ // Should be called to clear the current context.
+ virtual void AddProjectFontDirectory(const char8_t *inProjectDirectory) = 0;
+ virtual void ClearProjectFontDirectories() = 0;
+ // Force font loading *right now*
+ virtual void PreloadFonts() = 0;
+ // Do not access object in between begin/end preload pairs.
+ virtual void BeginPreloadFonts(IThreadPool &inThreadPool, IPerfTimer &inTimer) = 0;
+ virtual void EndPreloadFonts() = 0;
+ // Force a clear and reload of all of the fonts.
+ virtual void ReloadFonts() = 0;
+ // Get the list of project fonts. These are the only fonts that can be displayed.
+ virtual NVConstDataRef<SRendererFontEntry> GetProjectFontList() = 0;
+ // The name stored in the ttf file isn't the actual name we use; we use the file stems.
+ // But we used to use the name. So this provides a sort of first-come-first-serve remapping
+ // from ttf-name to file-stem.
+ virtual Option<CRegisteredString> GetFontNameForFont(CRegisteredString inFontname) = 0;
+ virtual Option<CRegisteredString> GetFontNameForFont(const char8_t *inFontname) = 0;
+
+ virtual ITextRenderer &GetTextRenderer(NVRenderContext &inContext) = 0;
+
+ static ITextRendererCore &CreateQtTextRenderer(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable);
+
+ // call this to create onscreen text renderer
+ // it needs true type fonts
+ static ITextRendererCore &CreateOnscreenTextRenderer(NVFoundationBase &inFoundation);
+ };
+ /**
+ * Opaque text rendering system. Must be able to render text to an opengl texture object.
+ */
+ class ITextRenderer : public ITextRendererCore
+ {
+ protected:
+ virtual ~ITextRenderer() {}
+
+ public:
+ // Measure text will inText if it isn't null or the text on the info if inText is null
+ virtual STextDimensions MeasureText(const STextRenderInfo &inText, QT3DSF32 inTextScaleFactor,
+ const char8_t *inTextOverride = NULL) = 0;
+ // The system will use the 'r' channel as an alpha mask in order to render the
+ // text. You can assume GetTextDimensions was called *just* prior to this.
+ // It is a good idea to ensure the texture is a power of two as not all rendering systems
+ // support nonpot textures. Our text rendering algorithms will render a sub-rect of the
+ // image
+ // assuming it is located toward the upper-left of the image and we are also capable of
+ // flipping
+ // the image.
+ virtual STextTextureDetails RenderText(const STextRenderInfo &inText,
+ NVRenderTexture2D &inTexture) = 0;
+ // this is for rendering text with NV path rendering
+ virtual STextTextureDetails
+ RenderText(const STextRenderInfo &inText, NVRenderPathFontItem &inPathFontItem,
+ NVRenderPathFontSpecification &inPathFontSpecicification) = 0;
+ // this is for rednering text using a texture atlas
+ virtual SRenderTextureAtlasDetails RenderText(const STextRenderInfo &inText) = 0;
+
+ virtual void BeginFrame() = 0;
+ virtual void EndFrame() = 0;
+
+ // these two function are for texture atlas usage only
+ // returns the atlas entries count
+ virtual QT3DSI32 CreateTextureAtlas() = 0;
+ virtual STextTextureAtlasEntryDetails RenderAtlasEntry(QT3DSU32 index,
+ NVRenderTexture2D &inTexture) = 0;
+
+ // Helper function to upload the texture data to the texture
+ // Will resize texture as necessary and upload using texSubImage for
+ // quickest upload times
+ // This function expects that the dataWidth to be divisible by four and
+ // that the total data height is larger then inTextHeight *and* divisible by four.
+ // and that textWidth and textHeight are less than or equal to dataWidth,dataHeight
+ //,can be zero, and don't need to be divisible by four (or 2).
+ static STextTextureDetails
+ UploadData(NVDataRef<QT3DSU8> inTextureData, NVRenderTexture2D &inTexture, QT3DSU32 inDataWidth,
+ QT3DSU32 inDataHeight, QT3DSU32 inTextWidth, QT3DSU32 inTextHeight,
+ NVRenderTextureFormats::Enum inFormat, bool inFlipYAxis);
+
+ // Helper function to return the next power of two.
+ // Fails for values of 0 or QT3DS_MAX_U32
+ static QT3DSU32 NextPowerOf2(QT3DSU32 inValue);
+ // If inValue is divisible by four, then return inValue
+ // else next largest number that is divisible by four.
+ static QT3DSU32 NextMultipleOf4(QT3DSU32 inValue);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/WINDOWS/DynamicLibLoader.h b/src/Runtime/Source/UICRender/Include/WINDOWS/DynamicLibLoader.h
new file mode 100644
index 00000000..628a4d1e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/WINDOWS/DynamicLibLoader.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_WINDOWS_DYNAMIC_LIB_LOADER_H
+#define UIC_WINDOWS_DYNAMIC_LIB_LOADER_H
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+#include <QLibrary>
+
+namespace uic {
+namespace render {
+ using namespace qt3ds;
+ // using namespace qt3ds::render;
+
+ class CLoadedDynamicLibrary
+ {
+ QLibrary* m_DLLHandle;
+ CLoadedDynamicLibrary(QLibrary* hdl)
+ : m_DLLHandle(hdl)
+ {
+ }
+ CLoadedDynamicLibrary(const CLoadedDynamicLibrary &);
+ CLoadedDynamicLibrary &operator=(const CLoadedDynamicLibrary &);
+
+ public:
+ ~CLoadedDynamicLibrary()
+ {
+ if (m_DLLHandle) {
+ m_DLLHandle->unload();
+ delete m_DLLHandle;
+ }
+ m_DLLHandle = 0;
+ }
+ void *FindFunction(const char *name) { return (void*)m_DLLHandle->resolve(name); }
+ static CLoadedDynamicLibrary *Create(const char *inFullDllPath, NVFoundationBase &fnd)
+ {
+ QLibrary* hdl = new QLibrary(inFullDllPath);
+ if (!hdl->load()) {
+ qCCritical(INVALID_OPERATION, "Failed to load dynamic library %s: %s",
+ inFullDllPath, qPrintable(hdl->errorString()));
+
+ delete hdl;
+ return nullptr;
+ }
+ return QT3DS_NEW(fnd.getAllocator(), CLoadedDynamicLibrary)(hdl);
+ }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Include/q3dsqmlrender.h b/src/Runtime/Source/UICRender/Include/q3dsqmlrender.h
new file mode 100644
index 00000000..3e80080c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Include/q3dsqmlrender.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_QML_RENDER_H
+#define QT3DS_QML_RENDER_H
+
+#include "UICOffscreenRenderManager.h"
+#include "UICRenderContext.h"
+
+class IQt3DS;
+
+using namespace uic::render;
+
+class IQ3DSQmlStreamService;
+class IQ3DSQmlStreamRenderer;
+
+class Q3DSQmlRender : public IOffscreenRenderer
+{
+public:
+ Q3DSQmlRender(IUICRenderContext &inRenderContext, const char *asset);
+ ~Q3DSQmlRender();
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
+
+ CRegisteredString GetOffscreenRendererType() override;
+
+ SOffscreenRendererEnvironment GetDesiredEnvironment(QT3DSVec2 inPresentationScaleFactor) override;
+
+ // Returns true of this object needs to be rendered, false if this object is not dirty
+ SOffscreenRenderFlags NeedsRender(const SOffscreenRendererEnvironment &inEnvironment,
+ QT3DSVec2 inPresentationScaleFactor) override;
+
+ void Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 inPresentationScaleFactor,
+ SScene::RenderClearCommand inColorBufferNeedsClear) override;
+
+ IGraphObjectPickQuery *GetGraphObjectPickQuery() override
+ {
+ return nullptr;
+ }
+ bool Pick(const QT3DSVec2 &inMouseCoords, const QT3DSVec2 &inViewportDimensions) override
+ {
+ Q_UNUSED(inMouseCoords)
+ Q_UNUSED(inViewportDimensions)
+ return false;
+ }
+ static const char *GetRendererName() { return "qml-render"; }
+private:
+
+ void initializeRenderer();
+
+ IUICRenderContext &m_RenderContext;
+ IQ3DSQmlStreamRenderer *m_qmlStreamRenderer;
+ CRegisteredString m_offscreenRenderType;
+ CRegisteredString m_assetString;
+ volatile QT3DSI32 mRefCount;
+};
+
+#endif
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.cpp
new file mode 100644
index 00000000..47dbbb59
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.cpp
@@ -0,0 +1,529 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderableObjects.h"
+#include "UICRendererImpl.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderCustomMaterialRenderContext.h"
+#include "UICRenderLight.h"
+#include "UICRenderPathManager.h"
+#include "UICRenderPathRenderContext.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+
+using qt3ds::foundation::CRegisteredString;
+
+namespace uic {
+namespace render {
+ struct SRenderableImage;
+ struct SShaderGeneratorGeneratedShader;
+ struct SSubsetRenderable;
+ using eastl::make_pair;
+ using eastl::reverse;
+
+ STextScaleAndOffset::STextScaleAndOffset(NVRenderTexture2D &inTexture,
+ const STextTextureDetails &inTextDetails,
+ const STextRenderInfo &inInfo)
+ : m_TextOffset(0, 0)
+ , m_TextScale(1, 1)
+
+ {
+ NVRenderTexture2D &theTexture = inTexture;
+ STextureDetails theDetails(theTexture.GetTextureDetails());
+ QT3DSVec2 textDimensions(inTextDetails.m_TextWidth / 2.0f, inTextDetails.m_TextHeight / 2.0f);
+ textDimensions.x /= inTextDetails.m_ScaleFactor.x;
+ textDimensions.y /= inTextDetails.m_ScaleFactor.y;
+ QT3DSVec2 theTextScale(textDimensions.x, textDimensions.y);
+ QT3DSVec2 theTextOffset(0, 0);
+
+ // Set the offsets to use after scaling the rect coordinates.
+ switch (inInfo.m_HorizontalAlignment) {
+ case TextHorizontalAlignment::Left:
+ theTextOffset[0] = theTextScale[0];
+ break;
+ case TextHorizontalAlignment::Center:
+ break;
+ case TextHorizontalAlignment::Right:
+ theTextOffset[0] = -theTextScale[0];
+ break;
+ default:
+ break;
+ }
+
+ switch (inInfo.m_VerticalAlignment) {
+ case TextVerticalAlignment::Top:
+ theTextOffset[1] = -theTextScale[1];
+ break;
+ case TextVerticalAlignment::Middle:
+ break;
+ case TextVerticalAlignment::Bottom:
+ theTextOffset[1] = theTextScale[1];
+ break;
+ default:
+ break;
+ }
+ m_TextScale = theTextScale;
+ m_TextOffset = theTextOffset;
+ }
+
+ void SSubsetRenderableBase::RenderShadowMapPass(const QT3DSVec2 &inCameraVec,
+ const SLight *inLight, const SCamera &inCamera,
+ SShadowMapEntry *inShadowMapEntry)
+ {
+ NVRenderContext &context(m_Generator.GetContext());
+ SRenderableDepthPrepassShader *shader = NULL;
+ NVRenderInputAssembler *pIA = NULL;
+
+ /*
+ if ( inLight->m_LightType == RenderLightTypes::Area )
+ shader = m_Generator.GetParaboloidDepthShader( m_TessellationMode );
+ else if ( inLight->m_LightType == RenderLightTypes::Directional )
+ shader = m_Generator.GetOrthographicDepthShader( m_TessellationMode );
+ else if ( inLight->m_LightType == RenderLightTypes::Point )
+ shader = m_Generator.GetCubeShadowDepthShader( m_TessellationMode ); // This
+ will change to include a geometry shader pass.
+ */
+
+ if (inLight->m_LightType == RenderLightTypes::Directional)
+ shader = m_Generator.GetOrthographicDepthShader(m_TessellationMode);
+ else
+ shader = m_Generator.GetCubeShadowDepthShader(m_TessellationMode);
+
+ if (shader == NULL || inShadowMapEntry == NULL)
+ return;
+
+ // for phong and npatch tesselleation we need the normals too
+ if (m_TessellationMode == TessModeValues::NoTess
+ || m_TessellationMode == TessModeValues::TessLinear)
+ pIA = m_Subset.m_InputAssemblerDepth;
+ else
+ pIA = m_Subset.m_InputAssembler;
+
+ QT3DSMat44 theModelViewProjection = inShadowMapEntry->m_LightVP * m_GlobalTransform;
+ // QT3DSMat44 theModelView = inLight->m_GlobalTransform.getInverse() * m_GlobalTransform;
+
+ context.SetActiveShader(&shader->m_Shader);
+ shader->m_MVP.Set(theModelViewProjection);
+ shader->m_CameraPosition.Set(inCamera.m_Position);
+ shader->m_GlobalTransform.Set(m_GlobalTransform);
+ shader->m_CameraProperties.Set(inCameraVec);
+ /*
+ shader->m_CameraDirection.Set( inCamera.GetDirection() );
+
+ shader->m_ShadowMV[0].Set( inShadowMapEntry->m_LightCubeView[0] * m_GlobalTransform );
+ shader->m_ShadowMV[1].Set( inShadowMapEntry->m_LightCubeView[1] * m_GlobalTransform );
+ shader->m_ShadowMV[2].Set( inShadowMapEntry->m_LightCubeView[2] * m_GlobalTransform );
+ shader->m_ShadowMV[3].Set( inShadowMapEntry->m_LightCubeView[3] * m_GlobalTransform );
+ shader->m_ShadowMV[4].Set( inShadowMapEntry->m_LightCubeView[4] * m_GlobalTransform );
+ shader->m_ShadowMV[5].Set( inShadowMapEntry->m_LightCubeView[5] * m_GlobalTransform );
+ shader->m_Projection.Set( inCamera.m_Projection );
+ */
+
+ // tesselation
+ if (m_TessellationMode != TessModeValues::NoTess) {
+ // set uniforms we need
+ shader->m_Tessellation.m_EdgeTessLevel.Set(m_Subset.m_EdgeTessFactor);
+ shader->m_Tessellation.m_InsideTessLevel.Set(m_Subset.m_InnerTessFactor);
+ // the blend value is hardcoded
+ shader->m_Tessellation.m_PhongBlend.Set(0.75);
+ // set distance range value
+ shader->m_Tessellation.m_DistanceRange.Set(inCameraVec);
+ // disable culling
+ shader->m_Tessellation.m_DisableCulling.Set(1.0);
+ }
+
+ context.SetInputAssembler(pIA);
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ }
+
+ void SSubsetRenderableBase::RenderDepthPass(const QT3DSVec2 &inCameraVec,
+ SRenderableImage *inDisplacementImage,
+ float inDisplacementAmount)
+ {
+ NVRenderContext &context(m_Generator.GetContext());
+ SRenderableDepthPrepassShader *shader = NULL;
+ NVRenderInputAssembler *pIA = NULL;
+ SRenderableImage *displacementImage = inDisplacementImage;
+
+ if (m_Subset.m_PrimitiveType != NVRenderDrawMode::Patches)
+ shader = m_Generator.GetDepthPrepassShader(displacementImage != NULL);
+ else
+ shader = m_Generator.GetDepthTessPrepassShader(m_TessellationMode,
+ displacementImage != NULL);
+
+ if (shader == NULL)
+ return;
+
+ // for phong and npatch tesselleation or displacement mapping we need the normals (and uv's)
+ // too
+ if ((m_TessellationMode == TessModeValues::NoTess
+ || m_TessellationMode == TessModeValues::TessLinear)
+ && !displacementImage)
+ pIA = m_Subset.m_InputAssemblerDepth;
+ else
+ pIA = m_Subset.m_InputAssembler;
+
+ context.SetActiveShader(&shader->m_Shader);
+ context.SetCullingEnabled(true);
+
+ shader->m_MVP.Set(m_ModelContext.m_ModelViewProjection);
+
+ if (displacementImage) {
+ // setup image transform
+ const QT3DSMat44 &textureTransform = displacementImage->m_Image.m_TextureTransform;
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ QT3DSVec3 offsets(dataPtr[12], dataPtr[13],
+ displacementImage->m_Image.m_TextureData.m_TextureFlags.IsPreMultiplied()
+ ? 1.0f
+ : 0.0f);
+ QT3DSVec4 rotations(dataPtr[0], dataPtr[4], dataPtr[1], dataPtr[5]);
+ displacementImage->m_Image.m_TextureData.m_Texture->SetTextureWrapS(
+ displacementImage->m_Image.m_HorizontalTilingMode);
+ displacementImage->m_Image.m_TextureData.m_Texture->SetTextureWrapT(
+ displacementImage->m_Image.m_VerticalTilingMode);
+
+ shader->m_DisplaceAmount.Set(inDisplacementAmount);
+ shader->m_DisplacementProps.m_Offsets.Set(offsets);
+ shader->m_DisplacementProps.m_Rotations.Set(rotations);
+ shader->m_DisplacementProps.m_Sampler.Set(
+ displacementImage->m_Image.m_TextureData.m_Texture);
+ }
+
+ // tesselation
+ if (m_TessellationMode != TessModeValues::NoTess) {
+ // set uniforms we need
+ shader->m_GlobalTransform.Set(m_GlobalTransform);
+
+ if (m_Generator.GetLayerRenderData() && m_Generator.GetLayerRenderData()->m_Camera)
+ shader->m_CameraPosition.Set(
+ m_Generator.GetLayerRenderData()->m_Camera->GetGlobalPos());
+ else if (m_Generator.GetLayerRenderData()->m_Camera)
+ shader->m_CameraPosition.Set(QT3DSVec3(0.0, 0.0, 1.0));
+
+ shader->m_Tessellation.m_EdgeTessLevel.Set(m_Subset.m_EdgeTessFactor);
+ shader->m_Tessellation.m_InsideTessLevel.Set(m_Subset.m_InnerTessFactor);
+ // the blend value is hardcoded
+ shader->m_Tessellation.m_PhongBlend.Set(0.75);
+ // set distance range value
+ shader->m_Tessellation.m_DistanceRange.Set(inCameraVec);
+ // enable culling
+ shader->m_Tessellation.m_DisableCulling.Set(0.0);
+ }
+
+ context.SetInputAssembler(pIA);
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ }
+
+ // An interface to the shader generator that is available to the renderables
+
+ void SSubsetRenderable::Render(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet)
+ {
+ NVRenderContext &context(m_Generator.GetContext());
+
+ SShaderGeneratorGeneratedShader *shader = m_Generator.GetShader(*this, inFeatureSet);
+ if (shader == NULL)
+ return;
+
+ context.SetActiveShader(&shader->m_Shader);
+
+ m_Generator.GetUICContext().GetDefaultMaterialShaderGenerator().SetMaterialProperties(
+ shader->m_Shader, m_Material, inCameraVec, m_ModelContext.m_ModelViewProjection,
+ m_ModelContext.m_NormalMatrix, m_ModelContext.m_Model.m_GlobalTransform, m_FirstImage,
+ m_Opacity, m_Generator.GetLayerGlobalRenderProperties());
+
+ // tesselation
+ if (m_Subset.m_PrimitiveType == NVRenderDrawMode::Patches) {
+ shader->m_Tessellation.m_EdgeTessLevel.Set(m_Subset.m_EdgeTessFactor);
+ shader->m_Tessellation.m_InsideTessLevel.Set(m_Subset.m_InnerTessFactor);
+ // the blend value is hardcoded
+ shader->m_Tessellation.m_PhongBlend.Set(0.75);
+ // this should finally be based on some user input
+ shader->m_Tessellation.m_DistanceRange.Set(inCameraVec);
+ // enable culling
+ shader->m_Tessellation.m_DisableCulling.Set(0.0);
+
+ if (m_Subset.m_WireframeMode) {
+ // we need the viewport matrix
+ NVRenderRect theViewport(context.GetViewport());
+ QT3DSMat44 vpMatrix;
+ vpMatrix.column0 = QT3DSVec4((float)theViewport.m_Width / 2.0f, 0.0, 0.0, 0.0);
+ vpMatrix.column1 = QT3DSVec4(0.0, (float)theViewport.m_Height / 2.0f, 0.0, 0.0);
+ vpMatrix.column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ vpMatrix.column3 =
+ QT3DSVec4((float)theViewport.m_Width / 2.0f + (float)theViewport.m_X,
+ (float)theViewport.m_Height / 2.0f + (float)theViewport.m_Y, 0.0, 1.0);
+
+ shader->m_ViewportMatrix.Set(vpMatrix);
+ }
+ }
+
+ context.SetCullingEnabled(true);
+ context.SetInputAssembler(m_Subset.m_InputAssembler);
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ }
+
+ void SSubsetRenderable::RenderDepthPass(const QT3DSVec2 &inCameraVec)
+ {
+ SRenderableImage *displacementImage = NULL;
+ for (SRenderableImage *theImage = m_FirstImage;
+ theImage != NULL && displacementImage == NULL; theImage = theImage->m_NextImage) {
+ if (theImage->m_MapType == ImageMapTypes::Displacement)
+ displacementImage = theImage;
+ }
+ SSubsetRenderableBase::RenderDepthPass(inCameraVec, displacementImage,
+ m_Material.m_DisplaceAmount);
+ }
+
+ void STextRenderable::Render(const QT3DSVec2 &inCameraVec)
+ {
+ NVRenderContext &context(m_Generator.GetContext());
+
+ if (!m_Text.m_PathFontDetails) {
+
+ STextRenderHelper theInfo = m_Generator.GetShader(*this, false);
+ if (theInfo.m_Shader == NULL)
+ return;
+ // All of our shaders produce premultiplied values.
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc(
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha);
+
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+
+ context.SetBlendFunction(blendFunc);
+ context.SetBlendEquation(blendEqu);
+ QT3DSVec4 theColor(m_Text.m_TextColor, m_Text.m_GlobalOpacity);
+
+ STextShader &shader(*theInfo.m_Shader);
+ shader.Render(*m_Text.m_TextTexture, *this, theColor, m_ModelViewProjection,
+ inCameraVec, context, theInfo.m_QuadInputAssembler,
+ theInfo.m_QuadInputAssembler.GetIndexCount(), m_Text.m_TextTextureDetails,
+ QT3DSVec3(0, 0, 0));
+ } else {
+ QT3DS_ASSERT(context.IsPathRenderingSupported() && context.IsProgramPipelineSupported());
+
+ STextRenderHelper theInfo = m_Generator.GetShader(*this, true);
+ if (theInfo.m_Shader == NULL)
+ return;
+
+ // All of our shaders produce premultiplied values.
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc(
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha);
+
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+
+ context.SetBlendFunction(blendFunc);
+ context.SetBlendEquation(blendEqu);
+ QT3DSVec4 theColor(m_Text.m_TextColor, m_Text.m_GlobalOpacity);
+
+ STextShader &shader(*theInfo.m_Shader);
+
+ shader.RenderPath(*m_Text.m_PathFontItem, *m_Text.m_PathFontDetails, *this, theColor,
+ m_ViewProjection, m_GlobalTransform, inCameraVec, context,
+ m_Text.m_TextTextureDetails, QT3DSVec3(0, 0, 0));
+ }
+ }
+
+ void STextRenderable::RenderDepthPass(const QT3DSVec2 &inCameraVec)
+ {
+ NVRenderContext &context(m_Generator.GetContext());
+ STextDepthShader *theDepthShader = m_Generator.GetTextDepthShader();
+ if (theDepthShader == NULL)
+ return;
+
+ if (!m_Text.m_PathFontDetails) {
+ // we may change stencil test state
+ qt3ds::render::NVRenderContextScopedProperty<bool> __stencilTest(
+ context, &NVRenderContext::IsStencilTestEnabled,
+ &NVRenderContext::SetStencilTestEnabled, true);
+
+ NVRenderShaderProgram &theShader(theDepthShader->m_Shader);
+ context.SetCullingEnabled(false);
+ context.SetActiveShader(&theShader);
+ theDepthShader->m_MVP.Set(m_ModelViewProjection);
+ theDepthShader->m_Sampler.Set(m_Text.m_TextTexture);
+ const STextScaleAndOffset &theScaleAndOffset(*this);
+ theDepthShader->m_Dimensions.Set(
+ QT3DSVec4(theScaleAndOffset.m_TextScale.x, theScaleAndOffset.m_TextScale.y,
+ theScaleAndOffset.m_TextOffset.x, theScaleAndOffset.m_TextOffset.y));
+ theDepthShader->m_CameraProperties.Set(inCameraVec);
+
+ STextureDetails theTextureDetails = m_Text.m_TextTexture->GetTextureDetails();
+ const STextTextureDetails &theTextTextureDetails(m_Text.m_TextTextureDetails);
+ QT3DSF32 theWidthScale =
+ (QT3DSF32)theTextTextureDetails.m_TextWidth / (QT3DSF32)theTextureDetails.m_Width;
+ QT3DSF32 theHeightScale =
+ (QT3DSF32)theTextTextureDetails.m_TextHeight / (QT3DSF32)theTextureDetails.m_Height;
+ theDepthShader->m_TextDimensions.Set(
+ QT3DSVec3(theWidthScale, theHeightScale, theTextTextureDetails.m_FlipY ? 1.0f : 0.0f));
+ context.SetInputAssembler(&theDepthShader->m_QuadInputAssembler);
+ context.Draw(NVRenderDrawMode::Triangles,
+ theDepthShader->m_QuadInputAssembler.GetIndexCount(), 0);
+ } else {
+ qt3ds::render::NVRenderBoolOp::Enum theDepthFunction = context.GetDepthFunction();
+ bool isDepthEnabled = context.IsDepthTestEnabled();
+ bool isStencilEnabled = context.IsStencilTestEnabled();
+ bool isDepthWriteEnabled = context.IsDepthWriteEnabled();
+ qt3ds::render::NVRenderStencilFunctionArgument theArg(qt3ds::render::NVRenderBoolOp::NotEqual,
+ 0, 0xFF);
+ qt3ds::render::NVRenderStencilOperationArgument theOpArg(
+ qt3ds::render::NVRenderStencilOp::Keep, qt3ds::render::NVRenderStencilOp::Keep,
+ qt3ds::render::NVRenderStencilOp::Zero);
+ NVScopedRefCounted<NVRenderDepthStencilState> depthStencilState =
+ context.CreateDepthStencilState(isDepthEnabled, isDepthWriteEnabled,
+ theDepthFunction, false, theArg, theArg, theOpArg,
+ theOpArg);
+
+ context.SetActiveShader(NULL);
+ context.SetCullingEnabled(false);
+
+ context.SetDepthStencilState(depthStencilState);
+
+ // setup transform
+ QT3DSMat44 offsetMatrix = QT3DSMat44::createIdentity();
+ offsetMatrix.setPosition(QT3DSVec3(
+ m_TextOffset.x - (QT3DSF32)m_Text.m_TextTextureDetails.m_TextWidth / 2.0f,
+ m_TextOffset.y - (QT3DSF32)m_Text.m_TextTextureDetails.m_TextHeight / 2.0f, 0.0));
+
+ QT3DSMat44 pathMatrix = m_Text.m_PathFontItem->GetTransform();
+
+ context.SetPathProjectionMatrix(m_ViewProjection);
+ context.SetPathModelViewMatrix(m_GlobalTransform * offsetMatrix * pathMatrix);
+
+ // first pass
+ m_Text.m_PathFontDetails->StencilFillPathInstanced(*m_Text.m_PathFontItem);
+
+ // second pass
+ context.SetStencilTestEnabled(true);
+ m_Text.m_PathFontDetails->CoverFillPathInstanced(*m_Text.m_PathFontItem);
+
+ context.SetStencilTestEnabled(isStencilEnabled);
+ context.SetDepthFunction(theDepthFunction);
+ }
+ }
+
+ void SCustomMaterialRenderable::Render(const QT3DSVec2 & /*inCameraVec*/,
+ const SLayerRenderData &inLayerData,
+ const SLayer &inLayer, NVDataRef<SLight *> inLights,
+ const SCamera &inCamera,
+ const NVRenderTexture2D *inDepthTexture,
+ const NVRenderTexture2D *inSsaoTexture,
+ TShaderFeatureSet inFeatureSet)
+ {
+ IUICRenderContext &uicContext(m_Generator.GetUICContext());
+ SCustomMaterialRenderContext theRenderContext(
+ inLayer, inLayerData, inLights, inCamera, m_ModelContext.m_Model, m_Subset,
+ m_ModelContext.m_ModelViewProjection, m_GlobalTransform, m_ModelContext.m_NormalMatrix,
+ m_Material, inDepthTexture, inSsaoTexture, m_ShaderDescription, m_FirstImage);
+
+ uicContext.GetCustomMaterialSystem().RenderSubset(theRenderContext, inFeatureSet);
+ }
+
+ void SCustomMaterialRenderable::RenderDepthPass(const QT3DSVec2 &inCameraVec,
+ const SLayer & /*inLayer*/,
+ NVConstDataRef<SLight *> /*inLights*/
+ ,
+ const SCamera & /*inCamera*/,
+ const NVRenderTexture2D * /*inDepthTexture*/)
+ {
+
+ IUICRenderContext &uicContext(m_Generator.GetUICContext());
+ if (!uicContext.GetCustomMaterialSystem().RenderDepthPrepass(
+ m_ModelContext.m_ModelViewProjection, m_Material, m_Subset)) {
+ SRenderableImage *displacementImage = NULL;
+ for (SRenderableImage *theImage = m_FirstImage;
+ theImage != NULL && displacementImage == NULL; theImage = theImage->m_NextImage) {
+ if (theImage->m_MapType == ImageMapTypes::Displacement)
+ displacementImage = theImage;
+ }
+
+ SSubsetRenderableBase::RenderDepthPass(inCameraVec, displacementImage,
+ m_Material.m_DisplaceAmount);
+ }
+ }
+
+ void SPathRenderable::RenderDepthPass(const QT3DSVec2 &inCameraVec, const SLayer & /*inLayer*/,
+ NVConstDataRef<SLight *> inLights,
+ const SCamera &inCamera,
+ const NVRenderTexture2D * /*inDepthTexture*/)
+ {
+ IUICRenderContext &uicContext(m_Generator.GetUICContext());
+ SPathRenderContext theRenderContext(
+ inLights, inCamera, m_Path, m_ModelViewProjection, m_GlobalTransform, m_NormalMatrix,
+ m_Opacity, m_Material, m_ShaderDescription, m_FirstImage, uicContext.GetWireframeMode(),
+ inCameraVec, false, m_IsStroke);
+
+ uicContext.GetPathManager().RenderDepthPrepass(
+ theRenderContext, m_Generator.GetLayerGlobalRenderProperties(), TShaderFeatureSet());
+ }
+
+ void SPathRenderable::Render(const QT3DSVec2 &inCameraVec, const SLayer & /*inLayer*/,
+ NVConstDataRef<SLight *> inLights, const SCamera &inCamera,
+ const NVRenderTexture2D * /*inDepthTexture*/
+ ,
+ const NVRenderTexture2D * /*inSsaoTexture*/
+ ,
+ TShaderFeatureSet inFeatureSet)
+ {
+ IUICRenderContext &uicContext(m_Generator.GetUICContext());
+ SPathRenderContext theRenderContext(
+ inLights, inCamera, m_Path, m_ModelViewProjection, m_GlobalTransform, m_NormalMatrix,
+ m_Opacity, m_Material, m_ShaderDescription, m_FirstImage, uicContext.GetWireframeMode(),
+ inCameraVec, m_RenderableFlags.HasTransparency(), m_IsStroke);
+
+ uicContext.GetPathManager().RenderPath(
+ theRenderContext, m_Generator.GetLayerGlobalRenderProperties(), inFeatureSet);
+ }
+
+ void SPathRenderable::RenderShadowMapPass(const QT3DSVec2 &inCameraVec, const SLight *inLight,
+ const SCamera &inCamera,
+ SShadowMapEntry *inShadowMapEntry)
+ {
+ NVConstDataRef<SLight *> theLights;
+ IUICRenderContext &uicContext(m_Generator.GetUICContext());
+
+ QT3DSMat44 theModelViewProjection = inShadowMapEntry->m_LightVP * m_GlobalTransform;
+ SPathRenderContext theRenderContext(
+ theLights, inCamera, m_Path, theModelViewProjection, m_GlobalTransform, m_NormalMatrix,
+ m_Opacity, m_Material, m_ShaderDescription, m_FirstImage, uicContext.GetWireframeMode(),
+ inCameraVec, false, m_IsStroke);
+
+ if (inLight->m_LightType != RenderLightTypes::Directional) {
+ uicContext.GetPathManager().RenderCubeFaceShadowPass(
+ theRenderContext, m_Generator.GetLayerGlobalRenderProperties(),
+ TShaderFeatureSet());
+ } else
+ uicContext.GetPathManager().RenderShadowMapPass(
+ theRenderContext, m_Generator.GetLayerGlobalRenderProperties(),
+ TShaderFeatureSet());
+ }
+}
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.h b/src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.h
new file mode 100644
index 00000000..5d3e7c29
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRenderableObjects.h
@@ -0,0 +1,419 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_IMPL_RENDERABLE_OBJECTS_H
+#define UIC_RENDER_IMPL_RENDERABLE_OBJECTS_H
+#include "UICRender.h"
+#include "foundation/Qt3DSFlags.h"
+#include "UICRenderModel.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderText.h"
+#include "UICRenderMesh.h"
+#include "UICRenderShaderKeys.h"
+#include "UICRenderShaderCache.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "UICRenderableImage.h"
+
+namespace uic {
+namespace render {
+
+ struct RenderPreparationResultFlagValues
+ {
+ enum Enum {
+ HasTransparency = 1 << 0,
+ CompletelyTransparent = 1 << 1,
+ Dirty = 1 << 2,
+ Pickable = 1 << 3,
+ DefaultMaterialMeshSubset = 1 << 4,
+ Text = 1 << 5,
+ Custom = 1 << 6,
+ CustomMaterialMeshSubset = 1 << 7,
+ HasRefraction = 1 << 8,
+ Path = 1 << 9,
+ };
+ };
+
+ struct SRenderableObjectFlags : public NVFlags<RenderPreparationResultFlagValues::Enum, QT3DSU32>
+ {
+ void ClearOrSet(bool value, RenderPreparationResultFlagValues::Enum enumVal)
+ {
+ if (value)
+ this->operator|=(enumVal);
+ else
+ clear(enumVal);
+ }
+
+ void SetHasTransparency(bool inHasTransparency)
+ {
+ ClearOrSet(inHasTransparency, RenderPreparationResultFlagValues::HasTransparency);
+ }
+ bool HasTransparency() const
+ {
+ return this->operator&(RenderPreparationResultFlagValues::HasTransparency);
+ }
+ bool HasRefraction() const
+ {
+ return this->operator&(RenderPreparationResultFlagValues::HasRefraction);
+ }
+ void SetCompletelyTransparent(bool inTransparent)
+ {
+ ClearOrSet(inTransparent, RenderPreparationResultFlagValues::CompletelyTransparent);
+ }
+ bool IsCompletelyTransparent() const
+ {
+ return this->operator&(RenderPreparationResultFlagValues::CompletelyTransparent);
+ }
+ void SetDirty(bool inDirty)
+ {
+ ClearOrSet(inDirty, RenderPreparationResultFlagValues::Dirty);
+ }
+ bool IsDirty() const { return this->operator&(RenderPreparationResultFlagValues::Dirty); }
+ void SetPickable(bool inPickable)
+ {
+ ClearOrSet(inPickable, RenderPreparationResultFlagValues::Pickable);
+ }
+ bool GetPickable() const
+ {
+ return this->operator&(RenderPreparationResultFlagValues::Pickable);
+ }
+
+ // Mutually exclusive values
+ void SetDefaultMaterialMeshSubset(bool inMeshSubset)
+ {
+ ClearOrSet(inMeshSubset, RenderPreparationResultFlagValues::DefaultMaterialMeshSubset);
+ }
+ bool IsDefaultMaterialMeshSubset() const
+ {
+ return this->operator&(RenderPreparationResultFlagValues::DefaultMaterialMeshSubset);
+ }
+
+ void SetCustomMaterialMeshSubset(bool inMeshSubset)
+ {
+ ClearOrSet(inMeshSubset, RenderPreparationResultFlagValues::CustomMaterialMeshSubset);
+ }
+ bool IsCustomMaterialMeshSubset() const
+ {
+ return this->operator&(RenderPreparationResultFlagValues::CustomMaterialMeshSubset);
+ }
+
+ void SetText(bool inText) { ClearOrSet(inText, RenderPreparationResultFlagValues::Text); }
+ bool IsText() const { return this->operator&(RenderPreparationResultFlagValues::Text); }
+
+ void SetCustom(bool inCustom)
+ {
+ ClearOrSet(inCustom, RenderPreparationResultFlagValues::Custom);
+ }
+ bool IsCustom() const { return this->operator&(RenderPreparationResultFlagValues::Custom); }
+
+ void SetPath(bool inPath) { ClearOrSet(inPath, RenderPreparationResultFlagValues::Path); }
+ bool IsPath() const { return this->operator&(RenderPreparationResultFlagValues::Path); }
+ };
+
+ struct SNodeLightEntry
+ {
+ SLight *m_Light;
+ QT3DSU32 m_LightIndex;
+ SNodeLightEntry *m_NextNode;
+ SNodeLightEntry()
+ : m_Light(NULL)
+ , m_NextNode(NULL)
+ {
+ }
+ SNodeLightEntry(SLight *inLight, QT3DSU32 inLightIndex)
+ : m_Light(inLight)
+ , m_LightIndex(inLightIndex)
+ , m_NextNode(NULL)
+ {
+ }
+ };
+
+ DEFINE_INVASIVE_SINGLE_LIST(NodeLightEntry);
+
+ IMPLEMENT_INVASIVE_SINGLE_LIST(NodeLightEntry, m_NextNode);
+
+ struct SRenderableObject;
+
+ typedef void (*TRenderFunction)(SRenderableObject &inObject, const QT3DSVec2 &inCameraProperties);
+
+ struct SRenderableObject
+ {
+ // Variables used for picking
+ const QT3DSMat44 &m_GlobalTransform;
+ const NVBounds3 &m_Bounds;
+ SRenderableObjectFlags m_RenderableFlags;
+ // For rough sorting for transparency and for depth
+ QT3DSVec3 m_WorldCenterPoint;
+ QT3DSF32 m_CameraDistanceSq;
+ TessModeValues::Enum m_TessellationMode;
+ // For custom renderable objects the render function must be defined
+ TRenderFunction m_RenderFunction;
+ TNodeLightEntryList m_ScopedLights;
+ SRenderableObject(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt,
+ const QT3DSMat44 &inGlobalTransform, const NVBounds3 &inBounds,
+ TessModeValues::Enum inTessMode = TessModeValues::NoTess,
+ TRenderFunction inFunction = NULL)
+
+ : m_GlobalTransform(inGlobalTransform)
+ , m_Bounds(inBounds)
+ , m_RenderableFlags(inFlags)
+ , m_WorldCenterPoint(inWorldCenterPt)
+ , m_CameraDistanceSq(0)
+ , m_TessellationMode(inTessMode)
+ , m_RenderFunction(inFunction)
+ {
+ }
+ bool operator<(SRenderableObject *inOther) const
+ {
+ return m_CameraDistanceSq < inOther->m_CameraDistanceSq;
+ }
+ };
+
+ typedef nvvector<SRenderableObject *> TRenderableObjectList;
+
+ // Different subsets from the same model will get the same
+ // model context so we can generate the MVP and normal matrix once
+ // and only once per subset.
+ struct SModelContext
+ {
+ const SModel &m_Model;
+ QT3DSMat44 m_ModelViewProjection;
+ QT3DSMat33 m_NormalMatrix;
+
+ SModelContext(const SModel &inModel, const QT3DSMat44 &inViewProjection)
+ : m_Model(inModel)
+ {
+ m_Model.CalculateMVPAndNormalMatrix(inViewProjection, m_ModelViewProjection,
+ m_NormalMatrix);
+ }
+ SModelContext(const SModelContext &inOther)
+ : m_Model(inOther.m_Model)
+ {
+ // The default copy constructor for these objects is pretty darn slow.
+ memCopy(&m_ModelViewProjection, &inOther.m_ModelViewProjection,
+ sizeof(m_ModelViewProjection));
+ memCopy(&m_NormalMatrix, &inOther.m_NormalMatrix, sizeof(m_NormalMatrix));
+ }
+ };
+
+ typedef nvvector<SModelContext *> TModelContextPtrList;
+
+ class CUICRendererImpl;
+ struct SLayerRenderData;
+ struct SShadowMapEntry;
+
+ struct SSubsetRenderableBase : public SRenderableObject
+ {
+ CUICRendererImpl &m_Generator;
+ const SModelContext &m_ModelContext;
+ SRenderSubset m_Subset;
+ QT3DSF32 m_Opacity;
+
+ SSubsetRenderableBase(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt,
+ CUICRendererImpl &gen, const SRenderSubset &subset,
+ const SModelContext &modelContext, QT3DSF32 inOpacity)
+
+ : SRenderableObject(inFlags, inWorldCenterPt, modelContext.m_Model.m_GlobalTransform,
+ m_Subset.m_Bounds)
+ , m_Generator(gen)
+ , m_ModelContext(modelContext)
+ , m_Subset(subset)
+ , m_Opacity(inOpacity)
+ {
+ }
+ void RenderShadowMapPass(const QT3DSVec2 &inCameraVec, const SLight *inLight,
+ const SCamera &inCamera, SShadowMapEntry *inShadowMapEntry);
+
+ void RenderDepthPass(const QT3DSVec2 &inCameraVec, SRenderableImage *inDisplacementImage,
+ float inDisplacementAmount);
+ };
+
+ /**
+ * A renderable that corresponds to a subset (a part of a model).
+ * These are created per subset per layer and are responsible for actually
+ * rendering this type of object.
+ */
+ struct SSubsetRenderable : public SSubsetRenderableBase
+ {
+ const SDefaultMaterial &m_Material;
+ SRenderableImage *m_FirstImage;
+ SShaderDefaultMaterialKey m_ShaderDescription;
+ NVConstDataRef<QT3DSMat44> m_Bones;
+
+ SSubsetRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt,
+ CUICRendererImpl &gen, const SRenderSubset &subset,
+ const SDefaultMaterial &mat, const SModelContext &modelContext,
+ QT3DSF32 inOpacity, SRenderableImage *inFirstImage,
+ SShaderDefaultMaterialKey inShaderKey,
+ NVConstDataRef<QT3DSMat44> inBoneGlobals)
+
+ : SSubsetRenderableBase(inFlags, inWorldCenterPt, gen, subset, modelContext, inOpacity)
+ , m_Material(mat)
+ , m_FirstImage(inFirstImage)
+ , m_ShaderDescription(inShaderKey)
+ , m_Bones(inBoneGlobals)
+ {
+ m_RenderableFlags.SetDefaultMaterialMeshSubset(true);
+ m_RenderableFlags.SetCustom(false);
+ m_RenderableFlags.SetText(false);
+ }
+
+ void Render(const QT3DSVec2 &inCameraVec, TShaderFeatureSet inFeatureSet);
+
+ void RenderDepthPass(const QT3DSVec2 &inCameraVec);
+
+ DefaultMaterialBlendMode::Enum getBlendingMode()
+ {
+ return m_Material.m_BlendMode;
+ }
+ };
+
+ struct SCustomMaterialRenderable : public SSubsetRenderableBase
+ {
+ const SCustomMaterial &m_Material;
+ SRenderableImage *m_FirstImage;
+ SShaderDefaultMaterialKey m_ShaderDescription;
+
+ SCustomMaterialRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt,
+ CUICRendererImpl &gen, const SRenderSubset &subset,
+ const SCustomMaterial &mat, const SModelContext &modelContext,
+ QT3DSF32 inOpacity, SRenderableImage *inFirstImage,
+ SShaderDefaultMaterialKey inShaderKey)
+ : SSubsetRenderableBase(inFlags, inWorldCenterPt, gen, subset, modelContext, inOpacity)
+ , m_Material(mat)
+ , m_FirstImage(inFirstImage)
+ , m_ShaderDescription(inShaderKey)
+ {
+ m_RenderableFlags.SetCustomMaterialMeshSubset(true);
+ }
+
+ void Render(const QT3DSVec2 &inCameraVec, const SLayerRenderData &inLayerData,
+ const SLayer &inLayer, NVDataRef<SLight *> inLights, const SCamera &inCamera,
+ const NVRenderTexture2D *inDepthTexture, const NVRenderTexture2D *inSsaoTexture,
+ TShaderFeatureSet inFeatureSet);
+
+ void RenderDepthPass(const QT3DSVec2 &inCameraVec, const SLayer &inLayer,
+ NVConstDataRef<SLight *> inLights, const SCamera &inCamera,
+ const NVRenderTexture2D *inDepthTexture);
+ };
+
+ struct STextScaleAndOffset
+ {
+ QT3DSVec2 m_TextOffset;
+ QT3DSVec2 m_TextScale;
+ STextScaleAndOffset(const QT3DSVec2 &inTextOffset, const QT3DSVec2 &inTextScale)
+ : m_TextOffset(inTextOffset)
+ , m_TextScale(inTextScale)
+ {
+ }
+ STextScaleAndOffset(NVRenderTexture2D &inTexture, const STextTextureDetails &inTextDetails,
+ const STextRenderInfo &inInfo);
+ };
+
+ struct STextRenderable : public SRenderableObject, public STextScaleAndOffset
+ {
+ CUICRendererImpl &m_Generator;
+ const SText &m_Text;
+ NVRenderTexture2D &m_Texture;
+ QT3DSMat44 m_ModelViewProjection;
+ QT3DSMat44 m_ViewProjection;
+
+ STextRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt,
+ CUICRendererImpl &gen, const SText &inText, const NVBounds3 &inBounds,
+ const QT3DSMat44 &inModelViewProjection, const QT3DSMat44 &inViewProjection,
+ NVRenderTexture2D &inTextTexture, const QT3DSVec2 &inTextOffset,
+ const QT3DSVec2 &inTextScale)
+ : SRenderableObject(inFlags, inWorldCenterPt, inText.m_GlobalTransform, inBounds)
+ , STextScaleAndOffset(inTextOffset, inTextScale)
+ , m_Generator(gen)
+ , m_Text(inText)
+ , m_Texture(inTextTexture)
+ , m_ModelViewProjection(inModelViewProjection)
+ , m_ViewProjection(inViewProjection)
+ {
+ m_RenderableFlags.SetDefaultMaterialMeshSubset(false);
+ m_RenderableFlags.SetCustom(false);
+ m_RenderableFlags.SetText(true);
+ }
+
+ void Render(const QT3DSVec2 &inCameraVec);
+ void RenderDepthPass(const QT3DSVec2 &inCameraVec);
+ };
+
+ struct SPathRenderable : public SRenderableObject
+ {
+ CUICRendererImpl &m_Generator;
+ SPath &m_Path;
+ NVBounds3 m_Bounds;
+ QT3DSMat44 m_ModelViewProjection;
+ QT3DSMat33 m_NormalMatrix;
+ const SGraphObject &m_Material;
+ QT3DSF32 m_Opacity;
+ SRenderableImage *m_FirstImage;
+ SShaderDefaultMaterialKey m_ShaderDescription;
+ bool m_IsStroke;
+
+ SPathRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt,
+ CUICRendererImpl &gen, const QT3DSMat44 &inGlobalTransform,
+ NVBounds3 &inBounds, SPath &inPath, const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 inNormalMat, const SGraphObject &inMaterial, QT3DSF32 inOpacity,
+ SShaderDefaultMaterialKey inShaderKey, bool inIsStroke)
+
+ : SRenderableObject(inFlags, inWorldCenterPt, inGlobalTransform, m_Bounds)
+ , m_Generator(gen)
+ , m_Path(inPath)
+ , m_Bounds(inBounds)
+ , m_ModelViewProjection(inModelViewProjection)
+ , m_NormalMatrix(inNormalMat)
+ , m_Material(inMaterial)
+ , m_Opacity(inOpacity)
+ , m_FirstImage(NULL)
+ , m_ShaderDescription(inShaderKey)
+ , m_IsStroke(inIsStroke)
+ {
+ m_RenderableFlags.SetPath(true);
+ }
+ void Render(const QT3DSVec2 &inCameraVec, const SLayer &inLayer,
+ NVConstDataRef<SLight *> inLights, const SCamera &inCamera,
+ const NVRenderTexture2D *inDepthTexture, const NVRenderTexture2D *inSsaoTexture,
+ TShaderFeatureSet inFeatureSet);
+
+ void RenderDepthPass(const QT3DSVec2 &inCameraVec, const SLayer &inLayer,
+ NVConstDataRef<SLight *> inLights, const SCamera &inCamera,
+ const NVRenderTexture2D *inDepthTexture);
+
+ void RenderShadowMapPass(const QT3DSVec2 &inCameraVec, const SLight *inLight,
+ const SCamera &inCamera, SShadowMapEntry *inShadowMapEntry);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp
new file mode 100644
index 00000000..592b41d5
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.cpp
@@ -0,0 +1,2007 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRender.h"
+#include "UICRenderer.h"
+#include "UICRendererImpl.h"
+#include "UICRenderContext.h"
+#include "UICRenderCamera.h"
+#include "UICRenderLight.h"
+#include "UICRenderImage.h"
+#include "UICRenderBufferManager.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "UICOffscreenRenderManager.h"
+#include "EASTL/sort.h"
+#include "UICRenderContext.h"
+#include "UICTextRenderer.h"
+#include "UICRenderScene.h"
+#include "UICRenderPresentation.h"
+#include "UICRenderEffect.h"
+#include "UICRenderEffectSystem.h"
+#include "UICRenderResourceManager.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "UICRenderTextTextureCache.h"
+#include "UICRenderTextTextureAtlas.h"
+#include "UICRenderMaterialHelpers.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderRenderList.h"
+#include "UICRenderPath.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+#include <stdlib.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4355)
+#endif
+
+// Quick tests you can run to find performance problems
+
+//#define UIC_RENDER_DISABLE_HARDWARE_BLENDING 1
+//#define UIC_RENDER_DISABLE_LIGHTING 1
+//#define UIC_RENDER_DISABLE_TEXTURING 1
+//#define UIC_RENDER_DISABLE_TRANSPARENCY 1
+//#define UIC_RENDER_DISABLE_FRUSTUM_CULLING 1
+
+// If you are fillrate bound then sorting opaque objects can help in some circumstances
+//#define UIC_RENDER_DISABLE_OPAQUE_SORT 1
+
+using qt3ds::foundation::CRegisteredString;
+
+namespace uic {
+namespace render {
+
+ struct SRenderableImage;
+ struct SShaderGeneratorGeneratedShader;
+ struct SSubsetRenderable;
+ using eastl::make_pair;
+ using eastl::reverse;
+ using eastl::stable_sort;
+
+ SEndlType Endl;
+
+ CUICRendererImpl::CUICRendererImpl(IUICRenderContext &ctx)
+ : m_UICContext(ctx)
+ , m_Context(ctx.GetRenderContext())
+ , m_BufferManager(ctx.GetBufferManager())
+ , m_OffscreenRenderManager(ctx.GetOffscreenRenderManager())
+ , m_StringTable(IStringTable::CreateStringTable(ctx.GetAllocator()))
+ , m_LayerShaders(ctx.GetAllocator(), "CUICRendererImpl::m_LayerShaders")
+ , m_Shaders(ctx.GetAllocator(), "CUICRendererImpl::m_Shaders")
+ , m_ConstantBuffers(ctx.GetAllocator(), "CUICRendererImpl::m_ConstantBuffers")
+ , m_TextShader(ctx.GetAllocator())
+ , m_TextPathShader(ctx.GetAllocator())
+ , m_TextWidgetShader(ctx.GetAllocator())
+ , m_TextOnscreenShader(ctx.GetAllocator())
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ , m_LayerBlendTexture(ctx.GetResourceManager())
+ , m_BlendFB(NULL)
+#endif
+ , m_LayerToRenderMap(ctx.GetAllocator(), "CUICRendererImpl::m_LayerToRenderMap")
+ , m_LastFrameLayers(ctx.GetAllocator(), "CUICRendererImpl::m_LastFrameLayers")
+ , mRefCount(0)
+ , m_LastPickResults(ctx.GetAllocator(), "CUICRendererImpl::m_LastPickResults")
+ , m_CurrentLayer(NULL)
+ , m_WidgetVertexBuffers(ctx.GetAllocator(), "CUICRendererImpl::m_WidgetVertexBuffers")
+ , m_WidgetIndexBuffers(ctx.GetAllocator(), "CUICRendererImpl::m_WidgetIndexBuffers")
+ , m_WidgetShaders(ctx.GetAllocator(), "CUICRendererImpl::m_WidgetShaders")
+ , m_WidgetInputAssembler(ctx.GetAllocator(), "CUICRendererImpl::m_WidgetInputAssembler")
+ , m_BoneIdNodeMap(ctx.GetAllocator(), "CUICRendererImpl::m_BoneIdNodeMap")
+ , m_PickRenderPlugins(true)
+ , m_LayerCachingEnabled(true)
+ , m_LayerGPuProfilingEnabled(false)
+ {
+ }
+ CUICRendererImpl::~CUICRendererImpl()
+ {
+ m_LayerShaders.clear();
+ for (TShaderMap::iterator iter = m_Shaders.begin(), end = m_Shaders.end(); iter != end;
+ ++iter)
+ NVDelete(m_Context->GetAllocator(), iter->second);
+
+ m_Shaders.clear();
+ m_LayerToRenderMap.clear();
+ m_ConstantBuffers.clear();
+ }
+
+ void CUICRendererImpl::addRef() { atomicIncrement(&mRefCount); }
+
+ void CUICRendererImpl::release() { QT3DS_IMPLEMENT_REF_COUNT_RELEASE(m_Context->GetAllocator()); }
+
+ void CUICRendererImpl::ChildrenUpdated(SNode &inParent)
+ {
+ if (inParent.m_Type == GraphObjectTypes::Layer) {
+ TLayerRenderMap::iterator theIter =
+ m_LayerToRenderMap.find(static_cast<SLayer *>(&inParent));
+ if (theIter != m_LayerToRenderMap.end()) {
+ theIter->second->m_CamerasAndLights.clear();
+ theIter->second->m_RenderableNodes.clear();
+ }
+ } else if (inParent.m_Parent)
+ ChildrenUpdated(*inParent.m_Parent);
+ }
+
+ QT3DSF32 CUICRendererImpl::GetTextScale(const SText &inText)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inText);
+ if (theData)
+ return theData->m_TextScale;
+ return 1.0f;
+ }
+
+ static inline SLayer *GetNextLayer(SLayer &inLayer)
+ {
+ if (inLayer.m_NextSibling && inLayer.m_NextSibling->m_Type == GraphObjectTypes::Layer)
+ return static_cast<SLayer *>(inLayer.m_NextSibling);
+ return NULL;
+ }
+
+ static inline void MaybePushLayer(SLayer &inLayer, nvvector<SLayer *> &outLayerList)
+ {
+ inLayer.CalculateGlobalVariables();
+ if (inLayer.m_Flags.IsGloballyActive() && inLayer.m_Flags.IsLayerRenderToTarget())
+ outLayerList.push_back(&inLayer);
+ }
+ static void BuildRenderableLayers(SLayer &inLayer, nvvector<SLayer *> &renderableLayers,
+ bool inRenderSiblings)
+ {
+ MaybePushLayer(inLayer, renderableLayers);
+ if (inRenderSiblings) {
+ for (SLayer *theNextLayer = GetNextLayer(inLayer); theNextLayer;
+ theNextLayer = GetNextLayer(*theNextLayer))
+ MaybePushLayer(*theNextLayer, renderableLayers);
+ }
+ }
+
+ bool CUICRendererImpl::PrepareLayerForRender(SLayer &inLayer,
+ const QT3DSVec2 &inViewportDimensions,
+ bool inRenderSiblings)
+ {
+ (void)inViewportDimensions;
+ nvvector<SLayer *> renderableLayers(m_UICContext.GetPerFrameAllocator(), "LayerVector");
+ // Found by fair roll of the dice.
+ renderableLayers.reserve(4);
+
+ BuildRenderableLayers(inLayer, renderableLayers, inRenderSiblings);
+
+ bool retval = false;
+
+ for (nvvector<SLayer *>::reverse_iterator iter = renderableLayers.rbegin(),
+ end = renderableLayers.rend();
+ iter != end; ++iter) {
+ // Store the previous state of if we were rendering a layer.
+ SLayer *theLayer = *iter;
+ SLayerRenderData *theRenderData = GetOrCreateLayerRenderDataForNode(*theLayer);
+
+ if (theRenderData) {
+ theRenderData->PrepareForRender();
+ retval = retval || theRenderData->m_LayerPrepResult->m_Flags.WasDirty();
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ return retval;
+ }
+
+ void CUICRendererImpl::RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ bool clear, QT3DSVec3 clearColor, bool inRenderSiblings)
+ {
+ (void)inViewportDimensions;
+ nvvector<SLayer *> renderableLayers(m_UICContext.GetPerFrameAllocator(), "LayerVector");
+ // Found by fair roll of the dice.
+ renderableLayers.reserve(4);
+
+ BuildRenderableLayers(inLayer, renderableLayers, inRenderSiblings);
+
+ NVRenderContext &theRenderContext(m_UICContext.GetRenderContext());
+ qt3ds::render::NVRenderFrameBuffer *theFB = theRenderContext.GetRenderTarget();
+ for (nvvector<SLayer *>::reverse_iterator iter = renderableLayers.rbegin(),
+ end = renderableLayers.rend();
+ iter != end; ++iter) {
+ SLayer *theLayer = *iter;
+ SLayerRenderData *theRenderData = GetOrCreateLayerRenderDataForNode(*theLayer);
+ SLayerRenderPreparationResult &prepRes(*theRenderData->m_LayerPrepResult);
+ LayerBlendTypes::Enum layerBlend = prepRes.GetLayer()->GetLayerBlend();
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ if ((layerBlend == LayerBlendTypes::Overlay ||
+ layerBlend == LayerBlendTypes::ColorBurn ||
+ layerBlend == LayerBlendTypes::ColorDodge) &&
+ !theRenderContext.IsAdvancedBlendHwSupported() &&
+ !theRenderContext.IsAdvancedBlendHwSupportedKHR()) {
+ // Create and set up FBO and texture for advanced blending SW fallback
+ m_LayerBlendTexture.EnsureTexture(prepRes.GetLayerToPresentationViewport().m_Width,
+ prepRes.GetLayerToPresentationViewport().m_Height,
+ NVRenderTextureFormats::RGBA8);
+ if (m_BlendFB == NULL)
+ m_BlendFB = theRenderContext.CreateFrameBuffer();
+ m_BlendFB->Attach(NVRenderFrameBufferAttachments::Color0, *m_LayerBlendTexture);
+ theRenderContext.SetRenderTarget(m_BlendFB);
+ theRenderContext.SetScissorTestEnabled(false);
+ QT3DSVec4 color(0.0f, 0.0f, 0.0f, 0.0f);
+ if (clear) {
+ color.x = clearColor.x;
+ color.y = clearColor.y;
+ color.z = clearColor.z;
+ color.w = 1.0f;
+ }
+ QT3DSVec4 origColor = theRenderContext.GetClearColor();
+ theRenderContext.SetClearColor(color);
+ theRenderContext.Clear(qt3ds::render::NVRenderClearValues::Color);
+ theRenderContext.SetClearColor(origColor);
+ theRenderContext.SetRenderTarget(theFB);
+ break;
+ } else {
+ m_LayerBlendTexture.ReleaseTexture();
+ }
+#endif
+ }
+ for (nvvector<SLayer *>::reverse_iterator iter = renderableLayers.rbegin(),
+ end = renderableLayers.rend();
+ iter != end; ++iter) {
+ // Store the previous state of if we were rendering a layer.
+ SLayer *theLayer = *iter;
+ SLayerRenderData *theRenderData = GetOrCreateLayerRenderDataForNode(*theLayer);
+
+ if (theRenderData) {
+ if (theRenderData->m_LayerPrepResult->IsLayerVisible())
+ theRenderData->RunnableRenderToViewport(theFB);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ SLayer *CUICRendererImpl::GetLayerForNode(const SNode &inNode) const
+ {
+ if (inNode.m_Type == GraphObjectTypes::Layer) {
+ return &const_cast<SLayer &>(static_cast<const SLayer &>(inNode));
+ }
+ if (inNode.m_Parent)
+ return GetLayerForNode(*inNode.m_Parent);
+ return NULL;
+ }
+
+ SLayerRenderData *CUICRendererImpl::GetOrCreateLayerRenderDataForNode(const SNode &inNode)
+ {
+ const SLayer *theLayer = GetLayerForNode(inNode);
+ if (theLayer) {
+ TLayerRenderMap::const_iterator theIter = m_LayerToRenderMap.find(theLayer);
+ if (theIter != m_LayerToRenderMap.end())
+ return const_cast<SLayerRenderData *>(theIter->second.mPtr);
+
+ SLayerRenderData *theRenderData = QT3DS_NEW(m_Context->GetAllocator(), SLayerRenderData)(
+ const_cast<SLayer &>(*theLayer), *this);
+ m_LayerToRenderMap.insert(make_pair(theLayer, theRenderData));
+
+ // create a profiler if enabled
+ if (IsLayerGpuProfilingEnabled() && theRenderData)
+ theRenderData->CreateGpuProfiler();
+
+ return theRenderData;
+ }
+ return NULL;
+ }
+
+ SCamera *CUICRendererImpl::GetCameraForNode(const SNode &inNode) const
+ {
+ SLayerRenderData *theLayer =
+ const_cast<CUICRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
+ if (theLayer)
+ return theLayer->m_Camera;
+ return NULL;
+ }
+
+ Option<SCuboidRect> CUICRendererImpl::GetCameraBounds(const SGraphObject &inObject)
+ {
+ if (GraphObjectTypes::IsNodeType(inObject.m_Type)) {
+ const SNode &theNode = static_cast<const SNode &>(inObject);
+ SLayerRenderData *theLayer = GetOrCreateLayerRenderDataForNode(theNode);
+ if (theLayer->GetOffscreenRenderer() == false) {
+ SCamera *theCamera = theLayer->m_Camera;
+ if (theCamera)
+ return theCamera->GetCameraBounds(
+ theLayer->m_LayerPrepResult->GetLayerToPresentationViewport(),
+ theLayer->m_LayerPrepResult->GetPresentationDesignDimensions());
+ }
+ }
+ return Option<SCuboidRect>();
+ }
+
+ void CUICRendererImpl::DrawScreenRect(NVRenderRectF inRect, const QT3DSVec3 &inColor)
+ {
+ SCamera theScreenCamera;
+ theScreenCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ NVRenderRectF theViewport(m_Context->GetViewport());
+ theScreenCamera.m_Flags.SetOrthographic(true);
+ theScreenCamera.CalculateGlobalVariables(theViewport,
+ QT3DSVec2(theViewport.m_Width, theViewport.m_Height));
+ GenerateXYQuad();
+ if (!m_ScreenRectShader) {
+ IShaderProgramGenerator &theGenerator(GetProgramGenerator());
+ theGenerator.BeginProgram();
+ IShaderStageGenerator &vertexGenerator(
+ *theGenerator.GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *theGenerator.GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddUniform("rectangle_dims", "vec3");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append(
+ "\tgl_Position = model_view_projection * vec4(attr_pos * rectangle_dims, 1.0);");
+ vertexGenerator.Append("}");
+ fragmentGenerator.AddUniform("output_color", "vec3");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tgl_FragColor.rgb = output_color;");
+ fragmentGenerator.Append("\tgl_FragColor.a = 1.0;");
+ fragmentGenerator.Append("}");
+ // No flags enabled
+ m_ScreenRectShader = theGenerator.CompileGeneratedShader(
+ "DrawScreenRect", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ }
+ if (m_ScreenRectShader) {
+ // Fudge the rect by one pixel to ensure we see all the corners.
+ if (inRect.m_Width > 1)
+ inRect.m_Width -= 1;
+ if (inRect.m_Height > 1)
+ inRect.m_Height -= 1;
+ inRect.m_X += 1;
+ inRect.m_Y += 1;
+ // Figure out the rect center.
+ SNode theNode;
+
+ QT3DSVec2 rectGlobalCenter = inRect.Center();
+ QT3DSVec2 rectCenter(theViewport.ToNormalizedRectRelative(rectGlobalCenter));
+ theNode.m_Position.x = rectCenter.x;
+ theNode.m_Position.y = rectCenter.y;
+ theNode.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ theNode.CalculateGlobalVariables();
+ QT3DSMat44 theViewProjection;
+ theScreenCamera.CalculateViewProjectionMatrix(theViewProjection);
+ QT3DSMat44 theMVP;
+ QT3DSMat33 theNormal;
+ theNode.CalculateMVPAndNormalMatrix(theViewProjection, theMVP, theNormal);
+ m_Context->SetBlendingEnabled(false);
+ m_Context->SetDepthWriteEnabled(false);
+ m_Context->SetDepthTestEnabled(false);
+ m_Context->SetCullingEnabled(false);
+ m_Context->SetActiveShader(m_ScreenRectShader);
+ m_ScreenRectShader->SetPropertyValue("model_view_projection", theMVP);
+ m_ScreenRectShader->SetPropertyValue("output_color", inColor);
+ m_ScreenRectShader->SetPropertyValue(
+ "rectangle_dims", QT3DSVec3(inRect.m_Width / 2.0f, inRect.m_Height / 2.0f, 0.0f));
+ }
+ if (!m_RectInputAssembler) {
+ QT3DS_ASSERT(m_QuadVertexBuffer);
+ QT3DSU8 indexData[] = { 0, 1, 1, 2, 2, 3, 3, 0 };
+
+ m_RectIndexBuffer = m_Context->CreateIndexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static,
+ qt3ds::render::NVRenderComponentTypes::QT3DSU8, sizeof(indexData),
+ toConstDataRef(indexData, sizeof(indexData)));
+
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ };
+
+ // create our attribute layout
+ m_RectAttribLayout = m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 1));
+
+ QT3DSU32 strides = m_QuadVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_RectInputAssembler = m_Context->CreateInputAssembler(
+ m_RectAttribLayout, toConstDataRef(&m_QuadVertexBuffer.mPtr, 1), m_RectIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+
+ m_Context->SetInputAssembler(m_RectInputAssembler);
+ m_Context->Draw(NVRenderDrawMode::Lines, m_RectIndexBuffer->GetNumIndices(), 0);
+ }
+
+ void CUICRendererImpl::SetupWidgetLayer()
+ {
+ NVRenderContext &theContext = m_UICContext.GetRenderContext();
+
+ if (!m_WidgetTexture) {
+ IResourceManager &theManager = m_UICContext.GetResourceManager();
+ m_WidgetTexture = theManager.AllocateTexture2D(m_BeginFrameViewport.m_Width,
+ m_BeginFrameViewport.m_Height,
+ NVRenderTextureFormats::RGBA8);
+ m_WidgetFBO = theManager.AllocateFrameBuffer();
+ m_WidgetFBO->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*m_WidgetTexture));
+ theContext.SetRenderTarget(m_WidgetFBO);
+
+ // NVRenderRect theScissorRect( 0, 0, m_BeginFrameViewport.m_Width,
+ // m_BeginFrameViewport.m_Height );
+ // NVRenderContextScopedProperty<NVRenderRect> __scissorRect( theContext,
+ // &NVRenderContext::GetScissorRect, &NVRenderContext::SetScissorRect, theScissorRect );
+ qt3ds::render::NVRenderContextScopedProperty<bool> __scissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled, false);
+ m_Context->SetClearColor(QT3DSVec4(0, 0, 0, 0));
+ m_Context->Clear(NVRenderClearValues::Color);
+
+ } else
+ theContext.SetRenderTarget(m_WidgetFBO);
+ }
+
+ void CUICRendererImpl::BeginFrame()
+ {
+ for (QT3DSU32 idx = 0, end = m_LastFrameLayers.size(); idx < end; ++idx)
+ m_LastFrameLayers[idx]->ResetForFrame();
+ m_LastFrameLayers.clear();
+ m_BeginFrameViewport = m_UICContext.GetRenderList().GetViewport();
+ }
+ void CUICRendererImpl::EndFrame()
+ {
+ if (m_WidgetTexture) {
+ using qt3ds::render::NVRenderContextScopedProperty;
+ // Releasing the widget FBO can set it as the active frame buffer.
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __fbo(
+ *m_Context, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ STextureDetails theDetails = m_WidgetTexture->GetTextureDetails();
+ m_Context->SetBlendingEnabled(true);
+ // Colors are expected to be non-premultiplied, so we premultiply alpha into them at
+ // this point.
+ m_Context->SetBlendFunction(qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha));
+ m_Context->SetBlendEquation(qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add));
+
+ m_Context->SetDepthTestEnabled(false);
+ m_Context->SetScissorTestEnabled(false);
+ m_Context->SetViewport(m_BeginFrameViewport);
+ SCamera theCamera;
+ theCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ theCamera.m_Flags.SetOrthographic(true);
+ QT3DSVec2 theTextureDims((QT3DSF32)theDetails.m_Width, (QT3DSF32)theDetails.m_Height);
+ theCamera.CalculateGlobalVariables(
+ NVRenderRect(0, 0, theDetails.m_Width, theDetails.m_Height), theTextureDims);
+ QT3DSMat44 theViewProj;
+ theCamera.CalculateViewProjectionMatrix(theViewProj);
+ RenderQuad(theTextureDims, theViewProj, *m_WidgetTexture);
+
+ IResourceManager &theManager(m_UICContext.GetResourceManager());
+ theManager.Release(*m_WidgetFBO);
+ theManager.Release(*m_WidgetTexture);
+ m_WidgetTexture = NULL;
+ m_WidgetFBO = NULL;
+ }
+ }
+
+ inline bool PickResultLessThan(const SUICRenderPickResult &lhs, const SUICRenderPickResult &rhs)
+ {
+ return FloatLessThan(lhs.m_CameraDistanceSq, rhs.m_CameraDistanceSq);
+ }
+
+ inline QT3DSF32 ClampUVCoord(QT3DSF32 inUVCoord, NVRenderTextureCoordOp::Enum inCoordOp)
+ {
+ if (inUVCoord > 1.0f || inUVCoord < 0.0f) {
+ switch (inCoordOp) {
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ case NVRenderTextureCoordOp::ClampToEdge:
+ inUVCoord = NVMin(inUVCoord, 1.0f);
+ inUVCoord = NVMax(inUVCoord, 0.0f);
+ break;
+ case NVRenderTextureCoordOp::Repeat: {
+ QT3DSF32 multiplier = inUVCoord > 0.0f ? 1.0f : -1.0f;
+ QT3DSF32 clamp = fabs(inUVCoord);
+ clamp = clamp - floor(clamp);
+ if (multiplier < 0)
+ inUVCoord = 1.0f - clamp;
+ else
+ inUVCoord = clamp;
+ } break;
+ case NVRenderTextureCoordOp::MirroredRepeat: {
+ QT3DSF32 multiplier = inUVCoord > 0.0f ? 1.0f : -1.0f;
+ QT3DSF32 clamp = fabs(inUVCoord);
+ if (multiplier > 0.0f)
+ clamp -= 1.0f;
+ QT3DSU32 isMirrored = ((QT3DSU32)clamp) % 2 == 0;
+ QT3DSF32 remainder = clamp - floor(clamp);
+ inUVCoord = remainder;
+ if (isMirrored) {
+ if (multiplier > 0.0f)
+ inUVCoord = 1.0f - inUVCoord;
+ } else {
+ if (multiplier < 0.0f)
+ inUVCoord = 1.0f - remainder;
+ }
+ } break;
+ }
+ }
+ return inUVCoord;
+ }
+
+ static eastl::pair<QT3DSVec2, QT3DSVec2>
+ GetMouseCoordsAndViewportFromSubObject(QT3DSVec2 inLocalHitUVSpace,
+ SUICRenderPickSubResult &inSubResult)
+ {
+ QT3DSMat44 theTextureMatrix(inSubResult.m_TextureMatrix);
+ QT3DSVec3 theNewUVCoords(
+ theTextureMatrix.transform(QT3DSVec3(inLocalHitUVSpace.x, inLocalHitUVSpace.y, 0)));
+ theNewUVCoords.x = ClampUVCoord(theNewUVCoords.x, inSubResult.m_HorizontalTilingMode);
+ theNewUVCoords.y = ClampUVCoord(theNewUVCoords.y, inSubResult.m_VerticalTilingMode);
+ QT3DSVec2 theViewportDimensions =
+ QT3DSVec2((QT3DSF32)inSubResult.m_ViewportWidth, (QT3DSF32)inSubResult.m_ViewportHeight);
+ QT3DSVec2 theMouseCoords(theNewUVCoords.x * theViewportDimensions.x,
+ (1.0f - theNewUVCoords.y) * theViewportDimensions.y);
+
+ return eastl::make_pair(theMouseCoords, theViewportDimensions);
+ }
+
+ SPickResultProcessResult CUICRendererImpl::ProcessPickResultList(bool inPickEverything)
+ {
+ if (m_LastPickResults.empty())
+ return SPickResultProcessResult();
+ // Things are rendered in a particular order and we need to respect that ordering.
+ eastl::stable_sort(m_LastPickResults.begin(), m_LastPickResults.end(), PickResultLessThan);
+
+ // We need to pick against sub objects basically somewhat recursively
+ // but if we don't hit any sub objects and the parent isn't pickable then
+ // we need to move onto the next item in the list.
+ // We need to keep in mind that theQuery->Pick will enter this method in a later
+ // stack frame so *if* we get to sub objects we need to pick against them but if the pick
+ // completely misses *and* the parent object locally pickable is false then we need to move
+ // onto the next object.
+
+ QT3DSU32 maxPerFrameAllocationPickResultCount =
+ SFastAllocator<>::SlabSize / sizeof(SUICRenderPickResult);
+ QT3DSU32 numToCopy =
+ NVMin(maxPerFrameAllocationPickResultCount, (QT3DSU32)m_LastPickResults.size());
+ QT3DSU32 numCopyBytes = numToCopy * sizeof(SUICRenderPickResult);
+ SUICRenderPickResult *thePickResults = reinterpret_cast<SUICRenderPickResult *>(
+ GetPerFrameAllocator().allocate(numCopyBytes, "tempPickData", __FILE__, __LINE__));
+ memCopy(thePickResults, m_LastPickResults.data(), numCopyBytes);
+ m_LastPickResults.clear();
+ bool foundValidResult = false;
+ SPickResultProcessResult thePickResult(thePickResults[0]);
+ for (size_t idx = 0; idx < numToCopy && foundValidResult == false; ++idx) {
+ thePickResult = thePickResults[idx];
+ // Here we do a hierarchy. Picking against sub objects takes precedence.
+ // If picking against the sub object doesn't return a valid result *and*
+ // the current object isn't globally pickable then we move onto the next object returned
+ // by the pick query.
+ if (thePickResult.m_HitObject != NULL && thePickResult.m_FirstSubObject != NULL
+ && m_PickRenderPlugins) {
+ QT3DSVec2 theUVCoords(thePickResult.m_LocalUVCoords.x,
+ thePickResult.m_LocalUVCoords.y);
+ IOffscreenRenderer *theSubRenderer(thePickResult.m_FirstSubObject->m_SubRenderer);
+ eastl::pair<QT3DSVec2, QT3DSVec2> mouseAndViewport =
+ GetMouseCoordsAndViewportFromSubObject(theUVCoords,
+ *thePickResult.m_FirstSubObject);
+ QT3DSVec2 theMouseCoords = mouseAndViewport.first;
+ QT3DSVec2 theViewportDimensions = mouseAndViewport.second;
+ IGraphObjectPickQuery *theQuery = theSubRenderer->GetGraphObjectPickQuery();
+ if (theQuery) {
+ SUICRenderPickResult theInnerPickResult =
+ theQuery->Pick(theMouseCoords, theViewportDimensions, inPickEverything);
+ if (theInnerPickResult.m_HitObject) {
+ thePickResult = theInnerPickResult;
+ thePickResult.m_OffscreenRenderer = theSubRenderer;
+ foundValidResult = true;
+ thePickResult.m_WasPickConsumed = true;
+ } else if (GraphObjectTypes::IsNodeType(thePickResult.m_HitObject->m_Type)) {
+ const SNode *theNode =
+ static_cast<const SNode *>(thePickResult.m_HitObject);
+ if (theNode->m_Flags.IsGloballyPickable() == true) {
+ foundValidResult = true;
+ thePickResult.m_WasPickConsumed = true;
+ }
+ }
+ } else {
+ // If the sub renderer doesn't consume the pick then we return the picked object
+ // itself. So no matter what, if we get to here the pick was consumed.
+ thePickResult.m_WasPickConsumed = true;
+ bool wasPickConsumed =
+ theSubRenderer->Pick(theMouseCoords, theViewportDimensions);
+ if (wasPickConsumed) {
+ thePickResult.m_HitObject = NULL;
+ foundValidResult = true;
+ }
+ }
+ } else {
+ foundValidResult = true;
+ thePickResult.m_WasPickConsumed = true;
+ }
+ }
+ return thePickResult;
+ }
+
+ SUICRenderPickResult CUICRendererImpl::Pick(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords, bool inPickSiblings,
+ bool inPickEverything)
+ {
+ m_LastPickResults.clear();
+
+ SLayer *theLayer = &inLayer;
+ // Stepping through how the original runtime did picking it picked layers in order
+ // stopping at the first hit. So objects on the top layer had first crack at the pick
+ // vector itself.
+ do {
+ if (theLayer->m_Flags.IsActive()) {
+ TLayerRenderMap::iterator theIter = m_LayerToRenderMap.find(theLayer);
+ if (theIter != m_LayerToRenderMap.end()) {
+ m_LastPickResults.clear();
+ GetLayerHitObjectList(*theIter->second, inViewportDimensions, inMouseCoords,
+ inPickEverything, m_LastPickResults,
+ GetPerFrameAllocator());
+ SPickResultProcessResult retval(ProcessPickResultList(inPickEverything));
+ if (retval.m_WasPickConsumed)
+ return retval;
+ } else {
+ // QT3DS_ASSERT( false );
+ }
+ }
+
+ if (inPickSiblings)
+ theLayer = GetNextLayer(*theLayer);
+ else
+ theLayer = NULL;
+ } while (theLayer != NULL);
+
+ return SUICRenderPickResult();
+ }
+
+ static inline Option<QT3DSVec2> IntersectRayWithNode(const SNode &inNode,
+ SRenderableObject &inRenderableObject,
+ const SRay &inPickRay)
+ {
+ if (inRenderableObject.m_RenderableFlags.IsText()) {
+ STextRenderable &theRenderable = static_cast<STextRenderable &>(inRenderableObject);
+ if (&theRenderable.m_Text == &inNode)
+ return inPickRay.GetRelativeXY(inRenderableObject.m_GlobalTransform,
+ inRenderableObject.m_Bounds);
+ } else if (inRenderableObject.m_RenderableFlags.IsDefaultMaterialMeshSubset()) {
+ SSubsetRenderable &theRenderable = static_cast<SSubsetRenderable &>(inRenderableObject);
+ if (&theRenderable.m_ModelContext.m_Model == &inNode)
+ return inPickRay.GetRelativeXY(inRenderableObject.m_GlobalTransform,
+ inRenderableObject.m_Bounds);
+ } else if (inRenderableObject.m_RenderableFlags.IsCustomMaterialMeshSubset()) {
+ SCustomMaterialRenderable &theRenderable =
+ static_cast<SCustomMaterialRenderable &>(inRenderableObject);
+ if (&theRenderable.m_ModelContext.m_Model == &inNode)
+ return inPickRay.GetRelativeXY(inRenderableObject.m_GlobalTransform,
+ inRenderableObject.m_Bounds);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return Empty();
+ }
+
+ static inline SUICRenderPickSubResult ConstructSubResult(SImage &inImage)
+ {
+ STextureDetails theDetails = inImage.m_TextureData.m_Texture->GetTextureDetails();
+ return SUICRenderPickSubResult(*inImage.m_LastFrameOffscreenRenderer,
+ inImage.m_TextureTransform, inImage.m_HorizontalTilingMode,
+ inImage.m_VerticalTilingMode, theDetails.m_Width,
+ theDetails.m_Height);
+ }
+
+ Option<QT3DSVec2> CUICRendererImpl::FacePosition(SNode &inNode, NVBounds3 inBounds,
+ const QT3DSMat44 &inGlobalTransform,
+ const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords,
+ NVDataRef<SGraphObject *> inMapperObjects,
+ SBasisPlanes::Enum inPlane)
+ {
+ SLayerRenderData *theLayerData = GetOrCreateLayerRenderDataForNode(inNode);
+ if (theLayerData == NULL)
+ return Empty();
+ // This function assumes the layer was rendered to the scene itself. There is another
+ // function
+ // for completely offscreen layers that don't get rendered to the scene.
+ bool wasRenderToTarget(theLayerData->m_Layer.m_Flags.IsLayerRenderToTarget());
+ if (wasRenderToTarget == false || theLayerData->m_Camera == NULL
+ || theLayerData->m_LayerPrepResult.hasValue() == false
+ || theLayerData->m_LastFrameOffscreenRenderer.mPtr != NULL)
+ return Empty();
+
+ QT3DSVec2 theMouseCoords(inMouseCoords);
+ QT3DSVec2 theViewportDimensions(inViewportDimensions);
+
+ for (QT3DSU32 idx = 0, end = inMapperObjects.size(); idx < end; ++idx) {
+ SGraphObject &currentObject = *inMapperObjects[idx];
+ if (currentObject.m_Type == GraphObjectTypes::Layer) {
+ // The layer knows its viewport so it can take the information directly.
+ // This is extremely counter intuitive but a good sign.
+ } else if (currentObject.m_Type == GraphObjectTypes::Image) {
+ SImage &theImage = static_cast<SImage &>(currentObject);
+ SModel *theParentModel = NULL;
+ if (theImage.m_Parent
+ && theImage.m_Parent->m_Type == GraphObjectTypes::DefaultMaterial) {
+ SDefaultMaterial *theMaterial =
+ static_cast<SDefaultMaterial *>(theImage.m_Parent);
+ if (theMaterial) {
+ theParentModel = theMaterial->m_Parent;
+ }
+ }
+ if (theParentModel == NULL) {
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ NVBounds3 theModelBounds = theParentModel->GetBounds(
+ GetUICContext().GetBufferManager(), GetUICContext().GetPathManager(), false);
+
+ if (theModelBounds.isEmpty()) {
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ Option<QT3DSVec2> relativeHit =
+ FacePosition(*theParentModel, theModelBounds, theParentModel->m_GlobalTransform,
+ theViewportDimensions, theMouseCoords, NVDataRef<SGraphObject *>(),
+ SBasisPlanes::XY);
+ if (relativeHit.isEmpty()) {
+ return Empty();
+ }
+ SUICRenderPickSubResult theResult = ConstructSubResult(theImage);
+ QT3DSVec2 hitInUVSpace = (*relativeHit) + QT3DSVec2(.5f, .5f);
+ eastl::pair<QT3DSVec2, QT3DSVec2> mouseAndViewport =
+ GetMouseCoordsAndViewportFromSubObject(hitInUVSpace, theResult);
+ theMouseCoords = mouseAndViewport.first;
+ theViewportDimensions = mouseAndViewport.second;
+ }
+ }
+
+ Option<SRay> theHitRay = theLayerData->m_LayerPrepResult->GetPickRay(
+ theMouseCoords, theViewportDimensions, false);
+ if (theHitRay.hasValue() == false)
+ return Empty();
+
+ // Scale the mouse coords to change them into the camera's numerical space.
+ SRay thePickRay = *theHitRay;
+ Option<QT3DSVec2> newValue = thePickRay.GetRelative(inGlobalTransform, inBounds, inPlane);
+ return newValue;
+ }
+
+ SUICRenderPickResult
+ CUICRendererImpl::PickOffscreenLayer(SLayer &inLayer, const QT3DSVec2 & /*inViewportDimensions*/
+ ,
+ const QT3DSVec2 & /*inMouseCoords*/
+ ,
+ bool /*inPickEverything*/)
+ {
+ if (inLayer.m_Flags.IsActive()) {
+ TLayerRenderMap::iterator theIter = m_LayerToRenderMap.find(&inLayer);
+ if (theIter != m_LayerToRenderMap.end()) {
+ /*
+ m_LastPickResults.clear();
+ GetLayerHitObjectList( *theIter->second, inViewportDimensions, inMouseCoords,
+ m_LastPickResults, m_FrameTemporaryAllocator );
+ SPickResultProcessResult retval( ProcessPickResultList() );
+ if ( retval.m_WasPickConsumed )
+ return retval;*/
+ } else {
+ // QT3DS_ASSERT( false );
+ }
+ }
+ return SUICRenderPickResult();
+ }
+
+ QT3DSVec3 CUICRendererImpl::UnprojectToPosition(SNode &inNode, QT3DSVec3 &inPosition,
+ const QT3DSVec2 &inMouseVec) const
+ {
+ // Translate mouse into layer's coordinates
+ SLayerRenderData *theData =
+ const_cast<CUICRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ return QT3DSVec3(0, 0, 0);
+ } // QT3DS_ASSERT( false ); return QT3DSVec3(0,0,0); }
+
+ SWindowDimensions theWindow = m_UICContext.GetWindowDimensions();
+ QT3DSVec2 theDims((QT3DSF32)theWindow.m_Width, (QT3DSF32)theWindow.m_Height);
+
+ SLayerRenderPreparationResult &thePrepResult(*theData->m_LayerPrepResult);
+ SRay theRay = thePrepResult.GetPickRay(inMouseVec, theDims, true);
+
+ return theData->m_Camera->UnprojectToPosition(inPosition, theRay);
+ }
+
+ QT3DSVec3 CUICRendererImpl::UnprojectWithDepth(SNode &inNode, QT3DSVec3 &,
+ const QT3DSVec3 &inMouseVec) const
+ {
+ // Translate mouse into layer's coordinates
+ SLayerRenderData *theData =
+ const_cast<CUICRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ return QT3DSVec3(0, 0, 0);
+ } // QT3DS_ASSERT( false ); return QT3DSVec3(0,0,0); }
+
+ // Flip the y into gl coordinates from window coordinates.
+ QT3DSVec2 theMouse(inMouseVec.x, inMouseVec.y);
+ NVReal theDepth = inMouseVec.z;
+
+ SLayerRenderPreparationResult &thePrepResult(*theData->m_LayerPrepResult);
+ SWindowDimensions theWindow = m_UICContext.GetWindowDimensions();
+ SRay theRay = thePrepResult.GetPickRay(
+ theMouse, QT3DSVec2((QT3DSF32)theWindow.m_Width, (QT3DSF32)theWindow.m_Height), true);
+ QT3DSVec3 theTargetPosition = theRay.m_Origin + theRay.m_Direction * theDepth;
+ if (inNode.m_Parent != NULL && inNode.m_Parent->m_Type != GraphObjectTypes::Layer)
+ theTargetPosition =
+ inNode.m_Parent->m_GlobalTransform.getInverse().transform(theTargetPosition);
+ // Our default global space is right handed, so if you are left handed z means something
+ // opposite.
+ if (inNode.m_Flags.IsLeftHanded())
+ theTargetPosition.z *= -1;
+ return theTargetPosition;
+ }
+
+ QT3DSVec3 CUICRendererImpl::ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const
+ {
+ // Translate mouse into layer's coordinates
+ SLayerRenderData *theData =
+ const_cast<CUICRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inNode);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ return QT3DSVec3(0, 0, 0);
+ }
+
+ QT3DSMat44 viewProj;
+ theData->m_Camera->CalculateViewProjectionMatrix(viewProj);
+ QT3DSVec4 projPos = viewProj.transform(QT3DSVec4(inPosition, 1.0f));
+ projPos.x /= projPos.w;
+ projPos.y /= projPos.w;
+
+ NVRenderRectF theViewport = theData->m_LayerPrepResult->GetLayerToPresentationViewport();
+ QT3DSVec2 theDims((QT3DSF32)theViewport.m_Width, (QT3DSF32)theViewport.m_Height);
+ projPos.x += 1.0;
+ projPos.y += 1.0;
+ projPos.x *= 0.5;
+ projPos.y *= 0.5;
+ QT3DSVec3 cameraToObject = theData->m_Camera->GetGlobalPos() - inPosition;
+ projPos.z = sqrtf(cameraToObject.dot(cameraToObject));
+ QT3DSVec3 mouseVec = QT3DSVec3(projPos.x, projPos.y, projPos.z);
+ mouseVec.x *= theDims.x;
+ mouseVec.y *= theDims.y;
+
+ mouseVec.x += theViewport.m_X;
+ mouseVec.y += theViewport.m_Y;
+
+ // Flip the y into window coordinates so it matches the mouse.
+ SWindowDimensions theWindow = m_UICContext.GetWindowDimensions();
+ mouseVec.y = theWindow.m_Height - mouseVec.y;
+
+ return mouseVec;
+ }
+
+ Option<SLayerPickSetup> CUICRendererImpl::GetLayerPickSetup(SLayer &inLayer,
+ const QT3DSVec2 &inMouseCoords,
+ const SWindowDimensions &inPickDims)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ SWindowDimensions theWindow = m_UICContext.GetWindowDimensions();
+ QT3DSVec2 theDims((QT3DSF32)theWindow.m_Width, (QT3DSF32)theWindow.m_Height);
+ // The mouse is relative to the layer
+ Option<QT3DSVec2> theLocalMouse = GetLayerMouseCoords(*theData, inMouseCoords, theDims, false);
+ if (theLocalMouse.hasValue() == false) {
+ return Empty();
+ }
+
+ SLayerRenderPreparationResult &thePrepResult(*theData->m_LayerPrepResult);
+ if (thePrepResult.GetCamera() == NULL) {
+ return Empty();
+ }
+ // Perform gluPickMatrix and pre-multiply it into the view projection
+ QT3DSMat44 theTransScale(QT3DSMat44::createIdentity());
+ SCamera &theCamera(*thePrepResult.GetCamera());
+
+ NVRenderRectF layerToPresentation = thePrepResult.GetLayerToPresentationViewport();
+ // Offsetting is already taken care of in the camera's projection.
+ // All we need to do is to scale and translate the image.
+ layerToPresentation.m_X = 0;
+ layerToPresentation.m_Y = 0;
+ QT3DSVec2 theMouse(*theLocalMouse);
+ // The viewport will need to center at this location
+ QT3DSVec2 viewportDims((QT3DSF32)inPickDims.m_Width, (QT3DSF32)inPickDims.m_Height);
+ QT3DSVec2 bottomLeft =
+ QT3DSVec2(theMouse.x - viewportDims.x / 2.0f, theMouse.y - viewportDims.y / 2.0f);
+ // For some reason, and I haven't figured out why yet, the offsets need to be backwards for
+ // this to work.
+ // bottomLeft.x = layerToPresentation.m_Width - bottomLeft.x;
+ // bottomLeft.y = layerToPresentation.m_Height - bottomLeft.y;
+ // Virtual rect is relative to the layer.
+ NVRenderRectF thePickRect(bottomLeft.x, bottomLeft.y, viewportDims.x, viewportDims.y);
+ QT3DSMat44 projectionPremult(QT3DSMat44::createIdentity());
+ projectionPremult = render::NVRenderContext::ApplyVirtualViewportToProjectionMatrix(
+ projectionPremult, layerToPresentation, thePickRect);
+ projectionPremult = projectionPremult.getInverse();
+
+ QT3DSMat44 globalInverse = theCamera.m_GlobalTransform.getInverse();
+ QT3DSMat44 theVP = theCamera.m_Projection * globalInverse;
+ // For now we won't setup the scissor, so we may be off by inPickDims at most because
+ // GetLayerMouseCoords will return
+ // false if the mouse is too far off the layer.
+ return SLayerPickSetup(projectionPremult, theVP,
+ NVRenderRect(0, 0, (QT3DSU32)layerToPresentation.m_Width,
+ (QT3DSU32)layerToPresentation.m_Height));
+ }
+
+ Option<NVRenderRectF> CUICRendererImpl::GetLayerRect(SLayer &inLayer)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ SLayerRenderPreparationResult &thePrepResult(*theData->m_LayerPrepResult);
+ return thePrepResult.GetLayerToPresentationViewport();
+ }
+
+ // This doesn't have to be cheap.
+ void CUICRendererImpl::RunLayerRender(SLayer &inLayer, const QT3DSMat44 &inViewProjection)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ theData->PrepareAndRender(inViewProjection);
+ }
+
+ void CUICRendererImpl::AddRenderWidget(IRenderWidget &inWidget)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inWidget.GetNode());
+ if (theData)
+ theData->AddRenderWidget(inWidget);
+ }
+
+ void CUICRendererImpl::RenderLayerRect(SLayer &inLayer, const QT3DSVec3 &inColor)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
+ if (theData)
+ theData->m_BoundingRectColor = inColor;
+ }
+
+ SScaleAndPosition CUICRendererImpl::GetWorldToPixelScaleFactor(const SCamera &inCamera,
+ const QT3DSVec3 &inWorldPoint,
+ SLayerRenderData &inRenderData)
+ {
+ if (inCamera.m_Flags.IsOrthographic() == true) {
+ // There are situations where the camera can scale.
+ return SScaleAndPosition(
+ inWorldPoint,
+ inCamera.GetOrthographicScaleFactor(
+ inRenderData.m_LayerPrepResult->GetLayerToPresentationViewport(),
+ inRenderData.m_LayerPrepResult->GetPresentationDesignDimensions()));
+ } else {
+ QT3DSVec3 theCameraPos(0, 0, 0);
+ QT3DSVec3 theCameraDir(0, 0, -1);
+ SRay theRay(theCameraPos, inWorldPoint - theCameraPos);
+ NVPlane thePlane(theCameraDir, -600);
+ QT3DSVec3 theItemPosition(inWorldPoint);
+ Option<QT3DSVec3> theIntersection = theRay.Intersect(thePlane);
+ if (theIntersection.hasValue())
+ theItemPosition = *theIntersection;
+ // The special number comes in from physically measuring how off we are on the screen.
+ QT3DSF32 theScaleFactor = (1.0f / inCamera.m_Projection.column1[1]);
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inCamera);
+ QT3DSU32 theHeight = theData->m_LayerPrepResult->GetTextureDimensions().m_Height;
+ QT3DSF32 theScaleMultiplier = 600.0f / ((QT3DSF32)theHeight / 2.0f);
+ theScaleFactor *= theScaleMultiplier;
+
+ return SScaleAndPosition(theItemPosition, theScaleFactor);
+ }
+ }
+
+ SScaleAndPosition CUICRendererImpl::GetWorldToPixelScaleFactor(SLayer &inLayer,
+ const QT3DSVec3 &inWorldPoint)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer);
+ if (theData == NULL || theData->m_Camera == NULL) {
+ QT3DS_ASSERT(false);
+ return SScaleAndPosition();
+ }
+ return GetWorldToPixelScaleFactor(*theData->m_Camera, inWorldPoint, *theData);
+ }
+
+ void CUICRendererImpl::ReleaseLayerRenderResources(SLayer &inLayer)
+ {
+ TLayerRenderMap::iterator theIter = m_LayerToRenderMap.find(&inLayer);
+ if (theIter != m_LayerToRenderMap.end()) {
+ TLayerRenderList::iterator theLastFrm = eastl::find(
+ m_LastFrameLayers.begin(), m_LastFrameLayers.end(), theIter->second.mPtr);
+ if (theLastFrm != m_LastFrameLayers.end()) {
+ theIter->second->ResetForFrame();
+ m_LastFrameLayers.erase(theLastFrm);
+ }
+ m_LayerToRenderMap.erase(theIter);
+ }
+ }
+
+ void CUICRendererImpl::RenderQuad(const QT3DSVec2 inDimensions, const QT3DSMat44 &inMVP,
+ NVRenderTexture2D &inQuadTexture)
+ {
+ m_Context->SetCullingEnabled(false);
+ SLayerSceneShader *theShader = GetSceneLayerShader();
+ NVRenderContext &theContext(*m_Context);
+ theContext.SetActiveShader(&theShader->m_Shader);
+ theShader->m_MVP.Set(inMVP);
+ theShader->m_Dimensions.Set(inDimensions);
+ theShader->m_Sampler.Set(&inQuadTexture);
+
+ GenerateXYQuad();
+ theContext.SetInputAssembler(m_QuadInputAssembler);
+ theContext.Draw(NVRenderDrawMode::Triangles, m_QuadIndexBuffer->GetNumIndices(), 0);
+ }
+
+ void CUICRendererImpl::RenderQuad()
+ {
+ m_Context->SetCullingEnabled(false);
+ GenerateXYQuad();
+ m_Context->SetInputAssembler(m_QuadInputAssembler);
+ m_Context->Draw(NVRenderDrawMode::Triangles, m_QuadIndexBuffer->GetNumIndices(), 0);
+ }
+
+ void CUICRendererImpl::RenderPointsIndirect()
+ {
+ m_Context->SetCullingEnabled(false);
+ GenerateXYZPoint();
+ m_Context->SetInputAssembler(m_PointInputAssembler);
+ m_Context->DrawIndirect(NVRenderDrawMode::Points, 0);
+ }
+
+ void CUICRendererImpl::LayerNeedsFrameClear(SLayerRenderData &inLayer)
+ {
+ m_LastFrameLayers.push_back(&inLayer);
+ }
+
+ void CUICRendererImpl::BeginLayerDepthPassRender(SLayerRenderData &inLayer)
+ {
+ m_CurrentLayer = &inLayer;
+ }
+
+ void CUICRendererImpl::EndLayerDepthPassRender() { m_CurrentLayer = NULL; }
+
+ void CUICRendererImpl::BeginLayerRender(SLayerRenderData &inLayer)
+ {
+ m_CurrentLayer = &inLayer;
+ // Remove all of the shaders from the layer shader set
+ // so that we can only apply the camera and lighting properties to
+ // shaders that are in the layer.
+ m_LayerShaders.clear();
+ }
+ void CUICRendererImpl::EndLayerRender() { m_CurrentLayer = NULL; }
+
+// Allocate an object that lasts only this frame.
+#define RENDER_FRAME_NEW(type) \
+ new (m_PerFrameAllocator.m_FastAllocator.allocate(sizeof(type), __FILE__, __LINE__)) type
+
+ void CUICRendererImpl::PrepareImageForIbl(SImage &inImage)
+ {
+ if (inImage.m_TextureData.m_Texture && inImage.m_TextureData.m_Texture->GetNumMipmaps() < 1)
+ inImage.m_TextureData.m_Texture->GenerateMipmaps();
+ }
+
+ bool NodeContainsBoneRoot(SNode &childNode, QT3DSI32 rootID)
+ {
+ for (SNode *childChild = childNode.m_FirstChild; childChild != NULL;
+ childChild = childChild->m_NextSibling) {
+ if (childChild->m_SkeletonId == rootID)
+ return true;
+ }
+
+ return false;
+ }
+
+ void FillBoneIdNodeMap(SNode &childNode, nvhash_map<long, SNode *> &ioMap)
+ {
+ if (childNode.m_SkeletonId >= 0)
+ ioMap[childNode.m_SkeletonId] = &childNode;
+ for (SNode *childChild = childNode.m_FirstChild; childChild != NULL;
+ childChild = childChild->m_NextSibling)
+ FillBoneIdNodeMap(*childChild, ioMap);
+ }
+
+ bool CUICRendererImpl::PrepareTextureAtlasForRender()
+ {
+ ITextTextureAtlas *theTextureAtlas = m_UICContext.GetTextureAtlas();
+ if (theTextureAtlas == NULL)
+ return false;
+
+ // this is a one time creation
+ if (!theTextureAtlas->IsInitialized()) {
+ NVRenderContext &theContext(*m_Context);
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ // temporay FB
+ using qt3ds::render::NVRenderContextScopedProperty;
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __fbo(
+ *m_Context, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+
+ ITextRenderer &theTextRenderer(*m_UICContext.GetOnscreenTextRenderer());
+ TTextTextureAtlasDetailsAndTexture theResult = theTextureAtlas->PrepareTextureAtlas();
+ if (!theResult.first.m_EntryCount) {
+ QT3DS_ASSERT(theResult.first.m_EntryCount);
+ return false;
+ }
+
+ // generate the index buffer we need
+ GenerateXYQuad();
+
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_uv", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 12),
+ };
+
+ // create our attribute layout
+ mAttribLayout = m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 2));
+
+ NVRenderFrameBuffer *theAtlasFB(
+ m_UICContext.GetResourceManager().AllocateFrameBuffer());
+ theAtlasFB->Attach(NVRenderFrameBufferAttachments::Color0, *theResult.second);
+ m_UICContext.GetRenderContext().SetRenderTarget(theAtlasFB);
+
+ // this texture contains our single entries
+ NVRenderTexture2D *theTexture = m_UICContext.GetResourceManager().AllocateTexture2D(
+ 32, 32, NVRenderTextureFormats::Alpha8);
+
+ m_Context->SetClearColor(QT3DSVec4(0, 0, 0, 0));
+ m_Context->Clear(NVRenderClearValues::Color);
+ m_Context->SetDepthTestEnabled(false);
+ m_Context->SetScissorTestEnabled(false);
+ m_Context->SetCullingEnabled(false);
+ m_Context->SetBlendingEnabled(false);
+ m_Context->SetViewport(
+ NVRenderRect(0, 0, theResult.first.m_TextWidth, theResult.first.m_TextHeight));
+
+ SCamera theCamera;
+ theCamera.m_ClipNear = -1.0;
+ theCamera.m_ClipFar = 1.0;
+ theCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ theCamera.m_Flags.SetOrthographic(true);
+ QT3DSVec2 theTextureDims((QT3DSF32)theResult.first.m_TextWidth,
+ (QT3DSF32)theResult.first.m_TextHeight);
+ theCamera.CalculateGlobalVariables(
+ NVRenderRect(0, 0, theResult.first.m_TextWidth, theResult.first.m_TextHeight),
+ theTextureDims);
+ // We want a 2D lower left projection
+ QT3DSF32 *writePtr(theCamera.m_Projection.front());
+ writePtr[12] = -1;
+ writePtr[13] = -1;
+
+ // generate render stuff
+ // We dynamicall update the vertex buffer
+ QT3DSF32 tempBuf[20];
+ QT3DSF32 *bufPtr = tempBuf;
+ QT3DSU32 bufSize = 20 * sizeof(QT3DSF32); // 4 vertices 3 pos 2 tex
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)bufPtr, bufSize);
+ mVertexBuffer = theContext.CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Dynamic, 20 * sizeof(QT3DSF32),
+ 3 * sizeof(QT3DSF32) + 2 * sizeof(QT3DSF32), vertData);
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = theContext.CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), m_QuadIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+
+ NVRenderShaderProgram *theShader = GetTextAtlasEntryShader();
+ STextShader theTextShader(*theShader);
+
+ if (theShader) {
+ theContext.SetActiveShader(theShader);
+ theTextShader.m_MVP.Set(theCamera.m_Projection);
+
+ // we are going through all entries and render to the FBO
+ for (QT3DSU32 i = 0; i < theResult.first.m_EntryCount; i++) {
+ STextTextureAtlasEntryDetails theDetails =
+ theTextRenderer.RenderAtlasEntry(i, *theTexture);
+ // update vbo
+ // we need to mirror coordinates
+ QT3DSF32 x1 = (QT3DSF32)theDetails.m_X;
+ QT3DSF32 x2 = (QT3DSF32)theDetails.m_X + theDetails.m_TextWidth;
+ QT3DSF32 y1 = (QT3DSF32)theDetails.m_Y;
+ QT3DSF32 y2 = (QT3DSF32)theDetails.m_Y + theDetails.m_TextHeight;
+
+ QT3DSF32 box[4][5] = {
+ { x1, y1, 0, 0, 1 },
+ { x1, y2, 0, 0, 0 },
+ { x2, y2, 0, 1, 0 },
+ { x2, y1, 0, 1, 1 },
+ };
+
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)box, bufSize);
+ mVertexBuffer->UpdateBuffer(vertData, false);
+
+ theTextShader.m_Sampler.Set(theTexture);
+
+ theContext.SetInputAssembler(mInputAssembler);
+ theContext.Draw(NVRenderDrawMode::Triangles, m_QuadIndexBuffer->GetNumIndices(),
+ 0);
+ }
+ }
+
+ m_UICContext.GetResourceManager().Release(*theTexture);
+ m_UICContext.GetResourceManager().Release(*theAtlasFB);
+
+ return true;
+ }
+
+ return theTextureAtlas->IsInitialized();
+ }
+
+ Option<QT3DSVec2> CUICRendererImpl::GetLayerMouseCoords(SLayerRenderData &inLayerRenderData,
+ const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool forceImageIntersect) const
+ {
+ if (inLayerRenderData.m_LayerPrepResult.hasValue())
+ return inLayerRenderData.m_LayerPrepResult->GetLayerMouseCoords(
+ inMouseCoords, inViewportDimensions, forceImageIntersect);
+ return Empty();
+ }
+
+ void CUICRendererImpl::GetLayerHitObjectList(SLayerRenderData &inLayerRenderData,
+ const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inPresCoords, bool inPickEverything,
+ TPickResultArray &outIntersectionResult,
+ NVAllocatorCallback &inTempAllocator)
+ {
+ // This function assumes the layer was rendered to the scene itself. There is another
+ // function
+ // for completely offscreen layers that don't get rendered to the scene.
+ bool wasRenderToTarget(inLayerRenderData.m_Layer.m_Flags.IsLayerRenderToTarget());
+ if (wasRenderToTarget && inLayerRenderData.m_Camera != NULL) {
+ Option<SRay> theHitRay;
+ if (inLayerRenderData.m_LayerPrepResult.hasValue())
+ theHitRay = inLayerRenderData.m_LayerPrepResult->GetPickRay(
+ inPresCoords, inViewportDimensions, false);
+ if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr == NULL) {
+ if (theHitRay.hasValue()) {
+ // Scale the mouse coords to change them into the camera's numerical space.
+ SRay thePickRay = *theHitRay;
+ for (QT3DSU32 idx = inLayerRenderData.m_OpaqueObjects.size(), end = 0; idx > end;
+ --idx) {
+ SRenderableObject *theRenderableObject =
+ inLayerRenderData.m_OpaqueObjects[idx - 1];
+ if (inPickEverything
+ || theRenderableObject->m_RenderableFlags.GetPickable())
+ IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
+ outIntersectionResult,
+ inTempAllocator);
+ }
+ for (QT3DSU32 idx = inLayerRenderData.m_TransparentObjects.size(), end = 0;
+ idx > end; --idx) {
+ SRenderableObject *theRenderableObject =
+ inLayerRenderData.m_TransparentObjects[idx - 1];
+ if (inPickEverything
+ || theRenderableObject->m_RenderableFlags.GetPickable())
+ IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
+ outIntersectionResult,
+ inTempAllocator);
+ }
+ }
+ } else {
+ IGraphObjectPickQuery *theQuery =
+ inLayerRenderData.m_LastFrameOffscreenRenderer->GetGraphObjectPickQuery();
+ if (theQuery) {
+ SUICRenderPickResult theResult =
+ theQuery->Pick(inPresCoords, inViewportDimensions, inPickEverything);
+ if (theResult.m_HitObject) {
+ theResult.m_OffscreenRenderer =
+ inLayerRenderData.m_LastFrameOffscreenRenderer;
+ outIntersectionResult.push_back(theResult);
+ }
+ } else
+ inLayerRenderData.m_LastFrameOffscreenRenderer->Pick(inPresCoords,
+ inViewportDimensions);
+ }
+ }
+ }
+
+ static inline SUICRenderPickSubResult ConstructSubResult(SRenderableImage &inImage)
+ {
+ return ConstructSubResult(inImage.m_Image);
+ }
+
+ void CUICRendererImpl::IntersectRayWithSubsetRenderable(
+ const SRay &inRay, SRenderableObject &inRenderableObject,
+ TPickResultArray &outIntersectionResultList, NVAllocatorCallback &inTempAllocator)
+ {
+ Option<SRayIntersectionResult> theIntersectionResultOpt(inRay.IntersectWithAABB(
+ inRenderableObject.m_GlobalTransform, inRenderableObject.m_Bounds));
+ if (theIntersectionResultOpt.hasValue() == false)
+ return;
+ SRayIntersectionResult &theResult(*theIntersectionResultOpt);
+
+ // Leave the coordinates relative for right now.
+ const SGraphObject *thePickObject = NULL;
+ if (inRenderableObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ thePickObject =
+ &static_cast<SSubsetRenderable *>(&inRenderableObject)->m_ModelContext.m_Model;
+ else if (inRenderableObject.m_RenderableFlags.IsText())
+ thePickObject = &static_cast<STextRenderable *>(&inRenderableObject)->m_Text;
+ else if (inRenderableObject.m_RenderableFlags.IsCustomMaterialMeshSubset())
+ thePickObject = &static_cast<SCustomMaterialRenderable *>(&inRenderableObject)
+ ->m_ModelContext.m_Model;
+ else if (inRenderableObject.m_RenderableFlags.IsPath())
+ thePickObject = &static_cast<SPathRenderable *>(&inRenderableObject)->m_Path;
+
+ if (thePickObject != NULL) {
+ outIntersectionResultList.push_back(SUICRenderPickResult(
+ *thePickObject, theResult.m_RayLengthSquared, theResult.m_RelXY));
+
+ // For subsets, we know we can find images on them which may have been the result
+ // of rendering a sub-presentation.
+ if (inRenderableObject.m_RenderableFlags.IsDefaultMaterialMeshSubset()) {
+ SUICRenderPickSubResult *theLastResult = NULL;
+ for (SRenderableImage *theImage =
+ static_cast<SSubsetRenderable *>(&inRenderableObject)->m_FirstImage;
+ theImage != NULL; theImage = theImage->m_NextImage) {
+ if (theImage->m_Image.m_LastFrameOffscreenRenderer != NULL
+ && theImage->m_Image.m_TextureData.m_Texture != NULL) {
+ SUICRenderPickSubResult *theSubResult =
+ (SUICRenderPickSubResult *)inTempAllocator.allocate(
+ sizeof(SUICRenderPickSubResult), "SUICRenderPickSubResult",
+ __FILE__, __LINE__);
+
+ new (theSubResult) SUICRenderPickSubResult(ConstructSubResult(*theImage));
+ if (theLastResult == NULL)
+ outIntersectionResultList.back().m_FirstSubObject = theSubResult;
+ else
+ theLastResult->m_NextSibling = theSubResult;
+ theLastResult = theSubResult;
+ }
+ }
+ }
+ }
+ }
+
+#ifndef EA_PLATFORM_WINDOWS
+#define _snprintf snprintf
+#endif
+
+ NVRenderShaderProgram *CUICRendererImpl::CompileShader(CRegisteredString inName,
+ const char8_t *inVert,
+ const char8_t *inFrag)
+ {
+ GetProgramGenerator().BeginProgram();
+ GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)->Append(inVert);
+ GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)->Append(inFrag);
+ return GetProgramGenerator().CompileGeneratedShader(inName);
+ }
+
+ const QT3DSF32 MINATTENUATION = 0;
+ const QT3DSF32 MAXATTENUATION = 1000;
+
+ QT3DSF32 ClampFloat(QT3DSF32 value, QT3DSF32 min, QT3DSF32 max)
+ {
+ return value < min ? min : ((value > max) ? max : value);
+ }
+
+ QT3DSF32 TranslateConstantAttenuation(QT3DSF32 attenuation) { return attenuation * .01f; }
+
+ QT3DSF32 TranslateLinearAttenuation(QT3DSF32 attenuation)
+ {
+ attenuation = ClampFloat(attenuation, MINATTENUATION, MAXATTENUATION);
+ return attenuation * 0.0001f;
+ }
+
+ QT3DSF32 TranslateQuadraticAttenuation(QT3DSF32 attenuation)
+ {
+ attenuation = ClampFloat(attenuation, MINATTENUATION, MAXATTENUATION);
+ return attenuation * 0.0000001f;
+ }
+
+ SShaderGeneratorGeneratedShader *CUICRendererImpl::GetShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet)
+ {
+ if (m_CurrentLayer == NULL) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ TShaderMap::iterator theFind = m_Shaders.find(inRenderable.m_ShaderDescription);
+ SShaderGeneratorGeneratedShader *retval = NULL;
+ if (theFind == m_Shaders.end()) {
+ // Generate the shader.
+ NVRenderShaderProgram *theShader(GenerateShader(inRenderable, inFeatureSet));
+ if (theShader) {
+ SShaderGeneratorGeneratedShader *theGeneratedShader =
+ (SShaderGeneratorGeneratedShader *)m_Context->GetAllocator().allocate(
+ sizeof(SShaderGeneratorGeneratedShader), "SShaderGeneratorGeneratedShader",
+ __FILE__, __LINE__);
+ new (theGeneratedShader) SShaderGeneratorGeneratedShader(
+ m_StringTable->RegisterStr(m_GeneratedShaderString.c_str()), *theShader);
+ m_Shaders.insert(make_pair(inRenderable.m_ShaderDescription, theGeneratedShader));
+ retval = theGeneratedShader;
+ }
+ // We still insert something because we don't to attempt to generate the same bad shader
+ // twice.
+ else
+ m_Shaders.insert(make_pair(inRenderable.m_ShaderDescription,
+ (SShaderGeneratorGeneratedShader *)NULL));
+ } else
+ retval = theFind->second;
+
+ if (retval != NULL) {
+ if (!m_LayerShaders.contains(*retval)) {
+ m_LayerShaders.insert(*retval);
+ }
+ if (m_CurrentLayer && m_CurrentLayer->m_Camera) {
+ SCamera &theCamera(*m_CurrentLayer->m_Camera);
+ if (m_CurrentLayer->m_CameraDirection.hasValue() == false)
+ m_CurrentLayer->m_CameraDirection = theCamera.GetScalingCorrectDirection();
+ }
+ }
+ return retval;
+ }
+ static QT3DSVec3 g_fullScreenRectFace[] = {
+ QT3DSVec3(-1, -1, 0), QT3DSVec3(-1, 1, 0), QT3DSVec3(1, 1, 0), QT3DSVec3(1, -1, 0),
+ };
+
+ static QT3DSVec2 g_fullScreenRectUVs[] = { QT3DSVec2(0, 0), QT3DSVec2(0, 1), QT3DSVec2(1, 1),
+ QT3DSVec2(1, 0) };
+
+ void CUICRendererImpl::GenerateXYQuad()
+ {
+ if (m_QuadInputAssembler)
+ return;
+
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry("attr_uv",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 12),
+ };
+
+ QT3DSF32 tempBuf[20];
+ QT3DSF32 *bufPtr = tempBuf;
+ QT3DSVec3 *facePtr(g_fullScreenRectFace);
+ QT3DSVec2 *uvPtr(g_fullScreenRectUVs);
+ for (int j = 0; j < 4; j++, ++facePtr, ++uvPtr, bufPtr += 5) {
+ bufPtr[0] = facePtr->x;
+ bufPtr[1] = facePtr->y;
+ bufPtr[2] = facePtr->z;
+ bufPtr[3] = uvPtr->x;
+ bufPtr[4] = uvPtr->y;
+ }
+ m_QuadVertexBuffer = m_Context->CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static, 20 * sizeof(QT3DSF32),
+ 3 * sizeof(QT3DSF32) + 2 * sizeof(QT3DSF32), toU8DataRef(tempBuf, 20));
+
+ QT3DSU8 indexData[] = {
+ 0, 1, 2, 0, 2, 3,
+ };
+ m_QuadIndexBuffer = m_Context->CreateIndexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static, qt3ds::render::NVRenderComponentTypes::QT3DSU8,
+ sizeof(indexData), toU8DataRef(indexData, sizeof(indexData)));
+
+ // create our attribute layout
+ m_QuadAttribLayout = m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 2));
+
+ // create input assembler object
+ QT3DSU32 strides = m_QuadVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_QuadInputAssembler = m_Context->CreateInputAssembler(
+ m_QuadAttribLayout, toConstDataRef(&m_QuadVertexBuffer.mPtr, 1), m_QuadIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+
+ void CUICRendererImpl::GenerateXYZPoint()
+ {
+ if (m_PointInputAssembler)
+ return;
+
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry("attr_uv",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 12),
+ };
+
+ QT3DSF32 tempBuf[5];
+ tempBuf[0] = tempBuf[1] = tempBuf[2] = 0.0;
+ tempBuf[3] = tempBuf[4] = 0.0;
+
+ m_PointVertexBuffer = m_Context->CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static, 5 * sizeof(QT3DSF32),
+ 3 * sizeof(QT3DSF32) + 2 * sizeof(QT3DSF32), toU8DataRef(tempBuf, 5));
+
+ // create our attribute layout
+ m_PointAttribLayout = m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 2));
+
+ // create input assembler object
+ QT3DSU32 strides = m_PointVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_PointInputAssembler = m_Context->CreateInputAssembler(
+ m_PointAttribLayout, toConstDataRef(&m_PointVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+
+ eastl::pair<NVRenderVertexBuffer *, NVRenderIndexBuffer *> CUICRendererImpl::GetXYQuad()
+ {
+ if (!m_QuadInputAssembler)
+ GenerateXYQuad();
+
+ return eastl::make_pair(m_QuadVertexBuffer.mPtr, m_QuadIndexBuffer.mPtr);
+ }
+
+ SLayerGlobalRenderProperties CUICRendererImpl::GetLayerGlobalRenderProperties()
+ {
+ SLayerRenderData &theData = *m_CurrentLayer;
+ SLayer &theLayer = theData.m_Layer;
+ if (theData.m_CameraDirection.hasValue() == false)
+ theData.m_CameraDirection = theData.m_Camera->GetScalingCorrectDirection();
+
+ return SLayerGlobalRenderProperties(
+ theLayer, *theData.m_Camera, *theData.m_CameraDirection, theData.m_Lights,
+ theData.m_LightDirections, theData.m_ShadowMapManager.mPtr, theData.m_LayerDepthTexture,
+ theData.m_LayerSsaoTexture, theLayer.m_LightProbe, theLayer.m_LightProbe2,
+ theLayer.m_ProbeHorizon, theLayer.m_ProbeBright, theLayer.m_Probe2Window,
+ theLayer.m_Probe2Pos, theLayer.m_Probe2Fade, theLayer.m_ProbeFov);
+ }
+
+ void CUICRendererImpl::GenerateXYQuadStrip()
+ {
+ if (m_QuadStripInputAssembler)
+ return;
+
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry("attr_uv",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 12),
+ };
+
+ // this buffer is filled dynmically
+ m_QuadStripVertexBuffer =
+ m_Context->CreateVertexBuffer(qt3ds::render::NVRenderBufferUsageType::Dynamic, 0,
+ 3 * sizeof(QT3DSF32) + 2 * sizeof(QT3DSF32) // stride
+ ,
+ NVDataRef<QT3DSU8>());
+
+ // create our attribute layout
+ m_QuadStripAttribLayout = m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 2));
+
+ // create input assembler object
+ QT3DSU32 strides = m_QuadStripVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_QuadStripInputAssembler = m_Context->CreateInputAssembler(
+ m_QuadStripAttribLayout, toConstDataRef(&m_QuadStripVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+
+ void CUICRendererImpl::UpdateCbAoShadow(const SLayer *pLayer, const SCamera *pCamera,
+ CResourceTexture2D &inDepthTexture)
+ {
+ if (m_Context->GetConstantBufferSupport()) {
+ CRegisteredString theName = m_Context->GetStringTable().RegisterStr("cbAoShadow");
+ NVRenderConstantBuffer *pCB = m_Context->GetConstantBuffer(theName);
+
+ if (!pCB) {
+ // the size is determined automatically later on
+ pCB = m_Context->CreateConstantBuffer(
+ theName, qt3ds::render::NVRenderBufferUsageType::Static, 0, NVDataRef<QT3DSU8>());
+ if (!pCB) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_ConstantBuffers.insert(eastl::make_pair(theName, pCB));
+
+ // Add paramters. Note should match the appearance in the shader program
+ pCB->AddParam(m_Context->GetStringTable().RegisterStr("ao_properties"),
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4, 1);
+ pCB->AddParam(m_Context->GetStringTable().RegisterStr("ao_properties2"),
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4, 1);
+ pCB->AddParam(m_Context->GetStringTable().RegisterStr("shadow_properties"),
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4, 1);
+ pCB->AddParam(m_Context->GetStringTable().RegisterStr("aoScreenConst"),
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4, 1);
+ pCB->AddParam(m_Context->GetStringTable().RegisterStr("UvToEyeConst"),
+ qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4, 1);
+ }
+
+ // update values
+ QT3DSVec4 aoProps(pLayer->m_AoStrength * 0.01f, pLayer->m_AoDistance * 0.4f,
+ pLayer->m_AoSoftness * 0.02f, pLayer->m_AoBias);
+ pCB->UpdateParam("ao_properties", NVDataRef<QT3DSU8>((QT3DSU8 *)&aoProps, 1));
+ QT3DSVec4 aoProps2((QT3DSF32)pLayer->m_AoSamplerate, (pLayer->m_AoDither) ? 1.0f : 0.0f, 0.0f,
+ 0.0f);
+ pCB->UpdateParam("ao_properties2", NVDataRef<QT3DSU8>((QT3DSU8 *)&aoProps2, 1));
+ QT3DSVec4 shadowProps(pLayer->m_ShadowStrength * 0.01f, pLayer->m_ShadowDist,
+ pLayer->m_ShadowSoftness * 0.01f, pLayer->m_ShadowBias);
+ pCB->UpdateParam("shadow_properties", NVDataRef<QT3DSU8>((QT3DSU8 *)&shadowProps, 1));
+
+ QT3DSF32 R2 = pLayer->m_AoDistance * pLayer->m_AoDistance * 0.16f;
+ QT3DSF32 rw = 100, rh = 100;
+ QT3DSF32 fov = (pCamera) ? pCamera->m_FOV : 1.0f;
+ if (inDepthTexture && inDepthTexture.GetTexture()) {
+ rw = (QT3DSF32)inDepthTexture.GetTexture()->GetTextureDetails().m_Width;
+ rh = (QT3DSF32)inDepthTexture.GetTexture()->GetTextureDetails().m_Height;
+ }
+ QT3DSF32 tanHalfFovY = tanf(0.5f * fov * (rh / rw));
+ QT3DSF32 invFocalLenX = tanHalfFovY * (rw / rh);
+
+ QT3DSVec4 aoScreenConst(1.0f / R2, rh / (2.0f * tanHalfFovY), 1.0f / rw, 1.0f / rh);
+ pCB->UpdateParam("aoScreenConst", NVDataRef<QT3DSU8>((QT3DSU8 *)&aoScreenConst, 1));
+ QT3DSVec4 UvToEyeConst(2.0f * invFocalLenX, -2.0f * tanHalfFovY, -invFocalLenX,
+ tanHalfFovY);
+ pCB->UpdateParam("UvToEyeConst", NVDataRef<QT3DSU8>((QT3DSU8 *)&UvToEyeConst, 1));
+
+ // update buffer to hardware
+ pCB->Update();
+ }
+ }
+
+ // widget context implementation
+
+ NVRenderVertexBuffer &CUICRendererImpl::GetOrCreateVertexBuffer(CRegisteredString &inStr,
+ QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderVertexBuffer *retval = GetVertexBuffer(inStr);
+ if (retval) {
+ // we update the buffer
+ retval->UpdateBuffer(bufferData, false);
+ return *retval;
+ }
+ retval = m_Context->CreateVertexBuffer(qt3ds::render::NVRenderBufferUsageType::Dynamic,
+ bufferData.size(), stride, bufferData);
+ m_WidgetVertexBuffers.insert(eastl::make_pair(inStr, retval));
+ return *retval;
+ }
+ NVRenderIndexBuffer &
+ CUICRendererImpl::GetOrCreateIndexBuffer(CRegisteredString &inStr,
+ qt3ds::render::NVRenderComponentTypes::Enum componentType,
+ size_t size, NVConstDataRef<QT3DSU8> bufferData)
+ {
+ NVRenderIndexBuffer *retval = GetIndexBuffer(inStr);
+ if (retval) {
+ // we update the buffer
+ retval->UpdateBuffer(bufferData, false);
+ return *retval;
+ }
+
+ retval = m_Context->CreateIndexBuffer(qt3ds::render::NVRenderBufferUsageType::Dynamic,
+ componentType, size, bufferData);
+ m_WidgetIndexBuffers.insert(eastl::make_pair(inStr, retval));
+ return *retval;
+ }
+
+ NVRenderAttribLayout &CUICRendererImpl::CreateAttributeLayout(
+ NVConstDataRef<qt3ds::render::NVRenderVertexBufferEntry> attribs)
+ {
+ // create our attribute layout
+ NVRenderAttribLayout *theAttribLAyout = m_Context->CreateAttributeLayout(attribs);
+ return *theAttribLAyout;
+ }
+
+ NVRenderInputAssembler &CUICRendererImpl::GetOrCreateInputAssembler(
+ CRegisteredString &inStr, NVRenderAttribLayout *attribLayout,
+ NVConstDataRef<NVRenderVertexBuffer *> buffers, const NVRenderIndexBuffer *indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets)
+ {
+ NVRenderInputAssembler *retval = GetInputAssembler(inStr);
+ if (retval)
+ return *retval;
+
+ retval =
+ m_Context->CreateInputAssembler(attribLayout, buffers, indexBuffer, strides, offsets);
+ m_WidgetInputAssembler.insert(eastl::make_pair(inStr, retval));
+ return *retval;
+ }
+
+ NVRenderVertexBuffer *CUICRendererImpl::GetVertexBuffer(CRegisteredString &inStr)
+ {
+ TStrVertBufMap::iterator theIter = m_WidgetVertexBuffers.find(inStr);
+ if (theIter != m_WidgetVertexBuffers.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ NVRenderIndexBuffer *CUICRendererImpl::GetIndexBuffer(CRegisteredString &inStr)
+ {
+ TStrIndexBufMap::iterator theIter = m_WidgetIndexBuffers.find(inStr);
+ if (theIter != m_WidgetIndexBuffers.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ NVRenderInputAssembler *CUICRendererImpl::GetInputAssembler(CRegisteredString &inStr)
+ {
+ TStrIAMap::iterator theIter = m_WidgetInputAssembler.find(inStr);
+ if (theIter != m_WidgetInputAssembler.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ NVRenderShaderProgram *CUICRendererImpl::GetShader(CRegisteredString inStr)
+ {
+ TStrShaderMap::iterator theIter = m_WidgetShaders.find(inStr);
+ if (theIter != m_WidgetShaders.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ NVRenderShaderProgram *CUICRendererImpl::CompileAndStoreShader(CRegisteredString inStr)
+ {
+ NVRenderShaderProgram *newProgram = GetProgramGenerator().CompileGeneratedShader(inStr);
+ if (newProgram)
+ m_WidgetShaders.insert(eastl::make_pair(inStr, newProgram));
+ return newProgram;
+ }
+
+ IShaderProgramGenerator &CUICRendererImpl::GetProgramGenerator()
+ {
+ return m_UICContext.GetShaderProgramGenerator();
+ }
+
+ STextDimensions CUICRendererImpl::MeasureText(const STextRenderInfo &inText)
+ {
+ if (m_UICContext.GetTextRenderer() != NULL)
+ return m_UICContext.GetTextRenderer()->MeasureText(inText, 0);
+ return STextDimensions();
+ }
+
+ void CUICRendererImpl::RenderText(const STextRenderInfo &inText, const QT3DSVec3 &inTextColor,
+ const QT3DSVec3 &inBackgroundColor, const QT3DSMat44 &inMVP)
+ {
+ if (m_UICContext.GetTextRenderer() != NULL) {
+ ITextRenderer &theTextRenderer(*m_UICContext.GetTextRenderer());
+ NVRenderTexture2D *theTexture = m_UICContext.GetResourceManager().AllocateTexture2D(
+ 32, 32, NVRenderTextureFormats::RGBA8);
+ STextTextureDetails theTextTextureDetails =
+ theTextRenderer.RenderText(inText, *theTexture);
+ STextRenderHelper theTextHelper(GetTextWidgetShader());
+ if (theTextHelper.m_Shader != NULL) {
+ m_UICContext.GetRenderContext().SetBlendingEnabled(false);
+ STextScaleAndOffset theScaleAndOffset(*theTexture, theTextTextureDetails, inText);
+ theTextHelper.m_Shader->Render(*theTexture, theScaleAndOffset,
+ QT3DSVec4(inTextColor, 1.0f), inMVP, QT3DSVec2(0, 0),
+ GetContext(), theTextHelper.m_QuadInputAssembler,
+ theTextHelper.m_QuadInputAssembler.GetIndexCount(),
+ theTextTextureDetails, inBackgroundColor);
+ }
+ m_UICContext.GetResourceManager().Release(*theTexture);
+ }
+ }
+
+ void CUICRendererImpl::RenderText2D(QT3DSF32 x, QT3DSF32 y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
+ const char *text)
+ {
+ if (m_UICContext.GetOnscreenTextRenderer() != NULL) {
+ GenerateXYQuadStrip();
+
+ if (PrepareTextureAtlasForRender()) {
+ TTextRenderAtlasDetailsAndTexture theRenderTextDetails;
+ ITextTextureAtlas *theTextureAtlas = m_UICContext.GetTextureAtlas();
+ SWindowDimensions theWindow = m_UICContext.GetWindowDimensions();
+
+ const wchar_t *wText = m_StringTable->GetWideStr(text);
+ STextRenderInfo theInfo;
+ theInfo.m_Text = m_StringTable->RegisterStr(wText);
+ theInfo.m_FontSize = 20;
+ // text scale 2% of screen we don't scale Y though because it becomes unreadable
+ theInfo.m_ScaleX = (theWindow.m_Width / 100.0f) * 1.5f / (theInfo.m_FontSize);
+ theInfo.m_ScaleY = 1.0f;
+
+ theRenderTextDetails = theTextureAtlas->RenderText(theInfo);
+
+ if (theRenderTextDetails.first.m_Vertices.size()) {
+ STextRenderHelper theTextHelper(GetOnscreenTextShader());
+ if (theTextHelper.m_Shader != NULL) {
+ // setup 2D projection
+ SCamera theCamera;
+ theCamera.m_ClipNear = -1.0;
+ theCamera.m_ClipFar = 1.0;
+
+ theCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ theCamera.m_Flags.SetOrthographic(true);
+ QT3DSVec2 theWindowDim((QT3DSF32)theWindow.m_Width, (QT3DSF32)theWindow.m_Height);
+ theCamera.CalculateGlobalVariables(
+ NVRenderRect(0, 0, theWindow.m_Width, theWindow.m_Height),
+ theWindowDim);
+ // We want a 2D lower left projection
+ QT3DSF32 *writePtr(theCamera.m_Projection.front());
+ writePtr[12] = -1;
+ writePtr[13] = -1;
+
+ // upload vertices
+ m_QuadStripVertexBuffer->UpdateBuffer(theRenderTextDetails.first.m_Vertices,
+ false);
+
+ theTextHelper.m_Shader->Render2D(
+ *theRenderTextDetails.second, QT3DSVec4(inColor, 1.0f),
+ theCamera.m_Projection, GetContext(),
+ theTextHelper.m_QuadInputAssembler,
+ theRenderTextDetails.first.m_VertexCount, QT3DSVec2(x, y));
+ }
+ // we release the memory here
+ QT3DS_FREE(m_Context->GetAllocator(),
+ theRenderTextDetails.first.m_Vertices.begin());
+ }
+ }
+ }
+ }
+
+ void CUICRendererImpl::RenderGpuProfilerStats(QT3DSF32 x, QT3DSF32 y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor)
+ {
+ if (!IsLayerGpuProfilingEnabled())
+ return;
+
+ char messageLine[1024];
+ TLayerRenderMap::const_iterator theIter;
+
+ QT3DSF32 startY = y;
+
+ for (theIter = m_LayerToRenderMap.begin(); theIter != m_LayerToRenderMap.end(); theIter++) {
+ QT3DSF32 startX = x;
+ const SLayerRenderData *theLayerRenderData = theIter->second;
+ const SLayer *theLayer = theIter->first;
+
+ if (theLayer->m_Flags.IsActive() && theLayerRenderData->m_LayerProfilerGpu.mPtr) {
+ const IRenderProfiler::TStrIDVec &idList =
+ theLayerRenderData->m_LayerProfilerGpu->GetTimerIDs();
+ if (!idList.empty()) {
+ startY -= 22;
+ startX += 20;
+ RenderText2D(startX, startY, inColor, theLayer->m_Id);
+ IRenderProfiler::TStrIDVec::const_iterator theIdIter = idList.begin();
+ for (theIdIter = idList.begin(); theIdIter != idList.end(); theIdIter++) {
+ startY -= 22;
+ sprintf(messageLine, "%s: %.3f ms", theIdIter->c_str(),
+ theLayerRenderData->m_LayerProfilerGpu->GetElapsedTime(*theIdIter));
+ RenderText2D(startX + 20, startY, inColor, messageLine);
+ }
+ }
+ }
+ }
+ }
+
+ // Given a node and a point in the node's local space (most likely its pivot point), we return
+ // a normal matrix so you can get the axis out, a transformation from node to camera
+ // a new position and a floating point scale factor so you can render in 1/2 perspective mode
+ // or orthographic mode if you would like to.
+ SWidgetRenderInformation
+ CUICRendererImpl::GetWidgetRenderInformation(SNode &inNode, const QT3DSVec3 &inPos,
+ RenderWidgetModes::Enum inWidgetMode)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inNode);
+ SCamera *theCamera = theData->m_Camera;
+ if (theCamera == NULL || theData->m_LayerPrepResult.hasValue() == false) {
+ QT3DS_ASSERT(false);
+ return SWidgetRenderInformation();
+ }
+ QT3DSMat44 theGlobalTransform(QT3DSMat44::createIdentity());
+ if (inNode.m_Parent != NULL && inNode.m_Parent->m_Type != GraphObjectTypes::Layer
+ && !inNode.m_Flags.IsIgnoreParentTransform())
+ theGlobalTransform = inNode.m_Parent->m_GlobalTransform;
+ QT3DSMat44 theCameraInverse(theCamera->m_GlobalTransform.getInverse());
+ QT3DSMat44 theNodeParentToCamera;
+ if (inWidgetMode == RenderWidgetModes::Local)
+ theNodeParentToCamera = theCameraInverse * theGlobalTransform;
+ else
+ theNodeParentToCamera = theCameraInverse;
+
+ QT3DSMat33 theNormalMat(theNodeParentToCamera.column0.getXYZ(),
+ theNodeParentToCamera.column1.getXYZ(),
+ theNodeParentToCamera.column2.getXYZ());
+ theNormalMat = theNormalMat.getInverse().getTranspose();
+ theNormalMat.column0.normalize();
+ theNormalMat.column1.normalize();
+ theNormalMat.column2.normalize();
+
+ QT3DSMat44 theTranslation(QT3DSMat44::createIdentity());
+ theTranslation.column3.x = inNode.m_Position.x;
+ theTranslation.column3.y = inNode.m_Position.y;
+ theTranslation.column3.z = inNode.m_Position.z;
+ theTranslation.column3.z *= -1.0f;
+
+ theGlobalTransform = theGlobalTransform * theTranslation;
+
+ QT3DSMat44 theNodeToParentPlusTranslation = theCameraInverse * theGlobalTransform;
+ QT3DSVec3 thePos = theNodeToParentPlusTranslation.transform(inPos);
+ SScaleAndPosition theScaleAndPos = GetWorldToPixelScaleFactor(*theCamera, thePos, *theData);
+ QT3DSMat33 theLookAtMatrix(QT3DSMat33::createIdentity());
+ if (theCamera->m_Flags.IsOrthographic() == false) {
+ QT3DSVec3 theNodeToCamera = theScaleAndPos.m_Position;
+ theNodeToCamera.normalize();
+ QT3DSVec3 theOriginalAxis = QT3DSVec3(0, 0, -1);
+ QT3DSVec3 theRotAxis = theOriginalAxis.cross(theNodeToCamera);
+ QT3DSF32 theAxisLen = theRotAxis.normalize();
+ if (theAxisLen > .05f) {
+ QT3DSF32 theRotAmount = acos(theOriginalAxis.dot(theNodeToCamera));
+ QT3DSQuat theQuat(theRotAmount, theRotAxis);
+ theLookAtMatrix = QT3DSMat33(theQuat);
+ }
+ }
+ QT3DSVec3 thePosInWorldSpace = theGlobalTransform.transform(inPos);
+ QT3DSVec3 theCameraPosInWorldSpace = theCamera->GetGlobalPos();
+ QT3DSVec3 theCameraOffset = thePosInWorldSpace - theCameraPosInWorldSpace;
+ QT3DSVec3 theDir = theCameraOffset;
+ theDir.normalize();
+ // Things should be 600 units from the camera, as that is how all of our math is setup.
+ theCameraOffset = 600.0f * theDir;
+ return SWidgetRenderInformation(
+ theNormalMat, theNodeParentToCamera, theCamera->m_Projection, theCamera->m_Projection,
+ theLookAtMatrix, theCameraInverse, theCameraOffset, theScaleAndPos.m_Position,
+ theScaleAndPos.m_Scale, *theCamera);
+ }
+
+ Option<QT3DSVec2> CUICRendererImpl::GetLayerMouseCoords(SLayer &inLayer,
+ const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool forceImageIntersect) const
+ {
+ SLayerRenderData *theData =
+ const_cast<CUICRendererImpl &>(*this).GetOrCreateLayerRenderDataForNode(inLayer);
+ return GetLayerMouseCoords(*theData, inMouseCoords, inViewportDimensions,
+ forceImageIntersect);
+ }
+
+ bool IUICRenderer::IsGlEsContext(qt3ds::render::NVRenderContextType inContextType)
+ {
+ qt3ds::render::NVRenderContextType esContextTypes(NVRenderContextValues::GLES2
+ | NVRenderContextValues::GLES3
+ | NVRenderContextValues::GLES3PLUS);
+
+ if ((inContextType & esContextTypes))
+ return true;
+
+ return false;
+ }
+
+ bool IUICRenderer::IsGlEs3Context(qt3ds::render::NVRenderContextType inContextType)
+ {
+ if (inContextType == NVRenderContextValues::GLES3
+ || inContextType == NVRenderContextValues::GLES3PLUS)
+ return true;
+
+ return false;
+ }
+
+ bool IUICRenderer::IsGl2Context(qt3ds::render::NVRenderContextType inContextType)
+ {
+ if (inContextType == NVRenderContextValues::GL2)
+ return true;
+
+ return false;
+ }
+
+ IUICRenderer &IUICRenderer::CreateRenderer(IUICRenderContext &inContext)
+ {
+ return *QT3DS_NEW(inContext.GetAllocator(), CUICRendererImpl)(inContext);
+ }
+}
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.h b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.h
new file mode 100644
index 00000000..ee553415
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImpl.h
@@ -0,0 +1,543 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_SHADER_GENERATOR_IMPL_H
+#define UIC_RENDER_SHADER_GENERATOR_IMPL_H
+#include "UICRender.h"
+#include "UICRenderer.h"
+#include "UICRenderableObjects.h"
+#include "UICRendererImplShaders.h"
+#include "UICRendererImplLayerRenderData.h"
+#include "foundation/Qt3DSFlags.h"
+#include "UICRenderMesh.h"
+#include "UICRenderModel.h"
+#include "foundation/Qt3DSBounds3.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderDefaultMaterial.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSInvasiveSet.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "UICRenderLayer.h"
+#include "UICRenderRay.h"
+#include "UICRenderText.h"
+#include "UICOffscreenRenderManager.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICRenderCamera.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderContext.h"
+#include "UICOffscreenRenderManager.h"
+#include "UICRendererImplLayerRenderHelper.h"
+#include "UICRenderWidgets.h"
+#include "UICRenderShaderCodeGenerator.h"
+#include "UICRenderClippingFrustum.h"
+#include "foundation/Qt3DSUnionCast.h"
+#include "foundation/FastAllocator.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "UICRenderShaderKeys.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderProfiler.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+
+namespace uic {
+namespace render {
+
+ inline bool FloatLessThan(QT3DSF32 lhs, QT3DSF32 rhs)
+ {
+ QT3DSF32 diff = lhs - rhs;
+ if (fabs(diff) < .001)
+ return false;
+ return diff < 0.0f ? true : false;
+ }
+ inline bool ISRenderObjectPtrLessThan(const SRenderableObject *lhs,
+ const SRenderableObject *rhs)
+ {
+ return FloatLessThan(lhs->m_CameraDistanceSq, rhs->m_CameraDistanceSq);
+ }
+ inline bool ISRenderObjectPtrGreatThan(const SRenderableObject *lhs,
+ const SRenderableObject *rhs)
+ {
+ return FloatLessThan(rhs->m_CameraDistanceSq, lhs->m_CameraDistanceSq);
+ }
+ inline bool NonZero(float inValue) { return fabs(inValue) > .001f; }
+ inline bool NonZero(QT3DSU32 inValue) { return inValue != 0; }
+ inline bool IsZero(float inValue) { return fabs(inValue) < .001f; }
+ inline bool IsNotOne(float inValue) { return fabs(1.0f - inValue) > .001f; }
+
+ inline bool IsRectEdgeInBounds(QT3DSI32 inNewRectOffset, QT3DSI32 inNewRectWidth,
+ QT3DSI32 inCurrentRectOffset, QT3DSI32 inCurrentRectWidth)
+ {
+ QT3DSI32 newEnd = inNewRectOffset + inNewRectWidth;
+ QT3DSI32 currentEnd = inCurrentRectOffset + inCurrentRectWidth;
+ return inNewRectOffset >= inCurrentRectOffset && newEnd <= currentEnd;
+ }
+
+ struct STextRenderHelper
+ {
+ STextShader *m_Shader;
+ NVRenderInputAssembler &m_QuadInputAssembler;
+ STextRenderHelper(STextShader *inShader, NVRenderInputAssembler &inQuadInputAssembler)
+ : m_Shader(inShader)
+ , m_QuadInputAssembler(inQuadInputAssembler)
+ {
+ }
+ };
+
+ struct SPickResultProcessResult : public SUICRenderPickResult
+ {
+ SPickResultProcessResult(const SUICRenderPickResult &inSrc)
+ : SUICRenderPickResult(inSrc)
+ , m_WasPickConsumed(false)
+ {
+ }
+ SPickResultProcessResult()
+ : m_WasPickConsumed(false)
+ {
+ }
+ bool m_WasPickConsumed;
+ };
+
+ struct STextShaderPtr
+ {
+ NVAllocatorCallback &m_Allocator;
+ bool m_HasGeneratedShader;
+ STextShader *m_Shader;
+ STextShaderPtr(NVAllocatorCallback &alloc)
+ : m_Allocator(alloc)
+ , m_HasGeneratedShader(false)
+ , m_Shader(NULL)
+ {
+ }
+ bool HasGeneratedShader() { return m_HasGeneratedShader; }
+ void Set(STextShader *inShader)
+ {
+ m_Shader = inShader;
+ m_HasGeneratedShader = true;
+ }
+ ~STextShaderPtr()
+ {
+ if (m_Shader)
+ NVDelete(m_Allocator, m_Shader);
+ }
+ operator STextShader *() { return m_Shader; }
+ };
+
+ class CUICRendererImpl : public IUICRenderer, public IRenderWidgetContext
+ {
+ typedef nvhash_map<SShaderDefaultMaterialKey, SShaderGeneratorGeneratedShader *> TShaderMap;
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderConstantBuffer>>
+ TStrConstanBufMap;
+ typedef nvhash_map<const SLayer *, NVScopedRefCounted<SLayerRenderData>> TLayerRenderMap;
+ typedef nvvector<SLayerRenderData *> TLayerRenderList;
+ typedef nvvector<SUICRenderPickResult> TPickResultArray;
+
+ // Items to implement the widget context.
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderVertexBuffer>>
+ TStrVertBufMap;
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderIndexBuffer>>
+ TStrIndexBufMap;
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderShaderProgram>>
+ TStrShaderMap;
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderInputAssembler>> TStrIAMap;
+
+ typedef nvhash_map<long, SNode *> TBoneIdNodeMap;
+
+ IUICRenderContext &m_UICContext;
+ NVScopedRefCounted<NVRenderContext> m_Context;
+ NVScopedRefCounted<IBufferManager> m_BufferManager;
+ NVScopedRefCounted<IOffscreenRenderManager> m_OffscreenRenderManager;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ InvasiveSet<SShaderGeneratorGeneratedShader, SGGSGet, SGGSSet> m_LayerShaders;
+ // For rendering bounding boxes.
+ NVScopedRefCounted<NVRenderVertexBuffer> m_BoxVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> m_BoxIndexBuffer;
+ NVScopedRefCounted<NVRenderShaderProgram> m_BoxShader;
+ NVScopedRefCounted<NVRenderShaderProgram> m_ScreenRectShader;
+
+ NVScopedRefCounted<NVRenderVertexBuffer> m_AxisVertexBuffer;
+ NVScopedRefCounted<NVRenderShaderProgram> m_AxisShader;
+
+ // X,Y quad, broken down into 2 triangles and normalized over
+ //-1,1.
+ NVScopedRefCounted<NVRenderVertexBuffer> m_QuadVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> m_QuadIndexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> m_RectIndexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> m_QuadInputAssembler;
+ NVScopedRefCounted<NVRenderInputAssembler> m_RectInputAssembler;
+ NVScopedRefCounted<NVRenderAttribLayout> m_QuadAttribLayout;
+ NVScopedRefCounted<NVRenderAttribLayout> m_RectAttribLayout;
+
+ // X,Y triangle strip quads in screen coord dynamiclly setup
+ NVScopedRefCounted<NVRenderVertexBuffer> m_QuadStripVertexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> m_QuadStripInputAssembler;
+ NVScopedRefCounted<NVRenderAttribLayout> m_QuadStripAttribLayout;
+
+ // X,Y,Z point which is used for instanced based rendering of points
+ NVScopedRefCounted<NVRenderVertexBuffer> m_PointVertexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> m_PointInputAssembler;
+ NVScopedRefCounted<NVRenderAttribLayout> m_PointAttribLayout;
+
+ Option<NVScopedRefCounted<SLayerSceneShader>> m_SceneLayerShader;
+ Option<NVScopedRefCounted<SLayerProgAABlendShader>> m_LayerProgAAShader;
+
+ TShaderMap m_Shaders;
+ TStrConstanBufMap m_ConstantBuffers; ///< store the the shader constant buffers
+ // Option is true if we have attempted to generate the shader.
+ // This does not mean we were successul, however.
+ Option<NVScopedRefCounted<SDefaultMaterialRenderableDepthShader>>
+ m_DefaultMaterialDepthPrepassShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthPrepassShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthPrepassShaderDisplaced;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthTessLinearPrepassShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>>
+ m_DepthTessLinearPrepassShaderDisplaced;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthTessPhongPrepassShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_DepthTessNPatchPrepassShader;
+ Option<NVScopedRefCounted<STextDepthShader>> m_TextDepthPrepassShader;
+ Option<NVScopedRefCounted<SDefaultAoPassShader>> m_DefaultAoPassShader;
+ Option<NVScopedRefCounted<SDefaultAoPassShader>> m_FakeDepthShader;
+ Option<NVScopedRefCounted<SDefaultAoPassShader>> m_FakeCubemapDepthShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_ParaboloidDepthShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_ParaboloidDepthTessLinearShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_ParaboloidDepthTessPhongShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_ParaboloidDepthTessNPatchShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_CubemapDepthShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_CubemapDepthTessLinearShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_CubemapDepthTessPhongShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_CubemapDepthTessNPatchShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> m_OrthographicDepthShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>>
+ m_OrthographicDepthTessLinearShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>>
+ m_OrthographicDepthTessPhongShader;
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>>
+ m_OrthographicDepthTessNPatchShader;
+ Option<NVScopedRefCounted<SShadowmapPreblurShader>> m_CubeShadowBlurXShader;
+ Option<NVScopedRefCounted<SShadowmapPreblurShader>> m_CubeShadowBlurYShader;
+ Option<NVScopedRefCounted<SShadowmapPreblurShader>> m_OrthoShadowBlurXShader;
+ Option<NVScopedRefCounted<SShadowmapPreblurShader>> m_OrthoShadowBlurYShader;
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ Option<NVScopedRefCounted<SAdvancedModeBlendShader>> m_AdvancedModeOverlayBlendShader;
+ Option<NVScopedRefCounted<SAdvancedModeBlendShader>> m_AdvancedModeColorBurnBlendShader;
+ Option<NVScopedRefCounted<SAdvancedModeBlendShader>> m_AdvancedModeColorDodgeBlendShader;
+#endif
+ // Text shaders may be generated on demand.
+ STextShaderPtr m_TextShader;
+ STextShaderPtr m_TextPathShader;
+ STextShaderPtr m_TextWidgetShader;
+ STextShaderPtr m_TextOnscreenShader;
+
+ // Overlay used to render all widgets.
+ NVRenderRect m_BeginFrameViewport;
+ NVScopedRefCounted<NVRenderTexture2D> m_WidgetTexture;
+ NVScopedRefCounted<NVRenderFrameBuffer> m_WidgetFBO;
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // Advanced blend mode SW fallback
+ CResourceTexture2D m_LayerBlendTexture;
+ NVScopedRefCounted<NVRenderFrameBuffer> m_BlendFB;
+#endif
+ // Allocator for temporary data that is cleared after every layer.
+ TLayerRenderMap m_LayerToRenderMap;
+ TLayerRenderList m_LastFrameLayers;
+ volatile QT3DSI32 mRefCount;
+
+ // Set from the first layer.
+ TPickResultArray m_LastPickResults;
+
+ // Temporary information stored only when rendering a particular layer.
+ SLayerRenderData *m_CurrentLayer;
+ QT3DSMat44 m_ViewProjection;
+ eastl::string m_GeneratedShaderString;
+
+ TStrVertBufMap m_WidgetVertexBuffers;
+ TStrIndexBufMap m_WidgetIndexBuffers;
+ TStrShaderMap m_WidgetShaders;
+ TStrIAMap m_WidgetInputAssembler;
+
+ TBoneIdNodeMap m_BoneIdNodeMap;
+
+ bool m_PickRenderPlugins;
+ bool m_LayerCachingEnabled;
+ bool m_LayerGPuProfilingEnabled;
+ SShaderDefaultMaterialKeyProperties m_DefaultMaterialShaderKeyProperties;
+
+ public:
+ CUICRendererImpl(IUICRenderContext &ctx);
+ virtual ~CUICRendererImpl();
+ SShaderDefaultMaterialKeyProperties &DefaultMaterialShaderKeyProperties()
+ {
+ return m_DefaultMaterialShaderKeyProperties;
+ }
+
+ // NVRefCounted
+ void addRef() override;
+ void release() override;
+
+ void EnableLayerCaching(bool inEnabled) override { m_LayerCachingEnabled = inEnabled; }
+ bool IsLayerCachingEnabled() const override { return m_LayerCachingEnabled; }
+
+ void EnableLayerGpuProfiling(bool inEnabled) override
+ {
+ m_LayerGPuProfilingEnabled = inEnabled;
+ }
+ bool IsLayerGpuProfilingEnabled() const override { return m_LayerGPuProfilingEnabled; }
+
+ // Calls prepare layer for render
+ // and then do render layer.
+ bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ bool inRenderSiblings) override;
+ void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ bool clear, QT3DSVec3 clearColor, bool inRenderSiblings) override;
+ void ChildrenUpdated(SNode &inParent) override;
+ QT3DSF32 GetTextScale(const SText &inText) override;
+
+ SCamera *GetCameraForNode(const SNode &inNode) const override;
+ Option<SCuboidRect> GetCameraBounds(const SGraphObject &inObject) override;
+ virtual SLayer *GetLayerForNode(const SNode &inNode) const;
+ SLayerRenderData *GetOrCreateLayerRenderDataForNode(const SNode &inNode);
+
+ void BeginFrame() override;
+ void EndFrame() override;
+
+ void PickRenderPlugins(bool inPick) override { m_PickRenderPlugins = inPick; }
+ SUICRenderPickResult Pick(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords, bool inPickSiblings,
+ bool inPickEverything) override;
+
+ virtual Option<QT3DSVec2>
+ FacePosition(SNode &inNode, NVBounds3 inBounds, const QT3DSMat44 &inGlobalTransform,
+ const QT3DSVec2 &inViewportDimensions, const QT3DSVec2 &inMouseCoords,
+ NVDataRef<SGraphObject *> inMapperObjects, SBasisPlanes::Enum inPlane) override;
+
+ virtual SUICRenderPickResult PickOffscreenLayer(SLayer &inLayer,
+ const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords,
+ bool inPickEverything);
+
+ QT3DSVec3 UnprojectToPosition(SNode &inNode, QT3DSVec3 &inPosition,
+ const QT3DSVec2 &inMouseVec) const override;
+ QT3DSVec3 UnprojectWithDepth(SNode &inNode, QT3DSVec3 &inPosition,
+ const QT3DSVec3 &inMouseVec) const override;
+ QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const override;
+
+ Option<SLayerPickSetup> GetLayerPickSetup(SLayer &inLayer,
+ const QT3DSVec2 &inMouseCoords,
+ const SWindowDimensions &inPickDims) override;
+
+ Option<NVRenderRectF> GetLayerRect(SLayer &inLayer) override;
+
+ void RunLayerRender(SLayer &inLayer, const QT3DSMat44 &inViewProjection) override;
+
+ // Note that this allocator is completely reset on BeginFrame.
+ NVAllocatorCallback &GetPerFrameAllocator() override
+ {
+ return m_UICContext.GetPerFrameAllocator();
+ }
+ void RenderLayerRect(SLayer &inLayer, const QT3DSVec3 &inColor) override;
+ void AddRenderWidget(IRenderWidget &inWidget) override;
+
+ SScaleAndPosition GetWorldToPixelScaleFactor(SLayer &inLayer,
+ const QT3DSVec3 &inWorldPoint) override;
+ SScaleAndPosition GetWorldToPixelScaleFactor(const SCamera &inCamera,
+ const QT3DSVec3 &inWorldPoint,
+ SLayerRenderData &inRenderData);
+
+ void ReleaseLayerRenderResources(SLayer &inLayer) override;
+
+ void RenderQuad(const QT3DSVec2 inDimensions, const QT3DSMat44 &inMVP,
+ NVRenderTexture2D &inQuadTexture) override;
+ void RenderQuad() override;
+
+ void RenderPointsIndirect() override;
+
+ // render a screen aligned 2D text
+ void RenderText2D(QT3DSF32 x, QT3DSF32 y, qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
+ const char *text) override;
+ bool PrepareTextureAtlasForRender();
+
+ // render Gpu profiler values
+ void RenderGpuProfilerStats(QT3DSF32 x, QT3DSF32 y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor) override;
+
+ // Callback during the layer render process.
+ void LayerNeedsFrameClear(SLayerRenderData &inLayer);
+ void BeginLayerDepthPassRender(SLayerRenderData &inLayer);
+ void EndLayerDepthPassRender();
+ void BeginLayerRender(SLayerRenderData &inLayer);
+ void EndLayerRender();
+ void PrepareImageForIbl(SImage &inImage);
+
+ NVRenderShaderProgram *CompileShader(CRegisteredString inName, const char8_t *inVert,
+ const char8_t *inFrame);
+
+ NVRenderShaderProgram *GenerateShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet);
+ SShaderGeneratorGeneratedShader *GetShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet);
+
+ SDefaultAoPassShader *GetDefaultAoPassShader(TShaderFeatureSet inFeatureSet);
+ SDefaultAoPassShader *GetFakeDepthShader(TShaderFeatureSet inFeatureSet);
+ SDefaultAoPassShader *GetFakeCubeDepthShader(TShaderFeatureSet inFeatureSet);
+ SDefaultMaterialRenderableDepthShader *GetRenderableDepthShader();
+
+ SRenderableDepthPrepassShader *GetParaboloidDepthShader(TessModeValues::Enum inTessMode);
+ SRenderableDepthPrepassShader *GetParaboloidDepthNoTessShader();
+ SRenderableDepthPrepassShader *GetParaboloidDepthTessLinearShader();
+ SRenderableDepthPrepassShader *GetParaboloidDepthTessPhongShader();
+ SRenderableDepthPrepassShader *GetParaboloidDepthTessNPatchShader();
+ SRenderableDepthPrepassShader *GetCubeShadowDepthShader(TessModeValues::Enum inTessMode);
+ SRenderableDepthPrepassShader *GetCubeDepthNoTessShader();
+ SRenderableDepthPrepassShader *GetCubeDepthTessLinearShader();
+ SRenderableDepthPrepassShader *GetCubeDepthTessPhongShader();
+ SRenderableDepthPrepassShader *GetCubeDepthTessNPatchShader();
+ SRenderableDepthPrepassShader *GetOrthographicDepthShader(TessModeValues::Enum inTessMode);
+ SRenderableDepthPrepassShader *GetOrthographicDepthNoTessShader();
+ SRenderableDepthPrepassShader *GetOrthographicDepthTessLinearShader();
+ SRenderableDepthPrepassShader *GetOrthographicDepthTessPhongShader();
+ SRenderableDepthPrepassShader *GetOrthographicDepthTessNPatchShader();
+
+ SRenderableDepthPrepassShader *GetDepthPrepassShader(bool inDisplaced);
+ SRenderableDepthPrepassShader *GetDepthTessPrepassShader(TessModeValues::Enum inTessMode,
+ bool inDisplaced);
+ SRenderableDepthPrepassShader *GetDepthTessLinearPrepassShader(bool inDisplaced);
+ SRenderableDepthPrepassShader *GetDepthTessPhongPrepassShader();
+ SRenderableDepthPrepassShader *GetDepthTessNPatchPrepassShader();
+ STextDepthShader *GetTextDepthShader();
+ STextRenderHelper GetShader(STextRenderable &inRenderable, bool inUsePathRendering);
+ STextRenderHelper GetTextShader(bool inUsePathRendering);
+ STextRenderHelper GetTextWidgetShader();
+ STextRenderHelper GetOnscreenTextShader();
+ SLayerSceneShader *GetSceneLayerShader();
+ NVRenderShaderProgram *GetTextAtlasEntryShader();
+ void GenerateXYQuad();
+ void GenerateXYQuadStrip();
+ void GenerateXYZPoint();
+ eastl::pair<NVRenderVertexBuffer *, NVRenderIndexBuffer *> GetXYQuad();
+ SLayerProgAABlendShader *GetLayerProgAABlendShader();
+ SShadowmapPreblurShader *GetCubeShadowBlurXShader();
+ SShadowmapPreblurShader *GetCubeShadowBlurYShader();
+ SShadowmapPreblurShader *GetOrthoShadowBlurXShader();
+ SShadowmapPreblurShader *GetOrthoShadowBlurYShader();
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ SAdvancedModeBlendShader *GetAdvancedBlendModeShader(AdvancedBlendModes::Enum blendMode);
+ SAdvancedModeBlendShader *GetOverlayBlendModeShader();
+ SAdvancedModeBlendShader *GetColorBurnBlendModeShader();
+ SAdvancedModeBlendShader *GetColorDodgeBlendModeShader();
+#endif
+ SLayerRenderData *GetLayerRenderData() { return m_CurrentLayer; }
+ SLayerGlobalRenderProperties GetLayerGlobalRenderProperties();
+ void UpdateCbAoShadow(const SLayer *pLayer, const SCamera *pCamera,
+ CResourceTexture2D &inDepthTexture);
+
+ NVRenderContext &GetContext() { return *m_Context; }
+
+ IUICRenderContext &GetUICContext() { return m_UICContext; }
+
+ void DrawScreenRect(NVRenderRectF inRect, const QT3DSVec3 &inColor);
+ // Binds an offscreen texture. Widgets are rendered last.
+ void SetupWidgetLayer();
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ NVScopedRefCounted<NVRenderTexture2D> GetLayerBlendTexture()
+ {
+ return m_LayerBlendTexture.GetTexture();
+ }
+
+ NVScopedRefCounted<NVRenderFrameBuffer> GetBlendFB()
+ {
+ return m_BlendFB;
+ }
+#endif
+ // widget context implementation
+ virtual NVRenderVertexBuffer &
+ GetOrCreateVertexBuffer(CRegisteredString &inStr, QT3DSU32 stride,
+ NVConstDataRef<QT3DSU8> bufferData = NVConstDataRef<QT3DSU8>()) override;
+ virtual NVRenderIndexBuffer &
+ GetOrCreateIndexBuffer(CRegisteredString &inStr,
+ qt3ds::render::NVRenderComponentTypes::Enum componentType, size_t size,
+ NVConstDataRef<QT3DSU8> bufferData = NVConstDataRef<QT3DSU8>()) override;
+ virtual NVRenderAttribLayout &
+ CreateAttributeLayout(NVConstDataRef<qt3ds::render::NVRenderVertexBufferEntry> attribs) override;
+ virtual NVRenderInputAssembler &
+ GetOrCreateInputAssembler(CRegisteredString &inStr, NVRenderAttribLayout *attribLayout,
+ NVConstDataRef<NVRenderVertexBuffer *> buffers,
+ const NVRenderIndexBuffer *indexBuffer,
+ NVConstDataRef<QT3DSU32> strides, NVConstDataRef<QT3DSU32> offsets) override;
+
+ NVRenderVertexBuffer *GetVertexBuffer(CRegisteredString &inStr) override;
+ NVRenderIndexBuffer *GetIndexBuffer(CRegisteredString &inStr) override;
+ NVRenderInputAssembler *GetInputAssembler(CRegisteredString &inStr) override;
+
+ NVRenderShaderProgram *GetShader(CRegisteredString inStr) override;
+ NVRenderShaderProgram *CompileAndStoreShader(CRegisteredString inStr) override;
+ IShaderProgramGenerator &GetProgramGenerator() override;
+
+ STextDimensions MeasureText(const STextRenderInfo &inText) override;
+ void RenderText(const STextRenderInfo &inText, const QT3DSVec3 &inTextColor,
+ const QT3DSVec3 &inBackgroundColor, const QT3DSMat44 &inMVP) override;
+
+ // Given a node and a point in the node's local space (most likely its pivot point), we
+ // return
+ // a normal matrix so you can get the axis out, a transformation from node to camera
+ // a new position and a floating point scale factor so you can render in 1/2 perspective
+ // mode
+ // or orthographic mode if you would like to.
+ virtual SWidgetRenderInformation
+ GetWidgetRenderInformation(SNode &inNode, const QT3DSVec3 &inPos,
+ RenderWidgetModes::Enum inWidgetMode) override;
+
+ Option<QT3DSVec2> GetLayerMouseCoords(SLayer &inLayer, const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool forceImageIntersect = false) const override;
+
+ protected:
+ Option<QT3DSVec2> GetLayerMouseCoords(SLayerRenderData &inLayer, const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool forceImageIntersect = false) const;
+ SPickResultProcessResult ProcessPickResultList(bool inPickEverything);
+ // If the mouse y coordinates need to be flipped we expect that to happen before entry into
+ // this function
+ void GetLayerHitObjectList(SLayerRenderData &inLayer, const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inMouseCoords, bool inPickEverything,
+ TPickResultArray &outIntersectionResult,
+ NVAllocatorCallback &inTempAllocator);
+ void IntersectRayWithSubsetRenderable(const SRay &inRay,
+ SRenderableObject &inRenderableObject,
+ TPickResultArray &outIntersectionResultList,
+ NVAllocatorCallback &inTempAllocator);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp
new file mode 100644
index 00000000..5f976be8
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.cpp
@@ -0,0 +1,2117 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRender.h"
+#include "UICRenderer.h"
+#include "UICRendererImpl.h"
+#include "UICRenderLayer.h"
+#include "UICRenderEffect.h"
+#include "EASTL/sort.h"
+#include "UICRenderLight.h"
+#include "UICRenderCamera.h"
+#include "UICRenderScene.h"
+#include "UICRenderPresentation.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICRenderContext.h"
+#include "UICRenderResourceManager.h"
+#include "UICTextRenderer.h"
+#include "UICRenderEffectSystem.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "UICOffscreenRenderKey.h"
+#include "UICRenderPlugin.h"
+#include "UICRenderPluginGraphObject.h"
+#include "UICRenderResourceBufferObjects.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "UICRenderMaterialHelpers.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderTextTextureCache.h"
+#include "UICRenderTextTextureAtlas.h"
+#include "UICRenderRenderList.h"
+#include "UICRendererUtil.h"
+
+#ifdef WIN32
+#pragma warning(disable : 4355)
+#endif
+
+#define UIC_CACHED_POST_EFFECT
+
+namespace uic {
+namespace render {
+ using eastl::reverse;
+ using eastl::stable_sort;
+ using qt3ds::render::NVRenderContextScopedProperty;
+ using qt3ds::QT3DSVec2;
+
+ SLayerRenderData::SLayerRenderData(SLayer &inLayer, CUICRendererImpl &inRenderer)
+ : SLayerRenderPreparationData(inLayer, inRenderer)
+ , m_LayerTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_TemporalAATexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerDepthTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerPrepassDepthTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerWidgetTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerSsaoTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerMultisampleTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerMultisamplePrepassDepthTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerMultisampleWidgetTexture(inRenderer.GetUICContext().GetResourceManager())
+ , m_LayerCachedTexture(NULL)
+ , m_AdvancedBlendDrawTexture(NULL)
+ , m_AdvancedBlendBlendTexture(NULL)
+ , m_AdvancedModeDrawFB(NULL)
+ , m_AdvancedModeBlendFB(NULL)
+ , m_ProgressiveAAPassIndex(0)
+ , m_TemporalAAPassIndex(0)
+ , m_NonDirtyTemporalAAPassIndex(0)
+ , m_TextScale(1.0f)
+ , mRefCount(0)
+ , m_DepthBufferFormat(NVRenderTextureFormats::Unknown)
+ {
+ }
+
+ SLayerRenderData::~SLayerRenderData()
+ {
+ IResourceManager &theResourceManager(m_Renderer.GetUICContext().GetResourceManager());
+ if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture)
+ theResourceManager.Release(*m_LayerCachedTexture);
+ if (m_AdvancedModeDrawFB) {
+ m_AdvancedModeDrawFB->release();
+ m_AdvancedModeDrawFB = NULL;
+ }
+ if (m_AdvancedModeBlendFB) {
+ m_AdvancedModeBlendFB->release();
+ m_AdvancedModeBlendFB = NULL;
+ }
+ if (m_AdvancedBlendBlendTexture)
+ m_AdvancedBlendBlendTexture = NULL;
+ if (m_AdvancedBlendDrawTexture)
+ m_AdvancedBlendDrawTexture = NULL;
+ }
+ void SLayerRenderData::PrepareForRender(const SWindowDimensions &inViewportDimensions)
+ {
+ SLayerRenderPreparationData::PrepareForRender(inViewportDimensions);
+ SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
+ IResourceManager &theResourceManager(m_Renderer.GetUICContext().GetResourceManager());
+ // at that time all values shoud be updated
+ m_Renderer.UpdateCbAoShadow(&m_Layer, m_Camera, m_LayerDepthTexture);
+
+ // Generate all necessary lighting keys
+
+ if (thePrepResult.m_Flags.WasLayerDataDirty()) {
+ m_ProgressiveAAPassIndex = 0;
+ }
+
+ // Get rid of the layer texture if we aren't rendering to texture this frame.
+ if (m_LayerTexture && !thePrepResult.m_Flags.ShouldRenderToTexture()) {
+ if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture) {
+ theResourceManager.Release(*m_LayerCachedTexture);
+ m_LayerCachedTexture = NULL;
+ }
+
+ m_LayerTexture.ReleaseTexture();
+ m_LayerDepthTexture.ReleaseTexture();
+ m_LayerWidgetTexture.ReleaseTexture();
+ m_LayerSsaoTexture.ReleaseTexture();
+ m_LayerMultisampleTexture.ReleaseTexture();
+ m_LayerMultisamplePrepassDepthTexture.ReleaseTexture();
+ m_LayerMultisampleWidgetTexture.ReleaseTexture();
+ }
+
+ if (NeedsWidgetTexture() == false)
+ m_LayerWidgetTexture.ReleaseTexture();
+
+ if (m_LayerDepthTexture && !thePrepResult.m_Flags.RequiresDepthTexture())
+ m_LayerDepthTexture.ReleaseTexture();
+
+ if (m_LayerSsaoTexture && !thePrepResult.m_Flags.RequiresSsaoPass())
+ m_LayerSsaoTexture.ReleaseTexture();
+
+ m_Renderer.LayerNeedsFrameClear(*this);
+
+ // Clean up the texture cache if layer dimensions changed
+ if (inViewportDimensions.m_Width != m_previousDimensions.width()
+ || inViewportDimensions.m_Height != m_previousDimensions.height()) {
+ m_LayerTexture.ReleaseTexture();
+ m_LayerDepthTexture.ReleaseTexture();
+ m_LayerSsaoTexture.ReleaseTexture();
+ m_LayerWidgetTexture.ReleaseTexture();
+ m_LayerPrepassDepthTexture.ReleaseTexture();
+ m_TemporalAATexture.ReleaseTexture();
+ m_LayerMultisampleTexture.ReleaseTexture();
+ m_LayerMultisamplePrepassDepthTexture.ReleaseTexture();
+ m_LayerMultisampleWidgetTexture.ReleaseTexture();
+
+ m_previousDimensions.setWidth(inViewportDimensions.m_Width);
+ m_previousDimensions.setHeight(inViewportDimensions.m_Height);
+
+ theResourceManager.DestroyFreeSizedResources();
+
+ // Effect system uses different resource manager, so clean that up too
+ m_Renderer.GetUICContext().GetEffectSystem().GetResourceManager()
+ .DestroyFreeSizedResources();
+ }
+ }
+
+ NVRenderTextureFormats::Enum SLayerRenderData::GetDepthBufferFormat()
+ {
+ if (m_DepthBufferFormat == NVRenderTextureFormats::Unknown) {
+ QT3DSU32 theExistingDepthBits = m_Renderer.GetContext().GetDepthBits();
+ QT3DSU32 theExistingStencilBits = m_Renderer.GetContext().GetStencilBits();
+ switch (theExistingDepthBits) {
+ case 32:
+ m_DepthBufferFormat = NVRenderTextureFormats::Depth32;
+ break;
+ case 24:
+ // check if we have stencil bits
+ if (theExistingStencilBits > 0)
+ m_DepthBufferFormat =
+ NVRenderTextureFormats::Depth24Stencil8; // currently no stencil usage
+ // should be Depth24Stencil8 in
+ // this case
+ else
+ m_DepthBufferFormat = NVRenderTextureFormats::Depth24;
+ break;
+ case 16:
+ m_DepthBufferFormat = NVRenderTextureFormats::Depth16;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ m_DepthBufferFormat = NVRenderTextureFormats::Depth16;
+ break;
+ }
+ }
+ return m_DepthBufferFormat;
+ }
+
+ NVRenderFrameBufferAttachments::Enum
+ SLayerRenderData::GetFramebufferDepthAttachmentFormat(NVRenderTextureFormats::Enum depthFormat)
+ {
+ NVRenderFrameBufferAttachments::Enum fmt = NVRenderFrameBufferAttachments::Depth;
+
+ switch (depthFormat) {
+ case NVRenderTextureFormats::Depth16:
+ case NVRenderTextureFormats::Depth24:
+ case NVRenderTextureFormats::Depth32:
+ fmt = NVRenderFrameBufferAttachments::Depth;
+ break;
+ case NVRenderTextureFormats::Depth24Stencil8:
+ fmt = NVRenderFrameBufferAttachments::DepthStencil;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ return fmt;
+ }
+
+ void SLayerRenderData::RenderAoPass()
+ {
+ m_Renderer.BeginLayerDepthPassRender(*this);
+
+ NVRenderContext &theContext(m_Renderer.GetContext());
+ SDefaultAoPassShader *shader = m_Renderer.GetDefaultAoPassShader(GetShaderFeatureSet());
+ if (shader == NULL)
+ return;
+
+ // Set initial state
+ theContext.SetBlendingEnabled(false);
+ theContext.SetDepthWriteEnabled(false);
+ theContext.SetDepthTestEnabled(false);
+ theContext.SetActiveShader(&(shader->m_Shader));
+
+ // Setup constants
+ shader->m_CameraDirection.Set(m_CameraDirection);
+ shader->m_ViewMatrix.Set(m_Camera->m_GlobalTransform);
+
+ shader->m_DepthTexture.Set(m_LayerDepthTexture);
+
+ // Important uniforms for AO calculations
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ shader->m_CameraProperties.Set(theCameraProps);
+ shader->m_AoShadowParams.Set();
+
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+
+ m_Renderer.EndLayerDepthPassRender();
+ }
+
+ void SLayerRenderData::RenderFakeDepthMapPass(NVRenderTexture2D *theDepthTex,
+ NVRenderTextureCube *theDepthCube)
+ {
+ m_Renderer.BeginLayerDepthPassRender(*this);
+
+ NVRenderContext &theContext(m_Renderer.GetContext());
+ SDefaultAoPassShader *shader = theDepthTex
+ ? m_Renderer.GetFakeDepthShader(GetShaderFeatureSet())
+ : m_Renderer.GetFakeCubeDepthShader(GetShaderFeatureSet());
+ if (shader == NULL)
+ return;
+
+ // Set initial state
+ theContext.SetBlendingEnabled(false);
+ theContext.SetDepthWriteEnabled(false);
+ theContext.SetDepthTestEnabled(false);
+ theContext.SetActiveShader(&(shader->m_Shader));
+
+ // Setup constants
+ shader->m_CameraDirection.Set(m_CameraDirection);
+ shader->m_ViewMatrix.Set(m_Camera->m_GlobalTransform);
+
+ shader->m_DepthTexture.Set(theDepthTex);
+ shader->m_CubeTexture.Set(theDepthCube);
+
+ // Important uniforms for AO calculations
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ shader->m_CameraProperties.Set(theCameraProps);
+ shader->m_AoShadowParams.Set();
+
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+ }
+
+ namespace {
+
+ void computeFrustumBounds(const SCamera &inCamera, const NVRenderRectF &inViewPort,
+ QT3DSVec3 &ctrBound, QT3DSVec3 camVerts[8])
+ {
+ QT3DSVec3 camEdges[4];
+
+ const QT3DSF32 *dataPtr(inCamera.m_GlobalTransform.front());
+ QT3DSVec3 camX(dataPtr[0], dataPtr[1], dataPtr[2]);
+ QT3DSVec3 camY(dataPtr[4], dataPtr[5], dataPtr[6]);
+ QT3DSVec3 camZ(dataPtr[8], dataPtr[9], dataPtr[10]);
+
+ float tanFOV = tanf(inCamera.m_FOV * 0.5f);
+ float asTanFOV = tanFOV * inViewPort.m_Height / inViewPort.m_Width;
+ camEdges[0] = -tanFOV * camX + asTanFOV * camY + camZ;
+ camEdges[1] = tanFOV * camX + asTanFOV * camY + camZ;
+ camEdges[2] = tanFOV * camX - asTanFOV * camY + camZ;
+ camEdges[3] = -tanFOV * camX - asTanFOV * camY + camZ;
+
+ camVerts[0] = inCamera.m_Position + camEdges[0] * inCamera.m_ClipNear;
+ camVerts[1] = inCamera.m_Position + camEdges[0] * inCamera.m_ClipFar;
+ camVerts[2] = inCamera.m_Position + camEdges[1] * inCamera.m_ClipNear;
+ camVerts[3] = inCamera.m_Position + camEdges[1] * inCamera.m_ClipFar;
+ camVerts[4] = inCamera.m_Position + camEdges[2] * inCamera.m_ClipNear;
+ camVerts[5] = inCamera.m_Position + camEdges[2] * inCamera.m_ClipFar;
+ camVerts[6] = inCamera.m_Position + camEdges[3] * inCamera.m_ClipNear;
+ camVerts[7] = inCamera.m_Position + camEdges[3] * inCamera.m_ClipFar;
+
+ ctrBound = camVerts[0];
+ for (int i = 1; i < 8; ++i) {
+ ctrBound += camVerts[i];
+ }
+ ctrBound *= 0.125f;
+ }
+
+ void SetupCameraForShadowMap(const QT3DSVec2 &inCameraVec, NVRenderContext & /*inContext*/
+ ,
+ const SCamera &inCamera, const SLight *inLight,
+ SCamera &theCamera)
+ {
+ // setup light matrix
+ QT3DSU32 mapRes = 1 << inLight->m_ShadowMapRes;
+ NVRenderRectF theViewport(0.0f, 0.0f, (float)mapRes, (float)mapRes);
+ theCamera.m_ClipNear = 1.0f;
+ theCamera.m_ClipFar = inLight->m_ShadowMapFar;
+ // Setup camera projection
+ // we adjust light pos z to camera for directional lights if pos is zero
+ QT3DSVec3 inCameraDir = inCamera.GetDirection();
+ QT3DSVec3 inLightPos = inLight->GetGlobalPos();
+ QT3DSVec3 inLightDir = inLight->GetDirection();
+
+ if (inLight->m_Flags.IsLeftHanded())
+ inLightPos.z = -inLightPos.z;
+
+ inLightPos -= inLightDir * inCamera.m_ClipNear;
+
+ if (inLight->m_LightType == RenderLightTypes::Directional) {
+ QT3DSVec3 frustBounds[8], boundCtr;
+ computeFrustumBounds(inCamera, theViewport, boundCtr, frustBounds);
+
+ inLightPos = boundCtr;
+ // inLightPos += inLightDir * 0.5 * ( inCamera.m_ClipNear + inCamera.m_ClipFar );
+ float d = 0.5f * (inLight->m_ShadowMapFar + 1.0f);
+ inLightPos += inLightDir * d;
+
+ float o1 = d * 2.0f * tan(0.5f * theCamera.m_FOV);
+ float o2 = inLight->m_ShadowMapFar - 1.0f;
+ float o = fabs(inLightDir.dot(inCameraDir));
+ o = (1.0f - o) * o2 + o * o1;
+
+ theViewport.m_Height = NVHalfPi * o;
+ theViewport.m_Width = NVHalfPi * o;
+
+ inLightPos -= inLightDir * d;
+ theCamera.m_ClipFar += inCameraVec.x;
+ }
+
+ theCamera.m_Flags.SetLeftHanded(false);
+
+ theCamera.m_Flags.ClearOrSet(inLight->m_LightType == RenderLightTypes::Directional,
+ NodeFlagValues::Orthographic);
+ theCamera.m_Parent = NULL;
+ theCamera.m_Pivot = inLight->m_Pivot;
+
+ if (inLight->m_LightType != RenderLightTypes::Point) {
+ theCamera.LookAt(inLightPos, QT3DSVec3(0, 1.0, 0), inLightPos + inLightDir);
+ } else {
+ theCamera.LookAt(inLightPos, QT3DSVec3(0, 1.0, 0), QT3DSVec3(0, 0, 0));
+ }
+
+ theCamera.m_FOV = 1.57079f;
+ theCamera.CalculateGlobalVariables(theViewport,
+ QT3DSVec2(theViewport.m_Width, theViewport.m_Height));
+ }
+ }
+
+ void SetupCubeShadowCameras(const SLight *inLight, SCamera inCameras[6])
+ {
+ // setup light matrix
+ QT3DSU32 mapRes = 1 << inLight->m_ShadowMapRes;
+ NVRenderRectF theViewport(0.0f, 0.0f, (float)mapRes, (float)mapRes);
+ QT3DSVec3 rotOfs[6];
+
+ QT3DS_ASSERT(inLight != NULL);
+ QT3DS_ASSERT(inLight->m_LightType != RenderLightTypes::Directional);
+
+ QT3DSVec3 inLightPos = inLight->GetGlobalPos();
+ if (inLight->m_Flags.IsLeftHanded())
+ inLightPos.z = -inLightPos.z;
+
+ rotOfs[0] = QT3DSVec3(0.f, -NVHalfPi, NVPi);
+ rotOfs[1] = QT3DSVec3(0.f, NVHalfPi, NVPi);
+ rotOfs[2] = QT3DSVec3(NVHalfPi, 0.f, 0.f);
+ rotOfs[3] = QT3DSVec3(-NVHalfPi, 0.f, 0.f);
+ rotOfs[4] = QT3DSVec3(0.f, NVPi, -NVPi);
+ rotOfs[5] = QT3DSVec3(0.f, 0.f, NVPi);
+
+ for (int i = 0; i < 6; ++i) {
+ inCameras[i].m_Flags.SetLeftHanded(false);
+
+ inCameras[i].m_Flags.ClearOrSet(false, NodeFlagValues::Orthographic);
+ inCameras[i].m_Parent = NULL;
+ inCameras[i].m_Pivot = inLight->m_Pivot;
+ inCameras[i].m_ClipNear = 1.0f;
+ inCameras[i].m_ClipFar = NVMax<QT3DSF32>(2.0f, inLight->m_ShadowMapFar);
+ inCameras[i].m_FOV = NVHalfPi;
+
+ inCameras[i].m_Position = inLightPos;
+ inCameras[i].m_Rotation = rotOfs[i];
+ inCameras[i].CalculateGlobalVariables(
+ theViewport, QT3DSVec2(theViewport.m_Width, theViewport.m_Height));
+ }
+
+ /*
+ if ( inLight->m_LightType == RenderLightTypes::Point ) return;
+
+ QT3DSVec3 viewDirs[6];
+ QT3DSVec3 viewUp[6];
+ QT3DSMat33 theDirMatrix( inLight->m_GlobalTransform.getUpper3x3() );
+
+ viewDirs[0] = theDirMatrix.transform( QT3DSVec3( 1.f, 0.f, 0.f ) );
+ viewDirs[2] = theDirMatrix.transform( QT3DSVec3( 0.f, -1.f, 0.f ) );
+ viewDirs[4] = theDirMatrix.transform( QT3DSVec3( 0.f, 0.f, 1.f ) );
+ viewDirs[0].normalize(); viewDirs[2].normalize(); viewDirs[4].normalize();
+ viewDirs[1] = -viewDirs[0];
+ viewDirs[3] = -viewDirs[2];
+ viewDirs[5] = -viewDirs[4];
+
+ viewUp[0] = viewDirs[2];
+ viewUp[1] = viewDirs[2];
+ viewUp[2] = viewDirs[5];
+ viewUp[3] = viewDirs[4];
+ viewUp[4] = viewDirs[2];
+ viewUp[5] = viewDirs[2];
+
+ for (int i = 0; i < 6; ++i)
+ {
+ inCameras[i].LookAt( inLightPos, viewUp[i], inLightPos + viewDirs[i] );
+ inCameras[i].CalculateGlobalVariables( theViewport, QT3DSVec2( theViewport.m_Width,
+ theViewport.m_Height ) );
+ }
+ */
+ }
+
+ inline void RenderRenderableShadowMapPass(SLayerRenderData &inData, SRenderableObject &inObject,
+ const QT3DSVec2 &inCameraProps, TShaderFeatureSet,
+ QT3DSU32 lightIndex, const SCamera &inCamera)
+ {
+ SShadowMapEntry *pEntry = inData.m_ShadowMapManager->GetShadowMapEntry(lightIndex);
+
+ if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ static_cast<SSubsetRenderableBase &>(inObject).RenderShadowMapPass(
+ inCameraProps, inData.m_Lights[lightIndex], inCamera, pEntry);
+ else if (inObject.m_RenderableFlags.IsCustomMaterialMeshSubset()) {
+ static_cast<SSubsetRenderableBase &>(inObject).RenderShadowMapPass(
+ inCameraProps, inData.m_Lights[lightIndex], inCamera, pEntry);
+ } else if (inObject.m_RenderableFlags.IsPath()) {
+ static_cast<SPathRenderable &>(inObject).RenderShadowMapPass(
+ inCameraProps, inData.m_Lights[lightIndex], inCamera, pEntry);
+ }
+ }
+
+ void SLayerRenderData::RenderShadowCubeBlurPass(CResourceFrameBuffer *theFB,
+ NVRenderTextureCube *target0,
+ NVRenderTextureCube *target1, QT3DSF32 filterSz,
+ QT3DSF32 clipFar)
+ {
+ NVRenderContext &theContext(m_Renderer.GetContext());
+
+ SShadowmapPreblurShader *shaderX = m_Renderer.GetCubeShadowBlurXShader();
+ SShadowmapPreblurShader *shaderY = m_Renderer.GetCubeShadowBlurYShader();
+
+ if (shaderX == NULL)
+ return;
+ if (shaderY == NULL)
+ return;
+ // if ( theShader == NULL ) return;
+
+ // Enable drawing to 6 color attachment buffers for cubemap passes
+ qt3ds::QT3DSI32 buffers[6] = { 0, 1, 2, 3, 4, 5 };
+ qt3ds::foundation::NVConstDataRef<qt3ds::QT3DSI32> bufferList(buffers, 6);
+ theContext.SetDrawBuffers(bufferList);
+
+ // Attach framebuffer targets
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color0, *target1,
+ NVRenderTextureCubeFaces::CubePosX);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color1, *target1,
+ NVRenderTextureCubeFaces::CubeNegX);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color2, *target1,
+ NVRenderTextureCubeFaces::CubePosY);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color3, *target1,
+ NVRenderTextureCubeFaces::CubeNegY);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color4, *target1,
+ NVRenderTextureCubeFaces::CubePosZ);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color5, *target1,
+ NVRenderTextureCubeFaces::CubeNegZ);
+
+ // Set initial state
+ theContext.SetBlendingEnabled(false);
+ theContext.SetDepthWriteEnabled(false);
+ theContext.SetDepthTestEnabled(false);
+ // theContext.SetColorWritesEnabled(true);
+ theContext.SetActiveShader(&(shaderX->m_Shader));
+
+ shaderX->m_CameraProperties.Set(QT3DSVec2(filterSz, clipFar));
+ shaderX->m_DepthCube.Set(target0);
+
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+
+ theContext.SetActiveShader(&(shaderY->m_Shader));
+
+ // Lather, Rinse, and Repeat for the Y-blur pass
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color0, *target0,
+ NVRenderTextureCubeFaces::CubePosX);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color1, *target0,
+ NVRenderTextureCubeFaces::CubeNegX);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color2, *target0,
+ NVRenderTextureCubeFaces::CubePosY);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color3, *target0,
+ NVRenderTextureCubeFaces::CubeNegY);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color4, *target0,
+ NVRenderTextureCubeFaces::CubePosZ);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color5, *target0,
+ NVRenderTextureCubeFaces::CubeNegZ);
+
+ shaderY->m_CameraProperties.Set(QT3DSVec2(filterSz, clipFar));
+ shaderY->m_DepthCube.Set(target1);
+
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+
+ theContext.SetDepthWriteEnabled(true);
+ theContext.SetDepthTestEnabled(true);
+ // theContext.SetColorWritesEnabled(false);
+
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color0, NVRenderTextureOrRenderBuffer(),
+ NVRenderTextureCubeFaces::CubePosX);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color1, NVRenderTextureOrRenderBuffer(),
+ NVRenderTextureCubeFaces::CubeNegX);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color2, NVRenderTextureOrRenderBuffer(),
+ NVRenderTextureCubeFaces::CubePosY);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color3, NVRenderTextureOrRenderBuffer(),
+ NVRenderTextureCubeFaces::CubeNegY);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color4, NVRenderTextureOrRenderBuffer(),
+ NVRenderTextureCubeFaces::CubePosZ);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color5, NVRenderTextureOrRenderBuffer(),
+ NVRenderTextureCubeFaces::CubeNegZ);
+
+ theContext.SetDrawBuffers(qt3ds::foundation::toConstDataRef((qt3ds::QT3DSI32)0));
+ }
+
+ void SLayerRenderData::RenderShadowMapBlurPass(CResourceFrameBuffer *theFB,
+ NVRenderTexture2D *target0,
+ NVRenderTexture2D *target1, QT3DSF32 filterSz,
+ QT3DSF32 clipFar)
+ {
+ NVRenderContext &theContext(m_Renderer.GetContext());
+
+ SShadowmapPreblurShader *shaderX = m_Renderer.GetOrthoShadowBlurXShader();
+ SShadowmapPreblurShader *shaderY = m_Renderer.GetOrthoShadowBlurYShader();
+
+ if (shaderX == NULL)
+ return;
+ if (shaderY == NULL)
+ return;
+
+ // Attach framebuffer target
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::Color0, *target1);
+ //(*theFB)->Attach( NVRenderFrameBufferAttachments::DepthStencil, *target1 );
+
+ // Set initial state
+ theContext.SetBlendingEnabled(false);
+ theContext.SetDepthWriteEnabled(false);
+ theContext.SetDepthTestEnabled(false);
+ theContext.SetColorWritesEnabled(true);
+ theContext.SetActiveShader(&(shaderX->m_Shader));
+
+ shaderX->m_CameraProperties.Set(QT3DSVec2(filterSz, clipFar));
+ shaderX->m_DepthMap.Set(target0);
+
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::Color0, *target0);
+ //(*theFB)->Attach( NVRenderFrameBufferAttachments::DepthStencil, *target0 );
+ theContext.SetActiveShader(&(shaderY->m_Shader));
+
+ shaderY->m_CameraProperties.Set(QT3DSVec2(filterSz, clipFar));
+ shaderY->m_DepthMap.Set(target1);
+
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+
+ theContext.SetDepthWriteEnabled(true);
+ theContext.SetDepthTestEnabled(true);
+ theContext.SetColorWritesEnabled(false);
+
+ //(*theFB)->Attach( NVRenderFrameBufferAttachments::DepthStencil,
+ //NVRenderTextureOrRenderBuffer() );
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::Color0, NVRenderTextureOrRenderBuffer());
+ }
+
+ void SLayerRenderData::RenderShadowMapPass(CResourceFrameBuffer *theFB)
+ {
+ SStackPerfTimer ___timer(m_Renderer.GetUICContext().GetPerfTimer(),
+ "SLayerRenderData::RenderShadowMapPass");
+
+ if (m_Camera == NULL || !GetShadowMapManager())
+ return;
+
+ // Check if we have anything to render
+ if (m_OpaqueObjects.size() == 0 || m_Lights.size() == 0)
+ return;
+
+ m_Renderer.BeginLayerDepthPassRender(*this);
+
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+
+ // we may change the viewport
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theRenderContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport);
+
+ // disable color writes
+ // theRenderContext.SetColorWritesEnabled( false );
+ theRenderContext.SetColorWritesEnabled(true);
+ theRenderContext.SetDepthWriteEnabled(true);
+ theRenderContext.SetCullingEnabled(false);
+ theRenderContext.SetClearColor(QT3DSVec4(1.0f));
+
+ // we render the shadow map with a slight offset to prevent shadow acne and cull the front
+ // faces
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> rsdefaultstate =
+ theRenderContext.CreateRasterizerState(0.0, 0.0, qt3ds::render::NVRenderFaces::Back);
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> rsstate =
+ theRenderContext.CreateRasterizerState(1.5, 2.0, qt3ds::render::NVRenderFaces::Front);
+ theRenderContext.SetRasterizerState(rsstate);
+
+ qt3ds::render::NVRenderClearFlags clearFlags(qt3ds::render::NVRenderClearValues::Depth
+ | qt3ds::render::NVRenderClearValues::Stencil
+ | qt3ds::render::NVRenderClearValues::Color);
+
+ for (QT3DSU32 i = 0; i < m_Lights.size(); i++) {
+ SShadowMapEntry *pEntry = m_ShadowMapManager->GetShadowMapEntry(i);
+ if (pEntry && pEntry->m_DepthMap && pEntry->m_DepthCopy && pEntry->m_DepthRender) {
+ SCamera theCamera;
+
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ SetupCameraForShadowMap(theCameraProps, m_Renderer.GetContext(), *m_Camera,
+ m_Lights[i], theCamera);
+ // we need this matrix for the final rendering
+ theCamera.CalculateViewProjectionMatrix(pEntry->m_LightVP);
+ pEntry->m_LightView = theCamera.m_GlobalTransform.getInverse();
+
+ STextureDetails theDetails(pEntry->m_DepthMap->GetTextureDetails());
+ theRenderContext.SetViewport(
+ NVRenderRect(0, 0, (QT3DSU32)theDetails.m_Width, (QT3DSU32)theDetails.m_Height));
+
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::Color0, *pEntry->m_DepthMap);
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ *pEntry->m_DepthRender);
+ theRenderContext.Clear(clearFlags);
+
+ RunRenderPass(RenderRenderableShadowMapPass, false, true, true, i, theCamera);
+ RenderShadowMapBlurPass(theFB, pEntry->m_DepthMap, pEntry->m_DepthCopy,
+ m_Lights[i]->m_ShadowFilter, m_Lights[i]->m_ShadowMapFar);
+ } else if (pEntry && pEntry->m_DepthCube && pEntry->m_CubeCopy
+ && pEntry->m_DepthRender) {
+ SCamera theCameras[6];
+
+ SetupCubeShadowCameras(m_Lights[i], theCameras);
+
+ // pEntry->m_LightView = m_Lights[i]->m_LightType == RenderLightTypes::Point ?
+ // QT3DSMat44::createIdentity()
+ // : m_Lights[i]->m_GlobalTransform;
+ pEntry->m_LightView = QT3DSMat44::createIdentity();
+
+ STextureDetails theDetails(pEntry->m_DepthCube->GetTextureDetails());
+ theRenderContext.SetViewport(
+ NVRenderRect(0, 0, (QT3DSU32)theDetails.m_Width, (QT3DSU32)theDetails.m_Height));
+
+ // int passes = m_Lights[i]->m_LightType == RenderLightTypes::Point ? 6 : 5;
+ int passes = 6;
+ for (int k = 0; k < passes; ++k) {
+ // theCameras[k].CalculateViewProjectionMatrix( pEntry->m_LightCubeVP[k] );
+ pEntry->m_LightCubeView[k] = theCameras[k].m_GlobalTransform.getInverse();
+ theCameras[k].CalculateViewProjectionMatrix(pEntry->m_LightVP);
+
+ // Geometry shader multiplication really doesn't work unless you have a
+ // 6-layered 3D depth texture...
+ // Otherwise, you have no way to depth test while rendering...
+ // which more or less completely defeats the purpose of having a cubemap render
+ // target.
+ NVRenderTextureCubeFaces::Enum curFace =
+ (NVRenderTextureCubeFaces::Enum)(k + 1);
+ //(*theFB)->AttachFace( NVRenderFrameBufferAttachments::DepthStencil,
+ //*pEntry->m_DepthCube, curFace );
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ *pEntry->m_DepthRender);
+ (*theFB)->AttachFace(NVRenderFrameBufferAttachments::Color0,
+ *pEntry->m_DepthCube, curFace);
+ theRenderContext.Clear(clearFlags);
+ RunRenderPass(RenderRenderableShadowMapPass, false, true, true, i,
+ theCameras[k]);
+ }
+
+ RenderShadowCubeBlurPass(theFB, pEntry->m_DepthCube, pEntry->m_CubeCopy,
+ m_Lights[i]->m_ShadowFilter, m_Lights[i]->m_ShadowMapFar);
+ }
+ }
+
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+ (*theFB)->Attach(NVRenderFrameBufferAttachments::Color0, NVRenderTextureOrRenderBuffer());
+
+ // enable color writes
+ theRenderContext.SetColorWritesEnabled(true);
+ theRenderContext.SetCullingEnabled(true);
+ theRenderContext.SetClearColor(QT3DSVec4(0.0f));
+ // reset rasterizer state
+ theRenderContext.SetRasterizerState(rsdefaultstate);
+
+ m_Renderer.EndLayerDepthPassRender();
+ }
+
+ inline void RenderRenderableDepthPass(SLayerRenderData &inData, SRenderableObject &inObject,
+ const QT3DSVec2 &inCameraProps, TShaderFeatureSet, QT3DSU32,
+ const SCamera &inCamera)
+ {
+ if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ static_cast<SSubsetRenderable &>(inObject).RenderDepthPass(inCameraProps);
+ else if (inObject.m_RenderableFlags.IsText())
+ static_cast<STextRenderable &>(inObject).RenderDepthPass(inCameraProps);
+ else if (inObject.m_RenderableFlags.IsCustomMaterialMeshSubset()) {
+ static_cast<SCustomMaterialRenderable &>(inObject).RenderDepthPass(
+ inCameraProps, inData.m_Layer, inData.m_Lights, inCamera, NULL);
+ } else if (inObject.m_RenderableFlags.IsPath()) {
+ static_cast<SPathRenderable &>(inObject).RenderDepthPass(
+ inCameraProps, inData.m_Layer, inData.m_Lights, inCamera, NULL);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void SLayerRenderData::RenderDepthPass(bool inEnableTransparentDepthWrite)
+ {
+ SStackPerfTimer ___timer(m_Renderer.GetUICContext().GetPerfTimer(),
+ "SLayerRenderData::RenderDepthPass");
+ if (m_Camera == NULL)
+ return;
+
+ // Avoid running this method if possible.
+ if ((inEnableTransparentDepthWrite == false
+ && (m_OpaqueObjects.size() == 0
+ || m_Layer.m_Flags.IsLayerEnableDepthPrepass() == false))
+ || m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ return;
+
+ m_Renderer.BeginLayerDepthPassRender(*this);
+
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+
+ // disable color writes
+ theRenderContext.SetColorWritesEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(true);
+
+ qt3ds::render::NVRenderClearFlags clearFlags(qt3ds::render::NVRenderClearValues::Stencil
+ | qt3ds::render::NVRenderClearValues::Depth);
+
+ theRenderContext.Clear(clearFlags);
+
+ RunRenderPass(RenderRenderableDepthPass, false, true, inEnableTransparentDepthWrite, 0,
+ *m_Camera);
+
+ // enable color writes
+ theRenderContext.SetColorWritesEnabled(true);
+
+ m_Renderer.EndLayerDepthPassRender();
+ }
+
+ inline void RenderRenderable(SLayerRenderData &inData, SRenderableObject &inObject,
+ const QT3DSVec2 &inCameraProps, TShaderFeatureSet inFeatureSet, QT3DSU32,
+ const SCamera &inCamera)
+ {
+ if (inObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ static_cast<SSubsetRenderable &>(inObject).Render(inCameraProps, inFeatureSet);
+ else if (inObject.m_RenderableFlags.IsText())
+ static_cast<STextRenderable &>(inObject).Render(inCameraProps);
+ else if (inObject.m_RenderableFlags.IsCustomMaterialMeshSubset()) {
+ // PKC : Need a better place to do this.
+ SCustomMaterialRenderable &theObject =
+ static_cast<SCustomMaterialRenderable &>(inObject);
+ if (!inData.m_Layer.m_LightProbe && theObject.m_Material.m_IblProbe)
+ inData.SetShaderFeature("UIC_ENABLE_LIGHT_PROBE",
+ theObject.m_Material.m_IblProbe->m_TextureData.m_Texture
+ != NULL);
+ else if (inData.m_Layer.m_LightProbe)
+ inData.SetShaderFeature("UIC_ENABLE_LIGHT_PROBE",
+ inData.m_Layer.m_LightProbe->m_TextureData.m_Texture
+ != NULL);
+
+ static_cast<SCustomMaterialRenderable &>(inObject).Render(
+ inCameraProps, inData, inData.m_Layer, inData.m_Lights, inCamera,
+ inData.m_LayerDepthTexture, inData.m_LayerSsaoTexture, inFeatureSet);
+ } else if (inObject.m_RenderableFlags.IsPath()) {
+ static_cast<SPathRenderable &>(inObject).Render(
+ inCameraProps, inData.m_Layer, inData.m_Lights, inCamera,
+ inData.m_LayerDepthTexture, inData.m_LayerSsaoTexture, inFeatureSet);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+ {
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
+ theRenderContext.SetBlendingEnabled(false);
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ NVDataRef<SRenderableObject *> theOpaqueObjects = GetOpaqueRenderableObjects();
+ bool usingDepthBuffer =
+ m_Layer.m_Flags.IsLayerEnableDepthTest() && theOpaqueObjects.size() > 0;
+
+ if (usingDepthBuffer) {
+ theRenderContext.SetDepthTestEnabled(true);
+ theRenderContext.SetDepthWriteEnabled(inEnableDepthWrite);
+ } else {
+ theRenderContext.SetDepthWriteEnabled(false);
+ theRenderContext.SetDepthTestEnabled(false);
+ }
+
+ for (QT3DSU32 idx = 0, end = theOpaqueObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theOpaqueObjects[idx]);
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ }
+
+ // transparent objects
+ if (inEnableBlending || m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
+ theRenderContext.SetBlendingEnabled(true && inEnableBlending);
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+
+ NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
+ // Assume all objects have transparency if the layer's depth test enabled flag is true.
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() == true) {
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // SW fallback for advanced blend modes.
+ // Renders transparent objects to a separate FBO and blends them in shader
+ // with the opaque items and background.
+ DefaultMaterialBlendMode::Enum blendMode
+ = DefaultMaterialBlendMode::Enum::Normal;
+ if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
+ bool useBlendFallback = (blendMode == DefaultMaterialBlendMode::Overlay ||
+ blendMode == DefaultMaterialBlendMode::ColorBurn ||
+ blendMode == DefaultMaterialBlendMode::ColorDodge) &&
+ !theRenderContext.IsAdvancedBlendHwSupported() &&
+ !theRenderContext.IsAdvancedBlendHwSupportedKHR() &&
+ m_LayerPrepassDepthTexture;
+ if (useBlendFallback)
+ SetupDrawFB(true);
+#endif
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections,
+ m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
+ indexLight, inCamera);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // SW fallback for advanced blend modes.
+ // Continue blending after transparent objects have been rendered to a FBO
+ if (useBlendFallback) {
+ BlendAdvancedToFB(blendMode, true, theFB);
+ // restore blending status
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
+ // restore depth test status
+ theRenderContext.SetDepthTestEnabled(usingDepthBuffer);
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+ }
+#endif
+ }
+ }
+ }
+ // If the layer doesn't have depth enabled then we have to render via an alternate route
+ // where the transparent objects vector could have both opaque and transparent objects.
+ else {
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ DefaultMaterialBlendMode::Enum blendMode
+ = DefaultMaterialBlendMode::Enum::Normal;
+ if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
+ bool useBlendFallback = (blendMode == DefaultMaterialBlendMode::Overlay ||
+ blendMode == DefaultMaterialBlendMode::ColorBurn ||
+ blendMode == DefaultMaterialBlendMode::ColorDodge) &&
+ !theRenderContext.IsAdvancedBlendHwSupported() &&
+ !theRenderContext.IsAdvancedBlendHwSupportedKHR();
+
+ if (theObject.m_RenderableFlags.HasTransparency()) {
+ theRenderContext.SetBlendingEnabled(true && inEnableBlending);
+ // If we have SW fallback for blend mode, render to a FBO and blend back.
+ // Slow as this must be done per-object (transparent and opaque items
+ // are mixed, not batched)
+ if (useBlendFallback)
+ SetupDrawFB(false);
+ }
+#endif
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections,
+ m_SourceLightDirections,
+ theObject.m_ScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
+ indexLight, inCamera);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ if (useBlendFallback) {
+ BlendAdvancedToFB(blendMode, false, theFB);
+ // restore blending status
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
+
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+
+ void SLayerRenderData::Render(CResourceFrameBuffer *theFB)
+ {
+ SStackPerfTimer ___timer(m_Renderer.GetUICContext().GetPerfTimer(),
+ "SLayerRenderData::Render");
+ if (m_Camera == NULL)
+ return;
+
+ m_Renderer.BeginLayerRender(*this);
+ RunRenderPass(RenderRenderable, true, !m_Layer.m_Flags.IsLayerEnableDepthPrepass(), false,
+ 0, *m_Camera, theFB);
+ m_Renderer.EndLayerRender();
+ }
+
+ void SLayerRenderData::CreateGpuProfiler()
+ {
+ if (m_Renderer.GetContext().IsTimerQuerySupported()) {
+ m_LayerProfilerGpu = IRenderProfiler::CreateGpuProfiler(
+ m_Renderer.GetContext().GetFoundation(), m_Renderer.GetUICContext(),
+ m_Renderer.GetContext());
+ }
+ }
+
+ void SLayerRenderData::StartProfiling(CRegisteredString &nameID, bool sync)
+ {
+ if (m_LayerProfilerGpu.mPtr) {
+ m_LayerProfilerGpu->StartTimer(nameID, false, sync);
+ }
+ }
+
+ void SLayerRenderData::EndProfiling(CRegisteredString &nameID)
+ {
+ if (m_LayerProfilerGpu.mPtr) {
+ m_LayerProfilerGpu->EndTimer(nameID);
+ }
+ }
+
+ void SLayerRenderData::StartProfiling(const char *nameID, bool sync)
+ {
+ if (m_LayerProfilerGpu.mPtr) {
+ CRegisteredString theStr(
+ m_Renderer.GetUICContext().GetStringTable().RegisterStr(nameID));
+ m_LayerProfilerGpu->StartTimer(theStr, false, sync);
+ }
+ }
+
+ void SLayerRenderData::EndProfiling(const char *nameID)
+ {
+ if (m_LayerProfilerGpu.mPtr) {
+ CRegisteredString theStr(
+ m_Renderer.GetUICContext().GetStringTable().RegisterStr(nameID));
+ m_LayerProfilerGpu->EndTimer(theStr);
+ }
+ }
+
+ void SLayerRenderData::AddVertexCount(QT3DSU32 count)
+ {
+ if (m_LayerProfilerGpu.mPtr) {
+ m_LayerProfilerGpu->AddVertexCount(count);
+ }
+ }
+
+ // Assumes the viewport is setup appropriately to render the widget.
+ void SLayerRenderData::RenderRenderWidgets()
+ {
+ if (m_Camera) {
+ NVRenderContext &theContext(m_Renderer.GetContext());
+ for (QT3DSU32 idx = 0, end = m_IRenderWidgets.size(); idx < end; ++idx) {
+ IRenderWidget &theWidget = *m_IRenderWidgets[idx];
+ theWidget.Render(m_Renderer, theContext);
+ }
+ }
+ }
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ void SLayerRenderData::BlendAdvancedEquationSwFallback(NVRenderTexture2D *drawTexture,
+ NVRenderTexture2D *layerTexture,
+ AdvancedBlendModes::Enum blendMode)
+ {
+ NVRenderContext &theContext(m_Renderer.GetContext());
+ SAdvancedModeBlendShader *shader = m_Renderer.GetAdvancedBlendModeShader(blendMode);
+ if (shader == NULL)
+ return;
+
+ theContext.SetActiveShader(&(shader->m_Shader));
+
+ shader->m_baseLayer.Set(layerTexture);
+ shader->m_blendLayer.Set(drawTexture);
+ // Draw a fullscreen quad
+ m_Renderer.RenderQuad();
+ }
+
+ void SLayerRenderData::SetupDrawFB(bool depthEnabled)
+ {
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ // create drawing FBO and texture, if not existing
+ if (!m_AdvancedModeDrawFB)
+ m_AdvancedModeDrawFB = theRenderContext.CreateFrameBuffer();
+ if (!m_AdvancedBlendDrawTexture) {
+ m_AdvancedBlendDrawTexture = theRenderContext.CreateTexture2D();
+ NVRenderRect theViewport = m_Renderer.GetUICContext().GetRenderList().GetViewport();
+ m_AdvancedBlendDrawTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0,
+ theViewport.m_Width,
+ theViewport.m_Height,
+ NVRenderTextureFormats::RGBA8);
+ m_AdvancedModeDrawFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ *m_AdvancedBlendDrawTexture);
+ // Use existing depth prepass information when rendering transparent objects to a FBO
+ if (depthEnabled)
+ m_AdvancedModeDrawFB->Attach(NVRenderFrameBufferAttachments::Depth,
+ *m_LayerPrepassDepthTexture);
+ }
+ theRenderContext.SetRenderTarget(m_AdvancedModeDrawFB);
+ // make sure that depth testing is on in order to render just the
+ // depth-passed objects (=transparent objects) and leave background intact
+ if (depthEnabled)
+ theRenderContext.SetDepthTestEnabled(true);
+ theRenderContext.SetBlendingEnabled(false);
+ // clear color commonly is the layer background, make sure that it is all-zero here
+ QT3DSVec4 originalClrColor = theRenderContext.GetClearColor();
+ theRenderContext.SetClearColor(QT3DSVec4(0.0));
+ theRenderContext.Clear(NVRenderClearValues::Color);
+ theRenderContext.SetClearColor(originalClrColor);
+
+ }
+ void SLayerRenderData::BlendAdvancedToFB(DefaultMaterialBlendMode::Enum blendMode,
+ bool depthEnabled, CResourceFrameBuffer *theFB)
+ {
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ NVRenderRect theViewport = m_Renderer.GetUICContext().GetRenderList().GetViewport();
+ AdvancedBlendModes::Enum advancedMode;
+
+ switch (blendMode) {
+ case DefaultMaterialBlendMode::Overlay:
+ advancedMode = AdvancedBlendModes::Overlay;
+ break;
+ case DefaultMaterialBlendMode::ColorBurn:
+ advancedMode = AdvancedBlendModes::ColorBurn;
+ break;
+ case DefaultMaterialBlendMode::ColorDodge:
+ advancedMode = AdvancedBlendModes::ColorDodge;
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ // create blending FBO and texture if not existing
+ if (!m_AdvancedModeBlendFB)
+ m_AdvancedModeBlendFB = theRenderContext.CreateFrameBuffer();
+ if (!m_AdvancedBlendBlendTexture) {
+ m_AdvancedBlendBlendTexture = theRenderContext.CreateTexture2D();
+ m_AdvancedBlendBlendTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0,
+ theViewport.m_Width,
+ theViewport.m_Height,
+ NVRenderTextureFormats::RGBA8);
+ m_AdvancedModeBlendFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ *m_AdvancedBlendBlendTexture);
+ }
+ theRenderContext.SetRenderTarget(m_AdvancedModeBlendFB);
+
+ // Blend transparent objects with SW fallback shaders.
+ // Disable depth testing as transparent objects have already been
+ // depth-checked; here we want to run shader for all layer pixels
+ if (depthEnabled)
+ {
+ theRenderContext.SetDepthTestEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(false);
+ }
+ BlendAdvancedEquationSwFallback(m_AdvancedBlendDrawTexture, m_LayerTexture, advancedMode);
+ theRenderContext.SetRenderTarget(*theFB);
+ // setup read target
+ theRenderContext.SetReadTarget(m_AdvancedModeBlendFB);
+ theRenderContext.SetReadBuffer(NVReadFaces::Color0);
+ theRenderContext.BlitFramebuffer(0, 0, theViewport.m_Width, theViewport.m_Height,
+ 0, 0, theViewport.m_Width, theViewport.m_Height,
+ NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+ }
+#endif
+
+ void SLayerRenderData::RenderToViewport()
+ {
+ if (m_LayerPrepResult->IsLayerVisible()) {
+ if (GetOffscreenRenderer()) {
+ m_LastFrameOffscreenRenderer->Render(
+ CreateOffscreenRenderEnvironment(), m_Renderer.GetContext(),
+ m_Renderer.GetUICContext().GetPresentationScaleFactor(),
+ SScene::ClearIsOptional);
+ } else {
+ RenderDepthPass(false);
+ Render();
+ RenderRenderWidgets();
+ }
+ }
+ }
+ // These are meant to be pixel offsets, so you need to divide them by the width/height
+ // of the layer respectively.
+ const QT3DSVec2 s_VertexOffsets[SLayerRenderPreparationData::MAX_AA_LEVELS] = {
+ QT3DSVec2(-0.170840f, -0.553840f), // 1x
+ QT3DSVec2(0.162960f, -0.319340f), // 2x
+ QT3DSVec2(0.360260f, -0.245840f), // 3x
+ QT3DSVec2(-0.561340f, -0.149540f), // 4x
+ QT3DSVec2(0.249460f, 0.453460f), // 5x
+ QT3DSVec2(-0.336340f, 0.378260f), // 6x
+ QT3DSVec2(0.340000f, 0.166260f), // 7x
+ QT3DSVec2(0.235760f, 0.527760f), // 8x
+ };
+
+ // Blend factors are in the form of (frame blend factor, accumulator blend factor)
+ const QT3DSVec2 s_BlendFactors[SLayerRenderPreparationData::MAX_AA_LEVELS] = {
+ QT3DSVec2(0.500000f, 0.500000f), // 1x
+ QT3DSVec2(0.333333f, 0.666667f), // 2x
+ QT3DSVec2(0.250000f, 0.750000f), // 3x
+ QT3DSVec2(0.200000f, 0.800000f), // 4x
+ QT3DSVec2(0.166667f, 0.833333f), // 5x
+ QT3DSVec2(0.142857f, 0.857143f), // 6x
+ QT3DSVec2(0.125000f, 0.875000f), // 7x
+ QT3DSVec2(0.111111f, 0.888889f), // 8x
+ };
+
+ const QT3DSVec2 s_TemporalVertexOffsets[SLayerRenderPreparationData::MAX_TEMPORAL_AA_LEVELS] = {
+ QT3DSVec2(.3f, .3f), QT3DSVec2(-.3f, -.3f)
+ };
+
+ static inline void OffsetProjectionMatrix(QT3DSMat44 &inProjectionMatrix, QT3DSVec2 inVertexOffsets)
+ {
+ inProjectionMatrix.column3.x =
+ inProjectionMatrix.column3.x + inProjectionMatrix.column3.w * inVertexOffsets.x;
+ inProjectionMatrix.column3.y =
+ inProjectionMatrix.column3.y + inProjectionMatrix.column3.w * inVertexOffsets.y;
+ }
+
+ CRegisteredString depthPassStr;
+
+ // Render this layer's data to a texture. Required if we have any effects,
+ // prog AA, or if forced.
+ void SLayerRenderData::RenderToTexture()
+ {
+ QT3DS_ASSERT(m_LayerPrepResult->m_Flags.ShouldRenderToTexture());
+ SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ SWindowDimensions theLayerTextureDimensions = thePrepResult.GetTextureDimensions();
+ SWindowDimensions theLayerOriginalTextureDimensions = theLayerTextureDimensions;
+ NVRenderTextureFormats::Enum DepthTextureFormat = NVRenderTextureFormats::Depth24Stencil8;
+ NVRenderTextureFormats::Enum ColorTextureFormat = NVRenderTextureFormats::RGBA8;
+ if (thePrepResult.m_LastEffect) {
+ if (m_Layer.m_Background != LayerBackground::Transparent)
+ ColorTextureFormat = NVRenderTextureFormats::R11G11B10;
+ else
+ ColorTextureFormat = NVRenderTextureFormats::RGBA16F;
+ }
+ NVRenderTextureFormats::Enum ColorSSAOTextureFormat = NVRenderTextureFormats::RGBA8;
+
+ bool needsRender = false;
+ QT3DSU32 sampleCount = 1;
+ // check multsample mode and MSAA texture support
+ if (m_Layer.m_MultisampleAAMode != AAModeValues::NoAA
+ && theRenderContext.AreMultisampleTexturesSupported())
+ sampleCount = (QT3DSU32)m_Layer.m_MultisampleAAMode;
+
+ bool isMultisamplePass =
+ (sampleCount > 1) || (m_Layer.m_MultisampleAAMode == AAModeValues::SSAA);
+
+ qt3ds::render::NVRenderTextureTargetType::Enum thFboAttachTarget =
+ qt3ds::render::NVRenderTextureTargetType::Texture2D;
+
+ // If the user has disabled all layer caching this has the side effect of disabling the
+ // progressive AA algorithm.
+ if (thePrepResult.m_Flags.WasLayerDataDirty()
+ || thePrepResult.m_Flags.WasDirty()
+ || m_Renderer.IsLayerCachingEnabled() == false) {
+ m_ProgressiveAAPassIndex = 0;
+ m_NonDirtyTemporalAAPassIndex = 0;
+ needsRender = true;
+ }
+
+ CResourceTexture2D *renderColorTexture = &m_LayerTexture;
+ CResourceTexture2D *renderPrepassDepthTexture = &m_LayerPrepassDepthTexture;
+ CResourceTexture2D *renderWidgetTexture = &m_LayerWidgetTexture;
+ NVRenderContextScopedProperty<bool> __multisampleEnabled(
+ theRenderContext, &NVRenderContext::IsMultisampleEnabled,
+ &NVRenderContext::SetMultisampleEnabled);
+ theRenderContext.SetMultisampleEnabled(false);
+ if (isMultisamplePass) {
+ renderColorTexture = &m_LayerMultisampleTexture;
+ renderPrepassDepthTexture = &m_LayerMultisamplePrepassDepthTexture;
+ renderWidgetTexture = &m_LayerMultisampleWidgetTexture;
+ // for SSAA we don't use MS textures
+ if (m_Layer.m_MultisampleAAMode != AAModeValues::SSAA)
+ thFboAttachTarget = qt3ds::render::NVRenderTextureTargetType::Texture2D_MS;
+ }
+ QT3DSU32 maxTemporalPassIndex = m_Layer.m_TemporalAAEnabled ? 2 : 0;
+
+ // If all the dimensions match then we do not have to re-render the layer.
+ if (m_LayerTexture.TextureMatches(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height, ColorTextureFormat)
+ && (!thePrepResult.m_Flags.RequiresDepthTexture()
+ || m_LayerDepthTexture.TextureMatches(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height,
+ DepthTextureFormat))
+ && m_ProgressiveAAPassIndex >= thePrepResult.m_MaxAAPassIndex
+ && m_NonDirtyTemporalAAPassIndex >= maxTemporalPassIndex && needsRender == false) {
+ return;
+ }
+
+ // adjust render size for SSAA
+ if (m_Layer.m_MultisampleAAMode == AAModeValues::SSAA) {
+ CRendererUtil::GetSSAARenderSize(theLayerOriginalTextureDimensions.m_Width,
+ theLayerOriginalTextureDimensions.m_Height,
+ theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height);
+ }
+
+ // If our pass index == thePreResult.m_MaxAAPassIndex then
+ // we shouldn't get into here.
+
+ IResourceManager &theResourceManager = m_Renderer.GetUICContext().GetResourceManager();
+ bool hadLayerTexture = true;
+
+ if (renderColorTexture->EnsureTexture(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height,
+ ColorTextureFormat, sampleCount)) {
+ m_ProgressiveAAPassIndex = 0;
+ m_NonDirtyTemporalAAPassIndex = 0;
+ hadLayerTexture = false;
+ }
+
+ if (thePrepResult.m_Flags.RequiresDepthTexture()) {
+ // The depth texture doesn't need to be multisample, the prepass depth does.
+ if (m_LayerDepthTexture.EnsureTexture(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height,
+ DepthTextureFormat)) {
+ // Depth textures are generally not bilinear filtered.
+ m_LayerDepthTexture->SetMinFilter(NVRenderTextureMinifyingOp::Nearest);
+ m_LayerDepthTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Nearest);
+ m_ProgressiveAAPassIndex = 0;
+ m_NonDirtyTemporalAAPassIndex = 0;
+ }
+ }
+
+ if (thePrepResult.m_Flags.RequiresSsaoPass()) {
+ if (m_LayerSsaoTexture.EnsureTexture(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height,
+ ColorSSAOTextureFormat)) {
+ m_LayerSsaoTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ m_LayerSsaoTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ m_ProgressiveAAPassIndex = 0;
+ m_NonDirtyTemporalAAPassIndex = 0;
+ }
+ }
+
+ QT3DS_ASSERT(!thePrepResult.m_Flags.RequiresDepthTexture() || m_LayerDepthTexture);
+ QT3DS_ASSERT(!thePrepResult.m_Flags.RequiresSsaoPass() || m_LayerSsaoTexture);
+
+ CResourceTexture2D theLastLayerTexture(theResourceManager);
+ SLayerProgAABlendShader *theBlendShader = NULL;
+ QT3DSU32 aaFactorIndex = 0;
+ bool isProgressiveAABlendPass =
+ m_ProgressiveAAPassIndex && m_ProgressiveAAPassIndex < thePrepResult.m_MaxAAPassIndex;
+ bool isTemporalAABlendPass = m_Layer.m_TemporalAAEnabled && m_ProgressiveAAPassIndex == 0;
+
+ if (isProgressiveAABlendPass || isTemporalAABlendPass) {
+ theBlendShader = m_Renderer.GetLayerProgAABlendShader();
+ if (theBlendShader) {
+ m_LayerTexture.EnsureTexture(theLayerOriginalTextureDimensions.m_Width,
+ theLayerOriginalTextureDimensions.m_Height,
+ ColorTextureFormat);
+ QT3DSVec2 theVertexOffsets;
+ if (isProgressiveAABlendPass) {
+ theLastLayerTexture.StealTexture(m_LayerTexture);
+ aaFactorIndex = (m_ProgressiveAAPassIndex - 1);
+ theVertexOffsets = s_VertexOffsets[aaFactorIndex];
+ } else {
+ if (m_TemporalAATexture.GetTexture())
+ theLastLayerTexture.StealTexture(m_TemporalAATexture);
+ else {
+ if (hadLayerTexture) {
+ theLastLayerTexture.StealTexture(m_LayerTexture);
+ }
+ }
+ theVertexOffsets = s_TemporalVertexOffsets[m_TemporalAAPassIndex];
+ ++m_TemporalAAPassIndex;
+ ++m_NonDirtyTemporalAAPassIndex;
+ m_TemporalAAPassIndex = m_TemporalAAPassIndex % MAX_TEMPORAL_AA_LEVELS;
+ }
+ if (theLastLayerTexture.GetTexture()) {
+ theVertexOffsets.x =
+ theVertexOffsets.x / (theLayerOriginalTextureDimensions.m_Width / 2.0f);
+ theVertexOffsets.y =
+ theVertexOffsets.y / (theLayerOriginalTextureDimensions.m_Height / 2.0f);
+ // Run through all models and update MVP.
+ // run through all texts and update MVP.
+ // run through all path and update MVP.
+
+ // TODO - optimize this exact matrix operation.
+ for (QT3DSU32 idx = 0, end = m_ModelContexts.size(); idx < end; ++idx) {
+ QT3DSMat44 &originalProjection(m_ModelContexts[idx]->m_ModelViewProjection);
+ OffsetProjectionMatrix(originalProjection, theVertexOffsets);
+ }
+ for (QT3DSU32 idx = 0, end = m_OpaqueObjects.size(); idx < end; ++idx) {
+ if (m_OpaqueObjects[idx]->m_RenderableFlags.IsPath()) {
+ SPathRenderable &theRenderable =
+ static_cast<SPathRenderable &>(*m_OpaqueObjects[idx]);
+ OffsetProjectionMatrix(theRenderable.m_ModelViewProjection,
+ theVertexOffsets);
+ }
+ }
+ for (QT3DSU32 idx = 0, end = m_TransparentObjects.size(); idx < end; ++idx) {
+ if (m_TransparentObjects[idx]->m_RenderableFlags.IsText()) {
+ STextRenderable &theRenderable =
+ static_cast<STextRenderable &>(*m_TransparentObjects[idx]);
+ OffsetProjectionMatrix(theRenderable.m_ModelViewProjection,
+ theVertexOffsets);
+ } else if (m_TransparentObjects[idx]->m_RenderableFlags.IsPath()) {
+ SPathRenderable &theRenderable =
+ static_cast<SPathRenderable &>(*m_TransparentObjects[idx]);
+ OffsetProjectionMatrix(theRenderable.m_ModelViewProjection,
+ theVertexOffsets);
+ }
+ }
+ }
+ }
+ }
+ if (theLastLayerTexture.GetTexture() == NULL) {
+ isProgressiveAABlendPass = false;
+ isTemporalAABlendPass = false;
+ }
+ // Sometimes we will have stolen the render texture.
+ renderColorTexture->EnsureTexture(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height, ColorTextureFormat,
+ sampleCount);
+
+ if (!isTemporalAABlendPass)
+ m_TemporalAATexture.ReleaseTexture();
+
+ // Allocating a frame buffer can cause it to be bound, so we need to save state before this
+ // happens.
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __framebuf(
+ theRenderContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ // Match the bit depth of the current render target to avoid popping when we switch from aa
+ // to non aa layers
+ // We have to all this here in because once we change the FB by allocating an FB we are
+ // screwed.
+ NVRenderTextureFormats::Enum theDepthFormat(GetDepthBufferFormat());
+ NVRenderFrameBufferAttachments::Enum theDepthAttachmentFormat(
+ GetFramebufferDepthAttachmentFormat(theDepthFormat));
+
+ // Definitely disable the scissor rect if it is running right now.
+ NVRenderContextScopedProperty<bool> __scissorEnabled(
+ theRenderContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled, false);
+ CResourceFrameBuffer theFB(theResourceManager);
+ // Allocates the frame buffer which has the side effect of setting the current render target
+ // to that frame buffer.
+ theFB.EnsureFrameBuffer();
+
+ bool hasDepthObjects = m_OpaqueObjects.size() > 0;
+ bool requiresDepthStencilBuffer =
+ hasDepthObjects || thePrepResult.m_Flags.RequiresStencilBuffer();
+ NVRenderRect theNewViewport(0, 0, theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height);
+ {
+ theRenderContext.SetRenderTarget(theFB);
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theRenderContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport,
+ theNewViewport);
+ QT3DSVec4 clearColor(0.0);
+ if (m_Layer.m_Background == LayerBackground::Color)
+ clearColor = QT3DSVec4(m_Layer.m_ClearColor, 1.0);
+
+ NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ theRenderContext, &NVRenderContext::GetClearColor, &NVRenderContext::SetClearColor,
+ clearColor);
+ if (requiresDepthStencilBuffer) {
+ if (renderPrepassDepthTexture->EnsureTexture(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height,
+ theDepthFormat, sampleCount)) {
+ (*renderPrepassDepthTexture)->SetMinFilter(NVRenderTextureMinifyingOp::Nearest);
+ (*renderPrepassDepthTexture)
+ ->SetMagFilter(NVRenderTextureMagnifyingOp::Nearest);
+ }
+ }
+
+ if (thePrepResult.m_Flags.RequiresDepthTexture() && m_ProgressiveAAPassIndex == 0) {
+ // Setup FBO with single depth buffer target.
+ // Note this does not use multisample.
+ NVRenderFrameBufferAttachments::Enum theAttachment =
+ GetFramebufferDepthAttachmentFormat(DepthTextureFormat);
+ theFB->Attach(theAttachment, *m_LayerDepthTexture);
+
+ // In this case transparent objects also may write their depth.
+ RenderDepthPass(true);
+ theFB->Attach(theAttachment, NVRenderTextureOrRenderBuffer());
+ }
+
+ if (thePrepResult.m_Flags.RequiresSsaoPass() && m_ProgressiveAAPassIndex == 0) {
+ StartProfiling("AO pass", false);
+ // Setup FBO with single color buffer target
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0, *m_LayerSsaoTexture);
+ theRenderContext.Clear(qt3ds::render::NVRenderClearValues::Color);
+ RenderAoPass();
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer());
+ EndProfiling("AO pass");
+ }
+
+ if (thePrepResult.m_Flags.RequiresShadowMapPass() && m_ProgressiveAAPassIndex == 0) {
+ // shadow map path
+ RenderShadowMapPass(&theFB);
+ }
+
+ if (sampleCount > 1) {
+ theRenderContext.SetMultisampleEnabled(true);
+ }
+
+ qt3ds::render::NVRenderClearFlags clearFlags = qt3ds::render::NVRenderClearValues::Color;
+
+ // render depth prepass
+ if ((*renderPrepassDepthTexture)) {
+ theFB->Attach(theDepthAttachmentFormat, **renderPrepassDepthTexture,
+ thFboAttachTarget);
+
+ if (m_Layer.m_Flags.IsLayerEnableDepthPrepass()) {
+ StartProfiling("Depth pass", false);
+ RenderDepthPass(false);
+ EndProfiling("Depth pass");
+ } else {
+ clearFlags |= (qt3ds::render::NVRenderClearValues::Depth);
+ clearFlags |= (qt3ds::render::NVRenderClearValues::Stencil);
+ // enable depth write for the clear below
+ theRenderContext.SetDepthWriteEnabled(true);
+ }
+ }
+
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0, **renderColorTexture,
+ thFboAttachTarget);
+ if (m_Layer.m_Background != LayerBackground::Unspecified)
+ theRenderContext.Clear(clearFlags);
+
+ // We don't clear the depth buffer because the layer render code we are about to call
+ // will do this.
+ StartProfiling("Render pass", false);
+ Render(&theFB);
+ // Debug measure to view the depth map to ensure we're rendering it correctly.
+ //if (m_Layer.m_TemporalAAEnabled) {
+ // RenderFakeDepthMapPass(m_ShadowMapManager->GetShadowMapEntry(0)->m_DepthMap,
+ // m_ShadowMapManager->GetShadowMapEntry(0)->m_DepthCube);
+ //}
+ EndProfiling("Render pass");
+
+ // Now before going further, we downsample and resolve the multisample information.
+ // This allows all algorithms running after
+ // this point to run unchanged.
+ if (isMultisamplePass) {
+ if (m_Layer.m_MultisampleAAMode != AAModeValues::SSAA) {
+ // Resolve the FBO to the layer texture
+ CRendererUtil::ResolveMutisampleFBOColorOnly(
+ theResourceManager, m_LayerTexture, theRenderContext,
+ theLayerTextureDimensions.m_Width, theLayerTextureDimensions.m_Height,
+ ColorTextureFormat, *theFB);
+
+ theRenderContext.SetMultisampleEnabled(false);
+ } else {
+ // Resolve the FBO to the layer texture
+ CRendererUtil::ResolveSSAAFBOColorOnly(
+ theResourceManager, m_LayerTexture,
+ theLayerOriginalTextureDimensions.m_Width,
+ theLayerOriginalTextureDimensions.m_Height, theRenderContext,
+ theLayerTextureDimensions.m_Width, theLayerTextureDimensions.m_Height,
+ ColorTextureFormat, *theFB);
+ }
+ }
+
+ // CN - when I tried to get anti-aliased widgets I lost all transparency on the widget
+ // layer which made it overwrite the object you were
+ // manipulating. When I tried to use parallel nsight on it the entire studio
+ // application crashed on startup.
+ if (NeedsWidgetTexture()) {
+ m_LayerWidgetTexture.EnsureTexture(theLayerTextureDimensions.m_Width,
+ theLayerTextureDimensions.m_Height,
+ NVRenderTextureFormats::RGBA8);
+ theRenderContext.SetRenderTarget(theFB);
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0, *m_LayerWidgetTexture);
+ theFB->Attach(GetFramebufferDepthAttachmentFormat(DepthTextureFormat),
+ *m_LayerDepthTexture);
+ theRenderContext.SetClearColor(QT3DSVec4(0.0f));
+ theRenderContext.Clear(qt3ds::render::NVRenderClearValues::Color);
+ // We should already have the viewport and everything setup for this.
+ RenderRenderWidgets();
+ }
+
+ if (theLastLayerTexture.GetTexture() != NULL
+ && (isProgressiveAABlendPass || isTemporalAABlendPass)) {
+ theRenderContext.SetViewport(
+ NVRenderRect(0, 0, theLayerOriginalTextureDimensions.m_Width,
+ theLayerOriginalTextureDimensions.m_Height));
+ CResourceTexture2D targetTexture(
+ theResourceManager, theLayerOriginalTextureDimensions.m_Width,
+ theLayerOriginalTextureDimensions.m_Height, ColorTextureFormat);
+ theFB->Attach(theDepthAttachmentFormat,
+ NVRenderTextureOrRenderBuffer());
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0, *targetTexture);
+ QT3DSVec2 theBlendFactors;
+ if (isProgressiveAABlendPass)
+ theBlendFactors = s_BlendFactors[aaFactorIndex];
+ else
+ theBlendFactors = QT3DSVec2(.5f, .5f);
+
+ theRenderContext.SetDepthTestEnabled(false);
+ theRenderContext.SetBlendingEnabled(false);
+ theRenderContext.SetCullingEnabled(false);
+ theRenderContext.SetActiveShader(theBlendShader->m_Shader);
+ theBlendShader->m_AccumSampler.Set(theLastLayerTexture);
+ theBlendShader->m_LastFrame.Set(m_LayerTexture);
+ theBlendShader->m_BlendFactors.Set(theBlendFactors);
+ m_Renderer.RenderQuad();
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ if (isTemporalAABlendPass)
+ m_TemporalAATexture.StealTexture(m_LayerTexture);
+ m_LayerTexture.StealTexture(targetTexture);
+ }
+
+ m_LayerTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ m_LayerTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+
+ // Don't remember why needs widget texture is false here.
+ // Should have commented why progAA plus widgets is a fail.
+ if (m_ProgressiveAAPassIndex < thePrepResult.m_MaxAAPassIndex
+ && NeedsWidgetTexture() == false)
+ ++m_ProgressiveAAPassIndex;
+
+// now we render all post effects
+#ifdef UIC_CACHED_POST_EFFECT
+ ApplyLayerPostEffects();
+#endif
+
+ if (m_LayerPrepassDepthTexture) {
+ // Detach any depth buffers.
+ theFB->Attach(theDepthAttachmentFormat, qt3ds::render::NVRenderTextureOrRenderBuffer(),
+ thFboAttachTarget);
+ }
+
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ qt3ds::render::NVRenderTextureOrRenderBuffer(), thFboAttachTarget);
+ // Let natural scoping rules destroy the other stuff.
+ }
+ }
+
+ void SLayerRenderData::ApplyLayerPostEffects()
+ {
+ if (m_Layer.m_FirstEffect == NULL) {
+ if (m_LayerCachedTexture) {
+ IResourceManager &theResourceManager(m_Renderer.GetUICContext().GetResourceManager());
+ theResourceManager.Release(*m_LayerCachedTexture);
+ m_LayerCachedTexture = NULL;
+ }
+ return;
+ }
+
+ IEffectSystem &theEffectSystem(m_Renderer.GetUICContext().GetEffectSystem());
+ IResourceManager &theResourceManager(m_Renderer.GetUICContext().GetResourceManager());
+ // we use the non MSAA buffer for the effect
+ NVRenderTexture2D *theLayerColorTexture = m_LayerTexture;
+ NVRenderTexture2D *theLayerDepthTexture = m_LayerDepthTexture;
+
+ NVRenderTexture2D *theCurrentTexture = theLayerColorTexture;
+ for (SEffect *theEffect = m_Layer.m_FirstEffect; theEffect;
+ theEffect = theEffect->m_NextEffect) {
+ if (theEffect->m_Flags.IsActive() && m_Camera) {
+ StartProfiling(theEffect->m_ClassName, false);
+
+ NVRenderTexture2D *theRenderedEffect = theEffectSystem.RenderEffect(
+ SEffectRenderArgument(*theEffect, *theCurrentTexture,
+ QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar),
+ theLayerDepthTexture, m_LayerPrepassDepthTexture));
+
+ EndProfiling(theEffect->m_ClassName);
+
+ // If the texture came from rendering a chain of effects, then we don't need it
+ // after this.
+ if (theCurrentTexture != theLayerColorTexture)
+ theResourceManager.Release(*theCurrentTexture);
+
+ theCurrentTexture = theRenderedEffect;
+ }
+ }
+
+ if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture) {
+ theResourceManager.Release(*m_LayerCachedTexture);
+ m_LayerCachedTexture = NULL;
+ }
+
+ if (theCurrentTexture != m_LayerTexture)
+ m_LayerCachedTexture = theCurrentTexture;
+ }
+
+ inline bool AnyCompletelyNonTransparentObjects(TRenderableObjectList &inObjects)
+ {
+ for (QT3DSU32 idx = 0, end = inObjects.size(); idx < end; ++idx) {
+ if (inObjects[idx]->m_RenderableFlags.IsCompletelyTransparent() == false)
+ return true;
+ }
+ return false;
+ }
+
+ void SLayerRenderData::RunnableRenderToViewport(qt3ds::render::NVRenderFrameBuffer *theFB)
+ {
+ // If we have an effect, an opaque object, or any transparent objects that aren't completely
+ // transparent
+ // or an offscreen renderer or a layer widget texture
+ // Then we can't possible affect the resulting render target.
+ bool needsToRender = m_Layer.m_FirstEffect != NULL || m_OpaqueObjects.empty() == false
+ || AnyCompletelyNonTransparentObjects(m_TransparentObjects) || GetOffscreenRenderer()
+ || m_LayerWidgetTexture || m_BoundingRectColor.hasValue()
+ || m_Layer.m_Background == LayerBackground::Color;
+
+ if (needsToRender == false)
+ return;
+
+ NVRenderContext &theContext(m_Renderer.GetContext());
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __fbo(
+ theContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ qt3ds::render::NVRenderRect theCurrentViewport = theContext.GetViewport();
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport);
+ NVRenderContextScopedProperty<bool> theScissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled);
+ NVRenderContextScopedProperty<qt3ds::render::NVRenderRect> theScissorRect(
+ theContext, &NVRenderContext::GetScissorRect, &NVRenderContext::SetScissorRect);
+ SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
+ NVRenderRectF theScreenRect(thePrepResult.GetLayerToPresentationViewport());
+
+ bool blendingEnabled = m_Layer.m_Background == LayerBackground::Transparent;
+ if (!thePrepResult.m_Flags.ShouldRenderToTexture()) {
+ theContext.SetViewport(
+ m_LayerPrepResult->GetLayerToPresentationViewport().ToIntegerRect());
+ theContext.SetScissorTestEnabled(true);
+ theContext.SetScissorRect(
+ m_LayerPrepResult->GetLayerToPresentationScissorRect().ToIntegerRect());
+ if (m_Layer.m_Background == LayerBackground::Color) {
+ NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ theContext, &NVRenderContext::GetClearColor, &NVRenderContext::SetClearColor,
+ QT3DSVec4(m_Layer.m_ClearColor, 0.0f));
+ theContext.Clear(NVRenderClearValues::Color);
+ }
+ RenderToViewport();
+ } else {
+// First, render the layer along with whatever progressive AA is appropriate.
+// The render graph should have taken care of the render to texture step.
+#ifdef UIC_CACHED_POST_EFFECT
+ NVRenderTexture2D *theLayerColorTexture =
+ (m_LayerCachedTexture) ? m_LayerCachedTexture : m_LayerTexture;
+#else
+ // Then render all but the last effect
+ IEffectSystem &theEffectSystem(m_Renderer.GetUICContext().GetEffectSystem());
+ IResourceManager &theResourceManager(m_Renderer.GetUICContext().GetResourceManager());
+ // we use the non MSAA buffer for the effect
+ NVRenderTexture2D *theLayerColorTexture = m_LayerTexture;
+ NVRenderTexture2D *theLayerDepthTexture = m_LayerDepthTexture;
+
+ NVRenderTexture2D *theCurrentTexture = theLayerColorTexture;
+ for (SEffect *theEffect = m_Layer.m_FirstEffect;
+ theEffect && theEffect != thePrepResult.m_LastEffect;
+ theEffect = theEffect->m_NextEffect) {
+ if (theEffect->m_Flags.IsActive() && m_Camera) {
+ StartProfiling(theEffect->m_ClassName, false);
+
+ NVRenderTexture2D *theRenderedEffect = theEffectSystem.RenderEffect(
+ SEffectRenderArgument(*theEffect, *theCurrentTexture,
+ QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar),
+ theLayerDepthTexture, m_LayerPrepassDepthTexture));
+
+ EndProfiling(theEffect->m_ClassName);
+
+ // If the texture came from rendering a chain of effects, then we don't need it
+ // after this.
+ if (theCurrentTexture != theLayerColorTexture)
+ theResourceManager.Release(*theCurrentTexture);
+
+ theCurrentTexture = theRenderedEffect;
+ }
+ }
+#endif
+ // Now the last effect or straight to the scene if we have no last effect
+ // There are two cases we need to consider here. The first is when we shouldn't
+ // transform
+ // the result and thus we need to setup an MVP that just maps to the viewport width and
+ // height.
+ // The second is when we are expected to render to the scene using some global
+ // transform.
+ QT3DSMat44 theFinalMVP(QT3DSMat44::createIdentity());
+ SCamera theTempCamera;
+ NVRenderRect theLayerViewport(
+ thePrepResult.GetLayerToPresentationViewport().ToIntegerRect());
+ NVRenderRect theLayerClip(
+ thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect());
+
+ {
+ QT3DSMat33 ignored;
+ QT3DSMat44 theViewProjection;
+ // We could cache these variables
+ theTempCamera.m_Flags.SetOrthographic(true);
+ theTempCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ // Move the camera back far enough that we can see everything
+ QT3DSF32 theCameraSetback(10);
+ // Attempt to ensure the layer can never be clipped.
+ theTempCamera.m_Position.z = -theCameraSetback;
+ theTempCamera.m_ClipFar = 2.0f * theCameraSetback;
+ // Render the layer texture to the entire viewport.
+ SCameraGlobalCalculationResult theResult = theTempCamera.CalculateGlobalVariables(
+ theLayerViewport,
+ QT3DSVec2((QT3DSF32)theLayerViewport.m_Width, (QT3DSF32)theLayerViewport.m_Height));
+ theTempCamera.CalculateViewProjectionMatrix(theViewProjection);
+ SNode theTempNode;
+ theFinalMVP = theViewProjection;
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc;
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu;
+
+ switch (m_Layer.m_BlendType) {
+ case LayerBlendTypes::Screen:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::SrcAlpha, NVRenderDstBlendFunc::One,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add);
+ break;
+ case LayerBlendTypes::Multiply:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::DstColor, NVRenderDstBlendFunc::Zero,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add);
+ break;
+ case LayerBlendTypes::Add:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add);
+ break;
+ case LayerBlendTypes::Subtract:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::ReverseSubtract,
+ NVRenderBlendEquation::ReverseSubtract);
+ break;
+ case LayerBlendTypes::Overlay:
+ // SW fallback doesn't use blend equation
+ // note blend func is not used here anymore
+ if (theContext.IsAdvancedBlendHwSupported() ||
+ theContext.IsAdvancedBlendHwSupportedKHR())
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Overlay, NVRenderBlendEquation::Overlay);
+ break;
+ case LayerBlendTypes::ColorBurn:
+ // SW fallback doesn't use blend equation
+ // note blend func is not used here anymore
+ if (theContext.IsAdvancedBlendHwSupported() ||
+ theContext.IsAdvancedBlendHwSupportedKHR())
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::ColorBurn, NVRenderBlendEquation::ColorBurn);
+ break;
+ case LayerBlendTypes::ColorDodge:
+ // SW fallback doesn't use blend equation
+ // note blend func is not used here anymore
+ if (theContext.IsAdvancedBlendHwSupported() ||
+ theContext.IsAdvancedBlendHwSupportedKHR())
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::ColorDodge, NVRenderBlendEquation::ColorDodge);
+ break;
+ default:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha);
+ blendEqu = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add);
+ break;
+ }
+ theContext.SetBlendFunction(blendFunc);
+ theContext.SetBlendEquation(blendEqu);
+ theContext.SetBlendingEnabled(blendingEnabled);
+ theContext.SetDepthTestEnabled(false);
+ }
+
+ {
+ theContext.SetScissorTestEnabled(true);
+ theContext.SetViewport(theLayerViewport);
+ theContext.SetScissorRect(theLayerClip);
+
+ // Remember the camera we used so we can get a valid pick ray
+ m_SceneCamera = theTempCamera;
+ theContext.SetDepthTestEnabled(false);
+#ifndef UIC_CACHED_POST_EFFECT
+ if (thePrepResult.m_LastEffect && m_Camera) {
+ StartProfiling(thePrepResult.m_LastEffect->m_ClassName, false);
+ // inUseLayerMPV is true then we are rendering directly to the scene and thus we
+ // should enable blending
+ // for the final render pass. Else we should leave it.
+ theEffectSystem.RenderEffect(
+ SEffectRenderArgument(*thePrepResult.m_LastEffect, *theCurrentTexture,
+ QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar),
+ theLayerDepthTexture, m_LayerPrepassDepthTexture),
+ theFinalMVP, blendingEnabled);
+ EndProfiling(thePrepResult.m_LastEffect->m_ClassName);
+ // If the texture came from rendering a chain of effects, then we don't need it
+ // after this.
+ if (theCurrentTexture != theLayerColorTexture)
+ theResourceManager.Release(*theCurrentTexture);
+ } else
+#endif
+ {
+ theContext.SetCullingEnabled(false);
+ theContext.SetBlendingEnabled(blendingEnabled);
+ theContext.SetDepthTestEnabled(false);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ NVScopedRefCounted<NVRenderTexture2D> layerBlendTexture =
+ m_Renderer.GetLayerBlendTexture();
+ NVScopedRefCounted<NVRenderFrameBuffer> blendFB = m_Renderer.GetBlendFB();
+
+ // Layer blending for advanced blending modes if SW fallback is needed
+ // rendering to FBO and blending with separate shader
+ if (layerBlendTexture) {
+ // Blending is enabled only if layer background has been chosen transparent
+ // Layers with advanced blending modes
+ if (blendingEnabled && (m_Layer.m_BlendType == LayerBlendTypes::Overlay ||
+ m_Layer.m_BlendType == LayerBlendTypes::ColorBurn ||
+ m_Layer.m_BlendType == LayerBlendTypes::ColorDodge)) {
+ // Set up for rendering to texture
+ theContext.SetScissorTestEnabled(false);
+ theContext.SetBlendingEnabled(false);
+ theContext.SetViewport(NVRenderRect(0, 0, theCurrentViewport.m_Width,
+ theCurrentViewport.m_Height));
+ qt3ds::render::NVRenderTexture2D *blendResultTexture;
+ blendResultTexture = theContext.CreateTexture2D();
+ blendResultTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0,
+ theCurrentViewport.m_Width,
+ theCurrentViewport.m_Height,
+ NVRenderTextureFormats::RGBA8);
+ blendFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*blendResultTexture));
+ theContext.SetRenderTarget(blendFB);
+
+ AdvancedBlendModes::Enum advancedMode;
+ switch (m_Layer.m_BlendType) {
+ case LayerBlendTypes::Overlay:
+ advancedMode = AdvancedBlendModes::Overlay;
+ break;
+ case LayerBlendTypes::ColorBurn:
+ advancedMode = AdvancedBlendModes::ColorBurn;
+ break;
+ case LayerBlendTypes::ColorDodge:
+ advancedMode = AdvancedBlendModes::ColorDodge;
+ break;
+ default:
+ advancedMode = AdvancedBlendModes::None;
+ break;
+ }
+ BlendAdvancedEquationSwFallback(theLayerColorTexture, layerBlendTexture,
+ advancedMode);
+ // save blending result for use with other layers
+ qt3ds::render::NVRenderFrameBuffer *drawFB;
+ drawFB = theContext.CreateFrameBuffer();
+ drawFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*layerBlendTexture));
+ theContext.SetRenderTarget(drawFB);
+ theContext.SetReadTarget(blendFB);
+ theContext.SetReadBuffer(NVReadFaces::Color0);
+ theContext.BlitFramebuffer(0, 0, theCurrentViewport.m_Width,
+ theCurrentViewport.m_Height, 0, 0,
+ theCurrentViewport.m_Width,
+ theCurrentViewport.m_Height,
+ NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+ // render the blended result
+ theContext.SetRenderTarget(theFB);
+ theContext.SetScissorTestEnabled(true);
+ theContext.SetViewport(theCurrentViewport);
+ m_Renderer.RenderQuad(QT3DSVec2((QT3DSF32)theCurrentViewport.m_Width,
+ (QT3DSF32)theCurrentViewport.m_Height),
+ theFinalMVP, *layerBlendTexture);
+ blendFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*layerBlendTexture));
+ drawFB->release();
+ } else {
+ // Layers with normal blending modes
+ // save result for future use
+ theContext.SetViewport(NVRenderRect(0, 0, theCurrentViewport.m_Width,
+ theCurrentViewport.m_Height));
+ theContext.SetScissorTestEnabled(false);
+ blendFB->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*layerBlendTexture));
+ theContext.SetRenderTarget(blendFB);
+ m_Renderer.RenderQuad(QT3DSVec2((QT3DSF32)theCurrentViewport.m_Width,
+ (QT3DSF32)theCurrentViewport.m_Height),
+ theFinalMVP, *theLayerColorTexture);
+ theContext.SetRenderTarget(theFB);
+ theContext.SetScissorTestEnabled(true);
+ theContext.SetViewport(theCurrentViewport);
+ m_Renderer.RenderQuad(QT3DSVec2((QT3DSF32)theCurrentViewport.m_Width,
+ (QT3DSF32)theCurrentViewport.m_Height),
+ theFinalMVP, *theLayerColorTexture);
+ }
+ } else {
+ // No advanced blending SW fallback needed
+ m_Renderer.RenderQuad(QT3DSVec2((QT3DSF32)theLayerViewport.m_Width,
+ (QT3DSF32)theLayerViewport.m_Height),
+ theFinalMVP, *theLayerColorTexture);
+ }
+#else
+ m_Renderer.RenderQuad(QT3DSVec2((QT3DSF32)theLayerViewport.m_Width,
+ (QT3DSF32)theLayerViewport.m_Height),
+ theFinalMVP, *theLayerColorTexture);
+#endif
+ }
+ if (m_LayerWidgetTexture) {
+ theContext.SetBlendingEnabled(false);
+ m_Renderer.SetupWidgetLayer();
+ SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
+ NVRenderRectF thePresRect(thePrepResult.GetPresentationViewport());
+ NVRenderRectF theLayerRect(thePrepResult.GetLayerToPresentationViewport());
+
+ // Ensure we remove any offsetting in the layer rect that was caused simply by
+ // the
+ // presentation rect offsetting but then use a new rect.
+ NVRenderRectF theWidgetLayerRect(theLayerRect.m_X - thePresRect.m_X,
+ theLayerRect.m_Y - thePresRect.m_Y,
+ theLayerRect.m_Width, theLayerRect.m_Height);
+ theContext.SetScissorTestEnabled(false);
+ theContext.SetViewport(theWidgetLayerRect.ToIntegerRect());
+ m_Renderer.RenderQuad(
+ QT3DSVec2((QT3DSF32)theLayerViewport.m_Width, (QT3DSF32)theLayerViewport.m_Height),
+ theFinalMVP, *m_LayerWidgetTexture);
+ }
+ }
+ } // End offscreen render code.
+
+ if (m_BoundingRectColor.hasValue()) {
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport);
+ NVRenderContextScopedProperty<bool> theScissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled);
+ NVRenderContextScopedProperty<qt3ds::render::NVRenderRect> theScissorRect(
+ theContext, &NVRenderContext::GetScissorRect, &NVRenderContext::SetScissorRect);
+ m_Renderer.SetupWidgetLayer();
+ // Setup a simple viewport to render to the entire presentation viewport.
+ theContext.SetViewport(
+ NVRenderRect(0, 0, (QT3DSU32)thePrepResult.GetPresentationViewport().m_Width,
+ (QT3DSU32)thePrepResult.GetPresentationViewport().m_Height));
+
+ NVRenderRectF thePresRect(thePrepResult.GetPresentationViewport());
+
+ // Remove any offsetting from the presentation rect since the widget layer is a
+ // stand-alone fbo.
+ NVRenderRectF theWidgetScreenRect(theScreenRect.m_X - thePresRect.m_X,
+ theScreenRect.m_Y - thePresRect.m_Y,
+ theScreenRect.m_Width, theScreenRect.m_Height);
+ theContext.SetScissorTestEnabled(false);
+ m_Renderer.DrawScreenRect(theWidgetScreenRect, *m_BoundingRectColor);
+ }
+ }
+
+#define RENDER_FRAME_NEW(type) QT3DS_NEW(m_Renderer.GetPerFrameAllocator(), type)
+
+ void SLayerRenderData::AddLayerRenderStep()
+ {
+ SStackPerfTimer __perfTimer(m_Renderer.GetUICContext().GetPerfTimer(),
+ "SLayerRenderData::AddLayerRenderStep");
+ QT3DS_ASSERT(m_Camera);
+ if (!m_Camera)
+ return;
+
+ IRenderList &theGraph(m_Renderer.GetUICContext().GetRenderList());
+
+ qt3ds::render::NVRenderRect theCurrentViewport = theGraph.GetViewport();
+ if (!m_LayerPrepResult.hasValue())
+ PrepareForRender(
+ SWindowDimensions(theCurrentViewport.m_Width, theCurrentViewport.m_Height));
+ }
+
+ void SLayerRenderData::PrepareForRender()
+ {
+ // When we render to the scene itself (as opposed to an offscreen buffer somewhere)
+ // then we use the MVP of the layer somewhat.
+ NVRenderRect theViewport = m_Renderer.GetUICContext().GetRenderList().GetViewport();
+ PrepareForRender(
+ SWindowDimensions((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height));
+ }
+
+ void SLayerRenderData::ResetForFrame()
+ {
+ SLayerRenderPreparationData::ResetForFrame();
+ m_BoundingRectColor.setEmpty();
+ }
+
+ void SLayerRenderData::PrepareAndRender(const QT3DSMat44 &inViewProjection)
+ {
+ TRenderableObjectList theTransparentObjects(m_TransparentObjects);
+ TRenderableObjectList theOpaqueObjects(m_OpaqueObjects);
+ theTransparentObjects.clear();
+ theOpaqueObjects.clear();
+ m_ModelContexts.clear();
+ SLayerRenderPreparationResultFlags theFlags;
+ PrepareRenderablesForRender(inViewProjection, Empty(), 1.0, theFlags);
+ RenderDepthPass(false);
+ Render();
+ }
+
+ struct SLayerRenderToTextureRunnable : public IRenderTask
+ {
+ SLayerRenderData &m_Data;
+ SLayerRenderToTextureRunnable(SLayerRenderData &d)
+ : m_Data(d)
+ {
+ }
+
+ void Run() override { m_Data.RenderToTexture(); }
+ };
+
+ static inline OffscreenRendererDepthValues::Enum
+ GetOffscreenRendererDepthValue(NVRenderTextureFormats::Enum inBufferFormat)
+ {
+ switch (inBufferFormat) {
+ case NVRenderTextureFormats::Depth32:
+ return OffscreenRendererDepthValues::Depth32;
+ case NVRenderTextureFormats::Depth24:
+ return OffscreenRendererDepthValues::Depth24;
+ case NVRenderTextureFormats::Depth24Stencil8:
+ return OffscreenRendererDepthValues::Depth24;
+ default:
+ QT3DS_ASSERT(false); // fallthrough intentional
+ case NVRenderTextureFormats::Depth16:
+ return OffscreenRendererDepthValues::Depth16;
+ }
+ }
+
+ SOffscreenRendererEnvironment SLayerRenderData::CreateOffscreenRenderEnvironment()
+ {
+ OffscreenRendererDepthValues::Enum theOffscreenDepth(
+ GetOffscreenRendererDepthValue(GetDepthBufferFormat()));
+ NVRenderRect theViewport = m_Renderer.GetUICContext().GetRenderList().GetViewport();
+ return SOffscreenRendererEnvironment(theViewport.m_Width, theViewport.m_Height,
+ NVRenderTextureFormats::RGBA8, theOffscreenDepth,
+ false, AAModeValues::NoAA);
+ }
+
+ IRenderTask &SLayerRenderData::CreateRenderToTextureRunnable()
+ {
+ return *RENDER_FRAME_NEW(SLayerRenderToTextureRunnable)(*this);
+ }
+
+ void SLayerRenderData::addRef() { atomicIncrement(&mRefCount); }
+
+ void SLayerRenderData::release() { QT3DS_IMPLEMENT_REF_COUNT_RELEASE(m_Allocator); }
+}
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.h b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.h
new file mode 100644
index 00000000..e73e9610
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderData.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDERER_IMPL_LAYER_RENDER_DATA_H
+#define UIC_RENDERER_IMPL_LAYER_RENDER_DATA_H
+#include "UICRender.h"
+#include "UICRendererImplLayerRenderPreparationData.h"
+#include "UICRenderResourceBufferObjects.h"
+
+namespace uic {
+namespace render {
+
+struct AdvancedBlendModes
+{
+ enum Enum {
+ None = 0,
+ Overlay,
+ ColorBurn,
+ ColorDodge
+ };
+};
+ struct SLayerRenderData : public SLayerRenderPreparationData
+ {
+
+ // Layers can be rendered offscreen for many reasons; effects, progressive aa,
+ // or just because a flag forces it. If they are rendered offscreen we can then
+ // cache the result so we don't render the layer again if it isn't dirty.
+ CResourceTexture2D m_LayerTexture;
+ CResourceTexture2D m_TemporalAATexture;
+ // Sometimes we need to render our depth buffer to a depth texture.
+ CResourceTexture2D m_LayerDepthTexture;
+ CResourceTexture2D m_LayerPrepassDepthTexture;
+ CResourceTexture2D m_LayerWidgetTexture;
+ CResourceTexture2D m_LayerSsaoTexture;
+ // if we render multisampled we need resolve buffers
+ CResourceTexture2D m_LayerMultisampleTexture;
+ CResourceTexture2D m_LayerMultisamplePrepassDepthTexture;
+ CResourceTexture2D m_LayerMultisampleWidgetTexture;
+ // the texture contains the render result inclusive post effects
+ NVRenderTexture2D *m_LayerCachedTexture;
+
+ NVRenderTexture2D *m_AdvancedBlendDrawTexture;
+ NVRenderTexture2D *m_AdvancedBlendBlendTexture;
+ qt3ds::render::NVRenderFrameBuffer *m_AdvancedModeDrawFB;
+ qt3ds::render::NVRenderFrameBuffer *m_AdvancedModeBlendFB;
+
+ // True if this layer was rendered offscreen.
+ // If this object has no value then this layer wasn't rendered at all.
+ SOffscreenRendererEnvironment m_LastOffscreenRenderEnvironment;
+
+ // GPU profiler per layer
+ NVScopedRefCounted<IRenderProfiler> m_LayerProfilerGpu;
+
+ SCamera m_SceneCamera;
+ QT3DSVec2 m_SceneDimensions;
+
+ // ProgressiveAA algorithm details.
+ QT3DSU32 m_ProgressiveAAPassIndex;
+ // Increments every frame regardless to provide appropriate jittering
+ QT3DSU32 m_TemporalAAPassIndex;
+ // Ensures we don't stop on an in-between frame; we will run two frames after the dirty flag
+ // is clear.
+ QT3DSU32 m_NonDirtyTemporalAAPassIndex;
+ QT3DSF32 m_TextScale;
+
+ volatile QT3DSI32 mRefCount;
+ Option<QT3DSVec3> m_BoundingRectColor;
+ NVRenderTextureFormats::Enum m_DepthBufferFormat;
+
+ QSize m_previousDimensions;
+
+ SLayerRenderData(SLayer &inLayer, CUICRendererImpl &inRenderer);
+
+ virtual ~SLayerRenderData();
+
+ void PrepareForRender();
+
+ // Internal Call
+ void PrepareForRender(const SWindowDimensions &inViewportDimensions) override;
+
+ NVRenderTextureFormats::Enum GetDepthBufferFormat();
+ NVRenderFrameBufferAttachments::Enum
+ GetFramebufferDepthAttachmentFormat(NVRenderTextureFormats::Enum depthFormat);
+
+ // Render this layer assuming viewport and RT are setup. Just renders exactly this item
+ // no effects.
+ void RenderDepthPass(bool inEnableTransparentDepthWrite = false);
+ void RenderAoPass();
+ void RenderFakeDepthMapPass(NVRenderTexture2D *theDepthTex,
+ NVRenderTextureCube *theDepthCube);
+ void RenderShadowMapPass(CResourceFrameBuffer *theFB);
+ void RenderShadowCubeBlurPass(CResourceFrameBuffer *theFB, NVRenderTextureCube *target0,
+ NVRenderTextureCube *target1, QT3DSF32 filterSz, QT3DSF32 clipFar);
+ void RenderShadowMapBlurPass(CResourceFrameBuffer *theFB, NVRenderTexture2D *target0,
+ NVRenderTexture2D *target1, QT3DSF32 filterSz, QT3DSF32 clipFar);
+
+ void Render(CResourceFrameBuffer *theFB = NULL);
+ void ResetForFrame() override;
+
+ void CreateGpuProfiler();
+ void StartProfiling(CRegisteredString &nameID, bool sync);
+ void EndProfiling(CRegisteredString &nameID);
+ void StartProfiling(const char *nameID, bool sync);
+ void EndProfiling(const char *nameID);
+ void AddVertexCount(QT3DSU32 count);
+
+ void RenderToViewport();
+ // Render this layer's data to a texture. Required if we have any effects,
+ // prog AA, or if forced.
+ void RenderToTexture();
+
+ void ApplyLayerPostEffects();
+
+ void RunnableRenderToViewport(qt3ds::render::NVRenderFrameBuffer *theFB);
+
+ void AddLayerRenderStep();
+
+ void RenderRenderWidgets();
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ void BlendAdvancedEquationSwFallback(NVRenderTexture2D *drawTexture,
+ NVRenderTexture2D *m_LayerTexture,
+ AdvancedBlendModes::Enum blendMode);
+#endif
+ // test method to render this layer to a given view projection without running the entire
+ // layer setup system. This assumes the client has setup the viewport, scissor, and render
+ // target
+ // the way they want them.
+ void PrepareAndRender(const QT3DSMat44 &inViewProjection);
+
+ SOffscreenRendererEnvironment CreateOffscreenRenderEnvironment() override;
+ IRenderTask &CreateRenderToTextureRunnable() override;
+
+ void addRef();
+ void release();
+
+ protected:
+ // Used for both the normal passes and the depth pass.
+ // When doing the depth pass, we disable blending completely because it does not really make
+ // sense
+ // to write blend equations into
+ void RunRenderPass(TRenderRenderableFunction renderFn, bool inEnableBlending,
+ bool inEnableDepthWrite, bool inEnableTransparentDepthWrite,
+ QT3DSU32 indexLight, const SCamera &inCamera,
+ CResourceFrameBuffer *theFB = NULL);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ //Functions for advanced blending mode fallback
+ void SetupDrawFB(bool depthEnabled);
+ void BlendAdvancedToFB(DefaultMaterialBlendMode::Enum blendMode, bool depthEnabled,
+ CResourceFrameBuffer *theFB);
+#endif
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.cpp
new file mode 100644
index 00000000..32028ef2
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRendererImplLayerRenderHelper.h"
+#include "UICRenderLayer.h"
+#include "UICTextRenderer.h"
+
+using namespace uic::render;
+
+namespace {
+// left/top
+QT3DSF32 GetMinValue(QT3DSF32 start, QT3DSF32 width, QT3DSF32 value, LayerUnitTypes::Enum units)
+{
+ if (units == LayerUnitTypes::Pixels)
+ return start + value;
+
+ return start + (value * width / 100.0f);
+}
+
+// width/height
+QT3DSF32 GetValueLen(QT3DSF32 width, QT3DSF32 value, LayerUnitTypes::Enum units)
+{
+ if (units == LayerUnitTypes::Pixels)
+ return value;
+
+ return width * value / 100.0f;
+}
+
+// right/bottom
+QT3DSF32 GetMaxValue(QT3DSF32 start, QT3DSF32 width, QT3DSF32 value, LayerUnitTypes::Enum units)
+{
+ if (units == LayerUnitTypes::Pixels)
+ return start + width - value;
+
+ return start + width - (value * width / 100.0f);
+}
+
+QT3DSVec2 ToRectRelativeCoords(const QT3DSVec2 &inCoords, const NVRenderRectF &inRect)
+{
+ return QT3DSVec2(inCoords.x - inRect.m_X, inCoords.y - inRect.m_Y);
+}
+}
+
+SLayerRenderHelper::SLayerRenderHelper()
+ : m_Layer(NULL)
+ , m_Camera(NULL)
+ , m_Offscreen(false)
+{
+}
+
+SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewport,
+ const NVRenderRectF &inPresentationScissor,
+ const QT3DSVec2 &inPresentationDesignDimensions,
+ SLayer &inLayer, bool inOffscreen,
+ uic::render::ScaleModes::Enum inScaleMode,
+ qt3ds::QT3DSVec2 inScaleFactor)
+ : m_PresentationViewport(inPresentationViewport)
+ , m_PresentationScissor(inPresentationScissor)
+ , m_PresentationDesignDimensions(inPresentationDesignDimensions)
+ , m_Layer(&inLayer)
+ , m_Offscreen(inOffscreen)
+ , m_ScaleMode(inScaleMode)
+ , m_ScaleFactor(inScaleFactor)
+{
+ {
+ QT3DSF32 left = m_Layer->m_Left;
+ QT3DSF32 right = m_Layer->m_Right;
+ QT3DSF32 width = m_Layer->m_Width;
+
+ if (m_ScaleMode == uic::render::ScaleModes::FitSelected) {
+ if (m_Layer->m_LeftUnits == LayerUnitTypes::Pixels)
+ left *= m_ScaleFactor.x;
+
+ if (m_Layer->m_RightUnits == LayerUnitTypes::Pixels)
+ right *= m_ScaleFactor.x;
+
+ if (m_Layer->m_WidthUnits == LayerUnitTypes::Pixels)
+ width *= m_ScaleFactor.x;
+ }
+
+ QT3DSF32 horzMin = GetMinValue(inPresentationViewport.m_X, inPresentationViewport.m_Width,
+ left, m_Layer->m_LeftUnits);
+ QT3DSF32 horzWidth = GetValueLen(inPresentationViewport.m_Width, width, m_Layer->m_WidthUnits);
+ QT3DSF32 horzMax = GetMaxValue(inPresentationViewport.m_X, inPresentationViewport.m_Width,
+ right, m_Layer->m_RightUnits);
+
+ switch (inLayer.m_HorizontalFieldValues) {
+ case HorizontalFieldValues::LeftWidth:
+ m_Viewport.m_X = horzMin;
+ m_Viewport.m_Width = horzWidth;
+ break;
+ case HorizontalFieldValues::LeftRight:
+ m_Viewport.m_X = horzMin;
+ m_Viewport.m_Width = horzMax - horzMin;
+ break;
+ case HorizontalFieldValues::WidthRight:
+ m_Viewport.m_Width = horzWidth;
+ m_Viewport.m_X = horzMax - horzWidth;
+ break;
+ }
+ }
+ {
+ QT3DSF32 top = m_Layer->m_Top;
+ QT3DSF32 bottom = m_Layer->m_Bottom;
+ QT3DSF32 height = m_Layer->m_Height;
+
+ if (m_ScaleMode == uic::render::ScaleModes::FitSelected) {
+
+ if (m_Layer->m_TopUnits == LayerUnitTypes::Pixels)
+ top *= m_ScaleFactor.y;
+
+ if (m_Layer->m_BottomUnits == LayerUnitTypes::Pixels)
+ bottom *= m_ScaleFactor.y;
+
+ if (m_Layer->m_HeightUnits == LayerUnitTypes::Pixels)
+ height *= m_ScaleFactor.y;
+ }
+
+ QT3DSF32 vertMin = GetMinValue(inPresentationViewport.m_Y, inPresentationViewport.m_Height,
+ bottom, m_Layer->m_BottomUnits);
+ QT3DSF32 vertWidth =
+ GetValueLen(inPresentationViewport.m_Height, height, m_Layer->m_HeightUnits);
+ QT3DSF32 vertMax = GetMaxValue(inPresentationViewport.m_Y, inPresentationViewport.m_Height,
+ top, m_Layer->m_TopUnits);
+
+ switch (inLayer.m_VerticalFieldValues) {
+ case VerticalFieldValues::HeightBottom:
+ m_Viewport.m_Y = vertMin;
+ m_Viewport.m_Height = vertWidth;
+ break;
+ case VerticalFieldValues::TopBottom:
+ m_Viewport.m_Y = vertMin;
+ m_Viewport.m_Height = vertMax - vertMin;
+ break;
+ case VerticalFieldValues::TopHeight:
+ m_Viewport.m_Height = vertWidth;
+ m_Viewport.m_Y = vertMax - vertWidth;
+ break;
+ }
+ }
+
+ m_Viewport.m_Width = NVMax(1.0f, m_Viewport.m_Width);
+ m_Viewport.m_Height = NVMax(1.0f, m_Viewport.m_Height);
+ // Now force the viewport to be a multiple of four in width and height. This is because
+ // when rendering to a texture we have to respect this and not forcing it causes scaling issues
+ // that are noticeable especially in situations where customers are using text and such.
+ QT3DSF32 originalWidth = m_Viewport.m_Width;
+ QT3DSF32 originalHeight = m_Viewport.m_Height;
+
+ m_Viewport.m_Width = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Width);
+ m_Viewport.m_Height = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Height);
+
+ // Now fudge the offsets to account for this slight difference
+ m_Viewport.m_X += (originalWidth - m_Viewport.m_Width) / 2.0f;
+ m_Viewport.m_Y += (originalHeight - m_Viewport.m_Height) / 2.0f;
+
+ m_Scissor = m_Viewport;
+ m_Scissor.EnsureInBounds(inPresentationScissor);
+ QT3DS_ASSERT(m_Scissor.m_Width >= 0.0f);
+ QT3DS_ASSERT(m_Scissor.m_Height >= 0.0f);
+}
+
+// This is the viewport the camera will use to setup the projection.
+NVRenderRectF SLayerRenderHelper::GetLayerRenderViewport() const
+{
+ if (m_Offscreen)
+ return NVRenderRectF(0, 0, m_Viewport.m_Width, (QT3DSF32)m_Viewport.m_Height);
+ else
+ return m_Viewport;
+}
+
+SWindowDimensions SLayerRenderHelper::GetTextureDimensions() const
+{
+ QT3DSU32 width = (QT3DSU32)m_Viewport.m_Width;
+ QT3DSU32 height = (QT3DSU32)m_Viewport.m_Height;
+ return SWindowDimensions(ITextRenderer::NextMultipleOf4(width),
+ ITextRenderer::NextMultipleOf4(height));
+}
+
+SCameraGlobalCalculationResult SLayerRenderHelper::SetupCameraForRender(SCamera &inCamera)
+{
+ m_Camera = &inCamera;
+ NVRenderRectF rect = GetLayerRenderViewport();
+ if (m_ScaleMode == ScaleModes::FitSelected) {
+ rect.m_Width =
+ (QT3DSF32)(ITextRenderer::NextMultipleOf4((QT3DSU32)(rect.m_Width / m_ScaleFactor.x)));
+ rect.m_Height =
+ (QT3DSF32)(ITextRenderer::NextMultipleOf4((QT3DSU32)(rect.m_Height / m_ScaleFactor.y)));
+ }
+ return m_Camera->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+}
+
+Option<QT3DSVec2> SLayerRenderHelper::GetLayerMouseCoords(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inWindowDimensions,
+ bool inForceIntersect) const
+{
+ // First invert the y so we are dealing with numbers in a normal coordinate space.
+ // Second, move into our layer's coordinate space
+ QT3DSVec2 correctCoords(inMouseCoords.x, inWindowDimensions.y - inMouseCoords.y);
+ QT3DSVec2 theLocalMouse = m_Viewport.ToRectRelative(correctCoords);
+
+ QT3DSF32 theRenderRectWidth = m_Viewport.m_Width;
+ QT3DSF32 theRenderRectHeight = m_Viewport.m_Height;
+ // Crop the mouse to the rect. Apply no further translations.
+ if (inForceIntersect == false
+ && (theLocalMouse.x < 0.0f || theLocalMouse.x >= theRenderRectWidth
+ || theLocalMouse.y < 0.0f || theLocalMouse.y >= theRenderRectHeight)) {
+ return Empty();
+ }
+ return theLocalMouse;
+}
+
+Option<SRay> SLayerRenderHelper::GetPickRay(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inWindowDimensions,
+ bool inForceIntersect) const
+{
+ if (m_Camera == NULL)
+ return Empty();
+ Option<QT3DSVec2> theCoords(
+ GetLayerMouseCoords(inMouseCoords, inWindowDimensions, inForceIntersect));
+ if (theCoords.hasValue()) {
+ // The cameras projection is different if we are onscreen vs. offscreen.
+ // When offscreen, we need to move the mouse coordinates into a local space
+ // to the layer.
+ return m_Camera->Unproject(*theCoords, m_Viewport, m_PresentationDesignDimensions);
+ }
+ return Empty();
+}
+
+bool SLayerRenderHelper::IsLayerVisible() const
+{
+ return m_Scissor.m_Height >= 2.0f && m_Scissor.m_Width >= 2.0f;
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.h b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.h
new file mode 100644
index 00000000..4947c7f1
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderHelper.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#include "UICRender.h"
+#include "foundation/Qt3DSVec2.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "UICRenderWindowDimensions.h"
+#include "UICRenderCamera.h"
+#include "UICRenderContext.h"
+
+namespace uic {
+namespace render {
+
+ /** An independent, testable entity to encapsulate taking at least:
+ * layer, current viewport rect, current scissor rect, presentation design dimensions
+ * and producing a set of rectangles:
+ * layer viewport rect (inside viewport rect and calculated using outer viewport rect info)
+ * layer scissor rect (inside current scissor rect)
+ * layer camera rect (may be the viewport rect)
+ *
+ * In the case where we have to render offscreen for this layer then we need to handle produce
+ * a set of texture dimensions and the layer camera rect ends up being same size but with no
+ *offsets.
+ *
+ * This object should handle part of any translation from screenspace to global space.
+ * I am using language level access control on this object because it needs specific
+ * interface design that will enable future modifications.
+ */
+ struct SLayerRenderHelper
+ {
+ private:
+ NVRenderRectF m_PresentationViewport;
+ NVRenderRectF m_PresentationScissor;
+ QT3DSVec2 m_PresentationDesignDimensions;
+ SLayer *m_Layer;
+ SCamera *m_Camera;
+ bool m_Offscreen;
+
+ NVRenderRectF m_Viewport;
+ NVRenderRectF m_Scissor;
+
+ ScaleModes::Enum m_ScaleMode;
+ QT3DSVec2 m_ScaleFactor;
+
+ public:
+ SLayerRenderHelper();
+
+ SLayerRenderHelper(const NVRenderRectF &inPresentationViewport,
+ const NVRenderRectF &inPresentationScissor,
+ const QT3DSVec2 &inPresentationDesignDimensions, SLayer &inLayer,
+ bool inOffscreen, uic::render::ScaleModes::Enum inScaleMode,
+ qt3ds::QT3DSVec2 inScaleFactor);
+
+ NVRenderRectF GetPresentationViewport() const { return m_PresentationViewport; }
+ NVRenderRectF GetPresentationScissor() const { return m_PresentationScissor; }
+ QT3DSVec2 GetPresentationDesignDimensions() const { return m_PresentationDesignDimensions; }
+ SLayer *GetLayer() const { return m_Layer; }
+ SCamera *GetCamera() const { return m_Camera; }
+ bool IsOffscreen() const { return m_Offscreen; }
+
+ // Does not differ whether offscreen or not, simply states how this layer maps to the
+ // presentation
+ NVRenderRectF GetLayerToPresentationViewport() const { return m_Viewport; }
+ // Does not differ whether offscreen or not, scissor rect of how this layer maps to
+ // presentation.
+ NVRenderRectF GetLayerToPresentationScissorRect() const { return m_Scissor; }
+
+ SWindowDimensions GetTextureDimensions() const;
+
+ SCameraGlobalCalculationResult SetupCameraForRender(SCamera &inCamera);
+
+ Option<QT3DSVec2> GetLayerMouseCoords(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inWindowDimensions,
+ bool inForceIntersect) const;
+
+ Option<SRay> GetPickRay(const QT3DSVec2 &inMouseCoords, const QT3DSVec2 &inWindowDimensions,
+ bool inForceIntersect) const;
+
+ // Checks the various viewports and determines if the layer is visible or not.
+ bool IsLayerVisible() const;
+
+ private:
+ // Viewport used when actually rendering. In the case where this is an offscreen item then
+ // it may be
+ // different than the layer to presentation viewport.
+ NVRenderRectF GetLayerRenderViewport() const;
+ };
+}
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp
new file mode 100644
index 00000000..d06a7678
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.cpp
@@ -0,0 +1,1432 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRender.h"
+#include "UICRenderer.h"
+#include "UICRendererImpl.h"
+#include "UICRenderLayer.h"
+#include "UICRenderEffect.h"
+#include "EASTL/sort.h"
+#include "UICRenderLight.h"
+#include "UICRenderCamera.h"
+#include "UICRenderScene.h"
+#include "UICRenderPresentation.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICRenderContext.h"
+#include "UICRenderResourceManager.h"
+#include "UICTextRenderer.h"
+#include "UICRenderEffectSystem.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "UICOffscreenRenderKey.h"
+#include "UICRenderPlugin.h"
+#include "UICRenderPluginGraphObject.h"
+#include "UICRenderResourceBufferObjects.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "UICRenderMaterialHelpers.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderTextTextureCache.h"
+#include "UICRenderTextTextureAtlas.h"
+#include "UICRenderRenderList.h"
+#include "UICRenderPath.h"
+#include "UICRenderPathManager.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4355)
+#endif
+namespace uic {
+namespace render {
+ using eastl::reverse;
+ using eastl::stable_sort;
+ using qt3ds::render::NVRenderContextScopedProperty;
+ using qt3ds::QT3DSVec2;
+
+ namespace {
+ void MaybeQueueNodeForRender(SNode &inNode, nvvector<SRenderableNodeEntry> &outRenderables,
+ nvvector<SNode *> &outCamerasAndLights, QT3DSU32 &ioDFSIndex)
+ {
+ ++ioDFSIndex;
+ inNode.m_DFSIndex = ioDFSIndex;
+ if (GraphObjectTypes::IsRenderableType(inNode.m_Type))
+ outRenderables.push_back(inNode);
+ else if (GraphObjectTypes::IsLightCameraType(inNode.m_Type))
+ outCamerasAndLights.push_back(&inNode);
+
+ for (SNode *theChild = inNode.m_FirstChild; theChild != NULL;
+ theChild = theChild->m_NextSibling)
+ MaybeQueueNodeForRender(*theChild, outRenderables, outCamerasAndLights, ioDFSIndex);
+ }
+
+ bool HasValidLightProbe(SImage *inLightProbeImage)
+ {
+ return inLightProbeImage && inLightProbeImage->m_TextureData.m_Texture;
+ }
+ }
+
+ SDefaultMaterialPreparationResult::SDefaultMaterialPreparationResult(
+ SShaderDefaultMaterialKey inKey)
+ : m_FirstImage(NULL)
+ , m_Opacity(1.0f)
+ , m_MaterialKey(inKey)
+ , m_Dirty(false)
+ {
+ }
+
+#define MAX_AA_LEVELS 8
+
+ SLayerRenderPreparationData::SLayerRenderPreparationData(SLayer &inLayer,
+ CUICRendererImpl &inRenderer)
+ : m_Layer(inLayer)
+ , m_Renderer(inRenderer)
+ , m_Allocator(inRenderer.GetContext().GetAllocator())
+ , m_RenderableNodeLightEntryPool(
+ ForwardingAllocator(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_RenderableNodes"))
+ , m_RenderableNodes(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_RenderableNodes")
+ , m_LightToNodeMap(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_LightToNodeMap")
+ , m_CamerasAndLights(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_CamerasAndLights")
+ , m_Camera(NULL)
+ , m_Lights(inRenderer.GetContext().GetAllocator(), "SLayerRenderPreparationData::m_Lights")
+ , m_OpaqueObjects(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_OpaqueObjects")
+ , m_TransparentObjects(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_TransparentObjects")
+ , m_RenderedOpaqueObjects(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_RenderedOpaqueObjects")
+ , m_RenderedTransparentObjects(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_RenderedTransparentObjects")
+ , m_IRenderWidgets(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_IRenderWidgets")
+ , m_SourceLightDirections(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_SourceLightDirections")
+ , m_LightDirections(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_LightDirections")
+ , m_ModelContexts(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_ModelContexts")
+ , m_CGLightingFeatureName(
+ inRenderer.GetContext().GetStringTable().RegisterStr("UIC_ENABLE_CG_LIGHTING"))
+ , m_FeaturesDirty(true)
+ , m_FeatureSetHash(0)
+ , m_TooManyLightsError(false)
+ {
+ }
+
+ SLayerRenderPreparationData::~SLayerRenderPreparationData() {}
+
+ bool SLayerRenderPreparationData::NeedsWidgetTexture() const
+ {
+ return m_IRenderWidgets.size() > 0;
+ }
+
+ void SLayerRenderPreparationData::SetShaderFeature(CRegisteredString theStr, bool inValue)
+ {
+ SShaderPreprocessorFeature item(theStr, inValue);
+ eastl::vector<SShaderPreprocessorFeature>::iterator iter = m_Features.begin(),
+ end = m_Features.end();
+
+ // empty loop intentional.
+ for (; iter != end && ((iter->m_Name == theStr) == false); ++iter)
+ ;
+
+ if (iter != end) {
+ if (iter->m_Enabled != inValue) {
+ iter->m_Enabled = inValue;
+ m_FeaturesDirty = true;
+ m_FeatureSetHash = 0;
+ }
+ } else {
+ m_Features.push_back(item);
+ m_FeaturesDirty = true;
+ m_FeatureSetHash = 0;
+ }
+ }
+
+ void SLayerRenderPreparationData::SetShaderFeature(const char *inName, bool inValue)
+ {
+ CRegisteredString theStr(m_Renderer.GetUICContext().GetStringTable().RegisterStr(inName));
+ SetShaderFeature(theStr, inValue);
+ }
+
+ NVConstDataRef<SShaderPreprocessorFeature> SLayerRenderPreparationData::GetShaderFeatureSet()
+ {
+ if (m_FeaturesDirty) {
+ eastl::sort(m_Features.begin(), m_Features.end());
+ m_FeaturesDirty = false;
+ }
+ return toConstDataRef(m_Features.data(), (QT3DSU32)m_Features.size());
+ }
+
+ size_t SLayerRenderPreparationData::GetShaderFeatureSetHash()
+ {
+ if (!m_FeatureSetHash)
+ m_FeatureSetHash = HashShaderFeatureSet(GetShaderFeatureSet());
+ return m_FeatureSetHash;
+ }
+
+ bool SLayerRenderPreparationData::GetShadowMapManager()
+ {
+ if (m_ShadowMapManager.mPtr)
+ return true;
+
+ m_ShadowMapManager.mPtr = UICShadowMap::Create(m_Renderer.GetUICContext());
+
+ return m_ShadowMapManager.mPtr != NULL;
+ }
+
+ bool SLayerRenderPreparationData::GetOffscreenRenderer()
+ {
+ if (m_LastFrameOffscreenRenderer.mPtr)
+ return true;
+
+ if (m_Layer.m_RenderPlugin && m_Layer.m_RenderPlugin->m_Flags.IsActive()) {
+ IRenderPluginInstance *theInstance =
+ m_Renderer.GetUICContext().GetRenderPluginManager().GetOrCreateRenderPluginInstance(
+ m_Layer.m_RenderPlugin->m_PluginPath, m_Layer.m_RenderPlugin);
+ if (theInstance) {
+ m_Renderer.GetUICContext()
+ .GetOffscreenRenderManager()
+ .MaybeRegisterOffscreenRenderer(&theInstance, *theInstance);
+ m_LastFrameOffscreenRenderer = theInstance;
+ }
+ }
+ if (m_LastFrameOffscreenRenderer.mPtr == NULL)
+ m_LastFrameOffscreenRenderer =
+ m_Renderer.GetUICContext().GetOffscreenRenderManager().GetOffscreenRenderer(
+ m_Layer.m_TexturePath);
+ return m_LastFrameOffscreenRenderer.mPtr != NULL;
+ }
+
+ QT3DSVec3 SLayerRenderPreparationData::GetCameraDirection()
+ {
+ if (m_CameraDirection.hasValue() == false) {
+ if (m_Camera)
+ m_CameraDirection = m_Camera->GetScalingCorrectDirection();
+ else
+ m_CameraDirection = QT3DSVec3(0, 0, -1);
+ }
+ return *m_CameraDirection;
+ }
+
+ // Per-frame cache of renderable objects post-sort.
+ NVDataRef<SRenderableObject *> SLayerRenderPreparationData::GetOpaqueRenderableObjects()
+ {
+ if (m_RenderedOpaqueObjects.empty() == false || m_Camera == NULL)
+ return m_RenderedOpaqueObjects;
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() && m_OpaqueObjects.empty() == false) {
+ QT3DSVec3 theCameraDirection(GetCameraDirection());
+ QT3DSVec3 theCameraPosition = m_Camera->GetGlobalPos();
+ m_RenderedOpaqueObjects.assign(m_OpaqueObjects.begin(), m_OpaqueObjects.end());
+ // Setup the object's sorting information
+ for (QT3DSU32 idx = 0, end = m_RenderedOpaqueObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theInfo = *m_RenderedOpaqueObjects[idx];
+ QT3DSVec3 difference = theInfo.m_WorldCenterPoint - theCameraPosition;
+ theInfo.m_CameraDistanceSq = difference.dot(theCameraDirection);
+ }
+
+ ForwardingAllocator alloc(m_Renderer.GetPerFrameAllocator(), "SortAllocations");
+ // Render nearest to furthest objects
+ eastl::merge_sort(m_RenderedOpaqueObjects.begin(), m_RenderedOpaqueObjects.end(), alloc,
+ ISRenderObjectPtrLessThan);
+ }
+ return m_RenderedOpaqueObjects;
+ }
+
+ // If layer depth test is false, this may also contain opaque objects.
+ NVDataRef<SRenderableObject *> SLayerRenderPreparationData::GetTransparentRenderableObjects()
+ {
+ if (m_RenderedTransparentObjects.empty() == false || m_Camera == NULL)
+ return m_RenderedTransparentObjects;
+
+ m_RenderedTransparentObjects.assign(m_TransparentObjects.begin(),
+ m_TransparentObjects.end());
+
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.end(),
+ m_OpaqueObjects.begin(), m_OpaqueObjects.end());
+
+ if (m_RenderedTransparentObjects.empty() == false) {
+ QT3DSVec3 theCameraDirection(GetCameraDirection());
+ QT3DSVec3 theCameraPosition = m_Camera->GetGlobalPos();
+
+ // Setup the object's sorting information
+ for (QT3DSU32 idx = 0, end = m_RenderedTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theInfo = *m_RenderedTransparentObjects[idx];
+ QT3DSVec3 difference = theInfo.m_WorldCenterPoint - theCameraPosition;
+ theInfo.m_CameraDistanceSq = difference.dot(theCameraDirection);
+ }
+ ForwardingAllocator alloc(m_Renderer.GetPerFrameAllocator(), "SortAllocations");
+ // render furthest to nearest.
+ eastl::merge_sort(m_RenderedTransparentObjects.begin(),
+ m_RenderedTransparentObjects.end(), alloc,
+ ISRenderObjectPtrGreatThan);
+ }
+
+ return m_RenderedTransparentObjects;
+ }
+
+#define MAX_LAYER_WIDGETS 200
+
+ void SLayerRenderPreparationData::AddRenderWidget(IRenderWidget &inWidget)
+ {
+ // The if the layer is not active then the widget can't be displayed.
+ // Furthermore ResetForFrame won't be called below which leads to stale
+ // widgets in the m_IRenderWidgets array. These stale widgets would get rendered
+ // the next time the layer was active potentially causing a crash.
+ if (!m_Layer.m_Flags.IsActive())
+ return;
+
+ if (m_IRenderWidgets.size() < MAX_LAYER_WIDGETS)
+ m_IRenderWidgets.push_back(&inWidget);
+ }
+
+#define RENDER_FRAME_NEW(type) QT3DS_NEW(m_Renderer.GetPerFrameAllocator(), type)
+
+#define UIC_RENDER_MINIMUM_RENDER_OPACITY .01f
+
+ SShaderDefaultMaterialKey
+ SLayerRenderPreparationData::GenerateLightingKey(DefaultMaterialLighting::Enum inLightingType)
+ {
+ SShaderDefaultMaterialKey theGeneratedKey(GetShaderFeatureSetHash());
+ if (inLightingType != DefaultMaterialLighting::NoLighting) {
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_HasLighting.SetValue(theGeneratedKey,
+ true);
+
+ if (m_Layer.m_LightProbe && m_Layer.m_LightProbe->m_TextureData.m_Texture)
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_HasIbl.SetValue(theGeneratedKey,
+ true);
+
+ QT3DSU32 numLights = (QT3DSU32)m_Lights.size();
+ if (numLights > SShaderDefaultMaterialKeyProperties::LightCount
+ && m_TooManyLightsError == false) {
+ m_TooManyLightsError = true;
+ numLights = SShaderDefaultMaterialKeyProperties::LightCount;
+ qCCritical(INVALID_OPERATION, "Too many lights on layer, max is 7");
+ QT3DS_ASSERT(false);
+ }
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_LightCount.SetValue(theGeneratedKey,
+ numLights);
+
+ for (QT3DSU32 lightIdx = 0, lightEnd = m_Lights.size(); lightIdx < lightEnd; ++lightIdx) {
+ SLight *theLight(m_Lights[lightIdx]);
+ if (theLight->m_LightType != RenderLightTypes::Directional)
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_LightFlags[lightIdx].SetValue(
+ theGeneratedKey, true);
+ if (theLight->m_LightType == RenderLightTypes::Area)
+ m_Renderer.DefaultMaterialShaderKeyProperties()
+ .m_LightAreaFlags[lightIdx]
+ .SetValue(theGeneratedKey, true);
+ if ((theLight->m_LightType != RenderLightTypes::Point) && (theLight->m_CastShadow))
+ m_Renderer.DefaultMaterialShaderKeyProperties()
+ .m_LightShadowFlags[lightIdx]
+ .SetValue(theGeneratedKey, true);
+ }
+ }
+ return theGeneratedKey;
+ }
+
+ bool SLayerRenderPreparationData::PrepareTextForRender(
+ SText &inText, const QT3DSMat44 &inViewProjection, QT3DSF32 inTextScaleFactor,
+ SLayerRenderPreparationResultFlags &ioFlags)
+ {
+ ITextTextureCache *theTextRenderer = m_Renderer.GetUICContext().GetTextureCache();
+ if (theTextRenderer == NULL)
+ return false;
+
+ SRenderableObjectFlags theFlags;
+ theFlags.SetHasTransparency(true);
+ theFlags.SetCompletelyTransparent(inText.m_GlobalOpacity < .01f);
+ theFlags.SetPickable(true);
+ bool retval = false;
+
+ if (theFlags.IsCompletelyTransparent() == false) {
+ retval = inText.m_Flags.IsDirty() || inText.m_Flags.IsTextDirty();
+ inText.m_Flags.SetTextDirty(false);
+ TTPathObjectAndTexture theResult =
+ theTextRenderer->RenderText(inText, inTextScaleFactor);
+ inText.m_TextTexture = theResult.second.second.mPtr;
+ inText.m_TextTextureDetails = theResult.second.first;
+ inText.m_PathFontItem = theResult.first.second;
+ inText.m_PathFontDetails = theResult.first.first;
+ STextScaleAndOffset theScaleAndOffset(*inText.m_TextTexture,
+ inText.m_TextTextureDetails, inText);
+ QT3DSVec2 theTextScale(theScaleAndOffset.m_TextScale);
+ QT3DSVec2 theTextOffset(theScaleAndOffset.m_TextOffset);
+ QT3DSVec3 minimum(theTextOffset[0] - theTextScale[0], theTextOffset[1] - theTextScale[1],
+ 0);
+ QT3DSVec3 maximum(theTextOffset[0] + theTextScale[0], theTextOffset[1] + theTextScale[1],
+ 0);
+ inText.m_Bounds = NVBounds3(minimum, maximum);
+ QT3DSMat44 theMVP;
+ QT3DSMat33 theNormalMatrix;
+ inText.CalculateMVPAndNormalMatrix(inViewProjection, theMVP, theNormalMatrix);
+
+ if (inText.m_PathFontDetails)
+ ioFlags.SetRequiresStencilBuffer(true);
+
+ STextRenderable *theRenderable = RENDER_FRAME_NEW(STextRenderable)(
+ theFlags, inText.GetGlobalPos(), m_Renderer, inText, inText.m_Bounds, theMVP,
+ inViewProjection, *inText.m_TextTexture, theTextOffset, theTextScale);
+ m_TransparentObjects.push_back(theRenderable);
+ }
+ return retval;
+ }
+
+ eastl::pair<bool, SGraphObject *>
+ SLayerRenderPreparationData::ResolveReferenceMaterial(SGraphObject *inMaterial)
+ {
+ bool subsetDirty = false;
+ bool badIdea = false;
+ SGraphObject *theSourceMaterialObject(inMaterial);
+ SGraphObject *theMaterialObject(inMaterial);
+ while (theMaterialObject
+ && theMaterialObject->m_Type == GraphObjectTypes::ReferencedMaterial && !badIdea) {
+ SReferencedMaterial *theRefMaterial =
+ static_cast<SReferencedMaterial *>(theMaterialObject);
+ theMaterialObject = theRefMaterial->m_ReferencedMaterial;
+ if (theMaterialObject == theSourceMaterialObject) {
+ badIdea = true;
+ }
+
+ if (theRefMaterial == theSourceMaterialObject) {
+ theRefMaterial->m_Dirty.UpdateDirtyForFrame();
+ }
+ subsetDirty = subsetDirty | theRefMaterial->m_Dirty.IsDirty();
+ }
+ if (badIdea) {
+ theMaterialObject = NULL;
+ }
+ return eastl::make_pair(subsetDirty, theMaterialObject);
+ }
+
+ bool SLayerRenderPreparationData::PreparePathForRender(
+ SPath &inPath, const QT3DSMat44 &inViewProjection,
+ const Option<SClippingFrustum> &inClipFrustum, SLayerRenderPreparationResultFlags &ioFlags)
+ {
+ SRenderableObjectFlags theSharedFlags;
+ theSharedFlags.SetPickable(true);
+ QT3DSF32 subsetOpacity = inPath.m_GlobalOpacity;
+ bool retval = inPath.m_Flags.IsDirty();
+ inPath.m_Flags.SetDirty(false);
+ QT3DSMat44 theMVP;
+ QT3DSMat33 theNormalMatrix;
+
+ inPath.CalculateMVPAndNormalMatrix(inViewProjection, theMVP, theNormalMatrix);
+ NVBounds3 theBounds(this->m_Renderer.GetUICContext().GetPathManager().GetBounds(inPath));
+
+ if (inPath.m_GlobalOpacity >= UIC_RENDER_MINIMUM_RENDER_OPACITY
+ && inClipFrustum.hasValue()) {
+ // Check bounding box against the clipping planes
+ NVBounds3 theGlobalBounds = theBounds;
+ theGlobalBounds.transform(inPath.m_GlobalTransform);
+ if (inClipFrustum->intersectsWith(theGlobalBounds) == false)
+ subsetOpacity = 0.0f;
+ }
+
+ SGraphObject *theMaterials[2] = { inPath.m_Material, inPath.m_SecondMaterial };
+
+ if (inPath.m_PathType == PathTypes::Geometry
+ || inPath.m_PaintStyle != PathPaintStyles::FilledAndStroked)
+ theMaterials[1] = NULL;
+
+ // We need to fill material to be the first one rendered so the stroke goes on top.
+ // In the timeline, however, this is reversed.
+
+ if (theMaterials[1])
+ eastl::swap(theMaterials[1], theMaterials[0]);
+
+ for (QT3DSU32 idx = 0, end = 2; idx < end; ++idx) {
+ if (theMaterials[idx] == NULL)
+ continue;
+
+ SRenderableObjectFlags theFlags = theSharedFlags;
+
+ eastl::pair<bool, SGraphObject *> theMaterialAndDirty(
+ ResolveReferenceMaterial(theMaterials[idx]));
+ SGraphObject *theMaterial(theMaterialAndDirty.second);
+ retval = retval || theMaterialAndDirty.first;
+
+ if (theMaterial != NULL && theMaterial->m_Type == GraphObjectTypes::DefaultMaterial) {
+ SDefaultMaterial *theDefaultMaterial = static_cast<SDefaultMaterial *>(theMaterial);
+ // Don't clear dirty flags if the material was referenced.
+ bool clearMaterialFlags = theMaterial == inPath.m_Material;
+ SDefaultMaterialPreparationResult prepResult(PrepareDefaultMaterialForRender(
+ *theDefaultMaterial, theFlags, subsetOpacity, clearMaterialFlags));
+
+ theFlags = prepResult.m_RenderableFlags;
+ if (inPath.m_PathType == PathTypes::Geometry) {
+ if ((inPath.m_BeginCapping != PathCapping::Noner
+ && inPath.m_BeginCapOpacity < 1.0f)
+ || (inPath.m_EndCapping != PathCapping::Noner
+ && inPath.m_EndCapOpacity < 1.0f))
+ theFlags.SetHasTransparency(true);
+ } else {
+ ioFlags.SetRequiresStencilBuffer(true);
+ }
+ retval = retval || prepResult.m_Dirty;
+ bool isStroke = true;
+ if (idx == 0 && inPath.m_PathType == PathTypes::Painted) {
+ if (inPath.m_PaintStyle == PathPaintStyles::Filled
+ || inPath.m_PaintStyle == PathPaintStyles::FilledAndStroked)
+ isStroke = false;
+ }
+
+ SPathRenderable *theRenderable = RENDER_FRAME_NEW(SPathRenderable)(
+ theFlags, inPath.GetGlobalPos(), m_Renderer, inPath.m_GlobalTransform,
+ theBounds, inPath, theMVP, theNormalMatrix, *theMaterial, prepResult.m_Opacity,
+ prepResult.m_MaterialKey, isStroke);
+ theRenderable->m_FirstImage = prepResult.m_FirstImage;
+
+ IUICRenderContext &theUICContext(m_Renderer.GetUICContext());
+ IPathManager &thePathManager = theUICContext.GetPathManager();
+ retval = thePathManager.PrepareForRender(inPath) || retval;
+ retval |= (inPath.m_WireframeMode != theUICContext.GetWireframeMode());
+ inPath.m_WireframeMode = theUICContext.GetWireframeMode();
+
+ if (theFlags.HasTransparency())
+ m_TransparentObjects.push_back(theRenderable);
+ else
+ m_OpaqueObjects.push_back(theRenderable);
+ } else if (theMaterial != NULL
+ && theMaterial->m_Type == GraphObjectTypes::CustomMaterial) {
+ SCustomMaterial *theCustomMaterial = static_cast<SCustomMaterial *>(theMaterial);
+ // Don't clear dirty flags if the material was referenced.
+ // bool clearMaterialFlags = theMaterial == inPath.m_Material;
+ SDefaultMaterialPreparationResult prepResult(
+ PrepareCustomMaterialForRender(*theCustomMaterial, theFlags, subsetOpacity));
+
+ theFlags = prepResult.m_RenderableFlags;
+ if (inPath.m_PathType == PathTypes::Geometry) {
+ if ((inPath.m_BeginCapping != PathCapping::Noner
+ && inPath.m_BeginCapOpacity < 1.0f)
+ || (inPath.m_EndCapping != PathCapping::Noner
+ && inPath.m_EndCapOpacity < 1.0f))
+ theFlags.SetHasTransparency(true);
+ } else {
+ ioFlags.SetRequiresStencilBuffer(true);
+ }
+
+ retval = retval || prepResult.m_Dirty;
+ bool isStroke = true;
+ if (idx == 0 && inPath.m_PathType == PathTypes::Painted) {
+ if (inPath.m_PaintStyle == PathPaintStyles::Filled
+ || inPath.m_PaintStyle == PathPaintStyles::FilledAndStroked)
+ isStroke = false;
+ }
+
+ SPathRenderable *theRenderable = RENDER_FRAME_NEW(SPathRenderable)(
+ theFlags, inPath.GetGlobalPos(), m_Renderer, inPath.m_GlobalTransform,
+ theBounds, inPath, theMVP, theNormalMatrix, *theMaterial, prepResult.m_Opacity,
+ prepResult.m_MaterialKey, isStroke);
+ theRenderable->m_FirstImage = prepResult.m_FirstImage;
+
+ IUICRenderContext &theUICContext(m_Renderer.GetUICContext());
+ IPathManager &thePathManager = theUICContext.GetPathManager();
+ retval = thePathManager.PrepareForRender(inPath) || retval;
+ retval |= (inPath.m_WireframeMode != theUICContext.GetWireframeMode());
+ inPath.m_WireframeMode = theUICContext.GetWireframeMode();
+
+ if (theFlags.HasTransparency())
+ m_TransparentObjects.push_back(theRenderable);
+ else
+ m_OpaqueObjects.push_back(theRenderable);
+ }
+ }
+ return retval;
+ }
+
+ void SLayerRenderPreparationData::PrepareImageForRender(
+ SImage &inImage, ImageMapTypes::Enum inMapType, SRenderableImage *&ioFirstImage,
+ SRenderableImage *&ioNextImage, SRenderableObjectFlags &ioFlags,
+ SShaderDefaultMaterialKey &inShaderKey, QT3DSU32 inImageIndex)
+ {
+ IUICRenderContext &theUICContext(m_Renderer.GetUICContext());
+ IBufferManager &bufferManager = theUICContext.GetBufferManager();
+ IOffscreenRenderManager &theOffscreenRenderManager(
+ theUICContext.GetOffscreenRenderManager());
+ IRenderPluginManager &theRenderPluginManager(theUICContext.GetRenderPluginManager());
+ if (inImage.ClearDirty(bufferManager, theOffscreenRenderManager, theRenderPluginManager))
+ ioFlags |= RenderPreparationResultFlagValues::Dirty;
+
+ // All objects with offscreen renderers are pickable so we can pass the pick through to the
+ // offscreen renderer and let it deal with the pick.
+ if (inImage.m_LastFrameOffscreenRenderer != NULL)
+ ioFlags.SetPickable(true);
+
+ if (inImage.m_TextureData.m_Texture) {
+ if (inImage.m_TextureData.m_TextureFlags.HasTransparency()
+ && (inMapType == ImageMapTypes::Diffuse
+ || inMapType == ImageMapTypes::Opacity
+ || inMapType == ImageMapTypes::Translucency)) {
+ ioFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ }
+ // Textures used in general have linear characteristics.
+ // PKC -- The filters are properly set already. Setting them here only overrides what
+ // would
+ // otherwise be a correct setting.
+ // inImage.m_TextureData.m_Texture->SetMinFilter( NVRenderTextureMinifyingOp::Linear );
+ // inImage.m_TextureData.m_Texture->SetMagFilter( NVRenderTextureMagnifyingOp::Linear );
+
+ SRenderableImage *theImage = RENDER_FRAME_NEW(SRenderableImage)(inMapType, inImage);
+ SShaderKeyImageMap &theKeyProp =
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_ImageMaps[inImageIndex];
+
+ theKeyProp.SetEnabled(inShaderKey, true);
+ switch (inImage.m_MappingMode) {
+ default:
+ QT3DS_ASSERT(false);
+ // fallthrough intentional
+ case ImageMappingModes::Normal:
+ break;
+ case ImageMappingModes::Environment:
+ theKeyProp.SetEnvMap(inShaderKey, true);
+ break;
+ case ImageMappingModes::LightProbe:
+ theKeyProp.SetLightProbe(inShaderKey, true);
+ break;
+ }
+
+ if (inImage.m_TextureData.m_TextureFlags.IsInvertUVCoords())
+ theKeyProp.SetInvertUVMap(inShaderKey, true);
+ if (ioFirstImage == NULL)
+ ioFirstImage = theImage;
+ else
+ ioNextImage->m_NextImage = theImage;
+
+ if (inImage.m_TextureData.m_TextureFlags.IsPreMultiplied())
+ theKeyProp.SetPremultiplied(inShaderKey, true);
+
+ SShaderKeyTextureSwizzle &theSwizzleKeyProp =
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_TextureSwizzle[inImageIndex];
+ theSwizzleKeyProp.SetSwizzleMode(
+ inShaderKey, inImage.m_TextureData.m_Texture->GetTextureSwizzleMode(), true);
+
+ ioNextImage = theImage;
+ }
+ }
+
+ SDefaultMaterialPreparationResult SLayerRenderPreparationData::PrepareDefaultMaterialForRender(
+ SDefaultMaterial &inMaterial, SRenderableObjectFlags &inExistingFlags, QT3DSF32 inOpacity,
+ bool inClearDirtyFlags)
+ {
+ SDefaultMaterial *theMaterial = &inMaterial;
+ SDefaultMaterialPreparationResult retval(GenerateLightingKey(theMaterial->m_Lighting));
+ retval.m_RenderableFlags = inExistingFlags;
+ SRenderableObjectFlags &renderableFlags(retval.m_RenderableFlags);
+ SShaderDefaultMaterialKey &theGeneratedKey(retval.m_MaterialKey);
+ retval.m_Opacity = inOpacity;
+ QT3DSF32 &subsetOpacity(retval.m_Opacity);
+
+ if (theMaterial->m_Dirty.IsDirty()) {
+ renderableFlags |= RenderPreparationResultFlagValues::Dirty;
+ }
+ subsetOpacity *= theMaterial->m_Opacity;
+ if (inClearDirtyFlags)
+ theMaterial->m_Dirty.UpdateDirtyForFrame();
+
+ SRenderableImage *firstImage = NULL;
+
+ // set wireframe mode
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
+ theGeneratedKey, m_Renderer.GetUICContext().GetWireframeMode());
+
+ if (theMaterial->m_IblProbe && CheckLightProbeDirty(*theMaterial->m_IblProbe)) {
+ m_Renderer.PrepareImageForIbl(*theMaterial->m_IblProbe);
+ }
+
+ if (!m_Renderer.DefaultMaterialShaderKeyProperties().m_HasIbl.GetValue(theGeneratedKey)) {
+ bool lightProbeValid = HasValidLightProbe(theMaterial->m_IblProbe);
+ SetShaderFeature("UIC_ENABLE_LIGHT_PROBE", lightProbeValid);
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_HasIbl.SetValue(theGeneratedKey,
+ lightProbeValid);
+ // SetShaderFeature( "UIC_ENABLE_IBL_FOV",
+ // m_Renderer.GetLayerRenderData()->m_Layer.m_ProbeFov < 180.0f );
+ }
+
+ if (subsetOpacity >= UIC_RENDER_MINIMUM_RENDER_OPACITY) {
+
+ if (theMaterial->m_BlendMode != DefaultMaterialBlendMode::Normal
+ || theMaterial->m_OpacityMap) {
+ renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ }
+
+ bool specularEnabled = theMaterial->IsSpecularEnabled();
+ if (specularEnabled) {
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_SpecularEnabled.SetValue(
+ theGeneratedKey, true);
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_SpecularModel.SetSpecularModel(
+ theGeneratedKey, theMaterial->m_SpecularModel);
+ }
+
+ if (theMaterial->IsFresnelEnabled()) {
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_FresnelEnabled.SetValue(
+ theGeneratedKey, true);
+ }
+
+ // Run through the material's images and prepare them for render.
+ // this may in fact set pickable on the renderable flags if one of the images
+ // links to a sub presentation or any offscreen rendered object.
+ SRenderableImage *nextImage = NULL;
+#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent) \
+ if ((img)) \
+ PrepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags, \
+ theGeneratedKey, shadercomponent);
+
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_DiffuseMaps[0], ImageMapTypes::Diffuse,
+ SShaderDefaultMaterialKeyProperties::DiffuseMap0);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_DiffuseMaps[1], ImageMapTypes::Diffuse,
+ SShaderDefaultMaterialKeyProperties::DiffuseMap1);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_DiffuseMaps[2], ImageMapTypes::Diffuse,
+ SShaderDefaultMaterialKeyProperties::DiffuseMap2);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_EmissiveMap, ImageMapTypes::Emissive,
+ SShaderDefaultMaterialKeyProperties::EmissiveMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_EmissiveMap2, ImageMapTypes::Emissive,
+ SShaderDefaultMaterialKeyProperties::EmissiveMap2);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_SpecularReflection, ImageMapTypes::Specular,
+ SShaderDefaultMaterialKeyProperties::SpecularMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_OpacityMap, ImageMapTypes::Opacity,
+ SShaderDefaultMaterialKeyProperties::OpacityMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_BumpMap, ImageMapTypes::Bump,
+ SShaderDefaultMaterialKeyProperties::BumpMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_SpecularMap, ImageMapTypes::SpecularAmountMap,
+ SShaderDefaultMaterialKeyProperties::SpecularAmountMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_NormalMap, ImageMapTypes::Normal,
+ SShaderDefaultMaterialKeyProperties::NormalMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_DisplacementMap, ImageMapTypes::Displacement,
+ SShaderDefaultMaterialKeyProperties::DisplacementMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_TranslucencyMap, ImageMapTypes::Translucency,
+ SShaderDefaultMaterialKeyProperties::TranslucencyMap);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_Lightmaps.m_LightmapIndirect,
+ ImageMapTypes::LightmapIndirect,
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_Lightmaps.m_LightmapRadiosity,
+ ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ CHECK_IMAGE_AND_PREPARE(theMaterial->m_Lightmaps.m_LightmapShadow,
+ ImageMapTypes::LightmapShadow,
+ SShaderDefaultMaterialKeyProperties::LightmapShadow);
+ }
+#undef CHECK_IMAGE_AND_PREPARE
+
+ if (subsetOpacity < UIC_RENDER_MINIMUM_RENDER_OPACITY) {
+ subsetOpacity = 0.0f;
+ // You can still pick against completely transparent objects(or rather their bounding
+ // box)
+ // you just don't render them.
+ renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ renderableFlags |= RenderPreparationResultFlagValues::CompletelyTransparent;
+ }
+
+ if (IsNotOne(subsetOpacity))
+ renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+
+ retval.m_FirstImage = firstImage;
+ if (retval.m_RenderableFlags.IsDirty())
+ retval.m_Dirty = true;
+ return retval;
+ }
+
+ SDefaultMaterialPreparationResult SLayerRenderPreparationData::PrepareCustomMaterialForRender(
+ SCustomMaterial &inMaterial, SRenderableObjectFlags &inExistingFlags, QT3DSF32 inOpacity)
+ {
+ SDefaultMaterialPreparationResult retval(GenerateLightingKey(
+ DefaultMaterialLighting::FragmentLighting)); // always fragment lighting
+ retval.m_RenderableFlags = inExistingFlags;
+ SRenderableObjectFlags &renderableFlags(retval.m_RenderableFlags);
+ SShaderDefaultMaterialKey &theGeneratedKey(retval.m_MaterialKey);
+ retval.m_Opacity = inOpacity;
+ QT3DSF32 &subsetOpacity(retval.m_Opacity);
+
+ // set wireframe mode
+ m_Renderer.DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
+ theGeneratedKey, m_Renderer.GetUICContext().GetWireframeMode());
+
+ if (subsetOpacity < UIC_RENDER_MINIMUM_RENDER_OPACITY) {
+ subsetOpacity = 0.0f;
+ // You can still pick against completely transparent objects(or rather their bounding
+ // box)
+ // you just don't render them.
+ renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ renderableFlags |= RenderPreparationResultFlagValues::CompletelyTransparent;
+ }
+
+ if (IsNotOne(subsetOpacity))
+ renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+
+ SRenderableImage *firstImage = NULL;
+ SRenderableImage *nextImage = NULL;
+
+#define CHECK_IMAGE_AND_PREPARE(img, imgtype, shadercomponent) \
+ if ((img)) \
+ PrepareImageForRender(*(img), imgtype, firstImage, nextImage, renderableFlags, \
+ theGeneratedKey, shadercomponent);
+
+ CHECK_IMAGE_AND_PREPARE(inMaterial.m_DisplacementMap, ImageMapTypes::Displacement,
+ SShaderDefaultMaterialKeyProperties::DisplacementMap);
+ CHECK_IMAGE_AND_PREPARE(inMaterial.m_Lightmaps.m_LightmapIndirect,
+ ImageMapTypes::LightmapIndirect,
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ CHECK_IMAGE_AND_PREPARE(inMaterial.m_Lightmaps.m_LightmapRadiosity,
+ ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ CHECK_IMAGE_AND_PREPARE(inMaterial.m_Lightmaps.m_LightmapShadow,
+ ImageMapTypes::LightmapShadow,
+ SShaderDefaultMaterialKeyProperties::LightmapShadow);
+#undef CHECK_IMAGE_AND_PREPARE
+
+ retval.m_FirstImage = firstImage;
+ return retval;
+ }
+
+ bool SLayerRenderPreparationData::PrepareModelForRender(
+ SModel &inModel, const QT3DSMat44 &inViewProjection,
+ const Option<SClippingFrustum> &inClipFrustum, TNodeLightEntryList &inScopedLights)
+ {
+ IUICRenderContext &theUICContext(m_Renderer.GetUICContext());
+ IBufferManager &bufferManager = theUICContext.GetBufferManager();
+ SRenderMesh *theMesh = bufferManager.LoadMesh(inModel.m_MeshPath);
+ if (theMesh == NULL)
+ return false;
+
+ SGraphObject *theSourceMaterialObject = inModel.m_FirstMaterial;
+ SModelContext &theModelContext =
+ *RENDER_FRAME_NEW(SModelContext)(inModel, inViewProjection);
+ m_ModelContexts.push_back(&theModelContext);
+
+ bool subsetDirty = false;
+
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
+ inScopedLights);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ for (QT3DSU32 idx = 0, end = theMesh->m_Subsets.size(); idx < end && theSourceMaterialObject;
+ ++idx, theSourceMaterialObject = GetNextMaterialSibling(theSourceMaterialObject)) {
+ SRenderSubset &theOuterSubset(theMesh->m_Subsets[idx]);
+ {
+ SRenderSubset &theSubset(theOuterSubset);
+ SRenderableObjectFlags renderableFlags;
+ renderableFlags.SetPickable(false);
+ QT3DSF32 subsetOpacity = inModel.m_GlobalOpacity;
+ QT3DSVec3 theModelCenter(theSubset.m_Bounds.getCenter());
+ theModelCenter = inModel.m_GlobalTransform.transform(theModelCenter);
+
+ if (subsetOpacity >= UIC_RENDER_MINIMUM_RENDER_OPACITY
+ && inClipFrustum.hasValue()) {
+ // Check bounding box against the clipping planes
+ NVBounds3 theGlobalBounds = theSubset.m_Bounds;
+ theGlobalBounds.transform(theModelContext.m_Model.m_GlobalTransform);
+ if (inClipFrustum->intersectsWith(theGlobalBounds) == false)
+ subsetOpacity = 0.0f;
+ }
+
+ // For now everything is pickable. Eventually we want to have localPickable and
+ // globalPickable set on the node during
+ // updates and have the runtime tell us what is pickable and what is not pickable.
+ // Completely transparent models cannot be pickable. But models with completely
+ // transparent materials
+ // still are. This allows the artist to control pickability in a somewhat
+ // fine-grained style.
+ bool canModelBePickable = inModel.m_GlobalOpacity > .01f;
+ renderableFlags.SetPickable(canModelBePickable
+ && (theModelContext.m_Model.m_Flags.IsGloballyPickable()
+ || renderableFlags.GetPickable()));
+ SRenderableObject *theRenderableObject(NULL);
+ eastl::pair<bool, SGraphObject *> theMaterialObjectAndDirty =
+ ResolveReferenceMaterial(theSourceMaterialObject);
+ SGraphObject *theMaterialObject = theMaterialObjectAndDirty.second;
+ subsetDirty = subsetDirty || theMaterialObjectAndDirty.first;
+ if (theMaterialObject == NULL)
+ continue;
+
+ // set tessellation
+ if (inModel.m_TessellationMode != TessModeValues::NoTess) {
+ theSubset.m_PrimitiveType = NVRenderDrawMode::Patches;
+ // set tessellation factor
+ theSubset.m_EdgeTessFactor = inModel.m_EdgeTess;
+ theSubset.m_InnerTessFactor = inModel.m_InnerTess;
+ // update the vertex ver patch count in the input assembler
+ // currently we only support triangle patches so count is always 3
+ theSubset.m_InputAssembler->SetPatchVertexCount(3);
+ theSubset.m_InputAssemblerDepth->SetPatchVertexCount(3);
+ // check wireframe mode
+ theSubset.m_WireframeMode = theUICContext.GetWireframeMode();
+
+ subsetDirty =
+ subsetDirty | (theSubset.m_WireframeMode != inModel.m_WireframeMode);
+ inModel.m_WireframeMode = theUICContext.GetWireframeMode();
+ } else {
+ theSubset.m_PrimitiveType = theSubset.m_InputAssembler->GetPrimitiveType();
+ theSubset.m_InputAssembler->SetPatchVertexCount(1);
+ theSubset.m_InputAssemblerDepth->SetPatchVertexCount(1);
+ // currently we allow wirframe mode only if tessellation is on
+ theSubset.m_WireframeMode = false;
+
+ subsetDirty =
+ subsetDirty | (theSubset.m_WireframeMode != inModel.m_WireframeMode);
+ inModel.m_WireframeMode = false;
+ }
+ // Only clear flags on the materials in this direct hierarchy. Do not clear them of
+ // this
+ // references materials in another hierarchy.
+ bool clearMaterialDirtyFlags = theMaterialObject == theSourceMaterialObject;
+
+ if (theMaterialObject == NULL)
+ continue;
+
+ if (theMaterialObject->m_Type == GraphObjectTypes::DefaultMaterial) {
+ SDefaultMaterial &theMaterial(
+ static_cast<SDefaultMaterial &>(*theMaterialObject));
+ SDefaultMaterialPreparationResult theMaterialPrepResult(
+ PrepareDefaultMaterialForRender(theMaterial, renderableFlags, subsetOpacity,
+ clearMaterialDirtyFlags));
+ SShaderDefaultMaterialKey theGeneratedKey = theMaterialPrepResult.m_MaterialKey;
+ subsetOpacity = theMaterialPrepResult.m_Opacity;
+ SRenderableImage *firstImage(theMaterialPrepResult.m_FirstImage);
+ subsetDirty |= theMaterialPrepResult.m_Dirty;
+ renderableFlags = theMaterialPrepResult.m_RenderableFlags;
+
+ m_Renderer.DefaultMaterialShaderKeyProperties()
+ .m_TessellationMode.SetTessellationMode(theGeneratedKey,
+ inModel.m_TessellationMode, true);
+
+ NVConstDataRef<QT3DSMat44> boneGlobals;
+ if (theSubset.m_Joints.size()) {
+ QT3DS_ASSERT(false);
+ }
+
+ theRenderableObject = RENDER_FRAME_NEW(SSubsetRenderable)(
+ renderableFlags, theModelCenter, m_Renderer, theSubset, theMaterial,
+ theModelContext, subsetOpacity, firstImage, theGeneratedKey, boneGlobals);
+ subsetDirty = subsetDirty || renderableFlags.IsDirty();
+
+ } // if type == DefaultMaterial
+ else if (theMaterialObject->m_Type == GraphObjectTypes::CustomMaterial) {
+ SCustomMaterial &theMaterial(
+ static_cast<SCustomMaterial &>(*theMaterialObject));
+
+ ICustomMaterialSystem &theMaterialSystem(
+ theUICContext.GetCustomMaterialSystem());
+ subsetDirty |= theMaterialSystem.PrepareForRender(
+ theModelContext.m_Model, theSubset, theMaterial, clearMaterialDirtyFlags);
+
+ SDefaultMaterialPreparationResult theMaterialPrepResult(
+ PrepareCustomMaterialForRender(theMaterial, renderableFlags,
+ subsetOpacity));
+ SShaderDefaultMaterialKey theGeneratedKey = theMaterialPrepResult.m_MaterialKey;
+ subsetOpacity = theMaterialPrepResult.m_Opacity;
+ SRenderableImage *firstImage(theMaterialPrepResult.m_FirstImage);
+ renderableFlags = theMaterialPrepResult.m_RenderableFlags;
+
+ // prepare for render tells us if the object is transparent
+ if (theMaterial.m_hasTransparency)
+ renderableFlags |= RenderPreparationResultFlagValues::HasTransparency;
+ // prepare for render tells us if the object is transparent
+ if (theMaterial.m_hasRefraction)
+ renderableFlags |= RenderPreparationResultFlagValues::HasRefraction;
+
+ m_Renderer.DefaultMaterialShaderKeyProperties()
+ .m_TessellationMode.SetTessellationMode(theGeneratedKey,
+ inModel.m_TessellationMode, true);
+
+ if (theMaterial.m_IblProbe && CheckLightProbeDirty(*theMaterial.m_IblProbe)) {
+ m_Renderer.PrepareImageForIbl(*theMaterial.m_IblProbe);
+ }
+
+ theRenderableObject = RENDER_FRAME_NEW(SCustomMaterialRenderable)(
+ renderableFlags, theModelCenter, m_Renderer, theSubset, theMaterial,
+ theModelContext, subsetOpacity, firstImage, theGeneratedKey);
+ }
+ if (theRenderableObject) {
+ theRenderableObject->m_ScopedLights = inScopedLights;
+ // set tessellation
+ theRenderableObject->m_TessellationMode = inModel.m_TessellationMode;
+
+ if (theRenderableObject->m_RenderableFlags.HasTransparency()
+ || theRenderableObject->m_RenderableFlags.HasRefraction()) {
+ m_TransparentObjects.push_back(theRenderableObject);
+ } else {
+ m_OpaqueObjects.push_back(theRenderableObject);
+ }
+ }
+ }
+ }
+ return subsetDirty;
+ }
+
+ bool SLayerRenderPreparationData::PrepareRenderablesForRender(
+ const QT3DSMat44 &inViewProjection, const Option<SClippingFrustum> &inClipFrustum,
+ QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags)
+ {
+ SStackPerfTimer __timer(m_Renderer.GetUICContext().GetPerfTimer(),
+ "SLayerRenderData::PrepareRenderablesForRender");
+ m_ViewProjection = inViewProjection;
+ QT3DSF32 theTextScaleFactor = inTextScaleFactor;
+ bool wasDataDirty = false;
+ bool hasTextRenderer = m_Renderer.GetUICContext().GetTextRenderer() != NULL;
+ for (QT3DSU32 idx = 0, end = m_RenderableNodes.size(); idx < end; ++idx) {
+ SRenderableNodeEntry &theNodeEntry(m_RenderableNodes[idx]);
+ SNode *theNode = theNodeEntry.m_Node;
+ wasDataDirty = wasDataDirty || theNode->m_Flags.IsDirty();
+ switch (theNode->m_Type) {
+ case GraphObjectTypes::Model: {
+ SModel *theModel = static_cast<SModel *>(theNode);
+ theModel->CalculateGlobalVariables();
+ if (theModel->m_Flags.IsGloballyActive()) {
+ bool wasModelDirty = PrepareModelForRender(
+ *theModel, inViewProjection, inClipFrustum, theNodeEntry.m_Lights);
+ wasDataDirty = wasDataDirty || wasModelDirty;
+ }
+ } break;
+ case GraphObjectTypes::Text: {
+ if (hasTextRenderer) {
+ SText *theText = static_cast<SText *>(theNode);
+ theText->CalculateGlobalVariables();
+ if (theText->m_Flags.IsGloballyActive()) {
+ bool wasTextDirty = PrepareTextForRender(*theText, inViewProjection,
+ theTextScaleFactor, ioFlags);
+ wasDataDirty = wasDataDirty || wasTextDirty;
+ }
+ }
+ } break;
+ case GraphObjectTypes::Path: {
+ SPath *thePath = static_cast<SPath *>(theNode);
+ thePath->CalculateGlobalVariables();
+ if (thePath->m_Flags.IsGloballyActive()) {
+ bool wasPathDirty =
+ PreparePathForRender(*thePath, inViewProjection, inClipFrustum, ioFlags);
+ wasDataDirty = wasDataDirty || wasPathDirty;
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ return wasDataDirty;
+ }
+
+ bool SLayerRenderPreparationData::CheckLightProbeDirty(SImage &inLightProbe)
+ {
+ IUICRenderContext &theContext(m_Renderer.GetUICContext());
+ return inLightProbe.ClearDirty(theContext.GetBufferManager(),
+ theContext.GetOffscreenRenderManager(),
+ theContext.GetRenderPluginManager(), true);
+ }
+
+ struct SLightNodeMarker
+ {
+ SLight *m_Light;
+ QT3DSU32 m_LightIndex;
+ QT3DSU32 m_FirstValidIndex;
+ QT3DSU32 m_JustPastLastValidIndex;
+ bool m_AddOrRemove;
+ SLightNodeMarker()
+ : m_Light(NULL)
+ , m_FirstValidIndex(0)
+ , m_JustPastLastValidIndex(0)
+ , m_AddOrRemove(false)
+ {
+ }
+ SLightNodeMarker(SLight &inLight, QT3DSU32 inLightIndex, SNode &inNode, bool aorm)
+ : m_Light(&inLight)
+ , m_LightIndex(inLightIndex)
+ , m_AddOrRemove(aorm)
+ {
+ if (inNode.m_Type == GraphObjectTypes::Layer) {
+ m_FirstValidIndex = 0;
+ m_JustPastLastValidIndex = QT3DS_MAX_U32;
+ } else {
+ m_FirstValidIndex = inNode.m_DFSIndex;
+ SNode *lastChild = NULL;
+ SNode *firstChild = inNode.m_FirstChild;
+ // find deepest last child
+ while (firstChild) {
+ for (SNode *childNode = firstChild; childNode;
+ childNode = childNode->m_NextSibling)
+ lastChild = childNode;
+
+ if (lastChild)
+ firstChild = lastChild->m_FirstChild;
+ else
+ firstChild = NULL;
+ }
+ if (lastChild)
+ // last valid index would be the last child index + 1
+ m_JustPastLastValidIndex = lastChild->m_DFSIndex + 1;
+ else // no children.
+ m_JustPastLastValidIndex = m_FirstValidIndex + 1;
+ }
+ }
+ };
+
+ // m_Layer.m_Camera->CalculateViewProjectionMatrix(m_ViewProjection);
+ void
+ SLayerRenderPreparationData::PrepareForRender(const SWindowDimensions &inViewportDimensions)
+ {
+ SStackPerfTimer __timer(m_Renderer.GetUICContext().GetPerfTimer(),
+ "SLayerRenderData::PrepareForRender");
+ if (m_LayerPrepResult.hasValue())
+ return;
+
+ m_Features.clear();
+ m_FeatureSetHash = 0;
+ QT3DSVec2 thePresentationDimensions((QT3DSF32)inViewportDimensions.m_Width,
+ (QT3DSF32)inViewportDimensions.m_Height);
+ IRenderList &theGraph(m_Renderer.GetUICContext().GetRenderList());
+ NVRenderRect theViewport(theGraph.GetViewport());
+ NVRenderRect theScissor(theGraph.GetViewport());
+ if (theGraph.IsScissorTestEnabled())
+ theScissor = m_Renderer.GetContext().GetScissorRect();
+ bool wasDirty = false;
+ bool wasDataDirty = false;
+ wasDirty = m_Layer.m_Flags.IsDirty();
+ // The first pass is just to render the data.
+ QT3DSU32 maxNumAAPasses = m_Layer.m_ProgressiveAAMode == AAModeValues::NoAA
+ ? (QT3DSU32)0
+ : (QT3DSU32)(m_Layer.m_ProgressiveAAMode) + 1;
+ maxNumAAPasses = NVMin((QT3DSU32)(MAX_AA_LEVELS + 1), maxNumAAPasses);
+ SEffect *theLastEffect = NULL;
+ // Uncomment the line below to disable all progressive AA.
+ // maxNumAAPasses = 0;
+
+ SLayerRenderPreparationResult thePrepResult;
+ bool hasOffscreenRenderer = GetOffscreenRenderer();
+
+ bool SSAOEnabled = (m_Layer.m_AoStrength > 0.0f && m_Layer.m_AoDistance > 0.0f);
+ bool SSDOEnabled = (m_Layer.m_ShadowStrength > 0.0f && m_Layer.m_ShadowDist > 0.0f);
+ SetShaderFeature("UIC_ENABLE_SSAO", SSAOEnabled);
+ SetShaderFeature("UIC_ENABLE_SSDO", SSDOEnabled);
+ bool requiresDepthPrepass = (hasOffscreenRenderer == false) && (SSAOEnabled || SSDOEnabled);
+ SetShaderFeature("UIC_ENABLE_SSM", false); // by default no shadow map generation
+
+ if (m_Layer.m_Flags.IsActive()) {
+ // Get the layer's width and height.
+ IEffectSystem &theEffectSystem(m_Renderer.GetUICContext().GetEffectSystem());
+ for (SEffect *theEffect = m_Layer.m_FirstEffect; theEffect;
+ theEffect = theEffect->m_NextEffect) {
+ if (theEffect->m_Flags.IsDirty()) {
+ wasDirty = true;
+ theEffect->m_Flags.SetDirty(false);
+ }
+ if (theEffect->m_Flags.IsActive()) {
+ theLastEffect = theEffect;
+ if (hasOffscreenRenderer == false
+ && theEffectSystem.DoesEffectRequireDepthTexture(theEffect->m_ClassName))
+ requiresDepthPrepass = true;
+ }
+ }
+ if (m_Layer.m_Flags.IsDirty()) {
+ wasDirty = true;
+ m_Layer.CalculateGlobalVariables();
+ }
+
+ bool shouldRenderToTexture = true;
+
+ if (hasOffscreenRenderer) {
+ // We don't render to texture with offscreen renderers, we just render them to the
+ // viewport.
+ shouldRenderToTexture = false;
+ // Progaa disabled when using offscreen rendering.
+ maxNumAAPasses = 0;
+ }
+
+ thePrepResult = SLayerRenderPreparationResult(SLayerRenderHelper(
+ theViewport, theScissor, m_Layer.m_Scene->m_Presentation->m_PresentationDimensions,
+ m_Layer, shouldRenderToTexture, m_Renderer.GetUICContext().GetScaleMode(),
+ m_Renderer.GetUICContext().GetPresentationScaleFactor()));
+ thePrepResult.m_LastEffect = theLastEffect;
+ thePrepResult.m_MaxAAPassIndex = maxNumAAPasses;
+ thePrepResult.m_Flags.SetRequiresDepthTexture(requiresDepthPrepass
+ || NeedsWidgetTexture());
+ thePrepResult.m_Flags.SetShouldRenderToTexture(shouldRenderToTexture);
+ thePrepResult.m_Flags.SetRequiresSsaoPass(SSAOEnabled);
+
+ if (thePrepResult.IsLayerVisible()) {
+ if (shouldRenderToTexture) {
+ m_Renderer.GetUICContext().GetRenderList().AddRenderTask(
+ CreateRenderToTextureRunnable());
+ }
+ if (m_Layer.m_LightProbe && CheckLightProbeDirty(*m_Layer.m_LightProbe)) {
+ m_Renderer.PrepareImageForIbl(*m_Layer.m_LightProbe);
+ wasDataDirty = true;
+ }
+
+ bool lightProbeValid = HasValidLightProbe(m_Layer.m_LightProbe);
+
+ SetShaderFeature("UIC_ENABLE_LIGHT_PROBE", lightProbeValid);
+ SetShaderFeature("UIC_ENABLE_IBL_FOV", m_Layer.m_ProbeFov < 180.0f);
+
+ if (lightProbeValid && m_Layer.m_LightProbe2
+ && CheckLightProbeDirty(*m_Layer.m_LightProbe2)) {
+ m_Renderer.PrepareImageForIbl(*m_Layer.m_LightProbe2);
+ wasDataDirty = true;
+ }
+
+ SetShaderFeature("UIC_ENABLE_LIGHT_PROBE_2",
+ lightProbeValid && HasValidLightProbe(m_Layer.m_LightProbe2));
+
+ // Push nodes in reverse depth first order
+ if (m_RenderableNodes.empty()) {
+ m_CamerasAndLights.clear();
+ QT3DSU32 dfsIndex = 0;
+ for (SNode *theChild = m_Layer.m_FirstChild; theChild;
+ theChild = theChild->m_NextSibling)
+ MaybeQueueNodeForRender(*theChild, m_RenderableNodes, m_CamerasAndLights,
+ dfsIndex);
+ reverse(m_CamerasAndLights.begin(), m_CamerasAndLights.end());
+ reverse(m_RenderableNodes.begin(), m_RenderableNodes.end());
+ m_LightToNodeMap.clear();
+ }
+ m_Camera = NULL;
+ m_Lights.clear();
+ m_OpaqueObjects.clear();
+ m_TransparentObjects.clear();
+ nvvector<SLightNodeMarker> theLightNodeMarkers(m_Renderer.GetPerFrameAllocator(),
+ "LightNodeMarkers");
+ m_SourceLightDirections.clear();
+
+ for (QT3DSU32 idx = 0, end = m_CamerasAndLights.size(); idx < end; ++idx) {
+ SNode *theNode(m_CamerasAndLights[idx]);
+ wasDataDirty = wasDataDirty || theNode->m_Flags.IsDirty();
+ switch (theNode->m_Type) {
+ case GraphObjectTypes::Camera: {
+ SCamera *theCamera = static_cast<SCamera *>(theNode);
+ SCameraGlobalCalculationResult theResult =
+ thePrepResult.SetupCameraForRender(*theCamera);
+ wasDataDirty = wasDataDirty || theResult.m_WasDirty;
+ if (theCamera->m_Flags.IsGloballyActive())
+ m_Camera = theCamera;
+ if (theResult.m_ComputeFrustumSucceeded == false) {
+ qCCritical(INTERNAL_ERROR, "Failed to calculate camera frustum");
+ }
+ } break;
+ case GraphObjectTypes::Light: {
+ SLight *theLight = static_cast<SLight *>(theNode);
+ bool lightResult = theLight->CalculateGlobalVariables();
+ wasDataDirty = lightResult || wasDataDirty;
+ // Note we setup the light index such that it is completely invariant of if
+ // the
+ // light is active or scoped.
+ QT3DSU32 lightIndex = (QT3DSU32)m_SourceLightDirections.size();
+ m_SourceLightDirections.push_back(QT3DSVec3(0.0f));
+ // Note we still need a light check when building the renderable light list.
+ // We also cannot cache shader-light bindings based on layers any more
+ // because
+ // the number of lights for a given renderable does not depend on the layer
+ // as it used to but
+ // additional perhaps on the light's scoping rules.
+ if (theLight->m_Flags.IsGloballyActive()) {
+ if (theLight->m_Scope == NULL) {
+ m_Lights.push_back(theLight);
+
+ if (theLight->m_CastShadow && GetShadowMapManager()) {
+ // PKC -- use of "res" as an exponent of two is an annoying
+ // artifact of the XML interface
+ // I'll change this with an enum interface later on, but that's
+ // less important right now.
+ QT3DSU32 mapSize = 1 << theLight->m_ShadowMapRes;
+ ShadowMapModes::Enum mapMode =
+ (theLight->m_LightType != RenderLightTypes::Directional)
+ ? ShadowMapModes::CUBE
+ : ShadowMapModes::VSM;
+ m_ShadowMapManager->AddShadowMapEntry(
+ m_Lights.size() - 1, mapSize, mapSize,
+ NVRenderTextureFormats::R16, 1, mapMode,
+ ShadowFilterValues::NONE);
+
+ thePrepResult.m_Flags.SetRequiresShadowMapPass(true);
+ SetShaderFeature("UIC_ENABLE_SSM", true);
+ }
+ }
+ TLightToNodeMap::iterator iter =
+ m_LightToNodeMap.insert(eastl::make_pair(theLight, (SNode *)NULL))
+ .first;
+ SNode *oldLightScope = iter->second;
+ SNode *newLightScope = theLight->m_Scope;
+
+ if (oldLightScope != newLightScope) {
+ iter->second = newLightScope;
+ if (oldLightScope)
+ theLightNodeMarkers.push_back(SLightNodeMarker(
+ *theLight, lightIndex, *oldLightScope, false));
+ if (newLightScope)
+ theLightNodeMarkers.push_back(SLightNodeMarker(
+ *theLight, lightIndex, *newLightScope, true));
+ }
+ if (newLightScope) {
+ m_SourceLightDirections.back() =
+ theLight->GetScalingCorrectDirection();
+ }
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ if (theLightNodeMarkers.empty() == false) {
+ for (QT3DSU32 idx = 0, end = m_RenderableNodes.size(); idx < end; ++idx) {
+ SRenderableNodeEntry &theNodeEntry(m_RenderableNodes[idx]);
+ QT3DSU32 nodeDFSIndex = theNodeEntry.m_Node->m_DFSIndex;
+ for (QT3DSU32 markerIdx = 0, markerEnd = theLightNodeMarkers.size();
+ markerIdx < markerEnd; ++markerIdx) {
+ SLightNodeMarker &theMarker = theLightNodeMarkers[markerIdx];
+ if (nodeDFSIndex >= theMarker.m_FirstValidIndex
+ && nodeDFSIndex < theMarker.m_JustPastLastValidIndex) {
+ if (theMarker.m_AddOrRemove) {
+ SNodeLightEntry *theNewEntry =
+ m_RenderableNodeLightEntryPool.construct(
+ theMarker.m_Light, theMarker.m_LightIndex, __FILE__,
+ __LINE__);
+ theNodeEntry.m_Lights.push_back(*theNewEntry);
+ } else {
+ for (TNodeLightEntryList::iterator
+ lightIter = theNodeEntry.m_Lights.begin(),
+ lightEnd = theNodeEntry.m_Lights.end();
+ lightIter != lightEnd; ++lightIter) {
+ if (lightIter->m_Light == theMarker.m_Light) {
+ SNodeLightEntry &theEntry = *lightIter;
+ theNodeEntry.m_Lights.remove(theEntry);
+ m_RenderableNodeLightEntryPool.deallocate(&theEntry);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ QT3DSF32 theTextScaleFactor = 1.0f;
+ if (m_Camera) {
+ m_Camera->CalculateViewProjectionMatrix(m_ViewProjection);
+ theTextScaleFactor = m_Camera->GetTextScaleFactor(
+ thePrepResult.GetLayerToPresentationViewport(),
+ thePrepResult.GetPresentationDesignDimensions());
+ SClipPlane nearPlane;
+ QT3DSMat33 theUpper33(m_Camera->m_GlobalTransform.getUpper3x3InverseTranspose());
+
+ QT3DSVec3 dir(theUpper33.transform(QT3DSVec3(0, 0, -1)));
+ dir.normalize();
+ nearPlane.normal = dir;
+ QT3DSVec3 theGlobalPos = m_Camera->GetGlobalPos() + m_Camera->m_ClipNear * dir;
+ nearPlane.d = -(dir.dot(theGlobalPos));
+ // the near plane's bbox edges are calculated in the clipping frustum's
+ // constructor.
+ m_ClippingFrustum = SClippingFrustum(m_ViewProjection, nearPlane);
+ } else
+ m_ViewProjection = QT3DSMat44::createIdentity();
+
+ // Setup the light directions here.
+
+ for (QT3DSU32 lightIdx = 0, lightEnd = m_Lights.size(); lightIdx < lightEnd;
+ ++lightIdx) {
+ m_LightDirections.push_back(m_Lights[lightIdx]->GetScalingCorrectDirection());
+ }
+
+ m_ModelContexts.clear();
+ if (GetOffscreenRenderer() == false) {
+ bool renderablesDirty =
+ PrepareRenderablesForRender(m_ViewProjection, m_ClippingFrustum,
+ theTextScaleFactor, thePrepResult.m_Flags);
+ wasDataDirty = wasDataDirty || renderablesDirty;
+ if (thePrepResult.m_Flags.RequiresStencilBuffer())
+ thePrepResult.m_Flags.SetShouldRenderToTexture(true);
+ } else {
+ NVRenderRect theViewport =
+ thePrepResult.GetLayerToPresentationViewport().ToIntegerRect();
+ bool theScissor = true;
+ NVRenderRect theScissorRect =
+ thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect();
+ // This happens here because if there are any fancy render steps
+ IRenderList &theRenderList(m_Renderer.GetUICContext().GetRenderList());
+ NVRenderContext &theContext(m_Renderer.GetContext());
+ SRenderListScopedProperty<bool> _listScissorEnabled(
+ theRenderList, &IRenderList::IsScissorTestEnabled,
+ &IRenderList::SetScissorTestEnabled, theScissor);
+ SRenderListScopedProperty<NVRenderRect> _listViewport(
+ theRenderList, &IRenderList::GetViewport, &IRenderList::SetViewport,
+ theViewport);
+ SRenderListScopedProperty<NVRenderRect> _listScissor(
+ theRenderList, &IRenderList::GetScissor, &IRenderList::SetScissorRect,
+ theScissorRect);
+ // Some plugins don't use the render list so they need the actual gl context
+ // setup.
+ qt3ds::render::NVRenderContextScopedProperty<bool> __scissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled, true);
+ qt3ds::render::NVRenderContextScopedProperty<NVRenderRect> __scissorRect(
+ theContext, &NVRenderContext::GetScissorRect,
+ &NVRenderContext::SetScissorRect, theScissorRect);
+ qt3ds::render::NVRenderContextScopedProperty<NVRenderRect> __viewportRect(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport,
+ theViewport);
+ SOffscreenRenderFlags theResult = m_LastFrameOffscreenRenderer->NeedsRender(
+ CreateOffscreenRenderEnvironment(),
+ m_Renderer.GetUICContext().GetPresentationScaleFactor());
+ wasDataDirty = wasDataDirty || theResult.m_HasChangedSinceLastFrame;
+ }
+ }
+ }
+ wasDirty = wasDirty || wasDataDirty;
+ thePrepResult.m_Flags.SetWasDirty(wasDirty);
+ thePrepResult.m_Flags.SetLayerDataDirty(wasDataDirty);
+
+ m_LayerPrepResult = thePrepResult;
+
+ // Per-frame cache of renderable objects post-sort.
+ GetOpaqueRenderableObjects();
+ // If layer depth test is false, this may also contain opaque objects.
+ GetTransparentRenderableObjects();
+
+ GetCameraDirection();
+ }
+
+ void SLayerRenderPreparationData::ResetForFrame()
+ {
+ m_TransparentObjects.clear_unsafe();
+ m_OpaqueObjects.clear_unsafe();
+ m_LayerPrepResult.setEmpty();
+ // The check for if the camera is or is not null is used
+ // to figure out if this layer was rendered at all.
+ m_Camera = NULL;
+ m_LastFrameOffscreenRenderer = NULL;
+ m_IRenderWidgets.clear_unsafe();
+ m_CameraDirection.setEmpty();
+ m_LightDirections.clear_unsafe();
+ m_RenderedOpaqueObjects.clear_unsafe();
+ m_RenderedTransparentObjects.clear_unsafe();
+ }
+}
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.h b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.h
new file mode 100644
index 00000000..c2edd416
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplLayerRenderPreparationData.h
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDERER_IMPL_LAYER_RENDER_PREPARATION_DATA_H
+#define UIC_RENDERER_IMPL_LAYER_RENDER_PREPARATION_DATA_H
+#include "UICRender.h"
+#include "foundation/Qt3DSFlags.h"
+#include "UICRendererImplLayerRenderHelper.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderableObjects.h"
+#include "UICRenderClippingFrustum.h"
+#include "UICRenderResourceTexture2D.h"
+#include "UICOffscreenRenderManager.h"
+#include "UICRenderProfiler.h"
+#include "UICRenderShadowMap.h"
+#include "foundation/Qt3DSPool.h"
+#include "UICRenderableObjects.h"
+
+namespace uic {
+namespace render {
+ struct SLayerRenderData;
+ class CUICRendererImpl;
+ struct SRenderableObject;
+
+ struct LayerRenderPreparationResultFlagValues
+ {
+ enum Enum {
+ // Was the data in this layer dirty (meaning re-render to texture, possibly)
+ WasLayerDataDirty = 1,
+ // Was the data in this layer dirty *or* this layer *or* any effect dirty.
+ WasDirty = 1 << 1,
+ // An effect or flag or rotation on the layer dictates this object should
+ // render to the texture.
+ ShouldRenderToTexture = 1 << 2,
+ // Some effects require depth texturing, this should be set on the effect
+ // instance.
+ RequiresDepthTexture = 1 << 3,
+
+ // Should create independent viewport
+ // If we aren't rendering to texture we still may have width/height manipulations
+ // that require our own viewport.
+ ShouldCreateIndependentViewport = 1 << 4,
+
+ // SSAO should be done in a separate pass
+ // Note that having an AO pass necessitates a DepthTexture so this flag should
+ // never be set without the RequiresDepthTexture flag as well.
+ RequiresSsaoPass = 1 << 5,
+
+ // if some light cause shadow
+ // we need a separate per light shadow map pass
+ RequiresShadowMapPass = 1 << 6,
+
+ // Currently we use a stencil-cover algorithm to render bezier curves.
+ RequiresStencilBuffer = 1 << 7
+ };
+ };
+
+ struct SLayerRenderPreparationResultFlags
+ : public NVFlags<LayerRenderPreparationResultFlagValues::Enum, QT3DSU32>
+ {
+ bool WasLayerDataDirty() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::WasLayerDataDirty);
+ }
+ void SetLayerDataDirty(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::WasLayerDataDirty);
+ }
+
+ bool WasDirty() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::WasDirty);
+ }
+ void SetWasDirty(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::WasDirty);
+ }
+
+ bool ShouldRenderToTexture() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::ShouldRenderToTexture);
+ }
+ void SetShouldRenderToTexture(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::ShouldRenderToTexture);
+ }
+
+ bool RequiresDepthTexture() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::RequiresDepthTexture);
+ }
+ void SetRequiresDepthTexture(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::RequiresDepthTexture);
+ }
+
+ bool ShouldCreateIndependentViewport() const
+ {
+ return this->operator&(
+ LayerRenderPreparationResultFlagValues::ShouldCreateIndependentViewport);
+ }
+ void SetShouldCreateIndependentViewport(bool inValue)
+ {
+ clearOrSet(inValue,
+ LayerRenderPreparationResultFlagValues::ShouldCreateIndependentViewport);
+ }
+
+ bool RequiresSsaoPass() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::RequiresSsaoPass);
+ }
+ void SetRequiresSsaoPass(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::RequiresSsaoPass);
+ }
+
+ bool RequiresShadowMapPass() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::RequiresShadowMapPass);
+ }
+ void SetRequiresShadowMapPass(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::RequiresShadowMapPass);
+ }
+
+ bool RequiresStencilBuffer() const
+ {
+ return this->operator&(LayerRenderPreparationResultFlagValues::RequiresStencilBuffer);
+ }
+ void SetRequiresStencilBuffer(bool inValue)
+ {
+ clearOrSet(inValue, LayerRenderPreparationResultFlagValues::RequiresStencilBuffer);
+ }
+ };
+
+ struct SLayerRenderPreparationResult : public SLayerRenderHelper
+ {
+ SEffect *m_LastEffect;
+ SLayerRenderPreparationResultFlags m_Flags;
+ QT3DSU32 m_MaxAAPassIndex;
+ SLayerRenderPreparationResult()
+ : m_LastEffect(NULL)
+ , m_MaxAAPassIndex(0)
+ {
+ }
+ SLayerRenderPreparationResult(const SLayerRenderHelper &inHelper)
+ : SLayerRenderHelper(inHelper)
+ , m_LastEffect(NULL)
+ , m_MaxAAPassIndex(0)
+ {
+ }
+ };
+
+ struct SRenderableNodeEntry
+ {
+ SNode *m_Node;
+ TNodeLightEntryList m_Lights;
+ SRenderableNodeEntry()
+ : m_Node(NULL)
+ {
+ }
+ SRenderableNodeEntry(SNode &inNode)
+ : m_Node(&inNode)
+ {
+ }
+ };
+
+ struct SScopedLightsListScope
+ {
+ nvvector<SLight *> &m_LightsList;
+ nvvector<QT3DSVec3> &m_LightDirList;
+ QT3DSU32 m_ListOriginalSize;
+ SScopedLightsListScope(nvvector<SLight *> &inLights, nvvector<QT3DSVec3> &inDestLightDirList,
+ nvvector<QT3DSVec3> &inSrcLightDirList,
+ TNodeLightEntryList &inScopedLights)
+ : m_LightsList(inLights)
+ , m_LightDirList(inDestLightDirList)
+ , m_ListOriginalSize(m_LightsList.size())
+ {
+ for (TNodeLightEntryList::iterator iter = inScopedLights.begin(),
+ end = inScopedLights.end();
+ iter != end; ++iter) {
+ m_LightsList.push_back(iter->m_Light);
+ m_LightDirList.push_back(inSrcLightDirList[iter->m_LightIndex]);
+ }
+ }
+ ~SScopedLightsListScope()
+ {
+ m_LightsList.resize(m_ListOriginalSize);
+ m_LightDirList.resize(m_ListOriginalSize);
+ }
+ };
+
+ struct SDefaultMaterialPreparationResult
+ {
+ SRenderableImage *m_FirstImage;
+ QT3DSF32 m_Opacity;
+ SRenderableObjectFlags m_RenderableFlags;
+ SShaderDefaultMaterialKey m_MaterialKey;
+ bool m_Dirty;
+
+ SDefaultMaterialPreparationResult(SShaderDefaultMaterialKey inMaterialKey);
+ };
+
+ // Data used strictly in the render preparation step.
+ struct SLayerRenderPreparationData
+ {
+ typedef void (*TRenderRenderableFunction)(SLayerRenderData &inData,
+ SRenderableObject &inObject,
+ const QT3DSVec2 &inCameraProps,
+ TShaderFeatureSet inShaderFeatures,
+ QT3DSU32 lightIndex, const SCamera &inCamera);
+ typedef nvhash_map<SLight *, SNode *> TLightToNodeMap;
+ typedef Pool<SNodeLightEntry, ForwardingAllocator> TNodeLightEntryPoolType;
+
+ enum Enum {
+ MAX_AA_LEVELS = 8,
+ MAX_TEMPORAL_AA_LEVELS = 2,
+ };
+
+ SLayer &m_Layer;
+ CUICRendererImpl &m_Renderer;
+ NVAllocatorCallback &m_Allocator;
+ // List of nodes we can render, not all may be active. Found by doing a depth-first
+ // search through m_FirstChild if length is zero.
+
+ TNodeLightEntryPoolType m_RenderableNodeLightEntryPool;
+ nvvector<SRenderableNodeEntry> m_RenderableNodes;
+ TLightToNodeMap m_LightToNodeMap; // map of lights to nodes to cache if we have looked up a
+ // given scoped light yet.
+ // Built at the same time as the renderable nodes map.
+ // these are processed so they are available when the shaders for the models
+ // are being generated.
+ nvvector<SNode *> m_CamerasAndLights;
+
+ // Results of prepare for render.
+ SCamera *m_Camera;
+ nvvector<SLight *> m_Lights; // Only contains lights that are global.
+ TRenderableObjectList m_OpaqueObjects;
+ TRenderableObjectList m_TransparentObjects;
+ // Sorted lists of the rendered objects. There may be other transforms applied so
+ // it is simplest to duplicate the lists.
+ TRenderableObjectList m_RenderedOpaqueObjects;
+ TRenderableObjectList m_RenderedTransparentObjects;
+ QT3DSMat44 m_ViewProjection;
+ SClippingFrustum m_ClippingFrustum;
+ Option<SLayerRenderPreparationResult> m_LayerPrepResult;
+ // Widgets drawn at particular times during the rendering process
+ nvvector<IRenderWidget *> m_IRenderWidgets;
+ Option<QT3DSVec3> m_CameraDirection;
+ // Scoped lights need a level of indirection into a light direction list. The source light
+ // directions list is as long as there are lights on the layer. It holds invalid
+ // information for
+ // any lights that are not both active and scoped; but the relative position for a given
+ // light
+ // in this list is completely constant and immutable; this relative position is saved on a
+ // structure
+ // and used when looking up the light direction for a given light.
+ nvvector<QT3DSVec3> m_SourceLightDirections;
+ nvvector<QT3DSVec3> m_LightDirections;
+ TModelContextPtrList m_ModelContexts;
+ NVScopedRefCounted<IOffscreenRenderer> m_LastFrameOffscreenRenderer;
+
+ eastl::vector<SShaderPreprocessorFeature> m_Features;
+ CRegisteredString m_CGLightingFeatureName;
+ bool m_FeaturesDirty;
+ size_t m_FeatureSetHash;
+ bool m_TooManyLightsError;
+
+ // shadow mapps
+ NVScopedRefCounted<UICShadowMap> m_ShadowMapManager;
+
+ SLayerRenderPreparationData(SLayer &inLayer, CUICRendererImpl &inRenderer);
+ virtual ~SLayerRenderPreparationData();
+ bool GetOffscreenRenderer();
+ bool GetShadowMapManager();
+ bool NeedsWidgetTexture() const;
+
+ SShaderDefaultMaterialKey GenerateLightingKey(DefaultMaterialLighting::Enum inLightingType);
+
+ void PrepareImageForRender(SImage &inImage, ImageMapTypes::Enum inMapType,
+ SRenderableImage *&ioFirstImage, SRenderableImage *&ioNextImage,
+ SRenderableObjectFlags &ioFlags,
+ SShaderDefaultMaterialKey &ioGeneratedShaderKey,
+ QT3DSU32 inImageIndex);
+
+ SDefaultMaterialPreparationResult
+ PrepareDefaultMaterialForRender(SDefaultMaterial &inMaterial,
+ SRenderableObjectFlags &inExistingFlags, QT3DSF32 inOpacity,
+ bool inClearMaterialFlags);
+
+ SDefaultMaterialPreparationResult
+ PrepareCustomMaterialForRender(SCustomMaterial &inMaterial,
+ SRenderableObjectFlags &inExistingFlags, QT3DSF32 inOpacity);
+
+ bool PrepareModelForRender(SModel &inModel, const QT3DSMat44 &inViewProjection,
+ const Option<SClippingFrustum> &inClipFrustum,
+ TNodeLightEntryList &inScopedLights);
+
+ bool PrepareTextForRender(SText &inText, const QT3DSMat44 &inViewProjection,
+ QT3DSF32 inTextScaleFactor,
+ SLayerRenderPreparationResultFlags &ioFlags);
+ bool PreparePathForRender(SPath &inPath, const QT3DSMat44 &inViewProjection,
+ const Option<SClippingFrustum> &inClipFrustum,
+ SLayerRenderPreparationResultFlags &ioFlags);
+ // Helper function used during PRepareForRender and PrepareAndRender
+ bool PrepareRenderablesForRender(const QT3DSMat44 &inViewProjection,
+ const Option<SClippingFrustum> &inClipFrustum,
+ QT3DSF32 inTextScaleFactor,
+ SLayerRenderPreparationResultFlags &ioFlags);
+
+ // returns true if this object will render something different than it rendered the last
+ // time.
+ virtual void PrepareForRender(const SWindowDimensions &inViewportDimensions);
+ bool CheckLightProbeDirty(SImage &inLightProbe);
+ void AddRenderWidget(IRenderWidget &inWidget);
+ void SetShaderFeature(const char *inName, bool inValue);
+ void SetShaderFeature(CRegisteredString inName, bool inValue);
+ NVConstDataRef<SShaderPreprocessorFeature> GetShaderFeatureSet();
+ size_t GetShaderFeatureSetHash();
+ // The graph object is not const because this traversal updates dirty state on the objects.
+ eastl::pair<bool, SGraphObject *> ResolveReferenceMaterial(SGraphObject *inMaterial);
+
+ QT3DSVec3 GetCameraDirection();
+ // Per-frame cache of renderable objects post-sort.
+ NVDataRef<SRenderableObject *> GetOpaqueRenderableObjects();
+ // If layer depth test is false, this may also contain opaque objects.
+ NVDataRef<SRenderableObject *> GetTransparentRenderableObjects();
+
+ virtual void ResetForFrame();
+
+ // The render list and gl context are setup for what the embedded item will
+ // need.
+ virtual SOffscreenRendererEnvironment CreateOffscreenRenderEnvironment() = 0;
+
+ virtual IRenderTask &CreateRenderToTextureRunnable() = 0;
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp
new file mode 100644
index 00000000..a9a9a947
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.cpp
@@ -0,0 +1,2964 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRendererImpl.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICRenderLight.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+#include "../RendererImpl/UICVertexPipelineImpl.h"
+
+// This adds support for the depth buffers in the shader so we can do depth
+// texture-based effects.
+#define UIC_RENDER_SUPPORT_DEPTH_TEXTURE 1
+
+namespace uic {
+namespace render {
+
+ void STextShader::Render(NVRenderTexture2D &inTexture,
+ const STextScaleAndOffset &inScaleAndOffset, const QT3DSVec4 &inTextColor,
+ const QT3DSMat44 &inMVP, const QT3DSVec2 &inCameraVec,
+ NVRenderContext &inRenderContext,
+ NVRenderInputAssembler &inInputAssemblerBuffer, QT3DSU32 count,
+ const STextTextureDetails &inTextTextureDetails,
+ const QT3DSVec3 &inBackgroundColor)
+ {
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(&m_Shader);
+ m_MVP.Set(inMVP);
+ m_Sampler.Set(&inTexture);
+ m_TextColor.Set(inTextColor);
+ m_Dimensions.Set(QT3DSVec4(inScaleAndOffset.m_TextScale.x, inScaleAndOffset.m_TextScale.y,
+ inScaleAndOffset.m_TextOffset.x, inScaleAndOffset.m_TextOffset.y));
+ m_CameraProperties.Set(inCameraVec);
+ STextureDetails theTextureDetails = inTexture.GetTextureDetails();
+ QT3DSF32 theWidthScale =
+ (QT3DSF32)inTextTextureDetails.m_TextWidth / (QT3DSF32)theTextureDetails.m_Width;
+ QT3DSF32 theHeightScale =
+ (QT3DSF32)inTextTextureDetails.m_TextHeight / (QT3DSF32)theTextureDetails.m_Height;
+ m_BackgroundColor.Set(inBackgroundColor);
+
+ m_TextDimensions.Set(
+ QT3DSVec3(theWidthScale, theHeightScale, inTextTextureDetails.m_FlipY ? 1.0f : 0.0f));
+ inRenderContext.SetInputAssembler(&inInputAssemblerBuffer);
+ inRenderContext.Draw(NVRenderDrawMode::Triangles, count, 0);
+ }
+
+ void STextShader::RenderPath(NVRenderPathFontItem &inPathFontItem,
+ NVRenderPathFontSpecification &inPathFontSpec,
+ const STextScaleAndOffset &inScaleAndOffset,
+ const QT3DSVec4 &inTextColor, const QT3DSMat44 &inViewProjection,
+ const QT3DSMat44 &inModel, const QT3DSVec2 &,
+ NVRenderContext &inRenderContext,
+ const STextTextureDetails &inTextTextureDetails,
+ const QT3DSVec3 &inBackgroundColor)
+ {
+ qt3ds::render::NVRenderBoolOp::Enum theDepthFunction = inRenderContext.GetDepthFunction();
+ bool isDepthEnabled = inRenderContext.IsDepthTestEnabled();
+ bool isStencilEnabled = inRenderContext.IsStencilTestEnabled();
+ bool isDepthWriteEnabled = inRenderContext.IsDepthWriteEnabled();
+ qt3ds::render::NVRenderStencilFunctionArgument theArg(qt3ds::render::NVRenderBoolOp::NotEqual, 0,
+ 0xFF);
+ qt3ds::render::NVRenderStencilOperationArgument theOpArg(qt3ds::render::NVRenderStencilOp::Keep,
+ qt3ds::render::NVRenderStencilOp::Keep,
+ qt3ds::render::NVRenderStencilOp::Zero);
+ NVScopedRefCounted<NVRenderDepthStencilState> depthStencilState =
+ inRenderContext.CreateDepthStencilState(isDepthEnabled, isDepthWriteEnabled,
+ theDepthFunction, false, theArg, theArg,
+ theOpArg, theOpArg);
+
+ inRenderContext.SetActiveShader(NULL);
+ inRenderContext.SetCullingEnabled(false);
+
+ inRenderContext.SetDepthStencilState(depthStencilState);
+
+ // setup transform
+ QT3DSMat44 offsetMatrix = QT3DSMat44::createIdentity();
+ offsetMatrix.setPosition(QT3DSVec3(
+ inScaleAndOffset.m_TextOffset.x - (QT3DSF32)inTextTextureDetails.m_TextWidth / 2.0f,
+ inScaleAndOffset.m_TextOffset.y - (QT3DSF32)inTextTextureDetails.m_TextHeight / 2.0f,
+ 0.0));
+
+ QT3DSMat44 pathMatrix = inPathFontItem.GetTransform();
+
+ inRenderContext.SetPathProjectionMatrix(inViewProjection);
+ inRenderContext.SetPathModelViewMatrix(inModel * offsetMatrix * pathMatrix);
+
+ // first pass
+ inPathFontSpec.StencilFillPathInstanced(inPathFontItem);
+
+ // second pass
+ inRenderContext.SetActiveProgramPipeline(m_ProgramPipeline);
+ m_TextColor.Set(inTextColor);
+ m_BackgroundColor.Set(inBackgroundColor);
+
+ inRenderContext.SetStencilTestEnabled(true);
+ inPathFontSpec.CoverFillPathInstanced(inPathFontItem);
+
+ inRenderContext.SetStencilTestEnabled(isStencilEnabled);
+ inRenderContext.SetDepthFunction(theDepthFunction);
+
+ inRenderContext.SetActiveProgramPipeline(NULL);
+ }
+
+ void STextShader::Render2D(NVRenderTexture2D &inTexture, const QT3DSVec4 &inTextColor,
+ const QT3DSMat44 &inMVP, NVRenderContext &inRenderContext,
+ NVRenderInputAssembler &inInputAssemblerBuffer, QT3DSU32 count,
+ QT3DSVec2 inVertexOffsets)
+ {
+ // inRenderContext.SetCullingEnabled( false );
+ inRenderContext.SetBlendingEnabled(true);
+ inRenderContext.SetDepthWriteEnabled(false);
+ inRenderContext.SetDepthTestEnabled(false);
+
+ inRenderContext.SetActiveShader(&m_Shader);
+
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc(
+ NVRenderSrcBlendFunc::SrcAlpha, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+
+ inRenderContext.SetBlendFunction(blendFunc);
+ inRenderContext.SetBlendEquation(blendEqu);
+
+ m_MVP.Set(inMVP);
+ m_Sampler.Set(&inTexture);
+ m_TextColor.Set(inTextColor);
+ m_VertexOffsets.Set(inVertexOffsets);
+
+ inRenderContext.SetInputAssembler(&inInputAssemblerBuffer);
+ inRenderContext.Draw(NVRenderDrawMode::Triangles, count, 0);
+ }
+
+ using eastl::make_pair;
+
+ static inline void AddVertexDepth(SShaderVertexCodeGenerator &vertexShader)
+ {
+ // near plane, far plane
+ vertexShader.AddInclude("viewProperties.glsllib");
+ vertexShader.AddVarying("vertex_depth", "float");
+ // the w coordinate is the unormalized distance to the object from the camera
+ // We want the normalized distance, with 0 representing the far plane and 1 representing
+ // the near plane, of the object in the vertex depth variable.
+
+ vertexShader << "\tvertex_depth = calculateVertexDepth( camera_properties, gl_Position );"
+ << Endl;
+ }
+
+ // Helper implements the vertex pipeline for mesh subsets when bound to the default material.
+ // Should be completely possible to use for custom materials with a bit of refactoring.
+ struct SSubsetMaterialVertexPipeline : public SVertexPipelineImpl
+ {
+ CUICRendererImpl &m_Renderer;
+ SSubsetRenderable &m_Renderable;
+ TessModeValues::Enum m_TessMode;
+
+ SSubsetMaterialVertexPipeline(CUICRendererImpl &renderer, SSubsetRenderable &renderable,
+ bool inWireframeRequested)
+ : SVertexPipelineImpl(renderer.GetUICContext().GetAllocator(),
+ renderer.GetUICContext().GetDefaultMaterialShaderGenerator(),
+ renderer.GetUICContext().GetShaderProgramGenerator(),
+ renderer.GetUICContext().GetStringTable(), false)
+ , m_Renderer(renderer)
+ , m_Renderable(renderable)
+ , m_TessMode(TessModeValues::NoTess)
+ {
+ if (m_Renderer.GetContext().IsTessellationSupported()) {
+ m_TessMode = renderable.m_TessellationMode;
+ }
+
+ if (m_Renderer.GetContext().IsGeometryStageSupported()
+ && m_TessMode != TessModeValues::NoTess)
+ m_Wireframe = inWireframeRequested;
+ }
+
+ void InitializeTessControlShader()
+ {
+ if (m_TessMode == TessModeValues::NoTess
+ || ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl) == NULL)
+ return;
+
+ IShaderStageGenerator &tessCtrlShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+
+ SetupTessIncludes(ShaderGeneratorStages::TessControl, m_TessMode);
+
+ tessCtrlShader.Append("void main() {\n");
+
+ tessCtrlShader.Append("\tctWorldPos[0] = varWorldPos[0];");
+ tessCtrlShader.Append("\tctWorldPos[1] = varWorldPos[1];");
+ tessCtrlShader.Append("\tctWorldPos[2] = varWorldPos[2];");
+
+ if (m_TessMode == TessModeValues::TessPhong
+ || m_TessMode == TessModeValues::TessNPatch) {
+ tessCtrlShader.Append("\tctNorm[0] = varObjectNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = varObjectNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = varObjectNormal[2];");
+ }
+ if (m_TessMode == TessModeValues::TessNPatch) {
+ tessCtrlShader.Append("\tctTangent[0] = varTangent[0];");
+ tessCtrlShader.Append("\tctTangent[1] = varTangent[1];");
+ tessCtrlShader.Append("\tctTangent[2] = varTangent[2];");
+ }
+
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ }
+ void InitializeTessEvaluationShader()
+ {
+ if (m_TessMode == TessModeValues::NoTess
+ || ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval) == NULL)
+ return;
+
+ IShaderStageGenerator &tessEvalShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ SetupTessIncludes(ShaderGeneratorStages::TessEval, m_TessMode);
+
+ if (m_TessMode == TessModeValues::TessLinear)
+ m_Renderer.GetUICContext()
+ .GetDefaultMaterialShaderGenerator()
+ .AddDisplacementImageUniforms(tessEvalShader, m_DisplacementIdx,
+ m_DisplacementImage);
+
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddUniform("normal_matrix", "mat3");
+
+ tessEvalShader.Append("void main() {");
+
+ if (m_TessMode == TessModeValues::TessNPatch) {
+ tessEvalShader.Append("\tctNorm[0] = varObjectNormalTC[0];");
+ tessEvalShader.Append("\tctNorm[1] = varObjectNormalTC[1];");
+ tessEvalShader.Append("\tctNorm[2] = varObjectNormalTC[2];");
+
+ tessEvalShader.Append("\tctTangent[0] = varTangentTC[0];");
+ tessEvalShader.Append("\tctTangent[1] = varTangentTC[1];");
+ tessEvalShader.Append("\tctTangent[2] = varTangentTC[2];");
+ }
+
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ }
+
+ void FinalizeTessControlShader()
+ {
+ IShaderStageGenerator &tessCtrlShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ // add varyings we must pass through
+ typedef TStrTableStrMap::const_iterator TParamIter;
+ for (TParamIter iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ tessCtrlShader << "\t" << iter->first.c_str()
+ << "TC[gl_InvocationID] = " << iter->first.c_str()
+ << "[gl_InvocationID];\n";
+ }
+ }
+
+ void FinalizeTessEvaluationShader()
+ {
+ IShaderStageGenerator &tessEvalShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ eastl::string outExt("");
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
+ outExt = "TE";
+
+ // add varyings we must pass through
+ typedef TStrTableStrMap::const_iterator TParamIter;
+ if (m_TessMode == TessModeValues::TessNPatch) {
+ for (TParamIter iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ tessEvalShader << "\t" << iter->first.c_str() << outExt.c_str()
+ << " = gl_TessCoord.z * " << iter->first.c_str() << "TC[0] + ";
+ tessEvalShader << "gl_TessCoord.x * " << iter->first.c_str() << "TC[1] + ";
+ tessEvalShader << "gl_TessCoord.y * " << iter->first.c_str() << "TC[2];\n";
+ }
+
+ // transform the normal
+ if (m_GenerationFlags & GenerationFlagValues::WorldNormal)
+ tessEvalShader << "\n\tvarNormal" << outExt.c_str()
+ << " = normalize(normal_matrix * teNorm);\n";
+ // transform the tangent
+ if (m_GenerationFlags & GenerationFlagValues::TangentBinormal) {
+ tessEvalShader << "\n\tvarTangent" << outExt.c_str()
+ << " = normalize(normal_matrix * teTangent);\n";
+ // transform the binormal
+ tessEvalShader << "\n\tvarBinormal" << outExt.c_str()
+ << " = normalize(normal_matrix * teBinormal);\n";
+ }
+ } else {
+ for (TParamIter iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ tessEvalShader << "\t" << iter->first.c_str() << outExt.c_str()
+ << " = gl_TessCoord.x * " << iter->first.c_str() << "TC[0] + ";
+ tessEvalShader << "gl_TessCoord.y * " << iter->first.c_str() << "TC[1] + ";
+ tessEvalShader << "gl_TessCoord.z * " << iter->first.c_str() << "TC[2];\n";
+ }
+
+ // displacement mapping makes only sense with linear tessellation
+ if (m_TessMode == TessModeValues::TessLinear && m_DisplacementImage) {
+ IDefaultMaterialShaderGenerator::SImageVariableNames theNames =
+ m_Renderer.GetUICContext()
+ .GetDefaultMaterialShaderGenerator()
+ .GetImageVariableNames(m_DisplacementIdx);
+ tessEvalShader << "\tpos.xyz = uicDefaultMaterialFileDisplacementTexture( "
+ << theNames.m_ImageSampler << ", displaceAmount, "
+ << theNames.m_ImageFragCoords << outExt.c_str();
+ tessEvalShader << ", varObjectNormal" << outExt.c_str() << ", pos.xyz );"
+ << Endl;
+ tessEvalShader << "\tvarWorldPos" << outExt.c_str()
+ << "= (model_matrix * pos).xyz;" << Endl;
+ tessEvalShader << "\tvarViewVector" << outExt.c_str()
+ << "= normalize(camera_position - "
+ << "varWorldPos" << outExt.c_str() << ");" << Endl;
+ }
+
+ // transform the normal
+ tessEvalShader << "\n\tvarNormal" << outExt.c_str()
+ << " = normalize(normal_matrix * varObjectNormal" << outExt.c_str()
+ << ");\n";
+ }
+
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n");
+ }
+
+ void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) override
+ {
+ m_DisplacementIdx = displacementImageIdx;
+ m_DisplacementImage = displacementImage;
+
+ TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
+ if (m_TessMode != TessModeValues::NoTess) {
+ theStages |= ShaderGeneratorStages::TessControl;
+ theStages |= ShaderGeneratorStages::TessEval;
+ }
+ if (m_Wireframe) {
+ theStages |= ShaderGeneratorStages::Geometry;
+ }
+ ProgramGenerator().BeginProgram(theStages);
+ if (m_TessMode != TessModeValues::NoTess) {
+ InitializeTessControlShader();
+ InitializeTessEvaluationShader();
+ }
+ if (m_Wireframe) {
+ InitializeWireframeGeometryShader();
+ }
+ // Open up each stage.
+ IShaderStageGenerator &vertexShader(Vertex());
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader << "void main()" << Endl << "{" << Endl;
+ vertexShader << "\tvec3 uTransform;" << Endl;
+ vertexShader << "\tvec3 vTransform;" << Endl;
+
+ if (displacementImage) {
+ GenerateUVCoords();
+ MaterialGenerator().GenerateImageUVCoordinates(*this, displacementImageIdx, 0,
+ *displacementImage);
+ if (!HasTessellation()) {
+ vertexShader.AddUniform("displaceAmount", "float");
+ // we create the world position setup here
+ // because it will be replaced with the displaced position
+ SetCode(GenerationFlagValues::WorldPosition);
+ vertexShader.AddUniform("model_matrix", "mat4");
+
+ vertexShader.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+ IDefaultMaterialShaderGenerator::SImageVariableNames theVarNames =
+ MaterialGenerator().GetImageVariableNames(displacementImageIdx);
+
+ vertexShader.AddUniform(theVarNames.m_ImageSampler, "sampler2D");
+
+ vertexShader
+ << "\tvec3 displacedPos = uicDefaultMaterialFileDisplacementTexture( "
+ << theVarNames.m_ImageSampler << ", displaceAmount, "
+ << theVarNames.m_ImageFragCoords << ", attr_norm, attr_pos );" << Endl;
+ AddInterpolationParameter("varWorldPos", "vec3");
+ vertexShader.Append("\tvec3 local_model_world_position = (model_matrix * "
+ "vec4(displacedPos, 1.0)).xyz;");
+ AssignOutput("varWorldPos", "local_model_world_position");
+ }
+ }
+ // for tessellation we pass on the position in object coordinates
+ // Also note that gl_Position is written in the tess eval shader
+ if (HasTessellation())
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ else {
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ if (displacementImage)
+ vertexShader.Append(
+ "\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ else
+ vertexShader.Append(
+ "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ }
+
+ if (HasTessellation()) {
+ GenerateWorldPosition();
+ GenerateWorldNormal();
+ GenerateObjectNormal();
+ GenerateVarTangentAndBinormal();
+ }
+ }
+
+ void BeginFragmentGeneration() override
+ {
+ Fragment().AddUniform("material_diffuse", "vec4");
+ Fragment() << "void main()" << Endl << "{" << Endl;
+ // We do not pass object opacity through the pipeline.
+ Fragment() << "\tfloat object_opacity = material_diffuse.a;" << Endl;
+ }
+
+ void AssignOutput(const char8_t *inVarName, const char8_t *inVarValue) override
+ {
+ Vertex() << "\t" << inVarName << " = " << inVarValue << ";\n";
+ }
+ void DoGenerateUVCoords(QT3DSU32 inUVSet = 0) override
+ {
+ QT3DS_ASSERT(inUVSet == 0 || inUVSet == 1);
+
+ if (inUVSet == 0) {
+ Vertex().AddIncoming("attr_uv0", "vec2");
+ Vertex() << "\tvarTexCoord0 = attr_uv0;" << Endl;
+ } else if (inUVSet == 1) {
+ Vertex().AddIncoming("attr_uv1", "vec2");
+ Vertex() << "\tvarTexCoord1 = attr_uv1;" << Endl;
+ }
+ }
+
+ // fragment shader expects varying vertex normal
+ // lighting in vertex pipeline expects world_normal
+ void DoGenerateWorldNormal() override
+ {
+ IShaderStageGenerator &vertexGenerator(Vertex());
+ vertexGenerator.AddIncoming("attr_norm", "vec3");
+ vertexGenerator.AddUniform("normal_matrix", "mat3");
+ if (HasTessellation() == false) {
+ vertexGenerator.Append(
+ "\tvec3 world_normal = normalize(normal_matrix * attr_norm).xyz;");
+ vertexGenerator.Append("\tvarNormal = world_normal;");
+ }
+ }
+ void DoGenerateObjectNormal() override
+ {
+ AddInterpolationParameter("varObjectNormal", "vec3");
+ Vertex().Append("\tvarObjectNormal = attr_norm;");
+ }
+ void DoGenerateWorldPosition() override
+ {
+ Vertex().Append(
+ "\tvec3 local_model_world_position = (model_matrix * vec4(attr_pos, 1.0)).xyz;");
+ AssignOutput("varWorldPos", "local_model_world_position");
+ }
+
+ void DoGenerateVarTangentAndBinormal() override
+ {
+ Vertex().AddIncoming("attr_textan", "vec3");
+ Vertex().AddIncoming("attr_binormal", "vec3");
+
+ bool hasNPatchTessellation = m_TessMode == TessModeValues::TessNPatch;
+
+ if (!hasNPatchTessellation) {
+ Vertex() << "\tvarTangent = normal_matrix * attr_textan;" << Endl
+ << "\tvarBinormal = normal_matrix * attr_binormal;" << Endl;
+ } else {
+ Vertex() << "\tvarTangent = attr_textan;" << Endl
+ << "\tvarBinormal = attr_binormal;" << Endl;
+ }
+ }
+
+ void EndVertexGeneration() override
+ {
+
+ if (HasTessellation()) {
+ // finalize tess control shader
+ FinalizeTessControlShader();
+ // finalize tess evaluation shader
+ FinalizeTessEvaluationShader();
+
+ TessControl().Append("}");
+ TessEval().Append("}");
+ }
+ if (m_Wireframe) {
+ // finalize geometry shader
+ FinalizeWireframeGeometryShader();
+ Geometry().Append("}");
+ }
+ Vertex().Append("}");
+ }
+
+ void EndFragmentGeneration() override { Fragment().Append("}"); }
+
+ void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override
+ {
+ m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType)));
+ Vertex().AddOutgoing(inName, inType);
+ Fragment().AddIncoming(inName, inType);
+ if (HasTessellation()) {
+ eastl::string nameBuilder(inName);
+ nameBuilder.append("TC");
+ TessControl().AddOutgoing(nameBuilder.c_str(), inType);
+
+ nameBuilder.assign(inName);
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry) {
+ nameBuilder.append("TE");
+ Geometry().AddOutgoing(inName, inType);
+ }
+ TessEval().AddOutgoing(nameBuilder.c_str(), inType);
+ }
+ }
+
+ IShaderStageGenerator &ActiveStage() override { return Vertex(); }
+ };
+
+ NVRenderShaderProgram *CUICRendererImpl::GenerateShader(SSubsetRenderable &inRenderable,
+ TShaderFeatureSet inFeatureSet)
+ {
+ // build a string that allows us to print out the shader we are generating to the log.
+ // This is time consuming but I feel like it doesn't happen all that often and is very
+ // useful to users
+ // looking at the log file.
+ m_GeneratedShaderString.clear();
+ SShaderDefaultMaterialKey theKey(inRenderable.m_ShaderDescription);
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey =
+ m_UICContext.GetStringTable().RegisterStr(m_GeneratedShaderString.c_str());
+ NVRenderShaderProgram *cachedProgram = theCache.GetProgram(theCacheKey, inFeatureSet);
+ if (cachedProgram)
+ return cachedProgram;
+
+ SSubsetMaterialVertexPipeline pipeline(
+ *this, inRenderable,
+ m_DefaultMaterialShaderKeyProperties.m_WireframeMode.GetValue(theKey));
+ return m_UICContext.GetDefaultMaterialShaderGenerator().GenerateShader(
+ inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet,
+ m_CurrentLayer->m_Lights, inRenderable.m_FirstImage,
+ inRenderable.m_RenderableFlags.HasTransparency(), "mesh subset pipeline-- ");
+ }
+
+ // -------------- Special cases for shadows -------------------
+
+ SRenderableDepthPrepassShader *
+ CUICRendererImpl::GetParaboloidDepthShader(TessModeValues::Enum inTessMode)
+ {
+ if (!m_UICContext.GetRenderContext().IsTessellationSupported()
+ || inTessMode == TessModeValues::NoTess) {
+ return GetParaboloidDepthNoTessShader();
+ } else if (inTessMode == TessModeValues::TessLinear) {
+ return GetParaboloidDepthTessLinearShader();
+ } else if (inTessMode == TessModeValues::TessPhong) {
+ return GetParaboloidDepthTessPhongShader();
+ } else if (inTessMode == TessModeValues::TessNPatch) {
+ return GetParaboloidDepthTessNPatchShader();
+ }
+
+ return GetParaboloidDepthNoTessShader();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetParaboloidDepthNoTessShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_ParaboloidDepthShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("paraboloid depth shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ IShaderProgramGenerator::OutputParaboloidDepthVertex(vertexShader);
+ IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader);
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetParaboloidDepthTessLinearShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_ParaboloidDepthTessLinearShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("paraboloid depth tess linear shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ // vertexShader.AddOutgoing("world_pos", "vec4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ // vertexShader.Append("\tworld_pos = attr_pos;");
+ vertexShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationLinear.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ // tessCtrlShader.AddOutgoing( "outUVTC", "vec2" );
+ // tessCtrlShader.AddOutgoing( "outNormalTC", "vec3" );
+ tessCtrlShader.Append("void main() {\n");
+ // tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];");
+ // tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];");
+ // tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationLinear.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ IShaderProgramGenerator::OutputParaboloidDepthTessEval(tessEvalShader);
+ tessEvalShader.Append("}");
+
+ IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader);
+ }
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetParaboloidDepthTessPhongShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_ParaboloidDepthTessPhongShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("paraboloid depth tess phong shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ // vertexShader.AddOutgoing("world_pos", "vec4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ // vertexShader.Append("\tworld_pos = attr_pos;");
+ vertexShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationPhong.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ // tessCtrlShader.AddOutgoing( "outUVTC", "vec2" );
+ // tessCtrlShader.AddOutgoing( "outNormalTC", "vec3" );
+ tessCtrlShader.Append("void main() {\n");
+ // tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];");
+ // tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];");
+ // tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationPhong.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ IShaderProgramGenerator::OutputParaboloidDepthTessEval(tessEvalShader);
+ tessEvalShader.Append("}");
+
+ IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader);
+ }
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetParaboloidDepthTessNPatchShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_ParaboloidDepthTessNPatchShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("paraboloid depth tess NPatch shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ // vertexShader.AddOutgoing("world_pos", "vec4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ // vertexShader.Append("\tworld_pos = attr_pos;");
+ vertexShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationNPatch.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ // tessCtrlShader.AddOutgoing( "outUVTC", "vec2" );
+ // tessCtrlShader.AddOutgoing( "outNormalTC", "vec3" );
+ tessCtrlShader.Append("void main() {\n");
+ // tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];");
+ // tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];");
+ // tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationNPatch.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ IShaderProgramGenerator::OutputParaboloidDepthTessEval(tessEvalShader);
+ tessEvalShader.Append("}");
+
+ IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader);
+ }
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *
+ CUICRendererImpl::GetCubeShadowDepthShader(TessModeValues::Enum inTessMode)
+ {
+ if (!m_UICContext.GetRenderContext().IsTessellationSupported()
+ || inTessMode == TessModeValues::NoTess) {
+ return GetCubeDepthNoTessShader();
+ } else if (inTessMode == TessModeValues::TessLinear) {
+ return GetCubeDepthTessLinearShader();
+ } else if (inTessMode == TessModeValues::TessPhong) {
+ return GetCubeDepthTessPhongShader();
+ } else if (inTessMode == TessModeValues::TessNPatch) {
+ return GetCubeDepthTessNPatchShader();
+ }
+
+ return GetCubeDepthNoTessShader();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetCubeDepthNoTessShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_CubemapDepthShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("cubemap face depth shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+
+ if (!depthShaderProgram) {
+ // GetProgramGenerator().BeginProgram(
+ // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex |
+ // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) );
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage(
+ // ShaderGeneratorStages::Geometry ) );
+
+ IShaderProgramGenerator::OutputCubeFaceDepthVertex(vertexShader);
+ // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader );
+ IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader);
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram();
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetCubeDepthTessLinearShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_CubemapDepthTessLinearShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("cubemap face depth linear tess shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+
+ if (!depthShaderProgram) {
+ // GetProgramGenerator().BeginProgram(
+ // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex |
+ // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) );
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage(
+ // ShaderGeneratorStages::Geometry ) );
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("}");
+
+ // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader );
+ IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader);
+
+ tessCtrlShader.AddInclude("tessellationLinear.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationLinear.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddUniform("model_matrix", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tworld_pos = model_matrix * pos;");
+ tessEvalShader.Append("\tworld_pos /= world_pos.w;");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+ tessEvalShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetCubeDepthTessPhongShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_CubemapDepthTessPhongShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("cubemap face depth phong tess shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+
+ if (!depthShaderProgram) {
+ // GetProgramGenerator().BeginProgram(
+ // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex |
+ // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) );
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage(
+ // ShaderGeneratorStages::Geometry ) );
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("}");
+
+ // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader );
+ IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader);
+
+ tessCtrlShader.AddInclude("tessellationPhong.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctNorm[0] = outNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationPhong.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddUniform("model_matrix", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tworld_pos = model_matrix * pos;");
+ tessEvalShader.Append("\tworld_pos /= world_pos.w;");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+ tessEvalShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetCubeDepthTessNPatchShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_CubemapDepthTessNPatchShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("cubemap face depth npatch tess shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+
+ if (!depthShaderProgram) {
+ // GetProgramGenerator().BeginProgram(
+ // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex |
+ // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) );
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage(
+ // ShaderGeneratorStages::Geometry ) );
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("}");
+
+ // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader );
+ IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader);
+
+ tessCtrlShader.AddOutgoing("outNormalTC", "vec3");
+ tessCtrlShader.AddInclude("tessellationNPatch.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctNorm[0] = outNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append(
+ "\toutNormalTC[gl_InvocationID] = outNormal[gl_InvocationID];\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationNPatch.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddUniform("model_matrix", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tctNorm[0] = outNormalTC[0];");
+ tessEvalShader.Append("\tctNorm[1] = outNormalTC[1];");
+ tessEvalShader.Append("\tctNorm[2] = outNormalTC[2];");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tworld_pos = model_matrix * pos;");
+ tessEvalShader.Append("\tworld_pos /= world_pos.w;");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+ tessEvalShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *
+ CUICRendererImpl::GetOrthographicDepthShader(TessModeValues::Enum inTessMode)
+ {
+ if (!m_UICContext.GetRenderContext().IsTessellationSupported()
+ || inTessMode == TessModeValues::NoTess) {
+ return GetOrthographicDepthNoTessShader();
+ } else if (inTessMode == TessModeValues::TessLinear) {
+ return GetOrthographicDepthTessLinearShader();
+ } else if (inTessMode == TessModeValues::TessPhong) {
+ return GetOrthographicDepthTessPhongShader();
+ } else if (inTessMode == TessModeValues::TessNPatch) {
+ return GetOrthographicDepthTessNPatchShader();
+ }
+
+ return GetOrthographicDepthNoTessShader();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetOrthographicDepthNoTessShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_OrthographicDepthShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("orthographic depth shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.AddOutgoing("outDepth", "vec3");
+ vertexShader.Append("void main() {");
+ vertexShader.Append(
+ " gl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" outDepth.x = gl_Position.z / gl_Position.w;");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;");
+ fragmentShader.Append("\tfragOutput = vec4(depth);");
+ fragmentShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetOrthographicDepthTessLinearShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_OrthographicDepthTessLinearShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("orthographic depth tess linear shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;");
+ fragmentShader.Append("\tfragOutput = vec4(depth);");
+ fragmentShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationLinear.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationLinear.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddOutgoing("outDepth", "vec3");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+ tessEvalShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;");
+ tessEvalShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetOrthographicDepthTessPhongShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_OrthographicDepthTessPhongShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("orthographic depth tess phong shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;");
+ fragmentShader.Append("\tfragOutput = vec4(depth);");
+ fragmentShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationPhong.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctNorm[0] = outNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationPhong.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddOutgoing("outDepth", "vec3");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+ tessEvalShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;");
+ tessEvalShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetOrthographicDepthTessNPatchShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthShader =
+ m_OrthographicDepthTessNPatchShader;
+
+ if (theDepthShader.hasValue() == false) {
+ TStrType name;
+ name.assign("orthographic depth tess npatch shader");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ fragmentShader.AddUniform("model_view_projection", "mat4");
+ fragmentShader.AddUniform("camera_properties", "vec2");
+ fragmentShader.AddUniform("camera_position", "vec3");
+ fragmentShader.AddUniform("camera_direction", "vec3");
+ fragmentShader.AddInclude("depthpass.glsllib");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ // fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);");
+ fragmentShader.Append("\tfloat depth = (outDepth.x - camera_properties.x) / "
+ "(camera_properties.y - camera_properties.x);");
+ fragmentShader.Append("\tfragOutput = vec4(depth);");
+ fragmentShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationNPatch.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.AddOutgoing("outNormalTC", "vec3");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctNorm[0] = outNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationNPatch.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddUniform("model_matrix", "mat4");
+ tessEvalShader.AddOutgoing("outDepth", "vec3");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+ tessEvalShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;");
+ tessEvalShader.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ // ---------------------------------
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetDepthPrepassShader(bool inDisplaced)
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthPrePassShader =
+ (!inDisplaced) ? m_DepthPrepassShader : m_DepthPrepassShaderDisplaced;
+
+ if (theDepthPrePassShader.hasValue() == false) {
+ // check if we do displacement mapping
+ TStrType name;
+ name.assign("depth prepass shader");
+ if (inDisplaced)
+ name.append(" displacement");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.Append("void main() {");
+
+ if (inDisplaced) {
+ GetUICContext()
+ .GetDefaultMaterialShaderGenerator()
+ .AddDisplacementMappingForDepthPass(vertexShader);
+ } else {
+ vertexShader.Append(
+ "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ }
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);");
+ fragmentShader.Append("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram();
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ return theDepthPrePassShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *
+ CUICRendererImpl::GetDepthTessPrepassShader(TessModeValues::Enum inTessMode, bool inDisplaced)
+ {
+ if (!m_UICContext.GetRenderContext().IsTessellationSupported()
+ || inTessMode == TessModeValues::NoTess) {
+ return GetDepthPrepassShader(inDisplaced);
+ } else if (inTessMode == TessModeValues::TessLinear) {
+ return GetDepthTessLinearPrepassShader(inDisplaced);
+ } else if (inTessMode == TessModeValues::TessPhong) {
+ return GetDepthTessPhongPrepassShader();
+ } else if (inTessMode == TessModeValues::TessNPatch) {
+ return GetDepthTessNPatchPrepassShader();
+ }
+
+ return GetDepthPrepassShader(inDisplaced);
+ }
+
+ SRenderableDepthPrepassShader *
+ CUICRendererImpl::GetDepthTessLinearPrepassShader(bool inDisplaced)
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &theDepthPrePassShader =
+ (!inDisplaced) ? m_DepthTessLinearPrepassShader
+ : m_DepthTessLinearPrepassShaderDisplaced;
+
+ if (theDepthPrePassShader.hasValue() == false) {
+ // check if we do displacement mapping
+ TStrType name;
+ name.assign("depth tess linear prepass shader");
+ if (inDisplaced)
+ name.append(" displacement");
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(name.c_str());
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ if (inDisplaced) {
+ vertexShader.AddIncoming("attr_uv0", "vec2");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+
+ vertexShader.AddUniform("displacementMap_rot", "vec4");
+ vertexShader.AddUniform("displacementMap_offset", "vec3");
+
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.AddOutgoing("outUV", "vec2");
+ }
+ vertexShader.AddOutgoing("outWorldPos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.AddUniform("model_matrix", "mat4");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ if (inDisplaced) {
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("\tvec3 uTransform = vec3( displacementMap_rot.x, "
+ "displacementMap_rot.y, displacementMap_offset.x );");
+ vertexShader.Append("\tvec3 vTransform = vec3( displacementMap_rot.z, "
+ "displacementMap_rot.w, displacementMap_offset.y );");
+ vertexShader.AddInclude(
+ "defaultMaterialLighting.glsllib"); // getTransformedUVCoords is in the
+ // lighting code addition.
+ vertexShader << "\tvec2 uv_coords = attr_uv0;" << Endl;
+ vertexShader << "\toutUV = getTransformedUVCoords( vec3( uv_coords, 1.0), "
+ "uTransform, vTransform );\n";
+ }
+ vertexShader.Append("\toutWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);");
+ fragmentShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationLinear.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.AddOutgoing("outUVTC", "vec2");
+ tessCtrlShader.AddOutgoing("outNormalTC", "vec3");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];");
+ tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];");
+ tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+
+ if (inDisplaced) {
+ tessCtrlShader.Append("\toutUVTC[gl_InvocationID] = outUV[gl_InvocationID];");
+ tessCtrlShader.Append(
+ "\toutNormalTC[gl_InvocationID] = outNormal[gl_InvocationID];");
+ }
+
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationLinear.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ if (inDisplaced) {
+ tessEvalShader.AddUniform("displacementSampler", "sampler2D");
+ tessEvalShader.AddUniform("displaceAmount", "float");
+ tessEvalShader.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+ }
+ tessEvalShader.AddOutgoing("outUV", "vec2");
+ tessEvalShader.AddOutgoing("outNormal", "vec3");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+
+ if (inDisplaced) {
+ tessEvalShader << "\toutUV = gl_TessCoord.x * outUVTC[0] + gl_TessCoord.y * "
+ "outUVTC[1] + gl_TessCoord.z * outUVTC[2];"
+ << Endl;
+ tessEvalShader
+ << "\toutNormal = gl_TessCoord.x * outNormalTC[0] + gl_TessCoord.y * "
+ "outNormalTC[1] + gl_TessCoord.z * outNormalTC[2];"
+ << Endl;
+ tessEvalShader
+ << "\tvec3 displacedPos = uicDefaultMaterialFileDisplacementTexture( "
+ "displacementSampler , displaceAmount, outUV , outNormal, pos.xyz );"
+ << Endl;
+ tessEvalShader.Append(
+ "\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ } else
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;");
+
+ tessEvalShader.Append("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ }
+
+ SShaderCacheProgramFlags theFlags;
+ theFlags.SetTessellationEnabled(true);
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), theFlags, TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ return theDepthPrePassShader->mPtr;
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetDepthTessPhongPrepassShader()
+ {
+ if (m_DepthTessPhongPrepassShader.hasValue() == false) {
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey =
+ m_UICContext.GetStringTable().RegisterStr("depth tess phong prepass shader");
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.AddOutgoing("outWorldPos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.AddUniform("model_matrix", "mat4");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("\toutWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;");
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);");
+ fragmentShader.Append("}");
+
+ tessCtrlShader.AddInclude("tessellationPhong.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];");
+ tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];");
+ tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];");
+ tessCtrlShader.Append("\tctNorm[0] = outNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationPhong.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n");
+ tessEvalShader.Append("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ }
+
+ SShaderCacheProgramFlags theFlags;
+ theFlags.SetTessellationEnabled(true);
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "depth tess phong prepass shader", theFlags, TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ m_DepthTessPhongPrepassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ m_DepthTessPhongPrepassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ return m_DepthTessPhongPrepassShader->mPtr;
+ }
+
+ SRenderableDepthPrepassShader *CUICRendererImpl::GetDepthTessNPatchPrepassShader()
+ {
+ if (m_DepthTessNPatchPrepassShader.hasValue() == false) {
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey =
+ m_UICContext.GetStringTable().RegisterStr("depth tess npatch prepass shader");
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &vertexShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &tessCtrlShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ IShaderStageGenerator &tessEvalShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ IShaderStageGenerator &fragmentShader(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddIncoming("attr_norm", "vec3");
+ vertexShader.AddOutgoing("outNormal", "vec3");
+ vertexShader.AddOutgoing("outWorldPos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.AddUniform("model_matrix", "mat4");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ vertexShader.Append("\toutWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;");
+ vertexShader.Append("\toutNormal = attr_norm;");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);");
+ fragmentShader.Append("}");
+
+ tessCtrlShader.AddOutgoing("outNormalTC", "vec3");
+ tessCtrlShader.AddInclude("tessellationNPatch.glsllib");
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+ tessCtrlShader.Append("void main() {\n");
+ tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];");
+ tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];");
+ tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];");
+ tessCtrlShader.Append("\tctNorm[0] = outNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tctTangent[0] = outNormal[0];"); // we don't care for the tangent
+ tessCtrlShader.Append("\tctTangent[1] = outNormal[1];");
+ tessCtrlShader.Append("\tctTangent[2] = outNormal[2];");
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+ tessCtrlShader.Append(
+ "\toutNormalTC[gl_InvocationID] = outNormal[gl_InvocationID];\n");
+ tessCtrlShader.Append("}");
+
+ tessEvalShader.AddInclude("tessellationNPatch.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.Append("void main() {");
+ tessEvalShader.Append("\tctNorm[0] = outNormalTC[0];");
+ tessEvalShader.Append("\tctNorm[1] = outNormalTC[1];");
+ tessEvalShader.Append("\tctNorm[2] = outNormalTC[2];");
+ tessEvalShader.Append(
+ "\tctTangent[0] = outNormalTC[0];"); // we don't care for the tangent
+ tessEvalShader.Append("\tctTangent[1] = outNormalTC[1];");
+ tessEvalShader.Append("\tctTangent[2] = outNormalTC[2];");
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n");
+ tessEvalShader.Append("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ }
+
+ SShaderCacheProgramFlags theFlags;
+ theFlags.SetTessellationEnabled(true);
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "depth tess npatch prepass shader", theFlags, TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ m_DepthTessNPatchPrepassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ m_DepthTessNPatchPrepassShader =
+ NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ return m_DepthTessNPatchPrepassShader->mPtr;
+ }
+
+ SDefaultAoPassShader *CUICRendererImpl::GetDefaultAoPassShader(TShaderFeatureSet inFeatureSet)
+ {
+ if (m_DefaultAoPassShader.hasValue() == false) {
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey =
+ m_UICContext.GetStringTable().RegisterStr("fullscreen AO pass shader");
+ NVRenderShaderProgram *aoPassShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!aoPassShaderProgram) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &theVertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &theFragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddIncoming("attr_uv", "vec2");
+ theVertexGenerator.AddOutgoing("uv_coords", "vec2");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append("\tgl_Position = vec4(attr_pos.xy, 0.5, 1.0 );");
+ theVertexGenerator.Append("\tuv_coords = attr_uv;");
+ theVertexGenerator.Append("}");
+
+ // fragmentGenerator.AddInclude( "SSAOCustomMaterial.glsllib" );
+ theFragmentGenerator.AddInclude("viewProperties.glsllib");
+ theFragmentGenerator.AddInclude("screenSpaceAO.glsllib");
+
+ theFragmentGenerator
+ << "layout (std140) uniform cbAoShadow { " << Endl << " vec4 ao_properties;"
+ << Endl << " vec4 ao_properties2;" << Endl << " vec4 shadow_properties;"
+ << Endl << " vec4 aoScreenConst;" << Endl << " vec4 UvToEyeConst;" << Endl
+ << "};" << Endl;
+
+ theFragmentGenerator.AddUniform("camera_direction", "vec3");
+ theFragmentGenerator.AddUniform("depth_sampler", "sampler2D");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator << "\tfloat aoFactor;" << Endl;
+ theFragmentGenerator << "\tvec3 screenNorm;" << Endl;
+
+ // We're taking multiple depth samples and getting the derivatives at each of them
+ // to get a more
+ // accurate view space normal vector. When we do only one, we tend to get bizarre
+ // values at the edges
+ // surrounding objects, and this also ends up giving us weird AO values.
+ // If we had a proper screen-space normal map, that would also do the trick.
+ theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );");
+ theFragmentGenerator.Append("\tfloat depth = getDepthValue( "
+ "texelFetch(depth_sampler, iCoords, 0), "
+ "camera_properties );");
+ theFragmentGenerator.Append(
+ "\tdepth = depthValueToLinearDistance( depth, camera_properties );");
+ theFragmentGenerator.Append("\tdepth = (depth - camera_properties.x) / "
+ "(camera_properties.y - camera_properties.x);");
+ theFragmentGenerator.Append("\tfloat depth2 = getDepthValue( "
+ "texelFetch(depth_sampler, iCoords+ivec2(1), 0), "
+ "camera_properties );");
+ theFragmentGenerator.Append(
+ "\tdepth2 = depthValueToLinearDistance( depth, camera_properties );");
+ theFragmentGenerator.Append("\tfloat depth3 = getDepthValue( "
+ "texelFetch(depth_sampler, iCoords-ivec2(1), 0), "
+ "camera_properties );");
+ theFragmentGenerator.Append(
+ "\tdepth3 = depthValueToLinearDistance( depth, camera_properties );");
+ theFragmentGenerator.Append("\tvec3 tanU = vec3(10, 0, dFdx(depth));");
+ theFragmentGenerator.Append("\tvec3 tanV = vec3(0, 10, dFdy(depth));");
+ theFragmentGenerator.Append("\tscreenNorm = normalize(cross(tanU, tanV));");
+ theFragmentGenerator.Append("\ttanU = vec3(10, 0, dFdx(depth2));");
+ theFragmentGenerator.Append("\ttanV = vec3(0, 10, dFdy(depth2));");
+ theFragmentGenerator.Append("\tscreenNorm += normalize(cross(tanU, tanV));");
+ theFragmentGenerator.Append("\ttanU = vec3(10, 0, dFdx(depth3));");
+ theFragmentGenerator.Append("\ttanV = vec3(0, 10, dFdy(depth3));");
+ theFragmentGenerator.Append("\tscreenNorm += normalize(cross(tanU, tanV));");
+ theFragmentGenerator.Append("\tscreenNorm = -normalize(screenNorm);");
+
+ theFragmentGenerator.Append("\taoFactor = \
+ SSambientOcclusion( depth_sampler, screenNorm, ao_properties, ao_properties2, \
+ camera_properties, aoScreenConst, UvToEyeConst );");
+
+ theFragmentGenerator.Append(
+ "\tgl_FragColor = vec4(aoFactor, aoFactor, aoFactor, 1.0);");
+
+ theFragmentGenerator.Append("}");
+ }
+
+ aoPassShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "fullscreen AO pass shader", SShaderCacheProgramFlags(), inFeatureSet);
+
+ if (aoPassShaderProgram) {
+ m_DefaultAoPassShader = NVScopedRefCounted<SDefaultAoPassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(*aoPassShaderProgram,
+ GetContext()));
+ } else {
+ m_DefaultAoPassShader = NVScopedRefCounted<SDefaultAoPassShader>();
+ }
+ }
+ return m_DefaultAoPassShader->mPtr;
+ }
+
+ SDefaultAoPassShader *CUICRendererImpl::GetFakeDepthShader(TShaderFeatureSet inFeatureSet)
+ {
+ if (m_FakeDepthShader.hasValue() == false) {
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey =
+ m_UICContext.GetStringTable().RegisterStr("depth display shader");
+ NVRenderShaderProgram *depthShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!depthShaderProgram) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &theVertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &theFragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddIncoming("attr_uv", "vec2");
+ theVertexGenerator.AddOutgoing("uv_coords", "vec2");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append("\tgl_Position = vec4(attr_pos.xy, 0.5, 1.0 );");
+ theVertexGenerator.Append("\tuv_coords = attr_uv;");
+ theVertexGenerator.Append("}");
+
+ theFragmentGenerator.AddUniform("depth_sampler", "sampler2D");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );");
+ theFragmentGenerator.Append(
+ "\tfloat depSample = texelFetch(depth_sampler, iCoords, 0).x;");
+ theFragmentGenerator.Append(
+ "\tgl_FragColor = vec4( depSample, depSample, depSample, 1.0 );");
+ theFragmentGenerator.Append("\treturn;");
+ theFragmentGenerator.Append("}");
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "depth display shader", SShaderCacheProgramFlags(), inFeatureSet);
+
+ if (depthShaderProgram) {
+ m_FakeDepthShader = NVScopedRefCounted<SDefaultAoPassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(
+ *depthShaderProgram, GetContext()));
+ } else {
+ m_FakeDepthShader = NVScopedRefCounted<SDefaultAoPassShader>();
+ }
+ }
+ return m_FakeDepthShader->mPtr;
+ }
+
+ SDefaultAoPassShader *CUICRendererImpl::GetFakeCubeDepthShader(TShaderFeatureSet inFeatureSet)
+ {
+ if (!m_FakeCubemapDepthShader.hasValue()) {
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey =
+ m_UICContext.GetStringTable().RegisterStr("cube depth display shader");
+ NVRenderShaderProgram *cubeShaderProgram =
+ theCache.GetProgram(theCacheKey, TShaderFeatureSet());
+ if (!cubeShaderProgram) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &theVertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &theFragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddIncoming("attr_uv", "vec2");
+ theVertexGenerator.AddOutgoing("sample_dir", "vec3");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append("\tgl_Position = vec4(attr_pos.xy, 0.5, 1.0 );");
+ theVertexGenerator.Append(
+ "\tsample_dir = vec3(4.0 * (attr_uv.x - 0.5), -1.0, 4.0 * (attr_uv.y - 0.5));");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.AddUniform("depth_cube", "samplerCube");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append(
+ "\tfloat smpDepth = texture( depth_cube, sample_dir ).x;");
+ theFragmentGenerator.Append(
+ "\tgl_FragColor = vec4(smpDepth, smpDepth, smpDepth, 1.0);");
+ theFragmentGenerator.Append("}");
+ }
+
+ cubeShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "cube depth display shader", SShaderCacheProgramFlags(), inFeatureSet);
+
+ if (cubeShaderProgram) {
+ m_FakeCubemapDepthShader = NVScopedRefCounted<SDefaultAoPassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(*cubeShaderProgram,
+ GetContext()));
+ } else {
+ m_FakeCubemapDepthShader = NVScopedRefCounted<SDefaultAoPassShader>();
+ }
+ }
+ return m_FakeCubemapDepthShader.getValue();
+ }
+
+ STextRenderHelper CUICRendererImpl::GetTextShader(bool inUsePathRendering)
+ {
+ STextShaderPtr &thePtr = (!inUsePathRendering) ? m_TextShader : m_TextPathShader;
+ if (thePtr.HasGeneratedShader())
+ return STextRenderHelper(thePtr, *m_QuadInputAssembler);
+
+ NVRenderShaderProgram *theShader = NULL;
+ NVRenderProgramPipeline *thePipeline = NULL;
+
+ if (!inUsePathRendering) {
+ GetProgramGenerator().BeginProgram();
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ // xy of text dimensions are scaling factors, zw are offset factors.
+ vertexGenerator.AddUniform("text_dimensions", "vec4");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator
+ << "\tvec3 textPos = vec3(attr_pos.x * text_dimensions.x + text_dimensions.z"
+ << ", attr_pos.y * text_dimensions.y + text_dimensions.w"
+ << ", attr_pos.z);" << Endl;
+
+ vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(textPos, 1.0);");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+
+ fragmentGenerator.AddUniform("text_textcolor", "vec4");
+ fragmentGenerator.AddUniform("text_textdimensions", "vec3");
+ fragmentGenerator.AddUniform("text_image", "sampler2D");
+ fragmentGenerator.AddUniform("text_backgroundcolor", "vec3");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec2 theCoords = uv_coords;");
+ // Enable rendering from a sub-rect
+
+ fragmentGenerator
+ << "\ttheCoords.x = theCoords.x * text_textdimensions.x;" << Endl
+ << "\ttheCoords.y = theCoords.y * text_textdimensions.y;" << Endl
+ // flip the y uv coord if the dimension's z variable is set
+ << "\tif ( text_textdimensions.z > 0.0 ) theCoords.y = 1.0 - theCoords.y;" << Endl;
+ fragmentGenerator.Append(
+ "\tfloat alpha_mask = texture2D( text_image, theCoords ).r * text_textcolor.a;");
+ fragmentGenerator.Append("\tfragOutput = vec4(mix(text_backgroundcolor.rgb, "
+ "text_textcolor.rgb, alpha_mask), alpha_mask );");
+
+ vertexGenerator.Append("}");
+ fragmentGenerator.Append("}");
+ const char *shaderName = "text shader";
+ theShader = GetProgramGenerator().CompileGeneratedShader(
+ shaderName, SShaderCacheProgramFlags(), TShaderFeatureSet(), false);
+ } else {
+ GetProgramGenerator().BeginProgram(
+ TShaderGeneratorStageFlags(ShaderGeneratorStages::Fragment));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ fragmentGenerator.AddUniform("text_textcolor", "vec4");
+ fragmentGenerator.AddUniform("text_backgroundcolor", "vec3");
+
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tfragOutput = vec4(mix(text_backgroundcolor.rgb, "
+ "text_textcolor.rgb, text_textcolor.a), text_textcolor.a );");
+ fragmentGenerator.Append("}");
+
+ const char *shaderName = "text path shader";
+ theShader = GetProgramGenerator().CompileGeneratedShader(
+ shaderName, SShaderCacheProgramFlags(), TShaderFeatureSet(), true);
+
+ // setup program pipeline
+ if (theShader) {
+ thePipeline = GetContext().CreateProgramPipeline();
+ if (thePipeline) {
+ thePipeline->SetProgramStages(
+ theShader,
+ qt3ds::render::NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Fragment));
+ }
+ }
+ }
+
+ if (theShader == NULL) {
+ thePtr.Set(NULL);
+ } else {
+ GenerateXYQuad();
+ thePtr.Set(QT3DS_NEW(m_Context->GetAllocator(), STextShader)(*theShader, thePipeline));
+ }
+ return STextRenderHelper(thePtr, *m_QuadInputAssembler);
+ }
+
+ STextDepthShader *CUICRendererImpl::GetTextDepthShader()
+ {
+ if (m_TextDepthPrepassShader.hasValue() == false) {
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ // xy of text dimensions are scaling factors, zw are offset factors.
+ vertexGenerator.AddUniform("text_dimensions", "vec4");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator
+ << "\tvec3 textPos = vec3(attr_pos.x * text_dimensions.x + text_dimensions.z"
+ << ", attr_pos.y * text_dimensions.y + text_dimensions.w"
+ << ", attr_pos.z);" << Endl;
+
+ vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(textPos, 1.0);");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+
+ fragmentGenerator.AddUniform("text_textdimensions", "vec3");
+ fragmentGenerator.AddUniform("text_image", "sampler2D");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec2 theCoords = uv_coords;");
+ // Enable rendering from a sub-rect
+
+ fragmentGenerator
+ << "\ttheCoords.x = theCoords.x * text_textdimensions.x;" << Endl
+ << "\ttheCoords.y = theCoords.y * text_textdimensions.y;" << Endl
+ // flip the y uv coord if the dimension's z variable is set
+ << "\tif ( text_textdimensions.z > 0.0 ) theCoords.y = 1.0 - theCoords.y;" << Endl;
+ fragmentGenerator.Append("\tfloat alpha_mask = texture2D( text_image, theCoords ).r;");
+ fragmentGenerator.Append("\tif ( alpha_mask < .05 ) discard;");
+ vertexGenerator.Append("}");
+ fragmentGenerator.Append("}");
+ const char *shaderName = "text depth shader";
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ shaderName, SShaderCacheProgramFlags(), TShaderFeatureSet());
+ if (theShader == NULL) {
+ m_TextDepthPrepassShader = NVScopedRefCounted<STextDepthShader>();
+ } else {
+ GenerateXYQuad();
+ m_TextDepthPrepassShader = NVScopedRefCounted<STextDepthShader>(
+ QT3DS_NEW(m_Context->GetAllocator(), STextDepthShader)(
+ m_Context->GetAllocator(), *theShader, *m_QuadInputAssembler));
+ }
+ }
+ return m_TextDepthPrepassShader->mPtr;
+ }
+
+ STextRenderHelper CUICRendererImpl::GetTextWidgetShader()
+ {
+ if (m_TextWidgetShader.HasGeneratedShader())
+ return STextRenderHelper(m_TextWidgetShader, *m_QuadInputAssembler);
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ // xy of text dimensions are scaling factors, zw are offset factors.
+ vertexGenerator.AddUniform("text_dimensions", "vec4");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator
+ << "\tvec3 textPos = vec3(attr_pos.x * text_dimensions.x + text_dimensions.z"
+ << ", attr_pos.y * text_dimensions.y + text_dimensions.w"
+ << ", attr_pos.z);" << Endl;
+
+ vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(textPos, 1.0);");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("text_textcolor", "vec4");
+ fragmentGenerator.AddUniform("text_textdimensions", "vec3");
+ fragmentGenerator.AddUniform("text_image", "sampler2D");
+ fragmentGenerator.AddUniform("text_backgroundcolor", "vec3");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec2 theCoords = uv_coords;");
+ // Enable rendering from a sub-rect
+
+ fragmentGenerator << "\ttheCoords.x = theCoords.x * text_textdimensions.x;" << Endl
+ << "\ttheCoords.y = theCoords.y * text_textdimensions.y;" << Endl
+ // flip the y uv coord if the dimension's z variable is set
+ << "\tif ( text_textdimensions.z > 0.0 ) theCoords.y = 1.0 - theCoords.y;"
+ << Endl;
+ fragmentGenerator.Append(
+ "\tfloat alpha_mask = texture2D( text_image, theCoords ).r * text_textcolor.a;");
+ fragmentGenerator.Append("\tfragOutput = vec4(mix(text_backgroundcolor.rgb, "
+ "text_textcolor.rgb, alpha_mask), 1.0 );");
+ fragmentGenerator.Append("}");
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "text widget shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (theShader == NULL)
+ m_TextWidgetShader.Set(NULL);
+ else {
+ GenerateXYQuad();
+ m_TextWidgetShader.Set(QT3DS_NEW(m_Context->GetAllocator(), STextShader)(*theShader));
+ }
+ return STextRenderHelper(m_TextWidgetShader, *m_QuadInputAssembler);
+ }
+
+ STextRenderHelper CUICRendererImpl::GetOnscreenTextShader()
+ {
+ if (m_TextOnscreenShader.HasGeneratedShader())
+ return STextRenderHelper(m_TextOnscreenShader, *m_QuadStripInputAssembler);
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddUniform("vertex_offsets", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+
+ vertexGenerator.Append("\tvec3 pos = attr_pos + vec3(vertex_offsets, 0.0);");
+ vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(pos, 1.0);");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("text_textcolor", "vec4");
+ fragmentGenerator.AddUniform("text_image", "sampler2D");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tfloat alpha = texture2D( text_image, uv_coords ).a;");
+ fragmentGenerator.Append(
+ "\tfragOutput = vec4(text_textcolor.r, text_textcolor.g, text_textcolor.b, alpha);");
+ fragmentGenerator.Append("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "onscreen texture shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (theShader == NULL)
+ m_TextOnscreenShader.Set(NULL);
+ else {
+ GenerateXYQuadStrip();
+ m_TextOnscreenShader.Set(QT3DS_NEW(m_Context->GetAllocator(), STextShader)(*theShader));
+ }
+ return STextRenderHelper(m_TextOnscreenShader, *m_QuadStripInputAssembler);
+ }
+
+ NVRenderShaderProgram *CUICRendererImpl::GetTextAtlasEntryShader()
+ {
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+
+ vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("text_image", "sampler2D");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tfloat alpha = texture2D( text_image, uv_coords ).a;");
+ fragmentGenerator.Append("\tfragOutput = vec4(alpha, alpha, alpha, alpha);");
+ fragmentGenerator.Append("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "texture atlas entry shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ return theShader;
+ }
+
+ STextRenderHelper CUICRendererImpl::GetShader(STextRenderable & /*inRenderable*/,
+ bool inUsePathRendering)
+ {
+ return GetTextShader(inUsePathRendering);
+ }
+
+ SLayerSceneShader *CUICRendererImpl::GetSceneLayerShader()
+ {
+ if (m_SceneLayerShader.hasValue())
+ return m_SceneLayerShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ // xy of text dimensions are scaling factors, zw are offset factors.
+ vertexGenerator.AddUniform("layer_dimensions", "vec2");
+ vertexGenerator.AddUniform("model_view_projection", "mat4");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator << "\tvec3 layerPos = vec3(attr_pos.x * layer_dimensions.x / 2.0"
+ << ", attr_pos.y * layer_dimensions.y / 2.0"
+ << ", attr_pos.z);" << Endl;
+
+ vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(layerPos, 1.0);");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("layer_image", "sampler2D");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec2 theCoords = uv_coords;\n");
+ fragmentGenerator.Append("\tvec4 theLayerTexture = texture2D( layer_image, theCoords );\n");
+ fragmentGenerator.Append("\tif( theLayerTexture.a == 0.0 ) discard;\n");
+ fragmentGenerator.Append("\tfragOutput = theLayerTexture;\n");
+ fragmentGenerator.Append("}");
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "layer shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SLayerSceneShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SLayerSceneShader)(*theShader);
+ m_SceneLayerShader = retval;
+ return m_SceneLayerShader.getValue();
+ }
+
+ SLayerProgAABlendShader *CUICRendererImpl::GetLayerProgAABlendShader()
+ {
+ if (m_LayerProgAAShader.hasValue())
+ return m_LayerProgAAShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+ fragmentGenerator.AddUniform("accumulator", "sampler2D");
+ fragmentGenerator.AddUniform("last_frame", "sampler2D");
+ fragmentGenerator.AddUniform("blend_factors", "vec2");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec4 accum = texture2D( accumulator, uv_coords );");
+ fragmentGenerator.Append("\tvec4 lastFrame = texture2D( last_frame, uv_coords );");
+ fragmentGenerator.Append(
+ "\tgl_FragColor = accum*blend_factors.y + lastFrame*blend_factors.x;");
+ fragmentGenerator.Append("}");
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "layer progressiveAA blend shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SLayerProgAABlendShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SLayerProgAABlendShader)(*theShader);
+ m_LayerProgAAShader = retval;
+ return m_LayerProgAAShader.getValue();
+ }
+
+ SShadowmapPreblurShader *CUICRendererImpl::GetCubeShadowBlurXShader()
+ {
+ if (m_CubeShadowBlurXShader.hasValue())
+ return m_CubeShadowBlurXShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ // vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords.xy = attr_pos.xy;");
+ vertexGenerator.Append("}");
+
+ // This with the ShadowBlurYShader design for a 2-pass 5x5 (sigma=1.0)
+ // Weights computed using -- http://dev.theomader.com/gaussian-kernel-calculator/
+ fragmentGenerator.AddUniform("camera_properties", "vec2");
+ fragmentGenerator.AddUniform("depthCube", "samplerCube");
+ // fragmentGenerator.AddUniform("depthSrc", "sampler2D");
+ fragmentGenerator.Append("layout(location = 0) out vec4 frag0;");
+ fragmentGenerator.Append("layout(location = 1) out vec4 frag1;");
+ fragmentGenerator.Append("layout(location = 2) out vec4 frag2;");
+ fragmentGenerator.Append("layout(location = 3) out vec4 frag3;");
+ fragmentGenerator.Append("layout(location = 4) out vec4 frag4;");
+ fragmentGenerator.Append("layout(location = 5) out vec4 frag5;");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tfloat ofsScale = camera_properties.x / 2500.0;");
+ fragmentGenerator.Append("\tvec3 dir0 = vec3(1.0, -uv_coords.y, -uv_coords.x);");
+ fragmentGenerator.Append("\tvec3 dir1 = vec3(-1.0, -uv_coords.y, uv_coords.x);");
+ fragmentGenerator.Append("\tvec3 dir2 = vec3(uv_coords.x, 1.0, uv_coords.y);");
+ fragmentGenerator.Append("\tvec3 dir3 = vec3(uv_coords.x, -1.0, -uv_coords.y);");
+ fragmentGenerator.Append("\tvec3 dir4 = vec3(uv_coords.x, -uv_coords.y, 1.0);");
+ fragmentGenerator.Append("\tvec3 dir5 = vec3(-uv_coords.x, -uv_coords.y, -1.0);");
+ fragmentGenerator.Append("\tfloat depth0;");
+ fragmentGenerator.Append("\tfloat depth1;");
+ fragmentGenerator.Append("\tfloat depth2;");
+ fragmentGenerator.Append("\tfloat outDepth;");
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir0).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir0 + vec3(0.0, 0.0, -ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir0 + vec3(0.0, 0.0, ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir0 + vec3(0.0, 0.0, -2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir0 + vec3(0.0, 0.0, 2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag0 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir1).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir1 + vec3(0.0, 0.0, -ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir1 + vec3(0.0, 0.0, ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir1 + vec3(0.0, 0.0, -2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir1 + vec3(0.0, 0.0, 2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag1 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir2).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir2 + vec3(-ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir2 + vec3(ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir2 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir2 + vec3(2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag2 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir3).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir3 + vec3(-ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir3 + vec3(ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir3 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir3 + vec3(2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag3 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir4).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir4 + vec3(-ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir4 + vec3(ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir4 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir4 + vec3(2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag4 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir5).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir5 + vec3(-ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir5 + vec3(ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir5 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir5 + vec3(2.0*ofsScale, 0.0, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag5 = vec4(outDepth);");
+
+ fragmentGenerator.Append("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "cubemap shadow blur X shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SShadowmapPreblurShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader);
+ m_CubeShadowBlurXShader = retval;
+ return m_CubeShadowBlurXShader.getValue();
+ }
+
+ SShadowmapPreblurShader *CUICRendererImpl::GetCubeShadowBlurYShader()
+ {
+ if (m_CubeShadowBlurYShader.hasValue())
+ return m_CubeShadowBlurYShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ // vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords.xy = attr_pos.xy;");
+ vertexGenerator.Append("}");
+
+ // This with the ShadowBlurXShader design for a 2-pass 5x5 (sigma=1.0)
+ // Weights computed using -- http://dev.theomader.com/gaussian-kernel-calculator/
+ fragmentGenerator.AddUniform("camera_properties", "vec2");
+ fragmentGenerator.AddUniform("depthCube", "samplerCube");
+ // fragmentGenerator.AddUniform("depthSrc", "sampler2D");
+ fragmentGenerator.Append("layout(location = 0) out vec4 frag0;");
+ fragmentGenerator.Append("layout(location = 1) out vec4 frag1;");
+ fragmentGenerator.Append("layout(location = 2) out vec4 frag2;");
+ fragmentGenerator.Append("layout(location = 3) out vec4 frag3;");
+ fragmentGenerator.Append("layout(location = 4) out vec4 frag4;");
+ fragmentGenerator.Append("layout(location = 5) out vec4 frag5;");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tfloat ofsScale = camera_properties.x / 2500.0;");
+ fragmentGenerator.Append("\tvec3 dir0 = vec3(1.0, -uv_coords.y, -uv_coords.x);");
+ fragmentGenerator.Append("\tvec3 dir1 = vec3(-1.0, -uv_coords.y, uv_coords.x);");
+ fragmentGenerator.Append("\tvec3 dir2 = vec3(uv_coords.x, 1.0, uv_coords.y);");
+ fragmentGenerator.Append("\tvec3 dir3 = vec3(uv_coords.x, -1.0, -uv_coords.y);");
+ fragmentGenerator.Append("\tvec3 dir4 = vec3(uv_coords.x, -uv_coords.y, 1.0);");
+ fragmentGenerator.Append("\tvec3 dir5 = vec3(-uv_coords.x, -uv_coords.y, -1.0);");
+ fragmentGenerator.Append("\tfloat depth0;");
+ fragmentGenerator.Append("\tfloat depth1;");
+ fragmentGenerator.Append("\tfloat depth2;");
+ fragmentGenerator.Append("\tfloat outDepth;");
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir0).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir0 + vec3(0.0, -ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir0 + vec3(0.0, ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir0 + vec3(0.0, -2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir0 + vec3(0.0, 2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag0 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir1).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir1 + vec3(0.0, -ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir1 + vec3(0.0, ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir1 + vec3(0.0, -2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir1 + vec3(0.0, 2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag1 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir2).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir2 + vec3(0.0, 0.0, -ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir2 + vec3(0.0, 0.0, ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir2 + vec3(0.0, 0.0, -2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir2 + vec3(0.0, 0.0, 2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag2 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir3).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir3 + vec3(0.0, 0.0, -ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir3 + vec3(0.0, 0.0, ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir3 + vec3(0.0, 0.0, -2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir3 + vec3(0.0, 0.0, 2.0*ofsScale)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag3 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir4).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir4 + vec3(0.0, -ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir4 + vec3(0.0, ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir4 + vec3(0.0, -2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir4 + vec3(0.0, 2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag4 = vec4(outDepth);");
+
+ fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir5).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 = texture(depthCube, dir5 + vec3(0.0, -ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth1 += texture(depthCube, dir5 + vec3(0.0, ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 = texture(depthCube, dir5 + vec3(0.0, -2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\tdepth2 += texture(depthCube, dir5 + vec3(0.0, 2.0*ofsScale, 0.0)).x;");
+ fragmentGenerator.Append(
+ "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfrag5 = vec4(outDepth);");
+
+ fragmentGenerator.Append("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "cubemap shadow blur Y shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SShadowmapPreblurShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader);
+ m_CubeShadowBlurYShader = retval;
+ return m_CubeShadowBlurYShader.getValue();
+ }
+
+ SShadowmapPreblurShader *CUICRendererImpl::GetOrthoShadowBlurXShader()
+ {
+ if (m_OrthoShadowBlurXShader.hasValue())
+ return m_OrthoShadowBlurXShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords.xy = attr_uv.xy;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("camera_properties", "vec2");
+ fragmentGenerator.AddUniform("depthSrc", "sampler2D");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec2 ofsScale = vec2( camera_properties.x / 7680.0, 0.0 );");
+ fragmentGenerator.Append("\tfloat depth0 = texture(depthSrc, uv_coords).x;");
+ fragmentGenerator.Append("\tfloat depth1 = texture(depthSrc, uv_coords + ofsScale).x;");
+ fragmentGenerator.Append("\tdepth1 += texture(depthSrc, uv_coords - ofsScale).x;");
+ fragmentGenerator.Append(
+ "\tfloat depth2 = texture(depthSrc, uv_coords + 2.0 * ofsScale).x;");
+ fragmentGenerator.Append("\tdepth2 += texture(depthSrc, uv_coords - 2.0 * ofsScale).x;");
+ fragmentGenerator.Append(
+ "\tfloat outDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfragOutput = vec4(outDepth);");
+ fragmentGenerator.Append("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "shadow map blur X shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SShadowmapPreblurShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader);
+ m_OrthoShadowBlurXShader = retval;
+ return m_OrthoShadowBlurXShader.getValue();
+ }
+
+ SShadowmapPreblurShader *CUICRendererImpl::GetOrthoShadowBlurYShader()
+ {
+ if (m_OrthoShadowBlurYShader.hasValue())
+ return m_OrthoShadowBlurYShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords.xy = attr_uv.xy;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("camera_properties", "vec2");
+ fragmentGenerator.AddUniform("depthSrc", "sampler2D");
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec2 ofsScale = vec2( 0.0, camera_properties.x / 7680.0 );");
+ fragmentGenerator.Append("\tfloat depth0 = texture(depthSrc, uv_coords).x;");
+ fragmentGenerator.Append("\tfloat depth1 = texture(depthSrc, uv_coords + ofsScale).x;");
+ fragmentGenerator.Append("\tdepth1 += texture(depthSrc, uv_coords - ofsScale).x;");
+ fragmentGenerator.Append(
+ "\tfloat depth2 = texture(depthSrc, uv_coords + 2.0 * ofsScale).x;");
+ fragmentGenerator.Append("\tdepth2 += texture(depthSrc, uv_coords - 2.0 * ofsScale).x;");
+ fragmentGenerator.Append(
+ "\tfloat outDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;");
+ fragmentGenerator.Append("\tfragOutput = vec4(outDepth);");
+ fragmentGenerator.Append("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "shadow map blur Y shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SShadowmapPreblurShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader);
+ m_OrthoShadowBlurYShader = retval;
+ return m_OrthoShadowBlurYShader.getValue();
+ }
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ SAdvancedModeBlendShader *
+ CUICRendererImpl::GetAdvancedBlendModeShader(AdvancedBlendModes::Enum blendMode)
+ {
+ // Select between blend equations.
+ if (blendMode == AdvancedBlendModes::Overlay) {
+ return GetOverlayBlendModeShader();
+ } else if (blendMode == AdvancedBlendModes::ColorBurn) {
+ return GetColorBurnBlendModeShader();
+ } else if (blendMode == AdvancedBlendModes::ColorDodge) {
+ return GetColorDodgeBlendModeShader();
+ }
+ return {};
+ }
+
+ SAdvancedModeBlendShader *CUICRendererImpl::GetOverlayBlendModeShader()
+ {
+ if (m_AdvancedModeOverlayBlendShader.hasValue())
+ return m_AdvancedModeOverlayBlendShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("base_layer", "sampler2D");
+ fragmentGenerator.AddUniform("blend_layer", "sampler2D");
+
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec4 base = texture2D( base_layer, uv_coords );");
+ fragmentGenerator.Append("\tvec4 blend_orig = texture2D( blend_layer, uv_coords );");
+ fragmentGenerator.Append("\tvec4 blend = blend_orig * vec4(blend_orig.a);");
+
+ fragmentGenerator.Append("\tvec3 res = vec3(0.0, 0.0, 0.0);");
+
+ // As we are doing per-object pass we need to directly copy the base layer
+ // fragment whenever there is no object in the blend layer (alpha = 0), in order to
+ // preserve already-rendered objects and background-colored pixels.
+ // Fragments with base alpha = 0 indicate fully transparent background
+ // in which case we use blend layer fragments directly.
+ NVRenderShaderProgram *theShader;
+ fragmentGenerator.Append("if (blend_orig.a != 0.0 && base.a != 0.0) {");
+ fragmentGenerator.Append(
+ "\tres.r = (base.r < 0.5? (2.0 * base.r * blend.r) : "
+ "(1.0 - 2.0 * (1.0 - base.r) * (1.0 - blend.r)));");
+ fragmentGenerator.Append(
+ "\tres.g = (base.g < 0.5? (2.0 * base.g * blend.g) : "
+ "(1.0 - 2.0 * (1.0 - base.g) * (1.0 - blend.g)));");
+ fragmentGenerator.Append(
+ "\tres.b = (base.b < 0.5? (2.0 * base.b * blend.b) : "
+ "(1.0 - 2.0 * (1.0 - base.b) * (1.0 - blend.b)));");
+ fragmentGenerator.Append("\tgl_FragColor = vec4(res.rgb, blend_orig.a);");
+ fragmentGenerator.Append("} else if (base.a == 0.0 && blend_orig.a == 0.0) {");
+ fragmentGenerator.Append("\tgl_FragColor = vec4(blend.rgb , 0.0);");
+ fragmentGenerator.Append("} else if (base.a == 0.0) {");
+ fragmentGenerator.Append("\tgl_FragColor = vec4(blend.rgb , 1.0);");
+ fragmentGenerator.Append("} else {");
+ fragmentGenerator.Append("\tgl_FragColor = vec4(base.rgb, 1.0);");
+ fragmentGenerator.Append("}");
+ fragmentGenerator.Append("}");
+ theShader = GetProgramGenerator().CompileGeneratedShader(
+ "advanced overlay shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ NVScopedRefCounted<SAdvancedModeBlendShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader);
+ m_AdvancedModeOverlayBlendShader = retval;
+ return m_AdvancedModeOverlayBlendShader.getValue();
+ }
+
+ SAdvancedModeBlendShader *CUICRendererImpl::GetColorBurnBlendModeShader()
+ {
+ if (m_AdvancedModeColorBurnBlendShader.hasValue())
+ return m_AdvancedModeColorBurnBlendShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("base_layer", "sampler2D");
+ fragmentGenerator.AddUniform("blend_layer", "sampler2D");
+
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec4 base = texture2D( base_layer, uv_coords );");
+ fragmentGenerator.Append("\tvec4 blend_orig = texture2D( blend_layer, uv_coords );");
+ fragmentGenerator.Append("\tvec4 blend = blend_orig * vec4(blend_orig.a);");
+
+ fragmentGenerator.Append("\tvec3 res = vec3(0.0, 0.0, 0.0);");
+
+ // As we are doing per-object pass we need to directly copy the base layer
+ // fragment whenever there is no object in the blend layer (alpha = 0), in order to
+ // preserve already-rendered objects and background-colored pixels.
+ // Fragments with base alpha = 0 indicate fully transparent background
+ // in which case we use blend layer fragments directly.
+ NVRenderShaderProgram *theShader;
+ fragmentGenerator.Append("if (blend_orig.a != 0.0 && base.a != 0.0) {");
+ fragmentGenerator.Append(
+ "\tres.r = ((base.r == 1.0) ? 1.0 : "
+ "(blend.r == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.r) / blend.r)));");
+ fragmentGenerator.Append(
+ "\tres.g = ((base.g == 1.0) ? 1.0 : "
+ "(blend.g == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.g) / blend.g)));");
+ fragmentGenerator.Append(
+ "\tres.b = ((base.b == 1.0) ? 1.0 : "
+ "(blend.b == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.b) / blend.b)));");
+ fragmentGenerator.Append("\tgl_FragColor = vec4(res.rgb, blend_orig.a);");
+ fragmentGenerator.Append("} else if (base.a == 0.0) {");
+ fragmentGenerator.Append("\tgl_FragColor = blend;");
+ fragmentGenerator.Append("} else {");
+ fragmentGenerator.Append("\tgl_FragColor = base;");
+ fragmentGenerator.Append("}");
+ fragmentGenerator.Append("}");
+
+ theShader = GetProgramGenerator().CompileGeneratedShader(
+ "advanced colorBurn shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SAdvancedModeBlendShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader);
+ m_AdvancedModeColorBurnBlendShader = retval;
+ return m_AdvancedModeColorBurnBlendShader.getValue();
+
+ }
+
+ SAdvancedModeBlendShader *CUICRendererImpl::GetColorDodgeBlendModeShader()
+ {
+ if (m_AdvancedModeColorDodgeBlendShader.hasValue())
+ return m_AdvancedModeColorDodgeBlendShader.getValue();
+
+ GetProgramGenerator().BeginProgram();
+
+ IShaderStageGenerator &vertexGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex));
+ IShaderStageGenerator &fragmentGenerator(
+ *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment));
+ vertexGenerator.AddIncoming("attr_pos", "vec3");
+ vertexGenerator.AddIncoming("attr_uv", "vec2");
+ vertexGenerator.AddOutgoing("uv_coords", "vec2");
+ vertexGenerator.Append("void main() {");
+ vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );");
+ vertexGenerator.Append("\tuv_coords = attr_uv;");
+ vertexGenerator.Append("}");
+
+ fragmentGenerator.AddUniform("base_layer", "sampler2D");
+ fragmentGenerator.AddUniform("blend_layer", "sampler2D");
+
+ fragmentGenerator.Append("void main() {");
+ fragmentGenerator.Append("\tvec4 base = texture2D( base_layer, uv_coords );");
+ fragmentGenerator.Append("\tvec4 blend_orig = texture2D( blend_layer, uv_coords );");
+ fragmentGenerator.Append("\tvec4 blend = blend_orig * vec4(blend_orig.a);");
+
+ fragmentGenerator.Append("\tvec3 res = vec3(0.0, 0.0, 0.0);");
+
+ // As we are doing per-object pass we need to directly copy the base layer
+ // fragment whenever there is no object in the blend layer (alpha = 0), in order to
+ // preserve already-rendered objects and background-colored pixels.
+ // Fragments with base alpha = 0 indicate fully transparent background
+ // in which case we use blend layer fragments directly.
+ NVRenderShaderProgram *theShader;
+ fragmentGenerator.Append("if (blend_orig.a != 0.0 && base.a != 0.0) {");
+ fragmentGenerator.Append(
+ "\tres.r = ((base.r == 0.0) ? 0.0 : "
+ "(blend.r == 1.0) ? 1.0 : min(base.r / (1.0 - blend.r), 1.0));");
+ fragmentGenerator.Append(
+ "\tres.g = ((base.g == 0.0) ? 0.0 : "
+ "(blend.g == 1.0) ? 1.0 : min(base.g / (1.0 - blend.g), 1.0));");
+ fragmentGenerator.Append(
+ "\tres.b = ((base.b == 0.0) ? 0.0 : "
+ "(blend.b == 1.0) ? 1.0 : min(base.b / (1.0 - blend.b), 1.0));");
+ fragmentGenerator.Append("\tgl_FragColor = vec4(res.rgb, blend_orig.a);");
+ fragmentGenerator.Append("} else if (base.a == 0.0) {");
+ fragmentGenerator.Append("\tgl_FragColor = blend;");
+ fragmentGenerator.Append("} else {");
+ fragmentGenerator.Append("\tgl_FragColor = base;");
+ fragmentGenerator.Append("}");
+ fragmentGenerator.Append("}");
+ theShader = GetProgramGenerator().CompileGeneratedShader(
+ "advanced colorDodge shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SAdvancedModeBlendShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader);
+ m_AdvancedModeColorDodgeBlendShader = retval;
+ return m_AdvancedModeColorDodgeBlendShader.getValue();
+
+ }
+#endif
+}
+}
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h
new file mode 100644
index 00000000..fd5e2a1f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICRendererImplShaders.h
@@ -0,0 +1,450 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDERER_IMPL_SHADERS_H
+#define UIC_RENDERER_IMPL_SHADERS_H
+#include "UICRender.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderProgramPipeline.h"
+
+namespace uic {
+namespace render {
+ using qt3ds::render::NVRenderCachedShaderProperty;
+ using qt3ds::render::NVRenderCachedShaderBuffer;
+
+ /**
+ * Cached tessellation property lookups this is on a per mesh base
+ */
+ struct SShaderTessellationProperties
+ {
+ NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessLevel; ///< tesselation value for the edges
+ NVRenderCachedShaderProperty<QT3DSF32> m_InsideTessLevel; ///< tesselation value for the inside
+ NVRenderCachedShaderProperty<QT3DSF32>
+ m_PhongBlend; ///< blending between linear and phong component
+ NVRenderCachedShaderProperty<QT3DSVec2>
+ m_DistanceRange; ///< distance range for min and max tess level
+ NVRenderCachedShaderProperty<QT3DSF32> m_DisableCulling; ///< if set to 1.0 this disables
+ ///backface culling optimization in
+ ///the tess shader
+
+ SShaderTessellationProperties() {}
+ SShaderTessellationProperties(NVRenderShaderProgram &inShader)
+ : m_EdgeTessLevel("tessLevelOuter", inShader)
+ , m_InsideTessLevel("tessLevelInner", inShader)
+ , m_PhongBlend("phongBlend", inShader)
+ , m_DistanceRange("distanceRange", inShader)
+ , m_DisableCulling("disableCulling", inShader)
+ {
+ }
+ };
+
+ /**
+ * The results of generating a shader. Caches all possible variable names into
+ * typesafe objects.
+ */
+ struct SShaderGeneratorGeneratedShader
+ {
+ QT3DSU32 m_LayerSetIndex;
+ CRegisteredString m_QueryString;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewportMatrix;
+ SShaderTessellationProperties m_Tessellation;
+
+ SShaderGeneratorGeneratedShader(CRegisteredString inQueryString,
+ NVRenderShaderProgram &inShader)
+ : m_LayerSetIndex(QT3DS_MAX_U32)
+ , m_QueryString(inQueryString)
+ , m_Shader(inShader)
+ , m_ViewportMatrix("viewport_matrix", inShader)
+ , m_Tessellation(inShader)
+ {
+ m_Shader.addRef();
+ }
+ ~SShaderGeneratorGeneratedShader() { m_Shader.release(); }
+ static QT3DSU32 GetLayerIndex(const SShaderGeneratorGeneratedShader &inShader)
+ {
+ return inShader.m_LayerSetIndex;
+ }
+ static void SetLayerIndex(SShaderGeneratorGeneratedShader &inShader, QT3DSU32 idx)
+ {
+ inShader.m_LayerSetIndex = idx;
+ }
+ };
+
+ struct SDefaultMaterialRenderableDepthShader
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+
+ QT3DSI32 m_RefCount;
+ SDefaultMaterialRenderableDepthShader(NVRenderShaderProgram &inShader,
+ NVRenderContext &inContext)
+ : m_Allocator(inContext.GetAllocator())
+ , m_Shader(inShader)
+ , m_MVP("model_view_projection", inShader)
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+
+ ~SDefaultMaterialRenderableDepthShader() { m_Shader.release(); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ NVDelete(m_Allocator, this);
+ }
+ };
+
+ /**
+ * Cached texture property lookups, used one per texture so a shader generator for N
+ * textures will have an array of N of these lookup objects.
+ */
+ struct SShaderTextureProperties
+ {
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_Offsets;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_Rotations;
+ SShaderTextureProperties(const char *sampName, const char *offName, const char *rotName,
+ NVRenderShaderProgram &inShader)
+ : m_Sampler(sampName, inShader)
+ , m_Offsets(offName, inShader)
+ , m_Rotations(rotName, inShader)
+ {
+ }
+ SShaderTextureProperties() {}
+ };
+
+ struct SRenderableDepthPrepassShader
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_GlobalTransform;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_Projection;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPosition;
+ NVRenderCachedShaderProperty<QT3DSF32> m_DisplaceAmount;
+ SShaderTextureProperties m_DisplacementProps;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraDirection;
+ // NVRenderCachedShaderProperty<QT3DSMat44> m_ShadowMV[6];
+
+ QT3DSI32 m_RefCount;
+ // Cache the tessellation property name lookups
+ SShaderTessellationProperties m_Tessellation;
+
+ SRenderableDepthPrepassShader(NVRenderShaderProgram &inShader, NVRenderContext &inContext)
+ : m_Allocator(inContext.GetAllocator())
+ , m_Shader(inShader)
+ , m_MVP("model_view_projection", inShader)
+ , m_GlobalTransform("model_matrix", inShader)
+ , m_Projection("projection", inShader)
+ , m_CameraPosition("camera_position", inShader)
+ , m_DisplaceAmount("displaceAmount", inShader)
+ , m_DisplacementProps("displacementSampler", "displacementMap_offset",
+ "displacementMap_rot", inShader)
+ , m_CameraProperties("camera_properties", inShader)
+ , m_CameraDirection("camera_direction", inShader)
+ , m_RefCount(0)
+ , m_Tessellation(inShader)
+ {
+ /*
+ m_ShadowMV[0].m_Shader = &inShader;
+ m_ShadowMV[0].m_Constant = inShader.GetShaderConstant( "shadow_mv0" );
+ m_ShadowMV[1].m_Shader = &inShader;
+ m_ShadowMV[1].m_Constant = inShader.GetShaderConstant( "shadow_mv1" );
+ m_ShadowMV[2].m_Shader = &inShader;
+ m_ShadowMV[2].m_Constant = inShader.GetShaderConstant( "shadow_mv2" );
+ m_ShadowMV[3].m_Shader = &inShader;
+ m_ShadowMV[3].m_Constant = inShader.GetShaderConstant( "shadow_mv3" );
+ m_ShadowMV[4].m_Shader = &inShader;
+ m_ShadowMV[4].m_Constant = inShader.GetShaderConstant( "shadow_mv4" );
+ m_ShadowMV[5].m_Shader = &inShader;
+ m_ShadowMV[5].m_Constant = inShader.GetShaderConstant( "shadow_mv5" );
+ */
+ m_Shader.addRef();
+ }
+
+ ~SRenderableDepthPrepassShader() { m_Shader.release(); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ NVDelete(m_Allocator, this);
+ }
+ };
+
+ struct SDefaultAoPassShader
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraDirection;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthTexture;
+ NVRenderCachedShaderProperty<NVRenderTextureCube *> m_CubeTexture;
+
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams;
+ QT3DSI32 m_RefCount;
+
+ SDefaultAoPassShader(NVRenderShaderProgram &inShader, NVRenderContext &inContext)
+ : m_Allocator(inContext.GetAllocator())
+ , m_Shader(inShader)
+ , m_ViewMatrix("view_matrix", inShader)
+ , m_CameraProperties("camera_properties", inShader)
+ , m_CameraDirection("camera_direction", inShader)
+ , m_DepthTexture("depth_sampler", inShader)
+ , m_CubeTexture("depth_cube", inShader)
+ , m_AoShadowParams("cbAoShadow", inShader)
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~SDefaultAoPassShader() { m_Shader.release(); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ NVDelete(m_Allocator, this);
+ }
+ };
+
+ struct STextShader
+ {
+ NVRenderShaderProgram &m_Shader;
+
+ NVScopedRefCounted<NVRenderProgramPipeline> m_ProgramPipeline;
+
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+ // Dimensions and offsetting of the image.
+ NVRenderCachedShaderProperty<QT3DSVec4> m_Dimensions;
+ // The fourth member of text color is the opacity
+ NVRenderCachedShaderProperty<QT3DSVec4> m_TextColor;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_BackgroundColor;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+ // Dimensions and offsetting of the texture
+ NVRenderCachedShaderProperty<QT3DSVec3> m_TextDimensions;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+ // Used only for onscreen text
+ NVRenderCachedShaderProperty<QT3DSVec2> m_VertexOffsets;
+
+ STextShader(NVRenderShaderProgram &shader, NVRenderProgramPipeline *pipeline = NULL)
+ : m_Shader(shader)
+ , m_ProgramPipeline(pipeline)
+ , m_MVP("model_view_projection", shader)
+ , m_Dimensions("text_dimensions", shader)
+ , m_TextColor("text_textcolor", shader)
+ , m_BackgroundColor("text_backgroundcolor", shader)
+ , m_Sampler("text_image", shader)
+ , m_TextDimensions("text_textdimensions", shader)
+ , m_CameraProperties("camera_properties", shader)
+ , m_VertexOffsets("vertex_offsets", shader)
+ {
+ if (!pipeline)
+ m_Shader.addRef();
+ }
+ ~STextShader()
+ {
+ if (!m_ProgramPipeline.mPtr)
+ m_Shader.release();
+ }
+ void Render(NVRenderTexture2D &inTexture, const STextScaleAndOffset &inScaleAndOffset,
+ const QT3DSVec4 &inTextColor, const QT3DSMat44 &inMVP, const QT3DSVec2 &inCameraVec,
+ NVRenderContext &inRenderContext,
+ NVRenderInputAssembler &inInputAssemblerBuffer, QT3DSU32 count,
+ const STextTextureDetails &inTextTextureDetails,
+ const QT3DSVec3 &inBackgroundColor);
+
+ void RenderPath(NVRenderPathFontItem &inPathFontItem,
+ NVRenderPathFontSpecification &inPathFontSpec,
+ const STextScaleAndOffset &inScaleAndOffset, const QT3DSVec4 &inTextColor,
+ const QT3DSMat44 &inViewProjection, const QT3DSMat44 &inModel,
+ const QT3DSVec2 &inCameraVec, NVRenderContext &inRenderContext,
+ const STextTextureDetails &inTextTextureDetails,
+ const QT3DSVec3 &inBackgroundColor);
+
+ void Render2D(NVRenderTexture2D &inTexture, const QT3DSVec4 &inTextColor, const QT3DSMat44 &inMVP,
+ NVRenderContext &inRenderContext,
+ NVRenderInputAssembler &inInputAssemblerBuffer, QT3DSU32 count,
+ QT3DSVec2 inVertexOffsets);
+ };
+
+ struct STextDepthShader
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+ // Dimensions and offsetting of the image.
+ NVRenderCachedShaderProperty<QT3DSVec4> m_Dimensions;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_TextDimensions;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+ NVRenderInputAssembler &m_QuadInputAssembler;
+ QT3DSI32 m_RefCount;
+
+ STextDepthShader(NVAllocatorCallback &alloc, NVRenderShaderProgram &prog,
+ NVRenderInputAssembler &assembler)
+ : m_Allocator(alloc)
+ , m_Shader(prog)
+ , m_MVP("model_view_projection", prog)
+ , m_Dimensions("text_dimensions", prog)
+ , m_TextDimensions("text_textdimensions", prog)
+ , m_CameraProperties("camera_properties", prog)
+ , m_Sampler("text_image", prog)
+ , m_QuadInputAssembler(assembler)
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~STextDepthShader() { m_Shader.release(); }
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ NVDelete(m_Allocator, this);
+ }
+ };
+
+ struct SLayerProgAABlendShader
+ {
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_AccumSampler;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LastFrame;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_BlendFactors;
+ volatile QT3DSI32 mRefCount;
+ SLayerProgAABlendShader(NVRenderShaderProgram &inShader)
+ : m_Shader(inShader)
+ , m_AccumSampler("accumulator", inShader)
+ , m_LastFrame("last_frame", inShader)
+ , m_BlendFactors("blend_factors", inShader)
+ , mRefCount(0)
+ {
+ }
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+ };
+
+ struct SLayerSceneShader
+ {
+ NVRenderShaderProgram &m_Shader;
+
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+ // Dimensions and offsetting of the image.
+ NVRenderCachedShaderProperty<QT3DSVec2> m_Dimensions;
+ // The fourth member of text color is the opacity
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+
+ volatile QT3DSI32 mRefCount;
+
+ SLayerSceneShader(NVRenderShaderProgram &inShader)
+ : m_Shader(inShader)
+ , m_MVP("model_view_projection", inShader)
+ , m_Dimensions("layer_dimensions", inShader)
+ , m_Sampler("layer_image", inShader)
+ , mRefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~SLayerSceneShader() { m_Shader.release(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader.GetRenderContext().GetAllocator())
+ };
+
+ struct SShadowmapPreblurShader
+ {
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+ NVRenderCachedShaderProperty<NVRenderTextureCube *> m_DepthCube;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthMap;
+
+ volatile QT3DSI32 mRefCount;
+
+ SShadowmapPreblurShader(NVRenderShaderProgram &inShader)
+ : m_Shader(inShader)
+ , m_CameraProperties("camera_properties", inShader)
+ , m_DepthCube("depthCube", inShader)
+ , m_DepthMap("depthSrc", inShader)
+ , mRefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~SShadowmapPreblurShader() { m_Shader.release(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader.GetRenderContext().GetAllocator())
+ };
+
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ struct SAdvancedModeBlendShader
+ {
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_baseLayer;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_blendLayer;
+
+ volatile QT3DSI32 mRefCount;
+
+ SAdvancedModeBlendShader(NVRenderShaderProgram &inShader)
+ : m_Shader(inShader)
+ , m_baseLayer("base_layer", inShader)
+ , m_blendLayer("blend_layer", inShader)
+ , mRefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~SAdvancedModeBlendShader() { m_Shader.release(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader.GetRenderContext().GetAllocator())
+
+ };
+#endif
+
+ struct SGGSGet
+ {
+ QT3DSU32 operator()(const SShaderGeneratorGeneratedShader &inShader)
+ {
+ return inShader.m_LayerSetIndex;
+ }
+ };
+ struct SGGSSet
+ {
+ void operator()(SShaderGeneratorGeneratedShader &inShader, QT3DSU32 idx)
+ {
+ inShader.m_LayerSetIndex = idx;
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICRender/RendererImpl/UICVertexPipelineImpl.h b/src/Runtime/Source/UICRender/RendererImpl/UICVertexPipelineImpl.h
new file mode 100644
index 00000000..47419a99
--- /dev/null
+++ b/src/Runtime/Source/UICRender/RendererImpl/UICVertexPipelineImpl.h
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_VERTEX_PIPELINE_IMPL_H
+#define UIC_VERTEX_PIPELINE_IMPL_H
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+
+namespace uic {
+namespace render {
+ // Baseclass for the vertex pipelines to be sure we have consistent implementations.
+ struct SVertexPipelineImpl : public IDefaultMaterialVertexPipeline
+ {
+ struct GenerationFlagValues
+ {
+ enum Enum {
+ UVCoords = 1,
+ EnvMapReflection = 1 << 1,
+ ViewVector = 1 << 2,
+ WorldNormal = 1 << 3,
+ ObjectNormal = 1 << 4,
+ WorldPosition = 1 << 5,
+ TangentBinormal = 1 << 6,
+ UVCoords1 = 1 << 7,
+ };
+ };
+
+ typedef TStrTableStrMap::const_iterator TParamIter;
+ typedef NVFlags<GenerationFlagValues::Enum> TGenerationFlags;
+
+ IMaterialShaderGenerator &m_MaterialGenerator;
+ IShaderProgramGenerator &m_ProgramGenerator;
+ IStringTable &m_StringTable;
+ CRenderString m_TempString;
+
+ TGenerationFlags m_GenerationFlags;
+ bool m_Wireframe;
+ TStrTableStrMap m_InterpolationParameters;
+ QT3DSU32 m_DisplacementIdx;
+ SRenderableImage *m_DisplacementImage;
+ QStringList m_addedFunctions;
+
+ SVertexPipelineImpl(NVAllocatorCallback &inAllocator, IMaterialShaderGenerator &inMaterial,
+ IShaderProgramGenerator &inProgram, IStringTable &inStringTable,
+ bool inWireframe // only works if tessellation is true
+ )
+
+ : m_MaterialGenerator(inMaterial)
+ , m_ProgramGenerator(inProgram)
+ , m_StringTable(inStringTable)
+ , m_Wireframe(inWireframe)
+ , m_InterpolationParameters(inAllocator, "m_InterpolationParameters")
+ , m_DisplacementIdx(0)
+ , m_DisplacementImage(NULL)
+ {
+ }
+
+ // Trues true if the code was *not* set.
+ bool SetCode(GenerationFlagValues::Enum inCode)
+ {
+ if (((QT3DSU32)m_GenerationFlags & inCode) != 0)
+ return true;
+ m_GenerationFlags |= inCode;
+ return false;
+ }
+ bool HasCode(GenerationFlagValues::Enum inCode)
+ {
+ return ((QT3DSU32)(m_GenerationFlags & inCode)) != 0;
+ }
+ IShaderProgramGenerator &ProgramGenerator() { return m_ProgramGenerator; }
+ IShaderStageGenerator &Vertex()
+ {
+ return *ProgramGenerator().GetStage(ShaderGeneratorStages::Vertex);
+ }
+ IShaderStageGenerator &TessControl()
+ {
+ return *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl);
+ }
+ IShaderStageGenerator &TessEval()
+ {
+ return *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval);
+ }
+ IShaderStageGenerator &Geometry()
+ {
+ return *ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry);
+ }
+ IShaderStageGenerator &Fragment()
+ {
+ return *ProgramGenerator().GetStage(ShaderGeneratorStages::Fragment);
+ }
+ IMaterialShaderGenerator &MaterialGenerator() { return m_MaterialGenerator; }
+
+ void SetupDisplacement(QT3DSU32 displacementImageIdx, SRenderableImage *displacementImage)
+ {
+ m_DisplacementIdx = displacementImageIdx;
+ m_DisplacementImage = displacementImage;
+ }
+
+ CRegisteredString Str(const char8_t *inItem) { return m_StringTable.RegisterStr(inItem); }
+
+ bool HasTessellation() const
+ {
+ return m_ProgramGenerator.GetEnabledStages() & ShaderGeneratorStages::TessEval;
+ }
+ bool HasGeometryStage() const
+ {
+ return m_ProgramGenerator.GetEnabledStages() & ShaderGeneratorStages::Geometry;
+ }
+ bool HasDisplacment() const { return m_DisplacementImage != NULL; }
+
+ void InitializeWireframeGeometryShader()
+ {
+ if (m_Wireframe && ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry)
+ && ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)) {
+ IShaderStageGenerator &geometryShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry));
+ // currently geometry shader is only used for drawing wireframe
+ if (m_Wireframe) {
+ geometryShader.AddUniform("viewport_matrix", "mat4");
+ geometryShader.AddOutgoing("varEdgeDistance", "vec3");
+ geometryShader.Append("layout (triangles) in;");
+ geometryShader.Append("layout (triangle_strip, max_vertices = 3) out;");
+ geometryShader.Append("void main() {");
+
+ // how this all work see
+ // http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf
+
+ geometryShader.Append(
+ "// project points to screen space\n"
+ "\tvec3 p0 = vec3(viewport_matrix * (gl_in[0].gl_Position / "
+ "gl_in[0].gl_Position.w));\n"
+ "\tvec3 p1 = vec3(viewport_matrix * (gl_in[1].gl_Position / "
+ "gl_in[1].gl_Position.w));\n"
+ "\tvec3 p2 = vec3(viewport_matrix * (gl_in[2].gl_Position / "
+ "gl_in[2].gl_Position.w));\n"
+ "// compute triangle heights\n"
+ "\tfloat e1 = length(p1 - p2);\n"
+ "\tfloat e2 = length(p2 - p0);\n"
+ "\tfloat e3 = length(p1 - p0);\n"
+ "\tfloat alpha = acos( (e2*e2 + e3*e3 - e1*e1) / (2.0*e2*e3) );\n"
+ "\tfloat beta = acos( (e1*e1 + e3*e3 - e2*e2) / (2.0*e1*e3) );\n"
+ "\tfloat ha = abs( e3 * sin( beta ) );\n"
+ "\tfloat hb = abs( e3 * sin( alpha ) );\n"
+ "\tfloat hc = abs( e2 * sin( alpha ) );\n");
+ }
+ }
+ }
+
+ void FinalizeWireframeGeometryShader()
+ {
+ IShaderStageGenerator &geometryShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry));
+
+ if (m_Wireframe == true && ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry)
+ && ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)) {
+ const char8_t *theExtension("TE[");
+ // we always assume triangles
+ for (size_t i = 0; i < 3; i++) {
+ char buf[10];
+ sprintf(buf, "%lu", i);
+ for (TStrTableStrMap::const_iterator iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ geometryShader << "\t" << iter->first.c_str() << " = "
+ << iter->first.c_str() << theExtension << buf << "];\n";
+ }
+
+ geometryShader << "\tgl_Position = gl_in[" << buf << "].gl_Position;\n";
+ // the triangle distance is interpolated through the shader stage
+ if (i == 0)
+ geometryShader << "\n\tvarEdgeDistance = vec3(ha*"
+ << "gl_in[" << buf << "].gl_Position.w, 0.0, 0.0);\n";
+ else if (i == 1)
+ geometryShader << "\n\tvarEdgeDistance = vec3(0.0, hb*"
+ << "gl_in[" << buf << "].gl_Position.w, 0.0);\n";
+ else if (i == 2)
+ geometryShader << "\n\tvarEdgeDistance = vec3(0.0, 0.0, hc*"
+ << "gl_in[" << buf << "].gl_Position.w);\n";
+
+ // submit vertex
+ geometryShader << "\tEmitVertex();\n";
+ }
+ // end primitive
+ geometryShader << "\tEndPrimitive();\n";
+ }
+ }
+
+ virtual void SetupTessIncludes(ShaderGeneratorStages::Enum inStage,
+ TessModeValues::Enum inTessMode)
+ {
+ IShaderStageGenerator &tessShader(*ProgramGenerator().GetStage(inStage));
+
+ // depending on the selected tessellation mode chose program
+ switch (inTessMode) {
+ case TessModeValues::TessPhong:
+ tessShader.AddInclude("tessellationPhong.glsllib");
+ break;
+ case TessModeValues::TessNPatch:
+ tessShader.AddInclude("tessellationNPatch.glsllib");
+ break;
+ default:
+ QT3DS_ASSERT(false); // fallthrough intentional
+ case TessModeValues::TessLinear:
+ tessShader.AddInclude("tessellationLinear.glsllib");
+ break;
+ }
+ }
+
+ void GenerateUVCoords(QT3DSU32 inUVSet = 0) override
+ {
+ if (inUVSet == 0 && SetCode(GenerationFlagValues::UVCoords))
+ return;
+ if (inUVSet == 1 && SetCode(GenerationFlagValues::UVCoords1))
+ return;
+
+ QT3DS_ASSERT(inUVSet == 0 || inUVSet == 1);
+
+ if (inUVSet == 0)
+ AddInterpolationParameter("varTexCoord0", "vec2");
+ else if (inUVSet == 1)
+ AddInterpolationParameter("varTexCoord1", "vec2");
+
+ DoGenerateUVCoords(inUVSet);
+ }
+ void GenerateEnvMapReflection() override
+ {
+ if (SetCode(GenerationFlagValues::EnvMapReflection))
+ return;
+
+ GenerateWorldPosition();
+ GenerateWorldNormal();
+ IShaderStageGenerator &activeGenerator(ActiveStage());
+ activeGenerator.AddInclude("viewProperties.glsllib");
+ AddInterpolationParameter("var_object_to_camera", "vec3");
+ activeGenerator.Append("\tvar_object_to_camera = normalize( local_model_world_position "
+ "- camera_position );");
+ // World normal cannot be relied upon in the vertex shader because of bump maps.
+ Fragment().Append("\tvec3 environment_map_reflection = reflect( "
+ "normalize(var_object_to_camera), world_normal.xyz );");
+ Fragment().Append("\tenvironment_map_reflection *= vec3( 0.5, 0.5, 0 );");
+ Fragment().Append("\tenvironment_map_reflection += vec3( 0.5, 0.5, 1.0 );");
+ }
+ void GenerateViewVector() override
+ {
+ if (SetCode(GenerationFlagValues::ViewVector))
+ return;
+ GenerateWorldPosition();
+ IShaderStageGenerator &activeGenerator(ActiveStage());
+ activeGenerator.AddInclude("viewProperties.glsllib");
+ AddInterpolationParameter("varViewVector", "vec3");
+ activeGenerator.Append("\tvec3 local_view_vector = normalize(camera_position - "
+ "local_model_world_position);");
+ AssignOutput("varViewVector", "local_view_vector");
+ Fragment() << "\tvec3 view_vector = normalize(varViewVector);" << Endl;
+ }
+
+ // fragment shader expects varying vertex normal
+ // lighting in vertex pipeline expects world_normal
+ void GenerateWorldNormal() override
+ {
+ if (SetCode(GenerationFlagValues::WorldNormal))
+ return;
+ AddInterpolationParameter("varNormal", "vec3");
+ DoGenerateWorldNormal();
+ Fragment().Append("\tvec3 world_normal = normalize( varNormal );");
+ }
+ void GenerateObjectNormal() override
+ {
+ if (SetCode(GenerationFlagValues::ObjectNormal))
+ return;
+ DoGenerateObjectNormal();
+ Fragment().Append("\tvec3 object_normal = normalize(varObjectNormal);");
+ }
+ void GenerateWorldPosition() override
+ {
+ if (SetCode(GenerationFlagValues::WorldPosition))
+ return;
+
+ ActiveStage().AddUniform("model_matrix", "mat4");
+ AddInterpolationParameter("varWorldPos", "vec3");
+ DoGenerateWorldPosition();
+
+ AssignOutput("varWorldPos", "local_model_world_position");
+ }
+ void GenerateVarTangentAndBinormal() override
+ {
+ if (SetCode(GenerationFlagValues::TangentBinormal))
+ return;
+ AddInterpolationParameter("varTangent", "vec3");
+ AddInterpolationParameter("varBinormal", "vec3");
+ DoGenerateVarTangentAndBinormal();
+ Fragment() << "\tvec3 tangent = normalize(varTangent);" << Endl
+ << "\tvec3 binormal = normalize(varBinormal);" << Endl;
+ }
+
+ bool HasActiveWireframe() override { return m_Wireframe; }
+
+ // IShaderStageGenerator interface
+ void AddIncoming(const char8_t *name, const char8_t *type) override
+ {
+ ActiveStage().AddIncoming(name, type);
+ }
+ void AddIncoming(const TStrType &name, const char8_t *type) override
+ {
+ AddIncoming(name.c_str(), type);
+ }
+
+ void AddOutgoing(const char8_t *name, const char8_t *type) override
+ {
+ AddInterpolationParameter(name, type);
+ }
+ void AddOutgoing(const TStrType &name, const char8_t *type) override
+ {
+ AddOutgoing(name.c_str(), type);
+ }
+
+ void AddUniform(const char8_t *name, const char8_t *type) override
+ {
+ ActiveStage().AddUniform(name, type);
+ }
+ void AddUniform(const TStrType &name, const char8_t *type) override
+ {
+ AddUniform(name.c_str(), type);
+ }
+
+ void AddInclude(const char8_t *name) override { ActiveStage().AddInclude(name); }
+ void AddInclude(const TStrType &name) override { AddInclude(name.c_str()); }
+ void AddInclude(const QString &name) override
+ {
+ QByteArray arr = name.toLatin1();
+ AddInclude(arr.data());
+ }
+
+ void AddFunction(const QString &functionName) override
+ {
+ if (!m_addedFunctions.contains(functionName)) {
+ m_addedFunctions.push_back(functionName);
+ QString includeName;
+ QTextStream stream(&includeName);
+ stream << "func" << functionName << ".glsllib";
+ AddInclude(includeName);
+ }
+ }
+
+ void AddConstantBuffer(const char *name, const char *layout) override
+ {
+ ActiveStage().AddConstantBuffer(name, layout);
+ }
+ void AddConstantBufferParam(const char *cbName, const char *paramName,
+ const char *type) override
+ {
+ ActiveStage().AddConstantBufferParam(cbName, paramName, type);
+ }
+
+ IShaderStageGenerator &operator<<(const char *data) override
+ {
+ ActiveStage() << data;
+ return *this;
+ }
+ IShaderStageGenerator &operator<<(const TStrType &data) override
+ {
+ ActiveStage() << data;
+ return *this;
+ }
+ IShaderStageGenerator &operator<<(const SEndlType &data) override
+ {
+ ActiveStage() << data;
+ return *this;
+ }
+ void Append(const char *data) override { ActiveStage().Append(data); }
+ void AppendPartial(const char *data) override { ActiveStage().Append(data); }
+
+ ShaderGeneratorStages::Enum Stage() const override
+ {
+ return const_cast<SVertexPipelineImpl *>(this)->ActiveStage().Stage();
+ }
+
+ void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) override = 0;
+ void AssignOutput(const char8_t *inVarName, const char8_t *inVarValueExpr) override = 0;
+ void EndVertexGeneration() override = 0;
+
+ void BeginFragmentGeneration() override = 0;
+ void EndFragmentGeneration() override = 0;
+
+ virtual IShaderStageGenerator &ActiveStage() = 0;
+ virtual void AddInterpolationParameter(const char8_t *inParamName,
+ const char8_t *inParamType) = 0;
+
+ virtual void DoGenerateUVCoords(QT3DSU32 inUVSet) = 0;
+ virtual void DoGenerateWorldNormal() = 0;
+ virtual void DoGenerateObjectNormal() = 0;
+ virtual void DoGenerateWorldPosition() = 0;
+ virtual void DoGenerateVarTangentAndBinormal() = 0;
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.cpp
new file mode 100644
index 00000000..725a3c2e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderBufferLoader.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSSync.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderThreadPool.h"
+
+using namespace uic::render;
+
+namespace {
+struct SBufferLoader;
+struct SBufferLoadResult : public ILoadedBuffer
+{
+ NVFoundationBase &m_Foundation;
+ CRegisteredString m_Path;
+ IBufferLoaderCallback *m_UserData;
+ NVDataRef<QT3DSU8> m_Data;
+ QT3DSI32 mRefCount;
+
+ SBufferLoadResult(NVFoundationBase &fnd, CRegisteredString p, IBufferLoaderCallback *ud,
+ NVDataRef<QT3DSU8> data)
+ : m_Foundation(fnd)
+ , m_Path(p)
+ , m_UserData(ud)
+ , m_Data(data)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ CRegisteredString Path() override { return m_Path; }
+ // Data is released when the buffer itself is released.
+ NVDataRef<QT3DSU8> Data() override { return m_Data; }
+ IBufferLoaderCallback *UserData() override { return m_UserData; }
+
+ static SBufferLoadResult *Allocate(QT3DSU32 inBufferSize, NVFoundationBase &fnd,
+ CRegisteredString p,
+ NVScopedRefCounted<IBufferLoaderCallback> ud)
+ {
+ size_t allocSize = sizeof(SBufferLoadResult) + inBufferSize;
+ QT3DSU8 *allocMem =
+ (QT3DSU8 *)fnd.getAllocator().allocate(allocSize, "ILoadedBuffer", __FILE__, __LINE__);
+ if (allocMem == NULL)
+ return NULL;
+ QT3DSU8 *bufferStart = allocMem + sizeof(SBufferLoadResult);
+ NVDataRef<QT3DSU8> dataBuffer = toDataRef(bufferStart, inBufferSize);
+ return new (allocMem) SBufferLoadResult(fnd, p, ud, dataBuffer);
+ }
+};
+struct SLoadedBufferImpl
+{
+ SBufferLoader &m_Loader;
+ QT3DSU64 m_JobId;
+ QT3DSU64 m_LoadId;
+ CRegisteredString m_Path;
+ NVScopedRefCounted<IBufferLoaderCallback> m_UserData;
+ bool m_Quiet;
+ volatile bool m_Cancel;
+ NVScopedRefCounted<SBufferLoadResult> m_Result;
+ SLoadedBufferImpl *m_NextBuffer;
+ SLoadedBufferImpl *m_PreviousBuffer;
+
+ SLoadedBufferImpl(SBufferLoader &l, CRegisteredString inPath,
+ NVScopedRefCounted<IBufferLoaderCallback> ud, bool inQuiet, QT3DSU64 loadId)
+ : m_Loader(l)
+ , m_JobId(0)
+ , m_LoadId(loadId)
+ , m_Path(inPath)
+ , m_UserData(ud)
+ , m_Quiet(inQuiet)
+ , m_Cancel(false)
+ , m_NextBuffer(NULL)
+ , m_PreviousBuffer(NULL)
+ {
+ }
+};
+
+DEFINE_INVASIVE_LIST(LoadedBufferImpl);
+IMPLEMENT_INVASIVE_LIST(LoadedBufferImpl, m_PreviousBuffer, m_NextBuffer);
+
+struct SBufferLoader : public IBufferLoader
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IInputStreamFactory> m_Factory;
+ NVScopedRefCounted<IThreadPool> m_ThreadPool;
+
+ Mutex m_BuffersToLoadMutex;
+ TLoadedBufferImplList m_BuffersToLoad;
+
+ Mutex m_BuffersLoadingMutex;
+ TLoadedBufferImplList m_BuffersLoading;
+
+ Mutex m_LoadedBuffersMutex;
+ TLoadedBufferImplList m_LoadedBuffers;
+
+ Sync m_BufferLoadedEvent;
+
+ QT3DSU64 m_NextBufferId;
+
+ QT3DSI32 mRefCount;
+
+ SBufferLoader(NVFoundationBase &fnd, IInputStreamFactory &fac, IThreadPool &tp)
+ : m_Foundation(fnd)
+ , m_Factory(fac)
+ , m_ThreadPool(tp)
+ , m_BuffersToLoadMutex(fnd.getAllocator())
+ , m_BuffersLoadingMutex(fnd.getAllocator())
+ , m_LoadedBuffersMutex(fnd.getAllocator())
+ , m_BufferLoadedEvent(fnd.getAllocator())
+ , m_NextBufferId(1)
+ , mRefCount(0)
+ {
+ m_BufferLoadedEvent.reset();
+ }
+
+ virtual ~SBufferLoader()
+ {
+ {
+ Mutex::ScopedLock __locker(m_BuffersToLoadMutex);
+ for (TLoadedBufferImplList::iterator iter = m_BuffersToLoad.begin(),
+ end = m_BuffersToLoad.end();
+ iter != end; ++iter) {
+ m_ThreadPool->CancelTask(iter->m_JobId);
+ }
+ }
+
+ // Pull any remaining buffers out of the thread system.
+ while (WillLoadedBuffersBeAvailable()) {
+ NextLoadedBuffer();
+ }
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ static void InitializeActiveLoadingBuffer(SLoadedBufferImpl &theBuffer)
+ {
+ Mutex::ScopedLock theLocker(theBuffer.m_Loader.m_BuffersToLoadMutex);
+ Mutex::ScopedLock theSecondLocker(theBuffer.m_Loader.m_BuffersLoadingMutex);
+ theBuffer.m_Loader.m_BuffersToLoad.remove(theBuffer);
+ theBuffer.m_Loader.m_BuffersLoading.push_back(theBuffer);
+ }
+
+ static void SetBufferAsLoaded(SLoadedBufferImpl &theBuffer)
+ {
+ Mutex::ScopedLock theSecondLocker(theBuffer.m_Loader.m_BuffersLoadingMutex);
+ Mutex::ScopedLock theLocker(theBuffer.m_Loader.m_LoadedBuffersMutex);
+ theBuffer.m_Loader.m_BuffersLoading.remove(theBuffer);
+ theBuffer.m_Loader.m_LoadedBuffers.push_back(theBuffer);
+ theBuffer.m_Loader.m_BufferLoadedEvent.set();
+ theBuffer.m_Loader.m_BufferLoadedEvent.reset();
+ }
+
+ static void LoadNextBuffer(void *loader)
+ {
+ SLoadedBufferImpl &theBuffer = *reinterpret_cast<SLoadedBufferImpl *>(loader);
+
+ InitializeActiveLoadingBuffer(theBuffer);
+ NVScopedRefCounted<IRefCountedInputStream> theStream =
+ theBuffer.m_Loader.m_Factory->GetStreamForFile(theBuffer.m_Path.c_str(),
+ theBuffer.m_Quiet);
+ if (theStream && theBuffer.m_Cancel == false) {
+ theStream->SetPosition(0, SeekPosition::End);
+ QT3DSI64 theFileLen = theStream->GetPosition();
+ if (theFileLen > 0 && theFileLen < (QT3DSU32)QT3DS_MAX_U32) {
+ QT3DSU32 required = (QT3DSU32)theFileLen;
+ theBuffer.m_Result =
+ SBufferLoadResult::Allocate(required, theBuffer.m_Loader.m_Foundation,
+ theBuffer.m_Path, theBuffer.m_UserData);
+ QT3DSU32 amountRead = 0;
+ QT3DSU32 total = amountRead;
+ if (theBuffer.m_Result && theBuffer.m_Cancel == false) {
+ NVDataRef<QT3DSU8> theDataBuffer(theBuffer.m_Result->m_Data);
+ theStream->SetPosition(0, SeekPosition::Begin);
+ amountRead = theStream->Read(theDataBuffer);
+ total += amountRead;
+ // Ensure we keep trying, not all file systems allow huge reads.
+ while (total < required && amountRead > 0 && theBuffer.m_Cancel == false) {
+ NVDataRef<QT3DSU8> newBuffer(theDataBuffer.mData + total, required - total);
+ amountRead = theStream->Read(newBuffer);
+ total += amountRead;
+ }
+ }
+ if (theBuffer.m_Cancel || total != required) {
+ theBuffer.m_Result->m_Data = NVDataRef<QT3DSU8>();
+ }
+ }
+ }
+
+ // only callback if the file was successfully loaded.
+ if (theBuffer.m_UserData) {
+ if (theBuffer.m_Cancel == false && theBuffer.m_Result.mPtr
+ && theBuffer.m_Result->m_Data.size()) {
+ theBuffer.m_UserData->OnBufferLoaded(*theBuffer.m_Result.mPtr);
+ } else {
+ if (theBuffer.m_Cancel)
+ theBuffer.m_UserData->OnBufferLoadCancelled(theBuffer.m_Path);
+ else
+ theBuffer.m_UserData->OnBufferLoadFailed(theBuffer.m_Path);
+ }
+ }
+
+ SetBufferAsLoaded(theBuffer);
+ }
+ static void CancelNextBuffer(void *loader)
+ {
+ SLoadedBufferImpl &theBuffer = *reinterpret_cast<SLoadedBufferImpl *>(loader);
+ theBuffer.m_Cancel = true;
+ InitializeActiveLoadingBuffer(theBuffer);
+
+ if (theBuffer.m_UserData)
+ theBuffer.m_UserData->OnBufferLoadCancelled(theBuffer.m_Path);
+
+ SetBufferAsLoaded(theBuffer);
+ }
+
+ // nonblocking. Quiet failure is passed to the input stream factory.
+ QT3DSU64 QueueForLoading(CRegisteredString inPath,
+ IBufferLoaderCallback *inUserData = NULL,
+ bool inQuietFailure = false) override
+ {
+ SLoadedBufferImpl &theBuffer = *QT3DS_NEW(m_Foundation.getAllocator(), SLoadedBufferImpl)(
+ *this, inPath, inUserData, inQuietFailure, m_NextBufferId);
+ ++m_NextBufferId;
+ {
+ Mutex::ScopedLock theLocker(m_BuffersToLoadMutex);
+ m_BuffersToLoad.push_back(theBuffer);
+ }
+ theBuffer.m_JobId = m_ThreadPool->AddTask(&theBuffer, LoadNextBuffer, CancelNextBuffer);
+ return theBuffer.m_LoadId;
+ }
+
+ void CancelBufferLoad(QT3DSU64 inBufferId) override
+ {
+ {
+ Mutex::ScopedLock theLocker(m_BuffersToLoadMutex);
+ SLoadedBufferImpl *theLoadedBuffer = NULL;
+ for (TLoadedBufferImplList::iterator iter = m_BuffersToLoad.begin(),
+ end = m_BuffersToLoad.end();
+ iter != end && theLoadedBuffer == NULL; ++iter) {
+ if (iter->m_LoadId == inBufferId) {
+ theLoadedBuffer = &(*iter);
+ // both cancellation attempts are necessary. The user will still get
+ // a load result, it will just have no data.
+ theLoadedBuffer->m_Cancel = true;
+ m_ThreadPool->CancelTask(theLoadedBuffer->m_JobId);
+ }
+ }
+ }
+ }
+
+ // If we were will to wait, will we ever get another buffer
+ bool WillLoadedBuffersBeAvailable() override
+ {
+ Mutex::ScopedLock theLocker(m_BuffersToLoadMutex);
+ Mutex::ScopedLock theSecondLocker(m_BuffersLoadingMutex);
+ return AreLoadedBuffersAvailable() || m_BuffersToLoad.empty() == false
+ || m_BuffersLoading.empty() == false;
+ }
+ // Will nextLoadedBuffer block or not?
+ bool AreLoadedBuffersAvailable() override
+ {
+ Mutex::ScopedLock theLocker(m_LoadedBuffersMutex);
+ return m_LoadedBuffers.empty() == false;
+ }
+
+ // blocking, be careful with this. No order guarantees here.
+ NVScopedRefCounted<ILoadedBuffer> NextLoadedBuffer() override
+ {
+ while (!AreLoadedBuffersAvailable()) {
+ m_BufferLoadedEvent.wait();
+ }
+ SLoadedBufferImpl *theBuffer;
+ {
+ Mutex::ScopedLock theLocker(m_LoadedBuffersMutex);
+ theBuffer = m_LoadedBuffers.back_ptr();
+ m_LoadedBuffers.remove(*theBuffer);
+ }
+ NVScopedRefCounted<ILoadedBuffer> retval(theBuffer->m_Result);
+ if (retval.mPtr == NULL) {
+ retval = SBufferLoadResult::Allocate(0, m_Foundation, theBuffer->m_Path,
+ theBuffer->m_UserData);
+ }
+ NVDelete(m_Foundation.getAllocator(), theBuffer);
+ return retval;
+ }
+};
+}
+
+IBufferLoader &IBufferLoader::Create(NVFoundationBase &fnd, IInputStreamFactory &inFactory,
+ IThreadPool &inThreadPool)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SBufferLoader)(fnd, inFactory, inThreadPool);
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.h
new file mode 100644
index 00000000..dde8c1ab
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferLoader.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_BUFFER_LOADED_H
+#define UIC_RENDER_BUFFER_LOADED_H
+
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+namespace render {
+
+ class IBufferLoaderCallback;
+
+ class ILoadedBuffer : public NVRefCounted
+ {
+ public:
+ virtual CRegisteredString Path() = 0;
+ // Data is released when the buffer itself is released.
+ virtual NVDataRef<QT3DSU8> Data() = 0;
+ virtual IBufferLoaderCallback *UserData() = 0;
+ };
+
+ class IBufferLoaderCallback : public NVRefCounted
+ {
+ public:
+ virtual void OnBufferLoaded(ILoadedBuffer &inBuffer) = 0;
+ virtual void OnBufferLoadFailed(CRegisteredString inPath) = 0;
+ virtual void OnBufferLoadCancelled(CRegisteredString inPath) = 0;
+ };
+
+ // Job of this object is to load buffers all the way to memory as fast as possible.
+ class IBufferLoader : public NVRefCounted
+ {
+ public:
+ // nonblocking. Quiet failure is passed to the input stream factory.
+ // Returns handle to loading buffer
+ virtual QT3DSU64 QueueForLoading(CRegisteredString inPath,
+ IBufferLoaderCallback *inUserData = NULL,
+ bool inQuietFailure = false) = 0;
+ // Cancel a buffer that has not made it to the loaded buffers list.
+ virtual void CancelBufferLoad(QT3DSU64 inBufferId) = 0;
+ // If we were will to wait, will we ever get another buffer
+ virtual bool WillLoadedBuffersBeAvailable() = 0;
+ // Will nextLoadedBuffer block or not?
+ virtual bool AreLoadedBuffersAvailable() = 0;
+
+ // blocking, be careful with this. No guarantees about timely return here.
+ virtual NVScopedRefCounted<ILoadedBuffer> NextLoadedBuffer() = 0;
+
+ static IBufferLoader &Create(NVFoundationBase &fnd, IInputStreamFactory &inFactory,
+ IThreadPool &inThreadPool);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp
new file mode 100644
index 00000000..b6230707
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.cpp
@@ -0,0 +1,874 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef _WIN32
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+#endif
+#include "UICRender.h"
+#include "UICRenderBufferManager.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/hash_map.h"
+#include "foundation/FileTools.h"
+#include "UICImportMesh.h"
+#include "UICRenderMesh.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "UICRenderLoadedTexture.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderImageScaler.h"
+#include "UICTextRenderer.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "foundation/Qt3DSMutex.h"
+#include "UICRenderPrefilterTexture.h"
+
+using namespace uic::render;
+
+namespace {
+
+using eastl::hash;
+using eastl::pair;
+using eastl::make_pair;
+typedef eastl::basic_string<char8_t, ForwardingAllocator> TStr;
+struct StrHasher
+{
+ size_t operator()(const TStr &str) const
+ {
+ return hash<const char8_t *>()((const char8_t *)str.c_str());
+ }
+};
+
+struct StrEq
+{
+ bool operator()(const TStr &lhs, const TStr &rhs) const { return lhs == rhs; }
+};
+
+struct SImageEntry : public SImageTextureData
+{
+ bool m_Loaded;
+ SImageEntry()
+ : m_Loaded(false)
+ {
+ }
+ ~SImageEntry()
+ {
+ if (m_BSDFMipMap)
+ m_BSDFMipMap->release();
+ }
+};
+
+struct SPrimitiveEntry
+{
+ // Name of the primitive as it will be in the UIP file
+ CRegisteredString m_PrimitiveName;
+ // Name of the primitive file on the filesystem
+ CRegisteredString m_FileName;
+};
+
+struct SBufferManager : public IBufferManager
+{
+ typedef eastl::hash_set<CRegisteredString, eastl::hash<CRegisteredString>,
+ eastl::equal_to<CRegisteredString>, ForwardingAllocator>
+ TStringSet;
+ typedef nvhash_map<CRegisteredString, SImageEntry> TImageMap;
+ typedef nvhash_map<CRegisteredString, SRenderMesh *> TMeshMap;
+ typedef nvhash_map<CRegisteredString, CRegisteredString> TAliasImageMap;
+
+ NVScopedRefCounted<NVRenderContext> m_Context;
+ NVScopedRefCounted<IStringTable> m_StrTable;
+ NVScopedRefCounted<IInputStreamFactory> m_InputStreamFactory;
+ IPerfTimer &m_PerfTimer;
+ volatile QT3DSI32 mRefCount;
+ TStr m_PathBuilder;
+ TImageMap m_ImageMap;
+ Mutex m_LoadedImageSetMutex;
+ TStringSet m_LoadedImageSet;
+ TAliasImageMap m_AliasImageMap;
+ TMeshMap m_MeshMap;
+ SPrimitiveEntry m_PrimitiveNames[5];
+ nvvector<qt3ds::render::NVRenderVertexBufferEntry> m_EntryBuffer;
+ bool m_GPUSupportsDXT;
+ static const char8_t *GetPrimitivesDirectory() { return "res//primitives"; }
+
+ SBufferManager(NVRenderContext &ctx, IStringTable &strTable,
+ IInputStreamFactory &inInputStreamFactory, IPerfTimer &inTimer)
+ : m_Context(ctx)
+ , m_StrTable(strTable)
+ , m_InputStreamFactory(inInputStreamFactory)
+ , m_PerfTimer(inTimer)
+ , mRefCount(0)
+ , m_PathBuilder(ForwardingAllocator(ctx.GetAllocator(), "SBufferManager::m_PathBuilder"))
+ , m_ImageMap(ctx.GetAllocator(), "SBufferManager::m_ImageMap")
+ , m_LoadedImageSetMutex(ctx.GetAllocator())
+ , m_LoadedImageSet(
+ ForwardingAllocator(ctx.GetAllocator(), "SBufferManager::m_LoadedImageSet"))
+ , m_AliasImageMap(ctx.GetAllocator(), "SBufferManager::m_AliasImageMap")
+ , m_MeshMap(ctx.GetAllocator(), "SBufferManager::m_MeshMap")
+ , m_EntryBuffer(ctx.GetAllocator(), "SBufferManager::m_EntryBuffer")
+ , m_GPUSupportsDXT(ctx.AreDXTImagesSupported())
+ {
+ }
+ virtual ~SBufferManager() { Clear(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Context->GetAllocator())
+
+ CRegisteredString CombineBaseAndRelative(const char8_t *inBase,
+ const char8_t *inRelative) override
+ {
+ CFileTools::CombineBaseAndRelative(inBase, inRelative, m_PathBuilder);
+ return m_StrTable->RegisterStr(m_PathBuilder.c_str());
+ }
+
+ void SetImageHasTransparency(CRegisteredString inImagePath, bool inHasTransparency) override
+ {
+ pair<TImageMap::iterator, bool> theImage =
+ m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
+ theImage.first->second.m_TextureFlags.SetHasTransparency(inHasTransparency);
+ }
+
+ bool GetImageHasTransparency(CRegisteredString inSourcePath) const override
+ {
+ TImageMap::const_iterator theIter = m_ImageMap.find(inSourcePath);
+ if (theIter != m_ImageMap.end())
+ return theIter->second.m_TextureFlags.HasTransparency();
+ return false;
+ }
+
+ void SetImageTransparencyToFalseIfNotSet(CRegisteredString inSourcePath) override
+ {
+ pair<TImageMap::iterator, bool> theImage =
+ m_ImageMap.insert(make_pair(inSourcePath, SImageEntry()));
+ // If we did actually insert something
+ if (theImage.second)
+ theImage.first->second.m_TextureFlags.SetHasTransparency(false);
+ }
+
+ void SetInvertImageUVCoords(CRegisteredString inImagePath, bool inShouldInvertCoords) override
+ {
+ pair<TImageMap::iterator, bool> theImage =
+ m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
+ theImage.first->second.m_TextureFlags.SetInvertUVCoords(inShouldInvertCoords);
+ }
+
+ bool IsImageLoaded(CRegisteredString inSourcePath) override
+ {
+ Mutex::ScopedLock __locker(m_LoadedImageSetMutex);
+ return m_LoadedImageSet.find(inSourcePath) != m_LoadedImageSet.end();
+ }
+
+ bool AliasImagePath(CRegisteredString inSourcePath, CRegisteredString inAliasPath,
+ bool inIgnoreIfLoaded) override
+ {
+ if (inSourcePath.IsValid() == false || inAliasPath.IsValid() == false)
+ return false;
+ // If the image is loaded then we ignore this call in some cases.
+ if (inIgnoreIfLoaded && IsImageLoaded(inSourcePath))
+ return false;
+ m_AliasImageMap.insert(eastl::make_pair(inSourcePath, inAliasPath));
+ return true;
+ }
+
+ void UnaliasImagePath(CRegisteredString inSourcePath) override
+ {
+ m_AliasImageMap.erase(inSourcePath);
+ }
+
+ CRegisteredString GetImagePath(CRegisteredString inSourcePath) override
+ {
+ TAliasImageMap::iterator theAliasIter = m_AliasImageMap.find(inSourcePath);
+ if (theAliasIter != m_AliasImageMap.end())
+ return theAliasIter->second;
+ return inSourcePath;
+ }
+
+ static inline int wrapMod(int a, int base)
+ {
+ int ret = a % base;
+ if (ret < 0)
+ ret += base;
+ return ret;
+ }
+
+ static inline void getWrappedCoords(int &sX, int &sY, int width, int height)
+ {
+ if (sY < 0) {
+ sX -= width >> 1;
+ sY = -sY;
+ }
+ if (sY >= height) {
+ sX += width >> 1;
+ sY = height - sY;
+ }
+ sX = wrapMod(sX, width);
+ sY = wrapMod(sY, height);
+ }
+
+ SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
+ SLoadedTexture &inLoadedImage,
+ bool inForceScanForTransparency, bool inBsdfMipmaps) override
+ {
+ SStackPerfTimer __perfTimer(m_PerfTimer, "Image Upload");
+ {
+ Mutex::ScopedLock __mapLocker(m_LoadedImageSetMutex);
+ m_LoadedImageSet.insert(inImagePath);
+ }
+ pair<TImageMap::iterator, bool> theImage =
+ m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
+ bool wasInserted = theImage.second;
+ theImage.first->second.m_Loaded = true;
+ // inLoadedImage.EnsureMultiplerOfFour( m_Context->GetFoundation(), inImagePath.c_str() );
+
+ NVRenderTexture2D *theTexture = m_Context->CreateTexture2D();
+ if (inLoadedImage.data) {
+ qt3ds::render::NVRenderTextureFormats::Enum destFormat = inLoadedImage.format;
+ if (inBsdfMipmaps)
+ destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F;
+ else
+ theTexture->SetTextureData(
+ NVDataRef<QT3DSU8>((QT3DSU8 *)inLoadedImage.data, inLoadedImage.dataSizeInBytes), 0,
+ inLoadedImage.width, inLoadedImage.height, inLoadedImage.format, destFormat);
+
+ if (inBsdfMipmaps
+ && NVRenderTextureFormats::isUncompressedTextureFormat(inLoadedImage.format)) {
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
+ UICRenderPrefilterTexture *theBSDFMipMap = theImage.first->second.m_BSDFMipMap;
+ if (theBSDFMipMap == NULL) {
+ theBSDFMipMap = UICRenderPrefilterTexture::Create(
+ m_Context, inLoadedImage.width, inLoadedImage.height, *theTexture,
+ destFormat, m_Context->GetFoundation());
+ theImage.first->second.m_BSDFMipMap = theBSDFMipMap;
+ }
+
+ if (theBSDFMipMap) {
+ theBSDFMipMap->Build(inLoadedImage.data, inLoadedImage.dataSizeInBytes,
+ inLoadedImage.format);
+ }
+ }
+ } else if (inLoadedImage.dds) {
+ theImage.first->second.m_Texture = theTexture;
+ bool supportsDXT = m_GPUSupportsDXT;
+ bool isDXT = NVRenderTextureFormats::isCompressedTextureFormat(inLoadedImage.format);
+ bool requiresDecompression = (supportsDXT == false && isDXT) || false;
+ // test code for DXT decompression
+ // if ( isDXT ) requiresDecompression = true;
+ if (requiresDecompression) {
+ qCWarning(WARNING, PERF_INFO,
+ "Image %s is DXT format which is unsupported by "
+ "the graphics subsystem, decompressing in CPU",
+ inImagePath.c_str());
+ }
+ STextureData theDecompressedImage;
+ for (int idx = 0; idx < inLoadedImage.dds->numMipmaps; ++idx) {
+ if (inLoadedImage.dds->mipwidth[idx] && inLoadedImage.dds->mipheight[idx]) {
+ if (requiresDecompression == false) {
+ theTexture->SetTextureData(
+ toU8DataRef((char *)inLoadedImage.dds->data[idx],
+ (QT3DSU32)inLoadedImage.dds->size[idx]),
+ (QT3DSU8)idx, (QT3DSU32)inLoadedImage.dds->mipwidth[idx],
+ (QT3DSU32)inLoadedImage.dds->mipheight[idx], inLoadedImage.format);
+ } else {
+ theDecompressedImage =
+ inLoadedImage.DecompressDXTImage(idx, &theDecompressedImage);
+
+ if (theDecompressedImage.data) {
+ theTexture->SetTextureData(
+ toU8DataRef((char *)theDecompressedImage.data,
+ (QT3DSU32)theDecompressedImage.dataSizeInBytes),
+ (QT3DSU8)idx, (QT3DSU32)inLoadedImage.dds->mipwidth[idx],
+ (QT3DSU32)inLoadedImage.dds->mipheight[idx],
+ theDecompressedImage.format);
+ }
+ }
+ }
+ }
+ if (theDecompressedImage.data)
+ inLoadedImage.ReleaseDecompressedTexture(theDecompressedImage);
+ }
+ if (wasInserted == true || inForceScanForTransparency)
+ theImage.first->second.m_TextureFlags.SetHasTransparency(
+ inLoadedImage.ScanForTransparency());
+ theImage.first->second.m_Texture = theTexture;
+ return theImage.first->second;
+ }
+
+ SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
+ bool inForceScanForTransparency, bool inBsdfMipmaps) override
+ {
+ inImagePath = GetImagePath(inImagePath);
+
+ if (!inImagePath.IsValid())
+ return SImageEntry();
+
+ TImageMap::iterator theIter = m_ImageMap.find(inImagePath);
+ if (theIter == m_ImageMap.end() && inImagePath.IsValid()) {
+ NVScopedReleasable<SLoadedTexture> theLoadedImage;
+ {
+ SStackPerfTimer __perfTimer(m_PerfTimer, "Image Decompression");
+ theLoadedImage = SLoadedTexture::Load(
+ inImagePath.c_str(), m_Context->GetFoundation(), *m_InputStreamFactory);
+ }
+
+ if (theLoadedImage) {
+ return LoadRenderImage(inImagePath, *theLoadedImage, inForceScanForTransparency,
+ inBsdfMipmaps);
+ } else {
+ // We want to make sure that bad path fails once and doesn't fail over and over
+ // again
+ // which could slow down the system quite a bit.
+ pair<TImageMap::iterator, bool> theImage =
+ m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
+ theImage.first->second.m_Loaded = true;
+ qCWarning(WARNING, "Failed to load image: %s", inImagePath.c_str());
+ theIter = theImage.first;
+ }
+ }
+ return theIter->second;
+ }
+
+ UICIMP::SMultiLoadResult LoadPrimitive(const char8_t *inRelativePath)
+ {
+ CRegisteredString theName(m_StrTable->RegisterStr(inRelativePath));
+ if (m_PrimitiveNames[0].m_PrimitiveName.IsValid() == false) {
+ IStringTable &strTable(m_Context->GetStringTable());
+ m_PrimitiveNames[0].m_PrimitiveName = strTable.RegisterStr("#Rectangle");
+ m_PrimitiveNames[0].m_FileName = strTable.RegisterStr("Rectangle.mesh");
+ m_PrimitiveNames[1].m_PrimitiveName = strTable.RegisterStr("#Sphere");
+ m_PrimitiveNames[1].m_FileName = strTable.RegisterStr("Sphere.mesh");
+ m_PrimitiveNames[2].m_PrimitiveName = strTable.RegisterStr("#Cube");
+ m_PrimitiveNames[2].m_FileName = strTable.RegisterStr("Cube.mesh");
+ m_PrimitiveNames[3].m_PrimitiveName = strTable.RegisterStr("#Cone");
+ m_PrimitiveNames[3].m_FileName = strTable.RegisterStr("Cone.mesh");
+ m_PrimitiveNames[4].m_PrimitiveName = strTable.RegisterStr("#Cylinder");
+ m_PrimitiveNames[4].m_FileName = strTable.RegisterStr("Cylinder.mesh");
+ }
+ for (size_t idx = 0; idx < 5; ++idx) {
+ if (m_PrimitiveNames[idx].m_PrimitiveName == theName) {
+ CFileTools::CombineBaseAndRelative(GetPrimitivesDirectory(),
+ m_PrimitiveNames[idx].m_FileName, m_PathBuilder);
+ QT3DSU32 id = 1;
+ NVScopedRefCounted<IRefCountedInputStream> theInStream(
+ m_InputStreamFactory->GetStreamForFile(m_PathBuilder.c_str()));
+ if (theInStream)
+ return UICIMP::Mesh::LoadMulti(m_Context->GetAllocator(), *theInStream, id);
+ else {
+ qCCritical(INTERNAL_ERROR, "Unable to find mesh primitive %s",
+ m_PathBuilder.c_str());
+ return UICIMP::SMultiLoadResult();
+ }
+ }
+ }
+ return UICIMP::SMultiLoadResult();
+ }
+
+ virtual NVConstDataRef<QT3DSU8> CreatePackedPositionDataArray(UICIMP::SMultiLoadResult *inResult)
+ {
+ // we assume a position consists of 3 floats
+ QT3DSU32 vertexCount = inResult->m_Mesh->m_VertexBuffer.m_Data.size()
+ / inResult->m_Mesh->m_VertexBuffer.m_Stride;
+ QT3DSU32 dataSize = vertexCount * 3 * sizeof(QT3DSF32);
+ QT3DSF32 *posData = (QT3DSF32 *)QT3DS_ALLOC(m_Context->GetAllocator(), dataSize,
+ "SRenderMesh::CreatePackedPositionDataArray");
+ QT3DSU8 *baseOffset = reinterpret_cast<QT3DSU8 *>(inResult->m_Mesh);
+ // copy position data
+ if (posData) {
+ QT3DSF32 *srcData = (QT3DSF32 *)inResult->m_Mesh->m_VertexBuffer.m_Data.begin(baseOffset);
+ QT3DSU32 srcStride = inResult->m_Mesh->m_VertexBuffer.m_Stride / sizeof(QT3DSF32);
+ QT3DSF32 *dstData = posData;
+ QT3DSU32 dstStride = 3;
+
+ for (QT3DSU32 i = 0; i < vertexCount; ++i) {
+ dstData[0] = srcData[0];
+ dstData[1] = srcData[1];
+ dstData[2] = srcData[2];
+
+ dstData += dstStride;
+ srcData += srcStride;
+ }
+
+ return toConstDataRef((const qt3ds::QT3DSU8 *)posData, dataSize);
+ }
+
+ return NVConstDataRef<QT3DSU8>();
+ }
+
+ SRenderMesh *LoadMesh(CRegisteredString inMeshPath) override
+ {
+ if (inMeshPath.IsValid() == false)
+ return NULL;
+ pair<TMeshMap::iterator, bool> theMesh =
+ m_MeshMap.insert(make_pair(inMeshPath, (SRenderMesh *)NULL));
+ if (theMesh.second == true) {
+ // check to see if this is primitive
+
+ UICIMP::SMultiLoadResult theResult = LoadPrimitive(inMeshPath);
+
+ // Attempt a load from the filesystem if this mesh isn't a primitive.
+ if (theResult.m_Mesh == NULL) {
+ m_PathBuilder = inMeshPath;
+ TStr::size_type pound = m_PathBuilder.rfind('#');
+ QT3DSU32 id = 0;
+ if (pound != TStr::npos) {
+ id = atoi(m_PathBuilder.c_str() + pound + 1);
+ m_PathBuilder.erase(m_PathBuilder.begin() + pound, m_PathBuilder.end());
+ }
+ NVScopedRefCounted<IRefCountedInputStream> theStream(
+ m_InputStreamFactory->GetStreamForFile(m_PathBuilder.c_str()));
+ if (theStream) {
+ theResult = UICIMP::Mesh::LoadMulti(m_Context->GetAllocator(), *theStream, id);
+ }
+ if (theResult.m_Mesh == NULL)
+ qCWarning(WARNING, "Failed to load mesh: %s", m_PathBuilder.c_str());
+ }
+
+ if (theResult.m_Mesh) {
+ SRenderMesh *theNewMesh = QT3DS_NEW(m_Context->GetAllocator(), SRenderMesh)(
+ qt3ds::render::NVRenderDrawMode::Triangles,
+ qt3ds::render::NVRenderWinding::CounterClockwise, theResult.m_Id,
+ m_Context->GetAllocator());
+ QT3DSU8 *baseAddress = reinterpret_cast<QT3DSU8 *>(theResult.m_Mesh);
+ theMesh.first->second = theNewMesh;
+ NVConstDataRef<QT3DSU8> theVBufData(
+ theResult.m_Mesh->m_VertexBuffer.m_Data.begin(baseAddress),
+ theResult.m_Mesh->m_VertexBuffer.m_Data.size());
+
+ NVRenderVertexBuffer *theVertexBuffer = m_Context->CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static,
+ theResult.m_Mesh->m_VertexBuffer.m_Data.m_Size,
+ theResult.m_Mesh->m_VertexBuffer.m_Stride, theVBufData);
+
+ // create a tight packed position data VBO
+ // this should improve our depth pre pass rendering
+ NVRenderVertexBuffer *thePosVertexBuffer = NULL;
+ NVConstDataRef<QT3DSU8> posData = CreatePackedPositionDataArray(&theResult);
+ if (posData.size()) {
+ thePosVertexBuffer =
+ m_Context->CreateVertexBuffer(qt3ds::render::NVRenderBufferUsageType::Static,
+ posData.size(), 3 * sizeof(QT3DSF32), posData);
+ }
+
+ NVRenderIndexBuffer *theIndexBuffer = NULL;
+ if (theResult.m_Mesh->m_IndexBuffer.m_Data.size()) {
+ using qt3ds::render::NVRenderComponentTypes;
+ QT3DSU32 theIndexBufferSize = theResult.m_Mesh->m_IndexBuffer.m_Data.size();
+ NVRenderComponentTypes::Enum bufComponentType =
+ theResult.m_Mesh->m_IndexBuffer.m_ComponentType;
+ QT3DSU32 sizeofType =
+ qt3ds::render::NVRenderComponentTypes::getSizeofType(bufComponentType);
+
+ if (sizeofType == 2 || sizeofType == 4) {
+ // Ensure type is unsigned; else things will fail in rendering pipeline.
+ if (bufComponentType == NVRenderComponentTypes::QT3DSI16)
+ bufComponentType = NVRenderComponentTypes::QT3DSU16;
+ if (bufComponentType == NVRenderComponentTypes::QT3DSI32)
+ bufComponentType = NVRenderComponentTypes::QT3DSU32;
+
+ NVConstDataRef<QT3DSU8> theIBufData(
+ theResult.m_Mesh->m_IndexBuffer.m_Data.begin(baseAddress),
+ theResult.m_Mesh->m_IndexBuffer.m_Data.size());
+ theIndexBuffer = m_Context->CreateIndexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static, bufComponentType,
+ theIndexBufferSize, theIBufData);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ nvvector<qt3ds::render::NVRenderVertexBufferEntry> &theEntryBuffer(m_EntryBuffer);
+ theEntryBuffer.resize(theResult.m_Mesh->m_VertexBuffer.m_Entries.size());
+ for (QT3DSU32 entryIdx = 0,
+ entryEnd = theResult.m_Mesh->m_VertexBuffer.m_Entries.size();
+ entryIdx < entryEnd; ++entryIdx) {
+ theEntryBuffer[entryIdx] =
+ theResult.m_Mesh->m_VertexBuffer.m_Entries.index(baseAddress, entryIdx)
+ .ToVertexBufferEntry(baseAddress);
+ }
+ // create our attribute layout
+ NVRenderAttribLayout *theAttribLayout =
+ m_Context->CreateAttributeLayout(theEntryBuffer);
+ // create our attribute layout for depth pass
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ };
+ NVRenderAttribLayout *theAttribLayoutDepth =
+ m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 1));
+
+ // create input assembler object
+ QT3DSU32 strides = theResult.m_Mesh->m_VertexBuffer.m_Stride;
+ QT3DSU32 offsets = 0;
+ NVRenderInputAssembler *theInputAssembler = m_Context->CreateInputAssembler(
+ theAttribLayout, toConstDataRef(&theVertexBuffer, 1), theIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1),
+ theResult.m_Mesh->m_DrawMode);
+
+ // create depth input assembler object
+ QT3DSU32 posStrides = (thePosVertexBuffer) ? 3 * sizeof(QT3DSF32) : strides;
+ NVRenderInputAssembler *theInputAssemblerDepth = m_Context->CreateInputAssembler(
+ theAttribLayoutDepth,
+ toConstDataRef((thePosVertexBuffer) ? &thePosVertexBuffer : &theVertexBuffer,
+ 1),
+ theIndexBuffer, toConstDataRef(&posStrides, 1), toConstDataRef(&offsets, 1),
+ theResult.m_Mesh->m_DrawMode);
+
+ NVRenderInputAssembler *theInputAssemblerPoints = m_Context->CreateInputAssembler(
+ theAttribLayoutDepth,
+ toConstDataRef((thePosVertexBuffer) ? &thePosVertexBuffer : &theVertexBuffer,
+ 1),
+ NULL, toConstDataRef(&posStrides, 1), toConstDataRef(&offsets, 1),
+ NVRenderDrawMode::Points);
+
+ if (!theInputAssembler || !theInputAssemblerDepth || !theInputAssemblerPoints) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ theNewMesh->m_Joints.resize(theResult.m_Mesh->m_Joints.size());
+ for (QT3DSU32 jointIdx = 0, jointEnd = theResult.m_Mesh->m_Joints.size();
+ jointIdx < jointEnd; ++jointIdx) {
+ const UICIMP::Joint &theImportJoint(
+ theResult.m_Mesh->m_Joints.index(baseAddress, jointIdx));
+ SRenderJoint &theNewJoint(theNewMesh->m_Joints[jointIdx]);
+ theNewJoint.m_JointID = theImportJoint.m_JointID;
+ theNewJoint.m_ParentID = theImportJoint.m_ParentID;
+ memCopy(theNewJoint.m_invBindPose, theImportJoint.m_invBindPose,
+ 16 * sizeof(QT3DSF32));
+ memCopy(theNewJoint.m_localToGlobalBoneSpace,
+ theImportJoint.m_localToGlobalBoneSpace, 16 * sizeof(QT3DSF32));
+ }
+
+ for (QT3DSU32 subsetIdx = 0, subsetEnd = theResult.m_Mesh->m_Subsets.size();
+ subsetIdx < subsetEnd; ++subsetIdx) {
+ SRenderSubset theSubset(m_Context->GetAllocator());
+ const UICIMP::MeshSubset &source(
+ theResult.m_Mesh->m_Subsets.index(baseAddress, subsetIdx));
+ theSubset.m_Bounds = source.m_Bounds;
+ theSubset.m_Count = source.m_Count;
+ theSubset.m_Offset = source.m_Offset;
+ theSubset.m_Joints = theNewMesh->m_Joints;
+ theSubset.m_Name = m_StrTable->RegisterStr(source.m_Name.begin(baseAddress));
+ theVertexBuffer->addRef();
+ theSubset.m_VertexBuffer = theVertexBuffer;
+ if (thePosVertexBuffer) {
+ thePosVertexBuffer->addRef();
+ theSubset.m_PosVertexBuffer = thePosVertexBuffer;
+ }
+ if (theIndexBuffer) {
+ theIndexBuffer->addRef();
+ theSubset.m_IndexBuffer = theIndexBuffer;
+ }
+ theSubset.m_InputAssembler = theInputAssembler;
+ theSubset.m_InputAssemblerDepth = theInputAssemblerDepth;
+ theSubset.m_InputAssemblerPoints = theInputAssemblerPoints;
+ theSubset.m_PrimitiveType = theResult.m_Mesh->m_DrawMode;
+ theInputAssembler->addRef();
+ theInputAssemblerDepth->addRef();
+ theSubset.m_InputAssemblerPoints->addRef();
+ theNewMesh->m_Subsets.push_back(theSubset);
+ }
+// If we want to, we can an in a quite stupid way break up modes into sub-subsets.
+// These are assumed to use the same material as the outer subset but have fewer tris
+// and should have a more exact bounding box. This sort of thing helps with using the frustum
+// culling
+// system but it is really done incorrectly. It should be done via some sort of oct-tree mechanism
+// and it
+// so that the sub-subsets spatially sorted and it should only be done upon save-to-binary with the
+// results
+// saved out to disk. As you can see, doing it properly requires some real engineering effort so it
+// is somewhat
+// unlikely it will ever happen. Or it could be done on import if someone really wants to change
+// the mesh buffer
+// format. Either way it isn't going to happen here and it isn't going to happen this way but this
+// is a working
+// example of using the technique.
+#ifdef UIC_RENDER_GENERATE_SUB_SUBSETS
+ Option<qt3ds::render::NVRenderVertexBufferEntry> thePosAttrOpt =
+ theVertexBuffer->GetEntryByName("attr_pos");
+ bool hasPosAttr = thePosAttrOpt.hasValue()
+ && thePosAttrOpt->m_ComponentType == qt3ds::render::NVRenderComponentTypes::QT3DSF32
+ && thePosAttrOpt->m_NumComponents == 3;
+
+ for (size_t subsetIdx = 0, subsetEnd = theNewMesh->m_Subsets.size();
+ subsetIdx < subsetEnd; ++subsetIdx) {
+ SRenderSubset &theOuterSubset = theNewMesh->m_Subsets[subsetIdx];
+ if (theOuterSubset.m_Count && theIndexBuffer
+ && theIndexBuffer->GetComponentType()
+ == qt3ds::render::NVRenderComponentTypes::QT3DSU16
+ && theNewMesh->m_DrawMode == NVRenderDrawMode::Triangles && hasPosAttr) {
+ // Num tris in a sub subset.
+ QT3DSU32 theSubsetSize = 3334 * 3; // divisible by three.
+ size_t theNumSubSubsets =
+ ((theOuterSubset.m_Count - 1) / theSubsetSize) + 1;
+ QT3DSU32 thePosAttrOffset = thePosAttrOpt->m_FirstItemOffset;
+ const QT3DSU8 *theVertData = theResult.m_Mesh->m_VertexBuffer.m_Data.begin();
+ const QT3DSU8 *theIdxData = theResult.m_Mesh->m_IndexBuffer.m_Data.begin();
+ QT3DSU32 theVertStride = theResult.m_Mesh->m_VertexBuffer.m_Stride;
+ QT3DSU32 theOffset = theOuterSubset.m_Offset;
+ QT3DSU32 theCount = theOuterSubset.m_Count;
+ for (size_t subSubsetIdx = 0, subSubsetEnd = theNumSubSubsets;
+ subSubsetIdx < subSubsetEnd; ++subSubsetIdx) {
+ SRenderSubsetBase theBase;
+ theBase.m_Offset = theOffset;
+ theBase.m_Count = NVMin(theSubsetSize, theCount);
+ theBase.m_Bounds.setEmpty();
+ theCount -= theBase.m_Count;
+ theOffset += theBase.m_Count;
+ // Create new bounds.
+ // Offset is in item size, not bytes.
+ const QT3DSU16 *theSubsetIdxData =
+ reinterpret_cast<const QT3DSU16 *>(theIdxData + theBase.m_Offset * 2);
+ for (size_t theIdxIdx = 0, theIdxEnd = theBase.m_Count;
+ theIdxIdx < theIdxEnd; ++theIdxIdx) {
+ QT3DSU32 theVertOffset = theSubsetIdxData[theIdxIdx] * theVertStride;
+ theVertOffset += thePosAttrOffset;
+ QT3DSVec3 thePos = *(
+ reinterpret_cast<const QT3DSVec3 *>(theVertData + theVertOffset));
+ theBase.m_Bounds.include(thePos);
+ }
+ theOuterSubset.m_SubSubsets.push_back(theBase);
+ }
+ } else {
+ SRenderSubsetBase theBase;
+ theBase.m_Bounds = theOuterSubset.m_Bounds;
+ theBase.m_Count = theOuterSubset.m_Count;
+ theBase.m_Offset = theOuterSubset.m_Offset;
+ theOuterSubset.m_SubSubsets.push_back(theBase);
+ }
+ }
+#endif
+ if (posData.size())
+ m_Context->GetAllocator().deallocate((void *)posData.begin());
+
+ m_Context->GetAllocator().deallocate(theResult.m_Mesh);
+ }
+ }
+ return theMesh.first->second;
+ }
+
+ SRenderMesh *CreateMesh(UICBCharPtr inSourcePath, QT3DSU8 *inVertData, QT3DSU32 inNumVerts,
+ QT3DSU32 inVertStride, QT3DSU32 *inIndexData, QT3DSU32 inIndexCount,
+ qt3ds::NVBounds3 inBounds) override
+ {
+ CRegisteredString sourcePath = m_StrTable->RegisterStr(inSourcePath);
+
+ // eastl::pair<CRegisteredString, SRenderMesh*> thePair(sourcePath, (SRenderMesh*)NULL);
+ pair<TMeshMap::iterator, bool> theMesh;
+ // Make sure there isn't already a buffer entry for this mesh.
+ if (m_MeshMap.contains(sourcePath)) {
+ theMesh = make_pair<TMeshMap::iterator, bool>(m_MeshMap.find(sourcePath), true);
+ } else {
+ theMesh = m_MeshMap.insert(make_pair(sourcePath, (SRenderMesh *)NULL));
+ }
+
+ if (theMesh.second == true) {
+ SRenderMesh *theNewMesh = QT3DS_NEW(m_Context->GetAllocator(), SRenderMesh)(
+ qt3ds::render::NVRenderDrawMode::Triangles,
+ qt3ds::render::NVRenderWinding::CounterClockwise, 0, m_Context->GetAllocator());
+
+ // If we failed to create the RenderMesh, return a failure.
+ if (!theNewMesh) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ // Get rid of any old mesh that was sitting here and fill it with a new one.
+ // NOTE : This is assuming that the source of our mesh data doesn't do its own memory
+ // management and always returns new buffer pointers every time.
+ // Don't know for sure if that's what we'll get from our intended sources, but that's
+ // easily
+ // adjustable by looking for matching pointers in the Subsets.
+ if (theNewMesh && theMesh.first->second != NULL) {
+ delete theMesh.first->second;
+ theMesh.first->second = NULL;
+ }
+
+ theMesh.first->second = theNewMesh;
+ QT3DSU32 vertDataSize = inNumVerts * inVertStride;
+ NVConstDataRef<QT3DSU8> theVBufData(inVertData, vertDataSize);
+ // NVConstDataRef<QT3DSU8> theVBufData( theResult.m_Mesh->m_VertexBuffer.m_Data.begin(
+ // baseAddress )
+ // , theResult.m_Mesh->m_VertexBuffer.m_Data.size() );
+
+ NVRenderVertexBuffer *theVertexBuffer =
+ m_Context->CreateVertexBuffer(qt3ds::render::NVRenderBufferUsageType::Static,
+ vertDataSize, inVertStride, theVBufData);
+ NVRenderIndexBuffer *theIndexBuffer = NULL;
+ if (inIndexData != NULL && inIndexCount > 3) {
+ NVConstDataRef<QT3DSU8> theIBufData((QT3DSU8 *)inIndexData, inIndexCount * sizeof(QT3DSU32));
+ theIndexBuffer =
+ m_Context->CreateIndexBuffer(qt3ds::render::NVRenderBufferUsageType::Static,
+ qt3ds::render::NVRenderComponentTypes::QT3DSU32,
+ inIndexCount * sizeof(QT3DSU32), theIBufData);
+ }
+
+ // WARNING
+ // Making an assumption here about the contents of the stream
+ // PKC TODO : We may have to consider some other format.
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_uv", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 12),
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_norm", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3, 18),
+ };
+
+ // create our attribute layout
+ NVRenderAttribLayout *theAttribLayout =
+ m_Context->CreateAttributeLayout(toConstDataRef(theEntries, 3));
+ /*
+ // create our attribute layout for depth pass
+ qt3ds::render::NVRenderVertexBufferEntry theEntriesDepth[] = {
+ qt3ds::render::NVRenderVertexBufferEntry( "attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3 ),
+ };
+ NVRenderAttribLayout* theAttribLayoutDepth = m_Context->CreateAttributeLayout(
+ toConstDataRef( theEntriesDepth, 1 ) );
+ */
+ // create input assembler object
+ QT3DSU32 strides = inVertStride;
+ QT3DSU32 offsets = 0;
+ NVRenderInputAssembler *theInputAssembler = m_Context->CreateInputAssembler(
+ theAttribLayout, toConstDataRef(&theVertexBuffer, 1), theIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1),
+ qt3ds::render::NVRenderDrawMode::Triangles);
+
+ if (!theInputAssembler) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ // Pull out just the mesh object name from the total path
+ eastl::string fullName(inSourcePath);
+ eastl::string subName(inSourcePath);
+ if (fullName.rfind("#") != eastl::string::npos) {
+ subName = fullName.substr(fullName.rfind("#"), eastl::string::npos);
+ }
+
+ theNewMesh->m_Joints.clear();
+ SRenderSubset theSubset(m_Context->GetAllocator());
+ theSubset.m_Bounds = inBounds;
+ theSubset.m_Count = inIndexCount;
+ theSubset.m_Offset = 0;
+ theSubset.m_Joints = theNewMesh->m_Joints;
+ theSubset.m_Name = m_StrTable->RegisterStr(subName.c_str());
+ theVertexBuffer->addRef();
+ theSubset.m_VertexBuffer = theVertexBuffer;
+ theSubset.m_PosVertexBuffer = NULL;
+ if (theIndexBuffer)
+ theIndexBuffer->addRef();
+ theSubset.m_IndexBuffer = theIndexBuffer;
+ theSubset.m_InputAssembler = theInputAssembler;
+ theSubset.m_InputAssemblerDepth = theInputAssembler;
+ theSubset.m_InputAssemblerPoints = theInputAssembler;
+ theSubset.m_PrimitiveType = qt3ds::render::NVRenderDrawMode::Triangles;
+ theSubset.m_InputAssembler->addRef();
+ theSubset.m_InputAssemblerDepth->addRef();
+ theSubset.m_InputAssemblerPoints->addRef();
+ theNewMesh->m_Subsets.push_back(theSubset);
+ }
+
+ return theMesh.first->second;
+ }
+
+ void ReleaseMesh(SRenderMesh &inMesh)
+ {
+ for (QT3DSU32 subsetIdx = 0, subsetEnd = inMesh.m_Subsets.size(); subsetIdx < subsetEnd;
+ ++subsetIdx) {
+ inMesh.m_Subsets[subsetIdx].m_VertexBuffer->release();
+ if (inMesh.m_Subsets[subsetIdx].m_PosVertexBuffer) // can be NULL
+ inMesh.m_Subsets[subsetIdx].m_PosVertexBuffer->release();
+ if (inMesh.m_Subsets[subsetIdx].m_IndexBuffer) // can be NULL
+ inMesh.m_Subsets[subsetIdx].m_IndexBuffer->release();
+ inMesh.m_Subsets[subsetIdx].m_InputAssembler->release();
+ inMesh.m_Subsets[subsetIdx].m_InputAssemblerDepth->release();
+ if (inMesh.m_Subsets[subsetIdx].m_InputAssemblerPoints)
+ inMesh.m_Subsets[subsetIdx].m_InputAssemblerPoints->release();
+ }
+ NVDelete(m_Context->GetAllocator(), &inMesh);
+ }
+ void ReleaseTexture(SImageEntry &inEntry)
+ {
+ if (inEntry.m_Texture)
+ inEntry.m_Texture->release();
+ }
+ void Clear() override
+ {
+ for (TMeshMap::iterator iter = m_MeshMap.begin(), end = m_MeshMap.end(); iter != end;
+ ++iter) {
+ SRenderMesh *theMesh = iter->second;
+ if (theMesh)
+ ReleaseMesh(*theMesh);
+ }
+ m_MeshMap.clear();
+ for (TImageMap::iterator iter = m_ImageMap.begin(), end = m_ImageMap.end(); iter != end;
+ ++iter) {
+ SImageEntry &theEntry = iter->second;
+ ReleaseTexture(theEntry);
+ }
+ m_ImageMap.clear();
+ m_AliasImageMap.clear();
+ {
+ Mutex::ScopedLock __locker(m_LoadedImageSetMutex);
+ m_LoadedImageSet.clear();
+ }
+ }
+ void InvalidateBuffer(CRegisteredString inSourcePath) override
+ {
+ {
+ TMeshMap::iterator iter = m_MeshMap.find(inSourcePath);
+ if (iter != m_MeshMap.end()) {
+ if (iter->second)
+ ReleaseMesh(*iter->second);
+ m_MeshMap.erase(iter);
+ return;
+ }
+ }
+ {
+ TImageMap::iterator iter = m_ImageMap.find(inSourcePath);
+ if (iter != m_ImageMap.end()) {
+ SImageEntry &theEntry = iter->second;
+ ReleaseTexture(theEntry);
+ m_ImageMap.erase(inSourcePath);
+ {
+ Mutex::ScopedLock __locker(m_LoadedImageSetMutex);
+ m_LoadedImageSet.erase(inSourcePath);
+ }
+ }
+ }
+ }
+ IStringTable &GetStringTable() override { return *m_StrTable; }
+};
+}
+
+IBufferManager &IBufferManager::Create(NVRenderContext &inRenderContext, IStringTable &inStrTable,
+ IInputStreamFactory &inFactory, IPerfTimer &inPerfTimer)
+{
+ return *QT3DS_NEW(inRenderContext.GetAllocator(), SBufferManager)(inRenderContext, inStrTable,
+ inFactory, inPerfTimer);
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.h
new file mode 100644
index 00000000..0c68bfc7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderBufferManager.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_BUFFER_MANAGER_H
+#define UIC_RENDER_BUFFER_MANAGER_H
+#include "UICRender.h"
+#include "EASTL/utility.h" //pair
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "UICRenderImageTextureData.h"
+#include "foundation/Qt3DSBounds3.h"
+
+namespace uic {
+namespace render {
+
+ class IBufferManager : public NVRefCounted
+ {
+ protected:
+ virtual ~IBufferManager() {}
+
+ public:
+ // Path manipulation used to get the final path form a base path plus relative extension
+ virtual CRegisteredString CombineBaseAndRelative(const char8_t *inBase,
+ const char8_t *inRelative) = 0;
+ virtual void SetImageHasTransparency(CRegisteredString inSourcePath,
+ bool inHasTransparency) = 0;
+ virtual bool GetImageHasTransparency(CRegisteredString inSourcePath) const = 0;
+ virtual void SetImageTransparencyToFalseIfNotSet(CRegisteredString inSourcePath) = 0;
+ virtual void SetInvertImageUVCoords(CRegisteredString inSourcePath,
+ bool inShouldInvertCoords) = 0;
+
+ // Returns true if this image has been loaded into memory
+ // This call is threadsafe. Nothing else on this object is guaranteed to be.
+ virtual bool IsImageLoaded(CRegisteredString inSourcePath) = 0;
+
+ // Alias one image path with another image path. Optionally this object will ignore the
+ // call if
+ // the source path is already loaded. Aliasing is currently used to allow a default image
+ // to be shown
+ // in place of an image that is loading offline.
+ // Returns true if the image was aliased, false otherwise.
+ virtual bool AliasImagePath(CRegisteredString inSourcePath, CRegisteredString inAliasPath,
+ bool inIgnoreIfLoaded) = 0;
+ virtual void UnaliasImagePath(CRegisteredString inSourcePath) = 0;
+
+ // Returns the given source path unless the source path is aliased; in which case returns
+ // the aliased path.
+ virtual CRegisteredString GetImagePath(CRegisteredString inSourcePath) = 0;
+ // Returns a texture and a boolean indicating if this texture has transparency in it or not.
+ // Can't name this LoadImage because that gets mangled by windows to LoadImageA (uggh)
+ // In some cases we need to only scan particular images for transparency.
+ virtual SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
+ SLoadedTexture &inTexture,
+ bool inForceScanForTransparency = false,
+ bool inBsdfMipmaps = false) = 0;
+ virtual SImageTextureData LoadRenderImage(CRegisteredString inSourcePath,
+ bool inForceScanForTransparency = false,
+ bool inBsdfMipmaps = false) = 0;
+ virtual SRenderMesh *LoadMesh(CRegisteredString inSourcePath) = 0;
+
+ virtual SRenderMesh *CreateMesh(const char *inSourcePath, QT3DSU8 *inVertData,
+ QT3DSU32 inNumVerts, QT3DSU32 inVertStride, QT3DSU32 *inIndexData,
+ QT3DSU32 inIndexCount, qt3ds::NVBounds3 inBounds) = 0;
+
+ // Remove *all* buffers from the buffer manager;
+ virtual void Clear() = 0;
+ virtual void InvalidateBuffer(CRegisteredString inSourcePath) = 0;
+ virtual IStringTable &GetStringTable() = 0;
+
+ static IBufferManager &Create(NVRenderContext &inRenderContext, IStringTable &inStrTable,
+ IInputStreamFactory &inInputStreamFactory,
+ IPerfTimer &inTimer);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.cpp
new file mode 100644
index 00000000..f498d176
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.cpp
@@ -0,0 +1,521 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderImageBatchLoader.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StringTable.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderThreadPool.h"
+#include "UICRenderImageScaler.h"
+#include "UICRenderLoadedTexture.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSPerfTimer.h"
+
+using namespace uic::render;
+
+namespace {
+
+struct SImageLoaderBatch;
+typedef Mutex::ScopedLock TScopedLock;
+
+struct SLoadingImage
+{
+ SImageLoaderBatch *m_Batch;
+ CRegisteredString m_SourcePath;
+ QT3DSU64 m_TaskId;
+ SLoadingImage *m_Tail;
+
+ // Called from main thread
+ SLoadingImage(CRegisteredString inSourcePath)
+ : m_Batch(NULL)
+ , m_SourcePath(inSourcePath)
+ , m_TaskId(0)
+ , m_Tail(NULL)
+ {
+ }
+ SLoadingImage()
+ : m_Batch(NULL)
+ , m_TaskId(0)
+ , m_Tail(NULL)
+ {
+ }
+ // Called from main thread
+ void Setup(SImageLoaderBatch &inBatch);
+
+ // Called from loader thread
+ static void LoadImage(void *inImg);
+
+ // Potentially called from loader thread
+ static void TaskCancelled(void *inImg);
+};
+
+struct SLoadingImageTailOp
+{
+ SLoadingImage *get(SLoadingImage &inImg) { return inImg.m_Tail; }
+ void set(SLoadingImage &inImg, SLoadingImage *inItem) { inImg.m_Tail = inItem; }
+};
+
+typedef InvasiveSingleLinkedList<SLoadingImage, SLoadingImageTailOp> TLoadingImageList;
+
+struct SBatchLoader;
+
+struct SImageLoaderBatch
+{
+ // All variables setup in main thread and constant from then on except
+ // loaded image count.
+ SBatchLoader &m_Loader;
+ NVScopedRefCounted<IImageLoadListener> m_LoadListener;
+ Sync m_LoadEvent;
+ Mutex m_LoadMutex;
+ TLoadingImageList m_Images;
+
+ TImageBatchId m_BatchId;
+ // Incremented in main thread
+ QT3DSU32 m_LoadedOrCanceledImageCount;
+ QT3DSU32 m_FinalizedImageCount;
+ QT3DSU32 m_NumImages;
+
+ // Called from main thread
+ static SImageLoaderBatch *CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBatchId,
+ NVConstDataRef<CRegisteredString> inSourcePaths,
+ CRegisteredString inImageTillLoaded,
+ IImageLoadListener *inListener);
+
+ // Called from main thread
+ SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener *inLoadListener,
+ const TLoadingImageList &inImageList, TImageBatchId inBatchId,
+ QT3DSU32 inImageCount);
+
+ // Called from main thread
+ ~SImageLoaderBatch();
+
+ // Called from main thread
+ bool IsLoadingFinished()
+ {
+ Mutex::ScopedLock __locker(m_LoadMutex);
+ return m_LoadedOrCanceledImageCount >= m_NumImages;
+ }
+
+ bool IsFinalizedFinished()
+ {
+ Mutex::ScopedLock __locker(m_LoadMutex);
+ return m_FinalizedImageCount >= m_NumImages;
+ }
+
+ void IncrementLoadedImageCount()
+ {
+ Mutex::ScopedLock __locker(m_LoadMutex);
+ ++m_LoadedOrCanceledImageCount;
+ }
+ void IncrementFinalizedImageCount()
+ {
+ Mutex::ScopedLock __locker(m_LoadMutex);
+ ++m_FinalizedImageCount;
+ }
+ // Called from main thread
+ void Cancel();
+ void Cancel(CRegisteredString inSourcePath);
+};
+
+struct SBatchLoadedImage
+{
+ CRegisteredString m_SourcePath;
+ SLoadedTexture *m_Texture;
+ SImageLoaderBatch *m_Batch;
+ SBatchLoadedImage()
+ : m_Texture(NULL)
+ , m_Batch(NULL)
+ {
+ }
+
+ // Called from loading thread
+ SBatchLoadedImage(CRegisteredString inSourcePath, SLoadedTexture *inTexture,
+ SImageLoaderBatch &inBatch)
+ : m_SourcePath(inSourcePath)
+ , m_Texture(inTexture)
+ , m_Batch(&inBatch)
+ {
+ }
+
+ // Called from main thread
+ bool Finalize(IBufferManager &inMgr);
+};
+
+struct SBatchLoader : public IImageBatchLoader
+{
+ typedef nvhash_map<TImageBatchId, SImageLoaderBatch *> TImageLoaderBatchMap;
+ typedef nvhash_map<CRegisteredString, TImageBatchId> TSourcePathToBatchMap;
+ typedef Pool<SLoadingImage, ForwardingAllocator> TLoadingImagePool;
+ typedef Pool<SImageLoaderBatch, ForwardingAllocator> TBatchPool;
+
+ // Accessed from loader thread
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ // Accessed from loader thread
+ IInputStreamFactory &m_InputStreamFactory;
+ //!!Not threadsafe! accessed only from main thread
+ IBufferManager &m_BufferManager;
+ // Accessed from main thread
+ IThreadPool &m_ThreadPool;
+ // Accessed from both threads
+ IPerfTimer &m_PerfTimer;
+ // main thread
+ TImageBatchId m_NextBatchId;
+ // main thread
+ TImageLoaderBatchMap m_Batches;
+ // main thread
+ Mutex m_LoaderMutex;
+
+ // Both loader and main threads
+ nvvector<SBatchLoadedImage> m_LoadedImages;
+ // main thread
+ nvvector<TImageBatchId> m_FinishedBatches;
+ // main thread
+ TSourcePathToBatchMap m_SourcePathToBatches;
+ // main thread
+ nvvector<SLoadingImage> m_LoaderBuilderWorkspace;
+ TLoadingImagePool m_LoadingImagePool;
+ TBatchPool m_BatchPool;
+
+ SBatchLoader(NVFoundationBase &inFoundation, IInputStreamFactory &inFactory,
+ IBufferManager &inBufferManager, IThreadPool &inThreadPool, IPerfTimer &inTimer)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_InputStreamFactory(inFactory)
+ , m_BufferManager(inBufferManager)
+ , m_ThreadPool(inThreadPool)
+ , m_PerfTimer(inTimer)
+ , m_NextBatchId(1)
+ , m_Batches(inFoundation.getAllocator(), "SBatchLoader::m_Batches")
+ , m_LoaderMutex(inFoundation.getAllocator())
+ , m_LoadedImages(inFoundation.getAllocator(), "SBatchLoader::m_LoadedImages")
+ , m_FinishedBatches(inFoundation.getAllocator(), "SBatchLoader::m_FinishedBatches")
+ , m_SourcePathToBatches(inFoundation.getAllocator(), "SBatchLoader::m_SourcePathToBatches")
+ , m_LoaderBuilderWorkspace(inFoundation.getAllocator(),
+ "SBatchLoader::m_LoaderBuilderWorkspace")
+ , m_LoadingImagePool(
+ ForwardingAllocator(inFoundation.getAllocator(), "SBatchLoader::m_LoadingImagePool"))
+ , m_BatchPool(ForwardingAllocator(inFoundation.getAllocator(), "SBatchLoader::m_BatchPool"))
+ {
+ }
+
+ virtual ~SBatchLoader()
+ {
+ nvvector<TImageBatchId> theCancelledBatches(m_Foundation.getAllocator(), "~SBatchLoader");
+ for (TImageLoaderBatchMap::iterator theIter = m_Batches.begin(), theEnd = m_Batches.end();
+ theIter != theEnd; ++theIter) {
+ theIter->second->Cancel();
+ theCancelledBatches.push_back(theIter->second->m_BatchId);
+ }
+ for (QT3DSU32 idx = 0, end = theCancelledBatches.size(); idx < end; ++idx)
+ BlockUntilLoaded(theCancelledBatches[idx]);
+
+ QT3DS_ASSERT(m_Batches.size() == 0);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ // Returns an ID to the load request. Request a block of images to be loaded.
+ // Also takes an image that the buffer system will return when requested for the given source
+ // paths
+ // until said path is loaded.
+ // An optional listener can be passed in to get callbacks about the batch.
+ TImageBatchId LoadImageBatch(NVConstDataRef<CRegisteredString> inSourcePaths,
+ CRegisteredString inImageTillLoaded,
+ IImageLoadListener *inListener) override
+ {
+ if (inSourcePaths.size() == 0)
+ return 0;
+
+ TScopedLock __loaderLock(m_LoaderMutex);
+
+ TImageBatchId theBatchId = 0;
+
+ // Empty loop intentional to find an unused batch id.
+ for (theBatchId = m_NextBatchId; m_Batches.find(theBatchId) != m_Batches.end();
+ ++m_NextBatchId, theBatchId = m_NextBatchId) {
+ }
+
+ SImageLoaderBatch *theBatch(SImageLoaderBatch::CreateLoaderBatch(
+ *this, theBatchId, inSourcePaths, inImageTillLoaded, inListener));
+ if (theBatch) {
+ m_Batches.insert(eastl::make_pair(theBatchId, theBatch));
+ return theBatchId;
+ }
+ return 0;
+ }
+
+ void CancelImageBatchLoading(TImageBatchId inBatchId) override
+ {
+ SImageLoaderBatch *theBatch(GetBatch(inBatchId));
+ if (theBatch)
+ theBatch->Cancel();
+ }
+
+ // Blocks if the image is currently in-flight
+ void CancelImageLoading(CRegisteredString inSourcePath) override
+ {
+ TScopedLock __loaderLock(m_LoaderMutex);
+ TSourcePathToBatchMap::iterator theIter = m_SourcePathToBatches.find(inSourcePath);
+ if (theIter != m_SourcePathToBatches.end()) {
+ TImageBatchId theBatchId = theIter->second;
+ TImageLoaderBatchMap::iterator theBatchIter = m_Batches.find(theBatchId);
+ if (theBatchIter != m_Batches.end())
+ theBatchIter->second->Cancel(inSourcePath);
+ }
+ }
+
+ SImageLoaderBatch *GetBatch(TImageBatchId inId)
+ {
+ TScopedLock __loaderLock(m_LoaderMutex);
+ TImageLoaderBatchMap::iterator theIter = m_Batches.find(inId);
+ if (theIter != m_Batches.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ void BlockUntilLoaded(TImageBatchId inId) override
+ {
+ for (SImageLoaderBatch *theBatch = GetBatch(inId); theBatch; theBatch = GetBatch(inId)) {
+ // Only need to block if images aren't loaded. Don't need to block if they aren't
+ // finalized.
+ if (!theBatch->IsLoadingFinished()) {
+ theBatch->m_LoadEvent.wait(200);
+ theBatch->m_LoadEvent.reset();
+ }
+ BeginFrame();
+ }
+ }
+ void ImageLoaded(SLoadingImage &inImage, SLoadedTexture *inTexture)
+ {
+ TScopedLock __loaderLock(m_LoaderMutex);
+ m_LoadedImages.push_back(
+ SBatchLoadedImage(inImage.m_SourcePath, inTexture, *inImage.m_Batch));
+ inImage.m_Batch->IncrementLoadedImageCount();
+ inImage.m_Batch->m_LoadEvent.set();
+ }
+ // These are called by the render context, users don't need to call this.
+ void BeginFrame() override
+ {
+ TScopedLock __loaderLock(m_LoaderMutex);
+ // Pass 1 - send out all image loaded signals
+ for (QT3DSU32 idx = 0, end = m_LoadedImages.size(); idx < end; ++idx) {
+
+ m_SourcePathToBatches.erase(m_LoadedImages[idx].m_SourcePath);
+ m_LoadedImages[idx].Finalize(m_BufferManager);
+ m_LoadedImages[idx].m_Batch->IncrementFinalizedImageCount();
+ if (m_LoadedImages[idx].m_Batch->IsFinalizedFinished())
+ m_FinishedBatches.push_back(m_LoadedImages[idx].m_Batch->m_BatchId);
+ }
+ m_LoadedImages.clear();
+ // pass 2 - clean up any existing batches.
+ for (QT3DSU32 idx = 0, end = m_FinishedBatches.size(); idx < end; ++idx) {
+ TImageLoaderBatchMap::iterator theIter = m_Batches.find(m_FinishedBatches[idx]);
+ if (theIter != m_Batches.end()) {
+ SImageLoaderBatch *theBatch = theIter->second;
+ if (theBatch->m_LoadListener)
+ theBatch->m_LoadListener->OnImageBatchComplete(theBatch->m_BatchId);
+ m_Batches.erase(m_FinishedBatches[idx]);
+ theBatch->~SImageLoaderBatch();
+ m_BatchPool.deallocate(theBatch);
+ }
+ }
+ m_FinishedBatches.clear();
+ }
+
+ void EndFrame() override {}
+};
+
+void SLoadingImage::Setup(SImageLoaderBatch &inBatch)
+{
+ m_Batch = &inBatch;
+ m_TaskId = inBatch.m_Loader.m_ThreadPool.AddTask(this, LoadImage, TaskCancelled);
+}
+
+void SLoadingImage::LoadImage(void *inImg)
+{
+ SLoadingImage *theThis = reinterpret_cast<SLoadingImage *>(inImg);
+ SStackPerfTimer theTimer(theThis->m_Batch->m_Loader.m_PerfTimer, "Image Decompression");
+ if (theThis->m_Batch->m_Loader.m_BufferManager.IsImageLoaded(theThis->m_SourcePath) == false) {
+ SLoadedTexture *theTexture = SLoadedTexture::Load(
+ theThis->m_SourcePath.c_str(), theThis->m_Batch->m_Loader.m_Foundation,
+ theThis->m_Batch->m_Loader.m_InputStreamFactory);
+ // if ( theTexture )
+ // theTexture->EnsureMultiplerOfFour( theThis->m_Batch->m_Loader.m_Foundation,
+ //theThis->m_SourcePath.c_str() );
+
+ theThis->m_Batch->m_Loader.ImageLoaded(*theThis, theTexture);
+ } else {
+ theThis->m_Batch->m_Loader.ImageLoaded(*theThis, NULL);
+ }
+}
+
+void SLoadingImage::TaskCancelled(void *inImg)
+{
+ SLoadingImage *theThis = reinterpret_cast<SLoadingImage *>(inImg);
+ theThis->m_Batch->m_Loader.ImageLoaded(*theThis, NULL);
+}
+
+bool SBatchLoadedImage::Finalize(IBufferManager &inMgr)
+{
+ if (m_Texture) {
+ // PKC : We'll look at the path location to see if the image is in the standard
+ // location for IBL light probes or a standard hdr format and decide to generate BSDF
+ // miplevels (if the image doesn't have
+ // mipmaps of its own that is).
+ eastl::string thepath(m_SourcePath);
+ bool isIBL = (thepath.find(".hdr") != eastl::string::npos)
+ || (thepath.find("\\IBL\\") != eastl::string::npos)
+ || (thepath.find("/IBL/") != eastl::string::npos);
+ inMgr.LoadRenderImage(m_SourcePath, *m_Texture, false, isIBL);
+ inMgr.UnaliasImagePath(m_SourcePath);
+ }
+ if (m_Batch->m_LoadListener)
+ m_Batch->m_LoadListener->OnImageLoadComplete(
+ m_SourcePath, m_Texture ? ImageLoadResult::Succeeded : ImageLoadResult::Failed);
+
+ if (m_Texture) {
+ m_Texture->release();
+ return true;
+ }
+
+ return false;
+}
+
+SImageLoaderBatch *
+SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBatchId,
+ NVConstDataRef<CRegisteredString> inSourcePaths,
+ CRegisteredString inImageTillLoaded,
+ IImageLoadListener *inListener)
+{
+ TLoadingImageList theImages;
+ QT3DSU32 theLoadingImageCount = 0;
+ for (QT3DSU32 idx = 0, end = inSourcePaths.size(); idx < end; ++idx) {
+ CRegisteredString theSourcePath(inSourcePaths[idx]);
+
+ if (theSourcePath.IsValid() == false)
+ continue;
+
+ if (inLoader.m_BufferManager.IsImageLoaded(theSourcePath))
+ continue;
+
+ eastl::pair<SBatchLoader::TSourcePathToBatchMap::iterator, bool> theInserter =
+ inLoader.m_SourcePathToBatches.insert(eastl::make_pair(inSourcePaths[idx], inBatchId));
+
+ // If the loader has already seen this image.
+ if (theInserter.second == false)
+ continue;
+
+ if (inImageTillLoaded.IsValid()) {
+ // Alias the image so any further requests for this source path will result in
+ // the default images (image till loaded).
+ bool aliasSuccess =
+ inLoader.m_BufferManager.AliasImagePath(theSourcePath, inImageTillLoaded, true);
+ (void)aliasSuccess;
+ QT3DS_ASSERT(aliasSuccess);
+ }
+
+ theImages.push_front(
+ *inLoader.m_LoadingImagePool.construct(theSourcePath, __FILE__, __LINE__));
+ ++theLoadingImageCount;
+ }
+ if (theImages.empty() == false) {
+ SImageLoaderBatch *theBatch =
+ (SImageLoaderBatch *)inLoader.m_BatchPool.allocate(__FILE__, __LINE__);
+ new (theBatch)
+ SImageLoaderBatch(inLoader, inListener, theImages, inBatchId, theLoadingImageCount);
+ return theBatch;
+ }
+ return NULL;
+}
+
+SImageLoaderBatch::SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener *inLoadListener,
+ const TLoadingImageList &inImageList, TImageBatchId inBatchId,
+ QT3DSU32 inImageCount)
+ : m_Loader(inLoader)
+ , m_LoadListener(inLoadListener)
+ , m_LoadEvent(inLoader.m_Foundation.getAllocator())
+ , m_LoadMutex(inLoader.m_Foundation.getAllocator())
+ , m_Images(inImageList)
+ , m_BatchId(inBatchId)
+ , m_LoadedOrCanceledImageCount(0)
+ , m_FinalizedImageCount(0)
+ , m_NumImages(inImageCount)
+{
+ for (TLoadingImageList::iterator iter = m_Images.begin(), end = m_Images.end(); iter != end;
+ ++iter) {
+ iter->Setup(*this);
+ }
+}
+
+SImageLoaderBatch::~SImageLoaderBatch()
+{
+ for (TLoadingImageList::iterator iter = m_Images.begin(), end = m_Images.end(); iter != end;
+ ++iter) {
+ TLoadingImageList::iterator temp(iter);
+ ++iter;
+ m_Loader.m_LoadingImagePool.deallocate(temp.m_Obj);
+ }
+}
+
+void SImageLoaderBatch::Cancel()
+{
+ for (TLoadingImageList::iterator iter = m_Images.begin(), end = m_Images.end(); iter != end;
+ ++iter)
+ m_Loader.m_ThreadPool.CancelTask(iter->m_TaskId);
+}
+
+void SImageLoaderBatch::Cancel(CRegisteredString inSourcePath)
+{
+ for (TLoadingImageList::iterator iter = m_Images.begin(), end = m_Images.end(); iter != end;
+ ++iter) {
+ if (iter->m_SourcePath == inSourcePath) {
+ m_Loader.m_ThreadPool.CancelTask(iter->m_TaskId);
+ break;
+ }
+ }
+}
+}
+
+IImageBatchLoader &IImageBatchLoader::CreateBatchLoader(NVFoundationBase &inFoundation,
+ IInputStreamFactory &inFactory,
+ IBufferManager &inBufferManager,
+ IThreadPool &inThreadPool,
+ IPerfTimer &inTimer)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(),
+ SBatchLoader)(inFoundation, inFactory, inBufferManager, inThreadPool, inTimer);
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.h
new file mode 100644
index 00000000..5c176f75
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderImageBatchLoader.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_THREADED_IMAGE_LOADER_H
+#define UIC_RENDER_THREADED_IMAGE_LOADER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace uic {
+namespace render {
+ struct ImageLoadResult
+ {
+ enum Enum {
+ Succeeded,
+ Failed,
+ };
+ };
+
+ class IImageLoadListener : public NVRefCounted
+ {
+ protected:
+ virtual ~IImageLoadListener() {}
+
+ public:
+ virtual void OnImageLoadComplete(CRegisteredString inPath,
+ ImageLoadResult::Enum inResult) = 0;
+ virtual void OnImageBatchComplete(QT3DSU64 inBatch) = 0;
+ };
+
+ typedef QT3DSU32 TImageBatchId;
+
+ class IImageBatchLoader : public NVRefCounted
+ {
+ protected:
+ virtual ~IImageBatchLoader() {}
+
+ public:
+ // Returns an ID to the load request. Request a block of images to be loaded.
+ // Also takes an image that the buffer system will return when requested for the given
+ // source paths
+ // until said path is loaded.
+ // An optional listener can be passed in to get callbacks about the batch.
+ virtual TImageBatchId LoadImageBatch(NVConstDataRef<CRegisteredString> inSourcePaths,
+ CRegisteredString inImageTillLoaded,
+ IImageLoadListener *inListener) = 0;
+ // Blocks if any of the images in the batch are in flight
+ virtual void CancelImageBatchLoading(TImageBatchId inBatchId) = 0;
+ // Blocks if the image is currently in-flight
+ virtual void CancelImageLoading(CRegisteredString inSourcePath) = 0;
+ // Block until every image in the batch is loaded.
+ virtual void BlockUntilLoaded(TImageBatchId inId) = 0;
+
+ // These are called by the render context, users don't need to call this.
+ virtual void BeginFrame() = 0;
+ virtual void EndFrame() = 0;
+
+ static IImageBatchLoader &CreateBatchLoader(NVFoundationBase &inFoundation,
+ IInputStreamFactory &inFactory,
+ IBufferManager &inBufferManager,
+ IThreadPool &inThreadPool, IPerfTimer &inTimer);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.cpp
new file mode 100644
index 00000000..4e87a016
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.cpp
@@ -0,0 +1,679 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderLoadedTexture.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICDMWindowsCompatibility.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICRenderImageScaler.h"
+#include "UICTextRenderer.h"
+#include <QImage>
+
+using namespace uic::render;
+
+SLoadedTexture *SLoadedTexture::LoadQImage(const QString &inPath, QT3DSI32 flipVertical,
+ NVFoundationBase &fnd)
+{
+ Q_UNUSED(flipVertical)
+ SLoadedTexture *retval(NULL);
+ NVAllocatorCallback &alloc(fnd.getAllocator());
+ QImage image(inPath);
+ image = image.mirrored();
+ image = image.rgbSwapped();
+ retval = QT3DS_NEW(alloc, SLoadedTexture)(alloc);
+ retval->width = image.width();
+ retval->height = image.height();
+ retval->components = image.pixelFormat().channelCount();
+ retval->image = image;
+ retval->data = (void*)retval->image.bits();
+ retval->dataSizeInBytes = image.byteCount();
+ retval->setFormatFromComponents();
+ return retval;
+}
+
+
+namespace {
+
+/**
+ !!Large section of code ripped from FreeImage!!
+
+*/
+// ----------------------------------------------------------
+// Structures used by DXT textures
+// ----------------------------------------------------------
+typedef QT3DSU8 BYTE;
+typedef QT3DSU16 WORD;
+
+typedef struct tagColor8888
+{
+ BYTE b;
+ BYTE g;
+ BYTE r;
+ BYTE a;
+} Color8888;
+
+typedef struct tagColor565
+{
+ WORD b : 5;
+ WORD g : 6;
+ WORD r : 5;
+} Color565;
+
+typedef struct tagDXTColBlock
+{
+ Color565 colors[2];
+ BYTE row[4];
+} DXTColBlock;
+
+typedef struct tagDXTAlphaBlockExplicit
+{
+ WORD row[4];
+} DXTAlphaBlockExplicit;
+
+typedef struct tagDXTAlphaBlock3BitLinear
+{
+ BYTE alpha[2];
+ BYTE data[6];
+} DXTAlphaBlock3BitLinear;
+
+typedef struct tagDXT1Block
+{
+ DXTColBlock color;
+} DXT1Block;
+
+typedef struct tagDXT3Block
+{ // also used by dxt2
+ DXTAlphaBlockExplicit alpha;
+ DXTColBlock color;
+} DXT3Block;
+
+typedef struct tagDXT5Block
+{ // also used by dxt4
+ DXTAlphaBlock3BitLinear alpha;
+ DXTColBlock color;
+} DXT5Block;
+
+static void GetBlockColors(const DXTColBlock &block, Color8888 colors[4], bool isDXT1)
+{
+ int i;
+ for (i = 0; i < 2; i++) {
+ colors[i].a = 0xff;
+ colors[i].r = (BYTE)(block.colors[i].r * 0xff / 0x1f);
+ colors[i].g = (BYTE)(block.colors[i].g * 0xff / 0x3f);
+ colors[i].b = (BYTE)(block.colors[i].b * 0xff / 0x1f);
+ }
+
+ WORD *wCol = (WORD *)block.colors;
+ if (wCol[0] > wCol[1] || !isDXT1) {
+ // 4 color block
+ for (i = 0; i < 2; i++) {
+ colors[i + 2].a = 0xff;
+ colors[i + 2].r =
+ (BYTE)((WORD(colors[0].r) * (2 - i) + WORD(colors[1].r) * (1 + i)) / 3);
+ colors[i + 2].g =
+ (BYTE)((WORD(colors[0].g) * (2 - i) + WORD(colors[1].g) * (1 + i)) / 3);
+ colors[i + 2].b =
+ (BYTE)((WORD(colors[0].b) * (2 - i) + WORD(colors[1].b) * (1 + i)) / 3);
+ }
+ } else {
+ // 3 color block, number 4 is transparent
+ colors[2].a = 0xff;
+ colors[2].r = (BYTE)((WORD(colors[0].r) + WORD(colors[1].r)) / 2);
+ colors[2].g = (BYTE)((WORD(colors[0].g) + WORD(colors[1].g)) / 2);
+ colors[2].b = (BYTE)((WORD(colors[0].b) + WORD(colors[1].b)) / 2);
+
+ colors[3].a = 0x00;
+ colors[3].g = 0x00;
+ colors[3].b = 0x00;
+ colors[3].r = 0x00;
+ }
+}
+
+struct DXT_INFO_1
+{
+ typedef DXT1Block Block;
+ enum { isDXT1 = 1, bytesPerBlock = 8 };
+};
+
+struct DXT_INFO_3
+{
+ typedef DXT3Block Block;
+ enum { isDXT1 = 1, bytesPerBlock = 16 };
+};
+
+struct DXT_INFO_5
+{
+ typedef DXT5Block Block;
+ enum { isDXT1 = 1, bytesPerBlock = 16 };
+};
+
+template <class INFO>
+class DXT_BLOCKDECODER_BASE
+{
+protected:
+ Color8888 m_colors[4];
+ const typename INFO::Block *m_pBlock;
+ unsigned m_colorRow;
+
+public:
+ void Setup(const BYTE *pBlock)
+ {
+ m_pBlock = (const typename INFO::Block *)pBlock;
+ GetBlockColors(m_pBlock->color, m_colors, INFO::isDXT1);
+ }
+
+ void SetY(int y) { m_colorRow = m_pBlock->color.row[y]; }
+
+ void GetColor(int x, int y, Color8888 &color)
+ {
+ Q_UNUSED(y)
+ unsigned bits = (m_colorRow >> (x * 2)) & 3;
+ color = m_colors[bits];
+ std::swap(color.r, color.b);
+ }
+};
+
+class DXT_BLOCKDECODER_1 : public DXT_BLOCKDECODER_BASE<DXT_INFO_1>
+{
+public:
+ typedef DXT_INFO_1 INFO;
+};
+
+class DXT_BLOCKDECODER_3 : public DXT_BLOCKDECODER_BASE<DXT_INFO_3>
+{
+public:
+ typedef DXT_BLOCKDECODER_BASE<DXT_INFO_3> base;
+ typedef DXT_INFO_3 INFO;
+
+protected:
+ unsigned m_alphaRow;
+
+public:
+ void SetY(int y)
+ {
+ base::SetY(y);
+ m_alphaRow = m_pBlock->alpha.row[y];
+ }
+
+ void GetColor(int x, int y, Color8888 &color)
+ {
+ base::GetColor(x, y, color);
+ const unsigned bits = (m_alphaRow >> (x * 4)) & 0xF;
+ color.a = (BYTE)((bits * 0xFF) / 0xF);
+ }
+};
+
+class DXT_BLOCKDECODER_5 : public DXT_BLOCKDECODER_BASE<DXT_INFO_5>
+{
+public:
+ typedef DXT_BLOCKDECODER_BASE<DXT_INFO_5> base;
+ typedef DXT_INFO_5 INFO;
+
+protected:
+ unsigned m_alphas[8];
+ unsigned m_alphaBits;
+ int m_offset;
+
+public:
+ void Setup(const BYTE *pBlock)
+ {
+ base::Setup(pBlock);
+
+ const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
+ m_alphas[0] = block.alpha[0];
+ m_alphas[1] = block.alpha[1];
+ if (m_alphas[0] > m_alphas[1]) {
+ // 8 alpha block
+ for (int i = 0; i < 6; i++) {
+ m_alphas[i + 2] = ((6 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 3) / 7;
+ }
+ } else {
+ // 6 alpha block
+ for (int i = 0; i < 4; i++) {
+ m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5;
+ }
+ m_alphas[6] = 0;
+ m_alphas[7] = 0xFF;
+ }
+ }
+
+ void SetY(int y)
+ {
+ base::SetY(y);
+ int i = y / 2;
+ const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
+ m_alphaBits = unsigned(block.data[0 + i * 3]) | (unsigned(block.data[1 + i * 3]) << 8)
+ | (unsigned(block.data[2 + i * 3]) << 16);
+ m_offset = (y & 1) * 12;
+ }
+
+ void GetColor(int x, int y, Color8888 &color)
+ {
+ base::GetColor(x, y, color);
+ unsigned bits = (m_alphaBits >> (x * 3 + m_offset)) & 7;
+ color.a = (BYTE)m_alphas[bits];
+ std::swap(color.r, color.b);
+ }
+};
+
+template <class DECODER>
+void DecodeDXTBlock(BYTE *dstData, const BYTE *srcBlock, long dstPitch, int bw, int bh)
+{
+ DECODER decoder;
+ decoder.Setup(srcBlock);
+ for (int y = 0; y < bh; y++) {
+ // Note that this assumes the pointer is pointing to the *last* valid start
+ // row.
+ BYTE *dst = dstData - y * dstPitch;
+ decoder.SetY(y);
+ for (int x = 0; x < bw; x++) {
+ decoder.GetColor(x, y, (Color8888 &)*dst);
+ dst += 4;
+ }
+ }
+}
+
+struct STextureDataWriter
+{
+ QT3DSU32 m_Width;
+ QT3DSU32 m_Height;
+ QT3DSU32 m_Stride;
+ QT3DSU32 m_NumComponents;
+ STextureData &m_TextureData;
+ STextureDataWriter(QT3DSU32 w, QT3DSU32 h, bool hasA, STextureData &inTd, NVAllocatorCallback &alloc)
+ : m_Width(w)
+ , m_Height(h)
+ , m_Stride(hasA ? m_Width * 4 : m_Width * 3)
+ , m_NumComponents(hasA ? 4 : 3)
+ , m_TextureData(inTd)
+ {
+ QT3DSU32 dataSize = m_Stride * m_Height;
+ if (dataSize > m_TextureData.dataSizeInBytes) {
+ alloc.deallocate(m_TextureData.data);
+ m_TextureData.data =
+ alloc.allocate(dataSize, "SLoadedTexture::DecompressDXTImage", __FILE__, __LINE__);
+ m_TextureData.dataSizeInBytes = dataSize;
+ }
+ memZero(m_TextureData.data, m_TextureData.dataSizeInBytes);
+ m_TextureData.format = hasA ? NVRenderTextureFormats::RGBA8 : NVRenderTextureFormats::RGB8;
+ }
+
+ void WritePixel(QT3DSU32 X, QT3DSU32 Y, QT3DSU8 *pixelData)
+ {
+ if (X < m_Width && Y < m_Height) {
+ char *textureData = reinterpret_cast<char *>(m_TextureData.data);
+ QT3DSU32 offset = Y * m_Stride + X * m_NumComponents;
+
+ for (QT3DSU32 idx = 0; idx < m_NumComponents; ++idx)
+ QT3DS_ASSERT(textureData[offset + idx] == 0);
+
+ memCopy(textureData + offset, pixelData, m_NumComponents);
+ }
+ }
+
+ // Incoming pixels are assumed to be RGBA or RGBX, 32 bit in any case
+ void WriteBlock(QT3DSU32 X, QT3DSU32 Y, QT3DSU32 width, QT3DSU32 height, QT3DSU8 *pixelData)
+ {
+ QT3DSU32 offset = 0;
+ for (QT3DSU32 yidx = 0; yidx < height; ++yidx) {
+ for (QT3DSU32 xidx = 0; xidx < width; ++xidx, offset += 4) {
+ WritePixel(X + xidx, Y + (height - yidx - 1), pixelData + offset);
+ }
+ }
+ }
+ bool Finished() { return false; }
+};
+
+struct STextureAlphaScanner
+{
+ bool &m_Alpha;
+
+ STextureAlphaScanner(bool &inAlpha)
+ : m_Alpha(inAlpha)
+ {
+ }
+
+ void WriteBlock(QT3DSU32 X, QT3DSU32 Y, QT3DSU32 width, QT3DSU32 height, QT3DSU8 *pixelData)
+ {
+ Q_UNUSED(X)
+ Q_UNUSED(Y)
+ QT3DSU32 offset = 0;
+ for (QT3DSU32 yidx = 0; yidx < height; ++yidx) {
+ for (QT3DSU32 xidx = 0; xidx < width; ++xidx, offset += 4) {
+ if (pixelData[offset + 3] < 255)
+ m_Alpha = true;
+ }
+ }
+ }
+
+ // If we detect alpha we can stop right there.
+ bool Finished() { return m_Alpha; }
+};
+// Scan the dds image's mipmap 0 level for alpha.
+template <class DECODER, class TWriterType>
+static void DecompressDDS(void *inSrc, QT3DSU32 inDataSize, QT3DSU32 inWidth, QT3DSU32 inHeight,
+ TWriterType ioWriter)
+{
+ typedef typename DECODER::INFO INFO;
+ typedef typename INFO::Block Block;
+ (void)inDataSize;
+
+ const QT3DSU8 *pbSrc = (const QT3DSU8 *)inSrc;
+ // Each DX block is composed of 16 pixels. Free image decodes those
+ // pixels into a 4x4 block of data.
+ QT3DSU8 pbDstData[4 * 4 * 4];
+ // The decoder decodes backwards
+ // So we need to point to the last line.
+ QT3DSU8 *pbDst = pbDstData + 48;
+
+ int width = (int)inWidth;
+ int height = (int)inHeight;
+ int lineStride = 16;
+ for (int y = 0; y < height && ioWriter.Finished() == false; y += 4) {
+ int yPixels = NVMin(height - y, 4);
+ for (int x = 0; x < width && ioWriter.Finished() == false; x += 4) {
+ int xPixels = NVMin(width - x, 4);
+ DecodeDXTBlock<DECODER>(pbDst, pbSrc, lineStride, xPixels, yPixels);
+ pbSrc += INFO::bytesPerBlock;
+ ioWriter.WriteBlock(x, y, xPixels, yPixels, pbDstData);
+ }
+ }
+}
+
+bool ScanDDSForAlpha(UICDDSImage *dds)
+{
+ bool hasAlpha = false;
+ switch (dds->format) {
+ case qt3ds::render::NVRenderTextureFormats::RGBA_DXT1:
+ DecompressDDS<DXT_BLOCKDECODER_1>(dds->data[0], dds->size[0], dds->mipwidth[0],
+ dds->mipheight[0], STextureAlphaScanner(hasAlpha));
+ break;
+ case qt3ds::render::NVRenderTextureFormats::RGBA_DXT3:
+ DecompressDDS<DXT_BLOCKDECODER_3>(dds->data[0], dds->size[0], dds->mipwidth[0],
+ dds->mipheight[0], STextureAlphaScanner(hasAlpha));
+ break;
+ case qt3ds::render::NVRenderTextureFormats::RGBA_DXT5:
+ DecompressDDS<DXT_BLOCKDECODER_5>(dds->data[0], dds->size[0], dds->mipwidth[0],
+ dds->mipheight[0], STextureAlphaScanner(hasAlpha));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return hasAlpha;
+}
+
+bool ScanImageForAlpha(const void *inData, QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 inPixelSizeInBytes,
+ QT3DSU8 inAlphaSizeInBits)
+{
+ const QT3DSU8 *rowPtr = reinterpret_cast<const QT3DSU8 *>(inData);
+ bool hasAlpha = false;
+ if (inAlphaSizeInBits == 0)
+ return hasAlpha;
+ if (inPixelSizeInBytes != 2 && inPixelSizeInBytes != 4) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (inAlphaSizeInBits > 8) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ QT3DSU32 alphaRightShift = inPixelSizeInBytes * 8 - inAlphaSizeInBits;
+ QT3DSU32 maxAlphaValue = (1 << inAlphaSizeInBits) - 1;
+
+ for (QT3DSU32 rowIdx = 0; rowIdx < inHeight && hasAlpha == false; ++rowIdx) {
+ for (QT3DSU32 idx = 0; idx < inWidth && hasAlpha == false;
+ ++idx, rowPtr += inPixelSizeInBytes) {
+ QT3DSU32 pixelValue = 0;
+ if (inPixelSizeInBytes == 2)
+ pixelValue = *(reinterpret_cast<const QT3DSU16 *>(rowPtr));
+ else
+ pixelValue = *(reinterpret_cast<const QT3DSU32 *>(rowPtr));
+ pixelValue = pixelValue >> alphaRightShift;
+ if (pixelValue < maxAlphaValue)
+ hasAlpha = true;
+ }
+ }
+ return hasAlpha;
+}
+}
+
+SLoadedTexture::~SLoadedTexture()
+{
+ if (dds) {
+ if (dds->dataBlock)
+ QT3DS_FREE(m_Allocator, dds->dataBlock);
+
+ QT3DS_FREE(m_Allocator, dds);
+ } else if (data && image.byteCount() <= 0) {
+ m_Allocator.deallocate(data);
+ }
+ if (m_Palette)
+ m_Allocator.deallocate(m_Palette);
+ if (m_TransparencyTable)
+ m_Allocator.deallocate(m_TransparencyTable);
+}
+
+void SLoadedTexture::release()
+{
+ NVAllocatorCallback *theAllocator(&m_Allocator);
+ this->~SLoadedTexture();
+ theAllocator->deallocate(this);
+}
+
+bool SLoadedTexture::ScanForTransparency()
+{
+ switch (format) {
+ case NVRenderTextureFormats::SRGB8A8:
+ case NVRenderTextureFormats::RGBA8:
+ if (!data) { // dds
+ return true;
+ } else {
+ return ScanImageForAlpha(data, width, height, 4, 8);
+ }
+ break;
+ // Scan the image.
+ case NVRenderTextureFormats::SRGB8:
+ case NVRenderTextureFormats::RGB8:
+ return false;
+ break;
+ case NVRenderTextureFormats::RGB565:
+ return false;
+ break;
+ case NVRenderTextureFormats::RGBA5551:
+ if (!data) { // dds
+ return true;
+ } else {
+ return ScanImageForAlpha(data, width, height, 2, 1);
+ }
+ break;
+ case NVRenderTextureFormats::Alpha8:
+ return true;
+ break;
+ case NVRenderTextureFormats::Luminance8:
+ return false;
+ break;
+ case NVRenderTextureFormats::LuminanceAlpha8:
+ if (!data) { // dds
+ return true;
+ } else {
+ return ScanImageForAlpha(data, width, height, 2, 8);
+ }
+ break;
+ case NVRenderTextureFormats::RGB_DXT1:
+ return false;
+ break;
+ case NVRenderTextureFormats::RGBA_DXT3:
+ case NVRenderTextureFormats::RGBA_DXT1:
+ case NVRenderTextureFormats::RGBA_DXT5:
+ if (dds) {
+ return ScanDDSForAlpha(dds);
+ } else {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ break;
+ case NVRenderTextureFormats::RGB9E5:
+ return false;
+ break;
+ case NVRenderTextureFormats::RG32F:
+ case NVRenderTextureFormats::RGB32F:
+ case NVRenderTextureFormats::RGBA16F:
+ case NVRenderTextureFormats::RGBA32F:
+ // PKC TODO : For now, since IBL will be the main consumer, we'll just pretend there's no
+ // alpha.
+ // Need to do a proper scan down the line, but doing it for floats is a little different
+ // from
+ // integer scans.
+ return false;
+ break;
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return false;
+}
+
+void SLoadedTexture::EnsureMultiplerOfFour(NVFoundationBase &inFoundation, const char *inPath)
+{
+ if (width % 4 || height % 4) {
+ qCWarning(PERF_WARNING,
+ "Image %s has non multiple of four width or height; perf hit for scaling", inPath);
+ if (data) {
+ QT3DSU32 newWidth = ITextRenderer::NextMultipleOf4(width);
+ QT3DSU32 newHeight = ITextRenderer::NextMultipleOf4(height);
+ QT3DSU32 newDataSize = newWidth * newHeight * components;
+ NVAllocatorCallback &theAllocator(inFoundation.getAllocator());
+ QT3DSU8 *newData = (QT3DSU8 *)(theAllocator.allocate(newDataSize, "Scaled Image Data",
+ __FILE__, __LINE__));
+ CImageScaler theScaler(theAllocator);
+ if (components == 4) {
+ theScaler.FastExpandRowsAndColumns((unsigned char *)data, width, height, newData,
+ newWidth, newHeight);
+ } else
+ theScaler.ExpandRowsAndColumns((unsigned char *)data, width, height, newData,
+ newWidth, newHeight, components);
+
+ theAllocator.deallocate(data);
+ data = newData;
+ width = newWidth;
+ height = newHeight;
+ dataSizeInBytes = newDataSize;
+ }
+ }
+}
+
+STextureData SLoadedTexture::DecompressDXTImage(int inMipMapIdx, STextureData *inOptLastImage)
+{
+ STextureData retval;
+ if (inOptLastImage)
+ retval = *inOptLastImage;
+
+ if (dds == NULL || inMipMapIdx >= dds->numMipmaps) {
+ QT3DS_ASSERT(false);
+ ReleaseDecompressedTexture(retval);
+ return STextureData();
+ }
+ char *srcData = (char *)dds->data[inMipMapIdx];
+ int srcDataSize = dds->size[inMipMapIdx];
+ QT3DSU32 imgWidth = (QT3DSU32)dds->mipwidth[inMipMapIdx];
+ QT3DSU32 imgHeight = (QT3DSU32)dds->mipheight[inMipMapIdx];
+
+ switch (format) {
+ case NVRenderTextureFormats::RGB_DXT1:
+ DecompressDDS<DXT_BLOCKDECODER_1>(
+ srcData, srcDataSize, imgWidth, imgHeight,
+ STextureDataWriter(imgWidth, imgHeight, false, retval, m_Allocator));
+ break;
+ case NVRenderTextureFormats::RGBA_DXT1:
+ DecompressDDS<DXT_BLOCKDECODER_1>(
+ srcData, srcDataSize, imgWidth, imgHeight,
+ STextureDataWriter(imgWidth, imgHeight, true, retval, m_Allocator));
+ break;
+ case NVRenderTextureFormats::RGBA_DXT3:
+ DecompressDDS<DXT_BLOCKDECODER_3>(
+ srcData, srcDataSize, imgWidth, imgHeight,
+ STextureDataWriter(imgWidth, imgHeight, true, retval, m_Allocator));
+ break;
+ case NVRenderTextureFormats::RGBA_DXT5:
+ DecompressDDS<DXT_BLOCKDECODER_5>(
+ srcData, srcDataSize, imgWidth, imgHeight,
+ STextureDataWriter(imgWidth, imgHeight, true, retval, m_Allocator));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return retval;
+}
+
+void SLoadedTexture::ReleaseDecompressedTexture(STextureData inImage)
+{
+ if (inImage.data)
+ m_Allocator.deallocate(inImage.data);
+}
+
+#ifndef EA_PLATFORM_WINDOWS
+#define stricmp strcasecmp
+#endif
+
+SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &inFoundation,
+ IInputStreamFactory &inFactory, bool inFlipY)
+{
+ if (inPath.isEmpty())
+ return NULL;
+
+ SLoadedTexture *theLoadedImage = NULL;
+ NVScopedRefCounted<IRefCountedInputStream> theStream(inFactory.GetStreamForFile(inPath));
+ QString fileName;
+ inFactory.GetPathForFile(inPath, fileName);
+ if (theStream.mPtr && inPath.size() > 3) {
+ if (inPath.endsWith("png"))
+ theLoadedImage = LoadQImage(fileName, inFlipY, inFoundation);
+ else if (inPath.endsWith("jpg") || inPath.endsWith("peg"))
+ theLoadedImage = LoadQImage(fileName, inFlipY, inFoundation);
+ else if (inPath.endsWith("dds"))
+ theLoadedImage = LoadDDS(*theStream, inFlipY, inFoundation);
+ else if (inPath.endsWith("gif"))
+ theLoadedImage = LoadGIF(*theStream, !inFlipY, inFoundation);
+ else if (inPath.endsWith("bmp"))
+ theLoadedImage = LoadBMP(*theStream, !inFlipY, inFoundation);
+ else if (inPath.endsWith("hdr"))
+ theLoadedImage = LoadHDR(*theStream, inFoundation);
+ else {
+ qCCritical(INTERNAL_ERROR, "Unrecognized image extension: %s", qPrintable(inPath));
+ }
+ }
+ return theLoadedImage;
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.h
new file mode 100644
index 00000000..cc708903
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTexture.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_LOADED_TEXTURE_H
+#define UIC_RENDER_LOADED_TEXTURE_H
+#include "UICRender.h"
+#include "foundation/Qt3DSSimpleTypes.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "UICRenderLoadedTextureDDS.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include <QImage>
+
+namespace qt3ds {
+namespace foundation {
+ class ISeekableIOStream;
+ class IInStream;
+}
+}
+
+namespace uic {
+namespace render {
+
+ class IInputStreamFactory;
+
+ struct STextureData
+ {
+ void *data;
+ QT3DSU32 dataSizeInBytes;
+ qt3ds::render::NVRenderTextureFormats::Enum format;
+ STextureData()
+ : data(NULL)
+ , dataSizeInBytes(0)
+ , format(qt3ds::render::NVRenderTextureFormats::Unknown)
+ {
+ }
+ };
+ struct ExtendedTextureFormats
+ {
+ enum Enum {
+ NoExtendedFormat = 0,
+ Palettized,
+ CustomRGB,
+ };
+ };
+ // Utility class used for loading image data from disk.
+ // Supports jpg, png, and dds.
+ struct SLoadedTexture : public NVReleasable
+ {
+ private:
+ ~SLoadedTexture();
+
+ public:
+ NVAllocatorCallback &m_Allocator;
+ QT3DSI32 width;
+ QT3DSI32 height;
+ QT3DSI32 components;
+ void *data;
+ QImage image;
+ QT3DSU32 dataSizeInBytes;
+ qt3ds::render::NVRenderTextureFormats::Enum format;
+ UICDDSImage *dds;
+ ExtendedTextureFormats::Enum m_ExtendedFormat;
+ // Used for palettized images.
+ void *m_Palette;
+ QT3DSI32 m_CustomMasks[3];
+ int m_BitCount;
+ char8_t m_BackgroundColor[3];
+ uint8_t *m_TransparencyTable;
+ int32_t m_TransparentPaletteIndex;
+
+ SLoadedTexture(NVAllocatorCallback &inAllocator)
+ : m_Allocator(inAllocator)
+ , width(0)
+ , height(0)
+ , components(0)
+ , data(NULL)
+ , image(0)
+ , dataSizeInBytes(0)
+ , format(qt3ds::render::NVRenderTextureFormats::RGBA8)
+ , dds(NULL)
+ , m_ExtendedFormat(ExtendedTextureFormats::NoExtendedFormat)
+ , m_Palette(NULL)
+ , m_BitCount(0)
+ , m_TransparencyTable(NULL)
+ , m_TransparentPaletteIndex(-1)
+ {
+ m_CustomMasks[0] = 0;
+ m_CustomMasks[1] = 0;
+ m_CustomMasks[2] = 0;
+ m_BackgroundColor[0] = 0;
+ m_BackgroundColor[1] = 0;
+ m_BackgroundColor[2] = 0;
+ }
+ void setFormatFromComponents()
+ {
+ switch (components) {
+ case 1: // undefined, but in this context probably luminance
+ format = qt3ds::render::NVRenderTextureFormats::Luminance8;
+ break;
+ case 2:
+ format = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8;
+ break;
+ case 3:
+ format = qt3ds::render::NVRenderTextureFormats::RGB8;
+ break;
+
+ default:
+ QT3DS_ASSERT(false);
+ // fallthrough intentional
+ case 4:
+ format = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ break;
+ }
+ }
+
+ void EnsureMultiplerOfFour(NVFoundationBase &inFoundation, const char *inPath);
+ // Returns true if this image has a pixel less than 255.
+ bool ScanForTransparency();
+
+ // Be sure to call this or risk leaking an enormous amount of memory
+ void release() override;
+
+ // Not all video cards support dxt compression. Giving the last image allows
+ // this object to potentially reuse the memory
+ STextureData DecompressDXTImage(int inMipMapIdx, STextureData *inOptLastImage = NULL);
+ void ReleaseDecompressedTexture(STextureData inImage);
+
+ static SLoadedTexture *Load(const QString &inPath, NVFoundationBase &inAllocator,
+ IInputStreamFactory &inFactory, bool inFlipY = true);
+ static SLoadedTexture *LoadDDS(IInStream &inStream, QT3DSI32 flipVertical,
+ NVFoundationBase &fnd);
+ static SLoadedTexture *LoadBMP(ISeekableIOStream &inStream, bool inFlipY,
+ NVFoundationBase &inFnd);
+ static SLoadedTexture *LoadGIF(ISeekableIOStream &inStream, bool inFlipY,
+ NVFoundationBase &inFnd);
+ static SLoadedTexture *LoadHDR(ISeekableIOStream &inStream, NVFoundationBase &inFnd);
+
+ static SLoadedTexture *LoadQImage(const QString &inPath, QT3DSI32 flipVertical,
+ NVFoundationBase &fnd);
+
+ private:
+ // Implemented in the bmp loader.
+ void FreeImagePostProcess(bool inFlipY);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureBMP.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureBMP.cpp
new file mode 100644
index 00000000..e74b42f3
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureBMP.cpp
@@ -0,0 +1,1267 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// ==========================================================
+// BMP Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Markus Loibl (markus.loibl@epost.de)
+// - Martin Weber (martweb@gmx.net)
+// - Herve Drolon (drolon@infonie.fr)
+// - Michal Novotny (michal@etc.cz)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "UICRenderLoadedTextureFreeImageCompat.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+static const BYTE RLE_COMMAND = 0;
+static const BYTE RLE_ENDOFLINE = 0;
+static const BYTE RLE_ENDOFBITMAP = 1;
+static const BYTE RLE_DELTA = 2;
+
+#ifndef __MINGW32__ // prevents a bug in mingw32
+
+static const BYTE BI_RGB = 0;
+static const BYTE BI_RLE8 = 1;
+static const BYTE BI_RLE4 = 2;
+static const BYTE BI_BITFIELDS = 3;
+
+#endif // __MINGW32__
+
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+#ifndef __MINGW32__
+typedef struct tagBITMAPCOREHEADER
+{
+ DWORD bcSize;
+ WORD bcWidth;
+ WORD bcHeight;
+ WORD bcPlanes;
+ WORD bcBitCnt;
+} BITMAPCOREHEADER, *PBITMAPCOREHEADER;
+#endif //__MINGW32__
+
+typedef struct tagBITMAPINFOOS2_1X_HEADER
+{
+ DWORD biSize;
+ WORD biWidth;
+ WORD biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+} BITMAPINFOOS2_1X_HEADER, *PBITMAPINFOOS2_1X_HEADER;
+
+#ifndef __MINGW32__
+typedef struct tagBITMAPFILEHEADER
+{
+ WORD bfType;
+ DWORD bfSize;
+ WORD bfReserved1;
+ WORD bfReserved2;
+ DWORD bfOffBits;
+} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
+#endif //__MINGW32__
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+#ifdef FREEIMAGE_BIGENDIAN
+static void SwapInfoHeader(BITMAPINFOHEADER *header)
+{
+ SwapLong(&header->biSize);
+ SwapLong((DWORD *)&header->biWidth);
+ SwapLong((DWORD *)&header->biHeight);
+ SwapShort(&header->biPlanes);
+ SwapShort(&header->biBitCount);
+ SwapLong(&header->biCompression);
+ SwapLong(&header->biSizeImage);
+ SwapLong((DWORD *)&header->biXPelsPerMeter);
+ SwapLong((DWORD *)&header->biYPelsPerMeter);
+ SwapLong(&header->biClrUsed);
+ SwapLong(&header->biClrImportant);
+}
+
+static void SwapCoreHeader(BITMAPCOREHEADER *header)
+{
+ SwapLong(&header->bcSize);
+ SwapShort(&header->bcWidth);
+ SwapShort(&header->bcHeight);
+ SwapShort(&header->bcPlanes);
+ SwapShort(&header->bcBitCnt);
+}
+
+static void SwapOS21XHeader(BITMAPINFOOS2_1X_HEADER *header)
+{
+ SwapLong(&header->biSize);
+ SwapShort(&header->biWidth);
+ SwapShort(&header->biHeight);
+ SwapShort(&header->biPlanes);
+ SwapShort(&header->biBitCount);
+}
+
+static void SwapFileHeader(BITMAPFILEHEADER *header)
+{
+ SwapShort(&header->bfType);
+ SwapLong(&header->bfSize);
+ SwapShort(&header->bfReserved1);
+ SwapShort(&header->bfReserved2);
+ SwapLong(&header->bfOffBits);
+}
+#endif
+
+// --------------------------------------------------------------------------
+
+/**
+Load uncompressed image pixels for 1-, 4-, 8-, 16-, 24- and 32-bit dib
+@param io FreeImage IO
+@param handle FreeImage IO handle
+@param dib Image to be loaded
+@param height Image height
+@param pitch Image pitch
+@param bit_count Image bit-depth (1-, 4-, 8-, 16-, 24- or 32-bit)
+*/
+static void LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, int pitch,
+ int bit_count)
+{
+ (void)bit_count;
+ // Load pixel data
+ // NB: height can be < 0 for BMP data
+ if (height > 0) {
+ io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle);
+ } else {
+ int positiveHeight = abs(height);
+ for (int c = 0; c < positiveHeight; ++c) {
+ io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1,
+ handle);
+ }
+ }
+
+// swap as needed
+#ifdef FREEIMAGE_BIGENDIAN
+ if (bit_count == 16) {
+ for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ SwapShort(pixel);
+ pixel++;
+ }
+ }
+ }
+#endif
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ if (bit_count == 24 || bit_count == 32) {
+ for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ BYTE *pixel = FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ INPLACESWAP(pixel[0], pixel[2]);
+ pixel += (bit_count >> 3);
+ }
+ }
+ }
+#endif
+}
+
+/**
+Load image pixels for 4-bit RLE compressed dib
+@param io FreeImage IO
+@param handle FreeImage IO handle
+@param width Image width
+@param height Image height
+@param dib Image to be loaded
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL LoadPixelDataRLE4(FreeImageIO *io, fi_handle handle, int width, int height,
+ FIBITMAP *dib)
+{
+ int status_byte = 0;
+ BYTE second_byte = 0;
+ int bits = 0;
+
+ BYTE *pixels = NULL; // temporary 8-bit buffer
+
+ try {
+ height = abs(height);
+
+ pixels = (BYTE *)malloc(width * height * sizeof(BYTE));
+ if (!pixels)
+ throw(1);
+ memset(pixels, 0, width * height * sizeof(BYTE));
+
+ BYTE *q = pixels;
+ BYTE *end = pixels + height * width;
+
+ for (int scanline = 0; scanline < height;) {
+ if (q < pixels || q >= end) {
+ break;
+ }
+ if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ if (status_byte != 0) {
+ status_byte = (int)MIN((size_t)status_byte, (size_t)(end - q));
+ // Encoded mode
+ if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ for (int i = 0; i < status_byte; i++) {
+ *q++ = (BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
+ }
+ bits += status_byte;
+ } else {
+ // Escape mode
+ if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ switch (status_byte) {
+ case RLE_ENDOFLINE: {
+ // End of line
+ bits = 0;
+ scanline++;
+ q = pixels + scanline * width;
+ } break;
+
+ case RLE_ENDOFBITMAP:
+ // End of bitmap
+ q = end;
+ break;
+
+ case RLE_DELTA: {
+ // read the delta values
+
+ BYTE delta_x = 0;
+ BYTE delta_y = 0;
+
+ if (io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ if (io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+
+ // apply them
+
+ bits += delta_x;
+ scanline += delta_y;
+ q = pixels + scanline * width + bits;
+ } break;
+
+ default: {
+ // Absolute mode
+ status_byte = (int)MIN((size_t)status_byte, (size_t)(end - q));
+ for (int i = 0; i < status_byte; i++) {
+ if ((i & 0x01) == 0) {
+ if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ }
+ *q++ =
+ (BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
+ }
+ bits += status_byte;
+ // Read pad byte
+ if (((status_byte & 0x03) == 1) || ((status_byte & 0x03) == 2)) {
+ BYTE padding = 0;
+ if (io->read_proc(&padding, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ }
+ } break;
+ }
+ }
+ }
+
+ {
+ // Convert to 4-bit
+ for (int y = 0; y < height; y++) {
+ const BYTE *src = (BYTE *)pixels + y * width;
+ BYTE *dst = FreeImage_GetScanLine(dib, y);
+
+ BOOL hinibble = TRUE;
+
+ for (int cols = 0; cols < width; cols++) {
+ if (hinibble) {
+ dst[cols >> 1] = (src[cols] << 4);
+ } else {
+ dst[cols >> 1] |= src[cols];
+ }
+
+ hinibble = !hinibble;
+ }
+ }
+ }
+
+ free(pixels);
+
+ return TRUE;
+
+ } catch (int) {
+ if (pixels)
+ free(pixels);
+ return FALSE;
+ }
+}
+
+/**
+Load image pixels for 8-bit RLE compressed dib
+@param io FreeImage IO
+@param handle FreeImage IO handle
+@param width Image width
+@param height Image height
+@param dib Image to be loaded
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL LoadPixelDataRLE8(FreeImageIO *io, fi_handle handle, int width, int height,
+ FIBITMAP *dib)
+{
+ BYTE status_byte = 0;
+ BYTE second_byte = 0;
+ int scanline = 0;
+ int bits = 0;
+
+ for (;;) {
+ if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ switch (status_byte) {
+ case RLE_COMMAND:
+ if (io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ switch (status_byte) {
+ case RLE_ENDOFLINE:
+ bits = 0;
+ scanline++;
+ break;
+
+ case RLE_ENDOFBITMAP:
+ return TRUE;
+
+ case RLE_DELTA: {
+ // read the delta values
+
+ BYTE delta_x = 0;
+ BYTE delta_y = 0;
+
+ if (io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ if (io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ // apply them
+
+ bits += delta_x;
+ scanline += delta_y;
+
+ break;
+ }
+
+ default: {
+ if (scanline >= abs(height)) {
+ return TRUE;
+ }
+
+ int count = MIN((int)status_byte, width - bits);
+
+ BYTE *sline = FreeImage_GetScanLine(dib, scanline);
+
+ if (io->read_proc((void *)(sline + bits), sizeof(BYTE) * count, 1, handle) != 1) {
+ return FALSE;
+ }
+
+ // align run length to even number of bytes
+
+ if ((status_byte & 1) == 1) {
+ if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ }
+
+ bits += status_byte;
+
+ break;
+ }
+ }
+
+ break;
+
+ default: {
+ if (scanline >= abs(height)) {
+ return TRUE;
+ }
+
+ int count = MIN((int)status_byte, width - bits);
+
+ BYTE *sline = FreeImage_GetScanLine(dib, scanline);
+
+ if (io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ for (int i = 0; i < count; i++) {
+ *(sline + bits) = second_byte;
+
+ bits++;
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP *LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags,
+ unsigned bitmap_bits_offset)
+{
+ FIBITMAP *dib = NULL;
+ (void)flags;
+ try {
+ // load the info header
+
+ BITMAPINFOHEADER bih;
+
+ io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(&bih);
+#endif
+
+ // keep some general information about the bitmap
+
+ int used_colors = bih.biClrUsed;
+ int width = bih.biWidth;
+ int height = bih.biHeight; // WARNING: height can be < 0 => check each call using 'height'
+ // as a parameter
+ int alloc_height = abs(height);
+ int bit_count = bih.biBitCount;
+ int compression = bih.biCompression;
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+
+ switch (bit_count) {
+ case 1:
+ case 4:
+ case 8: {
+ if ((used_colors <= 0) || (used_colors > CalculateUsedPaletteEntries(bit_count)))
+ used_colors = CalculateUsedPaletteEntries(bit_count);
+
+ // allocate enough memory to hold the bitmap (header, palette, pixels) and read the
+ // palette
+
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, io);
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // load the palette
+
+ io->read_proc(FreeImage_GetPalette(dib), used_colors * sizeof(RGBQUAD), 1, handle);
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ for (int i = 0; i < used_colors; i++) {
+ INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue);
+ }
+#endif
+
+ // seek to the actual pixel data.
+ // this is needed because sometimes the palette is larger than the entries it contains
+ // predicts
+
+ if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ + (used_colors * sizeof(RGBQUAD))))
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read the pixel data
+
+ switch (compression) {
+ case BI_RGB:
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+ return dib;
+
+ case BI_RLE4:
+ if (LoadPixelDataRLE4(io, handle, width, height, dib)) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE4 BMP data";
+ }
+ break;
+
+ case BI_RLE8:
+ if (LoadPixelDataRLE8(io, handle, width, height, dib)) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE8 BMP data";
+ }
+ break;
+
+ default:
+ throw "compression type not supported";
+ }
+ } break; // 1-, 4-, 8-bit
+
+ case 16: {
+ if (bih.biCompression == BI_BITFIELDS) {
+ DWORD bitfields[3];
+
+ io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);
+
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, bitfields[0], bitfields[1],
+ bitfields[2], io);
+ } else {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI16_555_RED_MASK,
+ FI16_555_GREEN_MASK, FI16_555_BLUE_MASK, io);
+ }
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ } break; // 16-bit
+
+ case 24:
+ case 32: {
+ if (bih.biCompression == BI_BITFIELDS) {
+ DWORD bitfields[3];
+
+ io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);
+
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, bitfields[0], bitfields[1],
+ bitfields[2], io);
+ } else {
+ if (bit_count == 32) {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, io);
+ } else {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, io);
+ }
+ }
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ if (used_colors > 0) {
+ io->seek_proc(handle, used_colors * sizeof(RGBQUAD), SEEK_CUR);
+ } else if ((bih.biCompression != BI_BITFIELDS)
+ && (bitmap_bits_offset
+ > sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))) {
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+ }
+
+ // read in the bitmap bits
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ // check if the bitmap contains transparency, if so enable it in the header
+
+ return dib;
+ } break; // 24-, 32-bit
+ }
+ } catch (const char *message) {
+ if (dib) {
+ FreeImage_Unload(dib);
+ }
+ if (message) {
+ FreeImage_OutputMessageProc(s_format_id, message, io);
+ }
+ }
+
+ return NULL;
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP *LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags,
+ unsigned bitmap_bits_offset)
+{
+ FIBITMAP *dib = NULL;
+ (void)flags;
+ try {
+ // load the info header
+
+ BITMAPINFOHEADER bih;
+
+ io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(&bih);
+#endif
+
+ // keep some general information about the bitmap
+
+ int used_colors = bih.biClrUsed;
+ int width = bih.biWidth;
+ int height = bih.biHeight; // WARNING: height can be < 0 => check each read_proc using
+ // 'height' as a parameter
+ int alloc_height = abs(height);
+ int bit_count = bih.biBitCount;
+ int compression = bih.biCompression;
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+
+ switch (bit_count) {
+ case 1:
+ case 4:
+ case 8: {
+ if ((used_colors <= 0) || (used_colors > CalculateUsedPaletteEntries(bit_count)))
+ used_colors = CalculateUsedPaletteEntries(bit_count);
+
+ // allocate enough memory to hold the bitmap (header, palette, pixels) and read the
+ // palette
+
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, io);
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // load the palette
+
+ io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET);
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ for (int count = 0; count < used_colors; count++) {
+ FILE_BGR bgr;
+
+ io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle);
+
+ pal[count].rgbRed = bgr.r;
+ pal[count].rgbGreen = bgr.g;
+ pal[count].rgbBlue = bgr.b;
+ }
+
+ // seek to the actual pixel data.
+ // this is needed because sometimes the palette is larger than the entries it contains
+ // predicts
+
+ if (bitmap_bits_offset
+ > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read the pixel data
+
+ switch (compression) {
+ case BI_RGB:
+ // load pixel data
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+ return dib;
+
+ case BI_RLE4:
+ if (LoadPixelDataRLE4(io, handle, width, height, dib)) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE4 BMP data";
+ }
+ break;
+
+ case BI_RLE8:
+ if (LoadPixelDataRLE8(io, handle, width, height, dib)) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE8 BMP data";
+ }
+ break;
+
+ default:
+ throw "compression type not supported";
+ }
+ }
+
+ case 16: {
+ if (bih.biCompression == 3) {
+ DWORD bitfields[3];
+
+ io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);
+
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, bitfields[0], bitfields[1],
+ bitfields[2], io);
+ } else {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI16_555_RED_MASK,
+ FI16_555_GREEN_MASK, FI16_555_BLUE_MASK, io);
+ }
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ if (bitmap_bits_offset
+ > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) {
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+ }
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+
+ case 24:
+ case 32: {
+ if (bit_count == 32) {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, io);
+ } else {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, io);
+ }
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ if (bitmap_bits_offset
+ > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read in the bitmap bits
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+ }
+ } catch (const char *message) {
+ if (dib)
+ FreeImage_Unload(dib);
+
+ FreeImage_OutputMessageProc(s_format_id, message, io);
+ }
+
+ return NULL;
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP *LoadOS21XBMP(FreeImageIO *io, fi_handle handle, int flags,
+ unsigned bitmap_bits_offset)
+{
+ FIBITMAP *dib = NULL;
+ (void)flags;
+ try {
+ BITMAPINFOOS2_1X_HEADER bios2_1x;
+
+ io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapOS21XHeader(&bios2_1x);
+#endif
+ // keep some general information about the bitmap
+
+ int used_colors = 0;
+ int width = bios2_1x.biWidth;
+ int height = bios2_1x.biHeight; // WARNING: height can be < 0 => check each read_proc using
+ // 'height' as a parameter
+ int alloc_height = abs(height);
+ int bit_count = bios2_1x.biBitCount;
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+
+ switch (bit_count) {
+ case 1:
+ case 4:
+ case 8: {
+ used_colors = CalculateUsedPaletteEntries(bit_count);
+
+ // allocate enough memory to hold the bitmap (header, palette, pixels) and read the
+ // palette
+
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, io);
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information to default values (72 dpi in english units)
+ FreeImage_SetDotsPerMeterX(dib, 2835);
+ FreeImage_SetDotsPerMeterY(dib, 2835);
+
+ // load the palette
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ for (int count = 0; count < used_colors; count++) {
+ FILE_BGR bgr;
+
+ io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle);
+
+ pal[count].rgbRed = bgr.r;
+ pal[count].rgbGreen = bgr.g;
+ pal[count].rgbBlue = bgr.b;
+ }
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read the pixel data
+
+ // load pixel data
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+
+ case 16: {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI16_555_RED_MASK,
+ FI16_555_GREEN_MASK, FI16_555_BLUE_MASK, io);
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information to default values (72 dpi in english units)
+ FreeImage_SetDotsPerMeterX(dib, 2835);
+ FreeImage_SetDotsPerMeterY(dib, 2835);
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+
+ case 24:
+ case 32: {
+ if (bit_count == 32) {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, io);
+ } else {
+ dib = FreeImage_Allocate(width, alloc_height, bit_count, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, io);
+ }
+
+ if (dib == NULL)
+ throw "DIB allocation failed";
+
+ // set resolution information to default values (72 dpi in english units)
+ FreeImage_SetDotsPerMeterX(dib, 2835);
+ FreeImage_SetDotsPerMeterY(dib, 2835);
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ // check if the bitmap contains transparency, if so enable it in the header
+
+ return dib;
+ }
+ }
+ } catch (const char *message) {
+ if (dib)
+ FreeImage_Unload(dib);
+
+ FreeImage_OutputMessageProc(s_format_id, message, io);
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+// ----------------------------------------------------------
+
+static FIBITMAP *DoLoadBMP(FreeImageIO *io, fi_handle handle, int flags)
+{
+ if (handle != NULL) {
+ BITMAPFILEHEADER bitmapfileheader;
+ DWORD type = 0;
+ BYTE magic[2];
+
+ // we use this offset value to make seemingly absolute seeks relative in the file
+
+ long offset_in_file = io->tell_proc(handle);
+
+ // read the magic
+
+ io->read_proc(&magic, sizeof(magic), 1, handle);
+
+ // compare the magic with the number we know
+
+ // somebody put a comment here explaining the purpose of this loop
+ while (memcmp(&magic, "BA", 2) == 0) {
+ io->read_proc(&bitmapfileheader.bfSize, sizeof(DWORD), 1, handle);
+ io->read_proc(&bitmapfileheader.bfReserved1, sizeof(WORD), 1, handle);
+ io->read_proc(&bitmapfileheader.bfReserved2, sizeof(WORD), 1, handle);
+ io->read_proc(&bitmapfileheader.bfOffBits, sizeof(DWORD), 1, handle);
+ io->read_proc(&magic, sizeof(magic), 1, handle);
+ }
+
+ // read the fileheader
+
+ io->seek_proc(handle, (0 - (int)sizeof(magic)), SEEK_CUR);
+ io->read_proc(&bitmapfileheader, (int)sizeof(BITMAPFILEHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapFileHeader(&bitmapfileheader);
+#endif
+
+ // read the first byte of the infoheader
+
+ io->read_proc(&type, sizeof(DWORD), 1, handle);
+ io->seek_proc(handle, 0 - (int)sizeof(DWORD), SEEK_CUR);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapLong(&type);
+#endif
+
+ // call the appropriate load function for the found bitmap type
+
+ if (type == 40)
+ return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits);
+
+ if (type == 12)
+ return LoadOS21XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits);
+
+ if (type <= 64)
+ return LoadOS22XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits);
+
+ char buf[256];
+ sprintf(buf, "unknown bmp subtype with id %d", type);
+ FreeImage_OutputMessageProc(s_format_id, buf, io);
+ }
+
+ return NULL;
+}
+
+template <QT3DSU32 TBitWidth>
+struct SPaletteIndexer
+{
+ static inline uint32_t IndexOf(const uint8_t *inData, uint32_t inPos)
+ {
+ uint32_t divisor = 8 / TBitWidth;
+ uint32_t byte = inPos / divisor;
+ uint32_t modulus = inPos % divisor;
+ uint32_t shift = TBitWidth * modulus;
+ uint32_t mask = (1 << TBitWidth) - 1;
+ mask = mask << shift;
+ uint32_t byteData = inData[byte];
+ return (byteData & mask) >> shift;
+ }
+};
+
+template <>
+struct SPaletteIndexer<1>
+{
+ static inline uint32_t IndexOf(const uint8_t *inData, uint32_t inPos)
+ {
+ uint32_t byte = (inPos / 8);
+ uint32_t bit = 1 << (7 - (inPos % 8));
+ uint32_t byteData = inData[byte];
+ return (byteData & bit) ? 1 : 0;
+ }
+};
+
+template <>
+struct SPaletteIndexer<8>
+{
+ static inline uint32_t IndexOf(const uint8_t *inData, uint32_t inPos)
+ {
+ uint32_t byte = inPos;
+ uint32_t bit = 0xFF;
+ uint32_t byteData = inData[byte];
+ return byteData & bit;
+ }
+};
+
+static inline void assignQuad(uint8_t *dest, const RGBQUAD &quad)
+{
+ dest[0] = quad.rgbRed;
+ dest[1] = quad.rgbGreen;
+ dest[2] = quad.rgbBlue;
+}
+
+template <QT3DSU32 bitCount>
+inline void LoadPalettized(bool inFlipY, const RGBQUAD *palette, void *data, uint8_t *newData,
+ int width, int height, int components, int transparentIndex)
+{
+ const uint8_t *oldData = (const uint8_t *)data;
+ int pitch = CalculatePitch(CalculateLine(width, bitCount));
+ for (uint32_t h = 0; h < (uint32_t)height; ++h) {
+ uint32_t relHeight = h;
+ if (inFlipY)
+ relHeight = ((uint32_t)height) - h - 1;
+ for (uint32_t w = 0; w < (uint32_t)width; ++w) {
+ const uint8_t *dataLine = oldData + pitch * h;
+ uint32_t pos = width * relHeight + w;
+ uint32_t paletteIndex = SPaletteIndexer<bitCount>::IndexOf(dataLine, w);
+ const RGBQUAD &theQuad = palette[paletteIndex];
+ uint8_t *writePtr = newData + (pos * components);
+ assignQuad(writePtr, theQuad);
+ if (paletteIndex == (uint32_t)transparentIndex && components == 4) {
+ writePtr[3] = 0;
+ }
+ }
+ }
+}
+
+inline int firstHighBit(int data)
+{
+ if (data == 0)
+ return 0;
+ int idx = 0;
+ while ((data % 2) == 0) {
+ data = data >> 1;
+ ++idx;
+ }
+ return idx;
+}
+
+struct SMaskData
+{
+ uint32_t mask;
+ uint32_t shift;
+ uint32_t max;
+
+ SMaskData(int inMask)
+ {
+ mask = inMask;
+ shift = firstHighBit(mask);
+ max = mask >> shift;
+ }
+
+ inline uint8_t MapColor(uint32_t color) const
+ {
+ uint32_t intermediateValue = (color & mask) >> shift;
+ return (uint8_t)((intermediateValue * 255) / max);
+ }
+};
+
+template <QT3DSU32>
+struct ColorAccess
+{
+};
+
+template <>
+struct ColorAccess<16>
+{
+ static uint32_t GetPixelWidth() { return 2; }
+ static uint32_t GetColor(const char8_t *src)
+ {
+ return (uint32_t) * reinterpret_cast<const QT3DSU16 *>(src);
+ }
+};
+
+template <>
+struct ColorAccess<24>
+{
+ static uint32_t GetPixelWidth() { return 3; }
+ static uint32_t GetColor(const char8_t *src)
+ {
+ return (uint32_t)(*reinterpret_cast<const QT3DSU32 *>(src) & 0xFFFFFF);
+ }
+};
+
+template <>
+struct ColorAccess<32>
+{
+ static uint32_t GetPixelWidth() { return 4; }
+ static uint32_t GetColor(const char8_t *src)
+ {
+ return *reinterpret_cast<const uint32_t *>(src);
+ }
+};
+
+template <QT3DSU32 TBitCount>
+inline void LoadMasked(bool inFlipY, QT3DSI32 *inMasks, void *data, uint8_t *newData, int width,
+ int height)
+{
+ const char8_t *oldData = (const char8_t *)data;
+ SMaskData rMask(inMasks[0]);
+ SMaskData gMask(inMasks[1]);
+ SMaskData bMask(inMasks[2]);
+ for (int h = 0; h < height; ++h) {
+ int relHeight = h;
+ if (inFlipY)
+ relHeight = height - h - 1;
+ for (int w = 0; w < width; ++w) {
+ int pos = width * relHeight + w;
+ const char8_t *readPtr = oldData + (pos * ColorAccess<TBitCount>::GetPixelWidth());
+ uint8_t *writePtr = newData + (pos * 3);
+ uint32_t colorVal = ColorAccess<TBitCount>::GetColor(readPtr);
+ writePtr[0] = rMask.MapColor(colorVal);
+ writePtr[1] = gMask.MapColor(colorVal);
+ writePtr[2] = bMask.MapColor(colorVal);
+ }
+ }
+}
+
+void SLoadedTexture::FreeImagePostProcess(bool inFlipY)
+{
+ // We always convert 32 bit RGBA
+ if (m_ExtendedFormat != ExtendedTextureFormats::NoExtendedFormat) {
+
+ QT3DSU32 stride = 3 * width;
+ format = NVRenderTextureFormats::RGB8;
+ components = 3;
+ if (m_ExtendedFormat == ExtendedTextureFormats::Palettized && m_TransparentPaletteIndex > -1
+ && m_TransparentPaletteIndex < 256) {
+ stride = 4 * width;
+ components = 4;
+ format = NVRenderTextureFormats::RGBA8;
+ }
+ QT3DSU32 byteSize = height * stride;
+ uint8_t *newData =
+ (uint8_t *)m_Allocator.allocate(byteSize, "texture data", __FILE__, __LINE__);
+ if (format == NVRenderTextureFormats::RGBA8)
+ memSet(newData, 255, byteSize);
+ switch (m_ExtendedFormat) {
+ case ExtendedTextureFormats::Palettized: {
+ RGBQUAD *palette = (RGBQUAD *)m_Palette;
+ switch (m_BitCount) {
+ case 1:
+ LoadPalettized<1>(inFlipY, palette, data, newData, width, height, components,
+ m_TransparentPaletteIndex);
+ break;
+ case 2:
+ LoadPalettized<2>(inFlipY, palette, data, newData, width, height, components,
+ m_TransparentPaletteIndex);
+ break;
+ case 4:
+ LoadPalettized<4>(inFlipY, palette, data, newData, width, height, components,
+ m_TransparentPaletteIndex);
+ break;
+ case 8:
+ LoadPalettized<8>(inFlipY, palette, data, newData, width, height, components,
+ m_TransparentPaletteIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ memSet(newData, 0, byteSize);
+ break;
+ }
+ } break;
+ case ExtendedTextureFormats::CustomRGB: {
+ switch (m_BitCount) {
+ case 16:
+ LoadMasked<16>(inFlipY, m_CustomMasks, data, newData, width, height);
+ break;
+ case 24:
+ LoadMasked<24>(inFlipY, m_CustomMasks, data, newData, width, height);
+ break;
+ case 32:
+ LoadMasked<32>(inFlipY, m_CustomMasks, data, newData, width, height);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ memSet(newData, 0, byteSize);
+ break;
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ memSet(newData, 0, byteSize);
+ break;
+ }
+ m_Allocator.deallocate(data);
+ if (m_Palette)
+ m_Allocator.deallocate(m_Palette);
+ data = newData;
+ m_Palette = NULL;
+ m_BitCount = 0;
+ this->dataSizeInBytes = byteSize;
+ m_ExtendedFormat = ExtendedTextureFormats::NoExtendedFormat;
+ }
+}
+
+SLoadedTexture *SLoadedTexture::LoadBMP(ISeekableIOStream &inStream, bool inFlipY,
+ NVFoundationBase &inFnd)
+{
+ FreeImageIO theIO(inFnd.getAllocator(), inFnd);
+ SLoadedTexture *retval = DoLoadBMP(&theIO, &inStream, 0);
+ if (retval)
+ retval->FreeImagePostProcess(inFlipY);
+ return retval;
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.cpp
new file mode 100644
index 00000000..c494a688
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.cpp
@@ -0,0 +1,693 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderLoadedTextureDDS.h"
+#include "UICRenderLoadedTextureFreeImageCompat.h"
+
+using namespace uic::render;
+
+namespace uic {
+namespace render {
+
+ static int s_exception_string;
+
+ //================================================================================
+ // DXT data-layout structure definitions.
+ typedef struct
+ {
+ QT3DSU16 col0; // 16-bit 565 interpolant endpoints
+ QT3DSU16 col1;
+ QT3DSU8 row[4]; // 4x4 * 2bpp color-index == 4 bytes.
+ } DXTColBlock;
+
+ typedef struct
+ {
+ QT3DSU16 row[4]; // 4x4 * 4bpp alpha == 8 bytes. (pure 4-bit alpha values)
+ } DXT3AlphaBlock;
+
+ typedef struct
+ {
+ QT3DSU8 alpha0; // 8-bit alpha interpolant endpoints
+ QT3DSU8 alpha1;
+ QT3DSU8 row[6]; // 4x4 * 3bpp alpha-index == 48bits == 6 bytes.
+ } DXT5AlphaBlock;
+
+ typedef struct
+ {
+ QT3DSU8 red;
+ QT3DSU8 green;
+ QT3DSU8 blue;
+ QT3DSU8 alpha;
+ } Color8888;
+
+//================================================================================
+// Various DDS file defines
+
+#define DDSD_CAPS 0x00000001l
+#define DDSD_HEIGHT 0x00000002l
+#define DDSD_WIDTH 0x00000004l
+#define DDSD_PIXELFORMAT 0x00001000l
+#define DDS_ALPHAPIXELS 0x00000001l
+#define DDS_FOURCC 0x00000004l
+#define DDS_PITCH 0x00000008l
+#define DDS_COMPLEX 0x00000008l
+#define DDS_RGB 0x00000040l
+#define DDS_TEXTURE 0x00001000l
+#define DDS_MIPMAPCOUNT 0x00020000l
+#define DDS_LINEARSIZE 0x00080000l
+#define DDS_VOLUME 0x00200000l
+#define DDS_MIPMAP 0x00400000l
+#define DDS_DEPTH 0x00800000l
+
+#define DDS_CUBEMAP 0x00000200L
+#define DDS_CUBEMAP_POSITIVEX 0x00000400L
+#define DDS_CUBEMAP_NEGATIVEX 0x00000800L
+#define DDS_CUBEMAP_POSITIVEY 0x00001000L
+#define DDS_CUBEMAP_NEGATIVEY 0x00002000L
+#define DDS_CUBEMAP_POSITIVEZ 0x00004000L
+#define DDS_CUBEMAP_NEGATIVEZ 0x00008000L
+
+#define FOURCC_DXT1 0x31545844 //(MAKEFOURCC('D','X','T','1'))
+#define FOURCC_DXT3 0x33545844 //(MAKEFOURCC('D','X','T','3'))
+#define FOURCC_DXT5 0x35545844 //(MAKEFOURCC('D','X','T','5'))
+
+#define DDS_MAGIC_FLIPPED 0x0F7166ED
+
+ //================================================================================
+ // DDS file format structures.
+ typedef struct _DDS_PIXELFORMAT
+ {
+ QT3DSU32 dwSize;
+ QT3DSU32 dwFlags;
+ QT3DSU32 dwFourCC;
+ QT3DSU32 dwRGBBitCount;
+ QT3DSU32 dwRBitMask;
+ QT3DSU32 dwGBitMask;
+ QT3DSU32 dwBBitMask;
+ QT3DSU32 dwABitMask;
+ } DDS_PIXELFORMAT;
+
+ typedef struct _DDS_HEADER
+ {
+ QT3DSU32 dwSize;
+ QT3DSU32 dwFlags;
+ QT3DSU32 dwHeight;
+ QT3DSU32 dwWidth;
+ QT3DSU32 dwPitchOrLinearSize;
+ QT3DSU32 dwDepth;
+ QT3DSU32 dwMipMapCount;
+ QT3DSU32 dwReserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ QT3DSU32 dwCaps1;
+ QT3DSU32 dwCaps2;
+ QT3DSU32 dwReserved2[3];
+ } DDS_HEADER;
+
+ //================================================================================
+ // helper functions
+ //================================================================================
+
+ // helper macros.
+ static inline void NvSwapChar(QT3DSU8 &a, QT3DSU8 &b)
+ {
+ QT3DSU8 tmp;
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ static inline void NvSwapShort(QT3DSU16 &a, QT3DSU16 &b)
+ {
+ QT3DSU16 tmp;
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ //================================================================================
+ //================================================================================
+ static void flip_blocks_dxtc1(DXTColBlock *line, QT3DSI32 numBlocks)
+ {
+ DXTColBlock *curblock = line;
+ QT3DSI32 i;
+
+ for (i = 0; i < numBlocks; i++) {
+ NvSwapChar(curblock->row[0], curblock->row[3]);
+ NvSwapChar(curblock->row[1], curblock->row[2]);
+ curblock++;
+ }
+ }
+
+ //================================================================================
+ //================================================================================
+ static void flip_blocks_dxtc3(DXTColBlock *line, QT3DSI32 numBlocks)
+ {
+ DXTColBlock *curblock = line;
+ DXT3AlphaBlock *alphablock;
+ QT3DSI32 i;
+
+ for (i = 0; i < numBlocks; i++) {
+ alphablock = (DXT3AlphaBlock *)curblock;
+
+ NvSwapShort(alphablock->row[0], alphablock->row[3]);
+ NvSwapShort(alphablock->row[1], alphablock->row[2]);
+ curblock++;
+
+ NvSwapChar(curblock->row[0], curblock->row[3]);
+ NvSwapChar(curblock->row[1], curblock->row[2]);
+ curblock++;
+ }
+ }
+
+ static void flip_dxt5_alpha(DXT5AlphaBlock *block)
+ {
+ QT3DSI8 gBits[4][4];
+
+ const QT3DSU32 mask = 0x00000007; // bits = 00 00 01 11
+ QT3DSU32 bits = 0;
+ memcpy(&bits, &block->row[0], sizeof(QT3DSI8) * 3);
+
+ gBits[0][0] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[0][1] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[0][2] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[0][3] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[1][0] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[1][1] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[1][2] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[1][3] = (QT3DSI8)(bits & mask);
+
+ bits = 0;
+ memcpy(&bits, &block->row[3], sizeof(QT3DSI8) * 3);
+
+ gBits[2][0] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[2][1] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[2][2] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[2][3] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[3][0] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[3][1] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[3][2] = (QT3DSI8)(bits & mask);
+ bits >>= 3;
+ gBits[3][3] = (QT3DSI8)(bits & mask);
+
+ bits = (gBits[3][0] << 0) | (gBits[3][1] << 3) | (gBits[3][2] << 6) | (gBits[3][3] << 9)
+ | (gBits[2][0] << 12) | (gBits[2][1] << 15) | (gBits[2][2] << 18) | (gBits[2][3] << 21);
+ memcpy(&block->row[0], &bits, 3);
+
+ bits = (gBits[1][0] << 0) | (gBits[1][1] << 3) | (gBits[1][2] << 6) | (gBits[1][3] << 9)
+ | (gBits[0][0] << 12) | (gBits[0][1] << 15) | (gBits[0][2] << 18) | (gBits[0][3] << 21);
+ memcpy(&block->row[3], &bits, 3);
+ }
+
+ static void flip_blocks_dxtc5(DXTColBlock *line, QT3DSI32 numBlocks)
+ {
+ DXTColBlock *curblock = line;
+ DXT5AlphaBlock *alphablock;
+ QT3DSI32 i;
+
+ for (i = 0; i < numBlocks; i++) {
+ alphablock = (DXT5AlphaBlock *)curblock;
+
+ flip_dxt5_alpha(alphablock);
+ curblock++;
+
+ NvSwapChar(curblock->row[0], curblock->row[3]);
+ NvSwapChar(curblock->row[1], curblock->row[2]);
+ curblock++;
+ }
+ }
+
+ static void flip_data_vertical(FreeImageIO *io, QT3DSI8 *image, QT3DSI32 width, QT3DSI32 height,
+ UICDDSImage *info)
+ {
+ if (info->compressed) {
+ QT3DSI32 linesize, j;
+ DXTColBlock *top;
+ DXTColBlock *bottom;
+ QT3DSI8 *tmp;
+ void (*flipblocks)(DXTColBlock *, QT3DSI32) = NULL;
+ QT3DSI32 xblocks = width / 4;
+ QT3DSI32 yblocks = height / 4;
+ QT3DSI32 blocksize;
+
+ switch (info->format) {
+ case qt3ds::render::NVRenderTextureFormats::RGBA_DXT1:
+ blocksize = 8;
+ flipblocks = &flip_blocks_dxtc1;
+ break;
+ case qt3ds::render::NVRenderTextureFormats::RGBA_DXT3:
+ blocksize = 16;
+ flipblocks = &flip_blocks_dxtc3;
+ break;
+ case qt3ds::render::NVRenderTextureFormats::RGBA_DXT5:
+ blocksize = 16;
+ flipblocks = &flip_blocks_dxtc5;
+ break;
+ default:
+ return;
+ }
+
+ linesize = xblocks * blocksize;
+ tmp = (QT3DSI8 *)QT3DS_ALLOC(io->m_Allocator, linesize, "flip_data_vertical compressed");
+
+ for (j = 0; j < (yblocks >> 1); j++) {
+ top = (DXTColBlock *)(void *)(image + j * linesize);
+ bottom = (DXTColBlock *)(void *)(image + (((yblocks - j) - 1) * linesize));
+
+ (*flipblocks)(top, xblocks);
+ (*flipblocks)(bottom, xblocks);
+
+ memcpy(tmp, bottom, linesize);
+ memcpy(bottom, top, linesize);
+ memcpy(top, tmp, linesize);
+ }
+
+ // Catch the middle row of blocks if there is one
+ // The loop above will skip the middle row
+ if (yblocks & 0x01) {
+ DXTColBlock *middle = (DXTColBlock *)(void *)(image + (yblocks >> 1) * linesize);
+ (*flipblocks)(middle, xblocks);
+ }
+
+ QT3DS_FREE(io->m_Allocator, tmp);
+ } else {
+ QT3DSI32 linesize = width * info->bytesPerPixel;
+ QT3DSI32 j;
+ QT3DSI8 *top;
+ QT3DSI8 *bottom;
+ QT3DSI8 *tmp;
+
+ // much simpler - just compute the line length and swap each row
+ tmp = (QT3DSI8 *)QT3DS_ALLOC(io->m_Allocator, linesize, "flip_data_vertical");
+ ;
+
+ for (j = 0; j < (height >> 1); j++) {
+ top = (QT3DSI8 *)(image + j * linesize);
+ bottom = (QT3DSI8 *)(image + (((height - j) - 1) * linesize));
+
+ memcpy(tmp, bottom, linesize);
+ memcpy(bottom, top, linesize);
+ memcpy(top, tmp, linesize);
+ }
+
+ QT3DS_FREE(io->m_Allocator, tmp);
+ }
+ }
+
+ static QT3DSI32 size_image(QT3DSI32 width, QT3DSI32 height, const UICDDSImage *image)
+ {
+ if (image->compressed) {
+ return ((width + 3) / 4) * ((height + 3) / 4)
+ * (image->format == qt3ds::render::NVRenderTextureFormats::RGBA_DXT1 ? 8 : 16);
+ } else {
+ return width * height * image->bytesPerPixel;
+ }
+ }
+
+ static QT3DSI32 total_image_data_size(UICDDSImage *image)
+ {
+ QT3DSI32 i, j, index = 0, size = 0, w, h;
+ QT3DSI32 cubeCount = image->cubemap ? 6 : 1;
+
+ for (j = 0; j < cubeCount; j++) {
+ w = image->width;
+ h = image->height;
+
+ for (i = 0; i < image->numMipmaps; i++) // account for base plus each mip
+ {
+ image->size[index] = size_image(w, h, image);
+ image->mipwidth[index] = w;
+ image->mipheight[index] = h;
+ size += image->size[index];
+ if (w != 1) {
+ w >>= 1;
+ }
+ if (h != 1) {
+ h >>= 1;
+ }
+
+ index++;
+ }
+ }
+
+ return (size);
+ }
+
+ void *UICDDSAllocDataBlock(FreeImageIO *io, UICDDSImage *image)
+ {
+ if (image) {
+ QT3DSI32 i;
+ QT3DSI32 size = total_image_data_size(image);
+ image->dataBlock =
+ QT3DS_ALLOC(io->m_Allocator, size,
+ "UICDDSAllocDataBlock"); // no need to calloc, as we fill every bit...
+ if (image->dataBlock == NULL) {
+ return NULL;
+ }
+
+ image->data[0] = image->dataBlock;
+
+ QT3DSI32 planes = image->numMipmaps * (image->cubemap ? 6 : 1);
+
+ for (i = 1; i < planes; i++) // account for base plus each mip
+ {
+ image->data[i] =
+ (void *)(((size_t)(image->data[i - 1])) + (size_t)image->size[i - 1]);
+ }
+
+ return (image->dataBlock); // in case caller wants to sanity check...
+ }
+ return (NULL);
+ }
+
+ static FIBITMAP *DoLoadDDS(FreeImageIO *io, IInStream &inStream, QT3DSI32 flipVertical)
+ {
+ FIBITMAP *dib = NULL;
+ DDS_HEADER ddsh;
+ QT3DSI8 filecode[4];
+ UICDDSImage *image = NULL;
+ bool needsBGRASwap = false;
+ ;
+ bool isAllreadyFlipped = false;
+
+ try {
+ // check file code
+ inStream.Read(filecode, 4);
+ if (memcmp(filecode, "DDS ", 4)) {
+ throw "Invalid DDS file";
+ }
+
+ image = (UICDDSImage *)QT3DS_ALLOC(io->m_Allocator, sizeof(UICDDSImage), "DoLoadDDS");
+ if (image == NULL) {
+ throw "UICDDSImage allocation failed";
+ }
+ memset(image, 0, sizeof(UICDDSImage));
+
+ // read in DDS header
+ inStream.Read(&ddsh, 1);
+
+ // check if image is a cubempap
+ if (ddsh.dwCaps2 & DDS_CUBEMAP) {
+ const QT3DSI32 allFaces = DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_POSITIVEY
+ | DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEX | DDS_CUBEMAP_NEGATIVEY
+ | DDS_CUBEMAP_NEGATIVEZ;
+
+ if ((ddsh.dwCaps2 & allFaces) != allFaces) {
+ throw "Not all cubemap faces defined - not supported";
+ }
+
+ image->cubemap = 1;
+ } else {
+ image->cubemap = 0;
+ }
+
+ // check if image is a volume texture
+ if ((ddsh.dwCaps2 & DDS_VOLUME) && (ddsh.dwDepth > 0)) {
+ throw "Volume textures not supported";
+ }
+
+ // allocated the memory for the structure we return
+ dib = QT3DS_NEW(io->m_Allocator, SLoadedTexture)(io->m_Allocator);
+ if (dib == NULL) {
+ throw "DIB allocation failed";
+ }
+
+ // figure out what the image format is
+ if (ddsh.ddspf.dwFlags & DDS_FOURCC) {
+ switch (ddsh.ddspf.dwFourCC) {
+ case FOURCC_DXT1:
+ image->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT1;
+ image->components = 3;
+ image->compressed = 1;
+ image->alpha = 0; // Ugh - for backwards compatibility
+ dib->format = qt3ds::render::NVRenderTextureFormats::RGB_DXT1;
+ break;
+ case FOURCC_DXT3:
+ image->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT3;
+ image->components = 4;
+ image->compressed = 1;
+ image->alpha = 1;
+ dib->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT3;
+ break;
+ case FOURCC_DXT5:
+ image->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT5;
+ image->components = 4;
+ image->compressed = 1;
+ image->alpha = 1;
+ dib->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT5;
+ break;
+ default:
+ throw "Unsupported FOURCC code";
+ }
+ } else {
+ // Check for a supported pixel format
+ if ((ddsh.ddspf.dwRGBBitCount == 32) && (ddsh.ddspf.dwRBitMask == 0x000000FF)
+ && (ddsh.ddspf.dwGBitMask == 0x0000FF00)
+ && (ddsh.ddspf.dwBBitMask == 0x00FF0000)
+ && (ddsh.ddspf.dwABitMask == 0xFF000000)) {
+ // We support D3D's A8B8G8R8, which is actually RGBA in linear
+ // memory, equivalent to GL's RGBA
+ image->format = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ image->components = 4;
+ image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8;
+ image->bytesPerPixel = 4;
+ image->alpha = 1;
+ image->compressed = 0;
+ dib->format = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ } else if ((ddsh.ddspf.dwRGBBitCount == 32) && (ddsh.ddspf.dwRBitMask == 0x00FF0000)
+ && (ddsh.ddspf.dwGBitMask == 0x0000FF00)
+ && (ddsh.ddspf.dwBBitMask == 0x000000FF)
+ && (ddsh.ddspf.dwABitMask == 0xFF000000)) {
+ // We support D3D's A8R8G8B8, which is actually BGRA in linear
+ // memory, need to be
+ image->format = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ image->components = 4;
+ image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8;
+ image->bytesPerPixel = 4;
+ image->alpha = 1;
+ image->compressed = 0;
+ needsBGRASwap = true;
+ dib->format = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ } else if ((ddsh.ddspf.dwRGBBitCount == 16) && (ddsh.ddspf.dwRBitMask == 0x0000F800)
+ && (ddsh.ddspf.dwGBitMask == 0x000007E0)
+ && (ddsh.ddspf.dwBBitMask == 0x0000001F)
+ && (ddsh.ddspf.dwABitMask == 0x00000000)) {
+ // We support D3D's R5G6B5, which is actually RGB in linear
+ // memory. It is equivalent to GL's GL_UNSIGNED_SHORT_5_6_5
+ image->format = qt3ds::render::NVRenderTextureFormats::RGB8;
+ image->components = 3;
+ image->alpha = 0;
+ image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU16;
+ image->bytesPerPixel = 2;
+ image->compressed = 0;
+ dib->format = qt3ds::render::NVRenderTextureFormats::RGB8;
+ } else if ((ddsh.ddspf.dwRGBBitCount == 8) && (ddsh.ddspf.dwRBitMask == 0x00000000)
+ && (ddsh.ddspf.dwGBitMask == 0x00000000)
+ && (ddsh.ddspf.dwBBitMask == 0x00000000)
+ && (ddsh.ddspf.dwABitMask == 0x000000FF)) {
+ // We support D3D's A8
+ image->format = qt3ds::render::NVRenderTextureFormats::Alpha8;
+ image->components = 1;
+ image->alpha = 1;
+ image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8;
+ image->bytesPerPixel = 1;
+ image->compressed = 0;
+ dib->format = qt3ds::render::NVRenderTextureFormats::Alpha8;
+ } else if ((ddsh.ddspf.dwRGBBitCount == 8) && (ddsh.ddspf.dwRBitMask == 0x000000FF)
+ && (ddsh.ddspf.dwGBitMask == 0x00000000)
+ && (ddsh.ddspf.dwBBitMask == 0x00000000)
+ && (ddsh.ddspf.dwABitMask == 0x00000000)) {
+ // We support D3D's L8 (flagged as 8 bits of red only)
+ image->format = qt3ds::render::NVRenderTextureFormats::Luminance8;
+ image->components = 1;
+ image->alpha = 0;
+ image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8;
+ image->bytesPerPixel = 1;
+ image->compressed = 0;
+ dib->format = qt3ds::render::NVRenderTextureFormats::Luminance8;
+ } else if ((ddsh.ddspf.dwRGBBitCount == 16) && (ddsh.ddspf.dwRBitMask == 0x000000FF)
+ && (ddsh.ddspf.dwGBitMask == 0x00000000)
+ && (ddsh.ddspf.dwBBitMask == 0x00000000)
+ && (ddsh.ddspf.dwABitMask == 0x0000FF00)) {
+ // We support D3D's A8L8 (flagged as 8 bits of red and 8 bits of alpha)
+ image->format = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8;
+ image->components = 2;
+ image->alpha = 1;
+ image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8;
+ image->bytesPerPixel = 2;
+ image->compressed = 0;
+ dib->format = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8;
+ } else {
+ throw "not a DXTC or supported RGB(A) format image";
+ }
+ }
+
+ // detect flagging to indicate this texture was stored in a y-inverted fashion
+ if (!(ddsh.dwFlags & DDS_LINEARSIZE)) {
+ if (ddsh.dwPitchOrLinearSize == DDS_MAGIC_FLIPPED) {
+ isAllreadyFlipped = true;
+ }
+ }
+
+ flipVertical = (isAllreadyFlipped != (flipVertical ? true : false)) ? 1 : 0;
+
+ // store primary surface width/height/numMipmaps
+ image->width = ddsh.dwWidth;
+ image->height = ddsh.dwHeight;
+ image->numMipmaps = ddsh.dwFlags & DDS_MIPMAPCOUNT ? ddsh.dwMipMapCount : 1;
+
+ if (image->numMipmaps > UIC_DDS_MAX_MIPMAPS) {
+ throw "Too many mipmaps: max 16";
+ }
+
+ // allocate the meta datablock for all mip storage.
+ UICDDSAllocDataBlock(io, image);
+ if (image->dataBlock == NULL) {
+ throw "Failed to allocate memory for image data storage";
+ }
+
+ dib->width = image->width;
+ dib->height = image->height;
+ dib->dds = image;
+
+ QT3DSI32 faces = image->cubemap ? 6 : 1;
+
+ QT3DSI32 index = 0;
+ for (QT3DSI32 j = 0; j < faces; j++) {
+ // load all surfaces for the image
+ QT3DSI32 width = image->width;
+ QT3DSI32 height = image->height;
+
+ for (QT3DSI32 i = 0; i < image->numMipmaps; i++) {
+ // Get the size, read in the data.
+ inStream.Read(
+ NVDataRef<QT3DSU8>((QT3DSU8 *)image->data[index], (QT3DSU32)image->size[index]));
+
+ // Flip in Y for OpenGL if needed
+ if (flipVertical)
+ flip_data_vertical(io, (QT3DSI8 *)image->data[index], width, height, image);
+
+ // shrink to next power of 2
+ width >>= 1;
+ height >>= 1;
+
+ if (!width)
+ width = 1;
+
+ if (!height)
+ height = 1;
+
+ // make sure DXT isn't <4 on a side...
+ if (image->compressed) {
+ if (width < 4)
+ width = 4;
+ if (height < 4)
+ height = 4;
+ }
+
+ index++;
+ }
+ }
+
+ if (needsBGRASwap) {
+ QT3DSI32 index = 0;
+ QT3DSI32 k;
+
+ for (k = 0; k < faces; k++) {
+ QT3DSI32 width = image->width;
+ QT3DSI32 height = image->height;
+
+ for (QT3DSI32 i = 0; i < image->numMipmaps; i++) {
+ QT3DSI8 *data = (QT3DSI8 *)(image->data[index]);
+ QT3DSI32 pixels = width * height;
+ QT3DSI32 j;
+
+ for (j = 0; j < pixels; j++) {
+ QT3DSI8 temp = data[0];
+ data[0] = data[2];
+ data[2] = temp;
+
+ data += 4;
+ }
+
+ // shrink to next power of 2
+ width >>= 1;
+ height >>= 1;
+
+ if (!width)
+ width = 1;
+
+ if (!height)
+ height = 1;
+
+ index++;
+ }
+ }
+ }
+ } catch (const char *message) {
+ if (image) {
+ if (image->dataBlock)
+ QT3DS_FREE(io->m_Allocator, image->dataBlock);
+
+ QT3DS_FREE(io->m_Allocator, image);
+ }
+ if (dib) {
+ FreeImage_Unload(dib);
+ }
+ if (message) {
+ FreeImage_OutputMessageProc(s_exception_string, message, io);
+ }
+ }
+
+ return dib;
+ }
+
+ SLoadedTexture *SLoadedTexture::LoadDDS(IInStream &inStream, QT3DSI32 flipVertical,
+ NVFoundationBase &inFnd)
+ {
+ FreeImageIO theIO(inFnd.getAllocator(), inFnd);
+ SLoadedTexture *retval = DoLoadDDS(&theIO, inStream, flipVertical);
+
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.h
new file mode 100644
index 00000000..7e074cca
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureDDS.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef UIC_RENDER_LOAD_DDS_H
+#define UIC_RENDER_LOAD_DDS_H
+
+namespace uic {
+namespace render {
+
+/** The maximum number of mipmap levels (per texture or per cubemap face) */
+#define UIC_DDS_MAX_MIPMAPS (16)
+
+/** The number of cubemap faces that must exist in a cubemap-bearing DDS file */
+#define UIC_DDS_NUM_CUBEMAP_FACES (6)
+
+ /** The master DDS structure for loading and saving
+
+ This is the master DDS structure. It shouldn't be allocated by hand,
+ always use NVHHDDSAlloc/NVHHDDSAllocData/NVHHDDSFree to manage them properly.
+ */
+
+ struct UICDDSImage
+ {
+ /** Width of the overall texture in texels */
+ int width;
+ /** Height of the overall texture in texels */
+ int height;
+ /** Number of color/alpha components per texel 1-4 */
+ int components;
+ /** The GL type of each color component (noncompressed textures only) */
+ int componentFormat;
+ /** The number of bytes per pixel (noncompressed textures only) */
+ int bytesPerPixel;
+ /** Nonzero if the format is DXT-compressed */
+ int compressed;
+ /** The number of levels in the mipmap pyramid (including the base level) */
+ int numMipmaps;
+ /** If nonzero, then the file contains 6 cubemap faces */
+ int cubemap;
+ /** The GL format of the loaded texture data */
+ int format;
+ /** Nonzero if the texture data includes alpha */
+ int alpha;
+ /** Base of the allocated block of all texel data */
+ void *dataBlock;
+ /** Pointers to the mipmap levels for the texture or each cubemap face */
+ void *data[UIC_DDS_MAX_MIPMAPS * UIC_DDS_NUM_CUBEMAP_FACES];
+ /** Array of sizes of the mipmap levels for the texture or each cubemap face */
+ int size[UIC_DDS_MAX_MIPMAPS * UIC_DDS_NUM_CUBEMAP_FACES];
+ /** Array of widths of the mipmap levels for the texture or each cubemap face */
+ int mipwidth[UIC_DDS_MAX_MIPMAPS * UIC_DDS_NUM_CUBEMAP_FACES];
+ /** Array of heights of the mipmap levels for the texture or each cubemap face */
+ int mipheight[UIC_DDS_MAX_MIPMAPS * UIC_DDS_NUM_CUBEMAP_FACES];
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureFreeImageCompat.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureFreeImageCompat.h
new file mode 100644
index 00000000..9b3f73b8
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureFreeImageCompat.h
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_LOADED_TEXTURE_FREEIMAGE_COMPAT_H
+#define UIC_RENDER_LOADED_TEXTURE_FREEIMAGE_COMPAT_H
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICRenderLoadedTexture.h"
+#include "EASTL/algorithm.h"
+#include <stdlib.h>
+#ifndef _MACOSX
+#ifndef _INTEGRITYPLATFORM
+#include <malloc.h>
+#endif
+#endif
+
+// We use a compatibility layer so we can easily convert freeimage code to load our texture formats
+// where necessary.
+
+namespace uic {
+namespace render {
+ using namespace qt3ds::foundation;
+
+ typedef int32_t BOOL;
+ typedef uint8_t BYTE;
+ typedef uint16_t WORD;
+ typedef uint32_t DWORD;
+ typedef int32_t LONG;
+
+#define FREEIMAGE_COLORORDER_BGR 0
+#define FREEIMAGE_COLORORDER_RGB 1
+
+#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_BGR
+
+ typedef ISeekableIOStream *fi_handle;
+
+ struct FreeImageIO
+ {
+ NVAllocatorCallback &m_Allocator;
+ NVFoundationBase &m_Foundation;
+ int (*read_proc)(void *data, int size, int itemSize, fi_handle handle);
+ void (*seek_proc)(fi_handle handle, int offset, int pos);
+ int (*tell_proc)(fi_handle handle);
+ static inline int reader(void *data, int size, int itemSize, fi_handle handle)
+ {
+ NVDataRef<QT3DSU8> theData(toDataRef((QT3DSU8 *)data, (QT3DSU32)size * itemSize));
+ QT3DSU32 amount = handle->Read(theData);
+ return (int)amount;
+ }
+ static inline void seeker(fi_handle handle, int offset, int pos)
+ {
+ SeekPosition::Enum seekPos(SeekPosition::Begin);
+ /*
+#define SEEK_CUR 1
+#define SEEK_END 2
+#define SEEK_SET 0*/
+ switch (pos) {
+ case 0:
+ seekPos = SeekPosition::Begin;
+ break;
+ case 1:
+ seekPos = SeekPosition::Current;
+ break;
+ case 2:
+ seekPos = SeekPosition::End;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ handle->SetPosition(offset, seekPos);
+ }
+ static inline int teller(fi_handle handle) { return (int)handle->GetPosition(); }
+ FreeImageIO(NVAllocatorCallback &alloc, NVFoundationBase &fnd)
+ : m_Allocator(alloc)
+ , m_Foundation(fnd)
+ , read_proc(reader)
+ , seek_proc(seeker)
+ , tell_proc(teller)
+ {
+ }
+ };
+
+ typedef SLoadedTexture FIBITMAP;
+ inline BYTE *FreeImage_GetBits(FIBITMAP *bmp) { return (BYTE *)bmp->data; }
+
+ inline int FreeImage_GetHeight(FIBITMAP *bmp) { return bmp->height; }
+ inline int FreeImage_GetWidth(FIBITMAP *bmp) { return bmp->width; }
+
+#define INPLACESWAP(x, y) eastl::swap(x, y)
+#define MIN(x, y) NVMin(x, y)
+#define MAX(x, y) NVMax(x, y)
+
+#define TRUE 1
+#define FALSE 0
+
+ typedef struct tagBITMAPINFOHEADER
+ {
+ DWORD biSize;
+ LONG biWidth;
+ LONG biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+ DWORD biCompression;
+ DWORD biSizeImage;
+ LONG biXPelsPerMeter;
+ LONG biYPelsPerMeter;
+ DWORD biClrUsed;
+ DWORD biClrImportant;
+ } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
+
+ typedef struct tagRGBQUAD
+ {
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+#else
+ BYTE rgbRed;
+ BYTE rgbGreen;
+ BYTE rgbBlue;
+#endif // FREEIMAGE_COLORORDER
+ BYTE rgbReserved;
+ } RGBQUAD;
+
+ typedef struct tagRGBTRIPLE
+ {
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ BYTE rgbtBlue;
+ BYTE rgbtGreen;
+ BYTE rgbtRed;
+#else
+ BYTE rgbtRed;
+ BYTE rgbtGreen;
+ BYTE rgbtBlue;
+#endif // FREEIMAGE_COLORORDER
+ } RGBTRIPLE;
+
+ typedef struct tagBITMAPINFO
+ {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[1];
+ } BITMAPINFO, *PBITMAPINFO;
+
+ typedef struct tagFILE_RGBA
+ {
+ unsigned char r, g, b, a;
+ } FILE_RGBA;
+
+ typedef struct tagFILE_BGRA
+ {
+ unsigned char b, g, r, a;
+ } FILE_BGRA;
+
+ typedef struct tagFILE_RGB
+ {
+ unsigned char r, g, b;
+ } FILE_RGB;
+
+ typedef struct tagFILE_BGR
+ {
+ unsigned char b, g, r;
+ } FILE_BGR;
+
+// Indexes for byte arrays, masks and shifts for treating pixels as words ---
+// These coincide with the order of RGBQUAD and RGBTRIPLE -------------------
+
+#ifndef FREEIMAGE_BIGENDIAN
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+// Little Endian (x86 / MS Windows, Linux) : BGR(A) order
+#define FI_RGBA_RED 2
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 0
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0x00FF0000
+#define FI_RGBA_GREEN_MASK 0x0000FF00
+#define FI_RGBA_BLUE_MASK 0x000000FF
+#define FI_RGBA_ALPHA_MASK 0xFF000000
+#define FI_RGBA_RED_SHIFT 16
+#define FI_RGBA_GREEN_SHIFT 8
+#define FI_RGBA_BLUE_SHIFT 0
+#define FI_RGBA_ALPHA_SHIFT 24
+#else
+// Little Endian (x86 / MaxOSX) : RGB(A) order
+#define FI_RGBA_RED 0
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 2
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0x000000FF
+#define FI_RGBA_GREEN_MASK 0x0000FF00
+#define FI_RGBA_BLUE_MASK 0x00FF0000
+#define FI_RGBA_ALPHA_MASK 0xFF000000
+#define FI_RGBA_RED_SHIFT 0
+#define FI_RGBA_GREEN_SHIFT 8
+#define FI_RGBA_BLUE_SHIFT 16
+#define FI_RGBA_ALPHA_SHIFT 24
+#endif // FREEIMAGE_COLORORDER
+#else
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+// Big Endian (PPC / none) : BGR(A) order
+#define FI_RGBA_RED 2
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 0
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0x0000FF00
+#define FI_RGBA_GREEN_MASK 0x00FF0000
+#define FI_RGBA_BLUE_MASK 0xFF000000
+#define FI_RGBA_ALPHA_MASK 0x000000FF
+#define FI_RGBA_RED_SHIFT 8
+#define FI_RGBA_GREEN_SHIFT 16
+#define FI_RGBA_BLUE_SHIFT 24
+#define FI_RGBA_ALPHA_SHIFT 0
+#else
+// Big Endian (PPC / Linux, MaxOSX) : RGB(A) order
+#define FI_RGBA_RED 0
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 2
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0xFF000000
+#define FI_RGBA_GREEN_MASK 0x00FF0000
+#define FI_RGBA_BLUE_MASK 0x0000FF00
+#define FI_RGBA_ALPHA_MASK 0x000000FF
+#define FI_RGBA_RED_SHIFT 24
+#define FI_RGBA_GREEN_SHIFT 16
+#define FI_RGBA_BLUE_SHIFT 8
+#define FI_RGBA_ALPHA_SHIFT 0
+#endif // FREEIMAGE_COLORORDER
+#endif // FREEIMAGE_BIGENDIAN
+
+#define FI_RGBA_RGB_MASK (FI_RGBA_RED_MASK | FI_RGBA_GREEN_MASK | FI_RGBA_BLUE_MASK)
+
+// The 16bit macros only include masks and shifts, since each color element is not byte aligned
+
+#define FI16_555_RED_MASK 0x7C00
+#define FI16_555_GREEN_MASK 0x03E0
+#define FI16_555_BLUE_MASK 0x001F
+#define FI16_555_RED_SHIFT 10
+#define FI16_555_GREEN_SHIFT 5
+#define FI16_555_BLUE_SHIFT 0
+#define FI16_565_RED_MASK 0xF800
+#define FI16_565_GREEN_MASK 0x07E0
+#define FI16_565_BLUE_MASK 0x001F
+#define FI16_565_RED_SHIFT 11
+#define FI16_565_GREEN_SHIFT 5
+#define FI16_565_BLUE_SHIFT 0
+
+ inline unsigned char HINIBBLE(unsigned char byte) { return byte & 0xF0; }
+
+ inline unsigned char LOWNIBBLE(unsigned char byte) { return byte & 0x0F; }
+
+ inline int CalculateUsedBits(int bits)
+ {
+ int bit_count = 0;
+ unsigned bit = 1;
+
+ for (unsigned i = 0; i < 32; i++) {
+ if ((bits & bit) == bit) {
+ bit_count++;
+ }
+
+ bit <<= 1;
+ }
+
+ return bit_count;
+ }
+
+ inline int CalculateLine(int width, int bitdepth) { return ((width * bitdepth) + 7) / 8; }
+
+ inline int CalculatePitch(int line) { return (line + 3) & ~3; }
+
+ inline int CalculateUsedPaletteEntries(int bit_count)
+ {
+ if ((bit_count >= 1) && (bit_count <= 8))
+ return 1 << bit_count;
+
+ return 0;
+ }
+
+ inline unsigned char *CalculateScanLine(unsigned char *bits, unsigned pitch, int scanline)
+ {
+ return (bits + (pitch * scanline));
+ }
+
+ inline void ReplaceExtension(char *result, const char *filename, const char *extension)
+ {
+ for (size_t i = strlen(filename) - 1; i > 0; --i) {
+ if (filename[i] == '.') {
+ memcpy(result, filename, i);
+ result[i] = '.';
+ memcpy(result + i + 1, extension, strlen(extension) + 1);
+ return;
+ }
+ }
+
+ memcpy(result, filename, strlen(filename));
+ result[strlen(filename)] = '.';
+ memcpy(result + strlen(filename) + 1, extension, strlen(extension) + 1);
+ }
+
+ inline BYTE *FreeImage_GetScanLine(FIBITMAP *bmp, int height)
+ {
+ return CalculateScanLine(
+ (BYTE *)bmp->data, CalculatePitch(CalculateLine(bmp->width, bmp->m_BitCount)), height);
+ }
+
+#define DLL_CALLCONV
+
+// ignored for now.
+#define FreeImage_SetDotsPerMeterX(img, dots)
+#define FreeImage_SetDotsPerMeterY(img, dots)
+
+ inline SLoadedTexture *FreeImage_Allocate(int width, int height, int bit_count, FreeImageIO *io)
+ {
+ SLoadedTexture *theTexture = QT3DS_NEW(io->m_Allocator, SLoadedTexture)(io->m_Allocator);
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+ QT3DSU32 dataSize = (QT3DSU32)(height * pitch);
+ theTexture->dataSizeInBytes = dataSize;
+ theTexture->data = io->m_Allocator.allocate(dataSize, "image data", __FILE__, __LINE__);
+ memZero(theTexture->data, dataSize);
+ theTexture->width = width;
+ theTexture->height = height;
+ theTexture->m_BitCount = bit_count;
+ // If free image asks us for a palette, we change our format at that time.
+ theTexture->m_ExtendedFormat = ExtendedTextureFormats::CustomRGB;
+ return theTexture;
+ }
+
+ inline SLoadedTexture *FreeImage_Allocate(int width, int height, int bit_count, int rmask,
+ int gmask, int bmask, FreeImageIO *io)
+ {
+ SLoadedTexture *retval = FreeImage_Allocate(width, height, bit_count, io);
+ retval->m_CustomMasks[0] = rmask;
+ retval->m_CustomMasks[1] = gmask;
+ retval->m_CustomMasks[2] = bmask;
+ return retval;
+ }
+
+ inline RGBQUAD *FreeImage_GetPalette(SLoadedTexture *texture)
+ {
+ if (texture->m_Palette == NULL) {
+ texture->m_ExtendedFormat = ExtendedTextureFormats::Palettized;
+ QT3DSU32 memory = 256 * sizeof(RGBQUAD);
+ if (memory) {
+ texture->m_Palette =
+ texture->m_Allocator.allocate(memory, "texture palette", __FILE__, __LINE__);
+ memZero(texture->m_Palette, memory);
+ }
+ }
+ return (RGBQUAD *)texture->m_Palette;
+ }
+
+ inline void FreeImage_Unload(SLoadedTexture *texture) { texture->release(); }
+ inline void FreeImage_OutputMessageProc(int, const char *message, FreeImageIO *io)
+ {
+ Q_UNUSED(io);
+ qCCritical(INVALID_OPERATION, "Error loading image: %s", message);
+ }
+
+ inline void FreeImage_SetBackgroundColor(SLoadedTexture *texture, RGBQUAD *inColor)
+ {
+ if (inColor) {
+ texture->m_BackgroundColor[0] = inColor->rgbRed;
+ texture->m_BackgroundColor[1] = inColor->rgbGreen;
+ texture->m_BackgroundColor[2] = inColor->rgbBlue;
+ } else
+ memSet(texture->m_BackgroundColor, 0, 3);
+ }
+
+ inline void FreeImage_SetTransparencyTable(SLoadedTexture *texture, BYTE *table, int size)
+ {
+ if (texture->m_TransparencyTable)
+ texture->m_Allocator.deallocate(texture->m_TransparencyTable);
+ texture->m_TransparencyTable = NULL;
+ if (table && size) {
+ texture->m_TransparencyTable = (uint8_t *)texture->m_Allocator.allocate(
+ size, "texture transparency table", __FILE__, __LINE__);
+ memCopy(texture->m_TransparencyTable, table, size);
+ }
+ }
+}
+}
+
+using namespace uic::render;
+
+#endif
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureGIF.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureGIF.cpp
new file mode 100644
index 00000000..f9840c62
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureGIF.cpp
@@ -0,0 +1,849 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// ==========================================================
+// GIF Loader and Writer
+//
+// Design and implementation by
+// - Ryan Rubley <ryan@lostreality.org>
+// - Raphael Gaquer <raphael.gaquer@alcer.com>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+#ifdef _MSC_VER
+#pragma warning(disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "UICRenderLoadedTextureFreeImageCompat.h"
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+// ==========================================================
+// Metadata declarations
+// ==========================================================
+
+#define GIF_DISPOSAL_UNSPECIFIED 0
+#define GIF_DISPOSAL_LEAVE 1
+#define GIF_DISPOSAL_BACKGROUND 2
+#define GIF_DISPOSAL_PREVIOUS 3
+
+// ==========================================================
+// Constant/Typedef declarations
+// ==========================================================
+
+struct GIFinfo
+{
+ BOOL read;
+ // only really used when reading
+ size_t global_color_table_offset;
+ int global_color_table_size;
+ BYTE background_color;
+ eastl::vector<size_t> application_extension_offsets;
+ eastl::vector<size_t> comment_extension_offsets;
+ eastl::vector<size_t> graphic_control_extension_offsets;
+ eastl::vector<size_t> image_descriptor_offsets;
+
+ GIFinfo()
+ : read(0)
+ , global_color_table_offset(0)
+ , global_color_table_size(0)
+ , background_color(0)
+ {
+ }
+};
+
+struct PageInfo
+{
+ PageInfo(int d, int l, int t, int w, int h)
+ {
+ disposal_method = d;
+ left = (WORD)l;
+ top = (WORD)t;
+ width = (WORD)w;
+ height = (WORD)h;
+ }
+ int disposal_method;
+ WORD left, top, width, height;
+};
+
+// GIF defines a max of 12 bits per code
+#define MAX_LZW_CODE 4096
+
+class StringTable
+{
+public:
+ StringTable();
+ ~StringTable();
+ void Initialize(int minCodeSize);
+ BYTE *FillInputBuffer(int len);
+ void CompressStart(int bpp, int width);
+ int CompressEnd(BYTE *buf); // 0-4 bytes
+ bool Compress(BYTE *buf, int *len);
+ bool Decompress(BYTE *buf, int *len);
+ void Done(void);
+
+protected:
+ bool m_done;
+
+ int m_minCodeSize, m_clearCode, m_endCode, m_nextCode;
+
+ int m_bpp, m_slack; // Compressor information
+
+ int m_prefix; // Compressor state variable
+ int m_codeSize, m_codeMask; // Compressor/Decompressor state variables
+ int m_oldCode; // Decompressor state variable
+ int m_partial, m_partialSize; // Compressor/Decompressor bit buffer
+
+ int firstPixelPassed; // A specific flag that indicates if the first pixel
+ // of the whole image had already been read
+
+ eastl::string m_strings[MAX_LZW_CODE]; // This is what is really the "string table" data for the
+ // Decompressor
+ int *m_strmap;
+
+ // input buffer
+ BYTE *m_buffer;
+ int m_bufferSize, m_bufferRealSize, m_bufferPos, m_bufferShift;
+
+ void ClearCompressorTable(void);
+ void ClearDecompressorTable(void);
+};
+
+#define GIF_PACKED_LSD_HAVEGCT 0x80
+#define GIF_PACKED_LSD_COLORRES 0x70
+#define GIF_PACKED_LSD_GCTSORTED 0x08
+#define GIF_PACKED_LSD_GCTSIZE 0x07
+#define GIF_PACKED_ID_HAVELCT 0x80
+#define GIF_PACKED_ID_INTERLACED 0x40
+#define GIF_PACKED_ID_LCTSORTED 0x20
+#define GIF_PACKED_ID_RESERVED 0x18
+#define GIF_PACKED_ID_LCTSIZE 0x07
+#define GIF_PACKED_GCE_RESERVED 0xE0
+#define GIF_PACKED_GCE_DISPOSAL 0x1C
+#define GIF_PACKED_GCE_WAITINPUT 0x02
+#define GIF_PACKED_GCE_HAVETRANS 0x01
+
+#define GIF_BLOCK_IMAGE_DESCRIPTOR 0x2C
+#define GIF_BLOCK_EXTENSION 0x21
+#define GIF_BLOCK_TRAILER 0x3B
+
+#define GIF_EXT_PLAINTEXT 0x01
+#define GIF_EXT_GRAPHIC_CONTROL 0xF9
+#define GIF_EXT_COMMENT 0xFE
+#define GIF_EXT_APPLICATION 0xFF
+
+#define GIF_INTERLACE_PASSES 4
+static int g_GifInterlaceOffset[GIF_INTERLACE_PASSES] = { 0, 4, 2, 1 };
+static int g_GifInterlaceIncrement[GIF_INTERLACE_PASSES] = { 8, 8, 4, 2 };
+
+StringTable::StringTable()
+{
+ m_buffer = NULL;
+ firstPixelPassed = 0; // Still no pixel read
+ // Maximum number of entries in the map is MAX_LZW_CODE * 256
+ // (aka 2**12 * 2**8 => a 20 bits key)
+ // This Map could be optmized to only handle MAX_LZW_CODE * 2**(m_bpp)
+ m_strmap = (int *)new int[1 << 20];
+}
+
+StringTable::~StringTable()
+{
+ if (m_buffer != NULL) {
+ delete[] m_buffer;
+ }
+ if (m_strmap != NULL) {
+ delete[] m_strmap;
+ m_strmap = NULL;
+ }
+}
+
+void StringTable::Initialize(int minCodeSize)
+{
+ m_done = false;
+
+ m_bpp = 8;
+ m_minCodeSize = minCodeSize;
+ m_clearCode = 1 << m_minCodeSize;
+ if (m_clearCode > MAX_LZW_CODE) {
+ m_clearCode = MAX_LZW_CODE;
+ }
+ m_endCode = m_clearCode + 1;
+
+ m_partial = 0;
+ m_partialSize = 0;
+
+ m_bufferSize = 0;
+ ClearCompressorTable();
+ ClearDecompressorTable();
+}
+
+BYTE *StringTable::FillInputBuffer(int len)
+{
+ if (m_buffer == NULL) {
+ m_buffer = new BYTE[len];
+ m_bufferRealSize = len;
+ } else if (len > m_bufferRealSize) {
+ delete[] m_buffer;
+ m_buffer = new BYTE[len];
+ m_bufferRealSize = len;
+ }
+ m_bufferSize = len;
+ m_bufferPos = 0;
+ m_bufferShift = 8 - m_bpp;
+ return m_buffer;
+}
+
+void StringTable::CompressStart(int bpp, int width)
+{
+ m_bpp = bpp;
+ m_slack = (8 - ((width * bpp) % 8)) % 8;
+
+ m_partial |= m_clearCode << m_partialSize;
+ m_partialSize += m_codeSize;
+ ClearCompressorTable();
+}
+
+int StringTable::CompressEnd(BYTE *buf)
+{
+ int len = 0;
+
+ // output code for remaining prefix
+ m_partial |= m_prefix << m_partialSize;
+ m_partialSize += m_codeSize;
+ while (m_partialSize >= 8) {
+ *buf++ = (BYTE)m_partial;
+ m_partial >>= 8;
+ m_partialSize -= 8;
+ len++;
+ }
+
+ // add the end of information code and flush the entire buffer out
+ m_partial |= m_endCode << m_partialSize;
+ m_partialSize += m_codeSize;
+ while (m_partialSize > 0) {
+ *buf++ = (BYTE)m_partial;
+ m_partial >>= 8;
+ m_partialSize -= 8;
+ len++;
+ }
+
+ // most this can be is 4 bytes. 7 bits in m_partial to start + 12 for the
+ // last code + 12 for the end code = 31 bits total.
+ return len;
+}
+
+bool StringTable::Compress(BYTE *buf, int *len)
+{
+ if (m_bufferSize == 0 || m_done) {
+ return false;
+ }
+
+ int mask = (1 << m_bpp) - 1;
+ BYTE *bufpos = buf;
+ while (m_bufferPos < m_bufferSize) {
+ // get the current pixel value
+ char ch = (char)((m_buffer[m_bufferPos] >> m_bufferShift) & mask);
+
+ // The next prefix is :
+ // <the previous LZW code (on 12 bits << 8)> | <the code of the current pixel (on 8 bits)>
+ int nextprefix = (((m_prefix) << 8) & 0xFFF00) + (ch & 0x000FF);
+ if (firstPixelPassed) {
+
+ if (m_strmap[nextprefix] > 0) {
+ m_prefix = m_strmap[nextprefix];
+ } else {
+ m_partial |= m_prefix << m_partialSize;
+ m_partialSize += m_codeSize;
+ // grab full bytes for the output buffer
+ while (m_partialSize >= 8 && bufpos - buf < *len) {
+ *bufpos++ = (BYTE)m_partial;
+ m_partial >>= 8;
+ m_partialSize -= 8;
+ }
+
+ // add the code to the "table map"
+ m_strmap[nextprefix] = m_nextCode;
+
+ // increment the next highest valid code, increase the code size
+ if (m_nextCode == (1 << m_codeSize)) {
+ m_codeSize++;
+ }
+ m_nextCode++;
+
+ // if we're out of codes, restart the string table
+ if (m_nextCode == MAX_LZW_CODE) {
+ m_partial |= m_clearCode << m_partialSize;
+ m_partialSize += m_codeSize;
+ ClearCompressorTable();
+ }
+
+ // Only keep the 8 lowest bits (prevent problems with "negative chars")
+ m_prefix = ch & 0x000FF;
+ }
+
+ // increment to the next pixel
+ if (m_bufferShift > 0
+ && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack)) {
+ m_bufferShift -= m_bpp;
+ } else {
+ m_bufferPos++;
+ m_bufferShift = 8 - m_bpp;
+ }
+
+ // jump out here if the output buffer is full
+ if (bufpos - buf == *len) {
+ return true;
+ }
+
+ } else {
+ // Specific behavior for the first pixel of the whole image
+
+ firstPixelPassed = 1;
+ // Only keep the 8 lowest bits (prevent problems with "negative chars")
+ m_prefix = ch & 0x000FF;
+
+ // increment to the next pixel
+ if (m_bufferShift > 0
+ && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack)) {
+ m_bufferShift -= m_bpp;
+ } else {
+ m_bufferPos++;
+ m_bufferShift = 8 - m_bpp;
+ }
+
+ // jump out here if the output buffer is full
+ if (bufpos - buf == *len) {
+ return true;
+ }
+ }
+ }
+
+ m_bufferSize = 0;
+ *len = (int)(bufpos - buf);
+
+ return true;
+}
+
+bool StringTable::Decompress(BYTE *buf, int *len)
+{
+ if (m_bufferSize == 0 || m_done) {
+ return false;
+ }
+
+ BYTE *bufpos = buf;
+ for (; m_bufferPos < m_bufferSize; m_bufferPos++) {
+ m_partial |= (int)m_buffer[m_bufferPos] << m_partialSize;
+ m_partialSize += 8;
+ while (m_partialSize >= m_codeSize) {
+ int code = m_partial & m_codeMask;
+ m_partial >>= m_codeSize;
+ m_partialSize -= m_codeSize;
+
+ if (code > m_nextCode || (m_nextCode == MAX_LZW_CODE && code != m_clearCode)
+ || code == m_endCode) {
+ m_done = true;
+ *len = (int)(bufpos - buf);
+ return true;
+ }
+ if (code == m_clearCode) {
+ ClearDecompressorTable();
+ continue;
+ }
+
+ // add new string to string table, if not the first pass since a clear code
+ if (m_oldCode != MAX_LZW_CODE) {
+ m_strings[m_nextCode] =
+ m_strings[m_oldCode] + m_strings[code == m_nextCode ? m_oldCode : code][0];
+ }
+
+ if ((int)m_strings[code].size() > *len - (bufpos - buf)) {
+ // out of space, stuff the code back in for next time
+ m_partial <<= m_codeSize;
+ m_partialSize += m_codeSize;
+ m_partial |= code;
+ m_bufferPos++;
+ *len = (int)(bufpos - buf);
+ return true;
+ }
+
+ // output the string into the buffer
+ memcpy(bufpos, m_strings[code].data(), m_strings[code].size());
+ bufpos += m_strings[code].size();
+
+ // increment the next highest valid code, add a bit to the mask if we need to increase
+ // the code size
+ if (m_oldCode != MAX_LZW_CODE && m_nextCode < MAX_LZW_CODE) {
+ if (++m_nextCode < MAX_LZW_CODE) {
+ if ((m_nextCode & m_codeMask) == 0) {
+ m_codeSize++;
+ m_codeMask |= m_nextCode;
+ }
+ }
+ }
+
+ m_oldCode = code;
+ }
+ }
+
+ m_bufferSize = 0;
+ *len = (int)(bufpos - buf);
+
+ return true;
+}
+
+void StringTable::Done(void)
+{
+ m_done = true;
+}
+
+void StringTable::ClearCompressorTable(void)
+{
+ if (m_strmap) {
+ memset(m_strmap, 0xFF, sizeof(unsigned int) * (1 << 20));
+ }
+ m_nextCode = m_endCode + 1;
+
+ m_prefix = 0;
+ m_codeSize = m_minCodeSize + 1;
+}
+
+void StringTable::ClearDecompressorTable(void)
+{
+ for (int i = 0; i < m_clearCode; i++) {
+ m_strings[i].resize(1);
+ m_strings[i][0] = (char)i;
+ }
+ m_nextCode = m_endCode + 1;
+
+ m_codeSize = m_minCodeSize + 1;
+ m_codeMask = (1 << m_codeSize) - 1;
+ m_oldCode = MAX_LZW_CODE;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static BOOL DLL_CALLCONV Validate(FreeImageIO *io, fi_handle handle)
+{
+ char buf[6];
+ if (io->read_proc(buf, 6, 1, handle) < 1) {
+ return FALSE;
+ }
+
+ BOOL bResult = FALSE;
+ if (!strncmp(buf, "GIF", 3)) {
+ if (buf[3] >= '0' && buf[3] <= '9' && buf[4] >= '0' && buf[4] <= '9' && buf[5] >= 'a'
+ && buf[5] <= 'z') {
+ bResult = TRUE;
+ }
+ }
+
+ io->seek_proc(handle, -6, SEEK_CUR);
+
+ return bResult;
+}
+
+// ----------------------------------------------------------
+
+static void *DLL_CALLCONV Open(FreeImageIO *io, fi_handle handle)
+{
+ GIFinfo *info = new GIFinfo;
+ if (info == NULL) {
+ return NULL;
+ }
+ BOOL read = TRUE;
+
+ // 25/02/2008 MDA: Not safe to memset GIFinfo structure with VS 2008 (safe iterators),
+ // perform initialization in constructor instead.
+ // memset(info, 0, sizeof(GIFinfo));
+
+ info->read = read;
+ try {
+ // Header
+ if (!Validate(io, handle)) {
+ throw "Not a GIF file";
+ }
+ io->seek_proc(handle, 6, SEEK_CUR);
+
+ // Logical Screen Descriptor
+ io->seek_proc(handle, 4, SEEK_CUR);
+ BYTE packed;
+ if (io->read_proc(&packed, 1, 1, handle) < 1) {
+ throw "EOF reading Logical Screen Descriptor";
+ }
+ if (io->read_proc(&info->background_color, 1, 1, handle) < 1) {
+ throw "EOF reading Logical Screen Descriptor";
+ }
+ io->seek_proc(handle, 1, SEEK_CUR);
+
+ // Global Color Table
+ if (packed & GIF_PACKED_LSD_HAVEGCT) {
+ info->global_color_table_offset = io->tell_proc(handle);
+ info->global_color_table_size = 2 << (packed & GIF_PACKED_LSD_GCTSIZE);
+ io->seek_proc(handle, 3 * info->global_color_table_size, SEEK_CUR);
+ }
+
+ // Scan through all the rest of the blocks, saving offsets
+ size_t gce_offset = 0;
+ BYTE block = 0;
+ while (block != GIF_BLOCK_TRAILER) {
+ if (io->read_proc(&block, 1, 1, handle) < 1) {
+ throw "EOF reading blocks";
+ }
+ if (block == GIF_BLOCK_IMAGE_DESCRIPTOR) {
+ info->image_descriptor_offsets.push_back(io->tell_proc(handle));
+ // GCE may be 0, meaning no GCE preceded this ID
+ info->graphic_control_extension_offsets.push_back(gce_offset);
+ gce_offset = 0;
+
+ io->seek_proc(handle, 8, SEEK_CUR);
+ if (io->read_proc(&packed, 1, 1, handle) < 1) {
+ throw "EOF reading Image Descriptor";
+ }
+
+ // Local Color Table
+ if (packed & GIF_PACKED_ID_HAVELCT) {
+ io->seek_proc(handle, 3 * (2 << (packed & GIF_PACKED_ID_LCTSIZE)), SEEK_CUR);
+ }
+
+ // LZW Minimum Code Size
+ io->seek_proc(handle, 1, SEEK_CUR);
+ } else if (block == GIF_BLOCK_EXTENSION) {
+ BYTE ext;
+ if (io->read_proc(&ext, 1, 1, handle) < 1) {
+ throw "EOF reading extension";
+ }
+
+ if (ext == GIF_EXT_GRAPHIC_CONTROL) {
+ // overwrite previous offset if more than one GCE found before an ID
+ gce_offset = io->tell_proc(handle);
+ } else if (ext == GIF_EXT_COMMENT) {
+ info->comment_extension_offsets.push_back(io->tell_proc(handle));
+ } else if (ext == GIF_EXT_APPLICATION) {
+ info->application_extension_offsets.push_back(io->tell_proc(handle));
+ }
+ } else if (block == GIF_BLOCK_TRAILER) {
+ continue;
+ } else {
+ throw "Invalid GIF block found";
+ }
+
+ // Data Sub-blocks
+ BYTE len;
+ if (io->read_proc(&len, 1, 1, handle) < 1) {
+ throw "EOF reading sub-block";
+ }
+ while (len != 0) {
+ io->seek_proc(handle, len, SEEK_CUR);
+ if (io->read_proc(&len, 1, 1, handle) < 1) {
+ throw "EOF reading sub-block";
+ }
+ }
+ }
+ } catch (const char *msg) {
+ FreeImage_OutputMessageProc(s_format_id, msg, io);
+ delete info;
+ return NULL;
+ }
+
+ return info;
+}
+
+static FIBITMAP *DLL_CALLCONV DoLoadGIF(FreeImageIO *io, fi_handle handle, int flags, void *data)
+{
+ if (data == NULL) {
+ return NULL;
+ }
+ (void)flags;
+ GIFinfo *info = (GIFinfo *)data;
+
+ int page = 0;
+ FIBITMAP *dib = NULL;
+ try {
+ bool have_transparent = false, no_local_palette = false, interlaced = false;
+ int disposal_method = GIF_DISPOSAL_LEAVE, transparent_color = 0;
+ WORD left, top, width, height;
+ BYTE packed, b;
+ WORD w;
+
+ // Image Descriptor
+ io->seek_proc(handle, (long)info->image_descriptor_offsets[page], SEEK_SET);
+ io->read_proc(&left, 2, 1, handle);
+ io->read_proc(&top, 2, 1, handle);
+ io->read_proc(&width, 2, 1, handle);
+ io->read_proc(&height, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&left);
+ SwapShort(&top);
+ SwapShort(&width);
+ SwapShort(&height);
+#endif
+ io->read_proc(&packed, 1, 1, handle);
+ interlaced = (packed & GIF_PACKED_ID_INTERLACED) ? true : false;
+ no_local_palette = (packed & GIF_PACKED_ID_HAVELCT) ? false : true;
+
+ int bpp = 8;
+ if (!no_local_palette) {
+ int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE);
+ if (size <= 2)
+ bpp = 1;
+ else if (size <= 16)
+ bpp = 4;
+ } else if (info->global_color_table_offset != 0) {
+ if (info->global_color_table_size <= 2)
+ bpp = 1;
+ else if (info->global_color_table_size <= 16)
+ bpp = 4;
+ }
+ dib = FreeImage_Allocate(width, height, bpp, io);
+ if (dib == NULL) {
+ throw "DIB allocated failed";
+ }
+
+ // Palette
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ if (!no_local_palette) {
+ int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE);
+
+ int i = 0;
+ while (i < size) {
+ io->read_proc(&pal[i].rgbRed, 1, 1, handle);
+ io->read_proc(&pal[i].rgbGreen, 1, 1, handle);
+ io->read_proc(&pal[i].rgbBlue, 1, 1, handle);
+ i++;
+ }
+ } else if (info->global_color_table_offset != 0) {
+ long pos = io->tell_proc(handle);
+ io->seek_proc(handle, (long)info->global_color_table_offset, SEEK_SET);
+
+ int i = 0;
+ while (i < info->global_color_table_size) {
+ io->read_proc(&pal[i].rgbRed, 1, 1, handle);
+ io->read_proc(&pal[i].rgbGreen, 1, 1, handle);
+ io->read_proc(&pal[i].rgbBlue, 1, 1, handle);
+ i++;
+ }
+
+ io->seek_proc(handle, pos, SEEK_SET);
+ } else {
+ // its legal to have no palette, but we're going to generate *something*
+ for (int i = 0; i < 256; i++) {
+ pal[i].rgbRed = (BYTE)i;
+ pal[i].rgbGreen = (BYTE)i;
+ pal[i].rgbBlue = (BYTE)i;
+ }
+ }
+
+ // LZW Minimum Code Size
+ io->read_proc(&b, 1, 1, handle);
+ StringTable *stringtable = new StringTable;
+ stringtable->Initialize(b);
+
+ // Image Data Sub-blocks
+ int x = 0, xpos = 0, y = 0, shift = 8 - bpp, mask = (1 << bpp) - 1, interlacepass = 0;
+ BYTE *scanline = FreeImage_GetScanLine(dib, height - 1);
+ BYTE buf[4096];
+ io->read_proc(&b, 1, 1, handle);
+ while (b) {
+ io->read_proc(stringtable->FillInputBuffer(b), b, 1, handle);
+ int size = sizeof(buf);
+ while (stringtable->Decompress(buf, &size)) {
+ for (int i = 0; i < size; i++) {
+ scanline[xpos] |= (buf[i] & mask) << shift;
+ if (shift > 0) {
+ shift -= bpp;
+ } else {
+ xpos++;
+ shift = 8 - bpp;
+ }
+ if (++x >= width) {
+ if (interlaced) {
+ y += g_GifInterlaceIncrement[interlacepass];
+ if (y >= height && ++interlacepass < GIF_INTERLACE_PASSES) {
+ y = g_GifInterlaceOffset[interlacepass];
+ }
+ } else {
+ y++;
+ }
+ if (y >= height) {
+ stringtable->Done();
+ break;
+ }
+ x = xpos = 0;
+ shift = 8 - bpp;
+ scanline = FreeImage_GetScanLine(dib, height - y - 1);
+ }
+ }
+ size = sizeof(buf);
+ }
+ io->read_proc(&b, 1, 1, handle);
+ }
+
+ if (page == 0) {
+ QT3DSU32 idx;
+
+ // Logical Screen Descriptor
+ io->seek_proc(handle, 6, SEEK_SET);
+ WORD logicalwidth, logicalheight;
+ io->read_proc(&logicalwidth, 2, 1, handle);
+ io->read_proc(&logicalheight, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&logicalwidth);
+ SwapShort(&logicalheight);
+#endif
+
+ // Global Color Table
+ if (info->global_color_table_offset != 0) {
+ RGBQUAD globalpalette[256];
+ io->seek_proc(handle, (long)info->global_color_table_offset, SEEK_SET);
+ int i = 0;
+ while (i < info->global_color_table_size) {
+ io->read_proc(&globalpalette[i].rgbRed, 1, 1, handle);
+ io->read_proc(&globalpalette[i].rgbGreen, 1, 1, handle);
+ io->read_proc(&globalpalette[i].rgbBlue, 1, 1, handle);
+ globalpalette[i].rgbReserved = 0;
+ i++;
+ }
+ // background color
+ if (info->background_color < info->global_color_table_size) {
+ FreeImage_SetBackgroundColor(dib, &globalpalette[info->background_color]);
+ }
+ }
+
+ // Application Extension
+ LONG loop = 1; // If no AE with a loop count is found, the default must be 1
+ for (idx = 0; idx < info->application_extension_offsets.size(); idx++) {
+ io->seek_proc(handle, (long)info->application_extension_offsets[idx], SEEK_SET);
+ io->read_proc(&b, 1, 1, handle);
+ if (b == 11) { // All AEs start with an 11 byte sub-block to determine what type of
+ // AE it is
+ char buf[11];
+ io->read_proc(buf, 11, 1, handle);
+ if (!memcmp(buf, "NETSCAPE2.0", 11)
+ || !memcmp(buf, "ANIMEXTS1.0",
+ 11)) { // Not everybody recognizes ANIMEXTS1.0 but it is valid
+ io->read_proc(&b, 1, 1, handle);
+ if (b == 3) { // we're supposed to have a 3 byte sub-block now
+ io->read_proc(&b, 1, 1,
+ handle); // this should be 0x01 but isn't really important
+ io->read_proc(&w, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&w);
+#endif
+ loop = w;
+ if (loop > 0)
+ loop++;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Graphic Control Extension
+ if (info->graphic_control_extension_offsets[page] != 0) {
+ io->seek_proc(handle, (long)(info->graphic_control_extension_offsets[page] + 1),
+ SEEK_SET);
+ io->read_proc(&packed, 1, 1, handle);
+ io->read_proc(&w, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&w);
+#endif
+ io->read_proc(&b, 1, 1, handle);
+ have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false;
+ disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2;
+
+ transparent_color = b;
+ if (have_transparent) {
+ int size = 1 << bpp;
+ if (transparent_color <= size) {
+ BYTE table[256];
+ memset(table, 0xFF, size);
+ table[transparent_color] = 0;
+ FreeImage_SetTransparencyTable(dib, table, size);
+ dib->m_TransparentPaletteIndex = b;
+ }
+ }
+ }
+ b = (BYTE)disposal_method;
+
+ delete stringtable;
+
+ } catch (const char *msg) {
+ if (dib != NULL) {
+ FreeImage_Unload(dib);
+ }
+ FreeImage_OutputMessageProc(s_format_id, msg, io);
+ return NULL;
+ }
+
+ return dib;
+}
+
+static void DLL_CALLCONV Close(void *data)
+{
+ if (data == NULL) {
+ return;
+ }
+ GIFinfo *info = (GIFinfo *)data;
+ delete info;
+}
+
+SLoadedTexture *SLoadedTexture::LoadGIF(ISeekableIOStream &inStream, bool inFlipY,
+ NVFoundationBase &inFnd)
+{
+ FreeImageIO theIO(inFnd.getAllocator(), inFnd);
+ void *gifData = Open(&theIO, &inStream);
+ if (gifData) {
+ SLoadedTexture *retval = DoLoadGIF(&theIO, &inStream, 0, gifData);
+ Close(gifData);
+ if (retval)
+ retval->FreeImagePostProcess(inFlipY);
+ return retval;
+ }
+ return NULL;
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp
new file mode 100644
index 00000000..91cd9cb5
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderLoadedTextureHDR.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// ==========================================================
+// Radiance RGBE .HDR Loader
+// Decodes Radiance RGBE HDR image into FP16 texture buffer.
+//
+// Implementation by
+// Parashar Krishnamachari (parashark@nvidia.com)
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "UICRenderLoadedTextureFreeImageCompat.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+typedef unsigned char RGBE[4];
+#define R 0
+#define G 1
+#define B 2
+#define E 3
+
+#define MINELEN 8 // minimum scanline length for encoding
+#define MAXELEN 0x7fff // maximum scanline length for encoding
+
+static int s_format_id;
+
+static float convertComponent(int exponent, int val)
+{
+ float v = val / (256.0f);
+ float d = powf(2.0f, (float)exponent - 128.0f);
+ return v * d;
+}
+
+static void decrunchScanlineOld(FreeImageIO *io, fi_handle handle, RGBE *scanline, int width)
+{
+ int i;
+ int rshift = 0;
+
+ while (width > 0) {
+ io->read_proc(scanline, 4, 1, handle);
+
+ // The older version of RLE encodes the length in the exponent.
+ // and marks a run with 1, 1, 1 in RGB. This is differentiated from
+ // a raw value of 1, 1, 1, by having a exponent of 0;
+ if (scanline[0][R] == 1 && scanline[0][G] == 1 && scanline[0][B] == 1) {
+ for (i = (scanline[0][E] << rshift); i > 0; --i) {
+ memcpy(&scanline[0][0], &scanline[-1][0], 4);
+ ++scanline;
+ --width;
+ }
+ rshift += 8;
+ } else {
+ ++scanline;
+ --width;
+ rshift = 0;
+ }
+ }
+}
+
+static void decrunchScanline(FreeImageIO *io, fi_handle handle, RGBE *scanline, int width)
+{
+ if ((width < MINELEN) || (width > MAXELEN)) {
+ decrunchScanlineOld(io, handle, scanline, width);
+ return;
+ }
+
+ char c;
+ io->read_proc(&c, 1, 1, handle);
+ if (c != 2) {
+ io->seek_proc(handle, -1, SEEK_CUR);
+ decrunchScanlineOld(io, handle, scanline, width);
+ return;
+ }
+
+ io->read_proc(&(scanline[0][G]), 1, 1, handle);
+ io->read_proc(&(scanline[0][B]), 1, 1, handle);
+ io->read_proc(&c, 1, 1, handle);
+
+ if (scanline[0][G] != 2 || scanline[0][B] & 128) {
+ scanline[0][R] = 2;
+ scanline[0][E] = c;
+ decrunchScanlineOld(io, handle, scanline + 1, width - 1);
+ }
+
+ // RLE-encoded version does a separate buffer for each channel per scanline
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < width;) {
+ unsigned char code, val;
+ io->read_proc(&code, 1, 1, handle);
+ if (code
+ > 128) // RLE-encoded run... read 1 value and copy it forward for some n count.
+ {
+ code &= 127;
+ io->read_proc(&val, 1, 1, handle);
+ while (code--)
+ scanline[j++][i] = val;
+ } else // Not a run, so we read it as raw data
+ {
+ // Note -- we store each pixel in memory 4 bytes apart, so we can't just
+ // do one long read.
+ while (code--)
+ io->read_proc(&(scanline[j++][i]), 1, 1, handle);
+ }
+ }
+ }
+}
+
+static void decodeScanlineToTexture(RGBE *scanline, int width, void *outBuf, QT3DSU32 offset,
+ NVRenderTextureFormats::Enum inFormat)
+{
+ float rgbaF32[4];
+
+ for (int i = 0; i < width; ++i) {
+ rgbaF32[R] = convertComponent(scanline[i][E], scanline[i][R]);
+ rgbaF32[G] = convertComponent(scanline[i][E], scanline[i][G]);
+ rgbaF32[B] = convertComponent(scanline[i][E], scanline[i][B]);
+ rgbaF32[3] = 1.0f;
+
+ QT3DSU8 *target = reinterpret_cast<QT3DSU8 *>(outBuf);
+ target += offset;
+ NVRenderTextureFormats::encodeToPixel(
+ rgbaF32, target, i * NVRenderTextureFormats::getSizeofFormat(inFormat), inFormat);
+ }
+}
+
+static FIBITMAP *DoLoadHDR(FreeImageIO *io, fi_handle handle,
+ NVRenderTextureFormats::Enum inFormat = NVRenderTextureFormats::RGB32F)
+{
+ FIBITMAP *dib = NULL;
+ try {
+ if (handle != NULL) {
+ char str[200];
+ int i;
+
+ // Make sure it's a Radiance RGBE file
+ io->read_proc(str, 10, 1, handle);
+ if (memcmp(str, "#?RADIANCE", 10)) {
+ throw "Invalid HDR file";
+ }
+
+ io->seek_proc(handle, 1, SEEK_CUR);
+
+ // Get the command string (it's not really important for us; We're always assuming
+ // 32bit_rle_rgbe is the format
+ // we're just reading it to skip ahead the correct number of bytes).
+ i = 0;
+ char c = 0, prevC;
+ do {
+ prevC = c;
+ io->read_proc(&c, 1, 1, handle);
+ str[i++] = c;
+ } while (!(c == 0xa && prevC == 0xa));
+
+ // Get the resolution string (it will be NULL-terminated for us)
+ char res[200];
+ i = 0;
+ do {
+ io->read_proc(&c, 1, 1, handle);
+ res[i++] = c;
+ } while (c != 0xa);
+ res[i] = 0;
+
+ int width, height;
+ if (!sscanf(res, "-Y %d +X %d", &height, &width)) {
+ throw "Error encountered while loading HDR stream : could not determine image "
+ "resolution!";
+ }
+ int bytesPerPixel = NVRenderTextureFormats::getSizeofFormat(inFormat);
+ dib = FreeImage_Allocate(width, height, bytesPerPixel * 8, io);
+ if (dib == NULL) {
+ throw "DIB allocation failed";
+ }
+
+ dib->format = inFormat;
+ dib->components = NVRenderTextureFormats::getNumberOfComponent(inFormat);
+
+ // Allocate a scanline worth of RGBE data
+ RGBE *scanline = new RGBE[width];
+ if (!scanline) {
+ throw "Error encountered while loading HDR stream : could not buffer scanlines!";
+ }
+
+ // Go through all the scanlines
+ for (int y = 0; y < height; ++y) {
+ QT3DSU32 byteOfs = (height - 1 - y) * width * bytesPerPixel;
+ decrunchScanline(io, handle, scanline, width);
+ decodeScanlineToTexture(scanline, width, dib->data, byteOfs, inFormat);
+ }
+ }
+ return dib;
+ } catch (const char *message) {
+ if (dib) {
+ FreeImage_Unload(dib);
+ }
+ if (message) {
+ FreeImage_OutputMessageProc(s_format_id, message, io);
+ }
+ }
+
+ return NULL;
+}
+
+SLoadedTexture *SLoadedTexture::LoadHDR(ISeekableIOStream &inStream, NVFoundationBase &inFnd)
+{
+ FreeImageIO theIO(inFnd.getAllocator(), inFnd);
+ SLoadedTexture *retval = DoLoadHDR(&theIO, &inStream, NVRenderTextureFormats::RGBA16F);
+
+ // Let's just assume we don't support this just yet.
+ // if ( retval )
+ // retval->FreeImagePostProcess( inFlipY );
+ return retval;
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.cpp
new file mode 100644
index 00000000..6a2e466c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.cpp
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderPrefilterTexture.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+using namespace uic::render;
+
+UICRenderPrefilterTexture::UICRenderPrefilterTexture(NVRenderContext *inNVRenderContext,
+ QT3DSI32 inWidth, QT3DSI32 inHeight,
+ NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat,
+ NVFoundationBase &inFnd)
+ : m_Foundation(inFnd)
+ , mRefCount(0)
+ , m_Texture2D(inTexture2D)
+ , m_DestinationFormat(inDestFormat)
+ , m_Width(inWidth)
+ , m_Height(inHeight)
+ , m_NVRenderContext(inNVRenderContext)
+{
+ // Calculate mip level
+ int maxDim = inWidth >= inHeight ? inWidth : inHeight;
+
+ m_MaxMipMapLevel = static_cast<int>(logf((float)maxDim) / logf(2.0f));
+ // no concept of sizeOfFormat just does'nt make sense
+ m_SizeOfFormat = NVRenderTextureFormats::getSizeofFormat(m_DestinationFormat);
+ m_NoOfComponent = NVRenderTextureFormats::getNumberOfComponent(m_DestinationFormat);
+}
+
+UICRenderPrefilterTexture *
+UICRenderPrefilterTexture::Create(NVRenderContext *inNVRenderContext, QT3DSI32 inWidth, QT3DSI32 inHeight,
+ NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd)
+{
+ UICRenderPrefilterTexture *theBSDFMipMap = NULL;
+
+ if (inNVRenderContext->IsComputeSupported()) {
+ theBSDFMipMap = QT3DS_NEW(inFnd.getAllocator(), UICRenderPrefilterTextureCompute)(
+ inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd);
+ }
+
+ if (!theBSDFMipMap) {
+ theBSDFMipMap = QT3DS_NEW(inFnd.getAllocator(), UICRenderPrefilterTextureCPU)(
+ inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat, inFnd);
+ }
+
+ if (theBSDFMipMap)
+ theBSDFMipMap->addRef();
+
+ return theBSDFMipMap;
+}
+
+UICRenderPrefilterTexture::~UICRenderPrefilterTexture()
+{
+}
+
+//------------------------------------------------------------------------------------
+// CPU based filtering
+//------------------------------------------------------------------------------------
+
+UICRenderPrefilterTextureCPU::UICRenderPrefilterTextureCPU(
+ NVRenderContext *inNVRenderContext, int inWidth, int inHeight, NVRenderTexture2D &inTexture2D,
+ NVRenderTextureFormats::Enum inDestFormat, NVFoundationBase &inFnd)
+ : UICRenderPrefilterTexture(inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat,
+ inFnd)
+{
+}
+
+inline int UICRenderPrefilterTextureCPU::wrapMod(int a, int base)
+{
+ return (a >= 0) ? a % base : (a % base) + base;
+}
+
+inline void UICRenderPrefilterTextureCPU::getWrappedCoords(int &sX, int &sY, int width, int height)
+{
+ if (sY < 0) {
+ sX -= width >> 1;
+ sY = -sY;
+ }
+ if (sY >= height) {
+ sX += width >> 1;
+ sY = height - sY;
+ }
+ sX = wrapMod(sX, width);
+}
+
+STextureData
+UICRenderPrefilterTextureCPU::CreateBsdfMipLevel(STextureData &inCurMipLevel,
+ STextureData &inPrevMipLevel, int width,
+ int height) //, IPerfTimer& inPerfTimer )
+{
+ STextureData retval;
+ int newWidth = width >> 1;
+ int newHeight = height >> 1;
+ newWidth = newWidth >= 1 ? newWidth : 1;
+ newHeight = newHeight >= 1 ? newHeight : 1;
+
+ if (inCurMipLevel.data) {
+ retval = inCurMipLevel;
+ retval.dataSizeInBytes =
+ newWidth * newHeight * NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
+ } else {
+ retval.dataSizeInBytes =
+ newWidth * newHeight * NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
+ retval.format = inPrevMipLevel.format; // inLoadedImage.format;
+ retval.data = m_Foundation.getAllocator().allocate(
+ retval.dataSizeInBytes, "Bsdf Scaled Image Data", __FILE__, __LINE__);
+ }
+
+ for (int y = 0; y < newHeight; ++y) {
+ for (int x = 0; x < newWidth; ++x) {
+ float accumVal[4];
+ accumVal[0] = 0;
+ accumVal[1] = 0;
+ accumVal[2] = 0;
+ accumVal[3] = 0;
+ for (int sy = -2; sy <= 2; ++sy) {
+ for (int sx = -2; sx <= 2; ++sx) {
+ int sampleX = sx + (x << 1);
+ int sampleY = sy + (y << 1);
+ getWrappedCoords(sampleX, sampleY, width, height);
+
+ // Cauchy filter (this is simply because it's the easiest to evaluate, and
+ // requires no complex
+ // functions).
+ float filterPdf = 1.f / (1.f + float(sx * sx + sy * sy) * 2.f);
+ // With FP HDR formats, we're not worried about intensity loss so much as
+ // unnecessary energy gain,
+ // whereas with LDR formats, the fear with a continuous normalization factor is
+ // that we'd lose
+ // intensity and saturation as well.
+ filterPdf /= (NVRenderTextureFormats::getSizeofFormat(retval.format) >= 8)
+ ? 4.71238898f
+ : 4.5403446f;
+ // filterPdf /= 4.5403446f; // Discrete normalization factor
+ // filterPdf /= 4.71238898f; // Continuous normalization factor
+ float curPix[4];
+ QT3DSI32 byteOffset = (sampleY * width + sampleX)
+ * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ if (byteOffset < 0) {
+ sampleY = height + sampleY;
+ byteOffset = (sampleY * width + sampleX)
+ * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ }
+
+ NVRenderTextureFormats::decodeToFloat(inPrevMipLevel.data, byteOffset, curPix,
+ retval.format);
+
+ accumVal[0] += filterPdf * curPix[0];
+ accumVal[1] += filterPdf * curPix[1];
+ accumVal[2] += filterPdf * curPix[2];
+ accumVal[3] += filterPdf * curPix[3];
+ }
+ }
+
+ QT3DSU32 newIdx =
+ (y * newWidth + x) * NVRenderTextureFormats::getSizeofFormat(retval.format);
+
+ NVRenderTextureFormats::encodeToPixel(accumVal, retval.data, newIdx, retval.format);
+ }
+ }
+
+ return retval;
+}
+
+void UICRenderPrefilterTextureCPU::Build(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat)
+{
+
+ m_InternalFormat = inFormat;
+ m_SizeOfInternalFormat = NVRenderTextureFormats::getSizeofFormat(m_InternalFormat);
+ m_InternalNoOfComponent = NVRenderTextureFormats::getNumberOfComponent(m_InternalFormat);
+
+ m_Texture2D.SetTextureData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
+ m_Width, m_Height, inFormat, m_DestinationFormat);
+
+ STextureData theMipImage;
+ STextureData prevImage;
+ prevImage.data = inTextureData;
+ prevImage.dataSizeInBytes = inTextureDataSize;
+ prevImage.format = inFormat;
+ int curWidth = m_Width;
+ int curHeight = m_Height;
+ int size = NVRenderTextureFormats::getSizeofFormat(m_InternalFormat);
+ for (int idx = 1; idx <= m_MaxMipMapLevel; ++idx) {
+ theMipImage =
+ CreateBsdfMipLevel(theMipImage, prevImage, curWidth, curHeight); //, m_PerfTimer );
+ curWidth = curWidth >> 1;
+ curHeight = curHeight >> 1;
+ curWidth = curWidth >= 1 ? curWidth : 1;
+ curHeight = curHeight >= 1 ? curHeight : 1;
+ inTextureDataSize = curWidth * curHeight * size;
+
+ m_Texture2D.SetTextureData(toU8DataRef((char *)theMipImage.data, (QT3DSU32)inTextureDataSize),
+ (QT3DSU8)idx, (QT3DSU32)curWidth, (QT3DSU32)curHeight, theMipImage.format,
+ m_DestinationFormat);
+
+ if (prevImage.data == inTextureData)
+ prevImage = STextureData();
+
+ STextureData temp = prevImage;
+ prevImage = theMipImage;
+ theMipImage = temp;
+ }
+ QT3DS_FREE(m_Foundation.getAllocator(), theMipImage.data);
+ QT3DS_FREE(m_Foundation.getAllocator(), prevImage.data);
+}
+
+//------------------------------------------------------------------------------------
+// GL compute based filtering
+//------------------------------------------------------------------------------------
+
+static const char *computeUploadShader(std::string &prog, NVRenderTextureFormats::Enum inFormat,
+ bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "precision mediump image2D;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ if (inFormat == NVRenderTextureFormats::RGBA8) {
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (rgba8, binding = 1) readonly uniform image2D inputImage;\n\n"
+ "layout (rgba16f, binding = 2) writeonly uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " if ( gl_GlobalInvocationID.x >= gl_NumWorkGroups.x || gl_GlobalInvocationID.y "
+ ">= gl_NumWorkGroups.y )\n"
+ " return;\n"
+ " vec4 value = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.xy));\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), value );\n"
+ "}\n";
+ } else {
+ prog += "float convertToFloat( in uint inValue )\n"
+ "{\n"
+ " uint v = inValue & uint(0xFF);\n"
+ " float f = float(v)/256.0;\n"
+ " return f;\n"
+ "}\n";
+
+ prog += "int getMod( in int inValue, in int mod )\n"
+ "{\n"
+ " int v = mod * (inValue/mod);\n"
+ " return inValue - v;\n"
+ "}\n";
+
+ prog += "vec4 getRGBValue( in int byteNo, vec4 inVal, vec4 inVal1 )\n"
+ "{\n"
+ " vec4 result= vec4(0.0);\n"
+ " if( byteNo == 0) {\n"
+ " result.r = inVal.r;\n"
+ " result.g = inVal.g;\n"
+ " result.b = inVal.b;\n"
+ " }\n"
+ " else if( byteNo == 1) {\n"
+ " result.r = inVal.g;\n"
+ " result.g = inVal.b;\n"
+ " result.b = inVal.a;\n"
+ " }\n"
+ " else if( byteNo == 2) {\n"
+ " result.r = inVal.b;\n"
+ " result.g = inVal.a;\n"
+ " result.b = inVal1.r;\n"
+ " }\n"
+ " else if( byteNo == 3) {\n"
+ " result.r = inVal.a;\n"
+ " result.g = inVal1.r;\n"
+ " result.b = inVal1.g;\n"
+ " }\n"
+ " return result;\n"
+ "}\n";
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (rgba8, binding = 1) readonly uniform image2D inputImage;\n\n"
+ "layout (rgba16f, binding = 2) writeonly uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " vec4 result = vec4(0.0);\n"
+ " if ( gl_GlobalInvocationID.x >= gl_NumWorkGroups.x || gl_GlobalInvocationID.y "
+ ">= gl_NumWorkGroups.y )\n"
+ " return;\n"
+ " int xpos = (int(gl_GlobalInvocationID.x)*3)/4;\n"
+ " int xmod = getMod(int(gl_GlobalInvocationID.x)*3, 4);\n"
+ " ivec2 readPos = ivec2(xpos, gl_GlobalInvocationID.y);\n"
+ " vec4 value = imageLoad(inputImage, readPos);\n"
+ " vec4 value1 = imageLoad(inputImage, ivec2(readPos.x + 1, readPos.y));\n"
+ " result = getRGBValue( xmod, value, value1);\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), result );\n"
+ "}\n";
+ }
+ return prog.c_str();
+}
+
+static const char *computeWorkShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "precision mediump image2D;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ prog += "int wrapMod( in int a, in int base )\n"
+ "{\n"
+ " return ( a >= 0 ) ? a % base : -(a % base) + base;\n"
+ "}\n";
+
+ prog += "void getWrappedCoords( inout int sX, inout int sY, in int width, in int height )\n"
+ "{\n"
+ " if (sY < 0) { sX -= width >> 1; sY = -sY; }\n"
+ " if (sY >= height) { sX += width >> 1; sY = height - sY; }\n"
+ " sX = wrapMod( sX, width );\n"
+ "}\n";
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (rgba16f, binding = 1) readonly uniform image2D inputImage;\n\n"
+ "layout (rgba16f, binding = 2) writeonly uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " int prevWidth = int(gl_NumWorkGroups.x) << 1;\n"
+ " int prevHeight = int(gl_NumWorkGroups.y) << 1;\n"
+ " if ( gl_GlobalInvocationID.x >= gl_NumWorkGroups.x || gl_GlobalInvocationID.y >= "
+ "gl_NumWorkGroups.y )\n"
+ " return;\n"
+ " vec4 accumVal = vec4(0.0);\n"
+ " for ( int sy = -2; sy <= 2; ++sy )\n"
+ " {\n"
+ " for ( int sx = -2; sx <= 2; ++sx )\n"
+ " {\n"
+ " int sampleX = sx + (int(gl_GlobalInvocationID.x) << 1);\n"
+ " int sampleY = sy + (int(gl_GlobalInvocationID.y) << 1);\n"
+ " getWrappedCoords(sampleX, sampleY, prevWidth, prevHeight);\n"
+ " if ((sampleY * prevWidth + sampleX) < 0 )\n"
+ " sampleY = prevHeight + sampleY;\n"
+ " ivec2 pos = ivec2(sampleX, sampleY);\n"
+ " vec4 value = imageLoad(inputImage, pos);\n"
+ " float filterPdf = 1.0 / ( 1.0 + float(sx*sx + sy*sy)*2.0 );\n"
+ " filterPdf /= 4.71238898;\n"
+ " accumVal[0] += filterPdf * value.r;\n"
+ " accumVal[1] += filterPdf * value.g;\n"
+ " accumVal[2] += filterPdf * value.b;\n"
+ " accumVal[3] += filterPdf * value.a;\n"
+ " }\n"
+ " }\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), accumVal );\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+static bool isGLESContext(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+
+ // Need minimum of GL3 or GLES3
+ if (ctxType == NVRenderContextValues::GLES2 || ctxType == NVRenderContextValues::GLES3
+ || ctxType == NVRenderContextValues::GLES3PLUS) {
+ return true;
+ }
+
+ return false;
+}
+
+#define WORKGROUP_SIZE 16
+
+UICRenderPrefilterTextureCompute::UICRenderPrefilterTextureCompute(
+ NVRenderContext *inNVRenderContext, QT3DSI32 inWidth, QT3DSI32 inHeight,
+ NVRenderTexture2D &inTexture2D, NVRenderTextureFormats::Enum inDestFormat,
+ NVFoundationBase &inFnd)
+ : UICRenderPrefilterTexture(inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat,
+ inFnd)
+ , m_BSDFProgram(NULL)
+ , m_UploadProgram_RGBA8(NULL)
+ , m_UploadProgram_RGB8(NULL)
+ , m_Level0Tex(NULL)
+ , m_TextureCreated(false)
+{
+}
+
+UICRenderPrefilterTextureCompute::~UICRenderPrefilterTextureCompute()
+{
+ m_UploadProgram_RGB8 = NULL;
+ m_UploadProgram_RGBA8 = NULL;
+ m_BSDFProgram = NULL;
+ m_Level0Tex = NULL;
+}
+
+void UICRenderPrefilterTextureCompute::createComputeProgram(NVRenderContext *context)
+{
+ std::string computeProg;
+
+ if (!m_BSDFProgram) {
+ m_BSDFProgram = context
+ ->CompileComputeSource(
+ "Compute BSDF mipmap shader",
+ toRef(computeWorkShader(computeProg, isGLESContext(context))))
+ .mShader;
+ }
+}
+
+NVRenderShaderProgram *UICRenderPrefilterTextureCompute::getOrCreateUploadComputeProgram(
+ NVRenderContext *context, NVRenderTextureFormats::Enum inFormat)
+{
+ std::string computeProg;
+
+ if (inFormat == NVRenderTextureFormats::RGB8) {
+ if (!m_UploadProgram_RGB8) {
+ m_UploadProgram_RGB8 =
+ context
+ ->CompileComputeSource(
+ "Compute BSDF mipmap level 0 RGB8 shader",
+ toRef(computeUploadShader(computeProg, inFormat, isGLESContext(context))))
+ .mShader;
+ }
+
+ return m_UploadProgram_RGB8;
+ } else {
+ if (!m_UploadProgram_RGBA8) {
+ m_UploadProgram_RGBA8 =
+ context
+ ->CompileComputeSource(
+ "Compute BSDF mipmap level 0 RGBA8 shader",
+ toRef(computeUploadShader(computeProg, inFormat, isGLESContext(context))))
+ .mShader;
+ }
+
+ return m_UploadProgram_RGBA8;
+ }
+}
+
+void UICRenderPrefilterTextureCompute::CreateLevel0Tex(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat)
+{
+ NVRenderTextureFormats::Enum theFormat = inFormat;
+ QT3DSI32 theWidth = m_Width;
+
+ // Since we cannot use RGB format in GL compute
+ // we treat it as a RGBA component format
+ if (inFormat == NVRenderTextureFormats::RGB8) {
+ // This works only with 4 byte aligned data
+ QT3DS_ASSERT(m_Width % 4 == 0);
+ theFormat = NVRenderTextureFormats::RGBA8;
+ theWidth = (m_Width * 3) / 4;
+ }
+
+ if (m_Level0Tex == NULL) {
+ m_Level0Tex = m_NVRenderContext->CreateTexture2D();
+ m_Level0Tex->SetTextureStorage(1, theWidth, m_Height, theFormat, theFormat,
+ NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize));
+ } else {
+ m_Level0Tex->SetTextureSubData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
+ 0, 0, theWidth, m_Height, theFormat);
+ }
+}
+
+void UICRenderPrefilterTextureCompute::Build(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat)
+{
+ bool needMipUpload = (inFormat != m_DestinationFormat);
+ // re-upload data
+ if (!m_TextureCreated) {
+ m_Texture2D.SetTextureStorage(
+ m_MaxMipMapLevel + 1, m_Width, m_Height, m_DestinationFormat, inFormat, (needMipUpload)
+ ? NVDataRef<QT3DSU8>()
+ : NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize));
+ m_Texture2D.addRef();
+ // create a compute shader (if not aloread done) which computes the BSDF mipmaps for this
+ // texture
+ createComputeProgram(m_NVRenderContext);
+
+ if (!m_BSDFProgram) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ m_TextureCreated = true;
+ } else if (!needMipUpload) {
+ m_Texture2D.SetTextureSubData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
+ 0, 0, m_Width, m_Height, inFormat);
+ }
+
+ if (needMipUpload) {
+ CreateLevel0Tex(inTextureData, inTextureDataSize, inFormat);
+ }
+
+ NVScopedRefCounted<NVRenderImage2D> theInputImage;
+ NVScopedRefCounted<NVRenderImage2D> theOutputImage;
+ theInputImage =
+ m_NVRenderContext->CreateImage2D(&m_Texture2D, NVRenderImageAccessType::ReadWrite);
+ theOutputImage =
+ m_NVRenderContext->CreateImage2D(&m_Texture2D, NVRenderImageAccessType::ReadWrite);
+
+ if (needMipUpload && m_Level0Tex) {
+ NVRenderShaderProgram *uploadProg =
+ getOrCreateUploadComputeProgram(m_NVRenderContext, inFormat);
+ if (!uploadProg)
+ return;
+
+ m_NVRenderContext->SetActiveShader(uploadProg);
+
+ NVScopedRefCounted<NVRenderImage2D> theInputImage0;
+ theInputImage0 =
+ m_NVRenderContext->CreateImage2D(m_Level0Tex, NVRenderImageAccessType::ReadWrite);
+
+ theInputImage0->SetTextureLevel(0);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedinputImage0("inputImage",
+ *uploadProg);
+ theCachedinputImage0.Set(theInputImage0);
+
+ theOutputImage->SetTextureLevel(0);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedOutputImage("outputImage",
+ *uploadProg);
+ theCachedOutputImage.Set(theOutputImage);
+
+ m_NVRenderContext->DispatchCompute(uploadProg, m_Width, m_Height, 1);
+
+ // sync
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderImageAccess);
+ m_NVRenderContext->SetMemoryBarrier(flags);
+ }
+
+ int width = m_Width >> 1;
+ int height = m_Height >> 1;
+
+ m_NVRenderContext->SetActiveShader(m_BSDFProgram);
+
+ for (int i = 1; i <= m_MaxMipMapLevel; ++i) {
+ theOutputImage->SetTextureLevel(i);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedOutputImage("outputImage",
+ *m_BSDFProgram);
+ theCachedOutputImage.Set(theOutputImage);
+ theInputImage->SetTextureLevel(i - 1);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedinputImage("inputImage",
+ *m_BSDFProgram);
+ theCachedinputImage.Set(theInputImage);
+
+ m_NVRenderContext->DispatchCompute(m_BSDFProgram, width, height, 1);
+
+ width = width > 2 ? width >> 1 : 1;
+ height = height > 2 ? height >> 1 : 1;
+
+ // sync
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderImageAccess);
+ m_NVRenderContext->SetMemoryBarrier(flags);
+ }
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.h
new file mode 100644
index 00000000..fb637ef4
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderPrefilterTexture.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_PREFILTER_TEXTURE_H
+#define UIC_RENDER_PREFILTER_TEXTURE_H
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "UICRender.h"
+
+#include "UICTypes.h"
+#include "UICRenderLoadedTexture.h"
+
+namespace uic {
+namespace render {
+
+ class UICRenderPrefilterTexture : public NVRefCounted
+ {
+ public:
+ UICRenderPrefilterTexture(NVRenderContext *inNVRenderContext, QT3DSI32 inWidth, QT3DSI32 inHeight,
+ NVRenderTexture2D &inTexture,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+ virtual ~UICRenderPrefilterTexture();
+
+ virtual void Build(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat) = 0;
+
+ static UICRenderPrefilterTexture *Create(NVRenderContext *inNVRenderContext, QT3DSI32 inWidth,
+ QT3DSI32 inHeight, NVRenderTexture2D &inTexture,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+
+ protected:
+ NVFoundationBase &m_Foundation; ///< Foundation class for allocations and other base things
+ volatile QT3DSI32 mRefCount; ///< reference count
+
+ NVRenderTexture2D &m_Texture2D;
+ NVRenderTextureFormats::Enum m_InternalFormat;
+ NVRenderTextureFormats::Enum m_DestinationFormat;
+
+ QT3DSI32 m_Width;
+ QT3DSI32 m_Height;
+ QT3DSI32 m_MaxMipMapLevel;
+ QT3DSI32 m_SizeOfFormat;
+ QT3DSI32 m_SizeOfInternalFormat;
+ QT3DSI32 m_InternalNoOfComponent;
+ QT3DSI32 m_NoOfComponent;
+ NVRenderContext *m_NVRenderContext;
+ };
+
+ class UICRenderPrefilterTextureCPU : public UICRenderPrefilterTexture
+ {
+ public:
+ UICRenderPrefilterTextureCPU(NVRenderContext *inNVRenderContext, QT3DSI32 inWidth,
+ QT3DSI32 inHeight, NVRenderTexture2D &inTexture,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+
+ void Build(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat) override;
+
+ STextureData CreateBsdfMipLevel(STextureData &inCurMipLevel, STextureData &inPrevMipLevel,
+ QT3DSI32 width, QT3DSI32 height);
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ int wrapMod(int a, int base);
+ void getWrappedCoords(int &sX, int &sY, int width, int height);
+ };
+
+ class UICRenderPrefilterTextureCompute : public UICRenderPrefilterTexture
+ {
+ public:
+ UICRenderPrefilterTextureCompute(NVRenderContext *inNVRenderContext, QT3DSI32 inWidth,
+ QT3DSI32 inHeight, NVRenderTexture2D &inTexture,
+ NVRenderTextureFormats::Enum inDestFormat,
+ qt3ds::NVFoundationBase &inFnd);
+ ~UICRenderPrefilterTextureCompute();
+
+ void Build(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat) override;
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation)
+
+ private:
+ void CreateLevel0Tex(void *inTextureData, QT3DSI32 inTextureDataSize,
+ NVRenderTextureFormats::Enum inFormat);
+
+ NVScopedRefCounted<NVRenderShaderProgram> m_BSDFProgram;
+ NVScopedRefCounted<NVRenderShaderProgram> m_UploadProgram_RGBA8;
+ NVScopedRefCounted<NVRenderShaderProgram> m_UploadProgram_RGB8;
+ NVScopedRefCounted<NVRenderTexture2D> m_Level0Tex;
+ bool m_TextureCreated;
+
+ void createComputeProgram(NVRenderContext *context);
+ NVRenderShaderProgram *
+ getOrCreateUploadComputeProgram(NVRenderContext *context,
+ NVRenderTextureFormats::Enum inFormat);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.cpp
new file mode 100644
index 00000000..501b82c9
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderResourceBufferObjects.h"
+
+using namespace uic::render;
+
+/*
+ IResourceManager& m_ResourceManager;
+ NVRenderFrameBuffer* m_FrameBuffer;
+ */
+
+CResourceFrameBuffer::CResourceFrameBuffer(IResourceManager &mgr)
+ : m_ResourceManager(mgr)
+ , m_FrameBuffer(NULL)
+{
+}
+
+CResourceFrameBuffer::~CResourceFrameBuffer()
+{
+ ReleaseFrameBuffer();
+}
+
+bool CResourceFrameBuffer::EnsureFrameBuffer()
+{
+ if (!m_FrameBuffer) {
+ m_FrameBuffer = m_ResourceManager.AllocateFrameBuffer();
+ return true;
+ }
+ return false;
+}
+
+void CResourceFrameBuffer::ReleaseFrameBuffer()
+{
+ if (m_FrameBuffer) {
+ m_ResourceManager.Release(*m_FrameBuffer);
+ }
+}
+
+CResourceRenderBuffer::CResourceRenderBuffer(IResourceManager &mgr)
+ : m_ResourceManager(mgr)
+ , m_RenderBuffer(NULL)
+{
+}
+
+CResourceRenderBuffer::~CResourceRenderBuffer()
+{
+ ReleaseRenderBuffer();
+}
+
+bool CResourceRenderBuffer::EnsureRenderBuffer(QT3DSU32 width, QT3DSU32 height,
+ NVRenderRenderBufferFormats::Enum storageFormat)
+{
+ if (m_RenderBuffer == NULL || m_Dimensions.m_Width != width || m_Dimensions.m_Height != height
+ || m_StorageFormat != storageFormat) {
+ if (m_RenderBuffer == NULL || m_StorageFormat != storageFormat) {
+ ReleaseRenderBuffer();
+ m_RenderBuffer = m_ResourceManager.AllocateRenderBuffer(width, height, storageFormat);
+ } else
+ m_RenderBuffer->SetDimensions(
+ qt3ds::render::NVRenderRenderBufferDimensions(width, height));
+ m_Dimensions = m_RenderBuffer->GetDimensions();
+ m_StorageFormat = m_RenderBuffer->GetStorageFormat();
+ return true;
+ }
+ return false;
+}
+
+void CResourceRenderBuffer::ReleaseRenderBuffer()
+{
+ if (m_RenderBuffer) {
+ m_ResourceManager.Release(*m_RenderBuffer);
+ m_RenderBuffer = NULL;
+ }
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.h
new file mode 100644
index 00000000..846cd054
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceBufferObjects.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_RESOURCE_BUFFER_OBJECTS_H
+#define UIC_RENDER_RESOURCE_BUFFER_OBJECTS_H
+#include "UICRender.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderResourceManager.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+
+namespace uic {
+namespace render {
+ class CResourceFrameBuffer
+ {
+ protected:
+ IResourceManager &m_ResourceManager;
+ NVRenderFrameBuffer *m_FrameBuffer;
+
+ public:
+ CResourceFrameBuffer(IResourceManager &mgr);
+ ~CResourceFrameBuffer();
+ bool EnsureFrameBuffer();
+ void ReleaseFrameBuffer();
+
+ IResourceManager &GetResourceManager() { return m_ResourceManager; }
+ operator NVRenderFrameBuffer *() { return m_FrameBuffer; }
+ NVRenderFrameBuffer *operator->()
+ {
+ QT3DS_ASSERT(m_FrameBuffer);
+ return m_FrameBuffer;
+ }
+ NVRenderFrameBuffer &operator*()
+ {
+ QT3DS_ASSERT(m_FrameBuffer);
+ return *m_FrameBuffer;
+ }
+ };
+
+ class CResourceRenderBuffer
+ {
+ protected:
+ IResourceManager &m_ResourceManager;
+ NVRenderRenderBuffer *m_RenderBuffer;
+ qt3ds::render::NVRenderRenderBufferFormats::Enum m_StorageFormat;
+ qt3ds::render::NVRenderRenderBufferDimensions m_Dimensions;
+
+ public:
+ CResourceRenderBuffer(IResourceManager &mgr);
+ ~CResourceRenderBuffer();
+ bool EnsureRenderBuffer(QT3DSU32 width, QT3DSU32 height,
+ NVRenderRenderBufferFormats::Enum storageFormat);
+ void ReleaseRenderBuffer();
+
+ operator NVRenderRenderBuffer *() { return m_RenderBuffer; }
+ NVRenderRenderBuffer *operator->()
+ {
+ QT3DS_ASSERT(m_RenderBuffer);
+ return m_RenderBuffer;
+ }
+ NVRenderRenderBuffer &operator*()
+ {
+ QT3DS_ASSERT(m_RenderBuffer);
+ return *m_RenderBuffer;
+ }
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.cpp
new file mode 100644
index 00000000..b87a60a6
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderResourceManager.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderTexture2DArray.h"
+#include "render/Qt3DSRenderTextureCube.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+
+using namespace uic::render;
+
+namespace {
+
+struct SResourceManager : public IResourceManager
+{
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ // Complete list of all allocated objects
+ nvvector<NVScopedRefCounted<NVRefCounted>> m_AllocatedObjects;
+
+ nvvector<NVRenderFrameBuffer *> m_FreeFrameBuffers;
+ nvvector<NVRenderRenderBuffer *> m_FreeRenderBuffers;
+ nvvector<NVRenderTexture2D *> m_FreeTextures;
+ nvvector<NVRenderTexture2DArray *> m_FreeTexArrays;
+ nvvector<NVRenderTextureCube *> m_FreeTexCubes;
+ nvvector<NVRenderImage2D *> m_FreeImages;
+
+ volatile QT3DSI32 mRefCount;
+
+ SResourceManager(NVRenderContext &ctx)
+ : m_RenderContext(ctx)
+ , m_AllocatedObjects(ctx.GetAllocator(), "SResourceManager::m_FrameBuffers")
+ , m_FreeFrameBuffers(ctx.GetAllocator(), "SResourceManager::m_FreeFrameBuffers")
+ , m_FreeRenderBuffers(ctx.GetAllocator(), "SResourceManager::m_FreeRenderBuffers")
+ , m_FreeTextures(ctx.GetAllocator(), "SResourceManager::m_FreeTextures")
+ , m_FreeTexArrays(ctx.GetAllocator(), "SResourceManager::m_FreeTexArrays")
+ , m_FreeTexCubes(ctx.GetAllocator(), "SResourceManager::m_FreeTexCubes")
+ , m_FreeImages(ctx.GetAllocator(), "SResourceManager::m_FreeImages")
+ , mRefCount(0)
+ {
+ }
+ virtual ~SResourceManager() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext->GetAllocator())
+
+ NVRenderFrameBuffer *AllocateFrameBuffer() override
+ {
+ if (m_FreeFrameBuffers.empty() == true) {
+ NVRenderFrameBuffer *newBuffer = m_RenderContext->CreateFrameBuffer();
+ m_AllocatedObjects.push_back(newBuffer);
+ m_FreeFrameBuffers.push_back(newBuffer);
+ }
+ NVRenderFrameBuffer *retval = m_FreeFrameBuffers.back();
+ m_FreeFrameBuffers.pop_back();
+ return retval;
+ }
+ void Release(NVRenderFrameBuffer &inBuffer) override
+ {
+ if (inBuffer.HasAnyAttachment()) {
+ // Ensure the framebuffer has no attachments.
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color0,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color1,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color2,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color3,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color4,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color5,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color6,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Color7,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Depth,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ inBuffer.Attach(NVRenderFrameBufferAttachments::Stencil,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ if (m_RenderContext->IsDepthStencilSupported())
+ inBuffer.Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ qt3ds::render::NVRenderTextureOrRenderBuffer());
+ }
+#ifdef _DEBUG
+ nvvector<NVRenderFrameBuffer *>::iterator theFind =
+ eastl::find(m_FreeFrameBuffers.begin(), m_FreeFrameBuffers.end(), &inBuffer);
+ QT3DS_ASSERT(theFind == m_FreeFrameBuffers.end());
+#endif
+ m_FreeFrameBuffers.push_back(&inBuffer);
+ }
+
+ virtual NVRenderRenderBuffer *
+ AllocateRenderBuffer(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderRenderBufferFormats::Enum inBufferFormat) override
+ {
+ // Look for one of this specific size and format.
+ QT3DSU32 existingMatchIdx = m_FreeRenderBuffers.size();
+ for (QT3DSU32 idx = 0, end = existingMatchIdx; idx < end; ++idx) {
+ NVRenderRenderBuffer *theBuffer = m_FreeRenderBuffers[idx];
+ qt3ds::render::NVRenderRenderBufferDimensions theDims = theBuffer->GetDimensions();
+ NVRenderRenderBufferFormats::Enum theFormat = theBuffer->GetStorageFormat();
+ if (theDims.m_Width == inWidth && theDims.m_Height == inHeight
+ && theFormat == inBufferFormat) {
+ // Replace idx with last for efficient erasure (that reorders the vector).
+ m_FreeRenderBuffers.replace_with_last(idx);
+ return theBuffer;
+ } else if (theFormat == inBufferFormat)
+ existingMatchIdx = idx;
+ }
+ // If a specific exact match couldn't be found, just use the buffer with
+ // the same format and resize it.
+ if (existingMatchIdx < m_FreeRenderBuffers.size()) {
+ NVRenderRenderBuffer *theBuffer = m_FreeRenderBuffers[existingMatchIdx];
+ m_FreeRenderBuffers.replace_with_last(existingMatchIdx);
+ theBuffer->SetDimensions(qt3ds::render::NVRenderRenderBufferDimensions(inWidth, inHeight));
+ return theBuffer;
+ }
+
+ NVRenderRenderBuffer *theBuffer =
+ m_RenderContext->CreateRenderBuffer(inBufferFormat, inWidth, inHeight);
+ m_AllocatedObjects.push_back(theBuffer);
+ return theBuffer;
+ }
+ void Release(NVRenderRenderBuffer &inBuffer) override
+ {
+#ifdef _DEBUG
+ nvvector<NVRenderRenderBuffer *>::iterator theFind =
+ eastl::find(m_FreeRenderBuffers.begin(), m_FreeRenderBuffers.end(), &inBuffer);
+ QT3DS_ASSERT(theFind == m_FreeRenderBuffers.end());
+#endif
+ m_FreeRenderBuffers.push_back(&inBuffer);
+ }
+ NVRenderTexture2D *SetupAllocatedTexture(NVRenderTexture2D &inTexture)
+ {
+ inTexture.SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ inTexture.SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return &inTexture;
+ }
+ NVRenderTexture2D *AllocateTexture2D(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inTextureFormat,
+ QT3DSU32 inSampleCount, bool immutable) override
+ {
+ bool inMultisample =
+ inSampleCount > 1 && m_RenderContext->AreMultisampleTexturesSupported();
+ for (QT3DSU32 idx = 0, end = m_FreeTextures.size(); idx < end; ++idx) {
+ NVRenderTexture2D *theTexture = m_FreeTextures[idx];
+ STextureDetails theDetails = theTexture->GetTextureDetails();
+ if (theDetails.m_Width == inWidth && theDetails.m_Height == inHeight
+ && inTextureFormat == theDetails.m_Format
+ && theTexture->GetSampleCount() == inSampleCount) {
+ m_FreeTextures.replace_with_last(idx);
+ return SetupAllocatedTexture(*theTexture);
+ }
+ }
+ // else resize an existing texture. This is very expensive
+ // note that MSAA textures are not resizable ( in GLES )
+ /*
+ if ( !m_FreeTextures.empty() && !inMultisample )
+ {
+ NVRenderTexture2D* theTexture = m_FreeTextures.back();
+ m_FreeTextures.pop_back();
+
+ // note we could re-use a former MSAA texture
+ // this causes a entiere destroy of the previous texture object
+ theTexture->SetTextureData( NVDataRef<QT3DSU8>(), 0, inWidth, inHeight, inTextureFormat
+ );
+
+ return SetupAllocatedTexture( *theTexture );
+ }*/
+ // else create a new texture.
+ NVRenderTexture2D *theTexture = m_RenderContext->CreateTexture2D();
+
+ if (inMultisample)
+ theTexture->SetTextureDataMultisample(inSampleCount, inWidth, inHeight,
+ inTextureFormat);
+ else if (immutable)
+ theTexture->SetTextureStorage(1, inWidth, inHeight, inTextureFormat);
+ else
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, inWidth, inHeight, inTextureFormat);
+
+ m_AllocatedObjects.push_back(theTexture);
+ return SetupAllocatedTexture(*theTexture);
+ }
+ void Release(NVRenderTexture2D &inBuffer) override
+ {
+#ifdef _DEBUG
+ nvvector<NVRenderTexture2D *>::iterator theFind =
+ eastl::find(m_FreeTextures.begin(), m_FreeTextures.end(), &inBuffer);
+ QT3DS_ASSERT(theFind == m_FreeTextures.end());
+#endif
+ m_FreeTextures.push_back(&inBuffer);
+ }
+
+ NVRenderTexture2DArray *AllocateTexture2DArray(QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 inSlices,
+ NVRenderTextureFormats::Enum inTextureFormat,
+ QT3DSU32 inSampleCount) override
+ {
+ bool inMultisample =
+ inSampleCount > 1 && m_RenderContext->AreMultisampleTexturesSupported();
+ for (QT3DSU32 idx = 0, end = m_FreeTexArrays.size(); idx < end; ++idx) {
+ NVRenderTexture2DArray *theTexture = m_FreeTexArrays[idx];
+ STextureDetails theDetails = theTexture->GetTextureDetails();
+ if (theDetails.m_Width == inWidth && theDetails.m_Height == inHeight
+ && theDetails.m_Depth == inSlices && inTextureFormat == theDetails.m_Format
+ && theTexture->GetSampleCount() == inSampleCount) {
+ m_FreeTexArrays.replace_with_last(idx);
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return theTexture;
+ }
+ }
+
+ // else resize an existing texture. This should be fairly quick at the driver level.
+ // note that MSAA textures are not resizable ( in GLES )
+ if (!m_FreeTexArrays.empty() && !inMultisample) {
+ NVRenderTexture2DArray *theTexture = m_FreeTexArrays.back();
+ m_FreeTexArrays.pop_back();
+
+ // note we could re-use a former MSAA texture
+ // this causes a entiere destroy of the previous texture object
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, inWidth, inHeight, inSlices,
+ inTextureFormat);
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return theTexture;
+ }
+
+ // else create a new texture.
+ NVRenderTexture2DArray *theTexture = NULL;
+
+ if (!inMultisample) {
+ theTexture = m_RenderContext->CreateTexture2DArray();
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, inWidth, inHeight, inSlices,
+ inTextureFormat);
+ } else {
+ // Not supported yet
+ return NULL;
+ }
+
+ m_AllocatedObjects.push_back(theTexture);
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return theTexture;
+ }
+
+ void Release(NVRenderTexture2DArray &inBuffer) override
+ {
+#ifdef _DEBUG
+ nvvector<NVRenderTexture2DArray *>::iterator theFind =
+ eastl::find(m_FreeTexArrays.begin(), m_FreeTexArrays.end(), &inBuffer);
+ QT3DS_ASSERT(theFind == m_FreeTexArrays.end());
+#endif
+ m_FreeTexArrays.push_back(&inBuffer);
+ }
+
+ NVRenderTextureCube *AllocateTextureCube(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inTextureFormat,
+ QT3DSU32 inSampleCount) override
+ {
+ bool inMultisample =
+ inSampleCount > 1 && m_RenderContext->AreMultisampleTexturesSupported();
+ for (QT3DSU32 idx = 0, end = m_FreeTexCubes.size(); idx < end; ++idx) {
+ NVRenderTextureCube *theTexture = m_FreeTexCubes[idx];
+ STextureDetails theDetails = theTexture->GetTextureDetails();
+ if (theDetails.m_Width == inWidth && theDetails.m_Height == inHeight
+ && inTextureFormat == theDetails.m_Format
+ && theTexture->GetSampleCount() == inSampleCount) {
+ m_FreeTexCubes.replace_with_last(idx);
+
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return theTexture;
+ }
+ }
+
+ // else resize an existing texture. This should be fairly quick at the driver level.
+ // note that MSAA textures are not resizable ( in GLES )
+ if (!m_FreeTexCubes.empty() && !inMultisample) {
+ NVRenderTextureCube *theTexture = m_FreeTexCubes.back();
+ m_FreeTexCubes.pop_back();
+
+ // note we could re-use a former MSAA texture
+ // this causes a entire destroy of the previous texture object
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubePosX,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubeNegX,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubePosY,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubeNegY,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubePosZ,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubeNegZ,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return theTexture;
+ }
+
+ // else create a new texture.
+ NVRenderTextureCube *theTexture = NULL;
+
+ if (!inMultisample) {
+ theTexture = m_RenderContext->CreateTextureCube();
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubePosX,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubeNegX,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubePosY,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubeNegY,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubePosZ,
+ inWidth, inHeight, inTextureFormat);
+ theTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, NVRenderTextureCubeFaces::CubeNegZ,
+ inWidth, inHeight, inTextureFormat);
+ } else {
+ // Not supported yet
+ return NULL;
+ }
+
+ m_AllocatedObjects.push_back(theTexture);
+ theTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ theTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ return theTexture;
+ }
+
+ void Release(NVRenderTextureCube &inBuffer) override
+ {
+#ifdef _DEBUG
+ nvvector<NVRenderTextureCube *>::iterator theFind =
+ eastl::find(m_FreeTexCubes.begin(), m_FreeTexCubes.end(), &inBuffer);
+ QT3DS_ASSERT(theFind == m_FreeTexCubes.end());
+#endif
+ m_FreeTexCubes.push_back(&inBuffer);
+ }
+
+ NVRenderImage2D *AllocateImage2D(NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess) override
+ {
+ if (m_FreeImages.empty() == true) {
+ NVRenderImage2D *newImage = m_RenderContext->CreateImage2D(inTexture, inAccess);
+ if (newImage) {
+ m_AllocatedObjects.push_back(newImage);
+ m_FreeImages.push_back(newImage);
+ }
+ }
+
+ NVRenderImage2D *retval = m_FreeImages.back();
+ m_FreeImages.pop_back();
+
+ return retval;
+ }
+
+ void Release(NVRenderImage2D &inBuffer) override
+ {
+#ifdef _DEBUG
+ nvvector<NVRenderImage2D *>::iterator theFind =
+ eastl::find(m_FreeImages.begin(), m_FreeImages.end(), &inBuffer);
+ QT3DS_ASSERT(theFind == m_FreeImages.end());
+#endif
+ m_FreeImages.push_back(&inBuffer);
+ }
+
+ NVRenderContext &GetRenderContext() override { return *m_RenderContext; }
+
+ void RemoveObjectAllocation(NVRefCounted *obj) {
+ for (QT3DSU32 idx = 0, end = m_AllocatedObjects.size(); idx < end; ++idx) {
+ if (obj == m_AllocatedObjects[idx]) {
+ m_AllocatedObjects.replace_with_last(idx);
+ break;
+ }
+ }
+ }
+
+ void DestroyFreeSizedResources()
+ {
+ for (int idx = m_FreeRenderBuffers.size() - 1; idx >= 0; --idx) {
+ NVRenderRenderBuffer *obj = m_FreeRenderBuffers[idx];
+ m_FreeRenderBuffers.replace_with_last(idx);
+ RemoveObjectAllocation(obj);
+ }
+ for (int idx = m_FreeTextures.size() - 1; idx >= 0; --idx) {
+ NVRenderTexture2D *obj = m_FreeTextures[idx];
+ m_FreeTextures.replace_with_last(idx);
+ RemoveObjectAllocation(obj);
+ }
+ for (int idx = m_FreeTexArrays.size() - 1; idx >= 0; --idx) {
+ NVRenderTexture2DArray *obj = m_FreeTexArrays[idx];
+ m_FreeTexArrays.replace_with_last(idx);
+ RemoveObjectAllocation(obj);
+ }
+ for (int idx = m_FreeTexCubes.size() - 1; idx >= 0; --idx) {
+ NVRenderTextureCube *obj = m_FreeTexCubes[idx];
+ m_FreeTexCubes.replace_with_last(idx);
+ RemoveObjectAllocation(obj);
+ }
+ }
+};
+}
+
+IResourceManager &IResourceManager::CreateResourceManager(NVRenderContext &inContext)
+{
+ return *QT3DS_NEW(inContext.GetAllocator(), SResourceManager)(inContext);
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.h
new file mode 100644
index 00000000..a684bbee
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceManager.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_RESOURCE_MANAGER_H
+#define UIC_RENDER_RESOURCE_MANAGER_H
+#include "UICRender.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+namespace uic {
+namespace render {
+ /**
+ * Implements simple pooling of render resources
+ */
+ class IResourceManager : public NVRefCounted
+ {
+ protected:
+ virtual ~IResourceManager() {}
+
+ public:
+ virtual NVRenderFrameBuffer *AllocateFrameBuffer() = 0;
+ virtual void Release(NVRenderFrameBuffer &inBuffer) = 0;
+ virtual NVRenderRenderBuffer *
+ AllocateRenderBuffer(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderRenderBufferFormats::Enum inBufferFormat) = 0;
+ virtual void Release(NVRenderRenderBuffer &inBuffer) = 0;
+ virtual NVRenderTexture2D *AllocateTexture2D(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inTextureFormat,
+ QT3DSU32 inSampleCount = 1,
+ bool immutable = false) = 0;
+ virtual void Release(NVRenderTexture2D &inBuffer) = 0;
+ virtual NVRenderTexture2DArray *
+ AllocateTexture2DArray(QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 inSlices,
+ NVRenderTextureFormats::Enum inTextureFormat,
+ QT3DSU32 inSampleCount = 1) = 0;
+ virtual void Release(NVRenderTexture2DArray &inBuffer) = 0;
+ virtual NVRenderTextureCube *
+ AllocateTextureCube(QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inTextureFormat,
+ QT3DSU32 inSampleCount = 1) = 0;
+ virtual void Release(NVRenderTextureCube &inBuffer) = 0;
+ virtual NVRenderImage2D *AllocateImage2D(NVRenderTexture2D *inTexture,
+ NVRenderImageAccessType::Enum inAccess) = 0;
+ virtual void Release(NVRenderImage2D &inBuffer) = 0;
+
+ virtual NVRenderContext &GetRenderContext() = 0;
+ virtual void DestroyFreeSizedResources() = 0;
+
+ static IResourceManager &CreateResourceManager(NVRenderContext &inContext);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.cpp b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.cpp
new file mode 100644
index 00000000..228f75c8
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderResourceTexture2D.h"
+
+using namespace uic::render;
+
+CResourceTexture2D::CResourceTexture2D(IResourceManager &mgr, NVRenderTexture2D *inTexture)
+ : m_ResourceManager(mgr)
+ , m_Texture(inTexture)
+{
+ if (inTexture)
+ m_TextureDetails = inTexture->GetTextureDetails();
+}
+
+CResourceTexture2D::CResourceTexture2D(IResourceManager &mgr, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples)
+ : m_ResourceManager(mgr)
+ , m_Texture(NULL)
+{
+ EnsureTexture(width, height, inFormat, inSamples);
+}
+
+CResourceTexture2D::~CResourceTexture2D()
+{
+ ReleaseTexture();
+}
+
+// Returns true if the texture was allocated, false if nothing changed (no allocation).
+bool CResourceTexture2D::TextureMatches(QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples)
+{
+ return m_Texture && m_TextureDetails.m_Width == width && m_TextureDetails.m_Height == height
+ && m_TextureDetails.m_Format == inFormat && m_TextureDetails.m_SampleCount == inSamples;
+}
+
+bool CResourceTexture2D::EnsureTexture(QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples)
+{
+ if (TextureMatches(width, height, inFormat, inSamples))
+ return false;
+
+ if (m_Texture && inSamples > 1) {
+ // we cannot resize MSAA textures though release first
+ ReleaseTexture();
+ }
+
+ if (!m_Texture)
+ m_Texture = m_ResourceManager.AllocateTexture2D(width, height, inFormat, inSamples);
+ else {
+ // multisampled textures are immuteable
+ QT3DS_ASSERT(inSamples == 1);
+ m_Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, width, height, inFormat);
+ }
+
+ m_TextureDetails = m_Texture->GetTextureDetails();
+ return true;
+}
+
+void CResourceTexture2D::ReleaseTexture()
+{
+ if (m_Texture) {
+ m_ResourceManager.Release(*m_Texture);
+ ForgetTexture();
+ }
+}
+
+void CResourceTexture2D::ForgetTexture()
+{
+ m_Texture = NULL;
+}
+
+void CResourceTexture2D::StealTexture(CResourceTexture2D &inOther)
+{
+ ReleaseTexture();
+ m_Texture = inOther.m_Texture;
+ m_TextureDetails = inOther.m_TextureDetails;
+ inOther.m_Texture = NULL;
+}
+
+CResourceTexture2DArray::CResourceTexture2DArray(IResourceManager &mgr)
+ : m_ResourceManager(mgr)
+ , m_Texture(NULL)
+{
+}
+
+CResourceTexture2DArray::CResourceTexture2DArray(IResourceManager &mgr, QT3DSU32 width, QT3DSU32 height,
+ QT3DSU32 slices,
+ NVRenderTextureFormats::Enum inFormat,
+ QT3DSU32 inSamples)
+ : m_ResourceManager(mgr)
+ , m_Texture(NULL)
+{
+ EnsureTexture(width, height, slices, inFormat, inSamples);
+}
+
+CResourceTexture2DArray::~CResourceTexture2DArray()
+{
+ ReleaseTexture();
+}
+
+bool CResourceTexture2DArray::TextureMatches(QT3DSU32 width, QT3DSU32 height, QT3DSU32 slices,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples)
+{
+ return m_Texture && m_TextureDetails.m_Depth == slices && m_TextureDetails.m_Width == width
+ && m_TextureDetails.m_Height == height && m_TextureDetails.m_Format == inFormat
+ && m_TextureDetails.m_SampleCount == inSamples;
+}
+
+bool CResourceTexture2DArray::EnsureTexture(QT3DSU32 width, QT3DSU32 height, QT3DSU32 slices,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples)
+{
+ if (TextureMatches(width, height, slices, inFormat, inSamples))
+ return false;
+
+ if (m_Texture && inSamples > 1) {
+ // we cannot resize MSAA textures though release first
+ ReleaseTexture();
+ }
+
+ if (!m_Texture)
+ m_Texture =
+ m_ResourceManager.AllocateTexture2DArray(width, height, slices, inFormat, inSamples);
+ else {
+ // multisampled textures are immuteable
+ QT3DS_ASSERT(inSamples == 1);
+ m_Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, width, height, slices, inFormat);
+ }
+
+ m_TextureDetails = m_Texture->GetTextureDetails();
+ return true;
+}
+
+void CResourceTexture2DArray::ReleaseTexture()
+{
+ if (m_Texture) {
+ m_ResourceManager.Release(*m_Texture);
+ m_Texture = NULL;
+ }
+}
+
+void CResourceTexture2DArray::StealTexture(CResourceTexture2DArray &inOther)
+{
+ ReleaseTexture();
+ m_Texture = inOther.m_Texture;
+ m_TextureDetails = inOther.m_TextureDetails;
+ inOther.m_Texture = NULL;
+}
diff --git a/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.h b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.h
new file mode 100644
index 00000000..936a5a15
--- /dev/null
+++ b/src/Runtime/Source/UICRender/ResourceManager/UICRenderResourceTexture2D.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_RENDER_RESOURCE_TEXTURE_2D_H
+#define UIC_RENDER_RESOURCE_TEXTURE_2D_H
+#include "UICRender.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderTexture2DArray.h"
+#include "UICRenderResourceManager.h"
+
+namespace uic {
+namespace render {
+ class CResourceTexture2D
+ {
+ protected:
+ IResourceManager &m_ResourceManager;
+ NVRenderTexture2D *m_Texture;
+ STextureDetails m_TextureDetails;
+
+ public:
+ CResourceTexture2D(IResourceManager &mgr, NVRenderTexture2D *inTexture = NULL);
+ // create and allocate the texture right away.
+ CResourceTexture2D(IResourceManager &mgr, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples = 1);
+ ~CResourceTexture2D();
+ // Returns true if the texture matches the specs, false if the texture needs to be
+ // reallocated
+ bool TextureMatches(QT3DSU32 width, QT3DSU32 height, NVRenderTextureFormats::Enum inFormat,
+ QT3DSU32 inSamples = 1);
+
+ // Returns true if the texture was allocated, false if nothing changed (no allocation).
+ // Note this is the exact opposite of TextureMatches.
+ bool EnsureTexture(QT3DSU32 width, QT3DSU32 height, NVRenderTextureFormats::Enum inFormat,
+ QT3DSU32 inSamples = 1);
+
+ // Force release the texture.
+ void ReleaseTexture();
+ NVRenderTexture2D &operator*()
+ {
+ QT3DS_ASSERT(m_Texture);
+ return *m_Texture;
+ }
+ NVRenderTexture2D *operator->()
+ {
+ QT3DS_ASSERT(m_Texture);
+ return m_Texture;
+ }
+ operator NVRenderTexture2D *() { return m_Texture; }
+ NVRenderTexture2D *GetTexture() { return m_Texture; }
+ void ForgetTexture();
+ // Enforces single ownership rules.
+ void StealTexture(CResourceTexture2D &inOther);
+ };
+
+ class CResourceTexture2DArray
+ {
+ protected:
+ IResourceManager &m_ResourceManager;
+ qt3ds::render::NVRenderTexture2DArray *m_Texture;
+ STextureDetails m_TextureDetails;
+
+ public:
+ CResourceTexture2DArray(IResourceManager &mgr);
+ // create and allocate the texture right away.
+ CResourceTexture2DArray(IResourceManager &mgr, QT3DSU32 width, QT3DSU32 height, QT3DSU32 slices,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples = 1);
+ ~CResourceTexture2DArray();
+ // Returns true if the texture matches the specs, false if the texture needs to be
+ // reallocated
+ bool TextureMatches(QT3DSU32 width, QT3DSU32 height, QT3DSU32 slices,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples = 1);
+
+ // Returns true if the texture was allocated, false if nothing changed (no allocation).
+ // Note this is the exact opposite of TextureMatches.
+ bool EnsureTexture(QT3DSU32 width, QT3DSU32 height, QT3DSU32 slices,
+ NVRenderTextureFormats::Enum inFormat, QT3DSU32 inSamples = 1);
+
+ // Force release the texture.
+ void ReleaseTexture();
+ qt3ds::render::NVRenderTexture2DArray &operator*()
+ {
+ QT3DS_ASSERT(m_Texture);
+ return *m_Texture;
+ }
+ qt3ds::render::NVRenderTexture2DArray *operator->()
+ {
+ QT3DS_ASSERT(m_Texture);
+ return m_Texture;
+ }
+ operator qt3ds::render::NVRenderTexture2DArray *() { return m_Texture; }
+ qt3ds::render::NVRenderTexture2DArray *GetTexture() { return m_Texture; }
+ // Enforces single ownership rules.
+ void StealTexture(CResourceTexture2DArray &inOther);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Source/UICOffscreenRenderManager.cpp b/src/Runtime/Source/UICRender/Source/UICOffscreenRenderManager.cpp
new file mode 100644
index 00000000..307086b4
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICOffscreenRenderManager.cpp
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICOffscreenRenderManager.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "foundation/StringTable.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "UICRenderResourceManager.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICTextRenderer.h"
+#include "UICRenderContext.h"
+#include "UICOffscreenRenderKey.h"
+#include "foundation/FastAllocator.h"
+#include "UICRenderRenderList.h"
+#include "UICRenderResourceTexture2D.h"
+#include "UICRenderResourceBufferObjects.h"
+#include "UICRendererUtil.h"
+
+using namespace uic::render;
+
+namespace eastl {
+template <>
+struct hash<SOffscreenRendererKey>
+{
+ size_t operator()(const SOffscreenRendererKey &key) const
+ {
+ switch (key.getType()) {
+ case OffscreenRendererKeyTypes::RegisteredString:
+ return hash<CRegisteredString>()(key.getData<CRegisteredString>());
+ case OffscreenRendererKeyTypes::VoidPtr:
+ return hash<size_t>()(reinterpret_cast<size_t>(key.getData<void *>()));
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ bool operator()(const SOffscreenRendererKey &lhs, const SOffscreenRendererKey &rhs) const
+ {
+ return lhs == rhs;
+ }
+};
+}
+
+namespace {
+
+using eastl::pair;
+using eastl::make_pair;
+
+struct SRendererData : SOffscreenRenderResult
+{
+ NVAllocatorCallback &m_Allocator;
+ IResourceManager &m_ResourceManager;
+ QT3DSU32 m_FrameCount;
+ bool m_Rendering;
+
+ SRendererData(NVAllocatorCallback &inAllocator, IResourceManager &inResourceManager)
+ : m_Allocator(inAllocator)
+ , m_ResourceManager(inResourceManager)
+ , m_FrameCount(QT3DS_MAX_U32)
+ , m_Rendering(false)
+ {
+ }
+ ~SRendererData()
+ {
+ if (m_Texture)
+ m_ResourceManager.Release(*m_Texture);
+ m_Texture = NULL;
+ }
+ void Release() { NVDelete(m_Allocator, this); }
+};
+
+struct SScopedRenderDataRenderMarker
+{
+ SRendererData &m_Data;
+ SScopedRenderDataRenderMarker(SRendererData &d)
+ : m_Data(d)
+ {
+ QT3DS_ASSERT(m_Data.m_Rendering == false);
+ m_Data.m_Rendering = true;
+ }
+ ~SScopedRenderDataRenderMarker() { m_Data.m_Rendering = false; }
+};
+
+struct SRenderDataReleaser
+{
+ SRendererData *mPtr;
+ SRenderDataReleaser(SRendererData *inItem)
+ : mPtr(inItem)
+ {
+ }
+ // Transfer ownership
+ SRenderDataReleaser(const SRenderDataReleaser &inOther)
+ : mPtr(inOther.mPtr)
+ {
+ const_cast<SRenderDataReleaser &>(inOther).mPtr = NULL;
+ }
+
+ ~SRenderDataReleaser()
+ {
+ if (mPtr)
+ mPtr->Release();
+ }
+};
+struct SOffscreenRenderManager;
+
+struct SOffscreenRunnable : public IRenderTask
+{
+ SOffscreenRenderManager &m_RenderManager;
+ SRendererData &m_Data;
+ SOffscreenRendererEnvironment m_DesiredEnvironment;
+ SOffscreenRunnable(SOffscreenRenderManager &rm, SRendererData &data,
+ SOffscreenRendererEnvironment env)
+ : m_RenderManager(rm)
+ , m_Data(data)
+ , m_DesiredEnvironment(env)
+ {
+ }
+ void Run() override;
+};
+
+struct SOffscreenRenderManager : public IOffscreenRenderManager
+{
+ typedef nvhash_map<SOffscreenRendererKey, SRenderDataReleaser> TRendererMap;
+ IUICRenderContext &m_Context;
+ NVAllocatorCallback &m_Allocator;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IResourceManager> m_ResourceManager;
+ TRendererMap m_Renderers;
+ SFastAllocator<> m_PerFrameAllocator;
+ QT3DSU32 m_FrameCount; // cheap per-
+
+ volatile QT3DSI32 mRefCount;
+
+ SOffscreenRenderManager(NVAllocatorCallback &inCallback, IStringTable &inStringTable,
+ IResourceManager &inManager, IUICRenderContext &inContext)
+ : m_Context(inContext)
+ , m_Allocator(inCallback)
+ , m_StringTable(inStringTable)
+ , m_ResourceManager(inManager)
+ , m_Renderers(inCallback, "SOffscreenRenderManager::m_Renderers")
+ , m_PerFrameAllocator(inCallback, "m_PerFrameAllocator")
+ , m_FrameCount(0)
+ , mRefCount(0)
+ {
+ }
+
+ virtual ~SOffscreenRenderManager() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Allocator)
+
+ Option<bool> MaybeRegisterOffscreenRenderer(const SOffscreenRendererKey &inKey,
+ IOffscreenRenderer &inRenderer) override
+ {
+ TRendererMap::iterator theIter = m_Renderers.find(inKey);
+ if (theIter != m_Renderers.end()) {
+ SRendererData &theData = *(theIter->second.mPtr);
+ if (theData.m_Renderer != &inRenderer) {
+ if (inKey.getType() == OffscreenRendererKeyTypes::RegisteredString) {
+ qCCritical(INVALID_OPERATION, "Different renderers registered under same key: %s",
+ inKey.getData<CRegisteredString>().c_str());
+ }
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ return false;
+ }
+ RegisterOffscreenRenderer(inKey, inRenderer);
+ return true;
+ }
+
+ void RegisterOffscreenRenderer(const SOffscreenRendererKey &inKey,
+ IOffscreenRenderer &inRenderer) override
+ {
+ pair<TRendererMap::iterator, bool> theInsert = m_Renderers.insert(
+ make_pair(inKey, QT3DS_NEW(m_Allocator, SRendererData)(m_Allocator, *m_ResourceManager)));
+ QT3DS_ASSERT(theInsert.second);
+ SRendererData &theData = *(theInsert.first->second.mPtr);
+ theData.m_Renderer = &inRenderer;
+ }
+
+ bool HasOffscreenRenderer(const SOffscreenRendererKey &inKey) override
+ {
+ return m_Renderers.find(inKey) != m_Renderers.end();
+ }
+
+ IOffscreenRenderer *GetOffscreenRenderer(const SOffscreenRendererKey &inKey) override
+ {
+ TRendererMap::iterator theRenderer = m_Renderers.find(inKey);
+ if (theRenderer != m_Renderers.end()) {
+ SRendererData &theData = *theRenderer->second.mPtr;
+ return theData.m_Renderer;
+ }
+ return NULL;
+ }
+ void ReleaseOffscreenRenderer(const SOffscreenRendererKey &inKey) override
+ {
+ m_Renderers.erase(inKey);
+ }
+
+ void RenderItem(SRendererData &theData, SOffscreenRendererEnvironment theDesiredEnvironment)
+ {
+ NVRenderContext &theContext = m_ResourceManager->GetRenderContext();
+ QT3DSVec2 thePresScaleFactor = m_Context.GetPresentationScaleFactor();
+ SOffscreenRendererEnvironment theOriginalDesiredEnvironment(theDesiredEnvironment);
+ // Ensure that our overall render context comes back no matter what the client does.
+ qt3ds::render::NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ theContext, &NVRenderContext::GetClearColor, &NVRenderContext::SetClearColor,
+ QT3DSVec4(0, 0, 0, 0));
+ qt3ds::render::NVRenderContextScopedProperty<bool> __scissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled, false);
+ qt3ds::render::NVRenderContextScopedProperty<NVRenderRect> __scissorRect(
+ theContext, &NVRenderContext::GetScissorRect, &NVRenderContext::SetScissorRect);
+ qt3ds::render::NVRenderContextScopedProperty<NVRenderRect> __viewportRect(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport);
+ qt3ds::render::NVRenderContextScopedProperty<bool> __depthWrite(
+ theContext, &NVRenderContext::IsDepthWriteEnabled,
+ &NVRenderContext::SetDepthWriteEnabled, false);
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderBoolOp::Enum> __depthFunction(
+ theContext, &NVRenderContext::GetDepthFunction, &NVRenderContext::SetDepthFunction,
+ qt3ds::render::NVRenderBoolOp::Less);
+ qt3ds::render::NVRenderContextScopedProperty<bool> __blendEnabled(
+ theContext, &NVRenderContext::IsBlendingEnabled, &NVRenderContext::SetBlendingEnabled,
+ false);
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderBlendFunctionArgument>
+ __blendFunction(theContext, &NVRenderContext::GetBlendFunction,
+ &NVRenderContext::SetBlendFunction,
+ qt3ds::render::NVRenderBlendFunctionArgument());
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderBlendEquationArgument>
+ __blendEquation(theContext, &NVRenderContext::GetBlendEquation,
+ &NVRenderContext::SetBlendEquation,
+ qt3ds::render::NVRenderBlendEquationArgument());
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderFrameBufferPtr>
+ __rendertarget(theContext, &NVRenderContext::GetRenderTarget,
+ &NVRenderContext::SetRenderTarget);
+
+ QT3DSU32 theSampleCount = 1;
+ bool isMultisamplePass = false;
+ if (theDesiredEnvironment.m_MSAAMode != AAModeValues::NoAA) {
+ switch (theDesiredEnvironment.m_MSAAMode) {
+ case AAModeValues::SSAA:
+ theSampleCount = 1;
+ isMultisamplePass = true;
+ break;
+ case AAModeValues::X2:
+ theSampleCount = 2;
+ isMultisamplePass = true;
+ break;
+ case AAModeValues::X4:
+ theSampleCount = 4;
+ isMultisamplePass = true;
+ break;
+ case AAModeValues::X8:
+ theSampleCount = 8;
+ isMultisamplePass = true;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ };
+
+ // adjust render size for SSAA
+ if (theDesiredEnvironment.m_MSAAMode == AAModeValues::SSAA) {
+ CRendererUtil::GetSSAARenderSize(
+ theOriginalDesiredEnvironment.m_Width, theOriginalDesiredEnvironment.m_Height,
+ theDesiredEnvironment.m_Width, theDesiredEnvironment.m_Height);
+ }
+ }
+ CResourceFrameBuffer theFrameBuffer(*m_ResourceManager);
+ theFrameBuffer.EnsureFrameBuffer();
+ NVRenderTexture2D *renderTargetTexture(theData.m_Texture);
+ qt3ds::render::NVRenderTextureTargetType::Enum fboAttachmentType =
+ qt3ds::render::NVRenderTextureTargetType::Texture2D;
+ if (isMultisamplePass) {
+ renderTargetTexture = NULL;
+ if (theSampleCount > 1)
+ fboAttachmentType = qt3ds::render::NVRenderTextureTargetType::Texture2D_MS;
+ }
+
+ CResourceTexture2D renderColorTexture(*m_ResourceManager, renderTargetTexture);
+
+ CResourceTexture2D renderDepthStencilTexture(*m_ResourceManager);
+
+ if (theSampleCount > 1)
+ m_Context.GetRenderContext().SetMultisampleEnabled(true);
+
+ qt3ds::render::NVRenderClearFlags theClearFlags;
+ NVRenderTextureFormats::Enum theDepthStencilTextureFormat(NVRenderTextureFormats::Unknown);
+ NVRenderFrameBufferAttachments::Enum theAttachmentLocation(
+ NVRenderFrameBufferAttachments::Unknown);
+ if (theDesiredEnvironment.m_Stencil) {
+ theDepthStencilTextureFormat = NVRenderTextureFormats::Depth24Stencil8;
+ theAttachmentLocation = NVRenderFrameBufferAttachments::DepthStencil;
+ } else if (theDesiredEnvironment.m_Depth != OffscreenRendererDepthValues::NoDepthBuffer) {
+ theAttachmentLocation = NVRenderFrameBufferAttachments::Depth;
+ switch (theDesiredEnvironment.m_Depth) {
+ case OffscreenRendererDepthValues::Depth16:
+ theDepthStencilTextureFormat = NVRenderTextureFormats::Depth16;
+ break;
+ case OffscreenRendererDepthValues::Depth24:
+ theDepthStencilTextureFormat = NVRenderTextureFormats::Depth24;
+ break;
+ case OffscreenRendererDepthValues::Depth32:
+ theDepthStencilTextureFormat = NVRenderTextureFormats::Depth32;
+ break;
+ default:
+ theAttachmentLocation = NVRenderFrameBufferAttachments::Unknown;
+ theDepthStencilTextureFormat = NVRenderTextureFormats::Unknown;
+ break;
+ }
+ }
+ renderColorTexture.EnsureTexture(theDesiredEnvironment.m_Width,
+ theDesiredEnvironment.m_Height,
+ theDesiredEnvironment.m_Format, theSampleCount);
+ theFrameBuffer->Attach(NVRenderFrameBufferAttachments::Color0, *renderColorTexture,
+ fboAttachmentType);
+
+ if (theDepthStencilTextureFormat != NVRenderTextureFormats::Unknown) {
+ renderDepthStencilTexture.EnsureTexture(theDesiredEnvironment.m_Width,
+ theDesiredEnvironment.m_Height,
+ theDepthStencilTextureFormat, theSampleCount);
+ theFrameBuffer->Attach(theAttachmentLocation, *renderDepthStencilTexture,
+ fboAttachmentType);
+ }
+ // IsComplete check takes a really long time so I am not going to worry about it for now.
+
+ theContext.SetRenderTarget(theFrameBuffer);
+ theContext.SetViewport(
+ NVRenderRect(0, 0, theDesiredEnvironment.m_Width, theDesiredEnvironment.m_Height));
+ theContext.SetScissorTestEnabled(false);
+
+ theData.m_Renderer->Render(theDesiredEnvironment, theContext, thePresScaleFactor,
+ SScene::AlwaysClear);
+
+ if (theSampleCount > 1) {
+ CResourceTexture2D theResult(*m_ResourceManager, theData.m_Texture);
+
+ if (theDesiredEnvironment.m_MSAAMode != AAModeValues::SSAA) {
+ // Have to downsample the FBO.
+ CRendererUtil::ResolveMutisampleFBOColorOnly(
+ *m_ResourceManager, theResult, m_Context.GetRenderContext(),
+ theDesiredEnvironment.m_Width, theDesiredEnvironment.m_Height,
+ theDesiredEnvironment.m_Format, *theFrameBuffer);
+
+ m_Context.GetRenderContext().SetMultisampleEnabled(false);
+ } else {
+ // Resolve the FBO to the layer texture
+ CRendererUtil::ResolveSSAAFBOColorOnly(
+ *m_ResourceManager, theResult, theOriginalDesiredEnvironment.m_Width,
+ theOriginalDesiredEnvironment.m_Height, m_Context.GetRenderContext(),
+ theDesiredEnvironment.m_Width, theDesiredEnvironment.m_Height,
+ theDesiredEnvironment.m_Format, *theFrameBuffer);
+ }
+
+ QT3DS_ASSERT(theData.m_Texture == theResult.GetTexture());
+ theResult.ForgetTexture();
+ } else {
+ renderColorTexture.ForgetTexture();
+ }
+ theFrameBuffer->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(), fboAttachmentType);
+ if (theAttachmentLocation != NVRenderFrameBufferAttachments::Unknown)
+ theFrameBuffer->Attach(theAttachmentLocation, NVRenderTextureOrRenderBuffer(),
+ fboAttachmentType);
+ }
+
+ SOffscreenRenderResult GetRenderedItem(const SOffscreenRendererKey &inKey) override
+ {
+ TRendererMap::iterator theRenderer = m_Renderers.find(inKey);
+ QT3DSVec2 thePresScaleFactor = m_Context.GetPresentationScaleFactor();
+ if (theRenderer != m_Renderers.end() && theRenderer->second.mPtr->m_Rendering == false) {
+ SRendererData &theData = *theRenderer->second.mPtr;
+ SScopedRenderDataRenderMarker __renderMarker(theData);
+
+ bool renderedThisFrame = theData.m_Texture && theData.m_FrameCount == m_FrameCount;
+ theData.m_FrameCount = m_FrameCount;
+ // Two different quick-out pathways.
+ if (renderedThisFrame)
+ return theData;
+
+ SOffscreenRendererEnvironment theDesiredEnvironment =
+ theData.m_Renderer->GetDesiredEnvironment(thePresScaleFactor);
+ // Ensure we get a valid width and height
+ theDesiredEnvironment.m_Width =
+ ITextRenderer::NextMultipleOf4(theDesiredEnvironment.m_Width);
+ theDesiredEnvironment.m_Height =
+ ITextRenderer::NextMultipleOf4(theDesiredEnvironment.m_Height);
+ if (theDesiredEnvironment.m_Width == 0 || theDesiredEnvironment.m_Height == 0) {
+ return SOffscreenRenderResult();
+ }
+
+ NVRenderRect theViewport(0, 0, theDesiredEnvironment.m_Width,
+ theDesiredEnvironment.m_Height);
+ IRenderList &theRenderList(m_Context.GetRenderList());
+ NVRenderContext &theContext(m_Context.GetRenderContext());
+ // This happens here because if there are any fancy render steps
+ SRenderListScopedProperty<bool> _scissor(theRenderList,
+ &IRenderList::IsScissorTestEnabled,
+ &IRenderList::SetScissorTestEnabled, false);
+ SRenderListScopedProperty<NVRenderRect> _viewport(
+ theRenderList, &IRenderList::GetViewport, &IRenderList::SetViewport, theViewport);
+ // Some plugins don't use the render list so they need the actual gl context setup.
+ qt3ds::render::NVRenderContextScopedProperty<bool> __scissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled, false);
+ qt3ds::render::NVRenderContextScopedProperty<NVRenderRect> __viewportRect(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport,
+ theViewport);
+
+ QT3DSU32 taskId = m_Context.GetRenderList().AddRenderTask(
+ *QT3DS_NEW(m_Context.GetPerFrameAllocator(),
+ SOffscreenRunnable)(*this, theData, theDesiredEnvironment));
+
+ SOffscreenRenderFlags theFlags =
+ theData.m_Renderer->NeedsRender(theDesiredEnvironment, thePresScaleFactor);
+ theData.m_HasTransparency = theFlags.m_HasTransparency;
+ theData.m_HasChangedSinceLastFrame = theFlags.m_HasChangedSinceLastFrame;
+ if (theData.m_Texture) {
+ // Quick-out if the renderer doesn't need to render itself.
+ if (theData.m_HasChangedSinceLastFrame == false) {
+ m_Context.GetRenderList().DiscardRenderTask(taskId);
+ return theData;
+ }
+ } else
+ theData.m_HasChangedSinceLastFrame = true;
+
+ // Release existing texture if it doesn't match latest environment request.
+ if (theData.m_Texture) {
+ STextureDetails theDetails = theData.m_Texture->GetTextureDetails();
+ if (theDesiredEnvironment.m_Width != theDetails.m_Width
+ || theDesiredEnvironment.m_Height != theDetails.m_Height
+ || theDesiredEnvironment.m_Format != theDetails.m_Format) {
+ m_ResourceManager->Release(*theData.m_Texture);
+ theData.m_Texture = NULL;
+ }
+ }
+
+ if (theData.m_Texture == NULL)
+ theData.m_Texture = m_ResourceManager->AllocateTexture2D(
+ theDesiredEnvironment.m_Width, theDesiredEnvironment.m_Height,
+ theDesiredEnvironment.m_Format);
+
+ // Add the node to the graph and get on with it.
+
+ return theData;
+ }
+ return SOffscreenRenderResult();
+ }
+
+ void BeginFrame() override { m_PerFrameAllocator.reset(); }
+ void EndFrame() override { ++m_FrameCount; }
+};
+
+void SOffscreenRunnable::Run()
+{
+ m_RenderManager.RenderItem(m_Data, m_DesiredEnvironment);
+}
+}
+
+IOffscreenRenderManager &IOffscreenRenderManager::CreateOffscreenRenderManager(
+ NVAllocatorCallback &inCallback, IStringTable &inStringTable, IResourceManager &inManager,
+ IUICRenderContext &inContext)
+{
+ return *QT3DS_NEW(inCallback, SOffscreenRenderManager)(inCallback, inStringTable, inManager,
+ inContext);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICOldNBustedRenderPlugin.cpp b/src/Runtime/Source/UICRender/Source/UICOldNBustedRenderPlugin.cpp
new file mode 100644
index 00000000..11e55faa
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICOldNBustedRenderPlugin.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICOldNBustedRenderPlugin.h"
+#include "SystemPrefix.h"
+#include "UICDLLManager.h"
+#include "render/Qt3DSRenderContext.h"
+
+#ifdef WIN32
+#pragma warning(disable : 4355) // this used in initializer list. I have never seen this result in
+ // a physical error
+#endif
+
+namespace uic {
+namespace render {
+
+ COldNBustedPluginRenderer::COldNBustedPluginRenderer(IUICRenderContext &inRenderContext,
+ long inDLLHandle)
+ : m_RenderContext(inRenderContext)
+ , m_DLLHandle(inDLLHandle)
+ , mRefCount(0)
+ , m_OffscreenRendererType(inRenderContext.GetStringTable().RegisterStr(GetRendererName()))
+ {
+ if (m_DLLHandle != -1) {
+ Q3DStudio::CDLLManager &theManager = Q3DStudio::CDLLManager::GetDLLManager();
+
+ // Grab function procs
+ m_GetTextureSizeProc = reinterpret_cast<PROC_GetDesiredTextureSize>(
+ theManager.GetProc("GetDesiredTextureSize", m_DLLHandle));
+ Q3DStudio_ASSERT(m_GetTextureSizeProc);
+
+ m_RenderProc = reinterpret_cast<PROC_Render>(theManager.GetProc("Render", m_DLLHandle));
+ Q3DStudio_ASSERT(m_RenderProc);
+ }
+ }
+
+ NVRenderTextureFormats::Enum convertTextureFormat(ETEXTUREFORMAT fmt)
+ {
+ NVRenderTextureFormats::Enum ret = NVRenderTextureFormats::RGBA8;
+ switch (fmt) {
+
+ case ETEXTUREFORMAT_RGBA8:
+ break;
+
+ case ETEXTUREFORMAT_RGB8:
+ ret = NVRenderTextureFormats::RGB8;
+ break;
+
+ default:
+ break;
+
+ }
+ return ret;
+ }
+
+ SOffscreenRendererEnvironment
+ COldNBustedPluginRenderer::GetDesiredEnvironment(QT3DSVec2 inPresScale)
+ {
+ long width, height;
+ ETEXTUREFORMAT format;
+
+ m_GetTextureSizeProc(&width, &height, &format);
+
+ return SOffscreenRendererEnvironment(
+ (QT3DSU32)(width * inPresScale.x), (QT3DSU32)(height * inPresScale.y),
+ convertTextureFormat(format), OffscreenRendererDepthValues::Depth24, false,
+ AAModeValues::NoAA);
+ }
+
+ SOffscreenRenderFlags
+ COldNBustedPluginRenderer::NeedsRender(const SOffscreenRendererEnvironment & /*inEnvironment*/,
+ QT3DSVec2 /*inPresScale*/)
+ {
+ return SOffscreenRenderFlags(true, true);
+ }
+
+ // Returns true if the rendered result image has transparency, or false
+ // if it should be treated as a completely opaque image.
+ void COldNBustedPluginRenderer::Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 /*inPresScale*/,
+ SScene::RenderClearCommand /*inClearColorBuffer*/)
+ {
+ inRenderContext.PushPropertySet();
+
+ m_RenderProc(inEnvironment.m_Width, inEnvironment.m_Height, 1);
+
+ inRenderContext.PopPropertySet(true);
+ }
+}
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICOnscreenTextRenderer.cpp b/src/Runtime/Source/UICRender/Source/UICOnscreenTextRenderer.cpp
new file mode 100644
index 00000000..3c42ea5c
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICOnscreenTextRenderer.cpp
@@ -0,0 +1,421 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#define UIC_RENDER_ONSCREEN_TEXT
+#ifdef UIC_RENDER_ONSCREEN_TEXT
+
+#include "UICTextRenderer.h"
+#include "UICRenderTextureAtlas.h"
+
+#include "EASTL/string.h"
+#include "EASTL/hash_set.h"
+
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StrConvertUTF.h"
+
+#include "render/Qt3DSRenderContext.h"
+
+#include <QtGui/qpainter.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qrawfont.h>
+#include <QtCore/qfile.h>
+
+using namespace uic::render;
+
+namespace {
+
+struct STextureAtlasFontEntry
+{
+ STextureAtlasFontEntry()
+ : m_x(0)
+ , m_y(0)
+ , m_width(0)
+ , m_height(0)
+ , m_xOffset(0)
+ , m_yOffset(0)
+ , m_advance(0)
+ , m_s(0)
+ , m_t(0)
+ , m_s1(0)
+ , m_t1(0)
+ {
+ }
+
+ STextureAtlasFontEntry(float x, float y, float width, float height, float xoffset,
+ float yoffset, float advance, float s, float t, float s1, float t1)
+ : m_x(x)
+ , m_y(y)
+ , m_width(width)
+ , m_height(height)
+ , m_xOffset(xoffset)
+ , m_yOffset(yoffset)
+ , m_advance(advance)
+ , m_s(s)
+ , m_t(t)
+ , m_s1(s1)
+ , m_t1(t1)
+ {
+ }
+
+ QT3DSF32 m_x;
+ QT3DSF32 m_y;
+ QT3DSF32 m_width;
+ QT3DSF32 m_height;
+ QT3DSF32 m_xOffset;
+ QT3DSF32 m_yOffset;
+ QT3DSF32 m_advance;
+
+ QT3DSF32 m_s;
+ QT3DSF32 m_t;
+ QT3DSF32 m_s1;
+ QT3DSF32 m_t1;
+};
+
+typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+typedef nvhash_map<wchar_t, STextureAtlasFontEntry> TTextureAtlasMap;
+
+struct STextAtlasFont
+{
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ QT3DSU32 m_FontSize;
+ TTextureAtlasMap m_AtlasEntries; ///< our entries in the atlas
+
+ STextAtlasFont(NVFoundationBase &inFoundation, QT3DSU32 fontSize)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_FontSize(fontSize)
+ , m_AtlasEntries(inFoundation.getAllocator(),
+ "UICOnscreenRenderer::STextAtlasFont::m_AtlasEntrys")
+ {
+ }
+
+ ~STextAtlasFont() { m_AtlasEntries.clear(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ static STextAtlasFont &CreateTextureAtlasFont(NVFoundationBase &inFnd, QT3DSU32 fontSize)
+ {
+ return *QT3DS_NEW(inFnd.getAllocator(), STextAtlasFont)(inFnd, fontSize);
+ }
+};
+
+// This class is only for rendering 2D screen aligned text
+// it uses a predefined true type font and character set with various sizes
+struct UICOnscreenTextRenderer : public ITextRenderer
+{
+
+ static const QT3DSI32 TEXTURE_ATLAS_DIM =
+ 256; // if you change this you need to adjust STextTextureAtlas size as well
+
+private:
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ volatile QT3DSI32 mRefCount;
+ bool m_TextureAtlasInitialized; ///< true if atlas is setup
+ NVScopedRefCounted<ITextureAtlas> m_TextTextureAtlas;
+ NVScopedRefCounted<STextAtlasFont> m_TextFont;
+ QRawFont *m_font;
+public:
+ UICOnscreenTextRenderer(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_TextureAtlasInitialized(false)
+ , m_font(nullptr)
+ {
+ }
+
+ virtual ~UICOnscreenTextRenderer()
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ void AddSystemFontDirectory(const char8_t *) override {}
+
+ virtual void AddProjectFontDirectory(CRegisteredString)
+ {
+ // We always render using the default font with on-screen renderer,
+ // so no need to care about font directories
+ }
+
+ void AddProjectFontDirectory(const char8_t *inProjectDirectory) override
+ {
+ if (m_RenderContext)
+ AddProjectFontDirectory(
+ m_RenderContext->GetStringTable().RegisterStr(inProjectDirectory));
+ }
+
+ void loadFont()
+ {
+ // Ensure font. We can only render text of single size at the moment.
+ // Add a size map of fonts if it ever becomes necessary to render multiple font sizes.
+ if (!m_font)
+ m_font = new QRawFont(QStringLiteral(":res/Font/TitilliumWeb-Regular.ttf"), 20.0);
+
+ // setup texture atlas
+ m_TextTextureAtlas =
+ ITextureAtlas::CreateTextureAtlas(m_RenderContext->GetFoundation(), *m_RenderContext,
+ TEXTURE_ATLAS_DIM, TEXTURE_ATLAS_DIM);
+
+ // our list of predefined cached characters
+ QString cache = QStringLiteral(" !\"#$%&'()*+,-./0123456789:;<=>?"
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmnopqrstuvwxyz{|}~");
+
+ m_TextFont = STextAtlasFont::CreateTextureAtlasFont(m_Foundation, 20);
+ CreateTextureAtlasEntries(m_font, *m_TextFont, cache);
+ m_TextureAtlasInitialized = true;
+ }
+
+ void CreateTextureAtlasEntries(QRawFont *rawFont, STextAtlasFont &font, const QString &cache)
+ {
+ if (m_TextureAtlasInitialized || !m_TextTextureAtlas || !rawFont)
+ return;
+
+ STextureAtlasRect theAtlasRect;
+
+ QVector<quint32> glyphIndices = rawFont->glyphIndexesForString(cache);
+ QVector<QPointF> glyphAdvances = rawFont->advancesForGlyphIndexes(glyphIndices);
+
+ for (int i = 0; i < glyphIndices.size(); i++) {
+ quint32 index = glyphIndices[i];
+ QImage glyphImage;
+
+ // blank char is not contained in a true type font
+ if (cache.at(i) != QChar(' '))
+ glyphImage = rawFont->alphaMapForGlyph(index, QRawFont::PixelAntialiasing);
+
+ QRectF rect = rawFont->boundingRect(index);
+ NVConstDataRef<QT3DSU8> bufferData(static_cast<const QT3DSU8 *>(glyphImage.bits()),
+ glyphImage.byteCount());
+
+ theAtlasRect = m_TextTextureAtlas->AddAtlasEntry(
+ glyphImage.width(), glyphImage.height(),
+ glyphImage.bytesPerLine(), glyphImage.width(), bufferData);
+
+ if (theAtlasRect.m_Width != 0) {
+ font.m_AtlasEntries.insert(
+ eastl::make_pair(
+ cache.at(i).unicode(), STextureAtlasFontEntry(
+ (QT3DSF32)theAtlasRect.m_X, (QT3DSF32)theAtlasRect.m_Y,
+ (QT3DSF32)theAtlasRect.m_Width, (QT3DSF32)theAtlasRect.m_Height,
+ (QT3DSF32)rect.x(), (QT3DSF32)(0.0 - rect.height() - rect.y()),
+ glyphAdvances[i].x(),
+ theAtlasRect.m_NormX, theAtlasRect.m_NormY,
+ theAtlasRect.m_NormX + theAtlasRect.m_NormWidth,
+ theAtlasRect.m_NormY + theAtlasRect.m_NormHeight)));
+ }
+ }
+ }
+
+ void ClearProjectFontDirectories() override {}
+
+ ITextRenderer &GetTextRenderer(NVRenderContext &inRenderContext) override
+ {
+ m_RenderContext = inRenderContext;
+ return *this;
+ }
+
+ void PreloadFonts() override {}
+ void ReloadFonts() override {}
+
+ // unused
+ NVConstDataRef<SRendererFontEntry> GetProjectFontList() override
+ {
+ Q_ASSERT(false);
+ return NVConstDataRef<SRendererFontEntry>();
+ }
+
+ // unused
+ Option<CRegisteredString> GetFontNameForFont(CRegisteredString) override
+ {
+ Q_ASSERT(false);
+ return Empty();
+ }
+
+ // unused
+ Option<CRegisteredString> GetFontNameForFont(const char8_t *) override
+ {
+ Q_ASSERT(false);
+ return Empty();
+ }
+
+ // unused
+ STextDimensions MeasureText(const STextRenderInfo &, QT3DSF32, const char8_t *) override
+ {
+ Q_ASSERT(false);
+ return STextDimensions(0, 0);
+ }
+
+ // unused
+ STextTextureDetails RenderText(const STextRenderInfo &, NVRenderTexture2D &) override
+ {
+ QT3DS_ASSERT(false);
+ return STextTextureDetails();
+ }
+
+ // unused
+ STextTextureDetails RenderText(const STextRenderInfo &, NVRenderPathFontItem &,
+ NVRenderPathFontSpecification &) override
+ {
+ QT3DS_ASSERT(false);
+ return STextTextureDetails();
+ }
+
+ SRenderTextureAtlasDetails RenderText(const STextRenderInfo &inText) override
+ {
+ qt3ds::foundation::IStringTable &theStringTable(m_RenderContext->GetStringTable());
+
+ const wchar_t *wText = theStringTable.GetWideStr(inText.m_Text);
+ QT3DSU32 length = (QT3DSU32)wcslen(wText);
+
+ if (length) {
+ STextAtlasFont *pFont = m_TextFont;
+ const STextureAtlasFontEntry *pEntry;
+ QT3DSF32 x1, y1, x2, y2;
+ QT3DSF32 s, t, s1, t1;
+ QT3DSF32 advance = 0.0;
+ // allocate buffer for all the vertex data we need
+ // we construct triangles here
+ // which means character count x 6 vertices x 5 floats
+ QT3DSF32 *vertexData =
+ (QT3DSF32 *)QT3DS_ALLOC(m_Foundation.getAllocator(),
+ length * 6 * 5 * sizeof(QT3DSF32),
+ "UICOnscreenTextRenderer");
+ QT3DSF32 *bufPtr = vertexData;
+ if (vertexData) {
+ for (size_t i = 0; i < length; ++i) {
+ pEntry = &pFont->m_AtlasEntries.find(wText[i])->second;
+
+ if (pEntry) {
+ x1 = advance + pEntry->m_xOffset;
+ x2 = x1 + pEntry->m_width * inText.m_ScaleX;
+ y1 = pEntry->m_yOffset;
+ y2 = y1 + pEntry->m_height * inText.m_ScaleY;
+
+ s = pEntry->m_s;
+ s1 = pEntry->m_s1;
+ t = pEntry->m_t;
+ t1 = pEntry->m_t1;
+ // store vertex data
+ bufPtr[0] = x1;
+ bufPtr[1] = y1;
+ bufPtr[2] = 0.0;
+ bufPtr[3] = s;
+ bufPtr[4] = t;
+ bufPtr[5] = x2;
+ bufPtr[6] = y1;
+ bufPtr[7] = 0.0;
+ bufPtr[8] = s1;
+ bufPtr[9] = t;
+ bufPtr[10] = x2;
+ bufPtr[11] = y2;
+ bufPtr[12] = 0.0;
+ bufPtr[13] = s1;
+ bufPtr[14] = t1;
+
+ bufPtr[15] = x1;
+ bufPtr[16] = y1;
+ bufPtr[17] = 0.0;
+ bufPtr[18] = s;
+ bufPtr[19] = t;
+ bufPtr[20] = x2;
+ bufPtr[21] = y2;
+ bufPtr[22] = 0.0;
+ bufPtr[23] = s1;
+ bufPtr[24] = t1;
+ bufPtr[25] = x1;
+ bufPtr[26] = y2;
+ bufPtr[27] = 0.0;
+ bufPtr[28] = s;
+ bufPtr[29] = t1;
+
+ advance += pEntry->m_advance * inText.m_ScaleX;
+
+ bufPtr += 30;
+ }
+ }
+
+ m_TextTextureAtlas->RelaseEntries();
+
+ return SRenderTextureAtlasDetails(length * 6,
+ toU8DataRef(vertexData, length * 6 * 5));
+ }
+ }
+
+ return SRenderTextureAtlasDetails();
+ }
+
+ STextTextureAtlasEntryDetails RenderAtlasEntry(QT3DSU32 index,
+ NVRenderTexture2D &inTexture) override
+ {
+ if (m_TextTextureAtlas) {
+ TTextureAtlasEntryAndBuffer theEntry = m_TextTextureAtlas->GetAtlasEntryByIndex(index);
+ if (theEntry.first.m_Width) {
+ inTexture.SetTextureData(theEntry.second, 0, theEntry.first.m_Width,
+ theEntry.first.m_Height, NVRenderTextureFormats::Alpha8);
+ inTexture.SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ inTexture.SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ inTexture.SetTextureWrapS(qt3ds::render::NVRenderTextureCoordOp::ClampToEdge);
+ inTexture.SetTextureWrapT(qt3ds::render::NVRenderTextureCoordOp::ClampToEdge);
+ STextureDetails theTextureDetails = inTexture.GetTextureDetails();
+ return STextTextureAtlasEntryDetails(theTextureDetails.m_Width,
+ theTextureDetails.m_Height, theEntry.first.m_X,
+ theEntry.first.m_Y);
+ }
+ }
+
+ return STextTextureAtlasEntryDetails();
+ }
+ QT3DSI32 CreateTextureAtlas() override
+ {
+ loadFont();
+
+ QT3DSI32 count = 0;
+ if (m_TextTextureAtlas)
+ count = m_TextTextureAtlas->GetAtlasEntryCount();
+
+ return count;
+ }
+
+ void BeginFrame() override {}
+ void EndFrame() override {}
+ void BeginPreloadFonts(IThreadPool &, IPerfTimer &) override {}
+ void EndPreloadFonts() override {}
+};
+}
+
+ITextRendererCore &ITextRendererCore::CreateOnscreenTextRenderer(NVFoundationBase &inFnd)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), UICOnscreenTextRenderer)(inFnd);
+}
+
+#endif // UIC_RENDER_ONSCREEN_TEXT
diff --git a/src/Runtime/Source/UICRender/Source/UICQtTextRenderer.cpp b/src/Runtime/Source/UICRender/Source/UICQtTextRenderer.cpp
new file mode 100644
index 00000000..2696ed11
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICQtTextRenderer.cpp
@@ -0,0 +1,609 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICTextRenderer.h"
+#include "UICRenderText.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/FileTools.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderThreadPool.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "EASTL/set.h"
+#include "EASTL/list.h"
+
+#include <QPainter>
+#include <QImage>
+#include <QFontDatabase>
+#include <QDir>
+#include <QDebug>
+#include <QHash>
+#include <QGuiApplication>
+#include <QtMath>
+#include <QRawFont>
+
+using namespace uic::render;
+
+namespace {
+
+struct UICQtTextRenderer : public ITextRenderer
+{
+ struct FontInfo
+ {
+ QString fontFileName;
+ QString fontName;
+ QString fontFamily;
+ int fontId;
+ QFont font;
+
+ FontInfo() :
+ fontId(-1)
+ {}
+
+ FontInfo(const QString &fileName, const QString &name, const QString &family, int id) :
+ fontFileName(fileName)
+ , fontName(name)
+ , fontFamily(family)
+ , fontId(id)
+ {
+ font.setFamily(fontFamily);
+ }
+
+ FontInfo(const FontInfo &other) :
+ fontFileName(other.fontFileName)
+ , fontName(other.fontName)
+ , fontFamily(other.fontFamily)
+ , fontId(other.fontId)
+ , font(other.font)
+ {}
+
+ FontInfo &operator=(const FontInfo &other)
+ {
+ fontFileName = other.fontFileName;
+ fontName = other.fontName;
+ fontFamily = other.fontFamily;
+ fontId = other.fontId;
+ font = other.font;
+
+ return *this;
+ }
+ };
+
+ typedef eastl::string TStrType;
+ typedef eastl::set<TStrType> TStringSet;
+ typedef QHash<QString, FontInfo> TFontInfoHash;
+
+ NVFoundationBase &m_foundation;
+ NVScopedRefCounted<IStringTable> m_stringTable;
+ NVScopedRefCounted<NVRenderContext> m_renderContext;
+ NVScopedRefCounted<IPerfTimer> m_perfTimer;
+ volatile QT3DSI32 mRefCount;
+ nvvector<SRendererFontEntry> m_installedFonts;
+
+ Sync m_PreloadSync;
+
+ TStringSet m_systemFontDirs;
+ TStringSet m_projectFontDirs;
+ TFontInfoHash m_projectFontInfos;
+ TFontInfoHash m_systemFontInfos;
+ TStrType m_workspace;
+
+ bool m_systemFontsInitialized;
+ bool m_projectFontsInitialized;
+ bool m_PreloadingFonts;
+
+ QStringList m_nameFilters;
+ qreal m_pixelRatio;
+
+ UICQtTextRenderer(NVFoundationBase &inFoundation, IStringTable &inStrTable)
+ : m_foundation(inFoundation)
+ , m_stringTable(inStrTable)
+ , mRefCount(0)
+ , m_installedFonts(inFoundation.getAllocator(), "UICQtTextRenderer::m_installedFonts")
+ , m_PreloadSync(inFoundation.getAllocator())
+ , m_systemFontsInitialized(false)
+ , m_projectFontsInitialized(false)
+ , m_PreloadingFonts(false)
+ , m_pixelRatio(1.0)
+ {
+ const QWindowList list = QGuiApplication::topLevelWindows();
+ if (list.size() > 0)
+ m_pixelRatio = list[0]->devicePixelRatio();
+
+ m_nameFilters << QStringLiteral("*.ttf");
+ m_nameFilters << QStringLiteral("*.otf");
+ }
+ virtual ~UICQtTextRenderer()
+ {
+ QFontDatabase::removeAllApplicationFonts();
+ }
+
+ QString stringToQString(const CRegisteredString &str)
+ {
+ return QString::fromUtf8(str.c_str());
+ }
+
+ QString stringToQString(const eastl::string &str)
+ {
+ return QString::fromUtf8(str.c_str());
+ }
+
+ QString stringToQString(const char8_t *str)
+ {
+ return QString::fromUtf8(str);
+ }
+
+ CRegisteredString QStringToRegisteredString(const QString &str)
+ {
+ return m_stringTable->RegisterStr(str.toUtf8().constData());
+ }
+
+ void unregisterProjectFonts()
+ {
+ for (FontInfo &fi : m_projectFontInfos.values())
+ QFontDatabase::removeApplicationFont(fi.fontId);
+ m_projectFontsInitialized = false;
+ m_installedFonts.clear();
+ m_projectFontInfos.clear();
+ }
+
+ QString getFileStem(const QString &fileName)
+ {
+ QString retVal;
+ int dotPos = fileName.lastIndexOf(QChar('.'));
+ if (dotPos < 0)
+ return retVal;
+ int slashPos = fileName.lastIndexOf(QChar('/'));
+ retVal = fileName.mid(slashPos + 1);
+ retVal.chop(fileName.length() - dotPos);
+ return retVal;
+ }
+
+ void registerFonts(TStringSet dirSet, TFontInfoHash *fontInfos = nullptr)
+ {
+ for (TStringSet::const_iterator theIter = dirSet.begin(),
+ theEnd = dirSet.end();
+ theIter != theEnd; ++theIter) {
+ QString localDir = CFileTools::NormalizePathForQtUsage(stringToQString(*theIter));
+ QDir dir(localDir);
+ if (!dir.exists()) {
+ qCCritical(INTERNAL_ERROR) << "Adding font directory:" << localDir;
+ continue;
+ }
+ if (fontInfos)
+ dir.cd(QStringLiteral("fonts"));
+ QStringList entryList = dir.entryList(m_nameFilters);
+ for (QString entry : entryList) {
+ entry = dir.absoluteFilePath(entry);
+ QFile file(entry);
+ if (file.open(QIODevice::ReadOnly)) {
+ QByteArray rawData = file.readAll();
+ int fontId = QFontDatabase::addApplicationFontFromData(rawData);
+ if (fontId < 0) {
+ qCWarning(WARNING, "Failed to register font: %s",
+ entry.toStdString().c_str());
+ } else if (fontInfos) {
+ QString fontName = getFileStem(entry);
+ QString fontFamily;
+ QStringList families = QFontDatabase::applicationFontFamilies(fontId);
+ if (families.size() > 0)
+ fontFamily = families.at(0);
+ FontInfo fi(entry, fontName, fontFamily, fontId);
+ // Detect font style and weight using a dummy QRawFont
+ QRawFont rawFont(rawData, 1.0);
+ if (rawFont.isValid()) {
+ fi.font.setStyle(rawFont.style());
+ fi.font.setWeight(rawFont.weight());
+ } else {
+ qCWarning(WARNING, "Failed to determine font style: %s",
+ entry.toStdString().c_str());
+ }
+ fontInfos->insert(fontName, fi);
+ }
+ } else {
+ qCWarning(WARNING, "Failed to load font: %s",
+ entry.toStdString().c_str());
+ }
+ }
+ }
+ }
+
+ void projectCleanup()
+ {
+ m_projectFontsInitialized = false;
+ unregisterProjectFonts();
+ m_projectFontDirs.clear();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_foundation.getAllocator())
+
+ eastl::pair<TStrType, bool> AddFontDirectory(const TStrType &inDirectory, TStringSet &inDirSet)
+ {
+ if (inDirectory.empty()) {
+ m_workspace.assign("./");
+ } else {
+ m_workspace.clear();
+ for (const char8_t *item = inDirectory.c_str(); item && *item; ++item) {
+ if (*item == '\\')
+ m_workspace.append(1, '/');
+ else
+ m_workspace.append(1, static_cast<char8_t>(*item));
+ }
+ if (m_workspace.back() != '/')
+ m_workspace.append(1, '/');
+ }
+
+ return eastl::make_pair(m_workspace, inDirSet.insert(m_workspace).second);
+ }
+
+ // You can have several standard font directories and these will be persistent
+ void AddSystemFontDirectory(const char8_t *inDirectory) override
+ {
+ AddFontDirectory(inDirectory, m_systemFontDirs);
+ }
+
+ void AddProjectFontDirectory(const char8_t *inProjectDirectory) override
+ {
+ eastl::pair<TStrType, bool> theAddResult =
+ AddFontDirectory(inProjectDirectory, m_projectFontDirs);
+ if (theAddResult.second && m_projectFontsInitialized)
+ ReloadFonts();
+ }
+
+ void ReloadFonts() override
+ {
+ unregisterProjectFonts();
+ PreloadFonts();
+ }
+
+ void PreloadFonts() override
+ {
+ if (!m_systemFontsInitialized) {
+ m_systemFontsInitialized = true;
+ registerFonts(m_systemFontDirs, &m_systemFontInfos);
+ }
+
+ if (!m_projectFontsInitialized) {
+ m_projectFontsInitialized = true;
+ registerFonts(m_projectFontDirs, &m_projectFontInfos);
+ }
+ }
+
+ void ClearProjectFontDirectories() override
+ {
+ projectCleanup();
+ }
+
+ static void PreloadThreadCallback(void *inData)
+ {
+ UICQtTextRenderer *theRenderer(reinterpret_cast<UICQtTextRenderer *>(inData));
+ theRenderer->PreloadFonts();
+ theRenderer->m_PreloadSync.set();
+ }
+
+ void BeginPreloadFonts(IThreadPool &inThreadPool, IPerfTimer &inTimer) override
+ {
+ m_PreloadingFonts = true;
+
+ m_PreloadSync.reset();
+ m_perfTimer = inTimer;
+
+ inThreadPool.AddTask(this, PreloadThreadCallback, NULL);
+ }
+
+ void EndPreloadFonts() override
+ {
+ if (m_PreloadingFonts) {
+ {
+ SStackPerfTimer __perfTimer(*m_perfTimer, "QtText: Wait till font preloading completed");
+ m_PreloadSync.wait();
+ }
+ }
+ m_PreloadingFonts = false;
+ }
+
+ // Get the list of project fonts. These are the only fonts that can be displayed.
+ NVConstDataRef<SRendererFontEntry> GetProjectFontList() override
+ {
+ PreloadFonts();
+ if (m_installedFonts.empty()) {
+ m_installedFonts.reserve(m_projectFontInfos.size());
+ for (FontInfo &fi : m_projectFontInfos.values()) {
+ m_installedFonts.push_back(SRendererFontEntry(
+ QStringToRegisteredString(fi.fontName),
+ QStringToRegisteredString(fi.fontFileName)));
+ }
+ }
+ return m_installedFonts;
+ }
+
+ Option<CRegisteredString> GetFontNameForFont(CRegisteredString inFontname) override
+ {
+ // This function is there to support legacy font names.
+
+ QString inStr = stringToQString(inFontname);
+ if (m_projectFontInfos.keys().contains(inStr))
+ return inFontname;
+
+ // Fall back for family name detection if not found by font name
+ for (FontInfo &fi : m_projectFontInfos.values()) {
+ if (inStr == fi.fontFamily)
+ return QStringToRegisteredString(fi.fontName);
+ }
+
+ return Empty();
+ }
+
+ Option<CRegisteredString> GetFontNameForFont(const char8_t *inFontname) override
+ {
+ return GetFontNameForFont(m_stringTable->RegisterStr(inFontname));
+ }
+
+ ITextRenderer &GetTextRenderer(NVRenderContext &inRenderContext) override
+ {
+ m_renderContext = inRenderContext;
+ return *this;
+ }
+
+ FontInfo &fontInfoForName(const CRegisteredString &fontName)
+ {
+ PreloadFonts();
+ QString qtFontName = stringToQString(fontName);
+ if (m_projectFontInfos.contains(qtFontName))
+ return m_projectFontInfos[qtFontName];
+
+ if (m_systemFontInfos.contains(qtFontName))
+ return m_systemFontInfos[qtFontName];
+
+ // Unknown font, create a system font for it
+ FontInfo fi("", qtFontName, qtFontName, -1);
+ m_systemFontInfos.insert(qtFontName, fi);
+
+ return m_systemFontInfos[qtFontName];
+ }
+
+ void updateFontInfo(FontInfo &fi, const STextRenderInfo &inText,
+ QT3DSF32 inTextScaleFactor = 1.0f)
+ {
+ fi.font.setPointSizeF(inText.m_FontSize * inTextScaleFactor);
+ fi.font.setLetterSpacing(QFont::AbsoluteSpacing, qreal(inText.m_Tracking));
+ }
+
+ QStringList splitText(const char8_t *theText)
+ {
+ // Split the text into lines
+ int lines = 1;
+ int lineLen = 0;
+ QStringList lineList;
+ const char8_t *lineStartItem = nullptr;
+ for (const char8_t *item = theText; item && *item; ++item) {
+ if (!lineLen)
+ lineStartItem = item;
+ ++lineLen;
+ if (*item == '\n') {
+ int chopAmount = 1;
+ if (lineLen > 1 && *(item - 1) == '\r')
+ ++chopAmount;
+
+ ++lines;
+ lineList.append(QString::fromUtf8(lineStartItem, lineLen - chopAmount));
+ lineLen = 0;
+ }
+ }
+ if (lineStartItem)
+ lineList.append(QString::fromUtf8(lineStartItem, lineLen));
+
+ return lineList;
+ }
+
+ QRectF textBoundingBox(const STextRenderInfo &inText,
+ const QFontMetricsF &fm, QStringList &lineList,
+ QVector<qreal> &lineWidths, const char8_t *inTextOverride = nullptr)
+ {
+ const char8_t *theText = inTextOverride ? inTextOverride : inText.m_Text.c_str();
+ lineList = splitText(theText);
+
+ QRectF boundingBox;
+ boundingBox.setHeight(lineList.size() * fm.height() + qCeil(qreal(lineList.size() - 1) * qreal(inText.m_Leading)));
+
+ lineWidths.resize(lineList.size());
+
+ for (int i = 0; i < lineList.size(); ++i) {
+ // For italicized fonts the bounding box right is the correct method
+ // to measure since the left offset may extend, but for
+ // non-italicized fonts we need the width method to meausure
+ // otherwise the resultant text will be clipped.
+ QString line = lineList.at(i);
+ qreal width = fm.width(line);
+ qreal right = fm.boundingRect(line).right();
+ // For hdpi displays, fontmetrics doesn't always calculate enough space for fonts, so
+ // we add the pixel ratio to all widths to avoid clipping
+ qreal lineWidth = qMax(width, right) + m_pixelRatio;
+ lineWidths[i] = lineWidth;
+ if (boundingBox.width() < lineWidth)
+ boundingBox.setWidth(lineWidth);
+ }
+
+ // We don't want extra letter spacing on the last glyph, so let's remove it
+ boundingBox.setRight(qMax(boundingBox.left(), boundingBox.right() - qFloor(inText.m_Tracking)));
+
+ return boundingBox;
+ }
+
+ STextDimensions MeasureText(const STextRenderInfo &inText, QT3DSF32 inTextScaleFactor,
+ const char8_t *inTextOverride) override
+ {
+ FontInfo &fi = fontInfoForName(inText.m_Font);
+ updateFontInfo(fi, inText, inTextScaleFactor);
+ QFontMetricsF fm(fi.font);
+ QStringList dummyList;
+ QVector<qreal> dummyWidth;
+ QRectF boundingBox = textBoundingBox(inText, fm, dummyList, dummyWidth, inTextOverride);
+ return STextDimensions(boundingBox.width(), boundingBox.height());
+ }
+
+ int alignToQtAlign(TextVerticalAlignment::Enum va)
+ {
+ int qtAlign(0);
+ switch (va) {
+ case TextVerticalAlignment::Top:
+ qtAlign = Qt::AlignTop;
+ break;
+ case TextVerticalAlignment::Bottom:
+ qtAlign = Qt::AlignBottom;
+ break;
+ default:
+ qtAlign = Qt::AlignVCenter;
+ }
+
+ return qtAlign;
+ }
+
+ // The system will use the 'r' channel as an alpha mask in order to render the text.
+ STextTextureDetails RenderText(const STextRenderInfo &inSrcText,
+ NVRenderTexture2D &inTexture) override
+ {
+ FontInfo &fi = fontInfoForName(inSrcText.m_Font);
+ updateFontInfo(fi, inSrcText);
+ QFontMetricsF fm(fi.font);
+
+ QStringList lineList;
+ QVector<qreal> lineWidths;
+ QRectF boundingBox = textBoundingBox(inSrcText, fm, lineList, lineWidths);
+
+ if (boundingBox.width() <= 0 || boundingBox.height() <= 0) {
+ return ITextRenderer::UploadData(toU8DataRef((char *)NULL, 0), inTexture, 4, 4,
+ 0, 0,
+ NVRenderTextureFormats::RGBA8, true);
+ }
+
+ int finalWidth = NextMultipleOf4(boundingBox.width());
+ int finalHeight = NextMultipleOf4(boundingBox.height());
+
+ QImage image(finalWidth, finalHeight, QImage::Format_Grayscale8);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setPen(Qt::white);
+ painter.setFont(fi.font);
+
+ // Translate painter to remove the extra spacing of the last letter
+ qreal tracking = 0.0;
+ switch (inSrcText.m_HorizontalAlignment) {
+ case TextHorizontalAlignment::Center:
+ tracking += qreal(inSrcText.m_Tracking / 2.0f);
+ break;
+ case TextHorizontalAlignment::Right:
+ tracking += qreal(inSrcText.m_Tracking);
+ break;
+ default:
+ break; // Do nothing
+ }
+
+ int lineHeight = fm.height();
+ QT3DSF32 nextHeight = 0;
+ for (int i = 0; i < lineList.size(); ++i) {
+ const QString &line = lineList.at(i);
+ qreal xTranslation = tracking;
+ switch (inSrcText.m_HorizontalAlignment) {
+ case TextHorizontalAlignment::Center:
+ xTranslation += qreal(boundingBox.width() - lineWidths.at(i)) / 2.0;
+ break;
+ case TextHorizontalAlignment::Right:
+ xTranslation += qreal(boundingBox.width() - lineWidths.at(i));
+ break;
+ default:
+ break; // Do nothing
+ }
+ QRectF bound(xTranslation, qreal(nextHeight), lineWidths.at(i), lineHeight);
+ QRectF actualBound;
+ painter.drawText(bound,
+ alignToQtAlign(inSrcText.m_VerticalAlignment) |
+ Qt::TextDontClip | Qt::AlignLeft, line, &actualBound);
+
+ nextHeight += QT3DSF32(lineHeight) + inSrcText.m_Leading;
+ }
+
+ return ITextRenderer::UploadData(toU8DataRef(image.bits(), image.byteCount()), inTexture,
+ image.width(), image.height(), image.width(), image.height(),
+ NVRenderTextureFormats::Luminance8, true);
+
+ }
+
+ STextTextureDetails RenderText(const STextRenderInfo &inText,
+ NVRenderPathFontItem &inPathFontItem,
+ NVRenderPathFontSpecification &inFontPathSpec) override
+ {
+ Q_UNUSED(inText);
+ Q_UNUSED(inPathFontItem);
+ Q_UNUSED(inFontPathSpec);
+ QT3DS_ASSERT(m_renderContext->IsPathRenderingSupported());
+
+ // We do not support HW accelerated fonts (yet?)
+ QT3DS_ASSERT(false);
+
+ return STextTextureDetails();
+ }
+
+ void BeginFrame() override
+ {
+ // Nothing to do
+ }
+
+ void EndFrame() override
+ {
+ // Nothing to do
+ }
+
+ // unused for text rendering via texture atlas
+ STextTextureAtlasEntryDetails RenderAtlasEntry(QT3DSU32, NVRenderTexture2D &) override
+ {
+ return STextTextureAtlasEntryDetails();
+ }
+ QT3DSI32 CreateTextureAtlas() override
+ {
+ return 0;
+ }
+ SRenderTextureAtlasDetails RenderText(const STextRenderInfo &) override
+ {
+ return SRenderTextureAtlasDetails();
+ }
+};
+}
+
+ITextRendererCore &ITextRendererCore::CreateQtTextRenderer(NVFoundationBase &inFnd,
+ IStringTable &inStrTable)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), UICQtTextRenderer)(inFnd, inStrTable);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderClippingFrustum.cpp b/src/Runtime/Source/UICRender/Source/UICRenderClippingFrustum.cpp
new file mode 100644
index 00000000..b0328619
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderClippingFrustum.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderClippingFrustum.h"
+
+using namespace uic::render;
+
+SClippingFrustum::SClippingFrustum(const QT3DSMat44 &modelviewprojection, SClipPlane nearPlane)
+{
+ SClipPlane *_cullingPlanes = mPlanes;
+ const QT3DSMat44 &modelViewProjectionMat(modelviewprojection);
+ const QT3DSF32 *modelviewProjection = modelViewProjectionMat.front();
+
+// update planes (http://read.pudn.com/downloads128/doc/542641/Frustum.pdf)
+// Google for Gribb plane extraction if that link doesn't work.
+// http://www.google.com/search?q=ravensoft+plane+extraction
+#define M(_x, _y) modelviewProjection[(4 * (_y)) + (_x)]
+ // left plane
+ _cullingPlanes[0].normal.x = M(3, 0) + M(0, 0);
+ _cullingPlanes[0].normal.y = M(3, 1) + M(0, 1);
+ _cullingPlanes[0].normal.z = M(3, 2) + M(0, 2);
+ _cullingPlanes[0].d = M(3, 3) + M(0, 3);
+ _cullingPlanes[0].d /= _cullingPlanes[0].normal.normalize();
+
+ // right plane
+ _cullingPlanes[1].normal.x = M(3, 0) - M(0, 0);
+ _cullingPlanes[1].normal.y = M(3, 1) - M(0, 1);
+ _cullingPlanes[1].normal.z = M(3, 2) - M(0, 2);
+ _cullingPlanes[1].d = M(3, 3) - M(0, 3);
+ _cullingPlanes[1].d /= _cullingPlanes[1].normal.normalize();
+
+ // far plane
+ _cullingPlanes[2].normal.x = M(3, 0) - M(2, 0);
+ _cullingPlanes[2].normal.y = M(3, 1) - M(2, 1);
+ _cullingPlanes[2].normal.z = M(3, 2) - M(2, 2);
+ _cullingPlanes[2].d = M(3, 3) - M(2, 3);
+ _cullingPlanes[2].d /= _cullingPlanes[2].normal.normalize();
+
+ // bottom plane
+ _cullingPlanes[3].normal.x = M(3, 0) + M(1, 0);
+ _cullingPlanes[3].normal.y = M(3, 1) + M(1, 1);
+ _cullingPlanes[3].normal.z = M(3, 2) + M(1, 2);
+ _cullingPlanes[3].d = M(3, 3) + M(1, 3);
+ _cullingPlanes[3].d /= _cullingPlanes[3].normal.normalize();
+
+ // top plane
+ _cullingPlanes[4].normal.x = M(3, 0) - M(1, 0);
+ _cullingPlanes[4].normal.y = M(3, 1) - M(1, 1);
+ _cullingPlanes[4].normal.z = M(3, 2) - M(1, 2);
+ _cullingPlanes[4].d = M(3, 3) - M(1, 3);
+ _cullingPlanes[4].d /= _cullingPlanes[4].normal.normalize();
+#undef M
+ _cullingPlanes[5] = nearPlane;
+ // http://www.openscenegraph.org/projects/osg/browser/OpenSceneGraph/trunk/include/osg/Plane?rev=5328
+ // setup the edges of the plane that we will clip against an axis-aligned bounding box.
+ for (QT3DSU32 idx = 0; idx < 6; ++idx) {
+ _cullingPlanes[idx].calculateBBoxEdges();
+ }
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderContext.cpp b/src/Runtime/Source/UICRender/Source/UICRenderContext.cpp
new file mode 100644
index 00000000..d0442450
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderContext.cpp
@@ -0,0 +1,928 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRender.h"
+#include "EABase/eabase.h" //char16_t definition
+#include "UICRenderContext.h"
+#include "foundation/StringTable.h"
+#include "UICRenderNode.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderer.h"
+#include "UICRenderResourceManager.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICOffscreenRenderManager.h"
+#include "UICTextRenderer.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderEffectSystem.h"
+#include "UICRenderShaderCache.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderRenderBuffer.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "UICRenderCamera.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderThreadPool.h"
+#include "UICRenderImageBatchLoader.h"
+#include "UICRenderTextTextureCache.h"
+#include "UICRenderTextTextureAtlas.h"
+#include "UICRenderPlugin.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderPixelGraphicsRenderer.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "UICRenderBufferLoader.h"
+#include "foundation/FastAllocator.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "UICRenderRenderList.h"
+#include "UICRenderPathManager.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+#include "UICRenderCustomMaterialShaderGenerator.h"
+
+using namespace uic::render;
+
+namespace {
+
+struct SRenderContextCore : public IUICRenderContextCore
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IPerfTimer> m_PerfTimer;
+ NVScopedRefCounted<IInputStreamFactory> m_InputStreamFactory;
+ NVScopedRefCounted<IThreadPool> m_ThreadPool;
+ NVScopedRefCounted<IDynamicObjectSystemCore> m_DynamicObjectSystem;
+ NVScopedRefCounted<ICustomMaterialSystemCore> m_MaterialSystem;
+ NVScopedRefCounted<IEffectSystemCore> m_EffectSystem;
+ NVScopedRefCounted<IBufferLoader> m_BufferLoader;
+ NVScopedRefCounted<IRenderPluginManagerCore> m_RenderPluginManagerCore;
+ NVScopedRefCounted<ITextRendererCore> m_TextRenderer;
+ NVScopedRefCounted<ITextRendererCore> m_OnscreenTexRenderer;
+ NVScopedRefCounted<IPathManagerCore> m_PathManagerCore;
+
+ QT3DSI32 mRefCount;
+ SRenderContextCore(NVFoundationBase &fnd, IStringTable &strTable)
+ : m_Foundation(fnd)
+ , m_StringTable(strTable)
+ , m_PerfTimer(IPerfTimer::CreatePerfTimer(fnd))
+ , m_InputStreamFactory(IInputStreamFactory::Create(fnd))
+ , m_ThreadPool(IThreadPool::CreateThreadPool(fnd, 4))
+ , mRefCount(0)
+ {
+ m_DynamicObjectSystem = IDynamicObjectSystemCore::CreateDynamicSystemCore(*this);
+ m_MaterialSystem = ICustomMaterialSystemCore::CreateCustomMaterialSystemCore(*this);
+ m_EffectSystem = IEffectSystemCore::CreateEffectSystemCore(*this);
+ m_RenderPluginManagerCore =
+ IRenderPluginManagerCore::Create(fnd, strTable, *m_InputStreamFactory);
+ m_BufferLoader = IBufferLoader::Create(m_Foundation, *m_InputStreamFactory, *m_ThreadPool);
+ m_PathManagerCore = IPathManagerCore::CreatePathManagerCore(*this);
+ }
+
+ virtual ~SRenderContextCore() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ IStringTable &GetStringTable() override { return *m_StringTable; }
+ NVFoundationBase &GetFoundation() override { return m_Foundation; }
+ NVAllocatorCallback &GetAllocator() override { return m_Foundation.getAllocator(); }
+ IInputStreamFactory &GetInputStreamFactory() override { return *m_InputStreamFactory; }
+ IThreadPool &GetThreadPool() override { return *m_ThreadPool; }
+ IDynamicObjectSystemCore &GetDynamicObjectSystemCore() override
+ {
+ return *m_DynamicObjectSystem;
+ }
+ ICustomMaterialSystemCore &GetMaterialSystemCore() override { return *m_MaterialSystem; }
+ IEffectSystemCore &GetEffectSystemCore() override { return *m_EffectSystem; }
+ IPerfTimer &GetPerfTimer() override { return *m_PerfTimer; }
+ IBufferLoader &GetBufferLoader() override { return *m_BufferLoader; }
+ IRenderPluginManagerCore &GetRenderPluginCore() override { return *m_RenderPluginManagerCore; }
+ IPathManagerCore &GetPathManagerCore() override { return *m_PathManagerCore; }
+ IUICRenderContext &CreateRenderContext(NVRenderContext &inContext,
+ const char8_t *inPrimitivesDirectory) override;
+ void SetTextRendererCore(ITextRendererCore &inRenderer) override { m_TextRenderer = inRenderer; }
+ ITextRendererCore *GetTextRendererCore() override { return m_TextRenderer.mPtr; }
+ void SetOnscreenTextRendererCore(ITextRendererCore &inRenderer) override
+ {
+ m_OnscreenTexRenderer = inRenderer;
+ }
+ ITextRendererCore *GetOnscreenTextRendererCore() override { return m_OnscreenTexRenderer.mPtr; }
+};
+
+inline float Clamp(float val, float inMin = 0.0f, float inMax = 1.0f)
+{
+ if (val < inMin)
+ return inMin;
+ if (val > inMax)
+ return inMax;
+ return val;
+}
+
+struct SPerFrameAllocator : public NVAllocatorCallback
+{
+ SFastAllocator<> m_FastAllocator;
+ SSAutoDeallocatorAllocator m_LargeAllocator;
+
+ SPerFrameAllocator(NVAllocatorCallback &baseAllocator)
+ : m_FastAllocator(baseAllocator, "PerFrameAllocation")
+ , m_LargeAllocator(baseAllocator)
+ {
+ }
+
+ inline void *allocate(size_t inSize, const char *inFile, int inLine)
+ {
+ if (inSize < 8192)
+ return m_FastAllocator.allocate(inSize, "PerFrameAllocation", inFile, inLine, 0);
+ else
+ return m_LargeAllocator.allocate(inSize, "PerFrameAllocation", inFile, inLine, 0);
+ }
+
+ inline void *allocate(size_t inSize, const char *inFile, int inLine, int, int)
+ {
+ if (inSize < 8192)
+ return m_FastAllocator.allocate(inSize, "PerFrameAllocation", inFile, inLine, 0);
+ else
+ return m_LargeAllocator.allocate(inSize, "PerFrameAllocation", inFile, inLine, 0);
+ }
+
+ inline void deallocate(void *, size_t) {}
+
+ void reset()
+ {
+ m_FastAllocator.reset();
+ m_LargeAllocator.deallocateAllAllocations();
+ }
+
+ void *allocate(size_t inSize, const char *typeName, const char *inFile, int inLine,
+ int flags = 0) override
+ {
+ if (inSize < SFastAllocator<>::SlabSize)
+ return m_FastAllocator.allocate(inSize, typeName, inFile, inLine, flags);
+ else
+ return m_LargeAllocator.allocate(inSize, typeName, inFile, inLine, flags);
+ }
+
+ void *allocate(size_t inSize, const char *typeName, const char *inFile, int inLine,
+ size_t alignment, size_t alignmentOffset) override
+ {
+ if (inSize < SFastAllocator<>::SlabSize)
+ return m_FastAllocator.allocate(inSize, typeName, inFile, inLine, alignment,
+ alignmentOffset);
+ else
+ return m_LargeAllocator.allocate(inSize, typeName, inFile, inLine, alignment,
+ alignmentOffset);
+ }
+
+ void deallocate(void *) override {}
+};
+
+struct SRenderContext : public IUICRenderContext
+{
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ NVScopedRefCounted<IUICRenderContextCore> m_CoreContext;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IPerfTimer> m_PerfTimer;
+ NVScopedRefCounted<IInputStreamFactory> m_InputStreamFactory;
+ NVScopedRefCounted<IBufferManager> m_BufferManager;
+ NVScopedRefCounted<IResourceManager> m_ResourceManager;
+ NVScopedRefCounted<IOffscreenRenderManager> m_OffscreenRenderManager;
+ NVScopedRefCounted<IUICRenderer> m_Renderer;
+ NVScopedRefCounted<ITextRenderer> m_TextRenderer;
+ NVScopedRefCounted<ITextRenderer> m_OnscreenTextRenderer;
+ NVScopedRefCounted<ITextTextureCache> m_TextTextureCache;
+ NVScopedRefCounted<ITextTextureAtlas> m_TextTextureAtlas;
+ NVScopedRefCounted<IDynamicObjectSystem> m_DynamicObjectSystem;
+ NVScopedRefCounted<IEffectSystem> m_EffectSystem;
+ NVScopedRefCounted<IShaderCache> m_ShaderCache;
+ NVScopedRefCounted<IThreadPool> m_ThreadPool;
+ NVScopedRefCounted<IImageBatchLoader> m_ImageBatchLoader;
+ NVScopedRefCounted<IRenderPluginManager> m_RenderPluginManager;
+ NVScopedRefCounted<ICustomMaterialSystem> m_CustomMaterialSystem;
+ NVScopedRefCounted<IPixelGraphicsRenderer> m_PixelGraphicsRenderer;
+ NVScopedRefCounted<IPathManager> m_PathManager;
+ NVScopedRefCounted<IShaderProgramGenerator> m_ShaderProgramGenerator;
+ NVScopedRefCounted<IDefaultMaterialShaderGenerator> m_DefaultMaterialShaderGenerator;
+ NVScopedRefCounted<ICustomMaterialShaderGenerator> m_CustomMaterialShaderGenerator;
+ SPerFrameAllocator m_PerFrameAllocator;
+ NVScopedRefCounted<IRenderList> m_RenderList;
+ QT3DSU32 m_FrameCount;
+ volatile QT3DSI32 mRefCount;
+ // Viewport that this render context should use
+ Option<NVRenderRect> m_Viewport;
+ SWindowDimensions m_WindowDimensions;
+ ScaleModes::Enum m_ScaleMode;
+ bool m_WireframeMode;
+ bool m_IsInSubPresentation;
+ Option<QT3DSVec4> m_SceneColor;
+ Option<QT3DSVec4> m_MatteColor;
+ RenderRotationValues::Enum m_Rotation;
+ NVScopedRefCounted<NVRenderFrameBuffer> m_RotationFBO;
+ NVScopedRefCounted<NVRenderTexture2D> m_RotationTexture;
+ NVScopedRefCounted<NVRenderRenderBuffer> m_RotationDepthBuffer;
+ NVRenderFrameBuffer *m_ContextRenderTarget;
+ NVRenderRect m_PresentationViewport;
+ SWindowDimensions m_PresentationDimensions;
+ SWindowDimensions m_RenderPresentationDimensions;
+ SWindowDimensions m_PreRenderPresentationDimensions;
+ QT3DSVec2 m_PresentationScale;
+ NVRenderRect m_VirtualViewport;
+ NVScopedRefCounted<NVRenderTexture2D> m_Watermark;
+ QT3DSVec2 m_WatermarkLocation;
+ QPair<QT3DSF32, int> m_FPS;
+ bool m_AuthoringMode;
+
+ SRenderContext(NVRenderContext &ctx, IUICRenderContextCore &inCore,
+ const char8_t *inApplicationDirectory)
+ : m_RenderContext(ctx)
+ , m_CoreContext(inCore)
+ , m_StringTable(ctx.GetStringTable())
+ , m_PerfTimer(inCore.GetPerfTimer())
+ , m_InputStreamFactory(inCore.GetInputStreamFactory())
+ , m_BufferManager(
+ IBufferManager::Create(ctx, *m_StringTable, *m_InputStreamFactory, *m_PerfTimer))
+ , m_ResourceManager(IResourceManager::CreateResourceManager(ctx))
+ , m_ShaderCache(IShaderCache::CreateShaderCache(ctx, *m_InputStreamFactory, *m_PerfTimer))
+ , m_ThreadPool(inCore.GetThreadPool())
+ , m_RenderList(IRenderList::CreateRenderList(ctx.GetFoundation()))
+ , m_PerFrameAllocator(ctx.GetAllocator())
+ , m_FrameCount(0)
+ , mRefCount(0)
+ , m_WindowDimensions(800, 480)
+ , m_ScaleMode(ScaleModes::ExactSize)
+ , m_WireframeMode(false)
+ , m_IsInSubPresentation(false)
+ , m_Rotation(RenderRotationValues::NoRotation)
+ , m_ContextRenderTarget(NULL)
+ , m_PresentationScale(0, 0)
+ , m_WatermarkLocation(1, 1)
+ , m_FPS(qMakePair(0.0, 0))
+ , m_AuthoringMode(false)
+ {
+ m_OffscreenRenderManager = IOffscreenRenderManager::CreateOffscreenRenderManager(
+ ctx.GetAllocator(), *m_StringTable, *m_ResourceManager, *this);
+ m_Renderer = IUICRenderer::CreateRenderer(*this);
+ if (inApplicationDirectory && *inApplicationDirectory)
+ m_InputStreamFactory->AddSearchDirectory(inApplicationDirectory);
+
+ m_ImageBatchLoader =
+ IImageBatchLoader::CreateBatchLoader(ctx.GetFoundation(), *m_InputStreamFactory,
+ *m_BufferManager, *m_ThreadPool, *m_PerfTimer);
+ m_RenderPluginManager = inCore.GetRenderPluginCore().GetRenderPluginManager(ctx);
+ m_DynamicObjectSystem = inCore.GetDynamicObjectSystemCore().CreateDynamicSystem(*this);
+ m_EffectSystem = inCore.GetEffectSystemCore().GetEffectSystem(*this);
+ m_CustomMaterialSystem = inCore.GetMaterialSystemCore().GetCustomMaterialSystem(*this);
+ // as does the custom material system
+ m_PixelGraphicsRenderer = IPixelGraphicsRenderer::CreateRenderer(*this, *m_StringTable);
+ ITextRendererCore *theTextCore = inCore.GetTextRendererCore();
+ m_ShaderProgramGenerator = IShaderProgramGenerator::CreateProgramGenerator(*this);
+ m_DefaultMaterialShaderGenerator =
+ IDefaultMaterialShaderGenerator::CreateDefaultMaterialShaderGenerator(*this);
+ m_CustomMaterialShaderGenerator =
+ ICustomMaterialShaderGenerator::CreateCustomMaterialShaderGenerator(*this);
+ if (theTextCore) {
+ m_TextRenderer = theTextCore->GetTextRenderer(ctx);
+ m_TextTextureCache = ITextTextureCache::CreateTextureCache(
+ m_RenderContext->GetFoundation(), *m_TextRenderer, *m_RenderContext);
+ }
+
+ ITextRendererCore *theOnscreenTextCore = inCore.GetOnscreenTextRendererCore();
+ if (theOnscreenTextCore) {
+ m_OnscreenTextRenderer = theOnscreenTextCore->GetTextRenderer(ctx);
+ m_TextTextureAtlas = ITextTextureAtlas::CreateTextureAtlas(
+ m_RenderContext->GetFoundation(), *m_OnscreenTextRenderer, *m_RenderContext);
+ }
+ m_PathManager = inCore.GetPathManagerCore().OnRenderSystemInitialize(*this);
+
+ QString versionString;
+ switch ((QT3DSU32)ctx.GetRenderContextType()) {
+ case NVRenderContextValues::GLES2:
+ versionString = QLatin1Literal("gles2");
+ break;
+ case NVRenderContextValues::GL2:
+ versionString = QLatin1Literal("gl2");
+ break;
+ case NVRenderContextValues::GLES3:
+ versionString = QLatin1Literal("gles3");
+ break;
+ case NVRenderContextValues::GL3:
+ versionString = QLatin1Literal("gl3");
+ break;
+ case NVRenderContextValues::GLES3PLUS:
+ versionString = QLatin1Literal("gles3x");
+ break;
+ case NVRenderContextValues::GL4:
+ versionString = QLatin1Literal("gl4");
+ break;
+ default:
+ break;
+ }
+
+ GetDynamicObjectSystem().setShaderCodeLibraryVersion(versionString);
+#if defined (QT3DS_SHADER_PLATFORM_LIBRARY_DIR)
+ const QString platformDirectory;
+#if defined(_WIN32)
+ platformDirectory = QStringLiteral("res\\platform\\win");
+#elif defined(_LINUX)
+ platformDirectory = QStringLiteral("res\\platform\\linux");
+#elif defined(_MACOSX)
+ platformDirectory = QStringLiteral("res\\platform\\macos");
+#endif
+ GetDynamicObjectSystem().setShaderCodeLibraryPlatformDirectory(platformDirectory);
+#endif
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext->GetAllocator());
+
+ IStringTable &GetStringTable() override { return *m_StringTable; }
+ NVFoundationBase &GetFoundation() override { return m_RenderContext->GetFoundation(); }
+ NVAllocatorCallback &GetAllocator() override { return m_RenderContext->GetAllocator(); }
+ IUICRenderer &GetRenderer() override { return *m_Renderer; }
+ IBufferManager &GetBufferManager() override { return *m_BufferManager; }
+ IResourceManager &GetResourceManager() override { return *m_ResourceManager; }
+ NVRenderContext &GetRenderContext() override { return *m_RenderContext; }
+ IOffscreenRenderManager &GetOffscreenRenderManager() override
+ {
+ return *m_OffscreenRenderManager;
+ }
+ IInputStreamFactory &GetInputStreamFactory() override { return *m_InputStreamFactory; }
+ IEffectSystem &GetEffectSystem() override { return *m_EffectSystem; }
+ IShaderCache &GetShaderCache() override { return *m_ShaderCache; }
+ IThreadPool &GetThreadPool() override { return *m_ThreadPool; }
+ IImageBatchLoader &GetImageBatchLoader() override { return *m_ImageBatchLoader; }
+ ITextTextureCache *GetTextureCache() override { return m_TextTextureCache.mPtr; }
+ ITextTextureAtlas *GetTextureAtlas() override { return m_TextTextureAtlas.mPtr; }
+ IRenderPluginManager &GetRenderPluginManager() override { return *m_RenderPluginManager; }
+ IDynamicObjectSystem &GetDynamicObjectSystem() override { return *m_DynamicObjectSystem; }
+ ICustomMaterialSystem &GetCustomMaterialSystem() override { return *m_CustomMaterialSystem; }
+ IPixelGraphicsRenderer &GetPixelGraphicsRenderer() override { return *m_PixelGraphicsRenderer; }
+ IPerfTimer &GetPerfTimer() override { return *m_PerfTimer; }
+ IRenderList &GetRenderList() override { return *m_RenderList; }
+ IPathManager &GetPathManager() override { return *m_PathManager; }
+ IShaderProgramGenerator &GetShaderProgramGenerator() override
+ {
+ return *m_ShaderProgramGenerator;
+ }
+ IDefaultMaterialShaderGenerator &GetDefaultMaterialShaderGenerator() override
+ {
+ return *m_DefaultMaterialShaderGenerator;
+ }
+ ICustomMaterialShaderGenerator &GetCustomMaterialShaderGenerator() override
+ {
+ return *m_CustomMaterialShaderGenerator;
+ }
+ NVAllocatorCallback &GetPerFrameAllocator() override { return m_PerFrameAllocator; }
+
+ QT3DSU32 GetFrameCount() override { return m_FrameCount; }
+ void SetFPS(QPair<QT3DSF32, int> inFPS) override { m_FPS = inFPS; }
+ QPair<QT3DSF32, int> GetFPS(void) override { return m_FPS; }
+
+ bool IsAuthoringMode() override { return m_AuthoringMode; }
+ void SetAuthoringMode(bool inMode) override { m_AuthoringMode = inMode; }
+
+ bool IsInSubPresentation() override { return m_IsInSubPresentation; }
+ void SetInSubPresentation(bool inValue) override { m_IsInSubPresentation = inValue; }
+
+ ITextRenderer *GetTextRenderer() override { return m_TextRenderer; }
+
+ ITextRenderer *GetOnscreenTextRenderer() override { return m_OnscreenTextRenderer; }
+
+ void SetSceneColor(Option<QT3DSVec4> inSceneColor) override { m_SceneColor = inSceneColor; }
+ void SetMatteColor(Option<QT3DSVec4> inMatteColor) override { m_MatteColor = inMatteColor; }
+
+ void SetWindowDimensions(const SWindowDimensions &inWindowDimensions) override
+ {
+ m_WindowDimensions = inWindowDimensions;
+ }
+
+ SWindowDimensions GetWindowDimensions() override { return m_WindowDimensions; }
+
+ void SetScaleMode(ScaleModes::Enum inMode) override { m_ScaleMode = inMode; }
+
+ ScaleModes::Enum GetScaleMode() override { return m_ScaleMode; }
+
+ void SetWireframeMode(bool inEnable) override { m_WireframeMode = inEnable; }
+
+ bool GetWireframeMode() override { return m_WireframeMode; }
+
+ void SetWatermark(NVRenderTexture2D &inTexture) override
+ {
+ qCInfo(TRACE_INFO, "UICContext -- Setting watermark texture");
+ m_Watermark = inTexture;
+ }
+
+ void SetWatermarkLocation(QT3DSVec2 inLocation) override
+ {
+ m_WatermarkLocation = QT3DSVec2(Clamp(inLocation.x), Clamp(inLocation.y));
+ }
+
+ void SetViewport(Option<NVRenderRect> inViewport) override { m_Viewport = inViewport; }
+ Option<NVRenderRect> GetViewport() const override { return m_Viewport; }
+
+ eastl::pair<NVRenderRect, NVRenderRect> GetPresentationViewportAndOuterViewport() const
+ {
+ SWindowDimensions thePresentationDimensions(m_PresentationDimensions);
+ NVRenderRect theOuterViewport(GetContextViewport());
+ if (m_Rotation == RenderRotationValues::Clockwise90
+ || m_Rotation == RenderRotationValues::Clockwise270) {
+ eastl::swap(theOuterViewport.m_Width, theOuterViewport.m_Height);
+ eastl::swap(theOuterViewport.m_X, theOuterViewport.m_Y);
+ }
+ // Calculate the presentation viewport perhaps with the window width and height swapped.
+ return eastl::make_pair(
+ GetPresentationViewport(theOuterViewport, m_ScaleMode, thePresentationDimensions),
+ theOuterViewport);
+ }
+
+ NVRenderRectF GetDisplayViewport() const override
+ {
+ return GetPresentationViewportAndOuterViewport().first;
+ }
+
+ void SetPresentationDimensions(const SWindowDimensions &inPresentationDimensions) override
+ {
+ m_PresentationDimensions = inPresentationDimensions;
+ }
+ SWindowDimensions GetCurrentPresentationDimensions() const override
+ {
+ return m_PresentationDimensions;
+ }
+
+ void SetRenderRotation(RenderRotationValues::Enum inRotation) override
+ {
+ m_Rotation = inRotation;
+ }
+
+ RenderRotationValues::Enum GetRenderRotation() const override { return m_Rotation; }
+ QT3DSVec2 GetMousePickViewport() const override
+ {
+ bool renderOffscreen = m_Rotation != RenderRotationValues::NoRotation;
+ if (renderOffscreen)
+ return QT3DSVec2((QT3DSF32)m_PresentationViewport.m_Width,
+ (QT3DSF32)m_PresentationViewport.m_Height);
+ else
+ return QT3DSVec2((QT3DSF32)m_WindowDimensions.m_Width, (QT3DSF32)m_WindowDimensions.m_Height);
+ }
+ NVRenderRect GetContextViewport() const override
+ {
+ NVRenderRect retval;
+ if (m_Viewport.hasValue())
+ retval = *m_Viewport;
+ else
+ retval = NVRenderRect(0, 0, m_WindowDimensions.m_Width, m_WindowDimensions.m_Height);
+
+ return retval;
+ }
+
+ QT3DSVec2 GetMousePickMouseCoords(const QT3DSVec2 &inMouseCoords) const override
+ {
+ bool renderOffscreen = m_Rotation != RenderRotationValues::NoRotation;
+ if (renderOffscreen) {
+ SWindowDimensions thePresentationDimensions(m_RenderPresentationDimensions);
+ NVRenderRect theViewport(GetContextViewport());
+ // Calculate the presentation viewport perhaps with the presentation width and height
+ // swapped.
+ NVRenderRect thePresentationViewport =
+ GetPresentationViewport(theViewport, m_ScaleMode, thePresentationDimensions);
+ // Translate pick into presentation space without rotations or anything else.
+ QT3DSF32 YHeightDiff = (QT3DSF32)((QT3DSF32)m_WindowDimensions.m_Height
+ - (QT3DSF32)thePresentationViewport.m_Height);
+ QT3DSVec2 theLocalMouse((inMouseCoords.x - thePresentationViewport.m_X),
+ (inMouseCoords.y - YHeightDiff + thePresentationViewport.m_Y));
+ switch (m_Rotation) {
+ default:
+ case RenderRotationValues::NoRotation:
+ QT3DS_ASSERT(false);
+ break;
+ case RenderRotationValues::Clockwise90:
+ eastl::swap(theLocalMouse.x, theLocalMouse.y);
+ theLocalMouse.y = thePresentationViewport.m_Width - theLocalMouse.y;
+ break;
+ case RenderRotationValues::Clockwise180:
+ theLocalMouse.y = thePresentationViewport.m_Height - theLocalMouse.y;
+ theLocalMouse.x = thePresentationViewport.m_Width - theLocalMouse.x;
+ break;
+ case RenderRotationValues::Clockwise270:
+ eastl::swap(theLocalMouse.x, theLocalMouse.y);
+ theLocalMouse.x = thePresentationViewport.m_Height - theLocalMouse.x;
+ break;
+ }
+ return theLocalMouse;
+ }
+ return inMouseCoords;
+ }
+
+ NVRenderRect GetPresentationViewport(const NVRenderRect &inViewerViewport,
+ ScaleModes::Enum inScaleToFit,
+ const SWindowDimensions &inPresDimensions) const
+ {
+ NVRenderRect retval;
+ QT3DSI32 theWidth = inViewerViewport.m_Width;
+ QT3DSI32 theHeight = inViewerViewport.m_Height;
+ if (inPresDimensions.m_Width == 0 || inPresDimensions.m_Height == 0)
+ return NVRenderRect(0, 0, 0, 0);
+ // Setup presentation viewport. This may or may not match the physical viewport that we
+ // want to setup.
+ // Avoiding scaling keeps things as sharp as possible.
+ if (inScaleToFit == ScaleModes::ExactSize) {
+ retval.m_Width = inPresDimensions.m_Width;
+ retval.m_Height = inPresDimensions.m_Height;
+ retval.m_X = (theWidth - (QT3DSI32)inPresDimensions.m_Width) / 2;
+ retval.m_Y = (theHeight - (QT3DSI32)inPresDimensions.m_Height) / 2;
+ } else if (inScaleToFit == ScaleModes::ScaleToFit
+ || inScaleToFit == ScaleModes::FitSelected) {
+ // Scale down in such a way to preserve aspect ratio.
+ float screenAspect = (float)theWidth / (float)theHeight;
+ float thePresentationAspect =
+ (float)inPresDimensions.m_Width / (float)inPresDimensions.m_Height;
+ if (screenAspect >= thePresentationAspect) {
+ // if the screen height is the limiting factor
+ retval.m_Y = 0;
+ retval.m_Height = theHeight;
+ retval.m_Width = (QT3DSI32)(thePresentationAspect * retval.m_Height);
+ retval.m_X = (theWidth - retval.m_Width) / 2;
+ } else {
+ retval.m_X = 0;
+ retval.m_Width = theWidth;
+ retval.m_Height = (QT3DSI32)(retval.m_Width / thePresentationAspect);
+ retval.m_Y = (theHeight - retval.m_Height) / 2;
+ }
+ } else {
+ // Setup the viewport for everything and let the presentations figure it out.
+ retval.m_X = 0;
+ retval.m_Y = 0;
+ retval.m_Width = theWidth;
+ retval.m_Height = theHeight;
+ }
+ retval.m_X += inViewerViewport.m_X;
+ retval.m_Y += inViewerViewport.m_Y;
+ return retval;
+ }
+
+ void RenderText2D(QT3DSF32 x, QT3DSF32 y, qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor,
+ const char *text) override
+ {
+ m_Renderer->RenderText2D(x, y, inColor, text);
+ }
+
+ void RenderGpuProfilerStats(QT3DSF32 x, QT3DSF32 y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> inColor) override
+ {
+ m_Renderer->RenderGpuProfilerStats(x, y, inColor);
+ }
+
+ NVRenderRect GetPresentationViewport() const override { return m_PresentationViewport; }
+ struct SBeginFrameResult
+ {
+ bool m_RenderOffscreen;
+ SWindowDimensions m_PresentationDimensions;
+ bool m_ScissorTestEnabled;
+ NVRenderRect m_ScissorRect;
+ NVRenderRect m_Viewport;
+ SWindowDimensions m_FBODimensions;
+ SBeginFrameResult(bool ro, SWindowDimensions presDims, bool scissorEnabled,
+ NVRenderRect scissorRect, NVRenderRect viewport,
+ SWindowDimensions fboDims)
+ : m_RenderOffscreen(ro)
+ , m_PresentationDimensions(presDims)
+ , m_ScissorTestEnabled(scissorEnabled)
+ , m_ScissorRect(scissorRect)
+ , m_Viewport(viewport)
+ , m_FBODimensions(fboDims)
+ {
+ }
+ SBeginFrameResult() {}
+ };
+
+ // Calculated values passed from beginframe to setupRenderTarget.
+ // Trying to avoid duplicate code as much as possible.
+ SBeginFrameResult m_BeginFrameResult;
+
+ void BeginFrame() override
+ {
+ m_PreRenderPresentationDimensions = m_PresentationDimensions;
+ SWindowDimensions thePresentationDimensions(m_PreRenderPresentationDimensions);
+ NVRenderRect theContextViewport(GetContextViewport());
+ m_PerFrameAllocator.reset();
+ IRenderList &theRenderList(*m_RenderList);
+ theRenderList.BeginFrame();
+ if (m_Viewport.hasValue()) {
+ theRenderList.SetScissorTestEnabled(true);
+ theRenderList.SetScissorRect(theContextViewport);
+ } else {
+ theRenderList.SetScissorTestEnabled(false);
+ }
+ bool renderOffscreen = m_Rotation != RenderRotationValues::NoRotation;
+ eastl::pair<NVRenderRect, NVRenderRect> thePresViewportAndOuterViewport =
+ GetPresentationViewportAndOuterViewport();
+ NVRenderRect theOuterViewport = thePresViewportAndOuterViewport.second;
+ // Calculate the presentation viewport perhaps with the window width and height swapped.
+ NVRenderRect thePresentationViewport = thePresViewportAndOuterViewport.first;
+ m_PresentationViewport = thePresentationViewport;
+ m_PresentationScale = QT3DSVec2(
+ (QT3DSF32)thePresentationViewport.m_Width / (QT3DSF32)thePresentationDimensions.m_Width,
+ (QT3DSF32)thePresentationViewport.m_Height / (QT3DSF32)thePresentationDimensions.m_Height);
+ SWindowDimensions fboDimensions;
+ if (thePresentationViewport.m_Width > 0 && thePresentationViewport.m_Height > 0) {
+ if (renderOffscreen == false) {
+ m_PresentationDimensions = SWindowDimensions(thePresentationViewport.m_Width,
+ thePresentationViewport.m_Height);
+ m_RenderList->SetViewport(thePresentationViewport);
+ if (thePresentationViewport.m_X || thePresentationViewport.m_Y
+ || thePresentationViewport.m_Width != (QT3DSI32)theOuterViewport.m_Width
+ || thePresentationViewport.m_Height != (QT3DSI32)theOuterViewport.m_Height) {
+ m_RenderList->SetScissorRect(thePresentationViewport);
+ m_RenderList->SetScissorTestEnabled(true);
+ }
+ } else {
+ QT3DSU32 imageWidth = ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Width);
+ QT3DSU32 imageHeight =
+ ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Height);
+ fboDimensions = SWindowDimensions(imageWidth, imageHeight);
+ m_PresentationDimensions = SWindowDimensions(thePresentationViewport.m_Width,
+ thePresentationViewport.m_Height);
+ NVRenderRect theSceneViewport = NVRenderRect(0, 0, imageWidth, imageHeight);
+ m_RenderList->SetScissorTestEnabled(false);
+ m_RenderList->SetViewport(theSceneViewport);
+ }
+ }
+
+ m_BeginFrameResult = SBeginFrameResult(
+ renderOffscreen, m_PresentationDimensions, m_RenderList->IsScissorTestEnabled(),
+ m_RenderList->GetScissor(), m_RenderList->GetViewport(), fboDimensions);
+
+ m_Renderer->BeginFrame();
+ m_OffscreenRenderManager->BeginFrame();
+ if (m_TextRenderer)
+ m_TextRenderer->BeginFrame();
+ if (m_TextTextureCache)
+ m_TextTextureCache->BeginFrame();
+ m_ImageBatchLoader->BeginFrame();
+ }
+
+ QT3DSVec2 GetPresentationScaleFactor() const override { return m_PresentationScale; }
+
+ virtual void SetupRenderTarget()
+ {
+ NVRenderRect theContextViewport(GetContextViewport());
+ if (m_Viewport.hasValue()) {
+ m_RenderContext->SetScissorTestEnabled(true);
+ m_RenderContext->SetScissorRect(theContextViewport);
+ } else {
+ m_RenderContext->SetScissorTestEnabled(false);
+ }
+ bool clearedScene = false;
+ {
+ QT3DSVec4 theClearColor;
+ if (m_MatteColor.hasValue())
+ theClearColor = m_MatteColor;
+ else {
+ theClearColor = m_SceneColor;
+ clearedScene = true;
+ }
+ m_RenderContext->SetClearColor(theClearColor);
+ m_RenderContext->Clear(qt3ds::render::NVRenderClearValues::Color);
+ }
+ bool renderOffscreen = m_BeginFrameResult.m_RenderOffscreen;
+ m_RenderContext->SetViewport(m_BeginFrameResult.m_Viewport);
+ m_RenderContext->SetScissorRect(m_BeginFrameResult.m_ScissorRect);
+ m_RenderContext->SetScissorTestEnabled(m_BeginFrameResult.m_ScissorTestEnabled);
+
+ if (m_PresentationViewport.m_Width > 0 && m_PresentationViewport.m_Height > 0) {
+ if (renderOffscreen == false) {
+ if (m_RotationFBO != NULL) {
+ m_ResourceManager->Release(*m_RotationFBO);
+ m_ResourceManager->Release(*m_RotationTexture);
+ m_ResourceManager->Release(*m_RotationDepthBuffer);
+ m_RotationFBO = NULL;
+ m_RotationTexture = NULL;
+ m_RotationDepthBuffer = NULL;
+ }
+ if (m_SceneColor.hasValue() && !clearedScene) {
+ m_RenderContext->SetClearColor(m_SceneColor);
+ m_RenderContext->Clear(qt3ds::render::NVRenderClearValues::Color);
+ }
+ } else {
+ QT3DSU32 imageWidth = m_BeginFrameResult.m_FBODimensions.m_Width;
+ QT3DSU32 imageHeight = m_BeginFrameResult.m_FBODimensions.m_Height;
+ NVRenderTextureFormats::Enum theColorBufferFormat = NVRenderTextureFormats::RGBA8;
+ NVRenderRenderBufferFormats::Enum theDepthBufferFormat =
+ NVRenderRenderBufferFormats::Depth16;
+ m_ContextRenderTarget = m_RenderContext->GetRenderTarget();
+ if (m_RotationFBO == NULL) {
+ m_RotationFBO = m_ResourceManager->AllocateFrameBuffer();
+ m_RotationTexture = m_ResourceManager->AllocateTexture2D(
+ imageWidth, imageHeight, theColorBufferFormat);
+ m_RotationDepthBuffer = m_ResourceManager->AllocateRenderBuffer(
+ imageWidth, imageHeight, theDepthBufferFormat);
+ m_RotationFBO->Attach(NVRenderFrameBufferAttachments::Color0,
+ *m_RotationTexture);
+ m_RotationFBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ *m_RotationDepthBuffer);
+ } else {
+ STextureDetails theDetails = m_RotationTexture->GetTextureDetails();
+ if (theDetails.m_Width != imageWidth || theDetails.m_Height != imageHeight) {
+ m_RotationTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, imageWidth,
+ imageHeight, theColorBufferFormat);
+ m_RotationDepthBuffer->SetDimensions(
+ qt3ds::render::NVRenderRenderBufferDimensions(imageWidth, imageHeight));
+ }
+ }
+ m_RenderContext->SetRenderTarget(m_RotationFBO);
+ if (m_SceneColor.hasValue()) {
+ m_RenderContext->SetClearColor(m_SceneColor);
+ m_RenderContext->Clear(qt3ds::render::NVRenderClearValues::Color);
+ }
+ }
+ }
+ }
+
+ void RunRenderTasks() override
+ {
+ m_RenderList->RunRenderTasks();
+ SetupRenderTarget();
+ }
+
+ // Note this runs before EndFrame
+ virtual void TeardownRenderTarget()
+ {
+ if (m_Watermark) {
+ STextureDetails theWatermarkDims = m_Watermark->GetTextureDetails();
+ SWindowDimensions thePresentationDimensions(m_PresentationDimensions);
+ NVRenderRect theViewport(GetContextViewport());
+ // Calculate the presentation viewport perhaps with the presentation width and height
+ // swapped.
+ NVRenderRect thePresentationViewport =
+ GetPresentationViewport(theViewport, m_ScaleMode, thePresentationDimensions);
+ if (m_RotationFBO) {
+ QT3DSU32 imageWidth = ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Width);
+ QT3DSU32 imageHeight =
+ ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Height);
+ m_RenderContext->SetRenderTarget(m_RotationFBO);
+ NVRenderRect theSceneViewport = NVRenderRect(0, 0, imageWidth, imageHeight);
+ m_RenderContext->SetViewport(theSceneViewport);
+ } else {
+ m_RenderContext->SetRenderTarget(m_ContextRenderTarget);
+ m_RenderContext->SetViewport(thePresentationViewport);
+ }
+ NVRenderRect theRenderViewport = m_RenderContext->GetViewport();
+ if (theRenderViewport.m_Width && theRenderViewport.m_Height) {
+ double theDesiredTextureArea =
+ theRenderViewport.m_Width * theRenderViewport.m_Height * 1.0 / 100;
+ double theMultiplier = sqrt(
+ theDesiredTextureArea / (theWatermarkDims.m_Width * theWatermarkDims.m_Height));
+ double theTargetWidth = theWatermarkDims.m_Width * theMultiplier;
+ double theTargetHeight = theWatermarkDims.m_Height * theMultiplier;
+ double theInset = theTargetHeight / 4.0f;
+ double theInsetRectWidth = theRenderViewport.m_Width - 2 * theInset;
+ double theInsetRectHeight = theRenderViewport.m_Height - 2 * theInset;
+ double rangeWidth = theInsetRectWidth - theTargetWidth;
+ double rangeHeight = theInsetRectHeight - theTargetHeight;
+ double leftOffset = rangeWidth * m_WatermarkLocation.x;
+ double bottomOffset = theInsetRectHeight - (rangeHeight * m_WatermarkLocation.y);
+ theRenderViewport.m_X += (QT3DSI32)leftOffset;
+ theRenderViewport.m_Y += (QT3DSI32)bottomOffset;
+ theRenderViewport.m_Width = (QT3DSI32)theTargetWidth;
+ theRenderViewport.m_Height = (QT3DSI32)theTargetHeight;
+ m_RenderContext->SetViewport(theRenderViewport);
+ m_RenderContext->SetDepthTestEnabled(false);
+ m_RenderContext->SetBlendingEnabled(true);
+ m_RenderContext->SetBlendFunction(qt3ds::render::NVRenderBlendFunctionArgument(
+ qt3ds::render::NVRenderSrcBlendFunc::SrcAlpha,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ qt3ds::render::NVRenderSrcBlendFunc::One,
+ qt3ds::render::NVRenderDstBlendFunc::OneMinusSrcAlpha));
+ m_RenderContext->SetBlendEquation(qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add));
+ m_RenderContext->SetScissorTestEnabled(false);
+ SCamera theCamera;
+ theCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ theCamera.m_Flags.SetOrthographic(true);
+ QT3DSVec2 theCameraDimensions((QT3DSF32)theRenderViewport.m_Width,
+ (QT3DSF32)theRenderViewport.m_Height);
+ theCamera.CalculateGlobalVariables(NVRenderRect(0, 0,
+ (QT3DSU32)theRenderViewport.m_Width,
+ (QT3DSU32)theRenderViewport.m_Height),
+ theCameraDimensions);
+
+ QT3DSMat44 theVP;
+ theCamera.CalculateViewProjectionMatrix(theVP);
+ SNode theTempNode;
+ theTempNode.CalculateGlobalVariables();
+ QT3DSMat44 theMVP;
+ QT3DSMat33 theNormalMat;
+ theTempNode.CalculateMVPAndNormalMatrix(theVP, theMVP, theNormalMat);
+ // Render fullscreen quad with the screen being defined as where the texture should
+ // go.
+ m_Renderer->RenderQuad(
+ QT3DSVec2((QT3DSF32)theRenderViewport.m_Width, (QT3DSF32)theRenderViewport.m_Height),
+ theMVP, *m_Watermark);
+ }
+ }
+ if (m_RotationFBO) {
+ ScaleModes::Enum theScaleToFit = m_ScaleMode;
+ NVRenderRect theOuterViewport(GetContextViewport());
+ m_RenderContext->SetRenderTarget(m_ContextRenderTarget);
+ SWindowDimensions thePresentationDimensions = GetCurrentPresentationDimensions();
+ if (m_Rotation == RenderRotationValues::Clockwise90
+ || m_Rotation == RenderRotationValues::Clockwise270) {
+ eastl::swap(thePresentationDimensions.m_Width, thePresentationDimensions.m_Height);
+ }
+ m_RenderPresentationDimensions = thePresentationDimensions;
+ // Calculate the presentation viewport perhaps with the presentation width and height
+ // swapped.
+ NVRenderRect thePresentationViewport =
+ GetPresentationViewport(theOuterViewport, theScaleToFit, thePresentationDimensions);
+ SCamera theCamera;
+ switch (m_Rotation) {
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ case RenderRotationValues::Clockwise90:
+ theCamera.m_Rotation.z = 90;
+ break;
+ case RenderRotationValues::Clockwise180:
+ theCamera.m_Rotation.z = 180;
+ break;
+ case RenderRotationValues::Clockwise270:
+ theCamera.m_Rotation.z = 270;
+ break;
+ }
+ TORAD(theCamera.m_Rotation.z);
+ theCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty);
+ theCamera.m_Flags.SetOrthographic(true);
+ m_RenderContext->SetViewport(thePresentationViewport);
+ QT3DSVec2 theCameraDimensions((QT3DSF32)thePresentationViewport.m_Width,
+ (QT3DSF32)thePresentationViewport.m_Height);
+ theCamera.CalculateGlobalVariables(
+ NVRenderRect(0, 0, (QT3DSU32)thePresentationViewport.m_Width,
+ (QT3DSU32)thePresentationViewport.m_Height),
+ theCameraDimensions);
+ QT3DSMat44 theVP;
+ theCamera.CalculateViewProjectionMatrix(theVP);
+ SNode theTempNode;
+ theTempNode.CalculateGlobalVariables();
+ QT3DSMat44 theMVP;
+ QT3DSMat33 theNormalMat;
+ theTempNode.CalculateMVPAndNormalMatrix(theVP, theMVP, theNormalMat);
+ m_RenderContext->SetCullingEnabled(false);
+ m_RenderContext->SetBlendingEnabled(false);
+ m_RenderContext->SetDepthTestEnabled(false);
+ m_Renderer->RenderQuad(QT3DSVec2((QT3DSF32)m_PresentationViewport.m_Width,
+ (QT3DSF32)m_PresentationViewport.m_Height),
+ theMVP, *m_RotationTexture);
+ }
+ }
+
+ void EndFrame() override
+ {
+ TeardownRenderTarget();
+ m_ImageBatchLoader->EndFrame();
+ if (m_TextTextureCache)
+ m_TextTextureCache->EndFrame();
+ if (m_TextRenderer)
+ m_TextRenderer->EndFrame();
+ m_OffscreenRenderManager->EndFrame();
+ m_Renderer->EndFrame();
+ m_CustomMaterialSystem->EndFrame();
+ m_PresentationDimensions = m_PreRenderPresentationDimensions;
+ ++m_FrameCount;
+ }
+};
+
+IUICRenderContext &SRenderContextCore::CreateRenderContext(NVRenderContext &inContext,
+ const char8_t *inPrimitivesDirectory)
+{
+ return *QT3DS_NEW(m_Foundation.getAllocator(), SRenderContext)(inContext, *this,
+ inPrimitivesDirectory);
+}
+}
+
+IUICRenderContextCore &IUICRenderContextCore::Create(NVFoundationBase &fnd, IStringTable &strt)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SRenderContextCore)(fnd, strt);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialShaderGenerator.cpp b/src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialShaderGenerator.cpp
new file mode 100644
index 00000000..c80e9c68
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialShaderGenerator.cpp
@@ -0,0 +1,1101 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderCustomMaterialShaderGenerator.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderableImage.h"
+#include "UICRenderImage.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderLight.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderCamera.h"
+#include "UICRenderShadowMap.h"
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderCustomMaterialSystem.h"
+
+using namespace uic::render;
+using qt3ds::render::NVRenderCachedShaderProperty;
+using qt3ds::render::NVRenderCachedShaderBuffer;
+
+namespace {
+struct SShaderLightProperties
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ RenderLightTypes::Enum m_LightType;
+ SLightSourceShader m_LightData;
+ volatile QT3DSI32 mRefCount;
+
+ SShaderLightProperties(NVRenderShaderProgram &inShader)
+ : m_Shader(inShader)
+ , m_LightType(RenderLightTypes::Directional)
+ , mRefCount(0)
+ {
+ }
+
+ void Set(const SLight *inLight)
+ {
+ QT3DSVec3 dir(0, 0, 1);
+ if (inLight->m_LightType == RenderLightTypes::Directional) {
+ dir = inLight->GetScalingCorrectDirection();
+ // we lit in world sapce
+ dir *= -1;
+ m_LightData.m_position = QT3DSVec4(dir, 0.0);
+ } else if (inLight->m_LightType == RenderLightTypes::Area) {
+ dir = -1.0 * inLight->GetScalingCorrectDirection();
+ m_LightData.m_position = QT3DSVec4(inLight->GetGlobalPos(), 1.0);
+ } else {
+ dir = inLight->GetGlobalPos();
+ m_LightData.m_position = QT3DSVec4(dir, 1.0);
+ }
+
+ m_LightType = inLight->m_LightType;
+
+ m_LightData.m_direction = QT3DSVec4(dir, 0.0);
+
+ float normalizedBrightness = inLight->m_Brightness / 100.0f;
+ m_LightData.m_diffuse = QT3DSVec4(inLight->m_DiffuseColor * normalizedBrightness, 1.0);
+ m_LightData.m_specular = QT3DSVec4(inLight->m_SpecularColor * normalizedBrightness, 1.0);
+
+ if (inLight->m_LightType == RenderLightTypes::Area) {
+ m_LightData.m_width = inLight->m_AreaWidth;
+ m_LightData.m_height = inLight->m_AreaWidth;
+
+ QT3DSMat33 theDirMatrix(inLight->m_GlobalTransform.getUpper3x3());
+ m_LightData.m_right =
+ QT3DSVec4(theDirMatrix.transform(QT3DSVec3(1, 0, 0)), inLight->m_AreaWidth);
+ m_LightData.m_up =
+ QT3DSVec4(theDirMatrix.transform(QT3DSVec3(0, 1, 0)), inLight->m_AreaHeight);
+ } else {
+ m_LightData.m_width = 0.0;
+ m_LightData.m_height = 0.0;
+ m_LightData.m_right = QT3DSVec4(0.0f);
+ m_LightData.m_up = QT3DSVec4(0.0f);
+
+ // These components only apply to CG lights
+ m_LightData.m_ambient = QT3DSVec4(inLight->m_AmbientColor, 1.0);
+
+ m_LightData.m_constantAttenuation = 1.0;
+ m_LightData.m_linearAttenuation = inLight->m_LinearFade;
+ m_LightData.m_quadraticAttenuation = inLight->m_ExponentialFade;
+ m_LightData.m_spotCutoff = 180.0;
+ }
+
+ if (m_LightType == RenderLightTypes::Point) {
+ m_LightData.m_shadowView = QT3DSMat44::createIdentity();
+ } else {
+ m_LightData.m_shadowView = inLight->m_GlobalTransform;
+ }
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+
+ static SShaderLightProperties CreateLightEntry(NVRenderShaderProgram &inShader)
+ {
+ return SShaderLightProperties(inShader);
+ }
+};
+
+/**
+ * Cached texture property lookups, used one per texture so a shader generator for N
+ * textures will have an array of N of these lookup objects.
+ */
+struct SShaderTextureProperties
+{
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_Offsets;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_Rotations;
+ SShaderTextureProperties(const char *sampName, const char *offName, const char *rotName,
+ NVRenderShaderProgram &inShader)
+ : m_Sampler(sampName, inShader)
+ , m_Offsets(offName, inShader)
+ , m_Rotations(rotName, inShader)
+ {
+ }
+ SShaderTextureProperties() {}
+};
+
+/* We setup some shared state on the custom material shaders */
+struct SShaderGeneratorGeneratedShader
+{
+ typedef nvhash_map<QT3DSU32, SShaderTextureProperties> TCustomMaterialImagMap;
+
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ // Specific properties we know the shader has to have.
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ModelMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat33> m_NormalMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPos;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewportMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CamProperties;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthTexture;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_AOTexture;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeProps;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOpts;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeRot;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOfs;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe2;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbe2Props;
+ NVRenderCachedShaderProperty<QT3DSI32> m_LightCount;
+ NVRenderCachedShaderProperty<QT3DSI32> m_AreaLightCount;
+ NVRenderCachedShaderProperty<QT3DSI32> m_ShadowMapCount;
+ NVRenderCachedShaderProperty<QT3DSI32> m_ShadowCubeCount;
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams;
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_LightsBuffer;
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AreaLightsBuffer;
+
+ // Cache the image property name lookups
+ TCustomMaterialImagMap m_Images; // Images external to custom material usage
+ volatile QT3DSI32 m_RefCount;
+
+ SShaderGeneratorGeneratedShader(NVRenderShaderProgram &inShader, NVRenderContext &inContext)
+ : m_Allocator(inContext.GetAllocator())
+ , m_Shader(inShader)
+ , m_ModelMatrix("model_matrix", inShader)
+ , m_ViewProjMatrix("model_view_projection", inShader)
+ , m_ViewMatrix("view_matrix", inShader)
+ , m_NormalMatrix("normal_matrix", inShader)
+ , m_CameraPos("camera_position", inShader)
+ , m_ProjMatrix("view_projection_matrix", inShader)
+ , m_ViewportMatrix("viewport_matrix", inShader)
+ , m_CamProperties("camera_properties", inShader)
+ , m_DepthTexture("depth_sampler", inShader)
+ , m_AOTexture("ao_sampler", inShader)
+ , m_LightProbe("light_probe", inShader)
+ , m_LightProbeProps("light_probe_props", inShader)
+ , m_LightProbeOpts("light_probe_opts", inShader)
+ , m_LightProbeRot("light_probe_rotation", inShader)
+ , m_LightProbeOfs("light_probe_offset", inShader)
+ , m_LightProbe2("light_probe2", inShader)
+ , m_LightProbe2Props("light_probe2_props", inShader)
+ , m_LightCount("uNumLights", inShader)
+ , m_AreaLightCount("uNumAreaLights", inShader)
+ , m_ShadowMapCount("uNumShadowMaps", inShader)
+ , m_ShadowCubeCount("uNumShadowCubes", inShader)
+ , m_AoShadowParams("cbAoShadow", inShader)
+ , m_LightsBuffer("cbBufferLights", inShader)
+ , m_AreaLightsBuffer("cbBufferAreaLights", inShader)
+ , m_Images(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Images")
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+
+ ~SShaderGeneratorGeneratedShader() { m_Shader.release(); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Allocator);
+ NVDelete(alloc, this);
+ }
+ }
+};
+
+struct SShaderGenerator : public ICustomMaterialShaderGenerator
+{
+ typedef CRenderString TStrType;
+ typedef nvhash_map<NVRenderShaderProgram *, NVScopedRefCounted<SShaderGeneratorGeneratedShader>>
+ TProgramToShaderMap;
+ typedef eastl::pair<size_t, NVScopedRefCounted<SShaderLightProperties>>
+ TCustomMaterialLightEntry;
+ typedef eastl::pair<size_t, NVRenderCachedShaderProperty<NVRenderTexture2D *>> TShadowMapEntry;
+ typedef eastl::pair<size_t, NVRenderCachedShaderProperty<NVRenderTextureCube *>>
+ TShadowCubeEntry;
+ typedef qt3ds::foundation::nvhash_map<CRegisteredString,
+ NVScopedRefCounted<qt3ds::render::NVRenderConstantBuffer>>
+ TStrConstanBufMap;
+
+ IUICRenderContext &m_RenderContext;
+ IShaderProgramGenerator &m_ProgramGenerator;
+
+ const SCustomMaterial *m_CurrentMaterial;
+ SShaderDefaultMaterialKey *m_CurrentKey;
+ IDefaultMaterialVertexPipeline *m_CurrentPipeline;
+ TShaderFeatureSet m_CurrentFeatureSet;
+ NVDataRef<SLight *> m_Lights;
+ SRenderableImage *m_FirstImage;
+ bool m_HasTransparency;
+
+ TStrType m_ImageStem;
+ TStrType m_ImageSampler;
+ TStrType m_ImageFragCoords;
+ TStrType m_ImageRotScale;
+ TStrType m_ImageOffset;
+
+ eastl::string m_GeneratedShaderString;
+
+ SShaderDefaultMaterialKeyProperties m_DefaultMaterialShaderKeyProperties;
+ TProgramToShaderMap m_ProgramToShaderMap;
+
+ nvvector<TCustomMaterialLightEntry> m_LightEntries;
+ nvvector<TShadowMapEntry> m_ShadowMapEntries;
+ nvvector<TShadowCubeEntry> m_ShadowCubeEntries;
+
+ TStrConstanBufMap m_ConstantBuffers; ///< store all constants buffers
+
+ QT3DSI32 m_RefCount;
+
+ SShaderGenerator(IUICRenderContext &inRc)
+ : m_RenderContext(inRc)
+ , m_ProgramGenerator(m_RenderContext.GetShaderProgramGenerator())
+ , m_CurrentMaterial(NULL)
+ , m_CurrentKey(NULL)
+ , m_CurrentPipeline(NULL)
+ , m_FirstImage(NULL)
+ , m_HasTransparency(false)
+ , m_ProgramToShaderMap(inRc.GetAllocator(), "m_ProgramToShaderMap")
+ , m_LightEntries(inRc.GetAllocator(), "m_LightEntries")
+ , m_ShadowMapEntries(inRc.GetAllocator(), "m_ShadowMapEntries")
+ , m_ShadowCubeEntries(inRc.GetAllocator(), "m_ShadowCubeEntries")
+ , m_ConstantBuffers(inRc.GetAllocator(), "m_ConstantBuffers")
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ m_ConstantBuffers.clear();
+ NVDelete(m_RenderContext.GetAllocator(), this);
+ }
+ }
+
+ IShaderProgramGenerator &ProgramGenerator() { return m_ProgramGenerator; }
+ IDefaultMaterialVertexPipeline &VertexGenerator() { return *m_CurrentPipeline; }
+ IShaderStageGenerator &FragmentGenerator()
+ {
+ return *m_ProgramGenerator.GetStage(ShaderGeneratorStages::Fragment);
+ }
+ SShaderDefaultMaterialKey &Key() { return *m_CurrentKey; }
+ const SCustomMaterial &Material() { return *m_CurrentMaterial; }
+ TShaderFeatureSet FeatureSet() { return m_CurrentFeatureSet; }
+ bool HasTransparency() { return m_HasTransparency; }
+
+ QT3DSU32
+ ConvertTextureTypeValue(ImageMapTypes::Enum inType)
+ {
+ NVRenderTextureTypeValue::Enum retVal = NVRenderTextureTypeValue::Unknown;
+
+ switch (inType) {
+ case ImageMapTypes::LightmapIndirect:
+ retVal = NVRenderTextureTypeValue::LightmapIndirect;
+ break;
+ case ImageMapTypes::LightmapRadiosity:
+ retVal = NVRenderTextureTypeValue::LightmapRadiosity;
+ break;
+ case ImageMapTypes::LightmapShadow:
+ retVal = NVRenderTextureTypeValue::LightmapShadow;
+ break;
+ case ImageMapTypes::Bump:
+ retVal = NVRenderTextureTypeValue::Bump;
+ break;
+ case ImageMapTypes::Diffuse:
+ retVal = NVRenderTextureTypeValue::Diffuse;
+ break;
+ case ImageMapTypes::Displacement:
+ retVal = NVRenderTextureTypeValue::Displace;
+ break;
+ default:
+ retVal = NVRenderTextureTypeValue::Unknown;
+ break;
+ }
+
+ QT3DS_ASSERT(retVal != NVRenderTextureTypeValue::Unknown);
+
+ return (QT3DSU32)retVal;
+ }
+
+ SImageVariableNames GetImageVariableNames(QT3DSU32 imageIdx) override
+ {
+ // convert to NVRenderTextureTypeValue
+ NVRenderTextureTypeValue::Enum texType = (NVRenderTextureTypeValue::Enum)imageIdx;
+ m_ImageStem = NVRenderTextureTypeValue::toString(texType);
+ m_ImageStem.append("_");
+ m_ImageSampler = m_ImageStem;
+ m_ImageSampler.append("sampler");
+ m_ImageFragCoords = m_ImageStem;
+ m_ImageFragCoords.append("uv_coords");
+ m_ImageRotScale = m_ImageStem;
+ m_ImageRotScale.append("rot_scale");
+ m_ImageOffset = m_ImageStem;
+ m_ImageOffset.append("offset");
+
+ SImageVariableNames retVal;
+ retVal.m_ImageSampler = m_ImageSampler.c_str();
+ retVal.m_ImageFragCoords = m_ImageFragCoords.c_str();
+ return retVal;
+ }
+
+ void SetImageShaderVariables(SShaderGeneratorGeneratedShader &inShader,
+ SRenderableImage &inImage)
+ {
+ // skip displacement and emissive mask maps which are handled differently
+ if (inImage.m_MapType == ImageMapTypes::Displacement
+ || inImage.m_MapType == ImageMapTypes::Emissive)
+ return;
+
+ SShaderGeneratorGeneratedShader::TCustomMaterialImagMap::iterator iter =
+ inShader.m_Images.find(inImage.m_MapType);
+ if (iter == inShader.m_Images.end()) {
+ SImageVariableNames names =
+ GetImageVariableNames(ConvertTextureTypeValue(inImage.m_MapType));
+ inShader.m_Images.insert(eastl::make_pair(
+ (QT3DSU32)inImage.m_MapType,
+ SShaderTextureProperties(names.m_ImageSampler, m_ImageOffset.c_str(),
+ m_ImageRotScale.c_str(), inShader.m_Shader)));
+ iter = inShader.m_Images.find(inImage.m_MapType);
+ }
+
+ SShaderTextureProperties &theShaderProps = iter->second;
+ const QT3DSMat44 &textureTransform = inImage.m_Image.m_TextureTransform;
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ QT3DSVec3 offsets(dataPtr[12], dataPtr[13], 0.0f);
+ // Grab just the upper 2x2 rotation matrix from the larger matrix.
+ QT3DSVec4 rotations(dataPtr[0], dataPtr[4], dataPtr[1], dataPtr[5]);
+
+ // The image horizontal and vertical tiling modes need to be set here, before we set texture
+ // on the shader.
+ // because setting the image on the texture forces the textue to bind and immediately apply
+ // any tex params.
+ inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapS(
+ inImage.m_Image.m_HorizontalTilingMode);
+ inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapT(
+ inImage.m_Image.m_VerticalTilingMode);
+
+ theShaderProps.m_Sampler.Set(inImage.m_Image.m_TextureData.m_Texture);
+ theShaderProps.m_Offsets.Set(offsets);
+ theShaderProps.m_Rotations.Set(rotations);
+ }
+
+ void GenerateImageUVCoordinates(IShaderStageGenerator &, QT3DSU32, QT3DSU32, SRenderableImage &) override {}
+
+ ///< get the light constant buffer and generate if necessary
+ NVRenderConstantBuffer *GetLightConstantBuffer(const char *name, QT3DSU32 inLightCount)
+ {
+ NVRenderContext &theContext(m_RenderContext.GetRenderContext());
+
+ // we assume constant buffer support
+ QT3DS_ASSERT(theContext.GetConstantBufferSupport());
+ // we only create if if we have lights
+ if (!inLightCount || !theContext.GetConstantBufferSupport())
+ return NULL;
+
+ CRegisteredString theName = theContext.GetStringTable().RegisterStr(name);
+ NVRenderConstantBuffer *pCB = theContext.GetConstantBuffer(theName);
+
+ if (!pCB) {
+ // create with size of all structures + int for light count
+ SLightSourceShader s[UIC_MAX_NUM_LIGHTS];
+ NVDataRef<QT3DSU8> cBuffer((QT3DSU8 *)&s, (sizeof(SLightSourceShader) * UIC_MAX_NUM_LIGHTS)
+ + (4 * sizeof(QT3DSI32)));
+ pCB = theContext.CreateConstantBuffer(
+ name, qt3ds::render::NVRenderBufferUsageType::Static,
+ (sizeof(SLightSourceShader) * UIC_MAX_NUM_LIGHTS) + (4 * sizeof(QT3DSI32)), cBuffer);
+ if (!pCB) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ // init first set
+ memset(&s[0], 0x0, sizeof(SLightSourceShader));
+ QT3DSI32 cgLights = 0;
+ pCB->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&cgLights, sizeof(QT3DSI32)));
+ pCB->UpdateRaw(4 * sizeof(QT3DSI32),
+ NVDataRef<QT3DSU8>((QT3DSU8 *)&s[0], sizeof(SLightSourceShader)));
+ pCB->Update(); // update to hardware
+
+ m_ConstantBuffers.insert(eastl::make_pair(theName, pCB));
+ }
+
+ return pCB;
+ }
+
+ void GenerateVertexShader()
+ {
+ // vertex displacement
+ QT3DSU32 imageIdx = 0;
+ SRenderableImage *displacementImage = NULL;
+ QT3DSU32 displacementImageIdx = 0;
+
+ for (SRenderableImage *img = m_FirstImage; img != NULL;
+ img = img->m_NextImage, ++imageIdx) {
+ if (img->m_MapType == ImageMapTypes::Displacement) {
+ displacementImage = img;
+ displacementImageIdx = imageIdx;
+ break;
+ }
+ }
+
+ // the pipeline opens/closes up the shaders stages
+ VertexGenerator().BeginVertexGeneration(displacementImageIdx, displacementImage);
+ }
+
+ SShaderGeneratorGeneratedShader &GetShaderForProgram(NVRenderShaderProgram &inProgram)
+ {
+ eastl::pair<TProgramToShaderMap::iterator, bool> inserter =
+ m_ProgramToShaderMap.insert(eastl::make_pair(
+ &inProgram, NVScopedRefCounted<SShaderGeneratorGeneratedShader>(NULL)));
+ if (inserter.second) {
+ NVAllocatorCallback &alloc(m_RenderContext.GetRenderContext().GetAllocator());
+ inserter.first->second = QT3DS_NEW(alloc, SShaderGeneratorGeneratedShader)(
+ inProgram, m_RenderContext.GetRenderContext());
+ }
+ return *inserter.first->second;
+ }
+
+ virtual SShaderLightProperties *SetLight(NVRenderShaderProgram &inShader, size_t lightIdx,
+ size_t shadeIdx, const SLight *inLight,
+ SShadowMapEntry *inShadow, QT3DSI32 shadowIdx,
+ QT3DSF32 shadowDist)
+ {
+ SShaderLightProperties *theLightEntry(NULL);
+ for (QT3DSU32 idx = 0, end = m_LightEntries.size(); idx < end && theLightEntry == NULL;
+ ++idx) {
+ if (m_LightEntries[idx].first == lightIdx
+ && m_LightEntries[idx].second->m_Shader.mPtr == &inShader
+ && m_LightEntries[idx].second->m_LightType == inLight->m_LightType) {
+ theLightEntry = m_LightEntries[idx].second;
+ }
+ }
+ if (theLightEntry == NULL) {
+ // create a new name
+ eastl::string lightName;
+ if (inLight->m_LightType == RenderLightTypes::Area)
+ lightName = "arealights";
+ else
+ lightName = "lights";
+ char buf[16];
+ _snprintf(buf, 16, "[%lu]", shadeIdx);
+ lightName.append(buf);
+
+ NVScopedRefCounted<SShaderLightProperties> theNewEntry =
+ QT3DS_NEW(m_RenderContext.GetAllocator(),
+ SShaderLightProperties)(SShaderLightProperties::CreateLightEntry(inShader));
+ m_LightEntries.push_back(eastl::make_pair(lightIdx, theNewEntry));
+ theLightEntry = theNewEntry.mPtr;
+ }
+ theLightEntry->Set(inLight);
+ theLightEntry->m_LightData.m_shadowControls =
+ QT3DSVec4(inLight->m_ShadowBias, inLight->m_ShadowFactor, shadowDist, 0.0);
+ theLightEntry->m_LightData.m_shadowIdx = (inShadow) ? shadowIdx : -1;
+
+ return theLightEntry;
+ }
+
+ void SetShadowMaps(NVRenderShaderProgram &inProgram, SShadowMapEntry *inShadow,
+ QT3DSI32 &numShadowMaps, QT3DSI32 &numShadowCubes)
+ {
+ if (inShadow) {
+ eastl::string shadowName;
+ if (inShadow->m_DepthCube && (numShadowCubes < UIC_MAX_NUM_SHADOWS)) {
+ shadowName = "shadowCubes";
+ char buf[16];
+ _snprintf(buf, 16, "[%d]", numShadowCubes);
+ shadowName.append(buf);
+
+ NVRenderCachedShaderProperty<NVRenderTextureCube *> theNewEntry(shadowName.c_str(),
+ inProgram);
+ theNewEntry.Set(inShadow->m_DepthCube);
+ m_ShadowCubeEntries.push_back(eastl::make_pair(numShadowCubes, theNewEntry));
+
+ ++numShadowCubes;
+ } else if (inShadow->m_DepthMap && (numShadowMaps < UIC_MAX_NUM_SHADOWS)) {
+ shadowName = "shadowMaps";
+ char buf[16];
+ _snprintf(buf, 16, "[%d]", numShadowMaps);
+ shadowName.append(buf);
+
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> theNewEntry(shadowName.c_str(),
+ inProgram);
+ theNewEntry.Set(inShadow->m_DepthMap);
+ m_ShadowMapEntries.push_back(eastl::make_pair(numShadowMaps, theNewEntry));
+
+ ++numShadowMaps;
+ }
+ }
+ }
+
+ void SetGlobalProperties(NVRenderShaderProgram &inProgram, const SLayer & /*inLayer*/
+ ,
+ SCamera &inCamera, QT3DSVec3, NVDataRef<SLight *> inLights,
+ NVDataRef<QT3DSVec3>, UICShadowMap *inShadowMaps)
+ {
+ SShaderGeneratorGeneratedShader &theShader(GetShaderForProgram(inProgram));
+ m_RenderContext.GetRenderContext().SetActiveShader(&inProgram);
+
+ SCamera &theCamera(inCamera);
+
+ QT3DSVec2 camProps(theCamera.m_ClipNear, theCamera.m_ClipFar);
+ theShader.m_CamProperties.Set(camProps);
+ theShader.m_CameraPos.Set(theCamera.GetGlobalPos());
+
+ if (theShader.m_ViewMatrix.IsValid())
+ theShader.m_ViewMatrix.Set(theCamera.m_GlobalTransform.getInverse());
+
+ if (theShader.m_ProjMatrix.IsValid()) {
+ QT3DSMat44 vProjMat;
+ inCamera.CalculateViewProjectionMatrix(vProjMat);
+ theShader.m_ProjMatrix.Set(vProjMat);
+ }
+
+ // this call setsup the constant buffer for ambient occlusion and shadow
+ theShader.m_AoShadowParams.Set();
+
+ //
+ NVRenderConstantBuffer *pLightCb =
+ GetLightConstantBuffer("cbBufferLights", inLights.size());
+ NVRenderConstantBuffer *pAreaLightCb =
+ GetLightConstantBuffer("cbBufferAreaLights", inLights.size());
+
+ // set lights separate for area lights
+ QT3DSI32 cgLights = 0, areaLights = 0;
+ QT3DSI32 numShadowMaps = 0, numShadowCubes = 0;
+
+ // Split the count between CG lights and area lights
+ for (QT3DSU32 lightIdx = 0; lightIdx < inLights.size() && pLightCb; ++lightIdx) {
+ SShadowMapEntry *theShadow = NULL;
+ if (inShadowMaps) {
+ theShadow = inShadowMaps->GetShadowMapEntry(lightIdx);
+ }
+
+ QT3DSI32 shdwIdx = (inLights[lightIdx]->m_LightType != RenderLightTypes::Directional)
+ ? numShadowCubes
+ : numShadowMaps;
+ SetShadowMaps(inProgram, theShadow, numShadowMaps, numShadowCubes);
+
+ if (inLights[lightIdx]->m_LightType == RenderLightTypes::Area) {
+ SShaderLightProperties *theAreaLightEntry =
+ SetLight(inProgram, lightIdx, areaLights, inLights[lightIdx], theShadow,
+ shdwIdx, inCamera.m_ClipFar);
+
+ if (theAreaLightEntry && pAreaLightCb)
+ pAreaLightCb->UpdateRaw(areaLights * sizeof(SLightSourceShader)
+ + (4 * sizeof(QT3DSI32)),
+ NVDataRef<QT3DSU8>((QT3DSU8 *)&theAreaLightEntry->m_LightData,
+ sizeof(SLightSourceShader)));
+
+ areaLights++;
+ } else {
+ SShaderLightProperties *theLightEntry =
+ SetLight(inProgram, lightIdx, cgLights, inLights[lightIdx], theShadow, shdwIdx,
+ inCamera.m_ClipFar);
+
+ if (theLightEntry && pLightCb)
+ pLightCb->UpdateRaw(cgLights * sizeof(SLightSourceShader) + (4 * sizeof(QT3DSI32)),
+ NVDataRef<QT3DSU8>((QT3DSU8 *)&theLightEntry->m_LightData,
+ sizeof(SLightSourceShader)));
+
+ cgLights++;
+ }
+ }
+
+ if (pLightCb) {
+ pLightCb->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&cgLights, sizeof(QT3DSI32)));
+ theShader.m_LightsBuffer.Set();
+ }
+ if (pAreaLightCb) {
+ pAreaLightCb->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&areaLights, sizeof(QT3DSI32)));
+ theShader.m_AreaLightsBuffer.Set();
+ }
+
+ theShader.m_LightCount.Set(cgLights);
+ theShader.m_AreaLightCount.Set(areaLights);
+ theShader.m_ShadowMapCount.Set(numShadowMaps);
+ theShader.m_ShadowCubeCount.Set(numShadowCubes);
+ }
+
+ void SetMaterialProperties(NVRenderShaderProgram &inProgram, const SCustomMaterial &inMaterial,
+ const QT3DSVec2 &, const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32,
+ NVRenderTexture2D *inDepthTexture, NVRenderTexture2D *inSSaoTexture,
+ SImage *inLightProbe, SImage *inLightProbe2, QT3DSF32 inProbeHorizon,
+ QT3DSF32 inProbeBright, QT3DSF32 inProbe2Window, QT3DSF32 inProbe2Pos,
+ QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV)
+ {
+ ICustomMaterialSystem &theMaterialSystem(m_RenderContext.GetCustomMaterialSystem());
+ SShaderGeneratorGeneratedShader &theShader(GetShaderForProgram(inProgram));
+
+ theShader.m_ViewProjMatrix.Set(inModelViewProjection);
+ theShader.m_NormalMatrix.Set(inNormalMatrix);
+ theShader.m_ModelMatrix.Set(inGlobalTransform);
+
+ theShader.m_DepthTexture.Set(inDepthTexture);
+ theShader.m_AOTexture.Set(inSSaoTexture);
+
+ uic::render::SImage *theLightProbe = inLightProbe;
+ uic::render::SImage *theLightProbe2 = inLightProbe2;
+
+ if (inMaterial.m_IblProbe && inMaterial.m_IblProbe->m_TextureData.m_Texture) {
+ theLightProbe = inMaterial.m_IblProbe;
+ }
+
+ if (theLightProbe) {
+ if (theLightProbe->m_TextureData.m_Texture) {
+ NVRenderTextureCoordOp::Enum theHorzLightProbeTilingMode =
+ NVRenderTextureCoordOp::Repeat;
+ NVRenderTextureCoordOp::Enum theVertLightProbeTilingMode =
+ theLightProbe->m_VerticalTilingMode;
+ theLightProbe->m_TextureData.m_Texture->SetTextureWrapS(
+ theHorzLightProbeTilingMode);
+ theLightProbe->m_TextureData.m_Texture->SetTextureWrapT(
+ theVertLightProbeTilingMode);
+
+ const QT3DSMat44 &textureTransform = theLightProbe->m_TextureTransform;
+ // We separate rotational information from offset information so that just maybe the
+ // shader
+ // will attempt to push less information to the card.
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ // The third member of the offsets contains a flag indicating if the texture was
+ // premultiplied or not.
+ // We use this to mix the texture alpha.
+ // light_probe_offsets.w is now no longer being used to enable/disable fast IBL,
+ // (it's now the only option)
+ // So now, it's storing the number of mip levels in the IBL image.
+ QT3DSVec4 offsets(dataPtr[12], dataPtr[13],
+ theLightProbe->m_TextureData.m_TextureFlags.IsPreMultiplied() ? 1.0f
+ : 0.0f,
+ (float)theLightProbe->m_TextureData.m_Texture->GetNumMipmaps());
+ // Fast IBL is always on;
+ // inRenderContext.m_Layer.m_FastIbl ? 1.0f : 0.0f );
+ // Grab just the upper 2x2 rotation matrix from the larger matrix.
+ QT3DSVec4 rotations(dataPtr[0], dataPtr[4], dataPtr[1], dataPtr[5]);
+
+ theShader.m_LightProbeRot.Set(rotations);
+ theShader.m_LightProbeOfs.Set(offsets);
+
+ if ((!inMaterial.m_IblProbe) && (inProbeFOV < 180.f)) {
+ theShader.m_LightProbeOpts.Set(
+ QT3DSVec4(0.01745329251994329547f * inProbeFOV, 0.0f, 0.0f, 0.0f));
+ }
+
+ // Also make sure to add the secondary texture, but it should only be added if the
+ // primary
+ // (i.e. background) texture is also there.
+ if (theLightProbe2 && theLightProbe2->m_TextureData.m_Texture) {
+ theLightProbe2->m_TextureData.m_Texture->SetTextureWrapS(
+ theHorzLightProbeTilingMode);
+ theLightProbe2->m_TextureData.m_Texture->SetTextureWrapT(
+ theVertLightProbeTilingMode);
+ theShader.m_LightProbe2.Set(theLightProbe2->m_TextureData.m_Texture);
+ theShader.m_LightProbe2Props.Set(
+ QT3DSVec4(inProbe2Window, inProbe2Pos, inProbe2Fade, 1.0f));
+
+ const QT3DSMat44 &xform2 = theLightProbe2->m_TextureTransform;
+ const QT3DSF32 *dataPtr(xform2.front());
+
+ theShader.m_LightProbeProps.Set(
+ QT3DSVec4(dataPtr[12], dataPtr[13], inProbeHorizon, inProbeBright * 0.01f));
+ } else {
+ theShader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ theShader.m_LightProbeProps.Set(
+ QT3DSVec4(0.0f, 0.0f, inProbeHorizon, inProbeBright * 0.01f));
+ }
+ } else {
+ theShader.m_LightProbeProps.Set(QT3DSVec4(0.0f, 0.0f, -1.0f, 0.0f));
+ theShader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ }
+
+ theShader.m_LightProbe.Set(theLightProbe->m_TextureData.m_Texture);
+
+ } else {
+ theShader.m_LightProbeProps.Set(QT3DSVec4(0.0f, 0.0f, -1.0f, 0.0f));
+ theShader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ }
+
+ // finally apply custom material shader properties
+ theMaterialSystem.ApplyShaderPropertyValues(inMaterial, inProgram);
+
+ // additional textures
+ for (SRenderableImage *theImage = inFirstImage; theImage; theImage = theImage->m_NextImage)
+ SetImageShaderVariables(theShader, *theImage);
+ }
+
+ void SetMaterialProperties(NVRenderShaderProgram &inProgram,
+ const SGraphObject &inMaterial, const QT3DSVec2 &inCameraVec,
+ const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix,
+ const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties) override
+ {
+ const SCustomMaterial &theCustomMaterial(
+ reinterpret_cast<const SCustomMaterial &>(inMaterial));
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::CustomMaterial);
+
+ SetGlobalProperties(inProgram, inRenderProperties.m_Layer, inRenderProperties.m_Camera,
+ inRenderProperties.m_CameraDirection, inRenderProperties.m_Lights,
+ inRenderProperties.m_LightDirections,
+ inRenderProperties.m_ShadowMapManager);
+
+ SetMaterialProperties(inProgram, theCustomMaterial, inCameraVec, inModelViewProjection,
+ inNormalMatrix, inGlobalTransform, inFirstImage, inOpacity,
+ inRenderProperties.m_DepthTexture, inRenderProperties.m_SSaoTexture,
+ inRenderProperties.m_LightProbe, inRenderProperties.m_LightProbe2,
+ inRenderProperties.m_ProbeHorizon, inRenderProperties.m_ProbeBright,
+ inRenderProperties.m_Probe2Window, inRenderProperties.m_Probe2Pos,
+ inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV);
+ }
+
+ void GenerateLightmapIndirectFunc(IShaderStageGenerator &inFragmentShader,
+ SImage *pEmissiveLightmap)
+ {
+ inFragmentShader << "\n";
+ inFragmentShader << "vec3 computeMaterialLightmapIndirect()\n{\n";
+ inFragmentShader << " vec4 indirect = vec4( 0.0, 0.0, 0.0, 0.0 );\n";
+ if (pEmissiveLightmap) {
+ SImageVariableNames names =
+ GetImageVariableNames(ConvertTextureTypeValue(ImageMapTypes::LightmapIndirect));
+ inFragmentShader.AddUniform(names.m_ImageSampler, "sampler2D");
+ inFragmentShader.AddUniform(m_ImageOffset, "vec3");
+ inFragmentShader.AddUniform(m_ImageRotScale, "vec4");
+
+ inFragmentShader << "\n indirect = evalIndirectLightmap( " << m_ImageSampler
+ << ", varTexCoord1, ";
+ inFragmentShader << m_ImageRotScale << ", ";
+ inFragmentShader << m_ImageOffset << " );\n\n";
+ }
+
+ inFragmentShader << " return indirect.rgb;\n";
+ inFragmentShader << "}\n\n";
+ }
+
+ void GenerateLightmapRadiosityFunc(IShaderStageGenerator &inFragmentShader,
+ SImage *pRadiosityLightmap)
+ {
+ inFragmentShader << "\n";
+ inFragmentShader << "vec3 computeMaterialLightmapRadiosity()\n{\n";
+ inFragmentShader << " vec4 radiosity = vec4( 1.0, 1.0, 1.0, 1.0 );\n";
+ if (pRadiosityLightmap) {
+ SImageVariableNames names =
+ GetImageVariableNames(ConvertTextureTypeValue(ImageMapTypes::LightmapRadiosity));
+ inFragmentShader.AddUniform(names.m_ImageSampler, "sampler2D");
+ inFragmentShader.AddUniform(m_ImageOffset, "vec3");
+ inFragmentShader.AddUniform(m_ImageRotScale, "vec4");
+
+ inFragmentShader << "\n radiosity = evalRadiosityLightmap( " << m_ImageSampler
+ << ", varTexCoord1, ";
+ inFragmentShader << m_ImageRotScale << ", ";
+ inFragmentShader << m_ImageOffset << " );\n\n";
+ }
+
+ inFragmentShader << " return radiosity.rgb;\n";
+ inFragmentShader << "}\n\n";
+ }
+
+ void GenerateLightmapShadowFunc(IShaderStageGenerator &inFragmentShader,
+ SImage *pBakedShadowMap)
+ {
+ inFragmentShader << "\n";
+ inFragmentShader << "vec4 computeMaterialLightmapShadow()\n{\n";
+ inFragmentShader << " vec4 shadowMask = vec4( 1.0, 1.0, 1.0, 1.0 );\n";
+ if (pBakedShadowMap) {
+ SImageVariableNames names =
+ GetImageVariableNames((QT3DSU32)NVRenderTextureTypeValue::LightmapShadow);
+ // Add uniforms
+ inFragmentShader.AddUniform(names.m_ImageSampler, "sampler2D");
+ inFragmentShader.AddUniform(m_ImageOffset, "vec3");
+ inFragmentShader.AddUniform(m_ImageRotScale, "vec4");
+
+ inFragmentShader << "\n shadowMask = evalShadowLightmap( " << m_ImageSampler
+ << ", texCoord0, ";
+ inFragmentShader << m_ImageRotScale << ", ";
+ inFragmentShader << m_ImageOffset << " );\n\n";
+ }
+
+ inFragmentShader << " return shadowMask;\n";
+ inFragmentShader << "}\n\n";
+ }
+
+ void GenerateLightmapIndirectSetupCode(IShaderStageGenerator &inFragmentShader,
+ SRenderableImage *pIndirectLightmap,
+ SRenderableImage *pRadiosityLightmap)
+ {
+ if (!pIndirectLightmap && !pRadiosityLightmap)
+ return;
+
+ eastl::string finalValue;
+
+ inFragmentShader << "\n";
+ inFragmentShader << "void initializeLayerVariablesWithLightmap(void)\n{\n";
+ if (pIndirectLightmap) {
+ inFragmentShader
+ << " vec3 lightmapIndirectValue = computeMaterialLightmapIndirect( );\n";
+ finalValue.append("vec4(lightmapIndirectValue, 1.0)");
+ }
+ if (pRadiosityLightmap) {
+ inFragmentShader
+ << " vec3 lightmapRadisoityValue = computeMaterialLightmapRadiosity( );\n";
+ if (finalValue.empty())
+ finalValue.append("vec4(lightmapRadisoityValue, 1.0)");
+ else
+ finalValue.append(" + vec4(lightmapRadisoityValue, 1.0)");
+ }
+
+ finalValue.append(";\n");
+
+ char buf[16];
+ for (QT3DSU32 idx = 0; idx < Material().m_LayerCount; idx++) {
+ _snprintf(buf, 16, "[%d]", idx);
+ inFragmentShader << " layers" << buf << ".base += " << finalValue.c_str();
+ inFragmentShader << " layers" << buf << ".layer += " << finalValue.c_str();
+ }
+
+ inFragmentShader << "}\n\n";
+ }
+
+ void GenerateLightmapShadowCode(IShaderStageGenerator &inFragmentShader,
+ SRenderableImage *pBakedShadowMap)
+ {
+ if (pBakedShadowMap) {
+ inFragmentShader << " tmpShadowTerm *= computeMaterialLightmapShadow( );\n\n";
+ }
+ }
+
+ void ApplyEmissiveMask(IShaderStageGenerator &inFragmentShader, SImage *pEmissiveMaskMap)
+ {
+ inFragmentShader << "\n";
+ inFragmentShader << "vec3 computeMaterialEmissiveMask()\n{\n";
+ inFragmentShader << " vec3 emissiveMask = vec3( 1.0, 1.0, 1.0 );\n";
+ if (pEmissiveMaskMap) {
+ inFragmentShader << " texture_coordinate_info tci;\n";
+ inFragmentShader << " texture_coordinate_info transformed_tci;\n";
+ inFragmentShader << " tci = textureCoordinateInfo( texCoord0, tangent, binormal );\n";
+ inFragmentShader << " transformed_tci = transformCoordinate( "
+ "rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), ";
+ inFragmentShader << "vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, "
+ "1.000000 ) ), tci );\n";
+ inFragmentShader << " emissiveMask = fileTexture( "
+ << pEmissiveMaskMap->m_ImageShaderName.c_str()
+ << ", vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformed_tci, ";
+ inFragmentShader << "vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), "
+ "wrap_repeat, wrap_repeat, gamma_default ).tint;\n";
+ }
+
+ inFragmentShader << " return emissiveMask;\n";
+ inFragmentShader << "}\n\n";
+ }
+
+ void GenerateFragmentShader(SShaderDefaultMaterialKey &, const char8_t *inShaderPathName)
+ {
+ uic::render::IDynamicObjectSystem &theDynamicSystem(
+ m_RenderContext.GetDynamicObjectSystem());
+ CRenderString theShaderBuffer;
+ const char8_t *fragSource = theDynamicSystem.GetShaderSource(
+ m_RenderContext.GetStringTable().RegisterStr(inShaderPathName), theShaderBuffer);
+
+ QT3DS_ASSERT(fragSource);
+
+ // light maps
+ bool hasLightmaps = false;
+ SRenderableImage *lightmapShadowImage = NULL;
+ SRenderableImage *lightmapIndirectImage = NULL;
+ SRenderableImage *lightmapRadisoityImage = NULL;
+
+ for (SRenderableImage *img = m_FirstImage; img != NULL; img = img->m_NextImage) {
+ if (img->m_MapType == ImageMapTypes::LightmapIndirect) {
+ lightmapIndirectImage = img;
+ hasLightmaps = true;
+ } else if (img->m_MapType == ImageMapTypes::LightmapRadiosity) {
+ lightmapRadisoityImage = img;
+ hasLightmaps = true;
+ } else if (img->m_MapType == ImageMapTypes::LightmapShadow) {
+ lightmapShadowImage = img;
+ }
+ }
+
+ VertexGenerator().GenerateUVCoords(0);
+ // for lightmaps we expect a second set of uv coordinates
+ if (hasLightmaps)
+ VertexGenerator().GenerateUVCoords(1);
+
+ IDefaultMaterialVertexPipeline &vertexShader(VertexGenerator());
+ IShaderStageGenerator &fragmentShader(FragmentGenerator());
+
+ eastl::string srcString(fragSource);
+
+ fragmentShader << "#define FRAGMENT_SHADER\n\n";
+
+ if (srcString.find("void main()") == eastl::string::npos)
+ fragmentShader.AddInclude("evalLightmaps.glsllib");
+
+ // check dielectric materials
+ if (!Material().IsDielectric())
+ fragmentShader << "#define MATERIAL_IS_NON_DIELECTRIC 1\n\n";
+ else
+ fragmentShader << "#define MATERIAL_IS_NON_DIELECTRIC 0\n\n";
+
+ fragmentShader << "#define UIC_ENABLE_RNM 0\n\n";
+
+ fragmentShader << fragSource << Endl;
+
+ if (srcString.find("void main()") != eastl::string::npos) // If a "main()" is already
+ // written, we'll assume that the
+ // shader
+ { // pass is already written out and we don't need to add anything.
+ // Nothing beyond the basics, anyway
+ vertexShader.GenerateWorldNormal();
+ vertexShader.GenerateVarTangentAndBinormal();
+ vertexShader.GenerateWorldPosition();
+
+ vertexShader.GenerateViewVector();
+ return;
+ }
+
+ if (Material().HasLighting() && lightmapIndirectImage) {
+ GenerateLightmapIndirectFunc(fragmentShader, &lightmapIndirectImage->m_Image);
+ }
+ if (Material().HasLighting() && lightmapRadisoityImage) {
+ GenerateLightmapRadiosityFunc(fragmentShader, &lightmapRadisoityImage->m_Image);
+ }
+ if (Material().HasLighting() && lightmapShadowImage) {
+ GenerateLightmapShadowFunc(fragmentShader, &lightmapShadowImage->m_Image);
+ }
+
+ if (Material().HasLighting() && (lightmapIndirectImage || lightmapRadisoityImage))
+ GenerateLightmapIndirectSetupCode(fragmentShader, lightmapIndirectImage,
+ lightmapRadisoityImage);
+
+ if (Material().HasLighting()) {
+ ApplyEmissiveMask(fragmentShader, Material().m_EmissiveMap2);
+ }
+
+ // setup main
+ VertexGenerator().BeginFragmentGeneration();
+
+ // since we do pixel lighting we always need this if lighting is enabled
+ // We write this here because the functions below may also write to
+ // the fragment shader
+ if (Material().HasLighting()) {
+ vertexShader.GenerateWorldNormal();
+ vertexShader.GenerateVarTangentAndBinormal();
+ vertexShader.GenerateWorldPosition();
+
+ if (Material().IsSpecularEnabled())
+ vertexShader.GenerateViewVector();
+ }
+
+ fragmentShader << " initializeBaseFragmentVariables();" << Endl;
+ fragmentShader << " computeTemporaries();" << Endl;
+ fragmentShader << " normal = normalize( computeNormal() );" << Endl;
+ fragmentShader << " initializeLayerVariables();" << Endl;
+ fragmentShader << " float alpha = clamp( evalCutout(), 0.0, 1.0 );" << Endl;
+
+ if (Material().IsCutOutEnabled()) {
+ fragmentShader << " if ( alpha <= 0.0f )" << Endl;
+ fragmentShader << " discard;" << Endl;
+ }
+
+ // indirect / direct lightmap init
+ if (Material().HasLighting() && (lightmapIndirectImage || lightmapRadisoityImage))
+ fragmentShader << " initializeLayerVariablesWithLightmap();" << Endl;
+
+ // shadow map
+ GenerateLightmapShadowCode(fragmentShader, lightmapShadowImage);
+
+ // main Body
+ fragmentShader << "#include \"customMaterialFragBodyAO.glsllib\"" << Endl;
+
+ // for us right now transparency means we render a glass style material
+ if (m_HasTransparency && !Material().IsTransmissive())
+ fragmentShader << " rgba = computeGlass( normal, materialIOR, alpha, rgba );" << Endl;
+ if (Material().IsTransmissive())
+ fragmentShader << " rgba = computeOpacity( rgba );" << Endl;
+
+ if (VertexGenerator().HasActiveWireframe()) {
+ fragmentShader.Append("vec3 edgeDistance = varEdgeDistance * gl_FragCoord.w;");
+ fragmentShader.Append(
+ "\tfloat d = min(min(edgeDistance.x, edgeDistance.y), edgeDistance.z);");
+ fragmentShader.Append("\tfloat mixVal = smoothstep(0.0, 1.0, d);"); // line width 1.0
+
+ fragmentShader.Append("\trgba = mix( vec4(0.0, 1.0, 0.0, 1.0), rgba, mixVal);");
+ }
+
+ fragmentShader << " fragColor = rgba;" << Endl;
+ }
+
+ NVRenderShaderProgram *GenerateCustomMaterialShader(const char8_t *inShaderPrefix,
+ const char8_t *inCustomMaterialName)
+ {
+ // build a string that allows us to print out the shader we are generating to the log.
+ // This is time consuming but I feel like it doesn't happen all that often and is very
+ // useful to users
+ // looking at the log file.
+ m_GeneratedShaderString.clear();
+ m_GeneratedShaderString.assign(nonNull(inShaderPrefix));
+ m_GeneratedShaderString.append(inCustomMaterialName);
+ SShaderDefaultMaterialKey theKey(Key());
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+
+ GenerateVertexShader();
+ GenerateFragmentShader(theKey, inCustomMaterialName);
+
+ VertexGenerator().EndVertexGeneration();
+ VertexGenerator().EndFragmentGeneration();
+
+ return ProgramGenerator().CompileGeneratedShader(m_GeneratedShaderString.c_str(),
+ SShaderCacheProgramFlags(), FeatureSet());
+ }
+
+ virtual NVRenderShaderProgram *
+ GenerateShader(const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage,
+ bool inHasTransparency, const char8_t *inShaderPrefix,
+ const char8_t *inCustomMaterialName) override
+ {
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::CustomMaterial);
+ m_CurrentMaterial = reinterpret_cast<const SCustomMaterial *>(&inMaterial);
+ m_CurrentKey = &inShaderDescription;
+ m_CurrentPipeline = static_cast<IDefaultMaterialVertexPipeline *>(&inVertexPipeline);
+ m_CurrentFeatureSet = inFeatureSet;
+ m_Lights = inLights;
+ m_FirstImage = inFirstImage;
+ m_HasTransparency = inHasTransparency;
+
+ return GenerateCustomMaterialShader(inShaderPrefix, inCustomMaterialName);
+ }
+};
+}
+
+ICustomMaterialShaderGenerator &
+ICustomMaterialShaderGenerator::CreateCustomMaterialShaderGenerator(IUICRenderContext &inRc)
+{
+ return *QT3DS_NEW(inRc.GetAllocator(), SShaderGenerator)(inRc);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialSystem.cpp b/src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialSystem.cpp
new file mode 100644
index 00000000..5ee2efd5
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderCustomMaterialSystem.cpp
@@ -0,0 +1,2909 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderCustomMaterialRenderContext.h"
+#include "UICRenderContext.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderResourceManager.h"
+#include "UICRenderMesh.h"
+#include "UICRenderCamera.h"
+#include "UICRenderLight.h"
+#include "UICRenderLayer.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderComputeShader.h"
+#include "foundation/PreAllocatedAllocator.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/Qt3DSTime.h"
+#include "foundation/StringConversionImpl.h" //snprintf
+#include "UICRenderDynamicObjectSystemUtil.h"
+#include "UICRenderableImage.h"
+#include "../RendererImpl/UICVertexPipelineImpl.h"
+#include "../RendererImpl/UICRendererImplLayerRenderData.h"
+#include "UICRenderCustomMaterialShaderGenerator.h"
+#include "UICRenderModel.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace uic::render;
+using namespace uic::render::dynamic;
+using qt3ds::render::NVRenderContextScopedProperty;
+using qt3ds::render::NVRenderCachedShaderProperty;
+using qt3ds::render::NVRenderCachedShaderBuffer;
+
+SCustomMaterialVertexPipeline::SCustomMaterialVertexPipeline(IUICRenderContext *inContext,
+ TessModeValues::Enum inTessMode)
+ : SVertexPipelineImpl(
+ inContext->GetAllocator(), inContext->GetCustomMaterialShaderGenerator(),
+ inContext->GetShaderProgramGenerator(), inContext->GetStringTable(), false)
+ , m_UICContext(inContext)
+ , m_TessMode(TessModeValues::NoTess)
+{
+ if (m_UICContext->GetRenderContext().IsTessellationSupported()) {
+ m_TessMode = inTessMode;
+ }
+
+ if (m_UICContext->GetRenderContext().IsGeometryStageSupported()
+ && m_TessMode != TessModeValues::NoTess) {
+ m_Wireframe = inContext->GetWireframeMode();
+ }
+}
+
+void SCustomMaterialVertexPipeline::InitializeTessControlShader()
+{
+ if (m_TessMode == TessModeValues::NoTess
+ || ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl) == NULL) {
+ return;
+ }
+
+ IShaderStageGenerator &tessCtrlShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+
+ tessCtrlShader.AddUniform("tessLevelInner", "float");
+ tessCtrlShader.AddUniform("tessLevelOuter", "float");
+
+ SetupTessIncludes(ShaderGeneratorStages::TessControl, m_TessMode);
+
+ tessCtrlShader.Append("void main() {\n");
+
+ tessCtrlShader.Append("\tctWorldPos[0] = varWorldPos[0];");
+ tessCtrlShader.Append("\tctWorldPos[1] = varWorldPos[1];");
+ tessCtrlShader.Append("\tctWorldPos[2] = varWorldPos[2];");
+
+ if (m_TessMode == TessModeValues::TessPhong || m_TessMode == TessModeValues::TessNPatch) {
+ tessCtrlShader.Append("\tctNorm[0] = varObjectNormal[0];");
+ tessCtrlShader.Append("\tctNorm[1] = varObjectNormal[1];");
+ tessCtrlShader.Append("\tctNorm[2] = varObjectNormal[2];");
+ }
+ if (m_TessMode == TessModeValues::TessNPatch) {
+ tessCtrlShader.Append("\tctTangent[0] = varObjTangent[0];");
+ tessCtrlShader.Append("\tctTangent[1] = varObjTangent[1];");
+ tessCtrlShader.Append("\tctTangent[2] = varObjTangent[2];");
+ }
+
+ tessCtrlShader.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n");
+}
+
+void SCustomMaterialVertexPipeline::InitializeTessEvaluationShader()
+{
+ if (m_TessMode == TessModeValues::NoTess
+ || ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval) == NULL) {
+ return;
+ }
+
+ IShaderStageGenerator &tessEvalShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddUniform("normal_matrix", "mat3");
+
+ SetupTessIncludes(ShaderGeneratorStages::TessEval, m_TessMode);
+
+ if (m_TessMode == TessModeValues::TessLinear && m_DisplacementImage) {
+ tessEvalShader.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+ tessEvalShader.AddUniform("model_matrix", "mat4");
+ tessEvalShader.AddUniform("displace_tiling", "vec3");
+ tessEvalShader.AddUniform("displaceAmount", "float");
+ tessEvalShader.AddUniform(m_DisplacementImage->m_Image.m_ImageShaderName.c_str(),
+ "sampler2D");
+ }
+
+ tessEvalShader.Append("void main() {");
+
+ if (m_TessMode == TessModeValues::TessNPatch) {
+ tessEvalShader.Append("\tctNorm[0] = varObjectNormalTC[0];");
+ tessEvalShader.Append("\tctNorm[1] = varObjectNormalTC[1];");
+ tessEvalShader.Append("\tctNorm[2] = varObjectNormalTC[2];");
+
+ tessEvalShader.Append("\tctTangent[0] = varTangentTC[0];");
+ tessEvalShader.Append("\tctTangent[1] = varTangentTC[1];");
+ tessEvalShader.Append("\tctTangent[2] = varTangentTC[2];");
+ }
+
+ tessEvalShader.Append("\tvec4 pos = tessShader( );\n");
+}
+
+void SCustomMaterialVertexPipeline::FinalizeTessControlShader()
+{
+ IShaderStageGenerator &tessCtrlShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl));
+ // add varyings we must pass through
+ typedef TStrTableStrMap::const_iterator TParamIter;
+ for (TParamIter iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ tessCtrlShader << "\t" << iter->first.c_str()
+ << "TC[gl_InvocationID] = " << iter->first.c_str()
+ << "[gl_InvocationID];\n";
+ }
+}
+
+void SCustomMaterialVertexPipeline::FinalizeTessEvaluationShader()
+{
+ IShaderStageGenerator &tessEvalShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+
+ eastl::string outExt("");
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
+ outExt = "TE";
+
+ // add varyings we must pass through
+ typedef TStrTableStrMap::const_iterator TParamIter;
+ if (m_TessMode == TessModeValues::TessNPatch) {
+ for (TParamIter iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ tessEvalShader << "\t" << iter->first.c_str() << outExt.c_str()
+ << " = gl_TessCoord.z * " << iter->first.c_str() << "TC[0] + ";
+ tessEvalShader << "gl_TessCoord.x * " << iter->first.c_str() << "TC[1] + ";
+ tessEvalShader << "gl_TessCoord.y * " << iter->first.c_str() << "TC[2];\n";
+ }
+
+ // transform the normal
+ if (m_GenerationFlags & GenerationFlagValues::WorldNormal)
+ tessEvalShader << "\n\tvarNormal" << outExt.c_str()
+ << " = normalize(normal_matrix * teNorm);\n";
+ // transform the tangent
+ if (m_GenerationFlags & GenerationFlagValues::TangentBinormal) {
+ tessEvalShader << "\n\tvarTangent" << outExt.c_str()
+ << " = normalize(normal_matrix * teTangent);\n";
+ // transform the binormal
+ tessEvalShader << "\n\tvarBinormal" << outExt.c_str()
+ << " = normalize(normal_matrix * teBinormal);\n";
+ }
+ } else {
+ for (TParamIter iter = m_InterpolationParameters.begin(),
+ end = m_InterpolationParameters.end();
+ iter != end; ++iter) {
+ tessEvalShader << "\t" << iter->first.c_str() << outExt.c_str()
+ << " = gl_TessCoord.x * " << iter->first.c_str() << "TC[0] + ";
+ tessEvalShader << "gl_TessCoord.y * " << iter->first.c_str() << "TC[1] + ";
+ tessEvalShader << "gl_TessCoord.z * " << iter->first.c_str() << "TC[2];\n";
+ }
+
+ // displacement mapping makes only sense with linear tessellation
+ if (m_TessMode == TessModeValues::TessLinear && m_DisplacementImage) {
+ tessEvalShader
+ << "\ttexture_coordinate_info tmp = textureCoordinateInfo( varTexCoord0"
+ << outExt.c_str() << ", varTangent" << outExt.c_str() << ", varBinormal"
+ << outExt.c_str() << " );" << Endl;
+ tessEvalShader << "\ttmp = transformCoordinate( rotationTranslationScale( vec3( "
+ "0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, "
+ "0.000000 ), displace_tiling ), tmp);"
+ << Endl;
+
+ tessEvalShader << "\tpos.xyz = uicDefaultMaterialFileDisplacementTexture( "
+ << m_DisplacementImage->m_Image.m_ImageShaderName.c_str()
+ << ", displaceAmount, "
+ << "tmp.position.xy";
+ tessEvalShader << ", varObjectNormal" << outExt.c_str() << ", pos.xyz );" << Endl;
+ tessEvalShader << "\tvarWorldPos" << outExt.c_str() << "= (model_matrix * pos).xyz;"
+ << Endl;
+ }
+
+ // transform the normal
+ tessEvalShader << "\n\tvarNormal" << outExt.c_str()
+ << " = normalize(normal_matrix * varObjectNormal" << outExt.c_str()
+ << ");\n";
+ }
+
+ tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n");
+}
+
+// Responsible for beginning all vertex and fragment generation (void main() { etc).
+void SCustomMaterialVertexPipeline::BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage)
+{
+ m_DisplacementIdx = displacementImageIdx;
+ m_DisplacementImage = displacementImage;
+
+ TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
+
+ if (m_TessMode != TessModeValues::NoTess) {
+ theStages |= ShaderGeneratorStages::TessControl;
+ theStages |= ShaderGeneratorStages::TessEval;
+ }
+ if (m_Wireframe) {
+ theStages |= ShaderGeneratorStages::Geometry;
+ }
+
+ ProgramGenerator().BeginProgram(theStages);
+
+ if (m_TessMode != TessModeValues::NoTess) {
+ InitializeTessControlShader();
+ InitializeTessEvaluationShader();
+ }
+ if (m_Wireframe) {
+ InitializeWireframeGeometryShader();
+ }
+
+ IShaderStageGenerator &vertexShader(Vertex());
+
+ // thinks we need
+ vertexShader.AddInclude("viewProperties.glsllib");
+ vertexShader.AddInclude("customMaterial.glsllib");
+
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader << "void main()" << Endl << "{" << Endl;
+
+ if (displacementImage) {
+ GenerateUVCoords(0);
+ if (!HasTessellation()) {
+ vertexShader.AddUniform("displaceAmount", "float");
+ vertexShader.AddUniform("displace_tiling", "vec3");
+ // we create the world position setup here
+ // because it will be replaced with the displaced position
+ SetCode(GenerationFlagValues::WorldPosition);
+ vertexShader.AddUniform("model_matrix", "mat4");
+
+ vertexShader.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+ vertexShader.AddUniform(displacementImage->m_Image.m_ImageShaderName.c_str(),
+ "sampler2D");
+
+ vertexShader << "\ttexture_coordinate_info tmp = textureCoordinateInfo( texCoord0, "
+ "varTangent, varBinormal );"
+ << Endl;
+ vertexShader << "\ttmp = transformCoordinate( rotationTranslationScale( vec3( "
+ "0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, "
+ "0.000000 ), displace_tiling ), tmp);"
+ << Endl;
+
+ vertexShader << "\tvec3 displacedPos = uicDefaultMaterialFileDisplacementTexture( "
+ << displacementImage->m_Image.m_ImageShaderName.c_str()
+ << ", displaceAmount, "
+ << "tmp.position.xy"
+ << ", attr_norm, attr_pos );" << Endl;
+
+ AddInterpolationParameter("varWorldPos", "vec3");
+ vertexShader.Append("\tvec3 local_model_world_position = (model_matrix * "
+ "vec4(displacedPos, 1.0)).xyz;");
+ AssignOutput("varWorldPos", "local_model_world_position");
+ }
+ }
+
+ if (HasTessellation()) {
+ vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);");
+ } else {
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ if (displacementImage)
+ vertexShader.Append(
+ "\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ else
+ vertexShader.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ }
+
+ if (HasTessellation()) {
+ GenerateWorldPosition();
+ GenerateWorldNormal();
+ GenerateObjectNormal();
+ GenerateVarTangentAndBinormal();
+ }
+}
+
+void SCustomMaterialVertexPipeline::BeginFragmentGeneration()
+{
+ Fragment() << "void main()" << Endl << "{" << Endl;
+}
+
+void SCustomMaterialVertexPipeline::AssignOutput(const char8_t *inVarName,
+ const char8_t *inVarValue)
+{
+ Vertex() << "\t" << inVarName << " = " << inVarValue << ";\n";
+}
+
+void SCustomMaterialVertexPipeline::GenerateUVCoords(QT3DSU32 inUVSet)
+{
+ if (inUVSet == 0 && SetCode(GenerationFlagValues::UVCoords))
+ return;
+ if (inUVSet == 1 && SetCode(GenerationFlagValues::UVCoords1))
+ return;
+
+ QT3DS_ASSERT(inUVSet == 0 || inUVSet == 1);
+
+ if (inUVSet == 0)
+ AddInterpolationParameter("varTexCoord0", "vec3");
+ else if (inUVSet == 1)
+ AddInterpolationParameter("varTexCoord1", "vec3");
+
+ DoGenerateUVCoords(inUVSet);
+}
+
+void SCustomMaterialVertexPipeline::GenerateWorldNormal()
+{
+ if (SetCode(GenerationFlagValues::WorldNormal))
+ return;
+ AddInterpolationParameter("varNormal", "vec3");
+ DoGenerateWorldNormal();
+}
+
+void SCustomMaterialVertexPipeline::GenerateObjectNormal()
+{
+ if (SetCode(GenerationFlagValues::ObjectNormal))
+ return;
+ DoGenerateObjectNormal();
+}
+
+void SCustomMaterialVertexPipeline::GenerateVarTangentAndBinormal()
+{
+ if (SetCode(GenerationFlagValues::TangentBinormal))
+ return;
+ AddInterpolationParameter("varTangent", "vec3");
+ AddInterpolationParameter("varBinormal", "vec3");
+ AddInterpolationParameter("varObjTangent", "vec3");
+ AddInterpolationParameter("varObjBinormal", "vec3");
+ DoGenerateVarTangentAndBinormal();
+}
+
+void SCustomMaterialVertexPipeline::GenerateWorldPosition()
+{
+ if (SetCode(GenerationFlagValues::WorldPosition))
+ return;
+
+ ActiveStage().AddUniform("model_matrix", "mat4");
+ AddInterpolationParameter("varWorldPos", "vec3");
+ AddInterpolationParameter("varObjPos", "vec3");
+ DoGenerateWorldPosition();
+}
+
+// responsible for closing all vertex and fragment generation
+void SCustomMaterialVertexPipeline::EndVertexGeneration()
+{
+ if (HasTessellation()) {
+ // finalize tess control shader
+ FinalizeTessControlShader();
+ // finalize tess evaluation shader
+ FinalizeTessEvaluationShader();
+
+ TessControl().Append("}");
+ TessEval().Append("}");
+
+ if (m_Wireframe) {
+ // finalize geometry shader
+ FinalizeWireframeGeometryShader();
+ Geometry().Append("}");
+ }
+ }
+
+ Vertex().Append("}");
+}
+
+void SCustomMaterialVertexPipeline::EndFragmentGeneration()
+{
+ Fragment().Append("}");
+}
+
+IShaderStageGenerator &SCustomMaterialVertexPipeline::ActiveStage()
+{
+ return Vertex();
+}
+
+void SCustomMaterialVertexPipeline::AddInterpolationParameter(const char8_t *inName,
+ const char8_t *inType)
+{
+ m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType)));
+ Vertex().AddOutgoing(inName, inType);
+ Fragment().AddIncoming(inName, inType);
+
+ if (HasTessellation()) {
+ eastl::string nameBuilder(inName);
+ nameBuilder.append("TC");
+ TessControl().AddOutgoing(nameBuilder.c_str(), inType);
+
+ nameBuilder.assign(inName);
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry) {
+ nameBuilder.append("TE");
+ Geometry().AddOutgoing(inName, inType);
+ }
+ TessEval().AddOutgoing(nameBuilder.c_str(), inType);
+ }
+}
+
+void SCustomMaterialVertexPipeline::DoGenerateUVCoords(QT3DSU32 inUVSet)
+{
+ QT3DS_ASSERT(inUVSet == 0 || inUVSet == 1);
+
+ if (inUVSet == 0) {
+ Vertex().AddIncoming("attr_uv0", "vec2");
+ Vertex() << "\tvec3 texCoord0 = vec3( attr_uv0, 0.0 );" << Endl;
+ AssignOutput("varTexCoord0", "texCoord0");
+ } else if (inUVSet == 1) {
+ Vertex().AddIncoming("attr_uv1", "vec2");
+ Vertex() << "\tvec3 texCoord1 = vec3( attr_uv1, 1.0 );" << Endl;
+ AssignOutput("varTexCoord1", "texCoord1");
+ }
+}
+
+void SCustomMaterialVertexPipeline::DoGenerateWorldNormal()
+{
+ IShaderStageGenerator &vertexGenerator(Vertex());
+ vertexGenerator.AddIncoming("attr_norm", "vec3");
+ vertexGenerator.AddUniform("normal_matrix", "mat3");
+
+ if (HasTessellation() == false) {
+ Vertex().Append("\tvarNormal = normalize( normal_matrix * attr_norm );");
+ }
+}
+
+void SCustomMaterialVertexPipeline::DoGenerateObjectNormal()
+{
+ AddInterpolationParameter("varObjectNormal", "vec3");
+ Vertex().Append("\tvarObjectNormal = attr_norm;");
+}
+
+void SCustomMaterialVertexPipeline::DoGenerateWorldPosition()
+{
+ Vertex().Append("\tvarObjPos = attr_pos;");
+ Vertex().Append("\tvec4 worldPos = (model_matrix * vec4(attr_pos, 1.0));");
+ AssignOutput("varWorldPos", "worldPos.xyz");
+}
+
+void SCustomMaterialVertexPipeline::DoGenerateVarTangentAndBinormal()
+{
+ Vertex().AddIncoming("attr_textan", "vec3");
+ Vertex().AddIncoming("attr_binormal", "vec3");
+
+ Vertex() << "\tvarTangent = normal_matrix * attr_textan;" << Endl
+ << "\tvarBinormal = normal_matrix * attr_binormal;" << Endl;
+
+ Vertex() << "\tvarObjTangent = attr_textan;" << Endl << "\tvarObjBinormal = attr_binormal;"
+ << Endl;
+}
+
+
+struct SMaterialClass
+{
+ NVAllocatorCallback *m_Allocator;
+ IDynamicObjectClass *m_Class;
+ bool m_HasTransparency;
+ bool m_HasRefraction;
+ bool m_HasDisplacement;
+ bool m_AlwaysDirty;
+ QT3DSU32 m_ShaderKey;
+ QT3DSU32 m_LayerCount;
+ QT3DSI32 mRefCount;
+ SMaterialClass(NVAllocatorCallback &alloc, IDynamicObjectClass &inCls)
+ : m_Allocator(&alloc)
+ , m_Class(&inCls)
+ , m_HasTransparency(false)
+ , m_HasRefraction(false)
+ , m_HasDisplacement(false)
+ , m_AlwaysDirty(false)
+ , m_ShaderKey(0)
+ , m_LayerCount(0)
+ , mRefCount(0)
+ {
+ }
+
+ ~SMaterialClass() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(*m_Allocator)
+
+ void AfterWrite()
+ {
+ m_Allocator = NULL;
+ m_Class = NULL;
+ mRefCount = 0;
+ }
+
+ void AfterRead(NVAllocatorCallback &alloc, IDynamicObjectClass &inCls)
+ {
+ m_Allocator = &alloc;
+ m_Class = &inCls;
+ mRefCount = 0;
+ }
+};
+
+typedef nvhash_map<CRegisteredString, NVScopedRefCounted<SMaterialClass>> TStringMaterialMap;
+typedef eastl::pair<CRegisteredString, CRegisteredString> TStrStrPair;
+
+namespace eastl {
+template <>
+struct hash<TStrStrPair>
+{
+ size_t operator()(const TStrStrPair &item) const
+ {
+ return hash<CRegisteredString>()(item.first) ^ hash<CRegisteredString>()(item.second);
+ }
+};
+}
+
+struct SShaderMapKey
+{
+ TStrStrPair m_Name;
+ eastl::vector<SShaderPreprocessorFeature> m_Features;
+ TessModeValues::Enum m_TessMode;
+ bool m_WireframeMode;
+ SShaderDefaultMaterialKey m_MaterialKey;
+ size_t m_HashCode;
+ SShaderMapKey(TStrStrPair inName, TShaderFeatureSet inFeatures, TessModeValues::Enum inTessMode,
+ bool inWireframeMode, SShaderDefaultMaterialKey inMaterialKey)
+ : m_Name(inName)
+ , m_Features(inFeatures.begin(), inFeatures.end())
+ , m_TessMode(inTessMode)
+ , m_WireframeMode(inWireframeMode)
+ , m_MaterialKey(inMaterialKey)
+ {
+ m_HashCode = eastl::hash<TStrStrPair>()(m_Name)
+ ^ HashShaderFeatureSet(toDataRef(m_Features.data(), (QT3DSU32)m_Features.size()))
+ ^ eastl::hash<QT3DSU32>()(m_TessMode) ^ eastl::hash<bool>()(m_WireframeMode)
+ ^ eastl::hash<size_t>()(inMaterialKey.hash());
+ }
+ bool operator==(const SShaderMapKey &inKey) const
+ {
+ return m_Name == inKey.m_Name && m_Features == inKey.m_Features
+ && m_TessMode == inKey.m_TessMode && m_WireframeMode == inKey.m_WireframeMode
+ && m_MaterialKey == inKey.m_MaterialKey;
+ }
+};
+
+namespace eastl {
+template <>
+struct hash<SShaderMapKey>
+{
+ size_t operator()(const SShaderMapKey &inKey) const { return inKey.m_HashCode; }
+};
+}
+
+namespace {
+
+struct SCustomMaterialTextureData
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ qt3ds::render::NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+ qt3ds::render::NVRenderTexture2D *m_Texture;
+ bool m_needsMips;
+ volatile QT3DSI32 mRefCount;
+
+ SCustomMaterialTextureData(NVRenderShaderProgram &inShader, NVRenderTexture2D *inTexture,
+ const char *inTexName, bool needMips)
+ : m_Shader(inShader)
+ , m_Sampler(inTexName, inShader)
+ , m_Texture(inTexture)
+ , m_needsMips(needMips)
+ , mRefCount(0)
+ {
+ }
+
+ void Set(const SPropertyDefinition *inDefinition)
+ {
+ if (m_Texture && inDefinition) {
+ m_Texture->SetMagFilter(inDefinition->m_MagFilterOp);
+ m_Texture->SetMinFilter(inDefinition->m_MinFilterOp);
+ m_Texture->SetTextureWrapS(inDefinition->m_CoordOp);
+ m_Texture->SetTextureWrapT(inDefinition->m_CoordOp);
+ } else if (m_Texture) {
+ // set some defaults
+ m_Texture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ m_Texture->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ m_Texture->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+ }
+
+ if ((m_Texture->GetNumMipmaps() == 0) && m_needsMips)
+ m_Texture->GenerateMipmaps();
+
+ m_Sampler.Set(m_Texture);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+
+ static SCustomMaterialTextureData CreateTextureEntry(NVRenderShaderProgram &inShader,
+ NVRenderTexture2D *inTexture,
+ const char *inTexName, bool needMips)
+ {
+ return SCustomMaterialTextureData(inShader, inTexture, inTexName, needMips);
+ }
+};
+
+typedef eastl::pair<CRegisteredString, NVScopedRefCounted<SCustomMaterialTextureData>>
+ TCustomMaterialTextureEntry;
+
+/**
+ * Cached tessellation property lookups this is on a per mesh base
+ */
+struct SCustomMaterialsTessellationProperties
+{
+ NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessLevel; ///< tesselation value for the edges
+ NVRenderCachedShaderProperty<QT3DSF32> m_InsideTessLevel; ///< tesselation value for the inside
+ NVRenderCachedShaderProperty<QT3DSF32>
+ m_PhongBlend; ///< blending between linear and phong component
+ NVRenderCachedShaderProperty<QT3DSVec2>
+ m_DistanceRange; ///< distance range for min and max tess level
+ NVRenderCachedShaderProperty<QT3DSF32> m_DisableCulling; ///< if set to 1.0 this disables backface
+ ///culling optimization in the tess shader
+
+ SCustomMaterialsTessellationProperties() {}
+ SCustomMaterialsTessellationProperties(NVRenderShaderProgram &inShader)
+ : m_EdgeTessLevel("tessLevelOuter", inShader)
+ , m_InsideTessLevel("tessLevelInner", inShader)
+ , m_PhongBlend("phongBlend", inShader)
+ , m_DistanceRange("distanceRange", inShader)
+ , m_DisableCulling("disableCulling", inShader)
+ {
+ }
+};
+
+/* We setup some shared state on the custom material shaders */
+struct SCustomMaterialShader
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ModelMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat33> m_NormalMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPos;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewportMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CamProperties;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthTexture;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_AOTexture;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeProps;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOpts;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeRot;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOfs;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe2;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbe2Props;
+ NVRenderCachedShaderProperty<QT3DSI32> m_LightCount;
+ NVRenderCachedShaderProperty<QT3DSI32> m_AreaLightCount;
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams;
+ SCustomMaterialsTessellationProperties m_Tessellation;
+ SDynamicShaderProgramFlags m_ProgramFlags;
+ volatile QT3DSI32 mRefCount;
+ SCustomMaterialShader(NVRenderShaderProgram &inShader, SDynamicShaderProgramFlags inFlags)
+ : m_Shader(inShader)
+ , m_ModelMatrix("model_matrix", inShader)
+ , m_ViewProjMatrix("model_view_projection", inShader)
+ , m_ViewMatrix("view_matrix", inShader)
+ , m_NormalMatrix("normal_matrix", inShader)
+ , m_CameraPos("camera_position", inShader)
+ , m_ProjMatrix("view_projection_matrix", inShader)
+ , m_ViewportMatrix("viewport_matrix", inShader)
+ , m_CamProperties("camera_properties", inShader)
+ , m_DepthTexture("depth_sampler", inShader)
+ , m_AOTexture("ao_sampler", inShader)
+ , m_LightProbe("light_probe", inShader)
+ , m_LightProbeProps("light_probe_props", inShader)
+ , m_LightProbeOpts("light_probe_opts", inShader)
+ , m_LightProbeRot("light_probe_rotation", inShader)
+ , m_LightProbeOfs("light_probe_offset", inShader)
+ , m_LightProbe2("light_probe2", inShader)
+ , m_LightProbe2Props("light_probe2_props", inShader)
+ , m_LightCount("uNumLights", inShader)
+ , m_AreaLightCount("uNumAreaLights", inShader)
+ , m_AoShadowParams("cbAoShadow", inShader)
+ , m_Tessellation(inShader)
+ , m_ProgramFlags(inFlags)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+};
+
+struct SMaterialOrComputeShader
+{
+ SCustomMaterialShader *m_MaterialShader;
+ NVRenderShaderProgram *m_ComputeShader;
+ SMaterialOrComputeShader()
+ : m_MaterialShader(NULL)
+ , m_ComputeShader(NULL)
+ {
+ }
+ SMaterialOrComputeShader(SCustomMaterialShader &inMaterialShader)
+ : m_MaterialShader(&inMaterialShader)
+ , m_ComputeShader(NULL)
+ {
+ }
+ SMaterialOrComputeShader(NVRenderShaderProgram &inComputeShader)
+ : m_MaterialShader(NULL)
+ , m_ComputeShader(&inComputeShader)
+ {
+ QT3DS_ASSERT(inComputeShader.GetProgramType() == NVRenderShaderProgram::ProgramType::Compute);
+ }
+ bool IsValid() const { return m_MaterialShader || m_ComputeShader; }
+ bool IsComputeShader() const { return m_ComputeShader != NULL; }
+ bool IsMaterialShader() const { return m_MaterialShader != NULL; }
+ SCustomMaterialShader &MaterialShader()
+ {
+ QT3DS_ASSERT(IsMaterialShader());
+ return *m_MaterialShader;
+ }
+ NVRenderShaderProgram &ComputeShader()
+ {
+ QT3DS_ASSERT(IsComputeShader());
+ return *m_ComputeShader;
+ }
+};
+
+struct SCustomMaterialBuffer
+{
+ CRegisteredString m_Name;
+ NVScopedRefCounted<NVRenderFrameBuffer> m_FrameBuffer;
+ NVScopedRefCounted<NVRenderTexture2D> m_Texture;
+ SAllocateBufferFlags m_Flags;
+
+ SCustomMaterialBuffer(CRegisteredString inName, NVRenderFrameBuffer &inFb,
+ NVRenderTexture2D &inTexture, SAllocateBufferFlags inFlags)
+ : m_Name(inName)
+ , m_FrameBuffer(&inFb)
+ , m_Texture(&inTexture)
+ , m_Flags(inFlags)
+ {
+ }
+ SCustomMaterialBuffer() {}
+};
+
+struct SMaterialSystem;
+typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderVertexBuffer>>
+ TStringVertexBufferMap;
+typedef nvhash_map<CRegisteredString, NVScopedRefCounted<NVRenderInputAssembler>>
+ TStringAssemblerMap;
+
+struct SMaterialLuaContext
+{
+ SCustomMaterial &m_Material;
+ SMaterialClass &m_Class;
+ lua_State &m_LuaState;
+ QT3DSU32 m_LuaId;
+ SMaterialSystem &m_MaterialSystem;
+ TStringVertexBufferMap m_VertexBuffers;
+ TStringAssemblerMap m_InputAssemblers;
+ QT3DSI32 m_RefCount;
+
+ // Per frame render args.
+
+ SCustomMaterialRenderContext *m_RenderContext;
+ NVRenderFrameBuffer *m_Target;
+ TShaderFeatureSet m_FeatureSet;
+ SMaterialOrComputeShader m_CurrentShader;
+ NVRenderInputAssembler *m_CurrentInputAssembler;
+
+ SMaterialLuaContext(SCustomMaterial &inMaterial, SMaterialClass &inClass, lua_State &inLuaState,
+ QT3DSU32 inLuaId, SMaterialSystem &inMaterialSystem,
+ NVAllocatorCallback &inAllocator)
+ : m_Material(inMaterial)
+ , m_Class(inClass)
+ , m_LuaState(inLuaState)
+ , m_LuaId(inLuaId)
+ , m_MaterialSystem(inMaterialSystem)
+ , m_VertexBuffers(inAllocator, "m_VertexBuffers")
+ , m_InputAssemblers(inAllocator, "m_InputAssemblers")
+ , m_RefCount(0)
+ , m_RenderContext(NULL)
+ , m_Target(NULL)
+ , m_CurrentInputAssembler(NULL)
+ {
+ }
+ void Render(SCustomMaterialRenderContext &inRc, NVRenderFrameBuffer *inFb,
+ TShaderFeatureSet inFS)
+ {
+ m_RenderContext = &inRc;
+ m_Target = inFb;
+ m_FeatureSet = inFS;
+ m_CurrentShader = SMaterialOrComputeShader();
+ m_CurrentInputAssembler = NULL;
+ DoRender();
+ }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ DeleteThis();
+ }
+
+ ~SMaterialLuaContext();
+ void DeleteThis();
+ void DoRender();
+ bool GetOrCreateVertexBuffer(const char *inIdStr, QT3DSU32 inSize, QT3DSU32 inStride);
+ NVRenderVertexBuffer *GetVertexBuffer(const char *inIdStr);
+ void OnActivationChange(bool inActive);
+};
+
+struct STopScope
+{
+ lua_State *m_LuaState;
+ int m_Top;
+ STopScope(lua_State *inState)
+ : m_LuaState(inState)
+ , m_Top(lua_gettop(inState))
+ {
+ }
+ ~STopScope() { lua_settop(m_LuaState, m_Top); }
+};
+
+static void *LuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize);
+
+struct SStringMemoryBarrierFlagMap
+{
+ const char8_t *m_Name;
+ qt3ds::render::NVRenderBufferBarrierValues::Enum m_Value;
+ SStringMemoryBarrierFlagMap(const char8_t *nm,
+ qt3ds::render::NVRenderBufferBarrierValues::Enum val)
+ : m_Name(nm)
+ , m_Value(val)
+ {
+ }
+};
+
+SStringMemoryBarrierFlagMap g_StringMemoryFlagMap[] = {
+ SStringMemoryBarrierFlagMap("vertex_attribute",
+ qt3ds::render::NVRenderBufferBarrierValues::VertexAttribArray),
+ SStringMemoryBarrierFlagMap("element_array",
+ qt3ds::render::NVRenderBufferBarrierValues::ElementArray),
+ SStringMemoryBarrierFlagMap("uniform_buffer",
+ qt3ds::render::NVRenderBufferBarrierValues::UniformBuffer),
+ SStringMemoryBarrierFlagMap("texture_fetch",
+ qt3ds::render::NVRenderBufferBarrierValues::TextureFetch),
+ SStringMemoryBarrierFlagMap("shader_image_access",
+ qt3ds::render::NVRenderBufferBarrierValues::ShaderImageAccess),
+ SStringMemoryBarrierFlagMap("command_buffer",
+ qt3ds::render::NVRenderBufferBarrierValues::CommandBuffer),
+ SStringMemoryBarrierFlagMap("pixel_buffer",
+ qt3ds::render::NVRenderBufferBarrierValues::PixelBuffer),
+ SStringMemoryBarrierFlagMap("texture_update",
+ qt3ds::render::NVRenderBufferBarrierValues::TextureUpdate),
+ SStringMemoryBarrierFlagMap("buffer_update",
+ qt3ds::render::NVRenderBufferBarrierValues::BufferUpdate),
+ SStringMemoryBarrierFlagMap("frame_buffer",
+ qt3ds::render::NVRenderBufferBarrierValues::Framebuffer),
+ SStringMemoryBarrierFlagMap("transform_feedback",
+ qt3ds::render::NVRenderBufferBarrierValues::TransformFeedback),
+ SStringMemoryBarrierFlagMap("atomic_counter",
+ qt3ds::render::NVRenderBufferBarrierValues::AtomicCounter),
+ SStringMemoryBarrierFlagMap("shader_storage",
+ qt3ds::render::NVRenderBufferBarrierValues::ShaderStorage),
+};
+
+QT3DSU32 g_StringMemoryFlagMapSize = sizeof(g_StringMemoryFlagMap) / sizeof(*g_StringMemoryFlagMap);
+
+struct SStringBlendFuncMap
+{
+ const char8_t *m_Name;
+ qt3ds::render::NVRenderSrcBlendFunc::Enum m_Value;
+ SStringBlendFuncMap(const char8_t *nm, qt3ds::render::NVRenderSrcBlendFunc::Enum val)
+ : m_Name(nm)
+ , m_Value(val)
+ {
+ }
+};
+
+SStringBlendFuncMap g_BlendFuncMap[] = {
+#define QT3DS_RENDER_HANDLE_BLEND_FUNC(nm) \
+ SStringBlendFuncMap(#nm, qt3ds::render::NVRenderSrcBlendFunc::nm),
+#define QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC(nm) \
+ SStringBlendFuncMap(#nm, qt3ds::render::NVRenderSrcBlendFunc::nm),
+ QT3DS_RENDER_ITERATE_BLEND_FUNC
+#undef QT3DS_RENDER_HANDLE_BLEND_FUNC
+#undef QT3DS_RENDER_HANDLE_SRC_BLEND_FUNC
+};
+
+QT3DSU32 g_BlendFuncMapSize = sizeof(g_BlendFuncMap) / sizeof(*g_BlendFuncMap);
+
+struct SMaterialSystem : public ICustomMaterialSystem
+{
+ typedef nvhash_map<SShaderMapKey, NVScopedRefCounted<SCustomMaterialShader>> TShaderMap;
+ typedef nvhash_map<SCustomMaterial *, NVScopedRefCounted<SMaterialLuaContext>>
+ TMaterialLuaContextMap;
+ typedef eastl::pair<CRegisteredString, SImage *> TAllocatedImageEntry;
+
+ IUICRenderContextCore &m_CoreContext;
+ IUICRenderContext *m_UICContext;
+ mutable qt3ds::render::SPreAllocatedAllocator m_Allocator;
+ TStringMaterialMap m_StringMaterialMap;
+ TShaderMap m_ShaderMap;
+ TMaterialLuaContextMap m_MaterialLuaContextMap;
+ lua_State *m_LuaState;
+ nvvector<TCustomMaterialTextureEntry> m_TextureEntries;
+ nvvector<SCustomMaterialBuffer> m_AllocatedBuffers;
+ nvvector<TAllocatedImageEntry> m_AllocatedImages;
+ bool m_UseFastBlits;
+ eastl::string m_ShaderNameBuilder;
+ QT3DSU64 m_LastFrameTime;
+ QT3DSF32 m_MillisecondsSinceLastFrame;
+ QT3DSI32 mRefCount;
+
+ SMaterialSystem(IUICRenderContextCore &ct)
+ : m_CoreContext(ct)
+ , m_UICContext(NULL)
+ , m_Allocator(ct.GetAllocator())
+ , m_StringMaterialMap(ct.GetAllocator(), "SMaterialSystem::m_StringMaterialMap")
+ , m_ShaderMap(ct.GetAllocator(), "SMaterialSystem::m_ShaderMap")
+ , m_MaterialLuaContextMap(ct.GetAllocator(), "SMaterialSystem::m_MaterialLuaContextMap")
+ , m_LuaState(NULL)
+ , m_TextureEntries(ct.GetAllocator(), "SMaterialSystem::m_TextureEntries")
+ , m_AllocatedBuffers(ct.GetAllocator(), "SMaterialSystem::m_AllocatedBuffers")
+ , m_AllocatedImages(ct.GetAllocator(), "SMaterialSystem::m_AllocatedImages")
+ , m_UseFastBlits(true)
+ , m_LastFrameTime(0)
+ , m_MillisecondsSinceLastFrame(0)
+ , mRefCount(0)
+ {
+ }
+
+ ~SMaterialSystem()
+ {
+ while (m_AllocatedBuffers.size())
+ m_AllocatedBuffers.replace_with_last(0);
+
+ for (QT3DSU32 idx = 0; idx < m_AllocatedImages.size(); ++idx) {
+ SImage *pImage = m_AllocatedImages[idx].second;
+ QT3DS_FREE(m_CoreContext.GetAllocator(), pImage);
+ }
+ m_AllocatedImages.clear();
+
+ if (m_LuaState)
+ lua_close(m_LuaState);
+ m_LuaState = NULL;
+ }
+
+ void ReleaseBuffer(QT3DSU32 inIdx)
+ {
+ // Don't call this on MaterialSystem destroy.
+ // This causes issues for scene liftime buffers
+ // because the resource manager is destroyed before
+ IResourceManager &theManager(m_UICContext->GetResourceManager());
+ SCustomMaterialBuffer &theEntry(m_AllocatedBuffers[inIdx]);
+ theEntry.m_FrameBuffer->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer());
+
+ theManager.Release(*theEntry.m_FrameBuffer);
+ theManager.Release(*theEntry.m_Texture);
+ m_AllocatedBuffers.replace_with_last(inIdx);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_CoreContext.GetAllocator())
+
+ bool IsMaterialRegistered(CRegisteredString inStr) override
+ {
+ return m_StringMaterialMap.find(inStr) != m_StringMaterialMap.end();
+ }
+
+ bool RegisterMaterialClass(CRegisteredString inName,
+ NVConstDataRef<dynamic::SPropertyDeclaration> inProperties) override
+ {
+ if (IsMaterialRegistered(inName))
+ return false;
+ m_CoreContext.GetDynamicObjectSystemCore().Register(
+ inName, inProperties, sizeof(SCustomMaterial), GraphObjectTypes::CustomMaterial);
+ IDynamicObjectClass *theClass =
+ m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ SMaterialClass *theNewClass = QT3DS_NEW(m_Allocator, SMaterialClass)(m_Allocator, *theClass);
+ m_StringMaterialMap.insert(eastl::make_pair(inName, theNewClass));
+ return true;
+ }
+
+ SMaterialClass *GetMaterialClass(CRegisteredString inStr)
+ {
+ TStringMaterialMap::iterator theIter = m_StringMaterialMap.find(inStr);
+ if (theIter != m_StringMaterialMap.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ const SMaterialClass *GetMaterialClass(CRegisteredString inStr) const
+ {
+ return const_cast<SMaterialSystem *>(this)->GetMaterialClass(inStr);
+ }
+
+ virtual NVConstDataRef<SPropertyDefinition>
+ GetCustomMaterialProperties(CRegisteredString inCustomMaterialName) const override
+ {
+ IDynamicObjectClass *theMaterialClass =
+ m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inCustomMaterialName);
+
+ if (theMaterialClass)
+ return theMaterialClass->GetProperties();
+
+ return NVConstDataRef<SPropertyDefinition>();
+ }
+
+ virtual QT3DSU32 FindBuffer(CRegisteredString inName)
+ {
+ for (QT3DSU32 idx = 0, end = m_AllocatedBuffers.size(); idx < end; ++idx)
+ if (m_AllocatedBuffers[idx].m_Name == inName)
+ return idx;
+ return m_AllocatedBuffers.size();
+ }
+
+ virtual QT3DSU32 FindAllocatedImage(CRegisteredString inName)
+ {
+ for (QT3DSU32 idx = 0, end = m_AllocatedImages.size(); idx < end; ++idx)
+ if (m_AllocatedImages[idx].first == inName)
+ return idx;
+ return QT3DSU32(-1);
+ }
+
+ virtual bool TextureNeedsMips(const SPropertyDefinition *inPropDec,
+ qt3ds::render::NVRenderTexture2D *inTexture)
+ {
+ if (inPropDec && inTexture) {
+ return bool((inPropDec->m_MinFilterOp == NVRenderTextureMinifyingOp::LinearMipmapLinear)
+ && (inTexture->GetNumMipmaps() == 0));
+ }
+
+ return false;
+ }
+
+ virtual void SetTexture(NVRenderShaderProgram &inShader, CRegisteredString inPropName,
+ NVRenderTexture2D *inTexture,
+ const SPropertyDefinition *inPropDec = NULL, bool needMips = false)
+ {
+ SCustomMaterialTextureData *theTextureEntry(NULL);
+ for (QT3DSU32 idx = 0, end = m_TextureEntries.size(); idx < end && theTextureEntry == NULL;
+ ++idx) {
+ if (m_TextureEntries[idx].first == inPropName
+ && m_TextureEntries[idx].second->m_Shader.mPtr == &inShader
+ && m_TextureEntries[idx].second->m_Texture == inTexture) {
+ theTextureEntry = m_TextureEntries[idx].second;
+ break;
+ }
+ }
+ if (theTextureEntry == NULL) {
+ NVScopedRefCounted<SCustomMaterialTextureData> theNewEntry =
+ QT3DS_NEW(m_CoreContext.GetAllocator(), SCustomMaterialTextureData)(
+ SCustomMaterialTextureData::CreateTextureEntry(inShader, inTexture, inPropName,
+ needMips));
+ m_TextureEntries.push_back(eastl::make_pair(inPropName, theNewEntry));
+ theTextureEntry = theNewEntry.mPtr;
+ }
+ theTextureEntry->Set(inPropDec);
+ }
+
+ void SetPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<CRegisteredString> inNames) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetPropertyEnumNames(inName, inPropName,
+ inNames);
+ }
+
+ void SetPropertyTextureSettings(CRegisteredString inName, CRegisteredString inPropName,
+ CRegisteredString inPropPath,
+ NVRenderTextureTypeValue::Enum inTexType,
+ NVRenderTextureCoordOp::Enum inCoordOp,
+ NVRenderTextureMagnifyingOp::Enum inMagFilterOp,
+ NVRenderTextureMinifyingOp::Enum inMinFilterOp) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inName);
+ if (theClass && inTexType == NVRenderTextureTypeValue::Displace) {
+ theClass->m_HasDisplacement = true;
+ }
+ m_CoreContext.GetDynamicObjectSystemCore().SetPropertyTextureSettings(
+ inName, inPropName, inPropPath, inTexType, inCoordOp, inMagFilterOp, inMinFilterOp);
+ }
+
+ void SetMaterialClassShader(CRegisteredString inName, const char8_t *inShaderType,
+ const char8_t *inShaderVersion, const char8_t *inShaderData,
+ bool inHasGeomShader, bool inIsComputeShader) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetShaderData(inName, inShaderData, inShaderType,
+ inShaderVersion, inHasGeomShader,
+ inIsComputeShader);
+ }
+
+ SCustomMaterial *CreateCustomMaterial(CRegisteredString inName,
+ NVAllocatorCallback &inSceneGraphAllocator) override
+ {
+ SCustomMaterial *theMaterial = static_cast<SCustomMaterial *>(
+ m_CoreContext.GetDynamicObjectSystemCore().CreateInstance(inName,
+ inSceneGraphAllocator));
+ SMaterialClass *theClass = GetMaterialClass(inName);
+
+ if (theMaterial) {
+ QT3DSU32 key = 0, count = 0;
+ if (theClass) {
+ key = theClass->m_ShaderKey;
+ count = theClass->m_LayerCount;
+ }
+ theMaterial->Initialize(key, count);
+ }
+
+ return theMaterial;
+ }
+
+ void SetCustomMaterialTransparency(CRegisteredString inName, bool inHasTransparency) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inName);
+
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ theClass->m_HasTransparency = inHasTransparency;
+ }
+
+ void SetCustomMaterialRefraction(CRegisteredString inName, bool inHasRefraction) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inName);
+
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ theClass->m_HasRefraction = inHasRefraction;
+ }
+
+ void SetCustomMaterialAlwaysDirty(CRegisteredString inName, bool inIsAlwaysDirty) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inName);
+
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ theClass->m_AlwaysDirty = inIsAlwaysDirty;
+ }
+
+ void SetCustomMaterialShaderKey(CRegisteredString inName, QT3DSU32 inShaderKey) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inName);
+
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ theClass->m_ShaderKey = inShaderKey;
+ }
+
+ void SetCustomMaterialLayerCount(CRegisteredString inName, QT3DSU32 inLayerCount) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inName);
+
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ theClass->m_LayerCount = inLayerCount;
+ }
+
+ void SetCustomMaterialCommands(CRegisteredString inName,
+ NVConstDataRef<dynamic::SCommand *> inCommands) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetRenderCommands(inName, inCommands);
+ }
+
+ CRegisteredString GetShaderCacheKey(CRenderString &inShaderKeyBuffer, const char8_t *inId,
+ const char8_t *inProgramMacro,
+ const dynamic::SDynamicShaderProgramFlags &inFlags)
+ {
+ inShaderKeyBuffer.assign(inId);
+ if (inProgramMacro && *inProgramMacro) {
+ inShaderKeyBuffer.append("#");
+ inShaderKeyBuffer.append(inProgramMacro);
+ }
+ if (inFlags.IsTessellationEnabled()) {
+ inShaderKeyBuffer.append("#");
+ inShaderKeyBuffer.append(TessModeValues::toString(inFlags.m_TessMode));
+ }
+ if (inFlags.IsGeometryShaderEnabled() && inFlags.m_WireframeMode) {
+ inShaderKeyBuffer.append("#");
+ inShaderKeyBuffer.append(inFlags.wireframeToString(inFlags.m_WireframeMode));
+ }
+
+ return m_CoreContext.GetStringTable().RegisterStr(inShaderKeyBuffer.c_str());
+ }
+
+ NVRenderShaderProgram *GetShader(SCustomMaterialRenderContext &inRenderContext,
+ const SCustomMaterial &inMaterial,
+ const SBindShader &inCommand, TShaderFeatureSet inFeatureSet,
+ const dynamic::SDynamicShaderProgramFlags &inFlags)
+ {
+ ICustomMaterialShaderGenerator &theMaterialGenerator(
+ m_UICContext->GetCustomMaterialShaderGenerator());
+
+ // generate key
+ CRenderString theShaderKeyBuffer;
+ CRegisteredString theKey = GetShaderCacheKey(theShaderKeyBuffer, inCommand.m_ShaderPath,
+ inCommand.m_ShaderDefine, inFlags);
+
+ SCustomMaterialVertexPipeline thePipeline(m_UICContext,
+ inRenderContext.m_Model.m_TessellationMode);
+
+ NVRenderShaderProgram *theProgram = theMaterialGenerator.GenerateShader(
+ inMaterial, inRenderContext.m_MaterialKey, thePipeline, inFeatureSet,
+ inRenderContext.m_Lights, inRenderContext.m_FirstImage,
+ (inMaterial.m_hasTransparency || inMaterial.m_hasRefraction),
+ "custom material pipeline-- ", inCommand.m_ShaderPath.c_str());
+
+ return theProgram;
+ }
+
+ SMaterialOrComputeShader BindShader(SCustomMaterialRenderContext &inRenderContext,
+ const SCustomMaterial &inMaterial,
+ const SBindShader &inCommand,
+ TShaderFeatureSet inFeatureSet)
+ {
+ NVRenderShaderProgram *theProgram = NULL;
+
+ SDynamicShaderProgramFlags theFlags(inRenderContext.m_Model.m_TessellationMode,
+ inRenderContext.m_Subset.m_WireframeMode);
+ theFlags.SetTessellationEnabled(inRenderContext.m_Model.m_TessellationMode
+ != TessModeValues::NoTess);
+ theFlags.SetGeometryShaderEnabled(inRenderContext.m_Subset.m_WireframeMode);
+
+ SShaderMapKey skey = SShaderMapKey(
+ TStrStrPair(inCommand.m_ShaderPath, inCommand.m_ShaderDefine), inFeatureSet,
+ theFlags.m_TessMode, theFlags.m_WireframeMode, inRenderContext.m_MaterialKey);
+ eastl::pair<TShaderMap::iterator, bool> theInsertResult(m_ShaderMap.insert(
+ eastl::make_pair(skey, NVScopedRefCounted<SCustomMaterialShader>(NULL))));
+
+ if (theInsertResult.second) {
+ theProgram = GetShader(inRenderContext, inMaterial, inCommand, inFeatureSet, theFlags);
+
+ if (theProgram) {
+ theInsertResult.first->second =
+ QT3DS_NEW(m_Allocator, SCustomMaterialShader)(*theProgram, theFlags);
+ }
+ } else if (theInsertResult.first->second)
+ theProgram = theInsertResult.first->second->m_Shader;
+
+ if (theProgram) {
+ if (theProgram->GetProgramType() == NVRenderShaderProgram::ProgramType::Graphics) {
+ if (theInsertResult.first->second) {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetActiveShader(theInsertResult.first->second->m_Shader);
+ }
+
+ return *theInsertResult.first->second;
+ } else {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetActiveShader(theProgram);
+ return *(static_cast<NVRenderShaderProgram *>(theProgram));
+ }
+ }
+ return SMaterialOrComputeShader();
+ }
+
+ SMaterialOrComputeShader BindShaderFromLua(SCustomMaterialRenderContext &inRenderContext,
+ const SBindShader &inCommand,
+ TShaderFeatureSet inFeatureSet)
+ {
+ SDynamicShaderProgramFlags theFlags(inRenderContext.m_Model.m_TessellationMode,
+ inRenderContext.m_Subset.m_WireframeMode);
+ theFlags.SetTessellationEnabled(inRenderContext.m_Model.m_TessellationMode
+ != TessModeValues::NoTess);
+ theFlags.SetGeometryShaderEnabled(inRenderContext.m_Subset.m_WireframeMode);
+
+ TShaderAndFlags theProgramAndFlags =
+ m_UICContext->GetDynamicObjectSystem().GetShaderProgram(
+ inCommand.m_ShaderPath, inCommand.m_ShaderDefine, inFeatureSet, theFlags);
+
+ NVRenderShaderProgram *theProgram = theProgramAndFlags.first;
+ if (theProgram) {
+ if (theProgram->GetProgramType() == NVRenderShaderProgram::ProgramType::Graphics) {
+ SShaderDefaultMaterialKey theMaterialKey = 0;
+ SShaderMapKey skey = SShaderMapKey(
+ TStrStrPair(inCommand.m_ShaderPath, inCommand.m_ShaderDefine), inFeatureSet,
+ theFlags.m_TessMode, theFlags.m_WireframeMode, theMaterialKey);
+ eastl::pair<TShaderMap::iterator, bool> theInsertResult(m_ShaderMap.insert(
+ eastl::make_pair(skey, NVScopedRefCounted<SCustomMaterialShader>(NULL))));
+
+ if (theInsertResult.second) {
+ if (theProgram)
+ theInsertResult.first->second = QT3DS_NEW(m_Allocator, SCustomMaterialShader)(
+ *theProgram, theProgramAndFlags.second);
+ }
+
+ if (theInsertResult.first->second) {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetActiveShader(theInsertResult.first->second->m_Shader);
+ }
+
+ return *theInsertResult.first->second;
+ } else {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetActiveShader(theProgram);
+ return *(static_cast<NVRenderShaderProgram *>(theProgram));
+ }
+ }
+ return SMaterialOrComputeShader();
+ }
+
+ void DoApplyInstanceValue(SCustomMaterial & /* inMaterial */, QT3DSU8 *inDataPtr,
+ CRegisteredString inPropertyName,
+ NVRenderShaderDataTypes::Enum inPropertyType,
+ NVRenderShaderProgram &inShader,
+ const SPropertyDefinition &inDefinition)
+ {
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(inPropertyName);
+ using namespace qt3ds::render;
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType() == inPropertyType) {
+ if (inPropertyType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ StaticAssert<sizeof(CRegisteredString)
+ == sizeof(NVRenderTexture2DPtr)>::valid_expression();
+ CRegisteredString *theStrPtr = reinterpret_cast<CRegisteredString *>(inDataPtr);
+ IBufferManager &theBufferManager(m_UICContext->GetBufferManager());
+ NVRenderTexture2D *theTexture = NULL;
+
+ if (theStrPtr->IsValid()) {
+ SImageTextureData theTextureData =
+ theBufferManager.LoadRenderImage(*theStrPtr);
+ if (theTextureData.m_Texture) {
+ theTexture = theTextureData.m_Texture;
+ SetTexture(inShader, inPropertyName, theTexture, &inDefinition,
+ TextureNeedsMips(&inDefinition, theTexture));
+ }
+ }
+ } else {
+ switch (inPropertyType) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(type) \
+ case NVRenderShaderDataTypes::type: \
+ inShader.SetPropertyValue(theConstant, *(reinterpret_cast<type *>(inDataPtr))); \
+ break;
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ } else {
+ qCCritical(INVALID_OPERATION,
+ "CustomMaterial ApplyInstanceValue command datatype and "
+ "shader datatypes differ for property %s",
+ inPropertyName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ void ApplyInstanceValue(SCustomMaterial &inMaterial, SMaterialClass &inClass,
+ NVRenderShaderProgram &inShader, const SApplyInstanceValue &inCommand)
+ {
+ // sanity check
+ if (inCommand.m_PropertyName.IsValid()) {
+ bool canGetData =
+ inCommand.m_ValueOffset + getSizeofShaderDataType(inCommand.m_ValueType)
+ <= inMaterial.m_DataSectionByteSize;
+ if (canGetData == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ QT3DSU8 *dataPtr = inMaterial.GetDataSectionBegin() + inCommand.m_ValueOffset;
+ const SPropertyDefinition *theDefinition =
+ inClass.m_Class->FindPropertyByName(inCommand.m_PropertyName);
+ if (theDefinition)
+ DoApplyInstanceValue(inMaterial, dataPtr, inCommand.m_PropertyName,
+ inCommand.m_ValueType, inShader, *theDefinition);
+ } else {
+ NVConstDataRef<SPropertyDefinition> theDefs = inClass.m_Class->GetProperties();
+ for (QT3DSU32 idx = 0, end = theDefs.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(theDefs[idx]);
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(theDefinition.m_Name);
+
+ // This is fine, the property wasn't found and we continue, no problem.
+ if (!theConstant)
+ continue;
+ QT3DSU8 *dataPtr = inMaterial.GetDataSectionBegin() + theDefinition.m_Offset;
+ DoApplyInstanceValue(inMaterial, dataPtr, theDefinition.m_Name,
+ theDefinition.m_DataType, inShader, theDefinition);
+ }
+ }
+ }
+
+ void ApplyBlending(const SApplyBlending &inCommand)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+
+ theContext.SetBlendingEnabled(true);
+
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc =
+ qt3ds::render::NVRenderBlendFunctionArgument(
+ inCommand.m_SrcBlendFunc, inCommand.m_DstBlendFunc, inCommand.m_SrcBlendFunc,
+ inCommand.m_DstBlendFunc);
+
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+
+ theContext.SetBlendFunction(blendFunc);
+ theContext.SetBlendEquation(blendEqu);
+ }
+
+ // we currently only bind a source texture
+ const NVRenderTexture2D *ApplyBufferValue(const SCustomMaterial &inMaterial,
+ NVRenderShaderProgram &inShader,
+ const SApplyBufferValue &inCommand,
+ const NVRenderTexture2D *inSourceTexture)
+ {
+ const NVRenderTexture2D *theTexture = NULL;
+
+ if (inCommand.m_BufferName.IsValid()) {
+ QT3DSU32 bufferIdx = FindBuffer(inCommand.m_BufferName);
+ if (bufferIdx < m_AllocatedBuffers.size()) {
+ SCustomMaterialBuffer &theEntry(m_AllocatedBuffers[bufferIdx]);
+ theTexture = theEntry.m_Texture;
+ } else {
+ // we must have allocated the read target before
+ qCCritical(INTERNAL_ERROR,
+ "CustomMaterial: ApplyBufferValue: Failed to setup read target");
+ QT3DS_ASSERT(false);
+ }
+ } else
+ theTexture = inSourceTexture;
+
+ if (inCommand.m_ParamName.IsValid()) {
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(inCommand.m_ParamName);
+
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType()
+ != NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ qCCritical(INVALID_OPERATION,
+ "CustomMaterial %s: Binding buffer to parameter %s that is not a texture",
+ inMaterial.m_ClassName.c_str(), inCommand.m_ParamName.c_str());
+ QT3DS_ASSERT(false);
+ } else {
+ SetTexture(inShader, inCommand.m_ParamName,
+ const_cast<NVRenderTexture2D *>(theTexture));
+ }
+ }
+ }
+
+ return theTexture;
+ }
+
+ void AllocateBuffer(const SAllocateBuffer &inCommand, NVRenderFrameBuffer *inTarget)
+ {
+ STextureDetails theSourceTextureDetails;
+ NVRenderTexture2D *theTexture = NULL;
+ // get color attachment we always assume at location 0
+ if (inTarget) {
+ NVRenderTextureOrRenderBuffer theSourceTexture =
+ inTarget->GetAttachment(NVRenderFrameBufferAttachments::Color0);
+ // we need a texture
+ if (theSourceTexture.HasTexture2D()) {
+ theSourceTextureDetails = theSourceTexture.GetTexture2D()->GetTextureDetails();
+ } else {
+ qCCritical(INVALID_OPERATION, "CustomMaterial %s: Invalid source texture",
+ inCommand.m_Name.c_str());
+ QT3DS_ASSERT(false);
+ return;
+ }
+ } else {
+ NVRenderContext &theContext = m_UICContext->GetRenderContext();
+ // if we allocate a buffer based on the default target use viewport to get the dimension
+ NVRenderRect theViewport(theContext.GetViewport());
+ theSourceTextureDetails.m_Height = theViewport.m_Height;
+ theSourceTextureDetails.m_Width = theViewport.m_Width;
+ }
+
+ QT3DSU32 theWidth = (QT3DSU32)(theSourceTextureDetails.m_Width * inCommand.m_SizeMultiplier);
+ QT3DSU32 theHeight = (QT3DSU32)(theSourceTextureDetails.m_Height * inCommand.m_SizeMultiplier);
+ NVRenderTextureFormats::Enum theFormat = inCommand.m_Format;
+ if (theFormat == NVRenderTextureFormats::Unknown)
+ theFormat = theSourceTextureDetails.m_Format;
+ IResourceManager &theResourceManager(m_UICContext->GetResourceManager());
+ // size intentionally requiried every loop;
+ QT3DSU32 bufferIdx = FindBuffer(inCommand.m_Name);
+ if (bufferIdx < m_AllocatedBuffers.size()) {
+ SCustomMaterialBuffer &theEntry(m_AllocatedBuffers[bufferIdx]);
+ STextureDetails theDetails = theEntry.m_Texture->GetTextureDetails();
+ if (theDetails.m_Width == theWidth && theDetails.m_Height == theHeight
+ && theDetails.m_Format == theFormat) {
+ theTexture = theEntry.m_Texture;
+ } else {
+ ReleaseBuffer(bufferIdx);
+ }
+ }
+
+ if (theTexture == NULL) {
+ NVRenderFrameBuffer *theFB(theResourceManager.AllocateFrameBuffer());
+ NVRenderTexture2D *theTexture(
+ theResourceManager.AllocateTexture2D(theWidth, theHeight, theFormat));
+ theTexture->SetMagFilter(inCommand.m_FilterOp);
+ theTexture->SetMinFilter(
+ static_cast<NVRenderTextureMinifyingOp::Enum>(inCommand.m_FilterOp));
+ theTexture->SetTextureWrapS(inCommand.m_TexCoordOp);
+ theTexture->SetTextureWrapT(inCommand.m_TexCoordOp);
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0, *theTexture);
+ m_AllocatedBuffers.push_back(SCustomMaterialBuffer(
+ inCommand.m_Name, *theFB, *theTexture, inCommand.m_BufferFlags));
+ }
+ }
+
+ NVRenderFrameBuffer *BindBuffer(const SCustomMaterial &inMaterial, const SBindBuffer &inCommand,
+ bool &outClearTarget, QT3DSVec2 &outDestSize)
+ {
+ NVRenderFrameBuffer *theBuffer = NULL;
+ NVRenderTexture2D *theTexture = NULL;
+
+ // search for the buffer
+ QT3DSU32 bufferIdx = FindBuffer(inCommand.m_BufferName);
+ if (bufferIdx < m_AllocatedBuffers.size()) {
+ theBuffer = m_AllocatedBuffers[bufferIdx].m_FrameBuffer;
+ theTexture = m_AllocatedBuffers[bufferIdx].m_Texture;
+ }
+
+ if (theBuffer == NULL) {
+ qCCritical(INVALID_OPERATION, "Effect %s: Failed to find buffer %s for bind",
+ inMaterial.m_ClassName.c_str(), inCommand.m_BufferName.c_str());
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ if (theTexture) {
+ STextureDetails theDetails(theTexture->GetTextureDetails());
+ m_UICContext->GetRenderContext().SetViewport(
+ NVRenderRect(0, 0, (QT3DSU32)theDetails.m_Width, (QT3DSU32)theDetails.m_Height));
+ outDestSize = QT3DSVec2((QT3DSF32)theDetails.m_Width, (QT3DSF32)theDetails.m_Height);
+ outClearTarget = inCommand.m_NeedsClear;
+ }
+
+ return theBuffer;
+ }
+
+ void computeScreenCoverage(SCustomMaterialRenderContext &inRenderContext, QT3DSI32 *xMin,
+ QT3DSI32 *yMin, QT3DSI32 *xMax, QT3DSI32 *yMax)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ TNVBounds2BoxPoints outPoints;
+ QT3DSVec4 projMin(QT3DS_MAX_REAL);
+ QT3DSVec4 projMax(-QT3DS_MAX_REAL);
+
+ // get points
+ inRenderContext.m_Subset.m_Bounds.expand(outPoints);
+ for (QT3DSU32 idx = 0; idx < 8; ++idx) {
+ QT3DSVec4 homPoint(outPoints[idx], 1.0);
+ QT3DSVec4 projPoint = inRenderContext.m_ModelViewProjection.transform(homPoint);
+ projPoint /= projPoint.w;
+
+ if (projMin.x > projPoint.x)
+ projMin.x = projPoint.x;
+ if (projMin.y > projPoint.y)
+ projMin.y = projPoint.y;
+ if (projMin.z > projPoint.z)
+ projMin.z = projPoint.z;
+
+ if (projMax.x < projPoint.x)
+ projMax.x = projPoint.x;
+ if (projMax.y < projPoint.y)
+ projMax.y = projPoint.y;
+ if (projMax.z < projPoint.z)
+ projMax.z = projPoint.z;
+ }
+
+ NVRenderRect theViewport(theContext.GetViewport());
+ QT3DSI32 x1 = QT3DSI32(projMax.x * (theViewport.m_Width / 2)
+ + (theViewport.m_X + (theViewport.m_Width / 2)));
+ QT3DSI32 y1 = QT3DSI32(projMax.y * (theViewport.m_Height / 2)
+ + (theViewport.m_Y + (theViewport.m_Height / 2)));
+
+ QT3DSI32 x2 = QT3DSI32(projMin.x * (theViewport.m_Width / 2)
+ + (theViewport.m_X + (theViewport.m_Width / 2)));
+ QT3DSI32 y2 = QT3DSI32(projMin.y * (theViewport.m_Height / 2)
+ + (theViewport.m_Y + (theViewport.m_Height / 2)));
+
+ if (x1 > x2) {
+ *xMin = x2;
+ *xMax = x1;
+ } else {
+ *xMin = x1;
+ *xMax = x2;
+ }
+ if (y1 > y2) {
+ *yMin = y2;
+ *yMax = y1;
+ } else {
+ *yMin = y1;
+ *yMax = y2;
+ }
+ }
+
+ void BlitFramebuffer(SCustomMaterialRenderContext &inRenderContext,
+ const SApplyBlitFramebuffer &inCommand, NVRenderFrameBuffer *inTarget)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ // we change the read/render targets here
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __framebuffer(
+ theContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ // we may alter scissor
+ NVRenderContextScopedProperty<bool> theScissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled);
+
+ if (inCommand.m_DestBufferName.IsValid()) {
+ QT3DSU32 bufferIdx = FindBuffer(inCommand.m_DestBufferName);
+ if (bufferIdx < m_AllocatedBuffers.size()) {
+ SCustomMaterialBuffer &theEntry(m_AllocatedBuffers[bufferIdx]);
+ theContext.SetRenderTarget(theEntry.m_FrameBuffer);
+ } else {
+ // we must have allocated the read target before
+ qCCritical(INTERNAL_ERROR,
+ "CustomMaterial: BlitFramebuffer: Failed to setup render target");
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ // our dest is the default render target
+ theContext.SetRenderTarget(inTarget);
+ }
+
+ if (inCommand.m_SourceBufferName.IsValid()) {
+ QT3DSU32 bufferIdx = FindBuffer(inCommand.m_SourceBufferName);
+ if (bufferIdx < m_AllocatedBuffers.size()) {
+ SCustomMaterialBuffer &theEntry(m_AllocatedBuffers[bufferIdx]);
+ theContext.SetReadTarget(theEntry.m_FrameBuffer);
+ theContext.SetReadBuffer(NVReadFaces::Color0);
+ } else {
+ // we must have allocated the read target before
+ qCCritical(INTERNAL_ERROR,
+ "CustomMaterial: BlitFramebuffer: Failed to setup read target");
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ // our source is the default read target
+ // depending on what we render we assume color0 or back
+ theContext.SetReadTarget(inTarget);
+ NVReadFaces::Enum value = (inTarget) ? NVReadFaces::Color0 : NVReadFaces::Back;
+ theContext.SetReadBuffer(value);
+ }
+
+ NVRenderRect theViewport(theContext.GetViewport());
+ theContext.SetScissorTestEnabled(false);
+
+ if (!m_UseFastBlits) {
+ // only copy sreen amount of pixels
+ QT3DSI32 xMin, yMin, xMax, yMax;
+ computeScreenCoverage(inRenderContext, &xMin, &yMin, &xMax, &yMax);
+
+ // same dimension
+ theContext.BlitFramebuffer(xMin, yMin, xMax, yMax, xMin, yMin, xMax, yMax,
+ NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+ } else {
+ // same dimension
+ theContext.BlitFramebuffer(
+ theViewport.m_X, theViewport.m_Y, theViewport.m_X + theViewport.m_Width,
+ theViewport.m_Y + theViewport.m_Height, theViewport.m_X, theViewport.m_Y,
+ theViewport.m_X + theViewport.m_Width, theViewport.m_Y + theViewport.m_Height,
+ NVRenderClearValues::Color, NVRenderTextureMagnifyingOp::Nearest);
+ }
+ }
+
+ SLayerGlobalRenderProperties
+ GetLayerGlobalRenderProperties(SCustomMaterialRenderContext &inRenderContext)
+ {
+ const SLayer &theLayer = inRenderContext.m_Layer;
+ const SLayerRenderData &theData = inRenderContext.m_LayerData;
+
+ return SLayerGlobalRenderProperties(
+ theLayer, const_cast<SCamera &>(inRenderContext.m_Camera), theData.m_CameraDirection,
+ inRenderContext.m_Lights, NVDataRef<QT3DSVec3>(), theData.m_ShadowMapManager.mPtr,
+ const_cast<NVRenderTexture2D *>(inRenderContext.m_DepthTexture),
+ const_cast<NVRenderTexture2D *>(inRenderContext.m_AOTexture), theLayer.m_LightProbe,
+ theLayer.m_LightProbe2, theLayer.m_ProbeHorizon, theLayer.m_ProbeBright,
+ theLayer.m_Probe2Window, theLayer.m_Probe2Pos, theLayer.m_Probe2Fade,
+ theLayer.m_ProbeFov);
+ }
+
+ void RenderPass(SCustomMaterialRenderContext &inRenderContext, SCustomMaterialShader &inShader,
+ NVRenderTexture2D * /* inSourceTexture */
+ ,
+ NVRenderFrameBuffer *inFrameBuffer, bool inRenderTargetNeedsClear,
+ NVRenderInputAssembler &inAssembler, QT3DSU32 inCount, QT3DSU32 inOffset)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetRenderTarget(inFrameBuffer);
+
+ QT3DSVec4 clearColor(0.0);
+ NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ theContext, &NVRenderContext::GetClearColor, &NVRenderContext::SetClearColor,
+ clearColor);
+ if (inRenderTargetNeedsClear) {
+ theContext.Clear(qt3ds::render::NVRenderClearValues::Color);
+ }
+
+ ICustomMaterialShaderGenerator &theMaterialGenerator(
+ m_UICContext->GetCustomMaterialShaderGenerator());
+
+ theMaterialGenerator.SetMaterialProperties(
+ *inShader.m_Shader, inRenderContext.m_Material, QT3DSVec2(1.0, 1.0),
+ inRenderContext.m_ModelViewProjection, inRenderContext.m_NormalMatrix,
+ inRenderContext.m_ModelMatrix, inRenderContext.m_FirstImage, 1.0,
+ GetLayerGlobalRenderProperties(inRenderContext));
+
+ // I think the prim type should always be fetched from the
+ // current mesh subset setup because there you get the actual draw mode
+ // for this frame
+ NVRenderDrawMode::Enum theDrawMode = inAssembler.GetPrimitiveType();
+
+ // tesselation
+ if (inRenderContext.m_Subset.m_PrimitiveType == NVRenderDrawMode::Patches) {
+ QT3DSVec2 camProps(inRenderContext.m_Camera.m_ClipNear,
+ inRenderContext.m_Camera.m_ClipFar);
+ theDrawMode = inRenderContext.m_Subset.m_PrimitiveType;
+ inShader.m_Tessellation.m_EdgeTessLevel.Set(inRenderContext.m_Subset.m_EdgeTessFactor);
+ inShader.m_Tessellation.m_InsideTessLevel.Set(
+ inRenderContext.m_Subset.m_InnerTessFactor);
+ // the blend value is hardcoded
+ inShader.m_Tessellation.m_PhongBlend.Set(0.75);
+ // this should finally be based on some user input
+ inShader.m_Tessellation.m_DistanceRange.Set(camProps);
+ // enable culling
+ inShader.m_Tessellation.m_DisableCulling.Set(0.0);
+ }
+
+ if (inRenderContext.m_Subset.m_WireframeMode) {
+ NVRenderRect theViewport(theContext.GetViewport());
+ QT3DSMat44 vpMatrix;
+ vpMatrix.column0 = QT3DSVec4((float)theViewport.m_Width / 2.0f, 0.0, 0.0, 0.0);
+ vpMatrix.column1 = QT3DSVec4(0.0, (float)theViewport.m_Height / 2.0f, 0.0, 0.0);
+ vpMatrix.column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ vpMatrix.column3 =
+ QT3DSVec4((float)theViewport.m_Width / 2.0f + (float)theViewport.m_X,
+ (float)theViewport.m_Height / 2.0f + (float)theViewport.m_Y, 0.0, 1.0);
+
+ inShader.m_ViewportMatrix.Set(vpMatrix);
+ }
+
+ theContext.SetInputAssembler(&inAssembler);
+
+ theContext.SetCullingEnabled(true);
+ QT3DSU32 count = inCount;
+ QT3DSU32 offset = inOffset;
+
+ theContext.Draw(theDrawMode, count, offset);
+ }
+
+ void DoRenderCustomMaterial(SCustomMaterialRenderContext &inRenderContext,
+ const SCustomMaterial &inMaterial, SMaterialClass &inClass,
+ NVRenderFrameBuffer *inTarget, TShaderFeatureSet inFeatureSet)
+ {
+ NVRenderContext &theContext = m_UICContext->GetRenderContext();
+ SCustomMaterialShader *theCurrentShader(NULL);
+
+ NVRenderFrameBuffer *theCurrentRenderTarget(inTarget);
+ NVRenderRect theOriginalViewport(theContext.GetViewport());
+ NVRenderTexture2D *theCurrentSourceTexture = 0;
+
+ // for refrative materials we come from the transparent render path
+ // but we do not want to do blending
+ bool wasBlendingEnabled = theContext.IsBlendingEnabled();
+ if (inMaterial.m_hasRefraction)
+ theContext.SetBlendingEnabled(false);
+
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __framebuffer(
+ theContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport);
+
+ QT3DSVec2 theDestSize;
+ bool theRenderTargetNeedsClear = false;
+
+ NVConstDataRef<dynamic::SCommand *> theCommands(inClass.m_Class->GetRenderCommands());
+ for (QT3DSU32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd;
+ ++commandIdx) {
+ const SCommand &theCommand(*theCommands[commandIdx]);
+
+ switch (theCommand.m_Type) {
+ case CommandTypes::AllocateBuffer:
+ AllocateBuffer(static_cast<const SAllocateBuffer &>(theCommand), inTarget);
+ break;
+ case CommandTypes::BindBuffer:
+ theCurrentRenderTarget =
+ BindBuffer(inMaterial, static_cast<const SBindBuffer &>(theCommand),
+ theRenderTargetNeedsClear, theDestSize);
+ break;
+ case CommandTypes::BindTarget:
+ // Restore the previous render target and info.
+ theCurrentRenderTarget = inTarget;
+ theContext.SetViewport(theOriginalViewport);
+ break;
+ case CommandTypes::BindShader: {
+ theCurrentShader = NULL;
+ SMaterialOrComputeShader theBindResult =
+ BindShader(inRenderContext, inMaterial,
+ static_cast<const SBindShader &>(theCommand), inFeatureSet);
+ if (theBindResult.IsMaterialShader())
+ theCurrentShader = &theBindResult.MaterialShader();
+ } break;
+ case CommandTypes::ApplyInstanceValue:
+ // we apply the property update explicitly at the render pass
+ break;
+ case CommandTypes::Render:
+ if (theCurrentShader) {
+ RenderPass(inRenderContext, *theCurrentShader, theCurrentSourceTexture,
+ theCurrentRenderTarget, theRenderTargetNeedsClear,
+ *inRenderContext.m_Subset.m_InputAssembler,
+ inRenderContext.m_Subset.m_Count, inRenderContext.m_Subset.m_Offset);
+ }
+ // reset
+ theRenderTargetNeedsClear = false;
+ break;
+ case CommandTypes::ApplyBlending:
+ ApplyBlending(static_cast<const SApplyBlending &>(theCommand));
+ break;
+ case CommandTypes::ApplyBufferValue:
+ if (theCurrentShader)
+ ApplyBufferValue(inMaterial, *theCurrentShader->m_Shader,
+ static_cast<const SApplyBufferValue &>(theCommand),
+ theCurrentSourceTexture);
+ break;
+ case CommandTypes::ApplyBlitFramebuffer:
+ BlitFramebuffer(inRenderContext,
+ static_cast<const SApplyBlitFramebuffer &>(theCommand), inTarget);
+ break;
+ case CommandTypes::LuaCommand: {
+ if (m_LuaState == NULL) {
+ m_LuaState = lua_newstate(LuaAlloc, this);
+ luaL_openlibs(m_LuaState);
+ lua_pushlightuserdata(m_LuaState, this);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "__materialSystem");
+ RegisterGlobalFunctions();
+ lua_newtable(m_LuaState);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "__materialcontexts");
+ }
+ SCustomMaterial &theMaterial = const_cast<SCustomMaterial &>(inMaterial);
+ eastl::pair<TMaterialLuaContextMap::iterator, bool> inserter =
+ m_MaterialLuaContextMap.insert(
+ eastl::make_pair(&theMaterial, NVScopedRefCounted<SMaterialLuaContext>()));
+ if (inserter.second) {
+ QT3DSU32 contextId = (QT3DSU32)m_MaterialLuaContextMap.size();
+ NVScopedRefCounted<SMaterialLuaContext> theNewContext =
+ QT3DS_NEW(m_CoreContext.GetAllocator(),
+ SMaterialLuaContext)(theMaterial, inClass, *m_LuaState, contextId,
+ *this, m_CoreContext.GetAllocator());
+ // Attempt to compile the lua.
+ // first, create a new table that will be the global context
+ const char *initScript = "local P = {} \n"
+ "setmetatable(P, {__index = _G})\n"
+ "return P\n";
+ luaL_loadstring(m_LuaState, initScript);
+ int callResult = lua_pcall(m_LuaState, 0, 1, 0);
+ if (callResult) {
+ const char *error = lua_tostring(m_LuaState, -1);
+ qCCritical(INTERNAL_ERROR, "Error initializing lua state: %s", error);
+ return;
+ }
+ lua_pushlightuserdata(m_LuaState, theNewContext.mPtr);
+ lua_setfield(m_LuaState, -2, "__context");
+ // Store the context table in the context list.
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "__materialcontexts");
+ lua_pushvalue(m_LuaState, -2);
+ lua_rawseti(m_LuaState, -2, contextId);
+ lua_pop(m_LuaState, 1);
+
+ const SLuaCommand &theLuaCommand = static_cast<const SLuaCommand &>(theCommand);
+ int loadResult = luaL_loadstring(m_LuaState, theLuaCommand.m_LuaScript.c_str());
+ if (loadResult) {
+ const char *error = lua_tostring(m_LuaState, -1);
+ qCCritical(INTERNAL_ERROR, "Error initializing lua state for material: %s: %s",
+ inMaterial.m_Id.c_str(), error);
+ return;
+ }
+ // Swap the table and the function so fenv call works.
+ lua_insert(m_LuaState, -2);
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -2));
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ lua_getfield(m_LuaState, -1, "__context");
+ QT3DS_ASSERT(!lua_isnil(m_LuaState, -1));
+ lua_pop(m_LuaState, 1);
+ lua_setfenv(m_LuaState, -2);
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -1));
+
+ callResult = lua_pcall(m_LuaState, 0, 0, 0);
+ if (callResult) {
+ const char *error = lua_tostring(m_LuaState, -1);
+ qCCritical(INTERNAL_ERROR, "Error initializing lua state for material: %s: %s",
+ inMaterial.m_Id.c_str(), error);
+ return;
+ }
+
+ inserter.first->second = theNewContext;
+ }
+ if (inserter.first->second)
+ inserter.first->second->Render(inRenderContext, inTarget, inFeatureSet);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ if (inMaterial.m_hasRefraction)
+ theContext.SetBlendingEnabled(wasBlendingEnabled);
+
+ // Release any per-frame buffers
+ for (QT3DSU32 idx = 0; idx < m_AllocatedBuffers.size(); ++idx) {
+ if (m_AllocatedBuffers[idx].m_Flags.IsSceneLifetime() == false) {
+ ReleaseBuffer(idx);
+ --idx;
+ }
+ }
+ }
+
+ const char *GetShaderName(const SCustomMaterial &inMaterial) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inMaterial.m_ClassName);
+ if (!theClass)
+ return NULL;
+
+ NVConstDataRef<dynamic::SCommand *> theCommands = theClass->m_Class->GetRenderCommands();
+ TShaderAndFlags thePrepassShader;
+ for (QT3DSU32 idx = 0, end = theCommands.size();
+ idx < end && thePrepassShader.first.mPtr == NULL; ++idx) {
+ const SCommand &theCommand = *theCommands[idx];
+ if (theCommand.m_Type == CommandTypes::BindShader) {
+ const SBindShader &theBindCommand = static_cast<const SBindShader &>(theCommand);
+ return theBindCommand.m_ShaderPath.c_str();
+ }
+ }
+
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ void ApplyShaderPropertyValues(const SCustomMaterial &inMaterial,
+ NVRenderShaderProgram &inProgram) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inMaterial.m_ClassName);
+ if (!theClass)
+ return;
+
+ SApplyInstanceValue applier;
+ ApplyInstanceValue(const_cast<SCustomMaterial &>(inMaterial), *theClass, inProgram,
+ applier);
+ }
+
+ virtual void PrepareTextureForRender(SMaterialClass &inClass, SCustomMaterial &inMaterial)
+ {
+ NVConstDataRef<SPropertyDefinition> thePropDefs = inClass.m_Class->GetProperties();
+ for (QT3DSU32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) {
+ if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ if (thePropDefs[idx].m_TexUsageType == NVRenderTextureTypeValue::Displace) {
+ SImage *pImage = NULL;
+
+ // we only do this to not miss if "None" is selected
+ CRegisteredString theStrPtr = *reinterpret_cast<CRegisteredString *>(
+ inMaterial.GetDataSectionBegin() + thePropDefs[idx].m_Offset);
+
+ if (theStrPtr.IsValid()) {
+
+ QT3DSU32 index = FindAllocatedImage(thePropDefs[idx].m_ImagePath);
+ if (index == QT3DSU32(-1)) {
+ pImage = QT3DS_NEW(m_CoreContext.GetAllocator(), SImage)();
+ m_AllocatedImages.push_back(
+ eastl::make_pair(thePropDefs[idx].m_ImagePath, pImage));
+ } else
+ pImage = m_AllocatedImages[index].second;
+
+ if (inMaterial.m_DisplacementMap != pImage) {
+ inMaterial.m_DisplacementMap = pImage;
+ inMaterial.m_DisplacementMap->m_ImagePath =
+ thePropDefs[idx].m_ImagePath;
+ inMaterial.m_DisplacementMap->m_ImageShaderName =
+ thePropDefs[idx].m_Name; // this is our name in the shader
+ inMaterial.m_DisplacementMap->m_VerticalTilingMode =
+ thePropDefs[idx].m_CoordOp;
+ inMaterial.m_DisplacementMap->m_HorizontalTilingMode =
+ thePropDefs[idx].m_CoordOp;
+ }
+ } else {
+ inMaterial.m_DisplacementMap = NULL;
+ }
+ } else if (thePropDefs[idx].m_TexUsageType == NVRenderTextureTypeValue::Emissive2) {
+ SImage *pImage = NULL;
+
+ // we only do this to not miss if "None" is selected
+ CRegisteredString theStrPtr = *reinterpret_cast<CRegisteredString *>(
+ inMaterial.GetDataSectionBegin() + thePropDefs[idx].m_Offset);
+
+ if (theStrPtr.IsValid()) {
+ QT3DSU32 index = FindAllocatedImage(thePropDefs[idx].m_ImagePath);
+ if (index == QT3DSU32(-1)) {
+ pImage = QT3DS_NEW(m_CoreContext.GetAllocator(), SImage)();
+ m_AllocatedImages.push_back(
+ eastl::make_pair(thePropDefs[idx].m_ImagePath, pImage));
+ } else
+ pImage = m_AllocatedImages[index].second;
+
+ if (inMaterial.m_EmissiveMap2 != pImage) {
+ inMaterial.m_EmissiveMap2 = pImage;
+ inMaterial.m_EmissiveMap2->m_ImagePath = thePropDefs[idx].m_ImagePath;
+ inMaterial.m_EmissiveMap2->m_ImageShaderName =
+ thePropDefs[idx].m_Name; // this is our name in the shader
+ inMaterial.m_EmissiveMap2->m_VerticalTilingMode =
+ thePropDefs[idx].m_CoordOp;
+ inMaterial.m_EmissiveMap2->m_HorizontalTilingMode =
+ thePropDefs[idx].m_CoordOp;
+ }
+ } else {
+ inMaterial.m_EmissiveMap2 = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ virtual void PrepareDisplacementForRender(SMaterialClass &inClass, SCustomMaterial &inMaterial)
+ {
+ if (inMaterial.m_DisplacementMap == NULL)
+ return;
+
+ // our displacement mappin in MDL has fixed naming
+ NVConstDataRef<SPropertyDefinition> thePropDefs = inClass.m_Class->GetProperties();
+ for (QT3DSU32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) {
+ if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::QT3DSF32
+ && AreEqual(thePropDefs[idx].m_Name.c_str(), "displaceAmount")) {
+ QT3DSF32 theValue = *reinterpret_cast<const QT3DSF32 *>(inMaterial.GetDataSectionBegin()
+ + thePropDefs[idx].m_Offset);
+ inMaterial.m_DisplaceAmount = theValue;
+ } else if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::QT3DSVec3
+ && AreEqual(thePropDefs[idx].m_Name.c_str(), "displace_tiling")) {
+ QT3DSVec3 theValue = *reinterpret_cast<const QT3DSVec3 *>(inMaterial.GetDataSectionBegin()
+ + thePropDefs[idx].m_Offset);
+ if (theValue.x != inMaterial.m_DisplacementMap->m_Scale.x
+ || theValue.y != inMaterial.m_DisplacementMap->m_Scale.y) {
+ inMaterial.m_DisplacementMap->m_Scale = QT3DSVec2(theValue.x, theValue.y);
+ inMaterial.m_DisplacementMap->m_Flags.SetTransformDirty(true);
+ }
+ }
+ }
+ }
+
+ void PrepareMaterialForRender(SMaterialClass &inClass, SCustomMaterial &inMaterial)
+ {
+ PrepareTextureForRender(inClass, inMaterial);
+
+ if (inClass.m_HasDisplacement)
+ PrepareDisplacementForRender(inClass, inMaterial);
+ }
+
+ // Returns true if the material is dirty and thus will produce a different render result
+ // than previously. This effects things like progressive AA.
+ // TODO - return more information, specifically about transparency (object is transparent,
+ // object is completely transparent
+ bool PrepareForRender(const SModel & /*inModel*/, const SRenderSubset & /*inSubset*/,
+ SCustomMaterial &inMaterial, bool clearMaterialDirtyFlags) override
+ {
+ SMaterialClass *theMaterialClass = GetMaterialClass(inMaterial.m_ClassName);
+ if (theMaterialClass == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ PrepareMaterialForRender(*theMaterialClass, inMaterial);
+
+ inMaterial.m_hasTransparency = theMaterialClass->m_HasTransparency;
+ inMaterial.m_hasRefraction = theMaterialClass->m_HasRefraction;
+ inMaterial.m_hasVolumetricDF = false;
+
+ bool wasDirty = inMaterial.IsDirty() || theMaterialClass->m_AlwaysDirty;
+ if (clearMaterialDirtyFlags)
+ inMaterial.UpdateDirtyForFrame();
+
+ return wasDirty;
+ }
+
+ // TODO - handle UIC specific features such as vertex offsets for prog-aa and opacity.
+ void RenderSubset(SCustomMaterialRenderContext &inRenderContext,
+ TShaderFeatureSet inFeatureSet) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inRenderContext.m_Material.m_ClassName);
+
+ // Ensure that our overall render context comes back no matter what the client does.
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderBlendFunctionArgument>
+ __blendFunction(m_UICContext->GetRenderContext(), &NVRenderContext::GetBlendFunction,
+ &NVRenderContext::SetBlendFunction,
+ qt3ds::render::NVRenderBlendFunctionArgument());
+ qt3ds::render::NVRenderContextScopedProperty<qt3ds::render::NVRenderBlendEquationArgument>
+ __blendEquation(m_UICContext->GetRenderContext(), &NVRenderContext::GetBlendEquation,
+ &NVRenderContext::SetBlendEquation,
+ qt3ds::render::NVRenderBlendEquationArgument());
+
+ NVRenderContextScopedProperty<bool> theBlendEnabled(m_UICContext->GetRenderContext(),
+ &NVRenderContext::IsBlendingEnabled,
+ &NVRenderContext::SetBlendingEnabled);
+
+ DoRenderCustomMaterial(inRenderContext, inRenderContext.m_Material, *theClass,
+ m_UICContext->GetRenderContext().GetRenderTarget(), inFeatureSet);
+ }
+
+ bool RenderDepthPrepass(const QT3DSMat44 &inMVP, const SCustomMaterial &inMaterial,
+ const SRenderSubset &inSubset) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inMaterial.m_ClassName);
+ NVConstDataRef<dynamic::SCommand *> theCommands = theClass->m_Class->GetRenderCommands();
+ TShaderAndFlags thePrepassShader;
+ for (QT3DSU32 idx = 0, end = theCommands.size();
+ idx < end && thePrepassShader.first.mPtr == NULL; ++idx) {
+ const SCommand &theCommand = *theCommands[idx];
+ if (theCommand.m_Type == CommandTypes::BindShader) {
+ const SBindShader &theBindCommand = static_cast<const SBindShader &>(theCommand);
+ thePrepassShader = m_UICContext->GetDynamicObjectSystem().GetDepthPrepassShader(
+ theBindCommand.m_ShaderPath, CRegisteredString(), TShaderFeatureSet());
+ }
+ }
+
+ if (thePrepassShader.first.mPtr == NULL)
+ return false;
+
+ NVRenderContext &theContext = m_UICContext->GetRenderContext();
+ NVRenderShaderProgram &theProgram = *thePrepassShader.first;
+ theContext.SetActiveShader(&theProgram);
+ theProgram.SetPropertyValue("model_view_projection", inMVP);
+ theContext.SetInputAssembler(inSubset.m_InputAssemblerPoints);
+ theContext.Draw(NVRenderDrawMode::Lines, inSubset.m_PosVertexBuffer->GetNumVertexes(), 0);
+ return true;
+ }
+
+ void OnMaterialActivationChange(const SCustomMaterial &inMaterial, bool inActive) override
+ {
+ SMaterialClass *theClass = GetMaterialClass(inMaterial.m_ClassName);
+ NVConstDataRef<dynamic::SCommand *> theCommands = theClass->m_Class->GetRenderCommands();
+ for (QT3DSU32 idx = 0, end = theCommands.size(); idx < end; ++idx) {
+ const SCommand &theCommand(*theCommands[idx]);
+ if (theCommand.m_Type == CommandTypes::LuaCommand) {
+ SCustomMaterial &theMaterial = const_cast<SCustomMaterial &>(inMaterial);
+ TMaterialLuaContextMap::iterator theIterator =
+ m_MaterialLuaContextMap.find(&theMaterial);
+ if (theIterator != m_MaterialLuaContextMap.end()
+ && theIterator->second.mPtr != NULL)
+ theIterator->second->OnActivationChange(inActive);
+
+ break;
+ }
+ }
+ }
+
+ void EndFrame() override
+ {
+ QT3DSU64 currentFrameTime = qt3ds::foundation::Time::getCurrentTimeInTensOfNanoSeconds();
+ if (m_LastFrameTime) {
+ QT3DSU64 timePassed = currentFrameTime - m_LastFrameTime;
+ m_MillisecondsSinceLastFrame = static_cast<QT3DSF32>(timePassed / 100000.0);
+ }
+ m_LastFrameTime = currentFrameTime;
+ }
+
+ void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap,
+ const char8_t * /*inProjectDir*/) const override
+ {
+ QT3DSU32 offset = ioBuffer.size();
+ ioBuffer.write((QT3DSU32)m_StringMaterialMap.size());
+ for (TStringMaterialMap::const_iterator iter = m_StringMaterialMap.begin(),
+ end = m_StringMaterialMap.end();
+ iter != end; ++iter) {
+ size_t nameOffset = ioBuffer.size() - offset;
+ (void)nameOffset;
+ CRegisteredString materialName(iter->first);
+ materialName.Remap(inRemapMap);
+ ioBuffer.write(materialName);
+ const SMaterialClass *materialClass = iter->second.mPtr;
+ QT3DSU32 offset = ioBuffer.size();
+ ioBuffer.write(*materialClass);
+ QT3DSU8 *materialOffset = ioBuffer.begin() + offset;
+ SMaterialClass *writtenClass = (SMaterialClass *)materialOffset;
+ writtenClass->AfterWrite();
+ ioBuffer.align(4);
+ }
+ }
+
+ void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t * /*inProjectDir*/) override
+ {
+ m_Allocator.m_PreAllocatedBlock = inData;
+ m_Allocator.m_OwnsMemory = false;
+ qt3ds::render::SDataReader theReader(inData.begin(), inData.end());
+ QT3DSU32 numMaterialClasses = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0; idx < numMaterialClasses; ++idx) {
+ CRegisteredString clsName = theReader.LoadRef<CRegisteredString>();
+ clsName.Remap(inStrDataBlock);
+ IDynamicObjectClass *theDynamicCls =
+ m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(clsName);
+ SMaterialClass *theReadClass = theReader.Load<SMaterialClass>();
+ theReader.Align(4);
+ if (theDynamicCls) {
+ theReadClass->AfterRead(m_Allocator, *theDynamicCls);
+ m_StringMaterialMap.insert(eastl::make_pair(clsName, theReadClass));
+ }
+ }
+ }
+
+ ICustomMaterialSystem &GetCustomMaterialSystem(IUICRenderContext &inContext) override
+ {
+ m_UICContext = &inContext;
+
+ // check for fast blits
+ NVRenderContext &theContext = m_UICContext->GetRenderContext();
+ m_UseFastBlits = theContext.GetRenderBackendCap(
+ qt3ds::render::NVRenderBackend::NVRenderBackendCaps::FastBlits);
+
+ return *this;
+ }
+
+ //=======================================================================
+ // Begin material system lua functions
+ //=======================================================================
+ static SMaterialSystem &GetMaterialSystem(lua_State *inState)
+ {
+ STopScope __scope(inState);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "__materialSystem");
+ return *reinterpret_cast<SMaterialSystem *>(lua_touserdata(inState, -1));
+ }
+
+ static SMaterialLuaContext *GetMaterialContext(lua_State *inState)
+ {
+ STopScope __scope(inState);
+ // hack, but I don't want to work around this elegantly right now. The problem is that
+ // the global index indexes to a fixed table, not the actually current acting globals table.
+ // To get that, I would need to use getfenv and getinfo and friends which is not worth it.
+ lua_getfield(inState, LUA_REGISTRYINDEX, "__current_context");
+ SMaterialLuaContext *retval =
+ reinterpret_cast<SMaterialLuaContext *>(lua_touserdata(inState, -1));
+ return retval;
+ }
+
+ // Leave the context table TOS
+ static void PushMaterialContextTable(lua_State *inState, QT3DSU32 inContextId)
+ {
+ lua_getfield(inState, LUA_REGISTRYINDEX, "__materialcontexts");
+ lua_rawgeti(inState, -1, inContextId);
+ lua_insert(inState, -2); // swap the table of contexts and the context table
+ lua_pop(
+ inState,
+ 1); // get rid of the table of contexts, leaving just the context table top of stack.
+ }
+
+ void RegisterGlobalFunctions()
+ {
+ lua_pushcfunction(m_LuaState, LuaOutput);
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, "output");
+ // Really, we should have done this a long time ago, overridden print.
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, "print");
+
+ lua_register(m_LuaState, "getOrCreateVertexBuffer", LuaGetOrCreateVertexBuffer);
+ lua_register(m_LuaState, "bindShader", LuaBindShader);
+ lua_register(m_LuaState, "bindComputeInput", LuaBindComputeInput);
+ lua_register(m_LuaState, "applyInstanceValues", LuaApplyInstanceValues);
+ lua_register(m_LuaState, "executeCompute", LuaExecuteCompute);
+ lua_register(m_LuaState, "memoryBarrier", LuaMemoryBarrier);
+ lua_register(m_LuaState, "getOrCreateInputAssembler", LuaGetOrCreateInputAssembler);
+ lua_register(m_LuaState, "bindInputAssembler", LuaBindInputAssembler);
+ lua_register(m_LuaState, "draw", LuaDraw);
+ lua_register(m_LuaState, "setBlendFunction", LuaSetBlendFunction);
+ lua_register(m_LuaState, "getGlobalTransform", LuaGetGlobalTransform);
+ lua_register(m_LuaState, "setUniform", LuaSetUniform);
+ lua_register(m_LuaState, "invertMatrix", LuaInvertMatrix);
+ lua_register(m_LuaState, "getAttribute", LuaGetAttribute);
+ lua_pushboolean(m_LuaState, m_UICContext->IsAuthoringMode() ? 1 : 0);
+ lua_setfield(m_LuaState, LUA_GLOBALSINDEX, "authoring_mode");
+ }
+
+ static int LuaOutput(lua_State *inState)
+ {
+ STopScope __scope(inState);
+
+ lua_concat(inState, lua_gettop(inState));
+ const char *message = lua_tostring(inState, -1);
+ qCDebug(TRACE_INFO, "%s", nonNull(message));
+ return 0;
+ }
+
+ static int LuaGetOrCreateVertexBuffer(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ luaL_checktype(inState, 2, LUA_TNUMBER);
+ luaL_checktype(inState, 3, LUA_TNUMBER);
+ const char *idStr = lua_tostring(inState, 1);
+ int bufferSize = (int)lua_tonumber(inState, 2);
+ int bufferStride = (int)lua_tonumber(inState, 3);
+ bool created = currentContext->GetOrCreateVertexBuffer(idStr, bufferSize, bufferStride);
+ lua_pushboolean(inState, created ? 1 : 0);
+ return 1;
+ }
+
+ CRegisteredString GetShaderName(const char *inObjectName, const char8_t *inShaderSpecificName)
+ {
+ m_ShaderNameBuilder.assign(inObjectName);
+ m_ShaderNameBuilder.append(" - ");
+ m_ShaderNameBuilder.append(inShaderSpecificName);
+ return m_CoreContext.GetStringTable().RegisterStr(m_ShaderNameBuilder.c_str());
+ }
+
+ static int LuaBindShader(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ const char *shaderIdStr = lua_tostring(inState, 1);
+ const char *className = currentContext->m_RenderContext->m_Material.m_ClassName;
+ SBindShader theBindCommand;
+ theBindCommand.m_ShaderPath =
+ currentContext->m_MaterialSystem.GetShaderName(className, shaderIdStr);
+ // We don't care about the result.
+ currentContext->m_CurrentShader = currentContext->m_MaterialSystem.BindShaderFromLua(
+ *currentContext->m_RenderContext, theBindCommand, currentContext->m_FeatureSet);
+
+ return 0;
+ }
+
+ static int LuaBindComputeInput(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ luaL_checktype(inState, 2, LUA_TNUMBER);
+ const char *bufferIdStr = lua_tostring(inState, 1);
+ QT3DSU32 bufferIndex = (QT3DSU32)lua_tonumber(inState, 2);
+ qt3ds::render::NVRenderDataBuffer *baseBuffer = currentContext->GetVertexBuffer(bufferIdStr);
+ if (!baseBuffer) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ if (currentContext->m_CurrentShader.IsComputeShader())
+ currentContext->m_CurrentShader.ComputeShader().BindComputeInput(baseBuffer,
+ bufferIndex);
+
+ return 0;
+ }
+
+ static int LuaApplyInstanceValues(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ if (currentContext->m_CurrentShader.IsValid()) {
+ SApplyInstanceValue applier;
+ NVRenderShaderProgram *theProgram(NULL);
+ if (currentContext->m_CurrentShader.IsMaterialShader())
+ theProgram = currentContext->m_CurrentShader.MaterialShader().m_Shader;
+ else
+ theProgram = &currentContext->m_CurrentShader.ComputeShader();
+
+ currentContext->m_MaterialSystem.ApplyInstanceValue(
+ currentContext->m_Material, currentContext->m_Class, *theProgram, applier);
+ }
+ return 0;
+ }
+
+ static int LuaExecuteCompute(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ int numArgs = lua_gettop(inState);
+ QT3DSU32 workgroupX = 1, workgroupY = 1, workgroupZ = 1;
+ switch (numArgs) {
+ case 3:
+ luaL_checknumber(inState, 3);
+ workgroupZ = (QT3DSU32)lua_tonumber(inState, 3);
+ case 2:
+ luaL_checknumber(inState, 2);
+ workgroupY = (QT3DSU32)lua_tonumber(inState, 2);
+ case 1:
+ default:
+ luaL_checknumber(inState, 1);
+ workgroupX = (QT3DSU32)lua_tonumber(inState, 1);
+ break;
+ }
+
+ if (currentContext->m_CurrentShader.IsComputeShader()) {
+ NVRenderContext &theContext =
+ currentContext->m_MaterialSystem.m_UICContext->GetRenderContext();
+ theContext.DispatchCompute(&currentContext->m_CurrentShader.ComputeShader(), workgroupX,
+ workgroupY, workgroupZ);
+ }
+ return 0;
+ }
+
+ static int LuaMemoryBarrier(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ QT3DSU32 flags = 0;
+ int numArgs = lua_gettop(inState);
+ for (int idx = 0; idx < numArgs; ++idx) {
+ const char *data = lua_tostring(inState, idx + 1);
+ for (QT3DSU32 flagIdx = 0, flagEnd = g_StringMemoryFlagMapSize; flagIdx < flagEnd;
+ ++flagIdx) {
+ if (AreEqual(g_StringMemoryFlagMap[flagIdx].m_Name, data)) {
+ flags = flags | (QT3DSU32)g_StringMemoryFlagMap[flagIdx].m_Value;
+ break;
+ }
+ }
+ }
+ if (flags == 0)
+ flags = (QT3DSU32)qt3ds::render::NVRenderBufferBarrierValues::All;
+ NVRenderContext &theContext =
+ currentContext->m_MaterialSystem.m_UICContext->GetRenderContext();
+ theContext.SetMemoryBarrier(qt3ds::render::NVRenderBufferBarrierFlags(flags));
+ return 0;
+ }
+
+ static int LuaGetOrCreateInputAssembler(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ const char *assemblerIdStr = lua_tostring(inState, 1);
+ IStringTable &theStrTable(currentContext->m_MaterialSystem.m_CoreContext.GetStringTable());
+ NVRenderContext &theRenderContext =
+ currentContext->m_MaterialSystem.m_UICContext->GetRenderContext();
+ CRegisteredString assemblerId = theStrTable.RegisterStr(assemblerIdStr);
+ eastl::pair<TStringAssemblerMap::iterator, bool> inserter =
+ currentContext->m_InputAssemblers.insert(
+ eastl::make_pair(assemblerId, NVScopedRefCounted<NVRenderInputAssembler>()));
+ if (inserter.second) {
+ // This one is pretty hardcore.
+ NVRenderVertexBuffer *theVertexBuffer(
+ currentContext->GetVertexBuffer(lua_tostring(inState, 2)));
+ // NVRenderIndexBuffer* theIndexBuffer( NULL );
+ eastl::vector<qt3ds::render::NVRenderVertexBufferEntry> entries;
+ // Build the set of vbuf entries.
+ luaL_checktype(inState, 3, LUA_TTABLE);
+ lua_pushvalue(inState, 3);
+ // Iterate through outer table values. WE don't care about keys.
+ lua_pushnil(inState);
+ while (lua_next(inState, -2)) {
+ int TOS = lua_gettop(inState);
+ // Can't use checktype with relative indexes.
+ luaL_checktype(inState, TOS, LUA_TTABLE);
+ qt3ds::render::NVRenderVertexBufferEntry theEntry;
+ // Ensure defaults are setup intelligently.
+ theEntry.m_ComponentType = qt3ds::render::NVRenderComponentTypes::QT3DSF32;
+ theEntry.m_FirstItemOffset = 0;
+ // iterate through inner table
+ lua_pushnil(inState);
+ while (lua_next(inState, -2)) {
+ // dup the key
+ lua_pushvalue(inState, -2);
+ const char *keyName = lua_tostring(inState, -1);
+ if (AreEqual(keyName, "name")) {
+ const char *valueStr = lua_tostring(inState, -2);
+ theEntry.m_Name = theStrTable.RegisterStr(valueStr);
+ } else if (AreEqual(keyName, "type")) // ignored for now; they are all float
+ {
+
+ } else if (AreEqual(keyName, "offset")) {
+ theEntry.m_FirstItemOffset = (QT3DSU32)lua_tonumber(inState, -2);
+ } else if (AreEqual(keyName, "num_components")) {
+ theEntry.m_NumComponents = (QT3DSU32)lua_tonumber(inState, -2);
+ }
+ // pop duplicated key and value off stack.
+ lua_pop(inState, 2);
+ }
+ // Pop both last table key and current value off stack
+ if (!isTrivial(theEntry.m_Name))
+ entries.push_back(theEntry);
+ lua_settop(inState, TOS - 1);
+ }
+ // pop leftover key off stack.
+ lua_pop(inState, 1);
+
+ QT3DSU32 stride = lua_tonumber(inState, 5);
+ QT3DSU32 offset = lua_tonumber(inState, 6);
+ const char *primTypeStr = lua_tostring(inState, 7);
+ NVRenderDrawMode::Enum theDrawMode(NVRenderDrawMode::Triangles);
+ if (AreEqual(primTypeStr, "points"))
+ theDrawMode = NVRenderDrawMode::Points;
+ else if (AreEqual(primTypeStr, "lines"))
+ theDrawMode = NVRenderDrawMode::Lines;
+ else if (AreEqual(primTypeStr, "triangles"))
+ theDrawMode = NVRenderDrawMode::Triangles;
+
+ NVRenderAttribLayout *theLayout = theRenderContext.CreateAttributeLayout(
+ toConstDataRef(entries.data(), entries.size()));
+ inserter.first->second = theRenderContext.CreateInputAssembler(
+ theLayout, toConstDataRef(&theVertexBuffer, 1), NULL, toConstDataRef(stride),
+ toConstDataRef(offset), theDrawMode);
+ }
+ lua_pushboolean(inState, inserter.second ? 1 : 0);
+ return 1;
+ }
+
+ static int LuaBindInputAssembler(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ IStringTable &theStrTable(currentContext->m_MaterialSystem.m_CoreContext.GetStringTable());
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ const char *assemblerId = lua_tostring(inState, 1);
+ currentContext->m_CurrentInputAssembler = NULL;
+ if (AreEqual(assemblerId, "source_assembler")) {
+ currentContext->m_CurrentInputAssembler =
+ currentContext->m_RenderContext->m_Subset.m_InputAssembler;
+ } else {
+ CRegisteredString assemblerIdStr = theStrTable.RegisterStr(assemblerId);
+ TStringAssemblerMap::iterator iter =
+ currentContext->m_InputAssemblers.find(assemblerIdStr);
+ if (iter != currentContext->m_InputAssemblers.end())
+ currentContext->m_CurrentInputAssembler = iter->second;
+ }
+ return 0;
+ }
+ static qt3ds::render::NVRenderSrcBlendFunc::Enum ToBlendFunc(const char8_t *str)
+ {
+ for (QT3DSU32 idx = 0, end = g_BlendFuncMapSize; idx < end; ++idx) {
+ if (AreEqual(str, g_BlendFuncMap[idx].m_Name))
+ return g_BlendFuncMap[idx].m_Value;
+ }
+ QT3DS_ASSERT(false);
+ return qt3ds::render::NVRenderSrcBlendFunc::Unknown;
+ }
+
+ static int LuaSetBlendFunction(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ NVRenderContext &theContext(
+ currentContext->m_MaterialSystem.m_UICContext->GetRenderContext());
+ if (lua_gettop(inState) == 0) {
+ theContext.SetBlendingEnabled(false);
+ } else {
+ const char8_t *srcEquation = lua_tostring(inState, 1);
+ const char8_t *destEquation = lua_tostring(inState, 2);
+ theContext.SetBlendingEnabled(true);
+ qt3ds::render::NVRenderSrcBlendFunc::Enum srcFunc(ToBlendFunc(srcEquation));
+ qt3ds::render::NVRenderDstBlendFunc::Enum destFunc(
+ static_cast<qt3ds::render::NVRenderDstBlendFunc::Enum>(ToBlendFunc(destEquation)));
+ qt3ds::render::NVRenderBlendFunctionArgument args(srcFunc, destFunc, srcFunc, destFunc);
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+ theContext.SetBlendFunction(args);
+ theContext.SetBlendEquation(blendEqu);
+ }
+ return 0;
+ }
+
+ static int LuaDraw(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ if (!currentContext->m_CurrentShader.IsMaterialShader()) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ if (!currentContext->m_CurrentInputAssembler) {
+ currentContext->m_CurrentInputAssembler =
+ currentContext->m_RenderContext->m_Subset.m_InputAssembler;
+ }
+
+ QT3DSU32 count = (QT3DSU32)lua_tonumber(inState, 1);
+ QT3DSU32 offset = (QT3DSU32)lua_tonumber(inState, 2);
+ currentContext->m_MaterialSystem.RenderPass(
+ *currentContext->m_RenderContext, currentContext->m_CurrentShader.MaterialShader(),
+ NULL, currentContext->m_Target, false, *currentContext->m_CurrentInputAssembler, count,
+ offset);
+ return 0;
+ }
+
+ static int LuaGetGlobalTransform(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ const QT3DSF32 *matData = currentContext->m_RenderContext->m_ModelMatrix.front();
+ // had better be packed...
+ size_t byteSize = sizeof(currentContext->m_RenderContext->m_ModelMatrix);
+ QT3DSU8 *dataPtr = reinterpret_cast<QT3DSU8 *>(lua_newuserdata(inState, byteSize));
+ memCopy(dataPtr, matData, (QT3DSU32)byteSize);
+ return 1;
+ }
+
+ static int LuaSetUniform(lua_State *inState)
+ {
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ if (currentContext->m_CurrentShader.IsValid() == false) {
+ lua_pushstring(inState, "No bound shader");
+ lua_error(inState);
+ }
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ const char *uniName = lua_tostring(inState, 1);
+ NVRenderShaderProgram *theProgram = NULL;
+ if (currentContext->m_CurrentShader.IsComputeShader())
+ theProgram = &currentContext->m_CurrentShader.ComputeShader();
+ else
+ theProgram = currentContext->m_CurrentShader.MaterialShader().m_Shader.mPtr;
+ NVRenderShaderConstantBase *theBase = theProgram->GetShaderConstant(uniName);
+ // We don't error here because that makes editing and testing really tough.
+ if (theBase) {
+ NVRenderShaderDataTypes::Enum theConstantType = theBase->GetShaderConstantType();
+ // Someone less lazy than me can fill the rest of this in
+ switch (theConstantType) {
+ case NVRenderShaderDataTypes::QT3DSF32: {
+ if (theBase->m_ElementCount == 1) {
+ QT3DSF32 theValue = lua_tonumber(inState, 2);
+ theProgram->SetConstantValue(theBase, theValue, 1);
+ }
+ } break;
+ case NVRenderShaderDataTypes::QT3DSMat44: {
+ if (theBase->m_ElementCount == 1) {
+ luaL_checktype(inState, 2, LUA_TUSERDATA);
+ size_t matLen = lua_objlen(inState, 2);
+ if (matLen == sizeof(QT3DSMat44)) {
+ QT3DSMat44 *dataPtr = (QT3DSMat44 *)lua_touserdata(inState, 2);
+ theProgram->SetConstantValue(theBase, *dataPtr, 1);
+ } else {
+ lua_pushstring(inState, "Invalid matrix length for matrix uniform");
+ lua_error(inState);
+ }
+ }
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ return 0;
+ }
+
+ static int LuaInvertMatrix(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TUSERDATA);
+ size_t matLen = lua_objlen(inState, 1);
+ if (matLen == sizeof(QT3DSMat44)) {
+ QT3DSMat44 *dataPtr = (QT3DSMat44 *)lua_touserdata(inState, 1);
+ QT3DSMat44 newMatrix = dataPtr->getInverse();
+ void *newPtr = lua_newuserdata(inState, matLen);
+ memCopy(newPtr, &newMatrix, (QT3DSU32)matLen);
+ return 1;
+ } else {
+ lua_pushstring(inState, "Invalid matrix length for matrix uniform");
+ lua_error(inState);
+ }
+ return 0;
+ }
+
+ static int LuaGetAttribute(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ const char *attName = lua_tostring(inState, 1);
+ SMaterialLuaContext *currentContext = GetMaterialContext(inState);
+ if (!currentContext) {
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+ CRegisteredString propName =
+ currentContext->m_MaterialSystem.m_UICContext->GetStringTable().RegisterStr(attName);
+ NVConstDataRef<dynamic::SPropertyDefinition> props =
+ currentContext->m_Class.m_Class->GetProperties();
+ for (QT3DSU32 idx = 0, end = props.size(); idx < end; ++idx) {
+ if (propName == props[idx].m_Name) {
+ switch (props[idx].m_DataType) {
+ case NVRenderShaderDataTypes::QT3DSRenderBool: {
+ bool theValue = *reinterpret_cast<const bool *>(
+ currentContext->m_Material.GetDataSectionBegin() + props[idx].m_Offset);
+ lua_pushboolean(inState, theValue ? 1 : 0);
+ return 1;
+ }
+ case NVRenderShaderDataTypes::QT3DSF32: {
+ QT3DSF32 theValue = *reinterpret_cast<const QT3DSF32 *>(
+ currentContext->m_Material.GetDataSectionBegin() + props[idx].m_Offset);
+ lua_pushnumber(inState, theValue);
+ return 1;
+ }
+ default:
+ lua_pushstring(inState, "Property is of incorrect type");
+ lua_error(inState);
+ }
+ }
+ }
+ lua_pushstring(inState, "Failed to find property");
+ lua_error(inState);
+ return 0;
+ }
+};
+
+static void *LuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
+{
+ SMaterialSystem *ctx = reinterpret_cast<SMaterialSystem *>(ud);
+ if (nsize == 0) {
+ if (ptr)
+ ctx->m_CoreContext.GetAllocator().deallocate(ptr);
+ return NULL;
+ } else {
+ if (nsize < osize && ptr)
+ return ptr;
+
+ void *newMem =
+ ctx->m_CoreContext.GetAllocator().allocate(nsize, "lua memory", __FILE__, __LINE__);
+ if (osize && ptr) {
+ size_t copyAmt = NVMin(osize, nsize);
+ memCopy(newMem, ptr, (QT3DSU32)copyAmt);
+ ctx->m_CoreContext.GetAllocator().deallocate(ptr);
+ }
+ return newMem;
+ }
+}
+
+SMaterialLuaContext::~SMaterialLuaContext()
+{
+}
+void SMaterialLuaContext::DeleteThis()
+{
+ NVAllocatorCallback &theCallback = m_MaterialSystem.m_CoreContext.GetAllocator();
+ NVDelete(theCallback, this);
+}
+void SMaterialLuaContext::DoRender()
+{
+ STopScope __scope(&m_LuaState);
+ m_MaterialSystem.PushMaterialContextTable(m_MaterialSystem.m_LuaState, m_LuaId);
+ // Update with per-render information
+ QT3DSU32 numEntries = m_RenderContext->m_Subset.m_Count;
+ switch (m_RenderContext->m_Subset.m_PrimitiveType) {
+ default:
+ QT3DS_ASSERT(false);
+ case NVRenderDrawMode::Points:
+ break;
+ case NVRenderDrawMode::Lines:
+ numEntries /= 2;
+ break;
+ case NVRenderDrawMode::Triangles:
+ numEntries /= 3;
+ break;
+ }
+ lua_pushnumber(&m_LuaState, numEntries);
+ lua_setfield(&m_LuaState, -2, "source_mesh_entries");
+ lua_pushnumber(&m_LuaState, m_RenderContext->m_Subset.m_VertexBuffer->GetNumVertexes());
+ lua_setfield(&m_LuaState, -2, "source_mesh_vertices");
+ lua_pushnumber(&m_LuaState, m_MaterialSystem.m_MillisecondsSinceLastFrame);
+ lua_setfield(&m_LuaState, -2, "milliseconds_since_last_frame");
+ lua_getfield(&m_LuaState, -1, "onRender");
+ if (lua_isfunction(&m_LuaState, -1)) {
+ lua_pushlightuserdata(&m_LuaState, this);
+ lua_setfield(&m_LuaState, LUA_REGISTRYINDEX, "__current_context");
+ int callResult = lua_pcall(&m_LuaState, 0, 0, 0);
+ if (callResult) {
+ qCCritical(INVALID_OPERATION, "%s", lua_tostring(&m_LuaState, -1));
+ }
+ }
+}
+
+void SMaterialLuaContext::OnActivationChange(bool inActive)
+{
+ STopScope __scope(&m_LuaState);
+ m_MaterialSystem.PushMaterialContextTable(m_MaterialSystem.m_LuaState, m_LuaId);
+ const char *fnName = inActive ? "onActivate" : "onDeactivate";
+ lua_getfield(&m_LuaState, -1, fnName);
+ if (lua_isfunction(&m_LuaState, -1)) {
+ lua_pushlightuserdata(&m_LuaState, this);
+ lua_setfield(&m_LuaState, LUA_REGISTRYINDEX, "__current_context");
+ int callResult = lua_pcall(&m_LuaState, 0, 0, 0);
+ if (callResult) {
+ const char *message = lua_tostring(&m_LuaState, -1);
+ qCCritical(INVALID_OPERATION, "%s", message);
+ }
+ }
+}
+
+bool SMaterialLuaContext::GetOrCreateVertexBuffer(const char *inIdStr, QT3DSU32 inSize, QT3DSU32 inStride)
+{
+ CRegisteredString mapKey = m_MaterialSystem.m_CoreContext.GetStringTable().RegisterStr(inIdStr);
+ eastl::pair<TStringVertexBufferMap::iterator, bool> inserter = m_VertexBuffers.insert(
+ eastl::make_pair(mapKey, NVScopedRefCounted<NVRenderVertexBuffer>()));
+ if (inserter.second) {
+ inserter.first->second =
+ m_MaterialSystem.m_UICContext->GetRenderContext().CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Dynamic, inSize, inStride);
+ }
+ return inserter.second;
+}
+
+NVRenderVertexBuffer *SMaterialLuaContext::GetVertexBuffer(const char *inIdStr)
+{
+ if (AreEqual("source_mesh", nonNull(inIdStr)))
+ return m_RenderContext->m_Subset.m_VertexBuffer;
+
+ CRegisteredString mapKey = m_MaterialSystem.m_CoreContext.GetStringTable().RegisterStr(inIdStr);
+ TStringVertexBufferMap::iterator theFind = m_VertexBuffers.find(mapKey);
+ if (theFind != m_VertexBuffers.end())
+ return theFind->second.mPtr;
+ return NULL;
+}
+}
+
+ICustomMaterialSystemCore &
+ICustomMaterialSystemCore::CreateCustomMaterialSystemCore(IUICRenderContextCore &ctx)
+{
+ return *QT3DS_NEW(ctx.GetAllocator(), SMaterialSystem)(ctx);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp b/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp
new file mode 100644
index 00000000..fa5c9e5b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderDefaultMaterialShaderGenerator.cpp
@@ -0,0 +1,1783 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderableImage.h"
+#include "UICRenderImage.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderLight.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderCamera.h"
+#include "UICRenderShadowMap.h"
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderDynamicObjectSystem.h"
+
+using namespace uic::render;
+using qt3ds::render::NVRenderCachedShaderProperty;
+using qt3ds::render::NVRenderCachedShaderBuffer;
+
+namespace {
+
+const QT3DSF32 MINATTENUATION = 0;
+const QT3DSF32 MAXATTENUATION = 1000;
+
+QT3DSF32 ClampFloat(QT3DSF32 value, QT3DSF32 min, QT3DSF32 max)
+{
+ return value < min ? min : ((value > max) ? max : value);
+}
+
+QT3DSF32 TranslateConstantAttenuation(QT3DSF32 attenuation)
+{
+ return attenuation * .01f;
+}
+
+QT3DSF32 TranslateLinearAttenuation(QT3DSF32 attenuation)
+{
+ attenuation = ClampFloat(attenuation, MINATTENUATION, MAXATTENUATION);
+ return attenuation * 0.0001f;
+}
+
+QT3DSF32 TranslateQuadraticAttenuation(QT3DSF32 attenuation)
+{
+ attenuation = ClampFloat(attenuation, MINATTENUATION, MAXATTENUATION);
+ return attenuation * 0.0000001f;
+}
+
+/**
+ * Cached texture property lookups, used one per texture so a shader generator for N
+ * textures will have an array of N of these lookup objects.
+ */
+struct SShaderTextureProperties
+{
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_Offsets;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_Rotations;
+ SShaderTextureProperties(const char *sampName, const char *offName, const char *rotName,
+ NVRenderShaderProgram &inShader)
+ : m_Sampler(sampName, inShader)
+ , m_Offsets(offName, inShader)
+ , m_Rotations(rotName, inShader)
+ {
+ }
+ SShaderTextureProperties() {}
+};
+
+/**
+ * Cached light property lookups, used one per light so a shader generator for N
+ * lights will have an array of N of these lookup objects.
+ */
+struct SShaderLightProperties
+{
+ // Color of the light
+ QT3DSVec3 m_LightColor;
+ SLightSourceShader m_LightData;
+
+ SShaderLightProperties() {}
+};
+
+struct SShadowMapProperties
+{
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_ShadowmapTexture; ///< shadow texture
+ NVRenderCachedShaderProperty<NVRenderTextureCube *> m_ShadowCubeTexture; ///< shadow cubemap
+ NVRenderCachedShaderProperty<QT3DSMat44>
+ m_ShadowmapMatrix; ///< world to ligh space transform matrix
+ NVRenderCachedShaderProperty<QT3DSVec4> m_ShadowmapSettings; ///< shadow rendering settings
+
+ SShadowMapProperties() {}
+ SShadowMapProperties(const char *shadowmapTextureName, const char *shadowcubeTextureName,
+ const char *shadowmapMatrixName, const char *shadowmapSettingsName,
+ NVRenderShaderProgram &inShader)
+ : m_ShadowmapTexture(shadowmapTextureName, inShader)
+ , m_ShadowCubeTexture(shadowcubeTextureName, inShader)
+ , m_ShadowmapMatrix(shadowmapMatrixName, inShader)
+ , m_ShadowmapSettings(shadowmapSettingsName, inShader)
+ {
+ }
+};
+
+/**
+ * The results of generating a shader. Caches all possible variable names into
+ * typesafe objects.
+ */
+struct SShaderGeneratorGeneratedShader
+{
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ // Specific properties we know the shader has to have.
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+ NVRenderCachedShaderProperty<QT3DSMat33> m_NormalMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_GlobalTransform;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProj;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_MaterialDiffuse;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_MaterialProperties;
+ // tint, ior
+ NVRenderCachedShaderProperty<QT3DSVec4> m_MaterialSpecular;
+ NVRenderCachedShaderProperty<QT3DSF32> m_BumpAmount;
+ NVRenderCachedShaderProperty<QT3DSF32> m_DisplaceAmount;
+ NVRenderCachedShaderProperty<QT3DSF32> m_TranslucentFalloff;
+ NVRenderCachedShaderProperty<QT3DSF32> m_DiffuseLightWrap;
+ NVRenderCachedShaderProperty<QT3DSF32> m_FresnelPower;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_DiffuseColor;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPosition;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraDirection;
+ QT3DSVec3 m_LightAmbientTotal;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_MaterialDiffuseLightAmbientTotal;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthTexture;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_AOTexture;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeProps;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOpts;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeRot;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbeOfs;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_LightProbe2;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_LightProbe2Props;
+
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_AoShadowParams;
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderConstantBuffer *> m_LightsBuffer;
+
+ // Cache the image property name lookups
+ nvvector<SShaderTextureProperties> m_Images;
+ nvvector<SShaderLightProperties> m_Lights;
+ // Cache shadow map properties
+ nvvector<SShadowMapProperties> m_ShadowMaps;
+
+ QT3DSI32 m_RefCount;
+
+ SShaderGeneratorGeneratedShader(NVRenderShaderProgram &inShader, NVRenderContext &inContext)
+ : m_Allocator(inContext.GetAllocator())
+ , m_Shader(inShader)
+ , m_MVP("model_view_projection", inShader)
+ , m_NormalMatrix("normal_matrix", inShader)
+ , m_GlobalTransform("model_matrix", inShader)
+ , m_ViewProj("view_projection_matrix", inShader)
+ , m_ViewMatrix("view_matrix", inShader)
+ , m_MaterialDiffuse("material_diffuse", inShader)
+ , m_MaterialProperties("material_properties", inShader)
+ , m_MaterialSpecular("material_specular", inShader)
+ , m_BumpAmount("bumpAmount", inShader)
+ , m_DisplaceAmount("displaceAmount", inShader)
+ , m_TranslucentFalloff("translucentFalloff", inShader)
+ , m_DiffuseLightWrap("diffuseLightWrap", inShader)
+ , m_FresnelPower("fresnelPower", inShader)
+ , m_DiffuseColor("diffuse_color", inShader)
+ , m_CameraPosition("camera_position", inShader)
+ , m_CameraDirection("camera_direction", inShader)
+ , m_MaterialDiffuseLightAmbientTotal("light_ambient_total", inShader)
+ , m_CameraProperties("camera_properties", inShader)
+ , m_DepthTexture("depth_sampler", inShader)
+ , m_AOTexture("ao_sampler", inShader)
+ , m_LightProbe("light_probe", inShader)
+ , m_LightProbeProps("light_probe_props", inShader)
+ , m_LightProbeOpts("light_probe_opts", inShader)
+ , m_LightProbeRot("light_probe_rotation", inShader)
+ , m_LightProbeOfs("light_probe_offset", inShader)
+ , m_LightProbe2("light_probe2", inShader)
+ , m_LightProbe2Props("light_probe2_props", inShader)
+ , m_AoShadowParams("cbAoShadow", inShader)
+ , m_LightsBuffer("cbBufferLights", inShader)
+ , m_Images(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Images")
+ , m_Lights(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_Lights")
+ , m_ShadowMaps(inContext.GetAllocator(), "SShaderGeneratorGeneratedShader::m_ShadowMaps")
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~SShaderGeneratorGeneratedShader() { m_Shader.release(); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Allocator);
+ NVDelete(alloc, this);
+ }
+ }
+};
+
+#ifndef EA_PLATFORM_WINDOWS
+#define _snprintf snprintf
+#endif
+
+struct SShaderGenerator : public IDefaultMaterialShaderGenerator
+{
+ typedef CRenderString TStrType;
+ typedef nvhash_map<NVRenderShaderProgram *, NVScopedRefCounted<SShaderGeneratorGeneratedShader>>
+ TProgramToShaderMap;
+ typedef qt3ds::foundation::nvhash_map<CRegisteredString,
+ NVScopedRefCounted<qt3ds::render::NVRenderConstantBuffer>>
+ TStrConstanBufMap;
+
+ IUICRenderContext &m_RenderContext;
+ IShaderProgramGenerator &m_ProgramGenerator;
+
+ const SDefaultMaterial *m_CurrentMaterial;
+ SShaderDefaultMaterialKey *m_CurrentKey;
+ UICShadowMap *m_ShadowMapManager;
+ IDefaultMaterialVertexPipeline *m_CurrentPipeline;
+ TShaderFeatureSet m_CurrentFeatureSet;
+ NVDataRef<SLight *> m_Lights;
+ SRenderableImage *m_FirstImage;
+ bool m_HasTransparency;
+
+ TStrType m_ImageStem;
+ TStrType m_ImageSampler;
+ TStrType m_ImageOffsets;
+ TStrType m_ImageRotations;
+ TStrType m_ImageFragCoords;
+ TStrType m_ImageTemp;
+
+ TStrType m_TexCoordTemp;
+
+ TStrType m_LightStem;
+ TStrType m_LightColor;
+ TStrType m_LightSpecularColor;
+ TStrType m_LightAttenutation;
+ TStrType m_LightConstantAttenuation;
+ TStrType m_LightLinearAttenuation;
+ TStrType m_LightQuadraticAttenuation;
+ TStrType m_NormalizedDirection;
+ TStrType m_LightDirection;
+ TStrType m_LightPos;
+ TStrType m_LightUp;
+ TStrType m_LightRt;
+ TStrType m_RelativeDistance;
+ TStrType m_RelativeDirection;
+
+ TStrType m_ShadowMapStem;
+ TStrType m_ShadowCubeStem;
+ TStrType m_ShadowMatrixStem;
+ TStrType m_ShadowCoordStem;
+ TStrType m_ShadowControlStem;
+
+ TStrType m_TempStr;
+
+ eastl::string m_GeneratedShaderString;
+
+ SShaderDefaultMaterialKeyProperties m_DefaultMaterialShaderKeyProperties;
+ TProgramToShaderMap m_ProgramToShaderMap;
+
+ TStrConstanBufMap m_ConstantBuffers; ///< store all constants buffers
+
+ QT3DSI32 m_RefCount;
+
+ SShaderGenerator(IUICRenderContext &inRc)
+ : m_RenderContext(inRc)
+ , m_ProgramGenerator(m_RenderContext.GetShaderProgramGenerator())
+ , m_CurrentMaterial(NULL)
+ , m_CurrentKey(NULL)
+ , m_ShadowMapManager(NULL)
+ , m_CurrentPipeline(NULL)
+ , m_FirstImage(NULL)
+ , m_ProgramToShaderMap(inRc.GetAllocator(), "m_ProgramToShaderMap")
+ , m_ConstantBuffers(inRc.GetAllocator(), "m_ConstantBuffers")
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ m_ConstantBuffers.clear();
+ NVDelete(m_RenderContext.GetAllocator(), this);
+ }
+ }
+ IShaderProgramGenerator &ProgramGenerator() { return m_ProgramGenerator; }
+ IDefaultMaterialVertexPipeline &VertexGenerator() { return *m_CurrentPipeline; }
+ IShaderStageGenerator &FragmentGenerator()
+ {
+ return *m_ProgramGenerator.GetStage(ShaderGeneratorStages::Fragment);
+ }
+ SShaderDefaultMaterialKey &Key() { return *m_CurrentKey; }
+ const SDefaultMaterial &Material() { return *m_CurrentMaterial; }
+ TShaderFeatureSet FeatureSet() { return m_CurrentFeatureSet; }
+ bool HasTransparency() { return m_HasTransparency; }
+
+ void addFunction(IShaderStageGenerator &generator, QString functionName)
+ {
+ generator.AddFunction(functionName);
+ }
+
+ void SetupImageVariableNames(size_t imageIdx)
+ {
+ m_ImageStem = "image";
+ char buf[16];
+ _snprintf(buf, 16, "%lu", imageIdx);
+ m_ImageStem.append(buf);
+ m_ImageStem.append("_");
+
+ m_ImageSampler = m_ImageStem;
+ m_ImageSampler.append("sampler");
+ m_ImageOffsets = m_ImageStem;
+ m_ImageOffsets.append("offsets");
+ m_ImageRotations = m_ImageStem;
+ m_ImageRotations.append("rotations");
+ m_ImageFragCoords = m_ImageStem;
+ m_ImageFragCoords.append("uv_coords");
+ }
+
+ void SetupTexCoordVariableName(size_t uvSet)
+ {
+ m_TexCoordTemp = "varTexCoord";
+ char buf[16];
+ _snprintf(buf, 16, "%lu", uvSet);
+ m_TexCoordTemp.append(buf);
+ }
+
+ SImageVariableNames GetImageVariableNames(QT3DSU32 inIdx) override
+ {
+ SetupImageVariableNames(inIdx);
+ SImageVariableNames retval;
+ retval.m_ImageSampler = m_ImageSampler.c_str();
+ retval.m_ImageFragCoords = m_ImageFragCoords.c_str();
+ return retval;
+ }
+
+ void AddLocalVariable(IShaderStageGenerator &inGenerator, const char8_t *inName,
+ const char8_t *inType)
+ {
+ inGenerator << "\t" << inType << " " << inName << ";" << Endl;
+ }
+
+ void AddLocalVariable(IShaderStageGenerator &inGenerator, const TStrType &inName,
+ const char8_t *inType)
+ {
+ AddLocalVariable(inGenerator, inName.c_str(), inType);
+ }
+
+ void GenerateImageUVCoordinates(IShaderStageGenerator &inVertexPipeline, QT3DSU32 idx, QT3DSU32 uvSet,
+ SRenderableImage &image) override
+ {
+ IDefaultMaterialVertexPipeline &vertexShader(
+ static_cast<IDefaultMaterialVertexPipeline &>(inVertexPipeline));
+ IShaderStageGenerator &fragmentShader(FragmentGenerator());
+ SetupImageVariableNames(idx);
+ SetupTexCoordVariableName(uvSet);
+ fragmentShader.AddUniform(m_ImageSampler, "sampler2D");
+ vertexShader.AddUniform(m_ImageOffsets, "vec3");
+ fragmentShader.AddUniform(m_ImageOffsets, "vec3");
+ vertexShader.AddUniform(m_ImageRotations, "vec4");
+ fragmentShader.AddUniform(m_ImageRotations, "vec4");
+
+ if (image.m_Image.m_MappingMode == ImageMappingModes::Normal) {
+ vertexShader << "\tuTransform = vec3( " << m_ImageRotations << ".x, "
+ << m_ImageRotations << ".y, " << m_ImageOffsets << ".x );" << Endl;
+ vertexShader << "\tvTransform = vec3( " << m_ImageRotations << ".z, "
+ << m_ImageRotations << ".w, " << m_ImageOffsets << ".y );" << Endl;
+ vertexShader.AddOutgoing(m_ImageFragCoords, "vec2");
+ addFunction(vertexShader, "getTransformedUVCoords");
+ vertexShader.GenerateUVCoords(uvSet);
+ m_ImageTemp = m_ImageFragCoords;
+ m_ImageTemp.append("temp");
+ vertexShader << "\tvec2 " << m_ImageTemp << " = getTransformedUVCoords( vec3( "
+ << m_TexCoordTemp << ", 1.0), uTransform, vTransform );" << Endl;
+ if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
+ vertexShader << "\t" << m_ImageTemp << ".y = 1.0 - " << m_ImageFragCoords << ".y;"
+ << Endl;
+
+ vertexShader.AssignOutput(m_ImageFragCoords.c_str(), m_ImageTemp.c_str());
+ } else {
+ fragmentShader << "\tuTransform = vec3( " << m_ImageRotations << ".x, "
+ << m_ImageRotations << ".y, " << m_ImageOffsets << ".x );" << Endl;
+ fragmentShader << "\tvTransform = vec3( " << m_ImageRotations << ".z, "
+ << m_ImageRotations << ".w, " << m_ImageOffsets << ".y );" << Endl;
+ vertexShader.GenerateEnvMapReflection();
+ addFunction(fragmentShader, "getTransformedUVCoords");
+ fragmentShader << "\tvec2 " << m_ImageFragCoords
+ << " = getTransformedUVCoords( environment_map_reflection, uTransform, "
+ "vTransform );"
+ << Endl;
+ if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
+ fragmentShader << "\t" << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords
+ << ".y;" << Endl;
+ }
+ }
+
+ void GenerateImageUVCoordinates(QT3DSU32 idx, SRenderableImage &image, QT3DSU32 uvSet = 0)
+ {
+ GenerateImageUVCoordinates(VertexGenerator(), idx, uvSet, image);
+ }
+
+ void GenerateImageUVCoordinates(QT3DSU32 idx, SRenderableImage &image,
+ IDefaultMaterialVertexPipeline &inShader)
+ {
+ if (image.m_Image.m_MappingMode == ImageMappingModes::Normal) {
+ SetupImageVariableNames(idx);
+ inShader.AddUniform(m_ImageSampler, "sampler2D");
+ inShader.AddUniform(m_ImageOffsets, "vec3");
+ inShader.AddUniform(m_ImageRotations, "vec4");
+
+ inShader << "\tuTransform = vec3( " << m_ImageRotations << ".x, " << m_ImageRotations
+ << ".y, " << m_ImageOffsets << ".x );" << Endl;
+ inShader << "\tvTransform = vec3( " << m_ImageRotations << ".z, " << m_ImageRotations
+ << ".w, " << m_ImageOffsets << ".y );" << Endl;
+ inShader << "\tvec2 " << m_ImageFragCoords << ";" << Endl;
+ addFunction(inShader, "getTransformedUVCoords");
+ inShader.GenerateUVCoords();
+ inShader
+ << "\t" << m_ImageFragCoords
+ << " = getTransformedUVCoords( vec3( varTexCoord0, 1.0), uTransform, vTransform );"
+ << Endl;
+ if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
+ inShader << "\t" << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords << ".y;"
+ << Endl;
+ }
+ }
+
+ void OutputSpecularEquation(DefaultMaterialSpecularModel::Enum inSpecularModel,
+ IShaderStageGenerator &fragmentShader, const char *inLightDir,
+ const char *inLightSpecColor)
+ {
+ switch (inSpecularModel) {
+ case DefaultMaterialSpecularModel::KGGX: {
+ fragmentShader.AddInclude("defaultMaterialPhysGlossyBSDF.glsllib");
+ fragmentShader.AddUniform("material_specular", "vec4");
+ fragmentShader << "\tglobal_specular_light.rgb += lightAttenuation * specularAmount * "
+ "kggxGlossyDefaultMtl( "
+ << "world_normal, tangent, -" << inLightDir << ".xyz, view_vector, "
+ << inLightSpecColor
+ << ".rgb, vec3(material_specular.xyz), material_properties.y, "
+ "material_properties.y ).rgb;"
+ << Endl;
+ } break;
+ case DefaultMaterialSpecularModel::KWard: {
+ fragmentShader.AddInclude("defaultMaterialPhysGlossyBSDF.glsllib");
+ fragmentShader.AddUniform("material_specular", "vec4");
+ fragmentShader << "\tglobal_specular_light.rgb += lightAttenuation * specularAmount * "
+ "wardGlossyDefaultMtl( "
+ << "world_normal, tangent, -" << inLightDir << ".xyz, view_vector, "
+ << inLightSpecColor
+ << ".rgb, vec3(material_specular.xyz), material_properties.y, "
+ "material_properties.y ).rgb;"
+ << Endl;
+ } break;
+ default:
+ addFunction(fragmentShader, "specularBSDF");
+ fragmentShader << "\tglobal_specular_light.rgb += lightAttenuation * specularAmount * "
+ "specularBSDF( "
+ << "world_normal, -" << inLightDir << ".xyz, view_vector, "
+ << inLightSpecColor << ".rgb, 1.0, 2.56 / (material_properties.y + "
+ "0.01), vec3(1.0), scatter_reflect ).rgb;"
+ << Endl;
+ break;
+ }
+ }
+
+ void OutputDiffuseAreaLighting(IShaderStageGenerator &infragmentShader, const char *inPos,
+ TStrType inLightPrefix)
+ {
+ m_LightAttenutation = inLightPrefix + "_attenuation";
+ m_NormalizedDirection = inLightPrefix + "_areaDir";
+ AddLocalVariable(infragmentShader, m_NormalizedDirection, "vec3");
+ infragmentShader << "\tlightAttenuation = calculateDiffuseAreaOld( " << m_LightDirection
+ << ".xyz, " << m_LightPos << ".xyz, " << m_LightUp << ", " << m_LightRt
+ << ", " << inPos << ", " << m_NormalizedDirection << " );" << Endl;
+ }
+
+ void OutputSpecularAreaLighting(IShaderStageGenerator &infragmentShader, const char *inPos,
+ const char *inView, const char *inLightSpecColor)
+ {
+ addFunction(infragmentShader, "sampleAreaGlossyDefault");
+ infragmentShader.AddUniform("material_specular", "vec4");
+ infragmentShader << "global_specular_light.rgb += " << inLightSpecColor
+ << ".rgb * lightAttenuation * shadowFac * material_specular.rgb * "
+ "specularAmount * sampleAreaGlossyDefault( tanFrame, "
+ << inPos << ", " << m_NormalizedDirection << ", " << m_LightPos << ".xyz, "
+ << m_LightRt << ".w, " << m_LightUp << ".w, " << inView
+ << ", material_properties.y, material_properties.y ).rgb;" << Endl;
+ }
+
+ void AddTranslucencyIrradiance(IShaderStageGenerator &infragmentShader, SRenderableImage *image,
+ TStrType inLightPrefix, bool areaLight)
+ {
+ if (image == NULL)
+ return;
+
+ addFunction(infragmentShader, "diffuseReflectionWrapBSDF");
+ if (areaLight) {
+ infragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ "translucent_thickness_exp * diffuseReflectionWrapBSDF( "
+ "-world_normal, "
+ << m_NormalizedDirection << ", " << m_LightColor
+ << ".rgb, diffuseLightWrap ).rgb;" << Endl;
+ } else {
+ infragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ "translucent_thickness_exp * diffuseReflectionWrapBSDF( "
+ "-world_normal, "
+ << "-" << m_NormalizedDirection << ", " << m_LightColor
+ << ".rgb, diffuseLightWrap ).rgb;" << Endl;
+ }
+ }
+
+ void SetupShadowMapVariableNames(size_t lightIdx)
+ {
+ m_ShadowMapStem = "shadowmap";
+ m_ShadowCubeStem = "shadowcube";
+ char buf[16];
+ _snprintf(buf, 16, "%lu", lightIdx);
+ m_ShadowMapStem.append(buf);
+ m_ShadowCubeStem.append(buf);
+ m_ShadowMatrixStem = m_ShadowMapStem;
+ m_ShadowMatrixStem.append("_matrix");
+ m_ShadowCoordStem = m_ShadowMapStem;
+ m_ShadowCoordStem.append("_coord");
+ m_ShadowControlStem = m_ShadowMapStem;
+ m_ShadowControlStem.append("_control");
+ }
+
+ void AddShadowMapContribution(IShaderStageGenerator &inLightShader, QT3DSU32 lightIndex,
+ RenderLightTypes::Enum inType)
+ {
+ SetupShadowMapVariableNames(lightIndex);
+
+ inLightShader.AddInclude("shadowMapping.glsllib");
+ if (inType == RenderLightTypes::Directional) {
+ inLightShader.AddUniform(m_ShadowMapStem, "sampler2D");
+ } else {
+ inLightShader.AddUniform(m_ShadowCubeStem, "samplerCube");
+ }
+ inLightShader.AddUniform(m_ShadowControlStem, "vec4");
+ inLightShader.AddUniform(m_ShadowMatrixStem, "mat4");
+
+ /*
+ if ( inType == RenderLightTypes::Area )
+ {
+ inLightShader << "vec2 " << m_ShadowCoordStem << ";" << Endl;
+ inLightShader << "\tshadow_map_occl = sampleParaboloid( " << m_ShadowMapStem << ", "
+ << m_ShadowControlStem << ", "
+ <<
+ m_ShadowMatrixStem << ", varWorldPos, vec2(1.0, " << m_ShadowControlStem << ".z), "
+ << m_ShadowCoordStem
+ << " );" << Endl;
+ }
+ else */
+ if (inType != RenderLightTypes::Directional) {
+ inLightShader << "\tshadow_map_occl = sampleCubemap( " << m_ShadowCubeStem << ", "
+ << m_ShadowControlStem << ", " << m_ShadowMatrixStem << ", " << m_LightPos
+ << ".xyz, varWorldPos, vec2(1.0, " << m_ShadowControlStem << ".z) );"
+ << Endl;
+ } else
+ inLightShader << "\tshadow_map_occl = sampleOrthographic( " << m_ShadowMapStem << ", "
+ << m_ShadowControlStem << ", " << m_ShadowMatrixStem
+ << ", varWorldPos, vec2(1.0, " << m_ShadowControlStem << ".z) );" << Endl;
+ }
+
+ void AddDisplacementMappingForDepthPass(IShaderStageGenerator &inShader) override
+ {
+ inShader.AddIncoming("attr_uv0", "vec2");
+ inShader.AddIncoming("attr_norm", "vec3");
+ inShader.AddUniform("displacementSampler", "sampler2D");
+ inShader.AddUniform("displaceAmount", "float");
+ inShader.AddUniform("displacementMap_rot", "vec4");
+ inShader.AddUniform("displacementMap_offset", "vec3");
+ inShader.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+
+ inShader.Append("\tvec3 uTransform = vec3( displacementMap_rot.x, displacementMap_rot.y, "
+ "displacementMap_offset.x );");
+ inShader.Append("\tvec3 vTransform = vec3( displacementMap_rot.z, displacementMap_rot.w, "
+ "displacementMap_offset.y );");
+ addFunction(inShader, "getTransformedUVCoords");
+ inShader.Append("\tvec2 uv_coords = attr_uv0;");
+ inShader << "\tuv_coords = getTransformedUVCoords( vec3( uv_coords, 1.0), uTransform, "
+ "vTransform );\n";
+ inShader << "\tvec3 displacedPos = uicDefaultMaterialFileDisplacementTexture( "
+ "displacementSampler , displaceAmount, uv_coords , attr_norm, attr_pos );"
+ << Endl;
+ inShader.Append("\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ }
+
+ void AddDisplacementImageUniforms(IShaderStageGenerator &inGenerator,
+ QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) override
+ {
+ if (displacementImage) {
+ SetupImageVariableNames(displacementImageIdx);
+ inGenerator.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+ inGenerator.AddUniform("model_matrix", "mat4");
+ inGenerator.AddUniform("camera_position", "vec3");
+ inGenerator.AddUniform("displaceAmount", "float");
+ inGenerator.AddUniform(m_ImageSampler, "sampler2D");
+ }
+ }
+
+ bool MaybeAddMaterialFresnel(IShaderStageGenerator &fragmentShader, NVConstDataRef<QT3DSU32> inKey,
+ bool inFragmentHasSpecularAmount)
+ {
+ if (m_DefaultMaterialShaderKeyProperties.m_FresnelEnabled.GetValue(inKey)) {
+ if (inFragmentHasSpecularAmount == false)
+ fragmentShader << "\tfloat specularAmount = 1.0;" << Endl;
+ inFragmentHasSpecularAmount = true;
+ fragmentShader.AddInclude("defaultMaterialFresnel.glsllib");
+ fragmentShader.AddUniform("fresnelPower", "float");
+ fragmentShader.AddUniform("material_specular", "vec4");
+ fragmentShader << "\tfloat fresnelRatio = defaultMaterialSimpleFresnel( world_normal, "
+ "view_vector, material_specular.w, fresnelPower );"
+ << Endl;
+ fragmentShader << "\tspecularAmount *= fresnelRatio;" << Endl;
+ }
+ return inFragmentHasSpecularAmount;
+ }
+ void SetupLightVariableNames(size_t lightIdx, SLight &inLight)
+ {
+ m_LightStem = "lights";
+ char buf[16];
+ _snprintf(buf, 16, "[%lu].", lightIdx);
+ m_LightStem.append(buf);
+
+ m_LightColor = m_LightStem;
+ m_LightColor.append("diffuse");
+ m_LightDirection = m_LightStem;
+ m_LightDirection.append("direction");
+ m_LightSpecularColor = m_LightStem;
+ m_LightSpecularColor.append("specular");
+ if (inLight.m_LightType == RenderLightTypes::Point) {
+ m_LightPos = m_LightStem;
+ m_LightPos.append("position");
+ m_LightConstantAttenuation = m_LightStem;
+ m_LightConstantAttenuation.append("constantAttenuation");
+ m_LightLinearAttenuation = m_LightStem;
+ m_LightLinearAttenuation.append("linearAttenuation");
+ m_LightQuadraticAttenuation = m_LightStem;
+ m_LightQuadraticAttenuation.append("quadraticAttenuation");
+ } else if (inLight.m_LightType == RenderLightTypes::Area) {
+ m_LightPos = m_LightStem;
+ m_LightPos.append("position");
+ m_LightUp = m_LightStem;
+ m_LightUp.append("up");
+ m_LightRt = m_LightStem;
+ m_LightRt.append("right");
+ }
+ }
+
+ void addDisplacementMapping(IDefaultMaterialVertexPipeline &inShader)
+ {
+ inShader.AddIncoming("attr_uv0", "vec2");
+ inShader.AddIncoming("attr_norm", "vec3");
+ inShader.AddUniform("displacementSampler", "sampler2D");
+ inShader.AddUniform("displaceAmount", "float");
+ inShader.AddUniform("displacementMap_rot", "vec4");
+ inShader.AddUniform("displacementMap_offset", "vec3");
+ inShader.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+
+ inShader.Append("\tvec3 uTransform = vec3( displacementMap_rot.x, displacementMap_rot.y, "
+ "displacementMap_offset.x );");
+ inShader.Append("\tvec3 vTransform = vec3( displacementMap_rot.z, displacementMap_rot.w, "
+ "displacementMap_offset.y );");
+ addFunction(inShader, "getTransformedUVCoords");
+ inShader.GenerateUVCoords();
+ inShader << "\tvarTexCoord0 = getTransformedUVCoords( vec3( varTexCoord0, 1.0), "
+ "uTransform, vTransform );\n";
+ inShader << "\tvec3 displacedPos = uicDefaultMaterialFileDisplacementTexture( "
+ "displacementSampler , displaceAmount, varTexCoord0 , attr_norm, attr_pos );"
+ << Endl;
+ inShader.Append("\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ }
+
+ void GenerateTextureSwizzle(NVRenderTextureSwizzleMode::Enum swizzleMode,
+ eastl::basic_string<char8_t> &texSwizzle,
+ eastl::basic_string<char8_t> &lookupSwizzle)
+ {
+ qt3ds::render::NVRenderContextType deprecatedContextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+
+ if (!(m_RenderContext.GetRenderContext().GetRenderContextType() & deprecatedContextFlags)) {
+ switch (swizzleMode) {
+ case NVRenderTextureSwizzleMode::L8toR8:
+ case NVRenderTextureSwizzleMode::L16toR16:
+ texSwizzle.append(".rgb");
+ lookupSwizzle.append(".rrr");
+ break;
+ case NVRenderTextureSwizzleMode::L8A8toRG8:
+ texSwizzle.append(".rgba");
+ lookupSwizzle.append(".rrrg");
+ break;
+ case NVRenderTextureSwizzleMode::A8toR8:
+ texSwizzle.append(".a");
+ lookupSwizzle.append(".r");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ ///< get the light constant buffer and generate if necessary
+ NVRenderConstantBuffer *GetLightConstantBuffer(QT3DSU32 inLightCount)
+ {
+ NVRenderContext &theContext(m_RenderContext.GetRenderContext());
+
+ // we assume constant buffer support
+ QT3DS_ASSERT(theContext.GetConstantBufferSupport());
+
+ // we only create if if we have lights
+ if (!inLightCount || !theContext.GetConstantBufferSupport())
+ return NULL;
+
+ CRegisteredString theName = theContext.GetStringTable().RegisterStr("cbBufferLights");
+ NVRenderConstantBuffer *pCB = theContext.GetConstantBuffer(theName);
+
+ if (!pCB) {
+ // create
+ SLightSourceShader s[UIC_MAX_NUM_LIGHTS];
+ NVDataRef<QT3DSU8> cBuffer((QT3DSU8 *)&s, (sizeof(SLightSourceShader) * UIC_MAX_NUM_LIGHTS)
+ + (4 * sizeof(QT3DSI32)));
+ pCB = theContext.CreateConstantBuffer(
+ theName, qt3ds::render::NVRenderBufferUsageType::Static,
+ (sizeof(SLightSourceShader) * UIC_MAX_NUM_LIGHTS) + (4 * sizeof(QT3DSI32)), cBuffer);
+ if (!pCB) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ // init first set
+ memset(&s[0], 0x0, sizeof(SLightSourceShader));
+ QT3DSI32 cgLights = 0;
+ pCB->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&cgLights, sizeof(QT3DSI32)));
+ pCB->UpdateRaw(4 * sizeof(QT3DSI32),
+ NVDataRef<QT3DSU8>((QT3DSU8 *)&s[0], sizeof(SLightSourceShader)));
+ pCB->Update(); // update to hardware
+
+ m_ConstantBuffers.insert(eastl::make_pair(theName, pCB));
+ }
+
+ return pCB;
+ }
+
+ void SetImageShaderVariables(SShaderGeneratorGeneratedShader &inShader,
+ SRenderableImage &inImage, QT3DSU32 idx)
+ {
+ size_t numImageVariables = inShader.m_Images.size();
+ for (size_t namesIdx = numImageVariables; namesIdx <= idx; ++namesIdx) {
+ SetupImageVariableNames(idx);
+ inShader.m_Images.push_back(
+ SShaderTextureProperties(m_ImageSampler.c_str(), m_ImageOffsets.c_str(),
+ m_ImageRotations.c_str(), inShader.m_Shader));
+ }
+ SShaderTextureProperties &theShaderProps = inShader.m_Images[idx];
+ const QT3DSMat44 &textureTransform = inImage.m_Image.m_TextureTransform;
+ // We separate rotational information from offset information so that just maybe the shader
+ // will attempt to push less information to the card.
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ // The third member of the offsets contains a flag indicating if the texture was
+ // premultiplied or not.
+ // We use this to mix the texture alpha.
+ QT3DSVec3 offsets(dataPtr[12], dataPtr[13],
+ inImage.m_Image.m_TextureData.m_TextureFlags.IsPreMultiplied() ? 1.0f
+ : 0.0f);
+ // Grab just the upper 2x2 rotation matrix from the larger matrix.
+ QT3DSVec4 rotations(dataPtr[0], dataPtr[4], dataPtr[1], dataPtr[5]);
+
+ // The image horizontal and vertical tiling modes need to be set here, before we set texture
+ // on the shader.
+ // because setting the image on the texture forces the textue to bind and immediately apply
+ // any tex params.
+ inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapS(
+ inImage.m_Image.m_HorizontalTilingMode);
+ inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapT(
+ inImage.m_Image.m_VerticalTilingMode);
+ theShaderProps.m_Sampler.Set(inImage.m_Image.m_TextureData.m_Texture);
+ theShaderProps.m_Offsets.Set(offsets);
+ theShaderProps.m_Rotations.Set(rotations);
+ }
+
+ void GenerateShadowMapOcclusion(QT3DSU32 lightIdx, bool inShadowEnabled,
+ RenderLightTypes::Enum inType)
+ {
+ if (inShadowEnabled) {
+ VertexGenerator().GenerateWorldPosition();
+ AddShadowMapContribution(FragmentGenerator(), lightIdx, inType);
+ /*
+ VertexGenerator().AddUniform( m_ShadowMatrixStem, "mat4" );
+ VertexGenerator().AddOutgoing( m_ShadowCoordStem, "vec4" );
+ VertexGenerator() << "\tvec4 local_" << m_ShadowCoordStem << " = " << m_ShadowMatrixStem
+ << " * vec4(local_model_world_position, 1.0);" << Endl;
+ m_TempStr.assign( "local_" );
+ m_TempStr.append( m_ShadowCoordStem );
+ VertexGenerator().AssignOutput( m_ShadowCoordStem.c_str(), m_TempStr.c_str() );
+ */
+ } else {
+ FragmentGenerator() << "\tshadow_map_occl = 1.0;" << Endl;
+ }
+ }
+
+ void GenerateVertexShader()
+ {
+ // vertex displacement
+ QT3DSU32 imageIdx = 0;
+ SRenderableImage *displacementImage = NULL;
+ QT3DSU32 displacementImageIdx = 0;
+
+ for (SRenderableImage *img = m_FirstImage; img != NULL;
+ img = img->m_NextImage, ++imageIdx) {
+ if (img->m_MapType == ImageMapTypes::Displacement) {
+ displacementImage = img;
+ displacementImageIdx = imageIdx;
+ break;
+ }
+ }
+
+ // the pipeline opens/closes up the shaders stages
+ VertexGenerator().BeginVertexGeneration(displacementImageIdx, displacementImage);
+ }
+
+ void GenerateFragmentShader(SShaderDefaultMaterialKey &inKey)
+ {
+ bool specularEnabled = Material().IsSpecularEnabled();
+
+ bool hasLighting = Material().HasLighting();
+ bool hasImage = m_FirstImage != NULL;
+
+ bool hasIblProbe = m_DefaultMaterialShaderKeyProperties.m_HasIbl.GetValue(inKey);
+ bool hasSpecMap = false;
+ bool hasEnvMap = false;
+ bool hasEmissiveMap = false;
+ bool hasLightmaps = false;
+ // Pull the bump out as
+ SRenderableImage *bumpImage = NULL;
+ QT3DSU32 imageIdx = 0;
+ QT3DSU32 bumpImageIdx = 0;
+ SRenderableImage *specularAmountImage = NULL;
+ QT3DSU32 specularAmountImageIdx = 0;
+ // normal mapping
+ SRenderableImage *normalImage = NULL;
+ QT3DSU32 normalImageIdx = 0;
+ // translucency map
+ SRenderableImage *translucencyImage = NULL;
+ QT3DSU32 translucencyImageIdx = 0;
+ // lightmaps
+ SRenderableImage *lightmapIndirectImage = NULL;
+ QT3DSU32 lightmapIndirectImageIdx = 0;
+ SRenderableImage *lightmapRadiosityImage = NULL;
+ QT3DSU32 lightmapRadiosityImageIdx = 0;
+ SRenderableImage *lightmapShadowImage = NULL;
+ QT3DSU32 lightmapShadowImageIdx = 0;
+
+ for (SRenderableImage *img = m_FirstImage; img != NULL;
+ img = img->m_NextImage, ++imageIdx) {
+ hasSpecMap = img->m_MapType == ImageMapTypes::Specular;
+ if (img->m_MapType == ImageMapTypes::Bump) {
+ bumpImage = img;
+ bumpImageIdx = imageIdx;
+ } else if (img->m_MapType == ImageMapTypes::SpecularAmountMap) {
+ specularAmountImage = img;
+ specularAmountImageIdx = imageIdx;
+ } else if (img->m_MapType == ImageMapTypes::Normal) {
+ normalImage = img;
+ normalImageIdx = imageIdx;
+ } else if (img->m_Image.m_MappingMode == ImageMappingModes::Environment) {
+ hasEnvMap = true;
+ } else if (img->m_MapType == ImageMapTypes::Translucency) {
+ translucencyImage = img;
+ translucencyImageIdx = imageIdx;
+ } else if (img->m_MapType == ImageMapTypes::Emissive) {
+ hasEmissiveMap = true;
+ } else if (img->m_MapType == ImageMapTypes::LightmapIndirect) {
+ lightmapIndirectImage = img;
+ lightmapIndirectImageIdx = imageIdx;
+ hasLightmaps = true;
+ } else if (img->m_MapType == ImageMapTypes::LightmapRadiosity) {
+ lightmapRadiosityImage = img;
+ lightmapRadiosityImageIdx = imageIdx;
+ hasLightmaps = true;
+ } else if (img->m_MapType == ImageMapTypes::LightmapShadow) {
+ lightmapShadowImage = img;
+ lightmapShadowImageIdx = imageIdx;
+ hasLightmaps = true;
+ }
+ }
+
+ bool enableFresnel = m_DefaultMaterialShaderKeyProperties.m_FresnelEnabled.GetValue(inKey);
+ bool enableSSAO = false;
+ bool enableSSDO = false;
+ bool enableShadowMaps = false;
+
+ for (QT3DSU32 idx = 0; idx < FeatureSet().size(); ++idx) {
+ eastl::string name(FeatureSet()[idx].m_Name.c_str());
+ if (name == "UIC_ENABLE_SSAO")
+ enableSSAO = FeatureSet()[idx].m_Enabled;
+ else if (name == "UIC_ENABLE_SSDO")
+ enableSSDO = FeatureSet()[idx].m_Enabled;
+ else if (name == "UIC_ENABLE_SSM")
+ enableShadowMaps = FeatureSet()[idx].m_Enabled;
+ }
+
+ bool includeSSAOSSDOVars = enableSSAO || enableSSDO || enableShadowMaps;
+
+ VertexGenerator().BeginFragmentGeneration();
+ IShaderStageGenerator &fragmentShader(FragmentGenerator());
+ IDefaultMaterialVertexPipeline &vertexShader(VertexGenerator());
+
+ // The fragment or vertex shaders may not use the material_properties or diffuse
+ // uniforms in all cases but it is simpler to just add them and let the linker strip them.
+ fragmentShader.AddUniform("material_diffuse", "vec4");
+ fragmentShader.AddUniform("diffuse_color", "vec3");
+ fragmentShader.AddUniform("material_properties", "vec4");
+
+ // All these are needed for SSAO
+ if (includeSSAOSSDOVars) {
+ fragmentShader.AddInclude("SSAOCustomMaterial.glsllib");
+ // fragmentShader.AddUniform( "ao_sampler", "sampler2D" );
+ }
+
+ if (hasIblProbe && hasLighting) {
+ fragmentShader.AddInclude("sampleProbe.glsllib");
+ }
+
+ if (hasLighting) {
+ addFunction(fragmentShader, "sampleLightVars");
+ addFunction(fragmentShader, "diffuseReflectionBSDF");
+ }
+
+ if (hasLighting && hasLightmaps) {
+ fragmentShader.AddInclude("evalLightmaps.glsllib");
+ }
+
+ // view_vector, varWorldPos, world_normal are all used if there is a specular map
+ // in addition to if there is specular lighting. So they are lifted up here, always
+ // generated.
+ // we rely on the linker to strip out what isn't necessary instead of explicitly stripping
+ // it for code simplicity.
+ if (hasImage) {
+ fragmentShader.Append("\tvec3 uTransform;");
+ fragmentShader.Append("\tvec3 vTransform;");
+ }
+
+ if (includeSSAOSSDOVars || hasSpecMap || hasLighting || hasEnvMap || enableFresnel || hasIblProbe) {
+ vertexShader.GenerateViewVector();
+ vertexShader.GenerateWorldNormal();
+ vertexShader.GenerateWorldPosition();
+ }
+ if (includeSSAOSSDOVars || bumpImage || normalImage || specularEnabled || hasIblProbe)
+ vertexShader.GenerateVarTangentAndBinormal();
+
+ // You do bump or normal mapping but not both
+ if (bumpImage != NULL) {
+ GenerateImageUVCoordinates(bumpImageIdx, *bumpImage);
+ fragmentShader.AddUniform("bumpAmount", "float");
+
+ fragmentShader.AddInclude("uicDefaultMaterialFileBumpTexture.glsllib");
+ // vec3 simplerFileBumpTexture( in sampler2D sampler, in float factor, vec2
+ // texCoord, vec3 tangent, vec3 binormal, vec3 normal )
+
+ fragmentShader << "\tworld_normal = simplerFileBumpTexture( " << m_ImageSampler
+ << ", bumpAmount, " << m_ImageFragCoords
+ << ", tangent, binormal, world_normal );" << Endl;
+ // Do gram schmidt
+ fragmentShader << "\tbinormal = normalize(cross(world_normal, tangent) );\n";
+ fragmentShader << "\ttangent = normalize(cross(binormal, world_normal) );\n";
+
+ } else if (normalImage != NULL) {
+ GenerateImageUVCoordinates(normalImageIdx, *normalImage);
+
+ fragmentShader.AddInclude("uicDefaultMaterialFileNormalTexture.glsllib");
+ fragmentShader.AddUniform("bumpAmount", "float");
+
+ fragmentShader << "\tworld_normal = uicDefaultMaterialFileNormalTexture( "
+ << m_ImageSampler << ", bumpAmount, " << m_ImageFragCoords
+ << ", tangent, binormal );" << Endl;
+ }
+
+ if (includeSSAOSSDOVars || specularEnabled || hasIblProbe)
+ fragmentShader << "\tmat3 tanFrame = mat3(tangent, binormal, world_normal);" << Endl;
+
+ bool fragmentHasSpecularAmount = false;
+
+ if (hasEmissiveMap) {
+ fragmentShader.Append("\tvec3 global_emission = material_diffuse.rgb;");
+ }
+
+ if (hasLighting) {
+ fragmentShader.AddUniform("light_ambient_total", "vec3");
+
+ fragmentShader.Append(
+ "\tvec4 global_diffuse_light = vec4(light_ambient_total.xyz, 1.0);");
+ fragmentShader.Append("\tvec3 global_specular_light = vec3(0.0, 0.0, 0.0);");
+ fragmentShader.Append("\tfloat shadow_map_occl = 1.0;");
+
+ if (specularEnabled) {
+ vertexShader.GenerateViewVector();
+ fragmentShader.AddUniform("material_properties", "vec4");
+ }
+
+ if (lightmapIndirectImage != NULL) {
+ GenerateImageUVCoordinates(lightmapIndirectImageIdx, *lightmapIndirectImage, 1);
+ fragmentShader << "\tvec4 indirect_light = texture2D( " << m_ImageSampler << ", "
+ << m_ImageFragCoords << ");" << Endl;
+ fragmentShader << "\tglobal_diffuse_light += indirect_light;" << Endl;
+ if (specularEnabled) {
+ fragmentShader
+ << "\tglobal_specular_light += indirect_light.rgb * material_properties.x;"
+ << Endl;
+ }
+ }
+
+ if (lightmapRadiosityImage != NULL) {
+ GenerateImageUVCoordinates(lightmapRadiosityImageIdx, *lightmapRadiosityImage, 1);
+ fragmentShader << "\tvec4 direct_light = texture2D( " << m_ImageSampler << ", "
+ << m_ImageFragCoords << ");" << Endl;
+ fragmentShader << "\tglobal_diffuse_light += direct_light;" << Endl;
+ if (specularEnabled) {
+ fragmentShader
+ << "\tglobal_specular_light += direct_light.rgb * material_properties.x;"
+ << Endl;
+ }
+ }
+
+ if (translucencyImage != NULL) {
+ fragmentShader.AddUniform("translucentFalloff", "float");
+ fragmentShader.AddUniform("diffuseLightWrap", "float");
+
+ GenerateImageUVCoordinates(translucencyImageIdx, *translucencyImage);
+
+ fragmentShader << "\tvec4 translucent_depth_range = texture2D( " << m_ImageSampler
+ << ", " << m_ImageFragCoords << ");" << Endl;
+ fragmentShader << "\tfloat translucent_thickness = translucent_depth_range.r * "
+ "translucent_depth_range.r;"
+ << Endl;
+ fragmentShader << "\tfloat translucent_thickness_exp = exp( translucent_thickness "
+ "* translucentFalloff);"
+ << Endl;
+ }
+
+ fragmentShader.Append("\tfloat lightAttenuation = 1.0;");
+
+ AddLocalVariable(fragmentShader, "aoFactor", "float");
+
+ if (hasLighting && enableSSAO)
+ fragmentShader.Append("\taoFactor = customMaterialAO();");
+ else
+ fragmentShader.Append("\taoFactor = 1.0;");
+
+ AddLocalVariable(fragmentShader, "shadowFac", "float");
+
+ if (specularEnabled) {
+ fragmentShader << "\tfloat specularAmount = material_properties.x;" << Endl;
+ fragmentHasSpecularAmount = true;
+ }
+ // Fragment lighting means we can perhaps attenuate the specular amount by a texture
+ // lookup.
+ if (specularAmountImage) {
+ if (!specularEnabled)
+ fragmentShader << "\tfloat specularAmount = 1.0;" << Endl;
+ GenerateImageUVCoordinates(specularAmountImageIdx, *specularAmountImage);
+ fragmentShader << "\tspecularAmount = specularAmount * texture2D( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << " ).x;" << Endl;
+ fragmentHasSpecularAmount = true;
+ }
+
+ fragmentHasSpecularAmount =
+ MaybeAddMaterialFresnel(fragmentShader, inKey, fragmentHasSpecularAmount);
+
+ // Iterate through all lights
+ for (QT3DSU32 lightIdx = 0; lightIdx < m_Lights.size(); ++lightIdx) {
+ SLight *lightNode = m_Lights[lightIdx];
+ SetupLightVariableNames(lightIdx, *lightNode);
+ bool isDirectional = lightNode->m_LightType == RenderLightTypes::Directional;
+ bool isArea = lightNode->m_LightType == RenderLightTypes::Area;
+ bool isShadow = enableShadowMaps && lightNode->m_CastShadow;
+
+ fragmentShader.Append("");
+ char buf[10];
+ sprintf(buf, "%d", lightIdx);
+
+ m_TempStr.assign("light");
+ m_TempStr.append(buf);
+
+ fragmentShader << "\t//Light " << buf << Endl;
+ fragmentShader << "\tlightAttenuation = 1.0;" << Endl;
+ if (isDirectional) {
+
+ if (enableSSDO) {
+ fragmentShader << "\tshadowFac = customMaterialShadow( " << m_LightDirection
+ << ".xyz, varWorldPos );" << Endl;
+ } else {
+ fragmentShader << "\tshadowFac = 1.0;" << Endl;
+ }
+
+ GenerateShadowMapOcclusion(lightIdx, enableShadowMaps && isShadow,
+ lightNode->m_LightType);
+
+ if (specularEnabled && enableShadowMaps && isShadow)
+ fragmentShader << "\tlightAttenuation *= shadow_map_occl;" << Endl;
+
+ fragmentShader << "\tglobal_diffuse_light.rgb += shadowFac * shadow_map_occl * "
+ "diffuseReflectionBSDF( world_normal, "
+ << "-" << m_LightDirection << ".xyz, view_vector, "
+ << m_LightColor << ".rgb, 0.0 ).rgb;" << Endl;
+
+ if (specularEnabled) {
+ OutputSpecularEquation(Material().m_SpecularModel, fragmentShader,
+ m_LightDirection.c_str(),
+ m_LightSpecularColor.c_str());
+ }
+ } else if (isArea) {
+ addFunction(fragmentShader, "areaLightVars");
+ addFunction(fragmentShader, "calculateDiffuseAreaOld");
+ vertexShader.GenerateWorldPosition();
+ GenerateShadowMapOcclusion(lightIdx, enableShadowMaps && isShadow,
+ lightNode->m_LightType);
+
+ // Debug measure to make sure paraboloid sampling was projecting to the right
+ // location
+ // fragmentShader << "\tglobal_diffuse_light.rg += " << m_ShadowCoordStem << ";"
+ // << Endl;
+ m_NormalizedDirection = m_TempStr;
+ m_NormalizedDirection.append("_Frame");
+
+ AddLocalVariable(fragmentShader, m_NormalizedDirection, "mat3");
+ fragmentShader << m_NormalizedDirection << " = mat3( " << m_LightRt << ".xyz, "
+ << m_LightUp << ".xyz, -" << m_LightDirection << ".xyz );"
+ << Endl;
+
+ if (enableSSDO) {
+ fragmentShader << "\tshadowFac = shadow_map_occl * customMaterialShadow( "
+ << m_LightDirection << ".xyz, varWorldPos );" << Endl;
+ } else {
+ fragmentShader << "\tshadowFac = shadow_map_occl;" << Endl;
+ }
+
+ if (specularEnabled) {
+ vertexShader.GenerateViewVector();
+ OutputSpecularAreaLighting(fragmentShader, "varWorldPos", "view_vector",
+ m_LightSpecularColor.c_str());
+ }
+
+ OutputDiffuseAreaLighting(fragmentShader, "varWorldPos", m_TempStr);
+ fragmentShader << "\tlightAttenuation *= shadowFac;" << Endl;
+
+ AddTranslucencyIrradiance(fragmentShader, translucencyImage, m_TempStr, true);
+
+ fragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ "diffuseReflectionBSDF( world_normal, "
+ << m_NormalizedDirection << ", view_vector, " << m_LightColor
+ << ".rgb, 0.0 ).rgb;" << Endl;
+ } else {
+
+ vertexShader.GenerateWorldPosition();
+ GenerateShadowMapOcclusion(lightIdx, enableShadowMaps && isShadow,
+ lightNode->m_LightType);
+
+ m_RelativeDirection = m_TempStr;
+ m_RelativeDirection.append("_relativeDirection");
+
+ m_NormalizedDirection = m_RelativeDirection;
+ m_NormalizedDirection.append("_normalized");
+
+ m_RelativeDistance = m_TempStr;
+ m_RelativeDistance.append("_distance");
+
+ fragmentShader << "\tvec3 " << m_RelativeDirection << " = varWorldPos - "
+ << m_LightPos << ".xyz;" << Endl;
+ fragmentShader << "\tfloat " << m_RelativeDistance << " = length( "
+ << m_RelativeDirection << " );" << Endl;
+ fragmentShader << "\tvec3 " << m_NormalizedDirection << " = "
+ << m_RelativeDirection << " / " << m_RelativeDistance << ";"
+ << Endl;
+
+ if (enableSSDO) {
+ fragmentShader << "\tshadowFac = shadow_map_occl * customMaterialShadow( "
+ << m_NormalizedDirection << ", varWorldPos );" << Endl;
+ } else {
+ fragmentShader << "\tshadowFac = shadow_map_occl;" << Endl;
+ }
+
+ addFunction(fragmentShader, "calculatePointLightAttenuation");
+
+ fragmentShader
+ << "\tlightAttenuation = shadowFac * calculatePointLightAttenuation( vec3( "
+ << m_LightConstantAttenuation << ", " << m_LightLinearAttenuation << ", "
+ << m_LightQuadraticAttenuation << "), " << m_RelativeDistance << ");"
+ << Endl;
+
+ AddTranslucencyIrradiance(fragmentShader, translucencyImage, m_TempStr, false);
+
+ fragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ "diffuseReflectionBSDF( world_normal, "
+ << "-" << m_NormalizedDirection << ", view_vector, "
+ << m_LightColor << ".rgb, 0.0 ).rgb;" << Endl;
+
+ if (specularEnabled) {
+ OutputSpecularEquation(Material().m_SpecularModel, fragmentShader,
+ m_NormalizedDirection.c_str(),
+ m_LightSpecularColor.c_str());
+ }
+ }
+ }
+
+ // This may be confusing but the light colors are already modulated by the base
+ // material color.
+ // Thus material color is the base material color * material emissive.
+ // Except material_color.a *is* the actual opacity factor.
+ // Furthermore object_opacity is something that may come from the vertex pipeline or
+ // somewhere else.
+ // We leave it up to the vertex pipeline to figure it out.
+ fragmentShader << "\tglobal_diffuse_light = vec4(global_diffuse_light.xyz * aoFactor, "
+ "object_opacity);"
+ << Endl << "\tglobal_specular_light = vec3(global_specular_light.xyz);"
+ << Endl;
+ } else // no lighting.
+ {
+ fragmentShader << "\tvec4 global_diffuse_light = vec4(0.0, 0.0, 0.0, object_opacity);"
+ << Endl << "\tvec3 global_specular_light = vec3(0.0, 0.0, 0.0);" << Endl;
+
+ // We still have specular maps and such that could potentially use the fresnel variable.
+ fragmentHasSpecularAmount =
+ MaybeAddMaterialFresnel(fragmentShader, inKey, fragmentHasSpecularAmount);
+ }
+
+ // Fresnel also modulates alpha.
+ if (m_DefaultMaterialShaderKeyProperties.m_FresnelEnabled.GetValue(inKey)) {
+ fragmentShader
+ << "\tglobal_diffuse_light.a = mix( global_diffuse_light.a, 1.0, fresnelRatio );"
+ << Endl;
+ }
+
+ if (!hasEmissiveMap)
+ fragmentShader
+ << "\tglobal_diffuse_light.rgb += diffuse_color.rgb * material_diffuse.rgb;"
+ << Endl;
+
+ // since we already modulate our material diffuse color
+ // into the light color we will miss it entirely if no IBL
+ // or light is used
+ if (hasLightmaps && !(m_Lights.size() || hasIblProbe))
+ fragmentShader << "\tglobal_diffuse_light.rgb *= diffuse_color.rgb;" << Endl;
+
+ if (hasLighting && hasIblProbe) {
+ vertexShader.GenerateWorldNormal();
+
+ fragmentShader << "\tglobal_diffuse_light.rgb += diffuse_color.rgb * aoFactor * "
+ "sampleDiffuse( tanFrame ).xyz;"
+ << Endl;
+
+ if (specularEnabled) {
+
+ fragmentShader.AddUniform("material_specular", "vec4");
+
+ fragmentShader << "\tglobal_specular_light.xyz += specularAmount * "
+ "vec3(material_specular.xyz) * sampleGlossy( tanFrame, "
+ "view_vector, material_properties.y ).xyz;"
+ << Endl;
+ }
+ }
+
+ if (hasImage) {
+ fragmentShader.Append("\tvec4 texture_color;");
+ AddLocalVariable(fragmentShader, "fresnelColor", "vec3");
+ QT3DSU32 idx = 0;
+ for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
+ // Various maps are handled on a different locations
+ if (image->m_MapType == ImageMapTypes::Bump
+ || image->m_MapType == ImageMapTypes::Normal
+ || image->m_MapType == ImageMapTypes::Displacement
+ || image->m_MapType == ImageMapTypes::SpecularAmountMap
+ || image->m_MapType == ImageMapTypes::Translucency
+ || image->m_MapType == ImageMapTypes::LightmapIndirect
+ || image->m_MapType == ImageMapTypes::LightmapRadiosity) {
+ continue;
+ }
+
+ eastl::basic_string<char8_t> texSwizzle, lookupSwizzle, texLodStr;
+
+ GenerateImageUVCoordinates(idx, *image, 0);
+
+ GenerateTextureSwizzle(
+ image->m_Image.m_TextureData.m_Texture->GetTextureSwizzleMode(), texSwizzle,
+ lookupSwizzle);
+
+ if (texLodStr.empty()) {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ")"
+ << lookupSwizzle.c_str() << ";" << Endl;
+ } else {
+ fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ << m_ImageSampler << ", " << m_ImageFragCoords << ", "
+ << texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
+ << Endl;
+ fragmentShader << "\ttexture_color.xyz *= fresnelColor;" << Endl;
+ }
+
+ if (image->m_Image.m_TextureData.m_TextureFlags.IsPreMultiplied() == true)
+ fragmentShader << "\ttexture_color.rgb = texture_color.a > 0.0 ? "
+ "texture_color.rgb / texture_color.a : vec3( 0, 0, 0 );"
+ << Endl;
+
+ // These mapping types honestly don't make a whole ton of sense to me.
+ switch (image->m_MapType) {
+ case ImageMapTypes::Diffuse: // assume images are premultiplied.
+ case ImageMapTypes::LightmapShadow:
+ // We use image offsets.z to switch between incoming premultiplied textures or
+ // not premultiplied textures.
+ // If Z is 1, then we assume the incoming texture is already premultiplied, else
+ // we just read the rgb value.
+ fragmentShader.Append("\tglobal_diffuse_light *= texture_color;");
+ break;
+ case ImageMapTypes::Specular:
+
+ fragmentShader.AddUniform("material_specular", "vec4");
+ if (fragmentHasSpecularAmount) {
+ fragmentShader.Append("\tglobal_specular_light.xyz += specularAmount * "
+ "texture_color.xyz * material_specular.xyz;");
+ } else {
+ fragmentShader.Append("\tglobal_specular_light.xyz += texture_color.xyz * "
+ "material_specular.xyz;");
+ }
+ fragmentShader.Append("\tglobal_diffuse_light.a *= texture_color.a;");
+ break;
+ case ImageMapTypes::Opacity:
+ fragmentShader.Append("\tglobal_diffuse_light.a *= texture_color.a;");
+ break;
+ case ImageMapTypes::Emissive:
+ fragmentShader.Append(
+ "\tglobal_emission *= texture_color.xyz * texture_color.a;");
+ break;
+ default:
+ QT3DS_ASSERT(false); // fallthrough intentional
+ }
+ }
+ }
+
+ if (hasEmissiveMap) {
+ fragmentShader.Append("\tglobal_diffuse_light.rgb += global_emission.rgb;");
+ }
+
+ // Ensure the rgb colors are in range.
+ fragmentShader.Append("\tfragOutput = vec4( clamp( global_diffuse_light.xyz + "
+ "global_specular_light.xyz, 0.0, 65519.0 ), global_diffuse_light.a "
+ ");");
+
+ if (VertexGenerator().HasActiveWireframe()) {
+ fragmentShader.Append("vec3 edgeDistance = varEdgeDistance * gl_FragCoord.w;");
+ fragmentShader.Append(
+ "\tfloat d = min(min(edgeDistance.x, edgeDistance.y), edgeDistance.z);");
+ fragmentShader.Append("\tfloat mixVal = smoothstep(0.0, 1.0, d);"); // line width 1.0
+
+ fragmentShader.Append(
+ "\tfragOutput = mix( vec4(0.0, 1.0, 0.0, 1.0), fragOutput, mixVal);");
+ }
+ }
+
+ NVRenderShaderProgram *GenerateMaterialShader(const char8_t *inShaderPrefix)
+ {
+ // build a string that allows us to print out the shader we are generating to the log.
+ // This is time consuming but I feel like it doesn't happen all that often and is very
+ // useful to users
+ // looking at the log file.
+ m_GeneratedShaderString.assign(nonNull(inShaderPrefix));
+ SShaderDefaultMaterialKey theKey(Key());
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+
+ GenerateVertexShader();
+ GenerateFragmentShader(theKey);
+
+ VertexGenerator().EndVertexGeneration();
+ VertexGenerator().EndFragmentGeneration();
+
+ return ProgramGenerator().CompileGeneratedShader(m_GeneratedShaderString.c_str(),
+ SShaderCacheProgramFlags(), FeatureSet());
+ }
+
+ virtual NVRenderShaderProgram *
+ GenerateShader(const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription,
+ IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet,
+ NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage,
+ bool inHasTransparency, const char8_t *inVertexPipelineName, const char8_t *) override
+ {
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial);
+ m_CurrentMaterial = static_cast<const SDefaultMaterial *>(&inMaterial);
+ m_CurrentKey = &inShaderDescription;
+ m_CurrentPipeline = static_cast<IDefaultMaterialVertexPipeline *>(&inVertexPipeline);
+ m_CurrentFeatureSet = inFeatureSet;
+ m_Lights = inLights;
+ m_FirstImage = inFirstImage;
+ m_HasTransparency = inHasTransparency;
+
+ return GenerateMaterialShader(inVertexPipelineName);
+ }
+
+ SShaderGeneratorGeneratedShader &GetShaderForProgram(NVRenderShaderProgram &inProgram)
+ {
+ eastl::pair<TProgramToShaderMap::iterator, bool> inserter =
+ m_ProgramToShaderMap.insert(eastl::make_pair(
+ &inProgram, NVScopedRefCounted<SShaderGeneratorGeneratedShader>(NULL)));
+ if (inserter.second) {
+ NVAllocatorCallback &alloc(m_RenderContext.GetRenderContext().GetAllocator());
+ inserter.first->second = QT3DS_NEW(alloc, SShaderGeneratorGeneratedShader)(
+ inProgram, m_RenderContext.GetRenderContext());
+ }
+ return *inserter.first->second;
+ }
+
+ void SetGlobalProperties(NVRenderShaderProgram &inProgram, const SLayer & /*inLayer*/
+ ,
+ SCamera &inCamera, QT3DSVec3 inCameraDirection,
+ NVDataRef<SLight *> inLights, NVDataRef<QT3DSVec3> inLightDirections,
+ UICShadowMap *inShadowMapManager)
+ {
+ SShaderGeneratorGeneratedShader &shader(GetShaderForProgram(inProgram));
+ m_RenderContext.GetRenderContext().SetActiveShader(&inProgram);
+
+ m_ShadowMapManager = inShadowMapManager;
+
+ SCamera &theCamera(inCamera);
+ shader.m_CameraPosition.Set(theCamera.GetGlobalPos());
+ shader.m_CameraDirection.Set(inCameraDirection);
+
+ QT3DSMat44 viewProj;
+ if (shader.m_ViewProj.IsValid()) {
+ theCamera.CalculateViewProjectionMatrix(viewProj);
+ shader.m_ViewProj.Set(viewProj);
+ }
+
+ if (shader.m_ViewMatrix.IsValid()) {
+ viewProj = theCamera.m_GlobalTransform.getInverse();
+ shader.m_ViewMatrix.Set(viewProj);
+ }
+
+ // update the constant buffer
+ shader.m_AoShadowParams.Set();
+ // We can't cache light properties because they can change per object.
+ QT3DSVec3 theLightAmbientTotal = QT3DSVec3(0, 0, 0);
+ size_t numShaderLights = shader.m_Lights.size();
+ size_t numShadowLights = shader.m_ShadowMaps.size();
+ for (QT3DSU32 lightIdx = 0, shadowMapIdx = 0, lightEnd = inLights.size();
+ lightIdx < lightEnd && lightIdx < UIC_MAX_NUM_LIGHTS; ++lightIdx) {
+ SLight *theLight(inLights[lightIdx]);
+ if (lightIdx >= numShaderLights) {
+ shader.m_Lights.push_back(SShaderLightProperties());
+ ++numShaderLights;
+ }
+ if (shadowMapIdx >= numShadowLights && numShadowLights < UIC_MAX_NUM_SHADOWS) {
+ if (theLight->m_Scope == NULL && theLight->m_CastShadow) {
+ // PKC TODO : Fix multiple shadow issues.
+ // Need to know when the list of lights changes order, and clear shadow maps
+ // when that happens.
+ SetupShadowMapVariableNames(lightIdx);
+ shader.m_ShadowMaps.push_back(SShadowMapProperties(
+ m_ShadowMapStem.c_str(), m_ShadowCubeStem.c_str(),
+ m_ShadowMatrixStem.c_str(), m_ShadowControlStem.c_str(), inProgram));
+ }
+ }
+ QT3DS_ASSERT(lightIdx < numShaderLights);
+ SShaderLightProperties &theLightProperties(shader.m_Lights[lightIdx]);
+ float brightness = TranslateConstantAttenuation(theLight->m_Brightness);
+
+ // setup light data
+ theLightProperties.m_LightColor = theLight->m_DiffuseColor * brightness;
+ theLightProperties.m_LightData.m_specular =
+ QT3DSVec4(theLight->m_SpecularColor * brightness, 1.0);
+ theLightProperties.m_LightData.m_direction = QT3DSVec4(inLightDirections[lightIdx], 1.0);
+
+ // TODO : This does potentially mean that we can create more shadow map entries than
+ // we can actually use at once.
+ if ((theLight->m_Scope == NULL) && (theLight->m_CastShadow && inShadowMapManager)) {
+ SShadowMapProperties &theShadowMapProperties(shader.m_ShadowMaps[shadowMapIdx++]);
+ SShadowMapEntry *pEntry = inShadowMapManager->GetShadowMapEntry(lightIdx);
+ if (pEntry) {
+ // add fixed scale bias matrix
+ QT3DSMat44 bias(QT3DSVec4(0.5, 0.0, 0.0, 0.0), QT3DSVec4(0.0, 0.5, 0.0, 0.0),
+ QT3DSVec4(0.0, 0.0, 0.5, 0.0), QT3DSVec4(0.5, 0.5, 0.5, 1.0));
+
+ if (theLight->m_LightType != RenderLightTypes::Directional) {
+ theShadowMapProperties.m_ShadowCubeTexture.Set(pEntry->m_DepthCube);
+ theShadowMapProperties.m_ShadowmapMatrix.Set(pEntry->m_LightView);
+ } else {
+ theShadowMapProperties.m_ShadowmapTexture.Set(pEntry->m_DepthMap);
+ theShadowMapProperties.m_ShadowmapMatrix.Set(bias * pEntry->m_LightVP);
+ }
+
+ theShadowMapProperties.m_ShadowmapSettings.Set(
+ QT3DSVec4(theLight->m_ShadowBias, theLight->m_ShadowFactor,
+ theLight->m_ShadowMapFar, 0.0f));
+ } else {
+ // if we have a light casting shadow we should find an entry
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ if (theLight->m_LightType == RenderLightTypes::Point) {
+ theLightProperties.m_LightData.m_position = QT3DSVec4(theLight->GetGlobalPos(), 1.0);
+ theLightProperties.m_LightData.m_constantAttenuation = 1.0;
+ theLightProperties.m_LightData.m_linearAttenuation =
+ TranslateLinearAttenuation(theLight->m_LinearFade);
+ theLightProperties.m_LightData.m_quadraticAttenuation =
+ TranslateQuadraticAttenuation(theLight->m_ExponentialFade);
+ } else if (theLight->m_LightType == RenderLightTypes::Area) {
+ theLightProperties.m_LightData.m_position = QT3DSVec4(theLight->GetGlobalPos(), 1.0);
+
+ QT3DSVec3 upDir = theLight->m_GlobalTransform.getUpper3x3().transform(QT3DSVec3(0, 1, 0));
+ QT3DSVec3 rtDir = theLight->m_GlobalTransform.getUpper3x3().transform(QT3DSVec3(1, 0, 0));
+
+ theLightProperties.m_LightData.m_up = QT3DSVec4(upDir, theLight->m_AreaHeight);
+ theLightProperties.m_LightData.m_right = QT3DSVec4(rtDir, theLight->m_AreaWidth);
+ }
+ theLightAmbientTotal += theLight->m_AmbientColor;
+ }
+ shader.m_LightAmbientTotal = theLightAmbientTotal;
+ }
+
+ // Also sets the blend function on the render context.
+ void SetMaterialProperties(NVRenderShaderProgram &inProgram, const SDefaultMaterial &inMaterial,
+ const QT3DSVec2 &inCameraVec, const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix, const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ NVRenderTexture2D *inDepthTexture, NVRenderTexture2D *inSSaoTexture,
+ SImage *inLightProbe, SImage *inLightProbe2, QT3DSF32 inProbeHorizon,
+ QT3DSF32 inProbeBright, QT3DSF32 inProbe2Window, QT3DSF32 inProbe2Pos,
+ QT3DSF32 inProbe2Fade, QT3DSF32 inProbeFOV)
+ {
+
+ NVRenderContext &context(m_RenderContext.GetRenderContext());
+ SShaderGeneratorGeneratedShader &shader(GetShaderForProgram(inProgram));
+ shader.m_MVP.Set(inModelViewProjection);
+ shader.m_NormalMatrix.Set(inNormalMatrix);
+ shader.m_GlobalTransform.Set(inGlobalTransform);
+ shader.m_DepthTexture.Set(inDepthTexture);
+
+ shader.m_AOTexture.Set(inSSaoTexture);
+
+ uic::render::SImage *theLightProbe = inLightProbe;
+ uic::render::SImage *theLightProbe2 = inLightProbe2;
+
+ // If the material has its own IBL Override, we should use that image instead.
+ if ((inMaterial.m_IblProbe) && (inMaterial.m_IblProbe->m_TextureData.m_Texture)) {
+ theLightProbe = inMaterial.m_IblProbe;
+ }
+
+ if (theLightProbe) {
+ if (theLightProbe->m_TextureData.m_Texture) {
+ NVRenderTextureCoordOp::Enum theHorzLightProbeTilingMode =
+ NVRenderTextureCoordOp::Repeat;
+ NVRenderTextureCoordOp::Enum theVertLightProbeTilingMode =
+ theLightProbe->m_VerticalTilingMode;
+ theLightProbe->m_TextureData.m_Texture->SetTextureWrapS(
+ theHorzLightProbeTilingMode);
+ theLightProbe->m_TextureData.m_Texture->SetTextureWrapT(
+ theVertLightProbeTilingMode);
+ const QT3DSMat44 &textureTransform = theLightProbe->m_TextureTransform;
+ // We separate rotational information from offset information so that just maybe the
+ // shader
+ // will attempt to push less information to the card.
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ // The third member of the offsets contains a flag indicating if the texture was
+ // premultiplied or not.
+ // We use this to mix the texture alpha.
+ QT3DSVec4 offsets(dataPtr[12], dataPtr[13],
+ theLightProbe->m_TextureData.m_TextureFlags.IsPreMultiplied() ? 1.0f
+ : 0.0f,
+ (float)theLightProbe->m_TextureData.m_Texture->GetNumMipmaps());
+
+ // Grab just the upper 2x2 rotation matrix from the larger matrix.
+ QT3DSVec4 rotations(dataPtr[0], dataPtr[4], dataPtr[1], dataPtr[5]);
+
+ shader.m_LightProbeRot.Set(rotations);
+ shader.m_LightProbeOfs.Set(offsets);
+
+ if ((!inMaterial.m_IblProbe) && (inProbeFOV < 180.f)) {
+ shader.m_LightProbeOpts.Set(
+ QT3DSVec4(0.01745329251994329547f * inProbeFOV, 0.0f, 0.0f, 0.0f));
+ }
+
+ // Also make sure to add the secondary texture, but it should only be added if the
+ // primary
+ // (i.e. background) texture is also there.
+ if (theLightProbe2 && theLightProbe2->m_TextureData.m_Texture) {
+ theLightProbe2->m_TextureData.m_Texture->SetTextureWrapS(
+ theHorzLightProbeTilingMode);
+ theLightProbe2->m_TextureData.m_Texture->SetTextureWrapT(
+ theVertLightProbeTilingMode);
+ shader.m_LightProbe2.Set(theLightProbe2->m_TextureData.m_Texture);
+ shader.m_LightProbe2Props.Set(
+ QT3DSVec4(inProbe2Window, inProbe2Pos, inProbe2Fade, 1.0f));
+
+ const QT3DSMat44 &xform2 = theLightProbe2->m_TextureTransform;
+ const QT3DSF32 *dataPtr(xform2.front());
+ shader.m_LightProbeProps.Set(
+ QT3DSVec4(dataPtr[12], dataPtr[13], inProbeHorizon, inProbeBright * 0.01f));
+ } else {
+ shader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ shader.m_LightProbeProps.Set(
+ QT3DSVec4(0.0f, 0.0f, inProbeHorizon, inProbeBright * 0.01f));
+ }
+ } else {
+ shader.m_LightProbeProps.Set(QT3DSVec4(0.0f, 0.0f, -1.0f, 0.0f));
+ shader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ }
+ shader.m_LightProbe.Set(theLightProbe->m_TextureData.m_Texture);
+ } else {
+ shader.m_LightProbeProps.Set(QT3DSVec4(0.0f, 0.0f, -1.0f, 0.0f));
+ shader.m_LightProbe2Props.Set(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ }
+
+ NVRenderConstantBuffer *pLightCb = GetLightConstantBuffer(shader.m_Lights.size());
+ // if we have lights we need a light buffer
+ QT3DS_ASSERT(shader.m_Lights.size() == 0 || pLightCb);
+
+ QT3DSF32 emissivePower = 1.0;
+
+ QT3DSU32 hasLighting = inMaterial.m_Lighting != DefaultMaterialLighting::NoLighting;
+ if (hasLighting)
+ emissivePower = inMaterial.m_EmissivePower / 100.0f;
+
+ QT3DSVec4 material_diffuse = QT3DSVec4(inMaterial.m_EmissiveColor[0] * emissivePower,
+ inMaterial.m_EmissiveColor[1] * emissivePower,
+ inMaterial.m_EmissiveColor[2] * emissivePower, inOpacity);
+ shader.m_MaterialDiffuse.Set(material_diffuse);
+ shader.m_DiffuseColor.Set(inMaterial.m_DiffuseColor);
+ QT3DSVec4 material_specular =
+ QT3DSVec4(inMaterial.m_SpecularTint[0], inMaterial.m_SpecularTint[1],
+ inMaterial.m_SpecularTint[2], inMaterial.m_IOR);
+ shader.m_MaterialSpecular.Set(material_specular);
+ shader.m_CameraProperties.Set(inCameraVec);
+ shader.m_FresnelPower.Set(inMaterial.m_FresnelPower);
+ for (QT3DSU32 idx = 0, end = shader.m_Lights.size(); idx < end && pLightCb; ++idx) {
+ shader.m_Lights[idx].m_LightData.m_diffuse =
+ QT3DSVec4(shader.m_Lights[idx].m_LightColor.x * inMaterial.m_DiffuseColor.x,
+ shader.m_Lights[idx].m_LightColor.y * inMaterial.m_DiffuseColor.y,
+ shader.m_Lights[idx].m_LightColor.z * inMaterial.m_DiffuseColor.z, 1.0);
+
+ // this is our final change update memory
+ pLightCb->UpdateRaw(idx * sizeof(SLightSourceShader) + (4 * sizeof(QT3DSI32)),
+ NVDataRef<QT3DSU8>((QT3DSU8 *)&shader.m_Lights[idx].m_LightData,
+ sizeof(SLightSourceShader)));
+ }
+ // update light buffer to hardware
+ if (pLightCb) {
+ QT3DSI32 cgLights = shader.m_Lights.size();
+ pLightCb->UpdateRaw(0, NVDataRef<QT3DSU8>((QT3DSU8 *)&cgLights, sizeof(QT3DSI32)));
+ shader.m_LightsBuffer.Set();
+ }
+
+ shader.m_MaterialDiffuseLightAmbientTotal.Set(
+ QT3DSVec3(shader.m_LightAmbientTotal.x * inMaterial.m_DiffuseColor[0],
+ shader.m_LightAmbientTotal.y * inMaterial.m_DiffuseColor[1],
+ shader.m_LightAmbientTotal.z * inMaterial.m_DiffuseColor[2]));
+
+ shader.m_MaterialProperties.Set(QT3DSVec4(
+ inMaterial.m_SpecularAmount, inMaterial.m_SpecularRoughness, emissivePower, 0.0f));
+ shader.m_BumpAmount.Set(inMaterial.m_BumpAmount);
+ shader.m_DisplaceAmount.Set(inMaterial.m_DisplaceAmount);
+ shader.m_TranslucentFalloff.Set(inMaterial.m_TranslucentFalloff);
+ shader.m_DiffuseLightWrap.Set(inMaterial.m_DiffuseLightWrap);
+ QT3DSU32 imageIdx = 0;
+ for (SRenderableImage *theImage = inFirstImage; theImage;
+ theImage = theImage->m_NextImage, ++imageIdx)
+ SetImageShaderVariables(shader, *theImage, imageIdx);
+
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc;
+ qt3ds::render::NVRenderBlendEquationArgument blendEqua;
+ // The blend function goes:
+ // src op
+ // dst op
+ // src alpha op
+ // dst alpha op
+ // All of our shaders produce non-premultiplied values.
+ switch (inMaterial.m_BlendMode) {
+ case DefaultMaterialBlendMode::Screen:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::SrcAlpha, NVRenderDstBlendFunc::One,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ blendEqua = qt3ds::render::NVRenderBlendEquationArgument(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+ break;
+ case DefaultMaterialBlendMode::Multiply:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::DstColor, NVRenderDstBlendFunc::Zero,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One);
+ blendEqua = qt3ds::render::NVRenderBlendEquationArgument(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+ break;
+ case DefaultMaterialBlendMode::Overlay:
+ // SW fallback is not using blend equation
+ // note blend func is not used here anymore
+ if (context.IsAdvancedBlendHwSupported() || context.IsAdvancedBlendHwSupportedKHR())
+ blendEqua = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Overlay, NVRenderBlendEquation::Overlay);
+ break;
+ case DefaultMaterialBlendMode::ColorBurn:
+ // SW fallback is not using blend equation
+ // note blend func is not used here anymore
+ if (context.IsAdvancedBlendHwSupported() || context.IsAdvancedBlendHwSupportedKHR())
+ blendEqua = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::ColorBurn, NVRenderBlendEquation::ColorBurn);
+ break;
+ case DefaultMaterialBlendMode::ColorDodge:
+ // SW fallback is not using blend equation
+ // note blend func is not used here anymore
+ if (context.IsAdvancedBlendHwSupported() || context.IsAdvancedBlendHwSupportedKHR())
+ blendEqua = qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::ColorDodge, NVRenderBlendEquation::ColorDodge);
+ break;
+ default:
+ blendFunc = qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::SrcAlpha, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha);
+ break;
+ }
+ context.SetBlendFunction(blendFunc);
+ context.SetBlendEquation(blendEqua);
+ }
+ void SetMaterialProperties(NVRenderShaderProgram &inProgram,
+ const SGraphObject &inMaterial, const QT3DSVec2 &inCameraVec,
+ const QT3DSMat44 &inModelViewProjection,
+ const QT3DSMat33 &inNormalMatrix,
+ const QT3DSMat44 &inGlobalTransform,
+ SRenderableImage *inFirstImage, QT3DSF32 inOpacity,
+ SLayerGlobalRenderProperties inRenderProperties) override
+ {
+ const SDefaultMaterial &theMaterial(static_cast<const SDefaultMaterial &>(inMaterial));
+ QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial);
+
+ SetGlobalProperties(inProgram, inRenderProperties.m_Layer, inRenderProperties.m_Camera,
+ inRenderProperties.m_CameraDirection, inRenderProperties.m_Lights,
+ inRenderProperties.m_LightDirections,
+ inRenderProperties.m_ShadowMapManager);
+ SetMaterialProperties(inProgram, theMaterial, inCameraVec, inModelViewProjection,
+ inNormalMatrix, inGlobalTransform, inFirstImage, inOpacity,
+ inRenderProperties.m_DepthTexture, inRenderProperties.m_SSaoTexture,
+ inRenderProperties.m_LightProbe, inRenderProperties.m_LightProbe2,
+ inRenderProperties.m_ProbeHorizon, inRenderProperties.m_ProbeBright,
+ inRenderProperties.m_Probe2Window, inRenderProperties.m_Probe2Pos,
+ inRenderProperties.m_Probe2Fade, inRenderProperties.m_ProbeFOV);
+ }
+};
+}
+
+IDefaultMaterialShaderGenerator &
+IDefaultMaterialShaderGenerator::CreateDefaultMaterialShaderGenerator(IUICRenderContext &inRc)
+{
+ return *QT3DS_NEW(inRc.GetAllocator(), SShaderGenerator)(inRc);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderDynamicObjectSystem.cpp b/src/Runtime/Source/UICRender/Source/UICRenderDynamicObjectSystem.cpp
new file mode 100644
index 00000000..ff4d7597
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderDynamicObjectSystem.cpp
@@ -0,0 +1,1560 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderDynamicObjectSystem.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderContext.h"
+#include "render/Qt3DSRenderShaderConstant.h"
+#include "UICRenderDynamicObject.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/FileTools.h"
+#include "foundation/PreAllocatedAllocator.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderString.h"
+#include "UICRenderShaderCache.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICRenderer.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "UICRenderDynamicObjectSystemUtil.h"
+#include "UICRenderShaderCodeGenerator.h"
+#include "foundation/Qt3DSMutex.h"
+
+using namespace uic;
+using namespace uic::render;
+using namespace uic::render::dynamic;
+
+// QT3DS_COMPILE_TIME_ASSERT( sizeof(void*) == 4 );
+
+namespace {
+typedef eastl::pair<CRegisteredString, CRegisteredString> TStrStrPair;
+}
+
+namespace eastl {
+template <>
+struct hash<TStrStrPair>
+{
+ size_t operator()(const TStrStrPair &item) const
+ {
+ return hash<CRegisteredString>()(item.first) ^ hash<CRegisteredString>()(item.second);
+ }
+};
+}
+
+namespace uic {
+namespace render {
+ namespace dynamic {
+
+ QT3DSU32 SCommand::GetSizeofCommand(const SCommand &inCommand)
+ {
+ switch (inCommand.m_Type) {
+ case CommandTypes::AllocateBuffer:
+ return sizeof(SAllocateBuffer);
+ case CommandTypes::BindBuffer:
+ return sizeof(SBindBuffer);
+ case CommandTypes::BindTarget:
+ return sizeof(SBindTarget);
+ case CommandTypes::BindShader:
+ return sizeof(SBindShader);
+ case CommandTypes::Render:
+ return sizeof(SRender);
+ case CommandTypes::ApplyBufferValue:
+ return sizeof(SApplyBufferValue);
+ case CommandTypes::ApplyDepthValue:
+ return sizeof(SApplyDepthValue);
+ case CommandTypes::ApplyInstanceValue:
+ return sizeof(SApplyInstanceValue);
+ case CommandTypes::ApplyBlending:
+ return sizeof(SApplyBlending);
+ case CommandTypes::ApplyRenderState:
+ return sizeof(SApplyRenderState);
+ case CommandTypes::ApplyBlitFramebuffer:
+ return sizeof(SApplyBlitFramebuffer);
+ case CommandTypes::ApplyValue:
+ return sizeof(SApplyValue)
+ + static_cast<const SApplyValue &>(inCommand).m_Value.mSize;
+ case CommandTypes::DepthStencil:
+ return sizeof(SDepthStencil);
+ case CommandTypes::LuaCommand:
+ return sizeof(SLuaCommand);
+ case CommandTypes::AllocateImage:
+ return sizeof(SAllocateImage);
+ case CommandTypes::ApplyImageValue:
+ return sizeof(SApplyImageValue);
+ case CommandTypes::AllocateDataBuffer:
+ return sizeof(SAllocateDataBuffer);
+ case CommandTypes::ApplyDataBufferValue:
+ return sizeof(SApplyDataBufferValue);
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ template <typename TCommandType>
+ inline void CopyConstructCommandT(QT3DSU8 *inDataBuffer, const SCommand &inCommand,
+ IStringTable &inStrTable)
+ {
+ TCommandType *theCommand = (TCommandType *)inDataBuffer;
+ theCommand = new (theCommand)
+ TCommandType(static_cast<const TCommandType &>(inCommand), inStrTable);
+ }
+
+ void SCommand::CopyConstructCommand(QT3DSU8 *inDataBuffer, const SCommand &inCommand,
+ IStringTable &inStrTable)
+ {
+ switch (inCommand.m_Type) {
+ case CommandTypes::AllocateBuffer:
+ CopyConstructCommandT<SAllocateBuffer>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::BindBuffer:
+ CopyConstructCommandT<SBindBuffer>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::BindTarget:
+ CopyConstructCommandT<SBindTarget>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::BindShader:
+ CopyConstructCommandT<SBindShader>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::Render:
+ CopyConstructCommandT<SRender>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyBufferValue:
+ CopyConstructCommandT<SApplyBufferValue>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyDepthValue:
+ CopyConstructCommandT<SApplyDepthValue>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyInstanceValue:
+ CopyConstructCommandT<SApplyInstanceValue>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyBlending:
+ CopyConstructCommandT<SApplyBlending>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyRenderState:
+ CopyConstructCommandT<SApplyRenderState>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyBlitFramebuffer:
+ CopyConstructCommandT<SApplyBlitFramebuffer>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyValue: {
+ CopyConstructCommandT<SApplyValue>(inDataBuffer, inCommand, inStrTable);
+ SApplyValue &dest = *reinterpret_cast<SApplyValue *>(inDataBuffer);
+ QT3DSU8 *destMem = inDataBuffer + sizeof(SApplyValue);
+ const SApplyValue &src = static_cast<const SApplyValue &>(inCommand);
+ memcpy(destMem, src.m_Value.mData, src.m_Value.mSize);
+ dest.m_Value.mData = destMem;
+ break;
+ }
+ case CommandTypes::DepthStencil:
+ CopyConstructCommandT<SDepthStencil>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::LuaCommand:
+ CopyConstructCommandT<SLuaCommand>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::AllocateImage:
+ CopyConstructCommandT<SAllocateImage>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyImageValue:
+ CopyConstructCommandT<SApplyImageValue>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::AllocateDataBuffer:
+ CopyConstructCommandT<SAllocateDataBuffer>(inDataBuffer, inCommand, inStrTable);
+ break;
+ case CommandTypes::ApplyDataBufferValue:
+ CopyConstructCommandT<SApplyDataBufferValue>(inDataBuffer, inCommand, inStrTable);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+}
+}
+
+namespace {
+
+template <typename TCommandType>
+struct SCommandRemapping
+{
+ template <typename TRemapper>
+ static void RemapCommandData(TCommandType &, TRemapper &)
+ {
+ }
+};
+
+template <>
+struct SCommandRemapping<SAllocateBuffer>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SAllocateBuffer &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_Name);
+ }
+};
+
+template <>
+struct SCommandRemapping<SAllocateImage>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SAllocateImage &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_Name);
+ }
+};
+
+template <>
+struct SCommandRemapping<SAllocateDataBuffer>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SAllocateDataBuffer &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_Name);
+ if (cmd.m_WrapName)
+ remapper.Remap(cmd.m_WrapName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SBindBuffer>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SBindBuffer &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_BufferName);
+ }
+};
+template <>
+struct SCommandRemapping<SBindShader>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SBindShader &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_ShaderPath);
+ remapper.Remap(cmd.m_ShaderDefine);
+ }
+};
+template <>
+struct SCommandRemapping<SApplyInstanceValue>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SApplyInstanceValue &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_PropertyName);
+ }
+};
+template <>
+struct SCommandRemapping<SApplyBufferValue>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SApplyBufferValue &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_BufferName);
+ remapper.Remap(cmd.m_ParamName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SApplyDepthValue>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SApplyDepthValue &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_ParamName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SApplyBlitFramebuffer>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SApplyBlitFramebuffer &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_SourceBufferName);
+ remapper.Remap(cmd.m_DestBufferName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SApplyValue>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SApplyValue &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_PropertyName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SApplyDataBufferValue>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SApplyDataBufferValue &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_ParamName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SDepthStencil>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SDepthStencil &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_BufferName);
+ }
+};
+
+template <>
+struct SCommandRemapping<SLuaCommand>
+{
+ template <typename TRemapper>
+ static void RemapCommandData(SLuaCommand &cmd, TRemapper &remapper)
+ {
+ remapper.Remap(cmd.m_LuaScript);
+ }
+};
+
+QT3DSU32 Align(QT3DSU32 inValue)
+{
+ if (inValue % 4)
+ return inValue + (4 - (inValue % 4));
+ return inValue;
+}
+
+QT3DSU32 Align8(QT3DSU32 inValue)
+{
+ if (inValue % 8)
+ return inValue + (8 - (inValue % 8));
+ return inValue;
+}
+
+inline const char *GetShaderDatatypeName(NVRenderShaderDataTypes::Enum inValue)
+{
+ switch (inValue) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(type) \
+ case NVRenderShaderDataTypes::type: \
+ return #type;
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return "";
+}
+
+inline qt3ds::QT3DSU32 getSizeofShaderDataType(NVRenderShaderDataTypes::Enum value)
+{
+ using namespace qt3ds;
+ using namespace qt3ds::render;
+ switch (value) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(x) \
+ case NVRenderShaderDataTypes::x: \
+ return sizeof(x);
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+}
+
+struct SDynamicObjectShaderInfo
+{
+ CRegisteredString m_Type; ///< shader type (GLSL or HLSL)
+ CRegisteredString m_Version; ///< shader version (e.g. 330 vor GLSL)
+ bool m_HasGeomShader;
+ bool m_IsComputeShader;
+
+ SDynamicObjectShaderInfo()
+ : m_HasGeomShader(false)
+ , m_IsComputeShader(false)
+ {
+ }
+ SDynamicObjectShaderInfo(CRegisteredString inType, CRegisteredString inVersion,
+ bool inHasGeomShader, bool inIsComputeShader)
+ : m_Type(inType)
+ , m_Version(inVersion)
+ , m_HasGeomShader(inHasGeomShader)
+ , m_IsComputeShader(inIsComputeShader)
+ {
+ }
+};
+
+struct SDynamicObjClassImpl : public IDynamicObjectClass
+{
+ NVAllocatorCallback *m_Allocator;
+ CRegisteredString m_Id;
+ NVConstDataRef<SPropertyDefinition> m_PropertyDefinitions;
+ QT3DSU32 m_PropertySectionByteSize;
+ QT3DSU32 m_BaseObjectSize;
+ GraphObjectTypes::Enum m_GraphObjectType;
+ QT3DSU8 *m_PropertyDefaultData;
+ NVConstDataRef<SCommand *> m_RenderCommands;
+ volatile QT3DSI32 mRefCount;
+ bool m_RequiresDepthTexture;
+ bool m_RequiresCompilation;
+ NVRenderTextureFormats::Enum m_OutputFormat;
+
+ SDynamicObjClassImpl(
+ NVAllocatorCallback &alloc, CRegisteredString id,
+ NVConstDataRef<SPropertyDefinition> definitions, QT3DSU32 propertySectionByteSize,
+ QT3DSU32 baseObjectSize, GraphObjectTypes::Enum objectType, QT3DSU8 *propDefaultData,
+ bool inRequiresDepthTexture = false,
+ NVRenderTextureFormats::Enum inOutputFormat = NVRenderTextureFormats::RGBA8)
+ : m_Allocator(&alloc)
+ , m_Id(id)
+ , m_PropertyDefinitions(definitions)
+ , m_PropertySectionByteSize(propertySectionByteSize)
+ , m_BaseObjectSize(baseObjectSize)
+ , m_GraphObjectType(objectType)
+ , m_PropertyDefaultData(propDefaultData)
+ , mRefCount(0)
+ , m_RequiresDepthTexture(inRequiresDepthTexture)
+ , m_RequiresCompilation(false)
+ , m_OutputFormat(inOutputFormat)
+ {
+ }
+
+ ~SDynamicObjClassImpl()
+ {
+ if (m_PropertyDefinitions.size()) {
+ for (QT3DSU32 idx = 0, end = m_PropertyDefinitions.size(); idx < end; ++idx) {
+ if (m_PropertyDefinitions[idx].m_EnumValueNames.size())
+ m_Allocator->deallocate(
+ (void *)m_PropertyDefinitions[idx].m_EnumValueNames.begin());
+ }
+ }
+ ReleaseCommands();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(*m_Allocator)
+
+ template <typename TRemapperType>
+ static void RemapCommand(SCommand &inCommand, TRemapperType &inRemapper)
+ {
+ switch (inCommand.m_Type) {
+#define UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(type) \
+ case CommandTypes::type: \
+ SCommandRemapping<S##type>::RemapCommandData(static_cast<S##type &>(inCommand), \
+ inRemapper); \
+ break;
+ UIC_RENDER_EFFECTS_ITERATE_COMMAND_TYPES
+#undef UIC_RENDER_EFFECTS_HANDLE_COMMAND_TYPES
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ template <typename TRemapper>
+ void SetupThisObjectFromMemory(NVAllocatorCallback &inAlloc, TRemapper &inRemapper,
+ QT3DSU8 *inCommandStart, QT3DSU32 numEffectCommands)
+ {
+ m_Allocator = &inAlloc;
+ mRefCount = 0;
+ QT3DSU8 *theCommandPtrBegin = inCommandStart;
+ QT3DSU32 theCommandOffset = 0;
+ for (QT3DSU32 idx = 0; idx < numEffectCommands; ++idx) {
+ SCommand *theCommand = reinterpret_cast<SCommand *>(inCommandStart + theCommandOffset);
+ theCommandOffset += SCommand::GetSizeofCommand(*theCommand);
+ }
+ SCommand **theCommandPtrStart =
+ reinterpret_cast<SCommand **>(theCommandPtrBegin + theCommandOffset);
+ m_RenderCommands = NVConstDataRef<SCommand *>(theCommandPtrStart, numEffectCommands);
+ // Now run through the commands, fixup strings and setup the command ptrs
+ theCommandOffset = 0;
+ for (QT3DSU32 idx = 0; idx < numEffectCommands; ++idx) {
+ SCommand *theCommand =
+ reinterpret_cast<SCommand *>(theCommandPtrBegin + theCommandOffset);
+ theCommandPtrStart[idx] = theCommand;
+ RemapCommand(*theCommand, inRemapper);
+ theCommandOffset += SCommand::GetSizeofCommand(*theCommand);
+ }
+ }
+
+ void ReleaseCommands()
+ {
+ if (m_RenderCommands.size()) {
+ m_Allocator->deallocate(const_cast<SCommand *>(*m_RenderCommands.begin()));
+ m_RenderCommands = NVConstDataRef<SCommand *>();
+ }
+ }
+
+ CRegisteredString GetId() const override { return m_Id; }
+ NVConstDataRef<SPropertyDefinition> GetProperties() const override
+ {
+ return m_PropertyDefinitions;
+ }
+ QT3DSU32 GetPropertySectionByteSize() const override { return m_PropertySectionByteSize; }
+ const QT3DSU8 *GetDefaultValueBuffer() const override { return m_PropertyDefaultData; }
+ QT3DSU32 GetBaseObjectSize() const override { return m_BaseObjectSize; }
+ GraphObjectTypes::Enum GraphObjectType() const override { return m_GraphObjectType; }
+ const SPropertyDefinition *FindDefinition(CRegisteredString &str) const
+ {
+ for (QT3DSU32 idx = 0, end = m_PropertyDefinitions.size(); idx < end; ++idx) {
+ const SPropertyDefinition &def(m_PropertyDefinitions[idx]);
+ if (def.m_Name == str)
+ return &def;
+ }
+ return NULL;
+ }
+ const SPropertyDefinition *FindPropertyByName(CRegisteredString inName) const override
+ {
+ return FindDefinition(inName);
+ }
+ NVConstDataRef<dynamic::SCommand *> GetRenderCommands() const override
+ {
+ return m_RenderCommands;
+ }
+ bool RequiresDepthTexture() const override { return m_RequiresDepthTexture; }
+ void SetRequiresDepthTexture(bool inVal) override { m_RequiresDepthTexture = inVal; }
+ virtual bool RequiresCompilation() const override { return m_RequiresCompilation; }
+ virtual void SetRequiresCompilation(bool inVal) override { m_RequiresCompilation = inVal; }
+ NVRenderTextureFormats::Enum GetOutputTextureFormat() const override { return m_OutputFormat; }
+};
+
+struct SDataRemapper
+{
+ template <typename TRemapper>
+ void Remap(QT3DSU8 *inData, SPropertyDefinition &item, TRemapper &remapper)
+ {
+ switch (item.m_DataType) {
+ default:
+ break; // no remapping necessary
+ case NVRenderShaderDataTypes::NVRenderTexture2DPtr:
+ CRegisteredString *realData = reinterpret_cast<CRegisteredString *>(inData);
+ remapper.Remap(*realData);
+ break;
+ }
+ }
+};
+
+struct SShaderMapKey
+{
+ TStrStrPair m_Name;
+ eastl::vector<SShaderPreprocessorFeature> m_Features;
+ TessModeValues::Enum m_TessMode;
+ bool m_WireframeMode;
+ size_t m_HashCode;
+ SShaderMapKey(TStrStrPair inName, TShaderFeatureSet inFeatures, TessModeValues::Enum inTessMode,
+ bool inWireframeMode)
+ : m_Name(inName)
+ , m_Features(inFeatures.begin(), inFeatures.end())
+ , m_TessMode(inTessMode)
+ , m_WireframeMode(inWireframeMode)
+ {
+ m_HashCode = eastl::hash<TStrStrPair>()(m_Name)
+ ^ HashShaderFeatureSet(toDataRef(m_Features.data(), (QT3DSU32)m_Features.size()))
+ ^ eastl::hash<QT3DSU32>()(m_TessMode) ^ eastl::hash<bool>()(m_WireframeMode);
+ }
+ bool operator==(const SShaderMapKey &inKey) const
+ {
+ return m_Name == inKey.m_Name && m_Features == inKey.m_Features
+ && m_TessMode == inKey.m_TessMode && m_WireframeMode == inKey.m_WireframeMode;
+ }
+};
+}
+
+namespace eastl {
+template <>
+struct hash<SShaderMapKey>
+{
+ size_t operator()(const SShaderMapKey &inKey) const { return inKey.m_HashCode; }
+};
+}
+
+namespace {
+
+typedef nvhash_map<CRegisteredString, NVScopedRefCounted<SDynamicObjClassImpl>> TStringClassMap;
+typedef nvhash_map<CRegisteredString, char8_t *> TPathDataMap;
+typedef nvhash_map<CRegisteredString, SDynamicObjectShaderInfo> TShaderInfoMap;
+typedef nvhash_set<CRegisteredString> TPathSet;
+typedef nvhash_map<SShaderMapKey, TShaderAndFlags> TShaderMap;
+
+struct SDynamicObjectSystemCoreImpl : public IDynamicObjectSystem
+{
+};
+
+struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
+{
+ NVFoundationBase &m_Foundation;
+ mutable qt3ds::render::SPreAllocatedAllocator m_Allocator;
+ IUICRenderContextCore &m_CoreContext;
+ IUICRenderContext *m_UICContext;
+ TStringClassMap m_Classes;
+ TPathDataMap m_ExpandedFiles;
+ CRenderString m_ShaderKeyBuilder;
+ TShaderMap m_ShaderMap;
+ TShaderInfoMap m_ShaderInfoMap;
+ CRenderString m_IncludePath;
+ CRenderString m_IncludeSearch;
+ CRenderString m_VertShader;
+ CRenderString m_FragShader;
+ CRenderString m_GeometryShader;
+ QString m_shaderLibraryVersion;
+ QString m_shaderLibraryPlatformDirectory;
+ mutable Mutex m_PropertyLoadMutex;
+ QT3DSI32 mRefCount;
+
+ SDynamicObjectSystemImpl(IUICRenderContextCore &inCore)
+ : m_Foundation(inCore.GetFoundation())
+ , m_Allocator(inCore.GetAllocator())
+ , m_CoreContext(inCore)
+ , m_UICContext(NULL)
+ , m_Classes(inCore.GetAllocator(), "Classes")
+ , m_ExpandedFiles(inCore.GetAllocator(), "ExpandedShaderFiles")
+ , m_ShaderMap(inCore.GetAllocator(), "ShaderMap")
+ , m_ShaderInfoMap(inCore.GetAllocator(), "ShaderInfoMap")
+ , m_PropertyLoadMutex(inCore.GetAllocator())
+ , mRefCount(0)
+ {
+ m_IncludeSearch = "#include \"";
+ }
+
+ virtual ~SDynamicObjectSystemImpl()
+ {
+ for (TPathDataMap::iterator iter = m_ExpandedFiles.begin(), end = m_ExpandedFiles.end();
+ iter != end; ++iter)
+ m_Allocator.deallocate(iter->second);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ bool IsRegistered(CRegisteredString inStr) override
+ {
+ return m_Classes.find(inStr) != m_Classes.end();
+ }
+
+ bool Register(CRegisteredString inName,
+ NVConstDataRef<SPropertyDeclaration> inProperties, QT3DSU32 inBaseObjectSize,
+ GraphObjectTypes::Enum inGraphObjectType) override
+ {
+ if (IsRegistered(inName)) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ nvvector<SPropertyDefinition> definitions(m_Foundation.getAllocator(),
+ "PropertyDefinitions");
+ QT3DSU32 theCurrentOffset = 0;
+ for (QT3DSU32 idx = 0, end = inProperties.size(); idx < end; ++idx) {
+ const SPropertyDeclaration &thePropDec = inProperties[idx];
+ CRegisteredString thePropName(
+ m_CoreContext.GetStringTable().RegisterStr(thePropDec.m_Name));
+ QT3DSU32 propSize = getSizeofShaderDataType(thePropDec.m_DataType);
+ definitions.push_back(SPropertyDefinition(thePropName, thePropDec.m_DataType,
+ theCurrentOffset, propSize));
+ theCurrentOffset += propSize;
+ theCurrentOffset = Align(theCurrentOffset);
+ }
+ QT3DSU32 dataSectionSize = theCurrentOffset;
+ QT3DSU32 clsSize = Align(sizeof(SDynamicObjClassImpl));
+ QT3DSU32 defSize = Align(sizeof(SPropertyDefinition) * inProperties.size());
+ QT3DSU32 defaultSize = dataSectionSize;
+ QT3DSU32 allocSize = clsSize + defSize + defaultSize;
+ QT3DSU8 *allocData = reinterpret_cast<QT3DSU8 *>(
+ m_Allocator.allocate(allocSize, "SDynamicObjClassImpl", __FILE__, __LINE__));
+ QT3DSU8 *defData = allocData + clsSize;
+ QT3DSU8 *defaultData = defData + defSize;
+ SPropertyDefinition *defPtr = reinterpret_cast<SPropertyDefinition *>(defData);
+ if (defSize)
+ memCopy(defPtr, definitions.data(), defSize);
+ if (defaultSize)
+ memZero(defaultData, defaultSize);
+ SDynamicObjClassImpl *theClass = new (allocData)
+ SDynamicObjClassImpl(m_Allocator, inName, toDataRef(defPtr, inProperties.size()),
+ dataSectionSize, inBaseObjectSize, inGraphObjectType, defaultData);
+ m_Classes.insert(eastl::make_pair(inName, theClass));
+ return true;
+ }
+
+ bool Unregister(CRegisteredString inName) override {
+ if (!IsRegistered(inName)) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ TStringClassMap::iterator iter = m_Classes.find(inName);
+ if (iter != m_Classes.end())
+ m_Classes.erase(iter);
+ return true;
+ }
+
+ SDynamicObjClassImpl *FindClass(CRegisteredString inName)
+ {
+ TStringClassMap::iterator iter = m_Classes.find(inName);
+ if (iter != m_Classes.end())
+ return iter->second.mPtr;
+ return NULL;
+ }
+
+ eastl::pair<const SPropertyDefinition *, SDynamicObjClassImpl *>
+ FindProperty(CRegisteredString inName, CRegisteredString inPropName)
+ {
+ SDynamicObjClassImpl *cls = FindClass(inName);
+ if (cls) {
+ const SPropertyDefinition *def = cls->FindDefinition(inPropName);
+ if (def)
+ return eastl::make_pair(def, cls);
+ }
+ return eastl::pair<const SPropertyDefinition *, SDynamicObjClassImpl *>(NULL, NULL);
+ }
+
+ void SetPropertyDefaultValue(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<QT3DSU8> inDefaultData) override
+ {
+ eastl::pair<const SPropertyDefinition *, SDynamicObjClassImpl *> def =
+ FindProperty(inName, inPropName);
+ if (def.first && inDefaultData.size() >= def.first->m_ByteSize) {
+ memCopy(def.second->m_PropertyDefaultData + def.first->m_Offset, inDefaultData.begin(),
+ def.first->m_ByteSize);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void SetPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<CRegisteredString> inNames) override
+ {
+
+ eastl::pair<const SPropertyDefinition *, SDynamicObjClassImpl *> def =
+ FindProperty(inName, inPropName);
+ SPropertyDefinition *theDefinitionPtr = const_cast<SPropertyDefinition *>(def.first);
+ if (theDefinitionPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (theDefinitionPtr->m_EnumValueNames.size()) {
+ m_Foundation.getAllocator().deallocate(
+ (void *)theDefinitionPtr->m_EnumValueNames.begin());
+ theDefinitionPtr->m_EnumValueNames = NVConstDataRef<CRegisteredString>();
+ }
+ theDefinitionPtr->m_IsEnumProperty = true;
+ if (inNames.size()) {
+ CRegisteredString *theNameValues = (CRegisteredString *)m_Allocator.allocate(
+ inNames.size() * sizeof(CRegisteredString), "PropertyEnumNames", __FILE__,
+ __LINE__);
+
+ memCopy(theNameValues, inNames.begin(), inNames.size() * sizeof(CRegisteredString));
+ theDefinitionPtr->m_EnumValueNames =
+ NVConstDataRef<CRegisteredString>(theNameValues, inNames.size());
+ }
+ }
+
+ virtual NVConstDataRef<CRegisteredString>
+ GetPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName) const override
+ {
+ eastl::pair<const SPropertyDefinition *, SDynamicObjClassImpl *> def =
+ const_cast<SDynamicObjectSystemImpl &>(*this).FindProperty(inName, inPropName);
+ if (def.first)
+ return def.first->m_EnumValueNames;
+ return NVConstDataRef<CRegisteredString>();
+ }
+
+ // Called during loading which is pretty heavily multithreaded.
+ virtual NVConstDataRef<dynamic::SPropertyDefinition>
+ GetProperties(CRegisteredString inName) const override
+ {
+ Mutex::ScopedLock __locker(m_PropertyLoadMutex);
+ SDynamicObjClassImpl *cls = const_cast<SDynamicObjectSystemImpl &>(*this).FindClass(inName);
+ if (cls)
+ return cls->m_PropertyDefinitions;
+ return NVConstDataRef<dynamic::SPropertyDefinition>();
+ }
+
+ void SetPropertyTextureSettings(CRegisteredString inName, CRegisteredString inPropName,
+ CRegisteredString inPropPath,
+ NVRenderTextureTypeValue::Enum inTexType,
+ NVRenderTextureCoordOp::Enum inCoordOp,
+ NVRenderTextureMagnifyingOp::Enum inMagFilterOp,
+ NVRenderTextureMinifyingOp::Enum inMinFilterOp) override
+ {
+ eastl::pair<const SPropertyDefinition *, SDynamicObjClassImpl *> def =
+ FindProperty(inName, inPropName);
+ SPropertyDefinition *theDefinitionPtr = const_cast<SPropertyDefinition *>(def.first);
+ if (theDefinitionPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ theDefinitionPtr->m_ImagePath = inPropPath;
+ theDefinitionPtr->m_TexUsageType = inTexType;
+ theDefinitionPtr->m_CoordOp = inCoordOp;
+ theDefinitionPtr->m_MagFilterOp = inMagFilterOp;
+ theDefinitionPtr->m_MinFilterOp = inMinFilterOp;
+ }
+
+ IDynamicObjectClass *GetDynamicObjectClass(CRegisteredString inName) override
+ {
+ return FindClass(inName);
+ }
+
+ void SetRenderCommands(CRegisteredString inClassName,
+ NVConstDataRef<dynamic::SCommand *> inCommands) override
+ {
+ SDynamicObjClassImpl *theClass =
+ const_cast<SDynamicObjectSystemImpl &>(*this).FindClass(inClassName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ theClass->ReleaseCommands();
+ QT3DSU32 commandAllocationSize = 0;
+ for (QT3DSU32 idx = 0, end = inCommands.size(); idx < end; ++idx) {
+ QT3DSU32 commandSize = Align(SCommand::GetSizeofCommand(*inCommands[idx]));
+ commandAllocationSize += commandSize;
+ }
+ QT3DSU32 commandPtrSize = inCommands.size() * sizeof(SCommand *);
+ QT3DSU32 totalAllocationSize = Align8(commandAllocationSize) + commandPtrSize;
+ QT3DSU8 *theCommandDataBegin = (QT3DSU8 *)m_Allocator.allocate(
+ totalAllocationSize, "dynamic::SCommand", __FILE__, __LINE__);
+ QT3DSU8 *theCurrentCommandData(theCommandDataBegin);
+ SCommand **theCommandPtrBegin =
+ reinterpret_cast<SCommand **>(theCommandDataBegin + Align8(commandAllocationSize));
+ SCommand **theCurrentCommandPtr = theCommandPtrBegin;
+ memZero(theCommandDataBegin, totalAllocationSize);
+
+ theClass->m_RequiresDepthTexture = false;
+ for (QT3DSU32 idx = 0, end = inCommands.size(); idx < end; ++idx) {
+ SCommand &theCommand(*inCommands[idx]);
+ QT3DSU32 theCommandSize = SCommand::GetSizeofCommand(theCommand);
+ SCommand::CopyConstructCommand(theCurrentCommandData, theCommand,
+ m_CoreContext.GetStringTable());
+ if (theCommand.m_Type == CommandTypes::ApplyDepthValue)
+ theClass->m_RequiresDepthTexture = true;
+ if (theCommand.m_Type == CommandTypes::BindTarget) {
+ SBindTarget *bt = reinterpret_cast<SBindTarget *>(&theCommand);
+ theClass->m_OutputFormat = bt->m_OutputFormat;
+ }
+
+ *theCurrentCommandPtr = reinterpret_cast<SCommand *>(theCurrentCommandData);
+ ++theCurrentCommandPtr;
+ theCurrentCommandData += Align(theCommandSize);
+ }
+ QT3DS_ASSERT(theCurrentCommandData - theCommandDataBegin == (int)commandAllocationSize);
+ QT3DS_ASSERT((QT3DSU8 *)theCurrentCommandPtr - theCommandDataBegin == (int)totalAllocationSize);
+ theClass->m_RenderCommands =
+ NVConstDataRef<SCommand *>(theCommandPtrBegin, inCommands.size());
+ }
+
+ virtual NVConstDataRef<dynamic::SCommand *>
+ GetRenderCommands(CRegisteredString inClassName) const override
+ {
+ SDynamicObjClassImpl *cls =
+ const_cast<SDynamicObjectSystemImpl &>(*this).FindClass(inClassName);
+ if (cls)
+ return cls->m_RenderCommands;
+ return NVConstDataRef<dynamic::SCommand *>();
+ }
+
+ SDynamicObject *CreateInstance(CRegisteredString inClassName,
+ NVAllocatorCallback &inSceneGraphAllocator) override
+ {
+ SDynamicObjClassImpl *theClass = FindClass(inClassName);
+ if (!theClass) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ QT3DSU32 totalObjectSize = theClass->m_BaseObjectSize + theClass->m_PropertySectionByteSize;
+ SDynamicObject *retval = reinterpret_cast<SDynamicObject *>(inSceneGraphAllocator.allocate(
+ totalObjectSize, inClassName.c_str(), __FILE__, __LINE__));
+ new (retval)
+ SDynamicObject(theClass->m_GraphObjectType, inClassName,
+ theClass->m_PropertySectionByteSize, theClass->m_BaseObjectSize);
+ memCopy(retval->GetDataSectionBegin(), theClass->m_PropertyDefaultData,
+ theClass->m_PropertySectionByteSize);
+ return retval;
+ }
+
+ void SetShaderData(CRegisteredString inPath, const char8_t *inData,
+ const char8_t *inShaderType, const char8_t *inShaderVersion,
+ bool inHasGeomShader, bool inIsComputeShader) override
+ {
+ inData = inData ? inData : "";
+ eastl::pair<TPathDataMap::iterator, bool> theInserter =
+ m_ExpandedFiles.insert(eastl::make_pair(inPath, (char8_t *)""));
+ if (theInserter.second == false) {
+ // Delete the existing entry.
+ m_Allocator.deallocate(theInserter.first->second);
+ }
+ QT3DSU32 theLen = (QT3DSU32)strlen(inData) + 1;
+ char8_t *newData = (char8_t *)m_Allocator.allocate(
+ theLen, "SDynamicObjectSystem::SetShaderData", __FILE__, __LINE__);
+ memCopy(newData, inData, theLen);
+ theInserter.first->second = newData;
+
+ // set shader type and version if available
+ if (inShaderType || inShaderVersion || inHasGeomShader || inIsComputeShader) {
+ // UdoL TODO: Add this to the load / save setction
+ // In addition we should merge the source code into SDynamicObjectShaderInfo as well
+ SDynamicObjectShaderInfo &theShaderInfo =
+ m_ShaderInfoMap.insert(eastl::make_pair(inPath, SDynamicObjectShaderInfo()))
+ .first->second;
+ IStringTable &theStringTable(m_CoreContext.GetStringTable());
+ theShaderInfo.m_Type = theStringTable.RegisterStr(nonNull(inShaderType));
+ theShaderInfo.m_Version = theStringTable.RegisterStr(nonNull(inShaderVersion));
+ theShaderInfo.m_HasGeomShader = inHasGeomShader;
+ theShaderInfo.m_IsComputeShader = inIsComputeShader;
+ }
+
+ return;
+ }
+
+ CRegisteredString GetShaderCacheKey(const char8_t *inId, const char8_t *inProgramMacro,
+ const dynamic::SDynamicShaderProgramFlags &inFlags)
+ {
+ m_ShaderKeyBuilder.assign(inId);
+ if (inProgramMacro && *inProgramMacro) {
+ m_ShaderKeyBuilder.append("#");
+ m_ShaderKeyBuilder.append(inProgramMacro);
+ }
+ if (inFlags.IsTessellationEnabled()) {
+ m_ShaderKeyBuilder.append("#");
+ m_ShaderKeyBuilder.append(TessModeValues::toString(inFlags.m_TessMode));
+ }
+ if (inFlags.IsGeometryShaderEnabled() && inFlags.m_WireframeMode) {
+ m_ShaderKeyBuilder.append("#");
+ m_ShaderKeyBuilder.append(inFlags.wireframeToString(inFlags.m_WireframeMode));
+ }
+
+ return m_CoreContext.GetStringTable().RegisterStr(m_ShaderKeyBuilder.c_str());
+ }
+
+ void InsertShaderHeaderInformation(CRenderString &theReadBuffer,
+ const char8_t *inPathToEffect) override
+ {
+ DoInsertShaderHeaderInformation(theReadBuffer, inPathToEffect);
+ }
+
+ void DoInsertShaderHeaderInformation(CRenderString &theReadBuffer,
+ const char8_t *inPathToEffect)
+ {
+ // Now do search and replace for the headers
+ for (CRenderString::size_type thePos = theReadBuffer.find(m_IncludeSearch);
+ thePos != CRenderString::npos;
+ thePos = theReadBuffer.find(m_IncludeSearch, thePos + 1)) {
+ CRenderString::size_type theEndQuote =
+ theReadBuffer.find('\"', thePos + m_IncludeSearch.size() + 1);
+ // Indicates an unterminated include file.
+ if (theEndQuote == CRenderString::npos) {
+ qCCritical(INVALID_OPERATION, "Unterminated include in file: %s", inPathToEffect);
+ theReadBuffer.clear();
+ break;
+ }
+ CRenderString::size_type theActualBegin = thePos + m_IncludeSearch.size();
+ CRenderString::iterator theIncludeBegin = theReadBuffer.begin() + theActualBegin;
+ CRenderString::iterator theIncludeEnd = theReadBuffer.begin() + theEndQuote;
+ m_IncludePath.clear();
+ m_IncludePath.append(theIncludeBegin, theIncludeEnd);
+ // If we haven't included the file yet this round
+ CRenderString theIncludeBuffer;
+ const char8_t *theHeader = DoLoadShader(m_IncludePath.c_str(), theIncludeBuffer);
+ QT3DSU32 theLen = (QT3DSU32)strlen(theHeader);
+ theReadBuffer =
+ theReadBuffer.replace(theReadBuffer.begin() + thePos,
+ theReadBuffer.begin() + theEndQuote + 1, theHeader, theLen);
+ }
+ }
+
+ const char8_t *DoLoadShader(const char8_t *inPathToEffect, CRenderString &outShaderData)
+ {
+ eastl::pair<TPathDataMap::iterator, bool> theInsert =
+ m_ExpandedFiles.insert(eastl::make_pair(
+ m_CoreContext.GetStringTable().RegisterStr(inPathToEffect), (char8_t *)""));
+
+ CRenderString &theReadBuffer(outShaderData);
+ if (theInsert.second) {
+
+ const QString defaultDir = m_UICContext->GetDynamicObjectSystem()
+ .GetShaderCodeLibraryDirectory();
+ const QString platformDir = m_UICContext->GetDynamicObjectSystem()
+ .shaderCodeLibraryPlatformDirectory();
+ const QString ver = m_UICContext->GetDynamicObjectSystem()
+ .shaderCodeLibraryVersion();
+
+ QString fullPath;
+ NVScopedRefCounted<IRefCountedInputStream> theStream;
+ if (!platformDir.isEmpty()) {
+ QTextStream stream(&fullPath);
+ stream << platformDir << "\\" << inPathToEffect;
+ theStream = m_CoreContext.GetInputStreamFactory()
+ .GetStreamForFile(fullPath.toLatin1().data());
+ }
+
+ if (theStream.mPtr == NULL) {
+ fullPath.clear();
+ QTextStream stream(&fullPath);
+ stream << defaultDir << "\\" << ver << "\\" << inPathToEffect;
+ theStream = m_CoreContext.GetInputStreamFactory()
+ .GetStreamForFile(fullPath.toLatin1().data());
+ if (theStream.mPtr == NULL) {
+ fullPath.clear();
+ QTextStream stream(&fullPath);
+ stream << defaultDir << "\\" << inPathToEffect;
+ theStream = m_CoreContext.GetInputStreamFactory()
+ .GetStreamForFile(fullPath.toLatin1().data());
+ }
+ }
+ if (theStream.mPtr != NULL) {
+ QT3DSU8 readBuf[1024];
+ QT3DSU32 amountRead = 0;
+ do {
+ amountRead = theStream->Read(NVDataRef<QT3DSU8>(readBuf, 1024));
+ if (amountRead)
+ theReadBuffer.append((const char8_t *)readBuf, amountRead);
+ } while (amountRead);
+ } else {
+ qCCritical(INVALID_OPERATION, "Failed to find include file %s",
+ inPathToEffect);
+ QT3DS_ASSERT(false);
+ }
+ theInsert.first->second = (char8_t *)m_Allocator.allocate(
+ theReadBuffer.size() + 1, "SDynamicObjectSystem::DoLoadShader", __FILE__, __LINE__);
+ memCopy(theInsert.first->second, theReadBuffer.c_str(), theReadBuffer.size() + 1);
+ } else
+ theReadBuffer.assign(theInsert.first->second);
+ DoInsertShaderHeaderInformation(theReadBuffer, inPathToEffect);
+ return theReadBuffer.c_str();
+ }
+
+ void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap, const char8_t *inProjectDir) const override
+ {
+ QT3DSU32 startOffset = ioBuffer.size();
+ ioBuffer.write((QT3DSU32)m_ExpandedFiles.size());
+ for (TPathDataMap::const_iterator theIter = m_ExpandedFiles.begin();
+ theIter != m_ExpandedFiles.end(); ++theIter) {
+ CRegisteredString thePath(theIter->first);
+ char8_t *theData = theIter->second;
+ theData = theData ? theData : (char8_t *)"";
+ QT3DSU32 theLen = (QT3DSU32)strlen(theData);
+ thePath.Remap(inRemapMap);
+ ioBuffer.write(thePath);
+ ioBuffer.write(theLen + 1);
+ ioBuffer.write(theData, theLen + 1);
+ ioBuffer.align(sizeof(void *));
+ }
+ ioBuffer.write((QT3DSU32)m_Classes.size());
+ SStringSaveRemapper theRemapper(m_Allocator, inRemapMap, inProjectDir,
+ m_CoreContext.GetStringTable());
+ for (TStringClassMap::const_iterator iter = m_Classes.begin(), end = m_Classes.end();
+ iter != end; ++iter) {
+ const SDynamicObjClassImpl *theClass = iter->second;
+ ioBuffer.align(4);
+ QT3DSU32 objOffset = ioBuffer.size();
+ QT3DSU32 classOffset = objOffset - startOffset;
+ (void)classOffset;
+ QT3DSU32 defOffset = objOffset + sizeof(SDynamicObjClassImpl);
+ QT3DSU32 dataOffset =
+ defOffset + theClass->m_PropertyDefinitions.size() * sizeof(SPropertyDefinition);
+ QT3DSU32 dataEnd = dataOffset + theClass->m_PropertySectionByteSize;
+ QT3DSU32 writeAmount = dataEnd - objOffset;
+ ioBuffer.write((const QT3DSU8 *)theClass, writeAmount);
+ ioBuffer.align(4);
+ QT3DSU32 cmdOffset = 0;
+ QT3DSU8 *writeCommandStart = NULL;
+ if (theClass->m_RenderCommands.size()) {
+ // We know commands are allocated in a block.
+ const SCommand &firstCommand = *theClass->m_RenderCommands[0];
+ const QT3DSU8 *commandStart = reinterpret_cast<const QT3DSU8 *>(&firstCommand);
+ const SCommand &lastCommand(
+ *theClass->m_RenderCommands[theClass->m_RenderCommands.size() - 1]);
+ const QT3DSU8 *commandEnd = reinterpret_cast<const QT3DSU8 *>(&lastCommand)
+ + SCommand::GetSizeofCommand(lastCommand);
+ cmdOffset = ioBuffer.size();
+ ioBuffer.write(commandStart, (QT3DSU32)(commandEnd - commandStart));
+ // Write location of the actual storage for the command ptr array.
+ ioBuffer.writeZeros(theClass->m_RenderCommands.size() * sizeof(SCommand **));
+ }
+ ioBuffer.align(4);
+ if (cmdOffset)
+ writeCommandStart = ioBuffer.begin() + cmdOffset;
+
+ SDynamicObjClassImpl *writeClass =
+ (SDynamicObjClassImpl *)(ioBuffer.begin() + objOffset);
+ writeClass->m_Id.Remap(inRemapMap);
+ writeClass->SetupThisObjectFromMemory(m_Allocator, theRemapper, writeCommandStart,
+ theClass->m_RenderCommands.size());
+ for (QT3DSU32 idx = 0, end = theClass->m_PropertyDefinitions.size(); idx < end; ++idx) {
+ // Moved into the loop because writing the enumerations may resize the data buffer.
+ SPropertyDefinition *theDefinitions =
+ (SPropertyDefinition *)(ioBuffer.begin() + defOffset);
+ theDefinitions[idx].m_Name.Remap(inRemapMap);
+ const SPropertyDefinition &theDefinition(theClass->m_PropertyDefinitions[idx]);
+ if (theDefinitions[idx].m_EnumValueNames.size()) {
+ QT3DSU32 enumOffset = ioBuffer.size();
+ ioBuffer.write(theDefinition.m_EnumValueNames.begin(),
+ theDefinition.m_EnumValueNames.size()
+ * sizeof(CRegisteredString));
+ CRegisteredString *strPtr =
+ (CRegisteredString *)(ioBuffer.begin() + enumOffset);
+ for (QT3DSU32 enumIdx = 0, enumEnd = theDefinition.m_EnumValueNames.size();
+ enumIdx < enumEnd; ++enumIdx)
+ strPtr[enumIdx].Remap(inRemapMap);
+ }
+ if (theDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ QT3DSU8 *theDataPtr = ioBuffer.begin() + dataOffset;
+ CRegisteredString *realData =
+ reinterpret_cast<CRegisteredString *>(theDataPtr + theDefinition.m_Offset);
+ realData->Remap(inRemapMap);
+ }
+ }
+ }
+
+ // Write out meta information about the shader system
+ QT3DSU32 numShaderInfos = (QT3DSU32)m_ShaderInfoMap.size();
+ ioBuffer.write(numShaderInfos);
+ for (TShaderInfoMap::const_iterator iter = m_ShaderInfoMap.begin(),
+ end = m_ShaderInfoMap.end();
+ iter != end; ++iter) {
+ CRegisteredString infoName = iter->first;
+ infoName.Remap(inRemapMap);
+ ioBuffer.write(infoName);
+ const SDynamicObjectShaderInfo &theInfo = iter->second;
+ CRegisteredString infoType(theInfo.m_Type);
+ CRegisteredString infoVersion(theInfo.m_Version);
+ infoType.Remap(inRemapMap);
+ infoVersion.Remap(inRemapMap);
+ ioBuffer.write(infoType);
+ ioBuffer.write(infoVersion);
+ }
+ }
+
+ void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t *inProjectDir) override
+ {
+ m_Allocator.m_PreAllocatedBlock = inData;
+ m_Allocator.m_OwnsMemory = false;
+ TStr workspaceStr(ForwardingAllocator(m_Foundation.getAllocator(), "ProjPath"));
+ qt3ds::render::SDataReader theReader(inData.begin(), inData.end());
+ QT3DSU32 numMappedPaths = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numMappedPaths; idx < end; ++idx) {
+ CRegisteredString theStr(theReader.LoadRef<CRegisteredString>());
+ QT3DSU32 theCharLen = theReader.LoadRef<QT3DSU32>();
+ char8_t *thePathData = reinterpret_cast<char8_t *>(theReader.m_CurrentPtr);
+ theReader.m_CurrentPtr += theCharLen;
+ theReader.Align();
+ theStr.Remap(inStrDataBlock);
+ m_ExpandedFiles.insert(eastl::make_pair(theStr, thePathData));
+ }
+ SStringLoadRemapper theRemapper(m_Allocator, inStrDataBlock, inProjectDir,
+ m_CoreContext.GetStringTable());
+ QT3DSU32 numClasses = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numClasses; idx < end; ++idx) {
+ theReader.Align(4);
+ size_t classOffset = static_cast<QT3DSU32>(theReader.m_CurrentPtr - inData.mData);
+ (void)classOffset;
+ SDynamicObjClassImpl *theClass = (SDynamicObjClassImpl *)theReader.m_CurrentPtr;
+ theClass->m_Allocator = &m_Allocator;
+ theReader.m_CurrentPtr += sizeof(SDynamicObjClassImpl);
+ SPropertyDefinition *theDefinitions = (SPropertyDefinition *)theReader.m_CurrentPtr;
+ theReader.m_CurrentPtr +=
+ theClass->m_PropertyDefinitions.size() * sizeof(SPropertyDefinition);
+ QT3DSU8 *theDataBuffer = theReader.m_CurrentPtr;
+ theReader.m_CurrentPtr += theClass->m_PropertySectionByteSize;
+ theClass->m_Id.Remap(inStrDataBlock);
+ theClass->m_PropertyDefinitions = NVConstDataRef<SPropertyDefinition>(
+ theDefinitions, theClass->m_PropertyDefinitions.size());
+ theClass->m_PropertyDefaultData = theDataBuffer;
+ theReader.Align(4);
+ QT3DSU8 *theCommandStart = theReader.m_CurrentPtr;
+
+ QT3DSU32 numRenderCommands = theClass->m_RenderCommands.size();
+ new (theClass) SDynamicObjClassImpl(
+ m_Allocator, theClass->m_Id, theClass->m_PropertyDefinitions,
+ theClass->m_PropertySectionByteSize, theClass->m_BaseObjectSize,
+ theClass->m_GraphObjectType, theClass->m_PropertyDefaultData,
+ theClass->m_RequiresDepthTexture, theClass->m_OutputFormat);
+
+ theClass->SetupThisObjectFromMemory(m_Allocator, theRemapper, theCommandStart,
+ numRenderCommands);
+
+ if (theClass->m_RenderCommands.size()) {
+ const SCommand &theLastCommand =
+ *theClass->m_RenderCommands[theClass->m_RenderCommands.size() - 1];
+ const QT3DSU8 *theCommandEnd = reinterpret_cast<const QT3DSU8 *>(&theLastCommand)
+ + SCommand::GetSizeofCommand(theLastCommand);
+ theReader.m_CurrentPtr = const_cast<QT3DSU8 *>(theCommandEnd);
+ theReader.m_CurrentPtr += theClass->m_RenderCommands.size() * sizeof(SCommand **);
+ }
+ theReader.Align(4);
+
+ for (QT3DSU32 defIdx = 0, defEnd = theClass->m_PropertyDefinitions.size(); defIdx < defEnd;
+ ++defIdx) {
+ SPropertyDefinition &theDef(theDefinitions[defIdx]);
+ theDef.m_Name.Remap(inStrDataBlock);
+ if (theDef.m_EnumValueNames.size()) {
+ CRegisteredString *theNames = (CRegisteredString *)theReader.m_CurrentPtr;
+ theReader.m_CurrentPtr +=
+ theDef.m_EnumValueNames.size() * sizeof(CRegisteredString);
+ theDef.m_EnumValueNames =
+ NVDataRef<CRegisteredString>(theNames, theDef.m_EnumValueNames.size());
+ for (QT3DSU32 enumIdx = 0, enumEnd = theDef.m_EnumValueNames.size();
+ enumIdx < enumEnd; ++enumIdx)
+ theNames[enumIdx].Remap(inStrDataBlock);
+ }
+ if (theDef.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ CRegisteredString *realData =
+ reinterpret_cast<CRegisteredString *>(theDataBuffer + theDef.m_Offset);
+ realData->Remap(inStrDataBlock);
+ }
+ }
+ m_Classes.insert(eastl::make_pair(theClass->m_Id, theClass));
+ }
+ QT3DSU32 theNumShaderInfos = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = theNumShaderInfos; idx < end; ++idx) {
+ CRegisteredString name, type, version;
+ name = theReader.LoadRef<CRegisteredString>();
+ type = theReader.LoadRef<CRegisteredString>();
+ version = theReader.LoadRef<CRegisteredString>();
+ name.Remap(inStrDataBlock);
+ type.Remap(inStrDataBlock);
+ version.Remap(inStrDataBlock);
+ SDynamicObjectShaderInfo &theInfo =
+ m_ShaderInfoMap.insert(eastl::make_pair(name, SDynamicObjectShaderInfo()))
+ .first->second;
+ theInfo.m_Type = type;
+ theInfo.m_Version = version;
+ }
+ }
+
+ IDynamicObjectSystem &CreateDynamicSystem(IUICRenderContext &rc) override
+ {
+ m_UICContext = &rc;
+ return *this;
+ }
+
+ QStringList getParameters(const QString &str, int begin, int end)
+ {
+ const QString s = str.mid(begin, end - begin + 1);
+ return s.split(",");
+ }
+
+ void insertSnapperDirectives(QString &str)
+ {
+ int beginIndex = 0;
+ // Snapper macros:
+ // #define SNAPPER_SAMPLER2D(propName, propNiceName, texFilter, texWrap, showUI ) \
+ // uniform sampler2D propName; \
+ // uniform int flag##propName; \
+ // uniform vec4 propName##Info; \
+ // vec4 texture2D_##propName(vec2 uv) \
+ // { \
+ // return GetTextureValue( propName, uv, propName##Info.z ); \
+ // }
+ //
+ // #define SNAPPER_SAMPLER2DWITHDEFAULT(propName, propNiceName, texFilter, texWrap, defaultPath, showUI ) \
+ // SNAPPER_SAMPLER2D( propName, propNiceName, texFilter, texWrap, showUI )
+ //
+ // #define SNAPPER_SAMPLERCUBE(propName, propNiceName, texFilter, texWrap ) \
+ // uniform samplerCube propName; \
+ // uniform vec2 propName##UVRange; \
+ // uniform int flag##propName; \
+ // uniform vec2 propName##Size;
+ QString snapperSampler = QStringLiteral("SNAPPER_SAMPLER2D(");
+ QString snapperSamplerDefault = QStringLiteral("SNAPPER_SAMPLER2DWITHDEFAULT(");
+ QString snapperSamplerCube = QStringLiteral("SNAPPER_SAMPLERCUBE(");
+ QString endingBracket = QStringLiteral(")");
+
+ while ((beginIndex = str.indexOf(snapperSampler, beginIndex)) >= 0) {
+ int endIndex = str.indexOf(endingBracket, beginIndex);
+ const QStringList list = getParameters(str, beginIndex + snapperSampler.length(),
+ endIndex);
+ str.remove(beginIndex, endIndex - beginIndex + 1);
+ if (list.size() == 5) {
+ QString insertStr;
+ QTextStream stream(&insertStr);
+ stream << "uniform sampler2D " << list[0] << ";\n";
+ stream << "uniform int flag" << list[0] << ";\n";
+ stream << "vec4 " << list[0] << "Info;\n";
+ stream << "vec4 texture2D_" << list[0] << "(vec2 uv) "
+ << "{ return GetTextureValue( " << list[0] << ", uv, "
+ << list[0] <<"Info.z ); }\n";
+ str.insert(beginIndex, insertStr);
+ }
+ }
+ beginIndex = 0;
+ while ((beginIndex = str.indexOf(snapperSamplerDefault, beginIndex)) >= 0) {
+ int endIndex = str.indexOf(endingBracket, beginIndex);
+ const QStringList list = getParameters(str, beginIndex + snapperSamplerDefault.length(),
+ endIndex);
+ str.remove(beginIndex, endIndex - beginIndex + 1);
+ if (list.size() == 5) {
+ QString insertStr;
+ QTextStream stream(&insertStr);
+ stream << "uniform sampler2D " << list[0] << ";\n";
+ stream << "uniform int flag" << list[0] << ";\n";
+ stream << "vec4 " << list[0] << "Info;\n";
+ stream << "vec4 texture2D_" << list[0] << "(vec2 uv) "
+ << "{ return GetTextureValue( " << list[0] << ", uv, "
+ << list[0] <<"Info.z ); }\n";
+ str.insert(beginIndex, insertStr);
+ }
+ }
+ beginIndex = 0;
+ while ((beginIndex = str.indexOf(snapperSamplerCube, beginIndex)) >= 0) {
+ int endIndex = str.indexOf(endingBracket, beginIndex);
+ const QStringList list = getParameters(str, beginIndex + snapperSamplerCube.length(),
+ endIndex);
+ str.remove(beginIndex, endIndex - beginIndex + 1);
+ if (list.size() == 4) {
+ QString insertStr;
+ QTextStream stream(&insertStr);
+ stream << "uniform samplerCube " << list[0] << ";\n";
+ stream << "uniform vec2 "<< list[0] << "UVRange;\n";
+ stream << "uniform int flag" << list[0] << ";\n";
+ stream << "uniform vec2 "<< list[0] << "Size;\n";
+ str.insert(beginIndex, insertStr);
+ }
+ }
+ }
+
+ NVRenderShaderProgram *CompileShader(CRegisteredString inId, const char8_t *inProgramSource,
+ const char8_t *inGeomSource,
+ CRegisteredString inProgramMacroName,
+ TShaderFeatureSet inFeatureSet,
+ const dynamic::SDynamicShaderProgramFlags &inFlags,
+ bool inForceCompilation = false)
+ {
+ m_VertShader.clear();
+ m_FragShader.clear();
+ m_GeometryShader.clear();
+ SShaderCacheProgramFlags theFlags;
+
+ m_VertShader.append("#define VERTEX_SHADER\n");
+ m_FragShader.append("#define FRAGMENT_SHADER\n");
+
+ if (inProgramMacroName.IsValid()) {
+ m_VertShader.append("#define ");
+ m_VertShader.append(inProgramMacroName.c_str());
+ m_VertShader.append("\n");
+
+ m_FragShader.append("#define ");
+ m_FragShader.append(inProgramMacroName.c_str());
+ m_FragShader.append("\n");
+ }
+
+ if (inGeomSource && inFlags.IsGeometryShaderEnabled()) {
+ theFlags.SetGeometryShaderEnabled(true);
+
+ m_GeometryShader.append("#define GEOMETRY_SHADER 1\n");
+ m_GeometryShader.append(inGeomSource);
+
+ m_VertShader.append("#define GEOMETRY_SHADER 1\n");
+ } else if (inFlags.IsGeometryShaderEnabled()) {
+ theFlags.SetGeometryShaderEnabled(true);
+ m_GeometryShader.append("#define USER_GEOMETRY_SHADER 1\n");
+ m_GeometryShader.append(inProgramSource);
+ m_VertShader.append("#define GEOMETRY_SHADER 0\n");
+ m_FragShader.append("#define GEOMETRY_WIREFRAME_SHADER 0\n");
+ } else {
+ m_VertShader.append("#define GEOMETRY_SHADER 0\n");
+ m_FragShader.append("#define GEOMETRY_WIREFRAME_SHADER 0\n");
+ }
+
+ if (strstr(inProgramSource, "SNAPPER_SAMPLER")) {
+ QString programSource(inProgramSource);
+ insertSnapperDirectives(programSource);
+ QByteArray data = programSource.toLatin1();
+ const char *source = data.constData();
+
+ m_VertShader.append(source);
+ m_FragShader.append(source);
+ } else {
+ m_VertShader.append(inProgramSource);
+ m_FragShader.append(inProgramSource);
+ }
+
+ IShaderCache &theShaderCache = m_UICContext->GetShaderCache();
+
+ CRegisteredString theKey = m_UICContext->GetStringTable().RegisterStr(
+ GetShaderCacheKey(inId, inProgramMacroName, inFlags));
+
+ if (inForceCompilation) {
+ return theShaderCache.ForceCompileProgram(theKey, m_VertShader.c_str(),
+ m_FragShader.c_str(), NULL, NULL,
+ m_GeometryShader.c_str(), theFlags,
+ inFeatureSet, false);
+ }
+ return theShaderCache.CompileProgram(theKey, m_VertShader.c_str(), m_FragShader.c_str(),
+ NULL, NULL, m_GeometryShader.c_str(), theFlags,
+ inFeatureSet);
+ }
+
+ // This just returns the custom material shader source without compiling
+ const char8_t *GetShaderSource(CRegisteredString inPath, CRenderString &inBuffer) override
+ {
+ inBuffer.clear();
+ inBuffer.append("#define FRAGMENT_SHADER\n");
+
+ const char8_t *source = DoLoadShader(inPath, inBuffer);
+ return source;
+ }
+
+ TShaderAndFlags GetShaderProgram(CRegisteredString inPath,
+ CRegisteredString inProgramMacro,
+ TShaderFeatureSet inFeatureSet,
+ const SDynamicShaderProgramFlags &inFlags,
+ bool inForceCompilation) override
+ {
+ eastl::pair<const SShaderMapKey, TShaderAndFlags> theInserter(
+ SShaderMapKey(TStrStrPair(inPath, inProgramMacro), inFeatureSet, inFlags.m_TessMode,
+ inFlags.m_WireframeMode),
+ TShaderAndFlags());
+ eastl::pair<TShaderMap::iterator, bool> theInsertResult(m_ShaderMap.insert(theInserter));
+ if (theInsertResult.second || inForceCompilation) {
+ NVRenderShaderProgram *theProgram = m_UICContext->GetShaderCache().GetProgram(
+ GetShaderCacheKey(inPath, inProgramMacro, inFlags), inFeatureSet);
+ SDynamicShaderProgramFlags theFlags(inFlags);
+ if (!theProgram || inForceCompilation) {
+ SDynamicObjectShaderInfo &theShaderInfo =
+ m_ShaderInfoMap.insert(eastl::make_pair(inPath, SDynamicObjectShaderInfo()))
+ .first->second;
+ if (theShaderInfo.m_IsComputeShader == false) {
+ CRenderString theShaderBuffer;
+ const char8_t *programSource = DoLoadShader(inPath, theShaderBuffer);
+ if (theShaderInfo.m_HasGeomShader)
+ theFlags.SetGeometryShaderEnabled(true);
+ theProgram = CompileShader(inPath, programSource, NULL, inProgramMacro,
+ inFeatureSet, theFlags, inForceCompilation);
+ } else {
+ CRenderString theShaderBuffer;
+ const char8_t *shaderVersionStr = "#version 430\n";
+ if ((QT3DSU32)m_UICContext->GetRenderContext().GetRenderContextType()
+ == NVRenderContextValues::GLES3PLUS)
+ shaderVersionStr = "#version 310 es\n";
+ DoLoadShader(inPath, theShaderBuffer);
+ theShaderBuffer.insert(0, shaderVersionStr);
+ const char8_t *programSource = theShaderBuffer.c_str();
+ QT3DSU32 len = (QT3DSU32)strlen(nonNull(programSource)) + 1;
+ theProgram =
+ m_UICContext->GetRenderContext()
+ .CompileComputeSource(inPath.c_str(),
+ NVConstDataRef<QT3DSI8>((QT3DSI8 *)programSource, len))
+ .mShader;
+ }
+ }
+ theInsertResult.first->second = TShaderAndFlags(theProgram, theFlags);
+ }
+ return theInsertResult.first->second;
+ }
+
+ TShaderAndFlags GetDepthPrepassShader(CRegisteredString inPath,
+ CRegisteredString inPMacro,
+ TShaderFeatureSet inFeatureSet) override
+ {
+ SDynamicObjectShaderInfo &theShaderInfo =
+ m_ShaderInfoMap.insert(eastl::make_pair(inPath, SDynamicObjectShaderInfo()))
+ .first->second;
+ if (theShaderInfo.m_HasGeomShader == false)
+ return TShaderAndFlags();
+ // else, here we go...
+ SDynamicShaderProgramFlags theFlags;
+ m_ShaderKeyBuilder.assign(inPMacro.c_str());
+ m_ShaderKeyBuilder.append("depthprepass");
+
+ CRegisteredString theProgramMacro =
+ m_UICContext->GetStringTable().RegisterStr(m_ShaderKeyBuilder.c_str());
+
+ eastl::pair<const SShaderMapKey, TShaderAndFlags> theInserter(
+ SShaderMapKey(TStrStrPair(inPath, theProgramMacro), inFeatureSet, theFlags.m_TessMode,
+ theFlags.m_WireframeMode),
+ TShaderAndFlags());
+ eastl::pair<TShaderMap::iterator, bool> theInsertResult(m_ShaderMap.insert(theInserter));
+ if (theInsertResult.second) {
+ NVRenderShaderProgram *theProgram = m_UICContext->GetShaderCache().GetProgram(
+ GetShaderCacheKey(inPath, theProgramMacro, theFlags), inFeatureSet);
+ SDynamicShaderProgramFlags theFlags(theFlags);
+ if (!theProgram) {
+ CRenderString theShaderBuffer;
+ const char8_t *geomSource = DoLoadShader(inPath, theShaderBuffer);
+ SShaderVertexCodeGenerator vertexShader(
+ m_UICContext->GetStringTable(), m_Allocator,
+ m_UICContext->GetRenderContext().GetRenderContextType());
+ SShaderFragmentCodeGenerator fragmentShader(
+ vertexShader, m_Allocator,
+ m_UICContext->GetRenderContext().GetRenderContextType());
+
+ vertexShader.AddAttribute("attr_pos", "vec3");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader.Append("void main() {");
+ vertexShader.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ vertexShader.Append("}");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);");
+ fragmentShader.Append("}");
+ const char8_t *vertexSource = vertexShader.BuildShaderSource();
+ const char8_t *fragmentSource = fragmentShader.BuildShaderSource();
+
+ CRenderString programBuffer;
+ programBuffer.assign("#ifdef VERTEX_SHADER\n");
+ programBuffer.append(vertexSource);
+ programBuffer.append("\n#endif\n");
+ programBuffer.append("\n#ifdef FRAGMENT_SHADER\n");
+ programBuffer.append(fragmentSource);
+ programBuffer.append("\n#endif");
+ theFlags.SetGeometryShaderEnabled(true);
+ theProgram = CompileShader(inPath, programBuffer.c_str(), geomSource,
+ theProgramMacro, inFeatureSet, theFlags);
+ }
+ theInsertResult.first->second = TShaderAndFlags(theProgram, theFlags);
+ }
+ return theInsertResult.first->second;
+ }
+
+ void setShaderCodeLibraryVersion(const QString &version) override
+ {
+ m_shaderLibraryVersion = version;
+ }
+
+ QString shaderCodeLibraryVersion() override
+ {
+ return m_shaderLibraryVersion;
+ }
+
+ virtual void setShaderCodeLibraryPlatformDirectory(const QString &directory) override
+ {
+ m_shaderLibraryPlatformDirectory = directory;
+ }
+
+ virtual QString shaderCodeLibraryPlatformDirectory() override
+ {
+ return m_shaderLibraryPlatformDirectory;
+ }
+};
+}
+
+IDynamicObjectSystemCore &
+IDynamicObjectSystemCore::CreateDynamicSystemCore(IUICRenderContextCore &rc)
+{
+ return *QT3DS_NEW(rc.GetAllocator(), SDynamicObjectSystemImpl)(rc);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderEffectSystem.cpp b/src/Runtime/Source/UICRender/Source/UICRenderEffectSystem.cpp
new file mode 100644
index 00000000..fc9ce829
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderEffectSystem.cpp
@@ -0,0 +1,1845 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderEffectSystem.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderString.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICRenderEffect.h"
+#include "UICRenderResourceManager.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "render/Qt3DSRenderFrameBuffer.h"
+#include "render/Qt3DSRenderShaderConstant.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderContext.h"
+#include "UICRenderer.h"
+#include "UICTextRenderer.h"
+#include "UICRenderCamera.h"
+#include "UICRenderBufferManager.h"
+#include "UICOffscreenRenderManager.h"
+#include "foundation/PreAllocatedAllocator.h"
+#include "foundation/SerializationTypes.h"
+#include "UICRenderShaderCache.h"
+#include "foundation/FileTools.h"
+#include "UICOffscreenRenderKey.h"
+#include "UICRenderDynamicObjectSystemUtil.h"
+
+using namespace uic::render;
+using namespace uic::render::dynamic;
+using qt3ds::render::NVRenderContextScopedProperty;
+using qt3ds::render::NVRenderCachedShaderProperty;
+using qt3ds::render::NVRenderCachedShaderBuffer;
+
+// None of this code will work if the size of void* changes because that would mean that
+// the alignment of some of the objects isn't 4 bytes but would be 8 bytes.
+
+typedef eastl::pair<CRegisteredString, CRegisteredString> TStrStrPair;
+
+namespace eastl {
+template <>
+struct hash<TStrStrPair>
+{
+ size_t operator()(const TStrStrPair &item) const
+ {
+ return hash<CRegisteredString>()(item.first) ^ hash<CRegisteredString>()(item.second);
+ }
+};
+}
+
+namespace {
+
+/*
+ ApplyBufferValue,
+ //Apply the depth buffer as an input texture.
+ ApplyDepthValue,
+ Render, //Render to current FBO
+ */
+
+struct SEffectClass
+{
+ NVAllocatorCallback *m_Allocator;
+ IDynamicObjectClass *m_DynamicClass;
+ volatile QT3DSI32 mRefCount;
+
+ SEffectClass(NVAllocatorCallback &inFnd, IDynamicObjectClass &dynClass)
+ : m_Allocator(&inFnd)
+ , m_DynamicClass(&dynClass)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(*m_Allocator)
+
+ void SetupThisObjectFromMemory(NVAllocatorCallback &inAlloc, IDynamicObjectClass &inClass)
+ {
+ m_Allocator = &inAlloc;
+ m_DynamicClass = &inClass;
+ mRefCount = 0;
+ }
+};
+
+struct SAllocatedBufferEntry
+{
+ CRegisteredString m_Name;
+ NVScopedRefCounted<NVRenderFrameBuffer> m_FrameBuffer;
+ NVScopedRefCounted<NVRenderTexture2D> m_Texture;
+ SAllocateBufferFlags m_Flags;
+ bool m_NeedsClear;
+
+ SAllocatedBufferEntry(CRegisteredString inName, NVRenderFrameBuffer &inFb,
+ NVRenderTexture2D &inTexture, SAllocateBufferFlags inFlags)
+ : m_Name(inName)
+ , m_FrameBuffer(&inFb)
+ , m_Texture(&inTexture)
+ , m_Flags(inFlags)
+ , m_NeedsClear(true)
+ {
+ }
+ SAllocatedBufferEntry() {}
+};
+
+struct SAllocatedImageEntry
+{
+ CRegisteredString m_Name;
+ NVScopedRefCounted<NVRenderImage2D> m_Image;
+ NVScopedRefCounted<NVRenderTexture2D> m_Texture;
+ SAllocateBufferFlags m_Flags;
+
+ SAllocatedImageEntry(CRegisteredString inName, NVRenderImage2D &inImage,
+ NVRenderTexture2D &inTexture, SAllocateBufferFlags inFlags)
+ : m_Name(inName)
+ , m_Image(&inImage)
+ , m_Texture(&inTexture)
+ , m_Flags(inFlags)
+ {
+ }
+ SAllocatedImageEntry() {}
+};
+
+struct SImageEntry
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ NVRenderCachedShaderProperty<NVRenderImage2D *> m_Image;
+ volatile QT3DSI32 mRefCount;
+
+ SImageEntry(NVRenderShaderProgram &inShader, const char *inImageName)
+ : m_Shader(inShader)
+ , m_Image(inImageName, inShader)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+
+ void Set(NVRenderImage2D *inImage) { m_Image.Set(inImage); }
+
+ static SImageEntry CreateImageEntry(NVRenderShaderProgram &inShader, const char *inStem)
+ {
+ return SImageEntry(inShader, inStem);
+ }
+};
+
+struct SAllocatedDataBufferEntry
+{
+ CRegisteredString m_Name;
+ NVScopedRefCounted<qt3ds::render::NVRenderDataBuffer> m_DataBuffer;
+ NVRenderBufferBindValues::Enum m_BufferType;
+ NVDataRef<QT3DSU8> m_BufferData;
+ SAllocateBufferFlags m_Flags;
+ bool m_NeedsClear;
+
+ SAllocatedDataBufferEntry(CRegisteredString inName,
+ qt3ds::render::NVRenderDataBuffer &inDataBuffer,
+ NVRenderBufferBindValues::Enum inType, NVDataRef<QT3DSU8> data,
+ SAllocateBufferFlags inFlags)
+ : m_Name(inName)
+ , m_DataBuffer(&inDataBuffer)
+ , m_BufferType(inType)
+ , m_BufferData(data)
+ , m_Flags(inFlags)
+ , m_NeedsClear(false)
+ {
+ }
+ SAllocatedDataBufferEntry() {}
+};
+
+struct SDataBufferEntry
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ NVRenderCachedShaderBuffer<qt3ds::render::NVRenderShaderBufferBase *> m_DataBuffer;
+ volatile QT3DSI32 mRefCount;
+
+ SDataBufferEntry(NVRenderShaderProgram &inShader, const char *inBufferName)
+ : m_Shader(inShader)
+ , m_DataBuffer(inBufferName, inShader)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+
+ void Set(qt3ds::render::NVRenderDataBuffer *inBuffer)
+ {
+ if (inBuffer)
+ inBuffer->Bind();
+
+ m_DataBuffer.Set();
+ }
+
+ static SDataBufferEntry CreateDataBufferEntry(NVRenderShaderProgram &inShader,
+ const char *inStem)
+ {
+ return SDataBufferEntry(inShader, inStem);
+ }
+};
+
+struct SEffectTextureData
+{
+ NVRenderTexture2D *m_Texture;
+ bool m_NeedsAlphaMultiply;
+ SEffectTextureData(NVRenderTexture2D *inTexture, bool inNeedsMultiply)
+ : m_Texture(inTexture)
+ , m_NeedsAlphaMultiply(inNeedsMultiply)
+ {
+ }
+ SEffectTextureData()
+ : m_Texture(NULL)
+ , m_NeedsAlphaMultiply(false)
+ {
+ }
+};
+
+struct STextureEntry
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Texture;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_TextureData;
+ NVRenderCachedShaderProperty<QT3DSI32> m_TextureFlags;
+ volatile QT3DSI32 mRefCount;
+
+ STextureEntry(NVRenderShaderProgram &inShader, const char *inTexName, const char *inDataName,
+ const char *inFlagName)
+ : m_Shader(inShader)
+ , m_Texture(inTexName, inShader)
+ , m_TextureData(inDataName, inShader)
+ , m_TextureFlags(inFlagName, inShader)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+
+ void Set(NVRenderTexture2D *inTexture, bool inNeedsAlphaMultiply,
+ const SPropertyDefinition *inDefinition)
+ {
+ QT3DSF32 theMixValue(inNeedsAlphaMultiply ? 0.0f : 1.0f);
+ if (inTexture && inDefinition) {
+ inTexture->SetMagFilter(inDefinition->m_MagFilterOp);
+ inTexture->SetMinFilter(
+ static_cast<NVRenderTextureMinifyingOp::Enum>(inDefinition->m_MagFilterOp));
+ inTexture->SetTextureWrapS(inDefinition->m_CoordOp);
+ inTexture->SetTextureWrapT(inDefinition->m_CoordOp);
+ }
+ m_Texture.Set(inTexture);
+ if (inTexture) {
+ STextureDetails theDetails(inTexture->GetTextureDetails());
+ m_TextureData.Set(
+ QT3DSVec4((QT3DSF32)theDetails.m_Width, (QT3DSF32)theDetails.m_Height, theMixValue, 0.0f));
+ // I have no idea what these flags do.
+ m_TextureFlags.Set(1);
+ } else
+ m_TextureFlags.Set(0);
+ }
+
+ static STextureEntry CreateTextureEntry(NVRenderShaderProgram &inShader, const char *inStem,
+ CRenderString &inBuilder, CRenderString &inBuilder2)
+ {
+ inBuilder.assign(inStem);
+ inBuilder.append("Info");
+ inBuilder2.assign("flag");
+ inBuilder2.append(inStem);
+ return STextureEntry(inShader, inStem, inBuilder.c_str(), inBuilder2.c_str());
+ }
+};
+
+typedef eastl::pair<CRegisteredString, NVScopedRefCounted<STextureEntry>> TNamedTextureEntry;
+typedef eastl::pair<CRegisteredString, NVScopedRefCounted<SImageEntry>> TNamedImageEntry;
+typedef eastl::pair<CRegisteredString, NVScopedRefCounted<SDataBufferEntry>> TNamedDataBufferEntry;
+}
+
+namespace uic {
+namespace render {
+
+ struct SEffectContext
+ {
+ CRegisteredString m_ClassName;
+ IUICRenderContext &m_Context;
+ IResourceManager *m_ResourceManager;
+ nvvector<SAllocatedBufferEntry> m_AllocatedBuffers;
+ nvvector<SAllocatedImageEntry> m_AllocatedImages;
+ nvvector<SAllocatedDataBufferEntry> m_AllocatedDataBuffers;
+ nvvector<TNamedTextureEntry> m_TextureEntries;
+ nvvector<TNamedImageEntry> m_ImageEntries;
+ nvvector<TNamedDataBufferEntry> m_DataBufferEntries;
+
+ SEffectContext(CRegisteredString inName, IUICRenderContext &ctx, IResourceManager *inManager)
+ : m_ClassName(inName)
+ , m_Context(ctx)
+ , m_ResourceManager(inManager)
+ , m_AllocatedBuffers(ctx.GetAllocator(), "SEffectContext::m_AllocatedBuffers")
+ , m_AllocatedImages(ctx.GetAllocator(), "SEffectContext::m_AllocatedImages")
+ , m_AllocatedDataBuffers(ctx.GetAllocator(), "SEffectContext::m_AllocatedDataBuffers")
+ , m_TextureEntries(ctx.GetAllocator(), "SEffectContext::m_TextureEntries")
+ , m_ImageEntries(ctx.GetAllocator(), "SEffectContext::m_ImageEntries")
+ , m_DataBufferEntries(ctx.GetAllocator(), "SEffectContext::m_DataBufferEntries")
+ {
+ }
+
+ ~SEffectContext()
+ {
+ while (m_AllocatedBuffers.size())
+ ReleaseBuffer(0);
+
+ while (m_AllocatedImages.size())
+ ReleaseImage(0);
+
+ while (m_AllocatedDataBuffers.size())
+ ReleaseDataBuffer(0);
+ }
+
+ void ReleaseBuffer(QT3DSU32 inIdx)
+ {
+ SAllocatedBufferEntry &theEntry(m_AllocatedBuffers[inIdx]);
+ theEntry.m_FrameBuffer->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer());
+ m_ResourceManager->Release(*theEntry.m_FrameBuffer);
+ m_ResourceManager->Release(*theEntry.m_Texture);
+ m_AllocatedBuffers.replace_with_last(inIdx);
+ }
+
+ void ReleaseImage(QT3DSU32 inIdx)
+ {
+ SAllocatedImageEntry &theEntry(m_AllocatedImages[inIdx]);
+ m_ResourceManager->Release(*theEntry.m_Image);
+ m_ResourceManager->Release(*theEntry.m_Texture);
+ m_AllocatedImages.replace_with_last(inIdx);
+ }
+
+ void ReleaseDataBuffer(QT3DSU32 inIdx)
+ {
+ SAllocatedDataBufferEntry &theEntry(m_AllocatedDataBuffers[inIdx]);
+ m_Context.GetAllocator().deallocate(theEntry.m_BufferData.begin());
+
+ m_AllocatedDataBuffers.replace_with_last(inIdx);
+ }
+
+ QT3DSU32 FindBuffer(CRegisteredString inName)
+ {
+ for (QT3DSU32 idx = 0, end = m_AllocatedBuffers.size(); idx < end; ++idx)
+ if (m_AllocatedBuffers[idx].m_Name == inName)
+ return idx;
+ return m_AllocatedBuffers.size();
+ }
+
+ QT3DSU32 FindImage(CRegisteredString inName)
+ {
+ for (QT3DSU32 idx = 0, end = m_AllocatedImages.size(); idx < end; ++idx)
+ if (m_AllocatedImages[idx].m_Name == inName)
+ return idx;
+
+ return m_AllocatedImages.size();
+ }
+
+ QT3DSU32 FindDataBuffer(CRegisteredString inName)
+ {
+ for (QT3DSU32 idx = 0, end = m_AllocatedDataBuffers.size(); idx < end; ++idx) {
+ if (m_AllocatedDataBuffers[idx].m_Name == inName)
+ return idx;
+ }
+
+ return m_AllocatedDataBuffers.size();
+ }
+
+ void SetTexture(NVRenderShaderProgram &inShader, CRegisteredString inPropName,
+ NVRenderTexture2D *inTexture, bool inNeedsMultiply,
+ CRenderString &inStringBuilder, CRenderString &inStringBuilder2,
+ const SPropertyDefinition *inPropDec = NULL)
+ {
+ STextureEntry *theTextureEntry(NULL);
+ for (QT3DSU32 idx = 0, end = m_TextureEntries.size(); idx < end && theTextureEntry == NULL;
+ ++idx) {
+ if (m_TextureEntries[idx].first == inPropName
+ && m_TextureEntries[idx].second->m_Shader.mPtr == &inShader)
+ theTextureEntry = m_TextureEntries[idx].second;
+ }
+ if (theTextureEntry == NULL) {
+ NVScopedRefCounted<STextureEntry> theNewEntry = QT3DS_NEW(
+ m_Context.GetAllocator(), STextureEntry)(STextureEntry::CreateTextureEntry(
+ inShader, inPropName, inStringBuilder, inStringBuilder2));
+ m_TextureEntries.push_back(eastl::make_pair(inPropName, theNewEntry));
+ theTextureEntry = theNewEntry.mPtr;
+ }
+ theTextureEntry->Set(inTexture, inNeedsMultiply, inPropDec);
+ }
+
+ void SetImage(NVRenderShaderProgram &inShader, CRegisteredString inPropName,
+ NVRenderImage2D *inImage)
+ {
+ SImageEntry *theImageEntry(NULL);
+ for (QT3DSU32 idx = 0, end = m_ImageEntries.size(); idx < end && theImageEntry == NULL;
+ ++idx) {
+ if (m_ImageEntries[idx].first == inPropName
+ && m_ImageEntries[idx].second->m_Shader.mPtr == &inShader)
+ theImageEntry = m_ImageEntries[idx].second;
+ }
+ if (theImageEntry == NULL) {
+ NVScopedRefCounted<SImageEntry> theNewEntry =
+ QT3DS_NEW(m_Context.GetAllocator(),
+ SImageEntry)(SImageEntry::CreateImageEntry(inShader, inPropName));
+ m_ImageEntries.push_back(eastl::make_pair(inPropName, theNewEntry));
+ theImageEntry = theNewEntry.mPtr;
+ }
+
+ theImageEntry->Set(inImage);
+ }
+
+ void SetDataBuffer(NVRenderShaderProgram &inShader, CRegisteredString inPropName,
+ qt3ds::render::NVRenderDataBuffer *inBuffer)
+ {
+ SDataBufferEntry *theDataBufferEntry(NULL);
+ for (QT3DSU32 idx = 0, end = m_DataBufferEntries.size();
+ idx < end && theDataBufferEntry == NULL; ++idx) {
+ if (m_DataBufferEntries[idx].first == inPropName
+ && m_DataBufferEntries[idx].second->m_Shader.mPtr == &inShader)
+ theDataBufferEntry = m_DataBufferEntries[idx].second;
+ }
+ if (theDataBufferEntry == NULL) {
+ NVScopedRefCounted<SDataBufferEntry> theNewEntry =
+ QT3DS_NEW(m_Context.GetAllocator(), SDataBufferEntry)(
+ SDataBufferEntry::CreateDataBufferEntry(inShader, inPropName));
+ m_DataBufferEntries.push_back(eastl::make_pair(inPropName, theNewEntry));
+ theDataBufferEntry = theNewEntry.mPtr;
+ }
+
+ theDataBufferEntry->Set(inBuffer);
+ }
+ };
+}
+}
+
+namespace {
+
+using qt3ds::render::NVRenderCachedShaderProperty;
+/* We setup some shared state on the effect shaders */
+struct SEffectShader
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_MVP;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_FragColorAlphaSettings;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_DestSize;
+ NVRenderCachedShaderProperty<QT3DSF32> m_AppFrame;
+ NVRenderCachedShaderProperty<QT3DSF32> m_FPS;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraClipRange;
+ STextureEntry m_TextureEntry;
+ volatile QT3DSI32 mRefCount;
+ SEffectShader(NVRenderShaderProgram &inShader)
+ : m_Shader(inShader)
+ , m_MVP("ModelViewProjectionMatrix", inShader)
+ , m_FragColorAlphaSettings("FragColorAlphaSettings", inShader)
+ , m_DestSize("DestSize", inShader)
+ , m_AppFrame("AppFrame", inShader)
+ , m_FPS("FPS", inShader)
+ , m_CameraClipRange("CameraClipRange", inShader)
+ , m_TextureEntry(inShader, "Texture0", "Texture0Info", "Texture0Flags")
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Shader->GetRenderContext().GetAllocator())
+};
+
+struct SEffectSystem : public IEffectSystem
+{
+ typedef nvhash_map<CRegisteredString, char8_t *> TPathDataMap;
+ typedef nvhash_set<CRegisteredString> TPathSet;
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<SEffectClass>> TEffectClassMap;
+ typedef nvhash_map<TStrStrPair, NVScopedRefCounted<SEffectShader>> TShaderMap;
+ typedef nvvector<SEffectContext *> TContextList;
+
+ IUICRenderContextCore &m_CoreContext;
+ IUICRenderContext *m_UICContext;
+ NVScopedRefCounted<IResourceManager> m_ResourceManager;
+ mutable qt3ds::render::SPreAllocatedAllocator m_Allocator;
+ // Keep from dual-including headers.
+ TEffectClassMap m_EffectClasses;
+ nvvector<CRegisteredString> m_EffectList;
+ TContextList m_Contexts;
+ CRenderString m_TextureStringBuilder;
+ CRenderString m_TextureStringBuilder2;
+ TShaderMap m_ShaderMap;
+ NVScopedRefCounted<NVRenderDepthStencilState> m_DefaultStencilState;
+ nvvector<NVScopedRefCounted<NVRenderDepthStencilState>> m_DepthStencilStates;
+ volatile QT3DSI32 mRefCount;
+
+ SEffectSystem(IUICRenderContextCore &inUICContext)
+ : m_CoreContext(inUICContext)
+ , m_UICContext(NULL)
+ , m_Allocator(inUICContext.GetAllocator())
+ , m_EffectClasses(inUICContext.GetAllocator(), "SEffectSystem::m_EffectClasses")
+ , m_EffectList(inUICContext.GetAllocator(), "SEffectSystem::m_EffectList")
+ , m_Contexts(inUICContext.GetAllocator(), "SEffectSystem::m_Contexts")
+ , m_ShaderMap(inUICContext.GetAllocator(), "SEffectSystem::m_ShaderMap")
+ , m_DepthStencilStates(inUICContext.GetAllocator(), "SEffectSystem::m_DepthStencilStates")
+ , mRefCount(0)
+ {
+ }
+
+ ~SEffectSystem()
+ {
+ for (QT3DSU32 idx = 0, end = m_Contexts.size(); idx < end; ++idx)
+ NVDelete(m_Allocator, m_Contexts[idx]);
+ m_Contexts.clear();
+ }
+
+ SEffectContext &GetEffectContext(SEffect &inEffect)
+ {
+ if (inEffect.m_Context == NULL) {
+ inEffect.m_Context =
+ QT3DS_NEW(m_Allocator, SEffectContext)(inEffect.m_ClassName,
+ *m_UICContext, m_ResourceManager);
+ m_Contexts.push_back(inEffect.m_Context);
+ }
+ return *inEffect.m_Context;
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_CoreContext.GetAllocator());
+
+ SEffectClass *GetEffectClass(CRegisteredString inStr)
+ {
+ TEffectClassMap::iterator theIter = m_EffectClasses.find(inStr);
+ if (theIter != m_EffectClasses.end())
+ return theIter->second;
+ return NULL;
+ }
+ const SEffectClass *GetEffectClass(CRegisteredString inStr) const
+ {
+ return const_cast<SEffectSystem *>(this)->GetEffectClass(inStr);
+ }
+
+ bool IsEffectRegistered(CRegisteredString inStr) override
+ {
+ return GetEffectClass(inStr) != NULL;
+ }
+ NVConstDataRef<CRegisteredString> GetRegisteredEffects() override
+ {
+ m_EffectList.clear();
+ for (TEffectClassMap::iterator theIter = m_EffectClasses.begin(),
+ theEnd = m_EffectClasses.end();
+ theIter != theEnd; ++theIter)
+ m_EffectList.push_back(theIter->first);
+ return m_EffectList;
+ }
+
+ // Registers an effect that runs via a single GLSL file.
+ bool RegisterGLSLEffect(CRegisteredString inName, const char8_t *inPathToEffect,
+ NVConstDataRef<SPropertyDeclaration> inProperties) override
+ {
+ if (IsEffectRegistered(inName))
+ return false;
+
+ m_CoreContext.GetDynamicObjectSystemCore().Register(inName, inProperties, sizeof(SEffect),
+ GraphObjectTypes::Effect);
+ IDynamicObjectClass &theClass =
+ *m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inName);
+
+ SEffectClass *theEffect = QT3DS_NEW(m_Allocator, SEffectClass)(m_Allocator, theClass);
+ m_EffectClasses.insert(eastl::make_pair(inName, theEffect));
+
+ // Setup the commands required to run this effect
+ StaticAssert<(sizeof(SBindShader) % 4 == 0)>::valid_expression();
+ StaticAssert<(sizeof(SApplyInstanceValue) % 4 == 0)>::valid_expression();
+ StaticAssert<(sizeof(SRender) % 4 == 0)>::valid_expression();
+
+ QT3DSU32 commandAllocationSize = sizeof(SBindTarget);
+ commandAllocationSize += sizeof(SBindShader);
+ commandAllocationSize += sizeof(SApplyInstanceValue) * inProperties.size();
+ commandAllocationSize += sizeof(SRender);
+
+ QT3DSU32 commandCount = 3 + inProperties.size();
+ QT3DSU32 commandPtrAllocationSize = commandCount * sizeof(SCommand *);
+ QT3DSU32 allocationSize = Align8(commandAllocationSize) + commandPtrAllocationSize;
+ QT3DSU8 *startBuffer =
+ (QT3DSU8 *)m_Allocator.allocate(allocationSize, "dynamic::SCommand", __FILE__, __LINE__);
+ QT3DSU8 *dataBuffer = startBuffer;
+ // Setup the command buffer such that the ptrs to the commands and the commands themselves
+ // are
+ // all in the same block of memory. This enables quicker iteration (trivially quicker, most
+ // likely)
+ // but it also enables simpler memory management (single free).
+ // Furthermore, for a single glsl file the effect properties map precisely into the
+ // glsl file itself.
+ SCommand **theFirstCommandPtr =
+ (reinterpret_cast<SCommand **>(dataBuffer + Align8(commandAllocationSize)));
+ SCommand **theCommandPtr = theFirstCommandPtr;
+ memZero(dataBuffer, commandAllocationSize);
+
+ new (dataBuffer) SBindTarget();
+ *theCommandPtr = (SCommand *)dataBuffer;
+ ++theCommandPtr;
+ dataBuffer += sizeof(SBindTarget);
+
+ new (dataBuffer) SBindShader(m_CoreContext.GetStringTable().RegisterStr(inPathToEffect));
+ *theCommandPtr = (SCommand *)dataBuffer;
+ ++theCommandPtr;
+ dataBuffer += sizeof(SBindShader);
+
+ for (QT3DSU32 idx = 0, end = inProperties.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(
+ theEffect->m_DynamicClass->GetProperties()[idx]);
+ new (dataBuffer) SApplyInstanceValue(theDefinition.m_Name, theDefinition.m_DataType,
+ theDefinition.m_Offset);
+ *theCommandPtr = (SCommand *)dataBuffer;
+ ++theCommandPtr;
+ dataBuffer += sizeof(SApplyInstanceValue);
+ }
+ new (dataBuffer) SRender(false);
+ *theCommandPtr = (SCommand *)dataBuffer;
+ ++theCommandPtr;
+ dataBuffer += sizeof(SRender);
+ // Ensure we end up *exactly* where we expected to.
+ QT3DS_ASSERT(dataBuffer == startBuffer + commandAllocationSize);
+ QT3DS_ASSERT(theCommandPtr - theFirstCommandPtr == (int)inProperties.size() + 3);
+ m_CoreContext.GetDynamicObjectSystemCore().SetRenderCommands(
+ inName, NVConstDataRef<SCommand *>(theFirstCommandPtr, commandCount));
+ m_Allocator.deallocate(startBuffer);
+ return true;
+ }
+
+ void SetEffectPropertyDefaultValue(CRegisteredString inName,
+ CRegisteredString inPropName,
+ NVConstDataRef<QT3DSU8> inDefaultData) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetPropertyDefaultValue(inName, inPropName,
+ inDefaultData);
+ }
+
+ void SetEffectPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName,
+ NVConstDataRef<CRegisteredString> inNames) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetPropertyEnumNames(inName, inPropName,
+ inNames);
+ }
+
+ bool RegisterEffect(CRegisteredString inName,
+ NVConstDataRef<SPropertyDeclaration> inProperties) override
+ {
+ if (IsEffectRegistered(inName))
+ return false;
+ m_CoreContext.GetDynamicObjectSystemCore().Register(inName, inProperties, sizeof(SEffect),
+ GraphObjectTypes::Effect);
+ IDynamicObjectClass &theClass =
+ *m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inName);
+ SEffectClass *theEffect = QT3DS_NEW(m_Allocator, SEffectClass)(m_Allocator, theClass);
+ m_EffectClasses.insert(eastl::make_pair(inName, theEffect));
+ return true;
+ }
+
+ bool UnregisterEffect(CRegisteredString inName) override
+ {
+ if (!IsEffectRegistered(inName))
+ return false;
+
+ m_CoreContext.GetDynamicObjectSystemCore().Unregister(inName);
+
+ TEffectClassMap::iterator iter = m_EffectClasses.find(inName);
+ if (iter != m_EffectClasses.end())
+ m_EffectClasses.erase(iter);
+
+ for (QT3DSU32 idx = 0, end = m_Contexts.size(); idx < end; ++idx) {
+ if (m_Contexts[idx]->m_ClassName == inName)
+ ReleaseEffectContext(m_Contexts[idx]);
+ }
+ return true;
+ }
+
+ virtual NVConstDataRef<CRegisteredString>
+ GetEffectPropertyEnumNames(CRegisteredString inName, CRegisteredString inPropName) const override
+ {
+ const SEffectClass *theClass = GetEffectClass(inName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ NVConstDataRef<CRegisteredString>();
+ }
+ const SPropertyDefinition *theDefinitionPtr =
+ theClass->m_DynamicClass->FindPropertyByName(inPropName);
+ if (theDefinitionPtr)
+ return theDefinitionPtr->m_EnumValueNames;
+ return NVConstDataRef<CRegisteredString>();
+ }
+
+ virtual NVConstDataRef<SPropertyDefinition>
+ GetEffectProperties(CRegisteredString inEffectName) const override
+ {
+ const SEffectClass *theClass = GetEffectClass(inEffectName);
+ if (theClass)
+ return theClass->m_DynamicClass->GetProperties();
+ return NVConstDataRef<SPropertyDefinition>();
+ }
+
+ void SetEffectPropertyTextureSettings(CRegisteredString inName,
+ CRegisteredString inPropName,
+ CRegisteredString inPropPath,
+ NVRenderTextureTypeValue::Enum inTexType,
+ NVRenderTextureCoordOp::Enum inCoordOp,
+ NVRenderTextureMagnifyingOp::Enum inMagFilterOp,
+ NVRenderTextureMinifyingOp::Enum inMinFilterOp) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetPropertyTextureSettings(
+ inName, inPropName, inPropPath, inTexType, inCoordOp, inMagFilterOp, inMinFilterOp);
+ }
+
+ void SetEffectRequiresDepthTexture(CRegisteredString inEffectName, bool inValue) override
+ {
+ SEffectClass *theClass = GetEffectClass(inEffectName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ theClass->m_DynamicClass->SetRequiresDepthTexture(inValue);
+ }
+
+ bool DoesEffectRequireDepthTexture(CRegisteredString inEffectName) const override
+ {
+ const SEffectClass *theClass = GetEffectClass(inEffectName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ return theClass->m_DynamicClass->RequiresDepthTexture();
+ }
+
+ void SetEffectRequiresCompilation(CRegisteredString inEffectName, bool inValue) override
+ {
+ SEffectClass *theClass = GetEffectClass(inEffectName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ theClass->m_DynamicClass->SetRequiresCompilation(inValue);
+ }
+
+ bool DoesEffectRequireCompilation(CRegisteredString inEffectName) const override
+ {
+ const SEffectClass *theClass = GetEffectClass(inEffectName);
+ if (theClass == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ return theClass->m_DynamicClass->RequiresCompilation();
+ }
+
+ void SetEffectCommands(CRegisteredString inEffectName,
+ NVConstDataRef<dynamic::SCommand *> inCommands) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetRenderCommands(inEffectName, inCommands);
+ }
+
+ virtual NVConstDataRef<dynamic::SCommand *>
+ GetEffectCommands(CRegisteredString inEffectName) const override
+ {
+ return m_CoreContext.GetDynamicObjectSystemCore().GetRenderCommands(inEffectName);
+ }
+
+ SEffect *CreateEffectInstance(CRegisteredString inEffectName,
+ NVAllocatorCallback &inSceneGraphAllocator) override
+ {
+ SEffectClass *theClass = GetEffectClass(inEffectName);
+ if (theClass == NULL)
+ return NULL;
+ StaticAssert<(sizeof(SEffect) % 4 == 0)>::valid_expression();
+
+ SEffect *theEffect = (SEffect *)m_CoreContext.GetDynamicObjectSystemCore().CreateInstance(
+ inEffectName, inSceneGraphAllocator);
+ theEffect->Initialize();
+ return theEffect;
+ }
+
+ void AllocateBuffer(SEffect &inEffect, const SAllocateBuffer &inCommand, QT3DSU32 inFinalWidth,
+ QT3DSU32 inFinalHeight, NVRenderTextureFormats::Enum inSourceTextureFormat)
+ {
+ // Check to see if it is already allocated and if it is, is it the correct size. If both of
+ // these assumptions hold, then we are good.
+ NVRenderTexture2D *theBufferTexture = NULL;
+ QT3DSU32 theWidth =
+ ITextRenderer::NextMultipleOf4((QT3DSU32)(inFinalWidth * inCommand.m_SizeMultiplier));
+ QT3DSU32 theHeight =
+ ITextRenderer::NextMultipleOf4((QT3DSU32)(inFinalHeight * inCommand.m_SizeMultiplier));
+ NVRenderTextureFormats::Enum resultFormat = inCommand.m_Format;
+ if (resultFormat == NVRenderTextureFormats::Unknown)
+ resultFormat = inSourceTextureFormat;
+
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ // size intentionally requiried every loop;
+ QT3DSU32 bufferIdx = theContext.FindBuffer(inCommand.m_Name);
+ if (bufferIdx < theContext.m_AllocatedBuffers.size()) {
+ SAllocatedBufferEntry &theEntry(theContext.m_AllocatedBuffers[bufferIdx]);
+ STextureDetails theDetails = theEntry.m_Texture->GetTextureDetails();
+ if (theDetails.m_Width == theWidth && theDetails.m_Height == theHeight
+ && theDetails.m_Format == resultFormat) {
+ theBufferTexture = theEntry.m_Texture;
+ } else {
+ theContext.ReleaseBuffer(bufferIdx);
+ }
+ }
+ }
+ if (theBufferTexture == NULL) {
+ SEffectContext &theContext(GetEffectContext(inEffect));
+ NVRenderFrameBuffer *theFB(m_ResourceManager->AllocateFrameBuffer());
+ NVRenderTexture2D *theTexture(
+ m_ResourceManager->AllocateTexture2D(theWidth, theHeight, resultFormat));
+ theTexture->SetMagFilter(inCommand.m_FilterOp);
+ theTexture->SetMinFilter(
+ static_cast<NVRenderTextureMinifyingOp::Enum>(inCommand.m_FilterOp));
+ theTexture->SetTextureWrapS(inCommand.m_TexCoordOp);
+ theTexture->SetTextureWrapT(inCommand.m_TexCoordOp);
+ theFB->Attach(NVRenderFrameBufferAttachments::Color0, *theTexture);
+ theContext.m_AllocatedBuffers.push_back(SAllocatedBufferEntry(
+ inCommand.m_Name, *theFB, *theTexture, inCommand.m_BufferFlags));
+ theBufferTexture = theTexture;
+ }
+ }
+
+ void AllocateImage(SEffect &inEffect, const SAllocateImage &inCommand, QT3DSU32 inFinalWidth,
+ QT3DSU32 inFinalHeight)
+ {
+ NVRenderImage2D *theImage = NULL;
+ QT3DSU32 theWidth =
+ ITextRenderer::NextMultipleOf4((QT3DSU32)(inFinalWidth * inCommand.m_SizeMultiplier));
+ QT3DSU32 theHeight =
+ ITextRenderer::NextMultipleOf4((QT3DSU32)(inFinalHeight * inCommand.m_SizeMultiplier));
+
+ QT3DS_ASSERT(inCommand.m_Format != NVRenderTextureFormats::Unknown);
+
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ // size intentionally requiried every loop;
+ QT3DSU32 imageIdx = theContext.FindImage(inCommand.m_Name);
+ if (imageIdx < theContext.m_AllocatedImages.size()) {
+ SAllocatedImageEntry &theEntry(theContext.m_AllocatedImages[imageIdx]);
+ STextureDetails theDetails = theEntry.m_Texture->GetTextureDetails();
+ if (theDetails.m_Width == theWidth && theDetails.m_Height == theHeight
+ && theDetails.m_Format == inCommand.m_Format) {
+ theImage = theEntry.m_Image;
+ } else {
+ theContext.ReleaseImage(imageIdx);
+ }
+ }
+ }
+
+ if (theImage == NULL) {
+ SEffectContext &theContext(GetEffectContext(inEffect));
+ // allocate an immutable texture
+ NVRenderTexture2D *theTexture(m_ResourceManager->AllocateTexture2D(
+ theWidth, theHeight, inCommand.m_Format, 1, true));
+ theTexture->SetMagFilter(inCommand.m_FilterOp);
+ theTexture->SetMinFilter(
+ static_cast<NVRenderTextureMinifyingOp::Enum>(inCommand.m_FilterOp));
+ theTexture->SetTextureWrapS(inCommand.m_TexCoordOp);
+ theTexture->SetTextureWrapT(inCommand.m_TexCoordOp);
+ NVRenderImage2D *theImage =
+ (m_ResourceManager->AllocateImage2D(theTexture, inCommand.m_Access));
+ theContext.m_AllocatedImages.push_back(SAllocatedImageEntry(
+ inCommand.m_Name, *theImage, *theTexture, inCommand.m_BufferFlags));
+ }
+ }
+
+ void AllocateDataBuffer(SEffect &inEffect, const SAllocateDataBuffer &inCommand)
+ {
+ QT3DSU32 theBufferSize = (QT3DSU32)inCommand.m_Size;
+ QT3DS_ASSERT(theBufferSize);
+ qt3ds::render::NVRenderDataBuffer *theDataBuffer = NULL;
+ qt3ds::render::NVRenderDataBuffer *theDataWrapBuffer = NULL;
+
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ // size intentionally requiried every loop;
+ QT3DSU32 bufferIdx = theContext.FindDataBuffer(inCommand.m_Name);
+ if (bufferIdx < theContext.m_AllocatedDataBuffers.size()) {
+ SAllocatedDataBufferEntry &theEntry(theContext.m_AllocatedDataBuffers[bufferIdx]);
+ if (theEntry.m_BufferType == inCommand.m_DataBufferType
+ && theEntry.m_BufferData.size() == theBufferSize) {
+ theDataBuffer = theEntry.m_DataBuffer;
+ } else {
+ // if type and size don't match something is wrong
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ if (theDataBuffer == NULL) {
+ SEffectContext &theContext(GetEffectContext(inEffect));
+ NVRenderContext &theRenderContext(m_UICContext->GetRenderContext());
+ QT3DSU8 *initialData = (QT3DSU8 *)theContext.m_Context.GetAllocator().allocate(
+ theBufferSize, "SEffectContext::AllocateDataBuffer", __FILE__, __LINE__);
+ NVDataRef<QT3DSU8> data((QT3DSU8 *)initialData, theBufferSize);
+ memset(initialData, 0x0L, theBufferSize);
+ if (inCommand.m_DataBufferType == NVRenderBufferBindValues::Storage) {
+ theDataBuffer = theRenderContext.CreateStorageBuffer(
+ inCommand.m_Name, qt3ds::render::NVRenderBufferUsageType::Dynamic, theBufferSize,
+ data, NULL);
+ } else if (inCommand.m_DataBufferType == NVRenderBufferBindValues::Draw_Indirect) {
+ QT3DS_ASSERT(theBufferSize == sizeof(qt3ds::render::DrawArraysIndirectCommand));
+ // init a draw call
+ QT3DSU32 *pIndirectDrawCall = (QT3DSU32 *)initialData;
+ // vertex count we draw points right now only
+ // the rest we fill in by GPU
+ pIndirectDrawCall[0] = 1;
+ theDataBuffer = theRenderContext.CreateDrawIndirectBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Dynamic, theBufferSize, data);
+ } else
+ QT3DS_ASSERT(false);
+
+ theContext.m_AllocatedDataBuffers.push_back(SAllocatedDataBufferEntry(
+ inCommand.m_Name, *theDataBuffer, inCommand.m_DataBufferType, data,
+ inCommand.m_BufferFlags));
+
+ // create wrapper buffer
+ if (inCommand.m_DataBufferWrapType == NVRenderBufferBindValues::Storage
+ && inCommand.m_WrapName && theDataBuffer) {
+ theDataWrapBuffer = theRenderContext.CreateStorageBuffer(
+ inCommand.m_WrapName, qt3ds::render::NVRenderBufferUsageType::Dynamic,
+ theBufferSize, data, theDataBuffer);
+ theContext.m_AllocatedDataBuffers.push_back(SAllocatedDataBufferEntry(
+ inCommand.m_WrapName, *theDataWrapBuffer, inCommand.m_DataBufferWrapType,
+ NVDataRef<QT3DSU8>(), inCommand.m_BufferFlags));
+ }
+ }
+ }
+
+ NVRenderTexture2D *FindTexture(SEffect &inEffect, CRegisteredString inName)
+ {
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ QT3DSU32 bufferIdx = theContext.FindBuffer(inName);
+ if (bufferIdx < theContext.m_AllocatedBuffers.size()) {
+ return theContext.m_AllocatedBuffers[bufferIdx].m_Texture;
+ }
+ }
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ NVRenderFrameBuffer *BindBuffer(SEffect &inEffect, const SBindBuffer &inCommand,
+ QT3DSMat44 &outMVP, QT3DSVec2 &outDestSize)
+ {
+ NVRenderFrameBuffer *theBuffer = NULL;
+ NVRenderTexture2D *theTexture = NULL;
+ if (inEffect.m_Context) {
+
+ SEffectContext &theContext(*inEffect.m_Context);
+ QT3DSU32 bufferIdx = theContext.FindBuffer(inCommand.m_BufferName);
+ if (bufferIdx < theContext.m_AllocatedBuffers.size()) {
+ theBuffer = theContext.m_AllocatedBuffers[bufferIdx].m_FrameBuffer;
+ theTexture = theContext.m_AllocatedBuffers[bufferIdx].m_Texture;
+ theContext.m_AllocatedBuffers[bufferIdx].m_NeedsClear = false;
+ }
+ }
+ if (theBuffer == NULL) {
+ qCCritical(INVALID_OPERATION, "Effect %s: Failed to find buffer %s for bind",
+ inEffect.m_ClassName.c_str(), inCommand.m_BufferName.c_str());
+ QT3DS_ASSERT(false);
+ outMVP = QT3DSMat44::createIdentity();
+ return NULL;
+ }
+
+ if (theTexture) {
+ SCamera::SetupOrthographicCameraForOffscreenRender(*theTexture, outMVP);
+ STextureDetails theDetails(theTexture->GetTextureDetails());
+ m_UICContext->GetRenderContext().SetViewport(
+ NVRenderRect(0, 0, (QT3DSU32)theDetails.m_Width, (QT3DSU32)theDetails.m_Height));
+ outDestSize = QT3DSVec2((QT3DSF32)theDetails.m_Width, (QT3DSF32)theDetails.m_Height);
+ }
+
+ return theBuffer;
+ }
+
+ SEffectShader *BindShader(CRegisteredString &inEffectId, const SBindShader &inCommand)
+ {
+ SEffectClass *theClass = GetEffectClass(inEffectId);
+ if (!theClass) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ bool forceCompilation = theClass->m_DynamicClass->RequiresCompilation();
+
+ eastl::pair<const TStrStrPair, NVScopedRefCounted<SEffectShader>> theInserter(
+ TStrStrPair(inCommand.m_ShaderPath, inCommand.m_ShaderDefine),
+ NVScopedRefCounted<SEffectShader>());
+ eastl::pair<TShaderMap::iterator, bool> theInsertResult(m_ShaderMap.insert(theInserter));
+
+ if (theInsertResult.second || forceCompilation) {
+ NVRenderShaderProgram *theProgram =
+ m_UICContext->GetDynamicObjectSystem()
+ .GetShaderProgram(inCommand.m_ShaderPath, inCommand.m_ShaderDefine,
+ TShaderFeatureSet(), SDynamicShaderProgramFlags(),
+ forceCompilation).first;
+ if (theProgram)
+ theInsertResult.first->second = QT3DS_NEW(m_Allocator, SEffectShader)(*theProgram);
+ }
+ if (theInsertResult.first->second) {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetActiveShader(theInsertResult.first->second->m_Shader);
+ }
+
+ return theInsertResult.first->second;
+ }
+
+ void DoApplyInstanceValue(SEffect &inEffect, QT3DSU8 *inDataPtr, CRegisteredString inPropertyName,
+ NVRenderShaderDataTypes::Enum inPropertyType,
+ NVRenderShaderProgram &inShader,
+ const SPropertyDefinition &inDefinition)
+ {
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(inPropertyName);
+ using namespace qt3ds::render;
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType() == inPropertyType) {
+ if (inPropertyType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ StaticAssert<sizeof(CRegisteredString)
+ == sizeof(NVRenderTexture2DPtr)>::valid_expression();
+ CRegisteredString *theStrPtr = reinterpret_cast<CRegisteredString *>(inDataPtr);
+ IBufferManager &theBufferManager(m_UICContext->GetBufferManager());
+ IOffscreenRenderManager &theOffscreenRenderer(
+ m_UICContext->GetOffscreenRenderManager());
+ bool needsAlphaMultiply = true;
+ NVRenderTexture2D *theTexture = NULL;
+ if (theStrPtr->IsValid()) {
+ if (theOffscreenRenderer.HasOffscreenRenderer(*theStrPtr)) {
+ SOffscreenRenderResult theResult =
+ theOffscreenRenderer.GetRenderedItem(*theStrPtr);
+ needsAlphaMultiply = false;
+ theTexture = theResult.m_Texture;
+ } else {
+ SImageTextureData theTextureData =
+ theBufferManager.LoadRenderImage(*theStrPtr);
+ needsAlphaMultiply = true;
+ theTexture = theTextureData.m_Texture;
+ }
+ }
+ GetEffectContext(inEffect).SetTexture(
+ inShader, inPropertyName, theTexture, needsAlphaMultiply,
+ m_TextureStringBuilder, m_TextureStringBuilder2, &inDefinition);
+ } else if (inPropertyType == NVRenderShaderDataTypes::NVRenderImage2DPtr) {
+ StaticAssert<sizeof(CRegisteredString)
+ == sizeof(NVRenderTexture2DPtr)>::valid_expression();
+ NVRenderImage2D *theImage = NULL;
+ GetEffectContext(inEffect).SetImage(inShader, inPropertyName, theImage);
+ } else if (inPropertyType == NVRenderShaderDataTypes::NVRenderDataBufferPtr) {
+ // we don't handle this here
+ } else {
+ switch (inPropertyType) {
+#define HANDLE_QT3DS_SHADER_DATA_TYPE(type) \
+ case NVRenderShaderDataTypes::type: \
+ inShader.SetPropertyValue(theConstant, *(reinterpret_cast<type *>(inDataPtr))); \
+ break;
+ ITERATE_QT3DS_SHADER_DATA_TYPES
+#undef HANDLE_QT3DS_SHADER_DATA_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ } else {
+ qCCritical(INVALID_OPERATION,
+ "Effect ApplyInstanceValue command datatype "
+ "and shader datatypes differ for property %s",
+ inPropertyName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ void ApplyInstanceValue(SEffect &inEffect, SEffectClass &inClass,
+ NVRenderShaderProgram &inShader, const SApplyInstanceValue &inCommand)
+ {
+ // sanity check
+ if (inCommand.m_PropertyName.IsValid()) {
+ bool canGetData =
+ inCommand.m_ValueOffset + getSizeofShaderDataType(inCommand.m_ValueType)
+ <= inEffect.m_DataSectionByteSize;
+ if (canGetData == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ QT3DSU8 *dataPtr = inEffect.GetDataSectionBegin() + inCommand.m_ValueOffset;
+ const SPropertyDefinition *theDefinition =
+ inClass.m_DynamicClass->FindPropertyByName(inCommand.m_PropertyName);
+ if (theDefinition)
+ DoApplyInstanceValue(inEffect, dataPtr, inCommand.m_PropertyName,
+ inCommand.m_ValueType, inShader, *theDefinition);
+ } else {
+ NVConstDataRef<SPropertyDefinition> theDefs = inClass.m_DynamicClass->GetProperties();
+ for (QT3DSU32 idx = 0, end = theDefs.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(theDefs[idx]);
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(theDefinition.m_Name);
+
+ // This is fine, the property wasn't found and we continue, no problem.
+ if (!theConstant)
+ continue;
+ QT3DSU8 *dataPtr = inEffect.GetDataSectionBegin() + theDefinition.m_Offset;
+ DoApplyInstanceValue(inEffect, dataPtr, theDefinition.m_Name,
+ theDefinition.m_DataType, inShader, theDefinition);
+ }
+ }
+ }
+
+ void ApplyValue(SEffect &inEffect, SEffectClass &inClass, NVRenderShaderProgram &inShader,
+ const SApplyValue &inCommand)
+ {
+ if (inCommand.m_PropertyName.IsValid()) {
+ QT3DSU8 *dataPtr = inCommand.m_Value.mData;
+ const SPropertyDefinition *theDefinition =
+ inClass.m_DynamicClass->FindPropertyByName(inCommand.m_PropertyName);
+ if (theDefinition)
+ DoApplyInstanceValue(inEffect, dataPtr, inCommand.m_PropertyName,
+ inCommand.m_ValueType, inShader, *theDefinition);
+ }
+ }
+
+ bool ApplyBlending(const SApplyBlending &inCommand)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+
+ theContext.SetBlendingEnabled(true);
+
+ qt3ds::render::NVRenderBlendFunctionArgument blendFunc =
+ qt3ds::render::NVRenderBlendFunctionArgument(
+ inCommand.m_SrcBlendFunc, inCommand.m_DstBlendFunc, inCommand.m_SrcBlendFunc,
+ inCommand.m_DstBlendFunc);
+
+ qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add,
+ NVRenderBlendEquation::Add);
+
+ theContext.SetBlendFunction(blendFunc);
+ theContext.SetBlendEquation(blendEqu);
+
+ return true;
+ }
+
+ // This has the potential to change the source texture for the current render pass
+ SEffectTextureData ApplyBufferValue(SEffect &inEffect, NVRenderShaderProgram &inShader,
+ const SApplyBufferValue &inCommand,
+ NVRenderTexture2D &inSourceTexture,
+ SEffectTextureData inCurrentSourceTexture)
+ {
+ SEffectTextureData theTextureToBind;
+ if (inCommand.m_BufferName.IsValid()) {
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ QT3DSU32 bufferIdx = theContext.FindBuffer(inCommand.m_BufferName);
+ if (bufferIdx < theContext.m_AllocatedBuffers.size()) {
+ SAllocatedBufferEntry &theEntry(theContext.m_AllocatedBuffers[bufferIdx]);
+ if (theEntry.m_NeedsClear) {
+ NVRenderContext &theRenderContext(m_UICContext->GetRenderContext());
+
+ theRenderContext.SetRenderTarget(theEntry.m_FrameBuffer);
+ // Note that depth/stencil buffers need an explicit clear in their bind
+ // commands in order to ensure
+ // we clear the least amount of information possible.
+
+ if (theEntry.m_Texture) {
+ NVRenderTextureFormats::Enum theTextureFormat =
+ theEntry.m_Texture->GetTextureDetails().m_Format;
+ if (theTextureFormat != NVRenderTextureFormats::Depth16
+ && theTextureFormat != NVRenderTextureFormats::Depth24
+ && theTextureFormat != NVRenderTextureFormats::Depth32
+ && theTextureFormat != NVRenderTextureFormats::Depth24Stencil8) {
+ NVRenderContextScopedProperty<QT3DSVec4> __clearColor(
+ theRenderContext, &NVRenderContext::GetClearColor,
+ &NVRenderContext::SetClearColor, QT3DSVec4(0.0f));
+ theRenderContext.Clear(qt3ds::render::NVRenderClearValues::Color);
+ }
+ }
+ theEntry.m_NeedsClear = false;
+ }
+ theTextureToBind = SEffectTextureData(theEntry.m_Texture, false);
+ }
+ }
+ if (theTextureToBind.m_Texture == NULL) {
+ QT3DS_ASSERT(false);
+ qCCritical(INVALID_OPERATION, "Effect %s: Failed to find buffer %s for bind",
+ inEffect.m_ClassName.c_str(), inCommand.m_BufferName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ } else // no name means bind the source
+ theTextureToBind = SEffectTextureData(&inSourceTexture, false);
+
+ if (inCommand.m_ParamName.IsValid()) {
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(inCommand.m_ParamName);
+
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType()
+ != NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ qCCritical(INVALID_OPERATION,
+ "Effect %s: Binding buffer to parameter %s that is not a texture",
+ inEffect.m_ClassName.c_str(), inCommand.m_ParamName.c_str());
+ QT3DS_ASSERT(false);
+ } else {
+ GetEffectContext(inEffect).SetTexture(
+ inShader, inCommand.m_ParamName, theTextureToBind.m_Texture,
+ theTextureToBind.m_NeedsAlphaMultiply, m_TextureStringBuilder,
+ m_TextureStringBuilder2);
+ }
+ }
+ return inCurrentSourceTexture;
+ } else {
+ return theTextureToBind;
+ }
+ }
+
+ void ApplyDepthValue(SEffect &inEffect, NVRenderShaderProgram &inShader,
+ const SApplyDepthValue &inCommand, NVRenderTexture2D *inTexture)
+ {
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(inCommand.m_ParamName);
+
+ if (theConstant) {
+ if (theConstant->GetShaderConstantType()
+ != NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ qCCritical(INVALID_OPERATION,
+ "Effect %s: Binding buffer to parameter %s that is not a texture",
+ inEffect.m_ClassName.c_str(), inCommand.m_ParamName.c_str());
+ QT3DS_ASSERT(false);
+ } else {
+ GetEffectContext(inEffect).SetTexture(inShader, inCommand.m_ParamName, inTexture,
+ false, m_TextureStringBuilder,
+ m_TextureStringBuilder2);
+ }
+ }
+ }
+
+ void ApplyImageValue(SEffect &inEffect, NVRenderShaderProgram &inShader,
+ const SApplyImageValue &inCommand)
+ {
+ SAllocatedImageEntry theImageToBind;
+ if (inCommand.m_ImageName.IsValid()) {
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ QT3DSU32 bufferIdx = theContext.FindImage(inCommand.m_ImageName);
+ if (bufferIdx < theContext.m_AllocatedImages.size()) {
+ theImageToBind = SAllocatedImageEntry(theContext.m_AllocatedImages[bufferIdx]);
+ }
+ }
+ }
+
+ if (theImageToBind.m_Image == NULL) {
+ qCCritical(INVALID_OPERATION, "Effect %s: Failed to find image %s for bind",
+ inEffect.m_ClassName.c_str(), inCommand.m_ImageName.c_str());
+ QT3DS_ASSERT(false);
+ }
+
+ if (inCommand.m_ParamName.IsValid()) {
+ qt3ds::render::NVRenderShaderConstantBase *theConstant =
+ inShader.GetShaderConstant(inCommand.m_ParamName);
+
+ if (theConstant) {
+ if (inCommand.m_NeedSync) {
+ NVRenderBufferBarrierFlags flags(
+ qt3ds::render::NVRenderBufferBarrierValues::TextureFetch
+ | qt3ds::render::NVRenderBufferBarrierValues::TextureUpdate);
+ inShader.GetRenderContext().SetMemoryBarrier(flags);
+ }
+
+ if (theConstant->GetShaderConstantType()
+ == NVRenderShaderDataTypes::NVRenderImage2DPtr
+ && !inCommand.m_BindAsTexture) {
+ GetEffectContext(inEffect).SetImage(inShader, inCommand.m_ParamName,
+ theImageToBind.m_Image);
+ } else if (theConstant->GetShaderConstantType()
+ == NVRenderShaderDataTypes::NVRenderTexture2DPtr
+ && inCommand.m_BindAsTexture) {
+ GetEffectContext(inEffect).SetTexture(
+ inShader, inCommand.m_ParamName, theImageToBind.m_Texture, false,
+ m_TextureStringBuilder, m_TextureStringBuilder2);
+ } else {
+ qCCritical(INVALID_OPERATION,
+ "Effect %s: Binding buffer to parameter %s that is not a texture",
+ inEffect.m_ClassName.c_str(), inCommand.m_ParamName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+
+ void ApplyDataBufferValue(SEffect &inEffect, NVRenderShaderProgram &inShader,
+ const SApplyDataBufferValue &inCommand)
+ {
+ SAllocatedDataBufferEntry theBufferToBind;
+ if (inCommand.m_ParamName.IsValid()) {
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ QT3DSU32 bufferIdx = theContext.FindDataBuffer(inCommand.m_ParamName);
+ if (bufferIdx < theContext.m_AllocatedDataBuffers.size()) {
+ theBufferToBind =
+ SAllocatedDataBufferEntry(theContext.m_AllocatedDataBuffers[bufferIdx]);
+ if (theBufferToBind.m_NeedsClear) {
+ NVDataRef<QT3DSU8> pData = theBufferToBind.m_DataBuffer->MapBuffer();
+ memset(pData.begin(), 0x0L, theBufferToBind.m_BufferData.size());
+ theBufferToBind.m_DataBuffer->UnmapBuffer();
+ theBufferToBind.m_NeedsClear = false;
+ }
+ }
+ }
+
+ if (theBufferToBind.m_DataBuffer == NULL) {
+ qCCritical(INVALID_OPERATION, "Effect %s: Failed to find buffer %s for bind",
+ inEffect.m_ClassName.c_str(), inCommand.m_ParamName.c_str());
+ QT3DS_ASSERT(false);
+ }
+
+ qt3ds::render::NVRenderShaderBufferBase *theConstant =
+ inShader.GetShaderBuffer(inCommand.m_ParamName);
+
+ if (theConstant) {
+ GetEffectContext(inEffect).SetDataBuffer(inShader, inCommand.m_ParamName,
+ theBufferToBind.m_DataBuffer);
+ } else if (theBufferToBind.m_BufferType
+ == qt3ds::render::NVRenderBufferBindValues::Draw_Indirect) {
+ // since we filled part of this buffer on the GPU we need a sync before usage
+ NVRenderBufferBarrierFlags flags(
+ qt3ds::render::NVRenderBufferBarrierValues::CommandBuffer);
+ inShader.GetRenderContext().SetMemoryBarrier(flags);
+ }
+ }
+ }
+
+ void ApplyRenderStateValue(NVRenderFrameBuffer *inTarget,
+ NVRenderTexture2D *inDepthStencilTexture,
+ const SApplyRenderState &theCommand)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ QT3DSU32 inState = (QT3DSU32)theCommand.m_RenderState;
+ bool inEnable = theCommand.m_Enabled;
+
+ switch (inState) {
+ case NVRenderState::StencilTest: {
+ if (inEnable && inTarget) {
+ inTarget->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ *inDepthStencilTexture);
+ } else if (inTarget) {
+ inTarget->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ NVRenderTextureOrRenderBuffer());
+ }
+
+ theContext.SetStencilTestEnabled(inEnable);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ static bool CompareDepthStencilState(NVRenderDepthStencilState &inState,
+ SDepthStencil &inStencil)
+ {
+ qt3ds::render::NVRenderStencilFunctionArgument theFunction =
+ inState.GetStencilFunc(qt3ds::render::NVRenderFaces::Front);
+ qt3ds::render::NVRenderStencilOperationArgument theOperation =
+ inState.GetStencilOp(qt3ds::render::NVRenderFaces::Front);
+
+ return theFunction.m_Function == inStencil.m_StencilFunction
+ && theFunction.m_Mask == inStencil.m_Mask
+ && theFunction.m_ReferenceValue == inStencil.m_Reference
+ && theOperation.m_StencilFail == inStencil.m_StencilFailOperation
+ && theOperation.m_DepthFail == inStencil.m_DepthFailOperation
+ && theOperation.m_DepthPass == inStencil.m_DepthPassOperation;
+ }
+
+ void RenderPass(SEffectShader &inShader, const QT3DSMat44 &inMVP,
+ SEffectTextureData inSourceTexture, NVRenderFrameBuffer *inFrameBuffer,
+ QT3DSVec2 &inDestSize, const QT3DSVec2 &inCameraClipRange,
+ NVRenderTexture2D *inDepthStencil, Option<SDepthStencil> inDepthStencilCommand,
+ bool drawIndirect)
+ {
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ theContext.SetRenderTarget(inFrameBuffer);
+ if (inDepthStencil && inFrameBuffer) {
+ inFrameBuffer->Attach(NVRenderFrameBufferAttachments::DepthStencil, *inDepthStencil);
+ if (inDepthStencilCommand.hasValue()) {
+ SDepthStencil &theDepthStencil(*inDepthStencilCommand);
+ QT3DSU32 clearFlags = 0;
+ if (theDepthStencil.m_Flags.HasClearStencil())
+ clearFlags |= NVRenderClearValues::Stencil;
+ if (theDepthStencil.m_Flags.HasClearDepth())
+ clearFlags |= NVRenderClearValues::Depth;
+
+ if (clearFlags)
+ theContext.Clear(qt3ds::render::NVRenderClearFlags(clearFlags));
+
+ NVRenderDepthStencilState *targetState = NULL;
+ for (QT3DSU32 idx = 0, end = m_DepthStencilStates.size();
+ idx < end && targetState == NULL; ++idx) {
+ NVRenderDepthStencilState &theState = *m_DepthStencilStates[idx];
+ if (CompareDepthStencilState(theState, theDepthStencil))
+ targetState = &theState;
+ }
+ if (targetState == NULL) {
+ qt3ds::render::NVRenderStencilFunctionArgument theFunctionArg(
+ theDepthStencil.m_StencilFunction, theDepthStencil.m_Reference,
+ theDepthStencil.m_Mask);
+ qt3ds::render::NVRenderStencilOperationArgument theOpArg(
+ theDepthStencil.m_StencilFailOperation,
+ theDepthStencil.m_DepthFailOperation, theDepthStencil.m_DepthPassOperation);
+ targetState = theContext.CreateDepthStencilState(
+ theContext.IsDepthTestEnabled(), theContext.IsDepthWriteEnabled(),
+ theContext.GetDepthFunction(), true, theFunctionArg, theFunctionArg,
+ theOpArg, theOpArg);
+ m_DepthStencilStates.push_back(targetState);
+ }
+ theContext.SetDepthStencilState(targetState);
+ }
+ }
+
+ theContext.SetActiveShader(inShader.m_Shader);
+ inShader.m_MVP.Set(inMVP);
+ if (inSourceTexture.m_Texture) {
+ inShader.m_TextureEntry.Set(inSourceTexture.m_Texture,
+ inSourceTexture.m_NeedsAlphaMultiply, NULL);
+ } else {
+ qCCritical(INTERNAL_ERROR, "Failed to setup pass due to null source texture");
+ QT3DS_ASSERT(false);
+ }
+ inShader.m_FragColorAlphaSettings.Set(QT3DSVec2(1.0f, 0.0f));
+ inShader.m_DestSize.Set(inDestSize);
+ if (inShader.m_AppFrame.IsValid())
+ inShader.m_AppFrame.Set((QT3DSF32)m_UICContext->GetFrameCount());
+ if (inShader.m_FPS.IsValid())
+ inShader.m_FPS.Set((QT3DSF32)m_UICContext->GetFPS().first);
+ if (inShader.m_CameraClipRange.IsValid())
+ inShader.m_CameraClipRange.Set(inCameraClipRange);
+
+ if (!drawIndirect)
+ m_UICContext->GetRenderer().RenderQuad();
+ else
+ m_UICContext->GetRenderer().RenderPointsIndirect();
+
+ if (inDepthStencil && inFrameBuffer) {
+ inFrameBuffer->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ NVRenderTextureOrRenderBuffer());
+ theContext.SetDepthStencilState(m_DefaultStencilState);
+ }
+ }
+
+ void DoRenderEffect(SEffect &inEffect, SEffectClass &inClass,
+ NVRenderTexture2D &inSourceTexture, QT3DSMat44 &inMVP,
+ NVRenderFrameBuffer *inTarget, bool inEnableBlendWhenRenderToTarget,
+ NVRenderTexture2D *inDepthTexture, NVRenderTexture2D *inDepthStencilTexture,
+ const QT3DSVec2 inCameraClipRange)
+ {
+ // Run through the effect commands and render the effect.
+ // NVRenderTexture2D* theCurrentTexture(&inSourceTexture);
+ NVRenderContext &theContext = m_UICContext->GetRenderContext();
+
+ // Context variables that are updated during the course of a pass.
+ SEffectTextureData theCurrentSourceTexture(&inSourceTexture, false);
+ NVRenderTexture2D *theCurrentDepthStencilTexture = NULL;
+ NVRenderFrameBuffer *theCurrentRenderTarget(inTarget);
+ SEffectShader *theCurrentShader(NULL);
+ NVRenderRect theOriginalViewport(theContext.GetViewport());
+ bool wasScissorEnabled = theContext.IsScissorTestEnabled();
+ bool wasBlendingEnabled = theContext.IsBlendingEnabled();
+ // save current blending setup
+ qt3ds::render::NVRenderBlendFunctionArgument theBlendFunc = theContext.GetBlendFunction();
+ qt3ds::render::NVRenderBlendEquationArgument theBlendEqu = theContext.GetBlendEquation();
+ bool intermediateBlendingEnabled = false;
+ STextureDetails theDetails(inSourceTexture.GetTextureDetails());
+ QT3DSU32 theFinalWidth = (QT3DSU32)(theDetails.m_Width);
+ QT3DSU32 theFinalHeight = (QT3DSU32)(theDetails.m_Height);
+ QT3DSVec2 theDestSize;
+ {
+ // Ensure no matter the command run goes we replace the rendering system to some
+ // semblance of the approprate
+ // setting.
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __framebuffer(
+ theContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport);
+ NVRenderContextScopedProperty<bool> __scissorEnabled(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled);
+ NVRenderContextScopedProperty<bool> __stencilTest(
+ theContext, &NVRenderContext::IsStencilTestEnabled,
+ &NVRenderContext::SetStencilTestEnabled);
+ NVRenderContextScopedProperty<qt3ds::render::NVRenderBoolOp::Enum> __depthFunction(
+ theContext, &NVRenderContext::GetDepthFunction, &NVRenderContext::SetDepthFunction);
+ Option<SDepthStencil> theCurrentDepthStencil;
+
+ theContext.SetScissorTestEnabled(false);
+ theContext.SetBlendingEnabled(false);
+ theContext.SetCullingEnabled(false);
+ theContext.SetDepthTestEnabled(false);
+ theContext.SetDepthWriteEnabled(false);
+
+ QT3DSMat44 theMVP(QT3DSMat44::createIdentity());
+ NVConstDataRef<dynamic::SCommand *> theCommands =
+ inClass.m_DynamicClass->GetRenderCommands();
+ for (QT3DSU32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd;
+ ++commandIdx) {
+ const SCommand &theCommand(*theCommands[commandIdx]);
+ switch (theCommand.m_Type) {
+ case CommandTypes::AllocateBuffer:
+ AllocateBuffer(inEffect, static_cast<const SAllocateBuffer &>(theCommand),
+ theFinalWidth, theFinalHeight, theDetails.m_Format);
+ break;
+
+ case CommandTypes::AllocateImage:
+ AllocateImage(inEffect, static_cast<const SAllocateImage &>(theCommand),
+ theFinalWidth, theFinalHeight);
+ break;
+
+ case CommandTypes::AllocateDataBuffer:
+ AllocateDataBuffer(inEffect,
+ static_cast<const SAllocateDataBuffer &>(theCommand));
+ break;
+
+ case CommandTypes::BindBuffer:
+ theCurrentRenderTarget =
+ BindBuffer(inEffect, static_cast<const SBindBuffer &>(theCommand), theMVP,
+ theDestSize);
+ break;
+
+ case CommandTypes::BindTarget: {
+ m_UICContext->GetRenderContext().SetRenderTarget(inTarget);
+ theCurrentRenderTarget = inTarget;
+ theMVP = inMVP;
+ theContext.SetViewport(theOriginalViewport);
+ theDestSize = QT3DSVec2((QT3DSF32)theFinalWidth, (QT3DSF32)theFinalHeight);
+ // This isn't necessary if we are rendering to an offscreen buffer and not
+ // compositing
+ // with other objects.
+ if (inEnableBlendWhenRenderToTarget) {
+ theContext.SetBlendingEnabled(wasBlendingEnabled);
+ theContext.SetScissorTestEnabled(wasScissorEnabled);
+ // The blending setup was done before we apply the effect
+ theContext.SetBlendFunction(theBlendFunc);
+ theContext.SetBlendEquation(theBlendEqu);
+ }
+ } break;
+ case CommandTypes::BindShader:
+ theCurrentShader = BindShader(inEffect.m_ClassName,
+ static_cast<const SBindShader &>(theCommand));
+ break;
+ case CommandTypes::ApplyInstanceValue:
+ if (theCurrentShader)
+ ApplyInstanceValue(inEffect, inClass, *theCurrentShader->m_Shader,
+ static_cast<const SApplyInstanceValue &>(theCommand));
+ break;
+ case CommandTypes::ApplyValue:
+ if (theCurrentShader)
+ ApplyValue(inEffect, inClass, *theCurrentShader->m_Shader,
+ static_cast<const SApplyValue &>(theCommand));
+ break;
+ case CommandTypes::ApplyBlending:
+ intermediateBlendingEnabled =
+ ApplyBlending(static_cast<const SApplyBlending &>(theCommand));
+ break;
+ case CommandTypes::ApplyBufferValue:
+ if (theCurrentShader)
+ theCurrentSourceTexture =
+ ApplyBufferValue(inEffect, *theCurrentShader->m_Shader,
+ static_cast<const SApplyBufferValue &>(theCommand),
+ inSourceTexture, theCurrentSourceTexture);
+ break;
+ case CommandTypes::ApplyDepthValue:
+ if (theCurrentShader)
+ ApplyDepthValue(inEffect, *theCurrentShader->m_Shader,
+ static_cast<const SApplyDepthValue &>(theCommand),
+ inDepthTexture);
+ if (!inDepthTexture) {
+ qCCritical(INVALID_OPERATION,
+ "Depth value command detected but no "
+ "depth buffer provided for effect %s",
+ inEffect.m_ClassName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case CommandTypes::ApplyImageValue:
+ if (theCurrentShader)
+ ApplyImageValue(inEffect, *theCurrentShader->m_Shader,
+ static_cast<const SApplyImageValue &>(theCommand));
+ break;
+ case CommandTypes::ApplyDataBufferValue:
+ if (theCurrentShader)
+ ApplyDataBufferValue(
+ inEffect, *theCurrentShader->m_Shader,
+ static_cast<const SApplyDataBufferValue &>(theCommand));
+ break;
+ case CommandTypes::DepthStencil: {
+ const SDepthStencil &theDepthStencil =
+ static_cast<const SDepthStencil &>(theCommand);
+ theCurrentDepthStencilTexture =
+ FindTexture(inEffect, theDepthStencil.m_BufferName);
+ if (theCurrentDepthStencilTexture)
+ theCurrentDepthStencil = theDepthStencil;
+ } break;
+ case CommandTypes::Render:
+ if (theCurrentShader && theCurrentSourceTexture.m_Texture) {
+ RenderPass(*theCurrentShader, theMVP, theCurrentSourceTexture,
+ theCurrentRenderTarget, theDestSize, inCameraClipRange,
+ theCurrentDepthStencilTexture, theCurrentDepthStencil,
+ static_cast<const SRender &>(theCommand).m_DrawIndirect);
+ }
+ // Reset the source texture regardless
+ theCurrentSourceTexture = SEffectTextureData(&inSourceTexture, false);
+ theCurrentDepthStencilTexture = NULL;
+ theCurrentDepthStencil = Option<SDepthStencil>();
+ // reset intermediate blending state
+ if (intermediateBlendingEnabled) {
+ theContext.SetBlendingEnabled(false);
+ intermediateBlendingEnabled = false;
+ }
+ break;
+ case CommandTypes::ApplyRenderState:
+ ApplyRenderStateValue(theCurrentRenderTarget, inDepthStencilTexture,
+ static_cast<const SApplyRenderState &>(theCommand));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ SetEffectRequiresCompilation(inEffect.m_ClassName, false);
+
+ // reset to default stencil state
+ if (inDepthStencilTexture) {
+ theContext.SetDepthStencilState(m_DefaultStencilState);
+ }
+
+ // Release any per-frame buffers
+ if (inEffect.m_Context) {
+ SEffectContext &theContext(*inEffect.m_Context);
+ // Query for size on every loop intentional
+ for (QT3DSU32 idx = 0; idx < theContext.m_AllocatedBuffers.size(); ++idx) {
+ if (theContext.m_AllocatedBuffers[idx].m_Flags.IsSceneLifetime() == false) {
+ theContext.ReleaseBuffer(idx);
+ --idx;
+ }
+ }
+ for (QT3DSU32 idx = 0; idx < theContext.m_AllocatedImages.size(); ++idx) {
+ if (theContext.m_AllocatedImages[idx].m_Flags.IsSceneLifetime() == false) {
+ theContext.ReleaseImage(idx);
+ --idx;
+ }
+ }
+ }
+ }
+ }
+
+ NVRenderTexture2D *RenderEffect(SEffectRenderArgument inRenderArgument) override
+ {
+ SEffectClass *theClass = GetEffectClass(inRenderArgument.m_Effect.m_ClassName);
+ if (!theClass) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ QT3DSMat44 theMVP;
+ SCamera::SetupOrthographicCameraForOffscreenRender(inRenderArgument.m_ColorBuffer, theMVP);
+ // setup a render target
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+ IResourceManager &theManager(m_UICContext->GetResourceManager());
+ NVRenderContextScopedProperty<NVRenderFrameBuffer *> __framebuffer(
+ theContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
+ STextureDetails theDetails(inRenderArgument.m_ColorBuffer.GetTextureDetails());
+ QT3DSU32 theFinalWidth = ITextRenderer::NextMultipleOf4((QT3DSU32)(theDetails.m_Width));
+ QT3DSU32 theFinalHeight = ITextRenderer::NextMultipleOf4((QT3DSU32)(theDetails.m_Height));
+ NVRenderFrameBuffer *theBuffer = theManager.AllocateFrameBuffer();
+ // UdoL Some Effects may need to run before HDR tonemap. This means we need to keep the
+ // input format
+ NVRenderTextureFormats::Enum theOutputFormat = NVRenderTextureFormats::RGBA8;
+ if (theClass->m_DynamicClass->GetOutputTextureFormat() == NVRenderTextureFormats::Unknown)
+ theOutputFormat = theDetails.m_Format;
+ NVRenderTexture2D *theTargetTexture =
+ theManager.AllocateTexture2D(theFinalWidth, theFinalHeight, theOutputFormat);
+ theBuffer->Attach(NVRenderFrameBufferAttachments::Color0, *theTargetTexture);
+ theContext.SetRenderTarget(theBuffer);
+ NVRenderContextScopedProperty<NVRenderRect> __viewport(
+ theContext, &NVRenderContext::GetViewport, &NVRenderContext::SetViewport,
+ NVRenderRect(0, 0, theFinalWidth, theFinalHeight));
+
+ NVRenderContextScopedProperty<bool> __scissorEnable(
+ theContext, &NVRenderContext::IsScissorTestEnabled,
+ &NVRenderContext::SetScissorTestEnabled, false);
+
+ DoRenderEffect(inRenderArgument.m_Effect, *theClass, inRenderArgument.m_ColorBuffer, theMVP,
+ m_UICContext->GetRenderContext().GetRenderTarget(), false,
+ inRenderArgument.m_DepthTexture, inRenderArgument.m_DepthStencilBuffer,
+ inRenderArgument.m_CameraClipRange);
+
+ theBuffer->Attach(NVRenderFrameBufferAttachments::Color0, NVRenderTextureOrRenderBuffer());
+ theManager.Release(*theBuffer);
+ return theTargetTexture;
+ }
+
+ // Render the effect to the currently bound render target using this MVP
+ bool RenderEffect(SEffectRenderArgument inRenderArgument, QT3DSMat44 &inMVP,
+ bool inEnableBlendWhenRenderToTarget) override
+ {
+ SEffectClass *theClass = GetEffectClass(inRenderArgument.m_Effect.m_ClassName);
+ if (!theClass) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ DoRenderEffect(inRenderArgument.m_Effect, *theClass, inRenderArgument.m_ColorBuffer, inMVP,
+ m_UICContext->GetRenderContext().GetRenderTarget(),
+ inEnableBlendWhenRenderToTarget, inRenderArgument.m_DepthTexture,
+ inRenderArgument.m_DepthStencilBuffer, inRenderArgument.m_CameraClipRange);
+ return true;
+ }
+
+ void ReleaseEffectContext(SEffectContext *inContext) override
+ {
+ if (inContext == NULL)
+ return;
+ for (QT3DSU32 idx = 0, end = m_Contexts.size(); idx < end; ++idx) {
+ if (m_Contexts[idx] == inContext) {
+ m_Contexts.replace_with_last(idx);
+ NVDelete(m_Allocator, inContext);
+ }
+ }
+ }
+
+ void ResetEffectFrameData(SEffectContext &inContext) override
+ { // Query for size on every loop intentional
+ for (QT3DSU32 idx = 0; idx < inContext.m_AllocatedBuffers.size(); ++idx) {
+ SAllocatedBufferEntry &theBuffer(inContext.m_AllocatedBuffers[idx]);
+ if (theBuffer.m_Flags.IsSceneLifetime() == true)
+ theBuffer.m_NeedsClear = true;
+ }
+ for (QT3DSU32 idx = 0; idx < inContext.m_AllocatedDataBuffers.size(); ++idx) {
+ SAllocatedDataBufferEntry &theDataBuffer(inContext.m_AllocatedDataBuffers[idx]);
+ if (theDataBuffer.m_Flags.IsSceneLifetime() == true)
+ theDataBuffer.m_NeedsClear = true;
+ }
+ }
+
+ void SetShaderData(CRegisteredString path, const char8_t *data,
+ const char8_t *inShaderType, const char8_t *inShaderVersion,
+ bool inHasGeomShader, bool inIsComputeShader) override
+ {
+ m_CoreContext.GetDynamicObjectSystemCore().SetShaderData(
+ path, data, inShaderType, inShaderVersion, inHasGeomShader, inIsComputeShader);
+ }
+
+ void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap, const char8_t *inProjectDir) const override
+ {
+ ioBuffer.write((QT3DSU32)m_EffectClasses.size());
+ SStringSaveRemapper theRemapper(m_Allocator, inRemapMap, inProjectDir,
+ m_CoreContext.GetStringTable());
+ for (TEffectClassMap::const_iterator theIter = m_EffectClasses.begin(),
+ end = m_EffectClasses.end();
+ theIter != end; ++theIter) {
+ const SEffectClass &theClass = *theIter->second;
+ CRegisteredString theClassName = theClass.m_DynamicClass->GetId();
+ theClassName.Remap(inRemapMap);
+ ioBuffer.write(theClassName);
+ // Effect classes do not store any additional data from the dynamic object class.
+ ioBuffer.write(theClass);
+ }
+ }
+
+ void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t *inProjectDir) override
+ {
+ m_Allocator.m_PreAllocatedBlock = inData;
+ m_Allocator.m_OwnsMemory = false;
+ qt3ds::render::SDataReader theReader(inData.begin(), inData.end());
+ QT3DSU32 numEffectClasses = theReader.LoadRef<QT3DSU32>();
+ SStringLoadRemapper theRemapper(m_Allocator, inStrDataBlock, inProjectDir,
+ m_CoreContext.GetStringTable());
+ for (QT3DSU32 idx = 0, end = numEffectClasses; idx < end; ++idx) {
+ CRegisteredString theClassName = theReader.LoadRef<CRegisteredString>();
+ theClassName.Remap(inStrDataBlock);
+ IDynamicObjectClass *theBaseClass =
+ m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(theClassName);
+ if (theBaseClass == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SEffectClass *theClass = theReader.Load<SEffectClass>();
+ theClass->SetupThisObjectFromMemory(m_Allocator, *theBaseClass);
+ NVScopedRefCounted<SEffectClass> theClassPtr(theClass);
+ m_EffectClasses.insert(eastl::make_pair(theBaseClass->GetId(), theClassPtr));
+ }
+ }
+
+ IEffectSystem &GetEffectSystem(IUICRenderContext &context) override
+ {
+ m_UICContext = &context;
+
+ NVRenderContext &theContext(m_UICContext->GetRenderContext());
+
+ m_ResourceManager = &IResourceManager::CreateResourceManager(theContext);
+
+ // create default stencil state
+ qt3ds::render::NVRenderStencilFunctionArgument stencilDefaultFunc(
+ qt3ds::render::NVRenderBoolOp::AlwaysTrue, 0x0, 0xFF);
+ qt3ds::render::NVRenderStencilOperationArgument stencilDefaultOp(
+ qt3ds::render::NVRenderStencilOp::Keep, qt3ds::render::NVRenderStencilOp::Keep,
+ qt3ds::render::NVRenderStencilOp::Keep);
+ m_DefaultStencilState = theContext.CreateDepthStencilState(
+ theContext.IsDepthTestEnabled(), theContext.IsDepthWriteEnabled(),
+ theContext.GetDepthFunction(), theContext.IsStencilTestEnabled(), stencilDefaultFunc,
+ stencilDefaultFunc, stencilDefaultOp, stencilDefaultOp);
+
+ return *this;
+ }
+
+ IResourceManager &GetResourceManager() override
+ {
+ return *m_ResourceManager;
+ }
+};
+}
+
+IEffectSystemCore &IEffectSystemCore::CreateEffectSystemCore(IUICRenderContextCore &inContext)
+{
+ return *QT3DS_NEW(inContext.GetAllocator(), SEffectSystem)(inContext);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderEulerAngles.cpp b/src/Runtime/Source/UICRender/Source/UICRenderEulerAngles.cpp
new file mode 100644
index 00000000..e176c75f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderEulerAngles.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//==============================================================================
+// Includes
+//==============================================================================
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include "UICRenderEulerAngles.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4365) // warnings on conversion from unsigned int to int
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace uic {
+namespace render {
+
+ //==============================================================================
+ /**
+ * Constructor
+ */
+ CEulerAngleConverter::CEulerAngleConverter() { m_OrderInfoBuffer[0] = '\0'; }
+
+ //==============================================================================
+ /**
+ * Destructor
+ */
+ CEulerAngleConverter::~CEulerAngleConverter() {}
+
+ //==============================================================================
+ /**
+ * Constructs a Euler angle & holds it in a EulerAngles struct
+ * @param theI x rotation ( radians )
+ * @param theJ y rotation ( radians )
+ * @param theH z rotation ( radians )
+ * @param theOrder the order this angle is in namely XYZ( static ), etc.
+ * use the EulOrd**** macros to generate values
+ * 0 to 23 is valid
+ * @return the euler angle
+ */
+ EulerAngles CEulerAngleConverter::Eul_(float theI, float theJ, float theH, int theOrder)
+ {
+ EulerAngles theEulerAngle;
+ theEulerAngle.x = theI;
+ theEulerAngle.y = theJ;
+ theEulerAngle.z = theH;
+ theEulerAngle.w = (float)theOrder;
+ return theEulerAngle;
+ }
+
+ //==============================================================================
+ /**
+ * Construct quaternion from Euler angles (in radians).
+ * @param theEulerAngle incoming angle( radians )
+ * @return the Quaternion
+ */
+ Quat CEulerAngleConverter::Eul_ToQuat(EulerAngles theEulerAngle)
+ {
+ Quat theQuaternion;
+ double a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+
+ EulGetOrd((unsigned int)theEulerAngle.w, i, j, k, h, n, s, f);
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+
+ if (n == EulParOdd)
+ theEulerAngle.y = -theEulerAngle.y;
+
+ ti = theEulerAngle.x * 0.5;
+ tj = theEulerAngle.y * 0.5;
+ th = theEulerAngle.z * 0.5;
+
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == EulRepYes) {
+ a[i] = cj * (cs + sc); /* Could speed up with */
+ a[j] = sj * (cc + ss); /* trig identities. */
+ a[k] = sj * (cs - sc);
+ theQuaternion.w = (float)(cj * (cc - ss));
+ } else {
+ a[i] = cj * sc - sj * cs;
+ a[j] = cj * ss + sj * cc;
+ a[k] = cj * cs - sj * sc;
+ theQuaternion.w = (float)(cj * cc + sj * ss);
+ }
+ if (n == EulParOdd)
+ a[j] = -a[j];
+
+ theQuaternion.x = (float)a[X];
+ theQuaternion.y = (float)a[Y];
+ theQuaternion.z = (float)a[Z];
+ return theQuaternion;
+ }
+
+ //==============================================================================
+ /**
+ * Construct matrix from Euler angles (in radians).
+ * @param theEulerAngle incoming angle
+ * @param theMatrix outgoing matrix
+ */
+ void CEulerAngleConverter::Eul_ToHMatrix(EulerAngles theEulerAngle, HMatrix theMatrix)
+ {
+ double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+ EulGetOrd((unsigned int)theEulerAngle.w, i, j, k, h, n, s, f);
+
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+
+ if (n == EulParOdd) {
+ theEulerAngle.x = -theEulerAngle.x;
+ theEulerAngle.y = -theEulerAngle.y;
+ theEulerAngle.z = -theEulerAngle.z;
+ }
+
+ ti = theEulerAngle.x;
+ tj = theEulerAngle.y;
+ th = theEulerAngle.z;
+
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == EulRepYes) {
+ theMatrix[i][i] = (float)cj;
+ theMatrix[i][j] = (float)(sj * si);
+ theMatrix[i][k] = (float)(sj * ci);
+ theMatrix[j][i] = (float)(sj * sh);
+ theMatrix[j][j] = (float)(-cj * ss + cc);
+ theMatrix[j][k] = (float)(-cj * cs - sc);
+ theMatrix[k][i] = (float)(-sj * ch);
+ theMatrix[k][j] = (float)(cj * sc + cs);
+ theMatrix[k][k] = (float)(cj * cc - ss);
+ } else {
+ theMatrix[i][i] = (float)(cj * ch);
+ theMatrix[i][j] = (float)(sj * sc - cs);
+ theMatrix[i][k] = (float)(sj * cc + ss);
+ theMatrix[j][i] = (float)(cj * sh);
+ theMatrix[j][j] = (float)(sj * ss + cc);
+ theMatrix[j][k] = (float)(sj * cs - sc);
+ theMatrix[k][i] = (float)(-sj);
+ theMatrix[k][j] = (float)(cj * si);
+ theMatrix[k][k] = (float)(cj * ci);
+ }
+
+ theMatrix[W][X] = 0.0;
+ theMatrix[W][Y] = 0.0;
+ theMatrix[W][Z] = 0.0;
+ theMatrix[X][W] = 0.0;
+ theMatrix[Y][W] = 0.0;
+ theMatrix[Z][W] = 0.0;
+ theMatrix[W][W] = 1.0;
+ }
+
+ //==============================================================================
+ /**
+ * Convert matrix to Euler angles (in radians).
+ * @param theMatrix incoming matrix
+ * @param theOrder 0-23, use EulOrd**** to generate this value
+ * @return a set of angles in radians!!!!
+ */
+ EulerAngles CEulerAngleConverter::Eul_FromHMatrix(HMatrix theMatrix, int theOrder)
+ {
+ EulerAngles theEulerAngle;
+ int i, j, k, h, n, s, f;
+
+ EulGetOrd(theOrder, i, j, k, h, n, s, f);
+ if (s == EulRepYes) {
+ double sy = sqrt(theMatrix[i][j] * theMatrix[i][j] + theMatrix[i][k] * theMatrix[i][k]);
+ if (sy > 16 * FLT_EPSILON) {
+ theEulerAngle.x = (float)(atan2((double)theMatrix[i][j], (double)theMatrix[i][k]));
+ theEulerAngle.y = (float)(atan2((double)sy, (double)theMatrix[i][i]));
+ theEulerAngle.z = (float)(atan2((double)theMatrix[j][i], -(double)theMatrix[k][i]));
+ } else {
+ theEulerAngle.x = (float)(atan2(-(double)theMatrix[j][k], (double)theMatrix[j][j]));
+ theEulerAngle.y = (float)(atan2((double)sy, (double)theMatrix[i][i]));
+ theEulerAngle.z = 0;
+ }
+ } else {
+ double cy = sqrt(theMatrix[i][i] * theMatrix[i][i] + theMatrix[j][i] * theMatrix[j][i]);
+ if (cy > 16 * FLT_EPSILON) {
+ theEulerAngle.x = (float)(atan2((double)theMatrix[k][j], (double)theMatrix[k][k]));
+ theEulerAngle.y = (float)(atan2(-(double)theMatrix[k][i], (double)cy));
+ theEulerAngle.z = (float)(atan2((double)theMatrix[j][i], (double)theMatrix[i][i]));
+ } else {
+ theEulerAngle.x = (float)(atan2(-(double)theMatrix[j][k], (double)theMatrix[j][j]));
+ theEulerAngle.y = (float)(atan2(-(double)theMatrix[k][i], (double)cy));
+ theEulerAngle.z = 0;
+ }
+ }
+
+ if (n == EulParOdd) {
+ theEulerAngle.x = -theEulerAngle.x;
+ theEulerAngle.y = -theEulerAngle.y;
+ theEulerAngle.z = -theEulerAngle.z;
+ }
+
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+ theEulerAngle.w = (float)theOrder;
+ return theEulerAngle;
+ }
+
+ //==============================================================================
+ /**
+ * Convert quaternion to Euler angles (in radians).
+ * @param theQuaternion incoming quaternion
+ * @param theOrder 0-23, use EulOrd**** to generate this value
+ * @return the generated angles ( radians )
+ */
+ EulerAngles CEulerAngleConverter::Eul_FromQuat(Quat theQuaternion, int theOrder)
+ {
+ HMatrix theMatrix;
+ double Nq = theQuaternion.x * theQuaternion.x + theQuaternion.y * theQuaternion.y
+ + theQuaternion.z * theQuaternion.z + theQuaternion.w * theQuaternion.w;
+ double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
+ double xs = theQuaternion.x * s;
+ double ys = theQuaternion.y * s;
+ double zs = theQuaternion.z * s;
+ double wx = theQuaternion.w * xs;
+ double wy = theQuaternion.w * ys;
+ double wz = theQuaternion.w * zs;
+ double xx = theQuaternion.x * xs;
+ double xy = theQuaternion.x * ys;
+ double xz = theQuaternion.x * zs;
+ double yy = theQuaternion.y * ys;
+ double yz = theQuaternion.y * zs;
+ double zz = theQuaternion.z * zs;
+
+ theMatrix[X][X] = (float)(1.0 - (yy + zz));
+ theMatrix[X][Y] = (float)(xy - wz);
+ theMatrix[X][Z] = (float)(xz + wy);
+ theMatrix[Y][X] = (float)(xy + wz);
+ theMatrix[Y][Y] = (float)(1.0 - (xx + zz));
+ theMatrix[Y][Z] = (float)(yz - wx);
+ theMatrix[Z][X] = (float)(xz - wy);
+ theMatrix[Z][Y] = (float)(yz + wx);
+ theMatrix[Z][Z] = (float)(1.0 - (xx + yy));
+ theMatrix[W][X] = 0.0;
+ theMatrix[W][Y] = 0.0;
+ theMatrix[W][Z] = 0.0;
+ theMatrix[X][W] = 0.0;
+ theMatrix[Y][W] = 0.0;
+ theMatrix[Z][W] = 0.0;
+ theMatrix[W][W] = 1.0;
+
+ return Eul_FromHMatrix(theMatrix, theOrder);
+ }
+
+ //==============================================================================
+ /**
+ * Dump the Order information
+ */
+ const char *CEulerAngleConverter::DumpOrderInfo()
+ {
+ long theCount = 0;
+ long theOrder[24];
+ char theOrderStr[24][16];
+
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZr");
+
+ theCount = 0;
+ theOrder[theCount++] = EulOrdXYZs;
+ theOrder[theCount++] = EulOrdXYXs;
+ theOrder[theCount++] = EulOrdXZYs;
+ theOrder[theCount++] = EulOrdXZXs;
+ theOrder[theCount++] = EulOrdYZXs;
+ theOrder[theCount++] = EulOrdYZYs;
+ theOrder[theCount++] = EulOrdYXZs;
+ theOrder[theCount++] = EulOrdYXYs;
+ theOrder[theCount++] = EulOrdZXYs;
+ theOrder[theCount++] = EulOrdZXZs;
+ theOrder[theCount++] = EulOrdZYXs;
+ theOrder[theCount++] = EulOrdZYZs;
+
+ theOrder[theCount++] = EulOrdZYXr;
+ theOrder[theCount++] = EulOrdXYXr;
+ theOrder[theCount++] = EulOrdYZXr;
+ theOrder[theCount++] = EulOrdXZXr;
+ theOrder[theCount++] = EulOrdXZYr;
+ theOrder[theCount++] = EulOrdYZYr;
+ theOrder[theCount++] = EulOrdZXYr;
+ theOrder[theCount++] = EulOrdYXYr;
+ theOrder[theCount++] = EulOrdYXZr;
+ theOrder[theCount++] = EulOrdZXZr;
+ theOrder[theCount++] = EulOrdXYZr;
+ theOrder[theCount++] = EulOrdZYZr;
+
+ char theSubBuf[256];
+ m_OrderInfoBuffer[0] = '\0';
+ for (long theIndex = 0; theIndex < 24; ++theIndex) {
+ ::sprintf(theSubBuf, " %16s - %ld\n ", theOrderStr[theIndex], theOrder[theIndex]);
+ ::strcat(m_OrderInfoBuffer, theSubBuf);
+ }
+
+ return m_OrderInfoBuffer;
+ }
+}
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderGpuProfiler.cpp b/src/Runtime/Source/UICRender/Source/UICRenderGpuProfiler.cpp
new file mode 100644
index 00000000..eabb4a4d
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderGpuProfiler.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderProfiler.h"
+
+#include "EASTL/string.h"
+#include "EASTL/hash_map.h"
+
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSFoundation.h"
+
+#include "UICRenderContext.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderTimerQuery.h"
+#include "render/Qt3DSRenderSync.h"
+
+#define RECORDED_FRAME_DELAY 3
+#define RECORDED_FRAME_DELAY_MASK 0x0003
+
+using namespace uic::render;
+using namespace qt3ds::render;
+
+namespace {
+
+using eastl::make_pair;
+
+struct SGpuTimerInfo
+{
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ bool m_AbsoluteTime;
+ QT3DSU16 m_WriteID;
+ QT3DSU16 m_ReadID;
+ QT3DSU16 m_AverageTimeWriteID;
+ QT3DSU64 m_AverageTime[10];
+ QT3DSU32 m_FrameID[RECORDED_FRAME_DELAY];
+ NVScopedRefCounted<NVRenderTimerQuery> m_TimerStartQueryObjects[RECORDED_FRAME_DELAY];
+ NVScopedRefCounted<NVRenderTimerQuery> m_TimerEndQueryObjects[RECORDED_FRAME_DELAY];
+ NVScopedRefCounted<NVRenderSync> m_TimerSyncObjects[RECORDED_FRAME_DELAY];
+
+ SGpuTimerInfo(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_AbsoluteTime(false)
+ , m_WriteID(0)
+ , m_ReadID(0)
+ , m_AverageTimeWriteID(0)
+ {
+ memset(m_AverageTime, 0x0, 10 * sizeof(QT3DSU64));
+ }
+
+ ~SGpuTimerInfo() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void IncrementWriteCounter()
+ {
+ m_WriteID++;
+ m_WriteID %= RECORDED_FRAME_DELAY_MASK;
+ }
+
+ void IncrementReadCounter()
+ {
+ m_ReadID++;
+ m_ReadID %= RECORDED_FRAME_DELAY_MASK;
+ }
+
+ void IncrementAveragedWriteCounter()
+ {
+ m_AverageTimeWriteID++;
+ m_AverageTimeWriteID %= 10;
+ }
+
+ void StartTimerQuery(QT3DSU32 frameID)
+ {
+ m_FrameID[m_WriteID] = frameID;
+
+ if (m_AbsoluteTime)
+ m_TimerStartQueryObjects[m_WriteID]->SetTimerQuery();
+ else
+ m_TimerStartQueryObjects[m_WriteID]->Begin();
+ }
+
+ void EndTimerQuery()
+ {
+ if (m_AbsoluteTime)
+ m_TimerEndQueryObjects[m_WriteID]->SetTimerQuery();
+ else
+ m_TimerStartQueryObjects[m_WriteID]->End();
+
+ IncrementWriteCounter();
+ }
+
+ void AddSync()
+ {
+ m_TimerSyncObjects[m_WriteID]->Sync();
+ m_TimerSyncObjects[m_WriteID]->Wait();
+ }
+
+ QT3DSF64 GetAveragedElapsedTimeInMs()
+ {
+ QT3DSF64 time =
+ QT3DSF64(((m_AverageTime[0] + m_AverageTime[1] + m_AverageTime[2] + m_AverageTime[3]
+ + m_AverageTime[4] + m_AverageTime[5] + m_AverageTime[6] + m_AverageTime[7]
+ + m_AverageTime[8] + m_AverageTime[9])
+ / 10)
+ / 1e06);
+
+ return time;
+ }
+
+ QT3DSF64 GetElapsedTimeInMs(QT3DSU32 frameID)
+ {
+ QT3DSF64 time = 0;
+
+ if (((frameID - m_FrameID[m_ReadID]) < 2) || (m_ReadID == m_WriteID))
+ return time;
+
+ if (m_AbsoluteTime) {
+ QT3DSU64 startTime, endTime;
+
+ m_TimerStartQueryObjects[m_ReadID]->GetResult(&startTime);
+ m_TimerEndQueryObjects[m_ReadID]->GetResult(&endTime);
+
+ m_AverageTime[m_AverageTimeWriteID] = endTime - startTime;
+ } else {
+ QT3DSU64 elapsedTime;
+
+ m_TimerStartQueryObjects[m_ReadID]->GetResult(&elapsedTime);
+
+ m_AverageTime[m_AverageTimeWriteID] = elapsedTime;
+ }
+
+ IncrementReadCounter();
+ IncrementAveragedWriteCounter();
+
+ return GetAveragedElapsedTimeInMs();
+ }
+};
+
+class UICRenderGpuProfiler : public IRenderProfiler
+{
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<SGpuTimerInfo>> TStrGpuTimerInfoMap;
+
+private:
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ IUICRenderContext &m_UICContext;
+ volatile QT3DSI32 mRefCount;
+
+ TStrGpuTimerInfoMap m_StrToGpuTimerMap;
+ IRenderProfiler::TStrIDVec m_StrToIDVec;
+ mutable QT3DSU32 m_VertexCount;
+
+public:
+ UICRenderGpuProfiler(NVFoundationBase &inFoundation, IUICRenderContext &inContext,
+ NVRenderContext &inRenderContext)
+ : m_Foundation(inFoundation)
+ , m_RenderContext(inRenderContext)
+ , m_UICContext(inContext)
+ , mRefCount(0)
+ , m_StrToGpuTimerMap(inContext.GetAllocator(), "UICRenderGpuProfiler::m_StrToGpuTimerMap")
+ , m_StrToIDVec(inContext.GetAllocator(), "UICRenderGpuProfiler::m_StrToIDVec")
+ , m_VertexCount(0)
+ {
+ }
+
+ virtual ~UICRenderGpuProfiler() { m_StrToGpuTimerMap.clear(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void StartTimer(CRegisteredString &nameID, bool absoluteTime, bool sync) override
+ {
+ SGpuTimerInfo *theGpuTimerData = GetOrCreateGpuTimerInfo(nameID);
+
+ if (theGpuTimerData) {
+ if (sync)
+ theGpuTimerData->AddSync();
+
+ theGpuTimerData->m_AbsoluteTime = absoluteTime;
+ theGpuTimerData->StartTimerQuery(m_UICContext.GetFrameCount());
+ }
+ }
+
+ void EndTimer(CRegisteredString &nameID) override
+ {
+ SGpuTimerInfo *theGpuTimerData = GetOrCreateGpuTimerInfo(nameID);
+
+ if (theGpuTimerData) {
+ theGpuTimerData->EndTimerQuery();
+ }
+ }
+
+ QT3DSF64 GetElapsedTime(const CRegisteredString &nameID) const override
+ {
+ QT3DSF64 time = 0;
+ SGpuTimerInfo *theGpuTimerData = GetGpuTimerInfo(nameID);
+
+ if (theGpuTimerData) {
+ time = theGpuTimerData->GetElapsedTimeInMs(m_UICContext.GetFrameCount());
+ }
+
+ return time;
+ }
+
+ const TStrIDVec &GetTimerIDs() const override { return m_StrToIDVec; }
+
+ void AddVertexCount(QT3DSU32 count) override { m_VertexCount += count; }
+
+ QT3DSU32 GetAndResetTriangleCount() const override
+ {
+ QT3DSU32 tris = m_VertexCount / 3;
+ m_VertexCount = 0;
+ return tris;
+ }
+
+private:
+ SGpuTimerInfo *GetOrCreateGpuTimerInfo(CRegisteredString &nameID)
+ {
+ TStrGpuTimerInfoMap::const_iterator theIter = m_StrToGpuTimerMap.find(nameID);
+ if (theIter != m_StrToGpuTimerMap.end())
+ return const_cast<SGpuTimerInfo *>(theIter->second.mPtr);
+
+ SGpuTimerInfo *theGpuTimerData =
+ QT3DS_NEW(m_UICContext.GetAllocator(), SGpuTimerInfo)(m_Foundation);
+
+ if (theGpuTimerData) {
+ // create queries
+ for (QT3DSU32 i = 0; i < RECORDED_FRAME_DELAY; i++) {
+ theGpuTimerData->m_TimerStartQueryObjects[i] = m_RenderContext->CreateTimerQuery();
+ theGpuTimerData->m_TimerEndQueryObjects[i] = m_RenderContext->CreateTimerQuery();
+ theGpuTimerData->m_TimerSyncObjects[i] = m_RenderContext->CreateSync();
+ theGpuTimerData->m_FrameID[i] = 0;
+ }
+ m_StrToGpuTimerMap.insert(make_pair(nameID, theGpuTimerData));
+ m_StrToIDVec.push_back(nameID);
+ }
+
+ return theGpuTimerData;
+ }
+
+ SGpuTimerInfo *GetGpuTimerInfo(const CRegisteredString &nameID) const
+ {
+ TStrGpuTimerInfoMap::const_iterator theIter = m_StrToGpuTimerMap.find(nameID);
+ if (theIter != m_StrToGpuTimerMap.end())
+ return const_cast<SGpuTimerInfo *>(theIter->second.mPtr);
+
+ return NULL;
+ }
+};
+}
+
+IRenderProfiler &IRenderProfiler::CreateGpuProfiler(NVFoundationBase &inFnd,
+ IUICRenderContext &inContext,
+ NVRenderContext &inRenderContext)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), UICRenderGpuProfiler)(inFnd, inContext, inRenderContext);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderGraphObjectSerializer.cpp b/src/Runtime/Source/UICRender/Source/UICRenderGraphObjectSerializer.cpp
new file mode 100644
index 00000000..5f434156
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderGraphObjectSerializer.cpp
@@ -0,0 +1,668 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderGraphObjectSerializer.h"
+#include "UICRenderPresentation.h"
+#include "UICRenderNode.h"
+#include "UICRenderScene.h"
+#include "UICRenderLayer.h"
+#include "UICRenderModel.h"
+#include "UICRenderText.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderImage.h"
+#include "UICRenderEffect.h"
+#include "UICRenderCamera.h"
+#include "UICRenderLight.h"
+#include "UICRenderCustomMaterial.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICRenderEffectSystem.h"
+#include "foundation/SerializationTypes.h"
+#include "UICRenderString.h"
+#include "foundation/FileTools.h"
+#include "UICRenderPluginGraphObject.h"
+#include "UICRenderReferencedMaterial.h"
+#include "UICRenderPath.h"
+#include "UICRenderPathSubPath.h"
+#include "UICRenderPathManager.h"
+
+using namespace uic::render;
+using namespace uic::render::dynamic;
+
+namespace {
+typedef nvhash_set<void *> TPtrSet;
+
+void Align(MemoryBuffer<> &inBuffer)
+{
+ inBuffer.align(sizeof(void *));
+}
+typedef nvvector<eastl::pair<GraphObjectTypes::Enum, QT3DSU32>> TObjectFileStatList;
+typedef SPtrOffsetMap TPtrOffsetMap;
+
+struct SSerializerWriteContext
+{
+ SPtrOffsetMap &m_OffsetMap;
+ SWriteBuffer &m_MemoryBuffer;
+ const SStrRemapMap &m_StrRemapMap;
+ QT3DSU32 m_DataBlockStart;
+ IDynamicObjectSystem &m_DynamicObjectSystem;
+ IPathManager &m_PathManager;
+ TObjectFileStatList &m_FileSizeStats;
+ CRenderString m_PathMapper;
+ CRenderString m_BasePath;
+ CRenderString m_RelativePath;
+ IStringTable &m_StringTable;
+ SSerializerWriteContext(SPtrOffsetMap &inOffsetMap, SWriteBuffer &inWriteBuffer,
+ const SStrRemapMap &inStrMap, QT3DSU32 inDataBlockStart,
+ IDynamicObjectSystem &inDynamicObjectSystem,
+ IPathManager &inPathManager, TObjectFileStatList &inStats,
+ NVAllocatorCallback &inAllocator, const char8_t *inProjectDirectory,
+ IStringTable &inStringTable)
+ : m_OffsetMap(inOffsetMap)
+ , m_MemoryBuffer(inWriteBuffer)
+ , m_StrRemapMap(inStrMap)
+ , m_DataBlockStart(inDataBlockStart)
+ , m_DynamicObjectSystem(inDynamicObjectSystem)
+ , m_PathManager(inPathManager)
+ , m_FileSizeStats(inStats)
+ , m_StringTable(inStringTable)
+ {
+ m_BasePath.assign(inProjectDirectory);
+ }
+
+ bool HasWrittenObject(const void *inObject) { return m_OffsetMap.contains(inObject); }
+
+ QT3DSU32 &GetStatEntry(GraphObjectTypes::Enum inType) const
+ {
+ for (QT3DSU32 idx = 0, end = m_FileSizeStats.size(); idx < end; ++idx)
+ if (m_FileSizeStats[idx].first == inType)
+ return m_FileSizeStats[idx].second;
+ m_FileSizeStats.push_back(eastl::make_pair(inType, (QT3DSU32)0));
+ return m_FileSizeStats.back().second;
+ }
+
+ template <typename TObjType>
+ void AddPtrOffset(const TObjType *inObject)
+ {
+ QT3DSU32 objOffset = m_MemoryBuffer.size() - m_DataBlockStart;
+ m_OffsetMap.insert(eastl::make_pair(inObject, objOffset));
+// In debug we keep stats on how much each type of object
+// contributes to the file size.
+#ifdef _DEBUG
+ GetStatEntry(inObject->m_Type) += sizeof(TObjType);
+#endif
+ }
+
+ void Remap(CRegisteredString &inStr) { inStr.Remap(m_StrRemapMap); }
+
+ template <typename TObjType>
+ void Remap(TObjType *&inPtr)
+ {
+ if (inPtr) {
+ TPtrOffsetMap::iterator theIter = m_OffsetMap.find(inPtr);
+ if (theIter != m_OffsetMap.end())
+ inPtr = reinterpret_cast<TObjType *>(theIter->second);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ void RemapMaterial(SGraphObject *&inPtr) { Remap(inPtr); }
+
+ template <typename TObjType>
+ void NullPtr(TObjType *&inPtr)
+ {
+ inPtr = NULL;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////
+// --** Reading the scene graph is heavily threaded when we are loading
+// multiple presentations in one application --**
+///////////////////////////////////////////////////////////////////////
+struct SSerializerReadContext : public SDataReader
+{
+ IPathManagerCore &m_PathManager;
+ IDynamicObjectSystemCore &m_DynamicObjectSystem;
+ NVDataRef<QT3DSU8> m_DataBlock;
+ NVDataRef<QT3DSU8> m_StrTableBlock;
+ CRenderString m_PathMapper;
+ const char8_t *m_ProjectDirectory;
+
+ SSerializerReadContext(IPathManagerCore &inPathManager, IDynamicObjectSystemCore &inDynSystem,
+ NVDataRef<QT3DSU8> inDataBlock, NVDataRef<QT3DSU8> inStrTable,
+ NVAllocatorCallback &inAllocator, const char8_t *inProjectDirectory)
+ : SDataReader(inDataBlock.begin(), inDataBlock.end())
+ , m_PathManager(inPathManager)
+ , m_DynamicObjectSystem(inDynSystem)
+ , m_DataBlock(inDataBlock)
+ , m_StrTableBlock(inStrTable)
+ , m_ProjectDirectory(inProjectDirectory)
+ {
+ }
+ void Remap(CRegisteredString &inStr) { inStr.Remap(m_StrTableBlock); }
+ template <typename TObjType>
+ void Remap(TObjType *&inPtr)
+ {
+ if (inPtr) {
+ TObjType *purePtr = inPtr;
+ size_t ptrValue = reinterpret_cast<size_t>(purePtr);
+ if (ptrValue < m_DataBlock.size())
+ inPtr = reinterpret_cast<TObjType *>(m_DataBlock.begin() + ptrValue);
+ else {
+ QT3DS_ASSERT(false);
+ inPtr = NULL;
+ }
+ }
+ }
+ void RemapMaterial(SGraphObject *&inPtr) { Remap(inPtr); }
+ // Nulling out pointers was done on write, so we don't do it here.
+ template <typename TObjType>
+ void NullPtr(TObjType *&)
+ {
+ }
+};
+
+template <typename TObjType>
+struct SGraphObjectSerializerImpl
+{
+ static TObjType *Write(const TObjType &ioObject, SSerializerWriteContext &outSavedBuffer);
+ static void Remap(TObjType &inObject, SSerializerWriteContext &inRemapContext);
+ static TObjType *Read(SSerializerReadContext &inReadContext);
+};
+
+struct SWriteRemapper
+{
+ SSerializerWriteContext &m_WriteBuffer;
+ SWriteRemapper(SSerializerWriteContext &buf)
+ : m_WriteBuffer(buf)
+ {
+ }
+ // This will happen later
+ void Remap(const CRegisteredString &) {}
+ void RemapPath(const CRegisteredString &) {}
+
+ // We ignore objects that are saved out explicitly below.
+ void Remap(const SScene *) {}
+
+ void Remap(const SLayer *) {}
+ // Nodes are ignored because we save them out *not* in depth first order,
+ // with models, text, lights and camera saved out contiguously for in-memory
+ // traversal.
+ void Remap(const SNode *) {}
+#ifdef _INTEGRITYPLATFORM
+ // explicit specialization of class "<unnamed>::SGraphObjectSerializerImpl<uic::render::SCustomMaterial>"
+ // must precede its first use struct SGraphObjectSerializerImpl<SCustomMaterial>
+ template <typename TObjType>
+ void Remap(const TObjType *inObj);
+#else
+ template <typename TObjType>
+ void Remap(const TObjType *inObj)
+ {
+ if (inObj)
+ SGraphObjectSerializerImpl<TObjType>::Write(*inObj, m_WriteBuffer);
+ }
+#endif
+
+ void RemapMaterial(const SGraphObject *inObj)
+ {
+ if (inObj) {
+ if (inObj->m_Type == GraphObjectTypes::DefaultMaterial)
+ Remap(static_cast<const SDefaultMaterial *>(inObj));
+ else if (inObj->m_Type == GraphObjectTypes::CustomMaterial)
+ Remap(static_cast<const SCustomMaterial *>(inObj));
+ else if (inObj->m_Type == GraphObjectTypes::ReferencedMaterial)
+ Remap(static_cast<const SReferencedMaterial *>(inObj));
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ template <typename TObjType>
+ void NullPtr(const TObjType *)
+ {
+ }
+};
+
+void PrepareFirstPass(const SNode &inNode, nvvector<const SNode *> &ioLightCameras,
+ nvvector<const SNode *> &ioRenderable)
+{
+ if (GraphObjectTypes::IsRenderableType(inNode.m_Type))
+ ioRenderable.push_back(&inNode);
+ else if (GraphObjectTypes::IsLightCameraType(inNode.m_Type))
+ ioLightCameras.push_back(&inNode);
+
+ for (const SNode *theChild = inNode.m_FirstChild; theChild; theChild = theChild->m_NextSibling)
+ PrepareFirstPass(*theChild, ioLightCameras, ioRenderable);
+}
+
+template <typename TObject>
+TObject *WriteGenericGraphObjectNoRemap(const TObject &ioObject,
+ SSerializerWriteContext &outSavedBuffer)
+{
+ if (outSavedBuffer.HasWrittenObject(&ioObject))
+ return NULL;
+
+ outSavedBuffer.AddPtrOffset(&ioObject);
+ QT3DSU32 theOffset = outSavedBuffer.m_MemoryBuffer.size();
+ outSavedBuffer.m_MemoryBuffer.write(ioObject);
+ // Probably the buffer stays aligned but we want to work to keep it that way.
+ Align(outSavedBuffer.m_MemoryBuffer);
+ return reinterpret_cast<TObject *>(outSavedBuffer.m_MemoryBuffer.begin() + theOffset);
+}
+
+template <typename TObject>
+TObject *WriteGenericGraphObject(const TObject &ioObject, SSerializerWriteContext &outSavedBuffer)
+{
+ TObject *theObject = WriteGenericGraphObjectNoRemap(ioObject, outSavedBuffer);
+ if (theObject) // The object may have already been written.
+ {
+ // Write mappers just follow pointers and ensure all the associated objects
+ // are written out.
+ SWriteRemapper theWriteRemapper(outSavedBuffer);
+ const_cast<TObject &>(ioObject).Remap(theWriteRemapper);
+ }
+ return theObject;
+}
+
+template <typename TObject>
+TObject *ReadGenericGraphObject(SSerializerReadContext &inReadContext)
+{
+ TObject *retval = inReadContext.Load<TObject>();
+ inReadContext.Align();
+ if (retval) {
+ retval->Remap(inReadContext);
+ }
+ return retval;
+}
+
+template <typename TObjType>
+TObjType *SGraphObjectSerializerImpl<TObjType>::Write(const TObjType &ioObject,
+ SSerializerWriteContext &outSavedBuffer)
+{
+ return WriteGenericGraphObject(ioObject, outSavedBuffer);
+}
+template <typename TObjType>
+void SGraphObjectSerializerImpl<TObjType>::Remap(TObjType &ioObject,
+ SSerializerWriteContext &inRemapContext)
+{
+ return ioObject.Remap(inRemapContext);
+}
+
+template <typename TObjType>
+TObjType *SGraphObjectSerializerImpl<TObjType>::Read(SSerializerReadContext &inReadContext)
+{
+ return ReadGenericGraphObject<TObjType>(inReadContext);
+}
+
+void RemapProperties(SDynamicObject &ioObject, SSerializerWriteContext &outSavedBuffer,
+ CRegisteredString inClassName)
+{
+ NVConstDataRef<SPropertyDefinition> theObjectProps =
+ outSavedBuffer.m_DynamicObjectSystem.GetProperties(inClassName);
+ for (QT3DSU32 idx = 0, end = theObjectProps.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDef(theObjectProps[idx]);
+ if (theDef.m_DataType == qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ CRegisteredString *theStr = reinterpret_cast<CRegisteredString *>(
+ ioObject.GetDataSectionBegin() + theDef.m_Offset);
+ outSavedBuffer.Remap(*theStr);
+ }
+ }
+}
+
+void RemapProperties(SDynamicObject &ioObject, SSerializerReadContext &inReadContext)
+{
+ // CN - !!Note this call is done on multiple threads simultaneously. I added a mutex just to be
+ // sure even though
+ // this is a read-only call; I am not certain how good the arm memory locking is when it is
+ // completely unprotected.
+ NVConstDataRef<SPropertyDefinition> theProperties =
+ inReadContext.m_DynamicObjectSystem.GetProperties(ioObject.m_ClassName);
+ for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(theProperties[idx]);
+ if (theDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ CRegisteredString *theString = reinterpret_cast<CRegisteredString *>(
+ ioObject.GetDataSectionBegin() + theDefinition.m_Offset);
+ inReadContext.Remap(*theString);
+ }
+ }
+}
+
+template <>
+struct SGraphObjectSerializerImpl<SEffect>
+{
+ static SGraphObject *Write(const SEffect &ioObject, SSerializerWriteContext &outSavedBuffer)
+ {
+ size_t itemOffset = outSavedBuffer.m_MemoryBuffer.size();
+ SEffect *theNewEffect =
+ static_cast<SEffect *>(WriteGenericGraphObjectNoRemap(ioObject, outSavedBuffer));
+ if (theNewEffect) {
+ theNewEffect->m_Context = NULL;
+ // Writing it out is easy. Reading it back in means we have to have a correctly setup
+ // IEffectManager so we
+ // can remap strings.
+ outSavedBuffer.m_MemoryBuffer.write(ioObject.GetDataSectionBegin(),
+ ioObject.m_DataSectionByteSize);
+ Align(outSavedBuffer.m_MemoryBuffer);
+ SWriteRemapper theWriteRemapper(outSavedBuffer);
+ // Write any connected objects.
+ theNewEffect =
+ reinterpret_cast<SEffect *>(outSavedBuffer.m_MemoryBuffer.begin() + itemOffset);
+ theNewEffect->Remap(theWriteRemapper);
+ }
+ return theNewEffect;
+ }
+
+ static void Remap(SEffect &ioObject, SSerializerWriteContext &outSavedBuffer)
+ {
+ CRegisteredString theClassName = ioObject.m_ClassName;
+ ioObject.Remap(outSavedBuffer);
+ RemapProperties(ioObject, outSavedBuffer, theClassName);
+ }
+
+ static SEffect *Read(SSerializerReadContext &inReadContext)
+ {
+ SEffect *theEffect = ReadGenericGraphObject<SEffect>(inReadContext);
+ if (theEffect) {
+ inReadContext.m_CurrentPtr += theEffect->m_DataSectionByteSize;
+ inReadContext.Align();
+ RemapProperties(*theEffect, inReadContext);
+ }
+ return theEffect;
+ }
+};
+
+template <>
+struct SGraphObjectSerializerImpl<SCustomMaterial>
+{
+ static SGraphObject *Write(const SCustomMaterial &ioObject,
+ SSerializerWriteContext &outSavedBuffer)
+ {
+ size_t itemOffset = outSavedBuffer.m_MemoryBuffer.size();
+ SCustomMaterial *theNewObject = static_cast<SCustomMaterial *>(
+ WriteGenericGraphObjectNoRemap(ioObject, outSavedBuffer));
+ if (theNewObject) {
+ // Writing it out is easy. Reading it back in means we have to have a correctly setup
+ // IEffectManager so we
+ // can remap strings.
+ outSavedBuffer.m_MemoryBuffer.write(ioObject.GetDataSectionBegin(),
+ ioObject.m_DataSectionByteSize);
+ Align(outSavedBuffer.m_MemoryBuffer);
+ theNewObject = reinterpret_cast<SCustomMaterial *>(outSavedBuffer.m_MemoryBuffer.begin()
+ + itemOffset);
+ SWriteRemapper theWriteRemapper(outSavedBuffer);
+ // Write any connected objects.
+ theNewObject->Remap(theWriteRemapper);
+ }
+ return theNewObject;
+ }
+
+ static void Remap(SCustomMaterial &ioObject, SSerializerWriteContext &outSavedBuffer)
+ {
+ CRegisteredString theClassName(ioObject.m_ClassName);
+ ioObject.Remap(outSavedBuffer);
+ RemapProperties(ioObject, outSavedBuffer, theClassName);
+ }
+
+ static SCustomMaterial *Read(SSerializerReadContext &inReadContext)
+ {
+ SCustomMaterial *theMaterial = ReadGenericGraphObject<SCustomMaterial>(inReadContext);
+ if (theMaterial) {
+ inReadContext.m_CurrentPtr += theMaterial->m_DataSectionByteSize;
+ inReadContext.Align();
+ RemapProperties(*theMaterial, inReadContext);
+ }
+ return theMaterial;
+ }
+};
+
+#ifdef _INTEGRITYPLATFORM
+ template <typename TObjType>
+ void SWriteRemapper::Remap(const TObjType *inObj)
+ {
+ if (inObj)
+ SGraphObjectSerializerImpl<TObjType>::Write(*inObj, m_WriteBuffer);
+ }
+#endif
+
+template <>
+struct SGraphObjectSerializerImpl<SPathSubPath>
+{
+ static SGraphObject *Write(const SPathSubPath &ioObject,
+ SSerializerWriteContext &outSavedBuffer)
+ {
+ SPathSubPath *theObject = WriteGenericGraphObjectNoRemap(ioObject, outSavedBuffer);
+ if (theObject) // The object may have already been written.
+ {
+ NVConstDataRef<SPathAnchorPoint> thePoints =
+ outSavedBuffer.m_PathManager.GetPathSubPathBuffer(ioObject);
+ outSavedBuffer.m_MemoryBuffer.write((QT3DSU32)thePoints.size());
+ outSavedBuffer.m_MemoryBuffer.write(thePoints.begin(), thePoints.size());
+ // Write mappers just follow pointers and ensure all the associated objects
+ // are written out.
+ SWriteRemapper theWriteRemapper(outSavedBuffer);
+ const_cast<SPathSubPath &>(ioObject).Remap(theWriteRemapper);
+ }
+ return theObject;
+ }
+
+ static void Remap(SPathSubPath &ioObject, SSerializerWriteContext &outSavedBuffer)
+ {
+ ioObject.Remap(outSavedBuffer);
+ }
+
+ static SPathSubPath *Read(SSerializerReadContext &inReadContext)
+ {
+ SPathSubPath *theSubPath = ReadGenericGraphObject<SPathSubPath>(inReadContext);
+ if (theSubPath) {
+ QT3DSU32 numPoints = *inReadContext.Load<QT3DSU32>();
+ SPathAnchorPoint *theAnchorPointBuffer =
+ reinterpret_cast<uic::render::SPathAnchorPoint *>(inReadContext.m_CurrentPtr);
+ inReadContext.m_CurrentPtr += sizeof(SPathAnchorPoint) * numPoints;
+
+ // CN - !!Note this call is done on multiple threads simultaneously. I added a mutex to
+ // the path manager object
+ // so this exact call is always protected. This absolutely caused crashing when it was
+ // not protected approriately.
+ inReadContext.m_PathManager.SetPathSubPathData(
+ *theSubPath, toConstDataRef(theAnchorPointBuffer, numPoints));
+ }
+ return theSubPath;
+ }
+};
+
+void WriteGraphObject(const SGraphObject &inObject, SSerializerWriteContext &outSavedBuffer)
+{
+ SGraphObject *newObject = NULL;
+ switch (inObject.m_Type) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case GraphObjectTypes::type: \
+ newObject = SGraphObjectSerializerImpl<S##type>::Write( \
+ static_cast<const S##type &>(inObject), outSavedBuffer); \
+ break;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+}
+
+void WriteNodeList(nvvector<const SNode *> &inList, SSerializerWriteContext &outSavedBuffer)
+{
+ for (QT3DSU32 idx = 0, end = inList.size(); idx < end; ++idx)
+ WriteGraphObject(*inList[idx], outSavedBuffer);
+}
+
+// Now write everything you haven't written so far, skip writing renderables or cameras or lights
+void WriteNonRenderableNonCLNode(const SNode &inNode, SSerializerWriteContext &outSavedBuffer)
+{
+ if (GraphObjectTypes::IsLightCameraType(inNode.m_Type) == false
+ && GraphObjectTypes::IsRenderableType(inNode.m_Type) == false) {
+ WriteGraphObject(inNode, outSavedBuffer);
+ }
+ for (const SNode *theChild = inNode.m_FirstChild; theChild; theChild = theChild->m_NextSibling)
+ WriteNonRenderableNonCLNode(*theChild, outSavedBuffer);
+}
+
+SGraphObject *ReadGraphObject(SSerializerReadContext &inContext)
+{
+ if (inContext.m_CurrentPtr + sizeof(SGraphObject) < inContext.m_EndPtr) {
+ SGraphObject *theObject = reinterpret_cast<SGraphObject *>(inContext.m_CurrentPtr);
+ switch (theObject->m_Type) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case GraphObjectTypes::type: \
+ SGraphObjectSerializerImpl<S##type>::Read(inContext); \
+ break;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ theObject = NULL;
+ break;
+ }
+ return theObject;
+ }
+ return NULL;
+}
+}
+
+void SGraphObjectSerializer::Save(NVFoundationBase &inFoundation,
+ const SPresentation &inPresentation,
+ qt3ds::render::SWriteBuffer &outSavedData,
+ IDynamicObjectSystem &inDynamicObjectSystem,
+ IPathManager &inPathManager, SPtrOffsetMap &outSceneGraphOffsets,
+ IStringTable &inStringTable,
+ NVDataRef<SGraphObject *> inExtraGraphObjects)
+{
+ using namespace qt3ds::foundation;
+ nvvector<const SNode *> theLightCameraList(inFoundation.getAllocator(),
+ "SGraphObjectSerializer::theLightCameraList");
+ nvvector<const SNode *> theRenderableList(inFoundation.getAllocator(),
+ "SGraphObjectSerializer::theRenderableList");
+ TObjectFileStatList theStatList(inFoundation.getAllocator(),
+ "SGraphObjectSerializer::FileSizeStats");
+ // We want to save out the scene graph in the order we are going to traverse it normally.
+ // This is reverse depth first for the lights, cameras, and renderables and depth first for
+ // everything else so we go
+ // in two passes per layer.
+ // We expect the incoming data buffer to be aligned already.
+ QT3DS_ASSERT(outSavedData.size() % sizeof(void *) == 0);
+ if (inPresentation.m_Scene) {
+ QT3DSU32 theDataSectionStart = outSavedData.size();
+ outSavedData.writeZeros(4);
+ SSerializerWriteContext theWriteContext(
+ outSceneGraphOffsets, outSavedData, inStringTable.GetRemapMap(), theDataSectionStart,
+ inDynamicObjectSystem, inPathManager, theStatList, inFoundation.getAllocator(),
+ inPresentation.m_PresentationDirectory, inStringTable);
+ // First pass, just write out the data.
+ WriteGraphObject(inPresentation, theWriteContext);
+ WriteGraphObject(*inPresentation.m_Scene, theWriteContext);
+ for (const SLayer *theLayer = inPresentation.m_Scene->m_FirstChild; theLayer;
+ theLayer = static_cast<const SLayer *>(theLayer->m_NextSibling)) {
+ theLightCameraList.clear();
+ theRenderableList.clear();
+ PrepareFirstPass(*theLayer, theLightCameraList, theRenderableList);
+ eastl::reverse(theLightCameraList.begin(), theLightCameraList.end());
+ eastl::reverse(theRenderableList.begin(), theRenderableList.end());
+ WriteNodeList(theLightCameraList, theWriteContext);
+ WriteNodeList(theRenderableList, theWriteContext);
+ }
+ // Now just write everything *but* renderable objects and cameras.
+ for (const SLayer *theLayer = inPresentation.m_Scene->m_FirstChild; theLayer;
+ theLayer = static_cast<const SLayer *>(theLayer->m_NextSibling)) {
+ WriteNonRenderableNonCLNode(*theLayer, theWriteContext);
+ }
+ // Write out any extra objects we haven't covered yet.
+ for (QT3DSU32 idx = 0, end = inExtraGraphObjects.size(); idx < end; ++idx)
+ WriteGraphObject(*inExtraGraphObjects[idx], theWriteContext);
+
+ QT3DSU32 theNumObjects = theWriteContext.m_OffsetMap.size();
+ QT3DSU32 *theCountPtr = reinterpret_cast<QT3DSU32 *>(outSavedData.begin() + theDataSectionStart);
+ *theCountPtr = theNumObjects;
+
+ // Second pass, perform remapping on all the objects to change their pointers to offsets
+ for (SPtrOffsetMap::iterator theIter = outSceneGraphOffsets.begin(),
+ theEnd = outSceneGraphOffsets.end();
+ theIter != theEnd; ++theIter) {
+ QT3DSU8 *theDataPtr = outSavedData.begin() + theDataSectionStart + theIter->second;
+ SGraphObject *theGraphObj = reinterpret_cast<SGraphObject *>(theDataPtr);
+ switch (theGraphObj->m_Type) {
+#define UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \
+ case GraphObjectTypes::type: \
+ SGraphObjectSerializerImpl<S##type>::Remap(static_cast<S##type &>(*theGraphObj), \
+ theWriteContext); \
+ break;
+ UIC_RENDER_ITERATE_GRAPH_OBJECT_TYPES
+#undef UIC_RENDER_HANDL_GRAPH_OBJECT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+#ifdef _DEBUG
+ qCDebug(TRACE_INFO, "--File size stats:");
+ // Tell the users how much space is used in the file based on object type:
+ for (QT3DSU32 idx = 0, end = theStatList.size(); idx < end; ++idx) {
+ const char *theObjType = GraphObjectTypes::GetObjectTypeName(theStatList[idx].first);
+ qCDebug(TRACE_INFO, "%s - %d bytes:", theObjType, theStatList[idx].second);
+ }
+ qCDebug(TRACE_INFO, "--End file size stats:");
+#endif
+};
+
+SPresentation *SGraphObjectSerializer::Load(NVDataRef<QT3DSU8> inData, NVDataRef<QT3DSU8> inStrDataBlock,
+ IDynamicObjectSystemCore &inDynamicObjectSystem,
+ IPathManagerCore &inPathManager,
+ NVAllocatorCallback &inAllocator,
+ const char8_t *inProjectDirectory)
+{
+ SSerializerReadContext theReadContext(inPathManager, inDynamicObjectSystem, inData,
+ inStrDataBlock, inAllocator, inProjectDirectory);
+ SPresentation *retval = NULL;
+ if (inData.size() < 4) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ QT3DSU32 theNumObjects = theReadContext.LoadRef<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = theNumObjects; idx < end; ++idx) {
+ SGraphObject *theObject = ReadGraphObject(theReadContext);
+ if (theObject) {
+ if (theObject->m_Type == GraphObjectTypes::Presentation)
+ retval = static_cast<SPresentation *>(theObject);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ return retval;
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderImageScaler.cpp b/src/Runtime/Source/UICRender/Source/UICRenderImageScaler.cpp
new file mode 100644
index 00000000..0f69d626
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderImageScaler.cpp
@@ -0,0 +1,882 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICRender.h"
+#include "foundation/Qt3DSMath.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "UICRenderImageScaler.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+
+using namespace uic::render;
+//==============================================================================
+// Namespace
+//==============================================================================
+CImageScaler::CImageScaler(NVAllocatorCallback &inAlloc)
+ : m_Allocator(inAlloc)
+{
+}
+//==============================================================================
+/**
+ * Scales the given image by the given scale factor.
+ *
+ * This method creates a new image based on the parameters given.
+ *
+ * @param inScaleMethod type of scaling operation
+ * @param inOldBuffer points to the old picture
+ * @param inOldWidth width of the old picture
+ * @param inOldHeight height of the old picture
+ * @param inNewBuffer will point to the scaled picture
+ * @param inNewWidth width of the new picture
+ * @param inNewHeight height of the new picture
+ * @param inPlanes number of planes (1 for greyscale, 3 for rgb, etc)
+ * also equivalent to the return value of the CTextureType::PixelSize method.
+ */
+void CImageScaler::Scale(EScaleMethod inScaleMethod, unsigned char *inOldBuffer,
+ unsigned long inOldWidth, unsigned long inOldHeight,
+ unsigned char *&outNewBuffer, unsigned long inNewWidth,
+ unsigned long inNewHeight, unsigned long inPlanes)
+{
+ switch (inScaleMethod) {
+ case SCALEMETHOD_CROP:
+ CImageScaler::Crop(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer, inNewWidth,
+ inNewHeight, inPlanes);
+ break;
+
+ case SCALEMETHOD_BILINEAR:
+ CImageScaler::Bilinear(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer, inNewWidth,
+ inNewHeight, inPlanes);
+ break;
+
+ default:
+ // UIC_THROW( RENDER_E_ILLEGALPARAMETER )
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * Scales the given image by the given scale factor.
+ *
+ * This method creates a new image based on the parameters given.
+ *
+ * @param inScaleMethod type of scaling operation
+ * @param inOldBuffer points to the old picture
+ * @param inOldWidth width of the old picture
+ * @param inOldHeight height of the old picture
+ * @param inNewBuffer will point to the scaled picture
+ * @param inNewWidth width of the new picture
+ * @param inNewHeight height of the new picture
+ * @param inPlanes number of planes (1 for greyscale, 3 for rgb, etc)
+ * also equivalent to the return value of the CTextureType::PixelSize method.
+ */
+void CImageScaler::FastScale(EScaleMethod inScaleMethod, unsigned char *inOldBuffer,
+ unsigned long inOldWidth, unsigned long inOldHeight,
+ unsigned char *&outNewBuffer, unsigned long inNewWidth,
+ unsigned long inNewHeight, unsigned long inPlanes)
+{
+ switch (inScaleMethod) {
+ case SCALEMETHOD_CROP:
+ CImageScaler::Crop(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer, inNewWidth,
+ inNewHeight, inPlanes);
+ break;
+
+ case SCALEMETHOD_POINTSAMPLE:
+ CImageScaler::FastPointSample(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer,
+ inNewWidth, inNewHeight, inPlanes);
+ break;
+
+ default:
+ // UIC_THROW( RENDER_E_ILLEGALPARAMETER )
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * Debug method that simply crops the picture instead of scaling.
+ *
+ * Not for use in production. This is a test method to exercise the framework.
+ *
+ * @param inOldBuffer points to the old picture
+ * @param inOldWidth width of the old picture
+ * @param inOldHeight height of the old picture
+ * @param inNewBuffer will point to the scaled picture
+ * @param inNewWidth width of the new picture
+ * @param inNewHeight height of the new picture
+ * @param inPlanes number of planes (1 for greyscale, 3 for rgb, etc)
+ * also equivalent to the return value of the CTextureType::PixelSize method.
+*/
+void CImageScaler::Crop(unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long /*inOldHeight*/, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight, unsigned long inPlanes)
+{
+ long theMinWidth = NVMin(inOldWidth, inNewWidth);
+
+ // UIC_THROWFALSE( inNewWidth <= inOldWidth, RENDER_E_SCALERNOEXPAND )
+ // UIC_THROWFALSE( inNewHeight <= inOldHeight, RENDER_E_SCALERNOEXPAND )
+
+ outNewBuffer = new unsigned char[inNewWidth * inNewHeight * inPlanes];
+ ::memset(outNewBuffer, 0, inNewWidth * inNewHeight * inPlanes);
+
+ for (unsigned long theRow = 0; theRow < inNewHeight; ++theRow) {
+ ::memcpy(outNewBuffer + theRow * inNewWidth * inPlanes,
+ inOldBuffer + theRow * inOldWidth * inPlanes, theMinWidth * inPlanes);
+ }
+}
+
+//==============================================================================
+/**
+ * Plain scaling.
+ *
+ * Code adopted from http://www.codeguru.com/bitmap/SmoothBitmapResizing.html
+ * Preliminary formatting completed but still needs work.
+ *
+ * @param inOldBuffer points to the old picture
+ * @param inOldWidth width of the old picture
+ * @param inOldHeight height of the old picture
+ * @param inNewBuffer will point to the scaled picture
+ * @param inNewWidth width of the new picture
+ * @param inNewHeight height of the new picture
+ * @param inPlanes number of planes (1 for greyscale, 3 for rgb, etc)
+ * also equivalent to the return value of the CTextureType::PixelSize method.
+*/
+void CImageScaler::Bilinear(unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long inOldHeight, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight,
+ unsigned long inPlanes)
+{
+ // UIC_THROWFALSE( inPlanes > 0, RENDER_E_SCALERBADTYPE )
+
+ outNewBuffer = new unsigned char[inNewWidth * inNewHeight * inPlanes];
+ CImageScaler::Resize(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer, inNewWidth,
+ inNewHeight, inPlanes);
+}
+
+//==============================================================================
+/**
+ * Fast removal of selected pixels.
+ *
+ * Really fast scanning of every n-th pixel. This algorithm works basically by
+ * adding a fraction to the source pointer for each pixel destination, using
+ * fixed point arithmetic.
+ *
+ * @param inOldBuffer points to the old picture
+ * @param inOldWidth width of the old picture
+ * @param inOldHeight height of the old picture
+ * @param inNewBuffer will point to the scaled picture
+ * @param inNewWidth width of the new picture
+ * @param inNewHeight height of the new picture
+ * @param inPlanes number of planes (1 for greyscale, 3 for rgb, etc)
+ * also equivalent to the return value of the CTextureType::PixelSize method.
+*/
+void CImageScaler::FastPointSample(unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long inOldHeight, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight,
+ unsigned long inPlanes)
+{
+ unsigned long theXAccum;
+ unsigned long theYAccum;
+ unsigned long theXConst;
+ unsigned long theYConst;
+ unsigned long theRow;
+ unsigned long theColumn;
+ unsigned long theAdd;
+ unsigned long theSrcIndex;
+ outNewBuffer = new unsigned char[inNewWidth * inNewHeight * inPlanes];
+
+ // *** Debug ***
+ // char dMessage[100];
+ //::sprintf( dMessage, "PointSample: %ldx%ld to %ldx%ld\n",inOldInfo.m_Width, inOldInfo.m_Height, outNewInfo.m_Width, outNewInfo.m_Height );
+ //::OutputDebugString( dMessage );
+
+ switch (inPlanes) {
+ case 4: {
+ long *theSrc;
+ long *theDst;
+ theSrc = reinterpret_cast<long *>(inOldBuffer);
+ theDst = reinterpret_cast<long *>(outNewBuffer);
+ theYAccum = 0;
+ theXConst = (inOldWidth << 16) / inNewWidth;
+ theYConst = (inOldHeight << 16) / inNewHeight;
+ unsigned long theAdd;
+ for (theRow = 0; theRow < inNewHeight; theRow++) {
+ theXAccum = 0;
+ theSrcIndex = 0;
+ for (theColumn = 0; theColumn < inNewWidth; theColumn++) {
+
+ theXAccum += theXConst;
+ theAdd = theXAccum >> 16;
+ *theDst = theSrc[theSrcIndex];
+ theDst++;
+ theSrcIndex += theAdd;
+ // Clear out the integer portion of the accumulator.
+ theXAccum = theXAccum & 0xFFFF;
+ }
+
+ theYAccum += theYConst;
+ theAdd = (theYAccum) >> 16;
+ theSrc += theAdd * inOldWidth;
+ // Clear out the integer portion of the accumulator.
+ theYAccum = theYAccum & 0xFFFF;
+ }
+ } break;
+
+ case 3: {
+ unsigned char *theDest;
+ unsigned char *theSource;
+ theDest = reinterpret_cast<unsigned char *>(outNewBuffer);
+ theSource = reinterpret_cast<unsigned char *>(inOldBuffer);
+ theYAccum = 0;
+ theXConst = (inOldWidth << 16) / inNewWidth;
+ theYConst = (inOldHeight << 16) / inNewHeight;
+ for (theRow = 0; theRow < inNewHeight; ++theRow) {
+ theXAccum = 0;
+ theSrcIndex = 0;
+ for (theColumn = 0; theColumn < inNewWidth; ++theColumn) {
+ theDest[0] = theSource[0];
+ theDest[1] = theSource[1];
+ theDest[2] = theSource[2];
+ theDest += 3;
+ theSrcIndex += 3 * (theXAccum) >> 16;
+ theXAccum = theXAccum & 0xFFFF;
+ }
+ theYAccum += theYConst;
+ theAdd = (theYAccum) >> 16;
+ theSource += theAdd * inOldWidth * 3;
+ theYAccum = theYAccum & 0xFFFF;
+ }
+ } break;
+
+ case 2: {
+ short *theDest;
+ short *theSource;
+ theDest = reinterpret_cast<short *>(outNewBuffer);
+ theSource = reinterpret_cast<short *>(inOldBuffer);
+ theYAccum = 0;
+ theXConst = (inOldWidth << 16) / inNewWidth;
+ theYConst = (inOldHeight << 16) / inNewHeight;
+ for (unsigned long theY = 0; theY < inNewHeight; ++theY) {
+ theXAccum = 0;
+ theSrcIndex = 0;
+ for (unsigned long theX = 0; theX < inNewWidth; ++theX) {
+ *theDest = *theSource;
+ ++theDest;
+ theXAccum += theXConst;
+ theSrcIndex += (theXAccum) >> 16;
+ theXAccum = theXAccum & 0xFFFF;
+ }
+ theYAccum += theYConst;
+ theAdd = (theYAccum) >> 16;
+ theSource += theAdd * inOldWidth;
+ theYAccum = theYAccum & 0xFFFF;
+ }
+ } break;
+
+ case 1: {
+ unsigned char *theDest;
+ unsigned char *theSource;
+ theDest = reinterpret_cast<unsigned char *>(outNewBuffer);
+ theSource = reinterpret_cast<unsigned char *>(inOldBuffer);
+ theYAccum = 0;
+ theXConst = (inOldWidth << 16) / inNewWidth;
+ theYConst = (inOldHeight << 16) / inNewHeight;
+ for (unsigned long theY = 0; theY < inNewHeight; ++theY) {
+ theXAccum = 0;
+ theSrcIndex = 0;
+ for (unsigned long theX = 0; theX < inNewWidth; ++theX) {
+ *theDest = *theSource;
+ ++theDest;
+ theXAccum += theXConst;
+ theSrcIndex += (theXAccum) >> 16;
+ theXAccum = theXAccum & 0xFFFF;
+ }
+ theYAccum += theYConst;
+ theAdd = (theYAccum) >> 16;
+ theSource += theAdd * inOldWidth;
+ theYAccum = theYAccum & 0xFFFF;
+ }
+ } break;
+
+ default:
+ // UIC_THROW( RENDER_E_ILLEGALPARAMETER )
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * @param inWidth
+ * @param inHeight
+ * @return unsigned char*
+ */
+unsigned char *CImageScaler::AllocateBuffer(long inWidth, long inHeight)
+{
+ unsigned char *theBuffer = new unsigned char[inHeight * inWidth * 4];
+ return theBuffer;
+}
+
+//==============================================================================
+/**
+ * @param ioBuffer the buffer to release
+ */
+void CImageScaler::ReleaseBuffer(unsigned char *&ioBuffer)
+{
+ delete[] ioBuffer;
+ ioBuffer = NULL;
+}
+
+//==============================================================================
+/**
+ * @param inOldBuffer points to the old picture
+ * @param inOldWidth width of the old picture
+ * @param inOldHeight height of the old picture
+ * @param inNewBuffer will point to the scaled picture
+ * @param inNewWidth width of the new picture
+ * @param inNewHeight height of the new picture
+ * @param inPlanes number of planes (1 for greyscale, 3 for rgb, etc)
+ * also equivalent to the return value of the CTextureType::PixelSize method.
+ */
+void CImageScaler::Resize(unsigned char *inOldBuffer, unsigned long inOldWidth,
+ unsigned long inOldHeight, unsigned char *&outNewBuffer,
+ unsigned long inNewWidth, unsigned long inNewHeight,
+ unsigned long inPlanes)
+{
+ // UIC_THROWFALSE( inPlanes == 4, RENDER_E_ILLEGALPARAMETER );
+
+ // only do the temporary allocation if necessary
+ if (inOldWidth < inNewWidth || inOldHeight < inNewHeight) {
+ CImageScaler::ExpandRowsAndColumns(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer,
+ inNewWidth, inNewHeight, inPlanes);
+ return;
+ } else {
+ // The downsampling algorithms *do* assume four planes.
+ // UIC_THROWFALSE( inPlanes == 4, RENDER_E_ILLEGALPARAMETER );
+ if (inOldWidth > inNewWidth && inOldHeight > inNewHeight) {
+ MemoryBuffer<> theBuffer(ForwardingAllocator(m_Allocator, "ImageScaler::TempBuffer"));
+ theBuffer.reserve(inNewWidth * inOldHeight * 4);
+ unsigned char *theTempBuffer = theBuffer.begin();
+ CImageScaler::ReduceCols(inOldBuffer, inOldWidth, inOldHeight, theTempBuffer,
+ inNewWidth);
+ CImageScaler::ReduceRows(theTempBuffer, inNewWidth, inOldHeight, outNewBuffer,
+ inNewHeight);
+ } else if (inOldWidth > inNewWidth) {
+ CImageScaler::ReduceCols(inOldBuffer, inOldWidth, inOldHeight, outNewBuffer,
+ inNewWidth);
+ } else if (inOldHeight > inNewHeight) {
+ CImageScaler::ReduceRows(inOldBuffer, inNewWidth, inOldHeight, outNewBuffer,
+ inNewHeight);
+ }
+ }
+}
+
+void CImageScaler::ExpandRowsAndColumns(unsigned char *inBuffer, unsigned long inWidth,
+ unsigned long inHeight, unsigned char *outBuffer,
+ unsigned long inDstWidth, unsigned long inDstHeight,
+ unsigned long inPlanes)
+{
+ if (inDstWidth < inWidth || inDstHeight < inHeight) {
+ return;
+ }
+ /*if( inPlanes == 4 )
+ {
+ FastExpandRowsAndColumns( inBuffer, inWidth, inHeight,
+ outBuffer, inDstWidth, inDstHeight );
+ return;
+ }*/
+ unsigned long theYPosition;
+ unsigned short theYRatio;
+ unsigned short theYInvRatio;
+ unsigned long theXPosition;
+ unsigned short theXRatio;
+ unsigned short theXInvRatio;
+
+ unsigned long theRow;
+ unsigned long theColumn;
+ unsigned long theSrcIndex;
+ unsigned long theDstIndex;
+ unsigned long theSrcLineLength;
+ unsigned long theTemp;
+ unsigned long thePixel;
+
+ theDstIndex = 0;
+ theSrcIndex = 0;
+ theSrcLineLength = inWidth * inPlanes;
+ theYPosition = inDstHeight;
+ theYRatio = 1 << 8;
+ theYInvRatio = 0;
+ theXInvRatio = 0;
+ // Here we go....
+ // This algorithm will be quite a bit hairy, if you want
+ // to understand it, then look at the two expand alogorithms above
+ // and realize the this is just the logical combination of the two
+ for (theRow = 0; theRow < inDstHeight; theRow++) {
+ // Run through all the rows, multiplying if necessary the two ratio's together
+ theXPosition = inDstWidth;
+ if (theYPosition < inHeight) {
+ // We have crossed a row boundary
+ theYRatio = (unsigned short)((theYPosition << 8) / inHeight);
+ theYInvRatio = (unsigned short)((1 << 8) - theYRatio);
+
+ for (theColumn = 0; theColumn < inDstWidth; theColumn++) {
+ if (theXPosition < inWidth) {
+ theXRatio = (unsigned short)((theXPosition << 8) / inWidth);
+ theXInvRatio = (unsigned short)((1 << 8) - theXRatio);
+
+ // The combination of both the x and y ratio's
+ unsigned long theLeftRatio = (theXRatio * theYRatio) >> 8;
+ unsigned long theRightRatio = (theXInvRatio * theYRatio) >> 8;
+ unsigned long theLowLeftRatio = (theXRatio * theYInvRatio) >> 8;
+ unsigned long theLowRightRatio = (theXInvRatio * theYInvRatio) >> 8;
+ // We are on a row and column boundary, thus each pixel here is the
+ // combination of four pixels (left right, low left, low right)
+ for (thePixel = 0; thePixel < inPlanes; thePixel++) {
+ // Left side first
+ theTemp = (theLeftRatio * inBuffer[theSrcIndex]);
+ theTemp += (theRightRatio * inBuffer[theSrcIndex + inPlanes]);
+ theTemp += (theLowLeftRatio * inBuffer[theSrcIndex + theSrcLineLength]);
+ theTemp += (theLowRightRatio
+ * inBuffer[theSrcIndex + theSrcLineLength + inPlanes]);
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 8);
+ theDstIndex++;
+ theSrcIndex++;
+ }
+ // Reset our position calculation
+ theXPosition = inDstWidth - inWidth + theXPosition;
+ } else {
+ for (thePixel = 0; thePixel < inPlanes; thePixel++) {
+ theTemp = theYRatio * inBuffer[theSrcIndex + thePixel];
+ theTemp +=
+ theYInvRatio * inBuffer[theSrcIndex + theSrcLineLength + thePixel];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 8);
+ theDstIndex++;
+ }
+ // Reset our position calculation
+ theXPosition -= inWidth;
+ }
+ }
+ // Reset our position calculation
+ theYPosition = inDstHeight - inHeight + theYPosition;
+ // Make the src index point to the next line
+ theSrcIndex += inPlanes;
+ } // Ends the if to check if we are crossing a row boundary
+ // Else we are not crossing a row boundary
+ else {
+ for (theColumn = 0; theColumn < inDstWidth; theColumn++) {
+ // If we are crossing a column boundary
+ if (theXPosition < inWidth) {
+ theXRatio = (unsigned short)((theXPosition << 8) / inWidth);
+ theXInvRatio = (unsigned short)((1 << 8) - theXRatio);
+ for (thePixel = 0; thePixel < inPlanes; thePixel++) {
+ theTemp = theXRatio * inBuffer[theSrcIndex];
+ theTemp += theXInvRatio * inBuffer[theSrcIndex + inPlanes];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 8);
+ theSrcIndex++;
+ theDstIndex++;
+ }
+
+ theXPosition = inDstWidth - inWidth + theXPosition;
+ }
+ // Else we are not crossing a column boundary
+ else {
+ for (thePixel = 0; thePixel < inPlanes; thePixel++) {
+ outBuffer[theDstIndex] = inBuffer[theSrcIndex + thePixel];
+ theDstIndex++;
+ }
+ theXPosition -= inWidth;
+ }
+ }
+ // reset our y position indicator
+ theYPosition -= inHeight;
+ // reset the src index to the beginning the next line
+ theSrcIndex += inPlanes;
+ // reset src index to the beginning of this line
+ theSrcIndex -= theSrcLineLength;
+ } // End of else for row boundary
+ } // End of for loop for iterating through all rows
+}
+
+// Assuming the number of planes is four
+
+void CImageScaler::FastExpandRowsAndColumns(unsigned char *inBuffer, unsigned long inWidth,
+ unsigned long inHeight, unsigned char *outBuffer,
+ unsigned long inDstWidth, unsigned long inDstHeight)
+{
+
+ if (inDstWidth < inWidth || inDstHeight < inHeight) {
+ return;
+ }
+ unsigned long theYPosition;
+ unsigned short theYRatio;
+ unsigned short theYInvRatio;
+ unsigned long theXPosition;
+ unsigned short theXRatio;
+ unsigned short theXInvRatio;
+ // The combination of both the x and y ratio's
+ unsigned long theLeftRatio;
+ unsigned long theRightRatio;
+ unsigned long theLowLeftRatio;
+ unsigned long theLowRightRatio;
+
+ unsigned long theRow;
+ unsigned long theColumn;
+ unsigned long theSrcIndex;
+ unsigned long theDstIndex;
+ unsigned long theSrcLineLength;
+ unsigned long theTemp;
+
+ theDstIndex = 0;
+ theSrcIndex = 0;
+ theSrcLineLength = inWidth * 4;
+ theYPosition = inDstHeight;
+ theYInvRatio = 0;
+ theXInvRatio = 0;
+ // Here we go....
+ // This algorithm will be quite a bit hairy, if you want
+ // to understand it, then look at the two expand alogorithms above
+ // and realize the this is just the logical combination of the two
+ for (theRow = 0; theRow < inDstHeight; theRow++) {
+ // Run through all the rows, multiplying if necessary the two ratio's together
+ theXPosition = inDstWidth;
+ if (theYPosition < inHeight) {
+ // We have crossed a row boundary
+ theYRatio = (unsigned short)((theYPosition << 8) / inHeight);
+ theYInvRatio = (unsigned short)((1 << 8) - theYRatio);
+
+ for (theColumn = 0; theColumn < inDstWidth; theColumn++) {
+ if (theXPosition < inWidth) {
+ theXRatio = (unsigned short)((theXPosition << 8) / inWidth);
+ theXInvRatio = (unsigned short)((1 << 8) - theXRatio);
+ theLeftRatio = (theXRatio * theYRatio) >> 8;
+ theRightRatio = (theXInvRatio * theYRatio) >> 8;
+ theLowLeftRatio = (theXRatio * theYInvRatio) >> 8;
+ theLowRightRatio = (theXInvRatio * theYInvRatio) >> 8;
+ // We are on a row and column boundary, thus each pixel here is the
+ // combination of four pixels (left right, low left, low right)
+
+ // Left side first
+ theTemp = (inBuffer[theSrcIndex]);
+ theTemp += (inBuffer[theSrcIndex + 4]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength + 4]);
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 2);
+ theDstIndex++;
+ theSrcIndex++;
+ // Left side first
+ theTemp = (inBuffer[theSrcIndex]);
+ theTemp += (inBuffer[theSrcIndex + 4]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength + 4]);
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 2);
+ theDstIndex++;
+ theSrcIndex++;
+ // Left side first
+ theTemp = (inBuffer[theSrcIndex]);
+ theTemp += (inBuffer[theSrcIndex + 4]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength + 4]);
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 2);
+ theDstIndex++;
+ theSrcIndex++;
+ // Left side first
+ theTemp = (inBuffer[theSrcIndex]);
+ theTemp += (inBuffer[theSrcIndex + 4]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength]);
+ theTemp += (inBuffer[theSrcIndex + theSrcLineLength + 4]);
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 2);
+ theDstIndex++;
+ theSrcIndex++;
+ // Reset our position calculation
+ theXPosition = inDstWidth - inWidth + theXPosition;
+ } else {
+
+ theTemp = inBuffer[theSrcIndex];
+ theTemp += inBuffer[theSrcIndex + theSrcLineLength];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theDstIndex++;
+ theTemp = inBuffer[theSrcIndex + 1];
+ theTemp += inBuffer[theSrcIndex + theSrcLineLength + 1];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theDstIndex++;
+ theTemp = inBuffer[theSrcIndex + 2];
+ theTemp += inBuffer[theSrcIndex + theSrcLineLength + 2];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theDstIndex++;
+ theTemp = inBuffer[theSrcIndex + 3];
+ theTemp += inBuffer[theSrcIndex + theSrcLineLength + 3];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theDstIndex++;
+ // Reset our position calculation
+ theXPosition -= inWidth;
+ }
+ }
+ // Reset our position calculation
+ theYPosition = inDstHeight - inHeight + theYPosition;
+ // Make the src index point to the next line
+ theSrcIndex += 4;
+ } // Ends the if to check if we are crossing a row boundary
+ // Else we are not crossing a row boundary
+ else {
+ for (theColumn = 0; theColumn < inDstWidth; theColumn++) {
+ // If we are crossing a column boundary
+ if (theXPosition < inWidth) {
+ theXRatio = (unsigned short)((theXPosition << 8) / inWidth);
+ theXInvRatio = (unsigned short)((1 << 8) - theXRatio);
+
+ theTemp = inBuffer[theSrcIndex];
+ theTemp += inBuffer[theSrcIndex + 4];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theSrcIndex++;
+ theDstIndex++;
+ theTemp = inBuffer[theSrcIndex];
+ theTemp += inBuffer[theSrcIndex + 4];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theSrcIndex++;
+ theDstIndex++;
+ theTemp = inBuffer[theSrcIndex];
+ theTemp += inBuffer[theSrcIndex + 4];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theSrcIndex++;
+ theDstIndex++;
+ theTemp = inBuffer[theSrcIndex];
+ theTemp += inBuffer[theSrcIndex + 4];
+ outBuffer[theDstIndex] = (unsigned char)(theTemp >> 1);
+ theSrcIndex++;
+ theDstIndex++;
+
+ theXPosition = inDstWidth - inWidth + theXPosition;
+ }
+ // Else we are not crossing a column boundary
+ else {
+ *((long *)(outBuffer + theDstIndex)) = *((long *)(inBuffer + theSrcIndex));
+ theDstIndex += 4;
+ theXPosition -= inWidth;
+ }
+ }
+ // reset our y position indicator
+ theYPosition -= inHeight;
+ // reset the src index to the beginning the next line
+ theSrcIndex += 4;
+ // reset src index to the beginning of this line
+ theSrcIndex -= theSrcLineLength;
+ } // End of else for row boundary
+ } // End of for loop for iterating through all rows
+}
+
+//==============================================================================
+/**
+ * @param inSrcBuffer
+ */
+void CImageScaler::ReduceCols(unsigned char *inSrcBuffer, long inSrcWidth, long inSrcHeight,
+ unsigned char *&outDstBuffer, long inDstWidth)
+{
+ long theDDAConst = static_cast<long>(1024.0 * inDstWidth / inSrcWidth);
+ long theDDAAccum = 0L;
+ long thePixelCount;
+
+ long theSrcRow;
+ long theSrcCol;
+ long theDstCol;
+
+ long theRedAccum;
+ long theGreenAccum;
+ long theBlueAccum;
+ long theAlphaAccum;
+
+ unsigned char *theDstPointer = outDstBuffer;
+ unsigned char *theSrcPointer = inSrcBuffer;
+ unsigned char *theSrcRowPointer;
+ unsigned char *theDstRowPointer;
+
+ long theSrcStepSize = 4;
+ long theDstStepSize = 4;
+
+ for (theSrcRow = 0; theSrcRow < inSrcHeight; ++theSrcRow) {
+
+ theSrcRowPointer = theSrcPointer + (theSrcRow * inSrcWidth * theSrcStepSize);
+ theDstRowPointer = theDstPointer + (theSrcRow * inDstWidth * theDstStepSize);
+
+ theSrcCol = 0L;
+ theDstCol = 0L;
+ theRedAccum = 0L;
+ theGreenAccum = 0L;
+ theBlueAccum = 0L;
+ theAlphaAccum = 0L;
+ thePixelCount = 0L;
+ theDDAAccum = 0L;
+
+ while (theSrcCol < inSrcWidth) {
+ while ((theDDAAccum < 1024L) && (theSrcCol < inSrcWidth)) {
+ theRedAccum += 1024L * theSrcRowPointer[(theSrcCol * theSrcStepSize) + 0];
+ theGreenAccum += 1024L * theSrcRowPointer[(theSrcCol * theSrcStepSize) + 1];
+ theBlueAccum += 1024L * theSrcRowPointer[(theSrcCol * theSrcStepSize) + 2];
+ theAlphaAccum += 1024L * theSrcRowPointer[(theSrcCol * theSrcStepSize) + 3];
+
+ theDDAAccum += theDDAConst;
+ thePixelCount += 1024L;
+ ++theSrcCol;
+ }
+
+ theDDAAccum = (theSrcCol < inSrcWidth) ? (theDDAAccum - 1024L) : (0L);
+ thePixelCount -= theDDAAccum;
+
+ theRedAccum -=
+ theDDAAccum * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 0];
+ theGreenAccum -=
+ theDDAAccum * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 1];
+ theBlueAccum -=
+ theDDAAccum * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 2];
+ theAlphaAccum -=
+ theDDAAccum * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 3];
+
+ theDstRowPointer[(theDstCol * theDstStepSize) + 0] =
+ (unsigned char)(theRedAccum / thePixelCount);
+ theDstRowPointer[(theDstCol * theDstStepSize) + 1] =
+ (unsigned char)(theGreenAccum / thePixelCount);
+ theDstRowPointer[(theDstCol * theDstStepSize) + 2] =
+ (unsigned char)(theBlueAccum / thePixelCount);
+ theDstRowPointer[(theDstCol * theDstStepSize) + 3] =
+ (unsigned char)(theAlphaAccum / thePixelCount);
+
+ thePixelCount = 1024L - theDDAAccum;
+ ++theDstCol;
+
+ if (theDstCol >= inDstWidth) {
+ break;
+ }
+
+ theRedAccum =
+ thePixelCount * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 0];
+ theGreenAccum =
+ thePixelCount * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 1];
+ theBlueAccum =
+ thePixelCount * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 2];
+ theAlphaAccum =
+ thePixelCount * (long)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + 3];
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * @param inSrcBuffer
+ */
+void CImageScaler::ReduceRows(unsigned char *inSrcBuffer, long inSrcWidth, long inSrcHeight,
+ unsigned char *&outDstBuffer, long inDstHeight)
+{
+ long theDDAConst = static_cast<long>(1024.0 * inDstHeight / inSrcHeight);
+ long theDDAAccum = 0;
+ long thePixelCount;
+
+ long theSrcRow;
+ long theSrcCol;
+ long theDstRow;
+
+ long theRedAccum;
+ long theGreenAccum;
+ long theBlueAccum;
+ long theAlphaAccum;
+
+ unsigned char *theDstPointer = outDstBuffer;
+ unsigned char *theSrcPointer = inSrcBuffer;
+ unsigned char *theSrcColPointer = NULL;
+ unsigned char *theDstColPointer = NULL;
+
+ long theStepSize = 4;
+ long theSrcStride = 4 * inSrcWidth;
+ long theDstStride = 4 * inSrcWidth;
+
+ for (theSrcCol = 0; theSrcCol < inSrcWidth; ++theSrcCol) {
+ theSrcColPointer = theSrcPointer + (theSrcCol * theStepSize);
+ theDstColPointer = theDstPointer + (theSrcCol * theStepSize);
+
+ theSrcRow = 0L;
+ theDstRow = 0L;
+ theRedAccum = 0L;
+ theGreenAccum = 0L;
+ theBlueAccum = 0L;
+ theAlphaAccum = 0L;
+ thePixelCount = 0L;
+
+ theDDAAccum = 0L;
+
+ while (theSrcRow < inSrcHeight) {
+ while ((theDDAAccum < 1024L) && (theSrcRow < inSrcHeight)) {
+ theRedAccum += 1024L * theSrcColPointer[(theSrcRow * theSrcStride) + 0];
+ theGreenAccum += 1024L * theSrcColPointer[(theSrcRow * theSrcStride) + 1];
+ theBlueAccum += 1024L * theSrcColPointer[(theSrcRow * theSrcStride) + 2];
+ theAlphaAccum += 1024L * theSrcColPointer[(theSrcRow * theSrcStride) + 3];
+
+ theDDAAccum += theDDAConst;
+ thePixelCount += 1024L;
+ ++theSrcRow;
+ }
+
+ theDDAAccum = (theSrcRow < inSrcHeight) ? (theDDAAccum - 1024L) : (0L);
+ thePixelCount -= theDDAAccum;
+
+ theRedAccum -=
+ theDDAAccum * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 0];
+ theGreenAccum -=
+ theDDAAccum * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 1];
+ theBlueAccum -=
+ theDDAAccum * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 2];
+ theAlphaAccum -=
+ theDDAAccum * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 3];
+
+ theDstColPointer[(theDstRow * theDstStride) + 0] =
+ (unsigned char)(theRedAccum / thePixelCount);
+ theDstColPointer[(theDstRow * theDstStride) + 1] =
+ (unsigned char)(theGreenAccum / thePixelCount);
+ theDstColPointer[(theDstRow * theDstStride) + 2] =
+ (unsigned char)(theBlueAccum / thePixelCount);
+ theDstColPointer[(theDstRow * theDstStride) + 3] =
+ (unsigned char)(theAlphaAccum / thePixelCount);
+
+ thePixelCount = 1024L - theDDAAccum;
+ ++theDstRow;
+
+ if (theDstRow >= inDstHeight) {
+ break;
+ }
+
+ theRedAccum =
+ thePixelCount * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 0];
+ theGreenAccum =
+ thePixelCount * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 1];
+ theBlueAccum =
+ thePixelCount * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 2];
+ theAlphaAccum =
+ thePixelCount * (long)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + 3];
+ }
+ }
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderInputStreamFactory.cpp b/src/Runtime/Source/UICRender/Source/UICRenderInputStreamFactory.cpp
new file mode 100644
index 00000000..c7637c48
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderInputStreamFactory.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderInputStreamFactory.h"
+
+#include "stdio.h"
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/string.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSMutex.h"
+
+#include <QDir>
+#include <QDirIterator>
+#include <QFile>
+#include <QFileInfo>
+#include <QUrl>
+
+using namespace uic::render;
+
+namespace {
+struct SInputStream : public IRefCountedInputStream
+{
+ NVFoundationBase &m_Foundation;
+ QString m_Path;
+ QFile m_File;
+ volatile QT3DSI32 mRefCount;
+
+ SInputStream(NVFoundationBase &inFoundation, const QString &inPath)
+ : m_Foundation(inFoundation)
+ , m_Path(inPath)
+ , m_File(inPath)
+ , mRefCount(0)
+ {
+ m_File.open(QIODevice::ReadOnly);
+ }
+ virtual ~SInputStream()
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ return m_File.read((char *)data.begin(), data.size());
+ }
+
+ bool Write(NVConstDataRef<QT3DSU8> /*data*/) override
+ {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ void SetPosition(QT3DSI64 inOffset, qt3ds::foundation::SeekPosition::Enum inEnum) override
+ {
+ if (inOffset > QT3DS_MAX_I32 || inOffset < QT3DS_MIN_I32) {
+ qCCritical(INVALID_OPERATION, "Attempt to seek further than platform allows");
+ QT3DS_ASSERT(false);
+ return;
+ } else {
+ CFileTools::SetStreamPosition(m_File, inOffset, inEnum);
+ }
+ }
+ QT3DSI64 GetPosition() const override
+ {
+ return m_File.pos();
+ }
+
+ static SInputStream *OpenFile(const QString &inPath, NVFoundationBase &inFoundation)
+ {
+ return QT3DS_NEW(inFoundation.getAllocator(), SInputStream)(inFoundation, inPath);
+ }
+};
+
+typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+struct SFactory : public IInputStreamFactory
+{
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+
+ Mutex m_Mutex;
+ typedef Mutex::ScopedLock TScopedLock;
+
+ SFactory(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_Mutex(inFoundation.getAllocator())
+ {
+ // Add the top-level qrc directory
+ QDir::addSearchPath("qt3dstudio", ":/");
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ QFileInfo matchCaseInsensitiveFile(const QString& file)
+ {
+ qCWarning(WARNING, PERF_INFO, "Case-insensitive matching with file: %s",
+ file.toLatin1().constData());
+ QStringList searchDirectories = QDir::searchPaths("qt3dstudio");
+ for (const auto &directoryPath : qAsConst(searchDirectories)) {
+ QFileInfo fileInfo(file);
+ QDirIterator it(directoryPath, QStringList { fileInfo.fileName() },
+ QDir::NoFilter, QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ QString filePath = it.next();
+ if (filePath.compare(directoryPath + '/' + file, Qt::CaseInsensitive) == 0)
+ return QFileInfo(filePath);
+ }
+ }
+
+ return QFileInfo();
+ }
+
+ void AddSearchDirectory(const char8_t *inDirectory) override
+ {
+ TScopedLock __factoryLocker(m_Mutex);
+ QString localDir = CFileTools::NormalizePathForQtUsage(inDirectory);
+ QDir directory(localDir);
+ if (!directory.exists()) {
+ qCCritical(INTERNAL_ERROR, "Adding search directory: %s", inDirectory);
+ return;
+ }
+
+ if (!QDir::searchPaths("qt3dstudio").contains(localDir))
+ QDir::addSearchPath("qt3dstudio", localDir);
+ }
+
+
+ IRefCountedInputStream *GetStreamForFile(const QString &inFilename, bool inQuiet) override
+ {
+ TScopedLock __factoryLocker(m_Mutex);
+ QString localFile = CFileTools::NormalizePathForQtUsage(inFilename);
+ QFileInfo fileInfo = QFileInfo(localFile);
+ SInputStream *inputStream = NULL;
+ // Try to match the file with the search paths
+ if (!fileInfo.exists())
+ fileInfo = QFileInfo("qt3dstudio:" + localFile);
+
+ // Try to match the case-insensitive file with the given search paths
+ if (!fileInfo.exists())
+ fileInfo = matchCaseInsensitiveFile(localFile);
+
+ if (fileInfo.exists())
+ inputStream = SInputStream::OpenFile(fileInfo.absoluteFilePath(), m_Foundation);
+
+ if (inputStream) {
+ qCInfo(TRACE_INFO, "file %s resolved to: %s", inFilename.toLatin1().data(),
+ fileInfo.absoluteFilePath().toLatin1().constData());
+ } else if (!inQuiet) {
+ // Print extensive debugging information.
+ qCCritical(INTERNAL_ERROR, "Failed to find file: %s", inFilename.toLatin1().data());
+ qCCritical(INTERNAL_ERROR, "Searched path: %s",
+ QDir::searchPaths("qt3dstudio").join(',').toLatin1().constData());
+ }
+ return inputStream;
+ }
+
+ bool GetPathForFile(const QString &inFilename, QString &outFile,
+ bool inQuiet = false) override
+ {
+ NVScopedRefCounted<IRefCountedInputStream> theStream =
+ GetStreamForFile(inFilename, inQuiet);
+ if (theStream) {
+ SInputStream *theRealStream = static_cast<SInputStream *>(theStream.mPtr);
+ outFile = theRealStream->m_Path;
+ return true;
+ }
+ return false;
+ }
+};
+}
+
+IInputStreamFactory &IInputStreamFactory::Create(NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SFactory)(inFoundation);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderPathManager.cpp b/src/Runtime/Source/UICRender/Source/UICRenderPathManager.cpp
new file mode 100644
index 00000000..7427dcbf
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderPathManager.cpp
@@ -0,0 +1,1948 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderPathManager.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSContainers.h"
+#include "EASTL/string.h"
+#include "UICRenderContext.h"
+#include "foundation/Utils.h"
+#include "foundation/StringConversionImpl.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderInputAssembler.h"
+#include "UICRenderPath.h"
+#include "EASTL/sort.h"
+#include "render/Qt3DSRenderContext.h"
+#include "render/Qt3DSRenderVertexBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderShaderCodeGenerator.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderCamera.h"
+#include "UICRenderPathRenderContext.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "UICRenderDefaultMaterialShaderGenerator.h"
+#include "UICRenderCustomMaterialShaderGenerator.h"
+#include "UICRenderCustomMaterial.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "../RendererImpl/UICVertexPipelineImpl.h"
+#include "foundation/Qt3DSMathUtils.h"
+#include "render/Qt3DSRenderPathRender.h"
+#include "render/Qt3DSRenderPathSpecification.h"
+#include "UICRenderPathSubPath.h"
+#include "UICImportPath.h"
+#include "UICRenderPathMath.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/Qt3DSMutex.h"
+
+using namespace uic::render;
+using qt3ds::render::NVRenderCachedShaderProperty;
+using qt3ds::render::NVRenderCachedShaderBuffer;
+using qt3ds::render::NVRenderStencilFunctionArgument;
+using qt3ds::render::NVRenderBoolOp;
+using qt3ds::render::NVRenderStencilOperationArgument;
+using qt3ds::render::NVRenderStencilOp;
+
+typedef UICIMP::SPathBuffer TImportPathBuffer;
+using namespace uic::render::path;
+
+typedef eastl::pair<CRegisteredString, CRegisteredString> TStrStrPair;
+
+namespace eastl {
+template <>
+struct hash<TStrStrPair>
+{
+ size_t operator()(const TStrStrPair &item) const
+ {
+ return eastl::hash<CRegisteredString>()(item.first)
+ ^ eastl::hash<CRegisteredString>()(item.second);
+ }
+};
+}
+
+struct SPathShaderMapKey
+{
+ CRegisteredString m_Name;
+ SShaderDefaultMaterialKey m_MaterialKey;
+ size_t m_HashCode;
+ SPathShaderMapKey(CRegisteredString inName, SShaderDefaultMaterialKey inKey)
+ : m_Name(inName)
+ , m_MaterialKey(inKey)
+ {
+ m_HashCode = eastl::hash<TStrStrPair>()(m_Name) ^ m_MaterialKey.hash();
+ }
+ bool operator==(const SPathShaderMapKey &inKey) const
+ {
+ return m_Name == inKey.m_Name && m_MaterialKey == inKey.m_MaterialKey;
+ }
+};
+
+namespace eastl {
+template <>
+struct hash<SPathShaderMapKey>
+{
+ size_t operator()(const SPathShaderMapKey &inKey) const { return inKey.m_HashCode; }
+};
+}
+
+namespace {
+
+struct SPathSubPathBuffer
+{
+ NVAllocatorCallback &m_Allocator;
+ nvvector<SPathAnchorPoint> m_SourceData;
+ SPathDirtyFlags m_Flags;
+ SPathSubPath &m_SubPath;
+ bool m_Closed;
+
+ QT3DSI32 m_RefCount;
+
+ SPathSubPathBuffer(NVAllocatorCallback &alloc, SPathSubPath &inSubPath)
+ : m_Allocator(alloc)
+ , m_SourceData(alloc, "m_SourceData")
+ , m_SubPath(inSubPath)
+ , m_Closed(false)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() { atomicIncrement(&m_RefCount); }
+ void release()
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Allocator);
+ NVDelete(alloc, this);
+ }
+ }
+};
+
+struct SImportPathWrapper
+{
+ NVAllocatorCallback &m_Alloc;
+ UICIMP::SPathBuffer *m_Path;
+ QT3DSI32 m_RefCount;
+
+ SImportPathWrapper(NVAllocatorCallback &inAlloc, UICIMP::SPathBuffer &inPath)
+ : m_Alloc(inAlloc)
+ , m_Path(&inPath)
+ , m_RefCount(0)
+ {
+ }
+
+ ~SImportPathWrapper() { m_Path->Free(m_Alloc); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Alloc);
+ NVDelete(alloc, this);
+ }
+ }
+};
+
+typedef NVScopedRefCounted<SImportPathWrapper> TPathBufferPtr;
+
+struct SPathBuffer
+{
+ NVAllocatorCallback &m_Allocator;
+ nvvector<NVScopedRefCounted<SPathSubPathBuffer>> m_SubPaths;
+ TPathBufferPtr m_PathBuffer;
+
+ NVScopedRefCounted<NVRenderVertexBuffer> m_PatchData;
+ NVScopedRefCounted<NVRenderInputAssembler> m_InputAssembler;
+ NVScopedRefCounted<NVRenderPathRender> m_PathRender;
+
+ QT3DSVec2 m_BeginTaperData;
+ QT3DSVec2 m_EndTaperData;
+ QT3DSU32 m_NumVertexes;
+ PathTypes::Enum m_PathType;
+ QT3DSF32 m_Width;
+ QT3DSF32 m_CPUError;
+ NVBounds3 m_Bounds;
+ Option<STaperInformation> m_BeginTaper;
+ Option<STaperInformation> m_EndTaper;
+ CRegisteredString m_SourcePath;
+
+ // Cached data for geometry paths
+
+ SPathDirtyFlags m_Flags;
+
+ QT3DSI32 m_RefCount;
+
+ SPathBuffer(NVAllocatorCallback &alloc)
+ : m_Allocator(alloc)
+ , m_SubPaths(alloc, "m_SubPaths")
+ , m_NumVertexes(0)
+ , m_PathType(PathTypes::Geometry)
+ , m_Width(0.0f)
+ , m_CPUError(0.0f)
+ , m_Bounds(NVBounds3::empty())
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() { atomicIncrement(&m_RefCount); }
+ void release()
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Allocator);
+ NVDelete(alloc, this);
+ }
+ }
+
+ void ClearGeometryPathData()
+ {
+ m_PatchData = NULL;
+ m_InputAssembler = NULL;
+ }
+
+ void ClearPaintedPathData() { m_PathRender = NULL; }
+
+ UICIMP::SPathBuffer GetPathData(UICIMP::IPathBufferBuilder &inSpec)
+ {
+ if (m_SubPaths.size()) {
+ inSpec.Clear();
+ for (QT3DSU32 idx = 0, end = m_SubPaths.size(); idx < end; ++idx) {
+ const SPathSubPathBuffer &theSubPathBuffer(*m_SubPaths[idx]);
+ for (QT3DSU32 equationIdx = 0, equationEnd = theSubPathBuffer.m_SourceData.size();
+ equationIdx < equationEnd; ++equationIdx) {
+ const SPathAnchorPoint &thePoint = theSubPathBuffer.m_SourceData[equationIdx];
+ if (equationIdx == 0) {
+ inSpec.MoveTo(thePoint.m_Position);
+ } else {
+ const SPathAnchorPoint &thePrevPoint =
+ theSubPathBuffer.m_SourceData[equationIdx - 1];
+ QT3DSVec2 c1 = IPathManager::GetControlPointFromAngleDistance(
+ thePrevPoint.m_Position, thePrevPoint.m_OutgoingAngle,
+ thePrevPoint.m_OutgoingDistance);
+ QT3DSVec2 c2 = IPathManager::GetControlPointFromAngleDistance(
+ thePoint.m_Position, thePoint.m_IncomingAngle,
+ thePoint.m_IncomingDistance);
+ QT3DSVec2 p2 = thePoint.m_Position;
+ inSpec.CubicCurveTo(c1, c2, p2);
+ }
+ }
+ if (theSubPathBuffer.m_Closed)
+ inSpec.Close();
+ }
+ return inSpec.GetPathBuffer();
+ } else if (m_PathBuffer.mPtr)
+ return *m_PathBuffer.mPtr->m_Path;
+ return UICIMP::SPathBuffer();
+ }
+
+ void SetPathType(PathTypes::Enum inPathType)
+ {
+ if (inPathType != m_PathType) {
+ switch (m_PathType) {
+ case PathTypes::Geometry:
+ ClearGeometryPathData();
+ break;
+ case PathTypes::Painted:
+ ClearPaintedPathData();
+ break;
+ }
+ m_Flags.clearOrSet(true, PathDirtyFlagValues::PathType);
+ }
+ m_PathType = inPathType;
+ }
+
+ static Option<STaperInformation> ToTaperInfo(PathCapping::Enum capping, QT3DSF32 capOffset,
+ QT3DSF32 capOpacity, QT3DSF32 capWidth)
+ {
+ if (capping == PathCapping::Noner)
+ return Empty();
+
+ return STaperInformation(capOffset, capOpacity, capWidth);
+ }
+
+ void SetBeginTaperInfo(PathCapping::Enum capping, QT3DSF32 capOffset, QT3DSF32 capOpacity,
+ QT3DSF32 capWidth)
+ {
+ Option<STaperInformation> newBeginInfo =
+ ToTaperInfo(capping, capOffset, capOpacity, capWidth);
+ if (!OptionEquals(newBeginInfo, m_BeginTaper)) {
+ m_BeginTaper = newBeginInfo;
+ m_Flags.clearOrSet(true, PathDirtyFlagValues::BeginTaper);
+ }
+ }
+
+ void SetEndTaperInfo(PathCapping::Enum capping, QT3DSF32 capOffset, QT3DSF32 capOpacity,
+ QT3DSF32 capWidth)
+ {
+ Option<STaperInformation> newEndInfo =
+ ToTaperInfo(capping, capOffset, capOpacity, capWidth);
+ if (!OptionEquals(newEndInfo, m_EndTaper)) {
+ m_EndTaper = newEndInfo;
+ m_Flags.clearOrSet(true, PathDirtyFlagValues::EndTaper);
+ }
+ }
+
+ void SetWidth(QT3DSF32 inWidth)
+ {
+ if (inWidth != m_Width) {
+ m_Width = inWidth;
+ m_Flags.clearOrSet(true, PathDirtyFlagValues::Width);
+ }
+ }
+
+ void SetCPUError(QT3DSF32 inError)
+ {
+ if (inError != m_CPUError) {
+ m_CPUError = inError;
+ m_Flags.clearOrSet(true, PathDirtyFlagValues::CPUError);
+ }
+ }
+};
+
+struct SPathGeneratedShader
+{
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSF32> m_Width;
+ NVRenderCachedShaderProperty<QT3DSF32> m_InnerTessAmount;
+ NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessAmount;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_BeginTaperData;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_EndTaperData;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_WireframeViewMatrix;
+
+ QT3DSI32 m_RefCount;
+
+ SPathGeneratedShader(NVRenderShaderProgram &sh, NVAllocatorCallback &alloc)
+ : m_Allocator(alloc)
+ , m_Shader(sh)
+ , m_Width("pathWidth", sh)
+ , m_InnerTessAmount("tessInnerLevel", sh)
+ , m_EdgeTessAmount("tessEdgeLevel", sh)
+ , m_BeginTaperData("beginTaperInfo", sh)
+ , m_EndTaperData("endTaperInfo", sh)
+ , m_WireframeViewMatrix("viewport_matrix", sh)
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ ~SPathGeneratedShader() { m_Shader.release(); }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &allocator(m_Allocator);
+ NVDelete(allocator, this);
+ }
+ }
+};
+
+struct SPathVertexPipeline : public SVertexPipelineImpl
+{
+
+ SPathVertexPipeline(IShaderProgramGenerator &inProgGenerator,
+ IMaterialShaderGenerator &inMaterialGenerator, NVAllocatorCallback &inAlloc,
+ IStringTable &inStringTable, bool inWireframe)
+ : SVertexPipelineImpl(inAlloc, inMaterialGenerator, inProgGenerator, inStringTable,
+ inWireframe)
+ {
+ }
+
+ // Trues true if the code was *not* set.
+ bool SetCode(GenerationFlagValues::Enum inCode)
+ {
+ if (((QT3DSU32)m_GenerationFlags & inCode) != 0)
+ return true;
+ m_GenerationFlags |= inCode;
+ return false;
+ }
+
+ void AssignTessEvalVarying(const char8_t *inVarName, const char8_t *inVarValueExpr)
+ {
+ const char8_t *ext = "";
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
+ ext = "TE";
+ TessEval() << "\t" << inVarName << ext << " = " << inVarValueExpr << ";" << Endl;
+ }
+
+ void AssignOutput(const char8_t *inVarName, const char8_t *inVarValueExpr) override
+ {
+ AssignTessEvalVarying(inVarName, inVarValueExpr);
+ }
+
+ void InitializeTessShaders()
+ {
+ IShaderStageGenerator &theTessControl(TessControl());
+ IShaderStageGenerator &theTessEval(TessEval());
+
+ // first setup tessellation control shader
+ theTessControl.AddUniform("tessEdgeLevel", "float");
+ theTessControl.AddUniform("tessInnerLevel", "float");
+
+ theTessControl.AddInclude("tessellationPath.glsllib");
+
+ theTessControl.Append("void main() {\n");
+ theTessControl.Append(
+ "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
+ theTessControl.Append("\ttessShader( tessEdgeLevel, tessInnerLevel );\n");
+
+ bool hasGeometryShader =
+ ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry) != NULL;
+
+ // second setup tessellation control shader
+ eastl::string outExt("");
+ if (hasGeometryShader)
+ outExt = "TE";
+
+ theTessEval.AddInclude("tessellationPath.glsllib");
+ theTessEval.AddUniform("normal_matrix", "mat3");
+ theTessEval.AddUniform("model_view_projection", "mat4");
+ theTessEval.AddUniform("pathWidth", "float");
+ theTessEval.AddUniform("material_diffuse", "vec4");
+ AddInterpolationParameter("varTexCoord0", "vec2");
+ AddInterpolationParameter("varTessOpacity", "float");
+
+ theTessEval.Append("void main() {\n");
+ theTessEval.Append("\tSTessShaderResult shaderResult = tessShader( pathWidth );\n");
+ theTessEval.Append("\tvec3 pos = shaderResult.m_Position;\n");
+ AssignTessEvalVarying("varTessOpacity", "shaderResult.m_Opacity");
+ AssignTessEvalVarying("varTexCoord0", "shaderResult.m_TexCoord.xy");
+ if (hasGeometryShader)
+ theTessEval << "\tvec2 varTexCoord0 = shaderResult.m_TexCoord.xy;\n";
+
+ theTessEval << "\tvec3 object_normal = vec3(0.0, 0.0, 1.0);\n";
+ theTessEval << "\tvec3 world_normal = normal_matrix * object_normal;\n";
+ theTessEval << "\tvec3 tangent = vec3( shaderResult.m_Tangent, 0.0 );\n";
+ theTessEval << "\tvec3 binormal = vec3( shaderResult.m_Binormal, 0.0 );\n";
+
+ // These are necessary for texture generation.
+ theTessEval << "\tvec3 uTransform;" << Endl;
+ theTessEval << "\tvec3 vTransform;" << Endl;
+
+ if (m_DisplacementImage) {
+ MaterialGenerator().GenerateImageUVCoordinates(*this, m_DisplacementIdx, 0,
+ *m_DisplacementImage);
+ theTessEval.AddUniform("displaceAmount", "float");
+ theTessEval.AddUniform("model_matrix", "mat4");
+ theTessEval.AddInclude("uicDefaultMaterialFileDisplacementTexture.glsllib");
+ IDefaultMaterialShaderGenerator::SImageVariableNames theVarNames =
+ MaterialGenerator().GetImageVariableNames(m_DisplacementIdx);
+
+ theTessEval.AddUniform(theVarNames.m_ImageSampler, "sampler2D");
+ IDefaultMaterialShaderGenerator::SImageVariableNames theNames =
+ MaterialGenerator().GetImageVariableNames(m_DisplacementIdx);
+ theTessEval << "\tpos = uicDefaultMaterialFileDisplacementTexture( "
+ << theNames.m_ImageSampler << ", displaceAmount, "
+ << theNames.m_ImageFragCoords << outExt.c_str() << ", vec3( 0.0, 0.0, 1.0 )"
+ << ", pos.xyz );" << Endl;
+ }
+ }
+ void FinalizeTessControlShader() {}
+
+ void FinalizeTessEvaluationShader()
+ {
+ eastl::string outExt("");
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
+ outExt = "TE";
+
+ IShaderStageGenerator &tessEvalShader(
+ *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
+ tessEvalShader.Append("\tgl_Position = model_view_projection * vec4( pos, 1.0 );\n");
+ }
+
+ void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) override
+ {
+ SetupDisplacement(displacementImageIdx, displacementImage);
+
+ TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
+ theStages |= ShaderGeneratorStages::TessControl;
+ theStages |= ShaderGeneratorStages::TessEval;
+ if (m_Wireframe) {
+ theStages |= ShaderGeneratorStages::Geometry;
+ }
+ ProgramGenerator().BeginProgram(theStages);
+ InitializeTessShaders();
+ if (m_Wireframe) {
+ InitializeWireframeGeometryShader();
+ }
+ // Open up each stage.
+ IShaderStageGenerator &vertexShader(Vertex());
+
+ vertexShader.AddIncoming("attr_pos", "vec4");
+
+ // useless vert shader because real work is done in TES.
+ vertexShader << "void main()\n"
+ "{\n";
+ vertexShader << "\tgl_Position = attr_pos;\n"; // if tessellation is enabled pass down
+ // object coordinates;
+ vertexShader << "}\n";
+ }
+
+ void BeginFragmentGeneration() override
+ {
+ Fragment().AddUniform("material_diffuse", "vec4");
+ Fragment() << "void main()" << Endl << "{" << Endl;
+ // We do not pass object opacity through the pipeline.
+ Fragment() << "\tfloat object_opacity = varTessOpacity * material_diffuse.a;" << Endl;
+ }
+ void DoGenerateUVCoords(QT3DSU32) override
+ {
+ // these are always generated regardless
+ }
+
+ // fragment shader expects varying vertex normal
+ // lighting in vertex pipeline expects world_normal
+ void DoGenerateWorldNormal() override { AssignTessEvalVarying("varNormal", "world_normal"); }
+ void DoGenerateObjectNormal() override
+ {
+ AssignTessEvalVarying("varObjectNormal", "object_normal");
+ }
+ void DoGenerateWorldPosition() override
+ {
+ TessEval().AddUniform("model_matrix", "mat4");
+ TessEval()
+ << "\tvec3 local_model_world_position = vec3((model_matrix * vec4(pos, 1.0)).xyz);\n";
+ }
+ void DoGenerateVarTangentAndBinormal() override
+ {
+ TessEval().AddUniform("normal_matrix", "mat3");
+ AssignOutput("varTangent", "normal_matrix * tangent");
+ AssignOutput("varBinormal", "normal_matrix * binormal");
+ }
+
+ void EndVertexGeneration() override
+ {
+
+ if (HasTessellation()) {
+ // finalize tess control shader
+ FinalizeTessControlShader();
+ // finalize tess evaluation shader
+ FinalizeTessEvaluationShader();
+
+ TessControl().Append("}");
+ TessEval().Append("}");
+ }
+ if (m_Wireframe) {
+ // finalize geometry shader
+ FinalizeWireframeGeometryShader();
+ Geometry().Append("}");
+ }
+ }
+
+ void EndFragmentGeneration() override { Fragment().Append("}"); }
+
+ void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override
+ {
+ m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType)));
+ Fragment().AddIncoming(inName, inType);
+ if (HasTessellation()) {
+ eastl::string nameBuilder;
+ nameBuilder.assign(inName);
+ if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
+ nameBuilder.append("TE");
+
+ TessEval().AddOutgoing(nameBuilder.c_str(), inType);
+ }
+ }
+
+ IShaderStageGenerator &ActiveStage() override { return TessEval(); }
+};
+
+struct SPathXYGeneratedShader
+{
+ NVAllocatorCallback &m_Allocator;
+ NVRenderShaderProgram &m_Shader;
+ NVRenderCachedShaderProperty<QT3DSVec4> m_RectDimensions;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ModelMatrix;
+ NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPosition;
+ NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
+ QT3DSI32 m_RefCount;
+
+ SPathXYGeneratedShader(NVRenderShaderProgram &sh, NVAllocatorCallback &alloc)
+ : m_Allocator(alloc)
+ , m_Shader(sh)
+ , m_RectDimensions("uni_rect_dimensions", sh)
+ , m_ModelMatrix("model_matrix", sh)
+ , m_CameraPosition("camera_position", sh)
+ , m_CameraProperties("camera_properties", sh)
+ , m_RefCount(0)
+ {
+ m_Shader.addRef();
+ }
+ virtual ~SPathXYGeneratedShader() { m_Shader.release(); }
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &allocator(m_Allocator);
+ NVDelete(allocator, this);
+ }
+ }
+};
+
+// Helper implements the vertex pipeline for mesh subsets when bound to the default material.
+// Should be completely possible to use for custom materials with a bit of refactoring.
+struct SXYRectVertexPipeline : public SVertexPipelineImpl
+{
+
+ SXYRectVertexPipeline(IShaderProgramGenerator &inProgGenerator,
+ IMaterialShaderGenerator &inMaterialGenerator,
+ NVAllocatorCallback &inAlloc, IStringTable &inStringTable)
+ : SVertexPipelineImpl(inAlloc, inMaterialGenerator, inProgGenerator, inStringTable, false)
+ {
+ }
+
+ void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
+ SRenderableImage *displacementImage) override
+ {
+ m_DisplacementIdx = displacementImageIdx;
+ m_DisplacementImage = displacementImage;
+
+ TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
+ ProgramGenerator().BeginProgram(theStages);
+ // Open up each stage.
+ IShaderStageGenerator &vertexShader(Vertex());
+ vertexShader.AddIncoming("attr_pos", "vec2");
+ vertexShader.AddUniform("uni_rect_dimensions", "vec4");
+
+ vertexShader << "void main()" << Endl << "{" << Endl;
+ vertexShader << "\tvec3 uTransform;" << Endl;
+ vertexShader << "\tvec3 vTransform;" << Endl;
+
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader
+ << "\tfloat posX = mix( uni_rect_dimensions.x, uni_rect_dimensions.z, attr_pos.x );"
+ << Endl;
+ vertexShader
+ << "\tfloat posY = mix( uni_rect_dimensions.y, uni_rect_dimensions.w, attr_pos.y );"
+ << Endl;
+ vertexShader << "\tvec3 pos = vec3(posX, posY, 0.0 );" << Endl;
+ vertexShader.Append("\tgl_Position = model_view_projection * vec4(pos, 1.0);");
+ }
+
+ void OutputParaboloidDepthShaders()
+ {
+ TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
+ ProgramGenerator().BeginProgram(theStages);
+ IShaderStageGenerator &vertexShader(Vertex());
+ vertexShader.AddIncoming("attr_pos", "vec2");
+ vertexShader.AddUniform("uni_rect_dimensions", "vec4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ vertexShader << "void main()" << Endl << "{" << Endl;
+ vertexShader
+ << "\tfloat posX = mix( uni_rect_dimensions.x, uni_rect_dimensions.z, attr_pos.x );"
+ << Endl;
+ vertexShader
+ << "\tfloat posY = mix( uni_rect_dimensions.y, uni_rect_dimensions.w, attr_pos.y );"
+ << Endl;
+ vertexShader << "\tvec3 pos = vec3(posX, posY, 0.0 );" << Endl;
+ IShaderProgramGenerator::OutputParaboloidDepthTessEval(vertexShader);
+ vertexShader << "}" << Endl;
+
+ IShaderProgramGenerator::OutputParaboloidDepthFragment(Fragment());
+ }
+
+ void OutputCubeFaceDepthShaders()
+ {
+ TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
+ ProgramGenerator().BeginProgram(theStages);
+ IShaderStageGenerator &vertexShader(Vertex());
+ IShaderStageGenerator &fragmentShader(Fragment());
+ vertexShader.AddIncoming("attr_pos", "vec2");
+ vertexShader.AddUniform("uni_rect_dimensions", "vec4");
+ vertexShader.AddUniform("model_matrix", "mat4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.AddOutgoing("world_pos", "vec4");
+ vertexShader.Append("void main() {");
+ vertexShader.Append(
+ " float posX = mix( uni_rect_dimensions.x, uni_rect_dimensions.z, attr_pos.x );");
+ vertexShader.Append(
+ " float posY = mix( uni_rect_dimensions.y, uni_rect_dimensions.w, attr_pos.y );");
+ vertexShader.Append(" world_pos = model_matrix * vec4( posX, posY, 0.0, 1.0 );");
+ vertexShader.Append(" world_pos /= world_pos.w;");
+ vertexShader.Append(
+ " gl_Position = model_view_projection * vec4( posX, posY, 0.0, 1.0 );");
+ vertexShader.Append("}");
+
+ fragmentShader.AddUniform("camera_position", "vec3");
+ fragmentShader.AddUniform("camera_properties", "vec2");
+
+ BeginFragmentGeneration();
+ fragmentShader.Append(
+ "\tfloat dist = 0.5 * length( world_pos.xyz - camera_position );"); // Why?
+ fragmentShader.Append(
+ "\tdist = (dist - camera_properties.x) / (camera_properties.y - camera_properties.x);");
+ fragmentShader.Append("\tfragOutput = vec4(dist);");
+ fragmentShader.Append("}");
+ }
+
+ void BeginFragmentGeneration() override
+ {
+ Fragment().AddUniform("material_diffuse", "vec4");
+ Fragment() << "void main()" << Endl << "{" << Endl;
+ // We do not pass object opacity through the pipeline.
+ Fragment() << "\tfloat object_opacity = material_diffuse.a;" << Endl;
+ }
+
+ void AssignOutput(const char8_t *inVarName, const char8_t *inVarValue) override
+ {
+ Vertex() << "\t" << inVarName << " = " << inVarValue << ";\n";
+ }
+ void DoGenerateUVCoords(QT3DSU32) override { Vertex() << "\tvarTexCoord0 = attr_pos;" << Endl; }
+
+ // fragment shader expects varying vertex normal
+ // lighting in vertex pipeline expects world_normal
+ void DoGenerateWorldNormal() override
+ {
+ IShaderStageGenerator &vertexGenerator(Vertex());
+ vertexGenerator.AddUniform("normal_matrix", "mat3");
+ vertexGenerator.Append(
+ "\tvec3 world_normal = normalize(normal_matrix * vec3( 0.0, 0.0, 1.0) ).xyz;");
+ vertexGenerator.Append("\tvarNormal = world_normal;");
+ }
+
+ void DoGenerateObjectNormal() override
+ {
+ AddInterpolationParameter("varObjectNormal", "vec3");
+ Vertex().Append("\tvarObjectNormal = vec3(0.0, 0.0, 1.0 );");
+ }
+
+ void DoGenerateWorldPosition() override
+ {
+ Vertex().Append("\tvec3 local_model_world_position = (model_matrix * vec4(pos, 1.0)).xyz;");
+ AssignOutput("varWorldPos", "local_model_world_position");
+ }
+
+ void DoGenerateVarTangentAndBinormal() override
+ {
+ Vertex().AddIncoming("attr_textan", "vec3");
+ Vertex().AddIncoming("attr_binormal", "vec3");
+ Vertex() << "\tvarTangent = normal_matrix * vec3(1.0, 0.0, 0.0);" << Endl
+ << "\tvarBinormal = normal_matrix * vec3(0.0, 1.0, 0.0);" << Endl;
+ }
+
+ void EndVertexGeneration() override { Vertex().Append("}"); }
+
+ void EndFragmentGeneration() override { Fragment().Append("}"); }
+
+ void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override
+ {
+ m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType)));
+ Vertex().AddOutgoing(inName, inType);
+ Fragment().AddIncoming(inName, inType);
+ }
+
+ IShaderStageGenerator &ActiveStage() override { return Vertex(); }
+};
+
+struct SPathManager : public IPathManager
+{
+ typedef nvhash_map<SPath *, NVScopedRefCounted<SPathBuffer>> TPathBufferHash;
+ typedef nvhash_map<SPathSubPath *, NVScopedRefCounted<SPathSubPathBuffer>>
+ TPathSubPathBufferHash;
+ typedef nvhash_map<SPathShaderMapKey, NVScopedRefCounted<SPathGeneratedShader>> TShaderMap;
+ typedef nvhash_map<SPathShaderMapKey, NVScopedRefCounted<SPathXYGeneratedShader>>
+ TPaintedShaderMap;
+ typedef nvhash_map<CRegisteredString, TPathBufferPtr> TStringPathBufferMap;
+
+ IUICRenderContextCore &m_CoreContext;
+ IUICRenderContext *m_RenderContext;
+ eastl::string m_IdBuilder;
+ TPathSubPathBufferHash m_SubPathBuffers;
+ TPathBufferHash m_Buffers;
+ nvvector<SResultCubic> m_SubdivResult;
+ nvvector<QT3DSF32> m_KeyPointVec;
+ nvvector<QT3DSVec4> m_PatchBuffer;
+ TShaderMap m_PathGeometryShaders;
+ TPaintedShaderMap m_PathPaintedShaders;
+ TStringPathBufferMap m_SourcePathBufferMap;
+ Mutex m_PathBufferMutex;
+
+ NVScopedRefCounted<SPathGeneratedShader> m_DepthShader;
+ NVScopedRefCounted<SPathGeneratedShader> m_DepthDisplacementShader;
+ NVScopedRefCounted<SPathGeneratedShader> m_GeometryShadowShader;
+ NVScopedRefCounted<SPathGeneratedShader> m_GeometryCubeShadowShader;
+ NVScopedRefCounted<SPathGeneratedShader> m_GeometryDisplacementShadowShader;
+
+ NVScopedRefCounted<SPathXYGeneratedShader> m_PaintedDepthShader;
+ NVScopedRefCounted<SPathXYGeneratedShader> m_PaintedShadowShader;
+ NVScopedRefCounted<SPathXYGeneratedShader> m_PaintedCubeShadowShader;
+ NVScopedRefCounted<NVRenderInputAssembler> m_PaintedRectInputAssembler;
+ NVScopedRefCounted<NVRenderVertexBuffer> m_PaintedRectVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> m_PaintedRectIndexBuffer;
+
+ nvvector<NVScopedRefCounted<NVRenderDepthStencilState>> m_DepthStencilStates;
+
+ NVScopedRefCounted<NVRenderPathSpecification> m_PathSpecification;
+ NVScopedRefCounted<UICIMP::IPathBufferBuilder> m_PathBuilder;
+
+ QT3DSI32 m_RefCount;
+
+ SPathManager(IUICRenderContextCore &inRC)
+ : m_CoreContext(inRC)
+ , m_RenderContext(NULL)
+ , m_SubPathBuffers(inRC.GetAllocator(), "m_SubPathBuffers")
+ , m_Buffers(inRC.GetAllocator(), "m_Buffers")
+ , m_SubdivResult(inRC.GetAllocator(), "m_SubdivResult")
+ , m_KeyPointVec(inRC.GetAllocator(), "m_KeyPointVec")
+ , m_PatchBuffer(inRC.GetAllocator(), "m_QuadStrip")
+ , m_PathGeometryShaders(inRC.GetAllocator(), "m_PathGeometryShaders")
+ , m_PathPaintedShaders(inRC.GetAllocator(), "m_PathPaintedShaders")
+ , m_SourcePathBufferMap(inRC.GetAllocator(), "m_SourcePathBufferMap")
+ , m_PathBufferMutex(inRC.GetAllocator())
+ , m_DepthStencilStates(inRC.GetAllocator(), "m_DepthStencilStates")
+ , m_RefCount(0)
+ {
+ }
+
+ virtual ~SPathManager() { m_PaintedRectInputAssembler = NULL; }
+
+ NVAllocatorCallback &GetAllocator() { return m_CoreContext.GetAllocator(); }
+ IStringTable &GetStringTable() { return m_CoreContext.GetStringTable(); }
+ NVFoundationBase &GetFoundation() { return m_CoreContext.GetFoundation(); }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(GetAllocator());
+ NVDelete(alloc, this);
+ }
+ }
+ // Called during binary load which is heavily threaded.
+ void SetPathSubPathData(const SPathSubPath &inPath,
+ NVConstDataRef<SPathAnchorPoint> inPathCubicCurves) override
+ {
+ Mutex::ScopedLock __locker(m_PathBufferMutex);
+ eastl::pair<TPathSubPathBufferHash::iterator, bool> inserter =
+ m_SubPathBuffers.insert(eastl::make_pair((SPathSubPath *)&inPath,
+ NVScopedRefCounted<SPathSubPathBuffer>(NULL)));
+ if (!inserter.first->second)
+ inserter.first->second = QT3DS_NEW(GetAllocator(), SPathSubPathBuffer)(
+ GetAllocator(), const_cast<SPathSubPath &>(inPath));
+ SPathSubPathBuffer &theBuffer = *inserter.first->second.mPtr;
+ theBuffer.m_SourceData.assign(inPathCubicCurves.begin(), inPathCubicCurves.end());
+ theBuffer.m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
+ }
+
+ SPathBuffer *GetPathBufferObject(const SPath &inPath)
+ {
+ eastl::pair<TPathBufferHash::iterator, bool> inserter = m_Buffers.insert(
+ eastl::make_pair((SPath *)&inPath, NVScopedRefCounted<SPathBuffer>(NULL)));
+ if (inserter.second) {
+ inserter.first->second = QT3DS_NEW(GetAllocator(), SPathBuffer)(GetAllocator());
+ }
+ return inserter.first->second.mPtr;
+ }
+
+ SPathSubPathBuffer *GetPathBufferObject(const SPathSubPath &inSubPath)
+ {
+ TPathSubPathBufferHash::iterator iter = m_SubPathBuffers.find((SPathSubPath *)&inSubPath);
+ if (iter != m_SubPathBuffers.end())
+ return iter->second.mPtr;
+ return NULL;
+ }
+
+ NVDataRef<SPathAnchorPoint> GetPathSubPathBuffer(const SPathSubPath &inPath) override
+ {
+ SPathSubPathBuffer *theBuffer = GetPathBufferObject(inPath);
+ if (theBuffer)
+ return toDataRef(theBuffer->m_SourceData.data(), (QT3DSU32)theBuffer->m_SourceData.size());
+ return NVDataRef<SPathAnchorPoint>();
+ }
+
+ NVDataRef<SPathAnchorPoint> ResizePathSubPathBuffer(const SPathSubPath &inPath,
+ QT3DSU32 inNumAnchors) override
+ {
+ SPathSubPathBuffer *theBuffer = GetPathBufferObject(inPath);
+ if (theBuffer == NULL)
+ SetPathSubPathData(inPath, NVConstDataRef<SPathAnchorPoint>());
+ theBuffer = GetPathBufferObject(inPath);
+ theBuffer->m_SourceData.resize(inNumAnchors);
+ theBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
+ return toDataRef(theBuffer->m_SourceData.data(), (QT3DSU32)theBuffer->m_SourceData.size());
+ }
+
+ // This needs to be done using roots of the first derivative.
+ NVBounds3 GetBounds(const SPath &inPath) override
+ {
+ NVBounds3 retval(NVBounds3::empty());
+
+ SPathBuffer *thePathBuffer = GetPathBufferObject(inPath);
+ if (thePathBuffer) {
+ SPathDirtyFlags geomDirtyFlags(
+ PathDirtyFlagValues::SourceData | PathDirtyFlagValues::BeginTaper
+ | PathDirtyFlagValues::EndTaper | PathDirtyFlagValues::Width
+ | PathDirtyFlagValues::CPUError);
+
+ if ((((QT3DSU32)thePathBuffer->m_Flags) & (QT3DSU32)geomDirtyFlags) == 0) {
+ return thePathBuffer->m_Bounds;
+ }
+ }
+
+ for (SPathSubPath *theSubPath = inPath.m_FirstSubPath; theSubPath;
+ theSubPath = theSubPath->m_NextSubPath) {
+ SPathSubPathBuffer *theBuffer = GetPathBufferObject(*theSubPath);
+ if (!theBuffer)
+ continue;
+
+ QT3DSU32 numAnchors = theBuffer->m_SourceData.size();
+ for (QT3DSU32 idx = 0, end = numAnchors; idx < end; ++idx) {
+ const SPathAnchorPoint &thePoint(theBuffer->m_SourceData[idx]);
+ QT3DSVec2 position(thePoint.m_Position);
+ retval.include(QT3DSVec3(position.x, position.y, 0.0f));
+ if (idx) {
+ QT3DSVec2 incoming(IPathManagerCore::GetControlPointFromAngleDistance(
+ thePoint.m_Position, thePoint.m_IncomingAngle,
+ thePoint.m_IncomingDistance));
+ retval.include(QT3DSVec3(incoming.x, incoming.y, 0.0f));
+ }
+
+ if (idx < (numAnchors - 1)) {
+ QT3DSVec2 outgoing(IPathManagerCore::GetControlPointFromAngleDistance(
+ thePoint.m_Position, thePoint.m_OutgoingAngle,
+ thePoint.m_OutgoingDistance));
+ retval.include(QT3DSVec3(outgoing.x, outgoing.y, 0.0f));
+ }
+ }
+ }
+
+ return retval;
+ }
+
+ IPathManager &OnRenderSystemInitialize(IUICRenderContext &context) override
+ {
+ m_RenderContext = &context;
+ return *this;
+ }
+
+ // find a point that will join these two curves *if* they are not first derivative continuous
+ static Option<QT3DSVec2> GetAdjoiningPoint(QT3DSVec2 prevC2, QT3DSVec2 point, QT3DSVec2 C1, QT3DSF32 pathWidth)
+ {
+ QT3DSVec2 incomingDxDy = (point - prevC2);
+ QT3DSVec2 outgoingDxDy = (C1 - point);
+ incomingDxDy.normalize();
+ outgoingDxDy.normalize();
+ float determinant = (incomingDxDy.x * outgoingDxDy.y) - (incomingDxDy.y * outgoingDxDy.x);
+ if (fabs(determinant) > .001f) {
+ float mult = determinant > 0.0f ? 1.0f : -1.0f;
+ QT3DSVec2 incomingNormal(incomingDxDy.y, -incomingDxDy.x);
+ QT3DSVec2 outgoingNormal(outgoingDxDy.y, -outgoingDxDy.x);
+
+ QT3DSVec2 leftEdge = point + mult * incomingNormal * pathWidth;
+ QT3DSVec2 rightEdge = point + mult * outgoingNormal * pathWidth;
+
+ return (leftEdge + rightEdge) / 2.0f;
+ }
+ return Empty();
+ }
+
+ Option<eastl::pair<QT3DSU32, QT3DSF32>> FindBreakEquation(QT3DSF32 inTaperStart)
+ {
+ QT3DSF32 lengthTotal = 0;
+ for (QT3DSU32 idx = 0, end = m_SubdivResult.size(); idx < end; ++idx) {
+ if (lengthTotal + m_SubdivResult[idx].m_Length > inTaperStart) {
+ QT3DSF32 breakTValue = (inTaperStart - lengthTotal) / m_SubdivResult[idx].m_Length;
+ nvvector<SResultCubic>::iterator breakIter = m_SubdivResult.begin() + idx;
+ SCubicBezierCurve theCurve(breakIter->m_P1, breakIter->m_C1, breakIter->m_C2,
+ breakIter->m_P2);
+ eastl::pair<SCubicBezierCurve, SCubicBezierCurve> subdivCurve =
+ theCurve.SplitCubicBezierCurve(breakTValue);
+ QT3DSF32 originalBreakT =
+ breakIter->m_TStart + (breakIter->m_TStop - breakIter->m_TStart) * breakTValue;
+ // Update the existing item to point to the second equation
+ breakIter->m_P1 = subdivCurve.second.m_Points[0];
+ breakIter->m_C1 = subdivCurve.second.m_Points[1];
+ breakIter->m_C2 = subdivCurve.second.m_Points[2];
+ breakIter->m_P2 = subdivCurve.second.m_Points[3];
+ QT3DSF32 originalLength = breakIter->m_Length;
+ QT3DSF32 originalStart = breakIter->m_TStart;
+ breakIter->m_Length *= (1.0f - breakTValue);
+ breakIter->m_TStart = originalBreakT;
+ SResultCubic newCubic(subdivCurve.first.m_Points[0], subdivCurve.first.m_Points[1],
+ subdivCurve.first.m_Points[2], subdivCurve.first.m_Points[3],
+ breakIter->m_EquationIndex, originalStart, originalBreakT,
+ originalLength * breakTValue);
+
+ m_SubdivResult.insert(breakIter, newCubic);
+ return eastl::make_pair(idx, breakTValue);
+ }
+ lengthTotal += m_SubdivResult[idx].m_Length;
+ }
+ return Empty();
+ }
+
+ bool PrepareGeometryPathForRender(const SPath &inPath, SPathBuffer &inPathBuffer)
+ {
+
+ m_SubdivResult.clear();
+ m_KeyPointVec.clear();
+ const SPath &thePath(inPath);
+
+ inPathBuffer.SetBeginTaperInfo(thePath.m_BeginCapping, thePath.m_BeginCapOffset,
+ thePath.m_BeginCapOpacity, thePath.m_BeginCapWidth);
+ inPathBuffer.SetEndTaperInfo(thePath.m_EndCapping, thePath.m_EndCapOffset,
+ thePath.m_EndCapOpacity, thePath.m_EndCapWidth);
+ inPathBuffer.SetWidth(inPath.m_Width);
+ inPathBuffer.SetCPUError(inPath.m_LinearError);
+
+ SPathDirtyFlags geomDirtyFlags(PathDirtyFlagValues::SourceData
+ | PathDirtyFlagValues::BeginTaper
+ | PathDirtyFlagValues::EndTaper | PathDirtyFlagValues::Width
+ | PathDirtyFlagValues::CPUError);
+
+ bool retval = false;
+ if (!inPathBuffer.m_PatchData
+ || (((QT3DSU32)inPathBuffer.m_Flags) & (QT3DSU32)geomDirtyFlags) != 0) {
+ UICIMP::SPathBuffer thePathData = inPathBuffer.GetPathData(*m_PathBuilder);
+
+ QT3DSU32 dataIdx = 0;
+ QT3DSVec2 prevPoint(0, 0);
+ QT3DSU32 equationIdx = 0;
+ for (QT3DSU32 commandIdx = 0, commandEnd = thePathData.m_Commands.size();
+ commandIdx < commandEnd; ++commandIdx) {
+ switch (thePathData.m_Commands[commandIdx]) {
+ case UICIMP::PathCommand::MoveTo:
+ prevPoint =
+ QT3DSVec2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ break;
+ case UICIMP::PathCommand::CubicCurveTo: {
+ QT3DSVec2 c1(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ QT3DSVec2 c2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ QT3DSVec2 p2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ OuterAdaptiveSubdivideBezierCurve(
+ m_SubdivResult, m_KeyPointVec, SCubicBezierCurve(prevPoint, c1, c2, p2),
+ NVMax(inPath.m_LinearError, 1.0f), equationIdx);
+ ++equationIdx;
+ prevPoint = p2;
+ } break;
+ case UICIMP::PathCommand::Close:
+ break;
+
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ QT3DSF32 theLocalWidth = inPath.m_Width / 2.0f;
+
+ QT3DSVec2 theBeginTaperData(theLocalWidth, thePath.m_GlobalOpacity);
+ QT3DSVec2 theEndTaperData(theLocalWidth, thePath.m_GlobalOpacity);
+
+ QT3DSF32 pathLength = 0.0f;
+ for (QT3DSU32 idx = 0, end = m_SubdivResult.size(); idx < end; ++idx)
+ pathLength += m_SubdivResult[idx].m_Length;
+
+ if (thePath.m_BeginCapping == PathCapping::Taper
+ || thePath.m_EndCapping == PathCapping::Taper) {
+ QT3DSF32 maxTaperStart = pathLength / 2.0f;
+ if (thePath.m_BeginCapping == PathCapping::Taper) {
+ // Can't start more than halfway across the path.
+ QT3DSF32 taperStart = NVMin(thePath.m_BeginCapOffset, maxTaperStart);
+ QT3DSF32 endTaperWidth = thePath.m_BeginCapWidth;
+ QT3DSF32 endTaperOpacity = thePath.m_GlobalOpacity * thePath.m_BeginCapOpacity;
+ theBeginTaperData = QT3DSVec2(endTaperWidth, endTaperOpacity);
+ // Find where we need to break the current equations.
+ Option<eastl::pair<QT3DSU32, QT3DSF32>> breakEquationAndT(
+ FindBreakEquation(taperStart));
+ if (breakEquationAndT.hasValue()) {
+ QT3DSU32 breakEquation = breakEquationAndT->first;
+
+ QT3DSF32 lengthTotal = 0;
+ for (QT3DSU32 idx = 0, end = breakEquation; idx <= end; ++idx) {
+ SResultCubic &theCubic = m_SubdivResult[idx];
+ theCubic.m_Mode = SResultCubic::BeginTaper;
+
+ theCubic.m_TaperMultiplier[0] = lengthTotal / taperStart;
+ lengthTotal += theCubic.m_Length;
+ theCubic.m_TaperMultiplier[1] = lengthTotal / taperStart;
+ }
+ }
+ }
+ if (thePath.m_EndCapping == PathCapping::Taper) {
+ QT3DSF32 taperStart = NVMin(thePath.m_EndCapOffset, maxTaperStart);
+ QT3DSF32 endTaperWidth = thePath.m_EndCapWidth;
+ QT3DSF32 endTaperOpacity = thePath.m_GlobalOpacity * thePath.m_EndCapOpacity;
+ theEndTaperData = QT3DSVec2(endTaperWidth, endTaperOpacity);
+ // Invert taper start so that the forward search works.
+ Option<eastl::pair<QT3DSU32, QT3DSF32>> breakEquationAndT(
+ FindBreakEquation(pathLength - taperStart));
+
+ if (breakEquationAndT.hasValue()) {
+ QT3DSU32 breakEquation = breakEquationAndT->first;
+ ++breakEquation;
+
+ QT3DSF32 lengthTotal = 0;
+ for (QT3DSU32 idx = breakEquation, end = m_SubdivResult.size(); idx < end;
+ ++idx) {
+ SResultCubic &theCubic = m_SubdivResult[idx];
+ theCubic.m_Mode = SResultCubic::EndTaper;
+
+ theCubic.m_TaperMultiplier[0] = 1.0f - (lengthTotal / taperStart);
+ lengthTotal += theCubic.m_Length;
+ theCubic.m_TaperMultiplier[1] = 1.0f - (lengthTotal / taperStart);
+ }
+ }
+ }
+ }
+
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+ // Create quads out of each point.
+ if (m_SubdivResult.empty())
+ return false;
+
+ // Generate patches.
+ m_PatchBuffer.clear();
+ QT3DSF32 pathWidth = thePath.m_Width / 2.0f;
+ // texture coords
+ float texCoordU = 0.0;
+
+ for (QT3DSU32 idx = 0, end = m_SubdivResult.size(); idx < end; ++idx) {
+ // create patches
+ SResultCubic thePoint(m_SubdivResult[idx]);
+
+ m_PatchBuffer.push_back(CreateVec4(thePoint.m_P1, thePoint.m_C1));
+ m_PatchBuffer.push_back(CreateVec4(thePoint.m_C2, thePoint.m_P2));
+
+ // Now we need to take care of cases where the control points of the adjoining
+ // SubPaths
+ // do not line up; i.e. there is a discontinuity of the 1st derivative
+ // The simplest way to do this is to move the edge vertex to a halfway point
+ // between a line bisecting the two control lines
+ QT3DSVec2 incomingAdjoining(thePoint.m_P1);
+ QT3DSVec2 outgoingAdjoining(thePoint.m_P2);
+ if (idx) {
+ SResultCubic previousCurve = m_SubdivResult[idx - 1];
+ if (previousCurve.m_EquationIndex != thePoint.m_EquationIndex) {
+ QT3DSF32 anchorWidth =
+ thePoint.GetP1Width(pathWidth, theBeginTaperData.x, theEndTaperData.x);
+ Option<QT3DSVec2> adjoining = GetAdjoiningPoint(
+ previousCurve.m_C2, thePoint.m_P1, thePoint.m_C1, anchorWidth);
+ if (adjoining.hasValue())
+ incomingAdjoining = *adjoining;
+ }
+ }
+ if (idx < (end - 1)) {
+ SResultCubic nextCurve = m_SubdivResult[idx + 1];
+ if (nextCurve.m_EquationIndex != thePoint.m_EquationIndex) {
+ QT3DSF32 anchorWidth =
+ thePoint.GetP2Width(pathWidth, theBeginTaperData.x, theEndTaperData.x);
+ Option<QT3DSVec2> adjoining = GetAdjoiningPoint(thePoint.m_C2, thePoint.m_P2,
+ nextCurve.m_C1, anchorWidth);
+ if (adjoining.hasValue())
+ outgoingAdjoining = *adjoining;
+ }
+ }
+ m_PatchBuffer.push_back(CreateVec4(incomingAdjoining, outgoingAdjoining));
+
+ QT3DSVec4 taperData(0.0f);
+ taperData.x = thePoint.m_TaperMultiplier.x;
+ taperData.y = thePoint.m_TaperMultiplier.y;
+ // Note we could put a *lot* more data into this thing.
+ taperData.z = (QT3DSF32)thePoint.m_Mode;
+ m_PatchBuffer.push_back(taperData);
+
+ // texture coord generation
+ // note we only generate u here. v is generated in the tess shader
+ // u coord for P1 and C1
+ QT3DSVec2 udata(texCoordU, texCoordU + (thePoint.m_Length / pathLength));
+ texCoordU = udata.y;
+ m_PatchBuffer.push_back(QT3DSVec4(udata.x, udata.y, 0.0, 0.0));
+ }
+
+ // buffer size is 3.0*4.0*bufSize
+ QT3DSU32 bufSize = (QT3DSU32)m_PatchBuffer.size() * sizeof(QT3DSVec4);
+ QT3DSU32 stride = sizeof(QT3DSVec4);
+
+ if ((!inPathBuffer.m_PatchData) || inPathBuffer.m_PatchData->Size() < bufSize) {
+ inPathBuffer.m_PatchData = theRenderContext.CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Dynamic, bufSize, stride,
+ toU8DataRef(m_PatchBuffer.data(), (QT3DSU32)m_PatchBuffer.size()));
+ inPathBuffer.m_NumVertexes = (QT3DSU32)m_PatchBuffer.size();
+ inPathBuffer.m_InputAssembler = NULL;
+ } else {
+ QT3DS_ASSERT(inPathBuffer.m_PatchData->Size() >= bufSize);
+ inPathBuffer.m_PatchData->UpdateBuffer(
+ toU8DataRef(m_PatchBuffer.data(), (QT3DSU32)m_PatchBuffer.size()));
+ }
+
+ if (!inPathBuffer.m_InputAssembler) {
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry(
+ "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 4),
+ };
+
+ NVRenderDrawMode::Enum primType = NVRenderDrawMode::Patches;
+
+ NVRenderAttribLayout *theLayout =
+ theRenderContext.CreateAttributeLayout(toConstDataRef(theEntries, 1));
+ // How many vertices the TCS shader has access to in order to produce its output
+ // array of vertices.
+ const QT3DSU32 inputPatchVertexCount = 5;
+ inPathBuffer.m_InputAssembler = theRenderContext.CreateInputAssembler(
+ theLayout, toConstDataRef(inPathBuffer.m_PatchData.mPtr), NULL,
+ toConstDataRef(stride), toConstDataRef((QT3DSU32)0), primType,
+ inputPatchVertexCount);
+ }
+ inPathBuffer.m_BeginTaperData = theBeginTaperData;
+ inPathBuffer.m_EndTaperData = theEndTaperData;
+
+ // cache bounds
+ NVBounds3 bounds = GetBounds(inPath);
+ inPathBuffer.m_Bounds.minimum = bounds.minimum;
+ inPathBuffer.m_Bounds.maximum = bounds.maximum;
+ }
+
+ return retval;
+ }
+
+ IMaterialShaderGenerator *GetMaterialShaderGenertator(SPathRenderContext &inRenderContext)
+ {
+ bool isDefaultMaterial =
+ (inRenderContext.m_Material.m_Type == GraphObjectTypes::DefaultMaterial);
+
+ IMaterialShaderGenerator *theMaterialGenerator = NULL;
+ if (isDefaultMaterial)
+ theMaterialGenerator = &m_RenderContext->GetDefaultMaterialShaderGenerator();
+ else
+ theMaterialGenerator = &m_RenderContext->GetCustomMaterialShaderGenerator();
+
+ return theMaterialGenerator;
+ }
+
+ CRegisteredString GetMaterialNameForKey(SPathRenderContext &inRenderContext)
+ {
+ bool isDefaultMaterial =
+ (inRenderContext.m_Material.m_Type == GraphObjectTypes::DefaultMaterial);
+
+ if (!isDefaultMaterial) {
+ ICustomMaterialSystem &theMaterialSystem(m_RenderContext->GetCustomMaterialSystem());
+ const SCustomMaterial &theCustomMaterial(
+ reinterpret_cast<const SCustomMaterial &>(inRenderContext.m_Material));
+
+ return m_RenderContext->GetStringTable().RegisterStr(
+ theMaterialSystem.GetShaderName(theCustomMaterial));
+ }
+
+ return m_RenderContext->GetStringTable().RegisterStr("");
+ }
+
+ bool PreparePaintedPathForRender(const SPath &inPath, SPathBuffer &inPathBuffer)
+ {
+ NVRenderContext &theContext(this->m_RenderContext->GetRenderContext());
+ if (!inPathBuffer.m_PathRender
+ || (((QT3DSU32)inPathBuffer.m_Flags) & PathDirtyFlagValues::SourceData)) {
+ if (!inPathBuffer.m_PathRender) {
+ inPathBuffer.m_PathRender = theContext.CreatePathRender();
+ }
+
+ if (inPathBuffer.m_PathRender == NULL || m_PathSpecification == NULL) {
+ // QT3DS_ASSERT( false );
+ return false;
+ }
+
+ m_PathSpecification->Reset();
+ UICIMP::SPathBuffer thePathData = inPathBuffer.GetPathData(*m_PathBuilder);
+
+ QT3DSU32 dataIdx = 0;
+ for (QT3DSU32 commandIdx = 0, commandEnd = thePathData.m_Commands.size();
+ commandIdx < commandEnd; ++commandIdx) {
+
+ switch (thePathData.m_Commands[commandIdx]) {
+ case UICIMP::PathCommand::MoveTo:
+ m_PathSpecification->MoveTo(
+ QT3DSVec2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]));
+ dataIdx += 2;
+ break;
+ case UICIMP::PathCommand::CubicCurveTo: {
+ QT3DSVec2 c1(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ QT3DSVec2 c2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ QT3DSVec2 p2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
+ dataIdx += 2;
+ m_PathSpecification->CubicCurveTo(c1, c2, p2);
+ } break;
+ case UICIMP::PathCommand::Close:
+ m_PathSpecification->ClosePath();
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ inPathBuffer.m_PathRender->SetPathSpecification(*m_PathSpecification);
+
+ // cache bounds
+ NVBounds3 bounds = GetBounds(inPath);
+ inPathBuffer.m_Bounds.minimum = bounds.minimum;
+ inPathBuffer.m_Bounds.maximum = bounds.maximum;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ bool PrepareForRender(const SPath &inPath) override
+ {
+ SPathBuffer *thePathBuffer = GetPathBufferObject(inPath);
+ if (!thePathBuffer) {
+ return false;
+ }
+ NVRenderContext &theContext(this->m_RenderContext->GetRenderContext());
+ if (!m_PathSpecification)
+ m_PathSpecification = theContext.CreatePathSpecification();
+ if (!m_PathSpecification)
+ return false;
+ if (!m_PathBuilder)
+ m_PathBuilder = UICIMP::IPathBufferBuilder::CreateBuilder(GetFoundation());
+
+ thePathBuffer->SetPathType(inPath.m_PathType);
+ bool retval = false;
+ if (inPath.m_PathBuffer.IsValid() == false) {
+ thePathBuffer->m_PathBuffer = NULL;
+ // Ensure the SubPath list is identical and clear, percolating any dirty flags up to the
+ // path buffer.
+ QT3DSU32 SubPathIdx = 0;
+ for (const SPathSubPath *theSubPath = inPath.m_FirstSubPath; theSubPath;
+ theSubPath = theSubPath->m_NextSubPath, ++SubPathIdx) {
+ SPathSubPathBuffer *theSubPathBuffer = GetPathBufferObject(*theSubPath);
+ if (theSubPathBuffer == NULL)
+ continue;
+ thePathBuffer->m_Flags =
+ (QT3DSU32)(thePathBuffer->m_Flags | theSubPathBuffer->m_Flags);
+
+ if (theSubPathBuffer->m_Closed != theSubPath->m_Closed) {
+ thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
+ theSubPathBuffer->m_Closed = theSubPath->m_Closed;
+ }
+
+ if (thePathBuffer->m_SubPaths.size() <= SubPathIdx
+ || thePathBuffer->m_SubPaths[SubPathIdx] != theSubPathBuffer) {
+ thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
+ if (thePathBuffer->m_SubPaths.size() <= SubPathIdx)
+ thePathBuffer->m_SubPaths.push_back(theSubPathBuffer);
+ else
+ thePathBuffer->m_SubPaths[SubPathIdx] = theSubPathBuffer;
+ }
+
+ theSubPathBuffer->m_Flags.Clear();
+ }
+
+ if (SubPathIdx != thePathBuffer->m_SubPaths.size()) {
+ thePathBuffer->m_SubPaths.resize(SubPathIdx);
+ thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
+ }
+ } else {
+ thePathBuffer->m_SubPaths.clear();
+ eastl::pair<TStringPathBufferMap::iterator, bool> inserter =
+ m_SourcePathBufferMap.insert(
+ eastl::make_pair(inPath.m_PathBuffer, TPathBufferPtr()));
+ if (inserter.second) {
+ NVScopedRefCounted<IRefCountedInputStream> theStream =
+ m_CoreContext.GetInputStreamFactory().GetStreamForFile(
+ inPath.m_PathBuffer.c_str());
+ if (theStream) {
+ UICIMP::SPathBuffer *theNewBuffer =
+ UICIMP::SPathBuffer::Load(*theStream, GetFoundation());
+ if (theNewBuffer)
+ inserter.first->second = QT3DS_NEW(GetAllocator(), SImportPathWrapper)(
+ GetAllocator(), *theNewBuffer);
+ }
+ }
+ if (thePathBuffer->m_PathBuffer != inserter.first->second) {
+ thePathBuffer->m_PathBuffer = inserter.first->second;
+ thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
+ }
+ }
+
+ if (inPath.m_PathType == PathTypes::Geometry)
+ retval = PrepareGeometryPathForRender(inPath, *thePathBuffer);
+ else
+ retval = PreparePaintedPathForRender(inPath, *thePathBuffer);
+ thePathBuffer->m_Flags.Clear();
+ return retval;
+ }
+
+ void SetMaterialProperties(NVRenderShaderProgram &inShader, SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties &inRenderProperties)
+ {
+ IMaterialShaderGenerator *theMaterialGenerator =
+ GetMaterialShaderGenertator(inRenderContext);
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+ theRenderContext.SetActiveShader(&inShader);
+
+ theMaterialGenerator->SetMaterialProperties(
+ inShader, inRenderContext.m_Material, inRenderContext.m_CameraVec,
+ inRenderContext.m_ModelViewProjection, inRenderContext.m_NormalMatrix,
+ inRenderContext.m_Path.m_GlobalTransform, inRenderContext.m_FirstImage,
+ inRenderContext.m_Opacity, inRenderProperties);
+ }
+
+ void DoRenderGeometryPath(SPathGeneratedShader &inShader, SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties &inRenderProperties,
+ SPathBuffer &inPathBuffer)
+ {
+ if (inPathBuffer.m_InputAssembler == NULL)
+ return;
+
+ SetMaterialProperties(inShader.m_Shader, inRenderContext, inRenderProperties);
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+
+ inShader.m_BeginTaperData.Set(inPathBuffer.m_BeginTaperData);
+ inShader.m_EndTaperData.Set(inPathBuffer.m_EndTaperData);
+ if (inRenderContext.m_EnableWireframe) {
+ // we need the viewport matrix
+ NVRenderRect theViewport(theRenderContext.GetViewport());
+ QT3DSMat44 vpMatrix;
+ vpMatrix.column0 = QT3DSVec4((float)theViewport.m_Width / 2.0f, 0.0, 0.0, 0.0);
+ vpMatrix.column1 = QT3DSVec4(0.0, (float)theViewport.m_Height / 2.0f, 0.0, 0.0);
+ vpMatrix.column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ vpMatrix.column3 =
+ QT3DSVec4((float)theViewport.m_Width / 2.0f + (float)theViewport.m_X,
+ (float)theViewport.m_Height / 2.0f + (float)theViewport.m_Y, 0.0, 1.0);
+
+ inShader.m_WireframeViewMatrix.Set(vpMatrix);
+ }
+
+ QT3DSF32 tessEdgeValue = NVMin(64.0f, NVMax(1.0f, inRenderContext.m_Path.m_EdgeTessAmount));
+ QT3DSF32 tessInnerValue = NVMin(64.0f, NVMax(1.0f, inRenderContext.m_Path.m_InnerTessAmount));
+ inShader.m_EdgeTessAmount.Set(tessEdgeValue);
+ inShader.m_InnerTessAmount.Set(tessInnerValue);
+ inShader.m_Width.Set(inRenderContext.m_Path.m_Width / 2.0f);
+ theRenderContext.SetInputAssembler(inPathBuffer.m_InputAssembler);
+ theRenderContext.SetCullingEnabled(false);
+ NVRenderDrawMode::Enum primType = NVRenderDrawMode::Patches;
+ theRenderContext.Draw(primType, (QT3DSU32)inPathBuffer.m_NumVertexes, 0);
+ }
+
+ NVRenderDepthStencilState *GetDepthStencilState()
+ {
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+ NVRenderBoolOp::Enum theDepthFunction = theRenderContext.GetDepthFunction();
+ bool isDepthEnabled = theRenderContext.IsDepthTestEnabled();
+ bool isStencilEnabled = theRenderContext.IsStencilTestEnabled();
+ bool isDepthWriteEnabled = theRenderContext.IsDepthWriteEnabled();
+ for (QT3DSU32 idx = 0, end = m_DepthStencilStates.size(); idx < end; ++idx) {
+ NVRenderDepthStencilState &theState = *m_DepthStencilStates[idx];
+ if (theState.GetDepthFunc() == theDepthFunction
+ && theState.GetDepthEnabled() == isDepthEnabled
+ && theState.GetDepthMask() == isDepthWriteEnabled)
+ return &theState;
+ }
+ NVRenderStencilFunctionArgument theArg(NVRenderBoolOp::NotEqual, 0, 0xFF);
+ NVRenderStencilOperationArgument theOpArg(NVRenderStencilOp::Keep, NVRenderStencilOp::Keep,
+ NVRenderStencilOp::Zero);
+ m_DepthStencilStates.push_back(theRenderContext.CreateDepthStencilState(
+ isDepthEnabled, isDepthWriteEnabled, theDepthFunction, isStencilEnabled, theArg, theArg,
+ theOpArg, theOpArg));
+ return m_DepthStencilStates.back();
+ }
+
+ static void DoSetCorrectiveScale(const QT3DSMat44 &mvp, QT3DSMat44 &outScale, NVBounds3 pathBounds)
+ {
+ // Compute the projected locations for the paraboloid and regular projection
+ // and thereby set the appropriate scaling factor.
+ QT3DSVec3 points[4];
+ QT3DSVec3 projReg[4], projParab[4];
+ points[0] = pathBounds.minimum;
+ points[1] = QT3DSVec3(pathBounds.maximum.x, pathBounds.minimum.y, pathBounds.minimum.z);
+ points[2] = pathBounds.maximum;
+ points[3] = QT3DSVec3(pathBounds.minimum.x, pathBounds.maximum.y, pathBounds.maximum.z);
+
+ // Do the two different projections.
+ for (int i = 0; i < 4; ++i) {
+ QT3DSVec4 tmp;
+ tmp = mvp.transform(QT3DSVec4(points[i], 1.0f));
+ tmp /= tmp.w;
+ projReg[i] = tmp.getXYZ();
+ projParab[i] = tmp.getXYZ().getNormalized();
+ projParab[i] /= projParab[i].z + 1.0f;
+ }
+
+ NVBounds3 boundsA, boundsB;
+ for (int i = 0; i < 4; ++i) {
+ boundsA.include(projReg[i]);
+ boundsB.include(projParab[i]);
+ }
+ QT3DSF32 xscale =
+ (boundsB.maximum.x - boundsB.minimum.x) / (boundsA.maximum.x - boundsA.minimum.x);
+ QT3DSF32 yscale =
+ (boundsB.maximum.y - boundsB.minimum.y) / (boundsA.maximum.y - boundsA.minimum.y);
+ QT3DSF32 zscale = (boundsB.maximum - boundsB.minimum).magnitudeSquared()
+ / (boundsA.maximum - boundsA.minimum).magnitudeSquared();
+ // The default minimum here is just a stupid figure that looks good on our content because
+ // we'd
+ // been using it for a little while before. Just for demo.
+ xscale = NVMin<QT3DSF32>(0.5333333f, NVMin<QT3DSF32>(xscale, yscale));
+ yscale = NVMin<QT3DSF32>(0.5333333f, NVMin<QT3DSF32>(xscale, yscale));
+ outScale.scale(QT3DSVec4(xscale, yscale, zscale, 1.0f));
+ }
+
+ void DoRenderPaintedPath(SPathXYGeneratedShader &inShader, SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties &inRenderProperties,
+ SPathBuffer &inPathBuffer, bool isParaboloidPass = false)
+ {
+ if (!inPathBuffer.m_PathRender)
+ return;
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+ if (!m_PaintedRectInputAssembler) {
+ QT3DSVec2 vertexes[] = {
+ QT3DSVec2(0.0, 0.0), QT3DSVec2(1.0, 0.0), QT3DSVec2(1.0, 1.0), QT3DSVec2(0.0, 1.0),
+ };
+
+ QT3DSU8 indexes[] = {
+ 0, 1, 2, 2, 3, 0,
+ };
+
+ QT3DSU32 stride = sizeof(QT3DSVec2);
+
+ NVRenderVertexBufferEntry theBufferEntries[] = { NVRenderVertexBufferEntry(
+ "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 0) };
+
+ m_PaintedRectVertexBuffer = theRenderContext.CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static, 4 * sizeof(QT3DSVec2), sizeof(QT3DSVec2),
+ toU8DataRef(vertexes, 4));
+ m_PaintedRectIndexBuffer = theRenderContext.CreateIndexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static,
+ qt3ds::render::NVRenderComponentTypes::QT3DSU8, 6, toU8DataRef(indexes, 6));
+ NVRenderAttribLayout *theAttribLayout =
+ theRenderContext.CreateAttributeLayout(toConstDataRef(theBufferEntries, 1));
+ m_PaintedRectInputAssembler = theRenderContext.CreateInputAssembler(
+ theAttribLayout, toConstDataRef(m_PaintedRectVertexBuffer.mPtr),
+ m_PaintedRectIndexBuffer.mPtr, toConstDataRef(stride), toConstDataRef((QT3DSU32)0),
+ qt3ds::render::NVRenderDrawMode::Triangles);
+ }
+
+ // our current render target needs stencil
+ QT3DS_ASSERT(theRenderContext.GetStencilBits() > 0);
+
+ theRenderContext.SetDepthStencilState(GetDepthStencilState());
+
+ // http://developer.download.nvidia.com/assets/gamedev/files/Mixing_Path_Rendering_and_3D.pdf
+ theRenderContext.SetPathStencilDepthOffset(-.05f, -1.0f);
+
+ // Stencil out the geometry.
+ QT3DSMat44 pathMdlView = QT3DSMat44::createIdentity();
+ // Why is this happening? Well, it's because the painted-on path rendering is always
+ // a flat splatted 2D object. This is bad because a paraboloid projection demands a very
+ // different
+ // non-linear space into which we must draw. Path Rendering does not allow this sort of
+ // spatial
+ // warping internally, and all we end up passing in as a simple perspective projection.
+ // So for the fix, I'm scaling the actual "object" size so that it fits into the correctly
+ // projected
+ // polygon inside the paraboloid depth pass. Obviously, this scaling factor is wrong, and
+ // not generic
+ // enough to cover cases like polygons covering a large spread of the FOV and so on. It's
+ // really
+ // just a filthy awful, morally deplorable HACK. But it's basically the quickest fix at
+ // hand.
+ // This is also about the only possible approach that *could* work short of rendering the
+ // paths in
+ // a render-to-texture pass and splatting that texture on a sufficiently tessellated quad.
+ // Unless
+ // there's a way to program NVPR's internal projection scheme, that is.
+ // Geometry-based paths will work out better, I think, because they're actually creating
+ // geometry.
+ // This is essentially a 2D painting process inside a quad where the actual rendered region
+ // isn't
+ // exactly where NVPR thinks it should be because they're not projecting points the same
+ // way.
+ if (isParaboloidPass) {
+ DoSetCorrectiveScale(inRenderContext.m_ModelViewProjection, pathMdlView,
+ inPathBuffer.m_PathRender->GetPathObjectStrokeBox());
+ }
+
+ bool isStencilEnabled = theRenderContext.IsStencilTestEnabled();
+ theRenderContext.SetStencilTestEnabled(true);
+ theRenderContext.SetPathProjectionMatrix(inRenderContext.m_ModelViewProjection);
+ theRenderContext.SetPathModelViewMatrix(pathMdlView);
+
+ if (inRenderContext.m_IsStroke) {
+ inPathBuffer.m_PathRender->SetStrokeWidth(inRenderContext.m_Path.m_Width);
+ inPathBuffer.m_PathRender->StencilStroke();
+ } else
+ inPathBuffer.m_PathRender->StencilFill();
+
+ // The stencil buffer will dictate whether this object renders or not. So we need to ignore
+ // the depth test result.
+ NVRenderBoolOp::Enum theDepthFunc = theRenderContext.GetDepthFunction();
+ theRenderContext.SetDepthFunction(NVRenderBoolOp::AlwaysTrue);
+ // Now render the path; this resets the stencil buffer.
+ SetMaterialProperties(inShader.m_Shader, inRenderContext, inRenderProperties);
+ NVBounds3 rectBounds = inPathBuffer.m_PathRender->GetPathObjectStrokeBox();
+ if (isParaboloidPass) {
+ rectBounds.scale(1.570796326795f);
+ } // PKC : More of the same ugly hack.
+ inShader.m_RectDimensions.Set(QT3DSVec4(rectBounds.minimum.x, rectBounds.minimum.y,
+ rectBounds.maximum.x, rectBounds.maximum.y));
+ theRenderContext.SetInputAssembler(m_PaintedRectInputAssembler);
+ theRenderContext.SetCullingEnabled(false);
+ // Render exactly two triangles
+ theRenderContext.Draw(NVRenderDrawMode::Triangles, 6, 0);
+ theRenderContext.SetStencilTestEnabled(isStencilEnabled);
+ theRenderContext.SetDepthFunction(theDepthFunc);
+ }
+
+ void RenderDepthPrepass(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) override
+ {
+ SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
+ if (!thePathBuffer) {
+ return;
+ }
+
+ if (thePathBuffer->m_PathType == PathTypes::Geometry) {
+ QT3DSU32 displacementIdx = 0;
+ QT3DSU32 imageIdx = 0;
+ SRenderableImage *displacementImage = 0;
+
+ for (SRenderableImage *theImage = inRenderContext.m_FirstImage;
+ theImage != NULL && displacementImage == NULL;
+ theImage = theImage->m_NextImage, ++imageIdx) {
+ if (theImage->m_MapType == ImageMapTypes::Displacement) {
+ displacementIdx = imageIdx;
+ displacementImage = theImage;
+ }
+ }
+
+ NVScopedRefCounted<SPathGeneratedShader> &theDesiredDepthShader =
+ displacementImage == NULL ? m_DepthShader : m_DepthDisplacementShader;
+
+ if (!theDesiredDepthShader) {
+ IDefaultMaterialShaderGenerator &theMaterialGenerator(
+ m_RenderContext->GetDefaultMaterialShaderGenerator());
+ SPathVertexPipeline thePipeline(
+ m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
+ m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable(), false);
+ thePipeline.BeginVertexGeneration(displacementIdx, displacementImage);
+ thePipeline.BeginFragmentGeneration();
+ thePipeline.Fragment().Append("\tfragOutput = vec4(1.0, 1.0, 1.0, 1.0);");
+ thePipeline.EndVertexGeneration();
+ thePipeline.EndFragmentGeneration();
+ const char8_t *shaderName = "path depth";
+ if (displacementImage)
+ shaderName = "path depth displacement";
+
+ SShaderCacheProgramFlags theFlags;
+ NVRenderShaderProgram *theProgram =
+ thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
+ inFeatureSet);
+ if (theProgram) {
+ theDesiredDepthShader =
+ QT3DS_NEW(m_RenderContext->GetAllocator(),
+ SPathGeneratedShader)(*theProgram, m_RenderContext->GetAllocator());
+ }
+ }
+ if (theDesiredDepthShader) {
+ DoRenderGeometryPath(*theDesiredDepthShader, inRenderContext, inRenderProperties,
+ *thePathBuffer);
+ }
+ } else {
+ // painted path, go stroke route for now.
+ if (!m_PaintedDepthShader) {
+ IDefaultMaterialShaderGenerator &theMaterialGenerator(
+ m_RenderContext->GetDefaultMaterialShaderGenerator());
+ SXYRectVertexPipeline thePipeline(
+ m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
+ m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
+ thePipeline.BeginVertexGeneration(0, NULL);
+ thePipeline.BeginFragmentGeneration();
+ thePipeline.Fragment().Append("\tfragOutput = vec4(1.0, 1.0, 1.0, 1.0);");
+ thePipeline.EndVertexGeneration();
+ thePipeline.EndFragmentGeneration();
+ const char8_t *shaderName = "path painted depth";
+ SShaderCacheProgramFlags theFlags;
+ NVRenderShaderProgram *theProgram =
+ thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
+ inFeatureSet);
+ if (theProgram) {
+ m_PaintedDepthShader =
+ QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
+ *theProgram, m_RenderContext->GetAllocator());
+ }
+ }
+ if (m_PaintedDepthShader) {
+
+ DoRenderPaintedPath(*m_PaintedDepthShader, inRenderContext, inRenderProperties,
+ *thePathBuffer);
+ }
+ }
+ }
+
+ void RenderShadowMapPass(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) override
+ {
+ SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
+ if (!thePathBuffer) {
+ return;
+ }
+
+ if (inRenderContext.m_Material.m_Type != GraphObjectTypes::DefaultMaterial)
+ return;
+
+ if (thePathBuffer->m_PathType == PathTypes::Painted) {
+ // painted path, go stroke route for now.
+ if (!m_PaintedShadowShader) {
+ IDefaultMaterialShaderGenerator &theMaterialGenerator(
+ m_RenderContext->GetDefaultMaterialShaderGenerator());
+ SXYRectVertexPipeline thePipeline(
+ m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
+ m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
+ thePipeline.OutputParaboloidDepthShaders();
+ const char8_t *shaderName = "path painted paraboloid depth";
+ SShaderCacheProgramFlags theFlags;
+ NVRenderShaderProgram *theProgram =
+ thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
+ inFeatureSet);
+ if (theProgram) {
+ m_PaintedShadowShader =
+ QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
+ *theProgram, m_RenderContext->GetAllocator());
+ }
+ }
+ if (m_PaintedShadowShader) {
+ // Setup the shader paraboloid information.
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+ theRenderContext.SetActiveShader(&m_PaintedShadowShader->m_Shader);
+
+ DoRenderPaintedPath(*m_PaintedShadowShader, inRenderContext, inRenderProperties,
+ *thePathBuffer, true);
+ }
+ } else {
+ // Until we've also got a proper path render path for this, we'll call the old-fashioned
+ // stuff.
+ RenderDepthPrepass(inRenderContext, inRenderProperties, inFeatureSet);
+ // QT3DS_ASSERT( false );
+ }
+ }
+
+ void RenderCubeFaceShadowPass(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) override
+ {
+ SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
+ if (!thePathBuffer) {
+ return;
+ }
+
+ if (inRenderContext.m_Material.m_Type != GraphObjectTypes::DefaultMaterial)
+ return;
+
+ if (thePathBuffer->m_PathType == PathTypes::Painted) {
+ if (!m_PaintedCubeShadowShader) {
+ IDefaultMaterialShaderGenerator &theMaterialGenerator(
+ m_RenderContext->GetDefaultMaterialShaderGenerator());
+ SXYRectVertexPipeline thePipeline(
+ m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
+ m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
+ thePipeline.OutputCubeFaceDepthShaders();
+ const char8_t *shaderName = "path painted cube face depth";
+ SShaderCacheProgramFlags theFlags;
+ NVRenderShaderProgram *theProgram =
+ thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
+ inFeatureSet);
+ if (theProgram) {
+ m_PaintedCubeShadowShader =
+ QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
+ *theProgram, m_RenderContext->GetAllocator());
+ }
+ }
+ if (m_PaintedCubeShadowShader) {
+ // Setup the shader information.
+ NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
+ theRenderContext.SetActiveShader(&m_PaintedCubeShadowShader->m_Shader);
+
+ m_PaintedCubeShadowShader->m_CameraPosition.Set(
+ inRenderContext.m_Camera.GetGlobalPos());
+ m_PaintedCubeShadowShader->m_CameraProperties.Set(
+ QT3DSVec2(1.0f, inRenderContext.m_Camera.m_ClipFar));
+ m_PaintedCubeShadowShader->m_ModelMatrix.Set(inRenderContext.m_ModelMatrix);
+
+ DoRenderPaintedPath(*m_PaintedCubeShadowShader, inRenderContext, inRenderProperties,
+ *thePathBuffer, false);
+ }
+ } else {
+ // Until we've also got a proper path render path for this, we'll call the old-fashioned
+ // stuff.
+ RenderDepthPrepass(inRenderContext, inRenderProperties, inFeatureSet);
+ }
+ }
+
+ void RenderPath(SPathRenderContext &inRenderContext,
+ SLayerGlobalRenderProperties inRenderProperties,
+ TShaderFeatureSet inFeatureSet) override
+ {
+ SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
+ if (!thePathBuffer) {
+ return;
+ }
+
+ bool isDefaultMaterial =
+ (inRenderContext.m_Material.m_Type == GraphObjectTypes::DefaultMaterial);
+
+ if (thePathBuffer->m_PathType == PathTypes::Geometry) {
+ IMaterialShaderGenerator *theMaterialGenerator =
+ GetMaterialShaderGenertator(inRenderContext);
+
+ // we need a more evolved key her for custom materials
+ // the same key can still need a different shader
+ SPathShaderMapKey sPathkey = SPathShaderMapKey(GetMaterialNameForKey(inRenderContext),
+ inRenderContext.m_MaterialKey);
+ eastl::pair<TShaderMap::iterator, bool> inserter = m_PathGeometryShaders.insert(
+ eastl::make_pair(sPathkey, NVScopedRefCounted<SPathGeneratedShader>(NULL)));
+ if (inserter.second) {
+ SPathVertexPipeline thePipeline(
+ m_RenderContext->GetShaderProgramGenerator(), *theMaterialGenerator,
+ m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable(),
+ m_RenderContext->GetWireframeMode());
+
+ NVRenderShaderProgram *theProgram = NULL;
+
+ if (isDefaultMaterial) {
+ theProgram = theMaterialGenerator->GenerateShader(
+ inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
+ inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
+ inRenderContext.m_Opacity < 1.0, "path geometry pipeline-- ");
+ } else {
+ ICustomMaterialSystem &theMaterialSystem(
+ m_RenderContext->GetCustomMaterialSystem());
+ const SCustomMaterial &theCustomMaterial(
+ reinterpret_cast<const SCustomMaterial &>(inRenderContext.m_Material));
+
+ theProgram = theMaterialGenerator->GenerateShader(
+ inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
+ inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
+ inRenderContext.m_Opacity < 1.0, "path geometry pipeline-- ",
+ theMaterialSystem.GetShaderName(theCustomMaterial));
+ }
+
+ if (theProgram)
+ inserter.first->second =
+ QT3DS_NEW(m_RenderContext->GetAllocator(),
+ SPathGeneratedShader)(*theProgram, m_RenderContext->GetAllocator());
+ }
+ if (!inserter.first->second)
+ return;
+
+ DoRenderGeometryPath(*inserter.first->second.mPtr, inRenderContext, inRenderProperties,
+ *thePathBuffer);
+ } else {
+ IMaterialShaderGenerator *theMaterialGenerator =
+ GetMaterialShaderGenertator(inRenderContext);
+
+ // we need a more evolved key her for custom materials
+ // the same key can still need a different shader
+ SPathShaderMapKey sPathkey = SPathShaderMapKey(GetMaterialNameForKey(inRenderContext),
+ inRenderContext.m_MaterialKey);
+ eastl::pair<TPaintedShaderMap::iterator, bool> inserter = m_PathPaintedShaders.insert(
+ eastl::make_pair(sPathkey, NVScopedRefCounted<SPathXYGeneratedShader>(NULL)));
+
+ if (inserter.second) {
+ SXYRectVertexPipeline thePipeline(
+ m_RenderContext->GetShaderProgramGenerator(), *theMaterialGenerator,
+ m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
+
+ NVRenderShaderProgram *theProgram = NULL;
+
+ if (isDefaultMaterial) {
+ theProgram = theMaterialGenerator->GenerateShader(
+ inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
+ inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
+ inRenderContext.m_Opacity < 1.0, "path painted pipeline-- ");
+ } else {
+ ICustomMaterialSystem &theMaterialSystem(
+ m_RenderContext->GetCustomMaterialSystem());
+ const SCustomMaterial &theCustomMaterial(
+ reinterpret_cast<const SCustomMaterial &>(inRenderContext.m_Material));
+
+ theProgram = theMaterialGenerator->GenerateShader(
+ inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
+ inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
+ inRenderContext.m_Opacity < 1.0, "path painted pipeline-- ",
+ theMaterialSystem.GetShaderName(theCustomMaterial));
+ }
+
+ if (theProgram)
+ inserter.first->second =
+ QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
+ *theProgram, m_RenderContext->GetAllocator());
+ }
+ if (!inserter.first->second)
+ return;
+
+ DoRenderPaintedPath(*inserter.first->second.mPtr, inRenderContext, inRenderProperties,
+ *thePathBuffer);
+ }
+ }
+};
+}
+
+QT3DSVec2 IPathManagerCore::GetControlPointFromAngleDistance(QT3DSVec2 inPosition, float inIncomingAngle,
+ float inIncomingDistance)
+{
+ if (inIncomingDistance == 0.0f)
+ return inPosition;
+ float angleRad = degToRad(inIncomingAngle);
+ float angleSin = NVSin(angleRad);
+ float angleCos = NVCos(angleRad);
+ QT3DSVec2 relativeAngles = QT3DSVec2(angleCos * inIncomingDistance, angleSin * inIncomingDistance);
+ return inPosition + relativeAngles;
+}
+
+QT3DSVec2 IPathManagerCore::GetAngleDistanceFromControlPoint(QT3DSVec2 inPosition, QT3DSVec2 inControlPoint)
+{
+ QT3DSVec2 relative = inControlPoint - inPosition;
+ float angleRad = atan2(relative.y, relative.x);
+ float distance = relative.magnitude();
+ return QT3DSVec2(radToDeg(angleRad), distance);
+}
+
+IPathManagerCore &IPathManagerCore::CreatePathManagerCore(IUICRenderContextCore &ctx)
+{
+ return *QT3DS_NEW(ctx.GetAllocator(), SPathManager)(ctx);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp b/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp
new file mode 100644
index 00000000..0a832321
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsRenderer.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderPixelGraphicsRenderer.h"
+#include "UICRenderPixelGraphicsTypes.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderCamera.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCodeGenerator.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderShaderCache.h"
+
+using namespace uic;
+using namespace uic::render;
+
+namespace {
+
+struct SPGRectShader
+{
+ NVScopedRefCounted<NVRenderShaderProgram> m_RectShader;
+ NVRenderShaderConstantBase *mvp;
+ NVRenderShaderConstantBase *rectColor;
+ NVRenderShaderConstantBase *leftright;
+ NVRenderShaderConstantBase *bottomtop;
+
+ SPGRectShader()
+ : mvp(NULL)
+ , rectColor(NULL)
+ , leftright(NULL)
+ , bottomtop(NULL)
+ {
+ }
+ void SetShader(NVRenderShaderProgram *program)
+ {
+ m_RectShader = program;
+ if (program) {
+ mvp = program->GetShaderConstant("model_view_projection");
+ rectColor = program->GetShaderConstant("rect_color");
+ leftright = program->GetShaderConstant("leftright[0]");
+ bottomtop = program->GetShaderConstant("bottomtop[0]");
+ }
+ }
+
+ void Apply(QT3DSMat44 &inVP, const SPGRect &inObject)
+ {
+ if (mvp)
+ m_RectShader->SetConstantValue(mvp, toConstDataRef(inVP), 1);
+ if (rectColor)
+ m_RectShader->SetConstantValue(rectColor, inObject.m_FillColor, 1);
+ if (leftright) {
+ QT3DSF32 theData[] = { inObject.m_Left, inObject.m_Right };
+ m_RectShader->SetConstantValue(leftright, *theData, 2);
+ }
+ if (bottomtop) {
+ QT3DSF32 theData[] = { inObject.m_Bottom, inObject.m_Top };
+ m_RectShader->SetConstantValue(bottomtop, *theData, 2);
+ }
+ }
+
+ operator bool() { return m_RectShader.mPtr != NULL; }
+};
+
+struct SPGRenderer : public IPixelGraphicsRenderer
+{
+ IUICRenderContext &m_RenderContext;
+ IStringTable &m_StringTable;
+ NVScopedRefCounted<NVRenderVertexBuffer> m_QuadVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> m_QuadIndexBuffer;
+ NVScopedRefCounted<NVRenderInputAssembler> m_QuadInputAssembler;
+ NVScopedRefCounted<NVRenderAttribLayout> m_QuadAttribLayout;
+ SShaderVertexCodeGenerator m_VertexGenerator;
+ SShaderFragmentCodeGenerator m_FragmentGenerator;
+ SPGRectShader m_RectShader;
+ QT3DSI32 mRefCount;
+
+ SPGRenderer(IUICRenderContext &ctx, IStringTable &strt)
+ : m_RenderContext(ctx)
+ , m_StringTable(strt)
+ , m_VertexGenerator(m_StringTable, ctx.GetAllocator(),
+ m_RenderContext.GetRenderContext().GetRenderContextType())
+ , m_FragmentGenerator(m_VertexGenerator, ctx.GetAllocator(),
+ m_RenderContext.GetRenderContext().GetRenderContextType())
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
+ void GetRectShaderProgram()
+ {
+ if (!m_RectShader) {
+ m_VertexGenerator.Begin();
+ m_FragmentGenerator.Begin();
+ m_VertexGenerator.AddAttribute("attr_pos", "vec2");
+ m_VertexGenerator.AddUniform("model_view_projection", "mat4");
+ m_VertexGenerator.AddUniform("leftright", "float[2]");
+ m_VertexGenerator.AddUniform("bottomtop", "float[2]");
+ m_FragmentGenerator.AddVarying("rect_uvs", "vec2");
+ m_FragmentGenerator.AddUniform("rect_color", "vec4");
+ m_VertexGenerator << "void main() {" << Endl
+ << "\tgl_Position = model_view_projection * vec4( "
+ "leftright[int(attr_pos.x)], bottomtop[int(attr_pos.y)], 0.0, 1.0 "
+ ");"
+ << Endl << "\trect_uvs = attr_pos;" << Endl << "}" << Endl;
+
+ m_FragmentGenerator << "void main() {" << Endl << "\tfragOutput = rect_color;" << Endl
+ << "}" << Endl;
+
+ m_VertexGenerator.BuildShaderSource();
+ m_FragmentGenerator.BuildShaderSource();
+
+ m_RectShader.SetShader(m_RenderContext.GetShaderCache().CompileProgram(
+ m_StringTable.RegisterStr("PixelRectShader"),
+ m_VertexGenerator.m_FinalShaderBuilder.c_str(),
+ m_FragmentGenerator.m_FinalShaderBuilder.c_str(), NULL // no tess control shader
+ ,
+ NULL // no tess eval shader
+ ,
+ NULL // no geometry shader
+ ,
+ SShaderCacheProgramFlags(), ShaderCacheNoFeatures()));
+ }
+ }
+ void GenerateXYQuad()
+ {
+ NVRenderContext &theRenderContext(m_RenderContext.GetRenderContext());
+
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2),
+ };
+
+ QT3DSVec2 pos[] = { QT3DSVec2(0, 0), QT3DSVec2(0, 1), QT3DSVec2(1, 1), QT3DSVec2(1, 0) };
+
+ if (m_QuadVertexBuffer == NULL) {
+ size_t bufSize = sizeof(pos);
+ m_QuadVertexBuffer = theRenderContext.CreateVertexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static, bufSize, 2 * sizeof(QT3DSF32),
+ toU8DataRef(pos, 4));
+ }
+
+ if (m_QuadIndexBuffer == NULL) {
+ QT3DSU8 indexData[] = {
+ 0, 1, 2, 0, 2, 3,
+ };
+ m_QuadIndexBuffer = theRenderContext.CreateIndexBuffer(
+ qt3ds::render::NVRenderBufferUsageType::Static,
+ qt3ds::render::NVRenderComponentTypes::QT3DSU8, sizeof(indexData),
+ toU8DataRef(indexData, sizeof(indexData)));
+ }
+
+ if (m_QuadAttribLayout == NULL) {
+ // create our attribute layout
+ m_QuadAttribLayout =
+ theRenderContext.CreateAttributeLayout(toConstDataRef(theEntries, 1));
+ }
+
+ if (m_QuadInputAssembler == NULL) {
+
+ // create input assembler object
+ QT3DSU32 strides = m_QuadVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_QuadInputAssembler = theRenderContext.CreateInputAssembler(
+ m_QuadAttribLayout, toConstDataRef(&m_QuadVertexBuffer.mPtr, 1), m_QuadIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+ }
+
+ void RenderPixelObject(QT3DSMat44 &inProjection, const SPGRect &inObject)
+ {
+ GenerateXYQuad();
+ GetRectShaderProgram();
+ if (m_RectShader) {
+ m_RenderContext.GetRenderContext().SetActiveShader(m_RectShader.m_RectShader.mPtr);
+ m_RectShader.Apply(inProjection, inObject);
+
+ m_RenderContext.GetRenderContext().SetInputAssembler(m_QuadInputAssembler.mPtr);
+ m_RenderContext.GetRenderContext().Draw(NVRenderDrawMode::Triangles,
+ m_QuadInputAssembler->GetIndexCount(), 0);
+ }
+ }
+
+ void RenderPixelObject(QT3DSMat44 &inProjection, const SPGVertLine &inObject)
+ {
+ // lines are really just rects, but they grow in width in a sort of odd way.
+ // specifically, they grow the increasing coordinate on even boundaries and centered on odd
+ // boundaries.
+ SPGRect theRect;
+ theRect.m_Top = inObject.m_Top;
+ theRect.m_Bottom = inObject.m_Bottom;
+ theRect.m_FillColor = inObject.m_LineColor;
+ theRect.m_Left = inObject.m_X;
+ theRect.m_Right = theRect.m_Left + 1.0f;
+ RenderPixelObject(inProjection, theRect);
+ }
+
+ void RenderPixelObject(QT3DSMat44 &inProjection, const SPGHorzLine &inObject)
+ {
+ SPGRect theRect;
+ theRect.m_Right = inObject.m_Right;
+ theRect.m_Left = inObject.m_Left;
+ theRect.m_FillColor = inObject.m_LineColor;
+ theRect.m_Bottom = inObject.m_Y;
+ theRect.m_Top = theRect.m_Bottom + 1.0f;
+ RenderPixelObject(inProjection, theRect);
+ }
+
+ void Render(NVConstDataRef<SPGGraphObject *> inObjects) override
+ {
+ NVRenderContext &theRenderContext(m_RenderContext.GetRenderContext());
+ theRenderContext.PushPropertySet();
+ // Setup an orthographic camera that places the center at the
+ // lower left of the viewport.
+ NVRenderRectF theViewport = theRenderContext.GetViewport();
+ // With no projection at all, we are going to get a square view box
+ // with boundaries from -1,1 in all dimensions. This is close to what we want.
+ theRenderContext.SetDepthTestEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(false);
+ theRenderContext.SetScissorTestEnabled(false);
+ theRenderContext.SetBlendingEnabled(true);
+ theRenderContext.SetCullingEnabled(false);
+ // Colors are expected to be non-premultiplied, so we premultiply alpha into them at this
+ // point.
+ theRenderContext.SetBlendFunction(qt3ds::render::NVRenderBlendFunctionArgument(
+ NVRenderSrcBlendFunc::SrcAlpha, NVRenderDstBlendFunc::OneMinusSrcAlpha,
+ NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::OneMinusSrcAlpha));
+ theRenderContext.SetBlendEquation(qt3ds::render::NVRenderBlendEquationArgument(
+ NVRenderBlendEquation::Add, NVRenderBlendEquation::Add));
+
+ SCamera theCamera;
+ theCamera.m_Position.z = -5;
+ theCamera.m_ClipNear = 1.0f;
+ theCamera.m_ClipFar = 10.0f;
+ theCamera.m_Flags.SetOrthographic(true);
+ // Setup camera projection
+ theCamera.ComputeFrustumOrtho(theViewport,
+ QT3DSVec2(theViewport.m_Width, theViewport.m_Height));
+ // Translate such that 0, 0 is lower left of screen.
+ NVRenderRectF theIdealViewport = theViewport;
+ theIdealViewport.m_X -= theViewport.m_Width / 2.0f;
+ theIdealViewport.m_Y -= theViewport.m_Height / 2.0f;
+ QT3DSMat44 theProjectionMatrix = NVRenderContext::ApplyVirtualViewportToProjectionMatrix(
+ theCamera.m_Projection, theViewport, theIdealViewport);
+ theCamera.m_Projection = theProjectionMatrix;
+ // Explicitly call the node's calculate global variables so that the camera doesn't attempt
+ // to change the projection we setup.
+ static_cast<SNode &>(theCamera).CalculateGlobalVariables();
+ QT3DSMat44 theVPMatrix(QT3DSMat44::createIdentity());
+ theCamera.CalculateViewProjectionMatrix(theVPMatrix);
+
+ QT3DSVec4 theTest(60, 200, 0, 1);
+ QT3DSVec4 theResult = theVPMatrix.transform(theTest);
+
+ (void)theTest;
+ (void)theResult;
+
+ for (QT3DSU32 idx = 0, end = inObjects.size(); idx < end; ++idx) {
+ const SPGGraphObject &theObject(*inObjects[idx]);
+
+ switch (theObject.m_Type) {
+ case SGTypes::VertLine:
+ RenderPixelObject(theVPMatrix, static_cast<const SPGVertLine &>(theObject));
+ break;
+ case SGTypes::HorzLine:
+ RenderPixelObject(theVPMatrix, static_cast<const SPGHorzLine &>(theObject));
+ break;
+ case SGTypes::Rect:
+ RenderPixelObject(theVPMatrix, static_cast<const SPGRect &>(theObject));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ theRenderContext.PopPropertySet(false);
+ }
+};
+}
+
+IPixelGraphicsRenderer &IPixelGraphicsRenderer::CreateRenderer(IUICRenderContext &ctx,
+ IStringTable &strt)
+{
+ return *QT3DS_NEW(ctx.GetAllocator(), SPGRenderer)(ctx, strt);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsTypes.cpp b/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsTypes.cpp
new file mode 100644
index 00000000..5d072f1f
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderPixelGraphicsTypes.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderPixelGraphicsTypes.h"
+
+using namespace uic;
+using namespace uic::render;
+
+SPGGraphObject::SPGGraphObject(SGTypes::Enum inType)
+ : m_Type(inType)
+{
+}
+
+SPGRect::SPGRect()
+ : SPGGraphObject(SGTypes::Rect)
+ , m_Left(0)
+ , m_Top(0)
+ , m_Right(0)
+ , m_Bottom(0)
+ , m_FillColor(0, 0, 0, 0)
+{
+}
+
+SPGVertLine::SPGVertLine()
+ : SPGGraphObject(SGTypes::VertLine)
+ , m_X(0)
+ , m_Top(0)
+ , m_Bottom(0)
+ , m_LineColor(0, 0, 0, 0)
+{
+}
+
+SPGHorzLine::SPGHorzLine()
+ : SPGGraphObject(SGTypes::HorzLine)
+ , m_Y(0)
+ , m_Left(0)
+ , m_Right(0)
+ , m_LineColor(0, 0, 0, 0)
+{
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderPlugin.cpp b/src/Runtime/Source/UICRender/Source/UICRenderPlugin.cpp
new file mode 100644
index 00000000..65ce11e1
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderPlugin.cpp
@@ -0,0 +1,921 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderPlugin.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSSystem.h"
+#include "foundation/FileTools.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderString.h"
+#include "UICRenderPluginPropertyValue.h"
+#include "UICRenderInputStreamFactory.h"
+
+#if defined(QT3DS_WINDOWS)
+#include "WINDOWS/DynamicLibLoader.h"
+#elif defined(QT3DS_ANDROID)
+#include "ANDROID/DynamicLibLoader.h"
+#elif defined(QT3DS_LINUX)
+#include "LINUX/DynamicLibLoader.h"
+#elif defined(QT3DS_APPLE)
+#include "OSX/DynamicLibLoader.h"
+#elif defined(QT3DS_QNX)
+#include "QNX/DynamicLibLoader.h"
+#else
+#error "Must define an operating system type (QT3DS_WINDOWS, QT3DS_ANDROID, QT3DS_LINUX, QT3DS_APPLE, QT3DS_QNX)"
+#endif
+
+using namespace uic::render;
+
+namespace {
+// Legacy definitions...
+// API version 1 definitions
+typedef struct _RenderPluginSurfaceDescriptionV1
+{
+ long m_Width;
+ long m_Height;
+ enum EUICRenderPluginDepthTypes m_DepthBuffer;
+ enum EUICRenderPluginTextureTypes m_ColorBuffer;
+ TUICBOOL m_HasStencilBuffer;
+} TRenderPluginSurfaceDescriptionV1;
+
+typedef TNeedsRenderResult (*TNeedsRenderFunctionV1)(TRenderPluginClassPtr cls,
+ TRenderPluginInstancePtr instance,
+ TRenderPluginSurfaceDescriptionV1 surface,
+ TUICVec2 presScaleFactor);
+
+typedef void (*TRenderFunctionV1)(TRenderPluginClassPtr cls, TRenderPluginInstancePtr instance,
+ TRenderPluginSurfaceDescriptionV1 surface,
+ TUICVec2 presScaleFactor,
+ EUICRenderPluginColorClearState inClearColorBuffer);
+
+// End API version 1 definitions
+
+TRenderPluginSurfaceDescription ToCInterface(const SOffscreenRendererEnvironment &env)
+{
+ TRenderPluginSurfaceDescription retval;
+ retval.m_Width = (long)env.m_Width;
+ retval.m_Height = (long)env.m_Height;
+ retval.m_ColorBuffer = static_cast<EUICRenderPluginTextureTypes>(env.m_Format);
+ retval.m_DepthBuffer = static_cast<EUICRenderPluginDepthTypes>(env.m_Depth);
+ retval.m_HasStencilBuffer = env.m_Stencil ? UICTRUE : UICFALSE;
+ retval.m_MSAALevel = EUICRenderPluginMSAALevelNoMSAA;
+ // note no supersampling AA support for plugins
+ // we fall back to 4xMSAA
+ switch (env.m_MSAAMode) {
+ case AAModeValues::X2:
+ retval.m_MSAALevel = EUICRenderPluginMSAALevelTwo;
+ break;
+ case AAModeValues::SSAA:
+ case AAModeValues::X4:
+ retval.m_MSAALevel = EUICRenderPluginMSAALevelFour;
+ break;
+ case AAModeValues::X8:
+ retval.m_MSAALevel = EUICRenderPluginMSAALevelEight;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ // fallthrough intentional.
+ case AAModeValues::NoAA:
+ break;
+ };
+ return retval;
+}
+
+TRenderPluginSurfaceDescriptionV1 ToCInterfaceV1(const SOffscreenRendererEnvironment &env)
+{
+ TRenderPluginSurfaceDescriptionV1 retval;
+ retval.m_Width = (long)env.m_Width;
+ retval.m_Height = (long)env.m_Height;
+ retval.m_ColorBuffer = static_cast<EUICRenderPluginTextureTypes>(env.m_Format);
+ retval.m_DepthBuffer = static_cast<EUICRenderPluginDepthTypes>(env.m_Depth);
+ retval.m_HasStencilBuffer = env.m_Stencil ? UICTRUE : UICFALSE;
+ return retval;
+}
+
+TUICVec2 ToCInterface(const QT3DSVec2 &item)
+{
+ TUICVec2 retval = { item.x, item.y };
+ return retval;
+}
+
+EUICRenderPluginColorClearState ToCInterface(SScene::RenderClearCommand inClearCommand)
+{
+ switch (inClearCommand) {
+ case SScene::DoNotClear:
+ return EUICRenderPluginColorClearStateDoNotClear;
+ case SScene::AlwaysClear:
+ return EUICRenderPluginColorClearStateAlwaysClear;
+ default:
+ QT3DS_ASSERT(false); // fallthrough intentional
+ case SScene::ClearIsOptional:
+ return EUICRenderPluginColorClearStateClearIsOptional;
+ };
+}
+
+class SRenderPluginPropertyData
+{
+ SRenderPluginPropertyValue m_Value;
+ bool m_Dirty;
+
+public:
+ SRenderPluginPropertyData()
+ : m_Dirty(false)
+ {
+ }
+ SRenderPluginPropertyData(const SRenderPluginPropertyData &other)
+ : m_Value(other.m_Value)
+ , m_Dirty(other.m_Dirty)
+ {
+ }
+ SRenderPluginPropertyData &operator=(const SRenderPluginPropertyData &other)
+ {
+ m_Value = other.m_Value;
+ m_Dirty = other.m_Dirty;
+ return *this;
+ }
+
+ bool IsDirty() const
+ {
+ return m_Value.getType() != RenderPluginPropertyValueTypes::NoRenderPluginPropertyValue
+ && m_Dirty;
+ }
+ void SetValue(const SRenderPluginPropertyValue &value)
+ {
+ m_Value = value;
+ m_Dirty = true;
+ }
+
+ TRenderPluginPropertyUpdate ClearDirty(CRegisteredString inPropName)
+ {
+ m_Dirty = false;
+ TRenderPluginPropertyUpdate retval;
+ memset(&retval, 0, sizeof(TRenderPluginPropertyUpdate));
+ retval.m_PropName = inPropName.c_str();
+ switch (m_Value.getType()) {
+ case RenderPluginPropertyValueTypes::Long: {
+ retval.m_PropertyType = EUICRenderPluginPropertyTypeLong;
+ long temp = (long)m_Value.getData<QT3DSI32>();
+ retval.m_PropertyValue = *reinterpret_cast<void **>(&temp);
+ } break;
+ case RenderPluginPropertyValueTypes::Float: {
+ retval.m_PropertyType = EUICRenderPluginPropertyTypeFloat;
+ float temp = m_Value.getData<QT3DSF32>();
+ retval.m_PropertyValue = *reinterpret_cast<void **>(&temp);
+ } break;
+ case RenderPluginPropertyValueTypes::Boolean: {
+ retval.m_PropertyType = EUICRenderPluginPropertyTypeLong;
+ long temp = m_Value.getData<bool>() ? UICTRUE : UICFALSE;
+ retval.m_PropertyValue = *reinterpret_cast<void **>(&temp);
+ } break;
+ case RenderPluginPropertyValueTypes::String: {
+ retval.m_PropertyType = EUICRenderPluginPropertyTypeCharPtr;
+ const char *temp = m_Value.getData<CRegisteredString>().c_str();
+ retval.m_PropertyValue = reinterpret_cast<void *>(const_cast<char *>(temp));
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ return retval;
+ }
+};
+
+typedef nvvector<SRenderPluginPropertyData> TPropertyValueList;
+
+struct IInternalPluginClass : public IRenderPluginClass
+{
+ virtual void PushUpdates(TRenderPluginInstancePtr instance,
+ TPropertyValueList &propertyValues) = 0;
+ virtual void Update(NVConstDataRef<SRenderPropertyValueUpdate> updateBuffer,
+ TPropertyValueList &propertyValues) = 0;
+ virtual QT3DSI32 GetAPIVersion() = 0;
+};
+
+static NVRenderTextureFormats::Enum ToTextureFormat(EUICRenderPluginTextureTypes inTextureType)
+{
+ switch (inTextureType) {
+ default:
+ case EUICRenderPluginTextureTypeRGBA8:
+ return NVRenderTextureFormats::RGBA8;
+ case EUICRenderPluginTextureTypeRGB8:
+ return NVRenderTextureFormats::RGB8;
+ case EUICRenderPluginTextureTypeRGB565:
+ return NVRenderTextureFormats::RGB565;
+ case EUICRenderPluginTextureTypeRGBA5551:
+ return NVRenderTextureFormats::RGBA5551;
+ }
+}
+
+static OffscreenRendererDepthValues::Enum ToDepthValue(EUICRenderPluginDepthTypes inType)
+{
+ switch (inType) {
+ default:
+ case EUICRenderPluginDepthTypeDepth16:
+ return OffscreenRendererDepthValues::Depth16;
+ case EUICRenderPluginDepthTypeDepth24:
+ return OffscreenRendererDepthValues::Depth24;
+ case EUICRenderPluginDepthTypeDepth32:
+ return OffscreenRendererDepthValues::Depth32;
+ }
+}
+
+static AAModeValues::Enum ToAAMode(EUICRenderPluginMSAALevel inMode)
+{
+ switch (inMode) {
+ case EUICRenderPluginMSAALevelTwo:
+ return AAModeValues::X2;
+ case EUICRenderPluginMSAALevelFour:
+ return AAModeValues::X4;
+ case EUICRenderPluginMSAALevelEight:
+ return AAModeValues::X8;
+ default:
+ QT3DS_ASSERT(false); // fallthrough intentional
+ case EUICRenderPluginMSAALevelNoMSAA:
+ return AAModeValues::NoAA;
+ }
+}
+
+struct InstanceImpl : public IRenderPluginInstance
+{
+ NVFoundationBase &m_Foundation;
+ TRenderPluginInstancePtr m_Instance;
+ TRenderPluginClass m_Class;
+ NVScopedRefCounted<IInternalPluginClass> m_Owner;
+ CRegisteredString m_RendererType;
+ // Backing store of property values
+ nvvector<SRenderPluginPropertyData> m_PropertyValues;
+ bool m_Dirty;
+ NVRenderContext *m_RenderContext;
+ QT3DSI32 mRefCount;
+
+ InstanceImpl(NVFoundationBase &fnd, TRenderPluginInstancePtr instance, TRenderPluginClass cls,
+ IInternalPluginClass &owner, IStringTable &strTable)
+ : m_Foundation(fnd)
+ , m_Instance(instance)
+ , m_Class(cls)
+ , m_Owner(owner)
+ , m_RendererType(
+ strTable.RegisterStr(IRenderPluginInstance::IRenderPluginOffscreenRendererType()))
+ , m_PropertyValues(m_Foundation.getAllocator(), "InstanceImpl::m_PropertyValues")
+ , m_Dirty(false)
+ , m_RenderContext(NULL)
+ , mRefCount(0)
+ {
+ }
+
+ virtual ~InstanceImpl() { m_Class.ReleaseInstance(m_Class.m_Class, m_Instance); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void CreateLuaProxy(lua_State *state) override
+ {
+ if (m_Class.CreateInstanceLuaProxy)
+ m_Class.CreateInstanceLuaProxy(m_Class.m_Class, m_Instance, state);
+ }
+
+ // Arbitrary const char* returned to indicate the type of this renderer
+ // Can be overloaded to form the basis of an RTTI type system.
+ // Not currently used by the rendering system.
+ CRegisteredString GetOffscreenRendererType() override { return m_RendererType; }
+
+ SOffscreenRendererEnvironment GetDesiredEnvironment(QT3DSVec2 inPresentationScaleFactor) override
+ {
+ if (m_Class.QueryInstanceRenderSurface) {
+ EUICRenderPluginMSAALevel theLevel = EUICRenderPluginMSAALevelNoMSAA;
+ TRenderPluginSurfaceDescription desc = m_Class.QueryInstanceRenderSurface(
+ m_Class.m_Class, m_Instance, ToCInterface(inPresentationScaleFactor));
+ if (m_Owner->GetAPIVersion() > 1)
+ theLevel = desc.m_MSAALevel;
+
+ return SOffscreenRendererEnvironment(
+ (QT3DSU32)desc.m_Width, (QT3DSU32)desc.m_Height, ToTextureFormat(desc.m_ColorBuffer),
+ ToDepthValue(desc.m_DepthBuffer), desc.m_HasStencilBuffer ? true : false,
+ ToAAMode(theLevel));
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return SOffscreenRendererEnvironment();
+ }
+
+ // Returns true of this object needs to be rendered, false if this object is not dirty
+ SOffscreenRenderFlags NeedsRender(const SOffscreenRendererEnvironment &inEnvironment,
+ QT3DSVec2 inPresentationScaleFactor) override
+ {
+ if (m_Dirty) {
+ m_Dirty = false;
+ m_Owner->PushUpdates(m_Instance, m_PropertyValues);
+ }
+ if (m_Class.NeedsRenderFunction) {
+ if (m_Owner->GetAPIVersion() > 1) {
+ TNeedsRenderResult result = m_Class.NeedsRenderFunction(
+ m_Class.m_Class, m_Instance, ToCInterface(inEnvironment),
+ ToCInterface(inPresentationScaleFactor));
+ return SOffscreenRenderFlags(result.HasTransparency ? true : false,
+ result.HasChangedSinceLastFrame ? true : false);
+ } else {
+ TNeedsRenderFunctionV1 theV1Function =
+ reinterpret_cast<TNeedsRenderFunctionV1>(m_Class.NeedsRenderFunction);
+
+ TNeedsRenderResult result =
+ theV1Function(m_Class.m_Class, m_Instance, ToCInterfaceV1(inEnvironment),
+ ToCInterface(inPresentationScaleFactor));
+ return SOffscreenRenderFlags(result.HasTransparency ? true : false,
+ result.HasChangedSinceLastFrame ? true : false);
+ }
+ }
+ return SOffscreenRenderFlags(true, true);
+ }
+ // Returns true if the rendered result image has transparency, or false
+ // if it should be treated as a completely opaque image.
+ // It is the IOffscreenRenderer's job to clear any buffers (color, depth, stencil) that it
+ // needs to. It should not assume that it's buffers are clear;
+ // Sometimes we scale the width and height of the main presentation in order to fit a window.
+ // If we do so, the scale factor tells the subpresentation renderer how much the system has
+ // scaled.
+ void Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 inPresentationScaleFactor,
+ SScene::RenderClearCommand inColorBufferNeedsClear) override
+ {
+ m_RenderContext = &inRenderContext;
+ if (m_Class.RenderInstance) {
+ inRenderContext.PushPropertySet();
+ if (m_Owner->GetAPIVersion() > 1) {
+ m_Class.RenderInstance(m_Class.m_Class, m_Instance, ToCInterface(inEnvironment),
+ ToCInterface(inPresentationScaleFactor),
+ ToCInterface(inColorBufferNeedsClear));
+ } else {
+ TRenderFunctionV1 theV1Function =
+ reinterpret_cast<TRenderFunctionV1>(m_Class.RenderInstance);
+ theV1Function(m_Class.m_Class, m_Instance, ToCInterfaceV1(inEnvironment),
+ ToCInterface(inPresentationScaleFactor),
+ ToCInterface(inColorBufferNeedsClear));
+ }
+
+ inRenderContext.PopPropertySet(true);
+ }
+ }
+
+ // Implementors should implement one of the two interfaces below.
+
+ // If this renderer supports picking that can return graph objects
+ // then return an interface here.
+ IGraphObjectPickQuery *GetGraphObjectPickQuery() override { return NULL; }
+
+ // If you *don't* support the GraphObjectPickIterator interface, then you should implement this
+ // interface
+ // The system will just ask you to pick.
+ // If you return true, then we will assume that you swallowed the pick and will continue no
+ // further.
+ // else we will assume you did not and will continue the picking algorithm.
+ bool Pick(const QT3DSVec2 &inMouseCoords, const QT3DSVec2 &inViewportDimensions) override
+ {
+ if (m_Class.Pick) {
+ if (m_RenderContext) {
+ m_RenderContext->PushPropertySet();
+ bool retval = m_Class.Pick(m_Class.m_Class, m_Instance, ToCInterface(inMouseCoords),
+ ToCInterface(inViewportDimensions))
+ ? true
+ : false;
+ m_RenderContext->PopPropertySet(true);
+ return retval;
+ }
+ }
+ return false;
+ }
+
+ TRenderPluginInstancePtr GetRenderPluginInstance() override { return m_Instance; }
+ void Update(NVConstDataRef<SRenderPropertyValueUpdate> updateBuffer) override
+ {
+ m_Dirty = true;
+ m_Owner->Update(updateBuffer, m_PropertyValues);
+ }
+ IRenderPluginClass &GetPluginClass() override { return *m_Owner; }
+};
+
+typedef eastl::pair<CRegisteredString, RenderPluginPropertyValueTypes::Enum> TStringTypePair;
+
+struct PluginClassImpl : public IInternalPluginClass
+{
+ typedef nvhash_map<CRegisteredString, QT3DSU32> TStringIndexMap;
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ TRenderPluginClass m_Class;
+ CRegisteredString m_Type;
+ CLoadedDynamicLibrary *m_DynamicLibrary;
+ nvvector<SRenderPluginPropertyDeclaration> m_RegisteredProperties;
+ TStringIndexMap m_ComponentNameToComponentIndexMap;
+ nvvector<TStringTypePair> m_FullPropertyList;
+ nvvector<TRenderPluginPropertyUpdate> m_UpdateBuffer;
+ CRenderString m_TempString;
+ QT3DSI32 m_APIVersion;
+
+ QT3DSI32 mRefCount;
+
+ PluginClassImpl(NVFoundationBase &fnd, IStringTable &strTable, TRenderPluginClass inClass,
+ CRegisteredString inType, CLoadedDynamicLibrary *inLibrary)
+ : m_Foundation(fnd)
+ , m_StringTable(strTable)
+ , m_Class(inClass)
+ , m_Type(inType)
+ , m_DynamicLibrary(inLibrary)
+ , m_RegisteredProperties(m_Foundation.getAllocator(),
+ "PluginClassImpl::m_RegisteredProperties")
+ , m_ComponentNameToComponentIndexMap(m_Foundation.getAllocator(),
+ "PluginClassImpl::m_ComponentNameToComponentIndexMap")
+ , m_FullPropertyList(m_Foundation.getAllocator(), "PluginClassImpl::m_FullPropertyList")
+ , m_UpdateBuffer(m_Foundation.getAllocator(), "PluginClassImpl::m_UpdateBuffer")
+ , m_APIVersion(m_Class.GetRenderPluginAPIVersion(m_Class.m_Class))
+ , mRefCount(0)
+ {
+ }
+ ~PluginClassImpl()
+ {
+ if (m_Class.ReleaseClass)
+ m_Class.ReleaseClass(m_Class.m_Class);
+ if (m_DynamicLibrary)
+ NVDelete(m_Foundation.getAllocator(), m_DynamicLibrary);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ NVScopedRefCounted<IRenderPluginInstance> CreateInstance() override
+ {
+ if (m_Class.CreateInstance) {
+ TRenderPluginInstancePtr instance =
+ m_Class.CreateInstance(m_Class.m_Class, m_Type.c_str());
+ if (instance) {
+ InstanceImpl *retval = QT3DS_NEW(m_Foundation.getAllocator(), InstanceImpl)(
+ m_Foundation, instance, m_Class, *this, m_StringTable);
+ return retval;
+ }
+ }
+ return NVScopedRefCounted<IRenderPluginInstance>();
+ }
+
+ QT3DSI32 GetAPIVersion() override { return m_APIVersion; }
+
+ void AddFullPropertyType(const char *name, RenderPluginPropertyValueTypes::Enum inType)
+ {
+ QT3DSU32 itemIndex = (QT3DSU32)m_FullPropertyList.size();
+ CRegisteredString regName = m_StringTable.RegisterStr(name);
+ bool inserted =
+ m_ComponentNameToComponentIndexMap.insert(eastl::make_pair(regName, itemIndex)).second;
+ if (inserted) {
+ m_FullPropertyList.push_back(eastl::make_pair(regName, inType));
+ } else {
+ // Duplicate property declaration.
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void AddFullPropertyType(const char *name, const char *extension,
+ RenderPluginPropertyValueTypes::Enum inType)
+ {
+ m_TempString.assign(name);
+ if (!isTrivial(extension)) {
+ m_TempString.append(".");
+ m_TempString.append(extension);
+ }
+ AddFullPropertyType(m_TempString.c_str(), inType);
+ }
+
+ void RegisterProperty(const SRenderPluginPropertyDeclaration &dec) override
+ {
+ QT3DSU32 startOffset = (QT3DSU32)m_FullPropertyList.size();
+
+ switch (dec.m_Type) {
+
+ case SRenderPluginPropertyTypes::Vector2:
+ AddFullPropertyType(dec.m_Name, "x", RenderPluginPropertyValueTypes::Float);
+ AddFullPropertyType(dec.m_Name, "y", RenderPluginPropertyValueTypes::Float);
+ break;
+ case SRenderPluginPropertyTypes::Color:
+ AddFullPropertyType(dec.m_Name, "r", RenderPluginPropertyValueTypes::Float);
+ AddFullPropertyType(dec.m_Name, "g", RenderPluginPropertyValueTypes::Float);
+ AddFullPropertyType(dec.m_Name, "b", RenderPluginPropertyValueTypes::Float);
+ break;
+ case SRenderPluginPropertyTypes::Vector3:
+ AddFullPropertyType(dec.m_Name, "x", RenderPluginPropertyValueTypes::Float);
+ AddFullPropertyType(dec.m_Name, "y", RenderPluginPropertyValueTypes::Float);
+ AddFullPropertyType(dec.m_Name, "z", RenderPluginPropertyValueTypes::Float);
+ break;
+ case SRenderPluginPropertyTypes::Boolean:
+ AddFullPropertyType(dec.m_Name, RenderPluginPropertyValueTypes::Boolean);
+ break;
+ case SRenderPluginPropertyTypes::Float:
+ AddFullPropertyType(dec.m_Name, RenderPluginPropertyValueTypes::Float);
+ break;
+ case SRenderPluginPropertyTypes::Long:
+ AddFullPropertyType(dec.m_Name, RenderPluginPropertyValueTypes::Long);
+ break;
+ case SRenderPluginPropertyTypes::String:
+ AddFullPropertyType(dec.m_Name, RenderPluginPropertyValueTypes::String);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ m_RegisteredProperties.push_back(dec);
+ m_RegisteredProperties.back().m_StartOffset = startOffset;
+ }
+
+ NVConstDataRef<SRenderPluginPropertyDeclaration> GetRegisteredProperties() override
+ {
+ return m_RegisteredProperties;
+ }
+
+ SRenderPluginPropertyDeclaration GetPropertyDeclaration(CRegisteredString inPropName) override
+ {
+ for (QT3DSU32 idx = 0, end = m_RegisteredProperties.size(); idx < end; ++idx) {
+ if (m_RegisteredProperties[idx].m_Name == inPropName)
+ return m_RegisteredProperties[idx];
+ }
+ QT3DS_ASSERT(false);
+ return SRenderPluginPropertyDeclaration();
+ }
+
+ // From which you can get the property name breakdown
+ virtual eastl::pair<CRegisteredString, RenderPluginPropertyValueTypes::Enum>
+ GetPropertyValueInfo(QT3DSU32 inIndex) override
+ {
+ if (inIndex < m_FullPropertyList.size())
+ return m_FullPropertyList[inIndex];
+ QT3DS_ASSERT(false);
+ return eastl::pair<CRegisteredString, RenderPluginPropertyValueTypes::Enum>(
+ CRegisteredString(), RenderPluginPropertyValueTypes::NoRenderPluginPropertyValue);
+ }
+
+ void PushUpdates(TRenderPluginInstancePtr instance, TPropertyValueList &propertyValues) override
+ {
+ m_UpdateBuffer.clear();
+ for (QT3DSU32 idx = 0, end = propertyValues.size(); idx < end; ++idx) {
+ SRenderPluginPropertyData &theData(propertyValues[idx]);
+ if (theData.IsDirty())
+ m_UpdateBuffer.push_back(theData.ClearDirty(m_FullPropertyList[idx].first));
+ }
+ if (m_Class.UpdateInstance)
+ m_Class.UpdateInstance(m_Class.m_Class, instance, m_UpdateBuffer.data(),
+ (long)m_UpdateBuffer.size());
+ }
+
+ void Update(NVConstDataRef<SRenderPropertyValueUpdate> updateBuffer,
+ TPropertyValueList &propertyValues) override
+ {
+ for (QT3DSU32 idx = 0, end = updateBuffer.size(); idx < end; ++idx) {
+ const SRenderPropertyValueUpdate &update = updateBuffer[idx];
+ TStringIndexMap::iterator iter =
+ m_ComponentNameToComponentIndexMap.find(update.m_PropertyName);
+ if (iter == m_ComponentNameToComponentIndexMap.end()) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ QT3DSU32 propIndex = iter->second;
+ if (update.m_Value.getType() != m_FullPropertyList[propIndex].second) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ if (propIndex >= propertyValues.size())
+ propertyValues.resize(propIndex + 1);
+ propertyValues[propIndex].SetValue(update.m_Value);
+ }
+ }
+};
+
+struct PluginInstanceKey
+{
+ CRegisteredString m_Path;
+ void *m_InstanceKey;
+ PluginInstanceKey(CRegisteredString p, void *ik)
+ : m_Path(p)
+ , m_InstanceKey(ik)
+ {
+ }
+ bool operator==(const PluginInstanceKey &rhs) const
+ {
+ return m_Path == rhs.m_Path && m_InstanceKey == rhs.m_InstanceKey;
+ }
+};
+}
+
+namespace eastl {
+template <>
+struct hash<PluginInstanceKey>
+{
+ size_t operator()(const PluginInstanceKey &k) const
+ {
+ return hash<CRegisteredString>()(k.m_Path)
+ ^ hash<size_t>()(reinterpret_cast<size_t>(k.m_InstanceKey));
+ }
+ bool operator()(const PluginInstanceKey &lhs, const PluginInstanceKey &rhs) const
+ {
+ return lhs.m_Path == rhs.m_Path && lhs.m_InstanceKey == rhs.m_InstanceKey;
+ }
+};
+}
+
+namespace {
+
+struct SLoadedPluginData
+{
+ CRegisteredString m_PluginPath;
+ eastl::vector<SRenderPluginPropertyDeclaration> m_Properties;
+};
+
+typedef eastl::vector<SLoadedPluginData> TLoadedPluginDataList;
+
+struct PluginManagerImpl : public IRenderPluginManager, public IRenderPluginManagerCore
+{
+ typedef nvhash_map<CRegisteredString, NVScopedRefCounted<IRenderPluginClass>> TLoadedClassMap;
+ typedef nvhash_map<PluginInstanceKey, NVScopedRefCounted<IRenderPluginInstance>> TInstanceMap;
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ TLoadedClassMap m_LoadedClasses;
+ TInstanceMap m_Instances;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ IInputStreamFactory &m_InputStreamFactory;
+ QT3DSI32 mRefCount;
+ TStr m_DllDir;
+ TLoadedPluginDataList m_LoadedPluginData;
+
+ PluginManagerImpl(NVFoundationBase &fnd, IStringTable &st, IInputStreamFactory &inFactory)
+ : m_Foundation(fnd)
+ , m_StringTable(st)
+ , m_LoadedClasses(fnd.getAllocator(), "PluginManagerImpl::m_LoadedClasses")
+ , m_Instances(fnd.getAllocator(), "PluginManagerImpl::m_Instances")
+ , m_InputStreamFactory(inFactory)
+ , mRefCount(0)
+ , m_DllDir(ForwardingAllocator(fnd.getAllocator(), "PluginManagerImpl::m_DllDir"))
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ IRenderPluginClass *GetRenderPlugin(CRegisteredString inRelativePath) override
+ {
+ TLoadedClassMap::iterator iter = m_LoadedClasses.find(inRelativePath);
+ if (iter != m_LoadedClasses.end())
+ return iter->second;
+
+ return NVScopedRefCounted<IRenderPluginClass>();
+ }
+
+ IRenderPluginClass *GetOrCreateRenderPlugin(CRegisteredString inRelativePath) override
+ {
+ TLoadedClassMap::iterator iter = m_LoadedClasses.find(inRelativePath);
+ if (iter != m_LoadedClasses.end()) {
+ return iter->second;
+ }
+
+ // We insert right here to keep us from going down this path potentially for every instance.
+ iter =
+ m_LoadedClasses
+ .insert(eastl::make_pair(inRelativePath, NVScopedRefCounted<IRenderPluginClass>()))
+ .first;
+ eastl::string xmlDir, fname, extension;
+
+ CFileTools::Split(inRelativePath.c_str(), xmlDir, fname, extension);
+
+ eastl::string sharedLibrary(xmlDir);
+ eastl::string subdir(qt3ds::foundation::System::getPlatformGLStr());
+ eastl::string libdir;
+ eastl::string libpath;
+
+ CFileTools::CombineBaseAndRelative(xmlDir.c_str(), subdir.c_str(), libdir);
+ CFileTools::CombineBaseAndRelative(libdir.c_str(), fname.c_str(), libpath);
+#ifdef _DEBUG
+ libpath.append("d");
+#endif
+ libpath.append(qt3ds::foundation::System::g_DLLExtension);
+ eastl::string loadPath;
+ if (m_DllDir.size()) {
+ // Then we have to copy the dll to the dll directory before loading because the
+ // filesystem
+ // the plugin is on may not be executable.
+ eastl::string targetFile;
+ CFileTools::CombineBaseAndRelative(m_DllDir.c_str(), fname.c_str(), targetFile);
+#ifdef _DEBUG
+ targetFile.append("d");
+#endif
+ targetFile.append(qt3ds::foundation::System::g_DLLExtension);
+
+ qCInfo(TRACE_INFO, "Copying plugin shared library from %s to %s",
+ libpath.c_str(), targetFile.c_str());
+
+ // try to open the library.
+ NVScopedRefCounted<IRefCountedInputStream> theStream =
+ m_InputStreamFactory.GetStreamForFile(libpath.c_str());
+ if (!theStream) {
+ qCCritical(INVALID_OPERATION, "Failed to load render plugin %s",
+ libpath.c_str());
+ return NULL;
+ }
+ CFileSeekableIOStream outStream(targetFile.c_str(), FileWriteFlags());
+ if (!outStream.IsOpen()) {
+ qCCritical(INVALID_OPERATION, "Failed to load render plugin %s",
+ targetFile.c_str());
+ return NULL;
+ }
+
+ QT3DSU8 buf[1024] = { 0 };
+ for (QT3DSU32 len = theStream->Read(toDataRef(buf, 1024)); len;
+ len = theStream->Read(toDataRef(buf, 1024))) {
+ outStream.Write(toDataRef(buf, len));
+ }
+ loadPath = targetFile;
+ } else {
+ QString path;
+ m_InputStreamFactory.GetPathForFile(libpath.c_str(), path);
+ loadPath = path.toUtf8().data();
+ }
+ CLoadedDynamicLibrary *library = NULL;
+ TRenderPluginClass newPluginClass;
+ memSet(&newPluginClass, 0, sizeof(newPluginClass));
+
+ // Do not load plugin dlls during compilation steps or when we don't have a valid render
+ // context.
+ // They may try opengl access at some point and that would end in disaster during binary
+ // save steps.
+ if ((QT3DSU32)m_RenderContext->GetRenderContextType() != NVRenderContextValues::NullContext) {
+ library = CLoadedDynamicLibrary::Create(loadPath.c_str(), m_Foundation);
+ if (!library) {
+ // try loading it from the system instead of from this specific path. This means do
+ // not use any extensions or any special
+ // sauce.
+ loadPath = fname;
+#ifdef _DEBUG
+ loadPath.append("d");
+#endif
+ library = CLoadedDynamicLibrary::Create(loadPath.c_str(), m_Foundation);
+ }
+ }
+
+ if (library) {
+ TCreateRenderPluginClassFunction CreateClass =
+ reinterpret_cast<TCreateRenderPluginClassFunction>(
+ library->FindFunction("CreateRenderPlugin"));
+ if (CreateClass) {
+ newPluginClass = CreateClass(fname.c_str());
+ if (newPluginClass.m_Class) {
+ // Check that the required functions are there.
+ if (newPluginClass.CreateInstance == NULL
+ || newPluginClass.QueryInstanceRenderSurface == NULL
+ || newPluginClass.RenderInstance == NULL
+ || newPluginClass.ReleaseInstance == NULL
+ || newPluginClass.ReleaseClass == NULL) {
+ if (newPluginClass.ReleaseClass)
+ newPluginClass.ReleaseClass(newPluginClass.m_Class);
+ qCCritical(INVALID_OPERATION,
+ "Failed to load render plugin: %s, required functions "
+ "missing. Required functions are:"
+ "CreateInstance, QueryInstanceRenderSurface, "
+ "RenderInstance, ReleaseInstance, ReleaseClass",
+ inRelativePath.c_str());
+ NVDelete(m_Foundation.getAllocator(), library);
+ memSet(&newPluginClass, 0, sizeof(newPluginClass));
+ }
+ }
+ }
+ }
+ if (newPluginClass.m_Class) {
+ PluginClassImpl *retval = QT3DS_NEW(m_Foundation.getAllocator(), PluginClassImpl)(
+ m_Foundation, m_StringTable, newPluginClass,
+ m_StringTable.RegisterStr(fname.c_str()), library);
+
+ iter->second = retval;
+ if (newPluginClass.InitializeClassGLResources) {
+ m_RenderContext->PushPropertySet();
+ newPluginClass.InitializeClassGLResources(newPluginClass.m_Class, loadPath.c_str());
+ m_RenderContext->PopPropertySet(true);
+ }
+ return iter->second;
+ }
+ return NULL;
+ }
+
+ void SetDllDir(const char *inDllDir) override { m_DllDir.assign(nonNull(inDllDir)); }
+
+ IRenderPluginInstance *GetOrCreateRenderPluginInstance(CRegisteredString inRelativePath,
+ void *inKey) override
+ {
+ PluginInstanceKey theKey(inRelativePath, inKey);
+ TInstanceMap::iterator iter = m_Instances.find(theKey);
+ if (iter == m_Instances.end()) {
+ IRenderPluginClass *theClass = GetOrCreateRenderPlugin(inRelativePath);
+ NVScopedRefCounted<IRenderPluginInstance> theInstance;
+ if (theClass)
+ theInstance = theClass->CreateInstance();
+
+ iter = m_Instances.insert(eastl::make_pair(theKey, theInstance)).first;
+ }
+ return iter->second.mPtr;
+ }
+
+ void Save(qt3ds::render::SWriteBuffer &ioBuffer,
+ const qt3ds::render::SStrRemapMap &inRemapMap,
+ const char8_t * /*inProjectDir*/) const override
+ {
+ QT3DSU32 numClasses = m_LoadedClasses.size();
+ ioBuffer.write(numClasses);
+ for (TLoadedClassMap::const_iterator iter = m_LoadedClasses.begin(),
+ end = m_LoadedClasses.end();
+ iter != end; ++iter) {
+ CRegisteredString saveStr = iter->first;
+ saveStr.Remap(inRemapMap);
+ ioBuffer.write(saveStr);
+ if (iter->second) {
+ NVConstDataRef<SRenderPluginPropertyDeclaration> theProperties =
+ const_cast<IRenderPluginClass &>((*iter->second)).GetRegisteredProperties();
+ ioBuffer.write(theProperties.size());
+ for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
+ SRenderPluginPropertyDeclaration theDec(theProperties[idx]);
+ theDec.m_Name.Remap(inRemapMap);
+ ioBuffer.write(theDec);
+ }
+ } else
+ ioBuffer.write((QT3DSU32)0);
+ }
+ }
+
+ void Load(NVDataRef<QT3DSU8> inData, CStrTableOrDataRef inStrDataBlock,
+ const char8_t * /*inProjectDir*/) override
+ {
+ qt3ds::render::SDataReader theReader(inData.begin(), inData.end());
+ QT3DSU32 numClasses = theReader.LoadRef<QT3DSU32>();
+ ForwardingAllocator alloc(m_Foundation.getAllocator(), "tempstrings");
+ qt3ds::foundation::TStr workStr(alloc);
+ nvvector<SRenderPluginPropertyDeclaration> propertyBuffer(m_Foundation.getAllocator(),
+ "tempprops");
+ for (QT3DSU32 classIdx = 0; classIdx < numClasses; ++classIdx) {
+ CRegisteredString classPath = theReader.LoadRef<CRegisteredString>();
+ classPath.Remap(inStrDataBlock);
+ QT3DSU32 numProperties = theReader.LoadRef<QT3DSU32>();
+ propertyBuffer.clear();
+ for (QT3DSU32 propIdx = 0; propIdx < numProperties; ++propIdx) {
+ propertyBuffer.push_back(theReader.LoadRef<SRenderPluginPropertyDeclaration>());
+ propertyBuffer.back().m_Name.Remap(inStrDataBlock);
+ }
+ m_LoadedPluginData.push_back(SLoadedPluginData());
+ m_LoadedPluginData.back().m_PluginPath = classPath;
+ m_LoadedPluginData.back().m_Properties.assign(propertyBuffer.begin(),
+ propertyBuffer.end());
+ }
+ }
+ IRenderPluginManager &GetRenderPluginManager(NVRenderContext &rc) override
+ {
+ m_RenderContext = rc;
+ for (QT3DSU32 idx = 0, end = m_LoadedPluginData.size(); idx < end; ++idx) {
+ // Now we can attempt to load the class.
+ IRenderPluginClass *theClass =
+ GetOrCreateRenderPlugin(m_LoadedPluginData[idx].m_PluginPath);
+ if (theClass) {
+ eastl::vector<SRenderPluginPropertyDeclaration> &propertyBuffer(
+ m_LoadedPluginData[idx].m_Properties);
+ for (QT3DSU32 propIdx = 0, propEnd = propertyBuffer.size(); propIdx < propEnd;
+ ++propIdx) {
+ theClass->RegisterProperty(propertyBuffer[propIdx]);
+ }
+ }
+ }
+ m_LoadedPluginData.clear();
+ return *this;
+ }
+};
+}
+
+IRenderPluginManagerCore &IRenderPluginManagerCore::Create(NVFoundationBase &inFoundation,
+ IStringTable &strTable,
+ IInputStreamFactory &inFactory)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), PluginManagerImpl)(inFoundation, strTable,
+ inFactory);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderRay.cpp b/src/Runtime/Source/UICRender/Source/UICRenderRay.cpp
new file mode 100644
index 00000000..21e0d460
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderRay.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderRay.h"
+#include "foundation/Qt3DSPlane.h"
+
+using namespace uic::render;
+
+// http://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm
+
+Option<QT3DSVec3> SRay::Intersect(const NVPlane &inPlane) const
+{
+ QT3DSF32 Vd = inPlane.n.dot(m_Direction);
+ if (fabs(Vd) < .0001f)
+ return Empty();
+ QT3DSF32 V0 = -1.0f * (inPlane.n.dot(m_Origin) + inPlane.d);
+ QT3DSF32 t = V0 / Vd;
+ return m_Origin + (m_Direction * t);
+}
+
+Option<SRayIntersectionResult> SRay::IntersectWithAABB(const QT3DSMat44 &inGlobalTransform,
+ const NVBounds3 &inBounds,
+ bool inForceIntersect) const
+{
+ // Intersect the origin with the AABB described by bounds.
+
+ // Scan each axis separately. This code basically finds the distance
+ // distance from the origin to the near and far bbox planes for a given
+ // axis. It then divides this distance by the direction for that axis to
+ // get a range of t [near,far] that the ray intersects assuming the ray is
+ // described via origin + t*(direction). Running through all three axis means
+ // that you need to min/max those ranges together to find a global min/max
+ // that the pick could possibly be in.
+
+ // Transform pick origin and direction into the subset's space.
+ QT3DSMat44 theOriginTransform = inGlobalTransform.getInverse();
+
+ QT3DSVec3 theTransformedOrigin = theOriginTransform.transform(m_Origin);
+ QT3DSF32 *outOriginTransformPtr(theOriginTransform.front());
+ outOriginTransformPtr[12] = outOriginTransformPtr[13] = outOriginTransformPtr[14] = 0.0f;
+ QT3DSVec3 theTransformedDirection = theOriginTransform.rotate(m_Direction);
+
+ static const QT3DSF32 KD_FLT_MAX = 3.40282346638528860e+38;
+ static const QT3DSF32 kEpsilon = 1e-5f;
+
+ QT3DSF32 theMinWinner = -KD_FLT_MAX;
+ QT3DSF32 theMaxWinner = KD_FLT_MAX;
+
+ for (QT3DSU32 theAxis = 0; theAxis < 3; ++theAxis) {
+ // Extract the ranges and direction for this axis
+ QT3DSF32 theMinBox = inBounds.minimum[theAxis];
+ QT3DSF32 theMaxBox = inBounds.maximum[theAxis];
+ QT3DSF32 theDirectionAxis = theTransformedDirection[theAxis];
+ QT3DSF32 theOriginAxis = theTransformedOrigin[theAxis];
+
+ QT3DSF32 theMinAxis = -KD_FLT_MAX;
+ QT3DSF32 theMaxAxis = KD_FLT_MAX;
+ if (theDirectionAxis > kEpsilon) {
+ theMinAxis = (theMinBox - theOriginAxis) / theDirectionAxis;
+ theMaxAxis = (theMaxBox - theOriginAxis) / theDirectionAxis;
+ } else if (theDirectionAxis < -kEpsilon) {
+ theMinAxis = (theMaxBox - theOriginAxis) / theDirectionAxis;
+ theMaxAxis = (theMinBox - theOriginAxis) / theDirectionAxis;
+ } else if ((theOriginAxis < theMinBox || theOriginAxis > theMaxBox)
+ && inForceIntersect == false) {
+ // Pickray is roughly parallel to the plane of the slab
+ // so, if the origin is not in the range, we have no intersection
+ return Empty();
+ }
+
+ // Shrink the intersections to find the closest hit
+ theMinWinner = NVMax(theMinWinner, theMinAxis);
+ theMaxWinner = NVMin(theMaxWinner, theMaxAxis);
+
+ if ((theMinWinner > theMaxWinner || theMaxWinner < 0) && inForceIntersect == false)
+ return Empty();
+ }
+
+ QT3DSVec3 scaledDir = theTransformedDirection * theMinWinner;
+ QT3DSVec3 newPosInLocal = theTransformedOrigin + scaledDir;
+ QT3DSVec3 newPosInGlobal = inGlobalTransform.transform(newPosInLocal);
+ QT3DSVec3 cameraToLocal = m_Origin - newPosInGlobal;
+
+ QT3DSF32 rayLengthSquared = cameraToLocal.magnitudeSquared();
+
+ QT3DSF32 xRange = inBounds.maximum.x - inBounds.minimum.x;
+ QT3DSF32 yRange = inBounds.maximum.y - inBounds.minimum.y;
+
+ QT3DSVec2 relXY;
+ relXY.x = (newPosInLocal[0] - inBounds.minimum.x) / xRange;
+ relXY.y = (newPosInLocal[1] - inBounds.minimum.y) / yRange;
+
+ return SRayIntersectionResult(rayLengthSquared, relXY);
+}
+
+Option<QT3DSVec2> SRay::GetRelative(const QT3DSMat44 &inGlobalTransform, const NVBounds3 &inBounds,
+ SBasisPlanes::Enum inPlane) const
+{
+ QT3DSMat44 theOriginTransform = inGlobalTransform.getInverse();
+
+ QT3DSVec3 theTransformedOrigin = theOriginTransform.transform(m_Origin);
+ QT3DSF32 *outOriginTransformPtr(theOriginTransform.front());
+ outOriginTransformPtr[12] = outOriginTransformPtr[13] = outOriginTransformPtr[14] = 0.0f;
+ QT3DSVec3 theTransformedDirection = theOriginTransform.rotate(m_Direction);
+
+ // The XY plane is going to be a plane with either positive or negative Z direction that runs
+ // through
+ QT3DSVec3 theDirection(0, 0, 1);
+ QT3DSVec3 theRight(1, 0, 0);
+ QT3DSVec3 theUp(0, 1, 0);
+ switch (inPlane) {
+ case SBasisPlanes::XY:
+ break;
+ case SBasisPlanes::XZ:
+ theDirection = QT3DSVec3(0, 1, 0);
+ theUp = QT3DSVec3(0, 0, 1);
+ break;
+ case SBasisPlanes::YZ:
+ theDirection = QT3DSVec3(1, 0, 0);
+ theRight = QT3DSVec3(0, 0, 1);
+ break;
+ }
+ NVPlane thePlane(theDirection, theDirection.dot(theTransformedDirection) > 0.0f
+ ? theDirection.dot(inBounds.maximum)
+ : theDirection.dot(inBounds.minimum));
+
+ SRay relativeRay(theTransformedOrigin, theTransformedDirection);
+ Option<QT3DSVec3> localIsect = relativeRay.Intersect(thePlane);
+ if (localIsect.hasValue()) {
+ QT3DSF32 xRange = theRight.dot(inBounds.maximum) - theRight.dot(inBounds.minimum);
+ QT3DSF32 yRange = theUp.dot(inBounds.maximum) - theUp.dot(inBounds.minimum);
+ QT3DSF32 xOrigin = xRange / 2.0f + theRight.dot(inBounds.minimum);
+ QT3DSF32 yOrigin = yRange / 2.0f + theUp.dot(inBounds.minimum);
+ return QT3DSVec2((theRight.dot(*localIsect) - xOrigin) / xRange,
+ (theUp.dot(*localIsect) - yOrigin) / yRange);
+ }
+ return Empty();
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderRenderList.cpp b/src/Runtime/Source/UICRender/Source/UICRenderRenderList.cpp
new file mode 100644
index 00000000..f36bebb7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderRenderList.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderRenderList.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+
+using namespace uic::render;
+
+namespace {
+
+struct SRenderList : public IRenderList
+{
+ typedef eastl::pair<QT3DSU32, IRenderTask *> TTaskIdTaskPair;
+ typedef nvvector<TTaskIdTaskPair> TTaskList;
+
+ NVFoundationBase &m_Foundation;
+ TTaskList m_Tasks;
+ QT3DSU32 m_NextTaskId;
+ QT3DSI32 mRefCount;
+ bool m_ScissorEnabled;
+ NVRenderRect m_ScissorRect;
+ NVRenderRect m_Viewport;
+
+ SRenderList(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ , m_Tasks(fnd.getAllocator(), "m_Tasks")
+ , m_NextTaskId(1)
+ , mRefCount(0)
+ , m_ScissorEnabled(false)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void BeginFrame() override
+ {
+ m_NextTaskId = 1;
+ m_Tasks.clear();
+ }
+
+ QT3DSU32 AddRenderTask(IRenderTask &inTask) override
+ {
+ QT3DSU32 taskId = m_NextTaskId;
+ ++m_NextTaskId;
+ m_Tasks.push_back(eastl::make_pair(taskId, &inTask));
+ return taskId;
+ }
+
+ void DiscardRenderTask(QT3DSU32 inTaskId) override
+ {
+ TTaskList::iterator iter, end;
+ for (iter = m_Tasks.begin(), end = m_Tasks.end(); iter != end && iter->first != inTaskId;
+ ++iter) {
+ }
+ if (iter != end)
+ m_Tasks.erase(iter);
+ }
+ // This runs through the added tasks in reverse order. This is used to render dependencies
+ // before rendering to the main render target.
+ void RunRenderTasks() override
+ {
+ for (TTaskList::reverse_iterator iter = m_Tasks.rbegin(), end = m_Tasks.rend(); iter != end;
+ ++iter)
+ iter->second->Run();
+ BeginFrame();
+ }
+
+ void SetScissorTestEnabled(bool enabled) override { m_ScissorEnabled = enabled; }
+ void SetScissorRect(NVRenderRect rect) override { m_ScissorRect = rect; }
+ void SetViewport(NVRenderRect rect) override { m_Viewport = rect; }
+ bool IsScissorTestEnabled() const override { return m_ScissorEnabled; }
+ NVRenderRect GetScissor() const override { return m_ScissorRect; }
+ NVRenderRect GetViewport() const override { return m_Viewport; }
+};
+}
+
+IRenderList &IRenderList::CreateRenderList(NVFoundationBase &fnd)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SRenderList)(fnd);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp b/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp
new file mode 100644
index 00000000..1db2e77b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderShaderCache.cpp
@@ -0,0 +1,755 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderShaderCache.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICRenderString.h"
+#include "foundation/XML.h"
+#include "foundation/IOStreams.h"
+#include "foundation/StringConversionImpl.h"
+#include "UICRenderInputStreamFactory.h"
+#include "foundation/FileTools.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "UICRenderer.h"
+#include <memory>
+#include "foundation/Qt3DSTime.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include "EASTL/sort.h"
+
+#include <QRegularExpression>
+#include <QString>
+
+using namespace uic::render;
+
+namespace {
+using qt3ds::render::NVRenderContextScopedProperty;
+const char *TessellationEnabledStr = "TessellationStageEnabled";
+const char *GeometryEnabledStr = "GeometryStageEnabled";
+inline void AppendFlagValue(CRenderString &inStr, const char *flag)
+{
+ if (inStr.length())
+ inStr.append(1, ',');
+ inStr.append(flag);
+}
+inline void CacheFlagsToStr(const SShaderCacheProgramFlags &inFlags, CRenderString &inString)
+{
+ inString.clear();
+ if (inFlags.IsTessellationEnabled())
+ AppendFlagValue(inString, TessellationEnabledStr);
+ if (inFlags.IsGeometryShaderEnabled())
+ AppendFlagValue(inString, GeometryEnabledStr);
+}
+
+struct ShaderType
+{
+ enum Enum { Vertex, TessControl, TessEval, Fragment, Geometry, Compute };
+};
+
+inline ShaderType::Enum StringToShaderType(CRenderString &inShaderType)
+{
+ ShaderType::Enum retval = ShaderType::Vertex;
+
+ if (inShaderType.size() == 0)
+ return retval;
+
+ if (!inShaderType.compare("VertexCode"))
+ retval = ShaderType::Vertex;
+ else if (!inShaderType.compare("FragmentCode"))
+ retval = ShaderType::Fragment;
+ else if (!inShaderType.compare("TessControlCode"))
+ retval = ShaderType::TessControl;
+ else if (!inShaderType.compare("TessEvalCode"))
+ retval = ShaderType::TessEval;
+ else if (!inShaderType.compare("GeometryCode"))
+ retval = ShaderType::Geometry;
+ else
+ QT3DS_ASSERT(false);
+
+ return retval;
+}
+
+inline SShaderCacheProgramFlags CacheFlagsToStr(const CRenderString &inString)
+{
+ SShaderCacheProgramFlags retval;
+ if (inString.find(TessellationEnabledStr) != CRenderString::npos)
+ retval.SetTessellationEnabled(true);
+ if (inString.find(GeometryEnabledStr) != CRenderString::npos)
+ retval.SetGeometryShaderEnabled(true);
+ return retval;
+}
+
+typedef eastl::pair<const char *, NVRenderContextValues::Enum> TStringToContextValuePair;
+
+/*GLES2 = 1 << 0,
+GL2 = 1 << 1,
+GLES3 = 1 << 2,
+GL3 = 1 << 3,
+GL4 = 1 << 4,
+NullContext = 1 << 5,*/
+TStringToContextValuePair g_StringToContextTypeValue[] = {
+ TStringToContextValuePair("GLES2", NVRenderContextValues::GLES2),
+ TStringToContextValuePair("GL2", NVRenderContextValues::GL2),
+ TStringToContextValuePair("GLES3", NVRenderContextValues::GLES3),
+ TStringToContextValuePair("GLES3PLUS", NVRenderContextValues::GLES3PLUS),
+ TStringToContextValuePair("GL3", NVRenderContextValues::GL3),
+ TStringToContextValuePair("GL4", NVRenderContextValues::GL4),
+ TStringToContextValuePair("NullContext", NVRenderContextValues::NullContext),
+};
+
+size_t g_NumStringToContextValueEntries =
+ sizeof(g_StringToContextTypeValue) / sizeof(*g_StringToContextTypeValue);
+
+inline void ContextTypeToString(qt3ds::render::NVRenderContextType inType,
+ CRenderString &outContextType)
+{
+ outContextType.clear();
+ for (size_t idx = 0, end = g_NumStringToContextValueEntries; idx < end; ++idx) {
+ if (inType & g_StringToContextTypeValue[idx].second) {
+ if (outContextType.size())
+ outContextType.append(1, '|');
+ outContextType.append(g_StringToContextTypeValue[idx].first);
+ }
+ }
+}
+
+inline qt3ds::render::NVRenderContextType StringToContextType(const CRenderString &inContextType)
+{
+ qt3ds::render::NVRenderContextType retval;
+ char tempBuffer[128];
+ memZero(tempBuffer, 128);
+ const eastl::string::size_type lastTempBufIdx = 127;
+ eastl::string::size_type pos = 0, lastpos = 0;
+ if (inContextType.size() == 0)
+ return retval;
+
+ do {
+ pos = inContextType.find('|', lastpos);
+ if (pos == eastl::string::npos)
+ pos = inContextType.size();
+ {
+
+ eastl::string::size_type sectionLen = NVMin(pos - lastpos, lastTempBufIdx);
+ qt3ds::intrinsics::memCopy(tempBuffer, inContextType.c_str() + lastpos, sectionLen);
+ tempBuffer[lastTempBufIdx] = 0;
+ for (size_t idx = 0, end = g_NumStringToContextValueEntries; idx < end; ++idx) {
+ if (strcmp(g_StringToContextTypeValue[idx].first, tempBuffer) == 0)
+ retval = retval | g_StringToContextTypeValue[idx].second;
+ }
+ }
+ // iterate past the bar
+ ++pos;
+ lastpos = pos;
+ } while (pos < inContextType.size() && pos != eastl::string::npos);
+
+ return retval;
+}
+
+struct SShaderCacheKey
+{
+ CRegisteredString m_Key;
+ eastl::vector<SShaderPreprocessorFeature> m_Features;
+ size_t m_HashCode;
+
+ SShaderCacheKey(CRegisteredString key = CRegisteredString())
+ : m_Key(key)
+ , m_HashCode(0)
+ {
+ }
+
+ SShaderCacheKey(const SShaderCacheKey &other)
+ : m_Key(other.m_Key)
+ , m_Features(other.m_Features)
+ , m_HashCode(other.m_HashCode)
+ {
+ }
+
+ SShaderCacheKey &operator=(const SShaderCacheKey &other)
+ {
+ m_Key = other.m_Key;
+ m_Features = other.m_Features;
+ m_HashCode = other.m_HashCode;
+ return *this;
+ }
+
+ void GenerateHashCode()
+ {
+ m_HashCode = m_Key.hash();
+ m_HashCode = m_HashCode
+ ^ HashShaderFeatureSet(toDataRef(m_Features.data(), (QT3DSU32)m_Features.size()));
+ }
+ bool operator==(const SShaderCacheKey &inOther) const
+ {
+ return m_Key == inOther.m_Key && m_Features == inOther.m_Features;
+ }
+};
+}
+
+namespace eastl {
+template <>
+struct hash<SShaderCacheKey>
+{
+ size_t operator()(const SShaderCacheKey &inKey) const { return inKey.m_HashCode; }
+};
+}
+
+namespace {
+
+struct ShaderCache : public IShaderCache
+{
+ typedef nvhash_map<SShaderCacheKey, NVScopedRefCounted<NVRenderShaderProgram>> TShaderMap;
+ NVRenderContext &m_RenderContext;
+ IPerfTimer &m_PerfTimer;
+ TShaderMap m_Shaders;
+ CRenderString m_CacheFilePath;
+ CRenderString m_VertexCode;
+ CRenderString m_TessCtrlCode;
+ CRenderString m_TessEvalCode;
+ CRenderString m_GeometryCode;
+ CRenderString m_FragmentCode;
+ CRenderString m_InsertStr;
+ CRenderString m_FlagString;
+ CRenderString m_ContextTypeString;
+ SShaderCacheKey m_TempKey;
+
+ NVScopedRefCounted<IDOMWriter> m_ShaderCache;
+ IInputStreamFactory &m_InputStreamFactory;
+ bool m_ShaderCompilationEnabled;
+ volatile QT3DSI32 mRefCount;
+
+ ShaderCache(NVRenderContext &ctx, IInputStreamFactory &inInputStreamFactory,
+ IPerfTimer &inPerfTimer)
+ : m_RenderContext(ctx)
+ , m_PerfTimer(inPerfTimer)
+ , m_Shaders(ctx.GetAllocator(), "ShaderCache::m_Shaders")
+ , m_InputStreamFactory(inInputStreamFactory)
+ , m_ShaderCompilationEnabled(true)
+ , mRefCount(0)
+ {
+ }
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator())
+
+ NVRenderShaderProgram *GetProgram(CRegisteredString inKey,
+ NVConstDataRef<SShaderPreprocessorFeature> inFeatures) override
+ {
+ m_TempKey.m_Key = inKey;
+ m_TempKey.m_Features.assign(inFeatures.begin(), inFeatures.end());
+ m_TempKey.GenerateHashCode();
+ TShaderMap::iterator theIter = m_Shaders.find(m_TempKey);
+ if (theIter != m_Shaders.end())
+ return theIter->second;
+ return NULL;
+ }
+
+ void AddBackwardCompatibilityDefines(ShaderType::Enum shaderType)
+ {
+ if (shaderType == ShaderType::Vertex || shaderType == ShaderType::TessControl
+ || shaderType == ShaderType::TessEval || shaderType == ShaderType::Geometry) {
+ m_InsertStr += "#define attribute in\n";
+ m_InsertStr += "#define varying out\n";
+ } else if (shaderType == ShaderType::Fragment) {
+ m_InsertStr += "#define varying in\n";
+ m_InsertStr += "#define texture2D texture\n";
+ m_InsertStr += "#define gl_FragColor fragOutput\n";
+
+ if (m_RenderContext.IsAdvancedBlendHwSupportedKHR())
+ m_InsertStr += "layout(blend_support_all_equations) out;\n ";
+ m_InsertStr += "out vec4 fragOutput;\n";
+ }
+ }
+
+ void AddShaderExtensionStrings(ShaderType::Enum shaderType, bool isGLES)
+ {
+ if (isGLES)
+ m_InsertStr += "#extension GL_OES_standard_derivatives : enable\n";
+
+ if (IUICRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
+ if (shaderType == ShaderType::TessControl || shaderType == ShaderType::TessEval) {
+ m_InsertStr += "#extension GL_EXT_tessellation_shader : enable\n";
+ } else if (shaderType == ShaderType::Geometry) {
+ m_InsertStr += "#extension GL_EXT_geometry_shader : enable\n";
+ } else if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment) {
+ if (m_RenderContext.GetRenderBackendCap(render::NVRenderBackend::NVRenderBackendCaps::gpuShader5))
+ m_InsertStr += "#extension GL_EXT_gpu_shader5 : enable\n";
+ if (m_RenderContext.IsAdvancedBlendHwSupportedKHR())
+ m_InsertStr += "#extension GL_KHR_blend_equation_advanced : enable\n";
+ }
+ } else {
+ if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment
+ || shaderType == ShaderType::Geometry) {
+ m_InsertStr += "#extension GL_ARB_gpu_shader5 : enable\n";
+ m_InsertStr += "#extension GL_ARB_shading_language_420pack : enable\n";
+ if (m_RenderContext.IsShaderImageLoadStoreSupported()) {
+ m_InsertStr += "#extension GL_ARB_shader_image_load_store : enable\n";
+ }
+ if (m_RenderContext.IsAtomicCounterBufferSupported()) {
+ m_InsertStr += "#extension GL_ARB_shader_atomic_counters : enable\n";
+ }
+ if (m_RenderContext.IsStorageBufferSupported()) {
+ m_InsertStr += "#extension GL_ARB_shader_storage_buffer_object : enable\n";
+ }
+ if (m_RenderContext.IsAdvancedBlendHwSupportedKHR()) {
+ m_InsertStr += "#extension GL_KHR_blend_equation_advanced : enable\n";
+ }
+ }
+ }
+ }
+
+ void AddShaderPreprocessor(CRenderString &str, CRegisteredString inKey,
+ ShaderType::Enum shaderType,
+ NVConstDataRef<SShaderPreprocessorFeature> inFeatures)
+ {
+ // Don't use shading language version returned by the driver as it might
+ // differ from the context version. Instead use the context type to specify
+ // the version string.
+ bool isGlES = IUICRenderer::IsGlEsContext(m_RenderContext.GetRenderContextType());
+ m_InsertStr.clear();
+ int minor = m_RenderContext.format().minorVersion();
+ QString versionStr;
+ QTextStream stream(&versionStr);
+ stream << "#version ";
+ const QT3DSU32 type = (QT3DSU32)m_RenderContext.GetRenderContextType();
+ switch (type) {
+ case NVRenderContextValues::GLES2:
+ stream << "1" << minor << "0 es\n";
+ break;
+ case NVRenderContextValues::GL2:
+ stream << "1" << minor << "0\n";
+ break;
+ case NVRenderContextValues::GLES3PLUS:
+ case NVRenderContextValues::GLES3:
+ stream << "3" << minor << "0 es\n";
+ break;
+ case NVRenderContextValues::GL3:
+ if (minor == 3)
+ stream << "3" << minor << "0\n";
+ else
+ stream << "1" << 3 + minor << "0\n";
+ break;
+ case NVRenderContextValues::GL4:
+ stream << "4" << minor << "0\n";
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+
+ m_InsertStr.append(versionStr.toLatin1().data());
+
+ if (isGlES) {
+ if (!IUICRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
+ if (shaderType == ShaderType::Fragment) {
+ m_InsertStr += "#define fragOutput gl_FragData[0]\n";
+ }
+ } else {
+ m_InsertStr += "#define texture2D texture\n";
+ }
+
+ // add extenions strings before any other non-processor token
+ AddShaderExtensionStrings(shaderType, isGlES);
+
+ // add precision qualifier depending on backend
+ if (IUICRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
+ m_InsertStr.append("precision highp float;\n"
+ "precision highp int;\n");
+ if( m_RenderContext.GetRenderBackendCap(render::NVRenderBackend::NVRenderBackendCaps::gpuShader5) ) {
+ m_InsertStr.append("precision mediump sampler2D;\n"
+ "precision mediump sampler2DArray;\n"
+ "precision mediump sampler2DShadow;\n");
+ if (m_RenderContext.IsShaderImageLoadStoreSupported()) {
+ m_InsertStr.append("precision mediump image2D;\n");
+ }
+ }
+
+ AddBackwardCompatibilityDefines(shaderType);
+ } else {
+ m_InsertStr.append("precision mediump float;\n"
+ "precision mediump int;\n"
+ "precision mediump sampler2D;\n"
+ "precision mediump sampler2DArray;\n"
+ "precision mediump sampler2DShadow;\n");
+ }
+ } else {
+ if (!IUICRenderer::IsGl2Context(m_RenderContext.GetRenderContextType())) {
+ m_InsertStr += "#define texture2D texture\n";
+
+ AddShaderExtensionStrings(shaderType, isGlES);
+
+ m_InsertStr += "#if __VERSION__ >= 330\n";
+
+ AddBackwardCompatibilityDefines(shaderType);
+
+ m_InsertStr += "#else\n";
+ if (shaderType == ShaderType::Fragment) {
+ m_InsertStr += "#define fragOutput gl_FragData[0]\n";
+ }
+ m_InsertStr += "#endif\n";
+ }
+ }
+
+ if (inKey.IsValid()) {
+ m_InsertStr += "//Shader name -";
+ m_InsertStr += inKey.c_str();
+ m_InsertStr += "\n";
+ }
+
+ if (shaderType == ShaderType::TessControl) {
+ m_InsertStr += "#define TESSELLATION_CONTROL_SHADER 1\n";
+ m_InsertStr += "#define TESSELLATION_EVALUATION_SHADER 0\n";
+ } else if (shaderType == ShaderType::TessEval) {
+ m_InsertStr += "#define TESSELLATION_CONTROL_SHADER 0\n";
+ m_InsertStr += "#define TESSELLATION_EVALUATION_SHADER 1\n";
+ }
+
+ str.insert(0, m_InsertStr);
+ if (inFeatures.size()) {
+ eastl::string::size_type insertPos = m_InsertStr.size();
+ m_InsertStr.clear();
+ for (QT3DSU32 idx = 0, end = inFeatures.size(); idx < end; ++idx) {
+ SShaderPreprocessorFeature feature(inFeatures[idx]);
+ m_InsertStr.append("#define ");
+ m_InsertStr.append(inFeatures[idx].m_Name.c_str());
+ m_InsertStr.append(" ");
+ m_InsertStr.append(feature.m_Enabled ? "1" : "0");
+ m_InsertStr.append("\n");
+ }
+ str.insert(insertPos, m_InsertStr);
+ }
+ }
+ // Compile this program overwriting any existing ones.
+ NVRenderShaderProgram *
+ ForceCompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag,
+ const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom,
+ const SShaderCacheProgramFlags &inFlags,
+ NVConstDataRef<SShaderPreprocessorFeature> inFeatures,
+ bool separableProgram) override
+ {
+ if (m_ShaderCompilationEnabled == false)
+ return NULL;
+ SShaderCacheKey tempKey(inKey);
+ tempKey.m_Features.assign(inFeatures.begin(), inFeatures.end());
+ tempKey.GenerateHashCode();
+
+ eastl::pair<TShaderMap::iterator, bool> theInserter = m_Shaders.insert(tempKey);
+ if (!inVert)
+ inVert = "";
+ if (!inTessCtrl)
+ inTessCtrl = "";
+ if (!inTessEval)
+ inTessEval = "";
+ if (!inGeom)
+ inGeom = "";
+ if (!inFrag)
+ inFrag = "";
+
+ SStackPerfTimer __perfTimer(m_PerfTimer, "Shader Compilation");
+ m_VertexCode.assign(inVert);
+ m_TessCtrlCode.assign(inTessCtrl);
+ m_TessEvalCode.assign(inTessEval);
+ m_GeometryCode.assign(inGeom);
+ m_FragmentCode.assign(inFrag);
+ // Add defines and such so we can write unified shaders that work across platforms.
+ // vertex and fragment shaders are optional for separable shaders
+ if (!separableProgram || !m_VertexCode.empty())
+ AddShaderPreprocessor(m_VertexCode, inKey, ShaderType::Vertex, inFeatures);
+ if (!separableProgram || !m_FragmentCode.empty())
+ AddShaderPreprocessor(m_FragmentCode, inKey, ShaderType::Fragment, inFeatures);
+ // optional shaders
+ if (inFlags.IsTessellationEnabled()) {
+ QT3DS_ASSERT(m_TessCtrlCode.size() && m_TessEvalCode.size());
+ AddShaderPreprocessor(m_TessCtrlCode, inKey, ShaderType::TessControl, inFeatures);
+ AddShaderPreprocessor(m_TessEvalCode, inKey, ShaderType::TessEval, inFeatures);
+ }
+ if (inFlags.IsGeometryShaderEnabled())
+ AddShaderPreprocessor(m_GeometryCode, inKey, ShaderType::Geometry, inFeatures);
+
+ qCInfo(TRACE_INFO, "Shader compiler - compiling shader %s", inKey.c_str());
+
+ theInserter.first->second =
+ m_RenderContext
+ .CompileSource(inKey, m_VertexCode.c_str(), m_VertexCode.size(),
+ m_FragmentCode.c_str(), m_FragmentCode.size(),
+ m_TessCtrlCode.c_str(), m_TessCtrlCode.size(),
+ m_TessEvalCode.c_str(), m_TessEvalCode.size(),
+ m_GeometryCode.c_str(), m_GeometryCode.size(), separableProgram)
+ .mShader;
+ if (theInserter.first->second) {
+ if (m_ShaderCache) {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "Program");
+ m_ShaderCache->Att("key", inKey.c_str());
+ CacheFlagsToStr(inFlags, m_FlagString);
+ if (m_FlagString.size())
+ m_ShaderCache->Att("glflags", m_FlagString.c_str());
+ // write out the GL version.
+ {
+ qt3ds::render::NVRenderContextType theContextType =
+ m_RenderContext.GetRenderContextType();
+ ContextTypeToString(theContextType, m_ContextTypeString);
+ m_ShaderCache->Att("gl-context-type", m_ContextTypeString.c_str());
+ }
+ if (inFeatures.size()) {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "Features");
+ for (QT3DSU32 idx = 0, end = inFeatures.size(); idx < end; ++idx) {
+ m_ShaderCache->Att(inFeatures[idx].m_Name, inFeatures[idx].m_Enabled);
+ }
+ }
+
+ {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "VertexCode");
+ m_ShaderCache->Value(inVert);
+ }
+ {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "FragmentCode");
+ m_ShaderCache->Value(inFrag);
+ }
+ if (m_TessCtrlCode.size()) {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "TessControlCode");
+ m_ShaderCache->Value(inTessCtrl);
+ }
+ if (m_TessEvalCode.size()) {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "TessEvalCode");
+ m_ShaderCache->Value(inTessEval);
+ }
+ if (m_GeometryCode.size()) {
+ IDOMWriter::Scope __writeScope(*m_ShaderCache, "GeometryCode");
+ m_ShaderCache->Value(inGeom);
+ }
+ }
+ }
+ return theInserter.first->second;
+ }
+
+ virtual NVRenderShaderProgram *
+ CompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag,
+ const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom,
+ const SShaderCacheProgramFlags &inFlags,
+ NVConstDataRef<SShaderPreprocessorFeature> inFeatures, bool separableProgram) override
+ {
+ NVRenderShaderProgram *theProgram = GetProgram(inKey, inFeatures);
+ if (theProgram)
+ return theProgram;
+
+ NVRenderShaderProgram *retval =
+ ForceCompileProgram(inKey, inVert, inFrag, inTessCtrl, inTessEval, inGeom, inFlags,
+ inFeatures, separableProgram);
+ if (m_CacheFilePath.c_str() && m_ShaderCache && m_ShaderCompilationEnabled) {
+ CFileSeekableIOStream theStream(m_CacheFilePath.c_str(), FileWriteFlags());
+ if (theStream.IsOpen()) {
+ NVScopedRefCounted<IStringTable> theStringTable(
+ IStringTable::CreateStringTable(m_RenderContext.GetAllocator()));
+ CDOMSerializer::WriteXMLHeader(theStream);
+ CDOMSerializer::Write(m_RenderContext.GetAllocator(),
+ *m_ShaderCache->GetTopElement(), theStream, *theStringTable);
+ }
+ }
+ return retval;
+ }
+
+ void BootupDOMWriter()
+ {
+ NVScopedRefCounted<IStringTable> theStringTable(
+ IStringTable::CreateStringTable(m_RenderContext.GetAllocator()));
+ m_ShaderCache = IDOMWriter::CreateDOMWriter(m_RenderContext.GetAllocator(),
+ "UICShaderCache", theStringTable)
+ .first;
+ m_ShaderCache->Att("cache_version", IShaderCache::GetShaderVersion());
+ }
+
+ void SetShaderCachePersistenceEnabled(const char8_t *inDirectory) override
+ {
+ if (inDirectory == NULL) {
+ m_ShaderCache = NULL;
+ return;
+ }
+ BootupDOMWriter();
+ m_CacheFilePath = QDir(inDirectory).filePath(GetShaderCacheFileName()).toStdString();
+
+ NVScopedRefCounted<IRefCountedInputStream> theInStream =
+ m_InputStreamFactory.GetStreamForFile(m_CacheFilePath.c_str());
+ if (theInStream) {
+ SStackPerfTimer __perfTimer(m_PerfTimer, "ShaderCache - Load");
+ NVScopedRefCounted<IStringTable> theStringTable(
+ IStringTable::CreateStringTable(m_RenderContext.GetAllocator()));
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_RenderContext.GetAllocator(), theStringTable));
+ eastl::vector<SShaderPreprocessorFeature> theFeatures;
+
+ SDOMElement *theElem = CDOMSerializer::Read(*theFactory, *theInStream).second;
+ if (theElem) {
+ NVScopedRefCounted<IDOMReader> theReader = IDOMReader::CreateDOMReader(
+ m_RenderContext.GetAllocator(), *theElem, theStringTable, theFactory);
+ QT3DSU32 theAttValue = 0;
+ theReader->Att("cache_version", theAttValue);
+ if (theAttValue == IShaderCache::GetShaderVersion()) {
+ CRenderString loadVertexData;
+ CRenderString loadFragmentData;
+ CRenderString loadTessControlData;
+ CRenderString loadTessEvalData;
+ CRenderString loadGeometryData;
+ CRenderString shaderTypeString;
+ IStringTable &theStringTable(m_RenderContext.GetStringTable());
+ for (bool success = theReader->MoveToFirstChild(); success;
+ success = theReader->MoveToNextSibling()) {
+ const char8_t *theKeyStr = NULL;
+ theReader->UnregisteredAtt("key", theKeyStr);
+
+ CRegisteredString theKey = theStringTable.RegisterStr(theKeyStr);
+ if (theKey.IsValid()) {
+ m_FlagString.clear();
+ const char8_t *theFlagStr = "";
+ SShaderCacheProgramFlags theFlags;
+ if (theReader->UnregisteredAtt("glflags", theFlagStr)) {
+ m_FlagString.assign(theFlagStr);
+ theFlags = CacheFlagsToStr(m_FlagString);
+ }
+
+ m_ContextTypeString.clear();
+ if (theReader->UnregisteredAtt("gl-context-type", theFlagStr))
+ m_ContextTypeString.assign(theFlagStr);
+
+ theFeatures.clear();
+ {
+ IDOMReader::Scope __featureScope(*theReader);
+ if (theReader->MoveToFirstChild("Features")) {
+ for (SDOMAttribute *theAttribute =
+ theReader->GetFirstAttribute();
+ theAttribute;
+ theAttribute = theAttribute->m_NextAttribute) {
+ bool featureValue = false;
+ StringConversion<bool>().StrTo(theAttribute->m_Value,
+ featureValue);
+ theFeatures.push_back(SShaderPreprocessorFeature(
+ theStringTable.RegisterStr(
+ theAttribute->m_Name.c_str()),
+ featureValue));
+ }
+ }
+ }
+
+ qt3ds::render::NVRenderContextType theContextType =
+ StringToContextType(m_ContextTypeString);
+ if (((QT3DSU32)theContextType != 0)
+ && (theContextType & m_RenderContext.GetRenderContextType())
+ == theContextType) {
+ IDOMReader::Scope __readerScope(*theReader);
+ loadVertexData.clear();
+ loadFragmentData.clear();
+ loadTessControlData.clear();
+ loadTessEvalData.clear();
+ loadGeometryData.clear();
+
+ // Vertex *MUST* be the first
+ // Todo deal with pure compute shader programs
+ if (theReader->MoveToFirstChild("VertexCode")) {
+ const char8_t *theValue = NULL;
+ theReader->Value(theValue);
+ loadVertexData.assign(theValue);
+ while (theReader->MoveToNextSibling()) {
+ theReader->Value(theValue);
+
+ shaderTypeString.assign(
+ theReader->GetElementName().c_str());
+ ShaderType::Enum shaderType =
+ StringToShaderType(shaderTypeString);
+
+ if (shaderType == ShaderType::Fragment)
+ loadFragmentData.assign(theValue);
+ else if (shaderType == ShaderType::TessControl)
+ loadTessControlData.assign(theValue);
+ else if (shaderType == ShaderType::TessEval)
+ loadTessEvalData.assign(theValue);
+ else if (shaderType == ShaderType::Geometry)
+ loadGeometryData.assign(theValue);
+ }
+ }
+
+ if (loadVertexData.size()
+ && (loadFragmentData.size() || loadGeometryData.size())) {
+
+ NVRenderShaderProgram *theShader = ForceCompileProgram(
+ theKey, loadVertexData.c_str(), loadFragmentData.c_str(),
+ loadTessControlData.c_str(), loadTessEvalData.c_str(),
+ loadGeometryData.c_str(), theFlags,
+ qt3ds::foundation::toDataRef(theFeatures.data(),
+ (QT3DSU32)theFeatures.size()),
+ false);
+ // If something doesn't save or load correctly, get the runtime
+ // to re-generate.
+ if (!theShader)
+ m_Shaders.erase(theKey);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ bool IsShaderCachePersistenceEnabled() const override { return m_ShaderCache != NULL; }
+
+ void SetShaderCompilationEnabled(bool inEnableShaderCompilation) override
+ {
+ m_ShaderCompilationEnabled = inEnableShaderCompilation;
+ }
+};
+}
+
+size_t uic::render::HashShaderFeatureSet(NVConstDataRef<SShaderPreprocessorFeature> inFeatureSet)
+{
+ size_t retval(0);
+ for (QT3DSU32 idx = 0, end = inFeatureSet.size(); idx < end; ++idx) {
+ // From previous implementation, it seems we need to ignore the order of the features.
+ // But we need to bind the feature flag together with its name, so that the flags will
+ // influence
+ // the final hash not only by the true-value count.
+ retval = retval
+ ^ (inFeatureSet[idx].m_Name.hash() * eastl::hash<bool>()(inFeatureSet[idx].m_Enabled));
+ }
+ return retval;
+}
+
+bool SShaderPreprocessorFeature::operator<(const SShaderPreprocessorFeature &other) const
+{
+ return strcmp(m_Name.c_str(), other.m_Name.c_str()) < 0;
+}
+
+bool SShaderPreprocessorFeature::operator==(const SShaderPreprocessorFeature &other) const
+{
+ return m_Name == other.m_Name && m_Enabled == other.m_Enabled;
+}
+
+IShaderCache &IShaderCache::CreateShaderCache(NVRenderContext &inContext,
+ IInputStreamFactory &inInputStreamFactory,
+ IPerfTimer &inPerfTimer)
+{
+ return *QT3DS_NEW(inContext.GetAllocator(), ShaderCache)(inContext, inInputStreamFactory,
+ inPerfTimer);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGenerator.cpp b/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGenerator.cpp
new file mode 100644
index 00000000..db9e94d7
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGenerator.cpp
@@ -0,0 +1,526 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderShaderCodeGenerator.h"
+
+using namespace uic::render;
+
+using eastl::make_pair;
+
+SShaderCodeGeneratorBase::SShaderCodeGeneratorBase(IStringTable &inStringTable,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType)
+ : m_StringTable(inStringTable)
+ , m_Codes(alloc, "SShaderCodeGenerator::m_Codes")
+ , m_Includes(alloc, "SShaderCodeGenerator::m_Includes")
+ , m_Uniforms(alloc, "SShaderCodeGenerator::m_Uniforms")
+ , m_ConstantBuffers(alloc, "SShaderCodeGenerator::m_ConstantBuffers")
+ , m_ConstantBufferParams(alloc, "SShaderCodeGenerator::m_ConstantBufferParams")
+ , m_Attributes(alloc, "SShaderCodeGenerator::m_Uniforms")
+ , m_RenderContextType(ctxType)
+{
+}
+void SShaderCodeGeneratorBase::Begin()
+{
+ m_Uniforms.clear();
+ GetVaryings().clear();
+ m_Attributes.clear();
+ m_Includes.clear();
+ m_Codes.clear();
+ m_FinalShaderBuilder.clear();
+ m_CodeBuilder.clear();
+ m_ConstantBuffers.clear();
+ m_ConstantBufferParams.clear();
+}
+void SShaderCodeGeneratorBase::Append(const char *data)
+{
+ m_CodeBuilder.append(data);
+ m_CodeBuilder.append("\n");
+}
+// don't add the newline
+void SShaderCodeGeneratorBase::AppendPartial(const char *data)
+{
+ m_CodeBuilder.append(data);
+}
+void SShaderCodeGeneratorBase::AddUniform(const char *name, const char *type)
+{
+ m_Uniforms.insert(make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(type)));
+}
+void SShaderCodeGeneratorBase::AddUniform(TStrType &name, const char *type)
+{
+ AddUniform(name.c_str(), type);
+}
+
+void SShaderCodeGeneratorBase::AddConstantBuffer(const char *name, const char *layout)
+{
+ m_ConstantBuffers.insert(
+ make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(layout)));
+}
+void SShaderCodeGeneratorBase::AddConstantBufferParam(const char *cbName, const char *paramName,
+ const char *type)
+{
+ TParamPair theParamPair(m_StringTable.RegisterStr(paramName), m_StringTable.RegisterStr(type));
+ TConstantBufferParamPair theBufferParamPair(m_StringTable.RegisterStr(cbName), theParamPair);
+ m_ConstantBufferParams.push_back(theBufferParamPair);
+}
+void SShaderCodeGeneratorBase::AddAttribute(const char *name, const char *type)
+{
+ m_Attributes.insert(
+ make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(type)));
+}
+void SShaderCodeGeneratorBase::AddAttribute(TStrType &name, const char *type)
+{
+ AddAttribute(name.c_str(), type);
+}
+void SShaderCodeGeneratorBase::AddVarying(const char *name, const char *type)
+{
+ GetVaryings().insert(
+ make_pair(m_StringTable.RegisterStr(name), m_StringTable.RegisterStr(type)));
+}
+void SShaderCodeGeneratorBase::AddVarying(TStrType &name, const char *type)
+{
+ AddVarying(name.c_str(), type);
+}
+void SShaderCodeGeneratorBase::AddLocalVariable(const char *name, const char *type, int tabCount)
+{
+ for (; tabCount >= 0; --tabCount)
+ m_CodeBuilder.append("\t");
+ m_CodeBuilder.append(type);
+ m_CodeBuilder.append(" ");
+ m_CodeBuilder.append(name);
+ m_CodeBuilder.append(";\n");
+}
+
+void SShaderCodeGeneratorBase::AddInclude(const char *name)
+{
+ m_Includes.insert(m_StringTable.RegisterStr(name));
+}
+void SShaderCodeGeneratorBase::AddInclude(TStrType &name)
+{
+ AddInclude(name.c_str());
+}
+void SShaderCodeGeneratorBase::AddLocalVariable(TStrType &name, const char *type, int tabCount)
+{
+ AddLocalVariable(name.c_str(), type, tabCount);
+}
+bool SShaderCodeGeneratorBase::HasCode(Enum value)
+{
+ return m_Codes.contains(value);
+}
+void SShaderCodeGeneratorBase::SetCode(Enum value)
+{
+ m_Codes.insert((QT3DSU32)value);
+}
+
+void SShaderCodeGeneratorBase::SetupWorldPosition()
+{
+ if (!HasCode(WorldPosition)) {
+ SetCode(WorldPosition);
+ AddUniform("model_matrix", "mat4");
+ Append("\tvec3 varWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;");
+ }
+}
+
+void SShaderCodeGeneratorBase::GenerateViewVector()
+{
+ if (!HasCode(ViewVector)) {
+ SetCode(ViewVector);
+ SetupWorldPosition();
+ AddInclude("viewProperties.glsllib");
+ Append("\tvec3 view_vector = normalize(camera_position - varWorldPos);");
+ }
+}
+
+void SShaderCodeGeneratorBase::GenerateWorldNormal()
+{
+ if (!HasCode(WorldNormal)) {
+ SetCode(WorldNormal);
+ AddAttribute("attr_norm", "vec3");
+ AddUniform("normal_matrix", "mat3");
+ Append("\tvec3 world_normal = normalize(normal_matrix * objectNormal).xyz;");
+ }
+}
+
+void SShaderCodeGeneratorBase::GenerateEnvMapReflection(SShaderCodeGeneratorBase &inFragmentShader)
+{
+ if (!HasCode(EnvMapReflection)) {
+ SetCode(EnvMapReflection);
+ SetupWorldPosition();
+ GenerateWorldNormal();
+ AddInclude("viewProperties.glsllib");
+ AddVarying("var_object_to_camera", "vec3");
+ Append("\tvar_object_to_camera = normalize( varWorldPos - camera_position );");
+ // World normal cannot be relied upon in the vertex shader because of bump maps.
+ inFragmentShader.Append("\tvec3 environment_map_reflection = reflect( "
+ "vec3(var_object_to_camera.x, var_object_to_camera.y, "
+ "var_object_to_camera.z), world_normal.xyz );");
+ inFragmentShader.Append("\tenvironment_map_reflection *= vec3( 0.5, 0.5, 0 );");
+ inFragmentShader.Append("\tenvironment_map_reflection += vec3( 0.5, 0.5, 1.0 );");
+ }
+}
+
+void SShaderCodeGeneratorBase::GenerateUVCoords()
+{
+ if (!HasCode(UVCoords)) {
+ SetCode(UVCoords);
+ AddAttribute("attr_uv0", "vec2");
+ Append("\tvec2 uv_coords = attr_uv0;");
+ }
+}
+
+void SShaderCodeGeneratorBase::GenerateTextureSwizzle(NVRenderTextureSwizzleMode::Enum swizzleMode,
+ eastl::basic_string<char8_t> &texSwizzle,
+ eastl::basic_string<char8_t> &lookupSwizzle)
+{
+ qt3ds::render::NVRenderContextType deprecatedContextFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+
+ if (!(m_RenderContextType & deprecatedContextFlags)) {
+ switch (swizzleMode) {
+ case NVRenderTextureSwizzleMode::L8toR8:
+ case NVRenderTextureSwizzleMode::L16toR16:
+ texSwizzle.append(".rgb");
+ lookupSwizzle.append(".rrr");
+ break;
+ case NVRenderTextureSwizzleMode::L8A8toRG8:
+ texSwizzle.append(".rgba");
+ lookupSwizzle.append(".rrrg");
+ break;
+ case NVRenderTextureSwizzleMode::A8toR8:
+ texSwizzle.append(".a");
+ lookupSwizzle.append(".r");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void SShaderCodeGeneratorBase::GenerateShadedWireframeBase()
+{
+ // how this all work see
+ // http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf
+ Append("// project points to screen space\n"
+ "\tvec3 p0 = vec3(viewport_matrix * (gl_in[0].gl_Position / gl_in[0].gl_Position.w));\n"
+ "\tvec3 p1 = vec3(viewport_matrix * (gl_in[1].gl_Position / gl_in[1].gl_Position.w));\n"
+ "\tvec3 p2 = vec3(viewport_matrix * (gl_in[2].gl_Position / gl_in[2].gl_Position.w));\n"
+ "// compute triangle heights\n"
+ "\tfloat e1 = length(p1 - p2);\n"
+ "\tfloat e2 = length(p2 - p0);\n"
+ "\tfloat e3 = length(p1 - p0);\n"
+ "\tfloat alpha = acos( (e2*e2 + e3*e3 - e1*e1) / (2.0*e2*e3) );\n"
+ "\tfloat beta = acos( (e1*e1 + e3*e3 - e2*e2) / (2.0*e1*e3) );\n"
+ "\tfloat ha = abs( e3 * sin( beta ) );\n"
+ "\tfloat hb = abs( e3 * sin( alpha ) );\n"
+ "\tfloat hc = abs( e2 * sin( alpha ) );\n");
+}
+
+void SShaderCodeGeneratorBase::AddShaderItemMap(const char *itemType,
+ const TStrTableStrMap &itemMap)
+{
+ m_FinalShaderBuilder.append("\n");
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end;
+ ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(";\n");
+ }
+}
+
+void SShaderCodeGeneratorBase::AddShaderConstantBufferItemMap(
+ const char *itemType, const TStrTableStrMap &cbMap, TConstantBufferParamArray cbParamsArray)
+{
+ m_FinalShaderBuilder.append("\n");
+
+ // iterate over all constant buffers
+ for (TStrTableStrMap::const_iterator iter = cbMap.begin(), end = cbMap.end(); iter != end;
+ ++iter) {
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(" {\n");
+ // iterate over all param entries and add match
+ for (TConstantBufferParamArray::const_iterator iter1 = cbParamsArray.begin(),
+ end = cbParamsArray.end();
+ iter1 != end; ++iter1) {
+ if (iter1->first == iter->first) {
+ m_FinalShaderBuilder.append(iter1->second.second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter1->second.first);
+ m_FinalShaderBuilder.append(";\n");
+ }
+ }
+
+ m_FinalShaderBuilder.append("};\n");
+ }
+}
+
+const char *SShaderCodeGeneratorBase::BuildShaderSource()
+{
+ for (nvhash_set<CRegisteredString>::const_iterator iter = m_Includes.begin(),
+ end = m_Includes.end();
+ iter != end; ++iter) {
+ m_FinalShaderBuilder.append("#include \"");
+ m_FinalShaderBuilder.append(iter->c_str());
+ m_FinalShaderBuilder.append("\"\n");
+ }
+ AddShaderItemMap("attribute", m_Attributes);
+ AddShaderItemMap("uniform", m_Uniforms);
+ AddShaderConstantBufferItemMap("uniform", m_ConstantBuffers, m_ConstantBufferParams);
+ AddShaderItemMap("varying", GetVaryings());
+ m_FinalShaderBuilder.append("\n");
+ m_FinalShaderBuilder.append(m_CodeBuilder);
+ return m_FinalShaderBuilder.c_str();
+}
+SShaderCodeGeneratorBase &SShaderCodeGeneratorBase::operator<<(const char *data)
+{
+ m_CodeBuilder.append(data);
+ return *this;
+}
+SShaderCodeGeneratorBase &SShaderCodeGeneratorBase::operator<<(const TStrType &data)
+{
+ m_CodeBuilder.append(data);
+ return *this;
+}
+
+SShaderCodeGeneratorBase &SShaderCodeGeneratorBase::operator<<(const SEndlType & /*data*/)
+{
+ m_CodeBuilder.append("\n");
+ return *this;
+}
+
+SShaderVertexCodeGenerator::SShaderVertexCodeGenerator(IStringTable &inStringTable,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType)
+ : SShaderCodeGeneratorBase(inStringTable, alloc, ctxType)
+ , m_Varyings(alloc, "SShaderVertexCodeGenerator::m_Varyings")
+{
+}
+TStrTableStrMap &SShaderVertexCodeGenerator::GetVaryings()
+{
+ return m_Varyings;
+}
+
+SShaderTessControlCodeGenerator::SShaderTessControlCodeGenerator(
+ SShaderVertexCodeGenerator &vert, NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType)
+ : SShaderCodeGeneratorBase(vert.m_StringTable, alloc, ctxType)
+ , m_VertGenerator(vert)
+ , m_Varyings(alloc, "SShaderTessControlCodeGenerator::m_Varyings")
+{
+}
+
+// overwritten from base
+void SShaderTessControlCodeGenerator::AddShaderItemMap(const char *itemType,
+ const TStrTableStrMap &itemMap)
+{
+ eastl::string extVtx("");
+ eastl::string extTC("");
+ eastl::string type(itemType);
+ if (!type.compare("varying")) {
+ extVtx = "[]";
+ extTC = "TC[]";
+ itemType = "attribute";
+ }
+
+ m_FinalShaderBuilder.append("\n");
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end;
+ ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(extVtx.c_str());
+ m_FinalShaderBuilder.append(";\n");
+ }
+
+ // if this is varyings write output of tess control shader
+ if (!extVtx.empty()) {
+ m_FinalShaderBuilder.append("\n");
+ itemType = "varying";
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end();
+ iter != end; ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(extTC.c_str());
+ m_FinalShaderBuilder.append(";\n");
+ }
+ }
+}
+TStrTableStrMap &SShaderTessControlCodeGenerator::GetVaryings()
+{
+ return m_VertGenerator.m_Varyings;
+}
+
+SShaderTessEvalCodeGenerator::SShaderTessEvalCodeGenerator(SShaderTessControlCodeGenerator &tc,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType)
+ : SShaderCodeGeneratorBase(tc.m_StringTable, alloc, ctxType)
+ , m_TessControlGenerator(tc)
+ , m_hasGeometryStage(false)
+{
+}
+// overwritten from base
+void SShaderTessEvalCodeGenerator::AddShaderItemMap(const char *itemType,
+ const TStrTableStrMap &itemMap)
+{
+ eastl::string extTC("");
+ eastl::string extTE("");
+ eastl::string type(itemType);
+ if (!type.compare("varying")) {
+ extTC = "TC[]";
+ itemType = "attribute";
+ }
+ if (m_hasGeometryStage) {
+ extTE = "TE";
+ }
+
+ m_FinalShaderBuilder.append("\n");
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end;
+ ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(extTC.c_str());
+ m_FinalShaderBuilder.append(";\n");
+ }
+
+ // if this are varyings write output of tess eval shader
+ if (!extTC.empty()) {
+ m_FinalShaderBuilder.append("\n");
+ itemType = "varying";
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end();
+ iter != end; ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(extTE.c_str());
+ m_FinalShaderBuilder.append(";\n");
+ }
+ }
+}
+TStrTableStrMap &SShaderTessEvalCodeGenerator::GetVaryings()
+{
+ return m_TessControlGenerator.m_VertGenerator.GetVaryings();
+}
+void SShaderTessEvalCodeGenerator::SetGeometryStage(bool hasGeometryStage)
+{
+ m_hasGeometryStage = hasGeometryStage;
+}
+
+SShaderGeometryCodeGenerator::SShaderGeometryCodeGenerator(SShaderVertexCodeGenerator &vert,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType)
+ : SShaderCodeGeneratorBase(vert.m_StringTable, alloc, ctxType)
+ , m_VertGenerator(vert)
+ , m_hasTessellationStage(true)
+{
+}
+
+// overwritten from base
+void SShaderGeometryCodeGenerator::AddShaderItemMap(const char *itemType,
+ const TStrTableStrMap &itemMap)
+{
+ eastl::string inExt("");
+ eastl::string type(itemType);
+ if (!type.compare("varying")) {
+ itemType = "attribute";
+ if (m_hasTessellationStage)
+ inExt = "TE[]";
+ else
+ inExt = "[]";
+ }
+
+ m_FinalShaderBuilder.append("\n");
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end(); iter != end;
+ ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(inExt.c_str());
+ m_FinalShaderBuilder.append(";\n");
+ }
+
+ // if this are varyings write output of geometry shader
+ if (!type.compare("varying")) {
+ m_FinalShaderBuilder.append("\n");
+ itemType = "varying";
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end();
+ iter != end; ++iter) {
+ m_FinalShaderBuilder.append(itemType);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->second);
+ m_FinalShaderBuilder.append(" ");
+ m_FinalShaderBuilder.append(iter->first);
+ m_FinalShaderBuilder.append(";\n");
+ }
+ }
+}
+TStrTableStrMap &SShaderGeometryCodeGenerator::GetVaryings()
+{
+ return m_VertGenerator.m_Varyings;
+}
+void SShaderGeometryCodeGenerator::SetTessellationStage(bool hasTessellationStage)
+{
+ m_hasTessellationStage = hasTessellationStage;
+}
+
+SShaderFragmentCodeGenerator::SShaderFragmentCodeGenerator(SShaderVertexCodeGenerator &vert,
+ NVAllocatorCallback &alloc,
+ qt3ds::render::NVRenderContextType ctxType)
+ : SShaderCodeGeneratorBase(vert.m_StringTable, alloc, ctxType)
+ , m_VertGenerator(vert)
+{
+}
+TStrTableStrMap &SShaderFragmentCodeGenerator::GetVaryings()
+{
+ return m_VertGenerator.m_Varyings;
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp b/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp
new file mode 100644
index 00000000..6d72d322
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderShaderCodeGeneratorV2.cpp
@@ -0,0 +1,627 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Utils.h"
+#include "UICRenderContext.h"
+#include "UICRenderDynamicObjectSystem.h"
+
+using namespace uic::render;
+
+namespace {
+struct SStageGeneratorBase : public IShaderStageGenerator
+{
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ TStrTableStrMap m_Incoming;
+ TStrTableStrMap *m_Outgoing;
+ nvhash_set<CRegisteredString> m_Includes;
+ TStrTableStrMap m_Uniforms;
+ TStrTableStrMap m_ConstantBuffers;
+ TConstantBufferParamArray m_ConstantBufferParams;
+ CRenderString m_CodeBuilder;
+ CRenderString m_FinalBuilder;
+ ShaderGeneratorStages::Enum m_Stage;
+ TShaderGeneratorStageFlags m_EnabledStages;
+ QStringList m_addedFunctions;
+
+ SStageGeneratorBase(NVFoundationBase &inFnd, IStringTable &strTable,
+ ShaderGeneratorStages::Enum inStage)
+
+ : m_Foundation(inFnd)
+ , m_StringTable(strTable)
+ , m_Incoming(inFnd.getAllocator(), "m_Incoming")
+ , m_Outgoing(NULL)
+ , m_Includes(inFnd.getAllocator(), "m_Includes")
+ , m_Uniforms(inFnd.getAllocator(), "m_Uniforms")
+ , m_ConstantBuffers(inFnd.getAllocator(), "m_ConstantBuffers")
+ , m_ConstantBufferParams(inFnd.getAllocator(), "m_ConstantBufferParams")
+ , m_Stage(inStage)
+ {
+ }
+
+ virtual void Begin(TShaderGeneratorStageFlags inEnabledStages)
+ {
+ m_Incoming.clear();
+ m_Outgoing = NULL;
+ m_Includes.clear();
+ m_Uniforms.clear();
+ m_ConstantBuffers.clear();
+ m_ConstantBufferParams.clear();
+ m_CodeBuilder.clear();
+ m_FinalBuilder.clear();
+ m_EnabledStages = inEnabledStages;
+ m_addedFunctions.clear();
+ // the shared buffers will be cleared elsewhere.
+ }
+
+ CRegisteredString Str(const char8_t *var) { return m_StringTable.RegisterStr(var); }
+
+ void AddIncoming(const char8_t *name, const char8_t *type) override
+ {
+ m_Incoming.insert(eastl::make_pair(Str(name), Str(type)));
+ }
+
+ virtual const char8_t *GetIncomingVariableName() { return "in"; }
+
+ void AddIncoming(const TStrType &name, const char8_t *type) override
+ {
+ AddIncoming(name.c_str(), type);
+ }
+ void AddOutgoing(const char8_t *name, const char8_t *type) override
+ {
+ if (m_Outgoing == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_Outgoing->insert(eastl::make_pair(Str(name), Str(type)));
+ }
+ void AddOutgoing(const TStrType &name, const char8_t *type) override
+ {
+ AddOutgoing(name.c_str(), type);
+ }
+
+ void AddUniform(const char8_t *name, const char8_t *type) override
+ {
+ m_Uniforms.insert(eastl::make_pair(Str(name), Str(type)));
+ }
+ void AddUniform(const TStrType &name, const char8_t *type) override
+ {
+ AddUniform(name.c_str(), type);
+ }
+
+ void AddConstantBuffer(const char *name, const char *layout) override
+ {
+ m_ConstantBuffers.insert(eastl::make_pair(Str(name), Str(layout)));
+ }
+ void AddConstantBufferParam(const char *cbName, const char *paramName, const char *type) override
+ {
+ TParamPair theParamPair(m_StringTable.RegisterStr(paramName),
+ m_StringTable.RegisterStr(type));
+ TConstantBufferParamPair theBufferParamPair(m_StringTable.RegisterStr(cbName),
+ theParamPair);
+ m_ConstantBufferParams.push_back(theBufferParamPair);
+ }
+
+ IShaderStageGenerator &operator<<(const char *data) override
+ {
+ m_CodeBuilder.append(nonNull(data));
+ return *this;
+ }
+ IShaderStageGenerator &operator<<(const TStrType &data) override
+ {
+ m_CodeBuilder.append(data);
+ return *this;
+ }
+ IShaderStageGenerator &operator<<(const SEndlType & /*data*/) override
+ {
+ m_CodeBuilder.append("\n");
+ return *this;
+ }
+ void Append(const char *data) override
+ {
+ m_CodeBuilder.append(nonNull(data));
+ m_CodeBuilder.append("\n");
+ }
+ void AppendPartial(const char *data) override { m_CodeBuilder.append(nonNull(data)); }
+ ShaderGeneratorStages::Enum Stage() const override { return m_Stage; }
+
+ virtual void AddShaderItemMap(const char *itemType, const TStrTableStrMap &itemMap,
+ const char8_t *inItemSuffix = "")
+ {
+ m_FinalBuilder.append("\n");
+
+ for (TStrTableStrMap::const_iterator iter = itemMap.begin(), end = itemMap.end();
+ iter != end; ++iter) {
+ m_FinalBuilder.append(itemType);
+ m_FinalBuilder.append(" ");
+ m_FinalBuilder.append(iter->second);
+ m_FinalBuilder.append(" ");
+ m_FinalBuilder.append(iter->first);
+ m_FinalBuilder.append(inItemSuffix);
+ m_FinalBuilder.append(";\n");
+ }
+ }
+
+ virtual void AddShaderIncomingMap() { AddShaderItemMap(GetIncomingVariableName(), m_Incoming); }
+
+ virtual void AddShaderUniformMap() { AddShaderItemMap("uniform", m_Uniforms); }
+
+ virtual void AddShaderOutgoingMap()
+ {
+ if (m_Outgoing)
+ AddShaderItemMap("varying", *m_Outgoing);
+ }
+
+ virtual void AddShaderConstantBufferItemMap(const char *itemType, const TStrTableStrMap &cbMap,
+ TConstantBufferParamArray cbParamsArray)
+ {
+ m_FinalBuilder.append("\n");
+
+ // iterate over all constant buffers
+ for (TStrTableStrMap::const_iterator iter = cbMap.begin(), end = cbMap.end(); iter != end;
+ ++iter) {
+ m_FinalBuilder.append(iter->second);
+ m_FinalBuilder.append(" ");
+ m_FinalBuilder.append(itemType);
+ m_FinalBuilder.append(" ");
+ m_FinalBuilder.append(iter->first);
+ m_FinalBuilder.append(" {\n");
+ // iterate over all param entries and add match
+ for (TConstantBufferParamArray::const_iterator iter1 = cbParamsArray.begin(),
+ end = cbParamsArray.end();
+ iter1 != end; ++iter1) {
+ if (iter1->first == iter->first) {
+ m_FinalBuilder.append(iter1->second.second);
+ m_FinalBuilder.append(" ");
+ m_FinalBuilder.append(iter1->second.first);
+ m_FinalBuilder.append(";\n");
+ }
+ }
+
+ m_FinalBuilder.append("};\n");
+ }
+ }
+
+ virtual void AppendShaderCode() { m_FinalBuilder.append(m_CodeBuilder); }
+
+ virtual void UpdateShaderCacheFlags(SShaderCacheProgramFlags &) {}
+
+ void AddInclude(const char8_t *name) override { m_Includes.insert(Str(name)); }
+
+ void AddInclude(const TStrType &name) override { AddInclude(name.c_str()); }
+
+ void AddInclude(const QString &name) override
+ {
+ QByteArray arr = name.toLatin1();
+ AddInclude(arr.data());
+ }
+
+ virtual const char8_t *BuildShaderSource()
+ {
+ for (nvhash_set<CRegisteredString>::const_iterator iter = m_Includes.begin(),
+ end = m_Includes.end();
+ iter != end; ++iter) {
+ m_FinalBuilder.append("#include \"");
+ m_FinalBuilder.append(iter->c_str());
+ m_FinalBuilder.append("\"\n");
+ }
+ AddShaderIncomingMap();
+ AddShaderUniformMap();
+ AddShaderConstantBufferItemMap("uniform", m_ConstantBuffers, m_ConstantBufferParams);
+ AddShaderOutgoingMap();
+ m_FinalBuilder.append("\n");
+ AppendShaderCode();
+ return m_FinalBuilder.c_str();
+ }
+
+ void AddFunction(const QString &functionName) override
+ {
+ if (!m_addedFunctions.contains(functionName)) {
+ m_addedFunctions.push_back(functionName);
+ QString includeName;
+ QTextStream stream(&includeName);
+ stream << "func" << functionName << ".glsllib";
+ AddInclude(includeName);
+ }
+ }
+};
+
+struct SVertexShaderGenerator : public SStageGeneratorBase
+{
+ SVertexShaderGenerator(NVFoundationBase &inFnd, IStringTable &strTable)
+ : SStageGeneratorBase(inFnd, strTable, ShaderGeneratorStages::Vertex)
+ {
+ }
+
+ const char8_t *GetIncomingVariableName() override { return "attribute"; }
+ virtual void AddIncomingInterpolatedMap() {}
+
+ virtual const char8_t *GetInterpolatedIncomingSuffix() const { return "_attr"; }
+ virtual const char8_t *GetInterpolatedOutgoingSuffix() const { return ""; }
+};
+
+struct STessControlShaderGenerator : public SStageGeneratorBase
+{
+ STessControlShaderGenerator(NVFoundationBase &inFnd, IStringTable &strTable)
+ : SStageGeneratorBase(inFnd, strTable, ShaderGeneratorStages::TessControl)
+ {
+ }
+
+ void AddShaderIncomingMap() override { AddShaderItemMap("attribute", m_Incoming, "[]"); }
+
+ void AddShaderOutgoingMap() override
+ {
+ if (m_Outgoing)
+ AddShaderItemMap("varying", *m_Outgoing, "[]");
+ }
+
+ void UpdateShaderCacheFlags(SShaderCacheProgramFlags &inFlags) override
+ {
+ inFlags.SetTessellationEnabled(true);
+ }
+};
+
+struct STessEvalShaderGenerator : public SStageGeneratorBase
+{
+ STessEvalShaderGenerator(NVFoundationBase &inFnd, IStringTable &strTable)
+ : SStageGeneratorBase(inFnd, strTable, ShaderGeneratorStages::TessEval)
+ {
+ }
+
+ void AddShaderIncomingMap() override { AddShaderItemMap("attribute", m_Incoming, "[]"); }
+
+ void UpdateShaderCacheFlags(SShaderCacheProgramFlags &inFlags) override
+ {
+ inFlags.SetTessellationEnabled(true);
+ }
+};
+
+struct SGeometryShaderGenerator : public SStageGeneratorBase
+{
+ SGeometryShaderGenerator(NVFoundationBase &inFnd, IStringTable &strTable)
+ : SStageGeneratorBase(inFnd, strTable, ShaderGeneratorStages::Geometry)
+ {
+ }
+
+ void AddShaderIncomingMap() override { AddShaderItemMap("attribute", m_Incoming, "[]"); }
+
+ void AddShaderOutgoingMap() override
+ {
+ if (m_Outgoing)
+ AddShaderItemMap("varying", *m_Outgoing);
+ }
+ void UpdateShaderCacheFlags(SShaderCacheProgramFlags &inFlags) override
+ {
+ inFlags.SetGeometryShaderEnabled(true);
+ }
+};
+
+struct SFragmentShaderGenerator : public SStageGeneratorBase
+{
+ SFragmentShaderGenerator(NVFoundationBase &inFnd, IStringTable &strTable)
+ : SStageGeneratorBase(inFnd, strTable, ShaderGeneratorStages::Fragment)
+ {
+ }
+ void AddShaderOutgoingMap() override {}
+};
+
+struct SShaderGeneratedProgramOutput
+{
+ // never null; so safe to call strlen on.
+ const char8_t *m_VertexShader;
+ const char8_t *m_TessControlShader;
+ const char8_t *m_TessEvalShader;
+ const char8_t *m_GeometryShader;
+ const char8_t *m_FragmentShader;
+
+ SShaderGeneratedProgramOutput()
+ : m_VertexShader("")
+ , m_TessControlShader("")
+ , m_TessEvalShader("")
+ , m_GeometryShader("")
+ , m_FragmentShader("")
+ {
+ }
+
+ SShaderGeneratedProgramOutput(const char8_t *vs, const char8_t *tc, const char8_t *te,
+ const char8_t *gs, const char8_t *fs)
+ : m_VertexShader(vs)
+ , m_TessControlShader(tc)
+ , m_TessEvalShader(te)
+ , m_GeometryShader(gs)
+ , m_FragmentShader(fs)
+ {
+ }
+};
+
+struct SProgramGenerator : public IShaderProgramGenerator
+{
+ IUICRenderContext &m_UICContext;
+ SVertexShaderGenerator m_VS;
+ STessControlShaderGenerator m_TC;
+ STessEvalShaderGenerator m_TE;
+ SGeometryShaderGenerator m_GS;
+ SFragmentShaderGenerator m_FS;
+
+ TShaderGeneratorStageFlags m_EnabledStages;
+
+ QT3DSI32 m_RefCount;
+
+ SProgramGenerator(IUICRenderContext &inContext)
+ : m_UICContext(inContext)
+ , m_VS(inContext.GetFoundation(), inContext.GetStringTable())
+ , m_TC(inContext.GetFoundation(), inContext.GetStringTable())
+ , m_TE(inContext.GetFoundation(), inContext.GetStringTable())
+ , m_GS(inContext.GetFoundation(), inContext.GetStringTable())
+ , m_FS(inContext.GetFoundation(), inContext.GetStringTable())
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVFoundationBase &theFoundation(m_UICContext.GetFoundation());
+ NVDelete(theFoundation.getAllocator(), this);
+ }
+ }
+
+ void LinkStages()
+ {
+ // Link stages incoming to outgoing variables.
+ SStageGeneratorBase *previous = NULL;
+ QT3DSU32 theStageId = 1;
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)ShaderGeneratorStages::StageCount; idx < end;
+ ++idx, theStageId = theStageId << 1) {
+ SStageGeneratorBase *thisStage = NULL;
+ ShaderGeneratorStages::Enum theStageEnum =
+ static_cast<ShaderGeneratorStages::Enum>(theStageId);
+ if ((m_EnabledStages & theStageEnum)) {
+ thisStage = &InternalGetStage(theStageEnum);
+ if (previous)
+ previous->m_Outgoing = &thisStage->m_Incoming;
+ previous = thisStage;
+ }
+ }
+ }
+
+ void BeginProgram(TShaderGeneratorStageFlags inEnabledStages) override
+ {
+ m_VS.Begin(inEnabledStages);
+ m_TC.Begin(inEnabledStages);
+ m_TE.Begin(inEnabledStages);
+ m_GS.Begin(inEnabledStages);
+ m_FS.Begin(inEnabledStages);
+ m_EnabledStages = inEnabledStages;
+ LinkStages();
+ }
+
+ TShaderGeneratorStageFlags GetEnabledStages() const override { return m_EnabledStages; }
+
+ SStageGeneratorBase &InternalGetStage(ShaderGeneratorStages::Enum inStage)
+ {
+ switch (inStage) {
+ case ShaderGeneratorStages::Vertex:
+ return m_VS;
+ case ShaderGeneratorStages::TessControl:
+ return m_TC;
+ case ShaderGeneratorStages::TessEval:
+ return m_TE;
+ case ShaderGeneratorStages::Geometry:
+ return m_GS;
+ case ShaderGeneratorStages::Fragment:
+ return m_FS;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return m_VS;
+ }
+ // get the stage or NULL if it has not been created.
+ IShaderStageGenerator *GetStage(ShaderGeneratorStages::Enum inStage) override
+ {
+ if (inStage > 0 || inStage < ShaderGeneratorStages::StageCount) {
+ if ((m_EnabledStages & inStage))
+ return &InternalGetStage(inStage);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return NULL;
+ }
+
+ qt3ds::render::NVRenderShaderProgram *
+ CompileGeneratedShader(const char *inShaderName, const SShaderCacheProgramFlags &inFlags,
+ TShaderFeatureSet inFeatureSet, bool separableProgram) override
+ {
+ // No stages enabled
+ if (((QT3DSU32)m_EnabledStages) == 0) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ uic::render::IDynamicObjectSystem &theDynamicSystem(m_UICContext.GetDynamicObjectSystem());
+ SShaderCacheProgramFlags theCacheFlags(inFlags);
+ for (QT3DSU32 stageIdx = 0, stageEnd = ShaderGeneratorStages::StageCount; stageIdx < stageEnd;
+ ++stageIdx) {
+ ShaderGeneratorStages::Enum stageName =
+ static_cast<ShaderGeneratorStages::Enum>(1 << stageIdx);
+ if (m_EnabledStages & stageName) {
+ SStageGeneratorBase &theStage(InternalGetStage(stageName));
+ theStage.BuildShaderSource();
+ theStage.UpdateShaderCacheFlags(theCacheFlags);
+ theDynamicSystem.InsertShaderHeaderInformation(theStage.m_FinalBuilder,
+ inShaderName);
+ }
+ }
+
+ const char *vertexShaderSource = m_VS.m_FinalBuilder.c_str();
+ const char *tcShaderSource = m_TC.m_FinalBuilder.c_str();
+ const char *teShaderSource = m_TE.m_FinalBuilder.c_str();
+ const char *geShaderSource = m_GS.m_FinalBuilder.c_str();
+ const char *fragmentShaderSource = m_FS.m_FinalBuilder.c_str();
+
+ IShaderCache &theCache = m_UICContext.GetShaderCache();
+ CRegisteredString theCacheKey = m_UICContext.GetStringTable().RegisterStr(inShaderName);
+ return theCache.CompileProgram(theCacheKey, vertexShaderSource, fragmentShaderSource,
+ tcShaderSource, teShaderSource, geShaderSource,
+ theCacheFlags, inFeatureSet, separableProgram);
+ }
+};
+};
+
+IShaderProgramGenerator &
+IShaderProgramGenerator::CreateProgramGenerator(IUICRenderContext &inContext)
+{
+ return *QT3DS_NEW(inContext.GetAllocator(), SProgramGenerator)(inContext);
+}
+
+void IShaderProgramGenerator::OutputParaboloidDepthVertex(IShaderStageGenerator &vertexShader)
+{
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddInclude("shadowMapping.glsllib");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+ // vertexShader.AddUniform("model_view", "mat4");
+ vertexShader.AddUniform("camera_properties", "vec2");
+ // vertexShader.AddOutgoing("view_pos", "vec4");
+ vertexShader.AddOutgoing("world_pos", "vec4");
+
+ // Project the location onto screen space.
+ // This will be horrible if you have a single large polygon. Tessellation is your friend here!
+ vertexShader.Append("void main() {");
+ vertexShader.Append(
+ " ParaboloidMapResult data = VertexParaboloidDepth( attr_pos, model_view_projection );");
+ vertexShader.Append(" gl_Position = data.m_Position;");
+ vertexShader.Append(" world_pos = data.m_WorldPos;");
+ vertexShader.Append("}");
+}
+
+void IShaderProgramGenerator::OutputParaboloidDepthTessEval(IShaderStageGenerator &tessEvalShader)
+{
+ tessEvalShader.AddInclude("shadowMapping.glsllib");
+ tessEvalShader.AddUniform("model_view_projection", "mat4");
+ tessEvalShader.AddOutgoing("world_pos", "vec4");
+ tessEvalShader.Append(" ParaboloidMapResult data = VertexParaboloidDepth( vec3(pos.xyz), "
+ "model_view_projection );");
+ tessEvalShader.Append(" gl_Position = data.m_Position;");
+ tessEvalShader.Append(" world_pos = data.m_WorldPos;");
+}
+
+void IShaderProgramGenerator::OutputParaboloidDepthFragment(IShaderStageGenerator &fragmentShader)
+{
+ fragmentShader.AddInclude("shadowMappingFragment.glsllib");
+ fragmentShader.AddUniform("model_view_projection", "mat4");
+ fragmentShader.AddUniform("camera_properties", "vec2");
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append(" gl_FragDepth = FragmentParaboloidDepth( world_pos, "
+ "model_view_projection, camera_properties );");
+ fragmentShader.Append("}");
+}
+
+void IShaderProgramGenerator::OutputCubeFaceDepthVertex(IShaderStageGenerator &vertexShader)
+{
+ vertexShader.AddIncoming("attr_pos", "vec3");
+ vertexShader.AddUniform("model_matrix", "mat4");
+ vertexShader.AddUniform("model_view_projection", "mat4");
+
+ vertexShader.AddOutgoing("raw_pos", "vec4");
+ vertexShader.AddOutgoing("world_pos", "vec4");
+
+ vertexShader.Append("void main() {");
+ vertexShader.Append(" world_pos = model_matrix * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" world_pos /= world_pos.w;");
+ vertexShader.Append(" gl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" raw_pos = vec4( attr_pos, 1.0 );");
+ // vertexShader.Append(" gl_Position = vec4( attr_pos, 1.0 );");
+ vertexShader.Append("}");
+}
+
+void IShaderProgramGenerator::OutputCubeFaceDepthGeometry(IShaderStageGenerator &geometryShader)
+{
+ geometryShader.Append("layout(triangles) in;");
+ geometryShader.Append("layout(triangle_strip, max_vertices = 18) out;");
+ // geometryShader.AddUniform("shadow_mvp[6]", "mat4");
+
+ geometryShader.AddUniform("shadow_mv0", "mat4");
+ geometryShader.AddUniform("shadow_mv1", "mat4");
+ geometryShader.AddUniform("shadow_mv2", "mat4");
+ geometryShader.AddUniform("shadow_mv3", "mat4");
+ geometryShader.AddUniform("shadow_mv4", "mat4");
+ geometryShader.AddUniform("shadow_mv5", "mat4");
+ geometryShader.AddUniform("projection", "mat4");
+
+ geometryShader.AddUniform("model_matrix", "mat4");
+ geometryShader.AddOutgoing("world_pos", "vec4");
+
+ geometryShader.Append("void main() {");
+ geometryShader.Append(" mat4 layerMVP[6];");
+ geometryShader.Append(" layerMVP[0] = projection * shadow_mv0;");
+ geometryShader.Append(" layerMVP[1] = projection * shadow_mv1;");
+ geometryShader.Append(" layerMVP[2] = projection * shadow_mv2;");
+ geometryShader.Append(" layerMVP[3] = projection * shadow_mv3;");
+ geometryShader.Append(" layerMVP[4] = projection * shadow_mv4;");
+ geometryShader.Append(" layerMVP[5] = projection * shadow_mv5;");
+ geometryShader.Append(" for (int i = 0; i < 6; ++i)");
+ geometryShader.Append(" {");
+ geometryShader.Append(" gl_Layer = i;");
+ geometryShader.Append(" for(int j = 0; j < 3; ++j)");
+ geometryShader.Append(" {");
+ geometryShader.Append(" world_pos = model_matrix * raw_pos[j];");
+ geometryShader.Append(" world_pos /= world_pos.w;");
+ geometryShader.Append(" gl_Position = layerMVP[j] * raw_pos[j];");
+ geometryShader.Append(" world_pos.w = gl_Position.w;");
+ geometryShader.Append(" EmitVertex();");
+ geometryShader.Append(" }");
+ geometryShader.Append(" EndPrimitive();");
+ geometryShader.Append(" }");
+ geometryShader.Append("}");
+}
+
+void IShaderProgramGenerator::OutputCubeFaceDepthFragment(IShaderStageGenerator &fragmentShader)
+{
+ fragmentShader.AddUniform("camera_position", "vec3");
+ fragmentShader.AddUniform("camera_properties", "vec2");
+
+ fragmentShader.Append("void main() {");
+ fragmentShader.Append(
+ "\tvec3 camPos = vec3( camera_position.x, camera_position.y, -camera_position.z );");
+ fragmentShader.Append("\tfloat dist = length( world_pos.xyz - camPos );");
+ fragmentShader.Append(
+ "\tdist = (dist - camera_properties.x) / (camera_properties.y - camera_properties.x);");
+ // fragmentShader.Append("\tgl_FragDepth = dist;");
+ fragmentShader.Append("\tfragOutput = vec4(dist, dist, dist, 1.0);");
+ fragmentShader.Append("}");
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderShadowMap.cpp b/src/Runtime/Source/UICRender/Source/UICRenderShadowMap.cpp
new file mode 100644
index 00000000..c5b870c6
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderShadowMap.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderLayer.h"
+#include "UICRenderShadowMap.h"
+#include "UICRenderResourceManager.h"
+#include "../RendererImpl/UICRendererImplLayerRenderData.h"
+#include "render/Qt3DSRenderShaderConstant.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace uic::render;
+using qt3ds::render::NVRenderContextScopedProperty;
+using qt3ds::render::NVRenderCachedShaderProperty;
+
+UICShadowMap::UICShadowMap(IUICRenderContext &inContext)
+ : m_UICContext(inContext)
+ , mRefCount(0)
+ , m_ShadowMapList(inContext.GetAllocator(), "UICShadowMap::m_ShadowMapList")
+{
+}
+
+UICShadowMap::~UICShadowMap()
+{
+ m_ShadowMapList.clear();
+}
+
+namespace {
+bool IsDepthFormat(NVRenderTextureFormats::Enum format)
+{
+ switch (format) {
+ case NVRenderTextureFormats::Depth16:
+ case NVRenderTextureFormats::Depth24:
+ case NVRenderTextureFormats::Depth32:
+ case NVRenderTextureFormats::Depth24Stencil8:
+ return true;
+ default:
+ return false;
+ }
+}
+}
+
+void UICShadowMap::AddShadowMapEntry(QT3DSU32 index, QT3DSU32 width, QT3DSU32 height,
+ NVRenderTextureFormats::Enum format, QT3DSU32 samples,
+ ShadowMapModes::Enum mode, ShadowFilterValues::Enum filter)
+{
+ IResourceManager &theManager(m_UICContext.GetResourceManager());
+ SShadowMapEntry *pEntry = NULL;
+
+ if (index < m_ShadowMapList.size())
+ pEntry = &m_ShadowMapList[index];
+
+ if (pEntry) {
+ if ((NULL != pEntry->m_DepthMap) && (mode == ShadowMapModes::CUBE)) {
+ theManager.Release(*pEntry->m_DepthMap);
+ theManager.Release(*pEntry->m_DepthCopy);
+ theManager.Release(*pEntry->m_DepthRender);
+ pEntry->m_DepthCube = theManager.AllocateTextureCube(width, height, format, samples);
+ pEntry->m_CubeCopy = theManager.AllocateTextureCube(width, height, format, samples);
+ pEntry->m_DepthRender = theManager.AllocateTexture2D(
+ width, height, NVRenderTextureFormats::Depth24Stencil8, samples);
+ pEntry->m_DepthMap = NULL;
+ pEntry->m_DepthCopy = NULL;
+ } else if ((NULL != pEntry->m_DepthCube) && (mode != ShadowMapModes::CUBE)) {
+ theManager.Release(*pEntry->m_DepthCube);
+ theManager.Release(*pEntry->m_CubeCopy);
+ theManager.Release(*pEntry->m_DepthRender);
+ pEntry->m_DepthMap = theManager.AllocateTexture2D(width, height, format, samples);
+ pEntry->m_DepthCopy = theManager.AllocateTexture2D(width, height, format, samples);
+ pEntry->m_DepthCube = NULL;
+ pEntry->m_CubeCopy = NULL;
+ pEntry->m_DepthRender = theManager.AllocateTexture2D(
+ width, height, NVRenderTextureFormats::Depth24Stencil8, samples);
+ } else if (NULL != pEntry->m_DepthMap) {
+ STextureDetails theDetails(pEntry->m_DepthMap->GetTextureDetails());
+
+ // If anything differs about the map we're looking for, let's recreate it.
+ if (theDetails.m_Format != format || theDetails.m_Width != width
+ || theDetails.m_Height != height || theDetails.m_SampleCount != samples) {
+ // release texture
+ theManager.Release(*pEntry->m_DepthMap);
+ theManager.Release(*pEntry->m_DepthCopy);
+ theManager.Release(*pEntry->m_DepthRender);
+ pEntry->m_DepthMap = theManager.AllocateTexture2D(width, height, format, samples);
+ pEntry->m_DepthCopy = theManager.AllocateTexture2D(width, height, format, samples);
+ pEntry->m_DepthCube = NULL;
+ pEntry->m_CubeCopy = NULL;
+ pEntry->m_DepthRender = theManager.AllocateTexture2D(
+ width, height, NVRenderTextureFormats::Depth24Stencil8, samples);
+ }
+ } else {
+ STextureDetails theDetails(pEntry->m_DepthCube->GetTextureDetails());
+
+ // If anything differs about the map we're looking for, let's recreate it.
+ if (theDetails.m_Format != format || theDetails.m_Width != width
+ || theDetails.m_Height != height || theDetails.m_SampleCount != samples) {
+ // release texture
+ theManager.Release(*pEntry->m_DepthCube);
+ theManager.Release(*pEntry->m_CubeCopy);
+ theManager.Release(*pEntry->m_DepthRender);
+ pEntry->m_DepthCube =
+ theManager.AllocateTextureCube(width, height, format, samples);
+ pEntry->m_CubeCopy = theManager.AllocateTextureCube(width, height, format, samples);
+ pEntry->m_DepthRender = theManager.AllocateTexture2D(
+ width, height, NVRenderTextureFormats::Depth24Stencil8, samples);
+ pEntry->m_DepthMap = NULL;
+ pEntry->m_DepthCopy = NULL;
+ }
+ }
+
+ pEntry->m_ShadowMapMode = mode;
+ pEntry->m_ShadowFilterFlags = filter;
+ } else if (mode == ShadowMapModes::CUBE) {
+ NVRenderTextureCube *theDepthTex =
+ theManager.AllocateTextureCube(width, height, format, samples);
+ NVRenderTextureCube *theDepthCopy =
+ theManager.AllocateTextureCube(width, height, format, samples);
+ NVRenderTexture2D *theDepthTemp = theManager.AllocateTexture2D(
+ width, height, NVRenderTextureFormats::Depth24Stencil8, samples);
+
+ m_ShadowMapList.push_back(
+ SShadowMapEntry(index, mode, filter, *theDepthTex, *theDepthCopy, *theDepthTemp));
+
+ pEntry = &m_ShadowMapList.back();
+ } else {
+ NVRenderTexture2D *theDepthMap =
+ theManager.AllocateTexture2D(width, height, format, samples);
+ NVRenderTexture2D *theDepthCopy =
+ theManager.AllocateTexture2D(width, height, format, samples);
+ NVRenderTexture2D *theDepthTemp = theManager.AllocateTexture2D(
+ width, height, NVRenderTextureFormats::Depth24Stencil8, samples);
+
+ m_ShadowMapList.push_back(
+ SShadowMapEntry(index, mode, filter, *theDepthMap, *theDepthCopy, *theDepthTemp));
+
+ pEntry = &m_ShadowMapList.back();
+ }
+
+ if (pEntry) {
+ // setup some texture settings
+ if (pEntry->m_DepthMap) {
+ pEntry->m_DepthMap->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ pEntry->m_DepthMap->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ pEntry->m_DepthMap->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ pEntry->m_DepthMap->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+
+ pEntry->m_DepthCopy->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ pEntry->m_DepthCopy->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ pEntry->m_DepthCopy->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ pEntry->m_DepthCopy->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+
+ pEntry->m_DepthRender->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ pEntry->m_DepthRender->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ pEntry->m_DepthRender->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ pEntry->m_DepthRender->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+ } else {
+ pEntry->m_DepthCube->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ pEntry->m_DepthCube->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ pEntry->m_DepthCube->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ pEntry->m_DepthCube->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+
+ pEntry->m_CubeCopy->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ pEntry->m_CubeCopy->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ pEntry->m_CubeCopy->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ pEntry->m_CubeCopy->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+
+ pEntry->m_DepthRender->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ pEntry->m_DepthRender->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ pEntry->m_DepthRender->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ pEntry->m_DepthRender->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+ }
+
+ pEntry->m_LightIndex = index;
+ }
+}
+
+SShadowMapEntry *UICShadowMap::GetShadowMapEntry(QT3DSU32 index)
+{
+ SShadowMapEntry *pEntry = NULL;
+
+ for (QT3DSU32 i = 0; i < m_ShadowMapList.size(); i++) {
+ pEntry = &m_ShadowMapList[i];
+ if (pEntry->m_LightIndex == index)
+ return pEntry;
+ }
+
+ return NULL;
+}
+
+UICShadowMap *UICShadowMap::Create(IUICRenderContext &inContext)
+{
+ return QT3DS_NEW(inContext.GetFoundation().getAllocator(), UICShadowMap)(inContext);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderSubpresentation.cpp b/src/Runtime/Source/UICRender/Source/UICRenderSubpresentation.cpp
new file mode 100644
index 00000000..b045be95
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderSubpresentation.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderSubpresentation.h"
+#include "UICRenderRenderList.h"
+#ifdef _WIN32
+#pragma warning(disable : 4355) // this used in initializer list. I have never seen this result in
+ // a physical error
+#endif
+namespace uic {
+namespace render {
+
+ SUICRenderPickResult CSubPresentationPickQuery::Pick(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inViewportDimensions,
+ bool inPickEverything)
+ {
+ return m_Renderer.DoGraphQueryPick(inMouseCoords, inViewportDimensions, inPickEverything);
+ }
+
+ CSubPresentationRenderer::CSubPresentationRenderer(IUICRenderContext &inRenderContext,
+ SPresentation &inPresentation)
+ : m_RenderContext(inRenderContext)
+ , m_Presentation(inPresentation)
+ , mRefCount(0)
+ , m_PickQuery(*this)
+ , m_OffscreenRendererType(inRenderContext.GetStringTable().RegisterStr(GetRendererName()))
+ {
+ }
+
+ SOffscreenRendererEnvironment
+ CSubPresentationRenderer::GetDesiredEnvironment(QT3DSVec2 /*inPresScale*/)
+ {
+ // If we aren't using a clear color, then we are expected to blend with the background
+ bool hasTransparency = m_Presentation.m_Scene->m_UseClearColor ? false : true;
+ NVRenderTextureFormats::Enum format =
+ hasTransparency ? NVRenderTextureFormats::RGBA8 : NVRenderTextureFormats::RGB8;
+ return SOffscreenRendererEnvironment((QT3DSU32)(m_Presentation.m_PresentationDimensions.x),
+ (QT3DSU32)(m_Presentation.m_PresentationDimensions.y),
+ format, OffscreenRendererDepthValues::Depth16, false,
+ AAModeValues::NoAA);
+ }
+
+ SOffscreenRenderFlags
+ CSubPresentationRenderer::NeedsRender(const SOffscreenRendererEnvironment & /*inEnvironment*/,
+ QT3DSVec2 /*inPresScale*/)
+ {
+ bool hasTransparency = m_Presentation.m_Scene->m_UseClearColor ? false : true;
+ NVRenderRect theViewportSize(m_RenderContext.GetRenderList().GetViewport());
+ bool wasDirty = m_Presentation.m_Scene->PrepareForRender(
+ QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
+ m_RenderContext);
+ return SOffscreenRenderFlags(hasTransparency, wasDirty);
+ }
+
+ // Returns true if the rendered result image has transparency, or false
+ // if it should be treated as a completely opaque image.
+ void CSubPresentationRenderer::Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2,
+ SScene::RenderClearCommand inClearColorBuffer)
+ {
+ SSubPresentationHelper theHelper(
+ m_RenderContext,
+ SWindowDimensions((QT3DSU32)inEnvironment.m_Width, (QT3DSU32)inEnvironment.m_Height));
+ NVRenderRect theViewportSize(inRenderContext.GetViewport());
+ m_Presentation.m_Scene->Render(
+ QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
+ m_RenderContext, inClearColorBuffer);
+ m_LastRenderedEnvironment = inEnvironment;
+ }
+
+ // You know the viewport dimensions because
+ SUICRenderPickResult CSubPresentationRenderer::DoGraphQueryPick(
+ const QT3DSVec2 &inMouseCoords, const QT3DSVec2 &inViewportDimensions, bool inPickEverything)
+ {
+ SUICRenderPickResult thePickResult;
+
+ if (m_Presentation.m_Scene && m_Presentation.m_Scene->m_FirstChild) {
+ thePickResult = m_RenderContext.GetRenderer().Pick(
+ *m_Presentation.m_Scene->m_FirstChild, inViewportDimensions,
+ QT3DSVec2(inMouseCoords.x, inMouseCoords.y), true, inPickEverything);
+ }
+ return thePickResult;
+ }
+}
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp b/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp
new file mode 100644
index 00000000..2f11944d
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderTextTextureAtlas.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderTextTextureAtlas.h"
+#include "UICTextRenderer.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderContext.h"
+
+using namespace uic::render;
+
+namespace {
+
+struct STextTextureAtlas : public ITextTextureAtlas
+{
+ static const QT3DSI32 TEXTURE_ATLAS_DIM =
+ 256; // if you change this you need to adjust UICOnscreenTextRenderer size as well
+
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ NVScopedRefCounted<ITextRenderer> m_TextRenderer;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+
+ STextTextureAtlas(NVFoundationBase &inFnd, ITextRenderer &inRenderer,
+ NVRenderContext &inRenderContext)
+ : m_Foundation(inFnd)
+ , mRefCount(0)
+ , m_TextRenderer(inRenderer)
+ , m_RenderContext(inRenderContext)
+ , m_TextureAtlasInitialized(false)
+ , m_textureAtlas(NULL)
+ {
+ }
+
+ virtual ~STextTextureAtlas()
+ {
+ if (m_textureAtlas) {
+ m_textureAtlas->release();
+ }
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ TTextRenderAtlasDetailsAndTexture RenderText(const STextRenderInfo &inText) override
+ {
+ SRenderTextureAtlasDetails theDetails = m_TextRenderer->RenderText(inText);
+
+ return TTextRenderAtlasDetailsAndTexture(theDetails, m_textureAtlas);
+ }
+
+ bool IsInitialized() override { return m_TextureAtlasInitialized && m_textureAtlas; }
+
+ TTextTextureAtlasDetailsAndTexture PrepareTextureAtlas() override
+ {
+ if (!m_TextureAtlasInitialized && !m_textureAtlas) {
+ // create the texture atlas entries
+ QT3DSI32 count = m_TextRenderer->CreateTextureAtlas();
+
+ m_textureAtlas = m_RenderContext->CreateTexture2D();
+ if (m_textureAtlas && count) {
+ m_TextureAtlasInitialized = true;
+ m_textureAtlas->addRef();
+ // if you change the size you need to adjust UICOnscreenTextRenderer too
+ m_textureAtlas->SetTextureData(NVDataRef<QT3DSU8>(), 0, TEXTURE_ATLAS_DIM,
+ TEXTURE_ATLAS_DIM, NVRenderTextureFormats::Alpha8);
+ m_textureAtlas->SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ m_textureAtlas->SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ m_textureAtlas->SetTextureWrapS(NVRenderTextureCoordOp::ClampToEdge);
+ m_textureAtlas->SetTextureWrapT(NVRenderTextureCoordOp::ClampToEdge);
+ qt3ds::render::STextureDetails texTexDetails = m_textureAtlas->GetTextureDetails();
+ return TTextTextureAtlasDetailsAndTexture(
+ STextTextureAtlasDetails(texTexDetails.m_Height, texTexDetails.m_Height, false,
+ count),
+ m_textureAtlas);
+ }
+ }
+
+ return TTextTextureAtlasDetailsAndTexture(STextTextureAtlasDetails(), NULL);
+ }
+
+private:
+ bool m_TextureAtlasInitialized;
+ NVRenderTexture2D *m_textureAtlas; // this is the actual texture which has application lifetime
+};
+
+} // namespace
+
+ITextTextureAtlas &ITextTextureAtlas::CreateTextureAtlas(NVFoundationBase &inFnd,
+ ITextRenderer &inTextRenderer,
+ NVRenderContext &inRenderContext)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), STextTextureAtlas)(inFnd, inTextRenderer, inRenderContext);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderTextTextureCache.cpp b/src/Runtime/Source/UICRender/Source/UICRenderTextTextureCache.cpp
new file mode 100644
index 00000000..6aba0c36
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderTextTextureCache.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderTextTextureCache.h"
+#include "UICTextRenderer.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSPool.h"
+
+using namespace uic::render;
+
+namespace eastl {
+template <>
+struct hash<STextRenderInfo>
+{
+ size_t operator()(const uic::render::STextRenderInfo &inInfo) const
+ {
+ size_t retval = hash<size_t>()(reinterpret_cast<size_t>(inInfo.m_Text.c_str()));
+ retval = retval ^ hash<size_t>()(reinterpret_cast<size_t>(inInfo.m_Font.c_str()));
+ retval = retval ^ hash<float>()(inInfo.m_FontSize);
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_HorizontalAlignment));
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_VerticalAlignment));
+ retval = retval ^ hash<float>()(inInfo.m_Leading);
+ retval = retval ^ hash<float>()(inInfo.m_Tracking);
+ retval = retval ^ hash<bool>()(inInfo.m_EnableAcceleratedFont);
+ return retval;
+ }
+};
+}
+
+namespace {
+struct STextRenderInfoAndHash
+{
+ STextRenderInfo m_Info;
+ QT3DSF32 m_ScaleFactor;
+ size_t m_Hashcode;
+ STextRenderInfoAndHash(const STextRenderInfo &inInfo, QT3DSF32 inScaleFactor)
+ : m_Info(inInfo)
+ , m_ScaleFactor(inScaleFactor)
+ , m_Hashcode(eastl::hash<STextRenderInfo>()(inInfo) ^ eastl::hash<float>()(inScaleFactor))
+ {
+ }
+ bool operator==(const STextRenderInfoAndHash &inOther) const
+ {
+ return m_Info.m_Text == inOther.m_Info.m_Text && m_Info.m_Font == inOther.m_Info.m_Font
+ && m_Info.m_FontSize == inOther.m_Info.m_FontSize
+ && m_Info.m_HorizontalAlignment == inOther.m_Info.m_HorizontalAlignment
+ && m_Info.m_VerticalAlignment == inOther.m_Info.m_VerticalAlignment
+ && m_Info.m_Leading == inOther.m_Info.m_Leading
+ && m_Info.m_Tracking == inOther.m_Info.m_Tracking
+ && m_Info.m_EnableAcceleratedFont == inOther.m_Info.m_EnableAcceleratedFont
+ && m_ScaleFactor == inOther.m_ScaleFactor;
+ }
+};
+}
+
+namespace eastl {
+template <>
+struct hash<STextRenderInfoAndHash>
+{
+ size_t operator()(const STextRenderInfoAndHash &inInfo) const { return inInfo.m_Hashcode; }
+};
+};
+
+namespace {
+
+struct STextCacheNode
+{
+ STextCacheNode *m_PreviousSibling;
+ STextCacheNode *m_NextSibling;
+ STextRenderInfoAndHash m_RenderInfo;
+ TTPathObjectAndTexture m_TextInfo;
+ QT3DSU32 m_FrameCount;
+
+ STextCacheNode(const STextRenderInfoAndHash &inRenderInfo,
+ const TTPathObjectAndTexture &inTextInfo)
+ : m_PreviousSibling(NULL)
+ , m_NextSibling(NULL)
+ , m_RenderInfo(inRenderInfo)
+ , m_TextInfo(inTextInfo)
+ , m_FrameCount(0)
+ {
+ }
+};
+
+typedef nvhash_map<STextRenderInfoAndHash, STextCacheNode *> TTextureInfoHash;
+
+DEFINE_INVASIVE_LIST(TextCacheNode);
+IMPLEMENT_INVASIVE_LIST(TextCacheNode, m_PreviousSibling, m_NextSibling);
+
+struct STextTextureCache : public ITextTextureCache
+{
+ typedef Pool<STextCacheNode, ForwardingAllocator> TPoolType;
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ NVScopedRefCounted<ITextRenderer> m_TextRenderer;
+ TTextureInfoHash m_TextureCache;
+ TTextCacheNodeList m_LRUList;
+ TPoolType m_CacheNodePool;
+ QT3DSU32 m_HighWaterMark;
+ QT3DSU32 m_FrameCount;
+ QT3DSU32 m_TextureTotalBytes;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ bool m_CanUsePathRendering; ///< true if we use hardware accelerated font rendering
+
+ STextTextureCache(NVFoundationBase &inFnd, ITextRenderer &inRenderer,
+ NVRenderContext &inRenderContext)
+ : m_Foundation(inFnd)
+ , mRefCount(0)
+ , m_TextRenderer(inRenderer)
+ , m_TextureCache(m_Foundation.getAllocator(), "STextTextureCache::m_TextureCache")
+ , m_CacheNodePool(ForwardingAllocator(m_Foundation.getAllocator(),
+ "STextTextureCache::m_CacheNodePool"))
+ , m_HighWaterMark(0x100000)
+ , m_FrameCount(0)
+ , m_TextureTotalBytes(0)
+ , m_RenderContext(inRenderContext)
+ {
+ // hardware accelerate font rendering not ready yet
+ m_CanUsePathRendering = (m_RenderContext->IsPathRenderingSupported()
+ && m_RenderContext->IsProgramPipelineSupported());
+ }
+
+ virtual ~STextTextureCache()
+ {
+ for (TTextCacheNodeList::iterator iter = m_LRUList.begin(), end = m_LRUList.end();
+ iter != end; ++iter)
+ iter->~STextCacheNode();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ static inline QT3DSU32 GetNumBytes(NVRenderTexture2D &inTexture)
+ {
+ STextureDetails theDetails(inTexture.GetTextureDetails());
+ return theDetails.m_Width * theDetails.m_Height
+ * NVRenderTextureFormats::getSizeofFormat(theDetails.m_Format);
+ }
+
+ NVScopedRefCounted<NVRenderTexture2D> InvalidateLastItem()
+ {
+ NVScopedRefCounted<NVRenderTexture2D> nextTexture;
+ if (m_LRUList.empty() == false) {
+ STextCacheNode &theEnd = m_LRUList.back();
+ if (theEnd.m_FrameCount != m_FrameCount) {
+ nextTexture = theEnd.m_TextInfo.second.second;
+ STextureDetails theDetails = nextTexture->GetTextureDetails();
+ m_TextureTotalBytes -= GetNumBytes(*nextTexture.mPtr);
+ m_LRUList.remove(theEnd);
+ // copy the key because the next statement will destroy memory
+ m_TextureCache.erase(theEnd.m_RenderInfo);
+ theEnd.~STextCacheNode();
+ m_CacheNodePool.deallocate(&theEnd);
+ }
+ }
+ return nextTexture;
+ }
+
+ TTPathObjectAndTexture RenderText(const STextRenderInfo &inText, QT3DSF32 inScaleFactor) override
+ {
+ STextRenderInfoAndHash theKey(inText, inScaleFactor);
+ TTextureInfoHash::iterator theFind(
+ m_TextureCache.find(STextRenderInfoAndHash(inText, inScaleFactor)));
+ STextCacheNode *retval = NULL;
+ if (theFind != m_TextureCache.end()) {
+ retval = theFind->second;
+ m_LRUList.remove(*retval);
+ } else {
+ NVScopedRefCounted<NVRenderTexture2D> nextTexture;
+ if (m_TextureTotalBytes >= m_HighWaterMark && m_LRUList.empty() == false)
+ nextTexture = InvalidateLastItem();
+
+ if (nextTexture.mPtr == NULL)
+ nextTexture = m_RenderContext->CreateTexture2D();
+
+ NVScopedRefCounted<NVRenderPathFontItem> nextPathFontItemObject;
+ NVScopedRefCounted<NVRenderPathFontSpecification> nextPathFontObject;
+ // HW acceleration for fonts not supported
+ //if (m_CanUsePathRendering && inText.m_EnableAcceleratedFont) {
+ // nextPathFontItemObject = m_RenderContext->CreatePathFontItem();
+ // nextPathFontObject = m_RenderContext->CreatePathFontSpecification(inText.m_Font);
+ //}
+
+ STextRenderInfo theTextInfo(inText);
+ theTextInfo.m_FontSize *= inScaleFactor;
+ STextTextureDetails theDetails;
+
+
+ // HW acceleration for fonts not supported
+ //if (!m_CanUsePathRendering || !inText.m_EnableAcceleratedFont)
+ theDetails = m_TextRenderer->RenderText(theTextInfo, *nextTexture.mPtr);
+ //else
+ // theDetails = m_TextRenderer->RenderText(theTextInfo, *nextPathFontItemObject.mPtr,
+ // *nextPathFontObject.mPtr);
+
+ if (fabs(inScaleFactor - 1.0f) > .001f) {
+ TTPathObjectAndTexture theCanonicalDetails = RenderText(inText, 1.0f);
+ theDetails.m_ScaleFactor.x =
+ (QT3DSF32)theDetails.m_TextWidth / theCanonicalDetails.second.first.m_TextWidth;
+ theDetails.m_ScaleFactor.y =
+ (QT3DSF32)theDetails.m_TextHeight / theCanonicalDetails.second.first.m_TextHeight;
+ }
+ theKey = STextRenderInfoAndHash(inText, inScaleFactor);
+ retval = m_CacheNodePool.construct(
+ theKey, TTPathObjectAndTexture(
+ TPathFontSpecAndPathObject(nextPathFontObject, nextPathFontItemObject),
+ TTextTextureDetailsAndTexture(theDetails, nextTexture)),
+ __FILE__, __LINE__);
+ TTextureInfoHash::iterator insert =
+ m_TextureCache.insert(eastl::make_pair(theKey, retval)).first;
+ if (!m_CanUsePathRendering)
+ m_TextureTotalBytes += GetNumBytes(*(retval->m_TextInfo.second.second.mPtr));
+ }
+ retval->m_FrameCount = m_FrameCount;
+ m_LRUList.push_front(*retval);
+ return retval->m_TextInfo;
+ }
+ // We may have one more texture in cache than this byte count, but this will be the limiting
+ // factor.
+ QT3DSU32 GetCacheHighWaterBytes() const override { return m_HighWaterMark; }
+ // default cache size is 10 MB.
+ void SetCacheHighWaterBytes(QT3DSU32 inByteCount) override { m_HighWaterMark = inByteCount; }
+
+ void BeginFrame() override {}
+ void EndFrame() override
+ {
+ // algorithm is resistant to rollover.
+ ++m_FrameCount;
+ // Release any texture that put us over the limit.
+ // This almost guarantees thrashing if the limit is set too low. Enable at your
+ // own risk at *TEST CAREFULLY*
+ /*
+ while( m_TextureTotalBytes >= m_HighWaterMark && m_LRUList.empty() == false )
+ InvalidateLastItem();
+ */
+ }
+};
+}
+
+ITextTextureCache &ITextTextureCache::CreateTextureCache(NVFoundationBase &inFnd,
+ ITextRenderer &inTextRenderer,
+ NVRenderContext &inRenderContext)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), STextTextureCache)(inFnd, inTextRenderer, inRenderContext);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderTextureAtlas.cpp b/src/Runtime/Source/UICRender/Source/UICRenderTextureAtlas.cpp
new file mode 100644
index 00000000..194ec797
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderTextureAtlas.cpp
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderTextureAtlas.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderContext.h"
+
+using namespace uic::render;
+
+namespace {
+
+// a algorithm based on http://clb.demon.fi/files/RectangleBinPack/
+struct STextureAtlasBinPackSL
+{
+public:
+ STextureAtlasBinPackSL(NVRenderContext &inContext, QT3DSI32 width, QT3DSI32 height)
+ : m_BinWidth(width)
+ , m_BinHeight(height)
+ , m_SkyLine(inContext.GetAllocator(), "STextureAtlasBinPackSL::m_SkyLine")
+ {
+ // setup first entry
+ SSkylineNode theNode = { 0, 0, width };
+ m_SkyLine.push_back(theNode);
+ }
+
+ ~STextureAtlasBinPackSL() { m_SkyLine.clear(); }
+
+ /* insert new rect
+ *
+ */
+ STextureAtlasRect Insert(QT3DSI32 width, QT3DSI32 height)
+ {
+ QT3DSI32 binHeight;
+ QT3DSI32 binWidth;
+ QT3DSI32 binIndex;
+
+ STextureAtlasRect newNode = findPosition(width, height, &binWidth, &binHeight, &binIndex);
+
+ if (binIndex != -1) {
+ // adjust skyline nodes
+ addSkylineLevelNode(binIndex, newNode);
+ }
+
+ return newNode;
+ }
+
+private:
+ /// Represents a single level (a horizontal line) of the skyline/horizon/envelope.
+ struct SSkylineNode
+ {
+ int x; ///< The starting x-coordinate (leftmost).
+ int y; ///< The y-coordinate of the skyline level line.
+ int width; /// The line width. The ending coordinate (inclusive) will be x+width-1.
+ };
+
+ /* find position
+ *
+ */
+ STextureAtlasRect findPosition(QT3DSI32 width, QT3DSI32 height, QT3DSI32 *binWidth, QT3DSI32 *binHeight,
+ QT3DSI32 *binIndex)
+ {
+ *binWidth = m_BinWidth;
+ *binHeight = m_BinHeight;
+ *binIndex = -1;
+ STextureAtlasRect newRect;
+
+ for (QT3DSU32 i = 0; i < m_SkyLine.size(); ++i) {
+ QT3DSI32 y = getSkylineLevel(i, width, height);
+
+ if (y >= 0) {
+ if ((y + height < *binHeight)
+ || ((y + height == *binHeight) && m_SkyLine[i].width < *binWidth)) {
+ *binHeight = y + height;
+ *binIndex = i;
+ *binWidth = m_SkyLine[i].width;
+ newRect.m_X = m_SkyLine[i].x;
+ newRect.m_Y = y;
+ newRect.m_Width = width;
+ newRect.m_Height = height;
+ }
+ }
+ }
+
+ return newRect;
+ }
+
+ /* @brief check if rectangle can be placed into the the bin
+ *
+ * return skyline hight
+ */
+ int getSkylineLevel(QT3DSU32 binIndex, QT3DSI32 width, QT3DSI32 height)
+ {
+ // first check width exceed
+ QT3DSI32 x = m_SkyLine[binIndex].x;
+ if (x + width > m_BinWidth)
+ return -1;
+
+ QT3DSI32 leftAlign = width;
+ QT3DSU32 index = binIndex;
+ QT3DSI32 y = m_SkyLine[index].y;
+
+ while (leftAlign > 0) {
+ y = (y > m_SkyLine[index].y) ? y : m_SkyLine[index].y;
+ // check hight
+ if (y + height > m_BinHeight)
+ return -1;
+
+ leftAlign -= m_SkyLine[index].width;
+ ++index;
+
+ if (index > m_SkyLine.size())
+ return -1;
+ }
+
+ return y;
+ }
+
+ /* @brief add an new skyline entry
+ *
+ * return no return
+ */
+ void addSkylineLevelNode(QT3DSI32 binIndex, const STextureAtlasRect &newRect)
+ {
+ SSkylineNode newNode;
+
+ newNode.x = newRect.m_X;
+ newNode.y = newRect.m_Y + newRect.m_Height;
+ newNode.width = newRect.m_Width;
+ m_SkyLine.insert(m_SkyLine.begin() + binIndex, newNode);
+
+ // iterate over follow up nodes and adjust
+ for (QT3DSU32 i = binIndex + 1; i < m_SkyLine.size(); ++i) {
+ if (m_SkyLine[i].x < m_SkyLine[i - 1].x + m_SkyLine[i - 1].width) {
+ int shrink = m_SkyLine[i - 1].x + m_SkyLine[i - 1].width - m_SkyLine[i].x;
+
+ m_SkyLine[i].x += shrink;
+ m_SkyLine[i].width -= shrink;
+
+ if (m_SkyLine[i].width <= 0) {
+ m_SkyLine.erase(m_SkyLine.begin() + i);
+ --i;
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ mergeSkylineLevelNodes();
+ }
+
+ /* @brief merge skyline node
+ *
+ * return no return
+ */
+ void mergeSkylineLevelNodes()
+ {
+ // check if we can merge nodes
+ for (QT3DSU32 i = 0; i < m_SkyLine.size() - 1; ++i) {
+ if (m_SkyLine[i].y == m_SkyLine[i + 1].y) {
+ m_SkyLine[i].width += m_SkyLine[i + 1].width;
+ m_SkyLine.erase(m_SkyLine.begin() + (i + 1));
+ --i;
+ }
+ }
+ }
+
+ QT3DSI32 m_BinWidth;
+ QT3DSI32 m_BinHeight;
+
+ nvvector<SSkylineNode> m_SkyLine;
+};
+
+struct STextureAtlasEntry
+{
+ STextureAtlasEntry()
+ : m_X(0)
+ , m_Y(0)
+ , m_Width(0)
+ , m_Height(0)
+ , m_pBuffer(NVDataRef<QT3DSU8>())
+ {
+ }
+ STextureAtlasEntry(QT3DSF32 x, QT3DSF32 y, QT3DSF32 w, QT3DSF32 h, NVDataRef<QT3DSU8> buffer)
+ : m_X(x)
+ , m_Y(y)
+ , m_Width(w)
+ , m_Height(h)
+ , m_pBuffer(buffer)
+ {
+ }
+ STextureAtlasEntry(const STextureAtlasEntry &entry)
+ {
+ m_X = entry.m_X;
+ m_Y = entry.m_Y;
+ m_Width = entry.m_Width;
+ m_Height = entry.m_Height;
+ m_pBuffer = entry.m_pBuffer;
+ }
+ ~STextureAtlasEntry() {}
+
+ QT3DSF32 m_X, m_Y;
+ QT3DSF32 m_Width, m_Height;
+ NVDataRef<QT3DSU8> m_pBuffer;
+};
+
+struct STextureAtlas : public ITextureAtlas
+{
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+
+ STextureAtlas(NVFoundationBase &inFnd, NVRenderContext &inRenderContext, QT3DSI32 width,
+ QT3DSI32 height)
+ : m_Foundation(inFnd)
+ , mRefCount(0)
+ , m_RenderContext(inRenderContext)
+ , m_Width(width)
+ , m_Height(height)
+ , m_Spacing(1)
+ , m_AtlasEntrys(inFnd.getAllocator(), "STextureAtlas::m_SkyLine")
+ {
+ m_pBinPack =
+ QT3DS_NEW(inFnd.getAllocator(), STextureAtlasBinPackSL)(inRenderContext, width, height);
+ }
+
+ virtual ~STextureAtlas()
+ {
+ RelaseEntries();
+
+ if (m_pBinPack)
+ NVDelete(m_Foundation.getAllocator(), m_pBinPack);
+ }
+
+ void RelaseEntries() override
+ {
+ nvvector<STextureAtlasEntry>::iterator it;
+
+ for (it = m_AtlasEntrys.begin(); it != m_AtlasEntrys.end(); it++) {
+ QT3DS_FREE(m_Foundation.getAllocator(), it->m_pBuffer.begin());
+ }
+
+ m_AtlasEntrys.clear();
+ }
+ QT3DSI32 GetWidth() const override { return m_Width; }
+ QT3DSI32 GetHeight() const override { return m_Height; }
+
+ QT3DSI32 GetAtlasEntryCount() const override { return m_AtlasEntrys.size(); }
+
+ TTextureAtlasEntryAndBuffer GetAtlasEntryByIndex(QT3DSU32 index) override
+ {
+ if (index >= m_AtlasEntrys.size())
+ return eastl::make_pair(STextureAtlasRect(), NVDataRef<QT3DSU8>());
+
+ return eastl::make_pair(STextureAtlasRect((QT3DSI32)m_AtlasEntrys[index].m_X,
+ (QT3DSI32)m_AtlasEntrys[index].m_Y,
+ (QT3DSI32)m_AtlasEntrys[index].m_Width,
+ (QT3DSI32)m_AtlasEntrys[index].m_Height),
+ m_AtlasEntrys[index].m_pBuffer);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ STextureAtlasRect AddAtlasEntry(QT3DSI32 width, QT3DSI32 height, QT3DSI32 pitch,
+ QT3DSI32 dataWidth, NVConstDataRef<QT3DSU8> bufferData) override
+ {
+ STextureAtlasRect rect;
+
+ // pitch is the number of bytes per line in bufferData
+ // dataWidth is the relevant data width in bufferData. Rest is padding that can be ignored.
+ if (m_pBinPack) {
+ QT3DSI32 paddedWith, paddedPitch, paddedHeight;
+ // add spacing around the character
+ paddedWith = width + 2 * m_Spacing;
+ paddedPitch = dataWidth + 2 * m_Spacing;
+ paddedHeight = height + 2 * m_Spacing;
+ // first get entry in the texture atlas
+ rect = m_pBinPack->Insert(paddedWith, paddedHeight);
+ if (rect.m_Width == 0)
+ return rect;
+
+ // we align the data be to 4 byte
+ int alignment = (4 - (paddedPitch % 4)) % 4;
+ paddedPitch += alignment;
+
+ // since we do spacing around the character we need to copy line by line
+ QT3DSU8 *glyphBuffer =
+ (QT3DSU8 *)QT3DS_ALLOC(m_Foundation.getAllocator(),
+ paddedHeight * paddedPitch * sizeof(QT3DSU8), "STextureAtlas");
+ if (glyphBuffer) {
+ memset(glyphBuffer, 0, paddedHeight * paddedPitch);
+
+ QT3DSU8 *pDst = glyphBuffer + paddedPitch + m_Spacing;
+ QT3DSU8 *pSrc = const_cast<QT3DSU8 *>(bufferData.begin());
+ for (QT3DSI32 i = 0; i < height; ++i) {
+ memcpy(pDst, pSrc, dataWidth);
+
+ pDst += paddedPitch;
+ pSrc += pitch;
+ }
+
+ // add new entry
+ m_AtlasEntrys.push_back(STextureAtlasEntry(
+ (QT3DSF32)rect.m_X, (QT3DSF32)rect.m_Y, (QT3DSF32)paddedWith, (QT3DSF32)paddedHeight,
+ NVDataRef<QT3DSU8>(glyphBuffer, paddedHeight * paddedPitch * sizeof(QT3DSU8))));
+
+ // normalize texture coordinates
+ rect.m_NormX = (QT3DSF32)rect.m_X / (QT3DSF32)m_Width;
+ rect.m_NormY = (QT3DSF32)rect.m_Y / (QT3DSF32)m_Height;
+ rect.m_NormWidth = (QT3DSF32)paddedWith / (QT3DSF32)m_Width;
+ rect.m_NormHeight = (QT3DSF32)paddedHeight / (QT3DSF32)m_Height;
+ }
+ }
+
+ return rect;
+ }
+
+private:
+ QT3DSI32 m_Width; ///< texture atlas width
+ QT3DSI32 m_Height; ///< texture atlas height
+ QT3DSI32 m_Spacing; ///< spacing around the entry
+ nvvector<STextureAtlasEntry> m_AtlasEntrys; ///< our entries in the atlas
+ STextureAtlasBinPackSL *m_pBinPack; ///< our bin packer which actually does most of the work
+};
+
+} // namespace
+
+ITextureAtlas &ITextureAtlas::CreateTextureAtlas(NVFoundationBase &inFnd,
+ NVRenderContext &inRenderContext, QT3DSI32 width,
+ QT3DSI32 height)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), STextureAtlas)(inFnd, inRenderContext, width, height);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderThreadPool.cpp b/src/Runtime/Source/UICRender/Source/UICRenderThreadPool.cpp
new file mode 100644
index 00000000..0a6fbc61
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderThreadPool.cpp
@@ -0,0 +1,327 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderThreadPool.h"
+#include "foundation/Qt3DSThread.h"
+#include "EASTL/utility.h"
+#include "EASTL/list.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+
+using namespace uic::render;
+
+namespace {
+struct STask
+{
+ void *m_UserData;
+ TTaskFunction m_Function;
+ TTaskFunction m_CancelFunction;
+ QT3DSU64 m_Id;
+ TaskStates::Enum m_TaskState;
+ STask *m_NextTask;
+ STask *m_PreviousTask;
+
+ STask(void *ud, TTaskFunction func, TTaskFunction cancelFunc, QT3DSU64 inId)
+ : m_UserData(ud)
+ , m_Function(func)
+ , m_CancelFunction(cancelFunc)
+ , m_Id(inId)
+ , m_TaskState(TaskStates::Queued)
+ , m_NextTask(NULL)
+ , m_PreviousTask(NULL)
+ {
+ }
+ STask()
+ : m_UserData(NULL)
+ , m_Function(NULL)
+ , m_CancelFunction(NULL)
+ , m_Id(0)
+ , m_TaskState(TaskStates::UnknownTask)
+ , m_NextTask(NULL)
+ , m_PreviousTask(NULL)
+ {
+ }
+ void CallFunction()
+ {
+ if (m_Function)
+ m_Function(m_UserData);
+ }
+ void Cancel()
+ {
+ if (m_CancelFunction)
+ m_CancelFunction(m_UserData);
+ }
+};
+
+struct STaskHeadOp
+{
+ STask *get(STask &inTask) { return inTask.m_PreviousTask; }
+ void set(STask &inTask, STask *inItem) { inTask.m_PreviousTask = inItem; }
+};
+
+struct STaskTailOp
+{
+ STask *get(STask &inTask) { return inTask.m_NextTask; }
+ void set(STask &inTask, STask *inItem) { inTask.m_NextTask = inItem; }
+};
+
+typedef InvasiveLinkedList<STask, STaskHeadOp, STaskTailOp> TTaskList;
+
+class IInternalTaskManager
+{
+protected:
+ virtual ~IInternalTaskManager() {}
+public:
+ virtual STask GetNextTask() = 0;
+ virtual void TaskFinished(QT3DSU64 inId) = 0;
+};
+
+struct SThreadPoolThread : public Thread
+{
+ IInternalTaskManager &m_Mgr;
+ SThreadPoolThread(NVFoundationBase &foundation, IInternalTaskManager &inMgr)
+ : Thread(foundation)
+ , m_Mgr(inMgr)
+ {
+ }
+ void execute(void) override
+ {
+ setName("UICRender Thread manager thread");
+ while (!quitIsSignalled()) {
+ STask task = m_Mgr.GetNextTask();
+ if (task.m_Function) {
+ task.CallFunction();
+ m_Mgr.TaskFinished(task.m_Id);
+ }
+ }
+ quit();
+ }
+};
+
+struct SThreadPool : public IThreadPool, public IInternalTaskManager
+{
+ typedef nvhash_map<QT3DSU64, STask *> TIdTaskMap;
+ typedef Mutex::ScopedLock TLockType;
+ typedef Pool<STask, ForwardingAllocator> TTaskPool;
+
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ nvvector<SThreadPoolThread *> m_Threads;
+ TIdTaskMap m_Tasks;
+ Sync m_TaskListEvent;
+ volatile bool m_Running;
+ Mutex m_TaskListMutex;
+ TTaskPool m_TaskPool;
+ TTaskList m_TaskList;
+
+ QT3DSU64 m_NextId;
+
+ SThreadPool(NVFoundationBase &inBase, QT3DSU32 inMaxThreads)
+ : m_Foundation(inBase)
+ , mRefCount(0)
+ , m_Threads(inBase.getAllocator(), "SThreadPool::m_Threads")
+ , m_Tasks(inBase.getAllocator(), "SThreadPool::m_Tasks")
+ , m_TaskListEvent(inBase.getAllocator())
+ , m_Running(true)
+ , m_TaskListMutex(m_Foundation.getAllocator())
+ , m_TaskPool(ForwardingAllocator(m_Foundation.getAllocator(), "SThreadPool::m_TaskPool"))
+ , m_NextId(1)
+ {
+ // Fire up our little pools of chaos.
+ for (QT3DSU32 idx = 0; idx < inMaxThreads; ++idx) {
+ m_Threads.push_back(
+ QT3DS_NEW(m_Foundation.getAllocator(), SThreadPoolThread)(m_Foundation, *this));
+ m_Threads.back()->start(Thread::DEFAULT_STACK_SIZE);
+ }
+ }
+
+ void MutexHeldRemoveTaskFromList(STask *theTask)
+ {
+ if (theTask)
+ m_TaskList.remove(*theTask);
+ QT3DS_ASSERT(theTask->m_NextTask == NULL);
+ QT3DS_ASSERT(theTask->m_PreviousTask == NULL);
+ }
+
+ STask *MutexHeldNextTask()
+ {
+ STask *theTask = m_TaskList.front_ptr();
+ if (theTask) {
+ MutexHeldRemoveTaskFromList(theTask);
+ }
+ if (theTask) {
+ QT3DS_ASSERT(m_TaskList.m_Head != theTask);
+ QT3DS_ASSERT(m_TaskList.m_Tail != theTask);
+ }
+ return theTask;
+ }
+
+ virtual ~SThreadPool()
+ {
+ m_Running = false;
+
+ m_TaskListEvent.set();
+
+ for (QT3DSU32 idx = 0, end = m_Threads.size(); idx < end; ++idx)
+ m_Threads[idx]->signalQuit();
+
+ for (QT3DSU32 idx = 0, end = m_Threads.size(); idx < end; ++idx) {
+ m_Threads[idx]->waitForQuit();
+ NVDelete(m_Foundation.getAllocator(), m_Threads[idx]);
+ }
+
+ m_Threads.clear();
+
+ TLockType __listMutexLocker(m_TaskListMutex);
+
+ for (STask *theTask = MutexHeldNextTask(); theTask; theTask = MutexHeldNextTask()) {
+ theTask->Cancel();
+ }
+
+ m_Tasks.clear();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void VerifyTaskList()
+ {
+ STask *theLastTask = NULL;
+ for (STask *theTask = m_TaskList.m_Head; theTask; theTask = theTask->m_NextTask) {
+ QT3DS_ASSERT(theTask->m_PreviousTask == theLastTask);
+ theLastTask = theTask;
+ }
+ theLastTask = NULL;
+ for (STask *theTask = m_TaskList.m_Tail; theTask; theTask = theTask->m_PreviousTask) {
+ QT3DS_ASSERT(theTask->m_NextTask == theLastTask);
+ theLastTask = theTask;
+ }
+ }
+
+ QT3DSU64 AddTask(void *inUserData, TTaskFunction inFunction,
+ TTaskFunction inCancelFunction) override
+ {
+ if (inFunction && m_Running) {
+ TLockType __listMutexLocker(m_TaskListMutex);
+ QT3DSU64 taskId = m_NextId;
+ ++m_NextId;
+
+ STask *theTask = (STask *)m_TaskPool.allocate(__FILE__, __LINE__);
+ new (theTask) STask(inUserData, inFunction, inCancelFunction, taskId);
+ TIdTaskMap::iterator theTaskIter =
+ m_Tasks.insert(eastl::make_pair(taskId, theTask)).first;
+
+ m_TaskList.push_back(*theTask);
+ QT3DS_ASSERT(m_TaskList.m_Tail == theTask);
+
+#ifdef _DEBUG
+ VerifyTaskList();
+#endif
+ m_TaskListEvent.set();
+ m_TaskListEvent.reset();
+ return taskId;
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ TaskStates::Enum GetTaskState(QT3DSU64 inTaskId) override
+ {
+ TLockType __listMutexLocker(m_TaskListMutex);
+ TIdTaskMap::iterator theTaskIter = m_Tasks.find(inTaskId);
+ if (theTaskIter != m_Tasks.end())
+ return theTaskIter->second->m_TaskState;
+ return TaskStates::UnknownTask;
+ }
+
+ CancelReturnValues::Enum CancelTask(QT3DSU64 inTaskId) override
+ {
+ TLockType __listMutexLocker(m_TaskListMutex);
+ TIdTaskMap::iterator theTaskIter = m_Tasks.find(inTaskId);
+ if (theTaskIter == m_Tasks.end())
+ return CancelReturnValues::TaskCanceled;
+ if (theTaskIter->second->m_TaskState == TaskStates::Running)
+ return CancelReturnValues::TaskRunning;
+
+ STask *theTask = theTaskIter->second;
+ theTask->Cancel();
+ MutexHeldRemoveTaskFromList(theTask);
+ m_Tasks.erase(inTaskId);
+ m_TaskPool.deallocate(theTask);
+
+ return CancelReturnValues::TaskCanceled;
+ }
+
+ STask GetNextTask() override
+ {
+
+ if (m_Running) {
+ {
+ TLockType __listMutexLocker(m_TaskListMutex);
+ STask *retval = MutexHeldNextTask();
+ if (retval)
+ return *retval;
+ }
+ // If we couldn't get a task then wait.
+ m_TaskListEvent.wait(1000);
+ }
+ return STask();
+ }
+
+ void TaskFinished(QT3DSU64 inId) override
+ {
+ TLockType __listMutexLocker(m_TaskListMutex);
+ TIdTaskMap::iterator theTaskIter = m_Tasks.find(inId);
+ if (theTaskIter == m_Tasks.end()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ STask *theTask(theTaskIter->second);
+
+#ifdef _DEBUG
+ QT3DS_ASSERT(theTask->m_NextTask == NULL);
+ QT3DS_ASSERT(theTask->m_PreviousTask == NULL);
+#endif
+ m_TaskPool.deallocate(theTask);
+ m_Tasks.erase(inId);
+ return;
+ }
+};
+}
+
+IThreadPool &IThreadPool::CreateThreadPool(NVFoundationBase &inFoundation, QT3DSU32 inNumThreads)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SThreadPool)(inFoundation, inNumThreads);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderUIPLoader.cpp b/src/Runtime/Source/UICRender/Source/UICRenderUIPLoader.cpp
new file mode 100644
index 00000000..dbe4452a
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderUIPLoader.cpp
@@ -0,0 +1,2019 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifdef UIC_RENDER_ENABLE_LOAD_UIP
+
+#include "UICRenderUIPLoader.h"
+#include "UICRenderPresentation.h"
+#include "UICRenderNode.h"
+#include "UICRenderLight.h"
+#include "UICRenderCamera.h"
+#include "UICRenderLayer.h"
+#include "UICRenderModel.h"
+#include "UICRenderDefaultMaterial.h"
+#include "UICRenderImage.h"
+#include "UICRenderBufferManager.h"
+#include "UICRenderUIPSharedTranslation.h"
+#include <vector>
+#include <map>
+#include <set>
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4201)
+#endif
+#include "UICDMXML.h"
+#include "UICTypes.h"
+#include "UICVector3.h"
+#include "UICMetadata.h"
+#include "UICDMWStrOps.h"
+#include "UICDMWStrOpsImpl.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "EASTL/string.h"
+#include "foundation/StrConvertUTF.h"
+#include "UICRenderEffectSystem.h"
+#include "UICRenderString.h"
+#include "foundation/FileTools.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "EASTL/map.h"
+#include "UICRenderEffect.h"
+#include "UICDMMetaDataTypes.h"
+#include "UICTextRenderer.h"
+#include "UICRenderPlugin.h"
+#include "UICRenderPluginGraphObject.h"
+#include "UICRenderPluginPropertyValue.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderMaterialHelpers.h"
+#include "UICRenderPath.h"
+#include "UICRenderPathSubPath.h"
+#include "UICRenderPathManager.h"
+
+using qt3ds::foundation::Option;
+using qt3ds::foundation::Empty;
+using qt3ds::QT3DSF32;
+using qt3ds::QT3DSVec3;
+using qt3ds::foundation::nvvector;
+using qt3ds::QT3DSU32;
+using uic::render::RenderLightTypes;
+using uic::render::DefaultMaterialLighting;
+using uic::render::ImageMappingModes;
+using uic::render::DefaultMaterialBlendMode;
+using qt3ds::render::NVRenderTextureCoordOp;
+using qt3ds::foundation::IStringTable;
+using qt3ds::NVFoundationBase;
+using namespace qt3ds;
+using namespace qt3ds::foundation;
+using uic::render::TIdObjectMap;
+using uic::render::IBufferManager;
+using uic::render::IEffectSystem;
+using uic::render::SPresentation;
+using uic::render::SScene;
+using uic::render::SLayer;
+using uic::render::SNode;
+using uic::render::SLight;
+using uic::render::SCamera;
+using uic::render::SModel;
+using uic::render::SText;
+using uic::render::SDefaultMaterial;
+using uic::render::SImage;
+using uic::render::SGraphObject;
+using uic::render::SDynamicObject;
+using uic::render::SEffect;
+using uic::render::SCustomMaterial;
+using uic::render::GraphObjectTypes;
+using uic::render::NodeFlags;
+using qt3ds::foundation::CRegisteredString;
+using uic::render::CRenderString;
+using qt3ds::foundation::CFileTools;
+using uic::render::SReferencedMaterial;
+using uic::render::IUIPReferenceResolver;
+using uic::render::SPath;
+using uic::render::SPathSubPath;
+using uic::render::SLightmaps;
+
+namespace UICDM {
+template <>
+struct WStrOps<SFloat2>
+{
+ void StrTo(const char8_t *buffer, SFloat2 &item, nvvector<char8_t> &ioTempBuf)
+ {
+ QT3DSU32 len = (QT3DSU32)strlen(buffer);
+ ioTempBuf.resize(len + 1);
+ memCopy(ioTempBuf.data(), buffer, (len + 1) * sizeof(char8_t));
+ MemoryBuffer<RawAllocator> unused;
+ UICDM::IStringTable *theTable(NULL);
+ WCharTReader reader(ioTempBuf.begin(), unused, *theTable);
+ reader.ReadRef(NVDataRef<QT3DSF32>(item.m_Floats, 2));
+ }
+};
+
+template <>
+struct WStrOps<SFloat3>
+{
+ void StrTo(const char8_t *buffer, SFloat3 &item, nvvector<char8_t> &ioTempBuf)
+ {
+ QT3DSU32 len = (QT3DSU32)strlen(buffer);
+ ioTempBuf.resize(len + 1);
+ memCopy(ioTempBuf.data(), buffer, (len + 1) * sizeof(char8_t));
+ MemoryBuffer<RawAllocator> unused;
+ UICDM::IStringTable *theTable(NULL);
+ WCharTReader reader(ioTempBuf.begin(), unused, *theTable);
+ reader.ReadRef(NVDataRef<QT3DSF32>(item.m_Floats, 3));
+ }
+};
+}
+
+namespace {
+
+typedef eastl::basic_string<char8_t> TStrType;
+struct IPropertyParser
+{
+ virtual ~IPropertyParser() {}
+ virtual Option<TStrType> ParseStr(const char8_t *inName) = 0;
+ virtual Option<QT3DSF32> ParseFloat(const char8_t *inName) = 0;
+ virtual Option<QT3DSVec2> ParseVec2(const char8_t *inName) = 0;
+ virtual Option<QT3DSVec3> ParseVec3(const char8_t *inName) = 0;
+ virtual Option<bool> ParseBool(const char8_t *inName) = 0;
+ virtual Option<QT3DSU32> ParseU32(const char8_t *inName) = 0;
+ virtual Option<QT3DSI32> ParseI32(const char8_t *inName) = 0;
+ virtual Option<SGraphObject *> ParseGraphObject(const char8_t *inName) = 0;
+ virtual Option<SNode *> ParseNode(const char8_t *inName) = 0;
+};
+struct SMetaPropertyParser : public IPropertyParser
+{
+ Q3DStudio::IRuntimeMetaData &m_MetaData;
+ TStrType m_TempStr;
+ qt3ds::foundation::CRegisteredString m_Type;
+ qt3ds::foundation::CRegisteredString m_ClassId;
+
+ SMetaPropertyParser(const char8_t *inType, const char8_t *inClass,
+ Q3DStudio::IRuntimeMetaData &inMeta)
+ : m_MetaData(inMeta)
+ , m_Type(inMeta.GetStringTable()->GetRenderStringTable().RegisterStr(inType))
+ , m_ClassId(inMeta.GetStringTable()->GetRenderStringTable().RegisterStr(inClass))
+ {
+ }
+
+ qt3ds::foundation::CRegisteredString Register(const char8_t *inName)
+ {
+ return m_MetaData.GetStringTable()->GetRenderStringTable().RegisterStr(inName);
+ }
+
+ Option<TStrType> ParseStr(const char8_t *inName) override
+ {
+ qt3ds::foundation::CRegisteredString theName(Register(inName));
+ Q3DStudio::ERuntimeDataModelDataType theType(
+ m_MetaData.GetPropertyType(m_Type, theName, m_ClassId));
+ if (theType != Q3DStudio::ERuntimeDataModelDataTypeObjectRef
+ && theType != Q3DStudio::ERuntimeDataModelDataTypeLong4) {
+ return m_MetaData.GetPropertyValueString(m_Type, theName, m_ClassId);
+ }
+ return Empty();
+ }
+ Option<QT3DSF32> ParseFloat(const char8_t *inName) override
+ {
+ return m_MetaData.GetPropertyValueFloat(m_Type, Register(inName), m_ClassId);
+ }
+ Option<QT3DSVec2> ParseVec2(const char8_t *inName) override
+ {
+ Option<qt3ds::QT3DSVec3> theProperty =
+ m_MetaData.GetPropertyValueVector2(m_Type, Register(inName), m_ClassId);
+ if (theProperty.hasValue()) {
+ return QT3DSVec2(theProperty->x, theProperty->y);
+ }
+ return Empty();
+ }
+ Option<QT3DSVec3> ParseVec3(const char8_t *inName) override
+ {
+ Option<qt3ds::QT3DSVec3> theProperty =
+ m_MetaData.GetPropertyValueVector3(m_Type, Register(inName), m_ClassId);
+ if (theProperty.hasValue()) {
+ return *theProperty;
+ }
+ return Empty();
+ }
+ Option<bool> ParseBool(const char8_t *inName) override
+ {
+ return m_MetaData.GetPropertyValueBool(m_Type, Register(inName), m_ClassId);
+ }
+
+ Option<QT3DSU32> ParseU32(const char8_t *inName) override
+ {
+ Option<QT3DSI32> retval = m_MetaData.GetPropertyValueLong(m_Type, Register(inName), m_ClassId);
+ if (retval.hasValue())
+ return (QT3DSU32)retval.getValue();
+ return Empty();
+ }
+
+ Option<QT3DSI32> ParseI32(const char8_t *inName) override
+ {
+ Option<QT3DSI32> retval = m_MetaData.GetPropertyValueLong(m_Type, Register(inName), m_ClassId);
+ if (retval.hasValue())
+ return (QT3DSI32)retval.getValue();
+ return Empty();
+ }
+
+ Option<SGraphObject *> ParseGraphObject(const char8_t *) override { return Empty(); }
+ Option<SNode *> ParseNode(const char8_t *) override { return Empty(); }
+};
+
+class IDOMReferenceResolver
+{
+protected:
+ virtual ~IDOMReferenceResolver() {}
+public:
+ virtual SGraphObject *ResolveReference(SGraphObject &inRootObject, const char *path) = 0;
+};
+
+struct SDomReaderPropertyParser : public IPropertyParser
+{
+ UICDM::IDOMReader &m_Reader;
+ nvvector<char8_t> &m_TempBuf;
+ IDOMReferenceResolver &m_Resolver;
+ SGraphObject &m_Object;
+
+ SDomReaderPropertyParser(UICDM::IDOMReader &reader, nvvector<char8_t> &inTempBuf,
+ IDOMReferenceResolver &inResolver, SGraphObject &inObject)
+ : m_Reader(reader)
+ , m_TempBuf(inTempBuf)
+ , m_Resolver(inResolver)
+ , m_Object(inObject)
+ {
+ }
+ Option<TStrType> ParseStr(const char8_t *inName) override
+ {
+ const char8_t *retval;
+ if (m_Reader.Att(inName, retval))
+ return TStrType(retval);
+ return Empty();
+ }
+ Option<QT3DSF32> ParseFloat(const char8_t *inName) override
+ {
+ QT3DSF32 retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+ Option<QT3DSVec2> ParseVec2(const char8_t *inName) override
+ {
+ UICDM::SFloat2 retval;
+ const char8_t *tempData;
+ if (m_Reader.UnregisteredAtt(inName, tempData)) {
+ UICDM::WStrOps<UICDM::SFloat2>().StrTo(tempData, retval, m_TempBuf);
+ return QT3DSVec2(retval.m_Floats[0], retval.m_Floats[1]);
+ }
+ return Empty();
+ }
+ Option<QT3DSVec3> ParseVec3(const char8_t *inName) override
+ {
+ UICDM::SFloat3 retval;
+ const char8_t *tempData;
+ if (m_Reader.UnregisteredAtt(inName, tempData)) {
+ UICDM::WStrOps<UICDM::SFloat3>().StrTo(tempData, retval, m_TempBuf);
+ return QT3DSVec3(retval.m_Floats[0], retval.m_Floats[1], retval.m_Floats[2]);
+ }
+ return Empty();
+ }
+ Option<bool> ParseBool(const char8_t *inName) override
+ {
+ bool retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+
+ Option<QT3DSU32> ParseU32(const char8_t *inName) override
+ {
+ QT3DSU32 retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+
+ Option<QT3DSI32> ParseI32(const char8_t *inName) override
+ {
+ QT3DSI32 retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+
+ Option<SGraphObject *> ParseGraphObject(const char8_t *inName) override
+ {
+ const char *temp;
+ if (m_Reader.UnregisteredAtt(inName, temp)) {
+ // Now we need to figure out if this is an element reference or if it is a relative path
+ // from the current element.
+ SGraphObject *retval = m_Resolver.ResolveReference(m_Object, temp);
+ if (retval)
+ return retval;
+ }
+ return Empty();
+ }
+
+ Option<SNode *> ParseNode(const char8_t *inName) override
+ {
+ Option<SGraphObject *> obj = ParseGraphObject(inName);
+ if (obj.hasValue()) {
+ if (GraphObjectTypes::IsNodeType((*obj)->m_Type))
+ return static_cast<SNode *>((*obj));
+ }
+ return Empty();
+ }
+};
+
+template <typename TDataType>
+struct SParserHelper
+{
+};
+template <>
+struct SParserHelper<TStrType>
+{
+ static Option<TStrType> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseStr(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSF32>
+{
+ static Option<QT3DSF32> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseFloat(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSVec2>
+{
+ static Option<QT3DSVec2> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseVec2(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSVec3>
+{
+ static Option<QT3DSVec3> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseVec3(inName);
+ }
+};
+template <>
+struct SParserHelper<bool>
+{
+ static Option<bool> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseBool(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSU32>
+{
+ static Option<QT3DSU32> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseU32(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSI32>
+{
+ static Option<QT3DSI32> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseI32(inName);
+ }
+};
+template <>
+struct SParserHelper<SGraphObject *>
+{
+ static Option<SGraphObject *> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseGraphObject(inName);
+ }
+};
+template <>
+struct SParserHelper<SNode *>
+{
+ static Option<SNode *> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseNode(inName);
+ }
+};
+
+struct SPathAndAnchorIndex
+{
+ SPathSubPath *m_Segment;
+ QT3DSU32 m_AnchorIndex;
+ SPathAndAnchorIndex(SPathSubPath *inSegment, QT3DSU32 inAnchorIndex)
+ : m_Segment(inSegment)
+ , m_AnchorIndex(inAnchorIndex)
+ {
+ }
+ SPathAndAnchorIndex()
+ : m_Segment(NULL)
+ , m_AnchorIndex(0)
+ {
+ }
+};
+
+struct SRenderUIPLoader : public IDOMReferenceResolver
+{
+ typedef UICDM::IDOMReader::Scope TScope;
+ typedef eastl::map<CRegisteredString, eastl::string> TIdStringMap;
+ typedef eastl::hash_map<CRegisteredString, SPathAndAnchorIndex> TIdPathAnchorIndexMap;
+ UICDM::IDOMReader &m_Reader;
+ Q3DStudio::IRuntimeMetaData &m_MetaData;
+ IStringTable &m_StrTable;
+ NVFoundationBase &m_Foundation;
+ NVAllocatorCallback &m_PresentationAllocator;
+ uic::render::TIdObjectMap &m_ObjectMap;
+ IBufferManager &m_BufferManager;
+ SPresentation *m_Presentation;
+ nvvector<char8_t> m_TempBuf;
+ TStrType m_TempParseString;
+ IEffectSystem &m_EffectSystem;
+ const char8_t *m_PresentationDir;
+ CRenderString m_PathString;
+ uic::render::IRenderPluginManager &m_RenderPluginManager;
+ uic::render::ICustomMaterialSystem &m_CustomMaterialSystem;
+ uic::render::IDynamicObjectSystem &m_DynamicObjectSystem;
+ uic::render::IPathManager &m_PathManager;
+ TIdStringMap m_RenderPluginSourcePaths;
+ IUIPReferenceResolver *m_ReferenceResolver;
+ MemoryBuffer<RawAllocator> m_TempBuffer;
+ MemoryBuffer<RawAllocator> m_ValueBuffer;
+ TIdPathAnchorIndexMap m_AnchorIdToPathAndAnchorIndexMap;
+
+ SRenderUIPLoader(UICDM::IDOMReader &inReader, const char8_t *inFullPathToPresentationFile,
+ Q3DStudio::IRuntimeMetaData &inMetaData, IStringTable &inStrTable
+ // Allocator for datastructures we need to parse the file.
+ ,
+ NVFoundationBase &inFoundation
+ // Allocator used for the presentation objects themselves
+ ,
+ NVAllocatorCallback &inPresentationAllocator
+ // Map of string ids to objects
+ ,
+ TIdObjectMap &ioObjectMap, IBufferManager &inBufferManager,
+ IEffectSystem &inEffectSystem, const char8_t *inPresentationDir,
+ uic::render::IRenderPluginManager &inRPM,
+ uic::render::ICustomMaterialSystem &inCMS,
+ uic::render::IDynamicObjectSystem &inDynamicSystem,
+ uic::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver)
+ : m_Reader(inReader)
+ , m_MetaData(inMetaData)
+ , m_StrTable(inStrTable)
+ , m_Foundation(inFoundation)
+ , m_PresentationAllocator(inPresentationAllocator)
+ , m_ObjectMap(ioObjectMap)
+ , m_BufferManager(inBufferManager)
+ , m_Presentation(QT3DS_NEW(inPresentationAllocator, SPresentation)())
+ , m_TempBuf(inFoundation.getAllocator(), "SRenderUIPLoader::m_TempBuf")
+ , m_EffectSystem(inEffectSystem)
+ , m_PresentationDir(inPresentationDir)
+ , m_RenderPluginManager(inRPM)
+ , m_CustomMaterialSystem(inCMS)
+ , m_DynamicObjectSystem(inDynamicSystem)
+ , m_PathManager(inPathManager)
+ , m_ReferenceResolver(inResolver)
+ {
+ std::string presentationFile = inFullPathToPresentationFile;
+ std::string::size_type pos = presentationFile.find_last_of("\\/");
+ if (pos != std::string::npos) {
+ std::string path = presentationFile.substr(0, pos);
+ m_Presentation->m_PresentationDirectory = inStrTable.RegisterStr(path.c_str());
+ }
+ }
+
+ SGraphObject *ResolveReference(SGraphObject &inRoot, const char *path) override
+ {
+ if (m_ReferenceResolver) {
+ CRegisteredString resolvedReference =
+ m_ReferenceResolver->ResolveReference(inRoot.m_Id, path);
+ if (resolvedReference.IsValid()) {
+ uic::render::TIdObjectMap::iterator iter = m_ObjectMap.find(resolvedReference);
+ if (iter != m_ObjectMap.end())
+ return iter->second;
+ }
+ }
+ return NULL;
+ }
+
+ static bool IsNode(GraphObjectTypes::Enum inType)
+ {
+ return GraphObjectTypes::IsNodeType(inType);
+ }
+ template <typename TDataType>
+ bool ParseProperty(IPropertyParser &inParser, const char8_t *inName, TDataType &outData)
+ {
+ Option<TDataType> theValue(SParserHelper<TDataType>::Parse(inName, inParser));
+ if (theValue.hasValue()) {
+ outData = theValue;
+ return true;
+ }
+ return false;
+ }
+ bool ParseOpacityProperty(IPropertyParser &inParser, const char8_t *inName, QT3DSF32 &outOpacity)
+ {
+ if (ParseProperty(inParser, inName, outOpacity)) {
+ outOpacity /= 100.0f;
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseRadianProperty(IPropertyParser &inParser, const char8_t *inName, QT3DSVec3 &ioRotation)
+ {
+ if (ParseProperty(inParser, inName, ioRotation)) {
+ TORAD(ioRotation.x);
+ TORAD(ioRotation.y);
+ TORAD(ioRotation.z);
+ return true;
+ }
+ return false;
+ }
+ bool ParseRadianProperty(IPropertyParser &inParser, const char8_t *inName, QT3DSF32 &ioRotation)
+ {
+ if (ParseProperty(inParser, inName, ioRotation)) {
+ TORAD(ioRotation);
+ return true;
+ }
+ return false;
+ }
+
+ void ParseRotationOrder(IPropertyParser &inParser, const char8_t *inName,
+ QT3DSU32 &ioRotationOrder)
+ {
+ if (ParseProperty(inParser, inName, m_TempParseString))
+ ioRotationOrder = uic::render::MapRotationOrder(m_TempParseString.c_str());
+ }
+ void ParseOrientation(IPropertyParser &inParser, const char8_t *inName, NodeFlags &ioFlags)
+ {
+ if (ParseProperty(inParser, inName, m_TempParseString)) {
+ if (m_TempParseString == "Left Handed")
+ ioFlags.SetLeftHanded(true);
+ else
+ ioFlags.SetLeftHanded(false);
+ }
+ }
+ void ParseOrthographicProperty(IPropertyParser &inParser, const char8_t *inName,
+ NodeFlags &ioFlags)
+ {
+ bool isOrthographic;
+ if (ParseProperty(inParser, inName, isOrthographic))
+ ioFlags.SetOrthographic(isOrthographic);
+ }
+ template <typename TEnumType>
+ static bool ConvertEnumFromStr(const char8_t *inStr, TEnumType &ioEnum)
+ {
+ uic::render::SEnumNameMap *theMap = uic::render::SEnumParseMap<TEnumType>::GetMap();
+ for (uic::render::SEnumNameMap *item = theMap; item->m_Name; ++item) {
+ if (UICDM::AreEqual(inStr, item->m_Name)) {
+ ioEnum = static_cast<TEnumType>(item->m_Enum);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <typename TEnumType>
+ void ParseEnumProperty(IPropertyParser &inParser, const char8_t *inName, TEnumType &ioEnum)
+ {
+ if (ParseProperty(inParser, inName, m_TempParseString)) {
+ ConvertEnumFromStr(m_TempParseString.c_str(), ioEnum);
+ }
+ }
+ void ParseAndResolveSourcePath(IPropertyParser &inParser, const char8_t *inName,
+ CRegisteredString &ioString)
+ {
+ if (ParseProperty(inParser, inName, m_TempParseString))
+ ioString = m_StrTable.RegisterStr(m_TempParseString.c_str());
+ }
+ void ParseProperty(IPropertyParser &inParser, const char8_t *inName, SImage *&ioImage)
+ {
+ if (ParseProperty(inParser, inName, m_TempParseString)) {
+ TIdObjectMap::iterator theIter =
+ m_ObjectMap.find(m_StrTable.RegisterStr(m_TempParseString.c_str() + 1));
+ if (theIter != m_ObjectMap.end()
+ && theIter->second->m_Type == GraphObjectTypes::Image) {
+ ioImage = static_cast<SImage *>(theIter->second);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ void ParseProperty(IPropertyParser &inParser, const char8_t *inName, CRegisteredString &ioStr)
+ {
+ if (ParseProperty(inParser, inName, m_TempParseString))
+ ioStr = m_StrTable.RegisterStr(m_TempParseString.c_str());
+ }
+
+ void ParseNodeFlagsProperty(IPropertyParser &inParser, const char8_t *inName,
+ uic::render::NodeFlags &ioFlags,
+ uic::render::NodeFlagValues::Enum prop)
+ {
+ bool temp;
+ if (ParseProperty(inParser, inName, temp))
+ ioFlags.ClearOrSet(temp, prop);
+ }
+
+ void ParseNodeFlagsInverseProperty(IPropertyParser &inParser, const char8_t *inName,
+ uic::render::NodeFlags &ioFlags,
+ uic::render::NodeFlagValues::Enum prop)
+ {
+ bool temp;
+ if (ParseProperty(inParser, inName, temp))
+ ioFlags.ClearOrSet(!temp, prop);
+ }
+
+// Create a mapping from UICRenderPropertyNames to the string in the UIP file.
+#define Scene_ClearColor "backgroundcolor"
+#define Scene_UseClearColor "bgcolorenable"
+#define Node_Rotation "rotation"
+#define Node_Position "position"
+#define Node_Scale "scale"
+#define Node_Pivot "pivot"
+#define Node_LocalOpacity "opacity"
+#define Node_RotationOrder "rotationorder"
+#define Node_LeftHanded "orientation"
+#define Layer_TemporalAAEnabled "temporalaa"
+#define Layer_LayerEnableDepthTest "disabledepthtest"
+#define Layer_LayerEnableDepthPrePass "disabledepthprepass"
+#define Layer_ClearColor "backgroundcolor"
+#define Layer_Background "background"
+#define Layer_BlendType "blendtype"
+#define Layer_Size "size"
+#define Layer_Location "location"
+#define Layer_TexturePath "sourcepath"
+#define Layer_HorizontalFieldValues "horzfields"
+#define Layer_Left "left"
+#define Layer_LeftUnits "leftunits"
+#define Layer_Width "width"
+#define Layer_WidthUnits "widthunits"
+#define Layer_Right "right"
+#define Layer_RightUnits "rightunits"
+#define Layer_VerticalFieldValues "vertfields"
+#define Layer_Top "top"
+#define Layer_TopUnits "topunits"
+#define Layer_Height "height"
+#define Layer_HeightUnits "heightunits"
+#define Layer_Bottom "bottom"
+#define Layer_BottomUnits "bottomunits"
+#define Layer_AoStrength "aostrength"
+#define Layer_AoDistance "aodistance"
+#define Layer_AoSoftness "aosoftness"
+#define Layer_AoBias "aobias"
+#define Layer_AoSamplerate "aosamplerate"
+#define Layer_AoDither "aodither"
+#define Layer_ShadowStrength "shadowstrength"
+#define Layer_ShadowDist "shadowdist"
+#define Layer_ShadowSoftness "shadowsoftness"
+#define Layer_ShadowBias "shadowbias"
+#define Layer_LightProbe "lightprobe"
+#define Layer_ProbeBright "probebright"
+#define Layer_FastIbl "fastibl"
+#define Layer_ProbeHorizon "probehorizon"
+#define Layer_ProbeFov "probefov"
+#define Layer_LightProbe2 "lightprobe2"
+#define Layer_Probe2Fade "probe2fade"
+#define Layer_Probe2Window "probe2window"
+#define Layer_Probe2Pos "probe2pos"
+#define Camera_ClipNear "clipnear"
+#define Camera_ClipFar "clipfar"
+#define Camera_FOV "fov"
+#define Camera_Orthographic "orthographic"
+#define Camera_ScaleMode "scalemode"
+#define Camera_ScaleAnchor "scaleanchor"
+#define Light_LightType "lighttype"
+#define Light_DiffuseColor "lightdiffuse"
+#define Light_SpecularColor "lightspecular"
+#define Light_AmbientColor "lightambient"
+#define Light_Brightness "brightness"
+#define Light_LinearFade "linearfade"
+#define Light_ExponentialFade "expfade"
+#define Light_AreaWidth "areawidth"
+#define Light_AreaHeight "areaheight"
+#define Light_CastShadow "castshadow"
+#define Light_ShadowBias "shdwbias"
+#define Light_ShadowFactor "shdwfactor"
+#define Light_ShadowMapRes "shdwmapres"
+#define Light_ShadowMapFar "shdwmapfar"
+#define Light_ShadowFilter "shdwfilter"
+#define Model_MeshPath "sourcepath"
+#define Model_TessellationMode "tessellation"
+#define Model_EdgeTess "edgetess"
+#define Model_InnerTess "innertess"
+#define Lightmaps_LightmapIndirect "lightmapindirect"
+#define Lightmaps_LightmapRadiosity "lightmapradiosity"
+#define Lightmaps_LightmapShadow "lightmapshadow"
+#define Material_Lighting "shaderlighting"
+#define Material_BlendMode "blendmode"
+#define MaterialBase_IblProbe "iblprobe"
+#define Material_DiffuseColor "diffuse"
+#define Material_DiffuseMaps_0 "diffusemap"
+#define Material_DiffuseMaps_1 "diffusemap2"
+#define Material_DiffuseMaps_2 "diffusemap3"
+#define Material_EmissivePower "emissivepower"
+#define Material_EmissiveColor "emissivecolor"
+#define Material_EmissiveMap "emissivemap"
+#define Material_EmissiveMap2 "emissivemap2"
+#define Material_SpecularReflection "specularreflection"
+#define Material_SpecularMap "specularmap"
+#define Material_SpecularModel "specularmodel"
+#define Material_SpecularTint "speculartint"
+#define Material_IOR "ior"
+#define Material_FresnelPower "fresnelPower"
+#define Material_SpecularAmount "specularamount"
+#define Material_SpecularRoughness "specularroughness"
+#define Material_Opacity "opacity"
+#define Material_OpacityMap "opacitymap"
+#define Material_BumpMap "bumpmap"
+#define Material_BumpAmount "bumpamount"
+#define Material_NormalMap "normalmap"
+#define Material_DisplacementMap "displacementmap"
+#define Material_DisplaceAmount "displaceamount"
+#define Material_TranslucencyMap "translucencymap"
+#define Material_TranslucentFalloff "translucentfalloff"
+#define Material_DiffuseLightWrap "diffuselightwrap"
+#define Material_ReferencedMaterial "referencedmaterial"
+#define Image_ImagePath "sourcepath"
+#define Image_OffscreenRendererId "subpresentation"
+#define Image_Scale_X "scaleu"
+#define Image_Scale_Y "scalev"
+#define Image_Pivot_X "pivotu"
+#define Image_Pivot_Y "pivotv"
+#define Image_Rotation "rotationuv"
+#define Image_Position_X "positionu"
+#define Image_Position_Y "positionv"
+#define Image_MappingMode "mappingmode"
+#define Image_HorizontalTilingMode "tilingmodehorz"
+#define Image_VerticalTilingMode "tilingmodevert"
+#define Text_Text "textstring"
+#define Text_Font "font"
+#define Text_FontSize "size"
+#define Text_HorizontalAlignment "horzalign"
+#define Text_VerticalAlignment "vertalign"
+#define Text_Leading "leading"
+#define Text_Tracking "tracking"
+#define Text_TextColor "textcolor"
+#define Text_BackColor "backcolor"
+#define Text_EnableAcceleratedFont "enableacceleratedfont"
+#define Layer_ProgressiveAAMode "progressiveaa"
+#define Layer_MultisampleAAMode "multisampleaa"
+#define Light_Scope "scope"
+#define Path_PathType "pathtype"
+#define Path_PaintStyle "paintstyle"
+#define Path_Width "width"
+#define Path_Opacity "opacity"
+#define Path_LinearError "linearerror"
+#define Path_EdgeTessAmount "edgetessamount"
+#define Path_InnerTessAmount "innertessamount"
+#define Path_BeginCapping "begincap"
+#define Path_BeginCapOffset "begincapoffset"
+#define Path_BeginCapOpacity "begincapopacity"
+#define Path_BeginCapWidth "begincapwidth"
+#define Path_EndCapping "endcap"
+#define Path_EndCapOffset "endcapoffset"
+#define Path_EndCapOpacity "endcapopacity"
+#define Path_EndCapWidth "endcapwidth"
+#define Path_PathBuffer "sourcepath"
+#define SubPath_Closed "closed"
+
+// Fill in implementations for the actual parse tables.
+#define HANDLE_UIC_RENDER_PROPERTY(type, name, dirty) \
+ ParseProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_REAL_VEC2_PROPERTY(type, name, dirty) \
+ ParseProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_VEC3_PROPERTY(type, name, dirty) \
+ ParseProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_COLOR_PROPERTY(type, name, dirty) \
+ ParseProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_RADIAN_PROPERTY(type, name, dirty) \
+ ParseRadianProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_VEC3_RADIAN_PROPERTY(type, name, dirty) \
+ ParseRadianProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_OPACITY_PROPERTY(type, name, dirty) \
+ ParseOpacityProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_ROTATION_ORDER_PROPERTY(type, name, dirty) \
+ ParseRotationOrder(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_NODE_ORIENTATION_PROPERTY(type, name, dirty) \
+ ParseOrientation(inParser, type##_##name, inItem.m_Flags);
+#define HANDLE_UIC_RENDER_DEPTH_TEST_PROPERTY(type, name, dirty) \
+ if (ParseProperty(inParser, type##_##name, inItem.m_##name)) \
+ inItem.m_##name = !inItem.m_##name;
+#define HANDLE_UIC_NODE_FLAGS_PROPERTY(type, name, dirty) \
+ ParseNodeFlagsProperty(inParser, type##_##name, inItem.m_Flags, \
+ uic::render::NodeFlagValues::name);
+#define HANDLE_UIC_NODE_FLAGS_INVERSE_PROPERTY(type, name, dirty) \
+ ParseNodeFlagsInverseProperty(inParser, type##_##name, inItem.m_Flags, \
+ uic::render::NodeFlagValues::name);
+#define HANDLE_UIC_RENDER_ENUM_PROPERTY(type, name, dirty) \
+ ParseEnumProperty(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY(type, name, dirty) \
+ ParseAndResolveSourcePath(inParser, type##_##name, inItem.m_##name);
+#define HANDLE_UIC_RENDER_ARRAY_PROPERTY(type, name, index, dirty) \
+ ParseProperty(inParser, type##_##name##_##index, inItem.m_##name[index]);
+#define HANDLE_UIC_RENDER_VEC2_PROPERTY(type, name, dirty) \
+ ParseProperty(inParser, type##_##name##_##X, inItem.m_##name.x); \
+ ParseProperty(inParser, type##_##name##_##Y, inItem.m_##name.y);
+#define HANDLE_UIC_RENDER_COLOR_VEC3_PROPERTY( \
+ type, name, dirty) // noop by intention already handled by HANDLE_UIC_RENDER_COLOR_PROPERTY
+#define HANDLE_UIC_RENDER_TRANSFORM_VEC3_PROPERTY( \
+ type, name, dirty) // noop by intention already handled by HANDLE_UIC_RENDER_VEC3_PROPERTY
+
+ // Call the correct parser functions.
+ void ParseProperties(SScene &inItem, IPropertyParser &inParser)
+ {
+ ITERATE_UIC_RENDER_SCENE_PROPERTIES
+ }
+ void ParseProperties(SNode &inItem, IPropertyParser &inParser)
+ {
+ bool eyeball;
+ if (ParseProperty(inParser, "eyeball", eyeball))
+ inItem.m_Flags.SetActive(eyeball);
+ ITERATE_UIC_RENDER_NODE_PROPERTIES
+ ParseProperty(inParser, "boneid", inItem.m_SkeletonId);
+ bool ignoreParent = false;
+ if (ParseProperty(inParser, "ignoresparent", ignoreParent))
+ inItem.m_Flags.SetIgnoreParentTransform(ignoreParent);
+ }
+ void ParseProperties(SLayer &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SNode &>(inItem), inParser);
+ ITERATE_UIC_RENDER_LAYER_PROPERTIES
+ ParseProperty(inParser, "aosamplerate", inItem.m_AoSamplerate);
+ }
+ void ParseProperties(SCamera &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SNode &>(inItem), inParser);
+ ITERATE_UIC_RENDER_CAMERA_PROPERTIES
+ }
+ void ParseProperties(SLight &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SNode &>(inItem), inParser);
+ ITERATE_UIC_RENDER_LIGHT_PROPERTIES
+ ParseProperty(inParser, "shdwmapres", inItem.m_ShadowMapRes);
+ }
+ void ParseProperties(SModel &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SNode &>(inItem), inParser);
+ ITERATE_UIC_RENDER_MODEL_PROPERTIES
+ ParseProperty(inParser, "poseroot", inItem.m_SkeletonRoot);
+ }
+
+ void ParseProperties(SText &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SNode &>(inItem), inParser);
+ ITERATE_UIC_RENDER_TEXT_PROPERTIES
+ }
+ void ParseProperties(SLightmaps &inItem, IPropertyParser &inParser)
+ {
+ ITERATE_UIC_RENDER_LIGHTMAP_PROPERTIES
+ }
+ void ParseProperties(SDefaultMaterial &inItem, IPropertyParser &inParser)
+ {
+ ITERATE_UIC_RENDER_MATERIAL_PROPERTIES
+ ParseProperties(inItem.m_Lightmaps, inParser);
+ }
+ void ParseProperties(SReferencedMaterial &inItem, IPropertyParser &inParser)
+ {
+ ITERATE_UIC_RENDER_REFERENCED_MATERIAL_PROPERTIES
+ // Propagate lightmaps
+ if (inItem.m_ReferencedMaterial
+ && inItem.m_ReferencedMaterial->m_Type == GraphObjectTypes::DefaultMaterial)
+ ParseProperties(
+ static_cast<SDefaultMaterial *>(inItem.m_ReferencedMaterial)->m_Lightmaps,
+ inParser);
+ else if (inItem.m_ReferencedMaterial
+ && inItem.m_ReferencedMaterial->m_Type == GraphObjectTypes::CustomMaterial)
+ ParseProperties(
+ static_cast<SCustomMaterial *>(inItem.m_ReferencedMaterial)->m_Lightmaps, inParser);
+ }
+ void ParseProperties(SImage &inItem, IPropertyParser &inParser)
+ {
+ ITERATE_UIC_RENDER_IMAGE_PROPERTIES
+ }
+ template <typename TDataType>
+ void SetDynamicObjectProperty(SDynamicObject &inEffect,
+ const uic::render::dynamic::SPropertyDefinition &inPropDesc,
+ const TDataType &inProp)
+ {
+ memCopy(inEffect.GetDataSectionBegin() + inPropDesc.m_Offset, &inProp, sizeof(TDataType));
+ }
+ template <typename TDataType>
+ void SetDynamicObjectProperty(SDynamicObject &inEffect,
+ const uic::render::dynamic::SPropertyDefinition &inPropDesc,
+ Option<TDataType> inProp)
+ {
+ if (inProp.hasValue()) {
+ SetDynamicObjectProperty(inEffect, inPropDesc, *inProp);
+ }
+ }
+ void ParseProperties(SCustomMaterial &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SDynamicObject &>(inItem), inParser);
+ ParseProperties(inItem.m_Lightmaps, inParser);
+ ITERATE_UIC_RENDER_CUSTOM_MATERIAL_PROPERTIES
+ }
+ void ParseProperties(SDynamicObject &inDynamicObject, IPropertyParser &inParser)
+ {
+ NVConstDataRef<uic::render::dynamic::SPropertyDefinition> theProperties =
+ m_DynamicObjectSystem.GetProperties(inDynamicObject.m_ClassName);
+
+ for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
+ const uic::render::dynamic::SPropertyDefinition &theDefinition(theProperties[idx]);
+ switch (theDefinition.m_DataType) {
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool:
+ SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ inParser.ParseBool(theDefinition.m_Name));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32:
+ SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ inParser.ParseFloat(theDefinition.m_Name));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32:
+ if (theDefinition.m_IsEnumProperty == false)
+ SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ inParser.ParseU32(theDefinition.m_Name));
+ else {
+ Option<eastl::string> theEnum = inParser.ParseStr(theDefinition.m_Name);
+ if (theEnum.hasValue()) {
+ NVConstDataRef<CRegisteredString> theEnumNames =
+ theDefinition.m_EnumValueNames;
+ for (QT3DSU32 idx = 0, end = theEnumNames.size(); idx < end; ++idx) {
+ if (theEnum->compare(theEnumNames[idx].c_str()) == 0) {
+ SetDynamicObjectProperty(inDynamicObject, theDefinition, idx);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3:
+ SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ inParser.ParseVec3(theDefinition.m_Name));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2:
+ SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ inParser.ParseVec2(theDefinition.m_Name));
+ break;
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr:
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr: {
+ Option<eastl::string> theTexture = inParser.ParseStr(theDefinition.m_Name);
+ if (theTexture.hasValue()) {
+ CRegisteredString theStr;
+ if (theTexture->size())
+ theStr = m_StrTable.RegisterStr(theTexture->c_str());
+
+ SetDynamicObjectProperty(inDynamicObject, theDefinition, theStr);
+ }
+ } break;
+ case qt3ds::render::NVRenderShaderDataTypes::NVRenderDataBufferPtr:
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+ void ParseProperties(SPath &inItem, IPropertyParser &inParser)
+ {
+ ParseProperties(static_cast<SNode &>(inItem), inParser);
+ ITERATE_UIC_RENDER_PATH_PROPERTIES
+ }
+ void ParseProperties(SPathSubPath &inItem, IPropertyParser &inParser)
+ {
+ ITERATE_UIC_RENDER_PATH_SUBPATH_PROPERTIES
+ }
+
+ void AddPluginPropertyUpdate(eastl::vector<uic::render::SRenderPropertyValueUpdate> &ioUpdates,
+ uic::render::IRenderPluginClass &,
+ const uic::render::SRenderPluginPropertyDeclaration &inDeclaration,
+ Option<float> data)
+ {
+ if (data.hasValue()) {
+ ioUpdates.push_back(
+ uic::render::SRenderPropertyValueUpdate(inDeclaration.m_Name, *data));
+ }
+ }
+ void AddPluginPropertyUpdate(eastl::vector<uic::render::SRenderPropertyValueUpdate> &ioUpdates,
+ uic::render::IRenderPluginClass &inClass,
+ const uic::render::SRenderPluginPropertyDeclaration &inDeclaration,
+ Option<QT3DSVec2> data)
+ {
+ if (data.hasValue()) {
+ ioUpdates.push_back(uic::render::SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(inDeclaration.m_StartOffset).first, data->x));
+ ioUpdates.push_back(uic::render::SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(inDeclaration.m_StartOffset + 1).first, data->y));
+ }
+ }
+ void AddPluginPropertyUpdate(eastl::vector<uic::render::SRenderPropertyValueUpdate> &ioUpdates,
+ uic::render::IRenderPluginClass &inClass,
+ const uic::render::SRenderPluginPropertyDeclaration &inDeclaration,
+ Option<QT3DSVec3> data)
+ {
+ if (data.hasValue()) {
+ ioUpdates.push_back(uic::render::SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(inDeclaration.m_StartOffset).first, data->x));
+ ioUpdates.push_back(uic::render::SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(inDeclaration.m_StartOffset + 1).first, data->y));
+ ioUpdates.push_back(uic::render::SRenderPropertyValueUpdate(
+ inClass.GetPropertyValueInfo(inDeclaration.m_StartOffset + 2).first, data->z));
+ }
+ }
+ void AddPluginPropertyUpdate(eastl::vector<uic::render::SRenderPropertyValueUpdate> &ioUpdates,
+ uic::render::IRenderPluginClass &,
+ const uic::render::SRenderPluginPropertyDeclaration &inDeclaration,
+ Option<qt3ds::QT3DSI32> dataOpt)
+ {
+ if (dataOpt.hasValue()) {
+ long data = static_cast<long>(*dataOpt);
+ ioUpdates.push_back(
+ uic::render::SRenderPropertyValueUpdate(inDeclaration.m_Name, (QT3DSI32)data));
+ }
+ }
+ void AddPluginPropertyUpdate(eastl::vector<uic::render::SRenderPropertyValueUpdate> &ioUpdates,
+ uic::render::IRenderPluginClass &,
+ const uic::render::SRenderPluginPropertyDeclaration &inDeclaration,
+ Option<eastl::string> dataOpt)
+ {
+ if (dataOpt.hasValue()) {
+ eastl::string &data = dataOpt.getValue();
+ ioUpdates.push_back(uic::render::SRenderPropertyValueUpdate(
+ inDeclaration.m_Name, m_StrTable.RegisterStr(data.c_str())));
+ }
+ }
+ void AddPluginPropertyUpdate(eastl::vector<uic::render::SRenderPropertyValueUpdate> &ioUpdates,
+ uic::render::IRenderPluginClass &,
+ const uic::render::SRenderPluginPropertyDeclaration &inDeclaration,
+ Option<bool> dataOpt)
+ {
+ if (dataOpt.hasValue()) {
+ bool &data = dataOpt.getValue();
+ ioUpdates.push_back(
+ uic::render::SRenderPropertyValueUpdate(inDeclaration.m_Name, data));
+ }
+ }
+ void ParseProperties(uic::render::SRenderPlugin &inRenderPlugin, IPropertyParser &inParser)
+ {
+ uic::render::IRenderPluginClass *theClass =
+ m_RenderPluginManager.GetRenderPlugin(inRenderPlugin.m_PluginPath);
+ if (theClass) {
+ qt3ds::foundation::NVConstDataRef<uic::render::SRenderPluginPropertyDeclaration>
+ theClassProps = theClass->GetRegisteredProperties();
+ if (theClassProps.size()) {
+ uic::render::IRenderPluginInstance *theInstance =
+ m_RenderPluginManager.GetOrCreateRenderPluginInstance(
+ inRenderPlugin.m_PluginPath, &inRenderPlugin);
+ if (theInstance) {
+ eastl::vector<uic::render::SRenderPropertyValueUpdate> theUpdates;
+ for (QT3DSU32 idx = 0, end = theClassProps.size(); idx < end; ++idx) {
+ const uic::render::SRenderPluginPropertyDeclaration &theDec(
+ theClassProps[idx]);
+ eastl::string tempStr;
+ switch (theDec.m_Type) {
+ case uic::render::SRenderPluginPropertyTypes::Float:
+ AddPluginPropertyUpdate(theUpdates, *theClass, theDec,
+ inParser.ParseFloat(theDec.m_Name.c_str()));
+ break;
+ case uic::render::SRenderPluginPropertyTypes::Vector2:
+ AddPluginPropertyUpdate(theUpdates, *theClass, theDec,
+ inParser.ParseVec2(theDec.m_Name.c_str()));
+ break;
+ case uic::render::SRenderPluginPropertyTypes::Color:
+ case uic::render::SRenderPluginPropertyTypes::Vector3:
+ AddPluginPropertyUpdate(theUpdates, *theClass, theDec,
+ inParser.ParseVec3(theDec.m_Name.c_str()));
+ break;
+ case uic::render::SRenderPluginPropertyTypes::Long:
+ AddPluginPropertyUpdate(theUpdates, *theClass, theDec,
+ inParser.ParseI32(theDec.m_Name.c_str()));
+ break;
+ case uic::render::SRenderPluginPropertyTypes::String:
+ AddPluginPropertyUpdate(theUpdates, *theClass, theDec,
+ inParser.ParseStr(theDec.m_Name.c_str()));
+ break;
+ case uic::render::SRenderPluginPropertyTypes::Boolean:
+ AddPluginPropertyUpdate(theUpdates, *theClass, theDec,
+ inParser.ParseBool(theDec.m_Name.c_str()));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ }
+ theInstance->Update(
+ qt3ds::foundation::toConstDataRef(theUpdates.data(), theUpdates.size()));
+ }
+ }
+ }
+ }
+
+#undef HANDLE_UIC_RENDER_PROPERTY
+#undef HANDLE_UIC_RENDER_ENUM_PROPERTY
+#undef HANDLE_UIC_RENDER_RADIAN_PROPERTY
+#undef HANDLE_UIC_RENDER_SOURCEPATH_PROPERTY
+#undef HANDLE_UIC_RENDER_ARRAY_PROPERTY
+#undef HANDLE_UIC_NODE_FLAGS_PROPERTY
+#undef HANDLE_UIC_ROTATION_ORDER_PROPERTY
+#undef HANDLE_UIC_RENDER_OPACITY_PROPERTY
+#undef HANDLE_UIC_NODE_ORIENTATION_PROPERTY
+#undef HANDLE_UIC_RENDER_DEPTH_TEST_PROPERTY
+#undef HANDLE_UIC_RENDER_VEC2_PROPERTY
+
+ void ParseGraphPass1(SGraphObject *inParent)
+ {
+ TScope __elemScope(m_Reader);
+ UICDM::ComposerObjectTypes::Enum theObjType =
+ UICDM::ComposerObjectTypes::Convert(m_Reader.GetElementName());
+ SGraphObject *theNewObject(NULL);
+ const char8_t *theId;
+ m_Reader.Att("id", theId);
+
+ switch (theObjType) {
+ case UICDM::ComposerObjectTypes::Scene: {
+ SScene *theScene = QT3DS_NEW(m_PresentationAllocator, SScene)();
+ theNewObject = theScene;
+ m_Presentation->m_Scene = theScene;
+ theScene->m_Presentation = m_Presentation;
+ } break;
+ case UICDM::ComposerObjectTypes::Layer:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SLayer)();
+ break;
+ case UICDM::ComposerObjectTypes::Group:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)();
+ break;
+ case UICDM::ComposerObjectTypes::Component:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)();
+ break;
+ case UICDM::ComposerObjectTypes::Camera:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SCamera)();
+ break;
+ case UICDM::ComposerObjectTypes::Light:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SLight)();
+ break;
+ case UICDM::ComposerObjectTypes::Model:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SModel)();
+ break;
+ case UICDM::ComposerObjectTypes::Material:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SDefaultMaterial)();
+ break;
+ case UICDM::ComposerObjectTypes::ReferencedMaterial:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SReferencedMaterial)();
+ break;
+ case UICDM::ComposerObjectTypes::Image:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SImage)();
+ break;
+ case UICDM::ComposerObjectTypes::Text:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SText)();
+ break;
+ case UICDM::ComposerObjectTypes::Path:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SPath)();
+ break;
+ case UICDM::ComposerObjectTypes::SubPath: {
+ SPathSubPath *thePath = QT3DS_NEW(m_PresentationAllocator, SPathSubPath)();
+ theNewObject = thePath;
+ QT3DSU32 anchorCount = 0;
+ TScope _childScope(m_Reader);
+ for (bool success = m_Reader.MoveToFirstChild("PathAnchorPoint"); success;
+ success = m_Reader.MoveToNextSibling("PathAnchorPoint")) {
+ const char8_t *theId;
+ m_Reader.Att("id", theId);
+ CRegisteredString theIdStr = m_StrTable.RegisterStr(theId);
+ m_AnchorIdToPathAndAnchorIndexMap.insert(
+ eastl::make_pair(theIdStr, SPathAndAnchorIndex(thePath, anchorCount)));
+ ++anchorCount;
+ }
+ m_PathManager.ResizePathSubPathBuffer(*thePath, anchorCount);
+ } break;
+ case UICDM::ComposerObjectTypes::Effect: {
+ const char8_t *effectClassId;
+ m_Reader.Att("class", effectClassId);
+ CRegisteredString theStr = m_StrTable.RegisterStr(effectClassId + 1);
+ if (m_EffectSystem.IsEffectRegistered(theStr))
+ theNewObject = m_EffectSystem.CreateEffectInstance(theStr, m_PresentationAllocator);
+ } break;
+ case UICDM::ComposerObjectTypes::RenderPlugin: {
+ const char8_t *classId;
+ m_Reader.Att("class", classId);
+ if (!qt3ds::foundation::isTrivial(classId)) {
+ ++classId;
+ TIdStringMap::iterator iter =
+ m_RenderPluginSourcePaths.find(m_StrTable.RegisterStr(classId));
+ if (iter != m_RenderPluginSourcePaths.end()) {
+ CRegisteredString thePluginPath = m_StrTable.RegisterStr(iter->second.c_str());
+ uic::render::IRenderPluginClass *theClass =
+ m_RenderPluginManager.GetRenderPlugin(thePluginPath);
+ if (theClass) {
+ uic::render::SRenderPlugin *thePlugin =
+ QT3DS_NEW(m_PresentationAllocator, uic::render::SRenderPlugin)();
+ thePlugin->m_PluginPath = thePluginPath;
+ thePlugin->m_Flags.SetActive(true);
+ theNewObject = thePlugin;
+ }
+ }
+ }
+ } break;
+ case UICDM::ComposerObjectTypes::CustomMaterial: {
+ const char8_t *materialClassId;
+ m_Reader.Att("class", materialClassId);
+ CRegisteredString theStr = m_StrTable.RegisterStr(materialClassId + 1);
+ if (m_CustomMaterialSystem.IsMaterialRegistered(theStr))
+ theNewObject =
+ m_CustomMaterialSystem.CreateCustomMaterial(theStr, m_PresentationAllocator);
+ } break;
+ default:
+ // Ignoring unknown objects entirely at this point
+ break;
+ }
+ if (theNewObject) {
+ CRegisteredString theObjectId(m_StrTable.RegisterStr(theId));
+ m_ObjectMap.insert(eastl::make_pair(theObjectId, theNewObject));
+ theNewObject->m_Id = theObjectId;
+ // setup hierarchy
+ bool isParentNode;
+ bool isChildNode;
+ if (inParent) {
+ switch (inParent->m_Type) {
+ case GraphObjectTypes::Scene:
+ if (theNewObject->m_Type == GraphObjectTypes::Layer) {
+ static_cast<SScene *>(inParent)->AddChild(
+ *static_cast<SLayer *>(theNewObject));
+ } else {
+ // Something added to a scene that was not a layer.
+ QT3DS_ASSERT(false);
+ }
+ break;
+
+ case GraphObjectTypes::DefaultMaterial:
+ if (theNewObject->m_Type != GraphObjectTypes::Image) {
+ // Something added to a material that is not an image...
+ // how odd.
+ QT3DS_ASSERT(false);
+ } else {
+ static_cast<SImage *>(theNewObject)->m_Parent =
+ static_cast<SDefaultMaterial *>(inParent);
+ eastl::string thePath = eastl::string(theNewObject->m_Id.c_str());
+ if (thePath.find("probe") != eastl::string::npos)
+ static_cast<SImage *>(theNewObject)->m_MappingMode =
+ ImageMappingModes::LightProbe;
+ }
+ break;
+
+ case GraphObjectTypes::CustomMaterial:
+ if (theNewObject->m_Type == GraphObjectTypes::Image) {
+ static_cast<SImage *>(theNewObject)->m_Parent =
+ static_cast<SCustomMaterial *>(inParent);
+ eastl::string thePath = eastl::string(theNewObject->m_Id.c_str());
+ if (thePath.find("probe") != eastl::string::npos) {
+ static_cast<SImage *>(theNewObject)->m_MappingMode =
+ ImageMappingModes::LightProbe;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case GraphObjectTypes::ReferencedMaterial:
+ if (theNewObject->m_Type == GraphObjectTypes::Image) {
+ // nothing to do yet
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ break;
+ case GraphObjectTypes::Path:
+
+ if (GraphObjectTypes::IsMaterialType(theNewObject->m_Type))
+ static_cast<SPath *>(inParent)->AddMaterial(theNewObject);
+
+ else if (theNewObject->m_Type == GraphObjectTypes::PathSubPath)
+ static_cast<SPath *>(inParent)->AddSubPath(
+ *static_cast<SPathSubPath *>(theNewObject));
+
+ break;
+
+ default:
+ isParentNode = IsNode(inParent->m_Type);
+ isChildNode = IsNode(theNewObject->m_Type);
+ if (isParentNode && isChildNode) {
+ static_cast<SNode *>(inParent)->AddChild(
+ *static_cast<SNode *>(theNewObject));
+ } else if (isParentNode) {
+ if (inParent->m_Type == GraphObjectTypes::Model
+ && IsMaterial(theNewObject)) {
+ static_cast<SModel *>(inParent)->AddMaterial(*theNewObject);
+ } else {
+ if (inParent->m_Type == GraphObjectTypes::Layer
+ && theNewObject->m_Type == GraphObjectTypes::Effect) {
+ static_cast<SLayer *>(inParent)->AddEffect(
+ *static_cast<SEffect *>(theNewObject));
+ } else if (inParent->m_Type == GraphObjectTypes::Layer
+ && theNewObject->m_Type == GraphObjectTypes::Image) {
+ eastl::string thePath = eastl::string(theNewObject->m_Id.c_str());
+ if (thePath.find("probe2") != eastl::string::npos) {
+ static_cast<SLayer *>(inParent)->m_LightProbe2 =
+ static_cast<SImage *>(theNewObject);
+ } else {
+ static_cast<SLayer *>(inParent)->m_LightProbe =
+ static_cast<SImage *>(theNewObject);
+ }
+ } else {
+ if (theNewObject->m_Type == GraphObjectTypes::RenderPlugin) {
+ uic::render::SRenderPlugin *childObj =
+ static_cast<uic::render::SRenderPlugin *>(theNewObject);
+ if (inParent->m_Type == GraphObjectTypes::Layer) {
+ static_cast<SLayer *>(inParent)->m_RenderPlugin = childObj;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ } else {
+ if (inParent->m_Type == GraphObjectTypes::Image
+ && theNewObject->m_Type == GraphObjectTypes::RenderPlugin) {
+ static_cast<SImage *>(inParent)->m_RenderPlugin =
+ static_cast<uic::render::SRenderPlugin *>(theNewObject);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+ for (bool valid = m_Reader.MoveToFirstChild(); valid;
+ valid = m_Reader.MoveToNextSibling())
+ ParseGraphPass1(theNewObject);
+ } else {
+ for (bool valid = m_Reader.MoveToFirstChild(); valid;
+ valid = m_Reader.MoveToNextSibling())
+ ParseGraphPass1(NULL);
+ }
+ }
+
+ template <typename TObjType>
+ void ParsePass2Properties(TObjType &inObject, const char8_t *inClassId)
+ {
+ const char8_t *theTypeName = m_Reader.GetNarrowElementName();
+ SMetaPropertyParser theMetaParser(theTypeName, inClassId, m_MetaData);
+ // Set default values
+ ParseProperties(inObject, theMetaParser);
+
+ // Now setup property values from the element itself.
+ SDomReaderPropertyParser theReaderParser(m_Reader, m_TempBuf, *this, inObject);
+ ParseProperties(inObject, theReaderParser);
+ }
+
+ // Parse the instance properties from the graph.
+ void ParseGraphPass2()
+ {
+ TScope __instanceScope(m_Reader);
+ const char8_t *theId;
+ m_Reader.Att("id", theId);
+ const char8_t *theClass = "";
+ m_Reader.Att("class", theClass);
+ TIdObjectMap::iterator theObject = m_ObjectMap.find(m_StrTable.RegisterStr(theId));
+ if (theObject != m_ObjectMap.end()) {
+ switch (theObject->second->m_Type) {
+ case GraphObjectTypes::Scene:
+ ParsePass2Properties(*static_cast<SScene *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Node:
+ ParsePass2Properties(*static_cast<SNode *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Layer:
+ ParsePass2Properties(*static_cast<SLayer *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Camera:
+ ParsePass2Properties(*static_cast<SCamera *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Light:
+ ParsePass2Properties(*static_cast<SLight *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Model:
+ ParsePass2Properties(*static_cast<SModel *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::DefaultMaterial:
+ ParsePass2Properties(*static_cast<SDefaultMaterial *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::ReferencedMaterial:
+ ParsePass2Properties(*static_cast<SReferencedMaterial *>(theObject->second),
+ theClass);
+ break;
+ case GraphObjectTypes::Image:
+ ParsePass2Properties(*static_cast<SImage *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Text:
+ ParsePass2Properties(*static_cast<SText *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Effect:
+ ParsePass2Properties(*static_cast<SEffect *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::RenderPlugin:
+ ParsePass2Properties(*static_cast<uic::render::SRenderPlugin *>(theObject->second),
+ theClass);
+ break;
+ case GraphObjectTypes::CustomMaterial:
+ ParsePass2Properties(*static_cast<SCustomMaterial *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::Path:
+ ParsePass2Properties(*static_cast<SPath *>(theObject->second), theClass);
+ break;
+ case GraphObjectTypes::PathSubPath:
+ ParsePass2Properties(*static_cast<SPathSubPath *>(theObject->second), theClass);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ for (bool valid = m_Reader.MoveToFirstChild(); valid; valid = m_Reader.MoveToNextSibling())
+ ParseGraphPass2();
+ }
+
+ static bool ParseVec2(SDomReaderPropertyParser &inParser, const char *inName, QT3DSVec2 &outValue)
+ {
+ Option<QT3DSVec2> result = inParser.ParseVec2(inName);
+
+ if (result.hasValue())
+ outValue = *result;
+
+ return result.hasValue();
+ }
+
+ static bool ParseFloat(SDomReaderPropertyParser &inParser, const char *inName, QT3DSF32 &outValue)
+ {
+ Option<QT3DSF32> result = inParser.ParseFloat(inName);
+ if (result.hasValue())
+ outValue = *result;
+ return result.hasValue();
+ }
+
+ void ParseState(bool inSetSetValues)
+ {
+ TScope __slideScope(m_Reader);
+ for (bool valid = m_Reader.MoveToFirstChild(); valid;
+ valid = m_Reader.MoveToNextSibling()) {
+ if (strcmp(m_Reader.GetNarrowElementName(), "Add") == 0
+ || (inSetSetValues && strcmp(m_Reader.GetNarrowElementName(), "Set") == 0)) {
+ const char8_t *theId;
+ m_Reader.Att("ref", theId);
+ CRegisteredString theIdStr(m_StrTable.RegisterStr(theId + 1));
+ TIdObjectMap::iterator theObject = m_ObjectMap.find(theIdStr);
+ if (theObject != m_ObjectMap.end()) {
+ SDomReaderPropertyParser parser(m_Reader, m_TempBuf, *this, *theObject->second);
+ switch (theObject->second->m_Type) {
+ case GraphObjectTypes::Scene:
+ ParseProperties(*reinterpret_cast<SScene *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Node:
+ ParseProperties(*reinterpret_cast<SNode *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Layer:
+ ParseProperties(*reinterpret_cast<SLayer *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Camera:
+ ParseProperties(*reinterpret_cast<SCamera *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Light:
+ ParseProperties(*reinterpret_cast<SLight *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Model:
+ ParseProperties(*reinterpret_cast<SModel *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::DefaultMaterial:
+ ParseProperties(*reinterpret_cast<SDefaultMaterial *>(theObject->second),
+ parser);
+ break;
+ case GraphObjectTypes::ReferencedMaterial:
+ ParseProperties(*static_cast<SReferencedMaterial *>(theObject->second),
+ parser);
+ break;
+ case GraphObjectTypes::Image:
+ ParseProperties(*reinterpret_cast<SImage *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Text:
+ ParseProperties(*static_cast<SText *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::Effect:
+ ParseProperties(*static_cast<SEffect *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::RenderPlugin:
+ ParseProperties(
+ *static_cast<uic::render::SRenderPlugin *>(theObject->second), parser);
+ break;
+ case GraphObjectTypes::CustomMaterial:
+ ParseProperties(
+ *static_cast<uic::render::SCustomMaterial *>(theObject->second),
+ parser);
+ break;
+ case GraphObjectTypes::Path:
+ ParseProperties(*static_cast<uic::render::SPath *>(theObject->second),
+ parser);
+ break;
+ case GraphObjectTypes::PathSubPath:
+ ParseProperties(
+ *static_cast<uic::render::SPathSubPath *>(theObject->second), parser);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ } else {
+ TIdPathAnchorIndexMap::iterator iter =
+ m_AnchorIdToPathAndAnchorIndexMap.find(theIdStr);
+ if (iter != m_AnchorIdToPathAndAnchorIndexMap.end()) {
+ SDomReaderPropertyParser parser(m_Reader, m_TempBuf, *this,
+ *iter->second.m_Segment);
+ NVDataRef<uic::render::SPathAnchorPoint> thePathBuffer =
+ m_PathManager.GetPathSubPathBuffer(*iter->second.m_Segment);
+ QT3DSU32 anchorIndex = iter->second.m_AnchorIndex;
+ QT3DSU32 numAnchors = thePathBuffer.size();
+ if (anchorIndex < numAnchors) {
+ uic::render::SPathAnchorPoint &thePoint(thePathBuffer[anchorIndex]);
+ ParseVec2(parser, "position", thePoint.m_Position);
+ ParseFloat(parser, "incomingangle", thePoint.m_IncomingAngle);
+ thePoint.m_OutgoingAngle = thePoint.m_IncomingAngle + 180.0f;
+ ParseFloat(parser, "incomingdistance", thePoint.m_IncomingDistance);
+ ParseFloat(parser, "outgoingdistance", thePoint.m_OutgoingDistance);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void AddPluginProperty(uic::render::IRenderPluginClass &pluginClass,
+ uic::render::SRenderPluginPropertyTypes::Enum inPropType,
+ eastl::string &tempStr, const char *propName)
+ {
+ tempStr.assign(propName);
+ uic::render::SRenderPluginPropertyDeclaration theDec(
+ m_StrTable.RegisterStr(tempStr.c_str()), inPropType);
+ pluginClass.RegisterProperty(theDec);
+ }
+
+ SPresentation *Load(bool inSetValuesFromSlides)
+ {
+ {
+ TScope __outerScope(m_Reader);
+ if (m_Reader.MoveToFirstChild("ProjectSettings")) {
+ m_Reader.Att("presentationWidth", m_Presentation->m_PresentationDimensions.x);
+ m_Reader.Att("presentationHeight", m_Presentation->m_PresentationDimensions.y);
+ // Upsize them to a multiple of four.
+ m_Presentation->m_PresentationDimensions.x =
+ (QT3DSF32)uic::render::ITextRenderer::NextMultipleOf4(
+ (QT3DSU32)m_Presentation->m_PresentationDimensions.x);
+ m_Presentation->m_PresentationDimensions.y =
+ (QT3DSF32)uic::render::ITextRenderer::NextMultipleOf4(
+ (QT3DSU32)m_Presentation->m_PresentationDimensions.y);
+ const char8_t *thePresentationRotation = "";
+ if (m_Reader.Att("presentationRotation", thePresentationRotation)) {
+ bool success = SRenderUIPLoader::ConvertEnumFromStr(
+ thePresentationRotation, m_Presentation->m_PresentationRotation);
+ (void)success;
+ QT3DS_ASSERT(success);
+ }
+ }
+ }
+ {
+ TScope __outerScope(m_Reader);
+ if (m_Reader.MoveToFirstChild("Classes")) {
+ for (bool valid = m_Reader.MoveToFirstChild(); valid;
+ valid = m_Reader.MoveToNextSibling()) {
+ const char8_t *idStr = "", *name = "", *sourcepath = "";
+ m_Reader.Att("id", idStr);
+ m_Reader.Att("name", name);
+ m_Reader.Att("sourcepath", sourcepath);
+ if (AreEqual(m_Reader.GetNarrowElementName(), "Effect")) {
+ CRegisteredString theId(m_StrTable.RegisterStr(idStr));
+ if (m_EffectSystem.IsEffectRegistered(theId) == false) {
+ // File should already be loaded.
+ Option<UICDM::SMetaDataEffect> theEffectMetaData =
+ m_MetaData.GetEffectMetaDataBySourcePath(sourcepath);
+ if (theEffectMetaData.hasValue()) {
+ uic::render::IUIPLoader::CreateEffectClassFromMetaEffect(
+ theId, m_Foundation, m_EffectSystem, *theEffectMetaData,
+ m_StrTable);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ } else if (AreEqual(m_Reader.GetNarrowElementName(), "CustomMaterial")) {
+ CRegisteredString theId(m_StrTable.RegisterStr(idStr));
+ if (m_CustomMaterialSystem.IsMaterialRegistered(theId) == false) {
+ // File should already be loaded.
+ Option<UICDM::SMetaDataCustomMaterial> theMetaData =
+ m_MetaData.GetMaterialMetaDataBySourcePath(sourcepath);
+ if (theMetaData.hasValue()) {
+ uic::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ theId, m_Foundation, m_CustomMaterialSystem, *theMetaData,
+ m_StrTable);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ } else if (AreEqual(m_Reader.GetNarrowElementName(), "RenderPlugin")) {
+ CRegisteredString theId(m_StrTable.RegisterStr(idStr));
+ m_MetaData.LoadPluginXMLFile(m_Reader.GetNarrowElementName(), idStr, name,
+ sourcepath);
+ eastl::vector<Q3DStudio::TRuntimeMetaDataStrType> theProperties;
+ uic::render::IRenderPluginClass *thePluginClass =
+ m_RenderPluginManager.GetOrCreateRenderPlugin(
+ m_StrTable.RegisterStr(sourcepath));
+ if (thePluginClass) {
+ m_RenderPluginSourcePaths.insert(
+ eastl::make_pair(m_StrTable.RegisterStr(idStr), sourcepath));
+ m_MetaData.GetInstanceProperties(m_Reader.GetNarrowElementName(), idStr,
+ theProperties, false);
+ eastl::string thePropertyStr;
+ CRegisteredString metaType =
+ m_MetaData.GetStringTable()->GetRenderStringTable().RegisterStr(
+ m_Reader.GetNarrowElementName());
+ CRegisteredString metaId =
+ m_MetaData.GetStringTable()->GetRenderStringTable().RegisterStr(
+ idStr);
+ for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
+ using namespace Q3DStudio;
+ CRegisteredString metaProp =
+ m_MetaData.GetStringTable()->GetRenderStringTable().RegisterStr(
+ theProperties[idx].c_str());
+ Q3DStudio::ERuntimeDataModelDataType thePropType =
+ m_MetaData.GetPropertyType(metaType, metaProp, metaId);
+ switch (thePropType) {
+ case ERuntimeDataModelDataTypeFloat:
+ AddPluginProperty(
+ *thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::Float,
+ thePropertyStr, metaProp.c_str());
+ break;
+ case ERuntimeDataModelDataTypeFloat2:
+ AddPluginProperty(
+ *thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::Vector2,
+ thePropertyStr, metaProp.c_str());
+ break;
+ case ERuntimeDataModelDataTypeFloat3:
+ if (m_MetaData.GetAdditionalType(metaType, metaProp, metaId)
+ != ERuntimeAdditionalMetaDataTypeColor)
+ AddPluginProperty(
+ *thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::Vector3,
+ thePropertyStr, metaProp.c_str());
+ else
+ AddPluginProperty(
+ *thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::Color,
+ thePropertyStr, metaProp.c_str());
+ break;
+ case ERuntimeDataModelDataTypeLong:
+ AddPluginProperty(*thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::Long,
+ thePropertyStr, metaProp.c_str());
+ break;
+ case ERuntimeDataModelDataTypeString:
+ case ERuntimeDataModelDataTypeStringRef:
+ AddPluginProperty(
+ *thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::String,
+ thePropertyStr, metaProp.c_str());
+ break;
+ case ERuntimeDataModelDataTypeBool:
+ AddPluginProperty(
+ *thePluginClass,
+ uic::render::SRenderPluginPropertyTypes::Boolean,
+ thePropertyStr, metaProp.c_str());
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ TScope __outerScope(m_Reader);
+ if (m_Reader.MoveToFirstChild("BufferData")) {
+ {
+ TScope __imageScope(m_Reader);
+ for (bool valid = m_Reader.MoveToFirstChild("ImageBuffer"); valid;
+ valid = m_Reader.MoveToNextSibling()) {
+ const char8_t *srcPath;
+ m_Reader.UnregisteredAtt("sourcepath", srcPath);
+ CRegisteredString imgPath = m_StrTable.RegisterStr(srcPath);
+ bool hasTransparency = false;
+ m_Reader.Att(L"hasTransparency", hasTransparency);
+ m_BufferManager.SetImageHasTransparency(imgPath, hasTransparency);
+ }
+ }
+ }
+ }
+ {
+ TScope __outerScope(m_Reader);
+ {
+ if (m_Reader.MoveToFirstChild("Graph")) {
+ {
+ TScope __graphScope(m_Reader);
+ for (bool valid = m_Reader.MoveToFirstChild(); valid;
+ valid = m_Reader.MoveToNextSibling())
+ ParseGraphPass1(NULL);
+ }
+ {
+ TScope __graphScope(m_Reader);
+ for (bool valid = m_Reader.MoveToFirstChild(); valid;
+ valid = m_Reader.MoveToNextSibling())
+ ParseGraphPass2();
+ }
+ }
+ }
+ }
+ TScope __outerScope(m_Reader);
+ if (m_Reader.MoveToFirstChild("Logic")) {
+ for (bool valid = m_Reader.MoveToFirstChild("State"); valid;
+ valid = m_Reader.MoveToNextSibling()) {
+ {
+ TScope __slideScope(m_Reader);
+ ParseState(true); // parse master
+ for (bool subSlide = m_Reader.MoveToFirstChild("State"); subSlide;
+ subSlide = m_Reader.MoveToNextSibling("State")) {
+ TScope __subSlideScope(m_Reader);
+ ParseState(false); // parse slide setting only *add* values
+ }
+ }
+ {
+ TScope __slideScope(m_Reader);
+ if (inSetValuesFromSlides && m_Reader.MoveToFirstChild("State"))
+ ParseState(true); // parse slide setting only *set* values
+ }
+ }
+ }
+
+ return m_Presentation;
+ }
+};
+}
+
+SPresentation *uic::render::IUIPLoader::LoadUIPFile(
+ UICDM::IDOMReader &inReader, const char8_t *inFullPathToPresentationFile,
+ Q3DStudio::IRuntimeMetaData &inMetaData, IStringTable &inStrTable,
+ NVFoundationBase &inFoundation
+ // Allocator used for the presentation objects themselves
+ // this allows clients to pre-allocate a block of memory just for
+ // the scene graph
+ ,
+ NVAllocatorCallback &inPresentationAllocator
+ // Map of string ids to objects
+ ,
+ TIdObjectMap &ioObjectMap, IBufferManager &inBufferManager, IEffectSystem &inEffectSystem,
+ const char8_t *inPresentationDir, IRenderPluginManager &inPluginManager,
+ ICustomMaterialSystem &inCMS, IDynamicObjectSystem &inDynamicSystem,
+ uic::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver,
+ bool inSetValuesFromSlides)
+{
+ SRenderUIPLoader theLoader(inReader, inFullPathToPresentationFile, inMetaData, inStrTable,
+ inFoundation, inPresentationAllocator, ioObjectMap, inBufferManager,
+ inEffectSystem, inPresentationDir, inPluginManager, inCMS,
+ inDynamicSystem, inPathManager, inResolver);
+ return theLoader.Load(inSetValuesFromSlides);
+}
+using namespace UICDM;
+
+inline qt3ds::render::NVRenderTextureFormats::Enum
+ConvertTypeAndFormatToTextureFormat(const char8_t *inType, const char8_t *inFormat,
+ NVFoundationBase &inFoundation)
+{
+ qt3ds::render::NVRenderTextureFormats::Enum retval = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ if (AreEqual(inType, "ubyte")) {
+ if (AreEqual(inFormat, "rgb"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGB8;
+ else if (AreEqual(inFormat, "rgba"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ else if (AreEqual(inFormat, "alpha"))
+ retval = qt3ds::render::NVRenderTextureFormats::Alpha8;
+ else if (AreEqual(inFormat, "lum"))
+ retval = qt3ds::render::NVRenderTextureFormats::Luminance8;
+ else if (AreEqual(inFormat, "lum_alpha"))
+ retval = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8;
+ } else if (AreEqual(inType, "ushort")) {
+ if (AreEqual(inFormat, "rgb"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGB565;
+ else if (AreEqual(inFormat, "rgba"))
+ retval = qt3ds::render::NVRenderTextureFormats::RGBA5551;
+ } else {
+ qCCritical(INVALID_PARAMETER, "Unsupported texture type %s, defaulting to RGBA8",
+ inType);
+ }
+ return retval;
+}
+
+inline qt3ds::render::NVRenderTextureMagnifyingOp::Enum
+ConvertFilterToMagOp(const char8_t *inFilter, NVFoundationBase &inFoundation)
+{
+ if (AreEqual(inFilter, "linear"))
+ return qt3ds::render::NVRenderTextureMagnifyingOp::Linear;
+ if (AreEqual(inFilter, "nearest"))
+ return qt3ds::render::NVRenderTextureMagnifyingOp::Nearest;
+ else {
+ qCCritical(INVALID_PARAMETER, "Unsupported filter type %s, defaulting to linear",
+ inFilter);
+ return qt3ds::render::NVRenderTextureMagnifyingOp::Linear;
+ }
+}
+
+inline qt3ds::render::NVRenderTextureCoordOp::Enum
+ConvertTextureCoordOp(const char8_t *inWrap, NVFoundationBase &inFoundation)
+{
+ if (AreEqual(inWrap, "clamp"))
+ return qt3ds::render::NVRenderTextureCoordOp::ClampToEdge;
+ if (AreEqual(inWrap, "repeat"))
+ return qt3ds::render::NVRenderTextureCoordOp::Repeat;
+ else {
+ qCCritical(INVALID_PARAMETER, "Unsupported wrap type %s, defaulting to clamp",
+ inWrap);
+ return qt3ds::render::NVRenderTextureCoordOp::ClampToEdge;
+ }
+}
+
+template <typename TCharStr>
+QString ConvertUTFtoQString(const TCharStr *string);
+
+template <>
+QString ConvertUTFtoQString(const char16_t *string)
+{
+ return QString::fromUtf16(string);
+}
+
+template <>
+QString ConvertUTFtoQString(const char32_t *string)
+{
+ return QString::fromUcs4(string);
+}
+
+template <>
+QString ConvertUTFtoQString(const wchar_t *string)
+{
+ return QString::fromWCharArray(string);
+}
+
+// Re-register all strings because we can't be sure that the meta data system and the effect
+// system are sharing the same string table.
+void uic::render::IUIPLoader::CreateEffectClassFromMetaEffect(
+ CRegisteredString inEffectName, NVFoundationBase &inFoundation, IEffectSystem &inEffectSystem,
+ const UICDM::SMetaDataEffect &inMetaDataEffect, IStringTable &inStrTable)
+{
+ using namespace uic::render::dynamic;
+ if (inEffectSystem.IsEffectRegistered(inEffectName)) {
+ qCCritical(INVALID_OPERATION, "Effect %s is already registered",
+ inEffectName.c_str());
+ QT3DS_ASSERT(false);
+ return;
+ }
+ nvvector<SPropertyDeclaration> thePropertyDeclarations(
+ inFoundation.getAllocator(), "uic::render::IUIPLoader::CreateEffectClassFromMetaEffect");
+ nvvector<CRegisteredString> theEnumNames(
+ inFoundation.getAllocator(), "uic::render::IUIPLoader::CreateEffectClassFromMetaEffect");
+ CRenderString theConvertStr;
+ CRenderString theConvertShaderTypeStr;
+ CRenderString theConvertShaderVersionStr;
+
+ for (QT3DSU32 idx = 0, end = inMetaDataEffect.m_Properties.size(); idx < end; ++idx)
+ thePropertyDeclarations.push_back(
+ SPropertyDeclaration(inMetaDataEffect.m_Properties[idx].m_Name.c_str(),
+ inMetaDataEffect.m_Properties[idx].m_DataType));
+ inEffectSystem.RegisterEffect(inEffectName, thePropertyDeclarations);
+ for (QT3DSU32 idx = 0, end = inMetaDataEffect.m_Properties.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(inMetaDataEffect.m_Properties[idx]);
+ if (theDefinition.m_EnumValueNames.size()) {
+ theEnumNames.clear();
+ for (QT3DSU32 enumIdx = 0, enumEnd = theDefinition.m_EnumValueNames.size();
+ enumIdx < enumEnd; ++enumIdx)
+ theEnumNames.push_back(
+ inStrTable.RegisterStr(theDefinition.m_EnumValueNames[enumIdx]));
+ inEffectSystem.SetEffectPropertyEnumNames(
+ inEffectName, inStrTable.RegisterStr(theDefinition.m_Name), theEnumNames);
+ }
+ if (theDefinition.m_DataType == qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr)
+ inEffectSystem.SetEffectPropertyTextureSettings(
+ inEffectName, inStrTable.RegisterStr(theDefinition.m_Name),
+ inStrTable.RegisterStr(theDefinition.m_ImagePath), theDefinition.m_TexUsageType,
+ theDefinition.m_CoordOp, theDefinition.m_MagFilterOp, theDefinition.m_MinFilterOp);
+ }
+ for (QT3DSU32 idx = 0, end = inMetaDataEffect.m_Shaders.size(); idx < end; ++idx) {
+ const UICDM::SMetaDataShader &theShader = inMetaDataEffect.m_Shaders[idx];
+ theConvertStr.clear();
+ theConvertStr = ConvertUTFtoQString(
+ theShader.m_Code.c_str()).toStdString();
+ theConvertShaderTypeStr = ConvertUTFtoQString(
+ theShader.m_Type.c_str()).toStdString();
+ theConvertShaderVersionStr = ConvertUTFtoQString(
+ theShader.m_Version.c_str()).toStdString();
+
+ inEffectSystem.SetShaderData(inStrTable.RegisterStr(theShader.m_Name.c_str()),
+ theConvertStr.c_str(), theConvertShaderVersionStr.c_str(),
+ theConvertStr.c_str(), theShader.m_HasGeomShader,
+ theShader.m_IsComputeShader);
+ }
+
+ inEffectSystem.SetEffectCommands(inEffectName, inMetaDataEffect.m_EffectCommands);
+}
+
+void uic::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ CRegisteredString inClassName, NVFoundationBase &inFoundation,
+ ICustomMaterialSystem &inMaterialSystem,
+ const UICDM::SMetaDataCustomMaterial &inMetaDataMaterial, IStringTable &inStrTable)
+{
+ using namespace uic::render::dynamic;
+ if (inMaterialSystem.IsMaterialRegistered(inClassName)) {
+ qCCritical(INVALID_OPERATION, "Effect %s is already registered",
+ inClassName.c_str());
+ QT3DS_ASSERT(false);
+ return;
+ }
+ nvvector<SPropertyDeclaration> thePropertyDeclarations(
+ inFoundation.getAllocator(),
+ "uic::render::IUIPLoader::CreateMaterialClassFromMetaMaterial");
+ nvvector<CRegisteredString> theEnumNames(
+ inFoundation.getAllocator(),
+ "uic::render::IUIPLoader::CreateMaterialClassFromMetaMaterial");
+ CRenderString theConvertStr;
+ CRenderString theConvertShaderTypeStr;
+ CRenderString theConvertShaderVersionStr;
+ for (QT3DSU32 idx = 0, end = inMetaDataMaterial.m_Properties.size(); idx < end; ++idx)
+ thePropertyDeclarations.push_back(
+ SPropertyDeclaration(inMetaDataMaterial.m_Properties[idx].m_Name.c_str(),
+ inMetaDataMaterial.m_Properties[idx].m_DataType));
+ inMaterialSystem.RegisterMaterialClass(inClassName, thePropertyDeclarations);
+ for (QT3DSU32 idx = 0, end = inMetaDataMaterial.m_Properties.size(); idx < end; ++idx) {
+ const SPropertyDefinition &theDefinition(inMetaDataMaterial.m_Properties[idx]);
+ if (theDefinition.m_EnumValueNames.size()) {
+ theEnumNames.clear();
+ for (QT3DSU32 enumIdx = 0, enumEnd = theDefinition.m_EnumValueNames.size();
+ enumIdx < enumEnd; ++enumIdx)
+ theEnumNames.push_back(
+ inStrTable.RegisterStr(theDefinition.m_EnumValueNames[enumIdx]));
+ inMaterialSystem.SetPropertyEnumNames(
+ inClassName, inStrTable.RegisterStr(theDefinition.m_Name), theEnumNames);
+ }
+ if (theDefinition.m_DataType == qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr)
+ inMaterialSystem.SetPropertyTextureSettings(
+ inClassName, inStrTable.RegisterStr(theDefinition.m_Name),
+ inStrTable.RegisterStr(theDefinition.m_ImagePath), theDefinition.m_TexUsageType,
+ theDefinition.m_CoordOp, theDefinition.m_MagFilterOp, theDefinition.m_MinFilterOp);
+ }
+ if (inMetaDataMaterial.m_Shaders.size()) {
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)inMetaDataMaterial.m_Shaders.size(); idx < end; ++idx) {
+ const UICDM::SMetaDataShader &theShader = inMetaDataMaterial.m_Shaders[idx];
+ theConvertStr = ConvertUTFtoQString(
+ theShader.m_Code.c_str()).toStdString();
+ theConvertShaderTypeStr = ConvertUTFtoQString(
+ theShader.m_Type.c_str()).toStdString();
+ theConvertShaderVersionStr = ConvertUTFtoQString(
+ theShader.m_Version.c_str()).toStdString();
+ inMaterialSystem.SetMaterialClassShader(
+ inStrTable.RegisterStr(theShader.m_Name.c_str()), theConvertShaderTypeStr.c_str(),
+ theConvertShaderVersionStr.c_str(), theConvertStr.c_str(),
+ theShader.m_HasGeomShader, theShader.m_IsComputeShader);
+ }
+ }
+
+ inMaterialSystem.SetCustomMaterialCommands(inClassName,
+ inMetaDataMaterial.m_CustomMaterialCommands);
+ inMaterialSystem.SetCustomMaterialTransparency(inClassName,
+ inMetaDataMaterial.m_HasTransparency);
+ inMaterialSystem.SetCustomMaterialRefraction(inClassName, inMetaDataMaterial.m_HasRefraction);
+ inMaterialSystem.SetCustomMaterialAlwaysDirty(inClassName, inMetaDataMaterial.m_AlwaysDirty);
+ inMaterialSystem.SetCustomMaterialShaderKey(inClassName, inMetaDataMaterial.m_ShaderKey);
+ inMaterialSystem.SetCustomMaterialLayerCount(inClassName, inMetaDataMaterial.m_LayerCount);
+}
+
+#endif
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderUIPSharedTranslation.cpp b/src/Runtime/Source/UICRender/Source/UICRenderUIPSharedTranslation.cpp
new file mode 100644
index 00000000..bc3ec8e6
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderUIPSharedTranslation.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRenderUIPSharedTranslation.h"
+
+namespace uic {
+namespace render {
+
+#define WCHAR_T_Directional L"Directional"
+#define WCHAR_T_Point L"Point"
+#define WCHAR_T_Area L"Area"
+#define WCHAR_T_None L"None"
+#define WCHAR_T_Vertex L"Vertex"
+#define WCHAR_T_Pixel L"Pixel"
+#define WCHAR_T_Normal L"Normal"
+#define WCHAR_T_Screen L"Screen"
+#define WCHAR_T_Multiply L"Multiply"
+#define WCHAR_T_Overlay L"Overlay"
+#define WCHAR_T_ColorBurn L"ColorBurn"
+#define WCHAR_T_ColorDodge L"ColorDodge"
+#define WCHAR_T_Add L"Add"
+#define WCHAR_T_Subtract L"Subtract"
+#define WCHAR_T_UV_Mapping L"UV Mapping"
+#define WCHAR_T_Environmental_Mapping L"Environmental Mapping"
+#define WCHAR_T_Light_Probe L"Light Probe"
+#define WCHAR_T_No_Tiling L"No Tiling"
+#define WCHAR_T_Mirrored L"Mirrored"
+#define WCHAR_T_Tiled L"Tiled"
+#define WCHAR_T_Left L"Left"
+#define WCHAR_T_Center L"Center"
+#define WCHAR_T_Right L"Right"
+#define WCHAR_T_Top L"Top"
+#define WCHAR_T_Middle L"Middle"
+#define WCHAR_T_Bottom L"Bottom"
+#define WCHAR_T_2x L"2x"
+#define WCHAR_T_4x L"4x"
+#define WCHAR_T_8x L"8x"
+#define WCHAR_T_SSAA L"SSAA"
+#define WCHAR_T_NoRotation L"NoRotation"
+#define WCHAR_T_Clockwise90 L"90"
+#define WCHAR_T_Clockwise180 L"180"
+#define WCHAR_T_Clockwise270 L"270"
+#define WCHAR_T_Fit L"Fit"
+#define WCHAR_T_Same_Size L"Same Size"
+#define WCHAR_T_CENTER L"Center"
+#define WCHAR_T_North L"N"
+#define WCHAR_T_NorthEast L"NE"
+#define WCHAR_T_East L"E"
+#define WCHAR_T_SouthEast L"SE"
+#define WCHAR_T_South L"S"
+#define WCHAR_T_SouthWest L"SW"
+#define WCHAR_T_West L"W"
+#define WCHAR_T_NorthWest L"NW"
+#define WCHAR_T_LeftWidth L"Left/Width"
+#define WCHAR_T_LeftRight L"Left/Right"
+#define WCHAR_T_WidthRight L"Width/Right"
+#define WCHAR_T_TopHeight L"Top/Height"
+#define WCHAR_T_TopBottom L"Top/Bottom"
+#define WCHAR_T_HeightBottom L"Height/Bottom"
+#define WCHAR_T_Percent L"percent"
+#define WCHAR_T_Pixels L"pixels"
+#define WCHAR_T_Fit_Horizontal L"Fit Horizontal"
+#define WCHAR_T_Fit_Vertical L"Fit Vertical"
+#define WCHAR_T_Default L"Default"
+#define WCHAR_T_KGGX L"KGGX"
+#define WCHAR_T_KWard L"KWard"
+#define WCHAR_T_Transparent L"Transparent"
+#define WCHAR_T_Unspecified L"Unspecified"
+#define WCHAR_T_Color L"SolidColor"
+#define WCHAR_T_Linear L"Linear"
+#define WCHAR_T_Phong L"Phong"
+#define WCHAR_T_NPatch L"NPatch"
+#define WCHAR_T_Taper L"Taper"
+#define WCHAR_T_Geometry L"Geometry"
+#define WCHAR_T_Painted L"Painted"
+#define WCHAR_T_Filled L"Filled"
+#define WCHAR_T_Stroked L"Stroked"
+#define WCHAR_T_FilledAndStroked L"Filled and Stroked"
+#define WCHAR_T_Simple L"Simple"
+#define WCHAR_T_Smoke L"Smoke"
+#define WCHAR_T_Cloud L"Cloud"
+#define WCHAR_T_Fluid L"Fluid"
+#define WCHAR_T_User L"User"
+
+#define CHAR_T_Directional "Directional"
+#define CHAR_T_Point "Point"
+#define CHAR_T_Area "Area"
+#define CHAR_T_None "None"
+#define CHAR_T_Vertex "Vertex"
+#define CHAR_T_Pixel "Pixel"
+#define CHAR_T_Normal "Normal"
+#define CHAR_T_Screen "Screen"
+#define CHAR_T_Multiply "Multiply"
+#define CHAR_T_Overlay "Overlay"
+#define CHAR_T_ColorBurn "ColorBurn"
+#define CHAR_T_ColorDodge "ColorDodge"
+#define CHAR_T_Add "Add"
+#define CHAR_T_Subtract "Subtract"
+#define CHAR_T_UV_Mapping "UV Mapping"
+#define CHAR_T_Environmental_Mapping "Environmental Mapping"
+#define CHAR_T_Light_Probe "Light Probe"
+#define CHAR_T_No_Tiling "No Tiling"
+#define CHAR_T_Mirrored "Mirrored"
+#define CHAR_T_Tiled "Tiled"
+#define CHAR_T_Left "Left"
+#define CHAR_T_Center "Center"
+#define CHAR_T_Right "Right"
+#define CHAR_T_Top "Top"
+#define CHAR_T_Middle "Middle"
+#define CHAR_T_Bottom "Bottom"
+#define CHAR_T_2x "2x"
+#define CHAR_T_4x "4x"
+#define CHAR_T_8x "8x"
+#define CHAR_T_SSAA "SSAA"
+#define CHAR_T_NoRotation "NoRotation"
+#define CHAR_T_Clockwise90 "90"
+#define CHAR_T_Clockwise180 "180"
+#define CHAR_T_Clockwise270 "270"
+#define CHAR_T_Fit "Fit"
+#define CHAR_T_Same_Size "Same Size"
+#define CHAR_T_CENTER "Center"
+#define CHAR_T_North "N"
+#define CHAR_T_NorthEast "NE"
+#define CHAR_T_East "E"
+#define CHAR_T_SouthEast "SE"
+#define CHAR_T_South "S"
+#define CHAR_T_SouthWest "SW"
+#define CHAR_T_West "W"
+#define CHAR_T_NorthWest "NW"
+#define CHAR_T_LeftWidth "Left/Width"
+#define CHAR_T_LeftRight "Left/Right"
+#define CHAR_T_WidthRight "Width/Right"
+#define CHAR_T_TopHeight "Top/Height"
+#define CHAR_T_TopBottom "Top/Bottom"
+#define CHAR_T_HeightBottom "Height/Bottom"
+#define CHAR_T_Percent "percent"
+#define CHAR_T_Pixels "pixels"
+#define CHAR_T_Fit_Horizontal "Fit Horizontal"
+#define CHAR_T_Fit_Vertical "Fit Vertical"
+#define CHAR_T_Default "Default"
+#define CHAR_T_KGGX "KGGX"
+#define CHAR_T_KWard "KWard"
+#define CHAR_T_Transparent "Transparent"
+#define CHAR_T_Unspecified "Unspecified"
+#define CHAR_T_Color "SolidColor"
+#define CHAR_T_Linear "Linear"
+#define CHAR_T_Phong "Phong"
+#define CHAR_T_NPatch "NPatch"
+#define CHAR_T_Taper "Taper"
+#define CHAR_T_Geometry "Geometry"
+#define CHAR_T_Painted "Painted"
+#define CHAR_T_Filled "Filled"
+#define CHAR_T_Stroked "Stroked"
+#define CHAR_T_FilledAndStroked "Filled and Stroked"
+#define CHAR_T_Simple "Simple"
+#define CHAR_T_Smoke "Smoke"
+#define CHAR_T_Cloud "Cloud"
+#define CHAR_T_Fluid "Fluid"
+#define CHAR_T_User "User"
+
+#define DEFINE_NAME_MAP_ENTRY(enumval, name) \
+ { \
+ enumval, WCHAR_T_##name, CHAR_T_##name \
+ }
+ SEnumNameMap g_LightTypesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(RenderLightTypes::Directional, Directional),
+ DEFINE_NAME_MAP_ENTRY(RenderLightTypes::Point, Point),
+ DEFINE_NAME_MAP_ENTRY(RenderLightTypes::Area, Area),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_MaterialLightingMap[] = {
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialLighting::NoLighting, None),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialLighting::VertexLighting, Vertex),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialLighting::FragmentLighting, Pixel),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_BlendModeMap[] = {
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialBlendMode::Normal, Normal),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialBlendMode::Screen, Screen),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialBlendMode::Multiply, Multiply),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialBlendMode::Overlay, Overlay),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialBlendMode::ColorBurn, ColorBurn),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialBlendMode::ColorDodge, ColorDodge),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_ImageMappingModeMap[] = {
+ DEFINE_NAME_MAP_ENTRY(ImageMappingModes::Normal, UV_Mapping),
+ DEFINE_NAME_MAP_ENTRY(ImageMappingModes::Environment, Environmental_Mapping),
+ DEFINE_NAME_MAP_ENTRY(ImageMappingModes::LightProbe, Light_Probe),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_RenderTextureCoordOpMap[] = {
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureCoordOp::ClampToEdge, No_Tiling),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureCoordOp::MirroredRepeat, Mirrored),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureCoordOp::Repeat, Tiled),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_TextHorizontalAlignmentMap[] = {
+ DEFINE_NAME_MAP_ENTRY(TextHorizontalAlignment::Left, Left),
+ DEFINE_NAME_MAP_ENTRY(TextHorizontalAlignment::Center, Center),
+ DEFINE_NAME_MAP_ENTRY(TextHorizontalAlignment::Right, Right),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_TextVerticalAlignmentMap[] = {
+ DEFINE_NAME_MAP_ENTRY(TextVerticalAlignment::Top, Top),
+ DEFINE_NAME_MAP_ENTRY(TextVerticalAlignment::Middle, Middle),
+ DEFINE_NAME_MAP_ENTRY(TextVerticalAlignment::Bottom, Bottom),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_ProgressiveAAValuesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(AAModeValues::NoAA, None),
+ DEFINE_NAME_MAP_ENTRY(AAModeValues::SSAA, SSAA),
+ DEFINE_NAME_MAP_ENTRY(AAModeValues::X2, 2x),
+ DEFINE_NAME_MAP_ENTRY(AAModeValues::X4, 4x),
+ DEFINE_NAME_MAP_ENTRY(AAModeValues::X8, 8x),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_LayerBlendTypesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::Normal, Normal),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::Screen, Screen),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::Multiply, Multiply),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::Add, Add),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::Subtract, Subtract),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::Overlay, Overlay),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::ColorBurn, ColorBurn),
+ DEFINE_NAME_MAP_ENTRY(LayerBlendTypes::ColorDodge, ColorDodge),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_RenderRotationValuesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(RenderRotationValues::NoRotation, None),
+ DEFINE_NAME_MAP_ENTRY(RenderRotationValues::Clockwise90, Clockwise90),
+ DEFINE_NAME_MAP_ENTRY(RenderRotationValues::Clockwise180, Clockwise180),
+ DEFINE_NAME_MAP_ENTRY(RenderRotationValues::Clockwise270, Clockwise270),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_CameraScaleModesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(CameraScaleModes::Fit, Fit),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleModes::SameSize, Same_Size),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleModes::FitHorizontal, Fit_Horizontal),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleModes::FitVertical, Fit_Vertical),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_CameraScaleAnchorsMap[] = {
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::Center, Center),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::North, North),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::NorthEast, NorthEast),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::East, East),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::SouthEast, SouthEast),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::South, South),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::SouthWest, SouthWest),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::West, West),
+ DEFINE_NAME_MAP_ENTRY(CameraScaleAnchors::NorthWest, NorthWest),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_HorizontalFieldValuesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(HorizontalFieldValues::LeftWidth, LeftWidth),
+ DEFINE_NAME_MAP_ENTRY(HorizontalFieldValues::LeftRight, LeftRight),
+ DEFINE_NAME_MAP_ENTRY(HorizontalFieldValues::WidthRight, WidthRight),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_VerticalFieldValuesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(VerticalFieldValues::TopHeight, TopHeight),
+ DEFINE_NAME_MAP_ENTRY(VerticalFieldValues::TopBottom, TopBottom),
+ DEFINE_NAME_MAP_ENTRY(VerticalFieldValues::HeightBottom, HeightBottom),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_LayerUnitTypesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(LayerUnitTypes::Percent, Percent),
+ DEFINE_NAME_MAP_ENTRY(LayerUnitTypes::Pixels, Pixels),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_LayerBackgroundMap[] = {
+ DEFINE_NAME_MAP_ENTRY(LayerBackground::Transparent, Transparent),
+ DEFINE_NAME_MAP_ENTRY(LayerBackground::Unspecified, Unspecified),
+ DEFINE_NAME_MAP_ENTRY(LayerBackground::Color, Color),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_SpecularTypesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialSpecularModel::Default, Default),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialSpecularModel::KGGX, KGGX),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialSpecularModel::KWard, KWard),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_TessellationValuesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(TessModeValues::NoTess, None),
+ DEFINE_NAME_MAP_ENTRY(TessModeValues::TessLinear, Linear),
+ DEFINE_NAME_MAP_ENTRY(TessModeValues::TessPhong, Phong),
+ DEFINE_NAME_MAP_ENTRY(TessModeValues::TessNPatch, NPatch),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_PathCappingValuesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(PathCapping::Noner, None),
+ DEFINE_NAME_MAP_ENTRY(PathCapping::Taper, Taper),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_PathTypesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(PathTypes::Noner, None),
+ DEFINE_NAME_MAP_ENTRY(PathTypes::Painted, Painted),
+ DEFINE_NAME_MAP_ENTRY(PathTypes::Geometry, Geometry),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_PathPaintStylesMap[] = {
+ DEFINE_NAME_MAP_ENTRY(PathPaintStyles::Noner, None),
+ DEFINE_NAME_MAP_ENTRY(PathPaintStyles::FilledAndStroked, FilledAndStroked),
+ DEFINE_NAME_MAP_ENTRY(PathPaintStyles::Filled, Filled),
+ DEFINE_NAME_MAP_ENTRY(PathPaintStyles::Stroked, Stroked),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap *SEnumParseMap<RenderLightTypes::Enum>::GetMap() { return g_LightTypesMap; }
+
+ SEnumNameMap *SEnumParseMap<DefaultMaterialLighting::Enum>::GetMap()
+ {
+ return g_MaterialLightingMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<DefaultMaterialBlendMode::Enum>::GetMap() { return g_BlendModeMap; }
+
+ SEnumNameMap *SEnumParseMap<ImageMappingModes::Enum>::GetMap() { return g_ImageMappingModeMap; }
+
+ SEnumNameMap *SEnumParseMap<NVRenderTextureCoordOp::Enum>::GetMap()
+ {
+ return g_RenderTextureCoordOpMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<TextHorizontalAlignment::Enum>::GetMap()
+ {
+ return g_TextHorizontalAlignmentMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<TextVerticalAlignment::Enum>::GetMap()
+ {
+ return g_TextVerticalAlignmentMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<AAModeValues::Enum>::GetMap() { return g_ProgressiveAAValuesMap; }
+
+ SEnumNameMap *SEnumParseMap<LayerBlendTypes::Enum>::GetMap() { return g_LayerBlendTypesMap; }
+
+ SEnumNameMap *SEnumParseMap<RenderRotationValues::Enum>::GetMap()
+ {
+ return g_RenderRotationValuesMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<CameraScaleModes::Enum>::GetMap() { return g_CameraScaleModesMap; }
+
+ SEnumNameMap *SEnumParseMap<CameraScaleAnchors::Enum>::GetMap()
+ {
+ return g_CameraScaleAnchorsMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<HorizontalFieldValues::Enum>::GetMap()
+ {
+ return g_HorizontalFieldValuesMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<VerticalFieldValues::Enum>::GetMap()
+ {
+ return g_VerticalFieldValuesMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<LayerUnitTypes::Enum>::GetMap() { return g_LayerUnitTypesMap; }
+
+ SEnumNameMap *SEnumParseMap<LayerBackground::Enum>::GetMap() { return g_LayerBackgroundMap; }
+
+ SEnumNameMap *SEnumParseMap<DefaultMaterialSpecularModel::Enum>::GetMap()
+ {
+ return g_SpecularTypesMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<TessModeValues::Enum>::GetMap() { return g_TessellationValuesMap; }
+
+ SEnumNameMap *SEnumParseMap<PathCapping::Enum>::GetMap() { return g_PathCappingValuesMap; }
+
+ SEnumNameMap *SEnumParseMap<PathTypes::Enum>::GetMap() { return g_PathTypesMap; }
+
+ SEnumNameMap *SEnumParseMap<PathPaintStyles::Enum>::GetMap() { return g_PathPaintStylesMap; }
+}
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRenderWidgets.cpp b/src/Runtime/Source/UICRender/Source/UICRenderWidgets.cpp
new file mode 100644
index 00000000..2a56fc97
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRenderWidgets.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICRenderWidgets.h"
+#include "UICRenderNode.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderShaderCodeGeneratorV2.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace uic::render;
+
+namespace {
+
+struct SWidgetBBox : public IRenderWidget
+{
+ NVBounds3 m_Bounds;
+ QT3DSVec3 m_Color;
+ NVRenderVertexBuffer *m_BoxVertexBuffer;
+ NVRenderIndexBuffer *m_BoxIndexBuffer;
+ NVRenderInputAssembler *m_BoxInputAssembler;
+ NVRenderShaderProgram *m_BoxShader;
+ CRegisteredString m_ItemName;
+ SWidgetBBox(SNode &inNode, const NVBounds3 &inBounds, const QT3DSVec3 &inColor)
+ : IRenderWidget(inNode)
+ , m_Bounds(inBounds)
+ , m_Color(inColor)
+ , m_BoxVertexBuffer(NULL)
+ , m_BoxIndexBuffer(NULL)
+ , m_BoxInputAssembler(NULL)
+ , m_BoxShader(NULL)
+ {
+ }
+
+ void SetupBoxShader(IRenderWidgetContext &inContext)
+ {
+ m_BoxShader = inContext.GetShader(m_ItemName);
+ if (!m_BoxShader) {
+ uic::render::IShaderProgramGenerator &theGenerator(inContext.GetProgramGenerator());
+ theGenerator.BeginProgram();
+ uic::render::IShaderStageGenerator &theVertexGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Vertex));
+ uic::render::IShaderStageGenerator &theFragmentGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Fragment));
+
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddUniform("model_view_projection", "mat4");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append(
+ "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.AddUniform("output_color", "vec3");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tgl_FragColor.rgb = output_color;");
+ theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;");
+ theFragmentGenerator.Append("}");
+ m_BoxShader = inContext.CompileAndStoreShader(m_ItemName);
+ }
+ }
+
+ void SetupBoundingBoxGraphicsObjects(IRenderWidgetContext &inContext,
+ NVDataRef<QT3DSVec3> thePoints)
+ {
+ qt3ds::render::NVRenderVertexBufferEntry theEntry(
+ "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3);
+ m_BoxVertexBuffer = &inContext.GetOrCreateVertexBuffer(
+ m_ItemName, 3 * sizeof(QT3DSF32), toU8DataRef(thePoints.begin(), thePoints.size()));
+ m_BoxIndexBuffer = inContext.GetIndexBuffer(m_ItemName);
+ if (!m_BoxIndexBuffer) {
+ // The way the bounds lays out the bounds for the box
+ // capitalization indicates whether this was a max or min value.
+ enum _Indexes {
+ xyz = 0,
+ Xyz,
+ xYz,
+ xyZ,
+ XYZ,
+ xYZ,
+ XyZ,
+ XYz,
+ };
+ QT3DSU8 indexes[] = {
+ // The toBoxBounds function lays out points such that
+ // xyz, Xyz, xYz, xyZ, XYZ, xYZ, XyZ, XYz
+ // Min corner
+ xyz, Xyz, xyz, xYz, xyz, xyZ,
+
+ // Max corner
+ XYZ, xYZ, XYZ, XyZ, XYZ, XYz,
+
+ // Now connect the rest of the dots.
+ // the rules are that only one letter can change
+ // else you are connecting *across* the box somehow.
+
+ Xyz, XYz, Xyz, XyZ,
+
+ xYz, XYz, xYz, xYZ,
+
+ xyZ, XyZ, xyZ, xYZ,
+ };
+ m_BoxIndexBuffer = &inContext.GetOrCreateIndexBuffer(
+ m_ItemName, qt3ds::render::NVRenderComponentTypes::QT3DSU8, sizeof(indexes),
+ toU8DataRef(indexes, sizeof(indexes)));
+ }
+
+ m_BoxInputAssembler = inContext.GetInputAssembler(m_ItemName);
+ if (!m_BoxInputAssembler && m_BoxIndexBuffer && m_BoxVertexBuffer) {
+ // create our attribute layout
+ NVRenderAttribLayout *theAttribLAyout =
+ &inContext.CreateAttributeLayout(toConstDataRef(&theEntry, 1));
+
+ QT3DSU32 strides = m_BoxVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_BoxInputAssembler = &inContext.GetOrCreateInputAssembler(
+ m_ItemName, theAttribLAyout, toConstDataRef(&m_BoxVertexBuffer, 1),
+ m_BoxIndexBuffer, toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+ SetupBoxShader(inContext);
+ }
+
+ void Render(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext) override
+ {
+ m_ItemName = inRenderContext.GetStringTable().RegisterStr("SWidgetBBox");
+ SWidgetRenderInformation theInfo(inWidgetContext.GetWidgetRenderInformation(
+ *m_Node, m_Node->m_Position, RenderWidgetModes::Local));
+ TNVBounds2BoxPoints thePoints;
+ m_Bounds.expand(thePoints);
+ QT3DSMat44 theNodeRotation;
+ QT3DSMat44 theNodeToCamera = theInfo.m_NodeParentToCamera * m_Node->m_LocalTransform;
+ for (QT3DSU32 idx = 0; idx < 8; ++idx)
+ thePoints[idx] = theNodeToCamera.transform(thePoints[idx]);
+ SetupBoundingBoxGraphicsObjects(inWidgetContext, toDataRef(thePoints, 8));
+ if (m_BoxShader && m_BoxInputAssembler) {
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetDepthWriteEnabled(true);
+ inRenderContext.SetDepthTestEnabled(true);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_BoxShader);
+ m_BoxShader->SetPropertyValue("model_view_projection", theInfo.m_LayerProjection);
+ m_BoxShader->SetPropertyValue("output_color", m_Color);
+ inRenderContext.SetInputAssembler(m_BoxInputAssembler);
+ inRenderContext.Draw(qt3ds::render::NVRenderDrawMode::Lines,
+ m_BoxInputAssembler->GetIndexCount(), 0);
+ }
+ }
+};
+
+struct SWidgetAxis : public IRenderWidget
+{
+ NVRenderVertexBuffer *m_AxisVertexBuffer;
+ NVRenderInputAssembler *m_AxisInputAssembler;
+ NVRenderShaderProgram *m_AxisShader;
+ CRegisteredString m_ItemName;
+
+ SWidgetAxis(SNode &inNode)
+ : IRenderWidget(inNode)
+ , m_AxisVertexBuffer(NULL)
+ , m_AxisInputAssembler(NULL)
+ , m_AxisShader(NULL)
+ {
+ }
+
+ void SetupAxisShader(IRenderWidgetContext &inContext)
+ {
+ m_AxisShader = inContext.GetShader(m_ItemName);
+ if (!m_AxisShader) {
+ uic::render::IShaderProgramGenerator &theGenerator(inContext.GetProgramGenerator());
+ theGenerator.BeginProgram();
+ uic::render::IShaderStageGenerator &theVertexGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Vertex));
+ uic::render::IShaderStageGenerator &theFragmentGenerator(
+ *theGenerator.GetStage(uic::render::ShaderGeneratorStages::Fragment));
+ theVertexGenerator.AddIncoming("attr_pos", "vec3");
+ theVertexGenerator.AddIncoming("attr_color", "vec3");
+ theVertexGenerator.AddOutgoing("output_color", "vec3");
+ theVertexGenerator.AddUniform("model_view_projection", "mat4");
+ theVertexGenerator.Append("void main() {");
+ theVertexGenerator.Append(
+ "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);");
+ theVertexGenerator.Append("\toutput_color = attr_color;");
+ theVertexGenerator.Append("}");
+ theFragmentGenerator.Append("void main() {");
+ theFragmentGenerator.Append("\tgl_FragColor.rgb = output_color;");
+ theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;");
+ theFragmentGenerator.Append("}");
+ m_AxisShader = inContext.CompileAndStoreShader(m_ItemName);
+ }
+ }
+
+ void SetupAxesGraphicsObjects(IRenderWidgetContext &inContext, NVDataRef<QT3DSVec3> theAxes)
+ {
+ qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
+ qt3ds::render::NVRenderVertexBufferEntry("attr_pos",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3),
+ qt3ds::render::NVRenderVertexBufferEntry("attr_color",
+ qt3ds::render::NVRenderComponentTypes::QT3DSF32, 3, 12),
+ };
+
+ m_AxisVertexBuffer = &inContext.GetOrCreateVertexBuffer(
+ m_ItemName, 6 * sizeof(QT3DSF32), toU8DataRef(theAxes.begin(), theAxes.size()));
+
+ if (!m_AxisInputAssembler && m_AxisVertexBuffer) {
+ // create our attribute layout
+ NVRenderAttribLayout *theAttribLAyout =
+ &inContext.CreateAttributeLayout(toConstDataRef(theEntries, 2));
+
+ QT3DSU32 strides = m_AxisVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ m_AxisInputAssembler = &inContext.GetOrCreateInputAssembler(
+ m_ItemName, theAttribLAyout, toConstDataRef(&m_AxisVertexBuffer, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ }
+ }
+
+ inline QT3DSVec3 TransformDirection(const QT3DSMat33 &inMatrix, const QT3DSVec3 &inDir)
+ {
+ QT3DSVec3 retval = inMatrix.transform(inDir);
+ retval.normalize();
+ return retval;
+ }
+ void Render(IRenderWidgetContext &inWidgetContext, NVRenderContext &inRenderContext) override
+ {
+ m_ItemName = inRenderContext.GetStringTable().RegisterStr("SWidgetAxis");
+
+ SetupAxisShader(inWidgetContext);
+
+ if (m_AxisShader) {
+ QT3DSVec3 Red = QT3DSVec3(1, 0, 0);
+ QT3DSVec3 Green = QT3DSVec3(0, 1, 0);
+ QT3DSVec3 Blue = QT3DSVec3(0, 0, 1);
+ if (m_Node->m_Parent && m_Node->m_Parent->m_Type != GraphObjectTypes::Layer) {
+ m_Node->m_Parent->CalculateGlobalVariables();
+ }
+ QT3DSVec3 thePivot(m_Node->m_Pivot);
+ if (m_Node->m_Flags.IsLeftHanded())
+ thePivot.z *= -1;
+ SWidgetRenderInformation theInfo(inWidgetContext.GetWidgetRenderInformation(
+ *m_Node, thePivot, RenderWidgetModes::Local));
+
+ QT3DSMat44 theNodeRotation;
+ m_Node->CalculateRotationMatrix(theNodeRotation);
+ if (m_Node->m_Flags.IsLeftHanded())
+ SNode::FlipCoordinateSystem(theNodeRotation);
+ QT3DSMat33 theRotationMatrix(theNodeRotation.column0.getXYZ(),
+ theNodeRotation.column1.getXYZ(),
+ theNodeRotation.column2.getXYZ());
+ // Move the camera position into camera space. This is so that when we render we don't
+ // have to account
+ // for scaling done in the camera's MVP.
+ QT3DSVec3 theItemPosition = theInfo.m_Position;
+ QT3DSMat33 theAxisTransform = theInfo.m_NormalMatrix * theRotationMatrix;
+ QT3DSVec3 xAxis = TransformDirection(theAxisTransform, QT3DSVec3(1, 0, 0));
+ QT3DSVec3 yAxis = TransformDirection(theAxisTransform, QT3DSVec3(0, 1, 0));
+ QT3DSVec3 zAxis = TransformDirection(theAxisTransform, QT3DSVec3(0, 0, -1));
+
+ // This world to pixel scale factor function
+ QT3DSF32 theScaleFactor = theInfo.m_Scale;
+ theItemPosition = theInfo.m_Position;
+
+ QT3DSF32 overshootFactor = 10.0f * theScaleFactor; // amount to scale past the origin in
+ // the opposite direction as the axis
+ QT3DSF32 scaleFactor = 50.0f * theScaleFactor;
+ QT3DSVec3 theAxis[] = {
+ theItemPosition - (xAxis * overshootFactor), Red,
+ theItemPosition + (xAxis * scaleFactor), Red, // X axis
+ theItemPosition - (yAxis * overshootFactor), Green,
+ theItemPosition + (yAxis * scaleFactor), Green, // Y axis
+ theItemPosition - (zAxis * overshootFactor), Blue,
+ theItemPosition + (zAxis * scaleFactor), Blue, // Z axis
+ };
+
+ SetupAxesGraphicsObjects(inWidgetContext, toDataRef(theAxis, 3));
+
+ if (m_AxisInputAssembler) {
+ inRenderContext.SetBlendingEnabled(false);
+ inRenderContext.SetDepthWriteEnabled(false);
+ inRenderContext.SetDepthTestEnabled(false);
+ inRenderContext.SetCullingEnabled(false);
+ inRenderContext.SetActiveShader(m_AxisShader);
+ m_AxisShader->SetPropertyValue("model_view_projection", theInfo.m_LayerProjection);
+ inRenderContext.SetInputAssembler(m_AxisInputAssembler);
+ // Draw six points.
+ inRenderContext.Draw(qt3ds::render::NVRenderDrawMode::Lines, 6, 0);
+ }
+ }
+ }
+};
+}
+
+IRenderWidget &IRenderWidget::CreateBoundingBoxWidget(SNode &inNode, const NVBounds3 &inBounds,
+ const QT3DSVec3 &inColor,
+ NVAllocatorCallback &inAlloc)
+{
+ return *QT3DS_NEW(inAlloc, SWidgetBBox)(inNode, inBounds, inColor);
+}
+
+IRenderWidget &IRenderWidget::CreateAxisWidget(SNode &inNode, NVAllocatorCallback &inAlloc)
+{
+ return *QT3DS_NEW(inAlloc, SWidgetAxis)(inNode);
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICRendererUtil.cpp b/src/Runtime/Source/UICRender/Source/UICRendererUtil.cpp
new file mode 100644
index 00000000..132c873e
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICRendererUtil.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICRendererUtil.h"
+#include "UICRenderResourceBufferObjects.h"
+#include "UICRenderResourceTexture2D.h"
+
+using namespace uic::render;
+
+void CRendererUtil::ResolveMutisampleFBOColorOnly(IResourceManager &inManager,
+ CResourceTexture2D &ioResult,
+ NVRenderContext &inRenderContext, QT3DSU32 inWidth,
+ QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inColorFormat,
+ NVRenderFrameBuffer &inSourceFBO)
+{
+ // create resolve FBO
+ CResourceFrameBuffer theResolveFB(inManager);
+ // Allocates the frame buffer which has the side effect of setting the current render target to
+ // that frame buffer.
+ theResolveFB.EnsureFrameBuffer();
+ // set copy flags
+ qt3ds::render::NVRenderClearFlags copyFlags(NVRenderClearValues::Color);
+
+ // get / create resolve targets and attach
+ ioResult.EnsureTexture(inWidth, inHeight, inColorFormat);
+ theResolveFB->Attach(NVRenderFrameBufferAttachments::Color0, *ioResult);
+ // CN - I don't believe we have to resolve the depth.
+ // The reason is we render the depth texture specially unresolved. So there is no need to
+ // resolve
+ // the depth prepass texture to anything else.
+
+ // 1. Make resolve buffer be the render target ( already happend )
+ // 2. Make the current layer FBO the current read target
+ // 3. Do the blit from MSAA to non MSAA
+
+ // 2.
+ inRenderContext.SetReadTarget(&inSourceFBO);
+ inRenderContext.SetReadBuffer(NVReadFaces::Color0);
+ // 3.
+ inRenderContext.BlitFramebuffer(0, 0, inWidth, inHeight, 0, 0, inWidth, inHeight, copyFlags,
+ NVRenderTextureMagnifyingOp::Nearest);
+}
+
+void CRendererUtil::ResolveSSAAFBOColorOnly(IResourceManager &inManager,
+ CResourceTexture2D &ioResult, QT3DSU32 outWidth,
+ QT3DSU32 outHeight, NVRenderContext &inRenderContext,
+ QT3DSU32 inWidth, QT3DSU32 inHeight,
+ NVRenderTextureFormats::Enum inColorFormat,
+ NVRenderFrameBuffer &inSourceFBO)
+{
+ // create resolve FBO
+ CResourceFrameBuffer theResolveFB(inManager);
+ // Allocates the frame buffer which has the side effect of setting the current render target to
+ // that frame buffer.
+ theResolveFB.EnsureFrameBuffer();
+ // set copy flags
+ qt3ds::render::NVRenderClearFlags copyFlags(NVRenderClearValues::Color);
+
+ // get / create resolve targets and attach
+ ioResult.EnsureTexture(outWidth, outHeight, inColorFormat);
+ theResolveFB->Attach(NVRenderFrameBufferAttachments::Color0, *ioResult);
+ // CN - I don't believe we have to resolve the depth.
+ // The reason is we render the depth texture specially unresolved. So there is no need to
+ // resolve
+ // the depth prepass texture to anything else.
+
+ // 1. Make resolve buffer be the render target ( already happend )
+ // 2. Make the current layer FBO the current read target
+ // 3. Do the blit from High res to low res buffer
+
+ // 2.
+ inRenderContext.SetReadTarget(&inSourceFBO);
+ inRenderContext.SetReadBuffer(NVReadFaces::Color0);
+ // 3.
+ inRenderContext.BlitFramebuffer(0, 0, inWidth, inHeight, 0, 0, outWidth, outHeight, copyFlags,
+ NVRenderTextureMagnifyingOp::Linear);
+}
+
+void CRendererUtil::GetSSAARenderSize(QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 &outWidth,
+ QT3DSU32 &outHeight)
+{
+ // we currently double width and height
+ outWidth = inWidth * 2;
+ outHeight = inHeight * 2;
+
+ // keep aspect ration?
+ // clamp to max
+ if (outWidth > MAX_SSAA_DIM)
+ outWidth = MAX_SSAA_DIM;
+ if (outHeight > MAX_SSAA_DIM)
+ outHeight = MAX_SSAA_DIM;
+}
diff --git a/src/Runtime/Source/UICRender/Source/UICTextRenderer.cpp b/src/Runtime/Source/UICRender/Source/UICTextRenderer.cpp
new file mode 100644
index 00000000..2db33de3
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/UICTextRenderer.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICTextRenderer.h"
+#include "render/Qt3DSRenderTexture2D.h"
+
+using namespace uic::render;
+
+// http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html
+QT3DSU32 ITextRenderer::NextPowerOf2(QT3DSU32 input)
+{
+ // Algorithm doesn't work for 0 or QT3DS_MAX_U32
+ QT3DS_ASSERT(input > 0 && input < QT3DS_MAX_U32);
+ input--;
+ input = (input >> 1) | input;
+ input = (input >> 2) | input;
+ input = (input >> 4) | input;
+ input = (input >> 8) | input;
+ input = (input >> 16) | input;
+ input++; // input is now the next highest power of 2.
+ return input;
+}
+
+QT3DSU32 ITextRenderer::NextMultipleOf4(QT3DSU32 inValue)
+{
+ QT3DSU32 remainder(inValue % 4);
+ if (remainder != 0)
+ inValue = inValue + (4 - remainder);
+
+ return inValue;
+}
+
+STextTextureDetails ITextRenderer::UploadData(NVDataRef<QT3DSU8> inTextureData,
+ NVRenderTexture2D &inTexture, QT3DSU32 inDataWidth,
+ QT3DSU32 inDataHeight, QT3DSU32 inTextWidth,
+ QT3DSU32 inTextHeight,
+ NVRenderTextureFormats::Enum inFormat,
+ bool inFlipYAxis)
+{
+ if (inTextWidth == 0 || inTextHeight == 0) {
+ QT3DSU32 black[] = { 0, 0, 0, 0 };
+ inTexture.SetTextureData(toU8DataRef(black, 4), 0, 2, 2, NVRenderTextureFormats::RGBA8);
+ return STextTextureDetails(2, 2, false, QT3DSVec2(1.0));
+ }
+ QT3DS_ASSERT(NextMultipleOf4(inDataWidth) == inDataWidth);
+ QT3DSU32 theNecessaryHeight = NextMultipleOf4(inTextHeight);
+ QT3DSU32 dataStride = inDataWidth * NVRenderTextureFormats::getSizeofFormat(inFormat);
+ if (inTextureData.size() < dataStride * inDataHeight) {
+ QT3DS_ASSERT(false);
+ return STextTextureDetails();
+ }
+
+ STextureDetails theTextureDetails = inTexture.GetTextureDetails();
+ QT3DSU32 theUploadSize = theNecessaryHeight * dataStride;
+
+ NVDataRef<QT3DSU8> theUploadData = NVDataRef<QT3DSU8>(inTextureData.begin(), theUploadSize);
+ inTexture.SetTextureData(theUploadData, 0, inDataWidth, theNecessaryHeight, inFormat);
+ inTexture.SetMagFilter(qt3ds::render::NVRenderTextureMagnifyingOp::Linear);
+ inTexture.SetMinFilter(qt3ds::render::NVRenderTextureMinifyingOp::Linear);
+ return STextTextureDetails(inTextWidth, inTextHeight, inFlipYAxis, QT3DSVec2(1.0f, 1.0f));
+}
diff --git a/src/Runtime/Source/UICRender/Source/q3dsqmlrender.cpp b/src/Runtime/Source/UICRender/Source/q3dsqmlrender.cpp
new file mode 100644
index 00000000..82379f7b
--- /dev/null
+++ b/src/Runtime/Source/UICRender/Source/q3dsqmlrender.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsqmlrender.h"
+#include "q3dsqmlstreamservice.h"
+#include "render/Qt3DSRenderContext.h"
+
+#include <QSize>
+#include <QOpenGLContext>
+
+Q3DSQmlRender::Q3DSQmlRender(IUICRenderContext &inRenderContext, const char *asset)
+ : m_RenderContext(inRenderContext)
+ , m_qmlStreamRenderer(nullptr)
+ , m_offscreenRenderType(inRenderContext.GetStringTable().RegisterStr(GetRendererName()))
+ , m_assetString(inRenderContext.GetStringTable().RegisterStr(asset))
+ , mRefCount(0)
+{
+
+}
+
+Q3DSQmlRender::~Q3DSQmlRender()
+{
+ m_qmlStreamRenderer =
+ IQ3DSQmlStreamService::getQmlStreamService()->getRenderer(m_assetString.c_str());
+ if (m_qmlStreamRenderer)
+ m_qmlStreamRenderer->uninitialize();
+}
+
+CRegisteredString Q3DSQmlRender::GetOffscreenRendererType()
+{
+ return m_offscreenRenderType;
+}
+
+NVRenderTextureFormats::Enum convertTextureFormat(E_TEXTURE_FORMAT fmt)
+{
+ Q_UNUSED(fmt)
+ NVRenderTextureFormats::Enum ret = NVRenderTextureFormats::RGBA8;
+ return ret;
+}
+
+SOffscreenRendererEnvironment Q3DSQmlRender::GetDesiredEnvironment(QT3DSVec2 inPresScale)
+{
+ QSize size;
+ E_TEXTURE_FORMAT format;
+
+ if (!m_qmlStreamRenderer)
+ initializeRenderer();
+
+ if (m_qmlStreamRenderer) {
+ size = m_qmlStreamRenderer->getDesiredSize();
+ format = m_qmlStreamRenderer->getDesiredFormat();
+ }
+ return SOffscreenRendererEnvironment(
+ (QT3DSU32)(size.width() * inPresScale.x), (QT3DSU32)(size.height() * inPresScale.y),
+ convertTextureFormat(format), OffscreenRendererDepthValues::Depth24, false,
+ AAModeValues::NoAA);
+}
+
+SOffscreenRenderFlags Q3DSQmlRender::NeedsRender(const SOffscreenRendererEnvironment &inEnvironment,
+ QT3DSVec2 inPresentationScaleFactor)
+{
+ Q_UNUSED(inEnvironment);
+ Q_UNUSED(inPresentationScaleFactor);
+ bool render = false;
+ if (!m_qmlStreamRenderer)
+ initializeRenderer();
+ if (m_qmlStreamRenderer)
+ render = m_qmlStreamRenderer->isUpdateRequested();
+ return SOffscreenRenderFlags(false, render);
+}
+
+void Q3DSQmlRender::Render(const SOffscreenRendererEnvironment &inEnvironment,
+ NVRenderContext &inRenderContext, QT3DSVec2 inPresentationScaleFactor,
+ SScene::RenderClearCommand inColorBufferNeedsClear)
+{
+ Q_UNUSED(inEnvironment);
+ Q_UNUSED(inPresentationScaleFactor);
+ Q_UNUSED(inColorBufferNeedsClear);
+ if (m_qmlStreamRenderer) {
+ inRenderContext.PushPropertySet();
+
+ m_qmlStreamRenderer->render();
+
+ inRenderContext.PopPropertySet(true);
+ }
+}
+
+void Q3DSQmlRender::initializeRenderer()
+{
+ m_qmlStreamRenderer
+ = IQ3DSQmlStreamService::getQmlStreamService()->getRenderer(m_assetString.c_str());
+ if (m_qmlStreamRenderer) {
+ if (!m_qmlStreamRenderer->initialize(
+ QT_PREPEND_NAMESPACE(QOpenGLContext)::currentContext(),
+ QT_PREPEND_NAMESPACE(QOpenGLContext)::currentContext()->surface())) {
+ m_qmlStreamRenderer = nullptr;
+ }
+ }
+}
diff --git a/src/Runtime/Source/UICState/Application/UICStateApplication.cpp b/src/Runtime/Source/UICState/Application/UICStateApplication.cpp
new file mode 100644
index 00000000..ddca675a
--- /dev/null
+++ b/src/Runtime/Source/UICState/Application/UICStateApplication.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateApplication.h"
+#include "foundation/FileTools.h"
+#include "EASTL/vector.h"
+#include "foundation/IOStreams.h"
+#include "foundation/XML.h"
+
+#include <QtCore/qstringlist.h>
+
+typedef eastl::string TAppStr;
+
+using namespace qt3ds::foundation;
+using namespace uic::state;
+using namespace eastl;
+
+bool IApplication::EnsureApplicationFile(const char *inFullUIPPath,
+ const QStringList &presentations)
+{
+ eastl::string directory;
+ eastl::string filestem;
+ eastl::string extension;
+ eastl::string filename;
+
+ CFileTools::Split(inFullUIPPath, directory, filestem, extension);
+ filename = filestem;
+ filename.append(1, '.');
+ filename.append(extension);
+ CFileTools::CreateDir(directory.c_str());
+ eastl::vector<eastl::string> dirFiles;
+ CFileTools::GetDirectoryEntries(directory, dirFiles);
+ eastl::string uiaPath;
+
+ for (qt3ds::QT3DSU32 idx = 0, end = dirFiles.size(); idx < end && uiaPath.empty(); ++idx) {
+ eastl::string fileExt;
+ CFileTools::GetExtension(dirFiles[idx].c_str(), fileExt);
+ if (fileExt.comparei("uia") == 0)
+ CFileTools::CombineBaseAndRelative(directory.c_str(), dirFiles[idx].c_str(), uiaPath);
+ }
+
+ if (uiaPath.size()) {
+ MallocAllocator allocator;
+ NVScopedRefCounted<IStringTable> strTable(IStringTable::CreateStringTable(allocator));
+ NVScopedRefCounted<IDOMFactory> domFactory(
+ IDOMFactory::CreateDOMFactory(allocator, strTable));
+ eastl::pair<SNamespacePairNode *, SDOMElement *> readResult;
+ {
+ CFileSeekableIOStream theInStream(uiaPath.c_str(), FileReadFlags());
+ readResult = CDOMSerializer::Read(*domFactory, theInStream);
+ }
+ if (readResult.second == NULL) {
+ QT3DS_ASSERT(false);
+ uiaPath.clear();
+ } else {
+ eastl::pair<NVScopedRefCounted<IDOMWriter>, NVScopedRefCounted<IDOMReader>> writerData
+ = IDOMWriter::CreateDOMWriter(domFactory, *readResult.second, strTable);
+ NVScopedRefCounted<IDOMReader> domReader(writerData.second);
+ if (!domReader->MoveToFirstChild("assets"))
+ writerData.first->Begin("assets");
+ else {
+ int pre = domReader->CountChildren("presentation");
+ int preq = domReader->CountChildren("presentation-qml");
+ if (pre + preq > 0) {
+ while (domReader->MoveToFirstChild("presentation"))
+ writerData.first->RemoveCurrent();
+ while (domReader->MoveToFirstChild("presentation-qml"))
+ writerData.first->RemoveCurrent();
+ }
+ }
+
+ writerData.first->Begin("presentation");
+ writerData.first->Att("id", filestem.c_str());
+ writerData.first->Att("src", filename.c_str());
+ writerData.first->End();
+
+ for (int i = 0; i < presentations.size() / 3; i++) {
+ writerData.first->Begin(qPrintable(presentations[3 * i]));
+ writerData.first->Att("id", qPrintable(presentations[3 * i + 1]));
+ if (presentations[3 * i] == QStringLiteral("presentation"))
+ writerData.first->Att("src", qPrintable(presentations[3 * i + 2]));
+ else
+ writerData.first->Att("args", qPrintable(presentations[3 * i + 2]));
+ writerData.first->End();
+ }
+
+ CFileSeekableIOStream theOutStream(uiaPath.c_str(), FileWriteFlags());
+ if (theOutStream.IsOpen()) {
+ NVDataRef<SNamespacePair> namespacePairs;
+ if (readResult.first)
+ namespacePairs = toDataRef<SNamespacePair>(*readResult.first);
+ CDOMSerializer::WriteXMLHeader(theOutStream);
+ CDOMSerializer::Write(allocator, *readResult.second, theOutStream, *strTable,
+ namespacePairs, false);
+ } else
+ return false;
+ }
+ }
+ // No uia, just create a new one named after the uip file
+ if (!uiaPath.size()) {
+ eastl::string uiaName = filestem + ".uia";
+ CFileTools::CombineBaseAndRelative(directory.c_str(), uiaName.c_str(), uiaPath);
+ eastl::string uiaFileData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<application xmlns=\"http://qt.io/qt3dstudio/uia\">\n"
+ "\t<assets initial=\"";
+ uiaFileData.append(filestem.c_str());
+ uiaFileData.append("\">\n"
+ "\t\t<presentation id=\"");
+ uiaFileData.append(filestem.c_str());
+ uiaFileData.append("\"\tsrc=\"");
+ uiaFileData.append(filename);
+ uiaFileData.append("\"/>\n");
+
+ for (int i = 0; i < presentations.size() / 3; i++) {
+ uiaFileData.append("\t\t<");
+ uiaFileData.append(qPrintable(presentations[3 * i]));
+ uiaFileData.append("id=\"");
+ uiaFileData.append(qPrintable(presentations[3 * i + 1]));
+ if (presentations[3 * i] == QStringLiteral("presentation"))
+ uiaFileData.append("\" src=\"");
+ else
+ uiaFileData.append("\" args=\"");
+ uiaFileData.append(qPrintable(presentations[3 * i + 2]));
+ uiaFileData.append("\"/>\n");
+ }
+
+ uiaFileData.append("\t</assets>\n");
+
+ // Add initial state
+ uiaFileData.append("\n\t<statemachine ref=\"#logic\">\n");
+ uiaFileData.append("\t\t<visual-states>\n");
+ uiaFileData.append("\t\t\t<state ref=\"Initial\">\n");
+ uiaFileData.append("\t\t\t\t<enter>\n");
+ uiaFileData.append("\t\t\t\t\t<goto-slide element=\"main:Scene\" rel=\"next\"/>\n");
+ uiaFileData.append("\t\t\t\t</enter>\n");
+ uiaFileData.append("\t\t\t</state>\n");
+ uiaFileData.append("\t\t</visual-states>\n");
+ uiaFileData.append("\t</statemachine>\n");
+
+ uiaFileData.append("</application>\n");
+
+ CFileSeekableIOStream theStream(uiaPath.c_str(), FileWriteFlags());
+ if (!theStream.IsOpen()) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ theStream.Write(
+ toConstDataRef((const qt3ds::QT3DSU8 *)uiaFileData.c_str(),
+ (qt3ds::QT3DSU32)uiaFileData.length()));
+ }
+ return true;
+}
+
+eastl::string IApplication::GetLaunchFile(const char *inFullUIPPath)
+{
+ eastl::string directory;
+ eastl::string filestem;
+ eastl::string extension;
+ eastl::string filename;
+
+ CFileTools::Split(inFullUIPPath, directory, filestem, extension);
+ eastl::string uiaPath;
+
+ eastl::vector<eastl::string> dirFiles;
+ CFileTools::GetDirectoryEntries(directory, dirFiles);
+
+ for (qt3ds::QT3DSU32 idx = 0, end = dirFiles.size(); idx < end && uiaPath.empty(); ++idx) {
+ eastl::string fileExt;
+ CFileTools::GetExtension(dirFiles[idx].c_str(), fileExt);
+ if (fileExt.comparei("uia") == 0)
+ CFileTools::CombineBaseAndRelative(directory.c_str(), dirFiles[idx].c_str(), uiaPath);
+ }
+ return uiaPath.empty() == false ? uiaPath : eastl::string(inFullUIPPath);
+}
diff --git a/src/Runtime/Source/UICState/Application/UICStateApplication.h b/src/Runtime/Source/UICState/Application/UICStateApplication.h
new file mode 100644
index 00000000..3030e3bd
--- /dev/null
+++ b/src/Runtime/Source/UICState/Application/UICStateApplication.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_APPLICATION_H
+#define UIC_STATE_APPLICATION_H
+#include "EASTL/string.h"
+#include <QtCore/qvector.h>
+
+namespace uic {
+namespace state {
+ // Shared code for dealing with .uia files.
+ class IApplication
+ {
+ public:
+ // Upon creation of this application file, ensure the creation of
+ // Returns false if it was unable to write or update the uia file.
+ static bool EnsureApplicationFile(const char *inFullUIPPath,
+ const QStringList &presentations);
+ static eastl::string GetLaunchFile(const char *inFullUIPPath);
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Debugger/UICLuaDatamodelCache.cpp b/src/Runtime/Source/UICState/Debugger/UICLuaDatamodelCache.cpp
new file mode 100644
index 00000000..6f1dd55f
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICLuaDatamodelCache.cpp
@@ -0,0 +1,518 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_LUA_DATAMODLE_CACHE_H
+#define UIC_LUA_DATAMODLE_CACHE_H
+#include "UICLuaDebugger.h"
+#include "UICLuaDebuggerProtocol.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/FileTools.h"
+#include "foundation/StringConversionImpl.h"
+#include "EASTL/set.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+/**
+ * The caching system is fairly simple. Basically, the sender side keeps track of table and
+ *function info values and sends the entire table
+ * or function info if something is different than expected.
+ *
+ * On top of this design you have a system that just sends item pointers when possible, and it
+ *allows the server side to
+ * request the actual data behind the pointers when necessary. This minimizes the amount of
+ *information sent.
+ *
+ * The server side needs to know when the lua side has ended its update so that it knows to ask
+ *the lua side
+ * when to re-check various tables for changes.
+ *
+ */
+
+namespace {
+
+typedef eastl::hash_map<const void *, eastl::vector<STableEntry>> TTableToDataMap;
+typedef eastl::hash_map<const void *, lua::SFunctionInfo> TFunctionToInfoMap;
+typedef eastl::hash_set<const void *> TVoidPtrSet;
+
+struct SRuntimeDataCache : public ILuaRuntimeDataCache
+{
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ IDebugOutStream &m_Stream;
+ QT3DSU64 m_ClientId;
+ lua::SLuaDebuggerProtocolWriter m_ProtocolWriter;
+ TDebugStr m_WorkStr;
+ TDebugStr m_RelativeStr;
+ TDebugStr m_BaseStr;
+ QT3DSI32 mRefCount;
+
+ eastl::set<const void *> m_ScannedTables;
+ TTableToDataMap m_TableCache;
+ TFunctionToInfoMap m_FunctionCache;
+ char m_ConvertBuffer[256];
+
+ SRuntimeDataCache(NVFoundationBase &fnd, IStringTable &strTable, IDebugOutStream &stream,
+ QT3DSU64 cid, const char *inProjectDir)
+ : m_Foundation(fnd)
+ , m_StringTable(strTable)
+ , m_Stream(stream)
+ , m_ClientId(cid)
+ , m_ProtocolWriter(stream, fnd.getAllocator())
+ , m_BaseStr(nonNull(inProjectDir))
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ QT3DSU64 ToClientId() const { return m_ClientId; }
+
+ template <typename TMsgType>
+ void WriteMessage(const TMsgType &msg)
+ {
+ m_ProtocolWriter.WriteMessage(ToClientId(), const_cast<TMsgType &>(msg));
+ }
+
+ SDatamodelValue ToValue(lua_State &state, QT3DSI32 stackIdx)
+ {
+ switch (lua_type(&state, stackIdx)) {
+ case LUA_TBOOLEAN:
+ return lua_toboolean(&state, stackIdx) ? true : false;
+ case LUA_TNIL:
+ return SNil();
+
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ return reinterpret_cast<SDatamodelUserData *>(lua_touserdata(&state, stackIdx));
+
+ case LUA_TNUMBER:
+ return lua_tonumber(&state, stackIdx);
+ case LUA_TSTRING:
+ return TDebugStr(lua_tostring(&state, stackIdx));
+ case LUA_TTABLE:
+ return reinterpret_cast<SDatamodelTable *>((void *)lua_topointer(&state, stackIdx));
+ case LUA_TFUNCTION:
+ return reinterpret_cast<SDatamodelFunction *>((void *)lua_topointer(&state, stackIdx));
+ case LUA_TTHREAD:
+ return reinterpret_cast<SDatamodelThread *>((void *)lua_topointer(&state, stackIdx));
+ default:
+ QT3DS_ASSERT(false);
+ return SDatamodelValue();
+ }
+ }
+
+ static const char *GetPointerMapName() { return "uic-runtime-cache-ptr-map"; }
+
+ const char *PtrToKey(const void *ptr)
+ {
+ QT3DSU64 ptrVal = static_cast<QT3DSU64>(reinterpret_cast<size_t>(ptr));
+ StringConversion<QT3DSU64>().ToStr(ptrVal, toDataRef(m_ConvertBuffer, 256));
+ return m_ConvertBuffer;
+ }
+ // take the object at the top of the stack (either function or table)
+ // and store it away in a registry map. This allows us to defer scanning the object
+ // potentially forever
+ void MapPointerToLuaObject(lua_State &state, QT3DSI32 stackIdx)
+ {
+ const void *ptrValue = lua_topointer(&state, stackIdx);
+
+ if (m_ScannedTables.find(ptrValue) != m_ScannedTables.end())
+ return;
+
+ if (lua_type(&state, stackIdx) == LUA_TTABLE
+ || lua_type(&state, stackIdx) == LUA_TFUNCTION) {
+ lua_pushvalue(&state, stackIdx);
+ lua_getfield(&state, LUA_REGISTRYINDEX, GetPointerMapName());
+ if (lua_isnil(&state, -1)) {
+ lua_pop(&state, 1);
+ lua_newtable(&state);
+ lua_pushvalue(&state, -1);
+ lua_setfield(&state, LUA_REGISTRYINDEX, GetPointerMapName());
+ }
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TTABLE);
+ lua_insert(&state, -2);
+ lua_setfield(&state, -2, PtrToKey(ptrValue));
+ // knock the registry table off the stack.
+ lua_pop(&state, 1);
+ }
+ }
+
+ // If function fails, then nil is left on stack
+ void GetLuaObjectFromPointer(lua_State &state, void *ptrAddr)
+ {
+ lua_getfield(&state, LUA_REGISTRYINDEX, GetPointerMapName());
+ if (lua_istable(&state, -1)) {
+ lua_getfield(&state, -1, PtrToKey(ptrAddr));
+ // knock the original table off the map.
+ lua_insert(&state, -2);
+ lua_pop(&state, 1);
+ }
+ }
+
+ void CacheTable(lua_State &state, QT3DSI32 stackIdx)
+ {
+ QT3DS_ASSERT(lua_type(&state, stackIdx) == LUA_TTABLE);
+ int tableTop = lua_gettop(&state);
+ if (lua_type(&state, stackIdx) == LUA_TTABLE) {
+ const void *tableAddr = lua_topointer(&state, stackIdx);
+ if (m_ScannedTables.find(tableAddr) != m_ScannedTables.end())
+ return;
+ m_ScannedTables.insert(tableAddr);
+ SDatamodelTable *theTable = (SDatamodelTable *)tableAddr;
+ eastl::vector<STableEntry> &existing =
+ m_TableCache.insert(eastl::make_pair(tableAddr, eastl::vector<STableEntry>()))
+ .first->second;
+
+ bool sendTable = false;
+ // push the table to the top so the relative addressing will work.
+ lua_pushvalue(&state, stackIdx);
+ // Iterate through keys ensuring that we get a valid table entry for each key.
+ lua_pushnil(&state);
+ QT3DSU32 idx = 0;
+ while (lua_next(&state, -2) != 0) {
+ SDatamodelValue theValue(ToValue(state, -1));
+ int originalTop = lua_gettop(&state);
+ if (theValue.getType() == DatamodelValueTypes::Table
+ || theValue.getType() == DatamodelValueTypes::Function) {
+ // store it off for later.
+ MapPointerToLuaObject(state, -1);
+ }
+
+ int newtop = lua_gettop(&state);
+ QT3DS_ASSERT(originalTop == newtop);
+ (void)newtop;
+ (void)originalTop;
+
+ // dup the key so the tostring function doesn't change the actual table key type
+ lua_pushvalue(&state, -2);
+ const char *keyVal = lua_tostring(&state, -1);
+ STableEntry entry(keyVal, theValue);
+ if (idx >= existing.size() || ((existing[idx] == entry) == false)) {
+ if (idx >= existing.size())
+ existing.push_back(entry);
+ else
+ existing[idx] = entry;
+ sendTable = true;
+ }
+ ++idx;
+ // pop value and dupped key off the stack.
+ lua_pop(&state, 2);
+ }
+ // pop table off top.
+ lua_pop(&state, 1);
+
+ if (existing.size() != idx) {
+ sendTable = true;
+ existing.resize(idx);
+ }
+ if (sendTable) {
+ lua::STableData theData(*theTable,
+ toConstDataRef(existing.data(), existing.size()));
+ WriteMessage(lua::SUpdateTable(theData));
+ }
+ }
+ int finalTop = lua_gettop(&state);
+ QT3DS_ASSERT(finalTop == tableTop);
+ (void)finalTop;
+ (void)tableTop;
+ }
+
+ CRegisteredString ToRelative(const char *inFilePath)
+ {
+ m_RelativeStr.assign(nonNull(inFilePath));
+ CFileTools::GetRelativeFromBase(m_BaseStr, m_RelativeStr, m_WorkStr);
+ return m_StringTable.RegisterStr(m_WorkStr.c_str());
+ }
+
+ void CacheFunction(lua_State &state, QT3DSI32 stackIdx)
+ {
+ QT3DS_ASSERT(lua_type(&state, stackIdx) == LUA_TFUNCTION);
+ if (lua_type(&state, stackIdx) == LUA_TFUNCTION) {
+ const void *fn_addr = lua_topointer(&state, stackIdx);
+ if (m_ScannedTables.find(fn_addr) != m_ScannedTables.end())
+ return;
+ m_ScannedTables.insert(fn_addr);
+
+ lua_getfenv(&state, stackIdx);
+ SDatamodelTable *env = (SDatamodelTable *)lua_topointer(&state, -1);
+ MapPointerToLuaObject(state, -1);
+ lua_pop(&state, 1);
+ SDatamodelFunction *fn = (SDatamodelFunction *)lua_topointer(&state, stackIdx);
+
+ // dup the function to top of stack for the getinfo call.
+ lua_pushvalue(&state, stackIdx);
+
+ lua_Debug ar;
+ lua_getinfo(&state, ">S", &ar);
+ SFileAndLine fnData;
+ if (!isTrivial(ar.source) && ar.source[0] == '@') {
+ fnData.m_File = ToRelative(ar.source + 1);
+ fnData.m_Line = ar.linedefined;
+ } else if (!isTrivial(ar.source)) {
+ fnData.m_File = m_StringTable.RegisterStr(ar.source);
+ }
+
+ lua::SFunctionInfo theInfo(*fn, fnData, *env);
+ lua::SFunctionInfo &existingInfo(
+ m_FunctionCache.insert(eastl::make_pair(fn_addr, lua::SFunctionInfo()))
+ .first->second);
+ if (existingInfo != theInfo) {
+ existingInfo = theInfo;
+ WriteMessage(lua::SUpdateFunction(theInfo));
+ }
+ }
+ }
+
+ void BeginUpdate() override { WriteMessage(lua::SBeginCacheUpdate()); }
+
+ SDatamodelValue CacheValue(lua_State &state, QT3DSI32 stackIdx = -1) override
+ {
+ switch (lua_type(&state, stackIdx)) {
+ case LUA_TTABLE:
+ CacheTable(state, stackIdx);
+ break;
+ case LUA_TFUNCTION:
+ CacheFunction(state, stackIdx);
+ break;
+ default:
+ break;
+ }
+ return ToValue(state, stackIdx);
+ }
+
+ void EndUpdate(lua_State &state) override
+ {
+ m_ScannedTables.clear();
+ lua_pushnil(&state);
+ lua_setfield(&state, LUA_REGISTRYINDEX, GetPointerMapName());
+ }
+
+ bool IsCacheMessage(lua::SLuaDebugMessageHeader &header) override
+ {
+ return header.m_MessageName == lua::SProtocolMessageNames::RequestPointerValue;
+ }
+
+ void HandleCacheMessage(lua_State *state, lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader & /*header*/) override
+ {
+ int top = lua_gettop(state);
+ (void)top;
+ lua::SRequestPointerValue theMessage = reader.ReadMessage<lua::SRequestPointerValue>();
+ void *ptrValue = NULL;
+ switch (theMessage.m_Data.getType()) {
+ case DatamodelValueTypes::Function:
+ ptrValue = theMessage.m_Data.getData<SDatamodelFunction *>();
+ break;
+ case DatamodelValueTypes::Table:
+ ptrValue = theMessage.m_Data.getData<SDatamodelTable *>();
+ break;
+ case DatamodelValueTypes::CFunction:
+ ptrValue = theMessage.m_Data.getData<SDatamodelCFunction *>();
+ break;
+ case DatamodelValueTypes::Thread:
+ ptrValue = theMessage.m_Data.getData<SDatamodelThread *>();
+ break;
+ default:
+ break;
+ }
+
+ if (ptrValue == NULL || state == NULL)
+ WriteMessage(lua::SUnknownPointerValue());
+ else {
+ // Get the object to be TOS
+ GetLuaObjectFromPointer(*state, ptrValue);
+ CacheValue(*state);
+ lua_pop(state, 1);
+ }
+ QT3DS_ASSERT(lua_gettop(state) == top);
+ WriteMessage(lua::SEndPointerRequest());
+ }
+};
+
+struct SArchitectCache : public ILuaArchitectDataCache
+{
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ TTableToDataMap m_TableCache;
+ TFunctionToInfoMap m_FunctionInfo;
+ IDebugOutStream &m_Stream;
+ ILuaArchitectDataCacheListener &m_Listener;
+ QT3DSU64 m_ClientId;
+ lua::SLuaDebuggerProtocolWriter m_ProtocolWriter;
+ TVoidPtrSet m_UpdatedPointers;
+ QT3DSI32 mRefCount;
+
+ SArchitectCache(NVFoundationBase &fnd, IStringTable &strTable, IDebugOutStream &stream,
+ ILuaArchitectDataCacheListener &listener, QT3DSU64 inClientId)
+ : m_Foundation(fnd)
+ , m_StringTable(strTable)
+ , m_Stream(stream)
+ , m_Listener(listener)
+ , m_ClientId(inClientId)
+ , m_ProtocolWriter(stream, fnd.getAllocator())
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ QT3DSU64 ToClientId() const { return m_ClientId; }
+
+ template <typename TMsgType>
+ void WriteMessage(const TMsgType &msg)
+ {
+ m_ProtocolWriter.WriteMessage(ToClientId(), const_cast<TMsgType &>(msg));
+ }
+
+ void RequestPointerValue(const SDatamodelValue &inValue)
+ {
+ WriteMessage(lua::SRequestPointerValue(inValue));
+ while (m_Stream.Connected()) {
+ SDebugStreamMessage message = m_Stream.WaitForNextMessage();
+ if (message.m_Data.size() == 0)
+ return;
+ lua::SLuaDebuggerProtocolReader theReader(message.m_Data, m_StringTable);
+ while (theReader.HasData()) {
+ lua::SLuaDebugMessageHeader theHeader = theReader.ReadHeader();
+ if (theHeader.m_MessageName == lua::SProtocolMessageNames::EndPointerRequest)
+ return;
+ if (IsCacheMessage(theHeader)) {
+ HandleCacheMessage(theReader, theHeader);
+ } else
+ m_Listener.HandleMessage(theReader, theHeader);
+ }
+ }
+ }
+
+ template <typename TDataType>
+ void EnsurePointerIsUpToDate(TDataType &dtype)
+ {
+ const void *ptrAddr = &dtype;
+ bool needsUpdate = m_UpdatedPointers.insert(ptrAddr).second;
+ if (needsUpdate) {
+ RequestPointerValue(&dtype);
+ }
+ }
+
+ SFunctionInfo GetFunctionInfo(SDatamodelFunction &inFunction) override
+ {
+ EnsurePointerIsUpToDate(inFunction);
+ TFunctionToInfoMap::iterator iter = m_FunctionInfo.find((void *)&inFunction);
+ if (iter != m_FunctionInfo.end())
+ return SFunctionInfo(*iter->second.m_Environment, iter->second.m_DefinitionLocation);
+ return SFunctionInfo();
+ }
+
+ NVConstDataRef<STableEntry> GetTableValues(SDatamodelTable &inTable) override
+ {
+ EnsurePointerIsUpToDate(inTable);
+ TTableToDataMap::iterator iter = m_TableCache.find((const void *)&inTable);
+ if (iter != m_TableCache.end())
+ return toConstDataRef(iter->second.data(), (QT3DSU32)iter->second.size());
+
+ return NVConstDataRef<STableEntry>();
+ }
+
+ // Allow transparent handling of cache protocol.
+ bool IsCacheMessage(lua::SLuaDebugMessageHeader &header) override
+ {
+ return header.m_MessageName == lua::SProtocolMessageNames::UpdateFunction
+ || header.m_MessageName == lua::SProtocolMessageNames::UpdateTable
+ || header.m_MessageName == lua::SProtocolMessageNames::EndPointerRequest
+ || header.m_MessageName == lua::SProtocolMessageNames::BeginCacheUpdate;
+ }
+
+ void HandleUpdateFunction(const lua::SUpdateFunction &inFunction)
+ {
+ // Hard set it to new value regardless of what is in there now.
+ const void *ptrAddr = inFunction.m_Data.m_Function;
+ m_FunctionInfo.insert(eastl::make_pair(ptrAddr, inFunction.m_Data)).first->second =
+ inFunction.m_Data;
+ m_UpdatedPointers.insert(ptrAddr);
+ }
+
+ void HandleUpdateTable(const lua::SUpdateTable &inTable)
+ {
+ const void *ptrAddr = inTable.m_Data.m_Table;
+ m_TableCache.insert(eastl::make_pair(ptrAddr, eastl::vector<STableEntry>()))
+ .first->second.assign(inTable.m_Data.m_TableData.begin(),
+ inTable.m_Data.m_TableData.end());
+ m_UpdatedPointers.insert(ptrAddr);
+ }
+
+ void HandleCacheMessage(lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader &header) override
+ {
+ switch (header.m_MessageName) {
+ case lua::SProtocolMessageNames::UpdateFunction:
+ HandleUpdateFunction(reader.ReadMessage<lua::SUpdateFunction>());
+ break;
+ case lua::SProtocolMessageNames::UpdateTable:
+ HandleUpdateTable(reader.ReadMessage<lua::SUpdateTable>());
+ break;
+ case lua::SProtocolMessageNames::EndPointerRequest:
+ break;
+ case lua::SProtocolMessageNames::BeginCacheUpdate:
+ m_UpdatedPointers.clear();
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ return;
+ }
+ }
+};
+}
+
+ILuaRuntimeDataCache &ILuaRuntimeDataCache::Create(NVFoundationBase &fnd, IStringTable &strTable,
+ IDebugOutStream &stream, QT3DSU64 clientId,
+ const char *inProjectDir)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SRuntimeDataCache)(fnd, strTable, stream, clientId,
+ inProjectDir);
+}
+
+ILuaArchitectDataCache &ILuaArchitectDataCache::Create(NVFoundationBase &fnd,
+ IStringTable &strTable,
+ IDebugOutStream &stream,
+ ILuaArchitectDataCacheListener &listener,
+ QT3DSU64 inClientId)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), SArchitectCache)(fnd, strTable, stream, listener,
+ inClientId);
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Debugger/UICLuaDebugger.h b/src/Runtime/Source/UICState/Debugger/UICLuaDebugger.h
new file mode 100644
index 00000000..9c7b2f89
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICLuaDebugger.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_LUA_DEBUGGER_H
+#define UIC_LUA_DEBUGGER_H
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerValues.h"
+
+struct lua_State;
+
+namespace uic {
+namespace state {
+ namespace debugger {
+ namespace lua {
+ struct SLuaDebugMessageHeader;
+ struct SLuaDebuggerProtocolReader;
+ }
+
+ typedef eastl::string TDebugStr;
+
+ struct SFileAndLine
+ {
+ CRegisteredString m_File;
+ int m_Line;
+
+ SFileAndLine(CRegisteredString inFile = CRegisteredString(), int inLine = 0)
+ : m_File(inFile)
+ , m_Line(inLine)
+ {
+ }
+ bool operator==(const SFileAndLine &other) const
+ {
+ return m_File == other.m_File && m_Line == other.m_Line;
+ }
+ };
+
+ struct SLuaBreakpoint : public SFileAndLine
+ {
+ CRegisteredString m_Condition;
+ SLuaBreakpoint(CRegisteredString inFile = CRegisteredString(), int inLine = 0,
+ CRegisteredString inCondition = CRegisteredString())
+ : SFileAndLine(inFile, inLine)
+ , m_Condition(inCondition)
+ {
+ }
+ };
+
+ class ILuaSideListener
+ {
+ protected:
+ virtual ~ILuaSideListener() {}
+ public:
+ virtual void OnBreak() = 0;
+ };
+
+ // Runtime side of the equation
+
+ class ILuaDebugger : public NVRefCounted
+ {
+ public:
+ // Installs ourself as the debug hook and waits for a command from the other end of the
+ // stream.
+ // We are stored under a special registry variable; there can be only one debugger per
+ // lua state.
+ static ILuaDebugger &CreateLuaSideDebugger(NVFoundationBase &inFoundation,
+ IDebugOutStream &inStream,
+ lua_State *inState, IStringTable &inStrTable,
+ const char *inApplicationDirectory,
+ ILuaSideListener *inListener = NULL);
+ };
+
+ struct SFunctionInfo
+ {
+ SDatamodelTable *m_Environment;
+ SFileAndLine m_DefinitionInfo;
+ SFunctionInfo()
+ : m_Environment(NULL)
+ {
+ }
+ SFunctionInfo(SDatamodelTable &env, SFileAndLine def)
+ : m_Environment(&env)
+ , m_DefinitionInfo(def)
+ {
+ }
+ };
+
+ struct SLuaStackInfo
+ {
+ SDatamodelValue m_Function;
+ QT3DSI32 m_CurrentLine;
+ CRegisteredString m_CallType;
+ NVConstDataRef<STableEntry> m_LocalVars;
+ NVConstDataRef<STableEntry> m_UpVars;
+ SLuaStackInfo()
+ : m_CurrentLine(0)
+ {
+ }
+ SLuaStackInfo(SDatamodelValue fn, QT3DSI32 cl, CRegisteredString calltype,
+ NVConstDataRef<STableEntry> lv, NVConstDataRef<STableEntry> uv)
+ : m_Function(fn)
+ , m_CurrentLine(cl)
+ , m_CallType(calltype)
+ , m_LocalVars(lv)
+ , m_UpVars(uv)
+ {
+ }
+ };
+
+ // Architect side of the equation.
+
+ class ILuaArchitectDebugClient;
+
+ class ILuaProcessInfo
+ {
+ protected:
+ virtual ~ILuaProcessInfo() {}
+ public:
+ // Only valid while broken. The stack trace is from top down, retval[0] is the
+ // currently
+ // executing function...
+ virtual NVConstDataRef<SLuaStackInfo> StackTrace(QT3DSI32 limit = 100) = 0;
+ virtual SFunctionInfo GetFunctionInfo(SDatamodelFunction &inFunction) = 0;
+ virtual NVConstDataRef<STableEntry> GetTableValues(SDatamodelTable &inTable) = 0;
+ };
+
+ class ILuaArchitectDebugClientListener : public NVRefCounted
+ {
+ public:
+ virtual void OnConnect(ILuaArchitectDebugClient &inClient) = 0;
+ // Do not hold onto the process info object. Getting process info only makes sense when
+ // the process is stopped, there is no guarantee
+ // the process info object will be valid or the same in between breakpoint calls.
+ virtual void OnClientBreak(ILuaArchitectDebugClient &inClient,
+ const SLuaBreakpoint &inBreakpoint) = 0;
+ virtual void OnWatchUpdated(ILuaArchitectDebugClient &inClient,
+ CRegisteredString inExpression,
+ const SDatamodelValue &value) = 0;
+ virtual void OnStatementExecuted(ILuaArchitectDebugClient &inClient,
+ CRegisteredString inExpression,
+ const eastl::string &inErrorMsg,
+ const eastl::vector<eastl::string> &inPrintStatements,
+ const eastl::vector<SDatamodelValue> &inResults) = 0;
+ // Gets called for both step and step-into
+ virtual void OnDisconnect(ILuaArchitectDebugClient &inClient) = 0;
+ };
+
+ // Interface to running lua system.
+ class ILuaArchitectDebugClient : public NVRefCounted
+ {
+ public:
+ virtual void SetBreakpoint(const char *inFileRelativePath, int inLine,
+ const char *inCondition) = 0;
+ virtual NVConstDataRef<SLuaBreakpoint> GetBreakpoints() = 0;
+ virtual void ClearBreakpoint(const char *inFileRelativePath, int inLine) = 0;
+ virtual void ClearAllBreakpoints() = 0;
+ virtual void RequestBreak() = 0;
+ virtual bool IsPaused() = 0;
+ // May return NULL!!
+ // Returns NULL when IsPaused() == false
+ virtual ILuaProcessInfo *GetProcessInfo() = 0;
+ virtual void Continue() = 0;
+ virtual void StepInto() = 0;
+ virtual void StepOver() = 0;
+ virtual void StepOut() = 0;
+ virtual void AddWatch(const char *inExpression) = 0;
+ virtual void RemoveWatch(const char *inExpression) = 0;
+ virtual void ExecuteStatement(const char *inExpression) = 0;
+ };
+
+ // Lua debug system that sits in architect, created when
+
+ class ILuaArchitectDebugServer : public NVRefCounted
+ {
+ public:
+ virtual void SetListener(ILuaArchitectDebugClientListener &inListener) = 0;
+ static const char *LuaProtocolName() { return "LuaDebugger"; }
+ static ILuaArchitectDebugServer &CreateLuaServer(IDebugOutStream &outStream);
+ };
+
+ // Implementation objects used to keept track of lua state.
+ class ILuaRuntimeDataCache : public NVRefCounted
+ {
+ protected:
+ virtual ~ILuaRuntimeDataCache() {}
+ public:
+ // Cache the value at the current stack position.
+ // Note that value types aren't cached, just tables and functions at this point.
+ // This may generate a (possibly large) set of messages to the underlying stream.
+ // In the future it would be awesome if this object hooked into the lua system's garbage
+ // collection
+ // write barrier to automatically update table values as they actually change.
+ virtual void BeginUpdate() = 0;
+ virtual SDatamodelValue CacheValue(lua_State &state, QT3DSI32 stackIdx = -1) = 0;
+ virtual void EndUpdate(lua_State &state) = 0;
+
+ virtual bool IsCacheMessage(lua::SLuaDebugMessageHeader &header) = 0;
+ virtual void HandleCacheMessage(lua_State *state,
+ lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader &header) = 0;
+ static ILuaRuntimeDataCache &Create(NVFoundationBase &fnd, IStringTable &strTable,
+ IDebugOutStream &stream, QT3DSU64 clientId,
+ const char *inProjectDir);
+ };
+
+ class ILuaArchitectDataCacheListener
+ {
+ protected:
+ virtual ~ILuaArchitectDataCacheListener() {}
+ public:
+ virtual void HandleMessage(lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader &header) = 0;
+ };
+
+ class ILuaArchitectDataCache : public NVRefCounted
+ {
+ protected:
+ virtual ~ILuaArchitectDataCache() {}
+ public:
+ virtual SFunctionInfo GetFunctionInfo(SDatamodelFunction &inFunction) = 0;
+ virtual NVConstDataRef<STableEntry> GetTableValues(SDatamodelTable &inTable) = 0;
+
+ // Allow transparent handling of cache protocol.
+ virtual bool IsCacheMessage(lua::SLuaDebugMessageHeader &header) = 0;
+ virtual void HandleCacheMessage(lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader &header) = 0;
+
+ static ILuaArchitectDataCache &Create(NVFoundationBase &fnd, IStringTable &strTable,
+ IDebugOutStream &stream,
+ ILuaArchitectDataCacheListener &listener,
+ QT3DSU64 inClientId);
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICLuaDebuggerImpl.h b/src/Runtime/Source/UICState/Debugger/UICLuaDebuggerImpl.h
new file mode 100644
index 00000000..086e4195
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICLuaDebuggerImpl.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_LUA_DEBUGGER_IMPL_H
+#define UIC_LUA_DEBUGGER_IMPL_H
+#include "UICLuaDebugger.h"
+#include "EASTL/hash_map.h"
+
+namespace eastl {
+template <>
+struct hash<uic::state::debugger::SFileAndLine>
+{
+ size_t operator()(const uic::state::debugger::SFileAndLine &data) const
+ {
+ return hash<qt3ds::foundation::CRegisteredString>()(data.m_File)
+ ^ hash<qt3ds::QT3DSU32>()(data.m_Line);
+ }
+};
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICLuaDebuggerProtocol.h b/src/Runtime/Source/UICState/Debugger/UICLuaDebuggerProtocol.h
new file mode 100644
index 00000000..8f605265
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICLuaDebuggerProtocol.h
@@ -0,0 +1,710 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_LUA_DEBUGGER_PROTOCOL_H
+#define UIC_LUA_DEBUGGER_PROTOCOL_H
+#include "UICLuaDebugger.h"
+#include "foundation/Qt3DSTime.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "foundation/SerializationTypes.h"
+
+namespace uic {
+namespace state {
+ namespace debugger {
+ namespace lua {
+
+#define UIC_LUA_DEBUGGER_ITERATE_PROTOCOL_MESSAGES \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(Initialization) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(SetBreakpoint) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(RequestBreak) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(RequestAllBreakpoints) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(AllBreakpoints) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(ClearBreakpoint) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(ClearAllBreakpoints) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(Continue) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(OnBreak) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(UpdateTable) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(UpdateFunction) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(RequestStackTrace) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(StackTrace) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(StepInto) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(StepOver) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(StepOut) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(AddWatch) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(RemoveWatch) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(WatchUpdated) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(ExecuteStatement) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(StatementExecuted) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(RequestPointerValue) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(UnknownPointerValue) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(EndPointerRequest) \
+ UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(BeginCacheUpdate)
+
+ struct SProtocolMessageNames
+ {
+ enum Enum {
+ UnknownMessageName = 0,
+#define UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(name) name,
+ UIC_LUA_DEBUGGER_ITERATE_PROTOCOL_MESSAGES
+#undef UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE
+ };
+ };
+
+ struct SLuaDebugMessageHeader
+ {
+ SProtocolMessageNames::Enum m_MessageName;
+ QT3DSU32 m_Padding;
+ QT3DSU64 m_ClientId;
+ SLuaDebugMessageHeader(
+ SProtocolMessageNames::Enum name = SProtocolMessageNames::UnknownMessageName,
+ QT3DSU64 cid = 0)
+ : m_MessageName(name)
+ , m_Padding(0)
+ , m_ClientId(cid)
+ {
+ }
+ bool operator==(const SLuaDebugMessageHeader &inOther) const
+ {
+ return m_MessageName == inOther.m_MessageName
+ && m_ClientId == inOther.m_ClientId;
+ }
+ };
+
+ template <typename TDType>
+ struct SMessageTypeToNameMap
+ {
+ };
+
+ typedef eastl::vector<SLuaBreakpoint> TBreakpointList;
+
+ inline QT3DSU32 CurrentDebuggerProtocolVersion() { return 1; }
+
+ struct STableData
+ {
+ SDatamodelTable *m_Table;
+ NVConstDataRef<STableEntry> m_TableData;
+ STableData()
+ : m_Table(NULL)
+ {
+ }
+ STableData(SDatamodelTable &t, NVConstDataRef<STableEntry> td)
+ : m_Table(&t)
+ , m_TableData(td)
+ {
+ }
+ bool operator==(const STableData &other) const { return m_Table == other.m_Table; }
+ };
+
+ struct SFunctionInfo
+ {
+ SDatamodelFunction *m_Function;
+ SFileAndLine m_DefinitionLocation;
+ SDatamodelTable *m_Environment;
+ SFunctionInfo()
+ : m_Function(NULL)
+ , m_Environment(NULL)
+ {
+ }
+
+ SFunctionInfo(SDatamodelFunction &fn, SFileAndLine loc, SDatamodelTable &env)
+ : m_Function(&fn)
+ , m_DefinitionLocation(loc)
+ , m_Environment(&env)
+ {
+ }
+
+ bool operator==(const SFunctionInfo &other) const
+ {
+ return m_Function == other.m_Function
+ && m_DefinitionLocation == other.m_DefinitionLocation
+ && m_Environment == other.m_Environment;
+ }
+ bool operator!=(const SFunctionInfo &other) const { return !(operator==(other)); }
+ };
+
+ struct SStackTraceData
+ {
+ NVConstDataRef<SLuaStackInfo> m_Stack;
+ SStackTraceData() {}
+ SStackTraceData(NVConstDataRef<SLuaStackInfo> st)
+ : m_Stack(st)
+ {
+ }
+ bool operator==(const SStackTraceData &) const { return false; }
+ };
+
+ struct SWatchUpdateData
+ {
+ CRegisteredString m_Expression;
+ SDatamodelValue m_Value;
+ SWatchUpdateData(CRegisteredString exp, const SDatamodelValue &val)
+ : m_Expression(exp)
+ , m_Value(val)
+ {
+ }
+ SWatchUpdateData() {}
+ bool operator==(const SWatchUpdateData &other) const
+ {
+ return m_Expression == other.m_Expression && m_Value == other.m_Value;
+ }
+ };
+
+ struct SStatementExecuteData
+ {
+ CRegisteredString m_Expression;
+ eastl::string m_Error;
+ eastl::vector<eastl::string> m_PrintStatements;
+ eastl::vector<SDatamodelValue> m_Values;
+ SStatementExecuteData() {}
+ SStatementExecuteData(CRegisteredString expr, const eastl::string &errorMsg,
+ const eastl::vector<eastl::string> &inPrintStatements,
+ const eastl::vector<SDatamodelValue> &inExecResults)
+ : m_Expression(expr)
+ , m_Error(errorMsg)
+ , m_PrintStatements(inPrintStatements)
+ , m_Values(inExecResults)
+ {
+ }
+ bool operator==(const SStatementExecuteData &other) const
+ {
+ return m_Expression == other.m_Expression && m_Error == other.m_Error
+ && m_PrintStatements == other.m_PrintStatements
+ && m_Values == other.m_Values;
+ }
+ };
+
+#define UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(msgName) \
+ struct S##msgName \
+ { \
+ S##msgName() {} \
+ ~S##msgName() {} \
+ template <typename TVisitor> \
+ void Visit(TVisitor &) \
+ { \
+ } \
+ bool operator==(const SInitialization &) const { return true; } \
+ }; \
+ template <> \
+ struct SMessageTypeToNameMap<S##msgName> \
+ { \
+ enum { MessageName = SProtocolMessageNames::msgName }; \
+ };
+
+#define UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(msgName, ptype, pname) \
+ struct S##msgName \
+ { \
+ ptype m_##pname; \
+ S##msgName(const ptype &in_##pname = ptype()) \
+ : m_##pname(in_##pname) \
+ { \
+ } \
+ ~S##msgName() {} \
+ template <typename TVisitor> \
+ void Visit(TVisitor &inVisitor) \
+ { \
+ inVisitor.visit(m_##pname); \
+ } \
+ bool operator==(const S##msgName &other) const { return m_##pname == other.m_##pname; } \
+ }; \
+ template <> \
+ struct SMessageTypeToNameMap<S##msgName> \
+ { \
+ enum { MessageName = SProtocolMessageNames::msgName }; \
+ };
+
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(Initialization, QT3DSU32, Version);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(SetBreakpoint, SLuaBreakpoint, Breakpoint);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(RequestAllBreakpoints);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(RequestBreak);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(AllBreakpoints, TBreakpointList,
+ Breakpoints);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(ClearBreakpoint, SLuaBreakpoint,
+ Breakpoint);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(ClearAllBreakpoints);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(Continue);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(OnBreak, SFileAndLine, Position);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(UpdateTable, STableData, Data);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(UpdateFunction, SFunctionInfo, Data);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(RequestStackTrace);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(StackTrace, SStackTraceData, Data);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(StepInto);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(StepOver);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(StepOut);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(AddWatch, CRegisteredString, Expression);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(RemoveWatch, CRegisteredString, Expression);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(WatchUpdated, SWatchUpdateData, Data);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(ExecuteStatement, CRegisteredString,
+ Expression);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(StatementExecuted, SStatementExecuteData,
+ Data);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_MESSAGE_1(RequestPointerValue, SDatamodelValue, Data);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(UnknownPointerValue);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(EndPointerRequest);
+ UIC_LUA_DEBUGGER_PROTOCOL_DECLARE_TRIVIAL_MESSAGE(BeginCacheUpdate);
+
+ struct SLuaDebuggerProtocolWriter
+ {
+ IOutStream &m_Stream;
+ MemoryBuffer<> m_WriteBuffer;
+ SLuaDebuggerProtocolWriter(IOutStream &s, NVAllocatorCallback &alloc)
+ : m_Stream(s)
+ , m_WriteBuffer(ForwardingAllocator(alloc, "LuaWriteBuffer"))
+ {
+ }
+ void visit(QT3DSU32 data) { m_WriteBuffer.write(data); }
+
+ template <typename TDataType>
+ void visitStr(const TDataType &str)
+ {
+ QT3DSU32 len = (QT3DSU32)strlen(str.c_str());
+ if (len)
+ ++len;
+ m_WriteBuffer.write(len);
+ // include the null character. This allows far easier reading of the stream
+ // from a memory buffer read from the stream.
+ if (len)
+ m_WriteBuffer.write(str.c_str(), len);
+ }
+
+ void visit(const TDebugStr &str) { visitStr(str); }
+
+ void visit(CRegisteredString str) { visitStr(str); }
+
+ template <typename TDatatype>
+ static QT3DSU64 ToU64(TDatatype *ptr)
+ {
+ return static_cast<QT3DSU64>(reinterpret_cast<size_t>(ptr));
+ }
+
+ void visit(SDatamodelTable *table) { m_WriteBuffer.write(ToU64(table)); }
+
+ void visit(SDatamodelFunction *table) { m_WriteBuffer.write(ToU64(table)); }
+
+ void visit(const SDatamodelValue &value)
+ {
+ QT3DSU32 type = (QT3DSU32)value.getType();
+ visit(type);
+ switch (type) {
+ case DatamodelValueTypes::UnknownType:
+ case DatamodelValueTypes::Nil:
+ break;
+ case DatamodelValueTypes::Boolean:
+ m_WriteBuffer.write(value.getData<bool>());
+ break;
+ case DatamodelValueTypes::Number:
+ m_WriteBuffer.write(value.getData<float>());
+ break;
+ case DatamodelValueTypes::String:
+ visit(value.getData<TDebugStr>());
+ break;
+ case DatamodelValueTypes::Table:
+ visit(value.getData<SDatamodelTable *>());
+ break;
+ case DatamodelValueTypes::UserData:
+ m_WriteBuffer.write(ToU64(value.getData<SDatamodelUserData *>()));
+ break;
+ case DatamodelValueTypes::Function:
+ visit(value.getData<SDatamodelFunction *>());
+ break;
+ case DatamodelValueTypes::CFunction:
+ m_WriteBuffer.write(ToU64(value.getData<SDatamodelCFunction *>()));
+ break;
+ case DatamodelValueTypes::Thread:
+ m_WriteBuffer.write(ToU64(value.getData<SDatamodelThread *>()));
+ break;
+ }
+ }
+
+ void visit(const SFileAndLine &data)
+ {
+ visit(data.m_File);
+ m_WriteBuffer.write(data.m_Line);
+ }
+
+ void visit(const STableEntry &data)
+ {
+ visit(data.m_Key);
+ visit(data.m_Value);
+ }
+
+ void visit(NVConstDataRef<STableEntry> data)
+ {
+ m_WriteBuffer.write((QT3DSU32)data.size());
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)data.size(); idx < end; ++idx) {
+ visit(data[idx]);
+ }
+ }
+
+ void visit(const STableData &data)
+ {
+ visit(data.m_Table);
+ visit(data.m_TableData);
+ }
+
+ void visit(const SFunctionInfo &data)
+ {
+ visit(data.m_Function);
+ visit(data.m_Environment);
+ visit(data.m_DefinitionLocation);
+ }
+
+ void visit(const SLuaBreakpoint &data)
+ {
+ visit(static_cast<const SFileAndLine &>(data));
+ visit(data.m_Condition);
+ }
+
+ void visit(const TBreakpointList &data)
+ {
+ QT3DSU32 len = (QT3DSU32)data.size();
+ visit(len);
+ for (QT3DSU32 idx = 0, end = data.size(); idx < end; ++idx)
+ visit(data[idx]);
+ }
+
+ void visit(const SLuaStackInfo &data)
+ {
+ visit(data.m_Function);
+ visit(data.m_CurrentLine);
+ visit(data.m_CallType);
+ visit(data.m_LocalVars);
+ visit(data.m_UpVars);
+ }
+
+ void visit(NVConstDataRef<SLuaStackInfo> data)
+ {
+ QT3DSU32 len = data.size();
+ visit(len);
+ for (QT3DSU32 idx = 0, end = len; idx < end; ++idx) {
+ visit(data[idx]);
+ }
+ }
+
+ void visit(const SStackTraceData &data) { visit(data.m_Stack); }
+
+ void visit(const SWatchUpdateData &data)
+ {
+ visit(data.m_Expression);
+ visit(data.m_Value);
+ }
+
+ template <typename TVecData>
+ void visitVector(const eastl::vector<TVecData> &inVec)
+ {
+ QT3DSU32 len = (QT3DSU32)inVec.size();
+ visit(len);
+ for (QT3DSU32 idx = 0, end = inVec.size(); idx < end; ++idx) {
+ visit(inVec[idx]);
+ }
+ }
+
+ void visit(const SStatementExecuteData &data)
+ {
+ visit(data.m_Expression);
+ visit(data.m_Error);
+ visitVector(data.m_PrintStatements);
+ visitVector(data.m_Values);
+ }
+
+ template <typename TMsgType>
+ void WriteMessage(QT3DSU64 clientId, TMsgType &msg)
+ {
+ SLuaDebugMessageHeader theHeader(
+ static_cast<SProtocolMessageNames::Enum>(
+ SMessageTypeToNameMap<TMsgType>::MessageName),
+ clientId);
+ m_WriteBuffer.write(theHeader);
+ msg.Visit(*this);
+ Flush();
+ };
+
+ void Flush()
+ {
+ if (m_WriteBuffer.size()) {
+ m_Stream.Write((NVConstDataRef<QT3DSU8>)m_WriteBuffer);
+ m_WriteBuffer.clear();
+ }
+ }
+ };
+
+ struct STempStackInfo
+ {
+ SDatamodelValue m_Function;
+ QT3DSI32 m_CurrentLine;
+ CRegisteredString m_CallType;
+ eastl::vector<STableEntry> m_LocalVars;
+ eastl::vector<STableEntry> m_UpVars;
+ STempStackInfo()
+ : m_CurrentLine(0)
+ {
+ }
+ STempStackInfo(const SLuaStackInfo &info)
+ : m_Function(info.m_Function)
+ , m_CurrentLine(info.m_CurrentLine)
+ , m_CallType(info.m_CallType)
+ {
+
+ m_LocalVars.assign(info.m_LocalVars.begin(), info.m_LocalVars.end());
+ m_UpVars.assign(info.m_UpVars.begin(), info.m_UpVars.end());
+ }
+ operator SLuaStackInfo() const
+ {
+ return SLuaStackInfo(
+ m_Function, m_CurrentLine, m_CallType,
+ toConstDataRef(m_LocalVars.data(), (QT3DSU32)m_LocalVars.size()),
+ toConstDataRef(m_UpVars.data(), (QT3DSU32)m_UpVars.size()));
+ }
+ };
+
+ struct SLuaDebuggerProtocolReader
+ {
+ IStringTable &m_StringTable;
+ TDebugStr m_TempStr;
+ SDataReader m_Reader;
+ eastl::vector<STableEntry> m_TableUpdateList;
+ eastl::vector<STempStackInfo> m_StackInfo;
+ eastl::vector<SLuaStackInfo> m_OutgoingInfo;
+
+ SLuaDebuggerProtocolReader(NVConstDataRef<QT3DSU8> msg, IStringTable &strTable)
+ : m_StringTable(strTable)
+ , m_Reader(const_cast<QT3DSU8 *>(msg.begin()), const_cast<QT3DSU8 *>(msg.end()))
+ {
+ }
+
+ bool HasData() const { return m_Reader.m_CurrentPtr < m_Reader.m_EndPtr; }
+
+ SLuaDebugMessageHeader ReadHeader()
+ {
+ return m_Reader.LoadRef<SLuaDebugMessageHeader>();
+ }
+
+ void visit(QT3DSU32 &data) { data = m_Reader.LoadRef<QT3DSU32>(); }
+
+ void visit(SFileAndLine &data)
+ {
+ visit(data.m_File);
+ data.m_Line = m_Reader.LoadRef<QT3DSU32>();
+ }
+
+ void visit(SLuaBreakpoint &data)
+ {
+ visit(static_cast<SFileAndLine &>(data));
+ visit(data.m_Condition);
+ }
+
+ void visit(TBreakpointList &data)
+ {
+ QT3DSU32 len = m_Reader.LoadRef<QT3DSU32>();
+ data.resize(len);
+ for (QT3DSU32 idx = 0, end = data.size(); idx < end; ++idx)
+ visit(data[idx]);
+ }
+
+ template <typename Datatype>
+ Datatype *visitOpaquePtr()
+ {
+ QT3DSU64 data = m_Reader.LoadRef<QT3DSU64>();
+ return reinterpret_cast<Datatype *>(static_cast<size_t>(data));
+ }
+
+ void visit(SDatamodelTable *&item) { item = visitOpaquePtr<SDatamodelTable>(); }
+
+ void visit(SDatamodelFunction *&item)
+ {
+ item = visitOpaquePtr<SDatamodelFunction>();
+ }
+
+ void visit(SDatamodelValue &item)
+ {
+ QT3DSU32 dataType = m_Reader.LoadRef<QT3DSU32>();
+ switch (dataType) {
+ case DatamodelValueTypes::UnknownType:
+ item = SDatamodelValue();
+ break;
+ case DatamodelValueTypes::Nil:
+ item = SDatamodelValue(SNil());
+ break;
+ case DatamodelValueTypes::Boolean:
+ item = SDatamodelValue(m_Reader.LoadRef<bool>());
+ break;
+ case DatamodelValueTypes::Number:
+ item = SDatamodelValue(m_Reader.LoadRef<float>());
+ break;
+ case DatamodelValueTypes::String: {
+ TDebugStr temp;
+ visit(temp);
+ item = SDatamodelValue(temp);
+ } break;
+ case DatamodelValueTypes::Table:
+ item = SDatamodelValue(visitOpaquePtr<SDatamodelTable>());
+ break;
+ case DatamodelValueTypes::UserData:
+ item = SDatamodelValue(visitOpaquePtr<SDatamodelUserData>());
+ break;
+ case DatamodelValueTypes::Function:
+ item = SDatamodelValue(visitOpaquePtr<SDatamodelFunction>());
+ break;
+ case DatamodelValueTypes::CFunction:
+ item = SDatamodelValue(visitOpaquePtr<SDatamodelCFunction>());
+ break;
+ case DatamodelValueTypes::Thread:
+ item = SDatamodelValue(visitOpaquePtr<SDatamodelThread>());
+ break;
+ default:
+ // probably going off the rails here.
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ void visit(TDebugStr &item)
+ {
+ QT3DSU32 len = m_Reader.LoadRef<QT3DSU32>();
+ if (len) {
+ const char *strData = (const char *)m_Reader.m_CurrentPtr;
+ m_Reader.m_CurrentPtr += len;
+ item.assign(strData, strData + len);
+ }
+ }
+
+ void visit(CRegisteredString &item)
+ {
+ QT3DSU32 len = m_Reader.LoadRef<QT3DSU32>();
+ if (len) {
+ const char *strData = (const char *)m_Reader.m_CurrentPtr;
+ m_Reader.m_CurrentPtr += len;
+ item = m_StringTable.RegisterStr(strData);
+ }
+ }
+
+ void visit(QT3DSI32 &item) { item = m_Reader.LoadRef<QT3DSI32>(); }
+
+ void visit(STableEntry &item)
+ {
+ visit(item.m_Key);
+ visit(item.m_Value);
+ }
+
+ void visit(NVConstDataRef<STableEntry> &item)
+ {
+ m_TableUpdateList.clear();
+ QT3DSU32 count = m_Reader.LoadRef<QT3DSU32>();
+ m_TableUpdateList.resize(count);
+ for (QT3DSU32 idx = 0, end = count; idx < end; ++idx)
+ visit(m_TableUpdateList[idx]);
+
+ item =
+ toConstDataRef(m_TableUpdateList.data(), (QT3DSU32)m_TableUpdateList.size());
+ }
+
+ void visit(lua::STableData &data)
+ {
+ visit(data.m_Table);
+ visit(data.m_TableData);
+ }
+
+ void visit(lua::SFunctionInfo &item)
+ {
+ visit(item.m_Function);
+ visit(item.m_Environment);
+ visit(item.m_DefinitionLocation);
+ }
+
+ void visit(eastl::vector<STableEntry> &item)
+ {
+ QT3DSU32 len = m_Reader.LoadRef<QT3DSU32>();
+ if (len) {
+ item.resize(len);
+ for (QT3DSU32 idx = 0, end = len; idx < end; ++idx)
+ visit(item[idx]);
+ }
+ }
+
+ void visit(STempStackInfo &info)
+ {
+ visit(info.m_Function);
+ visit(info.m_CurrentLine);
+ visit(info.m_CallType);
+ visit(info.m_LocalVars);
+ visit(info.m_UpVars);
+ }
+
+ void visit(NVConstDataRef<SLuaStackInfo> &item)
+ {
+ m_StackInfo.clear();
+ QT3DSU32 len = m_Reader.LoadRef<QT3DSU32>();
+ m_StackInfo.resize(len);
+ for (QT3DSU32 idx = 0, end = len; idx < end; ++idx) {
+ visit(m_StackInfo[idx]);
+ }
+
+ m_OutgoingInfo.assign(m_StackInfo.begin(), m_StackInfo.end());
+ item = toConstDataRef(m_OutgoingInfo.data(), (QT3DSU32)m_OutgoingInfo.size());
+ }
+
+ void visit(lua::SStackTraceData &data) { visit(data.m_Stack); }
+
+ void visit(SWatchUpdateData &data)
+ {
+ visit(data.m_Expression);
+ visit(data.m_Value);
+ }
+
+ template <typename TVecData>
+ void visitVec(eastl::vector<TVecData> &inVec)
+ {
+ QT3DSU32 len = 0;
+ visit(len);
+ inVec.resize(len);
+ for (QT3DSU32 idx = 0, end = len; idx < end; ++idx) {
+ visit(inVec[idx]);
+ }
+ }
+
+ void visit(SStatementExecuteData &data)
+ {
+ visit(data.m_Expression);
+ visit(data.m_Error);
+ visitVec(data.m_PrintStatements);
+ visitVec(data.m_Values);
+ }
+
+ template <typename TMsgType>
+ TMsgType ReadMessage()
+ {
+ TMsgType retval;
+ retval.Visit(*this);
+ return retval;
+ }
+ };
+ }
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICLuaSideDebugger.cpp b/src/Runtime/Source/UICState/Debugger/UICLuaSideDebugger.cpp
new file mode 100644
index 00000000..6d58e077
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICLuaSideDebugger.cpp
@@ -0,0 +1,1176 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICLuaDebugger.h"
+#include "UICLuaDebuggerProtocol.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICLuaDebuggerImpl.h"
+#include "foundation/Qt3DSAtomic.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace qt3ds::foundation;
+using namespace uic::state::debugger;
+using namespace uic::state::debugger::lua;
+using namespace qt3ds;
+
+namespace {
+
+struct STopScope
+{
+ lua_State *m_LuaState;
+ int m_Top;
+ STopScope(lua_State *inState)
+ : m_LuaState(inState)
+ , m_Top(lua_gettop(inState))
+ {
+ }
+ ~STopScope() { lua_settop(m_LuaState, m_Top); }
+};
+
+struct SActiveBreakInfo
+{
+ enum Enum {
+ None = 0,
+ Step,
+ StepInto,
+ };
+ Enum m_Reason;
+ SFileAndLine m_PreviousBreak;
+ SActiveBreakInfo()
+ : m_Reason(None)
+ {
+ }
+ SActiveBreakInfo(Enum reason, const SFileAndLine data)
+ : m_Reason(reason)
+ , m_PreviousBreak(data)
+ {
+ }
+};
+
+struct BreakTestTypes
+{
+ enum Enum {
+ UnknownBreakTestType,
+ BreakRequested,
+ StepOut,
+ StepOver,
+ };
+};
+
+struct SBreakRequestedTest
+{
+};
+struct SStepOutTest
+{
+ QT3DSI32 m_StackDepth;
+ SStepOutTest()
+ : m_StackDepth(0)
+ {
+ }
+ SStepOutTest(QT3DSI32 sd)
+ : m_StackDepth(sd)
+ {
+ }
+};
+struct SStepOverTest
+{
+ QT3DSI32 m_StackDepth;
+ SFileAndLine m_Line;
+ SStepOverTest()
+ : m_StackDepth(0)
+ {
+ }
+ SStepOverTest(QT3DSI32 sd, SFileAndLine line)
+ : m_StackDepth(sd)
+ , m_Line(line)
+ {
+ }
+};
+
+template <typename TDataType>
+struct BreakTestTypeId
+{
+};
+
+template <>
+struct BreakTestTypeId<SBreakRequestedTest>
+{
+ static BreakTestTypes::Enum GetType() { return BreakTestTypes::BreakRequested; }
+};
+template <>
+struct BreakTestTypeId<SStepOutTest>
+{
+ static BreakTestTypes::Enum GetType() { return BreakTestTypes::StepOut; }
+};
+template <>
+struct BreakTestTypeId<SStepOverTest>
+{
+ static BreakTestTypes::Enum GetType() { return BreakTestTypes::StepOver; }
+};
+}
+namespace qt3ds {
+namespace foundation {
+ template <>
+ struct DestructTraits<SBreakRequestedTest>
+ {
+ static void destruct(SBreakRequestedTest &) {}
+ };
+ template <>
+ struct DestructTraits<SStepOutTest>
+ {
+ static void destruct(SStepOutTest &) {}
+ };
+ template <>
+ struct DestructTraits<SStepOverTest>
+ {
+ static void destruct(SStepOverTest &) {}
+ };
+}
+}
+
+namespace {
+
+struct SBreakTestValueTraits
+{
+ typedef BreakTestTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(SStepOverTest),
+ };
+
+ static TIdType getNoDataId() { return BreakTestTypes::UnknownBreakTestType; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return BreakTestTypeId<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case BreakTestTypes::BreakRequested:
+ return inVisitor(*NVUnionCast<SBreakRequestedTest *>(inData));
+ case BreakTestTypes::StepOut:
+ return inVisitor(*NVUnionCast<SStepOutTest *>(inData));
+ case BreakTestTypes::StepOver:
+ return inVisitor(*NVUnionCast<SStepOverTest *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case BreakTestTypes::UnknownBreakTestType:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case BreakTestTypes::BreakRequested:
+ return inVisitor(*NVUnionCast<const SBreakRequestedTest *>(inData));
+ case BreakTestTypes::StepOut:
+ return inVisitor(*NVUnionCast<const SStepOutTest *>(inData));
+ case BreakTestTypes::StepOver:
+ return inVisitor(*NVUnionCast<const SStepOverTest *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case BreakTestTypes::UnknownBreakTestType:
+ return inVisitor();
+ }
+ }
+};
+
+typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SBreakTestValueTraits,
+ SBreakTestValueTraits::TBufferSize>,
+ SBreakTestValueTraits::TBufferSize>
+ TBreakTestUnionType;
+
+struct SBreakTest : public TBreakTestUnionType
+{
+ typedef TBreakTestUnionType base;
+ SBreakTest() {}
+ SBreakTest(SBreakRequestedTest value)
+ : base(value)
+ {
+ }
+ SBreakTest(SStepOutTest value)
+ : base(value)
+ {
+ }
+ SBreakTest(SStepOverTest value)
+ : base(value)
+ {
+ }
+ SBreakTest(const SBreakTest &other)
+ : base(static_cast<const base &>(other))
+ {
+ }
+ SBreakTest &operator=(const SBreakTest &other)
+ {
+ base::operator=(other);
+ return *this;
+ }
+};
+
+const char *GetCachedEnvironmentName()
+{
+ return "lua_debugger_cached_environment";
+}
+
+struct SDataCacheUpdateWatcher
+{
+ lua_State &m_LuaState;
+ ILuaRuntimeDataCache &m_DataCache;
+ SDataCacheUpdateWatcher(lua_State &state, ILuaRuntimeDataCache &dc)
+ : m_LuaState(state)
+ , m_DataCache(dc)
+ {
+ m_DataCache.BeginUpdate();
+ }
+ ~SDataCacheUpdateWatcher()
+ {
+ m_DataCache.EndUpdate(m_LuaState);
+ lua_pushnil(&m_LuaState);
+ lua_setfield(&m_LuaState, LUA_REGISTRYINDEX, GetCachedEnvironmentName());
+ }
+};
+
+struct SLuaInternalBreakpoint : public SLuaBreakpoint
+{
+ bool m_CompileError;
+ SLuaInternalBreakpoint()
+ : m_CompileError(false)
+ {
+ }
+ SLuaInternalBreakpoint(const SLuaBreakpoint &other)
+ : SLuaBreakpoint(other)
+ , m_CompileError(false)
+ {
+ }
+ SLuaInternalBreakpoint &operator=(const SLuaBreakpoint &other)
+ {
+ SLuaBreakpoint::operator=(other);
+ m_CompileError = false;
+ return *this;
+ }
+};
+
+struct SWatchModifier
+{
+ eastl::string m_Str;
+
+ eastl::string modify(const char *inStr)
+ {
+ m_Str.assign(inStr);
+
+ eastl::string::size_type nonSpacePos = m_Str.find_first_not_of(" \n\r\t");
+ // eatwhite
+ if (nonSpacePos != eastl::string::npos && nonSpacePos > 0) {
+ m_Str.erase(m_Str.begin(), m_Str.begin() + nonSpacePos);
+ }
+
+ if (m_Str.size()) {
+ if (m_Str.find("return ")) {
+ m_Str.insert(0, "return ");
+ }
+ }
+
+ return m_Str;
+ }
+};
+
+struct SConsoleModifier
+{
+
+ eastl::string m_Str;
+
+ eastl::string modify(const char *inStr, int nPass = 1)
+ {
+
+ m_Str.assign(inStr);
+ m_Str.ltrim();
+ if (m_Str.size()) {
+ if (nPass == 1) {
+ if (m_Str[0] == '=') {
+ m_Str.erase(m_Str.begin(), m_Str.begin() + 1);
+ m_Str.ltrim();
+ }
+
+ eastl::replace(m_Str.begin(), m_Str.end(), '\n', ' ');
+ } else {
+ if (m_Str.find("return ")) {
+ m_Str.insert(0, "return ");
+ }
+ }
+ }
+
+ return m_Str;
+ }
+};
+
+// Runtime side LuaDebugger client
+// provides handlers for server commands from Architect
+// Registers a debug hook that performs break test
+struct SLuaSideDebugger : public ILuaDebugger, public IDebugStreamListener
+{
+ typedef eastl::hash_map<SFileAndLine, SLuaInternalBreakpoint, eastl::hash<SFileAndLine>,
+ eastl::equal_to<SFileAndLine>, ForwardingAllocator>
+ TBreakpointMap;
+ typedef eastl::vector<CRegisteredString, ForwardingAllocator> TWatchList;
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IDebugOutStream> m_Stream;
+ lua_State *m_LuaState;
+ IStringTable &m_StringTable;
+ SLuaDebuggerProtocolWriter m_ProtocolWriter;
+ CRegisteredString m_ApplicationDir;
+ TBreakpointMap m_Breakpoints;
+ lua::TBreakpointList m_BreakpointList;
+ TWatchList m_Watches;
+ Option<SActiveBreakInfo> m_ActiveBreakInfo;
+ NVScopedRefCounted<ILuaRuntimeDataCache> m_DataCache;
+ SStatementExecuteData m_StatementExecutionResult;
+
+ SBreakTest m_BreakTest;
+
+ TDebugStr m_BaseStr;
+ TDebugStr m_RelativeStr;
+ TDebugStr m_WorkStr;
+ TDebugStr m_SrcStr;
+
+ ILuaSideListener *m_Listener;
+ bool m_IgnoreDebugHook;
+ lua_State *m_BrokenState;
+
+ QT3DSI32 mRefCount;
+
+ struct SStackState
+ {
+ lua_State *&m_Value;
+ SStackState(lua_State *&inValue)
+ : m_Value(inValue)
+ {
+ }
+ ~SStackState() { m_Value = NULL; }
+ };
+
+ struct SStackBool
+ {
+ bool &m_Value;
+ SStackBool(bool &inValue)
+ : m_Value(inValue)
+ {
+ m_Value = true;
+ }
+ ~SStackBool() { m_Value = false; }
+ };
+
+ SLuaSideDebugger(NVFoundationBase &fnd, IDebugOutStream &inStream, lua_State *inState,
+ IStringTable &inStrTable, const char *inApplicationDirectory,
+ ILuaSideListener *inListener)
+ : m_Foundation(fnd)
+ , m_Stream(inStream)
+ , m_LuaState(inState)
+ , m_StringTable(inStrTable)
+ , m_ProtocolWriter(inStream, fnd.getAllocator())
+ , m_ApplicationDir(m_StringTable.RegisterStr(inApplicationDirectory))
+ , m_Breakpoints(ForwardingAllocator(fnd.getAllocator(), "LuaDebuggerBreakpoints"))
+ , m_Watches(ForwardingAllocator(fnd.getAllocator(), "LuaDebuggerWatches"))
+ , m_Listener(inListener)
+ , m_IgnoreDebugHook(false)
+ , m_BrokenState(NULL)
+ , mRefCount(0)
+ {
+ lua_pushlightuserdata(m_LuaState, this);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uic_lua_debugger_impl");
+ lua_sethook(m_LuaState, DebugHook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 0);
+ m_BaseStr.assign(m_ApplicationDir.c_str());
+ m_Stream->SetListener(this);
+ m_DataCache = ILuaRuntimeDataCache::Create(fnd, inStrTable, inStream, ToClientId(),
+ inApplicationDirectory);
+ WriteMessage(lua::SInitialization(CurrentDebuggerProtocolVersion()));
+ // The client starts broken so we can update breakpoints and such before any lua code runs.
+ SDataCacheUpdateWatcher watcher(*m_LuaState, *m_DataCache);
+ HandleBroken(*inState, -1);
+ }
+
+ ~SLuaSideDebugger() {}
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ //// IDebugStreamListener
+ //////////////////////////////////////////////////////////////////////////////////////
+ void OnMessageReceived(const SDebugStreamMessage &inMessage) override
+ {
+ SLuaDebuggerProtocolReader theReader(inMessage.m_Data, m_StringTable);
+ while (theReader.HasData()) {
+ SLuaDebugMessageHeader theHeader = theReader.ReadHeader();
+ HandleNextMessage(theReader, theHeader);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ //// Dispatch asynchronous messages
+ //////////////////////////////////////////////////////////////////////////////////////
+ void HandleNextMessage(SLuaDebuggerProtocolReader &inReader, SLuaDebugMessageHeader &inMessage)
+ {
+ if (m_DataCache->IsCacheMessage(inMessage)) {
+ m_DataCache->HandleCacheMessage(m_BrokenState, inReader, inMessage);
+ } else {
+ switch (inMessage.m_MessageName) {
+#define UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(name) \
+ case SProtocolMessageNames::name: \
+ Handle##name(inReader); \
+ break;
+ UIC_LUA_DEBUGGER_ITERATE_PROTOCOL_MESSAGES
+#undef UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+
+#define UIC_LUA_IGNORE_MESSAGE(name) \
+ void Handle##name(SLuaDebuggerProtocolReader &) { QT3DS_ASSERT(false); }
+ UIC_LUA_IGNORE_MESSAGE(Initialization)
+ UIC_LUA_IGNORE_MESSAGE(AllBreakpoints)
+ UIC_LUA_IGNORE_MESSAGE(Continue)
+ UIC_LUA_IGNORE_MESSAGE(OnBreak)
+ UIC_LUA_IGNORE_MESSAGE(OnClientConnect)
+ UIC_LUA_IGNORE_MESSAGE(UpdateTable)
+ UIC_LUA_IGNORE_MESSAGE(UpdateFunction)
+ UIC_LUA_IGNORE_MESSAGE(RequestStackTrace)
+ UIC_LUA_IGNORE_MESSAGE(StackTrace)
+ UIC_LUA_IGNORE_MESSAGE(StepInto)
+ UIC_LUA_IGNORE_MESSAGE(StepOver)
+ UIC_LUA_IGNORE_MESSAGE(StepOut)
+ UIC_LUA_IGNORE_MESSAGE(WatchUpdated)
+ UIC_LUA_IGNORE_MESSAGE(StatementExecuted)
+ UIC_LUA_IGNORE_MESSAGE(RequestPointerValue)
+ UIC_LUA_IGNORE_MESSAGE(UnknownPointerValue)
+ UIC_LUA_IGNORE_MESSAGE(EndPointerRequest)
+ UIC_LUA_IGNORE_MESSAGE(BeginCacheUpdate)
+
+ void HandleRequestBreak(SLuaDebuggerProtocolReader &)
+ {
+ m_BreakTest = SBreakTest(SBreakRequestedTest());
+ }
+
+ void HandleSetBreakpoint(SLuaDebuggerProtocolReader &inReader)
+ {
+ SSetBreakpoint message(inReader.ReadMessage<SSetBreakpoint>());
+ Option<SLuaBreakpoint> absolute =
+ ToAbsolute(message.m_Breakpoint.m_File.c_str(), message.m_Breakpoint.m_Line,
+ message.m_Breakpoint.m_Condition.c_str());
+ if (absolute.hasValue()) {
+ // insert a new breakpoint *or* override the existing breakpoint's member data
+ // with new information.
+ m_Breakpoints.insert(eastl::make_pair(*absolute, *absolute)).first->second = *absolute;
+ }
+ }
+
+ void HandleRequestAllBreakpoints(SLuaDebuggerProtocolReader &inReader)
+ {
+ SRequestAllBreakpoints message(inReader.ReadMessage<SRequestAllBreakpoints>());
+ m_BreakpointList.clear();
+ m_BreakpointList.reserve(m_Breakpoints.size());
+ for (TBreakpointMap::iterator iter = m_Breakpoints.begin(), end = m_Breakpoints.end();
+ iter != end; ++iter) {
+ m_BreakpointList.push_back(SLuaBreakpoint(ToRelative(iter->second.m_File.c_str()),
+ iter->second.m_Line,
+ iter->second.m_Condition));
+ }
+ SAllBreakpoints output(m_BreakpointList);
+ WriteMessage(output);
+ }
+
+ void HandleClearBreakpoint(SLuaDebuggerProtocolReader &inReader)
+ {
+ SClearBreakpoint message(inReader.ReadMessage<SClearBreakpoint>());
+ Option<SLuaBreakpoint> absolute =
+ ToAbsolute(message.m_Breakpoint.m_File.c_str(), message.m_Breakpoint.m_Line);
+ if (absolute.hasValue())
+ m_Breakpoints.erase(absolute);
+ }
+
+ void HandleClearAllBreakpoints(SLuaDebuggerProtocolReader &inReader)
+ {
+ SClearAllBreakpoints message(inReader.ReadMessage<SClearAllBreakpoints>());
+ m_Breakpoints.clear();
+ }
+
+ void HandleAddWatch(SLuaDebuggerProtocolReader &inReader)
+ {
+ SAddWatch message(inReader.ReadMessage<SAddWatch>());
+ if (message.m_Expression.IsValid()) {
+ TWatchList::iterator iter =
+ eastl::find(m_Watches.begin(), m_Watches.end(), message.m_Expression);
+ if (iter == m_Watches.end()) {
+ m_Watches.push_back(message.m_Expression);
+ if (m_BrokenState) {
+ EvaluateWatchExpression(*m_BrokenState, message.m_Expression);
+ }
+ }
+ }
+ }
+
+ void HandleRemoveWatch(SLuaDebuggerProtocolReader &inReader)
+ {
+ SRemoveWatch message(inReader.ReadMessage<SRemoveWatch>());
+ TWatchList::iterator iter =
+ eastl::find(m_Watches.begin(), m_Watches.end(), message.m_Expression);
+ if (iter != m_Watches.end())
+ m_Watches.erase(iter);
+ }
+
+ void HandleExecuteStatement(SLuaDebuggerProtocolReader &inReader)
+ {
+ SExecuteStatement message(inReader.ReadMessage<SExecuteStatement>());
+ if (m_BrokenState) {
+ EvaluateConsoleExpression(*m_BrokenState, message.m_Expression);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ //// hook
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ static void DebugHook(lua_State *state, lua_Debug *debugInfo)
+ {
+ SLuaSideDebugger *theThis = GetThisFromLua(state);
+ if (theThis && theThis->m_IgnoreDebugHook == false) {
+ switch (debugInfo->event) {
+ case LUA_HOOKLINE: {
+ // The focus of debug hook is check for break
+ theThis->CheckForBreak(state, debugInfo);
+ } break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // Do not use m_LuaState here. when someone executes things that has a side effect
+ // of creating a new lua state at times, and you need to use the lua state passed in
+ // on the stack, on the m_LuaState variable on this object.
+ void CheckForBreak(lua_State *state, lua_Debug * /*hookInfo*/)
+ {
+ lua_Debug stackInfo;
+ memset(&stackInfo, 0, sizeof(stackInfo));
+ if (lua_getstack(state, 0, &stackInfo)) {
+ // Ensure the datacache is cleared when we return to normal execution as we don't
+ // know what values change in the lua itself.
+ // This also resets the cached environment table.
+ SDataCacheUpdateWatcher cacheWatcher(*state, *m_DataCache);
+
+ // Are the files and such local or absolute?
+ // How does this work when things are loaded from the APK?
+ lua_getinfo(state, "nSlu", &stackInfo);
+ // The breakpoint check only works on source files
+ // which always start with an @ symbol.
+ TBreakpointMap::iterator iter = m_Breakpoints.end();
+ Option<SLuaBreakpoint> theBreakpoint;
+ if (stackInfo.currentline >= 0 && !isTrivial(stackInfo.source)
+ && stackInfo.source[0] == '@') {
+ theBreakpoint = ToAbsolute(stackInfo.source + 1, stackInfo.currentline);
+ if (theBreakpoint.hasValue()) {
+ SLuaBreakpoint theKey(theBreakpoint->m_File, theBreakpoint->m_Line);
+ iter = m_Breakpoints.find(theKey);
+ }
+ }
+
+ if (iter != m_Breakpoints.end()
+ || m_BreakTest.getType() != BreakTestTypes::UnknownBreakTestType) {
+
+ bool shouldDoBreak = true;
+
+ if (iter == m_Breakpoints.end()) {
+ switch (m_BreakTest.getType()) {
+ case BreakTestTypes::BreakRequested:
+ break;
+ case BreakTestTypes::StepOut: {
+ QT3DSI32 stackDepth = GetStackDepth(*state);
+ SStepOutTest &theTest = *m_BreakTest.getDataPtr<SStepOutTest>();
+ // We have popped up the stack once
+ shouldDoBreak = theTest.m_StackDepth > stackDepth;
+ } break;
+ case BreakTestTypes::StepOver: {
+ SStepOverTest &theTest = *m_BreakTest.getDataPtr<SStepOverTest>();
+ QT3DSI32 stackDepth = GetStackDepth(*state);
+ SLuaBreakpoint current = GetCurrentLocation(*state);
+ // Stack depth is equal but we have moved around the file
+ // stack depth is less than (we have popped up).
+ shouldDoBreak = (stackDepth == theTest.m_StackDepth
+ && (current.m_File == theTest.m_Line.m_File))
+ || theTest.m_StackDepth > stackDepth;
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ } else if (iter->second.m_Condition.IsValid()) {
+ Option<SDatamodelValue> theValue;
+ if (iter->second.m_CompileError == false)
+ theValue = ExecuteStringToValue(*state, iter->second.m_Condition.c_str(),
+ "Breakpoint");
+
+ if (theValue.hasValue())
+ shouldDoBreak = DatamodelValueToBoolean(*theValue);
+ else {
+ iter->second.m_CompileError = true;
+ shouldDoBreak = false;
+ }
+ }
+
+ // now break hits
+ // update stack (variables), re-evaluate watches and send to server
+ if (shouldDoBreak) {
+ QT3DSU64 curTime = qt3ds::foundation::Time::getCurrentCounterValue();
+ m_BrokenState = state;
+ SStackState __broken(m_BrokenState);
+ eastl::pair<QT3DSI32, SLuaBreakpoint> traceResult = PerformStackTrace(*state);
+ m_BreakTest = SBreakTest();
+ WriteMessage(lua::SOnBreak(traceResult.second));
+ UpdateWatchExpressions(*state);
+ QT3DSU64 updateTime = qt3ds::foundation::Time::getCurrentCounterValue() - curTime;
+ double milliseconds = updateTime / 100000.0;
+ qCInfo(TRACE_INFO, "Initial breakpoint update took: %fms\n", milliseconds);
+ HandleBroken(*state, traceResult.first, traceResult.second);
+ fflush(stdout); // flush stdout after handle broken message only
+ }
+ }
+ }
+ }
+
+ // This blocks Runtime with blocking read: NextBrokenMessage()
+ // Until Continue, Step Into, Step Over, Step Out is received
+ void HandleBroken(lua_State &inState, QT3DSI32 inStackDepth,
+ SLuaBreakpoint inCurrentBreakpoint = SLuaBreakpoint())
+ {
+ if (m_Listener)
+ m_Listener->OnBreak();
+ m_BrokenState = &inState;
+ SStackState __broken(m_BrokenState);
+ bool broken = true;
+ for (SDebugStreamMessage theMessage = NextBrokenMessage(broken);
+ m_Stream->Connected() && theMessage.m_Data.size();
+ theMessage = NextBrokenMessage(broken)) {
+ SLuaDebuggerProtocolReader theReader(theMessage.m_Data, m_StringTable);
+ while (theReader.HasData()) {
+ SLuaDebugMessageHeader theHeader = theReader.ReadHeader();
+ switch (theHeader.m_MessageName) {
+ case SProtocolMessageNames::Continue:
+ broken = false;
+ break;
+ case SProtocolMessageNames::StepInto:
+ broken = false;
+ m_BreakTest = SBreakTest(SBreakRequestedTest());
+ break;
+ case SProtocolMessageNames::StepOut:
+ broken = false;
+ m_BreakTest = SBreakTest(SStepOutTest(GetStackDepth(inState, inStackDepth)));
+ break;
+ case SProtocolMessageNames::StepOver:
+ broken = false;
+ m_BreakTest = SBreakTest(
+ SStepOverTest(GetStackDepth(inState, inStackDepth), inCurrentBreakpoint));
+ break;
+ default:
+ HandleNextMessage(theReader, theHeader);
+ }
+ }
+ }
+ }
+
+ SDebugStreamMessage NextBrokenMessage(bool broken)
+ {
+ if (broken)
+ return m_Stream->WaitForNextMessage();
+ return SDebugStreamMessage();
+ }
+
+ // update call stack, with non-detailed variables send back
+ eastl::pair<QT3DSI32, SLuaBreakpoint> PerformStackTrace(lua_State &state)
+ {
+ // Here we go!!!
+ lua_Debug stackInfo;
+ // Kind of expensive operation.
+ eastl::vector<STempStackInfo> stackData;
+ SLuaBreakpoint currentPoint;
+
+ for (QT3DSU32 idx = 0; idx < 100 && lua_getstack(&state, idx, &stackInfo)
+ && lua_getinfo(&state, "Slnuf", &stackInfo);
+ ++idx) {
+ stackData.push_back(STempStackInfo());
+ STempStackInfo &currentInfo(stackData.back());
+ // Note the function is TOS
+ currentInfo.m_Function = m_DataCache->CacheValue(state);
+ currentInfo.m_CurrentLine = stackInfo.currentline;
+ currentInfo.m_CallType = m_StringTable.RegisterStr(stackInfo.what);
+
+ int localIndex = 1;
+ const char *localName(NULL);
+
+ while ((localName = lua_getupvalue(&state, -1, localIndex)) != NULL) {
+ ++localIndex;
+ if (!isTrivial(localName) && localName[0] != '(') {
+ currentInfo.m_UpVars.push_back(
+ STableEntry(localName, m_DataCache->CacheValue(state)));
+ lua_pop(&state, 1);
+ }
+ }
+
+ // pop function off stack since we don't need it any more.
+ lua_pop(&state, 1);
+
+ localIndex = 1;
+ while ((localName = lua_getlocal(&state, &stackInfo, localIndex)) != NULL) {
+ ++localIndex;
+ // avoid unnamed or internal variables.
+ if (!isTrivial(localName) && localName[0] != '(') {
+ currentInfo.m_LocalVars.push_back(
+ STableEntry(localName, m_DataCache->CacheValue(state)));
+ }
+ lua_pop(&state, 1);
+ }
+
+ if (idx == 0) {
+ if (!isTrivial(stackInfo.source) && stackInfo.source[0] == '@') {
+ currentPoint.m_File = ToRelative(stackInfo.source + 1);
+ currentPoint.m_Line = stackInfo.currentline;
+ }
+ }
+ }
+ eastl::vector<SLuaStackInfo> outgoingStackData;
+ outgoingStackData.assign(stackData.begin(), stackData.end());
+ SStackTraceData theStackData(
+ toConstDataRef(outgoingStackData.data(), (QT3DSU32)outgoingStackData.size()));
+ WriteMessage(lua::SStackTrace(theStackData));
+ return eastl::make_pair((QT3DSI32)stackData.size(), currentPoint);
+ }
+
+ // re-evaluate watches and send back
+ void UpdateWatchExpressions(lua_State &state)
+ {
+ for (TWatchList::iterator iter = m_Watches.begin(), end = m_Watches.end(); iter != end;
+ ++iter) {
+ EvaluateWatchExpression(state, *iter);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ //// helper functions for calculation
+ //////////////////////////////////////////////////////////////////////////////////////
+ bool RestoreEnvironmentTable(lua_State &state)
+ {
+ int oldTop = lua_gettop(&state);
+ (void)oldTop;
+ bool bChange = false;
+ lua_getfield(&state, LUA_REGISTRYINDEX, GetCachedEnvironmentName());
+ if (lua_istable(&state, -1)) {
+ lua_Debug stackInfo;
+ if (lua_getstack(&state, 0, &stackInfo) && lua_getinfo(&state, "Slnuf", &stackInfo)) {
+ // run through locals and such and update function environment if changed
+ // upvars require the function to be TOS (top of stack).
+ int localIndex = 1;
+ const char *localName(NULL);
+ while ((localName = lua_getupvalue(&state, -1, localIndex)) != NULL) {
+
+ if (!isTrivial(localName) && localName[0] != '(') {
+ lua_getfield(&state, -3, localName);
+ if (!lua_equal(&state, -1, -2)) {
+ lua_setupvalue(&state, -3, localIndex);
+ bChange = true;
+ } else
+ lua_pop(&state, 1);
+ }
+ ++localIndex;
+ lua_pop(&state, 1);
+ }
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TFUNCTION);
+ // pop function off the stack because we don't need it any more.
+ lua_pop(&state, 1);
+
+ localIndex = 1;
+ while ((localName = lua_getlocal(&state, &stackInfo, localIndex)) != NULL) {
+ // avoid unnamed or internal variables.
+ if (!isTrivial(localName) && localName[0] != '(') {
+ lua_getfield(&state, -2, localName);
+ if (!lua_equal(&state, -1, -2)) {
+ lua_setlocal(&state, &stackInfo, localIndex);
+ bChange = true;
+ } else
+ lua_pop(&state, 1);
+ }
+ ++localIndex;
+ lua_pop(&state, 1);
+ }
+ }
+ }
+
+ lua_pop(&state, 1);
+ QT3DS_ASSERT(lua_gettop(&state) == oldTop);
+ return bChange;
+ }
+
+ bool BuildEnvironmentTable(lua_State &state)
+ {
+ int oldTop = lua_gettop(&state);
+ (void)oldTop;
+ lua_getfield(&state, LUA_REGISTRYINDEX, GetCachedEnvironmentName());
+ if (lua_isnil(&state, -1)) {
+ lua_pop(&state, 1);
+ lua_Debug stackInfo;
+ if (lua_getstack(&state, 0, &stackInfo) && lua_getinfo(&state, "Slnuf", &stackInfo)) {
+ // create metatable for globals table
+ lua_newtable(&state);
+ // get the current function globals
+ lua_getfenv(&state, -2);
+ lua_setfield(&state, -2, "__index");
+ // stack now should just have the new metatable on it.so push new table
+ lua_newtable(&state);
+ // reverse table order of new table and old table.
+ lua_insert(&state, -2);
+ // set the metatable.
+ lua_setmetatable(&state, -2);
+
+ // setup new print function
+ lua_pushcfunction(&state, DebuggerPrint);
+ lua_setfield(&state, -2, "print");
+
+ // Bring the function to TOS
+ lua_insert(&state, -2);
+ QT3DS_ASSERT(lua_gettop(&state) == oldTop + 2);
+ // Ensure it is what we think it should be.
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TFUNCTION);
+ // ensure the table is what we think it is.
+ QT3DS_ASSERT(lua_type(&state, -2) == LUA_TTABLE);
+
+ // now run through locals and such and add them to new global table
+ // upvars require the function to be TOS (top of stack).
+ int localIndex = 1;
+ const char *localName(NULL);
+ while ((localName = lua_getupvalue(&state, -1, localIndex)) != NULL) {
+ ++localIndex;
+ if (!isTrivial(localName) && localName[0] != '(')
+ lua_setfield(&state, -3, localName);
+ else
+ lua_pop(&state, 1);
+ }
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TFUNCTION);
+ // pop function off the stack because we don't need it any more.
+ lua_pop(&state, 1);
+
+ localIndex = 1;
+ while ((localName = lua_getlocal(&state, &stackInfo, localIndex)) != NULL) {
+ ++localIndex;
+ // avoid unnamed or internal variables.
+ if (!isTrivial(localName) && localName[0] != '(')
+ lua_setfield(&state, -2, localName);
+ else
+ lua_pop(&state, 1);
+ }
+ // OK, that should have built the global table and left nothing on the stack
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TTABLE);
+ QT3DS_ASSERT(lua_gettop(&state) == oldTop + 1);
+ // dup the table to store it.
+ lua_pushvalue(&state, -1);
+ lua_setfield(&state, LUA_REGISTRYINDEX, GetCachedEnvironmentName());
+ } else
+ return false;
+ }
+ QT3DS_ASSERT(lua_gettop(&state) == oldTop + 1);
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TTABLE);
+ return true;
+ }
+
+ SStatementExecuteData ExecuteString(lua_State &state, const char *str, bool needNil = true)
+ {
+ // Build the TOS execution environment.
+ STopScope theTopScope(&state);
+ m_StatementExecutionResult = SStatementExecuteData();
+ m_StatementExecutionResult.m_Expression = m_StringTable.RegisterStr(nonNull(str));
+ if (BuildEnvironmentTable(state)) {
+ SStackBool __ignoreHook(m_IgnoreDebugHook);
+
+ int errorNum = luaL_loadstring(&state, str);
+ if (errorNum) {
+ const char *errorMessageFromLua = lua_tostring(&state, -1);
+ m_StatementExecutionResult.m_Error.assign(errorMessageFromLua);
+ return m_StatementExecutionResult;
+ }
+ lua_insert(&state, -2);
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TTABLE);
+ lua_setfenv(&state, -2);
+ QT3DS_ASSERT(lua_type(&state, -1) == LUA_TFUNCTION);
+ int beforePCall = lua_gettop(&state);
+ errorNum = lua_pcall(&state, 0, LUA_MULTRET, 0);
+ int afterPCall = lua_gettop(&state);
+ if (errorNum) {
+ const char *errorMessageFromLua = lua_tostring(&state, -1);
+ m_StatementExecutionResult.m_Error.assign(errorMessageFromLua);
+ return m_StatementExecutionResult;
+ }
+ // Else, if no errors are present, then cache the value and return it.
+ if (afterPCall >= beforePCall) {
+ int numResults = afterPCall - beforePCall + 1;
+ for (int idx = 0, end = numResults; idx < end; ++idx) {
+ int relativeIndex = idx - numResults;
+ m_StatementExecutionResult.m_Values.push_back(
+ m_DataCache->CacheValue(state, relativeIndex));
+ }
+ } else if (needNil) {
+ m_StatementExecutionResult.m_Values.push_back(SDatamodelValue(SNil()));
+ }
+ }
+ return m_StatementExecutionResult;
+ }
+
+ Option<SDatamodelValue> ExecuteStringToValue(lua_State &state, const char *str,
+ const char *errorHeader)
+ {
+ SStatementExecuteData theData = ExecuteString(state, SWatchModifier().modify(str).c_str());
+ if (theData.m_Error.size()) {
+ qCCritical(INVALID_OPERATION, "%s %s:%s", nonNull(errorHeader), nonNull(str),
+ theData.m_Error.c_str());
+ } else {
+ if (theData.m_Values.size())
+ return theData.m_Values[0];
+ else
+ return SDatamodelValue(SNil());
+ }
+ return Option<SDatamodelValue>();
+ }
+
+ void EvaluateWatchExpression(lua_State &state, CRegisteredString exp)
+ {
+ if (exp.IsValid()) {
+ // We explicitly do not want watch expression errors coming out.
+ Option<SDatamodelValue> retval = ExecuteStringToValue(state, exp.c_str(), NULL);
+ SWatchUpdateData theData;
+ theData.m_Expression = exp;
+ if (retval.hasValue())
+ theData.m_Value = *retval;
+ WriteMessage(SWatchUpdated(theData));
+ }
+ }
+
+ void EvaluateConsoleExpression(lua_State &state, CRegisteredString exp)
+ {
+ if (exp.IsValid()) {
+ SConsoleModifier theModifier;
+ eastl::string str = theModifier.modify(exp.c_str());
+
+ SStatementExecuteData theData =
+ ExecuteString(state, theModifier.modify(str.c_str(), 2).c_str(), false);
+
+ if (theData.m_Error.size() || !theData.m_Values.size()) {
+ // 2nd pass w/o 'return'
+ theData = ExecuteString(state, str.c_str(), false);
+ }
+
+ WriteMessage(SStatementExecuted(theData));
+
+ if (!theData.m_Error.size()) {
+ // reflect new environment on palettes
+ if (m_BrokenState && RestoreEnvironmentTable(*m_BrokenState)) {
+ eastl::pair<QT3DSI32, SLuaBreakpoint> traceResult =
+ PerformStackTrace(*m_BrokenState);
+ UpdateWatchExpressions(*m_BrokenState);
+ WriteMessage(lua::SOnBreak(traceResult.second));
+ }
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ //// other functions
+ //////////////////////////////////////////////////////////////////////////////////////
+ QT3DSI32 GetStackDepth(lua_State &state, QT3DSI32 inStackDepth = -1)
+ {
+ if (inStackDepth != -1)
+ return inStackDepth;
+
+ lua_Debug stackInfo;
+ QT3DSI32 retval = 0;
+ for (QT3DSU32 idx = 0; idx < 100 && lua_getstack(&state, idx, &stackInfo)
+ && lua_getinfo(&state, "Slnuf", &stackInfo);
+ ++idx) {
+ ++retval;
+ // empty loop on purpose.
+ }
+ return retval;
+ }
+
+ SLuaBreakpoint GetCurrentLocation(lua_State &state)
+ {
+ lua_Debug stackInfo;
+ SLuaBreakpoint retval;
+ if (lua_getstack(&state, 0, &stackInfo) && lua_getinfo(&state, "Slnuf", &stackInfo)
+ && !isTrivial(stackInfo.source) && stackInfo.source[0] == '@') {
+ retval.m_File = ToRelative(stackInfo.source + 1);
+ retval.m_Line = stackInfo.currentline;
+ }
+ return retval;
+ }
+
+ virtual void Disconnect()
+ {
+ UninstallDebugHook();
+ m_Stream = NULL;
+ }
+
+ void UninstallDebugHook()
+ {
+ lua_sethook(m_LuaState, DebugHook, 0, 0);
+ lua_pushlightuserdata(m_LuaState, NULL);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uic_lua_debugger_impl");
+ }
+
+ template <typename TMsgType>
+ void WriteMessage(const TMsgType &msg)
+ {
+ if (m_Stream)
+ m_ProtocolWriter.WriteMessage(ToClientId(), const_cast<TMsgType &>(msg));
+ }
+
+ QT3DSU64 ToClientId() const { return static_cast<QT3DSU64>(reinterpret_cast<size_t>(this)); }
+
+ // Absolute/relative path conversion
+ void ToPlatformPath(TDebugStr &outString)
+ {
+ for (TStr::size_type pos = outString.find('\\'); pos != TStr::npos;
+ pos = outString.find('\\', pos + 1))
+ outString.replace(outString.begin() + pos, outString.begin() + pos + 1, "/");
+ }
+
+ Option<SLuaBreakpoint> ToAbsolute(const SLuaBreakpoint &inBreakpoint)
+ {
+ if (inBreakpoint.m_File.IsValid()) {
+ CFileTools::CombineBaseAndRelative(m_ApplicationDir, inBreakpoint.m_File, m_WorkStr);
+ ToPlatformPath(m_WorkStr);
+ SLuaBreakpoint result(m_StringTable.RegisterStr(m_WorkStr.c_str()), inBreakpoint.m_Line,
+ inBreakpoint.m_Condition);
+ return result;
+ }
+ return Empty();
+ }
+
+ CRegisteredString ToRelative(const char *inFilePath)
+ {
+ m_RelativeStr.assign(nonNull(inFilePath));
+ CFileTools::GetRelativeFromBase(m_BaseStr, m_RelativeStr, m_WorkStr);
+ return m_StringTable.RegisterStr(m_WorkStr.c_str());
+ }
+
+ Option<SLuaBreakpoint> ToAbsolute(const char *inFileRelativePath, int inLine,
+ const char *inCondition = "")
+ {
+ return ToAbsolute(SLuaBreakpoint(m_StringTable.RegisterStr(nonNull(inFileRelativePath)),
+ inLine, m_StringTable.RegisterStr(inCondition)));
+ }
+
+ static SLuaSideDebugger *GetThisFromLua(lua_State *state)
+ {
+ lua_getfield(state, LUA_REGISTRYINDEX, "uic_lua_debugger_impl");
+ SLuaSideDebugger *retval = reinterpret_cast<SLuaSideDebugger *>(lua_touserdata(state, -1));
+ lua_pop(state, 1);
+ return retval;
+ }
+
+ static int DebuggerPrint(lua_State *state)
+ {
+ lua_getfield(state, LUA_REGISTRYINDEX, "uic_lua_debugger_impl");
+ SLuaSideDebugger &theDebugger =
+ *reinterpret_cast<SLuaSideDebugger *>(lua_touserdata(state, -1));
+ lua_pop(state, 1);
+ int numArgs = lua_gettop(state);
+ lua_getglobal(state, "tostring");
+ eastl::string printResult;
+ for (int i = 1; i <= numArgs; i++) {
+ const char *s;
+ lua_pushvalue(state, -1); /* function to be called */
+ lua_pushvalue(state, i); /* value to print */
+ lua_call(state, 1, 1);
+ s = lua_tostring(state, -1); /* get result */
+ if (s == NULL)
+ return luaL_error(state,
+ LUA_QL("tostring") " must return a string to " LUA_QL("print"));
+
+ if (i > 1)
+ printResult.append("\t");
+
+ printResult.append(nonNull(s));
+ lua_pop(state, 1); /* pop result */
+ }
+ if (printResult.empty() == false)
+ theDebugger.m_StatementExecutionResult.m_PrintStatements.push_back(printResult);
+
+ return 0;
+ }
+
+ static bool DatamodelValueToBoolean(const SDatamodelValue &value)
+ {
+ switch (value.getType()) {
+ case DatamodelValueTypes::UnknownType:
+ return false;
+ case DatamodelValueTypes::Nil:
+ return false;
+ case DatamodelValueTypes::Boolean:
+ return value.getData<bool>();
+ case DatamodelValueTypes::Number:
+ return value.getData<float>() != 0.0f;
+ default:
+ return true;
+ }
+ }
+};
+}
+
+ILuaDebugger &ILuaDebugger::CreateLuaSideDebugger(NVFoundationBase &inFoundation,
+ IDebugOutStream &inStream, lua_State *inState,
+ IStringTable &inStrTable,
+ const char *inApplicationDirectory,
+ ILuaSideListener *inListener)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SLuaSideDebugger)(
+ inFoundation, inStream, inState, inStrTable, inApplicationDirectory, inListener);
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebugger.h b/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebugger.h
new file mode 100644
index 00000000..3c1fbdf8
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebugger.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_SCENE_GRAPH_DEBUGGER_H
+#define UIC_SCENE_GRAPH_DEBUGGER_H
+#pragma once
+#include "UICStateDebugger.h"
+#include "UICUIADatamodel.h"
+
+namespace uic {
+namespace state {
+ namespace debugger {
+
+ struct SSGValue;
+
+ struct SSGPropertyChange;
+
+ struct SGElemIdMap
+ {
+ void *m_Elem;
+ const char *m_Id;
+ };
+
+ // Persistant item that sticks around and appends some information to the binary file.
+ // The runtime debugger must exist for the entire time the runtime is running, not just
+ // during connection because the mapping from element->id only exists at file loading time.
+ class ISceneGraphRuntimeDebugger : public NVRefCounted, public IDebugStreamListener
+ {
+ public:
+ static const char *GetProtocolName() { return "Scene Graph Debugger"; }
+ // Nothing is returned if the object isn't connected. The returned value may not be
+ // valid
+ // after next GetOrCreateCall, so don't hold on to it.
+ virtual void MapPresentationId(void *presentation, const char *id) = 0;
+ virtual void MapElementIds(void *presentation, NVConstDataRef<SGElemIdMap> inIds) = 0;
+ virtual void OnPropertyChanged(void *elem,
+ NVConstDataRef<SSGPropertyChange> changes) = 0;
+ virtual void OnConnection(IDebugOutStream &outStream) = 0;
+ virtual void BinarySave(IOutStream &stream) = 0;
+ // Load the main datastructures, although we know the ids are wrong
+ virtual void BinaryLoad(IInStream &stream, NVDataRef<QT3DSU8> inStringTableData) = 0;
+ // Remap the presentation element points using id to map old presentation ptr to new
+ // presentation ptr.
+ virtual void BinaryLoadPresentation(void *presentation, const char *id,
+ size_t inElemOffset) = 0;
+ virtual void EndFrame() = 0;
+ virtual bool IsConnected() = 0;
+
+ static ISceneGraphRuntimeDebugger &Create(NVFoundationBase &fnd,
+ IStringTable &strTable);
+ };
+
+ class ISceneGraphArchitectDebuggerListener
+ {
+ public:
+ virtual void OnItemsDirty(NVConstDataRef<app::SAppElement *> inDirtySet) = 0;
+ };
+
+ // The architect debugger only exists when debugging.
+ class ISceneGraphArchitectDebugger : public NVRefCounted, public IDebugStreamListener
+ {
+ public:
+ virtual void SetListener(ISceneGraphArchitectDebuggerListener *listener) = 0;
+ // Note that we wrap the att or arg list and the initial values to provide extra
+ // information.
+ virtual Q3DStudio::TAttOrArgList GetElementAttributes(app::SAppElement &elem) = 0;
+
+ // These may be empty, so don't expect them. Also they are all string, no registered
+ // strings
+ // regardless of the type.
+ virtual eastl::vector<app::SDatamodelValue>
+ GetElementAttributeValues(app::SAppElement &elem) = 0;
+ virtual app::IDatamodel &GetDatamodel() = 0;
+
+ virtual void AttachToStream(IDebugOutStream &inStream) = 0;
+
+ virtual void RefreshData(bool inNeedReloadData) = 0;
+
+ static ISceneGraphArchitectDebugger &Create(uic::app::IDatamodel &inDatamodel);
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerProtocol.h b/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerProtocol.h
new file mode 100644
index 00000000..3246e09a
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerProtocol.h
@@ -0,0 +1,375 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_SCENE_GRAPH_DEBUGGER_PROTOCOL_H
+#define UIC_SCENE_GRAPH_DEBUGGER_PROTOCOL_H
+#include "UICSceneGraphDebugger.h"
+#include "UICSceneGraphDebuggerValue.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "foundation/SerializationTypes.h"
+
+namespace uic {
+namespace state {
+ namespace debugger {
+
+ // These are the datatypes we will communicate information with
+ static QT3DSU32 GetSceneGraphProtocolVersion() { return 1; }
+
+ struct SValueUpdate
+ {
+ QT3DSI32 m_Hash;
+ SSGValue m_Value;
+ SValueUpdate(QT3DSI32 h, const SSGValue &v)
+ : m_Hash(h)
+ , m_Value(v)
+ {
+ }
+ SValueUpdate()
+ : m_Hash(0)
+ {
+ }
+ template <typename Listener>
+ void IterateProperties(Listener &inListener)
+ {
+ inListener.Handle(m_Hash);
+ inListener.Handle(m_Value);
+ };
+ };
+
+ struct SElemUpdate
+ {
+ QT3DSU64 m_Elem;
+ NVDataRef<SValueUpdate> m_Updates;
+ template <typename Listener>
+ void IterateProperties(Listener &inListener)
+ {
+ inListener.Handle(m_Elem);
+ inListener.HandleRef(m_Updates);
+ };
+ };
+
+ struct SElemMap
+ {
+ QT3DSU64 m_Elem;
+ CRegisteredString m_Id;
+ SElemMap()
+ : m_Elem(0)
+ {
+ }
+ SElemMap(QT3DSU64 ptr, CRegisteredString name)
+ : m_Elem(ptr)
+ , m_Id(name)
+ {
+ }
+
+ template <typename Listener>
+ void IterateProperties(Listener &inListener)
+ {
+ inListener.Handle(m_Elem);
+ inListener.Handle(m_Id);
+ }
+ };
+
+ struct SIdUpdate
+ {
+ QT3DSU64 m_Presentation;
+ CRegisteredString m_PresentationId;
+ NVDataRef<SElemMap> m_IdUpdates;
+
+ template <typename Listener>
+ void IterateProperties(Listener &inListener)
+ {
+ inListener.Handle(m_Presentation);
+ inListener.Handle(m_PresentationId);
+ inListener.HandleRef(m_IdUpdates);
+ }
+ };
+
+ struct SSGProtocolMessageTypes
+ {
+ enum Enum {
+ UnknownMessage = 0,
+ Initialization,
+ IdUpdate,
+ ElemUpdate,
+ Frame,
+ };
+ };
+
+ // Implemented on runtime side.
+ struct SSGProtocolWriter
+ {
+ IOutStream &m_Stream;
+ MemoryBuffer<> m_WriteBuffer;
+ QT3DSU32 m_HighWaterMark;
+
+ SSGProtocolWriter(IOutStream &s, NVAllocatorCallback &alloc, QT3DSU32 highWaterMark = 4096)
+ : m_Stream(s)
+ , m_WriteBuffer(ForwardingAllocator(alloc, "WriteBuffer"))
+ , m_HighWaterMark(highWaterMark)
+ {
+ }
+
+ void Handle(QT3DSU64 data) { m_WriteBuffer.write(data); }
+
+ void Handle(QT3DSI32 data) { m_WriteBuffer.write(data); }
+
+ void Handle(CRegisteredString str)
+ {
+ QT3DSU32 len = static_cast<QT3DSU32>(strlen(str.c_str()) + 1);
+ m_WriteBuffer.write(len);
+ m_WriteBuffer.write(str.c_str(), len);
+ }
+ void Handle(SSGValue &value)
+ {
+ QT3DSU32 valType = static_cast<QT3DSU32>(value.getType());
+ m_WriteBuffer.write(valType);
+ switch (value.getType()) {
+ case SGPropertyValueTypes::Float:
+ m_WriteBuffer.write(value.getData<float>());
+ break;
+ case SGPropertyValueTypes::I32:
+ m_WriteBuffer.write(value.getData<QT3DSI32>());
+ break;
+ case SGPropertyValueTypes::String:
+ Handle(value.getData<CRegisteredString>());
+ break;
+ case SGPropertyValueTypes::Elem:
+ Handle(value.getData<QT3DSU64>());
+ break;
+ case SGPropertyValueTypes::NoSGValue:
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TDataType>
+ void HandleRef(NVDataRef<TDataType> &ref)
+ {
+ m_WriteBuffer.write(ref.size());
+ for (QT3DSU32 idx = 0, end = ref.size(); idx < end; ++idx)
+ Handle(ref[idx]);
+ }
+
+ template <typename TDataType>
+ void Handle(TDataType &dtype)
+ {
+ dtype.IterateProperties(*this);
+ }
+
+ void Flush()
+ {
+ if (m_WriteBuffer.size()) {
+ NVConstDataRef<QT3DSU8> writeData(m_WriteBuffer);
+ m_Stream.Write(writeData);
+ m_WriteBuffer.clear();
+ }
+ }
+
+ void CheckBuffer()
+ {
+ if (m_WriteBuffer.size() > m_HighWaterMark)
+ Flush();
+ }
+
+ void Write(SIdUpdate &inIdUpdate)
+ {
+ m_WriteBuffer.write((QT3DSU32)SSGProtocolMessageTypes::IdUpdate);
+ inIdUpdate.IterateProperties(*this);
+ Flush();
+ }
+
+ void Write(SElemUpdate &inIdUpdate)
+ {
+ m_WriteBuffer.write((QT3DSU32)SSGProtocolMessageTypes::ElemUpdate);
+ inIdUpdate.IterateProperties(*this);
+ CheckBuffer();
+ }
+
+ void WriteInitialization()
+ {
+ m_WriteBuffer.write((QT3DSU32)SSGProtocolMessageTypes::Initialization);
+ m_WriteBuffer.write(GetSceneGraphProtocolVersion());
+ Flush();
+ }
+ void WriteFrame()
+ {
+ m_WriteBuffer.write((QT3DSU32)SSGProtocolMessageTypes::Frame);
+ Flush();
+ }
+ };
+
+ struct SSGProtocolReader
+ {
+ NVConstDataRef<QT3DSU8> m_Message;
+ SDataReader m_Reader;
+ IStringTable &m_StringTable;
+ eastl::vector<QT3DSU8> m_DataBuffer;
+ eastl::string m_TempString;
+ QT3DSU32 m_Allocated;
+ bool m_RestartRead;
+ SSGProtocolReader(NVConstDataRef<QT3DSU8> msg, IStringTable &strTable)
+ : m_Message(msg)
+ , m_Reader(const_cast<QT3DSU8 *>(msg.begin()), const_cast<QT3DSU8 *>(msg.end()))
+ , m_StringTable(strTable)
+ , m_Allocated(0)
+ , m_RestartRead(false)
+ {
+ }
+
+ SSGProtocolMessageTypes::Enum MessageType()
+ {
+ QT3DSU32 data = m_Reader.LoadRef<QT3DSU32>();
+ return static_cast<SSGProtocolMessageTypes::Enum>(data);
+ }
+
+ template <typename TDataType>
+ Option<NVDataRef<TDataType>> AllocateData(size_t size)
+ {
+ if (m_RestartRead)
+ return Empty();
+ if (size == 0)
+ return NVDataRef<TDataType>();
+
+ QT3DSU32 current = m_Allocated;
+ QT3DSU32 newAlloc = (QT3DSU32)(size * sizeof(TDataType));
+ // 8 byte align
+ if (newAlloc % 8)
+ newAlloc += 8 - (newAlloc % 8);
+
+ QT3DSU32 required = current + newAlloc;
+
+ if (required > m_DataBuffer.size()) {
+ m_RestartRead = true;
+ m_DataBuffer.resize(required * 2);
+ return Empty();
+ }
+ TDataType *offset = reinterpret_cast<TDataType *>(&m_DataBuffer[current]);
+ m_Allocated += newAlloc;
+ return toDataRef(offset, (QT3DSU32)size);
+ }
+
+ void Handle(QT3DSU64 &data) { data = m_Reader.LoadRef<QT3DSU64>(); }
+
+ void Handle(QT3DSI32 &data) { data = m_Reader.LoadRef<QT3DSI32>(); }
+
+ void Handle(CRegisteredString &str)
+ {
+ QT3DSU32 len = m_Reader.LoadRef<QT3DSU32>();
+ m_TempString.clear();
+ if (len)
+ m_TempString.assign((const char *)m_Reader.m_CurrentPtr, (size_t)(len - 1));
+ m_Reader.m_CurrentPtr += len;
+ if (m_Reader.m_CurrentPtr > m_Reader.m_EndPtr)
+ m_Reader.m_CurrentPtr = m_Reader.m_EndPtr;
+
+ str = m_StringTable.RegisterStr(m_TempString.c_str());
+ }
+
+ void Handle(SSGValue &value)
+ {
+ QT3DSU32 valType = m_Reader.LoadRef<QT3DSU32>();
+ switch (valType) {
+ case SGPropertyValueTypes::Float:
+ value = SSGValue(m_Reader.LoadRef<float>());
+ break;
+ case SGPropertyValueTypes::I32:
+ value = SSGValue(m_Reader.LoadRef<QT3DSI32>());
+ break;
+ case SGPropertyValueTypes::String: {
+ CRegisteredString temp;
+ Handle(temp);
+ value = SSGValue(temp);
+ } break;
+ case SGPropertyValueTypes::Elem:
+ value = m_Reader.LoadRef<QT3DSU64>();
+ break;
+ case SGPropertyValueTypes::NoSGValue:
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ template <typename TDataType>
+ void HandleRef(NVDataRef<TDataType> &ref)
+ {
+ QT3DSU32 numItems = m_Reader.LoadRef<QT3DSU32>();
+ Option<NVDataRef<TDataType>> refOpt = AllocateData<TDataType>(numItems);
+ if (refOpt.hasValue()) {
+ ref = *refOpt;
+ for (QT3DSU32 idx = 0, end = ref.size(); idx < end && m_RestartRead == false;
+ ++idx)
+ Handle(ref[idx]);
+ }
+ }
+
+ template <typename TDataType>
+ void Handle(TDataType &dtype)
+ {
+ dtype.IterateProperties(*this);
+ }
+
+ template <typename TDataType>
+ void DoRead(TDataType &ioValue)
+ {
+ QT3DSU8 *startPtr = m_Reader.m_CurrentPtr;
+ QT3DSU32 restartCount = 0;
+ do {
+ m_RestartRead = false;
+ m_Allocated = 0;
+ m_Reader.m_CurrentPtr = startPtr;
+ ioValue.IterateProperties(*this);
+ ++restartCount;
+ } while (m_RestartRead);
+ }
+
+ SIdUpdate ReadIdUpdate()
+ {
+ SIdUpdate retval;
+ DoRead(retval);
+ return retval;
+ };
+
+ SElemUpdate ReadElemUpdate()
+ {
+ SElemUpdate retval;
+ DoRead(retval);
+ return retval;
+ };
+
+ QT3DSU32 ReadInitialization() { return m_Reader.LoadRef<QT3DSU32>(); }
+
+ bool Finished() { return m_Reader.m_CurrentPtr >= m_Reader.m_EndPtr; }
+ };
+ }
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerValue.h b/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerValue.h
new file mode 100644
index 00000000..8804ce7b
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICSceneGraphDebuggerValue.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_SCENE_GRAPH_DEBUGGER_VALUE_H
+#define UIC_SCENE_GRAPH_DEBUGGER_VALUE_H
+#include "UICSceneGraphDebugger.h"
+#include "UICUIADatamodel.h"
+#include "UICUIADatamodelValue.h"
+#include "UICStateEditorValue.h"
+
+namespace uic {
+namespace state {
+ namespace debugger {
+ struct SGPropertyValueTypes
+ {
+ enum Enum {
+ NoSGValue = 0,
+ Float,
+ I32,
+ String,
+ Elem,
+ };
+ };
+
+ template <typename dtype>
+ struct SGValueTypeMap
+ {
+ };
+
+ template <>
+ struct SGValueTypeMap<float>
+ {
+ static SGPropertyValueTypes::Enum GetType() { return SGPropertyValueTypes::Float; }
+ };
+
+ template <>
+ struct SGValueTypeMap<QT3DSI32>
+ {
+ static SGPropertyValueTypes::Enum GetType() { return SGPropertyValueTypes::I32; }
+ };
+
+ template <>
+ struct SGValueTypeMap<CRegisteredString>
+ {
+ static SGPropertyValueTypes::Enum GetType() { return SGPropertyValueTypes::String; }
+ };
+
+ template <>
+ struct SGValueTypeMap<QT3DSU64>
+ {
+ static SGPropertyValueTypes::Enum GetType() { return SGPropertyValueTypes::Elem; }
+ };
+
+ struct SSGValueUnionTraits
+ {
+ typedef SGPropertyValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(QT3DSU64),
+ };
+
+ static TIdType getNoDataId() { return SGPropertyValueTypes::NoSGValue; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SGValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case SGPropertyValueTypes::Float:
+ return inVisitor(*NVUnionCast<float *>(inData));
+ case SGPropertyValueTypes::I32:
+ return inVisitor(*NVUnionCast<QT3DSI32 *>(inData));
+ case SGPropertyValueTypes::String:
+ return inVisitor(*NVUnionCast<CRegisteredString *>(inData));
+ case SGPropertyValueTypes::Elem:
+ return inVisitor(*NVUnionCast<QT3DSU64 *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case SGPropertyValueTypes::NoSGValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case SGPropertyValueTypes::Float:
+ return inVisitor(*NVUnionCast<const float *>(inData));
+ case SGPropertyValueTypes::I32:
+ return inVisitor(*NVUnionCast<const QT3DSI32 *>(inData));
+ case SGPropertyValueTypes::String:
+ return inVisitor(*NVUnionCast<const CRegisteredString *>(inData));
+ case SGPropertyValueTypes::Elem:
+ return inVisitor(*NVUnionCast<const QT3DSU64 *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case SGPropertyValueTypes::NoSGValue:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SSGValueUnionTraits,
+ SSGValueUnionTraits::TBufferSize>,
+ SSGValueUnionTraits::TBufferSize>
+ TSGValueUnionType;
+
+ struct SSGValue : public TSGValueUnionType
+ {
+ SSGValue() {}
+ SSGValue(const SSGValue &other)
+ : TSGValueUnionType(static_cast<const TSGValueUnionType &>(other))
+ {
+ }
+ SSGValue(float val)
+ : TSGValueUnionType(val)
+ {
+ }
+ SSGValue(QT3DSI32 val)
+ : TSGValueUnionType(val)
+ {
+ }
+ SSGValue(CRegisteredString val)
+ : TSGValueUnionType(val)
+ {
+ }
+ SSGValue(QT3DSU64 val)
+ : TSGValueUnionType(val)
+ {
+ }
+
+ SSGValue &operator=(const SSGValue &other)
+ {
+ TSGValueUnionType::operator=(static_cast<const TSGValueUnionType &>(other));
+ return *this;
+ }
+ };
+
+ struct SSGPropertyChange
+ {
+ QT3DSI32 m_Hash;
+ SSGValue m_Value;
+ SSGPropertyChange(QT3DSI32 h, const SSGValue &v)
+ : m_Hash(h)
+ , m_Value(v)
+ {
+ }
+ SSGPropertyChange()
+ : m_Hash(0)
+ {
+ }
+ };
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Debugger/UICSceneGraphRuntimeDebugger.cpp b/src/Runtime/Source/UICState/Debugger/UICSceneGraphRuntimeDebugger.cpp
new file mode 100644
index 00000000..b133d8c1
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICSceneGraphRuntimeDebugger.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICSceneGraphDebugger.h"
+#include "UICSceneGraphDebuggerValue.h"
+#include "UICSceneGraphDebuggerProtocol.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "EASTL/sort.h"
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+namespace {
+
+typedef eastl::pair<QT3DSU64, CStringHandle> TElemStringHandlePair;
+
+struct SRegisteredIDComparator
+{
+ bool operator()(const TElemStringHandlePair &lhs, const TElemStringHandlePair &rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+};
+
+struct SPresentationIdMap
+{
+ void *m_Presentation;
+ CRegisteredString m_PresentationId;
+ nvvector<TElemStringHandlePair> m_RegisteredIdBackingStore;
+ NVDataRef<TElemStringHandlePair> m_RegisteredIds;
+ SPresentationIdMap(NVAllocatorCallback &alloc)
+ : m_RegisteredIdBackingStore(alloc, "registered ids")
+ {
+ }
+};
+
+struct RuntimeDebuggerImpl : public ISceneGraphRuntimeDebugger
+{
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ NVScopedRefCounted<IDebugOutStream> m_OutStream;
+ nvvector<SElemMap> m_ElemMapBuffer;
+ nvvector<SPresentationIdMap *> m_PresentationIdMap;
+ nvvector<SValueUpdate> m_ValueUpdates;
+ // Filter mechanism so we don't send the same thing twice.
+ nvhash_map<void *, eastl::vector<SValueUpdate>> m_LastUpdates;
+ SSGProtocolWriter *m_Writer;
+ SSAutoDeallocatorAllocator m_DataAllocator;
+ nvhash_map<void *, CStringHandle> m_ElemToNameMap;
+ QT3DSI32 mRefCount;
+
+ RuntimeDebuggerImpl(NVFoundationBase &fnd, IStringTable &strt)
+ : m_Foundation(fnd)
+ , m_StringTable(strt)
+ , m_ElemMapBuffer(fnd.getAllocator(), "elem map buffer")
+ , m_PresentationIdMap(fnd.getAllocator(), "Presentations")
+ , m_ValueUpdates(fnd.getAllocator(), "Value updates")
+ , m_LastUpdates(fnd.getAllocator(), "Last updates")
+ , m_Writer(NULL)
+ , m_DataAllocator(fnd)
+ , m_ElemToNameMap(fnd.getAllocator(), "ElemToNameMap")
+ , mRefCount(0)
+ {
+ }
+
+ ~RuntimeDebuggerImpl()
+ {
+ Disconnect();
+ for (QT3DSU32 idx = 0, end = m_PresentationIdMap.size(); idx < end; ++idx)
+ delete m_PresentationIdMap[idx];
+ // the auto-deallocator takes care of the load data.
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void Disconnect()
+ {
+ if (m_Writer)
+ delete m_Writer;
+ m_Writer = NULL;
+ }
+
+ bool CheckConnection()
+ {
+ if (m_OutStream) {
+ bool connected = m_OutStream->Connected();
+ if (!connected)
+ Disconnect();
+
+ return connected;
+ }
+ return false;
+ }
+
+ void MapPresentationId(void *presentation, const char *id) override
+ {
+ CRegisteredString newId = m_StringTable.RegisterStr(nonNull(id));
+ for (QT3DSU32 idx = 0, end = m_PresentationIdMap.size(); idx < end; ++idx) {
+ if (m_PresentationIdMap[idx]->m_Presentation == presentation) {
+ m_PresentationIdMap[idx]->m_PresentationId = newId;
+ return;
+ }
+ }
+
+ SPresentationIdMap *map = new SPresentationIdMap(m_Foundation.getAllocator());
+ map->m_Presentation = presentation;
+ map->m_PresentationId = newId;
+ m_PresentationIdMap.push_back(map);
+ }
+
+ void SendElemIdMap(SPresentationIdMap &map)
+ {
+ if (m_ElemMapBuffer.size() && CheckConnection()) {
+ SIdUpdate theUpdate;
+ theUpdate.m_Presentation = (QT3DSU64)map.m_Presentation;
+ theUpdate.m_PresentationId = map.m_PresentationId;
+ theUpdate.m_IdUpdates = m_ElemMapBuffer;
+ m_Writer->Write(theUpdate);
+ }
+ m_ElemMapBuffer.clear();
+ }
+
+ void MapElementIds(void *presentation, NVConstDataRef<SGElemIdMap> inIds) override
+ {
+ SPresentationIdMap *map = NULL;
+ for (QT3DSU32 idx = 0, end = m_PresentationIdMap.size(); idx < end && map == NULL; ++idx)
+ if (m_PresentationIdMap[idx]->m_Presentation == presentation)
+ map = m_PresentationIdMap[idx];
+ if (map == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_ElemMapBuffer.clear();
+ m_ElemToNameMap.clear();
+ for (QT3DSU32 idx = 0, end = inIds.size(); idx < end; ++idx) {
+ const SGElemIdMap &item(inIds[idx]);
+ SElemMap newMap;
+ newMap.m_Elem = (QT3DSU64)item.m_Elem;
+ CStringHandle idHandle = m_StringTable.GetHandle(nonNull(item.m_Id));
+ newMap.m_Id = m_StringTable.HandleToStr(idHandle);
+ m_ElemMapBuffer.push_back(newMap);
+ m_ElemToNameMap[item.m_Elem] = idHandle;
+ }
+ SendElemIdMap(*map);
+
+ // store them for later.
+ map->m_RegisteredIdBackingStore.reserve(m_ElemToNameMap.size());
+ for (nvhash_map<void *, CStringHandle>::iterator iter = m_ElemToNameMap.begin(),
+ end = m_ElemToNameMap.end();
+ iter != end; ++iter) {
+ map->m_RegisteredIdBackingStore.push_back(
+ eastl::make_pair((QT3DSU64)iter->first, iter->second));
+ }
+
+ eastl::sort(map->m_RegisteredIdBackingStore.begin(), map->m_RegisteredIdBackingStore.end(),
+ SRegisteredIDComparator());
+
+ map->m_RegisteredIds = NVDataRef<TElemStringHandlePair>(
+ map->m_RegisteredIdBackingStore.data(), (QT3DSU32)map->m_RegisteredIdBackingStore.size());
+ }
+
+ static bool Equals(const SValueUpdate &lhs, const SValueUpdate &rhs)
+ {
+ return lhs.m_Hash == rhs.m_Hash && lhs.m_Value == rhs.m_Value;
+ }
+
+ void OnPropertyChanged(void *elem, NVConstDataRef<SSGPropertyChange> changes) override
+ {
+ if (CheckConnection() == false)
+ return;
+ eastl::vector<SValueUpdate> &updates = m_LastUpdates[elem];
+ updates.resize(changes.size());
+ for (QT3DSU32 changeIdx = 0, changeEnd = changes.size(); changeIdx < changeEnd; ++changeIdx) {
+ SValueUpdate theUpdate;
+ theUpdate.m_Hash = changes[changeIdx].m_Hash;
+ theUpdate.m_Value = changes[changeIdx].m_Value;
+ if (Equals(theUpdate, updates[changeIdx]) == false) {
+ updates[changeIdx] = theUpdate;
+ m_ValueUpdates.push_back(theUpdate);
+ }
+ }
+ if (m_ValueUpdates.size()) {
+ SElemUpdate theUpdate;
+ theUpdate.m_Elem = (QT3DSU64)elem;
+ theUpdate.m_Updates = m_ValueUpdates;
+ m_Writer->Write(theUpdate);
+ m_ValueUpdates.clear();
+ }
+ }
+
+ void SendPresentation(SPresentationIdMap &pres)
+ {
+ if (m_OutStream) {
+ m_ElemMapBuffer.clear();
+ for (TElemStringHandlePair *iter = pres.m_RegisteredIds.begin(),
+ *end = pres.m_RegisteredIds.end();
+ iter != end; ++iter) {
+ SElemMap newMap;
+ newMap.m_Elem = (QT3DSU64)iter->first;
+ newMap.m_Id = m_StringTable.HandleToStr(iter->second);
+ m_ElemMapBuffer.push_back(newMap);
+ }
+ SendElemIdMap(pres);
+ }
+ }
+
+ void OnConnection(IDebugOutStream &outStream) override
+ {
+ Disconnect();
+ m_OutStream = outStream;
+ m_Writer = new SSGProtocolWriter(outStream, m_Foundation.getAllocator());
+ m_Writer->WriteInitialization();
+ for (QT3DSU32 idx = 0, end = m_PresentationIdMap.size(); idx < end; ++idx) {
+ SPresentationIdMap *map = m_PresentationIdMap[idx];
+ SendPresentation(*map);
+ }
+ }
+
+ bool IsConnected() override { return CheckConnection(); }
+
+ void BinarySave(IOutStream &ioStream) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriteBuffer(m_Foundation.getAllocator(),
+ "BinarySave::writebuffer");
+
+ theWriteBuffer.writeZeros(4); // Overall binary size
+ theWriteBuffer.write((QT3DSU32)m_PresentationIdMap.size());
+ for (QT3DSU32 idx = 0, end = m_PresentationIdMap.size(); idx < end; ++idx) {
+ // There is no use to writing out the presentation pointer address.
+ /*
+ void*
+ m_Presentation;
+ CRegisteredString m_PresentationId;
+ nvhash_map<void*, CRegisteredString> m_RegisteredIds;
+ */
+
+ SPresentationIdMap *map = m_PresentationIdMap[idx];
+ CRegisteredString presId(map->m_PresentationId);
+ presId.Remap(m_StringTable.GetRemapMap());
+ theWriteBuffer.write(presId);
+ theWriteBuffer.write((QT3DSU32)map->m_RegisteredIds.size());
+ theWriteBuffer.write(map->m_RegisteredIds.begin(), map->m_RegisteredIds.size());
+ }
+
+ QT3DSU32 totalSize = theWriteBuffer.size();
+ QT3DSU32 *data = (QT3DSU32 *)theWriteBuffer.begin();
+ data[0] = totalSize - 4;
+ ioStream.Write((QT3DSU8 *)data, totalSize);
+ }
+
+ void BinaryLoad(IInStream &ioStream, NVDataRef<QT3DSU8> strTableData) override
+ {
+ QT3DSU32 length;
+ ioStream.Read(length);
+ QT3DSU8 *data = (QT3DSU8 *)m_DataAllocator.allocate(length, "Binaryload", __FILE__, __LINE__);
+ ioStream.Read(data, length);
+ SDataReader theReader(data, data + length);
+ QT3DSU32 numPresentations = theReader.LoadRef<QT3DSU32>();
+ QT3DS_ASSERT(m_PresentationIdMap.size() == 0);
+ m_PresentationIdMap.resize(numPresentations);
+ for (QT3DSU32 idx = 0, end = numPresentations; idx < end; ++idx) {
+ m_PresentationIdMap[idx] = new SPresentationIdMap(m_Foundation.getAllocator());
+ SPresentationIdMap *map = m_PresentationIdMap[idx];
+ map->m_PresentationId = theReader.LoadRef<CRegisteredString>();
+ map->m_PresentationId.Remap(strTableData);
+ QT3DSU32 numElems = theReader.LoadRef<QT3DSU32>();
+ map->m_RegisteredIds =
+ toDataRef((TElemStringHandlePair *)theReader.m_CurrentPtr, numElems);
+ theReader.m_CurrentPtr += numElems * sizeof(TElemStringHandlePair);
+ }
+ }
+
+ void BinaryLoadPresentation(void *presPtr, const char *id, size_t elemOffset) override
+ {
+ CRegisteredString presId(m_StringTable.RegisterStr(id));
+ SPresentationIdMap *foundPres = NULL;
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)m_PresentationIdMap.size(); idx < end && foundPres == NULL;
+ ++idx) {
+ if (m_PresentationIdMap[idx]->m_PresentationId == presId)
+ foundPres = m_PresentationIdMap[idx];
+ }
+ if (foundPres == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ foundPres->m_Presentation = presPtr;
+ nvvector<eastl::pair<void *, CRegisteredString>> newElemIds(m_Foundation.getAllocator(),
+ "Temp load map");
+ newElemIds.reserve(foundPres->m_RegisteredIds.size());
+ for (TElemStringHandlePair *iter = foundPres->m_RegisteredIds.begin(),
+ *end = foundPres->m_RegisteredIds.end();
+ iter != end; ++iter) {
+ size_t oldId = (size_t)iter->first;
+ size_t newId = elemOffset + oldId;
+ iter->first = (QT3DSU64)newId;
+ }
+ SendPresentation(*foundPres);
+ }
+
+ void EndFrame() override
+ {
+ if (CheckConnection())
+ m_Writer->WriteFrame();
+ }
+
+ void OnMessageReceived(const SDebugStreamMessage &) override { QT3DS_ASSERT(false); }
+};
+}
+
+ISceneGraphRuntimeDebugger &ISceneGraphRuntimeDebugger::Create(NVFoundationBase &fnd,
+ IStringTable &strTable)
+{
+ return *QT3DS_NEW(fnd.getAllocator(), RuntimeDebuggerImpl)(fnd, strTable);
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDataTest.cpp b/src/Runtime/Source/UICState/Debugger/UICStateDataTest.cpp
new file mode 100644
index 00000000..f8a2722a
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDataTest.cpp
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICState.h"
+#include "UICStateTestCommon.h"
+#include "UICStateLuaScriptContext.h"
+#include "UICStateTest.h"
+#include "foundation/IOStreams.h"
+#include "EASTL/string.h"
+#include "foundation/Utils.h"
+#include "foundation/FileTools.h"
+#include "foundation/XML.h"
+#include "foundation/Qt3DSAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/StringTable.h"
+#include "UICStateContext.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "UICStateExecutionContext.h"
+#include "UICStateInterpreter.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace uic::state::test;
+using namespace uic::state;
+using qt3ds::foundation::CFileSeekableIOStream;
+using qt3ds::foundation::FileReadFlags;
+using qt3ds::foundation::nonNull;
+using qt3ds::foundation::CFileTools;
+using qt3ds::foundation::CDOMSerializer;
+using qt3ds::foundation::SDOMElement;
+using qt3ds::foundation::SDOMAttribute;
+using qt3ds::NVAllocatorCallback;
+using qt3ds::foundation::CAllocator;
+using qt3ds::foundation::NVScopedRefCounted;
+using qt3ds::NVFoundation;
+using qt3ds::NVFoundationBase;
+using qt3ds::foundation::IStringTable;
+using qt3ds::foundation::IDOMFactory;
+using qt3ds::foundation::IDOMReader;
+using qt3ds::foundation::SNamespacePairNode;
+using qt3ds::foundation::SSAutoDeallocatorAllocator;
+
+namespace {
+
+struct XMLHandler : public qt3ds::foundation::CXmlErrorHandler
+{
+ IDataLogger &m_Logger;
+ const char8_t *m_File;
+ eastl::string m_ErrorString;
+ XMLHandler(IDataLogger &logger, const char8_t *fname)
+ : m_Logger(logger)
+ , m_File(fname)
+ {
+ }
+
+ void OnXmlError(qt3ds::foundation::TXMLCharPtr errorName, int line, int /*column*/) override
+ {
+ m_ErrorString.assign("Failed to parse test file: ");
+ m_ErrorString.append(m_File);
+ m_Logger.Log(LogType::Error, m_File, line, errorName);
+ }
+};
+
+struct StateLogger : public IStateLogger
+{
+ lua_State *m_LuaState;
+ eastl::string m_LogString;
+ QT3DSI32 mRefCount;
+ StateLogger(lua_State *state)
+ : m_LuaState(state)
+ , mRefCount(0)
+ {
+ }
+ void addRef() override { ++mRefCount; }
+ void release() override
+ {
+ --mRefCount;
+ if (mRefCount <= 0)
+ delete this;
+ }
+
+ void Log(const char8_t *inLabel, const char8_t *inExpression) override
+ {
+ int theTop = lua_gettop(m_LuaState);
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_test_logger");
+ IDataLogger *theLogger = (IDataLogger *)lua_touserdata(m_LuaState, -1);
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_test_line");
+ int line = (int)lua_tonumber(m_LuaState, -1);
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uic_test_file");
+ const char *file = lua_tostring(m_LuaState, -1);
+ lua_settop(m_LuaState, theTop);
+ m_LogString.assign(nonNull(inLabel));
+ m_LogString.append(" - ");
+ m_LogString.assign(nonNull(inExpression));
+ if (theLogger) {
+ theLogger->Log(LogType::Info, file, line, m_LogString.c_str());
+ }
+ }
+};
+
+int Output(lua_State *inState)
+{
+ lua_concat(inState, lua_gettop(inState));
+ const char *message = lua_tostring(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_logger");
+ IDataLogger *theLogger = (IDataLogger *)lua_touserdata(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_line");
+ int line = (int)lua_tonumber(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_file");
+ const char *file = lua_tostring(inState, -1);
+ if (theLogger) {
+ theLogger->Log(LogType::Info, file, line, message);
+ }
+ return 0;
+}
+
+const char8_t *whitespaceChars = "\n \r\t";
+
+eastl::string::size_type FindNextNonWhite(eastl::string &str, eastl::string::size_type pos)
+{
+ eastl::string::size_type retval = str.find_first_of(whitespaceChars, pos);
+ if (retval != eastl::string::npos)
+ retval = str.find_first_of(whitespaceChars, retval);
+
+ if (retval == str.size())
+ retval = eastl::string::npos;
+
+ return retval;
+}
+
+int SetCurrentLine(NVScopedRefCounted<IDOMReader> domReader, lua_State *inContext)
+{
+ int line = domReader->GetElement()->m_Line;
+ int theTop = lua_gettop(inContext);
+ lua_pushnumber(inContext, line);
+ lua_setfield(inContext, LUA_REGISTRYINDEX, "uic_test_line");
+ lua_settop(inContext, theTop);
+ return line;
+}
+
+Option<STestResults> RunTest(const char8_t *inFullPath, const char8_t *inRoot,
+ IDataLogger &inLogger)
+{
+ CFileSeekableIOStream theXMLStream(inFullPath, FileReadFlags());
+ eastl::string relPath;
+ eastl::string fullPathStr(inFullPath);
+ eastl::string inProjectDir(inRoot);
+ CFileTools::GetRelativeFromBase(inProjectDir, fullPathStr, relPath);
+ const char8_t *fname = relPath.c_str();
+ eastl::string logString;
+ if (!theXMLStream.IsOpen()) {
+ logString.assign("Unable to open test file: ");
+ logString.append(nonNull(fname));
+ inLogger.Log(LogType::Error, fname, 0, logString.c_str());
+ return Option<STestResults>();
+ }
+ CAllocator nvAlloc;
+ NVScopedRefCounted<NVFoundation> nvFoundation(
+ NVCreateFoundation(QT3DS_FOUNDATION_VERSION, nvAlloc));
+ NVScopedRefCounted<IStringTable> strTable(
+ IStringTable::CreateStringTable(nvFoundation->getAllocator()));
+ NVScopedRefCounted<IDOMFactory> domFactory(
+ IDOMFactory::CreateDOMFactory(nvFoundation->getAllocator(), strTable));
+ XMLHandler theXMLHandler(inLogger, fname);
+ eastl::pair<SNamespacePairNode *, SDOMElement *> readResult =
+ CDOMSerializer::Read(*domFactory, theXMLStream, &theXMLHandler);
+ if (!readResult.second) {
+ return Option<STestResults>();
+ }
+ NVScopedRefCounted<IDOMReader> domReader(IDOMReader::CreateDOMReader(
+ nvFoundation->getAllocator(), *readResult.second, strTable, domFactory));
+
+ const char8_t *relDocument = 0;
+
+ if (!AreEqual("scxml-test", domReader->GetElementName().c_str())
+ || !domReader->UnregisteredAtt("document", relDocument)) {
+ logString.assign("Root element in file is not scxml-test: ");
+ logString.append(fname);
+ inLogger.Log(LogType::Error, fname, 0, logString.c_str());
+ return Option<STestResults>();
+ }
+
+ eastl::string fullDocPath;
+ qt3ds::foundation::CFileTools::CombineBaseAndRelative(inRoot, relDocument, fullDocPath);
+ CFileSeekableIOStream theSCXMLStream(fullDocPath.c_str(), FileReadFlags());
+ if (!theSCXMLStream.IsOpen()) {
+ logString.assign("Unable to open scxml file: ");
+ logString.append(nonNull(fullDocPath.c_str()));
+ inLogger.Log(LogType::Error, fname, 0, logString.c_str());
+ return Option<STestResults>();
+ }
+
+ SSAutoDeallocatorAllocator theGraphAlloc(*nvFoundation);
+
+ NVScopedRefCounted<IStateContext> theStateContext = IStateContext::Load(
+ theGraphAlloc, *nvFoundation, theSCXMLStream, fullDocPath.c_str(), strTable.mPtr);
+ if (!theStateContext) {
+ // it would have logged the error via foundation already
+ return Option<STestResults>();
+ }
+
+ // Build the lua context.
+ SLuaContext theContext(*nvFoundation);
+ int theDMStackIdx = 0;
+ {
+ IDOMReader::Scope __dmScope(domReader);
+ const char8_t *luaInit = NULL;
+ if (domReader->MoveToFirstChild("datamodel"))
+ domReader->Value(luaInit);
+ if (!isTrivial(luaInit)) {
+ eastl::string luaEval(luaInit);
+ luaL_loadstring(theContext, luaEval.c_str());
+
+ int failure = lua_pcall(theContext, 0, 1, 0);
+ if (failure) {
+ const char *errorMsg = lua_tostring(theContext, -1);
+ logString.assign("Failed to create datamodel: ");
+ logString.append(errorMsg);
+ inLogger.Log(LogType::Error, fname, 0, logString.c_str());
+ return Option<STestResults>();
+ }
+ theDMStackIdx = lua_gettop(theContext);
+ }
+ if (theDMStackIdx == 0) {
+ lua_newtable(theContext);
+ theDMStackIdx = lua_gettop(theContext);
+ }
+ // create an output functions
+ lua_pushlightuserdata(theContext, &inLogger);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "uic_test_logger");
+ lua_pushstring(theContext, fname);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "uic_test_file");
+ lua_pushnumber(theContext, 0.f);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "uic_test_line");
+ lua_pushcfunction(theContext, Output);
+ lua_pushvalue(theContext, -1);
+ lua_setfield(theContext, theDMStackIdx, "output");
+ // Really, we should have done this a long time ago, overridden print.
+ lua_setfield(theContext, theDMStackIdx, "print");
+ }
+ ILuaScriptContext &theScriptContext = ILuaScriptContext::CreateLuaScriptContext(
+ *nvFoundation, *strTable, theContext, theDMStackIdx);
+ lua_settop(theContext, 0);
+ StateLogger &theStateLogger(*(new StateLogger(theContext)));
+ IExecutionContext &theExecutionContext =
+ IExecutionContext::Create(*nvFoundation, *strTable, theStateLogger, theScriptContext);
+ IStateInterpreter &theInterpreter =
+ IStateInterpreter::Create(*nvFoundation, *strTable, theScriptContext, theExecutionContext);
+ NVScopedRefCounted<IStateInterpreter> __interpWatcher(theInterpreter);
+ theInterpreter.Initialize(*theStateContext);
+ theInterpreter.Start();
+
+ // Bind it to the script context under engine.
+ theScriptContext.GetGlobalTable();
+ ILuaScriptContext::Bind(theInterpreter, theContext);
+ lua_setfield(theContext, -2, "machine");
+ lua_settop(theContext, 0);
+
+ // Rather tedious, but it worked...
+
+ for (bool success = domReader->MoveToFirstChild("step"); success;
+ success = domReader->MoveToNextSibling("step")) {
+ IDOMReader::Scope __stepScope(domReader);
+ const char8_t *evtName = NULL;
+ domReader->UnregisteredAtt("event", evtName);
+ evtName = nonNull(evtName);
+ if (!isTrivial(evtName))
+ theInterpreter.QueueEvent(evtName);
+ int theLine = SetCurrentLine(domReader, theContext);
+ NVConstDataRef<SStateNode *> theConfig = theInterpreter.Execute();
+ const char8_t *inList = NULL;
+ if (domReader->UnregisteredAtt("in", inList)) {
+ eastl::string theList(inList);
+ eastl::string theItem;
+ for (eastl::string::size_type pos = theList.find_first_not_of(whitespaceChars);
+ pos != eastl::string::npos; pos = FindNextNonWhite(theList, pos)) {
+ eastl::string::size_type nextWhite = theList.find_first_of(whitespaceChars, pos);
+ if (nextWhite == eastl::string::npos)
+ nextWhite = theList.size();
+ theItem = theList.substr(pos, nextWhite - pos);
+
+ if (theItem.size()) {
+ bool found = false;
+ for (QT3DSU32 idx = 0, end = theConfig.size(); idx < end && !found; ++idx) {
+ if (AreEqual(theConfig[idx]->m_Id.c_str(), theItem.c_str()))
+ found = true;
+ }
+ if (!found) {
+ logString.assign("Assertion failed: item \"");
+ logString.append(theItem.c_str());
+ logString.append("\" not found in machine configuration");
+ inLogger.Log(LogType::Error, fname, theLine, logString.c_str());
+ return STestResults(1, 0);
+ }
+ }
+ }
+ }
+ for (bool assertSuccess = domReader->MoveToFirstChild("assert"); assertSuccess;
+ assertSuccess = domReader->MoveToNextSibling("assert")) {
+ IDOMReader::Scope __assertScope(domReader);
+ theLine = SetCurrentLine(domReader, theContext);
+ const char8_t *condExpr = NULL;
+ domReader->UnregisteredAtt("cond", condExpr);
+
+ if (isTrivial(condExpr))
+ domReader->Value(condExpr);
+
+ if (!isTrivial(condExpr)) {
+ Option<bool> condResult = theScriptContext.ExecuteCondition(condExpr);
+ if (!condResult.hasValue()) {
+ logString.assign("Assertion failed: condition \"");
+ logString.append(condExpr);
+ logString.append("\" failed to execute");
+ inLogger.Log(LogType::Error, fname, theLine, logString.c_str());
+ return STestResults(1, 0);
+ }
+ if (!condResult.getValue()) {
+ logString.assign("Assertion failed: condition \"");
+ logString.append(condExpr);
+ logString.append("\" evaluated to false");
+ inLogger.Log(LogType::Error, fname, theLine, logString.c_str());
+ return STestResults(1, 0);
+ }
+ }
+ }
+ }
+
+ return STestResults(1, 1);
+}
+}
+
+Option<STestResults> IDataTest::RunFile(const char8_t *fname, const char8_t *inRootDir,
+ IDataLogger &inLogger)
+{
+ return RunTest(fname, inRootDir, inLogger);
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.cpp b/src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.cpp
new file mode 100644
index 00000000..9f09f62a
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.cpp
@@ -0,0 +1,770 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateDebugStreams.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSMutex.h"
+#include "foundation/Qt3DSSync.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include "EASTL/string.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace uic;
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+namespace {
+
+struct MultiProtocolMessageTypes
+{
+ enum Enum {
+ UnknownMessageType = 0,
+ NewProtocol = 1,
+ ProtocolMessage = 1 << 2,
+ };
+};
+
+struct SMultiProtocolMessageFlags : public NVFlags<MultiProtocolMessageTypes::Enum, QT3DSU32>
+{
+ bool IsNewProtocol() { return this->operator&(MultiProtocolMessageTypes::NewProtocol); }
+ void SetNewProtocol(bool inValue)
+ {
+ this->clearOrSet(inValue, MultiProtocolMessageTypes::NewProtocol);
+ }
+
+ bool IsProtocolMessage() { return this->operator&(MultiProtocolMessageTypes::ProtocolMessage); }
+ void SetProtocolMessage(bool inValue)
+ {
+ this->clearOrSet(inValue, MultiProtocolMessageTypes::ProtocolMessage);
+ }
+};
+
+struct SMultiProtocolInitializer
+{
+ static QT3DSU16 GetCurrentMultiProtocolVersion() { return 1; }
+
+ QT3DSU64 m_TimeNumerator;
+ QT3DSU64 m_TimeDenominator;
+ QT3DSU32 m_ProtocolVersion;
+
+ SMultiProtocolInitializer()
+ : m_TimeNumerator(Time::sCounterFreq.mNumerator)
+ , m_TimeDenominator(Time::sCounterFreq.mDenominator)
+ , m_ProtocolVersion(GetCurrentMultiProtocolVersion())
+ {
+ }
+};
+
+struct SMultiProtocolMessageHeader
+{
+
+ SMultiProtocolMessageFlags m_Flags;
+ QT3DSU32 m_Size;
+ QT3DSU32 m_ProtocolId;
+ QT3DSU64 m_Timestamp;
+ SMultiProtocolMessageHeader(MultiProtocolMessageTypes::Enum inMessageType, QT3DSU32 size,
+ QT3DSU32 protocolId, QT3DSU64 timestamp)
+ : m_Size(size)
+ , m_ProtocolId(protocolId)
+ , m_Timestamp(timestamp)
+ {
+ m_Flags.clearOrSet(true, inMessageType);
+ }
+ SMultiProtocolMessageHeader() {}
+};
+
+struct IProtocolMessageHandler
+{
+protected:
+ virtual ~IProtocolMessageHandler() {}
+public:
+ virtual void OnMessageReceived(SDebugStreamMessage msgData) = 0;
+};
+
+struct IProtocolHandler
+{
+protected:
+ virtual ~IProtocolHandler() {}
+public:
+ virtual void OnNewProtocol(CRegisteredString inProtocolName) = 0;
+};
+
+struct SSharedStreamImpl : public NVRefCounted
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<SocketStream> m_Stream;
+ IOutStream &m_WriteStream;
+ SMultiProtocolInitializer m_Initializer;
+ eastl::hash_map<CRegisteredString, QT3DSU32> m_ProtocolIdMap;
+ eastl::hash_map<QT3DSU32, IProtocolMessageHandler *> m_MessageHandlers;
+ MemoryBuffer<> m_ReadBuffer;
+ IStringTable &m_StringTable;
+ IProtocolHandler *m_ProtocolHandler;
+ QT3DSU32 m_NextProtocolId;
+ QT3DSI32 mRefCount;
+
+ SSharedStreamImpl(NVFoundationBase &fnd, SocketStream &stream, IOutStream &writeStream,
+ IStringTable &strTable, IProtocolHandler &pHandler)
+ : m_Foundation(fnd)
+ , m_Stream(stream)
+ , m_WriteStream(writeStream)
+ , m_ReadBuffer(ForwardingAllocator(fnd.getAllocator(), "ReadBuffer"))
+ , m_StringTable(strTable)
+ , m_ProtocolHandler(&pHandler)
+ , m_NextProtocolId(1)
+ , mRefCount(0)
+ {
+ NVConstDataRef<QT3DSU8> msgData = toU8DataRef(m_Initializer);
+ bool streamValid = m_Stream->Write(msgData);
+ if (streamValid == false)
+ m_Stream = NULL;
+ }
+ ~SSharedStreamImpl() {}
+
+ bool Initialize()
+ {
+ if (m_Stream) {
+ NVDataRef<QT3DSU8> msgData = toU8DataRef(m_Initializer);
+ QT3DSU32 numBytes = m_Stream->Read(msgData);
+ if (numBytes != sizeof(SMultiProtocolInitializer)
+ || m_Initializer.m_ProtocolVersion
+ > SMultiProtocolInitializer::GetCurrentMultiProtocolVersion()) {
+ m_Stream = NULL;
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ QT3DSU32 GetIdForProtocol(CRegisteredString protocol)
+ {
+ if (protocol.IsValid() == false)
+ return 0;
+ eastl::pair<eastl::hash_map<CRegisteredString, QT3DSU32>::iterator, bool> inserter =
+ m_ProtocolIdMap.insert(eastl::make_pair(protocol, m_NextProtocolId));
+ if (inserter.second) {
+ QT3DSU32 newId = m_NextProtocolId;
+ ++m_NextProtocolId;
+ if (m_Stream) {
+ QT3DSU32 msgLen = (QT3DSU32)strlen(protocol) + 1;
+ NVConstDataRef<QT3DSU8> writeBuf(reinterpret_cast<const QT3DSU8 *>(protocol.c_str()),
+ msgLen);
+ WriteMessage(MultiProtocolMessageTypes::NewProtocol, writeBuf, newId);
+ }
+ }
+ return inserter.first->second;
+ }
+
+ CRegisteredString GetProtocolForId(QT3DSU32 id)
+ {
+ for (eastl::hash_map<CRegisteredString, QT3DSU32>::iterator iter = m_ProtocolIdMap.begin(),
+ end = m_ProtocolIdMap.end();
+ iter != end; ++iter) {
+ if (iter->second == id)
+ return iter->first;
+ }
+ return CRegisteredString();
+ }
+
+ void AddMessageHandler(CRegisteredString protocol, IProtocolMessageHandler &hdl)
+ {
+ m_MessageHandlers.insert(eastl::make_pair(GetIdForProtocol(protocol), &hdl));
+ }
+
+ void RemoveMessageHandler(CRegisteredString protocol)
+ {
+ m_MessageHandlers.erase(GetIdForProtocol(protocol));
+ }
+
+ IProtocolMessageHandler *GetMessageHandler(CRegisteredString protocol)
+ {
+ return GetMessageHandler(GetIdForProtocol(protocol));
+ }
+
+ IProtocolMessageHandler *GetMessageHandler(QT3DSU32 protocolId)
+ {
+ eastl::hash_map<QT3DSU32, IProtocolMessageHandler *>::iterator iter =
+ m_MessageHandlers.find(protocolId);
+ if (iter != m_MessageHandlers.end())
+ return iter->second;
+ return NULL;
+ }
+
+ void ProtocolHandlerLeaving() { m_ProtocolHandler = NULL; }
+
+ void DispatchMessage(SMultiProtocolMessageHeader inHeader, NVConstDataRef<QT3DSU8> msg)
+ {
+ if (inHeader.m_Flags.IsNewProtocol()) {
+ char *pId = reinterpret_cast<char *>(const_cast<QT3DSU8 *>(msg.begin()));
+ // Ensure null terminated, which should be done anyway but we don't know it will be.
+ pId[inHeader.m_Size] = 0;
+ CRegisteredString protocolName = m_StringTable.RegisterStr(pId);
+ eastl::pair<eastl::hash_map<CRegisteredString, QT3DSU32>::iterator, bool> inserter =
+ m_ProtocolIdMap.insert(eastl::make_pair(protocolName, inHeader.m_ProtocolId));
+ if (inserter.second == false) {
+ // remap id to higher id to reduce the chance of conflicts.
+ QT3DSU32 potentialNewId = NVMax(inserter.first->second, inHeader.m_ProtocolId);
+ if (potentialNewId != inserter.first->second) {
+ m_NextProtocolId = NVMax(m_NextProtocolId, potentialNewId + 1);
+ CRegisteredString existing = GetProtocolForId(potentialNewId);
+ if (existing.IsValid()) {
+ m_ProtocolIdMap.erase(protocolName);
+ GetIdForProtocol(protocolName);
+ return;
+ } else {
+ inserter.first->second = potentialNewId;
+ }
+ }
+ } else {
+ if (m_ProtocolHandler != NULL) {
+ m_ProtocolHandler->OnNewProtocol(protocolName);
+ }
+ }
+ } else {
+ IProtocolMessageHandler *handler = GetMessageHandler(inHeader.m_ProtocolId);
+ if (handler != NULL)
+ handler->OnMessageReceived(SDebugStreamMessage(inHeader.m_Timestamp, msg));
+ }
+ }
+
+ NVDataRef<QT3DSU8> ReadChunk(NVDataRef<QT3DSU8> target)
+ {
+ QT3DSU32 totalRead = 0;
+ do {
+ NVDataRef<QT3DSU8> nextBuf(target.begin() + totalRead, target.size() - totalRead);
+ QT3DSU32 readResult = m_Stream->Read(nextBuf);
+ totalRead += readResult;
+ if (totalRead < target.size()) {
+ totalRead = totalRead;
+ }
+ } while (connected() && totalRead < target.size());
+
+ return toDataRef(m_ReadBuffer.begin(), totalRead);
+ }
+
+ NVDataRef<QT3DSU8> ReadChunk(QT3DSU32 size)
+ {
+ m_ReadBuffer.reserve(size);
+ return ReadChunk(toDataRef(m_ReadBuffer.begin(), size));
+ }
+
+ virtual SDebugStreamMessage WaitForNextMessage(CRegisteredString protocol)
+ {
+ QT3DSU32 msgId = GetIdForProtocol(protocol);
+
+ while (m_Stream) {
+ SMultiProtocolMessageHeader header;
+ NVDataRef<QT3DSU8> buf = toU8DataRef(header);
+ buf = ReadChunk(buf);
+ if (buf.size() < sizeof(header)) {
+ m_Stream = NULL;
+ QT3DS_ASSERT(false);
+ } else {
+ NVDataRef<QT3DSU8> readResult = ReadChunk(header.m_Size);
+ if (readResult.mSize != header.m_Size) {
+ m_Stream = NULL;
+ QT3DS_ASSERT(false);
+ } else {
+ if (header.m_ProtocolId == msgId) {
+ SDebugStreamMessage message;
+ message.m_Timestamp = header.m_Timestamp;
+ message.m_Data = readResult;
+ return message;
+ } else
+ DispatchMessage(header, readResult);
+ }
+ }
+ }
+
+ return SDebugStreamMessage();
+ }
+
+ virtual void MessagePump()
+ {
+ if (m_Stream == NULL)
+ return;
+ bool lastMessage = true;
+ do {
+ SMultiProtocolMessageHeader header;
+ NVDataRef<QT3DSU8> buf = toU8DataRef(header);
+ QT3DSU32 amountRead = m_Stream->nonBlockingRead(buf);
+ if (amountRead == 0) {
+ if (m_Stream->connected() == false)
+ m_Stream = NULL;
+ lastMessage = false;
+ } else {
+ // read the rest of the header.
+ QT3DSU32 leftover = buf.size() - amountRead;
+ if (leftover) {
+ NVDataRef<QT3DSU8> nextPiece(buf.begin() + amountRead, leftover);
+ nextPiece = ReadChunk(nextPiece);
+ amountRead += nextPiece.size();
+ }
+
+ if (amountRead < sizeof(SMultiProtocolMessageHeader)) {
+ m_Stream = NULL;
+ QT3DS_ASSERT(false);
+
+ } else {
+ NVDataRef<QT3DSU8> msgData = ReadChunk(header.m_Size);
+ if (msgData.size() == header.m_Size) {
+ DispatchMessage(header, msgData);
+ } else {
+ m_Stream = NULL;
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ } while (lastMessage && m_Stream);
+ }
+
+ SMultiProtocolMessageHeader CreateHeader(MultiProtocolMessageTypes::Enum type, QT3DSU32 size,
+ QT3DSU32 protocolId)
+ {
+ SMultiProtocolMessageHeader retval;
+ retval.m_Flags.clearOrSet(true, type);
+ retval.m_ProtocolId = protocolId;
+ retval.m_Size = size;
+ retval.m_Timestamp = Time::getCurrentCounterValue();
+ return retval;
+ }
+
+ bool WriteMessage(MultiProtocolMessageTypes::Enum type, NVConstDataRef<QT3DSU8> data,
+ QT3DSU32 protocolId)
+ {
+ if (connected()) {
+ SMultiProtocolMessageHeader header(CreateHeader(type, data.size(), protocolId));
+ NVConstDataRef<QT3DSU8> writeBuf = toU8DataRef(header);
+ bool success = m_WriteStream.Write(writeBuf);
+ if (success) {
+ success = m_WriteStream.Write(data);
+ }
+ if (!success)
+ m_Stream = NULL;
+ return success;
+ }
+ return false;
+ }
+
+ virtual bool Write(CRegisteredString protocol, NVConstDataRef<QT3DSU8> data)
+ {
+ return WriteMessage(MultiProtocolMessageTypes::ProtocolMessage, data,
+ GetIdForProtocol(protocol));
+ }
+
+ bool connected() { return m_Stream != NULL && m_Stream->connected(); }
+};
+
+struct SMultiProtocolSocketStreamImpl : public IMultiProtocolSocketStream,
+ public IProtocolMessageHandler
+{
+ NVFoundationBase &m_Foundation;
+ CRegisteredString m_Protocol;
+ IDebugStreamListener *m_Listener;
+ NVScopedRefCounted<SSharedStreamImpl> m_SharedStream;
+ bool m_StreamValid;
+ QT3DSI32 mRefCount;
+
+ SMultiProtocolSocketStreamImpl(NVFoundationBase &fnd, CRegisteredString protocol,
+ IDebugStreamListener *listener, SSharedStreamImpl &stream)
+ : m_Foundation(fnd)
+ , m_Protocol(protocol)
+ , m_Listener(listener)
+ , m_SharedStream(stream)
+ , m_StreamValid(true)
+ , mRefCount(0)
+ {
+ m_SharedStream->AddMessageHandler(m_Protocol, *this);
+ }
+
+ ~SMultiProtocolSocketStreamImpl() { m_SharedStream->RemoveMessageHandler(m_Protocol); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ IDebugStreamListener *GetListener() override { return m_Listener; }
+ CRegisteredString GetProtocolName() override { return m_Protocol; }
+
+ void SetListener(IDebugStreamListener *listener) override { m_Listener = listener; }
+
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ if (m_StreamValid)
+ m_StreamValid = m_SharedStream->Write(m_Protocol, data);
+
+ return m_StreamValid;
+ }
+
+ SDebugStreamMessage WaitForNextMessage() override
+ {
+ if (m_StreamValid)
+ return m_SharedStream->WaitForNextMessage(m_Protocol);
+ return SDebugStreamMessage();
+ }
+
+ void OnMessageReceived(SDebugStreamMessage data) override
+ {
+ if (m_Listener)
+ m_Listener->OnMessageReceived(data);
+ }
+
+ bool Connected() override { return m_SharedStream->connected(); }
+};
+
+struct SMultiProtocolSocketImpl : public IMultiProtocolSocket, public IProtocolHandler
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<SSharedStreamImpl> m_SharedStream;
+ NVScopedRefCounted<IMultiProtocolSocketListener> m_ProtocolListener;
+ QT3DSI32 mRefCount;
+ SMultiProtocolSocketImpl(NVFoundationBase &fnd, SocketStream &inStream, IStringTable &strTable,
+ IMultiProtocolSocketListener *protocolListener)
+ : m_Foundation(fnd)
+ , m_ProtocolListener(protocolListener)
+ , mRefCount(0)
+ {
+ // At some point I may switch the writer to a buffered stream, at least on the client side.
+ m_SharedStream = QT3DS_NEW(m_Foundation.getAllocator(), SSharedStreamImpl)(
+ m_Foundation, inStream, inStream, strTable, *this);
+ }
+
+ ~SMultiProtocolSocketImpl() { m_SharedStream->ProtocolHandlerLeaving(); }
+
+ bool Initialize() override { return m_SharedStream->Initialize(); }
+
+ bool Connected() override { return m_SharedStream->connected(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ virtual NVScopedRefCounted<IMultiProtocolSocketStream>
+ CreateProtocol(const char *name, IDebugStreamListener *inListener) override
+ {
+ NVScopedRefCounted<IMultiProtocolSocketStream> retval = GetProtocol(name);
+ if (retval) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ CRegisteredString protocolName = m_SharedStream->m_StringTable.RegisterStr(name);
+ if (protocolName.IsValid() == false) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+ SMultiProtocolSocketStreamImpl *newStream =
+ QT3DS_NEW(m_Foundation.getAllocator(), SMultiProtocolSocketStreamImpl)(
+ m_Foundation, protocolName, inListener, *m_SharedStream);
+ return newStream;
+ }
+
+ NVScopedRefCounted<IMultiProtocolSocketStream> GetProtocol(const char *name) override
+ {
+ CRegisteredString protocolName = m_SharedStream->m_StringTable.RegisterStr(name);
+ IProtocolMessageHandler *handler = m_SharedStream->GetMessageHandler(protocolName);
+ if (handler) {
+ SMultiProtocolSocketStreamImpl *theImpl =
+ static_cast<SMultiProtocolSocketStreamImpl *>(handler);
+ return theImpl;
+ }
+ return NVScopedRefCounted<IMultiProtocolSocketStream>();
+ }
+
+ void OnNewProtocol(CRegisteredString inProtocolName) override
+ {
+ if (m_ProtocolListener) {
+ // We can expect the user to call create protocol at this point.
+ IDebugStreamListener *handler = m_ProtocolListener->OnNewProtocol(inProtocolName);
+ if (handler) {
+ SMultiProtocolSocketStreamImpl *newStream =
+ QT3DS_NEW(m_Foundation.getAllocator(), SMultiProtocolSocketStreamImpl)(
+ m_Foundation, inProtocolName, handler, *m_SharedStream);
+ m_ProtocolListener->OnNewProtocolStream(inProtocolName, *newStream);
+ }
+ }
+ }
+
+ CounterFrequencyToTensOfNanos SourceConversion() override
+ {
+ return CounterFrequencyToTensOfNanos(m_SharedStream->m_Initializer.m_TimeNumerator,
+ m_SharedStream->m_Initializer.m_TimeDenominator);
+ }
+
+ void MessagePump() override { m_SharedStream->MessagePump(); }
+};
+
+struct SMultiProtocolStreamLuaCompatImpl : public IMultiProtocolStreamLuaCompat,
+ public IDebugStreamListener
+{
+ NVFoundationBase &m_Foundation;
+ eastl::string m_MessageBuffer;
+ eastl::string m_CurrentMessage;
+ QT3DSU32 m_Timeout;
+ NVScopedRefCounted<IMultiProtocolSocketStream> m_Stream;
+ QT3DSI32 mRefCount;
+
+ SMultiProtocolStreamLuaCompatImpl(NVFoundationBase &fnd, IMultiProtocolSocket &socket)
+ : m_Foundation(fnd)
+ , m_Timeout(1000)
+ , mRefCount(0)
+ {
+ m_Stream = socket.CreateProtocol(getProtocolName(), this);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void settimeout(QT3DSU32 value = 0) override { m_Timeout = value; }
+ QT3DSU32 gettimeout() override { return m_Timeout; }
+ // returns next line of data
+ // or error
+ eastl::pair<const char *, LuaStreamError::_Enum> receive(QT3DSU32 numBytes) override
+ {
+ if (m_Stream->Connected() == false)
+ return eastl::make_pair("", LuaStreamError::Closed);
+
+ m_CurrentMessage.clear();
+
+ while (m_Stream->Connected()) {
+ if (numBytes == 0) {
+ eastl::string::size_type pos = m_MessageBuffer.find('\n');
+ if (pos != eastl::string::npos || m_MessageBuffer.size()) {
+ if (pos == eastl::string::npos)
+ pos = m_MessageBuffer.size();
+ m_CurrentMessage = m_MessageBuffer.substr(0, pos);
+ m_MessageBuffer.erase(m_MessageBuffer.begin(),
+ m_MessageBuffer.begin() + pos + 1);
+ }
+ if (m_CurrentMessage.size())
+ return eastl::make_pair(m_CurrentMessage.c_str(), LuaStreamError::NoLuaError);
+ } else {
+ QT3DSU32 required = numBytes - m_CurrentMessage.size();
+ QT3DSU32 possible = NVMin(required, (QT3DSU32)m_MessageBuffer.size());
+ m_CurrentMessage.append(m_MessageBuffer.begin(),
+ m_MessageBuffer.begin() + possible);
+ m_MessageBuffer.erase(m_MessageBuffer.begin(), m_MessageBuffer.begin() + possible);
+ if (m_CurrentMessage.size() == numBytes)
+ return eastl::make_pair(m_CurrentMessage.c_str(), LuaStreamError::NoLuaError);
+ }
+
+ // nonblocking mode
+ if (numBytes == 0 && m_Timeout == 0) {
+ return eastl::make_pair("", LuaStreamError::Timeout);
+ } else {
+ SDebugStreamMessage nextMessage = m_Stream->WaitForNextMessage();
+ OnMessageReceived(nextMessage);
+ }
+ }
+ return eastl::make_pair("", LuaStreamError::Closed);
+ }
+
+ void send(const char *data) override
+ {
+ if (isTrivial(data))
+ return;
+ QT3DSU32 len = (QT3DSU32)strlen(data);
+ m_Stream->Write(data, len);
+ }
+
+ bool hasData() override { return m_MessageBuffer.empty() == false; }
+
+ virtual IDebugStreamListener &GetListener() { return *this; }
+
+ void OnMessageReceived(const SDebugStreamMessage &msg) override
+ {
+ if (msg.m_Data.size()) {
+ const char *dataBegin = reinterpret_cast<const char *>(msg.m_Data.begin());
+ const char *dataEnd = dataBegin + msg.m_Data.size();
+ // eastl::string temp;
+ // temp.append( dataBegin, dataEnd );
+ // m_Foundation.error( QT3DS_INTERNAL_ERROR, "Received: %s", temp.c_str() );
+ m_MessageBuffer.append(dataBegin, dataEnd);
+ }
+ }
+};
+
+int MultiProtocolStreamLuaCompatGC(lua_State *state)
+{
+ int top = lua_gettop(state);
+ luaL_checktype(state, -1, LUA_TUSERDATA);
+ IMultiProtocolStreamLuaCompat **stream =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_touserdata(state, -1));
+ if (stream && *stream)
+ (*stream)->release();
+ lua_settop(state, top);
+ return 0;
+}
+
+int MultiProtocolStreamLuaReceive(lua_State *state)
+{
+ int top = lua_gettop(state);
+ luaL_checktype(state, 1, LUA_TTABLE);
+ lua_getfield(state, 1, "__streamimpl");
+ IMultiProtocolStreamLuaCompat **stream =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_touserdata(state, -1));
+ eastl::pair<const char *, LuaStreamError::_Enum> data("", LuaStreamError::Closed);
+ if (stream && *stream) {
+ QT3DSU32 numBytes = 0;
+ if (top > 1) {
+ int amount = lua_tointeger(state, 2);
+ if (amount < 0) {
+ QT3DS_ASSERT(false);
+ }
+ numBytes = static_cast<QT3DSU32>(amount);
+ }
+ data = (*stream)->receive(numBytes);
+ }
+ if (data.second == LuaStreamError::NoLuaError) {
+ lua_pushstring(state, data.first);
+ return 1;
+ } else {
+ lua_pushnil(state);
+ const char *errorStr = "closed";
+ if (data.second == LuaStreamError::Timeout)
+ errorStr = "timeout";
+ lua_pushstring(state, errorStr);
+ return 2;
+ }
+}
+
+int MultiProtocolStreamLuaSend(lua_State *state)
+{
+ luaL_checktype(state, 1, LUA_TTABLE);
+ luaL_checktype(state, 2, LUA_TSTRING);
+ lua_getfield(state, 1, "__streamimpl");
+ IMultiProtocolStreamLuaCompat **stream =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_touserdata(state, -1));
+ const char *data = lua_tostring(state, 2);
+ if (stream && *stream)
+ (*stream)->send(data);
+ return 0;
+}
+
+int MultiProtocolStreamLuaSettimeout(lua_State *state)
+{
+ int top = lua_gettop(state);
+ luaL_checktype(state, 1, LUA_TTABLE);
+ if (top == 2)
+ luaL_checktype(state, 2, LUA_TNUMBER);
+
+ lua_getfield(state, 1, "__streamimpl");
+ IMultiProtocolStreamLuaCompat **stream =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_touserdata(state, -1));
+ QT3DSU32 timeout = QT3DS_MAX_U32;
+ if (top == 2)
+ timeout = static_cast<QT3DSU32>(lua_tonumber(state, 2) * 1000);
+ if (stream && *stream)
+ (*stream)->settimeout(timeout);
+ return 0;
+}
+
+int MultiProtocolStreamLuaGettimeout(lua_State *state)
+{
+ luaL_checktype(state, 1, LUA_TTABLE);
+ lua_getfield(state, 1, "__streamimpl");
+ IMultiProtocolStreamLuaCompat **stream =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_touserdata(state, -1));
+ if (stream && *stream) {
+ lua_pushnumber(state, static_cast<lua_Number>((*stream)->gettimeout()));
+ return 1;
+ }
+ return 0;
+}
+
+int MultiProtocolStreamLuaHasData(lua_State *state)
+{
+ luaL_checktype(state, 1, LUA_TTABLE);
+ lua_getfield(state, 1, "__streamimpl");
+ IMultiProtocolStreamLuaCompat **stream =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_touserdata(state, -1));
+ if (stream && *stream) {
+ bool data = (*stream)->hasData();
+ lua_pushboolean(state, data ? 1 : 0);
+ return 1;
+ }
+ return 0;
+}
+}
+
+NVScopedRefCounted<IMultiProtocolSocket>
+IMultiProtocolSocket::CreateProtocolSocket(NVFoundationBase &fnd, SocketStream &inStream,
+ IStringTable &strTable,
+ IMultiProtocolSocketListener *protocolListener)
+{
+ return QT3DS_NEW(fnd.getAllocator(), SMultiProtocolSocketImpl)(fnd, inStream, strTable,
+ protocolListener);
+}
+
+NVScopedRefCounted<IMultiProtocolStreamLuaCompat>
+IMultiProtocolStreamLuaCompat::Create(NVFoundationBase &fnd, IMultiProtocolSocket &socket)
+{
+ return QT3DS_NEW(fnd.getAllocator(), SMultiProtocolStreamLuaCompatImpl)(fnd, socket);
+}
+
+void IMultiProtocolStreamLuaCompat::Bind(lua_State *state, IMultiProtocolStreamLuaCompat &stream)
+{
+ int top = lua_gettop(state);
+ lua_newtable(state);
+ IMultiProtocolStreamLuaCompat **theStreamAddress =
+ reinterpret_cast<IMultiProtocolStreamLuaCompat **>(lua_newuserdata(state, sizeof(&stream)));
+ *theStreamAddress = &stream;
+ luaL_getmetatable(state, "IMultiProtocolStreamLuaCompat");
+ if (lua_isnil(state, -1)) {
+ lua_pop(state, 1);
+ luaL_newmetatable(state, "IMultiProtocolStreamLuaCompat");
+ lua_pushcfunction(state, MultiProtocolStreamLuaCompatGC);
+ lua_setfield(state, -2, "__gc");
+ }
+ lua_setmetatable(state, -2);
+ stream.addRef();
+ lua_setfield(state, -2, "__streamimpl");
+ lua_pushcfunction(state, MultiProtocolStreamLuaReceive);
+ lua_setfield(state, -2, "receive");
+ lua_pushcfunction(state, MultiProtocolStreamLuaSend);
+ lua_setfield(state, -2, "send");
+ lua_pushcfunction(state, MultiProtocolStreamLuaGettimeout);
+ lua_setfield(state, -2, "gettimeout");
+ lua_pushcfunction(state, MultiProtocolStreamLuaSettimeout);
+ lua_setfield(state, -2, "settimeout");
+ lua_pushcfunction(state, MultiProtocolStreamLuaHasData);
+ lua_setfield(state, -2, "hasdata");
+ int rettop = lua_gettop(state);
+ QT3DS_ASSERT(rettop - top == 1);
+ luaL_checktype(state, -1, LUA_TTABLE);
+ (void)top;
+ (void)rettop;
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.h b/src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.h
new file mode 100644
index 00000000..b920bf40
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebugStreams.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_DEBUG_STREAMS_H
+#define UIC_STATE_DEBUG_STREAMS_H
+#pragma once
+#include "UICState.h"
+#include "foundation/Socket.h"
+#include "foundation/Qt3DSTime.h"
+#include "UICStateDebugger.h"
+
+struct lua_State;
+
+namespace uic {
+namespace state {
+ namespace debugger {
+
+ class IMultiProtocolSocketStream : public IDebugOutStream
+ {
+ public:
+ virtual CRegisteredString GetProtocolName() = 0;
+ };
+
+ class IMultiProtocolSocketListener : public NVRefCounted
+ {
+ public:
+ // If a listener is returned from on new protocol, the system creates a stream
+ // with the returned listener
+ virtual IDebugStreamListener *OnNewProtocol(CRegisteredString inProtocolName) = 0;
+ // Created with the listener returned from OnNewProtocol.
+ virtual void OnNewProtocolStream(CRegisteredString inProtocolName,
+ IMultiProtocolSocketStream &inStream) = 0;
+ };
+
+ // Create a system of multiplexing multipler unrelated protocols
+ // through a single network socket.
+ class IMultiProtocolSocket : public NVRefCounted
+ {
+ public:
+ virtual bool Initialize() = 0;
+ virtual NVScopedRefCounted<IMultiProtocolSocketStream>
+ CreateProtocol(const char *name, IDebugStreamListener *inListener) = 0;
+ virtual NVScopedRefCounted<IMultiProtocolSocketStream>
+ GetProtocol(const char *name) = 0;
+ virtual bool Connected() = 0;
+
+ // Upon connection the multi protocol system does a handshake where both sides send
+ // their nanosecond
+ // conversions across. Note that the times sent on the multi protocol packets are in a
+ // system-specific 64 bit quantity that
+ // needs conversion to actual nanoseconds to be useful (identical to
+ // QueryHighPerformanceFrequency, QueryHighPerformanceCounter
+ virtual CounterFrequencyToTensOfNanos SourceConversion() = 0;
+
+ // Manually do a nonblocking check on the network socket for any new information and
+ // call the various stream listeners
+ // with information packets if found.
+ virtual void MessagePump() = 0;
+
+ static NVScopedRefCounted<IMultiProtocolSocket>
+ CreateProtocolSocket(NVFoundationBase &fnd, SocketStream &inStream,
+ IStringTable &strTable,
+ IMultiProtocolSocketListener *protocolListener);
+ };
+
+ struct LuaStreamError
+ {
+ enum _Enum {
+ NoLuaError = 0,
+ Timeout,
+ Closed,
+ };
+ };
+
+ class CProtocolNames
+ {
+ public:
+ static const char *getMobdebugProtocolName() { return "mobdebug"; }
+ static const char *getSCXMLProtocolName() { return "scxml"; }
+ };
+
+ // Maintains a queue of messages and runs through them when asked.
+ // Mirrors the lua socket design and names so that systems built on lua
+ // socket can be retrofitted to channel through a multiple protocol stream
+ // as easily as possible.
+ class IMultiProtocolStreamLuaCompat : public NVRefCounted
+ {
+ public:
+ // timeout is just used to indicate if this should be
+ // blocking or not.
+ virtual void settimeout(QT3DSU32 value = 0) = 0;
+ virtual QT3DSU32 gettimeout() = 0;
+ // returns next line of data
+ // or error. If error, retval.second will be false.
+ // reads a line at a time.
+ virtual eastl::pair<const char *, LuaStreamError::_Enum> receive(QT3DSU32 numBytes) = 0;
+ virtual void send(const char *data) = 0;
+ virtual bool hasData() = 0;
+
+ static const char *getProtocolName()
+ {
+ return CProtocolNames::getMobdebugProtocolName();
+ }
+
+ static NVScopedRefCounted<IMultiProtocolStreamLuaCompat>
+ Create(NVFoundationBase &fnd, IMultiProtocolSocket &socket);
+
+ // Puts a table at the top of the stack that binds all the functions of the stream.
+ static void Bind(lua_State *state, IMultiProtocolStreamLuaCompat &stream);
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebuggedInterpreter.cpp b/src/Runtime/Source/UICState/Debugger/UICStateDebuggedInterpreter.cpp
new file mode 100644
index 00000000..1e92d3bb
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebuggedInterpreter.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerProtocol.h"
+#include "EASTL/map.h"
+#include "EASTL/set.h"
+#include "foundation/Qt3DSAtomic.h"
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+namespace {
+
+// Horrible name, I know.
+struct SDebuggedInterpreter : public IDebuggedInterpreter
+{
+ typedef eastl::set<TDebugStr> TDebugStrSet;
+ typedef eastl::vector<SBreakpoint> TBreakpointList;
+ typedef eastl::map<TDebugStr, SDatamodelValue> TDataModelTable;
+ typedef eastl::hash_map<SDatamodelTable *, TDataModelTable> TTableMap;
+ typedef eastl::vector<STableEntry> TTableEntryList;
+ // Null is the datamodel table.
+
+ NVAllocatorCallback &m_Allocator;
+ NVScopedRefCounted<IDebugOutStream> m_Stream;
+ QT3DSI32 mRefCount;
+ TEditorPtr m_Editor;
+ TDebugStr m_Filename;
+ SMessageSerializer m_Serializer;
+ QT3DSI32 m_StreamId;
+ TBreakpointList m_Breakpoints;
+ TDebugStrList m_StrList;
+ TDebugStrSet m_Configuration;
+ bool m_BreakOnMicrostep;
+ bool m_IsBroken;
+ Option<SBreakpoint> m_BrokenBreakpoint;
+ IDebuggerMasterListener &m_Listener;
+ TTableMap m_DatamodelValues;
+ mutable TTableEntryList m_TempEntries;
+ bool m_MicrostepHasData;
+ SMicrostepData m_MicrostepData;
+ TDebugStr m_MicrostepEvent;
+ TDebugStrList m_ConfigurationList;
+ TDebugStrList m_PreviousConfiguration;
+
+ SDebuggedInterpreter(NVAllocatorCallback &inAlloc, IDebugOutStream &inStream,
+ TEditorPtr inEditor, const TDebugStr &inFname, QT3DSI32 inStreamId,
+ NVConstDataRef<TDebugStr> inConfiguration,
+ IDebuggerMasterListener &inListener)
+ : m_Allocator(inAlloc)
+ , m_Stream(inStream)
+ , mRefCount(0)
+ , m_Editor(inEditor)
+ , m_Filename(inFname)
+ , m_StreamId(inStreamId)
+ , m_BreakOnMicrostep(false)
+ , m_IsBroken(false)
+ , m_Listener(inListener)
+ , m_MicrostepHasData(false)
+ {
+ m_ConfigurationList.assign(inConfiguration.begin(), inConfiguration.end());
+ m_Configuration.insert(inConfiguration.begin(), inConfiguration.end());
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+
+ // Get the editor that represents the state graph for this debugged interpreter.
+ TEditorPtr GetEditor() override { return m_Editor; }
+ TDebugStr GetFilename() const override { return m_Filename; }
+
+ template <typename TMessageType>
+ void SendMessage(const TMessageType &inMessage)
+ {
+ m_Serializer.Serialize(m_StreamId, inMessage, 0);
+ m_Stream->Write(m_Serializer.ToRawMessage());
+ }
+
+ // Used when connecting to a live session.
+ void SetBreakpoint(const SBreakpoint &inBreakpoint) override
+ {
+ TBreakpointList::iterator iter =
+ eastl::find(m_Breakpoints.begin(), m_Breakpoints.end(), inBreakpoint);
+ if (iter == m_Breakpoints.end()) {
+ SendMessage(SSetBreakpoint(inBreakpoint));
+ m_Breakpoints.push_back(inBreakpoint);
+ }
+ }
+
+ void ClearBreakpoint(const SBreakpoint &inBreakpoint) override
+ {
+ TBreakpointList::iterator iter =
+ eastl::find(m_Breakpoints.begin(), m_Breakpoints.end(), inBreakpoint);
+ if (iter != m_Breakpoints.end()) {
+ SendMessage(SClearBreakpoint(inBreakpoint));
+ m_Breakpoints.erase(iter);
+ }
+ }
+
+ NVConstDataRef<SBreakpoint> GetBreakpoints() override
+ {
+ return toDataRef(m_Breakpoints.data(), m_Breakpoints.size());
+ }
+
+ void ClearAllBreakpoints() override
+ {
+ SendMessage(SClearAllBreakpoints());
+ m_Breakpoints.clear();
+ }
+
+ // break at the *end* of the microstep so you can see the data of the microstep.
+ void SetBreakOnMicrostep(bool inBreak) override
+ {
+ if (m_BreakOnMicrostep != inBreak) {
+ m_BreakOnMicrostep = inBreak;
+ SendMessage(SBreakOnMicrostep(inBreak));
+ }
+ }
+ bool IsBreakOnMicrostep() const override { return m_BreakOnMicrostep; }
+
+ NVConstDataRef<STableEntry> TableToList(const TDataModelTable &inTable) const
+ {
+ m_TempEntries.resize(inTable.size());
+ QT3DSU32 idx = 0;
+ for (TDataModelTable::const_iterator iter = inTable.begin(), end = inTable.end();
+ iter != end; ++iter, ++idx)
+ m_TempEntries[idx] = STableEntry(iter->first, iter->second);
+ return toConstDataRef(m_TempEntries.data(), m_TempEntries.size());
+ }
+
+ NVConstDataRef<STableEntry> GetTableValues(SDatamodelTable *inTable) const override
+ {
+ TTableMap::const_iterator iter = m_DatamodelValues.find(inTable);
+ if (iter != m_DatamodelValues.end())
+ return TableToList(iter->second);
+ return NVConstDataRef<STableEntry>();
+ }
+
+ NVConstDataRef<TDebugStr> GetPreviousConfiguration() const override
+ {
+ return toConstDataRef(m_PreviousConfiguration.data(), m_PreviousConfiguration.size());
+ }
+ NVConstDataRef<TDebugStr> GetConfiguration() const override
+ {
+ return toConstDataRef(m_ConfigurationList.data(), m_ConfigurationList.size());
+ }
+ const TDebugStr &GetMicrostepEvent() const override { return m_MicrostepEvent; }
+ NVConstDataRef<STransitionId> GetMicrostepTransitions() const override
+ {
+ return toConstDataRef(m_MicrostepData.m_Transitions.data(),
+ m_MicrostepData.m_Transitions.size());
+ }
+ NVConstDataRef<TDebugStr> GetMicrostepEnterStates() const override
+ {
+ return toConstDataRef(m_MicrostepData.m_EnterStates.data(),
+ m_MicrostepData.m_EnterStates.size());
+ }
+ NVConstDataRef<TDebugStr> GetMicrostepExitStates() const override
+ {
+ return toConstDataRef(m_MicrostepData.m_ExitStates.data(),
+ m_MicrostepData.m_ExitStates.size());
+ }
+ void Continue() override
+ {
+ SendMessage(SContinue());
+ m_IsBroken = false;
+ m_BrokenBreakpoint = Option<SBreakpoint>();
+ }
+
+ void Disconnect() override
+ {
+ ClearAllBreakpoints();
+ SetBreakOnMicrostep(false);
+ if (m_IsBroken == true)
+ Continue();
+
+ SendMessage(SDisconnect());
+ }
+
+ void BreakpointHit(const SBreakpoint &inBreakpoint) override
+ {
+ m_BrokenBreakpoint = inBreakpoint;
+ m_IsBroken = true;
+ m_Listener.OnInterpreterBroken(*this, inBreakpoint);
+ }
+
+ void OnEventQueued(const SEventQueued &inMsg) override
+ {
+ m_Listener.OnEventQueued(inMsg.m_Event, inMsg.m_Internal);
+ }
+
+ void OnBeginStep(const SBeginStep &) override { m_Listener.OnBeginStep(*this); }
+
+ void OnBeginMicrostep(const SBeginMicrostep &) override
+ {
+ m_MicrostepEvent.clear();
+ m_MicrostepData.m_Transitions.clear();
+ m_MicrostepData.m_EnterStates.clear();
+ m_MicrostepData.m_ExitStates.clear();
+ m_MicrostepHasData = false;
+ m_Listener.OnBeginMicrostep(*this);
+ }
+
+ void OnMicrostepEvent(const SMicrostepEvent &inMsg) override
+ {
+ m_MicrostepEvent = inMsg.m_Event;
+ }
+
+ void OnMicrostepData(const SMicrostepData &inMsg) override
+ {
+ m_MicrostepData = inMsg;
+ m_MicrostepHasData = true;
+ }
+ void OnEndMicrostep(const SEndMicrostep & /*inMsg*/) override
+ {
+ if (m_MicrostepHasData == false && m_MicrostepEvent.empty() == false) {
+ m_Listener.OnEventProcessed(m_MicrostepEvent, false);
+ } else {
+ m_PreviousConfiguration = m_ConfigurationList;
+
+ for (TDebugStrList::const_iterator iter = m_MicrostepData.m_ExitStates.begin(),
+ end = m_MicrostepData.m_ExitStates.end();
+ iter != end; ++iter)
+ m_Configuration.erase(*iter);
+
+ m_Configuration.insert(m_MicrostepData.m_EnterStates.begin(),
+ m_MicrostepData.m_EnterStates.end());
+
+ m_ConfigurationList.clear();
+ m_ConfigurationList.insert(m_ConfigurationList.end(), m_Configuration.begin(),
+ m_Configuration.end());
+ if (m_BreakOnMicrostep) {
+ m_IsBroken = true;
+ m_Listener.OnInterpreterBroken(*this, Option<SBreakpoint>());
+ } else
+ m_Listener.OnMicrostep(*this);
+ }
+ }
+
+ void OnModifyTable(const SModifyTableValues &inValues) override
+ {
+ TTableMap::iterator iter =
+ m_DatamodelValues.insert(eastl::make_pair(inValues.m_TablePtr, TDataModelTable()))
+ .first;
+ for (QT3DSU32 idx = 0, end = inValues.m_Modifications.size(); idx < end; ++idx) {
+ const STableModification &theMod(inValues.m_Modifications[idx]);
+ switch (theMod.m_Type) {
+ case TableModificationType::RemoveKey:
+ iter->second.erase(theMod.m_Entry.m_Key);
+ break;
+ case TableModificationType::SetKey:
+ (iter->second)[theMod.m_Entry.m_Key] = theMod.m_Entry.m_Value;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ m_Listener.OnDatamodelChange(
+ *this, inValues.m_TablePtr,
+ toConstDataRef(inValues.m_Modifications.data(), inValues.m_Modifications.size()));
+ }
+
+ bool IsBroken() const override { return m_IsBroken; }
+};
+}
+
+IDebuggedInterpreter &IDebuggedInterpreter::Create(NVAllocatorCallback &inAlloc,
+ IDebugOutStream &inStream, TEditorPtr inEditor,
+ const TDebugStr &inFilename, QT3DSI32 inStreamId,
+ NVConstDataRef<TDebugStr> inConfiguration,
+ IDebuggerMasterListener &inListener)
+{
+ return *QT3DS_NEW(inAlloc, SDebuggedInterpreter)(inAlloc, inStream, inEditor, inFilename,
+ inStreamId, inConfiguration, inListener);
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebugger.cpp b/src/Runtime/Source/UICState/Debugger/UICStateDebugger.cpp
new file mode 100644
index 00000000..8f7428c9
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebugger.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerValues.h"
+#include "UICStateDebuggerProtocol.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/IOStreams.h"
+
+using namespace uic::state::debugger;
+using namespace uic::state;
+
+namespace {
+
+static MallocAllocator g_MallocAlloc;
+
+struct SDebugger : public IDebugger
+{
+ typedef eastl::vector<NVScopedRefCounted<IStateMachineDebugInterface>> TDebugList;
+ typedef eastl::hash_map<IStateMachineDebugInterface *, QT3DSI32> TMachineIdMap;
+ typedef eastl::hash_map<QT3DSI32, eastl::pair<NVScopedRefCounted<IStateMachineDebugInterface>,
+ NVScopedRefCounted<IStateMachineListener>>>
+ TIdMachineMap;
+ QT3DSI32 mRefCount;
+ QT3DSI32 m_NextStateMachineId;
+ TDebugList m_StateMachineList;
+ TMachineIdMap m_StateMachines;
+ TIdMachineMap m_IdToStateMachines;
+ QT3DSU64 m_StartTime;
+ NVScopedRefCounted<IDebugOutStream> m_OutStream;
+ SMessageParser<SDebugger> m_Parser;
+ SMessageSerializer m_MessageSerializer;
+ TDebugStr m_MessageStr;
+
+ SDebugger()
+ : mRefCount(0)
+ , m_NextStateMachineId(1)
+ , m_StartTime(Time::getCurrentCounterValue())
+ {
+ }
+
+ virtual ~SDebugger() { DisconnectFromServer(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_MallocAlloc)
+
+ void ConnectStateMachine(IStateMachineDebugInterface &inMachine)
+ {
+ TMachineIdMap::iterator theIter = m_StateMachines.find(&inMachine);
+ if (theIter != m_StateMachines.end())
+ return;
+ QT3DSI32 theId(m_NextStateMachineId);
+ ++m_NextStateMachineId;
+ IStateMachineListener *theListener =
+ &IStateMachineListener::Create(g_MallocAlloc, theId, *m_OutStream.mPtr, m_StartTime,
+ *this, inMachine.GetScriptContext());
+ inMachine.SetStateMachineListener(theListener);
+ m_StateMachines.insert(eastl::make_pair(&inMachine, theId));
+ m_IdToStateMachines.insert(
+ eastl::make_pair(theId, eastl::make_pair(&inMachine, theListener)));
+ }
+
+ void OnServerConnected(IDebugOutStream &inStream) override
+ {
+ m_OutStream = inStream;
+ inStream.SetListener(this);
+ m_MessageSerializer.Serialize(0, SInitialization(), m_StartTime);
+ m_OutStream->Write(m_MessageSerializer.ToRawMessage());
+ for (QT3DSU32 idx = 0, end = m_StateMachineList.size(); idx < end; ++idx)
+ ConnectStateMachine(*m_StateMachineList[idx]);
+ }
+
+ void Connect(IStateMachineDebugInterface &inMachine) override
+ {
+ TDebugList::iterator theFind =
+ eastl::find(m_StateMachineList.begin(), m_StateMachineList.end(), &inMachine);
+ if (theFind == m_StateMachineList.end()) {
+ m_StateMachineList.push_back(&inMachine);
+ if (m_OutStream)
+ ConnectStateMachine(inMachine);
+ }
+ }
+
+ void OnExternalBreak() override
+ {
+ if (m_OutStream) {
+ for (QT3DSU32 idx = 0, end = m_StateMachineList.size(); idx < end; ++idx)
+ m_StateMachineList[idx]->OnExternalBreak();
+ }
+ }
+
+ void DisconnectStateMachine(IStateMachineDebugInterface &inMachine)
+ {
+ TMachineIdMap::iterator theIter = m_StateMachines.find(&inMachine);
+ if (theIter == m_StateMachines.end())
+ return;
+
+ QT3DSI32 theId = theIter->second;
+ m_MessageSerializer.Serialize(theId, SDisconnect(),
+ Time::getCurrentCounterValue() - m_StartTime);
+ m_OutStream->Write(m_MessageSerializer.ToRawMessage());
+ inMachine.SetStateMachineListener(NULL);
+ m_StateMachines.erase(&inMachine);
+ m_IdToStateMachines.erase(theId);
+ }
+ void Disconnect(IStateMachineDebugInterface &inMachine) override
+ {
+ TDebugList::iterator theFind =
+ eastl::find(m_StateMachineList.begin(), m_StateMachineList.end(), &inMachine);
+ if (theFind != m_StateMachineList.end()) {
+ DisconnectStateMachine(inMachine);
+ m_StateMachineList.erase(theFind);
+ }
+ }
+
+ void DisconnectFromServer() override
+ {
+ if (m_OutStream) {
+ m_MessageSerializer.Serialize(-1, SDisconnect(),
+ Time::getCurrentCounterValue() - m_StartTime);
+ m_OutStream->Write(m_MessageSerializer.ToRawMessage());
+ }
+ m_StateMachines.clear();
+ m_IdToStateMachines.clear();
+ m_StateMachineList.clear();
+ m_OutStream = NULL;
+ }
+
+ void OnMessageReceived(const SDebugStreamMessage &msg) override
+ {
+ if (msg.m_Data.size())
+ m_Parser.Parse(msg.m_Data, *this);
+ }
+
+// Set of ignored messages
+#define IGNORE_DEBUG_MESSAGE_TYPE(tname) \
+ void OnMessage(QT3DSI32, QT3DSU64, const S##tname &) { QT3DS_ASSERT(false); }
+
+ // this are outgoing messages; we shouldn't be receiving them.
+ IGNORE_DEBUG_MESSAGE_TYPE(Initialization)
+ IGNORE_DEBUG_MESSAGE_TYPE(Connect)
+ IGNORE_DEBUG_MESSAGE_TYPE(BreakpointHit)
+ IGNORE_DEBUG_MESSAGE_TYPE(DebugLog)
+ IGNORE_DEBUG_MESSAGE_TYPE(EventQueued)
+ IGNORE_DEBUG_MESSAGE_TYPE(BeginStep)
+ IGNORE_DEBUG_MESSAGE_TYPE(BeginMicrostep)
+ IGNORE_DEBUG_MESSAGE_TYPE(MicrostepEvent)
+ IGNORE_DEBUG_MESSAGE_TYPE(MicrostepData)
+ IGNORE_DEBUG_MESSAGE_TYPE(EndMicrostep)
+ IGNORE_DEBUG_MESSAGE_TYPE(ModifyTableValues)
+
+ IStateMachineDebugInterface *GetStateMachine(QT3DSI32 inStreamId)
+ {
+ TIdMachineMap::iterator theIter = m_IdToStateMachines.find(inStreamId);
+ if (theIter == m_IdToStateMachines.end())
+ return NULL;
+ return theIter->second.first.mPtr;
+ }
+
+ IStateMachineListener *GetStateMachineListener(QT3DSI32 inStreamId)
+ {
+ TIdMachineMap::iterator theIter = m_IdToStateMachines.find(inStreamId);
+ if (theIter == m_IdToStateMachines.end())
+ return NULL;
+ return theIter->second.second.mPtr;
+ }
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SSetBreakpoint &inBp)
+ {
+ IStateMachineListener *iface = GetStateMachineListener(sid);
+ if (iface)
+ iface->SetBreakpoint(inBp.m_Breakpoint);
+ }
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SClearBreakpoint &inBp)
+ {
+ IStateMachineListener *iface = GetStateMachineListener(sid);
+ if (iface)
+ iface->ClearBreakpoint(inBp.m_Breakpoint);
+ }
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SClearAllBreakpoints &)
+ {
+ IStateMachineListener *iface = GetStateMachineListener(sid);
+ if (iface)
+ iface->ClearAllBreakpoints();
+ }
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SBreakOnMicrostep &inCmd)
+ {
+ IStateMachineListener *iface = GetStateMachineListener(sid);
+ if (iface)
+ iface->SetBreakOnMicrostep(inCmd.m_Value);
+ }
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SContinue &)
+ {
+ IStateMachineListener *iface = GetStateMachineListener(sid);
+ if (iface)
+ iface->Continue();
+ }
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SDisconnect &)
+ {
+ if (sid != 0 && sid != (QT3DSI32)QT3DS_MAX_U32) {
+ IStateMachineDebugInterface *iface = GetStateMachine(sid);
+ if (iface)
+ Disconnect(*iface);
+ } else {
+ if (sid == (QT3DSI32)QT3DS_MAX_U32)
+ DisconnectFromServer();
+ }
+ }
+
+ void error(const char8_t *, const char8_t *) {}
+};
+
+static inline NVConstDataRef<QT3DSU8> ToRef(const TDebugStr &str)
+{
+ return NVConstDataRef<QT3DSU8>((const QT3DSU8 *)str.begin(), str.size());
+}
+
+bool TestBasicParseRobustness()
+{
+ typedef STestMessageHandler<SInitialization> THandlerType;
+ typedef SMessageParser<THandlerType> TParserType;
+ // Just ensure things don't crash.
+ SInitialization testType;
+ THandlerType theHandler(2, 5, testType);
+ TDebugStr theStr;
+ TParserType theParser;
+ theParser.Parse(ToRef(theStr), theHandler);
+
+ theStr = "Initialization";
+ theParser.Parse(ToRef(theStr), theHandler);
+
+ theStr = "Initialization ";
+ theParser.Parse(ToRef(theStr), theHandler);
+ return true;
+}
+
+template <typename TDataType>
+bool TestSerialization(const TDataType &testType, SMessageSerializer &ioSerializer,
+ QT3DSU64 inTimestamp)
+{
+ typedef STestMessageHandler<TDataType> THandlerType;
+ typedef SMessageParser<THandlerType> TParserType;
+
+ ioSerializer.Serialize(5, testType, inTimestamp);
+ THandlerType theHandler(5, inTimestamp, testType);
+ TParserType theParser;
+ theParser.Parse(ioSerializer.ToRawMessage(), theHandler);
+ return theHandler.m_Result;
+}
+}
+
+IDebugger &IDebugger::CreateDebugger()
+{
+ return *QT3DS_NEW(g_MallocAlloc, SDebugger)();
+}
+
+bool CDebuggerTests::TestStreamProtocol()
+{
+ // for each message type, fill on some values, serialize to string and back and see what happens
+ TDebugStrList theList;
+ theList.push_back("one");
+ theList.push_back("two");
+ TTransitionIdList theTransList;
+ theTransList.push_back(STransitionId("one", 2));
+ theTransList.push_back(STransitionId("two", -1));
+ SBreakpoint bp1(SStateEnterBreakpoint("one"));
+ SBreakpoint bp2(SStateExitBreakpoint("two"));
+ SBreakpoint bp3(STransitionId("three", 4));
+ SMessageSerializer theSerializer;
+ bool retval = TestBasicParseRobustness();
+ // breaking out the large && statement to make testing easier.
+ retval = retval && TestSerialization(SInitialization(), theSerializer, 5);
+ retval = retval && TestSerialization(SConnect("abe.scxml", "<one>hey you</one>", theList),
+ theSerializer, 6);
+ retval = retval
+ && TestSerialization(SDebugLog(TDebugStr("Hey joe, where you goin'")), theSerializer, 7);
+ retval = retval && TestSerialization(SBeginMicrostep(), theSerializer, 8);
+ retval = retval && TestSerialization(SMicrostepEvent("evt1", true), theSerializer, 9);
+ retval = retval
+ && TestSerialization(SMicrostepData(theTransList, theList, theList), theSerializer, 9);
+ retval = retval && TestSerialization(SEndMicrostep(), theSerializer, 10);
+ retval = retval && TestSerialization(SEventQueued("evt1", false), theSerializer, 11);
+ retval = retval && TestSerialization(SEventQueued("evt1", false), theSerializer, 12);
+ retval = retval && TestSerialization(SSetBreakpoint(bp1), theSerializer, 13);
+ retval = retval && TestSerialization(SSetBreakpoint(bp2), theSerializer, 14);
+ retval = retval && TestSerialization(SSetBreakpoint(bp3), theSerializer, 15);
+ retval = retval && TestSerialization(SClearBreakpoint(bp1), theSerializer, 16);
+ retval = retval && TestSerialization(SClearAllBreakpoints(), theSerializer, 17);
+ return retval;
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebugger.h b/src/Runtime/Source/UICState/Debugger/UICStateDebugger.h
new file mode 100644
index 00000000..c5d50faf
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebugger.h
@@ -0,0 +1,391 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_DEBUGGER_H
+#define UIC_STATE_DEBUGGER_H
+#pragma once
+#include "UICState.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/StringTable.h"
+#include "foundation/IOStreams.h"
+#include "UICStateEditor.h"
+
+namespace uic {
+namespace state {
+ namespace debugger {
+ using namespace editor;
+
+ typedef TEditorStr TDebugStr;
+ struct SDebugValue;
+ struct SBreakpoint;
+ struct SNil;
+ struct SDatamodelTable;
+ struct SDatamodelUserData;
+ struct SDatamodelFunction;
+ struct SDatamodelCFunction;
+ struct SDatamodelThread;
+
+ typedef eastl::vector<SBreakpoint> TBreakpointList;
+
+ struct BreakpointTypes
+ {
+ enum Enum {
+ UnknownBreakpointType = 0,
+ StateEnter,
+ StateExit,
+ Transition,
+ };
+ };
+
+ struct SDebugStreamMessage
+ {
+ // Timestamp needs to be converted using the SourceConversion on the protocol socket.
+ QT3DSU64 m_Timestamp;
+ NVConstDataRef<QT3DSU8> m_Data;
+ SDebugStreamMessage()
+ : m_Timestamp(0)
+ {
+ }
+ SDebugStreamMessage(QT3DSU64 ts, NVConstDataRef<QT3DSU8> msg)
+ : m_Timestamp(ts)
+ , m_Data(msg)
+ {
+ }
+ };
+
+ // Note the stream listeners are not ref counted.
+ // it is your job to ensure it lasts as long as debug stream.
+ class IDebugStreamListener
+ {
+ protected:
+ virtual ~IDebugStreamListener() {}
+ public:
+ // Async message interface. Clients must provide this. Only called on main thread
+ virtual void OnMessageReceived(const SDebugStreamMessage &inMessage) = 0;
+ };
+
+ class IDebugOutStream : public NVRefCounted, public IOutStream
+ {
+ protected:
+ virtual ~IDebugOutStream() {}
+ public:
+ virtual void SetListener(IDebugStreamListener *listener) = 0;
+ virtual IDebugStreamListener *GetListener() = 0;
+ // return true if the stream is still connected to an output, false if
+ // something caused the connection to fail or close.
+ virtual SDebugStreamMessage WaitForNextMessage() = 0;
+ virtual bool Connected() = 0;
+ };
+
+ struct STransitionId
+ {
+ TDebugStr m_StateId;
+ // Index in file order of the transition.
+ //-1 means initial or history::transition, depending on if the state is
+ // a normal state or history state.
+ QT3DSI32 m_TransitionIndex;
+ STransitionId(const TDebugStr &inId = TDebugStr(), QT3DSI32 inIdx = -2)
+ : m_StateId(inId)
+ , m_TransitionIndex(inIdx)
+ {
+ }
+ bool operator==(const STransitionId &inOther) const
+ {
+ return m_StateId == inOther.m_StateId
+ && m_TransitionIndex == inOther.m_TransitionIndex;
+ }
+ };
+
+ typedef eastl::vector<STransitionId> TTransitionIdList;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Client (runtime) side types
+ ///////////////////////////////////////////////////////////////////////
+
+ struct DatamodelValueTypes
+ {
+ enum Enum {
+ UnknownType = 0,
+ Nil,
+ Boolean,
+ Number,
+ String,
+ Table,
+ UserData,
+ Function,
+ CFunction,
+ Thread,
+ };
+ };
+
+ struct SDatamodelValue;
+
+ struct SDatamodelTable;
+ struct SDatamodelUserData;
+ struct SDatamodelFunction;
+ struct SDatamodelCFunction;
+ struct SDatamodelThread;
+ struct STableEntry;
+
+ class IScriptStateListener
+ {
+ protected:
+ virtual ~IScriptStateListener() {}
+ public:
+ virtual void SetKey(void *inTable, const TDebugStr &inStr,
+ const SDatamodelValue &inValue) = 0;
+ virtual void RemoveKey(void *inTable, const TDebugStr &inStr) = 0;
+ };
+
+ class IDebugger;
+ // Information coming from the state machine
+ class IStateMachineListener : public NVRefCounted
+ {
+ protected:
+ virtual ~IStateMachineListener() {}
+ public:
+ // Events coming from the interpreter and sent over the interface.
+ virtual void OnConnect(const TDebugStr &SCXMLFilename, const TDebugStr &SCXMLFileData,
+ NVConstDataRef<TDebugStr> inConfiguration) = 0;
+
+ virtual void Log(const TDebugStr &inStr) = 0;
+ virtual void EventQueued(const TDebugStr &inEventName, bool inInternal) = 0;
+ virtual void BeginStep() = 0;
+ virtual void BeginMicroStep() = 0;
+ virtual void SetEvent(const TDebugStr &inEventName, bool inInternal) = 0;
+ virtual void SetTransitionSet(NVConstDataRef<STransitionId> inTransitions) = 0;
+ virtual void SetExitSet(NVConstDataRef<TDebugStr> inSet) = 0;
+ virtual void SetEnterSet(NVConstDataRef<TDebugStr> inSet) = 0;
+ // Log statements run through the debugger as well.
+ virtual void EndMicroStep() = 0;
+ virtual void EndStep() = 0;
+
+ // So far the breakpoints have all been things that are internal to the
+ // state machine.
+ virtual void SetBreakOnMicrostep(bool inEnableStep) = 0;
+ virtual void SetBreakpoint(const SBreakpoint &inBreakpoint) = 0;
+ virtual void ClearBreakpoint(const SBreakpoint &inBreakpoint) = 0;
+ virtual void ClearAllBreakpoints() = 0;
+
+ // Called internally.
+ virtual void Continue() = 0;
+ virtual void OnExternalBreak() = 0;
+
+ static IStateMachineListener &Create(NVAllocatorCallback &inAlloc, QT3DSU32 inStreamId,
+ IDebugOutStream &inOutStr, QT3DSU64 inStartTime,
+ IDebugger &inDebugger,
+ IScriptContext &inScriptContext);
+ };
+
+ // Information coming from the network stream will call these iterfaces
+ // Since we want to debug both c++ and lua state machines, we need a common
+ // interface to talk to.
+ class IStateMachineDebugInterface : public NVRefCounted
+ {
+ protected:
+ virtual ~IStateMachineDebugInterface() {}
+ public:
+ virtual void SetStateMachineListener(IStateMachineListener *inListener) = 0;
+ virtual void OnExternalBreak() = 0;
+ virtual IScriptContext &GetScriptContext() = 0;
+ };
+
+ // The debugger element is the object that sits in the debug process interpreter and sends
+ // information.
+ // There should be only one of these per network connection.
+ class IDebugger : public IDebugStreamListener, public NVRefCounted
+ {
+ protected:
+ virtual ~IDebugger() {}
+ public:
+ virtual void OnServerConnected(IDebugOutStream &inStream) = 0;
+ virtual void Connect(IStateMachineDebugInterface &inMachine) = 0;
+ // Called when an external entity breaks and we need to update the lua.
+ // In this case we want to update all state machine datasets.
+ virtual void OnExternalBreak() = 0;
+ virtual void Disconnect(IStateMachineDebugInterface &inMachine) = 0;
+ // Release any references to any state machines and to the output stream
+ virtual void DisconnectFromServer() = 0;
+
+ static IDebugger &CreateDebugger();
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Server (Architect) side types
+ ///////////////////////////////////////////////////////////////////////
+
+ struct DebugValueTypes
+ {
+ enum Enum { NoDebugValue = 0, String, StringList, TransitionIdList };
+ };
+
+ typedef eastl::vector<TDebugStr> TDebugStrList;
+
+ struct STableModification;
+
+ class IDebuggedInterpreter;
+
+ class IDebuggerMasterListener : public NVRefCounted
+ {
+ protected:
+ virtual ~IDebuggerMasterListener() {}
+ public:
+ virtual void OnInterpreterConnected(IDebuggedInterpreter &inInterpreter) = 0;
+ // If no breakpoint then the interpreter was broken on microstep.
+ virtual void OnEventQueued(const TDebugStr &inEvent, bool inInternal) = 0;
+ virtual void OnInterpreterBroken(IDebuggedInterpreter &inInterpreter,
+ const Option<SBreakpoint> &inBreakpoint) = 0;
+ // Event processed but no microstep was taken.
+ virtual void OnEventProcessed(const TDebugStr &inEvent, bool inInternal) = 0;
+ virtual void OnBeginStep(IDebuggedInterpreter &inInterpreter) = 0;
+ virtual void OnBeginMicrostep(IDebuggedInterpreter &inInterpreter) = 0;
+ // Event processed and microstep was taken.
+ virtual void OnMicrostep(IDebuggedInterpreter &inInterpreter) = 0;
+ // if inmodifications is empty the table needs to be replaced.
+ virtual void OnDatamodelChange(IDebuggedInterpreter &inInterpreter,
+ SDatamodelTable *inTable,
+ NVConstDataRef<STableModification> inModifications) = 0;
+ virtual void OnInterpreterDisconnected(IDebuggedInterpreter &inInterpreter) = 0;
+ virtual void OnLog(IDebuggedInterpreter *inInterpreter, const TDebugStr &inMessage) = 0;
+ };
+
+ struct STableEntry;
+
+ typedef eastl::vector<STableEntry> TTableEntryList;
+
+ // defined in UICStateDebuggerProtocol.h"
+ struct SBeginStep;
+ struct SBeginMicrostep;
+ struct SMicrostepEvent;
+ struct SMicrostepData;
+ struct SEndMicrostep;
+ struct SEventQueued;
+ struct SModifyTableValues;
+ struct SDatamodelTable;
+
+ // Represents the data stream coming from a single interpreter
+ class IDebuggedInterpreter : public NVRefCounted
+ {
+ protected:
+ virtual ~IDebuggedInterpreter() {}
+ public:
+ /* Playback interface, leaving until basic functionality is working.
+ virtual QT3DSU32 GetStepCount() = 0;
+ virtual void SetCurrentStep( QT3DSU32 inStep ) = 0;
+ virtual QT3DSU32 GetMicrostepCount() = 0;
+ virtual QT3DSU32 SetCurrentMicroStep( QT3DSU32 inStep ) = 0;
+ */
+
+ // Get the editor that represents the state graph for this debugged interpreter.
+ virtual TEditorPtr GetEditor() = 0;
+ virtual TDebugStr GetFilename() const = 0;
+
+ // Used when connecting to a live session.
+ virtual void SetBreakpoint(const SBreakpoint &inBreakpoint) = 0;
+ virtual void ClearBreakpoint(const SBreakpoint &inBreakpoint) = 0;
+ virtual NVConstDataRef<SBreakpoint> GetBreakpoints() = 0;
+ virtual void ClearAllBreakpoints() = 0;
+ // break at the *end* of the microstep so you can see the data of the microstep.
+ virtual void SetBreakOnMicrostep(bool inBreak) = 0;
+ virtual bool IsBreakOnMicrostep() const = 0;
+
+ // Return values not valid after *next* call.
+ // Null means the root.
+ virtual NVConstDataRef<STableEntry>
+ GetTableValues(SDatamodelTable *inTable = NULL) const = 0;
+
+ virtual NVConstDataRef<TDebugStr> GetPreviousConfiguration() const = 0;
+ virtual NVConstDataRef<TDebugStr> GetConfiguration() const = 0;
+ virtual const TDebugStr &GetMicrostepEvent() const = 0;
+ virtual NVConstDataRef<STransitionId> GetMicrostepTransitions() const = 0;
+ virtual NVConstDataRef<TDebugStr> GetMicrostepEnterStates() const = 0;
+ virtual NVConstDataRef<TDebugStr> GetMicrostepExitStates() const = 0;
+
+ virtual bool IsBroken() const = 0;
+ virtual void Continue() = 0;
+ // Get the set of changed properties since the last time you asked. Obviously this is
+ // assuming there
+ // is only one 'you' asking.
+ virtual void Disconnect() = 0;
+
+ // Semi-advanced debugger functionality that we don't need for version 1.
+
+ // virtual void SetPropertyValue( const char8_t* inName, const SDebugValue& inValue ) =
+ // 0;
+ // Set a property value on the running state machine.
+ // virtual void SetPropertyValue( TObjPtr inEditorObj, const char8_t* inName, const
+ // SValueOpt& inValue ) = 0;
+
+ // Eval code in the current state machine context. Works when connected live, wouldn't
+ // work if you
+ // were not connected live.
+ // virtual TDebugStr EvalCode( const TDebugStr& inStr ) = 0;
+
+ // Information coming from the stream, clients should not call these functions
+ virtual void BreakpointHit(const SBreakpoint &inBreakpoint) = 0;
+ virtual void OnEventQueued(const SEventQueued &inMsg) = 0;
+ virtual void OnBeginStep(const SBeginStep &inMsg) = 0;
+ virtual void OnBeginMicrostep(const SBeginMicrostep &inMsg) = 0;
+ virtual void OnMicrostepEvent(const SMicrostepEvent &inMsg) = 0;
+ virtual void OnMicrostepData(const SMicrostepData &inMsg) = 0;
+ virtual void OnEndMicrostep(const SEndMicrostep &inMsg) = 0;
+ virtual void OnModifyTable(const SModifyTableValues &inValues) = 0;
+
+ static IDebuggedInterpreter &Create(NVAllocatorCallback &inAlloc,
+ IDebugOutStream &inStream, TEditorPtr inEditor,
+ const TDebugStr &inFilename, QT3DSI32 inStreamId,
+ NVConstDataRef<TDebugStr> inConfiguration,
+ IDebuggerMasterListener &inListener);
+ };
+
+ // Debugger sites in the master process (Architect process) and controls one or more
+ // debuggers
+ // for one or more state machines running in the debug process.
+ class IDebuggerMaster : public IDebugStreamListener, public NVRefCounted
+ {
+ protected:
+ virtual ~IDebuggerMaster() {}
+ public:
+ virtual void Disconnect() = 0;
+
+ static IDebuggerMaster &CreateMaster(IDebugOutStream &outStream,
+ IDebuggerMasterListener &inListener);
+ };
+
+ class CDebuggerTests
+ {
+ public:
+ static bool TestStreamProtocol();
+ };
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebuggerListener.cpp b/src/Runtime/Source/UICState/Debugger/UICStateDebuggerListener.cpp
new file mode 100644
index 00000000..603f8a5c
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebuggerListener.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerValues.h"
+#include "UICStateDebuggerProtocol.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "UICStateScriptContext.h"
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+namespace {
+
+// Component sits in the state machine and receives messages from the state machine
+// itself.
+struct SListener : public IStateMachineListener, public IScriptStateListener
+{
+ typedef eastl::hash_map<SDatamodelTable *, SModifyTableValues> TTableModificationMap;
+ NVAllocatorCallback &m_Allocator;
+ QT3DSI32 mRefCount;
+ QT3DSU32 m_StreamId;
+ NVScopedRefCounted<IDebugOutStream> m_OutStream;
+ SMessageSerializer m_Serializer;
+ TDebugStrList m_DebugStrList;
+ TDebugStrList m_DebugStrAltList;
+ TTransitionIdList m_TransitionIdList;
+ QT3DSU64 m_StartTime;
+ bool m_BreakOnMicrostep;
+ bool m_Blocking;
+ IDebugger &m_Debugger;
+ TDebugStr m_BreakStr;
+ NVScopedRefCounted<IScriptContext> m_ScriptContext;
+ TTableModificationMap m_TableModifications;
+ TBreakpointList m_Breakpoints;
+ SMicrostepData m_MicrostepData;
+ bool m_MicrostepBeginSent;
+ bool m_StepSent;
+
+ SListener(NVAllocatorCallback &alloc, QT3DSU32 inStreamId, IDebugOutStream &inOutStr,
+ QT3DSU64 inStartTime, IDebugger &inDebugger, IScriptContext &inScriptContext)
+ : m_Allocator(alloc)
+ , mRefCount(0)
+ , m_StreamId(inStreamId)
+ , m_OutStream(inOutStr)
+ , m_StartTime(inStartTime)
+ , m_BreakOnMicrostep(false)
+ , m_Blocking(false)
+ , m_Debugger(inDebugger)
+ , m_ScriptContext(inScriptContext)
+ , m_MicrostepBeginSent(false)
+ , m_StepSent(false)
+ {
+ }
+
+ virtual ~SListener() { m_Blocking = false; }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+
+ template <typename TDataType>
+ static const eastl::vector<TDataType> &RefToList(NVConstDataRef<TDataType> inRef,
+ eastl::vector<TDataType> &outList)
+ {
+ outList.assign(inRef.begin(), inRef.end());
+ return outList;
+ }
+
+ template <typename TDataType>
+ void Serialize(const TDataType &dtype, QT3DSU64 inTime)
+ {
+ m_Serializer.Serialize(m_StreamId, dtype, inTime);
+ m_OutStream->Write(m_Serializer.ToRawMessage());
+ }
+
+ template <typename TDataType>
+ void Serialize(const TDataType &dtype)
+ {
+ Serialize(dtype, CurrentTime());
+ }
+
+ void OnConnect(const TDebugStr &SCXMLFilename, const TDebugStr &SCXMLFileData,
+ NVConstDataRef<TDebugStr> inConfiguration) override
+ {
+ Serialize(
+ SConnect(SCXMLFilename, SCXMLFileData, RefToList(inConfiguration, m_DebugStrList)));
+ DumpScriptState();
+ }
+
+ QT3DSU64 CurrentTime() { return Time::getCurrentCounterValue() - m_StartTime; }
+
+ void DumpScriptState()
+ {
+ // Run through the global state and output any keys that have changed.
+ m_TableModifications.clear();
+ m_ScriptContext->DumpState(*this);
+ for (TTableModificationMap::iterator iter = m_TableModifications.begin(),
+ end = m_TableModifications.end();
+ iter != end; ++iter) {
+ Serialize(iter->second);
+ }
+ m_TableModifications.clear();
+ }
+ virtual void OnBreakpointHit(const SBreakpoint &inBreakpointId)
+ {
+ DumpScriptState();
+ Serialize(SBreakpointHit(inBreakpointId));
+ Break();
+ }
+
+ void Log(const TDebugStr &inStr) override { Serialize(SDebugLog(inStr)); }
+
+ void SetBreakpoint(const SBreakpoint &inBreakpoint) override
+ {
+ m_Breakpoints.push_back(inBreakpoint);
+ }
+
+ void ClearBreakpoint(const SBreakpoint &inBreakpoint) override
+ {
+ TBreakpointList::iterator removeIter =
+ eastl::remove(m_Breakpoints.begin(), m_Breakpoints.end(), inBreakpoint);
+ if (removeIter != m_Breakpoints.end())
+ m_Breakpoints.erase(removeIter, m_Breakpoints.end());
+ }
+ void ClearAllBreakpoints() override { m_Breakpoints.clear(); }
+ void EventQueued(const TDebugStr &inEventName, bool inInternal) override
+ {
+ Serialize(SEventQueued(inEventName, inInternal));
+ }
+ void SendMicrostepBegin()
+ {
+ if (m_MicrostepBeginSent == false) {
+ if (m_StepSent == false) {
+ m_StepSent = true;
+ Serialize(SBeginStep());
+ }
+
+ m_MicrostepBeginSent = true;
+ Serialize(SBeginMicrostep());
+ }
+ }
+
+ void BeginStep() override { m_StepSent = false; }
+
+ void BeginMicroStep() override
+ {
+ m_MicrostepBeginSent = false;
+ m_MicrostepData.m_Transitions.clear();
+ m_MicrostepData.m_EnterStates.clear();
+ m_MicrostepData.m_ExitStates.clear();
+ }
+
+ void SetEvent(const TDebugStr &inEvent, bool inInternal) override
+ {
+ if (!inEvent.empty()) {
+ SendMicrostepBegin();
+ Serialize(SMicrostepEvent(inEvent, inInternal));
+ }
+ }
+ void SetTransitionSet(NVConstDataRef<STransitionId> inTransitions) override
+ {
+ SendMicrostepBegin();
+ RefToList(inTransitions, m_MicrostepData.m_Transitions);
+ }
+ void SetExitSet(NVConstDataRef<TDebugStr> inSet) override
+ {
+ SendMicrostepBegin();
+ RefToList(inSet, m_MicrostepData.m_ExitStates);
+ }
+ void SetEnterSet(NVConstDataRef<TDebugStr> inSet) override
+ {
+ SendMicrostepBegin();
+ RefToList(inSet, m_MicrostepData.m_EnterStates);
+ }
+
+ static inline bool FindInList(const TDebugStr &inStr, const TDebugStrList &inStrList)
+ {
+ if (eastl::find(inStrList.begin(), inStrList.end(), inStr) != inStrList.end())
+ return true;
+ return false;
+ }
+
+ static inline bool FindInList(const STransitionId &inStr, const TTransitionIdList &inStrList)
+ {
+ if (eastl::find(inStrList.begin(), inStrList.end(), inStr) != inStrList.end())
+ return true;
+ return false;
+ }
+
+ const SBreakpoint *FindHitBreakpoint()
+ {
+ // Now check for breakpoints.
+ for (QT3DSU32 breakIdx = 0, breakEnd = m_Breakpoints.size(); breakIdx < breakEnd; ++breakIdx) {
+ const SBreakpoint &theBreakpoint = m_Breakpoints[breakIdx];
+ switch (theBreakpoint.getType()) {
+ case BreakpointTypes::StateEnter:
+ if (FindInList(theBreakpoint.getData<SStateEnterBreakpoint>().m_ObjectId,
+ m_MicrostepData.m_EnterStates))
+ return &theBreakpoint;
+ case BreakpointTypes::StateExit:
+ if (FindInList(theBreakpoint.getData<SStateExitBreakpoint>().m_ObjectId,
+ m_MicrostepData.m_ExitStates))
+ return &theBreakpoint;
+ case BreakpointTypes::Transition:
+ if (FindInList(theBreakpoint.getData<STransitionId>(),
+ m_MicrostepData.m_Transitions))
+ return &theBreakpoint;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ return NULL;
+ }
+
+ // Log statements run through the debugger as well.
+ void EndMicroStep() override
+ {
+ DumpScriptState();
+ if (m_MicrostepBeginSent) {
+ if (m_MicrostepData.m_Transitions.empty() == false)
+ Serialize(m_MicrostepData);
+
+ Serialize(SEndMicrostep());
+ const SBreakpoint *theHitBreakpoint = FindHitBreakpoint();
+ if (theHitBreakpoint)
+ OnBreakpointHit(*theHitBreakpoint);
+ else if (m_BreakOnMicrostep)
+ Break();
+ }
+ }
+
+ void EndStep() override { m_StepSent = false; }
+
+ void SetBreakOnMicrostep(bool inEnableStep) override { m_BreakOnMicrostep = inEnableStep; }
+
+ virtual void Break()
+ {
+ if (!m_Blocking) {
+ // We may get disconnected *while* we are breaking.
+ // We need to ensure we don't get nuked while we are breaking.
+ NVScopedRefCounted<SListener> tempVar(this);
+ m_Blocking = true;
+ while (m_Blocking) {
+ SDebugStreamMessage msg = m_OutStream->WaitForNextMessage();
+ // Some out streams will have a reference to the debugger and some will not.
+ // If they do, then we do not have to hand our string to the debugger, we can assume
+ // the underlying implementation will have done that. If not, then we need to
+ // pass the message to the debugger.
+ if (m_Blocking && msg.m_Data.size())
+ m_Debugger.OnMessageReceived(msg);
+
+ if (!m_OutStream->Connected()) {
+ m_Blocking = false;
+ m_Debugger.DisconnectFromServer();
+ }
+ }
+ }
+ }
+
+ void Continue() override { m_Blocking = false; }
+
+ void OnExternalBreak() override { DumpScriptState(); }
+
+ // IScriptStateListener
+ void SetKey(void *inTable, const TDebugStr &inStr, const SDatamodelValue &inValue) override
+ {
+ SDatamodelTable *theTable((SDatamodelTable *)inTable);
+ SModifyTableValues &theModification =
+ m_TableModifications.insert(eastl::make_pair(theTable, SModifyTableValues(theTable)))
+ .first->second;
+ theModification.m_Modifications.push_back(
+ STableModification(STableEntry(inStr, inValue), TableModificationType::SetKey));
+ }
+
+ void RemoveKey(void *inTable, const TDebugStr &inStr) override
+ {
+ SDatamodelTable *theTable((SDatamodelTable *)inTable);
+ SModifyTableValues &theModification =
+ m_TableModifications.insert(eastl::make_pair(theTable, SModifyTableValues(theTable)))
+ .first->second;
+ theModification.m_Modifications.push_back(
+ STableModification(STableEntry(inStr), TableModificationType::RemoveKey));
+ }
+};
+}
+
+IStateMachineListener &IStateMachineListener::Create(NVAllocatorCallback &inAlloc, QT3DSU32 inStreamId,
+ IDebugOutStream &inOutStr, QT3DSU64 inStartTime,
+ IDebugger &inDebugger,
+ IScriptContext &inScriptContext)
+{
+ return *QT3DS_NEW(inAlloc, SListener)(inAlloc, inStreamId, inOutStr, inStartTime, inDebugger,
+ inScriptContext);
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebuggerProtocol.h b/src/Runtime/Source/UICState/Debugger/UICStateDebuggerProtocol.h
new file mode 100644
index 00000000..95552cc6
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebuggerProtocol.h
@@ -0,0 +1,925 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_DEBUGGER_PROTOCOL_H
+#define UIC_STATE_DEBUGGER_PROTOCOL_H
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerValues.h"
+#include "foundation/StringConversion.h"
+#include "foundation/StringConversionImpl.h"
+#include "foundation/Qt3DSTime.h"
+
+// Stream protocol, regardless of binary vs. text.
+namespace uic {
+namespace state {
+ namespace debugger {
+
+ struct SInitialization
+ {
+ QT3DSI32 m_Version;
+ QT3DSI32 m_Padding;
+ CounterFrequencyToTensOfNanos m_TimerFrequency;
+ static QT3DSI32 GetCurrentVersion() { return 1; }
+ SInitialization()
+ : m_Version(GetCurrentVersion())
+ , m_Padding(0)
+ , m_TimerFrequency(Time::sCounterFreq)
+ {
+ }
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visit(m_Version);
+ inVisitor.visit(m_TimerFrequency.mNumerator);
+ inVisitor.visit(m_TimerFrequency.mDenominator);
+ }
+ bool operator==(const SInitialization &inOther) const
+ {
+ return m_Version == inOther.m_Version
+ && m_TimerFrequency.mNumerator == inOther.m_TimerFrequency.mNumerator
+ && m_TimerFrequency.mDenominator == inOther.m_TimerFrequency.mDenominator;
+ }
+ };
+
+ // Listener interface. For on connect, we send the current timestamp for that state
+ // machine.
+ struct SConnect
+ {
+ TDebugStr m_Filename;
+ TDebugStr m_SCXMLData; // scxml file contents
+ TDebugStrList m_Configuration;
+ SConnect() {}
+ SConnect(const TDebugStr &fn, const TDebugStr &xmlData, const TDebugStrList &config)
+ : m_Filename(fn)
+ , m_SCXMLData(xmlData)
+ , m_Configuration(config)
+ {
+ }
+
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.randomText(m_Filename);
+ inVisitor.randomText(m_SCXMLData);
+ inVisitor.visitIdList(m_Configuration);
+ }
+ bool operator==(const SConnect &inOther) const
+ {
+ return m_Filename == inOther.m_Filename && m_SCXMLData == inOther.m_SCXMLData
+ && m_Configuration == inOther.m_Configuration;
+ }
+ };
+
+ struct SBreakpointHit
+ {
+ SBreakpoint m_Breakpoint;
+ SBreakpointHit() {}
+ SBreakpointHit(const SBreakpoint &bp)
+ : m_Breakpoint(bp)
+ {
+ }
+
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visit(m_Breakpoint);
+ }
+ bool operator==(const SBreakpointHit &inOther) const
+ {
+ return m_Breakpoint == inOther.m_Breakpoint;
+ }
+ };
+
+ struct SDebugLog
+ {
+ TDebugStr m_Message;
+ SDebugLog() {}
+ SDebugLog(const TDebugStr &msg)
+ : m_Message(msg)
+ {
+ }
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.randomText(m_Message);
+ }
+ bool operator==(const SDebugLog &inOther) const
+ {
+ return m_Message == inOther.m_Message;
+ }
+ };
+
+ struct SModifyTableValues
+ {
+ SDatamodelTable *m_TablePtr;
+ TTableModificationList m_Modifications;
+
+ SModifyTableValues(SDatamodelTable *inTable = NULL,
+ const TTableModificationList &inList = TTableModificationList())
+ : m_TablePtr(inTable)
+ , m_Modifications(inList)
+ {
+ }
+
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visit(m_TablePtr);
+ inVisitor.visit(m_Modifications);
+ }
+
+ bool operator==(const SModifyTableValues &inOther) const
+ {
+ return m_TablePtr == inOther.m_TablePtr
+ && m_Modifications == inOther.m_Modifications;
+ }
+ };
+
+ struct SBeginStep
+ {
+ SBeginStep() {}
+ template <typename TVisitor>
+ void Visit(TVisitor &)
+ {
+ }
+
+ bool operator==(const SBeginStep &) const { return true; }
+ };
+
+ struct SBeginMicrostep
+ {
+ SBeginMicrostep() {}
+ template <typename TVisitor>
+ void Visit(TVisitor &)
+ {
+ }
+
+ bool operator==(const SBeginMicrostep &) const { return true; }
+ };
+
+ struct SMicrostepEvent
+ {
+ TDebugStr m_Event;
+ bool m_Internal;
+
+ SMicrostepEvent(const TDebugStr &inEvent = TDebugStr(), bool inIsInternal = false)
+ : m_Event(inEvent)
+ , m_Internal(inIsInternal)
+ {
+ }
+
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visitId(m_Event);
+ inVisitor.visit(m_Internal);
+ }
+
+ bool operator==(const SMicrostepEvent &inOther) const
+ {
+ return m_Event == inOther.m_Event && m_Internal == inOther.m_Internal;
+ }
+ };
+
+ struct SMicrostepData
+ {
+ TTransitionIdList m_Transitions;
+ TDebugStrList m_ExitStates;
+ TDebugStrList m_EnterStates;
+
+ SMicrostepData() {}
+ SMicrostepData(const TTransitionIdList &inTransitions,
+ const TDebugStrList &inExitStates, const TDebugStrList &inEnterStates)
+ : m_Transitions(inTransitions)
+ , m_ExitStates(inExitStates)
+ , m_EnterStates(inEnterStates)
+ {
+ }
+
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ // Eventless transitions cause us to need to always write the string length.
+ inVisitor.visit(m_Transitions);
+ inVisitor.visitIdList(m_ExitStates);
+ inVisitor.visitIdList(m_EnterStates);
+ }
+ bool operator==(const SMicrostepData &inOther) const
+ {
+ return m_Transitions == inOther.m_Transitions
+ && m_ExitStates == inOther.m_ExitStates
+ && m_EnterStates == inOther.m_EnterStates;
+ }
+ };
+
+ struct SEndMicrostep
+ {
+ SEndMicrostep() {}
+ template <typename TVisitor>
+ void Visit(TVisitor & /*inVisitor*/)
+ {
+ }
+
+ bool operator==(const SEndMicrostep &) const { return true; }
+ };
+
+ struct SEventQueued
+ {
+ TDebugStr m_Event;
+ bool m_Internal;
+ SEventQueued()
+ : m_Internal(false)
+ {
+ }
+ SEventQueued(const TDebugStr &evt, bool intern)
+ : m_Event(evt)
+ , m_Internal(intern)
+ {
+ }
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visitEventName(m_Event);
+ inVisitor.visit(m_Internal);
+ }
+ bool operator==(const SEventQueued &inOther) const
+ {
+ return m_Event == inOther.m_Event && m_Internal == inOther.m_Internal;
+ }
+ };
+
+ // Debug interface
+
+ struct SSetBreakpoint
+ {
+ SBreakpoint m_Breakpoint;
+ SSetBreakpoint() {}
+ SSetBreakpoint(const SBreakpoint &bp)
+ : m_Breakpoint(bp)
+ {
+ }
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visit(m_Breakpoint);
+ }
+ bool operator==(const SSetBreakpoint &inOther) const
+ {
+ return m_Breakpoint == inOther.m_Breakpoint;
+ }
+ };
+
+ struct SClearBreakpoint
+ {
+ SBreakpoint m_Breakpoint;
+ SClearBreakpoint() {}
+ SClearBreakpoint(const SBreakpoint &bp)
+ : m_Breakpoint(bp)
+ {
+ }
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visit(m_Breakpoint);
+ }
+ bool operator==(const SClearBreakpoint &inOther) const
+ {
+ return m_Breakpoint == inOther.m_Breakpoint;
+ }
+ };
+
+ struct SClearAllBreakpoints
+ {
+ SClearAllBreakpoints() {}
+ template <typename TVisitor>
+ void Visit(TVisitor & /*inVisitor*/)
+ {
+ }
+ bool operator==(const SClearAllBreakpoints & /*inOther*/) const { return true; }
+ };
+
+ struct SBreakOnMicrostep
+ {
+ bool m_Value;
+ SBreakOnMicrostep(bool val = false)
+ : m_Value(val)
+ {
+ }
+ template <typename TVisitor>
+ void Visit(TVisitor &inVisitor)
+ {
+ inVisitor.visit(m_Value);
+ }
+ bool operator==(const SBreakOnMicrostep &inOther) const
+ {
+ return m_Value == inOther.m_Value;
+ }
+ };
+
+ struct SContinue
+ {
+ SContinue() {}
+ template <typename TVisitor>
+ void Visit(TVisitor & /*inVisitor*/)
+ {
+ }
+ bool operator==(const SContinue & /*inOther*/) const { return true; }
+ };
+
+ struct SDisconnect
+ {
+ SDisconnect() {}
+ template <typename TVisitor>
+ void Visit(TVisitor & /*inVisitor*/)
+ {
+ }
+ bool operator==(const SDisconnect & /*inOther*/) const { return true; }
+ };
+
+ // Visitors to handle the breakpoint subtypes.
+ // The empty top visitor will force a compile error if there is a breakpoint type we don't
+ // recognize.
+ template <typename TDataType>
+ struct SBreakpointSerializationVisitor
+ {
+ };
+
+ template <>
+ struct SBreakpointSerializationVisitor<SStateEnterBreakpoint>
+ {
+ enum { Type = BreakpointTypes::StateEnter };
+ template <typename TVisitor>
+ static void Visit(TVisitor &inVisitor, SStateEnterBreakpoint &inBp)
+ {
+ inVisitor.visitId(inBp.m_ObjectId);
+ }
+ };
+
+ template <>
+ struct SBreakpointSerializationVisitor<SStateExitBreakpoint>
+ {
+ enum { Type = BreakpointTypes::StateExit };
+ template <typename TVisitor>
+ static void Visit(TVisitor &inVisitor, SStateExitBreakpoint &inBp)
+ {
+ inVisitor.visitId(inBp.m_ObjectId);
+ }
+ };
+
+ template <>
+ struct SBreakpointSerializationVisitor<STransitionId>
+ {
+ enum { Type = BreakpointTypes::Transition };
+ template <typename TVisitor>
+ static void Visit(TVisitor &inVisitor, STransitionId &inBp)
+ {
+ inVisitor.visitId(inBp.m_StateId);
+ inVisitor.visit(inBp.m_TransitionIndex);
+ }
+ };
+
+#define ITERATE_BREAKPOINT_TYPES \
+ HANDLE_BREAKPOINT_TYPE(StateEnter, SStateEnterBreakpoint) \
+ HANDLE_BREAKPOINT_TYPE(StateExit, SStateExitBreakpoint) \
+ HANDLE_BREAKPOINT_TYPE(Transition, STransitionId)
+
+#define ITERATE_DEBUG_MESSAGE_TYPES \
+ HANDLE_DEBUG_MESSAGE_TYPE(Initialization) \
+ HANDLE_DEBUG_MESSAGE_TYPE(Connect) \
+ HANDLE_DEBUG_MESSAGE_TYPE(BreakpointHit) \
+ HANDLE_DEBUG_MESSAGE_TYPE(DebugLog) \
+ HANDLE_DEBUG_MESSAGE_TYPE(ModifyTableValues) \
+ HANDLE_DEBUG_MESSAGE_TYPE(BeginStep) \
+ HANDLE_DEBUG_MESSAGE_TYPE(BeginMicrostep) \
+ HANDLE_DEBUG_MESSAGE_TYPE(MicrostepEvent) \
+ HANDLE_DEBUG_MESSAGE_TYPE(MicrostepData) \
+ HANDLE_DEBUG_MESSAGE_TYPE(EndMicrostep) \
+ HANDLE_DEBUG_MESSAGE_TYPE(EventQueued) \
+ HANDLE_DEBUG_MESSAGE_TYPE(SetBreakpoint) \
+ HANDLE_DEBUG_MESSAGE_TYPE(ClearBreakpoint) \
+ HANDLE_DEBUG_MESSAGE_TYPE(ClearAllBreakpoints) \
+ HANDLE_DEBUG_MESSAGE_TYPE(Disconnect) \
+ HANDLE_DEBUG_MESSAGE_TYPE(BreakOnMicrostep) \
+ HANDLE_DEBUG_MESSAGE_TYPE(Continue)
+
+ template <typename TStructType>
+ struct STypeToName
+ {
+ };
+
+#define HANDLE_BREAKPOINT_TYPE(enumType, structType) \
+ template <> \
+ struct STypeToName<structType> \
+ { \
+ static const char8_t *GetName() { return #enumType; } \
+ };
+#define HANDLE_DEBUG_MESSAGE_TYPE(msgType) \
+ template <> \
+ struct STypeToName<S##msgType> \
+ { \
+ static const char8_t *GetName() { return #msgType; } \
+ };
+
+ ITERATE_BREAKPOINT_TYPES
+ ITERATE_DEBUG_MESSAGE_TYPES
+
+#undef HANDLE_BREAKPOINT_TYPE
+#undef HANDLE_DEBUG_MESSAGE_TYPE
+
+ template <typename TMessageHandler>
+ struct SMessageParser
+ {
+ TDebugStr m_MessageHeaderStr;
+ TDebugStr m_TimestampStr;
+ TDebugStr m_ParseStr;
+ TDebugStr m_BreakpointTypeStr;
+ TDebugStr m_TempStr[4];
+ TMessageHandler *m_CurrentHandler;
+ bool m_Valid;
+ static void Trim(TDebugStr &inStr)
+ {
+ if (inStr.empty())
+ return;
+ eastl::string::size_type nonSpace = inStr.find_first_not_of(' ');
+ eastl::string::size_type lastNonSpace = inStr.find_last_not_of(' ');
+ if (nonSpace == TDebugStr::npos || lastNonSpace == TDebugStr::npos) {
+ inStr.clear();
+ return;
+ }
+
+ eastl::string::size_type msgLen = lastNonSpace - nonSpace;
+ inStr.erase(inStr.begin(), inStr.begin() + nonSpace);
+ inStr.resize(msgLen + 1);
+ }
+
+ void TrimForward(eastl::string::size_type startPos)
+ {
+ eastl::string::size_type nextPos = m_ParseStr.find_first_not_of(' ', startPos);
+ if (nextPos != TDebugStr::npos)
+ m_ParseStr.erase(m_ParseStr.begin(), m_ParseStr.begin() + nextPos);
+ else
+ m_ParseStr.clear();
+ }
+
+ void TrimForward()
+ {
+ eastl::string::size_type nextSpace = m_ParseStr.find_first_of(' ');
+ TrimForward(nextSpace);
+ }
+
+ void visitId(TDebugStr &inStr)
+ {
+ eastl::string::size_type nextSpace = m_ParseStr.find_first_of(' ');
+ if (nextSpace == TDebugStr::npos)
+ nextSpace = m_ParseStr.size();
+ inStr.assign(m_ParseStr.begin(), m_ParseStr.begin() + nextSpace);
+ TrimForward(nextSpace);
+ }
+ void visit(TDebugStr &inStr) { randomText(inStr); }
+ void visit(QT3DSI32 &inData)
+ {
+ StringConversion<QT3DSI32>().StrTo(m_ParseStr.c_str(), inData);
+ TrimForward();
+ }
+ void visit(QT3DSU32 &inData)
+ {
+ StringConversion<QT3DSU32>().StrTo(m_ParseStr.c_str(), inData);
+ TrimForward();
+ }
+
+ void visit(QT3DSU64 &inData)
+ {
+ StringConversion<QT3DSU64>().StrTo(m_ParseStr.c_str(), inData);
+ TrimForward();
+ }
+
+ void visit(float &inData)
+ {
+ StringConversion<QT3DSF32>().StrTo(m_ParseStr.c_str(), inData);
+ TrimForward();
+ }
+
+ void visit(bool &inData)
+ {
+ if (CompareNChars(m_ParseStr.c_str(), "True", 4) == 0)
+ inData = true;
+ else
+ inData = false;
+
+ TrimForward();
+ }
+
+ template <typename TPtrType>
+ void visitOpaquePtr(TPtrType *&inPtr)
+ {
+ QT3DSU64 temp;
+ visit(temp);
+ inPtr = reinterpret_cast<TPtrType *>(static_cast<size_t>(temp));
+ }
+
+ void visit(SDatamodelTable *&inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelUserData *&inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelFunction *&inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelCFunction *&inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelThread *&inData) { visitOpaquePtr(inData); }
+ void visit(SNil &) {}
+
+ void visit(SDatamodelValue &inValue)
+ {
+ visitId(m_TempStr[0]);
+#define HANDLE_DATAMODEL_VALUE_TYPE(name, dtype) \
+ if (AreEqual(m_TempStr[0].c_str(), #name)) { \
+ dtype theData; \
+ visit(theData); \
+ inValue = theData; \
+ } else
+ ITERATE_DATAMODEL_VALUE_TYPES
+#undef HANDLE_DATAMODEL_VALUE_TYPE
+ {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void visit(TTableModificationList &inModifications)
+ {
+ QT3DSU32 numMods = 0;
+ visit(numMods);
+ inModifications.resize(numMods);
+ for (QT3DSU32 idx = 0, end = inModifications.size(); idx < end; ++idx) {
+ STableModification &theModification(inModifications[idx]);
+ visitId(m_TempStr[0]);
+ if (AreEqual(m_TempStr[0].c_str(), "SetKey"))
+ theModification.m_Type = TableModificationType::SetKey;
+ else if (AreEqual(m_TempStr[0].c_str(), "RemoveKey"))
+ theModification.m_Type = TableModificationType::RemoveKey;
+ else {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ visit(theModification.m_Entry.m_Key);
+ if (theModification.m_Type == TableModificationType::SetKey)
+ visit(theModification.m_Entry.m_Value);
+ }
+ }
+
+ void visit(TTableEntryList &inEntryList)
+ {
+ QT3DSU32 numMods = 0;
+ visit(numMods);
+ inEntryList.resize(numMods);
+ for (QT3DSU32 idx = 0, end = inEntryList.size(); idx < end; ++idx) {
+ STableEntry &theEntry(inEntryList[idx]);
+ visit(theEntry.m_Key);
+ visit(theEntry.m_Value);
+ }
+ }
+
+ void randomText(TDebugStr &outStr)
+ {
+ QT3DSU32 strLen = 0;
+ visit(strLen);
+ outStr.assign(m_ParseStr.begin(), m_ParseStr.begin() + strLen);
+ TrimForward(strLen);
+ }
+
+ void visitIdList(TDebugStrList &inList)
+ {
+ QT3DSU32 numItems = 0;
+ visit(numItems);
+ inList.resize(numItems);
+ for (QT3DSU32 idx = 0, end = numItems; idx < end; ++idx)
+ visitId(inList[idx]);
+ }
+
+ void visit(TTransitionIdList &inList)
+ {
+ QT3DSU32 numItems = 0;
+ visit(numItems);
+ inList.resize(numItems);
+ for (QT3DSU32 idx = 0, end = numItems; idx < end; ++idx)
+ inList[idx] = BreakpointTransition();
+ }
+
+ void visitEventName(TDebugStr &outStr) { visitId(outStr); }
+
+ SStateEnterBreakpoint BreakpointStateEnter()
+ {
+ SStateEnterBreakpoint retval;
+ SBreakpointSerializationVisitor<SStateEnterBreakpoint>::Visit(*this, retval);
+ return retval;
+ }
+
+ SStateExitBreakpoint BreakpointStateExit()
+ {
+ SStateExitBreakpoint retval;
+ SBreakpointSerializationVisitor<SStateExitBreakpoint>::Visit(*this, retval);
+ return retval;
+ }
+
+ STransitionId BreakpointTransition()
+ {
+ STransitionId retval;
+ SBreakpointSerializationVisitor<STransitionId>::Visit(*this, retval);
+ return retval;
+ }
+
+ void visit(SBreakpoint &breakpoint)
+ {
+ visitId(m_BreakpointTypeStr);
+#define HANDLE_BREAKPOINT_TYPE(enumType, bpType) \
+ if (AreEqual(STypeToName<bpType>::GetName(), m_BreakpointTypeStr.c_str())) { \
+ breakpoint = Breakpoint##enumType(); \
+ } else
+ ITERATE_BREAKPOINT_TYPES
+#undef HANDLE_BREAKPOINT_TYPE
+ // else is defined in the iterate breakpoints.
+ {
+ m_Valid = false;
+ m_CurrentHandler->error("Unrecognized breakpoint type: ",
+ m_BreakpointTypeStr.c_str());
+ }
+ }
+
+ template <typename TDataType>
+ void DoParseT(TDebugStr &inStr, QT3DSU64 inTimestamp, QT3DSI32 streamId,
+ TMessageHandler &inHandler)
+ {
+ TDataType theType;
+ m_ParseStr = inStr;
+ m_Valid = true;
+ m_CurrentHandler = &inHandler;
+ theType.Visit(*this);
+ if (m_Valid)
+ inHandler.OnMessage(streamId, inTimestamp, theType);
+ }
+
+ // destructive parsing.
+ void Parse(NVConstDataRef<QT3DSU8> data, TMessageHandler &inHandler)
+ {
+ m_ParseStr.assign((const char *)data.begin(), (const char *)data.end());
+ Trim(m_ParseStr);
+ size_t spacePos = m_ParseStr.find_first_of(' ');
+ if (spacePos == TDebugStr::npos) {
+ m_ParseStr.assign((const char *)data.begin(), (const char *)data.end());
+ inHandler.error("Failed to parse message: ", m_ParseStr.c_str());
+ return;
+ }
+ qt3ds::QT3DSI32 streamId = 0;
+ visitId(m_MessageHeaderStr);
+ visit(streamId);
+ qt3ds::QT3DSU64 timestamp = 0;
+ visit(timestamp);
+#define HANDLE_DEBUG_MESSAGE_TYPE(name) \
+ if (AreEqual(STypeToName<S##name>::GetName(), m_MessageHeaderStr.c_str())) { \
+ DoParseT<S##name>(m_ParseStr, timestamp, streamId, inHandler); \
+ } else
+ ITERATE_DEBUG_MESSAGE_TYPES
+#undef HANDLE_DEBUG_MESSAGE_TYPE
+ {
+ inHandler.error("Failed to parse message type: ", m_MessageHeaderStr.c_str());
+ }
+ }
+ };
+
+ struct SMessageSerializer
+ {
+ TDebugStr m_Message;
+ void appendSpace() { m_Message.append(1, ' '); }
+
+ void visitId(const TDebugStr &inStr)
+ {
+ m_Message.append(inStr);
+ appendSpace();
+ }
+ template <typename TDataType>
+ void rawTypeToStr(const TDataType &inType)
+ {
+ char8_t buf[256] = { 0 };
+ StringConversion<TDataType>().ToStr(inType, toDataRef(buf, 256));
+ m_Message.append(buf);
+ appendSpace();
+ }
+ void visit(QT3DSI32 inData) { rawTypeToStr(inData); }
+ void visit(QT3DSU32 inData) { rawTypeToStr(inData); }
+
+ void visit(QT3DSU64 inData) { rawTypeToStr(inData); }
+
+ void visit(bool inData) { rawTypeToStr(inData); }
+
+ void visit(const TDebugStr &inStr) { randomText(inStr); }
+
+ void visit(const SNil &) {}
+
+ void visit(const TTransitionIdList &inData)
+ {
+ QT3DSU32 len = (QT3DSU32)inData.size();
+ visit(len);
+ for (QT3DSU32 idx = 0; idx < len; ++idx)
+ Breakpoint(inData[idx]);
+ }
+
+ void randomText(const TDebugStr &outStr)
+ {
+ QT3DSU32 len = (QT3DSU32)outStr.size();
+ visit(len);
+ if (len)
+ m_Message.append(outStr);
+ appendSpace();
+ }
+
+ void visitIdList(const TDebugStrList &inList)
+ {
+ QT3DSU32 numItems = (QT3DSU32)inList.size();
+ visit(numItems);
+ for (QT3DSU32 idx = 0; idx < numItems; ++idx)
+ visitId(inList[idx]);
+ }
+
+ void visitEventName(const TDebugStr &outStr) { visitId(outStr); }
+ void visit(float inValue) { rawTypeToStr(inValue); }
+ template <typename TPtrType>
+ void visitOpaquePtr(const TPtrType *inPtr)
+ {
+ size_t ptrValue = reinterpret_cast<size_t>(inPtr);
+ QT3DSU64 fullValue = static_cast<QT3DSU64>(ptrValue);
+ visit(fullValue);
+ }
+
+ void visit(SDatamodelTable *inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelUserData *inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelFunction *inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelCFunction *inData) { visitOpaquePtr(inData); }
+ void visit(SDatamodelThread *inData) { visitOpaquePtr(inData); }
+
+ void visit(const SDatamodelValue &inValue)
+ {
+ switch (inValue.getType()) {
+#define HANDLE_DATAMODEL_VALUE_TYPE(name, dtype) \
+ case DatamodelValueTypes::name: { \
+ m_Message.append(#name); \
+ appendSpace(); \
+ visit(inValue.getData<dtype>()); \
+ break; \
+ }
+ ITERATE_DATAMODEL_VALUE_TYPES
+#undef HANDLE_DATAMODEL_VALUE_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ void visit(const TTableModificationList &inModifications)
+ {
+ QT3DSU32 numItems = (QT3DSU32)inModifications.size();
+ visit(numItems);
+ for (QT3DSU32 idx = 0, end = inModifications.size(); idx < end; ++idx) {
+ const STableModification &theMod(inModifications[idx]);
+ switch (theMod.m_Type) {
+ case TableModificationType::SetKey: {
+ m_Message.append("SetKey");
+ appendSpace();
+ visit(theMod.m_Entry.m_Key);
+ visit(theMod.m_Entry.m_Value);
+ break;
+ }
+ case TableModificationType::RemoveKey: {
+ m_Message.append("RemoveKey");
+ appendSpace();
+ visit(theMod.m_Entry.m_Key);
+ break;
+ }
+ default:
+ QT3DS_ASSERT(false);
+ m_Message.append("badvalue");
+ appendSpace();
+ continue;
+ }
+ }
+ }
+ void visit(TTableEntryList &inEntries)
+ {
+ QT3DSU32 numItems = (QT3DSU32)inEntries.size();
+ visit(numItems);
+ for (QT3DSU32 idx = 0, end = inEntries.size(); idx < end; ++idx) {
+ const STableEntry &theEntry(inEntries[idx]);
+ visit(theEntry.m_Key);
+ visit(theEntry.m_Value);
+ }
+ }
+
+ template <typename TBreakpointType>
+ void Breakpoint(const TBreakpointType &inBp)
+ {
+ SBreakpointSerializationVisitor<TBreakpointType>::Visit(
+ *this, const_cast<TBreakpointType &>(inBp));
+ }
+
+ void visit(const SBreakpoint &inBp)
+ {
+ switch (inBp.getType()) {
+#define HANDLE_BREAKPOINT_TYPE(enumName, typeName) \
+ case BreakpointTypes::enumName: \
+ m_Message.append(STypeToName<typeName>::GetName()); \
+ appendSpace(); \
+ Breakpoint(inBp.getData<typeName>()); \
+ break;
+ ITERATE_BREAKPOINT_TYPES
+#undef HANDLE_BREAKPOINT_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ template <typename TMsgType>
+ void Serialize(QT3DSI32 inStreamId, const TMsgType &inMsg, QT3DSU64 inTimestamp)
+ {
+ m_Message.clear();
+ m_Message.append(STypeToName<TMsgType>::GetName());
+ appendSpace();
+ visit(inStreamId);
+ visit(inTimestamp);
+ const_cast<TMsgType &>(inMsg).Visit(*this);
+ }
+
+ NVConstDataRef<QT3DSU8> ToRawMessage()
+ {
+ if (m_Message.size() == 0)
+ return NVConstDataRef<QT3DSU8>();
+ return NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(m_Message.c_str()),
+ (QT3DSU32)m_Message.size());
+ }
+ };
+
+ template <typename TLhs, typename TRhs>
+ struct SMsgComparer
+ {
+ static bool Compare(const TLhs &, const TRhs &) { return false; }
+ };
+#define HANDLE_DEBUG_MESSAGE_TYPE(typeName) \
+ template <> \
+ struct SMsgComparer<S##typeName, S##typeName> \
+ { \
+ static bool Compare(const S##typeName &lhs, const S##typeName &rhs) { return lhs == rhs; } \
+ };
+ ITERATE_DEBUG_MESSAGE_TYPES;
+#undef HANDLE_DEBUG_MESSAGE_TYPE
+
+ template <typename TMessageType>
+ struct STestMessageHandler
+ {
+ bool m_Result;
+ QT3DSU64 m_Timestamp;
+ QT3DSU32 m_StreamId;
+ const TMessageType &m_ExpectedResult;
+
+ STestMessageHandler(QT3DSU32 sid, QT3DSU64 ts, const TMessageType &res)
+ : m_Result(false)
+ , m_Timestamp(ts)
+ , m_StreamId(sid)
+ , m_ExpectedResult(res)
+ {
+ }
+
+ template <typename TCrapType>
+ void OnMessage(QT3DSU32 sid, QT3DSU64 ts, const TCrapType &msgType)
+ {
+ if (ts == m_Timestamp && m_StreamId == sid)
+ m_Result =
+ SMsgComparer<TCrapType, TMessageType>::Compare(msgType, m_ExpectedResult);
+ }
+
+ void error(const char8_t *, const char8_t *) {}
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateDebuggerValues.h b/src/Runtime/Source/UICState/Debugger/UICStateDebuggerValues.h
new file mode 100644
index 00000000..65e25c5b
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateDebuggerValues.h
@@ -0,0 +1,540 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_DEBUGGER_VALUES_H
+#define UIC_STATE_DEBUGGER_VALUES_H
+#pragma once
+#include "UICStateDebugger.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+
+namespace uic {
+namespace state {
+ namespace debugger {
+ using namespace uic::state::editor;
+
+ // Force compile error if unsupported datatype requested
+ template <typename TDataType>
+ struct SDebugValueTypeMap
+ {
+ };
+
+ template <>
+ struct SDebugValueTypeMap<TDebugStr>
+ {
+ static DebugValueTypes::Enum GetType() { return DebugValueTypes::String; }
+ };
+ template <>
+ struct SDebugValueTypeMap<TDebugStrList>
+ {
+ static DebugValueTypes::Enum GetType() { return DebugValueTypes::StringList; }
+ };
+ template <>
+ struct SDebugValueTypeMap<TTransitionIdList>
+ {
+ static DebugValueTypes::Enum GetType() { return DebugValueTypes::TransitionIdList; }
+ };
+
+ struct SDebugValueUnionTraits
+ {
+ typedef DebugValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(TDebugStrList),
+ };
+
+ static TIdType getNoDataId() { return DebugValueTypes::NoDebugValue; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SDebugValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case DebugValueTypes::String:
+ return inVisitor(*NVUnionCast<TDebugStr *>(inData));
+ case DebugValueTypes::StringList:
+ return inVisitor(*NVUnionCast<TDebugStrList *>(inData));
+ case DebugValueTypes::TransitionIdList:
+ return inVisitor(*NVUnionCast<TTransitionIdList *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case DebugValueTypes::NoDebugValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case DebugValueTypes::String:
+ return inVisitor(*NVUnionCast<const TDebugStr *>(inData));
+ case DebugValueTypes::StringList:
+ return inVisitor(*NVUnionCast<const TDebugStrList *>(inData));
+ case DebugValueTypes::TransitionIdList:
+ return inVisitor(*NVUnionCast<const TTransitionIdList *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case DebugValueTypes::NoDebugValue:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SDebugValueUnionTraits,
+ SDebugValueUnionTraits::
+ TBufferSize>,
+ SDebugValueUnionTraits::TBufferSize>
+ TDebugValueUnionType;
+
+ struct SDebugValue : public TDebugValueUnionType
+ {
+ SDebugValue() {}
+
+ SDebugValue(const SDebugValue &inOther)
+ : TDebugValueUnionType(static_cast<const TDebugValueUnionType &>(inOther))
+ {
+ }
+
+ SDebugValue(const char8_t *inOther)
+ : TDebugValueUnionType(TDebugStr(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SDebugValue(const TDataType &inDt)
+ : TDebugValueUnionType(inDt)
+ {
+ }
+
+ SDebugValue &operator=(const SDebugValue &inOther)
+ {
+ TDebugValueUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SDebugValue &inOther) const
+ {
+ return TDebugValueUnionType::operator==(inOther);
+ }
+ bool operator!=(const SDebugValue &inOther) const
+ {
+ return TDebugValueUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == DebugValueTypes::NoDebugValue; }
+ };
+
+ struct SDebugValueOpt : public Option<SDebugValue>
+ {
+ SDebugValueOpt(const SDebugValueOpt &inOther)
+ : Option<SDebugValue>(inOther)
+ {
+ }
+ SDebugValueOpt(const Empty &)
+ : Option<SDebugValue>()
+ {
+ }
+ SDebugValueOpt() {}
+ template <typename TDataType>
+ SDebugValueOpt(const TDataType &inOther)
+ : Option<SDebugValue>(SDebugValue(inOther))
+ {
+ }
+ SDebugValueOpt &operator=(const SDebugValueOpt &inOther)
+ {
+ Option<SDebugValue>::operator=(inOther);
+ return *this;
+ }
+ };
+
+ // Breakpoint subtypes
+
+ struct SStateEnterBreakpoint
+ {
+ TDebugStr m_ObjectId;
+ SStateEnterBreakpoint(const TDebugStr &inObj = TDebugStr())
+ : m_ObjectId(inObj)
+ {
+ }
+ bool operator==(const SStateEnterBreakpoint &inOther) const
+ {
+ return m_ObjectId == inOther.m_ObjectId;
+ }
+ };
+
+ struct SStateExitBreakpoint
+ {
+ TDebugStr m_ObjectId;
+ SStateExitBreakpoint(const TDebugStr &inObj = TDebugStr())
+ : m_ObjectId(inObj)
+ {
+ }
+ bool operator==(const SStateExitBreakpoint &inOther) const
+ {
+ return m_ObjectId == inOther.m_ObjectId;
+ }
+ };
+
+ template <typename TDataType>
+ struct SBreakpointTypeMap
+ {
+ static BreakpointTypes::Enum GetType()
+ {
+ return BreakpointTypes::UnknownBreakpointType;
+ }
+ };
+
+ template <>
+ struct SBreakpointTypeMap<SStateEnterBreakpoint>
+ {
+ static BreakpointTypes::Enum GetType() { return BreakpointTypes::StateEnter; }
+ };
+ template <>
+ struct SBreakpointTypeMap<SStateExitBreakpoint>
+ {
+ static BreakpointTypes::Enum GetType() { return BreakpointTypes::StateExit; }
+ };
+ template <>
+ struct SBreakpointTypeMap<STransitionId>
+ {
+ static BreakpointTypes::Enum GetType() { return BreakpointTypes::Transition; }
+ };
+
+ struct SBreakpointUnionTraits
+ {
+ typedef BreakpointTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(STransitionId),
+ };
+
+ static TIdType getNoDataId() { return BreakpointTypes::UnknownBreakpointType; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SBreakpointTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case BreakpointTypes::StateEnter:
+ return inVisitor(*NVUnionCast<SStateEnterBreakpoint *>(inData));
+ case BreakpointTypes::StateExit:
+ return inVisitor(*NVUnionCast<SStateExitBreakpoint *>(inData));
+ case BreakpointTypes::Transition:
+ return inVisitor(*NVUnionCast<STransitionId *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case BreakpointTypes::UnknownBreakpointType:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case BreakpointTypes::StateEnter:
+ return inVisitor(*NVUnionCast<const SStateEnterBreakpoint *>(inData));
+ case BreakpointTypes::StateExit:
+ return inVisitor(*NVUnionCast<const SStateExitBreakpoint *>(inData));
+ case BreakpointTypes::Transition:
+ return inVisitor(*NVUnionCast<const STransitionId *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case BreakpointTypes::UnknownBreakpointType:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SBreakpointUnionTraits,
+ SBreakpointUnionTraits::
+ TBufferSize>,
+ SBreakpointUnionTraits::TBufferSize>
+ TBreakpointUnionType;
+
+ struct SBreakpoint : public TBreakpointUnionType
+ {
+ SBreakpoint() {}
+
+ SBreakpoint(const SBreakpoint &inOther)
+ : TBreakpointUnionType(static_cast<const TBreakpointUnionType &>(inOther))
+ {
+ }
+
+ SBreakpoint(const char8_t *inOther)
+ : TBreakpointUnionType(TEditorStr(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SBreakpoint(const TDataType &inDt)
+ : TBreakpointUnionType(inDt)
+ {
+ }
+
+ SBreakpoint &operator=(const SBreakpoint &inOther)
+ {
+ TBreakpointUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SBreakpoint &inOther) const
+ {
+ return TBreakpointUnionType::operator==(inOther);
+ }
+ bool operator!=(const SBreakpoint &inOther) const
+ {
+ return TBreakpointUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == SBreakpointUnionTraits::getNoDataId(); }
+ };
+
+ struct SNil
+ {
+ bool operator==(const SNil &) const { return true; }
+ };
+
+#define ITERATE_DATAMODEL_VALUE_TYPES \
+ HANDLE_DATAMODEL_VALUE_TYPE(Number, float) \
+ HANDLE_DATAMODEL_VALUE_TYPE(String, TDebugStr) \
+ HANDLE_DATAMODEL_VALUE_TYPE(Nil, SNil) \
+ HANDLE_DATAMODEL_VALUE_TYPE(Boolean, bool) \
+ HANDLE_DATAMODEL_VALUE_TYPE(Table, SDatamodelTable *) \
+ HANDLE_DATAMODEL_VALUE_TYPE(UserData, SDatamodelUserData *) \
+ HANDLE_DATAMODEL_VALUE_TYPE(Function, SDatamodelFunction *) \
+ HANDLE_DATAMODEL_VALUE_TYPE(CFunction, SDatamodelCFunction *) \
+ HANDLE_DATAMODEL_VALUE_TYPE(Thread, SDatamodelThread *)
+
+ template <typename TDataType>
+ struct SDatamodelValueTypeMap
+ {
+ };
+
+#define HANDLE_DATAMODEL_VALUE_TYPE(name, type) \
+ template <> \
+ struct SDatamodelValueTypeMap<type> \
+ { \
+ static DatamodelValueTypes::Enum GetType() { return DatamodelValueTypes::name; } \
+ };
+ ITERATE_DATAMODEL_VALUE_TYPES
+#undef HANDLE_DATAMODEL_VALUE_TYPE
+
+ struct SDatamodelValueUnionTraits
+ {
+ typedef DatamodelValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(TDebugStr),
+ };
+
+ static TIdType getNoDataId() { return DatamodelValueTypes::UnknownType; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SDatamodelValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+#define HANDLE_DATAMODEL_VALUE_TYPE(name, type) \
+ case DatamodelValueTypes::name: \
+ return inVisitor(*NVUnionCast<type *>(inData));
+ ITERATE_DATAMODEL_VALUE_TYPES
+#undef HANDLE_DATAMODEL_VALUE_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ case DatamodelValueTypes::UnknownType:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+#define HANDLE_DATAMODEL_VALUE_TYPE(name, type) \
+ case DatamodelValueTypes::name: \
+ return inVisitor(*NVUnionCast<const type *>(inData));
+ ITERATE_DATAMODEL_VALUE_TYPES
+#undef HANDLE_DATAMODEL_VALUE_TYPE
+ default:
+ QT3DS_ASSERT(false);
+ case DatamodelValueTypes::UnknownType:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SDatamodelValueUnionTraits,
+ SDatamodelValueUnionTraits::
+ TBufferSize>,
+ SDatamodelValueUnionTraits::TBufferSize>
+ TDatamodelValueUnionType;
+
+ struct SDatamodelValue : public TDatamodelValueUnionType
+ {
+ SDatamodelValue() {}
+
+ SDatamodelValue(const SDatamodelValue &inOther)
+ : TDatamodelValueUnionType(static_cast<const TDatamodelValueUnionType &>(inOther))
+ {
+ }
+
+ SDatamodelValue(const char8_t *inOther)
+ : TDatamodelValueUnionType(TDebugStr(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SDatamodelValue(const TDataType &inDt)
+ : TDatamodelValueUnionType(inDt)
+ {
+ }
+
+ SDatamodelValue &operator=(const SDatamodelValue &inOther)
+ {
+ TDatamodelValueUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SDatamodelValue &inOther) const
+ {
+ return TDatamodelValueUnionType::operator==(inOther);
+ }
+ bool operator!=(const SDatamodelValue &inOther) const
+ {
+ return TDatamodelValueUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == SDatamodelValueUnionTraits::getNoDataId(); }
+ };
+
+ struct STableEntry
+ {
+ TDebugStr m_Key;
+ SDatamodelValue m_Value;
+ STableEntry(const TDebugStr &inKey = TDebugStr(),
+ const SDatamodelValue &inValue = SDatamodelValue())
+ : m_Key(inKey)
+ , m_Value(inValue)
+ {
+ }
+
+ bool operator==(const STableEntry &inOther) const
+ {
+ return m_Key == inOther.m_Key && m_Value == inOther.m_Value;
+ }
+ };
+
+ struct TableModificationType
+ {
+ enum Enum {
+ UnknownModification = 0,
+ SetKey = 1,
+ RemoveKey = 2,
+ };
+ };
+
+ struct STableModification
+ {
+ STableEntry m_Entry;
+ TableModificationType::Enum m_Type;
+ STableModification(
+ const STableEntry &inEntry = STableEntry(),
+ TableModificationType::Enum inEnum = TableModificationType::UnknownModification)
+ : m_Entry(inEntry)
+ , m_Type(inEnum)
+ {
+ }
+ bool operator==(const STableModification &inMod) const
+ {
+ return inMod.m_Entry == m_Entry && inMod.m_Type == m_Type;
+ }
+ };
+
+ typedef eastl::vector<STableModification> TTableModificationList;
+ }
+}
+}
+
+#ifndef _INTEGRITYPLATFORM
+namespace qt3ds {
+namespace foundation {
+ template <>
+ struct DestructTraits<uic::state::debugger::SNil>
+ {
+ void destruct(uic::state::debugger::SNil &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::debugger::SDatamodelTable *>
+ {
+ void destruct(uic::state::debugger::SDatamodelTable *) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::debugger::SDatamodelUserData *>
+ {
+ void destruct(uic::state::debugger::SDatamodelUserData *) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::debugger::SDatamodelFunction *>
+ {
+ void destruct(uic::state::debugger::SDatamodelFunction *) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::debugger::SDatamodelCFunction *>
+ {
+ void destruct(uic::state::debugger::SDatamodelCFunction *) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::debugger::SDatamodelThread *>
+ {
+ void destruct(uic::state::debugger::SDatamodelThread *) {}
+ };
+}
+}
+#endif
+
+#endif
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateLuaTest.cpp b/src/Runtime/Source/UICState/Debugger/UICStateLuaTest.cpp
new file mode 100644
index 00000000..64983216
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateLuaTest.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICState.h"
+#include "UICStateTest.h"
+#include "UICStateTestCommon.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace uic::state::test;
+using namespace uic::state;
+
+namespace {
+
+enum EPathType { eLuaPath, eCPath };
+const char *const sm_PathType[] = { "path", "cpath" };
+const char *const sm_PathTypeExtension[] = {
+ "lua",
+#ifdef _WIN32
+ "dll",
+#else
+ "so"
+#endif
+};
+
+// stack exchange
+// inspired by
+// http://stackoverflow.com/questions/4125971/setting-the-global-lua-path-variable-from-c-c
+int appendLuaPath(lua_State *L, const char *path, EPathType inPathType)
+{
+ if (L == NULL)
+ return 0;
+ lua_getglobal(L, "package");
+ lua_getfield(L, -1, sm_PathType[inPathType]);
+ eastl::string cur_path = lua_tostring(L, -1); // grab path string from top of stack
+ cur_path.append(1, ';'); // add separator
+ cur_path.append(path); // add additional path
+ cur_path.append("/?.");
+ cur_path.append(sm_PathTypeExtension[inPathType]);
+ lua_pop(L, 1);
+ lua_pushstring(L, cur_path.c_str()); // set new patth
+ lua_setfield(L, -2, sm_PathType[inPathType]);
+ lua_pop(L, 1); // get rid of package table from top of stack
+ return 0; // all done!
+}
+
+int Output(lua_State *inState)
+{
+ lua_concat(inState, lua_gettop(inState));
+ const char *message = lua_tostring(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_logger");
+ IDataLogger *theLogger = (IDataLogger *)lua_touserdata(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_line");
+ int line = (int)lua_tonumber(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_file");
+ const char *file = lua_tostring(inState, -1);
+ if (theLogger) {
+ theLogger->Log(LogType::Info, file, line, message);
+ }
+ return 0;
+}
+
+// this function doesn't return
+int TestError(lua_State *inState)
+{
+ const char *message = lua_tostring(inState, -2);
+ int stackDepth = (int)lua_tonumber(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_logger");
+ IDataLogger *theLogger = (IDataLogger *)lua_touserdata(inState, -1);
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uic_test_file");
+ const char *file = lua_tostring(inState, -1);
+
+ lua_Debug ar;
+ lua_getstack(inState, stackDepth, &ar);
+ lua_getinfo(inState, "nSl", &ar);
+ int line = ar.currentline;
+ if (theLogger) {
+ theLogger->Log(LogType::Error, file, line, message);
+ }
+ // and pow; no return.
+ lua_error(inState);
+ return 0;
+}
+
+Option<STestResults> RunTest(const char8_t *inFullPath, const char8_t *inRootDir,
+ const char8_t *inLunityPath, IDataLogger &inLogger)
+{
+ CAllocator nvAlloc;
+ NVScopedRefCounted<NVFoundation> nvFoundation(
+ NVCreateFoundation(QT3DS_FOUNDATION_VERSION, nvAlloc));
+ SLuaContext theContext(*nvFoundation);
+
+ luaL_loadfile(theContext, inLunityPath);
+ int failure = lua_pcall(theContext, 0, 0, 0);
+ if (failure) {
+ inLogger.Log(LogType::Error, inLunityPath, 0, "Failed to load lunity test library");
+ return Option<STestResults>();
+ }
+
+ eastl::string relPath;
+ eastl::string fullPathStr(inFullPath);
+ eastl::string inProjectDir(inRootDir);
+ CFileTools::GetRelativeFromBase(inProjectDir, fullPathStr, relPath);
+ eastl::string scriptsDir(inRootDir);
+ scriptsDir.append("/scripts");
+ appendLuaPath(theContext, scriptsDir.c_str(), eLuaPath);
+ const char8_t *fname = relPath.c_str();
+
+ // setup the test output system.
+ lua_pushlightuserdata(theContext, &inLogger);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "uic_test_logger");
+ lua_pushstring(theContext, fname);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "uic_test_file");
+ lua_pushnumber(theContext, 0.f);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "uic_test_line");
+ lua_pushcfunction(theContext, Output);
+ lua_setfield(theContext, LUA_GLOBALSINDEX, "output");
+ lua_pushcfunction(theContext, Output);
+ // Really, we should have done this a long time ago, overridden print.
+ lua_setfield(theContext, LUA_GLOBALSINDEX, "print");
+
+ lua_pushcfunction(theContext, TestError);
+ lua_setfield(theContext, LUA_GLOBALSINDEX, "testError");
+
+ luaL_loadfile(theContext, inFullPath);
+ // function at top of stack
+
+ // push new global table
+ lua_newtable(theContext);
+ // create new metatable
+ lua_newtable(theContext);
+ lua_getfield(theContext, LUA_GLOBALSINDEX, "_G");
+ lua_setfield(theContext, -2, "__index");
+ // the metatable is at the top of the stack, with the new table underneath
+ lua_setmetatable(theContext, -2);
+
+ // dup the new table and put it in the test context
+ lua_pushvalue(theContext, -1);
+ lua_setfield(theContext, LUA_REGISTRYINDEX, "test_context");
+
+ // now we only have the global table on the stack with the function underneath.
+ QT3DS_ASSERT(lua_istable(theContext, -1));
+ QT3DS_ASSERT(lua_isfunction(theContext, -2));
+ lua_setfenv(theContext, -2);
+
+ failure = lua_pcall(theContext, 0, 0, 0);
+ eastl::string logStr;
+ if (failure) {
+ const char8_t *failureMessage = lua_tostring(theContext, -1);
+ logStr.assign("Failed to load test file: ");
+ logStr.append(failureMessage);
+ inLogger.Log(LogType::Error, fname, 0, logStr.c_str());
+ return Option<STestResults>();
+ }
+ /* - useful for debugging
+ QT3DS_ASSERT( lua_istable( theContext, -1 ) );
+ lua_pushnil( theContext );
+ while( lua_next( theContext, -2 ) != 0 )
+ {
+ const char* valVal = lua_tostring(theContext, -1);
+ lua_pushvalue( theContext, -2 );
+ const char* keyVal = lua_tostring( theContext, -1 );
+ lua_pop( theContext, 2 );
+
+ logStr.assign( "Global: " );
+ logStr.append( keyVal );
+ logStr.append( " -> " );
+ logStr.append( valVal );
+ inLogger.Log( LogType::Info, fname, 0, logStr.c_str() );
+ (void)valVal;
+ (void)keyVal;
+ }
+ lua_pop( theContext, 1 );
+ */
+ // Find the run all tests function
+ lua_getfield(theContext, LUA_GLOBALSINDEX, "__runAllTests");
+ QT3DS_ASSERT(lua_isfunction(theContext, -1));
+ lua_getfield(theContext, LUA_REGISTRYINDEX, "test_context");
+ failure = lua_pcall(theContext, 1, 3, 0);
+ if (failure) {
+ const char8_t *failureMessage = lua_tostring(theContext, -1);
+ logStr.assign("Failed to run unit tests: ");
+ logStr.append(failureMessage);
+ inLogger.Log(LogType::Error, fname, 0, logStr.c_str());
+ return Option<STestResults>();
+ }
+ int numTests = (int)lua_tonumber(theContext, -3);
+ int testsPassed = (int)lua_tonumber(theContext, -2);
+ int assertsPassed = (int)lua_tonumber(theContext, -1);
+
+ (void)assertsPassed;
+
+ return STestResults((QT3DSU32)numTests, (QT3DSU32)testsPassed);
+}
+}
+
+Option<STestResults> ILuaTest::RunFile(const char8_t *inFullPath, const char8_t *inRootDir,
+ const char8_t *inLunityPath, IDataLogger &inLogger)
+{
+ return RunTest(inFullPath, inRootDir, inLunityPath, inLogger);
+}
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateTest.h b/src/Runtime/Source/UICState/Debugger/UICStateTest.h
new file mode 100644
index 00000000..8171ea4c
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateTest.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_TEST_H
+#define UIC_STATE_TEST_H
+#include "UICState.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+
+namespace uic {
+namespace state {
+ namespace test {
+
+ struct LogType
+ {
+ enum Enum {
+ Error = 0,
+ Info = 1,
+ };
+ };
+
+ struct STestResults
+ {
+ QT3DSU32 m_TotalTests;
+ QT3DSU32 m_PassingTests;
+ STestResults(QT3DSU32 totalTests = 0, QT3DSU32 testPassed = 0)
+ : m_TotalTests(totalTests)
+ , m_PassingTests(testPassed)
+ {
+ }
+ STestResults &operator+=(const STestResults &inOther)
+ {
+ m_TotalTests += inOther.m_TotalTests;
+ m_PassingTests += inOther.m_PassingTests;
+ return *this;
+ }
+
+ bool Failed() const { return m_TotalTests != m_PassingTests; }
+ bool Passed() const { return !Failed(); }
+ };
+
+ class IDataLogger
+ {
+ protected:
+ virtual ~IDataLogger() {}
+ public:
+ virtual void Log(LogType::Enum inLogType, const char8_t *file, int line,
+ const char8_t *message) = 0;
+ };
+
+ // Run a data test returning a true/false result for pass/fail.
+ class IDataTest
+ {
+ public:
+ static Option<STestResults> RunFile(const char8_t *fname, const char8_t *inRootDir,
+ IDataLogger &inLogger);
+ };
+
+ class ILuaTest
+ {
+ public:
+ static Option<STestResults> RunFile(const char8_t *fname, const char8_t *inRootDir,
+ const char8_t *inLunityPath, IDataLogger &inLogger);
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Debugger/UICStateTestCommon.h b/src/Runtime/Source/UICState/Debugger/UICStateTestCommon.h
new file mode 100644
index 00000000..37ab7591
--- /dev/null
+++ b/src/Runtime/Source/UICState/Debugger/UICStateTestCommon.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_TEST_COMMON_H
+#define UIC_STATE_TEST_COMMON_H
+#include "UICState.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSMath.h"
+#include "foundation/FileTools.h"
+#include "UICStateTest.h"
+#include "EASTL/string.h"
+#include "foundation/TrackingAllocator.h"
+
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+namespace uic {
+namespace state {
+ namespace test {
+
+ struct SLuaContext
+ {
+ NVFoundationBase &m_Foundation;
+ lua_State *m_LuaState;
+
+ SLuaContext(NVFoundationBase &fnd)
+ : m_Foundation(fnd)
+ {
+ m_LuaState = lua_newstate(LuaAlloc, this);
+ luaL_openlibs(m_LuaState);
+ }
+
+ static void *LuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
+ {
+ SLuaContext *ctx = reinterpret_cast<SLuaContext *>(ud);
+ if (nsize == 0) {
+ if (ptr)
+ ctx->m_Foundation.getAllocator().deallocate(ptr);
+ return NULL;
+ } else {
+ if (nsize < osize && ptr)
+ return ptr;
+
+ void *newMem = ctx->m_Foundation.getAllocator().allocate(nsize, "lua memory",
+ __FILE__, __LINE__);
+ if (osize && ptr) {
+ size_t copyAmt = qt3ds::NVMin(osize, nsize);
+ qt3ds::intrinsics::memCopy(newMem, ptr, (QT3DSU32)copyAmt);
+ ctx->m_Foundation.getAllocator().deallocate(ptr);
+ }
+ return newMem;
+ }
+ }
+
+ ~SLuaContext() { Close(); }
+
+ void Close()
+ {
+ if (m_LuaState)
+ lua_close(m_LuaState);
+ m_LuaState = NULL;
+ }
+
+ operator lua_State *() { return m_LuaState; }
+ };
+ }
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICState/Editor/UICLuaArchitectDebugger.cpp b/src/Runtime/Source/UICState/Editor/UICLuaArchitectDebugger.cpp
new file mode 100644
index 00000000..502178da
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICLuaArchitectDebugger.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICLuaDebugger.h"
+#include "UICStateEditorFoundation.h"
+#include "UICLuaDebuggerProtocol.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICLuaDebuggerImpl.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/ErrorStream.h"
+#include "foundation/StringTable.h"
+
+using namespace qt3ds::foundation;
+using namespace uic::state::debugger;
+using namespace uic::state::debugger::lua;
+using namespace qt3ds;
+
+namespace {
+
+struct IDebugClientOwner : public ILuaArchitectDataCacheListener
+{
+protected:
+ virtual ~IDebugClientOwner() {}
+public:
+ virtual Option<SAllBreakpoints> WaitForAllBreakpoints(QT3DSU64 inClientId) = 0;
+};
+struct SDebugClient : public ILuaArchitectDebugClient,
+ public ILuaProcessInfo,
+ public ILuaArchitectDataCacheListener
+{
+ NVFoundationBase &m_Foundation;
+ IStringTable &m_StringTable;
+ QT3DSU64 m_ClientId;
+ SLuaDebuggerProtocolWriter m_ProtocolWriter;
+ IDebugClientOwner &m_Owner;
+ lua::TBreakpointList m_BreakpointList;
+ NVScopedRefCounted<ILuaArchitectDataCache> m_DataCache;
+ eastl::vector<STempStackInfo> m_LastStackTrace;
+ eastl::vector<SLuaStackInfo> m_OutgoingStackTrace;
+ bool m_IsPaused;
+
+ QT3DSI32 mRefCount;
+
+ SDebugClient(NVFoundationBase &fnd, IStringTable &strTable, QT3DSU64 cid, IDebugOutStream &stream,
+ IDebugClientOwner &outerListener)
+ : m_Foundation(fnd)
+ , m_StringTable(strTable)
+ , m_ClientId(cid)
+ , m_ProtocolWriter(stream, fnd.getAllocator())
+ , m_Owner(outerListener)
+ , m_IsPaused(true) // The client starts paused.
+ , mRefCount(0)
+ {
+ m_DataCache =
+ ILuaArchitectDataCache::Create(m_Foundation, m_StringTable, stream, *this, m_ClientId);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator());
+
+ template <typename TMsgType>
+ void WriteMessage(const TMsgType &msg)
+ {
+ m_ProtocolWriter.WriteMessage(ToClientId(), const_cast<TMsgType &>(msg));
+ }
+
+ QT3DSU64 ToClientId() const { return m_ClientId; }
+
+ virtual void SetBreakpoint(const char *relativePath, int line, const char *inCondition)
+ {
+ SSetBreakpoint theMessage(SLuaBreakpoint(m_StringTable.RegisterStr(relativePath), line,
+ m_StringTable.RegisterStr(nonNull(inCondition))));
+ WriteMessage(theMessage);
+ }
+
+ virtual NVConstDataRef<SLuaBreakpoint> GetBreakpoints()
+ {
+ SRequestAllBreakpoints theMessage;
+ WriteMessage(theMessage);
+ Option<SAllBreakpoints> retval = m_Owner.WaitForAllBreakpoints(ToClientId());
+ m_BreakpointList.clear();
+ if (retval.hasValue())
+ m_BreakpointList = retval->m_Breakpoints;
+ return toConstDataRef(m_BreakpointList.data(), m_BreakpointList.size());
+ }
+
+ virtual void ClearBreakpoint(const char *relativePath, int line)
+ {
+ SClearBreakpoint msg(SLuaBreakpoint(m_StringTable.RegisterStr(relativePath), line));
+ WriteMessage(msg);
+ }
+
+ virtual void ClearAllBreakpoints() { WriteMessage(SClearAllBreakpoints()); }
+
+ // Process info
+ // limit ignored for now
+ virtual NVConstDataRef<SLuaStackInfo> StackTrace(QT3DSI32)
+ {
+ m_OutgoingStackTrace.assign(m_LastStackTrace.begin(), m_LastStackTrace.end());
+ return toConstDataRef(m_OutgoingStackTrace.data(), (QT3DSU32)m_OutgoingStackTrace.size());
+ }
+
+ virtual uic::state::debugger::SFunctionInfo GetFunctionInfo(SDatamodelFunction &inFunction)
+ {
+ return m_DataCache->GetFunctionInfo(inFunction);
+ }
+ virtual NVConstDataRef<STableEntry> GetTableValues(SDatamodelTable &inTable)
+ {
+ return m_DataCache->GetTableValues(inTable);
+ }
+
+ virtual void RequestBreak() { WriteMessage(SRequestBreak()); }
+
+ virtual bool IsPaused() { return m_IsPaused; }
+
+ virtual ILuaProcessInfo *GetProcessInfo()
+ {
+ if (m_IsPaused)
+ return this;
+ return NULL;
+ }
+
+ virtual void Continue()
+ {
+ WriteMessage(SContinue());
+ m_IsPaused = false;
+ }
+
+ virtual void StepInto() { WriteMessage(SStepInto()); }
+
+ virtual void StepOver() { WriteMessage(SStepOver()); }
+
+ virtual void StepOut() { WriteMessage(SStepOut()); }
+
+ virtual void AddWatch(const char *inExpression)
+ {
+ WriteMessage(SAddWatch(m_StringTable.RegisterStr(inExpression)));
+ }
+
+ virtual void RemoveWatch(const char *inExpression)
+ {
+ WriteMessage(SRemoveWatch(m_StringTable.RegisterStr(inExpression)));
+ }
+
+ virtual void ExecuteStatement(const char *inExpression)
+ {
+ WriteMessage(SExecuteStatement(m_StringTable.RegisterStr(inExpression)));
+ }
+
+ virtual void HandleMessage(lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader &header)
+ {
+ if (header.m_ClientId == ToClientId() && m_DataCache->IsCacheMessage(header)) {
+ m_DataCache->HandleCacheMessage(reader, header);
+ } else {
+ m_Owner.HandleMessage(reader, header);
+ }
+ }
+};
+
+static MallocAllocator g_MallocAlloc;
+
+struct SDebugServer : public ILuaArchitectDebugServer,
+ public IDebugStreamListener,
+ public IDebugClientOwner
+{
+ typedef eastl::hash_map<QT3DSU64, NVScopedRefCounted<SDebugClient>> TIdClientHash;
+
+ SErrorStream m_Errors;
+ CAllocator m_Allocator;
+ NVScopedRefCounted<NVFoundation> m_Foundation;
+ NVScopedRefCounted<IStringTable> m_StrTable;
+ TIdClientHash m_Clients;
+ NVScopedRefCounted<ILuaArchitectDebugClientListener> m_Listener;
+ NVScopedRefCounted<IDebugOutStream> m_OutStream;
+ QT3DSI32 mRefCount;
+
+ SDebugServer(IDebugOutStream &stream)
+ : m_Allocator(m_Errors)
+ , m_Foundation(NVCreateFoundation(QT3DS_FOUNDATION_VERSION, m_Allocator, m_Errors))
+ , m_StrTable(IStringTable::CreateStringTable(m_Foundation->getAllocator()))
+ , m_OutStream(stream)
+ , mRefCount(0)
+ {
+ m_OutStream->SetListener(this);
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_MallocAlloc);
+
+ virtual void SetListener(ILuaArchitectDebugClientListener &inListener)
+ {
+ m_Listener = &inListener;
+ for (TIdClientHash::iterator iter = m_Clients.begin(), end = m_Clients.end(); iter != end;
+ ++iter) {
+ m_Listener->OnConnect(*iter->second);
+ }
+ }
+
+ SDebugClient *FindClient(QT3DSU64 id)
+ {
+ TIdClientHash::iterator iter = m_Clients.find(id);
+ if (iter != m_Clients.end())
+ return iter->second.mPtr;
+ return NULL;
+ }
+
+#define SERVER_IGNORE_MESSAGE(msgname) \
+ void Handle##msgname(QT3DSU64, const lua::S##msgname &) { QT3DS_ASSERT(false); }
+ SERVER_IGNORE_MESSAGE(SetBreakpoint);
+ SERVER_IGNORE_MESSAGE(RequestAllBreakpoints);
+ SERVER_IGNORE_MESSAGE(RequestBreak);
+ SERVER_IGNORE_MESSAGE(ClearBreakpoint);
+ SERVER_IGNORE_MESSAGE(ClearAllBreakpoints);
+ SERVER_IGNORE_MESSAGE(Continue);
+ SERVER_IGNORE_MESSAGE(AllBreakpoints);
+ SERVER_IGNORE_MESSAGE(RequestStackTrace)
+ SERVER_IGNORE_MESSAGE(UpdateTable);
+ SERVER_IGNORE_MESSAGE(UpdateFunction);
+ SERVER_IGNORE_MESSAGE(StepInto);
+ SERVER_IGNORE_MESSAGE(StepOver);
+ SERVER_IGNORE_MESSAGE(StepOut);
+ SERVER_IGNORE_MESSAGE(AddWatch);
+ SERVER_IGNORE_MESSAGE(RemoveWatch);
+ SERVER_IGNORE_MESSAGE(ExecuteStatement);
+ SERVER_IGNORE_MESSAGE(RequestPointerValue);
+ SERVER_IGNORE_MESSAGE(UnknownPointerValue);
+ SERVER_IGNORE_MESSAGE(BeginCacheUpdate);
+ SERVER_IGNORE_MESSAGE(EndPointerRequest);
+
+ void HandleInitialization(QT3DSU64 clientId, const lua::SInitialization &)
+ {
+ SDebugClient *theClient = QT3DS_NEW(m_Foundation->getAllocator(), SDebugClient)(
+ *m_Foundation, *m_StrTable, clientId, *m_OutStream, *this);
+ m_Clients.insert(eastl::make_pair(clientId, theClient));
+ if (m_Listener)
+ m_Listener->OnConnect(*theClient);
+ }
+
+ void HandleOnBreak(QT3DSU64 clientId, const lua::SOnBreak &msg)
+ {
+ SDebugClient *client = FindClient(clientId);
+ if (client && m_Listener) {
+ client->m_IsPaused = true;
+ m_Listener->OnClientBreak(*client,
+ SLuaBreakpoint(msg.m_Position.m_File, msg.m_Position.m_Line));
+ }
+ }
+
+ void HandleStackTrace(QT3DSU64 clientId, const lua::SStackTrace &msg)
+ {
+ SDebugClient *client = FindClient(clientId);
+ if (client)
+ client->m_LastStackTrace.assign(msg.m_Data.m_Stack.begin(), msg.m_Data.m_Stack.end());
+ }
+
+ void HandleWatchUpdated(QT3DSU64 clientId, const lua::SWatchUpdated &msg)
+ {
+ SDebugClient *client = FindClient(clientId);
+ if (client && m_Listener) {
+ m_Listener->OnWatchUpdated(*client, msg.m_Data.m_Expression, msg.m_Data.m_Value);
+ }
+ }
+
+ void HandleStatementExecuted(QT3DSU64 clientId, const lua::SStatementExecuted &msg)
+ {
+ SDebugClient *client = FindClient(clientId);
+ if (client && m_Listener) {
+ m_Listener->OnStatementExecuted(*client, msg.m_Data.m_Expression, msg.m_Data.m_Error,
+ msg.m_Data.m_PrintStatements, msg.m_Data.m_Values);
+ }
+ }
+
+ void HandleNextMessage(SLuaDebuggerProtocolReader &inReader, SLuaDebugMessageHeader &inHeader)
+ {
+ SDebugClient *client = FindClient(inHeader.m_ClientId);
+ if (client && client->m_DataCache->IsCacheMessage(inHeader)) {
+ client->m_DataCache->HandleCacheMessage(inReader, inHeader);
+ } else {
+ switch (inHeader.m_MessageName) {
+#define UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE(msgname) \
+ case SProtocolMessageNames::msgname: \
+ Handle##msgname(inHeader.m_ClientId, inReader.ReadMessage<lua::S##msgname>()); \
+ break;
+ UIC_LUA_DEBUGGER_ITERATE_PROTOCOL_MESSAGES;
+#undef UIC_LUA_DEBUGGER_HANDLE_PROTOCOL_MESSAGE
+ }
+ }
+ }
+
+ virtual void OnMessageReceived(const SDebugStreamMessage &inMessage)
+ {
+ SLuaDebuggerProtocolReader theReader(inMessage.m_Data, *m_StrTable);
+ while (theReader.HasData()) {
+ SLuaDebugMessageHeader theHeader = theReader.ReadHeader();
+ HandleNextMessage(theReader, theHeader);
+ }
+ }
+
+ virtual Option<SAllBreakpoints> WaitForAllBreakpoints(QT3DSU64 inClientId)
+ {
+ while (m_OutStream->Connected()) {
+ SDebugStreamMessage theMessage = m_OutStream->WaitForNextMessage();
+ if (theMessage.m_Data.size() == 0)
+ return Option<SAllBreakpoints>();
+
+ SLuaDebuggerProtocolReader theReader(theMessage.m_Data, *m_StrTable);
+ while (theReader.HasData()) {
+ SLuaDebugMessageHeader theHeader = theReader.ReadHeader();
+ if (theHeader.m_MessageName == lua::SProtocolMessageNames::AllBreakpoints
+ && theHeader.m_ClientId == inClientId) {
+ return theReader.ReadMessage<lua::SAllBreakpoints>();
+ } else
+ HandleNextMessage(theReader, theHeader);
+ }
+ }
+ return Option<SAllBreakpoints>();
+ }
+
+ virtual void HandleMessage(lua::SLuaDebuggerProtocolReader &reader,
+ lua::SLuaDebugMessageHeader &header)
+ {
+ HandleNextMessage(reader, header);
+ }
+};
+}
+
+ILuaArchitectDebugServer &ILuaArchitectDebugServer::CreateLuaServer(IDebugOutStream &stream)
+{
+ return *QT3DS_NEW(g_MallocAlloc, SDebugServer)(stream);
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICSceneGraphArchitectDebugger.cpp b/src/Runtime/Source/UICState/Editor/UICSceneGraphArchitectDebugger.cpp
new file mode 100644
index 00000000..d752c9b1
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICSceneGraphArchitectDebugger.cpp
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICSceneGraphDebugger.h"
+#include "UICSceneGraphDebuggerValue.h"
+#include "UICSceneGraphDebuggerProtocol.h"
+#include "UICUIADatamodel.h"
+#include "UICStateEditorValue.h"
+#include "UICUIADatamodelValue.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSContainers.h"
+#include "UICKernelTypes.h"
+#include "UICHash.h" //we need to duplicate the hash attribute calls
+#include "EASTL/set.h"
+
+using namespace uic;
+using namespace uic::state;
+using namespace uic::app;
+using namespace uic::state::debugger;
+
+namespace {
+
+struct SAppElemVectorSet
+{
+ nvvector<SAppElement *> m_Elements;
+ eastl::hash_set<SAppElement *, eastl::hash<SAppElement *>, eastl::equal_to<SAppElement *>,
+ ForwardingAllocator>
+ m_Set;
+ SAppElemVectorSet(NVAllocatorCallback &alloc)
+ : m_Elements(alloc, "AppElemVectorSet")
+ , m_Set(ForwardingAllocator(alloc, "AppElemVectorSet"))
+ {
+ }
+
+ void insert(SAppElement *elem)
+ {
+ if (m_Set.insert(elem).second)
+ m_Elements.push_back(elem);
+ }
+
+ void clear()
+ {
+ m_Elements.clear();
+ m_Set.clear();
+ }
+ NVConstDataRef<SAppElement *> ToDataRef() { return m_Elements; }
+};
+
+struct SValueIndex
+{
+ QT3DSU32 m_ValueIndex;
+ QT3DSU32 m_Component;
+ SValueIndex(QT3DSU32 vi, QT3DSU32 component)
+ : m_ValueIndex(vi)
+ , m_Component(component)
+ {
+ }
+};
+
+struct SAppElementEntry
+{
+ Q3DStudio::TAttOrArgList m_AttList;
+ eastl::hash_map<QT3DSI32, SValueIndex> m_HashToIndexMap;
+ eastl::vector<app::SDatamodelValue> m_RuntimeValues;
+};
+
+struct SPresentationEntry
+{
+ CRegisteredString m_Id;
+ eastl::hash_map<CRegisteredString, SAppElement *> m_ElementMap;
+};
+
+Option<float> ValueToFloat(const SSGValue &val)
+{
+ if (val.getType() == SGPropertyValueTypes::Float)
+ return val.getData<float>();
+ return Empty();
+}
+
+Option<QT3DSI32> ValueToInteger(const SSGValue &val)
+{
+ if (val.getType() == SGPropertyValueTypes::I32)
+ return val.getData<QT3DSI32>();
+ return Empty();
+}
+
+Option<CRegisteredString> ValueToString(const SSGValue &val)
+{
+ if (val.getType() == SGPropertyValueTypes::String)
+ return val.getData<CRegisteredString>();
+ return Empty();
+}
+
+template <typename TDtype>
+struct SValueSetter
+{
+};
+
+template <>
+struct SValueSetter<float>
+{
+ static void SetValue(const SSGValue &incoming, float &outgoing, QT3DSU32 /*component*/)
+ {
+ Option<float> val = ValueToFloat(incoming);
+ if (val.hasValue())
+ outgoing = *val;
+ }
+};
+
+template <>
+struct SValueSetter<QT3DSVec2>
+{
+ static void SetValue(const SSGValue &incoming, QT3DSVec2 &outgoing, QT3DSU32 component)
+ {
+ Option<float> val = ValueToFloat(incoming);
+ if (val.hasValue()) {
+ switch (component) {
+ case 0:
+ outgoing.x = *val;
+ break;
+ case 1:
+ outgoing.y = *val;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+};
+
+template <>
+struct SValueSetter<QT3DSVec3>
+{
+ static void SetValue(const SSGValue &incoming, QT3DSVec3 &outgoing, QT3DSU32 component)
+ {
+ Option<float> val = ValueToFloat(incoming);
+ if (val.hasValue()) {
+ switch (component) {
+ case 0:
+ outgoing.x = *val;
+ break;
+ case 1:
+ outgoing.y = *val;
+ break;
+ case 2:
+ outgoing.z = *val;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ }
+};
+
+template <>
+struct SValueSetter<QT3DSI32>
+{
+ static void SetValue(const SSGValue &incoming, QT3DSI32 &outgoing, QT3DSU32 /*component*/)
+ {
+ Option<QT3DSI32> val = ValueToInteger(incoming);
+ if (val.hasValue())
+ outgoing = *val;
+ }
+};
+
+template <>
+struct SValueSetter<eastl::string>
+{
+ static void SetValue(const SSGValue &incoming, eastl::string &outgoing, QT3DSU32 /*component*/)
+ {
+ Option<CRegisteredString> val = ValueToString(incoming);
+ if (val.hasValue())
+ outgoing = eastl::string(val->c_str());
+ }
+};
+
+template <>
+struct SValueSetter<bool>
+{
+ static void SetValue(const SSGValue &incoming, bool &outgoing, QT3DSU32 /*component*/)
+ {
+ Option<QT3DSI32> val = ValueToInteger(incoming);
+ if (val.hasValue())
+ outgoing = (*val) != 0 ? true : false;
+ }
+};
+
+// Element ref. Not sure what to do about this right now
+template <>
+struct SValueSetter<SGuid>
+{
+ static void SetValue(const SSGValue & /*incoming*/, SGuid & /*outgoing*/, QT3DSU32 /*component*/)
+ {
+ }
+};
+
+template <>
+struct SValueSetter<CRegisteredString>
+{
+ static void SetValue(const SSGValue & /*incoming*/, CRegisteredString & /*outgoing*/,
+ QT3DSU32 /*component*/)
+ {
+ QT3DS_ASSERT(false);
+ }
+};
+
+template <>
+struct SValueSetter<SObjectRef>
+{
+ static void SetValue(const SSGValue & /*incoming*/, SObjectRef & /*outgoing*/,
+ QT3DSU32 /*component*/)
+ {
+ }
+};
+
+template <>
+struct SValueSetter<CStringOrInt>
+{
+ static void SetValue(const SSGValue & /*incoming*/, CStringOrInt & /*outgoing*/,
+ QT3DSU32 /*component*/)
+ {
+ }
+};
+
+struct SValueSetterVisitor
+{
+ const SSGValue &m_Incoming;
+ QT3DSU32 m_Component;
+ SValueSetterVisitor &operator=(const SValueSetterVisitor &);
+ SValueSetterVisitor(const SSGValue &i, QT3DSU32 c)
+ : m_Incoming(i)
+ , m_Component(c)
+ {
+ }
+ template <typename TDataType>
+ void operator()(TDataType &dt)
+ {
+ SValueSetter<TDataType>::SetValue(m_Incoming, dt, m_Component);
+ }
+ // object refs can generate this response.
+ void operator()() {}
+};
+
+void SetComponentValue(const SSGValue &incoming, app::SDatamodelValue &outgoing, QT3DSU32 component)
+{
+ SValueSetterVisitor visitor(incoming, component);
+ outgoing.visit<void>(visitor);
+}
+
+struct SArchitectDebuggerImpl : public ISceneGraphArchitectDebugger
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IDatamodel> m_Datamodel;
+ NVScopedRefCounted<IDebugOutStream> m_Stream;
+ ISceneGraphArchitectDebuggerListener *m_Listener;
+ nvhash_map<QT3DSU64, SAppElement *> m_ElemAppElemMap;
+ nvhash_map<SAppElement *, SAppElementEntry> m_RuntimeValues;
+ SAppElemVectorSet m_DirtySet;
+ eastl::vector<SPresentationEntry> m_Presentations;
+ bool m_Valid;
+ QT3DSI32 mRefCount;
+
+ SArchitectDebuggerImpl(IDatamodel &dm)
+ : m_Foundation(dm.GetFoundation())
+ , m_Datamodel(dm)
+ , m_Stream(NULL)
+ , m_Listener(NULL)
+ , m_ElemAppElemMap(dm.GetFoundation().getAllocator(), "ElemAppMap")
+ , m_RuntimeValues(dm.GetFoundation().getAllocator(), "RuntimeValues")
+ , m_DirtySet(dm.GetFoundation().getAllocator())
+ , m_Valid(true)
+ , mRefCount(0)
+ {
+ }
+
+ void addRef() { atomicIncrement(&mRefCount); }
+ void release()
+ {
+ // ensure the datamodel sticks around until after we are destroyed
+ NVScopedRefCounted<IDatamodel> dm(m_Datamodel);
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0) {
+ NVDelete(m_Foundation.getAllocator(), this);
+ }
+ }
+
+ virtual IDatamodel &GetDatamodel() { return *m_Datamodel; }
+
+ static QT3DSI32 GetHashValue(const char *name, const char *component, eastl::string &ioWorkspace)
+ {
+ ioWorkspace.assign(nonNull(name));
+ ioWorkspace.append(".");
+ ioWorkspace.append(component);
+ return Q3DStudio::CHash::HashAttribute(ioWorkspace.c_str());
+ }
+
+ void AppendAttribute(const char *name, const char *formalName, ERuntimeDataModelDataType dtype,
+ SAppElementEntry &theEntry)
+ {
+ SAttOrArg newValue;
+ newValue.m_Name = name;
+ newValue.m_FormalName = formalName;
+ newValue.m_DataType = dtype;
+ theEntry.m_AttList.push_back(newValue);
+ theEntry.m_RuntimeValues.push_back(uic::app::SDatamodelValue());
+ }
+
+ void LoadAppElement(SAppElement &elem, SPresentationEntry &entry)
+ {
+ entry.m_ElementMap.insert(eastl::make_pair(
+ m_Datamodel->GetStringTable().RegisterStr(m_Datamodel->GetElementId(elem).c_str()),
+ &elem));
+ SAppElementEntry &theEntry = m_RuntimeValues[&elem];
+ theEntry.m_AttList = m_Datamodel->GetElementAttributes(elem);
+ theEntry.m_RuntimeValues = m_Datamodel->GetElementAttributeInitialValues(elem);
+ AppendAttribute("active", "Active", ERuntimeDataModelDataTypeBool, theEntry);
+
+ if (m_Datamodel->IsComponent(elem)) {
+ AppendAttribute("slide", "(Slide)", ERuntimeDataModelDataTypeLong, theEntry);
+ AppendAttribute("time", "(Time)", ERuntimeDataModelDataTypeLong, theEntry);
+ AppendAttribute("paused", "(Mode)", ERuntimeDataModelDataTypeBool, theEntry);
+ }
+ eastl::string hashTemp;
+ for (QT3DSU32 idx = 0, end = (QT3DSU32)theEntry.m_AttList.size(); idx < end; ++idx) {
+ // Build out the component hash names.
+ const Q3DStudio::SAttOrArg &theProp(theEntry.m_AttList[idx]);
+ switch (theProp.m_DataType) {
+ // one component, one hash, just hash the name
+ default:
+ theEntry.m_HashToIndexMap.insert(
+ eastl::make_pair((QT3DSI32)Q3DStudio::CHash::HashAttribute(theProp.m_Name.c_str()),
+ SValueIndex(idx, 0)));
+ break;
+ case ERuntimeDataModelDataTypeFloat2: {
+ theEntry.m_HashToIndexMap.insert(eastl::make_pair(
+ GetHashValue(theProp.m_Name.c_str(), "x", hashTemp), SValueIndex(idx, 0)));
+ theEntry.m_HashToIndexMap.insert(eastl::make_pair(
+ GetHashValue(theProp.m_Name.c_str(), "y", hashTemp), SValueIndex(idx, 1)));
+ } break;
+ case ERuntimeDataModelDataTypeFloat3: {
+ const char *compNames[3] = { "x", "y", "z" };
+ if (theProp.m_MetaType == ERuntimeAdditionalMetaDataTypeColor) {
+ compNames[0] = "r";
+ compNames[1] = "g";
+ compNames[2] = "b";
+ }
+
+ theEntry.m_HashToIndexMap.insert(
+ eastl::make_pair(GetHashValue(theProp.m_Name.c_str(), compNames[0], hashTemp),
+ SValueIndex(idx, 0)));
+ theEntry.m_HashToIndexMap.insert(
+ eastl::make_pair(GetHashValue(theProp.m_Name.c_str(), compNames[1], hashTemp),
+ SValueIndex(idx, 1)));
+ theEntry.m_HashToIndexMap.insert(
+ eastl::make_pair(GetHashValue(theProp.m_Name.c_str(), compNames[2], hashTemp),
+ SValueIndex(idx, 2)));
+ } break;
+ }
+ // Set a value
+ if (theEntry.m_RuntimeValues[idx].getType() == ERuntimeDataModelDataTypeNone) {
+ switch (theProp.m_DataType) {
+ case ERuntimeDataModelDataTypeFloat:
+ theEntry.m_RuntimeValues[idx] = 0.0f;
+ break;
+ case ERuntimeDataModelDataTypeFloat2:
+ theEntry.m_RuntimeValues[idx] = QT3DSVec2(0, 0);
+ break;
+ case ERuntimeDataModelDataTypeFloat3:
+ theEntry.m_RuntimeValues[idx] = QT3DSVec3(0, 0, 0);
+ break;
+ case ERuntimeDataModelDataTypeLong:
+ theEntry.m_RuntimeValues[idx] = (QT3DSI32)0;
+ break;
+ case ERuntimeDataModelDataTypeString:
+ theEntry.m_RuntimeValues[idx] = eastl::string();
+ break;
+ case ERuntimeDataModelDataTypeBool:
+ theEntry.m_RuntimeValues[idx] = false;
+ break;
+ case ERuntimeDataModelDataTypeStringRef:
+ theEntry.m_RuntimeValues[idx] = eastl::string();
+ break;
+ // object references are stored as string values.
+ case ERuntimeDataModelDataTypeObjectRef:
+ theEntry.m_RuntimeValues[idx] = eastl::string();
+ break;
+ case ERuntimeDataModelDataTypeStringOrInt:
+ theEntry.m_RuntimeValues[idx] = eastl::string();
+ break;
+ }
+ }
+ }
+ eastl::vector<SAppElement *> children = m_Datamodel->GetElementChildren(elem);
+ for (size_t childIdx = 0, childEnd = children.size(); childIdx < childEnd; ++childIdx) {
+ LoadAppElement(*children[childIdx], entry);
+ }
+ }
+
+ void LoadDatamodel()
+ {
+ eastl::vector<app::SPresentation> presentations = m_Datamodel->GetPresentations();
+ m_Presentations.clear();
+ m_RuntimeValues.clear();
+ m_ElemAppElemMap.clear();
+ m_Presentations.resize(presentations.size());
+ for (size_t idx = 0, end = presentations.size(); idx < end; ++idx) {
+ app::SPresentation &incoming(presentations[idx]);
+ SPresentationEntry &pres = m_Presentations[idx];
+ pres.m_Id = m_Datamodel->GetStringTable().RegisterStr(incoming.m_Id.c_str());
+ if (incoming.m_Scene)
+ LoadAppElement(*incoming.m_Scene, pres);
+ }
+ }
+
+ SAppElementEntry *GetRuntimeValues(app::SAppElement &elem)
+ {
+ nvhash_map<SAppElement *, SAppElementEntry>::iterator iter = m_RuntimeValues.find(&elem);
+ if (iter != m_RuntimeValues.end())
+ return &iter->second;
+ return NULL;
+ }
+
+ SPresentationEntry *FindPresentation(CRegisteredString &str)
+ {
+ for (size_t idx = 0, end = m_Presentations.size(); idx < end; ++idx)
+ if (m_Presentations[idx].m_Id == str)
+ return &m_Presentations[idx];
+ return NULL;
+ }
+
+ /*External interface for clients*/
+
+ void SetListener(ISceneGraphArchitectDebuggerListener *listener) { m_Listener = listener; }
+
+ Q3DStudio::TAttOrArgList GetElementAttributes(app::SAppElement &elem)
+ {
+ SAppElementEntry *entry = GetRuntimeValues(elem);
+ if (entry)
+ return entry->m_AttList;
+ return Q3DStudio::TAttOrArgList();
+ }
+
+ eastl::vector<app::SDatamodelValue> GetElementAttributeValues(app::SAppElement &elem)
+ {
+ SAppElementEntry *entry = GetRuntimeValues(elem);
+ if (entry)
+ return entry->m_RuntimeValues;
+ return eastl::vector<app::SDatamodelValue>();
+ }
+
+ void OnMessageReceived(const SDebugStreamMessage &inMessage)
+ {
+ if (!m_Valid)
+ return;
+ SSGProtocolReader theReader(inMessage.m_Data, m_Datamodel->GetStringTable());
+ while (theReader.Finished() == false && m_Valid) {
+ SSGProtocolMessageTypes::Enum theMessageType = theReader.MessageType();
+ switch (theMessageType) {
+ case SSGProtocolMessageTypes::Initialization: {
+ QT3DSU32 version = theReader.ReadInitialization();
+ if (version > GetSceneGraphProtocolVersion()) {
+ QT3DS_ASSERT(false);
+ m_Foundation.error(QT3DS_INVALID_OPERATION,
+ "Invalid scene graph debugger protocol version");
+ m_Valid = false;
+ }
+ } break;
+ case SSGProtocolMessageTypes::IdUpdate: {
+ SIdUpdate theUpdate = theReader.ReadIdUpdate();
+ SPresentationEntry *theEntry = FindPresentation(theUpdate.m_PresentationId);
+ if (theEntry) {
+ for (size_t idx = 0, end = theUpdate.m_IdUpdates.size(); idx < end; ++idx) {
+ const SElemMap &elemMap(theUpdate.m_IdUpdates[idx]);
+ eastl::hash_map<CRegisteredString, SAppElement *>::iterator iter =
+ theEntry->m_ElementMap.find(elemMap.m_Id);
+ if (iter != theEntry->m_ElementMap.end())
+ m_ElemAppElemMap[elemMap.m_Elem] = iter->second;
+ else {
+ QT3DS_ASSERT(false);
+ m_Foundation.error(QT3DS_WARN, "Failed to map element");
+ }
+ }
+ }
+ } break;
+ case SSGProtocolMessageTypes::ElemUpdate: {
+ SElemUpdate theUpdate = theReader.ReadElemUpdate();
+ nvhash_map<QT3DSU64, SAppElement *>::iterator ptrToElem =
+ m_ElemAppElemMap.find(theUpdate.m_Elem);
+ if (ptrToElem != m_ElemAppElemMap.end()) {
+ nvhash_map<SAppElement *, SAppElementEntry>::iterator elemToEntry =
+ m_RuntimeValues.find(ptrToElem->second);
+ if (elemToEntry != m_RuntimeValues.end()) {
+ SAppElementEntry &theEntry(elemToEntry->second);
+ m_DirtySet.insert(elemToEntry->first);
+ for (size_t idx = 0, end = theUpdate.m_Updates.size(); idx < end; ++idx) {
+ const SValueUpdate &theValue(theUpdate.m_Updates[idx]);
+ eastl::hash_map<QT3DSI32, SValueIndex>::iterator hashIndex =
+ theEntry.m_HashToIndexMap.find(theValue.m_Hash);
+ if (hashIndex != theEntry.m_HashToIndexMap.end()) {
+ const SValueIndex theIdx = hashIndex->second;
+ SetComponentValue(theValue.m_Value,
+ theEntry.m_RuntimeValues[theIdx.m_ValueIndex],
+ theIdx.m_Component);
+ }
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ m_Foundation.error(QT3DS_WARN, "Failed to map element");
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ m_Foundation.error(QT3DS_WARN, "Failed to map element");
+ }
+ } break;
+ case SSGProtocolMessageTypes::Frame: {
+ NVConstDataRef<SAppElement *> dirtyItems = m_DirtySet.ToDataRef();
+ if (dirtyItems.size() && m_Listener) {
+ m_Listener->OnItemsDirty(dirtyItems);
+ m_DirtySet.clear();
+ }
+ } break;
+ }
+ } // end while
+ }
+
+ void AttachToStream(IDebugOutStream &inStream) { m_Stream = &inStream; }
+
+ void RefreshData(bool inNeedReloadData)
+ {
+ if (inNeedReloadData)
+ m_Datamodel->RefreshFile();
+ LoadDatamodel();
+ }
+};
+}
+
+ISceneGraphArchitectDebugger &
+ISceneGraphArchitectDebugger::Create(uic::app::IDatamodel &inDatamodel)
+{
+ SArchitectDebuggerImpl &retval =
+ *QT3DS_NEW(inDatamodel.GetFoundation().getAllocator(), SArchitectDebuggerImpl)(inDatamodel);
+ retval.LoadDatamodel();
+ return retval;
+}
diff --git a/src/Runtime/Source/UICState/Editor/UICStateDebuggerMaster.cpp b/src/Runtime/Source/UICState/Editor/UICStateDebuggerMaster.cpp
new file mode 100644
index 00000000..3706d194
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateDebuggerMaster.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerProtocol.h"
+#include "foundation/IOStreams.h"
+#include "foundation/Qt3DSAtomic.h"
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+namespace {
+MallocAllocator g_MallocAlloc;
+
+struct SDebugStrInStream : public IInStream
+{
+ size_t m_Pos;
+ const TDebugStr &m_Str;
+ SDebugStrInStream(const TDebugStr &inStr)
+ : m_Pos(0)
+ , m_Str(inStr)
+ {
+ }
+ virtual QT3DSU32 Read(NVDataRef<QT3DSU8> data)
+ {
+ size_t available = NVMin((size_t)data.size(), m_Str.size() - m_Pos);
+ if (available) {
+ memCopy(data.begin(), m_Str.data() + m_Pos, (QT3DSU32)available);
+ m_Pos += available;
+ }
+ return (QT3DSU32)available;
+ }
+};
+
+struct SDebuggerMaster : public IDebuggerMaster
+{
+ typedef eastl::hash_map<QT3DSI32, NVScopedRefCounted<IDebuggedInterpreter>> TIdInterpreterMap;
+
+ QT3DSI32 mRefCount;
+ NVScopedRefCounted<IDebugOutStream> m_OutStream;
+ TIdInterpreterMap m_Interpreters;
+ IDebuggerMasterListener &m_Listener;
+ SMessageSerializer m_Serializer;
+ SMessageParser<SDebuggerMaster> m_Parser;
+ TDebugStr m_LogStr;
+ TDebugStr m_MessageStr;
+ bool m_Invalid;
+
+ SDebuggerMaster(IDebugOutStream &inStream, IDebuggerMasterListener &listener)
+ : mRefCount(0)
+ , m_OutStream(inStream)
+ , m_Listener(listener)
+ , m_Invalid(false)
+ {
+ }
+
+ virtual ~SDebuggerMaster()
+ {
+ // Disconnect();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_MallocAlloc);
+
+ template <typename TMessageType>
+ void SendMessage(QT3DSI32 inStreamId, const TMessageType &inMessage)
+ {
+ m_Serializer.Serialize(inStreamId, inMessage, 0);
+ m_OutStream->Write(m_Serializer.ToRawMessage());
+ }
+
+ virtual void OnMessageReceived(const SDebugStreamMessage &inMessage)
+ {
+ if (m_Invalid)
+ return;
+ m_Parser.Parse(inMessage.m_Data, *this);
+ }
+
+ void ReleaseAllInterpreters()
+ {
+ for (TIdInterpreterMap::iterator iter = m_Interpreters.begin(), end = m_Interpreters.end();
+ iter != end; ++iter) {
+ iter->second->Disconnect();
+ m_Listener.OnInterpreterDisconnected(*iter->second.mPtr);
+ }
+ m_Interpreters.clear();
+ }
+
+ virtual void Disconnect()
+ {
+ SendMessage(-1, SDisconnect());
+ ReleaseAllInterpreters();
+ }
+
+ IDebuggedInterpreter *FindInterpreter(QT3DSI32 inStreamId)
+ {
+ TIdInterpreterMap::iterator iter = m_Interpreters.find(inStreamId);
+ if (iter != m_Interpreters.end())
+ return iter->second.mPtr;
+ return NULL;
+ }
+
+// Set of ignored messages
+#define IGNORE_DEBUG_MESSAGE_TYPE(tname) \
+ void OnMessage(QT3DSU32, QT3DSU64, const S##tname &) { QT3DS_ASSERT(false); }
+
+ // this are outgoing messages; we shouldn't be receiving them.
+ IGNORE_DEBUG_MESSAGE_TYPE(SetBreakpoint)
+ IGNORE_DEBUG_MESSAGE_TYPE(ClearBreakpoint)
+ IGNORE_DEBUG_MESSAGE_TYPE(BreakOnMicrostep)
+ IGNORE_DEBUG_MESSAGE_TYPE(ClearAllBreakpoints)
+ IGNORE_DEBUG_MESSAGE_TYPE(Continue)
+
+ void OnMessage(QT3DSU32 sid, QT3DSU64, const SConnect &inMessage)
+ {
+ SDebugStrInStream theStream(inMessage.m_SCXMLData);
+ TEditorPtr theEditor(IEditor::CreateEditor(inMessage.m_Filename.c_str(), theStream));
+ if (theEditor) {
+ IDebuggedInterpreter &theInterpreter = IDebuggedInterpreter::Create(
+ g_MallocAlloc, *m_OutStream.mPtr, theEditor, inMessage.m_Filename, sid,
+ toConstDataRef(inMessage.m_Configuration.data(),
+ (QT3DSU32)inMessage.m_Configuration.size()),
+ m_Listener);
+ m_Interpreters.insert(eastl::make_pair(sid, &theInterpreter));
+ m_Listener.OnInterpreterConnected(theInterpreter);
+ } else {
+ m_LogStr.assign("Connection failed: ");
+ m_LogStr.append(inMessage.m_Filename);
+ // log the failure somehow.
+ m_Listener.OnLog(NULL, m_LogStr);
+ }
+ }
+
+ void OnMessage(QT3DSU32 sid, QT3DSU64, const SBreakpointHit &inMessage)
+ {
+ IDebuggedInterpreter *interp = FindInterpreter(sid);
+ if (interp)
+ interp->BreakpointHit(inMessage.m_Breakpoint);
+ }
+
+ void OnMessage(QT3DSU32, QT3DSU64, const SInitialization &inMessage)
+ {
+ if (inMessage.m_Version != SInitialization::GetCurrentVersion()) {
+ QT3DS_ASSERT(false);
+ m_Invalid = true;
+ }
+ }
+
+ void OnMessage(QT3DSU32 sid, QT3DSU64, const SDebugLog &inMessage)
+ {
+ IDebuggedInterpreter *interp = FindInterpreter(sid);
+ m_Listener.OnLog(interp, inMessage.m_Message);
+ }
+
+#define FORWARD_INTERPRETER_EVENT(evnType, interpFun) \
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const evnType &inMsg) \
+ { \
+ IDebuggedInterpreter *interp = FindInterpreter(sid); \
+ if (interp) \
+ interp->interpFun(inMsg); \
+ }
+
+ FORWARD_INTERPRETER_EVENT(SEventQueued, OnEventQueued);
+ FORWARD_INTERPRETER_EVENT(SBeginStep, OnBeginStep);
+ FORWARD_INTERPRETER_EVENT(SBeginMicrostep, OnBeginMicrostep);
+ FORWARD_INTERPRETER_EVENT(SMicrostepEvent, OnMicrostepEvent);
+ FORWARD_INTERPRETER_EVENT(SMicrostepData, OnMicrostepData);
+ FORWARD_INTERPRETER_EVENT(SEndMicrostep, OnEndMicrostep);
+ FORWARD_INTERPRETER_EVENT(SModifyTableValues, OnModifyTable);
+
+ void OnMessage(QT3DSI32 sid, QT3DSU64, const SDisconnect &)
+ {
+ if (sid > 0) {
+ IDebuggedInterpreter *interp = FindInterpreter(sid);
+ if (interp) {
+ m_Listener.OnInterpreterDisconnected(*interp);
+ m_Interpreters.erase(sid);
+ }
+ } else {
+ ReleaseAllInterpreters();
+ }
+ }
+
+ void error(const char8_t *inPrefix, const char8_t *inSuffix)
+ {
+ m_LogStr.assign(nonNull(inPrefix));
+ m_LogStr.append(nonNull(inSuffix));
+ m_Listener.OnLog(NULL, m_LogStr);
+ }
+};
+}
+
+IDebuggerMaster &IDebuggerMaster::CreateMaster(IDebugOutStream &outStream,
+ IDebuggerMasterListener &inListener)
+{
+ return *QT3DS_NEW(g_MallocAlloc, SDebuggerMaster)(outStream, inListener);
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditor.cpp b/src/Runtime/Source/UICState/Editor/UICStateEditor.cpp
new file mode 100644
index 00000000..b8ffecbc
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditor.cpp
@@ -0,0 +1,1880 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICState.h"
+#include "UICStateEditorEditorsImpl.h"
+#include "UICStateExecutionContext.h"
+#include "EASTL/sort.h"
+
+using namespace uic::state;
+using namespace uic::state::editor;
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+#pragma warning(disable : 4355)
+
+ SEditorImpl::SEditorImpl(TFoundationPtr inFoundation,
+ NVScopedRefCounted<IStringTable> inStringTable)
+ : m_EditorFoundation(inFoundation)
+ , m_StringTable(inStringTable)
+ , m_AutoAllocator(m_EditorFoundation->getFoundation())
+ , m_StateContext(IStateContext::Create(m_EditorFoundation->getFoundation()))
+ , m_Editors(m_EditorFoundation->getAllocator(), "SEditorImpl::m_Editors")
+ , mRefCount(0)
+ , m_TransactionManager(
+ QT3DS_NEW(inFoundation->getAllocator(), STransactionManagerImpl)(inFoundation))
+ , m_Accessors(m_EditorFoundation->getAllocator(), "SEditorImpl::m_Accessors")
+ , m_CopyPasteListener(NULL)
+ {
+ }
+
+ void SEditorImpl::addRef() { atomicIncrement(&mRefCount); }
+
+ void SEditorImpl::release()
+ {
+ QT3DSI32 count = atomicDecrement(&mRefCount);
+ if (count <= 0) {
+ TFoundationPtr theFoundation(m_EditorFoundation);
+ NVDelete(theFoundation->getAllocator(), this);
+ }
+ }
+
+ TObjPtr SEditorImpl::InsertEditor(void *inData, IEditorObject *inEditor)
+ {
+ if (inEditor) {
+ bool insertResult = m_Editors.insert(eastl::make_pair(inData, inEditor)).second;
+ QT3DS_ASSERT(insertResult);
+ (void)insertResult;
+ }
+ return inEditor;
+ }
+
+ template <typename TStateType>
+ TObjPtr SEditorImpl::ToEditor(TStateType &inItem)
+ {
+ TStateEditorMap::iterator iter = m_Editors.find(&inItem);
+ if (iter != m_Editors.end())
+ return iter->second;
+
+ TObjPtr retval = SStateEditorMap<TStateType>::CreateEditor(inItem, *this, m_Accessors);
+ if (retval)
+ InsertEditor(&inItem, retval.mPtr);
+ return retval;
+ }
+
+ template <typename TStateType>
+ TObjPtr SEditorImpl::ToEditor(TStateType *inItem)
+ {
+ if (inItem == NULL)
+ return TObjPtr();
+
+ return ToEditor(*inItem);
+ }
+
+ TObjPtr SEditorImpl::ToEditor(SStateNode &inItem)
+ {
+ switch (inItem.m_Type) {
+ case StateNodeTypes::State:
+ return ToEditor(static_cast<SState &>(inItem));
+ case StateNodeTypes::Parallel:
+ return ToEditor(static_cast<SParallel &>(inItem));
+ case StateNodeTypes::Transition:
+ return ToEditor(static_cast<STransition &>(inItem));
+ case StateNodeTypes::Final:
+ return ToEditor(static_cast<SFinal &>(inItem));
+ case StateNodeTypes::SCXML:
+ return ToEditor(static_cast<SSCXML &>(inItem));
+ case StateNodeTypes::History:
+ return ToEditor(static_cast<SHistory &>(inItem));
+ default:
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ }
+
+ TObjPtr SEditorImpl::ExecutableContentToEditor(SExecutableContent &inItem)
+ {
+ TStateEditorMap::iterator iter = m_Editors.find(&inItem);
+ if (iter != m_Editors.end())
+ return iter->second;
+
+ switch (inItem.m_Type) {
+ case ExecutableContentTypes::Send:
+ return ToEditor(static_cast<SSend &>(inItem));
+ case ExecutableContentTypes::Raise:
+ return ToEditor(static_cast<SRaise &>(inItem));
+ case ExecutableContentTypes::Log:
+ return ToEditor(static_cast<SLog &>(inItem));
+ case ExecutableContentTypes::Assign:
+ return ToEditor(static_cast<SAssign &>(inItem));
+ case ExecutableContentTypes::If:
+ return ToEditor(static_cast<SIf &>(inItem));
+ case ExecutableContentTypes::ElseIf:
+ return ToEditor(static_cast<SElseIf &>(inItem));
+ case ExecutableContentTypes::Else:
+ return ToEditor(static_cast<SElse &>(inItem));
+ case ExecutableContentTypes::Script:
+ return ToEditor(static_cast<SScript &>(inItem));
+ case ExecutableContentTypes::Cancel:
+ return ToEditor(static_cast<SCancel &>(inItem));
+ default:
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ }
+
+ template <typename TStateType>
+ TStateType *SEditorImpl::FromEditor(TObjPtr inPtr)
+ {
+ if (inPtr.mPtr == NULL)
+ return NULL;
+ const char8_t *typeName = inPtr->TypeName();
+ typedef typename SStateEditorMap<TStateType>::TEditorType TProspectiveType;
+ if (AreEqual(typeName, TProspectiveType::GetTypeStr())) {
+ return reinterpret_cast<TStateType *>(
+ &static_cast<TProspectiveType *>(inPtr.mPtr)->m_Data);
+ }
+ return NULL;
+ }
+
+ SStateNode *SEditorImpl::StateNodeFromEditor(TObjPtr inPtr)
+ {
+ if (inPtr.mPtr == NULL)
+ return NULL;
+ const char8_t *typeName = inPtr->TypeName();
+ if (AreEqual(typeName, SSCXMLEditor::GetTypeStr()))
+ return FromEditor<SSCXML>(inPtr);
+ if (AreEqual(typeName, SStateEditor::GetTypeStr()))
+ return FromEditor<SState>(inPtr);
+ if (AreEqual(typeName, STransitionEditor::GetTypeStr()))
+ return FromEditor<STransition>(inPtr);
+ if (AreEqual(typeName, SParallelEditor::GetTypeStr()))
+ return FromEditor<SParallel>(inPtr);
+ if (AreEqual(typeName, SFinalEditor::GetTypeStr()))
+ return FromEditor<SFinal>(inPtr);
+ if (AreEqual(typeName, SHistoryEditor::GetTypeStr()))
+ return FromEditor<SHistory>(inPtr);
+ return NULL;
+ }
+
+ SExecutableContent *SEditorImpl::ExecutableContentFromEditor(TObjPtr inPtr)
+ {
+ if (inPtr.mPtr == NULL)
+ return NULL;
+ const char8_t *typeName = inPtr->TypeName();
+ if (AreEqual(typeName, SSendEditor::GetTypeStr())) {
+ return FromEditor<SSend>(inPtr);
+ }
+ if (AreEqual(typeName, SRaiseEditor::GetTypeStr())) {
+ return FromEditor<SRaise>(inPtr);
+ }
+ if (AreEqual(typeName, SLogEditor::GetTypeStr())) {
+ return FromEditor<SLog>(inPtr);
+ }
+ if (AreEqual(typeName, SAssignEditor::GetTypeStr())) {
+ return FromEditor<SAssign>(inPtr);
+ }
+ if (AreEqual(typeName, SIfEditor::GetTypeStr())) {
+ return FromEditor<SIf>(inPtr);
+ }
+ if (AreEqual(typeName, SElseIfEditor::GetTypeStr())) {
+ return FromEditor<SElseIf>(inPtr);
+ }
+ if (AreEqual(typeName, SElseEditor::GetTypeStr())) {
+ return FromEditor<SElse>(inPtr);
+ }
+ if (AreEqual(typeName, SScriptEditor::GetTypeStr())) {
+ return FromEditor<SScript>(inPtr);
+ }
+ if (AreEqual(typeName, SCancelEditor::GetTypeStr())) {
+ return FromEditor<SCancel>(inPtr);
+ }
+
+ return NULL;
+ }
+
+ void SEditorImpl::GenerateUniqueId(SStateNode &inNode, const char8_t *inStem)
+ {
+ QT3DS_ASSERT(inNode.m_Id.IsValid() == false);
+ CXMLIO::GenerateUniqueId(inNode, inStem, *m_StateContext, *m_StringTable);
+ }
+
+ void SEditorImpl::GenerateUniqueId(SSend &inNode, const char8_t *inStem)
+ {
+ CXMLIO::GenerateUniqueId(inNode, inStem, *m_StateContext, *m_StringTable);
+ }
+
+ TObjPtr SEditorImpl::GetRoot() { return ToEditor(m_StateContext->GetRoot()); }
+
+ template <typename TStateType>
+ eastl::pair<TStateType *, TObjPtr> SEditorImpl::CreateEditorAndObject()
+ {
+ typedef typename SStateEditorMap<TStateType>::TEditorType TEditorType;
+ TObjPtr newEditor = SStateEditorMap<TStateType>::CreateEditor(*this, m_Accessors);
+ TStateType *theState = &static_cast<TEditorType *>(newEditor.mPtr)->m_Data;
+ eastl::pair<TStateType *, TObjPtr> retval = eastl::make_pair(theState, newEditor);
+ InsertEditor(retval.first, retval.second.mPtr);
+ return retval;
+ }
+
+ TObjPtr SEditorImpl::DoCreate(const char8_t *inTypeName, const char8_t *inId)
+ {
+ if (AreEqual(inTypeName, SSCXMLEditor::GetTypeStr())) {
+ QT3DS_ASSERT(m_StateContext->GetRoot() == NULL);
+ eastl::pair<SSCXML *, TObjPtr> theNewEditor = CreateEditorAndObject<SSCXML>();
+ GenerateUniqueId(*theNewEditor.first, inId == NULL ? "scxml" : inId);
+ m_StateContext->SetRoot(*theNewEditor.first);
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, SStateEditor::GetTypeStr())) {
+ eastl::pair<SState *, TObjPtr> theNewEditor = CreateEditorAndObject<SState>();
+ GenerateUniqueId(*theNewEditor.first, inId == NULL ? "state" : inId);
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, SParallelEditor::GetTypeStr())) {
+ eastl::pair<SParallel *, TObjPtr> theNewEditor = CreateEditorAndObject<SParallel>();
+ GenerateUniqueId(*theNewEditor.first, inId == NULL ? "parallel" : inId);
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, SFinalEditor::GetTypeStr())) {
+ eastl::pair<SFinal *, TObjPtr> theNewEditor = CreateEditorAndObject<SFinal>();
+ GenerateUniqueId(*theNewEditor.first, inId == NULL ? "final" : inId);
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, SHistoryEditor::GetTypeStr())) {
+ eastl::pair<SHistory *, TObjPtr> theNewEditor = CreateEditorAndObject<SHistory>();
+ GenerateUniqueId(*theNewEditor.first, inId == NULL ? "history" : inId);
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, STransitionEditor::GetTypeStr())) {
+ eastl::pair<STransition *, TObjPtr> theNewEditor =
+ CreateEditorAndObject<STransition>();
+ GenerateUniqueId(*theNewEditor.first, inId == NULL ? "transition" : inId);
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, SDataModelEditor::GetTypeStr())) {
+ eastl::pair<SDataModel *, TObjPtr> theNewEditor =
+ CreateEditorAndObject<SDataModel>();
+ return theNewEditor.second;
+ } else if (AreEqual(inTypeName, SDataEditor::GetTypeStr())) {
+ eastl::pair<SData *, TObjPtr> theNewEditor = CreateEditorAndObject<SData>();
+ return theNewEditor.second;
+ }
+
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ TObjPtr SEditorImpl::Create(const char8_t *inTypeName, const char8_t *inId)
+ {
+ TObjPtr retval = DoCreate(inTypeName, inId);
+ m_TransactionManager->OnObjectCreated(retval);
+ return retval;
+ }
+
+ TObjPtr SEditorImpl::GetOrCreate(SSCXML &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(SState &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(STransition &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(SParallel &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(SFinal &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(SHistory &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(SDataModel &inData) { return ToEditor(inData); }
+ TObjPtr SEditorImpl::GetOrCreate(SData &inData) { return ToEditor(inData); }
+
+ TObjPtr SEditorImpl::GetObjectById(const char8_t *inId)
+ {
+ if (isTrivial(inId))
+ return TObjPtr();
+ SStateNode *theNode = m_StateContext->FindStateNode(RegisterStr(inId));
+ if (theNode)
+ return ToEditor(*theNode);
+ return TObjPtr();
+ }
+
+ TObjPtr SEditorImpl::GetEditor(void *inGraphData)
+ {
+ TStateEditorMap::iterator iter = m_Editors.find(inGraphData);
+ if (iter != m_Editors.end())
+ return iter->second;
+ return TObjPtr();
+ }
+
+ TSignalConnectionPtr SEditorImpl::AddChangeListener(IEditorChangeListener &inListener)
+ {
+ return m_TransactionManager->AddChangeListener(inListener);
+ }
+
+ TTransactionPtr SEditorImpl::BeginTransaction(const TEditorStr &inName)
+ {
+ return m_TransactionManager->BeginTransaction(inName);
+ }
+
+ TTransactionPtr SEditorImpl::GetOpenTransaction()
+ {
+ return m_TransactionManager->GetOpenTransaction();
+ }
+
+ void SEditorImpl::RollbackTransaction() { m_TransactionManager->RollbackTransaction(); }
+
+ void SEditorImpl::EndTransaction() { m_TransactionManager->EndTransaction(); }
+
+ TEditorStr SEditorImpl::Copy(TObjList inObjects, const QT3DSVec2 &inMousePos)
+ {
+ eastl::vector<SStateNode *> theNodeList;
+ for (size_t idx = 0, end = inObjects.size(); idx < end; ++idx) {
+ SStateNode *theNode = StateNodeFromEditor(inObjects[idx]);
+ if (theNode && theNode->m_Type != StateNodeTypes::Transition
+ && theNode->m_Type != StateNodeTypes::SCXML) {
+ theNodeList.push_back(theNode);
+ }
+ }
+ eastl::vector<SNamespacePair> theNamespaces;
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_EditorFoundation->getAllocator(), m_StringTable));
+ NVScopedRefCounted<IDOMWriter> theWriter(
+ IDOMWriter::CreateDOMWriter(m_EditorFoundation->getAllocator(), "scxml_fragment",
+ m_StringTable)
+ .first);
+
+ eastl::vector<SStateNode *> rootNodes = CXMLIO::SaveSCXMLFragment(
+ *m_StateContext, *m_EditorFoundation->m_Foundation, *m_StringTable, *theWriter,
+ toDataRef(theNodeList.data(), theNodeList.size()), *this, inMousePos,
+ theNamespaces);
+
+ if (m_CopyPasteListener)
+ m_CopyPasteListener->OnCopy(this, rootNodes, *theWriter, theNamespaces);
+
+ SEditorImplStrIOStream theStream;
+ CDOMSerializer::WriteXMLHeader(theStream);
+ CDOMSerializer::Write(m_EditorFoundation->getAllocator(), *theWriter->GetTopElement(),
+ theStream, *m_StringTable,
+ toDataRef(theNamespaces.data(), theNamespaces.size()), false);
+ return theStream.m_Str;
+ }
+
+ bool SEditorImpl::CanPaste(TObjPtr inTarget)
+ {
+ SStateNode *theNode = StateNodeFromEditor(inTarget);
+ if (theNode) {
+ return theNode->m_Type != StateNodeTypes::Transition
+ && theNode->m_Type != StateNodeTypes::History
+ && theNode->m_Type != StateNodeTypes::Final;
+ }
+
+ return false;
+ }
+
+ void SEditorImpl::AddNewPasteObjectToTransaction(SStateNode &inNode)
+ {
+ TObjPtr editorPtr = ToEditor(inNode);
+ if (editorPtr) {
+ m_TransactionManager->m_Transaction->m_Changes.push_back(new SChange(*editorPtr));
+ m_TransactionManager->OnObjectCreated(editorPtr);
+ Option<SValue> children = editorPtr->GetPropertyValue("children");
+ if (children.hasValue()) {
+ TObjList childList = children->getData<TObjList>();
+ for (size_t idx = 0, end = childList.size(); idx < end; ++idx) {
+ SStateNode *childNode = StateNodeFromEditor(childList[idx]);
+ if (childNode)
+ AddNewPasteObjectToTransaction(*childNode);
+ }
+ }
+ }
+ }
+
+ void RecurseAndCheckForValidHistoryAfterPaste(TObjPtr inNode, SEditorImpl &inEditor)
+ {
+ if (AreEqual(inNode->TypeName(), "history")) {
+ inEditor.CheckAndSetValidHistoryDefault(inNode);
+ } else {
+ Option<SValue> childrenOpt = inNode->GetPropertyValue("children");
+ if (childrenOpt.hasValue() == false) {
+ return;
+ }
+ TObjList children = childrenOpt->getData<TObjList>();
+ for (size_t childIdx = 0, childEnd = children.size(); childIdx < childEnd;
+ ++childIdx) {
+ RecurseAndCheckForValidHistoryAfterPaste(children[childIdx], inEditor);
+ }
+ }
+ }
+
+ void SEditorImpl::Paste(const TEditorStr &inCopiedObjects, TObjPtr inTarget,
+ const QT3DSVec2 &inMousePos)
+ {
+ Option<SValue> childrenOpt = inTarget->GetPropertyValue("children");
+ if (childrenOpt.hasValue() == false) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ TObjList children = childrenOpt->getData<TObjList>();
+
+ SEditorImplStrInStream inStream(inCopiedObjects);
+ NVScopedRefCounted<IDOMFactory> theFactory =
+ IDOMFactory::CreateDOMFactory(m_EditorFoundation->getAllocator(), m_StringTable);
+ eastl::pair<SNamespacePairNode *, SDOMElement *> readResult =
+ CDOMSerializer::Read(*theFactory, inStream);
+ SDOMElement *elem = readResult.second;
+ if (elem == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ NVScopedRefCounted<IDOMReader> theReader = IDOMReader::CreateDOMReader(
+ m_EditorFoundation->getAllocator(), *elem, m_StringTable, *theFactory);
+ eastl::pair<eastl::vector<SStateNode *>, CXMLIO::TIdRemapMap> theRootsPair;
+ {
+ IDOMReader::Scope __readerScope(*theReader);
+ theRootsPair =
+ CXMLIO::LoadSCXMLFragment(m_AutoAllocator, *m_EditorFoundation->m_Foundation,
+ *theReader, *m_StringTable, *m_StateContext, *this);
+ }
+ eastl::vector<SStateNode *> &theObjects(theRootsPair.first);
+ if (m_CopyPasteListener)
+ m_CopyPasteListener->OnPaste(this, *theReader, theRootsPair.second);
+ // Merge any namespaces into the context's namespace list.
+ if (m_StateContext->GetDOMFactory()) {
+ for (SNamespacePairNode *fragNode = readResult.first; fragNode;
+ fragNode = fragNode->m_NextNode) {
+ bool found = false;
+ for (SNamespacePairNode *ctxNode = m_StateContext->GetFirstNSNode();
+ ctxNode && !found; ctxNode = ctxNode->m_NextNode) {
+ if (ctxNode->m_Namespace == fragNode->m_Namespace)
+ found = true;
+ }
+ if (!found) {
+ SNamespacePairNode *newNode =
+ m_StateContext->GetDOMFactory()->NextNSPairNode(
+ fragNode->m_Namespace, fragNode->m_Abbreviation);
+ newNode->m_NextNode = m_StateContext->GetFirstNSNode();
+ m_StateContext->SetFirstNSNode(*newNode);
+ }
+ }
+ }
+ QT3DSVec2 globalPos(0, 0);
+ if (inTarget) {
+ for (TObjPtr posObj = inTarget; posObj; posObj = posObj->Parent()) {
+ Option<SValue> theData = posObj->GetPropertyValue("position");
+ if (theData.hasValue())
+ globalPos += theData->getData<QT3DSVec2>();
+ }
+ }
+ QT3DSVec2 theMousePos = inMousePos - globalPos;
+ for (size_t idx = 0, end = theObjects.size(); idx < end; ++idx) {
+ SStateNode *currentObject = theObjects[idx];
+ QT3DSVec2 objPos(0, 0);
+ if (currentObject->m_StateNodeFlags.HasPosition())
+ objPos = currentObject->m_Position;
+ currentObject->SetPosition(objPos + theMousePos);
+ if (m_TransactionManager->m_Transaction)
+ AddNewPasteObjectToTransaction(*currentObject);
+ TObjPtr editorPtr = ToEditor(*currentObject);
+ if (editorPtr.mPtr)
+ children.push_back(editorPtr);
+ }
+ // This sets up the valid parents. Without that, checking if a history node is valid
+ // is meaningless.
+ inTarget->SetPropertyValue("children", children);
+ for (size_t idx = 0, end = children.size(); idx < end; ++idx) {
+ RecurseAndCheckForValidHistoryAfterPaste(children[idx], *this);
+ }
+ }
+
+ bool SEditorImpl::IsDerivedFrom(SStateNode &child, SStateNode &parent)
+ {
+ if (&child == &parent)
+ return true;
+ if (child.m_Parent)
+ return IsDerivedFrom(*child.m_Parent, parent);
+ return false;
+ }
+
+ // This method should always return a value because the scxml root item
+ // is the parent of everyone else.
+ SStateNode &SEditorImpl::GetLeastCommonAncestor(SStateNode &lhs, SStateNode &rhs)
+ {
+ // If lhs is derived from rhs, return rhs
+ if (IsDerivedFrom(lhs, rhs))
+ return rhs;
+ // vice versa
+ else if (IsDerivedFrom(rhs, lhs))
+ return lhs;
+
+ // Else wander up the tree till we find a common ancestor.
+ QT3DS_ASSERT(lhs.m_Parent != NULL);
+ if (lhs.m_Parent != NULL)
+ return GetLeastCommonAncestor(*lhs.m_Parent, rhs);
+
+ return lhs;
+ }
+
+ TObjPtr SEditorImpl::GetLeastCommonAncestor(NVConstDataRef<TObjPtr> inObjects)
+ {
+ SStateNode *lastAncestor = NULL;
+ if (inObjects.size() == 0)
+ return TObjPtr();
+
+ for (QT3DSU32 idx = 0, end = inObjects.size(); idx < end; ++idx) {
+ if (lastAncestor == NULL) {
+ lastAncestor = StateNodeFromEditor(inObjects[idx]);
+ } else {
+ SStateNode *nextNode = StateNodeFromEditor(inObjects[idx]);
+ if (nextNode != NULL) {
+ lastAncestor = &GetLeastCommonAncestor(*lastAncestor, *nextNode);
+ }
+ }
+ }
+
+ if (lastAncestor)
+ return ToEditor(*lastAncestor);
+ else
+ return TObjPtr();
+ }
+
+ void GetCancelableSendIds(TExecutableContentList &inList, TObjList &outList,
+ SEditorImpl &inEditor);
+
+ void RecursiveGetCancelableSendIds(SExecutableContent &inNode, TObjList &outList,
+ SEditorImpl &inEditor)
+ {
+ if (inNode.m_Type == ExecutableContentTypes::Send) {
+ SSend &theSend = static_cast<SSend &>(inNode);
+ if (IExecutionContext::ParseTimeStrToMilliseconds(theSend.m_Delay)
+ || !isTrivial(theSend.m_DelayExpr)) {
+ outList.push_back(inEditor.ExecutableContentToEditor(theSend));
+ }
+ }
+ GetCancelableSendIds(inNode.m_Children, outList, inEditor);
+ }
+
+ void GetCancelableSendIds(TExecutableContentList &inList, TObjList &outList,
+ SEditorImpl &inEditor)
+ {
+ for (TExecutableContentList::iterator iter = inList.begin(), end = inList.end();
+ iter != end; ++iter)
+ RecursiveGetCancelableSendIds(*iter, outList, inEditor);
+ }
+
+ void RecursiveGetCancelableSendIds(SStateNode &inNode, TObjList &outList,
+ SEditorImpl &inEditor)
+ {
+ if (inNode.m_Type == StateNodeTypes::Transition) {
+ STransition &transition = static_cast<STransition &>(inNode);
+ GetCancelableSendIds(transition.m_ExecutableContent, outList, inEditor);
+ } else {
+ TOnEntryList *entryList = inNode.GetOnEntryList();
+ TOnExitList *exitList = inNode.GetOnExitList();
+ if (entryList) {
+ for (TOnEntryList::iterator iter = entryList->begin(), end = entryList->end();
+ iter != end; ++iter)
+ GetCancelableSendIds(iter->m_ExecutableContent, outList, inEditor);
+ }
+ if (exitList) {
+ for (TOnExitList::iterator iter = exitList->begin(), end = exitList->end();
+ iter != end; ++iter)
+ GetCancelableSendIds(iter->m_ExecutableContent, outList, inEditor);
+ }
+ }
+ TStateNodeList *childList = inNode.GetChildren();
+ if (childList) {
+ for (TStateNodeList::iterator childIter = childList->begin(),
+ childEnd = childList->end();
+ childIter != childEnd; ++childIter)
+ RecursiveGetCancelableSendIds(*childIter, outList, inEditor);
+ }
+ }
+
+ // TODO - think about a fast and easy way to cache things (and keep the cache correct).
+ TObjList SEditorImpl::GetCancelableSendIds()
+ {
+ TObjList retval;
+ if (m_StateContext->GetRoot())
+ RecursiveGetCancelableSendIds(*m_StateContext->GetRoot(), retval, *this);
+ return retval;
+ }
+
+ static const char8_t *whitespace = "\n\r\t ";
+
+ void StripIfLastChar(TEditorStr &str, char data)
+ {
+ if (str.size() && str.back() == data)
+ str.resize(str.size() - 1);
+ }
+
+ void AddUnique(TEditorStrList &list, const TEditorStr &str)
+ {
+ if (eastl::find(list.begin(), list.end(), str) == list.end())
+ list.push_back(str);
+ }
+
+ void RecursiveScanExecutableContentForEvents(TExecutableContentList &contentList,
+ TEditorStrList &ioStrList)
+ {
+ for (TExecutableContentList::iterator iter = contentList.begin(),
+ end = contentList.end();
+ iter != end; ++iter) {
+ if (iter->m_Type == ExecutableContentTypes::Send) {
+ SSend &theSend = static_cast<SSend &>(*iter);
+ if (!isTrivial(theSend.m_Event)) {
+ AddUnique(ioStrList, theSend.m_Event.c_str());
+ }
+ } else if (iter->m_Type == ExecutableContentTypes::Raise) {
+ SRaise &theRaise = static_cast<SRaise &>(*iter);
+ if (!isTrivial(theRaise.m_Event)) {
+ AddUnique(ioStrList, theRaise.m_Event.c_str());
+ }
+ }
+ RecursiveScanExecutableContentForEvents(iter->m_Children, ioStrList);
+ }
+ }
+
+ template <typename TListType>
+ void ScanItemListForEvents(TListType *itemList, TEditorStrList &ioEvents)
+ {
+ if (itemList) {
+ typedef typename TListType::iterator iterator;
+ for (iterator iter = itemList->begin(), end = itemList->end(); iter != end;
+ ++iter) {
+ RecursiveScanExecutableContentForEvents(iter->m_ExecutableContent, ioEvents);
+ }
+ }
+ }
+
+ void RecursiveGetStateMachineEvents(SStateNode &inNode, TEditorStrList &ioList)
+ {
+ if (inNode.m_Type == StateNodeTypes::Transition) {
+ STransition &theTransition = static_cast<STransition &>(inNode);
+ TEditorStr transStr(theTransition.m_Event);
+ for (size_t pos = transStr.find_first_not_of(whitespace); pos != TEditorStr::npos;
+ pos = transStr.find_first_not_of(whitespace, pos)) {
+ size_t end = transStr.find_first_of(whitespace, pos);
+ if (end == TEditorStr::npos)
+ end = transStr.size();
+ TEditorStr subStr = transStr.substr(pos, end - pos);
+ pos = end;
+ StripIfLastChar(subStr, '*');
+ StripIfLastChar(subStr, '.');
+ AddUnique(ioList, subStr);
+ }
+ RecursiveScanExecutableContentForEvents(theTransition.m_ExecutableContent, ioList);
+ } else {
+ ScanItemListForEvents(inNode.GetOnEntryList(), ioList);
+ ScanItemListForEvents(inNode.GetOnExitList(), ioList);
+ }
+ TStateNodeList *children = inNode.GetChildren();
+ if (children) {
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter)
+ RecursiveGetStateMachineEvents(*iter, ioList);
+ }
+ }
+
+ TEditorStrList SEditorImpl::GetStateMachineEvents()
+ {
+ TEditorStrList retval;
+ if (m_StateContext->GetRoot())
+ RecursiveGetStateMachineEvents(*m_StateContext->GetRoot(), retval);
+ eastl::sort(retval.begin(), retval.end());
+ return retval;
+ }
+
+ eastl::pair<SExecutableContent *, TObjPtr>
+ SEditorImpl::CreateExecutableContent(const char8_t *inTypeName)
+ {
+ SExecutableContent *newExecutable = NULL;
+ TObjPtr newObj;
+ if (AreEqual(inTypeName, SSendEditor::GetTypeStr())) {
+ eastl::pair<SSend *, TObjPtr> theNewEditor = CreateEditorAndObject<SSend>();
+ GenerateUniqueId(*theNewEditor.first, "send");
+ newExecutable = theNewEditor.first;
+ newObj = theNewEditor.second;
+ } else if (AreEqual(inTypeName, SScriptEditor::GetTypeStr())) {
+ eastl::pair<SScript *, TObjPtr> theNewEditor = CreateEditorAndObject<SScript>();
+ newExecutable = theNewEditor.first;
+ newObj = theNewEditor.second;
+ } else if (AreEqual(inTypeName, SCancelEditor::GetTypeStr())) {
+ eastl::pair<SCancel *, TObjPtr> theNewEditor = CreateEditorAndObject<SCancel>();
+ newExecutable = theNewEditor.first;
+ newObj = theNewEditor.second;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return eastl::make_pair(newExecutable, newObj);
+ }
+
+ struct SExecListAddChange : public IChange
+ {
+ TExecutableContentList &parentList;
+ SExecutableContent *prevSibling;
+ SExecutableContent &item;
+ TObjPtr editorObj;
+ QT3DSI32 mRefCount;
+ bool m_AddOnDo;
+ SExecListAddChange(TExecutableContentList &plist, SExecutableContent *prev,
+ SExecutableContent &_item, TObjPtr objPtr, bool addOnDo)
+ : parentList(plist)
+ , prevSibling(prev)
+ , item(_item)
+ , editorObj(objPtr)
+ , mRefCount(0)
+ , m_AddOnDo(addOnDo)
+ {
+ }
+
+ void Add()
+ {
+ if (prevSibling)
+ parentList.insert_after(*prevSibling, item);
+ else
+ parentList.push_front(item);
+ }
+ void Remove() { parentList.remove(item); }
+
+ virtual void Do()
+ {
+ if (m_AddOnDo)
+ Add();
+ else
+ Remove();
+ }
+
+ virtual void Undo()
+ {
+ if (m_AddOnDo)
+ Remove();
+ else
+ Add();
+ }
+
+ virtual TObjPtr GetEditor() { return editorObj; }
+
+ virtual void addRef() { ++mRefCount; }
+
+ virtual void release()
+ {
+ --mRefCount;
+ if (mRefCount <= 0)
+ delete this;
+ }
+ };
+
+ void SEditorImpl::ReplaceExecutableContent(SExecutableContent &oldContent,
+ SExecutableContent &newContent)
+ {
+ SStateNode *stateNodeParent = oldContent.m_StateNodeParent;
+ SExecutableContent *execContentParent = oldContent.m_Parent;
+ SExecutableContentParentInfo parentInfo(oldContent, *this);
+ SExecutableContent *prevSibling = oldContent.m_PreviousSibling;
+
+ // Can't use remove object from graph here because it is too aggressive.
+ NVScopedRefCounted<SExecListAddChange> oldChange = new SExecListAddChange(
+ *parentInfo.parentList, prevSibling, oldContent, parentInfo.editorObj, false);
+ oldChange->Do();
+ newContent.m_StateNodeParent = stateNodeParent;
+ newContent.m_Parent = execContentParent;
+ NVScopedRefCounted<SExecListAddChange> newChange = new SExecListAddChange(
+ *parentInfo.parentList, prevSibling, newContent, parentInfo.editorObj, true);
+ newChange->Do();
+ if (GetOpenTransactionImpl()) {
+ GetOpenTransactionImpl()->m_Changes.push_back(oldChange.mPtr);
+ GetOpenTransactionImpl()->m_Changes.push_back(newChange.mPtr);
+ }
+ }
+
+ TObjPtr SEditorImpl::ChangeExecutableContentType(TObjPtr inContent, const char8_t *newType)
+ {
+ SExecutableContent *theContent = ExecutableContentFromEditor(inContent);
+ if (!theContent) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ SExecutableContentParentInfo parentInfo(*theContent, *this);
+ // find the index of the item in the parent list.
+ if (parentInfo.parentList == NULL) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ eastl::pair<SExecutableContent *, TObjPtr> theNewContent =
+ CreateExecutableContent(newType);
+ if (!theNewContent.first) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ ReplaceExecutableContent(*theContent, *theNewContent.first);
+ return theNewContent.second;
+ }
+
+ TEditorStr SEditorImpl::ToXML(TObjPtr inContent)
+ {
+ SExecutableContent *theContent = ExecutableContentFromEditor(inContent);
+ if (!theContent) {
+ QT3DS_ASSERT(false);
+ return TEditorStr();
+ }
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_EditorFoundation->getAllocator(), m_StringTable));
+ NVScopedRefCounted<IDOMWriter> theWriter(
+ IDOMWriter::CreateDOMWriter(m_EditorFoundation->getAllocator(), "innerXML",
+ m_StringTable, 0)
+ .first);
+ CXMLIO::ToEditableXml(*m_StateContext, m_EditorFoundation->getFoundation(),
+ *m_StringTable, *theWriter, *theContent, *this);
+ SDOMElement *theTopElem = theWriter->GetTopElement();
+ SDOMElement *xmlElem = &theTopElem->m_Children.front();
+ SEditorImplStrIOStream theStream;
+ if (xmlElem) {
+
+ eastl::vector<SNamespacePair> theNamespaces;
+ for (SNamespacePairNode *theNode = m_StateContext->GetFirstNSNode(); theNode;
+ theNode = theNode->m_NextNode)
+ theNamespaces.push_back(*theNode);
+ if (theNamespaces.empty()) {
+ theNamespaces.push_back(SNamespacePair(
+ m_StringTable->RegisterStr("http://www.w3.org/2005/07/scxml")));
+ theNamespaces.push_back(
+ SNamespacePair(m_StringTable->RegisterStr("http://qt.io/qt3dstudio/uicstate"),
+ m_StringTable->RegisterStr("uic")));
+ }
+ CDOMSerializer::Write(
+ m_EditorFoundation->getAllocator(), *xmlElem, theStream, *m_StringTable,
+ toDataRef(theNamespaces.data(), theNamespaces.size()), false, 0, false);
+ }
+ return theStream.m_Str;
+ }
+
+ struct SStrXMLErrorHandler : public CXmlErrorHandler
+ {
+ TEditorStr m_Error;
+ virtual void OnXmlError(TXMLCharPtr errorName, int line, int /*column*/)
+ {
+ char buf[256];
+ sprintf(buf, "Error on line %d: ", line);
+ m_Error.assign(buf);
+ m_Error.append(nonNull(errorName));
+ }
+ };
+
+ eastl::pair<TEditorStr, TObjPtr> SEditorImpl::FromXML(TObjPtr inContent,
+ const TEditorStr &ioEditedXML)
+ {
+ TEditorStr wrappedXML("<snippet ");
+ eastl::vector<SNamespacePair> theNamespaces;
+ for (SNamespacePairNode *theNode = m_StateContext->GetFirstNSNode(); theNode;
+ theNode = theNode->m_NextNode)
+ theNamespaces.push_back(*theNode);
+ if (theNamespaces.empty()) {
+ theNamespaces.push_back(
+ SNamespacePair(m_StringTable->RegisterStr("http://www.w3.org/2005/07/scxml")));
+ theNamespaces.push_back(
+ SNamespacePair(m_StringTable->RegisterStr("http://qt.io/qt3dstudio/uicstate"),
+ m_StringTable->RegisterStr("uic")));
+ }
+ for (size_t idx = 0, end = theNamespaces.size(); idx < end; ++idx) {
+ SNamespacePair &theNode(theNamespaces[idx]);
+ wrappedXML.append(" xmlns");
+ if (theNode.m_Abbreviation.IsValid()) {
+ wrappedXML.append(":");
+ wrappedXML.append(theNode.m_Abbreviation.c_str());
+ }
+ wrappedXML.append("=\"");
+ wrappedXML.append(theNode.m_Namespace.c_str());
+ wrappedXML.append("\"");
+ }
+ wrappedXML.append(">");
+ wrappedXML.append(ioEditedXML);
+ wrappedXML.append("</snippet>");
+ SEditorImplStrInStream theStream(wrappedXML);
+
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_EditorFoundation->getAllocator(), m_StringTable));
+ SStrXMLErrorHandler errorHandler;
+ SDOMElement *theElem =
+ CDOMSerializer::Read(*theFactory, theStream, &errorHandler).second;
+ TObjPtr retval;
+ if (theElem) {
+ NVScopedRefCounted<IDOMReader> theReader(IDOMReader::CreateDOMReader(
+ m_EditorFoundation->getAllocator(), theElem->m_Children.front(), m_StringTable,
+ theFactory));
+ SExecutableContent *oldContent = ExecutableContentFromEditor(inContent);
+ SExecutableContent *theContent =
+ CXMLIO::FromEditableXML(*theReader, m_EditorFoundation->getFoundation(),
+ *m_StateContext, *m_StringTable, m_AutoAllocator, *this,
+ oldContent->m_StateNodeParent, oldContent->m_Parent);
+ if (theContent) {
+ ReplaceExecutableContent(*oldContent, *theContent);
+ retval = ExecutableContentToEditor(*theContent);
+ } else {
+ errorHandler.m_Error.assign("The \"");
+ errorHandler.m_Error.append(theReader->GetElementName().c_str());
+ errorHandler.m_Error.append("\" action is not recognized. It must be one of:");
+ eastl::vector<eastl::string> contentNames =
+ CXMLIO::GetSupportedExecutableContentNames();
+ for (size_t idx = 0, end = contentNames.size(); idx < end; ++idx) {
+ if (idx != 0)
+ errorHandler.m_Error.append(",");
+
+ errorHandler.m_Error.append(" \"");
+ errorHandler.m_Error.append(contentNames[idx].c_str());
+ errorHandler.m_Error.append("\"");
+ }
+ errorHandler.m_Error.append(".");
+ }
+ }
+
+ return eastl::make_pair(errorHandler.m_Error, retval);
+ }
+
+ void SEditorImpl::ReleaseEditor(void *inData)
+ {
+ TStateEditorMap::iterator iter = m_Editors.find(inData);
+ if (iter != m_Editors.end())
+ m_Editors.erase(iter);
+ }
+
+ bool SEditorImpl::Save(const char8_t *inFileName)
+ {
+ CFileSeekableIOStream theFile(inFileName, FileWriteFlags());
+ if (theFile.IsOpen() == false) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ Save(theFile);
+ return true;
+ }
+
+ void SEditorImpl::Save(IOutStream &inStream) { m_StateContext->Save(inStream, this); }
+
+ bool SEditorImpl::Load(IInStream &inStream, const char8_t *inFilename)
+ {
+ bool theRetval = false;
+ m_StateContext = IStateContext::Load(m_AutoAllocator, *m_EditorFoundation->m_Foundation,
+ inStream, inFilename, m_StringTable.mPtr, this);
+ if (m_StateContext.mPtr == 0)
+ m_StateContext = IStateContext::Create(*m_EditorFoundation->m_Foundation);
+ else
+ theRetval = true;
+ return theRetval;
+ }
+
+ STransaction *SEditorImpl::GetOpenTransactionImpl()
+ {
+ return m_TransactionManager->m_Transaction.mPtr;
+ }
+
+ void SEditorImpl::SetIdProperty(SStateNode &inNode, const SValue &inData,
+ CRegisteredString & /*inTarget*/)
+ {
+ IStateContext &theContext = *m_StateContext;
+ theContext.EraseId(inNode.m_Id);
+ TEditorStr potentialId = inData.getData<TEditorStr>();
+ if (potentialId.size() == 0) {
+ switch (inNode.m_Type) {
+ case StateNodeTypes::State:
+ potentialId = "state";
+ break;
+ case StateNodeTypes::Parallel:
+ potentialId = "parallel";
+ break;
+ case StateNodeTypes::Transition:
+ potentialId = "transition";
+ break;
+ case StateNodeTypes::Final:
+ potentialId = "final";
+ break;
+ case StateNodeTypes::History:
+ potentialId = "history";
+ break;
+ case StateNodeTypes::SCXML:
+ potentialId = "scxml";
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ potentialId = "id";
+ break;
+ }
+ }
+ CRegisteredString oldId = inNode.m_Id;
+ inNode.m_Id = CRegisteredString();
+ GenerateUniqueId(inNode, potentialId.c_str());
+ // This is a bad hack to get around:
+ // 1. user changes id calling this function
+ if (m_CopyPasteListener) {
+ m_CopyPasteListener->OnIDChange(this, inNode, oldId);
+ }
+ }
+
+ void SEditorImpl::SetIdProperty(SSend &inNode, const SValue &inData,
+ CRegisteredString & /*inTarget*/)
+ {
+ IStateContext &theContext = *m_StateContext;
+ theContext.EraseId(inNode.m_Id);
+ TEditorStr potentialId = inData.getData<TEditorStr>();
+ if (potentialId.size() == 0)
+ potentialId = "send";
+
+ inNode.m_Id = CRegisteredString();
+ GenerateUniqueId(inNode, potentialId.c_str());
+ }
+
+ void SEditorImpl::Set(const Option<SValue> &inData, NVConstDataRef<SStateNode *> &inTarget)
+ {
+ if (inTarget.mData != NULL) {
+ m_AutoAllocator.deallocate((void *)inTarget.mData);
+ inTarget.mData = NULL;
+ inTarget.mSize = 0;
+ }
+ if (inData.hasValue()) {
+ TObjList inList(inData->getData<TObjList>());
+ eastl::vector<SStateNode *> validObjects;
+ for (size_t idx = 0, end = inList.size(); idx < end; ++idx) {
+ TObjPtr theObj = inList[idx];
+ SStateNode *theNode = StateNodeFromEditor(theObj);
+ if (theNode) {
+ validObjects.push_back(theNode);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ if (validObjects.empty() == false) {
+ NVConstDataRef<SStateNode *> &outList(inTarget);
+ size_t byteCount = validObjects.size() * sizeof(SStateNode *);
+ outList.mData = (SStateNode * const *)m_AutoAllocator.allocate(
+ byteCount, "graph ref list data", __FILE__, __LINE__);
+ memCopy((void *)outList.mData, validObjects.data(), byteCount);
+ outList.mSize = validObjects.size();
+ }
+ }
+ }
+
+ SValue SEditorImpl::Get(NVConstDataRef<SStateNode *> &inTarget)
+ {
+ TObjList retval;
+ NVConstDataRef<SStateNode *> inRefList(inTarget);
+ for (QT3DSU32 idx = 0, end = inRefList.size(); idx < end; ++idx) {
+ TObjPtr obj = ToEditor(inRefList[idx]);
+ if (obj)
+ retval.push_back(obj);
+ else {
+ // This shouldn't ever happen, but it might when loading
+ // an invalid file.
+ QT3DS_ASSERT(false);
+ }
+ }
+ return retval;
+ }
+
+ void SEditorImpl::Set(const Option<SValue> &inData, STransition *&inTarget)
+ {
+ inTarget = NULL;
+ if (inData.hasValue()) {
+ TObjPtr theData(inData->getData<TObjPtr>());
+ inTarget = FromEditor<STransition>(theData);
+ }
+ }
+
+ Option<SValue> SEditorImpl::Get(STransition *&inTarget)
+ {
+ return SValue(ToEditor(inTarget));
+ }
+
+ void SEditorImpl::SetInitial(const TObjList &inList, STransition *&outTransitionPtr)
+ {
+ if (outTransitionPtr) {
+ Set(SValue(inList), outTransitionPtr->m_Target);
+ if (outTransitionPtr->m_Target.mSize == 0
+ && outTransitionPtr->m_ExecutableContent.empty())
+ outTransitionPtr = NULL;
+ } else {
+ NVConstDataRef<SStateNode *> theTemp;
+ Set(SValue(inList), theTemp);
+ if (theTemp.mSize) {
+ outTransitionPtr = QT3DS_NEW(m_AutoAllocator, STransition)();
+ outTransitionPtr->m_Target = theTemp;
+ }
+ }
+ }
+
+ SValue SEditorImpl::GetInitial(STransition *inInitialTrans)
+ {
+ if (inInitialTrans)
+ return Get(inInitialTrans->m_Target);
+
+ return TObjList();
+ }
+ static inline STransition **GetInitialTransitionPtr(SStateNode &inParent)
+ {
+ StateNodeTypes::Enum typeEnum(inParent.m_Type);
+ STransition **theParentTransPtr = NULL;
+ if (typeEnum == StateNodeTypes::SCXML)
+ theParentTransPtr = &static_cast<SSCXML &>(inParent).m_Initial;
+ else if (typeEnum == StateNodeTypes::State)
+ theParentTransPtr = &static_cast<SState &>(inParent).m_Initial;
+ return theParentTransPtr;
+ }
+
+ static inline bool IsFirstChild(SStateNode &inChild, SStateNode &inParent)
+ {
+ TStateNodeList *childList = inParent.GetChildren();
+ SStateNode *firstViableChild = NULL;
+ if (childList) {
+ for (TStateNodeList::iterator iter = childList->begin(), end = childList->end();
+ iter != end && firstViableChild == NULL; ++iter) {
+ StateNodeTypes::Enum typeEnum = iter->m_Type;
+ if (typeEnum == StateNodeTypes::State || typeEnum == StateNodeTypes::Parallel
+ || typeEnum == StateNodeTypes::Final) {
+ firstViableChild = &(*iter);
+ }
+ }
+ }
+ return firstViableChild == &inChild;
+ }
+
+ struct SInitialTargetChange : public IChange
+ {
+ TObjPtr m_EditorObj;
+ SStateNode &m_Parent;
+ STransition *m_InitialTransition;
+ STransition *m_FinalTransition;
+ QT3DSI32 m_RefCount;
+ // Implicitly setting c to be the initial target.
+ SInitialTargetChange(TObjPtr editorObj, SStateNode &p, SStateNode &c,
+ SEditorImpl &editor)
+ : m_EditorObj(editorObj)
+ , m_Parent(p)
+ , m_InitialTransition(NULL)
+ , m_FinalTransition(NULL)
+ , m_RefCount(0)
+ {
+ STransition **theTransitionPtr = GetInitialTransitionPtr(m_Parent);
+ QT3DS_ASSERT(theTransitionPtr);
+ if (theTransitionPtr) {
+ m_InitialTransition = *theTransitionPtr;
+ theTransitionPtr[0] = NULL;
+ bool firstChild = IsFirstChild(c, p);
+ if (!firstChild) {
+ TObjPtr editorObj = editor.Create("transition", "");
+ TObjList targets;
+ targets.push_back(editor.ToEditor(c));
+ editorObj->SetPropertyValue("target", targets);
+ SStateNode *stateNode = editor.StateNodeFromEditor(editorObj);
+ m_FinalTransition = static_cast<STransition *>(stateNode);
+ m_FinalTransition->m_Parent = &p;
+ *theTransitionPtr = m_FinalTransition;
+ }
+ }
+ }
+ virtual void addRef() { ++m_RefCount; }
+ virtual void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+ virtual TObjPtr GetEditor() { return m_EditorObj; }
+
+ template <typename TNodeType>
+ void Apply(STransition *trans, TNodeType &node)
+ {
+ node.m_Initial = trans;
+ }
+
+ virtual void Do()
+ {
+ if (m_Parent.m_Type == StateNodeTypes::SCXML)
+ Apply(m_FinalTransition, static_cast<SSCXML &>(m_Parent));
+ else if (m_Parent.m_Type == StateNodeTypes::State)
+ Apply(m_FinalTransition, static_cast<SState &>(m_Parent));
+ }
+
+ virtual void Undo()
+ {
+ if (m_Parent.m_Type == StateNodeTypes::SCXML)
+ Apply(m_InitialTransition, static_cast<SSCXML &>(m_Parent));
+ else if (m_Parent.m_Type == StateNodeTypes::State)
+ Apply(m_InitialTransition, static_cast<SState &>(m_Parent));
+ }
+ };
+
+ void SEditorImpl::SetInitialTarget(const Option<SValue> &inData, SStateNode &inNode)
+ {
+ if (inNode.m_Type == StateNodeTypes::Transition
+ /**|| inNode.m_Type == StateNodeTypes::History **/) {
+ QT3DS_ASSERT(false);
+ }
+ SStateNode *theParent = inNode.m_Parent;
+ if (theParent) {
+ STransition **theParentTransPtr = GetInitialTransitionPtr(*theParent);
+
+ if (theParentTransPtr) {
+ bool newValue = false;
+ if (inData.hasValue())
+ newValue = inData->getData<bool>();
+
+ NVScopedRefCounted<SInitialTargetChange> theChange =
+ new SInitialTargetChange(ToEditor(*theParent), *theParent, inNode, *this);
+ theChange->Do();
+ STransaction *theTransaction = GetOpenTransactionImpl();
+ if (theTransaction) {
+ theTransaction->m_Changes.push_back(theChange.mPtr);
+ TStateNodeList *children = theParent->GetChildren();
+ for (TStateNodeList::iterator iter = children->begin(),
+ end = children->end();
+ iter != end; ++iter) {
+ theTransaction->m_Changes.push_back(new SChange(*ToEditor(*iter)));
+ }
+ }
+ }
+ }
+ }
+
+ SValue SEditorImpl::IsInitialTarget(SStateNode &inNode)
+ {
+ if (inNode.m_Type == StateNodeTypes::Transition
+ /** || inNode.m_Type == StateNodeTypes::History **/)
+ return SValue(false);
+
+ SStateNode *theParent(inNode.m_Parent);
+ if (theParent) {
+ if (!isTrivial(theParent->GetInitialExpression()))
+ return false;
+
+ STransition *theTransition = theParent->GetInitialTransition();
+ if (theTransition) {
+ for (QT3DSU32 idx = 0, end = theTransition->m_Target.size(); idx < end; ++idx)
+ if (&inNode == theTransition->m_Target[idx])
+ return SValue(true);
+ } else {
+ if (GetInitialTransitionPtr(*theParent))
+ return SValue(IsFirstChild(inNode, *theParent));
+ }
+ }
+ return SValue(false);
+ }
+
+ TEditorStr SEditorImpl::GetDefaultInitialValue(SStateNode &inNode)
+ {
+ TStateNodeList *children = inNode.GetChildren();
+ if (children == NULL)
+ return TEditorStr();
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter) {
+ if (iter->m_Type != StateNodeTypes::History
+ && iter->m_Type != StateNodeTypes::Transition)
+ return TEditorStr(iter->m_Id.c_str());
+ }
+
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter) {
+ if (iter->m_Type != StateNodeTypes::Transition)
+ return TEditorStr(iter->m_Id.c_str());
+ }
+
+ return TEditorStr();
+ }
+
+ void SEditorImpl::GetLegalInitialValues(SStateNode &inNode,
+ eastl::vector<CRegisteredString> &outValues)
+ {
+ TStateNodeList *children = inNode.GetChildren();
+ if (children == NULL)
+ return;
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter) {
+ if (/** iter->m_Type != StateNodeTypes::History && **/ iter->m_Type
+ != StateNodeTypes::Transition)
+ outValues.push_back(iter->m_Id);
+ }
+ }
+
+ struct SInitialComboChange : public IChange
+ {
+ SStateNode &m_Node;
+ TObjPtr m_EditorObj;
+ const TEditorStr m_PreEditorComboValue;
+ const TEditorStr m_PostEditorComboValue;
+ const char8_t *m_PreInitialExpression;
+ const char8_t *m_PostInitialExpression;
+ STransition *m_PreComboTransition;
+ STransition *m_PostComboTransition;
+ QT3DSI32 m_RefCount;
+ SInitialComboChange(SStateNode &node, TObjPtr editObj, const char8_t *preExpr,
+ const char8_t *postExpr, STransition *preCombo,
+ STransition *postCombo, const TEditorStr &preEditorComboValue,
+ const TEditorStr &postEditorComboValue)
+ : m_Node(node)
+ , m_EditorObj(editObj)
+ , m_RefCount(0)
+ , m_PreInitialExpression(preExpr)
+ , m_PostInitialExpression(postExpr)
+ , m_PreComboTransition(preCombo)
+ , m_PostComboTransition(postCombo)
+ , m_PreEditorComboValue(preEditorComboValue)
+ , m_PostEditorComboValue(postEditorComboValue)
+ {
+ }
+
+ virtual void addRef() { ++m_RefCount; }
+ virtual void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+ virtual TObjPtr GetEditor() { return m_EditorObj; }
+
+ template <typename TNodeType, typename TEditorType>
+ void Apply(const char8_t *expr, STransition *trans, const TEditorStr &comboValue,
+ TNodeType &node, TEditorType &editor)
+ {
+ node.m_Initial = trans;
+ node.m_InitialExpr = expr;
+ editor.ApplyInitial(comboValue);
+ // editor.m_InitialComboValue = comboValue;
+ }
+
+ virtual void Do()
+ {
+ if (m_Node.m_Type == StateNodeTypes::SCXML)
+ Apply(m_PostInitialExpression, m_PostComboTransition, m_PostEditorComboValue,
+ static_cast<SSCXML &>(m_Node), static_cast<SSCXMLEditor &>(*m_EditorObj));
+ else if (m_Node.m_Type == StateNodeTypes::State)
+ Apply(m_PostInitialExpression, m_PostComboTransition, m_PostEditorComboValue,
+ static_cast<SState &>(m_Node), static_cast<SStateEditor &>(*m_EditorObj));
+ }
+
+ virtual void Undo()
+ {
+ if (m_Node.m_Type == StateNodeTypes::SCXML)
+ Apply(m_PreInitialExpression, m_PreComboTransition, m_PreEditorComboValue,
+ static_cast<SSCXML &>(m_Node), static_cast<SSCXMLEditor &>(*m_EditorObj));
+ else if (m_Node.m_Type == StateNodeTypes::State)
+ Apply(m_PreInitialExpression, m_PreComboTransition, m_PreEditorComboValue,
+ static_cast<SState &>(m_Node), static_cast<SStateEditor &>(*m_EditorObj));
+ }
+ };
+
+ void SEditorImpl::SetInitialAttribute(const Option<SValue> &inData, SStateNode &inNode)
+ {
+ TObjPtr theEditor = ToEditor(inNode);
+ STransition **targetPtr = NULL;
+ const char8_t **exprPtr = NULL;
+ TEditorStr comboValue;
+ if (inNode.m_Type == StateNodeTypes::State) {
+ targetPtr = &static_cast<SState &>(inNode).m_Initial;
+ exprPtr = &static_cast<SState &>(inNode).m_InitialExpr;
+ comboValue = static_cast<SStateEditor &>(*theEditor).m_InitialComboValue;
+ } else if (inNode.m_Type == StateNodeTypes::SCXML) {
+ targetPtr = &static_cast<SSCXML &>(inNode).m_Initial;
+ exprPtr = &static_cast<SSCXML &>(inNode).m_InitialExpr;
+ comboValue = static_cast<SSCXMLEditor &>(*theEditor).m_InitialComboValue;
+ }
+
+ if (targetPtr == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ STransition *initialTrans = *targetPtr;
+ const char8_t *initialExpr = *exprPtr;
+ TEditorStr initialComboValue = comboValue;
+
+ if (inData.isEmpty()) {
+ *targetPtr = NULL;
+ comboValue = "(script expression)";
+ } else {
+ TEditorStr stateId = inData->getData<TEditorStr>();
+ SStateNode *theNode =
+ this->m_StateContext->FindStateNode(RegisterStr(stateId.c_str()));
+ if (theNode) {
+ *targetPtr = QT3DS_NEW(this->m_AutoAllocator, STransition)();
+ SStateNode **newNode =
+ reinterpret_cast<SStateNode **>(this->m_AutoAllocator.allocate(
+ sizeof(SStateNode *), "TargetList", __FILE__, __LINE__));
+ targetPtr[0]->m_Target = toDataRef(newNode, 1);
+ *const_cast<SStateNode **>(targetPtr[0]->m_Target.begin()) = theNode;
+ targetPtr[0]->m_Target.mSize = 1;
+ comboValue = stateId;
+ } else {
+ *targetPtr = NULL;
+ comboValue = "";
+ }
+ *exprPtr = "";
+ }
+ STransition *postTrans = *targetPtr;
+ const char8_t *postExpr = *exprPtr;
+ TEditorStr postComboValue = comboValue;
+ STransaction *theTransaction = GetOpenTransactionImpl();
+ if (theTransaction) {
+ SInitialComboChange *theChange = new SInitialComboChange(
+ inNode, ToEditor(inNode), initialExpr, postExpr, initialTrans, postTrans,
+ initialComboValue, postComboValue);
+ theChange->Do();
+ theTransaction->m_Changes.push_back(theChange);
+ TStateNodeList *children = inNode.GetChildren();
+ if (children) {
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter) {
+ theTransaction->m_Changes.push_back(new SChange(*ToEditor(*iter)));
+ }
+ }
+ }
+ }
+
+ void SEditorImpl::Set(const Option<SValue> &inData, SDataModel *&inTarget)
+ {
+ if (inData.hasValue()) {
+ TObjPtr thePtr = inData->getData<TObjPtr>();
+ if (thePtr)
+ inTarget = FromEditor<SDataModel>(thePtr);
+ else
+ inTarget = NULL;
+ } else
+ inTarget = NULL;
+ }
+
+ SValue SEditorImpl::Get(SDataModel *inTarget) { return ToEditor(inTarget); }
+
+ void SEditorImpl::Set(const Option<SValue> &inData, TDataList &inTarget)
+ {
+ while (inTarget.empty() == false)
+ inTarget.remove(inTarget.front());
+ if (inData.hasValue()) {
+ TObjList newData = inData->getData<TObjList>();
+ for (TObjList::iterator iter = newData.begin(), end = newData.end(); iter != end;
+ ++iter) {
+ SData *entry = FromEditor<SData>(*iter);
+ if (entry)
+ inTarget.push_back(*entry);
+ }
+ }
+ }
+
+ SValue SEditorImpl::Get(TDataList &inTarget)
+ {
+ TObjList retval;
+ for (TDataList::iterator iter = inTarget.begin(), end = inTarget.end(); iter != end;
+ ++iter) {
+ TObjPtr item = ToEditor(*iter);
+ if (item)
+ retval.push_back(item);
+ }
+ return retval;
+ }
+
+ void SEditorImpl::Set(const Option<SValue> &inData, NVConstDataRef<QT3DSVec2> &inTarget)
+ {
+ if (inTarget.size()) {
+ m_AutoAllocator.deallocate((void *)inTarget.mData);
+ inTarget.mData = NULL;
+ inTarget.mSize = 0;
+ }
+ if (inData.hasValue()) {
+ TVec2List newData(inData->getData<TVec2List>());
+ if (newData.size()) {
+ size_t newDataSize = newData.size() * sizeof(QT3DSVec2);
+ QT3DSVec2 *newTargetData = (QT3DSVec2 *)m_AutoAllocator.allocate(
+ newDataSize, "Transition::m_Path", __FILE__, __LINE__);
+ memCopy(newTargetData, newData.data(), newDataSize);
+ inTarget = toDataRef(newTargetData, newData.size());
+ }
+ }
+ }
+
+ SValue SEditorImpl::Get(const NVConstDataRef<QT3DSVec2> &inTarget)
+ {
+ TVec2List retval;
+ if (inTarget.mSize)
+ retval.insert(retval.end(), inTarget.begin(), inTarget.end());
+ return retval;
+ }
+
+ void SEditorImpl::Set(const Option<SValue> &inData, SSend *&inTarget)
+ {
+ inTarget = NULL;
+ if (inData.hasValue() && inData->getType() == ValueTypes::ObjPtr) {
+ TObjPtr object = inData->getData<TObjPtr>();
+ SSend *newPtr = FromEditor<SSend>(object);
+ inTarget = newPtr;
+ }
+ }
+
+ SValue SEditorImpl::Get(SSend *inTarget)
+ {
+ if (!inTarget)
+ return SValue(TObjPtr());
+ return ToEditor(inTarget);
+ }
+
+ TObjPtr SEditorImpl::CreateExecutableContent(SStateNode &inParent,
+ const char8_t *inTypeName)
+ {
+ SExecutableContent *newExecutable = NULL;
+ TObjPtr newObj;
+ if (AreEqual(inTypeName, SSendEditor::GetTypeStr())) {
+ eastl::pair<SSend *, TObjPtr> theNewEditor = CreateEditorAndObject<SSend>();
+ GenerateUniqueId(*theNewEditor.first, "send");
+ newExecutable = theNewEditor.first;
+ newObj = theNewEditor.second;
+ } else if (AreEqual(inTypeName, SScriptEditor::GetTypeStr())) {
+ eastl::pair<SScript *, TObjPtr> theNewEditor = CreateEditorAndObject<SScript>();
+ newExecutable = theNewEditor.first;
+ newObj = theNewEditor.second;
+ } else if (AreEqual(inTypeName, SCancelEditor::GetTypeStr())) {
+ eastl::pair<SCancel *, TObjPtr> theNewEditor = CreateEditorAndObject<SCancel>();
+ newExecutable = theNewEditor.first;
+ newObj = theNewEditor.second;
+ } else {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ if (newExecutable)
+ newExecutable->m_StateNodeParent = &inParent;
+ return newObj;
+ }
+
+ SValue SEditorImpl::GetSendId(const char8_t *expression)
+ {
+ if (isTrivial(expression))
+ return SValue((QT3DSU32)0);
+ return static_cast<QT3DSU32>(IExecutionContext::ParseTimeStrToMilliseconds(expression));
+ }
+
+ void SEditorImpl::SetSendId(const Option<SValue> &inData, const char8_t *&outExpression)
+ {
+ if (!isTrivial(outExpression))
+ m_AutoAllocator.deallocate(const_cast<char8_t *>(outExpression));
+
+ outExpression = "";
+
+ if (inData.hasValue() && inData->getType() == ValueTypes::U32) {
+ QT3DSU32 expr = inData->getData<QT3DSU32>();
+ char buffer[64];
+ sprintf(buffer, "%u", expr);
+ int len = strlen(buffer);
+ if (len < 61) {
+ buffer[len] = 'm';
+ buffer[len + 1] = 's';
+ buffer[len + 2] = 0;
+ }
+ outExpression = ToGraphStr(buffer);
+ }
+ }
+
+ IStateContext &SEditorImpl::GetStateContext() { return *m_StateContext; }
+
+ void SEditorImpl::SetTransactionManager(STransactionManagerImpl &manager)
+ {
+ m_TransactionManager = &manager;
+ }
+
+ bool IsLegalHistoryTarget(StateNodeTypes::Enum inType)
+ {
+ return inType == StateNodeTypes::State || inType == StateNodeTypes::Final
+ || inType == StateNodeTypes::Parallel;
+ }
+
+ void RecurseGetChildrenForHistoryTarget(SState &inNode,
+ eastl::vector<CRegisteredString> &retval)
+ {
+ for (TStateNodeList::iterator iter = inNode.m_Children.begin(),
+ end = inNode.m_Children.end();
+ iter != end; ++iter) {
+ if (IsLegalHistoryTarget(iter->m_Type)) {
+ retval.push_back(iter->m_Id);
+ if (iter->m_Type == StateNodeTypes::State)
+ RecurseGetChildrenForHistoryTarget(static_cast<SState &>(*iter), retval);
+ }
+ }
+ }
+
+ eastl::vector<CRegisteredString> SEditorImpl::GetLegalHistoryDefaultValues(SHistory &inData)
+ {
+ eastl::vector<CRegisteredString> retval;
+ if (inData.m_Parent && inData.m_Parent->m_Type == StateNodeTypes::State) {
+ SState &theState = static_cast<SState &>(*inData.m_Parent);
+ for (TStateNodeList::iterator iter = theState.m_Children.begin(),
+ end = theState.m_Children.end();
+ iter != end; ++iter) {
+ if (IsLegalHistoryTarget(iter->m_Type)) {
+ retval.push_back(iter->m_Id);
+ if (inData.m_Flags.IsDeep()) {
+ if (iter->m_Type == StateNodeTypes::State)
+ RecurseGetChildrenForHistoryTarget(static_cast<SState &>(*iter),
+ retval);
+ }
+ }
+ }
+ }
+ return retval;
+ }
+
+ void RecurseGetLegalParents(eastl::vector<CRegisteredString> &outResult,
+ SStateNode &inTarget, SStateNode &inCurrent)
+ {
+ // Basic checks
+ if (inCurrent.m_Type == StateNodeTypes::History
+ || inCurrent.m_Type == StateNodeTypes::Final || &inCurrent == &inTarget)
+ return;
+
+ // Parallel's cannot have finals, but their children could
+ bool isIllegalChild = (inTarget.m_Type == StateNodeTypes::Final
+ && inCurrent.m_Type == StateNodeTypes::Parallel)
+ || inCurrent.m_Type == StateNodeTypes::SCXML;
+
+ if (isIllegalChild == false) {
+ outResult.push_back(inCurrent.m_Id);
+ }
+ TStateNodeList *children = inCurrent.GetChildren();
+ if (children) {
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter) {
+ RecurseGetLegalParents(outResult, inTarget, *iter);
+ }
+ }
+ }
+
+ static bool lexi(CRegisteredString lhs, CRegisteredString rhs)
+ {
+ return strcmp(lhs.c_str(), rhs.c_str()) < 0;
+ }
+
+ eastl::vector<CRegisteredString> SEditorImpl::GetLegalParentIds(SStateNode &inNode)
+ {
+ // Do a depth first search and just do not include this node or any history or final
+ // nodes.
+ eastl::vector<CRegisteredString> retval;
+ RecurseGetLegalParents(retval, inNode, *m_StateContext->GetRoot());
+ eastl::sort(retval.begin(), retval.end(), lexi);
+ return retval;
+ }
+
+ struct SParentChange : public IChange
+ {
+ TObjPtr m_ChildObj;
+ TStateNodeList *m_OldList;
+ TStateNodeList &m_NewList;
+ SStateNode *m_OldParent;
+ SStateNode &m_NewParent;
+ SStateNode &m_Child;
+ QT3DSI32 m_RefCount;
+ SParentChange(TObjPtr childObj, TStateNodeList *oldL, TStateNodeList &newL,
+ SStateNode *oldp, SStateNode &newp, SStateNode &c)
+ : m_ChildObj(childObj)
+ , m_OldList(oldL)
+ , m_NewList(newL)
+ , m_OldParent(oldp)
+ , m_NewParent(newp)
+ , m_Child(c)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+
+ virtual void Do()
+ {
+ if (m_OldList)
+ m_OldList->remove(m_Child);
+ m_NewList.push_back(m_Child);
+ m_Child.m_Parent = &m_NewParent;
+ }
+ virtual void Undo()
+ {
+ m_NewList.remove(m_Child);
+ if (m_OldList)
+ m_OldList->push_back(m_Child);
+ m_Child.m_Parent = m_OldParent;
+ }
+
+ virtual TObjPtr GetEditor() { return m_ChildObj; }
+ };
+
+ void SEditorImpl::SetParent(SStateNode &inNode, const Option<SValue> &inValue)
+ {
+ STransaction *theTransaction = m_TransactionManager->GetOpenTransactionImpl();
+ SStateNode *oldParent = inNode.m_Parent;
+ TEditorStr newParentId;
+ if (inValue.hasValue())
+ newParentId = inValue->getData<TEditorStr>();
+
+ SStateNode *newParent =
+ m_StateContext->FindStateNode(m_StringTable->RegisterStr(newParentId.c_str()));
+ if (newParent == NULL)
+ newParent = m_StateContext->GetRoot();
+ TStateNodeList *newList = newParent->GetChildren();
+ if (newList == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SParentChange *theChange =
+ new SParentChange(ToEditor(inNode), oldParent ? oldParent->GetChildren() : NULL,
+ *newList, oldParent, *newParent, inNode);
+ theChange->Do();
+ if (theTransaction) {
+ theTransaction->m_Changes.push_back(theChange);
+ if (oldParent)
+ theTransaction->m_Changes.push_back(new SChange(*ToEditor(*oldParent)));
+ theTransaction->m_Changes.push_back(new SChange(*ToEditor(*newParent)));
+ }
+ CheckAndSetValidHistoryDefault(ToEditor(inNode));
+ // Fix the initial state of the old parent if it exists
+ if (oldParent) {
+ if (isTrivial(oldParent->GetInitialExpression())
+ && oldParent->GetInitialTransition()) {
+ STransition *theTransition = oldParent->GetInitialTransition();
+ if (theTransition != NULL && theTransition->m_Target.size()) {
+ bool foundItem = false;
+ for (QT3DSU32 idx = 0, end = theTransition->m_Target.size();
+ idx < end && foundItem == false; ++idx) {
+ if (theTransition->m_Target[idx] == &inNode)
+ foundItem = true;
+ }
+ if (foundItem) {
+ SetInitialAttribute(SValue(TEditorStr()), *oldParent);
+ }
+ }
+ }
+ // fix all history nodes
+ TStateNodeList *parentChildren = oldParent->GetChildren();
+ if (parentChildren) {
+ for (TStateNodeList::iterator iter = parentChildren->begin(),
+ end = parentChildren->end();
+ iter != end; ++iter) {
+ if (iter->m_Type == StateNodeTypes::History) {
+ CheckAndSetValidHistoryDefault(ToEditor(*iter));
+ }
+ }
+ }
+ }
+ // Set the new object inside the new parent.
+ ToEditor(inNode)->SetPropertyValue("position", QT3DSVec2(0, 0));
+ }
+
+ void SEditorImpl::CheckAndSetValidHistoryDefault(TObjPtr inHistoryNode)
+ {
+ if (inHistoryNode && AreEqual(inHistoryNode->TypeName(), "history")) {
+ eastl::vector<CRegisteredString> validChildren =
+ inHistoryNode->GetLegalValues("default");
+ TObjList existing = inHistoryNode->GetPropertyValue("default")->getData<TObjList>();
+ if (existing.size()) {
+ // Ensure all of the existing nodes are in the valid children list.
+ bool allValid = true;
+ for (size_t existingIdx = 0, existingEnd = existing.size();
+ existingIdx < existingEnd && allValid; ++existingIdx) {
+ CRegisteredString idStr =
+ m_StringTable->RegisterStr(existing[existingIdx]->GetId().c_str());
+ if (eastl::find(validChildren.begin(), validChildren.end(), idStr)
+ == validChildren.end())
+ allValid = false;
+ }
+ if (allValid)
+ return;
+ }
+ SetValidHistoryDefault(inHistoryNode);
+ }
+ }
+
+ void SEditorImpl::SetValidHistoryDefault(TObjPtr inHistoryNode)
+ {
+ if (inHistoryNode && AreEqual(inHistoryNode->TypeName(), "history")) {
+ eastl::vector<CRegisteredString> legalValues =
+ inHistoryNode->GetLegalValues("default");
+ if (legalValues.size()) {
+ TObjPtr firstLegal = GetObjectById(legalValues[0]);
+ TObjList propValue;
+ propValue.push_back(firstLegal);
+ inHistoryNode->SetPropertyValue("default", propValue);
+ }
+ }
+ }
+
+ MallocAllocator SBaseEditorFoundation::g_BaseAlloc;
+
+ bool SPropertyDecNameFinder::operator()(const SPropertyDeclaration &dec) const
+ {
+ return AreEqual(m_NameStr, dec.m_Name.c_str());
+ }
+
+ void IEditorObject::Append(const char8_t *inPropName, TObjPtr inObj)
+ {
+ Option<SValue> theProp = GetPropertyValue(inPropName);
+ if (theProp.hasValue() && theProp->getType() == ValueTypes::ObjPtrList
+ && inObj != NULL) {
+ TObjList theData = theProp->getData<TObjList>();
+ theData.push_back(inObj);
+ SetPropertyValue(inPropName, theData);
+ }
+ }
+
+ void IEditorObject::Remove(const char8_t *inPropName, TObjPtr inObj)
+ {
+ Option<SValue> theProp = GetPropertyValue(inPropName);
+ if (theProp.hasValue() && theProp->getType() == ValueTypes::ObjPtrList
+ && inObj != NULL) {
+ TObjList theData = theProp->getData<TObjList>();
+ TObjList::iterator theFind = eastl::find(theData.begin(), theData.end(), inObj);
+ if (theFind != theData.end())
+ theData.erase(theFind);
+ SetPropertyValue(inPropName, theData);
+ }
+ }
+
+ IEditor &IEditor::CreateEditor()
+ {
+ TFoundationPtr theFoundation = SBaseEditorFoundation::Create();
+ return *QT3DS_NEW(theFoundation->getAllocator(), SEditorImpl)(
+ theFoundation, IStringTable::CreateStringTable(theFoundation->getAllocator()));
+ }
+
+ IEditor *IEditor::CreateEditor(const char8_t *inFname)
+ {
+ CFileSeekableIOStream theFile(inFname, FileReadFlags());
+ if (theFile.IsOpen() == false)
+ return NULL;
+
+ return CreateEditor(inFname, theFile);
+ }
+
+ IEditor *IEditor::CreateEditor(const char8_t *inFname, IInStream &inStream)
+ {
+ IEditor &theEditor(CreateEditor());
+ if (static_cast<SEditorImpl &>(theEditor).Load(inStream, inFname))
+ return &theEditor;
+
+ theEditor.release();
+ return NULL;
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditor.h b/src/Runtime/Source/UICState/Editor/UICStateEditor.h
new file mode 100644
index 00000000..9f089e93
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditor.h
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_H
+#define UIC_STATE_EDITOR_H
+#pragma once
+#include "UICState.h"
+#include "UICStateSignalConnection.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/TaggedPointer.h"
+#include "EASTL/vector.h"
+#include "EASTL/string.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "UICStateInterpreter.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ class IEditorObject;
+ typedef NVScopedRefCounted<IEditorObject> TObjPtr;
+ typedef eastl::vector<TObjPtr> TObjList;
+
+ class IEditorChangeListener
+ {
+ protected:
+ virtual ~IEditorChangeListener() {}
+ public:
+ // The same object may be represented multiple times in this list.
+ virtual void OnDataChange(const TObjList &inChangedObjects,
+ const TObjList &inRemovedObjects) = 0;
+ };
+
+ struct EditorPropertyTypes
+ {
+ enum Enum {
+ NoProperty = 0,
+ Event, // string
+ Id, // string
+ Object, // IEditorObject
+ ObjectList, // IEditorObject list
+ // A string, but one from a set of strings.
+ StringSet, // string
+ String, // string, single line
+ BigString, // string than may be multiple lines long
+ Position, // vec2
+ Dimension, // vec2
+ PositionList, // vector<QT3DSVec2>
+ Script, // string
+ Color,
+ Boolean,
+ U32,
+ };
+ };
+
+ struct SPropertyDeclaration
+ {
+ CRegisteredString m_Name;
+ EditorPropertyTypes::Enum m_Type;
+ // for enumerations, the list of enumerations
+ SPropertyDeclaration() {}
+ SPropertyDeclaration(CRegisteredString inName, EditorPropertyTypes::Enum inType)
+ : m_Name(inName)
+ , m_Type(inType)
+ {
+ }
+ };
+
+ typedef eastl::vector<SPropertyDeclaration> TPropertyDeclarationList;
+
+ struct SPropertyDecNameFinder
+ {
+ const char8_t *m_NameStr;
+ SPropertyDecNameFinder(const char8_t *nmStr)
+ : m_NameStr(nmStr)
+ {
+ }
+ // Implemented in UICStateEditor.cpp to include "foundation/Utils.h"
+ bool operator()(const SPropertyDeclaration &dec) const;
+ };
+
+ typedef eastl::vector<QT3DSVec2> TVec2List;
+ typedef eastl::string TEditorStr;
+ typedef eastl::vector<TEditorStr> TEditorStrList;
+
+ // Our generic discriminated union type for all property values.
+ struct SValue;
+ struct SValueOpt;
+
+ class IEditor;
+
+ class IEditorObject : public NVRefCounted
+ {
+ protected:
+ virtual ~IEditorObject() {}
+ const char8_t *m_TypeName;
+
+ public:
+ IEditorObject(const char8_t *tn)
+ : m_TypeName(tn)
+ {
+ }
+ const char8_t *TypeName() const { return m_TypeName; }
+ // implemented in UICStateEditor.cpp using getpropertyvalue.
+ virtual TEditorStr GetId() = 0;
+ virtual TEditorStr GetDescription() = 0;
+ virtual void SetId(const TEditorStr &inId) = 0;
+ virtual void SetDescription(const TEditorStr &inName) = 0;
+ // Things only have one canonical parent.
+ virtual TObjPtr Parent() = 0;
+
+ virtual void GetProperties(eastl::vector<SPropertyDeclaration> &outProperties) = 0;
+ virtual Option<SPropertyDeclaration> FindProperty(const char8_t *propName) = 0;
+ // The legal values for a property tend to be something that have to be calculated
+ // dynamically.
+ virtual eastl::vector<CRegisteredString> GetLegalValues(const char8_t *propName) = 0;
+
+ virtual Option<SValue> GetPropertyValue(const char8_t *inPropName) = 0;
+ virtual void SetPropertyValue(const char8_t *inPropName, const SValueOpt &inValue) = 0;
+ virtual bool endEdit() { return false; } // should SetPropertyValue end property edit
+
+ // Utility function implemented in UICStateEditor.cpp
+ virtual void Append(const char8_t *inPropName, TObjPtr inObj);
+ virtual void Remove(const char8_t *inPropName, TObjPtr inObj);
+
+ // Remove this from any parents. Remove any transitions pointing to this.
+ // Only works for state-node derived types.
+ // Executable content, onEntry onExit and such will not work with this.
+ // Also removes this item id from the id map. This is what is used to delete objects.
+ // Do not reattach yourself; callers should release all references to this object after
+ // calling
+ // this.
+ virtual void RemoveObjectFromGraph() = 0;
+
+ // Internal calls, don't call externally
+ virtual void RemoveIdFromContext() = 0;
+ virtual void AddIdToContext() = 0;
+
+ // Most things do not have any executable content.
+ virtual NVConstDataRef<InterpreterEventTypes::Enum> GetExecutableContentTypes()
+ {
+ return NVConstDataRef<InterpreterEventTypes::Enum>();
+ }
+
+ // Be aware that there are more types of executable content than indicated in the store;
+ // a lot more.
+ // So just ignore the types the story ignores.
+ virtual TObjList GetExecutableContent(InterpreterEventTypes::Enum /*inType*/)
+ {
+ return TObjList();
+ }
+
+ // inName can be an executable content:
+ //'script', 'send', 'cancel'
+ virtual TObjPtr CreateAndAppendExecutableContent(InterpreterEventTypes::Enum /*inType*/,
+ const char8_t * /*inName*/)
+ {
+ return TObjPtr();
+ }
+
+ virtual IEditor &GetEditor() = 0;
+ };
+
+ class ITransaction : public NVRefCounted
+ {
+ protected:
+ virtual ~ITransaction() {}
+ TEditorStr m_Name;
+
+ public:
+ ITransaction(const TEditorStr inName = TEditorStr())
+ : m_Name(inName)
+ {
+ }
+ TEditorStr GetName() const { return m_Name; }
+ // Send the signals collected during the creation of this transaction
+ virtual void SendDoSignals() = 0;
+ virtual TObjList GetEditedObjects() = 0;
+ virtual void Do() = 0;
+ virtual void Undo() = 0;
+ virtual bool Empty() = 0;
+ };
+
+ typedef NVScopedRefCounted<ITransaction> TTransactionPtr;
+
+ class ITransactionManager : public NVRefCounted
+ {
+ protected:
+ virtual ~ITransactionManager() {}
+ public:
+ virtual TSignalConnectionPtr AddChangeListener(IEditorChangeListener &inListener) = 0;
+ // Undo/redo is supported via a transparent transaction system.
+ // calls are reentrant but last call will close the transaction object.
+ // Any changes to any editor objects will go through this transaction when they happen.
+ virtual TTransactionPtr BeginTransaction(const TEditorStr &inName = TEditorStr()) = 0;
+ virtual TTransactionPtr GetOpenTransaction() = 0;
+ virtual void RollbackTransaction() = 0;
+ virtual void EndTransaction() = 0;
+ };
+
+ // Editor interface to a UICState dataset
+ class IEditor : public ITransactionManager
+ {
+ protected:
+ virtual ~IEditor() {}
+ public:
+ // Traditional editor interface.
+ virtual TObjPtr GetRoot() = 0;
+ // You can force the id to be a particular ID in some cases, this is useful for testing.
+ // ID is ignored for objects that don't have an id.
+ virtual TObjPtr Create(const char8_t *inTypeName, const char8_t *inId = 0) = 0;
+ virtual TObjPtr GetOrCreate(SSCXML &inData) = 0;
+ virtual TObjPtr GetOrCreate(SState &inData) = 0;
+ virtual TObjPtr GetOrCreate(STransition &inData) = 0;
+ virtual TObjPtr GetOrCreate(SParallel &inData) = 0;
+ virtual TObjPtr GetOrCreate(SHistory &inData) = 0;
+ virtual TObjPtr GetOrCreate(SFinal &inData) = 0;
+ virtual TObjPtr GetOrCreate(SDataModel &inData) = 0;
+ virtual TObjPtr GetOrCreate(SData &inData) = 0;
+ virtual TObjPtr ToEditor(SStateNode &inItem) = 0;
+
+ // Get a particular object by id. Useful in testing scenarios.
+ virtual TObjPtr GetObjectById(const char8_t *inId) = 0;
+
+ // Get an editor, if it already has been created, for this piece of graph data.
+ // Note that if it has not been created, this function couldn't possibly create it
+ // due to lack of type information.
+ virtual TObjPtr GetEditor(void *inGraphData) = 0;
+
+ // Copy save a subgraph to a string. Converts all top level positions to be relative to
+ // mouse pos.
+ virtual TEditorStr Copy(TObjList inObjects, const QT3DSVec2 &inMousePos) = 0;
+ virtual bool CanPaste(TObjPtr inTarget) = 0;
+ // Paste in, adding relative pos to all top level positions.
+ virtual void Paste(const TEditorStr &inCopiedObjects, TObjPtr inTarget,
+ const QT3DSVec2 &inRelativePos) = 0;
+
+ virtual TObjPtr GetLeastCommonAncestor(NVConstDataRef<TObjPtr> inObjects) = 0;
+
+ // Returns the list of send ids that have a delay on them.
+ virtual TObjList GetCancelableSendIds() = 0;
+
+ // Return the set of events in use in the state machine.
+ virtual TEditorStrList GetStateMachineEvents() = 0;
+
+ // Change content from one type to another.
+ virtual TObjPtr ChangeExecutableContentType(TObjPtr inContent,
+ const char8_t *newType) = 0;
+
+ virtual TEditorStr ToXML(TObjPtr inContent) = 0;
+ // Returns the error from parsing the xml or if everything went correctly replaces
+ // inContent
+ // with the result of parsing the xml and returns the new content.
+ virtual eastl::pair<TEditorStr, TObjPtr> FromXML(TObjPtr inContent,
+ const TEditorStr &ioEditedXML) = 0;
+
+ virtual bool Save(const char8_t *inFname) = 0;
+ virtual void Save(IOutStream &inStream) = 0;
+
+ // This must be called on history creation once it has been added to the proper parent.
+ virtual void SetValidHistoryDefault(TObjPtr inHistoryNode) = 0;
+
+ static IEditor &CreateEditor();
+
+ static IEditor *CreateEditor(const char8_t *inFname);
+ static IEditor *CreateEditor(const char8_t *inFname, IInStream &inStream);
+ };
+
+ typedef NVScopedRefCounted<IEditor> TEditorPtr;
+
+ struct SEditorImplTransactionScope
+ {
+ ITransactionManager &m_Editor;
+ TTransactionPtr m_Transaction;
+ SEditorImplTransactionScope(ITransactionManager &inEditor)
+ : m_Editor(inEditor)
+ , m_Transaction(inEditor.BeginTransaction())
+ {
+ }
+ ~SEditorImplTransactionScope() { m_Editor.EndTransaction(); }
+
+ TTransactionPtr operator->() { return m_Transaction; }
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorEditorsImpl.h b/src/Runtime/Source/UICState/Editor/UICStateEditorEditorsImpl.h
new file mode 100644
index 00000000..01c5528e
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorEditorsImpl.h
@@ -0,0 +1,1772 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_EDITORS_IMPL_H
+#define UIC_STATE_EDITOR_EDITORS_IMPL_H
+#include "UICState.h"
+#include "UICStateEditor.h"
+#include "UICStateEditorValue.h"
+#include "UICStateEditorTransactionImpl.h"
+#include "UICStateTypes.h"
+#include "UICStateEditorFoundation.h"
+#include "UICStateEditorProperties.h"
+#include "foundation/Utils.h"
+#include "foundation/XML.h"
+#include "UICStateXMLIO.h"
+#include "foundation/IOStreams.h"
+#include "UICStateExecutionTypes.h"
+#include "UICStateContext.h"
+#include "UICStateEditorImpl.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ struct EditorTypes
+ {
+ enum Enum {
+ UnknownEditor = 0,
+ SCXML,
+ State,
+ Parallel,
+ Transition,
+ History,
+ Final,
+ ExecutableContent,
+ OnEntry,
+ OnExit,
+ Send,
+ Raise,
+ If,
+ Else,
+ ElseIf,
+ Log,
+ Assign,
+ Script,
+ DataModel,
+ Data,
+ Cancel,
+ };
+ };
+
+ struct SEditorImplObject : public IEditorObject
+ {
+ TFoundationPtr m_Foundation;
+ SEditorImpl &m_Editor;
+ volatile QT3DSI32 mRefCount;
+ eastl::string m_Id;
+ eastl::string m_Description;
+ Option<QT3DSVec3> m_Color;
+ TPropertyAccessorList m_PropertyAccessors;
+
+ static void CreateAccessors(SEditorImpl &inData, TPropertyAccessorList &outAccessors,
+ bool includeId, bool includeColor)
+ {
+ if (includeId)
+ outAccessors.push_back(CreateEditorAccessor(inData, &SEditorImplObject::m_Id,
+ "id", EditorPropertyTypes::String));
+
+ outAccessors.push_back(
+ CreateEditorAccessor(inData, &SEditorImplObject::m_Description, "description",
+ EditorPropertyTypes::String));
+ if (includeColor)
+ outAccessors.push_back(CreateEditorAccessor(
+ inData, &SEditorImplObject::m_Color, "color", EditorPropertyTypes::Color));
+ }
+
+ SEditorImplObject(const char8_t *tn, SEditorImpl &inData,
+ const TPropertyAccessorList &inAccessors)
+ : IEditorObject(tn)
+ , m_Foundation(inData.m_EditorFoundation)
+ , m_Editor(inData)
+ , mRefCount(0)
+ , m_PropertyAccessors(inAccessors)
+ {
+ }
+
+ IPropertyAccessor *FindPropertyAccessor(const char8_t *inName)
+ {
+ CRegisteredString nameStr = m_Editor.m_StringTable->RegisterStr(inName);
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx)
+ if (m_PropertyAccessors[idx]->m_Declaration.m_Name == nameStr)
+ return m_PropertyAccessors[idx].mPtr;
+ return NULL;
+ }
+
+ virtual void GetProperties(eastl::vector<SPropertyDeclaration> &outProperties)
+ {
+ outProperties.clear();
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx)
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ }
+
+ virtual Option<SPropertyDeclaration> FindProperty(const char8_t *propName)
+ {
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx) {
+ if (AreEqual(m_PropertyAccessors[idx]->m_Declaration.m_Name.c_str(), propName))
+ return m_PropertyAccessors[idx]->m_Declaration;
+ }
+ return Empty();
+ }
+
+ virtual eastl::vector<CRegisteredString> GetLegalValues(const char8_t *propName)
+ {
+ IPropertyAccessor *accessor = FindPropertyAccessor(propName);
+ if (accessor)
+ return accessor->GetLegalValues(*this);
+ return eastl::vector<CRegisteredString>();
+ }
+
+ virtual Option<SValue> GetPropertyValue(const char8_t *inPropName)
+ {
+ IPropertyAccessor *accessor = FindPropertyAccessor(inPropName);
+ if (accessor) {
+ return accessor->Get(*this);
+ }
+ return Empty();
+ }
+ virtual void SetPropertyValue(const char8_t *inPropName, const SValueOpt &inValue)
+ {
+ IPropertyAccessor *accessor = FindPropertyAccessor(inPropName);
+ if (accessor) {
+ if (accessor->HandlesTransaction() == false) {
+ STransaction *theTransaction = m_Editor.GetOpenTransactionImpl();
+ if (theTransaction) {
+ Option<SValue> existing = accessor->Get(*this);
+ theTransaction->m_Changes.push_back(
+ new SChange(existing, inValue, *accessor, *this));
+ }
+ }
+ accessor->Set(*this, inValue);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ virtual TEditorStr GetId()
+ {
+ Option<SValue> propValue = GetPropertyValue("id");
+ if (propValue.hasValue())
+ return propValue->getData<TEditorStr>();
+ return TEditorStr();
+ }
+ virtual TEditorStr GetDescription() { return m_Description; }
+ // We have to go through the SPV interface to take transactions into account.
+
+ virtual void SetId(const TEditorStr &inName) { SetPropertyValue("id", SValue(inName)); }
+ virtual void SetDescription(const TEditorStr &inName)
+ {
+ SetPropertyValue("description", SValue(inName));
+ }
+
+ virtual TObjPtr Parent() { return TObjPtr(); }
+ virtual void RemoveObjectFromGraph() { QT3DS_ASSERT(false); }
+
+ virtual IEditor &GetEditor() { return m_Editor; }
+ };
+
+#define UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE \
+ void addRef() { atomicIncrement(&mRefCount); } \
+ void release() \
+ { \
+ TFoundationPtr fnd(m_Foundation); \
+ /*Ensure the editor sticks around till *after* we are gone. */ \
+ /*This is because our objects will keep several bits of the editor around */ \
+ QT3DS_IMPLEMENT_REF_COUNT_RELEASE(m_Foundation->getAllocator()); \
+ }
+
+ struct SSCXMLEditor : public SEditorImplObject
+ {
+ typedef SSCXML TStateType;
+ enum { EditorType = EditorTypes::SCXML };
+
+ SSCXML &m_Data;
+ eastl::string m_InitialComboValue;
+ bool m_endEdit;
+
+ static const char8_t *GetTypeStr() { return "scxml"; }
+
+ static TPropertyAccessorList CreateAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ typedef SDataProp<SSCXMLEditor, SSCXML, STransition *> TInitialProp;
+ typedef SFlagBooleanProperty<SSCXMLEditor, SSCXMLFlags> TBindingProp;
+ TPropertyAccessorList &retval(inList);
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+ typedef SDataProp<SSCXMLEditor, SSCXML, CRegisteredString> TNameProp;
+ typedef SInitialComboProp<SSCXMLEditor, SSCXML> TInitialComboProp;
+ typedef SDataProp<SSCXMLEditor, SSCXML, const char8_t *> TCharProp;
+ IPropertyAccessor *newAccessor =
+ QT3DS_NEW(alloc, TNameProp)(inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("name"),
+ EditorPropertyTypes::String),
+ &SSCXML::m_Name);
+ retval.push_back(newAccessor);
+ retval.push_back(CreateEditorAccessor(inEditorData,
+ &SEditorImplObject::m_Description,
+ "description", EditorPropertyTypes::String));
+ newAccessor = QT3DS_NEW(alloc, TBindingProp)(
+ inEditorData.m_EditorFoundation, *inEditorData.m_StringTable, "binding",
+ "early", "late", &SSCXMLFlags::IsLateBinding, &SSCXMLFlags::SetLateBinding);
+ retval.push_back(newAccessor);
+
+ TInitialComboProp *theInitialCombo = QT3DS_NEW(alloc, TInitialComboProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("initial"),
+ EditorPropertyTypes::StringSet));
+ retval.push_back(theInitialCombo);
+
+ TCharProp *theInitialExprProp = QT3DS_NEW(alloc, TCharProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("initialexpr"),
+ EditorPropertyTypes::BigString),
+ &SSCXML::m_InitialExpr);
+ retval.push_back(theInitialExprProp);
+
+ retval.push_back(CreateDataAccessor<SSCXMLEditor>(
+ inEditorData, &SSCXML::m_DataModel, "datamodel", EditorPropertyTypes::Object));
+ newAccessor = QT3DS_NEW(alloc, SChildrenProperty<SSCXMLEditor>)(
+ inEditorData.m_EditorFoundation, *inEditorData.m_StringTable);
+ retval.push_back(newAccessor);
+ // Replace the name property with one that writes to our data
+ return retval;
+ }
+
+ SSCXMLEditor(SSCXML &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SEditorImplObject(GetTypeStr(), inEditorData,
+ CreateAccessors(inEditorData, inList))
+ , m_Data(inData)
+ , m_endEdit(false)
+ {
+ }
+
+ void ApplyInitial(const TEditorStr &comboValue)
+ {
+ m_endEdit = false;
+
+ if (m_InitialComboValue == "(script expression)"
+ || comboValue == "(script expression)")
+ m_endEdit = true;
+
+ m_InitialComboValue = comboValue;
+ }
+
+ virtual bool endEdit()
+ {
+ bool bTemp = m_endEdit;
+ m_endEdit = false;
+ return bTemp;
+ }
+
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual void RemoveObjectFromGraph() { QT3DS_ASSERT(false); }
+
+ virtual void RemoveIdFromContext() { m_Editor.GetStateContext().EraseId(m_Data.m_Id); }
+
+ virtual void AddIdToContext()
+ {
+ if (m_Data.m_Id.IsValid())
+ m_Editor.GetStateContext().InsertId(m_Data.m_Id, &m_Data);
+ }
+
+ virtual void GetProperties(eastl::vector<SPropertyDeclaration> &outProperties)
+ {
+ outProperties.clear();
+ eastl::vector<CRegisteredString> temp;
+ m_Editor.GetLegalInitialValues(m_Data, temp);
+ bool hasInitialState = temp.size() > 1;
+ bool hasInitialExpr = false;
+ CRegisteredString nameStr = m_Editor.RegisterStr("initial");
+ CRegisteredString initialExprStr = m_Editor.RegisterStr("initialexpr");
+
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx) {
+ if (m_PropertyAccessors[idx]->m_Declaration.m_Name == nameStr) {
+ if (hasInitialState)
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ } else if (m_PropertyAccessors[idx]->m_Declaration.m_Name == initialExprStr) {
+ if (hasInitialExpr)
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ } else {
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ }
+
+ if (m_PropertyAccessors[idx]->m_Declaration.m_Name == nameStr) {
+ TEditorStr initialValue =
+ m_PropertyAccessors[idx]->Get(*this)->getData<TEditorStr>();
+ if (initialValue == "(script expression)")
+ hasInitialExpr = true;
+ }
+ }
+ }
+ };
+
+ struct SPositionalEditor : public SEditorImplObject
+ {
+ SPositionalEditor(const char8_t *inTypeName, SEditorImpl &inData,
+ const TPropertyAccessorList &inAccessors)
+ : SEditorImplObject(inTypeName, inData, inAccessors)
+ {
+ }
+ };
+
+ template <typename TListType, typename TListItem>
+ struct TListInsertDeleteChange : public IChange
+ {
+ TObjPtr m_EditorObject;
+ QT3DSI32 mRefCount;
+ TListType *m_ParentList;
+ TListItem *m_TargetContent;
+ QT3DSI32 m_ContentIdx;
+ bool m_AddOnDo;
+ // The item must be in the list for this to work.
+ TListInsertDeleteChange(TObjPtr inEditor, TListType *plist, TListItem *tc, bool addOnDo)
+ : m_EditorObject(inEditor)
+ , mRefCount(0)
+ , m_ParentList(plist)
+ , m_TargetContent(tc)
+ , m_ContentIdx(-1)
+ , m_AddOnDo(addOnDo)
+ {
+ for (typename TListType::iterator iter = m_ParentList->begin(),
+ end = m_ParentList->end();
+ iter != end; ++iter) {
+ if (&(*iter) == m_TargetContent)
+ break;
+ // setup content idx to point to the item just our target item.
+ ++m_ContentIdx;
+ }
+ }
+ virtual void addRef() { atomicIncrement(&mRefCount); }
+ virtual void release()
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0) {
+ delete this;
+ }
+ }
+ void add()
+ {
+ if (m_ContentIdx > -1) {
+ QT3DSI32 idx = m_ContentIdx - 1;
+ typename TListType::iterator iter = m_ParentList->begin();
+
+ for (typename TListType::iterator end = m_ParentList->end();
+ iter != end && idx > -1; ++iter, --idx) {
+ };
+
+ if (iter != m_ParentList->end())
+ m_ParentList->insert_after(*iter, *m_TargetContent);
+ else
+ m_ParentList->push_back(*m_TargetContent);
+ } else
+ m_ParentList->push_front(*m_TargetContent);
+ }
+ void remove() { m_ParentList->remove(*m_TargetContent); }
+
+ virtual void Do()
+ {
+ if (m_AddOnDo)
+ add();
+ else
+ remove();
+ }
+ virtual void Undo()
+ {
+ if (m_AddOnDo)
+ remove();
+ else
+ add();
+ }
+ virtual TObjPtr GetEditor() { return m_EditorObject; }
+ };
+
+ struct SExecutableContentChange
+ : public TListInsertDeleteChange<TExecutableContentList, SExecutableContent>
+ {
+ typedef TListInsertDeleteChange<TExecutableContentList, SExecutableContent> TBase;
+ SExecutableContentChange(TObjPtr inEditor, TExecutableContentList *plist,
+ SExecutableContent *tc, bool addOnDo)
+ : TBase(inEditor, plist, tc, addOnDo)
+ {
+ }
+ };
+
+ struct SStateEditor : public SPositionalEditor
+ {
+ typedef SState TStateType;
+ enum { EditorType = EditorTypes::State };
+ SState &m_Data;
+ eastl::string m_InitialComboValue;
+ bool m_endEdit;
+ static const char8_t *GetTypeStr() { return "state"; }
+
+ template <typename TEditorType>
+ static void CreateStateNodeChildren(SEditorImpl &inEditorData,
+ TPropertyAccessorList &retval)
+ {
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+ IPropertyAccessor *newAccessor = QT3DS_NEW(alloc, SChildrenProperty<TEditorType>)(
+ inEditorData.m_EditorFoundation, *inEditorData.m_StringTable);
+ retval.push_back(newAccessor);
+ }
+
+ template <typename TEditorType>
+ static void CreatePositionColorAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &retval)
+ {
+ typedef SOptionAccessorProp<TEditorType, SStateNode, QT3DSVec2> TVec2Access;
+ typedef SOptionAccessorProp<TEditorType, SStateNode, QT3DSVec3> TVec3Access;
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+ retval.push_back(QT3DS_NEW(alloc, TVec2Access)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("position"),
+ EditorPropertyTypes::Position),
+ &SStateNode::GetPosition, &SStateNode::SetPosition));
+ retval.push_back(QT3DS_NEW(alloc, TVec2Access)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("dimension"),
+ EditorPropertyTypes::Position),
+ &SStateNode::GetDimension, &SStateNode::SetDimension));
+
+ retval.push_back(QT3DS_NEW(alloc, TVec3Access)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("color"),
+ EditorPropertyTypes::Color),
+ &SStateNode::GetColor, &SStateNode::SetColor));
+ }
+
+ static TPropertyAccessorList CreateAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ typedef SDataProp<SStateEditor, SState, STransition *> TInitialProp;
+ typedef SDataIdProp<SStateEditor, SState> TIdPropType;
+ typedef SInitialTargetProp<SStateEditor, SState> TInitialTargetProp;
+ typedef SInitialComboProp<SStateEditor, SState> TInitialComboProp;
+ typedef SDataProp<SStateEditor, SState, const char8_t *> TCharProp;
+
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(QT3DS_NEW(alloc, TIdPropType)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("id"), EditorPropertyTypes::Id),
+ &SState::m_Id));
+
+ typedef SParentProp<SStateEditor> TParentPropType;
+ retval.push_back(QT3DS_NEW(alloc, TParentPropType)(inEditorData.m_EditorFoundation,
+ *inEditorData.m_StringTable));
+ SEditorImplObject::CreateAccessors(inEditorData, retval, false, false);
+
+ TInitialComboProp *theInitialCombo = QT3DS_NEW(alloc, TInitialComboProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("initial"),
+ EditorPropertyTypes::StringSet));
+ retval.push_back(theInitialCombo);
+
+ TCharProp *theInitialExprProp = QT3DS_NEW(alloc, TCharProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("initialexpr"),
+ EditorPropertyTypes::BigString),
+ &SState::m_InitialExpr);
+ retval.push_back(theInitialExprProp);
+ retval.push_back(CreateDataAccessor<SStateEditor>(
+ inEditorData, &SState::m_DataModel, "datamodel", EditorPropertyTypes::Object));
+ CreateStateNodeChildren<SStateEditor>(inEditorData, retval);
+ CreatePositionColorAccessors<SStateEditor>(inEditorData, retval);
+ retval.push_back(QT3DS_NEW(alloc, TInitialTargetProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("is initial target"),
+ EditorPropertyTypes::Boolean)));
+ // Replace the name property with one that writes to our data
+ return retval;
+ }
+ SStateEditor(SState &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SPositionalEditor(GetTypeStr(), inEditorData,
+ CreateAccessors(inEditorData, inList))
+ , m_Data(inData)
+ , m_endEdit(false)
+ {
+ }
+
+ virtual void GetProperties(eastl::vector<SPropertyDeclaration> &outProperties)
+ {
+ outProperties.clear();
+ eastl::vector<CRegisteredString> temp;
+ m_Editor.GetLegalInitialValues(m_Data, temp);
+ bool hasInitialState = temp.size() > 1;
+ bool hasInitialExpr = false;
+ CRegisteredString nameStr = m_Editor.RegisterStr("initial");
+ CRegisteredString initialExprStr = m_Editor.RegisterStr("initialexpr");
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx) {
+ if (m_PropertyAccessors[idx]->m_Declaration.m_Name == nameStr) {
+ if (hasInitialState)
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ } else if (m_PropertyAccessors[idx]->m_Declaration.m_Name == initialExprStr) {
+ if (hasInitialExpr)
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ } else
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+
+ if (hasInitialState
+ && m_PropertyAccessors[idx]->m_Declaration.m_Name == nameStr) {
+ TEditorStr initialValue =
+ m_PropertyAccessors[idx]->Get(*this)->getData<TEditorStr>();
+ if (initialValue == "(script expression)")
+ hasInitialExpr = true;
+ }
+ }
+ }
+
+ void ApplyInitial(const TEditorStr &comboValue)
+ {
+ m_endEdit = false;
+
+ if (m_InitialComboValue == "(script expression)"
+ || comboValue == "(script expression)")
+ m_endEdit = true;
+
+ m_InitialComboValue = comboValue;
+ }
+
+ virtual bool endEdit()
+ {
+ bool bTemp = m_endEdit;
+ m_endEdit = false;
+ return bTemp;
+ }
+
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+ virtual void RemoveIdFromContext() { m_Editor.GetStateContext().EraseId(m_Data.m_Id); }
+ virtual void AddIdToContext()
+ {
+ if (m_Data.m_Id.IsValid())
+ m_Editor.GetStateContext().InsertId(m_Data.m_Id, &m_Data);
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ struct SObjListContains
+ {
+ const TObjList &m_Targets;
+ SObjListContains(const TObjList &t)
+ : m_Targets(t)
+ {
+ }
+ bool operator()(const TObjPtr &inObj) const
+ {
+ return eastl::find(m_Targets.begin(), m_Targets.end(), inObj.mPtr)
+ != m_Targets.end();
+ }
+ };
+
+ static void CheckAndRemoveStateFromTransitionProperty(TObjList &removedItems,
+ IEditorObject &inEditorObj,
+ const char8_t *propName)
+ {
+ Option<SValue> propVal = inEditorObj.GetPropertyValue(propName);
+ if (propVal.hasValue()) {
+ if (propVal->getType() == ValueTypes::ObjPtr) {
+ TObjPtr transProp = propVal->getData<TObjPtr>();
+ if (transProp) {
+ TObjList propValValues =
+ transProp->GetPropertyValue("target")->getData<TObjList>();
+ TObjList::iterator lastIter =
+ eastl::remove_if(propValValues.begin(), propValValues.end(),
+ SObjListContains(removedItems));
+ if (lastIter != propValValues.end()) {
+ propValValues.erase(lastIter, propValValues.end());
+ if (propValValues.empty())
+ inEditorObj.SetPropertyValue(propName, TObjPtr());
+ else
+ transProp->SetPropertyValue("target", propValValues);
+ }
+ }
+ } else if (propVal->getType() == ValueTypes::String) {
+ TEditorStr theIdStr = propVal->getData<TEditorStr>();
+ for (size_t idx = 0, end = removedItems.size(); idx < end; ++idx) {
+ if (removedItems[idx]->GetId() == theIdStr) {
+ inEditorObj.SetPropertyValue(propName, TEditorStr());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ static void RemoveTransitionsPointingTo(TObjList &removedItems,
+ IEditorObject &inEditorObj)
+ {
+ if (AreEqual(inEditorObj.TypeName(), "transition")) {
+ TObjList targets = inEditorObj.GetPropertyValue("target")->getData<TObjList>();
+ TObjList::iterator lastIter = eastl::remove_if(targets.begin(), targets.end(),
+ SObjListContains(removedItems));
+ if (lastIter != targets.end()) {
+ targets.erase(lastIter, targets.end());
+ inEditorObj.SetPropertyValue("target", targets);
+ if (targets.size() == 0)
+ inEditorObj.RemoveObjectFromGraph();
+ }
+ } else {
+ // state and parallel
+ CheckAndRemoveStateFromTransitionProperty(removedItems, inEditorObj, "initial");
+ // history
+ CheckAndRemoveStateFromTransitionProperty(removedItems, inEditorObj,
+ "transition");
+ }
+ Option<SValue> childListOpt = inEditorObj.GetPropertyValue("children");
+ if (childListOpt.hasValue()) {
+ TObjList childList = childListOpt->getData<TObjList>();
+ for (size_t idx = 0, end = childList.size(); idx < end; ++idx)
+ RemoveTransitionsPointingTo(removedItems, *childList[idx]);
+ }
+ }
+ static void RemoveObjectFromGraph(IEditorObject &inEditorObj,
+ TObjList &outRemovedObjects)
+ {
+ TObjPtr parentPtr = inEditorObj.Parent();
+ outRemovedObjects.push_back(&inEditorObj);
+ if (parentPtr)
+ parentPtr->Remove("children", &inEditorObj);
+
+ Option<SValue> nodeChildrenOpt = inEditorObj.GetPropertyValue("children");
+ if (nodeChildrenOpt.hasValue()) {
+ TObjList nodeChildren(nodeChildrenOpt->getData<TObjList>());
+ for (size_t idx = 0, end = nodeChildren.size(); idx < end; ++idx)
+ RemoveObjectFromGraph(*nodeChildren[idx], outRemovedObjects);
+ }
+ }
+
+ virtual TObjPtr Parent() { return m_Editor.ToEditor(m_Data.m_Parent); }
+
+ // Simple and slow as hell.
+ static void RemoveObjectFromGraph(SEditorImplObject &inEditorObj)
+ {
+ TObjList removedItems;
+ TObjPtr oldParent = inEditorObj.Parent();
+ RemoveObjectFromGraph(inEditorObj, removedItems);
+ RemoveTransitionsPointingTo(removedItems, *inEditorObj.m_Editor.GetRoot());
+ for (size_t idx = 0, end = removedItems.size(); idx < end; ++idx) {
+ inEditorObj.m_Editor.m_TransactionManager->OnObjectDeleted(removedItems[idx]);
+ inEditorObj.RemoveIdFromContext();
+ }
+ if (oldParent) {
+ TObjList children =
+ oldParent->GetPropertyValue("children")->getData<TObjList>();
+ for (size_t childIdx = 0, childEnd = children.size(); childIdx < childEnd;
+ ++childIdx) {
+ inEditorObj.m_Editor.CheckAndSetValidHistoryDefault(children[childIdx]);
+ }
+ }
+ }
+
+ virtual void RemoveObjectFromGraph() { RemoveObjectFromGraph(*this); }
+
+ virtual TEditorStr GetId() { return m_Data.m_Id.c_str(); }
+
+ virtual NVConstDataRef<InterpreterEventTypes::Enum> GetExecutableContentTypes()
+ {
+ static InterpreterEventTypes::Enum retval[] = { InterpreterEventTypes::StateEnter,
+ InterpreterEventTypes::StateExit };
+ return toConstDataRef(retval, 2);
+ }
+
+ template <typename TListType>
+ static TObjList ListDataToEditor(TListType &inList, SEditorImplObject &ioObj)
+ {
+ TObjList retval;
+ typename TListType::iterator iter = inList.begin();
+ // Take the first one.
+ if (iter != inList.end()) {
+ for (TExecutableContentList::iterator
+ contentIter = iter->m_ExecutableContent.begin(),
+ contentEnd = iter->m_ExecutableContent.end();
+ contentIter != contentEnd; ++contentIter) {
+ TObjPtr editorData = ioObj.m_Editor.ExecutableContentToEditor(*contentIter);
+ retval.push_back(editorData);
+ }
+ }
+ return retval;
+ }
+
+ static TObjList ListDataToEditor(InterpreterEventTypes::Enum inType,
+ SEntryExitBase &inItem, SEditorImplObject &ioObj)
+ {
+ switch (inType) {
+ case InterpreterEventTypes::StateEnter:
+ return ListDataToEditor(inItem.m_OnEntry, ioObj);
+ case InterpreterEventTypes::StateExit:
+ return ListDataToEditor(inItem.m_OnExit, ioObj);
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return TObjList();
+ }
+
+ virtual TObjList GetExecutableContent(InterpreterEventTypes::Enum inType)
+ {
+ return SStateEditor::ListDataToEditor(inType, m_Data, *this);
+ }
+
+ template <typename TListItemType, typename TListType>
+ static TObjPtr DoCreateAppendExecutableContent(SEditorImplObject &inObj,
+ TListType &inList, const char8_t *inName,
+ SStateNode &inNode)
+ {
+ NVScopedRefCounted<IChange> theNewListItemChange;
+ if (inList.empty()) {
+ TListItemType *newType =
+ QT3DS_NEW(inObj.m_Editor.m_AutoAllocator, TListItemType)();
+ inList.push_back(*newType);
+ theNewListItemChange = new TListInsertDeleteChange<TListType, TListItemType>(
+ inObj, &inList, newType, true);
+ }
+ TListItemType &theFront = *inList.begin();
+ TObjPtr retval = inObj.m_Editor.CreateExecutableContent(inNode, inName);
+ SExecutableContent *theContent = inObj.m_Editor.ExecutableContentFromEditor(retval);
+ theFront.m_ExecutableContent.push_back(*theContent);
+ if (inObj.m_Editor.GetOpenTransactionImpl()) {
+ if (theNewListItemChange)
+ inObj.m_Editor.GetOpenTransactionImpl()->m_Changes.push_back(
+ theNewListItemChange);
+
+ NVScopedRefCounted<SExecutableContentChange> newChange =
+ new SExecutableContentChange(inObj, &theFront.m_ExecutableContent,
+ theContent, true);
+ inObj.m_Editor.GetOpenTransactionImpl()->m_Changes.push_back(newChange.mPtr);
+ }
+ return retval;
+ }
+
+ static TObjPtr DoCreateAppendExecutableContent(InterpreterEventTypes::Enum inType,
+ const char8_t *inName,
+ SEditorImplObject &inObj,
+ SEntryExitBase &inItem)
+ {
+ switch (inType) {
+ case InterpreterEventTypes::StateEnter:
+ return DoCreateAppendExecutableContent<SOnEntry>(inObj, inItem.m_OnEntry,
+ inName, inItem);
+ case InterpreterEventTypes::StateExit:
+ return DoCreateAppendExecutableContent<SOnExit>(inObj, inItem.m_OnExit, inName,
+ inItem);
+ default:
+ break;
+ }
+
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ virtual TObjPtr CreateAndAppendExecutableContent(InterpreterEventTypes::Enum inType,
+ const char8_t *inName)
+ {
+ return SStateEditor::DoCreateAppendExecutableContent(inType, inName, *this, m_Data);
+ }
+ };
+
+ struct SParallelEditor : public SPositionalEditor
+ {
+ typedef SParallel TStateType;
+ enum { EditorType = EditorTypes::Parallel };
+ SParallel &m_Data;
+ static const char8_t *GetTypeStr() { return "parallel"; }
+
+ static TPropertyAccessorList CreateAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+
+ typedef SInitialTargetProp<SParallelEditor, SParallel> TInitialTargetProp;
+ TPropertyAccessorList &retval(inList);
+ typedef SDataIdProp<SParallelEditor, SParallel> TIdPropType;
+ typedef SParentProp<SParallelEditor> TParallelParentProp;
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+ retval.push_back(QT3DS_NEW(alloc, TIdPropType)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("id"), EditorPropertyTypes::Id),
+ &SParallel::m_Id));
+
+ retval.push_back(QT3DS_NEW(alloc, TParallelParentProp)(inEditorData.m_EditorFoundation,
+ *inEditorData.m_StringTable));
+
+ SEditorImplObject::CreateAccessors(inEditorData, retval, false, false);
+ retval.push_back(CreateDataAccessor<SParallelEditor>(
+ inEditorData, &SState::m_DataModel, "datamodel", EditorPropertyTypes::Object));
+ SStateEditor::CreateStateNodeChildren<SParallelEditor>(inEditorData, retval);
+ SStateEditor::CreatePositionColorAccessors<SParallelEditor>(inEditorData, retval);
+ // Replace the name property with one that writes to our data
+ retval.push_back(QT3DS_NEW(alloc, TInitialTargetProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("is initial target"),
+ EditorPropertyTypes::Boolean)));
+ return retval;
+ }
+
+ SParallelEditor(SParallel &inData, SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ : SPositionalEditor(GetTypeStr(), inEditorData,
+ CreateAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual TObjPtr Parent() { return m_Editor.ToEditor(m_Data.m_Parent); }
+
+ virtual void RemoveObjectFromGraph() { SStateEditor::RemoveObjectFromGraph(*this); }
+
+ virtual TEditorStr GetId() { return m_Data.m_Id.c_str(); }
+ virtual void RemoveIdFromContext() { m_Editor.GetStateContext().EraseId(m_Data.m_Id); }
+
+ virtual void AddIdToContext()
+ {
+ if (m_Data.m_Id.IsValid())
+ m_Editor.GetStateContext().InsertId(m_Data.m_Id, &m_Data);
+ }
+
+ virtual NVConstDataRef<InterpreterEventTypes::Enum> GetExecutableContentTypes()
+ {
+ static InterpreterEventTypes::Enum retval[] = { InterpreterEventTypes::StateEnter,
+ InterpreterEventTypes::StateExit };
+ return toConstDataRef(retval, 2);
+ }
+
+ virtual TObjList GetExecutableContent(InterpreterEventTypes::Enum inType)
+ {
+ return SStateEditor::ListDataToEditor(inType, m_Data, *this);
+ }
+
+ virtual TObjPtr CreateAndAppendExecutableContent(InterpreterEventTypes::Enum inType,
+ const char8_t *inName)
+ {
+ return SStateEditor::DoCreateAppendExecutableContent(inType, inName, *this, m_Data);
+ }
+ };
+
+ struct SFinalEditor : public SPositionalEditor
+ {
+ typedef SFinal TStateType;
+ enum { EditorType = EditorTypes::Final };
+
+ SFinal &m_Data;
+ static const char8_t *GetTypeStr() { return "final"; }
+
+ static TPropertyAccessorList CreateAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ typedef SDataIdProp<SFinalEditor, SFinal> TIdPropType;
+ typedef SInitialTargetProp<SFinalEditor, SFinal> TInitialTargetProp;
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+ typedef SParentProp<SFinalEditor> TFinalParentProp;
+ retval.push_back(QT3DS_NEW(alloc, TIdPropType)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("id"), EditorPropertyTypes::Id),
+ &SFinal::m_Id));
+ retval.push_back(QT3DS_NEW(alloc, TFinalParentProp)(inEditorData.m_EditorFoundation,
+ *inEditorData.m_StringTable));
+ SEditorImplObject::CreateAccessors(inEditorData, retval, false, false);
+ SStateEditor::CreatePositionColorAccessors<SFinalEditor>(inEditorData, retval);
+ retval.push_back(QT3DS_NEW(alloc, TInitialTargetProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("is initial target"),
+ EditorPropertyTypes::Boolean)));
+ // Replace the name property with one that writes to our data
+ return retval;
+ }
+
+ SFinalEditor(SFinal &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SPositionalEditor(GetTypeStr(), inEditorData,
+ CreateAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual TObjPtr Parent() { return m_Editor.ToEditor(m_Data.m_Parent); }
+
+ virtual void RemoveObjectFromGraph() { SStateEditor::RemoveObjectFromGraph(*this); }
+
+ virtual TEditorStr GetId() { return m_Data.m_Id.c_str(); }
+ virtual void RemoveIdFromContext() { m_Editor.GetStateContext().EraseId(m_Data.m_Id); }
+
+ virtual void AddIdToContext()
+ {
+ if (m_Data.m_Id.IsValid())
+ m_Editor.GetStateContext().InsertId(m_Data.m_Id, &m_Data);
+ }
+
+ virtual NVConstDataRef<InterpreterEventTypes::Enum> GetExecutableContentTypes()
+ {
+ static InterpreterEventTypes::Enum retval[] = { InterpreterEventTypes::StateEnter,
+ InterpreterEventTypes::StateExit };
+ return toConstDataRef(retval, 2);
+ }
+
+ virtual TObjList GetExecutableContent(InterpreterEventTypes::Enum inType)
+ {
+ return SStateEditor::ListDataToEditor(inType, m_Data, *this);
+ }
+
+ virtual TObjPtr CreateAndAppendExecutableContent(InterpreterEventTypes::Enum inType,
+ const char8_t *inName)
+ {
+ return SStateEditor::DoCreateAppendExecutableContent(inType, inName, *this, m_Data);
+ }
+ };
+
+ struct SHistoryEditor : public SPositionalEditor
+ {
+ typedef SHistory TStateType;
+ enum { EditorType = EditorTypes::History };
+ SHistory &m_Data;
+ static const char8_t *GetTypeStr() { return "history"; }
+
+ static TPropertyAccessorList CreateAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ typedef SDataProp<SHistoryEditor, SHistory, STransition *> TTransitionProp;
+
+ typedef SFlagBooleanProperty<SHistoryEditor, SHistoryFlags> THistoryFlagsProp;
+ typedef SDataIdProp<SHistoryEditor, SHistory> TIdPropType;
+ typedef SHistoryTransitionProp<SHistoryEditor> THistoryTransitionProp;
+ typedef SParentProp<SHistoryEditor> THistoryParentProp;
+ typedef SInitialTargetProp<SHistoryEditor, SHistory> TInitialTargetProp;
+
+ TPropertyAccessorList &retval(inList);
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+ retval.push_back(QT3DS_NEW(alloc, TIdPropType)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("id"), EditorPropertyTypes::Id),
+ &SHistory::m_Id));
+ retval.push_back(QT3DS_NEW(alloc, THistoryParentProp)(inEditorData.m_EditorFoundation,
+ *inEditorData.m_StringTable));
+ SEditorImplObject::CreateAccessors(inEditorData, retval, false, false);
+ SStateEditor::CreatePositionColorAccessors<SHistoryEditor>(inEditorData, retval);
+ retval.push_back(QT3DS_NEW(
+ alloc, THistoryFlagsProp(inEditorData.m_EditorFoundation,
+ *inEditorData.m_StringTable, "type", "shallow", "deep",
+ &SHistoryFlags::IsDeep, &SHistoryFlags::SetDeep)));
+
+ retval.push_back(QT3DS_NEW(alloc, TTransitionProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("transition"),
+ EditorPropertyTypes::ObjectList),
+ &SHistory::m_Transition));
+
+ retval.push_back(QT3DS_NEW(alloc, THistoryTransitionProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("default"),
+ EditorPropertyTypes::ObjectList)));
+
+ retval.push_back(QT3DS_NEW(alloc, TInitialTargetProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("is initial target"),
+ EditorPropertyTypes::Boolean)));
+
+ return retval;
+ }
+
+ SHistoryEditor(SHistory &inData, SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ : SPositionalEditor(GetTypeStr(), inEditorData,
+ CreateAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual void RemoveObjectFromGraph() { SStateEditor::RemoveObjectFromGraph(*this); }
+
+ virtual TObjPtr Parent() { return m_Editor.ToEditor(m_Data.m_Parent); }
+
+ virtual TEditorStr GetId() { return m_Data.m_Id.c_str(); }
+ virtual void RemoveIdFromContext() { m_Editor.GetStateContext().EraseId(m_Data.m_Id); }
+
+ virtual void AddIdToContext()
+ {
+ if (m_Data.m_Id.IsValid())
+ m_Editor.GetStateContext().InsertId(m_Data.m_Id, &m_Data);
+ }
+ };
+
+ struct STransitionEditor : public SEditorImplObject
+ {
+ typedef STransition TStateType;
+ STransition &m_Data;
+ enum { EditorType = EditorTypes::Transition };
+ static const char8_t *GetTypeStr() { return "transition"; }
+ TVec2List m_PathList;
+
+ static TPropertyAccessorList CreateAccessors(SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ typedef SDataProp<STransitionEditor, STransition, const char8_t *> TTransCharProp;
+ typedef SDataProp<STransitionEditor, STransition, CRegisteredString>
+ TTransRegStrProp;
+ typedef SDataProp<STransitionEditor, STransition, NVConstDataRef<SStateNode *>>
+ TTransTargetProp;
+ typedef SDataProp<STransitionEditor, STransition, NVConstDataRef<QT3DSVec2>>
+ TTransPathProp;
+ typedef SFlagBooleanProperty<STransitionEditor, STransitionFlags>
+ TTransitionFlagsProp;
+ typedef SDataIdProp<STransitionEditor, STransition> TIdPropType;
+ typedef SOptionAccessorProp<STransitionEditor, STransition, QT3DSVec2> TVec2Access;
+ typedef SOptionAccessorProp<STransitionEditor, STransition, QT3DSVec3> TVec3Access;
+ typedef SDataIdProp<STransitionEditor, STransition> TIdPropType;
+
+ TPropertyAccessorList &retval(inList);
+ NVAllocatorCallback &alloc(inEditorData.m_EditorFoundation->getAllocator());
+
+ retval.push_back(
+ QT3DS_NEW(alloc, TIdPropType)(inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("id"),
+ EditorPropertyTypes::String),
+ &STransition::m_Id));
+
+ retval.push_back(QT3DS_NEW(alloc, TTransRegStrProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("event"),
+ EditorPropertyTypes::String),
+ &STransition::m_Event));
+
+ SEditorImplObject::CreateAccessors(inEditorData, retval, false, false);
+ IPropertyAccessor *accessor = QT3DS_NEW(alloc, TTransCharProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("cond"),
+ EditorPropertyTypes::BigString),
+ &STransition::m_Condition);
+
+ retval.push_back(accessor);
+ accessor = QT3DS_NEW(alloc, TTransTargetProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("target"),
+ EditorPropertyTypes::ObjectList),
+ &STransition::m_Target);
+ retval.push_back(accessor);
+ retval.push_back(QT3DS_NEW(alloc, TTransitionFlagsProp)(
+ inEditorData.m_EditorFoundation, *inEditorData.m_StringTable, "type",
+ "external", "internal", &STransitionFlags::IsInternal,
+ &STransitionFlags::SetInternal));
+
+ accessor = QT3DS_NEW(alloc, TTransPathProp)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("path"),
+ EditorPropertyTypes::PositionList),
+ &STransition::m_Path);
+ retval.push_back(accessor);
+ retval.push_back(QT3DS_NEW(alloc, TVec2Access)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("position"),
+ EditorPropertyTypes::PositionList),
+ &STransition::GetPosition, &STransition::SetPosition));
+
+ retval.push_back(QT3DS_NEW(alloc, TVec2Access)(
+ inEditorData.m_EditorFoundation,
+ SPropertyDeclaration(inEditorData.RegisterStr("end position"),
+ EditorPropertyTypes::PositionList),
+ &STransition::GetEndPosition, &STransition::SetEndPosition));
+
+ return retval;
+ }
+
+ STransitionEditor(STransition &inData, SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ : SEditorImplObject(GetTypeStr(), inEditorData,
+ CreateAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual void RemoveObjectFromGraph() { SStateEditor::RemoveObjectFromGraph(*this); }
+
+ virtual TEditorStr GetId() { return m_Data.m_Id.c_str(); }
+ virtual void RemoveIdFromContext() { m_Editor.GetStateContext().EraseId(m_Data.m_Id); }
+
+ virtual void AddIdToContext()
+ {
+ if (m_Data.m_Id.IsValid())
+ m_Editor.GetStateContext().InsertId(m_Data.m_Id, &m_Data);
+ }
+
+ virtual TObjPtr Parent() { return m_Editor.ToEditor(m_Data.m_Parent); }
+
+ virtual NVConstDataRef<InterpreterEventTypes::Enum> GetExecutableContentTypes()
+ {
+ static InterpreterEventTypes::Enum data[] = { InterpreterEventTypes::Transition };
+ return toConstDataRef(data, 1);
+ }
+
+ virtual TObjList GetExecutableContent(InterpreterEventTypes::Enum inType)
+ {
+ TObjList retval;
+ if (inType == InterpreterEventTypes::Transition) {
+ for (TExecutableContentList::iterator iter = m_Data.m_ExecutableContent.begin(),
+ end = m_Data.m_ExecutableContent.end();
+ iter != end; ++iter) {
+ retval.push_back(m_Editor.ExecutableContentToEditor(*iter));
+ }
+ }
+ return retval;
+ }
+ virtual TObjPtr CreateAndAppendExecutableContent(InterpreterEventTypes::Enum inType,
+ const char8_t *inName)
+ {
+ TObjPtr retval;
+ if (inType == InterpreterEventTypes::Transition) {
+ retval = m_Editor.CreateExecutableContent(m_Data, inName);
+ SExecutableContent *theContent = m_Editor.ExecutableContentFromEditor(retval);
+ m_Data.m_ExecutableContent.push_back(*theContent);
+ if (m_Editor.GetOpenTransactionImpl()) {
+ NVScopedRefCounted<SExecutableContentChange> newChange =
+ new SExecutableContentChange(*this, &m_Data.m_ExecutableContent,
+ theContent, true);
+ m_Editor.GetOpenTransactionImpl()->m_Changes.push_back(newChange.mPtr);
+ }
+ }
+ return retval;
+ }
+ };
+
+ struct SExecutableContentParentInfo
+ {
+ SExecutableContent &content;
+ SEditorImpl &m_Editor;
+ TExecutableContentList *parentList;
+ TObjPtr editorObj;
+ TOnEntryList *entryList;
+ SOnEntry *entryItem;
+ TOnExitList *exitList;
+ SOnExit *exitItem;
+ SExecutableContentParentInfo(SExecutableContent &c, SEditorImpl &e)
+ : content(c)
+ , m_Editor(e)
+ , parentList(NULL)
+ , entryList(NULL)
+ , entryItem(NULL)
+ , exitList(NULL)
+ , exitItem(NULL)
+ {
+ if (GetContent().m_StateNodeParent) {
+ editorObj = m_Editor.ToEditor(*GetContent().m_StateNodeParent);
+ if (GetContent().m_StateNodeParent->m_Type == StateNodeTypes::Transition)
+ parentList = &static_cast<STransition *>(GetContent().m_StateNodeParent)
+ ->m_ExecutableContent;
+ else {
+ SExecutableContent *targetContent = &GetContent();
+ entryList = GetContent().m_StateNodeParent->GetOnEntryList();
+ exitList = GetContent().m_StateNodeParent->GetOnExitList();
+ if (entryList) {
+ for (TOnEntryList::iterator iter = entryList->begin(),
+ end = entryList->end();
+ iter != end && parentList == NULL; ++iter) {
+ for (TExecutableContentList::iterator
+ contentIter = iter->m_ExecutableContent.begin(),
+ contentEnd = iter->m_ExecutableContent.end();
+ contentIter != contentEnd && parentList == NULL;
+ ++contentIter) {
+ if (&(*contentIter) == targetContent) {
+ parentList = &iter->m_ExecutableContent;
+ exitList = NULL;
+ entryItem = &(*iter);
+ }
+ }
+ }
+ }
+ if (parentList == NULL && exitList != NULL) {
+ for (TOnExitList::iterator iter = exitList->begin(),
+ end = exitList->end();
+ iter != end && parentList == NULL; ++iter) {
+ for (TExecutableContentList::iterator
+ contentIter = iter->m_ExecutableContent.begin(),
+ contentEnd = iter->m_ExecutableContent.end();
+ contentIter != contentEnd && parentList == NULL;
+ ++contentIter) {
+ if (&(*contentIter) == targetContent) {
+ parentList = &iter->m_ExecutableContent;
+ entryList = NULL;
+ exitItem = &(*iter);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ editorObj = m_Editor.ToEditor(GetContent().m_Parent);
+ parentList = &GetContent().m_Parent->m_Children;
+ }
+ }
+ SExecutableContent &GetContent() { return content; }
+ };
+
+ struct SExecutableContentEditor : public SEditorImplObject
+ {
+ SExecutableContentEditor(const char8_t *inTypeStr, SEditorImpl &inEditorData,
+ const TPropertyAccessorList &inList)
+ : SEditorImplObject(inTypeStr, inEditorData, inList)
+ {
+ }
+
+ virtual SExecutableContent &GetContent() = 0;
+
+ virtual void RemoveObjectFromGraph()
+ {
+ SExecutableContentParentInfo parentInfo(GetContent(), m_Editor);
+ TExecutableContentList *parentList = parentInfo.parentList;
+ TObjPtr editorObj = parentInfo.editorObj;
+ TOnEntryList *entryList = parentInfo.entryList;
+ SOnEntry *entryItem = parentInfo.entryItem;
+ TOnExitList *exitList = parentInfo.exitList;
+ SOnExit *exitItem = parentInfo.exitItem;
+
+ if (parentList) {
+ NVScopedRefCounted<SExecutableContentChange> change =
+ new SExecutableContentChange(editorObj, parentList, &GetContent(), false);
+ change->Do();
+ if (m_Editor.GetOpenTransactionImpl())
+ m_Editor.GetOpenTransactionImpl()->m_Changes.push_back(change.mPtr);
+ // Perhaps remove the item itself
+ if (parentList->empty()) {
+ NVScopedRefCounted<IChange> newChange;
+ if (entryItem)
+ newChange = new TListInsertDeleteChange<TOnEntryList, SOnEntry>(
+ editorObj, entryList, entryItem, false);
+ else if (exitItem)
+ newChange = new TListInsertDeleteChange<TOnExitList, SOnExit>(
+ editorObj, exitList, exitItem, false);
+
+ if (newChange) {
+ newChange->Do();
+ if (m_Editor.GetOpenTransactionImpl())
+ m_Editor.GetOpenTransactionImpl()->m_Changes.push_back(newChange);
+ }
+ }
+ }
+ }
+ };
+
+ struct SSendEditor : public SExecutableContentEditor
+ {
+ typedef SSend TStateType;
+ enum { EditorType = EditorTypes::Send };
+ SSend &m_Data;
+ static const char8_t *GetTypeStr() { return "send"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ typedef SDataIdProp<SSendEditor, SSend> TIdPropType;
+
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SSendEditor>(inData, &SSend::m_Event, "event",
+ EditorPropertyTypes::String));
+ NVFoundationBase &fnd = inData.m_EditorFoundation->getFoundation();
+
+ retval.push_back(QT3DS_NEW(fnd.getAllocator(), TIdPropType)(
+ inData.m_EditorFoundation,
+ SPropertyDeclaration(inData.RegisterStr("id"), EditorPropertyTypes::Id),
+ &SSend::m_Id));
+
+ retval.push_back(QT3DS_NEW(fnd.getAllocator(), SDelayProp<SSendEditor>)(
+ inData.m_EditorFoundation,
+ SPropertyDeclaration(inData.RegisterStr("delay"), EditorPropertyTypes::U32)));
+ return retval;
+ }
+ SSendEditor(SSend &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SRaiseEditor : public SExecutableContentEditor
+ {
+ typedef SRaise TStateType;
+ enum { EditorType = EditorTypes::Raise };
+ SRaise &m_Data;
+ static const char8_t *GetTypeStr() { return "raise"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SRaiseEditor>(inData, &SRaise::m_Event, "event",
+ EditorPropertyTypes::String));
+ return retval;
+ }
+ SRaiseEditor(SRaise &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SLogEditor : public SExecutableContentEditor
+ {
+ typedef SLog TStateType;
+ enum { EditorType = EditorTypes::Log };
+ SLog &m_Data;
+ static const char8_t *GetTypeStr() { return "log"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SLogEditor>(inData, &SLog::m_Label, "label",
+ EditorPropertyTypes::String));
+ retval.push_back(CreateDataAccessor<SLogEditor>(inData, &SLog::m_Expression, "expr",
+ EditorPropertyTypes::String));
+ return retval;
+ }
+ SLogEditor(SLog &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SAssignEditor : public SExecutableContentEditor
+ {
+ typedef SAssign TStateType;
+ enum { EditorType = EditorTypes::Assign };
+ SAssign &m_Data;
+ static const char8_t *GetTypeStr() { return "assign"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SAssignEditor>(
+ inData, &SAssign::m_Location, "location", EditorPropertyTypes::String));
+ retval.push_back(CreateDataAccessor<SAssignEditor>(
+ inData, &SAssign::m_Expression, "expr", EditorPropertyTypes::String));
+ return retval;
+ }
+ SAssignEditor(SAssign &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SIfEditor : public SExecutableContentEditor
+ {
+ typedef SIf TStateType;
+ enum { EditorType = EditorTypes::If };
+ SIf &m_Data;
+ static const char8_t *GetTypeStr() { return "if"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SIfEditor>(inData, &SIf::m_Cond, "cond",
+ EditorPropertyTypes::String));
+ return retval;
+ }
+
+ SIfEditor(SIf &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SElseIfEditor : public SExecutableContentEditor
+ {
+ typedef SElseIf TStateType;
+ enum { EditorType = EditorTypes::ElseIf };
+ SElseIf &m_Data;
+ static const char8_t *GetTypeStr() { return "elseif"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SElseIfEditor>(inData, &SElseIf::m_Cond, "cond",
+ EditorPropertyTypes::String));
+ return retval;
+ }
+
+ SElseIfEditor(SElseIf &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SElseEditor : public SExecutableContentEditor
+ {
+ typedef SElse TStateType;
+ enum { EditorType = EditorTypes::Else };
+ SElse &m_Data;
+ static const char8_t *GetTypeStr() { return "else"; }
+
+ SElseEditor(SElse &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData, inList)
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SScriptEditor : public SExecutableContentEditor
+ {
+ typedef SScript TStateType;
+ enum { EditorType = EditorTypes::Script };
+ SScript &m_Data;
+ static const char8_t *GetTypeStr() { return "script"; }
+
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SScriptEditor>(
+ inData, &SScript::m_Data, "content", EditorPropertyTypes::BigString));
+ return retval;
+ }
+
+ SScriptEditor(SScript &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SCancelEditor : public SExecutableContentEditor
+ {
+ typedef SData TStateType;
+ enum { EditorType = EditorTypes::Cancel };
+ SCancel &m_Data;
+ static const char8_t *GetTypeStr() { return "cancel"; }
+
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList retval;
+ retval.push_back(CreateDataAccessor<SCancelEditor>(
+ inData, &SCancel::m_Send, "sendid", EditorPropertyTypes::Object));
+ retval.push_back(CreateDataAccessor<SCancelEditor>(
+ inData, &SCancel::m_IdExpression, "sendidexpr", EditorPropertyTypes::String));
+ return retval;
+ }
+
+ SCancelEditor(SCancel &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SExecutableContentEditor(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual SExecutableContent &GetContent() { return m_Data; }
+ virtual void *GetWrappedObject() { return &m_Data; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SDataModelEditor : public SEditorImplObject
+ {
+ typedef SDataModel TStateType;
+ enum { EditorType = EditorTypes::DataModel };
+ SDataModel &m_Data;
+ static const char8_t *GetTypeStr() { return "datamodel"; }
+
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList &retval(inList);
+ retval.push_back(CreateDataAccessor<SDataModelEditor>(
+ inData, &SDataModel::m_Data, "data", EditorPropertyTypes::ObjectList));
+ return retval;
+ }
+
+ SDataModelEditor(SDataModel &inData, SEditorImpl &inEditorData,
+ TPropertyAccessorList &inList)
+ : SEditorImplObject(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SDataEditor : public SEditorImplObject
+ {
+ typedef SData TStateType;
+ enum { EditorType = EditorTypes::Data };
+ SData &m_Data;
+ static const char8_t *GetTypeStr() { return "data"; }
+ static TPropertyAccessorList GetPropertyAccessors(SEditorImpl &inData,
+ TPropertyAccessorList &inList)
+ {
+ if (inList.size())
+ return inList;
+ TPropertyAccessorList retval;
+ retval.push_back(CreateDataAccessor<SDataEditor>(inData, &SData::m_Id, "id",
+ EditorPropertyTypes::String));
+ retval.push_back(CreateDataAccessor<SDataEditor>(
+ inData, &SData::m_Expression, "expr", EditorPropertyTypes::String));
+ return retval;
+ }
+
+ SDataEditor(SData &inData, SEditorImpl &inEditorData, TPropertyAccessorList &inList)
+ : SEditorImplObject(GetTypeStr(), inEditorData,
+ GetPropertyAccessors(inEditorData, inList))
+ , m_Data(inData)
+ {
+ }
+
+ UICSTATE_EDITOR_OBJECT_IMPLEMENT_ADDREF_RELEASE;
+
+ virtual void *GetWrappedObject() { return &m_Data; }
+
+ virtual CRegisteredString GetId() const { return m_Data.m_Id; }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ };
+
+ struct SNullEditor
+ {
+ int m_Data;
+ static const char8_t *GetTypeStr() { return ""; }
+ };
+
+ template <typename TStateType>
+ struct SStateEditorMap
+ {
+ typedef SNullEditor TEditorType;
+ template <typename TIgnored>
+ static TObjPtr CreateEditor(TIgnored &, SEditorImpl &, TAccessorMap &)
+ {
+ return TObjPtr();
+ }
+ };
+
+ template <typename TEditorType>
+ struct SEditorImplStateMap
+ {
+ typedef int TStateType;
+ };
+
+ static inline TPropertyAccessorList &GetAccessorList(TAccessorMap &inMap, int inAccessor)
+ {
+ return inMap.insert(eastl::make_pair(inAccessor, TPropertyAccessorList()))
+ .first->second;
+ }
+
+ template <>
+ struct SStateEditorMap<STransition>
+ {
+ typedef STransition stateType;
+ typedef STransitionEditor TEditorType;
+ typedef STransitionEditor editorType;
+ static TObjPtr CreateEditor(stateType &inData, SEditorImpl &inEditorData,
+ TAccessorMap &inAccessors)
+ {
+ return QT3DS_NEW(inEditorData.m_EditorFoundation->getAllocator(), TEditorType)(
+ inData, inEditorData,
+ GetAccessorList(inAccessors, (int)editorType::EditorType));
+ }
+ static TObjPtr CreateEditor(SEditorImpl &inEditorData, TAccessorMap &inAccessors)
+ {
+ STransition *newTransition = QT3DS_NEW(inEditorData.m_AutoAllocator, stateType)();
+ newTransition->m_Flags.SetInternal(true);
+ return CreateEditor(*newTransition, inEditorData, inAccessors);
+ }
+ };
+ template <>
+ struct SEditorImplStateMap<STransitionEditor>
+ {
+ typedef STransition TStateType;
+ };
+
+#define DEFINE_STATE_EDITOR_TYPE_MAP(stateType, editorType) \
+ template <> \
+ struct SStateEditorMap<stateType> \
+ { \
+ typedef editorType TEditorType; \
+ static TObjPtr CreateEditor(stateType &inData, SEditorImpl &inEditorData, \
+ TAccessorMap &inAccessors) \
+ { \
+ return QT3DS_NEW(inEditorData.m_EditorFoundation->getAllocator(), TEditorType)( \
+ inData, inEditorData, GetAccessorList(inAccessors, (int)editorType::EditorType)); \
+ } \
+ static TObjPtr CreateEditor(SEditorImpl &inEditorData, TAccessorMap &inAccessors) \
+ { \
+ return CreateEditor(*QT3DS_NEW(inEditorData.m_AutoAllocator, stateType)(), inEditorData, \
+ inAccessors); \
+ } \
+ }; \
+ template <> \
+ struct SEditorImplStateMap<editorType> \
+ { \
+ typedef stateType TStateType; \
+ };
+
+ DEFINE_STATE_EDITOR_TYPE_MAP(SSCXML, SSCXMLEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SState, SStateEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SParallel, SParallelEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SHistory, SHistoryEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SFinal, SFinalEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SSend, SSendEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SRaise, SRaiseEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SLog, SLogEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SAssign, SAssignEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SIf, SIfEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SElseIf, SElseIfEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SElse, SElseEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SScript, SScriptEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SDataModel, SDataModelEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SData, SDataEditor);
+ DEFINE_STATE_EDITOR_TYPE_MAP(SCancel, SCancelEditor);
+
+#undef DEFINE_STATE_EDITOR_TYPE_MAP
+ }
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorFoundation.h b/src/Runtime/Source/UICState/Editor/UICStateEditorFoundation.h
new file mode 100644
index 00000000..a0d7467e
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorFoundation.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_FOUNDATION_H
+#define UIC_STATE_EDITOR_FOUNDATION_H
+#pragma once
+
+#include "UICState.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/IOStreams.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ struct SBaseEditorFoundation
+ {
+ static MallocAllocator g_BaseAlloc;
+ QT3DSI32 mRefCount;
+ CAllocator m_BaseAllocator;
+ NVScopedRefCounted<NVFoundation> m_Foundation;
+ SBaseEditorFoundation()
+ : mRefCount(0)
+ , m_BaseAllocator()
+ , m_Foundation(NVCreateFoundation(QT3DS_FOUNDATION_VERSION, m_BaseAllocator))
+ {
+ }
+
+ ~SBaseEditorFoundation() {}
+
+ NVFoundationBase &getFoundation() { return *m_Foundation; }
+ NVAllocatorCallback &getAllocator() { return m_Foundation->getAllocator(); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_BaseAlloc);
+
+ static SBaseEditorFoundation &Create()
+ {
+ SBaseEditorFoundation *fndPtr =
+ (SBaseEditorFoundation *)malloc(sizeof(SBaseEditorFoundation));
+ new (fndPtr) SBaseEditorFoundation();
+ return *fndPtr;
+ }
+ };
+
+ typedef NVScopedRefCounted<SBaseEditorFoundation> TFoundationPtr;
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorImpl.h b/src/Runtime/Source/UICState/Editor/UICStateEditorImpl.h
new file mode 100644
index 00000000..e0e3d793
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorImpl.h
@@ -0,0 +1,406 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_IMPL_H
+#define UIC_STATE_EDITOR_IMPL_H
+#include "UICStateEditor.h"
+#include "UICStateEditorValue.h"
+#include "UICStateTypes.h"
+#include "UICStateEditorFoundation.h"
+#include "foundation/Utils.h"
+#include "foundation/XML.h"
+#include "UICStateXMLIO.h"
+#include "foundation/IOStreams.h"
+#include "UICStateExecutionTypes.h"
+#include "UICStateContext.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ struct SEditorImpl;
+
+ typedef nvhash_map<void *, TObjPtr> TStateEditorMap;
+
+ class IPropertyAccessor : public NVRefCounted
+ {
+ protected:
+ virtual ~IPropertyAccessor() {}
+ public:
+ SPropertyDeclaration m_Declaration;
+ IPropertyAccessor(const SPropertyDeclaration &inDec)
+ : m_Declaration(inDec)
+ {
+ }
+ virtual eastl::vector<CRegisteredString> GetLegalValues(IEditorObject & /*inObj*/)
+ {
+ return eastl::vector<CRegisteredString>();
+ }
+
+ virtual Option<SValue> Get(IEditorObject &inObj) = 0;
+ virtual void Set(IEditorObject &inObj, const Option<SValue> &inValue) = 0;
+ // Return true if this access handles the transaction code itself.
+ // Currently only used for the is initial target property.
+ virtual bool HandlesTransaction() { return false; }
+ };
+
+ typedef NVScopedRefCounted<IPropertyAccessor> TPropertyAccessorPtr;
+ typedef eastl::vector<TPropertyAccessorPtr> TPropertyAccessorList;
+ typedef nvhash_map<int, TPropertyAccessorList> TAccessorMap;
+
+#define UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(foundationPtr, refcountVar) \
+ void addRef() { atomicIncrement(&(refcountVar)); } \
+ void release() \
+ { \
+ TFoundationPtr temp(foundationPtr); \
+ QT3DSI32 value = atomicDecrement(&(refcountVar)); \
+ if (value <= 0) \
+ NVDelete(foundationPtr->getAllocator(), this); \
+ }
+
+ struct SEditorImplStrIOStream : public IOutStream
+ {
+ TEditorStr m_Str;
+ bool Write(NVConstDataRef<QT3DSU8> data)
+ {
+ if (data.size())
+ m_Str.append((const char8_t *)data.begin(), (const char8_t *)data.end());
+ return true;
+ }
+ };
+
+ struct SEditorImplStrInStream : public IInStream
+ {
+ const char8_t *m_Pos;
+ const char8_t *m_End;
+ SEditorImplStrInStream(const TEditorStr &inStr)
+ : m_Pos(inStr.data())
+ , m_End(inStr.data() + inStr.size())
+ {
+ }
+
+ virtual QT3DSU32 Read(NVDataRef<QT3DSU8> data)
+ {
+ QT3DSU32 amountLeft = (QT3DSU32)(m_End - m_Pos);
+ QT3DSU32 amountToRead = NVMin(amountLeft, data.size());
+ memCopy(data.mData, m_Pos, amountToRead);
+ m_Pos += amountToRead;
+ return amountToRead;
+ }
+ };
+
+ struct STransaction;
+
+ typedef eastl::vector<IEditorChangeListener *> TChangeListenerList;
+ struct STransactionManagerImpl;
+
+ class IEditorCopyPasteListener
+ {
+ protected:
+ virtual ~IEditorCopyPasteListener() {}
+
+ public:
+ virtual void OnCopy(TEditorPtr inEditor, eastl::vector<SStateNode *> &ioCopiedRoots,
+ IDOMWriter &ioWriter,
+ eastl::vector<SNamespacePair> &ioNamespaces) = 0;
+ virtual void OnPaste(TEditorPtr inEditor, IDOMReader &ioReader,
+ CXMLIO::TIdRemapMap &inStateIdRemapMap) = 0;
+ virtual void OnIDChange(TEditorPtr inEditor, SStateNode &inNode,
+ const char8_t *inOldId) = 0;
+ };
+
+ // Forward declaration of the editor interface that the properties and the editor objects
+ // can all use. Implementation in UICStateEditor.cpp
+ struct SEditorImpl : public IEditor
+ {
+ // Note that *we* keep references to our editors
+ // but our editor objects *cannot* keep a reference to us.
+ // This means that our editor objects need to be able to function (not crash) if we
+ // ourselves go out of scope.
+ TFoundationPtr m_EditorFoundation;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ SSAutoDeallocatorAllocator m_AutoAllocator;
+ NVScopedRefCounted<IStateContext> m_StateContext;
+ TStateEditorMap m_Editors;
+ volatile QT3DSI32 mRefCount;
+ NVScopedRefCounted<STransactionManagerImpl> m_TransactionManager;
+ TAccessorMap m_Accessors;
+ IEditorCopyPasteListener *m_CopyPasteListener;
+
+ SEditorImpl(TFoundationPtr inFoundation,
+ NVScopedRefCounted<IStringTable> inStringTable);
+ void addRef();
+ void release();
+
+ TObjPtr InsertEditor(void *inData, IEditorObject *inEditor);
+
+ template <typename TStateType>
+ TObjPtr ToEditor(TStateType &inItem);
+
+ template <typename TStateType>
+ TObjPtr ToEditor(TStateType *inItem);
+ TObjPtr ToEditor(SStateNode &inItem);
+ TObjPtr ExecutableContentToEditor(SExecutableContent &inItem);
+
+ template <typename TStateType>
+ TStateType *FromEditor(TObjPtr inPtr);
+
+ SStateNode *StateNodeFromEditor(TObjPtr inPtr);
+
+ SExecutableContent *ExecutableContentFromEditor(TObjPtr inPtr);
+ void GenerateUniqueId(SStateNode &inNode, const char8_t *inStem);
+ void GenerateUniqueId(SSend &inNode, const char8_t *inStem);
+
+ virtual TObjPtr GetRoot();
+
+ template <typename TStateType>
+ eastl::pair<TStateType *, TObjPtr> CreateEditorAndObject();
+
+ TObjPtr DoCreate(const char8_t *inTypeName, const char8_t *inId);
+
+ virtual TObjPtr Create(const char8_t *inTypeName, const char8_t *inId);
+
+ virtual TObjPtr GetOrCreate(SSCXML &inData);
+ virtual TObjPtr GetOrCreate(SState &inData);
+ virtual TObjPtr GetOrCreate(STransition &inData);
+ virtual TObjPtr GetOrCreate(SParallel &inData);
+ virtual TObjPtr GetOrCreate(SFinal &inData);
+ virtual TObjPtr GetOrCreate(SHistory &inData);
+ virtual TObjPtr GetOrCreate(SDataModel &inData);
+ virtual TObjPtr GetOrCreate(SData &inData);
+
+ virtual TObjPtr GetObjectById(const char8_t *inId);
+
+ virtual TObjPtr GetEditor(void *inGraphData);
+
+ virtual TSignalConnectionPtr AddChangeListener(IEditorChangeListener &inListener);
+
+ void RemoveChangeListener(IEditorChangeListener &inListener);
+
+ virtual TTransactionPtr BeginTransaction(const TEditorStr &inName);
+
+ virtual TTransactionPtr GetOpenTransaction();
+
+ STransaction *GetOpenTransactionImpl();
+
+ virtual void RollbackTransaction();
+
+ virtual void EndTransaction();
+
+ virtual TEditorStr Copy(TObjList inObjects, const QT3DSVec2 &inMousePos);
+
+ virtual bool CanPaste(TObjPtr inTarget);
+
+ void AddNewPasteObjectToTransaction(SStateNode &inNode);
+
+ virtual void Paste(const TEditorStr &inCopiedObjects, TObjPtr inTarget,
+ const QT3DSVec2 &inMousePos);
+
+ static bool IsDerivedFrom(SStateNode &child, SStateNode &parent);
+
+ // This method should always return a value because the scxml root item
+ // is the parent of everyone else.
+ static SStateNode &GetLeastCommonAncestor(SStateNode &lhs, SStateNode &rhs);
+
+ TObjPtr GetLeastCommonAncestor(NVConstDataRef<TObjPtr> inObjects);
+
+ TObjList GetCancelableSendIds();
+
+ TObjPtr ChangeExecutableContentType(TObjPtr inContent, const char8_t *newType);
+
+ TEditorStr ToXML(TObjPtr inContent);
+
+ eastl::pair<TEditorStr, TObjPtr> FromXML(TObjPtr inContent,
+ const TEditorStr &ioEditedXML);
+
+ // Return the set of events in use in the state machine.
+ TEditorStrList GetStateMachineEvents();
+
+ void ReleaseEditor(void *inData);
+
+ virtual bool Save(const char8_t *inFileName);
+ virtual void Save(IOutStream &inStream);
+
+ bool Load(IInStream &inStream, const char8_t *inFilename);
+
+ /////////////////////////////////////////////////////////////////////
+ // Property access helpers
+ /////////////////////////////////////////////////////////////////////
+ void SetIdProperty(SStateNode &inNode, const SValue &inData,
+ CRegisteredString &inTarget);
+ void SetIdProperty(SSend &inNode, const SValue &inData, CRegisteredString &inTarget);
+
+ void Set(const SValue &inData, CRegisteredString &inTarget)
+ {
+ TEditorStr theStr(inData.getData<TEditorStr>());
+ inTarget = m_StringTable->RegisterStr(theStr.c_str());
+ }
+
+ void Set(const SValue &inData, const char8_t *&inTarget)
+ {
+ TEditorStr theStr(inData.getData<TEditorStr>());
+ const char8_t *theData(theStr.c_str());
+
+ if (inTarget && *inTarget != 0)
+ m_AutoAllocator.deallocate(const_cast<char8_t *>(inTarget));
+
+ size_t len = StrLen(theData);
+ if (len == 0)
+ inTarget = NULL;
+
+ ++len; // account for null terminate
+
+ char8_t *newTarget = (char8_t *)m_AutoAllocator.allocate(len + 1, "graph string",
+ __FILE__, __LINE__);
+ memCopy(newTarget, theData, len);
+ inTarget = newTarget;
+ }
+ SValue Get(CRegisteredString &inTarget) { return inTarget.c_str(); }
+ SValue Get(const char8_t *inItem) { return nonNull(inItem); }
+
+ void Set(const Option<SValue> &inData, NVConstDataRef<SStateNode *> &inTarget);
+ SValue Get(NVConstDataRef<SStateNode *> &inTarget);
+
+ void Set(const Option<SValue> &inData, STransition *&inTarget);
+ Option<SValue> Get(STransition *&inTarget);
+
+ void SetInitial(const TObjList &inList, STransition *&outInitialTransition);
+ SValue GetInitial(STransition *inInitialTransition);
+
+ void SetInitialTarget(const Option<SValue> &inData, SStateNode &inNode);
+ SValue IsInitialTarget(SStateNode &inNode);
+
+ void Set(const Option<SValue> &inData, SDataModel *&inTarget);
+ SValue Get(SDataModel *inTarget);
+
+ void Set(const Option<SValue> &inData, TDataList &inTarget);
+ SValue Get(TDataList &inTarget);
+
+ void Set(const Option<SValue> &inData, NVConstDataRef<QT3DSVec2> &inTarget);
+ SValue Get(const NVConstDataRef<QT3DSVec2> &inTarget);
+
+ void Set(const Option<SValue> &inData, SSend *&inTarget);
+ SValue Get(SSend *inTarget);
+
+ void Set(const Option<SValue> &inData, TEditorStr &inTarget)
+ {
+ inTarget.clear();
+ if (inData.hasValue())
+ inTarget = inData->getData<TEditorStr>();
+ }
+
+ SValue Get(const TEditorStr &inTarget) { return inTarget; }
+
+ void Set(const Option<SValue> &inData, Option<QT3DSVec2> &inTarget)
+ {
+ if (inData.hasValue()) {
+ inTarget = inData->getData<QT3DSVec2>();
+ } else {
+ inTarget = Empty();
+ }
+ }
+ Option<SValue> Get(const Option<QT3DSVec2> &inTarget)
+ {
+ Option<SValue> retval;
+ if (inTarget.hasValue())
+ retval = SValue(inTarget.getValue());
+ return retval;
+ }
+
+ void Set(const Option<SValue> &inData, TVec2List &inTarget)
+ {
+ if (inData.hasValue()) {
+ inTarget = inData->getData<TVec2List>();
+ } else {
+ inTarget.clear();
+ }
+ }
+ SValue Get(const TVec2List &inTarget) { return inTarget; }
+
+ void Set(const Option<SValue> &inData, Option<QT3DSVec3> &inTarget)
+ {
+ if (inData.hasValue()) {
+ inTarget = inData->getData<QT3DSVec3>();
+ } else {
+ inTarget = Empty();
+ }
+ }
+ const Option<SValue> Get(const Option<QT3DSVec3> &inTarget)
+ {
+ Option<SValue> retval;
+ if (inTarget.hasValue())
+ retval = SValue(inTarget.getValue());
+ return retval;
+ }
+
+ const char8_t *ToGraphStr(const char8_t *inStr)
+ {
+ if (isTrivial(inStr))
+ return "";
+ QT3DSU32 len = StrLen(inStr) + 1;
+ char8_t *retval =
+ (char8_t *)m_AutoAllocator.allocate(len, "GraphStr", __FILE__, __LINE__);
+ memCopy(retval, inStr, len);
+ return retval;
+ }
+
+ SValue GetSendId(const char8_t *expression);
+ void SetSendId(const Option<SValue> &inData, const char8_t *&outExpression);
+
+ TObjPtr CreateExecutableContent(SStateNode &inParent, const char8_t *inTypeName);
+ eastl::pair<SExecutableContent *, TObjPtr>
+ CreateExecutableContent(const char8_t *inTypeName);
+
+ CRegisteredString RegisterStr(const char8_t *str)
+ {
+ return m_StringTable->RegisterStr(str);
+ }
+ IStateContext &GetStateContext();
+
+ TEditorStr GetDefaultInitialValue(SStateNode &inNode);
+ void GetLegalInitialValues(SStateNode &inNode,
+ eastl::vector<CRegisteredString> &outValues);
+ void SetInitialAttribute(const Option<SValue> &inData, SStateNode &inNode);
+
+ void SetTransactionManager(STransactionManagerImpl &trans);
+
+ void ReplaceExecutableContent(SExecutableContent &oldContent,
+ SExecutableContent &newContent);
+
+ eastl::vector<CRegisteredString> GetLegalHistoryDefaultValues(SHistory &inData);
+
+ eastl::vector<CRegisteredString> GetLegalParentIds(SStateNode &inNode);
+ void SetParent(SStateNode &inNode, const Option<SValue> &inValue);
+ void CheckAndSetValidHistoryDefault(TObjPtr inHistoryNode);
+ void SetValidHistoryDefault(TObjPtr inHistoryNode);
+ };
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorProperties.h b/src/Runtime/Source/UICState/Editor/UICStateEditorProperties.h
new file mode 100644
index 00000000..91ed5b04
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorProperties.h
@@ -0,0 +1,599 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UICSTATE_EDITOR_PROPERTIES_H
+#define UICSTATE_EDITOR_PROPERTIES_H
+#pragma once
+
+#include "UICStateEditorFoundation.h"
+#include "UICStateEditorImpl.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ template <typename TEditorType>
+ struct SPropertyAccessorBase : public IPropertyAccessor
+ {
+ TFoundationPtr m_Allocator;
+ volatile QT3DSI32 mRefCount;
+
+ SPropertyAccessorBase(TFoundationPtr alloc, const SPropertyDeclaration &inDec)
+ : IPropertyAccessor(inDec)
+ , m_Allocator(alloc)
+ , mRefCount(0)
+ {
+ }
+
+ virtual Option<SValue> Get(IEditorObject &inObj)
+ {
+ return DoGet(static_cast<TEditorType &>(inObj));
+ }
+ virtual void Set(IEditorObject &inObj, const Option<SValue> &inValue)
+ {
+ DoSet(static_cast<TEditorType &>(inObj), inValue);
+ }
+
+ virtual Option<SValue> DoGet(TEditorType &inObj) = 0;
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue) = 0;
+ };
+
+ template <typename TEditorType>
+ struct SInitialProperty : SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ static SPropertyDeclaration CreatePropertyDeclaration(IStringTable &inStrTable)
+ {
+ SPropertyDeclaration theDeclaration;
+ theDeclaration.m_Name = inStrTable.RegisterStr("initial");
+ theDeclaration.m_Type = EditorPropertyTypes::Object;
+ return theDeclaration;
+ }
+ SInitialProperty(TFoundationPtr inAlloc, IStringTable &inStrTable)
+ : TBaseType(inAlloc, CreatePropertyDeclaration(inStrTable))
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ return SValue(inObj.Get(inObj.m_Data.m_Initial));
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.m_Initial =
+ inObj.template FromEditor<STransition>(inValue->getData<TObjPtr>());
+ }
+ };
+
+ template <typename TEditorType, typename TFlagsType>
+ struct SFlagBooleanProperty : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ typedef bool (TFlagsType::*TGetPropPtr)() const;
+ typedef void (TFlagsType::*TSetPropPtr)(bool);
+
+ TGetPropPtr m_GetProp;
+ TSetPropPtr m_SetProp;
+ eastl::vector<CRegisteredString> m_LegalValues;
+ virtual eastl::vector<CRegisteredString> GetLegalValues(IEditorObject & /*inObj*/)
+ {
+ return m_LegalValues;
+ }
+
+ static SPropertyDeclaration CreatePropertyDeclaration(IStringTable &inStrTable,
+ const char8_t *propName)
+ {
+ SPropertyDeclaration theDeclaration;
+ theDeclaration.m_Name = inStrTable.RegisterStr(propName);
+ theDeclaration.m_Type = EditorPropertyTypes::StringSet;
+ return theDeclaration;
+ }
+ SFlagBooleanProperty(TFoundationPtr inFnd, IStringTable &inStrTable,
+ const char8_t *inPropName, const char8_t *falseName,
+ const char8_t *trueName, TGetPropPtr inGetProp,
+ TSetPropPtr inSetProp)
+ : TBaseType(inFnd, CreatePropertyDeclaration(inStrTable, inPropName))
+ , m_GetProp(inGetProp)
+ , m_SetProp(inSetProp)
+ {
+ m_LegalValues.push_back(inStrTable.RegisterStr(falseName));
+ m_LegalValues.push_back(inStrTable.RegisterStr(trueName));
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ bool boolVal = (inObj.m_Data.m_Flags.*m_GetProp)();
+ TEditorStr retval = boolVal ? TEditorStr(m_LegalValues[1].c_str())
+ : TEditorStr(m_LegalValues[0].c_str());
+ return SValue(retval);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValueOpt)
+ {
+ if (inValueOpt.hasValue()) {
+ TEditorStr data = inValueOpt->getData<TEditorStr>();
+
+ if (AreEqual(data.c_str(), m_LegalValues[1].c_str()))
+ (inObj.m_Data.m_Flags.*m_SetProp)(true);
+
+ else if (AreEqual(data.c_str(), m_LegalValues[0].c_str()))
+ (inObj.m_Data.m_Flags.*m_SetProp)(false);
+
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ };
+
+ template <typename TEditorType>
+ struct SChildrenProperty : SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ static SPropertyDeclaration CreatePropertyDeclaration(IStringTable &inStrTable)
+ {
+ SPropertyDeclaration theDeclaration;
+ theDeclaration.m_Name = inStrTable.RegisterStr("children");
+ theDeclaration.m_Type = EditorPropertyTypes::ObjectList;
+ return theDeclaration;
+ }
+
+ SChildrenProperty(TFoundationPtr inAlloc, IStringTable &inStrTable)
+ : TBaseType(inAlloc, CreatePropertyDeclaration(inStrTable))
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ TObjList retval;
+ for (TStateNodeList::iterator iter = inObj.m_Data.m_Children.begin(),
+ end = inObj.m_Data.m_Children.end();
+ iter != end; ++iter)
+ retval.push_back(inObj.m_Editor.ToEditor(*iter));
+ return SValue(retval);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ if (inValue.hasValue()) {
+ const TObjList &data = inValue->getData<TObjList>();
+ TStateNodeList &theChildren(inObj.m_Data.m_Children);
+ // De-set all children.
+ while (theChildren.empty() == false)
+ inObj.m_Data.RemoveChild(theChildren.front());
+
+ for (TObjList::const_iterator iter = data.begin(), end = data.end();
+ iter != end; ++iter) {
+ SStateNode *theNode = inObj.m_Editor.StateNodeFromEditor(*iter);
+ if (theNode)
+ inObj.m_Data.AppendChild(*theNode);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+ };
+
+ // Property that is represented by a data item's member.
+ template <typename TEditorType, typename TStateType, typename TDataType>
+ struct SDataProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ typedef TDataType TStateType::*TPropertyPtr;
+ TPropertyPtr m_Ptr;
+ eastl::vector<CRegisteredString> m_LegalValues;
+
+ SDataProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec, TPropertyPtr inPtr)
+ : TBaseType(inAlloc, inDec)
+ , m_Ptr(inPtr)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual eastl::vector<CRegisteredString> GetLegalValues(IEditorObject & /*inObj*/)
+ {
+ return m_LegalValues;
+ }
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ return inObj.m_Editor.Get(inObj.m_Data.*(this->m_Ptr));
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.m_Editor.Set(inValue, inObj.m_Data.*(this->m_Ptr));
+ }
+ };
+
+ template <typename TEditorType, typename TStateType>
+ struct SInitialTargetProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ SInitialTargetProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec)
+ : TBaseType(inAlloc, inDec)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ return inObj.m_Editor.IsInitialTarget(inObj.m_Data);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.m_Editor.SetInitialTarget(inValue, inObj.m_Data);
+ }
+
+ virtual bool HandlesTransaction() { return true; }
+ };
+
+ template <typename TEditorType, typename TStateType>
+ struct SInitialComboProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ SInitialComboProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec)
+ : TBaseType(inAlloc, inDec)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual eastl::vector<CRegisteredString> GetLegalValues(IEditorObject &inEditor)
+ {
+ eastl::vector<CRegisteredString> retval;
+ TEditorType &theEditor = static_cast<TEditorType &>(inEditor);
+ retval.push_back(theEditor.m_Editor.RegisterStr("(script expression)"));
+ theEditor.m_Editor.GetLegalInitialValues(theEditor.m_Data, retval);
+ return retval;
+ }
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ TEditorType &theEditor = inObj;
+ if (theEditor.m_InitialComboValue.size() == 0) {
+ if (!isTrivial(inObj.m_Data.GetInitialExpression()))
+ theEditor.m_InitialComboValue = "(script expression)";
+ else if (inObj.m_Data.GetInitialTransition()
+ && inObj.m_Data.GetInitialTransition()->m_Target.size())
+ theEditor.m_InitialComboValue.assign(
+ inObj.m_Data.GetInitialTransition()->m_Target[0]->m_Id.c_str());
+ else
+ theEditor.m_InitialComboValue =
+ theEditor.m_Editor.GetDefaultInitialValue(theEditor.m_Data);
+ }
+ return theEditor.m_InitialComboValue;
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ if (inValue->getData<TEditorStr>() != "(script expression)") {
+ inObj.m_Editor.SetInitialAttribute(inValue, inObj.m_Data);
+ } else {
+ inObj.m_Editor.SetInitialAttribute(Option<SValue>(), inObj.m_Data);
+ }
+ }
+ virtual bool HandlesTransaction() { return true; }
+ };
+
+ template <typename TEditorType, typename TStateType, typename TDataType>
+ struct SOptionAccessorProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ typedef Option<TDataType> TOptType;
+ typedef TOptType (TStateType::*TGetPtr)() const;
+ typedef void (TStateType::*TSetPtr)(const TOptType &inOpt);
+ TGetPtr m_Getter;
+ TSetPtr m_Setter;
+
+ SOptionAccessorProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec,
+ TGetPtr inPtr, TSetPtr inSetPtr)
+ : TBaseType(inAlloc, inDec)
+ , m_Getter(inPtr)
+ , m_Setter(inSetPtr)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ TOptType theOpt = (inObj.m_Data.*m_Getter)();
+ if (theOpt.hasValue())
+ return SValue(*theOpt);
+ return Empty();
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ TOptType theNewValue;
+ if (inValue.hasValue())
+ theNewValue = TOptType(inValue->getData<TDataType>());
+ (inObj.m_Data.*m_Setter)(theNewValue);
+ }
+ };
+
+ template <typename TEditorType, typename TStateType>
+ struct SDataIdProp : SDataProp<TEditorType, TStateType, CRegisteredString>
+ {
+ typedef SDataProp<TEditorType, TStateType, CRegisteredString> TBaseType;
+ typedef CRegisteredString TStateType::*TPropertyPtr;
+
+ SDataIdProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec,
+ TPropertyPtr inPtr)
+ : TBaseType(inAlloc, inDec, inPtr)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ // This may mangle the id in order to find a unique id.
+ inObj.m_Editor.SetIdProperty(inObj.m_Data, inValue, inObj.m_Data.*(this->m_Ptr));
+ }
+ };
+
+ template <typename TEditorObject, typename TStateType, typename TDataType>
+ IPropertyAccessor *CreateDataAccessor(SEditorImpl &inData, TDataType TStateType::*inDataPtr,
+ const char8_t *inName,
+ EditorPropertyTypes::Enum inPropType)
+ {
+ typedef SDataProp<TEditorObject, TStateType, TDataType> TPropType;
+ return QT3DS_NEW(inData.m_EditorFoundation->getAllocator(), TPropType)(
+ inData.m_EditorFoundation,
+ SPropertyDeclaration(inData.RegisterStr(inName), inPropType), inDataPtr);
+ }
+
+ template <typename TEditorType, typename TDataType>
+ struct SEditorImplProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ typedef TDataType TEditorType::*TPropertyPtr;
+ TPropertyPtr m_Ptr;
+
+ SEditorImplProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec,
+ TPropertyPtr inPtr)
+ : TBaseType(inAlloc, inDec)
+ , m_Ptr(inPtr)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ return inObj.m_Editor.Get(inObj.*(this->m_Ptr));
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.m_Editor.Set(inValue, inObj.*(this->m_Ptr));
+ }
+ };
+
+ template <typename TEditorObject, typename TDataType>
+ IPropertyAccessor *
+ CreateEditorAccessor(SEditorImpl &inData, TDataType TEditorObject::*inDataPtr,
+ const char8_t *inName, EditorPropertyTypes::Enum inPropType)
+ {
+ typedef SEditorImplProp<TEditorObject, TDataType> TPropType;
+ return QT3DS_NEW(inData.m_EditorFoundation->getAllocator(), TPropType)(
+ inData.m_EditorFoundation,
+ SPropertyDeclaration(inData.RegisterStr(inName), inPropType), inDataPtr);
+ }
+
+ // General property for initial and history transition properties
+ template <typename TEditorType, typename TStateType>
+ struct SSCXMLInitialPtr : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef STransition *TStateType::*TPropertyType;
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ TPropertyType m_PropPtr;
+
+ SSCXMLInitialPtr(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec,
+ TPropertyType inPropPtr)
+ : TBaseType(inAlloc, inDec)
+ , m_PropPtr(inPropPtr)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ return inObj.GetInitial(inObj.m_Data.*m_PropPtr);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.SetInitial(inValue->getData<TObjList>(), inObj.m_Data.*m_PropPtr);
+ }
+ };
+
+ template <typename TEditorType, typename TStateType>
+ struct SSCXMLInitialContent : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef STransition *TStateType::*TPropertyType;
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+ TPropertyType m_PropPtr;
+
+ SSCXMLInitialContent(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec,
+ TPropertyType inPropPtr)
+ : TBaseType(inAlloc, inDec)
+ , m_PropPtr(inPropPtr)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ return inObj.GetInitialContent(inObj.m_Data.*m_PropPtr);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ if (inValue.hasValue()) {
+ inObj.SetInitialContent(inValue->getData<TObjList>(), inObj.m_Data.*m_PropPtr);
+ } else {
+ inObj.SetInitialContent(TObjList(), inObj.m_Data.*m_PropPtr);
+ }
+ }
+ };
+
+ template <typename TEditorType>
+ struct SDelayProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ SDelayProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec)
+ : TBaseType(inAlloc, inDec)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ if (!isTrivial(inObj.m_Data.m_DelayExpr))
+ return Empty();
+
+ return inObj.m_Editor.GetSendId(inObj.m_Data.m_Delay);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.m_Data.m_DelayExpr = "";
+ inObj.m_Editor.SetSendId(inValue, inObj.m_Data.m_Delay);
+ }
+ };
+
+ template <typename TEditorType>
+ struct SHistoryTransitionProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ SHistoryTransitionProp(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec)
+ : TBaseType(inAlloc, inDec)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual eastl::vector<CRegisteredString> GetLegalValues(IEditorObject &inEditor)
+ {
+ TEditorType &theEditor = static_cast<TEditorType &>(inEditor);
+ return theEditor.m_Editor.GetLegalHistoryDefaultValues(theEditor.m_Data);
+ }
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ if (inObj.m_Data.m_Transition)
+ return inObj.m_Editor.Get(inObj.m_Data.m_Transition->m_Target);
+
+ return SValue(TObjList());
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ TObjList newObjects;
+
+ if (inValue.hasValue())
+ newObjects = inValue->getData<TObjList>();
+
+ if (newObjects.size()) {
+ if (!inObj.m_Data.m_Transition) {
+ inObj.m_Data.m_Transition =
+ (STransition *)inObj.m_Editor.m_AutoAllocator.allocate(
+ sizeof(STransition), "transition", __FILE__, __LINE__);
+ new (inObj.m_Data.m_Transition) STransition();
+ inObj.m_Data.m_Transition->m_Parent = &inObj.m_Data;
+ }
+ inObj.m_Editor.Set(inValue, inObj.m_Data.m_Transition->m_Target);
+ } else
+ inObj.m_Data.m_Transition = NULL;
+ }
+ };
+
+ template <typename TEditorType>
+ struct SParentProp : public SPropertyAccessorBase<TEditorType>
+ {
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ SParentProp(TFoundationPtr inAlloc, IStringTable &inStrTable)
+ : TBaseType(inAlloc, SPropertyDeclaration(inStrTable.RegisterStr("parent"),
+ EditorPropertyTypes::StringSet))
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ static const char *SCXMLParentName() { return "(none)"; }
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ TObjPtr current = inObj.Parent();
+ if (current && AreEqual(current->TypeName(), "scxml") == false)
+ return SValue(current->GetId());
+ return Option<SValue>(SValue(eastl::string(SCXMLParentName())));
+ }
+
+ virtual eastl::vector<CRegisteredString> GetLegalValues(IEditorObject &inEditor)
+ {
+ TEditorType &theEditor = static_cast<TEditorType &>(inEditor);
+ eastl::vector<CRegisteredString> retval =
+ theEditor.m_Editor.GetLegalParentIds(theEditor.m_Data);
+ CRegisteredString parentName(theEditor.m_Editor.RegisterStr(SCXMLParentName()));
+ retval.insert(retval.begin(), parentName);
+ return retval;
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ inObj.m_Editor.SetParent(inObj.m_Data, inValue);
+ }
+
+ virtual bool HandlesTransaction() { return true; }
+ };
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.cpp b/src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.cpp
new file mode 100644
index 00000000..88794438
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateEditorTransactionImpl.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ // Some things have to be implemented below so that we can take advantage of the full
+ // SEditorImpl definition.
+
+ STransaction::STransaction(TFoundationPtr alloc, STransactionManagerImpl &inEditor,
+ const TEditorStr &inName)
+ : ITransaction(inName)
+ , m_Alloc(alloc)
+ , mRefCount(0)
+ , m_Editor(inEditor)
+ {
+ }
+
+ STransaction::~STransaction() {}
+
+ void STransaction::addRef() { atomicIncrement(&mRefCount); }
+
+ void STransaction::release()
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0) {
+ TFoundationPtr fnd(m_Alloc);
+ NVDelete(fnd->getAllocator(), this);
+ }
+ }
+
+ void STransaction::ChangesToEditors()
+ {
+ m_EditorsList.clear();
+ m_EditorsList.resize(m_Changes.size());
+ eastl::transform(m_Changes.begin(), m_Changes.end(), m_EditorsList.begin(),
+ SChangeToEditor());
+ }
+
+ void STransaction::SendDoSignals()
+ {
+ ChangesToEditors();
+ CreateRemovedEditorsList(true);
+ for (TChangeListenerList::iterator listenerIter = m_Editor->m_ChangeListeners.begin(),
+ listenerEnd = m_Editor->m_ChangeListeners.end();
+ listenerIter != listenerEnd; ++listenerIter)
+ (*listenerIter)->OnDataChange(m_EditorsList, m_RemovedEditorsList);
+ }
+
+ void STransaction::Do()
+ {
+ for (TChangeList::iterator iter = m_Changes.begin(), end = m_Changes.end(); iter != end;
+ ++iter)
+ (*iter)->Do();
+
+ for (TRemovePairList::iterator iter = m_RemovedPairs.begin(),
+ end = m_RemovedPairs.end();
+ iter != end; ++iter) {
+ if (iter->first)
+ iter->second->RemoveIdFromContext();
+ else
+ iter->second->AddIdToContext();
+ }
+
+ SendDoSignals();
+ }
+
+ void STransaction::SilentUndo()
+ {
+ for (TChangeList::reverse_iterator iter = m_Changes.rbegin(), end = m_Changes.rend();
+ iter != end; ++iter)
+ (*iter)->Undo();
+
+ for (TRemovePairList::iterator iter = m_RemovedPairs.begin(),
+ end = m_RemovedPairs.end();
+ iter != end; ++iter) {
+ if (iter->first)
+ iter->second->AddIdToContext();
+ else
+ iter->second->RemoveIdFromContext();
+ }
+ }
+
+ void STransaction::Undo()
+ {
+ SilentUndo();
+ m_EditorsList.clear();
+ m_EditorsList.resize(m_Changes.size());
+ eastl::transform(m_Changes.rbegin(), m_Changes.rend(), m_EditorsList.begin(),
+ SChangeToEditor());
+ CreateRemovedEditorsList(false);
+ for (TChangeListenerList::iterator listenerIter = m_Editor->m_ChangeListeners.begin(),
+ listenerEnd = m_Editor->m_ChangeListeners.end();
+ listenerIter != listenerEnd; ++listenerIter)
+ (*listenerIter)->OnDataChange(m_EditorsList, m_RemovedEditorsList);
+ }
+
+ struct STransactionImplConnection : public IStateSignalConnection
+ {
+ TFoundationPtr &m_Alloc;
+ QT3DSI32 mRefCount;
+ STransactionManagerImpl &m_Editor;
+ IEditorChangeListener &m_ChangeListener;
+ STransactionImplConnection(TFoundationPtr &alloc, STransactionManagerImpl &e,
+ IEditorChangeListener &listener)
+ : m_Alloc(alloc)
+ , mRefCount(0)
+ , m_Editor(e)
+ , m_ChangeListener(listener)
+ {
+ }
+ // Implemented below editor to use editor's interfaces
+ virtual ~STransactionImplConnection()
+ {
+ m_Editor.RemoveChangeListener(m_ChangeListener);
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Alloc, mRefCount);
+ };
+
+ void STransactionManagerImpl::addRef() { atomicIncrement(&mRefCount); }
+ void STransactionManagerImpl::release()
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0) {
+ TFoundationPtr fnd(m_EditorFoundation);
+ NVDelete(fnd->getAllocator(), this);
+ }
+ }
+
+ TSignalConnectionPtr
+ STransactionManagerImpl::AddChangeListener(IEditorChangeListener &inListener)
+ {
+ m_ChangeListeners.push_back(&inListener);
+ // If we have any listeners, then we can't be destroyed as their connections will still
+ // need
+ // to talk to us to release its stuff.
+ if (m_ChangeListeners.size() == 1)
+ addRef();
+ return QT3DS_NEW(m_EditorFoundation->getAllocator(),
+ STransactionImplConnection)(m_EditorFoundation, *this, inListener);
+ }
+
+ void STransactionManagerImpl::RemoveChangeListener(IEditorChangeListener &inListener)
+ {
+ TChangeListenerList::iterator iter =
+ eastl::find(m_ChangeListeners.begin(), m_ChangeListeners.end(), &inListener);
+ if (iter != m_ChangeListeners.end())
+ m_ChangeListeners.erase(iter);
+ if (m_ChangeListeners.size() == 0)
+ release();
+ }
+ TTransactionPtr STransactionManagerImpl::BeginTransaction(const TEditorStr &inName)
+ {
+ if (!m_Transaction) {
+ QT3DS_ASSERT(m_OpenCount == 0);
+ m_Transaction = QT3DS_NEW(m_EditorFoundation->getAllocator(),
+ STransaction)(m_EditorFoundation, *this, inName);
+ }
+ ++m_OpenCount;
+ return m_Transaction.mPtr;
+ }
+
+ TTransactionPtr STransactionManagerImpl::GetOpenTransaction() { return m_Transaction.mPtr; }
+ STransaction *STransactionManagerImpl::GetOpenTransactionImpl()
+ {
+ return m_Transaction.mPtr;
+ }
+
+ void STransactionManagerImpl::RollbackTransaction()
+ {
+ --m_OpenCount;
+ if (m_OpenCount <= 0) {
+ if (m_Transaction) {
+ m_Transaction->Undo();
+ m_Transaction = NULL;
+ }
+ }
+ QT3DS_ASSERT(m_OpenCount == 0);
+ m_OpenCount = 0;
+ }
+
+ void STransactionManagerImpl::EndTransaction()
+ {
+ TTransactionPtr retval = m_Transaction.mPtr;
+ --m_OpenCount;
+ if (m_OpenCount <= 0)
+ m_Transaction = NULL;
+ QT3DS_ASSERT(m_OpenCount >= 0);
+ m_OpenCount = 0;
+ }
+
+ void STransactionManagerImpl::OnObjectDeleted(TObjPtr inObj)
+ {
+ if (m_Transaction)
+ m_Transaction->m_RemovedPairs.push_back(eastl::make_pair(true, inObj));
+
+ if (m_ObjListener)
+ m_ObjListener->OnObjectDeleted(inObj);
+ }
+ void STransactionManagerImpl::OnObjectCreated(TObjPtr inObj)
+ {
+ if (m_Transaction)
+ m_Transaction->m_RemovedPairs.push_back(eastl::make_pair(false, inObj));
+
+ if (m_ObjListener)
+ m_ObjListener->OnObjectCreated(inObj);
+ }
+ }
+}
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.h b/src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.h
new file mode 100644
index 00000000..3a672a85
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorTransactionImpl.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_TRANSACTION_IMPL_H
+#define UIC_STATE_EDITOR_TRANSACTION_IMPL_H
+#include "UICStateEditor.h"
+#include "UICStateEditorFoundation.h"
+#include "UICStateEditorProperties.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ class IChange : public NVRefCounted
+ {
+ protected:
+ virtual ~IChange() {}
+ public:
+ virtual void Do() = 0;
+ virtual void Undo() = 0;
+ virtual TObjPtr GetEditor() = 0;
+ };
+
+ typedef eastl::vector<NVScopedRefCounted<IChange>> TChangeList;
+
+ struct SChange : public IChange
+ {
+ Option<SValue> m_OldVal;
+ Option<SValue> m_NewVal;
+ TPropertyAccessorPtr m_Accessor;
+ TObjPtr m_Editor;
+ QT3DSI32 mRefCount;
+
+ SChange(const Option<SValue> &inOldVal, const Option<SValue> &inNewVal,
+ IPropertyAccessor &inAccessor, IEditorObject &inEditor)
+ : m_OldVal(inOldVal)
+ , m_NewVal(inNewVal)
+ , m_Accessor(inAccessor)
+ , m_Editor(inEditor)
+ , mRefCount(0)
+ {
+ }
+ // Sometimes we need to create a change just to signal a new object.
+ // In this case there isn't an accessor and there aren't old values and
+ // new values.
+ SChange(IEditorObject &inEditor)
+ : m_Editor(inEditor)
+ , mRefCount(0)
+ {
+ }
+ SChange()
+ : mRefCount(0)
+ {
+ }
+ void Do()
+ {
+ if (m_Accessor)
+ m_Accessor->Set(*m_Editor, m_NewVal);
+ }
+
+ void Undo()
+ {
+ if (m_Accessor)
+ m_Accessor->Set(*m_Editor, m_OldVal);
+ }
+ void addRef() { atomicIncrement(&mRefCount); }
+ void release()
+ {
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0)
+ delete this;
+ }
+
+ TObjPtr GetEditor() { return m_Editor; }
+ };
+
+ // true if removed on do, false if removed on false;
+ typedef eastl::pair<bool, TObjPtr> TRemovePair;
+ typedef eastl::vector<TRemovePair> TRemovePairList;
+
+ struct STransactionManagerImpl;
+
+ struct STransaction : public ITransaction
+ {
+ TFoundationPtr m_Alloc;
+ TChangeList m_Changes;
+ volatile QT3DSI32 mRefCount;
+ // We have to keep a refcount to the editor ourselves.
+ NVScopedRefCounted<STransactionManagerImpl> m_Editor;
+ TObjList m_EditorsList;
+ TObjList m_RemovedEditorsList;
+ TRemovePairList m_RemovedPairs;
+
+ STransaction(TFoundationPtr alloc, STransactionManagerImpl &inEditor,
+ const TEditorStr &inName);
+ virtual ~STransaction();
+ virtual void addRef();
+ virtual void release();
+
+ void CreateRemovedEditorsList(bool inDo)
+ {
+ m_RemovedEditorsList.clear();
+ for (TRemovePairList::iterator iter = m_RemovedPairs.begin(),
+ end = m_RemovedPairs.end();
+ iter != end; ++iter)
+ if (iter->first == inDo)
+ m_RemovedEditorsList.push_back(iter->second);
+ }
+
+ struct SChangeToEditor
+ {
+ TObjPtr operator()(IChange *inChange) const { return inChange->GetEditor(); }
+ };
+ virtual void SendDoSignals();
+ virtual void Do();
+ virtual void SilentUndo();
+ virtual void Undo();
+ virtual bool Empty() { return m_Changes.empty() && m_RemovedPairs.empty(); }
+ virtual TObjList GetEditedObjects()
+ {
+ ChangesToEditors();
+ return m_EditorsList;
+ }
+ void ChangesToEditors();
+ };
+
+ class ITransManagerImplListener
+ {
+ protected:
+ virtual ~ITransManagerImplListener() {}
+ public:
+ virtual void OnObjectDeleted(TObjPtr inObj) = 0;
+ virtual void OnObjectCreated(TObjPtr inObj) = 0;
+ };
+
+ struct STransactionManagerImpl : public ITransactionManager
+ {
+ TFoundationPtr m_EditorFoundation;
+ volatile QT3DSI32 mRefCount;
+ TChangeListenerList m_ChangeListeners;
+ NVScopedRefCounted<STransaction> m_Transaction;
+ QT3DSI32 m_OpenCount;
+ ITransManagerImplListener *m_ObjListener;
+
+ STransactionManagerImpl(TFoundationPtr fnd)
+ : m_EditorFoundation(fnd)
+ , mRefCount(0)
+ , m_OpenCount(0)
+ , m_ObjListener(NULL)
+ {
+ }
+ virtual void addRef();
+ virtual void release();
+ virtual TSignalConnectionPtr AddChangeListener(IEditorChangeListener &inListener);
+ virtual TTransactionPtr BeginTransaction(const TEditorStr &inName = TEditorStr());
+ virtual TTransactionPtr GetOpenTransaction();
+ STransaction *GetOpenTransactionImpl();
+ virtual void RollbackTransaction();
+ virtual void EndTransaction();
+
+ void OnObjectDeleted(TObjPtr inObj);
+ void OnObjectCreated(TObjPtr inObj);
+
+ void RemoveChangeListener(IEditorChangeListener &inListener);
+ };
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.cpp b/src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.cpp
new file mode 100644
index 00000000..8df73b32
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.cpp
@@ -0,0 +1,813 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateEditorTransitionPath.h"
+
+namespace {
+
+using namespace uic::state::editor;
+using namespace uic::state;
+
+bool inBounds(QT3DSF32 item, QT3DSF32 lower, QT3DSF32 upper)
+{
+ if (item >= lower && item <= upper)
+ return true;
+ return false;
+}
+
+DirectionTypes::Enum EdgeTypeToDirectionType(EdgeTypes::Enum inEdgeType)
+{
+ switch (inEdgeType) {
+ case EdgeTypes::Bottom:
+ case EdgeTypes::Top:
+ return DirectionTypes::Vertical;
+ default:
+ return DirectionTypes::Horizontal;
+ }
+}
+
+static inline SEndPoint DoGetActualEndPoint(const SEndPoint &inPoint, const SRect &inMyRect,
+ const QT3DSVec2 &inOtherCenter)
+{
+ SEndPoint theEndPoint = inPoint;
+ if (inPoint.m_EdgeType == EdgeTypes::UnsetEdgeType)
+ theEndPoint = CEditorTransitionPath::CalculateDefaultEndPoint(inMyRect, inOtherCenter);
+ return theEndPoint;
+}
+
+static inline eastl::pair<QT3DSVec2, EdgeTypes::Enum>
+GetEndpointPoint(const SEndPoint &inPoint, const SRect &inMyRect, const QT3DSVec2 &inOtherCenter)
+{
+ SEndPoint theEndPoint = DoGetActualEndPoint(inPoint, inMyRect, inOtherCenter);
+ SLine theRectLine;
+ switch (theEndPoint.m_EdgeType) {
+ case EdgeTypes::Top:
+ theRectLine = inMyRect.topEdge();
+ break;
+ case EdgeTypes::Bottom:
+ theRectLine = inMyRect.bottomEdge();
+ break;
+ case EdgeTypes::Left:
+ theRectLine = inMyRect.leftEdge();
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ // fallthrough intentional
+ case EdgeTypes::Right:
+ theRectLine = inMyRect.rightEdge();
+ break;
+ }
+
+ return eastl::make_pair(theRectLine.toPoint(theEndPoint.m_Interp), theEndPoint.m_EdgeType);
+}
+
+inline bool RectDiffers(const Option<SRect> &inLhs, const SRect &inRhs)
+{
+ if (inLhs.isEmpty())
+ return true;
+ SRect lhs = *inLhs;
+ return CEditorTransitionPath::AreAlmostEqual(lhs.m_TopLeft, inRhs.m_TopLeft) == false
+ || CEditorTransitionPath::AreAlmostEqual(lhs.m_WidthHeight, inRhs.m_WidthHeight) == false;
+}
+}
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ bool SRect::contains(const QT3DSVec2 &inPoint) const
+ {
+ if (inPoint.x >= left() && inPoint.x <= right() && inPoint.y >= top()
+ && inPoint.y <= bottom())
+ return true;
+ return false;
+ }
+
+ void CEditorTransitionPath::SetPathType(TransitionPathTypes::Enum inType)
+ {
+ m_TransitionPathType = inType;
+ if (m_TransitionPathType == TransitionPathTypes::BeginToBegin
+ || m_TransitionPathType == TransitionPathTypes::Targetless)
+ m_ControlPoints.clear();
+ MarkDirty();
+ }
+
+ bool CEditorTransitionPath::UpdateBeginEndRects(const SRect &inStartRect,
+ const SRect &inEndRect)
+ {
+ bool dataChanged = false;
+
+ if (m_BeginRect.hasValue() && m_EndRect.hasValue()) {
+ QT3DSVec2 beginDiff = inStartRect.center() - m_BeginRect->center();
+ QT3DSVec2 endDiff = inEndRect.center() - m_EndRect->center();
+
+ if (AreAlmostEqual(beginDiff, QT3DSVec2(0, 0)) == false
+ && AreAlmostEqual(beginDiff, endDiff, 1)) {
+ dataChanged = m_ControlPoints.empty() == false;
+ // Move all the control points.
+ for (size_t idx = 0, end = m_ControlPoints.size(); idx < end; ++idx) {
+ SControlPoint &thePoint(m_ControlPoints[idx]);
+ QT3DSF32 diffComponent =
+ SControlPoint::GetComponent(beginDiff, thePoint.m_Direction);
+ thePoint.m_Position += diffComponent;
+ }
+ }
+ }
+ bool rectDiffers =
+ RectDiffers(m_BeginRect, inStartRect) || RectDiffers(m_EndRect, inEndRect);
+ m_BeginRect = inStartRect;
+ m_EndRect = inEndRect;
+ if (rectDiffers)
+ MarkDirty();
+ m_TransitionPathType = TransitionPathTypes::BeginToEnd;
+ return dataChanged;
+ }
+
+ bool CEditorTransitionPath::UpdateBeginEndRects(const SRect &inStartRect,
+ TransitionPathTypes::Enum inPathType)
+ {
+ bool dataChanged = m_ControlPoints.empty() == false;
+ QT3DS_ASSERT(inPathType == TransitionPathTypes::BeginToBegin
+ || inPathType == TransitionPathTypes::Targetless);
+ bool rectDiffers = m_EndRect.hasValue() || RectDiffers(m_BeginRect, inStartRect);
+ m_BeginRect = inStartRect;
+ m_EndRect = Empty();
+ if (rectDiffers || dataChanged)
+ MarkDirty();
+ m_TransitionPathType = inPathType;
+ return dataChanged;
+ }
+
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> CEditorTransitionPath::GetBeginPointAndEdge() const
+ {
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theStartPoint(QT3DSVec2(0, 0),
+ EdgeTypes::UnsetEdgeType);
+ if (m_BeginRect.hasValue()) {
+ QT3DSVec2 center(m_BeginRect->center());
+ center.x += 1;
+ if (m_EndRect.hasValue())
+ center = m_EndRect->center();
+ theStartPoint = GetEndpointPoint(m_Begin, *m_BeginRect, center);
+ }
+ return theStartPoint;
+ }
+
+ eastl::pair<QT3DSVec2, QT3DSVec2> CEditorTransitionPath::GetBeginEndPoints() const
+ {
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theStartPoint(GetBeginPointAndEdge());
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theEndPoint(QT3DSVec2(0, 0),
+ EdgeTypes::UnsetEdgeType);
+ if (m_EndRect.hasValue())
+ theEndPoint = GetEndpointPoint(m_End, *m_EndRect, m_BeginRect->center());
+
+ return eastl::make_pair(theStartPoint.first, theEndPoint.first);
+ }
+
+ SEndPoint CEditorTransitionPath::CalculateEndPoint(const SRect &inRect,
+ const QT3DSVec2 &inPoint,
+ QT3DSF32 inEdgeBoundary)
+ {
+ if (inRect.width() == 0 || inRect.height() == 0) {
+ QT3DS_ASSERT(false);
+ return SEndPoint();
+ }
+
+ SLine centerToPoint = SLine(inRect.center(), inPoint);
+ SLine leftOrRight;
+ SLine topOrBottom;
+ Option<QT3DSF32> isect;
+ EdgeTypes::Enum theEdge = EdgeTypes::UnsetEdgeType;
+ // If line runs right, test against right edge
+ QT3DSF32 distance = 0;
+ SLine theRectLine;
+ if (centerToPoint.dx() > 0) {
+ theRectLine = inRect.rightEdge();
+ isect = theRectLine.intersect(centerToPoint);
+ // If we are out of range for the right edge
+ if (isect.hasValue() && inBounds(*isect, 0.0f, 1.0f)) {
+ distance = theRectLine.dy();
+ theEdge = EdgeTypes::Right;
+ }
+ } else {
+ theRectLine = inRect.leftEdge();
+ isect = theRectLine.intersect(centerToPoint);
+ if (isect.hasValue() && inBounds(*isect, 0.0f, 1.0f)) {
+ distance = theRectLine.dy();
+ theEdge = EdgeTypes::Left;
+ }
+ }
+ // If we haven't resolved the edge type
+ if (theEdge == EdgeTypes::UnsetEdgeType) {
+ if (centerToPoint.dy() < 0) {
+ theRectLine = inRect.topEdge();
+ isect = theRectLine.intersect(centerToPoint);
+ theEdge = EdgeTypes::Top;
+ distance = theRectLine.dx();
+ } else {
+ theRectLine = inRect.bottomEdge();
+ isect = theRectLine.intersect(centerToPoint);
+ theEdge = EdgeTypes::Bottom;
+ distance = theRectLine.dx();
+ }
+ }
+ // Now drop a perpendicular from the point to the rect line.
+ SLine normalLine(inPoint, inPoint + QT3DSVec2(theRectLine.dy(), -theRectLine.dx()));
+ isect = theRectLine.intersect(normalLine);
+ if (isect.isEmpty()) {
+ theEdge = EdgeTypes::Right;
+ isect = .5f;
+ }
+ SEndPoint retval(theEdge, *isect);
+ QT3DSF32 normalizedBoundary =
+ NVMax(0.0f, inEdgeBoundary / static_cast<float>(fabs(distance)));
+
+ QT3DSF32 edgeLowerBound = NVMax(0.0f, normalizedBoundary);
+ QT3DSF32 edgeUpperBound = NVMin(1.0f, 1.0f - normalizedBoundary);
+ retval.m_Interp = NVMax(edgeLowerBound, retval.m_Interp);
+ retval.m_Interp = NVMin(edgeUpperBound, retval.m_Interp);
+ return retval;
+ }
+
+ // Default end points always are in the middle of the rect edge
+ SEndPoint CEditorTransitionPath::CalculateDefaultEndPoint(const SRect &inRect,
+ const QT3DSVec2 &inPoint)
+ {
+ SEndPoint ep = CalculateEndPoint(inRect, inPoint, 0.0f);
+ return SEndPoint(ep.m_EdgeType, .5f);
+ }
+
+ void CEditorTransitionPath::SetEndPoint(const QT3DSVec2 &inWorldPoint)
+ {
+ QT3DS_ASSERT(m_EndRect.hasValue());
+ m_End = CalculateEndPoint(*m_EndRect, inWorldPoint, m_StateEdgeBuffer);
+ MarkDirty();
+ }
+
+ void CEditorTransitionPath::SetBeginPoint(const QT3DSVec2 &inWorldPoint)
+ {
+ QT3DS_ASSERT(m_BeginRect.hasValue());
+ m_Begin = CalculateEndPoint(*m_BeginRect, inWorldPoint, m_StateEdgeBuffer);
+ MarkDirty();
+ }
+
+ SEndPoint CEditorTransitionPath::GetActualBeginPoint() const
+ {
+ return DoGetActualEndPoint(m_Begin, *m_BeginRect, m_EndRect->center());
+ }
+
+ SEndPoint CEditorTransitionPath::GetActualEndPoint() const
+ {
+ return DoGetActualEndPoint(m_End, *m_EndRect, m_BeginRect->center());
+ }
+
+ void CEditorTransitionPath::SetControlPoint(QT3DSI32 idx, const QT3DSVec2 &inPosition,
+ bool inMoveAdjacentEndPoint)
+ {
+ if (idx < 0 || idx >= (QT3DSI32)m_ControlPoints.size()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ m_ControlPoints[idx].Set(inPosition);
+ if (inMoveAdjacentEndPoint) {
+ // Move the end points adjacent to the handle.
+ QT3DSI32 possiblePoint = MapControlPointToPossibleControlPoint(idx);
+ size_t numPossible = m_PossibleControlPoints.size();
+ if (possiblePoint == 0)
+ SetBeginPoint(inPosition);
+ if (possiblePoint == ((QT3DSI32)numPossible - 1))
+ SetEndPoint(inPosition);
+ }
+
+ MarkDirty();
+ }
+
+ void CEditorTransitionPath::SetControlPoints(const TPointList &inList)
+ {
+ QT3DS_ASSERT(inList.size() == m_Path.size());
+ for (size_t idx = 0, end = m_ControlPoints.size(); idx < end; ++idx) {
+ SControlPoint &theControlPoint(m_ControlPoints[idx]);
+ if (theControlPoint.m_PathIndex >= 0
+ && theControlPoint.m_PathIndex < (QT3DSI32)inList.size())
+ theControlPoint.Set(inList[theControlPoint.m_PathIndex]);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ TPointList CEditorTransitionPath::GetPath() const
+ {
+ MaybeRegeneratePath();
+ return m_Path;
+ }
+
+ TControlPointList CEditorTransitionPath::GetPossibleControlPoints() const
+ {
+ MaybeRegeneratePath();
+ return m_PossibleControlPoints;
+ }
+
+ SControlPoint CEditorTransitionPath::GetPossibleControlPoint(QT3DSI32 inIdx) const
+ {
+ MaybeRegeneratePath();
+ if (inIdx >= 0 && inIdx < (QT3DSI32)m_PossibleControlPoints.size())
+ return m_PossibleControlPoints[inIdx];
+ QT3DS_ASSERT(false);
+ return SControlPoint();
+ }
+
+ // This may create a new control point thus invalidating the path and possible control
+ // points.
+ QT3DSI32
+ CEditorTransitionPath::MapPossibleControlPointToControlPoint(QT3DSI32 inPossiblePointIndex)
+ {
+ if (inPossiblePointIndex < 0
+ || inPossiblePointIndex >= (QT3DSI32)m_PossibleControlPoints.size()) {
+ QT3DS_ASSERT(false);
+ return -1;
+ }
+ const SControlPoint &thePossiblePoint(m_PossibleControlPoints[inPossiblePointIndex]);
+ TControlPointList::iterator iter = eastl::lower_bound(
+ m_ControlPoints.begin(), m_ControlPoints.end(), thePossiblePoint);
+ QT3DSI32 retval = (QT3DSI32)m_ControlPoints.size();
+ if (iter != m_ControlPoints.end()) {
+ retval = (QT3DSI32)(iter - m_ControlPoints.begin());
+ if (iter->m_PathIndex == thePossiblePoint.m_PathIndex)
+ return retval;
+ }
+
+ m_ControlPoints.insert(iter, thePossiblePoint);
+ return retval;
+ }
+
+ QT3DSI32 CEditorTransitionPath::MapControlPointToPossibleControlPoint(QT3DSI32 inPointIndex)
+ {
+ if (inPointIndex < 0 || inPointIndex >= (QT3DSI32)m_ControlPoints.size()) {
+ QT3DS_ASSERT(false);
+ return -1;
+ }
+ const SControlPoint &theControlPoint(m_ControlPoints[inPointIndex]);
+ TControlPointList::iterator iter = eastl::lower_bound(
+ m_PossibleControlPoints.begin(), m_PossibleControlPoints.end(), theControlPoint);
+ if (iter != m_PossibleControlPoints.end()) {
+ QT3DSI32 retval = (QT3DSI32)(iter - m_PossibleControlPoints.begin());
+ if (iter->m_PathIndex == theControlPoint.m_PathIndex)
+ return retval;
+ }
+ QT3DS_ASSERT(false);
+ return -1;
+ }
+
+ bool CEditorTransitionPath::DoesControlPointExist(QT3DSI32 inPossiblePointIndex) const
+ {
+ if (inPossiblePointIndex < 0
+ || inPossiblePointIndex >= (QT3DSI32)m_PossibleControlPoints.size()) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ const SControlPoint &thePossiblePoint(m_PossibleControlPoints[inPossiblePointIndex]);
+ TControlPointList::const_iterator iter = eastl::lower_bound(
+ m_ControlPoints.begin(), m_ControlPoints.end(), thePossiblePoint);
+ if (iter != m_ControlPoints.end() && iter->m_PathIndex == thePossiblePoint.m_PathIndex)
+ return true;
+ return false;
+ }
+
+ // Run through the control point list and if you find another control point on the line,
+ // return it's index. Else
+ // bail.
+ // If you are finding the remove algorithm is too specific or hard to use increase the 2.0f
+ // numbers below.
+ inline Option<size_t> NextParallelControlPointOnLine(const SControlPoint &inItem,
+ const SControlPoint &inEndPoint,
+ const TControlPointList &inList,
+ size_t inStartIdx)
+ {
+ for (size_t idx = inStartIdx, end = inList.size(); idx < end; ++idx) {
+ const SControlPoint &theTestPoint(inList[idx]);
+ if (theTestPoint.m_Direction == inItem.m_Direction) {
+ if (CEditorTransitionPath::AreAlmostEqual(inItem.m_Position,
+ theTestPoint.m_Position, 2.0f))
+ return idx + 1;
+ else
+ return Empty();
+ }
+ }
+
+ // Check if beginning and end lie in the same path, or within just a couple pixels.
+ if (inItem.m_Direction == inEndPoint.m_Direction
+ && CEditorTransitionPath::AreAlmostEqual(inItem.m_Position, inEndPoint.m_Position,
+ 2.0f))
+ return inList.size();
+
+ return Empty();
+ }
+
+ // We try to find control point that point the same direction and lie on the same line with
+ // only control points with
+ // orthogonal directions in between. If we find points that fullfill this criteria, we know
+ // we can remove all intermediate
+ // points because the transition path will end up making a straight line.
+ bool CEditorTransitionPath::RemoveRedundantControlPoints()
+ {
+ if (m_ControlPoints.empty())
+ return false;
+
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theStartPoint = GetBeginPointAndEdge();
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theEndPoint;
+ if (m_EndRect.hasValue())
+ theEndPoint = GetEndpointPoint(m_End, *m_EndRect, m_BeginRect->center());
+ else
+ theEndPoint = theStartPoint;
+ // Find runs of control points in the same line. Remove the points in the middle of the
+ // line.
+ SControlPoint theLastControlPoint(EdgeTypeToDirectionType(theStartPoint.second));
+ theLastControlPoint.Set(theStartPoint.first);
+ SControlPoint theEndControlPoint(EdgeTypeToDirectionType(theEndPoint.second));
+ theEndControlPoint.Set(theEndPoint.first);
+ size_t numControlPoints(m_ControlPoints.size());
+ for (size_t idx = 0, end = numControlPoints; idx < end; ++idx) {
+ Option<size_t> removeEnd = NextParallelControlPointOnLine(
+ theLastControlPoint, theEndControlPoint, m_ControlPoints, idx);
+ if (removeEnd.isEmpty() == false) {
+ size_t lastItem = *removeEnd;
+ m_ControlPoints.erase(m_ControlPoints.begin() + idx,
+ m_ControlPoints.begin() + lastItem);
+ --idx;
+ end = m_ControlPoints.size();
+ } else
+ theLastControlPoint = m_ControlPoints[idx];
+ }
+ if (m_ControlPoints.size() != numControlPoints) {
+ MarkDirty();
+ return true;
+ }
+ return false;
+ }
+
+ void CEditorTransitionPath::RestoreAutoTransition()
+ {
+ m_ControlPoints.clear();
+ m_Begin = SEndPoint();
+ m_End = SEndPoint();
+ MarkDirty();
+ }
+
+ bool CEditorTransitionPath::IsManualMode() const
+ {
+ return m_Begin.m_EdgeType != EdgeTypes::UnsetEdgeType
+ || m_End.m_EdgeType != EdgeTypes::UnsetEdgeType || m_ControlPoints.empty() == false;
+ }
+
+ SPointQueryResult CEditorTransitionPath::Pick(QT3DSVec2 inPoint, QT3DSVec2 inControlBoxDims,
+ QT3DSVec2 inEndBoxDims)
+ {
+ MaybeRegeneratePath();
+
+ if (inEndBoxDims.x && inEndBoxDims.y) {
+ SRect endBox(QT3DSVec2(-1.0f * inEndBoxDims.x / 2, -1.0f * inEndBoxDims.y / 2),
+ inEndBoxDims);
+ SRect testRect(endBox);
+ testRect.translate(m_Path.front());
+ if (testRect.contains(inPoint))
+ return SPointQueryResult(PointQueryResultType::Begin);
+ testRect = SRect(endBox);
+ testRect.translate(m_Path.back());
+ if (testRect.contains(inPoint))
+ return SPointQueryResult(PointQueryResultType::End);
+ }
+ if (inControlBoxDims.x && inControlBoxDims.y) {
+ SRect theControlBox(
+ QT3DSVec2(-1.0f * inControlBoxDims.x / 2.0f, -1.0f * inControlBoxDims.y / 2.0f),
+ inControlBoxDims);
+ for (size_t idx = 0, end = m_PossibleControlPoints.size(); idx < end; ++idx) {
+ const SControlPoint &thePoint(m_PossibleControlPoints[idx]);
+ QT3DSVec2 startPoint = m_Path[thePoint.m_PathIndex];
+ QT3DSVec2 endPoint = m_Path[thePoint.m_PathIndex + 1];
+ // We stretch the rect to contain the entire line, not just where we display the
+ // point.
+ QT3DSVec2 lineDims = endPoint - startPoint;
+ QT3DSF32 lineRectHeight = SControlPoint::GetComponent(theControlBox.m_WidthHeight,
+ thePoint.m_Direction);
+ QT3DSF32 lineRectLength =
+ fabs(SControlPoint::GetOrthogonalComponent(lineDims, thePoint.m_Direction));
+ QT3DSVec2 rectDims = SControlPoint::FromComponentToVector(
+ lineRectHeight, lineRectLength, thePoint.m_Direction);
+ QT3DSVec2 rectTopLeft =
+ QT3DSVec2(NVMin(startPoint.x, endPoint.x), NVMin(startPoint.y, endPoint.y));
+ QT3DSF32 rectComponent =
+ SControlPoint::GetComponent(rectTopLeft, thePoint.m_Direction);
+ rectComponent -= lineRectHeight / 2.0f; // Center the box about the line.
+ rectTopLeft = SControlPoint::SetComponent(rectTopLeft, rectComponent,
+ thePoint.m_Direction);
+ SRect testRect(rectTopLeft, rectDims);
+ if (testRect.contains(inPoint))
+ return SPointQueryResult(PointQueryResultType::Control, (QT3DSI32)idx);
+ }
+ }
+ return PointQueryResultType::NoPoint;
+ }
+
+ SPointQueryResult
+ CEditorTransitionPath::PickClosestControlPoint(QT3DSVec2 inPoint,
+ DirectionTypes::Enum inDirectionType)
+ {
+ MaybeRegeneratePath();
+ QT3DSI32 closestIdx = -1;
+ QT3DSF32 minDistance = QT3DS_MAX_F32;
+
+ for (size_t idx = 0, end = m_PossibleControlPoints.size(); idx < end; ++idx) {
+ const SControlPoint &thePoint(m_PossibleControlPoints[idx]);
+ QT3DSVec2 startPoint = m_Path[thePoint.m_PathIndex];
+ QT3DSVec2 endPoint = m_Path[thePoint.m_PathIndex + 1];
+ SLine theLine(startPoint, endPoint);
+ QT3DSF32 distance = theLine.distance(inPoint);
+
+ if (distance < minDistance && thePoint.m_Direction == inDirectionType) {
+ closestIdx = idx;
+ minDistance = distance;
+ }
+ }
+ if (closestIdx == -1)
+ return SPointQueryResult();
+ return SPointQueryResult(PointQueryResultType::Control, closestIdx);
+ }
+
+ // The output functions are both setup under these assumptions:
+ // 1. The current point does *not* have representation in the possible control points list.
+ // 2. The last point *does* have representation in the possible control points list.
+ // 3. The algorithm should output all path elements up and to but not including the
+ // current point.
+ // So, given straight line do not output any possible points.
+ // Given zig-zag, output two points.
+ SControlPoint
+ CEditorTransitionPath::OutputParallelPoints(const SControlPoint &inLastPoint,
+ const SControlPoint &inCurrentPoint,
+ QT3DSF32 runWidth) const
+ {
+ const SControlPoint &theRunPoint(inCurrentPoint);
+ const SControlPoint theLastControlPoint(inLastPoint);
+ DirectionTypes::Enum runDirection(inLastPoint.m_Direction);
+ if (AreAlmostEqual(theRunPoint.m_Position, theLastControlPoint.m_Position, 1.0)) {
+ // Straigh line. Perhaps remove this point?
+ theRunPoint.m_PathIndex = theLastControlPoint.m_PathIndex;
+ return theRunPoint;
+ } else {
+ // First, output a possible control point inline with inLastPoint
+ SControlPoint possiblePoint(inLastPoint);
+ possiblePoint.m_PathIndex = (QT3DSI32)(m_Path.size() - 1);
+ m_PossibleControlPoints.push_back(possiblePoint);
+ // Output zig-zag, we zig zag from last control point to theRunPoint. We need to
+ // push two points and two control points.
+ QT3DSVec2 startPos(m_Path.back());
+ QT3DSF32 startComponent = SControlPoint::GetComponent(startPos, runDirection);
+ QT3DSF32 orthoStartComponent =
+ SControlPoint::GetOrthogonalComponent(startPos, runDirection);
+ QT3DSF32 endComponent = theRunPoint.m_Position;
+ QT3DSF32 orthoEndComponent = orthoStartComponent + runWidth;
+ QT3DSVec2 endPos = SControlPoint::FromComponentToVector(
+ endComponent, orthoEndComponent, runDirection);
+ QT3DSF32 zigZagOrthoPos = orthoStartComponent + runWidth / 2;
+ QT3DSI32 crossbarIndex = (QT3DSI32)m_Path.size();
+ QT3DSVec2 crossbarStart = SControlPoint::FromComponentToVector(
+ startComponent, zigZagOrthoPos, runDirection);
+ m_Path.push_back(crossbarStart);
+ m_PossibleControlPoints.push_back(
+ SControlPoint(SControlPoint::OppositeDirection(theRunPoint.m_Direction),
+ orthoStartComponent, crossbarIndex));
+ QT3DSVec2 crossbarEnd = SControlPoint::FromComponentToVector(
+ endComponent, zigZagOrthoPos, theRunPoint.m_Direction);
+ m_Path.push_back(crossbarEnd);
+ theRunPoint.m_PathIndex = crossbarIndex + 1;
+ // Do not, however, output the run point. This will happen in the next step.
+ return inCurrentPoint;
+ }
+ }
+
+ // Given right angle, output 1 point.
+ SControlPoint
+ CEditorTransitionPath::OutputOrthogonalPoints(const SControlPoint &inLastPoint,
+ const SControlPoint &inCurrentPoint) const
+ {
+ SLine lastLine = inLastPoint.ToLine();
+ SLine currentLine = inCurrentPoint.ToLine();
+ Option<QT3DSF32> isect = lastLine.intersect(currentLine);
+ QT3DS_ASSERT(isect.hasValue());
+ inLastPoint.m_PathIndex = (QT3DSI32)(m_Path.size() - 1);
+ m_PossibleControlPoints.push_back(inLastPoint);
+ if (isect.hasValue()) {
+ QT3DSVec2 theIsectPoint = lastLine.toPoint(*isect);
+ m_Path.push_back(theIsectPoint);
+ }
+ inCurrentPoint.m_PathIndex = (QT3DSI32)(m_Path.size() - 1);
+ return inCurrentPoint;
+ }
+
+ void CEditorTransitionPath::MaybeRegeneratePath() const
+ {
+ if (IsDirty() == false)
+ return;
+
+ if (m_TransitionPathType == TransitionPathTypes::BeginToEnd) {
+ // Ensure intermediate information is cleared.
+ const_cast<CEditorTransitionPath *>(this)->MarkDirty();
+ // We don't have the begin and end states.
+ if (m_BeginRect.isEmpty() || m_EndRect.isEmpty()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ // Find the start and end points.
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theStartPoint =
+ GetEndpointPoint(m_Begin, *m_BeginRect, m_EndRect->center());
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theEndPoint =
+ GetEndpointPoint(m_End, *m_EndRect, m_BeginRect->center());
+ m_Path.push_back(theStartPoint.first);
+ SControlPoint theLastControlPoint(EdgeTypeToDirectionType(theStartPoint.second));
+ theLastControlPoint.Set(theStartPoint.first);
+ theLastControlPoint.m_PathIndex = 0;
+ SControlPoint theEndControlPoint(EdgeTypeToDirectionType(theEndPoint.second));
+ theEndControlPoint.Set(theEndPoint.first);
+ for (size_t idx = 0, end = m_ControlPoints.size(); idx < end; ++idx) {
+ const SControlPoint &thePoint(m_ControlPoints[idx]);
+ if (thePoint.m_Direction == theLastControlPoint.m_Direction) {
+ // zig zag. Requires us to find the first point that *isn't a zig zag in
+ // order to
+ // calculate where the zig zag should be. We could have a section composed
+ // of only
+ // parallel directions and we can't lay then out until we find how much
+ // distance we have
+ // to space each on out.
+ // Image you get to this point and you find you have a set of control points
+ // with vertical direction.
+ // Their positions will tell us how far left each one should sit. But we
+ // don't have enough information
+ // to lay them out without knowing how much vertical space this section
+ // should fill. So we would have to
+ // search forward until we can figure this out.
+ QT3DSVec2 runStart = m_Path.back();
+ // Search forward until either we run out of points or until we find a point
+ // who's direction
+ // does not match the current direction. We call a contiguous set of
+ // control points who all
+ // have the same direction a 'run'.
+ size_t runEnd;
+ size_t zigzagCount = 1;
+ DirectionTypes::Enum runDirection = theLastControlPoint.m_Direction;
+ // Search forward till we find a point that is different.
+ for (runEnd = idx + 1; runEnd < end
+ && m_ControlPoints[runEnd].m_Direction == thePoint.m_Direction;
+ ++runEnd) {
+ // Skip items that are in line. They shouldn't be counted towards our
+ // zigzag count.
+ if (AreAlmostEqual(m_ControlPoints[runEnd].m_Position,
+ m_ControlPoints[runEnd - 1].m_Position)
+ == false)
+ ++zigzagCount;
+ }
+ // Two possible cases. Either we find a control point that has a different
+ // direction in which case we then figure out
+ // how much space we need overall *or* we ran out of control points in which
+ // case we use the end point.
+ QT3DSVec2 runEndPoint(0, 0);
+ if (runEnd == end) {
+ // check if the end point direction is the same. This could be the
+ // final zig zag. Else it will be a righthand turn
+ if (EdgeTypeToDirectionType(theEndPoint.second) == runDirection
+ && AreAlmostEqual(theEndControlPoint.m_Position,
+ thePoint.m_Position)
+ == false)
+ ++zigzagCount;
+
+ runEndPoint = theEndPoint.first;
+ } else {
+ SLine thePointLine(thePoint.ToLine());
+ Option<QT3DSF32> isect =
+ thePointLine.intersect(m_ControlPoints[runEnd].ToLine());
+ if (isect.hasValue())
+ runEndPoint = thePointLine.toPoint(*isect);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ QT3DSF32 runOrthoStart =
+ SControlPoint::GetOrthogonalComponent(runStart, runDirection);
+ QT3DSF32 runOrthoEnd =
+ SControlPoint::GetOrthogonalComponent(runEndPoint, runDirection);
+ QT3DSF32 runRange = runOrthoEnd - runOrthoStart;
+ QT3DSF32 runWidth = runRange / (QT3DSF32)zigzagCount;
+ // Now we iterate through the run itself and output path elements.
+ for (; idx < runEnd; ++idx) {
+ theLastControlPoint = OutputParallelPoints(
+ theLastControlPoint, m_ControlPoints[idx], runWidth);
+ }
+ // Subtract one to account for the loop upate that happens next
+ --idx;
+ } else // right angle
+ {
+ theLastControlPoint =
+ OutputOrthogonalPoints(theLastControlPoint, m_ControlPoints[idx]);
+ }
+ }
+ // Finished iterating through the control points. Now we have the sticky situation
+ // of the very last point
+ // and how it joins with the end point.
+ QT3DSVec2 lastPoint(m_Path.back());
+ if (theEndControlPoint.m_Direction == theLastControlPoint.m_Direction) {
+ QT3DSF32 lastPointOrthoComponent = SControlPoint::GetOrthogonalComponent(
+ lastPoint, theLastControlPoint.m_Direction);
+ QT3DSF32 endOrthoComponent = SControlPoint::GetOrthogonalComponent(
+ theEndPoint.first, theLastControlPoint.m_Direction);
+ QT3DSF32 runWidth = endOrthoComponent - lastPointOrthoComponent;
+ OutputParallelPoints(theLastControlPoint, theEndControlPoint, runWidth);
+ } else {
+ theLastControlPoint =
+ OutputOrthogonalPoints(theLastControlPoint, theEndControlPoint);
+ }
+ // Now output the last possible point which matches the end control point's
+ // direction and such.
+ theEndControlPoint.m_PathIndex = (QT3DSI32)(m_Path.size() - 1);
+#ifdef _DEBUG
+ // The directly previous possible point in the list should not match this point. In
+ // fact, it really should be orthogonal.
+ if (m_PossibleControlPoints.size()) {
+ QT3DS_ASSERT(m_PossibleControlPoints.back().m_Direction
+ != theEndControlPoint.m_Direction
+ || AreAlmostEqual(m_PossibleControlPoints.back().m_Position,
+ theEndControlPoint.m_Position)
+ == false);
+ }
+#endif
+ m_PossibleControlPoints.push_back(theEndControlPoint);
+ // Finally push back the last item.
+ m_Path.push_back(theEndPoint.first);
+ } else if (m_TransitionPathType == TransitionPathTypes::BeginToBegin
+ || m_TransitionPathType == TransitionPathTypes::Targetless) {
+ QT3DSVec2 beginCenter(m_BeginRect->center());
+ beginCenter.x += 1;
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> theStartPoint =
+ GetEndpointPoint(m_Begin, *m_BeginRect, beginCenter);
+ QT3DSVec2 lineDir;
+ m_Path.push_back(theStartPoint.first);
+ if (m_TransitionPathType == TransitionPathTypes::BeginToBegin) {
+ switch (theStartPoint.second) {
+ case EdgeTypes::Top:
+ lineDir = QT3DSVec2(0, -1);
+ break;
+ case EdgeTypes::Bottom:
+ lineDir = QT3DSVec2(0, 1);
+ break;
+ case EdgeTypes::Left:
+ lineDir = QT3DSVec2(-1, 0);
+ break;
+ case EdgeTypes::Right:
+ lineDir = QT3DSVec2(1, 0);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ QT3DSF32 squareDiagLen = 30;
+ QT3DSF32 halfDiag = squareDiagLen / 2.0f;
+ QT3DSVec2 theOppPoint = theStartPoint.first + lineDir * squareDiagLen;
+ QT3DSVec2 middle = (theStartPoint.first + theOppPoint) / 2.0f;
+ QT3DSVec2 orthoLineDir = QT3DSVec2(lineDir.y, lineDir.x);
+ QT3DSVec2 loopTop = middle + orthoLineDir * halfDiag;
+ QT3DSVec2 loopBottom = middle - orthoLineDir * halfDiag;
+ m_Path.push_back(loopTop);
+ m_Path.push_back(theOppPoint);
+ m_Path.push_back(loopBottom);
+ m_Path.push_back(theStartPoint.first);
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+}
+} \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.h b/src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.h
new file mode 100644
index 00000000..24a4aa29
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorTransitionPath.h
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_TRANSITION_PATH_H
+#define UIC_STATE_EDITOR_TRANSITION_PATH_H
+#pragma once
+#include "UICState.h"
+#include "foundation/Qt3DSVec2.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSOption.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ struct EdgeTypes
+ {
+ enum Enum {
+ UnsetEdgeType = 0,
+ Left,
+ Right,
+ Top,
+ Bottom,
+ };
+ };
+
+ struct SEndPoint
+ {
+ // Which edge are we on
+ EdgeTypes::Enum m_EdgeType;
+ // How far from the start of the edge are we.
+ QT3DSF32 m_Interp;
+ SEndPoint(EdgeTypes::Enum inType = EdgeTypes::UnsetEdgeType, QT3DSF32 interp = .5f)
+ : m_EdgeType(inType)
+ , m_Interp(interp)
+ {
+ }
+ };
+
+ struct DirectionTypes
+ {
+ enum Enum {
+ UnknownDirection = 0,
+ Horizontal,
+ Vertical,
+ };
+ };
+
+ struct SLine
+ {
+ QT3DSVec2 m_Begin;
+ QT3DSVec2 m_End;
+
+ SLine(const QT3DSVec2 &beg = QT3DSVec2(0, 0), const QT3DSVec2 &end = QT3DSVec2(0, 0))
+ : m_Begin(beg)
+ , m_End(end)
+ {
+ }
+
+ QT3DSF32 dx() const { return m_End.x - m_Begin.x; }
+ QT3DSF32 dy() const { return m_End.y - m_Begin.y; }
+ QT3DSVec2 begin() const { return m_Begin; }
+ QT3DSVec2 end() const { return m_End; }
+ QT3DSVec2 toPoint(QT3DSF32 interp) { return m_Begin + QT3DSVec2(dx() * interp, dy() * interp); }
+ Option<QT3DSF32> slope() const
+ {
+ QT3DSF32 run = dx();
+ if (fabs(run) > .0001f)
+ return dy() / dx();
+ return Empty();
+ }
+ // If this function returns a value, it returns an interpolation value such that if you
+ // call toPoint on the return value it gives you the intersection point.
+ // http://tog.acm.org/resources/GraphicsGems/gemsiii/insectc.c
+ // Simplifications taken from Qt's line intersect
+ Option<QT3DSF32> intersect(const SLine &other) const
+ {
+ // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
+ QT3DSVec2 a = m_End - m_Begin;
+ QT3DSVec2 b = other.m_End - other.m_Begin;
+ QT3DSVec2 c = m_Begin - other.m_Begin;
+
+ QT3DSF32 denominator = a.y * b.x - a.x * b.y;
+
+ if (denominator == 0 || fabs(denominator) < .0001f)
+ return Empty();
+
+ QT3DSF32 reciprocal = 1.0f / denominator;
+ return (b.y * c.x - b.x * c.y) * reciprocal;
+ }
+
+ // Caculates the top half of the distance to line equation with the fabs or sqrt.
+ QT3DSF32 distanceNumerator(const QT3DSVec2 &inPoint) const
+ {
+ QT3DSF32 x2 = inPoint.x;
+ QT3DSF32 y2 = inPoint.y;
+
+ QT3DSF32 x1 = m_End.x;
+ QT3DSF32 y1 = m_End.y;
+
+ QT3DSF32 x0 = m_Begin.x;
+ QT3DSF32 y0 = m_Begin.y;
+ return ((x2 - x1) * (y1 - y0)) - ((x1 - x0) * (y2 - y1));
+ }
+
+ QT3DSF32 distance(const QT3DSVec2 &inPoint) const
+ {
+ QT3DSF32 theDx = dx();
+ QT3DSF32 theDy = dy();
+ return fabs(distanceNumerator(inPoint)) / sqrtf(theDx * theDx + theDy * theDy);
+ }
+ };
+
+ // Rect in same coordinate space as QT.
+ struct SRect
+ {
+ QT3DSVec2 m_TopLeft;
+ QT3DSVec2 m_WidthHeight;
+ SRect(const QT3DSVec2 &tl = QT3DSVec2(0, 0), const QT3DSVec2 &wh = QT3DSVec2(0, 0))
+ : m_TopLeft(tl)
+ , m_WidthHeight(wh)
+ {
+ }
+ QT3DSF32 left() const { return m_TopLeft.x; }
+ QT3DSF32 top() const { return m_TopLeft.y; }
+ QT3DSF32 right() const { return m_TopLeft.x + width(); }
+ QT3DSF32 bottom() const { return m_TopLeft.y + height(); }
+ QT3DSF32 width() const { return m_WidthHeight.x; }
+ QT3DSF32 height() const { return m_WidthHeight.y; }
+ QT3DSVec2 topLeft() const { return m_TopLeft; }
+ QT3DSVec2 bottomLeft() const { return QT3DSVec2(left(), bottom()); }
+ QT3DSVec2 bottomRight() const { return QT3DSVec2(right(), bottom()); }
+ QT3DSVec2 topRight() const { return QT3DSVec2(right(), top()); }
+ QT3DSVec2 center() const
+ {
+ return QT3DSVec2(left() + width() / 2.0f, top() + height() / 2.0f);
+ }
+ SLine leftEdge() const { return SLine(topLeft(), bottomLeft()); }
+ SLine rightEdge() const { return SLine(topRight(), bottomRight()); }
+ SLine topEdge() const { return SLine(topLeft(), topRight()); }
+ SLine bottomEdge() const { return SLine(bottomLeft(), bottomRight()); }
+ void translate(QT3DSF32 x, QT3DSF32 y)
+ {
+ m_TopLeft.x += x;
+ m_TopLeft.y += y;
+ }
+ void translate(const QT3DSVec2 &vec)
+ {
+ m_TopLeft.x += vec.x;
+ m_TopLeft.y += vec.y;
+ }
+ bool contains(const QT3DSVec2 &inPoint) const;
+ };
+
+ struct SControlPoint
+ {
+ DirectionTypes::Enum m_Direction;
+ // World space position
+ QT3DSF32 m_Position;
+ // This is a calculated value. Values set will be ignored in favor of recaculating by
+ // re-deriving
+ // the transition path.
+ mutable QT3DSI32 m_PathIndex;
+ SControlPoint(DirectionTypes::Enum inDir = DirectionTypes::UnknownDirection,
+ QT3DSF32 pos = 0.0f, QT3DSI32 idx = -1)
+ : m_Direction(inDir)
+ , m_Position(pos)
+ , m_PathIndex(idx)
+ {
+ }
+ bool operator<(const SControlPoint &inOther) const
+ {
+ return m_PathIndex < inOther.m_PathIndex;
+ }
+ static QT3DSF32 GetComponent(const QT3DSVec2 &inPoint, DirectionTypes::Enum inDir)
+ {
+ switch (inDir) {
+ case DirectionTypes::Horizontal:
+ return inPoint.y;
+ break;
+ case DirectionTypes::Vertical:
+ return inPoint.x;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return 0;
+ }
+ static DirectionTypes::Enum OppositeDirection(DirectionTypes::Enum inDir)
+ {
+ switch (inDir) {
+ case DirectionTypes::Horizontal:
+ return DirectionTypes::Vertical;
+ default:
+ return DirectionTypes::Horizontal;
+ }
+ }
+ static QT3DSF32 GetOrthogonalComponent(const QT3DSVec2 &inPoint, DirectionTypes::Enum inDir)
+ {
+ switch (inDir) {
+ case DirectionTypes::Horizontal:
+ return inPoint.x;
+ default:
+ return inPoint.y;
+ }
+ }
+ static QT3DSVec2 FromComponentToVector(QT3DSF32 inComponent, QT3DSF32 orthoComponent,
+ DirectionTypes::Enum inDir)
+ {
+ switch (inDir) {
+ case DirectionTypes::Horizontal:
+ return QT3DSVec2(orthoComponent, inComponent);
+ default:
+ return QT3DSVec2(inComponent, orthoComponent);
+ }
+ }
+ static QT3DSVec2 SetComponent(const QT3DSVec2 &inPoint, QT3DSF32 inValue,
+ DirectionTypes::Enum inDir)
+ {
+ switch (inDir) {
+ case DirectionTypes::Horizontal:
+ return QT3DSVec2(inPoint.x, inValue);
+ default:
+ return QT3DSVec2(inValue, inPoint.y);
+ }
+ }
+ void Set(const QT3DSVec2 &inPoint) { m_Position = GetComponent(inPoint, m_Direction); }
+ SLine ToLine() const
+ {
+ switch (m_Direction) {
+ case DirectionTypes::Horizontal:
+ return SLine(QT3DSVec2(0, m_Position), QT3DSVec2(1, m_Position));
+ default:
+ return SLine(QT3DSVec2(m_Position, 0), QT3DSVec2(m_Position, 1));
+ }
+ }
+ };
+
+ typedef eastl::vector<SControlPoint> TControlPointList;
+ typedef eastl::vector<QT3DSVec2> TPointList;
+
+ struct PointQueryResultType
+ {
+ enum Enum {
+ NoPoint = 0,
+ Begin,
+ End,
+ Control,
+ };
+ };
+
+ struct SPointQueryResult
+ {
+ PointQueryResultType::Enum m_QueryType;
+ QT3DSI32 m_Index;
+ SPointQueryResult(
+ PointQueryResultType::Enum inResultType = PointQueryResultType::NoPoint,
+ QT3DSI32 inIndex = -1)
+ : m_QueryType(inResultType)
+ , m_Index(inIndex)
+ {
+ }
+ };
+
+ struct TransitionPathTypes
+ {
+ enum Enum {
+ UnknownPathType = 0,
+ BeginToEnd = 1,
+ BeginToBegin = 2,
+ Targetless = 3,
+ };
+ };
+
+ class CEditorTransitionPath
+ {
+ QT3DSF32 m_StateEdgeBuffer;
+ Option<SRect> m_BeginRect;
+ Option<SRect> m_EndRect;
+ SEndPoint m_Begin;
+ SEndPoint m_End;
+ // Control points that the user has edited.
+ TControlPointList m_ControlPoints;
+ TransitionPathTypes::Enum m_TransitionPathType;
+
+ // ephemeral data, can be derived from start,end points (along with start/end state) and
+ // the
+ // user control points.
+ mutable TPointList m_Path;
+ // The full set of possible control points can be derived from the path.
+ mutable TControlPointList m_PossibleControlPoints;
+
+ public:
+ CEditorTransitionPath(QT3DSF32 inStateEdgeBuffer = 10.0f)
+ : m_StateEdgeBuffer(inStateEdgeBuffer)
+ , m_TransitionPathType(TransitionPathTypes::BeginToEnd)
+ {
+ }
+ Option<SRect> GetBeginRect() const { return m_BeginRect; }
+ void SetBeginRect(const Option<SRect> &inRect)
+ {
+ m_BeginRect = inRect;
+ MarkDirty();
+ }
+
+ Option<SRect> GetEndRect() const { return m_EndRect; }
+ void SetEndRect(const Option<SRect> &inRect)
+ {
+ m_EndRect = inRect;
+ MarkDirty();
+ }
+
+ TransitionPathTypes::Enum GetPathType() const { return m_TransitionPathType; }
+ // May delete all the control points.
+ void SetPathType(TransitionPathTypes::Enum inType);
+ // This may move control points if instart rect and inendrect have shifted by similar
+ // amounts
+ // Returns true if persistent data changed, false otherwise.
+ bool UpdateBeginEndRects(const SRect &inStartRect, const SRect &inEndRect);
+ bool UpdateBeginEndRects(const SRect &inStartRect,
+ TransitionPathTypes::Enum inPathType);
+ eastl::pair<QT3DSVec2, QT3DSVec2> GetBeginEndPoints() const;
+
+ SEndPoint GetEndPoint() const { return m_End; }
+ void SetEndPoint(const SEndPoint &pt)
+ {
+ m_End = pt;
+ MarkDirty();
+ }
+ void SetEndPoint(const QT3DSVec2 &inWorldPoint);
+
+ SEndPoint GetBeginPoint() const { return m_Begin; }
+ void SetBeginPoint(const SEndPoint &pt)
+ {
+ m_Begin = pt;
+ MarkDirty();
+ }
+ void SetBeginPoint(const QT3DSVec2 &inWorldPoint);
+ // Return where the end point will be. Will not return an invalid in point
+ // or an end point where information is not set.
+ SEndPoint GetActualBeginPoint() const;
+ SEndPoint GetActualEndPoint() const;
+
+ TControlPointList GetControlPoints() const { return m_ControlPoints; }
+ SControlPoint GetControlPoint(QT3DSI32 inIndex) const
+ {
+ if (inIndex < (QT3DSI32)m_ControlPoints.size())
+ return m_ControlPoints[inIndex];
+ return SControlPoint();
+ }
+ void SetControlPoints(const TControlPointList &list)
+ {
+ m_ControlPoints = list;
+ MarkDirty();
+ }
+ void SetControlPoint(QT3DSI32 inControlPointIndex, const QT3DSVec2 &inPosition,
+ bool inMoveAdjacentEndPoint);
+
+ // Set the control points by updating the individual items in the path list.
+ // This works if you do not add/remove points from the list.
+ //
+ // list = GetPath
+ // move points, don't add,delete
+ // setControlPoints(list)
+ void SetControlPoints(const TPointList &inList);
+ TPointList GetPath() const;
+ TControlPointList GetPossibleControlPoints() const;
+ SControlPoint GetPossibleControlPoint(QT3DSI32 inIdx) const;
+
+ // This may create a new control point thus invalidating the path and possible control
+ // points.
+ QT3DSI32 MapPossibleControlPointToControlPoint(QT3DSI32 inPossiblePointIndex);
+ QT3DSI32 MapControlPointToPossibleControlPoint(QT3DSI32 inPointIndex);
+ // Returns true if MapPossibleControlPointToControlPoint will *not* create a new point
+ // false otherwise.
+ bool DoesControlPointExist(QT3DSI32 inPossiblePointIndex) const;
+
+ // Returns true if any points were removed.
+ bool RemoveRedundantControlPoints();
+
+ void RestoreAutoTransition();
+
+ bool IsManualMode() const;
+
+ // Query against the dataset to see what got picked. Includes the endoints.
+ // The rects should be centered about the original and just describe the picking
+ // rect to hit against. Empty rects will not get hit.
+ // Note that the result is the index into the possible point list where the hit
+ // happened.
+ // If you intend to manipulate the point, you need to call
+ // MapPossibleControlPointToControlPoint,
+ // Which may add a control point which you then can manipulate.
+ SPointQueryResult Pick(QT3DSVec2 inPoint, QT3DSVec2 inControlBoxDims,
+ QT3DSVec2 inEndBoxDims = QT3DSVec2(0, 0));
+ SPointQueryResult PickClosestControlPoint(QT3DSVec2 inPoint,
+ DirectionTypes::Enum inDirectionType);
+
+ void MarkDirty()
+ {
+ m_Path.clear();
+ m_PossibleControlPoints.clear();
+ for (size_t idx = 0, end = m_ControlPoints.size(); idx < end; ++idx)
+ m_ControlPoints[idx].m_PathIndex = -1;
+ }
+
+ bool IsDirty() const { return m_Path.empty(); }
+
+ static SEndPoint CalculateEndPoint(const SRect &inRect, const QT3DSVec2 &inPoint,
+ QT3DSF32 inEdgeBoundary);
+ static SEndPoint CalculateDefaultEndPoint(const SRect &inRect, const QT3DSVec2 &inPoint);
+ static bool AreAlmostEqual(QT3DSF32 lhs, QT3DSF32 rhs, QT3DSF32 error = .001f)
+ {
+ if (fabs(lhs - rhs) < error)
+ return true;
+ return false;
+ }
+
+ static bool AreAlmostEqual(const QT3DSVec2 &lhs, const QT3DSVec2 &rhs, QT3DSF32 error = .001f)
+ {
+ return AreAlmostEqual(lhs.x, rhs.x, error) && AreAlmostEqual(lhs.y, rhs.y, error);
+ }
+
+ // Regenerates the path if this object is dirty.
+ void MaybeRegeneratePath() const;
+
+ eastl::pair<QT3DSVec2, EdgeTypes::Enum> GetBeginPointAndEdge() const;
+
+ protected:
+ // Output the path between points that have the same direction.
+ SControlPoint OutputParallelPoints(const SControlPoint &inLastPoint,
+ const SControlPoint &inCurrentPoint,
+ QT3DSF32 inRunWidth) const;
+ SControlPoint OutputOrthogonalPoints(const SControlPoint &inLastPoint,
+ const SControlPoint &inCurrentPoint) const;
+ };
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICStateEditorValue.h b/src/Runtime/Source/UICState/Editor/UICStateEditorValue.h
new file mode 100644
index 00000000..1a6acf6e
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICStateEditorValue.h
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EDITOR_VALUE_H
+#define UIC_STATE_EDITOR_VALUE_H
+#pragma once
+#include "UICState.h"
+#include "UICStateEditor.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "foundation/Qt3DSVec3.h"
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ struct ValueTypes
+ {
+ enum Enum {
+ NoEditorValue = 0,
+ String,
+ ObjPtr,
+ ObjPtrList,
+ Vec2,
+ Vec2List,
+ Vec3,
+ Boolean,
+ U32,
+ };
+ };
+
+ template <typename TDataType>
+ struct SValueTypeMap
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::NoEditorValue; }
+ };
+
+ template <>
+ struct SValueTypeMap<TEditorStr>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::String; }
+ };
+ template <>
+ struct SValueTypeMap<TObjPtr>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::ObjPtr; }
+ };
+ template <>
+ struct SValueTypeMap<TObjList>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::ObjPtrList; }
+ };
+ template <>
+ struct SValueTypeMap<QT3DSVec2>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::Vec2; }
+ };
+ template <>
+ struct SValueTypeMap<TVec2List>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::Vec2List; }
+ };
+ template <>
+ struct SValueTypeMap<QT3DSVec3>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::Vec3; }
+ };
+ template <>
+ struct SValueTypeMap<bool>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::Boolean; }
+ };
+ template <>
+ struct SValueTypeMap<QT3DSU32>
+ {
+ static ValueTypes::Enum GetType() { return ValueTypes::U32; }
+ };
+
+ struct SValueUnionTraits
+ {
+ typedef ValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(TVec2List),
+ };
+
+ static TIdType getNoDataId() { return ValueTypes::NoEditorValue; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case ValueTypes::String:
+ return inVisitor(*NVUnionCast<TEditorStr *>(inData));
+ case ValueTypes::ObjPtr:
+ return inVisitor(*NVUnionCast<TObjPtr *>(inData));
+ case ValueTypes::ObjPtrList:
+ return inVisitor(*NVUnionCast<TObjList *>(inData));
+ case ValueTypes::Vec2:
+ return inVisitor(*NVUnionCast<QT3DSVec2 *>(inData));
+ case ValueTypes::Vec2List:
+ return inVisitor(*NVUnionCast<TVec2List *>(inData));
+ case ValueTypes::Vec3:
+ return inVisitor(*NVUnionCast<QT3DSVec3 *>(inData));
+ case ValueTypes::Boolean:
+ return inVisitor(*NVUnionCast<bool *>(inData));
+ case ValueTypes::U32:
+ return inVisitor(*NVUnionCast<QT3DSU32 *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case ValueTypes::NoEditorValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case ValueTypes::String:
+ return inVisitor(*NVUnionCast<const TEditorStr *>(inData));
+ case ValueTypes::ObjPtr:
+ return inVisitor(*NVUnionCast<const TObjPtr *>(inData));
+ case ValueTypes::ObjPtrList:
+ return inVisitor(*NVUnionCast<const TObjList *>(inData));
+ case ValueTypes::Vec2:
+ return inVisitor(*NVUnionCast<const QT3DSVec2 *>(inData));
+ case ValueTypes::Vec2List:
+ return inVisitor(*NVUnionCast<const TVec2List *>(inData));
+ case ValueTypes::Vec3:
+ return inVisitor(*NVUnionCast<const QT3DSVec3 *>(inData));
+ case ValueTypes::Boolean:
+ return inVisitor(*NVUnionCast<const bool *>(inData));
+ case ValueTypes::U32:
+ return inVisitor(*NVUnionCast<const QT3DSU32 *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case ValueTypes::NoEditorValue:
+ return inVisitor();
+ }
+ }
+ };
+ }
+}
+}
+
+#ifndef _INTEGRITYPLATFORM
+// need some specializations in the original nv foundation namespace
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<QT3DSVec2>
+ {
+ void destruct(QT3DSVec2 &) {}
+ };
+ template <>
+ struct DestructTraits<QT3DSVec3>
+ {
+ void destruct(QT3DSVec3 &) {}
+ };
+}
+}
+#endif
+
+namespace uic {
+namespace state {
+ namespace editor {
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SValueUnionTraits,
+ SValueUnionTraits::TBufferSize>,
+ SValueUnionTraits::TBufferSize>
+ TEditorUnionType;
+
+ struct SValue : public TEditorUnionType
+ {
+ SValue() {}
+
+ SValue(const SValue &inOther)
+ : TEditorUnionType(static_cast<const TEditorUnionType &>(inOther))
+ {
+ }
+
+ SValue(const char8_t *inOther)
+ : TEditorUnionType(TEditorStr(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SValue(const TDataType &inDt)
+ : TEditorUnionType(inDt)
+ {
+ }
+
+ SValue &operator=(const SValue &inOther)
+ {
+ TEditorUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SValue &inOther) const
+ {
+ return TEditorUnionType::operator==(inOther);
+ }
+ bool operator!=(const SValue &inOther) const
+ {
+ return TEditorUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == ValueTypes::NoEditorValue; }
+ };
+
+ struct SValueOpt : public Option<SValue>
+ {
+ SValueOpt(const SValueOpt &inOther)
+ : Option<SValue>(inOther)
+ {
+ }
+ SValueOpt(const Empty &)
+ : Option<SValue>()
+ {
+ }
+ SValueOpt() {}
+ template <typename TDataType>
+ SValueOpt(const TDataType &inOther)
+ : Option<SValue>(SValue(inOther))
+ {
+ }
+ SValueOpt &operator=(const SValueOpt &inOther)
+ {
+ Option<SValue>::operator=(inOther);
+ return *this;
+ }
+ };
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Editor/UICUIADatamodel.cpp b/src/Runtime/Source/UICState/Editor/UICUIADatamodel.cpp
new file mode 100644
index 00000000..3f1d6fd9
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICUIADatamodel.cpp
@@ -0,0 +1,2527 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICUIADatamodel.h"
+#include "foundation/IOStreams.h"
+#include "foundation/XML.h"
+#include "foundation/FileTools.h"
+#include "UICStateEditorFoundation.h"
+#include "UICStateApplication.h"
+#include "UICRenderInputStreamFactory.h"
+#include "EASTL/map.h"
+#include "EASTL/sort.h"
+#include "UICStateEditorTransactionImpl.h"
+#include "UICUIADatamodelValue.h"
+#include "foundation/StringConversion.h"
+#include "foundation/StringConversionImpl.h"
+#include "UICDMStringTable.h"
+
+using namespace uic::app;
+using uic::render::IInputStreamFactory;
+
+namespace uic {
+namespace app {
+
+ struct ElementSubTypes
+ {
+ enum Enum {
+ NoSubType = 0,
+ Component = 1,
+ Behavior = 2,
+ };
+ };
+
+ struct SAppElement
+ {
+ TEditorStr m_Path;
+ TEditorStr m_Type;
+ TEditorStr m_Name;
+ TEditorStr m_Id;
+ Q3DStudio::TAttOrArgList m_Attributes;
+ Q3DStudio::TVisualEventList m_VisualEvents;
+ eastl::vector<NVScopedRefCounted<SAppElement>> m_Children;
+ eastl::vector<SDatamodelValue> m_InitialValues;
+
+ private:
+ QT3DSI32 m_RefCount;
+
+ public:
+ SAppElement()
+ : m_RefCount(0)
+ {
+ }
+
+ virtual ~SAppElement() {}
+
+ void addRef() { ++m_RefCount; }
+
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+
+ virtual ElementSubTypes::Enum GetSubType() { return ElementSubTypes::NoSubType; }
+ };
+}
+}
+
+namespace {
+
+typedef eastl::basic_string<char8_t> TStrType;
+struct IPropertyParser
+{
+ virtual ~IPropertyParser() {}
+ virtual Option<TStrType> ParseStr(const char8_t *inName) = 0;
+ virtual Option<QT3DSF32> ParseFloat(const char8_t *inName) = 0;
+ virtual Option<QT3DSVec2> ParseVec2(const char8_t *inName) = 0;
+ virtual Option<QT3DSVec3> ParseVec3(const char8_t *inName) = 0;
+ virtual Option<bool> ParseBool(const char8_t *inName) = 0;
+ virtual Option<QT3DSU32> ParseU32(const char8_t *inName) = 0;
+ virtual Option<QT3DSI32> ParseI32(const char8_t *inName) = 0;
+};
+
+struct SMetaPropertyParser : public IPropertyParser
+{
+ Q3DStudio::IRuntimeMetaData &m_MetaData;
+ IStringTable &m_StringTable;
+ TStrType m_TempStr;
+ qt3ds::foundation::CRegisteredString m_Type;
+ qt3ds::foundation::CRegisteredString m_ClassId;
+
+ SMetaPropertyParser(const char8_t *inType, const char8_t *inClass,
+ Q3DStudio::IRuntimeMetaData &inMeta, IStringTable &stringTable)
+ : m_MetaData(inMeta)
+ , m_StringTable(stringTable)
+ , m_Type(stringTable.RegisterStr(inType))
+ , m_ClassId(stringTable.RegisterStr(inClass))
+ {
+ }
+
+ qt3ds::foundation::CRegisteredString Register(const char8_t *inName)
+ {
+ return m_StringTable.RegisterStr(inName);
+ }
+
+ virtual Option<TStrType> ParseStr(const char8_t *inName)
+ {
+ qt3ds::foundation::CRegisteredString theName(Register(inName));
+ Q3DStudio::ERuntimeDataModelDataType theType(
+ m_MetaData.GetPropertyType(m_Type, theName, m_ClassId));
+ if (theType != Q3DStudio::ERuntimeDataModelDataTypeObjectRef
+ && theType != Q3DStudio::ERuntimeDataModelDataTypeLong4) {
+ return m_MetaData.GetPropertyValueString(m_Type, theName, m_ClassId);
+ }
+ return Empty();
+ }
+ virtual Option<QT3DSF32> ParseFloat(const char8_t *inName)
+ {
+ return m_MetaData.GetPropertyValueFloat(m_Type, Register(inName), m_ClassId);
+ }
+ virtual Option<QT3DSVec2> ParseVec2(const char8_t *inName)
+ {
+ Option<qt3ds::QT3DSVec3> theProperty =
+ m_MetaData.GetPropertyValueVector2(m_Type, Register(inName), m_ClassId);
+ if (theProperty.hasValue()) {
+ return QT3DSVec2(theProperty->x, theProperty->y);
+ }
+ return Empty();
+ }
+ virtual Option<QT3DSVec3> ParseVec3(const char8_t *inName)
+ {
+ Option<qt3ds::QT3DSVec3> theProperty =
+ m_MetaData.GetPropertyValueVector3(m_Type, Register(inName), m_ClassId);
+ if (theProperty.hasValue()) {
+ return *theProperty;
+ }
+ return Empty();
+ }
+ virtual Option<bool> ParseBool(const char8_t *inName)
+ {
+ return m_MetaData.GetPropertyValueBool(m_Type, Register(inName), m_ClassId);
+ }
+
+ virtual Option<QT3DSU32> ParseU32(const char8_t *inName)
+ {
+ Option<long> retval = m_MetaData.GetPropertyValueLong(m_Type, Register(inName), m_ClassId);
+ if (retval.hasValue())
+ return (QT3DSU32)retval.getValue();
+ return Empty();
+ }
+
+ virtual Option<QT3DSI32> ParseI32(const char8_t *inName)
+ {
+ Option<long> retval = m_MetaData.GetPropertyValueLong(m_Type, Register(inName), m_ClassId);
+ if (retval.hasValue())
+ return (QT3DSI32)retval.getValue();
+ return Empty();
+ }
+};
+
+struct SDomReaderPropertyParser : public IPropertyParser
+{
+ IDOMReader &m_Reader;
+ nvvector<char8_t> &m_TempBuf;
+ MemoryBuffer<ForwardingAllocator> &m_ReadBuffer;
+
+ SDomReaderPropertyParser(IDOMReader &reader, nvvector<char8_t> &inTempBuf,
+ MemoryBuffer<ForwardingAllocator> &readBuf)
+ : m_Reader(reader)
+ , m_TempBuf(inTempBuf)
+ , m_ReadBuffer(readBuf)
+ {
+ }
+ virtual Option<TStrType> ParseStr(const char8_t *inName)
+ {
+ const char8_t *retval;
+ if (m_Reader.UnregisteredAtt(inName, retval))
+ return TStrType(retval);
+ return Empty();
+ }
+ virtual Option<QT3DSF32> ParseFloat(const char8_t *inName)
+ {
+ QT3DSF32 retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+ virtual Option<QT3DSVec2> ParseVec2(const char8_t *inName)
+ {
+ QT3DSVec2 retval;
+ const char8_t *tempVal;
+
+ if (m_Reader.UnregisteredAtt(inName, tempVal)) {
+ eastl::string tempBuffer(tempVal);
+ Char8TReader theReader(const_cast<char *>(tempBuffer.c_str()), m_ReadBuffer);
+ NVDataRef<QT3DSF32> theDataRef(toDataRef(&retval.x, 2));
+ theReader.ReadRef(theDataRef);
+ return retval;
+ }
+ return Empty();
+ }
+ virtual Option<QT3DSVec3> ParseVec3(const char8_t *inName)
+ {
+ QT3DSVec3 retval;
+ const char8_t *tempVal;
+ if (m_Reader.UnregisteredAtt(inName, tempVal)) {
+ eastl::string tempBuffer(tempVal);
+ Char8TReader theReader(const_cast<char *>(tempBuffer.c_str()), m_ReadBuffer);
+ NVDataRef<QT3DSF32> theDataRef(toDataRef(&retval.x, 3));
+ theReader.ReadRef(theDataRef);
+ return retval;
+ }
+ return Empty();
+ }
+ virtual Option<bool> ParseBool(const char8_t *inName)
+ {
+ bool retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+
+ virtual Option<QT3DSU32> ParseU32(const char8_t *inName)
+ {
+ QT3DSU32 retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+
+ virtual Option<QT3DSI32> ParseI32(const char8_t *inName)
+ {
+ QT3DSI32 retval;
+ if (m_Reader.Att(inName, retval))
+ return retval;
+ return Empty();
+ }
+};
+
+template <typename TDataType>
+struct SParserHelper
+{
+};
+template <>
+struct SParserHelper<TStrType>
+{
+ static Option<TStrType> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseStr(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSF32>
+{
+ static Option<QT3DSF32> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseFloat(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSVec2>
+{
+ static Option<QT3DSVec2> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseVec2(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSVec3>
+{
+ static Option<QT3DSVec3> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseVec3(inName);
+ }
+};
+template <>
+struct SParserHelper<bool>
+{
+ static Option<bool> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseBool(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSU32>
+{
+ static Option<QT3DSU32> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseU32(inName);
+ }
+};
+template <>
+struct SParserHelper<QT3DSI32>
+{
+ static Option<QT3DSI32> Parse(const char8_t *inName, IPropertyParser &inParser)
+ {
+ return inParser.ParseI32(inName);
+ }
+};
+
+struct SSlideInfo
+{
+ TEditorStr m_Name;
+};
+
+struct SAppComponent : public SAppElement
+{
+ TEditorStrList m_Slides;
+ virtual ElementSubTypes::Enum GetSubType() { return ElementSubTypes::Component; }
+};
+
+struct SAppBehavior : public SAppElement
+{
+ Q3DStudio::THandlerList m_Handlers;
+ virtual ElementSubTypes::Enum GetSubType() { return ElementSubTypes::Behavior; }
+};
+
+struct SVSEditorObject;
+
+struct SVSEditor
+{
+ TFoundationPtr m_Foundation;
+ NVScopedRefCounted<STransactionManagerImpl> m_TransactionManager;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ SVSEditor(TFoundationPtr fnd, IStringTable &inStringTable)
+ : m_Foundation(fnd)
+ , m_TransactionManager(QT3DS_NEW(m_Foundation->getAllocator(), STransactionManagerImpl)(fnd))
+ , m_StringTable(inStringTable)
+ {
+ }
+
+ virtual void RemoveObjectFromGraph(SVSEditorObject &inObj) = 0;
+ STransaction *GetOpenTransactionImpl()
+ {
+ return m_TransactionManager->GetOpenTransactionImpl();
+ }
+};
+
+struct SVSEditorObject : public IEditorObject
+{
+ TFoundationPtr m_Foundation;
+ SVSEditor &m_Editor;
+ TObjPtr m_ParentObject;
+ TPropertyAccessorList m_PropertyAccessors;
+ QT3DSI32 mRefCount;
+ SVSEditorObject(SVSEditor &editor, TObjPtr parent, const char8_t *typeName,
+ const TPropertyAccessorList &ioList)
+ : IEditorObject(typeName)
+ , m_Foundation(editor.m_Foundation)
+ , m_Editor(editor)
+ , m_ParentObject(parent)
+ , m_PropertyAccessors(ioList)
+ , mRefCount(0)
+ {
+ }
+
+ virtual TEditorStr GetId() { return TEditorStr(); }
+ virtual TEditorStr GetDescription() { return TEditorStr(); }
+ virtual void SetId(const TEditorStr &) { QT3DS_ASSERT(false); }
+ virtual void SetDescription(const TEditorStr &) { QT3DS_ASSERT(false); }
+
+ virtual TObjPtr Parent() { return m_ParentObject; }
+
+ IPropertyAccessor *FindPropertyAccessor(const char8_t *inName)
+ {
+ CRegisteredString nameStr = m_Editor.m_StringTable->RegisterStr(inName);
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx)
+ if (m_PropertyAccessors[idx]->m_Declaration.m_Name == nameStr)
+ return m_PropertyAccessors[idx].mPtr;
+ return NULL;
+ }
+
+ virtual void GetProperties(eastl::vector<SPropertyDeclaration> &outProperties)
+ {
+ outProperties.clear();
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx)
+ outProperties.push_back(m_PropertyAccessors[idx]->m_Declaration);
+ }
+
+ virtual Option<SPropertyDeclaration> FindProperty(const char8_t *propName)
+ {
+ for (size_t idx = 0, end = m_PropertyAccessors.size(); idx < end; ++idx) {
+ if (AreEqual(m_PropertyAccessors[idx]->m_Declaration.m_Name.c_str(), propName))
+ return m_PropertyAccessors[idx]->m_Declaration;
+ }
+ return Empty();
+ }
+
+ virtual eastl::vector<CRegisteredString> GetLegalValues(const char8_t *)
+ {
+ return eastl::vector<CRegisteredString>();
+ }
+
+ virtual Option<SValue> GetPropertyValue(const char8_t *inPropName)
+ {
+ IPropertyAccessor *accessor = FindPropertyAccessor(inPropName);
+ if (accessor) {
+ return accessor->Get(*this);
+ }
+ return Empty();
+ }
+ virtual void SetPropertyValue(const char8_t *inPropName, const SValueOpt &inValue)
+ {
+ IPropertyAccessor *accessor = FindPropertyAccessor(inPropName);
+ if (accessor) {
+ STransaction *theTransaction = m_Editor.GetOpenTransactionImpl();
+ if (theTransaction) {
+ Option<SValue> existing = accessor->Get(*this);
+ theTransaction->m_Changes.push_back(
+ new SChange(existing, inValue, *accessor, *this));
+ }
+ accessor->Set(*this, inValue);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ virtual void RemoveObjectFromGraph() { m_Editor.RemoveObjectFromGraph(*this); }
+ virtual void RemoveIdFromContext() {}
+ virtual void AddIdToContext() {}
+ virtual IEditor &GetEditor() { return m_ParentObject->GetEditor(); }
+};
+
+template <typename TEditorType>
+struct SGenericPropertyStringAccessor : public SPropertyAccessorBase<TEditorType>
+{
+ typedef TEditorStr TDataType;
+ typedef TDataType TEditorType::*TPropertyPtr;
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ TPropertyPtr m_Property;
+
+ SGenericPropertyStringAccessor(TFoundationPtr inAlloc, const SPropertyDeclaration &inDec,
+ TPropertyPtr inPtr)
+ : TBaseType(inAlloc, inDec)
+ , m_Property(inPtr)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ TDataType &dtype = inObj.*(this->m_Property);
+ return SValue(dtype);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ TDataType &dtype = inObj.*(this->m_Property);
+ dtype.clear();
+ if (inValue.hasValue() && inValue->getType() == ValueTypes::String)
+ dtype = inValue->getData<TEditorStr>();
+ }
+};
+
+template <typename TEditorType>
+struct SGenericPropertyStringFunctionAccessor : public SPropertyAccessorBase<TEditorType>
+{
+ typedef TEditorStr TDataType;
+ typedef TDataType (TEditorType::*TGetter)() const;
+ typedef void (TEditorType::*TSetter)(const TDataType &);
+ typedef SPropertyAccessorBase<TEditorType> TBaseType;
+
+ TGetter m_Getter;
+ TSetter m_Setter;
+
+ SGenericPropertyStringFunctionAccessor(TFoundationPtr inAlloc,
+ const SPropertyDeclaration &inDec, TGetter inGetter,
+ TSetter inSetter)
+ : TBaseType(inAlloc, inDec)
+ , m_Getter(inGetter)
+ , m_Setter(inSetter)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Allocator, this->mRefCount);
+
+ virtual Option<SValue> DoGet(TEditorType &inObj)
+ {
+ TDataType dtype = (inObj.*m_Getter)();
+ return SValue(dtype);
+ }
+
+ virtual void DoSet(TEditorType &inObj, const Option<SValue> &inValue)
+ {
+ TDataType dtype;
+ dtype.clear();
+ if (inValue.hasValue() && inValue->getType() == ValueTypes::String)
+ dtype = inValue->getData<TEditorStr>();
+
+ (inObj.*m_Setter)(dtype);
+ }
+};
+
+struct SGotoSlideEditor : public SVSEditorObject
+{
+ TEditorStr m_Component;
+ TEditorStr m_Slide;
+ TEditorStr m_Rel;
+ TEditorStr m_Wrap;
+ TEditorStr m_Direction;
+ TEditorStr m_State;
+ TEditorStr m_Mode;
+ TEditorStr m_PlayThroughTo;
+ TEditorStr m_Rate;
+ TEditorStr m_Time;
+ static void CreateProperties(TPropertyAccessorList &ioList, SVSEditor &editor)
+ {
+ if (ioList.size())
+ return;
+
+ typedef SGenericPropertyStringAccessor<SGotoSlideEditor> TStrProp;
+ typedef SGenericPropertyStringFunctionAccessor<SGotoSlideEditor> TStrFunProp;
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("element"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_Component));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrFunProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("slide"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::GetSlide, &SGotoSlideEditor::SetSlide));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrFunProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("rel"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::GetRel, &SGotoSlideEditor::SetRel));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("wrap"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_Wrap));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation,
+ SPropertyDeclaration(editor.m_StringTable->RegisterStr("direction"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_Direction));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("state"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_State));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("mode"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_Mode));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation,
+ SPropertyDeclaration(editor.m_StringTable->RegisterStr("playthroughto"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_PlayThroughTo));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("rate"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_Rate));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("time"),
+ EditorPropertyTypes::String),
+ &SGotoSlideEditor::m_Time));
+ }
+
+ SGotoSlideEditor(SVSEditor &editor, TObjPtr parent, const TPropertyAccessorList &ioList)
+ : SVSEditorObject(editor, parent, ElementName(), ioList)
+ {
+ }
+
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Foundation, this->mRefCount);
+
+ static const char8_t *ElementName() { return "goto-slide"; }
+
+ void SetSlide(const TEditorStr &inSlide)
+ {
+ if (inSlide.empty() == false) {
+ if (m_Editor.GetOpenTransactionImpl())
+ SetPropertyValue("rel", SValueOpt());
+ else
+ m_Rel.clear();
+ }
+ m_Slide = inSlide;
+ }
+
+ TEditorStr GetSlide() const { return m_Slide; }
+
+ void SetRel(const TEditorStr &inRel)
+ {
+ if (inRel.empty() == false) {
+ if (m_Editor.GetOpenTransactionImpl())
+ SetPropertyValue("slide", SValueOpt());
+ else
+ m_Slide.clear();
+ }
+ m_Rel = inRel;
+ }
+
+ TEditorStr GetRel() const { return m_Rel; }
+};
+
+struct SRunHandlerEditor : public SVSEditorObject
+{
+ TEditorStr m_Behavior;
+ TEditorStr m_Handler;
+ TEditorStr m_ArgumentStr;
+ static void CreateProperties(TPropertyAccessorList &ioList, SVSEditor &editor)
+ {
+ if (ioList.size())
+ return;
+
+ typedef SGenericPropertyStringAccessor<SRunHandlerEditor> TStrProp;
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("element"),
+ EditorPropertyTypes::String),
+ &SRunHandlerEditor::m_Behavior));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("handler"),
+ EditorPropertyTypes::String),
+ &SRunHandlerEditor::m_Handler));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation,
+ SPropertyDeclaration(editor.m_StringTable->RegisterStr("arguments"),
+ EditorPropertyTypes::String),
+ &SRunHandlerEditor::m_ArgumentStr));
+ }
+ SRunHandlerEditor(SVSEditor &editor, TObjPtr parent, const TPropertyAccessorList &ioList)
+ : SVSEditorObject(editor, parent, ElementName(), ioList)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Foundation, this->mRefCount);
+ static const char8_t *ElementName() { return "call"; }
+};
+
+struct SSetAttributeEditor : public SVSEditorObject
+{
+ TEditorStr m_Element;
+ TEditorStr m_Attribute;
+ TEditorStr m_Value;
+
+ static void CreateProperties(TPropertyAccessorList &ioList, SVSEditor &editor)
+ {
+ if (ioList.size())
+ return;
+
+ typedef SGenericPropertyStringAccessor<SSetAttributeEditor> TStrProp;
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("element"),
+ EditorPropertyTypes::String),
+ &SSetAttributeEditor::m_Element));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation,
+ SPropertyDeclaration(editor.m_StringTable->RegisterStr("attribute"),
+ EditorPropertyTypes::String),
+ &SSetAttributeEditor::m_Attribute));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("value"),
+ EditorPropertyTypes::String),
+ &SSetAttributeEditor::m_Value));
+ }
+ SSetAttributeEditor(SVSEditor &editor, TObjPtr parent, const TPropertyAccessorList &ioList)
+ : SVSEditorObject(editor, parent, ElementName(), ioList)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Foundation, this->mRefCount);
+ static const char8_t *ElementName() { return "set-attribute"; }
+};
+
+struct SFireEventEditor : public SVSEditorObject
+{
+ TEditorStr m_Element;
+ TEditorStr m_Event;
+
+ static void CreateProperties(TPropertyAccessorList &ioList, SVSEditor &editor)
+ {
+ if (ioList.size())
+ return;
+
+ typedef SGenericPropertyStringAccessor<SFireEventEditor> TStrProp;
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("element"),
+ EditorPropertyTypes::String),
+ &SFireEventEditor::m_Element));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("event"),
+ EditorPropertyTypes::String),
+ &SFireEventEditor::m_Event));
+ }
+ SFireEventEditor(SVSEditor &editor, TObjPtr parent, const TPropertyAccessorList &ioList)
+ : SVSEditorObject(editor, parent, ElementName(), ioList)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Foundation, this->mRefCount);
+ static const char8_t *ElementName() { return "fire-event"; }
+};
+
+struct SSetPresentationEditor : public SVSEditorObject
+{
+ TEditorStr m_Ref;
+ TEditorStr m_Attribute;
+ TEditorStr m_Value;
+
+ static void CreateProperties(TPropertyAccessorList &ioList, SVSEditor &editor)
+ {
+ if (ioList.size())
+ return;
+
+ typedef SGenericPropertyStringAccessor<SSetPresentationEditor> TStrProp;
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("ref"),
+ EditorPropertyTypes::String),
+ &SSetPresentationEditor::m_Ref));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation,
+ SPropertyDeclaration(editor.m_StringTable->RegisterStr("attribute"),
+ EditorPropertyTypes::String),
+ &SSetPresentationEditor::m_Attribute));
+
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("value"),
+ EditorPropertyTypes::String),
+ &SSetPresentationEditor::m_Value));
+ }
+ SSetPresentationEditor(SVSEditor &editor, TObjPtr parent, const TPropertyAccessorList &ioList)
+ : SVSEditorObject(editor, parent, ElementName(), ioList)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Foundation, this->mRefCount);
+ static const char8_t *ElementName() { return "set-presentation"; }
+};
+
+struct SPlaySoundEditor : public SVSEditorObject
+{
+ TEditorStr m_FilePath;
+
+ static void CreateProperties(TPropertyAccessorList &ioList, SVSEditor &editor)
+ {
+ if (ioList.size())
+ return;
+
+ typedef SGenericPropertyStringAccessor<SPlaySoundEditor> TStrProp;
+ ioList.push_back(QT3DS_NEW(editor.m_Foundation->getAllocator(), TStrProp)(
+ editor.m_Foundation, SPropertyDeclaration(editor.m_StringTable->RegisterStr("file"),
+ EditorPropertyTypes::String),
+ &SPlaySoundEditor::m_FilePath));
+ }
+ SPlaySoundEditor(SVSEditor &editor, TObjPtr parent, const TPropertyAccessorList &ioList)
+ : SVSEditorObject(editor, parent, ElementName(), ioList)
+ {
+ }
+ UIC_STATE_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(this->m_Foundation, this->mRefCount);
+ static const char8_t *ElementName() { return "play-sound"; }
+};
+
+struct SVSEntry
+{
+ QT3DSI32 mRefCount;
+ InterpreterEventTypes::Enum m_EventType;
+ TObjList m_Editors;
+
+ SVSEntry(InterpreterEventTypes::Enum evtType = InterpreterEventTypes::UnknownInterpreterEvent)
+ : mRefCount(0)
+ , m_EventType(evtType)
+ {
+ }
+ void addRef() { ++mRefCount; }
+ void release()
+ {
+ --mRefCount;
+ if (mRefCount <= 0)
+ delete this;
+ }
+};
+
+struct SVSEntryListChange : public IChange
+{
+ TObjPtr m_Object;
+ NVScopedRefCounted<SVSEntry> m_Entry;
+ QT3DSI32 m_Index;
+ bool m_AddOnDo;
+ TObjPtr m_EditorObj;
+ QT3DSI32 m_RefCount;
+
+ SVSEntryListChange(TObjPtr inObj, TObjPtr inPositionObj, SVSEntry &entry, bool addOnDo,
+ TObjPtr inEditorObj)
+ : m_Object(inObj)
+ , m_Entry(entry)
+ , m_AddOnDo(addOnDo)
+ , m_EditorObj(inEditorObj)
+ , m_RefCount(0)
+ {
+ TObjList::iterator iter =
+ eastl::find(entry.m_Editors.begin(), entry.m_Editors.end(), inPositionObj);
+ m_Index = iter - entry.m_Editors.begin();
+ }
+ void addRef() { ++m_RefCount; }
+ void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+ void add() { m_Entry->m_Editors.insert(m_Entry->m_Editors.begin() + m_Index, m_Object); }
+ void remove()
+ {
+ TObjList::iterator iter =
+ eastl::find(m_Entry->m_Editors.begin(), m_Entry->m_Editors.end(), m_Object);
+ if (iter != m_Entry->m_Editors.end())
+ m_Entry->m_Editors.erase(iter);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ virtual void Do()
+ {
+ if (m_AddOnDo)
+ add();
+ else
+ remove();
+ }
+ virtual void Undo()
+ {
+ if (m_AddOnDo)
+ remove();
+ else
+ add();
+ }
+ virtual TObjPtr GetEditor() { return m_EditorObj; }
+};
+
+typedef eastl::pair<NVScopedRefCounted<SVSEntry>, NVScopedRefCounted<SVSEntry>> TEntryExitPair;
+typedef eastl::map<TEditorStr, TEntryExitPair> TIdEntryExitMap;
+typedef eastl::map<TEditorStr, TIdEntryExitMap> TIdStateMapMap;
+
+struct SIdEntryExitDeleteChange : public IChange
+{
+ TIdEntryExitMap &m_Map;
+ TEditorStr m_Id;
+ TEntryExitPair m_Data;
+ QT3DSI32 m_RefCount;
+ TObjPtr m_EditorObject;
+ bool m_RemoveOnDo;
+ SIdEntryExitDeleteChange(TIdEntryExitMap &inMap, const TEditorStr &inId, TObjPtr inObj,
+ bool removeOnDo = true)
+ : m_Map(inMap)
+ , m_Id(inId)
+ , m_RefCount(0)
+ , m_EditorObject(inObj)
+ , m_RemoveOnDo(removeOnDo)
+ {
+ m_Data = m_Map[m_Id];
+ }
+ virtual void addRef() { ++m_RefCount; }
+ virtual void release()
+ {
+ --m_RefCount;
+ if (m_RefCount <= 0)
+ delete this;
+ }
+ void remove()
+ {
+ TIdEntryExitMap::iterator iter = m_Map.find(m_Id);
+ if (iter != m_Map.end())
+ m_Map.erase(iter);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ void insert() { m_Map[m_Id] = m_Data; }
+ virtual void Do()
+ {
+ if (m_RemoveOnDo)
+ remove();
+ else
+ insert();
+ }
+ virtual void Undo()
+ {
+ if (m_RemoveOnDo)
+ insert();
+ else
+ remove();
+ }
+ virtual TObjPtr GetEditor() { return m_EditorObject; }
+};
+
+struct SEditorEntry
+{
+ TEditorPtr m_Editor;
+ TEditorStr m_Id;
+ TEditorStr m_FilePath;
+};
+
+template <typename TDataType>
+SDatamodelValue ParseInitialProperty(const char8_t *inName, IPropertyParser &metaParser,
+ IPropertyParser &runtimeParser)
+{
+ Option<TDataType> val = SParserHelper<TDataType>::Parse(inName, runtimeParser);
+ if (val.isEmpty())
+ val = SParserHelper<TDataType>::Parse(inName, metaParser);
+ if (val.hasValue())
+ return SDatamodelValue(*val);
+ return SDatamodelValue();
+}
+
+template <typename TDataType>
+SDatamodelValue ParseSlideProperty(const char8_t *inName, IPropertyParser &runtimeParser)
+{
+ Option<TDataType> val = SParserHelper<TDataType>::Parse(inName, runtimeParser);
+ if (val.hasValue())
+ return *val;
+ return SDatamodelValue();
+}
+
+struct DatamodelImpl : public IDatamodel,
+ public ITransManagerImplListener,
+ public SVSEditor,
+ public IEditorCopyPasteListener
+{
+ TEditorStr m_FilePath;
+ QT3DSI32 mRefCount;
+ NVScopedRefCounted<IInputStreamFactory> m_InputStreamFactory;
+ eastl::pair<NVScopedRefCounted<IDOMWriter>, NVScopedRefCounted<IDOMReader>> m_UIADocument;
+ nvvector<SNamespacePair> m_UIANamespaces;
+ bool m_Dirty;
+ nvvector<NVScopedRefCounted<SAppElement>> m_Elements;
+ NVScopedRefCounted<SAppElement> m_FinderElement;
+ nvvector<SEditorEntry> m_Editors;
+ TIdStateMapMap m_IdToStateMaps;
+ eastl::vector<SPresentation> m_Presentations;
+ nvvector<char8_t> m_ParseBuf;
+ Q3DStudio::TAttOrArgList m_SlideProperties;
+ eastl::string m_LoadingErrorString;
+ IStateMachineEditorManager &m_StateMachineEditorManager;
+
+ DatamodelImpl(TFoundationPtr inFoundation, const TEditorStr &inPath, const TEditorStr &inAppDir,
+ IStateMachineEditorManager &inStateMachineEditorManager,
+ IStringTable &inStringTable)
+ : SVSEditor(inFoundation, inStringTable)
+ , m_FilePath(inPath)
+ , mRefCount(0)
+ , m_InputStreamFactory(IInputStreamFactory::Create(m_Foundation->getFoundation()))
+ , m_UIANamespaces(m_Foundation->getAllocator(), "m_UIANamespaces")
+ , m_Dirty(false)
+ , m_Elements(m_Foundation->getAllocator(), "m_Elements")
+ , m_Editors(m_Foundation->getAllocator(), "m_Editors")
+ , m_ParseBuf(inFoundation->getAllocator(), "tempbuf")
+ , m_StateMachineEditorManager(inStateMachineEditorManager)
+ {
+ TEditorStr ext;
+ CFileTools::GetExtension(m_FilePath.c_str(), ext);
+ if (ext.comparei("uia") != 0) {
+ m_FilePath = IApplication::GetLaunchFile(inPath.c_str());
+ }
+ // Check extension, if it isn't what we expect then just set it to uia
+ ext.clear();
+ CFileTools::GetExtension(m_FilePath.c_str(), ext);
+ if (ext.comparei("uia") != 0)
+ CFileTools::SetExtension(m_FilePath, "uia");
+
+ m_InputStreamFactory->AddSearchDirectory(inAppDir.c_str());
+
+ m_TransactionManager->m_ObjListener = this;
+ }
+
+ ~DatamodelImpl() {}
+
+ void addRef() { atomicIncrement(&mRefCount); }
+
+ void release()
+ {
+ TFoundationPtr tempFoundation(m_Foundation);
+ atomicDecrement(&mRefCount);
+ if (mRefCount <= 0) {
+ NVDelete(m_Foundation->getAllocator(), this);
+ }
+ }
+ typedef eastl::map<TEditorStr, Q3DStudio::THandlerList> TIdHandlerMap;
+ typedef eastl::map<TEditorStr, Q3DStudio::TVisualEventList> TIdVisualEventMap;
+ typedef eastl::map<TEditorStr, NVScopedRefCounted<SAppElement>> TIdElemMap;
+
+ SAppElement &ParseElement(IDOMReader &inReader, Q3DStudio::IRuntimeMetaData &inMetaData,
+ eastl::vector<NVScopedRefCounted<SAppElement>> &ioChildList,
+ TIdElemMap &ioElemMap)
+ {
+ IDOMReader::Scope __elemScope(inReader);
+ const char8_t *className = inReader.GetElementName();
+ const char8_t *classRef;
+ inReader.UnregisteredAtt("class", classRef);
+ const char8_t *id;
+ inReader.UnregisteredAtt("id", id);
+ Q3DStudio::SElementInfo elemInfo = inMetaData.LoadElement(className, classRef, id);
+ NVScopedRefCounted<SAppElement> newElem;
+ if (elemInfo.m_ClassName.compare("Behavior") == 0) {
+ SAppBehavior *behavior = new SAppBehavior();
+ behavior->m_Handlers = inMetaData.GetCustomHandlers(id);
+ newElem = behavior;
+ } else if (elemInfo.m_IsComponent) {
+ SAppComponent *component = new SAppComponent();
+ newElem = component;
+ } else {
+ newElem = new SAppElement();
+ }
+ newElem->m_Attributes = elemInfo.m_Attributes;
+ newElem->m_VisualEvents = inMetaData.GetVisualEvents(id);
+ newElem->m_Type = elemInfo.m_ClassName;
+ newElem->m_Id = id;
+ const char8_t *elemName;
+ if (inReader.UnregisteredAtt("name", elemName))
+ newElem->m_Name.assign(elemName);
+ else {
+ Q3DStudio::TRuntimeMetaDataStrType str = inMetaData.GetPropertyValueString(
+ inMetaData.Register(className), inMetaData.Register("name"),
+ inMetaData.Register(id));
+ newElem->m_Name = str;
+ }
+
+ ioChildList.push_back(newElem);
+ m_Elements.push_back(newElem);
+ ioElemMap.insert(eastl::make_pair(TEditorStr(id), newElem));
+ {
+ SMetaPropertyParser theMetaParser(newElem->m_Type.c_str(), classRef, inMetaData,
+ inMetaData.GetStringTable()->GetRenderStringTable());
+ SDomReaderPropertyParser theDOMParser(inReader, m_ParseBuf, inReader.m_TempBuf);
+ for (size_t idx = 0, end = newElem->m_Attributes.size(); idx < end; ++idx) {
+ const SAttOrArg &theAtt(newElem->m_Attributes[idx]);
+ SDatamodelValue newValue;
+ switch (theAtt.m_DataType) {
+ case ERuntimeDataModelDataTypeFloat:
+ newValue = ParseInitialProperty<float>(theAtt.m_Name.c_str(), theMetaParser,
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeFloat2:
+ newValue = ParseInitialProperty<QT3DSVec2>(theAtt.m_Name.c_str(), theMetaParser,
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeFloat3:
+ newValue = ParseInitialProperty<QT3DSVec3>(theAtt.m_Name.c_str(), theMetaParser,
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeLong:
+ newValue = ParseInitialProperty<QT3DSI32>(theAtt.m_Name.c_str(), theMetaParser,
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeString:
+ newValue = ParseInitialProperty<eastl::string>(theAtt.m_Name.c_str(),
+ theMetaParser, theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeBool:
+ newValue = ParseInitialProperty<bool>(theAtt.m_Name.c_str(), theMetaParser,
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeStringRef:
+ newValue = ParseInitialProperty<eastl::string>(theAtt.m_Name.c_str(),
+ theMetaParser, theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeObjectRef:
+ newValue =
+ ParseSlideProperty<eastl::string>(theAtt.m_Name.c_str(), theDOMParser);
+ break;
+ default:
+ break;
+ }
+ newElem->m_InitialValues.push_back(newValue);
+ }
+ }
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling())
+ ParseElement(inReader, inMetaData, newElem->m_Children, ioElemMap);
+
+ return *newElem;
+ }
+
+ // Get the item names if not overridden
+ // Pull the names off so we can construct the item path.
+ void LoadSlide(IDOMReader &inReader, TIdElemMap &inMap)
+ {
+ IDOMReader::Scope __topScope(inReader);
+ for (bool commandSuccess = inReader.MoveToFirstChild(); commandSuccess;
+ commandSuccess = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __commandScope(inReader);
+ const char8_t *elemName = inReader.GetElementName();
+ if (AreEqual(elemName, "Set") || AreEqual(elemName, "Add")) {
+ const char8_t *name;
+ TIdElemMap::iterator iter = inMap.end();
+ const char8_t *itemRef;
+ inReader.UnregisteredAtt("ref", itemRef);
+ if (!isTrivial(itemRef)) {
+ if (itemRef[0] == '#')
+ ++itemRef;
+ iter = inMap.find(TEditorStr(itemRef));
+ }
+
+ if (inReader.UnregisteredAtt("name", name)) {
+ if (iter != inMap.end()) {
+ iter->second->m_Name.assign(name);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ if (iter != inMap.end() && AreEqual(elemName, "Add")) {
+ nvvector<char8_t> theTempBuf(this->m_Foundation->getAllocator(), "tempbuf");
+ SDomReaderPropertyParser theDOMParser(inReader, m_ParseBuf, inReader.m_TempBuf);
+ SAppElement *newElem = iter->second.mPtr;
+ for (size_t idx = 0, end = newElem->m_Attributes.size(); idx < end; ++idx) {
+ const SAttOrArg &theAtt(newElem->m_Attributes[idx]);
+ SDatamodelValue newValue;
+ switch (theAtt.m_DataType) {
+ case ERuntimeDataModelDataTypeFloat:
+ newValue =
+ ParseSlideProperty<float>(theAtt.m_Name.c_str(), theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeFloat2:
+ newValue =
+ ParseSlideProperty<QT3DSVec2>(theAtt.m_Name.c_str(), theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeFloat3:
+ newValue =
+ ParseSlideProperty<QT3DSVec3>(theAtt.m_Name.c_str(), theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeLong:
+ newValue =
+ ParseSlideProperty<QT3DSI32>(theAtt.m_Name.c_str(), theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeString:
+ newValue = ParseSlideProperty<eastl::string>(theAtt.m_Name.c_str(),
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeBool:
+ newValue =
+ ParseSlideProperty<bool>(theAtt.m_Name.c_str(), theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeStringRef:
+ newValue = ParseSlideProperty<eastl::string>(theAtt.m_Name.c_str(),
+ theDOMParser);
+ break;
+ case ERuntimeDataModelDataTypeObjectRef:
+ newValue = ParseSlideProperty<eastl::string>(theAtt.m_Name.c_str(),
+ theDOMParser);
+ break;
+ default:
+ break;
+ }
+ if (newValue.getType() != ERuntimeDataModelDataTypeNone)
+ newElem->m_InitialValues[idx] = newValue;
+ }
+ }
+ }
+ }
+ }
+
+ void ResolveElemPath(SAppElement &inElem, const eastl::string &parentId)
+ {
+ inElem.m_Path = parentId;
+ if (inElem.m_Path.back() != ':')
+ inElem.m_Path.append(1, '.');
+ inElem.m_Path.append(inElem.m_Name);
+ for (size_t idx = 0, end = inElem.m_Children.size(); idx < end; ++idx)
+ ResolveElemPath(*inElem.m_Children[idx], inElem.m_Path);
+ }
+
+ void LoadUIPFile(const char *inRelativePath, const char *inUIPId,
+ Q3DStudio::IRuntimeMetaData &inMetaData)
+ {
+ eastl::string appDir(m_FilePath);
+ CFileTools::GetDirectory(appDir);
+ eastl::string uipPath;
+ CFileTools::CombineBaseAndRelative(appDir.c_str(), inRelativePath, uipPath);
+ CFileSeekableIOStream uipStream(uipPath.c_str(), FileReadFlags());
+ if (!uipStream.IsOpen()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_Foundation->getAllocator(), m_StringTable));
+ SDOMElement *domElem = CDOMSerializer::Read(*theFactory, uipStream).second;
+ if (!domElem) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ NVScopedRefCounted<IDOMReader> theReader(IDOMReader::CreateDOMReader(
+ m_Foundation->getAllocator(), *domElem, m_StringTable, theFactory));
+ if (!theReader->MoveToFirstChild("Project")) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ Q3DStudio::IRuntimeMetaData &theMetaData(inMetaData);
+ theMetaData.ClearPerProjectData();
+
+ TEditorStr rootPath(inUIPId);
+ rootPath.append(1, ':');
+ eastl::vector<NVScopedRefCounted<SAppElement>> topElements;
+ TIdElemMap idElemMap;
+ m_Presentations.push_back(SPresentation());
+ SPresentation &currentPresentation(m_Presentations.back());
+ currentPresentation.m_Id.assign(inUIPId);
+ currentPresentation.m_SrcPath.assign(inRelativePath);
+ {
+ IDOMReader::Scope __projectScope(*theReader);
+ if (theReader->MoveToFirstChild("ProjectSettings")) {
+ const char8_t *temp;
+ theReader->UnregisteredAtt("author", temp);
+ currentPresentation.m_Author.assign(nonNull(temp));
+ theReader->UnregisteredAtt("company", temp);
+ currentPresentation.m_Company.assign(nonNull(temp));
+ theReader->Att("presentationWidth", currentPresentation.m_Width);
+ theReader->Att("presentationHeight", currentPresentation.m_Height);
+ }
+ // Presentation width and height as specified in the file.
+ }
+ // Classes/handlers
+ {
+ IDOMReader::Scope __projectScope(*theReader);
+ if (theReader->MoveToFirstChild("Classes")) {
+ // Load each class system into the meta data and then pull back the handlers
+ for (bool success = theReader->MoveToFirstChild(); success;
+ success = theReader->MoveToNextSibling()) {
+ const char8_t *id, *srcPath, *name;
+ theReader->UnregisteredAtt("id", id);
+ theReader->UnregisteredAtt("sourcepath", srcPath);
+ theReader->UnregisteredAtt("name", name);
+ eastl::string classItemPath;
+ CFileTools::CombineBaseAndRelative(appDir.c_str(), srcPath, classItemPath);
+
+ if (AreEqual(theReader->GetElementName().c_str(), "Behavior")) {
+ bool theLuaFile =
+ theMetaData.LoadLuaFile("Behavior", id, name, classItemPath.c_str());
+ QT3DS_ASSERT(theLuaFile);
+ (void)theLuaFile;
+ } else if (AreEqual(theReader->GetElementName().c_str(), "Effect")) {
+ bool theEffectFile = theMetaData.LoadEffectXMLFile("Effect", id, name,
+ classItemPath.c_str());
+ QT3DS_ASSERT(theEffectFile);
+ (void)theEffectFile;
+ } else if (AreEqual(theReader->GetElementName().c_str(), "RenderPlugin")) {
+ theMetaData.LoadPluginXMLFile("RenderPlugin", id, name,
+ classItemPath.c_str());
+ } else if (AreEqual(theReader->GetElementName().c_str(), "CustomMaterial")) {
+ theMetaData.LoadMaterialXMLFile("CustomMaterial", id, name,
+ classItemPath.c_str());
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+
+ // Graph
+ {
+ IDOMReader::Scope __projectScope(*theReader);
+ if (theReader->MoveToFirstChild("Graph")) {
+ for (bool success = theReader->MoveToFirstChild(); success;
+ success = theReader->MoveToNextSibling()) {
+ currentPresentation.m_Scene =
+ &ParseElement(*theReader, theMetaData, topElements, idElemMap);
+ }
+ }
+ }
+ // States/Slides
+ {
+ // This is where the name *may* be set,
+ IDOMReader::Scope __projectScope(*theReader);
+ if (theReader->MoveToFirstChild("Logic")) {
+ // Slides are just slightly hierarchical, master and then nonmaster children.
+ for (bool success = theReader->MoveToFirstChild(); success;
+ success = theReader->MoveToNextSibling()) {
+ IDOMReader::Scope __masterScope(*theReader);
+ LoadSlide(*theReader, idElemMap);
+ const char8_t *component;
+ theReader->UnregisteredAtt("component", component);
+ NVScopedRefCounted<SAppComponent> theComponent;
+ if (!isTrivial(component)) {
+ if (component[0] == '#')
+ ++component;
+ TIdElemMap::iterator iter = idElemMap.find(TEditorStr(component));
+ if (iter != idElemMap.end()) {
+ if (iter->second->GetSubType() == ElementSubTypes::Component)
+ theComponent = static_cast<SAppComponent *>(iter->second.mPtr);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ for (bool childSuccess = theReader->MoveToFirstChild("State"); childSuccess;
+ childSuccess = theReader->MoveToNextSibling("State")) {
+ IDOMReader::Scope __slideScope(*theReader);
+ const char8_t *slideName;
+ if (theReader->UnregisteredAtt("name", slideName))
+ theComponent->m_Slides.push_back(TEditorStr(slideName));
+ LoadSlide(*theReader, idElemMap);
+ }
+ }
+ }
+ }
+ // Now resolve all the names to create full paths.
+ for (size_t idx = 0, end = topElements.size(); idx < end; ++idx) {
+ ResolveElemPath(*topElements[idx], rootPath);
+ }
+ }
+
+ struct SElemLessThan
+ {
+ bool operator()(NVScopedRefCounted<SAppElement> lhs,
+ NVScopedRefCounted<SAppElement> rhs) const
+ {
+ return lhs->m_Path < rhs->m_Path;
+ }
+ };
+
+ static const char *GetUICNamespace() { return "http://qt.io/qt3dstudio/uia"; }
+ static const char *GetOldUICNamespace() { return "http://qt.io/qt3dstudio/uicomposer"; }
+
+ void LoadUIADatabase()
+ {
+ CFileSeekableIOStream theStream(m_FilePath.c_str(), FileReadFlags());
+ if (theStream.IsOpen()) {
+ LoadUIADatabaseFromStream(theStream);
+ }
+ }
+
+ struct SXmlErrorHandler : public CXmlErrorHandler
+ {
+ SXmlErrorHandler(const eastl::string &inFilePath, eastl::string &inErrorString)
+ : m_FilePath(inFilePath)
+ , m_ErrorString(inErrorString)
+ {
+ }
+ virtual ~SXmlErrorHandler() {}
+ virtual void OnXmlError(TXMLCharPtr errorName, int line, int column)
+ {
+ if (m_ErrorString.empty())
+ m_ErrorString.sprintf("%s(%d, %d): %s", m_FilePath.c_str(), line, column,
+ errorName);
+ }
+ eastl::string m_FilePath;
+ eastl::string &m_ErrorString;
+ };
+
+ void LoadUIADatabaseFromStream(IInStream &inStream)
+ {
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_Foundation->getAllocator(), m_StringTable));
+ m_UIADocument.first = NULL;
+ m_UIADocument.second = NULL;
+ m_UIANamespaces.clear();
+ m_Elements.clear();
+ m_IdToStateMaps.clear();
+ m_Editors.clear();
+ m_Presentations.clear();
+ m_SlideProperties.clear();
+ m_LoadingErrorString.clear();
+ eastl::string appDir(m_FilePath);
+ CFileTools::GetDirectory(appDir);
+
+ SXmlErrorHandler theXmlErrorWriter(m_FilePath, m_LoadingErrorString);
+ eastl::pair<SNamespacePairNode *, SDOMElement *> parseResult =
+ CDOMSerializer::Read(*theFactory, inStream, &theXmlErrorWriter);
+ if (parseResult.second != NULL) {
+ qt3ds::foundation::CRegisteredString theRegisteredOldNamespace =
+ m_StringTable->RegisterStr(GetOldUICNamespace());
+ qt3ds::foundation::CRegisteredString theRegisteredNamespace =
+ m_StringTable->RegisterStr(GetUICNamespace());
+
+ ReplaceDOMNamespace(*parseResult.second, theRegisteredOldNamespace,
+ theRegisteredNamespace);
+
+ m_UIADocument =
+ IDOMWriter::CreateDOMWriter(theFactory, *parseResult.second, m_StringTable);
+ for (SNamespacePairNode *nodePtr = parseResult.first; nodePtr;
+ nodePtr = nodePtr->m_NextNode) {
+ if (nodePtr->m_Namespace == theRegisteredOldNamespace)
+ nodePtr->m_Namespace = theRegisteredNamespace;
+ m_UIANamespaces.push_back(*nodePtr);
+ }
+ }
+
+ if (m_UIADocument.first.mPtr == NULL) {
+ m_UIADocument = IDOMWriter::CreateDOMWriter(m_Foundation->getAllocator(), "application",
+ m_StringTable, GetUICNamespace());
+ m_Dirty = true;
+ }
+ if (m_UIANamespaces.empty())
+ m_UIANamespaces.push_back(
+ SNamespacePair(m_StringTable->RegisterStr(GetUICNamespace())));
+
+ {
+ NVScopedReleasable<Q3DStudio::IRuntimeMetaData> theMetaData(
+ Q3DStudio::IRuntimeMetaData::Create(*m_InputStreamFactory));
+
+ if (theMetaData) {
+ m_SlideProperties = theMetaData->GetSlideAttributes();
+
+ eastl::vector<eastl::pair<TEditorStr, TEditorStr>> machinePathsAndIds;
+ IDOMReader::Scope __appScope(m_UIADocument.second);
+
+ if (m_UIADocument.second->MoveToFirstChild("assets")) {
+ IDOMReader::Scope __assetsScope(m_UIADocument.second);
+ for (bool success = m_UIADocument.second->MoveToFirstChild(); success;
+ success = m_UIADocument.second->MoveToNextSibling()) {
+ IDOMReader::Scope __assetScope(m_UIADocument.second);
+ const char8_t *elemName = m_UIADocument.second->GetElementName();
+ if (AreEqual(elemName, "presentation")) {
+ const char8_t *id, *relativePath;
+ m_UIADocument.second->UnregisteredAtt("id", id);
+ m_UIADocument.second->UnregisteredAtt("src", relativePath);
+ LoadUIPFile(relativePath, id, *theMetaData);
+ } else if (AreEqual(elemName, "statemachine")) {
+ const char8_t *id, *relativePath;
+ m_UIADocument.second->UnregisteredAtt("id", id);
+ m_UIADocument.second->UnregisteredAtt("src", relativePath);
+ TEditorStr fullPath;
+ CFileTools::CombineBaseAndRelative(appDir.c_str(), relativePath,
+ fullPath);
+ CreateSCXMLEditor(fullPath, nonNull(id));
+ }
+ }
+ }
+
+ // Now sort our list of elements by path after we have loaded all uip files.
+ eastl::sort(m_Elements.begin(), m_Elements.end(), SElemLessThan());
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ {
+ IDOMReader::Scope __appScope(m_UIADocument.second);
+ for (bool success = m_UIADocument.second->MoveToFirstChild("statemachine"); success;
+ success = m_UIADocument.second->MoveToNextSibling("statemachine")) {
+ IDOMReader::Scope __machineScope(m_UIADocument.second);
+ const char8_t *idref;
+ m_UIADocument.second->UnregisteredAtt("ref", idref);
+ if (!isTrivial(idref)) {
+ if (idref[0] == '#')
+ ++idref;
+ for (size_t idx = 0, end = m_Editors.size(); idx < end; ++idx) {
+ if (m_Editors[idx].m_Id.compare(idref) == 0)
+ ParseStateMachine(m_Editors[idx].m_Id, m_Editors[idx].m_Editor);
+ }
+ }
+ }
+ }
+ }
+
+ virtual bool IsDirty() const { return m_Dirty; }
+ // General queries of the dataset defined by the uia file and all uip files and scxml files it
+ // includes.
+
+ SAppElement *FindElementByPath(const TEditorStr &inPath)
+ {
+ if (!m_FinderElement)
+ m_FinderElement = new SAppElement();
+
+ m_FinderElement->m_Path = inPath;
+
+ nvvector<NVScopedRefCounted<SAppElement>>::iterator iter = eastl::lower_bound(
+ m_Elements.begin(), m_Elements.end(), m_FinderElement, SElemLessThan());
+ if (iter != m_Elements.end() && (*iter)->m_Path == m_FinderElement->m_Path) {
+ return iter->mPtr;
+ }
+ return NVScopedRefCounted<SAppElement>();
+ }
+
+ virtual TEditorStrList GetComponents()
+ {
+ TEditorStrList retval;
+ for (size_t idx = 0, end = m_Elements.size(); idx < end; ++idx) {
+ if (m_Elements[idx]->GetSubType() == ElementSubTypes::Component)
+ retval.push_back(m_Elements[idx]->m_Path);
+ }
+ return retval;
+ }
+
+ virtual TEditorStrList GetComponentSlides(const TEditorStr &inComponent)
+ {
+ SAppElement *elem = FindElementByPath(inComponent);
+ if (elem != NULL && elem->GetSubType() == ElementSubTypes::Component)
+ return static_cast<SAppComponent *>(elem)->m_Slides;
+ return TEditorStrList();
+ }
+
+ virtual TEditorStrList GetBehaviors()
+ {
+ TEditorStrList retval;
+ for (size_t idx = 0, end = m_Elements.size(); idx < end; ++idx) {
+ if (m_Elements[idx]->GetSubType() == ElementSubTypes::Behavior)
+ retval.push_back(m_Elements[idx]->m_Path);
+ }
+ return retval;
+ }
+
+ virtual Q3DStudio::THandlerList GetHandlers(const TEditorStr &inBehavior)
+ {
+ SAppElement *elem = FindElementByPath(inBehavior);
+ if (elem != NULL && elem->GetSubType() == ElementSubTypes::Behavior)
+ return static_cast<SAppBehavior *>(elem)->m_Handlers;
+ return Q3DStudio::THandlerList();
+ }
+
+ virtual Q3DStudio::TVisualEventList GetVisualEvents(const TEditorStr &inElement)
+ {
+ SAppElement *elem = FindElementByPath(inElement);
+ if (elem)
+ return elem->m_VisualEvents;
+ return Q3DStudio::TVisualEventList();
+ }
+
+ virtual TEditorStrList GetElements()
+ {
+ TEditorStrList retval;
+ for (size_t idx = 0, end = m_Elements.size(); idx < end; ++idx)
+ retval.push_back(m_Elements[idx]->m_Path);
+ return retval;
+ }
+
+ virtual Q3DStudio::TAttOrArgList GetElementAttributes(const TEditorStr &inElement)
+ {
+ SAppElement *elem = FindElementByPath(inElement);
+ if (elem)
+ return elem->m_Attributes;
+ return Q3DStudio::TAttOrArgList();
+ }
+
+ TEditorPtr CreateSCXMLEditor(const TEditorStr &inPath, const TEditorStr &inId)
+ {
+ TEditorPtr newEditor = m_StateMachineEditorManager.GetOrCreateEditor(inPath, 0);
+ if (newEditor) {
+ SEditorEntry theEntry;
+ theEntry.m_Editor = newEditor.mPtr;
+ theEntry.m_FilePath = inPath;
+ theEntry.m_Id = inId;
+ m_Editors.push_back(theEntry);
+ }
+ return newEditor.mPtr;
+ }
+
+ virtual TEditorPtr GetOrCreateEditor(const TEditorStr &inFullPath, bool *outLoadStatus)
+ {
+ (void)outLoadStatus;
+ TEditorStr normalizedPath(inFullPath);
+ CFileTools::NormalizePath(normalizedPath);
+ for (size_t idx = 0, end = m_Editors.size(); idx < end; ++idx) {
+ if (m_Editors[idx].m_FilePath == normalizedPath)
+ return m_Editors[idx].m_Editor;
+ }
+
+ // Is file full path under our application directory;
+ TEditorStr appDir(m_FilePath);
+ CFileTools::GetDirectory(appDir);
+ TEditorStr editorDir(inFullPath);
+ CFileTools::GetDirectory(editorDir);
+
+ // For scxml files outside our app dir, let the user create an editor manually.
+ // We will have nothing to do with it.
+ if (editorDir.find(appDir) == eastl::string::npos)
+ return TEditorPtr();
+
+ // Get an ID for the editor
+ IDOMReader::Scope __appScope(*m_UIADocument.second);
+ if (!m_UIADocument.second->MoveToFirstChild("assets")) {
+ m_UIADocument.first->Begin("assets", GetUICNamespace());
+ }
+
+ {
+ IDOMReader::Scope __assetsScope(*m_UIADocument.second);
+ for (bool success = m_UIADocument.second->MoveToFirstChild("statemachine"); success;
+ success = m_UIADocument.second->MoveToNextSibling("statemachine")) {
+ const char8_t *srcPath;
+ const char8_t *id;
+ m_UIADocument.second->UnregisteredAtt("src", srcPath);
+ m_UIADocument.second->UnregisteredAtt("id", id);
+ TEditorStr docPath;
+ CFileTools::CombineBaseAndRelative(appDir.c_str(), srcPath, docPath);
+ CFileTools::NormalizePath(docPath);
+ if (docPath == normalizedPath) {
+ return CreateSCXMLEditor(normalizedPath, nonNull(id));
+ }
+ }
+ }
+
+ eastl::string dirname, fname, extension;
+ CFileTools::Split(normalizedPath.c_str(), dirname, fname, extension);
+ m_UIADocument.first->Begin("statemachine", GetUICNamespace());
+ m_UIADocument.first->Att("id", fname.c_str(), GetUICNamespace());
+ eastl::string relativePath;
+ CFileTools::GetRelativeFromBase(appDir, normalizedPath, relativePath);
+ m_UIADocument.first->Att("src", relativePath.c_str());
+ m_Dirty = true;
+ return CreateSCXMLEditor(normalizedPath, nonNull(fname.c_str()));
+ }
+
+ static bool CouldHaveVisualStateExecutableContent(TObjPtr inObject)
+ {
+ return inObject->GetExecutableContentTypes().size() > 0;
+ }
+ template <typename TEditorType>
+ TEditorType &CreateEditor(TObjPtr inParent)
+ {
+ TPropertyAccessorList accessors;
+ TEditorType::CreateProperties(accessors, *this);
+ return *QT3DS_NEW(m_Foundation->getAllocator(), TEditorType)(*this, inParent, accessors);
+ }
+
+ SVSEntry *GetEntryForPair(TEntryExitPair &inPair, InterpreterEventTypes::Enum inType)
+ {
+ SVSEntry *theEntry;
+ if (inType == InterpreterEventTypes::StateEnter
+ || inType == InterpreterEventTypes::Transition) {
+ if (inPair.first == NULL)
+ inPair.first = new SVSEntry(inType);
+ theEntry = inPair.first.mPtr;
+ } else {
+ if (inPair.second == NULL)
+ inPair.second = new SVSEntry(inType);
+ theEntry = inPair.second.mPtr;
+ }
+ return theEntry;
+ }
+
+ void ParseExecutableContent(IDOMReader &inReader, const TEditorStr &inId,
+ TIdEntryExitMap &ioMap, InterpreterEventTypes::Enum inType,
+ TObjPtr parentPtr)
+ {
+ IDOMReader::Scope __contentScope(inReader);
+ {
+ IDOMReader::Scope __testScope(inReader);
+ // See if there is any executable content to begin with.
+ if (inReader.MoveToFirstChild() == false)
+ return;
+ }
+
+ TEntryExitPair &thePair =
+ ioMap.insert(eastl::make_pair(inId, TEntryExitPair())).first->second;
+ SVSEntry *theEntry = GetEntryForPair(thePair, inType);
+ QT3DS_ASSERT(theEntry->m_EventType == inType);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __elemScope(inReader);
+ const char8_t *elemName(inReader.GetElementName());
+ if (AreEqual(elemName, SGotoSlideEditor::ElementName())) {
+ const char8_t *component, *slide, *rel, *wrap, *direction, *state, *mode,
+ *playthroughto, *rate, *time;
+ inReader.UnregisteredAtt("element", component);
+ if (inReader.UnregisteredAtt("slide", slide) == false)
+ inReader.UnregisteredAtt("rel", rel);
+ else
+ rel = "";
+ inReader.UnregisteredAtt("wrap", wrap);
+ inReader.UnregisteredAtt("direction", direction);
+ inReader.UnregisteredAtt("state", state);
+ inReader.UnregisteredAtt("mode", mode);
+ inReader.UnregisteredAtt("playthroughto", playthroughto);
+ inReader.UnregisteredAtt("rate", rate);
+ inReader.UnregisteredAtt("time", time);
+ SGotoSlideEditor &theEditor = CreateEditor<SGotoSlideEditor>(parentPtr);
+ theEditor.m_Component.assign(nonNull(component));
+ theEditor.m_Slide.assign(nonNull(slide));
+ theEditor.m_Rel.assign(nonNull(rel));
+ theEditor.m_Wrap.assign(nonNull(wrap));
+ theEditor.m_Direction.assign(nonNull(direction));
+ theEditor.m_State.assign(nonNull(state));
+ theEditor.m_Mode.assign(nonNull(mode));
+ theEditor.m_PlayThroughTo.assign(nonNull(playthroughto));
+ theEditor.m_Rate.assign(nonNull(rate));
+ theEditor.m_Time.assign(nonNull(time));
+ theEntry->m_Editors.push_back(theEditor);
+ } else if (AreEqual(elemName, SSetAttributeEditor::ElementName())) {
+ const char8_t *element, *att, *val;
+ inReader.UnregisteredAtt("element", element);
+ inReader.UnregisteredAtt("attribute", att);
+ inReader.UnregisteredAtt("value", val);
+ SSetAttributeEditor &theEditor = CreateEditor<SSetAttributeEditor>(parentPtr);
+ theEditor.m_Element.assign(nonNull(element));
+ theEditor.m_Attribute.assign(nonNull(att));
+ theEditor.m_Value.assign(nonNull(val));
+ theEntry->m_Editors.push_back(theEditor);
+ } else if (AreEqual(elemName, SFireEventEditor::ElementName())) {
+ const char8_t *element, *evt;
+ inReader.UnregisteredAtt("element", element);
+ inReader.UnregisteredAtt("event", evt);
+ SFireEventEditor &theEditor = CreateEditor<SFireEventEditor>(parentPtr);
+ theEditor.m_Element.assign(nonNull(element));
+ theEditor.m_Event.assign(nonNull(evt));
+ theEntry->m_Editors.push_back(theEditor);
+ } else if (AreEqual(elemName, SRunHandlerEditor::ElementName())) {
+ const char8_t *element, *handler, *args;
+ inReader.UnregisteredAtt("element", element);
+ inReader.UnregisteredAtt("handler", handler);
+ inReader.UnregisteredAtt("arguments", args);
+ SRunHandlerEditor &theEditor = CreateEditor<SRunHandlerEditor>(parentPtr);
+ theEditor.m_Behavior.assign(nonNull(element));
+ theEditor.m_Handler.assign(nonNull(handler));
+ theEditor.m_ArgumentStr.assign(nonNull(args));
+ theEntry->m_Editors.push_back(theEditor);
+ } else if (AreEqual(elemName, SSetPresentationEditor::ElementName())) {
+ const char8_t *ref, *attribute, *value;
+ inReader.UnregisteredAtt("ref", ref);
+ inReader.UnregisteredAtt("attribute", attribute);
+ inReader.UnregisteredAtt("value", value);
+ SSetPresentationEditor &theEditor = CreateEditor<SSetPresentationEditor>(parentPtr);
+ theEditor.m_Ref.assign(nonNull(ref));
+ theEditor.m_Attribute.assign(nonNull(attribute));
+ theEditor.m_Value.assign(nonNull(value));
+ theEntry->m_Editors.push_back(theEditor);
+ } else if (AreEqual(elemName, SPlaySoundEditor::ElementName())) {
+ const char8_t *file;
+ inReader.UnregisteredAtt("file", file);
+ SPlaySoundEditor &theEditor = CreateEditor<SPlaySoundEditor>(parentPtr);
+ theEditor.m_FilePath.assign(nonNull(file));
+ theEntry->m_Editors.push_back(theEditor);
+ }
+ }
+ }
+
+ void ParseVisualStateEntry(IDOMReader &inReader, TEditorPtr inEditor, TIdEntryExitMap &retval,
+ const char8_t *stateId)
+ {
+ TObjPtr parentPtr = inEditor->GetObjectById(stateId);
+ if (parentPtr) {
+ if (AreEqual(inReader.GetElementName().c_str(), "state")) {
+ for (bool entryExitSucces = inReader.MoveToFirstChild(); entryExitSucces;
+ entryExitSucces = inReader.MoveToNextSibling()) {
+ const char8_t *signalName(inReader.GetElementName());
+ if (AreEqual(signalName, "enter")) {
+ ParseExecutableContent(inReader, stateId, retval,
+ InterpreterEventTypes::StateEnter, parentPtr);
+ } else if (AreEqual(signalName, "exit")) {
+ ParseExecutableContent(inReader, stateId, retval,
+ InterpreterEventTypes::StateExit, parentPtr);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ } else if (AreEqual(inReader.GetElementName().c_str(), "transition")) {
+ ParseExecutableContent(inReader, stateId, retval, InterpreterEventTypes::Transition,
+ parentPtr);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ TIdEntryExitMap &ParseStateMachine(const TEditorStr &inId, TEditorPtr inEditor)
+ {
+ TIdEntryExitMap &retval =
+ m_IdToStateMaps.insert(eastl::make_pair(inId, TIdEntryExitMap())).first->second;
+ if (m_UIADocument.second->MoveToFirstChild("visual-states")) {
+ for (bool stateSuccess = m_UIADocument.second->MoveToFirstChild(); stateSuccess;
+ stateSuccess = m_UIADocument.second->MoveToNextSibling()) {
+ IDOMReader::Scope __stateScope(*m_UIADocument.second);
+ const char8_t *stateId;
+ m_UIADocument.second->UnregisteredAtt("ref", stateId);
+ if (!isTrivial(stateId)) {
+ if (stateId[0] == '#')
+ ++stateId;
+
+ ParseVisualStateEntry(*m_UIADocument.second, inEditor, retval, stateId);
+ }
+ }
+ }
+ return retval; // found a statemachine with the right id.
+ }
+
+ TIdEntryExitMap &GetOrCreateStateMap(const TEditorStr &inId, TEditorPtr inEditor)
+ {
+ TIdEntryExitMap &retval =
+ m_IdToStateMaps.insert(eastl::make_pair(inId, TIdEntryExitMap())).first->second;
+
+ if (retval.empty()) {
+ IDOMReader::Scope __appScope(*m_UIADocument.second);
+ for (bool success = m_UIADocument.second->MoveToFirstChild("statemachine");
+ success && retval.empty();
+ success = m_UIADocument.second->MoveToNextSibling("statemachine")) {
+ IDOMReader::Scope __machineScope(*m_UIADocument.second);
+ const char8_t *idref;
+ m_UIADocument.second->UnregisteredAtt("ref", idref);
+ if (!isTrivial(idref)) {
+ if (idref[0] == '#')
+ ++idref;
+ if (inId.compare(idref) == 0) {
+ return ParseStateMachine(inId, inEditor);
+ }
+ }
+ } // for (statemachines)
+ }
+
+ return retval;
+ }
+
+ TIdEntryExitMap *GetStateMapForObject(TObjPtr inObject)
+ {
+ if (!CouldHaveVisualStateExecutableContent(inObject))
+ return NULL;
+
+ TEditorPtr theEditor = inObject->GetEditor();
+ // Find the id for the editor
+ TIdEntryExitMap *stateMap(NULL);
+
+ for (size_t idx = 0, end = m_Editors.size(); idx < end && stateMap == NULL; ++idx) {
+ if (m_Editors[idx].m_Editor == theEditor)
+ return &GetOrCreateStateMap(m_Editors[idx].m_Id, m_Editors[idx].m_Editor);
+ }
+ return NULL;
+ }
+
+ // The editor obj has a remove from graph function that really is delete
+ virtual TObjList GetVisualStateExecutableContent(TObjPtr inObject,
+ InterpreterEventTypes::Enum inEventType)
+ {
+ TIdEntryExitMap *stateMap = GetStateMapForObject(inObject);
+ if (stateMap == NULL)
+ return TObjList();
+
+ TEditorStr objId(inObject->GetId());
+ TIdEntryExitMap::iterator iter = stateMap->find(objId);
+ for (TIdEntryExitMap::iterator temp = stateMap->begin(), end = stateMap->end(); temp != end;
+ ++temp) {
+ objId = temp->first;
+ objId.clear();
+ }
+ if (iter != stateMap->end()) {
+ TEntryExitPair thePair = iter->second;
+ if (thePair.first && thePair.first->m_EventType == inEventType)
+ return thePair.first->m_Editors;
+ else if (thePair.second && thePair.second->m_EventType == inEventType)
+ return thePair.second->m_Editors;
+ }
+
+ return TObjList();
+ }
+
+ // Type name is the element name, so set-attribute, goto-slide, or fire-event
+ virtual TObjPtr AppendVisualStateExecutableContent(TObjPtr inObject,
+ InterpreterEventTypes::Enum inEventType,
+ const char8_t *inElementName)
+ {
+ TIdEntryExitMap *stateMap = GetStateMapForObject(inObject);
+ if (stateMap == NULL)
+ return TObjPtr();
+
+ NVConstDataRef<InterpreterEventTypes::Enum> supportedTypes =
+ inObject->GetExecutableContentTypes();
+ bool foundEventType = false;
+ for (size_t idx = 0, end = supportedTypes.size(); idx < end && foundEventType == false;
+ ++idx)
+ if (inEventType == supportedTypes[idx])
+ foundEventType = true;
+
+ if (foundEventType == false) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ TEntryExitPair &thePair =
+ stateMap->insert(eastl::make_pair(inObject->GetId(), TEntryExitPair())).first->second;
+ SVSEntry *entry = GetEntryForPair(thePair, inEventType);
+ if (!entry) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ if (AreEqual(inElementName, SGotoSlideEditor::ElementName())) {
+ entry->m_Editors.push_back(CreateEditor<SGotoSlideEditor>(inObject));
+ } else if (AreEqual(inElementName, SRunHandlerEditor::ElementName())) {
+ entry->m_Editors.push_back(CreateEditor<SRunHandlerEditor>(inObject));
+ } else if (AreEqual(inElementName, SSetAttributeEditor::ElementName())) {
+ entry->m_Editors.push_back(CreateEditor<SSetAttributeEditor>(inObject));
+ } else if (AreEqual(inElementName, SFireEventEditor::ElementName())) {
+ entry->m_Editors.push_back(CreateEditor<SFireEventEditor>(inObject));
+ } else if (AreEqual(inElementName, SSetPresentationEditor::ElementName())) {
+ entry->m_Editors.push_back(CreateEditor<SSetPresentationEditor>(inObject));
+ } else if (AreEqual(inElementName, SPlaySoundEditor::ElementName())) {
+ entry->m_Editors.push_back(CreateEditor<SPlaySoundEditor>(inObject));
+ } else {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ TObjPtr retval = entry->m_Editors.back();
+ STransaction *theTrans = GetOpenTransactionImpl();
+ if (theTrans) {
+ SVSEntryListChange *theChange =
+ new SVSEntryListChange(TObjPtr(), retval, *entry, true, inObject);
+ theTrans->m_Changes.push_back(theChange);
+ }
+ return retval;
+ }
+
+ virtual TObjPtr ChangeVisualStateExecutableContentName(TObjPtr inContent,
+ const char8_t *inElementName)
+ {
+ TObjPtr theParent = inContent->Parent();
+ if (!CouldHaveVisualStateExecutableContent(theParent)) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ TIdEntryExitMap *stateMap = GetStateMapForObject(theParent);
+ if (stateMap == NULL) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ TIdEntryExitMap::iterator iter = stateMap->find(theParent->GetId());
+ if (iter == stateMap->end()) {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+ TEntryExitPair thePair = iter->second;
+ NVScopedRefCounted<SVSEntry> theEntryFound;
+ if (!theEntryFound) {
+ NVScopedRefCounted<SVSEntry> theEntry = thePair.first;
+ TObjPtr theObj = inContent;
+ if (theEntry) {
+ TObjList::iterator iter =
+ eastl::find(theEntry->m_Editors.begin(), theEntry->m_Editors.end(), theObj);
+ if (iter != theEntry->m_Editors.end()) {
+ theEntryFound = theEntry;
+ }
+ }
+ }
+ if (!theEntryFound) {
+ NVScopedRefCounted<SVSEntry> theEntry = thePair.second;
+ TObjPtr theObj = inContent;
+ if (theEntry) {
+ TObjList::iterator iter =
+ eastl::find(theEntry->m_Editors.begin(), theEntry->m_Editors.end(), theObj);
+ if (iter != theEntry->m_Editors.end()) {
+ theEntryFound = theEntry;
+ }
+ }
+ }
+ if (!theEntryFound)
+ return TObjPtr();
+
+ TObjPtr theRetval;
+ if (AreEqual(inElementName, SGotoSlideEditor::ElementName())) {
+ theRetval = CreateEditor<SGotoSlideEditor>(theParent);
+ } else if (AreEqual(inElementName, SRunHandlerEditor::ElementName())) {
+ theRetval = CreateEditor<SRunHandlerEditor>(theParent);
+ } else if (AreEqual(inElementName, SSetAttributeEditor::ElementName())) {
+ theRetval = CreateEditor<SSetAttributeEditor>(theParent);
+ } else if (AreEqual(inElementName, SFireEventEditor::ElementName())) {
+ theRetval = CreateEditor<SFireEventEditor>(theParent);
+ } else if (AreEqual(inElementName, SSetPresentationEditor::ElementName())) {
+ theRetval = CreateEditor<SSetPresentationEditor>(theParent);
+ } else if (AreEqual(inElementName, SPlaySoundEditor::ElementName())) {
+ theRetval = CreateEditor<SPlaySoundEditor>(theParent);
+ } else {
+ QT3DS_ASSERT(false);
+ return TObjPtr();
+ }
+
+ NVScopedRefCounted<SVSEntryListChange> theOldChange =
+ new SVSEntryListChange(inContent, inContent, *theEntryFound, false, theParent);
+ NVScopedRefCounted<SVSEntryListChange> theNewChange =
+ new SVSEntryListChange(theRetval, inContent, *theEntryFound, true, theParent);
+ theOldChange->Do();
+ theNewChange->Do();
+ if (GetOpenTransactionImpl()) {
+ GetOpenTransactionImpl()->m_Changes.push_back(theOldChange.mPtr);
+ GetOpenTransactionImpl()->m_Changes.push_back(theNewChange.mPtr);
+ }
+
+ return theRetval;
+ }
+
+ // Called when the source uia changes.
+ virtual void RefreshFile() { LoadUIADatabase(); }
+
+ virtual void RefreshFromStream(qt3ds::foundation::IInStream &inStream)
+ {
+ LoadUIADatabaseFromStream(inStream);
+ }
+
+ // Returns the path that was passed in on create.
+ virtual TEditorStr GetFilePath() { return m_FilePath; }
+
+ void CopyDOM(IDOMReader &inReader, IDOMWriter &inWriter)
+ {
+ IDOMReader::Scope __itemScope(inReader);
+ const SDOMElement &theElement(*inReader.GetElement());
+ IDOMWriter::Scope __writeScope(inWriter, theElement.m_Name, theElement.m_Namespace);
+ if (theElement.m_Attributes.empty() && theElement.m_Children.empty()) {
+ if (!isTrivial(theElement.m_Value))
+ inWriter.Value(theElement.m_Value);
+ } else {
+ for (TAttributeList::iterator iter = theElement.m_Attributes.begin(),
+ end = theElement.m_Attributes.end();
+ iter != end; ++iter) {
+ inWriter.Att(iter->m_Name, iter->m_Value, iter->m_Namespace);
+ }
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __loopScope(inReader);
+ CopyDOM(inReader, inWriter);
+ }
+ }
+ }
+ void ReplaceDOMNamespace(SDOMElement &inDom,
+ qt3ds::foundation::CRegisteredString &inNamespaceToReplace,
+ qt3ds::foundation::CRegisteredString &inNewNamespace)
+ {
+ if (!inNamespaceToReplace.IsValid() || !inNewNamespace.IsValid())
+ return;
+ if (inDom.m_Namespace == inNamespaceToReplace)
+ inDom.m_Namespace = inNewNamespace;
+ // Set attributes namespace
+ for (qt3ds::foundation::TAttributeList::iterator theIter = inDom.m_Attributes.begin(),
+ theEnd = inDom.m_Attributes.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->m_Namespace == inNamespaceToReplace)
+ theIter->m_Namespace = inNewNamespace;
+ }
+ // Recursive
+ for (qt3ds::foundation::SDOMElement::TElementChildList::iterator
+ theIter = inDom.m_Children.begin(),
+ theEnd = inDom.m_Children.end();
+ theIter != theEnd; ++theIter) {
+ ReplaceDOMNamespace(*theIter, inNamespaceToReplace, inNewNamespace);
+ }
+ }
+ struct SEditorIDFinder
+ {
+ TEditorStr m_Id;
+ SEditorIDFinder(const TEditorStr &id)
+ : m_Id(id)
+ {
+ }
+ bool operator()(const SEditorEntry &entry) const { return m_Id == entry.m_Id; }
+ };
+
+ void WriteExecutableContent(IDOMWriter &inWriter, NVScopedRefCounted<SVSEntry> inEntry)
+ {
+ if (inEntry == NULL)
+ return;
+ const char *elemName = "";
+ switch (inEntry->m_EventType) {
+ case InterpreterEventTypes::Transition:
+ break;
+ case InterpreterEventTypes::StateEnter:
+ elemName = "enter";
+ break;
+ case InterpreterEventTypes::StateExit:
+ elemName = "exit";
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ if (!isTrivial(elemName))
+ inWriter.Begin(elemName, GetUICNamespace());
+
+ eastl::vector<SPropertyDeclaration> properties;
+ for (size_t idx = 0, end = inEntry->m_Editors.size(); idx < end; ++idx) {
+ TObjPtr editor(inEntry->m_Editors[idx]);
+ IDOMWriter::Scope __contentScope(inWriter, editor->TypeName(), GetUICNamespace());
+ editor->GetProperties(properties);
+ bool theNoProperty = true;
+ for (size_t idx = 0, end = properties.size(); idx < end; ++idx) {
+ TEditorStr theProp =
+ editor->GetPropertyValue(properties[idx].m_Name)->getData<TEditorStr>();
+ if (theProp.empty() == false) {
+ inWriter.Att(properties[idx].m_Name.c_str(), theProp.c_str(),
+ GetUICNamespace());
+ theNoProperty = false;
+ }
+ }
+ if (theNoProperty && properties.size() > 0)
+ inWriter.Att(properties[0].m_Name.c_str(), "", GetUICNamespace());
+ }
+
+ if (!isTrivial(elemName))
+ inWriter.End();
+ }
+
+ void WriteStateEntry(TIdEntryExitMap::const_iterator stateIter, IDOMWriter &writer,
+ const char *typeName, const char *id)
+ {
+ const char8_t *stateName = "state";
+ if (AreEqual(typeName, "transition"))
+ stateName = "transition";
+ eastl::string tempAtt;
+ IDOMWriter::Scope __stateScope(writer, stateName, GetUICNamespace());
+ tempAtt.assign("#");
+ tempAtt.append(id);
+ writer.Att("ref", tempAtt.c_str());
+ WriteExecutableContent(writer, stateIter->second.first);
+ WriteExecutableContent(writer, stateIter->second.second);
+ }
+
+ // Returns false if unable to save, ask users to check the file out.
+ bool SaveInner(qt3ds::foundation::IOutStream &inStream)
+ {
+ IDOMReader::Scope __saveScope(m_UIADocument.second);
+ NVScopedRefCounted<IDOMFactory> theFactory(
+ IDOMFactory::CreateDOMFactory(m_Foundation->getAllocator(), m_StringTable));
+ NVScopedRefCounted<IDOMWriter> outgoingDoc =
+ IDOMWriter::CreateDOMWriter(m_Foundation->getAllocator(), "application", m_StringTable,
+ GetUICNamespace())
+ .first;
+ {
+ m_UIADocument.second->MoveToFirstChild("application");
+ for (SDOMAttribute *theAtt = m_UIADocument.second->GetFirstAttribute(); theAtt;
+ theAtt = m_UIADocument.second->GetNextAttribute()) {
+ outgoingDoc->Att(theAtt->m_Name, theAtt->m_Value, theAtt->m_Namespace);
+ }
+ }
+
+ {
+ IDOMReader::Scope __appScope(m_UIADocument.second);
+ if (m_UIADocument.second->MoveToFirstChild("assets")) {
+ CopyDOM(*m_UIADocument.second, *outgoingDoc);
+ }
+ }
+ {
+ eastl::string tempAtt;
+ for (TIdStateMapMap::const_iterator iter = m_IdToStateMaps.begin(),
+ end = m_IdToStateMaps.end();
+ iter != end; ++iter) {
+ nvvector<SEditorEntry>::iterator editorEntry = eastl::find_if(
+ m_Editors.begin(), m_Editors.end(), SEditorIDFinder(iter->first));
+ if (editorEntry == m_Editors.end()) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ IDOMWriter::Scope __machineScope(*outgoingDoc, "statemachine", GetUICNamespace());
+ tempAtt.assign("#");
+ tempAtt.append(iter->first);
+ outgoingDoc->Att("ref", tempAtt.c_str());
+ IDOMWriter::Scope __vsScope(*outgoingDoc, "visual-states", GetUICNamespace());
+ const TIdEntryExitMap &itemMap = iter->second;
+ for (TIdEntryExitMap::const_iterator stateIter = itemMap.begin(),
+ stateEnd = itemMap.end();
+ stateIter != stateEnd; ++stateIter) {
+ TObjPtr editorObj =
+ editorEntry->m_Editor->GetObjectById(stateIter->first.c_str());
+ if (!editorObj) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ WriteStateEntry(stateIter, *outgoingDoc, editorObj->TypeName(),
+ stateIter->first.c_str());
+ }
+ }
+ }
+
+ SDOMElement *topElem = outgoingDoc->GetTopElement();
+ CDOMSerializer::WriteXMLHeader(inStream);
+ CDOMSerializer::Write(m_Foundation->getAllocator(), *topElem, inStream, *m_StringTable,
+ m_UIANamespaces);
+ m_Dirty = false;
+ return true;
+ }
+
+ virtual bool Save()
+ {
+ CFileSeekableIOStream theStream(m_FilePath.c_str(), FileWriteFlags());
+ if (!theStream.IsOpen())
+ return false;
+ return SaveInner(theStream);
+ }
+
+ virtual bool Save(qt3ds::foundation::IOutStream &inStream) { return SaveInner(inStream); }
+
+ virtual eastl::vector<SPresentation> GetPresentations() { return m_Presentations; }
+ virtual eastl::string GetElementType(SAppElement &elem) { return elem.m_Type; }
+
+ virtual eastl::string GetElementId(SAppElement &elem) { return elem.m_Id; }
+ virtual bool IsComponent(SAppElement &elem)
+ {
+ return elem.GetSubType() == ElementSubTypes::Component;
+ }
+ virtual Q3DStudio::TAttOrArgList GetElementAttributes(SAppElement &elem)
+ {
+ return elem.m_Attributes;
+ }
+ virtual Q3DStudio::TAttOrArgList GetSlideAttributes() { return m_SlideProperties; }
+ virtual eastl::vector<SDatamodelValue> GetElementAttributeInitialValues(SAppElement &elem)
+ {
+ return elem.m_InitialValues;
+ }
+ virtual eastl::vector<SAppElement *> GetElementChildren(SAppElement &elem)
+ {
+ eastl::vector<SAppElement *> retval;
+ retval.resize(elem.m_Children.size());
+ for (size_t idx = 0, end = elem.m_Children.size(); idx < end; ++idx)
+ retval[idx] = elem.m_Children[idx].mPtr;
+ return retval;
+ }
+ virtual eastl::string GetLastLoadingErrorString() { return m_LoadingErrorString; }
+ // The file may either exist or not. You can pass in a uip file as well as a uia file.
+
+ virtual NVFoundationBase &GetFoundation() { return m_Foundation->getFoundation(); }
+
+ virtual IStringTable &GetStringTable() { return *m_StringTable; }
+
+ // ITransactionManager
+ // Undo/redo is supported via a transparent transaction system.
+ // calls are reentrant but last call will close the transaction object.
+ // Any changes to any editor objects will go through this transaction when they happen.
+ virtual TSignalConnectionPtr AddChangeListener(IEditorChangeListener &inListener)
+ {
+ return m_TransactionManager->AddChangeListener(inListener);
+ }
+ virtual TTransactionPtr BeginTransaction(const TEditorStr &inName)
+ {
+ return m_TransactionManager->BeginTransaction(inName);
+ }
+
+ virtual TTransactionPtr GetOpenTransaction()
+ {
+ return m_TransactionManager->GetOpenTransaction();
+ }
+
+ virtual void RollbackTransaction() { m_TransactionManager->RollbackTransaction(); }
+ virtual void EndTransaction() { m_TransactionManager->EndTransaction(); }
+
+ virtual void OnObjectCreated(TObjPtr) {}
+
+ virtual void OnObjectDeleted(TObjPtr inObject)
+ {
+ // don't care.
+ if (!CouldHaveVisualStateExecutableContent(inObject))
+ return;
+
+ TIdEntryExitMap *stateMap = GetStateMapForObject(inObject);
+ if (stateMap == NULL)
+ return;
+
+ TIdEntryExitMap::iterator iter = stateMap->find(inObject->GetId());
+ if (iter == stateMap->end())
+ return;
+ NVScopedRefCounted<SIdEntryExitDeleteChange> theChange =
+ new SIdEntryExitDeleteChange(*stateMap, inObject->GetId(), inObject);
+ theChange->Do();
+ if (GetOpenTransactionImpl())
+ GetOpenTransactionImpl()->m_Changes.push_back(theChange.mPtr);
+ }
+ bool RemoveObjectFromEntry(NVScopedRefCounted<SVSEntry> inEntry, SVSEditorObject &inObj)
+ {
+ if (inEntry) {
+ TObjList::iterator iter =
+ eastl::find(inEntry->m_Editors.begin(), inEntry->m_Editors.end(), TObjPtr(inObj));
+ if (iter != inEntry->m_Editors.end()) {
+ NVScopedRefCounted<SVSEntryListChange> theChange = new SVSEntryListChange(
+ TObjPtr(inObj), TObjPtr(inObj), *inEntry, false, inObj.m_ParentObject);
+ theChange->Do();
+ if (GetOpenTransactionImpl())
+ GetOpenTransactionImpl()->m_Changes.push_back(theChange.mPtr);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual void RemoveObjectFromGraph(SVSEditorObject &inObj)
+ {
+ TObjPtr parentPtr = inObj.m_ParentObject;
+ if (!CouldHaveVisualStateExecutableContent(parentPtr)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ TIdEntryExitMap *stateMap = GetStateMapForObject(parentPtr);
+ if (stateMap == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ TIdEntryExitMap::iterator iter = stateMap->find(parentPtr->GetId());
+ if (iter == stateMap->end()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ TEntryExitPair thePair = iter->second;
+ if (!RemoveObjectFromEntry(thePair.first, inObj)) {
+ RemoveObjectFromEntry(thePair.second, inObj);
+ }
+ }
+
+ struct SEditorFinder
+ {
+ TEditorPtr m_Editor;
+ SEditorFinder(TEditorPtr editor)
+ : m_Editor(editor)
+ {
+ }
+ bool operator()(const SEditorEntry &entry) const { return entry.m_Editor == m_Editor; }
+ };
+
+ void CopyStateNode(SStateNode &inNode, TIdEntryExitMap &idMap, IDOMWriter &writer)
+ {
+ TIdEntryExitMap::iterator iter = idMap.find(inNode.m_Id.c_str());
+ if (iter != idMap.end()) {
+ const char *typeName = "state";
+ if (inNode.m_Type == StateNodeTypes::Transition)
+ typeName = "transition";
+ WriteStateEntry(iter, writer, typeName, inNode.m_Id.c_str());
+ }
+ TStateNodeList *childList = inNode.GetChildren();
+ if (childList) {
+ for (TStateNodeList::iterator iter = childList->begin(), end = childList->end();
+ iter != end; ++iter) {
+ CopyStateNode(*iter, idMap, writer);
+ }
+ }
+ }
+
+ virtual void OnCopy(TEditorPtr inEditor, eastl::vector<SStateNode *> &ioCopiedRoots,
+ IDOMWriter &ioWriter, eastl::vector<SNamespacePair> &ioNamespaces)
+ {
+ ioNamespaces.push_back(SNamespacePair(m_StringTable->RegisterStr(GetUICNamespace()),
+ m_StringTable->RegisterStr("uia")));
+ eastl::vector<SEditorEntry>::iterator entry =
+ eastl::find_if(m_Editors.begin(), m_Editors.end(), SEditorFinder(inEditor));
+ if (entry == m_Editors.end())
+ return;
+ TIdStateMapMap::iterator mapEntry = m_IdToStateMaps.find(entry->m_Id);
+ if (mapEntry == m_IdToStateMaps.end())
+ return;
+ IDOMWriter::Scope __modelScope(ioWriter, "datamodel_fragment", GetUICNamespace());
+ for (size_t idx = 0, end = ioCopiedRoots.size(); idx < end; ++idx) {
+ CopyStateNode(*ioCopiedRoots[idx], mapEntry->second, ioWriter);
+ }
+ }
+
+ virtual void OnPaste(TEditorPtr inEditor, IDOMReader &ioReader,
+ CXMLIO::TIdRemapMap &inStateIdRemapMap)
+ {
+ eastl::vector<SEditorEntry>::iterator entry =
+ eastl::find_if(m_Editors.begin(), m_Editors.end(), SEditorFinder(inEditor));
+ if (entry == m_Editors.end())
+ return;
+
+ IDOMReader::Scope __fragmentScope(ioReader);
+ if (ioReader.MoveToFirstChild("datamodel_fragment")) {
+ TIdEntryExitMap &stateMap =
+ m_IdToStateMaps.insert(eastl::make_pair(entry->m_Id, TIdEntryExitMap()))
+ .first->second;
+ for (bool success = ioReader.MoveToFirstChild(); success;
+ success = ioReader.MoveToNextSibling()) {
+ IDOMReader::Scope __childScope(ioReader);
+ const char8_t *idRef;
+ ioReader.UnregisteredAtt("ref", idRef);
+ if (isTrivial(idRef))
+ continue;
+ if (idRef[0] == '#')
+ ++idRef;
+
+ CXMLIO::TIdRemapMap::iterator finder = inStateIdRemapMap.find(idRef);
+ if (finder != inStateIdRemapMap.end())
+ idRef = finder->second.c_str();
+
+ TEditorStr idStr(idRef);
+ TObjPtr parentObj = inEditor->GetObjectById(idRef);
+ if (parentObj) {
+ ParseVisualStateEntry(ioReader, inEditor, stateMap, idRef);
+ if (stateMap.find(idStr) != stateMap.end()
+ && m_TransactionManager->GetOpenTransactionImpl()) {
+ m_TransactionManager->GetOpenTransactionImpl()->m_Changes.push_back(
+ new SIdEntryExitDeleteChange(stateMap, idStr, parentObj, false));
+ }
+ }
+ }
+ }
+ }
+
+ virtual void OnIDChange(TEditorPtr inEditor, SStateNode &inNode, const char8_t *inOldId)
+ {
+ eastl::vector<SEditorEntry>::iterator entry =
+ eastl::find_if(m_Editors.begin(), m_Editors.end(), SEditorFinder(inEditor));
+ if (entry == m_Editors.end())
+ return;
+
+ TIdEntryExitMap &stateMap =
+ m_IdToStateMaps.insert(eastl::make_pair(entry->m_Id, TIdEntryExitMap())).first->second;
+ TEditorStr oldIdStr(inOldId);
+ TEditorStr newIdStr(inNode.m_Id.c_str());
+ TIdEntryExitMap::iterator iter = stateMap.find(oldIdStr);
+ if (iter != stateMap.end()) {
+ TEntryExitPair thePair(iter->second);
+ stateMap.erase(iter);
+ stateMap.insert(eastl::make_pair(newIdStr, thePair));
+ }
+ }
+ virtual bool OnDeleteState(TObjPtr inObject)
+ {
+ // don't care.
+ if (!CouldHaveVisualStateExecutableContent(inObject))
+ return false;
+
+ TIdEntryExitMap *stateMap = GetStateMapForObject(inObject);
+ if (stateMap == NULL)
+ return false;
+
+ TIdEntryExitMap::iterator iter = stateMap->find(inObject->GetId());
+ if (iter == stateMap->end())
+ return false;
+ NVScopedRefCounted<SIdEntryExitDeleteChange> theChange =
+ new SIdEntryExitDeleteChange(*stateMap, inObject->GetId(), inObject);
+ theChange->Do();
+ if (GetOpenTransactionImpl())
+ GetOpenTransactionImpl()->m_Changes.push_back(theChange.mPtr);
+ return true;
+ }
+ virtual bool OnReloadStateMachine(TEditorPtr inStateMachineEditor)
+ {
+ bool theRetval = false;
+ TEditorPtr theEditor = inStateMachineEditor;
+
+ for (size_t idx = 0, end = m_Editors.size(); idx < end; ++idx) {
+ if (m_Editors[idx].m_Editor == theEditor) {
+ TIdStateMapMap::iterator theFind = m_IdToStateMaps.find(m_Editors[idx].m_Id);
+ if (theFind != m_IdToStateMaps.end()) {
+ TIdEntryExitMap &theStateMap = theFind->second;
+ for (TIdEntryExitMap::iterator theIter = theStateMap.begin(),
+ theEnd = theStateMap.end();
+ theIter != theEnd;) {
+ TEditorStr theStateId = theIter->first;
+ TObjPtr theState = inStateMachineEditor->GetObjectById(theStateId.c_str());
+ if (theState) {
+ {
+ NVScopedRefCounted<SVSEntry> theEntry = theIter->second.first;
+ if (theEntry) {
+ for (TObjList::iterator theIter = theEntry->m_Editors.begin(),
+ theEnd = theEntry->m_Editors.end();
+ theIter != theEnd; ++theIter) {
+ SVSEditorObject *theExecutableContent =
+ static_cast<SVSEditorObject *>(theIter->mPtr);
+ if (theExecutableContent) {
+ theExecutableContent->m_ParentObject = theState;
+ }
+ }
+ }
+ }
+ {
+ NVScopedRefCounted<SVSEntry> theEntry = theIter->second.second;
+ if (theEntry) {
+ for (TObjList::iterator theIter = theEntry->m_Editors.begin(),
+ theEnd = theEntry->m_Editors.end();
+ theIter != theEnd; ++theIter) {
+ SVSEditorObject *theExecutableContent =
+ static_cast<SVSEditorObject *>(theIter->mPtr);
+ if (theExecutableContent) {
+ theExecutableContent->m_ParentObject = theState;
+ }
+ }
+ }
+ }
+ ++theIter;
+ } else {
+ theStateMap.erase(theIter++);
+ theRetval = true;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return theRetval;
+ }
+ virtual void RegisterChangeListener(IStateMachineChangeListener &) {}
+ virtual void UnregisterChangeListener(IStateMachineChangeListener &) {}
+};
+}
+
+IDatamodel &IDatamodel::Create(uic::state::editor::TFoundationPtr inFoundation,
+ const TEditorStr &inPath, const TEditorStr &inAppDir,
+ IStateMachineEditorManager &inStateMachineEditorManager,
+ IInStream *inStream)
+{
+ return IDatamodel::Create(inFoundation, inPath, inAppDir, inStateMachineEditorManager,
+ IStringTable::CreateStringTable(inFoundation->getAllocator()),
+ inStream);
+}
+
+IDatamodel &IDatamodel::Create(uic::state::editor::TFoundationPtr inFoundation,
+ const TEditorStr &inPath, const TEditorStr &inAppDir,
+ IStateMachineEditorManager &inStateMachineEditorManager,
+ IStringTable &inStringTable, IInStream *inStream)
+{
+ DatamodelImpl &theDatamodel = *QT3DS_NEW(inFoundation->getAllocator(), DatamodelImpl)(
+ inFoundation, inPath, inAppDir, inStateMachineEditorManager, inStringTable);
+ if (inStream)
+ theDatamodel.LoadUIADatabaseFromStream(*inStream);
+ else
+ theDatamodel.LoadUIADatabase();
+ return theDatamodel;
+}
diff --git a/src/Runtime/Source/UICState/Editor/UICUIADatamodel.h b/src/Runtime/Source/UICState/Editor/UICUIADatamodel.h
new file mode 100644
index 00000000..e35a8a5e
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICUIADatamodel.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIA_DATAMODEL_H
+#define UIA_DATAMODEL_H
+#include "UICState.h"
+#include "UICStateEditor.h"
+#include "UICMetadata.h"
+#include "UICStateInterpreter.h"
+#include "UICStateEditorFoundation.h"
+
+namespace uic {
+namespace app {
+ using namespace uic::state;
+ using namespace uic::state::editor;
+
+ typedef eastl::pair<Q3DStudio::ERuntimeDataModelDataType,
+ Q3DStudio::ERuntimeAdditionalMetaDataType>
+ TDataType;
+
+ struct SDatamodelValue;
+
+ struct SAppElement;
+
+ struct SPresentation
+ {
+ eastl::string m_Id;
+ eastl::string m_SrcPath;
+ eastl::string m_Author;
+ eastl::string m_Company;
+ QT3DSU32 m_Width;
+ QT3DSU32 m_Height;
+ SAppElement *m_Scene;
+ SPresentation()
+ : m_Width(800)
+ , m_Height(480)
+ , m_Scene(NULL)
+ {
+ }
+ };
+
+ class IStateMachineChangeListener
+ {
+ public:
+ virtual ~IStateMachineChangeListener() {}
+ virtual bool OnDeleteState(TObjPtr inObject) = 0;
+ virtual bool OnReloadStateMachine(TEditorPtr inStateMachineEditor) = 0;
+ };
+
+ class IStateMachineEditorManager
+ {
+ public:
+ virtual ~IStateMachineEditorManager() {}
+ virtual TEditorPtr GetOrCreateEditor(const TEditorStr &inFullPath, bool *outLoadStatus) = 0;
+ virtual void RegisterChangeListener(IStateMachineChangeListener &inListener) = 0;
+ virtual void UnregisterChangeListener(IStateMachineChangeListener &inListener) = 0;
+ };
+
+ class IDatamodel : public ITransactionManager,
+ public IStateMachineEditorManager,
+ public IStateMachineChangeListener
+ {
+ protected:
+ virtual ~IDatamodel() {}
+ public:
+ // Returns true if we had to create the file. Users should always keep track of the
+ // transaction stack also
+ // this does not include that.
+ virtual bool IsDirty() const = 0;
+ // General queries of the dataset defined by the uia file and all uip files and scxml files
+ // it includes.
+
+ virtual TEditorStrList GetComponents() = 0;
+ virtual TEditorStrList GetComponentSlides(const TEditorStr &inComponent) = 0;
+
+ virtual TEditorStrList GetBehaviors() = 0;
+
+ virtual Q3DStudio::THandlerList GetHandlers(const TEditorStr &inBehavior) = 0;
+
+ virtual Q3DStudio::TVisualEventList GetVisualEvents(const TEditorStr &inElement) = 0;
+
+ virtual TEditorStrList GetElements() = 0;
+
+ virtual Q3DStudio::TAttOrArgList GetElementAttributes(const TEditorStr &inElement) = 0;
+
+ // Necessary to share transaction info and trigger deletes of related information but not
+ // going to get
+ // done right now.
+ // virtual TEditorPtr GetOrCreateEditor( const TEditorStr& inFullPath ) = 0;
+
+ // The editor obj has a remove from graph function that really is delete
+ virtual TObjList
+ GetVisualStateExecutableContent(TObjPtr inObject,
+ InterpreterEventTypes::Enum inEventType) = 0;
+ // Type name is the element name, so set-attribute, goto-slide, or fire-event
+ virtual TObjPtr AppendVisualStateExecutableContent(TObjPtr inObject,
+ InterpreterEventTypes::Enum inEventType,
+ const char8_t *inElementName) = 0;
+ virtual TObjPtr ChangeVisualStateExecutableContentName(TObjPtr inContent,
+ const char8_t *inElementName) = 0;
+
+ // Called when the source uia changes.
+ virtual void RefreshFile() = 0;
+ virtual void RefreshFromStream(qt3ds::foundation::IInStream &inStream) = 0;
+ // Returns the path that was passed in on create.
+ virtual TEditorStr GetFilePath() = 0;
+
+ // Returns false if unable to save, ask users to check the file out.
+ virtual bool Save() = 0;
+ virtual bool Save(qt3ds::foundation::IOutStream &inStream) = 0;
+
+ // The section below allows someone to build an initial scene graph.
+ // Note that components have additional properties
+ // Get a list of presentations found while parsing uia file.
+ virtual eastl::vector<SPresentation> GetPresentations() = 0;
+ virtual eastl::string GetElementType(SAppElement &elem) = 0;
+ virtual eastl::string GetElementId(SAppElement &elem) = 0;
+ virtual bool IsComponent(SAppElement &elem) = 0;
+ virtual Q3DStudio::TAttOrArgList GetElementAttributes(SAppElement &elem) = 0;
+ // These are found either on the slide or on the component depending on if you are working
+ // in uip space or runtime space.
+ virtual Q3DStudio::TAttOrArgList GetSlideAttributes() = 0;
+ virtual eastl::vector<SDatamodelValue>
+ GetElementAttributeInitialValues(SAppElement &elem) = 0;
+ virtual eastl::vector<SAppElement *> GetElementChildren(SAppElement &elem) = 0;
+
+ virtual eastl::string GetLastLoadingErrorString() = 0;
+
+ virtual NVFoundationBase &GetFoundation() = 0;
+ virtual IStringTable &GetStringTable() = 0;
+
+ // inPath may either exist or not. You can pass in a uip file as well as a uia file.
+ // application dir is so we can find the meta data.
+ // inStream provides a way to load from memory, it will be used if it's not NULL.
+ static IDatamodel &Create(uic::state::editor::TFoundationPtr inFoundation,
+ const TEditorStr &inPath, const TEditorStr &inApplicationDir,
+ IStateMachineEditorManager &inStateMachineEditorManager,
+ IInStream *inStream = 0);
+ static IDatamodel &Create(uic::state::editor::TFoundationPtr inFoundation,
+ const TEditorStr &inPath, const TEditorStr &inApplicationDir,
+ IStateMachineEditorManager &inStateMachineEditorManager,
+ IStringTable &inStringTable, IInStream *inStream = 0);
+ };
+
+ typedef NVScopedRefCounted<IDatamodel> TDatamodelPtr;
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Editor/UICUIADatamodelValue.h b/src/Runtime/Source/UICState/Editor/UICUIADatamodelValue.h
new file mode 100644
index 00000000..523c3bbb
--- /dev/null
+++ b/src/Runtime/Source/UICState/Editor/UICUIADatamodelValue.h
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIA_DATAMODEL_VALUE_H
+#define UIA_DATAMODEL_VALUE_H
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "UICUIADatamodel.h"
+
+namespace uic {
+namespace app {
+
+ using namespace Q3DStudio;
+
+ template <typename TDatatype>
+ struct SDatamodelValueTypeMap
+ {
+ };
+
+#define UIC_UIA_DATAMODEL_TYPE_MAP(type, enumname) \
+ template <> \
+ struct SDatamodelValueTypeMap<type> \
+ { \
+ static Q3DStudio::ERuntimeDataModelDataType GetType() { return Q3DStudio::enumname; } \
+ };
+
+ struct SGuid
+ {
+ long m_Data[4];
+ };
+
+ struct SObjectRef
+ {
+ CRegisteredString m_Presentation;
+ CRegisteredString m_Id;
+ };
+
+ class CStringOrInt
+ {
+ bool m_IsString;
+ CRegisteredString m_String;
+ int m_IntValue;
+
+ public:
+ CStringOrInt(CRegisteredString val = CRegisteredString())
+ : m_IsString(true)
+ , m_String(val)
+ , m_IntValue(0)
+ {
+ }
+ CStringOrInt(int val)
+ : m_IsString(false)
+ , m_IntValue(val)
+ {
+ }
+ CStringOrInt(const CStringOrInt &other)
+ : m_IsString(other.m_IsString)
+ , m_String(other.m_String)
+ , m_IntValue(other.m_IntValue)
+ {
+ }
+ CStringOrInt &operator=(const CStringOrInt &other)
+ {
+ m_IsString = other.m_IsString;
+ m_String = other.m_String;
+ m_IntValue = other.m_IntValue;
+ return *this;
+ }
+ bool IsString() const { return m_IsString; }
+ CRegisteredString StringValue() const
+ {
+ QT3DS_ASSERT(m_IsString);
+ return m_String;
+ }
+ int IntValue() const
+ {
+ QT3DS_ASSERT(m_IsString == false);
+ return m_IntValue;
+ }
+ };
+
+ UIC_UIA_DATAMODEL_TYPE_MAP(float, ERuntimeDataModelDataTypeFloat);
+ UIC_UIA_DATAMODEL_TYPE_MAP(QT3DSVec2, ERuntimeDataModelDataTypeFloat2);
+ UIC_UIA_DATAMODEL_TYPE_MAP(QT3DSVec3, ERuntimeDataModelDataTypeFloat3);
+ UIC_UIA_DATAMODEL_TYPE_MAP(QT3DSI32, ERuntimeDataModelDataTypeLong);
+ UIC_UIA_DATAMODEL_TYPE_MAP(eastl::string, ERuntimeDataModelDataTypeString);
+ UIC_UIA_DATAMODEL_TYPE_MAP(bool, ERuntimeDataModelDataTypeBool);
+ UIC_UIA_DATAMODEL_TYPE_MAP(SGuid, ERuntimeDataModelDataTypeLong4);
+ UIC_UIA_DATAMODEL_TYPE_MAP(CRegisteredString, ERuntimeDataModelDataTypeStringRef);
+ UIC_UIA_DATAMODEL_TYPE_MAP(SObjectRef, ERuntimeDataModelDataTypeObjectRef);
+ UIC_UIA_DATAMODEL_TYPE_MAP(CStringOrInt, ERuntimeDataModelDataTypeStringOrInt);
+
+ struct SDatamodelValueUnionTraits
+ {
+ typedef ERuntimeDataModelDataType TIdType;
+ enum {
+ TBufferSize = sizeof(eastl::string),
+ };
+
+ static TIdType getNoDataId() { return ERuntimeDataModelDataTypeNone; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SDatamodelValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case ERuntimeDataModelDataTypeFloat:
+ return inVisitor(*NVUnionCast<float *>(inData));
+ case ERuntimeDataModelDataTypeFloat2:
+ return inVisitor(*NVUnionCast<QT3DSVec2 *>(inData));
+ case ERuntimeDataModelDataTypeFloat3:
+ return inVisitor(*NVUnionCast<QT3DSVec3 *>(inData));
+ case ERuntimeDataModelDataTypeLong:
+ return inVisitor(*NVUnionCast<QT3DSI32 *>(inData));
+ case ERuntimeDataModelDataTypeString:
+ return inVisitor(*NVUnionCast<eastl::string *>(inData));
+ case ERuntimeDataModelDataTypeBool:
+ return inVisitor(*NVUnionCast<bool *>(inData));
+ case ERuntimeDataModelDataTypeLong4:
+ return inVisitor(*NVUnionCast<SGuid *>(inData));
+ case ERuntimeDataModelDataTypeStringRef:
+ return inVisitor(*NVUnionCast<CRegisteredString *>(inData));
+ case ERuntimeDataModelDataTypeObjectRef:
+ return inVisitor(*NVUnionCast<SObjectRef *>(inData));
+ case ERuntimeDataModelDataTypeStringOrInt:
+ return inVisitor(*NVUnionCast<CStringOrInt *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case ERuntimeDataModelDataTypeNone:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case ERuntimeDataModelDataTypeFloat:
+ return inVisitor(*NVUnionCast<const float *>(inData));
+ case ERuntimeDataModelDataTypeFloat2:
+ return inVisitor(*NVUnionCast<const QT3DSVec2 *>(inData));
+ case ERuntimeDataModelDataTypeFloat3:
+ return inVisitor(*NVUnionCast<const QT3DSVec3 *>(inData));
+ case ERuntimeDataModelDataTypeLong:
+ return inVisitor(*NVUnionCast<const QT3DSI32 *>(inData));
+ case ERuntimeDataModelDataTypeString:
+ return inVisitor(*NVUnionCast<const eastl::string *>(inData));
+ case ERuntimeDataModelDataTypeBool:
+ return inVisitor(*NVUnionCast<const bool *>(inData));
+ case ERuntimeDataModelDataTypeLong4:
+ return inVisitor(*NVUnionCast<const SGuid *>(inData));
+ case ERuntimeDataModelDataTypeStringRef:
+ return inVisitor(*NVUnionCast<const CRegisteredString *>(inData));
+ case ERuntimeDataModelDataTypeObjectRef:
+ return inVisitor(*NVUnionCast<const SObjectRef *>(inData));
+ case ERuntimeDataModelDataTypeStringOrInt:
+ return inVisitor(*NVUnionCast<const CStringOrInt *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case ERuntimeDataModelDataTypeNone:
+ return inVisitor();
+ }
+ }
+ };
+}
+}
+
+// need some specializations in the original nv foundation namespace
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<uic::app::SGuid>
+ {
+ void destruct(uic::app::SGuid &) {}
+ };
+ template <>
+ struct DestructTraits<uic::app::SObjectRef>
+ {
+ void destruct(uic::app::SObjectRef &) {}
+ };
+ template <>
+ struct DestructTraits<uic::app::CStringOrInt>
+ {
+ void destruct(uic::app::CStringOrInt &) {}
+ };
+ template <>
+ struct DestructTraits<CRegisteredString>
+ {
+ void destruct(CRegisteredString &) {}
+ };
+}
+}
+
+namespace uic {
+namespace app {
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SDatamodelValueUnionTraits,
+ SDatamodelValueUnionTraits::
+ TBufferSize>,
+ SDatamodelValueUnionTraits::TBufferSize>
+ TDatamodelUnionType;
+
+ struct SDatamodelValue : public TDatamodelUnionType
+ {
+ SDatamodelValue() {}
+ SDatamodelValue(const SDatamodelValue &other)
+ : TDatamodelUnionType(static_cast<const TDatamodelUnionType &>(other))
+ {
+ }
+ SDatamodelValue(float other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(QT3DSVec2 other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(QT3DSVec3 other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(QT3DSI32 other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(const eastl::string &other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(bool other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(SGuid other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(CRegisteredString other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(SObjectRef other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue(CStringOrInt other)
+ : TDatamodelUnionType(other)
+ {
+ }
+ SDatamodelValue &operator=(const SDatamodelValue &other)
+ {
+ TDatamodelUnionType::operator=(other);
+ return *this;
+ }
+ };
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICState/Include/UICState.h b/src/Runtime/Source/UICState/Include/UICState.h
new file mode 100644
index 00000000..64b23f8c
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICState.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_STATE_H
+#define UIC_STATE_H
+
+namespace qt3ds {
+class NVAllocatorCallback;
+class NVFoundationBase;
+namespace foundation {
+ class CRegisteredString;
+ class IStringTable;
+ class IOutStream;
+ class IInStream;
+ class IDOMFactory;
+ struct SDOMAttribute;
+ struct SDOMElement;
+ struct SNamespacePairNode;
+ class SocketStream;
+}
+
+namespace intrinsics {
+}
+}
+
+namespace uic {
+namespace state {
+
+ using namespace qt3ds;
+ using namespace qt3ds::foundation;
+ using namespace qt3ds::intrinsics;
+ using qt3ds::foundation::CRegisteredString;
+ using qt3ds::foundation::IStringTable;
+ class IStateContext;
+ class IStateInterpreter;
+ class IStateLogger;
+ class IExecutionContext;
+ class IScriptContext;
+ struct SSCXML;
+ struct SState;
+ struct STransition;
+ struct SParallel;
+ struct SFinal;
+ struct SHistory;
+ struct SOnEntry;
+ struct SOnExit;
+ struct SSend;
+ struct SRaise;
+ struct SIf;
+ struct SElseIf;
+ struct SElse;
+ struct SLog;
+ struct SAssign;
+ struct SScript;
+ struct SDataModel;
+ struct SData;
+ struct SStateNode;
+ struct SCancel;
+
+ namespace editor {
+ class IEditor;
+ class IEditorObject;
+ }
+
+ namespace debugger {
+ class IDebugOutStream;
+ struct STransitionId;
+ class IStateMachineListener;
+ class IStateMachineDebugInterface;
+ class IDebugger;
+ struct SDebugPropertyDeclaration;
+ class IDebuggedInterpreter;
+ class IDebuggerMasterListener;
+ class IDebuggedInterpreter;
+ struct SMicrostep;
+ class IScriptStateListener;
+ }
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Include/UICStateContext.h b/src/Runtime/Source/UICState/Include/UICStateContext.h
new file mode 100644
index 00000000..4f74bbf9
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateContext.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_CONTEXT_H
+#define UIC_STATE_CONTEXT_H
+#include "UICState.h"
+#include "UICStateTypes.h"
+
+namespace uic {
+namespace state {
+
+ // Thanks to the crazy world we live in, we have to store xml extension information
+ // on the state context.
+ struct SItemExtensionInfo
+ {
+ void *m_ItemPtr;
+ TDOMElementNodeList m_ExtensionNodes;
+ TDOMAttributeNodeList m_ExtensionAttributes;
+ SItemExtensionInfo(void *inItemPtr)
+ : m_ItemPtr(inItemPtr)
+ {
+ }
+ };
+ typedef nvhash_map<void *, SItemExtensionInfo> TPtrExtensionMap;
+ // Parsing produces a list of send objects that need to be added into the script
+ // context if they have their idlocation attribute set.
+ typedef nvvector<SSend *> TSendList;
+
+ class IStateContext : public NVRefCounted
+ {
+ public:
+ // Can only be done once.
+ virtual void SetRoot(SSCXML &inRoot) = 0;
+ virtual SSCXML *GetRoot() = 0;
+ virtual void AddSendToList(SSend &inSend) = 0;
+ virtual NVConstDataRef<SSend *> GetSendList() = 0;
+ virtual void SetDOMFactory(IDOMFactory *inFactory) = 0;
+ virtual IDOMFactory *GetDOMFactory() = 0;
+ virtual NVConstDataRef<NVScopedRefCounted<IStateContext>> GetSubContexts() = 0;
+ virtual bool ContainsId(const CRegisteredString &inId) = 0;
+ virtual bool InsertId(const CRegisteredString &inId, const SIdValue &inValue) = 0;
+ virtual void EraseId(const CRegisteredString &inId) = 0;
+ virtual SStateNode *FindStateNode(const CRegisteredString &inStr) = 0;
+ virtual SSend *FindSend(const CRegisteredString &inStr) = 0;
+
+ virtual SItemExtensionInfo *GetExtensionInfo(void *inItem) = 0;
+ virtual SItemExtensionInfo &GetOrCreateExtensionInfo(void *inItem) = 0;
+
+ virtual void SetFirstNSNode(SNamespacePairNode &inNode) = 0;
+ virtual SNamespacePairNode *GetFirstNSNode() = 0;
+
+ virtual void Save(IOutStream &inOutStream, editor::IEditor *inEditor = NULL) = 0;
+
+ // The graph allocator is expected to release anything allocated via it; the general
+ // allocator doesn't need to do this.
+ // Filename is stored on the context for debugging purposes, editor is used if during
+ // loading so we can load extra
+ // information that is associated with but not stored on the state graph.
+ // String table will be created if not passed in, editor is optional.
+ static IStateContext *Load(NVAllocatorCallback &inGraphAllocator,
+ NVFoundationBase &inFoundation, IInStream &inStream,
+ const char8_t *inFilename, IStringTable *inStrTable = NULL,
+ editor::IEditor *inEditor = NULL);
+
+ static IStateContext *Create(NVFoundationBase &inGeneralAlloc);
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateExecutionContext.h b/src/Runtime/Source/UICState/Include/UICStateExecutionContext.h
new file mode 100644
index 00000000..aa2de0b1
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateExecutionContext.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EXECUTION_CONTEXT_H
+#define UIC_STATE_EXECUTION_CONTEXT_H
+#pragma once
+#include "UICState.h"
+#include "UICStateTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+
+namespace uic {
+namespace state {
+
+ class IStateLogger : public NVRefCounted
+ {
+ protected:
+ virtual ~IStateLogger() {}
+ public:
+ virtual void Log(const char8_t *inLabel, const char8_t *inExpression) = 0;
+ };
+ // Implementation of the execution context of the scxml state specification.
+ // Implementations if,send,raise,foreach,etc working closely with the scripting
+ // system.
+ class IExecutionContext : public NVRefCounted
+ {
+ protected:
+ virtual ~IExecutionContext() {}
+ public:
+ virtual void SetInterpreter(IStateInterpreter &inInterpreter) = 0;
+ virtual void SetMachineDebugLogger(IStateLogger &inDebugLogger) = 0;
+ virtual void Execute(STransition &inTransaction) = 0;
+ // These functions take the node as well as the list so a context can cache a fast
+ // execution path if necessary.
+ virtual void Execute(SStateNode &inNode, TOnEntryList &inList) = 0;
+ virtual void Execute(SStateNode &inNode, TOnExitList &inList) = 0;
+
+ // Returns the time string in milliseconds.
+ static QT3DSU64 ParseTimeStrToMilliseconds(const char8_t *timeStr);
+
+ static IExecutionContext &Create(NVFoundationBase &inFoundation,
+ IStringTable &inStringTable, IStateLogger &inLogger,
+ IScriptContext &inScriptContext);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateExecutionTypes.h b/src/Runtime/Source/UICState/Include/UICStateExecutionTypes.h
new file mode 100644
index 00000000..1c8c6b2f
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateExecutionTypes.h
@@ -0,0 +1,392 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_EXECUTION_TYPES_H
+#define UIC_STATE_EXECUTION_TYPES_H
+#pragma once
+#include "UICStateTypes.h"
+
+namespace uic {
+namespace state {
+
+ struct ExecutableContentTypes
+ {
+ enum Enum {
+ NoType = 0,
+ Raise,
+ If,
+ ElseIf,
+ Else,
+ Foreach,
+ Log,
+ Assign,
+ Script,
+ Send,
+ Cancel,
+ Param,
+ Content,
+ };
+ static const char8_t *ToString(Enum inVal)
+ {
+ switch (inVal) {
+ case Raise:
+ return "Raise";
+ case If:
+ return "If";
+ case ElseIf:
+ return "ElseIf";
+ case Else:
+ return "Else";
+ case Foreach:
+ return "Foreach";
+ case Log:
+ return "Log";
+ case Assign:
+ return "Assign";
+ case Script:
+ return "Script";
+ case Send:
+ return "Send";
+ case Cancel:
+ return "Cancel";
+ case Param:
+ return "Param";
+ case Content:
+ return "Content";
+ default:
+ return "Unknown execution type";
+ }
+ }
+ };
+
+ struct SRaise;
+ struct SIf;
+ struct SElseIf;
+ struct SElse;
+ struct SForeach;
+ struct SLog;
+ struct SAssign;
+ struct SScript;
+ struct SSend;
+ struct SCancel;
+ struct SParam;
+ struct SContent;
+
+ template <typename TDataType>
+ struct SExecutableContentTypeMap
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::NoType;
+ }
+ };
+
+ template <>
+ struct SExecutableContentTypeMap<SRaise>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Raise;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SIf>
+ {
+ static ExecutableContentTypes::Enum GetContentType() { return ExecutableContentTypes::If; }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SElseIf>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::ElseIf;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SElse>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Else;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SForeach>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Foreach;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SLog>
+ {
+ static ExecutableContentTypes::Enum GetContentType() { return ExecutableContentTypes::Log; }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SAssign>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Assign;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SScript>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Script;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SSend>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Send;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SCancel>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Cancel;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SParam>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Param;
+ }
+ };
+ template <>
+ struct SExecutableContentTypeMap<SContent>
+ {
+ static ExecutableContentTypes::Enum GetContentType()
+ {
+ return ExecutableContentTypes::Content;
+ }
+ };
+
+ // Defined by the execution context to speed up evaluation of executable data.
+ struct SExecutionData;
+
+ struct SExecutableContent
+ {
+ const ExecutableContentTypes::Enum m_Type;
+ SStateNode *m_StateNodeParent;
+ SExecutableContent *m_Parent;
+ SExecutableContent *m_NextSibling;
+ SExecutableContent *m_PreviousSibling;
+ TExecutableContentList m_Children;
+
+ SExecutableContent(ExecutableContentTypes::Enum inType)
+ : m_Type(inType)
+ , m_StateNodeParent(NULL)
+ , m_Parent(NULL)
+ , m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ {
+ }
+
+ template <typename TDataType>
+ TDataType *CastTo()
+ {
+ if (m_Type == SExecutableContentTypeMap<TDataType>::GetContentType())
+ return static_cast<TDataType *>(this);
+ return NULL;
+ }
+
+ template <typename TDataType>
+ const TDataType *CastTo() const
+ {
+ if (m_Type == SExecutableContentTypeMap<TDataType>::GetContentType())
+ return static_cast<const TDataType *>(this);
+ return NULL;
+ }
+ };
+
+ IMPLEMENT_INVASIVE_LIST(ExecutableContent, m_PreviousSibling, m_NextSibling);
+
+ struct SRaise : public SExecutableContent
+ {
+ CRegisteredString m_Event;
+ SRaise()
+ : SExecutableContent(ExecutableContentTypes::Raise)
+ {
+ }
+ };
+
+ struct SIf : public SExecutableContent
+ {
+ const char8_t *m_Cond;
+ SIf()
+ : SExecutableContent(ExecutableContentTypes::If)
+ , m_Cond(NULL)
+ {
+ }
+ };
+
+ struct SElseIf : public SExecutableContent
+ {
+ const char8_t *m_Cond;
+ SElseIf()
+ : SExecutableContent(ExecutableContentTypes::ElseIf)
+ , m_Cond(NULL)
+ {
+ }
+ };
+
+ struct SElse : public SExecutableContent
+ {
+ SElse()
+ : SExecutableContent(ExecutableContentTypes::Else)
+ {
+ }
+ };
+
+ struct SForeach : public SExecutableContent
+ {
+ CRegisteredString m_Array;
+ CRegisteredString m_Item;
+ CRegisteredString m_Index;
+ SForeach()
+ : SExecutableContent(ExecutableContentTypes::Foreach)
+ {
+ }
+ };
+
+ struct SLog : public SExecutableContent
+ {
+ CRegisteredString m_Label;
+ const char8_t *m_Expression;
+ SLog()
+ : SExecutableContent(ExecutableContentTypes::Log)
+ , m_Expression(NULL)
+ {
+ }
+ };
+
+ struct SAssign : public SExecutableContent
+ {
+ const char8_t *m_Location;
+ const char8_t *m_Expression;
+ SAssign()
+ : SExecutableContent(ExecutableContentTypes::Assign)
+ , m_Location(NULL)
+ , m_Expression(NULL)
+ {
+ }
+ };
+
+ struct SScript : public SExecutableContent
+ {
+ const char8_t *m_URL;
+ const char8_t *m_Data;
+ SScript()
+ : SExecutableContent(ExecutableContentTypes::Script)
+ , m_URL(NULL)
+ , m_Data(NULL)
+ {
+ }
+ };
+
+ struct SSend : public SExecutableContent
+ {
+ CRegisteredString m_Event;
+ const char8_t *m_EventExpr;
+ const char8_t *m_Target;
+ const char8_t *m_TargetExpr;
+ const char8_t *m_Type;
+ const char8_t *m_TypeExpr;
+ CRegisteredString m_Id;
+ const char8_t *m_IdLocation;
+ const char8_t *m_Delay;
+ const char8_t *m_DelayExpr;
+ const char8_t *m_NameList;
+
+ SSend()
+ : SExecutableContent(ExecutableContentTypes::Send)
+ , m_EventExpr(NULL)
+ , m_Target(NULL)
+ , m_TargetExpr(NULL)
+ , m_Type(NULL)
+ , m_TypeExpr(NULL)
+ , m_IdLocation(NULL)
+ , m_Delay(NULL)
+ , m_DelayExpr(NULL)
+ , m_NameList(NULL)
+ {
+ }
+ };
+ struct SCancel : public SExecutableContent
+ {
+ // If we have an id.
+ SSend *m_Send;
+ const char8_t *m_IdExpression;
+
+ SCancel()
+ : SExecutableContent(ExecutableContentTypes::Cancel)
+ , m_Send(NULL)
+ , m_IdExpression(NULL)
+ {
+ }
+ };
+
+ struct SParam : public SExecutableContent
+ {
+ CRegisteredString m_Name;
+ const char8_t *m_Expr;
+ CRegisteredString m_Location;
+ SParam()
+ : SExecutableContent(ExecutableContentTypes::Param)
+ , m_Expr(NULL)
+ {
+ }
+ };
+
+ struct SContent : public SExecutableContent
+ {
+ const char8_t *m_Expr;
+ const char8_t *m_ContentValue;
+ SContent()
+ : SExecutableContent(ExecutableContentTypes::Content)
+ , m_Expr(NULL)
+ , m_ContentValue(NULL)
+ {
+ }
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateIdValue.h b/src/Runtime/Source/UICState/Include/UICStateIdValue.h
new file mode 100644
index 00000000..8d18da2b
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateIdValue.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_STATE_ID_TYPE_VALUE_H
+#define UIC_STATE_ID_TYPE_VALUE_H
+#include "UICState.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+
+// Discriminated union to unify different things that may be identified by an id
+namespace uic {
+namespace state {
+
+ struct IdValueTypes
+ {
+ enum Enum {
+ NoIdValue = 0,
+ StateNode,
+ Send,
+ };
+ };
+
+ template <typename TDataType>
+ struct SIdValueTypeMap
+ {
+ static IdValueTypes::Enum GetType() { return IdValueTypes::NoIdValue; }
+ };
+
+ template <>
+ struct SIdValueTypeMap<SStateNode *>
+ {
+ static IdValueTypes::Enum GetType() { return IdValueTypes::StateNode; }
+ };
+ template <>
+ struct SIdValueTypeMap<SSend *>
+ {
+ static IdValueTypes::Enum GetType() { return IdValueTypes::Send; }
+ };
+
+ struct SIdValueUnionTraits
+ {
+ typedef IdValueTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(void *),
+ };
+
+ static TIdType getNoDataId() { return IdValueTypes::NoIdValue; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SIdValueTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case IdValueTypes::StateNode:
+ return inVisitor(*NVUnionCast<SStateNode **>(inData));
+ case IdValueTypes::Send:
+ return inVisitor(*NVUnionCast<SSend **>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case IdValueTypes::NoIdValue:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case IdValueTypes::StateNode:
+ return inVisitor(*NVUnionCast<const SStateNode **>(inData));
+ case IdValueTypes::Send:
+ return inVisitor(*NVUnionCast<const SSend **>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case IdValueTypes::NoIdValue:
+ return inVisitor();
+ }
+ }
+ };
+}
+}
+
+// need some specializations in the original nv foundation namespace
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<uic::state::SStateNode *>
+ {
+ void destruct(uic::state::SStateNode *) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SSend *>
+ {
+ void destruct(uic::state::SSend *) {}
+ };
+}
+}
+
+namespace uic {
+namespace state {
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SIdValueUnionTraits,
+ SIdValueUnionTraits::TBufferSize>,
+ SIdValueUnionTraits::TBufferSize>
+ TIdUnionType;
+
+ struct SIdValue : public TIdUnionType
+ {
+ SIdValue() {}
+
+ SIdValue(const SIdValue &inOther)
+ : TIdUnionType(static_cast<const TIdUnionType &>(inOther))
+ {
+ }
+
+ SIdValue(SStateNode *inDt)
+ : TIdUnionType(inDt)
+ {
+ }
+ SIdValue(SSend *inDt)
+ : TIdUnionType(inDt)
+ {
+ }
+
+ SIdValue &operator=(const SIdValue &inOther)
+ {
+ TIdUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SIdValue &inOther) const { return TIdUnionType::operator==(inOther); }
+ bool operator!=(const SIdValue &inOther) const { return TIdUnionType::operator!=(inOther); }
+
+ bool empty() const { return getType() == IdValueTypes::NoIdValue; }
+ };
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Include/UICStateInterpreter.h b/src/Runtime/Source/UICState/Include/UICStateInterpreter.h
new file mode 100644
index 00000000..8e489a80
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateInterpreter.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_INTERPRETER_H
+#define UIC_STATE_INTERPRETER_H
+#pragma once
+#include "UICState.h"
+#include "UICStateTypes.h"
+#include "UICStateSignalConnection.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSDataRef.h"
+
+namespace uic {
+namespace state {
+ struct InterpreterEventTypes
+ {
+ enum Enum {
+ UnknownInterpreterEvent = 0,
+ StateEnter,
+ StateExit,
+ Transition,
+ };
+ };
+
+ struct IStateInterpreterEventHandler
+ {
+ protected:
+ virtual ~IStateInterpreterEventHandler() {}
+
+ public:
+ virtual void OnInterpreterEvent(InterpreterEventTypes::Enum inEvent,
+ CRegisteredString inEventId) = 0;
+ };
+
+ class IStateInterpreter : public NVRefCounted
+ {
+ protected:
+ virtual ~IStateInterpreter() {}
+ public:
+ // Setup of the state system, you can add a set of roots to the state graph.
+ virtual NVConstDataRef<SStateNode *> GetConfiguration() = 0;
+ // State context is referenced by this object.
+ // We can optionally validate the transitions to ensure that no transition can put us into
+ // an invalid state
+ // and so that simple loops don't exist. It is highly recommended to use this; it is done
+ // once via startup and
+ // shouldn't add appreciably to the initialization time but it makes the transition system a
+ // lot more robust.
+ virtual bool Initialize(IStateContext &inContext, bool inValidateTransitions = true) = 0;
+ // Bring the state machine to the internal state.
+ // Returns the list of states for the initial configuration
+ virtual NVConstDataRef<SStateNode *> Start() = 0;
+
+ // Execute transitions, internal events and external events until nothing is left to
+ // be done.
+ virtual NVConstDataRef<SStateNode *> Execute() = 0;
+
+ virtual bool IsRunning() const = 0;
+ virtual bool EventsPending() const = 0;
+
+ // Queue an event with an optional delay (0 means no delay).
+ // If the event has a delay then it can optionally be cancelled.
+ virtual void QueueEvent(const char8_t *inEventName, QT3DSU64 inDelay,
+ CRegisteredString inCancelId, bool inIsExternal = true) = 0;
+ virtual void QueueEvent(TEventPtr inEvent, QT3DSU64 inDelay, CRegisteredString inCancelId,
+ bool inIsExternal = true) = 0;
+ virtual void QueueEvent(TEventPtr inEvent, bool inIsExternal = true) = 0;
+ virtual void QueueEvent(const char8_t *inEventName, bool inIsExternal = true) = 0;
+
+ // Cancel an event with a particular id. Only cancels delayed events that have not fired
+ // yet.
+ virtual void CancelEvent(CRegisteredString inCancelId) = 0;
+
+ // When the connection gets destroyed, the hander will get no more events.
+ virtual TSignalConnectionPtr
+ RegisterEventHandler(IStateInterpreterEventHandler &inHandler) = 0;
+
+ virtual debugger::IStateMachineDebugInterface &GetDebugInterface() = 0;
+
+ virtual NVFoundationBase &GetFoundation() = 0;
+
+ virtual IScriptContext &GetScriptContext() = 0;
+
+ virtual IStateContext *GetStateContext() = 0;
+
+ // The only code that needs to happen in the state system is the code that executes a
+ // condition.
+ static IStateInterpreter &Create(NVFoundationBase &inFnd, IStringTable &inStrTable,
+ IScriptContext &inScriptContext,
+ IExecutionContext &inExecutionContext);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateLuaScriptContext.h b/src/Runtime/Source/UICState/Include/UICStateLuaScriptContext.h
new file mode 100644
index 00000000..224fec52
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateLuaScriptContext.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_LUA_SCRIPT_CONTEXT_H
+#define UIC_STATE_LUA_SCRIPT_CONTEXT_H
+#pragma once
+#include "UICState.h"
+#include "UICStateScriptContext.h"
+
+struct lua_State;
+
+namespace uic {
+namespace state {
+
+ class ILuaScriptContext : public IScriptContext
+ {
+ public:
+ static const char8_t *GetLuaContextTypeName() { return "lua5.1"; }
+ // Dump the global state table's keys and values
+ virtual void DumpGlobalState() = 0;
+
+ // Push the state machine's global table onto the stack.
+ virtual void GetGlobalTable() = 0;
+
+ static ILuaScriptContext &CreateLuaScriptContext(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable);
+ // Create a lua script context, chaining our information to another global state.
+ // In this case we won't close the state on exit.
+ static ILuaScriptContext &CreateLuaScriptContext(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable,
+ lua_State *inState,
+ int inGlobalTableIdx = 0);
+
+ // Export bindings that allow us to call the lua system.
+ // Exports these bindings to the global context:
+ // - parseSCXML{fullpathtofile} - parses an SCXML file and returns a lua object
+ //
+ // with at least these functions
+ //
+ // -- onAfterEnter - (callback) property called as function after state enter if valid.
+ // -- onBeforeExit - (callback) property called as function before state exit if valid.
+ //
+ // -- start {dm} start the state machine, optionally taking a datatable to use as the state
+ // machine's datatable.
+ // -- set(name,val) set the datamodel at name to value
+ // -- fireEvent(val) - val must have 'name' property set, will fire 'name' event in state
+ // machine.
+ // -- step() - step the state machine.
+ static void ExportLuaBindings(lua_State *inState);
+ // Export the parse function so clients can bind it wherever they like into their lua
+ // system.
+ // Optionally pass in a debugger for the system to use if a debug connection occurs.
+ static int ParseSCXML(lua_State *inState, debugger::IDebugger *inDebugger = NULL);
+ static int ParseSCXML(lua_State *inState, debugger::IDebugger *inDebugger,
+ NVFoundationBase &inFoundation, IStringTable &inStrTable);
+ static int Initialize(lua_State *inState, const char8_t *inId = 0);
+ static int Start(lua_State *inState);
+ // Given the lua state, the top item on the stack should be the table returned from the
+ // parseSCXML function
+ static IStateInterpreter *GetInterpreterFromBindings(lua_State *inState);
+
+ // Bind the lua interpreter into the lua state. The interpreter object is now at the top
+ // of the stack, so be sure to settop back when you are finished.
+ static void Bind(IStateInterpreter &inInterpreter, lua_State *inState);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateScriptContext.h b/src/Runtime/Source/UICState/Include/UICStateScriptContext.h
new file mode 100644
index 00000000..8342eb00
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateScriptContext.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_SCRIPT_CONTEXT_H
+#define UIC_STATE_SCRIPT_CONTEXT_H
+#pragma once
+#include "UICState.h"
+#include "UICStateTypes.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/Qt3DSOption.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+namespace state {
+
+ class IScriptEvent : public IEvent
+ {
+ public:
+ // returns true on success, false if error.execution should be signaled.
+ virtual bool SetParam(CRegisteredString inName, const char8_t *inExpression) = 0;
+ // Sets the expression as a string
+ virtual bool SetParamStr(CRegisteredString inName, const char8_t *inStr) = 0;
+ virtual bool SetDataExpr(const char8_t *inExpression) = 0;
+ virtual bool SetDataStr(const char8_t *inStr) = 0;
+ };
+
+ struct SScriptExecutionResult
+ {
+ const char8_t *m_Result;
+ const char8_t *m_Error;
+ SScriptExecutionResult(const char8_t *inData, const char8_t *inError)
+ : m_Result(inData)
+ , m_Error(inError)
+ {
+ }
+ SScriptExecutionResult()
+ : m_Result("")
+ , m_Error("")
+ {
+ }
+ bool Valid() const { return m_Error == NULL || *m_Error == 0; }
+ const char8_t *Result() const
+ {
+ QT3DS_ASSERT(Valid());
+ return m_Result;
+ }
+ const char8_t *Error() const
+ {
+ QT3DS_ASSERT(!Valid());
+ return m_Error;
+ }
+ };
+
+ class IScriptContext : public NVRefCounted
+ {
+ protected:
+ virtual ~IScriptContext() {}
+ public:
+ // Should functions returning options return othing
+ virtual Option<bool> ExecuteCondition(const char8_t *inCond) = 0;
+ // Used for logging.
+ // Error and result are good until next call into the script context.
+ virtual SScriptExecutionResult ExecuteExpressionToString(const char8_t *inExpr) = 0;
+
+ // If return value is false, error is signaled with GetErrorInfo.
+ virtual bool Assign(const char8_t *inVariable, const char8_t *inExpr) = 0;
+ // Assign a string to this variable location.
+ virtual void AssignStr(const char8_t *inVariable, const char8_t *inStr) = 0;
+
+ // If return value is false, error is signaled via GetErrorInfo.
+ // The actual pointer and content used for inscript is expected to not change during
+ // execution of the system.
+ // it is legal for contexts to cache information based off the script pointer value.
+ virtual bool ExecuteScript(const char8_t *inScript) = 0;
+ // Always return 1 result
+ virtual int ExecuteStr(const char8_t *inScript, bool withRet) = 0;
+
+ // Return true on success, false on failure, and Empty on error.
+ virtual Option<bool> BeginForeach(const char8_t *inArray, const char8_t *inItem,
+ const char8_t *inIdxVar = "") = 0;
+ virtual Option<bool> NextForeach(const char8_t *inItem, const char8_t *inIdxVar = "") = 0;
+ virtual void CancelForeach() = 0;
+
+ virtual void SetCurrentEvent(TEventPtr inEvent) = 0;
+ virtual void ClearCurrentEvent() = 0;
+ // Create an event we can attach extra data do.
+ virtual IScriptEvent *CreateScriptEvent(CRegisteredString inName) = 0;
+
+ virtual const char8_t *GetErrorInfo() = 0;
+
+ virtual void SetInterpreter(IStateInterpreter &inInterpreter) = 0;
+
+ virtual CRegisteredString GetContextType() { return CRegisteredString(); }
+
+ // Dumps a differential state from the last time someone asked. This is a debug interface;
+ // not meant to be used
+ // by multiple listeners concurrently.
+ virtual void DumpState(debugger::IScriptStateListener &inListener) = 0;
+ };
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateSharedImpl.h b/src/Runtime/Source/UICState/Include/UICStateSharedImpl.h
new file mode 100644
index 00000000..cb04f3f6
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateSharedImpl.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_SHARED_IMPL_H
+#define UIC_STATE_SHARED_IMPL_H
+#include "UICState.h"
+#include "foundation/Utils.h"
+
+namespace uic {
+namespace state {
+ namespace impl {
+
+ inline bool NameMatchesInternal(const char8_t *inTransEvent, QT3DSU32 transLen,
+ const char8_t *inEventName, QT3DSU32 eventLen)
+ {
+ QT3DSU32 idx, end;
+ // Empty loop intentional to find first nonmatching character
+ for (idx = 0, end = NVMin(transLen, eventLen);
+ idx < end && inTransEvent[idx] == inEventName[idx]; ++idx) {
+ }
+ // Note that in this case we point to the first nonmatching character which may be off
+ // the end of either
+ // eventStr or transStr
+ bool match = false;
+ if (idx == transLen) {
+ if (idx == eventLen)
+ match = true;
+ else if (inEventName[idx] == '.')
+ match = true;
+ else if (inTransEvent[idx - 1] == '.')
+ match = true;
+ } else if (idx == eventLen) {
+ if ((transLen - idx) == 1)
+ match = inTransEvent[idx] == '*' || inTransEvent[idx] == '.';
+
+ else if ((transLen - idx) == 2)
+ match = inTransEvent[idx] == '.' && inTransEvent[idx + 1] == '*';
+ } else {
+ if (inTransEvent[idx] == '*')
+ match = true;
+ }
+ return match;
+ }
+
+ inline const char8_t *FindNextNonSpace(const char8_t *inPtr)
+ {
+ for (; *inPtr == ' '; ++inPtr) {
+ }
+ return inPtr;
+ }
+
+ inline const char8_t *FindNextSpaceOrNull(const char8_t *inPtr)
+ {
+ for (; *inPtr && *inPtr != ' '; ++inPtr) {
+ }
+ return inPtr;
+ }
+
+ inline bool NameMatches(const char8_t *inTransEvent, const char8_t *inEventName)
+ {
+ inTransEvent = nonNull(inTransEvent);
+ inEventName = nonNull(inEventName);
+
+ QT3DSU32 transLen = StrLen(inTransEvent);
+
+ QT3DSU32 eventLen = StrLen(inEventName);
+ if (transLen == 0) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ if (eventLen == 0) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ for (inTransEvent = FindNextNonSpace(inTransEvent); inTransEvent && *inTransEvent;
+ inTransEvent = FindNextNonSpace(inTransEvent)) {
+ const char8_t *end = FindNextSpaceOrNull(inTransEvent);
+ QT3DSU32 len = (QT3DSU32)(end - inTransEvent);
+
+ if (len && NameMatchesInternal(inTransEvent, len, inEventName, eventLen))
+ return true;
+ inTransEvent = end;
+ }
+
+ return false;
+ }
+ }
+}
+}
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateSignalConnection.h b/src/Runtime/Source/UICState/Include/UICStateSignalConnection.h
new file mode 100644
index 00000000..ebf6c2a0
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateSignalConnection.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_SIGNAL_CONNECTION_H
+#define UIC_STATE_SIGNAL_CONNECTION_H
+#pragma once
+#include "UICState.h"
+#include "foundation/Qt3DSRefCounted.h"
+namespace uic {
+namespace state {
+
+ class IStateSignalConnection : public NVRefCounted
+ {
+ protected:
+ virtual ~IStateSignalConnection() {}
+ public:
+ };
+
+ typedef NVScopedRefCounted<IStateSignalConnection> TSignalConnectionPtr;
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateTypes.h b/src/Runtime/Source/UICState/Include/UICStateTypes.h
new file mode 100644
index 00000000..de2f7fb5
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateTypes.h
@@ -0,0 +1,720 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_STATE_TYPES_H
+#define UIC_STATE_TYPES_H
+#include "UICState.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSFlags.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/StringTable.h"
+#include "foundation/TaggedPointer.h"
+#include "foundation/Qt3DSVec2.h"
+#include "foundation/Qt3DSVec3.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Utils.h"
+#include "UICStateIdValue.h"
+
+namespace uic {
+namespace state {
+
+ // Link list definitions.
+ DEFINE_INVASIVE_LIST(StateNode);
+ DEFINE_INVASIVE_SINGLE_LIST(OnEntry);
+ DEFINE_INVASIVE_SINGLE_LIST(OnExit);
+ DEFINE_INVASIVE_SINGLE_LIST(DataModel);
+ DEFINE_INVASIVE_LIST(Invoke);
+
+ // Externally defined objects - These objects are defined by the implementation of the
+ // interpreter and the execution context. They are not used and cannot be manipulated by
+ // core state types.
+
+ // Standard content defined in another file so as to not clutter up the core state definitions.
+ struct SExecutableContent;
+ DEFINE_INVASIVE_LIST(ExecutableContent);
+ struct SScript;
+ struct SDataModel;
+
+ // Defined by the execution context; These objects can be defined by the implementation of the
+ // scripting
+ // system.
+ struct STransitionCondition;
+
+ // Defined by the interpreter. Really just a placeholder so the interpreter can cache
+ // item-specific data on an object.
+ struct SInterpreterData;
+
+ // We *have* to keep some subset of the data in document order because the algorithms
+ // defined in the specification rely on this.
+ struct StateNodeTypes
+ {
+ enum Enum {
+ UnknownType,
+ State,
+ Parallel,
+ Transition,
+ Final,
+ SCXML,
+ History,
+ };
+ static bool CanHaveChildren(StateNodeTypes::Enum val)
+ {
+ return val == State || val == Parallel || val == SCXML;
+ }
+ static bool CanHaveTransitions(StateNodeTypes::Enum val)
+ {
+ return val == State || val == Parallel;
+ }
+ static bool IsStateType(StateNodeTypes::Enum val)
+ {
+ return CanHaveChildren(val) || val == Final;
+ }
+ static bool IsTransitionType(StateNodeTypes::Enum val) { return val == Transition; }
+ static bool CanHaveInitializeNode(StateNodeTypes::Enum val) { return val == State; }
+ static bool IsAtomicType(StateNodeTypes::Enum val) { return val == State || val == Final; }
+ };
+
+ struct SState;
+ struct SParallel;
+ struct STransition;
+ struct SFinal;
+ struct SSCXML;
+ struct SHistory;
+
+ template <typename TDataType>
+ struct SStateNodeTypeMap
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::UnknownType; }
+ };
+
+ template <>
+ struct SStateNodeTypeMap<SState>
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::State; }
+ };
+ template <>
+ struct SStateNodeTypeMap<SParallel>
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::Parallel; }
+ };
+ template <>
+ struct SStateNodeTypeMap<STransition>
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::Transition; }
+ };
+ template <>
+ struct SStateNodeTypeMap<SFinal>
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::Final; }
+ };
+ template <>
+ struct SStateNodeTypeMap<SSCXML>
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::SCXML; }
+ };
+ template <>
+ struct SStateNodeTypeMap<SHistory>
+ {
+ static StateNodeTypes::Enum GetStateNodeType() { return StateNodeTypes::History; }
+ };
+ // Some editor info has to be contained on the state node. Description I am fine with eliding
+ // but
+ // most of the other information needs to sit on the nodes themselves.
+ struct StateNodeFlagValues
+ {
+ enum Enum {
+ HasNothing = 0,
+ HasPosition = 1,
+ HasDimension = 1 << 1,
+ HasColor = 1 << 2,
+ HasEndPosition = 1 << 3,
+ };
+ };
+
+ struct SStateNodeFlags : NVFlags<StateNodeFlagValues::Enum, QT3DSU32>
+ {
+ bool HasPosition() const { return this->operator&(StateNodeFlagValues::HasPosition); }
+ void SetHasPosition(bool val) { clearOrSet(val, StateNodeFlagValues::HasPosition); }
+ bool HasDimension() const { return this->operator&(StateNodeFlagValues::HasDimension); }
+ void SetHasDimension(bool val) { clearOrSet(val, StateNodeFlagValues::HasDimension); }
+ bool HasColor() const { return this->operator&(StateNodeFlagValues::HasColor); }
+ void SetHasColor(bool val) { clearOrSet(val, StateNodeFlagValues::HasColor); }
+ bool HasEndPosition() const { return this->operator&(StateNodeFlagValues::HasEndPosition); }
+ void SetHasEndPosition(bool val) { clearOrSet(val, StateNodeFlagValues::HasEndPosition); }
+ };
+
+ struct SStateNode
+ {
+ const StateNodeTypes::Enum m_Type;
+ CRegisteredString m_Id;
+ SStateNode *m_Parent;
+ SStateNode *m_NextSibling;
+ SStateNode *m_PreviousSibling;
+ SInterpreterData *m_InterpreterData;
+ SStateNodeFlags m_StateNodeFlags;
+ QT3DSVec2 m_Position;
+ QT3DSVec2 m_Dimension;
+ QT3DSVec3 m_Color;
+
+ SStateNode(StateNodeTypes::Enum inType)
+ : m_Type(inType)
+ , m_Parent(NULL)
+ , m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ , m_InterpreterData(NULL)
+ {
+ }
+
+ template <typename TDataType>
+ TDataType *CastTo()
+ {
+ if (m_Type == SStateNodeTypeMap<TDataType>::GetStateNodeType())
+ return static_cast<TDataType *>(this);
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+
+ template <typename TDataType>
+ const TDataType *CastTo() const
+ {
+ if (m_Type == SStateNodeTypeMap<TDataType>::GetStateNodeType())
+ return static_cast<const TDataType *>(this);
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ // Helper functions that take care of the drama around getting the various
+ // shared properties
+ bool IsCompound() const;
+ bool IsAtomic() const;
+ void AppendChild(SStateNode &inChild);
+ TOnEntryList *GetOnEntryList();
+ TOnExitList *GetOnExitList();
+ STransition *GetInitialTransition();
+ const char8_t *GetInitialExpression();
+ TStateNodeList *GetChildren();
+ SDataModel *GetDataModel();
+ Option<QT3DSVec2> GetPosition() const
+ {
+ if (m_StateNodeFlags.HasPosition())
+ return m_Position;
+ return Empty();
+ }
+ void SetPosition(const Option<QT3DSVec2> &pos)
+ {
+ if (pos.hasValue()) {
+ m_Position = *pos;
+ }
+ m_StateNodeFlags.SetHasPosition(pos.hasValue());
+ }
+ Option<QT3DSVec2> GetDimension() const
+ {
+ if (m_StateNodeFlags.HasDimension())
+ return m_Dimension;
+ return Empty();
+ }
+ void SetDimension(const Option<QT3DSVec2> &pos)
+ {
+ if (pos.hasValue()) {
+ m_Dimension = *pos;
+ }
+ m_StateNodeFlags.SetHasDimension(pos.hasValue());
+ }
+ Option<QT3DSVec3> GetColor() const
+ {
+ if (m_StateNodeFlags.HasColor())
+ return m_Color;
+ return Empty();
+ }
+ void SetColor(const Option<QT3DSVec3> &pos)
+ {
+ if (pos.hasValue()) {
+ m_Color = *pos;
+ }
+ m_StateNodeFlags.SetHasColor(pos.hasValue());
+ }
+ };
+
+ struct SEntryExitBase : public SStateNode
+ {
+ TOnEntryList m_OnEntry;
+ TOnExitList m_OnExit;
+ SEntryExitBase(StateNodeTypes::Enum inType)
+ : SStateNode(inType)
+ {
+ }
+ };
+
+ // State and parallel objects can have states as children. Nothing aside from
+ // SCXML can have this.
+ struct SStateParallelBase : public SEntryExitBase
+ {
+ TStateNodeList m_Children;
+ SDataModel *m_DataModel;
+ TInvokeList m_InvokeList;
+
+ SStateParallelBase(StateNodeTypes::Enum inType)
+ : SEntryExitBase(inType)
+ , m_DataModel(NULL)
+ {
+ }
+
+ void RemoveChild(SStateNode &inChild)
+ {
+ QT3DS_ASSERT(inChild.m_Parent == this);
+ m_Children.remove(inChild);
+ inChild.m_Parent = NULL;
+ }
+
+ void AppendChild(SStateNode &inChild, SStateNode *inLoc = NULL)
+ {
+ if (inChild.m_Parent != NULL)
+ static_cast<SStateParallelBase *>(inChild.m_Parent)->RemoveChild(inChild);
+ if (inLoc)
+ m_Children.insert_after(*inLoc, inChild);
+ else
+ m_Children.push_back(inChild);
+ inChild.m_Parent = this;
+ }
+
+ void PrependChild(SStateNode &inChild, SStateNode *inLoc = NULL)
+ {
+ if (inChild.m_Parent != NULL)
+ static_cast<SStateParallelBase *>(inChild.m_Parent)->RemoveChild(inChild);
+ if (inLoc)
+ m_Children.insert_before(*inLoc, inChild);
+ else
+ m_Children.push_front(inChild);
+ inChild.m_Parent = this;
+ }
+
+ bool IsAtomic() const
+ {
+ for (TStateNodeList::const_iterator iter = m_Children.begin(), end = m_Children.end();
+ iter != end; ++iter) {
+ if (iter->m_Type != StateNodeTypes::Transition)
+ return false;
+ }
+ return true;
+ }
+ bool IsCompound() const { return !IsAtomic(); }
+ };
+
+ struct SCXMLFlagValues
+ {
+ enum Enum {
+ Late = 1,
+ };
+ };
+
+ struct SSCXMLFlags : public NVFlags<SCXMLFlagValues::Enum, QT3DSU32>
+ {
+ SSCXMLFlags() {}
+
+ void SetLateBinding(bool inValue) { clearOrSet(inValue, SCXMLFlagValues::Late); }
+ bool IsLateBinding() const { return this->operator&(SCXMLFlagValues::Late); }
+ };
+
+ // Begin standard object definitions
+
+ struct SSCXML : public SStateNode
+ {
+ STransition *m_Initial;
+ CRegisteredString m_Name;
+ TStateNodeList m_Children;
+ SScript *m_Script;
+ SSCXMLFlags m_Flags;
+ SDataModel *m_DataModel;
+ QT3DSI32 m_UICVersion;
+ const char8_t *m_Filename;
+ const char8_t *m_InitialExpr;
+
+ static QT3DSI32 GetCurrentUICVersion() { return 1; }
+ SSCXML()
+ : SStateNode(StateNodeTypes::SCXML)
+ , m_Initial(NULL)
+ , m_Script(NULL)
+ , m_DataModel(NULL)
+ , m_UICVersion(GetCurrentUICVersion())
+ , m_InitialExpr(NULL)
+ {
+ }
+
+ void RemoveChild(SStateNode &inChild)
+ {
+ QT3DS_ASSERT(inChild.m_Parent == this);
+ m_Children.remove(inChild);
+ inChild.m_Parent = NULL;
+ }
+
+ void AppendChild(SStateNode &inChild, SStateNode *inLoc = NULL)
+ {
+ if (inChild.m_Parent != NULL)
+ static_cast<SStateParallelBase *>(inChild.m_Parent)->RemoveChild(inChild);
+ if (inLoc)
+ m_Children.insert_after(*inLoc, inChild);
+ else
+ m_Children.push_back(inChild);
+ inChild.m_Parent = this;
+ }
+ };
+
+ struct SState : public SStateParallelBase
+ {
+ // transition, state, parallel, and final are all handed by SStateNode
+ STransition *m_Initial;
+ const char8_t *m_InitialExpr;
+
+ SState()
+ : SStateParallelBase(StateNodeTypes::State)
+ , m_Initial(NULL)
+ , m_InitialExpr(NULL)
+ {
+ }
+ };
+
+ struct SParallel : public SStateParallelBase
+ {
+ SParallel()
+ : SStateParallelBase(StateNodeTypes::Parallel)
+ {
+ }
+ };
+
+ struct TransitionFlagValues
+ {
+ enum Enum {
+ Internal = 1,
+ };
+ };
+
+ struct STransitionFlags : public NVFlags<TransitionFlagValues::Enum, QT3DSU32>
+ {
+ STransitionFlags() {}
+
+ void SetInternal(bool inValue) { clearOrSet(inValue, TransitionFlagValues::Internal); }
+ bool IsInternal() const { return this->operator&(TransitionFlagValues::Internal); }
+ };
+
+ struct STransition : public SStateNode
+ {
+ CRegisteredString m_Event;
+ const char8_t *m_Condition;
+ NVConstDataRef<SStateNode *> m_Target;
+ STransitionFlags m_Flags;
+ TExecutableContentList m_ExecutableContent;
+ NVConstDataRef<QT3DSVec2> m_Path;
+ // If we have multiple end targets, on order to lay them out we need a branch point
+ // along with the number of control points in each target. The first index points to the
+ // branch point in the path vector, then next index tells the number of control points
+ // for the first end point, etc.
+ NVConstDataRef<QT3DSU32> m_PathIndexes;
+ QT3DSVec2 m_EndPosition;
+ // m_Source of the transition is its parent
+
+ STransition()
+ : SStateNode(StateNodeTypes::Transition)
+ , m_Condition(NULL)
+ , m_EndPosition(0, 0)
+ {
+ }
+
+ SStateNode *GetSource() { return m_Parent; }
+
+ Option<QT3DSVec2> GetEndPosition() const
+ {
+ if (m_StateNodeFlags.HasEndPosition())
+ return m_EndPosition;
+ return Empty();
+ }
+ void SetEndPosition(const Option<QT3DSVec2> &pos)
+ {
+ if (pos.hasValue()) {
+ m_EndPosition = *pos;
+ }
+ m_StateNodeFlags.SetHasEndPosition(pos.hasValue());
+ }
+ };
+
+ // TODO: DoneData
+ struct SFinal : public SEntryExitBase
+ {
+ SFinal()
+ : SEntryExitBase(StateNodeTypes::Final)
+ {
+ }
+ };
+
+ struct HistoryFlagValues
+ {
+ enum Enum {
+ Deep = 1,
+ };
+ };
+
+ struct SHistoryFlags : public NVFlags<HistoryFlagValues::Enum, QT3DSU32>
+ {
+ SHistoryFlags() {}
+
+ void SetDeep(bool inValue) { clearOrSet(inValue, HistoryFlagValues::Deep); }
+ bool IsDeep() const { return this->operator&(HistoryFlagValues::Deep); }
+ };
+
+ struct SHistory : public SStateNode
+ {
+ SHistoryFlags m_Flags;
+ qt3ds::foundation::STaggedPointer m_UserData;
+ STransition *m_Transition;
+
+ SHistory()
+ : SStateNode(StateNodeTypes::History)
+ , m_Transition(NULL)
+ {
+ }
+ };
+
+ struct SOnEntry
+ {
+ SOnEntry *m_NextSibling;
+ TExecutableContentList m_ExecutableContent;
+ qt3ds::foundation::STaggedPointer m_UserData;
+ SOnEntry()
+ : m_NextSibling(NULL)
+ {
+ }
+ };
+
+ struct SOnExit
+ {
+ SOnExit *m_NextSibling;
+ TExecutableContentList m_ExecutableContent;
+ qt3ds::foundation::STaggedPointer m_UserData;
+ SOnExit()
+ : m_NextSibling(NULL)
+ {
+ }
+ };
+
+ struct SInvoke
+ {
+ SInvoke *m_NextSibling;
+ SInvoke *m_PreviousSibling;
+ // Will have either SCXML content or dom content but not both.
+ SSCXML *m_SCXMLContent;
+ SDOMElement *m_DOMContent;
+ SInvoke()
+ : m_NextSibling(NULL)
+ , m_PreviousSibling(NULL)
+ , m_SCXMLContent(NULL)
+ , m_DOMContent(NULL)
+ {
+ }
+ };
+
+ // Events, because they created both inside and outside
+ // the state system by various parties.
+ class IEvent : public NVRefCounted
+ {
+ protected:
+ virtual ~IEvent() {}
+ public:
+ virtual CRegisteredString GetName() const = 0;
+ // Optional type string for rtti. No string means this is an opaque event
+ // that cannot be safely cast to any specific event type.
+ virtual CRegisteredString GetEventType() const { return CRegisteredString(); }
+ };
+
+ typedef NVScopedRefCounted<IEvent> TEventPtr;
+
+ struct SIdValue;
+
+ typedef nvhash_map<CRegisteredString, SIdValue> TIDStateMap;
+
+ struct SDOMElementNode
+ {
+ SDOMElementNode *m_NextNode;
+ SDOMElement *m_Element;
+ SDOMElementNode(SDOMElement *elem = NULL)
+ : m_NextNode(NULL)
+ , m_Element(elem)
+ {
+ }
+ };
+
+ struct SDOMAttributeNode
+ {
+ SDOMAttributeNode *m_NextNode;
+ SDOMAttribute *m_Attribute;
+ SDOMAttributeNode(SDOMAttribute *inAtt = NULL)
+ : m_NextNode(NULL)
+ , m_Attribute(inAtt)
+ {
+ }
+ };
+ DEFINE_INVASIVE_SINGLE_LIST(DOMElementNode);
+ DEFINE_INVASIVE_SINGLE_LIST(DOMAttributeNode);
+
+ inline bool SStateNode::IsCompound() const
+ {
+ if (m_Type == StateNodeTypes::SCXML)
+ return true;
+ if (m_Type == StateNodeTypes::State)
+ return !IsAtomic();
+ return false;
+ }
+
+ inline bool SStateNode::IsAtomic() const
+ {
+ if (m_Type == StateNodeTypes::SCXML)
+ return false;
+
+ if (m_Type == StateNodeTypes::State) {
+ const SState *theState = CastTo<SState>();
+ for (TStateNodeList::iterator iter = theState->m_Children.begin(),
+ end = theState->m_Children.end();
+ iter != end; ++iter) {
+ if (iter->m_Type != StateNodeTypes::Transition
+ && iter->m_Type != StateNodeTypes::History)
+ return false;
+ }
+ return true;
+ } else if (m_Type == StateNodeTypes::Final)
+ return true;
+ return false;
+ }
+
+ inline void SStateNode::AppendChild(SStateNode &inChild)
+ {
+ if (m_Type == StateNodeTypes::State || m_Type == StateNodeTypes::Parallel) {
+ static_cast<SStateParallelBase *>(this)->AppendChild(inChild);
+ } else if (m_Type == StateNodeTypes::SCXML) {
+ static_cast<SSCXML *>(this)->AppendChild(inChild);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ inline TOnEntryList *SStateNode::GetOnEntryList()
+ {
+ if (m_Type == StateNodeTypes::State || m_Type == StateNodeTypes::Parallel)
+ return &static_cast<SStateParallelBase *>(this)->m_OnEntry;
+ if (m_Type == StateNodeTypes::Final)
+ return &CastTo<SFinal>()->m_OnEntry;
+ return NULL;
+ }
+
+ inline TOnExitList *SStateNode::GetOnExitList()
+ {
+ if (m_Type == StateNodeTypes::State || m_Type == StateNodeTypes::Parallel)
+ return &static_cast<SStateParallelBase *>(this)->m_OnExit;
+ if (m_Type == StateNodeTypes::Final)
+ return &CastTo<SFinal>()->m_OnExit;
+ return NULL;
+ }
+
+ inline STransition *SStateNode::GetInitialTransition()
+ {
+ if (m_Type == StateNodeTypes::State)
+ return static_cast<SState *>(this)->m_Initial;
+ if (m_Type == StateNodeTypes::SCXML)
+ return static_cast<SSCXML *>(this)->m_Initial;
+ return NULL;
+ }
+
+ inline const char8_t *SStateNode::GetInitialExpression()
+ {
+ if (m_Type == StateNodeTypes::State)
+ return nonNull(static_cast<SState *>(this)->m_InitialExpr);
+ if (m_Type == StateNodeTypes::SCXML)
+ return nonNull(static_cast<SSCXML *>(this)->m_InitialExpr);
+ return "";
+ }
+
+ inline TStateNodeList *SStateNode::GetChildren()
+ {
+ if (m_Type == StateNodeTypes::State || m_Type == StateNodeTypes::Parallel)
+ return &static_cast<SStateParallelBase *>(this)->m_Children;
+ if (m_Type == StateNodeTypes::SCXML)
+ return &static_cast<SSCXML *>(this)->m_Children;
+ return NULL;
+ }
+
+ inline SDataModel *SStateNode::GetDataModel()
+ {
+ if (m_Type == StateNodeTypes::State || m_Type == StateNodeTypes::Parallel)
+ return static_cast<SStateParallelBase *>(this)->m_DataModel;
+ if (m_Type == StateNodeTypes::SCXML)
+ return static_cast<SSCXML *>(this)->m_DataModel;
+ return NULL;
+ }
+
+ IMPLEMENT_INVASIVE_LIST(Invoke, m_PreviousSibling, m_NextSibling);
+ IMPLEMENT_INVASIVE_LIST(StateNode, m_PreviousSibling, m_NextSibling);
+ IMPLEMENT_INVASIVE_SINGLE_LIST(OnEntry, m_NextSibling);
+ IMPLEMENT_INVASIVE_SINGLE_LIST(OnExit, m_NextSibling);
+ IMPLEMENT_INVASIVE_SINGLE_LIST(DOMElementNode, m_NextNode);
+ IMPLEMENT_INVASIVE_SINGLE_LIST(DOMAttributeNode, m_NextNode);
+
+ DEFINE_INVASIVE_SINGLE_LIST(Data);
+
+ struct SDataModel
+ {
+ CRegisteredString m_Id;
+ const char8_t *m_Source;
+ const char8_t *m_Expression;
+ TDataList m_Data;
+
+ SDataModel()
+ : m_Source(NULL)
+ , m_Expression(NULL)
+ {
+ }
+ };
+
+ struct SData
+ {
+ CRegisteredString m_Id;
+ const char8_t *m_Source;
+ const char8_t *m_Expression;
+ SData *m_NextSibling;
+ SData()
+ : m_Source(NULL)
+ , m_Expression(NULL)
+ , m_NextSibling(NULL)
+ {
+ }
+ };
+
+ IMPLEMENT_INVASIVE_SINGLE_LIST(Data, m_NextSibling);
+}
+}
+
+#endif
diff --git a/src/Runtime/Source/UICState/Include/UICStateVisualBindingContext.h b/src/Runtime/Source/UICState/Include/UICStateVisualBindingContext.h
new file mode 100644
index 00000000..016719bd
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateVisualBindingContext.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_STATE_VISUAL_BINDING_CONTEXT_H
+#define UIC_STATE_VISUAL_BINDING_CONTEXT_H
+#include "UICState.h"
+#include "foundation/Qt3DSRefCounted.h"
+#include "foundation/StringTable.h"
+#include "UICStateVisualBindingContextCommands.h"
+
+namespace qt3ds {
+namespace foundation {
+ class IDOMReader;
+ class CStrTableOrDataRef;
+}
+}
+
+namespace uic {
+namespace state {
+
+ struct SVisualStateCommand;
+ struct SSetAttribute;
+
+ // Entity responsible for implementing the various visual state commands.
+ class IVisualStateCommandHandler : public NVRefCounted
+ {
+ protected:
+ virtual ~IVisualStateCommandHandler() {}
+ public:
+ virtual void Handle(const SVisualStateCommand &inCommand,
+ IScriptContext &inScriptContext) = 0;
+ };
+
+ class IVisualStateInterpreterFactory : public NVRefCounted
+ {
+ protected:
+ virtual ~IVisualStateInterpreterFactory() {}
+ public:
+ // Create a new state machine
+ // inPath - relative path
+ // ID - state machine id
+ // datamodel - lua function to call to initialize datamodel
+ virtual IStateInterpreter *OnNewStateMachine(const char8_t *inPath, const char8_t *inId,
+ const char8_t *inDatamodel) = 0;
+ };
+
+ // It is important that the visual state context list the elements it expects to find in a uip
+ // file
+ // so that during parse of the uip file, we can generate an error if some element isn't found.
+ struct SElementReference
+ {
+ CRegisteredString m_ElementPath;
+ CRegisteredString m_Attribute;
+ SElementReference(CRegisteredString elemPath = CRegisteredString(),
+ CRegisteredString att = CRegisteredString())
+ : m_ElementPath(elemPath)
+ , m_Attribute(att)
+ {
+ }
+ };
+
+ class IVisualStateContext : public NVRefCounted
+ {
+ protected:
+ virtual ~IVisualStateContext() {}
+ public:
+ // All machines are loaded execute is called on the first update call.
+ // made after LoadVisualStateMapping
+ virtual void LoadStateMachine(const char8_t *id, const char8_t *inRelativePath,
+ const char8_t *inDatamodelFunction) = 0;
+ virtual void LoadVisualStateMapping(IDOMReader &inReader) = 0;
+ // We have to pre-parse the xml so we can reference everything in the various presentations
+ // We run this pass, then during uip file parsing we output errors if things don't match up.
+ virtual NVConstDataRef<SElementReference> PreParseDocument(IDOMReader &inReader) = 0;
+ virtual void SetCommandHandler(IVisualStateCommandHandler *inHandler) = 0;
+ virtual void SetInterpreterFactory(IVisualStateInterpreterFactory *inHandler) = 0;
+
+ // Initialize the state machines. Machines are initialized in order of LoadStateMachine
+ // calls.
+ virtual void Initialize() = 0;
+ virtual void Start() = 0;
+
+ // Initialize the state machines. Machines are updated in order of LoadStateMachine calls.
+ virtual void Update() = 0;
+
+ // Save out to a format that allows very rapid loading.
+ virtual void BinarySave(IOutStream &stream) = 0;
+ virtual void BinaryLoad(IInStream &stream, NVDataRef<QT3DSU8> inStringTableData) = 0;
+
+ static IVisualStateContext &Create(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable);
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateVisualBindingContextCommands.h b/src/Runtime/Source/UICState/Include/UICStateVisualBindingContextCommands.h
new file mode 100644
index 00000000..6e6b9c70
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateVisualBindingContextCommands.h
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_STATE_VISUAL_BINDING_CONTEXT_COMMANDS_H
+#define UIC_STATE_VISUAL_BINDING_CONTEXT_COMMANDS_H
+#include "UICState.h"
+#include "foundation/StringTable.h"
+
+namespace uic {
+namespace state {
+
+ struct VisualStateCommandTypes
+ {
+ enum Enum {
+ NoVisualStateCommand = 0,
+ GotoSlide,
+ CallFunction,
+ SetAttribute,
+ GotoSlideRelative,
+ FireEvent,
+ PresentationAttribute,
+ PlaySound,
+ };
+ };
+
+ struct SlidePlaybackModes
+ {
+ enum Enum {
+ StopAtEnd = 0,
+ Looping,
+ PingPong,
+ Ping,
+ PlaythroughTo,
+ };
+ };
+
+ struct SGotoSlideData
+ {
+ Option<SlidePlaybackModes::Enum> m_Mode;
+ Option<CRegisteredString> m_PlaythroughTo;
+ Option<QT3DSU32> m_StartTime;
+ QT3DSF32 m_Rate;
+ bool m_Reverse;
+ Option<bool> m_Paused;
+ SGotoSlideData()
+ : m_Rate(1.0f)
+ , m_Reverse(false)
+ {
+ }
+ };
+
+ // All the element references in this file need to be absolute, meaning they
+ // must begin with a presentationid:. The is because the state machine exists at the
+ // application level where all presentations are pretty much equal and must be referenced
+ // by id.
+
+ // Go to a particular slide.
+
+ /*
+ a. If the slide attribute references a slide name not present on the time context an error must
+ be logged each time the executable would have been run, and the executable ignored.
+ b. If the time context is already on the slide referenced, no change is made to the time
+ context.
+ The slide does not restart. */
+ struct SGotoSlide
+ {
+ CRegisteredString m_Component;
+ CRegisteredString m_Slide;
+ SGotoSlideData m_GotoSlideData;
+ SGotoSlide(CRegisteredString cmd = CRegisteredString(),
+ CRegisteredString slide = CRegisteredString())
+ : m_Component(cmd)
+ , m_Slide(slide)
+ {
+ }
+ bool operator==(const SGotoSlide &inOther) const
+ {
+ return m_Component == inOther.m_Component && m_Slide == inOther.m_Slide;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_Component);
+ inRemapper.Remap(m_Slide);
+ }
+ };
+
+ /*
+ 1. A <call.../> executable must have a element="..." attribute that references a behavior
+ element in one of the presentation assets for the application.
+ a. If the element attribute is missing, or references an element that cannot be found,
+ an error must be logged each time the executable would have been run, and the executable
+ ignored.
+ b. If the element attribute references an element that is not a behavior then an error
+ must be logged each time the executable would have been run, and the executable ignored.
+ 2. A <call.../> executable must have a handler="..." attribute that references a function value
+ in the table associated with the behavior element.
+ a. If the handler attribute is missing, or references a value that is not a function
+ value, an error must be logged each time the executable would have been run, and the executable
+ ignored.
+ 3. A <call.../> executable may have an args="..." attribute that specifies a Lua expression to
+ evaluate.
+ a. If the result of evaluating this expression is a single value, it is passed as the
+ first argument to the behavior's function.
+ b. If the result of evaluating this expression is a table, it is treated as a list that
+ is unpack'd, the numeric properties sent as arguments in order.
+ c. If the result of evaluating this expression is an error, an error message must be
+ logged and the executable ignored.
+ The function is not invoked with no parameters.
+ */
+ struct SCallFunction
+ {
+ CRegisteredString m_Behavior;
+ CRegisteredString m_Handler;
+ CRegisteredString m_Arguments;
+ SCallFunction(CRegisteredString behavior = CRegisteredString(),
+ CRegisteredString hdler = CRegisteredString(),
+ CRegisteredString args = CRegisteredString())
+ : m_Behavior(behavior)
+ , m_Handler(hdler)
+ , m_Arguments(args)
+ {
+ }
+ bool operator==(const SCallFunction &inOther) const
+ {
+ return m_Behavior == inOther.m_Behavior && m_Handler == inOther.m_Handler
+ && m_Arguments == inOther.m_Arguments;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_Behavior);
+ inRemapper.Remap(m_Handler);
+ inRemapper.Remap(m_Arguments);
+ }
+ };
+
+ /*
+ 1. A <set-attribute.../> executable must have an element="..." attribute that references an
+ element in one of the presentation assets for the application.
+ a. If the element attribute is missing, or references an element that cannot be found,
+ an error must be logged each time the executable would have been run, and the executable
+ ignored.
+ 2. A <set-attribute.../> executable must have an attribute="..." attribute that references an
+ attribute on the referenced element.
+ a. If the attribute attribute is missing, or references an attribute not present on the
+ element, an error must be logged each time the executable would have been run, and the
+ executable ignored.
+ 3. A <set-attribute.../> executable must have an value="..." attribute that describes the value
+ to set.
+ a. The contents of this attribute are evaluated as a Lua expression and the result used
+ to set the attribute.
+ i. If the result of evaluating this expression does not match the type of the
+ attribute on the element then an error must be logged and the executable ignored.
+ 4. If a single visual state has both <goto-slide/> and <set-attribute/> executables, and the
+ slide change affects the same attribute as the set-attribute executable, then the set-attribute
+ executable must take effect (be applied after the slide change occurs).
+ In the future we may wish to have the order of this interaction controllable by the
+ ordering of the executables.
+ */
+ struct SSetAttribute
+ {
+ CRegisteredString m_Element;
+ CRegisteredString m_Attribute;
+ CRegisteredString m_Value;
+ SSetAttribute(CRegisteredString elem = CRegisteredString(),
+ CRegisteredString att = CRegisteredString(),
+ CRegisteredString val = CRegisteredString())
+ : m_Element(elem)
+ , m_Attribute(att)
+ , m_Value(val)
+ {
+ }
+ bool operator==(const SSetAttribute &inOther) const
+ {
+ return m_Element == inOther.m_Element && m_Attribute == inOther.m_Attribute
+ && m_Value == inOther.m_Value;
+ }
+
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_Element);
+ inRemapper.Remap(m_Attribute);
+ inRemapper.Remap(m_Value);
+ }
+ };
+
+ /*
+ 4. A rel="..." attribute must have either the value next or prev.
+ a. If the rel attribute has a different value an error must be logged each time the
+ executable would have been run, and the executable ignored.
+ b. A value of next causes the time context to go to the next slide.
+ i. If the time context is at the last slide, and there is no wrap attribute, or
+ the wrap attribute does not have a value of true, then no change occurs to the time context.
+ The slide does not restart.
+ ii. If the time context is at the last slide and there exists a wrap attribute
+ with a value of true then the time context is taken to the first slide.
+ c. A value of prev causes the time context to go to the previous slide.
+ i. If the time context is at the first slide, and there is no wrap attribute, or
+ the wrap attribute does not have a value of true, then no change occurs to the time context.
+ The slide does not restart.
+ ii. If the time context is at the last first and there exists a wrap attribute
+ with a value of true then the time context is taken to the last slide.
+ */
+ struct SGotoSlideRelative
+ {
+ CRegisteredString m_Component;
+ enum Enum {
+ Next = 0,
+ Previous,
+ Error,
+ };
+ Enum m_Direction;
+ bool m_Wrap;
+ SGotoSlideData m_GotoSlideData;
+ SGotoSlideRelative(CRegisteredString comp = CRegisteredString(), Enum dir = Next,
+ bool wrap = false)
+ : m_Component(comp)
+ , m_Direction(dir)
+ , m_Wrap(wrap)
+ {
+ }
+ bool operator==(const SGotoSlideRelative &inOther) const
+ {
+ return m_Component == inOther.m_Component && m_Direction == inOther.m_Direction
+ && m_Wrap == inOther.m_Wrap;
+ }
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_Component);
+ }
+ };
+
+ /*
+ 1. A <fire-event.../> executable must have an element="..." attribute that references an element
+ in one of the presentation assets for the application.
+ a. If the element attribute is missing, or references an element that cannot be found,
+ an error must be logged each time the executable would have been run, and the executable
+ ignored.
+ 2. A <fire-event.../> executable must have an event="..." attribute that describes the event
+ name to fire.
+ a. If the event attribute is missing an error must be logged each time the executable
+ would have been run, and the executable ignored.
+ */
+ struct SFireEvent
+ {
+ CRegisteredString m_Element;
+ CRegisteredString m_Event;
+ SFireEvent(CRegisteredString elem, CRegisteredString evt)
+ : m_Element(elem)
+ , m_Event(evt)
+ {
+ }
+ SFireEvent() {}
+ bool operator==(const SFireEvent &inOther) const
+ {
+ return m_Element == inOther.m_Element && m_Event == inOther.m_Event;
+ }
+
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_Element);
+ inRemapper.Remap(m_Event);
+ }
+ };
+
+ struct SPresentationAttribute
+ {
+ CRegisteredString m_Presentation;
+ CRegisteredString m_Attribute;
+ CRegisteredString m_Value;
+ SPresentationAttribute(CRegisteredString pres, CRegisteredString att, CRegisteredString val)
+ : m_Presentation(pres)
+ , m_Attribute(att)
+ , m_Value(val)
+ {
+ }
+ SPresentationAttribute() {}
+ bool operator==(const SPresentationAttribute &inOther) const
+ {
+ return m_Presentation == inOther.m_Presentation && m_Attribute == inOther.m_Attribute
+ && m_Value == inOther.m_Value;
+ }
+
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_Presentation);
+ inRemapper.Remap(m_Attribute);
+ inRemapper.Remap(m_Value);
+ }
+ };
+
+ struct SPlaySound
+ {
+ CRegisteredString m_SoundFilePath;
+ SPlaySound(CRegisteredString inSoundFilePath)
+ : m_SoundFilePath(inSoundFilePath)
+ {
+ }
+ SPlaySound() {}
+ bool operator==(const SPlaySound &inOther) const
+ {
+ return m_SoundFilePath == inOther.m_SoundFilePath;
+ }
+
+ template <typename TRemapper>
+ void Remap(TRemapper &inRemapper)
+ {
+ inRemapper.Remap(m_SoundFilePath);
+ }
+ };
+
+ // defined in UICStateVisualBindingContextValues.h
+ struct SVisualStateCommand;
+}
+}
+#endif
diff --git a/src/Runtime/Source/UICState/Include/UICStateVisualBindingContextValues.h b/src/Runtime/Source/UICState/Include/UICStateVisualBindingContextValues.h
new file mode 100644
index 00000000..8b7c102d
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateVisualBindingContextValues.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#pragma once
+#ifndef UIC_STATE_VISUAL_BINDING_CONTEXT_VALUES_H
+#define UIC_STATE_VISUAL_BINDING_CONTEXT_VALUES_H
+#include "UICStateVisualBindingContext.h"
+#include "foundation/Qt3DSDiscriminatedUnion.h"
+#include "UICStateVisualBindingContextCommands.h"
+
+namespace uic {
+namespace state {
+
+ template <typename TDataType>
+ struct SVisualStateCommandTypeMap
+ {
+ };
+
+ template <>
+ struct SVisualStateCommandTypeMap<SGotoSlide>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::GotoSlide;
+ }
+ };
+ template <>
+ struct SVisualStateCommandTypeMap<SCallFunction>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::CallFunction;
+ }
+ };
+ template <>
+ struct SVisualStateCommandTypeMap<SSetAttribute>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::SetAttribute;
+ }
+ };
+ template <>
+ struct SVisualStateCommandTypeMap<SGotoSlideRelative>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::GotoSlideRelative;
+ }
+ };
+ template <>
+ struct SVisualStateCommandTypeMap<SFireEvent>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::FireEvent;
+ }
+ };
+ template <>
+ struct SVisualStateCommandTypeMap<SPresentationAttribute>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::PresentationAttribute;
+ }
+ };
+ template <>
+ struct SVisualStateCommandTypeMap<SPlaySound>
+ {
+ static VisualStateCommandTypes::Enum GetType()
+ {
+ return VisualStateCommandTypes::PlaySound;
+ }
+ };
+
+ struct SVisualStateCommandUnionTraits
+ {
+ typedef VisualStateCommandTypes::Enum TIdType;
+ enum {
+ TBufferSize = sizeof(SGotoSlideRelative),
+ };
+
+ static TIdType getNoDataId() { return VisualStateCommandTypes::NoVisualStateCommand; }
+
+ template <typename TDataType>
+ static TIdType getType()
+ {
+ return SVisualStateCommandTypeMap<TDataType>().GetType();
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case VisualStateCommandTypes::GotoSlide:
+ return inVisitor(*NVUnionCast<SGotoSlide *>(inData));
+ case VisualStateCommandTypes::CallFunction:
+ return inVisitor(*NVUnionCast<SCallFunction *>(inData));
+ case VisualStateCommandTypes::SetAttribute:
+ return inVisitor(*NVUnionCast<SSetAttribute *>(inData));
+ case VisualStateCommandTypes::GotoSlideRelative:
+ return inVisitor(*NVUnionCast<SGotoSlideRelative *>(inData));
+ case VisualStateCommandTypes::FireEvent:
+ return inVisitor(*NVUnionCast<SFireEvent *>(inData));
+ case VisualStateCommandTypes::PresentationAttribute:
+ return inVisitor(*NVUnionCast<SPresentationAttribute *>(inData));
+ case VisualStateCommandTypes::PlaySound:
+ return inVisitor(*NVUnionCast<SPlaySound *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case VisualStateCommandTypes::NoVisualStateCommand:
+ return inVisitor();
+ }
+ }
+
+ template <typename TRetType, typename TVisitorType>
+ static TRetType visit(const char *inData, TIdType inType, TVisitorType inVisitor)
+ {
+ switch (inType) {
+ case VisualStateCommandTypes::GotoSlide:
+ return inVisitor(*NVUnionCast<const SGotoSlide *>(inData));
+ case VisualStateCommandTypes::CallFunction:
+ return inVisitor(*NVUnionCast<const SCallFunction *>(inData));
+ case VisualStateCommandTypes::SetAttribute:
+ return inVisitor(*NVUnionCast<const SSetAttribute *>(inData));
+ case VisualStateCommandTypes::GotoSlideRelative:
+ return inVisitor(*NVUnionCast<const SGotoSlideRelative *>(inData));
+ case VisualStateCommandTypes::FireEvent:
+ return inVisitor(*NVUnionCast<const SFireEvent *>(inData));
+ case VisualStateCommandTypes::PresentationAttribute:
+ return inVisitor(*NVUnionCast<const SPresentationAttribute *>(inData));
+ case VisualStateCommandTypes::PlaySound:
+ return inVisitor(*NVUnionCast<const SPlaySound *>(inData));
+ default:
+ QT3DS_ASSERT(false);
+ case VisualStateCommandTypes::NoVisualStateCommand:
+ return inVisitor();
+ }
+ }
+ };
+
+ typedef qt3ds::foundation::
+ DiscriminatedUnion<qt3ds::foundation::
+ DiscriminatedUnionGenericBase<SVisualStateCommandUnionTraits,
+ SVisualStateCommandUnionTraits::
+ TBufferSize>,
+ SVisualStateCommandUnionTraits::TBufferSize>
+ TVisualStateCommandUnionType;
+
+ struct SVisualStateCommand : public TVisualStateCommandUnionType
+ {
+ SVisualStateCommand() {}
+
+ SVisualStateCommand(const SVisualStateCommand &inOther)
+ : TVisualStateCommandUnionType(
+ static_cast<const TVisualStateCommandUnionType &>(inOther))
+ {
+ }
+
+ template <typename TDataType>
+ SVisualStateCommand(const TDataType &inDt)
+ : TVisualStateCommandUnionType(inDt)
+ {
+ }
+
+ SVisualStateCommand &operator=(const SVisualStateCommand &inOther)
+ {
+ TVisualStateCommandUnionType::operator=(inOther);
+ return *this;
+ }
+
+ bool operator==(const SVisualStateCommand &inOther) const
+ {
+ return TVisualStateCommandUnionType::operator==(inOther);
+ }
+ bool operator!=(const SVisualStateCommand &inOther) const
+ {
+ return TVisualStateCommandUnionType::operator!=(inOther);
+ }
+
+ bool empty() const { return getType() == VisualStateCommandTypes::NoVisualStateCommand; }
+ };
+}
+}
+#ifndef _INTEGRITYPLATFORM
+namespace qt3ds {
+namespace foundation {
+
+ template <>
+ struct DestructTraits<uic::state::SGotoSlide>
+ {
+ void destruct(uic::state::SGotoSlide &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SCallFunction>
+ {
+ void destruct(uic::state::SCallFunction &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SSetAttribute>
+ {
+ void destruct(uic::state::SSetAttribute &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SGotoSlideRelative>
+ {
+ void destruct(uic::state::SGotoSlideRelative &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SFireEvent>
+ {
+ void destruct(uic::state::SFireEvent &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SPresentationAttribute>
+ {
+ void destruct(uic::state::SPresentationAttribute &) {}
+ };
+ template <>
+ struct DestructTraits<uic::state::SPlaySound>
+ {
+ void destruct(uic::state::SPlaySound &) {}
+ };
+}
+}
+#endif
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Include/UICStateXMLIO.h b/src/Runtime/Source/UICState/Include/UICStateXMLIO.h
new file mode 100644
index 00000000..efa3296f
--- /dev/null
+++ b/src/Runtime/Source/UICState/Include/UICStateXMLIO.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef UIC_STATE_XML_IO_H
+#define UIC_STATE_XML_IO_H
+#pragma once
+#include "UICState.h"
+#include "foundation/Qt3DSDataRef.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/StringTable.h"
+#include "foundation/XML.h"
+#include "EASTL/map.h"
+#include "EASTL/string.h"
+
+namespace qt3ds {
+namespace foundation {
+ class IDOMReader;
+ class IDOMWriter;
+}
+}
+
+namespace uic {
+namespace state {
+
+ struct SExecutableContent;
+ class CXMLIO
+ {
+ public:
+ typedef eastl::map<eastl::string, eastl::string> TIdRemapMap;
+
+ static void GenerateUniqueId(SStateNode &inNode, const char8_t *inStem,
+ IStateContext &ioContext, IStringTable &ioStringTable);
+ static void GenerateUniqueId(SSend &inNode, const char8_t *inStem, IStateContext &ioContext,
+ IStringTable &ioStringTable);
+ // Load an SCXML file and return the root states
+ // All states, transitions, and memory used in the graph is allocated using the graph
+ // allocator.
+ // This makes freeing the memory much easier because you can just free it by releasing the
+ // graph
+ // allocator and you don't have to go object by object.
+ // Filename is just used as another tag or name on the scxml object.
+ static bool LoadSCXMLFile(NVAllocatorCallback &inGraphAllocator, NVFoundationBase &inFnd,
+ IDOMReader &inReader, IStringTable &inStringTable,
+ const char8_t *inFilename, IStateContext &outContext,
+ editor::IEditor *inEditor = NULL);
+
+ // Loading fragments remaps their ids to avoid conflics. Returns the top nodes from the
+ // scxml graph.
+ static eastl::pair<eastl::vector<SStateNode *>, TIdRemapMap>
+ LoadSCXMLFragment(NVAllocatorCallback &inGraphAllocator, NVFoundationBase &inFnd,
+ IDOMReader &inReader, IStringTable &inStringTable,
+ IStateContext &ioContext, editor::IEditor &inEditor);
+
+ // We write all the way to file instead of a DOM writer because we have to add xml
+ // namespaces and those can only
+ // be added during the actual serialization process.
+ static void SaveSCXMLFile(IStateContext &inContext, NVFoundationBase &inFnd,
+ IStringTable &inStringTable, IOutStream &outStream,
+ editor::IEditor *inEditor = NULL);
+
+ static void FindRoots(NVConstDataRef<SStateNode *> inObjects,
+ eastl::vector<SStateNode *> &outRoots);
+
+ // Returns the roots of the copied list
+ static eastl::vector<SStateNode *>
+ SaveSCXMLFragment(IStateContext &inContext, NVFoundationBase &inFnd,
+ IStringTable &inStringTable, IDOMWriter &ioWriter,
+ NVDataRef<SStateNode *> inObjects, editor::IEditor &inEditor,
+ const QT3DSVec2 &inMousePos, eastl::vector<SNamespacePair> &outNamespaces);
+
+ static void ToEditableXml(IStateContext &inContext, NVFoundationBase &inFnd,
+ IStringTable &inStringTable, IDOMWriter &ioWriter,
+ SExecutableContent &inContent, editor::IEditor &inEditor);
+
+ static SExecutableContent *
+ FromEditableXML(IDOMReader &inReader, NVFoundationBase &inFnd, IStateContext &inContext,
+ IStringTable &inStringTable, NVAllocatorCallback &inGraphAllocator,
+ editor::IEditor &inEditor, SStateNode *inStateNodeParent,
+ SExecutableContent *inExecContentParent);
+
+ static eastl::vector<eastl::string> GetSupportedExecutableContentNames();
+ };
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/UICState/Source/UICStateContext.cpp b/src/Runtime/Source/UICState/Source/UICStateContext.cpp
new file mode 100644
index 00000000..256a98a3
--- /dev/null
+++ b/src/Runtime/Source/UICState/Source/UICStateContext.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateContext.h"
+#include "UICStateXMLIO.h"
+#include "foundation/XML.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+
+using namespace uic::state;
+
+namespace {
+
+struct SStateContext : public IStateContext
+{
+ NVFoundationBase &m_Foundation;
+ TIDStateMap m_IDStateMap;
+ TSendList m_SendList;
+ SSCXML *m_Root;
+
+ // the factory needs to be here in order that we can easily just assign variables
+ // left and right and make things work.
+ NVScopedRefCounted<IDOMFactory> m_DOMFactory;
+ TPtrExtensionMap m_ExtensionInfo;
+ SNamespacePairNode *m_NamespacePairs;
+ QT3DSI32 mRefCount;
+
+ SStateContext(NVFoundationBase &alloc)
+ : m_Foundation(alloc)
+ , m_IDStateMap(alloc.getAllocator(), "SStateContext::m_IDStateMap")
+ , m_SendList(alloc.getAllocator(), "SStateContext::m_SendList")
+ , m_Root(NULL)
+ , m_DOMFactory(NULL)
+ , m_ExtensionInfo(alloc.getAllocator(), "SStateContext::m_ExtensionInfo")
+ , m_NamespacePairs(NULL)
+ , mRefCount(0)
+ {
+ }
+ virtual ~SStateContext() {}
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+ void SetDOMFactory(IDOMFactory *inFactory) override;
+
+ void SetRoot(SSCXML &inRoot) override
+ {
+ QT3DS_ASSERT(m_Root == NULL);
+ if (!m_Root)
+ m_Root = &inRoot;
+ }
+ SSCXML *GetRoot() override { return m_Root; }
+ void AddSendToList(SSend &inSend) override { m_SendList.push_back(&inSend); }
+ NVConstDataRef<SSend *> GetSendList() override
+ {
+ return toConstDataRef(m_SendList.data(), (QT3DSU32)m_SendList.size());
+ }
+ IDOMFactory *GetDOMFactory() override { return m_DOMFactory; }
+ NVConstDataRef<NVScopedRefCounted<IStateContext>> GetSubContexts() override
+ {
+ return NVConstDataRef<NVScopedRefCounted<IStateContext>>();
+ }
+
+ // UICStateInterpreter.cpp;
+ bool InsertId(const CRegisteredString &inId, const SIdValue &inValue) override;
+ void EraseId(const CRegisteredString &inId) override;
+ bool ContainsId(const CRegisteredString &inStr) override;
+ SStateNode *FindStateNode(const CRegisteredString &inStr) override;
+ SSend *FindSend(const CRegisteredString &inStr) override;
+
+ SItemExtensionInfo *GetExtensionInfo(void *inItem) override;
+ SItemExtensionInfo &GetOrCreateExtensionInfo(void *inItem) override;
+
+ void SetFirstNSNode(SNamespacePairNode &inNode) override { m_NamespacePairs = &inNode; }
+ SNamespacePairNode *GetFirstNSNode() override { return m_NamespacePairs; }
+
+ void Save(IOutStream &inOutStream, editor::IEditor *inEditor) override;
+};
+
+void SStateContext::SetDOMFactory(IDOMFactory *inFactory)
+{
+ m_DOMFactory = inFactory;
+}
+
+bool SStateContext::InsertId(const CRegisteredString &inId, const SIdValue &inValue)
+{
+ return m_IDStateMap.insert(eastl::make_pair(inId, inValue)).second;
+}
+
+void SStateContext::EraseId(const CRegisteredString &inId)
+{
+ m_IDStateMap.erase(inId);
+}
+
+bool SStateContext::ContainsId(const CRegisteredString &inStr)
+{
+ return m_IDStateMap.find(inStr) != m_IDStateMap.end();
+}
+
+SStateNode *SStateContext::FindStateNode(const CRegisteredString &inStr)
+{
+ TIDStateMap::iterator iter = m_IDStateMap.find(inStr);
+
+ if (iter != m_IDStateMap.end()) {
+ IdValueTypes::Enum typeEnum = iter->second.getType();
+ if (typeEnum == IdValueTypes::StateNode)
+ return iter->second.getData<SStateNode *>();
+ }
+ return NULL;
+}
+
+SSend *SStateContext::FindSend(const CRegisteredString &inStr)
+{
+ TIDStateMap::iterator iter = m_IDStateMap.find(inStr);
+ if (iter != m_IDStateMap.end() && iter->second.getType() == IdValueTypes::Send)
+ return iter->second.getData<SSend *>();
+ return NULL;
+}
+
+SItemExtensionInfo *SStateContext::GetExtensionInfo(void *inItem)
+{
+ TPtrExtensionMap::iterator iter = m_ExtensionInfo.find(inItem);
+ if (iter != m_ExtensionInfo.end())
+ return &iter->second;
+ return NULL;
+}
+
+SItemExtensionInfo &SStateContext::GetOrCreateExtensionInfo(void *inItem)
+{
+ return m_ExtensionInfo.insert(eastl::make_pair(inItem, SItemExtensionInfo(inItem)))
+ .first->second;
+}
+
+void SStateContext::Save(IOutStream &inOutStream, editor::IEditor *inEditor)
+{
+ CXMLIO::SaveSCXMLFile(*this, m_Foundation, *m_DOMFactory->GetStringTable(), inOutStream,
+ inEditor);
+}
+}
+
+IStateContext *IStateContext::Load(NVAllocatorCallback &inGraphAllocator,
+ NVFoundationBase &inFoundation, IInStream &inStream,
+ const char8_t *inFilename, IStringTable *inStrTable,
+ editor::IEditor *inEditor)
+{
+
+ NVScopedRefCounted<IStringTable> theStringTable = inStrTable;
+ if (!theStringTable)
+ theStringTable = IStringTable::CreateStringTable(inFoundation.getAllocator());
+ NVScopedRefCounted<IDOMFactory> theFactory =
+ IDOMFactory::CreateDOMFactory(inFoundation.getAllocator(), theStringTable);
+ eastl::pair<SNamespacePairNode *, SDOMElement *> readResult =
+ CDOMSerializer::Read(*theFactory, inStream);
+ SDOMElement *elem = readResult.second;
+ if (elem == NULL)
+ return NULL;
+
+ NVScopedRefCounted<IDOMReader> theReader = IDOMReader::CreateDOMReader(
+ inFoundation.getAllocator(), *elem, theStringTable, *theFactory);
+ IStateContext *retval = QT3DS_NEW(inFoundation.getAllocator(), SStateContext)(inFoundation);
+ retval->SetDOMFactory(theFactory.mPtr);
+ CXMLIO::LoadSCXMLFile(inGraphAllocator, inFoundation, *theReader, *theStringTable, inFilename,
+ *retval, inEditor);
+ if (readResult.first)
+ retval->SetFirstNSNode(*readResult.first);
+ return retval;
+}
+
+IStateContext *IStateContext::Create(NVFoundationBase &inFoundation)
+{
+ NVScopedRefCounted<IStringTable> theStringTable =
+ IStringTable::CreateStringTable(inFoundation.getAllocator());
+ NVScopedRefCounted<IDOMFactory> theFactory =
+ IDOMFactory::CreateDOMFactory(inFoundation.getAllocator(), theStringTable);
+
+ SStateContext *retval = QT3DS_NEW(inFoundation.getAllocator(), SStateContext)(inFoundation);
+ retval->SetDOMFactory(theFactory);
+ return retval;
+}
diff --git a/src/Runtime/Source/UICState/Source/UICStateExecutionContext.cpp b/src/Runtime/Source/UICState/Source/UICStateExecutionContext.cpp
new file mode 100644
index 00000000..689fc92b
--- /dev/null
+++ b/src/Runtime/Source/UICState/Source/UICStateExecutionContext.cpp
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateExecutionContext.h"
+#include "UICStateExecutionTypes.h"
+#include "UICStateInterpreter.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/StringConversionImpl.h"
+#include "UICStateScriptContext.h"
+#include "foundation/Utils.h"
+#include "EASTL/string.h"
+
+using namespace uic::state;
+
+namespace {
+struct SExecContext : public IExecutionContext
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ // Referencing this here would create circular references
+ IStateInterpreter *m_Interpreter;
+ IStateLogger *m_DebugLogger;
+ NVScopedRefCounted<IStateLogger> m_Logger;
+ NVScopedRefCounted<IScriptContext> m_ScriptContext;
+ bool m_Error;
+ QT3DSI32 mRefCount;
+ eastl::string m_DelayStr;
+
+ SExecContext(NVFoundationBase &inFnd, IStringTable &inStrTable, IStateLogger &inLogger,
+ IScriptContext &inContext)
+ : m_Foundation(inFnd)
+ , m_StringTable(inStrTable)
+ , m_Interpreter(NULL)
+ , m_DebugLogger(NULL)
+ , m_Logger(inLogger)
+ , m_ScriptContext(inContext)
+ , m_Error(false)
+ , mRefCount(0)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void SetInterpreter(IStateInterpreter &inInterpreter) override
+ {
+ m_Interpreter = &inInterpreter;
+ }
+
+ void SetMachineDebugLogger(IStateLogger &inDebugLogger) override
+ {
+ m_DebugLogger = &inDebugLogger;
+ }
+
+ void SignalError()
+ {
+ const char8_t *errorInfo = m_ScriptContext->GetErrorInfo();
+ if (errorInfo && *errorInfo) {
+ m_Interpreter->QueueEvent("error.execution", false);
+ }
+ m_Error = true;
+ }
+ void ExecuteContent(SExecutableContent &content)
+ {
+ switch (content.m_Type) {
+ case ExecutableContentTypes::Send: {
+ SSend &theSend = *content.CastTo<SSend>();
+ CRegisteredString theEvent;
+ if (!isTrivial(theSend.m_EventExpr)) {
+ SScriptExecutionResult theStr =
+ m_ScriptContext->ExecuteExpressionToString(theSend.m_EventExpr);
+ if (theStr.Valid())
+ theEvent = m_StringTable->RegisterStr(theStr.Result());
+ } else
+ theEvent = theSend.m_Event;
+
+ QT3DSU64 theDelay(0);
+ m_DelayStr.clear();
+ if (!isTrivial(theSend.m_DelayExpr)) {
+ SScriptExecutionResult theStr =
+ m_ScriptContext->ExecuteExpressionToString(theSend.m_DelayExpr);
+ if (theStr.Valid())
+ m_DelayStr.assign(nonNull(theStr.Result()));
+ } else
+ m_DelayStr.assign(nonNull(theSend.m_Delay));
+ if (m_DelayStr.size())
+ theDelay = ParseTimeStrToMilliseconds(m_DelayStr.c_str());
+
+ if (theEvent.IsValid()) {
+ TEventPtr theEventPtr;
+ if (theSend.m_Children.empty() == false) {
+ IScriptEvent *theNewEvent = m_ScriptContext->CreateScriptEvent(theEvent);
+ theEventPtr = theNewEvent;
+ for (TExecutableContentList::iterator iter = theSend.m_Children.begin(),
+ end = theSend.m_Children.end();
+ iter != end && m_Error == false; ++iter) {
+ if (iter->m_Type == ExecutableContentTypes::Param) {
+ SParam &theParam = static_cast<SParam &>(*iter);
+ if (theParam.m_Location.IsValid() == false) {
+ bool success =
+ theNewEvent->SetParam(theParam.m_Name, theParam.m_Expr);
+ if (!success)
+ SignalError();
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ } else if (iter->m_Type == ExecutableContentTypes::Content) {
+ SContent &theContent = static_cast<SContent &>(*iter);
+ if (!isTrivial(theContent.m_Expr)) {
+ bool success = theNewEvent->SetDataExpr(theContent.m_Expr);
+ if (!success)
+ SignalError();
+ } else if (!isTrivial(theContent.m_ContentValue)) {
+ bool success = theNewEvent->SetDataStr(theContent.m_ContentValue);
+ if (!success)
+ SignalError();
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ if (m_Error == false) {
+ bool isExternal = true;
+ if (AreEqual("#_internal", theSend.m_Target))
+ isExternal = false;
+ if (theEventPtr)
+ m_Interpreter->QueueEvent(theEventPtr, theDelay, theSend.m_Id, isExternal);
+ else
+ m_Interpreter->QueueEvent(theEvent, theDelay, theSend.m_Id, isExternal);
+ }
+ }
+ } break;
+ case ExecutableContentTypes::Cancel: {
+ SCancel &theCancel = *content.CastTo<SCancel>();
+ if (theCancel.m_Send) {
+ m_Interpreter->CancelEvent(theCancel.m_Send->m_Id);
+ } else if (!isTrivial(theCancel.m_IdExpression)) {
+ SScriptExecutionResult theStr =
+ m_ScriptContext->ExecuteExpressionToString(theCancel.m_IdExpression);
+ if (theStr.Valid()) {
+ const char8_t *theStrVal(theStr.Result());
+ if (!isTrivial(theStrVal))
+ m_Interpreter->CancelEvent(m_StringTable->RegisterStr(theStrVal));
+ }
+ }
+ } break;
+ case ExecutableContentTypes::Raise: {
+ SRaise &theRaise = *content.CastTo<SRaise>();
+ m_Interpreter->QueueEvent(theRaise.m_Event, false);
+ } break;
+ case ExecutableContentTypes::Log: {
+ SLog *theLog = content.CastTo<SLog>();
+ SScriptExecutionResult str =
+ m_ScriptContext->ExecuteExpressionToString(theLog->m_Expression);
+ if (str.Valid()) {
+ m_Logger->Log(theLog->m_Label, str.Result());
+ if (m_DebugLogger)
+ m_DebugLogger->Log(theLog->m_Label, str.Result());
+ } else
+ SignalError();
+ } break;
+ case ExecutableContentTypes::If: {
+ SIf &theIf = *content.CastTo<SIf>();
+ Option<bool> theCondResult = m_ScriptContext->ExecuteCondition(theIf.m_Cond);
+ if (theCondResult.hasValue()) {
+ bool currentConditionResult = *theCondResult;
+ for (TExecutableContentList::iterator ifIter = theIf.m_Children.begin(),
+ ifEnd = theIf.m_Children.end();
+ ifIter != ifEnd && m_Error == false; ++ifIter) {
+ if (currentConditionResult) {
+ switch (ifIter->m_Type) {
+ case ExecutableContentTypes::Else:
+ case ExecutableContentTypes::ElseIf:
+ return;
+ default:
+ ExecuteContent(*ifIter);
+ break;
+ }
+ } else {
+ switch (ifIter->m_Type) {
+ case ExecutableContentTypes::ElseIf: {
+ SElseIf &theElseIf = *ifIter->CastTo<SElseIf>();
+ theCondResult = m_ScriptContext->ExecuteCondition(theElseIf.m_Cond);
+ if (theCondResult.hasValue())
+ currentConditionResult = *theCondResult;
+ else {
+ SignalError();
+ return;
+ }
+ } break;
+ case ExecutableContentTypes::Else:
+ currentConditionResult = true;
+ break;
+ // Ignore all content that isn't if or else if we shouldn't be currently
+ // executing it.
+ default:
+ break;
+ }
+ }
+ }
+ } else
+ SignalError();
+ } break;
+ case ExecutableContentTypes::Foreach: {
+ SForeach &theItem = *content.CastTo<SForeach>();
+ Option<bool> success;
+ for (success = m_ScriptContext->BeginForeach(theItem.m_Array, theItem.m_Item,
+ theItem.m_Index);
+ success.hasValue() && *success && m_Error == false;
+ success = m_ScriptContext->NextForeach(theItem.m_Item, theItem.m_Index)) {
+ ExecuteContent(theItem.m_Children);
+ }
+ if (m_Error) {
+
+ } else if (success.hasValue() == false)
+ SignalError();
+ } break;
+ // We shouldn't get top level else or else if statements, they can only be inside an if
+ // statement.
+ case ExecutableContentTypes::Else:
+ case ExecutableContentTypes::ElseIf:
+ QT3DS_ASSERT(false);
+ break;
+
+ case ExecutableContentTypes::Assign: {
+ SAssign &theAssign = *content.CastTo<SAssign>();
+ bool success = m_ScriptContext->Assign(theAssign.m_Location, theAssign.m_Expression);
+ if (!success)
+ SignalError();
+ } break;
+ case ExecutableContentTypes::Script: {
+ SScript &theScript = *content.CastTo<SScript>();
+ if (!isTrivial(theScript.m_Data))
+ m_ScriptContext->ExecuteScript(theScript.m_Data);
+ } break;
+ default:
+ qCCritical(INTERNAL_ERROR, "Unimplemented executable content %s",
+ ExecutableContentTypes::ToString(content.m_Type));
+ }
+ }
+
+ void ExecuteContent(TExecutableContentList &inContent)
+ {
+ for (TExecutableContentList::iterator iter = inContent.begin(), end = inContent.end();
+ iter != end && m_Error == false; ++iter) {
+ ExecuteContent(*iter);
+ }
+ }
+
+ void Execute(STransition &inTransaction) override
+ {
+ m_Error = false;
+ ExecuteContent(inTransaction.m_ExecutableContent);
+ }
+
+ // These functions take the node as well as the list so a context can cache a fast
+ // execution path if necessary.
+ void Execute(SStateNode & /*inNode*/, TOnEntryList &inList) override
+ {
+ for (TOnEntryList::iterator iter = inList.begin(), end = inList.end(); iter != end;
+ ++iter) {
+ m_Error = false;
+ ExecuteContent(iter->m_ExecutableContent);
+ }
+ }
+
+ void Execute(SStateNode & /*inNode*/, TOnExitList &inList) override
+ {
+ for (TOnExitList::iterator iter = inList.begin(), end = inList.end(); iter != end; ++iter) {
+ m_Error = false;
+ ExecuteContent(iter->m_ExecutableContent);
+ }
+ }
+};
+}
+
+QT3DSU64 IExecutionContext::ParseTimeStrToMilliseconds(const char8_t *timeStr)
+{
+ if (isTrivial(timeStr))
+ return 0;
+
+ char *endPtr;
+ double theData = strtod(timeStr, &endPtr);
+ if (!isTrivial(endPtr)) {
+ if (AreEqual(endPtr, "s")) {
+ theData *= 1000;
+ } else if (AreEqual(endPtr, "ms")) {
+ // empty intentional
+ } else
+ theData = 0;
+ } else
+ theData = 0;
+ if (theData < 0)
+ theData = 0.0;
+ return static_cast<QT3DSU64>(theData);
+}
+
+IExecutionContext &IExecutionContext::Create(NVFoundationBase &inFoundation,
+ IStringTable &inStringTable, IStateLogger &inLogger,
+ IScriptContext &inScriptContext)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SExecContext)(inFoundation, inStringTable, inLogger,
+ inScriptContext);
+}
diff --git a/src/Runtime/Source/UICState/Source/UICStateInterpreter.cpp b/src/Runtime/Source/UICState/Source/UICStateInterpreter.cpp
new file mode 100644
index 00000000..939525b2
--- /dev/null
+++ b/src/Runtime/Source/UICState/Source/UICStateInterpreter.cpp
@@ -0,0 +1,2057 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateTypes.h"
+#include "UICStateInterpreter.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Utils.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSTime.h"
+#include "EASTL/string.h"
+#include "EASTL/set.h"
+#include "EASTL/sort.h"
+#include "EASTL/list.h"
+#include "UICStateExecutionContext.h"
+#include "UICStateExecutionTypes.h"
+#include "UICStateScriptContext.h"
+#include "UICStateSharedImpl.h"
+#include "foundation/XML.h"
+#include "UICStateIdValue.h"
+#include "UICStateDebugger.h"
+#include "UICStateXMLIO.h"
+#include "UICStateDebuggerValues.h"
+#include "UICStateContext.h"
+#include "foundation/FastAllocator.h"
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+#ifdef _DEBUG
+#define UIC_LOG_ENTER_EXIT 1
+#define UIC_LOG_ACTIVE_EVENT 1
+#endif
+
+namespace uic {
+namespace state {
+ struct SInterpreterData
+ {
+ };
+}
+}
+
+namespace {
+struct SSimpleEvent : public IEvent
+{
+ NVAllocatorCallback &m_Alloc;
+ volatile QT3DSI32 mRefCount;
+ CRegisteredString m_Name;
+
+ SSimpleEvent(NVAllocatorCallback &alloc, CRegisteredString nm)
+ : m_Alloc(alloc)
+ , mRefCount(0)
+ , m_Name(nm)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Alloc)
+
+ CRegisteredString GetName() const override { return m_Name; }
+};
+
+struct SStateNodeInterpreterData : public SInterpreterData
+{
+
+ QT3DSI32 m_DocumentOrder;
+ bool m_Entered;
+ SStateNode *m_TransitionSubgraphRoot;
+
+ SStateNodeInterpreterData(QT3DSI32 inDocOrder)
+ : m_DocumentOrder(inDocOrder)
+ , m_Entered(false)
+ , m_TransitionSubgraphRoot(NULL)
+ {
+ }
+};
+
+template <typename TDataType, typename THasher = eastl::hash<TDataType>,
+ typename TEqOp = eastl::equal_to<TDataType>>
+struct SOrderedSet
+{
+ typedef eastl::hash_set<TDataType, THasher, TEqOp, ForwardingAllocator> TSetType;
+ typedef nvvector<TDataType> TListType;
+
+ TSetType m_Set;
+ TListType m_List;
+ typedef typename TListType::iterator iterator;
+
+ SOrderedSet(NVAllocatorCallback &alloc, const char *inTypeName)
+ : m_Set(ForwardingAllocator(alloc, inTypeName))
+ , m_List(alloc, inTypeName)
+ {
+ }
+
+ bool insert(const TDataType &inDtype)
+ {
+ if (m_Set.insert(inDtype).second) {
+ m_List.push_back(inDtype);
+ return true;
+ }
+ return false;
+ }
+
+ void clear()
+ {
+ m_Set.clear();
+ m_List.clear();
+ }
+
+ iterator begin() { return m_List.begin(); }
+ iterator end() { return m_List.end(); }
+ QT3DSU32 size() const { return m_List.size(); }
+ bool contains(const TDataType &inType) const { return m_Set.find(inType) != m_Set.end(); }
+ TDataType operator[](int inIndex)
+ {
+ if (inIndex < (int)size())
+ return m_List[inIndex];
+ return TDataType();
+ }
+ void erase(const TDataType &inType)
+ {
+ typename TSetType::iterator iter = m_Set.find(inType);
+ if (iter != m_Set.end()) {
+ m_Set.erase(iter);
+ typename TListType::iterator iter = eastl::find(m_List.begin(), m_List.end(), inType);
+ if (iter != m_List.end())
+ m_List.erase(iter);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+};
+
+struct SStateNodeNode
+{
+ SStateNode *m_Node;
+ SStateNodeNode *m_NextSibling;
+ SStateNodeNode()
+ : m_Node(NULL)
+ , m_NextSibling(NULL)
+ {
+ }
+ SStateNodeNode(SStateNode *inNode)
+ : m_Node(inNode)
+ , m_NextSibling(NULL)
+ {
+ }
+};
+
+DEFINE_INVASIVE_SINGLE_LIST(StateNodeNode);
+IMPLEMENT_INVASIVE_SINGLE_LIST(StateNodeNode, m_NextSibling);
+
+struct SFutureEvent
+{
+ TEventPtr m_Event;
+ QT3DSU64 m_FireTime;
+ CRegisteredString m_CancelId;
+ bool m_IsExternal;
+ SFutureEvent(TEventPtr evt, QT3DSU64 ft, CRegisteredString id, bool inExternal)
+ : m_Event(evt)
+ , m_FireTime(ft)
+ , m_CancelId(id)
+ , m_IsExternal(inExternal)
+ {
+ }
+ SFutureEvent()
+ : m_FireTime((QT3DSU64)-1)
+ , m_IsExternal(false)
+ {
+ }
+ // We want the events sorted in *reverse* time order.
+ bool operator<(const SFutureEvent &inOther) const { return m_FireTime < inOther.m_FireTime; }
+};
+
+struct StateSystem;
+
+typedef SOrderedSet<SStateNode *> TStateNodeSet;
+typedef SOrderedSet<STransition *> TTransitionSet;
+typedef nvvector<STransition *> TTransitionList;
+
+struct SDebugInterface : public IStateMachineDebugInterface, public IStateLogger
+{
+ StateSystem &m_StateSystem;
+ // No listener means no events and no active breakpoints of course
+ NVScopedRefCounted<IStateMachineListener> m_Listener;
+ TDebugStr m_LogStr;
+ TDebugStr m_TempStr;
+ TDebugStrList m_EnterList;
+ TDebugStrList m_ExitList;
+ TTransitionIdList m_TransitionList;
+
+ SDebugInterface(StateSystem &ss)
+ : m_StateSystem(ss)
+ , m_Listener(NULL)
+ {
+ }
+ // ignored as this object is part of the state system.
+ void addRef() override;
+ void release() override;
+ bool valid() { return m_Listener.mPtr != NULL; }
+
+ void SetStateMachineListener(IStateMachineListener *inListener) override
+ {
+ if (m_Listener.mPtr != inListener) {
+ m_Listener = inListener;
+ if (m_Listener)
+ OnConnect();
+ }
+ }
+
+ // IStateLogger interface
+ void Log(const char8_t *inLabel, const char8_t *inExpression) override
+ {
+ if (m_Listener) {
+ m_LogStr.assign(nonNull(inLabel));
+ m_LogStr.append(" - ");
+ m_LogStr.append(nonNull(inExpression));
+ m_Listener->Log(m_LogStr);
+ }
+ }
+
+ IScriptContext &GetScriptContext() override;
+
+ // Functions implemented after StateSystem in order to take advantage of the StateSystem struct
+ // members directly.
+ void OnConnect();
+
+ void EventQueued(const char8_t *inEventName, bool inInternal)
+ {
+ m_Listener->EventQueued(inEventName, inInternal);
+ }
+ // Functions should not be called in there is not a valid listener
+ void BeginStep();
+ void BeginMicrostep();
+ void SetCurrentEvent(const char8_t *inEventName, bool inInternal);
+ void SetTransitionSet(const TTransitionList &inTransitions);
+ void SetExitSet(const TStateNodeSet &inSet);
+ void SetEnterSet(const TStateNodeSet &inSet);
+ // Log statements run through the debugger as well.
+ void EndMicrostep();
+ void EndStep();
+ void OnExternalBreak() override;
+};
+
+#define DEBUGGER_CALL(function) \
+ if (m_DebugInterface.valid()) \
+ m_DebugInterface.function();
+#define DEBUGGER_CALL1(function, arg) \
+ if (m_DebugInterface.valid()) \
+ m_DebugInterface.function(arg);
+#define DEBUGGER_CALL2(function, arg, arg2) \
+ if (m_DebugInterface.valid()) \
+ m_DebugInterface.function(arg, arg2);
+
+#ifdef _WIN32
+#pragma warning(disable : 4355)
+#endif
+struct SStateSignalSender : public IStateSignalConnection
+{
+ NVAllocatorCallback &m_Alloc;
+ StateSystem *m_System;
+ IStateInterpreterEventHandler &m_Handler;
+ volatile QT3DSI32 mRefCount;
+ SStateSignalSender(NVAllocatorCallback &inAlloc, StateSystem &inSystem,
+ IStateInterpreterEventHandler &inHandler)
+ : m_Alloc(inAlloc)
+ , m_System(&inSystem)
+ , m_Handler(inHandler)
+ , mRefCount(0)
+ {
+ }
+ virtual ~SStateSignalSender();
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Alloc)
+};
+
+// Note that we explicity don't addref the signal sender internally. This is by design.
+typedef nvvector<SStateSignalSender *> TSignalSenderList;
+
+struct StateSystem : public IStateInterpreter
+{
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+ typedef Pool<SStateNodeInterpreterData, ForwardingAllocator> TInterperterDataPool;
+ typedef eastl::list<TEventPtr, ForwardingAllocator> TEventQueue;
+ typedef nvhash_map<SHistory *, TStateNodeNodeList> THistoryMap;
+ typedef Pool<SStateNodeNode, ForwardingAllocator> TStateNodeNodePool;
+ typedef nvvector<SFutureEvent> TFutureEventList;
+ typedef nvhash_set<STransition *> TTransitionHashSet;
+ typedef Pool<STransition, ForwardingAllocator> TTransitionPool;
+
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IStateContext> m_Context;
+ volatile QT3DSI32 mRefCount;
+ // Holds the leaves of the current state.
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IScriptContext> m_ScriptContext;
+ NVScopedRefCounted<IExecutionContext> m_ExecutionContext;
+ nvvector<SStateNode *> m_ParentComparisonLHS;
+ nvvector<SStateNode *> m_ParentComparisonRHS;
+ nvvector<SStateNode *> m_AncestorsList;
+ nvvector<SStateNode *> m_IDRefList;
+
+ THistoryMap m_HistoryMap;
+
+ SOrderedSet<SStateNode *> m_Configuration;
+ nvvector<SStateNode *> m_StatesToInvoke;
+ nvvector<SStateNode *> m_TransitionTargetList;
+ TTransitionList m_EnabledTransitions;
+
+ TEventQueue m_InternalQueue;
+ TEventQueue m_ExternalQueue;
+
+ SOrderedSet<STransition *> m_TransitionSet;
+
+ TStateNodeSet m_StatesToEnter;
+ TStateNodeSet m_StatesForDefaultEntry;
+ TStateNodeSet m_StatesToExit;
+
+ TInterperterDataPool m_InterpreterDataPool;
+ TStateNodeNodePool m_StateNodeNodePool;
+
+ TStrType m_Workspace;
+
+ TFutureEventList m_FutureEvents;
+
+ bool m_Initialized;
+ bool m_Running;
+
+ SDebugInterface m_DebugInterface;
+ TSignalSenderList m_SignalSenders;
+
+ TTransitionHashSet m_InvalidTransitions;
+
+ TTransitionPool m_TransitionPool;
+ nvvector<STransition *> m_TemporaryTransitions;
+ nvhash_map<SStateNode *, STransition *> m_StateInitialTransitionMap;
+ SFastAllocator<> m_TemporaryAllocator;
+ TStrType m_IdSplitter;
+ nvvector<SStateNode *> m_TempNodeList;
+
+ StateSystem(NVFoundationBase &inFnd, IStringTable &inStrTable, IScriptContext &inScriptContext,
+ IExecutionContext &inExecutionContext)
+ : m_Foundation(inFnd)
+ , mRefCount(0)
+ , m_StringTable(inStrTable)
+ , m_ScriptContext(inScriptContext)
+ , m_ExecutionContext(inExecutionContext)
+ , m_ParentComparisonLHS(inFnd.getAllocator(), "StateSystem::m_ParentComparisonLHS")
+ , m_ParentComparisonRHS(inFnd.getAllocator(), "StateSystem::m_ParentComparisonRHS")
+ , m_AncestorsList(inFnd.getAllocator(), "StateSystem::m_AncestorsList")
+ , m_IDRefList(inFnd.getAllocator(), "StateSystem::m_IDRefList")
+ , m_HistoryMap(inFnd.getAllocator(), "StateSystem::m_HistoryMap")
+ , m_Configuration(inFnd.getAllocator(), "StateSystem::m_Configuration")
+ , m_StatesToInvoke(inFnd.getAllocator(), "StateSystem::m_InvokeList")
+ , m_TransitionTargetList(inFnd.getAllocator(), "StateSystem::m_TransitionTargetList")
+ , m_EnabledTransitions(inFnd.getAllocator(), "StateSystem::m_TransitionList")
+ , m_InternalQueue(ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_InternalQueue"))
+ , m_ExternalQueue(ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_ExternalQueue"))
+ , m_TransitionSet(inFnd.getAllocator(), "StateSystem::m_TransitionSet")
+ , m_StatesToEnter(inFnd.getAllocator(), "StateSystem::m_StatesToEnter")
+ , m_StatesForDefaultEntry(inFnd.getAllocator(), "StateSystem::m_StatesForDefaultEntry")
+ , m_StatesToExit(inFnd.getAllocator(), "StateSystem::m_StatesToExit")
+ , m_InterpreterDataPool(
+ ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_InterpretDataPool"))
+ , m_StateNodeNodePool(
+ ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_StateNodeNodePool"))
+ , m_Workspace(ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_Workspace"))
+ , m_FutureEvents(inFnd.getAllocator(), "StateSystem::m_FutureEvents")
+ , m_Initialized(false)
+ , m_Running(false)
+ , m_DebugInterface(*this)
+ , m_SignalSenders(inFnd.getAllocator(), "StateSystem::m_SignalSenders")
+ , m_InvalidTransitions(inFnd.getAllocator(), "StateSystem::m_InvalidTransitions")
+ , m_TransitionPool(
+ ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_TransitionPool"))
+ , m_TemporaryTransitions(inFnd.getAllocator(), "StateSystem::m_TemporaryTransitions")
+ , m_StateInitialTransitionMap(inFnd.getAllocator(),
+ "StateSystem::m_StateInitialTempTransitionMap")
+ , m_TemporaryAllocator(inFnd.getAllocator(), "StateSystem::m_TemporaryAllocator")
+ , m_IdSplitter(ForwardingAllocator(inFnd.getAllocator(), "StateSystem::m_IdSplitter"))
+ , m_TempNodeList(inFnd.getAllocator(), "StateSystem::m_TempNodeList")
+ {
+ inExecutionContext.SetInterpreter(*this);
+ inExecutionContext.SetMachineDebugLogger(m_DebugInterface);
+ inScriptContext.SetInterpreter(*this);
+ }
+
+ ~StateSystem()
+ {
+ // Ensure the signallers will not attempt to communicate to this object.
+ for (TSignalSenderList::iterator iter = m_SignalSenders.begin(),
+ end = m_SignalSenders.end();
+ iter != end; ++iter)
+ (*iter)->m_System = NULL;
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void InitializeDataStructures()
+ {
+ m_Configuration.clear();
+ m_StatesToInvoke.clear();
+ m_EnabledTransitions.clear();
+ m_Running = true;
+ }
+
+ STransition &CreateTemporaryTransition()
+ {
+ STransition *newTrans = m_TransitionPool.construct(__FILE__, __LINE__);
+ m_TemporaryTransitions.push_back(newTrans);
+ return *newTrans;
+ }
+
+ void ReleaseInitialAndTemporaryTransitions()
+ {
+ for (QT3DSU32 idx = 0, end = m_TemporaryTransitions.size(); idx < end; ++idx)
+ m_TransitionPool.deallocate(m_TemporaryTransitions[idx]);
+ m_TemporaryTransitions.clear();
+ m_StateInitialTransitionMap.clear();
+ m_TemporaryAllocator.reset();
+ }
+
+ void FreeHistoryData(SHistory &inHistory)
+ {
+ THistoryMap::iterator historyData = m_HistoryMap.find(&inHistory);
+ if (historyData != m_HistoryMap.end()) {
+ for (TStateNodeNodeList::iterator iter = historyData->second.begin(),
+ end = historyData->second.end();
+ iter != end; ++iter)
+ m_StateNodeNodePool.deallocate(&(*iter));
+ // Force clear the list.
+ historyData->second.m_Head = NULL;
+ }
+ }
+
+ TStateNodeNodeList *GetHistoryData(SHistory &inHistory)
+ {
+ THistoryMap::iterator historyData = m_HistoryMap.find(&inHistory);
+ if (historyData != m_HistoryMap.end())
+ return &historyData->second;
+ return NULL;
+ }
+
+ TStateNodeNodeList &GetOrCreateHistoryData(SHistory &inHistory)
+ {
+ THistoryMap::iterator historyData = m_HistoryMap.find(&inHistory);
+ if (historyData != m_HistoryMap.end())
+ return historyData->second;
+ return m_HistoryMap.insert(eastl::make_pair(&inHistory, TStateNodeNodeList()))
+ .first->second;
+ }
+
+ // Setup of the state system, you can add a set of roots to the state graph.
+ NVConstDataRef<SStateNode *> GetConfiguration() override { return m_Configuration.m_List; }
+
+ void GetPathToRoot(SStateNode &state, nvvector<SStateNode *> &inParents, bool inProper)
+ {
+ inParents.clear();
+ SStateNode *stateIter = &state;
+ if (inProper)
+ stateIter = state.m_Parent;
+ for (; stateIter; stateIter = stateIter->m_Parent)
+ inParents.push_back(stateIter);
+ }
+
+ // Given these two states, get the nearest parent they share in common.
+ // Return valid is the index taken from the end of the m_ParentComparison* lists.
+ // the index is valid in both of them.
+ QT3DSI32 GetSharedParentState(SStateNode &lhs, SStateNode &rhs, bool inProper)
+ {
+ GetPathToRoot(lhs, m_ParentComparisonLHS, inProper);
+ GetPathToRoot(rhs, m_ParentComparisonRHS, inProper);
+ if (m_ParentComparisonLHS.empty() || m_ParentComparisonRHS.empty()) {
+ QT3DS_ASSERT(false);
+ return -1;
+ }
+ QT3DS_ASSERT(m_ParentComparisonLHS.back() == m_ParentComparisonRHS.back());
+ QT3DSI32 retval = 0;
+ for (nvvector<SStateNode *>::reverse_iterator lhsComp = m_ParentComparisonLHS.rbegin(),
+ rhsComp = m_ParentComparisonRHS.rbegin(),
+ lhsEnd = m_ParentComparisonLHS.rend(),
+ rhsEnd = m_ParentComparisonRHS.rend();
+ lhsComp != lhsEnd && rhsComp != rhsEnd && *lhsComp == *rhsComp;
+ ++lhsComp, ++rhsComp, ++retval) {
+ }
+ // Walk the path to the root backwards and note where it differs.
+ return retval - 1;
+ }
+
+ void CreateStateNodeInterpreterData(SStateNode &inNode, QT3DSI32 &inIdx)
+ {
+ inNode.m_InterpreterData = m_InterpreterDataPool.construct(inIdx, __FILE__, __LINE__);
+ ++inIdx;
+ if (inNode.m_Type == StateNodeTypes::SCXML) {
+ SSCXML *item = inNode.CastTo<SSCXML>();
+ if (item->m_Initial)
+ CreateStateNodeInterpreterData(*item->m_Initial, inIdx);
+ } else if (inNode.m_Type == StateNodeTypes::State) {
+ SState *item = inNode.CastTo<SState>();
+ if (item->m_Initial)
+ CreateStateNodeInterpreterData(*item->m_Initial, inIdx);
+ }
+ if (StateNodeTypes::CanHaveChildren(inNode.m_Type)) {
+ SStateParallelBase &theBase = static_cast<SStateParallelBase &>(inNode);
+ for (TStateNodeList::iterator iter = theBase.m_Children.begin(),
+ end = theBase.m_Children.end();
+ iter != end; ++iter)
+ CreateStateNodeInterpreterData(*iter, inIdx);
+ }
+ }
+
+ // Creates the interpreter data for the entire graph.
+ void CreateStateNodeInterpreterData()
+ {
+ if (m_Context->GetRoot() == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ QT3DSI32 nodeIdx = 1;
+ CreateStateNodeInterpreterData(*m_Context->GetRoot(), nodeIdx);
+ }
+
+ SStateNodeInterpreterData &GetOrCreateInterpreterData(SStateNode &inNode)
+ {
+ if (!inNode.m_InterpreterData)
+ CreateStateNodeInterpreterData();
+
+ return *static_cast<SStateNodeInterpreterData *>(inNode.m_InterpreterData);
+ }
+ struct SStateNodeSorter
+ {
+ StateSystem &m_System;
+ SStateNodeSorter(StateSystem &inS)
+ : m_System(inS)
+ {
+ }
+ bool operator()(SStateNode *lhs, SStateNode *rhs) const
+ {
+ return m_System.GetOrCreateInterpreterData(*lhs).m_DocumentOrder
+ < m_System.GetOrCreateInterpreterData(*rhs).m_DocumentOrder;
+ }
+ };
+
+ void SortByDocumentOrder(nvvector<SStateNode *> &inList)
+ {
+ eastl::sort(inList.begin(), inList.end(), SStateNodeSorter(*this));
+ }
+
+ void SortConfiguration() { SortByDocumentOrder(m_Configuration.m_List); }
+
+ void RunDataModel(SDataModel &inDM)
+ {
+ QT3DS_ASSERT(inDM.m_Source == NULL);
+ QT3DS_ASSERT(inDM.m_Expression == NULL);
+ for (TDataList::iterator iter = inDM.m_Data.begin(), end = inDM.m_Data.end(); iter != end;
+ ++iter) {
+ if (iter->m_Source == NULL)
+ m_ScriptContext->Assign(iter->m_Id.c_str(), iter->m_Expression);
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+
+ void RecursiveInitializeDataModel(SStateNode &inState)
+ {
+ SDataModel *theDataModel = inState.GetDataModel();
+ if (theDataModel)
+ RunDataModel(*theDataModel);
+
+ TStateNodeList *children = inState.GetChildren();
+ if (children) {
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter)
+ RecursiveInitializeDataModel(*iter);
+ }
+ }
+
+ // Called during initialization for early binding of the datamodel
+ void RecursiveInitializeDataModel()
+ {
+ QT3DS_ASSERT(m_Context->GetRoot());
+ QT3DS_ASSERT(m_Context->GetRoot()->m_Flags.IsLateBinding() == false);
+ RecursiveInitializeDataModel(*m_Context->GetRoot());
+ }
+
+ void MarkTransitionAsInvalid(STransition &inTransition, SStateNode &inParent, int inIndex)
+ {
+ if (inIndex >= 0) {
+ qCCritical(INVALID_OPERATION, "Detected invalid transition %s:%d",
+ inParent.m_Id.c_str(), inIndex);
+ } else {
+ const char *transitionType = "initial";
+ if (inIndex == -1)
+ transitionType = "history";
+ qCCritical(INVALID_OPERATION, "Detected invalid %s transition on node %s:%d",
+ transitionType, inParent.m_Id.c_str(), inIndex);
+ }
+ m_InvalidTransitions.insert(&inTransition);
+ }
+
+ bool IsTransitionValid(STransition &inTransition)
+ {
+ return m_InvalidTransitions.find(&inTransition) == m_InvalidTransitions.end();
+ }
+
+ bool IsTransitionValid(STransition *inTransition)
+ {
+ if (inTransition)
+ return IsTransitionValid(*inTransition);
+
+ // NULL transitions are of course, invalid.
+ return false;
+ }
+
+ bool ValidateTransitionTargetList(STransition &inTransition, SStateNode &inParent, int inIndex)
+ {
+ for (QT3DSU32 idx = 0, end = inTransition.m_Target.size(); idx < end; ++idx) {
+ for (QT3DSU32 outerIdx = idx + 1; outerIdx < end; ++outerIdx) {
+ // We handle this case dynamically during transition activation
+ if (IsDescendant(*inTransition.m_Target[idx], *inTransition.m_Target[outerIdx])
+ || IsDescendant(*inTransition.m_Target[outerIdx], *inTransition.m_Target[idx]))
+ continue;
+
+ // If they aren't directly related they must be related indirectly via a parallel.
+ SStateNode *theLCA =
+ FindLCA(*inTransition.m_Target[idx], *inTransition.m_Target[outerIdx]);
+ if (theLCA && theLCA->m_Type != StateNodeTypes::Parallel) {
+ MarkTransitionAsInvalid(inTransition, inParent, inIndex);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ void ValidateInitialOrHistoryTransition(STransition *inTransition, SStateNode &inParent,
+ bool inIsInitial = false)
+ {
+ if (inTransition == NULL)
+ return;
+ int transIndex = inIsInitial ? -2 : -1;
+ if (inTransition->m_Target.size() == 0) {
+ MarkTransitionAsInvalid(*inTransition, inParent, transIndex);
+ } else {
+ ValidateTransitionTargetList(*inTransition, inParent, transIndex);
+ }
+ }
+
+ void ValidateGeneralTransition(STransition &inTransition, SStateNode &inParent, int inIndex)
+ {
+ // Three distinct ways a transition could be invalid.
+ // 1. targetless, eventless and conditionless
+ if (inTransition.m_Target.size() == 0 && inTransition.m_Event.IsValid() == false
+ && isTrivial(inTransition.m_Condition))
+ MarkTransitionAsInvalid(inTransition, inParent, inIndex);
+ else {
+ // Else eventless ,targetless, and points back to source state
+ if (inTransition.m_Target.size() == 1) {
+ if (inTransition.m_Target[0] == inTransition.m_Parent
+ && inTransition.m_Event.IsValid() == false
+ && isTrivial(inTransition.m_Condition)) {
+ MarkTransitionAsInvalid(inTransition, inParent, inIndex);
+ }
+ } else {
+ ValidateTransitionTargetList(inTransition, inParent, inIndex);
+ }
+ }
+ }
+
+ void RecursiveValidateTransitions(SStateNode &inNode, SStateNode *inParent, int inIndex)
+ {
+ switch (inNode.m_Type) {
+ case StateNodeTypes::SCXML:
+ ValidateInitialOrHistoryTransition(inNode.GetInitialTransition(), inNode);
+ break;
+ case StateNodeTypes::State:
+ ValidateInitialOrHistoryTransition(inNode.GetInitialTransition(), inNode);
+ break;
+ case StateNodeTypes::Parallel:
+ ValidateInitialOrHistoryTransition(inNode.GetInitialTransition(), inNode);
+ break;
+ case StateNodeTypes::History:
+ ValidateInitialOrHistoryTransition(static_cast<SHistory &>(inNode).m_Transition, inNode,
+ false);
+ break;
+ case StateNodeTypes::Transition:
+ if (inParent)
+ ValidateGeneralTransition(static_cast<STransition &>(inNode), *inParent, inIndex);
+ break;
+ default: // don't care
+ break;
+ }
+ RecursiveValidateTransitions(inNode, inNode.GetChildren());
+ }
+
+ void RecursiveValidateTransitions(SStateNode &inParent, TStateNodeList *inNodes)
+ {
+ if (inNodes) {
+ int idx = 0;
+ for (TStateNodeList::iterator iter = inNodes->begin(), end = inNodes->end();
+ iter != end; ++iter, ++idx)
+ RecursiveValidateTransitions(*iter, &inParent, idx);
+ }
+ }
+
+ // The state machine is pretty robust but there are is one category of input that can
+ // put the machine in a bad state. Transitions with either multiple targets or no target
+ // or a single target that points back to its owner may be bad depending on different criteria.
+ // For multiple targets, we invalidate a transition that puts us into a bad state.
+ // For no targets, in invalidate a transition that would cause the interpreter to loop
+ // infinitely
+ // For a single target, we invalidate a transition if it points back to its source but it has no
+ // condition
+ // or event. We don't attempt any more sophisticated analysis at this point although one could
+ // conceive of
+ // an analysis that could find loops depending on how long you wanted it to run.
+ void RecursiveValidateTransitions()
+ {
+ QT3DS_ASSERT(m_Context->GetRoot());
+ RecursiveValidateTransitions(*m_Context->GetRoot(), NULL, 0);
+ }
+
+ NVConstDataRef<SStateNode *> GetRefList(NVConstDataRef<SStateNode *> inIds) { return inIds; }
+
+ // unsorted, may contain duplicates.
+ NVDataRef<SStateNode *> GetRefList(NVConstDataRef<CRegisteredString> inIds)
+ {
+ m_IDRefList.clear();
+ for (QT3DSU32 idx = 0, end = inIds.size(); idx < end; ++idx) {
+ SStateNode *theNode = m_Context->FindStateNode(inIds[idx]);
+ if (theNode != NULL) {
+ m_IDRefList.push_back(theNode);
+ }
+ }
+ return m_IDRefList;
+ }
+
+ NVConstDataRef<SStateNode *> GetTargetStates(STransition *inTransition)
+ {
+ if (inTransition)
+ return inTransition->m_Target;
+ return NVDataRef<SStateNode *>();
+ }
+
+ static bool IsCompoundState(const SStateNode *inNode)
+ {
+ if (inNode == NULL)
+ return false;
+ return inNode->IsCompound();
+ }
+
+ static bool IsDescendant(SStateNode &inParent, SStateNode &inChild)
+ {
+ if (&inChild == &inParent)
+ return false;
+
+ for (SStateNode *theNode = &inChild; theNode; theNode = theNode->m_Parent)
+ if (theNode == &inParent)
+ return true;
+ return false;
+ }
+
+ static bool AllAreDescendants(SStateNode &inParent, NVConstDataRef<SStateNode *> inList)
+ {
+ for (QT3DSU32 idx = 0, end = inList.size(); idx < end; ++idx)
+ if (IsDescendant(inParent, *inList[idx]) == false)
+ return false;
+ return true;
+ }
+ struct SRefListPlusOne
+ {
+ NVConstDataRef<SStateNode *> m_List;
+ SStateNode *m_Extra;
+
+ SRefListPlusOne(NVConstDataRef<SStateNode *> l, SStateNode *e)
+ : m_List(l)
+ , m_Extra(e)
+ {
+ }
+
+ QT3DSU32 size() { return m_List.size() + (m_Extra ? 1 : 0); }
+
+ SStateNode *operator[](int idx)
+ {
+ if (idx < (int)m_List.size())
+ return m_List[idx];
+ if (idx == (int)m_List.size())
+ return m_Extra;
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ };
+
+ SStateNode *FindLCA(SStateNode &lhs, SStateNode &rhs)
+ {
+ QT3DSU32 sharedIdx = GetSharedParentState(lhs, rhs, false);
+ return *(m_ParentComparisonLHS.rbegin() + sharedIdx);
+ }
+
+ SStateNode *FindLCCA(NVConstDataRef<SStateNode *> inList, SStateNode *inExtra = NULL)
+ {
+ SRefListPlusOne theList(inList, inExtra);
+ if (theList.size() == 0)
+ return NULL;
+ if (theList.size() == 1) {
+ for (SStateNode *item = theList[0]; item; item = item->m_Parent) {
+ if (item->IsCompound())
+ return item;
+ }
+ }
+ SStateNode *lhs = theList[0];
+ for (QT3DSU32 idx = 1, end = theList.size(); idx < end; ++idx) {
+ SStateNode *rhs = theList[idx];
+ QT3DSU32 sharedIdx = GetSharedParentState(*lhs, *rhs, false);
+ lhs = *(m_ParentComparisonLHS.rbegin() + sharedIdx);
+ }
+ for (SStateNode *item = lhs; item; item = item->m_Parent) {
+ if (item->IsCompound())
+ return item;
+ }
+ QT3DS_ASSERT(false);
+ return m_Context->GetRoot();
+ }
+ NVDataRef<SStateNode *> GetProperAncestors(SStateNode &inChild, SStateNode *inStop)
+ {
+ m_AncestorsList.clear();
+ for (SStateNode *parent = inChild.m_Parent; parent && parent != inStop;
+ parent = parent->m_Parent)
+ m_AncestorsList.push_back(parent);
+ return m_AncestorsList;
+ }
+
+ bool AddStateToEnterToSet(SStateNode &inNode)
+ {
+ if (m_Configuration.contains(&inNode) == false) {
+ m_StatesToEnter.insert(&inNode);
+ return true;
+ }
+ return false;
+ }
+
+ void AddStatesToEnter(SHistory &inState)
+ {
+ TStateNodeNodeList *history = GetHistoryData(inState);
+ if (history) {
+ for (TStateNodeNodeList::iterator iter = history->begin(), end = history->end();
+ iter != end; ++iter) {
+ AddStatesToEnter(*iter->m_Node);
+ NVDataRef<SStateNode *> ancestors =
+ GetProperAncestors(*iter->m_Node, inState.m_Parent);
+ for (QT3DSU32 ancIdx = 0, ancEnd = ancestors.size(); ancIdx < ancEnd; ++ancIdx)
+ AddStateToEnterToSet(*ancestors[ancIdx]);
+ }
+ } else {
+ if (IsTransitionValid(inState.m_Transition)) {
+ NVConstDataRef<SStateNode *> theList = GetRefList(inState.m_Transition->m_Target);
+ for (QT3DSU32 idx = 0, end = theList.size(); idx < end; ++idx) {
+ AddStatesToEnter(*theList[idx]);
+ NVDataRef<SStateNode *> ancestors =
+ GetProperAncestors(*theList[idx], inState.m_Parent);
+ for (QT3DSU32 ancIdx = 0, ancEnd = ancestors.size(); ancIdx < ancEnd; ++ancIdx)
+ AddStateToEnterToSet(*ancestors[ancIdx]);
+ }
+ } else {
+ qCCritical(INVALID_OPERATION,
+ "History node %s with no history, no transition, or invalid transition visited",
+ inState.m_Id.c_str());
+ SStateNode *theParent = inState.m_Parent;
+ if (theParent != NULL) {
+ if (theParent->m_Type != StateNodeTypes::Parallel) {
+ NVConstDataRef<SStateNode *> theDefaultInitial(
+ GetDefaultInitialState(*theParent));
+
+ QT3DS_ASSERT(theDefaultInitial.size() != 0);
+ for (QT3DSU32 idx = 0, end = theDefaultInitial.size(); idx < end; ++idx)
+ AddStatesToEnter(*theDefaultInitial[idx]);
+
+ EnterAncestors(theDefaultInitial, theParent);
+ } else {
+ SParallel *pstate = theParent->CastTo<SParallel>();
+ for (TStateNodeList::iterator iter = pstate->m_Children.begin(),
+ end = pstate->m_Children.end();
+ iter != end; ++iter) {
+ if (StateNodeTypes::IsStateType(iter->m_Type))
+ AddStatesToEnter(*iter);
+ }
+ }
+ } else {
+ QT3DS_ASSERT(false); // invalid configuration
+ }
+ }
+ }
+ }
+ NVConstDataRef<SStateNode *> GetDefaultInitialState(SStateNode &inState)
+ {
+ TStateNodeList *theChildren = inState.GetChildren();
+ NVConstDataRef<SStateNode *> retval;
+ if (theChildren) {
+ for (TStateNodeList::iterator iter = theChildren->begin(), end = theChildren->end();
+ iter != end && retval.size() == 0; ++iter) {
+ if (iter->m_Type == StateNodeTypes::State
+ || iter->m_Type == StateNodeTypes::Parallel
+ || iter->m_Type == StateNodeTypes::Final) {
+ SStateNode **newData =
+ reinterpret_cast<SStateNode **>(m_TemporaryAllocator.allocate(
+ sizeof(SStateNode *), "TempNode", __FILE__, __LINE__));
+ newData[0] = &(*iter);
+ retval = toDataRef(newData, 1);
+ }
+ }
+ }
+ return retval;
+ }
+
+ STransition *GetStateInitialTransition(SStateNode &inNode)
+ {
+ // Initialexpr, if it exists, takes precedence over the initial transition.
+ // they should not both exist but coding defensively, we have to take this into account.
+ eastl::pair<nvhash_map<SStateNode *, STransition *>::iterator, bool> inserter =
+ m_StateInitialTransitionMap.insert(eastl::make_pair(&inNode, (STransition *)NULL));
+ if (inserter.second) {
+ const char8_t *initialExpr = inNode.GetInitialExpression();
+ if (!isTrivial(initialExpr)) {
+ STransition *newTransition = &CreateTemporaryTransition();
+ newTransition->m_Parent = &inNode;
+ inserter.first->second = newTransition;
+ SScriptExecutionResult exprResultData =
+ m_ScriptContext->ExecuteExpressionToString(initialExpr);
+ if (exprResultData.Valid()) {
+ const char8_t *exprResult(exprResultData.Result());
+ // split this string into parts and extract ids.
+ m_IdSplitter.assign(nonNull(exprResult));
+ const char8_t *whitespaceData = " \n\t\r";
+ size_t charPos = m_IdSplitter.find_first_not_of(whitespaceData);
+ if (charPos == eastl::string::npos) {
+ m_IdSplitter.clear();
+ m_Workspace.clear();
+ }
+ if (charPos != 0)
+ m_IdSplitter.erase(m_IdSplitter.begin(), m_IdSplitter.begin() + charPos);
+ // Loop runs under assumption that idSplitter is empty or position 0 holds start
+ // of next id
+ while (m_IdSplitter.size()) {
+ // Trim to first character
+ eastl::string::size_type spacePos =
+ m_IdSplitter.find_first_of(whitespaceData);
+
+ if (spacePos != eastl::string::npos) {
+ charPos = m_IdSplitter.find_first_not_of(whitespaceData, spacePos);
+ m_Workspace = m_IdSplitter.c_str();
+ m_Workspace.resize(spacePos);
+ if (charPos != eastl::string::npos)
+ m_IdSplitter.erase(m_IdSplitter.begin(),
+ m_IdSplitter.begin() + charPos);
+ else
+ m_IdSplitter.clear();
+ } else {
+ m_Workspace = m_IdSplitter;
+ m_IdSplitter.clear();
+ }
+
+ if (m_Workspace.empty() == false) {
+ CRegisteredString stateId =
+ m_StringTable->RegisterStr(m_Workspace.c_str());
+ uic::state::SStateNode *transitionNode =
+ m_Context->FindStateNode(stateId);
+ if (!transitionNode) {
+ m_TempNodeList.clear();
+ m_IdSplitter.clear();
+ qCCritical(INVALID_OPERATION,
+ "initialexpr=\"%s\" evaluated to \"%s\", but "
+ "this does not match the states in this "
+ "document. Using the default initial state "
+ "instead.",
+ nonNull(initialExpr), nonNull(exprResult));
+
+ eastl::string errorBuf;
+ IScriptEvent *newEvent = m_ScriptContext->CreateScriptEvent(
+ m_StringTable->RegisterStr("error.execution.initialexpr"));
+ newEvent->SetParamStr(m_StringTable->RegisterStr("expr"),
+ nonNull(initialExpr));
+ errorBuf.assign(nonNull(exprResult));
+ errorBuf.append(" does not match the states in this document.");
+ newEvent->SetParamStr(m_StringTable->RegisterStr("error"),
+ errorBuf.c_str());
+ QueueEvent(*newEvent, false);
+ } else
+ m_TempNodeList.push_back(transitionNode);
+ }
+ }
+ if (m_TempNodeList.empty() == false) {
+ QT3DSU32 allocSize = sizeof(SStateNode *) * m_TempNodeList.size();
+ SStateNode **nodeData =
+ reinterpret_cast<SStateNode **>(m_TemporaryAllocator.allocate(
+ allocSize, "TempNodes", __FILE__, __LINE__));
+ memCopy(nodeData, m_TempNodeList.data(), allocSize);
+ newTransition->m_Target = toDataRef(nodeData, m_TempNodeList.size());
+ m_TempNodeList.clear();
+ }
+ if (newTransition->m_Target.size() != 0) {
+ bool isTransValid = ValidateTransitionTargetList(*newTransition, inNode, 0);
+ if (!isTransValid) {
+ m_InvalidTransitions.erase(newTransition);
+ // Reset the transition so that we get just the default initial state
+ // below
+ newTransition->m_Target = NVConstDataRef<SStateNode *>();
+ // Create appropriate messages and events.
+ qCCritical(INVALID_OPERATION,
+ "initialexpr=\"%s\" evaluated to \"%s\", but this "
+ "results in an invalid transition. Using the "
+ "default initial state instead.",
+ nonNull(initialExpr), nonNull(exprResult));
+ eastl::string errorBuf;
+ IScriptEvent *newEvent = m_ScriptContext->CreateScriptEvent(
+ m_StringTable->RegisterStr("error.execution.initialexpr"));
+ newEvent->SetParamStr(m_StringTable->RegisterStr("expr"),
+ nonNull(initialExpr));
+ errorBuf.assign(nonNull(exprResult));
+ errorBuf.append(" results in invalid transition.");
+ newEvent->SetParamStr(m_StringTable->RegisterStr("error"),
+ errorBuf.c_str());
+ QueueEvent(*newEvent, false);
+ }
+ }
+ } // if script executed successfully
+ else {
+ const char8_t *runtimeError = exprResultData.Error();
+ IScriptEvent *newEvent = m_ScriptContext->CreateScriptEvent(
+ m_StringTable->RegisterStr("error.execution.initialexpr"));
+ newEvent->SetParamStr(m_StringTable->RegisterStr("expr"), nonNull(initialExpr));
+ newEvent->SetParamStr(m_StringTable->RegisterStr("error"),
+ nonNull(runtimeError));
+ QueueEvent(*newEvent, false);
+ }
+ if (newTransition->m_Target.size() == 0) {
+ newTransition->m_Target = GetDefaultInitialState(inNode);
+ }
+ }
+ if (inserter.first->second == NULL) {
+ // Assume already validated
+ inserter.first->second = inNode.GetInitialTransition();
+ }
+ }
+ return inserter.first->second;
+ }
+
+ void AddStatesToEnter(SStateNode &inState)
+ {
+ if (inState.m_Type == StateNodeTypes::History)
+ AddStatesToEnter(*inState.CastTo<SHistory>());
+ else {
+ AddStateToEnterToSet(inState);
+ if (inState.IsCompound()) {
+ m_StatesForDefaultEntry.insert(&inState);
+ NVConstDataRef<SStateNode *> targets;
+ STransition *initialTrans = GetStateInitialTransition(inState);
+ if (IsTransitionValid(initialTrans))
+ targets = GetTargetStates(initialTrans);
+
+ if (targets.size() == 0)
+ targets = GetDefaultInitialState(inState);
+
+ QT3DS_ASSERT(targets.size() != 0);
+ for (QT3DSU32 idx = 0, end = targets.size(); idx < end; ++idx)
+ AddStatesToEnter(*targets[idx]);
+
+ EnterAncestors(targets, &inState);
+ } else if (inState.m_Type == StateNodeTypes::Parallel) {
+ SParallel *pstate = inState.CastTo<SParallel>();
+ for (TStateNodeList::iterator iter = pstate->m_Children.begin(),
+ end = pstate->m_Children.end();
+ iter != end; ++iter) {
+ if (StateNodeTypes::IsStateType(iter->m_Type))
+ AddStatesToEnter(*iter);
+ }
+ }
+ }
+ }
+ bool AllChildrenInFinalStates(SStateNode &inNode)
+ {
+ TStateNodeList *children = inNode.GetChildren();
+ if (children) {
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter)
+ if (!IsInFinalState(*iter))
+ return false;
+ return true;
+ }
+ return true;
+ }
+
+ void EraseState(nvvector<SStateNode *> &inList, SStateNode *inItem)
+ {
+ nvvector<SStateNode *>::iterator iter = eastl::find(inList.begin(), inList.end(), inItem);
+ if (iter != inList.end())
+ inList.erase(iter);
+ }
+
+ void ExitStates(NVDataRef<STransition *> inTransitions)
+ {
+ m_StatesToExit.clear();
+ for (QT3DSU32 idx = 0, end = inTransitions.size(); idx < end; ++idx) {
+ STransition &transition(*inTransitions[idx]);
+ if (transition.GetSource() == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ NVConstDataRef<SStateNode *> theList = GetRefList(transition.m_Target);
+ SStateNode *ancestor = GetTransitionSubgraphRoot(transition, theList);
+ if (theList.size() && transition.GetSource()) {
+ for (QT3DSU32 idx = 0, end = m_Configuration.size(); idx < end; ++idx)
+ if (IsDescendant(*ancestor, *m_Configuration[idx]))
+ m_StatesToExit.insert(m_Configuration[idx]);
+ }
+ }
+
+ /*
+ for s in m_StatesToExit:
+ statesToInvoke.delete(s)
+ */
+
+ SortByDocumentOrder(m_StatesToExit.m_List);
+ DEBUGGER_CALL1(SetExitSet, m_StatesToExit);
+ // Run through the list in reverse order.
+ for (nvvector<SStateNode *>::reverse_iterator iter = m_StatesToExit.m_List.rbegin(),
+ end = m_StatesToExit.m_List.rend();
+ iter != end; ++iter) {
+#ifdef UIC_LOG_ENTER_EXIT
+ qCInfo(TRACE_INFO, "Exiting state: %s", (*iter)->m_Id.c_str());
+#endif
+ TStateNodeList *children = (*iter)->GetChildren();
+ if (children) {
+ for (TStateNodeList::iterator iter = children->begin(), end = children->end();
+ iter != end; ++iter) {
+ if (iter->m_Type == StateNodeTypes::History) {
+ SHistory &theHistory = *iter->CastTo<SHistory>();
+ FreeHistoryData(theHistory);
+ TStateNodeNodeList &theHistoryData = GetOrCreateHistoryData(theHistory);
+
+ if (theHistory.m_Parent == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ // If deep, then record the leaves
+ if (theHistory.m_Flags.IsDeep()) {
+ for (TStateNodeSet::iterator configIter = m_Configuration.begin(),
+ configEnd = m_Configuration.end();
+ configIter != configEnd; ++configIter) {
+ if ((*configIter)->IsAtomic()
+ && IsDescendant(*theHistory.m_Parent, **configIter))
+ theHistoryData.push_back(*m_StateNodeNodePool.construct(
+ *configIter, __FILE__, __LINE__));
+ }
+ }
+ // Else record what may be branches.
+ else {
+ for (TStateNodeSet::iterator configIter = m_Configuration.begin(),
+ configEnd = m_Configuration.end();
+ configIter != configEnd; ++configIter) {
+ if ((*configIter)->m_Parent == theHistory.m_Parent)
+ theHistoryData.push_back(*m_StateNodeNodePool.construct(
+ *configIter, __FILE__, __LINE__));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (nvvector<SStateNode *>::reverse_iterator iter = m_StatesToExit.m_List.rbegin(),
+ end = m_StatesToExit.m_List.rend();
+ iter != end; ++iter) {
+ SStateNode *theState = *iter;
+ TOnExitList *theExitList = theState->GetOnExitList();
+ if (theExitList)
+ m_ExecutionContext->Execute(*theState, *theExitList);
+ for (QT3DSU32 idx = 0, end = m_SignalSenders.size(); idx < end; ++idx)
+ m_SignalSenders[idx]->m_Handler.OnInterpreterEvent(InterpreterEventTypes::StateExit,
+ theState->m_Id);
+ EraseState(m_StatesToInvoke, theState);
+ m_Configuration.erase(theState);
+ }
+ }
+
+ void EnterAncestor(SStateNode &inNode)
+ {
+ m_StatesToEnter.insert(&inNode);
+ if (inNode.m_Type == StateNodeTypes::Parallel) {
+ SParallel *anc = inNode.CastTo<SParallel>();
+ for (TStateNodeList::iterator childIter = anc->m_Children.begin(),
+ endChild = anc->m_Children.end();
+ childIter != endChild; ++childIter) {
+ if (!StateNodeTypes::IsStateType(childIter->m_Type))
+ continue;
+ bool hasDescendent = false;
+ for (TStateNodeSet::iterator existingIter = m_StatesToEnter.begin(),
+ existingEnd = m_StatesToEnter.end();
+ existingIter != existingEnd && hasDescendent == false; ++existingIter) {
+ hasDescendent = IsDescendant(*childIter, *(*existingIter));
+ }
+ if (hasDescendent == false)
+ AddStatesToEnter(*childIter);
+ }
+ }
+ }
+
+ void EnterAncestors(NVConstDataRef<SStateNode *> inList, SStateNode *ancestor)
+ {
+ for (QT3DSU32 idx = 0, end = inList.size(); idx < end; ++idx) {
+ NVDataRef<SStateNode *> theAncestors = GetProperAncestors(*inList[idx], ancestor);
+ for (QT3DSU32 ancIdx = 0, ancEnd = theAncestors.size(); ancIdx < ancEnd; ++ancIdx) {
+ EnterAncestor(*theAncestors[ancIdx]);
+ // Break earlier if we have gone back and included the ancestor.
+ if (theAncestors[ancIdx] == ancestor)
+ break;
+ }
+ }
+ }
+
+ void EnterStates(NVDataRef<STransition *> inTransitions)
+ {
+ m_StatesToEnter.clear();
+ m_StatesForDefaultEntry.clear();
+
+ for (QT3DSU32 idx = 0, end = inTransitions.size(); idx < end; ++idx) {
+ STransition &transition = *inTransitions[idx];
+ NVConstDataRef<SStateNode *> theList = GetRefList(transition.m_Target);
+ if (transition.GetSource() == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ // Multi-target transitions present their own set of problems. One is that a perfectly
+ // valid
+ // multi-target transition may
+ if (theList.size() > 1) {
+ m_TransitionTargetList.clear();
+ // We have to ensure that if two targets are directly related, we take the most
+ // derived one.
+ for (QT3DSU32 targetIdx = 0, targetEnd = theList.size(); targetIdx < targetEnd;
+ ++targetIdx) {
+ SStateNode *nextTarget = theList[targetIdx];
+ for (QT3DSU32 takenTargetListIdx = 0,
+ takenTargetListEnd = m_TransitionTargetList.size();
+ takenTargetListIdx < takenTargetListEnd && nextTarget;
+ ++takenTargetListIdx) {
+ SStateNode *previousTarget = m_TransitionTargetList[takenTargetListIdx];
+ // If the previous target is more descendant than the original target
+ if (IsDescendant(*nextTarget, *previousTarget)) {
+ // Then we don't need to consider next target at all and we can
+ // continue.
+ nextTarget = NULL;
+ } else if (IsDescendant(*previousTarget, *nextTarget)) {
+ // If next target derives from previous target, then we remove previous
+ // target from
+ // the list.
+ m_TransitionTargetList.erase(m_TransitionTargetList.begin()
+ + takenTargetListIdx);
+ --takenTargetListIdx;
+ takenTargetListEnd = m_TransitionTargetList.size();
+ }
+ // Else we don't care, we will add next target to the list.
+ }
+ if (nextTarget != NULL)
+ m_TransitionTargetList.push_back(nextTarget);
+ }
+ theList = m_TransitionTargetList;
+ }
+
+ for (QT3DSU32 idx = 0, end = theList.size(); idx < end; ++idx)
+ AddStatesToEnter(*theList[idx]);
+ }
+
+ for (QT3DSU32 idx = 0, end = inTransitions.size(); idx < end; ++idx) {
+ STransition &transition = *inTransitions[idx];
+ NVConstDataRef<SStateNode *> theList = GetRefList(transition.m_Target);
+
+ if (transition.GetSource() == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+
+ SStateNode *ancestor = GetTransitionSubgraphRoot(transition, theList);
+ EnterAncestors(theList, ancestor);
+ }
+ EnterStatesSecondHalf();
+ }
+
+ void EnterStatesSecondHalf()
+ {
+ nvvector<SStateNode *> &theEnterList(m_StatesToEnter.m_List);
+ SortByDocumentOrder(theEnterList);
+
+ DEBUGGER_CALL1(SetEnterSet, m_StatesToEnter);
+ for (QT3DSU32 idx = 0, end = theEnterList.size(); idx < end; ++idx) {
+ SStateNode *theEnterState(theEnterList[idx]);
+#ifdef UIC_LOG_ENTER_EXIT
+ qCInfo(TRACE_INFO, "Entering state: %s", theEnterState->m_Id.c_str());
+#endif
+ m_Configuration.insert(theEnterState);
+ m_StatesToInvoke.push_back(theEnterState);
+ SStateNodeInterpreterData &theData = GetOrCreateInterpreterData(*theEnterState);
+ if (theData.m_Entered == false) {
+ theData.m_Entered = true;
+ if (m_Context->GetRoot()->m_Flags.IsLateBinding()) {
+ SDataModel *theDataModel = theEnterState->GetDataModel();
+ if (theDataModel)
+ RunDataModel(*theDataModel);
+ }
+ }
+
+ TOnEntryList *theList = theEnterState->GetOnEntryList();
+ if (theList)
+ m_ExecutionContext->Execute(*theEnterState, *theList);
+ for (QT3DSU32 idx = 0, end = m_SignalSenders.size(); idx < end; ++idx)
+ m_SignalSenders[idx]->m_Handler.OnInterpreterEvent(
+ InterpreterEventTypes::StateEnter, theEnterState->m_Id);
+
+ if (m_StatesForDefaultEntry.contains(theEnterState)) {
+ SState *theState = theEnterState->CastTo<SState>();
+ if (theState && IsTransitionValid(theState->m_Initial))
+ m_ExecutionContext->Execute(*theState->m_Initial);
+ }
+ if (theEnterState->m_Type == StateNodeTypes::Final) {
+ SStateNode *parent = theEnterState->m_Parent;
+ SStateNode *grandparent = parent->m_Parent;
+ if (parent && grandparent) {
+ m_Workspace.assign("done.state.");
+ m_Workspace.append(parent->m_Id);
+
+ // TODO - donedata
+ QueueEvent(m_Workspace.c_str(), false);
+
+ if (grandparent && grandparent->m_Type == StateNodeTypes::Parallel
+ && AllChildrenInFinalStates(*grandparent)) {
+ m_Workspace.assign("done.state.");
+ m_Workspace.append(grandparent->m_Id);
+ QueueEvent(m_Workspace.c_str(), false);
+ }
+ }
+ }
+ }
+
+ if (IsInFinalState(m_Context->GetRoot()))
+ m_Running = false;
+ SortConfiguration();
+ }
+
+ bool InConfiguration(SStateNode &inState)
+ {
+ return eastl::find(m_Configuration.begin(), m_Configuration.end(), &inState)
+ != m_Configuration.end();
+ }
+
+ bool IsInFinalState(SStateNode &inState)
+ {
+ if (inState.m_Type == StateNodeTypes::State && inState.IsCompound()) {
+ SState *theState = inState.CastTo<SState>();
+ for (TStateNodeList::iterator childIter = theState->m_Children.begin(),
+ endIter = theState->m_Children.end();
+ childIter != endIter; ++childIter) {
+ if (IsInFinalState(*childIter))
+ return true;
+ }
+ } else if (inState.m_Type == StateNodeTypes::SCXML) {
+ SSCXML *theState = inState.CastTo<SSCXML>();
+ for (TStateNodeList::iterator childIter = theState->m_Children.begin(),
+ endIter = theState->m_Children.end();
+ childIter != endIter; ++childIter) {
+ if (childIter->m_Type == StateNodeTypes::Final && InConfiguration(*childIter))
+ return true;
+ }
+ } else if (inState.m_Type == StateNodeTypes::Parallel) {
+ SParallel *parallel = inState.CastTo<SParallel>();
+ for (TStateNodeList::iterator childIter = parallel->m_Children.begin(),
+ endIter = parallel->m_Children.end();
+ childIter != endIter; ++childIter) {
+ if (!IsInFinalState(*childIter))
+ return false;
+ }
+ return true;
+ } else if (inState.m_Type == StateNodeTypes::Final && InConfiguration(inState))
+ return true;
+
+ return false;
+ }
+
+ bool IsInFinalState(SStateNode *inState)
+ {
+ if (inState)
+ return IsInFinalState(*inState);
+ return false;
+ }
+
+ SStateNode *GetTransitionSubgraphRoot(STransition &inTransition,
+ NVConstDataRef<SStateNode *> inTargetList)
+ {
+ SStateNodeInterpreterData &data = GetOrCreateInterpreterData(inTransition);
+ if (data.m_TransitionSubgraphRoot != NULL)
+ return data.m_TransitionSubgraphRoot;
+ if (inTransition.GetSource() == NULL) {
+ QT3DS_ASSERT(false);
+ return NULL;
+ }
+ SStateNode &source = *inTransition.GetSource();
+ if (inTransition.m_Target.size() == 0)
+ data.m_TransitionSubgraphRoot = &source;
+ else {
+ if (inTransition.m_Flags.IsInternal() && source.IsCompound()
+ && AllAreDescendants(source, inTargetList))
+ data.m_TransitionSubgraphRoot = &source;
+ else
+ data.m_TransitionSubgraphRoot = FindLCCA(inTargetList, &source);
+ }
+
+ return data.m_TransitionSubgraphRoot;
+ }
+ SStateNode *GetTransitionSubgraphRoot(STransition &inTransition)
+ {
+ SStateNodeInterpreterData &data = GetOrCreateInterpreterData(inTransition);
+ if (data.m_TransitionSubgraphRoot != NULL)
+ return data.m_TransitionSubgraphRoot;
+
+ return GetTransitionSubgraphRoot(inTransition, GetRefList(inTransition.m_Target));
+ }
+ enum PreemptRule { AddNew, KeepExisting, ReplaceExisting };
+
+ PreemptRule IsPreempted(STransition &existing, STransition &nextTransition)
+ {
+ // Targetless transitions can get preempted and can preempt
+ SStateNode *existingRoot = GetTransitionSubgraphRoot(existing);
+ SStateNode *nextRoot = GetTransitionSubgraphRoot(nextTransition);
+ /*
+ http://www.w3.org/TR/scxml/#SelectingTransitions
+
+ A transition T is optimally enabled by event E in atomic state S if
+ a) T is enabled by E in S and
+ b) no transition that precedes T in document order in T's source state is enabled by E in S
+ and
+ c) no transition is enabled by E in S in any descendant of T's source state.
+ */
+
+ // static bool IsDescendant( SStateNode& inParent, SStateNode& inChild )
+
+ if (IsDescendant(*nextRoot, *existingRoot))
+ return KeepExisting;
+ if (IsDescendant(*existingRoot, *nextRoot))
+ return ReplaceExisting;
+
+ // Else these transactions are completely unrelated
+ return AddNew;
+ }
+
+ void FilterPreempted(TTransitionSet &inTransitionSet, TTransitionList &outTransitions)
+ {
+ outTransitions.clear();
+ for (TTransitionSet::iterator iter = inTransitionSet.begin(), end = inTransitionSet.end();
+ iter != end; ++iter) {
+ PreemptRule preempted = AddNew;
+ QT3DSU32 idx, endIdx;
+ for (idx = 0, endIdx = outTransitions.size(); idx < endIdx && preempted == AddNew;
+ ++idx)
+ preempted = IsPreempted(*outTransitions[idx], **iter);
+
+ switch (preempted) {
+ case KeepExisting: // Ignore the result.
+ break;
+ case ReplaceExisting:
+ // The iteration statement is evaluated before the exit test.
+ outTransitions[idx - 1] = *iter;
+ break;
+ case AddNew:
+ outTransitions.push_back(*iter);
+ break;
+ }
+ }
+ }
+
+ bool SelectEventlessTransitions(SStateNode &inNode, TTransitionSet &inSet)
+ {
+ TStateNodeList *theChildren = inNode.GetChildren();
+ if (theChildren == NULL) {
+ return false;
+ }
+ for (TStateNodeList::iterator iter = theChildren->begin(), end = theChildren->end();
+ iter != end; ++iter) {
+ if (iter->m_Type == StateNodeTypes::Transition) {
+ STransition &trans = *iter->CastTo<STransition>();
+ if (IsTransitionValid(&trans)) {
+ if (trans.m_Event.IsValid() == false) {
+ if (!isTrivial(trans.m_Condition)) {
+ Option<bool> condEval =
+ m_ScriptContext->ExecuteCondition(trans.m_Condition);
+ if (condEval.hasValue()) {
+ if (*condEval) {
+ inSet.insert(&trans);
+ return true;
+ }
+ } else {
+ QueueEvent("error.execution", false);
+ return false;
+ }
+ }
+ // Extension for running scxml documents with transitions with nothing but
+ // content
+ else {
+ inSet.insert(&trans);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ if (inNode.m_Parent)
+ SelectEventlessTransitions(*inNode.m_Parent, inSet);
+ return false;
+ }
+
+ // Precondition - m_Configuration is in document order.
+ // Postcondition - m_EnabledTransitions contains only the transitions selected
+ void SelectEventlessTransitions()
+ {
+ m_TransitionSet.clear();
+ static QT3DSU32 callCount = 0;
+ ++callCount;
+ for (QT3DSU32 idx = 0, end = m_Configuration.size(); idx < end; ++idx) {
+ if (idx) {
+ QT3DS_ASSERT(GetOrCreateInterpreterData(*m_Configuration[idx]).m_DocumentOrder
+ > GetOrCreateInterpreterData(*m_Configuration[idx - 1]).m_DocumentOrder);
+ }
+ if (m_Configuration[idx]->IsAtomic() == false)
+ continue;
+ SelectEventlessTransitions(*m_Configuration[idx], m_TransitionSet);
+ }
+ m_EnabledTransitions.clear();
+ FilterPreempted(m_TransitionSet, m_EnabledTransitions);
+ }
+ void SelectTransition(SStateNode &inNode, IEvent &inEvent, TTransitionSet &outTransitions)
+ {
+ TStateNodeList *theChildren = inNode.GetChildren();
+ if (theChildren) {
+ for (TStateNodeList::iterator iter = theChildren->begin(), end = theChildren->end();
+ iter != end; ++iter) {
+ if (iter->m_Type == StateNodeTypes::Transition) {
+ STransition &theTransition = *iter->CastTo<STransition>();
+ if (IsTransitionValid(theTransition)) {
+ if (theTransition.m_Event.IsValid()) {
+ if (uic::state::impl::NameMatches(theTransition.m_Event.c_str(),
+ inEvent.GetName().c_str())) {
+ if (!isTrivial(theTransition.m_Condition)) {
+ Option<bool> condResult = m_ScriptContext->ExecuteCondition(
+ theTransition.m_Condition);
+ if (condResult.hasValue()) {
+ if (*condResult) {
+ outTransitions.insert(&theTransition);
+ return;
+ }
+ } else {
+ QueueEvent("error.execution", false);
+ return;
+ }
+ } else {
+ outTransitions.insert(&theTransition);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (inNode.m_Parent)
+ SelectTransition(*inNode.m_Parent, inEvent, outTransitions);
+ }
+
+ // Precondition is that m_Configuration is in document order.
+ void SelectTransitions(IEvent &inEvent)
+ {
+ m_TransitionSet.clear();
+ for (QT3DSU32 idx = 0, end = m_Configuration.size(); idx < end; ++idx) {
+ // Ensure that m_Configuration is in document order.
+ if (idx) {
+ QT3DS_ASSERT(GetOrCreateInterpreterData(*m_Configuration[idx]).m_DocumentOrder
+ > GetOrCreateInterpreterData(*m_Configuration[idx - 1]).m_DocumentOrder);
+ }
+
+ if (!m_Configuration[idx]->IsAtomic())
+ continue;
+ SelectTransition(*m_Configuration[idx], inEvent, m_TransitionSet);
+ }
+
+ FilterPreempted(m_TransitionSet, m_EnabledTransitions);
+ }
+
+ bool Initialize(IStateContext &inContext, bool inValidateTransitions) override
+ {
+ m_Initialized = false;
+ InitializeDataStructures();
+ m_Context = inContext;
+ QT3DS_ASSERT(m_Context->GetRoot());
+ if (m_Context->GetRoot() == NULL) {
+ QT3DS_ASSERT(false);
+ m_Running = false;
+ return false;
+ }
+
+ // Disable transitions that can put us into a bad state
+ if (inValidateTransitions)
+ RecursiveValidateTransitions();
+ m_Initialized = true;
+ return true;
+ }
+ NVConstDataRef<SStateNode *> Start() override
+ {
+ if (!m_Initialized) {
+ QT3DS_ASSERT(false);
+ return NVConstDataRef<SStateNode *>();
+ }
+ m_Running = true;
+ SSCXML &rootState = *m_Context->GetRoot();
+ if (!rootState.m_Flags.IsLateBinding())
+ RecursiveInitializeDataModel();
+ eastl::string theSendLocExpr;
+ NVConstDataRef<SSend *> theSendData = m_Context->GetSendList();
+ for (QT3DSU32 idx = 0, end = theSendData.size(); idx < end; ++idx) {
+ SSend &theSend(*theSendData[idx]);
+ if (!isTrivial(theSend.m_IdLocation)) {
+ QT3DS_ASSERT(theSend.m_Id.IsValid());
+ m_ScriptContext->AssignStr(theSend.m_IdLocation, theSend.m_Id.c_str());
+ }
+ }
+
+ STransition *initialTrans = this->GetStateInitialTransition(rootState);
+ if (IsTransitionValid(initialTrans)) {
+ m_Configuration.insert(&rootState);
+ m_ExecutionContext->Execute(*initialTrans);
+ AddStatesToEnter(rootState);
+ EnterAncestors(initialTrans->m_Target, &rootState);
+ QT3DS_ASSERT(m_EnabledTransitions.empty());
+ m_EnabledTransitions.clear();
+ m_EnabledTransitions.push_back(initialTrans);
+ DEBUGGER_CALL1(SetTransitionSet, m_EnabledTransitions);
+ m_EnabledTransitions.clear();
+ EnterStatesSecondHalf();
+ ReleaseInitialAndTemporaryTransitions();
+ DEBUGGER_CALL(EndMicrostep);
+ DEBUGGER_CALL(EndStep);
+ } else {
+ m_Running = false;
+ qFatal("Invalid state machine: root initial configuration is invalid");
+ }
+ return m_Configuration.m_List;
+ }
+
+ void Microstep(TTransitionList &inTransitions)
+ {
+ DEBUGGER_CALL1(SetTransitionSet, inTransitions);
+ ExitStates(inTransitions);
+ for (QT3DSU32 idx = 0, end = inTransitions.size(); idx < end; ++idx) {
+ m_ExecutionContext->Execute(*inTransitions[idx]);
+ for (QT3DSU32 sigIdx = 0, sigEnd = m_SignalSenders.size(); sigIdx < sigEnd; ++sigIdx)
+ m_SignalSenders[sigIdx]->m_Handler.OnInterpreterEvent(
+ InterpreterEventTypes::Transition, inTransitions[idx]->m_Id);
+ }
+
+ EnterStates(inTransitions);
+ // Allow them to be selected again at some point.
+ inTransitions.clear();
+ ReleaseInitialAndTemporaryTransitions();
+ DEBUGGER_CALL(EndMicrostep);
+ }
+
+ void CheckForDelayedEvents()
+ {
+ QT3DSU64 currentTime = Time::getCurrentTimeInTensOfNanoSeconds();
+ TFutureEventList::iterator removeIter = m_FutureEvents.begin();
+ TFutureEventList::iterator endIter = m_FutureEvents.end();
+ // Future events list is sorted so all we have to do is iterate forward until
+ // fire time is greater than current time.
+
+ for (; removeIter != endIter && removeIter->m_FireTime < currentTime; ++removeIter) {
+ }
+ // remove iter points either to the end or to the first event who's time has come.
+ for (TFutureEventList::iterator evtIter = m_FutureEvents.begin(); evtIter != removeIter;
+ ++evtIter) {
+ qCInfo(TRACE_INFO, "Sending delayed event: %s", evtIter->m_Event->GetName().c_str());
+ QT3DS_ASSERT(evtIter->m_FireTime <= currentTime);
+ QueueEvent(evtIter->m_Event, evtIter->m_IsExternal);
+ }
+ if (removeIter != m_FutureEvents.begin()) {
+ m_FutureEvents.erase(m_FutureEvents.begin(), removeIter);
+ }
+ }
+
+ bool CheckForStable()
+ {
+ CheckForDelayedEvents();
+ if (m_EnabledTransitions.empty()) {
+ m_ScriptContext->ClearCurrentEvent();
+ DEBUGGER_CALL(BeginMicrostep);
+ SelectEventlessTransitions();
+ }
+
+ return m_EnabledTransitions.empty() && m_InternalQueue.empty() && m_ExternalQueue.empty();
+ }
+
+ // Execute these events, return what state you are in.
+ // We process all internal and all external events before returning, so you are free to
+ // free or just deal with all userdata after this.
+ NVConstDataRef<SStateNode *> Execute() override
+ {
+ if (m_Running == false)
+ return m_Configuration.m_List;
+
+ DEBUGGER_CALL(BeginStep);
+ DEBUGGER_CALL(BeginMicrostep);
+
+ m_EnabledTransitions.clear();
+
+ QT3DSU32 iterationCount = 0;
+ QT3DSU32 MAX_ITERATION_COUNT = 1000;
+
+ // Here we handle eventless transitions and transitions
+ // triggered by internal events until machine is stable
+ while (iterationCount < MAX_ITERATION_COUNT && m_Running && !CheckForStable()) {
+ ++iterationCount;
+ if (m_EnabledTransitions.empty() == false) {
+ Microstep(m_EnabledTransitions);
+ DEBUGGER_CALL(BeginMicrostep);
+ } else if (m_InternalQueue.empty() == false) {
+ NVScopedRefCounted<IEvent> theEvent = m_InternalQueue.front();
+ m_ScriptContext->SetCurrentEvent(theEvent);
+ m_InternalQueue.pop_front();
+ DEBUGGER_CALL2(SetCurrentEvent, theEvent->GetName().c_str(), true);
+#ifdef UIC_LOG_ACTIVE_EVENT
+ qCInfo(TRACE_INFO, "Current event: %s", theEvent->GetName().c_str());
+#endif
+ SelectTransitions(*theEvent);
+ } else if (m_ExternalQueue.empty() == false) {
+ NVScopedRefCounted<IEvent> theEvent = m_ExternalQueue.front();
+ m_ScriptContext->SetCurrentEvent(theEvent);
+ m_ExternalQueue.pop_front();
+
+ DEBUGGER_CALL2(SetCurrentEvent, theEvent->GetName().c_str(), false);
+
+#ifdef UIC_LOG_ACTIVE_EVENT
+ qCInfo(TRACE_INFO, "Current event: %s", theEvent->GetName().c_str());
+#endif
+
+ /*
+ if isCancelEvent(externalEvent)
+ running = false
+ continue
+ */
+
+ // TODO datamodel
+ // datamodel["_event"] = theEvent;
+
+ // TODO invoke
+ /*
+ for state in configuration:
+ for inv in state.invoke:
+ if inv.invokeid == externalEvent.invokeid:
+ applyFinalize(inv, externalEvent)
+ if inv.autoforward:
+ send(inv.id, externalEvent)
+ */
+ SelectTransitions(*theEvent);
+ }
+ }
+ if (m_Running == false) {
+ for (nvvector<SStateNode *>::reverse_iterator iter = m_Configuration.m_List.rbegin(),
+ end = m_Configuration.m_List.rend();
+ iter != end; ++iter) {
+ TOnExitList *theExitList = (*iter)->GetOnExitList();
+ if (theExitList)
+ m_ExecutionContext->Execute(**iter, *theExitList);
+ /*
+ for inv in s.invoke:
+ cancelInvoke(inv)
+ */
+
+ // Set final done data.
+ /*
+ if isFinalState(s) and isScxmlState(s.parent):
+ returnDoneEvent(s.donedata)
+ */
+ }
+ }
+ DEBUGGER_CALL(EndStep);
+ return m_Configuration.m_List;
+ }
+
+ bool EventsPending() const override
+ {
+ return m_InternalQueue.empty() == false || m_ExternalQueue.empty() == false
+ || m_FutureEvents.empty() == false;
+ }
+
+ bool IsRunning() const override { return m_Running; }
+
+ void QueueEvent(const char8_t *inEventName, QT3DSU64 inDelay, CRegisteredString inCancelId,
+ bool inIsExternal) override
+ {
+ TEventPtr theEvent = QT3DS_NEW(m_Foundation.getAllocator(), SSimpleEvent)(
+ m_Foundation.getAllocator(), m_StringTable->RegisterStr(inEventName));
+ QueueEvent(theEvent, inDelay, inCancelId, inIsExternal);
+ }
+
+ void QueueEvent(TEventPtr inEvent, QT3DSU64 inDelay, CRegisteredString inCancelId,
+ bool inIsExternal) override
+ {
+ if (inDelay == 0) {
+ QueueEvent(inEvent, inIsExternal);
+ } else {
+ static QT3DSU64 sTensOfNanoSecondsInAMillisecond =
+ Time::sNumTensOfNanoSecondsInASecond / 1000;
+ QT3DSU64 fireTime = Time::getCurrentTimeInTensOfNanoSeconds()
+ + inDelay * sTensOfNanoSecondsInAMillisecond;
+ SFutureEvent theNewEvent(inEvent, fireTime, inCancelId, inIsExternal);
+ TFutureEventList::iterator iter =
+ eastl::upper_bound(m_FutureEvents.begin(), m_FutureEvents.end(), theNewEvent);
+ m_FutureEvents.insert(iter, theNewEvent);
+ }
+ }
+
+ void QueueEvent(TEventPtr inEvent, bool inIsExternal) override
+ {
+ if (inIsExternal)
+ m_ExternalQueue.push_back(inEvent);
+ else
+ m_InternalQueue.push_back(inEvent);
+ DEBUGGER_CALL2(EventQueued, inEvent->GetName().c_str(), inIsExternal);
+ }
+
+ void QueueEvent(const char8_t *inEventName, bool inIsExternal) override
+ {
+ TEventPtr theEvent = QT3DS_NEW(m_Foundation.getAllocator(), SSimpleEvent)(
+ m_Foundation.getAllocator(), m_StringTable->RegisterStr(inEventName));
+ QueueEvent(theEvent, inIsExternal);
+ }
+
+ void CancelEvent(CRegisteredString inCancelId) override
+ {
+ if (inCancelId.IsValid() == false)
+ return;
+ qCInfo(TRACE_INFO, "Cancel of id %s requested", inCancelId.c_str());
+ for (QT3DSU32 idx = 0; idx < m_FutureEvents.size(); ++idx) {
+ if (m_FutureEvents[idx].m_CancelId == inCancelId) {
+ TFutureEventList::iterator iter = m_FutureEvents.begin() + idx;
+ qCInfo(TRACE_INFO, "Cancelling event: %s, %s",
+ iter->m_Event->GetName().c_str(), iter->m_CancelId.c_str());
+ m_FutureEvents.erase(iter);
+ --idx;
+ }
+ }
+ }
+
+ TSignalConnectionPtr RegisterEventHandler(IStateInterpreterEventHandler &inHandler) override
+ {
+ SStateSignalSender *sender = QT3DS_NEW(m_Foundation.getAllocator(), SStateSignalSender)(
+ m_Foundation.getAllocator(), *this, inHandler);
+ m_SignalSenders.push_back(sender);
+ return sender;
+ }
+
+ IScriptContext &GetScriptContext() override { return *m_ScriptContext; }
+
+ IStateContext *GetStateContext() override { return m_Context; }
+
+ debugger::IStateMachineDebugInterface &GetDebugInterface() override { return m_DebugInterface; }
+
+ NVFoundationBase &GetFoundation() override { return m_Foundation; }
+};
+
+////////////////////////////////////////////////////////////////////////////////////
+// SDebugInterface implementation
+////////////////////////////////////////////////////////////////////////////////////
+
+void SDebugInterface::addRef()
+{
+ m_StateSystem.addRef();
+}
+
+void SDebugInterface::release()
+{
+ m_StateSystem.release();
+}
+
+struct SDebugStrOutStream : public IOutStream
+{
+ TDebugStr m_Str;
+ bool Write(NVConstDataRef<QT3DSU8> data) override
+ {
+ m_Str.append((char8_t *)data.begin(), (char8_t *)data.end());
+ return true;
+ }
+};
+
+NVConstDataRef<TDebugStr> ListToRef(const nvvector<SStateNode *> &inList, TDebugStrList &outData)
+{
+ outData.resize(inList.size());
+ for (QT3DSU32 idx = 0, end = inList.size(); idx < end; ++idx)
+ outData[idx].assign(nonNull(inList[idx]->m_Id.c_str()));
+ return toConstDataRef(outData.data(), outData.size());
+}
+
+IScriptContext &SDebugInterface::GetScriptContext()
+{
+ return *m_StateSystem.m_ScriptContext.mPtr;
+}
+
+// Functions implemented after StateSystem in order to take advantage of the StateSystem struct
+// members directly.
+void SDebugInterface::OnConnect()
+{
+ TDebugStr theFilename;
+ SDebugStrOutStream theOutStream;
+ if (m_StateSystem.m_Context->GetRoot())
+ theFilename.assign(nonNull(m_StateSystem.m_Context->GetRoot()->m_Filename));
+ CXMLIO::SaveSCXMLFile(*m_StateSystem.m_Context, m_StateSystem.m_Foundation,
+ *m_StateSystem.m_StringTable, theOutStream);
+ m_Listener->OnConnect(theFilename, theOutStream.m_Str,
+ ListToRef(m_StateSystem.m_Configuration.m_List, m_EnterList));
+}
+
+// Functions should not be called in there is not a valid listener
+void SDebugInterface::BeginStep()
+{
+ m_Listener->BeginStep();
+}
+
+void SDebugInterface::BeginMicrostep()
+{
+ m_Listener->BeginMicroStep();
+}
+
+void SDebugInterface::SetCurrentEvent(const char8_t *inEventName, bool inInternal)
+{
+ m_TempStr.assign(nonNull(inEventName));
+ m_Listener->SetEvent(m_TempStr, inInternal);
+}
+
+STransitionId TransitionToId(const STransition &inTransition)
+{
+ SStateNode *parent(inTransition.m_Parent);
+ STransitionId retval;
+ if (parent == NULL) {
+ QT3DS_ASSERT(false);
+ return retval;
+ }
+
+ retval.m_StateId.assign(nonNull(parent->m_Id.c_str()));
+ if (&inTransition == parent->GetInitialTransition())
+ retval.m_TransitionIndex = -1;
+ else if (parent->m_Type == StateNodeTypes::History) {
+ SHistory &theHistory = static_cast<SHistory &>(*parent);
+ if (&inTransition == theHistory.m_Transition)
+ retval.m_TransitionIndex = -1;
+ }
+
+ if (retval.m_TransitionIndex == -2) {
+ TStateNodeList *childList = parent->GetChildren();
+ if (childList) {
+ QT3DSI32 index = 0;
+ for (TStateNodeList::iterator iter = childList->begin(), end = childList->end();
+ iter != end && retval.m_TransitionIndex == -2; ++iter, ++index) {
+ SStateNode &theNode(*iter);
+ if (theNode.m_Type == StateNodeTypes::Transition && &inTransition == (&theNode))
+ retval.m_TransitionIndex = index;
+ }
+ }
+ }
+
+ return retval;
+}
+
+void SDebugInterface::SetTransitionSet(const TTransitionList &inTransitions)
+{
+ m_TransitionList.resize(inTransitions.size());
+ for (QT3DSU32 idx = 0, end = inTransitions.size(); idx < end; ++idx)
+ m_TransitionList[idx] = TransitionToId(*inTransitions[idx]);
+ m_Listener->SetTransitionSet(toDataRef(m_TransitionList.data(), m_TransitionList.size()));
+}
+
+void SDebugInterface::SetExitSet(const TStateNodeSet &inSet)
+{
+ NVConstDataRef<TDebugStr> theSet(ListToRef(inSet.m_List, this->m_ExitList));
+ m_Listener->SetExitSet(theSet);
+}
+void SDebugInterface::SetEnterSet(const TStateNodeSet &inSet)
+{
+ NVConstDataRef<TDebugStr> theSet(ListToRef(inSet.m_List, this->m_EnterList));
+ m_Listener->SetEnterSet(theSet);
+}
+// Log statements run through the debugger as well.
+void SDebugInterface::EndMicrostep()
+{
+ m_Listener->EndMicroStep();
+}
+void SDebugInterface::EndStep()
+{
+ m_Listener->EndStep();
+}
+
+void SDebugInterface::OnExternalBreak()
+{
+ if (m_Listener)
+ m_Listener->OnExternalBreak();
+}
+
+SStateSignalSender::~SStateSignalSender()
+{
+ if (m_System) {
+ m_System->m_SignalSenders.erase(
+ eastl::find(m_System->m_SignalSenders.begin(), m_System->m_SignalSenders.end(), this));
+ }
+}
+}
+
+IStateInterpreter &IStateInterpreter::Create(NVFoundationBase &inFnd, IStringTable &inStrTable,
+ IScriptContext &inScriptContext,
+ IExecutionContext &inExecutionContext)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), StateSystem)(inFnd, inStrTable, inScriptContext,
+ inExecutionContext);
+}
diff --git a/src/Runtime/Source/UICState/Source/UICStateLuaScriptContext.cpp b/src/Runtime/Source/UICState/Source/UICStateLuaScriptContext.cpp
new file mode 100644
index 00000000..bfaa7f5e
--- /dev/null
+++ b/src/Runtime/Source/UICState/Source/UICStateLuaScriptContext.cpp
@@ -0,0 +1,1412 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateLuaScriptContext.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSIntrinsics.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Utils.h"
+#include "foundation/StringTable.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "foundation/TrackingAllocator.h"
+#include "UICStateExecutionContext.h"
+#include "UICStateInterpreter.h"
+#include "EASTL/string.h"
+#include "EASTL/map.h"
+#include "EASTL/hash_map.h"
+#include "EASTL/hash_set.h"
+#include "UICStateXMLIO.h"
+#include "foundation/XML.h"
+#include "foundation/IOStreams.h"
+#include "UICStateDebugger.h"
+#include "UICStateDebuggerValues.h"
+#include "UICStateContext.h"
+extern "C" {
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+}
+
+using namespace uic::state;
+using namespace uic::state::debugger;
+
+namespace {
+struct STopScope
+{
+ lua_State *m_LuaState;
+ int m_Top;
+ STopScope(lua_State *inState)
+ : m_LuaState(inState)
+ , m_Top(lua_gettop(inState))
+ {
+ }
+ ~STopScope() { lua_settop(m_LuaState, m_Top); }
+};
+
+struct SScriptContext;
+
+struct SLuaScriptEvent : public IScriptEvent
+{
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<SScriptContext> m_Context;
+ QT3DSI32 m_Id;
+ volatile QT3DSI32 mRefCount;
+
+ static const char *StaticType() { return "Lua Script Event"; }
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ SLuaScriptEvent(SScriptContext &inContext, QT3DSI32 inId, CRegisteredString inName);
+ virtual ~SLuaScriptEvent();
+
+ CRegisteredString RegisterString(const char8_t *inStr);
+ void GetEventTable();
+ void GetDataTable();
+ // new table is top of stack.
+ // popped off by function.
+ void SetDataTable();
+ CRegisteredString GetName() const override;
+ CRegisteredString GetEventType() const override;
+ bool SetParam(CRegisteredString inName, const char8_t *inExpression) override;
+ bool SetParamStr(CRegisteredString inName, const char8_t *inExpression) override;
+ bool SetDataExpr(const char8_t *inExpression) override;
+ bool SetDataStr(const char8_t *inStr) override;
+};
+
+struct SScriptContext : public ILuaScriptContext
+{
+ typedef nvhash_map<size_t, int, eastl::hash<size_t>, eastl::equal_to<size_t>> TStrIntMap;
+ typedef eastl::map<TDebugStr, SDatamodelValue> TDataModelTable;
+ typedef eastl::hash_map<SDatamodelTable *, TDataModelTable> TTableMap;
+ typedef eastl::hash_set<SDatamodelTable *> TTableHashSet;
+
+ NVFoundationBase &m_Foundation;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ QT3DSI32 mRefCount;
+ lua_State *m_LuaState;
+ const char8_t *m_CurPtr;
+ const char8_t *m_EndPtr;
+ // Index into the compiled scripts array for this str ptr.
+ TStrIntMap m_CompiledCodeMap;
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+ TStrType m_Workspace;
+ TStrType m_Script;
+ TStrType m_ErrorString;
+ TStrType m_Id;
+ IStateInterpreter *m_Interpreter;
+ char8_t m_ContextName[256];
+ bool m_OwnsLuaState;
+ TDebugStr m_TempDebugStr;
+ TTableMap m_TableMap;
+ // Set ensures we don't visit the same table twice during update tables.
+ TTableHashSet m_VisitedTables;
+ QT3DSI32 m_NextScriptId;
+
+ static void *LuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize)
+ {
+ SScriptContext *ctx = reinterpret_cast<SScriptContext *>(ud);
+ if (nsize == 0) {
+ if (ptr)
+ ctx->m_Foundation.getAllocator().deallocate(ptr);
+ return NULL;
+ } else {
+ if (nsize < osize && ptr)
+ return ptr;
+
+ void *newMem =
+ ctx->m_Foundation.getAllocator().allocate(nsize, "lua memory", __FILE__, __LINE__);
+ if (osize && ptr) {
+ size_t copyAmt = NVMin(osize, nsize);
+ memCopy(newMem, ptr, (QT3DSU32)copyAmt);
+ ctx->m_Foundation.getAllocator().deallocate(ptr);
+ }
+ return newMem;
+ }
+ }
+
+ static const char *LuaReader(lua_State * /*state*/, void *data, size_t *size)
+ {
+ SScriptContext *ctx = reinterpret_cast<SScriptContext *>(data);
+ const char *retval = (const char *)ctx->m_CurPtr;
+ *size = ctx->m_EndPtr - ctx->m_CurPtr;
+ ctx->m_CurPtr = ctx->m_EndPtr;
+ if (*size == 0)
+ retval = NULL;
+ return retval;
+ }
+
+ struct SNodeFinder
+ {
+ CRegisteredString m_Name;
+ SNodeFinder(CRegisteredString nm)
+ : m_Name(nm)
+ {
+ }
+ bool operator()(const SStateNode *inNode) const { return inNode->m_Id == m_Name; }
+ };
+
+ bool In(const char8_t *inStateName)
+ {
+ NVConstDataRef<SStateNode *> nodes = m_Interpreter->GetConfiguration();
+ CRegisteredString name = m_StringTable->RegisterStr(inStateName);
+ SStateNode *const *theFind = eastl::find_if(nodes.begin(), nodes.end(), SNodeFinder(name));
+ return theFind != nodes.end();
+ }
+
+ static int LuaIn(lua_State *state)
+ {
+ int numargs = lua_gettop(state);
+ QT3DS_ASSERT(numargs >= 2);
+ if (numargs >= 2) {
+ void *ctx = lua_touserdata(state, 1);
+ SScriptContext *context = reinterpret_cast<SScriptContext *>(ctx);
+ if (context != NULL && context->m_Interpreter != NULL) {
+ const char *stateName = lua_tostring(state, 2);
+ bool findResult = context->In(stateName);
+ lua_pushboolean(state, (int)findResult);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ struct SScopedStackTop
+ {
+ lua_State *m_LuaState;
+ int m_Top;
+ SScopedStackTop(lua_State *inState)
+ : m_LuaState(inState)
+ , m_Top(lua_gettop(inState))
+ {
+ }
+ ~SScopedStackTop() { lua_settop(m_LuaState, m_Top); }
+ };
+
+ void GetScriptCacheTable()
+ {
+ int top = lua_gettop(m_LuaState);
+ GetGlobalTable();
+ lua_getfield(m_LuaState, -1, "uicstate_scriptcache");
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1); // pop the nil
+ lua_newtable(m_LuaState);
+ lua_pushvalue(m_LuaState, -1); // dup the table
+ // stack layout -
+ // newtable,newtable,globaltable
+ // store it in our global table.
+ lua_setfield(m_LuaState, -3, "uicstate_scriptcache");
+ }
+ // stack layout - newtable, globaltable
+ // pop the global table off now that we have the script cache table.
+ lua_insert(m_LuaState, -2);
+ lua_pop(m_LuaState, 1);
+ QT3DS_ASSERT(lua_gettop(m_LuaState) == top + 1);
+ (void)top;
+ }
+
+ void InitLuaState(int inGlobalTableIdx)
+ {
+ SScopedStackTop __initTop(m_LuaState);
+
+ if (inGlobalTableIdx)
+ lua_pushvalue(m_LuaState, inGlobalTableIdx);
+ else {
+ const char *initScript = "local P = {} \n"
+ "setmetatable(P, {__index = _G})\n"
+ "return P\n";
+ luaL_loadstring(m_LuaState, initScript);
+ int callResult = lua_pcall(m_LuaState, 0, 1, 0);
+ if (callResult) {
+ qCCritical(INTERNAL_ERROR, "Error initializing lua state: %s", lua_tostring(m_LuaState, -1));
+ }
+ }
+
+ int theType = lua_type(m_LuaState, -1);
+ (void)theType;
+
+ // setup the global table
+ lua_pushcfunction(m_LuaState, LuaIn);
+ lua_setfield(m_LuaState, -2, "__InImpl");
+
+ const char *inScript = "local inFunc = function(stateName)\n"
+ " return __InImpl(uicstate_scriptcontext, stateName)\n"
+ " end\n"
+ "return inFunc\n";
+ luaL_loadstring(m_LuaState, inScript);
+ int callResult = lua_pcall(m_LuaState, 0, 1, 0);
+ if (callResult) {
+ qCCritical(INTERNAL_ERROR, "Error initializing lua state: %s", lua_tostring(m_LuaState, -1));
+ }
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -1));
+ // set the function wrapper to that script.
+ lua_setfield(m_LuaState, -2, "In");
+ lua_pushlightuserdata(m_LuaState, this);
+ lua_setfield(m_LuaState, -2, "uicstate_scriptcontext");
+
+ // Set the function environment for the lua table.
+ int top = lua_gettop(m_LuaState);
+ lua_getfield(m_LuaState, -1, "In");
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -1));
+ lua_pushvalue(m_LuaState, -2);
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -2));
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ // set the environment of the 'In' function to be the 'P' table.
+ lua_setfenv(m_LuaState, -2);
+ lua_pop(m_LuaState, 1);
+ QT3DS_ASSERT(top == lua_gettop(m_LuaState));
+
+ // store the global table somewhere we can get to it. WE get the global table of all lua
+ // contexts
+ lua_getfield(m_LuaState, LUA_REGISTRYINDEX, "uicstate_luacontexts");
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1);
+ lua_newtable(m_LuaState);
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, LUA_REGISTRYINDEX, "uicstate_luacontexts");
+ }
+ (void)top;
+ // move the table of all lua contexts before the global table.
+ lua_insert(m_LuaState, -2);
+ // store the global table in the master table of all lua contexts
+ sprintf(m_ContextName, "%p", (void *)this);
+ lua_setfield(m_LuaState, -2, m_ContextName);
+ }
+
+ SScriptContext(NVFoundationBase &inFnd, IStringTable &inStrTable, lua_State *inState = NULL,
+ int inGlobalTableIdx = 0)
+ : m_Foundation(inFnd)
+ , m_StringTable(inStrTable)
+ , mRefCount(0)
+ , m_CurPtr(NULL)
+ , m_EndPtr(NULL)
+ , m_CompiledCodeMap(inFnd.getAllocator(), "SScriptContext::m_CompiledCodeMap")
+ , m_Workspace(ForwardingAllocator(inFnd.getAllocator(), "SScriptContext::m_Workspace"))
+ , m_Script(ForwardingAllocator(inFnd.getAllocator(), "SScriptContext::m_Script"))
+ , m_ErrorString(ForwardingAllocator(inFnd.getAllocator(), "SScriptContext::m_ErrorString"))
+ , m_Id(ForwardingAllocator(inFnd.getAllocator(), "SScriptContext::m_Id"))
+ , m_Interpreter(NULL)
+ , m_NextScriptId(1)
+ {
+ if (inState) {
+ m_LuaState = inState;
+ m_OwnsLuaState = false;
+ } else {
+ m_LuaState = lua_newstate(LuaAlloc, this);
+ luaL_openlibs(m_LuaState);
+ m_OwnsLuaState = true;
+ }
+ InitLuaState(inGlobalTableIdx);
+ }
+
+ ~SScriptContext()
+ {
+ if (m_LuaState && m_OwnsLuaState)
+ lua_close(m_LuaState);
+ m_LuaState = NULL;
+ }
+
+ void SetId(const char8_t *inId) { m_Id.assign(nonNull(inId)); }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void GetGlobalTable(lua_State *inState)
+ {
+ lua_getfield(inState, LUA_REGISTRYINDEX, "uicstate_luacontexts");
+ lua_getfield(inState, -1, m_ContextName);
+ lua_insert(inState, -2);
+ // pop the registery table off the system.
+ lua_pop(inState, 1);
+ }
+ // get the global table and leave it on top ofthe stack.
+ void GetGlobalTable() override { GetGlobalTable(m_LuaState); }
+
+ // Compile a script. If returns true, compiled script is top of stack
+ bool CompileScript(const char8_t *inScript, bool withRet = true)
+ {
+ if (inScript && *inScript) {
+ m_Script.assign(inScript);
+ if (withRet) {
+ if (m_Script.find("return ") != 0)
+ m_Script.insert(0, "return ");
+ }
+
+ int top = lua_gettop(m_LuaState);
+ int loadResult = luaL_loadstring(m_LuaState, m_Script.c_str());
+ top = lua_gettop(m_LuaState);
+ if (loadResult != 0) {
+ m_ErrorString.assign("Failed to compile ");
+ m_ErrorString.append(inScript);
+ m_ErrorString.append(": ");
+ m_ErrorString.append(lua_tostring(m_LuaState, -1));
+ lua_pop(m_LuaState, 1);
+ qCCritical(INVALID_OPERATION, "%s", m_ErrorString.c_str());
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ bool ExecutePCall(const char8_t *inCond, int inArgCount, int inResultCount)
+ {
+ GetGlobalTable();
+ lua_istable(m_LuaState, -1);
+ lua_setfenv(m_LuaState, -2);
+ int pcallResult = lua_pcall(m_LuaState, inArgCount, inResultCount, 0);
+ if (pcallResult != 0) {
+ const char *errorStr = lua_tostring(m_LuaState, -1);
+ m_ErrorString.assign("Failure during execution of \"");
+ m_ErrorString.append(inCond);
+ m_ErrorString.append("\", ");
+ m_ErrorString.append(errorStr);
+ qCCritical(INVALID_OPERATION, "%s", m_ErrorString.c_str());
+ return false;
+ }
+ return true;
+ }
+
+ void ExecuteCall(int inArgCount, int inResultCount)
+ {
+ GetGlobalTable();
+ lua_istable(m_LuaState, -1);
+ lua_setfenv(m_LuaState, -2);
+ lua_call(m_LuaState, inArgCount, inResultCount);
+ }
+
+ int ExecuteStr(const char8_t *inCond, bool withRet) override
+ {
+ int originalTop = lua_gettop(m_LuaState);
+ if (GetOrCacheScript(inCond, withRet) && ExecutePCall(inCond, 0, 1))
+ return lua_gettop(m_LuaState) - originalTop;
+
+ return 0;
+ }
+
+ // Should functions returning options return othing
+ Option<bool> ExecuteCondition(const char8_t *inCond) override
+ {
+ if (inCond && *inCond) {
+ int stackSize = ExecuteStr(inCond, true);
+ if (stackSize) {
+ int boolval = lua_toboolean(m_LuaState, -1);
+ if (stackSize > 0)
+ lua_pop(m_LuaState, stackSize);
+ return boolval ? true : false;
+ }
+ }
+ return Empty();
+ }
+
+ // Used for logging.
+ SScriptExecutionResult ExecuteExpressionToString(const char8_t *inExpr) override
+ {
+ if (inExpr && *inExpr) {
+ int stackSize = ExecuteStr(inExpr, true);
+ if (stackSize) {
+ size_t strLen = 0;
+ const char8_t *str = lua_tolstring(m_LuaState, -1, &strLen);
+ if (!str)
+ str = "";
+ m_Workspace.assign(str);
+ lua_pop(m_LuaState, stackSize);
+ return SScriptExecutionResult(m_Workspace.c_str(), "");
+ }
+ return SScriptExecutionResult("", m_ErrorString.c_str());
+ }
+ return SScriptExecutionResult("", "no expression to execute");
+ }
+
+ // If return value is false, error is signaled with GetErrorInfo.
+ bool Assign(const char8_t *inVariable, const char8_t *inExpr) override
+ {
+ int top, newtop;
+ top = lua_gettop(m_LuaState);
+ int stacksize = ExecuteStr(inExpr, true);
+ if (stacksize) {
+ GetGlobalTable();
+ lua_insert(m_LuaState, -2);
+ lua_setfield(m_LuaState, -2, inVariable);
+ lua_pop(m_LuaState, 1);
+ newtop = lua_gettop(m_LuaState);
+ QT3DS_ASSERT(newtop == top);
+ return true;
+ } else
+ return false;
+ }
+
+ void AssignStr(const char8_t *inVariable, const char8_t *inStr) override
+ {
+ if (isTrivial(inVariable)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ STopScope __stack(m_LuaState);
+ GetGlobalTable();
+ lua_pushstring(m_LuaState, inStr);
+ lua_setfield(m_LuaState, -2, inVariable);
+ }
+
+ bool GetOrCacheScript(const char8_t *inScript, bool withRet)
+ {
+ TStrIntMap::iterator iter = m_CompiledCodeMap.find(reinterpret_cast<size_t>(inScript));
+ if (iter == m_CompiledCodeMap.end()) {
+ bool compilationSuccess = CompileScript(inScript, withRet);
+ if (compilationSuccess == false) {
+ m_CompiledCodeMap.insert(eastl::make_pair(reinterpret_cast<size_t>(inScript), -1));
+ return false;
+ }
+ GetScriptCacheTable();
+ int numScripts = (int)lua_objlen(m_LuaState, -1) + 1;
+ // Copy the executable to the top of the stack
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -2));
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ lua_pushvalue(m_LuaState, -2);
+ lua_rawseti(m_LuaState, -2, numScripts);
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ m_CompiledCodeMap.insert(
+ eastl::make_pair(reinterpret_cast<size_t>(inScript), numScripts));
+ // Pop the scriptcache table off the stack leaving only the executable
+ lua_rawgeti(m_LuaState, -1, numScripts);
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -1));
+ lua_pop(m_LuaState, 1);
+ lua_pop(m_LuaState, 1);
+ } else {
+ // We already failed to compile this script.
+ if (iter->second < 0)
+ return false;
+
+ GetScriptCacheTable();
+ lua_rawgeti(m_LuaState, -1, iter->second);
+ QT3DS_ASSERT(lua_isfunction(m_LuaState, -1));
+ // Move the compiled script *below* the table
+ lua_insert(m_LuaState, -2);
+ // now pop the table, leaving only the compiled script in its place.
+ lua_pop(m_LuaState, 1);
+ }
+ return true;
+ }
+
+ bool ExecuteScript(const char8_t *inScript) override
+ {
+ if (GetOrCacheScript(inScript, false))
+ return ExecutePCall(inScript, 0, 0);
+
+ return false;
+ }
+
+ void CleanupForeach()
+ {
+ // Pop the table off the stack;
+ // the lua_next would have popped the key already.
+ lua_pop(m_LuaState, 1);
+ }
+
+ // Expect a key, then value.
+ // Leaves the key on the stack.
+ void AssignForEach(const char8_t *inItem, const char8_t *inIdxVar)
+ {
+ int top = lua_gettop(m_LuaState);
+ GetGlobalTable();
+ // put the global table underneath everything
+ lua_insert(m_LuaState, -3);
+ // Set the value into the table, popping it off the stack
+ lua_setfield(m_LuaState, -3, inItem);
+ if (!isTrivial(inIdxVar)) {
+ // duplicate the key reference, we have to leave the key on the stack
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, -3, inIdxVar);
+ }
+ // push the key that is now on top of the stack under the table.
+ lua_insert(m_LuaState, -2);
+ lua_pop(m_LuaState, 1);
+ QT3DS_ASSERT(lua_gettop(m_LuaState) == top - 1);
+ (void)top;
+ }
+
+ Option<bool> BeginForeach(const char8_t *inArray, const char8_t *inItem,
+ const char8_t *inIdxVar = "") override
+ {
+ if (isTrivial(inItem) || isTrivial(inArray))
+ return false;
+ GetGlobalTable();
+ lua_getfield(m_LuaState, -1, inArray);
+ lua_insert(m_LuaState, -2);
+ // Pop the global table off the stack.
+ lua_pop(m_LuaState, 1);
+
+ if (lua_istable(m_LuaState, -1) == 0) {
+ lua_pop(m_LuaState, 1);
+ return Empty();
+ }
+
+ lua_pushnil(m_LuaState);
+
+ int success = lua_next(m_LuaState, -2);
+
+ if (!success) {
+ CleanupForeach();
+ return false;
+ }
+
+ AssignForEach(inItem, inIdxVar);
+
+ return true;
+ }
+
+ Option<bool> NextForeach(const char8_t *inItem, const char8_t *inIdxVar = "") override
+ {
+ if (lua_istable(m_LuaState, -2) == false) {
+ QT3DS_ASSERT(false);
+ return Empty();
+ }
+ int success = lua_next(m_LuaState, -2);
+
+ if (!success) {
+ CleanupForeach();
+ return false;
+ }
+
+ AssignForEach(inItem, inIdxVar);
+
+ return true;
+ }
+
+ void CancelForeach() override
+ {
+ // Called when something caused an error and we should cancel the foreach loop
+ // We should have a key and table on the stack.
+ lua_pop(m_LuaState, 2);
+ }
+
+ void SetCurrentEvent(TEventPtr inEvent) override
+ {
+ STopScope __stackScope(m_LuaState);
+ if (!inEvent) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ if (AreEqual(inEvent->GetEventType().c_str(), SLuaScriptEvent::StaticType())) {
+ SLuaScriptEvent &theEvent = static_cast<SLuaScriptEvent &>(*inEvent.mPtr);
+ theEvent.GetEventTable();
+ } else {
+ lua_newtable(m_LuaState);
+ lua_pushstring(m_LuaState, inEvent->GetName().c_str());
+ lua_setfield(m_LuaState, -2, "name");
+ }
+ QT3DS_ASSERT(lua_istable(m_LuaState, -1));
+ // End result is that the event table is top of stack
+ GetGlobalTable();
+ lua_insert(m_LuaState, -2);
+ lua_setfield(m_LuaState, -2, "_event");
+ }
+ void ClearCurrentEvent() override
+ {
+ STopScope __stackScope(m_LuaState);
+ GetGlobalTable();
+ lua_pushnil(m_LuaState);
+ lua_setfield(m_LuaState, -2, "_event");
+ }
+ // postcondition is that uicstate_scriptids[retval] == nil
+ QT3DSI32 FindUnusedScriptId()
+ {
+ STopScope __stackScope(m_LuaState);
+ GetGlobalTable();
+ lua_getfield(m_LuaState, -1, "uicstate_scriptids");
+ if (lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1);
+ lua_newtable(m_LuaState);
+ lua_pushvalue(m_LuaState, -1);
+ lua_setfield(m_LuaState, -3, "uicstate_scriptids");
+ }
+ lua_rawgeti(m_LuaState, -1, m_NextScriptId);
+ while (!lua_isnil(m_LuaState, -1)) {
+ lua_pop(m_LuaState, 1);
+ ++m_NextScriptId;
+ lua_rawgeti(m_LuaState, -1, m_NextScriptId);
+ }
+ QT3DSI32 retval = m_NextScriptId;
+ ++m_NextScriptId;
+ return retval;
+ }
+
+ // Item is expected to be at top of stack
+ // End result is that the item is still stop of stack (we don't pop the item)
+ void SetScriptIdItem(QT3DSI32 inId)
+ {
+ STopScope __stackScope(m_LuaState);
+ int topOfStack = lua_gettop(m_LuaState);
+ GetGlobalTable();
+ lua_getfield(m_LuaState, -1, "uicstate_scriptids");
+ if (!lua_istable(m_LuaState, -1)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ lua_pushvalue(m_LuaState, topOfStack);
+ lua_rawseti(m_LuaState, -2, inId);
+ }
+
+ // Returns with the script id item at the top of the stack
+ void GetScriptIdItem(QT3DSI32 inId)
+ {
+ GetGlobalTable();
+ lua_getfield(m_LuaState, -1, "uicstate_scriptids");
+ if (!lua_istable(m_LuaState, -1)) {
+ QT3DS_ASSERT(false);
+ lua_pop(m_LuaState, 2);
+ return;
+ }
+ lua_rawgeti(m_LuaState, -1, inId);
+ }
+
+ // postcondition is that uicstate_scriptids[inId] == nil
+ void ReleaseScriptIdItem(QT3DSI32 inId)
+ {
+ STopScope __stackScope(m_LuaState);
+ GetGlobalTable();
+ lua_getfield(m_LuaState, -1, "uicstate_scriptids");
+ if (!lua_isnil(m_LuaState, -1)) {
+ lua_pushnil(m_LuaState);
+ lua_rawseti(m_LuaState, -2, inId);
+ }
+ }
+ // Create an event we can attach extra data do.
+ IScriptEvent *CreateScriptEvent(CRegisteredString inName) override
+ {
+ return QT3DS_NEW(m_Foundation.getAllocator(), SLuaScriptEvent)(*this, FindUnusedScriptId(),
+ inName);
+ }
+
+ void SetInterpreter(IStateInterpreter &inInterpreter) override
+ {
+ m_Interpreter = &inInterpreter;
+ }
+
+ const char8_t *GetErrorInfo() override { return m_ErrorString.c_str(); }
+
+ void DumpGlobalState() override
+ {
+ // Get our table onto the stack.
+ GetGlobalTable();
+ qCInfo(TRACE_INFO, "Begin global state dump");
+ lua_pushnil(m_LuaState);
+ while (lua_next(m_LuaState, -2) != 0) {
+ // duplicate the key so that we don't mess it up.
+ const char *keyType = lua_typename(m_LuaState, lua_type(m_LuaState, -2));
+ const char *valType = lua_typename(m_LuaState, lua_type(m_LuaState, -1));
+ lua_pushvalue(m_LuaState, -2);
+ const char *keyVal = lua_tostring(m_LuaState, lua_gettop(m_LuaState));
+ const char *valVal = lua_tostring(m_LuaState, lua_gettop(m_LuaState) - 1);
+ qCInfo(TRACE_INFO, "%s -> %s, %s -> %s", keyType, valType, keyVal, valVal);
+ lua_pop(m_LuaState, 2);
+ }
+ // pop the global table from the stack.
+ lua_pop(m_LuaState, 1);
+ qCInfo(TRACE_INFO, "End global state dump");
+ }
+
+ CRegisteredString GetContextType() override
+ {
+ return m_StringTable->RegisterStr(ILuaScriptContext::GetLuaContextTypeName());
+ }
+
+ void OnTableValue(SDatamodelTable *inTable, const char *inKey, int inValueIndex,
+ IScriptStateListener &inListener)
+ {
+ m_TempDebugStr.assign(nonNull(inKey));
+
+ SDatamodelValue theValue;
+ switch (lua_type(m_LuaState, inValueIndex)) {
+ case LUA_TNIL:
+ theValue = SNil();
+ break;
+ case LUA_TNUMBER:
+ theValue = lua_tonumber(m_LuaState, inValueIndex);
+ break;
+ case LUA_TBOOLEAN:
+ theValue = lua_toboolean(m_LuaState, inValueIndex) ? true : false;
+ break;
+ case LUA_TSTRING:
+ theValue = TDebugStr(lua_tostring(m_LuaState, inValueIndex));
+ break;
+ case LUA_TTABLE:
+ theValue = (SDatamodelTable *)lua_topointer(m_LuaState, inValueIndex);
+ break;
+ case LUA_TFUNCTION:
+ theValue = (SDatamodelFunction *)lua_topointer(m_LuaState, inValueIndex);
+ break;
+ case LUA_TUSERDATA:
+ theValue = (SDatamodelUserData *)lua_touserdata(m_LuaState, inValueIndex);
+ break;
+ case LUA_TTHREAD:
+ break;
+ case LUA_TLIGHTUSERDATA:
+ theValue = (SDatamodelUserData *)lua_touserdata(m_LuaState, inValueIndex);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ TDataModelTable &theTable =
+ m_TableMap.insert(eastl::make_pair(inTable, TDataModelTable())).first->second;
+ TDataModelTable::iterator iter = theTable.find(m_TempDebugStr);
+ if (iter == theTable.end() || iter->second != theValue) {
+ bool comparison = false;
+ if (iter != theTable.end()) {
+ comparison = iter->second != theValue;
+ }
+ (void)comparison;
+ inListener.SetKey(inTable, m_TempDebugStr, theValue);
+ theTable[m_TempDebugStr] = theValue;
+ }
+ }
+
+ // Table to dump is expected to be on the top of the stack.
+ void DumpTable(IScriptStateListener &inListener, SDatamodelTable *inTable)
+ {
+ if (m_VisitedTables.find(inTable) != m_VisitedTables.end())
+ return;
+
+ STopScope __topScope(m_LuaState);
+ m_VisitedTables.insert(inTable);
+ lua_pushnil(m_LuaState);
+ while (lua_next(m_LuaState, -2) != 0) {
+ if (lua_type(m_LuaState, -1) == LUA_TTABLE)
+ DumpTable(inListener, (SDatamodelTable *)lua_topointer(m_LuaState, -1));
+ // dup the key so the tostring function doesn't change the actual table key type
+ lua_pushvalue(m_LuaState, -2);
+ const char *keyVal = lua_tostring(m_LuaState, -1);
+ OnTableValue(inTable, keyVal, -2, inListener);
+ lua_pop(m_LuaState, 2);
+ }
+ }
+
+ void DumpState(IScriptStateListener &inListener) override
+ {
+ STopScope __topScope(m_LuaState);
+ m_VisitedTables.clear();
+ GetGlobalTable();
+ DumpTable(inListener, NULL);
+ }
+};
+
+SLuaScriptEvent::SLuaScriptEvent(SScriptContext &inContext, QT3DSI32 inId, CRegisteredString inName)
+ : m_Foundation(inContext.m_Foundation)
+ , m_Context(inContext)
+ , m_Id(inId)
+ , mRefCount(0)
+{
+ STopScope __stackScope(inContext.m_LuaState);
+ lua_newtable(inContext.m_LuaState);
+ // set name value
+ lua_pushstring(m_Context->m_LuaState, inName.c_str());
+ lua_setfield(m_Context->m_LuaState, -2, "name");
+ // Ensure the event table is stored.
+ m_Context->SetScriptIdItem(m_Id);
+ lua_pop(inContext.m_LuaState, 1);
+}
+
+SLuaScriptEvent::~SLuaScriptEvent()
+{
+ m_Context->ReleaseScriptIdItem(m_Id);
+}
+
+CRegisteredString SLuaScriptEvent::RegisterString(const char8_t *inStr)
+{
+ return m_Context->m_StringTable->RegisterStr(inStr);
+}
+
+void SLuaScriptEvent::GetEventTable()
+{
+ m_Context->GetScriptIdItem(m_Id);
+}
+
+void SLuaScriptEvent::GetDataTable()
+{
+ m_Context->GetScriptIdItem(m_Id);
+ lua_getfield(m_Context->m_LuaState, -1, "data");
+ if (!lua_istable(m_Context->m_LuaState, -1)) {
+ lua_pop(m_Context->m_LuaState, 1);
+ // set data table
+ lua_newtable(m_Context->m_LuaState);
+ lua_setfield(m_Context->m_LuaState, -2, "data");
+ lua_getfield(m_Context->m_LuaState, -1, "data");
+ }
+}
+
+void SLuaScriptEvent::SetDataTable()
+{
+ {
+ STopScope __topScope(m_Context->m_LuaState);
+ // Assuming new table is top of stack.
+ m_Context->GetScriptIdItem(m_Id);
+ lua_pushvalue(m_Context->m_LuaState, __topScope.m_Top);
+ lua_setfield(m_Context->m_LuaState, -2, "data");
+ }
+ // pop the argument off the stack.
+ lua_pop(m_Context->m_LuaState, 1);
+}
+
+CRegisteredString SLuaScriptEvent::GetName() const
+{
+ STopScope __stackScope(m_Context->m_LuaState);
+ const_cast<SLuaScriptEvent &>(*this).GetEventTable();
+ lua_getfield(m_Context->m_LuaState, -1, "name");
+ const char *theStr = lua_tostring(m_Context->m_LuaState, -1);
+ return const_cast<SLuaScriptEvent &>(*this).RegisterString(theStr);
+}
+
+CRegisteredString SLuaScriptEvent::GetEventType() const
+{
+ return const_cast<SLuaScriptEvent &>(*this).RegisterString(SLuaScriptEvent::StaticType());
+}
+
+bool SLuaScriptEvent::SetParam(CRegisteredString inName, const char8_t *inExpression)
+{
+ STopScope __stackScope(m_Context->m_LuaState);
+ GetDataTable();
+ int stackIncrement = m_Context->ExecuteStr(inExpression, true);
+ if (stackIncrement) {
+ lua_setfield(m_Context->m_LuaState, -2, inName.c_str());
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SLuaScriptEvent::SetParamStr(CRegisteredString inName, const char8_t *inStr)
+{
+ STopScope __stackScope(m_Context->m_LuaState);
+ GetDataTable();
+ lua_pushstring(m_Context->m_LuaState, nonNull(inStr));
+ lua_setfield(m_Context->m_LuaState, -2, inName.c_str());
+ return true;
+}
+
+bool SLuaScriptEvent::SetDataExpr(const char8_t *inExpression)
+{
+ STopScope __stackScope(m_Context->m_LuaState);
+ GetEventTable();
+ int stackIncrement = m_Context->ExecuteStr(inExpression, true);
+ if (stackIncrement) {
+ lua_setfield(m_Context->m_LuaState, -2, "data");
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SLuaScriptEvent::SetDataStr(const char8_t *inStr)
+{
+ STopScope __stackScope(m_Context->m_LuaState);
+ GetEventTable();
+ lua_pushstring(m_Context->m_LuaState, inStr);
+ lua_setfield(m_Context->m_LuaState, -2, "data");
+ return true;
+}
+
+struct SFoundationLogger : public IStateLogger
+{
+ NVFoundationBase &m_Foundation;
+ SFoundationLogger(NVFoundationBase &inFnd)
+ : m_Foundation(inFnd)
+ {
+ }
+ void addRef() override {}
+ void release() override {}
+ void Log(const char8_t *inLabel, const char8_t *inExpression) override
+ {
+ if (inLabel && inExpression)
+ qCInfo(TRACE_INFO, "%s - %s", inLabel, inExpression);
+ }
+};
+
+struct SLuaInterpreterObject : public IStateInterpreterEventHandler
+{
+ CAllocator allocator;
+ NVScopedRefCounted<NVFoundation> __foundation;
+ NVFoundationBase *m_ExternalFoundation;
+ SFoundationLogger m_Logger;
+ SSAutoDeallocatorAllocator graphAllocator;
+ NVScopedRefCounted<IStateContext> m_StateContext;
+ NVScopedRefCounted<debugger::IDebugger> m_Debugger;
+ NVScopedRefCounted<SScriptContext> m_ScriptContext;
+ NVScopedRefCounted<IStateInterpreter> m_Interpreter;
+ TSignalConnectionPtr m_EventConnection;
+ eastl::string m_ErrorString;
+
+ NVFoundationBase &GetFoundation()
+ {
+ if (m_ExternalFoundation)
+ return *m_ExternalFoundation;
+ return *__foundation;
+ }
+
+ SLuaInterpreterObject(debugger::IDebugger *inDebugger, NVFoundationBase *inFoundation)
+ : allocator()
+ , __foundation(NVCreateFoundation(QT3DS_FOUNDATION_VERSION, allocator))
+ , m_ExternalFoundation(inFoundation)
+ , m_Logger(GetFoundation())
+ , graphAllocator(GetFoundation())
+ , m_Debugger(inDebugger)
+ {
+ }
+
+ ~SLuaInterpreterObject()
+ {
+ if (m_Debugger)
+ m_Debugger->Disconnect(m_Interpreter->GetDebugInterface());
+ }
+
+ void OnInterpreterEvent(InterpreterEventTypes::Enum inEvent,
+ CRegisteredString inEventId) override
+ {
+ const char *functionName = "";
+ switch (inEvent) {
+ case InterpreterEventTypes::StateEnter:
+ functionName = "onAfterEnter";
+ break;
+ case InterpreterEventTypes::StateExit:
+ functionName = "onBeforeExit";
+ break;
+ case InterpreterEventTypes::Transition:
+ return;
+ default:
+ QT3DS_ASSERT(false);
+ return;
+ }
+ int top = lua_gettop(m_ScriptContext->m_LuaState);
+ m_ScriptContext->GetGlobalTable();
+ lua_getfield(m_ScriptContext->m_LuaState, -1, "uicstate_interpreterobject");
+ QT3DS_ASSERT(lua_istable(m_ScriptContext->m_LuaState, -1));
+ lua_getfield(m_ScriptContext->m_LuaState, -1, functionName);
+ if (lua_isfunction(m_ScriptContext->m_LuaState, -1)) {
+ lua_pushstring(m_ScriptContext->m_LuaState, inEventId.c_str());
+ int success = lua_pcall(m_ScriptContext->m_LuaState, 1, 0, 0);
+ if (success != 0) {
+ const char *errorStr = lua_tostring(m_ScriptContext->m_LuaState, -1);
+ m_ErrorString.assign("Failure during execution of \"");
+ m_ErrorString.append(functionName);
+ m_ErrorString.append("\", ");
+ m_ErrorString.append(errorStr);
+ qCCritical(INVALID_OPERATION, m_ErrorString.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ lua_settop(m_ScriptContext->m_LuaState, top);
+ }
+
+ static int OnGC(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TUSERDATA);
+ SLuaInterpreterObject *theInterpreter = (SLuaInterpreterObject *)lua_touserdata(inState, 1);
+ theInterpreter->~SLuaInterpreterObject();
+ return 0;
+ }
+
+ static SLuaInterpreterObject *GetObjectFromTable(lua_State *inState, int inTableIdx)
+ {
+ lua_getfield(inState, inTableIdx, "__implementation");
+ luaL_checktype(inState, -1, LUA_TUSERDATA);
+ SLuaInterpreterObject *retval = (SLuaInterpreterObject *)lua_touserdata(inState, -1);
+ lua_pop(inState, 1);
+ return retval;
+ }
+
+ void DoStart(lua_State *inState, const char8_t *inId = "")
+ {
+ int tableIndex = 0;
+ // note that the first arg was the 'this' pointer
+ if (lua_gettop(inState) != 1 && lua_istable(inState, 2)) {
+ tableIndex = 2;
+ }
+ m_ScriptContext = QT3DS_NEW(GetFoundation().getAllocator(), SScriptContext)(
+ GetFoundation(), *m_StateContext->GetDOMFactory()->GetStringTable(), inState,
+ tableIndex);
+ // Append us to the global table.
+ m_ScriptContext->GetGlobalTable();
+ m_ScriptContext->SetId(inId);
+ // This first argument was the 'this' table.
+ lua_pushvalue(inState, 1);
+ lua_setfield(inState, -2, "uicstate_interpreterobject");
+ lua_pop(inState, 1);
+ m_Interpreter = IStateInterpreter::Create(
+ GetFoundation(), *m_StateContext->GetDOMFactory()->GetStringTable(), *m_ScriptContext,
+ IExecutionContext::Create(GetFoundation(),
+ *m_StateContext->GetDOMFactory()->GetStringTable(), m_Logger,
+ *m_ScriptContext));
+
+ m_EventConnection = m_Interpreter->RegisterEventHandler(*this);
+ m_Interpreter->Initialize(*m_StateContext);
+ if (m_Debugger)
+ m_Debugger->Connect(m_Interpreter->GetDebugInterface());
+ }
+
+ void DoBind(IStateInterpreter &inInterpreter, lua_State *inState)
+ {
+ int theTop = lua_gettop(inState);
+ // bad if someone is using a non-lua script context.
+ m_ScriptContext = static_cast<SScriptContext &>(inInterpreter.GetScriptContext());
+ m_ScriptContext->GetGlobalTable();
+ lua_pushvalue(inState, theTop);
+ lua_setfield(inState, -2, "uicstate_interpreterobject");
+ m_Interpreter = inInterpreter;
+ m_EventConnection = m_Interpreter->RegisterEventHandler(*this);
+ lua_settop(inState, theTop);
+ }
+
+ // All of these expect the table to be the first argument
+ static int Initialize(lua_State *inState, const char8_t *inId)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ if (!isTrivial(inId)) {
+ lua_pushstring(inState, inId);
+ lua_setfield(inState, 1, "id");
+ }
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself)
+ myself->DoStart(inState, inId);
+ return 0;
+ }
+
+ static int Start(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself) {
+ myself->DoStart(inState);
+ if (myself->m_Interpreter)
+ myself->m_Interpreter->Start();
+ }
+ return 0;
+ }
+
+ void DoSet(lua_State *inState)
+ {
+ if (lua_gettop(inState) > 2) {
+ m_ScriptContext->GetGlobalTable(inState);
+ lua_insert(inState, -3);
+ lua_settable(inState, -3);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ static int Set(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself)
+ myself->DoSet(inState);
+ return 0;
+ }
+
+ int DoGet(lua_State *inState)
+ {
+ if (lua_gettop(inState) > 1) {
+ m_ScriptContext->GetGlobalTable(inState);
+ // set the global table underneath the top of the stack so the top
+ // still has the 'get' argument.
+ lua_insert(inState, -2);
+ lua_gettable(inState, -2);
+ return 1;
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return 0;
+ }
+
+ static int Get(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself)
+ return myself->DoGet(inState);
+ return 0;
+ }
+
+ void DoFireEvent(lua_State *inState)
+ {
+ STopScope __stackScope(inState);
+ if (__stackScope.m_Top > 1) {
+ const char *evtName = lua_tostring(inState, 2);
+ // Table is set to the third arg, whatever that may be.
+ if (__stackScope.m_Top > 2) {
+ SLuaScriptEvent *theEvent =
+ static_cast<SLuaScriptEvent *>(m_ScriptContext->CreateScriptEvent(
+ m_ScriptContext->m_StringTable->RegisterStr(evtName)));
+ lua_pushvalue(inState, 3);
+ theEvent->SetDataTable();
+ m_Interpreter->QueueEvent(theEvent);
+ } else {
+ m_Interpreter->QueueEvent(evtName);
+ }
+ }
+ }
+
+ static int FireEvent(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself)
+ myself->DoFireEvent(inState);
+ return 0;
+ }
+
+ void DoStep(lua_State * /*inState*/) { m_Interpreter->Execute(); }
+
+ static int Step(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself)
+ myself->DoStep(inState);
+ return 0;
+ }
+
+ // We have to do things manually here because the lua state isn't the same
+ // when called from the console (!!).
+ bool DoEval(lua_State *inState)
+ {
+ luaL_checktype(inState, -1, LUA_TSTRING);
+ const char *evalStr = lua_tostring(inState, -1);
+ eastl::string compileStr("return ");
+ compileStr.append(evalStr);
+ int failure = luaL_loadstring(inState, compileStr.c_str());
+ if (failure) {
+ qCCritical(INVALID_OPERATION, "Failed to eval %s: %s", evalStr, lua_tostring(inState, -1));
+ return false;
+ }
+ m_ScriptContext->GetGlobalTable(inState);
+ lua_setfenv(inState, -2);
+ failure = lua_pcall(inState, 0, 1, 0);
+ if (failure) {
+ qCCritical(INVALID_OPERATION, "Failed to eval %s: %s", evalStr, lua_tostring(inState, -1));
+ return false;
+ }
+ return true;
+ }
+
+ static int Eval(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself) {
+ if (myself->DoEval(inState))
+ return 1;
+ }
+ return 0;
+ }
+
+ static int In(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ luaL_checktype(inState, 2, LUA_TSTRING);
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (myself) {
+ bool result = myself->m_ScriptContext->In(lua_tostring(inState, 2));
+ lua_pushboolean(inState, (int)result);
+ return 1;
+ }
+ return 0;
+ }
+
+ static int Configuration(lua_State *inState)
+ {
+ luaL_checktype(inState, 1, LUA_TTABLE);
+ bool onlyAtomic = false;
+ if (lua_gettop(inState) == 2)
+ onlyAtomic = lua_toboolean(inState, 2) ? true : false;
+ SLuaInterpreterObject *myself = GetObjectFromTable(inState, 1);
+ if (!myself)
+ return 0;
+ NVConstDataRef<SStateNode *> theConfiguration = myself->m_Interpreter->GetConfiguration();
+ lua_newtable(inState);
+ for (QT3DSU32 idx = 0, end = theConfiguration.size(); idx < end; ++idx) {
+ bool isStateAtomic = theConfiguration[idx]->IsAtomic();
+ if (!onlyAtomic || isStateAtomic) {
+ lua_pushstring(inState, theConfiguration[idx]->m_Id.c_str());
+ lua_pushnumber(inState, idx + 1);
+ lua_settable(inState, -3);
+ }
+ }
+ return 1;
+ }
+
+ // Bind the interpreter c functions into the interpreter table.
+ // the interpreter is assumed to be userdata at the top of the stack.
+ static void BindCFunctions(lua_State *inState)
+ {
+ // Don't create the interpreter yet because it requires a script context and we
+ // don't know what the datatable table is going to be.
+ lua_newtable(inState);
+ // Switch the order of the user data and this table
+ lua_insert(inState, -2);
+ lua_setfield(inState, -2, "__implementation");
+ lua_pushcfunction(inState, Start);
+ lua_setfield(inState, -2, "start");
+ lua_pushcfunction(inState, Set);
+ lua_setfield(inState, -2, "set");
+ lua_pushcfunction(inState, Get);
+ lua_setfield(inState, -2, "get");
+ lua_pushcfunction(inState, FireEvent);
+ lua_setfield(inState, -2, "fireEvent");
+ lua_pushcfunction(inState, Step);
+ lua_setfield(inState, -2, "step");
+ lua_pushcfunction(inState, Eval);
+ lua_setfield(inState, -2, "eval");
+ lua_pushcfunction(inState, In);
+ lua_setfield(inState, -2, "active");
+ lua_pushcfunction(inState, Configuration);
+ lua_setfield(inState, -2, "configuration");
+ }
+
+ static SLuaInterpreterObject *CreateInterpreter(lua_State *inState,
+ debugger::IDebugger *inDebugger,
+ NVFoundationBase *inFoundation)
+ {
+ SLuaInterpreterObject *retval =
+ (SLuaInterpreterObject *)lua_newuserdata(inState, sizeof(SLuaInterpreterObject));
+ new (retval) SLuaInterpreterObject(inDebugger, inFoundation);
+
+ int top = lua_gettop(inState);
+ luaL_getmetatable(inState, "SLuaInterpreterObjectUserData");
+ if (lua_isnil(inState, -1)) {
+ lua_pop(inState, 1);
+ luaL_newmetatable(inState, "SLuaInterpreterObjectUserData");
+ QT3DS_ASSERT(lua_istable(inState, -1));
+ lua_pushcfunction(inState, OnGC);
+ lua_setfield(inState, -2, "__gc");
+ }
+ // setup correct destruction of the user data
+ lua_setmetatable(inState, -2);
+ lua_settop(inState, top);
+ return retval;
+ }
+
+ static int Bind(IStateInterpreter &inInterpreter, lua_State *inState)
+ {
+ SLuaInterpreterObject *retval =
+ CreateInterpreter(inState, NULL, &inInterpreter.GetFoundation());
+ BindCFunctions(inState);
+ retval->DoBind(inInterpreter, inState);
+ return 1;
+ }
+
+ static int Parse(lua_State *inState, debugger::IDebugger *inDebugger = NULL,
+ NVFoundationBase *inFoundation = NULL, IStringTable *inStrTable = NULL)
+ {
+ luaL_checktype(inState, 1, LUA_TSTRING);
+ const char *path = lua_tostring(inState, 1);
+ CFileSeekableIOStream theStream(path, FileReadFlags());
+ if (theStream.IsOpen() == false)
+ luaL_error(inState, "UICState::parse - Failed to open %s", path);
+ SLuaInterpreterObject *retval = CreateInterpreter(inState, inDebugger, inFoundation);
+ int top = lua_gettop(inState);
+ retval->m_StateContext = IStateContext::Load(
+ retval->graphAllocator, retval->GetFoundation(), theStream, path, inStrTable);
+ if (retval->m_StateContext.mPtr == NULL) {
+ luaL_error(inState, "UICState::parse - Failed to parse %s", path);
+ }
+ BindCFunctions(inState);
+ QT3DS_ASSERT(top == lua_gettop(inState));
+ (void)top;
+ return 1;
+ }
+ static int RawParse(lua_State *inState) { return Parse(inState); }
+};
+
+MallocAllocator g_MallocAlloc;
+}
+
+ILuaScriptContext &ILuaScriptContext::CreateLuaScriptContext(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SScriptContext)(inFoundation, inStrTable);
+}
+
+ILuaScriptContext &ILuaScriptContext::CreateLuaScriptContext(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable,
+ lua_State *inState,
+ int inGlobalTableIdx)
+{
+ if (inState == NULL) {
+ QT3DS_ASSERT(false);
+ }
+ return *QT3DS_NEW(inFoundation.getAllocator(), SScriptContext)(inFoundation, inStrTable, inState,
+ inGlobalTableIdx);
+}
+
+void ILuaScriptContext::ExportLuaBindings(lua_State *inState)
+{
+ lua_pushcfunction(inState, SLuaInterpreterObject::RawParse);
+ lua_setglobal(inState, "parseSCXML");
+}
+
+int ILuaScriptContext::ParseSCXML(lua_State *inState, debugger::IDebugger *inDebugger)
+{
+ return SLuaInterpreterObject::Parse(inState, inDebugger);
+}
+
+int ILuaScriptContext::ParseSCXML(lua_State *inState, debugger::IDebugger *inDebugger,
+ NVFoundationBase &inFoundation, IStringTable &inStrTable)
+{
+ return SLuaInterpreterObject::Parse(inState, inDebugger, &inFoundation, &inStrTable);
+}
+
+int ILuaScriptContext::Initialize(lua_State *inState, const char8_t *inID)
+{
+ return SLuaInterpreterObject::Initialize(inState, inID);
+}
+
+int ILuaScriptContext::Start(lua_State *inState)
+{
+ return SLuaInterpreterObject::Start(inState);
+}
+
+void ILuaScriptContext::Bind(IStateInterpreter &inInterpreter, lua_State *inState)
+{
+ SLuaInterpreterObject::Bind(inInterpreter, inState);
+}
+
+IStateInterpreter *ILuaScriptContext::GetInterpreterFromBindings(lua_State *inState)
+{
+ if (lua_istable(inState, -1)) {
+ lua_getfield(inState, -1, "__implementation");
+ if (lua_isuserdata(inState, -1)) {
+ SLuaInterpreterObject *theObject = (SLuaInterpreterObject *)lua_touserdata(inState, -1);
+ if (theObject)
+ return theObject->m_Interpreter.mPtr;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return NULL;
+}
diff --git a/src/Runtime/Source/UICState/Source/UICStateVisualBindingContext.cpp b/src/Runtime/Source/UICState/Source/UICStateVisualBindingContext.cpp
new file mode 100644
index 00000000..4046272f
--- /dev/null
+++ b/src/Runtime/Source/UICState/Source/UICStateVisualBindingContext.cpp
@@ -0,0 +1,657 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateVisualBindingContext.h"
+
+#include "UICStateVisualBindingContextValues.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/AutoDeallocatorAllocator.h"
+#include "EASTL/string.h"
+#include "EASTL/hash_map.h"
+#include "UICStateInterpreter.h"
+#include "UICStateContext.h"
+#include "foundation/XML.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/StringConversionImpl.h"
+
+using namespace uic::state;
+
+namespace {
+
+struct SStateEventKey
+{
+ InterpreterEventTypes::Enum m_Event;
+ CRegisteredString m_Id;
+ SStateEventKey(InterpreterEventTypes::Enum inEvt, CRegisteredString inId)
+ : m_Event(inEvt)
+ , m_Id(inId)
+ {
+ }
+ bool operator==(const SStateEventKey &inOther) const
+ {
+ return m_Event == inOther.m_Event && m_Id == inOther.m_Id;
+ }
+};
+}
+namespace eastl {
+template <>
+struct hash<SStateEventKey>
+{
+ size_t operator()(const SStateEventKey &inKey) const
+ {
+ return hash<int>()((int)inKey.m_Event)
+ ^ hash<qt3ds::foundation::CRegisteredString>()(inKey.m_Id);
+ }
+};
+}
+
+namespace {
+struct SVisualStateCommandNode
+{
+ SVisualStateCommand m_Command;
+ SVisualStateCommandNode *m_NextSibling;
+ SVisualStateCommandNode(const SVisualStateCommand &inCommand = SVisualStateCommand())
+ : m_Command(inCommand)
+ , m_NextSibling(NULL)
+ {
+ }
+};
+
+DEFINE_INVASIVE_SINGLE_LIST(VisualStateCommandNode);
+IMPLEMENT_INVASIVE_SINGLE_LIST(VisualStateCommandNode, m_NextSibling);
+
+typedef TVisualStateCommandNodeList TCommandList;
+
+// Apparently eastl::hash_multimap isn't order preserving for items.
+typedef eastl::hash_map<SStateEventKey, TCommandList, eastl::hash<SStateEventKey>,
+ eastl::equal_to<SStateEventKey>, ForwardingAllocator>
+ TStateEventCommandMap;
+
+struct SStateMachineSystem : public IStateInterpreterEventHandler, public NVRefCounted
+{
+ NVAllocatorCallback &m_Allocator;
+ CRegisteredString m_Path;
+ CRegisteredString m_Id;
+ CRegisteredString m_DatamodelFunction;
+
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IStateInterpreter> m_Interpreter;
+ TStateEventCommandMap m_CommandMap;
+ QT3DSI32 mRefCount;
+ bool m_Error;
+ bool m_Running;
+
+ TSignalConnectionPtr m_InterpreterEventConnection;
+ NVScopedRefCounted<IVisualStateCommandHandler> m_CommandHandler;
+ NVScopedRefCounted<IVisualStateInterpreterFactory> m_InterpreterFactory;
+
+ SStateMachineSystem(const char8_t *inPath, const char8_t *inId, const char8_t *inFunction,
+ IStringTable &inStrTable, NVAllocatorCallback &inAlloc)
+ : m_Allocator(inAlloc)
+ , m_Path(inStrTable.RegisterStr(inPath))
+ , m_Id(inStrTable.RegisterStr(inId))
+ , m_DatamodelFunction(inStrTable.RegisterStr(inFunction))
+ , m_StringTable(inStrTable)
+ , m_CommandMap(ForwardingAllocator(inAlloc, "SStateMachineSystem::m_CommandMap"))
+ , mRefCount(0)
+ , m_Error(false)
+ , m_Running(false)
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
+
+ void Initialize()
+ {
+ if (!m_Interpreter) {
+ m_Running = false;
+ if (m_Error == false && m_InterpreterFactory) {
+ m_Interpreter = m_InterpreterFactory->OnNewStateMachine(
+ m_Path.c_str(), m_Id.c_str(), m_DatamodelFunction.c_str());
+ if (!m_Interpreter) {
+ m_Error = true;
+ } else {
+ IStateContext *theContext = m_Interpreter->GetStateContext();
+ if (theContext) {
+ // Validate all of our ids in our command map.
+ nvvector<CRegisteredString> invalidStates(
+ m_Allocator, "SStateMachineSystem::Initialize::invalidStates");
+ for (TStateEventCommandMap::iterator iter = m_CommandMap.begin(),
+ end = m_CommandMap.end();
+ iter != end; ++iter) {
+ CRegisteredString testId = iter->first.m_Id;
+ if (theContext->FindStateNode(testId) == NULL) {
+ nvvector<CRegisteredString>::iterator theFind =
+ eastl::find(invalidStates.begin(), invalidStates.end(), testId);
+ if (theFind == invalidStates.end()) {
+ qCCritical(INVALID_OPERATION, m_Path.c_str(), 0,
+ "State \"%s\" is not a valid state", testId.c_str());
+ invalidStates.push_back(testId);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void Start()
+ {
+ if (m_Error || m_Running || !m_Interpreter)
+ return;
+ m_Running = true;
+ m_Interpreter->Start();
+ // Event handler must be replaced after interpreter started
+ m_InterpreterEventConnection = m_Interpreter->RegisterEventHandler(*this);
+ // Run throw the initial configuration and fire any enter events. This takes care of
+ // initial states.
+ NVConstDataRef<SStateNode *> initialConfig = m_Interpreter->GetConfiguration();
+ for (QT3DSU32 nodeIdx = 0, nodeEnd = initialConfig.size(); nodeIdx < nodeEnd; ++nodeIdx) {
+ SStateNode *theNode(initialConfig[nodeIdx]);
+ OnInterpreterEvent(InterpreterEventTypes::StateEnter, theNode->m_Id);
+ }
+ }
+
+ void Update()
+ {
+ if (m_Interpreter) {
+ m_Interpreter->Execute();
+ }
+ }
+
+ void OnInterpreterEvent(InterpreterEventTypes::Enum inEvent,
+ CRegisteredString inEventId) override
+ {
+ if (m_CommandHandler) {
+ CRegisteredString theId = m_StringTable->RegisterStr(inEventId.c_str());
+ SStateEventKey theKey(inEvent, theId);
+ TStateEventCommandMap::iterator theItem = m_CommandMap.find(theKey);
+ if (theItem != m_CommandMap.end()) {
+ for (TCommandList::iterator iter = theItem->second.begin(),
+ end = theItem->second.end();
+ iter != end; ++iter)
+ m_CommandHandler->Handle(iter->m_Command, m_Interpreter->GetScriptContext());
+ }
+ }
+ }
+};
+
+typedef eastl::vector<NVScopedRefCounted<SStateMachineSystem>> TStateMachineList;
+
+struct SVisualStateContext : public IVisualStateContext
+{
+ NVFoundationBase &m_Foundation;
+ SSAutoDeallocatorAllocator m_DataAllocator;
+ QT3DSI32 mRefCount;
+ TStateMachineList m_StateMachines;
+ NVScopedRefCounted<IVisualStateCommandHandler> m_CommandHandler;
+ NVScopedRefCounted<IVisualStateInterpreterFactory> m_InterpreterFactory;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ nvvector<SElementReference> m_PreparseResults;
+
+ SVisualStateContext(NVFoundationBase &fnd, IStringTable &inStrTable)
+ : m_Foundation(fnd)
+ , m_DataAllocator(fnd)
+ , mRefCount(0)
+ , m_StringTable(inStrTable)
+ , m_PreparseResults(fnd.getAllocator(), "SVisualStateContext::m_PreparseResults")
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ void LoadStateMachine(const char8_t *id, const char8_t *inRelativePath,
+ const char8_t *inDatamodelFunction) override
+ {
+ SStateMachineSystem *theSystem = QT3DS_NEW(m_Foundation.getAllocator(), SStateMachineSystem)(
+ inRelativePath, id, inDatamodelFunction, *m_StringTable, m_Foundation.getAllocator());
+ theSystem->m_CommandHandler = m_CommandHandler;
+ theSystem->m_InterpreterFactory = m_InterpreterFactory;
+ m_StateMachines.push_back(theSystem);
+ }
+
+ CRegisteredString ParseStrAtt(IDOMReader &inReader, const char8_t *attName)
+ {
+ const char8_t *temp = "";
+ if (inReader.UnregisteredAtt(attName, temp)) {
+ return m_StringTable->RegisterStr(temp);
+ }
+ return CRegisteredString();
+ }
+
+ void PreparseExecutableContent(IDOMReader &inReader)
+ {
+ for (bool setatt = inReader.MoveToFirstChild(); setatt;
+ setatt = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __commandScope(inReader);
+ const char8_t *elemName = inReader.GetElementName();
+
+ SElementReference theReference;
+ if (AreEqual(elemName, "goto-slide")) {
+ theReference = SElementReference(ParseStrAtt(inReader, "element"));
+ } else if (AreEqual(elemName, "call")) {
+ theReference = SElementReference(ParseStrAtt(inReader, "element"));
+ } else if (AreEqual(elemName, "set-attribute")) {
+ theReference = SElementReference(ParseStrAtt(inReader, "element"),
+ ParseStrAtt(inReader, "attribute"));
+ } else if (AreEqual(elemName, "fire-event")) {
+ theReference = SElementReference(ParseStrAtt(inReader, "element"));
+ } else if (AreEqual(elemName, "set-presentation")) {
+ } else {
+ qCCritical(INVALID_PARAMETER, "Unrecognized child in an enter/exit node: %s", elemName);
+ }
+ if (theReference.m_ElementPath.IsValid()) {
+ m_PreparseResults.push_back(theReference);
+ }
+ }
+ }
+
+ NVConstDataRef<SElementReference> PreParseDocument(IDOMReader &inReader) override
+ {
+ m_PreparseResults.clear();
+ for (bool success = inReader.MoveToFirstChild("statemachine"); success;
+ success = inReader.MoveToNextSibling("statemachine")) {
+ IDOMReader::Scope __readerScope(inReader);
+ if (inReader.MoveToFirstChild("visual-states")) {
+ IDOMReader::Scope __bindingsScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __stateScope(inReader);
+ if (AreEqual(inReader.GetElementName().c_str(), "transition")) {
+ PreparseExecutableContent(inReader);
+ } else {
+ for (bool enterExitSuccess = inReader.MoveToFirstChild(); enterExitSuccess;
+ enterExitSuccess = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __enterExitScope(inReader);
+ PreparseExecutableContent(inReader);
+ }
+ }
+ }
+ }
+ }
+ return m_PreparseResults;
+ }
+
+ void ParseGotoSlideData(IDOMReader &inReader, SGotoSlideData &inData)
+ {
+ const char *tempData;
+ if (inReader.UnregisteredAtt("direction", tempData) && AreEqual(tempData, "reverse"))
+ inData.m_Reverse = true;
+
+ if (inReader.UnregisteredAtt("mode", tempData)) {
+ if (AreEqual(tempData, "stopatend")) {
+ inData.m_Mode = SlidePlaybackModes::StopAtEnd;
+ inData.m_PlaythroughTo = CRegisteredString();
+ } else if (AreEqual(tempData, "looping"))
+ inData.m_Mode = SlidePlaybackModes::Looping;
+ else if (AreEqual(tempData, "pingpong"))
+ inData.m_Mode = SlidePlaybackModes::PingPong;
+ else if (AreEqual(tempData, "ping"))
+ inData.m_Mode = SlidePlaybackModes::Ping;
+ else if (AreEqual(tempData, "playthrough")) {
+ if (!inReader.UnregisteredAtt("playthroughto", tempData) || isTrivial(tempData)) {
+ qCCritical(INVALID_OPERATION, "Goto slide command has playthough "
+ "mode but no playthroughto attribute; mode will be ignored");
+ } else {
+ inData.m_PlaythroughTo = m_StringTable->RegisterStr(tempData);
+ }
+
+ if (inData.m_PlaythroughTo.hasValue())
+ inData.m_Mode = SlidePlaybackModes::StopAtEnd;
+ }
+ }
+
+ if (inReader.UnregisteredAtt("state", tempData))
+ inData.m_Paused = AreEqual(tempData, "pause");
+
+ if (inReader.UnregisteredAtt("rate", tempData)) {
+ QT3DSF32 temp = 1.0f;
+ if (StringConversion<QT3DSF32>().StrTo(tempData, temp))
+ inData.m_Rate = temp;
+ }
+
+ if (inReader.UnregisteredAtt("time", tempData)) {
+ QT3DSF32 temp = 0.0f;
+ if (StringConversion<QT3DSF32>().StrTo(tempData, temp))
+ inData.m_StartTime = static_cast<QT3DSU32>(NVMax(0.0f, temp) * 1000.0f + .5f);
+ }
+ }
+
+ void ParseExecutableContent(IDOMReader &inReader, CRegisteredString &inStateId,
+ InterpreterEventTypes::Enum inEvent,
+ TStateEventCommandMap &inCommandMap)
+ {
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __itemScope(inReader);
+ const char8_t *elemName = inReader.GetElementName();
+ SVisualStateCommand theCommand;
+ if (AreEqual(elemName, "goto-slide")) {
+ const char8_t *rel;
+ if (inReader.UnregisteredAtt("rel", rel)) {
+ const char8_t *wrap;
+ inReader.UnregisteredAtt("wrap", wrap);
+ SGotoSlideRelative::Enum direction = SGotoSlideRelative::Error;
+ if (AreEqual(rel, "next"))
+ direction = SGotoSlideRelative::Next;
+ else if (AreEqual(rel, "previous"))
+ direction = SGotoSlideRelative::Previous;
+ else {
+ qCCritical(INVALID_OPERATION, "Goto slide relative has invalid "
+ "attribute (neither 'next' nor 'previous')");
+ }
+ bool doWrap = AreEqual(wrap, "true") ? true : false;
+
+ SGotoSlideRelative theCommandData(ParseStrAtt(inReader, "element"), direction,
+ doWrap);
+ ParseGotoSlideData(inReader, theCommandData.m_GotoSlideData);
+ theCommand = SVisualStateCommand(theCommandData);
+ } else {
+ SGotoSlide theCommandData(ParseStrAtt(inReader, "element"),
+ ParseStrAtt(inReader, "slide"));
+ ParseGotoSlideData(inReader, theCommandData.m_GotoSlideData);
+ theCommand = SVisualStateCommand(theCommandData);
+ }
+ } else if (AreEqual(elemName, "call")) {
+ theCommand = SVisualStateCommand(SCallFunction(ParseStrAtt(inReader, "element"),
+ ParseStrAtt(inReader, "handler"),
+ ParseStrAtt(inReader, "arguments")));
+ } else if (AreEqual(elemName, "set-attribute")) {
+ theCommand = SVisualStateCommand(SSetAttribute(ParseStrAtt(inReader, "element"),
+ ParseStrAtt(inReader, "attribute"),
+ ParseStrAtt(inReader, "value")));
+ } else if (AreEqual(elemName, "fire-event")) {
+ theCommand = SVisualStateCommand(
+ SFireEvent(ParseStrAtt(inReader, "element"), ParseStrAtt(inReader, "event")));
+ } else if (AreEqual(elemName, "set-presentation")) {
+ theCommand = SVisualStateCommand(SPresentationAttribute(
+ ParseStrAtt(inReader, "ref"), ParseStrAtt(inReader, "attribute"),
+ ParseStrAtt(inReader, "value")));
+ } else if (AreEqual(elemName, "play-sound")) {
+ theCommand = SVisualStateCommand(SPlaySound(ParseStrAtt(inReader, "file")));
+ } else {
+ qCCritical(INVALID_PARAMETER, "Unrecognized child in an enter/exit node: %s", elemName);
+ }
+ if (theCommand.getType() != VisualStateCommandTypes::NoVisualStateCommand) {
+ TCommandList &theList = inCommandMap
+ .insert(eastl::make_pair(
+ SStateEventKey(inEvent, inStateId), TCommandList()))
+ .first->second;
+ theList.push_back(*QT3DS_NEW(m_DataAllocator, SVisualStateCommandNode)(theCommand));
+ }
+ }
+ }
+
+ SStateMachineSystem *FindStateMachine(const char8_t *inId)
+ {
+ if (isTrivial(inId))
+ return NULL;
+ if (inId[0] == '#')
+ ++inId;
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx)
+ if (AreEqual(m_StateMachines[idx].mPtr->m_Id.c_str(), inId))
+ return m_StateMachines[idx].mPtr;
+ return NULL;
+ }
+
+ // We have to be careful of string table values coming from the state machine and from the
+ // reader
+ // because we don't necessarily share the same string table.
+ void LoadVisualStateMapping(IDOMReader &inReader) override
+ {
+ for (bool success = inReader.MoveToFirstChild("statemachine"); success;
+ success = inReader.MoveToNextSibling("statemachine")) {
+ IDOMReader::Scope __readerScope(inReader);
+ const char8_t *machineId = "";
+ if (inReader.UnregisteredAtt("ref", machineId)) {
+ SStateMachineSystem *theSystem = FindStateMachine(machineId + 1);
+ if (theSystem == NULL) {
+ qCCritical(INVALID_OPERATION, "Unknown state machine id: %s",
+ nonNull(machineId));
+ continue;
+ }
+
+ if (inReader.MoveToFirstChild("visual-states")) {
+ IDOMReader::Scope __bindingsScope(inReader);
+ for (bool bindingsSuccess = inReader.MoveToFirstChild(); bindingsSuccess;
+ bindingsSuccess = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __stateScope(inReader);
+ const char8_t *rawStateId = "";
+ inReader.UnregisteredAtt("ref", rawStateId);
+ if (isTrivial(rawStateId))
+ continue;
+
+ if (rawStateId[0] == '#')
+ ++rawStateId;
+ CRegisteredString elemName = m_StringTable->RegisterStr(rawStateId);
+
+ if (AreEqual(inReader.GetElementName().c_str(), "transition")) {
+ ParseExecutableContent(inReader, elemName,
+ InterpreterEventTypes::Transition,
+ theSystem->m_CommandMap);
+ } else {
+ for (bool stateSuccess = inReader.MoveToFirstChild(); stateSuccess;
+ stateSuccess = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __enterExitScope(inReader);
+ const char8_t *stateChildName = inReader.GetElementName();
+ if (AreEqual(stateChildName, "enter")) {
+ ParseExecutableContent(inReader, elemName,
+ InterpreterEventTypes::StateEnter,
+ theSystem->m_CommandMap);
+ } else if (AreEqual(stateChildName, "exit")) {
+ ParseExecutableContent(inReader, elemName,
+ InterpreterEventTypes::StateExit,
+ theSystem->m_CommandMap);
+ } else {
+ qCCritical(INVALID_PARAMETER,
+ "Unrecognized child in a visual state bindings state: %s",
+ stateChildName);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ qCCritical(INVALID_OPERATION, "visual-state element has no machine attribute");
+ }
+ }
+ }
+
+ void SetCommandHandler(IVisualStateCommandHandler *inHandler) override
+ {
+ m_CommandHandler = inHandler;
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx)
+ m_StateMachines[idx]->m_CommandHandler = inHandler;
+ }
+
+ void SetInterpreterFactory(IVisualStateInterpreterFactory *inHandler) override
+ {
+ m_InterpreterFactory = inHandler;
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx)
+ m_StateMachines[idx]->m_InterpreterFactory = inHandler;
+ }
+
+ void Initialize() override
+ {
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx)
+ m_StateMachines[idx]->Initialize();
+ }
+
+ void Start() override
+ {
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx)
+ m_StateMachines[idx]->Start();
+ }
+
+ void Update() override
+ {
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx)
+ m_StateMachines[idx]->Update();
+ }
+
+ QT3DSU32 CountItems(TCommandList &list)
+ {
+ QT3DSU32 retval = 0;
+ for (TCommandList::iterator iter = list.begin(), end = list.end(); iter != end; ++iter)
+ ++retval;
+ return retval;
+ }
+
+ struct SSaveVisitor
+ {
+ const SStrRemapMap &m_RemapMap;
+ SSaveVisitor(const SStrRemapMap &map)
+ : m_RemapMap(map)
+ {
+ }
+ template <typename TItemType>
+ SVisualStateCommand operator()(const TItemType &item)
+ {
+ TItemType newItem(item);
+ newItem.Remap(*this);
+ return newItem;
+ }
+ void Remap(CRegisteredString &inStr) { inStr.Remap(m_RemapMap); }
+ SVisualStateCommand operator()() { return SVisualStateCommand(); }
+ };
+
+ void BinarySave(IOutStream &stream) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriteBuffer(m_Foundation.getAllocator(),
+ "BinarySave::writebuffer");
+ // Allocate space for overall size of the data section
+ theWriteBuffer.writeZeros(4);
+ theWriteBuffer.write((QT3DSU32)m_StateMachines.size());
+ const SStrRemapMap &theRemapMap(m_StringTable->GetRemapMap());
+ for (QT3DSU32 idx = 0, end = m_StateMachines.size(); idx < end; ++idx) {
+ SStateMachineSystem &theSystem = *m_StateMachines[idx];
+ CRegisteredString path(theSystem.m_Path);
+ CRegisteredString id(theSystem.m_Id);
+ CRegisteredString fn(theSystem.m_DatamodelFunction);
+ path.Remap(theRemapMap);
+ id.Remap(theRemapMap);
+ fn.Remap(theRemapMap);
+ theWriteBuffer.write(path);
+ theWriteBuffer.write(id);
+ theWriteBuffer.write(fn);
+ theWriteBuffer.write((QT3DSU32)theSystem.m_CommandMap.size());
+ for (TStateEventCommandMap::iterator iter = theSystem.m_CommandMap.begin(),
+ mapEnd = theSystem.m_CommandMap.end();
+ iter != mapEnd; ++iter) {
+ theWriteBuffer.write((QT3DSU32)iter->first.m_Event);
+ CRegisteredString stateId(iter->first.m_Id);
+ stateId.Remap(theRemapMap);
+ theWriteBuffer.write(stateId);
+
+ theWriteBuffer.write(CountItems(iter->second));
+ for (TCommandList::iterator cmdIter = iter->second.begin(),
+ cmdEnd = iter->second.end();
+ cmdIter != cmdEnd; ++cmdIter) {
+ SVisualStateCommand remapped =
+ cmdIter->m_Command.visit<SVisualStateCommand>(SSaveVisitor(theRemapMap));
+ SVisualStateCommandNode theNode(remapped);
+ theWriteBuffer.write(theNode);
+ }
+ }
+ }
+ QT3DSU32 totalSize = theWriteBuffer.size();
+ QT3DSU32 *data = (QT3DSU32 *)theWriteBuffer.begin();
+ data[0] = totalSize - 4;
+ stream.Write((QT3DSU8 *)data, totalSize);
+ }
+
+ struct SLoadVisitor
+ {
+ NVDataRef<QT3DSU8> m_RemapMap;
+ SLoadVisitor(const NVDataRef<QT3DSU8> map)
+ : m_RemapMap(map)
+ {
+ }
+ template <typename TItemType>
+ void operator()(TItemType &item)
+ {
+ item.Remap(*this);
+ }
+
+ void Remap(CRegisteredString &inStr) { inStr.Remap(m_RemapMap); }
+ void operator()() {}
+ };
+
+ void BinaryLoad(IInStream &stream, NVDataRef<QT3DSU8> inStringTableData) override
+ {
+ QT3DSU32 length;
+ stream.Read(length);
+ QT3DSU8 *data = (QT3DSU8 *)m_DataAllocator.allocate(length, "Binaryload", __FILE__, __LINE__);
+ stream.Read(data, length);
+
+ SDataReader theReader(data, data + length);
+ QT3DSU32 numMachines = theReader.LoadRef<QT3DSU32>();
+ m_StateMachines.clear();
+ m_StateMachines.reserve(numMachines);
+ for (QT3DSU32 idx = 0, end = numMachines; idx < end; ++idx) {
+ CRegisteredString path = theReader.LoadRef<CRegisteredString>();
+ CRegisteredString id = theReader.LoadRef<CRegisteredString>();
+ CRegisteredString fn = theReader.LoadRef<CRegisteredString>();
+ path.Remap(inStringTableData);
+ id.Remap(inStringTableData);
+ fn.Remap(inStringTableData);
+ LoadStateMachine(id, path, fn);
+ SStateMachineSystem &theSystem(*m_StateMachines.back());
+ QT3DSU32 mapSize = theReader.LoadRef<QT3DSU32>();
+ for (QT3DSU32 mapIdx = 0; mapIdx < mapSize; ++mapIdx) {
+ InterpreterEventTypes::Enum evt =
+ static_cast<InterpreterEventTypes::Enum>(theReader.LoadRef<QT3DSU32>());
+ CRegisteredString stateId = theReader.LoadRef<CRegisteredString>();
+ stateId.Remap(inStringTableData);
+ QT3DSU32 numCommands = theReader.LoadRef<QT3DSU32>();
+ TCommandList &theList =
+ theSystem.m_CommandMap
+ .insert(eastl::make_pair(SStateEventKey(evt, stateId), TCommandList()))
+ .first->second;
+ for (QT3DSU32 cmdIdx = 0, cmdEnd = numCommands; cmdIdx < cmdEnd; ++cmdIdx) {
+ SVisualStateCommandNode *nextNode = theReader.Load<SVisualStateCommandNode>();
+ nextNode->m_Command.visit<void>(SLoadVisitor(inStringTableData));
+ theList.push_back(*nextNode);
+ }
+ }
+ }
+ }
+};
+}
+
+IVisualStateContext &IVisualStateContext::Create(NVFoundationBase &inFoundation,
+ IStringTable &inStrTable)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SVisualStateContext)(inFoundation, inStrTable);
+}
diff --git a/src/Runtime/Source/UICState/Source/UICStateXMLIO.cpp b/src/Runtime/Source/UICState/Source/UICStateXMLIO.cpp
new file mode 100644
index 00000000..f3bd7f08
--- /dev/null
+++ b/src/Runtime/Source/UICState/Source/UICStateXMLIO.cpp
@@ -0,0 +1,1948 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "UICStateXMLIO.h"
+#include "foundation/XML.h"
+#include "UICStateTypes.h"
+#include "UICStateContext.h"
+#include "foundation/Utils.h"
+#include "foundation/StringConversionImpl.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "EASTL/hash_map.h"
+#include "UICStateExecutionTypes.h"
+#include "UICStateEditor.h"
+#include "UICStateEditorValue.h"
+
+using namespace uic::state;
+using namespace uic::state::editor;
+
+namespace {
+#define ITERATE_XML_ELEMENT_NAMES \
+ HANDLE_XML_ELEMENT_NAME(scxml) \
+ HANDLE_XML_ELEMENT_NAME(state) \
+ HANDLE_XML_ELEMENT_NAME(parallel) \
+ HANDLE_XML_ELEMENT_NAME(transition) \
+ HANDLE_XML_ELEMENT_NAME(initial) \
+ HANDLE_XML_ELEMENT_NAME(final) \
+ HANDLE_XML_ELEMENT_NAME(onentry) \
+ HANDLE_XML_ELEMENT_NAME(onexit) \
+ HANDLE_XML_ELEMENT_NAME(history) \
+ HANDLE_XML_ELEMENT_NAME(raise) \
+ HANDLE_XML_ELEMENT_NAME(if) \
+ HANDLE_XML_ELEMENT_NAME(elseif) \
+ HANDLE_XML_ELEMENT_NAME(else) \
+ HANDLE_XML_ELEMENT_NAME(foreach) \
+ HANDLE_XML_ELEMENT_NAME(log) \
+ HANDLE_XML_ELEMENT_NAME(param) \
+ HANDLE_XML_ELEMENT_NAME(assign) \
+ HANDLE_XML_ELEMENT_NAME(script) \
+ HANDLE_XML_ELEMENT_NAME(send) \
+ HANDLE_XML_ELEMENT_NAME(cancel) \
+ HANDLE_XML_ELEMENT_NAME(invoke) \
+ HANDLE_XML_ELEMENT_NAME(finalize) \
+ HANDLE_XML_ELEMENT_NAME(cond) \
+ HANDLE_XML_ELEMENT_NAME(event) \
+ HANDLE_XML_ELEMENT_NAME(datamodel) \
+ HANDLE_XML_ELEMENT_NAME(data) \
+ HANDLE_XML_ELEMENT_NAME(content) \
+ HANDLE_XML_ELEMENT_NAME(external_transition)
+
+struct SXMLName
+{
+ enum Enum {
+#define HANDLE_XML_ELEMENT_NAME(nm) e##nm,
+ ITERATE_XML_ELEMENT_NAMES
+#undef HANDLE_XML_ELEMENT_NAME
+ LastName,
+ };
+ static const char *GetNameForElemName(Enum inName)
+ {
+ switch (inName) {
+#define HANDLE_XML_ELEMENT_NAME(nm) \
+ case e##nm: \
+ return #nm;
+ ITERATE_XML_ELEMENT_NAMES
+#undef HANDLE_XML_ELEMENT_NAME
+ default:
+ break;
+ }
+ QT3DS_ASSERT(false);
+ return "unknown element";
+ }
+};
+
+const char8_t *GetSCXMLNamespace()
+{
+ return "http://www.w3.org/2005/07/scxml";
+}
+const char8_t *GetStudioStateNamespace()
+{
+ return "http://qt.io/qt3dstudio/uicstate";
+}
+
+typedef eastl::pair<const char8_t *, NVConstDataRef<SStateNode *> *> TIdListPtrPair;
+typedef eastl::pair<const char8_t *, SSend **> TIdSendPair;
+
+TEditorStr DoGenerateUniqueId(const char *inRoot, IStateContext &ioContext,
+ IStringTable &ioStringTable)
+{
+ if (isTrivial(inRoot))
+ inRoot = "id";
+ TEditorStr stem(inRoot);
+ TEditorStr idStr(stem);
+ // Make the stem a valid possible id according xml specifications
+ if (idStr.size()) {
+ // Replace all spaces with undre
+ // Check that the first item isn't a space or a number. We can't do a real check here
+ // because we don't have unicode tables of letters and such.
+ // replace spaces with underscores.
+ for (TEditorStr::size_type thePos = idStr.find(' '); thePos != TEditorStr::npos;
+ thePos = idStr.find(' ', thePos + 1))
+ idStr.replace(thePos, 1, "_");
+ if (idStr[0] >= '0' && idStr[0] <= '9')
+ idStr.insert(idStr.begin(), 1, ':');
+ }
+
+ QT3DSU32 idx = 0;
+
+ while (ioContext.ContainsId(ioStringTable.RegisterStr(idStr.c_str()))) {
+ ++idx;
+ char temp[64];
+ sprintf(temp, "%d", idx);
+ idStr.assign(stem);
+ idStr.append("_");
+ idStr.append(temp);
+ }
+
+ return idStr;
+}
+
+struct SParseContext
+{
+ typedef nvvector<eastl::pair<CRegisteredString, STransition *>> TExternalTransitionList;
+
+ NVAllocatorCallback &m_GraphAllocator;
+ NVFoundationBase &m_Foundation;
+ IDOMReader &m_Reader;
+ IStateContext &m_Context;
+ IStringTable &m_StrTable;
+ IEditor *m_Editor;
+ CRegisteredString m_Names[SXMLName::LastName];
+ MemoryBuffer<ForwardingAllocator> m_ParseBuffer;
+ nvvector<char8_t> m_TempBuffer;
+ // To be filled in on the second parse pass
+ nvvector<TIdListPtrPair> m_References;
+ nvvector<TIdSendPair> m_SendReferences;
+ CXMLIO::TIdRemapMap m_RemapMap;
+ nvvector<SIdValue> m_GenerateIdList;
+ TExternalTransitionList m_ExternalTransitions;
+ CRegisteredString m_SCXMLNamespace;
+ CRegisteredString m_StudioNamespace;
+ QT3DSI32 m_UICVersion;
+
+ SParseContext(NVAllocatorCallback &inGraphAlloc, NVFoundationBase &inFnd, IDOMReader &inReader,
+ IStateContext &inCtx, IStringTable &inStrTable, IEditor *inEditor)
+ : m_GraphAllocator(inGraphAlloc)
+ , m_Foundation(inFnd)
+ , m_Reader(inReader)
+ , m_Context(inCtx)
+ , m_StrTable(inStrTable)
+ , m_Editor(inEditor)
+ , m_ParseBuffer(ForwardingAllocator(inFnd.getAllocator(), "ParseBuffer"))
+ , m_TempBuffer(inFnd.getAllocator(), "TempBuffer")
+ , m_References(inFnd.getAllocator(), "m_References")
+ , m_SendReferences(inFnd.getAllocator(), "m_StrReferences")
+ , m_GenerateIdList(inFnd.getAllocator(), "m_GenerateIdList")
+ , m_ExternalTransitions(inFnd.getAllocator(), "m_ExternalTransitions")
+ , m_UICVersion(SSCXML::GetCurrentUICVersion())
+ {
+#define HANDLE_XML_ELEMENT_NAME(nm) m_Names[SXMLName::e##nm] = inStrTable.RegisterStr(#nm);
+ ITERATE_XML_ELEMENT_NAMES
+#undef HANDLE_XML_ELEMENT_NAME
+ m_SCXMLNamespace = inStrTable.RegisterStr(GetSCXMLNamespace());
+ m_StudioNamespace = inStrTable.RegisterStr(GetStudioStateNamespace());
+ }
+
+ inline bool eq(CRegisteredString lhs, SXMLName::Enum rhs) { return lhs == m_Names[rhs]; }
+ const char8_t *ToGraphStr(const char8_t *temp)
+ {
+ temp = nonNull(temp);
+ QT3DSU32 len = StrLen(temp) + 1;
+ char8_t *retval =
+ (char8_t *)m_GraphAllocator.allocate(len, "graph string", __FILE__, __LINE__);
+ memCopy(retval, temp, len);
+ // Force null termination regardless.
+ retval[len] = 0;
+ return retval;
+ }
+ const char8_t *ParseStrAtt(const char8_t *attName)
+ {
+ const char8_t *temp;
+ if (m_Reader.UnregisteredAtt(attName, temp) && temp && *temp)
+ return ToGraphStr(temp);
+ return NULL;
+ }
+ void ParseStrAtt(const char8_t *attName, const char8_t *&outVal)
+ {
+ outVal = ParseStrAtt(attName);
+ }
+ void ParseStrAtt(const char8_t *attName, CRegisteredString &outVal)
+ {
+ m_Reader.Att(attName, outVal);
+ }
+
+ SItemExtensionInfo &GetExtensionInfo(void *inItem)
+ {
+ return m_Context.GetOrCreateExtensionInfo(inItem);
+ }
+
+ // Extension attributes are indicated by their namespace. If they have a namespace
+ // and they aren't scxml namespace and they aren't studio namespace, they are extension.
+ void ParseExtensionAttributes(void *inItem)
+ {
+ for (SDOMAttribute *theAttribute = m_Reader.GetFirstAttribute(); theAttribute;
+ theAttribute = theAttribute->m_NextAttribute) {
+ if (theAttribute->m_Namespace != m_StudioNamespace
+ && theAttribute->m_Namespace != m_SCXMLNamespace
+ && theAttribute->m_Namespace.IsValid()) {
+ GetExtensionInfo(inItem).m_ExtensionAttributes.push_back(
+ *QT3DS_NEW(m_GraphAllocator, SDOMAttributeNode)(theAttribute));
+ }
+ }
+ }
+ bool ParseExtensionElement(void *inItem)
+ {
+ SDOMElement &theElement(*m_Reader.GetElement());
+
+ if (theElement.m_Namespace != m_StudioNamespace
+ && theElement.m_Namespace != m_SCXMLNamespace && theElement.m_Namespace.IsValid()) {
+ GetExtensionInfo(inItem).m_ExtensionNodes.push_back(
+ *QT3DS_NEW(m_GraphAllocator, SDOMElementNode)(&theElement));
+ return true;
+ }
+ return false;
+ }
+
+ void ParseExtensionElements(void *inItem)
+ {
+ IDOMReader::Scope _childElemScope(m_Reader);
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ ParseExtensionElement(inItem);
+ }
+ }
+
+ NVConstDataRef<QT3DSF32> ParseFloats(const char8_t *inData)
+ {
+ size_t len = StrLen(inData) + 1;
+ if (len == 1)
+ return NVConstDataRef<QT3DSF32>();
+ m_TempBuffer.resize((QT3DSU32)len);
+ memCopy(m_TempBuffer.data(), inData, (QT3DSU32)len);
+ m_ParseBuffer.clear();
+ Char8TReader theReader(m_TempBuffer.data(), m_ParseBuffer);
+ NVConstDataRef<QT3DSF32> retval;
+ theReader.ReadBuffer(retval);
+ return retval;
+ }
+ bool ParseVec2Att(const char8_t *attName, QT3DSVec2 &outVal)
+ {
+ const char8_t *tempVal;
+ if (m_Reader.UnregisteredAtt(attName, tempVal, GetStudioStateNamespace())) {
+ NVConstDataRef<QT3DSF32> floats = ParseFloats(tempVal);
+ if (floats.mSize >= 2) {
+ memCopy(&outVal.x, floats.mData, sizeof(outVal));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool ParseVec3Att(const char8_t *attName, QT3DSVec3 &outVal)
+ {
+ const char8_t *tempVal;
+ if (m_Reader.UnregisteredAtt(attName, tempVal, GetStudioStateNamespace())) {
+ NVConstDataRef<QT3DSF32> floats = ParseFloats(tempVal);
+ if (floats.mSize >= 3) {
+ memCopy(&outVal.x, floats.mData, sizeof(outVal));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ CRegisteredString RemapStr(CRegisteredString inStr)
+ {
+ CXMLIO::TIdRemapMap::iterator iter = m_RemapMap.find(inStr.c_str());
+ if (iter != m_RemapMap.end())
+ inStr = m_StrTable.RegisterStr(iter->second.c_str());
+ return inStr;
+ }
+
+ SStateNode *FindStateNode(CRegisteredString inString)
+ {
+ return m_Context.FindStateNode(RemapStr(inString));
+ }
+
+ SSend *ParseSendIdSecondPass(const char8_t *inStr)
+ {
+ if (isTrivial(inStr))
+ return NULL;
+ return m_Context.FindSend(RemapStr(m_StrTable.RegisterStr(inStr)));
+ }
+
+ NVConstDataRef<SStateNode *> ParseIDRefSecondPass(const char8_t *inStr)
+ {
+ typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+ TStrType workspace(ForwardingAllocator(m_Foundation.getAllocator(), "ParseIDRef"));
+ TStrType str(ForwardingAllocator(m_Foundation.getAllocator(), "ParseIDRef"));
+ nvvector<SStateNode *> tempVal(m_Foundation.getAllocator(), "ParseIDRef");
+
+ workspace.assign(inStr);
+ for (TStrType::size_type startPos = workspace.find_first_not_of(' '),
+ endPos = workspace.find_first_of(' ', startPos);
+ startPos != TStrType::npos; startPos = workspace.find_first_not_of(' ', endPos),
+ endPos = workspace.find_first_of(' ', startPos)) {
+ if (endPos == TStrType::npos)
+ endPos = workspace.size();
+ str = workspace.substr(startPos, endPos - startPos);
+ CRegisteredString theStr(m_StrTable.RegisterStr(str.c_str()));
+ SStateNode *theNode = FindStateNode(theStr);
+ if (theNode)
+ tempVal.push_back(theNode);
+ }
+ if (tempVal.size() == 0)
+ return NVConstDataRef<SStateNode *>();
+
+ SStateNode **dataPtr = (SStateNode **)m_GraphAllocator.allocate(
+ tempVal.size() * sizeof(SStateNode *), "IDRef", __FILE__, __LINE__);
+ memCopy(dataPtr, tempVal.data(), tempVal.size() * sizeof(SStateNode *));
+ return toDataRef(dataPtr, tempVal.size());
+ }
+
+ void ParseIDRef(const char8_t *inStr, NVConstDataRef<SStateNode *> &ioNodes)
+ {
+ if (inStr == NULL || *inStr == 0) {
+ ioNodes = NVConstDataRef<SStateNode *>();
+ return;
+ }
+ m_References.push_back(eastl::make_pair(inStr, &ioNodes));
+ }
+
+ static void AppendChild(SStateNode &inParent, TStateNodeList &outChildren, SStateNode &inChild)
+ {
+ inChild.m_Parent = &inParent;
+ outChildren.push_back(inChild);
+ }
+
+ static void AppendChild(SStateNode *inNodeParent, SExecutableContent *inParent,
+ TExecutableContentList &outChildren, SExecutableContent &inChild)
+ {
+ if (inNodeParent) {
+ QT3DS_ASSERT(inParent == NULL);
+ } else {
+ QT3DS_ASSERT(inParent);
+ }
+ inChild.m_StateNodeParent = inNodeParent;
+ inChild.m_Parent = inParent;
+ outChildren.push_back(inChild);
+ }
+
+ template <typename TStateType>
+ void ParseEditorAttributes(TStateType &inNode)
+ {
+ ParseExtensionAttributes(&inNode);
+ if (m_Editor) {
+ const char8_t *name;
+ if (m_Reader.UnregisteredAtt("id", name, GetStudioStateNamespace()))
+ m_Editor->GetOrCreate(inNode)->SetPropertyValue("id", eastl::string(nonNull(name)));
+
+ QT3DSVec2 temp;
+ if (ParseVec2Att("position", temp))
+ m_Editor->GetOrCreate(inNode)->SetPropertyValue("position", temp);
+
+ if (ParseVec2Att("dimension", temp))
+ m_Editor->GetOrCreate(inNode)->SetPropertyValue("dimension", temp);
+
+ QT3DSVec3 tempv3;
+ if (ParseVec3Att("color", tempv3))
+ m_Editor->GetOrCreate(inNode)->SetPropertyValue("dimension", tempv3);
+ }
+ }
+
+ void ParseStateNodeEditorAttributes(SStateNode &inNode)
+ {
+ ParseExtensionAttributes(&inNode);
+ CRegisteredString Id;
+ if (inNode.m_Id.IsValid() == false)
+ m_Reader.Att("id", inNode.m_Id);
+
+ QT3DSVec2 temp;
+ if (ParseVec2Att("position", temp))
+ inNode.SetPosition(temp);
+
+ if (ParseVec2Att("dimension", temp))
+ inNode.SetDimension(temp);
+
+ QT3DSVec3 tempv3;
+ if (ParseVec3Att("color", tempv3))
+ inNode.SetColor(tempv3);
+
+ if (m_Editor) {
+ const char8_t *desc;
+ if (m_Reader.UnregisteredAtt("description", desc, GetStudioStateNamespace()))
+ m_Editor->ToEditor(inNode)->SetPropertyValue("description",
+ eastl::string(nonNull(desc)));
+ }
+ }
+
+ // Parse the node id. IF it exists, then schedule the id for remapping.
+ template <typename TDataType>
+ void ParseNodeId(TDataType &inNode)
+ {
+ m_Reader.Att("id", inNode.m_Id);
+ if (inNode.m_Id.IsValid() == false || m_Context.ContainsId(inNode.m_Id)) {
+ m_GenerateIdList.push_back(&inNode);
+ } else {
+ bool success = m_Context.InsertId(inNode.m_Id, &inNode);
+ (void)success;
+ QT3DS_ASSERT(success);
+ }
+ }
+
+ SParam &ParseParam()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SParam *retval = QT3DS_NEW(m_GraphAllocator, SParam)();
+ ParseStrAtt("name", retval->m_Name);
+ ParseStrAtt("expr", retval->m_Expr);
+ ParseStrAtt("location", retval->m_Location);
+ ParseExtensionAttributes(retval);
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+
+ SContent &ParseContent()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SContent *retval = QT3DS_NEW(m_GraphAllocator, SContent)();
+ ParseStrAtt("expr", retval->m_Expr);
+ if (isTrivial(retval->m_Expr)) {
+ if (m_Reader.CountChildren() == 0) {
+ const char8_t *val = NULL;
+ m_Reader.Value(val);
+ if (!isTrivial(val))
+ retval->m_ContentValue = this->ToGraphStr(val);
+ }
+ // We don't implement any extensions, so this is most certainly going into the
+ // extensions bin for this content.
+ else {
+ }
+ }
+ ParseExtensionAttributes(retval);
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+
+ SExecutableContent &ParseSend()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SSend *retval = QT3DS_NEW(m_GraphAllocator, SSend)();
+ ParseStrAtt("event", retval->m_Event);
+ ParseStrAtt("eventexpr", retval->m_EventExpr);
+ ParseStrAtt("target", retval->m_Target);
+ ParseStrAtt("targetexpr", retval->m_TargetExpr);
+ ParseStrAtt("type", retval->m_Type);
+ ParseStrAtt("typeExpr", retval->m_TypeExpr);
+ ParseNodeId(*retval);
+ ParseStrAtt("idlocation", retval->m_IdLocation);
+ ParseStrAtt("delay", retval->m_Delay);
+ ParseStrAtt("delayexpr", retval->m_DelayExpr);
+ ParseStrAtt("namelist", retval->m_NameList);
+ ParseExtensionAttributes(retval);
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (eq(elemName, SXMLName::eparam))
+ AppendChild(NULL, retval, retval->m_Children, ParseParam());
+ else if (eq(elemName, SXMLName::econtent))
+ retval->m_Children.push_back(ParseContent());
+ else {
+ if (!ParseExtensionElement(retval)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse send child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ m_Context.AddSendToList(*retval);
+ return *retval;
+ }
+ SExecutableContent &ParseIf()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SIf *retval = QT3DS_NEW(m_GraphAllocator, SIf)();
+ ParseStrAtt("cond", retval->m_Cond);
+ ParseExtensionAttributes(retval);
+ ParseExecutableContent(NULL, retval, retval->m_Children, retval);
+ return *retval;
+ }
+
+ SExecutableContent &ParseElseIf()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SElseIf *retval = QT3DS_NEW(m_GraphAllocator, SElseIf)();
+ ParseStrAtt("cond", retval->m_Cond);
+ ParseExtensionAttributes(retval);
+ ParseExecutableContent(NULL, retval, retval->m_Children, retval);
+ return *retval;
+ }
+
+ SExecutableContent &ParseElse()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SElse *retval = QT3DS_NEW(m_GraphAllocator, SElse)();
+ ParseExtensionAttributes(retval);
+ ParseExecutableContent(NULL, retval, retval->m_Children, retval);
+ return *retval;
+ }
+ SExecutableContent &ParseForEach()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SForeach *retval = QT3DS_NEW(m_GraphAllocator, SForeach)();
+ ParseStrAtt("array", retval->m_Array);
+ ParseStrAtt("item", retval->m_Item);
+ ParseStrAtt("index", retval->m_Index);
+ ParseExtensionAttributes(retval);
+ ParseExecutableContent(NULL, retval, retval->m_Children, retval);
+ return *retval;
+ }
+
+ SExecutableContent &ParseRaise()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SRaise *retval = QT3DS_NEW(m_GraphAllocator, SRaise)();
+ ParseStrAtt("event", retval->m_Event);
+ ParseExtensionAttributes(retval);
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+
+ SExecutableContent &ParseLog()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SLog *retval = QT3DS_NEW(m_GraphAllocator, SLog)();
+ ParseStrAtt("label", retval->m_Label);
+ ParseStrAtt("expr", retval->m_Expression);
+ ParseExtensionAttributes(retval);
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+
+ SData &ParseData()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SData *retval = QT3DS_NEW(m_GraphAllocator, SData)();
+ ParseStrAtt("id", retval->m_Id);
+ ParseStrAtt("src", retval->m_Source);
+ ParseStrAtt("expr", retval->m_Expression);
+ ParseEditorAttributes(*retval);
+ ParseExtensionElements(retval);
+ const char8_t *value;
+ m_Reader.Value(value);
+ // Not handling arbitrary content under data right now.
+ if (isTrivial(retval->m_Expression) && !isTrivial(value)) {
+ retval->m_Expression = ToGraphStr(value);
+ }
+ return *retval;
+ }
+
+ SDataModel *ParseDataModel()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SDataModel *retval = QT3DS_NEW(m_GraphAllocator, SDataModel)();
+ ParseStrAtt("id", retval->m_Id);
+ ParseStrAtt("src", retval->m_Source);
+ ParseStrAtt("expr", retval->m_Expression);
+ ParseEditorAttributes(*retval);
+ for (bool success = m_Reader.MoveToFirstChild("data"); success;
+ success = m_Reader.MoveToNextSibling("data"))
+ retval->m_Data.push_back(ParseData());
+
+ ParseExtensionElements(retval);
+
+ return retval;
+ }
+
+ SExecutableContent &ParseAssign()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SAssign *retval = QT3DS_NEW(m_GraphAllocator, SAssign)();
+ ParseStrAtt("location", retval->m_Location);
+ ParseStrAtt("expr", retval->m_Expression);
+ ParseExtensionAttributes(retval);
+ ParseExtensionElements(retval);
+ // Not dealing with children.
+ return *retval;
+ }
+
+ SExecutableContent &ParseScript()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SScript *retval = QT3DS_NEW(m_GraphAllocator, SScript)();
+ ParseStrAtt("src", retval->m_URL);
+ ParseExtensionAttributes(retval);
+ if (m_Reader.Value(retval->m_Data))
+ retval->m_Data = ToGraphStr(retval->m_Data);
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+
+ SExecutableContent &ParseCancel()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SCancel *retval = QT3DS_NEW(m_GraphAllocator, SCancel)();
+ const char8_t *sendId;
+ if (m_Reader.UnregisteredAtt("sendid", sendId))
+ m_SendReferences.push_back(eastl::make_pair(sendId, &retval->m_Send));
+ ParseStrAtt("sendidexpr", retval->m_IdExpression);
+ ParseExtensionAttributes(retval);
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+ struct SExecutableContentParseBinding
+ {
+ SXMLName::Enum m_Name;
+ typedef SExecutableContent &(SParseContext::*TParseFunc)();
+ TParseFunc m_ParseFunc;
+ };
+
+ static NVDataRef<SExecutableContentParseBinding> GetParseBindings()
+ {
+ static SExecutableContentParseBinding s_ExecContentParseBindings[10] = {
+ { SXMLName::esend, &SParseContext::ParseSend },
+ { SXMLName::eif, &SParseContext::ParseIf },
+ { SXMLName::eelseif, &SParseContext::ParseElseIf },
+ { SXMLName::eelse, &SParseContext::ParseElse },
+ { SXMLName::eforeach, &SParseContext::ParseForEach },
+ { SXMLName::eraise, &SParseContext::ParseRaise },
+ { SXMLName::elog, &SParseContext::ParseLog },
+ { SXMLName::eassign, &SParseContext::ParseAssign },
+ { SXMLName::escript, &SParseContext::ParseScript },
+ { SXMLName::ecancel, &SParseContext::ParseCancel },
+ };
+
+ return toDataRef(s_ExecContentParseBindings, 10);
+ }
+
+ bool ParseExecutableContentItem(SStateNode *inNodeParent, SExecutableContent *inParent,
+ TExecutableContentList &outContent)
+ {
+ CRegisteredString elemName = m_Reader.GetElementName();
+ NVDataRef<SExecutableContentParseBinding> theBindingList(GetParseBindings());
+ for (QT3DSU32 idx = 0, end = theBindingList.size(); idx < end; ++idx) {
+ SExecutableContentParseBinding theBinding(theBindingList[idx]);
+ if (eq(elemName, theBinding.m_Name)) {
+ AppendChild(inNodeParent, inParent, outContent, (this->*theBinding.m_ParseFunc)());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void ParseExecutableContent(SStateNode *inStateNodeParent, SExecutableContent *inParent,
+ TExecutableContentList &outContent, void *inExtensionPtr)
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (!ParseExecutableContentItem(inStateNodeParent, inParent, outContent)) {
+ if (!ParseExtensionElement(inExtensionPtr)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse extension child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+
+ SOnEntry &ParseOnEntry(SStateNode &inParent)
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SOnEntry *retval = QT3DS_NEW(m_GraphAllocator, SOnEntry)();
+ ParseExecutableContent(&inParent, NULL, retval->m_ExecutableContent, retval);
+ return *retval;
+ }
+
+ SOnExit &ParseOnExit(SStateNode &inParent)
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SOnExit *retval = QT3DS_NEW(m_GraphAllocator, SOnExit)();
+ ParseExecutableContent(&inParent, NULL, retval->m_ExecutableContent, retval);
+ return *retval;
+ }
+
+ SHistory &ParseHistory()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SHistory *retval = QT3DS_NEW(m_GraphAllocator, SHistory)();
+ ParseNodeId(*retval);
+ const char8_t *temp;
+ if (m_Reader.UnregisteredAtt("type", temp) && AreEqual(temp, "deep"))
+ retval->m_Flags.SetDeep(true);
+ ParseStateNodeEditorAttributes(*retval);
+ if (m_Reader.MoveToFirstChild("transition")) {
+ retval->m_Transition = &ParseTransition();
+ retval->m_Transition->m_Parent = retval;
+ }
+ ParseExtensionElements(retval);
+ return *retval;
+ }
+
+ STransition &ParseTransition()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ STransition *retval = QT3DS_NEW(m_GraphAllocator, STransition)();
+ m_Reader.Att("event", retval->m_Event);
+ ParseNodeId(*retval);
+ const char8_t *temp;
+ if (m_Reader.UnregisteredAtt("target", temp)) {
+ ParseIDRef(temp, retval->m_Target);
+ }
+ if (m_Reader.UnregisteredAtt("type", temp) && AreEqual(temp, "internal"))
+ retval->m_Flags.SetInternal(true);
+ ParseStateNodeEditorAttributes(*retval);
+
+ retval->m_Condition = ParseStrAtt("cond");
+ // Position and such is only valid for transitions after UIC version 0.
+ if (m_UICVersion > 0) {
+ QT3DSVec2 endPos;
+ if (ParseVec2Att("end_position", endPos))
+ retval->SetEndPosition(endPos);
+
+ if (m_Reader.UnregisteredAtt("path", temp)) {
+ NVConstDataRef<QT3DSF32> pathData = ParseFloats(temp);
+ QT3DS_ASSERT((pathData.size() % 2) == 0);
+ size_t newDataSize = pathData.size() * sizeof(QT3DSF32);
+ QT3DSVec2 *newData = (QT3DSVec2 *)m_GraphAllocator.allocate(
+ newDataSize, "STransition::m_Path", __FILE__, __LINE__);
+ memCopy(newData, pathData.begin(), (QT3DSU32)newDataSize);
+ retval->m_Path = toDataRef(newData, (QT3DSU32)(newDataSize / sizeof(QT3DSVec2)));
+ }
+ } else {
+ retval->SetPosition(Empty());
+ }
+
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (!ParseExecutableContentItem(retval, NULL, retval->m_ExecutableContent)) {
+ if (!ParseExtensionElement(retval)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse transition child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ return *retval;
+ }
+
+ SFinal &ParseFinal()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SFinal *retval = QT3DS_NEW(m_GraphAllocator, SFinal)();
+
+ ParseNodeId(*retval);
+ ParseStateNodeEditorAttributes(*retval);
+
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (eq(elemName, SXMLName::eonentry))
+ retval->m_OnEntry.push_back(ParseOnEntry(*retval));
+ else if (eq(elemName, SXMLName::eonexit))
+ retval->m_OnExit.push_back(ParseOnExit(*retval));
+ else if (!ParseExtensionElement(retval)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse final child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ return *retval;
+ }
+
+ bool ParseStateParallelChildren(SStateNode &inParent, CRegisteredString &inElemName,
+ TStateNodeList &outChildren, TOnEntryList &inOnEntry,
+ TOnExitList &inOnExit, SDataModel *&dmPtr)
+ {
+ if (eq(inElemName, SXMLName::estate))
+ AppendChild(inParent, outChildren, ParseState());
+ else if (eq(inElemName, SXMLName::etransition))
+ AppendChild(inParent, outChildren, ParseTransition());
+ else if (eq(inElemName, SXMLName::eparallel))
+ AppendChild(inParent, outChildren, ParseParallel());
+ else if (eq(inElemName, SXMLName::eonentry))
+ inOnEntry.push_back(ParseOnEntry(inParent));
+ else if (eq(inElemName, SXMLName::eonexit))
+ inOnExit.push_back(ParseOnExit(inParent));
+ else if (eq(inElemName, SXMLName::ehistory))
+ AppendChild(inParent, outChildren, ParseHistory());
+ else if (eq(inElemName, SXMLName::efinal))
+ AppendChild(inParent, outChildren, ParseFinal());
+ else if (eq(inElemName, SXMLName::edatamodel))
+ dmPtr = ParseDataModel();
+ else {
+ return false;
+ }
+ return true;
+ }
+
+ SStateNode &ParseParallel()
+ {
+ IDOMReader::Scope _itemScope(m_Reader);
+ SParallel *retval = QT3DS_NEW(m_GraphAllocator, SParallel)();
+ ParseNodeId(*retval);
+ ParseStateNodeEditorAttributes(*retval);
+
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (!ParseStateParallelChildren(*retval, elemName, retval->m_Children,
+ retval->m_OnEntry, retval->m_OnExit,
+ retval->m_DataModel)) {
+ if (!ParseExtensionElement(retval)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse parallel child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ return *retval;
+ }
+
+ void SetStateInitialTransition(STransition *&ioInitial, TStateNodeList &inChildren,
+ SStateNode &inSource)
+ {
+ if (ioInitial) {
+ ioInitial->m_Parent = &inSource;
+ return;
+ }
+ SStateNode *firstStateChild = NULL;
+ for (TStateNodeList::iterator iter = inChildren.begin();
+ iter != inChildren.end() && firstStateChild == NULL; ++iter) {
+ if (iter->m_Type == StateNodeTypes::State || iter->m_Type == StateNodeTypes::Parallel
+ || iter->m_Type == StateNodeTypes::Final) {
+ firstStateChild = &(*iter);
+ }
+ }
+
+ if (firstStateChild) {
+ STransition *theTransition = QT3DS_NEW(m_GraphAllocator, STransition)();
+ size_t byteSize = sizeof(SStateNode *);
+ SStateNode **theData = (SStateNode **)m_GraphAllocator.allocate(
+ byteSize, "InitialTransition", __FILE__, __LINE__);
+ *theData = firstStateChild;
+ theTransition->m_Target = toDataRef(theData, 1);
+ theTransition->m_Parent = &inSource;
+ ioInitial = theTransition;
+ }
+ }
+
+ STransition *ParseInitial()
+ {
+ if (m_Reader.MoveToFirstChild("transition"))
+ return &ParseTransition();
+ else {
+ QT3DS_ASSERT(false);
+ }
+ return NULL;
+ }
+
+ SStateNode &ParseState()
+ {
+ IDOMReader::Scope _stateScope(m_Reader);
+ SState *theNewState = QT3DS_NEW(m_GraphAllocator, SState)();
+ ParseNodeId(*theNewState);
+ const char8_t *initialAtt;
+ if (m_Reader.UnregisteredAtt("initialexpr", initialAtt, GetStudioStateNamespace())) {
+ theNewState->m_InitialExpr = ToGraphStr(initialAtt);
+ const char8_t *errorTest;
+ if (m_Reader.UnregisteredAtt("initial", errorTest)) {
+ qCCritical(INVALID_OPERATION, "Attribute initial=\"%s\" conflicts with "
+ "attribute initialexpr=\"%s\" on <state "
+ "id=\"%s\">; using initialexpr.",
+ nonNull(errorTest), nonNull(initialAtt),
+ nonNull(theNewState->m_Id.c_str()));
+ }
+ } else if (m_Reader.UnregisteredAtt("initial", initialAtt) && !isTrivial(initialAtt)) {
+ STransition *theTransition = QT3DS_NEW(m_GraphAllocator, STransition)();
+ ParseIDRef(initialAtt, theTransition->m_Target);
+ theTransition->m_Parent = theNewState;
+ theNewState->m_Initial = theTransition;
+ }
+
+ ParseStateNodeEditorAttributes(*theNewState);
+
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (!ParseStateParallelChildren(*theNewState, elemName, theNewState->m_Children,
+ theNewState->m_OnEntry, theNewState->m_OnExit,
+ theNewState->m_DataModel)) {
+ // InitialExpr takes precedence over initial transition
+ if (eq(elemName, SXMLName::einitial) && isTrivial(theNewState->m_InitialExpr)) {
+ if (!theNewState->m_Initial)
+ theNewState->m_Initial = ParseInitial();
+ } else {
+ if (!ParseExtensionElement(theNewState)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse state child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ }
+ if (isTrivial(theNewState->m_InitialExpr))
+ SetStateInitialTransition(theNewState->m_Initial, theNewState->m_Children,
+ *theNewState);
+ return *theNewState;
+ }
+
+ static const char8_t *GetDefaultIdName(SStateNode &theNode)
+ {
+ const char8_t *theTemp = "id";
+ switch (theNode.m_Type) {
+ case StateNodeTypes::State:
+ theTemp = "state";
+ break;
+ case StateNodeTypes::Parallel:
+ theTemp = "parallel";
+ break;
+ case StateNodeTypes::Final:
+ theTemp = "final";
+ break;
+ case StateNodeTypes::History:
+ theTemp = "history";
+ break;
+ case StateNodeTypes::Transition:
+ theTemp = "transition";
+ break;
+ default:
+ break;
+ }
+ return theTemp;
+ }
+
+ static const char8_t *GetDefaultIdName(SSend &) { return "send"; }
+
+ template <typename TDataType>
+ void GenerateIdValue(TDataType &theNode)
+ {
+ if (theNode.m_Id.IsValid() == true) {
+ bool preexisting = m_Context.ContainsId(theNode.m_Id);
+ if (preexisting) {
+ CRegisteredString oldId = theNode.m_Id;
+ theNode.m_Id = CRegisteredString();
+ CXMLIO::GenerateUniqueId(theNode, oldId.c_str(), m_Context, m_StrTable);
+ bool success = m_RemapMap.insert(eastl::make_pair(oldId, theNode.m_Id)).second;
+ (void)success;
+ QT3DS_ASSERT(success);
+ }
+ } else {
+ CXMLIO::GenerateUniqueId(theNode, GetDefaultIdName(theNode), m_Context, m_StrTable);
+ }
+ }
+
+ void FinishParsing()
+ {
+ for (QT3DSU32 idx = 0, end = m_GenerateIdList.size(); idx < end; ++idx) {
+ SIdValue &theNode(m_GenerateIdList[idx]);
+ switch (theNode.getType()) {
+ case IdValueTypes::StateNode:
+ GenerateIdValue(*(theNode.getData<SStateNode *>()));
+ break;
+ case IdValueTypes::Send:
+ GenerateIdValue(*(theNode.getData<SSend *>()));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ for (QT3DSU32 idx = 0, end = m_References.size(); idx < end; ++idx)
+ *(m_References[idx].second) = ParseIDRefSecondPass(m_References[idx].first);
+
+ for (QT3DSU32 idx = 0, end = m_SendReferences.size(); idx < end; ++idx)
+ *(m_SendReferences[idx].second) = ParseSendIdSecondPass(m_SendReferences[idx].first);
+
+ if (m_Editor) {
+ for (QT3DSU32 idx = 0, end = m_ExternalTransitions.size(); idx < end; ++idx) {
+ SStateNode *theNode = FindStateNode(m_ExternalTransitions[idx].first);
+ if (theNode) {
+ TObjPtr transObj = m_Editor->GetOrCreate(*m_ExternalTransitions[idx].second);
+ TObjPtr stateObj = m_Editor->ToEditor(*theNode);
+ stateObj->Append("children", transObj);
+ }
+ }
+ }
+ }
+ SSCXML &ParseSCXML()
+ {
+ IDOMReader::Scope _stateScope(m_Reader);
+ SSCXML *retval = QT3DS_NEW(m_GraphAllocator, SSCXML)();
+
+ if (m_Reader.Att("id", retval->m_Id))
+ m_Context.InsertId(retval->m_Id, retval);
+ const char8_t *initial;
+ if (m_Reader.UnregisteredAtt("initialexpr", initial, GetStudioStateNamespace())) {
+ retval->m_InitialExpr = ToGraphStr(initial);
+ } else if (m_Reader.UnregisteredAtt("initial", initial)) {
+ STransition *theTransition = QT3DS_NEW(m_GraphAllocator, STransition)();
+ ParseIDRef(initial, theTransition->m_Target);
+ theTransition->m_Parent = retval;
+ retval->m_Initial = theTransition;
+ }
+ ParseStrAtt("name", retval->m_Name);
+ const char8_t *uicVersion;
+ if (!m_Reader.UnregisteredAtt("version", uicVersion, GetStudioStateNamespace()))
+ retval->m_UICVersion = 0;
+ else {
+ StringConversion<QT3DSI32>().StrTo(uicVersion, retval->m_UICVersion);
+ }
+ m_UICVersion = retval->m_UICVersion;
+ const char8_t *desc;
+ if (m_Editor && m_Reader.UnregisteredAtt("description", desc))
+ m_Editor->GetOrCreate(*retval)->SetPropertyValue("description", desc);
+
+ const char8_t *temp;
+ if (m_Reader.UnregisteredAtt("binding", temp) && AreEqual(temp, "late"))
+ retval->m_Flags.SetLateBinding(true);
+
+ ParseExtensionAttributes(retval);
+
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (eq(elemName, SXMLName::estate))
+ AppendChild(*retval, retval->m_Children, ParseState());
+ else if (eq(elemName, SXMLName::eparallel))
+ AppendChild(*retval, retval->m_Children, ParseParallel());
+ else if (eq(elemName, SXMLName::etransition))
+ AppendChild(*retval, retval->m_Children, ParseTransition());
+ else if (eq(elemName, SXMLName::efinal))
+ AppendChild(*retval, retval->m_Children, ParseFinal());
+ else if (eq(elemName, SXMLName::einitial))
+ retval->m_Initial = ParseInitial();
+ else if (eq(elemName, SXMLName::edatamodel))
+ retval->m_DataModel = ParseDataModel();
+ else {
+ if (!ParseExtensionElement(retval)) {
+ qCCritical(INTERNAL_ERROR, "Failed to parse scxml child %s", elemName.c_str());
+ QT3DS_ASSERT(false);
+ }
+ }
+ }
+ if (isTrivial(retval->m_InitialExpr)) {
+ SetStateInitialTransition(retval->m_Initial, retval->m_Children, *retval);
+ }
+ FinishParsing();
+ return *retval;
+ }
+ eastl::vector<SStateNode *> ParseFragment()
+ {
+ eastl::vector<SStateNode *> retval;
+
+ for (bool success = m_Reader.MoveToFirstChild(); success;
+ success = m_Reader.MoveToNextSibling()) {
+ IDOMReader::Scope _loopScope(m_Reader);
+ CRegisteredString elemName = m_Reader.GetElementName();
+ if (eq(elemName, SXMLName::estate))
+ retval.push_back(&ParseState());
+ else if (eq(elemName, SXMLName::eparallel))
+ retval.push_back(&ParseParallel());
+ else if (eq(elemName, SXMLName::efinal))
+ retval.push_back(&ParseFinal());
+ else if (eq(elemName, SXMLName::ehistory))
+ retval.push_back(&ParseHistory());
+ else if (eq(elemName, SXMLName::eexternal_transition)) {
+ CRegisteredString src;
+ m_Reader.Att("source", src);
+ if (src.IsValid())
+ m_ExternalTransitions.push_back(eastl::make_pair(src, &ParseTransition()));
+ } else {
+ qCCritical(INTERNAL_ERROR, "Failed to parse scxml child %s", elemName.c_str() );
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ FinishParsing();
+ return retval;
+ }
+};
+
+struct SWriteContext
+{
+ IDOMWriter &m_Writer;
+ IStateContext &m_Context;
+ IStringTable &m_StringTable;
+ const char8_t *m_CurrentNamespace;
+ const char8_t *m_Names[SXMLName::LastName];
+ eastl::string m_IdStr;
+ eastl::string m_RefListWorkspace;
+ IEditor *m_Editor;
+ MemoryBuffer<ForwardingAllocator> m_Buffer;
+ Option<QT3DSVec2> m_MousePos;
+ nvvector<SStateNode *> m_WrittenNodes;
+ nvvector<STransition *> m_ExternalTransitions;
+
+ SWriteContext(IDOMWriter &inWriter, IStateContext &inContext, IStringTable &inStrTable,
+ IEditor *inEditor, NVAllocatorCallback &inAlloc)
+ : m_Writer(inWriter)
+ , m_Context(inContext)
+ , m_StringTable(inStrTable)
+ , m_CurrentNamespace(GetSCXMLNamespace())
+ , m_Editor(inEditor)
+ , m_Buffer(ForwardingAllocator(inAlloc, "WriteBuffer"))
+ , m_WrittenNodes(inAlloc, "m_WrittenNodes")
+ , m_ExternalTransitions(inAlloc, "m_ExternalTransitions")
+ {
+#define HANDLE_XML_ELEMENT_NAME(nm) m_Names[SXMLName::e##nm] = #nm;
+ ITERATE_XML_ELEMENT_NAMES
+#undef HANDLE_XML_ELEMENT_NAME
+ }
+
+ void GenerateId(SStateNode &inNode, const char8_t *stem)
+ {
+ if (inNode.m_Id.IsValid() == false)
+ CXMLIO::GenerateUniqueId(inNode, stem, m_Context, m_StringTable);
+ }
+
+ void WriteExtensionElement(SDOMElement &elem)
+ {
+ IDOMWriter::Scope _elemScope(m_Writer, elem.m_Name.c_str(), elem.m_Namespace.c_str());
+ for (TAttributeList::iterator iter = elem.m_Attributes.begin(),
+ end = elem.m_Attributes.end();
+ iter != end; ++iter) {
+ SDOMAttribute &theAttribute(*iter);
+ m_Writer.Att(theAttribute.m_Name, theAttribute.m_Value,
+ theAttribute.m_Namespace.c_str());
+ }
+ for (SDOMElement::TElementChildList::iterator iter = elem.m_Children.begin(),
+ end = elem.m_Children.end();
+ iter != end; ++iter) {
+ WriteExtensionElement(elem);
+ }
+ if (!isTrivial(elem.m_Value)) {
+ m_Writer.Value(elem.m_Value);
+ }
+ }
+
+ void WriteExtensionData(void *inItem)
+ {
+ SItemExtensionInfo *infoPtr = m_Context.GetExtensionInfo(inItem);
+ if (infoPtr) {
+ SItemExtensionInfo &theInfo(*infoPtr);
+ for (TDOMAttributeNodeList::iterator iter = theInfo.m_ExtensionAttributes.begin(),
+ end = theInfo.m_ExtensionAttributes.end();
+ iter != end; ++iter) {
+ SDOMAttribute &theAttribute(*iter->m_Attribute);
+ m_Writer.Att(theAttribute.m_Name.c_str(), theAttribute.m_Value,
+ theAttribute.m_Namespace.c_str());
+ }
+ for (TDOMElementNodeList::iterator iter = theInfo.m_ExtensionNodes.begin(),
+ end = theInfo.m_ExtensionNodes.end();
+ iter != end; ++iter) {
+ WriteExtensionElement(*iter->m_Element);
+ }
+ }
+ }
+
+ void Att(const char8_t *inName, const char8_t *inData)
+ {
+ if (!isTrivial(inData))
+ m_Writer.Att(inName, inData, m_CurrentNamespace);
+ }
+
+ void Att(const char8_t *inName, CRegisteredString inData)
+ {
+ if (inData.IsValid())
+ m_Writer.Att(inName, inData.c_str(), m_CurrentNamespace);
+ }
+
+ void Att(const char8_t *inName, NVConstDataRef<CRegisteredString> inData)
+ {
+ m_RefListWorkspace.clear();
+ for (QT3DSU32 idx = 0, end = inData.size(); idx < end; ++idx) {
+ if (m_RefListWorkspace.size())
+ m_RefListWorkspace.append(" ");
+ m_RefListWorkspace.append(inData[idx].c_str());
+ }
+ if (m_RefListWorkspace.size())
+ Att(inName, m_RefListWorkspace.c_str());
+ }
+ void Att(const char8_t *inName, NVConstDataRef<SStateNode *> inData)
+ {
+ m_RefListWorkspace.clear();
+ for (QT3DSU32 idx = 0, end = inData.size(); idx < end; ++idx) {
+ if (m_RefListWorkspace.size())
+ m_RefListWorkspace.append(" ");
+ if (inData[idx])
+ m_RefListWorkspace.append(inData[idx]->m_Id.c_str());
+ }
+ if (m_RefListWorkspace.size())
+ Att(inName, m_RefListWorkspace.c_str());
+ }
+ void Att(const char8_t *inName, const QT3DSVec2 &inData)
+ {
+ m_Buffer.clear();
+ Char8TWriter writer(m_Buffer);
+ writer.Write(NVConstDataRef<QT3DSF32>(&inData.x, 2));
+ m_Buffer.writeZeros(1);
+ m_Writer.Att(inName, (const char8_t *)m_Buffer.begin(), GetStudioStateNamespace());
+ }
+
+ void Att(const char8_t *inName, const QT3DSVec3 &inData)
+ {
+ m_Buffer.clear();
+ Char8TWriter writer(m_Buffer);
+ writer.Write(NVConstDataRef<QT3DSF32>(&inData.x, 3));
+ m_Buffer.writeZeros(1);
+ m_Writer.Att(inName, (const char8_t *)m_Buffer.begin(), GetStudioStateNamespace());
+ }
+
+ void WriteEditorAttributes(void *inType, bool inUICId, bool inAdjustPos = false)
+ {
+ if (m_Editor) {
+ TObjPtr editorObj = m_Editor->GetEditor(inType);
+ if (editorObj != NULL) {
+ if (inUICId) {
+ eastl::string name = editorObj->GetId();
+ if (name.empty() == false)
+ m_Writer.Att("id", name.c_str(), GetStudioStateNamespace());
+ }
+ eastl::string description = editorObj->GetDescription();
+ if (description.empty() == false)
+ m_Writer.Att("description", description.c_str(), GetStudioStateNamespace());
+
+ Option<SValue> tempData = editorObj->GetPropertyValue("position");
+ if (tempData.hasValue()) {
+ QT3DSVec2 thePos(tempData->getData<QT3DSVec2>());
+ if (inAdjustPos && m_MousePos.hasValue()) {
+ // Get the global pos, not the local position.
+ for (TObjPtr parentPtr = editorObj->Parent(); parentPtr;
+ parentPtr = parentPtr->Parent()) {
+ Option<SValue> parentPos = parentPtr->GetPropertyValue("position");
+ if (parentPos.hasValue())
+ thePos += parentPos->getData<QT3DSVec2>();
+ }
+ // Store pos in global coords adjusted.
+ thePos -= *m_MousePos;
+ }
+ Att("position", thePos);
+ }
+
+ tempData = editorObj->GetPropertyValue("dimension");
+ if (tempData.hasValue())
+ Att("dimension", tempData->getData<QT3DSVec2>());
+
+ tempData = editorObj->GetPropertyValue("color");
+ if (tempData.hasValue())
+ Att("color", tempData->getData<QT3DSVec3>());
+ }
+ }
+ }
+
+ void WriteSend(SSend &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "send", m_CurrentNamespace);
+ Att("event", inContent.m_Event);
+ Att("eventexpr", inContent.m_EventExpr);
+ Att("target", inContent.m_Target);
+ Att("targetexpr", inContent.m_TargetExpr);
+ Att("type", inContent.m_Type);
+ Att("typeExpr", inContent.m_TypeExpr);
+ Att("id", inContent.m_Id);
+ Att("idlocation", inContent.m_IdLocation);
+ Att("delay", inContent.m_Delay);
+ Att("delayexpr", inContent.m_DelayExpr);
+ Att("namelist", inContent.m_NameList);
+ WriteExecutableContentList(inContent.m_Children);
+ WriteEditorAttributes(&inContent, false);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteParam(SParam &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "param", m_CurrentNamespace);
+ Att("name", inContent.m_Name);
+
+ if (!isTrivial(inContent.m_Expr))
+ Att("expr", inContent.m_Expr);
+ else if (!isTrivial(inContent.m_Location))
+ Att("location", inContent.m_Location);
+
+ WriteEditorAttributes(&inContent, false);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteContent(SContent &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "content", m_CurrentNamespace);
+ if (!isTrivial(inContent.m_Expr))
+ Att("expr", inContent.m_Expr);
+ else if (!isTrivial(inContent.m_ContentValue))
+ m_Writer.Value(inContent.m_ContentValue);
+
+ WriteEditorAttributes(&inContent, false);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteRaise(SRaise &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "raise", m_CurrentNamespace);
+ Att("event", inContent.m_Event);
+ WriteEditorAttributes(&inContent, false);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteAssign(SAssign &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "assign", m_CurrentNamespace);
+ Att("location", inContent.m_Location);
+ Att("expr", inContent.m_Expression);
+ WriteEditorAttributes(&inContent, false);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteIf(SIf &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "if", m_CurrentNamespace);
+ Att("cond", inContent.m_Cond);
+ WriteEditorAttributes(&inContent, false);
+ WriteExecutableContentList(inContent.m_Children);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteElseIf(SElseIf &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "elseif", m_CurrentNamespace);
+ WriteEditorAttributes(&inContent, false);
+ Att("cond", inContent.m_Cond);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteElse(SElse &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "else", m_CurrentNamespace);
+ WriteEditorAttributes(&inContent, false);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteLog(SLog &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "log", m_CurrentNamespace);
+ WriteEditorAttributes(&inContent, false);
+ Att("label", inContent.m_Label);
+ Att("expr", inContent.m_Expression);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteScript(SScript &inContent)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "script", m_CurrentNamespace);
+ WriteEditorAttributes(&inContent, false);
+ if (isTrivial(inContent.m_Data) && !isTrivial(inContent.m_URL))
+ Att("src", inContent.m_URL);
+ else
+ m_Writer.Value(inContent.m_Data);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteCancel(SCancel &inContent)
+ {
+ // Do not serialize invalid cancel items.
+ if (isTrivial(inContent.m_IdExpression) && inContent.m_Send == NULL)
+ return;
+
+ IDOMWriter::Scope _itemScope(m_Writer, "cancel", m_CurrentNamespace);
+ if (!inContent.m_Send && inContent.m_IdExpression)
+ Att("sendidexpr", inContent.m_IdExpression);
+ else
+ Att("sendid", inContent.m_Send->m_Id);
+
+ WriteEditorAttributes(&inContent, true);
+ WriteExtensionData(&inContent);
+ }
+
+ void WriteExecutableContent(SExecutableContent &inContent)
+ {
+ switch (inContent.m_Type) {
+ case ExecutableContentTypes::Send:
+ WriteSend(static_cast<SSend &>(inContent));
+ break;
+ case ExecutableContentTypes::Raise:
+ WriteRaise(static_cast<SRaise &>(inContent));
+ break;
+ case ExecutableContentTypes::Assign:
+ WriteAssign(static_cast<SAssign &>(inContent));
+ break;
+ case ExecutableContentTypes::If:
+ WriteIf(static_cast<SIf &>(inContent));
+ break;
+ case ExecutableContentTypes::ElseIf:
+ WriteElseIf(static_cast<SElseIf &>(inContent));
+ break;
+ case ExecutableContentTypes::Else:
+ WriteElse(static_cast<SElse &>(inContent));
+ break;
+ case ExecutableContentTypes::Log:
+ WriteLog(static_cast<SLog &>(inContent));
+ break;
+ case ExecutableContentTypes::Script:
+ WriteScript(static_cast<SScript &>(inContent));
+ break;
+ case ExecutableContentTypes::Cancel:
+ WriteCancel(static_cast<SCancel &>(inContent));
+ break;
+ case ExecutableContentTypes::Param:
+ WriteParam(static_cast<SParam &>(inContent));
+ break;
+ case ExecutableContentTypes::Content:
+ WriteContent(static_cast<SContent &>(inContent));
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ void WriteExecutableContentList(TExecutableContentList &inList)
+ {
+ for (TExecutableContentList::iterator contentIter = inList.begin(),
+ contentEnd = inList.end();
+ contentIter != contentEnd; ++contentIter)
+ WriteExecutableContent(*contentIter);
+ }
+
+ void WriteOnEntry(SOnEntry &inItem)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "onentry", m_CurrentNamespace);
+ WriteEditorAttributes(&inItem, true);
+ WriteExecutableContentList(inItem.m_ExecutableContent);
+ WriteExtensionData(&inItem);
+ }
+
+ void WriteOnEntryList(TOnEntryList &inList)
+ {
+ for (TOnEntryList::iterator iter = inList.begin(), end = inList.end(); iter != end; ++iter)
+ WriteOnEntry(*iter);
+ }
+
+ void WriteOnExit(SOnExit &inItem)
+ {
+ IDOMWriter::Scope _itemScope(m_Writer, "onexit", m_CurrentNamespace);
+ WriteEditorAttributes(&inItem, true);
+ WriteExecutableContentList(inItem.m_ExecutableContent);
+ WriteExtensionData(&inItem);
+ }
+
+ void WriteOnExitList(TOnExitList &inList)
+ {
+ for (TOnExitList::iterator iter = inList.begin(), end = inList.end(); iter != end; ++iter)
+ WriteOnExit(*iter);
+ }
+
+ void WriteDataModel(SDataModel &inDataModel)
+ {
+ IDOMWriter::Scope _transitionScope(m_Writer, "datamodel", m_CurrentNamespace);
+ WriteEditorAttributes(&inDataModel, true);
+ for (TDataList::iterator iter = inDataModel.m_Data.begin(), end = inDataModel.m_Data.end();
+ iter != end; ++iter) {
+ IDOMWriter::Scope _transitionScope(m_Writer, "data", m_CurrentNamespace);
+ Att("id", iter->m_Id);
+ Att("expr", iter->m_Expression);
+ WriteEditorAttributes(&(*iter), true);
+ WriteExtensionData(&(*iter));
+ }
+ WriteExtensionData(&inDataModel);
+ }
+
+ static inline SStateNode *FirstValidChild(SState &inNode)
+ {
+ for (TStateNodeList::iterator iter = inNode.m_Children.begin(),
+ end = inNode.m_Children.end();
+ iter != end; ++iter) {
+ switch (iter->m_Type) {
+ case StateNodeTypes::State:
+ case StateNodeTypes::Parallel:
+ case StateNodeTypes::Final:
+ return iter.m_Obj;
+ default:
+ break;
+ }
+ }
+ return NULL;
+ }
+
+ void WriteState(SState &inNode, bool inAdjustPos)
+ {
+ m_WrittenNodes.push_back(&inNode);
+ IDOMWriter::Scope _transitionScope(m_Writer, "state", m_CurrentNamespace);
+ GenerateId(inNode, "state");
+ Att("id", inNode.m_Id);
+ WriteEditorAttributes(&inNode, false, inAdjustPos);
+ if (!isTrivial(inNode.m_InitialExpr)) {
+ m_Writer.Att("initialexpr", inNode.m_InitialExpr, GetStudioStateNamespace());
+ } else if (inNode.m_Initial) {
+ // First check to see if this could be an attribute
+ if (inNode.m_Initial->m_ExecutableContent.empty()) {
+ // Now check if it has one child and if it has only one child and that child is the
+ // first valid possible child
+ // then we don't write out the attribute
+ bool canElideInitial = inNode.m_Initial->m_Target.size() == 0
+ || (inNode.m_Initial->m_Target.size() == 1
+ && inNode.m_Initial->m_Target[0] == FirstValidChild(inNode));
+ if (!canElideInitial)
+ Att("initial", inNode.m_Initial->m_Target);
+ } else {
+ IDOMWriter::Scope _transitionScope(m_Writer, "initial", m_CurrentNamespace);
+ WriteTransition(*inNode.m_Initial, false);
+ }
+ }
+ WriteOnEntryList(inNode.m_OnEntry);
+ WriteOnExitList(inNode.m_OnExit);
+ WriteStateNodeList(inNode.m_Children);
+ if (inNode.m_DataModel)
+ WriteDataModel(*inNode.m_DataModel);
+ WriteExtensionData(&inNode);
+ }
+
+ void WriteParallel(SParallel &inNode, bool inAdjustPos)
+ {
+ m_WrittenNodes.push_back(&inNode);
+ IDOMWriter::Scope _transitionScope(m_Writer, "parallel", m_CurrentNamespace);
+ GenerateId(inNode, "parallel");
+ Att("id", inNode.m_Id);
+ WriteEditorAttributes(&inNode, false, inAdjustPos);
+ WriteOnEntryList(inNode.m_OnEntry);
+ WriteOnExitList(inNode.m_OnExit);
+ WriteStateNodeList(inNode.m_Children);
+ if (inNode.m_DataModel)
+ WriteDataModel(*inNode.m_DataModel);
+ WriteExtensionData(&inNode);
+ }
+
+ void WriteHistory(SHistory &inNode, bool inAdjustPos)
+ {
+ m_WrittenNodes.push_back(&inNode);
+ IDOMWriter::Scope _transitionScope(m_Writer, "history", m_CurrentNamespace);
+ GenerateId(inNode, "history");
+ Att("id", inNode.m_Id);
+ if (inNode.m_Flags.IsDeep())
+ Att("type", "deep");
+ WriteEditorAttributes(&inNode, false, inAdjustPos);
+ if (inNode.m_Transition)
+ WriteTransition(*inNode.m_Transition, false);
+ WriteExtensionData(&inNode);
+ }
+ void WriteTransitionData(STransition &inNode)
+ {
+ Att("event", inNode.m_Event);
+ Att("cond", inNode.m_Condition);
+ Att("target", inNode.m_Target);
+ if (inNode.m_Flags.IsInternal())
+ Att("type", "internal");
+ WriteEditorAttributes(&inNode, true, false);
+ if (inNode.m_StateNodeFlags.HasEndPosition()) {
+ Att("end_position", inNode.m_EndPosition);
+ }
+ if (inNode.m_Path.mSize) {
+ m_Buffer.clear();
+ Char8TWriter writer(m_Buffer);
+ writer.Write(
+ NVConstDataRef<QT3DSF32>((const QT3DSF32 *)inNode.m_Path.mData, 2 * inNode.m_Path.mSize),
+ QT3DS_MAX_U32);
+ m_Buffer.writeZeros(1);
+ m_Writer.Att("path", (const char8_t *)m_Buffer.begin(), GetStudioStateNamespace());
+ }
+ WriteExecutableContentList(inNode.m_ExecutableContent);
+ WriteExtensionData(&inNode);
+ }
+ void WriteTransition(STransition &inNode, bool /*inAdjustPos*/)
+ {
+ IDOMWriter::Scope _transitionScope(m_Writer, "transition", m_CurrentNamespace);
+ WriteTransitionData(inNode);
+ }
+ void WriteExternalTransition(STransition &inNode)
+ {
+ if (inNode.m_Parent != NULL) {
+ IDOMWriter::Scope _transitionScope(m_Writer, "external_transition",
+ GetStudioStateNamespace());
+ m_Writer.Att("source", inNode.m_Parent->m_Id.c_str(), GetStudioStateNamespace());
+ WriteTransitionData(inNode);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+
+ void WriteFinal(SFinal &inNode, bool inAdjustPos)
+ {
+ m_WrittenNodes.push_back(&inNode);
+ IDOMWriter::Scope _transitionScope(m_Writer, "final", m_CurrentNamespace);
+ GenerateId(inNode, "history");
+ Att("id", inNode.m_Id);
+ WriteEditorAttributes(&inNode, false, inAdjustPos);
+ WriteOnEntryList(inNode.m_OnEntry);
+ WriteOnExitList(inNode.m_OnExit);
+ WriteExtensionData(&inNode);
+ }
+
+ void Write(SStateNode &inNode, bool inAdjustPos)
+ {
+ switch (inNode.m_Type) {
+ case StateNodeTypes::State:
+ WriteState(static_cast<SState &>(inNode), inAdjustPos);
+ break;
+ case StateNodeTypes::Parallel:
+ WriteParallel(static_cast<SParallel &>(inNode), inAdjustPos);
+ break;
+ case StateNodeTypes::History:
+ WriteHistory(static_cast<SHistory &>(inNode), inAdjustPos);
+ break;
+ case StateNodeTypes::Transition:
+ WriteTransition(static_cast<STransition &>(inNode), inAdjustPos);
+ break;
+ case StateNodeTypes::Final:
+ WriteFinal(static_cast<SFinal &>(inNode), inAdjustPos);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+ void WriteStateNodeList(TStateNodeList &inNodeList)
+ {
+ for (TStateNodeList::iterator iter = inNodeList.begin(), end = inNodeList.end();
+ iter != end; ++iter) {
+ Write((*iter), false);
+ }
+ }
+
+ void Write()
+ {
+ SSCXML &item = *m_Context.GetRoot();
+ GenerateId(item, "scxml");
+ Att("name", item.m_Name);
+ if (item.m_Flags.IsLateBinding())
+ Att("binding", "late");
+ Att("version", "1");
+ m_Writer.Att("version", SSCXML::GetCurrentUICVersion(), GetStudioStateNamespace());
+
+ if (!isTrivial(item.m_InitialExpr)) {
+ m_Writer.Att("initialexpr", item.m_InitialExpr, GetStudioStateNamespace());
+ } else if (item.m_Initial)
+ Att("initial", item.m_Initial->m_Target);
+
+ WriteStateNodeList(item.m_Children);
+ if (item.m_DataModel)
+ WriteDataModel(*item.m_DataModel);
+ WriteExtensionData(&item);
+ }
+
+ void CheckTransitionForWrittenNodesList(STransition *transition)
+ {
+ if (transition == NULL)
+ return;
+ for (QT3DSU32 targetIdx = 0, targetEnd = transition->m_Target.size(); targetIdx < targetEnd;
+ ++targetIdx) {
+ if (eastl::find(m_WrittenNodes.begin(), m_WrittenNodes.end(),
+ transition->m_Target[targetIdx])
+ != m_WrittenNodes.end()) {
+ m_ExternalTransitions.push_back(transition);
+ return;
+ }
+ }
+ }
+
+ // Not sure the right answer here. I know you can't just blindly work with initials and such
+ // because you can't create new transitions for them.
+ void CheckForExternalTransitions(SStateNode &inNode, const eastl::vector<SStateNode *> &inRoots)
+ {
+ switch (inNode.m_Type) {
+ case StateNodeTypes::SCXML: {
+ SSCXML &theNode(static_cast<SSCXML &>(inNode));
+ // CheckTransitionForWrittenNodesList( theNode.m_Initial );
+ CheckForExternalTransitions(theNode.m_Children, inRoots);
+ } break;
+ case StateNodeTypes::State: {
+ SState &theNode(static_cast<SState &>(inNode));
+ // CheckTransitionForWrittenNodesList( theNode.m_Initial );
+ CheckForExternalTransitions(theNode.m_Children, inRoots);
+ } break;
+ case StateNodeTypes::Parallel: {
+ SParallel &theNode(static_cast<SParallel &>(inNode));
+ CheckForExternalTransitions(theNode.m_Children, inRoots);
+ } break;
+ case StateNodeTypes::Final:
+ break;
+ case StateNodeTypes::History: {
+ // CheckTransitionForWrittenNodesList( theNode.m_Transition );
+ } break;
+ case StateNodeTypes::Transition: {
+ STransition &theNode(static_cast<STransition &>(inNode));
+ CheckTransitionForWrittenNodesList(&theNode);
+ } break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ }
+
+ void CheckForExternalTransitions(TStateNodeList &ioList,
+ const eastl::vector<SStateNode *> &inRoots)
+ {
+ for (TStateNodeList::iterator iter = ioList.begin(), end = ioList.end(); iter != end;
+ ++iter) {
+ if (eastl::find(inRoots.begin(), inRoots.end(), &(*iter)) == inRoots.end())
+ CheckForExternalTransitions(*iter, inRoots);
+ }
+ }
+
+ void WriteFragment(eastl::vector<SStateNode *> &inRoots, const QT3DSVec2 &inMousePos)
+ {
+ m_MousePos = inMousePos;
+ for (QT3DSU32 idx = 0, end = inRoots.size(); idx < end; ++idx) {
+ Write(*inRoots[idx], true);
+ }
+ if (m_Context.GetRoot())
+ CheckForExternalTransitions(*m_Context.GetRoot(), inRoots);
+ m_CurrentNamespace = GetStudioStateNamespace();
+ for (QT3DSU32 idx = 0, end = m_ExternalTransitions.size(); idx < end; ++idx) {
+ WriteExternalTransition(*m_ExternalTransitions[idx]);
+ }
+ }
+};
+
+// True if child is a descedent of parent. False otherwise.
+inline bool IsDescendent(SStateNode &parent, SStateNode &child)
+{
+ if (&parent == &child)
+ return false;
+ if (&parent == child.m_Parent)
+ return true;
+
+ if (child.m_Parent)
+ return IsDescendent(parent, *child.m_Parent);
+
+ return false;
+}
+
+template <typename TDataType>
+void GenerateUniqueIdT(TDataType &inNode, const char8_t *inStem, IStateContext &ioContext,
+ IStringTable &ioStringTable)
+{
+ QT3DS_ASSERT(inNode.m_Id.IsValid() == false);
+ inNode.m_Id =
+ ioStringTable.RegisterStr(DoGenerateUniqueId(inStem, ioContext, ioStringTable).c_str());
+ bool insertResult = ioContext.InsertId(inNode.m_Id, &inNode);
+ QT3DS_ASSERT(insertResult);
+ (void)insertResult;
+}
+}
+
+namespace uic {
+namespace state {
+
+ void CXMLIO::GenerateUniqueId(SStateNode &inNode, const char8_t *inStem,
+ IStateContext &ioContext, IStringTable &ioStringTable)
+ {
+ GenerateUniqueIdT(inNode, inStem, ioContext, ioStringTable);
+ }
+
+ void CXMLIO::GenerateUniqueId(SSend &inNode, const char8_t *inStem, IStateContext &ioContext,
+ IStringTable &ioStringTable)
+ {
+ GenerateUniqueIdT(inNode, inStem, ioContext, ioStringTable);
+ }
+
+ bool CXMLIO::LoadSCXMLFile(NVAllocatorCallback &inGraphAllocator, NVFoundationBase &inFnd,
+ IDOMReader &inReader, IStringTable &inStringTable,
+ const char8_t *inFilename, IStateContext &outContext,
+ editor::IEditor *inEditor)
+ {
+ // the topmost scxml node is a state, so go from there.
+ if (AreEqual(inReader.GetElementName().c_str(), "scxml")) {
+ SParseContext theParseContext(inGraphAllocator, inFnd, inReader, outContext,
+ inStringTable, inEditor);
+ outContext.SetRoot(theParseContext.ParseSCXML());
+ if (outContext.GetRoot()) {
+ inFilename = nonNull(inFilename);
+ outContext.GetRoot()->m_Filename = theParseContext.ToGraphStr(inFilename);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ eastl::pair<eastl::vector<SStateNode *>, CXMLIO::TIdRemapMap>
+ CXMLIO::LoadSCXMLFragment(NVAllocatorCallback &inGraphAllocator, NVFoundationBase &inFnd,
+ IDOMReader &inReader, IStringTable &inStringTable,
+ IStateContext &ioContext, editor::IEditor &inEditor)
+ {
+ if (AreEqual(inReader.GetElementName().c_str(), "scxml_fragment")) {
+ SParseContext theParseContext(inGraphAllocator, inFnd, inReader, ioContext,
+ inStringTable, &inEditor);
+ eastl::vector<SStateNode *> retval = theParseContext.ParseFragment();
+ return eastl::make_pair(retval, theParseContext.m_RemapMap);
+ }
+ return eastl::make_pair(eastl::vector<SStateNode *>(), CXMLIO::TIdRemapMap());
+ }
+
+ void CXMLIO::SaveSCXMLFile(IStateContext &inContext, NVFoundationBase &inFnd,
+ IStringTable &inStringTable, IOutStream &outStream,
+ editor::IEditor *inEditor)
+ {
+ NVScopedRefCounted<IDOMFactory> theFactory =
+ IDOMFactory::CreateDOMFactory(inFnd.getAllocator(), inStringTable);
+ NVScopedRefCounted<IDOMWriter> theWriter =
+ IDOMWriter::CreateDOMWriter(inFnd.getAllocator(), "scxml", inStringTable,
+ GetSCXMLNamespace())
+ .first;
+ SWriteContext theWriteContext(*theWriter, inContext, inStringTable, inEditor,
+ inFnd.getAllocator());
+ theWriteContext.Write();
+
+ // Now we actually serialize the data.
+ eastl::vector<SNamespacePair> thePairs;
+ thePairs.push_back(
+ SNamespacePair(inStringTable.RegisterStr(GetSCXMLNamespace()), CRegisteredString()));
+ thePairs.push_back(SNamespacePair(inStringTable.RegisterStr(GetStudioStateNamespace()),
+ inStringTable.RegisterStr("uic")));
+
+ for (SNamespacePairNode *theNode = inContext.GetFirstNSNode(); theNode;
+ theNode = theNode->m_NextNode) {
+ if (AreEqual(theNode->m_Namespace.c_str(), GetSCXMLNamespace()) == false
+ && AreEqual(theNode->m_Namespace.c_str(), GetStudioStateNamespace()) == false
+ && theNode->m_Abbreviation.IsValid())
+ thePairs.push_back(*theNode);
+ }
+
+ CDOMSerializer::WriteXMLHeader(outStream);
+ CDOMSerializer::Write(inFnd.getAllocator(), *theWriter->GetTopElement(), outStream,
+ inStringTable, toDataRef(thePairs.data(), thePairs.size()), false);
+ }
+
+ void CXMLIO::FindRoots(NVConstDataRef<SStateNode *> inObjects,
+ eastl::vector<SStateNode *> &outRoots)
+ {
+ // Stupid but effective algorithm.
+ for (QT3DSU32 idx = 0, end = inObjects.size(); idx < end; ++idx) {
+ // Transitions never make it into the root, nor does the top scxml object
+ if (inObjects[idx]->m_Type == StateNodeTypes::Transition
+ || inObjects[idx]->m_Type == StateNodeTypes::SCXML)
+ continue;
+ SStateNode *newNode(inObjects[idx]);
+ // Note that re-querying size is important.
+ bool skip = false;
+ for (QT3DSU32 existingIdx = 0; existingIdx < outRoots.size() && skip == false;
+ ++existingIdx) {
+ SStateNode *existingNode(outRoots[existingIdx]);
+ if (newNode == existingNode || IsDescendent(*existingNode, *newNode))
+ skip = true;
+
+ // If the existing item is a descendent of new node,
+ // then get the existing item out of the list.
+ if (IsDescendent(*newNode, *existingNode)) {
+ // Get the existing item out of the list.
+ outRoots.erase(outRoots.begin() + existingIdx);
+ --existingIdx;
+ }
+ }
+ if (!skip)
+ outRoots.push_back(newNode);
+ }
+ }
+
+ eastl::vector<SStateNode *> CXMLIO::SaveSCXMLFragment(
+ IStateContext &inContext, NVFoundationBase &inFnd, IStringTable &inStringTable,
+ IDOMWriter &ioWriter, NVDataRef<SStateNode *> inObjects, editor::IEditor &inEditor,
+ const QT3DSVec2 &inMousePos, eastl::vector<SNamespacePair> &outNamespaces)
+ {
+ eastl::vector<SStateNode *> theRoots;
+ FindRoots(inObjects, theRoots);
+ NVScopedRefCounted<IDOMWriter> theWriter(ioWriter);
+ SWriteContext theWriteContext(*theWriter, inContext, inStringTable, &inEditor,
+ inFnd.getAllocator());
+ theWriteContext.WriteFragment(theRoots, inMousePos);
+
+ outNamespaces.push_back(
+ SNamespacePair(inStringTable.RegisterStr(GetSCXMLNamespace()), CRegisteredString()));
+ outNamespaces.push_back(SNamespacePair(inStringTable.RegisterStr(GetStudioStateNamespace()),
+ inStringTable.RegisterStr("uic")));
+ return theRoots;
+ }
+
+ void CXMLIO::ToEditableXml(IStateContext &inContext, NVFoundationBase &inFnd,
+ IStringTable &inStringTable, IDOMWriter &ioWriter,
+ SExecutableContent &inContent, editor::IEditor &inEditor)
+ {
+ SWriteContext theWriteContext(ioWriter, inContext, inStringTable, &inEditor,
+ inFnd.getAllocator());
+ theWriteContext.WriteExecutableContent(inContent);
+ }
+
+ SExecutableContent *
+ CXMLIO::FromEditableXML(IDOMReader &inReader, NVFoundationBase &inFnd, IStateContext &inContext,
+ IStringTable &inStringTable, NVAllocatorCallback &inGraphAllocator,
+ editor::IEditor &inEditor, SStateNode *inStateNodeParent,
+ SExecutableContent *inExecContentParent)
+ {
+ SParseContext theParseContext(inGraphAllocator, inFnd, inReader, inContext, inStringTable,
+ &inEditor);
+ TExecutableContentList theContentList;
+ theParseContext.ParseExecutableContentItem(inStateNodeParent, inExecContentParent,
+ theContentList);
+ return &(*theContentList.begin());
+ }
+
+ eastl::vector<eastl::string> CXMLIO::GetSupportedExecutableContentNames()
+ {
+ eastl::vector<eastl::string> retval;
+ NVConstDataRef<SParseContext::SExecutableContentParseBinding> theBindingList =
+ SParseContext::GetParseBindings();
+ for (QT3DSU32 idx = 0, end = theBindingList.size(); idx < end; ++idx)
+ retval.push_back(
+ eastl::string(SXMLName::GetNameForElemName(theBindingList[idx].m_Name)));
+ return retval;
+ }
+}
+}
diff --git a/src/Runtime/Source/UIPParser/Include/UICIPresentation.h b/src/Runtime/Source/UIPParser/Include/UICIPresentation.h
new file mode 100644
index 00000000..9b074102
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Include/UICIPresentation.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICEventCallbacks.h"
+
+namespace uic {
+namespace runtime {
+ class IApplication;
+ class IActivityZone;
+ class IAnimationSystem;
+ class ISlideSystem;
+ class ILogicSystem;
+ class IParametersSystem;
+}
+}
+
+namespace qt3ds {
+namespace foundation {
+ class IStringTable;
+}
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IComponentManager;
+class IEventManager;
+class IScene;
+class IScriptBridge;
+class CPresentationFrameData;
+class CTimePolicy;
+using uic::runtime::ISlideSystem;
+using uic::runtime::IAnimationSystem;
+using uic::runtime::ILogicSystem;
+using uic::runtime::IParametersSystem;
+
+//==============================================================================
+// Enumeration
+//==============================================================================
+/// Method used to translate from presentation size to window size
+enum EScaleMode {
+ SCALEMODE_FREE, ///< Free scaling mode
+ SCALEMODE_EXACT, ///< Fixed presentation size
+ SCALEMODE_ASPECT, ///< Maintain aspect ratio
+ SCALEMODE_UNKNOWN, ///< ERROR! - Uninitialized scale mode
+};
+
+//==============================================================================
+// Structs
+//==============================================================================
+struct SPresentationSize
+{
+ SPresentationSize()
+ : m_Width(0)
+ , m_Height(0)
+ , m_ScaleMode(0)
+ {
+ }
+ UINT16 m_Width; ///< Native width of the presentation
+ UINT16 m_Height; ///< Native height of the presentation
+ UINT8 m_ScaleMode; ///< Presentation to window scale method
+ UINT8 m_Padding[3];
+};
+
+//==============================================================================
+/**
+ * @interface IPresentation
+ * Base interface of the presentation.
+ */
+class IPresentation
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ IPresentation() {}
+ virtual ~IPresentation() {}
+
+public: // Execution
+ virtual void ClearDirtyList() = 0;
+ virtual void PreUpdate(const TTimeUnit inGlobalTime) = 0;
+ virtual void BeginUpdate() = 0;
+ virtual void EndUpdate() = 0;
+ virtual void PostUpdate(const TTimeUnit inGlobalTime) = 0;
+
+public: // Bridge Control
+ virtual void SetScene(IScene *inScene) = 0;
+ virtual IScene *GetScene() const = 0;
+ virtual IScriptBridge *GetScriptBridge() = 0;
+ virtual IScriptBridge *GetScriptBridgeQml() = 0;
+
+public: // Commands and Events
+ virtual void FireEvent(const TEventCommandHash inEventType, TElement *inTarget,
+ const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
+ const EAttributeType inType2 = ATTRIBUTETYPE_NONE) = 0;
+ virtual void FireCommand(const TEventCommandHash inEventType, TElement *inTarget,
+ const UVariant *inArg1 = NULL, const UVariant *inArg2 = NULL,
+ const EAttributeType inType1 = ATTRIBUTETYPE_NONE,
+ const EAttributeType inType2 = ATTRIBUTETYPE_NONE) = 0;
+ virtual void FlushEventCommandQueue(void) = 0;
+ virtual void ProcessEvent(SEventCommand &) = 0;
+
+public: // Manager Access
+ virtual IComponentManager &GetComponentManager() = 0;
+ virtual ISlideSystem &GetSlideSystem() = 0;
+ virtual IAnimationSystem &GetAnimationSystem() = 0;
+ virtual ILogicSystem &GetLogicSystem() = 0;
+ virtual IParametersSystem &GetParametersSystem() = 0;
+
+ virtual qt3ds::foundation::IStringTable &GetStringTable() = 0;
+ virtual uic::runtime::IApplication &GetApplication() = 0;
+ virtual uic::runtime::IActivityZone *GetActivityZone() = 0;
+
+public: // Hooks and callbacks
+ virtual void OnPresentationLoaded() = 0;
+
+public: // Full file path
+ virtual void SetFilePath(const CHAR *inPath) = 0;
+ virtual QString GetFilePath() = 0;
+ virtual TElement *GetRoot() = 0;
+ virtual void SetRoot(TElement &inRoot) = 0;
+
+public: // Configuration access
+ virtual SPresentationSize GetSize() const = 0;
+ virtual void SetSize(const SPresentationSize &inSize) = 0;
+ virtual void SetElementPath(TElement &inElement, const char8_t *inPath) = 0;
+ virtual qt3ds::foundation::CRegisteredString GetElementPath(TElement &inElement) = 0;
+
+public: // Event Callbacks
+ virtual void RegisterEventCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData) = 0;
+ virtual BOOL UnregisterEventCallback(TElement *inElement, const TEventCommandHash inEventHash,
+ const TEventCallback inCallback, void *inContextData) = 0;
+
+public: // FrameData access
+ virtual CPresentationFrameData &GetFrameData() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UIPParser/Include/UICUIPParser.h b/src/Runtime/Source/UIPParser/Include/UICUIPParser.h
new file mode 100644
index 00000000..17260760
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Include/UICUIPParser.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "foundation/StringTable.h"
+#include <EASTL/string.h>
+
+namespace uic {
+namespace state {
+ struct SSetAttribute;
+ namespace debugger {
+ class ISceneGraphRuntimeDebugger;
+ }
+}
+}
+
+namespace uic {
+namespace render {
+ class IInputStreamFactory;
+}
+}
+
+//==============================================================================
+// Forwards
+//==============================================================================
+namespace UICDM {
+class IDOMReader;
+class IStringTable;
+}
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+using namespace qt3ds::foundation;
+//==============================================================================
+// Forwards
+//==============================================================================
+class IRuntimeMetaData;
+class IPresentation;
+
+struct UIPElementTypes
+{
+ enum Enum {
+ Unknown = 0,
+ Scene = 1,
+ Node,
+ Layer,
+ Component,
+ Group,
+ Behavior,
+ Model,
+ Light,
+ Camera,
+ Image,
+ Material,
+ Text,
+ Effect,
+ RenderPlugin,
+ CustomMaterial,
+ ReferencedMaterial,
+ Path,
+ PathAnchorPoint,
+ PathSubPath,
+ };
+};
+
+struct SElementAndType
+{
+ UIPElementTypes::Enum m_Type;
+ TElement *m_Element;
+ SElementAndType(UIPElementTypes::Enum inType, TElement *elem)
+ : m_Type(inType)
+ , m_Element(elem)
+ {
+ }
+};
+
+// Ensure these elements exist and if the attribute isn't empty ensure the attribute is referenced.
+struct SElementAttributeReference
+{
+ eastl::string m_Path;
+ eastl::string m_Attribute;
+ SElementAttributeReference(const eastl::string &p, const eastl::string &a)
+ : m_Path(p)
+ , m_Attribute(a)
+ {
+ }
+};
+//==============================================================================
+/**
+ * @class CUIPParser
+ * @brief Class for parsing UIP file
+ */
+
+class IUIPParser : public NVReleasable
+{
+protected:
+ virtual ~IUIPParser() {}
+public: // Parse UIP file
+ virtual BOOL Load(IPresentation &inPresentation,
+ NVConstDataRef<SElementAttributeReference> inStateReferences,
+ uic::state::debugger::ISceneGraphRuntimeDebugger &inDebugger) = 0;
+ virtual UICDM::IDOMReader &GetDOMReader() = 0;
+ virtual IRuntimeMetaData &GetMetaData() = 0;
+ // Mapping back from file id to element id, needed to hook elements up to their respective
+ // parsed
+ // counterparts.
+ virtual SElementAndType GetElementForID(const char *inStringId) = 0;
+ virtual eastl::string ResolveReference(const char *inStringId, const char *inReferance) = 0;
+ // The rendering system needs to know every sourcepath found during parse of the UIP file
+ // so that it can do things like register images as opaque/transparent as well as preload
+ // mesh files (and possibly font files).
+ virtual NVConstDataRef<eastl::string> GetSourcePaths() const = 0;
+
+ // Creation function
+ static IUIPParser &Create(const QString &inFileName, IRuntimeMetaData &inMetaData,
+ uic::render::IInputStreamFactory &inStreamFactory,
+ qt3ds::foundation::IStringTable &inStrTable);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UIPParser/Include/UICUIPParserActionHelper.h b/src/Runtime/Source/UIPParser/Include/UICUIPParserActionHelper.h
new file mode 100644
index 00000000..a1b05b42
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Include/UICUIPParserActionHelper.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICUIPParserImpl.h"
+
+namespace uic {
+namespace runtime {
+ class IParametersSystem;
+}
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+using uic::runtime::IParametersSystem;
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CUIPParserActionHelper
+ * @brief Class for parsing UIP file - Action
+ */
+class CUIPParserActionHelper
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CUIPParserImpl *m_UIPParser;
+ CUIPParserObjectRefHelper *m_ObjRefHelper;
+ IRuntimeMetaData &m_MetaData; ///< Reference to Metadata
+
+ typedef eastl::map<eastl::string, INT32> TActionIdentifierMap; ///< Mapping of the string that
+ ///uniquely identify the action
+ ///to the index created
+ TActionIdentifierMap m_ActionIdentifierMap;
+
+ struct SHandlerArgumentInfo
+ {
+ eastl::string m_Name;
+ eastl::string m_Value;
+
+ SHandlerArgumentInfo() {}
+ };
+ typedef eastl::vector<SHandlerArgumentInfo> THandlerArguments; ///< List of handler arguments
+ struct SActionInfo
+ {
+ eastl::string m_Id;
+
+ // Where the action is added to
+ eastl::string m_Owner; // Absolute path of owner object
+
+ // Trigger object
+ eastl::string m_TriggerObject; // Absolute path of trigger object
+ eastl::string m_Event;
+
+ // Target object
+ eastl::string m_TargetObject; // Absolute path of target object
+ eastl::string m_Handler;
+ THandlerArguments m_HandlerArgs;
+
+ SActionInfo() {}
+ };
+ typedef eastl::map<eastl::string, SActionInfo> TActionMap; ///< Map of action id and action info
+
+ TActionMap m_ActionMap;
+
+ // There are 2 tables involved:
+ // 1. The Listener-To-Events tables - multimap of each listener to all events it is listening to
+ // 2. The Listener-Event-To-Actions table - multimap of each listener-event pair to all actions
+ // it triggers
+ // note: The struct for Action is a pair of EventAction node and its owner
+ struct SListenerEventNamePair
+ {
+ eastl::string m_Listener;
+ eastl::string m_Event;
+
+ SListenerEventNamePair(eastl::string inListener, const eastl::string &inEvent)
+ : m_Listener(inListener)
+ , m_Event(inEvent)
+ {
+ }
+
+ bool operator<(const SListenerEventNamePair &inListenerEventPair) const
+ {
+ if (m_Listener == inListenerEventPair.m_Listener)
+ return m_Event < inListenerEventPair.m_Event;
+ return m_Listener < inListenerEventPair.m_Listener;
+ }
+ };
+
+ typedef eastl::pair<eastl::string, eastl::string>
+ TEventActionOwnerPair; ///< One listener(source) can listen to multiple events
+ typedef eastl::multimap<eastl::string, eastl::string>
+ TListenerEventsNameMap; ///< One listener(source)-event pair can trigger multiple actions
+ typedef eastl::multimap<SListenerEventNamePair, TEventActionOwnerPair> TListenerEventActionsMap;
+
+ TListenerEventsNameMap m_ListenerEventsNameMap;
+ TListenerEventActionsMap m_ListenerEventActionsMap;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CUIPParserActionHelper(CUIPParserImpl *inUIPParser, CUIPParserObjectRefHelper *inObjRefHelper,
+ IRuntimeMetaData &inMetaData);
+ virtual ~CUIPParserActionHelper();
+
+public:
+ void CacheAction(UICDM::IDOMReader &inReader, const char8_t *inOwnerId);
+ void BuildActions(IPresentation &inPresentation);
+ void GetActionSectionCount(CUIPParserImpl::SActionSectionCount &outActionCount);
+ INT32 GetActionCount(const eastl::string &inActionId);
+ INT32 GetActionIndex(const eastl::string &inActionId);
+
+protected: // Action helper
+ void AddListenerEventPair(eastl::string inListener, const eastl::string &inEventName);
+ void CacheHandlerArguments(UICDM::IDOMReader &inReader, SActionInfo &inAction);
+ void BuildAction(TElement &inElement, UINT32 inEventName, IPresentation &inPresentation,
+ const eastl::string &inActionId);
+ INT32 GetActionCount(const eastl::string &inActionId, INT32 &outStringAttrCount,
+ INT32 &outCustomParamCount);
+ bool IsCustomHandler(const SActionInfo &inAction);
+ void GetHandlerArgumentType(const SActionInfo &inAction, int inArgumentIndex,
+ ERuntimeDataModelDataType &outType,
+ ERuntimeAdditionalMetaDataType &outAdditionalType);
+ void GetCustomActionParametersCount(ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType,
+ INT32 &outStringAttrCount, INT32 &outCustomParamCount);
+ void ExportCustomActionParameters(IPresentation &inPresentation,
+ IParametersSystem &inParamSystem, QT3DSI32 inParamGroup,
+ const char *inDataValue, ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType);
+
+ inline SElement *GetElement(const eastl::string &inElementName);
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UIPParser/Include/UICUIPParserImpl.h b/src/Runtime/Source/UIPParser/Include/UICUIPParserImpl.h
new file mode 100644
index 00000000..f21a2077
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Include/UICUIPParserImpl.h
@@ -0,0 +1,664 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+/*
+This is the main file responsible for conversion from the uip format into the runtime's data format.
+The runtime works in a sort of global space so any object, be it an animation, action or element,
+once
+activated stays activated. Furthermore it is important that the runtime declare and set the fewest
+number
+of properties possible to still get the right answer. In order to achieve this the runtime relies
+on the
+rendering system to have the initial state of the entire scene graph, including state that is only
+"Add"
+commands declared in slides.
+
+Given that you understand master slide/ slide distinction, an accurate description would be to do
+this:
+1. Move all parse objects (actions, animations, elements) to be master objects and deactivate them.
+2. Running through the list of nonmaster slides, activate the objects on those slides that would be
+activated.
+3. Now remove properties that are both unreferenced and applied 1 or fewer times.
+
+
+The parsing system does this in reverse order so the passes look like:
+1. Load meta data information (lua scripts, effects) to have a complete meta data model.
+1. Build element graph. This is used during attribute lookup
+2. Figure out which attributes will be on the elements in the graph by resolving behavior
+references, action references and
+ Animations, and Set command attribute applications.
+
+ During this pass we also build the set of actions and animations which will appear on each
+slide. This involves both promoting
+ actions/animations that appear on the master slide to child slides and pulling
+animations/actions declared on all child slides
+ onto the master slide.
+
+3. Count the objects that we will need. The runtime currently requires fixed object counts that
+can't be exceeded
+ thus we have to effectively preallocate all runtime objects.
+
+4. Run through the file again and build the actual runtime datastructures. Actions and animations
+are built from
+ an intermediate memory representation but the set commands and element activations are built
+via running through
+ the file.
+
+
+Care needs to be taken so the runtime can survive poorly formed or just meaningless uip files.
+Studio is only *one*
+system for producing UIP files, clients are free to use code generates (like ruby scripts and such)
+to build their final
+uip files so we need to be careful that we are as robust as possible and can tolerate gracefully
+some level of incorrect
+uip file data.
+*/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICUIPParser.h"
+#include "UICTypes.h"
+#include "UICMetadata.h"
+#include "UICRenderInputStreamFactory.h"
+#include "UICSlideSystem.h"
+#include "UICDMDataTypes.h"
+#include "foundation/Qt3DSMemoryBuffer.h"
+#include <EASTL/map.h>
+#include <EASTL/set.h>
+#include <EASTL/hash_map.h>
+#include "UICElementSystem.h"
+#include "UICSlideSystem.h"
+
+namespace uic {
+namespace render {
+ class IRefCountedInputStream;
+}
+}
+
+namespace UICDM {
+class IDOMReader;
+class IDOMWriter;
+}
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IPresentation;
+class SElementBuilder;
+class CContractBuilder;
+class CAnimationBuilder;
+class CLogicBuilder;
+class CSlideBuilder;
+class IRuntimeMetaData;
+class CUIPParserActionHelper;
+class CUIPParserObjectRefHelper;
+
+typedef eastl::vector<uic::runtime::element::TPropertyDescAndValue> TPropertyDescAndValueList;
+
+using uic::render::IInputStreamFactory;
+using uic::render::IRefCountedInputStream;
+typedef NVScopedRefCounted<IRefCountedInputStream> TInputStreamPtr;
+typedef qt3ds::foundation::CRegisteredString TStrType;
+using uic::runtime::element::SElement;
+
+struct SElementPropertyInfo
+{
+ enum Enum {
+ MaxArity = 4,
+ };
+ TStrType m_PropertyName;
+ ERuntimeDataModelDataType m_DataType;
+ ERuntimeAdditionalMetaDataType m_AdditionalType;
+ // Number of sub components of the property, 1-4
+ qt3ds::QT3DSU32 m_Arity;
+ qt3ds::QT3DSU32 m_PropertyHashes[MaxArity];
+ CRegisteredString m_PropertyNames[MaxArity];
+ bool m_ElementFlag; // True if this property exists on the element. Some properties do not.
+ bool m_SlideFlag; // True if this property exists on the slides at all.
+ // starttime,endtime are forced to be on the slides whether they are in the UIP or not.
+ bool m_SlideForceFlag; // True if this property is *forced* on the slides whether it needs to be
+ // there or not
+
+ SElementPropertyInfo(TStrType inPropName)
+ : m_PropertyName(inPropName)
+ , m_DataType(ERuntimeDataModelDataTypeNone)
+ , m_Arity(0)
+ , m_ElementFlag(false)
+ , m_SlideFlag(false)
+ , m_SlideForceFlag(false)
+ {
+ memZero(m_PropertyHashes, sizeof(m_PropertyHashes));
+ }
+ bool operator<(const SElementPropertyInfo &inOther) const
+ {
+ return m_PropertyName < inOther.m_PropertyName;
+ }
+};
+
+typedef eastl::hash_map<TStrType, SElementPropertyInfo> TAttrMap;
+
+struct SElementData
+{
+ SElement *m_Element;
+ TStrType m_Id;
+ TStrType m_Type;
+ TStrType m_Class;
+ TAttrMap m_PropertyMap;
+
+ SElementData(TStrType inId)
+ : m_Element(NULL)
+ , m_Id(inId)
+ {
+ }
+ void SetElement(SElement *inElement, TStrType inType, TStrType inClass)
+ {
+ m_Element = inElement;
+ m_Type = inType;
+ m_Class = inClass;
+ }
+};
+
+typedef eastl::hash_map<TStrType, SElementData> TIdElementMap;
+
+struct SParseElementManager
+{
+ IRuntimeMetaData &m_MetaData;
+ TIdElementMap m_ElementMap;
+ // Temporary variables for various algorithms
+ eastl::string m_Workspace;
+ eastl::vector<eastl::string> m_PropertyList;
+ qt3ds::foundation::IStringTable &m_StringTable;
+
+ SParseElementManager(IRuntimeMetaData &inMetaData, qt3ds::foundation::IStringTable &inStrTable)
+ : m_MetaData(inMetaData)
+ , m_StringTable(inStrTable)
+ {
+ }
+ TStrType RegisterStr(const char8_t *inStr);
+ SElementData &GetOrCreateElementData(const char8_t *inElemIdOrRef, const char8_t *inElemType,
+ const char8_t *inElemClassId);
+ SElementData *FindElementData(const char8_t *inIdOrRef);
+ // We don't allow creation of properties that don't exist in the meta data in the first place.
+ SElementPropertyInfo *GetOrCreateProperty(SElementData &inData, const char8_t *inPropertyName);
+ SElementPropertyInfo *GetOrCreateProperty(const char8_t *inIdOrRef, const char8_t *inElemType,
+ const char8_t *inElemClassId,
+ const char8_t *inPropertyName);
+ SElementPropertyInfo *FindProperty(SElementData &inElement, const char8_t *inPropertyName);
+ SElementPropertyInfo *FindProperty(const char8_t *inIdOrRef, const char8_t *inPropertyName);
+ eastl::pair<SElementPropertyInfo *, qt3ds::QT3DSU32>
+ FindPropertyWithSubIndex(SElementData &inElement, const char8_t *inPropertyName);
+ // Attribute marking stage; mark which attributes will be kept on elements at all.
+ void MarkAttributeAsReferenced(SElementData &inElement, const char8_t *inPropertyName);
+ void MarkAttributeAsReferenced(const char8_t *inElement, const char8_t *inPropertyName);
+ void MarkAllAttributesAsReferenced(SElementData &inElement);
+};
+
+struct SParseSlideActionEntry
+{
+ TStrType m_SlideId;
+ TStrType m_ActionId;
+ qt3ds::QT3DSI32 m_ActionCount;
+ bool m_Active;
+ uic::runtime::SSlideAnimAction *m_Actions[SElementPropertyInfo::MaxArity];
+
+ SParseSlideActionEntry(TStrType inSlideId, TStrType inActionId, qt3ds::QT3DSI32 inActionCount,
+ bool inActive)
+ : m_SlideId(inSlideId)
+ , m_ActionId(inActionId)
+ , m_ActionCount(inActionCount)
+ , m_Active(inActive)
+ {
+ memZero(m_Actions, sizeof(m_Actions));
+ }
+ SParseSlideActionEntry()
+ : m_ActionCount(0)
+ , m_Active(false)
+ {
+ }
+ // Partial equals, used for finding object in vector.
+ bool operator==(const SParseSlideActionEntry &inOther) const
+ {
+ return m_SlideId == inOther.m_SlideId && m_ActionId == inOther.m_ActionId;
+ }
+};
+
+typedef eastl::vector<SParseSlideActionEntry> TActionList;
+
+struct SParseSlideAnimationTypes
+{
+ enum Enum {
+ NoAnimation = 0,
+ Linear,
+ EaseInOut,
+ Bezier,
+ };
+};
+
+struct SParseSlideAnimationEntry
+{
+ TStrType m_SlideId;
+ TStrType m_InstanceId;
+ TStrType m_PropertyName;
+ qt3ds::QT3DSU32 m_PropertyHash;
+ qt3ds::QT3DSI32 m_AnimationIndex;
+ eastl::vector<float> m_KeyframeData;
+ SParseSlideAnimationTypes::Enum m_AnimationType;
+ bool m_IsDynamic;
+
+ SParseSlideAnimationEntry()
+ : m_AnimationIndex(-1)
+ , m_KeyframeData("")
+ , m_AnimationType(SParseSlideAnimationTypes::NoAnimation)
+ , m_IsDynamic(false)
+ {
+ }
+ SParseSlideAnimationEntry(TStrType inSlideId, TStrType inInstanceId, TStrType inPropertyName,
+ qt3ds::QT3DSU32 inPropHash, SParseSlideAnimationTypes::Enum inAnimType,
+ const float *inKeyframeData, qt3ds::QT3DSU32 inNumFloats, bool inIsDynamic)
+ : m_SlideId(inSlideId)
+ , m_InstanceId(inInstanceId)
+ , m_PropertyName(inPropertyName)
+ , m_PropertyHash(inPropHash)
+ , m_AnimationType(inAnimType)
+ , m_IsDynamic(inIsDynamic)
+ {
+ m_KeyframeData.insert(m_KeyframeData.begin(), inKeyframeData, inKeyframeData + inNumFloats);
+ }
+};
+
+struct SParseAnimationRef
+{
+ TStrType m_SlideId;
+ TStrType m_InstanceId;
+ TStrType m_PropertyName;
+ bool m_Active;
+ const SParseSlideAnimationEntry *m_Animation;
+
+ SParseAnimationRef(TStrType inSlideId, TStrType inInstanceId, TStrType inPropName,
+ const SParseSlideAnimationEntry *inAnimation, bool inActive)
+ : m_SlideId(inSlideId)
+ , m_InstanceId(inInstanceId)
+ , m_PropertyName(inPropName)
+ , m_Active(inActive)
+ , m_Animation(inAnimation)
+ {
+ }
+ SParseAnimationRef()
+ : m_Active(false)
+ , m_Animation(NULL)
+ {
+ }
+ // Partial equals, used for finding object in vector.
+ bool operator==(const SParseAnimationRef &inOther) const
+ {
+ return m_SlideId == inOther.m_SlideId && m_InstanceId == inOther.m_InstanceId
+ && m_PropertyName == inOther.m_PropertyName;
+ }
+};
+
+typedef eastl::vector<SParseAnimationRef> TAnimationList;
+
+typedef eastl::hash_map<TStrType, TAnimationList> TInstanceIdAnimationMap;
+
+struct SParseSlide
+{
+ TStrType m_SlideId;
+ qt3ds::QT3DSI32 m_SlideIndex;
+ TActionList m_ActionList;
+ TInstanceIdAnimationMap m_Animations;
+
+ SParseSlide(TStrType inId, qt3ds::QT3DSI32 inSlideIndex)
+ : m_SlideId(inId)
+ , m_SlideIndex(inSlideIndex)
+ {
+ }
+ SParseSlide() {}
+};
+
+typedef eastl::hash_map<TStrType, SParseSlide> TSlideIdToParseSlideMap;
+
+struct SParseSlideManager
+{
+ IRuntimeMetaData &m_MetaData;
+ SParseElementManager &m_ElementManager;
+ TSlideIdToParseSlideMap m_SlideMap;
+ eastl::vector<SParseSlideAnimationEntry *> m_Animations;
+ qt3ds::QT3DSI32 m_SlideAnimationCount;
+ qt3ds::QT3DSI32 m_AnimationKeyframeCount;
+ qt3ds::QT3DSI32 m_ActionCount;
+ eastl::vector<qt3ds::QT3DSF32> m_KeyframeParseFloatBuffer;
+ eastl::string m_KeyframeParseBuffer;
+
+ SParseSlideManager(IRuntimeMetaData &inMD, SParseElementManager &inElemMgr)
+ : m_MetaData(inMD)
+ , m_ElementManager(inElemMgr)
+ , m_SlideAnimationCount(0)
+ , m_AnimationKeyframeCount(0)
+ , m_ActionCount(0)
+ {
+ }
+ ~SParseSlideManager();
+ TStrType RegisterId(const char8_t *inStr);
+ TStrType RegisterStr(const char8_t *inStr) { return m_ElementManager.RegisterStr(inStr); }
+ SParseSlide &GetOrCreateSlide(const char8_t *inSlideId, qt3ds::QT3DSI32 inSlideIndex);
+ SParseSlide *FindSlide(const char8_t *inSlideId);
+ // Create an animation and reference that animation
+ void SetAnimationData(SParseSlide &inSlide, const char8_t *inInstanceId,
+ const char8_t *inPropertyName, const char8_t *inKeyframeData,
+ SParseSlideAnimationTypes::Enum inType, bool inIsDynamic,
+ bool inIsActive);
+ // Reference an animation.
+ void ReferenceAnimation(SParseSlide &inSlide, const SParseSlideAnimationEntry &inSource,
+ bool inIsActive);
+ TAnimationList *GetAnimationsForInstance(SParseSlide &inSlide, const char8_t *inInstanceId);
+ SParseSlideActionEntry &GetOrCreateAction(SParseSlide &inSlide, const char8_t *inActionId,
+ qt3ds::QT3DSI32 inActionCount, bool inEyeball);
+ SParseSlideActionEntry *FindAction(SParseSlide &inSlide, const char8_t *inActionId);
+};
+
+//==============================================================================
+/**
+ * @class CUIPParserImpl
+ * @brief Class for parsing UIP file
+ */
+class CUIPParserImpl : public IUIPParser
+{
+
+ typedef eastl::basic_string<char8_t> TNarrowStr;
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ std::shared_ptr<UICDM::IDOMReader> m_DOMReader;
+ std::shared_ptr<UICDM::IDOMWriter> m_DOMWriter;
+ IRuntimeMetaData &m_MetaData; ///< Reference to Metadata
+ IInputStreamFactory &m_InputStreamFactory;
+ SParseElementManager m_ParseElementManager; ///< Map of id, SElement*
+ SParseSlideManager m_ParseSlideManager;
+
+ CUIPParserActionHelper *m_ActionHelper; ///< Action Helper
+ CUIPParserObjectRefHelper *m_ObjectRefHelper; ///< Object Reference Helper
+
+ typedef eastl::set<SElement *> TAddedSlideElements;
+ TAddedSlideElements m_SlideElements; ///< Caching of slide elements added, so that we don't need
+ ///to pass this around
+
+ typedef eastl::map<eastl::string, eastl::string> TIdSourcePathMap;
+ TIdSourcePathMap m_IdScriptMap; ///< Map of the class id and script sourcepath
+
+ typedef eastl::map<eastl::string, eastl::string> TIdClassMap;
+ TIdClassMap m_IdClassMap; ///< Map of id and class reference
+
+ typedef eastl::set<eastl::string> TStringSet;
+ typedef eastl::vector<eastl::string> TStringVector;
+
+ TStringSet m_SourcePathSet;
+ TStringVector m_SourcePathList;
+
+ struct SElementRefCache
+ {
+ SElementData *m_Element;
+ eastl::string m_Name;
+ eastl::string m_Value;
+ };
+ eastl::vector<SElementRefCache> m_ElementRefCache; ///< Cache those element refs in the scene
+ ///graph that needs to be patch later
+
+ struct SEaseInEaseOutKeyframe
+ {
+ float m_Time;
+ float m_Value;
+ float m_EaseIn;
+ float m_EaseOut;
+ };
+
+ struct SGraphSectionCount
+ {
+ INT32 m_ElementCount;
+ INT32 m_ComponentCount;
+ INT32 m_AttributeCount;
+ INT32 m_StringAttrCount;
+
+ SGraphSectionCount()
+ : m_ElementCount(0)
+ , m_ComponentCount(0)
+ , m_AttributeCount(0)
+ , m_StringAttrCount(0)
+ {
+ }
+ };
+
+ struct SLogicSectionCount
+ {
+ INT32 m_SlideCount;
+ INT32 m_SlideElementCount;
+ INT32 m_SlideAttributeCount;
+ INT32 m_StringAttrCount;
+ INT32 m_PaddingCount;
+
+ SLogicSectionCount()
+ : m_SlideCount(0)
+ , m_SlideElementCount(0)
+ , m_SlideAttributeCount(0)
+ , m_StringAttrCount(0)
+ , m_PaddingCount(0)
+ {
+ }
+ };
+
+ struct SActionSectionCount
+ {
+ INT32 m_TriggerElementCount;
+ INT32 m_TriggerEventCount;
+ INT32 m_ActionCount;
+ INT32 m_StringAttrCount;
+ INT32 m_CustomParamCount;
+
+ SActionSectionCount()
+ : m_TriggerElementCount(0)
+ , m_TriggerEventCount(0)
+ , m_ActionCount(0)
+ , m_StringAttrCount(0)
+ , m_CustomParamCount(0)
+ {
+ }
+ };
+
+ long m_NumGraphElements; /// eclee testing only, must remove
+ long m_NumGraphComponents; /// eclee testing only, must remove
+ long m_NumGraphAttributes; /// eclee testing only, must remove
+ long m_NumSlides; /// eclee testing only, must remove
+ long m_NumSlideElements; /// eclee testing only, must remove
+ long m_NumSlideAttributes; /// eclee testing only, must remove
+ long m_NumAnimationTracks; /// eclee testing only, must remove
+ long m_NumAnimationKeys; /// eclee testing only, must remove
+ long m_NumSlideAnimations; /// eclee testing only, must remove
+ long m_NumSlideActions; /// klarinda testing only, must remove
+
+ // temporarily this is here
+ qt3ds::foundation::MemoryBuffer<RawAllocator> m_TempBuffer;
+ qt3ds::foundation::MemoryBuffer<RawAllocator> m_ValueBuffer;
+
+ IPresentation *m_CurrentPresentation;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CUIPParserImpl(const QString &inFileName, IRuntimeMetaData &inMetaData,
+ IInputStreamFactory &inFactory, qt3ds::foundation::IStringTable &inStringTable);
+ virtual ~CUIPParserImpl();
+
+public: // Parse UIP file
+ BOOL Load(IPresentation &inPresentation,
+ NVConstDataRef<SElementAttributeReference> inStateReferences,
+ uic::state::debugger::ISceneGraphRuntimeDebugger &debugger) override;
+ UICDM::IDOMReader &GetDOMReader() override;
+ IRuntimeMetaData &GetMetaData() override;
+ SElementAndType GetElementForID(const char *inStringId) override;
+ eastl::string ResolveReference(const char *inStringId, const char *inReferance) override;
+ NVConstDataRef<eastl::string> GetSourcePaths() const override
+ {
+ return NVConstDataRef<eastl::string>(m_SourcePathList.data(), m_SourcePathList.size());
+ }
+
+protected: // Operation
+ BOOL LoadProjectSettings(IPresentation &inPresentation, UICDM::IDOMReader &inReader);
+ BOOL LoadClasses(IPresentation &inPresentation, UICDM::IDOMReader &inReader);
+ BOOL LoadGraph(IPresentation &inPresentation, UICDM::IDOMReader &inReader);
+ BOOL LoadSceneGraph(IPresentation &inPresentation, UICDM::IDOMReader &inReader,
+ uic::runtime::element::SElement *inNewStyleParent = NULL);
+ BOOL LoadLogic(IPresentation &inPresentation, UICDM::IDOMReader &inReader);
+ BOOL LoadStateGraph(IPresentation &inPresentation, UICDM::IDOMReader &inReader);
+
+protected: // Memory Counter
+ void ComputeAndReserveMemory(IPresentation &inPresentation, UICDM::IDOMReader &inReader);
+ void DoGraphSectionCount(UICDM::IDOMReader &inReader, SGraphSectionCount &outGraphCounter);
+ void DoLogicSectionCount(UICDM::IDOMReader &inReader, SLogicSectionCount &outLogicCounter);
+ void DoStateSectionCount(UICDM::IDOMReader &inReader, INT32 inSlideIndex,
+ SLogicSectionCount &outLogicCounter);
+ void DoRefSectionCount(UICDM::IDOMReader &inReader, INT32 inNumSlideMultiplier,
+ INT32 inSlideIndex, SLogicSectionCount &outLogicCounter);
+
+protected: // Scene graph heler
+ void CacheGraphRequiredAttributes(UICDM::IDOMReader &inReader);
+ BOOL CacheLogicRequiredAttributes(UICDM::IDOMReader &inReader, qt3ds::QT3DSI32 inSlideIndex = 0,
+ SParseSlide *inParentSlide = NULL);
+ void CacheClassRequiredAttributes(UICDM::IDOMReader &inReader);
+ void CacheClassSceneAttributes(UICDM::IDOMReader &inReader);
+ void CacheClassStateAttributes(UICDM::IDOMReader &inReader);
+ void AddElementRefToPatch(TPropertyDescAndValueList &outDescList, SElementData &inElement,
+ const char *inName, const char *inValue);
+ void PatchSceneElementRef();
+
+protected: // Slide helper
+ BOOL LoadState(IPresentation &inPresentation, SElement *inComponent, INT32 inSlideIndex,
+ UICDM::IDOMReader &inReader);
+ uic::runtime::SSlidePlayInformation GetPlayMode(UICDM::IDOMReader &inReader);
+ INT32 GetPlayThroughTo(INT32 inCurrentSlideIndex, UICDM::IDOMReader &inReader);
+ eastl::string GetSlideName(UICDM::IDOMReader &inReader);
+ eastl::string GetSlideId(UICDM::IDOMReader &inReader);
+ BOOL LoadSlideElements(IPresentation &inPresentation, UICDM::IDOMReader &inReader,
+ bool inMaster, SElement *inComponent, INT32 *outMaxTime = NULL);
+ SElementData *AddSlideElement(IPresentation &inPresentation, bool inMaster,
+ UICDM::IDOMReader &inReader, INT32 *outMaxTime = NULL);
+ BOOL LoadSlideElementAttrs(IPresentation &inPresentation, bool inMaster,
+ SElementData &inElementData, UICDM::IDOMReader &inReader,
+ SElement *inComponent);
+ BOOL ProcessStateRef(IPresentation &inPresentation, SElement *inComponent, bool inMaster,
+ UICDM::IDOMReader &inReader);
+
+protected: // Animation helper
+ void LoadAnimationTrack(IPresentation &inPresentation, SElementData &inElementData,
+ SParseSlideAnimationEntry &inAnimation);
+ void LoadAnimationKeys(IPresentation &inPresentation,
+ const SParseSlideAnimationEntry &inAnimation, bool inIsRotation);
+ BOOL LoadBezierKeys(IPresentation &inPresentation, NVConstDataRef<float> &inValues,
+ bool inIsRotation);
+ BOOL LoadLinearKeys(IPresentation &inPresentation, NVConstDataRef<float> &inValues,
+ bool inIsRotation);
+ BOOL LoadEaseInOutKeys(IPresentation &inPresentation, NVConstDataRef<float> &inValues,
+ bool inIsRotation);
+ SEaseInEaseOutKeyframe ParseEaseInOutKey(const float *&inFloatIter);
+ BOOL ProcessSlideAnimAction(IPresentation &inPresentation, eastl::string &inSlideId,
+ bool inMaster, UICDM::IDOMReader &inReader);
+ BOOL AddSlideAction(IPresentation &inPresentation, eastl::string &inSlideId, bool inActive,
+ UICDM::IDOMReader &inReader);
+ void CreateBezierKeyframeFromEaseInEaseOutKeyframe(float *inPreviousValue,
+ SEaseInEaseOutKeyframe &inCurrent,
+ float *inNextValue, float *&outBezierValues);
+
+protected: // Helper methods
+ bool IsStringType(ERuntimeDataModelDataType inDataType);
+ void GetAttributeList(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList,
+ TStrType inType, TStrType inName, TStrType inClassId, const char *inValue,
+ CRegisteredString *inPropNameStrs);
+ void GetAttributeList(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList,
+ ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType, const char *inName,
+ const char *inValue, CRegisteredString *inPropNameStrs);
+
+ SElementData *GetElementData(TStrType inElementName);
+ SElementData *GetElementData(const char8_t *inElementName);
+ SElement *GetElement(const char8_t *inElementName);
+ // Returns the data type and a boolean indicating if this attribute is actually used on a
+ // particular slide.
+ eastl::pair<ERuntimeDataModelDataType, bool>
+ GetAttributeType(const char8_t *inElementName, const char8_t *inPropertyName,
+ const SElementData &inElementData);
+ SElementData *ParseObjectRef(const eastl::string &inObjectPath, const char8_t *inOwnerId);
+ TStrType ParseObjectRefId(const eastl::string &inObjectPath, const char8_t *inOwnerId);
+
+ void GetMetaAttribute(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList,
+ TStrType inType, TStrType inName, TStrType inClassId,
+ CRegisteredString *inAttStrNames);
+
+protected:
+ void AddFloatAttribute(TPropertyDescAndValueList &outDescList, CRegisteredString inAttStrName,
+ float &inValue);
+ void AddLongAttribute(TPropertyDescAndValueList &outDescList, CRegisteredString inAttStrName,
+ qt3ds::QT3DSI32 &inValue);
+ void AddBoolAttribute(TPropertyDescAndValueList &outDescList, CRegisteredString inAttStrName,
+ bool &inValue);
+ void AddFloat2Attribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString *inAttStrNames, UICDM::SFloat2 &inValue);
+ void AddFloat3Attribute(TPropertyDescAndValueList &outDescList,
+ ERuntimeAdditionalMetaDataType inAdditionalType,
+ CRegisteredString *inAttStrNames, UICDM::SFloat3 &inValue);
+ void AddStringAttribute(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, const char *inValue);
+ void AddElementRefAttribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, SElement *inElement);
+
+ void AddSourcePath(const char *inValue)
+ {
+ if (m_SourcePathSet.find(inValue) == m_SourcePathSet.end()) {
+ m_SourcePathSet.insert(inValue);
+ m_SourcePathList.push_back(eastl::string(inValue));
+ }
+ }
+
+public: //
+ void release() override { delete this; }
+
+ //==============================================================================
+ // Friends
+ //==============================================================================
+ friend class CUIPParserActionHelper;
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UIPParser/Include/UICUIPParserObjectRefHelper.h b/src/Runtime/Source/UIPParser/Include/UICUIPParserObjectRefHelper.h
new file mode 100644
index 00000000..6c545db9
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Include/UICUIPParserObjectRefHelper.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICUIPParser.h"
+#include "UICUIPParserImpl.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * @class CUIPParserObjectRefHelper
+ * @brief Class for parsing UIP file - Object Reference Helper
+ */
+class CUIPParserObjectRefHelper
+{
+ typedef qt3ds::foundation::CRegisteredString TStrType;
+
+public:
+ typedef eastl::hash_map<TStrType, TStrType> TStrToStrMap;
+
+ /// Tree structure to cache scene graph information. This is used to resolve relative object
+ /// reference
+ struct SGraphNode
+ {
+ typedef eastl::vector<SGraphNode *> TGraphNodeList;
+
+ TStrType m_Id; // node id
+ TStrType m_Name; // name of the node. the name can be default from metadata, specified in
+ // graph section, or specified in logic section.
+ TStrType m_Type; // for example: Layer, Camera, Model
+ TStrType
+ m_Class; // class id. usually used by Behavior or objects that have custom properties.
+ void *m_ReaderContext; // Context to warp back to this node.
+ void *m_MasterSlide;
+ SGraphNode *m_Parent;
+ TGraphNodeList m_Children;
+ SGraphNode()
+ : m_ReaderContext(NULL)
+ , m_MasterSlide(NULL)
+ , m_Parent(NULL)
+ {
+ }
+ };
+ //==============================================================================
+ // Fields
+ //==============================================================================
+private:
+ typedef eastl::hash_set<TStrType> TImageNamePropertyList;
+ IRuntimeMetaData &m_MetaData; ///< Reference to Metadata
+ typedef eastl::hash_map<TStrType, SGraphNode *> TGraphNodeMap;
+ SGraphNode *m_RootNode;
+ TGraphNodeMap m_GraphNodeMap;
+ TImageNamePropertyList m_SlideIdSet;
+
+ // List of Image property names, for example diffusemap, normalmap, etc
+ // This is to handle material and images. Material's Image properties point to instances.
+ TImageNamePropertyList m_ImageNamePropertyList;
+ TStrType m_MaterialStr;
+ eastl::vector<void *> m_SceneGraphAliasList;
+
+ typedef eastl::pair<eastl::string, eastl::string> TLightProbeAndNamePair;
+ typedef eastl::map<eastl::string, eastl::string> TLightProbeIdToNameMap;
+ TLightProbeIdToNameMap m_LayerImageIdToNameMap;
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CUIPParserObjectRefHelper(IRuntimeMetaData &inMetaData);
+ virtual ~CUIPParserObjectRefHelper();
+
+ void CacheGraph(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inWriter);
+ SGraphNode *GetNode(const char *inId);
+ SGraphNode *GetNode(eastl::string inId);
+ TStrType GetName(const eastl::string &inId); // return the node name given the node id
+ TStrType GetType(const eastl::string &inId); // return the node type given the node id
+ TStrType GetClass(const eastl::string &inId); // return the node class given the node id
+
+ TStrType ParseObjectRefId(const eastl::string &inObjectPath, const char8_t *inOwnerId);
+ eastl::string BuildReferenceString(eastl::string inObjectPath);
+ void MarkAllReferencedAttributes(eastl::string inId,
+ const eastl::vector<eastl::string> &inReferences,
+ UICDM::IDOMReader &inReader,
+ SParseElementManager &outIdAttributesMap);
+
+private:
+ void CacheSceneGraph(UICDM::IDOMReader &inReader, SGraphNode *inParent = NULL);
+ SGraphNode &CacheSceneGraphNode(UICDM::IDOMReader &inReader, SGraphNode *inParent = NULL);
+ void CacheStateGraph(UICDM::IDOMReader &inReader);
+
+ void CopySceneGraph(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inWriter,
+ UICDM::IDOMWriter &inSlideWriter, TStrToStrMap &inMap,
+ const char *inAliasName, const char *inAliasId, SGraphNode &inParent);
+ void CopyStates(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inSlideWriter,
+ TStrToStrMap &inMap, const char *inAliasName, const char *inAliasId);
+ void CopyAttributes(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inSlideWriter,
+ TStrToStrMap &inMap, const char *inAliasName, const char *inAliasId);
+ void CopyHierarchy(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inSlideWriter,
+ TStrToStrMap &inMap, const char *inAliasName, const char *inAliasId);
+ void CopyStateCommands(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inWriter,
+ TStrToStrMap &oldToNewIdMap, const char *inAliasName,
+ const char *inOldId, const char *inNewId);
+ // Helper method for Preseve Attributes
+ SGraphNode *GetReferenceNode(SGraphNode *inInstance, eastl::string &inAssetName,
+ eastl::vector<SGraphNode *> &outInstanceList,
+ UICDM::IDOMReader &inReader);
+ bool MarkAttributeAsReferenced(SGraphNode *inBaseInstance,
+ eastl::vector<SGraphNode *> &inInstanceList,
+ eastl::string &inAttributeName, UICDM::IDOMReader &inReader,
+ SParseElementManager &outIdAttributesMap);
+ void MarkPreserveFlag(SGraphNode *inInstance, eastl::string inProperty,
+ SParseElementManager &outIdAttributesMap);
+ eastl::pair<const char8_t *, const char8_t *>
+ ProcessAliasAttribute(const char8_t *inObjId,
+ eastl::pair<const char8_t *, const char8_t *> inAttribute,
+ eastl::string &ioStrBuilder, TStrToStrMap &inMap);
+
+ eastl::string BuildAbsoluteReferenceString(eastl::string inId);
+ eastl::string BuildAbsoluteReferenceString(SGraphNode *inNode);
+
+ // Special case for material and images. Material's Image properties point to instances.
+ void BuildImageNamePropertyList();
+};
+
+} // namespace Q3DStudio
diff --git a/src/Runtime/Source/UIPParser/Source/UICUIPParserActionHelper.cpp b/src/Runtime/Source/UIPParser/Source/UICUIPParserActionHelper.cpp
new file mode 100644
index 00000000..fe9bb2fd
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Source/UICUIPParserActionHelper.cpp
@@ -0,0 +1,746 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4396) // specializer warning nonsense
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICUIPParserActionHelper.h"
+#include "UICUIPParserObjectRefHelper.h"
+#include "UICIPresentation.h"
+#include "UICCommandEventTypes.h"
+
+#include "UICDMPrefix.h"
+#include "UICDMXML.h"
+#include "UICDMWStrOpsImpl.h"
+#include "UICMetadata.h"
+#include "UICEulerAngles.h"
+#include "UICLogicSystem.h"
+#include "UICParametersSystem.h"
+
+using namespace UICDM;
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUIPParserActionHelper::CUIPParserActionHelper(CUIPParserImpl *inUIPParser,
+ CUIPParserObjectRefHelper *inObjRefHelper,
+ IRuntimeMetaData &inMetaData)
+ : m_UIPParser(inUIPParser)
+ , m_ObjRefHelper(inObjRefHelper)
+ , m_MetaData(inMetaData)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CUIPParserActionHelper::~CUIPParserActionHelper()
+{
+}
+
+void CUIPParserActionHelper::CacheAction(UICDM::IDOMReader &inReader,
+ const char8_t *inActionOwnerId)
+{
+ if (IsTrivial(inActionOwnerId))
+ return;
+
+ IDOMReader::Scope __childScope(inReader);
+
+ const char *theRef;
+ if (inReader.Att("ref", theRef)) {
+ // Ignore "ref" because we are only interested in new actions
+ return;
+ }
+
+ // Parse the action
+ SActionInfo theAction;
+ inReader.Att("id", theAction.m_Id);
+ theAction.m_Owner = inActionOwnerId;
+
+ const char *tempStr;
+ if (inReader.Att("triggerObject", tempStr))
+ theAction.m_TriggerObject = m_UIPParser->ParseObjectRefId(tempStr, inActionOwnerId);
+ inReader.Att("event", theAction.m_Event);
+ if (inReader.Att("targetObject", tempStr))
+ theAction.m_TargetObject = m_UIPParser->ParseObjectRefId(tempStr, inActionOwnerId);
+ if (inReader.Att("handler", tempStr)) {
+ theAction.m_Handler = tempStr;
+ CacheHandlerArguments(inReader, theAction);
+ }
+
+ // Only proceeds if we can find the elements
+ if (theAction.m_TargetObject.empty() || theAction.m_TriggerObject.empty()
+ || theAction.m_Owner.empty()) {
+ qCWarning(qt3ds::INVALID_OPERATION) << "Action invalid, id: " << theAction.m_Id.c_str();
+ return;
+ }
+
+ m_ActionMap[theAction.m_Id] = theAction;
+
+ // Build up logic tables to be processed by BuildAction later
+ // There are 2 tables involved:
+ // 1. The Listener-To-Events tables - multimap of each listener to all events it is listening to
+ // 2. The Listener-Event-To-Actions table - multimap of each listener-event pair to all actions
+ // it triggers
+ // note: The struct for Action is a pair of EventAction node and its owner
+ AddListenerEventPair(theAction.m_TriggerObject, theAction.m_Event);
+
+ SListenerEventNamePair theListenerEventPair(theAction.m_TriggerObject, theAction.m_Event);
+ TEventActionOwnerPair theLogicOwnerPair(theAction.m_Id, theAction.m_Owner);
+ m_ListenerEventActionsMap.insert(eastl::make_pair(theListenerEventPair, theLogicOwnerPair));
+}
+
+void CUIPParserActionHelper::AddListenerEventPair(eastl::string inListener,
+ const eastl::string &inEventName)
+{
+ // Check for dupes
+ TListenerEventsNameMap::iterator theStartItr = m_ListenerEventsNameMap.lower_bound(inListener);
+ TListenerEventsNameMap::iterator theEndItr = m_ListenerEventsNameMap.upper_bound(inListener);
+ for (; theStartItr != theEndItr; ++theStartItr) {
+ if (theStartItr->second == inEventName)
+ return;
+ }
+
+ m_ListenerEventsNameMap.insert(eastl::make_pair(inListener, inEventName));
+}
+
+void CUIPParserActionHelper::CacheHandlerArguments(UICDM::IDOMReader &inReader,
+ SActionInfo &inAction)
+{
+ IDOMReader::Scope __handlerArgScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ SHandlerArgumentInfo theArg;
+ inReader.Att("name", theArg.m_Name);
+ inReader.Att("value", theArg.m_Value);
+ inAction.m_HandlerArgs.push_back(theArg);
+ }
+ if (inAction.m_Handler == "Set Property") {
+ SHandlerArgumentInfo theHandlerArg1 = inAction.m_HandlerArgs[0];
+ SElementData *targetData = m_UIPParser->GetElementData(inAction.m_TargetObject.c_str());
+ if (targetData && !theHandlerArg1.m_Value.empty()) {
+ m_UIPParser->m_ParseElementManager.MarkAttributeAsReferenced(
+ *targetData, theHandlerArg1.m_Value.c_str());
+ }
+ }
+}
+
+SElement *CUIPParserActionHelper::GetElement(const eastl::string &inElementName)
+{
+ return m_UIPParser->GetElement(inElementName.c_str());
+}
+
+void CUIPParserActionHelper::GetActionSectionCount(
+ CUIPParserImpl::SActionSectionCount &outActionCount)
+{
+ // There are 2 tables involved:
+ // 1. The Listener-To-Events tables - multimap of each listener to all events it is listening to
+ // 2. The Listener-Event-To-Actions table - multimap of each listener-event pair to all actions
+ // it triggers
+ // note: The struct for Action is a pair of EventAction node and its owner
+
+ // Get the count to reserve
+ // Iterate through each listener
+ for (TListenerEventsNameMap::iterator theListenerItr = m_ListenerEventsNameMap.begin();
+ theListenerItr != m_ListenerEventsNameMap.end();) {
+ ++outActionCount.m_TriggerElementCount;
+
+ INT32 theEventCount =
+ static_cast<INT32>(m_ListenerEventsNameMap.count(theListenerItr->first));
+ for (INT32 theEventCounter = 0; theEventCounter < theEventCount;
+ ++theEventCounter, ++theListenerItr) {
+ ++outActionCount.m_TriggerEventCount;
+
+ // iterate through each listener-event pair
+ SListenerEventNamePair thePair(theListenerItr->first, theListenerItr->second);
+ TListenerEventActionsMap::iterator theActionsItr =
+ m_ListenerEventActionsMap.lower_bound(thePair);
+ INT32 theActionCount = static_cast<INT32>(m_ListenerEventActionsMap.count(thePair));
+ for (INT32 theActionCounter = 0; theActionCounter < theActionCount;
+ ++theActionCounter) {
+ eastl::string theActionId = theActionsItr->second.first;
+ outActionCount.m_ActionCount +=
+ GetActionCount(theActionId, outActionCount.m_StringAttrCount,
+ outActionCount.m_CustomParamCount);
+ ++theActionsItr;
+ }
+ }
+ }
+}
+
+void CUIPParserActionHelper::BuildActions(IPresentation &inPresentation)
+{
+ // Now we start building
+ // Iterate through each listener
+ for (TListenerEventsNameMap::iterator theListenerItr = m_ListenerEventsNameMap.begin();
+ theListenerItr != m_ListenerEventsNameMap.end();) {
+ TElement *theElement = GetElement(theListenerItr->first);
+
+ INT32 theEventCount =
+ static_cast<INT32>(m_ListenerEventsNameMap.count(theListenerItr->first));
+ for (INT32 theEventCounter = 0; theEventCounter < theEventCount;
+ ++theEventCounter, ++theListenerItr) {
+ UINT32 theEventName =
+ CHash::HashEventCommand(theListenerItr->second.c_str()); // UINT32: HashedName
+
+ // iterate through each listener-event pair
+ SListenerEventNamePair thePair(theListenerItr->first, theListenerItr->second);
+ TListenerEventActionsMap::iterator theActionsItr =
+ m_ListenerEventActionsMap.lower_bound(thePair);
+ INT32 theActionCount = static_cast<INT32>(m_ListenerEventActionsMap.count(thePair));
+ for (INT32 theActionCounter = 0; theActionCounter < theActionCount;
+ ++theActionCounter) {
+ eastl::string theActionId = theActionsItr->second.first;
+ if (theElement)
+ BuildAction(*theElement, theEventName, inPresentation, theActionId);
+ ++theActionsItr;
+ }
+ }
+ }
+}
+
+union UTypeConverter {
+ SAttributeKey m_Key;
+ INT32 m_IntData;
+};
+
+struct SActionAdder
+{
+ ILogicSystem &m_LogicSystem;
+ TElement &m_EventElement;
+ UINT32 m_EventName;
+ TElement *m_Owner;
+ TElement *m_Target;
+
+ SActionAdder(ILogicSystem &inLogicSystem, TElement &inEventElement, UINT32 inEventName,
+ TElement *inOwner, TElement *inTarget)
+ : m_LogicSystem(inLogicSystem)
+ , m_EventElement(inEventElement)
+ , m_EventName(inEventName)
+ , m_Owner(inOwner)
+ , m_Target(inTarget)
+ {
+ }
+
+ INT32 AddAction(TEventCommandHash inCommand, UINT32 inArg1 = 0, UINT32 inArg2 = 0)
+ {
+ UVariant arg1Var;
+ UVariant arg2Var;
+ arg1Var.m_INT32 = (INT32)inArg1;
+ arg2Var.m_INT32 = (INT32)inArg2;
+ return m_LogicSystem.AddAction(m_EventElement, m_EventName, m_Target, m_Owner, inCommand,
+ arg1Var, arg2Var, true);
+ }
+};
+
+void CUIPParserActionHelper::BuildAction(TElement &inElement, UINT32 inEventName,
+ IPresentation &inPresentation,
+ const eastl::string &inActionId)
+{
+ ILogicSystem &theLogicBuilder = inPresentation.GetLogicSystem();
+ IParametersSystem &theParamSystem = inPresentation.GetParametersSystem();
+ TActionMap::iterator theIter = m_ActionMap.find(inActionId);
+ if (theIter == m_ActionMap.end()) {
+ Q3DStudio_ASSERT(false);
+ qCWarning(qt3ds::INVALID_OPERATION) << "Can't find action, id: " << inActionId.c_str();
+ return;
+ }
+
+ SActionInfo theAction = theIter->second;
+ INT32 theAddActionIndex = -1; // the index of newly added action. If there are more than 1
+ // actions, the index points to the firstly added action.
+ SActionAdder theAdder(theLogicBuilder, inElement, inEventName, GetElement(theAction.m_Owner),
+ GetElement(theAction.m_TargetObject));
+
+ // The list of applicable handler is loaded from metadata xml file (if it is non-custom handler)
+ bool theIsCustomHandler = IsCustomHandler(theAction);
+
+ if (theIsCustomHandler) {
+ // Argument 1 - param table start index
+ INT32 paramGroup = theParamSystem.CreateParameterGroup();
+
+ // First param is the handler name we want to invoke for the custom action.
+ ExportCustomActionParameters(inPresentation, theParamSystem, paramGroup,
+ theAction.m_Handler.c_str(), ERuntimeDataModelDataTypeString,
+ ERuntimeAdditionalMetaDataTypeNone);
+
+ int theHandlerArgumentCount = theAction.m_HandlerArgs.size();
+ ERuntimeDataModelDataType theType;
+ ERuntimeAdditionalMetaDataType theAdditionalType;
+ // Actual handler parameters to pass in.
+ for (int theIndex = 0; theIndex < theHandlerArgumentCount; ++theIndex) {
+ GetHandlerArgumentType(theAction, theIndex, theType, theAdditionalType);
+ ExportCustomActionParameters(inPresentation, theParamSystem, paramGroup,
+ theAction.m_HandlerArgs[theIndex].m_Value.c_str(), theType,
+ theAdditionalType);
+ }
+ theAddActionIndex = theAdder.AddAction(COMMAND_CUSTOMACTION, (UINT32)paramGroup);
+ } else if (theAction.m_Handler == "Set Property") // Plain set action
+ {
+ // ArgumentOne - HashPropertyName
+ // ArgumentTwo - Value
+ SHandlerArgumentInfo theHandlerArg1 = theAction.m_HandlerArgs[0];
+ SHandlerArgumentInfo theHandlerArg2 = theAction.m_HandlerArgs[1];
+
+ eastl::string thePropertyName = theHandlerArg1.m_Value;
+ SElementData *theTargetObject =
+ m_UIPParser->GetElementData(theAction.m_TargetObject.c_str());
+ if (theTargetObject) {
+ SElementPropertyInfo *theProperty = m_UIPParser->m_ParseElementManager.FindProperty(
+ *theTargetObject, thePropertyName.c_str());
+ if (theProperty) {
+ TPropertyDescAndValueList theProperties;
+ ERuntimeDataModelDataType theType = theProperty->m_DataType;
+ ERuntimeAdditionalMetaDataType theAdditionalType = theProperty->m_AdditionalType;
+
+ m_UIPParser->GetAttributeList(inPresentation, theProperties, theType,
+ theAdditionalType, thePropertyName.c_str(),
+ theHandlerArg2.m_Value.c_str(),
+ theProperty->m_PropertyNames);
+
+ UINT32 theActionCount = theProperties.size();
+ Q3DStudio_ASSERT(theActionCount > 0);
+ for (UINT32 theActionIndex = 0; theActionIndex < theActionCount; ++theActionIndex) {
+ INT32 actionId = theAdder.AddAction(
+ COMMAND_SETPROPERTY, theProperties[theActionIndex].first.GetNameHash(),
+ theProperties[theActionIndex].second.m_INT32);
+ if (theActionIndex == 0)
+ theAddActionIndex = actionId;
+ }
+ }
+ }
+ } else if (theAction.m_Handler == "Fire Event") // Fire the selected event on the element
+ {
+ theAddActionIndex = theAdder.AddAction(
+ COMMAND_FIREEVENT, CHash::HashEventCommand(theAction.m_HandlerArgs[0].m_Value.c_str()));
+ } else if (theAction.m_Handler == "Go to Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(
+ COMMAND_GOTOSLIDENAME, CHash::HashString(theAction.m_HandlerArgs[0].m_Value.c_str()));
+ } else if (theAction.m_Handler == "Next Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_GOTONEXTSLIDE);
+ } else if (theAction.m_Handler == "Previous Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_GOTOPREVIOUSSLIDE);
+ } else if (theAction.m_Handler == "Preceding Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_BACKSLIDE);
+ } else if (theAction.m_Handler == "Play") // Play
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_PLAY);
+ } else if (theAction.m_Handler == "Pause") // Pause
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_PAUSE);
+ } else if (theAction.m_Handler == "Go to Time") // Goto Time
+ {
+ float theTime = 0;
+ const char *theValue = theAction.m_HandlerArgs[0].m_Value.c_str();
+ if (!IsTrivial(theValue))
+ WStrOps<float>().StrTo(theValue, theTime);
+
+ theAddActionIndex =
+ theAdder.AddAction(COMMAND_GOTOTIME, static_cast<UINT32>(theTime * 1000.0f));
+
+ bool thePause = false;
+ theValue = theAction.m_HandlerArgs[1].m_Value.c_str();
+ if (!IsTrivial(theValue))
+ WStrOps<bool>().StrTo(theValue, thePause);
+ theAdder.AddAction(thePause ? COMMAND_PAUSE : COMMAND_PLAY);
+ } else if (theAction.m_Handler == "Play Sound") {
+ qt3ds::foundation::CStringHandle theStringHandle;
+ if (!theAction.m_HandlerArgs[0].m_Value.empty()) {
+ const char *theValue = theAction.m_HandlerArgs[0].m_Value.c_str();
+ theStringHandle = inPresentation.GetStringTable().GetHandle(theValue);
+ }
+ theAddActionIndex = theAdder.AddAction(COMMAND_PLAYSOUND, theStringHandle.handle());
+ } else if (theAction.m_Handler == "Emit Signal") // Emit a signal
+ {
+ qt3ds::foundation::CStringHandle theStringHandle;
+ if (!theAction.m_HandlerArgs[0].m_Value.empty()) {
+ const char *theValue = theAction.m_HandlerArgs[0].m_Value.c_str();
+ theStringHandle = inPresentation.GetStringTable().GetHandle(theValue);
+ }
+ theAddActionIndex = theAdder.AddAction(COMMAND_EMITSIGNAL, theStringHandle.handle());
+ } else {
+ Q3DStudio_ASSERT(false); // what sort of crazy action is this?
+ }
+
+ if (theAddActionIndex > -1)
+ m_ActionIdentifierMap[theAction.m_Id] = theAddActionIndex;
+}
+
+INT32 CUIPParserActionHelper::GetActionCount(const eastl::string &inActionId)
+{
+ INT32 theStringAttrCount = 0;
+ INT32 theCustomParamCount = 0;
+ return GetActionCount(inActionId, theStringAttrCount, theCustomParamCount);
+}
+
+INT32 CUIPParserActionHelper::GetActionCount(const eastl::string &inActionId,
+ INT32 &outStringAttrCount, INT32 &outCustomParamCount)
+{
+ INT32 theActionCount = 0;
+
+ TActionMap::iterator theIter = m_ActionMap.find(inActionId);
+ if (theIter == m_ActionMap.end()) {
+ Q3DStudio_ASSERT(false);
+ qCWarning(qt3ds::INVALID_OPERATION) << "Can't find action, id: " << inActionId.c_str();
+ return theActionCount;
+ }
+
+ SActionInfo theAction = theIter->second;
+
+ // The list of applicable handler is loaded from metadata xml file (if it is non-custom handler)
+ bool theIsCustomHandler = IsCustomHandler(theAction);
+
+ if (theIsCustomHandler) {
+ theActionCount = 1;
+
+ // First param is the handler name we want to invoke for the custom action.
+ ++outStringAttrCount;
+ ++outCustomParamCount;
+
+ int theHandlerArgumentCount = theAction.m_HandlerArgs.size();
+ ERuntimeDataModelDataType theType;
+ ERuntimeAdditionalMetaDataType theAdditionalType;
+ // Actual handler parameters to pass in.
+ for (int theIndex = 0; theIndex < theHandlerArgumentCount; ++theIndex) {
+ GetHandlerArgumentType(theAction, theIndex, theType, theAdditionalType);
+ GetCustomActionParametersCount(theType, theAdditionalType, outStringAttrCount,
+ outCustomParamCount);
+ }
+ }
+
+ else if (theAction.m_Handler == "Set Property") // Plain set action
+ {
+ SHandlerArgumentInfo theHandlerArg1 = theAction.m_HandlerArgs[0];
+
+ eastl::string thePropertyName = theHandlerArg1.m_Value;
+ SElementData *theData = m_UIPParser->GetElementData(theAction.m_TargetObject.c_str());
+ if (theData) {
+ SElementPropertyInfo *thePropertyInfo =
+ m_UIPParser->m_ParseElementManager.GetOrCreateProperty(*theData,
+ thePropertyName.c_str());
+ if (thePropertyInfo) {
+ theActionCount = thePropertyInfo->m_Arity;
+ if (m_UIPParser->IsStringType(thePropertyInfo->m_DataType))
+ ++outStringAttrCount;
+ }
+ }
+ }
+
+ else if (theAction.m_Handler == "Fire Event" // Fire the selected event on the element
+ || theAction.m_Handler == "Go to Slide" // Switch slides
+ || theAction.m_Handler == "Next Slide" // Switch slides
+ || theAction.m_Handler == "Previous Slide" // Switch slides
+ || theAction.m_Handler == "Preceding Slide" // Switch slides
+ || theAction.m_Handler == "Play" // Play
+ || theAction.m_Handler == "Pause" // Pause
+ ) {
+ theActionCount = 1;
+ }
+
+ else if (theAction.m_Handler == "Go to Time") // Goto Time
+ {
+ theActionCount = 2;
+ } else if (theAction.m_Handler == "Play Sound") // Play Sound
+ {
+ theActionCount = 1;
+ ++outStringAttrCount;
+ } else if (theAction.m_Handler == "Emit Signal") // Emit Signal
+ {
+ theActionCount = 1;
+ ++outStringAttrCount;
+ } else {
+ Q3DStudio_ASSERT(false); // what sort of crazy action is this?
+ }
+
+ return theActionCount;
+}
+
+INT32 CUIPParserActionHelper::GetActionIndex(const eastl::string &inActionId)
+{
+ TActionIdentifierMap::iterator theFind = m_ActionIdentifierMap.find(inActionId);
+ if (theFind != m_ActionIdentifierMap.end())
+ return theFind->second;
+ Q3DStudio_ASSERT(false);
+ return -1;
+}
+
+bool CUIPParserActionHelper::IsCustomHandler(const SActionInfo &inAction)
+{
+ const char *theClass = m_ObjRefHelper->GetClass(inAction.m_TargetObject);
+ if (!IsTrivial(theClass))
+ return m_MetaData.IsCustomHandler(theClass, inAction.m_Handler.c_str());
+ return false;
+}
+
+void CUIPParserActionHelper::GetHandlerArgumentType(
+ const SActionInfo &inAction, int inArgumentIndex, ERuntimeDataModelDataType &outType,
+ ERuntimeAdditionalMetaDataType &outAdditionalType)
+{
+ const char *theClass = m_ObjRefHelper->GetClass(inAction.m_TargetObject);
+ return m_MetaData.GetHandlerArgumentType(theClass, inAction.m_Handler.c_str(),
+ inAction.m_HandlerArgs[inArgumentIndex].m_Name.c_str(),
+ outType, outAdditionalType);
+}
+
+void CUIPParserActionHelper::GetCustomActionParametersCount(
+ ERuntimeDataModelDataType inDataType, ERuntimeAdditionalMetaDataType inAdditionalType,
+ INT32 &outStringAttrCount, INT32 &outCustomParamCount)
+{
+ // This function should match ExportCustomActionParameters
+ switch (inDataType) {
+ case ERuntimeDataModelDataTypeFloat:
+ case ERuntimeDataModelDataTypeLong:
+ case ERuntimeDataModelDataTypeBool: {
+ outCustomParamCount += 1;
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ outCustomParamCount += 2;
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ if (inAdditionalType == ERuntimeAdditionalMetaDataTypeColor) {
+ // Append rgba
+ outCustomParamCount += 4;
+ } else {
+ // Append xyz
+ outCustomParamCount += 3;
+ }
+ break;
+ }
+ // default to string
+ default: {
+ outCustomParamCount += 1;
+ outStringAttrCount += 1;
+ }
+ }
+}
+
+namespace {
+
+ using qt3ds::foundation::IStringTable;
+
+ struct SCustomParameterParseInfoFloat
+ {
+ typedef float TParseType;
+ static const char8_t *Name() { return "float"; }
+ static TParseType Default() { return 0; }
+ static Q3DStudio::UVariant ToVariant(const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = inParseType;
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoLong
+ {
+ typedef QT3DSI32 TParseType;
+ static const char8_t *Name() { return "long"; }
+ static TParseType Default() { return 0; }
+ static Q3DStudio::UVariant ToVariant(const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoBool
+ {
+ typedef bool TParseType;
+ static const char8_t *Name() { return "bool"; }
+ static TParseType Default() { return false; }
+ static Q3DStudio::UVariant ToVariant(const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoFloat2
+ {
+ typedef SFloat2 TParseType;
+ static const char8_t *Name() { return "float2"; }
+ static TParseType Default() { return SFloat2(0, 0); }
+ static QT3DSU32 NumParameters() { return 2; }
+ static Q3DStudio::UVariant ToVariant(QT3DSU32 inIdx, const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType[inIdx]);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoFloat3
+ {
+ typedef SFloat3 TParseType;
+ static const char8_t *Name() { return "float3"; }
+ static const char8_t **Extensions()
+ {
+ static const char8_t *retval[] = { ".x", ".y", ".z", NULL };
+ return retval;
+ }
+ static TParseType Default() { return SFloat3(0, 0, 0); }
+ static QT3DSU32 NumParameters() { return 3; }
+ static Q3DStudio::UVariant ToVariant(QT3DSU32 inIdx, const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType[inIdx]);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoColor
+ {
+ typedef SFloat3 TParseType;
+ static const char8_t *Name() { return "color4"; }
+ static TParseType Default() { return SFloat3(0, 0, 0); }
+ static QT3DSU32 NumParameters() { return 4; }
+ static Q3DStudio::UVariant ToVariant(QT3DSU32 inIdx, const TParseType &inParseType)
+ {
+ if (inIdx < 3) {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType[inIdx]) * 255.0f;
+ return retval;
+ } else {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = 255.0f;
+ return retval;
+ }
+ }
+ };
+
+ template <typename TParseInfo>
+ struct ParseParameter
+ {
+ void operator()(WCharTReader &inReader, const char *inValue, IParametersSystem &inSystem,
+ QT3DSI32 inGroupId)
+ {
+ typename TParseInfo::TParseType theValue = TParseInfo::Default();
+ if (!IsTrivial(inValue))
+ inReader.Read(theValue);
+ Q3DStudio::UVariant theVarValue = TParseInfo::ToVariant(theValue);
+ inSystem.AddParameter(inGroupId, CHash::HashString(TParseInfo::Name()), theVarValue);
+ }
+ };
+
+ template <typename TParseInfo>
+ struct ParseAggregateParameter
+ {
+ void operator()(WCharTReader &inReader, const char *inValue, IParametersSystem &inSystem,
+ QT3DSI32 inGroupId)
+ {
+ typename TParseInfo::TParseType theValue = TParseInfo::Default();
+ if (!IsTrivial(inValue))
+ inReader.ReadRef(NVDataRef<float>(&theValue[0], TParseInfo::NumParameters()));
+
+ for (QT3DSU32 idx = 0, end = TParseInfo::NumParameters(); idx < end; ++idx) {
+ Q3DStudio::UVariant theVarValue = TParseInfo::ToVariant(idx, theValue);
+ inSystem.AddParameter(inGroupId, CHash::HashString(TParseInfo::Name()),
+ theVarValue);
+ }
+ }
+ };
+}
+
+void CUIPParserActionHelper::ExportCustomActionParameters(
+ IPresentation &inPresentation, IParametersSystem &inParamSystem, QT3DSI32 inParamGroupId,
+ const char *inValue, ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType)
+{
+ // Create a destructible value
+ m_UIPParser->m_ValueBuffer.clear();
+ m_UIPParser->m_ValueBuffer.write(inValue, (QT3DSU32)strlen(inValue) + 1);
+ // Clear the destination buffer
+ m_UIPParser->m_TempBuffer.clear();
+ WCharTReader theReader((char8_t *)m_UIPParser->m_ValueBuffer.begin(), m_UIPParser->m_TempBuffer,
+ *m_UIPParser->GetDOMReader().GetStringTable());
+
+ // The function should match CLuaEngine::ProcessCustomActions
+ // The function should match CUIPParserActionHelper::GetCustomActionParametersCount
+ switch (inDataType) {
+ case ERuntimeDataModelDataTypeFloat: {
+ ParseParameter<SCustomParameterParseInfoFloat>()(theReader, inValue, inParamSystem,
+ inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeLong: {
+ ParseParameter<SCustomParameterParseInfoLong>()(theReader, inValue, inParamSystem,
+ inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeBool: {
+ ParseParameter<SCustomParameterParseInfoBool>()(theReader, inValue, inParamSystem,
+ inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ ParseAggregateParameter<SCustomParameterParseInfoFloat2>()(theReader, inValue,
+ inParamSystem, inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ if (inAdditionalType == ERuntimeAdditionalMetaDataTypeColor) {
+ ParseAggregateParameter<SCustomParameterParseInfoColor>()(
+ theReader, inValue, inParamSystem, inParamGroupId);
+ } else {
+ ParseAggregateParameter<SCustomParameterParseInfoFloat3>()(
+ theReader, inValue, inParamSystem, inParamGroupId);
+ }
+ break;
+ }
+ // default to string
+ default: {
+ UVariant theValue;
+ theValue.m_StringHandle = inPresentation.GetStringTable().GetHandle(inValue);
+ inParamSystem.AddParameter(inParamGroupId, CHash::HashString("string"), theValue);
+ break;
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/UIPParser/Source/UICUIPParserImpl.cpp b/src/Runtime/Source/UIPParser/Source/UICUIPParserImpl.cpp
new file mode 100644
index 00000000..fe2835f5
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Source/UICUIPParserImpl.cpp
@@ -0,0 +1,2574 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4396) // specializer warning nonsense
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICIPresentation.h"
+#include "UICIScriptBridge.h"
+#include "UICAttributeHashes.h"
+#include "UICCommandEventTypes.h"
+#include "UICDMPrefix.h"
+#include "UICDMComposerTypeDefinitions.h"
+#include "UICDMWStrOpsImpl.h"
+#include "UICUIPParserActionHelper.h"
+#include "UICUIPParserObjectRefHelper.h"
+#include "UICApplication.h"
+#include "UICRuntimeFactory.h"
+#include "UICSceneGraphDebugger.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "UICElementSystem.h"
+#include "UICAnimationSystem.h"
+#include "UICSlideSystem.h"
+
+using namespace UICDM;
+
+#ifndef M_PI
+#define M_PI 3.1415926535898
+#endif
+
+#define TODEG(x) x = (float)(x * 180 / M_PI);
+#define TORAD(x) x = (float)(x / 180 * M_PI);
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+TStrType SParseElementManager::RegisterStr(const char8_t *inStr)
+{
+ return m_MetaData.GetStringTable()->GetRenderStringTable().RegisterStr(inStr);
+}
+SElementData &SParseElementManager::GetOrCreateElementData(const char8_t *inIdOrRef,
+ const char8_t *inElemType,
+ const char8_t *inElemClassId)
+{
+ if (inIdOrRef == NULL)
+ inIdOrRef = "";
+ if (inIdOrRef[0] == '#')
+ ++inIdOrRef;
+ if (inElemClassId == NULL)
+ inElemClassId = "";
+ if (inElemClassId[0] == '#')
+ ++inElemClassId;
+ if (inElemType == NULL)
+ inElemType = "";
+ TStrType theStr = RegisterStr(inIdOrRef);
+ eastl::pair<TIdElementMap::iterator, bool> theInserter =
+ m_ElementMap.insert(eastl::make_pair(theStr, SElementData(theStr)));
+ SElementData &retval(theInserter.first->second);
+ if (theInserter.second) {
+ retval.m_Class = RegisterStr(inElemClassId);
+ retval.m_Type = RegisterStr(inElemType);
+ }
+ return retval;
+}
+SElementData *SParseElementManager::FindElementData(const char8_t *inIdOrRef)
+{
+ if (inIdOrRef == NULL)
+ inIdOrRef = "";
+ if (inIdOrRef[0] == '#')
+ ++inIdOrRef;
+ TStrType theStr = RegisterStr(inIdOrRef);
+ TIdElementMap::iterator theIter = m_ElementMap.find(theStr);
+ if (theIter != m_ElementMap.end())
+ return &theIter->second;
+ return NULL;
+}
+static void SetPropertyValueHash(eastl::string &inWorkspace, const char8_t *inExtension,
+ qt3ds::QT3DSU32 *&ioHashes, eastl::string::size_type originalSize,
+ CRegisteredString *&ioPropNames,
+ qt3ds::foundation::IStringTable &ioStringTable)
+{
+ if (inExtension && *inExtension)
+ inWorkspace.append(inExtension);
+ *ioHashes = Q3DStudio::CHash::HashAttribute(inWorkspace.c_str());
+ *ioPropNames = ioStringTable.RegisterStr(inWorkspace.c_str());
+ ++ioHashes;
+ ++ioPropNames;
+ inWorkspace.resize(originalSize);
+}
+static eastl::pair<qt3ds::QT3DSU32, eastl::string::size_type>
+SetupPropertyWorkspace(const char8_t *inPropName, eastl::string &ioWorkspace)
+{
+ qt3ds::QT3DSU32 outSubIndex = 0;
+ ioWorkspace.assign(inPropName ? inPropName : "");
+ eastl::string::size_type thePeriodPos = ioWorkspace.find('.');
+ if (thePeriodPos != eastl::string::npos) {
+ if (thePeriodPos < ioWorkspace.size() - 1) {
+ switch (ioWorkspace[thePeriodPos + 1]) {
+ default:
+ QT3DS_ASSERT(false);
+ case 'r':
+ case 'x':
+ break;
+ case 'g':
+ case 'y':
+ outSubIndex = 1;
+ break;
+ case 'b':
+ case 'z':
+ outSubIndex = 2;
+ break;
+ case 'a':
+ case 'w':
+ outSubIndex = 3;
+ break;
+ }
+ }
+ ioWorkspace.resize(thePeriodPos);
+ }
+ return eastl::make_pair(ioWorkspace.size(), outSubIndex);
+}
+SElementPropertyInfo *SParseElementManager::GetOrCreateProperty(SElementData &inData,
+ const char8_t *inPropertyName)
+{
+ SElementData &theData(inData);
+ SElementPropertyInfo *retvalPtr = FindProperty(inData, inPropertyName);
+ if (retvalPtr)
+ return retvalPtr;
+
+ eastl::string::size_type thePeriodPos =
+ SetupPropertyWorkspace(inPropertyName, m_Workspace).first;
+ TStrType theStr = RegisterStr(m_Workspace.c_str());
+
+ if (m_MetaData.IsPropertyExist(inData.m_Type, theStr, inData.m_Class) == false)
+ return NULL;
+
+ eastl::pair<TAttrMap::iterator, bool> theInserter =
+ theData.m_PropertyMap.insert(eastl::make_pair(theStr, SElementPropertyInfo(theStr)));
+ SElementPropertyInfo &retval(theInserter.first->second);
+ if (theInserter.second) {
+ qt3ds::intrinsics::memZero(retval.m_PropertyHashes, sizeof(retval.m_PropertyHashes));
+ qt3ds::QT3DSU32 *thePropHashes(retval.m_PropertyHashes);
+ CRegisteredString *thePropNames(retval.m_PropertyNames);
+ retval.m_DataType = m_MetaData.GetPropertyType(theData.m_Type, theStr, theData.m_Class);
+ retval.m_AdditionalType =
+ m_MetaData.GetAdditionalType(theData.m_Type, theStr, theData.m_Class);
+ if (retval.m_DataType != ERuntimeDataModelDataTypeNone) {
+ switch (retval.m_DataType) {
+ default:
+ retval.m_Arity = 1;
+ break;
+ case ERuntimeDataModelDataTypeFloat2:
+ retval.m_Arity = 2;
+ break;
+ case ERuntimeDataModelDataTypeFloat3:
+ retval.m_Arity = 3;
+ break;
+ }
+ if (retval.m_Arity > 1) {
+ if (retval.m_Arity == 2) {
+ SetPropertyValueHash(m_Workspace, ".x", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ SetPropertyValueHash(m_Workspace, ".y", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ } else {
+ if (m_MetaData.GetAdditionalType(theData.m_Type, theStr, theData.m_Class)
+ == ERuntimeAdditionalMetaDataTypeColor) {
+ SetPropertyValueHash(m_Workspace, ".r", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ SetPropertyValueHash(m_Workspace, ".g", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ SetPropertyValueHash(m_Workspace, ".b", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ } else {
+ SetPropertyValueHash(m_Workspace, ".x", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ SetPropertyValueHash(m_Workspace, ".y", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ SetPropertyValueHash(m_Workspace, ".z", thePropHashes, thePeriodPos,
+ thePropNames, m_StringTable);
+ }
+ }
+ } else {
+ retval.m_PropertyHashes[0] = Q3DStudio::CHash::HashAttribute(theStr.c_str());
+ retval.m_PropertyNames[0] = m_StringTable.RegisterStr(m_Workspace.c_str());
+ }
+ }
+ }
+ return &retval;
+}
+
+SElementPropertyInfo *SParseElementManager::GetOrCreateProperty(const char8_t *inIdOrRef,
+ const char8_t *inElemType,
+ const char8_t *inElemClassId,
+ const char8_t *inPropertyName)
+{
+ return GetOrCreateProperty(GetOrCreateElementData(inIdOrRef, inElemType, inElemClassId),
+ inPropertyName);
+}
+
+eastl::pair<SElementPropertyInfo *, qt3ds::QT3DSU32>
+SParseElementManager::FindPropertyWithSubIndex(SElementData &inElement,
+ const char8_t *inPropertyName)
+{
+ qt3ds::QT3DSU32 subIndex = SetupPropertyWorkspace(inPropertyName, m_Workspace).second;
+ TStrType theStr = RegisterStr(m_Workspace.c_str());
+ TAttrMap::iterator theIter = inElement.m_PropertyMap.find(theStr);
+ SElementPropertyInfo *retval = NULL;
+ if (theIter != inElement.m_PropertyMap.end())
+ retval = &theIter->second;
+ return eastl::make_pair(retval, subIndex);
+}
+
+SElementPropertyInfo *SParseElementManager::FindProperty(SElementData &inElement,
+ const char8_t *inPropertyName)
+{
+ return FindPropertyWithSubIndex(inElement, inPropertyName).first;
+}
+SElementPropertyInfo *SParseElementManager::FindProperty(const char8_t *inIdOrRef,
+ const char8_t *inPropertyName)
+{
+ SElementData *theData(FindElementData(inIdOrRef));
+ if (theData)
+ return FindProperty(*theData, inPropertyName);
+ return NULL;
+}
+
+void SParseElementManager::MarkAttributeAsReferenced(SElementData &inElement,
+ const char8_t *inPropertyName)
+{
+ SElementPropertyInfo *theProp = GetOrCreateProperty(inElement, inPropertyName);
+ if (theProp)
+ theProp->m_ElementFlag = true;
+}
+
+void SParseElementManager::MarkAttributeAsReferenced(const char8_t *inElement,
+ const char8_t *inPropertyName)
+{
+ SElementData *theData = FindElementData(inElement);
+ if (theData)
+ MarkAttributeAsReferenced(*theData, inPropertyName);
+}
+
+void SParseElementManager::MarkAllAttributesAsReferenced(SElementData &inElement)
+{
+ m_PropertyList.clear();
+ m_MetaData.GetInstanceProperties(inElement.m_Type, inElement.m_Class, m_PropertyList, false);
+ for (QT3DSU32 idx = 0, end = m_PropertyList.size(); idx < end; ++idx)
+ MarkAttributeAsReferenced(inElement, m_PropertyList[idx].c_str());
+}
+
+TStrType SParseSlideManager::RegisterId(const char8_t *inStr)
+{
+ if (!inStr)
+ inStr = "";
+ if (*inStr == '#')
+ ++inStr;
+ return RegisterStr(inStr);
+}
+
+SParseSlideManager::~SParseSlideManager()
+{
+ for (QT3DSU32 idx = 0, end = m_Animations.size(); idx < end; ++idx)
+ delete m_Animations[idx];
+ m_Animations.clear();
+}
+
+SParseSlide &SParseSlideManager::GetOrCreateSlide(const char8_t *inSlideId, qt3ds::QT3DSI32 inSlideIndex)
+{
+ TStrType theSlideId(RegisterId(inSlideId));
+ return m_SlideMap.insert(eastl::make_pair(theSlideId, SParseSlide(theSlideId, inSlideIndex)))
+ .first->second;
+}
+
+SParseSlide *SParseSlideManager::FindSlide(const char8_t *inSlideId)
+{
+ TStrType theSlideId(RegisterId(inSlideId));
+ TSlideIdToParseSlideMap::iterator theIter = m_SlideMap.find(theSlideId);
+ if (theIter != m_SlideMap.end())
+ return &theIter->second;
+ return NULL;
+}
+
+void SParseSlideManager::SetAnimationData(SParseSlide &inSlide, const char8_t *inInstanceId,
+ const char8_t *inPropertyName,
+ const char8_t *inKeyframeData,
+ SParseSlideAnimationTypes::Enum inType, bool inIsDynamic,
+ bool inIsActive)
+{
+ TStrType thePropertyName(RegisterStr(inPropertyName));
+ SElementData *theElemData = m_ElementManager.FindElementData(inInstanceId);
+ if (theElemData == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ eastl::pair<SElementPropertyInfo *, qt3ds::QT3DSU32> theProperty =
+ m_ElementManager.FindPropertyWithSubIndex(*theElemData, thePropertyName);
+ if (theProperty.first == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ qt3ds::QT3DSU32 thePropertyHash = theProperty.first->m_PropertyHashes[theProperty.second];
+ // Parse the keyframe data into floating point numbers.
+ if (inKeyframeData == NULL)
+ inKeyframeData = "";
+ m_KeyframeParseBuffer.clear();
+ m_KeyframeParseBuffer.assign(inKeyframeData);
+ m_KeyframeParseFloatBuffer.clear();
+ char8_t *theBufData = const_cast<char8_t *>(m_KeyframeParseBuffer.c_str());
+
+ char8_t *theStartPtr = UICDM::FindNextNonWhitespace(theBufData);
+ while (theStartPtr && *theStartPtr) {
+ char8_t *nextPtr = UICDM::FindNextWhitespace(theStartPtr);
+ if (nextPtr && *nextPtr)
+ *nextPtr = 0;
+ else
+ nextPtr = NULL;
+ QT3DSF32 temp;
+ WStrOps<QT3DSF32>().StrTo(theStartPtr, temp);
+ m_KeyframeParseFloatBuffer.push_back(temp);
+ theStartPtr = nextPtr;
+ if (theStartPtr)
+ theStartPtr = FindNextNonWhitespace(theStartPtr + 1);
+ }
+ // Don't create animations with no keyframes.
+ if (m_KeyframeParseFloatBuffer.empty()) {
+ return;
+ }
+
+ SParseSlideAnimationEntry *theEntry =
+ new SParseSlideAnimationEntry(inSlide.m_SlideId, theElemData->m_Id, thePropertyName,
+ thePropertyHash, inType, NULL, 0, inIsDynamic);
+ theEntry->m_KeyframeData = m_KeyframeParseFloatBuffer;
+ m_Animations.push_back(theEntry);
+ switch (inType) {
+ case SParseSlideAnimationTypes::Linear:
+ m_AnimationKeyframeCount += m_KeyframeParseFloatBuffer.size() / 2;
+ break;
+ case SParseSlideAnimationTypes::Bezier:
+ m_AnimationKeyframeCount += m_KeyframeParseFloatBuffer.size() / 6;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ case SParseSlideAnimationTypes::EaseInOut:
+ m_AnimationKeyframeCount += m_KeyframeParseFloatBuffer.size() / 4;
+ break;
+ }
+
+ ReferenceAnimation(inSlide, *theEntry, inIsActive);
+}
+
+void SParseSlideManager::ReferenceAnimation(SParseSlide &inSlide,
+ const SParseSlideAnimationEntry &inSource,
+ bool inIsActive)
+{
+ TAnimationList &theList =
+ inSlide.m_Animations.insert(eastl::make_pair(inSource.m_InstanceId, TAnimationList()))
+ .first->second;
+ theList.push_back(SParseAnimationRef(inSlide.m_SlideId, inSource.m_InstanceId,
+ inSource.m_PropertyName, &inSource, inIsActive));
+ m_SlideAnimationCount++;
+}
+
+TAnimationList *SParseSlideManager::GetAnimationsForInstance(SParseSlide &inSlide,
+ const char8_t *inInstanceId)
+{
+ SElementData *theElemData = m_ElementManager.FindElementData(inInstanceId);
+ if (theElemData) {
+ TInstanceIdAnimationMap::iterator theAnimations =
+ inSlide.m_Animations.find(theElemData->m_Id);
+ if (theAnimations != inSlide.m_Animations.end())
+ return &theAnimations->second;
+ }
+ return NULL;
+}
+
+SParseSlideActionEntry &SParseSlideManager::GetOrCreateAction(SParseSlide &inSlide,
+ const char8_t *inActionId,
+ qt3ds::QT3DSI32 inActionCount,
+ bool inActive)
+{
+ TStrType theActionId(RegisterId(inActionId));
+ SParseSlideActionEntry theAction(inSlide.m_SlideId, theActionId, inActionCount, inActive);
+ memZero(theAction.m_Actions, sizeof(theAction.m_Actions));
+ TActionList::iterator theIter =
+ eastl::find(inSlide.m_ActionList.begin(), inSlide.m_ActionList.end(), theAction);
+ if (theIter != inSlide.m_ActionList.end())
+ return *theIter;
+ inSlide.m_ActionList.push_back(theAction);
+ m_ActionCount += inActionCount;
+ return inSlide.m_ActionList.back();
+}
+
+SParseSlideActionEntry *SParseSlideManager::FindAction(SParseSlide &inSlide,
+ const char8_t *inActionId)
+{
+ TStrType theActionId(RegisterId(inActionId));
+ SParseSlideActionEntry theAction(inSlide.m_SlideId, theActionId, 0, false);
+ TActionList::iterator theIter =
+ eastl::find(inSlide.m_ActionList.begin(), inSlide.m_ActionList.end(), theAction);
+ if (theIter != inSlide.m_ActionList.end())
+ return &(*theIter);
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inFileName name of UIP file
+ */
+CUIPParserImpl::CUIPParserImpl(const QString &inFileName, IRuntimeMetaData &inMetaData,
+ IInputStreamFactory &inFactory,
+ qt3ds::foundation::IStringTable &inStringTable)
+ : m_MetaData(inMetaData)
+ , m_InputStreamFactory(inFactory)
+ , m_ParseElementManager(inMetaData, inStringTable)
+ , m_ParseSlideManager(inMetaData, m_ParseElementManager)
+{
+ // Setup DOMSerializer and DOMReader to read the file
+ std::shared_ptr<UICDM::IStringTable> theStrTable(inMetaData.GetStringTable());
+ shared_ptr<UICDM::IDOMFactory> theFactory(UICDM::IDOMFactory::CreateDOMFactory(theStrTable));
+ TInputStreamPtr theInStream(inFactory.GetStreamForFile(inFileName));
+ UICDM::SDOMElement *topElement = NULL;
+ if (theInStream)
+ topElement = CDOMSerializer::Read(*theFactory, *theInStream);
+ if (!topElement) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Could not open UIP file: " << inFileName.toLatin1().constData();
+ } else {
+ eastl::pair<std::shared_ptr<IDOMWriter>, std::shared_ptr<IDOMReader>> theWriteReader =
+ IDOMWriter::CreateDOMWriter(theFactory, *topElement, theStrTable);
+ m_DOMWriter = theWriteReader.first;
+ m_DOMReader = theWriteReader.second;
+ if (!AreEqual(m_DOMReader->GetNarrowElementName(), "UIP")) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Invalid UIP file: " << inFileName.toLatin1().constData();
+ }
+ }
+
+ // Create Helper class
+ m_ObjectRefHelper = new CUIPParserObjectRefHelper(m_MetaData);
+ m_ActionHelper = new CUIPParserActionHelper(this, m_ObjectRefHelper, m_MetaData);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CUIPParserImpl::~CUIPParserImpl()
+{
+ // Delete Helper class
+ delete m_ObjectRefHelper;
+ m_ObjectRefHelper = NULL;
+
+ delete m_ActionHelper;
+ m_ActionHelper = NULL;
+}
+
+//==============================================================================
+/**
+ * Load a presentation from a UIP file.
+ * @param inPresentation presentation written to
+ * @return a flag indicating whether or not we successfully loaded the file
+ */
+BOOL CUIPParserImpl::Load(IPresentation &inPresentation,
+ NVConstDataRef<SElementAttributeReference> inStateReferences,
+ uic::state::debugger::ISceneGraphRuntimeDebugger &debugger)
+{
+ m_CurrentPresentation = &inPresentation;
+ if (!m_DOMReader) {
+ qCCritical(qt3ds::INVALID_PARAMETER) << "CUIPParserImpl::Load, No DOM reader";
+ QT3DS_ASSERT(false);
+ return FALSE;
+ }
+
+ BOOL theLoadResult = m_DOMReader->MoveToFirstChild("Project");
+
+ // Load project settings
+ if (theLoadResult)
+ theLoadResult &= LoadProjectSettings(inPresentation, *m_DOMReader);
+
+ // First, we need to load the classes, because the class information will be stored in metadata
+ if (theLoadResult)
+ theLoadResult &= LoadClasses(inPresentation, *m_DOMReader);
+
+ // Next is to cache the scene graph because we need the id-name information to resolve object
+ // reference
+ m_ObjectRefHelper->CacheGraph(*m_DOMReader, *m_DOMWriter);
+
+ // Next is to cache the required attributes. This will be used to build Element
+ // We also need to cache the actions because we need to know the ActionCount to reserve the
+ // memory
+ {
+ IDOMReader::Scope __graphScope(*m_DOMReader);
+ m_DOMReader->MoveToFirstChild("Graph");
+ CacheGraphRequiredAttributes(*m_DOMReader);
+ }
+
+ {
+ IDOMReader::Scope __logicScope(*m_DOMReader);
+ m_DOMReader->MoveToFirstChild("Logic");
+ {
+
+ IDOMReader::Scope __stateScope(*m_DOMReader);
+ for (BOOL theSuccess = m_DOMReader->MoveToFirstChild("State"); theSuccess;
+ theSuccess = m_DOMReader->MoveToNextSibling("State")) {
+ IDOMReader::Scope __subSlideScope(*m_DOMReader);
+ if (theLoadResult)
+ theLoadResult &= CacheLogicRequiredAttributes(*m_DOMReader);
+ }
+ }
+ }
+
+ // go through all the references and make sure the elements exist and if they do ensure the
+ // attributes are marked as referenced.
+ for (QT3DSU32 idx = 0, end = inStateReferences.size(); idx < end; ++idx) {
+ const SElementAttributeReference &reference = inStateReferences[idx];
+ // All references are absolute, so the start node doesn't really matter.
+ CRegisteredString result = m_ObjectRefHelper->ParseObjectRefId(reference.m_Path, "Scene");
+ if (result.IsValid() == false) {
+ qCCritical(INVALID_OPERATION, "Failed to resolve reference: %s",
+ reference.m_Path.c_str());
+ } else {
+ m_ParseElementManager.MarkAttributeAsReferenced(result.c_str(),
+ reference.m_Attribute.c_str());
+ }
+ }
+
+ if (theLoadResult)
+ CacheClassRequiredAttributes(*m_DOMReader);
+
+ ComputeAndReserveMemory(inPresentation, *m_DOMReader);
+
+ // Now we are ready to load the scene graph
+ if (theLoadResult)
+ theLoadResult &= LoadGraph(inPresentation, *m_DOMReader);
+ if (theLoadResult)
+ theLoadResult &= LoadLogic(inPresentation, *m_DOMReader);
+
+ if (theLoadResult) {
+ // Register all element ids with the debugger
+ eastl::vector<uic::state::debugger::SGElemIdMap> elemMapBuffer;
+ for (TIdElementMap::iterator iter = m_ParseElementManager.m_ElementMap.begin(),
+ end = m_ParseElementManager.m_ElementMap.end();
+ iter != end; ++iter) {
+ const SElementData &theData = iter->second;
+ if (theData.m_Element) {
+ uic::state::debugger::SGElemIdMap mapEntry;
+ mapEntry.m_Elem = theData.m_Element;
+ mapEntry.m_Id = iter->first.c_str();
+ elemMapBuffer.push_back(mapEntry);
+ }
+ }
+ debugger.MapElementIds(&inPresentation,
+ toDataRef(elemMapBuffer.data(), (QT3DSU32)elemMapBuffer.size()));
+ }
+
+ return theLoadResult;
+}
+
+IDOMReader &CUIPParserImpl::GetDOMReader()
+{
+ return *m_DOMReader.get();
+}
+
+//==============================================================================
+/**
+ * Load Project Settings
+ * @param inPresentation presentation written to
+ * @return a flag indicating whether or not we successfully loaded the file
+ */
+BOOL CUIPParserImpl::LoadProjectSettings(IPresentation &inPresentation, IDOMReader &inReader)
+{
+ IDOMReader::Scope __projectSettingsScope(inReader);
+
+ if (inReader.MoveToFirstChild("ProjectSettings")) {
+ SPresentationSize thePresentationSize;
+ qt3ds::QT3DSI32 theWidth, theHeight;
+
+ if (inReader.Att("presentationWidth", theWidth))
+ thePresentationSize.m_Width = static_cast<UINT16>(theWidth);
+ if (inReader.Att("presentationHeight", theHeight))
+ thePresentationSize.m_Height = static_cast<UINT16>(theHeight);
+ thePresentationSize.m_ScaleMode = SCALEMODE_EXACT; // ScaleMode is always EXACT
+
+ inPresentation.SetSize(thePresentationSize);
+
+ return true;
+ } else
+ return false;
+}
+
+BOOL CUIPParserImpl::LoadClasses(IPresentation & /*inPresentation*/, IDOMReader &inReader)
+{
+ IDOMReader::Scope __classesScope(inReader);
+
+ if (inReader.MoveToFirstChild("Classes")) {
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ const char *theSourcePath;
+ const char *theId;
+ const char *theName;
+ // Read the sourcepath and id
+ if (inReader.Att("sourcepath", theSourcePath) && inReader.Att("id", theId)) {
+ // Read the name
+ if (!inReader.Att("name", theName))
+ theName = theId;
+
+ bool theLoadFlag = false;
+ QString theFullPath(theSourcePath);
+
+ if (theFullPath.endsWith(".lua")) {
+ // Load the lua file
+ theLoadFlag = m_MetaData.LoadLuaFile(inReader.GetNarrowElementName(), theId,
+ theName, theFullPath.toUtf8().data());
+
+ if (theLoadFlag)
+ m_IdScriptMap[theId] = theSourcePath;
+ } else if (theFullPath.endsWith(".qml")) {
+ theLoadFlag = m_MetaData.LoadScriptFile(inReader.GetNarrowElementName(), theId,
+ theName, theFullPath.toUtf8().data());
+ if (theLoadFlag)
+ m_IdScriptMap[theId] = theSourcePath;
+ } else if (theFullPath.endsWith(".effect")) {
+ theLoadFlag = m_MetaData.LoadEffectXMLFile(inReader.GetNarrowElementName(),
+ theId, theName,
+ theFullPath.toUtf8().data());
+ } else if (theFullPath.endsWith(".material")) {
+ theLoadFlag = m_MetaData.LoadMaterialXMLFile(
+ inReader.GetNarrowElementName(), theId, theName,
+ theFullPath.toUtf8().data());
+ } else if (theFullPath.endsWith(".plugin")) {
+ theLoadFlag = m_MetaData.LoadPluginXMLFile(inReader.GetNarrowElementName(),
+ theId, theName,
+ theFullPath.toUtf8().data());
+ }
+
+ if (!theLoadFlag) {
+ // What file is this?!?
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Could not load sourcepath file: "
+ << theFullPath.toLatin1().constData();
+ }
+ }
+ }
+ }
+
+ // Always return true. Failing to load classes should not block the rest of the system.
+ return true;
+}
+
+BOOL CUIPParserImpl::LoadGraph(IPresentation &inPresentation, UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __childScope(inReader);
+
+ m_NumGraphElements = 0;
+ m_NumGraphComponents = 0;
+ m_NumGraphAttributes = 0;
+
+ bool theLoadResult = inReader.MoveToFirstChild("Graph");
+ if (theLoadResult) {
+ theLoadResult &= LoadSceneGraph(inPresentation, inReader);
+ if (theLoadResult)
+ PatchSceneElementRef();
+ }
+
+ return theLoadResult;
+}
+
+inline RuntimeVector3 Convert(const QT3DSVec3 &input)
+{
+ return RuntimeVector3(input.x, input.y, input.z);
+}
+using uic::runtime::element::SPropertyDesc;
+using uic::runtime::element::TPropertyDescAndValue;
+
+void CUIPParserImpl::GetMetaAttribute(IPresentation &inPresentation,
+ TPropertyDescAndValueList &outDescList, TStrType inType,
+ TStrType inName, TStrType inClassId,
+ CRegisteredString *inAttStrNames)
+{
+ ERuntimeDataModelDataType thePropertyType =
+ m_MetaData.GetPropertyType(inType, inName, inClassId);
+
+ // TODO: Handle all other types
+ switch (thePropertyType) {
+ case ERuntimeDataModelDataTypeFloat:
+ AddFloatAttribute(outDescList, inAttStrNames[0],
+ m_MetaData.GetPropertyValueFloat(inType, inName, inClassId));
+ break;
+ case ERuntimeDataModelDataTypeFloat2: {
+ RuntimeVector3 theVector3 =
+ Convert(m_MetaData.GetPropertyValueVector2(inType, inName, inClassId));
+ SFloat2 theValue(theVector3.m_X, theVector3.m_Y);
+ AddFloat2Attribute(outDescList, inAttStrNames, theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ RuntimeVector3 theVector3 =
+ Convert(m_MetaData.GetPropertyValueVector3(inType, inName, inClassId));
+ SFloat3 theValue(theVector3.m_X, theVector3.m_Y, theVector3.m_Z);
+ ERuntimeAdditionalMetaDataType theAdditionalType =
+ m_MetaData.GetAdditionalType(inType, inName, inClassId);
+ AddFloat3Attribute(outDescList, theAdditionalType, inAttStrNames, theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeLong:
+ AddLongAttribute(outDescList, inAttStrNames[0],
+ m_MetaData.GetPropertyValueLong(inType, inName, inClassId));
+ break;
+ case ERuntimeDataModelDataTypeString: {
+ Option<eastl::string> theRuntimeStr =
+ m_MetaData.GetPropertyValueString(inType, inName, inClassId);
+ if (theRuntimeStr.hasValue())
+ AddStringAttribute(inPresentation, outDescList, inAttStrNames[0],
+ theRuntimeStr->c_str());
+ else
+ AddStringAttribute(inPresentation, outDescList, inAttStrNames[0], "");
+ } break;
+ case ERuntimeDataModelDataTypeBool:
+ AddBoolAttribute(outDescList, inAttStrNames[0],
+ m_MetaData.GetPropertyValueBool(inType, inName, inClassId));
+ break;
+ case ERuntimeDataModelDataTypeLong4:
+ AddElementRefAttribute(outDescList, inAttStrNames[0], NULL);
+ break;
+ case ERuntimeDataModelDataTypeObjectRef: {
+ // Object ref is converted to string path
+ eastl::string theRuntimeStr =
+ m_MetaData.GetPropertyValueObjectRef(inType, inName, inClassId);
+ eastl::string theObjectRef = m_ObjectRefHelper->BuildReferenceString(theRuntimeStr);
+ AddStringAttribute(inPresentation, outDescList, inAttStrNames[0], theObjectRef.c_str());
+ break;
+ }
+ default:
+ QT3DS_ASSERT(false);
+ }
+}
+
+void CUIPParserImpl::AddFloatAttribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, float &inValue)
+{
+ UVariant theValue;
+ theValue.m_FLOAT = inValue;
+ outDescList.push_back(
+ eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_FLOAT), theValue));
+}
+
+void CUIPParserImpl::AddLongAttribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, qt3ds::QT3DSI32 &inValue)
+{
+ UVariant theValue;
+ theValue.m_INT32 = inValue;
+ outDescList.push_back(
+ eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_INT32), theValue));
+}
+
+void CUIPParserImpl::AddBoolAttribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, bool &inValue)
+{
+ UVariant theValue;
+ theValue.m_INT32 = inValue;
+ outDescList.push_back(
+ eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_BOOL), theValue));
+}
+
+void CUIPParserImpl::AddFloat2Attribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString *inAttStrNames, SFloat2 &inValue)
+{
+ for (long theIndex = 0; theIndex < 2; ++theIndex) {
+ UVariant theValue;
+ theValue.m_FLOAT = inValue[theIndex];
+ outDescList.push_back(eastl::make_pair(
+ SPropertyDesc(inAttStrNames[theIndex], ATTRIBUTETYPE_FLOAT), theValue));
+ }
+}
+
+void CUIPParserImpl::AddFloat3Attribute(TPropertyDescAndValueList &outDescList,
+ ERuntimeAdditionalMetaDataType inAdditionalType,
+ CRegisteredString *inAttStrNames, SFloat3 &inValue)
+{
+ for (long theIndex = 0; theIndex < 3; ++theIndex) {
+ float theValue = inValue[theIndex];
+ if (inAdditionalType == ERuntimeAdditionalMetaDataTypeRotation)
+ TORAD(theValue);
+ UVariant theVarValue;
+ theVarValue.m_FLOAT = theValue;
+ outDescList.push_back(eastl::make_pair(
+ SPropertyDesc(inAttStrNames[theIndex], ATTRIBUTETYPE_FLOAT), theVarValue));
+ }
+}
+
+void CUIPParserImpl::AddStringAttribute(IPresentation &inPresentation,
+ TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, const char *inValue)
+{
+ qt3ds::foundation::CStringHandle theString = inPresentation.GetStringTable().GetHandle(inValue);
+ UVariant theValue;
+ theValue.m_StringHandle = theString.handle();
+ outDescList.push_back(
+ eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_STRING), theValue));
+ if (CHash::HashAttribute(inAttStrName.c_str()) == Q3DStudio::ATTRIBUTE_SOURCEPATH && inValue
+ && *inValue)
+ AddSourcePath(inValue);
+}
+
+void CUIPParserImpl::AddElementRefAttribute(TPropertyDescAndValueList &outDescList,
+ CRegisteredString inAttStrName, SElement *inElement)
+{
+ UVariant theValue;
+ if (inElement) {
+ theValue.m_ElementHandle = inElement->GetHandle();
+ QT3DS_ASSERT(theValue.m_ElementHandle);
+ } else
+ theValue.m_ElementHandle = 0;
+ outDescList.push_back(
+ eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_ELEMENTREF), theValue));
+}
+
+void CUIPParserImpl::GetAttributeList(IPresentation &inPresentation,
+ TPropertyDescAndValueList &outDescList, TStrType inType,
+ TStrType inName, TStrType inClassId, const char *inValue,
+ CRegisteredString *inPropNameStrs)
+{
+ ERuntimeDataModelDataType theDataType = m_MetaData.GetPropertyType(inType, inName, inClassId);
+ ERuntimeAdditionalMetaDataType theAdditionalType =
+ m_MetaData.GetAdditionalType(inType, inName, inClassId);
+
+ GetAttributeList(inPresentation, outDescList, theDataType, theAdditionalType, inName, inValue,
+ inPropNameStrs);
+}
+
+void CUIPParserImpl::GetAttributeList(IPresentation &inPresentation,
+ TPropertyDescAndValueList &outDescList,
+ ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType, const char *,
+ const char *inValue, CRegisteredString *inPropNameStrs)
+{
+ // Create a destructible value
+ m_ValueBuffer.clear();
+ m_TempBuffer.clear();
+ m_ValueBuffer.write(inValue, (QT3DSU32)strlen(inValue) + 1);
+ WCharTReader theReader((char8_t *)m_ValueBuffer.begin(), m_TempBuffer,
+ *m_DOMReader->GetStringTable());
+
+ // TODO: Handle all other types
+ // Note that the default value should be consistent with the SetDefault method of
+ // TDataModelValue
+ switch (inDataType) {
+ case ERuntimeDataModelDataTypeLong: {
+ qt3ds::QT3DSI32 theValue = 0;
+ if (!IsTrivial(inValue))
+ theReader.Read(theValue);
+ AddLongAttribute(outDescList, inPropNameStrs[0], theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat: {
+ float theValue = 0;
+ if (!IsTrivial(inValue))
+ theReader.Read(theValue);
+ AddFloatAttribute(outDescList, inPropNameStrs[0], theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ SFloat2 theValue(0);
+ if (!IsTrivial(inValue))
+ theReader.ReadRef(NVDataRef<QT3DSF32>(&theValue[0], 2));
+ AddFloat2Attribute(outDescList, inPropNameStrs, theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ SFloat3 theValue(0);
+ if (!IsTrivial(inValue))
+ theReader.ReadRef(NVDataRef<QT3DSF32>(&theValue[0], 3));
+ AddFloat3Attribute(outDescList, inAdditionalType, inPropNameStrs, theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeBool: {
+ bool theValue = false;
+ if (!IsTrivial(inValue))
+ theReader.Read(theValue);
+ AddBoolAttribute(outDescList, inPropNameStrs[0], theValue);
+ break;
+ }
+ case ERuntimeDataModelDataTypeStringRef:
+ case ERuntimeDataModelDataTypeString: {
+ const char *theDataPtr = "";
+ if (!IsTrivial(inValue))
+ theReader.Read(theDataPtr);
+ AddStringAttribute(inPresentation, outDescList, inPropNameStrs[0], theDataPtr);
+ break;
+ }
+ case ERuntimeDataModelDataTypeLong4: {
+ const char *theDataPtr = NULL;
+ if (!IsTrivial(inValue))
+ theReader.Read(theDataPtr);
+ SElement *theElementData = GetElement(theDataPtr);
+ AddElementRefAttribute(outDescList, inPropNameStrs[0], theElementData);
+ break;
+ }
+ case ERuntimeDataModelDataTypeObjectRef: {
+ // Object ref is converted to string path
+ const char *theDataPtr = NULL;
+ if (!IsTrivial(inValue))
+ theReader.Read(theDataPtr);
+ if (theDataPtr) {
+ eastl::string theObjectRef = m_ObjectRefHelper->BuildReferenceString(theDataPtr);
+ AddStringAttribute(inPresentation, outDescList, inPropNameStrs[0],
+ theObjectRef.c_str());
+ }
+ break;
+ }
+ default:
+ QT3DS_ASSERT(false);
+ }
+}
+
+//==============================================================================
+/**
+ * Looks up the EElementType from the asset type.
+ */
+EElementType GetElementType(const char *inType)
+{
+ if (AreEqual(inType, "Scene") || AreEqual(inType, "Layer") || AreEqual(inType, "Group")
+ || AreEqual(inType, "Model") || AreEqual(inType, "Path"))
+ return ELEMENTTYPE_NODE;
+
+ else if (AreEqual(inType, "Camera"))
+ return ELEMENTTYPE_CAMERA;
+
+ else if (AreEqual(inType, "Light"))
+ return ELEMENTTYPE_LIGHT;
+
+ else if (AreEqual(inType, "Component"))
+ return ELEMENTTYPE_COMPONENT;
+
+ else if (AreEqual(inType, "Material"))
+ return ELEMENTTYPE_MATERIAL;
+
+ else if (AreEqual(inType, "Image"))
+ return ELEMENTTYPE_TEXTURE;
+
+ else if (AreEqual(inType, "Behavior"))
+ return ELEMENTTYPE_BEHAVIOR;
+
+ else if (AreEqual(inType, "Text"))
+ return ELEMENTTYPE_TEXT;
+
+ else if (AreEqual(inType, "PathAnchorPoint"))
+ return ELEMENTTYPE_PATHANCHORPOINT;
+
+ else if (AreEqual(inType, "SubPath"))
+ return ELEMENTTYPE_SUBPATH;
+
+ else
+ return ELEMENTTYPE_UNKNOWN;
+}
+
+//==============================================================================
+/**
+ * Build out the graph.
+ * @param inPresentation presentation written to
+ * @return a flag indicating whether or not we successfully loaded the file
+ */
+BOOL CUIPParserImpl::LoadSceneGraph(IPresentation &inPresentation, IDOMReader &inReader,
+ uic::runtime::element::SElement *inNewStyleParent)
+{
+ IDOMReader::Scope __childScope(inReader);
+ IScriptBridge *theScriptBridge = inPresentation.GetScriptBridge();
+ IScriptBridge *theScriptBridgeQml = inPresentation.GetScriptBridgeQml();
+
+ eastl::string theFileString;
+ uic::runtime::IApplication &theApp(inPresentation.GetApplication());
+ uic::runtime::IElementAllocator &theElemAllocator(theApp.GetElementAllocator());
+ TPropertyDescAndValueList theProperties;
+ using uic::runtime::element::SPropertyDesc;
+ qt3ds::foundation::IStringTable &theStringTable(inPresentation.GetStringTable());
+ // build out the graph.
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ theProperties.clear();
+ const char *theId;
+ inReader.Att("id", theId);
+ const char *theClass;
+ inReader.Att("class", theClass);
+ const char *theType(inReader.GetNarrowElementName());
+ eastl::string theName(m_ObjectRefHelper->GetName(theId).c_str());
+ // Get default end time from metadata
+ UINT32 theLoopTime = 0;
+ bool isComponent = false;
+ bool isBehavior = false;
+
+ // Create SElement
+ if (AreEqual(theType, "Scene") || AreEqual(theType, "Component")) {
+ // TDataModelValue theValue;
+ theLoopTime = m_MetaData.GetPropertyValueLong(m_MetaData.Register(theType),
+ m_MetaData.Register("endtime"));
+ Q3DStudio_ASSERT(theLoopTime != 0); // Something is wrong here
+ isComponent = true;
+ } else {
+ if (AreEqual(theType, "Behavior") && !IsTrivial(theClass)) {
+ // Find the sourcepath and load the script
+ ++theClass; // remove the '#'
+ TIdSourcePathMap::iterator theSourcePathIter = m_IdScriptMap.find(theClass);
+ if (theSourcePathIter != m_IdScriptMap.end()) {
+ theFileString.assign(theSourcePathIter->second);
+
+// For non-windows platforms, we need to reverse the slashes
+#ifndef EA_PLATFORM_WINDOWS
+ for (eastl::string::size_type thePos = theFileString.find('\\');
+ thePos != eastl::string::npos;
+ thePos = theFileString.find('\\', thePos + 1)) {
+ theFileString.replace(thePos, 1, 1, '/');
+ }
+#endif
+ isBehavior = true;
+ UVariant theValue;
+ theValue.m_StringHandle =
+ inPresentation.GetStringTable().GetHandle(theFileString.c_str());
+ theProperties.push_back(eastl::make_pair(
+ SPropertyDesc(theStringTable.RegisterStr("behaviorscripts"),
+ ATTRIBUTETYPE_STRING),
+ theValue));
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Could not load Behavior script: " << theClass;
+ }
+ }
+ }
+
+ SElementData &theElementData =
+ m_ParseElementManager.GetOrCreateElementData(theId, theType, theClass);
+
+ const char8_t *theSourcePath;
+ if (inReader.UnregisteredAtt("sourcepath", theSourcePath))
+ AddSourcePath(theSourcePath);
+
+ TAttrMap &theList = theElementData.m_PropertyMap;
+
+ const char *theAttribute;
+ for (TAttrMap::iterator theIter = theList.begin(), theMapEnd = theList.end();
+ theIter != theMapEnd; ++theIter) {
+ if (theIter->second.m_ElementFlag) {
+ // Parse the property value from uip, this will overwrite the default value
+ const TStrType &thePropertyName(theIter->first);
+ CRegisteredString *thePropertyNames = theIter->second.m_PropertyNames;
+ size_t theListSize = theProperties.size();
+ if (inReader.Att(thePropertyName.c_str(), theAttribute)) {
+ ERuntimeDataModelDataType theDataType = m_MetaData.GetPropertyType(
+ theElementData.m_Type, thePropertyName, theElementData.m_Class);
+ if (theDataType == ERuntimeDataModelDataTypeLong4) {
+ AddElementRefToPatch(theProperties, theElementData, thePropertyName.c_str(),
+ theAttribute);
+ } else
+ GetAttributeList(inPresentation, theProperties, theElementData.m_Type,
+ thePropertyName, theElementData.m_Class, theAttribute,
+ thePropertyNames);
+ } else {
+ GetMetaAttribute(inPresentation, theProperties, theElementData.m_Type,
+ thePropertyName, theElementData.m_Class, thePropertyNames);
+ }
+ size_t theNumAtts = theProperties.size() - theListSize;
+ QT3DS_ASSERT(theNumAtts == (size_t)theIter->second.m_Arity);
+ (void)theNumAtts;
+ }
+ }
+ uic::runtime::element::SElement &theNewElem = theElemAllocator.CreateElement(
+ theStringTable.RegisterStr(theName.c_str()), theStringTable.RegisterStr(theType),
+ theStringTable.RegisterStr(theElementData.m_Class.c_str()),
+ toConstDataRef(theProperties.data(), (QT3DSU32)theProperties.size()), &inPresentation,
+ inNewStyleParent, isComponent);
+ theElementData.m_Element = &theNewElem;
+
+ if (inPresentation.GetRoot() == NULL)
+ inPresentation.SetRoot(theNewElem);
+
+ eastl::string thePath;
+ // build out the full path to the element for debugging
+ for (CUIPParserObjectRefHelper::SGraphNode *theNode =
+ this->m_ObjectRefHelper->GetNode(theId);
+ theNode; theNode = theNode->m_Parent) {
+ if (thePath.length())
+ thePath.insert(0, ".");
+ thePath.insert(0, theNode->m_Name);
+ }
+ if (thePath.size())
+ theNewElem.m_Path = m_ParseElementManager.m_StringTable.RegisterStr(thePath.c_str());
+
+ if (isBehavior) {
+ if (theFileString.find(".lua") != eastl::string::npos) {
+ theScriptBridge->LoadScript(&inPresentation, &theNewElem, theFileString.c_str());
+ } else {
+ theScriptBridgeQml->LoadScript(&inPresentation, &theNewElem,
+ theFileString.c_str());
+ }
+ }
+ LoadSceneGraph(inPresentation, inReader, &theNewElem);
+ }
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * This method will parse through the graph sections to cache those attributes that
+ * should never be optimized
+ */
+void CUIPParserImpl::CacheGraphRequiredAttributes(UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __childScope(inReader);
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ const char *theId;
+ inReader.Att("id", theId);
+ const char *theType(inReader.GetNarrowElementName());
+ const char *theClass = "";
+ inReader.Att("class", theClass);
+ SElementData &theData =
+ m_ParseElementManager.GetOrCreateElementData(theId, theType, theClass);
+ // name and sourcepath are never optimized out.
+ m_ParseElementManager.MarkAttributeAsReferenced(theData, "name");
+ // not everything needs to be in the time graph.
+ if (AreEqual(theType, "Scene") == false && AreEqual(theType, "Material") == false
+ && AreEqual(theType, "CustomMaterial") == false && AreEqual(theType, "Image") == false
+ && AreEqual(theType, "RenderPlugin") == false) {
+ SElementPropertyInfo *theProp =
+ m_ParseElementManager.GetOrCreateProperty(theData, "starttime");
+ theProp->m_SlideFlag = true;
+ theProp->m_SlideForceFlag = true;
+ theProp->m_ElementFlag = true;
+ theProp = m_ParseElementManager.GetOrCreateProperty(theData, "endtime");
+ theProp->m_SlideFlag = true;
+ theProp->m_SlideForceFlag = true;
+ theProp->m_ElementFlag = true;
+ }
+
+ if (AreEqual(theType, "Text")) {
+ m_ParseElementManager.MarkAttributeAsReferenced(theData, "textstring");
+ }
+
+ // Behaviors need all attributes possible on the object on them all the time.
+ if (AreEqual(theType, "Behavior") || AreEqual(theType, "RenderPlugin")) {
+ m_ParseElementManager.MarkAllAttributesAsReferenced(theData);
+ }
+
+ // Recursive
+ CacheGraphRequiredAttributes(inReader);
+ }
+}
+
+//==============================================================================
+/**
+ * This method will parse through the logic sections to cache those attributes that
+ * will be changed and thus needs to be at the SElement
+ */
+BOOL CUIPParserImpl::CacheLogicRequiredAttributes(UICDM::IDOMReader &inReader,
+ qt3ds::QT3DSI32 inSlideIndex,
+ SParseSlide *inParentSlide)
+{
+ IDOMReader::Scope __stateScope(inReader);
+ eastl::string theSlideId = GetSlideId(inReader);
+ SParseSlide &theSlide = m_ParseSlideManager.GetOrCreateSlide(theSlideId.c_str(), inSlideIndex);
+ eastl::hash_set<TStrType> theCommandInstances;
+ QT3DSU32 slideAnimActions = 0;
+
+ {
+ IDOMReader::Scope __commandLoopScope(inReader);
+ for (BOOL theSuccess = inReader.MoveToFirstChild(); theSuccess;
+ theSuccess = inReader.MoveToNextSibling()) {
+ IDOMReader::Scope __commandScope(inReader);
+ if (AreEqual(inReader.GetNarrowElementName(), "Add")
+ || AreEqual(inReader.GetNarrowElementName(), "Set")) {
+ bool isSet = AreEqual(inReader.GetNarrowElementName(), "Set");
+ const char *theRef;
+ if (inReader.Att("ref", theRef)) {
+ theRef++; // remove the '#'
+
+ // Set/Add command applied to an element *not* in the scene graph.
+ SElementData *theData = m_ParseElementManager.FindElementData(theRef);
+ if (theData == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ theCommandInstances.insert(theData->m_Id);
+ if (isSet) {
+ for (eastl::pair<const char *, const char *> theAtt =
+ inReader.GetNarrowFirstAttribute();
+ !IsTrivial(theAtt.first); theAtt = inReader.GetNarrowNextAttribute()) {
+ if (AreEqual(theAtt.first, "ref") || AreEqual(theAtt.first, "shy"))
+ continue;
+
+ SElementPropertyInfo *theProperty =
+ m_ParseElementManager.GetOrCreateProperty(*theData, theAtt.first);
+ // This property exists on both the elements and the slides.
+ if (theProperty) {
+ theProperty->m_ElementFlag = true;
+ theProperty->m_SlideFlag = true;
+ }
+ }
+ // Run through parent animations and forward them *if* this set command does
+ // not have this property present.
+ if (inParentSlide) {
+ TAnimationList *theAnimations =
+ m_ParseSlideManager.GetAnimationsForInstance(*inParentSlide,
+ theData->m_Id);
+ if (theAnimations != NULL) {
+ for (QT3DSU32 animIdx = 0, animEnd = theAnimations->size();
+ animIdx < animEnd; ++animIdx) {
+ SParseAnimationRef &theEntry((*theAnimations)[animIdx]);
+ const char8_t *propValue = "";
+ SElementPropertyInfo *thePropInfo =
+ m_ParseElementManager.FindProperty(
+ *theData, theEntry.m_PropertyName.c_str());
+ if (!thePropInfo) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ // If the attribute doesn't exist in the command, then we
+ // forward the animation to here
+ if (inReader.Att(thePropInfo->m_PropertyName, propValue)
+ == false) {
+ ++slideAnimActions;
+ m_ParseSlideManager.ReferenceAnimation(
+ theSlide, *theEntry.m_Animation, true);
+ }
+ }
+ }
+ }
+ }
+
+ // find all the animations, regardless of add or set.
+ {
+ IDOMReader::Scope __animationScope(inReader);
+ for (BOOL theAnimScopeSuccess = inReader.MoveToFirstChild("AnimationTrack");
+ theAnimScopeSuccess;
+ theAnimScopeSuccess = inReader.MoveToNextSibling("AnimationTrack")) {
+ const char *theProperty;
+ const char8_t *theValue = "";
+ inReader.Value(theValue);
+ if (theValue != NULL && *theValue
+ && inReader.UnregisteredAtt("property", theProperty)) {
+ m_ParseElementManager.MarkAttributeAsReferenced(*theData,
+ theProperty);
+ // PreParse the animation at this point. This allows us to easily
+ // count animations.
+ bool isDynamic = false;
+ inReader.Att("dynamic", isDynamic);
+ SParseSlideAnimationTypes::Enum theParseType =
+ SParseSlideAnimationTypes::EaseInOut;
+ const char8_t *animType;
+ if (inReader.Att("type", animType)) {
+ if (AreEqual(animType, "EaseInOut")) {
+ } else if (AreEqual(animType, "Bezier"))
+ theParseType = SParseSlideAnimationTypes::Bezier;
+ else if (AreEqual(animType, "Linear"))
+ theParseType = SParseSlideAnimationTypes::Linear;
+ else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ ++slideAnimActions;
+ m_ParseSlideManager.SetAnimationData(
+ theSlide, theData->m_Id, theProperty, theValue, theParseType,
+ isDynamic, inSlideIndex != 0);
+ }
+ }
+ }
+
+ // find all the actions
+ {
+ IDOMReader::Scope __actionScope(inReader);
+ for (BOOL theActionScopeSuccess = inReader.MoveToFirstChild("Action");
+ theActionScopeSuccess;
+ theActionScopeSuccess = inReader.MoveToNextSibling("Action")) {
+ const char8_t *theActionId;
+ // Don't cache reference actions
+ if (inReader.Att("id", theActionId)) {
+ m_ActionHelper->CacheAction(inReader, theData->m_Id);
+ bool active = true;
+ inReader.Att("eyeball", active);
+ ++slideAnimActions;
+ m_ParseSlideManager.GetOrCreateAction(
+ theSlide, theActionId,
+ m_ActionHelper->GetActionCount(theActionId), active);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Now forward all animations from the parent slide that are for instances that we haven't
+ // covered at all on this slide.
+ if (inParentSlide) {
+ for (TInstanceIdAnimationMap::iterator theIter = inParentSlide->m_Animations.begin(),
+ theEnd = inParentSlide->m_Animations.end();
+ theIter != theEnd; ++theIter) {
+ if (theCommandInstances.find(theIter->first) == theCommandInstances.end()) {
+ TAnimationList &theList(theIter->second);
+ for (QT3DSU32 animIdx = 0, animEnd = theList.size(); animIdx < animEnd; ++animIdx) {
+ SParseAnimationRef &theEntry(theList[animIdx]);
+ m_ParseSlideManager.ReferenceAnimation(theSlide, *theEntry.m_Animation, true);
+ ++slideAnimActions;
+ }
+ }
+ }
+ // Forward action creation onto this slide.
+ for (TActionList::iterator theIter = inParentSlide->m_ActionList.begin(),
+ theEnd = inParentSlide->m_ActionList.end();
+ theIter != theEnd; ++theIter) {
+ SParseSlideActionEntry &theAction(*theIter);
+ m_ParseSlideManager.GetOrCreateAction(theSlide, theAction.m_ActionId,
+ theAction.m_ActionCount, theAction.m_Active);
+ ++slideAnimActions;
+ }
+ }
+
+ eastl::vector<eastl::string> theChildSlideIds;
+
+ for (BOOL theSuccess = inReader.MoveToFirstChild("State"); theSuccess;
+ theSuccess = inReader.MoveToNextSibling("State")) {
+ IDOMReader::Scope __subSlideScope(inReader);
+ ++inSlideIndex;
+ theChildSlideIds.push_back(GetSlideId(inReader));
+ CacheLogicRequiredAttributes(inReader, inSlideIndex, &theSlide);
+ }
+
+ // Pull all child animations up into this slide, but set them to deactivated.
+ for (QT3DSU32 childSlideIdx = 0, childSlideEnd = theChildSlideIds.size();
+ childSlideIdx < childSlideEnd; ++childSlideIdx) {
+ SParseSlide *theChildSlide =
+ m_ParseSlideManager.FindSlide(theChildSlideIds[childSlideIdx].c_str());
+ if (theChildSlide) {
+ // Add animations that did not original in this slide to this slide.
+ for (TInstanceIdAnimationMap::iterator theIter = theChildSlide->m_Animations.begin(),
+ theEnd = theChildSlide->m_Animations.end();
+ theIter != theEnd; ++theIter) {
+ TAnimationList &theList(theIter->second);
+ for (QT3DSU32 animIdx = 0, animEnd = theList.size(); animIdx < animEnd; ++animIdx) {
+ SParseAnimationRef &theEntry(theList[animIdx]);
+ if (theEntry.m_Animation
+ && theEntry.m_Animation->m_SlideId != theSlide.m_SlideId) {
+ m_ParseSlideManager.ReferenceAnimation(theSlide, *theEntry.m_Animation,
+ false);
+ ++slideAnimActions;
+ }
+ }
+ }
+ for (TActionList::iterator theIter = theChildSlide->m_ActionList.begin(),
+ theEnd = theChildSlide->m_ActionList.end();
+ theIter != theEnd; ++theIter) {
+ SParseSlideActionEntry &theEntry(*theIter);
+ // This deactivates actions that may be active on another slide.
+ m_ParseSlideManager.GetOrCreateAction(theSlide, theEntry.m_ActionId,
+ theEntry.m_ActionCount, false);
+ ++slideAnimActions;
+ }
+ }
+ }
+ // qt3ds::NVFoundationBase& fnd(
+ // m_CurrentPresentation->GetApplication().GetRuntimeFactory().GetFoundation() );
+ // fnd.error( QT3DS_TRACE, "Loading slide %s, %d anim actions", theSlideId.c_str(),
+ // slideAnimActions );
+
+ return TRUE;
+}
+
+void CUIPParserImpl::CacheClassRequiredAttributes(UICDM::IDOMReader &inReader)
+{
+ {
+ // First, we parse Graph section to cache custom attributes specified by the class
+ IDOMReader::Scope __graphScope(inReader);
+ inReader.MoveToFirstChild("Graph");
+ CacheClassSceneAttributes(inReader);
+ }
+ if (!m_IdClassMap.empty()) {
+ // Next, we parse Logic section to update the references
+ IDOMReader::Scope __logicScope(inReader);
+ inReader.MoveToFirstChild("Logic");
+ CacheClassStateAttributes(inReader);
+ }
+}
+
+void CUIPParserImpl::CacheClassSceneAttributes(IDOMReader &inReader)
+{
+ IDOMReader::Scope __childScope(inReader);
+ // build out the graph.
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ const char *theId;
+ const char *theClass;
+ if (inReader.Att("class", theClass) && inReader.Att("id", theId)) {
+ // Add to id-class map
+ m_IdClassMap[theId] = theClass;
+ }
+ CacheClassSceneAttributes(inReader);
+ }
+}
+
+void CUIPParserImpl::CacheClassStateAttributes(IDOMReader &inReader)
+{
+ IDOMReader::Scope __childScope(inReader);
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "State"))
+ CacheClassStateAttributes(inReader);
+ else if (AreEqual(inReader.GetNarrowElementName(), "Add")
+ || AreEqual(inReader.GetNarrowElementName(), "Set")) {
+ const char *theRef;
+ if (inReader.Att("ref", theRef)) {
+ theRef++; // remove the '#'
+
+ // Find the class, if any
+ TIdClassMap::iterator theIter = m_IdClassMap.find(theRef);
+ if (theIter != m_IdClassMap.end()) {
+ // Get References of the class
+ eastl::vector<eastl::string> theReferences;
+ m_MetaData.GetReferences("", theReferences, theIter->second.c_str());
+ if (!theReferences.empty()) {
+ // Cache the references
+ m_ObjectRefHelper->MarkAllReferencedAttributes(
+ theRef, theReferences, inReader, m_ParseElementManager);
+ }
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * For ElementRef type, there could be times where the SElement isn't created yet, thus
+ * this method cache those Long4 type and add an empty attribute into the SElement
+ */
+void CUIPParserImpl::AddElementRefToPatch(TPropertyDescAndValueList &outDescList,
+ SElementData &inElement, const char *inName,
+ const char *inValue)
+{
+ SElementRefCache theElementRefData;
+ theElementRefData.m_Element = &inElement;
+ theElementRefData.m_Name = inName;
+ theElementRefData.m_Value = inValue;
+ m_ElementRefCache.push_back(theElementRefData);
+
+ UVariant theValue;
+ theValue.m_ElementHandle = 0;
+ outDescList.push_back(
+ eastl::make_pair(SPropertyDesc(m_ParseElementManager.m_StringTable.RegisterStr(inName),
+ ATTRIBUTETYPE_ELEMENTREF),
+ theValue));
+}
+
+//==============================================================================
+/**
+ * For those Long4 type that was not loaded correctly, go through all of them and
+ * fix up the ElementRef
+ */
+void CUIPParserImpl::PatchSceneElementRef()
+{
+ for (eastl::vector<SElementRefCache>::iterator theIter = m_ElementRefCache.begin();
+ theIter != m_ElementRefCache.end(); ++theIter) {
+ SElementRefCache &theCache = *theIter;
+
+ SElementData *theElementData = GetElementData(theCache.m_Value.c_str());
+
+ SElement *theElement = theCache.m_Element->m_Element;
+ UVariant *theValue = theElement->FindPropertyValue(
+ m_ParseElementManager.RegisterStr(theCache.m_Value.c_str()));
+ if (theValue) {
+ theValue->m_ElementHandle = 0;
+ if (theElementData->m_Element) {
+ theValue->m_ElementHandle = theElementData->m_Element->GetHandle();
+ QT3DS_ASSERT(theValue->m_ElementHandle);
+ }
+ }
+ }
+}
+
+BOOL CUIPParserImpl::LoadLogic(IPresentation &inPresentation, UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __logicScope(inReader);
+
+ m_NumSlides = 0;
+ m_NumSlideElements = 0;
+ m_NumSlideAttributes = 0;
+ m_NumAnimationTracks = 0;
+ m_NumAnimationKeys = 0;
+ m_NumSlideAnimations = 0;
+ m_NumSlideActions = 0;
+
+ bool theStatus = true;
+
+ // Build all of the animation objects that we have tallied up.
+ for (QT3DSU32 animIdx = 0, animEnd = m_ParseSlideManager.m_Animations.size(); animIdx < animEnd;
+ ++animIdx) {
+ SParseSlideAnimationEntry &theEntry = *m_ParseSlideManager.m_Animations[animIdx];
+ SElementData *theData = m_ParseElementManager.FindElementData(theEntry.m_InstanceId);
+ // Generate valid animation indexes while we are at it.
+ LoadAnimationTrack(inPresentation, *theData, theEntry);
+ }
+
+ if (inReader.MoveToFirstChild("Logic")) {
+
+ // Action
+ m_ActionHelper->BuildActions(inPresentation);
+
+ for (BOOL theSuccess = inReader.MoveToFirstChild("State"); theSuccess;
+ theSuccess = inReader.MoveToNextSibling("State")) {
+ theStatus &= LoadStateGraph(inPresentation, inReader);
+ }
+ }
+
+ return theStatus;
+}
+
+//==============================================================================
+/**
+ * Load the State (Slides)
+ * @param inPresentation presentation written to
+ * @return a flag indicating whether or not we successfully loaded the file
+ */
+BOOL CUIPParserImpl::LoadStateGraph(IPresentation &inPresentation, UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __slideScope(inReader);
+
+ BOOL theStatus = true;
+
+ SElement *theComponent = NULL;
+ const char8_t *theAttribute;
+ if (inReader.UnregisteredAtt("component", theAttribute))
+ theComponent = GetElement(theAttribute);
+ if (theComponent) {
+ INT32 theSlideIndex = 0;
+ LoadState(inPresentation, theComponent, theSlideIndex, inReader);
+
+ for (BOOL theResult = inReader.MoveToFirstChild("State"); theResult;
+ theResult = inReader.MoveToNextSibling("State")) {
+ if (theStatus)
+ theStatus &= LoadState(inPresentation, theComponent, ++theSlideIndex, inReader);
+ }
+ } else {
+ if (theAttribute) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Slide load failure!! Failed to find component: " << theAttribute;
+ } else {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Slide load failure!! Failed to find component.";
+ }
+ }
+
+ return theStatus;
+}
+
+//==============================================================================
+/**
+ * Load the State (Slides)
+ * @param inPresentation presentation written to
+ * @return a flag indicating whether or not we successfully loaded the file
+ */
+BOOL CUIPParserImpl::LoadState(IPresentation &inPresentation, SElement *inComponent,
+ INT32 inSlideIndex, UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __stateScope(inReader);
+
+ BOOL theResult = true;
+ ISlideSystem &theBuilder = inPresentation.GetSlideSystem();
+
+ eastl::string theSlideName = GetSlideName(inReader);
+
+ uic::runtime::SSlidePlayInformation thePlayMode = GetPlayMode(inReader);
+ thePlayMode.m_PlayThroughTo = (QT3DSU8)GetPlayThroughTo(inSlideIndex, inReader);
+ // Setup with the default value from the metadata
+ INT32 theMinTime = m_MetaData.GetPropertyValueLong(m_MetaData.Register("Asset"),
+ m_MetaData.Register("starttime"));
+ INT32 theMaxTime = m_MetaData.GetPropertyValueLong(m_MetaData.Register("Asset"),
+ m_MetaData.Register("endtime"));
+
+ theBuilder.AddSlide(*inComponent, theSlideName.c_str(), thePlayMode.m_PlayMode,
+ thePlayMode.m_Paused, thePlayMode.m_PlayThroughTo, theMinTime, theMaxTime);
+ m_NumSlides++;
+
+ m_SlideElements.clear();
+ m_SlideElements.insert(inComponent);
+
+ BOOL theActiveFlag = (inSlideIndex != 0);
+ theBuilder.AddSlideElement(*inComponent, theActiveFlag);
+ ProcessStateRef(inPresentation, inComponent, inSlideIndex == 0, inReader);
+
+ m_NumSlideElements++;
+
+ theMaxTime = 0;
+ theResult &=
+ LoadSlideElements(inPresentation, inReader, inSlideIndex == 0, inComponent, &theMaxTime);
+ if (theMaxTime != 0)
+ theBuilder.SetSlideMaxTime((QT3DSU32)theMaxTime);
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Process the state information to add all the animations and actions that might be setup
+ */
+BOOL CUIPParserImpl::ProcessStateRef(IPresentation &inPresentation, SElement *inComponent,
+ bool inMaster, UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __stateScope(inReader);
+ eastl::string theSlideId = GetSlideId(inReader);
+ for (BOOL theResult = inReader.MoveToFirstChild("Set"); theResult;
+ theResult = inReader.MoveToNextSibling("Set")) {
+ const char8_t *theElementRef;
+ if (inReader.UnregisteredAtt("ref", theElementRef)
+ && GetElement(theElementRef) == inComponent)
+ ProcessSlideAnimAction(inPresentation, theSlideId, inMaster, inReader);
+ }
+ return TRUE;
+}
+
+void CUIPParserImpl::ComputeAndReserveMemory(IPresentation & /*inPresentation*/,
+ UICDM::IDOMReader &inReader)
+{
+ SGraphSectionCount theGraphSectionCount;
+ SLogicSectionCount theLogicSectionCount;
+ SActionSectionCount theActionSectionCount;
+
+ {
+ IDOMReader::Scope __graphScope(inReader);
+ if (inReader.MoveToFirstChild("Graph"))
+ DoGraphSectionCount(inReader, theGraphSectionCount);
+ }
+ DoLogicSectionCount(inReader, theLogicSectionCount);
+ m_ActionHelper->GetActionSectionCount(theActionSectionCount);
+}
+
+void CUIPParserImpl::DoGraphSectionCount(UICDM::IDOMReader &inReader,
+ SGraphSectionCount &outGraphCounter)
+{
+ IDOMReader::Scope __graphScope(inReader);
+
+ for (bool theResult = inReader.MoveToFirstChild(); theResult;
+ theResult = inReader.MoveToNextSibling()) {
+ const char *theTypeStr(inReader.GetNarrowElementName());
+ if (AreEqual(theTypeStr, "Scene") || AreEqual(theTypeStr, "Component"))
+ outGraphCounter.m_ComponentCount++;
+ else
+ outGraphCounter.m_ElementCount++;
+
+ const char *theIdStr;
+ inReader.Att("id", theIdStr);
+ const char *theClassStr;
+ inReader.Att("class", theClassStr);
+
+ // For Behavior, we are adding a string attribute ATTRIBUTE_BEHAVIORSCRIPTS
+ if (AreEqual(theTypeStr, "Behavior") && !IsTrivial(theClassStr)) {
+ ++theClassStr; // remove the '#'
+ TIdSourcePathMap::iterator theSourcePathIter = m_IdScriptMap.find(theClassStr);
+ if (theSourcePathIter != m_IdScriptMap.end()) {
+ outGraphCounter.m_AttributeCount++;
+ outGraphCounter.m_StringAttrCount++;
+ }
+ }
+ SElementData *theData = m_ParseElementManager.FindElementData(theIdStr);
+
+ if (theData) {
+ TAttrMap &thePropertyMap = theData->m_PropertyMap;
+
+ // TODO: Maybe we should make m_IdAttributesMap only stores those valid attributes and
+ // also those attributes that already converted to Runtime type (e.g. position to
+ // position.x .y .z )
+ // then we can really stop calling all the IsValidAttribute all over the place
+ // and we can simple just use the size of the vector here.
+ for (TAttrMap::iterator theIter = thePropertyMap.begin(), theEnd = thePropertyMap.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->second.m_ElementFlag == false)
+ continue;
+ TStrType thePropertyName(theIter->first);
+ outGraphCounter.m_AttributeCount += theIter->second.m_Arity;
+ if (IsStringType(theIter->second.m_DataType))
+ outGraphCounter.m_StringAttrCount += 1;
+ }
+ }
+
+ DoGraphSectionCount(inReader, outGraphCounter);
+ }
+}
+
+void CUIPParserImpl::DoLogicSectionCount(UICDM::IDOMReader &inReader,
+ SLogicSectionCount &outLogicCounter)
+{
+ IDOMReader::Scope __logicCountScope(inReader);
+
+ if (inReader.MoveToFirstChild("Logic")) {
+ for (bool theResult = inReader.MoveToFirstChild("State"); theResult;
+ theResult = inReader.MoveToNextSibling("State")) {
+ DoStateSectionCount(inReader, 0, outLogicCounter);
+ }
+ }
+}
+
+void CUIPParserImpl::DoStateSectionCount(UICDM::IDOMReader &inReader, Q3DStudio::INT32 inStateIndex,
+ SLogicSectionCount &outLogicCounter)
+{
+ IDOMReader::Scope __slideCountScope(inReader);
+
+ outLogicCounter.m_SlideCount++;
+
+ INT32 theChildSlideCount = inReader.CountChildren("State");
+ outLogicCounter.m_SlideElementCount++; // this slide is also an element
+ Q3DStudio::INT32 theChildStateIndex(inStateIndex + 1);
+
+ for (bool theResult = inReader.MoveToFirstChild(); theResult;
+ theResult = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "State")) {
+ DoStateSectionCount(inReader, theChildStateIndex, outLogicCounter);
+ ++theChildStateIndex;
+ } else if (AreEqual(inReader.GetNarrowElementName(), "Add")
+ || AreEqual(inReader.GetNarrowElementName(), "Set")) {
+ // SlideMultipler is used as follows:
+ // For every element, animation or action, the slide is used to turn on/off them
+ // Hence, if it is inside master, it will have an entry in the master and all the child
+ // slides in the SlideManager ( hence, theChildSlideCount + 1 )
+ // if it is local, it will have an entry in the master and it's slide, ( thus 2 )
+ // the assumption made here is that State in uip is definitely 2 level, hence if it has
+ // no child slides, it is definitely master
+ INT32 theSlideMultiplier;
+ if (theChildSlideCount == 0)
+ theSlideMultiplier = 2;
+ else
+ theSlideMultiplier = theChildSlideCount + 1;
+ DoRefSectionCount(inReader, theSlideMultiplier, inStateIndex, outLogicCounter);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * @ param inNumSlideMultiplier To know how this is used, see comments on the place
+ *where SlideMultipler is calculated
+ */
+void CUIPParserImpl::DoRefSectionCount(UICDM::IDOMReader &inReader, INT32 inNumSlideMultiplier,
+ INT32, SLogicSectionCount &outLogicCounter)
+{
+ IDOMReader::Scope __refCountScope(inReader);
+ const char8_t *theElementRef;
+ inReader.UnregisteredAtt("ref", theElementRef);
+ SElementData *theData(m_ParseElementManager.FindElementData(theElementRef));
+ if (theData == NULL) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+
+ if (AreEqual(inReader.GetNarrowElementName(), "Add"))
+ outLogicCounter.m_SlideElementCount += inNumSlideMultiplier;
+
+ // There are cases where some attributes only appear in the local slide element, but not at the
+ // master slide. e.g. endTime.
+ // For these attributes, we must make sure that it is added to the slide element attribute of
+ // the master, so that everything will work correctly.
+ // This is done via the slide force flag on the element property object.
+ for (TAttrMap::iterator theIter = theData->m_PropertyMap.begin(),
+ theEnd = theData->m_PropertyMap.end();
+ theIter != theEnd; ++theIter) {
+ const char8_t *theAttValue = "";
+ bool hasAtt = inReader.UnregisteredAtt(theIter->first.c_str(), theAttValue);
+ if (theIter->second.m_SlideFlag == true
+ && (theIter->second.m_SlideForceFlag == true || hasAtt == true)) {
+ outLogicCounter.m_SlideAttributeCount += theIter->second.m_Arity * inNumSlideMultiplier;
+ }
+ // Strings we may still load regardless
+ if (hasAtt && IsStringType(theIter->second.m_DataType))
+ outLogicCounter.m_StringAttrCount += 1;
+ }
+ // Always add padding for now till I can figure out exactly why padding is needed
+ // and find a minimal way to handle it.
+ outLogicCounter.m_PaddingCount += inNumSlideMultiplier;
+}
+
+uic::runtime::SSlidePlayInformation CUIPParserImpl::GetPlayMode(UICDM::IDOMReader &inReader)
+{
+ using uic::runtime::PlayMode;
+
+ uic::runtime::SSlidePlayInformation thePlayInformation;
+ // Setup with the default value from the metadata
+ eastl::string thePlayMode = m_MetaData.GetPropertyValueString(m_MetaData.Register("Slide"),
+ m_MetaData.Register("playmode"));
+ PlayMode::Enum theMode = PlayMode::StopAtEnd;
+
+ if (thePlayMode == "Looping") {
+ theMode = PlayMode::Looping;
+ } else if (thePlayMode == "PingPong") {
+ theMode = PlayMode::PingPong;
+ } else if (thePlayMode == "Ping") {
+ theMode = PlayMode::Ping;
+ } else if (thePlayMode == "Play Through To...") {
+ theMode = PlayMode::PlayThroughTo;
+ }
+ thePlayInformation.m_PlayMode = theMode;
+
+ eastl::string theInitialPlayState = m_MetaData.GetPropertyValueString(
+ m_MetaData.Register("Slide"), m_MetaData.Register("initialplaystate"));
+ if (theInitialPlayState == "Pause")
+ thePlayInformation.m_Paused = true;
+
+ const char *theAttribute;
+ if (inReader.Att("playmode", theAttribute)) {
+ if (AreEqual(theAttribute, "Play Through To...")) {
+ thePlayInformation.m_PlayMode = PlayMode::PlayThroughTo;
+ } else if (AreEqual(theAttribute, "Stop at end")) {
+ thePlayInformation.m_PlayMode = PlayMode::StopAtEnd;
+ } else if (AreEqual(theAttribute, "Looping")) {
+ thePlayInformation.m_PlayMode = PlayMode::Looping;
+ } else if (AreEqual(theAttribute, "PingPong")) {
+ thePlayInformation.m_PlayMode = PlayMode::PingPong;
+ } else if (AreEqual(theAttribute, "Ping")) {
+ thePlayInformation.m_PlayMode = PlayMode::Ping;
+ }
+ }
+
+ if (inReader.Att("initialplaystate", theAttribute)) {
+ if (AreEqual(theAttribute, "Play"))
+ thePlayInformation.m_Paused = false;
+ else
+ thePlayInformation.m_Paused = true;
+ }
+
+ return thePlayInformation;
+}
+
+INT32 CUIPParserImpl::GetPlayThroughTo(INT32 inCurrentSlideIndex, UICDM::IDOMReader &inReader)
+{
+ // Just hardcode it to Next since we know from the metadata the default is Next.
+ // If we want to query from MetaData, need to write accessor to get back SStringOrInt
+ INT32 thePlayThroughTo = inCurrentSlideIndex + 1;
+
+ const char *theAttribute;
+ if (inReader.Att("playthroughto", theAttribute) && *theAttribute) {
+ if (AreEqual(theAttribute, "Previous"))
+ thePlayThroughTo = inCurrentSlideIndex - 1;
+ else if (AreEqual(theAttribute, "Next"))
+ thePlayThroughTo = inCurrentSlideIndex + 1;
+ else if (theAttribute[0] == '#') {
+ theAttribute++;
+ SParseSlide *theSlide = m_ParseSlideManager.FindSlide(theAttribute);
+ if (theSlide)
+ thePlayThroughTo = theSlide->m_SlideIndex;
+ else
+ Q_ASSERT(!"Slide Not Found");
+ }
+ }
+
+ return thePlayThroughTo;
+}
+
+eastl::string CUIPParserImpl::GetSlideName(UICDM::IDOMReader &inReader)
+{
+ eastl::string theSlideName;
+ if (!inReader.Att("name", theSlideName))
+ inReader.Att("id", theSlideName);
+ return theSlideName;
+}
+
+eastl::string CUIPParserImpl::GetSlideId(UICDM::IDOMReader &inReader)
+{
+ eastl::string theSlideId;
+ if (!inReader.Att("id", theSlideId))
+ inReader.Att("component", theSlideId);
+ return theSlideId;
+}
+
+// In the event we added something to the slide, we return the element data.
+SElementData *CUIPParserImpl::AddSlideElement(IPresentation &inPresentation, bool inMaster,
+ UICDM::IDOMReader &inReader, INT32 *outMaxTime)
+{
+ ISlideSystem &theBuilder = inPresentation.GetSlideSystem();
+
+ SElementData *theElementData = NULL;
+ const char8_t *theElementRef = "";
+ if (inReader.UnregisteredAtt("ref", theElementRef))
+ theElementData = m_ParseElementManager.FindElementData(theElementRef);
+
+ SElement *theElement = theElementData ? theElementData->m_Element : NULL;
+ if (theElement) {
+ if (m_SlideElements.find(theElement) == m_SlideElements.end()) {
+ const char *theEyeball;
+ bool theActiveFlag = !(
+ inMaster || (inReader.Att("eyeball", theEyeball) && AreEqual(theEyeball, "False")));
+
+ m_SlideElements.insert(theElement);
+ theBuilder.AddSlideElement(*theElement, theActiveFlag);
+ m_NumSlideElements++;
+ if (outMaxTime) {
+ INT32 theElementMaxTime;
+ SElement *theParent = theElement->GetParent();
+ if (theParent && theParent->IsComponent()) {
+ if (inReader.Att("endtime", theElementMaxTime) == false) {
+ theElementMaxTime = m_MetaData.GetPropertyValueLong(
+ theElementData->m_Type, m_MetaData.Register("endtime"),
+ theElementData->m_Class);
+ }
+ *outMaxTime = NVMax(*outMaxTime, theElementMaxTime);
+ }
+ }
+ } else
+ theElementData = NULL;
+ }
+
+ return theElementData;
+}
+
+BOOL CUIPParserImpl::LoadSlideElements(IPresentation &inPresentation, UICDM::IDOMReader &inReader,
+ bool inMaster, SElement *inComponent, INT32 *outMaxTime)
+{
+ BOOL theSuccess = true;
+
+ {
+ IDOMReader::Scope __childScope(inReader);
+ eastl::string theSlideId = GetSlideId(inReader);
+ eastl::string theActionIdStr;
+ // Setup the add/set commands for this slide.
+ {
+ IDOMReader::Scope __slideScope(inReader);
+ // Load all the animations for this slide right now:
+
+ SParseSlide *theSlide = m_ParseSlideManager.FindSlide(theSlideId.c_str());
+ // All animations and actions added to the master slide are deactivated.
+ QT3DSU32 animActions = 0;
+ if (theSlide) {
+ bool canActivateFlag = !inMaster;
+ ISlideSystem &theBuilder = inPresentation.GetSlideSystem();
+ for (TInstanceIdAnimationMap::iterator
+ theInstAnimIter = theSlide->m_Animations.begin(),
+ theInstAnimEnd = theSlide->m_Animations.end();
+ theInstAnimIter != theInstAnimEnd; ++theInstAnimIter) {
+ const TAnimationList &theAnimList(theInstAnimIter->second);
+ for (QT3DSU32 theAnimIdx = 0, theAnimEnd = theAnimList.size();
+ theAnimIdx < theAnimEnd; ++theAnimIdx) {
+ theBuilder.AddSlideAnimAction(
+ true, theAnimList[theAnimIdx].m_Animation->m_AnimationIndex,
+ theAnimList[theAnimIdx].m_Active && canActivateFlag);
+ ++animActions;
+ }
+ }
+ // Build the actions for this slide.
+ for (TActionList::iterator theActionIter = theSlide->m_ActionList.begin(),
+ theActionEnd = theSlide->m_ActionList.end();
+ theActionIter != theActionEnd; ++theActionIter) {
+ SParseSlideActionEntry &theActionEntry(*theActionIter);
+ theActionIdStr.assign(theActionEntry.m_ActionId.c_str());
+ qt3ds::QT3DSI32 theActionIndex = m_ActionHelper->GetActionIndex(theActionIdStr);
+ for (qt3ds::QT3DSI32 idx = 0; idx < theActionEntry.m_ActionCount; ++idx) {
+ uic::runtime::SSlideAnimAction *theSlideData =
+ theBuilder.AddSlideAnimAction(false, theActionIndex + idx,
+ theActionEntry.m_Active
+ && canActivateFlag);
+ theActionEntry.m_Actions[idx] = theSlideData;
+ ++animActions;
+ }
+ }
+
+ // qt3ds::NVFoundationBase& fnd(
+ // inPresentation.GetApplication().GetRuntimeFactory().GetFoundation() );
+ // fnd.error( QT3DS_TRACE, "Loading slide %s, %d anim actions", theSlideId.c_str(),
+ // animActions );
+ }
+ for (BOOL theResult = inReader.MoveToFirstChild(); theResult;
+ theResult = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "Add")
+ || AreEqual(inReader.GetNarrowElementName(), "Set")) {
+ SElementData *theAddedElement =
+ AddSlideElement(inPresentation, inMaster, inReader, outMaxTime);
+ if (theAddedElement && theAddedElement->m_Element) {
+ LoadSlideElementAttrs(inPresentation, inMaster, *theAddedElement, inReader,
+ inComponent);
+ // This can define actions or set the active
+ ProcessSlideAnimAction(inPresentation, theSlideId, inMaster, inReader);
+ }
+ }
+ }
+ }
+ // Pull add commands from child slides into master slide with active=false
+ // else things won't get reset when we switch slides.
+ {
+ // All child state adds go into this object with active set to false
+ IDOMReader::Scope __masterScope(inReader);
+ for (BOOL theResult = inReader.MoveToFirstChild("State"); theResult;
+ theResult = inReader.MoveToNextSibling("State")) {
+ IDOMReader::Scope __childScope(inReader);
+ for (BOOL theResult = inReader.MoveToFirstChild("Add"); theResult;
+ theResult = inReader.MoveToNextSibling("Add")) {
+ // Add the slide element, setting the active flag to false.
+ AddSlideElement(inPresentation, inMaster, inReader, outMaxTime);
+ }
+ }
+ }
+ // Pull add commands from master slide for objects in this slide.
+ // We do this after we process the add/set commands for this slide so that objects already
+ // added
+ // get ignored. If we do pull an object forward then we have to set all of the force-set
+ // properties as well
+ // as account for a possible end-time difference.
+ {
+ IDOMReader::Scope __childScope(inReader);
+ inReader.Leave();
+ if (AreEqual(inReader.GetNarrowElementName(), "State")) {
+ TPropertyDescAndValueList theProperties;
+ for (BOOL theResult = inReader.MoveToFirstChild("Add"); theResult;
+ theResult = inReader.MoveToNextSibling("Add")) {
+ theProperties.clear();
+ SElementData *theData =
+ AddSlideElement(inPresentation, inMaster, inReader, NULL);
+ if (theData) {
+ // Add all forced attributes to this slide.
+ for (TAttrMap::iterator theIter = theData->m_PropertyMap.begin(),
+ theEnd = theData->m_PropertyMap.end();
+ theIter != theEnd; ++theIter) {
+ if (theIter->second.m_SlideForceFlag) {
+ GetMetaAttribute(inPresentation, theProperties, theData->m_Type,
+ theIter->first, theData->m_Class,
+ theIter->second.m_PropertyNames);
+ }
+ }
+ ISlideSystem &theBuilder = inPresentation.GetSlideSystem();
+ for (TPropertyDescAndValueList::iterator theIter = theProperties.begin();
+ theIter != theProperties.end(); ++theIter) {
+ theBuilder.AddSlideAttribute(theIter->first.GetAttributeKey(),
+ theIter->second);
+ m_NumSlideAttributes++;
+ }
+
+ // Ensure the actual end time is accounted for.
+ if (outMaxTime && theData->m_Element) {
+ SElement *theParent = theData->m_Element->GetParent();
+ if (theParent && theParent->IsComponent()) {
+ long theoutMaxTime = (long)*outMaxTime;
+ long theMaxTime = m_MetaData.GetPropertyValueLong(
+ theData->m_Type, m_MetaData.Register("endtime"),
+ theData->m_Class);
+ *outMaxTime = NVMax(theoutMaxTime, theMaxTime);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return theSuccess;
+}
+
+BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool,
+ SElementData &inElementData, UICDM::IDOMReader &inReader,
+ SElement *inComponent)
+{
+ ISlideSystem &theBuilder = inPresentation.GetSlideSystem();
+
+ TPropertyDescAndValueList theAttributeList;
+
+ const char8_t *theRef = "";
+ inReader.Att("ref", theRef);
+ if (theRef && *theRef && theRef[0] == '#')
+ ++theRef;
+ bool isSet = AreEqual(inReader.GetNarrowElementName(), "Set");
+ const char8_t *sourcepath;
+ if (inReader.UnregisteredAtt("sourcepath", sourcepath))
+ AddSourcePath(sourcepath);
+
+ // We don't force set attributes when a given component has a set command within one of its
+ // child states. This happens in the case of actions (but nothing else).
+ bool shouldForce = inElementData.m_Element != inComponent;
+ for (TAttrMap::iterator theIter = inElementData.m_PropertyMap.begin(),
+ theEnd = inElementData.m_PropertyMap.end();
+ theIter != theEnd; ++theIter) {
+ const char8_t *theAttValue = "";
+ bool hasAtt = inReader.UnregisteredAtt(theIter->first, theAttValue);
+ QT3DSU32 previousListSize = theAttributeList.size();
+ if (hasAtt == false) {
+ // StartTime and EndTime in Master Slide are useless, so set it to the value in the
+ // metadata.
+ // if we look at the uip file, if the element doesn't have endTime, it means is 10000ms,
+ // and not really the value in the master slide
+ // this make it special from other attributes
+ if (theIter->second.m_SlideForceFlag && shouldForce)
+ GetMetaAttribute(inPresentation, theAttributeList, inElementData.m_Type,
+ theIter->first, inElementData.m_Class,
+ theIter->second.m_PropertyNames);
+ } else {
+ // Only use the attribute list from set blocks to set values into the slide, not from
+ // add attributes
+ // This isn't completely correct
+ GetAttributeList(inPresentation, theAttributeList, inElementData.m_Type, theIter->first,
+ inElementData.m_Class, theAttValue, theIter->second.m_PropertyNames);
+ }
+ if (isSet == false && theIter->second.m_SlideForceFlag == false) {
+ if (inElementData.m_Element != NULL && theIter->second.m_ElementFlag) {
+ for (QT3DSU32 idx = previousListSize, end = theAttributeList.size(); idx < end;
+ ++idx) {
+ UVariant *theValue = inElementData.m_Element->FindPropertyValue(
+ theAttributeList[idx].first.m_Name);
+ if (theValue) {
+ *theValue = theAttributeList[idx].second;
+ }
+ }
+ }
+ theAttributeList.resize(previousListSize);
+ }
+ }
+ for (TPropertyDescAndValueList::iterator theIter = theAttributeList.begin();
+ theIter != theAttributeList.end(); ++theIter) {
+ theBuilder.AddSlideAttribute(theIter->first.GetAttributeKey(), theIter->second);
+ m_NumSlideAttributes++;
+ }
+
+ return TRUE;
+}
+
+void CUIPParserImpl::LoadAnimationTrack(IPresentation &inPresentation, SElementData &inElementData,
+ SParseSlideAnimationEntry &inAnimation)
+{
+ SElementPropertyInfo *theInfo =
+ m_ParseElementManager.FindProperty(inElementData, inAnimation.m_PropertyName);
+ if (theInfo == NULL)
+ return;
+ UINT32 theHashedKey = inAnimation.m_PropertyHash;
+ bool theIsDynamic = inAnimation.m_IsDynamic;
+ INT32 theIndex = inPresentation.GetAnimationSystem().CreateAnimationTrack(
+ *inElementData.m_Element, theHashedKey, theIsDynamic);
+ inAnimation.m_AnimationIndex = theIndex;
+ m_NumAnimationTracks++;
+ bool isRotation = theInfo->m_AdditionalType == ERuntimeAdditionalMetaDataTypeRotation;
+ LoadAnimationKeys(inPresentation, inAnimation, isRotation);
+}
+
+void CUIPParserImpl::LoadAnimationKeys(IPresentation &inPresentation,
+ const SParseSlideAnimationEntry &inAnimation,
+ bool inIsRotation)
+{
+
+ NVConstDataRef<qt3ds::QT3DSF32> theFloatValues(inAnimation.m_KeyframeData.data(),
+ (qt3ds::QT3DSU32)inAnimation.m_KeyframeData.size());
+ switch (inAnimation.m_AnimationType) {
+ case SParseSlideAnimationTypes::Linear:
+ LoadLinearKeys(inPresentation, theFloatValues, inIsRotation);
+ break;
+ case SParseSlideAnimationTypes::Bezier:
+ LoadBezierKeys(inPresentation, theFloatValues, inIsRotation);
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ case SParseSlideAnimationTypes::EaseInOut:
+ LoadEaseInOutKeys(inPresentation, theFloatValues, inIsRotation);
+ break;
+ }
+}
+
+BOOL CUIPParserImpl::LoadBezierKeys(IPresentation &inPresentation, NVConstDataRef<float> &inValues,
+ bool inIsRotation)
+{
+ QT3DS_ASSERT(inValues.size() % 6 == 0);
+ if (inValues.size() % 6 != 0)
+ return FALSE;
+
+ IAnimationSystem &theBuilder = inPresentation.GetAnimationSystem();
+
+ float theTime;
+ float theValue;
+ float theC1Time;
+ float theC1Value;
+ float theC2Time;
+ float theC2Value;
+
+ const float *theIter = inValues.begin();
+
+ long theNumKeys = inValues.size() / 6;
+ QT3DS_ASSERT(theNumKeys > 0);
+ for (long theIndex = 0; theIndex < theNumKeys; ++theIndex) {
+ theTime = *theIter * 1000.0f;
+ ++theIter;
+ theValue = *theIter;
+ ++theIter;
+ ++theIter; // just increment the iterator, C2Time is set below
+ ++theIter; // just increment the iterator, C2Value is set below
+ theC1Time = *theIter * 1000.0f;
+ ++theIter;
+ theC1Value = *theIter;
+ ++theIter;
+
+ if (theIndex == theNumKeys - 1) {
+ // Last keyframe
+ theC2Time = 0.0f;
+ theC2Value = 0.0f;
+ } else {
+ theC2Time = *(theIter + 2) * 1000.0f; // access the next inTangentTime
+ theC2Value = *(theIter + 3); // access the next inTangentValue
+ }
+
+ if (inIsRotation) {
+ TORAD(theValue);
+ TORAD(theC1Value);
+ TORAD(theC2Value);
+ }
+
+ theBuilder.AddKey(theTime, theValue, theC1Time, theC1Value, theC2Time, theC2Value);
+ m_NumAnimationKeys++;
+ }
+ return TRUE;
+}
+
+BOOL CUIPParserImpl::LoadLinearKeys(IPresentation &inPresentation, NVConstDataRef<float> &inValues,
+ bool inIsRotation)
+{
+ QT3DS_ASSERT(inValues.size() % 2 == 0);
+ if (inValues.size() % 2 != 0)
+ return FALSE;
+
+ const float *theIter = inValues.begin();
+
+ long theNumKeys = inValues.size() / 2;
+ float *theEaseInOutValues = new float[theNumKeys * 4];
+ float *theEaseInOutPtr = theEaseInOutValues;
+ for (long theKeyIndex = 0; theKeyIndex < theNumKeys; ++theKeyIndex) {
+ *theEaseInOutPtr++ = *theIter++;
+ *theEaseInOutPtr++ = *theIter++;
+ *theEaseInOutPtr++ = 0.0f;
+ *theEaseInOutPtr++ = 0.0f;
+ }
+
+ NVConstDataRef<float> theFloatValues =
+ NVConstDataRef<float>(theEaseInOutValues, theNumKeys * 4);
+ BOOL theStatus = LoadEaseInOutKeys(inPresentation, theFloatValues, inIsRotation);
+
+ delete[] theEaseInOutValues;
+
+ return theStatus;
+}
+
+CUIPParserImpl::SEaseInEaseOutKeyframe CUIPParserImpl::ParseEaseInOutKey(const float *&inFloatIter)
+{
+ CUIPParserImpl::SEaseInEaseOutKeyframe theKeyframe;
+ theKeyframe.m_Time = *inFloatIter;
+ ++inFloatIter;
+ theKeyframe.m_Value = *inFloatIter;
+ ++inFloatIter;
+ theKeyframe.m_EaseIn = *inFloatIter;
+ ++inFloatIter;
+ theKeyframe.m_EaseOut = *inFloatIter;
+ ++inFloatIter;
+ return theKeyframe;
+}
+
+BOOL CUIPParserImpl::LoadEaseInOutKeys(IPresentation &inPresentation,
+ NVConstDataRef<float> &inValues, bool inIsRotation)
+{
+ QT3DS_ASSERT(inValues.size() % 4 == 0);
+ if (inValues.size() % 4 != 0)
+ return FALSE;
+
+ long theNumKeys = inValues.size() / 4;
+
+ float *theBezierValues = new float[theNumKeys * 6];
+ float *theBezierPtr = theBezierValues;
+
+ SEaseInEaseOutKeyframe thePreviousKeyframe;
+ thePreviousKeyframe.m_Value = 0.0f;
+ SEaseInEaseOutKeyframe theCurrentKeyframe;
+ theCurrentKeyframe.m_Value = 0.0f;
+ SEaseInEaseOutKeyframe theNextKeyframe;
+ theNextKeyframe.m_Value = 0.0f;
+
+ const float *theIter = inValues.begin();
+
+ if (theNumKeys > 0) {
+ theCurrentKeyframe = ParseEaseInOutKey(theIter);
+ float *theNextValuePtr = NULL;
+ float theNextValue;
+
+ if (theNumKeys > 1) {
+ theNextKeyframe = ParseEaseInOutKey(theIter);
+ theNextValue = theNextKeyframe.m_Value;
+ theNextValuePtr = &theNextValue;
+ }
+ CreateBezierKeyframeFromEaseInEaseOutKeyframe(NULL, theCurrentKeyframe, theNextValuePtr,
+ theBezierPtr);
+ }
+
+ for (long theKeyIndex = 1; theKeyIndex < theNumKeys; ++theKeyIndex) {
+ thePreviousKeyframe = theCurrentKeyframe;
+ theCurrentKeyframe = theNextKeyframe;
+
+ float theLastValue = thePreviousKeyframe.m_Value;
+ float *theNextValuePtr = NULL;
+ float theNextValue;
+ if (theKeyIndex + 1 < theNumKeys) {
+ theNextKeyframe = ParseEaseInOutKey(theIter);
+ theNextValue = theNextKeyframe.m_Value;
+ theNextValuePtr = &theNextValue;
+ }
+ CreateBezierKeyframeFromEaseInEaseOutKeyframe(&theLastValue, theCurrentKeyframe,
+ theNextValuePtr, theBezierPtr);
+ }
+
+ NVConstDataRef<float> theFloatValues = NVConstDataRef<float>(theBezierValues, theNumKeys * 6);
+ BOOL theStatus = LoadBezierKeys(inPresentation, theFloatValues, inIsRotation);
+
+ delete[] theBezierValues;
+ return theStatus;
+}
+
+inline float AnimationClamp(float inLowerBound, float inUpperBound, float inValue)
+{
+ if (inValue < inLowerBound)
+ return inLowerBound;
+ if (inValue > inUpperBound)
+ return inUpperBound;
+ return inValue;
+}
+
+void CUIPParserImpl::CreateBezierKeyframeFromEaseInEaseOutKeyframe(
+ float *inPreviousValue, SEaseInEaseOutKeyframe &inCurrent, float *inNextValue,
+ float *&outBezierValues)
+{
+ float theValue = inCurrent.m_Value;
+ float theSeconds = inCurrent.m_Time;
+ float inSeconds = 0.f;
+ float inValue = 0.f;
+ float outSeconds = 0.f;
+ float outValue = 0.f;
+ const double oneThird = 1.0 / 3.0;
+ if (inPreviousValue) {
+ float thePercent = 1.0f - AnimationClamp(0.0f, 1.0f, inCurrent.m_EaseIn / 100.f);
+ double theAmount = 1.0f - thePercent * oneThird;
+ inValue = *inPreviousValue + (float)(((inCurrent.m_Value - *inPreviousValue) * theAmount));
+ }
+ if (inNextValue) {
+ float thePercent = 1.0f - AnimationClamp(0.0f, 1.0f, inCurrent.m_EaseOut / 100.f);
+ double theAmount = thePercent * oneThird;
+ outValue = (float)(inCurrent.m_Value + ((*inNextValue - inCurrent.m_Value) * theAmount));
+ }
+
+ *outBezierValues++ = theSeconds;
+ *outBezierValues++ = theValue;
+ *outBezierValues++ = inSeconds;
+ *outBezierValues++ = inValue;
+ *outBezierValues++ = outSeconds;
+ *outBezierValues++ = outValue;
+}
+
+BOOL CUIPParserImpl::ProcessSlideAnimAction(IPresentation &inPresentation, eastl::string &inSlideId,
+ bool inMaster, UICDM::IDOMReader &inReader)
+{
+ IDOMReader::Scope __animationScope(inReader);
+
+ BOOL theStatus = true;
+
+ for (BOOL theResult = inReader.MoveToFirstChild("Action"); theResult;
+ theResult = inReader.MoveToNextSibling("Action")) {
+ // Get the active flag
+ const char *theEyeball;
+ bool theActiveFlag =
+ !(inMaster || (inReader.Att("eyeball", theEyeball) && AreEqual(theEyeball, "False")));
+ theStatus &= AddSlideAction(inPresentation, inSlideId, theActiveFlag, inReader);
+ }
+
+ return theStatus;
+}
+
+BOOL CUIPParserImpl::AddSlideAction(IPresentation &, eastl::string &inSlideId, bool inActive,
+ UICDM::IDOMReader &inReader)
+{
+ SParseSlide *theSlide = m_ParseSlideManager.FindSlide(inSlideId.c_str());
+ if (theSlide == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ // Get the Action id
+ const char *theRef;
+ if (inReader.Att("ref", theRef)) {
+ theRef++; // remove the '#'
+ SParseSlideActionEntry *theEntry = m_ParseSlideManager.FindAction(*theSlide, theRef);
+ if (theEntry == NULL) {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+ for (qt3ds::QT3DSI32 actIdx = 0; actIdx < theEntry->m_ActionCount; ++actIdx) {
+ if (theEntry->m_Actions[actIdx])
+ theEntry->m_Actions[actIdx]->m_Active = inActive ? 1 : 0;
+ }
+ } else {
+ const char8_t *theActionId;
+ inReader.Att("id", theActionId);
+ SParseSlideActionEntry *theEntry = m_ParseSlideManager.FindAction(*theSlide, theActionId);
+ QT3DS_ASSERT(theEntry);
+ // Check to ensure this action was created.
+ (void)theEntry;
+ }
+
+ return TRUE;
+}
+
+bool CUIPParserImpl::IsStringType(ERuntimeDataModelDataType inDataType)
+{
+ if (inDataType == ERuntimeDataModelDataTypeStringRef
+ || inDataType == ERuntimeDataModelDataTypeString
+ || inDataType == ERuntimeDataModelDataTypeObjectRef)
+ return true;
+ return false;
+}
+
+SElementData *CUIPParserImpl::GetElementData(TStrType inElementName)
+{
+ return m_ParseElementManager.FindElementData(inElementName);
+}
+
+//==============================================================================
+/**
+ * Helper function to to get the SElement object from the element name
+ */
+SElementData *CUIPParserImpl::GetElementData(const char8_t *inElementName)
+{
+ const char8_t *theElementName(inElementName);
+ if (!IsTrivial(inElementName) && inElementName[0] == '#')
+ ++theElementName;
+ return GetElementData(m_MetaData.Register(theElementName));
+}
+
+SElement *CUIPParserImpl::GetElement(const char8_t *inElementName)
+{
+ SElementData *theData(GetElementData(inElementName));
+ if (theData)
+ return theData->m_Element;
+ return NULL;
+}
+
+SElementData *CUIPParserImpl::ParseObjectRef(const eastl::string &inObjectPath,
+ const char8_t *inOwnerId)
+{
+ TStrType theId(ParseObjectRefId(inObjectPath, inOwnerId));
+ return GetElementData(theId);
+}
+
+TStrType CUIPParserImpl::ParseObjectRefId(const eastl::string &inObjectPath,
+ const char8_t *inOwnerId)
+{
+ return m_ObjectRefHelper->ParseObjectRefId(inObjectPath, inOwnerId);
+}
+
+SElementAndType CUIPParserImpl::GetElementForID(const char *inElementName)
+{
+ SElementData *theData = m_ParseElementManager.FindElementData(inElementName);
+ if (theData == NULL)
+ return SElementAndType(UIPElementTypes::Unknown, NULL);
+
+ UICDM::ComposerObjectTypes::Enum theComposerType(
+ UICDM::ComposerObjectTypes::Convert(theData->m_Type.c_str()));
+ UIPElementTypes::Enum theUIPType(UIPElementTypes::Unknown);
+ switch (theComposerType) {
+ case UICDM::ComposerObjectTypes::Scene:
+ theUIPType = UIPElementTypes::Scene;
+ break;
+ case UICDM::ComposerObjectTypes::Layer:
+ theUIPType = UIPElementTypes::Layer;
+ break;
+ case UICDM::ComposerObjectTypes::Group:
+ theUIPType = UIPElementTypes::Group;
+ break;
+ case UICDM::ComposerObjectTypes::Component:
+ theUIPType = UIPElementTypes::Component;
+ break;
+ case UICDM::ComposerObjectTypes::Camera:
+ theUIPType = UIPElementTypes::Camera;
+ break;
+ case UICDM::ComposerObjectTypes::Light:
+ theUIPType = UIPElementTypes::Light;
+ break;
+ case UICDM::ComposerObjectTypes::Model:
+ theUIPType = UIPElementTypes::Model;
+ break;
+ case UICDM::ComposerObjectTypes::Material:
+ theUIPType = UIPElementTypes::Material;
+ break;
+ case UICDM::ComposerObjectTypes::Image:
+ theUIPType = UIPElementTypes::Image;
+ break;
+ case UICDM::ComposerObjectTypes::Behavior:
+ theUIPType = UIPElementTypes::Behavior;
+ break;
+ case UICDM::ComposerObjectTypes::Text:
+ theUIPType = UIPElementTypes::Text;
+ break;
+ case UICDM::ComposerObjectTypes::Effect:
+ theUIPType = UIPElementTypes::Effect;
+ break;
+ case UICDM::ComposerObjectTypes::CustomMaterial:
+ theUIPType = UIPElementTypes::CustomMaterial;
+ break;
+ case UICDM::ComposerObjectTypes::ReferencedMaterial:
+ theUIPType = UIPElementTypes::ReferencedMaterial;
+ break;
+ case UICDM::ComposerObjectTypes::RenderPlugin:
+ theUIPType = UIPElementTypes::RenderPlugin;
+ break;
+ case UICDM::ComposerObjectTypes::Path:
+ theUIPType = UIPElementTypes::Path;
+ break;
+ case UICDM::ComposerObjectTypes::PathAnchorPoint:
+ theUIPType = UIPElementTypes::PathAnchorPoint;
+ break;
+ case UICDM::ComposerObjectTypes::SubPath:
+ theUIPType = UIPElementTypes::PathSubPath;
+ break;
+ default:
+ QT3DS_ASSERT(false);
+ break;
+ }
+ return SElementAndType(theUIPType, theData->m_Element);
+}
+
+eastl::string CUIPParserImpl::ResolveReference(const char *inStringId, const char *inReference)
+{
+ SElementData *theData = ParseObjectRef(inReference, inStringId);
+ if (theData) {
+ return theData->m_Id.c_str();
+ }
+ return eastl::string();
+}
+
+IRuntimeMetaData &CUIPParserImpl::GetMetaData()
+{
+ return m_MetaData;
+}
+
+IUIPParser &IUIPParser::Create(const QString &inFileName, IRuntimeMetaData &inMetaData,
+ IInputStreamFactory &inFactory,
+ qt3ds::foundation::IStringTable &inStrTable)
+{
+ CUIPParserImpl &retval = *new CUIPParserImpl(inFileName, inMetaData, inFactory, inStrTable);
+ return retval;
+}
+}
diff --git a/src/Runtime/Source/UIPParser/Source/UICUIPParserObjectRefHelper.cpp b/src/Runtime/Source/UIPParser/Source/UICUIPParserObjectRefHelper.cpp
new file mode 100644
index 00000000..08edef8c
--- /dev/null
+++ b/src/Runtime/Source/UIPParser/Source/UICUIPParserObjectRefHelper.cpp
@@ -0,0 +1,1004 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4100) // std::variant
+#pragma warning(disable : 4396) // specializer warning nonsense
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICUIPParserObjectRefHelper.h"
+
+#include "UICDMPrefix.h"
+#include "UICDMXML.h"
+#include "UICMetadata.h"
+
+using namespace UICDM;
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+static const char PATH_DELIMITER = '.'; // can only be single char!
+static const char PATH_LINE_END = '\n';
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUIPParserObjectRefHelper::CUIPParserObjectRefHelper(IRuntimeMetaData &inMetaData)
+ : m_MetaData(inMetaData)
+ , m_MaterialStr(m_MetaData.Register("Material"))
+{
+ BuildImageNamePropertyList();
+
+ if (m_LayerImageIdToNameMap.empty()) {
+ {
+ TLightProbeAndNamePair theNamePair =
+ eastl::make_pair<eastl::string, eastl::string>("Layer_lightprobe", "lightprobe");
+ m_LayerImageIdToNameMap.insert(theNamePair);
+ }
+ {
+ TLightProbeAndNamePair theNamePair =
+ eastl::make_pair<eastl::string, eastl::string>("Layer_lightprobe2", "lightprobe2");
+ m_LayerImageIdToNameMap.insert(theNamePair);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CUIPParserObjectRefHelper::~CUIPParserObjectRefHelper()
+{
+ // Delete SGraphNode
+ for (TGraphNodeMap::iterator theIter = m_GraphNodeMap.begin(); theIter != m_GraphNodeMap.end();
+ ++theIter)
+ delete theIter->second;
+ m_GraphNodeMap.clear();
+ m_RootNode = NULL;
+}
+
+namespace {
+ void StoreTopLevelAliasAttributes(
+ IDOMReader &inReader,
+ eastl::vector<eastl::pair<eastl::string, eastl::string>> &copiedAttributes)
+ {
+ for (eastl::pair<const char8_t *, const char8_t *> att = inReader.GetNarrowFirstAttribute();
+ !isTrivial(att.first); att = inReader.GetNarrowNextAttribute()) {
+ if (!AreEqual(att.first, "scale") && !AreEqual(att.first, "position")
+ && !AreEqual(att.first, "rotation") && !AreEqual(att.first, "pivot")
+ && !AreEqual(att.first, "endtime") && !AreEqual(att.first, "eyeball")
+ && !AreEqual(att.first, "ref") && !AreEqual(att.first, "id")
+ && !AreEqual(att.first, "name") && !AreEqual(att.first, "orientation")
+ && !AreEqual(att.first, "rotationorder")) // note that sourcepath does come through.
+ {
+ copiedAttributes.push_back(eastl::make_pair(att.first, att.second));
+ }
+ }
+ }
+}
+
+void CUIPParserObjectRefHelper::CacheGraph(UICDM::IDOMReader &inReader, UICDM::IDOMWriter &inWriter)
+{
+ {
+ // First, we parse Graph section to build the scene graph
+ IDOMReader::Scope __graphScope(inReader);
+ inReader.MoveToFirstChild("Graph");
+ CacheSceneGraph(inReader);
+ }
+ void *logicScopeItem = NULL;
+ {
+ // Next, we parse Logic section to update the node name and image information
+ IDOMReader::Scope __logicScope(inReader);
+ inReader.MoveToFirstChild("Logic");
+ logicScopeItem = inReader.GetScope();
+ CacheStateGraph(inReader);
+ }
+ if (m_SceneGraphAliasList.empty() == false) {
+ IDOMReader::Scope __aliasScope(inReader);
+ // Now we expand aliases
+ eastl::hash_map<TStrType, TStrType> oldToNewIdMap;
+ std::shared_ptr<UICDM::IDOMFactory> theFactory = inWriter.GetFactory();
+ std::shared_ptr<UICDM::IStringTable> theStrTable = inReader.GetStringTable();
+ UICDM::SDOMElement *theSlidesRoot = theFactory->NextElement("AliasSlides");
+ eastl::pair<std::shared_ptr<UICDM::IDOMWriter>, std::shared_ptr<UICDM::IDOMReader>>
+ slideWriterReaderPair =
+ UICDM::IDOMWriter::CreateDOMWriter(theFactory, *theSlidesRoot, theStrTable);
+ std::shared_ptr<UICDM::IDOMWriter> slideWriter = slideWriterReaderPair.first;
+
+ {
+ IDOMReader::Scope __loopScope(inReader);
+ for (QT3DSU32 idx = 0, end = m_SceneGraphAliasList.size(); idx < end; ++idx) {
+ inReader.SetScope(m_SceneGraphAliasList[idx]);
+ const char8_t *reference;
+ SGraphNode *referencedNode = NULL;
+ const char8_t *theIdStr;
+ inReader.Att("id", theIdStr);
+ SGraphNode *aliasNode = NULL;
+ TGraphNodeMap::iterator iter = m_GraphNodeMap.find(m_MetaData.Register(theIdStr));
+ if (iter != m_GraphNodeMap.end())
+ aliasNode = iter->second;
+
+ if (inReader.UnregisteredAtt("referencednode", reference)) {
+ TStrType theSourceElemId = ParseObjectRefId(reference, theIdStr);
+ iter = m_GraphNodeMap.find(theSourceElemId);
+ if (iter != m_GraphNodeMap.end())
+ referencedNode = iter->second;
+ }
+ if (referencedNode == NULL || aliasNode == NULL) {
+ QT3DS_ASSERT(false);
+ continue;
+ }
+ inReader.SetScope(referencedNode->m_ReaderContext);
+ oldToNewIdMap.clear();
+ std::shared_ptr<UICDM::IDOMFactory> theFactory = inWriter.GetFactory();
+ std::shared_ptr<UICDM::IStringTable> theStrTable = inReader.GetStringTable();
+ UICDM::SDOMElement *theRoot = theFactory->NextElement(inReader.GetElementName());
+ std::shared_ptr<UICDM::IDOMWriter> copyWriter =
+ UICDM::IDOMWriter::CreateDOMWriter(theFactory, *theRoot, theStrTable).first;
+
+ // Step one is just to copy the scene graph generating ids.
+ SGraphNode *theParent = aliasNode->m_Parent;
+ aliasNode->m_Class = referencedNode->m_Class;
+ aliasNode->m_Type = referencedNode->m_Type;
+ // Copy the alias id
+ copyWriter->Att("id", theIdStr);
+ eastl::vector<eastl::pair<eastl::string, eastl::string>> copiedAttributes;
+ StoreTopLevelAliasAttributes(inReader, copiedAttributes);
+ for (QT3DSU32 idx = 0, end = copiedAttributes.size(); idx < end; ++idx) {
+ copyWriter->Att(copiedAttributes[idx].first.c_str(),
+ copiedAttributes[idx].second.c_str());
+ }
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "Alias"))
+ continue;
+ UICDM::IDOMReader::Scope __loopScoper(inReader);
+ UICDM::IDOMWriter::Scope writerScope(*copyWriter,
+ inReader.GetNarrowElementName());
+ CopySceneGraph(inReader, *copyWriter, *slideWriter, oldToNewIdMap,
+ aliasNode->m_Name.c_str(), theIdStr, *aliasNode);
+ }
+ if (referencedNode->m_MasterSlide) {
+ inReader.SetScope(referencedNode->m_MasterSlide);
+ CopyStates(inReader, *slideWriter, oldToNewIdMap, aliasNode->m_Name.c_str(),
+ theIdStr);
+ }
+ // Set the scope to point at the alias node.
+ inReader.SetScope(aliasNode->m_ReaderContext);
+ inWriter.ReplaceCurrent(*theRoot);
+ // Now find the owning component.
+ SGraphNode *theComponent = theParent;
+ while (theComponent && theComponent->m_MasterSlide == NULL)
+ theComponent = theComponent->m_Parent;
+
+ if (theComponent && theComponent->m_MasterSlide) {
+ inReader.SetScope(theComponent->m_MasterSlide);
+ // Copy any state commands that have entries in the old to new map.
+ CopyStateCommands(inReader, inWriter, oldToNewIdMap, aliasNode->m_Name.c_str(),
+ referencedNode->m_Id, theIdStr);
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ } // End of loop scope.
+
+ {
+ // Next, we parse Logic section to update the node name and image information
+ {
+ IDOMReader::Scope __logicScope(inReader);
+ inReader.SetScope(theSlidesRoot);
+ // Cache the new items and their names and such.
+ CacheStateGraph(inReader);
+ }
+
+ inReader.MoveToFirstChild("Logic");
+ inWriter.AppendChildren(*theSlidesRoot);
+ }
+
+ /*
+#if defined _DEBUG && defined _WIN32
+ {
+ UICDM::SDOMElement* theElem = inWriter.GetTopElement();
+ {
+ qt3ds::foundation::CFileSeekableIOStream theWriter( "c:\\temp.xml",
+FileWriteFlags() );
+ UICDM::CDOMSerializer::Write( *theElem, theWriter );
+ }
+ }
+#endif
+ */
+ }
+}
+
+void CUIPParserObjectRefHelper::CacheSceneGraph(IDOMReader &inReader, SGraphNode *inParent)
+{
+ IDOMReader::Scope __childScope(inReader);
+
+ // build out the graph.
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "Alias")) {
+ CacheSceneGraphNode(inReader, inParent);
+ m_SceneGraphAliasList.push_back(inReader.GetScope());
+ } else {
+ SGraphNode &theNode(CacheSceneGraphNode(inReader, inParent));
+ CacheSceneGraph(inReader, &theNode);
+ }
+ }
+}
+
+CUIPParserObjectRefHelper::SGraphNode &
+CUIPParserObjectRefHelper::CacheSceneGraphNode(UICDM::IDOMReader &inReader, SGraphNode *inParent)
+{
+ SGraphNode *theNode = new SGraphNode();
+ const char8_t *theIdStr;
+ inReader.Att("id", theIdStr);
+ theNode->m_Id = m_MetaData.Register(theIdStr);
+ theNode->m_Type = m_MetaData.Register(inReader.GetNarrowElementName());
+ const char8_t *theClassStr;
+ inReader.Att("class", theClassStr);
+ theNode->m_Class = m_MetaData.Register(theClassStr);
+ const char *theNameStr;
+ theNode->m_ReaderContext = inReader.GetScope();
+
+ if (inParent && inParent->m_Type == m_MetaData.Register("Layer")
+ && theNode->m_Type == m_MetaData.Register("Image")) {
+ TLightProbeIdToNameMap::iterator theFind = m_LayerImageIdToNameMap.find(theIdStr);
+ if (theFind != m_LayerImageIdToNameMap.end())
+ theNode->m_Name = m_MetaData.Register(theFind->second.c_str());
+ } else if (!inReader.Att("name", theNameStr)) {
+ Option<eastl::string> theNameStrOpt = m_MetaData.GetPropertyValueString(
+ theNode->m_Type, m_MetaData.Register("name"), theNode->m_Class);
+ if (theNameStrOpt.hasValue())
+ theNode->m_Name = m_MetaData.Register(theNameStrOpt->c_str());
+ } else
+ theNode->m_Name = m_MetaData.Register(theNameStr);
+
+ if (inParent) {
+ theNode->m_Parent = inParent;
+ inParent->m_Children.push_back(theNode);
+ } else {
+ m_RootNode = theNode;
+ }
+
+ m_GraphNodeMap[theNode->m_Id] = theNode;
+ return *theNode;
+}
+
+void CUIPParserObjectRefHelper::CacheStateGraph(IDOMReader &inReader)
+{
+ IDOMReader::Scope __childScope(inReader);
+ const char8_t *component;
+ if (inReader.UnregisteredAtt("component", component)) {
+ TGraphNodeMap::iterator iter = m_GraphNodeMap.find(m_MetaData.Register(component + 1));
+ if (iter != m_GraphNodeMap.end()) {
+ iter->second->m_MasterSlide = inReader.GetScope();
+ }
+ }
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "State"))
+ CacheStateGraph(inReader);
+ else if (AreEqual(inReader.GetNarrowElementName(), "Add")
+ || AreEqual(inReader.GetNarrowElementName(), "Set")) {
+ const char *theRef;
+ const char *theName;
+ if (inReader.Att("ref", theRef)) {
+ theRef++; // remove the '#'
+ SGraphNode *theNode = GetNode(theRef);
+ if (theNode) {
+ // Overwrite the name. This assumes that "name" property is always linked.
+ if (inReader.Att("name", theName)) {
+ theNode->m_Name = m_MetaData.Register(theName);
+ }
+
+ // Special case for material. Image properties refer to instances.
+ // For example: Scene.Layer.Rectangle.Material.diffusemap.rotationuv ->
+ // diffusemap refers to Image instance
+ // So if we find image instance, overwrite the name of the image with the
+ // property name.
+ // This assumes that user can't rename image property
+ if (theNode->m_Type == m_MaterialStr && !theNode->m_Children.empty()) {
+ for (TImageNamePropertyList::iterator theProp =
+ m_ImageNamePropertyList.begin();
+ theProp != m_ImageNamePropertyList.end(); ++theProp) {
+ const char *theImageInstance;
+ if (inReader.Att(theProp->c_str(), theImageInstance)) {
+ ++theImageInstance; // remove the '#'
+ SGraphNode *theImageNode = GetNode(theImageInstance);
+ QT3DS_ASSERT(theImageNode && theImageNode->m_Parent == theNode);
+ if (theImageNode)
+ theImageNode->m_Name = *theProp;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void CUIPParserObjectRefHelper::CopySceneGraph(UICDM::IDOMReader &inReader,
+ UICDM::IDOMWriter &inWriter,
+ UICDM::IDOMWriter &inSlideWriter,
+ TStrToStrMap &inMap, const char *inAliasName,
+ const char *inAliasId, SGraphNode &inParent)
+{
+ UICDM::IDOMReader::Scope __graphScope(inReader);
+ // Assume the element itself is already copied.
+ // Run through attributes and duplicate them, but for any id attributes generate a new id.
+ const char8_t *tempItem;
+ if (!inReader.Att("id", tempItem)) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SGraphNode *theParent = &inParent;
+ eastl::string idGenerator(inAliasName);
+ idGenerator.append("-");
+ idGenerator.append(tempItem);
+ while (m_GraphNodeMap.find(m_MetaData.Register(idGenerator.c_str())) != m_GraphNodeMap.end())
+ idGenerator.append("_");
+ inWriter.Att("id", idGenerator.c_str());
+ TStrType srcId = m_MetaData.Register(tempItem);
+ TStrType newId = m_MetaData.Register(idGenerator.c_str());
+ inMap[srcId] = newId;
+ SGraphNode *srcNode = m_GraphNodeMap.find(srcId)->second;
+ SGraphNode *newNode = new SGraphNode();
+ newNode->m_Class = srcNode->m_Class;
+ newNode->m_Id = newId;
+ newNode->m_Name = srcNode->m_Name;
+ newNode->m_Type = srcNode->m_Type;
+ newNode->m_Parent = &inParent;
+ theParent = newNode;
+ m_GraphNodeMap[newId] = newNode;
+ inParent.m_Children.push_back(newNode);
+
+ {
+ UICDM::IDOMReader::Scope __childrenScope(inReader);
+
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "Alias"))
+ continue;
+ UICDM::IDOMWriter::Scope __newNode(inWriter, inReader.GetNarrowElementName());
+ CopySceneGraph(inReader, inWriter, inSlideWriter, inMap, inAliasName, inAliasId,
+ *theParent);
+ }
+ }
+ TGraphNodeMap::iterator iter = m_GraphNodeMap.find(m_MetaData.Register(tempItem));
+ if (iter == m_GraphNodeMap.end()) {
+ QT3DS_ASSERT(false);
+ return;
+ }
+ SGraphNode *targetNode = iter->second;
+
+ for (eastl::pair<const char8_t *, const char8_t *> att = inReader.GetNarrowFirstAttribute();
+ !isTrivial(att.first); att = inReader.GetNarrowNextAttribute()) {
+ if (AreEqual(att.first, "id"))
+ continue;
+ Q3DStudio::ERuntimeDataModelDataType theDataType = m_MetaData.GetPropertyType(
+ targetNode->m_Type, m_MetaData.Register(att.first), targetNode->m_Class);
+ // Ensure we use new ids for this datatype. This ensures that we go
+ if (theDataType == ERuntimeDataModelDataTypeLong4) {
+ TStrToStrMap::iterator aliasIdName = inMap.find(m_MetaData.Register(att.second));
+ if (aliasIdName != inMap.end())
+ inWriter.Att(att.first, aliasIdName->second.c_str());
+ else {
+ QT3DS_ASSERT(false);
+ }
+ } else
+ inWriter.Att(att.first, att.second);
+ }
+ if (targetNode->m_MasterSlide) {
+ inReader.SetScope(targetNode->m_MasterSlide);
+ CopyStates(inReader, inSlideWriter, inMap, inAliasName, inAliasId);
+ }
+}
+
+void CUIPParserObjectRefHelper::CopyStates(UICDM::IDOMReader &inReader,
+ UICDM::IDOMWriter &inSlideWriter, TStrToStrMap &inMap,
+ const char *inAliasName, const char *inAliasId)
+{
+ UICDM::IDOMReader::Scope __stateScope(inReader);
+ UICDM::IDOMWriter::Scope stateScope(inSlideWriter, "State");
+ CopyAttributes(inReader, inSlideWriter, inMap, inAliasName, inAliasId);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ if (AreEqual(inReader.GetNarrowElementName(), "State"))
+ CopyStates(inReader, inSlideWriter, inMap, inAliasName, inAliasId);
+ else {
+ CopyHierarchy(inReader, inSlideWriter, inMap, inAliasName, inAliasId);
+ }
+ }
+}
+
+eastl::pair<const char8_t *, const char8_t *> CUIPParserObjectRefHelper::ProcessAliasAttribute(
+ const char8_t *inObjId, eastl::pair<const char8_t *, const char8_t *> inAttribute,
+ eastl::string &ioStrBuilder, TStrToStrMap &inMap)
+{
+ inObjId = nonNull(inObjId);
+ if (inObjId[0] == '#')
+ ++inObjId;
+ SGraphNode *theNode = GetNode(nonNull(inObjId));
+ if (theNode == NULL)
+ return inAttribute;
+ const char8_t *propName = inAttribute.first;
+ const char8_t *propValue = inAttribute.second;
+ ERuntimeAdditionalMetaDataType thePropertyType = m_MetaData.GetAdditionalType(
+ theNode->m_Type, m_MetaData.Register(propName), theNode->m_Class);
+ if (thePropertyType == ERuntimeAdditionalMetaDataTypeImage
+ || thePropertyType == ERuntimeAdditionalMetaDataTypeObjectRef) {
+ propValue = nonNull(propValue);
+ if (propValue[0] == '#')
+ ++propValue;
+ TStrToStrMap::iterator iter = inMap.find(m_MetaData.Register(propValue));
+ if (iter != inMap.end()) {
+ ioStrBuilder.assign("#");
+ ioStrBuilder.append(iter->second);
+ propValue = ioStrBuilder.c_str();
+ } else
+ propValue = inAttribute.second;
+ }
+ return eastl::make_pair(propName, propValue);
+}
+
+void CUIPParserObjectRefHelper::CopyAttributes(UICDM::IDOMReader &inReader,
+ UICDM::IDOMWriter &inSlideWriter,
+ TStrToStrMap &inMap, const char *inAliasName,
+ const char *inAliasId)
+{
+ eastl::string builder;
+ const char8_t *elemId = "";
+ for (eastl::pair<const char8_t *, const char8_t *> att = inReader.GetNarrowFirstAttribute();
+ !isTrivial(att.first); att = inReader.GetNarrowNextAttribute()) {
+ if (AreEqual(att.first, "component")) {
+ TStrToStrMap::iterator iter = inMap.find(m_MetaData.Register(att.second + 1));
+ builder.assign("#");
+ if (iter != inMap.end()) {
+ builder.append(iter->second);
+ } else {
+ builder.append(inAliasId);
+ }
+ inSlideWriter.Att(att.first, builder.c_str());
+ } else if (AreEqual(att.first, "id")) {
+ builder.assign(inAliasName);
+ builder.append("-");
+ builder.append(att.second);
+ // cannot be
+ while (m_SlideIdSet.find(m_MetaData.Register(builder.c_str())) != m_SlideIdSet.end())
+ builder.append("_");
+ inSlideWriter.Att(att.first, builder.c_str());
+ m_SlideIdSet.insert(m_MetaData.Register(builder.c_str()));
+ inMap[m_MetaData.Register(att.second)] = m_MetaData.Register(builder.c_str());
+ } else if (AreEqual(att.first, "ref")) {
+ const char8_t *refItem = att.second;
+ if (!isTrivial(refItem)) {
+ ++refItem;
+ elemId = refItem;
+ TStrToStrMap::iterator iter = inMap.find(m_MetaData.Register(refItem));
+ if (iter != inMap.end()) {
+ builder.assign("#");
+ builder.append(iter->second.c_str());
+ inSlideWriter.Att("ref", builder.c_str());
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ }
+ } else {
+ att = ProcessAliasAttribute(elemId, att, builder, inMap);
+ inSlideWriter.Att(att.first, att.second);
+ }
+ }
+}
+
+void CUIPParserObjectRefHelper::CopyHierarchy(UICDM::IDOMReader &inReader,
+ UICDM::IDOMWriter &inSlideWriter, TStrToStrMap &inMap,
+ const char *inAliasName, const char *inAliasId)
+{
+ UICDM::IDOMReader::Scope __commandScope(inReader);
+ UICDM::IDOMWriter::Scope __writerScope(inSlideWriter, inReader.GetNarrowElementName());
+ CopyAttributes(inReader, inSlideWriter, inMap, inAliasName, inAliasId);
+ const char8_t *childData;
+ if (inReader.Value(childData)) {
+ inSlideWriter.Value(childData);
+ }
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling())
+ CopyHierarchy(inReader, inSlideWriter, inMap, inAliasName, inAliasId);
+}
+
+void CUIPParserObjectRefHelper::CopyStateCommands(UICDM::IDOMReader &inReader,
+ UICDM::IDOMWriter &inWriter,
+ TStrToStrMap &oldToNewIdMap,
+ const char *inAliasName, const char *inOldId,
+ const char *inNewId)
+{
+ UICDM::IDOMReader::Scope __commandScope(inReader);
+ UICDM::SDOMElement *theSlidesRoot = NULL;
+ eastl::pair<std::shared_ptr<UICDM::IDOMWriter>, std::shared_ptr<UICDM::IDOMReader>>
+ slideWriterReaderPair;
+ std::shared_ptr<UICDM::IDOMWriter> commandWriter;
+ {
+ UICDM::IDOMReader::Scope __loopScope(inReader);
+ eastl::vector<eastl::pair<eastl::string, eastl::string>> copiedAttributes;
+ void *destCommand = NULL;
+ eastl::string strBuilder;
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ UICDM::IDOMReader::Scope childScope(inReader);
+ if (AreEqual(inReader.GetNarrowElementName(), "State"))
+ CopyStateCommands(inReader, inWriter, oldToNewIdMap, inAliasName, inOldId, inNewId);
+ else {
+ const char8_t *refItem = "";
+ if (inReader.Att("ref", refItem) && !isTrivial(refItem)) {
+ ++refItem;
+ TStrToStrMap::iterator iter = oldToNewIdMap.find(m_MetaData.Register(refItem));
+ if (iter != oldToNewIdMap.end()) {
+ if (theSlidesRoot == NULL) {
+ std::shared_ptr<UICDM::IDOMFactory> theFactory =
+ inWriter.GetFactory();
+ std::shared_ptr<UICDM::IStringTable> theStrTable =
+ inReader.GetStringTable();
+ theSlidesRoot = theFactory->NextElement("AliasSlides");
+ slideWriterReaderPair = UICDM::IDOMWriter::CreateDOMWriter(
+ theFactory, *theSlidesRoot, theStrTable);
+ commandWriter = slideWriterReaderPair.first;
+ }
+ UICDM::IDOMWriter::Scope elemScope(*commandWriter,
+ inReader.GetNarrowElementName());
+ for (eastl::pair<const char8_t *, const char8_t *> att =
+ inReader.GetNarrowFirstAttribute();
+ !isTrivial(att.first); att = inReader.GetNarrowNextAttribute()) {
+ if (AreEqual(att.first, "ref")) {
+ strBuilder.assign("#");
+ strBuilder.append(iter->second);
+ commandWriter->Att("ref", strBuilder.c_str());
+ } else {
+
+ att =
+ ProcessAliasAttribute(refItem, att, strBuilder, oldToNewIdMap);
+ commandWriter->Att(att.first, att.second);
+ }
+ }
+ for (bool commandChild = inReader.MoveToFirstChild(); commandChild;
+ commandChild = inReader.MoveToNextSibling()) {
+ UICDM::IDOMReader::Scope commandChildScope(inReader);
+ CopyHierarchy(inReader, *commandWriter, oldToNewIdMap, inAliasName, "");
+ }
+ } else if (AreEqual(refItem, inOldId)) {
+ StoreTopLevelAliasAttributes(inReader, copiedAttributes);
+ } else if (AreEqual(refItem, inNewId))
+ destCommand = inReader.GetScope();
+ }
+ }
+ }
+ if (copiedAttributes.size() && destCommand) {
+ inReader.SetScope(destCommand);
+ for (QT3DSU32 idx = 0, end = copiedAttributes.size(); idx < end; ++idx) {
+ eastl::pair<eastl::string, eastl::string> &theItem(copiedAttributes[idx]);
+ inWriter.Att(theItem.first.c_str(), theItem.second.c_str());
+ }
+ }
+ }
+ if (commandWriter)
+ inWriter.AppendChildren(*commandWriter->GetTopElement());
+}
+
+CUIPParserObjectRefHelper::SGraphNode *CUIPParserObjectRefHelper::GetNode(const char *inId)
+{
+ if (IsTrivial(inId))
+ return NULL;
+ if (inId[0] == '#')
+ ++inId;
+ TGraphNodeMap::iterator theIter = m_GraphNodeMap.find(m_MetaData.Register(inId));
+ if (theIter != m_GraphNodeMap.end())
+ return theIter->second;
+ return NULL;
+}
+
+CUIPParserObjectRefHelper::SGraphNode *CUIPParserObjectRefHelper::GetNode(eastl::string inId)
+{
+ return GetNode(inId.c_str());
+}
+
+CUIPParserObjectRefHelper::TStrType CUIPParserObjectRefHelper::GetName(const eastl::string &inId)
+{
+ SGraphNode *theNode = GetNode(inId.c_str());
+ if (theNode)
+ return theNode->m_Name;
+ QT3DS_ASSERT(false);
+ return m_MetaData.Register(inId.c_str());
+}
+
+CUIPParserObjectRefHelper::TStrType CUIPParserObjectRefHelper::GetType(const eastl::string &inId)
+{
+ SGraphNode *theNode = GetNode(inId.c_str());
+ if (theNode)
+ return theNode->m_Type;
+ QT3DS_ASSERT(false);
+ return m_MetaData.Register(inId.c_str());
+}
+
+CUIPParserObjectRefHelper::TStrType CUIPParserObjectRefHelper::GetClass(const eastl::string &inId)
+{
+ SGraphNode *theNode = GetNode(inId.c_str());
+ if (theNode)
+ return theNode->m_Class;
+ QT3DS_ASSERT(false);
+ return m_MetaData.Register(inId.c_str());
+}
+
+CUIPParserObjectRefHelper::TStrType
+CUIPParserObjectRefHelper::ParseObjectRefId(const eastl::string &inObjectPath,
+ const char8_t *inOwnerId)
+{
+ if (inObjectPath.empty()) {
+ QT3DS_ASSERT(false);
+ return TStrType();
+ } else if (inObjectPath[0] == '#') {
+ // Absolute path
+ return m_MetaData.Register(inObjectPath.substr(1).c_str());
+ } else {
+ // Relative path
+ SGraphNode *theNode = GetNode(inOwnerId);
+
+ // Split the string based on PATH_DELIMITER
+ eastl::string theStr = inObjectPath;
+ eastl::string theCurrentPart;
+ eastl::string::size_type thePos;
+ while (theNode) {
+ thePos = theStr.find(PATH_DELIMITER);
+ theCurrentPart = theStr.substr(0, thePos);
+
+ if (theCurrentPart == "parent") {
+ theNode = theNode->m_Parent;
+ } else if (theCurrentPart == "this") {
+ // Do nothing because theNode points to itself
+ } else if (theCurrentPart == "Scene") {
+ theNode = m_RootNode;
+ } else {
+ SGraphNode *theFoundChild = NULL;
+ for (QT3DSU32 childIdx = 0;
+ childIdx < theNode->m_Children.size() && theFoundChild == NULL; ++childIdx) {
+ if (AreEqual(theNode->m_Children[childIdx]->m_Name, theCurrentPart.c_str()))
+ theFoundChild = theNode->m_Children[childIdx];
+ }
+ theNode = theFoundChild;
+ }
+
+ if (thePos == eastl::string::npos)
+ break;
+
+ // Move on to the next token
+ theStr = theStr.substr(thePos + 1);
+ }
+
+ if (theNode)
+ return theNode->m_Id;
+
+ return TStrType();
+ }
+}
+
+eastl::string CUIPParserObjectRefHelper::BuildReferenceString(eastl::string inObjectPath)
+{
+ if (inObjectPath.empty()) {
+ // QT3DS_ASSERT( false );
+ return "";
+ } else if (inObjectPath[0] == '#') {
+ // Absolute path
+ return BuildAbsoluteReferenceString(inObjectPath.substr(1));
+ } else {
+ // Relative path
+ return inObjectPath;
+ }
+}
+
+eastl::string CUIPParserObjectRefHelper::BuildAbsoluteReferenceString(eastl::string inId)
+{
+ return BuildAbsoluteReferenceString(GetNode(inId));
+}
+
+eastl::string CUIPParserObjectRefHelper::BuildAbsoluteReferenceString(SGraphNode *inNode)
+{
+ if (inNode == NULL)
+ return "";
+
+ eastl::string theNameStart;
+ eastl::string theNameEnd(inNode->m_Name);
+
+ SGraphNode *theParent = inNode->m_Parent;
+ if (theParent) {
+ theNameStart.assign(BuildAbsoluteReferenceString(theParent));
+ theNameStart.append(".");
+ }
+ theNameStart += theNameEnd;
+ return theNameStart;
+}
+
+void CUIPParserObjectRefHelper::MarkAllReferencedAttributes(
+ eastl::string inId, const eastl::vector<eastl::string> &inReferences,
+ UICDM::IDOMReader &inReader, SParseElementManager &outIdAttributesMap)
+{
+ IDOMReader::Scope __scope(inReader);
+ eastl::string theReferencesTokenizer;
+ eastl::string theCurrentReference;
+ eastl::string theReferenceTokenizer;
+ eastl::string theCurrentString;
+ eastl::string::size_type startPos = 0;
+ eastl::string::size_type endPos = 0;
+ eastl::string::size_type theReferencesTokenizerPos = 0;
+ eastl::string::size_type theReferenceTokenizerPos = 0;
+ SGraphNode *theBaseInstance = GetNode(inId);
+ SGraphNode *theCurrentInstance = theBaseInstance;
+ eastl::vector<SGraphNode *> theInstanceList;
+
+ for (QT3DSU32 theRefIdx = 0, theRefEnd = inReferences.size(); theRefIdx < theRefEnd; ++theRefIdx) {
+ // Split the string based on PATH_LINE_END
+ theReferencesTokenizer = inReferences[theRefIdx];
+ theReferencesTokenizerPos = 0;
+ while (theReferencesTokenizerPos != eastl::string::npos
+ && !theReferencesTokenizer.empty()) {
+ theCurrentInstance = theBaseInstance;
+ theReferencesTokenizerPos = theReferencesTokenizer.find(PATH_LINE_END);
+ theCurrentReference = theReferencesTokenizer.substr(0, theReferencesTokenizerPos);
+
+ // Move to the next token
+ theReferencesTokenizer = theReferencesTokenizer.substr(theReferencesTokenizerPos + 1);
+
+ // trim whitespace from the beginning and the end of the string
+ startPos = theCurrentReference.find_first_not_of("\n\r\t ");
+ endPos = theCurrentReference.find_last_not_of("\n\r\t ");
+ if (startPos != eastl::string::npos)
+ theCurrentReference = theCurrentReference.substr(startPos, endPos - startPos + 1);
+
+ // Split the string based on PATH_DELIMITER
+ theReferenceTokenizer = theCurrentReference;
+ theReferenceTokenizerPos = 0;
+ theInstanceList.clear();
+ while (theReferenceTokenizerPos != eastl::string::npos
+ && !theReferenceTokenizer.empty()) {
+ theReferenceTokenizerPos = theReferenceTokenizer.find(PATH_DELIMITER);
+ theCurrentString = theReferenceTokenizer.substr(0, theReferenceTokenizerPos);
+
+ // Move to the next token
+ theReferenceTokenizer = theReferenceTokenizer.substr(theReferenceTokenizerPos + 1);
+
+ if (theReferenceTokenizerPos != eastl::string::npos) {
+ theCurrentInstance = GetReferenceNode(theCurrentInstance, theCurrentString,
+ theInstanceList, inReader);
+ } else {
+ if (theInstanceList.size() == 0 && theCurrentInstance)
+ theInstanceList.push_back(theCurrentInstance);
+ if (!MarkAttributeAsReferenced(theBaseInstance, theInstanceList,
+ theCurrentString, inReader,
+ outIdAttributesMap)) {
+ qCCritical(qt3ds::INVALID_OPERATION)
+ << "Unable to parse reference: "
+ << theBaseInstance->m_Id.c_str() << " : "
+ << theCurrentReference.c_str();
+ }
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Helper method to find the VAsset via the name which is the child of inAsset.
+ */
+CUIPParserObjectRefHelper::SGraphNode *
+CUIPParserObjectRefHelper::GetReferenceNode(SGraphNode *inInstance, eastl::string &inAssetName,
+ eastl::vector<SGraphNode *> &outInstanceList,
+ UICDM::IDOMReader &inReader)
+{
+ if (!inInstance)
+ return NULL;
+
+ SGraphNode *theReturnInstance = NULL;
+
+ if (inAssetName == "Scene") {
+ theReturnInstance = m_RootNode;
+ } else if (inAssetName == "parent") {
+ theReturnInstance = inInstance->m_Parent;
+ } else if (inAssetName == "children") {
+ outInstanceList.insert(outInstanceList.end(), inInstance->m_Children.begin(),
+ inInstance->m_Children.end());
+ } else if (inAssetName == "descendants") {
+ for (SGraphNode::TGraphNodeList::iterator theChildren = inInstance->m_Children.begin();
+ theChildren != inInstance->m_Children.end(); ++theChildren) {
+ outInstanceList.push_back(*theChildren);
+ GetReferenceNode(*theChildren, inAssetName, outInstanceList, inReader);
+ }
+ } else if (inAssetName[0] == '[' && inAssetName[inAssetName.length() - 1] == ']') {
+ // For example: [targetElement].position
+ // targetElement should be an Object picker specifying which element to preserve.
+ eastl::string theAssetName = inAssetName.substr(1, inAssetName.length() - 2);
+
+ // Check if the target element property exists and get the property value
+ eastl::string theValue;
+ if (!inReader.Att(theAssetName.c_str(), theValue)) {
+ // Try to find the parent context and get the element name from there.
+ if (AreEqual(inReader.GetElementName(), L"Set")) {
+ IDOMReader::Scope __setScope(inReader);
+ const char8_t *refValue = "";
+ inReader.Att("ref", refValue);
+ inReader.Leave();
+ inReader.Leave();
+ for (bool success = inReader.MoveToFirstChild("Add"); success;
+ success = inReader.MoveToNextSibling("Add")) {
+ const char8_t *newRef;
+ inReader.Att("ref", newRef);
+ if (AreEqual(newRef, refValue)) {
+ inReader.Att(theAssetName.c_str(), theValue);
+ break;
+ }
+ }
+ }
+ if (theValue.empty()) {
+ Option<TRuntimeMetaDataStrType> theRef = m_MetaData.GetPropertyValueObjectRef(
+ inInstance->m_Type, m_MetaData.Register(theAssetName.c_str()),
+ inInstance->m_Class);
+ if (theRef.hasValue())
+ theValue = *theRef;
+ }
+ }
+ if (!IsTrivial(theValue.c_str())) {
+ // Get the target element id
+ eastl::string theTargetElement =
+ ParseObjectRefId(theValue, inInstance->m_Id.c_str()).c_str();
+ if (theTargetElement != "") {
+ // Get the corresponding instance
+ theReturnInstance = GetNode(theTargetElement);
+ }
+ }
+ } else {
+ // Get the child with the specified name.
+ // Note that name is not unique and so this will only return the first child that matches
+ // the name
+ for (SGraphNode::TGraphNodeList::iterator theChildren = inInstance->m_Children.begin();
+ theChildren != inInstance->m_Children.end(); ++theChildren) {
+ if (AreEqual((*theChildren)->m_Name.c_str(), inAssetName.c_str())) {
+ theReturnInstance = *theChildren;
+ break;
+ }
+ }
+ }
+ return theReturnInstance;
+}
+
+bool CUIPParserObjectRefHelper::MarkAttributeAsReferenced(
+ SGraphNode *inBaseInstance, eastl::vector<SGraphNode *> &inInstanceList,
+ eastl::string &inAttributeName, UICDM::IDOMReader &inReader,
+ SParseElementManager &outIdAttributesMap)
+{
+ bool theRet(false);
+ eastl::vector<SGraphNode *>::iterator theIter = inInstanceList.begin();
+ eastl::vector<SGraphNode *>::iterator theEnd = inInstanceList.end();
+ for (; theIter != theEnd; ++theIter) {
+ SGraphNode *theCurrentInstance = *theIter;
+
+ if (inAttributeName == "all") {
+ eastl::vector<TRuntimeMetaDataStrType> theProperties;
+ m_MetaData.GetInstanceProperties(theCurrentInstance->m_Type.c_str(),
+ theCurrentInstance->m_Class.c_str(), theProperties,
+ true);
+
+ if (theProperties.size() > 0) {
+ SElementData *theData =
+ outIdAttributesMap.FindElementData(theCurrentInstance->m_Id.c_str());
+ if (theData) {
+ for (QT3DSU32 theIndex = 0; theIndex < theProperties.size(); ++theIndex)
+ outIdAttributesMap.MarkAttributeAsReferenced(
+ *theData, theProperties[theIndex].c_str());
+ }
+ theRet = true;
+ }
+ } else {
+ eastl::string theAttributeName = inAttributeName;
+ if (inAttributeName[0] == '[' && inAttributeName[inAttributeName.length() - 1] == ']') {
+ // For example: parent.[targetProp]
+ // targetProp should be a string specifying which property to preserve
+ theAttributeName = theAttributeName.substr(1, theAttributeName.length() - 2);
+
+ // Get the targetProp property value from the uip file
+ const char *theValue;
+ if (inReader.Att(theAttributeName.c_str(), theValue)) {
+ theAttributeName = theValue;
+ } else {
+ // Query metadata value of base instance
+ theAttributeName = m_MetaData.GetPropertyValueString(
+ inBaseInstance->m_Type, m_MetaData.Register(theAttributeName.c_str()),
+ inBaseInstance->m_Class);
+ }
+ }
+
+ // Check if the property exists
+ if (m_MetaData.IsPropertyExist(theCurrentInstance->m_Type,
+ m_MetaData.Register(theAttributeName.c_str()),
+ theCurrentInstance->m_Class)) {
+ MarkPreserveFlag(theCurrentInstance, theAttributeName, outIdAttributesMap);
+ theRet = true;
+ } else {
+ // check whether the attribute name has ".", strip those after that and try again
+ eastl::string::size_type theIndex = theAttributeName.rfind('.');
+ if (theIndex != eastl::string::npos) {
+ theAttributeName = theAttributeName.substr(0, theIndex);
+ if (m_MetaData.IsPropertyExist(theCurrentInstance->m_Type,
+ m_MetaData.Register(theAttributeName.c_str()),
+ theCurrentInstance->m_Class)) {
+ MarkPreserveFlag(theCurrentInstance, theAttributeName, outIdAttributesMap);
+ theRet = true;
+ }
+ }
+ }
+ }
+ }
+
+ return theRet;
+}
+
+void CUIPParserObjectRefHelper::MarkPreserveFlag(SGraphNode *inInstance, eastl::string inProperty,
+ SParseElementManager &outIdAttributesMap)
+{
+ outIdAttributesMap.MarkAttributeAsReferenced(inInstance->m_Id.c_str(), inProperty.c_str());
+}
+
+void CUIPParserObjectRefHelper::BuildImageNamePropertyList()
+{
+ // Special case for material
+ // Material's Image properties (such as diffuse map, etc) point to Image instances
+ eastl::vector<TRuntimeMetaDataStrType> theProperties;
+ m_MetaData.GetInstanceProperties("Material", NULL, theProperties, true);
+
+ size_t thePropertyCount = theProperties.size();
+ for (QT3DSU32 thePropertyIndex = 0; thePropertyIndex < thePropertyCount; ++thePropertyIndex) {
+ eastl::string theProperty = theProperties[thePropertyIndex];
+ ERuntimeAdditionalMetaDataType theAdditionalMetaDataType =
+ m_MetaData.GetAdditionalType(m_MaterialStr, m_MetaData.Register(theProperty.c_str()));
+
+ if (theAdditionalMetaDataType == ERuntimeAdditionalMetaDataTypeImage) {
+ m_ImageNamePropertyList.insert(m_MetaData.Register(theProperty.c_str()));
+ }
+ }
+}
+}
diff --git a/src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.cpp b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.cpp
new file mode 100644
index 00000000..b8e290f8
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define ADDRINFO struct addrinfo
+#define INVALID_SOCKET -1
+#define closesocket close
+#define SD_BOTH SHUT_RDWR
+#define SOCKET_ERROR -1
+
+#endif
+
+#include "SimpleTCPClientSocket.h"
+
+//==============================================================================
+/**
+ * CTOR
+ * Accepts a buffer size for internal storage and a flag to indicate if
+ * Recv should return fixed sized packets or not.
+ */
+SimpleTCPClientSocket::SimpleTCPClientSocket(long inBufferSize, bool inWaitForFull)
+ : m_ClientSocket(NULL)
+ , m_Data(NULL)
+ , m_BytesRead(0)
+ , m_BufferSize(inBufferSize)
+ , m_WaitForFull(inWaitForFull)
+{
+ m_Data = new char[m_BufferSize];
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+SimpleTCPClientSocket::~SimpleTCPClientSocket()
+{
+ if (m_ClientSocket)
+ Disconnect();
+
+ delete[] m_Data;
+}
+
+//==============================================================================
+/**
+ * Initializes TCP communications.
+ * Needs to be called once per app.
+ */
+bool SimpleTCPClientSocket::Initialize()
+{
+#ifdef _PCPLATFORM
+ WSADATA theWsaData;
+
+ if (WSAStartup(WINSOCK_VERSION, &theWsaData)) {
+ // WSAStartup failed
+ return false;
+ }
+#endif
+ return true;
+}
+
+//==============================================================================
+/**
+ * Deinitializes TCP communications.
+ * Needs to be called once per app.
+ */
+void SimpleTCPClientSocket::DeInitialize()
+{
+#ifdef _PCPLATFORM
+ WSACleanup();
+#endif
+}
+
+//==============================================================================
+/**
+ * Attempts to connect at the specified address and port.
+ */
+bool SimpleTCPClientSocket::Connect(const char *inServerAddress, const char *inServerPort)
+{
+ bool theReturn = false;
+ ADDRINFO theHints;
+ ADDRINFO *theAddrInfo = NULL;
+ ADDRINFO *theAddrInfoPtr = NULL;
+
+ memset(&theHints, 0, sizeof(theHints));
+ theHints.ai_family = PF_INET;
+ theHints.ai_socktype = SOCK_STREAM;
+
+ if (getaddrinfo(inServerAddress, inServerPort, &theHints, &theAddrInfo) == 0) {
+ for (theAddrInfoPtr = theAddrInfo; theAddrInfoPtr != NULL;
+ theAddrInfoPtr = theAddrInfoPtr->ai_next) {
+ if ((theAddrInfoPtr->ai_family == PF_INET)
+ || (theAddrInfoPtr->ai_family == PF_INET6)) // only want PF_INET or PF_INET6
+ {
+ m_ClientSocket = socket(theAddrInfoPtr->ai_family, theAddrInfoPtr->ai_socktype,
+ theAddrInfoPtr->ai_protocol);
+
+ if (m_ClientSocket != INVALID_SOCKET) {
+ if (theAddrInfoPtr->ai_socktype == SOCK_STREAM) {
+ if (connect(m_ClientSocket, theAddrInfoPtr->ai_addr,
+ theAddrInfoPtr->ai_addrlen)
+ == 0) {
+// Set this up to be a non-blocking socket
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+ int theFlags = fcntl(m_ClientSocket, F_GETFL, 0);
+ fcntl(m_ClientSocket, F_SETFL, theFlags | O_NONBLOCK);
+#endif
+
+#ifdef _PCPLATFORM
+ u_long theBlockMode = 1;
+ ioctlsocket(m_ClientSocket, FIONBIO, &theBlockMode);
+#endif
+
+ theReturn = true;
+ break;
+ }
+
+ // Connect failed
+ closesocket(m_ClientSocket);
+ }
+ }
+ }
+ }
+ }
+
+ freeaddrinfo(theAddrInfo);
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * Disconnect and closes the TCP connection.
+ */
+void SimpleTCPClientSocket::Disconnect()
+{
+ shutdown(m_ClientSocket, SD_BOTH);
+ closesocket(m_ClientSocket);
+ m_BytesRead = 0;
+ m_ClientSocket = 0;
+}
+
+//==============================================================================
+/**
+ * Receives a data packet from the socket.
+ * If m_WaitForFull is true, Recv will always return 0 until it reads m_BufferSize
+ * bytes.
+ * Else, it will return the number of bytes read (if any) per call.
+ */
+long SimpleTCPClientSocket::Recv()
+{
+ long theReturnValue = 0;
+
+ if (m_WaitForFull) {
+ theReturnValue = recv(m_ClientSocket, m_Data + m_BytesRead, m_BufferSize - m_BytesRead, 0);
+
+ if (theReturnValue > 0)
+ m_BytesRead += theReturnValue;
+
+ if (m_BytesRead < m_BufferSize)
+ theReturnValue = 0;
+ else {
+ m_BytesRead = 0;
+ theReturnValue = m_BufferSize;
+ }
+ } else {
+ theReturnValue = recv(m_ClientSocket, m_Data, m_BufferSize, 0);
+ if (theReturnValue == SOCKET_ERROR)
+ theReturnValue = 0;
+ }
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Sends a data packet to the socket.
+ * If m_WaitForFull is true, Send will always return 0 until it receives m_BufferSize
+ * bytes.
+ * Else, it will return the number of bytes sent (if any) per call.
+ */
+long SimpleTCPClientSocket::Send()
+{
+ long theReturnValue = 0;
+
+ if (m_WaitForFull) {
+ theReturnValue = send(m_ClientSocket, m_Data + m_BytesSent, m_BufferSize - m_BytesSent, 0);
+
+ if (theReturnValue > 0)
+ m_BytesSent += theReturnValue;
+
+ if (m_BytesSent < m_BufferSize)
+ theReturnValue = 0;
+ else {
+ m_BytesSent = 0;
+ theReturnValue = m_BufferSize;
+ }
+ } else {
+ theReturnValue = send(m_ClientSocket, m_Data, m_BufferSize, 0);
+ if (theReturnValue == SOCKET_ERROR)
+ theReturnValue = 0;
+ }
+
+ return theReturnValue;
+}
diff --git a/src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.h b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.h
new file mode 100644
index 00000000..c320f7fd
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPClientSocket.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#define SOCKET int
+#endif
+
+#ifdef _PCPLATFORM
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+//==============================================================================
+// Creates a TCP socket to an address and port.
+// Can return either fixed sized packets or variable sized ones.
+//==============================================================================
+class SimpleTCPClientSocket
+{
+public:
+ SimpleTCPClientSocket(long inBufferSize, bool inWaitForFull);
+ ~SimpleTCPClientSocket();
+
+public:
+ static bool Initialize();
+ static void DeInitialize();
+
+ // Client side
+ bool Connect(const char *inServerAddress, const char *inServerPort);
+ void Disconnect();
+
+ // General
+ long Recv();
+ long Send();
+
+ // operator char*( ){ return m_Data; }
+ void *GetData() { return m_Data; }
+
+protected:
+ SOCKET m_ClientSocket;
+ char *m_Data;
+ long m_BytesRead;
+ long m_BytesSent;
+ const long m_BufferSize;
+ bool m_WaitForFull;
+};
diff --git a/src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.cpp b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.cpp
new file mode 100644
index 00000000..44202739
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define ADDRINFO struct addrinfo
+#define INVALID_SOCKET -1
+#define closesocket close
+#define SD_BOTH SHUT_RDWR
+#define SOCKET_ERROR -1
+
+#endif
+
+#include "SimpleTCPServerSocket.h"
+
+//==============================================================================
+/**
+ * CTOR
+ * Accepts a buffer size for internal storage and a flag to indicate if
+ * Recv should return fixed sized packets or not.
+ */
+SimpleTCPServerSocket::SimpleTCPServerSocket(long inBufferSize, bool inWaitForFull)
+ : m_ServerSocket(NULL)
+ , m_ClientSocket(NULL)
+ , m_Data(NULL)
+ , m_BytesRead(0)
+ , m_BytesSent(0)
+ , m_BufferSize(inBufferSize)
+ , m_WaitForFull(inWaitForFull)
+ , m_Initialized(false)
+{
+ m_Data = new char[m_BufferSize];
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+SimpleTCPServerSocket::~SimpleTCPServerSocket()
+{
+ if (m_ClientSocket)
+ Disconnect();
+
+ delete[] m_Data;
+}
+
+//==============================================================================
+/**
+ * Initializes TCP communications.
+ * Needs to be called once per app.
+ */
+bool SimpleTCPServerSocket::Initialize()
+{
+#ifdef _PCPLATFORM
+ WSADATA theWsaData;
+
+ if (WSAStartup(WINSOCK_VERSION, &theWsaData)) {
+ // WSAStartup failed
+ return false;
+ }
+#endif
+ return true;
+}
+
+//==============================================================================
+/**
+ * Deinitializes TCP communications.
+ * Needs to be called once per app.
+ */
+void SimpleTCPServerSocket::DeInitialize()
+{
+#ifdef _PCPLATFORM
+ WSACleanup();
+#endif
+}
+
+//==============================================================================
+/**
+ * Creates server socket, bind it and listen for incoming connection from a client.
+ */
+bool SimpleTCPServerSocket::Accept(const char *inServerAddress /*=NULL*/,
+ unsigned short inServerPort /*=0*/)
+{
+ bool theReturn = false;
+ struct sockaddr_in sockaddrServer;
+ struct sockaddr_in sockaddrClient;
+
+ if (!m_Initialized) {
+ /* Create the TCP socket */
+ if ((m_ServerSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET) {
+ /* Construct the server sockaddr_in structure */
+ memset(&sockaddrServer, 0, sizeof(sockaddrServer)); /* Clear struct */
+ sockaddrServer.sin_family = AF_INET; /* Internet/IP */
+ sockaddrServer.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */
+ sockaddrServer.sin_port = htons(inServerPort); /* server port */
+
+ /* Bind the server socket */
+ if (bind(m_ServerSocket, (struct sockaddr *)&sockaddrServer, sizeof(sockaddrServer))
+ == 0)
+ m_Initialized = true;
+ }
+ }
+
+ /* Listen on the server socket */
+ if (listen(m_ServerSocket, 1) == 0) {
+ socklen_t theClientLen = sizeof(sockaddrClient);
+ /* Wait for client connection */
+ if ((m_ClientSocket =
+ accept(m_ServerSocket, (struct sockaddr *)&sockaddrClient, &theClientLen))
+ == 0) {
+ SetNonBlocking(m_ClientSocket);
+ theReturn = true;
+ }
+ }
+
+ return theReturn;
+}
+
+//==============================================================================
+/**
+ * Sets socket to non blocking state
+ */
+bool SimpleTCPServerSocket::SetNonBlocking(SOCKET inSocket)
+{
+// Set this up to be a non-blocking socket
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+ int theFlags = fcntl(inSocket, F_GETFL, 0);
+ return fcntl(m_ClientSocket, F_SETFL, theFlags | O_NONBLOCK) == 0;
+#endif
+
+#ifdef _PCPLATFORM
+ u_long theBlockMode = 1;
+ return ioctlsocket(inSocket, FIONBIO, &theBlockMode) == 0;
+#endif
+}
+
+//==============================================================================
+/**
+ * Disconnect and closes the TCP connection.
+ */
+void SimpleTCPServerSocket::Disconnect(bool inShutdown /*= false*/)
+{
+ shutdown(m_ClientSocket, SD_BOTH);
+ closesocket(m_ClientSocket);
+ m_BytesRead = 0;
+ m_BytesSent = 0;
+ m_ClientSocket = 0;
+
+ if (inShutdown) {
+ shutdown(m_ServerSocket, SD_BOTH);
+ closesocket(m_ServerSocket);
+ m_ServerSocket = 0;
+ }
+}
+
+//==============================================================================
+/**
+ * Receives a data packet from the socket.
+ * If m_WaitForFull is true, Recv will always return 0 until it reads m_BufferSize
+ * bytes.
+ * Else, it will return the number of bytes read (if any) per call.
+ */
+long SimpleTCPServerSocket::Recv()
+{
+ long theReturnValue = 0;
+
+ if (m_WaitForFull) {
+ theReturnValue = recv(m_ClientSocket, m_Data + m_BytesRead, m_BufferSize - m_BytesRead, 0);
+
+ if (theReturnValue > 0)
+ m_BytesRead += theReturnValue;
+
+ if (m_BytesRead < m_BufferSize)
+ theReturnValue = 0;
+ else {
+ m_BytesRead = 0;
+ theReturnValue = m_BufferSize;
+ }
+ } else {
+ theReturnValue = recv(m_ClientSocket, m_Data, m_BufferSize, 0);
+ if (theReturnValue == SOCKET_ERROR)
+ theReturnValue = 0;
+ }
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Sends a data packet to the socket.
+ * If m_WaitForFull is true, Send will always return 0 until it receives m_BufferSize
+ * bytes.
+ * Else, it will return the number of bytes sent (if any) per call.
+ */
+long SimpleTCPServerSocket::Send()
+{
+ long theReturnValue = 0;
+
+ if (m_WaitForFull) {
+ theReturnValue = send(m_ClientSocket, m_Data + m_BytesSent, m_BufferSize - m_BytesSent, 0);
+
+ if (theReturnValue > 0)
+ m_BytesSent += theReturnValue;
+
+ if (m_BytesSent < m_BufferSize)
+ theReturnValue = 0;
+ else {
+ m_BytesSent = 0;
+ theReturnValue = m_BufferSize;
+ }
+ } else {
+ theReturnValue = send(m_ClientSocket, m_Data, m_BufferSize, 0);
+ if (theReturnValue == SOCKET_ERROR)
+ theReturnValue = 0;
+ }
+
+ return theReturnValue;
+}
diff --git a/src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.h b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.h
new file mode 100644
index 00000000..565dd736
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/SimpleTCPServerSocket.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#define SOCKET int
+#endif
+
+#ifdef _PCPLATFORM
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+//==============================================================================
+// Creates a TCP socket to an address and port.
+// Can return either fixed sized packets or variable sized ones.
+//==============================================================================
+class SimpleTCPServerSocket
+{
+public:
+ SimpleTCPServerSocket(long inBufferSize, bool inWaitForFull);
+ ~SimpleTCPServerSocket();
+
+public:
+ static bool Initialize();
+ static void DeInitialize();
+
+ // Client side
+ // bool Connect( const char* inServerAddress, const char* inServerPort );
+ void Disconnect(bool inShutdown = false);
+
+ bool Accept(const char *inServerAddress = 0, unsigned short inServerPort = 0);
+
+ // General
+ long Recv();
+ long Send();
+
+ // operator void*( ){ return m_Data; }
+ void *GetData() { return m_Data; }
+
+protected:
+ bool SetNonBlocking(SOCKET inSocket);
+
+protected:
+ SOCKET m_ServerSocket;
+ SOCKET m_ClientSocket;
+ char *m_Data;
+ long m_BytesRead;
+ long m_BytesSent;
+ const long m_BufferSize;
+ bool m_WaitForFull;
+ bool m_Initialized;
+};
diff --git a/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.cpp b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.cpp
new file mode 100644
index 00000000..ef51931b
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.cpp
@@ -0,0 +1,476 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "TCPPerfLogClient.h"
+#include "UICMacros.h"
+#include "UICPlatformSpecific.h"
+#include <stdio.h>
+#include <string.h>
+
+//==============================================================================
+// Statics
+//==============================================================================
+static TCPPerfLogClient *s_PerfLogClient = NULL;
+static SPerfLogDataExtra s_LogDataExtra = { 0 };
+static const KDust s_OneSec = 1000000000;
+
+//==============================================================================
+/**
+ * Extern function to create and initialize the TCPPerfLogClient.
+ */
+int InitializePerfLogClient(const char *inServerAddress, const char *inPort, KDust inLogFreqMsec,
+ const char *inLocalLogFilename)
+{
+ int theReturn = 1;
+
+ if (!s_PerfLogClient) {
+ s_PerfLogClient =
+ new TCPPerfLogClient(inServerAddress, inPort, inLogFreqMsec, inLocalLogFilename);
+ theReturn = s_PerfLogClient->IsConnected() || s_PerfLogClient->IsLocal();
+ }
+
+ return theReturn;
+}
+
+void PerfLogMarkBegin(KDust inCurrentTimeMsec)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->MarkLogBegin(inCurrentTimeMsec);
+}
+
+void PerfLogMarkEnd(KDust inCurrentTimeMsec)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->MarkLogEnd(inCurrentTimeMsec);
+}
+
+void InitializeNVPerfMon(EGLDisplay inDisplay)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->InitializeNVPerfMon(inDisplay);
+}
+
+void CleanupPerfLogClient(EGLDisplay inDisplay)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->CleanupPerfLogClient(inDisplay);
+
+ delete s_PerfLogClient;
+}
+
+void PerfLogGetShortDisplay(char *outMessageBuffer)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->GetShortDisplay(outMessageBuffer);
+}
+
+//==============================================================================
+/**
+ * Extern function to send a log given a timestamp and the currently measured
+ * FPS
+ */
+void PerfLogSend(unsigned long inTimeStamp, float inFPS)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->SendLog(inTimeStamp, inFPS);
+}
+
+//==============================================================================
+/**
+ * Extern function to set string data into the log packet.
+ */
+void PerfLogSetStringData(const char *inStringData)
+{
+ if (s_PerfLogClient)
+ s_PerfLogClient->SetStringData(inStringData);
+}
+
+//==============================================================================
+/**
+ * CTOR
+ * Attempts to make a connection to a specified server address and port.
+ */
+TCPPerfLogClient::TCPPerfLogClient(const char *inServerAddress, const char *inServerPort,
+ KDust inLogFreqUSec, const char *inLocalLogFilename)
+ : m_Socket(sizeof(SPerfLogData), true)
+ , m_ProcMeminfo(NULL)
+ , m_ProcStatinfo(NULL)
+ , m_NvRmHandle(NULL)
+ , m_Connected(false)
+ , m_SendLog(false)
+ , m_LocalLogFile(NULL)
+ , m_RequiredPasses(1)
+ , m_CurrentPass(0)
+ , m_FrameCount(0)
+ , m_LogFreq(inLogFreqUSec)
+ , m_LastLogTime(0)
+ , m_LastExtraLogTime(0)
+ , m_NVPerfMonitor(NULL)
+ , m_NVGPUIdleCounter(NULL)
+{
+ //::memset( &m_Data, 0, sizeof( m_Data) );
+ m_Connected = m_Socket.Connect(inServerAddress, inServerPort);
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+ // Open the meminfo procfs
+ m_ProcMeminfo = ::fopen("/proc/meminfo", "r");
+ ::setvbuf(m_ProcMeminfo, NULL, _IONBF, 0);
+
+ // Open the stat procfs
+ m_ProcStatinfo = ::fopen("/proc/stat", "r");
+ ::setvbuf(m_ProcStatinfo, NULL, _IONBF, 0);
+#endif
+
+#ifdef _TEGRA_LINUX
+ // Get a handle into vrm
+ NvRmOpen(m_NvRmHandle, 0);
+
+ // Activate DFS so that we can retrieve the EMC utilization
+ if (NvRmDfsSetState(m_NvRmHandle, NvRmDfsRunState_ClosedLoop) != 0)
+ kdLogMessage("\nUnable to activate DFS");
+#endif
+
+ if (inLocalLogFilename)
+ m_LocalLogFile = ::fopen(inLocalLogFilename, "w");
+}
+
+//==============================================================================
+/**
+ * DTOR
+ * Closes opened handles.
+ */
+TCPPerfLogClient::~TCPPerfLogClient()
+{
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+ fclose(m_ProcMeminfo);
+ fclose(m_ProcStatinfo);
+#endif
+
+#ifdef _TEGRA_LINUX
+ NvRmClose(m_NvRmHandle);
+#endif
+ m_Socket.Disconnect();
+
+ if (m_LocalLogFile)
+ ::fclose(m_LocalLogFile);
+}
+
+//==============================================================================
+/**
+ * Marks the beginning of perf logging.
+ */
+void TCPPerfLogClient::MarkLogBegin(KDust inCurrentTime)
+{
+ if (m_LogFreq > 0) {
+ if ((inCurrentTime - m_LastLogTime) > m_LogFreq) {
+ m_SendLog = true; // Signal to initiate logging (might required a few frames before log
+ // data is fully captured)
+
+ // Starts the NV perf monitor for this frame
+ if (m_NVPerfMonitor)
+ m_NVPerfMonFuncs.eglPerfMonitorBeginExperimentNV();
+ }
+
+ if (m_SendLog) {
+ if (m_NVPerfMonitor)
+ m_NVPerfMonFuncs.eglPerfMonitorBeginPassNV(m_CurrentPass % m_RequiredPasses);
+ }
+
+ if ((inCurrentTime - m_LastExtraLogTime) > s_OneSec) {
+ SPerfLogData *theData = static_cast<SPerfLogData *>(m_Socket.GetData());
+ s_LogDataExtra.m_MinFPS = s_LogDataExtra.m_MaxFPS = theData->m_FPS;
+ s_LogDataExtra.m_MinCPULoad = s_LogDataExtra.m_MaxCPULoad = theData->m_CPULoad;
+ s_LogDataExtra.m_MinGPULoad = s_LogDataExtra.m_MaxGPULoad = theData->m_GPULoad;
+ m_LastExtraLogTime = inCurrentTime;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Marks the end of perf logging.
+ */
+void TCPPerfLogClient::MarkLogEnd(KDust inCurrentTime)
+{
+ ++m_FrameCount;
+
+ if (m_SendLog) {
+ if (m_NVPerfMonitor) {
+ // Signal the end of NV perf logging for this frame
+ m_NVPerfMonFuncs.eglPerfMonitorEndPassNV();
+ ++m_CurrentPass;
+ }
+
+ if ((m_CurrentPass % m_RequiredPasses == 0)) {
+ if (m_NVPerfMonitor)
+ m_NVPerfMonFuncs.eglPerfMonitorEndExperimentNV();
+
+ KDust theElaspedTime = inCurrentTime - m_LastLogTime;
+ SendLog(static_cast<unsigned long>(inCurrentTime / 1000000),
+ static_cast<float>(m_FrameCount / (theElaspedTime / 1000000000.0)));
+ m_LastLogTime = inCurrentTime;
+ m_FrameCount = 0;
+ m_SendLog = false;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Sets timestamp and FPS into log and calls GatherStatistics.
+ * Sends log data into the socket.
+ */
+bool TCPPerfLogClient::SendLog(unsigned long inTimestamp, float inFPS)
+{
+ SPerfLogData *theData = static_cast<SPerfLogData *>(m_Socket.GetData());
+ theData->m_Timestamp = inTimestamp;
+ theData->m_FPS = inFPS;
+ GatherStatistics(theData);
+
+ s_LogDataExtra.m_MinFPS = Q3DStudio::Q3DStudio_min(inFPS, s_LogDataExtra.m_MinFPS);
+ s_LogDataExtra.m_MaxFPS = Q3DStudio::Q3DStudio_max(inFPS, s_LogDataExtra.m_MaxFPS);
+
+ s_LogDataExtra.m_MinCPULoad =
+ Q3DStudio::Q3DStudio_min(theData->m_CPULoad, s_LogDataExtra.m_MinCPULoad);
+ s_LogDataExtra.m_MaxCPULoad =
+ Q3DStudio::Q3DStudio_max(theData->m_CPULoad, s_LogDataExtra.m_MaxCPULoad);
+
+ s_LogDataExtra.m_MinGPULoad =
+ Q3DStudio::Q3DStudio_min(theData->m_GPULoad, s_LogDataExtra.m_MinGPULoad);
+ s_LogDataExtra.m_MaxGPULoad =
+ Q3DStudio::Q3DStudio_max(theData->m_GPULoad, s_LogDataExtra.m_MaxGPULoad);
+
+ bool theResult = false;
+
+ if (m_LocalLogFile)
+ theResult |= ::fputs(FormatPerfLogData(theData), m_LocalLogFile) > 0;
+
+ if (IsConnected())
+ theResult |= m_Socket.Send() > 0;
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Sets string data into the next log packet to be sent.
+ */
+void TCPPerfLogClient::SetStringData(const char *inStringData)
+{
+ SPerfLogData *theData = static_cast<SPerfLogData *>(m_Socket.GetData());
+ ::strcpy(theData->m_StringData, inStringData);
+}
+
+//==============================================================================
+/**
+ * Obtain memory usage using meminfo procfs.
+ */
+void TCPPerfLogClient::GetCPUMemoryUsage(unsigned long &outUsage)
+{
+ unsigned long theTotalMem = 0;
+ unsigned long theFreeMem = 0;
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+ rewind(m_ProcMeminfo);
+ fflush(m_ProcMeminfo);
+
+ fscanf(m_ProcMeminfo, "MemTotal: %lu kB\nMemFree: %lu kB", &theTotalMem, &theFreeMem);
+#endif
+
+ outUsage = theTotalMem - theFreeMem;
+}
+
+//==============================================================================
+/**
+ * Obtain GPU memory usage from nvrm.
+ */
+void TCPPerfLogClient::GetGPUCarveoutUsage(unsigned long &outUsage)
+{
+ long theUsedCarveout = 0;
+
+#ifdef _TEGRA_LINUX
+ NvRmMemGetStat(NvRmMemStat_UsedCarveout, theUsedCarveout);
+#endif
+
+ outUsage = theUsedCarveout;
+}
+
+//==============================================================================
+/**
+ * Obtain CPU utilization from nvrm DFS.
+ */
+void TCPPerfLogClient::GetCPULoad(float &outPercentage)
+{
+#ifdef _LINUXPLATFORM
+ // Get CPU load from /proc/stat
+ static SCPUInfo thePreviousInfo;
+ SCPUInfo theCurrentInfo;
+
+ rewind(m_ProcStatinfo);
+ fflush(m_ProcStatinfo);
+
+ // Read first line in /proc/stat which is a summary for all CPU cores on the system
+ fscanf(m_ProcStatinfo, "cpu %lu %lu %lu %lu %lu %lu %lu %lu", &theCurrentInfo.m_User,
+ &theCurrentInfo.m_Nice, &theCurrentInfo.m_System, &theCurrentInfo.m_Idle,
+ &theCurrentInfo.m_Wait, &theCurrentInfo.m_X, &theCurrentInfo.m_Y, &theCurrentInfo.m_Z);
+
+ // Idle frames calculation
+ unsigned long theIdleFrames = theCurrentInfo.m_Idle - thePreviousInfo.m_Idle;
+ if (theIdleFrames < 0)
+ theIdleFrames = 0; // Appears to be a bug in 2.4.x kernels??
+
+ // Get the total number of timeslices
+ unsigned long theTotalFrames = (theCurrentInfo.m_User - thePreviousInfo.m_User)
+ + (theCurrentInfo.m_Nice - thePreviousInfo.m_Nice)
+ + (theCurrentInfo.m_System - thePreviousInfo.m_System) + theIdleFrames
+ + (theCurrentInfo.m_Wait - thePreviousInfo.m_Wait)
+ + (theCurrentInfo.m_X - thePreviousInfo.m_X) + (theCurrentInfo.m_Y - thePreviousInfo.m_Y)
+ + (theCurrentInfo.m_Z - thePreviousInfo.m_Z);
+
+ if (theTotalFrames < 1)
+ theTotalFrames = 1;
+
+ outPercentage = 1.0f - (theIdleFrames * 1.0f / theTotalFrames);
+
+ thePreviousInfo = theCurrentInfo; // /proc/stat is an aggregation, so track this for the next
+ // time GetCPULoad is called
+
+#else
+ outPercentage = -.01f;
+#endif
+}
+
+//==============================================================================
+/**
+ * Retrieve the GPU load performance counter
+ */
+void TCPPerfLogClient::GetGPULoad(long &outPercentage)
+{
+ EGLuint64NV theCycles = 0;
+ EGLuint64NV theGPUIdle = 0;
+
+ if (m_NVPerfMonitor
+ && (m_NVPerfMonFuncs.eglGetPerfMarkerCounterNV(EGL_DEFAULT_PERFMARKER_NV,
+ m_NVGPUIdleCounter, &theGPUIdle, &theCycles)
+ == EGL_TRUE))
+ outPercentage = static_cast<long>(100 - theGPUIdle);
+ else
+ outPercentage = 0;
+}
+
+//==============================================================================
+/**
+ * Retrieve the external memory controller load.
+ * DFS must be running first.
+ */
+void TCPPerfLogClient::GetEMCLoad(float &outPercentage)
+{
+// Get CPU clock utilization from DFS
+#ifdef _TEGRA_LINUX
+ NvRmDfsClockUsage theUsage;
+ ::memset(&theUsage, 0, sizeof(theUsage));
+ if (NvRmDfsGetClockUtilization(m_NvRmHandle, NvRmDfsClockId_Emc, theUsage) == 0)
+ outPercentage = theUsage.AverageKHz * 1.0f / theUsage.CurrentKHz;
+ else
+#endif
+ outPercentage = -0.01f;
+}
+
+//==============================================================================
+/**
+ * Helper function to gather various statistics.
+ */
+void TCPPerfLogClient::GatherStatistics(SPerfLogData *inLogData)
+{
+ // Grab and set statistics here
+ GetGPUCarveoutUsage(inLogData->m_GPUMemoryUsage);
+ GetCPUMemoryUsage(inLogData->m_CPUMemoryUsage);
+ GetCPULoad(inLogData->m_CPULoad);
+ GetGPULoad(inLogData->m_GPULoad);
+ GetEMCLoad(inLogData->m_EMCLoad);
+}
+
+//==============================================================================
+/**
+ * Initialize NV perf monitor counters
+ * Currently only one counter requested (GPU Idle)
+ */
+void TCPPerfLogClient::InitializeNVPerfMon(EGLDisplay inDisplay)
+{
+#ifdef _TEGRA_LINUX
+ EGLPerfCounterNV theCounters[50];
+ EGLint theReturnedCounterSize = 0;
+
+ m_NVPerfMonitor = m_NVPerfMonFuncs.eglCreatePerfMonitorNV(
+ inDisplay, EGL_PERFMONITOR_HARDWARE_COUNTERS_BIT_NV);
+ m_NVPerfMonFuncs.eglMakeCurrentPerfMonitorNV(m_NVPerfMonitor);
+
+ m_NVPerfMonFuncs.eglGetPerfCountersNV(m_NVPerfMonitor, theCounters, 100,
+ &theReturnedCounterSize);
+ for (long theIndex = 0; theIndex < theReturnedCounterSize; ++theIndex) {
+ const char *theCounterName = m_NVPerfMonFuncs.eglQueryPerfCounterStringNV(
+ m_NVPerfMonitor, theCounters[theIndex], EGL_COUNTER_NAME_NV);
+
+ // Look for a counter with the name 'gpu idle'
+ if (Q3DStudio_stricmp(theCounterName, "GPU Idle") == 0) {
+ m_NVPerfMonFuncs.eglPerfMonitorAddCountersNV(1, &theCounters[theIndex]);
+ m_NVGPUIdleCounter = theCounters[theIndex];
+ break;
+ }
+ }
+
+ m_NVPerfMonFuncs.eglValidatePerfMonitorNV(&m_RequiredPasses);
+#else
+ UNREFERENCED_PARAMETER(inDisplay);
+#endif
+}
+
+//==============================================================================
+/**
+ * Deinitializes the NV perf monitor
+ */
+void TCPPerfLogClient::CleanupPerfLogClient(EGLDisplay inDisplay)
+{
+ if (m_NVPerfMonitor)
+ m_NVPerfMonFuncs.eglDestroyPerfMonitorNV(inDisplay, m_NVPerfMonitor);
+}
+
+//==============================================================================
+/**
+ * Retrieve a formatted output string containing performance statistics
+ */
+void TCPPerfLogClient::GetShortDisplay(char *inMessageBuffer)
+{
+ SPerfLogData *theData = static_cast<SPerfLogData *>(m_Socket.GetData());
+ FormatPerfLogDataExtra(theData, &s_LogDataExtra, inMessageBuffer);
+}
diff --git a/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.h b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.h
new file mode 100644
index 00000000..8a39dab6
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClient.h
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+//==============================================================================
+// Includes
+//==============================================================================
+#include <stdio.h>
+#include <EGL/egl.h>
+#include "SimpleTCPClientSocket.h"
+#include "TCPPerfLogCommon.h"
+#include "TCPPerfLogClientStub.h"
+
+#ifdef _PCPLATFORM
+#include <EGL/eglext.h>
+#endif
+
+//==============================================================================
+// Header definations copied from nvrm headers
+//==============================================================================
+extern "C" {
+
+/**
+ * NvRm heap statistics. See NvRmMemGetStat() for further details.
+ */
+enum NvRmMemStat {
+ /**
+ * Total number of bytes reserved for the carveout heap.
+ */
+ NvRmMemStat_TotalCarveout = 1,
+ /**
+ * Number of bytes used in the carveout heap.
+ */
+ NvRmMemStat_UsedCarveout,
+ /**
+ * Size of the largest free block in the carveout heap.
+ * Size can be less than the difference of total and
+ * used memory.
+ */
+ NvRmMemStat_LargestFreeCarveoutBlock,
+ /**
+ * Total number of bytes in the GART heap.
+ */
+ NvRmMemStat_TotalGart,
+ /**
+ * Number of bytes reserved from the GART heap.
+ */
+ NvRmMemStat_UsedGart,
+ /**
+ * Size of the largest free block in GART heap. Size can be
+ * less than the difference of total and used memory.
+ */
+ NvRmMemStat_LargestFreeGartBlock,
+};
+
+/**
+ * Defines SOC-wide clocks controlled by Dynamic Frequency Scaling (DFS)
+ * that can be targeted by Starvation and Busy hints
+ */
+enum NvRmDfsClockId {
+ /// Specifies CPU clock
+ NvRmDfsClockId_Cpu = 1,
+
+ /// Specifies AVP clock
+ NvRmDfsClockId_Avp,
+
+ /// Specifies System bus clock
+ NvRmDfsClockId_System,
+
+ /// Specifies AHB bus clock
+ NvRmDfsClockId_Ahb,
+
+ /// Specifies APB bus clock
+ NvRmDfsClockId_Apb,
+
+ /// Specifies video pipe clock
+ NvRmDfsClockId_Vpipe,
+
+ /// Specifies external memory controller clock
+ NvRmDfsClockId_Emc,
+};
+
+typedef unsigned long NvRmFreqKHz;
+
+/**
+ * Holds information on DFS clock domain utilization
+ */
+struct NvRmDfsClockUsage
+{
+ /// Minimum clock domain frequency
+ NvRmFreqKHz MinKHz;
+
+ /// Maximum clock domain frequency
+ NvRmFreqKHz MaxKHz;
+
+ /// Low corner frequency - current low boundary for DFS control algorithm.
+ /// Can be dynamically adjusted via APIs: NvRmDfsSetLowCorner() for all DFS
+ /// domains, NvRmDfsSetCpuEnvelope() for CPU, and NvRmDfsSetEmcEnvelope()
+ /// for EMC. When all DFS domains hit low corner, DFS stops waking up CPU
+ /// from low power state.
+ NvRmFreqKHz LowCornerKHz;
+
+ /// High corner frequency - current high boundary for DFS control algorithm.
+ /// Can be dynamically adjusted via APIs: NvRmDfsSetCpuEnvelope() for Cpu,
+ /// NvRmDfsSetEmcEnvelope() for Emc, and NvRmDfsSetAvHighCorner() for other
+ // DFS domains.
+ NvRmFreqKHz HighCornerKHz;
+
+ /// Current clock domain frequency
+ NvRmFreqKHz CurrentKHz;
+
+ /// Average frequency of domain *activity* (not average frequency). For
+ /// domains that do not have activity monitors reported as unspecified.
+ NvRmFreqKHz AverageKHz;
+};
+
+/**
+ * Defines DFS manager run states
+ */
+enum NvRmDfsRunState {
+ /// DFS is in invalid, not initialized state
+ NvRmDfsRunState_Invalid = 0,
+
+ /// DFS is disabled / not supported (terminal state)
+ NvRmDfsRunState_Disabled = 1,
+
+ /// DFS is stopped - no automatic clock control. Starvation and Busy hints
+ /// are recorded but have no affect.
+ NvRmDfsRunState_Stopped,
+
+ /// DFS is running in closed loop - full automatic control of SoC-wide
+ /// clocks based on clock activity measuremnets. Starvation and Busy hints
+ /// are functional as well.
+ NvRmDfsRunState_ClosedLoop,
+
+ /// DFS is running in closed loop with profiling (can not be set on non
+ /// profiling build).
+ NvRmDfsRunState_ProfiledLoop,
+};
+
+typedef void *NvRmDeviceHandle;
+
+NvRmDfsRunState NvRmDfsGetState(NvRmDeviceHandle inRmDeviceHandle);
+long NvRmDfsSetState(NvRmDeviceHandle inRmDeviceHandle, NvRmDfsRunState inDfsRunState);
+
+/**
+ * Gets information on DFS controlled clock utilization. If DFS is stopped
+ * or disabled the average frequency is always equal to current frequency.
+ *
+ * @param hRmDeviceHandle The RM device handle.
+ * @param ClockId The DFS ID of the clock targeted by this request.
+ * @param pClockInfo Output storage pointer for clock utilization information.
+ *
+ * @return NvSuccess if clock usage information is returned successfully.
+ */
+// NvError
+// NvRmDfsGetClockUtilization(
+// [in] NvRmDeviceHandle hRmDeviceHandle,
+// [in] NvRmDfsClockId ClockId,
+// [out] NvRmDfsClockUsage pClockUsage);
+long NvRmDfsGetClockUtilization(NvRmDeviceHandle inRmDeviceHandle, NvRmDfsClockId inClockId,
+ NvRmDfsClockUsage &inClockUsage);
+
+/**
+ * Get a memory statistics value.
+ *
+ * Querying values may have an effect on system performance and may include
+ * processing, like heap traversal.
+ *
+ * @param Stat NvRmMemStat value that chooses the value to return.
+ * @param Result Result, if the call was successful. Otherwise value
+ * is not touched.
+ * @returns NvSuccess on success, NvError_BadParameter if Stat is
+ * not a valid value, NvError_NotSupported if the Stat is
+ * not available for some reason, or
+ * NvError_InsufficientMemory.
+ */
+// NvError
+// NvRmMemGetStat([in] NvRmMemStat Stat, [out] NvS32 Result);
+long NvRmMemGetStat(NvRmMemStat inStat, long &outResult);
+
+/**
+ * Opens the Resource Manager for a given device.
+ *
+ * Can be called multiple times for a given device. Subsequent
+ * calls will not necessarily return the same handle. Each call to
+ * NvRmOpen() must be paired with a corresponding call to NvRmClose().
+ *
+ * Assert encountered in debug mode if DeviceId value is invalid.
+ *
+ * This call is not intended to perform any significant hardware
+ * initialization of the device; rather its primary purpose is to
+ * initialize RM's internal data structures that are involved in
+ * managing the device.
+ *
+ * @param pHandle the RM handle is stored here.
+ * @param DeviceId implementation-dependent value specifying the device
+ * to be opened. Currently must be set to zero.
+ *
+ * @retval NvSuccess Indicates that RM was successfully opened.
+ * @retval NvError_InsufficientMemory Indicates that RM was unable to allocate
+ * memory for its internal data structures.
+ */
+// NvError NvRmOpen( [out] NvRmDeviceHandle pHandle, [in] NvU32 DeviceId );
+long NvRmOpen(NvRmDeviceHandle &inHandle, unsigned long outDeviceId);
+
+/**
+ * Closes the Resource Manager for a given device.
+ *
+ * Each call to NvRmOpen() must be paired with a corresponding call
+ * to NvRmClose().
+ *
+ * @param hDevice The RM handle. If hDevice is NULL, this API has no effect.
+ */
+// void NvRmClose( [in] NvRmDeviceHandle hDevice );
+void NvRmClose(void *inDevice);
+
+} // extern "C"
+
+// Represents information obtained from /proc/stat
+typedef struct _SCPUInfo
+{
+ unsigned long m_User; // timeslices in userspace
+ unsigned long m_Nice; // timeslices for niced processed
+ unsigned long m_System; // timeslices in kernelspace
+ unsigned long m_Idle; // timeslices in idle
+ unsigned long m_Wait; // timeslices in wait
+ unsigned long m_X; // other timeslices
+ unsigned long m_Y; // other timeslices
+ unsigned long m_Z; // other timeslices
+
+ _SCPUInfo()
+ : m_User(0)
+ , m_Nice(0)
+ , m_System(0)
+ , m_Idle(0)
+ , m_Wait(0)
+ , m_X(0)
+ , m_Y(0)
+ , m_Z(0)
+ {
+ }
+
+} SCPUInfo;
+
+//==============================================================================
+// Utility function to grab EGL function pointers for NV perf monitor.
+//==============================================================================
+typedef struct _SNVPerfMonitorFuncs
+{
+ PFNEGLCREATEPERFMONITORNVPROC eglCreatePerfMonitorNV;
+ PFNEGLGETCURRENTPERFMONITORNVPROC eglGetCurrentPerfMonitorNV;
+ PFNEGLDESTROYPERFMONITORNVPROC eglDestroyPerfMonitorNV;
+ PFNEGLGETPERFCOUNTERSNVPROC eglGetPerfCountersNV;
+ PFNEGLQUERYPERFCOUNTERSTRINGNVPROC eglQueryPerfCounterStringNV;
+ PFNEGLPERFMONITORADDCOUNTERSNVPROC eglPerfMonitorAddCountersNV;
+ PFNEGLMAKECURRENTPERFMONITORNVPROC eglMakeCurrentPerfMonitorNV;
+ PFNEGLGETPERFMARKERCOUNTERNVPROC eglGetPerfMarkerCounterNV;
+ PFNEGLPERFMONITORBEGINEXPERIMENTNVPROC eglPerfMonitorBeginExperimentNV;
+ PFNEGLPERFMONITORENDEXPERIMENTNVPROC eglPerfMonitorEndExperimentNV;
+ PFNEGLPERFMONITORBEGINPASSNVPROC eglPerfMonitorBeginPassNV;
+ PFNEGLPERFMONITORENDPASSNVPROC eglPerfMonitorEndPassNV;
+ PFNEGLVALIDATEPERFMONITORNVPROC eglValidatePerfMonitorNV;
+
+ _SNVPerfMonitorFuncs()
+ {
+ eglCreatePerfMonitorNV =
+ (PFNEGLCREATEPERFMONITORNVPROC)eglGetProcAddress("eglCreatePerfMonitorNV");
+ eglDestroyPerfMonitorNV =
+ (PFNEGLDESTROYPERFMONITORNVPROC)eglGetProcAddress("eglDestroyPerfMonitorNV");
+ eglGetCurrentPerfMonitorNV =
+ (PFNEGLGETCURRENTPERFMONITORNVPROC)eglGetProcAddress("eglGetCurrentPerfMonitorNV");
+ eglGetPerfCountersNV =
+ (PFNEGLGETPERFCOUNTERSNVPROC)eglGetProcAddress("eglGetPerfCountersNV");
+ eglQueryPerfCounterStringNV =
+ (PFNEGLQUERYPERFCOUNTERSTRINGNVPROC)eglGetProcAddress("eglQueryPerfCounterStringNV");
+ eglPerfMonitorAddCountersNV =
+ (PFNEGLPERFMONITORADDCOUNTERSNVPROC)eglGetProcAddress("eglPerfMonitorAddCountersNV");
+ eglMakeCurrentPerfMonitorNV =
+ (PFNEGLMAKECURRENTPERFMONITORNVPROC)eglGetProcAddress("eglMakeCurrentPerfMonitorNV");
+ eglGetPerfMarkerCounterNV =
+ (PFNEGLGETPERFMARKERCOUNTERNVPROC)eglGetProcAddress("eglGetPerfMarkerCounterNV");
+ eglPerfMonitorBeginExperimentNV = (PFNEGLPERFMONITORBEGINEXPERIMENTNVPROC)eglGetProcAddress(
+ "eglPerfMonitorBeginExperimentNV");
+ eglPerfMonitorEndExperimentNV = (PFNEGLPERFMONITORENDEXPERIMENTNVPROC)eglGetProcAddress(
+ "eglPerfMonitorEndExperimentNV");
+ eglPerfMonitorBeginPassNV =
+ (PFNEGLPERFMONITORBEGINPASSNVPROC)eglGetProcAddress("eglPerfMonitorBeginPassNV");
+ eglPerfMonitorEndPassNV =
+ (PFNEGLPERFMONITORENDPASSNVPROC)eglGetProcAddress("eglPerfMonitorEndPassNV");
+ eglValidatePerfMonitorNV =
+ (PFNEGLVALIDATEPERFMONITORNVPROC)eglGetProcAddress("eglValidatePerfMonitorNV");
+ }
+
+} SNVPerfMonitorFuncs;
+
+//==============================================================================
+// Handles gathering of performance statistics and sending them.
+// Attempts to make a connection to a server that it will send data to.
+//==============================================================================
+class TCPPerfLogClient
+{
+public:
+ TCPPerfLogClient(const char *inServerAddress, const char *inServerPort, KDust inLogFreqUSec,
+ const char *inLocalLogFilename);
+ ~TCPPerfLogClient();
+
+public:
+ void MarkLogBegin(KDust inCurrentTime);
+ void MarkLogEnd(KDust inCurrentTime);
+
+ bool SendLog(unsigned long inTimeStamp, float inFPS);
+ void SetStringData(const char *inStringData);
+ bool IsConnected() { return m_Connected; }
+ bool IsLocal() { return m_LocalLogFile != NULL; }
+ void InitializeNVPerfMon(EGLDisplay inDisplay);
+ void CleanupPerfLogClient(EGLDisplay inDisplay);
+ void GetShortDisplay(char *inMessageBuffer);
+
+protected:
+ void GatherStatistics(SPerfLogData *inLogData);
+ void GetCPUMemoryUsage(unsigned long &outUsage);
+ void GetGPUCarveoutUsage(unsigned long &outUsage);
+ void GetCPULoad(float &outPercentage);
+ void GetGPULoad(long &outPercentage);
+ void GetEMCLoad(float &outPercentage);
+ void GetGPUWaits(long &outPercentage);
+
+protected:
+ SimpleTCPClientSocket m_Socket;
+ FILE *m_ProcMeminfo;
+ FILE *m_ProcStatinfo;
+ void *m_NvRmHandle;
+ bool m_Connected;
+ bool m_SendLog;
+ FILE *m_LocalLogFile;
+
+ EGLint m_RequiredPasses;
+ EGLint m_CurrentPass;
+
+ long m_FrameCount;
+ KDust m_LogFreq;
+ KDust m_LastLogTime;
+ KDust m_LastExtraLogTime;
+
+ const SNVPerfMonitorFuncs m_NVPerfMonFuncs;
+ EGLPerfMonitorNV m_NVPerfMonitor;
+ EGLPerfCounterNV m_NVGPUIdleCounter;
+};
diff --git a/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClientStub.h b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClientStub.h
new file mode 100644
index 00000000..66e13e73
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogClientStub.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <KD/kd.h>
+
+//==============================================================================
+// Extern interfaces
+//==============================================================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int InitializePerfLogClient(const char *inServerAddress, const char *inPort, KDust inLogFreqMsec,
+ const char *inLocalLogFilename);
+void InitializeNVPerfMon(EGLDisplay inDisplay);
+void CleanupPerfLogClient(EGLDisplay inDisplay);
+
+void PerfLogMarkBegin(KDust inCurrentTimeMsec);
+void PerfLogMarkEnd(KDust inCurrentTimeMsec);
+void PerfLogSend(unsigned long inTimeStamp, float inFPS);
+void PerfLogSetStringData(const char *inStringData);
+void PerfLogGetShortDisplay(char *outMessageBuffer);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogCommon.h b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogCommon.h
new file mode 100644
index 00000000..23bc58f2
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogCommon.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <stdio.h>
+
+//==============================================================================
+// Structs
+//==============================================================================
+typedef struct _SPerfLogData
+{
+ unsigned long m_Timestamp;
+ float m_FPS;
+ unsigned long m_GPUMemoryUsage;
+ unsigned long m_CPUMemoryUsage;
+ float m_CPULoad;
+ long m_GPULoad;
+ float m_EMCLoad;
+ char m_StringData[128];
+} SPerfLogData;
+
+typedef struct _SPerfLogDataExtra
+{
+ float m_MinFPS;
+ float m_MaxFPS;
+ float m_MinCPULoad;
+ float m_MaxCPULoad;
+ long m_MinGPULoad;
+ long m_MaxGPULoad;
+} SPerfLogDataExtra;
+
+//==============================================================================
+/**
+ * Formats SPerfLogData into a user readable form.
+ */
+const char *FormatPerfLogData(const SPerfLogData *inData)
+{
+ static char theMessageBuffer[256];
+ theMessageBuffer[0] = 0;
+
+ static unsigned long thePrevTimestamp = 0;
+ static unsigned long theTimestampDiff = 0;
+ if (thePrevTimestamp != 0)
+ theTimestampDiff = inData->m_Timestamp - thePrevTimestamp;
+
+ ::sprintf(theMessageBuffer, "Timestamp: %lu\tTimediff: %lu\tFPS: %.2f\tUsecase: "
+ "%s\tGPUMemoryUsage: %lu\tCPUMemoryUsage: %lu\tCPULoad: "
+ "%.2f\tGPULoad: %ld\tEMCLoad: %.2f\n",
+ inData->m_Timestamp, theTimestampDiff, inData->m_FPS, inData->m_StringData,
+ inData->m_GPUMemoryUsage, inData->m_CPUMemoryUsage, inData->m_CPULoad * 100,
+ inData->m_GPULoad, inData->m_EMCLoad * 100);
+
+ thePrevTimestamp = inData->m_Timestamp;
+
+ return theMessageBuffer;
+}
+
+//==============================================================================
+/**
+ * Formats SPerfLogDataExtra into a user readable form.
+ */
+void FormatPerfLogDataExtra(const SPerfLogData *inData, const SPerfLogDataExtra *inExtraData,
+ char *inMessageBuffer)
+{
+ ::sprintf(inMessageBuffer, "FPS: %.0f/%.0f/%.0f CPU: %.0f/%.0f/%.0f GPU: %ld/%ld/%ld EMC: %.0f",
+ inData->m_FPS, inExtraData->m_MaxFPS, inExtraData->m_MinFPS, inData->m_CPULoad * 100,
+ inExtraData->m_MaxCPULoad * 100, inExtraData->m_MinCPULoad * 100, inData->m_GPULoad,
+ inExtraData->m_MaxGPULoad, inExtraData->m_MinGPULoad, inData->m_EMCLoad * 100);
+}
diff --git a/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.cpp b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.cpp
new file mode 100644
index 00000000..b62663b2
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+#ifdef _PCPLATFORM
+#include <conio.h>
+#endif
+
+#include <fcntl.h>
+#include "TCPPerfLogServer.h"
+
+//==============================================================================
+/**
+ * CTOR
+ * Sets up listening server at specificed address and port.
+ * Opens log file to be ready for writing.
+ */
+TCPPerfLogServer::TCPPerfLogServer(const char *inServerAddress, unsigned short inServerPort,
+ const char *inLogFilename)
+ : m_LogFileHandle(0)
+ , m_Socket(sizeof(SPerfLogData), true)
+{
+ m_LogFileHandle = ::fopen(inLogFilename, "w");
+ m_Socket.Accept(inServerAddress, inServerPort);
+}
+
+//==============================================================================
+/**
+ * DTOR
+ * Closes log file and disconnects server.
+ */
+TCPPerfLogServer::~TCPPerfLogServer()
+{
+ ::fclose(m_LogFileHandle);
+ m_Socket.Disconnect(true);
+}
+
+//==============================================================================
+/**
+ * Checks for any received packets and write them into the log file
+ */
+const char *TCPPerfLogServer::Update()
+{
+ if (m_Socket.Recv() > 0) {
+ const char *theOutputMessage = Output();
+ ::fputs(theOutputMessage, m_LogFileHandle);
+ return theOutputMessage;
+ }
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Formats receieved data into a text string.
+ */
+const char *TCPPerfLogServer::Output()
+{
+ SPerfLogData *thePerfLogData = static_cast<SPerfLogData *>(m_Socket.GetData());
+
+ return FormatPerfLogData(thePerfLogData);
+}
+
+//==============================================================================
+/**
+ * Keyboard hittest for Linux
+ */
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+int kbhit(void)
+{
+ return 0;
+}
+#else
+#define kbhit _kbhit
+#endif
+
+//==============================================================================
+/**
+ * Main
+ */
+int main(int argc, const char *argv[])
+{
+ const char *theServerIP = "10.0.0.1";
+ const char *theLogFile = "perf.log";
+ if (argc > 1)
+ theServerIP = argv[1];
+
+ if (argc > 2)
+ theLogFile = argv[2];
+
+ SimpleTCPServerSocket::Initialize();
+
+ {
+ ::printf("\nLog file: %s", theLogFile);
+ ::printf("\nServer listening at: %s", theServerIP);
+
+ ::printf("\nWaiting for client...");
+ ::fflush(stdout);
+ TCPPerfLogServer theServer(theServerIP, 9997, theLogFile);
+ ::printf("\nClient connected...");
+ ::fflush(stdout);
+
+ while (true) {
+ const char *theReceivedMessage = theServer.Update();
+ if (theReceivedMessage)
+ printf("\n%s", theReceivedMessage);
+
+ if (kbhit()) {
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+ char theKey = getchar();
+#endif
+#ifdef _PCPLATFORM
+ char theKey = (char)_getch();
+#endif
+ if (theKey == 'q')
+ break;
+ }
+ }
+ }
+
+ SimpleTCPServerSocket::DeInitialize();
+ return 0;
+}
diff --git a/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.h b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.h
new file mode 100644
index 00000000..bfa6abcc
--- /dev/null
+++ b/src/Runtime/Source/Viewer/PerfLog/TCPPerfLogServer.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SimpleTCPServerSocket.h"
+#include "TCPPerfLogCommon.h"
+#include <stdio.h>
+
+//==============================================================================
+// Creates a polling server that listens for incoming log packets.
+// Creates a write received log data into a file.
+//==============================================================================
+class TCPPerfLogServer
+{
+public:
+ TCPPerfLogServer(const char *inServerAddress, unsigned short inServerPort,
+ const char *inLogFilename);
+ ~TCPPerfLogServer();
+
+ const char *Update();
+
+protected:
+ const char *Output();
+
+protected:
+ FILE *m_LogFileHandle;
+ SimpleTCPServerSocket m_Socket;
+};
diff --git a/src/Runtime/Source/Viewer/UICAudioPlayerImpl.cpp b/src/Runtime/Source/Viewer/UICAudioPlayerImpl.cpp
new file mode 100644
index 00000000..4f7f8fb4
--- /dev/null
+++ b/src/Runtime/Source/Viewer/UICAudioPlayerImpl.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "UICAudioPlayerImpl.h"
+#include "foundation/Qt3DSLogging.h"
+#include <QDebug>
+
+#ifdef PLATFORM_HAS_QT_MULTIMEDIA_LIB
+#include <QSound>
+#endif // PLATFORM_HAS_QT_MULTIMEDIA_LIB
+
+namespace UICViewer {
+
+CUICAudioPlayerImpl::CUICAudioPlayerImpl()
+{
+}
+
+CUICAudioPlayerImpl::~CUICAudioPlayerImpl()
+{
+}
+
+bool CUICAudioPlayerImpl::PlaySoundFile(const char *inFilePath)
+{
+#ifdef PLATFORM_HAS_QT_MULTIMEDIA_LIB
+ QSound::play(QString(inFilePath));
+ return true;
+#else
+ Q_UNUSED(inFilePath)
+ qCWarning(qt3ds::WARNING, "CUICAudioPlayerImpl::PlaySoundFile: no QT multimedia lib on this platform");
+ return false;
+#endif // PLATFORM_HAS_QT_MULTIMEDIA_LIB
+}
+}
diff --git a/src/Runtime/Source/Viewer/UICAudioPlayerImpl.h b/src/Runtime/Source/Viewer/UICAudioPlayerImpl.h
new file mode 100644
index 00000000..33f11540
--- /dev/null
+++ b/src/Runtime/Source/Viewer/UICAudioPlayerImpl.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UIC_VIEWER_LIB_UIC_AUDIO_PLAYER_IMPL_H
+#define UIC_VIEWER_LIB_UIC_AUDIO_PLAYER_IMPL_H
+
+#include "UICAudioPlayer.h"
+#include "qt3dsruntimeglobal.h"
+
+namespace UICViewer {
+
+class QT3DS_RUNTIME_API CUICAudioPlayerImpl : public Q3DStudio::IAudioPlayer
+{
+public:
+ CUICAudioPlayerImpl();
+ virtual ~CUICAudioPlayerImpl();
+ bool PlaySoundFile(const char *inFilePath) override;
+};
+}
+
+#endif // !UIC_VIEWER_LIB_UIC_AUDIO_PLAYER_IMPL_H
diff --git a/src/Runtime/Source/Viewer/UICEmbeddedWatermark.h b/src/Runtime/Source/Viewer/UICEmbeddedWatermark.h
new file mode 100644
index 00000000..cbead585
--- /dev/null
+++ b/src/Runtime/Source/Viewer/UICEmbeddedWatermark.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UIC_EMBEDDED_WATERMARK_H
+#define UIC_EMBEDDED_WATERMARK_H
+#pragma once
+
+#include <stddef.h>
+
+namespace uic {
+namespace viewer {
+ struct SUICEmbeddedFile
+ {
+ const char *name;
+ const unsigned char *data;
+ size_t size;
+ SUICEmbeddedFile()
+ : name(NULL)
+ , data(NULL)
+ , size(0)
+ {
+ }
+ SUICEmbeddedFile(const char *n, const unsigned char *d, size_t s)
+ : name(n)
+ , data(d)
+ , size(s)
+ {
+ }
+ };
+
+ inline const char *GetWatermarkFileName() { return "AutoworksWatermark.dds"; }
+
+ SUICEmbeddedFile FindEmbeddedFile(const char *inName = GetWatermarkFileName());
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/Source/Viewer/UICViewerApp.cpp b/src/Runtime/Source/Viewer/UICViewerApp.cpp
new file mode 100644
index 00000000..e70c12fc
--- /dev/null
+++ b/src/Runtime/Source/Viewer/UICViewerApp.cpp
@@ -0,0 +1,821 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <algorithm>
+
+#include "EnginePrefix.h"
+#include "UICTegraApplication.h"
+#include "UICViewerApp.h"
+#include "UICTegraInputEngine.h"
+#if !defined(Q_OS_MACOS)
+#include "TCPPerfLogClientStub.h"
+#endif
+#include "UICInputFrame.h" // keyboard mapping
+#include "foundation/Qt3DSTime.h"
+#include "UICFNDTimer.h"
+#include "UICAudioPlayer.h"
+
+#include <QList>
+#include <QFileInfo>
+#include <QDebug>
+
+#ifdef _MACOSX
+#include <mach-o/dyld.h>
+#endif
+
+#if defined(_LINUX) || defined(_MACOSX) || defined(_LINUXPLATFORM)
+// Boost insists this be defined
+namespace boost {
+void throw_exception(std::exception const & e) {}
+}
+
+namespace qt3ds {
+void NVAssert(const char *exp, const char *file, int line, bool *igonore)
+{
+ qCritical() << "NVAssertion thrown: " << file << " " << line << " " << exp;
+}
+}
+
+#ifndef EASTL_DEBUG_BREAK
+void EASTL_DEBUG_BREAK()
+{
+ qFatal("EASTL_DEBUG_BREAK: Assertion blown");
+}
+
+#endif
+#endif
+
+#ifdef _WIN32
+#include <Xinput.h>
+#include <ShellAPI.h>
+#include "UICInputFrame.h"
+
+void HandleController(Q3DStudio::CTegraApplication &inApplication)
+{
+ static const class XInputLibrary
+ {
+ private:
+ typedef DWORD(__stdcall *GetStateFunction)(DWORD, XINPUT_STATE *);
+
+ public:
+ XInputLibrary()
+ : m_module(NULL)
+ , GetState(NULL)
+ {
+ m_module = LoadLibraryA("XINPUT9_1_0.DLL");
+ if (m_module != NULL) {
+ GetState = reinterpret_cast<GetStateFunction>(GetProcAddress(m_module,
+ "XInputGetState"));
+ }
+ }
+
+ ~XInputLibrary()
+ {
+ if (m_module != NULL)
+ FreeLibrary(m_module);
+ }
+
+ GetStateFunction GetState;
+
+ private:
+ HMODULE m_module;
+ } library;
+
+ static const DWORD MAX_USERS = 4;
+ static const Q3DStudio::FLOAT STICK_RANGE = 32767;
+ static const Q3DStudio::FLOAT TRIGGER_RANGE = 255;
+
+ static const struct ButtonEntry
+ {
+ WORD XBoxButton;
+ Q3DStudio::INT32 UICButton;
+ } buttonMap[] = {
+ { XINPUT_GAMEPAD_START, Q3DStudio::BUTTON_START },
+ { XINPUT_GAMEPAD_BACK, Q3DStudio::BUTTON_SELECT },
+ { XINPUT_GAMEPAD_LEFT_THUMB, Q3DStudio::BUTTON_THUMBL },
+ { XINPUT_GAMEPAD_RIGHT_THUMB, Q3DStudio::BUTTON_THUMBR },
+ { XINPUT_GAMEPAD_LEFT_SHOULDER, Q3DStudio::BUTTON_L1 },
+ { XINPUT_GAMEPAD_RIGHT_SHOULDER, Q3DStudio::BUTTON_R1 },
+ { XINPUT_GAMEPAD_A, Q3DStudio::BUTTON_A },
+ { XINPUT_GAMEPAD_B, Q3DStudio::BUTTON_B },
+ { XINPUT_GAMEPAD_X, Q3DStudio::BUTTON_X },
+ { XINPUT_GAMEPAD_Y, Q3DStudio::BUTTON_Y } };
+
+ static DWORD userLastPacketNumber[MAX_USERS] = { 0 };
+ static WORD userLastButtons[MAX_USERS] = { 0 };
+
+ Q3DStudio::CInputEngine *input = inApplication.GetInputEngine();
+ if (input != NULL && library.GetState) {
+ // for each controller
+ for (DWORD userIndex = 0; userIndex < MAX_USERS; ++userIndex) {
+ DWORD &lastPacketNumber = userLastPacketNumber[userIndex];
+ WORD &lastButtons = userLastButtons[userIndex];
+
+ // get the state
+ XINPUT_STATE state = { 0 };
+ if (library.GetState(userIndex, &state) == ERROR_SUCCESS
+ && state.dwPacketNumber != lastPacketNumber) {
+ using namespace Q3DStudio;
+ const XINPUT_GAMEPAD &gamepad = state.Gamepad;
+ const WORD &buttons = gamepad.wButtons;
+
+ // handle button changes
+ DWORD buttonChanges = buttons ^ lastButtons;
+ for (size_t buttonMapIndex = 0;
+ buttonMapIndex < sizeof(buttonMap) / sizeof(buttonMap[0]); ++buttonMapIndex) {
+ const ButtonEntry &buttonEntry = buttonMap[buttonMapIndex];
+ if (buttonEntry.XBoxButton & buttonChanges) {
+ input->HandleButton(buttonEntry.UICButton,
+ buttons & buttonEntry.XBoxButton);
+ }
+ }
+
+ // handle gamepad
+ if (buttons & XINPUT_GAMEPAD_DPAD_LEFT)
+ input->HandleAxis(AXIS_HAT_X, -1);
+ else if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT)
+ input->HandleAxis(AXIS_HAT_X, 1);
+ else
+ input->HandleAxis(AXIS_HAT_X, 0);
+ if (buttons & XINPUT_GAMEPAD_DPAD_UP)
+ input->HandleAxis(AXIS_HAT_Y, -1);
+ else if (buttons & XINPUT_GAMEPAD_DPAD_DOWN)
+ input->HandleAxis(AXIS_HAT_Y, 1);
+ else
+ input->HandleAxis(AXIS_HAT_Y, 0);
+
+ // handle sticks and triggers
+ input->HandleAxis(AXIS_X, gamepad.sThumbLX / STICK_RANGE);
+ input->HandleAxis(AXIS_Y, gamepad.sThumbLY / -STICK_RANGE);
+ input->HandleAxis(AXIS_Z, gamepad.sThumbRX / STICK_RANGE);
+ input->HandleAxis(AXIS_RZ, gamepad.sThumbRY / -STICK_RANGE);
+ input->HandleAxis(AXIS_LTRIGGER, gamepad.bLeftTrigger / TRIGGER_RANGE);
+ input->HandleAxis(AXIS_RTRIGGER, gamepad.bRightTrigger / TRIGGER_RANGE);
+
+ // save the state
+ lastButtons = buttons;
+ lastPacketNumber = state.dwPacketNumber;
+ }
+ }
+ }
+}
+#endif
+
+using namespace Q3DStudio;
+
+struct WindowRect
+{
+ int x;
+ int y;
+ int width;
+ int height;
+};
+
+void PerfLogSetStringData(const char *)
+{
+} // Dummy defination when TCP perf logging isnt used
+
+//-----------------------------------------------------------------------------
+// KD overwrite
+//-----------------------------------------------------------------------------
+void kdLogMessage(const KDchar *string)
+{
+ qCInfo(qt3ds::TRACE_INFO) << string;
+}
+
+void kdHandleAssertion(const KDchar *condition, const KDchar *filename, KDint linenumber)
+{
+ qCCritical(qt3ds::TRACE_INFO) << "assertion failed: " << condition
+ << " " << filename << " " << linenumber;
+}
+
+Q3DStudio::SUICFNDTimer g_GlobalTimeProvider;
+
+KDust GetTimeUST()
+{
+ // this needs to be nano seconds
+ // KDust kdTime = static_cast<KDust>( g_gobalTimer.getNanoSeconds() );
+ Q3DStudio::ITimeProvider &theTimer = g_GlobalTimeProvider;
+ KDust kdTime = static_cast<KDust>(theTimer.GetCurrentTimeMicroSeconds() * 1000);
+
+ return kdTime;
+}
+
+void initResource() {
+ // init runtime static resources
+ Q_INIT_RESOURCE(res);
+}
+
+namespace UICViewer {
+
+struct SWindowSystemImpl : public Q3DStudio::IWindowSystem
+{
+ WindowRect m_Rect;
+ int m_OffscreenID;
+ int m_DepthBitCount;
+
+ SSize GetWindowDimensions() override { return SSize(m_Rect.width, m_Rect.height); }
+ void SetWindowDimensions(const SSize &inSize) override
+ {
+ m_Rect.width = inSize.m_Width;
+ m_Rect.height = inSize.m_Height;
+ }
+ // For platforms that support it, we get the egl info for render plugins
+ // Feel free to return NULL.
+ SEGLInfo *GetEGLInfo() override { return NULL; }
+ // on some systems we allow our default render target to be a offscreen buffer
+ // otherwise return 0;
+ int GetDefaultRenderTargetID() override { return m_OffscreenID; }
+ // returns the depth buffer bit count for the render window
+ int GetDepthBitCount() override { return m_DepthBitCount; }
+};
+
+class CUICViewerAppImpl
+{
+public:
+ CUICViewerAppImpl(Q3DStudio::IAudioPlayer *inAudioPlayer)
+ : m_tegraApp(0)
+ , m_appInitSuccessful(false)
+ , m_WatermarkX(-1.0f)
+ , m_WatermarkY(-1.0f)
+ , m_AudioPlayer(inAudioPlayer)
+ {
+#ifndef EMBEDDED_LINUX
+ initResource();
+#endif
+ }
+ Q3DStudio::CTegraApplication *m_tegraApp; ///< pointer to internal "tegra appliction"
+ bool m_appInitSuccessful; ///< true if m_tegraApp is initialized successful
+ std::vector<unsigned char> m_WatermarkData; ///< Watermark data discarded after upload
+ float m_WatermarkX;
+ float m_WatermarkY;
+
+ std::vector<int> m_mouseButtons;
+ Q3DStudio::IWindowSystem *m_WindowSystem;
+
+ IAudioPlayer *m_AudioPlayer;
+ QList<KDEvent *> m_pendingEvents;
+
+ void queueMouseEvent(int index, int select, int x, int y)
+ {
+ KDEvent *e = new KDEvent;
+ e->timestamp = GetTimeUST();
+ e->type = KD_EVENT_INPUT_POINTER;
+ e->userptr = reinterpret_cast<void*>(KD_NULL);
+ KDEventInputPointer *dataPtr = reinterpret_cast<KDEventInputPointer *>(&(e->data));
+ dataPtr->index = index;
+ dataPtr->select = select;
+ dataPtr->x = x;
+ dataPtr->y = y;
+
+ m_pendingEvents.append(e);
+ }
+};
+
+///< @brief contructor
+UICViewerApp::UICViewerApp(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer)
+ : m_Impl(*new CUICViewerAppImpl(inAudioPlayer))
+{
+ Q_UNUSED(glContext)
+ m_Impl.m_WindowSystem = new SWindowSystemImpl();
+}
+
+///< @brief destructor
+UICViewerApp::~UICViewerApp()
+{
+ qDeleteAll(m_Impl.m_pendingEvents);
+
+ delete m_Impl.m_AudioPlayer;
+
+ if (m_Impl.m_tegraApp) {
+ disconnect(m_Impl.m_tegraApp->getNDDView()->signalProxy(), 0);
+
+ m_Impl.m_tegraApp->Cleanup();
+ Q3DStudio_virtual_delete(m_Impl.m_tegraApp, CTegraApplication);
+
+ if (GetMemoryManager().GetLineTracker())
+ GetMemoryManager().GetLineTracker()->Report();
+
+ GetMemoryManager().Release();
+ }
+ delete static_cast<SWindowSystemImpl *>(m_Impl.m_WindowSystem);
+}
+
+void UICViewerApp::setOffscreenId(int offscreenID)
+{
+ static_cast<SWindowSystemImpl *>(m_Impl.m_WindowSystem)->m_OffscreenID
+ = offscreenID;
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine())
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->ensureRenderTarget();
+}
+
+bool UICViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFormat &format,
+ int offscreenID, const QString &source,
+ uic::UICAssetVisitor *assetVisitor)
+{
+ bool hasValidPresentationFile = !source.isEmpty();
+
+ QFileInfo info(source);
+ if (!info.exists()) {
+ qWarning("Failed to initialize UICViewer,"
+ " presentation doesn't exist");
+ return false;
+ }
+
+ m_Impl.m_WindowSystem->SetWindowDimensions(SSize(winWidth, winHeight));
+
+ // create our internal application
+ if (hasValidPresentationFile && !m_Impl.m_tegraApp) {
+ WindowRect &theWindowRect = static_cast<SWindowSystemImpl *>(m_Impl.m_WindowSystem)->m_Rect;
+ theWindowRect.x = 0;
+ theWindowRect.y = 0;
+ theWindowRect.width = winWidth;
+ theWindowRect.height = winHeight;
+ static_cast<SWindowSystemImpl *>(m_Impl.m_WindowSystem)->m_OffscreenID = offscreenID;
+ static_cast<SWindowSystemImpl *>(m_Impl.m_WindowSystem)->m_DepthBitCount
+ = format.depthBufferSize();
+
+ // create memory manager
+ // GetMemoryManager( ).Initialize( "GlobalManager", g_ChunkSize, g_ChunkCount );
+ // create internal app
+ m_Impl.m_tegraApp = Q3DStudio_virtual_new(CTegraApplication)
+ CTegraApplication(g_GlobalTimeProvider, *m_Impl.m_WindowSystem,
+ m_Impl.m_AudioPlayer);
+
+ if (assetVisitor)
+ m_Impl.m_tegraApp->getNDDView()->setAssetVisitor(assetVisitor);
+
+ m_Impl.m_appInitSuccessful = m_Impl.m_tegraApp->BeginLoad(source) ? true : false;
+
+ // Simulate killing the application during loading. Useful for finding serious issues with
+ // loading.
+ /*for ( unsigned idx = 0; idx < 100; ++idx )
+ {
+ Sleep( 10*idx );
+ m_Impl.m_tegraApp->Cleanup();
+ Q3DStudio_virtual_delete( m_Impl.m_tegraApp, CTegraApplication );
+
+ m_Impl.m_tegraApp =
+ Q3DStudio_virtual_new(CTegraApplication)CTegraApplication(g_GlobalTimeProvider,
+ *m_Impl.m_WindowSystem);
+ m_Impl.m_appInitSuccessful = m_Impl.m_tegraApp->BeginLoad( viewerArgs ) ? true :
+ false;
+ }*/
+
+ if (m_Impl.m_appInitSuccessful == false) {
+ qCritical() << "UICViewer Launch failure!! Failed to load" << source;
+ return false;
+ }
+
+ m_Impl.m_tegraApp->InitializeGraphics(format);
+
+ SigPresentationReady();
+
+ // Connect signals
+ connect(m_Impl.m_tegraApp->getNDDView()->signalProxy(),
+ &QINDDViewSignalProxy::SigSlideEntered, this, &UICViewerApp::SigSlideEntered);
+ connect(m_Impl.m_tegraApp->getNDDView()->signalProxy(),
+ &QINDDViewSignalProxy::SigSlideExited, this, &UICViewerApp::SigSlideExited);
+
+ DoEnableWatermark();
+ DoSetWatermarkLocation();
+
+ Resize(winWidth, winHeight);
+ }
+ return true;
+}
+
+bool UICViewerApp::IsInitialised(void)
+{
+ return m_Impl.m_tegraApp != NULL && m_Impl.m_appInitSuccessful == true;
+}
+
+int UICViewerApp::GetWindowHeight()
+{
+ return m_Impl.m_WindowSystem->GetWindowDimensions().m_Height;
+}
+
+int UICViewerApp::GetWindowWidth()
+{
+ return m_Impl.m_WindowSystem->GetWindowDimensions().m_Width;
+}
+
+void UICViewerApp::setupSearchPath(std::vector<std::string> &cmdLineArgs)
+{
+ // setup some additional search path
+ // index 0 contains the module directory
+#ifdef _MACOSX
+ char buf[2056];
+ uint32_t bufsize = 2056;
+ _NSGetExecutablePath(buf, &bufsize);
+ std::string theModuleDirectory = buf;
+#else
+ std::string theModuleDirectory = cmdLineArgs[0];
+#endif
+ std::string::size_type pos = theModuleDirectory.rfind('\\');
+ if (pos == std::string::npos)
+ pos = theModuleDirectory.rfind('/');
+
+ // Include the slash
+ theModuleDirectory = theModuleDirectory.substr(0, pos + 1);
+
+ // TODO: Search path needs to be set up properly
+ //NvFAppendSearchPath(theModuleDirectory.c_str());
+}
+
+void UICViewerApp::Render()
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ if (m_Impl.m_appInitSuccessful) {
+ for (KDEvent *e : m_Impl.m_pendingEvents) {
+ m_Impl.m_tegraApp->HandleMessage(e);
+ delete e;
+ }
+ m_Impl.m_pendingEvents.clear();
+#ifdef WIN32
+ HandleController(*m_Impl.m_tegraApp);
+#endif
+
+ m_Impl.m_tegraApp->Render();
+ }
+ }
+}
+
+void UICViewerApp::SaveState()
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ if (m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ ITegraRenderStateManager &manager =
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->GetTegraRenderStateManager();
+
+ manager.SaveAllState();
+ }
+}
+
+void UICViewerApp::RestoreState()
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ if (m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ ITegraRenderStateManager &manager =
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->GetTegraRenderStateManager();
+
+ manager.RestoreAllState();
+ }
+}
+
+void UICViewerApp::EnableWatermarkDDS(const unsigned char *inData, size_t inDataSize)
+{
+ m_Impl.m_WatermarkData.assign(inData, inData + inDataSize);
+ DoEnableWatermark();
+}
+
+void UICViewerApp::SetWatermarkLocation(float x, float y)
+{
+ m_Impl.m_WatermarkX = x;
+ m_Impl.m_WatermarkY = y;
+ DoSetWatermarkLocation();
+}
+
+bool UICViewerApp::WasLastFrameDirty()
+{
+ if (m_Impl.m_tegraApp)
+ return m_Impl.m_tegraApp->WasLastFrameDirty();
+ return false;
+}
+
+void UICViewerApp::DoEnableWatermark()
+{
+ if (m_Impl.m_WatermarkData.size() && m_Impl.m_tegraApp
+ && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->SetWatermarkTextureDataDDS(
+ m_Impl.m_WatermarkData.data(), m_Impl.m_WatermarkData.size());
+ }
+}
+
+void UICViewerApp::DoSetWatermarkLocation()
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine()
+ && m_Impl.m_WatermarkX >= 0.0f) {
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->SetWatermarkLocation(m_Impl.m_WatermarkX,
+ m_Impl.m_WatermarkY);
+ }
+}
+
+void UICViewerApp::Resize(int width, int height)
+{
+ WindowRect &theWindowRect = static_cast<SWindowSystemImpl *>(m_Impl.m_WindowSystem)->m_Rect;
+ theWindowRect.width = width;
+ theWindowRect.height = height;
+
+#if !defined(Q_OS_MACOS)
+ if (m_Impl.m_appInitSuccessful && m_Impl.m_tegraApp
+ && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ KDEvent event;
+ memset(&event, 0, sizeof(KDEvent));
+ event.type = KD_EVENT_WINDOWPROPERTY_CHANGE;
+ event.data.windowproperty.pname = KD_WINDOWPROPERTY_SIZE;
+ m_Impl.m_tegraApp->HandleMessage(&event);
+ }
+#endif
+}
+
+void UICViewerApp::HandleKeyInput(Q3DStudio::EKeyCode inKeyCode, bool isPressed)
+{
+ if (!m_Impl.m_tegraApp || inKeyCode == Q3DStudio::KEY_NOKEY)
+ return;
+
+ CInputEngine *input = m_Impl.m_tegraApp->GetInputEngine();
+ if (input)
+ input->HandleKeyboard(inKeyCode, isPressed);
+}
+
+void UICViewerApp::HandleMouseMove(int x, int y, bool isPressed)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ CInputEngine *input = m_Impl.m_tegraApp->GetInputEngine();
+ if (input) {
+ input->BeginPickInput();
+ input->EndPickInput();
+ input->SetPickInput(static_cast<Q3DStudio::FLOAT>(x), static_cast<Q3DStudio::FLOAT>(y),
+ isPressed);
+ }
+
+}
+
+void UICViewerApp::HandleMousePress(int x, int y, int mouseButton, bool isPressed)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ bool hasButton
+ = std::find(m_Impl.m_mouseButtons.begin(), m_Impl.m_mouseButtons.end(), mouseButton)
+ != m_Impl.m_mouseButtons.end();
+
+ if ((mouseButton == 1 || mouseButton == 2)) {
+ // We keep track of the mouse presses because there are situations where the application
+ // will not give us a mouse
+ // up for each mouse down. This ameleorates the effects of those slightly misbehaving
+ // applications.
+ if (isPressed == hasButton) {
+ bool localIsPressed = !isPressed;
+ // Slightly recursive call in order to handle situations where we aren't getting
+ // the mouse up with the corresponding mouse down or vice versa.
+ HandleMousePress(x, y, mouseButton, localIsPressed);
+ HandleMousePress(x, y, mouseButton, isPressed);
+ } else {
+ if (isPressed) {
+ m_Impl.m_mouseButtons.push_back(mouseButton);
+ qCInfo(qt3ds::TRACE_INFO)
+ << "ViewerApp: Mouse down of frame "
+ << m_Impl.m_tegraApp->GetFrameCount();
+ } else {
+ m_Impl.m_mouseButtons.erase(std::remove(m_Impl.m_mouseButtons.begin(),
+ m_Impl.m_mouseButtons.end(), mouseButton),
+ m_Impl.m_mouseButtons.end());
+ }
+
+ CInputEngine *input = m_Impl.m_tegraApp->GetInputEngine();
+
+ if (input) {
+ input->BeginPickInput();
+ input->SetPickInput(static_cast<Q3DStudio::FLOAT>(x),
+ static_cast<Q3DStudio::FLOAT>(y), isPressed);
+ input->EndPickInput();
+
+ m_Impl.queueMouseEvent(mouseButton, isPressed ? 1 : 0, x, y);
+ }
+ }
+ }
+}
+
+void UICViewerApp::HandleMouseWheel(int x, int y, int orientation, int numSteps)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ CInputEngine *input = m_Impl.m_tegraApp->GetInputEngine();
+ if (input) {
+ input->SetPickInput(static_cast<Q3DStudio::FLOAT>(x), static_cast<Q3DStudio::FLOAT>(y), 0);
+ input->SetScrollValue(orientation == 0 ? VSCROLLWHEEL : HSCROLLWHEEL, numSteps);
+ }
+}
+
+void UICViewerApp::GoToSlideByName(const char *elementPath, const char *slideName)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->GoToSlideByName(elementPath, slideName);
+}
+
+void UICViewerApp::GoToSlideByIndex(const char *elementPath, const int slideIndex)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->GoToSlideByIndex(elementPath, slideIndex);
+}
+
+void UICViewerApp::GoToSlideRelative(const char *elementPath, const bool next, const bool wrap)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->GoToSlideRelative(elementPath, next, wrap);
+}
+
+bool UICViewerApp::GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName)
+{
+ if (!m_Impl.m_tegraApp)
+ return false;
+
+ return m_Impl.m_tegraApp->GetSlideInfo(elementPath, currentIndex, previousIndex,
+ currentName, previousName);
+}
+
+void UICViewerApp::SetPresentationActive(const char *presId, const bool active)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->SetPresentationAttribute(presId, nullptr, active ? "True" : "False");
+}
+
+void UICViewerApp::GoToTime(const char *elementPath, const float time)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->GoToTime(elementPath, time);
+}
+
+void UICViewerApp::PlaySoundFile(const char *soundPath)
+{
+ if (!m_Impl.m_AudioPlayer || !soundPath)
+ return;
+
+ m_Impl.m_AudioPlayer->PlaySoundFile(soundPath);
+}
+
+void UICViewerApp::SetAttribute(const char *elementPath, const char *attributeName,
+ const char *value)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->SetAttribute(elementPath, attributeName, value);
+}
+
+bool UICViewerApp::GetAttribute(const char *elementPath, const char *attributeName, void *value)
+{
+ if (!m_Impl.m_tegraApp)
+ return false;
+
+ return m_Impl.m_tegraApp->GetAttribute(elementPath, attributeName, value);
+}
+
+void UICViewerApp::FireEvent(const char *elementPath, const char *evtName)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->FireEvent(elementPath, evtName);
+}
+
+bool UICViewerApp::PeekCustomAction(std::string &outElementPath, std::string &outActionName)
+{
+ if (!m_Impl.m_tegraApp)
+ return false;
+
+ char *theElementPath = NULL;
+ char *theActioName = NULL;
+ bool retVal = m_Impl.m_tegraApp->PeekCustomAction(theElementPath, theActioName);
+
+ if (theElementPath)
+ outElementPath = theElementPath;
+ if (theActioName)
+ outActionName = theActioName;
+
+ return retVal;
+}
+
+bool UICViewerApp::RegisterScriptCallback(ViewerCallbackType::Enum inCallbackType,
+ const qml_Function inCallback, void *inUserData)
+{
+ if (!m_Impl.m_tegraApp)
+ return false;
+
+ // convert to int
+ int callbackType = 0;
+ if (inCallbackType == UICViewer::ViewerCallbackType::CALLBACK_ON_INIT)
+ callbackType = 1;
+ else if (inCallbackType == UICViewer::ViewerCallbackType::CALLBACK_ON_UPDATE)
+ callbackType = 2;
+ else
+ return false;
+
+ bool retVal = m_Impl.m_tegraApp->RegisterScriptCallback(callbackType, inCallback, inUserData);
+
+ return retVal;
+}
+
+void UICViewerApp::SetScaleMode(ViewerScaleModes::Enum inScale)
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->SetScaleMode(
+ static_cast<TegraRenderScaleModes::Enum>(inScale));
+ }
+}
+
+ViewerScaleModes::Enum UICViewerApp::GetScaleMode()
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ return static_cast<ViewerScaleModes::Enum>(
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->GetScaleMode());
+ }
+
+ return ViewerScaleModes::ExactSize;
+}
+
+void UICViewerApp::setMatteColor(const QColor &color)
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->SetMatteColor(
+ qt3ds::QT3DSVec4(color.redF(), color.greenF(),
+ color.blueF(), color.alphaF()));
+ }
+}
+
+void UICViewerApp::setShowOnScreenStats(bool inShow)
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine())
+ m_Impl.m_tegraApp->getNDDView()->showOnScreenStats(inShow);
+}
+
+void UICViewerApp::SetShadeMode(ViewerShadeModes::Enum inShadeMode)
+{
+ if (m_Impl.m_tegraApp && m_Impl.m_tegraApp->GetTegraRenderEngine()) {
+ StaticAssert<ViewerShadeModes::Shaded == TegraRenderShadeModes::Shaded>::valid_expression();
+ StaticAssert<ViewerShadeModes::ShadedWireframe
+ == TegraRenderShadeModes::ShadedWireframe>::valid_expression();
+ StaticAssert<ViewerShadeModes::Wireframe
+ == TegraRenderShadeModes::Wireframe>::valid_expression();
+
+ m_Impl.m_tegraApp->GetTegraRenderEngine()->SetShadeMode(
+ static_cast<TegraRenderShadeModes::Enum>(inShadeMode));
+ }
+}
+
+void UICViewerApp::SetGlobalAnimationTime(qint64 inMilliSecs)
+{
+ if (!m_Impl.m_tegraApp)
+ return;
+
+ m_Impl.m_tegraApp->SetGlobalAnimationTime(inMilliSecs);
+}
+
+UICViewerApp &UICViewerApp::Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer)
+{
+ return *Q3DStudio_virtual_new(UICViewerApp) UICViewerApp(glContext, inAudioPlayer);
+}
+
+void UICViewerApp::Release()
+{
+ Q3DStudio_virtual_delete(this, UICViewerApp);
+}
+
+} // end namespace
diff --git a/src/Runtime/Source/Viewer/UICViewerApp.h b/src/Runtime/Source/Viewer/UICViewerApp.h
new file mode 100644
index 00000000..68dccd95
--- /dev/null
+++ b/src/Runtime/Source/Viewer/UICViewerApp.h
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UICVIEWER_H
+#define UICVIEWER_H
+
+#include "qt3dsruntimeglobal.h"
+
+#include <string>
+#include <vector>
+#include <QObject>
+
+#include "UICInputDefs.h"
+
+#include <QtGui/qsurfaceformat.h>
+
+namespace Q3DStudio {
+class CTegraApplication;
+class IWindowSystem;
+class IAudioPlayer;
+}
+
+namespace uic {
+class UICAssetVisitor
+{
+public:
+ virtual void visit(const char *path) = 0;
+ virtual void visit(const char *type, const char *id, const char *src, const char *args) = 0;
+};
+}
+
+namespace UICViewer {
+
+typedef void (*qml_Function)(void *inUserData);
+
+// not must match the NDDRuntime see
+// UICQmlEngine.h
+struct ViewerCallbackType
+{
+ enum Enum {
+ CALLBACK_ON_INIT = 1,
+ CALLBACK_ON_UPDATE = 2,
+ };
+};
+
+struct ViewerContextType
+{
+ enum Enum { GL_ES2 = 0, GL_ES3, GL_ES31, GL_ES32, GL_2, GL_3_3, GL_4 };
+};
+
+struct ViewerScaleModes
+{
+ enum Enum {
+ ExactSize = 0, // Ensure the viewport is exactly same size as application
+ ScaleToFit = 1, // Resize viewport keeping aspect ratio
+ ScaleToFill = 2, // Resize viewport to entire window
+ };
+};
+
+struct ViewerShadeModes
+{
+ enum Enum {
+ Shaded = 0, // Geometry is shaded only
+ ShadedWireframe = 1, // Wireframe is drawn on top shaded geometry
+ Wireframe = 2, // Wireframe only
+ };
+};
+
+class CUICViewerAppImpl;
+class QT3DS_RUNTIME_API UICViewerApp : public QObject
+{
+ Q_OBJECT
+private:
+ UICViewerApp(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer);
+ ~UICViewerApp();
+
+public:
+ /**
+ * @brief Initialize viewer app
+ *
+ * @param[in] winWidth window width
+ * @param[in] winHeight window height
+ * @param[in] format OpenGL API version
+ * @param[in] offscreenID ID of an OpenGL FBO we should render to by default
+ * @param[in] source string to presentation source
+ *
+ * @return true on success
+ */
+ bool InitializeApp(int winWidth, int winHeight, const QSurfaceFormat& format,
+ int offscreenID, const QString &source,
+ uic::UICAssetVisitor *assetVisitor = nullptr);
+
+ bool IsInitialised(void);
+ void setOffscreenId(int offscreenID);
+
+
+ /*
+ * @brief handle window resize
+ *
+ * @param[in] width new width
+ * @param[in] height new size
+ *
+ * @return no return
+ */
+ void Resize(int width, int height);
+
+ /*
+ * @brief does the actual scene rendering
+ *
+ * @return no return
+ */
+ void Render();
+
+ /*
+ * @brief handle keyboard input
+ *
+ * @param[in] keyEvent event
+ * @param[in] isPressed true if key pressed
+ *
+ * @return no return
+ */
+ void HandleKeyInput(Q3DStudio::EKeyCode inKeyCode, bool isPressed);
+
+ /*
+ * @brief handle mouse move input
+ *
+ * @param[in] x mouse pos x
+ * @param[in] y mouse pos y
+ * @param[in] mouseButton mouse button id
+ * @param[in] isPressed true if key pressed
+ *
+ * @return no return
+ */
+ void HandleMouseMove(int x, int y, bool isPressed);
+
+ /*
+ * @brief handle mouse press events
+ *
+ * @param[in] x mouse pos x
+ * @param[in] y mouse pos y
+ * @param[in] mouseButton mouse button id
+ * @param[in] isPressed true if key pressed
+ *
+ * @return no return
+ */
+ void HandleMousePress(int x, int y, int mouseButton, bool isPressed);
+
+ /*
+ * @brief handle mouse wheel events
+ *
+ * @param[in] x mouse pos x
+ * @param[in] y mouse pos y
+ * @param[in] orientation 0 vertical, 1 horizontal
+ * @param[in] numSteps how much the wheel has turned
+ *
+ * @return no return
+ */
+ void HandleMouseWheel(int x, int y, int orientation, int numSteps);
+
+ /*
+ * @brief Scale scene to adjsut to window size regarding width and height
+ *
+ * @param[in] inScale true if scale false if unscale
+ *
+ * @return no return
+ */
+ void SetScaleMode(ViewerScaleModes::Enum inScaleMode);
+
+ ViewerScaleModes::Enum GetScaleMode();
+
+ void setMatteColor(const QColor &color);
+ void setShowOnScreenStats(bool s);
+
+ /*
+ * @brief Set the shading mode
+ *
+ * @param[in] inShadeMode the selected shade mode
+ *
+ * @return no return
+ */
+ void SetShadeMode(ViewerShadeModes::Enum inShadeMode);
+
+ /*
+ * @brief Save current render state
+ *
+ * @return no return
+ */
+ void SaveState();
+ /*
+ * @brief Restore current render state
+ *
+ * @return no return
+ */
+ void RestoreState();
+
+ /// event call back slots
+
+ /*
+ * @brief Go to a slide by name
+ *
+ * @param[in] elementPath where to find the element
+ * @param[in] slideName slide name
+ *
+ * @return no return
+ */
+ void GoToSlideByName(const char *elementPath, const char *slideName);
+
+ /*
+ * @brief Go to a slide by index
+ *
+ * @param[in] elementPath where to find the element
+ * @param[in] slideIndex slide index
+ *
+ * @return no return
+ */
+ void GoToSlideByIndex(const char *elementPath, const int slideIndex);
+
+ /*
+ * @brief Go to relative slide
+ *
+ * @param[in] elementPath where to find the element
+ * @param[in] next next or previous
+ * @param[in] wrap wrap to beginning if end is reached
+ *
+ * @return no return
+ */
+ void GoToSlideRelative(const char *elementPath, const bool next, const bool wrap);
+
+ bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName);
+
+ /*
+ * @brief Set presentation active or inactive
+ *
+ * @param[in] presId presentation id (name without .uip)
+ * @param[in] active set active or inactive
+ *
+ * @return no return
+ */
+ void SetPresentationActive(const char *presId, const bool active);
+
+ /*
+ * @brief Go to a certain time
+ *
+ * @param[in] elementPath where to find the element
+ * @param[in] time time to move
+ *
+ * @return no return
+ */
+ void GoToTime(const char *elementPath, const float time);
+
+ /*
+ * @brief Play a sound
+ *
+ * @param[in] soundPath sound file to play
+ *
+ * @return no return
+ */
+ void PlaySoundFile(const char *soundPath);
+
+ /*
+ * @brief Set attribute values
+ *
+ * @param[in] elementPath where to find the element
+ * @param[in] attributeName attribute name
+ * @param[in] value new value of the attribute
+ *
+ * @return no return
+ */
+ void SetAttribute(const char *elementPath, const char *attributeName, const char *value);
+
+ /*
+ * @brief Get attribute values
+ *
+ * @param[in] elementPath where to find the element
+ * @param[in] attributeName attribute name
+ * @param[out] value current attribute values
+ *
+ * @return true if successful
+ */
+ bool GetAttribute(const char *elementPath, const char *attributeName, void *value);
+
+ /*
+ * @brief Fire an event
+ *
+ * @param[in] elementPath where to find the element to fire the event on
+ * @param[in] evtName the string that identifies and defines the event
+ *
+ * @return no return
+ */
+ void FireEvent(const char *elementPath, const char *evtName);
+
+ /*
+ * @brief Peek a custom action from the queue
+ * Note the action is remvoved from the queue
+ *
+ * @param[out] outElementPath element path
+ * @param[out] actionName action name
+ *
+ * @return true if action available
+ */
+ bool PeekCustomAction(std::string &outElementPath, std::string &actionName);
+
+ /**
+ * @brief Register a callback
+ *
+ * @param[in] callbackType callback type
+ * @param[in] inCallback pointer to callback
+ * @param[in] inCallback pointer to user data
+ *
+ * @return true on success
+ */
+ bool RegisterScriptCallback(ViewerCallbackType::Enum callbackType,
+ const qml_Function inCallback, void *inUserData);
+
+ void EnableWatermarkDDS(const unsigned char *inData, size_t inDataSize);
+
+ void SetWatermarkLocation(float x, float y);
+
+ bool WasLastFrameDirty();
+
+ int GetWindowHeight();
+ int GetWindowWidth();
+
+ void SetGlobalAnimationTime(qint64 inMilliSecs);
+
+private:
+ /*
+ * @brief parse command line arguments this fills in our
+ * global command line variables
+ *
+ * @param[in] cmdLineArgs string to command line parameter
+ *
+ * @return no return
+ */
+ void handleCmdLineArguments(std::vector<std::string> &cmdLineArgs);
+ /*
+ * @brief setup search path.
+ * This functions setup additonal search path for resoruces
+ * and the lua engine
+ *
+ * @param[in] cmdLineArgs string to command line parameter
+ *
+ * @return no return
+ */
+ void setupSearchPath(std::vector<std::string> &cmdLineArgs);
+
+ void DoEnableWatermark();
+
+ void DoSetWatermarkLocation();
+
+private:
+ CUICViewerAppImpl &m_Impl;
+
+public:
+ static UICViewerApp &Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer = 0);
+ void Release();
+
+Q_SIGNALS:
+ void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
+ void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name);
+ void SigPresentationReady();
+};
+
+} // end namespace
+
+#endif // UICVIEWER_H
diff --git a/src/Runtime/Source/Viewer/UICViewerTimer.h b/src/Runtime/Source/Viewer/UICViewerTimer.h
new file mode 100644
index 00000000..cf7ac032
--- /dev/null
+++ b/src/Runtime/Source/Viewer/UICViewerTimer.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UICELAPSED_TIMER_H
+#define UICELAPSED_TIMER_H
+#include <QElapsedTimer>
+
+namespace UICViewer {
+
+///< @brief this class implementes a elapsed timer using QElapsedTimer
+class UICElapsedTimer
+{
+public:
+ QElapsedTimer m_elapsedTimer;
+ QElapsedTimer::ClockType m_clockType;
+
+ UICElapsedTimer()
+ {
+ m_clockType = QElapsedTimer::clockType();
+ reset();
+ }
+
+ void reset() { m_elapsedTimer.start(); }
+
+ qint64 getNanoSeconds()
+ {
+ qint64 time = m_elapsedTimer.nsecsElapsed();
+ reset();
+ return time;
+ }
+};
+
+///< @brief this class implementes a timer using QElapsedTimer
+class UICTimer
+{
+public:
+ QElapsedTimer m_timer;
+
+ UICTimer() { start(); }
+
+ void start() { m_timer.start(); }
+
+ qint64 getNanoSeconds() { return static_cast<qint64>(m_timer.elapsed() * 1000 * 1000); }
+};
+
+///< @brief this class implementes a circular buffer
+template <typename TDataType, unsigned long TBufferSize = 20>
+struct NumericCircularBuffer
+{
+ unsigned long m_TotalNumElements; ///< holds the current number of elements
+ unsigned long m_NumElements; ///< restricts the size to TBufferSize and wrappes around
+ unsigned long m_NextIndex; ///< next index
+ TDataType m_RunningTotal; ///< summed value of all entries
+ TDataType m_Elements[TBufferSize]; ///< element buffer
+
+ NumericCircularBuffer() { clear(); }
+ void clear()
+ {
+ m_TotalNumElements = 0;
+ m_NumElements = 0;
+ m_NextIndex = 0;
+ m_RunningTotal = 0;
+ memset(m_Elements, 0, sizeof(TDataType) * TBufferSize);
+ }
+
+ void push_back(const TDataType &data)
+ {
+ if (m_NumElements < TBufferSize)
+ ++m_NumElements;
+ else
+ m_RunningTotal -= m_Elements[m_NextIndex];
+ m_RunningTotal += data;
+ ++m_TotalNumElements;
+ m_Elements[m_NextIndex] = data;
+ m_NextIndex = (m_NextIndex + 1) % TBufferSize;
+ }
+ unsigned long size() const { return m_NumElements; }
+ TDataType average() const
+ {
+ TDataType mySize = ((TDataType)size());
+ if (mySize)
+ return m_RunningTotal / mySize;
+ return 0;
+ }
+
+ unsigned long getTotalItems() const { return m_TotalNumElements; }
+
+ static unsigned long getBufferSize() { return TBufferSize; }
+};
+
+} // end namspace
+
+#endif // UICELAPSED_TIMER_H
diff --git a/src/Runtime/Source/Viewer/qt3dsruntimeglobal.h b/src/Runtime/Source/Viewer/qt3dsruntimeglobal.h
new file mode 100644
index 00000000..6732c85d
--- /dev/null
+++ b/src/Runtime/Source/Viewer/qt3dsruntimeglobal.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DSRUNTIMEGLOBAL_H
+#define QT3DSRUNTIMEGLOBAL_H
+
+#include <QtCore/QtGlobal>
+
+#ifndef _INTEGRITYPLATFORM
+#if defined QT3DS_RUNTIME_EXPORTS
+#define QT3DS_RUNTIME_API Q_DECL_EXPORT
+#else
+#define QT3DS_RUNTIME_API Q_DECL_IMPORT
+#endif
+#else
+#define QT3DS_RUNTIME_API
+#endif
+
+#endif // QT3DSRUNTIMEGLOBAL_H
diff --git a/src/Runtime/commoninclude.pri b/src/Runtime/commoninclude.pri
new file mode 100644
index 00000000..14fca023
--- /dev/null
+++ b/src/Runtime/commoninclude.pri
@@ -0,0 +1,87 @@
+include($$PWD/../commonplatform.pri)
+
+contains(TEMPLATE, lib) {
+ load(qt_helper_lib)
+ # qt_helper_lib assumes non-qt lib, so it clears qt from config - reset that
+ CONFIG += qt exceptions
+}
+QT += core gui openglextensions
+
+DEFINES += COMPILED_FROM_DSP \
+ UICDM_USE_NVLOG UICDM_META_DATA_NO_SIGNALS
+
+INCLUDEPATH += \
+ $$PWD/Source \
+ $$PWD/Source/UICRender/Include \
+ $$PWD/Source/RuntimeUICDM/Include \
+ $$PWD/Source/Runtime/Include \
+ $$PWD/Source/System/Include \
+ $$PWD/Source/Engine/Include \
+ $$PWD/Source/Qt3DSFoundation/Include \
+ $$PWD/Source/Qt3DSRender/Include \
+ $$PWD/Source/Qt3DSRender/Source \
+ $$PWD/Source/Qt3DSRender/Source/gl2 \
+ $$PWD/Source/Qt3DSRender/Source/gl3 \
+ $$PWD/Source/Qt3DSRender/Source/glg \
+ $$PWD/Source/UIPParser/Include \
+ $$PWD/Source/UICState/Include \
+ $$PWD/Source/UICState/Editor \
+ $$PWD/Source/UICState/Debugger \
+ $$PWD/Source/UICEvent/Include \
+ $$PWD/Source/UICEvent/InternalInclude \
+ $$PWD/Source/UICRender/GraphObjects \
+ $$PWD/Source/UICRender/ResourceManager \
+ $$PWD/Source/Viewer \
+ $$PWD/Source/Viewer/PerfLog \
+ $$PWD/../Authoring/UICIMP/UICImportLib \
+ $$PWD/../Authoring/UICDM \
+ $$PWD/../Authoring/UICDM/Systems \
+ $$PWD/../Authoring/UICDM/Systems/Cores \
+ ../3rdparty/EASTL/UnknownVersion/include \
+ ../3rdparty/Lua/UnknownVersion/src \
+ ../3rdparty/utf8cpp/2.3.2/source \
+ ../3rdparty/color \
+ ../3rdparty/RuntimePlatformSpecific/$$PlatformSpecificDir/PlatformLibs \
+ $$PWD/../QtExtras/qmlstreamer
+
+# TODO: Investigate whether these can be moved to commonplatform
+win32 {
+CONFIG += nostrictstrings
+QMAKE_CXXFLAGS += /EHsc /GA
+QMAKE_CFLAGS += /EHsc /GA
+INCLUDEPATH += \
+ $$PWD/Source/PlatformSpecific/Windows/Qt3DSLibs
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Windows/Qt3DSLibs
+}
+
+linux {
+QMAKE_CXXFLAGS += -fpermissive
+QMAKE_CFLAGS += -fpermissive
+INCLUDEPATH += \
+ $$PWD/Source/Qt3DSFoundation/Include/foundation/linux \
+ $$PWD/Source/Qt3DSFoundation/Source/foundation/linux \
+ $$PWD/Source/PlatformSpecific/Linux/Qt3DSLibs
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs
+}
+
+integrity {
+INCLUDEPATH += \
+ $$PWD/Source/Qt3DSFoundation/Include/foundation/linux \
+ $$PWD/Source/Qt3DSFoundation/Source/foundation/linux \
+ $$PWD/Source/PlatformSpecific/Linux/Qt3DSLibs
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Linux/Qt3DSLibs
+}
+
+macos {
+INCLUDEPATH += \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Macos/Qt3DSLibs \
+ $$PWD/Source/PlatformSpecific/Macos/Qt3DSLibs
+
+}
+
+android {
+INCLUDEPATH += \
+ $$PWD/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Android/jni/Qt3DSLibs \
+ $$PWD/../3rdparty/RuntimePlatformSpecific/Android/jni
+}
diff --git a/src/Runtime/platformres.qrc b/src/Runtime/platformres.qrc
new file mode 100644
index 00000000..af8a564b
--- /dev/null
+++ b/src/Runtime/platformres.qrc
@@ -0,0 +1,4 @@
+<RCC>
+ <qresource prefix="/">
+ </qresource>
+</RCC>
diff --git a/src/Runtime/res.qrc b/src/Runtime/res.qrc
new file mode 100644
index 00000000..8941190d
--- /dev/null
+++ b/src/Runtime/res.qrc
@@ -0,0 +1,98 @@
+<RCC>
+ <qresource prefix="/">
+ <file>res/DataModelMetadata/en-us/MetaData.xml</file>
+ <file>res/effectlib/abbeNumberIOR.glsllib</file>
+ <file>res/effectlib/anisotropyConversion.glsllib</file>
+ <file>res/effectlib/average.glsllib</file>
+ <file>res/effectlib/blendColorLayers.glsllib</file>
+ <file>res/effectlib/blur.glsllib</file>
+ <file>res/effectlib/calculateRoughness.glsllib</file>
+ <file>res/effectlib/coordinateSource.glsllib</file>
+ <file>res/effectlib/cube.glsllib</file>
+ <file>res/effectlib/customCurveLayer.glsllib</file>
+ <file>res/effectlib/customMaterial.glsllib</file>
+ <file>res/effectlib/customMaterialFragBody.glsllib</file>
+ <file>res/effectlib/customMaterialFragBodyAO.glsllib</file>
+ <file>res/effectlib/defaultMaterialFresnel.glsllib</file>
+ <file>res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib</file>
+ <file>res/effectlib/funcsampleAreaGlossyDefault.glsllib</file>
+ <file>res/effectlib/funccomputeMicroHit.glsllib</file>
+ <file>res/effectlib/funcgetTransformedUVCoords.glsllib</file>
+ <file>res/effectlib/funcareaLightVars.glsllib</file>
+ <file>res/effectlib/funcspecularBSDF.glsllib</file>
+ <file>res/effectlib/funccalculateDiffuseAreaOld.glsllib</file>
+ <file>res/effectlib/funccalculatePointLightAttenuation.glsllib</file>
+ <file>res/effectlib/defaultMaterialLighting.glsllib</file>
+ <file>res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib</file>
+ <file>res/effectlib/depthpass.glsllib</file>
+ <file>res/effectlib/dfTint.glsllib</file>
+ <file>res/effectlib/funcdiffuseReflectionBSDF.glsllib</file>
+ <file>res/effectlib/diffuseReflectionBSDF.glsllib</file>
+ <file>res/effectlib/diffuseTransmissionBSDF.glsllib</file>
+ <file>res/effectlib/directionalFactor.glsllib</file>
+ <file>res/effectlib/effect.glsllib</file>
+ <file>res/effectlib/evalBakedShadowMap.glsllib</file>
+ <file>res/effectlib/evalEnvironmentMap.glsllib</file>
+ <file>res/effectlib/evalLightmaps.glsllib</file>
+ <file>res/effectlib/fileBumpTexture.glsllib</file>
+ <file>res/effectlib/fileDisplacementTexture.glsllib</file>
+ <file>res/effectlib/fileTexture.glsllib</file>
+ <file>res/effectlib/flakeNoiseBumpTexture.glsllib</file>
+ <file>res/effectlib/flakeNoiseTexture.glsllib</file>
+ <file>res/effectlib/fresnelLayer.glsllib</file>
+ <file>res/effectlib/Fxaa3_11.glsllib</file>
+ <file>res/effectlib/Fxaa3_8.glsllib</file>
+ <file>res/effectlib/gradient3Recolor.glsllib</file>
+ <file>res/effectlib/gradient3Texture.glsllib</file>
+ <file>res/effectlib/gradientGetPosition.glsllib</file>
+ <file>res/effectlib/luminance.glsllib</file>
+ <file>res/effectlib/microfacetBSDF.glsllib</file>
+ <file>res/effectlib/miNoise.glsllib</file>
+ <file>res/effectlib/monoChannel.glsllib</file>
+ <file>res/effectlib/normalizedMix.glsllib</file>
+ <file>res/effectlib/perlinNoise.glsllib</file>
+ <file>res/effectlib/perlinNoiseBumpTexture.glsllib</file>
+ <file>res/effectlib/perlinNoiseTexture.glsllib</file>
+ <file>res/effectlib/physGlossyBSDF.glsllib</file>
+ <file>res/effectlib/random255.glsllib</file>
+ <file>res/effectlib/refraction.glsllib</file>
+ <file>res/effectlib/rotationTranslationScale.glsllib</file>
+ <file>res/effectlib/sampleArea.glsllib</file>
+ <file>res/effectlib/funcsampleLightVars.glsllib</file>
+ <file>res/effectlib/sampleLight.glsllib</file>
+ <file>res/effectlib/sampleProbe.glsllib</file>
+ <file>res/effectlib/screenSpaceAO.glsllib</file>
+ <file>res/effectlib/screenSpaceDO.glsllib</file>
+ <file>res/effectlib/shadowMapping.glsllib</file>
+ <file>res/effectlib/shadowMappingFragment.glsllib</file>
+ <file>res/effectlib/simpleGlossyBSDF.glsllib</file>
+ <file>res/effectlib/SMAA.glsllib</file>
+ <file>res/effectlib/specularBSDF.glsllib</file>
+ <file>res/effectlib/spotEdf.glsllib</file>
+ <file>res/effectlib/square.glsllib</file>
+ <file>res/effectlib/SSAOCustomMaterial.glsllib</file>
+ <file>res/effectlib/tangentSpaceNormalTexture.glsllib</file>
+ <file>res/effectlib/tessellationLinear.glsllib</file>
+ <file>res/effectlib/tessellationLinearCM.glsllib</file>
+ <file>res/effectlib/tessellationNPatch.glsllib</file>
+ <file>res/effectlib/tessellationNPatchCM.glsllib</file>
+ <file>res/effectlib/tessellationPath.glsllib</file>
+ <file>res/effectlib/tessellationPhong.glsllib</file>
+ <file>res/effectlib/tessellationPhongCM.glsllib</file>
+ <file>res/effectlib/textureCoordinateInfo.glsllib</file>
+ <file>res/effectlib/transformCoordinate.glsllib</file>
+ <file>res/effectlib/uicDefaultMaterialFileBumpTexture.glsllib</file>
+ <file>res/effectlib/uicDefaultMaterialFileDisplacementTexture.glsllib</file>
+ <file>res/effectlib/uicDefaultMaterialFileNormalTexture.glsllib</file>
+ <file>res/effectlib/vertexFragmentBase.glsllib</file>
+ <file>res/effectlib/viewProperties.glsllib</file>
+ <file>res/effectlib/weightedLayer.glsllib</file>
+ <file>res/effectlib/wireframeCM.glsllib</file>
+ <file>res/primitives/Cone.mesh</file>
+ <file>res/primitives/Cube.mesh</file>
+ <file>res/primitives/Cylinder.mesh</file>
+ <file>res/primitives/Rectangle.mesh</file>
+ <file>res/primitives/Sphere.mesh</file>
+ <file>res/Font/TitilliumWeb-Regular.ttf</file>
+ </qresource>
+</RCC>
diff --git a/src/Runtime/res/DataModelMetadata/en-us/MetaData.xml b/src/Runtime/res/DataModelMetadata/en-us/MetaData.xml
new file mode 100644
index 00000000..dc41f912
--- /dev/null
+++ b/src/Runtime/res/DataModelMetadata/en-us/MetaData.xml
@@ -0,0 +1,503 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<MetaData>
+ <Category name="Custom Events" description="Custom events exposed on the behavior." icon="Objects-Behavior-Normal.png" highlightIcon="Objects-Behavior-Normal.png" />
+ <Category name="Default" description="Default events on all objects" icon="Objects-Folder-Normal.png" highlightIcon="Objects-Folder-Normal.png" />
+ <Category name="Gesture" description="Input from the touch screen or the mouse" icon="Objects-Folder-Normal.png" highlightIcon="Objects-Folder-Normal.png" />
+ <Category name="Slide" description="Events generated when a slide is changing." icon="Objects-Folder-Normal.png" highlightIcon="Objects-Folder-Normal.png" />
+ <Category name="Asset" description="Handlers exposed on the asset." icon="Objects-Folder-Normal.png" highlightIcon="Objects-Folder-Normal.png" />
+ <Category name="Custom Handlers" description="Custom Handlers exposed on the behavior." icon="Objects-Behavior-Normal.png" highlightIcon="Objects-Behavior-Normal.png" />
+ <Category name="Time" description="Handlers exposed on the asset's time." icon="Objects-Folder-Normal.png" highlightIcon="Objects-Folder-Normal.png" />
+ <Alias>
+ <Property name="name" formalName="Name" type="String" default="Alias" hidden="True" />
+ <Property name="referencednode" formalName="Reference" description="Original element (e.g. group, component, model) to clone" type="ObjectRef" />
+ </Alias>
+ <Asset>
+ <Property name="starttime" formalName="Start Time" type="Long" hidden="True" />
+ <Property name="endtime" formalName="End Time" type="Long" default="10000" hidden="True" />
+ <Property name="eyeball" formalName="Visible" type="Boolean" default="True" hidden="True" />
+ <Property name="shy" formalName="Shy" type="Boolean" hidden="True" />
+ <Property name="sourcepath" type="String" hidden="True" />
+ <Property name="importfile" type="String" hidden="True" />
+
+ <Handler name="Set Property" category="Asset" description="Set a property to a new value.">
+ <Argument name="Property Name" formalName="Property" description="Property to change" type="Slide" argumentType="Property" />
+ <Argument name="Property Value" formalName="New Value" description="New value for the property" type="None" argumentType="Dependent" />
+ </Handler>
+ <Handler name="Fire Event" category="Asset" description="Fire an event on the target.">
+ <Argument name="Event" description="The event to fire" type="None" argumentType="Event" />
+ </Handler>
+ <Handler name="Emit Signal" category="Asset" description="Emit a Signal.">
+ <Argument name="Signal Name" description="The signal to emit" type="String" argumentType="Signal" />
+ </Handler>
+ <Handler name="Play Sound" category="Asset" description="Play a sound file.">
+ <Argument name="Sound File" description="The sound file to play" type="String" argumentType="Sound" />
+ </Handler>
+ </Asset>
+ <Behavior>
+ <Property name="name" formalName="Name" type="String" default="Behavior" hidden="True" />
+ </Behavior>
+ <Camera>
+
+ <Property name="name" formalName="Name" type="String" default="Camera" hidden="True" />
+ <Property name="opacity" formalName="Opacity" min="0" max="100" default="100" hidden="True" />
+ <Property name="orthographic" formalName="Orthographic" description="Remove all perspective from the camera?" type="Boolean" animatable="False" />
+ <Property name="position" formalName="Position" description="Location in local space" type="Vector" default="0 0 -600" />
+ <Property name="rotation" formalName="Rotation" description="Rotation around local axes" type="Rotation" />
+ <Property name="scale" formalName="Scale" description="Size adjustments along local axes" type="Vector" default="1 1 1" />
+ <Property name="pivot" formalName="Pivot" description="Offset of the contents away from the local center" type="Vector" />
+ <Property name="fov" formalName="Field of View" description="Viewing angle of the camera (how much it can see)" min="1" max="180" default="60">
+ <ShowIfEqual property="orthographic" value="False"/>
+ </Property>
+ <Property name="clipnear" formalName="Clipping Start" description="Near distance at which objects disappear" min="1" max="1000" default="10" />
+ <Property name="clipfar" formalName="Clipping End" description="Far distance at which objects disappear" default="5000" />
+ <Property name="scalemode" formalName="Scale Mode" description="Render more content as the layer expands (same size) or scale up the content (fit)" list="Same Size:Fit:Fit Horizontal:Fit Vertical" default="Fit" />
+ <Property name="scaleanchor" formalName="Scale Anchor" description="Corner of the content to pin as the layer size changes" list="Center:N:NE:E:SE:S:SW:W:NW" default="Center"/>
+ </Camera>
+ <Component>
+ <Property name="name" formalName="Name" type="String" default="Component" hidden="True" />
+ </Component>
+ <Effect>
+ <Property name="name" formalName="Name" type="String" default="Effect" hidden="True" />
+ </Effect>
+ <Group>
+ <Property name="name" formalName="Name" type="String" default="Group" hidden="True" />
+ <Property name="sourcepath" formalName="Import" description="Path to the source of this group" type="Import" />
+ </Group>
+ <Image>
+ <!--Images and materials don't have lifetimes, so we use a value that we know just won't cause any issues-->
+ <Property name="endtime" formalName="End Time" type="Long" default="2147483647" hidden="True" />
+ <Property name="name" formalName="Name" type="String" default="Image" hidden="True" />
+ <Property name="scaleu" formalName="U Repeat" description="Number of times the image is tiled on the U direction of the material" default="1" />
+ <Property name="scalev" formalName="V Repeat" description="Number of times the image is tiled on the V direction of the material" default="1" />
+ <Property name="mappingmode" formalName="Texture Mapping" description="How the image is applied to the material" list="UV Mapping:Environmental Mapping:Light Probe" default="UV Mapping" />
+ <Property name="tilingmodehorz" formalName="U Tiling" description="How the image is tiled in the U direction" list="Tiled:Mirrored:No Tiling" default="No Tiling" />
+ <Property name="tilingmodevert" formalName="V Tiling" description="How the image is tiled in the V direction" list="Tiled:Mirrored:No Tiling" default="No Tiling" />
+ <Property name="rotationuv" formalName="UV Rotation" description="Rotate the image's coordinates" />
+ <Property name="positionu" formalName="U Position" description="Offset of the image along the U direction of the material" />
+ <Property name="positionv" formalName="V Position" description="Offset of the image along the V direction of the material" />
+ <Property name="pivotu" formalName="U Pivot" description="Offset the image in the U direction without affecting rotation center" />
+ <Property name="pivotv" formalName="V Pivot" description="Offset the image in the V direction without affecting rotation center" />
+ <Property name="subpresentation" formalName="Sub-Presentation" description="Presentation (or plugin) to use instead of the image" type="Renderable" />
+ </Image>
+ <Layer>
+ <Property name="name" formalName="Name" type="String" default="Layer" hidden="True" />
+ <Property name="disabledepthtest" formalName="Disable Depth Test" description="Optimize render speed for layers with mostly transparent objects?" type="Boolean" animatable="False"/>
+ <Property name="disabledepthprepass" formalName="Disable Depth Prepass" description="Optimize render speed for layers with low depth complexity" type="Boolean" animatable="False"/>
+ <Property name="progressiveaa" formalName="Progressive AA" description="Improves the visual quality when no items are moving" list="None:2x:4x:8x" default="None" />
+ <Property name="multisampleaa" formalName="Multisample AA" description="Improves geometry quality, e.g. silhouettes." list="None:2x:4x:SSAA" default="None" />
+ <Property name="temporalaa" formalName="Temporal AA" description="Improve overall quality using camera jittering and frame blending?" type="Boolean" default="False"/>
+ <Property name="background" formalName="Layer Background" description="The color to use for the layer each frame" list="Transparent:SolidColor:Unspecified" default="Transparent" />
+ <Property name="backgroundcolor" formalName="Background Color" description="The background color for the layer" type="Color" animatable="False">
+ <ShowIfEqual property="background" value="SolidColor"/>
+ </Property>
+ <Property name="blendtype" formalName="Blend Mode" list="Normal:Screen:Multiply:Add:Subtract:*Overlay:*ColorBurn:*ColorDodge" default="Normal" description="Mode of blending between this layer and layers below. Modes marked with * are available only with HW supporting advanced blending modes." />
+ <Property name="horzfields" formalName="Horizontal Fields" description="Properties to use to control the horizontal size and placement" list="Left/Width:Left/Right:Width/Right" default="Left/Width" />
+ <Property name="left" formalName="Left" description="Distance between presentation and layer left edges">
+ <ShowIfEqual property="horzfields" value="Left/Width"/>
+ <ShowIfEqual property="horzfields" value="Left/Right"/>
+ </Property>
+ <Property name="leftunits" formalName="Left Units" description="Left distance is percent of overall width or absolute pixels" list="percent:pixels" default="percent">
+ <ShowIfEqual property="horzfields" value="Left/Width"/>
+ <ShowIfEqual property="horzfields" value="Left/Right"/>
+ </Property>
+ <Property name="width" formalName="Width" description="Overall layer width" default="100">
+ <ShowIfEqual property="horzfields" value="Left/Width"/>
+ <ShowIfEqual property="horzfields" value="Width/Right"/>
+ </Property>
+ <Property name="widthunits" formalName="Width Units" description="Width is percent of overall width or absolute pixels" list="percent:pixels" default="percent">
+ <ShowIfEqual property="horzfields" value="Left/Width"/>
+ <ShowIfEqual property="horzfields" value="Width/Right"/>
+ </Property>
+ <Property name="right" formalName="Right" description="Distance between presentation and layer right edges">
+ <ShowIfEqual property="horzfields" value="Left/Right"/>
+ <ShowIfEqual property="horzfields" value="Width/Right"/>
+ </Property>
+ <Property name="rightunits" formalName="Right Units" description="Right distance is percent of overall width or absolute pixels" list="percent:pixels" default="percent">
+ <ShowIfEqual property="horzfields" value="Left/Right"/>
+ <ShowIfEqual property="horzfields" value="Width/Right"/>
+ </Property>
+ <Property name="vertfields" formalName="Vertical Fields" description="Properties to use to control the vertical size and placement" list="Top/Height:Top/Bottom:Height/Bottom" default="Top/Height" />
+ <Property name="top" formalName="Top" description="Distance between presentation and layer top edges.">
+ <ShowIfEqual property="vertfields" value="Top/Height"/>
+ <ShowIfEqual property="vertfields" value="Top/Bottom"/>
+ </Property>
+ <Property name="topunits" formalName="Top Units" description="Top distance is percent of overall height or absolute pixels" list="percent:pixels" default="percent">
+ <ShowIfEqual property="vertfields" value="Top/Height"/>
+ <ShowIfEqual property="vertfields" value="Top/Bottom"/>
+ </Property>
+ <Property name="height" formalName="Height" description="Overall layer height." default="100">
+ <ShowIfEqual property="vertfields" value="Top/Height"/>
+ <ShowIfEqual property="vertfields" value="Height/Bottom"/>
+ </Property>
+ <Property name="heightunits" formalName="Height Units" description="Height is percent of overall height or absolute pixels" list="percent:pixels" default="percent">
+ <ShowIfEqual property="vertfields" value="Top/Height"/>
+ <ShowIfEqual property="vertfields" value="Height/Bottom"/>
+ </Property>
+ <Property name="bottom" formalName="Bottom" description="Distance between presentation and layer bottom edges">
+ <ShowIfEqual property="vertfields" value="Top/Bottom"/>
+ <ShowIfEqual property="vertfields" value="Height/Bottom"/>
+ </Property>
+ <Property name="bottomunits" formalName="Bottom Units" description="Bottom distance is percent of overall height or absolute pixels" list="percent:pixels" default="percent">
+ <ShowIfEqual property="vertfields" value="Top/Bottom"/>
+ <ShowIfEqual property="vertfields" value="Height/Bottom"/>
+ </Property>
+ <Property name="sourcepath" formalName="Sub-Presentation" description="Presentation (or plugin) to render for this layer" type="Renderable" />
+ <!-- Restating the node properties so they appear at the bottom of the list because they won't be used quite as much -->
+ <!--CN - removing properties that may force the layer to render offscreen. We aren't ready to support this feature-->
+ <Property name="position" formalName="Position" description="Position" type="Vector" hidden="True"/>
+ <Property name="rotation" formalName="Rotation" description="Rotation" type="Rotation" hidden="True" />
+ <Property name="scale" formalName="Scale" description="Scale" type="Vector" default="1 1 1" hidden="True" />
+ <Property name="pivot" formalName="Pivot" description="Pivot" type="Vector" hidden="True" />
+ <Property name="opacity" formalName="Opacity" min="0" max="100" default="100" hidden="True" />
+
+ <Property name="aostrength" formalName="Ambient Occlusion" description="Amount of ambient occlusion shading to apply" min="0" max="100" default="0">
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="aodistance" formalName="AO Distance" description="Size of the ambient occlusion shading" default="5">
+ <HideIfEqual property="aostrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="aosoftness" formalName="AO Softness" description="Magnitude of the blurring used to soften shading" min="0" max="50" default="50">
+ <HideIfEqual property="aostrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="aobias" formalName="AO Threshold" description="Remove AO from flat surfaces to prevent artifacts" default="0">
+ <HideIfEqual property="aostrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="aosamplerate" formalName="AO Sampling Rate" description="Quality of AO sampling" type="Long" default="2" min="2" max="4">
+ <HideIfEqual property="aostrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="aodither" formalName="AO Detail" description="Use close-range detail AO" type="Boolean" default="True">
+ <HideIfEqual property="aostrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+
+ <Property name="shadowstrength" formalName="Shadow Strength" description="Amount of shadowing to apply" min="0" max="100" default="0" hidden="True">
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="shadowdist" formalName="Shadow Distance" description="Maximum distance to ray march for shadows test" default="10" hidden="True">
+ <HideIfEqual property="shadowstrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="shadowsoftness" formalName="Shadow Softness" description="Amount of softening of the shadow edges" min="0" max="100" default="100" hidden="True">
+ <HideIfEqual property="shadowstrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="shadowbias" formalName="Shadow Threshold" description="Remove self-shadowing from flat surfaces" default="0" hidden="True">
+ <HideIfEqual property="shadowstrength" value="0"/>
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+
+ <Property name="lightprobe" formalName="Light Probe" description="Image used for image-based lighting and reflections" type="Image" />
+ <Property name="probebright" formalName="IBL Brightness" description="Amount of light emitted by the light probe." default="100" />
+ <Property name="fastibl" formalName="Fast IBL" description="Use a faster approximation to image-based lighting" type="Boolean" default="True" hidden="True" />
+ <Property name="probehorizon" formalName="IBL Horizon Cutoff" description="Upper limit for horizon darkening of the light probe" min="-1" max="-0.001" default="-1">
+ <HideIfEqual property="lightprobe" value=""/>
+ </Property>
+ <Property name="probefov" formalName="IBL FOV Angle" description="Image source FOV for the case of using a camera-source as the IBL probe" min="1.0" max="180" default="180">
+ <HideIfEqual property="lightprobe" value=""/>
+ </Property>
+ <Property name="lightprobe2" formalName="Secondary Light Probe" description="Image to blend over the primary light probe" type="Image">
+ <HideIfEqual property="lightprobe" value=""/>
+ </Property>
+ <Property name="probe2fade" formalName="Probe Crossfade" description="Blend amount between the primary and seconary probes" min="0.0" max="1.0" default="1.0">
+ <HideIfEqual property="lightprobe" value=""/>
+ <HideIfEqual property="lightprobe2" value=""/>
+ </Property>
+ <Property name="probe2window" formalName="Secondary Probe Window" description="Texture-U window size used for the moving window (for scrolling textures" min="0.01" max="1.0" default="1.0" hidden="True">
+ <HideIfEqual property="lightprobe" value=""/>
+ <HideIfEqual property="lightprobe2" value=""/>
+ </Property>
+ <Property name="probe2pos" formalName="Secondary Probe Offset" description="Texture-U window offset used for the moving window" default="0.5" hidden="True">
+ <HideIfEqual property="lightprobe" value=""/>
+ <HideIfEqual property="lightprobe2" value=""/>
+ </Property>
+ </Layer>
+ <Light>
+ <Property name="name" formalName="Name" type="String" default="Light" hidden="True" />
+ <Property name="opacity" formalName="Opacity" min="0" max="100" default="100" hidden="True" />
+ <Property name='scope' formalName="Scope" description="Portion of the scene graph lit by this light; no value results in entire layer being affected." type='ObjectRef' />
+ <Property name="lighttype" formalName="Light Type" description="Type of illumination to use" list="Directional:Point:Area" default="Directional" />
+ <Property name="position" formalName="Position" description="Location in local space" type="Vector"/>
+ <Property name="rotation" formalName="Rotation" description="Rotation around local axes" type="Rotation" />
+ <Property name="scale" formalName="Scale" description="Size adjustments along local axes" type="Vector" default="1 1 1" />
+ <Property name="pivot" formalName="Pivot" description="Offset of the contents away from the local center" type="Vector" />
+ <Property name="lightdiffuse" formalName="Light Color" description="Color of diffuse lighting effect" type="Color" default="1 1 1"/>
+ <Property name="lightspecular" formalName="Specular Color" description="Color of specular lighting highlights" type="Color" default="1 1 1"/>
+ <Property name="lightambient" formalName="Ambient Color" description="Color of unlit areas (black for none)" type="Color"/>
+ <Property name="brightness" formalName="Brightness" description="Strength of the light" default="100"/>
+ <Property name="linearfade" formalName="Linear Fade" description="Falloff of the point light" min="0" max="1000">
+ <ShowIfEqual property="lighttype" value="Point"/>
+ </Property>
+ <Property name="expfade" formalName="Exponential Fade" description="Additional falloff" min="0" max="1000">
+ <ShowIfEqual property="lighttype" value="Point"/>
+ </Property>
+ <Property name="areawidth" formalName="Width" description="Width of the surface of the area light" min="0" default="100" hidden="True">
+ <ShowIfEqual property="lighttype" value="Area"/>
+ </Property>
+ <Property name="areaheight" formalName="Height" description="Height of the surface of the area light" min="0" default="100" hidden="True">
+ <ShowIfEqual property="lighttype" value="Area"/>
+ </Property>
+ <Property name="castshadow" formalName="Cast Shadows?" description="Enable shadow casting for this light" type="Boolean" default="False"/>
+ <Property name="shdwfactor" formalName="Shadow Darkness" description="Factor used to darken shadows" default="10.0" min="1.0" max="100.0">
+ <ShowIfEqual property="castshadow" value="True"/>
+ </Property>
+ <Property name="shdwfilter" formalName="Shadow Softness" description="Width of the blur filter on the shadow map" min="1" max="100" default="35">
+ <ShowIfEqual property="castshadow" value="True"/>
+ </Property>
+ <Property name="shdwmapres" formalName="Shadow Resolution" description="Resolution of shadow map (powers of two)" type="ShadowMapResolution">
+ <ShowIfEqual property="castshadow" value="True"/>
+ </Property>
+ <Property name="shdwbias" formalName="Shadow Depth Bias" description="Slight offset to avoid self-shadowing artifacts" default="0" min="-1.0" max="1.0">
+ <ShowIfEqual property="castshadow" value="True"/>
+ </Property>
+ <Property name="shdwmapfar" formalName="Shadow Far Clip" description="Affects the maximum distance for the shadow depth map" default="5000">
+ <ShowIfEqual property="castshadow" value="True"/>
+ </Property>
+ </Light>
+ <Lightmaps>
+ <Property name="name" formalName="Name" type="String" default="Lightmaps" hidden="True" category="Lighting" />
+ <Property name="lightmapindirect" formalName="Indirect Lightmap" description="Image providing indirect lighty values for GI" type="Image" category="Lighting" />
+ <Property name="lightmapradiosity" formalName="Radiosity Lightmap" description="Image providing directional light values" type="Image" category="Lighting" />
+ <Property name="lightmapshadow" formalName="Shadow Lightmap" description="Baked Shadow map" type="Image" category="Lighting" />
+ </Lightmaps>
+ <MaterialBase>
+ <Property name="name" formalName="Name" type="String" default="MaterialBase" hidden="True" category="Material" />
+ <Property name="iblprobe" formalName="IBL Override" description="IBL probe to use in place of the layer probe for this material" type="Image" category="Material" />
+ </MaterialBase>
+ <Material>
+ <Property name="name" formalName="Name" type="String" default="Material" hidden="True" category="Material" />
+ <Property name="shaderlighting" formalName="Lighting" description="Light model" list="Pixel:None" default="Pixel" category="Material" />
+ <Property name="blendmode" formalName="Blending Mode" description="How this material blends with content behind it. Modes marked with * are available only with HW supporting advanced blending modes." list="Normal:Screen:Multiply:*Overlay:*ColorBurn:*ColorDodge" default="Normal" category="Material" />
+ <Property name="diffuse" formalName="Diffuse Color" description="Color when lit from any direction" type="Color" default="1 1 1" category="Material" />
+ <Property name="diffusemap" formalName="Diffuse Map" description="Image to multiply with diffuse color" type="Image" category="Material" />
+ <Property name="diffusemap2" formalName="Diffuse Map 2" description="Image to multiply with diffuse color" type="Image" category="Material" />
+ <Property name="diffusemap3" formalName="Diffuse Map 3" description="Image to multiply with diffuse color" type="Image" category="Material" />
+ <Property name="specularreflection" formalName="Specular Reflection" description="Image to use as a faked reflection" type="Image" category="Material" />
+ <Property name="speculartint" formalName="Specular Tint" type="Color" description="Coloration applied to specular reflections" default="1 1 1" category="Material" />
+ <Property name="specularamount" formalName="Specular Amount" description="Amount of shine/gloss" category="Material" />
+ <Property name="specularmap" formalName="Specular Map" description="Image to vary the specular amount across the material" type="Image" category="Material" >
+ <HideIfEqual property="specularamount" value='0'/>
+ </Property>
+ <Property name="specularmodel" formalName="Specular Model" description="Equation to use when calculating specular highlights for CG lights" list="Default:KGGX:KWard" default="Default" category="Material" >
+ <HideIfEqual property="specularamount" value='0'/>
+ </Property>
+ <Property name="specularroughness" formalName="Specular Roughness" description="Softening applied to reflections and highlights" min='0.001' max='1' category="Material" >
+ <HideIfEqual property="specularamount" value='0'/>
+ </Property>
+ <Property name="fresnelPower" formalName="Fresnel Power" description="Damping of head-on reflections" category="Material" />
+ <Property name="ior" formalName="Index of Refraction" description="Angle at which fresnel reflection damping applies" min="0" max="1" default=".2" category="Material" >
+ <HideIfEqual property="fresnelPower" value="0"/>
+ </Property>
+ <Property name="bumpmap" formalName="Bump Map" description="Grayscale image simulating roughness in the lighting" type="Image" category="Material" />
+ <Property name="normalmap" formalName="Normal Map" description="Special RGB image describing surface roughness" type="Image" category="Material" />
+ <Property name="bumpamount" formalName="Bump Amount" description="Strength of bump/normal map effect" type="float" default=".5" category="Material" />
+ <Property name="displacementmap" formalName="Displacement Map" description="Grayscale image used to offset vertices of the geometry" type="Image" category="Material" />
+ <Property name="displaceamount" formalName="Displacement Amount" description="Distance to offset vertices" type="float" default="20" category="Material" >
+ <HideIfEqual property="displacementmap" value=""/>
+ </Property>
+ <Property name="opacity" formalName="Opacity" description="Visibility of the geometry for this material." min="0" max="100" default="100" category="Material" />
+ <Property name="opacitymap" formalName="Opacity Map" description="Image to vary the opacity across the material" type="Image" category="Material" />
+ <Property name="emissivecolor" formalName="Emissive Color" description="Color of self-illumination for this material" type="Color" default="1 1 1" category="Material" />
+ <Property name="emissivepower" formalName="Emissive Power" description="Amount of self-illumination for this material (will not light other objects)" category="Material" />
+ <Property name="emissivemap" formalName="Emissive Map" description="Image to vary the emissive power across the material" type="Image" category="Material" />
+ <Property name="emissivemap2" formalName="Emissive Map 2" description="Second image to modulate the emissive power across the material" type="Image" category="Material" />
+ <Property name="translucencymap" formalName="Translucency Map" description="Grayscale image controlling how much light can pass through the material from behind" type="Image" category="Material" />
+ <Property name="translucentfalloff" formalName="Translucent Falloff" type="float" default="1" category="Material" >
+ <HideIfEqual property="translucencymap" value=""/>
+ </Property>
+ <Property name="diffuselightwrap" formalName="Diffuse Light Wrap" type="float" min='0.0' max='1.0' category="Material" >
+ <HideIfEqual property="translucencymap" value=""/>
+ </Property>
+ </Material>
+ <ReferencedMaterial>
+ <Property name="name" formalName="Name" type="String" default="Material" hidden="True" category="Material" />
+ <Property name="referencedmaterial" formalName="Referenced Material" description="Material to use all settings from" type="ObjectRef" category="Material" />
+ </ReferencedMaterial>
+ <Model>
+ <Property name="name" formalName="Name" type="String" default="Model" hidden="True" />
+ <Property name="sourcepath" formalName="Mesh" description="Geometry to use for this model" type="Mesh" />
+ <Property name="poseroot" hidden="True" type="Long" default="-1" />
+ <Property name="tessellation" formalName="Tessellation Mode" description="Type of tessellation to subdivide the geometry" list="None:Linear:Phong:NPatch" default="None" />
+ <Property name="edgetess" formalName="Edge Tessellation Value" description="Max Tessellation amount" min="1" max="64" default="4">
+ <HideIfEqual property="tessellation" value="None"/>
+ </Property>
+ <Property name="innertess" formalName="Inner Tessellation Value" description="Min Tessellation amount" min="1" max="64" default="4">
+ <HideIfEqual property="tessellation" value="None"/>
+ </Property>
+ </Model>
+ <Node>
+ <Event name="onPressureDown" category="Gesture" />
+ <Event name="onPressureUp" category="Gesture" />
+ <Event name="onTap" category="Gesture" />
+ <!--
+ <Event name="onDoubleTap" category="Gesture" />
+ <Event name="onSingleTap" category="Gesture" />
+ <Event name="onOnePointDragStart" category="Gesture" />
+ <Event name="onOnePointDrag" category="Gesture" />
+ <Event name="onOnePointDragRelease" category="Gesture" />
+ <Event name="onTwoPointDragStart" category="Gesture" />
+ <Event name="onTwoPointDrag" category="Gesture" />
+ <Event name="onTwoPointDragRelease" category="Gesture" />
+ <Event name="onSwipeLeft" category="Gesture" />
+ <Event name="onSwipeRight" category="Gesture" />
+ <Event name="onSwipeUp" category="Gesture" />
+ <Event name="onSwipeDown" category="Gesture" />
+ <Event name="onTwoPointSwipeLeft" category="Gesture" />
+ <Event name="onTwoPointSwipeRight" category="Gesture" />
+ <Event name="onTwoPointSwipeUp" category="Gesture" />
+ <Event name="onTwoPointSwipeDown" category="Gesture" />
+ -->
+
+ <Property name="position" formalName="Position" description="Location in local space" type="Vector"/>
+ <Property name="rotation" formalName="Rotation" description="Rotation around local axes" type="Rotation" />
+ <Property name="scale" formalName="Scale" description="Size adjustments along local axes" type="Vector" default="1 1 1" />
+ <Property name="pivot" formalName="Pivot" description="Offset of the contents away from the local center" type="Vector" />
+ <Property name="opacity" formalName="Opacity" description="How much the element (and its children) occlude items behind them" min="0" max="100" default="100" />
+ <Property name="rotationorder" formalName="Rotation Order" description="Rotation Order" list="XYZ:YZX:ZXY:XZY:YXZ:ZYX:XYZr:YZXr:ZXYr:XZYr:YXZr:ZYXr" default="YXZ" hidden="True"/>
+ <Property name="orientation" formalName="Orientation" description="Orientation" list="Left Handed:Right Handed" default="Left Handed" hidden="True"/>
+ <Property name="boneid" type="Long" hidden="True" default="-1" />
+ <Property name="ignoresparent" type="Boolean" hidden="True" default="False" />
+ </Node>
+ <Path>
+ <Property name="name" formalName="Name" type="String" default="Path" hidden="True" />
+ <Property name="opacity" formalName="Opacity" description="How much the element (and its children) occlude items behind them" min="0" max="100" default="100" />
+ <Property name="sourcepath" formalName="Path" description="Path data to use for this path" type="PathBuffer" />
+ <Property name='width' formalName="Stroke Width" description="The size of the stroke in local units" default='5'/>
+ <Property name='pathtype' formalName='Path Type' description="The type of this path" list='Painted:Geometry' default='Painted' />
+ <Property name='linearerror' formalName="CPU Limit" description="Amount of tessellation work done on the CPU before GPU tessellation is involved" default='1000'>
+ <ShowIfEqual property='pathtype' value='Geometry'/>
+ </Property>
+ <Property name='edgetessamount' formalName="Edge Detail" description="Amount of GPU tessellation along the length of the path." default='8' min='1' max='64' >
+ <ShowIfEqual property='pathtype' value='Geometry'/>
+ </Property>
+ <Property name='innertessamount' formalName="Width Detail" description="Amount of GPU tessellation across the stroke of the path." default='1' min='1' max='64' >
+ <ShowIfEqual property='pathtype' value='Geometry'/>
+ </Property>
+ <Property name='begincap' formalName="Begin Cap Style" description='Set this to &quot;Taper&quot; to finely taper the beginning of your stroke over a specified distance' list="None:Taper" default="None">
+ <ShowIfEqual property='pathtype' value='Geometry'/>
+ </Property>
+ <Property name='begincapoffset' formalName='Taper Length' description="Control the length of the taper" default='10'>
+ <HideIfEqual property='pathtype' value='Painted'/>
+ <ShowIfEqual property='begincap' value='Taper'/>
+ </Property>
+ <Property name='begincapopacity' formalName='Tip Opacity' description="Control the opacity of the taper" min='0' max='1'>
+ <HideIfEqual property='pathtype' value='Painted'/>
+ <ShowIfEqual property='begincap' value='Taper'/>
+ </Property>
+ <Property name='begincapwidth' formalName='Tip Width' description="Control the size of the taper" default='0'>
+ <HideIfEqual property='pathtype' value='Painted'/>
+ <ShowIfEqual property='begincap' value='Taper'/>
+ </Property>
+ <Property name='endcap' formalName="End Cap Style" description='Set this to &quot;Taper&quot; to finely taper the end of your stroke over a specified distance' list="None:Taper" default="None">
+ <ShowIfEqual property='pathtype' value='Geometry'/>
+ </Property>
+ <Property name='endcapoffset' formalName='Taper Length' description="Control the length of the taper" default='10'>
+ <HideIfEqual property='pathtype' value='Painted'/>
+ <ShowIfEqual property='endcap' value='Taper'/>
+ </Property>
+ <Property name='endcapopacity' formalName='Tip Opacity' description="Control the opacity of the taper" min='0' max='1'>
+ <HideIfEqual property='pathtype' value='Painted'/>
+ <ShowIfEqual property='endcap' value='Taper'/>
+ </Property>
+ <Property name='endcapwidth' formalName='Tip Width' description="Control the size of the taper" default='0'>
+ <HideIfEqual property='pathtype' value='Painted'/>
+ <ShowIfEqual property='endcap' value='Taper'/>
+ </Property>
+ <!--Painted paths have a dropdown called “Paint Style†with values “Filled and Strokedâ€, “Filledâ€, “Strokedâ€. Default is “Filled and Strokedâ€, but derived on import.-->
+ <Property name='paintstyle' formalName='Paint Style' description="The style of this path" list='Filled and Stroked:Filled:Stroked' default='Stroked'>
+ <ShowIfEqual property='pathtype' value='Painted'/>
+ </Property>
+ </Path>
+ <SubPath>
+ <Property name="name" formalName="Name" type="String" default="SubPath" hidden="True" />
+ <Property name='closed' formalName='Closed Path?' type='Boolean' default='False'/>
+ </SubPath>
+ <PathAnchorPoint>
+ <Property name="name" formalName="Name" type="String" default="Anchor Point" hidden="True" />
+ <Property name='position' formalName='Position' type='Float2'/>
+ <Property name="incomingangle" formalName='Handle Angle' />
+ <Property name="incomingdistance" formalName="Incoming Distance" />
+ <Property name="outgoingdistance" formalName="Outgoing Distance" />
+ </PathAnchorPoint>
+ <Particle>
+ <Property name="name" formalName="Name" type="String" default="Particle" hidden="True" />
+ <Property name="particletype" formalName="Particle Type" description="Type of particle System" list="Simple:Smoke:Cloud:Fluid:User" default="Cloud" />
+ <Property name="opacity" formalName="Opacity" description="How much the element (and its children) occlude items behind them" min="0" max="100" default="100" />
+ <Property name="maxparticles" formalName="MaxParticle" description="Max count of particles" type="Long" min="0" max="1000000" default="100" />
+ <Property name="particlesize" formalName="ParticleSize" description="Render size of particle" min="0" default="1" />
+ <Property name="lifetime" formalName="Lifetime" description="Particle lifetime before it dies" min="-1" default="5">
+ <HideIfEqual property='particletype' value='Cloud'/>
+ </Property>
+ </Particle>
+ <RenderPlugin>
+ <Property name="name" formalName="Name" type="String" default="RenderPlugin" hidden="True" />
+ </RenderPlugin>
+ <Scene>
+ <Property name="name" formalName="Name" type="String" default="Scene" hidden="True" />
+ <Property name="bgcolorenable" formalName="Use Background" description="Clear the contents to a solid color before each frame?" type="Boolean" default="True" />
+ <Property name="backgroundcolor" formalName="Background Color" description="Color to use for the background" type="Color" animatable="False">
+ <ShowIfEqual property="bgcolorenable" value="True"/>
+ </Property>
+ <Event name="onPressureDown" category="Gesture" />
+ <Event name="onPressureUp" category="Gesture" />
+ <Event name="onTap" category="Gesture" />
+ <!--
+ <Event name="onDoubleTap" category="Gesture" />
+ <Event name="onSingleTap" category="Gesture" />
+ <Event name="onOnePointDragStart" category="Gesture" />
+ <Event name="onOnePointDrag" category="Gesture" />
+ <Event name="onOnePointDragRelease" category="Gesture" />
+ <Event name="onTwoPointDragStart" category="Gesture" />
+ <Event name="onTwoPointDrag" category="Gesture" />
+ <Event name="onTwoPointDragRelease" category="Gesture" />
+ <Event name="onSwipeLeft" category="Gesture" />
+ <Event name="onSwipeRight" category="Gesture" />
+ <Event name="onSwipeUp" category="Gesture" />
+ <Event name="onSwipeDown" category="Gesture" />
+ <Event name="onTwoPointSwipeLeft" category="Gesture" />
+ <Event name="onTwoPointSwipeRight" category="Gesture" />
+ <Event name="onTwoPointSwipeUp" category="Gesture" />
+ <Event name="onTwoPointSwipeDown" category="Gesture" />
+ -->
+ </Scene>
+ <Slide>
+ <Property name="playmode" formalName="Play Mode" description="Action to take when reaching the end of all timebars on this slide" list="Stop at end:Looping:PingPong:Ping:Play Through To..." default="Stop at end" animatable="False" />
+ <Property name="playthroughto" formalName="Play Through To" description="Slide to go to after this one" type="StringListOrInt" list="Next:Previous" default="Next" animatable="False">
+ <ShowIfEqual property="playmode" value="Play Through To..."/>
+ </Property>
+ <Property name="initialplaystate" formalName="Initial Play State" description="Do animations start when coming to this slide?" list="Play:Pause" default="Play" animatable="False" />
+ </Slide>
+ <SlideOwner>
+ <Event name="onSlideEnter" category="Slide" description="Fired when the slide is changing" />
+ <Event name="onSlideExit" category="Slide" description="Fired when the slide is changing" />
+ <Handler name="Go to Time" category="Time" description="Set the current time on the component.">
+ <Argument name="Time" description="Time to go do" />
+ <Argument name="Pause" description="Pause playback at the new time?" type="Boolean" />
+ </Handler>
+ <Handler name="Play" category="Time" description="Start the component's time playing." />
+ <Handler name="Pause" category="Time" description="Pause the component's time." />
+ <Handler name="Go to Slide" category="Slide" description="Go to a specified slide of the component.">
+ <Argument name="Slide" description="Target slide to go to" type="Slide" argumentType="Slide" />
+ </Handler>
+ <Handler name="Next Slide" category="Slide" description="Activate the next slide of the component." />
+ <Handler name="Previous Slide" category="Slide" description="Activate the previous slide of the component." />
+ <Handler name="Preceding Slide" category="Slide" description="Activate the slide that was previously active." />
+ </SlideOwner>
+ <Text>
+ <Property name="name" formalName="Name" type="String" default="Text" hidden="True" />
+ <Property name="textstring" formalName="Text String" description="Text String" type="MultiLineString" default="Text" />
+ <Property name="textcolor" formalName="Text Color" description="Text Color" type="Color" default="1 1 1" />
+ <Property name="font" formalName="Font" description="Font" type="Font" default="TitilliumWeb-Regular" />
+ <!-- HW accelerated fonts not supported
+ <Property name="enableacceleratedfont" formalName="Hardware accelerated font" description="Enabled hardware acclerated font" type="Boolean" default="false" />
+ -->
+ <Property name="size" formalName="Font Size" description="Font Size" type="FontSize" default="24" animatable="False" />
+ <Property name="horzalign" formalName="Horizontal Alignment" description="Horizontal Alignment" list="Left:Center:Right" default="Center" />
+ <Property name="vertalign" formalName="Vertical Alignment" description="Vertical Alignment" list="Top:Middle:Bottom" default="Middle" />
+ <Property name="leading" formalName="Leading" description="Leading" />
+ <Property name="tracking" formalName="Tracking" description="Tracking" />
+ </Text>
+</MetaData>
diff --git a/src/Runtime/res/Font/TitilliumWeb-Regular.ttf b/src/Runtime/res/Font/TitilliumWeb-Regular.ttf
new file mode 100644
index 00000000..6da82193
--- /dev/null
+++ b/src/Runtime/res/Font/TitilliumWeb-Regular.ttf
Binary files differ
diff --git a/src/Runtime/res/effectlib/Fxaa3_11.glsllib b/src/Runtime/res/effectlib/Fxaa3_11.glsllib
new file mode 100644
index 00000000..52053c0d
--- /dev/null
+++ b/src/Runtime/res/effectlib/Fxaa3_11.glsllib
@@ -0,0 +1,2073 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*============================================================================
+
+
+ NVIDIA FXAA 3.11 by TIMOTHY LOTTES
+
+------------------------------------------------------------------------------
+ INTEGRATION CHECKLIST
+------------------------------------------------------------------------------
+(1.)
+In the shader source, setup defines for the desired configuration.
+When providing multiple shaders (for different presets),
+simply setup the defines differently in multiple files.
+Example,
+
+ #define FXAA_PC 1
+ #define FXAA_HLSL_5 1
+ #define FXAA_QUALITY__PRESET 12
+
+Or,
+
+ #define FXAA_360 1
+
+Or,
+
+ #define FXAA_PS3 1
+
+Etc.
+
+(2.)
+Then include this file,
+
+(3.)
+Then call the FXAA pixel shader from within your desired shader.
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+As for FXAA 3.11 all inputs for all shaders are the same
+to enable easy porting between platforms.
+
+ return FxaaPixelShader(...);
+
+(4.)
+Insure pass prior to FXAA outputs RGBL (see next section).
+Or use,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+(5.)
+Setup engine to provide the following constants
+which are used in the FxaaPixelShader() inputs,
+
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+
+(6.)
+Have FXAA vertex shader run as a full screen triangle,
+and output "pos" and "fxaaConsolePosPos"
+such that inputs in the pixel shader provide,
+
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+
+(7.)
+Insure the texture sampler(s) used by FXAA are set to bilinear filtering.
+
+
+------------------------------------------------------------------------------
+ INTEGRATION - RGBL AND COLORSPACE
+------------------------------------------------------------------------------
+FXAA3 requires RGBL as input unless the following is set,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+In which case the engine uses green in place of luma,
+and requires RGB input is in a non-linear colorspace.
+
+RGB should be LDR (low dynamic range).
+Specifically do FXAA after tonemapping.
+
+RGB data as returned by a texture fetch can be non-linear,
+or linear when FXAA_GREEN_AS_LUMA is not set.
+Note an "sRGB format" texture counts as linear,
+because the result of a texture fetch is linear data.
+Regular "RGBA8" textures in the sRGB colorspace are non-linear.
+
+If FXAA_GREEN_AS_LUMA is not set,
+luma must be stored in the alpha channel prior to running FXAA.
+This luma should be in a perceptual space (could be gamma 2.0).
+Example pass before FXAA where output is gamma 2.0 encoded,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma
+ return color;
+
+Another example where output is linear encoded,
+say for instance writing to an sRGB formated render target,
+where the render target does the conversion back to sRGB after blending,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma
+ return color;
+
+Getting luma correct is required for the algorithm to work correctly.
+
+
+------------------------------------------------------------------------------
+ BEING LINEARLY CORRECT?
+------------------------------------------------------------------------------
+Applying FXAA to a framebuffer with linear RGB color will look worse.
+This is very counter intuitive, but happends to be true in this case.
+The reason is because dithering artifacts will be more visiable
+in a linear colorspace.
+
+
+------------------------------------------------------------------------------
+ COMPLEX INTEGRATION
+------------------------------------------------------------------------------
+Q. What if the engine is blending into RGB before wanting to run FXAA?
+
+A. In the last opaque pass prior to FXAA,
+ have the pass write out luma into alpha.
+ Then blend into RGB only.
+ FXAA should be able to run ok
+ assuming the blending pass did not any add aliasing.
+ This should be the common case for particles and common blending passes.
+
+A. Or use FXAA_GREEN_AS_LUMA.
+
+============================================================================*/
+
+/*============================================================================
+
+ INTEGRATION KNOBS
+
+============================================================================*/
+//
+// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).
+// FXAA_360_OPT is a prototype for the new optimized 360 version.
+//
+// 1 = Use API.
+// 0 = Don't use API.
+//
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PS3
+ #define FXAA_PS3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360
+ #define FXAA_360 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360_OPT
+ #define FXAA_360_OPT 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_PC
+ //
+ // FXAA Quality
+ // The high quality PC algorithm.
+ //
+ #define FXAA_PC 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PC_CONSOLE
+ //
+ // The console algorithm for PC is included
+ // for developers targeting really low spec machines.
+ // Likely better to just run FXAA_PC, and use a really low preset.
+ //
+ #define FXAA_PC_CONSOLE 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_120
+ #define FXAA_GLSL_120 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_130
+ #define FXAA_GLSL_130 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_3
+ #define FXAA_HLSL_3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_4
+ #define FXAA_HLSL_4 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_5
+ #define FXAA_HLSL_5 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_GREEN_AS_LUMA
+ //
+ // For those using non-linear color,
+ // and either not able to get luma in alpha, or not wanting to,
+ // this enables FXAA to run using green as a proxy for luma.
+ // So with this enabled, no need to pack luma in alpha.
+ //
+ // This will turn off AA on anything which lacks some amount of green.
+ // Pure red and blue or combination of only R and B, will get no AA.
+ //
+ // Might want to lower the settings for both,
+ // fxaaConsoleEdgeThresholdMin
+ // fxaaQualityEdgeThresholdMin
+ // In order to insure AA does not get turned off on colors
+ // which contain a minor amount of green.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_GREEN_AS_LUMA 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_EARLY_EXIT
+ //
+ // Controls algorithm's early exit path.
+ // On PS3 turning this ON adds 2 cycles to the shader.
+ // On 360 turning this OFF adds 10ths of a millisecond to the shader.
+ // Turning this off on console will result in a more blurry image.
+ // So this defaults to on.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_EARLY_EXIT 1
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_DISCARD
+ //
+ // Only valid for PC OpenGL currently.
+ // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
+ //
+ // 1 = Use discard on pixels which don't need AA.
+ // For APIs which enable concurrent TEX+ROP from same surface.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ //
+ #define FXAA_DISCARD 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_FAST_PIXEL_OFFSET
+ //
+ // Used for GLSL 120 only.
+ //
+ // 1 = GL API supports fast pixel offsets
+ // 0 = do not use fast pixel offsets
+ //
+ #ifdef GL_EXT_gpu_shader4
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifndef FXAA_FAST_PIXEL_OFFSET
+ #define FXAA_FAST_PIXEL_OFFSET 0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GATHER4_ALPHA
+
+ //
+ // 1 = API supports gather4 on alpha channel.
+ // 0 = API does not support gather4 on alpha channel.
+ //
+
+#ifdef GL_ES
+ #if __VERSION__ >= 310
+ #ifdef GL_EXT_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#else
+ #if (FXAA_HLSL_5 == 1)
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+ #endif
+#endif
+
+/*============================================================================
+ FXAA CONSOLE PS3 - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS
+ //
+ // Consoles the sharpness of edges on PS3 only.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 8.0 is sharper
+ // 4.0 is softer
+ // 2.0 is really soft (good for vector graphics inputs)
+ //
+ #if 1
+ #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD
+ //
+ // Only effects PS3.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 0.25 and 0.125.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 0.125 leaves less aliasing, but is softer
+ // 0.25 leaves more aliasing, and is sharper
+ //
+ #if 1
+ #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125
+ #else
+ #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25
+ #endif
+#endif
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+------------------------------------------------------------------------------
+NOTE the other tuning knobs are now in the shader function inputs!
+============================================================================*/
+#ifndef FXAA_QUALITY__PRESET
+ //
+ // Choose the quality preset.
+ // This needs to be compiled into the shader as it effects code.
+ // Best option to include multiple presets is to
+ // in each shader define the preset, then include this file.
+ //
+ // OPTIONS
+ // -----------------------------------------------------------------------
+ // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
+ // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
+ // 39 - no dither, very expensive
+ //
+ // NOTES
+ // -----------------------------------------------------------------------
+ // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
+ // 13 = about same speed as FXAA 3.9 and better than 12
+ // 23 = closest to FXAA 3.9 visually and performance wise
+ // _ = the lowest digit is directly related to performance
+ // _ = the highest digit is directly related to style
+ //
+ #define FXAA_QUALITY__PRESET 12
+#endif
+
+
+/*============================================================================
+
+ FXAA QUALITY - PRESETS
+
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 10)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 3.0
+ #define FXAA_QUALITY__P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 11)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 3.0
+ #define FXAA_QUALITY__P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 12)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 4.0
+ #define FXAA_QUALITY__P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 13)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 4.0
+ #define FXAA_QUALITY__P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 14)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 4.0
+ #define FXAA_QUALITY__P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 15)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 20)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 2.0
+ #define FXAA_QUALITY__P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 21)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 22)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 23)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 24)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 3.0
+ #define FXAA_QUALITY__P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 25)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 26)
+ #define FXAA_QUALITY__PS 9
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 4.0
+ #define FXAA_QUALITY__P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 27)
+ #define FXAA_QUALITY__PS 10
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 4.0
+ #define FXAA_QUALITY__P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 28)
+ #define FXAA_QUALITY__PS 11
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 4.0
+ #define FXAA_QUALITY__P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 29)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 39)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.0
+ #define FXAA_QUALITY__P2 1.0
+ #define FXAA_QUALITY__P3 1.0
+ #define FXAA_QUALITY__P4 1.0
+ #define FXAA_QUALITY__P5 1.5
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+
+
+/*============================================================================
+
+ API PORTING
+
+============================================================================*/
+#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)
+ #define FxaaBool bool
+ #define FxaaDiscard discard
+ #define FxaaFloat float
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaHalf float
+ #define FxaaHalf2 vec2
+ #define FxaaHalf3 vec3
+ #define FxaaHalf4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaTex sampler2D
+#else
+ #define FxaaBool bool
+ #define FxaaDiscard clip(-1)
+ #define FxaaFloat float
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaHalf half
+ #define FxaaHalf2 half2
+ #define FxaaHalf3 half3
+ #define FxaaHalf4 half4
+ #define FxaaSat(x) saturate(x)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_120 == 1)
+ // Requires,
+ // #version 120
+ // And at least,
+ // #extension GL_EXT_gpu_shader4 : enable
+ // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
+ #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
+ #if (FXAA_FAST_PIXEL_OFFSET == 1)
+ #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
+ #else
+ #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
+ #endif
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_130 == 1)
+ // Requires "#version 130" or better
+ #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1)
+ #define FxaaInt2 float2
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
+ #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_4 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_5 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+ #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)
+ #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)
+ #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)
+ #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)
+#endif
+
+
+/*============================================================================
+ GREEN AS LUMA OPTION SUPPORT FUNCTION
+============================================================================*/
+#if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
+#else
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+#if (FXAA_PC == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+ //
+ // Used only for FXAA Console, and not used on the 360 version.
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ // if (FXAA_GREEN_AS_LUMA == 0)
+ // {___a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 2nd sampler.
+ // This sampler needs to have an exponent bias of -1.
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 3nd sampler.
+ // This sampler needs to have an exponent bias of -2.
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ FxaaFloat2 fxaaQualityRcpFrame,
+ //
+ // Only used on FXAA Console.
+ // This must be from a constant/uniform.
+ // This effects sub-pixel AA quality and inversely sharpness.
+ // Where N ranges between,
+ // N = 0.50 (default)
+ // N = 0.33 (sharper)
+ // {x___} = -N/screenWidthInPixels
+ // {_y__} = -N/screenHeightInPixels
+ // {__z_} = N/screenWidthInPixels
+ // {___w} = N/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ //
+ // Only used on FXAA Console.
+ // Not used on 360, but used on PS3 and PC.
+ // This must be from a constant/uniform.
+ // {x___} = -2.0/screenWidthInPixels
+ // {_y__} = -2.0/screenHeightInPixels
+ // {__z_} = 2.0/screenWidthInPixels
+ // {___w} = 2.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ //
+ // Only used on FXAA Console.
+ // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.
+ // This must be from a constant/uniform.
+ // {x___} = 8.0/screenWidthInPixels
+ // {_y__} = 8.0/screenHeightInPixels
+ // {__z_} = -4.0/screenWidthInPixels
+ // {___w} = -4.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__SUBPIX define.
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ FxaaFloat fxaaQualitySubpix,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ FxaaFloat fxaaQualityEdgeThreshold,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only three safe values here: 2 and 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // For all other platforms can be a non-power of two.
+ // 8.0 is sharper (default!!!)
+ // 4.0 is softer
+ // 2.0 is really soft (good only for vector graphics inputs)
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 1/4 and 1/8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // The console setting has a different mapping than the quality setting.
+ // Other platforms can use other values.
+ // 0.125 leaves less aliasing, but is softer (default!!!)
+ // 0.25 leaves more aliasing, and is sharper
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ // This does not apply to PS3,
+ // PS3 was simplified to avoid more shader instructions.
+ // 0.06 - faster but more aliasing in darks
+ // 0.05 - default
+ // 0.04 - slower and less aliasing in darks
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ //
+ // Extra constants for 360 FXAA Console only.
+ // Use zeros or anything else for other platforms.
+ // These must be in physical constant registers and NOT immedates.
+ // Immedates will result in compiler un-optimizing.
+ // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ #if (FXAA_GATHER4_ALPHA == 1)
+ #if (FXAA_DISCARD == 0)
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ #endif
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
+ #else
+ FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
+ #endif
+ #if (FXAA_DISCARD == 1)
+ #define lumaM luma4A.w
+ #endif
+ #define lumaE luma4A.z
+ #define lumaS luma4A.x
+ #define lumaSE luma4A.y
+ #define lumaNW luma4B.w
+ #define lumaN luma4B.z
+ #define lumaW luma4B.x
+ #else
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat maxSM = max(lumaS, lumaM);
+ FxaaFloat minSM = min(lumaS, lumaM);
+ FxaaFloat maxESM = max(lumaE, maxSM);
+ FxaaFloat minESM = min(lumaE, minSM);
+ FxaaFloat maxWN = max(lumaN, lumaW);
+ FxaaFloat minWN = min(lumaN, lumaW);
+ FxaaFloat rangeMax = max(maxWN, maxESM);
+ FxaaFloat rangeMin = min(minWN, minESM);
+ FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ FxaaFloat range = rangeMax - rangeMin;
+ FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ FxaaBool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit)
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 0)
+ FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #else
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNS = lumaN + lumaS;
+ FxaaFloat lumaWE = lumaW + lumaE;
+ FxaaFloat subpixRcpRange = 1.0/range;
+ FxaaFloat subpixNSWE = lumaNS + lumaWE;
+ FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNESE = lumaNE + lumaSE;
+ FxaaFloat lumaNWNE = lumaNW + lumaNE;
+ FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNWSW = lumaNW + lumaSW;
+ FxaaFloat lumaSWSE = lumaSW + lumaSE;
+ FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
+ FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
+ FxaaBool horzSpan = edgeHorz >= edgeVert;
+ FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat gradientN = lumaN - lumaM;
+ FxaaFloat gradientS = lumaS - lumaM;
+ FxaaFloat lumaNN = lumaN + lumaM;
+ FxaaFloat lumaSS = lumaS + lumaM;
+ FxaaBool pairN = abs(gradientN) >= abs(gradientS);
+ FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ FxaaFloat2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
+ FxaaFloat2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
+ FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
+ FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ FxaaFloat subpixE = subpixC * subpixC;
+ FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ FxaaFloat gradientScaled = gradient * 1.0/4.0;
+ FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
+ FxaaFloat subpixF = subpixD * subpixE;
+ FxaaBool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
+ FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
+ FxaaBool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dstN = posM.x - posN.x;
+ FxaaFloat dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ FxaaFloat spanLength = (dstP + dstN);
+ FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ FxaaFloat spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ FxaaBool directionN = dstN < dstP;
+ FxaaFloat dst = min(dstN, dstP);
+ FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
+ FxaaFloat subpixG = subpixF * subpixF;
+ FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ #if (FXAA_DISCARD == 1)
+ return FxaaTexTop(tex, posM);
+ #else
+ return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
+ #endif
+}
+/*==========================================================================*/
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - PC VERSION
+
+------------------------------------------------------------------------------
+Instead of using this on PC, I'd suggest just using FXAA Quality with
+ #define FXAA_QUALITY__PRESET 10
+Or
+ #define FXAA_QUALITY__PRESET 20
+Either are higher qualilty and almost as fast as this on modern PC GPUs.
+============================================================================*/
+#if (FXAA_PC_CONSOLE == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));
+ FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));
+ FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));
+ FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat lumaM = rgbyM.w;
+ #else
+ FxaaFloat lumaM = rgbyM.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);
+ lumaNe += 1.0/384.0;
+ FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);
+ FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
+ FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMinM = min(lumaMin, lumaM);
+ FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);
+ FxaaFloat lumaMaxM = max(lumaMax, lumaM);
+ FxaaFloat dirSwMinusNe = lumaSw - lumaNe;
+ FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;
+ FxaaFloat dirSeMinusNw = lumaSe - lumaNw;
+ if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir;
+ dir.x = dirSwMinusNe + dirSeMinusNw;
+ dir.y = dirSwMinusNe - dirSeMinusNw;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir1 = normalize(dir.xy);
+ FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);
+ FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;
+ FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);
+ FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;
+ FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
+ #else
+ FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);
+ #endif
+ if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;
+ return rgbyB; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - 360 PIXEL SHADER
+
+------------------------------------------------------------------------------
+This optimized version thanks to suggestions from Andy Luedke.
+Should be fully tex bound in all cases.
+As of the FXAA 3.11 release, I have still not tested this code,
+however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10.
+And note this is replacing the old unoptimized version.
+If it does not work, please let me know so I can fix it.
+============================================================================*/
+#if (FXAA_360 == 1)
+/*--------------------------------------------------------------------------*/
+[reduceTempRegUsage(4)]
+float4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ float4 lumaNwNeSwSe;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ asm {
+ tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #else
+ asm {
+ tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #endif
+/*--------------------------------------------------------------------------*/
+ lumaNwNeSwSe.y += 1.0/384.0;
+ float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);
+ float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);
+/*--------------------------------------------------------------------------*/
+ float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ float lumaMinM = min(lumaMin, rgbyM.w);
+ float lumaMaxM = max(lumaMax, rgbyM.w);
+ #else
+ float lumaMinM = min(lumaMin, rgbyM.y);
+ float lumaMaxM = max(lumaMax, rgbyM.y);
+ #endif
+ if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ float2 dir;
+ dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx);
+ dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy);
+ dir = normalize(dir);
+/*--------------------------------------------------------------------------*/
+ float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw;
+/*--------------------------------------------------------------------------*/
+ float4 dir2;
+ float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness;
+ dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5);
+ dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0));
+ float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0));
+ float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0));
+ float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+ float4 rgbyA = rgbyN1 + rgbyP1;
+ float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB;
+ rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA;
+ return rgbyR; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)
+
+==============================================================================
+The code below does not exactly match the assembly.
+I have a feeling that 12 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h0.w(TRUE), v5.xwxx, #0
+ 6: addh h0.z(TRUE), -h2, h0.w
+ 7: texpkb h1.w(TRUE), v5, #0
+ 9: addh h0.x(TRUE), h0.z, -h1.w
+ 10: addh h3.w(TRUE), h0.z, h1
+ 11: texpkb h2.w(TRUE), v5.zwzz, #0
+ 13: addh h0.z(TRUE), h3.w, -h2.w
+ 14: addh h0.x(TRUE), h2.w, h0
+ 15: nrmh h1.xz(TRUE), h0_n
+ 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|
+ 17: maxh h4.w(TRUE), h0, h1
+ 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n
+ 19: movr r1.zw(TRUE), v4.xxxy
+ 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww
+ 22: minh h5.w(TRUE), h0, h1
+ 23: texpkb h0(TRUE), r2.xzxx, #0
+ 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1
+ 27: maxh h4.x(TRUE), h2.z, h2.w
+ 28: texpkb h1(TRUE), r0.zwzz, #0
+ 30: addh_d2 h1(TRUE), h0, h1
+ 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 33: texpkb h0(TRUE), r0, #0
+ 35: minh h4.z(TRUE), h2, h2.w
+ 36: fenct TRUE
+ 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 39: texpkb h2(TRUE), r1, #0
+ 41: addh_d2 h0(TRUE), h0, h2
+ 42: maxh h2.w(TRUE), h4, h4.x
+ 43: minh h2.x(TRUE), h5.w, h4.z
+ 44: addh_d2 h0(TRUE), h0, h1
+ 45: slth h2.x(TRUE), h0.w, h2
+ 46: sgth h2.w(TRUE), h0, h2
+ 47: movh h0(TRUE), h0
+ 48: addx.c0 rc(TRUE), h2, h2.w
+ 49: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---;
+ | SCB1 | add | 10: ADDh h3.w, h0.---z, h1;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h2.w---, h0;
+ | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-;
+ | | |
+ 5 | SCT1 | mov | 15: NRMh h1.xz, h0;
+ | SRB | nrm | 15: NRMh h1.xz, h0;
+ | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|;
+ | SCB1 | max | 17: MAXh h4.w, h0, h1;
+ | | |
+ 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0;
+ | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy;
+ | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-;
+ | SCB1 | min | 22: MINh h5.w, h0, h1;
+ | | |
+ 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---;
+ | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1;
+ | | |
+ 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | SCB0/1 | add | 30: ADDh/2 h1, h0, h1;
+ | | |
+ 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB1 | min | 35: MINh h4.z, h2, h2.--w-;
+ | | |
+ 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | SCB0/1 | add | 41: ADDh/2 h0, h0, h2;
+ | | |
+ 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---;
+ | SCT1 | max | 42: MAXh h2.w, h4, h4.---x;
+ | SCB0/1 | add | 44: ADDh/2 h0, h0, h1;
+ | | |
+ 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2;
+ | SCT1 | set | 46: SGTh h2.w, h0, h2;
+ | SCB0/1 | mul | 47: MOVh h0, h0;
+ | | |
+ 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---;
+ | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 0% 0% 50%
+ 6: 100% 0% 75%
+ 7: 0% 100% 75%
+ 8: 0% 100% 100%
+ 9: 0% 100% 25%
+ 10: 0% 100% 100%
+ 11: 50% 0% 100%
+ 12: 50% 0% 100%
+ 13: 25% 0% 100%
+
+MEAN: 17% 61% 67%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 0% 100%
+ 2: 0% 0% 100% 0% 100%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 0% 0% 0% 100% 100%
+ 6: 100% 100% 0% 100% 100%
+ 7: 0% 0% 100% 100% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 0% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 100% 100% 0% 100% 100%
+ 12: 100% 100% 0% 100% 100%
+ 13: 100% 0% 0% 100% 100%
+
+MEAN: 30% 23% 61% 76% 100%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 13 cycles, 3 r regs, 923,076,923 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O3
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 dir;
+ half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ lumaNe.w += half(1.0/512.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+ #else
+ lumaNe.y += half(1.0/512.0);
+ dir.x = -lumaNe.y;
+ dir.z = -lumaNe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+ #else
+ dir.x += lumaSw.y;
+ dir.z += lumaSw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+ #else
+ dir.x -= lumaNw.y;
+ dir.z += lumaNw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+ #else
+ dir.x += lumaSe.y;
+ dir.z -= lumaSe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (7)
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (8)
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (11)
+ // compilier moves these scalar ops up to other cycles
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ #else
+ half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y));
+ half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y));
+ #endif
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (12)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (13)
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)
+
+==============================================================================
+The code mostly matches the assembly.
+I have a feeling that 14 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks).
+Will look at fixing this for FXAA 3.12.
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h1.w(TRUE), v5.xwxx, #0
+ 6: addh h0.x(TRUE), h1.w, -h2.y
+ 7: texpkb h2.w(TRUE), v5.zwzz, #0
+ 9: minh h4.w(TRUE), h2.y, h2
+ 10: maxh h5.x(TRUE), h2.y, h2.w
+ 11: texpkb h0.w(TRUE), v5, #0
+ 13: addh h3.w(TRUE), -h0, h0.x
+ 14: addh h0.x(TRUE), h0.w, h0
+ 15: addh h0.z(TRUE), -h2.w, h0.x
+ 16: addh h0.x(TRUE), h2.w, h3.w
+ 17: minh h5.y(TRUE), h0.w, h1.w
+ 18: nrmh h2.xz(TRUE), h0_n
+ 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|
+ 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w
+ 21: movr r1.zw(TRUE), v4.xxxy
+ 22: maxh h2.w(TRUE), h0, h1
+ 23: fenct TRUE
+ 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 26: texpkb h0(TRUE), r0, #0
+ 28: maxh h5.x(TRUE), h2.w, h5
+ 29: minh h5.w(TRUE), h5.y, h4
+ 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 32: texpkb h2(TRUE), r1, #0
+ 34: addh_d2 h2(TRUE), h0, h2
+ 35: texpkb h1(TRUE), v4, #0
+ 37: maxh h5.y(TRUE), h5.x, h1.w
+ 38: minh h4.w(TRUE), h1, h5
+ 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 41: texpkb h0(TRUE), r0, #0
+ 43: addh_m8 h5.z(TRUE), h5.y, -h4.w
+ 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 46: texpkb h3(TRUE), r2, #0
+ 48: addh_d2 h0(TRUE), h0, h3
+ 49: addh_d2 h3(TRUE), h0, h2
+ 50: movh h0(TRUE), h3
+ 51: slth h3.x(TRUE), h3.w, h5.w
+ 52: sgth h3.w(TRUE), h3, h5.x
+ 53: addx.c0 rc(TRUE), h3.x, h3
+ 54: slth.c0 rc(TRUE), h5.z, h5
+ 55: movh h0(c0.NE.w), h2
+ 56: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---;
+ | SCB1 | min | 9: MINh h4.w, h2.---y, h2;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h0.w---, h0;
+ | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x;
+ | | |
+ 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---;
+ | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-;
+ | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--;
+ | | |
+ 6 | SCT1 | mov | 18: NRMh h2.xz, h0;
+ | SRB | nrm | 18: NRMh h2.xz, h0;
+ | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|;
+ | | |
+ 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--;
+ | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy;
+ | SCB1 | max | 22: MAXh h2.w, h0, h1;
+ | | |
+ 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | SCB0 | max | 28: MAXh h5.x, h2.w---, h5;
+ | SCB1 | min | 29: MINh h5.w, h5.---y, h4;
+ | | |
+ 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | SCB0/1 | add | 34: ADDh/2 h2, h0, h2;
+ | | |
+ 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--;
+ | SCB1 | min | 38: MINh h4.w, h1, h5;
+ | | |
+ 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--;
+ | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--;
+ | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-;
+ | | |
+ 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | SCB0/1 | add | 48: ADDh/2 h0, h0, h3;
+ | | |
+ 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2;
+ | SCB0/1 | mul | 50: MOVh h0, h3;
+ | | |
+ 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---;
+ | SCT1 | set | 52: SGTh h3.w, h3, h5.---x;
+ | SCB0 | set | 54: SLThc0 rc, h5.z---, h5;
+ | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3;
+ | | |
+ 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2;
+ | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 50% 0% 25%
+ 6: 0% 0% 25%
+ 7: 100% 0% 25%
+ 8: 0% 100% 50%
+ 9: 0% 100% 100%
+ 10: 0% 100% 50%
+ 11: 0% 100% 75%
+ 12: 0% 100% 100%
+ 13: 100% 0% 100%
+ 14: 50% 0% 50%
+ 15: 100% 0% 100%
+
+MEAN: 26% 60% 56%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 100% 0%
+ 2: 0% 0% 100% 100% 0%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 100% 100% 0% 100% 0%
+ 6: 0% 0% 0% 0% 100%
+ 7: 100% 100% 0% 0% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 100% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 0% 0% 100% 100% 100%
+ 12: 0% 0% 100% 100% 100%
+ 13: 100% 100% 0% 100% 100%
+ 14: 100% 100% 0% 100% 100%
+ 15: 100% 100% 0% 100% 100%
+
+MEAN: 33% 33% 60% 86% 80%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 15 cycles, 3 r regs, 800,000,000 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O2
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaNe = rgbyNe.w + half(1.0/512.0);
+ #else
+ half lumaNe = rgbyNe.y + half(1.0/512.0);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaSwNegNe = lumaSw.w - lumaNe;
+ #else
+ half lumaSwNegNe = lumaSw.y - lumaNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);
+ half lumaMinNwSw = min(lumaNw.w, lumaSw.w);
+ #else
+ half lumaMaxNwSw = max(lumaNw.y, lumaSw.y);
+ half lumaMinNwSw = min(lumaNw.y, lumaSw.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half dirZ = lumaNw.w + lumaSwNegNe;
+ half dirX = -lumaNw.w + lumaSwNegNe;
+ #else
+ half dirZ = lumaNw.y + lumaSwNegNe;
+ half dirX = -lumaNw.y + lumaSwNegNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half3 dir;
+ dir.y = 0.0;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x = lumaSe.w + dirX;
+ dir.z = -lumaSe.w + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.w);
+ #else
+ dir.x = lumaSe.y + dirX;
+ dir.z = -lumaSe.y + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir).xz;
+ half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (7)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNeSe = max(lumaNe, lumaSe.w);
+ #else
+ half lumaMaxNeSe = max(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (8)
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);
+ half lumaMin = min(lumaMinNwSw, lumaMinNeSe);
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ #else
+ half lumaMaxM = max(lumaMax, rgbyM.y);
+ half lumaMinM = min(lumaMin, rgbyM.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (11)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+// (12)
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (13)
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (14)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+ bool earlyExit = lumaRangeM < lumaMax;
+ bool twoTap = twoTapLt || twoTapGt;
+/*--------------------------------------------------------------------------*/
+// (15)
+ if(twoTap) rgby2 = rgby1;
+ if(earlyExit) rgby2 = rgbyM;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
diff --git a/src/Runtime/res/effectlib/Fxaa3_8.glsllib b/src/Runtime/res/effectlib/Fxaa3_8.glsllib
new file mode 100644
index 00000000..aa25c293
--- /dev/null
+++ b/src/Runtime/res/effectlib/Fxaa3_8.glsllib
@@ -0,0 +1,1423 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 - 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+/*============================================================================
+
+
+ NVIDIA FXAA III.8 by TIMOTHY LOTTES
+
+
+------------------------------------------------------------------------------
+ INTEGRATION CHECKLIST
+------------------------------------------------------------------------------
+(1.)
+In the shader source,
+setup defines for the desired configuration.
+Example,
+
+ #define FXAA_PC 1
+ #define FXAA_HLSL_3 1
+ #define FXAA_LINEAR 1
+
+(2.)
+Then include this file,
+
+
+
+(3.)
+Then call the FXAA pixel shader from within your desired shader,
+
+ return FxaaPixelShader(pos, posPos, tex, rcpFrame, rcpFrameOpt);
+
+(4.)
+Insure pass prior to FXAA outputs RGBL.
+See next section.
+
+(5.)
+Setup engine to provide "rcpFrame" and "rcpFrameOpt" constants.
+Not using constants will result in a performance loss.
+
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ float2 rcpFrame
+
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+
+(6.)
+Have FXAA vertex shader run as a full screen triangle,
+and output "pos" and "posPos" such that inputs in the pixel shader provide,
+
+ // {xy} = center of pixel
+ float2 pos,
+
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+
+(7.)
+Insure the texture sampler used by FXAA is set to bilinear filtering.
+
+
+------------------------------------------------------------------------------
+ INTEGRATION - RGBL AND COLORSPACE
+------------------------------------------------------------------------------
+FXAA3 requires RGBL as input.
+
+RGB should be LDR (low dynamic range).
+Specifically do FXAA after tonemapping.
+
+RGB data as returned by a texture fetch can be linear or non-linear.
+Note an "sRGB format" texture counts as linear,
+because the result of a texture fetch is linear data.
+Regular "RGBA8" textures in the sRGB colorspace are non-linear.
+If a texture fetch results linear data the following is required,
+
+ #define FXAA_LINEAR 1
+
+Otherwise,
+
+ #define FXAA_LINEAR 0
+
+Luma must be stored in the alpha channel prior to running FXAA.
+This luma value must be gamma 2.0 encoded if using FXAA_LINEAR 1.
+If using FXAA_LINEAR 0, luma should match the perceptual space used for RGB.
+
+Example pass before FXAA where output is gamma 2.0 encoded,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ color.a = dot(color.rgb, float3(0.299, 0.587, 0.114)); // compute luma
+ return color;
+
+Another example where output is linear encoded,
+say for instance writing to an sRGB formated render target,
+where the render target does the conversion back to sRGB after blending,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.a = sqrt(dot(color.rgb, float3(0.299, 0.587, 0.114))); // compute luma
+ return color;
+
+Getting luma correct is required for the algorithm to work correctly.
+
+
+------------------------------------------------------------------------------
+ COMPLEX INTEGRATION
+------------------------------------------------------------------------------
+Q. What if the engine is blending into RGB before wanting to run FXAA?
+
+A. In the last opaque pass prior to FXAA,
+ have the pass write out luma into alpha.
+ Then blend into RGB only.
+ FXAA should be able to run ok
+ assuming the blending pass did not any add aliasing.
+ This should be the common case for particles and common blending passes.
+
+============================================================================*/
+
+/*============================================================================
+
+ INTEGRATION KNOBS
+
+============================================================================*/
+//
+// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).
+//
+// 1 = Use API.
+// 0 = Don't use API.
+//
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PS3
+ #define FXAA_PS3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360
+ #define FXAA_360 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_PC
+ //
+ // FXAA Quality
+ // The high quality PC algorithm.
+ //
+ #define FXAA_PC 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PC_CONSOLE
+ //
+ // The console algorithm for PC is included
+ // for developers targeting really low spec machines.
+ //
+ #define FXAA_PC_CONSOLE 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_120
+ #define FXAA_GLSL_120 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_130
+ #define FXAA_GLSL_130 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_3
+ #define FXAA_HLSL_3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_4
+ #define FXAA_HLSL_4 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_5
+ #define FXAA_HLSL_5 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_EARLY_EXIT
+ //
+ // Controls algorithm's early exit path.
+ // On PS3 turning this on adds 2 cycles to the shader.
+ // On 360 turning this off adds 10ths of a millisecond to the shader.
+ // Turning this off on console will result in a more blurry image.
+ // So this defaults to on.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_EARLY_EXIT 1
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_DISCARD
+ //
+ // Only valid for PC OpenGL currently.
+ //
+ // 1 = Use discard on pixels which don't need AA.
+ // For APIs which enable concurrent TEX+ROP from same surface.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ //
+ #define FXAA_DISCARD 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_LINEAR
+ //
+ // 0 = Work in non-linear color space.
+ // Use this for standard 32-bit RGBA formats.
+ //
+ // 1 = Work in RGB=linear, A=non-linear luma.
+ // Use this for sRGB and FP16 formats.
+ // Works with either FXAA_ALGORITHM = 1 or 0.
+ //
+ #define FXAA_LINEAR 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_FAST_PIXEL_OFFSET
+ //
+ // Used for GLSL 120 only.
+ //
+ // 1 = GL API supports fast pixel offsets
+ // 0 = do not use fast pixel offsets
+ //
+ #ifdef GL_EXT_gpu_shader4
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifndef FXAA_FAST_PIXEL_OFFSET
+ #define FXAA_FAST_PIXEL_OFFSET 0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GATHER4_ALPHA
+ //
+ // 1 = API supports gather4 on alpha channel.
+ // 0 = API does not support gather4 on alpha channel.
+ //
+#ifdef GL_ES
+ #if __VERSION__ >= 310
+ #ifdef GL_EXT_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#else
+ #if (FXAA_HLSL_5 == 1)
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_EXT_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#endif
+#endif
+
+/*============================================================================
+ FXAA CONSOLE - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_CONSOLE__EDGE_SHARPNESS
+ //
+ // Consoles the sharpness of edges.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 4 and 8.
+ // These options use the shaders ability to a free *|/ by 4|8.
+ //
+ // 8.0 is sharper
+ // 4.0 is softer
+ //
+ #if 1
+ #define FXAA_CONSOLE__EDGE_SHARPNESS 8.0
+ #else
+ #define FXAA_CONSOLE__EDGE_SHARPNESS 4.0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE__EDGE_THRESHOLD
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 0.25 and 0.125.
+ // These options use the shaders ability to a free *|/ by 4|8.
+ //
+ // 0.125 leaves less aliasing, but is softer
+ // 0.25 leaves more aliasing, and is sharper
+ //
+ #if 1
+ #define FXAA_CONSOLE__EDGE_THRESHOLD 0.125
+ #else
+ #define FXAA_CONSOLE__EDGE_THRESHOLD 0.25
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE__EDGE_THRESHOLD_MIN
+ //
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // This does not apply to PS3.
+ // PS3 was simplified to avoid more shader instructions.
+ //
+ #define FXAA_CONSOLE__EDGE_THRESHOLD_MIN 0.05
+#endif
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_QUALITY__EDGE_THRESHOLD
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ //
+ // 1/3 - too little
+ // 1/4 - low quality
+ // 1/6 - default
+ // 1/8 - high quality
+ // 1/16 - overkill
+ //
+ #define FXAA_QUALITY__EDGE_THRESHOLD (1.0/6.0)
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_QUALITY__EDGE_THRESHOLD_MIN
+ //
+ // Trims the algorithm from processing darks.
+ //
+ // 1/32 - visible limit
+ // 1/16 - high quality
+ // 1/12 - upper limit (default, the start of visible unfiltered edges)
+ //
+ #define FXAA_QUALITY__EDGE_THRESHOLD_MIN (1.0/12.0)
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_QUALITY__SUBPIX_CAP
+ //
+ // Insures fine detail is not completely removed.
+ // This partly overrides FXAA_SUBPIX_TRIM.
+ //
+ // 3/4 - default amount of filtering
+ // 7/8 - high amount of filtering
+ // 1 - no capping of filtering
+ //
+ #define FXAA_QUALITY__SUBPIX_CAP (3.0/4.0)
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_QUALITY__SUBPIX_TRIM
+ //
+ // Controls removal of sub-pixel aliasing,
+ //
+ // 1/2 - low removal (sharper but more sub-pixel aliasing)
+ // 1/3 - medium removal
+ // 1/4 - default removal
+ // 1/8 - high removal
+ // 0 - complete removal (softer but less sub-pixel aliasing)
+ //
+ #define FXAA_QUALITY__SUBPIX_TRIM (1.0/4.0)
+#endif
+
+
+/*============================================================================
+
+ API PORTING
+
+============================================================================*/
+#if FXAA_GLSL_120
+ // Requires,
+ // #version 120
+ // And at least,
+ // #extension GL_EXT_gpu_shader4 : enable
+ // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
+ #define half float
+ #define half2 vec2
+ #define half3 vec3
+ #define half4 vec4
+ #define int2 ivec2
+ #define float2 vec2
+ #define float3 vec3
+ #define float4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaDiscard discard
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaLerp(x,y,s) mix(x,y,s)
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
+ #if (FXAA_FAST_PIXEL_OFFSET == 1)
+ #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
+ #else
+ #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
+ #endif
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if FXAA_GLSL_130
+ // Requires "#version 130" or better
+ #define half float
+ #define half2 vec2
+ #define half3 vec3
+ #define half4 vec4
+ #define int2 ivec2
+ #define float2 vec2
+ #define float3 vec3
+ #define float4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaDiscard discard
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaLerp(x,y,s) mix(x,y,s)
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1)
+ #define int2 float2
+ #define FxaaInt2 float2
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaDiscard clip(-1)
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) saturate(x)
+ #define FxaaLerp(x,y,s) lerp(x,y,s)
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
+ #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
+#endif
+/*--------------------------------------------------------------------------*/
+#if FXAA_HLSL_4
+ #define FxaaInt2 int2
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaDiscard clip(-1)
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) saturate(x)
+ #define FxaaLerp(x,y,s) lerp(x,y,s)
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+#endif
+/*--------------------------------------------------------------------------*/
+#if FXAA_HLSL_5
+ #define FxaaInt2 int2
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaDiscard clip(-1)
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) saturate(x)
+ #define FxaaLerp(x,y,s) lerp(x,y,s)
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+ #define FxaaTexAlpha4(t, p, r) t.tex.GatherAlpha(t.smpl, p)
+ #define FxaaTexOffAlpha4(t, p, o, r) t.tex.GatherAlpha(t.smpl, p, o)
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - 360 PIXEL SHADER
+
+------------------------------------------------------------------------------
+Might be some optimizations left here,
+as of this latest change didn't have a PIX dump to verify if TEX bound.
+============================================================================*/
+#if (FXAA_360 == 1)
+/*--------------------------------------------------------------------------*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = alpha output is junk value
+ FxaaTex tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PC version of FXAA Console
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+ half4 lumaNwNeSwSe;
+ lumaNwNeSwSe.x = FxaaTexTop(tex, posPos.xy).w;
+ lumaNwNeSwSe.y = FxaaTexTop(tex, posPos.zy).w;
+ lumaNwNeSwSe.z = FxaaTexTop(tex, posPos.xw).w;
+ lumaNwNeSwSe.w = FxaaTexTop(tex, posPos.zw).w;
+/*--------------------------------------------------------------------------*/
+ half4 rgbyM = FxaaTexTop(tex, pos.xy);
+/*--------------------------------------------------------------------------*/
+ lumaNwNeSwSe.y += 1.0/384.0;
+/*--------------------------------------------------------------------------*/
+ half2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ half2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+/*--------------------------------------------------------------------------*/
+ half lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);
+ half lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);
+/*--------------------------------------------------------------------------*/
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD))
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ half2 dir;
+ dir.x = dot(lumaNwNeSwSe, float4(-1.0, -1.0, 1.0, 1.0));
+ dir.y = dot(lumaNwNeSwSe, float4( 1.0, -1.0, 1.0,-1.0));
+/*--------------------------------------------------------------------------*/
+ half2 dir1;
+ dir1 = normalize(dir.xy);
+/*--------------------------------------------------------------------------*/
+ half dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * FXAA_CONSOLE__EDGE_SHARPNESS;
+ half2 dir2;
+ dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ half4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * rcpFrameOpt.zw);
+ half4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * rcpFrameOpt.zw);
+ half4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * rcpFrameOpt.xy);
+ half4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * rcpFrameOpt.xy);
+/*--------------------------------------------------------------------------*/
+ half4 rgbyA = rgbyN1 * 0.5 + rgbyP1 * 0.5;
+ half4 rgbyB = rgbyN2 * 0.25 + rgbyP2 * 0.25 + rgbyA * 0.5;
+/*--------------------------------------------------------------------------*/
+ bool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
+ if(twoTap) rgbyB.xyz = rgbyA.xyz;
+ return rgbyB;
+}
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)
+
+==============================================================================
+The code below does not exactly match the assembly.
+I have a feeling that 12 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h0.w(TRUE), v5.xwxx, #0
+ 6: addh h0.z(TRUE), -h2, h0.w
+ 7: texpkb h1.w(TRUE), v5, #0
+ 9: addh h0.x(TRUE), h0.z, -h1.w
+ 10: addh h3.w(TRUE), h0.z, h1
+ 11: texpkb h2.w(TRUE), v5.zwzz, #0
+ 13: addh h0.z(TRUE), h3.w, -h2.w
+ 14: addh h0.x(TRUE), h2.w, h0
+ 15: nrmh h1.xz(TRUE), h0_n
+ 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|
+ 17: maxh h4.w(TRUE), h0, h1
+ 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n
+ 19: movr r1.zw(TRUE), v4.xxxy
+ 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww
+ 22: minh h5.w(TRUE), h0, h1
+ 23: texpkb h0(TRUE), r2.xzxx, #0
+ 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1
+ 27: maxh h4.x(TRUE), h2.z, h2.w
+ 28: texpkb h1(TRUE), r0.zwzz, #0
+ 30: addh_d2 h1(TRUE), h0, h1
+ 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 33: texpkb h0(TRUE), r0, #0
+ 35: minh h4.z(TRUE), h2, h2.w
+ 36: fenct TRUE
+ 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 39: texpkb h2(TRUE), r1, #0
+ 41: addh_d2 h0(TRUE), h0, h2
+ 42: maxh h2.w(TRUE), h4, h4.x
+ 43: minh h2.x(TRUE), h5.w, h4.z
+ 44: addh_d2 h0(TRUE), h0, h1
+ 45: slth h2.x(TRUE), h0.w, h2
+ 46: sgth h2.w(TRUE), h0, h2
+ 47: movh h0(TRUE), h0
+ 48: addx.c0 rc(TRUE), h2, h2.w
+ 49: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---;
+ | SCB1 | add | 10: ADDh h3.w, h0.---z, h1;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h2.w---, h0;
+ | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-;
+ | | |
+ 5 | SCT1 | mov | 15: NRMh h1.xz, h0;
+ | SRB | nrm | 15: NRMh h1.xz, h0;
+ | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|;
+ | SCB1 | max | 17: MAXh h4.w, h0, h1;
+ | | |
+ 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0;
+ | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy;
+ | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-;
+ | SCB1 | min | 22: MINh h5.w, h0, h1;
+ | | |
+ 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---;
+ | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1;
+ | | |
+ 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | SCB0/1 | add | 30: ADDh/2 h1, h0, h1;
+ | | |
+ 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB1 | min | 35: MINh h4.z, h2, h2.--w-;
+ | | |
+ 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | SCB0/1 | add | 41: ADDh/2 h0, h0, h2;
+ | | |
+ 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---;
+ | SCT1 | max | 42: MAXh h2.w, h4, h4.---x;
+ | SCB0/1 | add | 44: ADDh/2 h0, h0, h1;
+ | | |
+ 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2;
+ | SCT1 | set | 46: SGTh h2.w, h0, h2;
+ | SCB0/1 | mul | 47: MOVh h0, h0;
+ | | |
+ 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---;
+ | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 0% 0% 50%
+ 6: 100% 0% 75%
+ 7: 0% 100% 75%
+ 8: 0% 100% 100%
+ 9: 0% 100% 25%
+ 10: 0% 100% 100%
+ 11: 50% 0% 100%
+ 12: 50% 0% 100%
+ 13: 25% 0% 100%
+
+MEAN: 17% 61% 67%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 0% 100%
+ 2: 0% 0% 100% 0% 100%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 0% 0% 0% 100% 100%
+ 6: 100% 100% 0% 100% 100%
+ 7: 0% 0% 100% 100% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 0% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 100% 100% 0% 100% 100%
+ 12: 100% 100% 0% 100% 100%
+ 13: 100% 0% 0% 100% 100%
+
+MEAN: 30% 23% 61% 76% 100%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 13 cycles, 3 r regs, 923,076,923 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)
+/*--------------------------------------------------------------------------*/
+#pragma disablepc all
+#pragma option O3
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = luma in perceptual color space (not linear)
+ sampler2D tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PS3
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 dir;
+ half4 lumaNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0));
+ lumaNe.w += half(1.0/512.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0));
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0));
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0));
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+/*--------------------------------------------------------------------------*/
+// (5)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (7)
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (8)
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy;
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (11)
+ // compilier moves these scalar ops up to other cycles
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (12)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+/*--------------------------------------------------------------------------*/
+// (13)
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)
+
+==============================================================================
+The code mostly matches the assembly.
+I have a feeling that 14 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h1.w(TRUE), v5.xwxx, #0
+ 6: addh h0.x(TRUE), h1.w, -h2.y
+ 7: texpkb h2.w(TRUE), v5.zwzz, #0
+ 9: minh h4.w(TRUE), h2.y, h2
+ 10: maxh h5.x(TRUE), h2.y, h2.w
+ 11: texpkb h0.w(TRUE), v5, #0
+ 13: addh h3.w(TRUE), -h0, h0.x
+ 14: addh h0.x(TRUE), h0.w, h0
+ 15: addh h0.z(TRUE), -h2.w, h0.x
+ 16: addh h0.x(TRUE), h2.w, h3.w
+ 17: minh h5.y(TRUE), h0.w, h1.w
+ 18: nrmh h2.xz(TRUE), h0_n
+ 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|
+ 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w
+ 21: movr r1.zw(TRUE), v4.xxxy
+ 22: maxh h2.w(TRUE), h0, h1
+ 23: fenct TRUE
+ 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 26: texpkb h0(TRUE), r0, #0
+ 28: maxh h5.x(TRUE), h2.w, h5
+ 29: minh h5.w(TRUE), h5.y, h4
+ 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 32: texpkb h2(TRUE), r1, #0
+ 34: addh_d2 h2(TRUE), h0, h2
+ 35: texpkb h1(TRUE), v4, #0
+ 37: maxh h5.y(TRUE), h5.x, h1.w
+ 38: minh h4.w(TRUE), h1, h5
+ 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 41: texpkb h0(TRUE), r0, #0
+ 43: addh_m8 h5.z(TRUE), h5.y, -h4.w
+ 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 46: texpkb h3(TRUE), r2, #0
+ 48: addh_d2 h0(TRUE), h0, h3
+ 49: addh_d2 h3(TRUE), h0, h2
+ 50: movh h0(TRUE), h3
+ 51: slth h3.x(TRUE), h3.w, h5.w
+ 52: sgth h3.w(TRUE), h3, h5.x
+ 53: addx.c0 rc(TRUE), h3.x, h3
+ 54: slth.c0 rc(TRUE), h5.z, h5
+ 55: movh h0(c0.NE.w), h2
+ 56: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---;
+ | SCB1 | min | 9: MINh h4.w, h2.---y, h2;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h0.w---, h0;
+ | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x;
+ | | |
+ 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---;
+ | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-;
+ | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--;
+ | | |
+ 6 | SCT1 | mov | 18: NRMh h2.xz, h0;
+ | SRB | nrm | 18: NRMh h2.xz, h0;
+ | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|;
+ | | |
+ 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--;
+ | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy;
+ | SCB1 | max | 22: MAXh h2.w, h0, h1;
+ | | |
+ 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | SCB0 | max | 28: MAXh h5.x, h2.w---, h5;
+ | SCB1 | min | 29: MINh h5.w, h5.---y, h4;
+ | | |
+ 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | SCB0/1 | add | 34: ADDh/2 h2, h0, h2;
+ | | |
+ 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--;
+ | SCB1 | min | 38: MINh h4.w, h1, h5;
+ | | |
+ 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--;
+ | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--;
+ | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-;
+ | | |
+ 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | SCB0/1 | add | 48: ADDh/2 h0, h0, h3;
+ | | |
+ 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2;
+ | SCB0/1 | mul | 50: MOVh h0, h3;
+ | | |
+ 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---;
+ | SCT1 | set | 52: SGTh h3.w, h3, h5.---x;
+ | SCB0 | set | 54: SLThc0 rc, h5.z---, h5;
+ | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3;
+ | | |
+ 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2;
+ | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 50% 0% 25%
+ 6: 0% 0% 25%
+ 7: 100% 0% 25%
+ 8: 0% 100% 50%
+ 9: 0% 100% 100%
+ 10: 0% 100% 50%
+ 11: 0% 100% 75%
+ 12: 0% 100% 100%
+ 13: 100% 0% 100%
+ 14: 50% 0% 50%
+ 15: 100% 0% 100%
+
+MEAN: 26% 60% 56%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 100% 0%
+ 2: 0% 0% 100% 100% 0%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 100% 100% 0% 100% 0%
+ 6: 0% 0% 0% 0% 100%
+ 7: 100% 100% 0% 0% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 100% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 0% 0% 100% 100% 100%
+ 12: 0% 0% 100% 100% 100%
+ 13: 100% 100% 0% 100% 100%
+ 14: 100% 100% 0% 100% 100%
+ 15: 100% 100% 0% 100% 100%
+
+MEAN: 33% 33% 60% 86% 80%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 15 cycles, 3 r regs, 800,000,000 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)
+/*--------------------------------------------------------------------------*/
+#pragma disablepc all
+#pragma option O2
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = luma in perceptual color space (not linear)
+ sampler2D tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PS3
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 rgbyNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0));
+ half lumaNe = rgbyNe.w + half(1.0/512.0);
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0));
+ half lumaSwNegNe = lumaSw.w - lumaNe;
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0));
+ half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);
+ half lumaMinNwSw = min(lumaNw.w, lumaSw.w);
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0));
+ half dirZ = lumaNw.w + lumaSwNegNe;
+ half dirX = -lumaNw.w + lumaSwNegNe;
+/*--------------------------------------------------------------------------*/
+// (5)
+ half3 dir;
+ dir.y = 0.0;
+ dir.x = lumaSe.w + dirX;
+ dir.z = -lumaSe.w + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.w);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir).xz;
+ half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (7)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half lumaMaxNeSe = max(lumaNe, lumaSe.w);
+/*--------------------------------------------------------------------------*/
+// (8)
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw;
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);
+ half lumaMin = min(lumaMinNwSw, lumaMinNeSe);
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw;
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ half lumaMinM = min(lumaMin, rgbyM.w);
+/*--------------------------------------------------------------------------*/
+// (11)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy;
+ half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__EDGE_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+// (12)
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (13)
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (14)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ bool earlyExit = lumaRangeM < lumaMax;
+ bool twoTap = twoTapLt || twoTapGt;
+/*--------------------------------------------------------------------------*/
+// (15)
+ if(twoTap) rgby2 = rgby1;
+ if(earlyExit) rgby2 = rgbyM;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - PC PIXEL SHADER
+
+------------------------------------------------------------------------------
+Using a modified version of the PS3 version here to best target old hardware.
+============================================================================*/
+#if (FXAA_PC_CONSOLE == 1)
+/*--------------------------------------------------------------------------*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = alpha output is junk value
+ FxaaTex tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PC version of FXAA Console
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+ half4 dir;
+ dir.y = 0.0;
+ half4 lumaNe = FxaaTexTop(tex, posPos.zy);
+ lumaNe.w += half(1.0/384.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+/*--------------------------------------------------------------------------*/
+ half4 lumaSw = FxaaTexTop(tex, posPos.xw);
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+/*--------------------------------------------------------------------------*/
+ half4 lumaNw = FxaaTexTop(tex, posPos.xy);
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+/*--------------------------------------------------------------------------*/
+ half4 lumaSe = FxaaTexTop(tex, posPos.zw);
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+/*==========================================================================*/
+ #if (FXAA_EARLY_EXIT == 1)
+ half4 rgbyM = FxaaTexTop(tex, pos.xy);
+/*--------------------------------------------------------------------------*/
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+/*--------------------------------------------------------------------------*/
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+/*--------------------------------------------------------------------------*/
+ if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD))
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+ #endif
+/*==========================================================================*/
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+ temp1N = FxaaTexTop(tex, temp1N.xy);
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+ rgby1 = FxaaTexTop(tex, rgby1.xy);
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy;
+ temp2N = FxaaTexTop(tex, temp2N.xy);
+/*--------------------------------------------------------------------------*/
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy;
+ rgby2 = FxaaTexTop(tex, rgby2.xy);
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_EARLY_EXIT == 0)
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ #endif
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+/*--------------------------------------------------------------------------*/
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+#if (FXAA_PC == 1)
+/*--------------------------------------------------------------------------*/
+float4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xyzw} = not used on FXAA3 Quality
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ float2 rcpFrame,
+ // {xyzw} = not used on FXAA3 Quality
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 1)
+ float4 luma4A = FxaaTexOffAlpha4(tex, pos.xy, FxaaInt2(-1, -1), rcpFrame.xy);
+ #if (FXAA_DISCARD == 0)
+ float4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #endif
+ float4 luma4B = FxaaTexAlpha4(tex, pos.xy, rcpFrame.xy);
+ float lumaNE = FxaaTexOff(tex, pos.xy, FxaaInt2(1, -1), rcpFrame.xy).w;
+ float lumaSW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 1), rcpFrame.xy).w;
+ float lumaNW = luma4A.w;
+ float lumaN = luma4A.z;
+ float lumaW = luma4A.x;
+ float lumaM = luma4A.y;
+ float lumaE = luma4B.z;
+ float lumaS = luma4B.x;
+ float lumaSE = luma4B.y;
+ #else
+ float lumaN = FxaaTexOff(tex, pos.xy, FxaaInt2(0, -1), rcpFrame.xy).w;
+ float lumaW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 0), rcpFrame.xy).w;
+ float4 rgbyM = FxaaTexTop(tex, pos.xy);
+ float lumaE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1, 0), rcpFrame.xy).w;
+ float lumaS = FxaaTexOff(tex, pos.xy, FxaaInt2( 0, 1), rcpFrame.xy).w;
+ float lumaM = rgbyM.w;
+ #endif
+/*--------------------------------------------------------------------------*/
+ float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
+ float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
+ float range = rangeMax - rangeMin;
+/*--------------------------------------------------------------------------*/
+ if(range < max(FXAA_QUALITY__EDGE_THRESHOLD_MIN, rangeMax * FXAA_QUALITY__EDGE_THRESHOLD))
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 0)
+ float lumaNW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1,-1), rcpFrame.xy).w;
+ float lumaNE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1,-1), rcpFrame.xy).w;
+ float lumaSW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 1), rcpFrame.xy).w;
+ float lumaSE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1, 1), rcpFrame.xy).w;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #define FXAA_QUALITY__SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_QUALITY__SUBPIX_TRIM))
+/*--------------------------------------------------------------------------*/
+ float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
+ float rangeL = abs(lumaL - lumaM);
+ float blendL = FxaaSat((rangeL / range) - FXAA_QUALITY__SUBPIX_TRIM) * FXAA_QUALITY__SUBPIX_TRIM_SCALE;
+ blendL = min(FXAA_QUALITY__SUBPIX_CAP, blendL);
+/*--------------------------------------------------------------------------*/
+ float edgeVert =
+ abs(lumaNW + (-2.0 * lumaN) + lumaNE) +
+ 2.0 * abs(lumaW + (-2.0 * lumaM) + lumaE ) +
+ abs(lumaSW + (-2.0 * lumaS) + lumaSE);
+ float edgeHorz =
+ abs(lumaNW + (-2.0 * lumaW) + lumaSW) +
+ 2.0 * abs(lumaN + (-2.0 * lumaM) + lumaS ) +
+ abs(lumaNE + (-2.0 * lumaE) + lumaSE);
+ bool horzSpan = edgeHorz >= edgeVert;
+/*--------------------------------------------------------------------------*/
+ float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ float gradientN = abs(lumaN - lumaM);
+ float gradientS = abs(lumaS - lumaM);
+ lumaN = (lumaN + lumaM) * 0.5;
+ lumaS = (lumaS + lumaM) * 0.5;
+/*--------------------------------------------------------------------------*/
+ bool pairN = gradientN >= gradientS;
+ if(!pairN) lumaN = lumaS;
+ if(!pairN) gradientN = gradientS;
+ if(!pairN) lengthSign *= -1.0;
+ float2 posN;
+ posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
+ posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
+/*--------------------------------------------------------------------------*/
+ #define FXAA_SEARCH_STEPS 6
+ #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
+/*--------------------------------------------------------------------------*/
+ gradientN *= FXAA_SEARCH_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+ float2 posP = posN;
+ float2 offNP = horzSpan ?
+ FxaaFloat2(rcpFrame.x, 0.0) :
+ FxaaFloat2(0.0f, rcpFrame.y);
+ float lumaEndN;
+ float lumaEndP;
+ bool doneN = false;
+ bool doneP = false;
+ posN += offNP * (-1.5);
+ posP += offNP * ( 1.5);
+ for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
+ lumaEndN = FxaaTexTop(tex, posN.xy).w;
+ lumaEndP = FxaaTexTop(tex, posP.xy).w;
+ bool doneN2 = abs(lumaEndN - lumaN) >= gradientN;
+ bool doneP2 = abs(lumaEndP - lumaN) >= gradientN;
+ if(doneN2 && !doneN) posN += offNP;
+ if(doneP2 && !doneP) posP -= offNP;
+ if(doneN2 && doneP2) break;
+ doneN = doneN2;
+ doneP = doneP2;
+ if(!doneN) posN -= offNP * 2.0;
+ if(!doneP) posP += offNP * 2.0; }
+/*--------------------------------------------------------------------------*/
+ float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
+ float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
+/*--------------------------------------------------------------------------*/
+ bool directionN = dstN < dstP;
+ lumaEndN = directionN ? lumaEndN : lumaEndP;
+/*--------------------------------------------------------------------------*/
+ if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
+ lengthSign = 0.0;
+/*--------------------------------------------------------------------------*/
+ float spanLength = (dstP + dstN);
+ dstN = directionN ? dstN : dstP;
+ float subPixelOffset = 0.5 + (dstN * (-1.0/spanLength));
+ subPixelOffset += blendL * (1.0/8.0);
+ subPixelOffset *= lengthSign;
+ float3 rgbF = FxaaTexTop(tex, FxaaFloat2(
+ pos.x + (horzSpan ? 0.0 : subPixelOffset),
+ pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_LINEAR == 1)
+ lumaL *= lumaL;
+ #endif
+ float lumaF = dot(rgbF, float3(0.299, 0.587, 0.114)) + (1.0/(65536.0*256.0));
+ float lumaB = FxaaLerp(lumaF, lumaL, blendL);
+ float scale = min(4.0, lumaB/lumaF);
+ rgbF *= scale;
+ return float4(rgbF, lumaM); }
+/*==========================================================================*/
+#endif
+
+
+
diff --git a/src/Runtime/res/effectlib/SMAA.glsllib b/src/Runtime/res/effectlib/SMAA.glsllib
new file mode 100644
index 00000000..cadbbdf0
--- /dev/null
+++ b/src/Runtime/res/effectlib/SMAA.glsllib
@@ -0,0 +1,1444 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/**
+ * Copyright (C) 2011 Jorge Jimenez (jorge@iryoku.com)
+ * Copyright (C) 2011 Jose I. Echevarria (joseignacioechevarria@gmail.com)
+ * Copyright (C) 2011 Belen Masia (bmasia@unizar.es)
+ * Copyright (C) 2011 Fernando Navarro (fernandn@microsoft.com)
+ * Copyright (C) 2011 Diego Gutierrez (diegog@unizar.es)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution:
+ *
+ * "Uses SMAA. Copyright (C) 2011 by Jorge Jimenez, Jose I. Echevarria,
+ * Tiago Sousa, Belen Masia, Fernando Navarro and Diego Gutierrez."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the copyright holders.
+ */
+
+
+/**
+ * _______ ___ ___ ___ ___
+ * / || \/ | / \ / \
+ * | (---- | \ / | / ^ \ / ^ \
+ * \ \ | |\/| | / /_\ \ / /_\ \
+ * ----) | | | | | / _____ \ / _____ \
+ * |_______/ |__| |__| /__/ \__\ /__/ \__\
+ *
+ * E N H A N C E D
+ * S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G
+ *
+ * http://www.iryoku.com/smaa/
+ *
+ * Hi, welcome aboard!
+ *
+ * Here you'll find instructions to get the shader up and running as fast as
+ * possible.
+ *
+ * IMPORTANTE NOTICE: when updating, remember to update both this file and the
+ * precomputed textures! They may change from version to version.
+ *
+ * The shader has three passes, chained together as follows:
+ *
+ * |input|------------------·
+ * v |
+ * [ SMAA*EdgeDetection ] |
+ * v |
+ * |edgesTex| |
+ * v |
+ * [ SMAABlendingWeightCalculation ] |
+ * v |
+ * |blendTex| |
+ * v |
+ * [ SMAANeighborhoodBlending ] <------·
+ * v
+ * |output|
+ *
+ * Note that each [pass] has its own vertex and pixel shader.
+ *
+ * You've three edge detection methods to choose from: luma, color or depth.
+ * They represent different quality/performance and anti-aliasing/sharpness
+ * tradeoffs, so our recommendation is for you to choose the one that best
+ * suits your particular scenario:
+ *
+ * - Depth edge detection is usually the fastest but it may miss some edges.
+ *
+ * - Luma edge detection is usually more expensive than depth edge detection,
+ * but catches visible edges that depth edge detection can miss.
+ *
+ * - Color edge detection is usually the most expensive one but catches
+ * chroma-only edges.
+ *
+ * For quickstarters: just use luma edge detection.
+ *
+ * The general advice is to not rush the integration process and ensure each
+ * step is done correctly (don't try to integrate SMAA T2x with predicated edge
+ * detection from the start!). Ok then, let's go!
+ *
+ * 1. The first step is to create two RGBA temporal framebuffers for holding
+ * |edgesTex| and |blendTex|.
+ *
+ * In DX10, you can use a RG framebuffer for the edges texture, but in our
+ * experience it yields worse performance.
+ *
+ * On the Xbox 360, you can use the same framebuffer for resolving both
+ * |edgesTex| and |blendTex|, as they aren't needed simultaneously.
+ *
+ * 2. Both temporal framebuffers |edgesTex| and |blendTex| must be cleared
+ * each frame. Do not forget to clear the alpha channel!
+ *
+ * 3. The next step is loading the two supporting precalculated textures,
+ * 'areaTex' and 'searchTex'. You'll find them in the 'Textures' folder as
+ * C++ headers, and also as regular DDS files. They'll be needed for the
+ * 'SMAABlendingWeightCalculation' pass.
+ *
+ * If you use the C++ headers, be sure to load them in the format specified
+ * inside of them.
+ *
+ * 4. In DX9, all samplers must be set to linear filtering and clamp, with the
+ * exception of 'searchTex', which must be set to point filtering.
+ *
+ * 5. All texture reads and buffer writes must be non-sRGB, with the exception
+ * of the input read and the output write of input in
+ * 'SMAANeighborhoodBlending' (and only in this pass!). If sRGB reads in
+ * this last pass are not possible, the technique will work anyway, but
+ * will perform antialiasing in gamma space.
+ *
+ * IMPORTANT: for best results the input read for the color/luma edge
+ * detection should *NOT* be sRGB.
+ *
+ * 6. Before including SMAA.h you'll have to setup the framebuffer pixel size,
+ * the target and any optional configuration defines. Optionally you can
+ * use a preset.
+ *
+ * You have three targets available:
+ * SMAA_HLSL_3
+ * SMAA_HLSL_4
+ * SMAA_HLSL_4_1
+ * SMAA_GLSL_3 *
+ * SMAA_GLSL_4 *
+ *
+ * * (See SMAA_ONLY_COMPILE_VS below).
+ *
+ * And four presets:
+ * SMAA_PRESET_LOW (%60 of the quality)
+ * SMAA_PRESET_MEDIUM (%80 of the quality)
+ * SMAA_PRESET_HIGH (%95 of the quality)
+ * SMAA_PRESET_ULTRA (%99 of the quality)
+ *
+ * For example:
+ * #define SMAA_PIXEL_SIZE float2(1.0 / 1280.0, 1.0 / 720.0)
+ * #define SMAA_HLSL_4 1
+ * #define SMAA_PRESET_HIGH 1
+ * include "SMAA.h"
+ *
+ * 7. Then, you'll have to setup the passes as indicated in the scheme above.
+ * You can take a look into SMAA.fx, to see how we did it for our demo.
+ * Checkout the function wrappers, you may want to copy-paste them!
+ *
+ * 8. It's recommended to validate the produced |edgesTex| and |blendTex|.
+ * It's advised to not continue with the implementation until both buffers
+ * are verified to produce identical results to our reference demo.
+ *
+ * 9. After you get the last pass to work, it's time to optimize. You'll have
+ * to initialize a stencil buffer in the first pass (discard is already in
+ * the code), then mask execution by using it the second pass. The last
+ * pass should be executed in all pixels.
+ *
+ *
+ * After this point you can choose to enable predicated thresholding,
+ * temporal supersampling and motion blur integration:
+ *
+ * a) If you want to use predicated thresholding, take a look into
+ * SMAA_PREDICATION; you'll need to pass an extra texture in the edge
+ * detection pass.
+ *
+ * b) If you want to enable temporal supersampling (SMAA T2x):
+ *
+ * 1. The first step is to render using subpixel jitters. I won't go into
+ * detail, but it's as simple as moving each vertex position in the
+ * vertex shader, you can check how we do it in our DX10 demo.
+ *
+ * 2. Then, you must setup the temporal resolve. You may want to take a look
+ * into SMAAResolve for resolving 2x modes. After you get it working, you'll
+ * probably see ghosting everywhere. But fear not, you can enable the
+ * CryENGINE temporal reprojection by setting the SMAA_REPROJECTION macro.
+ *
+ * 3. The next step is to apply SMAA to each subpixel jittered frame, just as
+ * done for 1x.
+ *
+ * 4. At this point you should already have something usable, but for best
+ * results the proper area textures must be set depending on current jitter.
+ * For this, the parameter 'subsampleIndices' of
+ * 'SMAABlendingWeightCalculationPS' must be set as follows, for our T2x
+ * mode:
+ *
+ * @SUBSAMPLE_INDICES
+ *
+ * | S# | Camera Jitter | subsampleIndices |
+ * +----+------------------+--------------------+
+ * | 0 | ( 0.25, -0.25) | int4(1, 1, 1, 0) |
+ * | 1 | (-0.25, 0.25) | int4(2, 2, 2, 0) |
+ *
+ * These jitter positions assume a bottom-to-top y axis. S# stands for the
+ * sample number.
+ *
+ * More information about temporal supersampling here:
+ * http://iryoku.com/aacourse/downloads/13-Anti-Aliasing-Methods-in-CryENGINE-3.pdf
+ *
+ * c) If you want to enable spatial multisampling (SMAA S2x):
+ *
+ * 1. The scene must be rendered using MSAA 2x. The MSAA 2x buffer must be
+ * created with:
+ * - DX10: see below (*)
+ * - DX10.1: D3D10_STANDARD_MULTISAMPLE_PATTERN or
+ * - DX11: D3D11_STANDARD_MULTISAMPLE_PATTERN
+ *
+ * This allows to ensure that the subsample order matches the table in
+ * @SUBSAMPLE_INDICES.
+ *
+ * (*) In the case of DX10, we refer the reader to:
+ * - SMAA::detectMSAAOrder and
+ * - SMAA::msaaReorder
+ *
+ * These functions allow to match the standard multisample patterns by
+ * detecting the subsample order for a specific GPU, and reordering
+ * them appropriately.
+ *
+ * 2. A shader must be run to output each subsample into a separate buffer
+ * (DX10 is required). You can use SMAASeparate for this purpose, or just do
+ * it in an existing pass (for example, in the tone mapping pass).
+ *
+ * 3. The full SMAA 1x pipeline must be run for each separated buffer, storing
+ * the results in the final buffer. The second run should alpha blend with
+ * the existing final buffer using a blending factor of 0.5.
+ * 'subsampleIndices' must be adjusted as in the SMAA T2x case (see point
+ * b).
+ *
+ * d) If you want to enable temporal supersampling on top of SMAA S2x
+ * (which actually is SMAA 4x):
+ *
+ * 1. SMAA 4x consists on temporally jittering SMAA S2x, so the first step is
+ * to calculate SMAA S2x for current frame. In this case, 'subsampleIndices'
+ * must be set as follows:
+ *
+ * | F# | S# | Camera Jitter | Net Jitter | subsampleIndices |
+ * +----+----+--------------------+-------------------+--------------------+
+ * | 0 | 0 | ( 0.125, 0.125) | ( 0.375, -0.125) | int4(5, 3, 1, 3) |
+ * | 0 | 1 | ( 0.125, 0.125) | (-0.125, 0.375) | int4(4, 6, 2, 3) |
+ * +----+----+--------------------+-------------------+--------------------+
+ * | 1 | 2 | (-0.125, -0.125) | ( 0.125, -0.375) | int4(3, 5, 1, 4) |
+ * | 1 | 3 | (-0.125, -0.125) | (-0.375, 0.125) | int4(6, 4, 2, 4) |
+ *
+ * These jitter positions assume a bottom-to-top y axis. F# stands for the
+ * frame number. S# stands for the sample number.
+ *
+ * 2. After calculating SMAA S2x for current frame (with the new subsample
+ * indices), previous frame must be reprojected as in SMAA T2x mode (see
+ * point b).
+ *
+ * e) If motion blur is used, you may want to do the edge detection pass
+ * together with motion blur. This has two advantages:
+ *
+ * 1. Pixels under heavy motion can be omitted from the edge detection process.
+ * For these pixels we can just store "no edge", as motion blur will take
+ * care of them.
+ * 2. The center pixel tap is reused.
+ *
+ * Note that in this case depth testing should be used instead of stenciling,
+ * as we have to write all the pixels in the motion blur pass.
+ *
+ * That's it!
+ */
+
+//-----------------------------------------------------------------------------
+// SMAA Presets
+
+/**
+ * Note that if you use one of these presets, the corresponding macros below
+ * won't be used.
+ */
+
+#if SMAA_PRESET_LOW == 1
+#define SMAA_THRESHOLD 0.15
+#define SMAA_MAX_SEARCH_STEPS 4
+#define SMAA_MAX_SEARCH_STEPS_DIAG 0
+#define SMAA_CORNER_ROUNDING 100
+#elif SMAA_PRESET_MEDIUM == 1
+#define SMAA_THRESHOLD 0.1
+#define SMAA_MAX_SEARCH_STEPS 8
+#define SMAA_MAX_SEARCH_STEPS_DIAG 0
+#define SMAA_CORNER_ROUNDING 100
+#elif SMAA_PRESET_HIGH == 1
+#define SMAA_THRESHOLD 0.1
+#define SMAA_MAX_SEARCH_STEPS 16
+#define SMAA_MAX_SEARCH_STEPS_DIAG 8
+#define SMAA_CORNER_ROUNDING 25
+#elif SMAA_PRESET_ULTRA == 1
+#define SMAA_THRESHOLD 0.05
+#define SMAA_MAX_SEARCH_STEPS 32
+#define SMAA_MAX_SEARCH_STEPS_DIAG 16
+#define SMAA_CORNER_ROUNDING 25
+#endif
+
+//-----------------------------------------------------------------------------
+// Configurable Defines
+
+/**
+ * SMAA_THRESHOLD specifies the threshold or sensitivity to edges.
+ * Lowering this value you will be able to detect more edges at the expense of
+ * performance.
+ *
+ * Range: [0, 0.5]
+ * 0.1 is a reasonable value, and allows to catch most visible edges.
+ * 0.05 is a rather overkill value, that allows to catch 'em all.
+ *
+ * If temporal supersampling is used, 0.2 could be a reasonable value, as low
+ * contrast edges are properly filtered by just 2x.
+ */
+#ifndef SMAA_THRESHOLD
+#define SMAA_THRESHOLD 0.1
+#endif
+
+/**
+ * SMAA_DEPTH_THRESHOLD specifies the threshold for depth edge detection.
+ *
+ * Range: depends on the depth range of the scene.
+ */
+#ifndef SMAA_DEPTH_THRESHOLD
+#define SMAA_DEPTH_THRESHOLD (0.1 * SMAA_THRESHOLD)
+#endif
+
+/**
+ * SMAA_MAX_SEARCH_STEPS specifies the maximum steps performed in the
+ * horizontal/vertical pattern searches, at each side of the pixel.
+ *
+ * In number of pixels, it's actually the double. So the maximum line length
+ * perfectly handled by, for example 16, is 64 (by perfectly, we meant that
+ * longer lines won't look as good, but still antialiased).
+ *
+ * Range: [0, 98]
+ */
+#ifndef SMAA_MAX_SEARCH_STEPS
+#define SMAA_MAX_SEARCH_STEPS 16
+#endif
+
+/**
+ * SMAA_MAX_SEARCH_STEPS_DIAG specifies the maximum steps performed in the
+ * diagonal pattern searches, at each side of the pixel. In this case we jump
+ * one pixel at time, instead of two.
+ *
+ * Range: [0, 20]; set it to 0 to disable diagonal processing.
+ *
+ * On high-end machines it is cheap (between a 0.8x and 0.9x slower for 16
+ * steps), but it can have a significant impact on older machines.
+ */
+#ifndef SMAA_MAX_SEARCH_STEPS_DIAG
+#define SMAA_MAX_SEARCH_STEPS_DIAG 8
+#endif
+
+/**
+ * SMAA_CORNER_ROUNDING specifies how much sharp corners will be rounded.
+ *
+ * Range: [0, 100]; set it to 100 to disable corner detection.
+ */
+#ifndef SMAA_CORNER_ROUNDING
+#define SMAA_CORNER_ROUNDING 25
+#endif
+
+/**
+ * Predicated thresholding allows to better preserve texture details and to
+ * improve performance, by decreasing the number of detected edges using an
+ * additional buffer like the light accumulation buffer, object ids or even the
+ * depth buffer (the depth buffer usage may be limited to indoor or short range
+ * scenes).
+ *
+ * It locally decreases the luma or color threshold if an edge is found in an
+ * additional buffer (so the global threshold can be higher).
+ *
+ * This method was developed by Playstation EDGE MLAA team, and used in
+ * Killzone 3, by using the light accumulation buffer. More information here:
+ * http://iryoku.com/aacourse/downloads/06-MLAA-on-PS3.pptx
+ */
+#ifndef SMAA_PREDICATION
+#define SMAA_PREDICATION 0
+#endif
+
+/**
+ * Threshold to be used in the additional predication buffer.
+ *
+ * Range: depends on the input, so you'll have to find the magic number that
+ * works for you.
+ */
+#ifndef SMAA_PREDICATION_THRESHOLD
+#define SMAA_PREDICATION_THRESHOLD 0.01
+#endif
+
+/**
+ * How much to scale the global threshold used for luma or color edge
+ * detection when using predication.
+ *
+ * Range: [1, 5]
+ */
+#ifndef SMAA_PREDICATION_SCALE
+#define SMAA_PREDICATION_SCALE 2.0
+#endif
+
+/**
+ * How much to locally decrease the threshold.
+ *
+ * Range: [0, 1]
+ */
+#ifndef SMAA_PREDICATION_STRENGTH
+#define SMAA_PREDICATION_STRENGTH 0.4
+#endif
+
+/**
+ * Temporal reprojection allows to remove ghosting artifacts when using
+ * temporal supersampling. We use the CryEngine 3 method which also introduces
+ * velocity weighting. This feature is of extreme importance for totally
+ * removing ghosting. More information here:
+ * http://iryoku.com/aacourse/downloads/13-Anti-Aliasing-Methods-in-CryENGINE-3.pdf
+ *
+ * Note that you'll need to setup a velocity buffer for enabling reprojection.
+ * For static geometry, saving the previous depth buffer is a viable
+ * alternative.
+ */
+#ifndef SMAA_REPROJECTION
+#define SMAA_REPROJECTION 0
+#endif
+
+/**
+ * SMAA_REPROJECTION_WEIGHT_SCALE controls the velocity weighting. It allows to
+ * remove ghosting trails behind the moving object, which are not removed by
+ * just using reprojection. Using low values will exhibit ghosting, while using
+ * high values will disable temporal supersampling under motion.
+ *
+ * Behind the scenes, velocity weighting removes temporal supersampling when
+ * the velocity of the subsamples differs (meaning they are different objects).
+ *
+ * Range: [0, 80]
+ */
+#define SMAA_REPROJECTION_WEIGHT_SCALE 30.0
+
+/**
+ * In the last pass we leverage bilinear filtering to avoid some lerps.
+ * However, bilinear filtering is done in gamma space in DX9, under DX9
+ * hardware (but not in DX9 code running on DX10 hardware), which gives
+ * inaccurate results.
+ *
+ * So, if you are in DX9, under DX9 hardware, and do you want accurate linear
+ * blending, you must set this flag to 1.
+ *
+ * It's ignored when using SMAA_HLSL_4, and of course, only has sense when
+ * using sRGB read and writes on the last pass.
+ */
+#ifndef SMAA_DIRECTX9_LINEAR_BLEND
+#define SMAA_DIRECTX9_LINEAR_BLEND 0
+#endif
+
+/**
+ * On ATI compilers, discard cannot be used in vertex shaders. Thus, they need
+ * to be compiled separately. These macros allow to easily accomplish it.
+ */
+#ifndef SMAA_ONLY_COMPILE_VS
+#define SMAA_ONLY_COMPILE_VS 0
+#endif
+#ifndef SMAA_ONLY_COMPILE_PS
+#define SMAA_ONLY_COMPILE_PS 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Non-Configurable Defines
+
+#ifndef SMAA_AREATEX_MAX_DISTANCE
+#define SMAA_AREATEX_MAX_DISTANCE 16
+#endif
+#ifndef SMAA_AREATEX_MAX_DISTANCE_DIAG
+#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20
+#endif
+#define SMAA_AREATEX_PIXEL_SIZE (1.0 / float2(160.0, 560.0))
+#define SMAA_AREATEX_SUBTEX_SIZE (1.0 / 7.0)
+
+//-----------------------------------------------------------------------------
+// Porting Functions
+
+#if SMAA_HLSL_3 == 1
+#define SMAATexture2D sampler2D
+#define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0))
+#define SMAASampleLevelZeroPoint(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0))
+#define SMAASample(tex, coord) tex2D(tex, coord)
+#define SMAASamplePoint(tex, coord) tex2D(tex, coord)
+#define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlod(tex, float4(coord + offset * SMAA_PIXEL_SIZE, 0.0, 0.0))
+#define SMAASampleOffset(tex, coord, offset) tex2D(tex, coord + offset * SMAA_PIXEL_SIZE)
+#define SMAALerp(a, b, t) lerp(a, b, t)
+#define SMAASaturate(a) saturate(a)
+#define SMAAMad(a, b, c) mad(a, b, c)
+#define SMAA_FLATTEN [flatten]
+#define SMAA_BRANCH [branch]
+#endif
+#if SMAA_HLSL_4 == 1 || SMAA_HLSL_4_1 == 1
+SamplerState LinearSampler { Filter = MIN_MAG_LINEAR_MIP_POINT; AddressU = Clamp; AddressV = Clamp; };
+SamplerState PointSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Clamp; AddressV = Clamp; };
+#define SMAATexture2D Texture2D
+#define SMAASampleLevelZero(tex, coord) tex.SampleLevel(LinearSampler, coord, 0)
+#define SMAASampleLevelZeroPoint(tex, coord) tex.SampleLevel(PointSampler, coord, 0)
+#define SMAASample(tex, coord) SMAASampleLevelZero(tex, coord)
+#define SMAASamplePoint(tex, coord) SMAASampleLevelZeroPoint(tex, coord)
+#define SMAASampleLevelZeroOffset(tex, coord, offset) tex.SampleLevel(LinearSampler, coord, 0, offset)
+#define SMAASampleOffset(tex, coord, offset) SMAASampleLevelZeroOffset(tex, coord, offset)
+#define SMAALerp(a, b, t) lerp(a, b, t)
+#define SMAASaturate(a) saturate(a)
+#define SMAAMad(a, b, c) mad(a, b, c)
+#define SMAA_FLATTEN [flatten]
+#define SMAA_BRANCH [branch]
+#define SMAATexture2DMS2 Texture2DMS<float4, 2>
+#define SMAALoad(tex, pos, sample) tex.Load(pos, sample)
+#endif
+#if SMAA_HLSL_4_1 == 1
+#define SMAAGather(tex, coord) tex.Gather(LinearSampler, coord, 0)
+#endif
+#if SMAA_GLSL_3 == 1 || SMAA_GLSL_4 == 1
+#define SMAATexture2D sampler2D
+#define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0)
+#define SMAASampleLevelZeroPoint(tex, coord) textureLod(tex, coord, 0.0)
+#define SMAASample(tex, coord) texture(tex, coord)
+#define SMAASamplePoint(tex, coord) texture(tex, coord)
+#define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodOffset(tex, coord, 0.0, offset)
+#define SMAASampleOffset(tex, coord, offset) texture(tex, coord, offset)
+#define SMAALerp(a, b, t) mix(a, b, t)
+#define SMAASaturate(a) clamp(a, 0.0, 1.0)
+#define SMAA_FLATTEN
+#define SMAA_BRANCH
+#define float2 vec2
+#define float3 vec3
+#define float4 vec4
+#define int2 ivec2
+#define int3 ivec3
+#define int4 ivec4
+#endif
+#if SMAA_GLSL_3 == 1
+#define SMAAMad(a, b, c) (a * b + c)
+#endif
+#if SMAA_GLSL_4 == 1
+#define SMAAMad(a, b, c) fma(a, b, c)
+#define SMAAGather(tex, coord) textureGather(tex, coord)
+#endif
+
+//-----------------------------------------------------------------------------
+// Misc functions
+
+/**
+ * Gathers current pixel, and the top-left neighbors.
+ */
+float3 SMAAGatherNeighbours(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D tex) {
+ #if SMAA_HLSL_4_1 == 1 || SMAA_GLSL_4 == 1
+ return SMAAGather(tex, texcoord + SMAA_PIXEL_SIZE * float2(-0.5, -0.5)).grb;
+ #else
+ float P = SMAASample(tex, texcoord).r;
+ float Pleft = SMAASample(tex, offset[0].xy).r;
+ float Ptop = SMAASample(tex, offset[0].zw).r;
+ return float3(P, Pleft, Ptop);
+ #endif
+}
+
+/**
+ * Adjusts the threshold by means of predication.
+ */
+float2 SMAACalculatePredicatedThreshold(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex,
+ SMAATexture2D predicationTex) {
+ float3 neighbours = SMAAGatherNeighbours(texcoord, offset, predicationTex);
+ float2 delta = abs(neighbours.xx - neighbours.yz);
+ float2 edges = step(SMAA_PREDICATION_THRESHOLD, delta);
+ return SMAA_PREDICATION_SCALE * SMAA_THRESHOLD * (1.0 - SMAA_PREDICATION_STRENGTH * edges);
+}
+
+#if SMAA_ONLY_COMPILE_PS == 0
+//-----------------------------------------------------------------------------
+// Vertex Shaders
+
+/**
+ * Edge Detection Vertex Shader
+ */
+void SMAAEdgeDetectionVS(float4 position,
+ out float4 svPosition,
+ in float2 texcoord,
+ out float4 offset[3]) {
+ svPosition = position;
+
+ offset[0] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-1.0, 0.0, 0.0, -1.0);
+ offset[1] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4( 1.0, 0.0, 0.0, 1.0);
+ offset[2] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-2.0, 0.0, 0.0, -2.0);
+}
+
+/**
+ * Blend Weight Calculation Vertex Shader
+ */
+void SMAABlendingWeightCalculationVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord,
+ out float2 pixcoord,
+ out float4 offset[3]) {
+ svPosition = position;
+
+ pixcoord = texcoord / SMAA_PIXEL_SIZE;
+
+ // We will use these offsets for the searches later on (see @PSEUDO_GATHER4):
+ offset[0] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-0.25, -0.125, 1.25, -0.125);
+ offset[1] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-0.125, -0.25, -0.125, 1.25);
+
+ // And these for the searches, they indicate the ends of the loops:
+ offset[2] = float4(offset[0].xz, offset[1].yw) +
+ float4(-2.0, 2.0, -2.0, 2.0) *
+ SMAA_PIXEL_SIZE.xxyy * float(SMAA_MAX_SEARCH_STEPS);
+}
+
+/**
+ * Neighborhood Blending Vertex Shader
+ */
+void SMAANeighborhoodBlendingVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord,
+ out float4 offset[2]) {
+ svPosition = position;
+
+ offset[0] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-1.0, 0.0, 0.0, -1.0);
+ offset[1] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4( 1.0, 0.0, 0.0, 1.0);
+}
+
+/**
+ * Resolve Vertex Shader
+ */
+void SMAAResolveVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord) {
+ svPosition = position;
+}
+
+/**
+ * Separate Vertex Shader
+ */
+void SMAASeparateVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord) {
+ svPosition = position;
+}
+#endif // SMAA_ONLY_COMPILE_PS == 0
+
+#if SMAA_ONLY_COMPILE_VS == 0
+//-----------------------------------------------------------------------------
+// Edge Detection Pixel Shaders (First Pass)
+
+/**
+ * Luma Edge Detection
+ *
+ * IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and
+ * thus 'colorTex' should be a non-sRGB texture.
+ */
+float4 SMAALumaEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex
+ #if SMAA_PREDICATION == 1
+ , SMAATexture2D predicationTex
+ #endif
+ ) {
+ // Calculate the threshold:
+ #if SMAA_PREDICATION == 1
+ float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, colorTex, predicationTex);
+ #else
+ float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+ #endif
+
+ // Calculate lumas:
+ float3 weights = float3(0.2126, 0.7152, 0.0722);
+ float L = dot(SMAASample(colorTex, texcoord).rgb, weights);
+ float Lleft = dot(SMAASample(colorTex, offset[0].xy).rgb, weights);
+ float Ltop = dot(SMAASample(colorTex, offset[0].zw).rgb, weights);
+
+ // We do the usual threshold:
+ float4 delta;
+ delta.xy = abs(L - float2(Lleft, Ltop));
+ float2 edges = step(threshold, delta.xy);
+
+ // Then discard if there is no edge:
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas:
+ float Lright = dot(SMAASample(colorTex, offset[1].xy).rgb, weights);
+ float Lbottom = dot(SMAASample(colorTex, offset[1].zw).rgb, weights);
+ delta.zw = abs(L - float2(Lright, Lbottom));
+
+ // Calculate the maximum delta in the direct neighborhood:
+ float2 maxDelta = max(delta.xy, delta.zw);
+ maxDelta = max(maxDelta.xx, maxDelta.yy);
+
+ // Calculate left-left and top-top deltas:
+ float Lleftleft = dot(SMAASample(colorTex, offset[2].xy).rgb, weights);
+ float Ltoptop = dot(SMAASample(colorTex, offset[2].zw).rgb, weights);
+ delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
+
+ // Calculate the final maximum delta:
+ maxDelta = max(maxDelta.xy, delta.zw);
+
+ /**
+ * Each edge with a delta in luma of less than 50% of the maximum luma
+ * surrounding this pixel is discarded. This allows to eliminate spurious
+ * crossing edges, and is based on the fact that, if there is too much
+ * contrast in a direction, that will hide contrast in the other
+ * neighbors.
+ * This is done after the discard intentionally as this situation doesn't
+ * happen too frequently (but it's important to do as it prevents some
+ * edges from going undetected).
+ */
+ edges.xy *= step(0.5 * maxDelta, delta.xy);
+
+ return float4(edges, 0.0, 0.0);
+}
+
+/**
+ * Color Edge Detection
+ *
+ * IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and
+ * thus 'colorTex' should be a non-sRGB texture.
+ */
+float4 SMAAColorEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex
+ #if SMAA_PREDICATION == 1
+ , SMAATexture2D predicationTex
+ #endif
+ ) {
+ // Calculate the threshold:
+ #if SMAA_PREDICATION == 1
+ float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, colorTex, predicationTex);
+ #else
+ float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+ #endif
+
+ // Calculate color deltas:
+ float4 delta;
+ float3 C = SMAASample(colorTex, texcoord).rgb;
+
+ float3 Cleft = SMAASample(colorTex, offset[0].xy).rgb;
+ float3 t = abs(C - Cleft);
+ delta.x = max(max(t.r, t.g), t.b);
+
+ float3 Ctop = SMAASample(colorTex, offset[0].zw).rgb;
+ t = abs(C - Ctop);
+ delta.y = max(max(t.r, t.g), t.b);
+
+ // We do the usual threshold:
+ float2 edges = step(threshold, delta.xy);
+
+ // Then discard if there is no edge:
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas:
+ float3 Cright = SMAASample(colorTex, offset[1].xy).rgb;
+ t = abs(C - Cright);
+ delta.z = max(max(t.r, t.g), t.b);
+
+ float3 Cbottom = SMAASample(colorTex, offset[1].zw).rgb;
+ t = abs(C - Cbottom);
+ delta.w = max(max(t.r, t.g), t.b);
+
+ // Calculate the maximum delta in the direct neighborhood:
+ float maxDelta = max(max(max(delta.x, delta.y), delta.z), delta.w);
+
+ // Calculate left-left and top-top deltas:
+ float3 Cleftleft = SMAASample(colorTex, offset[2].xy).rgb;
+ t = abs(C - Cleftleft);
+ delta.z = max(max(t.r, t.g), t.b);
+
+ float3 Ctoptop = SMAASample(colorTex, offset[2].zw).rgb;
+ t = abs(C - Ctoptop);
+ delta.w = max(max(t.r, t.g), t.b);
+
+ // Calculate the final maximum delta:
+ maxDelta = max(max(maxDelta, delta.z), delta.w);
+
+ // Local contrast adaptation in action:
+ edges.xy *= step(0.5 * maxDelta, delta.xy);
+
+ return float4(edges, 0.0, 0.0);
+}
+
+float4 SMAASingleChannelEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex
+ #if SMAA_PREDICATION == 1
+ , SMAATexture2D predicationTex
+ #endif
+ ) {
+ // Calculate the threshold:
+ #if SMAA_PREDICATION == 1
+ float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, colorTex, predicationTex);
+ #else
+ float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+ #endif
+
+ // Calculate lumas:
+ float L = SMAASample(colorTex, texcoord).r;
+ float Lleft = SMAASample(colorTex, offset[0].xy).r;
+ float Ltop = SMAASample(colorTex, offset[0].zw).r;
+
+ // We do the usual threshold:
+ float4 delta;
+ delta.xy = abs(L - float2(Lleft, Ltop));
+ float2 edges = step(threshold, delta.xy);
+
+ // Then discard if there is no edge:
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas:
+ float Lright = SMAASample(colorTex, offset[1].xy).r;
+ float Lbottom = SMAASample(colorTex, offset[1].zw).r;
+ delta.zw = abs(L - float2(Lright, Lbottom));
+
+ // Calculate the maximum delta in the direct neighborhood:
+ float2 maxDelta = max(delta.xy, delta.zw);
+ maxDelta = max(maxDelta.xx, maxDelta.yy);
+
+ // Calculate left-left and top-top deltas:
+ float Lleftleft = SMAASample(colorTex, offset[2].xy).r;
+ float Ltoptop = SMAASample(colorTex, offset[2].zw).r;
+ delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
+
+ // Calculate the final maximum delta:
+ maxDelta = max(maxDelta.xy, delta.zw);
+
+ /**
+ * Each edge with a delta in luma of less than 50% of the maximum luma
+ * surrounding this pixel is discarded. This allows to eliminate spurious
+ * crossing edges, and is based on the fact that, if there is too much
+ * contrast in a direction, that will hide contrast in the other
+ * neighbors.
+ * This is done after the discard intentionally as this situation doesn't
+ * happen too frequently (but it's important to do as it prevents some
+ * edges from going undetected).
+ */
+ edges.xy *= step(0.5 * maxDelta, delta.xy);
+
+ return float4(edges, 0.0, 0.0);
+}
+
+/**
+ * Depth Edge Detection
+ */
+float4 SMAADepthEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D depthTex) {
+ float3 neighbours = SMAAGatherNeighbours(texcoord, offset, depthTex);
+ float2 delta = abs(neighbours.xx - float2(neighbours.y, neighbours.z));
+ float2 edges = step(SMAA_DEPTH_THRESHOLD, delta);
+
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ return float4(edges, 0.0, 0.0);
+}
+
+//-----------------------------------------------------------------------------
+// Diagonal Search Functions
+
+#if SMAA_MAX_SEARCH_STEPS_DIAG > 0 || SMAA_FORCE_DIAGONAL_DETECTION == 1
+
+/**
+ * These functions allows to perform diagonal pattern searches.
+ */
+float SMAASearchDiag1(SMAATexture2D edgesTex, float2 texcoord, float2 dir, float c) {
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ float2 e = float2(0.0, 0.0);
+ float i;
+ for (i = 0.0; i < float(SMAA_MAX_SEARCH_STEPS_DIAG); i++) {
+ e.rg = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ SMAA_FLATTEN if (dot(e, float2(1.0, 1.0)) < 1.9) break;
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ }
+ return i + float(e.g > 0.9) * c;
+}
+
+float SMAASearchDiag2(SMAATexture2D edgesTex, float2 texcoord, float2 dir, float c) {
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ float2 e = float2(0.0, 0.0);
+ float i;
+ for (i = 0.0; i < float(SMAA_MAX_SEARCH_STEPS_DIAG); i++) {
+ e.g = SMAASampleLevelZero(edgesTex, texcoord).g;
+ e.r = SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r;
+ SMAA_FLATTEN if (dot(e, float2(1.0, 1.0)) < 1.9) break;
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ }
+ return i + float(e.g > 0.9) * c;
+}
+
+/**
+ * Similar to SMAAArea, this calculates the area corresponding to a certain
+ * diagonal distance and crossing edges 'e'.
+ */
+float2 SMAAAreaDiag(SMAATexture2D areaTex, float2 dist, float2 e, float offset) {
+ float2 texcoord = float(SMAA_AREATEX_MAX_DISTANCE_DIAG) * e + dist;
+
+ // We do a scale and bias for mapping to texel space:
+ texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + (0.5 * SMAA_AREATEX_PIXEL_SIZE);
+
+ // Diagonal areas are on the second half of the texture:
+ texcoord.x += 0.5;
+
+ // Move to proper place, according to the subpixel offset:
+ texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
+
+ // Do it!
+ return SMAASampleLevelZero(areaTex, texcoord).ra;
+}
+
+/**
+ * This searches for diagonal patterns and returns the corresponding weights.
+ */
+float2 SMAACalculateDiagWeights(SMAATexture2D edgesTex, SMAATexture2D areaTex, float2 texcoord, float2 e, int4 subsampleIndices) {
+ float2 weights = float2(0.0, 0.0);
+
+ float2 d;
+ d.x = e.r > 0.0? SMAASearchDiag1(edgesTex, texcoord, float2(-1.0, 1.0), 1.0) : 0.0;
+ d.y = SMAASearchDiag1(edgesTex, texcoord, float2(1.0, -1.0), 0.0);
+
+ SMAA_BRANCH
+ if (d.r + d.g > 2.0) { // d.r + d.g + 1 > 3
+ float4 coords = SMAAMad(float4(-d.r, d.r, d.g, -d.g), SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+
+ float4 c;
+ c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g;
+ c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, 0)).r;
+ c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).g;
+ c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1)).r;
+ float2 e = 2.0 * c.xz + c.yw;
+ float t = float(SMAA_MAX_SEARCH_STEPS_DIAG) - 1.0;
+ e *= step(d.rg, float2(t, t));
+
+ weights += SMAAAreaDiag(areaTex, d, e, float(subsampleIndices.z));
+ }
+
+ d.x = SMAASearchDiag2(edgesTex, texcoord, float2(-1.0, -1.0), 0.0);
+ float right = SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r;
+ d.y = right > 0.0? SMAASearchDiag2(edgesTex, texcoord, float2(1.0, 1.0), 1.0) : 0.0;
+
+ SMAA_BRANCH
+ if (d.r + d.g > 2.0) { // d.r + d.g + 1 > 3
+ float4 coords = SMAAMad(float4(-d.r, -d.r, d.g, d.g), SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+
+ float4 c;
+ c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g;
+ c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, -1)).r;
+ c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).gr;
+ float2 e = 2.0 * c.xz + c.yw;
+ float t = float(SMAA_MAX_SEARCH_STEPS_DIAG) - 1.0;
+ e *= step(d.rg, float2(t, t));
+
+ weights += SMAAAreaDiag(areaTex, d, e, float(subsampleIndices.w)).gr;
+ }
+
+ return weights;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Horizontal/Vertical Search Functions
+
+/**
+ * This allows to determine how much length should we add in the last step
+ * of the searches. It takes the bilinearly interpolated edge (see
+ * @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and
+ * crossing edges are active.
+ */
+float SMAASearchLength(SMAATexture2D searchTex, float2 e, float bias, float scale) {
+ // Not required if searchTex accesses are set to point:
+ // float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0);
+ // e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE +
+ // e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;
+ e.r = bias + e.r * scale;
+ return 255.0 * SMAASampleLevelZeroPoint(searchTex, e).r;
+}
+
+/**
+ * Horizontal/vertical search functions for the 2nd pass.
+ */
+float SMAASearchXLeft(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ /**
+ * @PSEUDO_GATHER4
+ * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to
+ * sample between edge, thus fetching four edges in a row.
+ * Sampling with different offsets in each direction allows to disambiguate
+ * which edges are active from the four fetched ones.
+ */
+ float2 e = float2(0.0, 1.0);
+ while (texcoord.x > end &&
+ e.g > 0.8281 && // Is there some edge not activated?
+ e.r == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord -= float2(2.0, 0.0) * SMAA_PIXEL_SIZE;
+ }
+
+ // We correct the previous (-0.25, -0.125) offset we applied:
+ texcoord.x += 0.25 * SMAA_PIXEL_SIZE.x;
+
+ // The searches are bias by 1, so adjust the coords accordingly:
+ texcoord.x += SMAA_PIXEL_SIZE.x;
+
+ // Disambiguate the length added by the last step:
+ texcoord.x += 2.0 * SMAA_PIXEL_SIZE.x; // Undo last step
+ texcoord.x -= SMAA_PIXEL_SIZE.x * SMAASearchLength(searchTex, e, 0.0, 0.5);
+
+ return texcoord.x;
+}
+
+float SMAASearchXRight(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ float2 e = float2(0.0, 1.0);
+ while (texcoord.x < end &&
+ e.g > 0.8281 && // Is there some edge not activated?
+ e.r == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord += float2(2.0, 0.0) * SMAA_PIXEL_SIZE;
+ }
+
+ texcoord.x -= 0.25 * SMAA_PIXEL_SIZE.x;
+ texcoord.x -= SMAA_PIXEL_SIZE.x;
+ texcoord.x -= 2.0 * SMAA_PIXEL_SIZE.x;
+ texcoord.x += SMAA_PIXEL_SIZE.x * SMAASearchLength(searchTex, e, 0.5, 0.5);
+ return texcoord.x;
+}
+
+float SMAASearchYUp(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ float2 e = float2(1.0, 0.0);
+ while (texcoord.y > end &&
+ e.r > 0.8281 && // Is there some edge not activated?
+ e.g == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord -= float2(0.0, 2.0) * SMAA_PIXEL_SIZE;
+ }
+
+ texcoord.y += 0.25 * SMAA_PIXEL_SIZE.y;
+ texcoord.y += SMAA_PIXEL_SIZE.y;
+ texcoord.y += 2.0 * SMAA_PIXEL_SIZE.y;
+ texcoord.y -= SMAA_PIXEL_SIZE.y * SMAASearchLength(searchTex, e.gr, 0.0, 0.5);
+ return texcoord.y;
+}
+
+float SMAASearchYDown(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ float2 e = float2(1.0, 0.0);
+ while (texcoord.y < end &&
+ e.r > 0.8281 && // Is there some edge not activated?
+ e.g == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord += float2(0.0, 2.0) * SMAA_PIXEL_SIZE;
+ }
+
+ texcoord.y -= 0.25 * SMAA_PIXEL_SIZE.y;
+ texcoord.y -= SMAA_PIXEL_SIZE.y;
+ texcoord.y -= 2.0 * SMAA_PIXEL_SIZE.y;
+ texcoord.y += SMAA_PIXEL_SIZE.y * SMAASearchLength(searchTex, e.gr, 0.5, 0.5);
+ return texcoord.y;
+}
+
+/**
+ * Ok, we have the distance and both crossing edges. So, what are the areas
+ * at each side of current edge?
+ */
+float2 SMAAArea(SMAATexture2D areaTex, float2 dist, float e1, float e2, float offset) {
+ // Rounding prevents precision errors of bilinear filtering:
+ float2 texcoord = float(SMAA_AREATEX_MAX_DISTANCE) * round(4.0 * float2(e1, e2)) + dist;
+
+ // We do a scale and bias for mapping to texel space:
+ texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + (0.5 * SMAA_AREATEX_PIXEL_SIZE);
+
+ // Move to proper place, according to the subpixel offset:
+ texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
+
+ // Do it!
+ return SMAASampleLevelZero(areaTex, texcoord).ra;
+}
+
+//-----------------------------------------------------------------------------
+// Corner Detection Functions
+
+void SMAADetectHorizontalCornerPattern(SMAATexture2D edgesTex, inout float2 weights, float2 texcoord, float2 d) {
+ #if SMAA_CORNER_ROUNDING < 100 || SMAA_FORCE_CORNER_DETECTION == 1
+ float4 coords = SMAAMad(float4(d.x, 0.0, d.y, 0.0),
+ SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+ float2 e;
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(0.0, 1.0)).r;
+ bool left = abs(d.x) < abs(d.y);
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(0.0, -2.0)).r;
+ if (left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2(1.0, 1.0)).r;
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2(1.0, -2.0)).r;
+ if (!left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+ #endif
+}
+
+void SMAADetectVerticalCornerPattern(SMAATexture2D edgesTex, inout float2 weights, float2 texcoord, float2 d) {
+ #if SMAA_CORNER_ROUNDING < 100 || SMAA_FORCE_CORNER_DETECTION == 1
+ float4 coords = SMAAMad(float4(0.0, d.x, 0.0, d.y),
+ SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+ float2 e;
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 1.0, 0.0)).g;
+ bool left = abs(d.x) < abs(d.y);
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-2.0, 0.0)).g;
+ if (left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1.0, 1.0)).g;
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2(-2.0, 1.0)).g;
+ if (!left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+// Blending Weight Calculation Pixel Shader (Second Pass)
+
+float4 SMAABlendingWeightCalculationPS(float2 texcoord,
+ float2 pixcoord,
+ float4 offset[3],
+ SMAATexture2D edgesTex,
+ SMAATexture2D areaTex,
+ SMAATexture2D searchTex,
+ int4 subsampleIndices) { // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES.
+ float4 weights = float4(0.0, 0.0, 0.0, 0.0);
+
+ float2 e = SMAASample(edgesTex, texcoord).rg;
+
+ SMAA_BRANCH
+ if (e.g > 0.0) { // Edge at north
+ #if SMAA_MAX_SEARCH_STEPS_DIAG > 0 || SMAA_FORCE_DIAGONAL_DETECTION == 1
+ // Diagonals have both north and west edges, so searching for them in
+ // one of the boundaries is enough.
+ weights.rg = SMAACalculateDiagWeights(edgesTex, areaTex, texcoord, e, subsampleIndices);
+
+ // We give priority to diagonals, so if we find a diagonal we skip
+ // horizontal/vertical processing.
+ SMAA_BRANCH
+ if (dot(weights.rg, float2(1.0, 1.0)) == 0.0) {
+ #endif
+
+ float2 d;
+
+ // Find the distance to the left:
+ float2 coords;
+ coords.x = SMAASearchXLeft(edgesTex, searchTex, offset[0].xy, offset[2].x);
+ coords.y = offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_PIXEL_SIZE.y (@CROSSING_OFFSET)
+ d.x = coords.x;
+
+ // Now fetch the left crossing edges, two at a time using bilinear
+ // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
+ // discern what value each edge has:
+ float e1 = SMAASampleLevelZero(edgesTex, coords).r;
+
+ // Find the distance to the right:
+ coords.x = SMAASearchXRight(edgesTex, searchTex, offset[0].zw, offset[2].y);
+ d.y = coords.x;
+
+ // We want the distances to be in pixel units (doing this here allow to
+ // better interleave arithmetic and memory accesses):
+ d = d / SMAA_PIXEL_SIZE.x - pixcoord.x;
+
+ // SMAAArea below needs a sqrt, as the areas texture is compressed
+ // quadratically:
+ float2 sqrt_d = sqrt(abs(d));
+
+ // Fetch the right crossing edges:
+ float e2 = SMAASampleLevelZeroOffset(edgesTex, coords, int2(1, 0)).r;
+
+ // Ok, we know how this pattern looks like, now it is time for getting
+ // the actual area:
+ weights.rg = SMAAArea(areaTex, sqrt_d, e1, e2, float(subsampleIndices.y));
+
+ // Fix corners:
+ SMAADetectHorizontalCornerPattern(edgesTex, weights.rg, texcoord, d);
+
+ #if SMAA_MAX_SEARCH_STEPS_DIAG > 0 || SMAA_FORCE_DIAGONAL_DETECTION == 1
+ } else
+ e.r = 0.0; // Skip vertical processing.
+ #endif
+ }
+
+ SMAA_BRANCH
+ if (e.r > 0.0) { // Edge at west
+ float2 d;
+
+ // Find the distance to the top:
+ float2 coords;
+ coords.y = SMAASearchYUp(edgesTex, searchTex, offset[1].xy, offset[2].z);
+ coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_PIXEL_SIZE.x;
+ d.x = coords.y;
+
+ // Fetch the top crossing edges:
+ float e1 = SMAASampleLevelZero(edgesTex, coords).g;
+
+ // Find the distance to the bottom:
+ coords.y = SMAASearchYDown(edgesTex, searchTex, offset[1].zw, offset[2].w);
+ d.y = coords.y;
+
+ // We want the distances to be in pixel units:
+ d = d / SMAA_PIXEL_SIZE.y - pixcoord.y;
+
+ // SMAAArea below needs a sqrt, as the areas texture is compressed
+ // quadratically:
+ float2 sqrt_d = sqrt(abs(d));
+
+ // Fetch the bottom crossing edges:
+ float e2 = SMAASampleLevelZeroOffset(edgesTex, coords, int2(0, 1)).g;
+
+ // Get the area for this direction:
+ weights.ba = SMAAArea(areaTex, sqrt_d, e1, e2, float(subsampleIndices.x));
+
+ // Fix corners:
+ SMAADetectVerticalCornerPattern(edgesTex, weights.ba, texcoord, d);
+ }
+
+ return weights;
+}
+
+//-----------------------------------------------------------------------------
+// Neighborhood Blending Pixel Shader (Third Pass)
+
+float4 SMAANeighborhoodBlendingPS(float2 texcoord,
+ float4 offset[2],
+ SMAATexture2D colorTex,
+ SMAATexture2D blendTex) {
+ // Fetch the blending weights for current pixel:
+ float4 a;
+ a.xz = SMAASample(blendTex, texcoord).xz;
+ a.y = SMAASample(blendTex, offset[1].zw).g;
+ a.w = SMAASample(blendTex, offset[1].xy).a;
+
+ // Is there any blending weight with a value greater than 0.0?
+ SMAA_BRANCH
+ if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5)
+ return SMAASampleLevelZero(colorTex, texcoord);
+ else {
+ float4 color = float4(0.0, 0.0, 0.0, 0.0);
+
+ // Up to 4 lines can be crossing a pixel (one through each edge). We
+ // favor blending by choosing the line with the maximum weight for each
+ // direction:
+ float2 offset;
+ offset.x = a.a > a.b? a.a : -a.b; // left vs. right
+ offset.y = a.g > a.r? a.g : -a.r; // top vs. bottom
+
+ // Then we go in the direction that has the maximum weight:
+ if (abs(offset.x) > abs(offset.y)) // horizontal vs. vertical
+ offset.y = 0.0;
+ else
+ offset.x = 0.0;
+
+ #if SMAA_REPROJECTION == 1
+ // Fetch the opposite color and lerp by hand:
+ float4 C = SMAASampleLevelZero(colorTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ float4 Cop = SMAASampleLevelZero(colorTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+
+ // Unpack the velocity values:
+ C.a *= C.a;
+ Cop.a *= Cop.a;
+
+ // Lerp the colors:
+ float4 Caa = SMAALerp(C, Cop, s);
+
+ // Unpack velocity and return the resulting value:
+ Caa.a = sqrt(Caa.a);
+ return Caa;
+ #elif SMAA_HLSL_4 == 1 || SMAA_DIRECTX9_LINEAR_BLEND == 0
+ // We exploit bilinear filtering to mix current pixel with the chosen
+ // neighbor:
+ texcoord += offset * SMAA_PIXEL_SIZE;
+ return SMAASampleLevelZero(colorTex, texcoord);
+ #else
+ // Fetch the opposite color and lerp by hand:
+ float4 C = SMAASampleLevelZero(colorTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ float4 Cop = SMAASampleLevelZero(colorTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+ return SMAALerp(C, Cop, s);
+ #endif
+ }
+}
+
+float4 SMAASampleLevelZeroResolve( SMAATexture2D currentTex,
+ SMAATexture2D previousTex,
+ float2 texcoord )
+{
+ return SMAALerp( SMAASampleLevelZero( currentTex, texcoord ), SMAASampleLevelZero( previousTex, texcoord ), .5 );
+}
+
+float4 SMAANeighborhoodBlendingTemporalPS(float2 texcoord,
+ float4 offset[2],
+ SMAATexture2D colorTex,
+ SMAATexture2D previousTex,
+ SMAATexture2D blendTex) {
+ // Fetch the blending weights for current pixel:
+ float4 a;
+ a.xz = SMAASample(blendTex, texcoord).xz;
+ a.y = SMAASample(blendTex, offset[1].zw).g;
+ a.w = SMAASample(blendTex, offset[1].xy).a;
+
+ // Is there any blending weight with a value greater than 0.0?
+ SMAA_BRANCH
+ if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5)
+ return SMAASampleLevelZero(colorTex, texcoord);
+ else {
+ float4 color = float4(0.0, 0.0, 0.0, 0.0);
+
+ // Up to 4 lines can be crossing a pixel (one through each edge). We
+ // favor blending by choosing the line with the maximum weight for each
+ // direction:
+ float2 offset;
+ offset.x = a.a > a.b? a.a : -a.b; // left vs. right
+ offset.y = a.g > a.r? a.g : -a.r; // top vs. bottom
+
+ // Then we go in the direction that has the maximum weight:
+ if (abs(offset.x) > abs(offset.y)) // horizontal vs. vertical
+ offset.y = 0.0;
+ else
+ offset.x = 0.0;
+
+ #if SMAA_REPROJECTION == 1
+ // Fetch the opposite color and lerp by hand:
+ return SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ return SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+
+ // Unpack the velocity values:
+ C.a *= C.a;
+ Cop.a *= Cop.a;
+
+ // Lerp the colors:
+ float4 Caa = SMAALerp(C, Cop, s);
+
+ // Unpack velocity and return the resulting value:
+ Caa.a = sqrt(Caa.a);
+ return Caa;
+ #elif SMAA_HLSL_4 == 1 || SMAA_DIRECTX9_LINEAR_BLEND == 0
+ // We exploit bilinear filtering to mix current pixel with the chosen
+ // neighbor:
+ texcoord += offset * SMAA_PIXEL_SIZE;
+ return SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ #else
+ // Fetch the opposite color and lerp by hand:
+ float4 C = SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ float4 Cop = SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+ return SMAALerp(C, Cop, s);
+ #endif
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Temporal Resolve Pixel Shader (Optional Pass)
+
+float4 SMAAResolvePS(float2 texcoord,
+ SMAATexture2D colorTexCurr,
+ SMAATexture2D colorTexPrev
+ #if SMAA_REPROJECTION == 1
+ , SMAATexture2D velocityTex
+ #endif
+ ) {
+ #if SMAA_REPROJECTION == 1
+ // Velocity is calculated from previous to current position, so we need to
+ // inverse it:
+ float2 velocity = -SMAASample(velocityTex, texcoord).rg;
+
+ // Fetch current pixel:
+ float4 current = SMAASample(colorTexCurr, texcoord);
+
+ // Reproject current coordinates and fetch previous pixel:
+ float4 previous = SMAASample(colorTexPrev, texcoord + velocity);
+
+ // Attenuate the previous pixel if the velocity is different:
+ float delta = abs(current.a * current.a - previous.a * previous.a) / 5.0;
+ float weight = 0.5 * SMAASaturate(1.0 - (sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE));
+
+ // Blend the pixels according to the calculated weight:
+ return SMAALerp(current, previous, weight);
+ #else
+ // Just blend the pixels:
+ float4 current = SMAASample(colorTexCurr, texcoord);
+ float4 previous = SMAASample(colorTexPrev, texcoord);
+ return SMAALerp(current, previous, 0.5);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+// Separate Multisamples Pixel Shader (Optional Pass)
+
+#if SMAA_HLSL_4 == 1 || SMAA_HLSL_4_1 == 1
+void SMAASeparatePS(float4 position : SV_POSITION,
+ float2 texcoord : TEXCOORD0,
+ out float4 target0,
+ out float4 target1,
+ uniform SMAATexture2DMS2 colorTexMS) {
+ int2 pos = int2(position.xy);
+ target0 = SMAALoad(colorTexMS, pos, 0);
+ target1 = SMAALoad(colorTexMS, pos, 1);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+#endif // SMAA_ONLY_COMPILE_VS == 0
diff --git a/src/Runtime/res/effectlib/SSAOCustomMaterial.glsllib b/src/Runtime/res/effectlib/SSAOCustomMaterial.glsllib
new file mode 100644
index 00000000..58dfff56
--- /dev/null
+++ b/src/Runtime/res/effectlib/SSAOCustomMaterial.glsllib
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB
+#define SSAO_CUSTOM_MATERIAL_GLSLLIB
+#if UIC_ENABLE_SSAO || UIC_ENABLE_SSDO
+
+#include "viewProperties.glsllib"
+#if UIC_ENABLE_SSDO
+#include "screenSpaceDO.glsllib"
+
+layout (std140) uniform cbAoShadow {
+ vec4 ao_properties;
+ vec4 ao_properties2;
+ vec4 shadow_properties;
+ vec4 aoScreenConst;
+ vec4 UvToEyeConst;
+ };
+
+uniform sampler2D depth_sampler;
+#endif
+uniform sampler2D ao_sampler;
+
+#endif // UIC_ENABLE_SSAO || UIC_ENABLE_SSDO
+
+#if UIC_ENABLE_SSAO
+
+float customMaterialAO()
+{
+#if UIC_ENABLE_SSDO
+ vec2 smpUV = (gl_FragCoord.xy) * aoScreenConst.zw;
+#else
+ ivec2 iSize = textureSize(ao_sampler, 0);
+ vec2 smpUV = (gl_FragCoord.xy) / vec2(iSize);
+#endif
+ return texture(ao_sampler, smpUV).x;
+}
+
+#else
+
+float customMaterialAO()
+{
+ return 1.0;
+}
+
+#endif
+
+#if UIC_ENABLE_SSDO
+
+float customMaterialShadow( vec3 lightDir, vec3 varWorldPos )
+{
+ return shadowOcclusion( depth_sampler, lightDir, varWorldPos, view_matrix, view_projection_matrix, shadow_properties, camera_properties, aoScreenConst, UvToEyeConst );
+}
+
+#else
+
+float customMaterialShadow( vec3 lightDir, vec3 varWorldPos )
+{
+ return 1.0;
+}
+
+#endif
+
+#endif // #ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB
diff --git a/src/Runtime/res/effectlib/abbeNumberIOR.glsllib b/src/Runtime/res/effectlib/abbeNumberIOR.glsllib
new file mode 100644
index 00000000..43ed79d8
--- /dev/null
+++ b/src/Runtime/res/effectlib/abbeNumberIOR.glsllib
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// TODO: compute spectral ior based on float ior and abbe number
+vec3 abbeNumberIOR( in float ior, in float abbeNumber )
+{
+ return( vec3( ior, ior, ior ) );
+}
+
diff --git a/src/Runtime/res/effectlib/anisotropyConversion.glsllib b/src/Runtime/res/effectlib/anisotropyConversion.glsllib
new file mode 100644
index 00000000..b8aae1ed
--- /dev/null
+++ b/src/Runtime/res/effectlib/anisotropyConversion.glsllib
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// TODO: real implementation
+anisotropy_return anisotropyConversion( in float roughness, in float anisotropy, in float anisotropyRotation, in vec3 tangentU, bool miaAnisotropySemantic )
+{
+ anisotropy_return aniso;
+ float angle = 2.0 * PI * anisotropyRotation;
+ float cos_angle = cos(angle);
+ float sin_angle = sin(angle);
+ aniso.tangent_u = normalize( cos_angle * tangentU + sin_angle * binormal );
+ // roughness
+ float anisoFac = 1.0 - clamp(anisotropy, 0.0, 0.999);
+ aniso.roughness_v = clamp( roughness / anisoFac, 0.0001, 1.0);
+ aniso.roughness_u = clamp( aniso.roughness_v * anisoFac, 0.0001, 1.0);
+ return( aniso );
+}
+
diff --git a/src/Runtime/res/effectlib/average.glsllib b/src/Runtime/res/effectlib/average.glsllib
new file mode 100644
index 00000000..8c3f3fc2
--- /dev/null
+++ b/src/Runtime/res/effectlib/average.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+float average( in vec3 v )
+{
+ return( ( v.x + v.y + v.z ) / 3.0f );
+}
+
diff --git a/src/Runtime/res/effectlib/blendColorLayers.glsllib b/src/Runtime/res/effectlib/blendColorLayers.glsllib
new file mode 100644
index 00000000..395b2f50
--- /dev/null
+++ b/src/Runtime/res/effectlib/blendColorLayers.glsllib
@@ -0,0 +1,45 @@
+#ifndef BLEND_COLOR_LAYERS_GLSLLIB
+#define BLEND_COLOR_LAYERS_GLSLLIB
+
+float maxValue( in vec3 t )
+{
+ return max( max( t.x, t.y ), t.z );
+}
+
+vec3 blendColor( in vec3 t, in vec3 b, in float weight, in int blendMode)
+{
+ vec3 blendResult = t;
+ switch( blendMode )
+ {
+ case color_layer_add :
+ blendResult += b;
+ break;
+ case color_layer_multiply :
+ blendResult *= b;
+ break;
+ case color_layer_screen :
+ blendResult += t - t * b;
+ break;
+ case color_layer_overlay:
+ blendResult = (maxValue(t) >= 0.5) ? 2.0 * (t+b - t*b - 0.5) : 2.0 * t*b;
+ break;
+ case color_layer_blend:
+ default:
+ // nothing to be done
+ break;
+ }
+
+ return mix( b, blendResult, weight );
+}
+
+texture_return blendColorLayers( in color_layer colorLayer[1], in vec3 base, in int monoSource )
+{
+ vec3 result = blendColor( colorLayer[0].layer_color, base, colorLayer[0].weight, colorLayer[0].mode );
+
+ texture_return tr;
+ tr.tint = result;
+ tr.mono = monoChannel( vec4( result, 1.0 ), monoSource );
+ return( tr );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/blur.glsllib b/src/Runtime/res/effectlib/blur.glsllib
new file mode 100644
index 00000000..c139e13e
--- /dev/null
+++ b/src/Runtime/res/effectlib/blur.glsllib
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BLUR_GLSLLIB
+#define BLUR_GLSLLIB 1
+#include "depthpass.glsllib"
+varying float xIncrement;
+varying float yIncrement;
+varying vec2 TexCoord0;
+varying vec2 TexCoord1;
+varying vec2 TexCoord2;
+varying vec2 TexCoord3;
+varying vec2 TexCoord4;
+varying vec2 TexCoord5;
+varying vec2 TexCoord6;
+varying vec2 TexCoord7;
+
+
+const vec3 poisson0 = vec3( 0.000000, 0.000000, 0.000000 );
+const vec3 poisson1 = vec3( 0.527837, -0.085868, 0.534776 );
+const vec3 poisson2 = vec3( -0.040088, 0.537087, 0.538581 );
+const vec3 poisson3 = vec3( -0.670445, -0.017995, 0.670686 );
+const vec3 poisson4 = vec3( -0.419418, -0.616039, 0.745262 );
+const vec3 poisson5 = vec3( 0.440453, -0.639399, 0.776421 );
+const vec3 poisson6 = vec3( -0.757088, 0.349334, 0.833796 );
+const vec3 poisson7 = vec3( 0.574619, 0.685879, 0.894772 );
+
+//7 textel gaussian
+#define WT7_0 20.0
+#define WT7_1 15.0
+#define WT7_2 6.0
+#define WT7_3 1.0
+#define WT7_NORMALIZE (WT7_0+2.0*(WT7_1+WT7_2+WT7_3))
+
+//3 textel gaussian
+#define WT3_0 1.0
+#define WT3_1 0.6
+#define WT3_NORMALIZE (WT3_0+2.0*(WT3_1))
+
+uniform vec2 CameraClipRange;
+
+float GetDepthMultiplier(vec2 inTexCoord, sampler2D inDepthSampler, float inFocusDistance, float inFocusWidth, float inFocusPenumbra)
+{
+ float depthTap = getDepthValue( texture2D(inDepthSampler, inTexCoord), CameraClipRange );
+ float linearDepth = depthValueToLinearDistance( depthTap, CameraClipRange );
+ float depthDiff = max( 0.0, abs( linearDepth - inFocusDistance ) - (inFocusWidth/2.0) ) / inFocusPenumbra;
+ return clamp( depthDiff, 0.0, 1.0 );
+}
+
+float GetTiltShiftMultiplier(vec2 inTexCoord, float inFocusBarHeight, float inFocusWidth )
+{
+ //For now, you can't rotate the focus blur but in time you will be able to.
+ float texPos = inTexCoord.y;
+ float focusDiff = max( 0.0, abs( texPos - inFocusBarHeight ) - (inFocusWidth/2.0) ) / inFocusWidth;
+ return clamp( focusDiff, 0.0, 1.0 );
+}
+
+#ifdef VERTEX_SHADER
+
+void SetupBoxBlurCoords(vec2 inTexInfo)
+{
+ xIncrement = .5 / inTexInfo.x;
+ yIncrement = .5 / inTexInfo.y;
+ TexCoord0 = vec2( TexCoord.x + xIncrement, TexCoord.y + yIncrement );
+ TexCoord1 = vec2( TexCoord.x - xIncrement, TexCoord.y - yIncrement );
+ TexCoord2 = vec2( TexCoord.x - xIncrement, TexCoord.y + yIncrement );
+ TexCoord3 = vec2( TexCoord.x + xIncrement, TexCoord.y - yIncrement );
+}
+
+void SetupPoissonBlurCoords(float inBlurAmount, vec2 inTexInfo )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ TexCoord0 = vec2( TexCoord.x + poisson0.x * incX, TexCoord.y + poisson0.y * incY );
+ TexCoord1 = vec2( TexCoord.x + poisson1.x * incX, TexCoord.y + poisson1.y * incY );
+ TexCoord2 = vec2( TexCoord.x + poisson2.x * incX, TexCoord.y + poisson2.y * incY );
+ TexCoord3 = vec2( TexCoord.x + poisson3.x * incX, TexCoord.y + poisson3.y * incY );
+ TexCoord4 = vec2( TexCoord.x + poisson4.x * incX, TexCoord.y + poisson4.y * incY );
+ TexCoord5 = vec2( TexCoord.x + poisson5.x * incX, TexCoord.y + poisson5.y * incY );
+ TexCoord6 = vec2( TexCoord.x + poisson6.x * incX, TexCoord.y + poisson6.y * incY );
+ TexCoord7 = vec2( TexCoord.x + poisson7.x * incX, TexCoord.y + poisson7.y * incY );
+}
+
+void SetupHorizontalGaussianBlur( float inDestWidth, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestWidth;
+ TexCoord0 = vec2(inTexCoord.x + increment , inTexCoord.y );
+ TexCoord1 = vec2(inTexCoord.x + increment * 2.0 , inTexCoord.y);
+ TexCoord2 = vec2(inTexCoord.x + increment * 3.0 , inTexCoord.y);
+ TexCoord3 = vec2(inTexCoord.x , inTexCoord.y);
+ TexCoord4 = vec2(inTexCoord.x - increment , inTexCoord.y);
+ TexCoord5 = vec2(inTexCoord.x - increment * 2.0 , inTexCoord.y);
+ TexCoord6 = vec2(inTexCoord.x - increment * 3.0 , inTexCoord.y);
+}
+
+void SetupVerticalGaussianBlur( float inDestHeight, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestHeight;
+ TexCoord0 = vec2(inTexCoord.x, inTexCoord.y + increment );
+ TexCoord1 = vec2(inTexCoord.x, inTexCoord.y + increment * 2.0 );
+ TexCoord2 = vec2(inTexCoord.x, inTexCoord.y + increment * 3.0);
+ TexCoord3 = vec2(inTexCoord.x, inTexCoord.y);
+ TexCoord4 = vec2(inTexCoord.x, inTexCoord.y - increment);
+ TexCoord5 = vec2(inTexCoord.x, inTexCoord.y - increment * 2.0);
+ TexCoord6 = vec2(inTexCoord.x, inTexCoord.y - increment * 3.0);
+}
+
+void SetupHorizontalGaussianBlur3Tap( float inDestWidth, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestWidth;
+ TexCoord0 = vec2(inTexCoord.x + increment , inTexCoord.y );
+ TexCoord1 = vec2(inTexCoord.x , inTexCoord.y);
+ TexCoord2 = vec2(inTexCoord.x - increment , inTexCoord.y);
+}
+
+void SetupVerticalGaussianBlur3Tap( float inDestHeight, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestHeight;
+ TexCoord0 = vec2(inTexCoord.x, inTexCoord.y + increment );
+ TexCoord1 = vec2(inTexCoord.x, inTexCoord.y);
+ TexCoord2 = vec2(inTexCoord.x, inTexCoord.y - increment);
+}
+
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+vec4 BoxDepthBlur(sampler2D inDepthSampler, sampler2D inBlurSampler, float inBlurSamplerAlphaFlag
+ , float inFocusDistance, float inFocusWidth, float inFocusPenumbra )
+{
+ float mult0 = .25 * GetDepthMultiplier( TexCoord0, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float mult1 = .25 * GetDepthMultiplier( TexCoord1, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float mult2 = .25 * GetDepthMultiplier( TexCoord2, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float mult3 = .25 * GetDepthMultiplier( TexCoord3, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float multTotal = mult0 + mult1 + mult2 + mult3;
+ float totalDivisor = multTotal != 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = GetTextureValue(inBlurSampler, TexCoord0, inBlurSamplerAlphaFlag) * mult0;
+ OutCol += GetTextureValue(inBlurSampler, TexCoord1, inBlurSamplerAlphaFlag) * mult1;
+ OutCol += GetTextureValue(inBlurSampler, TexCoord2, inBlurSamplerAlphaFlag) * mult2;
+ OutCol += GetTextureValue(inBlurSampler, TexCoord3, inBlurSamplerAlphaFlag) * mult3;
+ return OutCol * totalDivisor;
+}
+
+vec4 BoxTiltShiftBlur( sampler2D inBlurSampler, float inBlurSamplerAlphaFlag
+ , float inFocusBarHeight, float inFocusWidth )
+{
+ float mult0 = .25 * GetTiltShiftMultiplier( TexCoord0, inFocusBarHeight, inFocusWidth );
+ float mult1 = .25 * GetTiltShiftMultiplier( TexCoord1, inFocusBarHeight, inFocusWidth );
+ float mult2 = .25 * GetTiltShiftMultiplier( TexCoord2, inFocusBarHeight, inFocusWidth );
+ float mult3 = .25 * GetTiltShiftMultiplier( TexCoord3, inFocusBarHeight, inFocusWidth );
+ float multTotal = mult0 + mult1 + mult2 + mult3;
+ float totalDivisor = multTotal != 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = GetTextureValuePreMult(inBlurSampler, TexCoord0) * mult0;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord1) * mult1;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord2) * mult2;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord3) * mult3;
+ return OutCol * totalDivisor;
+}
+
+vec4 PoissonDepthBlur(sampler2D inSampler, float inAlphaFlag, sampler2D inDepthSampler
+ , float inFocusDistance, float inFocusWidth, float inFocusPenumbra )
+{
+ float mult0 = (1.0 - poisson0.z) * GetDepthMultiplier(TexCoord0,inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra);
+ float mult1 = (1.0 - poisson1.z) * GetDepthMultiplier(TexCoord1,inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra);
+ float mult2 = (1.0 - poisson2.z) * GetDepthMultiplier(TexCoord2,inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra);
+
+ float multTotal = mult0 + mult1 + mult2;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+
+ vec4 outColor = GetTextureValue( inSampler, TexCoord0, inAlphaFlag ) * (mult0 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord1, inAlphaFlag ) * (mult1 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord2, inAlphaFlag ) * (mult2 * multMultiplier);
+ return outColor;
+}
+
+vec4 PoissonTiltShiftBlur(sampler2D inSampler, float inAlphaFlag, float inBarHeight, float inFocusWidth )
+{
+ float mult0 = (1.0 - poisson0.z) * GetTiltShiftMultiplier(TexCoord0, inBarHeight, inFocusWidth );
+ float mult1 = (1.0 - poisson1.z) * GetTiltShiftMultiplier(TexCoord1, inBarHeight, inFocusWidth );
+ float mult2 = (1.0 - poisson2.z) * GetTiltShiftMultiplier(TexCoord2, inBarHeight, inFocusWidth );
+ float mult3 = (1.0 - poisson3.z) * GetTiltShiftMultiplier(TexCoord3, inBarHeight, inFocusWidth );
+ float mult4 = (1.0 - poisson4.z) * GetTiltShiftMultiplier(TexCoord4, inBarHeight, inFocusWidth );
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+
+ vec4 outColor = GetTextureValuePreMult( inSampler, TexCoord0 ) * (mult0 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord1 ) * (mult1 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord2 ) * (mult2 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord3 ) * (mult3 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord4 ) * (mult4 * multMultiplier);
+ return outColor;
+}
+
+float GaussianAlphaBlur( sampler2D inSampler, float inAlphaFlag )
+{
+ float OutCol = 0.0;
+ OutCol += GetTextureValue(inSampler, TexCoord0, inAlphaFlag).a * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord1, inAlphaFlag).a * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord2, inAlphaFlag).a * ( WT7_3/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord3, inAlphaFlag).a * ( WT7_0/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord4, inAlphaFlag).a * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord5, inAlphaFlag).a * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord6, inAlphaFlag).a * ( WT7_3/WT7_NORMALIZE );
+ return OutCol;
+}
+
+vec4 GaussianBlur( sampler2D inSampler, float inAlphaFlag )
+{
+ vec4 OutCol = vec4(0.0);
+ OutCol += GetTextureValue(inSampler, TexCoord0, inAlphaFlag) * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord1, inAlphaFlag) * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord2, inAlphaFlag) * ( WT7_3/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord3, inAlphaFlag) * ( WT7_0/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord4, inAlphaFlag) * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord5, inAlphaFlag) * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord6, inAlphaFlag) * ( WT7_3/WT7_NORMALIZE );
+ return OutCol;
+}
+
+vec4 GaussianBlur3Tap( sampler2D inSampler, float inAlphaFlag )
+{
+ vec4 OutCol = vec4(0.0);
+ OutCol += GetTextureValue(inSampler, TexCoord0, inAlphaFlag) * ( WT3_1/WT3_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord1, inAlphaFlag) * ( WT3_0/WT3_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord2, inAlphaFlag) * ( WT3_1/WT3_NORMALIZE );
+ return OutCol;
+}
+
+//Get texture data for a texture we know is premultiplied.
+vec4 GaussianBlur3TapPremultiplied( sampler2D inSampler )
+{
+ vec4 OutCol = vec4(0.0);
+ OutCol += texture2D(inSampler, TexCoord0) * ( WT3_1/WT3_NORMALIZE );
+ OutCol += texture2D(inSampler, TexCoord1) * ( WT3_0/WT3_NORMALIZE );
+ OutCol += texture2D(inSampler, TexCoord2) * ( WT3_1/WT3_NORMALIZE );
+ return OutCol;
+}
+
+vec4 GaussianDepthBlur( sampler2D inSampler, float inTextureAlphaInfo, sampler2D inDepthSampler
+ , float inFocusDistance, float inFocusWidth, float inFocusPenumbra )
+{
+ //We modulate each sample weight by the depth value so that we minimize bleeding of the focused
+ //area into the non-focused area.
+ float mult0 = GetDepthMultiplier(TexCoord0, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_1;
+ float mult1 = GetDepthMultiplier(TexCoord1, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_2;
+ float mult2 = GetDepthMultiplier(TexCoord2, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_3;
+ float mult3 = GetDepthMultiplier(TexCoord3, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_0;
+ float mult4 = GetDepthMultiplier(TexCoord4, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_1;
+ float mult5 = GetDepthMultiplier(TexCoord5, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_2;
+ float mult6 = GetDepthMultiplier(TexCoord6, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_3;
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = vec4(0.0);
+ OutCol += GetTextureValue(inSampler, TexCoord0, inTextureAlphaInfo) * (mult0 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord1, inTextureAlphaInfo) * (mult1 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord2, inTextureAlphaInfo) * (mult2 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord3, inTextureAlphaInfo) * (mult3 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord4, inTextureAlphaInfo) * (mult4 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord5, inTextureAlphaInfo) * (mult5 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord6, inTextureAlphaInfo) * (mult6 * multMultiplier);
+ return OutCol;
+}
+
+#endif
+
+
+#endif // BLUR_GLSLLIB
diff --git a/src/Runtime/res/effectlib/calculateRoughness.glsllib b/src/Runtime/res/effectlib/calculateRoughness.glsllib
new file mode 100644
index 00000000..d1e099bd
--- /dev/null
+++ b/src/Runtime/res/effectlib/calculateRoughness.glsllib
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+float calculateRoughness( in vec3 N, in float roughnessU, in float roughnessV, in vec3 tangentU )
+{
+ float roughness = roughnessU;
+ if ( abs(roughnessU - roughnessV) > 0.00001)
+ {
+ // determine major and minor radii a and b, and the vector along the major axis
+ float a = roughnessU;
+ float b = roughnessV;
+
+ // we need the angle between the major axis and the projection of viewDir on the tangential plane
+ // the major axis is the orthonormalization of tangentU with respect to N
+ // the projection of viewDir is the orthonormalization of viewDir with respect to N
+ // as both vectors would be calculated by orthonormalize, we can as well leave the second cross
+ // product in those calculations away, as they don't change the angular relation.
+ vec3 minorAxis = normalize( cross( tangentU, N ) ); // crossing this with N would give the major axis
+ // which is equivalent to orthonormalizing tangentU with respect to N
+ if ( roughnessU < roughnessV )
+ {
+ a = roughnessV;
+ b = roughnessU;
+ minorAxis = cross( N, minorAxis );
+ }
+
+ vec3 po = normalize( cross( viewDir, N ) );
+ float cosPhi = dot( po, minorAxis );
+
+ // determine the polar coordinate of viewDir, take that radius as the roughness
+ float excentricitySquare = 1.0f - square( b / a );
+ roughness = b / sqrt( 1.0f - excentricitySquare * square( cosPhi ) );
+ }
+ return( roughness );
+}
+
diff --git a/src/Runtime/res/effectlib/coordinateSource.glsllib b/src/Runtime/res/effectlib/coordinateSource.glsllib
new file mode 100644
index 00000000..bc435d51
--- /dev/null
+++ b/src/Runtime/res/effectlib/coordinateSource.glsllib
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+texture_coordinate_info coordinateSource( in int coordinateSystem, in int textureSpace )
+{
+ texture_coordinate_info tci;
+ switch( coordinateSystem )
+ {
+ case texture_coordinate_object :
+ tci.position = varObjPos;
+ tci.tangent_u = normalize( varObjTangent );
+ tci.tangent_v = normalize( varObjBinormal );
+ break;
+ case texture_coordinate_world :
+ tci.position = varWorldPos;
+ tci.tangent_u = normalize( varTangent );
+ tci.tangent_v = normalize( varBinormal );
+ break;
+ case texture_coordinate_uvw :
+ default :
+ tci.position = varTexCoord0;
+ tci.tangent_u = normalize( varTangent );
+ tci.tangent_v = normalize( varBinormal );
+ break;
+ }
+ return( tci );
+}
+
diff --git a/src/Runtime/res/effectlib/cube.glsllib b/src/Runtime/res/effectlib/cube.glsllib
new file mode 100644
index 00000000..74da8333
--- /dev/null
+++ b/src/Runtime/res/effectlib/cube.glsllib
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+float cube( in float x )
+{
+ return( x * x * x );
+}
+
+vec2 cube( in vec2 x )
+{
+ return( x * x * x );
+}
+
+vec3 cube( in vec3 x )
+{
+ return( x * x * x );
+}
+
+vec4 cube( in vec4 x )
+{
+ return( x * x * x );
+}
+
diff --git a/src/Runtime/res/effectlib/customCurveLayer.glsllib b/src/Runtime/res/effectlib/customCurveLayer.glsllib
new file mode 100644
index 00000000..87c1def8
--- /dev/null
+++ b/src/Runtime/res/effectlib/customCurveLayer.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 customCurveLayer( in vec3 L, in float normal_reflectivity, in float grazing_reflectivity, in float exponent, float weight, in vec3 layercolor, vec4 layer, vec4 base, in float alpha )
+{
+ vec3 H = normalize( viewDir + L );
+ vec3 refl = reflect( -viewDir, H );
+ float reflWt = clamp( dot( surfNormal, refl ) + 1.0, 0.0, 1.0 );
+
+ float curveFactor = mix( normal_reflectivity, grazing_reflectivity, pow(1.0 - abs(dot( viewDir, H )), exponent) );
+ curveFactor *= weight * reflWt;
+
+ return( vec4( mix( base.rgb, layercolor * layer.rgb, curveFactor ), mix(alpha, 1.0, curveFactor) ) );
+}
+
diff --git a/src/Runtime/res/effectlib/customMaterial.glsllib b/src/Runtime/res/effectlib/customMaterial.glsllib
new file mode 100644
index 00000000..e99fa6e6
--- /dev/null
+++ b/src/Runtime/res/effectlib/customMaterial.glsllib
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOM_MATERIAL_GLSLLIB
+#define CUSTOM_MATERIAL_GLSLLIB 1
+
+#define SNAPPER_SAMPLER2D(samplerName, samplerNiceName, texFilter, texWrap, showUI )\
+uniform sampler2D samplerName;
+
+// some useful defines
+#ifndef PI
+#define PI 3.14159265358979f
+#define PI_HALF ( 0.5f * PI )
+#define PI_TWO ( 2.0f * PI )
+#define ONE_OVER_PI ( 1.0f / PI )
+#define TWO_OVER_PI ( 2.0f / PI )
+#define PI_SQUARE ( PI * PI )
+#endif
+
+#endif // CUSTOM_MATERIAL_GLSLLIB
diff --git a/src/Runtime/res/effectlib/customMaterialFragBody.glsllib b/src/Runtime/res/effectlib/customMaterialFragBody.glsllib
new file mode 100644
index 00000000..0de59261
--- /dev/null
+++ b/src/Runtime/res/effectlib/customMaterialFragBody.glsllib
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOM_MATERIAL_FRAG_BODY_GLSLLIB
+#define CUSTOM_MATERIAL_FRAG_BODY_GLSLLIB
+
+ bool twoSided = false;
+ vec3 materialEmissive = vec3( 0.0f, 0.0f, 0.0f );
+
+ float materialIOR = computeIOR();
+
+ if ( gl_FrontFacing )
+ {
+ materialEmissive = computeFrontMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ else
+ {
+ materialIOR = 1.0f / materialIOR;
+ twoSided = evalTwoSided();
+ if ( twoSided )
+ {
+ normal = -normal;
+ materialEmissive = computeBackMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ }
+
+ vec4 rgba = vec4( materialEmissive, 0.0f );
+
+ vec3 lightAmbient, lightDiffuse, lightSpecular, L;
+ for ( int i=0 ; i<uNumLights ; i++ )
+ {
+ sampleLight( lights[i], varWorldPos, L, lightAmbient, lightDiffuse, lightSpecular);
+ //evalTemporariesPerLightSource( normal, L, lightDiffuse, lightSpecular, materialIOR );
+ if (gl_FrontFacing)
+ computeFrontLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, 1.0 );
+ else
+ computeBackLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, 1.0 );
+ }
+ for ( int i=0 ; i < uNumAreaLights; ++i )
+ {
+ if (gl_FrontFacing)
+ computeFrontAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ else
+ computeBackAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ }
+
+ if ( 0.0f < alpha )
+ {
+ if (gl_FrontFacing)
+ computeFrontLayerEnvironment( normal, viewDir, 1.0 );
+ else
+ computeBackLayerEnvironment( normal, viewDir, 1.0 );
+ }
+
+ rgba += computeLayerWeights( alpha );
+
+#endif
diff --git a/src/Runtime/res/effectlib/customMaterialFragBodyAO.glsllib b/src/Runtime/res/effectlib/customMaterialFragBodyAO.glsllib
new file mode 100644
index 00000000..08b2c788
--- /dev/null
+++ b/src/Runtime/res/effectlib/customMaterialFragBodyAO.glsllib
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOM_MATERIAL_FRAG_BODY_AO_GLSLLIB
+#define CUSTOM_MATERIAL_FRAG_BODY_AO_GLSLLIB
+
+ bool twoSided = false;
+ vec3 materialEmissive = vec3( 0.0f, 0.0f, 0.0f );
+
+ float materialIOR = computeIOR();
+
+ if ( gl_FrontFacing )
+ {
+ materialEmissive = computeFrontMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ else
+ {
+ materialIOR = 1.0f / materialIOR;
+ twoSided = evalTwoSided();
+ if ( twoSided )
+ {
+ normal = -normal;
+ materialEmissive = computeBackMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ }
+
+ vec4 rgba = vec4( materialEmissive, 0.0f );
+
+ // compute ambient occlusion
+ float aoFactor = customMaterialAO( );
+
+ vec3 lightAmbient, lightDiffuse, lightSpecular, L;
+ for ( int i=0 ; i<uNumLights ; i++ )
+ {
+ sampleLight( lights[i], varWorldPos, L, lightAmbient, lightDiffuse, lightSpecular);
+ lightAmbient *= aoFactor;
+ lightDiffuse *= aoFactor;
+
+ //evalTemporariesPerLightSource( normal, L, lightDiffuse, lightSpecular, materialIOR );
+ if (gl_FrontFacing)
+ computeFrontLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, aoFactor );
+ else
+ computeBackLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, aoFactor );
+ }
+ for ( int i=0 ; i < uNumAreaLights; ++i )
+ {
+ if (gl_FrontFacing)
+ computeFrontAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ else
+ computeBackAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ }
+
+ if ( 0.0f < alpha )
+ {
+ if (gl_FrontFacing)
+ computeFrontLayerEnvironment( normal, viewDir, aoFactor );
+ else
+ computeBackLayerEnvironment( normal, viewDir, aoFactor );
+ }
+
+ rgba += computeLayerWeights( alpha );
+
+#endif
diff --git a/src/Runtime/res/effectlib/defaultMaterialFresnel.glsllib b/src/Runtime/res/effectlib/defaultMaterialFresnel.glsllib
new file mode 100644
index 00000000..d7e9fa15
--- /dev/null
+++ b/src/Runtime/res/effectlib/defaultMaterialFresnel.glsllib
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_MATERIAL_FRESNEL_GLSLLIB
+#define DEFAULT_MATERIAL_FRESNEL_GLSLLIB
+
+float defaultMaterialSimpleFresnel( in vec3 N, in vec3 viewDir, in float ior, float fresnelPower )
+{
+ float F = ((1.0-ior) * (1.0-ior)) / ((1.0+ior) * (1.0+ior));
+ float VdotN = dot(viewDir, N);
+ float dvn = abs( dFdx(VdotN) * dFdy(VdotN) );
+ VdotN = clamp( VdotN, 0.0, 1.0 );
+ float ratio = F + (1.0 - F) * pow(1.0 - VdotN, fresnelPower);
+
+ return clamp( ratio * pow( VdotN, dvn * fresnelPower ), 0.0, 1.0 );
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/defaultMaterialLighting.glsllib b/src/Runtime/res/effectlib/defaultMaterialLighting.glsllib
new file mode 100644
index 00000000..1097c766
--- /dev/null
+++ b/src/Runtime/res/effectlib/defaultMaterialLighting.glsllib
@@ -0,0 +1,80 @@
+/**
+ * UICViewer lighting equation implementations
+ */
+
+#ifndef DEFAULT_MATERIAL_LIGHTING
+#define DEFAULT_MATERIAL_LIGHTING
+
+#include "diffuseReflectionBSDF.glsllib"
+#include "luminance.glsllib"
+#include "specularBSDF.glsllib"
+
+#include "funccalculatePointLightAttenuation.glsllib"
+#include "funcgetTransformedUVCoords.glsllib"
+
+vec2 calculateLightParameters( vec3 lightDir, vec3 normalDir )
+{
+ vec2 retval;
+ retval.x = max( 0.0, -1.0 * dot( lightDir, normalDir ) ); //diffuseIntensity
+ retval.y = clamp( retval.x * 4.0, 0.0, 1.0 ); //selfShadowTerm
+ return retval;
+}
+vec2 calculateWrapLightParameters( vec3 lightDir, vec3 normalDir, float wrap )
+{
+ vec2 retval;
+ retval.x = max( 0.0, -1.0 * ((dot(lightDir, normalDir) + wrap)/ (1.0 + wrap)) ); //diffuseIntensity
+ retval.y = clamp( retval.x, 0.0, 1.0 ); //selfShadowTerm
+ return retval;
+}
+
+vec3 calculateDirectionalAddition( vec3 lightColor, vec2 lightParameters ) {
+ return ( lightColor * lightParameters.x * lightParameters.y );
+}
+
+vec3 calculateSpecularAddition( vec3 lightDir, vec3 normalDir, vec3 viewVec, vec3 lightSpecularColor, float specularAmount
+ , float specularRoughness, vec2 lightParameters )
+{
+ vec3 reflection = normalize( 2.0 * lightParameters.x * normalDir + lightDir );
+ return ( lightParameters.y * specularAmount * lightSpecularColor * pow( clamp( dot( reflection, viewVec ), 0.0, 1.0 ), specularRoughness ) );
+}
+
+float calculateDiffuseAreaFactors( in vec3 lightDir, in vec3 lightPos, in vec4 lightUp, in vec4 lightRt, in vec3 worldPos, out vec3 outDir )
+{
+ vec3 v0 = lightPos - (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v1 = lightPos - (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v2 = lightPos + (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v3 = lightPos + (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ v0 = normalize( v0 - worldPos ); v1 = normalize( v1 - worldPos );
+ v2 = normalize( v2 - worldPos ); v3 = normalize( v3 - worldPos );
+ float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
+ float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
+ float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
+ float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );
+ outDir = vec3( 0.0 );
+ outDir -= normalize(cross( v0, v1 )) * a01;
+ outDir -= normalize(cross( v1, v2 )) * a12;
+ outDir -= normalize(cross( v2, v3 )) * a23;
+ outDir -= normalize(cross( v3, v0 )) * a30;
+ float retVal = length(outDir) * 0.15915494309; // solid angle / 2*pi
+ outDir = -normalize(outDir);
+ retVal *= clamp( dot( worldPos-lightPos, lightDir), 0.0, 1.0 );
+ return retVal;
+}
+
+vec3 calculateSpecDirection( in vec3 lightDir, in vec3 lightPos, in vec4 lightUp, in vec4 lightRt, in vec3 worldPos, in vec3 worldNorm, in vec3 viewDir )
+{
+ vec3 reflDir = reflect(viewDir, worldNorm);
+ vec3 ldir = normalize( lightPos - worldPos );
+ if ( dot( ldir, lightDir ) > 0.0 ) { return vec3(0.0001); }
+ float t = (dot(lightDir, worldPos) - dot(lightDir, lightPos)) / dot(lightDir, reflDir);
+ if ( t < 0.0 ) { return vec3(0.0001); }
+ vec3 xsectPos = worldPos - t * reflDir;
+ float tx = dot( xsectPos - lightPos, lightRt.xyz );
+ float ty = dot( xsectPos - lightPos, lightUp.xyz );
+ tx = clamp(tx, -lightRt.w*0.5, lightRt.w*0.5);
+ ty = clamp(ty, -lightUp.w*0.5, lightUp.w*0.5);
+ xsectPos = lightPos + lightUp.xyz * ty + lightRt.xyz * tx;
+ return normalize( worldPos - xsectPos );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib b/src/Runtime/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib
new file mode 100644
index 00000000..729f0d76
--- /dev/null
+++ b/src/Runtime/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_MATERIAL_PHYS_GLOSSY_BSDF_GLSLLIB
+#define DEFAULT_MATERIAL_PHYS_GLOSSY_BSDF_GLSLLIB
+#ifndef UIC_DEFINE_API
+#define UIC_DEFINE_API
+#endif
+
+#include "luminance.glsllib"
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#include "physGlossyBSDF.glsllib"
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/depthpass.glsllib b/src/Runtime/res/effectlib/depthpass.glsllib
new file mode 100644
index 00000000..59849701
--- /dev/null
+++ b/src/Runtime/res/effectlib/depthpass.glsllib
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEPTHPASS_GLSLIB
+#define DEPTHPASS_GLSLIB 1
+
+float calculateVertexDepth( vec2 camera_properties, vec4 position )
+{
+ float camera_range = camera_properties.y - camera_properties.x;
+ return 1.0 - ((position.w - camera_properties.x) / (camera_range));
+}
+
+#if __VERSION__ <= 120
+float modf(in float val, out float integer)
+{
+ integer = floor(val);
+ return val - integer;
+}
+#endif
+
+vec4 outputDepth( float vert_depth )
+{
+ float integer_portion = 0.0;
+ float fraction = modf((vert_depth * 255.0), integer_portion);
+ return vec4( integer_portion / 255.0, fraction, 0, 1.0 );
+}
+
+float getDepthValue( vec4 depth_texture_sample, vec2 camera_properties )
+{
+
+#if __VERSION__ >= 300
+ float zNear = camera_properties.x;
+ float zFar = camera_properties.y;
+ float zRange = zFar - zNear;
+ float z_b = depth_texture_sample.x;
+ float z_n = 2.0 * z_b - 1.0;
+ float z_e = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zRange));
+ return 1.0 - ((z_e - camera_properties.x) / (zRange));
+#else
+ return depth_texture_sample.x + (depth_texture_sample.y / 255.0);
+#endif
+}
+
+float depthValueToLinearDistance( float depth_value, vec2 camera_properties )
+{
+ float FarClipDistance = camera_properties.y;
+ float NearClipDistance = camera_properties.x;
+ float DepthRange = FarClipDistance - NearClipDistance;
+ float linearDepth = NearClipDistance + (DepthRange * (1.0 - depth_value));
+ return linearDepth;
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/dfTint.glsllib b/src/Runtime/res/effectlib/dfTint.glsllib
new file mode 100644
index 00000000..f1f4b7ac
--- /dev/null
+++ b/src/Runtime/res/effectlib/dfTint.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 dfTint( in vec3 tint, in vec4 base )
+{
+ return( vec4( tint * base.rgb, base.a ) );
+}
+
diff --git a/src/Runtime/res/effectlib/diffuseReflectionBSDF.glsllib b/src/Runtime/res/effectlib/diffuseReflectionBSDF.glsllib
new file mode 100644
index 00000000..0f4aaed2
--- /dev/null
+++ b/src/Runtime/res/effectlib/diffuseReflectionBSDF.glsllib
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "funcdiffuseReflectionBSDF.glsllib"
+#include "funcdiffuseReflectionWrapBSDF.glsllib"
+
+vec4 lambertReflectionBSDF( in vec3 N, in vec3 L, in vec3 lightDiffuse )
+{
+ // If we're not going to use the roughness on the diffuse, there's no point
+ // in wasting the cycles for the branching.
+ float cosThetaI = max( 0.0f, dot( N, L ) );
+ return vec4( cosThetaI * lightDiffuse, 1.0f );
+}
+
+
+vec4 diffuseReflectionBSDFEnvironment( in vec3 N, in float roughness )
+{
+ return( vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
+}
+
+// RNM radiosity normal maps
+vec4 diffuseRNM( in vec3 N, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+ // we use a fixed basis like Half Life
+ vec3 B0 = vec3( -0.40825, 0.70711, 0.57735);
+ vec3 B1 = vec3( -0.40825, -0.70711, 0.57735);
+ vec3 B2 = vec3( 0.8165, 0.0, 0.57735);
+
+ vec3 dp;
+ dp.x = clamp( dot ( N , B0 ), 0.0, 1.0);
+ dp.y = clamp( dot ( N , B1 ), 0.0, 1.0);
+ dp.z = clamp( dot ( N , B2 ), 0.0, 1.0);
+
+ float sum = 1.0 / dot( dp, vec3(1.0, 1.0, 1.0) );
+ vec3 diffuseLight = dp.x * rnmX + dp.y * rnmY + dp.z * rnmZ;
+ //vec3 diffuseLight = N.x * rnmX + N.y * rnmY + N.z * rnmZ;
+
+ return (vec4(diffuseLight, 1.0) * sum);
+}
diff --git a/src/Runtime/res/effectlib/diffuseTransmissionBSDF.glsllib b/src/Runtime/res/effectlib/diffuseTransmissionBSDF.glsllib
new file mode 100644
index 00000000..16b70b04
--- /dev/null
+++ b/src/Runtime/res/effectlib/diffuseTransmissionBSDF.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 diffuseTransmissionBSDF( in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightDiffuse, in vec4 transmissiveColor, in float translucentFalloff, float lightWrap )
+{
+ float cosThetaI = max( 0.0f, (dot( N, L ) + lightWrap) / (1.0 + lightWrap) );
+ float factor = cosThetaI;
+
+ float l = 0.2126f * transmissiveColor.r + 0.7152f * transmissiveColor.g + 0.0722f * transmissiveColor.b;
+
+ float translucent_thickness = l * l;
+ float translucent_thickness_exp = exp( translucent_thickness * translucentFalloff);
+
+ return( translucent_thickness_exp * vec4( factor * lightDiffuse, 1.0f ) );
+}
diff --git a/src/Runtime/res/effectlib/directionalFactor.glsllib b/src/Runtime/res/effectlib/directionalFactor.glsllib
new file mode 100644
index 00000000..da3d310e
--- /dev/null
+++ b/src/Runtime/res/effectlib/directionalFactor.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 directionalFactor( in vec3 normal, in vec3 viewDir, in vec3 normal_col, in vec3 grazing_col, in float exponent, in vec4 base )
+{
+ float f;
+
+ f = clamp(dot(viewDir, normal),0.0, 1.0 );
+ f = 1.0 - pow(f, 1.0/exponent);
+ vec3 directionalColor = mix( normal_col, grazing_col, f );
+
+ vec4 color = base * vec4(directionalColor, 1.0);
+
+ return color;
+} \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/effect.glsllib b/src/Runtime/res/effectlib/effect.glsllib
new file mode 100644
index 00000000..c5bfee5a
--- /dev/null
+++ b/src/Runtime/res/effectlib/effect.glsllib
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EFFECT_GLSLLIB
+#define EFFECT_GLSLLIB 1
+
+//Defines used in the effect files.
+
+vec4 GetTextureValue( sampler2D sampler, vec2 inUVCoords, float inTextureAlphaInfo )
+{
+ vec4 c = texture2D(sampler, inUVCoords);
+ c.rgb = mix( c.rgb*c.a, c.rgb, inTextureAlphaInfo );
+ return c;
+}
+
+vec4 GetTextureValuePreMult( sampler2D sampler, vec2 inUVCoords )
+{
+ return texture2D(sampler, inUVCoords);
+}
+
+#define SNAPPER_TITLE( title )
+
+#define SNAPPER_PARAMETER(propName, datatype, rangeMin, rangeMax, propNiceName, defaultValue) datatype propName
+
+#define SNAPPER_ANGLE( propName, propNiceName, defaultValueAsFloat ) uniform float propName;
+#define SNAPPER_CHECKBOX(propName, propNiceName, defaultValue) uniform float propName;
+
+#define SNAPPER_ENUM_BEGIN(propName, propNiceName, defaultValueAsIndex) uniform int propName;
+#define SNAPPER_ENUM_VALUE(valueNiceName)
+#define SNAPPER_ENUM_END()
+
+#define SNAPPER_POINT2(propName, propNiceName, defaultValue) uniform vec2 propName;
+#define SNAPPER_COLOR(propName, propNiceName, defaultValue) uniform vec3 propName;
+
+
+#define TEXTURE_LOOKUP_FUNC(name) \
+
+
+//texType = one of: ubyte, ushort, float
+//texFormat = one of: rgb, rgba, lum, lum_alpha
+//texFilter = one of: nearest, linear
+//texWrap = one of: repeat, clamp
+#define SNAPPER_EXTERNAL_PARAMETER(propName, datatype, rangeMin, rangeMax, propNiceName, defaultValue)
+#define SNAPPER_EXTERNAL_ANGLE(propName, propNiceName, defaultValueAsFloat)
+
+// Provide the ability to render outside a effect boundary.
+// Total size = The original effect size * Overrendering value
+// Overrendering value needs to be >= 1.0
+#define SNAPPER_OVERRENDERING(value) const float OverrenderingValue = value;
+
+
+
+#ifdef VERTEX_SHADER
+// Attributes and uniforms used throughout the system.
+attribute vec3 attr_pos;
+attribute vec2 attr_uv;
+#endif
+
+uniform mat4 ModelViewProjectionMatrix;
+//x holds the texture width, y holds the texture height
+//z holds 0,1 value if it should be premultiplied
+uniform vec4 Texture0Info;
+uniform vec2 DestSize; //size of the destination in pixels including overrendering if specified.
+uniform sampler2D Texture0;
+varying vec2 TexCoord;
+uniform vec2 FragColorAlphaSettings; //x > 0.0 premultiply result, y is an alpha multiplier (opacity setting)
+
+vec4 Transform( mat4 ModelViewProjectionMatrix, vec2 inDestSize, vec4 inVertex )
+{
+ vec4 temp = ModelViewProjectionMatrix * vec4( inDestSize.x * .5 * inVertex.x, inDestSize.y * .5 * inVertex.y, inVertex.z, inVertex.w );
+ return temp;
+}
+////////////////////////////////////////////////////////////
+// provide the texture lookup functions for the default
+// texture (Texture0).
+vec4 texture2D_0(vec2 uv)
+{
+ return GetTextureValue( Texture0, uv, Texture0Info.z );
+}
+
+#ifdef FRAGMENT_SHADER
+////////////////////////////////////////////////////////////
+// the functions to set the final frag result.
+void colorOutput(vec4 c)
+{
+ c *= FragColorAlphaSettings.x;
+ gl_FragColor = clamp(c, 0.0, c.a );
+}
+
+#endif
+
+
+
+////////////////////////////////////////////////////////////
+// define the main functions.
+
+#ifdef VERTEX_SHADER
+#ifndef NO_VERT_MAIN
+
+void vert();
+void main()
+{
+ gl_Position = Transform( ModelViewProjectionMatrix, DestSize, vec4(attr_pos, 1.0) );
+ TexCoord = attr_uv;
+ vert();
+}
+
+#endif
+#endif
+
+#ifdef FRAGMENT_SHADER
+#ifndef NO_FRAG_MAIN
+void frag();
+void main()
+{
+ frag();
+}
+#endif // NO_FRAG_MAIN
+#endif // FRAGMENT_SHADER
+
+#endif // EFFECT_GLSLLIB
diff --git a/src/Runtime/res/effectlib/evalBakedShadowMap.glsllib b/src/Runtime/res/effectlib/evalBakedShadowMap.glsllib
new file mode 100644
index 00000000..8bbe4036
--- /dev/null
+++ b/src/Runtime/res/effectlib/evalBakedShadowMap.glsllib
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 evalBakedShadowMap( in vec3 inCoords )
+{
+ vec4 shadowCol = (uShadowMappingEnabled) ? texture( uBakedShadowTexture, inCoords.xy ) : vec4( 1.0, 1.0, 1.0, 1.0 );
+
+ return shadowCol;
+}
diff --git a/src/Runtime/res/effectlib/evalEnvironmentMap.glsllib b/src/Runtime/res/effectlib/evalEnvironmentMap.glsllib
new file mode 100644
index 00000000..df62c3b8
--- /dev/null
+++ b/src/Runtime/res/effectlib/evalEnvironmentMap.glsllib
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec3 evalEnvironmentMap( in vec3 R, float roughness )
+{
+ // convert R to spherical texture coordinates
+ vec2 tc = vec2( ( atan( R.x, -R.z ) + PI ) / ( PI_TWO ), acos( -R.y ) / PI );
+
+ vec2 envMapSize = vec2( textureSize( uEnvironmentTexture, 0 ) );
+ float envMapLevels = log2( max( envMapSize.x, envMapSize.y ) );
+
+ // simulate textureQueryLod
+ vec2 dx = dFdx( tc * envMapSize.x );
+ vec2 dy = dFdy( tc * envMapSize.y );
+
+ float px = dot( dx, dx );
+ float py = dot( dy, dy );
+
+ float maxlod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
+ float minlod = 0.5 * log2( min( px, py ) );
+
+ //float lod = max(0.0, maxlod - min( maxlod - minlod, envMapLevels ));
+ float lod = max(0.0, min( minlod, envMapLevels ));
+
+ float roughLevel = mix( lod , envMapLevels, roughness );
+
+ return( textureLod( uEnvironmentTexture, tc, roughLevel ).rgb );
+}
diff --git a/src/Runtime/res/effectlib/evalLightmaps.glsllib b/src/Runtime/res/effectlib/evalLightmaps.glsllib
new file mode 100644
index 00000000..1486cadc
--- /dev/null
+++ b/src/Runtime/res/effectlib/evalLightmaps.glsllib
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 evalLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ vec3 uTransform = vec3(rotScale.x, rotScale.y, offset.x);
+ vec3 vTransform = vec3(rotScale.z, rotScale.w, offset.y);
+
+ vec2 transfCoord = vec2( dot( uTransform, inCoords ), dot( vTransform, inCoords ) );
+
+ vec4 value = texture( sampler, transfCoord.xy);
+
+ return value;
+}
+
+vec4 evalIndirectLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ return evalLightmap( sampler, inCoords, rotScale, offset );
+}
+
+vec4 evalRadiosityLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ return evalLightmap( sampler, inCoords, rotScale, offset );
+}
+
+vec4 evalShadowLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ return evalLightmap( sampler, inCoords, rotScale, offset );
+} \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/fileBumpTexture.glsllib b/src/Runtime/res/effectlib/fileBumpTexture.glsllib
new file mode 100644
index 00000000..ff7c30ec
--- /dev/null
+++ b/src/Runtime/res/effectlib/fileBumpTexture.glsllib
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILE_BUMP_TEXTURE_GLSLLIB
+#define FILE_BUMP_TEXTURE_GLSLLIB
+
+#ifdef UIC_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+// compute a normal based on a heightfield style bump texture
+// example call:
+// fileBumpTexture(bump_texture, bump_amount, mono_average
+// , transformCoordinate(
+// rotationTranslationScale(
+// vec3( 0.000000, 0.000000, 0.000000 )
+// , vec3( 0.000000, 0.000000, 0.000000 )
+// , vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) )
+// , textureCoordinateInfo( texCoord0, tangent, binormal ) )
+// , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 )
+// , wrap_repeat, wrap_repeat, normal );
+
+
+
+vec3 fileBumpTexture( in sampler2D sampler, in float factor, in int bumpSource
+ , in texture_coordinate_info uvw
+ , in vec2 cropU, in vec2 cropV
+ , in int wrapU, in int wrapV, in vec3 normal )
+{
+ vec2 bumpMapSize = vec2( textureSize( sampler, 0 ) );
+ float bumpMapLevels = log2( max( bumpMapSize.x, bumpMapSize.y ) );
+ // simulate textureQueryLod
+ vec2 dx = dFdx( uvw.position.xy * bumpMapSize.x );
+ vec2 dy = dFdy( uvw.position.xy * bumpMapSize.y );
+
+ float px = dot( dx, dx );
+ float py = dot( dy, dy );
+
+ float maxlod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
+ float minlod = 0.5 * log2( min( px, py ) );
+
+ float lod = max(0.0, min( maxlod, bumpMapLevels ));
+
+ // invert factor
+ float invFactor = -factor;
+
+ // currently no lod supported we use 3.3 GL
+ //float lod = textureQueryLod( sampler, uvw.position.xy ).x;
+ vec2 size = mix( vec2( textureSize( sampler, int( floor( lod ) ) ) ), vec2( textureSize( sampler, int( ceil( lod ) ) ) ), fract( lod ) );
+ vec2 unitStep = 1.0f / size;
+
+ // Add an inveres scale to keep the original gradient values
+ // this makes the bumps a lot smoother.
+ // Or we could do it like in iRay and sample always at original size.
+ // But this makes me feel better.
+ vec2 scale = size / bumpMapSize;
+
+ float du = monoChannel( textureLod( sampler, vec2( uvw.position.x + unitStep.x, uvw.position.y ), lod ), bumpSource )
+ - monoChannel( textureLod( sampler, vec2( uvw.position.x, uvw.position.y ), lod ), bumpSource );
+ float dv = monoChannel( textureLod( sampler, vec2( uvw.position.x, uvw.position.y + unitStep.y ), lod ), bumpSource )
+ - monoChannel( textureLod( sampler, vec2( uvw.position.x, uvw.position.y ), lod ), bumpSource );
+
+
+ vec3 n = normalize(vec3(invFactor * scale.x * du, invFactor * scale.x * dv, 1.0));
+ n = n.x*uvw.tangent_u + n.y*uvw.tangent_v + n.z*normal;
+ return normalize(normal + n);
+}
+
+#include "textureCoordinateInfo.glsllib"
+
+//Simpler version built to run from UIC image data
+//In our case, we have already generated the texture coordinate x,y position
+//TODO - figure out if we need to manipulate tangent_u, tangent_v.
+vec3 simplerFileBumpTexture( in sampler2D sampler, in float factor, vec2 texCoord, vec3 tangent, vec3 binormal, vec3 normal )
+{
+ return fileBumpTexture( sampler, factor, mono_average
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), tangent, binormal )
+ , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 )
+ , wrap_repeat, wrap_repeat, normal );
+}
+
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/fileDisplacementTexture.glsllib b/src/Runtime/res/effectlib/fileDisplacementTexture.glsllib
new file mode 100644
index 00000000..21156d68
--- /dev/null
+++ b/src/Runtime/res/effectlib/fileDisplacementTexture.glsllib
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+#define FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+
+#ifdef UIC_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+
+vec3 fileDisplacementTexture( in sampler2D sampler, in float factor, in int displaceSource
+ , in texture_coordinate_info uvw, in vec3 normal, in vec3 pos )
+{
+ // compute displace factor
+ float df = monoChannel( texture( sampler, uvw.position.xy ), displaceSource );
+
+ return( normal * df * factor + pos );
+}
+
+
+//default material path version
+vec3 uicDefaultMaterialFileDisplacementTexture( in sampler2D sampler, in float factor, vec2 texCoord, in vec3 normal, vec3 pos )
+{
+ return fileDisplacementTexture( sampler, factor, mono_luminance
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0) )
+ , normal, pos );
+}
+
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/fileTexture.glsllib b/src/Runtime/res/effectlib/fileTexture.glsllib
new file mode 100644
index 00000000..6b9f6ab8
--- /dev/null
+++ b/src/Runtime/res/effectlib/fileTexture.glsllib
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+texture_return fileTexture( in sampler2D sampler, in vec3 colorOffset, in vec3 colorScale, in int monoSource, in texture_coordinate_info uvw
+ , in vec2 cropU, in vec2 cropV, in int wrapU, in int wrapV, in int gammaMode )
+{
+ vec4 t4 = texture( sampler, uvw.position.xy );
+ vec3 t3 = colorOffset + colorScale * t4.xyz;
+
+ // When we want to operate in linear color space uncomment the lines
+ if ( gammaMode == gamma_srgb )
+ {
+ t3 = pow( t3, vec3( 2.2 ) );
+ }
+
+ texture_return tr;
+ tr.tint = t3;
+ tr.mono = monoChannel( vec4( t3, t4.w ), monoSource );
+ return( tr );
+}
+
diff --git a/src/Runtime/res/effectlib/flakeNoiseBumpTexture.glsllib b/src/Runtime/res/effectlib/flakeNoiseBumpTexture.glsllib
new file mode 100644
index 00000000..6bd5f7e4
--- /dev/null
+++ b/src/Runtime/res/effectlib/flakeNoiseBumpTexture.glsllib
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec3 flakeNoiseBumpTexture( in texture_coordinate_info uvw, in float scale, in float strength, in vec3 normal )
+{
+ vec3 tex = uvw.position / scale;
+ vec3 grad = miNoise( tex ).xyz;
+
+ // displace coordinate according to noise value
+ tex += 2.0f * grad;
+
+ // then use only integer coordinates, to make flakes transients harder and not wobbly
+ grad = miNoise( round( tex ) ).xyz;
+
+ vec3 n = normalize(vec3(strength * grad.x, strength * grad.y, 1.0));
+ n = n.x*uvw.tangent_u + n.y*uvw.tangent_v + n.z*normal;
+ return normalize(normal + n);
+}
+
diff --git a/src/Runtime/res/effectlib/flakeNoiseTexture.glsllib b/src/Runtime/res/effectlib/flakeNoiseTexture.glsllib
new file mode 100644
index 00000000..219b2950
--- /dev/null
+++ b/src/Runtime/res/effectlib/flakeNoiseTexture.glsllib
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+texture_return flakeNoiseTexture( in texture_coordinate_info uvw, in float intensity, in float scale, in float density )
+{
+ vec3 tex = uvw.position / scale;
+ vec3 grad = miNoise( tex ).xyz;
+
+ // displace coordinate according to noise value
+ tex += 2.0f * grad;
+
+ // then use only integer coordinates, to make flakes transients harder and not wobbly
+ vec4 noise = miNoise( floor( tex ) );
+ float s = pow( noise.w, 1.0f / density ) * intensity;
+
+ texture_return tr;
+ tr.tint = vec3( noise.x, noise.y, noise.z );
+ tr.mono = clamp(s, 0.0, 1.0);
+ return( tr );
+}
+
+
+texture_return flakeNoiseAndBumpTexture( in texture_coordinate_info uvw, in float scale, in float intensity, in float density, float strength, in vec3 normal )
+{
+ vec3 tex = uvw.position / scale;
+ vec3 grad = miNoise( tex ).xyz;
+
+ // displace coordinate according to noise value
+ tex += 2.0f * grad;
+
+ // then use only integer coordinates, to make flakes transients harder and not wobbly
+ vec4 noise = miNoise( round( tex ) );
+ float s = pow( noise.w, 1.0f / density ) * intensity;
+
+ texture_return tr;
+ tr.tint = normalize( normal/strength + ( uvw.tangent_u * grad.x + uvw.tangent_v * grad.y + normal * abs( grad.z ) ) );
+ tr.mono = s;
+ return( tr );
+}
diff --git a/src/Runtime/res/effectlib/fresnelLayer.glsllib b/src/Runtime/res/effectlib/fresnelLayer.glsllib
new file mode 100644
index 00000000..123c38b5
--- /dev/null
+++ b/src/Runtime/res/effectlib/fresnelLayer.glsllib
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+float simpleFresnel( in vec3 N, in float ior, float fresnelPower )
+{
+ float F = ((1.0-ior) * (1.0-ior)) / ((1.0+ior) * (1.0+ior));
+ float fresnelGlancingAngle = clamp( 1.0 - dot(viewDir, N), 0.0, 1.0 );
+ float ratio = F + (1.0 - F) * pow(fresnelGlancingAngle, fresnelPower);
+
+ return ratio;
+}
+
+// PKC : A variation on the simple Schlick approach that also handles the characteristic
+// "dip" that metals exhibit. The dip is very mild or virtually nonexisting in dielectrics,
+// but shows up in metals because of their strong incident reflectivity, and also allows for
+// colored metals like gold or copper to show their Fresnel hue shift as well because certain
+// components will have different baseline responses.
+vec3 pseudoFresnel( in vec3 N, in vec3 ior, float fresnelPower )
+{
+ vec3 F0 = ((vec3(1.0)-ior) * (vec3(1.0)-ior)) / ((vec3(1.0)+ior) * (vec3(1.0)+ior));
+
+ float fresnelGlancingAngle = clamp( 1.0 - dot(viewDir, N), 0.0, 1.0 );
+
+ float fresCurve = pow(fresnelGlancingAngle, fresnelPower);
+ vec3 dipCurve = F0 * sin( 3.1415926535 * fresCurve ) * 0.31830988618;
+
+ vec3 retCol = (vec3(1.0) - F0) * fresCurve;
+ retCol += F0 - dipCurve;
+ return clamp(retCol, 0.0, 1.0);
+}
+
+// look here: http://en.wikipedia.org/wiki/Fresnel_equations
+float fresnel( in float eta1, in float eta2, in float cosTheta1 )
+{
+ float etaInv = eta1 / eta2;
+ float cosTheta2 = 1.0f - ( 1.0f - cosTheta1 * cosTheta1 ) * ( etaInv * etaInv );
+ if ( 0.0f <= cosTheta2 )
+ {
+ cosTheta2 = sqrt( cosTheta2 );
+ float n1t1 = eta1 * cosTheta1;
+ float n1t2 = eta1 * cosTheta2;
+ float n2t1 = eta2 * cosTheta1;
+ float n2t2 = eta2 * cosTheta2;
+ float rs = ( n1t1 - n2t2 ) / ( n1t1 + n2t2 );
+ float rp = ( n1t2 - n2t1 ) / ( n1t2 + n2t1 );
+ float f = 0.5f * ( rs * rs + rp * rp );
+ return( clamp( f, 0.0, 1.0 ) );
+ }
+ else
+ {
+ return( 1.0f );
+ }
+}
+
+// we assume, light rays run through air with ior == 1.0f
+// with eta = eta2 / eta1, we have
+// - when hitting a front face: eta2 == ior, eta1 == 1.0f => eta = ior
+// - when hitting a back face : eta2 == 1.0f, eta1 == ior => eta = 1.0f / ior
+vec3 fresnel( in vec3 N, in vec3 ior )
+{
+ float cosTheta1 = dot( N, viewDir );
+ if ( gl_FrontFacing )
+ {
+ return( vec3( fresnel( 1.0f, ior[0], cosTheta1 ), fresnel( 1.0f, ior[1], cosTheta1 ), fresnel( 1.0f, ior[2], cosTheta1 ) ) );
+ }
+ else
+ {
+ return( vec3( fresnel( ior[0], 1.0f, cosTheta1 ), fresnel( ior[1], 1.0f, cosTheta1 ), fresnel( ior[2], 1.0f, cosTheta1 ) ) );
+ }
+}
+
+vec4 fresnelLayer( in vec3 N, in vec3 ior, in float weight, in vec3 layercolor, in vec4 layer, in vec4 base, in float alpha )
+{
+ vec3 refl = reflect( -viewDir, N );
+ float reflWt = clamp( dot( surfNormal, refl ) + 1.0, 0.0, 1.0 );
+
+ vec3 fresColor = reflWt * weight * layercolor * pseudoFresnel( N, ior, 5.0 );
+
+ return( vec4( mix( base.rgb, layer.rgb, fresColor ), mix(alpha, 1.0, luminance(fresColor)) ) );
+}
+
diff --git a/src/Runtime/res/effectlib/funcareaLightVars.glsllib b/src/Runtime/res/effectlib/funcareaLightVars.glsllib
new file mode 100644
index 00000000..7505b348
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcareaLightVars.glsllib
@@ -0,0 +1,32 @@
+#define MAX_AREA_LIGHTS 16
+
+// note this struct must exactly match the memory layout of the
+// struct SLightSourceShader in the source code. If you make changes here you need
+// to adjust the struct SLightSourceShader as well
+struct AreaLight
+{
+ vec4 position;
+ vec4 direction; // Specifies the light direction in world coordinates.
+ vec4 up;
+ vec4 right;
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ float spotExponent; // Specifies the intensity distribution of the light.
+ float spotCutoff; // Specifies the maximum spread angle of the light.
+ float constantAttenuation; // Specifies the constant light attenuation factor.
+ float linearAttenuation; // Specifies the linear light attenuation factor.
+ float quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ float range; // Specifies the maximum distance of the light influence
+ float width; // Specifies the width of the area light surface.
+ float height; // Specifies the height of the area light surface;
+ vec4 shadowControls;
+ mat4 shadowView;
+ int shadowIdx;
+};
+
+layout (std140) uniform cbBufferAreaLights
+{
+ int uNumAreaLights;
+ AreaLight arealights[MAX_AREA_LIGHTS];
+};
diff --git a/src/Runtime/res/effectlib/funccalculateDiffuseAreaOld.glsllib b/src/Runtime/res/effectlib/funccalculateDiffuseAreaOld.glsllib
new file mode 100644
index 00000000..fc37390c
--- /dev/null
+++ b/src/Runtime/res/effectlib/funccalculateDiffuseAreaOld.glsllib
@@ -0,0 +1,29 @@
+float calculateDiffuseAreaOld(in vec3 lightDir, in vec3 lightPos, in vec4 lightUp,
+ in vec4 lightRt, in vec3 worldPos, out vec3 outDir)
+{
+ if ( dot( worldPos-lightPos, lightDir) < 0.0 )
+ return 0.0;
+
+ vec3 v0 = lightPos - (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v1 = lightPos - (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v2 = lightPos + (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v3 = lightPos + (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ v0 = normalize( v0 - worldPos ); v1 = normalize( v1 - worldPos );
+ v2 = normalize( v2 - worldPos ); v3 = normalize( v3 - worldPos );
+
+ float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
+ float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
+ float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
+ float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );
+
+ outDir = vec3( 0.0 );
+ outDir -= normalize(cross( v0, v1 )) * a01;
+ outDir -= normalize(cross( v1, v2 )) * a12;
+ outDir -= normalize(cross( v2, v3 )) * a23;
+ outDir -= normalize(cross( v3, v0 )) * a30;
+
+ float retVal = length(outDir) * 0.15915494309; // solid angle / 2*pi
+ outDir = normalize(outDir);
+ retVal *= clamp( dot( worldPos-lightPos, lightDir), 0.0, 1.0 );
+ return retVal;
+}
diff --git a/src/Runtime/res/effectlib/funccalculatePointLightAttenuation.glsllib b/src/Runtime/res/effectlib/funccalculatePointLightAttenuation.glsllib
new file mode 100644
index 00000000..5f421622
--- /dev/null
+++ b/src/Runtime/res/effectlib/funccalculatePointLightAttenuation.glsllib
@@ -0,0 +1,4 @@
+float calculatePointLightAttenuation(vec3 attenuationConstants, float lightDistance ) {
+ return 1.0 / (attenuationConstants.x + attenuationConstants.y * lightDistance
+ + attenuationConstants.z * lightDistance * lightDistance);
+}
diff --git a/src/Runtime/res/effectlib/funccomputeMicroHit.glsllib b/src/Runtime/res/effectlib/funccomputeMicroHit.glsllib
new file mode 100644
index 00000000..7c526916
--- /dev/null
+++ b/src/Runtime/res/effectlib/funccomputeMicroHit.glsllib
@@ -0,0 +1,50 @@
+bool rayToLightUV( in vec3 pos, in mat3 lightFrame, in vec3 lightPos, in float width, in float height, in vec3 rayDir, out vec2 uv )
+{
+ float d0 = dot( lightPos, lightFrame[2] );
+ float d1 = dot( pos, lightFrame[2] );
+ float fac = dot( rayDir, lightFrame[2] );
+
+ if ((d0 < d1) || ( fac < 0.001 ))
+ {
+ uv = vec2(-1.0);
+ return false;
+ }
+
+ float t = (d0 - d1) / fac;
+ vec3 hitPos = pos + t * rayDir;
+ width *= dot(lightFrame[0], lightFrame[0]);
+ height *= dot(lightFrame[1], lightFrame[1]);
+
+ hitPos -= lightPos;
+ uv.x = ( dot(hitPos, lightFrame[0]) / width ) + 0.5;
+ uv.y = ( dot(hitPos, lightFrame[1]) / height ) + 0.5;
+ return true;
+}
+
+float computeMicroHit( in vec3 pos, in mat3 tanFrame, in vec3 lightPos, in mat3 lightFrame, in float width, in float height, in vec3 viewDir, out vec2 UV[5] )
+{
+ vec3 rayDir = reflect( -viewDir, tanFrame[2] );
+ vec2 ctrUV;
+ bool isHit = rayToLightUV( pos, lightFrame, lightPos, width, height, rayDir, ctrUV );
+ if ((!isHit) || ( dot(rayDir, tanFrame[2]) < 0.001 )) { return 0.0; }
+
+ vec3 H0 = 0.99749686716 * tanFrame[2] + 0.005 * tanFrame[0];
+ vec3 H1 = 0.99749686716 * tanFrame[2] - 0.005 * tanFrame[0];
+ vec3 H2 = 0.99749686716 * tanFrame[2] + 0.005 * tanFrame[1];
+ vec3 H3 = 0.99749686716 * tanFrame[2] - 0.005 * tanFrame[1];
+
+ vec3 R[4];
+ R[0] = reflect( -viewDir, H0 );
+ R[1] = reflect( -viewDir, H1 );
+ R[2] = reflect( -viewDir, H2 );
+ R[3] = reflect( -viewDir, H3 );
+
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[0], UV[0] );
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[1], UV[1] );
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[2], UV[2] );
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[3], UV[3] );
+
+ UV[4] = ctrUV;
+
+ return clamp( dot(rayDir, tanFrame[2]), 0.0, 1.0 );
+}
diff --git a/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib b/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib
new file mode 100644
index 00000000..250056af
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcdiffuseReflectionBSDF.glsllib
@@ -0,0 +1,43 @@
+#ifndef PI
+#define PI 3.14159265358979f
+#define PI_SQUARE ( PI * PI )
+#endif
+
+vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 viewDir,
+ in vec3 lightDiffuse, in float roughness)
+{
+ float cosThetaI = max( 0.0f, dot( N, L ) );
+ float factor = cosThetaI;
+ if ( ( 0.0f < factor ) && ( 0.0f < roughness ) )
+ {
+ // see http://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model
+ float sigmaSquare = 0.25f * PI_SQUARE * roughness * roughness;
+ float A = 1.0f - 0.5f * sigmaSquare / ( sigmaSquare + 0.33f );
+ float B = 0.45f * sigmaSquare / ( sigmaSquare + 0.09f );
+
+ // project L and viewDir on surface to get the azimuthal angle between them
+ // as we don't really need the projections, but the angle between them,
+ // it's enough to just use the cross instead
+ vec3 pl = normalize( cross( L, N ) );
+ vec3 pv = normalize( cross( viewDir, N ) );
+ float cosPhi = max( 0.0f, dot( pl, pv ) );
+
+ float sinAlpha, tanBeta;
+ float cosThetaO = max( 0.0f, dot( N, viewDir ) );
+ float sinThetaI = sqrt( max( 0.0f, 1.0f - cosThetaI * cosThetaI ) );
+ float sinThetaO = sqrt( max( 0.0f, 1.0f - cosThetaO * cosThetaO ) );
+ if ( cosThetaI < cosThetaO )
+ { // -> thetaO < thetaI
+ sinAlpha = sinThetaI;
+ tanBeta = sinThetaO / cosThetaO;
+ }
+ else
+ {
+ sinAlpha = sinThetaO;
+ tanBeta = sinThetaI / cosThetaI;
+ }
+
+ factor *= A + B * cosPhi * sinAlpha * tanBeta;
+ }
+ return( vec4( factor * lightDiffuse, 1.0f ) );
+}
diff --git a/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib b/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib
new file mode 100644
index 00000000..3b8f2d9f
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib
@@ -0,0 +1,5 @@
+vec4 diffuseReflectionWrapBSDF(vec3 normalDir, in vec3 L, in vec3 lightDiffuse, float wrap)
+{
+ float I = max( 0.0, ((dot(L, normalDir) + wrap)/ (1.0 + wrap)) ); //diffuseIntensity
+ return vec4( I * lightDiffuse, 1.0f );
+}
diff --git a/src/Runtime/res/effectlib/funcgetTransformedUVCoords.glsllib b/src/Runtime/res/effectlib/funcgetTransformedUVCoords.glsllib
new file mode 100644
index 00000000..9b14a284
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcgetTransformedUVCoords.glsllib
@@ -0,0 +1,4 @@
+vec2 getTransformedUVCoords( vec3 inCoords, vec3 inUTransform, vec3 inVTransform )
+{
+ return vec2( dot( inUTransform, inCoords ), dot( inVTransform, inCoords ) );
+}
diff --git a/src/Runtime/res/effectlib/funcsampleAreaGlossyDefault.glsllib b/src/Runtime/res/effectlib/funcsampleAreaGlossyDefault.glsllib
new file mode 100644
index 00000000..cb9cba11
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcsampleAreaGlossyDefault.glsllib
@@ -0,0 +1,42 @@
+#include "funccomputeMicroHit.glsllib"
+
+vec3 sampleAreaGlossyDefault( in mat3 tanFrame, in vec3 pos, in mat3 lightFrame, in vec3 lightPos, in float width, in float height, in vec3 viewDir, in float roughU, in float roughV )
+{
+ float sigmaU = clamp( 0.5 * roughU, 0.005, 0.5 );
+ float sigmaV = clamp( 0.5 * roughV, 0.005, 0.5 );
+ vec2 UVset[5];
+
+ float thetaI = acos( dot(viewDir, lightFrame[2]) );
+ vec2 minMaxThetaH = vec2( (thetaI - 1.5707) * 0.5,
+ (thetaI + 1.5707) * 0.5 );
+ vec4 sinCosThetaH = vec4( abs(sin(minMaxThetaH)), abs(cos(minMaxThetaH)) );
+
+ // First thing we do is compute a small-scale version of the ray hit for a very tiny roughness
+ // then we scale that up based on the _actual_ roughness.
+ float wt = computeMicroHit( pos, tanFrame, lightPos, lightFrame, width, height, viewDir, UVset );
+
+ UVset[0] -= UVset[4]; UVset[1] -= UVset[4];
+ UVset[2] -= UVset[4]; UVset[3] -= UVset[4];
+
+ UVset[0] *= mix(1.0, sinCosThetaH.y / 0.005, sigmaU); UVset[1] *= mix(1.0, sinCosThetaH.x / 0.005, sigmaU);
+ UVset[2] *= mix(1.0, sinCosThetaH.y / 0.005, sigmaV); UVset[3] *= mix(1.0, sinCosThetaH.x / 0.005, sigmaV);
+
+ UVset[0] += UVset[4]; UVset[1] += UVset[4];
+ UVset[2] += UVset[4]; UVset[3] += UVset[4];
+
+ vec2 UVmin = UVset[4], UVmax = UVset[4];
+ vec2 cminUV, cmaxUV;
+ UVmin = min(UVmin, UVset[0]); UVmax = max(UVmax, UVset[0]);
+ UVmin = min(UVmin, UVset[1]); UVmax = max(UVmax, UVset[1]);
+ UVmin = min(UVmin, UVset[2]); UVmax = max(UVmax, UVset[2]);
+ UVmin = min(UVmin, UVset[3]); UVmax = max(UVmax, UVset[3]);
+
+ cminUV = clamp( UVmin, vec2(0.0), vec2(1.0) );
+ cmaxUV = clamp( UVmax, vec2(0.0), vec2(1.0) );
+
+ vec2 hitScale = (cmaxUV - cminUV);
+ vec2 fullScale = (UVmax - UVmin);
+ float intensity = ( hitScale.x * hitScale.y ) / max( fullScale.x * fullScale.y, 0.0001 );
+
+ return vec3( wt * intensity );
+}
diff --git a/src/Runtime/res/effectlib/funcsampleLightVars.glsllib b/src/Runtime/res/effectlib/funcsampleLightVars.glsllib
new file mode 100644
index 00000000..85ca1448
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcsampleLightVars.glsllib
@@ -0,0 +1,29 @@
+#define MAX_NUM_LIGHTS 16
+
+struct LightSource
+{
+ vec4 position;
+ vec4 direction; // Specifies the light direction in world coordinates.
+ vec4 up;
+ vec4 right;
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ float spotExponent; // Specifies the intensity distribution of the light.
+ float spotCutoff; // Specifies the maximum spread angle of the light.
+ float constantAttenuation; // Specifies the constant light attenuation factor.
+ float linearAttenuation; // Specifies the linear light attenuation factor.
+ float quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ float range; // Specifies the maximum distance of the light influence
+ float width; // Specifies the width of the area light surface.
+ float height; // Specifies the height of the area light surface;
+ vec4 shadowControls;
+ mat4 shadowView;
+ int shadowIdx;
+};
+
+layout (std140) uniform cbBufferLights
+{
+ int uNumLights;
+ LightSource lights[MAX_NUM_LIGHTS];
+};
diff --git a/src/Runtime/res/effectlib/funcspecularBSDF.glsllib b/src/Runtime/res/effectlib/funcspecularBSDF.glsllib
new file mode 100644
index 00000000..44e81966
--- /dev/null
+++ b/src/Runtime/res/effectlib/funcspecularBSDF.glsllib
@@ -0,0 +1,42 @@
+#include "luminance.glsllib"
+
+#ifndef scatter_reflect
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#endif
+
+vec4 specularBSDF(in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightSpecular,
+ in float ior, in float shininess, in vec3 tint, int mode)
+{
+ vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ float cosTheta = dot( N, L );
+ if ( 0.0f < cosTheta )
+ {
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ vec3 R = reflect( -L, N );
+ float cosAlpha = max( 0.0f, dot( R, viewDir ) );
+ float shine = pow( cosAlpha, shininess );
+ rgba.rgb = shine * lightSpecular;
+ }
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ // check against total reflection
+ vec3 R = refract( -viewDir, N, ior );
+ if ( R == vec3( 0.0f, 0.0f, 0.0f ) )
+ {
+ rgba.a = 1.0f;
+ }
+ else if ( mode == scatter_transmit )
+ {
+ rgba.a = 0.0f;
+ }
+ else
+ {
+ rgba.a = 1.0f - luminance( tint );
+ }
+ }
+ return( rgba );
+}
diff --git a/src/Runtime/res/effectlib/gradient3Recolor.glsllib b/src/Runtime/res/effectlib/gradient3Recolor.glsllib
new file mode 100644
index 00000000..18556f3e
--- /dev/null
+++ b/src/Runtime/res/effectlib/gradient3Recolor.glsllib
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+float gradientInterpolate( in int interpolationMode, in float value )
+{
+ switch( interpolationMode )
+ {
+ case gradient_interpolation_linear :
+ return( value );
+ case gradient_interpolation_off :
+ return( 0.0f );
+ case gradient_interpolation_ease_in :
+ return( 1.0f - pow( 1.0f - value, 2.0f/3.0f ) );
+ case gradient_interpolation_ease_out :
+ return( pow( value, 2.0f/3.0f ) );
+ case gradient_interpolation_ease_in_out :
+ return( ( value <= 0.5f )
+ ? 0.5f * pow( 2.0f * value, 2.0f/3.0f )
+ : 0.5f + 0.5f * ( 1.0f - pow( 2.0f * ( 1.0f - value ), 2.0f/3.0f ) ) );
+ default:
+ return( value ); // default is linear
+ }
+}
+
+texture_return gradient3Recolor( in float gradientPositions[3], in vec3 gradientColors[3], in int interpolationModes[3], in int monoSource, in float distortion, in float position )
+{
+ texture_return tr;
+ float pos = position + distortion;
+ if ( pos <= gradientPositions[0] )
+ {
+ tr.tint = gradientColors[0];
+ }
+ else if ( pos >= gradientPositions[2] )
+ {
+ tr.tint = gradientColors[2];
+ }
+ else
+ {
+ int index = ( position < gradientPositions[1] ) ? 0 : 1;
+ float relPos = gradientInterpolate( interpolationModes[index], ( pos - gradientPositions[index] ) / ( gradientPositions[index+1] - gradientPositions[index] ) );
+ tr.tint = mix( gradientColors[index], gradientColors[index+1], relPos );
+ }
+ tr.mono = 0.0f;
+ return( tr );
+}
+
diff --git a/src/Runtime/res/effectlib/gradient3Texture.glsllib b/src/Runtime/res/effectlib/gradient3Texture.glsllib
new file mode 100644
index 00000000..7bd6cec7
--- /dev/null
+++ b/src/Runtime/res/effectlib/gradient3Texture.glsllib
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+texture_return gradient3Texture( in int gradientMode, in float gradientPositions[3], in vec3 gradientColors[3], in int interpolationModes[3], in texture_coordinate_info uvw, in float distortion )
+{
+ float position = gradientGetPosition( gradientMode, uvw.position.xy );
+ return( gradient3Recolor( gradientPositions, gradientColors, interpolationModes, 0, distortion, position ) );
+}
+
diff --git a/src/Runtime/res/effectlib/gradientGetPosition.glsllib b/src/Runtime/res/effectlib/gradientGetPosition.glsllib
new file mode 100644
index 00000000..26b687d6
--- /dev/null
+++ b/src/Runtime/res/effectlib/gradientGetPosition.glsllib
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// calculate the length of the hypotenuse of a right-angle triangle
+float hypot( in float x, in float y )
+{
+ // (sqrt( x * x + y * y )) might over- or underflow
+ // see http://en.wikipedia.org/wiki/Hypot for details
+ x = abs( x );
+ y = abs( y );
+ float t = min( x, y );
+ x = max( x, y );
+ t = t/x;
+ return( x * sqrt( 1.0f + ( t * t ) ) );
+}
+
+float gradientGetPosition( in int gradientMode, in vec2 xy )
+{
+ // clamp to [0,1]
+ vec2 tex = xy - floor( xy );
+
+ switch( gradientMode )
+ {
+ case gradient_linear :
+ return( tex.x );
+ case gradient_squared :
+ return( tex.x * tex.x );
+ case gradient_box :
+ // gradient is based on the distance from the center
+ return( max( abs( tex.x - 0.5f ), abs( tex.y - 0.5f ) ) );
+ case gradient_diagonal :
+ // gradient is based on the distance from the diagonal
+ return( sqrt(2.0f) * abs( tex.x - tex.y ) );
+ case gradient_90_degree :
+ // Need to check
+ return( 0.0f );
+ case gradient_symmetric_90_degree :
+ // Need to check
+ return( 0.0f );
+ case gradient_radial :
+ // Distance from center
+ return( 2.0f * hypot( tex.x - 0.5f, tex.y - 0.5f ) );
+ case gradient_360_degree :
+ // fall through need to check
+ default :
+ return( 0.0f );
+ }
+}
diff --git a/src/Runtime/res/effectlib/luminance.glsllib b/src/Runtime/res/effectlib/luminance.glsllib
new file mode 100644
index 00000000..92648970
--- /dev/null
+++ b/src/Runtime/res/effectlib/luminance.glsllib
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LUMINANCE_GLSLLIB
+#define LUMINANCE_GLSLLIB
+
+// Luma coefficients according to ITU-R Recommendation BT.709 (http://en.wikipedia.org/wiki/Rec._709)
+const vec3 yCoeff_709 = vec3( 0.2126, 0.7152, 0.0722 );
+
+float luminance( in vec3 v )
+{
+ return dot( v, yCoeff_709 );
+}
+
+vec3 RGBToYPbPr( in vec3 v )
+{
+ vec3 ypp;
+ ypp.x = luminance( v );
+ ypp.y = 0.5 * (v.b - ypp.x) / (1.0 - yCoeff_709.b);
+ ypp.z = 0.5 * (v.r - ypp.x) / (1.0 - yCoeff_709.r);
+
+ return ypp;
+}
+
+vec3 YPbPrToRGB( in vec3 v )
+{
+ vec3 outRGB;
+ outRGB.x = dot(vec3(1.0, 0.0, 1.575), v);
+ outRGB.y = dot(vec3(1.0, -0.187, -0.468), v);
+ outRGB.z = dot(vec3(1.0, 1.856, 0.0), v);
+
+ return outRGB;
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/miNoise.glsllib b/src/Runtime/res/effectlib/miNoise.glsllib
new file mode 100644
index 00000000..f2daa814
--- /dev/null
+++ b/src/Runtime/res/effectlib/miNoise.glsllib
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 miNoise( in vec3 xyz )
+{
+ const float div = 1.0f / 256.0f;
+
+ ivec3 itmp = ivec3( xyz );
+ ivec3 ixyz[3] = ivec3[]( itmp & 0xFF, itmp+1 & 0xFF, itmp+2 & 0xFF );
+ vec3 fxyz = xyz - floor( xyz );
+
+ vec3 dux, ux;
+ dux.z = fxyz.x * div;
+ dux.y = div - 2.0f * dux.z;
+ dux.x = dux.z - div;
+ ux.z = 0.5f * fxyz.x * dux.z;
+ ux.y = dux.z + 0.5f * ( div - fxyz.x * dux.z );
+ ux.x = ux.z - dux.z + 0.5f * div;
+
+ vec3 duy, uy;
+ duy.z = fxyz.y;
+ duy.y = 1.0f - 2.0f * duy.z;
+ duy.x = duy.z - 1.0f;
+ uy.z = 0.5f * square( duy.z );
+ uy.y = duy.z + 0.5f - square( duy.z );
+ uy.x = uy.z - duy.z + 0.5f;
+
+ float duz[3] = float[]( fxyz.z - 1.0, 1.0 - 2.0 * fxyz.z, fxyz.z );
+ float uz[3] = float[]( 0.5 * square( fxyz.z ) - fxyz.z + 0.5, fxyz.z + 0.5 - square( fxyz.z ), 0.5 * square( fxyz.z ) );
+
+ int xx = random255X( ixyz[0].x );
+ int yx = random255Y( ixyz[0].y );
+ int zx = random255Z( ixyz[0].z );
+ int xy = random255X( ixyz[1].x );
+ int yy = random255Y( ixyz[1].y );
+ int zy = random255Z( ixyz[1].z );
+
+ int xxxy = xx ^ xy;
+ int yxxy = yx ^ xy;
+ int zxxy = zx ^ xy;
+ int xxyy = xx ^ yy;
+ int yxyy = yx ^ yy;
+ int zxyy = zx ^ yy;
+ int xxzy = xx ^ zy;
+ int yxzy = yx ^ zy;
+ int zxzy = zx ^ zy;
+
+ int ixyzxx = ixyz[0].x ^ ixyz[1].x;
+ int ixyzyx = ixyz[0].y ^ ixyz[1].x;
+ int ixyzzx = ixyz[0].z ^ ixyz[1].x;
+ int ixyzxy = ixyz[0].x ^ ixyz[1].y;
+ int ixyzyy = ixyz[0].y ^ ixyz[1].y;
+ int ixyzzy = ixyz[0].z ^ ixyz[1].y;
+ int ixyzxz = ixyz[0].x ^ ixyz[1].z;
+ int ixyzyz = ixyz[0].y ^ ixyz[1].z;
+ int ixyzzz = ixyz[0].z ^ ixyz[1].z;
+
+
+ vec4 ret = vec4( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ for ( int i=0 ; i<3 ; i++ )
+ {
+ int iz = random255Z( ixyz[2][i] );
+
+ mat3x3 nf = mat3x3( vec3( float( random255W( xxxy ^ iz ^ random255W( ixyzxx ^ ixyz[2][i] ) ) )
+ , float( random255W( yxxy ^ iz ^ random255W( ixyzyx ^ ixyz[2][i] ) ) )
+ , float( random255W( zxxy ^ iz ^ random255W( ixyzzx ^ ixyz[2][i] ) ) ) )
+ , vec3( float( random255W( xxyy ^ iz ^ random255W( ixyzxy ^ ixyz[2][i] ) ) )
+ , float( random255W( yxyy ^ iz ^ random255W( ixyzyy ^ ixyz[2][i] ) ) )
+ , float( random255W( zxyy ^ iz ^ random255W( ixyzzy ^ ixyz[2][i] ) ) ) )
+ , vec3( float( random255W( xxzy ^ iz ^ random255W( ixyzxz ^ ixyz[2][i] ) ) )
+ , float( random255W( yxzy ^ iz ^ random255W( ixyzyz ^ ixyz[2][i] ) ) )
+ , float( random255W( zxzy ^ iz ^ random255W( ixyzzz ^ ixyz[2][i] ) ) ) ) );
+
+ float fxdz = dot( uy, dux * nf );
+ vec3 dy = ux * nf;
+ float dz = dot( uy, dy );
+
+ ret.x += uz[i] * fxdz;
+ ret.y += uz[i] * dot( duy, dy );
+ ret.z += duz[i] * dz;
+ ret.w += uz[i] * dz;
+ }
+ return( ret );
+}
+
diff --git a/src/Runtime/res/effectlib/microfacetBSDF.glsllib b/src/Runtime/res/effectlib/microfacetBSDF.glsllib
new file mode 100644
index 00000000..89951ab4
--- /dev/null
+++ b/src/Runtime/res/effectlib/microfacetBSDF.glsllib
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MICROFACET_BSDF_GLSLLIB
+#define MICROFACET_BSDF_GLSLLIB 1
+
+
+float GtermSchlick( in mat3 tanFrame, in vec3 l, in vec3 v, in float roughness )
+{
+ float NdotV = clamp(dot(tanFrame[2], v), 0.0, 1.0);
+ float NdotL = clamp(dot(tanFrame[2], l), 0.0, 1.0);
+ float k = roughness*roughness*0.79788;
+
+ float G_V = NdotV / (NdotV * (1.0 + k) + k);
+ float G_L = NdotL / (NdotL * (1.0 + k) + k);
+
+ return clamp(( G_V * G_L ), 0.0, 1.0);
+}
+
+float GtermGGX( in mat3 tanFrame, in vec3 l, in vec3 v, in float roughness )
+{
+ float NdotV = clamp(dot(tanFrame[2], v), 0.0, 1.0);
+ float NdotL = clamp(dot(tanFrame[2], l), 0.0, 1.0);
+ float k = clamp(roughness*roughness, 0.00, 1.0);
+
+ float G_V = NdotV + sqrt( (NdotV - NdotV * k) * NdotV + k );
+ float G_L = NdotL + sqrt( (NdotL - NdotL * k) * NdotL + k );
+
+ return clamp( 2.0 / ( G_V * G_L ), 0.0, 1.0);
+}
+
+float DtermGGX( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughness )
+{
+ float m = clamp(roughness, 0.04, 1.0);
+ float m2 = m*m;
+
+ vec3 H = normalize(L + V);
+ float NdotH = clamp(dot( tanFrame[2], H ), 0.0001, 1.0);
+ float NdotH2 = NdotH * NdotH;
+
+ float denom = NdotH2 * (m2 - 1.0) + 1.0;
+ float D = m2 / (PI * denom * denom);
+
+ return max( 0.0, D);
+}
+
+float DtermGGXAniso( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughnessU, float roughnessV )
+{
+ float roughU = clamp(roughnessU, 0.04, 1.0);
+ float roughV = clamp(roughnessV, 0.04, 1.0);
+ vec3 H = normalize(L + V);
+ float NdotH = clamp( dot(tanFrame[2], H), 0.0001, 1.0 );
+ float m = PI * roughU * roughV;
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float x2 = roughU*roughU;
+ float y2 = roughV*roughV;
+
+ float D = (HdotX*HdotX/x2) + (HdotY*HdotY/y2) + (NdotH*NdotH);
+ D = 1.0 / ( m * D * D );
+
+ return max( 0.0, D);
+}
+
+vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ vec3 H = normalize(L + V);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+ float NdotL = dot(tanFrame[2], L);
+
+ if ( NdotL > 0.0 )
+ {
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ // G term
+ //float G = GtermSchlick( tanFrame, L, V, roughness );
+ float G = GtermGGX( tanFrame, L, V, roughness );
+
+ //float D = DtermGGX( tanFrame, L, V, roughness );
+ float D = DtermGGXAniso( tanFrame, L, V, roughnessU, roughnessV );
+ rgba.rgb = G * D * NdotL * lightSpecular;
+ }
+
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+ }
+
+ return rgba;
+}
+
+vec4 microfacetBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+#if !UIC_ENABLE_LIGHT_PROBE
+ if ( uEnvironmentMappingEnabled )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+ rgb = 0.01 * evalEnvironmentMap( R, roughness );
+ rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0f, roughnessU, roughnessV, scatter_reflect ).rgb;
+ }
+#endif
+ return( vec4( rgb, 1.0f ) );
+}
+
+
+// see http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+
+float radicalInverse_VdC( uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+ }
+
+vec2 hammersley2d(uint i, uint N)
+{
+ return vec2(float(i)/float(N), radicalInverse_VdC(i));
+}
+
+vec2 hammersly[4] = vec2[4] (
+ vec2(0.0, 0.0),
+ vec2(0.25, 0.5),
+ vec2(0.5, 0.25),
+ vec2(0.75, 0.75)
+ );
+
+vec3 ImportanceGGX( in mat3 tanFrame, vec2 Xi, float roughness , vec3 N )
+{
+ float a = roughness * roughness;
+ float Phi = 2.0 * PI * Xi.y;
+ float CosTheta = (1.0 - Xi.x);
+ float SinTheta = sqrt( 1.0 - CosTheta * CosTheta );
+
+ vec3 H;
+ H.x = SinTheta * cos( Phi );
+ H.y = SinTheta * sin( Phi );
+ H.z = CosTheta;
+
+ // Tangent to world space
+ return tanFrame[0] * H.x + tanFrame[1] * H.y + tanFrame[2] * H.z;
+}
+
+float DtermGGXAnisoSampled( in mat3 tanFrame, in vec3 H, in float roughnessU, float roughnessV )
+{
+#if (MATERIAL_IS_NON_DIELECTRIC == 1)
+ float roughU = clamp(roughnessU*roughnessU, 0.01, 1.0);
+ float roughV = clamp(roughnessV*roughnessV, 0.01, 1.0);
+#else
+ float roughU = clamp(roughnessU, 0.02, 1.0);
+ float roughV = clamp(roughnessV, 0.02, 1.0);
+#endif
+
+ float NdotH = clamp( dot(tanFrame[2], H), 0.0001, 1.0 );
+ float m = PI * roughU * roughV;
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float x2 = roughU*roughU;
+ float y2 = roughV*roughV;
+
+ float pdf = (HdotX*HdotX/x2) + (HdotY*HdotY/y2) + (NdotH*NdotH);
+ float D = 1.0 / ( m * pdf * pdf );
+
+ return max( 0.0, D);
+}
+
+vec3 sampleEnv(in vec3 L, float pdf, uint sampleCount, float roughness )
+{
+ vec2 envMapSize = vec2( textureSize( uEnvironmentTexture, 0 ) );
+ float envMapLevels = log2( max( envMapSize.x, envMapSize.y ) );
+
+ float a = 0.5*log2( float(envMapSize.x*envMapSize.y) / float(sampleCount) );
+ float d = 4.0 * (abs(L.z) + 1.0) * (abs(L.z) + 1.0);
+ float b = 0.5*log2( pdf * d );
+
+ // convert coord to 2D
+ vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0f * PI ), acos( -L.y ) / PI );
+ float weight = step( 0.0001, roughness );
+
+ float lod = max( 0.0, min( (a - b)*weight, envMapLevels ));
+
+ return( textureLod( uEnvironmentTexture, tc, lod ).rgb );
+}
+
+vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+
+ float roughness = clamp( calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ), 0.0, 1.0 );
+
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+
+ const uint NumSamples = 4u;
+ for( uint i = 0u; i < NumSamples; i++ )
+ {
+ vec2 Xi = hammersly[i]; // pre computed values
+ //vec2 Xi = hammersley2d(i, NumSamples);
+ vec3 Half = ImportanceGGX( tanFrame, Xi, roughness , tanFrame[2] );
+ vec3 H = normalize( Half );
+
+ vec3 L = 2.0 * dot( viewDir, Half ) * Half - viewDir;
+ float NdotV = clamp( dot( tanFrame[2], viewDir ), 0.0001, 1.0 );
+ float NdotR = clamp( dot( tanFrame[2], R ), 0.0, 1.0 );
+ float NdotH = clamp( dot( tanFrame[2], H ), 0.0001, 1.0 );
+
+ if( NdotV > 0.0001 )
+ {
+ float G = GtermGGX( tanFrame, L, viewDir, roughness );
+ float D = DtermGGXAnisoSampled( tanFrame, H, roughnessU, roughnessV);
+
+ vec3 envColor = 0.01 * sampleEnv( L, D, NumSamples, roughness );
+
+ rgb += (envColor * G * D * NdotR) / ( 4.0 * NdotV * NdotH);
+ }
+ }
+
+ rgb /= float(NumSamples);
+
+ return( vec4( rgb, 1.0f ) );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/monoChannel.glsllib b/src/Runtime/res/effectlib/monoChannel.glsllib
new file mode 100644
index 00000000..1ae6d529
--- /dev/null
+++ b/src/Runtime/res/effectlib/monoChannel.glsllib
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MONO_CHANNEL_GLSLLIB
+#define MONO_CHANNEL_GLSLLIB
+
+#ifdef UIC_DEFINE_API
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#endif
+
+float monoChannel( in vec4 t, in int monoSource )
+{
+ switch( monoSource )
+ {
+ case mono_alpha :
+ return( t.w );
+ case mono_average :
+ return( ( t.x + t.y + t.z ) / 3.0f );
+ case mono_luminance :
+ return( luminance( t.xyz ) );
+ case mono_maximum :
+ return( max( t.x, max( t.y, t.z ) ) );
+ default :
+ return( 1.0f );
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/normalizedMix.glsllib b/src/Runtime/res/effectlib/normalizedMix.glsllib
new file mode 100644
index 00000000..7a440224
--- /dev/null
+++ b/src/Runtime/res/effectlib/normalizedMix.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 normalizedMix( in bsdf_component components[1] )
+{
+ return( components[0].component );
+}
+
+vec4 normalizedMix( in bsdf_component components[2] )
+{
+ float sum = components[0].weight + components[1].weight;
+ float invSum = ( sum <= 1.0f ) ? 1.0f : 1.0f / sum;
+ return( invSum * ( components[0].weight * components[0].component + components[1].weight * components[1].component ) );
+}
+
diff --git a/src/Runtime/res/effectlib/perlinNoise.glsllib b/src/Runtime/res/effectlib/perlinNoise.glsllib
new file mode 100644
index 00000000..0445fef6
--- /dev/null
+++ b/src/Runtime/res/effectlib/perlinNoise.glsllib
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// check out implementation from GPU Gems 1 and 2
+
+float fade( in float x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0 - 2.0 * x ) );
+}
+
+vec2 fade( in vec2 x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0 - 2.0 * x ) );
+}
+
+vec3 fade( in vec3 x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0f - 2.0f * x ) );
+}
+
+vec4 fade( in vec4 x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0f - 2.0f * x ) );
+}
+
+float influence( in int hash, in float x )
+{
+ return( x * texelFetch( randomGradient1D, ivec2(hash, 0), 0 ).x );
+}
+
+float influence( in int hash, in float x, in float y )
+{
+ return( dot( vec2( x, y ), texelFetch( randomGradient2D, ivec2(hash, 0), 0 ).xy ) );
+}
+
+float influence( in int hash, in float x, in float y, in float z )
+{
+ return( dot( vec3( x, y, z ), texelFetch( randomGradient3D, ivec2(hash, 0), 0 ).xyz ) );
+}
+
+float influence( in int hash, in float x, in float y, in float z, in float w )
+{
+ return( dot( vec4( x, y, z, w ), texelFetch( randomGradient4D, ivec2(hash, 0), 0 ) ) );
+}
+
+float perlinNoise( in float pos )
+{
+ float floorPos = floor( pos );
+ int intPos = int( floorPos );
+ float fracPos = pos - floorPos;
+
+ return( mix( influence( random255X( intPos ), fracPos ), influence( random255X( intPos+1 ), fracPos - 1.0f ), fade( fracPos ) ) );
+}
+
+float perlinNoise( in vec2 pos )
+{
+ vec2 floorPos = floor( pos );
+ vec2 fracPos = pos - floorPos;
+ vec2 fadedPos = fade( fracPos );
+
+ int ax = random255X( int(floorPos.x) );
+ int bx = random255X( int(floorPos.x) + 1 );
+ int ay = random255Y( int(floorPos.y) );
+ int by = random255Y( int(floorPos.y) + 1 );
+
+ return( mix( mix( influence( ax^ay, fracPos.x, fracPos.y )
+ , influence( bx^ay, fracPos.x - 1.0f, fracPos.y ), fadedPos.x )
+ , mix( influence( ax^by, fracPos.x, fracPos.y - 1.0f )
+ , influence( bx^by, fracPos.x - 1.0f, fracPos.y - 1.0f ), fadedPos.x ), fadedPos.y ) );
+}
+
+float perlinNoise( in vec3 pos )
+{
+ vec3 floorPos = floor( pos );
+ vec3 fracPos = pos - floorPos;
+ vec3 fadedPos = fade( fracPos );
+
+ int ax = random255X( int(floorPos.x) );
+ int bx = random255X( int(floorPos.x) + 1 );
+ int ay = random255Y( int(floorPos.y) );
+ int by = random255Y( int(floorPos.y) + 1 );
+ int az = random255Z( int(floorPos.z) );
+ int bz = random255Z( int(floorPos.z) + 1 );
+
+ int axay = ax ^ ay;
+ int bxay = bx ^ ay;
+ int axby = ax ^ by;
+ int bxby = bx ^ by;
+
+ return( mix( mix( mix( influence( axay^az, fracPos.x, fracPos.y, fracPos.z )
+ , influence( bxay^az, fracPos.x - 1.0f, fracPos.y, fracPos.z ), fadedPos.x )
+ , mix( influence( axby^az, fracPos.x, fracPos.y - 1.0f, fracPos.z )
+ , influence( bxby^az, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z ), fadedPos.x ), fadedPos.y )
+ , mix( mix( influence( axay^bz, fracPos.x, fracPos.y , fracPos.z - 1.0f )
+ , influence( bxay^bz, fracPos.x - 1.0f, fracPos.y , fracPos.z - 1.0f ), fadedPos.x )
+ , mix( influence( axby^bz, fracPos.x, fracPos.y - 1.0f, fracPos.z - 1.0f )
+ , influence( bxby^bz, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z - 1.0f ), fadedPos.x ), fadedPos.y ), fadedPos.z ) );
+}
+
+float perlinNoise( in vec4 pos )
+{
+ vec4 floorPos = floor( pos );
+ vec4 fracPos = pos - floorPos;
+ vec4 fadedPos = fade( fracPos );
+
+ int ax = random255X( int(floorPos.x) );
+ int bx = random255X( int(floorPos.x) + 1 );
+ int ay = random255Y( int(floorPos.y) );
+ int by = random255Y( int(floorPos.y) + 1 );
+ int az = random255Z( int(floorPos.z) );
+ int bz = random255Z( int(floorPos.z) + 1 );
+ int aw = random255W( int(floorPos.w) );
+
+ int axay = ax ^ ay;
+ int bxay = bx ^ ay;
+ int axby = ax ^ by;
+ int bxby = bx ^ by;
+
+ float result[2];
+ for ( int i=0 ; i<2 ; i++ )
+ {
+ int azaw = az ^ aw;
+ int bzaw = bz ^ aw;
+
+ result[i] = mix( mix( mix( influence( axay^azaw, fracPos.x, fracPos.y, fracPos.z, fracPos.w )
+ , influence( bxay^azaw, fracPos.x - 1.0f, fracPos.y, fracPos.z, fracPos.w ), fadedPos.x )
+ , mix( influence( axby^azaw, fracPos.x, fracPos.y - 1.0f, fracPos.z, fracPos.w )
+ , influence( bxby^azaw, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z, fracPos.w ), fadedPos.x ), fadedPos.y )
+ , mix( mix( influence( axay^bzaw, fracPos.x, fracPos.y, fracPos.z - 1.0f, fracPos.w )
+ , influence( bxay^bzaw, fracPos.x - 1.0f, fracPos.y, fracPos.z - 1.0f, fracPos.w ), fadedPos.x )
+ , mix( influence( axby^bzaw, fracPos.x, fracPos.y - 1.0f, fracPos.z - 1.0f, fracPos.w )
+ , influence( bxby^bzaw, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z - 1.0f, fracPos.w ), fadedPos.x ), fadedPos.y ), fadedPos.z );
+ aw = random255W( int(floorPos.w) + 1 );
+ fracPos.w -= 1.0f;
+ }
+ return( mix( result[0], result[1], fadedPos.w ) );
+}
+
+float summedPerlinNoise( in vec3 pos, in int terms, in bool absNoise )
+{
+ float sum = 0.0f;
+ float weight = 1.0f;
+ vec3 p = pos;
+ while ( terms-- != 0 )
+ {
+ float noise = perlinNoise( p );
+ sum += weight * ( absNoise ? abs(noise) : noise );
+ p += p;
+ weight *= 0.5f;
+ }
+ return( sum );
+}
+
+float summedPerlinNoise( in vec4 pos, in int terms, in bool absNoise )
+{
+ float sum = 0.0f;
+ float weight = 1.0f;
+ vec4 p = pos;
+ while ( terms-- != 0 )
+ {
+ float noise = perlinNoise( p );
+ sum += weight * ( absNoise ? abs(noise) : noise );
+ p += p;
+ weight *= 0.5f;
+ }
+ return( sum );
+}
+
+float perlinNoise( in vec3 pos, in float time, in int terms, in vec3 turbulenceWeight, in bool absoluteNoise, in bool applyMarble
+ , in bool applyDent, in float noiseBands, in float noiseThresholdHigh, in float noiseThresholdLow )
+{
+ float noise = ( time == 0.0f ) ? summedPerlinNoise( pos, terms, absoluteNoise ) : summedPerlinNoise( vec4( pos, time ), terms, absoluteNoise );
+ if ( turbulenceWeight != vec3( 0.0f, 0.0f, 0.0f ) )
+ {
+ noise = sin( dot( pos, turbulenceWeight ) + noise );
+ }
+ if ( ! absoluteNoise )
+ {
+ noise = 0.5f * noise + 0.5f; // scale [-1,1] to [0,1]
+ }
+ if ( applyMarble )
+ {
+ noise = cos( pos.x + 5.0f * noise ); // classic Perlin marble function, with magic 5.0f
+ }
+ if ( applyDent )
+ {
+ noise = cube( noise );
+ }
+ if ( noiseBands != 1.0f )
+ {
+ // Create banding/stripes by using the fraction component only
+ noise *= noiseBands;
+ noise -= floor( noise );
+ noise += pow( 1.0f - noise, 20.0f );
+ }
+ if ( noiseThresholdLow < noiseThresholdHigh )
+ {
+ // clamp the noise
+ noise = clamp( ( noise - noiseThresholdLow ) / ( noiseThresholdHigh - noiseThresholdLow ), 0.0f, 1.0f );
+ }
+ return( noise );
+}
+
diff --git a/src/Runtime/res/effectlib/perlinNoiseBumpTexture.glsllib b/src/Runtime/res/effectlib/perlinNoiseBumpTexture.glsllib
new file mode 100644
index 00000000..6e0982f3
--- /dev/null
+++ b/src/Runtime/res/effectlib/perlinNoiseBumpTexture.glsllib
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec3 perlinNoiseBumpTexture( in texture_coordinate_info uvw, in float factor, in float size, in bool applyMarble
+ , in bool applyDent, in float noisePhase, in int noiseLevels, in bool absoluteNoise, in vec3 noiseDistortion
+ , in float noiseThresholdHigh, in float noiseThresholdLow, in float noiseBands, in vec3 normal )
+{
+ float delta = 0.1 / noiseBands;
+ vec3 pos = uvw.position / size;
+
+ float r0 = perlinNoise( pos, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ float r1 = perlinNoise( pos + delta * uvw.tangent_u, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ float r2 = perlinNoise( pos + delta * uvw.tangent_v, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ float r3 = perlinNoise( pos + delta * normal, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+
+ return( normalize( normal - factor * ( ( r1 - r0 ) * uvw.tangent_u + ( r2 - r0 ) * uvw.tangent_v + ( r3 - r0 ) * normal ) ) );
+}
+
diff --git a/src/Runtime/res/effectlib/perlinNoiseTexture.glsllib b/src/Runtime/res/effectlib/perlinNoiseTexture.glsllib
new file mode 100644
index 00000000..d968403e
--- /dev/null
+++ b/src/Runtime/res/effectlib/perlinNoiseTexture.glsllib
@@ -0,0 +1,11 @@
+texture_return perlinNoiseTexture( in texture_coordinate_info uvw, in vec3 color1, in vec3 color2, in float size, in bool applyMarble, in bool applyDent
+ , in float noisePhase, in int noiseLevels, in bool absoluteNoise, in vec3 noiseDistortion
+ , in float noiseThresholdHigh, in float noiseThresholdLow, in float noiseBands )
+{
+ float noise = perlinNoise( uvw.position / size, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ texture_return tr;
+ tr.tint = mix( color1, color2, noise );
+ tr.mono = average( tr.tint );
+ return( tr );
+}
diff --git a/src/Runtime/res/effectlib/physGlossyBSDF.glsllib b/src/Runtime/res/effectlib/physGlossyBSDF.glsllib
new file mode 100644
index 00000000..d94bc26a
--- /dev/null
+++ b/src/Runtime/res/effectlib/physGlossyBSDF.glsllib
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHYS_GLOSSY_BSDF_GLSLLIB
+#define PHYS_GLOSSY_BSDF_GLSLLIB 1
+
+float sqr(float v)
+{
+ return v*v;
+}
+
+float Gterm( float cosTheta, float roughness )
+{
+ float k = roughness * 0.31830988618; // roughness / pi
+ return clamp( ( cosTheta / (cosTheta*(1.0-k) + k) + (1.0 - k*k) ) * 0.5, 0.0, 1.0 );
+}
+
+
+// PKC -- I came up with an anisotropic microfacet BSDF that has some superficial similarity to GGX in
+// its appearance, but is far simpler and more compact in its implementation. It uses a Cauchy-like lobe
+// shape and because it has an analytic solution to its antiderivative, we can compute the integral given
+// the support boundaries. It's also possible to importance sample at perfect efficiency.
+// This is generally a good choice for any material which has a polish coating to it.
+// TODO : The way roughness scales with this BSDF is roughly equivalent to roughness^2 would affect Ward.
+// It's debatable whether we want that to be done as a sqrt here or as square in Ward.
+vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ vec3 H = normalize(L + V);
+
+ // NOTE : This BSDF allows roughness up to 2.0 which allows it
+ // to trend partially into Oren-Nayar diffuse territory, but we should
+ // assume that anything that falls under "glossy" should still be
+ // in the range of 0..1
+ float ax = clamp(roughnessU, 0.0001, 2.0);
+ float ay = clamp(roughnessV, 0.0001, 2.0);
+
+ float NdotL = dot(tanFrame[2], L);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+
+ // if (0.0f < NdotL)
+ // {
+ vec3 Haf = L + V;
+
+ float HdotN = clamp( dot(H, tanFrame[2]), 0.0001, 1.0 );
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float sigma = sqrt(ax * ay);
+ float sigma2 = ax * ay * HdotN;
+
+ float thetaI = acos( dot(V, tanFrame[2]) );
+ float maxThetaI = (thetaI + 1.57079632679) * 0.5;
+ float minThetaI = (thetaI - 1.57079632679) * 0.5;
+ float range = atan(maxThetaI / sigma) - atan(minThetaI / sigma);
+ range = max( range, ax*ay );
+
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float PDF = sigma2 / (sigma2 + sqr(HdotX / ax) + sqr(HdotY / ay));
+ PDF *= dot(Haf, Haf) / (4.71238898038 * sqr(dot(Haf, L)) * ax*ay * sigma * sqr(range));
+
+ rgba.rgb = Gterm(HdotL, sigma) * lightSpecular * PDF * max(NdotL, 0.0);
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+// }
+ return rgba;
+}
+
+vec4 kggxGlossyDefaultMtl( in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V, in vec3 lightSpecular,
+ in vec3 materialSpecular, in float roughU, in float roughV )
+{
+ vec3 bitan = normalize(cross(normal, tangent));
+ mat3 tanFrame = mat3( normalize(cross( bitan, normal) ), bitan, normal );
+ return vec4(materialSpecular, 1.0) * kggxGlossyBSDF( tanFrame, L, V, lightSpecular, 1.5, roughU, roughV, scatter_reflect );
+}
+
+// To be exact, this is not the Ward lobe as Ward originally described (there are a few flaws in
+// the original paper, which had spawned half a dozen corrective measures as papers of their own).
+// This is a Ward-Duer variant with Geisler-Moroder's modified normalization factor which serves
+// to bound the albedo.
+vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ vec3 H = normalize(L + V);
+
+ // specular
+ float ax = clamp(roughnessU, 0.0001, 1.0);
+ float ay = clamp(roughnessV, 0.0001, 1.0);
+
+ float NdotL = dot(tanFrame[2], L);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+
+// if (0.0f < NdotL)
+// {
+ vec3 Haf = L + V;
+
+ float HdotN = clamp( dot(H, tanFrame[2]), 0.0001, 1.0 );
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float exponent = -(sqr(HdotX/ax) + sqr(HdotY/ay));
+ exponent /= sqr(HdotN);
+ float PDF = exp(exponent) / (4.0 * 3.1415926535 * ax * ay);
+ PDF *= 4.0 * dot(Haf, Haf) / sqr(sqr(dot(Haf,tanFrame[2])));
+
+ rgba.rgb = Gterm(HdotL, sqrt(ax * ay)) * lightSpecular * PDF * max(NdotL, 0.0);
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+// }
+ return rgba;
+}
+
+vec4 wardGlossyDefaultMtl( in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V, in vec3 lightSpecular,
+ in vec3 materialSpecular, in float roughU, in float roughV )
+{
+ vec3 bitan = normalize(cross(normal, tangent));
+ mat3 tanFrame = mat3( normalize(cross( bitan, normal) ), bitan, normal );
+ return vec4(materialSpecular, 1.0) * wardGlossyBSDF( tanFrame, L, V, lightSpecular, 1.5, roughU, roughV, scatter_reflect );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/random255.glsllib b/src/Runtime/res/effectlib/random255.glsllib
new file mode 100644
index 00000000..ef586a78
--- /dev/null
+++ b/src/Runtime/res/effectlib/random255.glsllib
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// random [0..255] calculated by some simple Linear Congruential Generator (LCG)
+// Verfied, that each function is just a permutation of {0,...,255}, that is, with 0<=x<=255, each value in [0,255] is returned once
+int random255X( in int x )
+{
+ return( ( ( 8365 * ( x & 0xFF ) + 32285 ) >> 0 ) & 0xFF );
+}
+
+int random255Y( in int x )
+{
+ return( ( ( 3152 * ( x & 0xFF ) + 11819 ) >> 4 ) & 0xFF );
+}
+
+int random255Z( in int x )
+{
+ return( ( ( 119 * ( x & 0xFF ) + 18747 ) >> 0 ) & 0xFF );
+}
+
+int random255W( in int x )
+{
+ return( ( ( 26814 * ( x & 0xFF ) + 9642 ) >> 1 ) & 0xFF );
+}
+
+ivec3 random255XYZ( in ivec3 xyz )
+{
+ return( ivec3( random255X( xyz.x ), random255Y( xyz.y ), random255Z( xyz.z ) ) );
+}
diff --git a/src/Runtime/res/effectlib/refraction.glsllib b/src/Runtime/res/effectlib/refraction.glsllib
new file mode 100644
index 00000000..271ca44f
--- /dev/null
+++ b/src/Runtime/res/effectlib/refraction.glsllib
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// this is entirly phiysical incorrect
+// We just use this to fake distortion when we have no environment available
+// The displacement is calculated on ior
+vec3 refraction( in sampler2D sampler, in float materialIOR )
+{
+ vec3 displace = fresnel( viewDir, vec3( materialIOR ));
+
+ float xdir = abs( viewDir.x );
+ float ydir = abs( viewDir.y );
+
+ vec2 texSize = vec2( textureSize( sampler, 0 ) );
+ vec2 newUV = vec2(gl_FragCoord.xy/texSize);
+ if ( xdir > ydir)
+ {
+ newUV = ( viewDir.x > 0.0) ? newUV + displace.xy : newUV - displace.xy;
+ }
+ else
+ {
+ newUV = ( viewDir.y > 0.0) ? newUV - displace.xy : newUV + displace.xy;
+ }
+
+ vec3 refractColor = texture( sampler, newUV ).rgb;
+
+ return refractColor;
+}
+
+// This should really not be used, but it's there for the sake of testing.
+vec3 refractBlur( in sampler2D sampler, in vec3 viewDir, in float materialIOR, in float blurWidth )
+{
+ // This is really terrible, but at least is a little better than
+ vec3 displace = viewDir * materialIOR;
+
+ vec2 texSize = vec2( textureSize( sampler, 0 ) );
+ texSize = vec2(1.0) / texSize;
+ vec2 newUV = vec2(gl_FragCoord.xy * texSize);
+ newUV += displace.xy * 0.005;
+
+ //vec3 refractColor = texture( sampler, newUV ).rgb;
+ vec3 refractColor = vec3(0);
+ int sz = int(ceil(blurWidth));
+ float wtsum = 0.0;
+
+ for (int y = -sz; y <= sz; ++y)
+ {
+ for (int x = -sz; x <= sz; ++x)
+ {
+ float wt = float(x*x + y*y) / (blurWidth * 0.5);
+ wt = exp2(-wt);
+ //refractColor += wt * textureOffset( sampler, newUV, ivec2(x, y) ).rgb;
+ vec2 uvOfs = vec2(x, y) * texSize;
+ refractColor += wt * texture( sampler, newUV+uvOfs).rgb;
+ wtsum += wt;
+ }
+ }
+
+ return refractColor / wtsum;
+}
diff --git a/src/Runtime/res/effectlib/rotationTranslationScale.glsllib b/src/Runtime/res/effectlib/rotationTranslationScale.glsllib
new file mode 100644
index 00000000..8abc8c9e
--- /dev/null
+++ b/src/Runtime/res/effectlib/rotationTranslationScale.glsllib
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ROTATION_TRANSLATION_SCALE_GLSLLIB
+#define ROTATION_TRANSLATION_SCALE_GLSLLIB
+
+mat4 rotationTranslationScale( in vec3 rotation, in vec3 translation, in vec3 scaling )
+{
+ mat4 st = mat4( scaling.x, 0.0f, 0.0f, 0.0f
+ , 0.0f, scaling.y, 0.0f, 0.0f
+ , 0.0f, 0.0f, scaling.z, 0.0f
+ , translation.x - 0.5f, translation.y - 0.5f, translation.z - 0.5f, 1.0f );
+ vec3 s = sin( rotation );
+ vec3 c = cos( rotation );
+ mat4 r = mat4( c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0f
+ , c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0f
+ , -s.y , s.x * c.y , c.x * c.y , 0.0f
+ , 0.5f , 0.5f , 0.5f , 1.0f );
+ return( st * r );
+}
+
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/sampleArea.glsllib b/src/Runtime/res/effectlib/sampleArea.glsllib
new file mode 100644
index 00000000..d5c2b728
--- /dev/null
+++ b/src/Runtime/res/effectlib/sampleArea.glsllib
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SAMPLE_AREA_GLSLLIB
+#define SAMPLE_AREA_GLSLLIB 1
+
+#include "funcareaLightVars.glsllib"
+#include "funccalculateDiffuseAreaOld.glsllib"
+#include "funcsampleAreaGlossyDefault.glsllib"
+
+float rand1d(vec2 n)
+{
+ return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
+}
+
+vec3 quatRotate( vec4 q, vec3 v )
+{
+ return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz );
+}
+
+vec3 lightUVToRay( in vec3 pos, in vec3 lightPos, in mat3 lightFrame, in float width, in float height, in vec2 uv )
+{
+ width *= dot(lightFrame[0], lightFrame[0]);
+ height *= dot(lightFrame[1], lightFrame[1]);
+
+ vec3 hitPos = lightPos + (uv.x - 0.5) * width * lightFrame[0] + (uv.y - 0.5) * height * lightFrame[1];
+ return normalize(hitPos - pos);
+}
+
+// This is usable only for planar rectangular lights. Will need to break this down into different paths for different shapes.
+float getUVHitBounds( in vec3 pos, in mat3 lightFrame, in vec3 lightPos, in float width, in float height, in vec3 V0, in vec3 V1, in vec3 V2, in vec3 V3, out vec2 UVmin, out vec2 UVmax )
+{
+ float d0 = dot( lightPos, lightFrame[2] );
+ float d1 = dot( pos, lightFrame[2] );
+
+ // If the point is behind the light, it can't be illuminated.
+ if (d0 < d1)
+ {
+ UVmin = vec2( -1.0, -1.0 );
+ UVmax = vec2( -1.0, -1.0 );
+ return 0.0;
+ }
+
+ // Compute where all the rays of the light beam hit the light plane
+ float t[4];
+ vec3 v[4];
+
+ v[0] = V0; v[1] = V1; v[2] = V2; v[3] = V3;
+ t[0] = (d0 - d1) / dot(V0, lightFrame[2]);
+ t[1] = (d0 - d1) / dot(V1, lightFrame[2]);
+ t[2] = (d0 - d1) / dot(V2, lightFrame[2]);
+ t[3] = (d0 - d1) / dot(V3, lightFrame[2]);
+
+ UVmin = vec2(1e6, 1e6);
+ UVmax = vec2(-1e6, -1e6);
+
+ // If any of them are "negative" relative to the ray direction
+ // We don't want to consider them.
+ bool weight[4];
+ float wtsum = 0.0;
+ weight[0] = (t[0] > 0.0);
+ weight[1] = (t[1] > 0.0);
+ weight[2] = (t[2] > 0.0);
+ weight[3] = (t[3] > 0.0);
+
+ width *= dot(lightFrame[0], lightFrame[0]);
+ height *= dot(lightFrame[1], lightFrame[1]);
+
+ for (int i = 0; i < 4; ++i)
+ {
+ vec3 curPos = pos + v[i] * t[i];
+ curPos -= lightPos;
+ vec2 curUV = vec2( dot(curPos, lightFrame[0]) / width, dot(curPos, lightFrame[1]) / height ) + vec2(0.5);
+
+ UVmin = min(UVmin, curUV); UVmax = max(UVmax, curUV);
+ wtsum += weight[i] ? 0.25 : 0.0;
+ }
+
+ return wtsum;
+}
+
+// Shooting a narrow beam, and then scaling up that beam based on the actual roughness
+vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 viewDir, in float roughU, in float roughV )
+{
+ float sigmaU = clamp( 0.5 * roughU, 0.005, 0.5 );
+ float sigmaV = clamp( 0.5 * roughV, 0.005, 0.5 );
+ vec2 UVset[5];
+
+ mat3 lightFrame = mat3( arealights[lightIdx].right.xyz, arealights[lightIdx].up.xyz, arealights[lightIdx].direction.xyz );
+
+ float thetaI = acos( dot(viewDir, lightFrame[2]) );
+ vec2 minMaxThetaH = vec2( (thetaI - 1.5707) * 0.5,
+ (thetaI + 1.5707) * 0.5 );
+ vec4 sinCosThetaH = vec4( abs(sin(minMaxThetaH)), abs(cos(minMaxThetaH)) );
+
+ // First thing we do is compute a small-scale version of the ray hit for a very tiny roughness
+ // then we scale that up based on the _actual_ roughness.
+ float wt = computeMicroHit( pos, tanFrame, arealights[lightIdx].position.xyz, lightFrame,
+ arealights[lightIdx].right.w, arealights[lightIdx].up.w, viewDir, UVset );
+ UVset[0] -= UVset[4]; UVset[1] -= UVset[4];
+ UVset[2] -= UVset[4]; UVset[3] -= UVset[4];
+
+ UVset[0] *= mix(1.0, sinCosThetaH.y / 0.005, sigmaU); UVset[1] *= mix(1.0, sinCosThetaH.x / 0.005, sigmaU);
+ UVset[2] *= mix(1.0, sinCosThetaH.y / 0.005, sigmaV); UVset[3] *= mix(1.0, sinCosThetaH.x / 0.005, sigmaV);
+
+ UVset[0] += UVset[4]; UVset[1] += UVset[4];
+ UVset[2] += UVset[4]; UVset[3] += UVset[4];
+
+ vec2 UVmin = UVset[4], UVmax = UVset[4];
+ vec2 cminUV, cmaxUV;
+ UVmin = min(UVmin, UVset[0]); UVmax = max(UVmax, UVset[0]);
+ UVmin = min(UVmin, UVset[1]); UVmax = max(UVmax, UVset[1]);
+ UVmin = min(UVmin, UVset[2]); UVmax = max(UVmax, UVset[2]);
+ UVmin = min(UVmin, UVset[3]); UVmax = max(UVmax, UVset[3]);
+
+ cminUV = clamp( UVmin, vec2(0.0), vec2(1.0) );
+ cmaxUV = clamp( UVmax, vec2(0.0), vec2(1.0) );
+
+ vec2 hitScale = (cmaxUV - cminUV);
+ vec2 fullScale = (UVmax - UVmin);
+ float intensity = ( hitScale.x * hitScale.y ) / max( fullScale.x * fullScale.y, 0.0001 );
+
+ return vec4( wt * intensity );
+}
+
+vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx )
+{
+ float intensity = 0.0;
+ vec3 finalDir;
+ intensity = calculateDiffuseAreaOld( -arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
+ arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir );
+ intensity *= clamp( dot(finalDir, tanFrame[2]), 0.0, 1.0 );
+ return vec4( intensity );
+}
+
+vec4 sampleAreaDiffuseTransmissive( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec4 transmissiveColor, in float translucentFalloff, float lightWrap )
+{
+ float intensity = 0.0;
+ vec3 finalDir;
+ intensity = calculateDiffuseAreaOld( -arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
+ arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir );
+ intensity *= clamp( dot(finalDir, -tanFrame[2]), 0.0, 1.0 );
+
+ float l = 0.2126f * transmissiveColor.r + 0.7152f * transmissiveColor.g + 0.0722f * transmissiveColor.b;
+
+ float I = max( 0.0, ((dot(finalDir, -tanFrame[2]) + lightWrap)/ (1.0 + lightWrap)) );
+ float translucent_thickness = l * l;
+ float translucent_thickness_exp = exp( translucent_thickness * translucentFalloff) * I;
+
+ return vec4( translucent_thickness_exp * intensity );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/sampleLight.glsllib b/src/Runtime/res/effectlib/sampleLight.glsllib
new file mode 100644
index 00000000..35130305
--- /dev/null
+++ b/src/Runtime/res/effectlib/sampleLight.glsllib
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SAMPLE_LIGHT_GLSLLIB
+#define SAMPLE_LIGHT_GLSLLIB
+
+#define MAX_NUM_SHADOWS 8
+
+#ifndef UIC_ENABLE_SSM
+#define UIC_ENABLE_SSM 0
+#endif
+
+#include "SSAOCustomMaterial.glsllib"
+#if UIC_ENABLE_SSM
+#include "shadowMapping.glsllib"
+#endif
+
+#include "funcsampleLightVars.glsllib"
+
+#if UIC_ENABLE_SSM
+uniform sampler2D shadowMaps[MAX_NUM_SHADOWS];
+uniform samplerCube shadowCubes[MAX_NUM_SHADOWS];
+uniform int uNumShadowMaps;
+uniform int uNumShadowCubes;
+#endif
+
+void sampleLight(in LightSource light,
+ in vec3 pos,
+ out vec3 wi,
+ out vec3 opAmbient,
+ out vec3 opDiffuse,
+ out vec3 opSpecular)
+{
+ float att = 1.0;
+ if (light.position.w == 0.0f) // directional light
+ {
+ wi = normalize(light.position.xyz);
+#if UIC_ENABLE_SSM
+ if ( light.shadowIdx >= 0 )
+ att *= sampleOrthographic( shadowMaps[light.shadowIdx], light.shadowControls, light.shadowView, pos, vec2(1.0, light.shadowControls.z) );
+#endif
+ }
+ else if (light.width > 0.01f && light.height > 0.01f) // area light
+ {
+ // This approach is based on the 1994 Tech Report by James Arvo --
+ // The Irradiance Jacobian for Partially Occluded Polyhedral Sources
+ // The nice thing about this approach is that it extends to arbitrary geometry (if we choose to support it),
+ // and accounts for distance & geometric attenuation automatically.
+ // Downsides -- only really works for diffuse reflection, does not account properly for an area light that
+ // intersects its receiver, in which case it illuminates as if the light source is two-sided Lambertian emitter.
+ vec3 v0 = light.position.xyz - (light.right.xyz * light.width * 0.5) - (light.up.xyz * light.height * 0.5);
+ vec3 v1 = light.position.xyz - (light.right.xyz * light.width * 0.5) + (light.up.xyz * light.height * 0.5);
+ vec3 v2 = light.position.xyz + (light.right.xyz * light.width * 0.5) + (light.up.xyz * light.height * 0.5);
+ vec3 v3 = light.position.xyz + (light.right.xyz * light.width * 0.5) - (light.up.xyz * light.height * 0.5);
+
+ v0 = normalize( v0 - pos ); v1 = normalize( v1 - pos ); v2 = normalize( v2 - pos ); v3 = normalize( v3 - pos );
+
+ float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
+ float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
+ float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
+ float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );
+
+ wi = vec3( 0.0 );
+ wi -= normalize(cross( v0, v1 )) * a01;
+ wi -= normalize(cross( v1, v2 )) * a12;
+ wi -= normalize(cross( v2, v3 )) * a23;
+ wi -= normalize(cross( v3, v0 )) * a30;
+
+ att = length(wi) * 0.15915494309; // solid angle / 2*pi
+ wi = normalize(wi);
+ att *= clamp( dot( pos - light.position.xyz, light.direction.xyz ), 0.0, 1.0 );
+#if UIC_ENABLE_SSM
+ if ( light.shadowIdx >= 0 )
+ att *= sampleCubemap( shadowCubes[light.shadowIdx], light.shadowControls, light.shadowView, light.position.xyz, pos, vec2(1.0, light.shadowControls.z) );
+#endif
+ }
+ else // point or spot light
+ {
+ wi = light.position.xyz - pos;
+ float dist = length(wi);
+ wi = wi / dist; // == normalize(wi);
+ att = 1.0f / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist);
+ /*
+ if (light.spotCutoff < 180.0f) // spot light
+ {
+ float spot = max(0.0f, dot(wi, -light.direction.xyz));
+ att *= (spot >= cos(light.spotCutoff * PI / 180.0f)) ? pow(spot, light.spotExponent) : 0.0f;
+ }
+ */
+#if UIC_ENABLE_SSM
+ if ( light.shadowIdx >= 0 )
+ att *= sampleCubemap( shadowCubes[light.shadowIdx], light.shadowControls, light.shadowView, light.position.xyz, pos, vec2(1.0, light.shadowControls.z) );
+#endif
+ }
+ float shadow = customMaterialShadow( -light.direction.xyz, pos );
+ opAmbient = att * light.ambient.xyz;
+ opDiffuse = att * shadow * light.diffuse.xyz;
+ opSpecular = att * shadow * light.specular.xyz;
+}
+
+#include "sampleArea.glsllib"
+
+#endif
diff --git a/src/Runtime/res/effectlib/sampleProbe.glsllib b/src/Runtime/res/effectlib/sampleProbe.glsllib
new file mode 100644
index 00000000..4ecd416b
--- /dev/null
+++ b/src/Runtime/res/effectlib/sampleProbe.glsllib
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SAMPLE_PROBE_GLSLLIB
+#define SAMPLE_PROBE_GLSLLIB 1
+
+uniform sampler2D light_probe;
+uniform vec4 light_probe_props;
+uniform vec4 light_probe_rotation;
+uniform vec4 light_probe_offset; // light_probe_offset.w = number of mipmaps
+
+#if UIC_ENABLE_LIGHT_PROBE_2
+uniform sampler2D light_probe2;
+uniform vec4 light_probe2_props;
+#endif
+
+#if UIC_ENABLE_IBL_FOV
+uniform vec4 light_probe_opts;
+#endif
+
+float noise1d(vec2 n)
+{
+ return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
+}
+
+mat3 orthoNormalize( in mat3 tanFrame )
+{
+ mat3 outMat;
+ outMat[0] = normalize( cross( tanFrame[1], tanFrame[2] ) );
+ outMat[1] = normalize( cross( tanFrame[2], outMat[0] ) );
+ outMat[2] = tanFrame[2];
+
+ return outMat;
+}
+
+mat3 tangentFrame( vec3 N, vec3 p )
+{
+ // get edge vectors of the pixel triangle
+ vec3 dp1 = dFdx( p );
+ vec3 dp2 = dFdy( p );
+ // Using dPdu and dPdv would be nicer, but the nature of our materials
+ // are not ones with intrinsic UVs, so we can't really go there.
+// vec2 duv1 = dFdx( uv );
+// vec2 duv2 = dFdy( uv );
+
+ // solve the linear system
+ vec3 dp2perp = cross( dp2, N );
+ vec3 dp1perp = cross( N, dp1 );
+// vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
+// vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
+
+ vec3 T = normalize(dp1perp);
+ vec3 B = normalize(dp2perp);
+ return mat3( T , B , N );
+}
+
+vec2 transformSample( vec2 origUV, vec4 probeRot, vec2 probeOfs )
+{
+ vec2 retUV;
+ retUV.x = dot( vec3(origUV, 1.0), vec3(probeRot.xy, probeOfs.x) );
+ retUV.y = dot( vec3(origUV, 1.0), vec3(probeRot.zw, probeOfs.y) );
+ return retUV;
+}
+
+// This is broken out into its own routine so that if we get some other
+// format image than a lat-long, then we can account for that by changing
+// the code here alone.
+vec2 getProbeSampleUV( vec3 smpDir, vec4 probeRot, vec2 probeOfs )
+{
+ vec2 smpUV;
+
+#if UIC_ENABLE_IBL_FOV
+ smpUV.x = (2.0 * atan(-smpDir.z, smpDir.x) + 3.14159265358 ) / light_probe_opts.x;
+ smpUV.y = (2.0 * atan(-smpDir.z, smpDir.y) + 3.14159265358 ) / light_probe_opts.x;
+#else
+ smpUV.x = atan( smpDir.x, -smpDir.z) / 3.14159265359;
+ smpUV.y = 1.0 - (acos(smpDir.y) / 1.57079632679);
+#endif
+ smpUV = transformSample( smpUV.xy * 0.5, probeRot, probeOfs ) + vec2(0.5, 0.5);
+
+ return smpUV;
+}
+
+vec4 getTopLayerSample( vec3 inDir, float lodShift, vec3 lodOffsets )
+{
+#if UIC_ENABLE_LIGHT_PROBE_2
+ if ( light_probe2_props.w < 0.5 )
+ return vec4(0.0, 0.0, 0.0, 0.0);
+
+ vec2 smpUV = getProbeSampleUV( inDir, vec4(1.0, 0.0, 0.0, 1.0), light_probe_props.xy );
+ smpUV.x -= 0.5;
+ smpUV.x *= light_probe2_props.x;
+ smpUV.x += light_probe2_props.y;
+
+ vec4 retVal = 0.4 * textureLod( light_probe2, smpUV , lodShift );
+ retVal += 0.2 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.x );
+ retVal += 0.3 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.y );
+ retVal += 0.1 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.z );
+ return retVal;
+#else
+ return vec4(0.0, 0.0, 0.0, 0.0);
+#endif
+}
+
+vec3 getProbeSample( vec3 smpDir, float lodShift, vec3 normal )
+{
+ vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
+ return textureLod( light_probe, smpUV , lodShift ).xyz;
+}
+
+vec3 getProbeWeightedSample( vec3 smpDir, float lodShift, float roughness, vec3 normal )
+{
+ // This gives us a weighted sum that approximates the total filter support
+ // of the full-blown convolution.
+ vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
+ float wt = 1.0;
+
+#if UIC_ENABLE_IBL_FOV
+ wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.x));
+ wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.y));
+ wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.x));
+ wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.y));
+#endif
+
+ vec3 lodOffsets;
+ lodOffsets.x = mix(-2.0, -0.70710678, roughness);
+ lodOffsets.y = min( 2.0 * smoothstep(0.0, 0.1, roughness), 2.0 - 1.29289 * smoothstep(0.1, 1.0, roughness) );
+ lodOffsets.z = min( 6.0 * smoothstep(0.0, 0.1, roughness), 6.0 - 4.585786 * smoothstep(0.1, 1.0, roughness) );
+
+ ivec2 iSize = textureSize(light_probe, 0);
+ vec3 ddx = dFdx( smpDir ) * float(iSize.x);
+ vec3 ddy = dFdy( smpDir ) * float(iSize.y);
+// vec2 ddxUV = dFdx( smpUV ) * float(iSize.x);
+// vec2 ddyUV = dFdy( smpUV ) * float(iSize.y);
+
+ vec2 deriv;
+ deriv.x = max( dot(ddx, ddx), dot(ddy, ddy) );
+// deriv.y = max( dot(ddxUV, ddxUV), dot(ddyUV, ddyUV) );
+ deriv = clamp( deriv, vec2(1.0), vec2(iSize.x * iSize.y) );
+ vec2 lodBound = 0.5 * log2( deriv ) - vec2(1.0);
+
+// float minLod = 0.5 * (lodBound.x + lodBound.y);
+ float minLod = lodBound.x;
+ float maxLod = log2( max(float(iSize.x), float(iSize.y)) );
+ minLod = clamp( minLod / maxLod, 0.0, 1.0 );
+ minLod *= minLod * maxLod;
+
+ lodShift = max( lodShift, minLod );
+
+ vec3 retVal = 0.4 * textureLod( light_probe, smpUV , lodShift ).xyz;
+ retVal += 0.2 * textureLod( light_probe, smpUV , max(minLod, lodShift+lodOffsets.x) ).xyz;
+ retVal += 0.3 * textureLod( light_probe, smpUV , lodShift+lodOffsets.y ).xyz;
+ retVal += 0.1 * textureLod( light_probe, smpUV , lodShift+lodOffsets.z ).xyz;
+
+#if UIC_ENABLE_LIGHT_PROBE_2
+ vec4 topSmp = getTopLayerSample( smpDir, lodShift, lodOffsets );
+ vec3 tempVal = mix( retVal, topSmp.xyz, topSmp.w );
+ retVal = mix( retVal, tempVal, light_probe2_props.z );
+#endif
+
+ if (light_probe_props.z > -1.0) {
+ float ctr = 0.5 + 0.5 * light_probe_props.z;
+ float vertWt = smoothstep(ctr-roughness*0.25, ctr+roughness*0.25, smpUV.y);
+ float wtScaled = mix(1.0, vertWt, light_probe_props.z + 1.0);
+ retVal *= wtScaled;
+ }
+
+ return retVal * wt;
+}
+
+vec3 getProbeAnisoSample( vec3 smpDir, float roughU, float roughV, mat3 tanFrame )
+{
+ float minRough = min(roughU, roughV);
+ float maxRough = max(roughU, roughV);
+
+ float lodMin = log2( (minRough*3.0 + maxRough)*0.25 ) + (light_probe_offset.w - 2.0);
+
+ float ratio = clamp( maxRough / minRough, 1.01, 27.0);
+ vec2 texSize = vec2( textureSize( light_probe, int(floor( lodMin )) ) );
+ texSize = mix( texSize, texSize * 0.5, fract(lodMin) );
+
+ // Boundary of 1.0..9.0 is just to keep the number of samples to within a
+ // reasonable number of samples in the filter. Similarly, with the clamping
+ // of the ratio to a max of 27.0 is just to prevent the step size in the filter
+ // to be no bigger than 3 texels (beyond which, there are some artifacts at high
+ // roughness, aka low texture res).
+ float stepFig = clamp(floor( ratio ), 1.0, 9.0);
+
+ // numSteps is half the number of samples we need to take, which makes it
+ // the number of steps to take on each side.
+ int numSteps = int( floor(stepFig * 0.5) );
+
+ vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
+ vec4 result = vec4(0.0);
+
+ vec3 smpDirOfs = (maxRough == roughU) ? 0.01 * tanFrame[0] : 0.01 * tanFrame[1];
+ vec2 stepPos = getProbeSampleUV(normalize(smpDir + smpDirOfs), light_probe_rotation, light_probe_offset.xy);
+ vec2 stepNeg = getProbeSampleUV(normalize(smpDir - smpDirOfs), light_probe_rotation, light_probe_offset.xy);
+ stepPos -= smpUV; stepNeg -= smpUV;
+ stepPos *= texSize; stepNeg *= texSize;
+
+ // This ensures that we step along a size that makes sense even if one of the two
+ // sammpling directions wraps around the edges of the IBL texture.
+ smpDirOfs /= min( length(stepPos), length(stepNeg) );
+ smpDirOfs *= ratio / stepFig;
+
+ float sigma = mix(0.0, 2.0, ratio / 27.0);
+ sigma *= sigma;
+
+ float wt = (1.0 / (ratio - 1.0)) + 1.0;
+ result.xyz += wt * getProbeWeightedSample( smpDir, lodMin, minRough, tanFrame[2] );
+ result.w += wt;
+ for (int i = 0; i < numSteps; ++i)
+ {
+ wt = sigma / (sigma + float(i * i));
+ vec2 uv0 = getProbeSampleUV(normalize(smpDir + smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy);
+ vec2 uv1 = getProbeSampleUV(normalize(smpDir - smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy);
+ result.xyz += wt * textureLod( light_probe, uv0 , lodMin ).xyz;
+ result.w += wt;
+ result.xyz += wt * textureLod( light_probe, uv1 , lodMin ).xyz;
+ result.w += wt;
+ }
+
+ result /= result.w;
+ return result.xyz;
+}
+
+vec4 sampleDiffuse( mat3 tanFrame )
+{
+ if ( light_probe_props.w < 0.005 )
+ return vec4( 0.0 );
+
+// if ( light_probe_offset.w > 0.5 )
+// {
+ // The LOD offset comes from the assumption that a full diffuse convolution
+ // has a support of pi/2, which translates into x pixels, and the base 2 log
+ // gives us this LOD... Technically, "x" pixels depends on what the original
+ // texture resolution was, which is why we use light_probe_offset.w, which holds
+ // the number of mip levels the texture has.
+
+ return vec4( light_probe_props.w * getProbeWeightedSample( tanFrame[2], light_probe_offset.w - 2.65149613, 1.0, tanFrame[2] ), 1.0 );
+// }
+
+ /*
+ // PKC -- the code below is for full-blown IBL, which we'll skip for now
+
+ // Hand-calculated Hammersley points for t = 2, n = 33
+ // I exclude the 0,0 first point, hence why n=33 and not 32
+ // Nice thing about 2d Hammersley points is that any subset is
+ // also stratified, so even if I have 1000 points and truncate
+ // anywhere, I'm fine. Each of these represent the y of an xy
+ // while x for the kth point is always (k+1)/n.
+ float kernel[32];
+ kernel[0] = 0.5; kernel[1] = 0.25;
+ kernel[2] = 0.75; kernel[3] = 0.125;
+ kernel[4] = 0.625; kernel[5] = 0.375;
+ kernel[6] = 0.875; kernel[7] = 0.0625;
+ kernel[8] = 0.5625; kernel[9] = 0.3125;
+ kernel[10] = 0.8125; kernel[11] = 0.1875;
+ kernel[12] = 0.6875; kernel[13] = 0.4375;
+ kernel[14] = 0.9375; kernel[15] = 0.03125;
+ kernel[16] = 0.53125; kernel[17] = 0.28125;
+ kernel[18] = 0.78125; kernel[19] = 0.15625;
+ kernel[20] = 0.65625; kernel[21] = 0.40625;
+ kernel[22] = 0.90625; kernel[23] = 0.09375;
+ kernel[24] = 0.59375; kernel[25] = 0.34375;
+ kernel[26] = 0.84375; kernel[27] = 0.28175;
+ kernel[28] = 0.71875; kernel[29] = 0.46875;
+ kernel[30] = 0.96875; kernel[31] = 0.015625;
+
+ float phiShift = noise1d(gl_FragCoord.xy) - 0.5;
+
+ vec3 ret = vec3(0, 0, 0);
+
+ int ct = 24;
+ float step = 25.0;
+
+ // Importance sampling a cosine-weighted distribution. Since this
+ // matches the BSDF exactly, we are just going to assume that the PDF
+ // and the BSDF cancel out in sampling, so we just need to accumulate
+ // texture colors. The noise function puts randomized "twist" into
+ // the sampled directions.
+ for( int i = 0; i < ct; ++i )
+ {
+ vec3 localDir;
+ float phi = 6.28318530718 * (kernel[i] + phiShift);
+ float cosTheta = sqrt( float(i+1) / step);
+ localDir.z = sqrt(1.0 - cosTheta*cosTheta);
+ localDir.x = cos(phi) * cosTheta;
+ localDir.y = sin(phi) * cosTheta;
+ vec3 smpDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
+
+
+ float lodShift = light_probe_offset.w - 2 + log2( 3.1415926535 / (localDir.z * step) );
+ vec3 smpColor = getProbeSample( smpDir, lodShift, tanFrame[2] );
+
+ // The assumption here is that the BSDF and the sampling PDF are identical
+ // so they cancel out and therefore, we don't need to include it here.
+ ret += smpColor;
+ }
+
+ ret *= aoFactor / 24.0;
+ return ret;
+ */
+}
+
+vec4 sampleDiffuseCustomMaterial( vec3 normal, vec3 worldPos, float aoFactor )
+{
+
+ mat3 tanFrame = tangentFrame( normal, worldPos );
+ return sampleDiffuse( tanFrame );
+}
+
+vec4 sampleGlossyAniso( mat3 tanFrame, vec3 viewDir, float roughU, float roughV )
+{
+ if ( light_probe_props.w < 0.005 )
+ return vec4( 0.0 );
+
+ // PKC : If we do the full IBL sampling, it's useful to square the roughnesses because
+ // it makes the effect of roughness feel more linear in the low end. This isn't necessary
+ // for fast IBL.
+// float sigmaU = clamp(roughU*roughU, 0.0001, 1.0);
+// float sigmaV = clamp(roughV*roughV, 0.0001, 1.0);
+ float sigmaU = smoothstep( 0.0, 1.0, clamp(roughU, 0.0001, 1.0) );
+ float sigmaV = smoothstep( 0.0, 1.0, clamp(roughV, 0.0001, 1.0) );
+ vec3 ret = vec3(0, 0, 0);
+
+// if ( light_probe_offset.w > 0.5 )
+// {
+ vec3 smpDir = reflect( -viewDir, tanFrame[2] );
+ float sigma = sqrt(sigmaU * sigmaV);
+
+ // Compute the Geometric occlusion/self-shadowing term
+ float NdotL = clamp( dot( smpDir, tanFrame[2] ), 0.0, 0.999995);
+ float k = sigma * 0.31830988618; // roughness / pi
+ float Gl = clamp( (NdotL / (NdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
+
+ vec3 outColor;
+
+ outColor = getProbeAnisoSample( smpDir, sigmaU, sigmaV, tanFrame );
+
+ return vec4( light_probe_props.w * Gl * outColor, 1.0 );
+// }
+
+ // PKC -- the code below is for full-blown IBL, which we'll skip for now
+
+/*
+ float step = clamp( ceil(32.0 * sqrt(max(sigmaU, sigmaV))), 4.0, 32.0 );
+ int actualCt = int(step);
+ float phiShift = noise1d(gl_FragCoord.xy) - 0.5;
+
+ // Hand-calculated Hammersley points for t = 2, n = 33
+ // I exclude the 0,0 first point, hence why n=33 and not 32
+ // Nice thing about 2d Hammersley points is that any subset is
+ // also stratified, so even if I have 1000 points and truncate
+ // anywhere, I'm fine. Each of these represent the y of an xy
+ // while x for the kth point is always (k+1)/n.
+ float kernel[32];
+ kernel[0] = 0.5; kernel[1] = 0.25;
+ kernel[2] = 0.75; kernel[3] = 0.125;
+ kernel[4] = 0.625; kernel[5] = 0.375;
+ kernel[6] = 0.875; kernel[7] = 0.0625;
+ kernel[8] = 0.5625; kernel[9] = 0.3125;
+ kernel[10] = 0.8125; kernel[11] = 0.1875;
+ kernel[12] = 0.6875; kernel[13] = 0.4375;
+ kernel[14] = 0.9375; kernel[15] = 0.03125;
+ kernel[16] = 0.53125; kernel[17] = 0.28125;
+ kernel[18] = 0.78125; kernel[19] = 0.15625;
+ kernel[20] = 0.65625; kernel[21] = 0.40625;
+ kernel[22] = 0.90625; kernel[23] = 0.09375;
+ kernel[24] = 0.59375; kernel[25] = 0.34375;
+ kernel[26] = 0.84375; kernel[27] = 0.28175;
+ kernel[28] = 0.71875; kernel[29] = 0.46875;
+ kernel[30] = 0.96875; kernel[31] = 0.015625;
+
+ float thetaI = acos( dot(viewDir, tanFrame[2]) );
+
+ // NOTE : The model I'm using here is actually based on the KGGX model used in
+ // physGlossyBSDF. This is my own variation on the original GGX which uses something
+ // closer to a pure Cauchy distribution in tangent space, but also supports anisotropy.
+ for (int i = 0; i < actualCt; ++i)
+ {
+ vec3 localDir;
+
+ float phi = 6.28318530718 * (kernel[i] + phiShift);
+ float u = float(i + 1) / (step + 1.0);
+ float rU = cos(phi) * sigmaU;
+ float rV = sin(phi) * sigmaV;
+ float sigma = sqrt(rU * rU + rV * rV);
+
+ float boundA = atan( ((thetaI - 1.57079632679) * 0.5) / sigma );
+ float boundB = atan( ((thetaI + 1.57079632679) * 0.5) / sigma );
+ float t = (1.0 - u) * boundA + u * boundB;
+ float thetaH = tan( t ) * sigma;
+
+ float cosThetaH = cos( thetaH );
+ float sinThetaH = sin( thetaH );
+ localDir.z = cosThetaH;
+ localDir.y = sin(phi) * sinThetaH;
+ localDir.x = cos(phi) * sinThetaH;
+
+ vec3 halfDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
+ halfDir = normalize(halfDir);
+ vec3 smpDir = reflect( -viewDir, halfDir );
+
+ vec2 scaledXY = localDir.xy / vec2(sigmaU, sigmaV);
+ float PDF = (sigmaU*sigmaV) / (sigmaU*sigmaV + dot(scaledXY, scaledXY));
+ vec3 Haf = smpDir + viewDir; // We need the unnormalized half vecter as well as the normalized one
+ float HdotL = dot(halfDir, smpDir);
+ // normalize the PDF to compute the filter support
+ // This gives us the ideal miplevel at which to sample the texture map.
+ PDF *= dot(Haf, Haf) / (4.0 * dot(Haf, smpDir) * HdotL * sigmaU*sigmaV * (boundB-boundA)*(boundB-boundA));
+
+ // Again assuming that the pdf and BSDF are equivalent -- that's not generally valid,
+ // but it saves a lot of ALU cycles.
+ float lodShift = log2( 512.0 * sigma / PDF );
+
+ float k = sigma * 0.31830988618; // roughness / pi
+ float Gl = clamp( (HdotL / (HdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
+
+ vec3 smpColor = Gl * getProbeSample( smpDir, lodShift, tanFrame[2] );
+ ret += smpColor;
+ }
+ ret /= float(actualCt);
+ return vec4(ret, 1.0);
+*/
+}
+
+vec4 sampleGlossy( mat3 tanFrame, vec3 viewDir, float roughness )
+{
+ return sampleGlossyAniso( tanFrame, viewDir, roughness, roughness );
+}
+
+vec4 sampleGlossyCustomMaterial( vec3 normal, vec3 worldPos, vec3 viewDir, float roughness )
+{
+ mat3 tanFrame = tangentFrame( normal, worldPos );
+ return sampleGlossy( tanFrame, viewDir, roughness );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/screenSpaceAO.glsllib b/src/Runtime/res/effectlib/screenSpaceAO.glsllib
new file mode 100644
index 00000000..bb6cbbe6
--- /dev/null
+++ b/src/Runtime/res/effectlib/screenSpaceAO.glsllib
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCREEN_SPACE_AO_GLSLLIB
+#define SCREEN_SPACE_AO_GLSLLIB 1
+
+#include "depthpass.glsllib"
+
+
+float hashRot(vec2 pos)
+{
+ // Basically an odd-even hash.
+ float px = 2.0 * fract(floor(pos.x) * 0.5);
+ float py = fract(floor(pos.y) * 0.5);
+
+ return px + py;
+}
+
+vec3 quatRotate( vec4 q, vec3 v )
+{
+ return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz );
+}
+
+vec3 getViewSpacePos( sampler2D depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
+{
+ float sampleDepth = getDepthValue( texture(depthSampler, UV), camProps );
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ vec2 scaledUV = (UV * UvToEye.xy) + UvToEye.zw;
+ return vec3(scaledUV * sampleDepth, sampleDepth);
+}
+
+vec2 computeDir( vec2 baseDir, int v )
+{
+ float ang = 3.1415926535 * hashRot( gl_FragCoord.xy ) + float(v - 1);
+ vec2 vX = vec2(cos(ang), sin(ang));
+ vec2 vY = vec2(-sin(ang), cos(ang));
+
+ return vec2( dot(baseDir, vX), dot(baseDir, vY) );
+}
+
+vec2 offsetDir( vec2 baseDir, int v )
+{
+ float ang = float(v - 1);
+ vec2 vX = vec2(cos(ang), sin(ang));
+ vec2 vY = vec2(-sin(ang), cos(ang));
+
+ return vec2( dot(baseDir, vX), dot(baseDir, vY) );
+}
+
+float SSambientOcclusion(sampler2D depthSampler, vec3 viewNorm, vec4 aoParams, vec4 aoParams2, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+{
+ float ret = 0.0;
+
+ vec2 centerUV = gl_FragCoord.xy * aoScreen.zw;
+ vec3 viewPos = getViewSpacePos( depthSampler, camProps, centerUV, UvToEye );
+ viewPos += viewNorm * aoParams.w;
+
+ float screenRadius = aoParams.y * aoScreen.y / viewPos.z;
+ if (screenRadius < 1.0) { return 1.0; }
+
+ vec3 kernel[9];
+
+ // The X and Y are the 2d direction, while the Z is the height of the sphere at that point.
+ // In essence, it normalizes the 3d vector, but we're really interested in the 2D offset.
+ kernel[0] = vec3(-0.1376476, 0.2842022, 0.948832);
+ kernel[1] = vec3(-0.626618, 0.4594115, 0.629516);
+ kernel[2] = vec3(-0.8903138, -0.05865424, 0.451554);
+ kernel[3] = vec3(0.2871419, 0.8511679, 0.439389);
+ kernel[4] = vec3(-0.1525251, -0.3870117, 0.909372);
+ kernel[5] = vec3(0.6978705, -0.2176773, 0.682344);
+ kernel[6] = vec3(0.7343006, 0.3774331, 0.5642);
+ kernel[7] = vec3(0.1408805, -0.88915, 0.4353);
+ kernel[8] = vec3(-0.6642616, -0.543601, 0.5130);
+
+ int radLevels = int(floor(aoParams2.x));
+ float radStep = 1.0 / aoParams2.x;
+
+ for (int j = 1; j <= radLevels; ++j)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ float curRange = aoParams.y * radStep * float(j);
+ float curRadius = curRange * kernel[i].z;
+
+ vec3 smpDir;
+ smpDir.xy = computeDir(kernel[i].xy, j) * aoParams2.y + (1.0 - aoParams2.y) * offsetDir(kernel[i].xy, j);
+ smpDir.z = kernel[i].z;
+ smpDir *= curRange;
+
+ vec2 smpUV = centerUV.xy + smpDir.xy * aoScreen.zw;
+
+ // First method is based on Horizon-Based AO
+ vec3 samplePos = getViewSpacePos( depthSampler, camProps, smpUV, UvToEye );
+ vec3 smpVec = samplePos - viewPos;
+
+ float lenRad = dot(smpVec, smpVec);
+ smpVec = normalize(smpVec);
+ float lenDot = dot(smpVec, viewNorm);
+
+ lenRad /= aoParams.y*aoParams.y;
+ float falloff = smoothstep(8.0, 0.0, (lenRad - 1.0) * 0.125);
+ float occl = 1.0 - clamp(lenDot * falloff, 0.0, 1.0);
+
+ ret += occl * occl;
+ }
+ }
+
+ ret = (ret) / (9.0 * float(radLevels));
+
+ // Blend between soft and hard based on softness param
+ // NOTE : the 0.72974 is actually an gamma-inverted 0.5 (assuming gamma 2.2)
+ // Would not need this if we linearized color instead.
+ float hardCut = (1.0 - aoParams.z) * 0.72974;
+ ret = smoothstep(0.0, 1.0, (ret - hardCut) / (1.0 - hardCut));
+
+ // Blend between full and no occlusion based on strength param
+ ret = aoParams.x * ret + (1.0 - aoParams.x);
+
+ return ret;
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/screenSpaceDO.glsllib b/src/Runtime/res/effectlib/screenSpaceDO.glsllib
new file mode 100644
index 00000000..2a4a6080
--- /dev/null
+++ b/src/Runtime/res/effectlib/screenSpaceDO.glsllib
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCREEN_SPACE_DO_GLSLLIB
+#define SCREEN_SPACE_DO_GLSLLIB 1
+
+#include "depthpass.glsllib"
+
+vec3 getViewSpacePos( sampler2D depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
+{
+ float sampleDepth = getDepthValue( texture(depthSampler, UV), camProps );
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ vec2 scaledUV = (UV * UvToEye.xy) + UvToEye.zw;
+ return vec3(scaledUV * sampleDepth, sampleDepth);
+}
+
+float shadowOcclusion(sampler2D depthSampler, vec3 lightDir, vec3 worldPos, mat4 viewMat, mat4 viewProj, vec4 shadowParams, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+{
+ vec3 viewPos = getViewSpacePos( depthSampler, camProps, ( gl_FragCoord.xy * aoScreen.zw ), UvToEye );
+ float depth = viewPos.z;
+
+ // Get the screen-space UV
+ vec2 centerUV = gl_FragCoord.xy * aoScreen.zw;
+
+ float screenDist = shadowParams.y * 3.1415926535 * aoScreen.y / viewPos.z;
+ if (screenDist < 1.0) { return 1.0; }
+
+ vec3 viewL = normalize( (viewMat * vec4(lightDir, 0)).xyz );
+
+ float steps = min( screenDist, 20.0 );
+ int maxCt = int(steps);
+ float step = 3.1415926535 * shadowParams.y / float(maxCt);
+ float ret = float(maxCt);
+
+ for( int i = 0; i < maxCt; ++i )
+ {
+ vec3 ray = lightDir * step * float(i);
+ vec3 samplePos = worldPos - ray;
+
+ vec4 smpUV = viewProj * vec4(samplePos, 1.0);
+ smpUV /= smpUV.w;
+ smpUV.xy = (smpUV.xy + 1.0) * 0.5;
+
+ vec3 testPos = getViewSpacePos( depthSampler, camProps, smpUV.xy, UvToEye );
+ testPos.z += shadowParams.w;
+ vec3 testVec = normalize(viewPos - testPos);
+ testVec -= viewL;
+ float isBehind = clamp( testVec.z, 0.0, 1.0 );
+ float diff = (testPos.z - depth) / shadowParams.y;
+ ret -= isBehind * (1.0 / (1.0 + diff * diff));
+ }
+
+ ret /= float(maxCt); // divide by number of samples;
+ // Blend between soft and hard based on softness param
+ // NOTE : the 0.72974 is actually an gamma-inverted 0.5 (assuming gamma 2.2)
+ // Would not need this if we linearized color instead.
+ float hardCut = (ret <= 0.72974) ? 0.0 : 1.0;
+ ret = shadowParams.z * ret + (1.0 - shadowParams.z) * hardCut;
+
+ // Blend between full and no occlusion based on strength param
+ ret = shadowParams.x * ret + (1.0 - shadowParams.x);
+
+ return ret;
+}
+
+// For reference
+/*
+float glossyOcclusionBasis(sampler2D depthSampler, mat3 tanFrame, vec3 worldPos, mat4 viewProj, vec3 viewDir, vec4 shadowParams, vec2 camProps, float roughness)
+{
+ float ret = 16.0;
+
+ float kernel[16];
+ kernel[0] = 0.5; kernel[1] = 0.25;
+ kernel[2] = 0.75; kernel[3] = 0.125;
+ kernel[4] = 0.625; kernel[5] = 0.375;
+ kernel[6] = 0.875; kernel[7] = 0.0625;
+ kernel[8] = 0.5625; kernel[9] = 0.3125;
+ kernel[10] = 0.8125; kernel[11] = 0.1875;
+ kernel[12] = 0.6875; kernel[13] = 0.4375;
+ kernel[14] = 0.9375; kernel[15] = 0.03125;
+
+ float rough = clamp(roughness, 0.0001, 1.0);
+ float normFac = 1.0 / (rough);
+
+ float phiShift = hashRot( gl_FragCoord.xy );
+ ivec2 iCoords = ivec2( gl_FragCoord.xy );
+ float depth = getDepthValue( texelFetch(depthSampler, iCoords, 0) );
+ depth = depthValueToLinearDistance( depth, camProps );
+
+ for( int i = 0; i < 16; ++i )
+ {
+ vec3 localDir;
+ float phi = 6.28318530718 * (kernel[i] + phiShift);
+ float cosTheta = sqrt( float(i+1) / 33.0);
+ localDir.z = sqrt(1.0 - cosTheta*cosTheta) * normFac;
+ localDir.x = cos(phi) * cosTheta;
+ localDir.y = sin(phi) * cosTheta;
+
+ localDir = normalize(localDir);
+
+ vec3 halfDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
+ vec3 ray = reflect( -viewDir, halfDir ) * shadowParams.x;
+
+ vec4 samplePos = vec4( worldPos + ray, 1.0 );
+
+ vec4 sampleProj = viewProj * samplePos;
+ sampleProj /= sampleProj.w;
+ sampleProj.xy = (sampleProj.xy + 1.0) * 0.5;
+ float sampleDepth = getDepthValue( texture(depthSampler, sampleProj.xy) );
+
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ // Occlusion is applied based on a Cauchy distribution filter
+ // But with a "dead zone" for the very close samples. By subtracting it from 16,
+ // which represents no occlusion (16/16 = 1), we let nearby occluders have a
+ // lot of effect, but far away occluders do not. Furthermore, the "dead zone"
+ // in the filter means that the extremely near (which we assume to be part of the
+ // same surface) are also excluded to try and limit self-occlusion.
+ float occlDist = 4.0 * max(depth - sampleDepth - shadowParams.y, 0.0) / shadowParams.x;
+ float occlFactor = 1.0 / ( 1.0 + occlDist*occlDist*0.04 );
+ occlFactor -= 1.0 / ( 1.0 + occlDist*occlDist*4.0 );
+ ret -= min(2.0 * occlFactor, 1.0);
+ }
+
+ ret /= 16.0; // divide by number of samples;
+ return ret;
+}
+*/
+
+#endif
diff --git a/src/Runtime/res/effectlib/shadowMapping.glsllib b/src/Runtime/res/effectlib/shadowMapping.glsllib
new file mode 100644
index 00000000..666590e3
--- /dev/null
+++ b/src/Runtime/res/effectlib/shadowMapping.glsllib
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHADOW_MAPPING_GLSLLIB
+#define SHADOW_MAPPING_GLSLLIB
+
+#include "depthpass.glsllib"
+
+float sampleParaboloid( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps, out vec2 smpUV )
+{
+ vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 );
+ vec3 smpCoord = projCoord.xyz / projCoord.w;
+
+ float ptDepth = depthValueToLinearDistance( 1.0 - smpCoord.z, cameraProps );
+ ptDepth = (ptDepth - cameraProps.x) / (cameraProps.y - cameraProps.x);
+ smpCoord = normalize( smpCoord.xyz );
+ smpCoord.xy /= -( smpCoord.z + 1.0 );
+ smpCoord.xy = vec2(1.0) - smpCoord.xy;
+ smpCoord.xy *= 0.5;
+
+ smpUV = smpCoord.xy; // This is just for debug purposes to ensure what the sampled UV cooord is.
+
+ float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x;
+ sampleDepth *= sampleDepth;
+ ptDepth *= ptDepth;
+ float shadowFac = min(1.0, exp(shadowControls.y * sampleDepth * sampleDepth) / exp(shadowControls.y * ptDepth * ptDepth));
+
+ smpUV.xy *= shadowFac;
+ return shadowFac;
+}
+
+float sampleCubemap( in samplerCube shadowCube, in vec4 shadowControls, in mat4 shadowViewMat, in vec3 lightPos, in vec3 worldPos, in vec2 cameraProps )
+{
+ vec3 viewDir = worldPos - vec3(lightPos.x, lightPos.y, lightPos.z);
+ float ptDepth = length(viewDir.xyz);
+ vec4 viewCoord = shadowViewMat * vec4( viewDir.xyz, 0.0 );
+ viewCoord.xyz /= ptDepth;
+ ptDepth = clamp((ptDepth - 1.0) / (cameraProps.y - 1.0), 0.0, 1.0);
+
+ float smpDepth = texture( shadowCube, viewDir.xyz ).x + shadowControls.x;
+
+ float shadowFac = min(1.0, exp(shadowControls.y * smpDepth) / exp(shadowControls.y * ptDepth));
+ return shadowFac;
+}
+
+float sampleOrthographic( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps )
+{
+ vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 );
+ vec3 smpCoord = projCoord.xyz / projCoord.w;
+
+ float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x;
+
+ return min(1.0, exp(shadowControls.y * sampleDepth) / exp(shadowControls.y * smpCoord.z));
+}
+
+
+struct ParaboloidMapResult
+{
+ vec4 m_Position;
+ vec4 m_WorldPos;
+};
+
+ParaboloidMapResult VertexParaboloidDepth(vec3 pos, mat4 inMVP)
+{
+ vec4 glPos = inMVP * vec4( pos, 1.0 );
+ glPos /= glPos.w;
+ glPos.xyz = normalize( glPos.xyz );
+ vec4 world_pos;
+ world_pos.w = glPos.z;
+ glPos.xy /= glPos.z + 1.0;
+ world_pos.xyz = pos.xyz;
+
+ ParaboloidMapResult retval;
+ retval.m_Position = glPos;
+ retval.m_WorldPos = world_pos;
+ return retval;
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/shadowMappingFragment.glsllib b/src/Runtime/res/effectlib/shadowMappingFragment.glsllib
new file mode 100644
index 00000000..514d00e5
--- /dev/null
+++ b/src/Runtime/res/effectlib/shadowMappingFragment.glsllib
@@ -0,0 +1,10 @@
+#include "depthpass.glsllib"
+float FragmentParaboloidDepth( vec4 inWorldPos, mat4 inMVP, vec2 inCameraProperties )
+{
+ if (inWorldPos.w < 0.0)
+ discard;
+ vec4 projVec = inMVP * vec4( inWorldPos.xyz, 1.0 );
+ projVec /= projVec.w;
+ projVec.z = depthValueToLinearDistance( 1.0 - projVec.z, inCameraProperties );
+ return (projVec.z - inCameraProperties.x) / (inCameraProperties.y - inCameraProperties.x);
+}
diff --git a/src/Runtime/res/effectlib/simpleGlossyBSDF.glsllib b/src/Runtime/res/effectlib/simpleGlossyBSDF.glsllib
new file mode 100644
index 00000000..8c6a4632
--- /dev/null
+++ b/src/Runtime/res/effectlib/simpleGlossyBSDF.glsllib
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecular, in float ior
+ , in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+
+ float cosTheta = dot( tanFrame[2], L );
+ if ( 0.0f < cosTheta )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ vec3 R = reflect( -L, tanFrame[2] );
+ float cosine = dot( R, V );
+ float shine = ( 0.0f < cosine ) ? ( ( 0.0f < roughness ) ? pow( cosine, 1.0f / roughness ) : ( 0.9999f <= cosine ) ? 1.0f : 0.0f ) : 0.0f;
+ rgba.rgb = shine * lightSpecular;
+ }
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ // check against total reflection
+ vec3 R = refract( -V, tanFrame[2], ior );
+ if ( R == vec3( 0.0f, 0.0f, 0.0f ) )
+ {
+ rgba.a = 1.0f;
+ }
+ else
+ {
+ rgba.a = 0.0f;
+ }
+ }
+
+ return( rgba );
+}
+
+vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+#if !UIC_ENABLE_LIGHT_PROBE
+ if ( uEnvironmentMappingEnabled )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+ rgb = evalEnvironmentMap( R, roughness );
+ rgb = simpleGlossyBSDF( tanFrame, R, viewDir, rgb, 1.0f, roughnessU, roughnessV, scatter_reflect ).rgb;
+ }
+#endif
+ return( vec4( rgb, 1.0f ) );
+}
+
+// RNM radiosity normal maps
+vec4 glossyRNM( in vec3 N, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+ // we use a fixed basis like Half Life
+ vec3 B0 = vec3( -0.40825, 0.70711, 0.57735);
+ vec3 B1 = vec3( -0.40825, -0.70711, 0.57735);
+ vec3 B2 = vec3( 0.8165, 0.0, 0.57735);
+
+ vec3 dp;
+ dp.x = clamp( dot ( N , B0 ), 0.0, 1.0);
+ dp.y = clamp( dot ( N , B1 ), 0.0, 1.0);
+ dp.z = clamp( dot ( N , B2 ), 0.0, 1.0);
+
+ float sum = 1.0 / dot( dp, vec3(1.0, 1.0, 1.0) );
+ vec3 diffuseLight = dp.x * rnmX + dp.y * rnmY + dp.z * rnmZ;
+ //vec3 diffuseLight = N.x * rnmX + N.y * rnmY + N.z * rnmZ;
+
+ return (vec4(diffuseLight, 1.0) * sum);
+}
diff --git a/src/Runtime/res/effectlib/specularBSDF.glsllib b/src/Runtime/res/effectlib/specularBSDF.glsllib
new file mode 100644
index 00000000..9e315441
--- /dev/null
+++ b/src/Runtime/res/effectlib/specularBSDF.glsllib
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "funcspecularBSDF.glsllib"
+
+#ifndef DEFAULT_MATERIAL_LIGHTING
+
+vec4 specularBSDFEnvironment( in vec3 N, in vec3 viewDir, in vec3 tint, int mode )
+{
+ vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+ if ( uEnvironmentMappingEnabled )
+ {
+ vec3 R = reflect( -viewDir, N );
+ rgb = evalEnvironmentMap( R, 0.0f );
+ rgb = specularBSDF( N, R, viewDir, rgb, 1.0, 256.0, tint, scatter_reflect ).rgb;
+ }
+ return( vec4( rgb, 1.0f ) );
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/spotEdf.glsllib b/src/Runtime/res/effectlib/spotEdf.glsllib
new file mode 100644
index 00000000..defa641d
--- /dev/null
+++ b/src/Runtime/res/effectlib/spotEdf.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+float spotEdf( float exponent )
+{
+ float att = 1.0;
+
+ float dist = length(viewDir);
+ vec3 spotDir = viewDir / dist;
+
+ float spot = max(0.0f, dot(spotDir, normal));
+ att = pow(spot, exponent);
+
+ return att;
+}
diff --git a/src/Runtime/res/effectlib/square.glsllib b/src/Runtime/res/effectlib/square.glsllib
new file mode 100644
index 00000000..96857224
--- /dev/null
+++ b/src/Runtime/res/effectlib/square.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+float square( in float x )
+{
+ return( x * x );
+}
+
diff --git a/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib b/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib
new file mode 100644
index 00000000..853a8601
--- /dev/null
+++ b/src/Runtime/res/effectlib/tangentSpaceNormalTexture.glsllib
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILE_NORMAL_TEXTURE_GLSLLIB
+#define FILE_NORMAL_TEXTURE_GLSLLIB
+
+#ifdef UIC_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+//interpreting the color values of a bitmap as a vector in tangent space
+vec3 tangentSpaceNormalTexture( in sampler2D tex, in float factor, in bool flipTangentU, in bool flipTangentV
+ , in texture_coordinate_info uvw, in vec2 cropU, in vec2 cropV, in int wrapU, in int wrapV )
+{
+ // if we mirror repeat a tangent space texture, tangent space needs to be flipped for every other tile
+ bool flipU = flipTangentU;
+ bool flipV = flipTangentV;
+ if ( wrapU == wrap_mirrored_repeat )
+ {
+ if ( ( ( 0.0f < uvw.position.x ) && ( int( uvw.position.x ) % 2 == 1 ) )
+ || ( ( uvw.position.x < 0.0f ) && ( int( uvw.position.x ) % 2 == 0 ) ) )
+ {
+ flipU = !flipU;
+ }
+ if ( ( ( 0.0f < uvw.position.y ) && ( int( uvw.position.y ) % 2 == 1 ) )
+ || ( ( uvw.position.y < 0.0f ) && ( int( uvw.position.y ) % 2 == 0 ) ) )
+ {
+ flipV = !flipV;
+ }
+ }
+
+ vec3 tangent = 2.0f * texture( tex, uvw.position.xy ).xyz - 1.0f;
+
+ vec3 tangentU = normalize( flipU ? -uvw.tangent_u : uvw.tangent_u );
+ vec3 tangentV = normalize( flipV ? -uvw.tangent_v : uvw.tangent_v );
+ vec3 normal = normalize( cross( tangentU, tangentV ) );
+
+ return( mix( normal, normalize( tangent.x * tangentU - tangent.y * tangentV + tangent.z * normal ), factor ) );
+}
+
+#include "textureCoordinateInfo.glsllib"
+
+//Simpler version built to run from UIC image data
+//In our case, we have already generated the texture coordinate x,y position
+//TODO - figure out if we need to manipulate tangent_u, tangent_v.
+vec3 uicDefaultMaterialFileNormalTexture( in sampler2D sampler, in float factor, vec2 texCoord, vec3 tangent, vec3 binormal )
+{
+ // factor should be in [0,1] range
+ return tangentSpaceNormalTexture( sampler, clamp(factor, 0.0, 1.0), false, false
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), tangent, binormal )
+ , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 )
+ , wrap_repeat, wrap_repeat);
+}
+
+#endif
diff --git a/src/Runtime/res/effectlib/tessellationLinear.glsllib b/src/Runtime/res/effectlib/tessellationLinear.glsllib
new file mode 100644
index 00000000..99035145
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationLinear.glsllib
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_LINEAR_GLSLLIB
+#define TESSELLATION_LINEAR_GLSLLIB
+
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 3) out;
+
+// global setup in main
+vec3 ctWorldPos[3];
+
+uniform vec3 camera_position;
+uniform vec2 distanceRange;
+uniform float disableCulling;
+
+float isBackFace()
+{
+ vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) );
+
+ vec3 ncd = normalize( ctWorldPos[0] - camera_position );
+
+ return sign( dot(faceNormal, ncd) );
+}
+
+float adaptiveCameraFactor( in float minTess, in float maxTess )
+{
+ float distanceValue0 = distance( camera_position, ctWorldPos[0] );
+ float distanceValue1 = distance( camera_position, ctWorldPos[1] );
+ float distanceValue2 = distance( camera_position, ctWorldPos[2] );
+
+ float range = distanceRange[1] - distanceRange[0];
+
+ vec3 edgeDistance;
+ edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range;
+ edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range;
+ edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range;
+
+ edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) );
+
+ //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] );
+ float af = 1.0 - edgeDistance[gl_InvocationID];
+ af = clamp( af*af*maxTess , minTess, maxTess );
+
+ return af;
+}
+
+void tessShader ( in float tessEdge, in float tessInner )
+{
+ float bf = isBackFace();
+ bf = max(disableCulling, bf);
+
+ // adapative tessellation factor
+ float af = adaptiveCameraFactor( tessInner, tessEdge );
+
+ // Calculate the tessellation levels
+ gl_TessLevelInner[0] = af * bf;
+ gl_TessLevelOuter[gl_InvocationID] = af * bf;
+}
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (triangles, equal_spacing, ccw) in;
+
+vec4 tessShader ( )
+{
+ vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+ vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+ vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+ vec4 pos = p0 + p1 + p2;
+ return pos;
+}
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/tessellationLinearCM.glsllib b/src/Runtime/res/effectlib/tessellationLinearCM.glsllib
new file mode 100644
index 00000000..89d9d346
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationLinearCM.glsllib
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_LINEAR_CM_GLSLLIB
+#define TESSELLATION_LINEAR_CM_ GLSLLIB
+
+#include "tessellationLinear.glsllib"
+
+#if TESSELLATION_CONTROL_SHADER
+
+uniform float tessLevelOuter;
+uniform float tessLevelInner;
+
+attribute vec3 varNormal[];
+attribute vec3 varObjPos[];
+
+varying vec3 varNormalTC[];
+varying vec3 varObjPosTC[];
+
+#if UIC_ENABLE_UV0
+attribute vec3 varTexCoord0[];
+varying vec3 varTexCoord0TC[];
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 varTangent[];
+attribute vec3 varObjTangent[];
+varying vec3 varTangentTC[];
+varying vec3 varObjTangentTC[];
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 varBinormal[];
+attribute vec3 varObjBinormal[];
+varying vec3 varBinormalTC[];
+varying vec3 varObjBinormalTC[];
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPos[];
+varying vec3 varWorldPosTC[];
+#endif
+
+void main() {
+
+#if UIC_ENABLE_WORLD_POSITION
+ ctWorldPos[0] = varWorldPos[0];
+ ctWorldPos[1] = varWorldPos[1];
+ ctWorldPos[2] = varWorldPos[2];
+#endif
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ tessShader( tessLevelOuter, tessLevelInner);
+
+ varObjPosTC[gl_InvocationID] = varObjPos[gl_InvocationID];
+ varNormalTC[gl_InvocationID] = varNormal[gl_InvocationID];
+
+#if UIC_ENABLE_UV0
+ varTexCoord0TC[gl_InvocationID] = varTexCoord0[gl_InvocationID];
+#endif
+#if UIC_ENABLE_TEXTAN
+ varTangentTC[gl_InvocationID] = varTangent[gl_InvocationID];
+ varObjTangentTC[gl_InvocationID] = varObjTangent[gl_InvocationID];
+#endif
+#if UIC_ENABLE_BINORMAL
+ varBinormalTC[gl_InvocationID] = varBinormal[gl_InvocationID];
+ varObjBinormalTC[gl_InvocationID] = varObjBinormal[gl_InvocationID];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ varWorldPosTC[gl_InvocationID] = varWorldPos[gl_InvocationID];
+#endif
+}
+
+#endif
+
+
+#if TESSELLATION_EVALUATION_SHADER
+
+#if (GEOMETRY_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName
+#endif
+
+uniform mat3 normal_matrix;
+uniform mat4 model_view_projection_matrix;
+
+attribute vec3 varNormalTC[];
+attribute vec3 varObjPosTC[];
+
+varying vec3 VARYING_NAME(varNormal);
+varying vec3 VARYING_NAME(varObjPos);
+
+#if UIC_ENABLE_UV0
+attribute vec3 varTexCoord0TC[];
+varying vec3 VARYING_NAME(varTexCoord0);
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 varTangentTC[];
+attribute vec3 varObjTangentTC[];
+varying vec3 VARYING_NAME(varTangent);
+varying vec3 VARYING_NAME(varObjTangent);
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 varBinormalTC[];
+attribute vec3 varObjBinormalTC[];
+varying vec3 VARYING_NAME(varBinormal);
+varying vec3 VARYING_NAME(varObjBinormal);
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPosTC[];
+varying vec3 VARYING_NAME(varWorldPos);
+#endif
+
+void main() {
+ vec4 pos = tessShader( );
+
+ gl_Position = model_view_projection_matrix * pos;
+
+ VARYING_NAME(varObjPos) = gl_TessCoord.x * varObjPosTC[0] + gl_TessCoord.y * varObjPosTC[1] + gl_TessCoord.z * varObjPosTC[2];
+ VARYING_NAME(varNormal) = gl_TessCoord.x * varNormalTC[0] + gl_TessCoord.y * varNormalTC[1] + gl_TessCoord.z * varNormalTC[2];
+
+#if UIC_ENABLE_UV0
+ VARYING_NAME(varTexCoord0) = gl_TessCoord.x * varTexCoord0TC[0] + gl_TessCoord.y * varTexCoord0TC[1] + gl_TessCoord.z * varTexCoord0TC[2];
+#endif
+#if UIC_ENABLE_TEXTAN
+ VARYING_NAME(varTangent) = gl_TessCoord.x * varTangentTC[0] + gl_TessCoord.y * varTangentTC[1] + gl_TessCoord.z * varTangentTC[2];
+ VARYING_NAME(varObjTangent) = gl_TessCoord.x * varObjTangentTC[0] + gl_TessCoord.y * varObjTangentTC[1] + gl_TessCoord.z * varObjTangentTC[2];
+#endif
+#if UIC_ENABLE_BINORMAL
+ VARYING_NAME(varBinormal) = gl_TessCoord.x * varBinormalTC[0] + gl_TessCoord.y * varBinormalTC[1] + gl_TessCoord.z * varBinormalTC[2];
+ VARYING_NAME(varObjBinormal) = gl_TessCoord.x * varObjBinormalTC[0] + gl_TessCoord.y * varObjBinormalTC[1] + gl_TessCoord.z * varObjBinormalTC[2];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ VARYING_NAME(varWorldPos) = gl_TessCoord.x * varWorldPosTC[0] + gl_TessCoord.y * varWorldPosTC[1] + gl_TessCoord.z * varWorldPosTC[2];
+#endif
+
+ VARYING_NAME(varNormal) = normalize(normal_matrix * VARYING_NAME(varNormal));
+}
+
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/tessellationNPatch.glsllib b/src/Runtime/res/effectlib/tessellationNPatch.glsllib
new file mode 100644
index 00000000..a483440c
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationNPatch.glsllib
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_NPATCH_GLSLLIB
+#define TESSELLATION_NPATCH_GLSLLIB
+
+struct NPatchTessPatch
+{
+ float b210;
+ float b120;
+ float b021;
+ float b012;
+ float b102;
+ float b201;
+ float b111;
+ float n110;
+ float n011;
+ float n101;
+ float t110;
+ float t011;
+ float t101;
+};
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 3) out;
+
+layout(location=15) out NPatchTessPatch tcTessPatch[];
+
+// global setup in main
+vec3 ctWorldPos[3];
+vec3 ctNorm[3];
+vec3 ctTangent[3];
+
+uniform vec3 camera_position;
+uniform vec2 distanceRange;
+uniform float disableCulling;
+
+float isBackFace()
+{
+ vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) );
+
+ vec3 ncd = normalize( ctWorldPos[0] - camera_position );
+
+ return sign( 0.2 + dot(faceNormal, ncd) ); // 0.2 is a conservative offset to account for curved surfaces
+}
+
+float adaptiveCameraFactor( in float minTess, in float maxTess )
+{
+ float distanceValue0 = distance( camera_position, ctWorldPos[0] );
+ float distanceValue1 = distance( camera_position, ctWorldPos[1] );
+ float distanceValue2 = distance( camera_position, ctWorldPos[2] );
+
+ float range = distanceRange[1] - distanceRange[0];
+
+ vec3 edgeDistance;
+ edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range;
+ edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range;
+ edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range;
+
+ edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) );
+
+ //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] );
+ float af = 1.0 - edgeDistance[gl_InvocationID];
+ af = clamp( af*af*maxTess , minTess, maxTess );
+
+ return af;
+}
+
+float adaptiveFeatureFactor( in float minTess, in float maxTess )
+{
+ vec3 adaptValue;
+ adaptValue[0] = clamp( dot(ctNorm[1], ctNorm[2]), -1.0, 1.0 );
+ adaptValue[1] = clamp( dot(ctNorm[2], ctNorm[0]), -1.0, 1.0 );
+ adaptValue[2] = clamp( dot(ctNorm[0], ctNorm[1]), -1.0, 1.0 );
+
+ //float af = min( adaptValue[0], min(adaptValue[1], adaptValue[2]) );
+ // map [-1, +1] range to [0, 1] range
+ float af = (adaptValue[gl_InvocationID] + 1.0) / 2.0;
+
+ af = mix( minTess, maxTess, 1.0 - af );
+
+ return af;
+}
+
+float getwij(int i, int j)
+{
+ return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, ctNorm[i]);
+}
+
+float getvij(int i, int j)
+{
+ vec3 pji = gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz;
+ vec3 nij = ctNorm[i] + ctNorm[j];
+
+ return 2.0*dot(pji, nij)/dot(pji, pji);
+}
+
+void tessShader ( in float tessEdge, in float tessInner )
+{
+ // setup control points
+ // notations and formulas see http://alex.vlachos.com/graphics/CurvedPNTriangles.pdf
+ // note we compute separate x,y,z component for each invocation
+ float b300 = gl_in[0].gl_Position[gl_InvocationID];
+ float b030 = gl_in[1].gl_Position[gl_InvocationID];
+ float b003 = gl_in[2].gl_Position[gl_InvocationID];
+ float n200 = ctNorm[0][gl_InvocationID];
+ float n020 = ctNorm[1][gl_InvocationID];
+ float n002 = ctNorm[2][gl_InvocationID];
+ float t200 = ctTangent[0][gl_InvocationID];
+ float t020 = ctTangent[1][gl_InvocationID];
+ float t002 = ctTangent[2][gl_InvocationID];
+
+ // compute tangent control points
+ tcTessPatch[gl_InvocationID].b210 = (2.0*b300 + b030 - getwij(0,1)*n200)/3.0;
+ tcTessPatch[gl_InvocationID].b120 = (2.0*b030 + b300 - getwij(1,0)*n020)/3.0;
+ tcTessPatch[gl_InvocationID].b021 = (2.0*b030 + b003 - getwij(1,2)*n020)/3.0;
+ tcTessPatch[gl_InvocationID].b012 = (2.0*b003 + b030 - getwij(2,1)*n002)/3.0;
+ tcTessPatch[gl_InvocationID].b102 = (2.0*b003 + b300 - getwij(2,0)*n002)/3.0;
+ tcTessPatch[gl_InvocationID].b201 = (2.0*b300 + b003 - getwij(0,2)*n200)/3.0;
+ // compute center control point
+ float E = ( tcTessPatch[gl_InvocationID].b210
+ + tcTessPatch[gl_InvocationID].b120
+ + tcTessPatch[gl_InvocationID].b021
+ + tcTessPatch[gl_InvocationID].b012
+ + tcTessPatch[gl_InvocationID].b102
+ + tcTessPatch[gl_InvocationID].b201 ) / 6.0;
+
+ float V = ( b300 + b030 + b003 ) / 3.0;
+ tcTessPatch[gl_InvocationID].b111 = E + (E-V)*0.5;
+
+ // compute normals
+ tcTessPatch[gl_InvocationID].n110 = n200 + n020 - getvij(0,1) * (b030 - b300);
+ tcTessPatch[gl_InvocationID].n011 = n020 + n002 - getvij(1,2) * (b003 - b030);
+ tcTessPatch[gl_InvocationID].n101 = n002 + n200 - getvij(2,0) * (b300 - b003);
+ // compute tangents
+ tcTessPatch[gl_InvocationID].t110 = t200 + t020 - getvij(0,1) * (b030 - b300);
+ tcTessPatch[gl_InvocationID].t011 = t020 + t002 - getvij(1,2) * (b003 - b030);
+ tcTessPatch[gl_InvocationID].t101 = t002 + t200 - getvij(2,0) * (b300 - b003);
+
+ // compute backface
+ float bf = isBackFace();
+ bf = max(disableCulling, bf);
+
+ // adapative tessellation factor regarding features
+ float af = adaptiveFeatureFactor( tessInner, tessEdge );
+
+ //float cf = adaptiveCameraFactor( tessInner, tessEdge );
+
+ // Calculate the tessellation levels
+ gl_TessLevelInner[0] = af * bf;
+ gl_TessLevelOuter[gl_InvocationID] = af * bf;
+}
+
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (triangles, fractional_odd_spacing, ccw) in;
+
+layout(location=15) in NPatchTessPatch tcTessPatch[];
+
+// global setup in main
+vec3 ctNorm[3];
+vec3 teNorm;
+vec3 ctTangent[3];
+vec3 teTangent;
+vec3 teBinormal;
+
+bool doLinear(int i, int j)
+{
+ /*
+ vec3 edgeji = gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz;
+
+ float di = sign( dot( ctNorm[i], edgeji ) );
+ float dj = sign( dot( ctNorm[j], -edgeji ) );
+
+ if ( di != dj )
+ return false;
+ else
+ return true;*/
+
+ // Always do linear normal interpolation for now
+ // Seems to produce always good results unless we would produce
+ // a s-shaped triangle.
+ return true;
+}
+
+vec4 tessShader ( )
+{
+ // pre compute square tesselation coord
+ vec3 tessSquared = gl_TessCoord * gl_TessCoord;
+ vec3 tessCubed = tessSquared * gl_TessCoord;
+
+ // combine control points
+ vec3 b210 = vec3(tcTessPatch[0].b210, tcTessPatch[1].b210, tcTessPatch[2].b210);
+ vec3 b120 = vec3(tcTessPatch[0].b120, tcTessPatch[1].b120, tcTessPatch[2].b120);
+ vec3 b021 = vec3(tcTessPatch[0].b021, tcTessPatch[1].b021, tcTessPatch[2].b021);
+ vec3 b012 = vec3(tcTessPatch[0].b012, tcTessPatch[1].b012, tcTessPatch[2].b012);
+ vec3 b102 = vec3(tcTessPatch[0].b102, tcTessPatch[1].b102, tcTessPatch[2].b102);
+ vec3 b201 = vec3(tcTessPatch[0].b201, tcTessPatch[1].b201, tcTessPatch[2].b201);
+ vec3 b111 = vec3(tcTessPatch[0].b111, tcTessPatch[1].b111, tcTessPatch[2].b111);
+
+ // combine control normals
+ vec3 n110 = vec3(tcTessPatch[0].n110, tcTessPatch[1].n110, tcTessPatch[2].n110);
+ vec3 n011 = vec3(tcTessPatch[0].n011, tcTessPatch[1].n011, tcTessPatch[2].n011);
+ vec3 n101 = vec3(tcTessPatch[0].n101, tcTessPatch[1].n101, tcTessPatch[2].n101);
+
+ // combine control tangents
+ vec3 t110 = vec3(tcTessPatch[0].t110, tcTessPatch[1].t110, tcTessPatch[2].t110);
+ vec3 t011 = vec3(tcTessPatch[0].t011, tcTessPatch[1].t011, tcTessPatch[2].t011);
+ vec3 t101 = vec3(tcTessPatch[0].t101, tcTessPatch[1].t101, tcTessPatch[2].t101);
+
+ // NPatch normal
+ if ( doLinear( 0, 1 ) == true )
+ {
+ // linear normal
+ teNorm = ctNorm[0] * gl_TessCoord[2]
+ + ctNorm[1] * gl_TessCoord[0]
+ + ctNorm[2] * gl_TessCoord[1];
+ // NPatch tangent
+ teTangent = ctTangent[0] * gl_TessCoord[2]
+ + ctTangent[1] * gl_TessCoord[0]
+ + ctTangent[2] * gl_TessCoord[1];
+ }
+ else
+ {
+ // quadratic normal
+ teNorm = ctNorm[0] * tessSquared[2]
+ + ctNorm[1] * tessSquared[0]
+ + ctNorm[2] * tessSquared[1]
+ + n110*gl_TessCoord[2] * gl_TessCoord[0]
+ + n011*gl_TessCoord[0] * gl_TessCoord[1]
+ + n101*gl_TessCoord[2] * gl_TessCoord[1];
+
+ // NPatch tangent
+ teTangent = ctTangent[0] * tessSquared[2]
+ + ctTangent[1] * tessSquared[0]
+ + ctTangent[2] * tessSquared[1]
+ + t110*gl_TessCoord[2] * gl_TessCoord[0]
+ + t011*gl_TessCoord[0] * gl_TessCoord[1]
+ + t101*gl_TessCoord[2] * gl_TessCoord[1];
+ }
+
+ // NPatch binormal
+ teBinormal = cross( teNorm, teTangent );
+
+ // npatch interpolated position
+ vec3 finalPos = gl_in[0].gl_Position.xyz * tessCubed[2]
+ + gl_in[1].gl_Position.xyz * tessCubed[0]
+ + gl_in[2].gl_Position.xyz * tessCubed[1]
+ + b210 * 3.0 * tessSquared[2] * gl_TessCoord[0]
+ + b120 * 3.0 * tessSquared[0] * gl_TessCoord[2]
+ + b201 * 3.0 * tessSquared[2] * gl_TessCoord[1]
+ + b021 * 3.0 * tessSquared[0] * gl_TessCoord[1]
+ + b102 * 3.0 * tessSquared[1] * gl_TessCoord[2]
+ + b012 * 3.0 * tessSquared[1] * gl_TessCoord[0]
+ + b111 * 6.0 * gl_TessCoord[0] * gl_TessCoord[1] * gl_TessCoord[2];
+
+ return vec4( finalPos, 1.0 );
+}
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/tessellationNPatchCM.glsllib b/src/Runtime/res/effectlib/tessellationNPatchCM.glsllib
new file mode 100644
index 00000000..361efd31
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationNPatchCM.glsllib
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_NPATCH_CM_GLSLLIB
+#define TESSELLATION_NPATCH_CM_GLSLLIB GLSLLIB
+
+
+#include "tessellationNPatch.glsllib"
+
+
+#if TESSELLATION_CONTROL_SHADER
+
+uniform float tessLevelOuter;
+uniform float tessLevelInner;
+
+attribute vec3 varNormal[];
+attribute vec3 varObjPos[];
+
+varying vec3 varNormalTC[];
+varying vec3 varObjPosTC[];
+
+#if UIC_ENABLE_UV0
+attribute vec3 varTexCoord0[];
+varying vec3 varTexCoord0TC[];
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 varTangent[];
+attribute vec3 varObjTangent[];
+varying vec3 varTangentTC[];
+varying vec3 varObjTangentTC[];
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 varBinormal[];
+attribute vec3 varObjBinormal[];
+varying vec3 varBinormalTC[];
+varying vec3 varObjBinormalTC[];
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPos[];
+varying vec3 varWorldPosTC[];
+#endif
+
+void main() {
+
+ ctNorm[0] = varNormal[0];
+ ctNorm[1] = varNormal[1];
+ ctNorm[2] = varNormal[2];
+#if UIC_ENABLE_TEXTAN
+ ctTangent[0] = varObjTangent[0];
+ ctTangent[1] = varObjTangent[1];
+ ctTangent[2] = varObjTangent[2];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ ctWorldPos[0] = varWorldPos[0];
+ ctWorldPos[1] = varWorldPos[1];
+ ctWorldPos[2] = varWorldPos[2];
+#endif
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ tessShader( tessLevelOuter, tessLevelInner);
+
+ varObjPosTC[gl_InvocationID] = varObjPos[gl_InvocationID];
+ varNormalTC[gl_InvocationID] = varNormal[gl_InvocationID];
+
+#if UIC_ENABLE_UV0
+ varTexCoord0TC[gl_InvocationID] = varTexCoord0[gl_InvocationID];
+#endif
+#if UIC_ENABLE_TEXTAN
+ varTangentTC[gl_InvocationID] = varTangent[gl_InvocationID];
+ varObjTangentTC[gl_InvocationID] = varObjTangent[gl_InvocationID];
+#endif
+#if UIC_ENABLE_BINORMAL
+ varBinormalTC[gl_InvocationID] = varBinormal[gl_InvocationID];
+ varObjBinormalTC[gl_InvocationID] = varObjBinormal[gl_InvocationID];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ varWorldPosTC[gl_InvocationID] = varWorldPos[gl_InvocationID];
+#endif
+}
+
+#endif
+
+
+#if TESSELLATION_EVALUATION_SHADER
+
+#if (GEOMETRY_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName
+#endif
+
+uniform mat3 normal_matrix;
+uniform mat4 model_view_projection_matrix;
+
+attribute vec3 varNormalTC[];
+attribute vec3 varObjPosTC[];
+
+varying vec3 VARYING_NAME(varNormal);
+varying vec3 VARYING_NAME(varObjPos);
+
+#if UIC_ENABLE_UV0
+attribute vec3 varTexCoord0TC[];
+varying vec3 VARYING_NAME(varTexCoord0);
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 varTangentTC[];
+attribute vec3 varObjTangentTC[];
+varying vec3 VARYING_NAME(varTangent);
+varying vec3 VARYING_NAME(varObjTangent);
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 varBinormalTC[];
+attribute vec3 varObjBinormalTC[];
+varying vec3 VARYING_NAME(varBinormal);
+varying vec3 VARYING_NAME(varObjBinormal);
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPosTC[];
+varying vec3 VARYING_NAME(varWorldPos);
+#endif
+
+void main() {
+
+ ctNorm[0] = varNormalTC[0];
+ ctNorm[1] = varNormalTC[1];
+ ctNorm[2] = varNormalTC[2];
+#if UIC_ENABLE_TEXTAN
+ ctTangent[0] = varObjTangentTC[0];
+ ctTangent[1] = varObjTangentTC[1];
+ ctTangent[2] = varObjTangentTC[2];
+#endif
+
+ vec4 pos = tessShader( );
+
+ gl_Position = model_view_projection_matrix * pos;
+
+ VARYING_NAME(varObjPos) = gl_TessCoord.z * varObjPosTC[0] + gl_TessCoord.x * varObjPosTC[1] + gl_TessCoord.y * varObjPosTC[2];
+
+#if UIC_ENABLE_UV0
+ VARYING_NAME(varTexCoord0) = gl_TessCoord.z * varTexCoord0TC[0] + gl_TessCoord.x * varTexCoord0TC[1] + gl_TessCoord.y * varTexCoord0TC[2];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ VARYING_NAME(varWorldPos) = gl_TessCoord.z * varWorldPosTC[0] + gl_TessCoord.x * varWorldPosTC[1] + gl_TessCoord.y * varWorldPosTC[2];
+#endif
+
+ VARYING_NAME(varNormal) = normalize(normal_matrix * teNorm);
+
+#if UIC_ENABLE_TEXTAN
+ VARYING_NAME(varTangent) = normalize(normal_matrix * teTangent);
+ VARYING_NAME(varObjTangent) = gl_TessCoord.z * varObjTangentTC[0] + gl_TessCoord.x * varObjTangentTC[1] + gl_TessCoord.y * varObjTangentTC[2];
+#endif
+#if UIC_ENABLE_BINORMAL
+ VARYING_NAME(varBinormal) = normalize(normal_matrix * teBinormal);
+ VARYING_NAME(varObjBinormal) = gl_TessCoord.z * varObjBinormalTC[0] + gl_TessCoord.x * varObjBinormalTC[1] + gl_TessCoord.y * varObjBinormalTC[2];
+#endif
+}
+
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/tessellationPath.glsllib b/src/Runtime/res/effectlib/tessellationPath.glsllib
new file mode 100644
index 00000000..82d68fab
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationPath.glsllib
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_PATH_GLSLLIB
+#define TESSELLATION_PATH_GLSLLIB
+
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 5) out;
+
+void tessShader ( in float edgeTessAmount, float innerTessAmount )
+{
+ gl_TessLevelOuter[0] = innerTessAmount;
+ gl_TessLevelOuter[1] = edgeTessAmount;
+ gl_TessLevelOuter[2] = innerTessAmount;
+ gl_TessLevelOuter[3] = edgeTessAmount;
+
+ gl_TessLevelInner[0] = edgeTessAmount / 2.0;
+ gl_TessLevelInner[1] = innerTessAmount;
+}
+
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (quads, equal_spacing, cw) in;
+
+vec2 getTangent(vec2 p0, vec2 p1, vec2 p2, vec2 p3, float t)
+{
+ // derivative
+ float dbt0 = -3.0 * (1.0 - t) * (1.0 - t);
+ float dbt1 = 3.0 * (1.0 - t) * (1.0 - 3.0 * t);
+ float dbt2 = 3.0 * t * (2.0 - 3.0 * t);
+ float dbt3 = 3.0 * t * t;
+
+ // tangent on curve
+ return normalize( dbt0 * p0 + dbt1 * p1 + dbt2 * p2 + dbt3 * p3 );
+}
+//An exact cross product would involve normalizing dx,dy. Since
+//this algorithm needs merely the sign, normalization is not necessary.
+float roughCrossProd( vec2 prev, vec2 point, vec2 next )
+{
+ vec2 inDxDy = point - prev;
+ vec2 outDxDy = next - point;
+ return inDxDy.x * outDxDy.y - inDxDy.y * outDxDy.x;
+}
+
+//The incoming corss product tells us both if we should do a seam merge
+//and if the merge is above or below point in gl_TessCoord.y space; we know the
+//anchor point is at .5 gl_TessCoord.y space.
+vec3 computeAdjoiningFactors( float cross, vec2 adjoining, vec2 point, float tessY )
+{
+ vec3 retval = vec3( 0.0, 0.0, 0.0 );
+ float multiplier = cross < 0.0 ? 1.0 : -1.0;
+ float weight = abs(cross) > 0.001 ? multiplier * ( ( tessY - .5 )/ .5 ) : 0.0;
+ retval.z = weight > 0.0 ? 1.0 : 0.0;
+ retval.xy = mix( point, adjoining, weight );
+ return retval;
+}
+
+#define NO_TAPER 0
+#define BEGIN_TAPER 1
+#define END_TAPER 2
+
+//Tapering is done by interpolating the path width somewhat cleverly.
+float getTaperResult( float inIncomingValue, float inBeginValue, float inEndValue, vec2 taperData, uint inMode )
+{
+ float mixInfo = mix( taperData.x, taperData.y, gl_TessCoord.x );
+ float theValueMixer = inMode == BEGIN_TAPER ? inBeginValue : inEndValue;
+ return mix( theValueMixer, inIncomingValue, mixInfo );
+}
+
+uniform vec2 beginTaperInfo;
+uniform vec2 endTaperInfo;
+
+struct STessShaderResult
+{
+ vec3 m_Position;
+ vec2 m_TexCoord;
+ vec2 m_Tangent;
+ vec2 m_Binormal;
+ float m_Opacity;
+};
+
+STessShaderResult tessShader ( float inPathWidth )
+{
+ vec2 p1 = gl_in[0].gl_Position.xy;
+ vec2 c1 = gl_in[0].gl_Position.zw; //c1
+ vec2 c2 = gl_in[1].gl_Position.xy; //c2
+ vec2 p2 = gl_in[1].gl_Position.zw;
+ vec4 taperData = gl_in[3].gl_Position;
+ vec2 udata = gl_in[4].gl_Position.xy;
+
+ //Adjust width for taper if necessary.
+ inPathWidth = taperData.z > 0.0 ? getTaperResult( inPathWidth, beginTaperInfo.x, endTaperInfo.x, taperData.xy, uint(taperData.z) ) : inPathWidth;
+
+ float adjoiningWeight = 0.0;
+ vec2 adjoining = vec2( 0.0, 0.0 );
+ if ( gl_TessCoord.x == floor(gl_TessCoord.x) ) // gl_TessCord.x either 0.0 or 1.0
+ {
+ vec2 point, cross1, cross2;
+ if ( gl_TessCoord.x == 0.0 )
+ {
+ adjoining = gl_in[2].gl_Position.xy;
+ point = p1;
+ cross1 = adjoining;
+ cross2 = c1;
+ }
+ else // gl_TessCoord.x == 1.0
+ {
+ adjoining = gl_in[2].gl_Position.zw;
+ point = p2;
+ cross1 = c2;
+ cross2 = adjoining;
+ }
+ float cross = roughCrossProd( cross1, point, cross2 );
+ vec3 adjoiningFactors = computeAdjoiningFactors( cross, adjoining, point, gl_TessCoord.y );
+ adjoining = adjoiningFactors.xy;
+ adjoiningWeight = adjoiningFactors.z;
+ }
+
+ float v = gl_TessCoord.x;
+ // cubic basis function calculated from v.
+ float bv0 = (1.0 - v) * (1.0 - v) * (1.0 - v);
+ float bv1 = 3.0 * v * (1.0 - v) * (1.0 - v);
+ float bv2 = 3.0 * v * v * (1.0 - v);
+ float bv3 = v * v * v;
+
+ //u ranges from 0 - 1. What we want is to
+ //have u range from -1,1.
+ float u = 2.0 * ( gl_TessCoord.y - .5 );
+
+ vec2 tangent = getTangent( p1, c1, c2, p2, v );
+ vec2 normal = vec2( tangent.y, -tangent.x );
+
+ vec2 offset = normal * inPathWidth * u;
+
+ vec2 pointOnPath = bv0*p1 + bv1*c1 + bv2*c2 + bv3*p2;
+
+ vec2 finalPosXY = offset + pointOnPath;
+
+ STessShaderResult retval;
+ retval.m_Position = vec3( mix( finalPosXY, adjoining, adjoiningWeight), 0.0 );
+ retval.m_Opacity = taperData.z > 0.0 ? getTaperResult( 1.0, beginTaperInfo.y, endTaperInfo.y, taperData.xy, uint(taperData.z) ) : 1.0;
+
+ // cubic interpolation of the texture coords
+ retval.m_TexCoord.x = mix( udata.x, udata.y, v );
+ retval.m_TexCoord.y = gl_TessCoord.y;
+ retval.m_Tangent = tangent;
+ retval.m_Binormal = normal;
+
+ return retval;
+}
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/tessellationPhong.glsllib b/src/Runtime/res/effectlib/tessellationPhong.glsllib
new file mode 100644
index 00000000..a70eda4e
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationPhong.glsllib
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_PHONG_GLSLLIB
+#define TESSELLATION_PHONG_GLSLLIB
+
+struct PhongTessPatch
+{
+ float projIJ;
+ float projJK;
+ float projIK;
+};
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 3) out;
+
+layout(location = 15) out PhongTessPatch tcTessPatch[];
+
+// global setup in main
+vec3 ctWorldPos[3];
+vec3 ctNorm[3];
+
+uniform vec3 camera_position;
+uniform vec2 distanceRange;
+uniform float disableCulling;
+
+float isBackFace()
+{
+ vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) );
+
+ vec3 ncd = normalize( ctWorldPos[0] - camera_position );
+
+ return sign( 0.2 + dot(faceNormal, ncd) ); // 0.2 is a conservative offset to account for curved surfaces
+}
+
+float adaptiveCameraFactor( in float minTess, in float maxTess )
+{
+ float distanceValue0 = distance( camera_position, ctWorldPos[0] );
+ float distanceValue1 = distance( camera_position, ctWorldPos[1] );
+ float distanceValue2 = distance( camera_position, ctWorldPos[2] );
+
+ float range = distanceRange[1] - distanceRange[0];
+
+ vec3 edgeDistance;
+ edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range;
+ edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range;
+ edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range;
+
+ edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) );
+
+ //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] );
+ float af = 1.0 - edgeDistance[gl_InvocationID];
+ af = clamp( af*af*maxTess , minTess, maxTess );
+
+ return af;
+}
+
+float adaptiveFeatureFactor( in float minTess, in float maxTess )
+{
+ vec3 adaptValue;
+ adaptValue[0] = clamp( dot(ctNorm[1], ctNorm[2]), -1.0, 1.0 );
+ adaptValue[1] = clamp( dot(ctNorm[2], ctNorm[0]), -1.0, 1.0 );
+ adaptValue[2] = clamp( dot(ctNorm[0], ctNorm[1]), -1.0, 1.0 );
+
+ //float af = min( adaptValue[0], min(adaptValue[1], adaptValue[2]) );
+ // map [-1, +1] range to [0, 1] range
+ float af = (adaptValue[gl_InvocationID] + 1.0) / 2.0;
+
+ af = mix( minTess, maxTess, 1.0 - af );
+
+ return af;
+}
+
+float mapToTangentPlane(int i, vec3 q)
+{
+ vec3 q_minus_p = q - gl_in[i].gl_Position.xyz;
+ return q[gl_InvocationID] - dot(q_minus_p, ctNorm[i]) * ctNorm[i][gl_InvocationID];
+}
+
+void tessShader ( in float tessEdge, in float tessInner )
+{
+ // compute projections separate for each xyz component
+ tcTessPatch[gl_InvocationID].projIJ = mapToTangentPlane(0, gl_in[1].gl_Position.xyz) + mapToTangentPlane(1, gl_in[0].gl_Position.xyz);
+ tcTessPatch[gl_InvocationID].projJK = mapToTangentPlane(1, gl_in[2].gl_Position.xyz) + mapToTangentPlane(2, gl_in[1].gl_Position.xyz);
+ tcTessPatch[gl_InvocationID].projIK = mapToTangentPlane(2, gl_in[0].gl_Position.xyz) + mapToTangentPlane(0, gl_in[2].gl_Position.xyz);
+
+ // compute backface
+ float bf = isBackFace();
+ bf = max(disableCulling, bf);
+ // adapative tessellation factor regarding features
+ float af = adaptiveFeatureFactor( tessInner, tessEdge );
+ // adapative tessellation factor regarding camera
+ //float cf = adaptiveFeatureFactor( tessInner, tessEdge );
+
+ // the camera tess factor is the limit
+ //af = min(af, cf);
+
+ // Calculate the tessellation levels
+ gl_TessLevelInner[0] = af * bf;
+ gl_TessLevelOuter[gl_InvocationID] = af * bf;
+}
+
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (triangles, equal_spacing, ccw) in;
+
+layout(location = 15) in PhongTessPatch tcTessPatch[];
+
+uniform float phongBlend;
+
+vec4 tessShader ( )
+{
+ // pre compute square tesselation coord
+ vec3 tessSquared = gl_TessCoord * gl_TessCoord;
+
+ // barycentric linear position
+ vec3 linearPos = gl_TessCoord.x * gl_in[0].gl_Position.xyz
+ + gl_TessCoord.y * gl_in[1].gl_Position.xyz
+ + gl_TessCoord.z * gl_in[2].gl_Position.xyz;
+
+ // projective terms
+ vec3 projJI = vec3(tcTessPatch[0].projIJ, tcTessPatch[1].projIJ, tcTessPatch[2].projIJ);
+ vec3 projKJ = vec3(tcTessPatch[0].projJK, tcTessPatch[1].projJK, tcTessPatch[2].projJK);
+ vec3 projIK = vec3(tcTessPatch[0].projIK, tcTessPatch[1].projIK, tcTessPatch[2].projIK);
+
+ // phong interpolated position
+ vec3 phongPos = tessSquared.x * gl_in[0].gl_Position.xyz
+ + tessSquared.y * gl_in[1].gl_Position.xyz
+ + tessSquared.z * gl_in[2].gl_Position.xyz
+ + gl_TessCoord.x * gl_TessCoord.y * projJI
+ + gl_TessCoord.y * gl_TessCoord.z * projKJ
+ + gl_TessCoord.z * gl_TessCoord.x * projIK;
+
+ // final blend between linear and phong interpolation
+ vec3 finalPos = (1.0-phongBlend)*linearPos + phongBlend*phongPos;
+
+ return vec4( finalPos, 1.0 );
+}
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/tessellationPhongCM.glsllib b/src/Runtime/res/effectlib/tessellationPhongCM.glsllib
new file mode 100644
index 00000000..f70c72b3
--- /dev/null
+++ b/src/Runtime/res/effectlib/tessellationPhongCM.glsllib
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESSELLATION_PHONG_CM_GLSLLIB
+#define TESSELLATION_PHONG_CM_ GLSLLIB
+
+
+#include "tessellationPhong.glsllib"
+
+
+#if TESSELLATION_CONTROL_SHADER
+
+uniform float tessLevelOuter;
+uniform float tessLevelInner;
+
+attribute vec3 varNormal[];
+attribute vec3 varObjPos[];
+
+varying vec3 varNormalTC[];
+varying vec3 varObjPosTC[];
+
+#if UIC_ENABLE_UV0
+attribute vec3 varTexCoord0[];
+varying vec3 varTexCoord0TC[];
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 varTangent[];
+attribute vec3 varObjTangent[];
+varying vec3 varTangentTC[];
+varying vec3 varObjTangentTC[];
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 varBinormal[];
+attribute vec3 varObjBinormal[];
+varying vec3 varBinormalTC[];
+varying vec3 varObjBinormalTC[];
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPos[];
+varying vec3 varWorldPosTC[];
+#endif
+
+void main() {
+
+#if UIC_ENABLE_WORLD_POSITION
+ ctWorldPos[0] = varWorldPos[0];
+ ctWorldPos[1] = varWorldPos[1];
+ ctWorldPos[2] = varWorldPos[2];
+#endif
+ ctNorm[0] = varNormal[0];
+ ctNorm[1] = varNormal[1];
+ ctNorm[2] = varNormal[2];
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ tessShader( tessLevelOuter, tessLevelInner);
+
+ varObjPosTC[gl_InvocationID] = varObjPos[gl_InvocationID];
+ varNormalTC[gl_InvocationID] = varNormal[gl_InvocationID];
+
+#if UIC_ENABLE_UV0
+ varTexCoord0TC[gl_InvocationID] = varTexCoord0[gl_InvocationID];
+#endif
+#if UIC_ENABLE_TEXTAN
+ varTangentTC[gl_InvocationID] = varTangent[gl_InvocationID];
+ varObjTangentTC[gl_InvocationID] = varObjTangent[gl_InvocationID];
+#endif
+#if UIC_ENABLE_BINORMAL
+ varBinormalTC[gl_InvocationID] = varBinormal[gl_InvocationID];
+ varObjBinormalTC[gl_InvocationID] = varObjBinormal[gl_InvocationID];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ varWorldPosTC[gl_InvocationID] = varWorldPos[gl_InvocationID];
+#endif
+}
+
+#endif
+
+
+#if TESSELLATION_EVALUATION_SHADER
+
+#if (GEOMETRY_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName
+#endif
+
+uniform mat3 normal_matrix;
+uniform mat4 model_view_projection_matrix;
+
+attribute vec3 varNormalTC[];
+attribute vec3 varObjPosTC[];
+
+varying vec3 VARYING_NAME(varNormal);
+varying vec3 VARYING_NAME(varObjPos);
+
+#if UIC_ENABLE_UV0
+attribute vec3 varTexCoord0TC[];
+varying vec3 VARYING_NAME(varTexCoord0);
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 varTangentTC[];
+attribute vec3 varObjTangentTC[];
+varying vec3 VARYING_NAME(varTangent);
+varying vec3 VARYING_NAME(varObjTangent);
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 varBinormalTC[];
+attribute vec3 varObjBinormalTC[];
+varying vec3 VARYING_NAME(varBinormal);
+varying vec3 VARYING_NAME(varObjBinormal);
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPosTC[];
+varying vec3 VARYING_NAME(varWorldPos);
+#endif
+
+void main() {
+ vec4 pos = tessShader( );
+
+ gl_Position = model_view_projection_matrix * pos;
+
+ VARYING_NAME(varObjPos) = gl_TessCoord.x * varObjPosTC[0] + gl_TessCoord.y * varObjPosTC[1] + gl_TessCoord.z * varObjPosTC[2];
+ VARYING_NAME(varNormal) = gl_TessCoord.x * varNormalTC[0] + gl_TessCoord.y * varNormalTC[1] + gl_TessCoord.z * varNormalTC[2];
+
+#if UIC_ENABLE_UV0
+ VARYING_NAME(varTexCoord0) = gl_TessCoord.x * varTexCoord0TC[0] + gl_TessCoord.y * varTexCoord0TC[1] + gl_TessCoord.z * varTexCoord0TC[2];
+#endif
+#if UIC_ENABLE_TEXTAN
+ VARYING_NAME(varTangent) = gl_TessCoord.x * varTangentTC[0] + gl_TessCoord.y * varTangentTC[1] + gl_TessCoord.z * varTangentTC[2];
+ VARYING_NAME(varObjTangent) = gl_TessCoord.x * varObjTangentTC[0] + gl_TessCoord.y * varObjTangentTC[1] + gl_TessCoord.z * varObjTangentTC[2];
+#endif
+#if UIC_ENABLE_BINORMAL
+ VARYING_NAME(varBinormal) = gl_TessCoord.x * varBinormalTC[0] + gl_TessCoord.y * varBinormalTC[1] + gl_TessCoord.z * varBinormalTC[2];
+ VARYING_NAME(varObjBinormal) = gl_TessCoord.x * varObjBinormalTC[0] + gl_TessCoord.y * varObjBinormalTC[1] + gl_TessCoord.z * varObjBinormalTC[2];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ VARYING_NAME(varWorldPos) = gl_TessCoord.x * varWorldPosTC[0] + gl_TessCoord.y * varWorldPosTC[1] + gl_TessCoord.z * varWorldPosTC[2];
+#endif
+
+ VARYING_NAME(varNormal) = normalize(normal_matrix * VARYING_NAME(varNormal));
+}
+
+#endif
+
+#endif
+
diff --git a/src/Runtime/res/effectlib/textureCoordinateInfo.glsllib b/src/Runtime/res/effectlib/textureCoordinateInfo.glsllib
new file mode 100644
index 00000000..b1ed86b3
--- /dev/null
+++ b/src/Runtime/res/effectlib/textureCoordinateInfo.glsllib
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTURE_COORDINATE_INFO_GLSLLIB
+#define TEXTURE_COORDINATE_INFO_GLSLLIB
+
+#ifdef UIC_DEFINE_API
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+#endif
+
+texture_coordinate_info textureCoordinateInfo( in vec3 pos, in vec3 tangentU, in vec3 tangentV )
+{
+ texture_coordinate_info tci;
+ tci.position = pos;
+ tci.tangent_u = normalize( tangentU );
+ tci.tangent_v = normalize( tangentV );
+ return( tci );
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/transformCoordinate.glsllib b/src/Runtime/res/effectlib/transformCoordinate.glsllib
new file mode 100644
index 00000000..53237d02
--- /dev/null
+++ b/src/Runtime/res/effectlib/transformCoordinate.glsllib
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRANSFORM_COORDINATE_GLSLLIB
+#define TRANSFORM_COORDINATE_GLSLLIB
+
+texture_coordinate_info transformCoordinate( in mat4 transform, in texture_coordinate_info coordinate )
+{
+ texture_coordinate_info tci;
+ tci.position = ( transform * vec4( coordinate.position, 1.0f ) ).xyz;
+ tci.tangent_u = ( transform * vec4( coordinate.tangent_u, 0.0f ) ).xyz;
+ tci.tangent_v = ( transform * vec4( coordinate.tangent_v, 0.0f ) ).xyz;
+ return( tci );
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/uicDefaultMaterialFileBumpTexture.glsllib b/src/Runtime/res/effectlib/uicDefaultMaterialFileBumpTexture.glsllib
new file mode 100644
index 00000000..62ba4c45
--- /dev/null
+++ b/src/Runtime/res/effectlib/uicDefaultMaterialFileBumpTexture.glsllib
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UIC_DEFAULT_MATERIAL_FILE_BUMP_TEXTURE_GLSLLIB
+#define UIC_DEFAULT_MATERIAL_FILE_BUMP_TEXTURE_GLSLLIB
+
+#ifndef UIC_DEFINE_API
+#define UIC_DEFINE_API
+#endif
+
+#include "fileBumpTexture.glsllib"
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/uicDefaultMaterialFileDisplacementTexture.glsllib b/src/Runtime/res/effectlib/uicDefaultMaterialFileDisplacementTexture.glsllib
new file mode 100644
index 00000000..9b61cb41
--- /dev/null
+++ b/src/Runtime/res/effectlib/uicDefaultMaterialFileDisplacementTexture.glsllib
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UIC_DEFAULT_MATERIAL_FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+#define UIC_DEFAULT_MATERIAL_FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+
+#ifndef UIC_DEFINE_API
+#define UIC_DEFINE_API
+#endif
+
+#include "fileDisplacementTexture.glsllib"
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/uicDefaultMaterialFileNormalTexture.glsllib b/src/Runtime/res/effectlib/uicDefaultMaterialFileNormalTexture.glsllib
new file mode 100644
index 00000000..18e14fd8
--- /dev/null
+++ b/src/Runtime/res/effectlib/uicDefaultMaterialFileNormalTexture.glsllib
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UIC_DEFAULT_MATERIAL_FILE_NORMAL_TEXTURE_GLSLLIB
+#define UIC_DEFAULT_MATERIAL_FILE_NORMAL_TEXTURE_GLSLLIB
+
+#ifndef UIC_DEFINE_API
+#define UIC_DEFINE_API
+#endif
+
+#include "tangentSpaceNormalTexture.glsllib"
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/vertexFragmentBase.glsllib b/src/Runtime/res/effectlib/vertexFragmentBase.glsllib
new file mode 100644
index 00000000..6da8a701
--- /dev/null
+++ b/src/Runtime/res/effectlib/vertexFragmentBase.glsllib
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VERTEX_FRAGMENT_BASE_GLSLLIB
+#define VERTEX_FRAGMENT_BASE_GLSLLIB
+
+ //FRAGMENT_SHADER
+ uniform vec3 camera_position; //position in world space of the camera
+
+// add global variables
+vec3 normal;
+vec3 surfNormal;
+vec3 texCoord0;
+vec3 tangent;
+vec3 binormal;
+vec3 viewDir;
+
+
+// add shader input
+
+void initializeBaseFragmentVariables()
+{
+ normal = normalize( varNormal );
+ surfNormal = normalize( varNormal );
+
+ texCoord0 = vec3( varTexCoord0.xy, 1.0 );
+ tangent = normalize( varTangent );
+
+ binormal = normalize( varBinormal );
+
+ viewDir = normalize( camera_position - varWorldPos );
+}
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/viewProperties.glsllib b/src/Runtime/res/effectlib/viewProperties.glsllib
new file mode 100644
index 00000000..ef6b01ff
--- /dev/null
+++ b/src/Runtime/res/effectlib/viewProperties.glsllib
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEW_PROPERTIES_GLSLLIB
+#define VIEW_PROPERTIES_GLSLLIB
+
+uniform mat4 view_projection_matrix;
+uniform mat4 view_matrix;
+uniform vec2 camera_properties; //near clip x, far clip y
+#ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB
+uniform vec3 camera_position; //position in world space of the camera
+#endif
+
+#endif \ No newline at end of file
diff --git a/src/Runtime/res/effectlib/weightedLayer.glsllib b/src/Runtime/res/effectlib/weightedLayer.glsllib
new file mode 100644
index 00000000..781ffacf
--- /dev/null
+++ b/src/Runtime/res/effectlib/weightedLayer.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+vec4 weightedLayer( in float weight, in vec3 layercolor, in vec4 layer, in vec4 base, in float alpha )
+{
+ return vec4( mix( base.rgb, layer.rgb * layercolor, weight ), alpha );
+}
+
diff --git a/src/Runtime/res/effectlib/wireframeCM.glsllib b/src/Runtime/res/effectlib/wireframeCM.glsllib
new file mode 100644
index 00000000..2132ed45
--- /dev/null
+++ b/src/Runtime/res/effectlib/wireframeCM.glsllib
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIREFRAME_CM_GLSLLIB
+#define WIREFRAME_CM_GLSLLIB
+
+#ifdef GL_ES
+precision highp float;
+precision highp int;
+#endif
+
+#if (TESSELLATION_EVALUATION_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName##VX
+#endif
+
+
+attribute vec3 VARYING_NAME(varNormal)[];
+attribute vec3 VARYING_NAME(varObjPos)[];
+
+varying vec3 varNormal;
+varying vec3 varObjPos;
+
+#if UIC_ENABLE_UV0
+attribute vec3 VARYING_NAME(varTexCoord0)[];
+varying vec3 varTexCoord0;
+#endif
+
+#if UIC_ENABLE_TEXTAN
+attribute vec3 VARYING_NAME(varTangent)[];
+attribute vec3 VARYING_NAME(varObjTangent)[];
+varying vec3 varTangent;
+varying vec3 varObjTangent;
+#endif
+
+#if UIC_ENABLE_BINORMAL
+attribute vec3 VARYING_NAME(varBinormal)[];
+attribute vec3 VARYING_NAME(varObjBinormal)[];
+varying vec3 varBinormal;
+varying vec3 varObjBinormal;
+#endif
+
+#if UIC_ENABLE_WORLD_POSITION
+attribute vec3 VARYING_NAME(varWorldPos)[];
+varying vec3 varWorldPos;
+#endif
+
+varying vec3 varEdgeDistance;
+
+uniform mat4 viewport_matrix;
+
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices = 3) out;
+
+void main()
+{
+ // how this all work see http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf
+ // project points to screen space
+ vec3 p0 = vec3(viewport_matrix * (gl_in[0].gl_Position / gl_in[0].gl_Position.w));
+ vec3 p1 = vec3(viewport_matrix * (gl_in[1].gl_Position / gl_in[1].gl_Position.w));
+ vec3 p2 = vec3(viewport_matrix * (gl_in[2].gl_Position / gl_in[2].gl_Position.w));
+ // compute triangle heights
+ float e1 = length(p1 - p2);
+ float e2 = length(p2 - p0);
+ float e3 = length(p1 - p0);
+ float alpha = acos( (e2*e2 + e3*e3 - e1*e1) / (2.0*e2*e3) );
+ float beta = acos( (e1*e1 + e3*e3 - e2*e2) / (2.0*e1*e3) );
+ float ha = abs( e3 * sin( beta ) );
+ float hb = abs( e3 * sin( alpha ) );
+ float hc = abs( e2 * sin( alpha ) );
+
+
+ // vertex 0
+ varEdgeDistance = vec3(ha*gl_in[0].gl_Position.w, 0.0, 0.0);
+ varNormal = VARYING_NAME(varNormal)[0];
+ varObjPos = VARYING_NAME(varObjPos)[0];
+#if UIC_ENABLE_UV0
+ varTexCoord0 = VARYING_NAME(varTexCoord0)[0];
+#endif
+#if UIC_ENABLE_TEXTAN
+ varTangent = VARYING_NAME(varTangent)[0];
+ varObjTangent = VARYING_NAME(varObjTangent)[0];
+#endif
+#if UIC_ENABLE_BINORMAL
+ varBinormal = VARYING_NAME(varBinormal)[0];
+ varObjBinormal = VARYING_NAME(varObjBinormal)[0];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ varWorldPos = VARYING_NAME(varWorldPos)[0];
+#endif
+
+ gl_Position = gl_in[0].gl_Position;
+ EmitVertex();
+
+ // vertex 1
+ varEdgeDistance = vec3(0.0, hb*gl_in[1].gl_Position.w, 0.0);
+ varNormal = VARYING_NAME(varNormal)[1];
+ varObjPos = VARYING_NAME(varObjPos)[1];
+#if UIC_ENABLE_UV0
+ varTexCoord0 = VARYING_NAME(varTexCoord0)[1];
+#endif
+#if UIC_ENABLE_TEXTAN
+ varTangent = VARYING_NAME(varTangent)[1];
+ varObjTangent = VARYING_NAME(varObjTangent)[1];
+#endif
+#if UIC_ENABLE_BINORMAL
+ varBinormal = VARYING_NAME(varBinormal)[1];
+ varObjBinormal = VARYING_NAME(varObjBinormal)[1];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ varWorldPos = VARYING_NAME(varWorldPos)[1];
+#endif
+
+ gl_Position = gl_in[1].gl_Position;
+ EmitVertex();
+
+ // vertex 2
+ varEdgeDistance = vec3(0.0, 0.0, hc*gl_in[2].gl_Position.w);
+ varNormal = VARYING_NAME(varNormal)[2];
+ varObjPos = VARYING_NAME(varObjPos)[2];
+#if UIC_ENABLE_UV0
+ varTexCoord0 = VARYING_NAME(varTexCoord0)[2];
+#endif
+#if UIC_ENABLE_TEXTAN
+ varTangent = VARYING_NAME(varTangent)[2];
+ varObjTangent = VARYING_NAME(varObjTangent)[2];
+#endif
+#if UIC_ENABLE_BINORMAL
+ varBinormal = VARYING_NAME(varBinormal)[2];
+ varObjBinormal = VARYING_NAME(varObjBinormal)[2];
+#endif
+#if UIC_ENABLE_WORLD_POSITION
+ varWorldPos = VARYING_NAME(varWorldPos)[2];
+#endif
+
+ gl_Position = gl_in[2].gl_Position;
+ EmitVertex();
+
+ EndPrimitive();
+}
+
+
+#endif
+ \ No newline at end of file
diff --git a/src/Runtime/res/primitives/Cone.mesh b/src/Runtime/res/primitives/Cone.mesh
new file mode 100644
index 00000000..7ef00f3b
--- /dev/null
+++ b/src/Runtime/res/primitives/Cone.mesh
Binary files differ
diff --git a/src/Runtime/res/primitives/Cube.mesh b/src/Runtime/res/primitives/Cube.mesh
new file mode 100644
index 00000000..af594b2f
--- /dev/null
+++ b/src/Runtime/res/primitives/Cube.mesh
Binary files differ
diff --git a/src/Runtime/res/primitives/Cylinder.mesh b/src/Runtime/res/primitives/Cylinder.mesh
new file mode 100644
index 00000000..0e9fbfcc
--- /dev/null
+++ b/src/Runtime/res/primitives/Cylinder.mesh
Binary files differ
diff --git a/src/Runtime/res/primitives/Rectangle.mesh b/src/Runtime/res/primitives/Rectangle.mesh
new file mode 100644
index 00000000..b137cb93
--- /dev/null
+++ b/src/Runtime/res/primitives/Rectangle.mesh
Binary files differ
diff --git a/src/Runtime/res/primitives/Sphere.mesh b/src/Runtime/res/primitives/Sphere.mesh
new file mode 100644
index 00000000..4f61d4c6
--- /dev/null
+++ b/src/Runtime/res/primitives/Sphere.mesh
Binary files differ
diff --git a/src/Runtime/testres.qrc b/src/Runtime/testres.qrc
new file mode 100644
index 00000000..d099c345
--- /dev/null
+++ b/src/Runtime/testres.qrc
@@ -0,0 +1,14 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="aluminium.material">../../Studio/Content/Material Library/aluminum.material</file>
+ <file alias="asphalt.material">../../Studio/Content/Material Library/asphalt.material</file>
+ <file alias="concrete.material">../../Studio/Content/Material Library/concrete.material</file>
+ <file alias="copper.material">../../Studio/Content/Material Library/copper.material</file>
+ <file alias="porcelain.material">../../Studio/Content/Material Library/porcelain.material</file>
+ <file alias="simple_glass.material">../../Studio/Content/Material Library/simple_glass.material</file>
+ <file alias="Desaturate.effect">../../Studio/Content/Effect Library/Desaturate.effect</file>
+ <file alias="Gaussian Blur.effect">../../Studio/Content/Effect Library/Gaussian Blur.effect</file>
+ <file alias="Sepia.effect">../../Studio/Content/Effect Library/Sepia.effect</file>
+ <file alias="Bloom.effect">../../Studio/Content/Effect Library/Bloom.effect</file>
+ </qresource>
+</RCC>
diff --git a/src/Viewer/Qt3DViewer/Qt3DViewer.pro b/src/Viewer/Qt3DViewer/Qt3DViewer.pro
new file mode 100644
index 00000000..7680b8bf
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/Qt3DViewer.pro
@@ -0,0 +1,34 @@
+include($$PWD/../../Runtime/commoninclude.pri)
+
+TEMPLATE = app
+TARGET = Qt3DViewer
+QT += widgets opengl qml quickwidgets quickcontrols2 studio3d-private
+
+INCLUDEPATH += $$PWD/../qmlviewer
+
+FORMS += mainwindow.ui
+RESOURCES += Viewer.qrc
+RC_FILE += Viewer.rc
+
+SOURCES += \
+ $$PWD/../qmlviewer/Qt3DSViewPlugin.cpp \
+ $$PWD/../qmlviewer/Qt3DSView.cpp \
+ $$PWD/../qmlviewer/Qt3DSRenderer.cpp \
+ $$PWD/../qmlviewer/q3dspresentationitem.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ remoteproject.cpp
+
+HEADERS += \
+ $$PWD/../qmlviewer/Qt3DSViewPlugin.h \
+ $$PWD/../qmlviewer/Qt3DSView.h \
+ $$PWD/../qmlviewer/Qt3DSRenderer.h \
+ $$PWD/../qmlviewer/q3dspresentationitem.h \
+ mainwindow.h \
+ remoteproject.h
+
+LIBS += \
+ -lqt3dsruntime$$qtPlatformTargetSuffix() \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+macos:QMAKE_RPATHDIR += $$PWD/../../../lib
diff --git a/src/Viewer/Qt3DViewer/Viewer.qrc b/src/Viewer/Qt3DViewer/Viewer.qrc
new file mode 100644
index 00000000..f166ccc5
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/Viewer.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/">
+ <file>resources/style/dark.qss</file>
+ <file>resources/images/viewer_icon.png</file>
+ <file>resources/style/checkbox.png</file>
+ <file>resources/style/down_arrow.png</file>
+ <file>resources/style/handle.png</file>
+ <file>viewer.qml</file>
+ </qresource>
+</RCC>
diff --git a/src/Viewer/Qt3DViewer/Viewer.rc b/src/Viewer/Qt3DViewer/Viewer.rc
new file mode 100644
index 00000000..bda70099
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/Viewer.rc
@@ -0,0 +1,54 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "../../Authoring/Build/versionnumber.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+IDI_ICON1 ICON DISCARDABLE "resources/images/Viewer.ico"
+IDI_ICON2 ICON DISCARDABLE "resources/images/ViewerDoc.ico"
+
+1 VERSIONINFO
+FILEVERSION FILEVER
+PRODUCTVERSION PRODUCTVER
+FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "Comments", STRCOMMENTS
+ VALUE "CompanyName", STRCOMPANYNAME
+ VALUE "FileDescription", "Qt 3D Viewer " STRMAJVER
+ VALUE "FileVersion", STRFILEVER
+ VALUE "InternalName", "Qt3DViewer\0"
+ VALUE "LegalCopyright", STRCOPYRIGHT
+ VALUE "LegalTrademarks", STRCOMMENTS
+ VALUE "OriginalFilename", "Qt3DViewer.exe\0"
+ VALUE "PrivateBuild", STRCOMMENTS
+ VALUE "ProductName", STRPRODUCTNAME STRMAJVER
+ VALUE "ProductVersion", STRPRODUCTVER
+ VALUE "SpecialBuild", STRCOMMENTS
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* The following line should only be modified for localized versions. */
+ /* It consists of any number of WORD,WORD pairs, with each pair */
+ /* describing a language,codepage combination supported by the file. */
+ /* */
+ /* For example, a file might have values "0x409,1252" indicating that it */
+ /* supports English language (0x409) in the Windows ANSI codepage (1252). */
+
+ VALUE "Translation", 0x409, 1252
+
+ END
+END
+
+
diff --git a/src/Viewer/Qt3DViewer/android/AndroidManifest.xml b/src/Viewer/Qt3DViewer/android/AndroidManifest.xml
new file mode 100644
index 00000000..e1833d40
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/android/AndroidManifest.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<manifest package="org.qtproject.qt3dviewer" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon">
+ <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+
+ <!-- Application arguments -->
+ <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
+ <!-- Application arguments -->
+
+ <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
+ <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
+ <meta-data android:name="android.app.repository" android:value="default"/>
+ <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
+ <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
+ <!-- Deploy Qt libs as part of package -->
+ <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
+ <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
+ <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
+ <!-- Run with local libs -->
+ <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
+ <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+ <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
+ <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
+ <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
+ <!-- Messages maps -->
+ <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
+ <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
+ <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
+ <!-- Messages maps -->
+
+ <!-- Splash screen -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
+ <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
+ <!-- Splash screen -->
+
+ <!-- Background running -->
+ <!-- Warning: changing this value to true may cause unexpected crashes if the
+ application still try to draw after
+ "applicationStateChanged(Qt::ApplicationSuspended)"
+ signal is sent! -->
+ <meta-data android:name="android.app.background_running" android:value="false"/>
+ <!-- Background running -->
+
+ <!-- auto screen scale factor -->
+ <meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
+ <!-- auto screen scale factor -->
+
+ <!-- extract android style -->
+ <!-- available android:values :
+ * full - useful QWidget & Quick Controls 1 apps
+ * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
+ * none - useful for apps that don't use any of the above Qt modules
+ -->
+ <meta-data android:name="android.app.extract_android_style" android:value="full"/>
+ <!-- extract android style -->
+ </activity>
+
+ <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
+
+ </application>
+
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
+ <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+ <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
+ Remove the comment if you do not require these default permissions. -->
+ <!-- %%INSERT_PERMISSIONS -->
+
+ <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
+ Remove the comment if you do not require these default features. -->
+ <!-- %%INSERT_FEATURES -->
+
+</manifest>
diff --git a/src/Viewer/Qt3DViewer/main.cpp b/src/Viewer/Qt3DViewer/main.cpp
new file mode 100644
index 00000000..3a69201a
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QCommandLineParser>
+#include <QFile>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QCoreApplication::setOrganizationName("The Qt Company");
+ QCoreApplication::setOrganizationDomain("qt.io");
+ QCoreApplication::setApplicationName("Qt 3D Viewer");
+
+ QApplication a(argc, argv);
+
+ QCommandLineParser parser;
+ parser.addHelpOption();
+ parser.addPositionalArgument("file",
+ QCoreApplication::translate("main", "The file to open."));
+ parser.process(a);
+
+ const QStringList files = parser.positionalArguments();
+ if (files.count() > 1)
+ parser.showHelp(-1);
+
+ MainWindow w;
+ w.resize(1280, 720);
+ w.show();
+
+ if (!files.isEmpty())
+ w.loadFile(files.first());
+
+ QFile styleFile(":/resources/style/dark.qss");
+ styleFile.open(QFile::ReadOnly);
+
+ QString style(styleFile.readAll());
+ a.setStyleSheet(style);
+
+ return a.exec();
+}
diff --git a/src/Viewer/Qt3DViewer/mainwindow.cpp b/src/Viewer/Qt3DViewer/mainwindow.cpp
new file mode 100644
index 00000000..2f8e5ea0
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/mainwindow.cpp
@@ -0,0 +1,456 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QKeyEvent>
+#include <QDebug>
+#include <QSettings>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QMimeData>
+#include <QMessageBox>
+#include <QShortcut>
+#include <QWindow>
+#include <QVariant>
+#include <QGLFormat>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QtStudio3D/private/q3dsviewersettings_p.h>
+#include <QtGui/qguiapplication.h>
+
+#include "Qt3DSView.h"
+#include "q3dspresentationitem.h"
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+ , m_studio3D(0)
+ , m_connectionInfo(0)
+ , m_remoteProject(0)
+{
+ ui->setupUi(this);
+
+ ui->actionOpen->setShortcut(QKeySequence::Open);
+ QList<QKeySequence> shortcuts;
+ shortcuts.push_back(QKeySequence(QKeySequence::Quit));
+ shortcuts.push_back(QKeySequence("CTRL+Q"));
+ ui->actionQuit->setShortcuts(shortcuts);
+ ui->actionReload->setShortcut(QKeySequence::Refresh);
+
+ QStringList strArg = QApplication::arguments();
+ if (strArg.size() >= 2) {
+ QFileInfo theFilePath(strArg[1]);
+ if (theFilePath.exists()) {
+ m_openFileDir = theFilePath.path();
+ QSettings().setValue("DirectoryOfLastOpen", m_openFileDir);
+ }
+ }
+
+#ifdef Q_OS_ANDROID
+ m_openFileDir = QStringLiteral("/sdcard/qt3dviewer"); // Add default folder for Android
+#else
+ // Allow drops. Not usable for Android.
+ setAcceptDrops(true);
+#endif
+
+ addAction(ui->actionFull_Screen);
+ addAction(ui->actionShowOnScreenStats);
+ addAction(ui->actionBorder);
+
+ // Set import paths so that standalone installation works
+ QString extraImportPath1(QStringLiteral("%1/qml"));
+ QString extraImportPath2(QStringLiteral("%1/../qml"));
+ ui->quickWidget->engine()->addImportPath(
+ extraImportPath1.arg(QGuiApplication::applicationDirPath()));
+ ui->quickWidget->engine()->addImportPath(
+ extraImportPath2.arg(QGuiApplication::applicationDirPath()));
+
+ ui->quickWidget->setSource(QUrl("qrc:/viewer.qml"));
+
+ updateUI();
+}
+
+MainWindow::~MainWindow()
+{
+}
+
+void MainWindow::on_actionBorder_triggered()
+{
+ Q3DSView *view = viewer();
+ if (!view)
+ return;
+
+ QColor matte = view->viewerSettings()->matteColor();
+ if (matte == QColor(Qt::black) || !matte.isValid())
+ view->viewerSettings()->setMatteColor(QColor(50, 50, 50));
+ else
+ view->viewerSettings()->setMatteColor(Qt::black);
+
+ updateUI();
+}
+
+void MainWindow::on_actionFull_Screen_triggered()
+{
+ if (ui->actionFull_Screen->isChecked()) {
+ showFullScreen();
+ ui->menuBar->hide();
+ } else {
+ showNormal();
+ ui->menuBar->show();
+ }
+}
+
+void MainWindow::on_actionShowOnScreenStats_triggered()
+{
+ Q3DSView *view = viewer();
+ if (!view)
+ return;
+
+ view->viewerSettings()->setShowRenderStats(!view->viewerSettings()->isShowRenderStats());
+ updateUI();
+}
+
+void MainWindow::on_actionQuit_triggered()
+{
+ delete m_studio3D;
+ m_studio3D = 0;
+ close();
+}
+
+void MainWindow::on_actionOpen_triggered()
+{
+ QSettings settings;
+ if (m_openFileDir.size() == 0) {
+ m_openFileDir
+ = settings.value("DirectoryOfLastOpen", QString("")).toString();
+ }
+
+ QString filename = QFileDialog::getOpenFileName(
+ this, tr("Open File or Project"), m_openFileDir,
+ tr("All supported formats (*.uip *.uia *.uiab);;Studio UI Presentation "
+ "(*.uip);;Application file (*.uia);;Binary Application (*.uiab)"),
+ NULL, QFileDialog::DontUseNativeDialog);
+
+ if (filename.size() == 0)
+ return;
+
+ QFileInfo theInfo(filename);
+ m_openFileDir = theInfo.path();
+ settings.setValue("DirectoryOfLastOpen", m_openFileDir);
+
+ loadFile(filename);
+}
+
+void MainWindow::on_actionConnect_triggered()
+{
+ if (m_remoteProject) {
+ delete m_remoteProject;
+ m_remoteProject = 0;
+ delete m_connectionInfo;
+ m_connectionInfo = 0;
+ if (m_studio3D)
+ m_studio3D->setVisible(true);
+
+ updateUI();
+ return;
+ }
+
+ m_remoteProject = new RemoteProject(this);
+ if (!m_remoteProject->startServer()) {
+ QString msg = "Unable to connect to remote project.\n";
+ QMessageBox::warning(this, "Connection Error", msg, QMessageBox::Close);
+ delete m_remoteProject;
+ m_remoteProject = 0;
+ updateUI();
+ return;
+ }
+
+ int port = m_remoteProject->serverPort();
+ QString message;
+ QTextStream stream(&message);
+ stream << "Connection Info\n"
+ << "Address: " << m_remoteProject->hostAddress().toString() << "\n"
+ << "Port: " + QString::number(port);
+
+ QQmlEngine *engine = ui->quickWidget->engine();
+ QQuickItem *root = ui->quickWidget->rootObject();
+
+ QByteArray qml = "import QtQuick 2.7\n"
+ "import QtQuick.Controls 2.2\n"
+ "Label {\n"
+ " color: \"White\"\n"
+ " horizontalAlignment: Text.AlignHCenter\n"
+ " verticalAlignment: Text.AlignVCenter\n"
+ " anchors.fill: parent\n"
+ " font.pixelSize: 42\n"
+ "}";
+
+ QQmlComponent component(engine);
+ component.setData(qml, QUrl());
+
+ if (component.isError()) {
+ qCritical() << "error" << component.errors();
+ return;
+ }
+
+ m_connectionInfo = qobject_cast<QQuickItem *>(component.create());
+ m_connectionInfo->setProperty("text", message);
+
+ QQmlEngine::setObjectOwnership(m_connectionInfo, QQmlEngine::CppOwnership);
+ m_connectionInfo->setParentItem(root);
+ m_connectionInfo->setParent(engine);
+
+ connect(m_remoteProject, &RemoteProject::remoteConnected,
+ this, &MainWindow::remoteConnected);
+
+ connect(m_remoteProject, &RemoteProject::remoteDisconnected,
+ this, &MainWindow::remoteDisconnected);
+
+ connect(m_remoteProject, &RemoteProject::projectChanged,
+ this, &MainWindow::loadRemoteProject);
+
+ updateUI();
+}
+
+void MainWindow::on_actionReload_triggered()
+{
+ if (Q3DSView *view = viewer()) {
+ view->reset();
+ updateUI();
+ }
+}
+
+Q3DSView *MainWindow::viewer() const
+{
+ return dynamic_cast<Q3DSView *>(m_studio3D);
+}
+
+void MainWindow::loadFile(const QString &filename)
+{
+ QFileInfo fileInfo(filename);
+ if (!fileInfo.exists())
+ return;
+
+ QUrl sourceUrl = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+
+ if (m_studio3D) {
+ viewer()->presentation()->setSource(sourceUrl);
+ return;
+ }
+
+ QQmlEngine *engine = ui->quickWidget->engine();
+ QQuickItem *root = ui->quickWidget->rootObject();
+
+ QByteArray qml = "import QtStudio3D 1.0\n"
+ "Studio3D {\n"
+ " id: studio3D\n"
+ " anchors.fill: parent\n"
+ " focus: true\n"
+ "}";
+
+ QQmlComponent component(engine);
+ component.setData(qml, QUrl());
+
+ if (component.isError()) {
+ qDebug() << "error" << component.errors();
+ return;
+ }
+
+ m_studio3D = qobject_cast<QQuickItem *>(component.create());
+ viewer()->presentation()->setSource(sourceUrl);
+
+ QQmlEngine::setObjectOwnership(m_studio3D, QQmlEngine::CppOwnership);
+ m_studio3D->setParentItem(root);
+ m_studio3D->setParent(engine);
+
+#ifdef Q_OS_ANDROID
+ // We have custom mouse event handling in android
+ viewer()->setIgnoreEvents(true, false, false);
+#endif
+
+ updateUI();
+}
+
+void MainWindow::on_actionCenter_triggered()
+{
+ if (Q3DSView *view = viewer()) {
+ view->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeCenter);
+ updateUI();
+ }
+}
+
+void MainWindow::on_actionScale_To_Fit_triggered()
+{
+ if (Q3DSView *view = viewer()) {
+ view->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ updateUI();
+ }
+}
+
+void MainWindow::on_actionScale_To_Fill_triggered()
+{
+ if (Q3DSView *view = viewer()) {
+ view->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ updateUI();
+ }
+}
+
+QString MainWindow::convertMimeDataToFilename(const QMimeData *mimeData)
+{
+ if (mimeData->hasUrls()) {
+ for (const QUrl &url : mimeData->urls()) {
+ QString str = url.toLocalFile();
+ if (str.isEmpty() == false) {
+ if ((QFileInfo(str).suffix() == "uip")
+ || (QFileInfo(str).suffix() == "uia")
+ || (QFileInfo(str).suffix() == "uiab"))
+ {
+ return str;
+ }
+ }
+ }
+ }
+ return QString();
+}
+
+void MainWindow::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (convertMimeDataToFilename(event->mimeData()).isEmpty() == false)
+ event->acceptProposedAction();
+}
+
+void MainWindow::dropEvent(QDropEvent *event)
+{
+ QString fileName = convertMimeDataToFilename(event->mimeData());
+ if (fileName.isEmpty() == false)
+ loadFile(fileName);
+}
+
+void MainWindow::showEvent(QShowEvent *event)
+{
+ QMainWindow::showEvent(event);
+ QSettings settings(QCoreApplication::organizationName(),
+ QCoreApplication::applicationName());
+ restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
+ restoreState(settings.value("mainWindowState").toByteArray());
+ updateUI();
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ QSettings settings(QCoreApplication::organizationName(),
+ QCoreApplication::applicationName());
+ settings.setValue("mainWindowGeometry", saveGeometry());
+ settings.setValue("mainWindowState", saveState());
+ QMainWindow::closeEvent(event);
+}
+
+#ifdef Q_OS_ANDROID
+void MainWindow::mousePressEvent(QMouseEvent *event)
+{
+ m_swipeStart = event->pos();
+
+ Q3DSView *view = viewer();
+ if (view)
+ view->presentation()->mousePressEvent(event);
+
+ event->accept();
+}
+
+void MainWindow::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q3DSView *view = viewer();
+ if (view)
+ view->presentation()->mouseReleaseEvent(event);
+
+ event->accept();
+}
+
+void MainWindow::mouseMoveEvent(QMouseEvent *event)
+{
+ // Fake swipe down event, as SwipeGesture doesn't work (unless you use 3 fingers..)
+ int swipeLength = height() / 10;
+ if (ui->actionFull_Screen->isChecked() && event->pos().y() > m_swipeStart.y() + swipeLength) {
+ ui->actionFull_Screen->setChecked(false);
+ on_actionFull_Screen_triggered();
+ }
+
+ Q3DSView *view = viewer();
+ if (view)
+ view->presentation()->mouseMoveEvent(event);
+
+ event->accept();
+}
+#endif
+
+void MainWindow::updateUI()
+{
+ ui->actionConnect->setChecked(m_remoteProject);
+
+ if (m_remoteProject) {
+ if (m_connectionInfo)
+ m_connectionInfo->setVisible(!m_remoteProject->isConnected());
+ if (m_studio3D)
+ m_studio3D->setVisible(m_remoteProject->isConnected());
+ }
+
+ Q3DSView *view = viewer();
+ if (!view)
+ return;
+
+ Q3DSViewerSettings::ScaleMode scaleMode = view->viewerSettings()->scaleMode();
+ ui->actionCenter->setChecked(scaleMode == Q3DSViewerSettings::ScaleModeCenter);
+ ui->actionScale_To_Fit->setChecked(scaleMode == Q3DSViewerSettings::ScaleModeFit);
+ ui->actionScale_To_Fill->setChecked(scaleMode == Q3DSViewerSettings::ScaleModeFill);
+
+ QColor matte = view->viewerSettings()->matteColor();
+ ui->actionBorder->setChecked(matte.isValid() && matte != QColor(Qt::black));
+ ui->actionShowOnScreenStats->setChecked(view->viewerSettings()->isShowRenderStats());
+}
+
+void MainWindow::loadRemoteProject()
+{
+ Q_ASSERT(m_remoteProject);
+ const QString remote = m_remoteProject->fileName();
+ loadFile(remote);
+ updateUI();
+}
+
+void MainWindow::remoteConnected()
+{
+ updateUI();
+}
+
+void MainWindow::remoteDisconnected()
+{
+ updateUI();
+}
diff --git a/src/Viewer/Qt3DViewer/mainwindow.h b/src/Viewer/Qt3DViewer/mainwindow.h
new file mode 100644
index 00000000..2e41a9fb
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/mainwindow.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtWidgets/QMainWindow>
+#include <QtQuickWidgets/QQuickWidget>
+
+#include "remoteproject.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+class MainWindow;
+}
+class QMimeData;
+class Q3DSView;
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+
+ void loadFile(const QString &filename);
+ void loadProject(const QByteArray &data);
+
+protected:
+ void dragEnterEvent(QDragEnterEvent *event) override;
+ void dropEvent(QDropEvent *event) override;
+ void showEvent(QShowEvent *event) override;
+ void closeEvent(QCloseEvent *event) override;
+#ifdef Q_OS_ANDROID
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+#endif
+
+private:
+ Q3DSView *viewer() const;
+ QString convertMimeDataToFilename(const QMimeData *mimeData);
+
+private Q_SLOTS:
+ void on_actionBorder_triggered();
+ void on_actionFull_Screen_triggered();
+ void on_actionShowOnScreenStats_triggered();
+ void on_actionQuit_triggered();
+ void on_actionOpen_triggered();
+ void on_actionConnect_triggered();
+ void on_actionReload_triggered();
+ void on_actionCenter_triggered();
+ void on_actionScale_To_Fit_triggered();
+ void on_actionScale_To_Fill_triggered();
+
+ void updateUI();
+
+ void loadRemoteProject();
+ void remoteConnected();
+ void remoteDisconnected();
+
+private:
+ Ui::MainWindow *ui;
+ QQuickItem *m_studio3D = nullptr;
+ QQuickItem *m_connectionInfo = nullptr;
+ QString m_openFileDir;
+ bool m_embeddedMode;
+ QPoint m_swipeStart;
+ RemoteProject *m_remoteProject = nullptr;
+};
+
+#endif // MAINWINDOW_H
diff --git a/src/Viewer/Qt3DViewer/mainwindow.ui b/src/Viewer/Qt3DViewer/mainwindow.ui
new file mode 100644
index 00000000..863f9cef
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/mainwindow.ui
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1042</width>
+ <height>556</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qt 3D Viewer</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="Viewer.qrc">
+ <normaloff>:/resources/images/viewer_icon.png</normaloff>:/resources/images/viewer_icon.png</iconset>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QQuickWidget" name="quickWidget">
+ <property name="resizeMode">
+ <enum>QQuickWidget::SizeRootObjectToView</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1042</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>File</string>
+ </property>
+ <addaction name="actionOpen"/>
+ <addaction name="actionConnect"/>
+ <addaction name="actionReload"/>
+ <addaction name="separator"/>
+ <addaction name="actionQuit"/>
+ </widget>
+ <widget class="QMenu" name="menuView">
+ <property name="title">
+ <string>View</string>
+ </property>
+ <widget class="QMenu" name="menuScale_Mode">
+ <property name="toolTip">
+ <string>Set application scale mode (-scalemode [center,fit,fill] command line parameter)</string>
+ </property>
+ <property name="title">
+ <string>Scale Mode</string>
+ </property>
+ <addaction name="actionCenter"/>
+ <addaction name="actionScale_To_Fit"/>
+ <addaction name="actionScale_To_Fill"/>
+ </widget>
+ <addaction name="actionBorder"/>
+ <addaction name="menuScale_Mode"/>
+ <addaction name="actionFull_Screen"/>
+ <addaction name="actionShowOnScreenStats"/>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuView"/>
+ </widget>
+ <action name="actionQuit">
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ </action>
+ <action name="actionFull_Screen">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Full Screen</string>
+ </property>
+ <property name="shortcut">
+ <string>F11</string>
+ </property>
+ </action>
+ <action name="actionBorder">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Matte</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="actionShowOnScreenStats">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Show Render Statistics</string>
+ </property>
+ <property name="shortcut">
+ <string>F1</string>
+ </property>
+ <property name="visible">
+ <bool>true</bool>
+ </property>
+ </action>
+ <action name="actionOpen">
+ <property name="text">
+ <string>Open...</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="actionConnect">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Connect</string>
+ </property>
+ </action>
+ <action name="actionReload">
+ <property name="text">
+ <string>Reload</string>
+ </property>
+ </action>
+ <action name="actionCenter">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Center</string>
+ </property>
+ <property name="toolTip">
+ <string>Center content and use design dimensions</string>
+ </property>
+ </action>
+ <action name="actionScale_To_Fit">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Scale To Fit</string>
+ </property>
+ <property name="toolTip">
+ <string>Fit content to available space but maintain aspect ratio</string>
+ </property>
+ </action>
+ <action name="actionScale_To_Fill">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Scale To Fill</string>
+ </property>
+ <property name="toolTip">
+ <string>Use entire screen space for content, changing aspect ratio as necessary</string>
+ </property>
+ </action>
+ <action name="actionToggle_Scale_Mode">
+ <property name="text">
+ <string>Toggle Scale Mode</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle between the various scale modes</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+S</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>QQuickWidget</class>
+ <extends>QWidget</extends>
+ <header>QtQuickWidgets/QQuickWidget</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="Viewer.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/Viewer/Qt3DViewer/remoteproject.cpp b/src/Viewer/Qt3DViewer/remoteproject.cpp
new file mode 100644
index 00000000..24a12f31
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/remoteproject.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "remoteproject.h"
+
+#include <QtNetwork>
+#include <QtWidgets/qinputdialog.h>
+
+RemoteProject::RemoteProject(QWidget *parent)
+ : QObject(parent)
+ , m_mainWindow(parent)
+ , m_tcpServer(0)
+ , m_connection(0)
+ , m_temporaryDir(0)
+ , m_serverPort(36000)
+{
+ m_incoming.setVersion(QDataStream::Qt_5_8);
+ m_serverPort = QInputDialog::getInt(m_mainWindow, tr("Connection Info"),
+ tr("Enter IP Port:"), m_serverPort);
+}
+
+RemoteProject::~RemoteProject()
+{
+ delete m_temporaryDir;
+ m_temporaryDir = 0;
+}
+
+bool RemoteProject::startServer()
+{
+ if (m_tcpServer)
+ return true;
+
+ m_tcpServer = new QTcpServer(this);
+ if (!m_tcpServer->listen(QHostAddress::Any, m_serverPort)) {
+ qWarning() << "Can't start the remote connection: "
+ << m_tcpServer->errorString();
+ delete m_tcpServer;
+ m_tcpServer = 0;
+ return false;
+ }
+
+ QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
+ // use the first non-localhost IPv4 address
+ for (int i = 0; i < ipAddressesList.size(); ++i) {
+ if (ipAddressesList.at(i) != QHostAddress::LocalHost
+ && ipAddressesList.at(i).toIPv4Address()) {
+ m_hostAddress = ipAddressesList.at(i);
+ break;
+ }
+ }
+
+ // if we did not find one, use IPv4 localhost
+ if (m_hostAddress.isNull())
+ m_hostAddress = QHostAddress(QHostAddress::LocalHost);
+
+ m_serverPort = m_tcpServer->serverPort();
+ connect(m_tcpServer, SIGNAL(newConnection()),
+ this, SLOT(acceptRemoteConnection()));
+ return true;
+}
+
+void RemoteProject::acceptRemoteConnection()
+{
+ Q_ASSERT(m_tcpServer);
+ Q_ASSERT(!m_connection);
+ m_connection = m_tcpServer->nextPendingConnection();
+ Q_ASSERT(m_connection);
+
+ m_incoming.setDevice(m_connection);
+
+ connect(m_connection, SIGNAL(disconnected()),
+ this, SLOT(acceptRemoteDisconnection()));
+
+ connect(m_connection, SIGNAL(readyRead()),
+ this, SLOT(readProject()));
+
+ Q_EMIT(remoteConnected());
+}
+
+void RemoteProject::acceptRemoteDisconnection()
+{
+ Q_ASSERT(m_tcpServer);
+ Q_ASSERT(m_connection);
+ m_connection->deleteLater();
+ m_connection = 0;
+
+ m_incoming.setDevice(0);
+
+ Q_EMIT(remoteDisconnected());
+}
+
+void RemoteProject::readProject()
+{
+ m_incoming.startTransaction();
+
+ int totalBytes = 0;
+ m_incoming >> totalBytes;
+
+ if (m_connection->bytesAvailable() < totalBytes) {
+ m_incoming.rollbackTransaction();
+ return;
+ }
+
+ int numberOfFiles = 0;
+ QString projectFile;
+ m_incoming >> numberOfFiles;
+ m_incoming >> projectFile;
+
+ QVector<QPair<QString, QByteArray> > files;
+ for (int i = 0; i < numberOfFiles; ++i) {
+ QString fileName;
+ QByteArray fileContents;
+ m_incoming >> fileName;
+ m_incoming >> fileContents;
+ files.append(qMakePair(fileName, fileContents));
+ }
+
+ if (!m_incoming.commitTransaction()) {
+ m_incoming.abortTransaction();
+ qWarning() << "Error transferring remote project in one payload";
+ return;
+ }
+
+ delete m_temporaryDir;
+ m_temporaryDir = new QTemporaryDir;
+ Q_ASSERT(m_temporaryDir->isValid());
+
+ for (const auto &file : qAsConst(files)) {
+ QString filePath = m_temporaryDir->path() + QDir::separator() + file.first;
+ QFile tmpFile(filePath);
+ QDir tmpFileDir = QFileInfo(tmpFile).absoluteDir();
+ if (!tmpFileDir.exists())
+ tmpFileDir.mkpath(".");
+ if (!tmpFile.open(QIODevice::WriteOnly)) {
+ delete m_temporaryDir;
+ m_temporaryDir = 0;
+ qWarning() << "Error opening temporary file for remote project:"
+ << filePath;
+ return;
+ }
+
+ if (file.first == projectFile)
+ m_projectFile = filePath;
+
+ tmpFile.write(file.second);
+ tmpFile.close();
+ }
+
+ Q_EMIT(projectChanged());
+}
diff --git a/src/Viewer/Qt3DViewer/remoteproject.h b/src/Viewer/Qt3DViewer/remoteproject.h
new file mode 100644
index 00000000..d11ce216
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/remoteproject.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef REMOTEPROJECT_H
+#define REMOTEPROJECT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qtemporarydir.h>
+#include <QtNetwork/qtcpserver.h>
+#include <QtWidgets/qwidget.h>
+
+class RemoteProject : public QObject
+{
+ Q_OBJECT
+public:
+ explicit RemoteProject(QWidget *parent);
+ ~RemoteProject();
+
+ bool startServer();
+
+ QHostAddress hostAddress() const { return m_hostAddress; }
+ int serverPort() const { return m_serverPort; }
+ void setServerPort(int port) { m_serverPort = port; }
+ bool isConnected() const { return m_connection; }
+ QString fileName() const { return m_projectFile; }
+
+Q_SIGNALS:
+ void projectChanged();
+ void remoteConnected();
+ void remoteDisconnected();
+
+private Q_SLOTS:
+ void acceptRemoteConnection();
+ void acceptRemoteDisconnection();
+ void readProject();
+
+private:
+ QWidget *m_mainWindow = nullptr;
+ QTcpServer *m_tcpServer = nullptr;
+ QTcpSocket *m_connection = nullptr;
+ QHostAddress m_hostAddress;
+ QDataStream m_incoming;
+ QTemporaryDir *m_temporaryDir = nullptr;
+ QString m_projectFile;
+ int m_serverPort;
+};
+
+#endif // REMOTEPROJECT_H
diff --git a/src/Viewer/Qt3DViewer/resources/images/Viewer.ico b/src/Viewer/Qt3DViewer/resources/images/Viewer.ico
new file mode 100644
index 00000000..09d91c78
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/Viewer.ico
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/ViewerDoc.ico b/src/Viewer/Qt3DViewer/resources/images/ViewerDoc.ico
new file mode 100644
index 00000000..02779b0d
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/ViewerDoc.ico
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/viewer_icon.png b/src/Viewer/Qt3DViewer/resources/images/viewer_icon.png
new file mode 100644
index 00000000..312e9b10
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/viewer_icon.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/style/checkbox.png b/src/Viewer/Qt3DViewer/resources/style/checkbox.png
new file mode 100644
index 00000000..b4a9aa3b
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/style/checkbox.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/style/dark.qss b/src/Viewer/Qt3DViewer/resources/style/dark.qss
new file mode 100644
index 00000000..f3f9b329
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/style/dark.qss
@@ -0,0 +1,459 @@
+QToolTip
+{
+ border: 1px solid black;
+ background-color: #ffa02f;
+ padding: 1px;
+ border-radius: 3px;
+ opacity: 100;
+}
+
+QWidget
+{
+ color: #b1b1b1;
+ background-color: #323232;
+}
+
+QWidget:item:hover
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #ca0619);
+ color: #000000;
+}
+
+QWidget:item:selected
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QMenuBar::item
+{
+ background: transparent;
+}
+
+QMenuBar::item:selected
+{
+ background: transparent;
+ border: 1px solid #ffaa00;
+}
+
+QMenuBar::item:pressed
+{
+ background: #444;
+ border: 1px solid #000;
+ background-color: QLinearGradient(
+ x1:0, y1:0,
+ x2:0, y2:1,
+ stop:1 #212121,
+ stop:0.4 #343434/*,
+ stop:0.2 #343434,
+ stop:0.1 #ffaa00*/
+ );
+ margin-bottom:-1px;
+ padding-bottom:1px;
+}
+
+QMenu
+{
+ border: 1px solid #000;
+}
+
+QMenu::item
+{
+ padding: 4px 20px 4px 20px;
+}
+
+QMenu::item:selected
+{
+ color: #000000;
+}
+
+QWidget:disabled
+{
+ color: #404040;
+ background-color: #323232;
+}
+
+QAbstractItemView
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0.1 #646464, stop: 1 #5d5d5d);
+}
+
+QWidget:focus
+{
+ /*border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);*/
+}
+
+QLineEdit
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4d4d4d, stop: 0 #646464, stop: 1 #5d5d5d);
+ padding: 1px;
+ border-style: solid;
+ border: 1px solid #1e1e1e;
+ border-radius: 5;
+}
+
+QPushButton
+{
+ color: #b1b1b1;
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
+ border-width: 1px;
+ border-color: #1e1e1e;
+ border-style: solid;
+ border-radius: 6;
+ padding: 3px;
+ font-size: 12px;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+QPushButton:pressed
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
+}
+
+QComboBox
+{
+ selection-background-color: #ffaa00;
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
+ border-style: solid;
+ border: 1px solid #1e1e1e;
+ border-radius: 5;
+}
+
+QComboBox:hover,QPushButton:hover
+{
+ border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+
+QComboBox:on
+{
+ padding-top: 3px;
+ padding-left: 4px;
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
+ selection-background-color: #ffaa00;
+}
+
+QComboBox QAbstractItemView
+{
+ border: 2px solid darkgray;
+ selection-background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QComboBox::drop-down
+{
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 15px;
+
+ border-left-width: 0px;
+ border-left-color: darkgray;
+ border-left-style: solid; /* just a single line */
+ border-top-right-radius: 3px; /* same radius as the QComboBox */
+ border-bottom-right-radius: 3px;
+ }
+
+QComboBox::down-arrow
+{
+ image: url(:/resources/style/down_arrow.png);
+}
+
+QGroupBox:focus
+{
+ border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QTextEdit:focus
+{
+ border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+}
+
+QScrollBar:horizontal {
+ border: 1px solid #222222;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);
+ height: 7px;
+ margin: 0px 16px 0 16px;
+}
+
+QScrollBar::handle:horizontal
+{
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);
+ min-height: 20px;
+ border-radius: 2px;
+}
+
+QScrollBar::add-line:horizontal {
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);
+ width: 14px;
+ subcontrol-position: right;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal {
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #ffa02f, stop: 1 #d7801a);
+ width: 14px;
+ subcontrol-position: left;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::right-arrow:horizontal, QScrollBar::left-arrow:horizontal
+{
+ border: 1px solid black;
+ width: 1px;
+ height: 1px;
+ background: white;
+}
+
+QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
+{
+ background: none;
+}
+
+QScrollBar:vertical
+{
+ background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0.0 #121212, stop: 0.2 #282828, stop: 1 #484848);
+ width: 7px;
+ margin: 16px 0 16px 0;
+ border: 1px solid #222222;
+}
+
+QScrollBar::handle:vertical
+{
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 0.5 #d7801a, stop: 1 #ffa02f);
+ min-height: 20px;
+ border-radius: 2px;
+}
+
+QScrollBar::add-line:vertical
+{
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a);
+ height: 14px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:vertical
+{
+ border: 1px solid #1b1b19;
+ border-radius: 2px;
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #d7801a, stop: 1 #ffa02f);
+ height: 14px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
+{
+ border: 1px solid black;
+ width: 1px;
+ height: 1px;
+ background: white;
+}
+
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
+{
+ background: none;
+}
+
+QTextEdit
+{
+ background-color: #242424;
+}
+
+QPlainTextEdit
+{
+ background-color: #242424;
+}
+
+QHeaderView::section
+{
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, stop: 0.6 #434343, stop:1 #656565);
+ color: white;
+ padding-left: 4px;
+ border: 1px solid #6c6c6c;
+}
+
+QCheckBox:disabled
+{
+color: #414141;
+}
+
+QDockWidget::title
+{
+ padding-left: 10px;
+ spacing: 3px; /* spacing between items in the tool bar */
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);
+}
+
+QDockWidget::close-button, QDockWidget::float-button
+{
+ text-align: center;
+ spacing: 1px; /* spacing between items in the tool bar */
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #323232, stop: 0.5 #242424, stop:1 #323232);
+}
+
+QDockWidget::close-button:hover, QDockWidget::float-button:hover
+{
+ background: #242424;
+}
+
+QDockWidget::close-button:pressed, QDockWidget::float-button:pressed
+{
+ padding: 1px -1px -1px 1px;
+}
+
+QMainWindow::separator
+{
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);
+ color: white;
+ padding-left: 4px;
+ border: 1px solid #4c4c4c;
+ spacing: 3px; /* spacing between items in the tool bar */
+}
+
+QMainWindow::separator:hover
+{
+
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #d7801a, stop:0.5 #b56c17 stop:1 #ffa02f);
+ color: white;
+ padding-left: 4px;
+ border: 1px solid #6c6c6c;
+ spacing: 3px; /* spacing between items in the tool bar */
+}
+
+QToolBar::handle
+{
+ spacing: 3px; /* spacing between items in the tool bar */
+ background: url(:/resources/style/handle.png);
+}
+
+QMenu::separator
+{
+ height: 2px;
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:0 #161616, stop: 0.5 #151515, stop: 0.6 #212121, stop:1 #343434);
+ color: white;
+ padding-left: 4px;
+ margin-left: 10px;
+ margin-right: 5px;
+}
+
+QProgressBar
+{
+ border: 2px solid grey;
+ border-radius: 5px;
+ text-align: center;
+}
+
+QProgressBar::chunk
+{
+ background-color: #d7801a;
+ width: 2.15px;
+ margin: 0.5px;
+}
+
+QTabBar::tab {
+ color: #b1b1b1;
+ border: 1px solid #444;
+ border-bottom-style: none;
+ background-color: #323232;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ margin-right: -1px;
+}
+
+QTabWidget::pane {
+ border: 1px solid #444;
+ top: 1px;
+}
+
+QTabBar::tab:last
+{
+ margin-right: 0; /* the last selected tab has nothing to overlap with on the right */
+ border-top-right-radius: 3px;
+}
+
+QTabBar::tab:first:!selected
+{
+ margin-left: 0px; /* the last selected tab has nothing to overlap with on the right */
+
+
+ border-top-left-radius: 3px;
+}
+
+QTabBar::tab:!selected
+{
+ color: #b1b1b1;
+ border-bottom-style: solid;
+ margin-top: 3px;
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
+}
+
+QTabBar::tab:selected
+{
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ margin-bottom: 0px;
+}
+
+QTabBar::tab:!selected:hover
+{
+ /*border-top: 2px solid #ffaa00;
+ padding-bottom: 3px;*/
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434, stop:0.2 #343434, stop:0.1 #ffaa00);
+}
+
+QRadioButton::indicator:checked, QRadioButton::indicator:unchecked{
+ color: #b1b1b1;
+ background-color: #323232;
+ border: 1px solid #b1b1b1;
+ border-radius: 6px;
+}
+
+QRadioButton::indicator:checked
+{
+ background-color: qradialgradient(
+ cx: 0.5, cy: 0.5,
+ fx: 0.5, fy: 0.5,
+ radius: 1.0,
+ stop: 0.25 #ffaa00,
+ stop: 0.3 #323232
+ );
+}
+
+QCheckBox::indicator{
+ color: #b1b1b1;
+ background-color: #323232;
+ border: 1px solid #b1b1b1;
+ width: 9px;
+ height: 9px;
+}
+
+QRadioButton::indicator
+{
+ border-radius: 6px;
+}
+
+QRadioButton::indicator:hover, QCheckBox::indicator:hover
+{
+ border: 1px solid #ffaa00;
+}
+
+QCheckBox::indicator:checked
+{
+ image:url(:/resources/style/checkbox.png);
+}
+
+QCheckBox::indicator:disabled, QRadioButton::indicator:disabled
+{
+ border: 1px solid #444;
+}
diff --git a/src/Viewer/Qt3DViewer/resources/style/down_arrow.png b/src/Viewer/Qt3DViewer/resources/style/down_arrow.png
new file mode 100644
index 00000000..db581cb7
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/style/down_arrow.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/style/handle.png b/src/Viewer/Qt3DViewer/resources/style/handle.png
new file mode 100644
index 00000000..fd50400f
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/style/handle.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt b/src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt
new file mode 100644
index 00000000..59afadae
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt
@@ -0,0 +1,81 @@
+_ENV
+_VERSION
+assert
+break
+calculateBoundingbox
+calculateGlobalTransform
+collectgarbage
+dofile
+else
+elseif
+error
+fireEvent
+fireEventOnPresentation
+fireFlowEvent
+function
+getAttribute
+getChildren
+getcurrentSlide
+getElapsedTime
+getElement
+getElementType
+getfenv
+getmetatable
+getMousePosition
+getScreenInfo
+getTime
+goToBackSlide
+goToNextSlide
+goToPreviousSlide
+goToSlide
+goToTime
+hasAttribute
+io.stderr
+io.stdin
+io.stdout
+ipairs
+load
+loadfile
+loadstring
+local
+math.huge
+math.pi
+measureText
+module
+next
+output
+package.config
+package.cpath
+package.loaded
+package.loaders
+package.path
+package.preload
+package.searchers
+pairs
+payse
+pcall
+play
+print
+rawequal
+rawget
+rawlen
+rawset
+registerForChange
+registerForEvent
+repeat
+require
+return
+select
+self
+setAttribute
+setfenv
+setmetatable
+then
+tonumber
+tostring
+type
+unpack
+unregisterForEvent
+until
+while
+xpcall \ No newline at end of file
diff --git a/src/Viewer/Qt3DViewer/viewer.qml b/src/Viewer/Qt3DViewer/viewer.qml
new file mode 100644
index 00000000..32025907
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/viewer.qml
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.7
+import QtQuick.Controls 2.2
+import QtStudio3D 1.0
+
+Rectangle {
+ id: window
+ visible: true
+ color: "black"
+}
diff --git a/src/Viewer/Viewer.pro b/src/Viewer/Viewer.pro
new file mode 100644
index 00000000..66a20a99
--- /dev/null
+++ b/src/Viewer/Viewer.pro
@@ -0,0 +1,9 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS += \
+ studio3d \
+ qmlviewer
+
+!boot2qt:!integrity {
+ SUBDIRS += Qt3DViewer
+}
diff --git a/src/Viewer/qmlviewer/Qt3DSRenderer.cpp b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp
new file mode 100644
index 00000000..51e2f9e9
--- /dev/null
+++ b/src/Viewer/qmlviewer/Qt3DSRenderer.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (c) 2016 NVIDIA CORPORATION.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderer.h"
+#include "UICViewerApp.h"
+#include "UICAudioPlayerImpl.h"
+
+#include <QtStudio3D/private/q3dscommandqueue_p.h>
+#include <QtStudio3D/private/q3dsviewersettings_p.h>
+#include <QtStudio3D/private/q3dspresentation_p.h>
+#include <QtStudio3D/private/studioutils_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtQuick/qquickwindow.h>
+
+using namespace UICViewer;
+
+QT_BEGIN_NAMESPACE
+
+Q3DSRenderer::Q3DSRenderer(bool visibleFlag, uic::UICAssetVisitor *assetVisitor)
+ : m_visibleFlag(visibleFlag)
+ , m_initElements(false)
+ , m_runtime(0)
+ , m_window(nullptr)
+ , m_initialized(false)
+ , m_visitor(assetVisitor)
+ , m_settings(new Q3DSViewerSettings(this))
+ , m_presentation(new Q3DSPresentation(this))
+{
+}
+
+Q3DSRenderer::~Q3DSRenderer()
+{
+ releaseRuntime();
+}
+
+QOpenGLFramebufferObject *Q3DSRenderer::createFramebufferObject(const QSize &size)
+{
+ QOpenGLFramebufferObjectFormat theFormat;
+ theFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObject *frameBuffer =
+ new QOpenGLFramebufferObject(size, theFormat);
+ if (m_runtime && m_runtime->IsInitialised())
+ m_runtime->setOffscreenId(frameBuffer->handle());
+ return frameBuffer;
+}
+
+/** Pull pending commands from the plugin.
+ * Invoked automatically by the QML scene graph.
+ *
+ * This is the only place where it is valid for the Q3DSView plugin and render to communicate.
+ */
+void Q3DSRenderer::synchronize(QQuickFramebufferObject *inView)
+{
+ // Passing m_InitElements here is a bit of a hack to easily set the flag on the plugin.
+ static_cast<Q3DSView *>(inView)->getCommands(m_initElements, m_commands);
+
+ if (m_commands.m_sourceChanged) {
+ releaseRuntime();
+ // Need to update source here rather than processCommands, as source is needed for init
+ m_presentation->setSource(m_commands.m_source);
+ m_initialized = false;
+ }
+
+ m_initElements = false;
+
+ // We need a handle to the window to be able to reset the GL state inside of Draw().
+ // See https://bugreports.qt.io/browse/QTBUG-47213
+ if (!m_window)
+ m_window = inView->window();
+}
+
+void Q3DSRenderer::releaseRuntime()
+{
+ m_settings->d_ptr->setViewerApp(nullptr);
+ m_presentation->d_ptr->setViewerApp(nullptr);
+
+ if (m_runtime) {
+ m_runtime->Release();
+ m_runtime = nullptr;
+ }
+}
+
+/** Invoked by the QML scene graph indicating that it's time to render.
+ * Calls `draw()` if the plugin is visible, or `processCommands()` otherwise.
+ *
+ * Note that this will still render if the plugin is opacity:0. To avoid this,
+ * add a line to your QML to hide the object when opacity is zero, like:
+ *
+ * visible: opacity != 0
+ */
+void Q3DSRenderer::render()
+{
+ // We may start in a non visible state but we still need
+ // to init the runtime otherwise the commands are never processed
+ if (!m_initialized)
+ m_initialized = initializeRuntime(this->framebufferObject());
+
+ // Don't render if the plugin is hidden; however, if hidden, but sure
+ // to process pending commands so we can be shown again.
+ if (m_visibleFlag)
+ draw();
+ else
+ processCommands();
+}
+
+/** Cause Qt3DS runtime to render content.
+ * Initializes GL and the runtime when called the first time.
+ */
+void Q3DSRenderer::draw()
+{
+ if (m_runtime && m_runtime->IsInitialised() && m_window) {
+ if (m_initialized)
+ m_runtime->RestoreState();
+ m_runtime->Render();
+ m_runtime->SaveState();
+
+ m_window->resetOpenGLState();
+ }
+}
+
+bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo)
+{
+ m_runtime = &UICViewerApp::Create(nullptr, new CUICAudioPlayerImpl());
+ Q_ASSERT(m_runtime);
+
+ int theWidth = inFbo->width();
+ int theHeight = inFbo->height();
+
+ const QString localSource = Q3DSUtils::urlToLocalFileOrQrc(m_presentation->source());
+
+ if (!m_runtime->InitializeApp(theWidth, theHeight, QOpenGLContext::currentContext()->format(),
+ inFbo->handle(), localSource, m_visitor)) {
+ releaseRuntime();
+ return false;
+ }
+
+ m_runtime->RegisterScriptCallback(UICViewer::ViewerCallbackType::Enum::CALLBACK_ON_INIT,
+ reinterpret_cast<qml_Function>(Q3DSRenderer::onInitHandler),
+ this);
+ m_runtime->RegisterScriptCallback(UICViewer::ViewerCallbackType::Enum::CALLBACK_ON_UPDATE,
+ reinterpret_cast<qml_Function>(Q3DSRenderer::onUpdateHandler),
+ this);
+
+ m_settings->d_ptr->setViewerApp(m_runtime);
+ m_presentation->d_ptr->setViewerApp(m_runtime, false);
+
+ // Connect signals
+ connect(m_runtime, &UICViewer::UICViewerApp::SigSlideEntered,
+ this, &Q3DSRenderer::enterSlide);
+ connect(m_runtime, &UICViewer::UICViewerApp::SigSlideExited,
+ this, &Q3DSRenderer::exitSlide);
+
+ return true;
+}
+
+/** Accept user commands (e.g. setAttribute) needed to initialize the code.
+ *
+ * If we attempt to run Qt3DS methods like setAttribute() before the runtime
+ * has been initialized, they will be lost. This method is the correct place
+ * to accept user commands.
+ *
+ * Currently this method just sets a flag needed to pass a flag to the
+ * plugin next time syncronize() is called, which eventually gets the plugin
+ * to emit an `runningChanged` signal the next time `tick()` is called.
+ * As a result, code specified in an `onRunningChanged` handler may be run
+ * after one or more frames have already rendered.
+ */
+void Q3DSRenderer::onInitHandler(void *userData)
+{
+ Q3DSRenderer *theRenderer = static_cast<Q3DSRenderer *>(userData);
+ theRenderer->setInitElements(true);
+}
+
+/** Accept the latest pending user commands (e.g. setAttribute).
+ *
+ * This method just calls `ProcessCommands` to avoid unnecessary
+ * pointer dereferencing and accessor methods (or public member variables).
+ */
+void Q3DSRenderer::onUpdateHandler(void *userData)
+{
+ Q3DSRenderer *theRenderer = static_cast<Q3DSRenderer *>(userData);
+ theRenderer->processCommands();
+}
+
+/** Apply commands queued up by the user (e.g. setAttribute).
+ *
+ * Note that these commands are executed even if the plugin is not visible,
+ * in part to allow changes to the visible flag to be noticed, but also
+ * to allow specialty code to continue to be queued up even when not rendering.
+ */
+void Q3DSRenderer::processCommands()
+{
+ if (!m_runtime)
+ return;
+
+ if (m_commands.m_visibleChanged)
+ m_visibleFlag = m_commands.m_visible;
+
+ if (QOpenGLFramebufferObject *inFbo = this->framebufferObject()) {
+ if (inFbo->isValid() && (inFbo->width() != m_runtime->GetWindowWidth()
+ || inFbo->height() != m_runtime->GetWindowHeight())) {
+ m_runtime->Resize(inFbo->width(), inFbo->height());
+ }
+ }
+
+ if (m_commands.m_scaleModeChanged)
+ m_settings->setScaleMode(m_commands.m_scaleMode);
+ if (m_commands.m_shadeModeChanged)
+ m_settings->setShadeMode(m_commands.m_shadeMode);
+ if (m_commands.m_matteColorChanged)
+ m_settings->setMatteColor(m_commands.m_matteColor);
+ if (m_commands.m_showRenderStatsChanged)
+ m_settings->setShowRenderStats(m_commands.m_showRenderStats);
+
+ if (m_commands.m_globalAnimationTimeChanged)
+ m_presentation->setGlobalAnimationTime(m_commands.m_globalAnimationTime);
+
+ // Send scene graph changes over to Q3DS
+ for (int i = 0; i < m_commands.size(); i++) {
+ const ElementCommand &cmd = m_commands.commandAt(i);
+ switch (cmd.m_commandType) {
+ case CommandType_SetAttribute:
+ m_presentation->setAttribute(cmd.m_elementPath, cmd.m_stringValue, cmd.m_variantValue);
+ break;
+ case CommandType_SetPresentationActive:
+ m_presentation->setPresentationActive(cmd.m_elementPath, cmd.m_boolValue);
+ break;
+ case CommandType_GoToTime:
+ m_presentation->goToTime(cmd.m_elementPath, cmd.m_floatValue);
+ break;
+ case CommandType_GoToSlide:
+ m_presentation->goToSlide(cmd.m_elementPath, cmd.m_intValues[0]);
+ break;
+ case CommandType_GoToSlideByName:
+ m_presentation->goToSlide(cmd.m_elementPath, cmd.m_stringValue);
+ break;
+ case CommandType_GoToSlideRelative:
+ m_presentation->goToSlide(cmd.m_elementPath, bool(cmd.m_intValues[0]),
+ bool(cmd.m_intValues[1]));
+ break;
+ case CommandType_FireEvent:
+ m_presentation->fireEvent(cmd.m_elementPath, cmd.m_stringValue);
+ break;
+ case CommandType_MousePress:
+ m_runtime->HandleMousePress(cmd.m_intValues[0],
+ cmd.m_intValues[1], cmd.m_intValues[2], true);
+ break;
+ case CommandType_MouseRelease:
+ m_runtime->HandleMousePress(cmd.m_intValues[0],
+ cmd.m_intValues[1], cmd.m_intValues[2], false);
+ break;
+ case CommandType_MouseMove:
+ m_runtime->HandleMouseMove(cmd.m_intValues[0], cmd.m_intValues[1], true);
+ break;
+ case CommandType_MouseWheel:
+ m_runtime->HandleMouseWheel(cmd.m_intValues[0], cmd.m_intValues[1],
+ bool(cmd.m_intValues[2]), cmd.m_intValues[3]);
+ break;
+ case CommandType_KeyPress:
+ m_runtime->HandleKeyInput(Q3DStudio::EKeyCode(cmd.m_intValues[0]), true);
+ break;
+ case CommandType_KeyRelease:
+ m_runtime->HandleKeyInput(Q3DStudio::EKeyCode(cmd.m_intValues[0]), false);
+ break;
+ case CommandType_RequestSlideInfo: {
+ int current = 0;
+ int previous = 0;
+ QString currentName;
+ QString previousName;
+ const QByteArray path(cmd.m_elementPath.toUtf8());
+ m_runtime->GetSlideInfo(path, current, previous, currentName, previousName);
+ QVariantList *requestData = new QVariantList();
+ requestData->append(QVariant(current));
+ requestData->append(QVariant(previous));
+ requestData->append(QVariant(currentName));
+ requestData->append(QVariant(previousName));
+
+ Q_EMIT requestResponse(cmd.m_elementPath, cmd.m_commandType, requestData);
+
+ break;
+ }
+ default:
+ qWarning() << __FUNCTION__ << "Unrecognized CommandType in command list!";
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/qmlviewer/Qt3DSRenderer.h b/src/Viewer/qmlviewer/Qt3DSRenderer.h
new file mode 100644
index 00000000..4f43c744
--- /dev/null
+++ b/src/Viewer/qmlviewer/Qt3DSRenderer.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (c) 2016 NVIDIA CORPORATION.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_RENDERER_H
+#define Q3DS_RENDERER_H
+
+#include <QtGui/qopenglframebufferobject.h>
+#include <QtQuick/qquickframebufferobject.h>
+
+#include "UICViewerApp.h"
+#include "Qt3DSView.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSViewerSettings;
+class Q3DSPresentation;
+
+class Q3DSRenderer : public QObject,
+ public QQuickFramebufferObject::Renderer
+{
+ Q_OBJECT
+
+public:
+ Q3DSRenderer(bool visibleFlag, uic::UICAssetVisitor *assetVisitor);
+ ~Q3DSRenderer();
+
+ QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
+
+ void setInitElements(bool inFlag) { m_initElements = inFlag; }
+ void processCommands();
+
+Q_SIGNALS:
+ void enterSlide(const QString &elementPath, unsigned int slide, const QString &slideName);
+ void exitSlide(const QString &elementPath, unsigned int slide, const QString &slideName);
+ void requestResponse(const QString &elementPath, CommandType commandType, void *requestData);
+
+protected:
+ static void onInitHandler(void *userData);
+ static void onUpdateHandler(void *userData);
+ bool initializeRuntime(QOpenGLFramebufferObject *inFbo);
+ void draw();
+ void render() override;
+ void synchronize(QQuickFramebufferObject *inView) override;
+ void releaseRuntime();
+
+protected:
+ bool m_visibleFlag; // Is the plugin visible? Prevents rendering hidden content.
+ CommandQueue m_commands; // A list of commands retrieved by the plugin to be applied.
+ bool m_initElements; // Flag set when the runtime is first ready to render.
+ UICViewer::UICViewerApp *m_runtime; // The Qt3DS viewer that renders all content.
+ QQuickWindow *m_window; // Window associated with the plugin; needed to reset OpenGL state.
+
+ bool m_initialized; // Has the runtime and OpenGL state been initialized?
+ uic::UICAssetVisitor *m_visitor;
+
+ Q3DSViewerSettings *m_settings;
+ Q3DSPresentation *m_presentation;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DS_RENDERER_H
diff --git a/src/Viewer/qmlviewer/Qt3DSView.cpp b/src/Viewer/qmlviewer/Qt3DSView.cpp
new file mode 100644
index 00000000..af11d61d
--- /dev/null
+++ b/src/Viewer/qmlviewer/Qt3DSView.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (c) 2016 NVIDIA CORPORATION.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSView.h"
+#include "Qt3DSRenderer.h"
+#include "q3dspresentationitem.h"
+
+#include <QtStudio3D/private/q3dsviewersettings_p.h>
+#include <QtStudio3D/private/q3dspresentation_p.h>
+#include <QtStudio3D/private/q3dssceneelement_p.h>
+#include <QtStudio3D/private/viewerqmlstreamproxy_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfileinfo.h>
+#include <QtQuick/qquickwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+Q3DSView::Q3DSView()
+ : m_viewerSettings(nullptr)
+ , m_presentation(nullptr)
+ , m_emitRunningChange(false)
+ , m_isRunning(false)
+ , m_ignoreMouseEvents(false)
+ , m_ignoreWheelEvents(false)
+ , m_ignoreKeyboardEvents(false)
+ , m_pixelRatio(1.0)
+{
+ setMirrorVertically(true);
+ connect(this, &Q3DSView::windowChanged, this, &Q3DSView::handleWindowChanged);
+ connect(this, &Q3DSView::visibleChanged, this, &Q3DSView::handleVisibleChanged);
+
+ setIgnoreEvents(false, false, false);
+}
+
+Q3DSView::~Q3DSView()
+{
+}
+
+Q3DSPresentationItem *Q3DSView::presentation() const
+{
+ return m_presentation;
+}
+
+Q3DSViewerSettings *Q3DSView::viewerSettings() const
+{
+ return m_viewerSettings;
+}
+
+void Q3DSView::setIgnoreEvents(bool mouse, bool wheel, bool keyboard)
+{
+ // TODO: It might be beneficial to have these as properties so they could be acceessed from QML
+ m_ignoreMouseEvents = mouse;
+ m_ignoreWheelEvents = wheel;
+ m_ignoreKeyboardEvents = keyboard;
+
+ if (mouse)
+ setAcceptedMouseButtons(Qt::NoButton);
+ else
+ setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton);
+ setAcceptHoverEvents(!mouse);
+}
+
+void Q3DSView::componentComplete()
+{
+ const auto childObjs = children();
+ for (QObject *child : childObjs) {
+ auto settings = qobject_cast<Q3DSViewerSettings *>(child);
+ if (settings) {
+ if (m_viewerSettings)
+ qWarning("Duplicate ViewerSettings defined for Studio3D.");
+ else
+ m_viewerSettings = settings;
+ }
+ auto presentation = qobject_cast<Q3DSPresentationItem *>(child);
+ if (presentation) {
+ if (m_presentation)
+ qWarning("Duplicate Presentation defined for Studio3D.");
+ else
+ m_presentation = presentation;
+ }
+ }
+
+ if (!m_viewerSettings)
+ m_viewerSettings = new Q3DSViewerSettings(this);
+ if (!m_presentation)
+ m_presentation = new Q3DSPresentationItem(this);
+
+ m_viewerSettings->d_ptr->setCommandQueue(&m_pendingCommands);
+ m_presentation->d_ptr->setCommandQueue(&m_pendingCommands);
+
+ QQuickFramebufferObject::componentComplete();
+}
+
+void Q3DSView::handleWindowChanged(QQuickWindow *window)
+{
+ if (!window)
+ return;
+
+ window->setClearBeforeRendering(false);
+ m_pixelRatio = window->devicePixelRatio();
+
+ // Call tick every frame of the GUI thread to notify QML about new frame via frameUpdate signal
+ connect(window, &QQuickWindow::afterAnimating, this, &Q3DSView::tick);
+ // Call update after the frame is handled to queue another frame
+ connect(window, &QQuickWindow::afterSynchronizing, this, &Q3DSView::update);
+}
+
+// Queue up a command to inform the renderer of a newly-changed visible/hidden status.
+void Q3DSView::handleVisibleChanged()
+{
+ m_pendingCommands.m_visibleChanged = true;
+ m_pendingCommands.m_visible = isVisible();
+}
+
+void Q3DSView::reset()
+{
+ // Fake a source change to trigger a reloading of the presentation
+ m_pendingCommands.m_sourceChanged = true;
+ m_pendingCommands.m_source = m_presentation->source();
+}
+
+void Q3DSView::requestResponseHandler(const QString &elementPath, CommandType commandType,
+ void *requestData)
+{
+ switch (commandType) {
+ case CommandType_RequestSlideInfo: {
+ Q3DSSceneElement *handler = qobject_cast<Q3DSSceneElement *>(
+ m_presentation->registeredElement(elementPath));
+ if (handler)
+ handler->d_ptr->requestResponseHandler(commandType, requestData);
+ else
+ qWarning() << __FUNCTION__ << "RequestSlideInfo response got for unregistered scene.";
+ break;
+ }
+ default:
+ qWarning() << __FUNCTION__ << "Unknown command type.";
+ break;
+ }
+}
+
+// Create the Q3DSRenderer. Invoked automatically by the QML scene graph.
+QQuickFramebufferObject::Renderer *Q3DSView::createRenderer() const
+{
+ // It is "illegal" to create a connection between the renderer
+ // and the plugin, and vice-versa. The only valid time the two
+ // may communicate is during Q3DSRenderer::synchronize().
+ Q3DSRenderer *renderer = new Q3DSRenderer(isVisible(), m_presentation->d_ptr->streamProxy());
+
+ connect(renderer, &Q3DSRenderer::enterSlide,
+ m_presentation->d_ptr, &Q3DSPresentationPrivate::handleSlideEntered);
+ connect(renderer, &Q3DSRenderer::exitSlide,
+ m_presentation, &Q3DSPresentation::slideExited);
+ connect(renderer, &Q3DSRenderer::requestResponse,
+ this, &Q3DSView::requestResponseHandler);
+ return renderer;
+}
+
+bool Q3DSView::isRunning() const
+{
+ return m_isRunning;
+}
+
+/** Emit QML `runningChanged` and `frameUpdate` and signals.
+ * This method is called every frame, and emits the `frameUpdate` signal every frame,
+ * regardless of plugin visibility. This allows a hidden Qt3DSView to still process
+ * information every frame, even though the Renderer is not rendering.
+ *
+ * To prevent expensive onFrameUpdate handlers from being processed when hidden,
+ * add an early return to the top like:
+ *
+ * onFrameUpdate: {
+ * if (!visible) return;
+ * ...
+ * }
+ */
+void Q3DSView::tick()
+{
+ if (m_emitRunningChange) {
+ Q_EMIT runningChanged(true);
+ m_emitRunningChange = false;
+ m_isRunning = true;
+ }
+
+ // Don't call onFrameUpdate until after onInitialize has been called
+ if (m_isRunning) {
+ // Give QML an opportunity to change Qt3DS values every frame
+ Q_EMIT frameUpdate();
+ }
+}
+
+// Copies the list of commands previously queued up. Called by Q3DSRenderer::synchronize().
+void Q3DSView::getCommands(bool emitInitialize, CommandQueue &renderQueue)
+{
+ if (emitInitialize)
+ m_emitRunningChange = true;
+
+ renderQueue.copyCommands(m_pendingCommands);
+ m_pendingCommands.clear();
+}
+
+void Q3DSView::mousePressEvent(QMouseEvent *event)
+{
+ if (!m_ignoreMouseEvents) {
+ if (m_pixelRatio != 1.0) {
+ QMouseEvent scaledEvent(event->type(), event->pos() * m_pixelRatio,
+ event->button(), event->buttons(), event->modifiers());
+ m_presentation->mousePressEvent(&scaledEvent);
+ } else {
+ m_presentation->mousePressEvent(event);
+ }
+ }
+}
+
+void Q3DSView::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (!m_ignoreMouseEvents) {
+ if (m_pixelRatio != 1.0) {
+ QMouseEvent scaledEvent(event->type(), event->pos() * m_pixelRatio,
+ event->button(), event->buttons(), event->modifiers());
+ m_presentation->mouseReleaseEvent(&scaledEvent);
+ } else {
+ m_presentation->mouseReleaseEvent(event);
+ }
+ }
+}
+
+void Q3DSView::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!m_ignoreMouseEvents) {
+ if (m_pixelRatio != 1.0) {
+ QMouseEvent scaledEvent(event->type(), event->pos() * m_pixelRatio,
+ event->button(), event->buttons(), event->modifiers());
+ m_presentation->mouseMoveEvent(&scaledEvent);
+ } else {
+ m_presentation->mouseMoveEvent(event);
+ }
+ }
+}
+
+void Q3DSView::wheelEvent(QWheelEvent *event)
+{
+ if (!m_ignoreWheelEvents)
+ m_presentation->wheelEvent(event);
+}
+
+void Q3DSView::keyPressEvent(QKeyEvent *event)
+{
+ if (m_ignoreKeyboardEvents)
+ return;
+ m_presentation->keyPressEvent(event);
+}
+
+void Q3DSView::keyReleaseEvent(QKeyEvent *event)
+{
+ if (m_ignoreKeyboardEvents)
+ return;
+ if (!event->isAutoRepeat())
+ m_presentation->keyReleaseEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/qmlviewer/Qt3DSView.h b/src/Viewer/qmlviewer/Qt3DSView.h
new file mode 100644
index 00000000..3ff9d679
--- /dev/null
+++ b/src/Viewer/qmlviewer/Qt3DSView.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (c) 2016 NVIDIA CORPORATION.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_VIEW_H
+#define Q3DS_VIEW_H
+
+
+#include <QtStudio3D/private/q3dscommandqueue_p.h>
+#include <QtGui/qopenglframebufferobject.h>
+#include <QtQuick/qquickframebufferobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSRenderer;
+class Q3DSViewerSettings;
+class Q3DSPresentationItem;
+
+class Q3DSView : public QQuickFramebufferObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged)
+ Q_PROPERTY(Q3DSPresentationItem *presentation READ presentation CONSTANT)
+ Q_PROPERTY(Q3DSViewerSettings *viewerSettings READ viewerSettings CONSTANT)
+
+public:
+ Q3DSView();
+ virtual ~Q3DSView();
+
+ QQuickFramebufferObject::Renderer *createRenderer() const override;
+
+ bool isRunning() const;
+ Q3DSPresentationItem *presentation() const;
+ Q3DSViewerSettings *viewerSettings() const;
+
+ void getCommands(bool emitInitialize, CommandQueue &renderQueue);
+
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void wheelEvent(QWheelEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
+
+ void setIgnoreEvents(bool mouse, bool wheel, bool keyboard);
+
+ void componentComplete() override;
+
+Q_SIGNALS:
+ void frameUpdate();
+ void runningChanged(bool initialized);
+
+public Q_SLOTS:
+ void reset();
+
+protected Q_SLOTS:
+ void handleWindowChanged(QQuickWindow *window);
+ void handleVisibleChanged();
+ void tick();
+ void requestResponseHandler(const QString &elementPath, CommandType commandType,
+ void *requestData);
+
+protected:
+ Q3DSViewerSettings *m_viewerSettings;
+ Q3DSPresentationItem *m_presentation;
+
+ bool m_emitRunningChange;
+ bool m_isRunning;
+ bool m_ignoreMouseEvents;
+ bool m_ignoreWheelEvents;
+ bool m_ignoreKeyboardEvents;
+
+ CommandQueue m_pendingCommands;
+ qreal m_pixelRatio;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DS_VIEW_H
diff --git a/src/Viewer/qmlviewer/Qt3DSViewPlugin.cpp b/src/Viewer/qmlviewer/Qt3DSViewPlugin.cpp
new file mode 100644
index 00000000..7ef6d278
--- /dev/null
+++ b/src/Viewer/qmlviewer/Qt3DSViewPlugin.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (c) 2016 NVIDIA CORPORATION.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSViewPlugin.h"
+
+#include <QtQml/qqml.h>
+
+#include <QtStudio3D/private/q3dsviewersettings_p.h>
+
+#include "Qt3DSView.h"
+#include "q3dspresentationitem.h"
+#include "q3dsqmlstream.h"
+#include "q3dsqmlsubpresentationsettings.h"
+#include "q3dssceneelement.h"
+
+QT_BEGIN_NAMESPACE
+
+//TODO: remove if works with X
+/*
+#if defined _LINUX || defined linux
+extern "C" {
+bool InitializeGL();
+}
+#endif
+*/
+
+void Q3DSViewPlugin::registerTypes(const char *uri)
+{
+ Q_ASSERT(uri == QLatin1String("QtStudio3D"));
+//TODO: remove if works with X
+/*
+#if defined _LINUX || defined linux
+ // To initialize GL functions for Qt3DS GL bindings
+ InitializeGL();
+#endif
+*/
+ // @uri Studio3D
+ qmlRegisterType<Q3DSView>(uri, 1, 0, "Studio3D");
+ qmlRegisterType<Q3DSViewerSettings>(uri, 1, 0, "ViewerSettings");
+ qmlRegisterType<Q3DSPresentationItem>(uri, 1, 0, "Presentation");
+ qmlRegisterType<Q3DSSceneElement>(uri, 1, 0, "SceneElement");
+ qmlRegisterType<Q3DSElement>(uri, 1, 0, "Element");
+ qmlRegisterType<Q3DSQmlStream>(uri, 1, 0, "QmlStream");
+ qmlRegisterType<Q3DSSubPresentationSettings>(uri, 1, 0, "SubPresentationSettings");
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/qmlviewer/Qt3DSViewPlugin.h b/src/Viewer/qmlviewer/Qt3DSViewPlugin.h
new file mode 100644
index 00000000..1d1a6fff
--- /dev/null
+++ b/src/Viewer/qmlviewer/Qt3DSViewPlugin.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (c) 2016 NVIDIA CORPORATION.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSVIEW_PLUGIN_H
+#define Q3DSVIEW_PLUGIN_H
+
+#include <QtQml/qqmlextensionplugin.h>
+
+static void initResources()
+{
+#ifdef QT_STATIC
+ Q_INIT_RESOURCE(qmake_QtStudio3D);
+#endif
+}
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSViewPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+ Q3DSViewPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent)
+ {
+ initResources();
+ }
+ void registerTypes(const char *uri) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSVIEW_PLUGIN_H
diff --git a/src/Viewer/qmlviewer/q3dspresentationitem.cpp b/src/Viewer/qmlviewer/q3dspresentationitem.cpp
new file mode 100644
index 00000000..c03a5439
--- /dev/null
+++ b/src/Viewer/qmlviewer/q3dspresentationitem.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dspresentationitem.h"
+
+#include <QtStudio3D/private/q3dspresentation_p.h>
+#include <QtStudio3D/private/viewerqmlstreamproxy_p.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+Q3DSPresentationItem::Q3DSPresentationItem(QObject *parent)
+ : Q3DSPresentation(parent)
+ , m_subPresentationSettings(nullptr)
+{
+}
+
+Q3DSPresentationItem::~Q3DSPresentationItem()
+{
+}
+
+Q3DSSubPresentationSettings *Q3DSPresentationItem::subPresentationSettings() const
+{
+ return m_subPresentationSettings;
+}
+
+QQmlListProperty<QObject> Q3DSPresentationItem::qmlChildren()
+{
+ return QQmlListProperty<QObject>(this, nullptr, &appendQmlChildren, nullptr, nullptr, nullptr);
+}
+
+void Q3DSPresentationItem::appendQmlChildren(QQmlListProperty<QObject> *list, QObject *element)
+{
+ auto item = qobject_cast<Q3DSPresentationItem *>(list->object);
+ if (item) {
+ auto scene = qobject_cast<Q3DSSceneElement *>(element);
+ if (scene) {
+ if (item->registeredElement(scene->elementPath()))
+ qWarning() << __FUNCTION__ << "A duplicate SceneElement defined for Presentation.";
+ else
+ item->registerElement(scene);
+ }
+ auto studioElement = qobject_cast<Q3DSElement *>(element);
+ if (studioElement) {
+ if (item->registeredElement(studioElement->elementPath()))
+ qWarning() << __FUNCTION__ << "A duplicate Element defined for Presentation.";
+ else
+ item->registerElement(studioElement);
+ }
+ auto subPresSettings = qobject_cast<Q3DSSubPresentationSettings *>(element);
+ if (subPresSettings) {
+ if (item->m_subPresentationSettings) {
+ qWarning() << __FUNCTION__
+ << "Duplicate SubPresentationSettings defined for Presentation.";
+ } else {
+ item->m_subPresentationSettings = subPresSettings;
+ item->d_ptr->streamProxy()->setSettings(subPresSettings);
+ }
+ }
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/qmlviewer/q3dspresentationitem.h b/src/Viewer/qmlviewer/q3dspresentationitem.h
new file mode 100644
index 00000000..59414275
--- /dev/null
+++ b/src/Viewer/qmlviewer/q3dspresentationitem.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSPRESENTATIONITEM_H
+#define Q3DSPRESENTATIONITEM_H
+
+#include "q3dsqmlsubpresentationsettings.h"
+
+#include <QtStudio3D/q3dspresentation.h>
+#include <QtStudio3D/q3dssceneelement.h>
+#include <QtQml/qqmllist.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSPresentationItem : public Q3DSPresentation
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> qmlChildren READ qmlChildren DESIGNABLE false)
+ Q_PROPERTY(Q3DSSubPresentationSettings *subPresentationSettings READ subPresentationSettings CONSTANT)
+ Q_CLASSINFO("DefaultProperty", "qmlChildren")
+
+public:
+ explicit Q3DSPresentationItem(QObject *parent = nullptr);
+ ~Q3DSPresentationItem();
+
+ Q3DSSubPresentationSettings *subPresentationSettings() const;
+
+ QQmlListProperty<QObject> qmlChildren();
+
+public Q_SLOTS:
+ static void appendQmlChildren(QQmlListProperty<QObject> *list, QObject *element);
+
+private:
+ Q3DSSubPresentationSettings *m_subPresentationSettings;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSPRESENTATIONITEM_H
diff --git a/src/Viewer/qmlviewer/qmldir b/src/Viewer/qmlviewer/qmldir
new file mode 100644
index 00000000..381f7e42
--- /dev/null
+++ b/src/Viewer/qmlviewer/qmldir
@@ -0,0 +1,3 @@
+module QtStudio3D
+plugin declarative_qtstudio3d
+classname Q3DSViewPlugin
diff --git a/src/Viewer/qmlviewer/qmlviewer.pro b/src/Viewer/qmlviewer/qmlviewer.pro
new file mode 100644
index 00000000..aefba2fd
--- /dev/null
+++ b/src/Viewer/qmlviewer/qmlviewer.pro
@@ -0,0 +1,37 @@
+include($$PWD/../../Runtime/commoninclude.pri)
+
+QT += qml quick opengl studio3d-private
+CONFIG += plugin
+
+qtHaveModule(multimedia) {
+DEFINES += PLATFORM_HAS_QT_MULTIMEDIA_LIB
+QT += multimedia
+}
+
+TARGET = qtstudio3d
+TARGETPATH = QtStudio3D
+IMPORT_VERSION = 1.0
+
+SOURCES += \
+ Qt3DSViewPlugin.cpp \
+ Qt3DSView.cpp \
+ Qt3DSRenderer.cpp \
+ q3dspresentationitem.cpp
+
+HEADERS += \
+ Qt3DSViewPlugin.h \
+ Qt3DSView.h \
+ Qt3DSRenderer.h \
+ q3dspresentationitem.h
+
+LIBS += \
+ -lqt3dsruntime$$qtPlatformTargetSuffix() \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+QMAKE_DOCS = $$absolute_path($$PWD/../../../doc/qt3dstudio.qdocconf)
+
+OTHER_FILES += \
+ qmldir \
+ $$PWD/../../../doc/src/06-qml-reference/*
+
+load(qml_plugin)
diff --git a/src/Viewer/studio3d/q3dscommandqueue.cpp b/src/Viewer/studio3d/q3dscommandqueue.cpp
new file mode 100644
index 00000000..cf7bd3f9
--- /dev/null
+++ b/src/Viewer/studio3d/q3dscommandqueue.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dscommandqueue_p.h"
+
+ElementCommand::ElementCommand()
+ : m_commandType(CommandType_Invalid)
+{
+}
+
+QString ElementCommand::toString() const
+{
+ QString ret = QStringLiteral("ElementCommand - Type: %1 Path: '%2' StrVal: '%3' VarVal: '%4'");
+ return ret.arg(m_commandType).arg(m_elementPath)
+ .arg(m_stringValue).arg(m_variantValue.toString());
+}
+
+CommandQueue::CommandQueue()
+ : m_visibleChanged(false)
+ , m_scaleModeChanged(false)
+ , m_shadeModeChanged(false)
+ , m_showRenderStatsChanged(false)
+ , m_matteColorChanged(false)
+ , m_sourceChanged(false)
+ , m_globalAnimationTimeChanged(false)
+ , m_visible(false)
+ , m_scaleMode(Q3DSViewerSettings::ScaleModeCenter)
+ , m_shadeMode(Q3DSViewerSettings::ShadeModeShaded)
+ , m_showRenderStats(false)
+ , m_matteColor(Qt::black)
+ , m_size(0)
+{
+ qRegisterMetaType<CommandType>();
+}
+
+ElementCommand &CommandQueue::queueCommand(const QString &elementPath,
+ CommandType commandType,
+ const QString &attributeName,
+ const QVariant &value)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+ cmd.m_stringValue = attributeName;
+ cmd.m_variantValue = value;
+
+ return cmd;
+}
+
+ElementCommand &CommandQueue::queueCommand(const QString &elementPath, CommandType commandType,
+ const QString &value)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+ cmd.m_stringValue = value;
+
+ return cmd;
+}
+
+ElementCommand &CommandQueue::queueCommand(const QString &elementPath,
+ CommandType commandType, bool value)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+ cmd.m_boolValue = value;
+
+ return cmd;
+}
+
+ElementCommand &CommandQueue::queueCommand(const QString &elementPath,
+ CommandType commandType, float value)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+ cmd.m_floatValue = value;
+
+ return cmd;
+}
+
+ElementCommand &CommandQueue::queueCommand(const QString &elementPath,
+ CommandType commandType, int value0, int value1,
+ int value2, int value3)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+ cmd.m_intValues[0] = value0;
+ cmd.m_intValues[1] = value1;
+ cmd.m_intValues[2] = value2;
+ cmd.m_intValues[3] = value3;
+
+ return cmd;
+}
+
+ElementCommand &CommandQueue::queueRequest(const QString &elementPath, CommandType commandType)
+{
+ ElementCommand &cmd = nextFreeCommand();
+
+ cmd.m_commandType = commandType;
+ cmd.m_elementPath = elementPath;
+
+ return cmd;
+}
+
+void CommandQueue::copyCommands(const CommandQueue &fromQueue)
+{
+ m_visibleChanged = fromQueue.m_visibleChanged;
+ m_scaleModeChanged = fromQueue.m_scaleModeChanged;
+ m_shadeModeChanged = fromQueue.m_shadeModeChanged;
+ m_showRenderStatsChanged = fromQueue.m_showRenderStatsChanged;
+ m_matteColorChanged = fromQueue.m_matteColorChanged;
+ m_sourceChanged = fromQueue.m_sourceChanged;
+ m_globalAnimationTimeChanged = fromQueue.m_globalAnimationTimeChanged;
+
+ if (m_visibleChanged)
+ m_visible = fromQueue.m_visible;
+ if (m_scaleModeChanged)
+ m_scaleMode = fromQueue.m_scaleMode;
+ if (m_shadeModeChanged)
+ m_shadeMode = fromQueue.m_shadeMode;
+ if (m_showRenderStatsChanged)
+ m_showRenderStats = fromQueue.m_showRenderStats;
+ if (m_matteColorChanged)
+ m_matteColor = fromQueue.m_matteColor;
+ if (m_sourceChanged)
+ m_source = fromQueue.m_source;
+ if (m_globalAnimationTimeChanged)
+ m_globalAnimationTime = fromQueue.m_globalAnimationTime;
+
+ m_size = 0;
+
+ for (int i = 0; i < fromQueue.m_size; i++) {
+ const ElementCommand &source = fromQueue.commandAt(i);
+ switch (source.m_commandType) {
+ case CommandType_SetAttribute:
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue,
+ source.m_variantValue);
+ break;
+ case CommandType_GoToSlideByName:
+ case CommandType_FireEvent:
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_stringValue);
+ break;
+ case CommandType_SetPresentationActive:
+ queueCommand(source.m_elementPath, source.m_commandType,
+ source.m_boolValue);
+ break;
+ case CommandType_GoToTime:
+ queueCommand(source.m_elementPath, source.m_commandType,
+ source.m_floatValue);
+ break;
+ case CommandType_GoToSlide:
+ case CommandType_GoToSlideRelative:
+ case CommandType_MousePress:
+ case CommandType_MouseRelease:
+ case CommandType_MouseMove:
+ case CommandType_MouseWheel:
+ case CommandType_KeyPress:
+ case CommandType_KeyRelease:
+ queueCommand(source.m_elementPath, source.m_commandType,
+ source.m_intValues[0], source.m_intValues[1],
+ source.m_intValues[2], source.m_intValues[3]);
+ break;
+ case CommandType_RequestSlideInfo:
+ queueRequest(source.m_elementPath, source.m_commandType);
+ break;
+ default:
+ queueCommand(QString(), CommandType_Invalid, false);
+ break;
+ }
+ }
+}
+
+// Clears changed states and empties the queue
+void CommandQueue::clear()
+{
+ m_visibleChanged = false;
+ m_scaleModeChanged = false;
+ m_shadeModeChanged = false;
+ m_showRenderStatsChanged = false;
+ m_matteColorChanged = false;
+ m_sourceChanged = false;
+ m_globalAnimationTimeChanged = false;
+
+ // We do not clear the actual queued commands, those will be reused the next frame
+ // To avoid a lot of unnecessary reallocations.
+ m_size = 0;
+}
+
+ElementCommand &CommandQueue::nextFreeCommand()
+{
+ m_size++;
+ if (m_size > m_elementCommands.size())
+ m_elementCommands.append(ElementCommand());
+ return m_elementCommands[m_size - 1];
+}
diff --git a/src/Viewer/studio3d/q3dscommandqueue_p.h b/src/Viewer/studio3d/q3dscommandqueue_p.h
new file mode 100644
index 00000000..6b0d29a8
--- /dev/null
+++ b/src/Viewer/studio3d/q3dscommandqueue_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DS_COMMAND_QUEUE_H
+#define Q3DS_COMMAND_QUEUE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "q3dsviewersettings.h"
+
+#include <QtGui/qcolor.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+enum CommandType {
+ CommandType_Invalid = 0,
+ CommandType_SetAttribute,
+ CommandType_SetPresentationActive,
+ CommandType_GoToSlideByName,
+ CommandType_GoToSlide,
+ CommandType_GoToSlideRelative,
+ CommandType_GoToTime,
+ CommandType_FireEvent,
+ CommandType_MousePress,
+ CommandType_MouseRelease,
+ CommandType_MouseMove,
+ CommandType_MouseWheel,
+ CommandType_KeyPress,
+ CommandType_KeyRelease,
+ CommandType_SetGlobalAnimationTime,
+ CommandType_RequestSlideInfo
+};
+
+Q_DECLARE_METATYPE(CommandType)
+
+class Q_STUDIO3D_EXPORT ElementCommand
+{
+public:
+ ElementCommand();
+
+ CommandType m_commandType;
+ QString m_elementPath;
+ QString m_stringValue;
+ QVariant m_variantValue;
+ union {
+ bool m_boolValue;
+ float m_floatValue;
+ int m_intValues[4];
+ qint64 m_int64Value;
+ };
+
+ QString toString() const;
+};
+
+typedef QVector<ElementCommand> CommandList;
+
+class Q_STUDIO3D_EXPORT CommandQueue
+{
+public:
+ CommandQueue();
+
+ ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
+ const QString &attributeName, const QVariant &value);
+ ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
+ const QString &value);
+ ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
+ bool value);
+ ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
+ float value);
+ ElementCommand &queueCommand(const QString &elementPath, CommandType commandType,
+ int value0, int value1 = 0,
+ int value2 = 0, int value3 = 0);
+ ElementCommand &queueRequest(const QString &elementPath, CommandType commandType);
+
+ void copyCommands(const CommandQueue &fromQueue);
+
+ bool m_visibleChanged;
+ bool m_scaleModeChanged;
+ bool m_shadeModeChanged;
+ bool m_showRenderStatsChanged;
+ bool m_matteColorChanged;
+ bool m_sourceChanged;
+ bool m_globalAnimationTimeChanged;
+
+ bool m_visible;
+ Q3DSViewerSettings::ScaleMode m_scaleMode;
+ Q3DSViewerSettings::ShadeMode m_shadeMode;
+ bool m_showRenderStats;
+ QColor m_matteColor;
+ QUrl m_source;
+ qint64 m_globalAnimationTime;
+
+ void clear();
+ int size() const { return m_size; }
+ const ElementCommand &commandAt(int index) const { return m_elementCommands.at(index); }
+
+private:
+ ElementCommand &nextFreeCommand();
+
+ CommandList m_elementCommands;
+ int m_size;
+};
+
+#endif // Q3DS_COMMAND_QUEUE_H
diff --git a/src/Viewer/studio3d/q3dselement.cpp b/src/Viewer/studio3d/q3dselement.cpp
new file mode 100644
index 00000000..4f13d7c2
--- /dev/null
+++ b/src/Viewer/studio3d/q3dselement.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dselement_p.h"
+#include "q3dspresentation_p.h"
+#include "q3dscommandqueue_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+Q3DSElement::Q3DSElement(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new Q3DSElementPrivate(this))
+{
+}
+
+Q3DSElement::Q3DSElement(const QString &elementPath, QObject *parent)
+ : QObject(parent)
+ , d_ptr(new Q3DSElementPrivate(this))
+{
+ d_ptr->m_elementPath = elementPath;
+}
+
+Q3DSElement::Q3DSElement(Q3DSPresentation *presentation, const QString &elementPath,
+ QObject *parent)
+ : QObject(parent)
+ , d_ptr(new Q3DSElementPrivate(this))
+{
+ d_ptr->m_elementPath = elementPath;
+ if (presentation)
+ presentation->registerElement(this);
+}
+
+Q3DSElement::Q3DSElement(Q3DSElementPrivate *d, Q3DSPresentation *presentation,
+ const QString &elementPath, QObject *parent)
+ : QObject(parent)
+ , d_ptr(d)
+{
+ d_ptr->m_elementPath = elementPath;
+ if (presentation)
+ presentation->registerElement(this);
+}
+
+Q3DSElement::~Q3DSElement()
+{
+ // Private class isn't QObject, so we need to delete it explicitly
+ delete d_ptr;
+}
+
+QString Q3DSElement::elementPath() const
+{
+ return d_ptr->m_elementPath;
+}
+
+void Q3DSElement::setElementPath(const QString &elementPath)
+{
+ if (d_ptr->m_elementPath != elementPath) {
+ d_ptr->setElementPath(elementPath);
+ Q_EMIT elementPathChanged(d_ptr->m_elementPath);
+ }
+}
+
+void Q3DSElement::setAttribute(const QString &attributeName, const QVariant &value)
+{
+ if (d_ptr->m_presentation)
+ d_ptr->m_presentation->q_ptr->setAttribute(d_ptr->m_elementPath, attributeName, value);
+ else
+ qWarning() << __FUNCTION__ << "Element is not registered to any presentation!";
+}
+
+void Q3DSElement::fireEvent(const QString &eventName)
+{
+ if (d_ptr->m_presentation)
+ d_ptr->m_presentation->q_ptr->fireEvent(d_ptr->m_elementPath, eventName);
+ else
+ qWarning() << __FUNCTION__ << "Element is not registered to any presentation!";
+}
+
+Q3DSElementPrivate::Q3DSElementPrivate(Q3DSElement *parent)
+ : q_ptr(parent)
+ , m_viewerApp(nullptr)
+ , m_commandQueue(nullptr)
+ , m_presentation(nullptr)
+{
+}
+
+Q3DSElementPrivate::~Q3DSElementPrivate()
+{
+ if (m_presentation)
+ m_presentation->unregisterElement(q_ptr);
+}
+
+void Q3DSElementPrivate::setElementPath(const QString &elementPath)
+{
+ m_elementPath = elementPath;
+
+ if (m_presentation)
+ m_presentation->registerElement(q_ptr);
+}
+
+void Q3DSElementPrivate::setViewerApp(UICViewer::UICViewerApp *app)
+{
+ m_viewerApp = app;
+}
+
+void Q3DSElementPrivate::setCommandQueue(CommandQueue *queue)
+{
+ m_commandQueue = queue;
+}
+
+void Q3DSElementPrivate::setPresentation(Q3DSPresentationPrivate *presentation)
+{
+ m_presentation = presentation;
+}
+
+void Q3DSElementPrivate::requestResponseHandler(CommandType commandType, void *requestData)
+{
+ Q_UNUSED(commandType)
+ Q_UNUSED(requestData)
+
+ // Base element doesn't handle any request command types yet
+ qWarning() << __FUNCTION__ << "Unknown command type.";
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/q3dselement.h b/src/Viewer/studio3d/q3dselement.h
new file mode 100644
index 00000000..6df5dde9
--- /dev/null
+++ b/src/Viewer/studio3d/q3dselement.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSELEMENT_H
+#define Q3DSELEMENT_H
+
+#include <QtStudio3D/qstudio3dglobal.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSElementPrivate;
+class Q3DSPresentation;
+
+class Q_STUDIO3D_EXPORT Q3DSElement : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3DSElement)
+
+ Q_PROPERTY(QString elementPath READ elementPath WRITE setElementPath NOTIFY elementPathChanged)
+
+public:
+ explicit Q3DSElement(QObject *parent = nullptr);
+ explicit Q3DSElement(const QString &elementPath, QObject *parent = nullptr);
+ explicit Q3DSElement(Q3DSPresentation *presentation, const QString &elementPath,
+ QObject *parent = nullptr);
+ virtual ~Q3DSElement();
+
+ QString elementPath() const;
+
+public Q_SLOTS:
+ void setElementPath(const QString &elementPath);
+ void setAttribute(const QString &attributeName, const QVariant &value);
+ void fireEvent(const QString &eventName);
+
+Q_SIGNALS:
+ void elementPathChanged(const QString &elementPath);
+
+protected:
+ explicit Q3DSElement(Q3DSElementPrivate *d, Q3DSPresentation *presentation,
+ const QString &elementPath, QObject *parent = nullptr);
+ Q3DSElementPrivate *d_ptr;
+
+private:
+ Q_DISABLE_COPY(Q3DSElement)
+
+ friend class Q3DSPresentationPrivate;
+ friend class Q3DSView;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSELEMENT_H
diff --git a/src/Viewer/studio3d/q3dselement_p.h b/src/Viewer/studio3d/q3dselement_p.h
new file mode 100644
index 00000000..6327b189
--- /dev/null
+++ b/src/Viewer/studio3d/q3dselement_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSSCENE_P_H
+#define Q3DSSCENE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "q3dselement.h"
+#include "q3dscommandqueue_p.h"
+#include "UICViewerApp.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSPresentationPrivate;
+
+class Q_STUDIO3D_EXPORT Q3DSElementPrivate
+{
+ Q_DECLARE_PUBLIC(Q3DSElement)
+public:
+ explicit Q3DSElementPrivate(Q3DSElement *parent);
+ virtual ~Q3DSElementPrivate();
+
+ void setElementPath(const QString &elementPath);
+
+ virtual void setViewerApp(UICViewer::UICViewerApp *app);
+ virtual void setCommandQueue(CommandQueue *queue);
+ virtual void setPresentation(Q3DSPresentationPrivate *presentation);
+
+ virtual void requestResponseHandler(CommandType commandType, void *requestData);
+
+protected:
+ Q3DSElement *q_ptr;
+ UICViewer::UICViewerApp *m_viewerApp; // Not owned
+ CommandQueue *m_commandQueue; // Not owned
+ Q3DSPresentationPrivate *m_presentation; // Not owned
+ QString m_elementPath;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSSCENE_P_H
diff --git a/src/Viewer/studio3d/q3dspresentation.cpp b/src/Viewer/studio3d/q3dspresentation.cpp
new file mode 100644
index 00000000..9d88c55d
--- /dev/null
+++ b/src/Viewer/studio3d/q3dspresentation.cpp
@@ -0,0 +1,688 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dspresentation_p.h"
+#include "q3dssceneelement_p.h"
+#include "q3dscommandqueue_p.h"
+#include "viewerqmlstreamproxy_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QWheelEvent>
+
+QT_BEGIN_NAMESPACE
+
+Q3DSPresentation::Q3DSPresentation(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new Q3DSPresentationPrivate(this))
+{
+}
+
+Q3DSPresentation::~Q3DSPresentation()
+{
+}
+
+QUrl Q3DSPresentation::source() const
+{
+ return d_ptr->m_source;
+}
+
+void Q3DSPresentation::registerElement(Q3DSElement *element)
+{
+ d_ptr->registerElement(element);
+}
+
+void Q3DSPresentation::unregisterElement(Q3DSElement *element)
+{
+ d_ptr->unregisterElement(element);
+}
+
+Q3DSElement *Q3DSPresentation::registeredElement(const QString &elementPath) const
+{
+ return d_ptr->m_elements.value(elementPath, nullptr);
+}
+
+void Q3DSPresentation::setSource(const QUrl &source)
+{
+ if (d_ptr->m_source != source) {
+ d_ptr->setSource(source);
+ Q_EMIT sourceChanged(source);
+ }
+}
+
+void Q3DSPresentation::goToSlide(const QString &elementPath, unsigned int index)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray path(elementPath.toUtf8());
+ d_ptr->m_viewerApp->GoToSlideByIndex(path, index);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToSlide, int(index));
+ }
+}
+
+void Q3DSPresentation::goToSlide(const QString &elementPath, const QString &name)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray path(elementPath.toUtf8());
+ const QByteArray byteName(name.toUtf8());
+ d_ptr->m_viewerApp->GoToSlideByName(path, byteName);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToSlideByName, name);
+ }
+}
+
+void Q3DSPresentation::goToSlide(const QString &elementPath, bool next, bool wrap)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray path(elementPath.toUtf8());
+ d_ptr->m_viewerApp->GoToSlideRelative(path, next, wrap);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToSlideRelative,
+ int(next), int(wrap));
+ }
+}
+
+void Q3DSPresentation::goToTime(const QString &elementPath, float time)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray path(elementPath.toUtf8());
+ d_ptr->m_viewerApp->GoToTime(path, time);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_GoToTime, time);
+ }
+}
+
+void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &attributeName,
+ const QVariant &value)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray path(elementPath.toUtf8());
+ const QByteArray name(attributeName.toUtf8());
+
+ QByteArray valueStr;
+ float valueFloat;
+
+ const void *theValue = nullptr;
+ switch (value.type()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::Double:
+ case QMetaType::Float:
+ valueFloat = value.toFloat();
+ theValue = &valueFloat;
+ break;
+ case QVariant::String:
+ default: // Try string for other types
+ valueStr = value.toString().toUtf8();
+ theValue = valueStr.constData();
+ break;
+ }
+ d_ptr->m_viewerApp->SetAttribute(path, name, (char *)theValue);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_SetAttribute,
+ attributeName, value);
+ }
+}
+
+void Q3DSPresentation::setPresentationActive(const QString &id, bool active)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray presId(id.toUtf8());
+ d_ptr->m_viewerApp->SetPresentationActive(presId, active);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(id, CommandType_SetPresentationActive, active);
+ }
+}
+
+void Q3DSPresentation::fireEvent(const QString &elementPath, const QString &eventName)
+{
+ if (d_ptr->m_viewerApp) {
+ const QByteArray path(elementPath.toUtf8());
+ const QByteArray name(eventName.toUtf8());
+ d_ptr->m_viewerApp->FireEvent(path, name);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(elementPath, CommandType_FireEvent, eventName);
+ }
+}
+
+void Q3DSPresentation::setGlobalAnimationTime(qint64 milliseconds)
+{
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->SetGlobalAnimationTime(milliseconds);
+ } else {
+ d_ptr->m_commandQueue->m_globalAnimationTimeChanged = true;
+ d_ptr->m_commandQueue->m_globalAnimationTime = milliseconds;
+ }
+}
+
+void Q3DSPresentation::mousePressEvent(QMouseEvent *e)
+{
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->HandleMousePress(e->x(), e->y(), e->button(), true);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MousePress,
+ e->x(), e->y(), int(e->button()));
+ }
+}
+
+void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->HandleMousePress(e->x(), e->y(), e->button(), false);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MouseRelease,
+ e->x(), e->y(), int(e->button()));
+ }
+}
+
+void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e)
+{
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->HandleMouseMove(e->x(), e->y(), true);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MouseMove,
+ e->x(), e->y());
+ }
+}
+
+void Q3DSPresentation::wheelEvent(QWheelEvent *e)
+{
+ QPoint pixelData = e->pixelDelta();
+ int numSteps = 0;
+ if (pixelData.isNull()) {
+ if (e->orientation() == Qt::Vertical)
+ numSteps = e->angleDelta().y() / 8;
+ else
+ numSteps = e->angleDelta().x() / 8;
+ } else {
+ // trackpad, pixel = one step in scroll wheel.
+ if (e->orientation() == Qt::Vertical)
+ numSteps = pixelData.y();
+ else
+ numSteps = pixelData.x();
+ }
+ if (numSteps != 0) {
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->HandleMouseWheel(e->x(), e->y(),
+ e->orientation() == Qt::Vertical ? 0 : 1,
+ numSteps);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(QString(), CommandType_MouseWheel,
+ e->x(), e->y(),
+ int(e->orientation() == Qt::Vertical), numSteps);
+ }
+ }
+}
+
+void Q3DSPresentation::keyPressEvent(QKeyEvent *e)
+{
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->HandleKeyInput(d_ptr->getScanCode(e), true);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(QString(), CommandType_KeyPress,
+ d_ptr->getScanCode(e));
+ }
+}
+
+void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
+{
+ if (d_ptr->m_viewerApp) {
+ d_ptr->m_viewerApp->HandleKeyInput(d_ptr->getScanCode(e), false);
+ } else if (d_ptr->m_commandQueue) {
+ d_ptr->m_commandQueue->queueCommand(QString(), CommandType_KeyRelease,
+ d_ptr->getScanCode(e));
+ }
+}
+
+Q3DSPresentationPrivate::Q3DSPresentationPrivate(Q3DSPresentation *q)
+ : QObject(q)
+ , q_ptr(q)
+ , m_viewerApp(nullptr)
+ , m_commandQueue(nullptr)
+ , m_streamProxy(nullptr)
+{
+}
+
+Q3DSPresentationPrivate::~Q3DSPresentationPrivate()
+{
+ unregisterAllElements();
+ delete m_streamProxy;
+}
+
+void Q3DSPresentationPrivate::setSource(const QUrl &source)
+{
+ m_source = source;
+ if (m_commandQueue) {
+ m_commandQueue->m_sourceChanged = true;
+ m_commandQueue->m_source = source;
+ }
+}
+
+void Q3DSPresentationPrivate::setViewerApp(UICViewer::UICViewerApp *app, bool connectApp)
+{
+
+ for (Q3DSElement *element : m_elements.values())
+ element->d_ptr->setViewerApp(app);
+
+ if (connectApp) {
+ if (app) {
+ connect(app, &UICViewer::UICViewerApp::SigSlideEntered,
+ this, &Q3DSPresentationPrivate::handleSlideEntered);
+ connect(app, &UICViewer::UICViewerApp::SigSlideExited,
+ q_ptr, &Q3DSPresentation::slideExited);
+ }
+ if (m_viewerApp) {
+ disconnect(m_viewerApp, &UICViewer::UICViewerApp::SigSlideEntered,
+ this, &Q3DSPresentationPrivate::handleSlideEntered);
+ disconnect(m_viewerApp, &UICViewer::UICViewerApp::SigSlideExited,
+ q_ptr, &Q3DSPresentation::slideExited);
+ }
+ }
+
+ m_viewerApp = app;
+}
+
+void Q3DSPresentationPrivate::setCommandQueue(CommandQueue *queue)
+{
+ for (Q3DSElement *element : m_elements.values())
+ element->d_ptr->setCommandQueue(queue);
+
+ m_commandQueue = queue;
+
+ if (m_commandQueue)
+ setSource(m_source);
+}
+
+// Doc note: The ownership of the registered scenes remains with the caller, who needs to
+// ensure that registered scenes are alive as long as the presentation is alive.
+void Q3DSPresentationPrivate::registerElement(Q3DSElement *element)
+{
+ Q_ASSERT(!element->elementPath().isEmpty());
+
+ // Allow only single registration for each element path and scene object
+ QMutableHashIterator<QString, Q3DSElement *> i(m_elements);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value() == element) {
+ // If the same scene object is already registered with different path,
+ // remove it from the map to avoid duplication.
+ if (i.key() != element->elementPath())
+ i.remove();
+ } else if (i.key() == element->elementPath()) {
+ // If the same element path is registered by another scene object, the old
+ // scene object is unregistered.
+ i.value()->d_ptr->setViewerApp(nullptr);
+ i.value()->d_ptr->setPresentation(nullptr);
+ i.remove();
+ }
+ }
+
+ element->d_ptr->setViewerApp(m_viewerApp);
+ element->d_ptr->setCommandQueue(m_commandQueue);
+ element->d_ptr->setPresentation(this);
+
+ m_elements.insert(element->elementPath(), element);
+}
+
+void Q3DSPresentationPrivate::unregisterElement(Q3DSElement *element)
+{
+ Q3DSElement *oldScene = m_elements.value(element->elementPath());
+ if (oldScene == element) {
+ element->d_ptr->setViewerApp(nullptr);
+ element->d_ptr->setCommandQueue(nullptr);
+ element->d_ptr->setPresentation(nullptr);
+ m_elements.remove(element->elementPath());
+ }
+}
+
+void Q3DSPresentationPrivate::unregisterAllElements()
+{
+ for (Q3DSElement *element : m_elements.values()) {
+ element->d_ptr->setViewerApp(nullptr);
+ element->d_ptr->setCommandQueue(nullptr);
+ element->d_ptr->setPresentation(nullptr);
+ }
+ m_elements.clear();
+}
+
+Q3DStudio::EKeyCode Q3DSPresentationPrivate::getScanCode(QKeyEvent *e)
+{
+ enum {
+ RIGHT_SHIFT = 0x036,
+ RIGHT_CTRL = 0x11d,
+ RIGHT_ALT = 0x138,
+ };
+
+ Qt::Key keyScanCode = static_cast<Qt::Key>(e->key());
+
+ Q3DStudio::EKeyCode newScanCode = Q3DStudio::KEY_NOKEY;
+ switch (keyScanCode) {
+ case Qt::Key_Down:
+ newScanCode = Q3DStudio::KEY_DOWN;
+ break;
+ case Qt::Key_Up:
+ newScanCode = Q3DStudio::KEY_UP;
+ break;
+ case Qt::Key_Left:
+ newScanCode = Q3DStudio::KEY_LEFT;
+ break;
+ case Qt::Key_Right:
+ newScanCode = Q3DStudio::KEY_RIGHT;
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADENTER
+ : Q3DStudio::KEY_RETURN;
+ break;
+ case Qt::Key_Backspace:
+ newScanCode = Q3DStudio::KEY_BACK;
+ break;
+ case Qt::Key_Tab:
+ newScanCode = Q3DStudio::KEY_TAB;
+ break;
+ case Qt::Key_Escape:
+ newScanCode = Q3DStudio::KEY_ESCAPE;
+ break;
+ case Qt::Key_A:
+ newScanCode = Q3DStudio::KEY_A;
+ break;
+ case Qt::Key_B:
+ newScanCode = Q3DStudio::KEY_B;
+ break;
+ case Qt::Key_C:
+ newScanCode = Q3DStudio::KEY_C;
+ break;
+ case Qt::Key_D:
+ newScanCode = Q3DStudio::KEY_D;
+ break;
+ case Qt::Key_E:
+ newScanCode = Q3DStudio::KEY_E;
+ break;
+ case Qt::Key_F:
+ newScanCode = Q3DStudio::KEY_F;
+ break;
+ case Qt::Key_G:
+ newScanCode = Q3DStudio::KEY_G;
+ break;
+ case Qt::Key_H:
+ newScanCode = Q3DStudio::KEY_H;
+ break;
+ case Qt::Key_I:
+ newScanCode = Q3DStudio::KEY_I;
+ break;
+ case Qt::Key_J:
+ newScanCode = Q3DStudio::KEY_J;
+ break;
+ case Qt::Key_K:
+ newScanCode = Q3DStudio::KEY_K;
+ break;
+ case Qt::Key_L:
+ newScanCode = Q3DStudio::KEY_L;
+ break;
+ case Qt::Key_M:
+ newScanCode = Q3DStudio::KEY_M;
+ break;
+ case Qt::Key_N:
+ newScanCode = Q3DStudio::KEY_N;
+ break;
+ case Qt::Key_O:
+ newScanCode = Q3DStudio::KEY_O;
+ break;
+ case Qt::Key_P:
+ newScanCode = Q3DStudio::KEY_P;
+ break;
+ case Qt::Key_Q:
+ newScanCode = Q3DStudio::KEY_Q;
+ break;
+ case Qt::Key_R:
+ newScanCode = Q3DStudio::KEY_R;
+ break;
+ case Qt::Key_S:
+ newScanCode = Q3DStudio::KEY_S;
+ break;
+ case Qt::Key_T:
+ newScanCode = Q3DStudio::KEY_T;
+ break;
+ case Qt::Key_U:
+ newScanCode = Q3DStudio::KEY_U;
+ break;
+ case Qt::Key_V:
+ newScanCode = Q3DStudio::KEY_V;
+ break;
+ case Qt::Key_W:
+ newScanCode = Q3DStudio::KEY_W;
+ break;
+ case Qt::Key_X:
+ newScanCode = Q3DStudio::KEY_X;
+ break;
+ case Qt::Key_Y:
+ newScanCode = Q3DStudio::KEY_Y;
+ break;
+ case Qt::Key_Z:
+ newScanCode = Q3DStudio::KEY_Z;
+ break;
+ case Qt::Key_0:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD0 : Q3DStudio::KEY_0;
+ break;
+ case Qt::Key_1:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD1 : Q3DStudio::KEY_1;
+ break;
+ case Qt::Key_2:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD2 : Q3DStudio::KEY_2;
+ break;
+ case Qt::Key_3:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD3 : Q3DStudio::KEY_3;
+ break;
+ case Qt::Key_4:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD4 : Q3DStudio::KEY_4;
+ break;
+ case Qt::Key_5:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD5 : Q3DStudio::KEY_5;
+ break;
+ case Qt::Key_6:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD6 : Q3DStudio::KEY_6;
+ break;
+ case Qt::Key_7:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD7 : Q3DStudio::KEY_7;
+ break;
+ case Qt::Key_8:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD8 : Q3DStudio::KEY_8;
+ break;
+ case Qt::Key_9:
+ newScanCode =
+ e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPAD9 : Q3DStudio::KEY_9;
+ break;
+ case Qt::Key_Minus:
+ newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADSUBTRACT
+ : Q3DStudio::KEY_SUBTRACT;
+ break;
+ case Qt::Key_Plus:
+ newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADADD
+ : Q3DStudio::KEY_EQUALS;
+ break;
+ case Qt::Key_NumLock:
+ newScanCode = Q3DStudio::KEY_NUMLOCK;
+ break;
+ case Qt::Key_ScrollLock:
+ newScanCode = Q3DStudio::KEY_SCROLL;
+ break;
+ case Qt::Key_CapsLock:
+ newScanCode = Q3DStudio::KEY_CAPITAL;
+ break;
+ case Qt::Key_Pause:
+ newScanCode = Q3DStudio::KEY_PAUSE;
+ break;
+ case Qt::Key_Print:
+ newScanCode = Q3DStudio::KEY_PRINTSCREEN;
+ break;
+ case Qt::Key_Insert:
+ newScanCode = Q3DStudio::KEY_INSERT;
+ break;
+ case Qt::Key_Delete:
+ newScanCode = Q3DStudio::KEY_DELETE;
+ break;
+ case Qt::Key_Home:
+ newScanCode = Q3DStudio::KEY_HOME;
+ break;
+ case Qt::Key_End:
+ newScanCode = Q3DStudio::KEY_END;
+ break;
+ case Qt::Key_PageUp:
+ newScanCode = Q3DStudio::KEY_PGUP;
+ break;
+ case Qt::Key_PageDown:
+ newScanCode = Q3DStudio::KEY_PGDN;
+ break;
+ case Qt::Key_F1:
+ newScanCode = Q3DStudio::KEY_F1;
+ break;
+ case Qt::Key_F2:
+ newScanCode = Q3DStudio::KEY_F2;
+ break;
+ case Qt::Key_F3:
+ newScanCode = Q3DStudio::KEY_F3;
+ break;
+ case Qt::Key_F4:
+ newScanCode = Q3DStudio::KEY_F4;
+ break;
+ case Qt::Key_F5:
+ newScanCode = Q3DStudio::KEY_F5;
+ break;
+ case Qt::Key_F6:
+ newScanCode = Q3DStudio::KEY_F6;
+ break;
+ case Qt::Key_F7:
+ newScanCode = Q3DStudio::KEY_F7;
+ break;
+ case Qt::Key_F8:
+ newScanCode = Q3DStudio::KEY_F8;
+ break;
+ case Qt::Key_F9:
+ newScanCode = Q3DStudio::KEY_F9;
+ break;
+ case Qt::Key_F10:
+ newScanCode = Q3DStudio::KEY_F10;
+ break;
+ case Qt::Key_F11:
+ newScanCode = Q3DStudio::KEY_F11;
+ break;
+ case Qt::Key_F12:
+ newScanCode = Q3DStudio::KEY_F12;
+ break;
+ case Qt::Key_F13:
+ newScanCode = Q3DStudio::KEY_F13;
+ break;
+ case Qt::Key_F14:
+ newScanCode = Q3DStudio::KEY_F14;
+ break;
+ case Qt::Key_QuoteLeft:
+ newScanCode = Q3DStudio::KEY_GRAVE;
+ break;
+ case Qt::Key_Asterisk:
+ newScanCode = Q3DStudio::KEY_MULTIPLY;
+ break;
+ case Qt::Key_BracketRight:
+ newScanCode = Q3DStudio::KEY_RBRACKET;
+ break;
+ case Qt::Key_BracketLeft:
+ newScanCode = Q3DStudio::KEY_LBRACKET;
+ break;
+ case Qt::Key_Semicolon:
+ newScanCode = Q3DStudio::KEY_SEMICOLON;
+ break;
+ case Qt::Key_Comma:
+ newScanCode = Q3DStudio::KEY_COMMA;
+ break;
+ case Qt::Key_Period:
+ newScanCode = e->modifiers() == Qt::KeypadModifier ? Q3DStudio::KEY_NUMPADDECIMAL
+ : Q3DStudio::KEY_PERIOD;
+ break;
+ case Qt::Key_Apostrophe:
+ newScanCode = Q3DStudio::KEY_APOSTROPHE;
+ break;
+ case Qt::Key_Slash:
+ newScanCode = Q3DStudio::KEY_SLASH;
+ break;
+ case Qt::Key_Backslash:
+ newScanCode = Q3DStudio::KEY_BACKSLASH;
+ break;
+ case Qt::Key_Equal:
+ newScanCode = Q3DStudio::KEY_EQUALS;
+ break;
+ case Qt::Key_Space:
+ newScanCode = Q3DStudio::KEY_SPACE;
+ break;
+ case Qt::Key_Shift:
+ newScanCode =
+ e->nativeScanCode() == RIGHT_SHIFT ? Q3DStudio::KEY_RSHIFT : Q3DStudio::KEY_LSHIFT;
+ break;
+ case Qt::Key_Control:
+ newScanCode = e->nativeScanCode() == RIGHT_CTRL ? Q3DStudio::KEY_RCONTROL
+ : Q3DStudio::KEY_LCONTROL;
+ break;
+ case Qt::Key_Alt:
+ newScanCode =
+ e->nativeScanCode() == RIGHT_ALT ? Q3DStudio::KEY_RALT : Q3DStudio::KEY_LALT;
+ break;
+ default:
+ break;
+ }
+
+ return newScanCode;
+}
+
+ViewerQmlStreamProxy *Q3DSPresentationPrivate::streamProxy()
+{
+ if (!m_streamProxy)
+ m_streamProxy = new ViewerQmlStreamProxy();
+ return m_streamProxy;
+}
+
+void Q3DSPresentationPrivate::handleSlideEntered(const QString &elementPath, unsigned int index,
+ const QString &name)
+{
+ Q3DSSceneElement *scene = qobject_cast<Q3DSSceneElement *>(m_elements.value(elementPath));
+ if (scene)
+ scene->d_func()->handleSlideEntered(index, name);
+ Q_EMIT q_ptr->slideEntered(elementPath, index, name);
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/q3dspresentation.h b/src/Viewer/studio3d/q3dspresentation.h
new file mode 100644
index 00000000..a00388ea
--- /dev/null
+++ b/src/Viewer/studio3d/q3dspresentation.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSPRESENTATION_H
+#define Q3DSPRESENTATION_H
+
+#include <QtStudio3D/qstudio3dglobal.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSPresentationPrivate;
+class Q3DSElement;
+class QMouseEvent;
+class QWheelEvent;
+class QKeyEvent;
+
+class Q_STUDIO3D_EXPORT Q3DSPresentation : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3DSPresentation)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+
+public:
+ explicit Q3DSPresentation(QObject *parent = nullptr);
+ ~Q3DSPresentation();
+
+ QUrl source() const;
+
+ void registerElement(Q3DSElement *scene);
+ void unregisterElement(Q3DSElement *scene);
+ Q3DSElement *registeredElement(const QString &elementPath) const;
+
+ // Input event handlers
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void wheelEvent(QWheelEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void keyReleaseEvent(QKeyEvent *e);
+
+public Q_SLOTS:
+ void setSource(const QUrl &source);
+ void goToSlide(const QString &elementPath, unsigned int index);
+ void goToSlide(const QString &elementPath, const QString &name);
+ void goToSlide(const QString &elementPath, bool next, bool wrap);
+ void goToTime(const QString &elementPath, float time);
+ void setAttribute(const QString &elementPath, const QString &attributeName,
+ const QVariant &value);
+ void setPresentationActive(const QString &id, bool active);
+ void fireEvent(const QString &elementPath, const QString &eventName);
+ void setGlobalAnimationTime(qint64 milliseconds);
+
+Q_SIGNALS:
+ void sourceChanged(const QUrl &source);
+ void slideEntered(const QString &elementPath, unsigned int index, const QString &name);
+ void slideExited(const QString &elementPath, unsigned int index, const QString &name);
+
+private:
+ Q_DISABLE_COPY(Q3DSPresentation)
+ Q3DSPresentationPrivate *d_ptr;
+
+ friend class Q3DSPresentationItem;
+ friend class Q3DSSurfaceViewerPrivate;
+ friend class Q3DSWidgetPrivate;
+ friend class Q3DSRenderer;
+ friend class Q3DSView;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSPRESENTATION_H
diff --git a/src/Viewer/studio3d/q3dspresentation_p.h b/src/Viewer/studio3d/q3dspresentation_p.h
new file mode 100644
index 00000000..5c953c35
--- /dev/null
+++ b/src/Viewer/studio3d/q3dspresentation_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSPRESENTATION_P_H
+#define Q3DSPRESENTATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "q3dspresentation.h"
+#include "UICViewerApp.h"
+#include <QtCore/QHash>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class CommandQueue;
+class ViewerQmlStreamProxy;
+class QKeyEvent;
+
+class Q_STUDIO3D_EXPORT Q3DSPresentationPrivate : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PUBLIC(Q3DSPresentation)
+
+public:
+ typedef QHash<QString, Q3DSElement *> ElementMap;
+
+ explicit Q3DSPresentationPrivate(Q3DSPresentation *parent);
+ ~Q3DSPresentationPrivate();
+
+ void setSource(const QUrl &source);
+ void setViewerApp(UICViewer::UICViewerApp *app, bool connectApp = true);
+ void setCommandQueue(CommandQueue *queue);
+
+ void registerElement(Q3DSElement *element);
+ void unregisterElement(Q3DSElement *element);
+ void unregisterAllElements();
+
+ ViewerQmlStreamProxy *streamProxy();
+ Q3DStudio::EKeyCode getScanCode(QKeyEvent *e);
+
+public Q_SLOTS:
+ void handleSlideEntered(const QString &elementPath, unsigned int index, const QString &name);
+
+public:
+ Q3DSPresentation *q_ptr;
+
+private:
+ UICViewer::UICViewerApp *m_viewerApp; // Not owned
+ CommandQueue *m_commandQueue; // Not owned
+ ElementMap m_elements;
+ QUrl m_source;
+ ViewerQmlStreamProxy *m_streamProxy;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSPRESENTATION_P_H
diff --git a/src/Viewer/studio3d/q3dssceneelement.cpp b/src/Viewer/studio3d/q3dssceneelement.cpp
new file mode 100644
index 00000000..0ef73566
--- /dev/null
+++ b/src/Viewer/studio3d/q3dssceneelement.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dssceneelement_p.h"
+#include "q3dspresentation_p.h"
+#include "q3dscommandqueue_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+Q3DSSceneElement::Q3DSSceneElement(QObject *parent)
+ : Q3DSElement(new Q3DSSceneElementPrivate(this), nullptr, QString(), parent)
+{
+}
+
+Q3DSSceneElement::Q3DSSceneElement(const QString &elementPath, QObject *parent)
+ : Q3DSElement(new Q3DSSceneElementPrivate(this), nullptr, elementPath, parent)
+{
+}
+
+Q3DSSceneElement::Q3DSSceneElement(Q3DSPresentation *presentation, const QString &elementPath,
+ QObject *parent)
+ : Q3DSElement(new Q3DSSceneElementPrivate(this), presentation, elementPath, parent)
+{
+
+}
+
+Q3DSSceneElement::~Q3DSSceneElement()
+{
+}
+
+int Q3DSSceneElement::currentSlideIndex() const
+{
+ Q_D(const Q3DSSceneElement);
+ return d->m_currentSlideIndex;
+}
+
+int Q3DSSceneElement::previousSlideIndex() const
+{
+ Q_D(const Q3DSSceneElement);
+ return d->m_previousSlideIndex;
+}
+
+QString Q3DSSceneElement::currentSlideName() const
+{
+ Q_D(const Q3DSSceneElement);
+ return d->m_currentSlideName;
+}
+
+QString Q3DSSceneElement::previousSlideName() const
+{
+ Q_D(const Q3DSSceneElement);
+ return d->m_previousSlideName;
+}
+
+void Q3DSSceneElement::setCurrentSlideIndex(int currentSlideIndex)
+{
+ Q_D(Q3DSSceneElement);
+ if (d->m_viewerApp) {
+ const QByteArray path(d->m_elementPath.toUtf8());
+ d->m_viewerApp->GoToSlideByIndex(path, currentSlideIndex);
+ } else if (d->m_commandQueue) {
+ d->m_commandQueue->queueCommand(d->m_elementPath, CommandType_GoToSlide,
+ int(currentSlideIndex));
+ } else {
+ // Store desired slide until we have either app or queue. Only name or index can be set.
+ d->m_initialSlideIndex = currentSlideIndex;
+ d->m_initialSlideName.clear();
+ }
+}
+
+void Q3DSSceneElement::setCurrentSlideName(const QString &currentSlideName)
+{
+ Q_D(Q3DSSceneElement);
+ if (d->m_viewerApp) {
+ const QByteArray path(d->m_elementPath.toUtf8());
+ const QByteArray name(currentSlideName.toUtf8());
+ d->m_viewerApp->GoToSlideByName(path, name);
+ } else if (d->m_commandQueue) {
+ d->m_commandQueue->queueCommand(d->m_elementPath, CommandType_GoToSlideByName,
+ currentSlideName);
+ } else {
+ // Store desired slide until we have either app or queue. Only name or index can be set.
+ d->m_initialSlideName = currentSlideName;
+ d->m_initialSlideIndex = 0;
+ }
+}
+
+void Q3DSSceneElement::goToSlide(bool next, bool wrap)
+{
+ Q_D(Q3DSSceneElement);
+ d->goToSlide(next, wrap);
+}
+
+void Q3DSSceneElement::goToTime(float time)
+{
+ Q_D(Q3DSSceneElement);
+ d->goToTime(time);
+}
+
+Q3DSSceneElementPrivate::Q3DSSceneElementPrivate(Q3DSSceneElement *parent)
+ : Q3DSElementPrivate(parent)
+ , m_currentSlideIndex(0)
+ , m_previousSlideIndex(0)
+ , m_initialSlideIndex(0)
+ , m_slideInfoRequestPending(false)
+{
+}
+
+Q3DSSceneElementPrivate::~Q3DSSceneElementPrivate()
+{
+}
+
+void Q3DSSceneElementPrivate::handleSlideEntered(int index, const QString &name)
+{
+ Q_Q(Q3DSSceneElement);
+
+ // Initializing presentation will report slide entered for the scenes on the default slide
+ // of the presentation even if user has specified different initial slides.
+ // Since we don't have robust error reporting mechanism from the viewerapp,
+ // we cannot simply ignore these initial enters, as there is no guarantee the slide
+ // user wants even exists.
+
+ // We ignore the slide exited signals and rely on stored previous slide data
+ // to avoid excessive signaling on slide changes.
+ bool notifyCurrent = m_currentSlideIndex != index;
+ bool notifyPrevious = m_previousSlideIndex != m_currentSlideIndex;
+
+ // Since child (i.e. component) slides always get enter event when parent slide is entered,
+ // it is possible that current and previous slides are the same. This feels bit odd, but is
+ // technically correct, as the last time we got enter, the same slide was made current.
+ // It also matches the internal m_viewerApp logic for previous slides.
+ m_previousSlideIndex = m_currentSlideIndex;
+ m_previousSlideName = m_currentSlideName;
+ m_currentSlideIndex = index;
+ m_currentSlideName = name;
+
+ if (notifyPrevious) {
+ Q_EMIT q->previousSlideIndexChanged(m_previousSlideIndex);
+ Q_EMIT q->previousSlideNameChanged(m_previousSlideName);
+ }
+
+ if (notifyCurrent) {
+ Q_EMIT q->currentSlideIndexChanged(m_currentSlideIndex);
+ Q_EMIT q->currentSlideNameChanged(m_currentSlideName);
+ }
+}
+
+void Q3DSSceneElementPrivate::goToSlide(bool next, bool wrap)
+{
+ if (m_presentation)
+ m_presentation->q_ptr->goToSlide(m_elementPath, next, wrap);
+ else
+ qWarning() << __FUNCTION__ << "Element is not registered to any presentation!";
+}
+
+void Q3DSSceneElementPrivate::goToTime(float time)
+{
+ if (m_presentation)
+ m_presentation->q_ptr->goToTime(m_elementPath, time);
+ else
+ qWarning() << __FUNCTION__ << "Element is not registered to any presentation!";
+}
+
+void Q3DSSceneElementPrivate::setViewerApp(UICViewer::UICViewerApp *app)
+{
+ Q_Q(Q3DSSceneElement);
+
+ if (app || m_viewerApp) {
+ m_currentSlideIndex = 0;
+ m_currentSlideName.clear();
+ m_previousSlideIndex = 0;
+ m_previousSlideName.clear();
+ }
+
+ Q3DSElementPrivate::setViewerApp(app);
+
+ if (m_viewerApp) {
+ const QByteArray path(m_elementPath.toUtf8());
+ m_viewerApp->GetSlideInfo(path, m_currentSlideIndex, m_previousSlideIndex,
+ m_currentSlideName, m_previousSlideName);
+
+ // If user has set current slide before viewer app has been set for the first time,
+ // we will switch to the desired slide after we initialize.
+ if (m_initialSlideIndex != 0)
+ q->setCurrentSlideIndex(m_initialSlideIndex);
+ else if (!m_initialSlideName.isEmpty())
+ q->setCurrentSlideName(m_initialSlideName);
+
+ m_initialSlideIndex = 0;
+ m_initialSlideName.clear();
+ }
+}
+
+void Q3DSSceneElementPrivate::setCommandQueue(CommandQueue *queue)
+{
+ Q_Q(Q3DSSceneElement);
+
+ if (queue || m_commandQueue) {
+ m_currentSlideIndex = 0;
+ m_currentSlideName.clear();
+ m_previousSlideIndex = 0;
+ m_previousSlideName.clear();
+ }
+ Q3DSElementPrivate::setCommandQueue(queue);
+
+ if (m_commandQueue) {
+ m_commandQueue->queueRequest(m_elementPath, CommandType_RequestSlideInfo);
+ m_slideInfoRequestPending = true;
+ // If user has set current slide before the queue has been set for the first time,
+ // we will switch to the desired slide after we initialize.
+ if (m_initialSlideIndex != 0)
+ q->setCurrentSlideIndex(m_initialSlideIndex);
+ else if (!m_initialSlideName.isEmpty())
+ q->setCurrentSlideName(m_initialSlideName);
+
+ m_initialSlideIndex = 0;
+ m_initialSlideName.clear();
+ }
+}
+
+void Q3DSSceneElementPrivate::requestResponseHandler(CommandType commandType, void *requestData)
+{
+ switch (commandType) {
+ case CommandType_RequestSlideInfo: {
+ QVariantList *response = reinterpret_cast<QVariantList *>(requestData);
+ if (m_slideInfoRequestPending) {
+ m_slideInfoRequestPending = false;
+
+ m_previousSlideIndex = response->at(1).toInt();
+ m_previousSlideName = response->at(3).toString();
+
+ handleSlideEntered(response->at(0).toInt(), response->at(2).toString());
+ }
+ delete response;
+ break;
+ }
+ default:
+ Q3DSElementPrivate::requestResponseHandler(commandType, requestData);
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/q3dssceneelement.h b/src/Viewer/studio3d/q3dssceneelement.h
new file mode 100644
index 00000000..0eb7a972
--- /dev/null
+++ b/src/Viewer/studio3d/q3dssceneelement.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSSCENEELEMENT_H
+#define Q3DSSCENEELEMENT_H
+
+#include <QtStudio3D/q3dselement.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSSceneElementPrivate;
+
+class Q_STUDIO3D_EXPORT Q3DSSceneElement : public Q3DSElement
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3DSSceneElement)
+
+ Q_PROPERTY(int currentSlideIndex READ currentSlideIndex WRITE setCurrentSlideIndex NOTIFY currentSlideIndexChanged)
+ Q_PROPERTY(int previousSlideIndex READ previousSlideIndex NOTIFY previousSlideIndexChanged)
+ Q_PROPERTY(QString currentSlideName READ currentSlideName WRITE setCurrentSlideName NOTIFY currentSlideNameChanged)
+ Q_PROPERTY(QString previousSlideName READ previousSlideName NOTIFY previousSlideNameChanged)
+
+public:
+ explicit Q3DSSceneElement(QObject *parent = nullptr);
+ explicit Q3DSSceneElement(const QString &elementPath, QObject *parent = nullptr);
+ explicit Q3DSSceneElement(Q3DSPresentation *presentation, const QString &elementPath,
+ QObject *parent = nullptr);
+ ~Q3DSSceneElement();
+
+ int currentSlideIndex() const;
+ int previousSlideIndex() const;
+ QString currentSlideName() const;
+ QString previousSlideName() const;
+
+public Q_SLOTS:
+ void setCurrentSlideIndex(int currentSlideIndex);
+ void setCurrentSlideName(const QString &currentSlideName);
+ void goToSlide(bool next, bool wrap);
+ void goToTime(float time);
+
+Q_SIGNALS:
+ void currentSlideIndexChanged(int currentSlideIndex);
+ void previousSlideIndexChanged(int previousSlideIndex);
+ void currentSlideNameChanged(const QString &currentSlideName);
+ void previousSlideNameChanged(const QString &previousSlideName);
+
+private:
+ Q_DISABLE_COPY(Q3DSSceneElement)
+
+ friend class Q3DSPresentationPrivate;
+ friend class Q3DSView;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSSCENEELEMENT_H
diff --git a/src/Viewer/studio3d/q3dssceneelement_p.h b/src/Viewer/studio3d/q3dssceneelement_p.h
new file mode 100644
index 00000000..548733d5
--- /dev/null
+++ b/src/Viewer/studio3d/q3dssceneelement_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSSCENEELEMENT_P_H
+#define Q3DSSCENEELEMENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "q3dssceneelement.h"
+#include "q3dselement_p.h"
+#include "q3dscommandqueue_p.h"
+#include "UICViewerApp.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSPresentationPrivate;
+
+class Q_STUDIO3D_EXPORT Q3DSSceneElementPrivate : public Q3DSElementPrivate
+{
+ Q_DECLARE_PUBLIC(Q3DSSceneElement)
+public:
+ explicit Q3DSSceneElementPrivate(Q3DSSceneElement *parent);
+ ~Q3DSSceneElementPrivate();
+
+ void handleSlideEntered(int index, const QString &name);
+ void goToSlide(bool next, bool wrap);
+ void goToTime(float time);
+
+ void setViewerApp(UICViewer::UICViewerApp *app) override;
+ void setCommandQueue(CommandQueue *queue) override;
+
+ void requestResponseHandler(CommandType commandType, void *requestData) override;
+
+private:
+ int m_currentSlideIndex;
+ int m_previousSlideIndex;
+ int m_initialSlideIndex;
+ QString m_currentSlideName;
+ QString m_previousSlideName;
+ QString m_initialSlideName;
+ bool m_slideInfoRequestPending;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSSCENEELEMENT_P_H
diff --git a/src/Viewer/studio3d/q3dssurfaceviewer.cpp b/src/Viewer/studio3d/q3dssurfaceviewer.cpp
new file mode 100644
index 00000000..b295ac37
--- /dev/null
+++ b/src/Viewer/studio3d/q3dssurfaceviewer.cpp
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dssurfaceviewer_p.h"
+#include "UICAudioPlayerImpl.h"
+#include "viewerqmlstreamproxy_p.h"
+#include "q3dsviewersettings_p.h"
+#include "q3dspresentation_p.h"
+#include "studioutils_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglfunctions.h>
+#include <QtGui/qoffscreensurface.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/QPlatformSurfaceEvent>
+
+#include <QtCore/QFileInfo>
+
+using namespace UICViewer;
+
+QT_BEGIN_NAMESPACE
+
+Q3DSSurfaceViewer::Q3DSSurfaceViewer(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new Q3DSSurfaceViewerPrivate(this))
+{
+}
+
+Q3DSSurfaceViewer::~Q3DSSurfaceViewer()
+{
+ delete d_ptr;
+}
+
+bool Q3DSSurfaceViewer::initialize(QSurface *surface, QOpenGLContext *context, GLuint fboId)
+{
+ return d_ptr->initialize(surface, context, fboId);
+}
+
+void Q3DSSurfaceViewer::shutdown()
+{
+ d_ptr->shutdown();
+}
+
+void Q3DSSurfaceViewer::reset()
+{
+ d_ptr->reset();
+}
+
+void Q3DSSurfaceViewer::update()
+{
+ d_ptr->update();
+}
+
+QImage Q3DSSurfaceViewer::grab(const QRect &rect)
+{
+ return d_ptr->grab(rect);
+}
+
+QSize Q3DSSurfaceViewer::size() const
+{
+ return d_ptr->m_size;
+}
+
+void Q3DSSurfaceViewer::setSize(const QSize &size)
+{
+ d_ptr->setSize(size);
+}
+
+bool Q3DSSurfaceViewer::autoSize() const
+{
+ return d_ptr->m_autoSize;
+}
+
+void Q3DSSurfaceViewer::setAutoSize(bool autoSize)
+{
+ if (d_ptr->m_autoSize != autoSize) {
+ d_ptr->m_autoSize = autoSize;
+ Q_EMIT autoSizeChanged(autoSize);
+ }
+}
+
+int Q3DSSurfaceViewer::updateInterval() const
+{
+ return d_ptr->m_updateInterval;
+}
+
+void Q3DSSurfaceViewer::setUpdateInterval(int interval)
+{
+ d_ptr->setUpdateInterval(interval);
+}
+
+bool Q3DSSurfaceViewer::isRunning() const
+{
+ return d_ptr->m_viewerApp != nullptr;
+}
+
+int Q3DSSurfaceViewer::fboId() const
+{
+ return d_ptr->m_fboId;
+}
+
+QSurface *Q3DSSurfaceViewer::surface() const
+{
+ return d_ptr->m_surface;
+}
+
+QOpenGLContext *Q3DSSurfaceViewer::context() const
+{
+ return d_ptr->m_context;
+}
+
+Q3DSViewerSettings *Q3DSSurfaceViewer::settings() const
+{
+ return d_ptr->m_settings;
+}
+
+Q3DSPresentation *Q3DSSurfaceViewer::presentation() const
+{
+ return d_ptr->m_presentation;
+}
+
+Q3DSSurfaceViewerPrivate::Q3DSSurfaceViewerPrivate(Q3DSSurfaceViewer *q)
+ : QObject(q)
+ , q_ptr(q)
+ , m_viewerApp(nullptr)
+ , m_timer(nullptr)
+ , m_updateInterval(-1)
+ , m_pixelRatio(1.0)
+ , m_fboId(0)
+ , m_surface(nullptr)
+ , m_context(nullptr)
+ , m_autoSize(true)
+ , m_settings(new Q3DSViewerSettings(this))
+ , m_presentation(new Q3DSPresentation(this))
+{
+ connect(m_presentation, &Q3DSPresentation::sourceChanged,
+ this, &Q3DSSurfaceViewerPrivate::reset);
+}
+
+Q3DSSurfaceViewerPrivate::~Q3DSSurfaceViewerPrivate()
+{
+ releaseRuntime();
+
+ delete m_timer;
+}
+
+void Q3DSSurfaceViewerPrivate::reset()
+{
+ if (m_viewerApp) {
+ releaseRuntime();
+ initializeRuntime();
+ }
+}
+
+void Q3DSSurfaceViewerPrivate::setSize(const QSize &size)
+{
+ if (m_size != size) {
+ m_size = size;
+
+ if (m_viewerApp) {
+ m_context->makeCurrent(m_surface);
+ m_viewerApp->Resize(int(m_size.width() * m_pixelRatio),
+ int(m_size.height() * m_pixelRatio));
+ }
+
+ Q_EMIT q_ptr->sizeChanged(m_size);
+ }
+}
+
+void Q3DSSurfaceViewerPrivate::setUpdateInterval(int interval)
+{
+ if (m_updateInterval != interval) {
+ m_updateInterval = interval;
+ resetUpdateTimer();
+ Q_EMIT q_ptr->updateIntervalChanged(m_updateInterval);
+ }
+}
+
+bool Q3DSSurfaceViewerPrivate::initialize(QSurface *surface, QOpenGLContext *context, GLuint fboId)
+{
+ Q_ASSERT(context);
+ Q_ASSERT(surface);
+
+ if (m_presentation->source().isEmpty()) {
+ qWarning("Failed to initialize Q3DSSurfaceViewer,"
+ " presentation source must be set before calling initialize()");
+ return false;
+ }
+
+ QFileInfo info(Q3DSUtils::urlToLocalFileOrQrc(m_presentation->source()));
+ if (!info.exists()) {
+ qWarning() << "Failed to initialize Q3DSSurfaceViewer, the presentation doesn't exist:"
+ << m_presentation->source().toString();
+ return false;
+ }
+
+ shutdown();
+
+ m_surface = surface;
+ m_context = context;
+ m_fboId = fboId;
+ if (m_surface->surfaceClass() == QSurface::Window && fboId == 0)
+ m_pixelRatio = static_cast<QWindow *>(m_surface)->devicePixelRatio();
+
+ surfaceObject()->installEventFilter(this);
+
+ connect(context, &QOpenGLContext::aboutToBeDestroyed, this, &Q3DSSurfaceViewerPrivate::shutdown);
+
+ bool success = initializeRuntime();
+
+ if (success)
+ Q_EMIT q_ptr->runningChanged(true);
+
+ return success;
+}
+
+
+void Q3DSSurfaceViewerPrivate::shutdown()
+{
+ bool oldInitialized = (m_viewerApp != nullptr);
+
+ if (m_context) {
+ disconnect(m_context, &QOpenGLContext::aboutToBeDestroyed,
+ this, &Q3DSSurfaceViewerPrivate::shutdown);
+ }
+
+ if (m_surface)
+ surfaceObject()->removeEventFilter(this);
+
+ releaseRuntime();
+
+ m_surface = nullptr;
+ m_context = nullptr;
+ m_fboId = 0;
+
+ if (oldInitialized)
+ Q_EMIT q_ptr->runningChanged(false);
+}
+
+
+void Q3DSSurfaceViewerPrivate::update()
+{
+ if (m_viewerApp && m_viewerApp->IsInitialised()) {
+ if (m_surface->surfaceClass() != QSurface::Window
+ || static_cast<QWindow *>(m_surface)->isExposed()) {
+ m_context->makeCurrent(m_surface);
+ if (m_autoSize)
+ setSize(m_surface->size());
+ m_viewerApp->Render();
+
+ if (m_fboId == 0)
+ m_context->swapBuffers(m_surface);
+ }
+ }
+}
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
+ bool include_alpha);
+
+QImage Q3DSSurfaceViewerPrivate::grab(const QRect &rect)
+{
+ QRect captureRect;
+ QSize fullSize = m_size * m_pixelRatio;
+ if (rect.isValid()) {
+ captureRect = QRect(rect.x() * m_pixelRatio, rect.y() * m_pixelRatio,
+ rect.width() * m_pixelRatio, rect.height() * m_pixelRatio);
+ } else {
+ captureRect = QRect(0, 0, fullSize.width(), fullSize.height());
+ }
+ QImage image(captureRect.size(), QImage::Format_ARGB32);
+
+ if (m_surface && m_context && m_viewerApp && m_viewerApp->IsInitialised()
+ && (m_surface->surfaceClass() != QSurface::Window
+ || static_cast<QWindow *>(m_surface)->isExposed())) {
+ m_context->makeCurrent(m_surface);
+
+ // Render now to ensure the image is up to date and will actually exist in case
+ // the surface has a non-preserved swap buffer
+ if (m_autoSize)
+ setSize(m_surface->size());
+ m_viewerApp->Render();
+
+ m_context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_fboId);
+ QImage fullGrab = qt_gl_read_framebuffer(fullSize, false, false);
+
+ // Also update the screen to match the grab, since we just rendered
+ if (m_fboId == 0)
+ m_context->swapBuffers(m_surface);
+
+ if (captureRect.size() == fullSize)
+ image = fullGrab;
+ else
+ image = fullGrab.copy(captureRect);
+ }
+
+ return image;
+}
+
+bool Q3DSSurfaceViewerPrivate::eventFilter(QObject *obj, QEvent *e)
+{
+ if (m_surface && e->type() == QEvent::PlatformSurface) {
+ if (surfaceObject() == obj) {
+ QPlatformSurfaceEvent *ev = static_cast<QPlatformSurfaceEvent *>(e);
+ if (ev->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ shutdown();
+ }
+ }
+ return QObject::eventFilter(obj, e);
+}
+
+bool Q3DSSurfaceViewerPrivate::initializeRuntime()
+{
+ Q_ASSERT(!m_viewerApp);
+
+ m_context->makeCurrent(m_surface);
+
+ m_viewerApp = &UICViewerApp::Create(m_context, new CUICAudioPlayerImpl());
+
+ Q_ASSERT(m_viewerApp);
+
+ const QString localSource = Q3DSUtils::urlToLocalFileOrQrc(m_presentation->source());
+
+ if (m_autoSize)
+ m_size = m_surface->size();
+
+ if (!m_viewerApp->InitializeApp(int(m_size.width() * m_pixelRatio),
+ int(m_size.height() * m_pixelRatio),
+ m_context->format(), m_fboId, localSource,
+ m_presentation->d_ptr->streamProxy())) {
+ releaseRuntime();
+ qWarning("Failed to initialize runtime");
+ return false;
+ }
+
+ m_settings->d_ptr->setViewerApp(m_viewerApp);
+ m_presentation->d_ptr->setViewerApp(m_viewerApp);
+
+ resetUpdateTimer();
+
+ return true;
+}
+
+void Q3DSSurfaceViewerPrivate::releaseRuntime()
+{
+ m_settings->d_ptr->setViewerApp(nullptr);
+ m_presentation->d_ptr->setViewerApp(nullptr);
+
+ if (m_context && m_surface)
+ m_context->makeCurrent(m_surface);
+
+ if (m_viewerApp) {
+ m_viewerApp->Release();
+ m_viewerApp = nullptr;
+ }
+
+ resetUpdateTimer();
+}
+
+void Q3DSSurfaceViewerPrivate::resetUpdateTimer()
+{
+ if (m_viewerApp && m_updateInterval >= 0) {
+ if (!m_timer) {
+ m_timer = new QTimer();
+ connect(m_timer, &QTimer::timeout, this, &Q3DSSurfaceViewerPrivate::update);
+ }
+ m_timer->start(m_updateInterval);
+ } else if (m_timer) {
+ m_timer->stop();
+ }
+}
+
+QObject *Q3DSSurfaceViewerPrivate::surfaceObject()
+{
+ if (m_surface) {
+ if (m_surface->surfaceClass() == QSurface::Window)
+ return static_cast<QWindow *>(m_surface);
+ else
+ return static_cast<QOffscreenSurface *>(m_surface);
+ }
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/q3dssurfaceviewer.h b/src/Viewer/studio3d/q3dssurfaceviewer.h
new file mode 100644
index 00000000..39f6317d
--- /dev/null
+++ b/src/Viewer/studio3d/q3dssurfaceviewer.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSSURFACEVIEWER_H
+#define Q3DSSURFACEVIEWER_H
+
+#include <QtStudio3D/qstudio3dglobal.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qopengl.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSSurfaceViewerPrivate;
+class QSurface;
+class QOpenGLContext;
+class Q3DSViewerSettings;
+class Q3DSPresentation;
+
+class Q_STUDIO3D_EXPORT Q3DSSurfaceViewer : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3DSSurfaceViewer)
+ Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
+ Q_PROPERTY(bool autoSize READ autoSize WRITE setAutoSize NOTIFY autoSizeChanged)
+ Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval NOTIFY updateIntervalChanged)
+ Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged)
+
+public:
+ explicit Q3DSSurfaceViewer(QObject *parent = nullptr);
+ ~Q3DSSurfaceViewer();
+
+ bool initialize(QSurface *surface, QOpenGLContext *context, GLuint fboId = 0);
+
+ QImage grab(const QRect &rect = QRect());
+
+ // Property accessors
+ QSize size() const;
+ bool autoSize() const;
+ int updateInterval() const;
+ bool isRunning() const;
+
+ int fboId() const;
+ QSurface *surface() const;
+ QOpenGLContext *context() const;
+
+ Q3DSViewerSettings *settings() const;
+ Q3DSPresentation *presentation() const;
+
+public Q_SLOTS:
+ void setSize(const QSize &size);
+ void setAutoSize(bool autoSize);
+ void setUpdateInterval(int interval);
+ void update();
+ void shutdown();
+ void reset();
+
+Q_SIGNALS:
+ void sizeChanged(const QSize &size);
+ void autoSizeChanged(bool autoSize);
+ void updateIntervalChanged(bool autoUpdate);
+ void runningChanged(bool initialized);
+
+private:
+ Q_DISABLE_COPY(Q3DSSurfaceViewer)
+ Q3DSSurfaceViewerPrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSSURFACEVIEWER_H
diff --git a/src/Viewer/studio3d/q3dssurfaceviewer_p.h b/src/Viewer/studio3d/q3dssurfaceviewer_p.h
new file mode 100644
index 00000000..f038de3f
--- /dev/null
+++ b/src/Viewer/studio3d/q3dssurfaceviewer_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSSURFACEVIEWER_P_H
+#define Q3DSSURFACEVIEWER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "q3dssurfaceviewer.h"
+#include "UICViewerApp.h"
+
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSurface;
+class QOpenGLContext;
+class Q3DSViewerSettings;
+class Q3DSPresentation;
+
+class Q_STUDIO3D_EXPORT Q3DSSurfaceViewerPrivate : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PUBLIC(Q3DSSurfaceViewer)
+public:
+ explicit Q3DSSurfaceViewerPrivate(Q3DSSurfaceViewer *parent = nullptr);
+ ~Q3DSSurfaceViewerPrivate();
+
+ void reset();
+ void setSize(const QSize &size);
+ void setUpdateInterval(int interval);
+ bool initialize(QSurface *surface, QOpenGLContext *context, GLuint fboId);
+ void update();
+
+ QImage grab(const QRect &rect);
+
+private Q_SLOTS:
+ void shutdown();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *e) override;
+
+private:
+ bool initializeRuntime();
+ void releaseRuntime();
+ void resetUpdateTimer();
+ QObject *surfaceObject();
+
+ Q3DSSurfaceViewer *q_ptr;
+
+ UICViewer::UICViewerApp *m_viewerApp;
+ QSize m_size;
+ QTimer *m_timer;
+ int m_updateInterval;
+ qreal m_pixelRatio;
+ GLuint m_fboId;
+ QSurface *m_surface; // Not owned
+ QOpenGLContext *m_context; // Not owned
+ bool m_autoSize;
+ Q3DSViewerSettings *m_settings;
+ Q3DSPresentation *m_presentation;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSSURFACEVIEWER_P_H
diff --git a/src/Viewer/studio3d/q3dsviewersettings.cpp b/src/Viewer/studio3d/q3dsviewersettings.cpp
new file mode 100644
index 00000000..e68a314d
--- /dev/null
+++ b/src/Viewer/studio3d/q3dsviewersettings.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dsviewersettings_p.h"
+#include "UICViewerApp.h"
+#include "q3dscommandqueue_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+Q3DSViewerSettings::Q3DSViewerSettings(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new Q3DSViewerSettingsPrivate(this))
+{
+}
+
+Q3DSViewerSettings::~Q3DSViewerSettings()
+{
+}
+
+QColor Q3DSViewerSettings::matteColor() const
+{
+ return d_ptr->m_matteColor;
+}
+
+bool Q3DSViewerSettings::isShowRenderStats() const
+{
+ return d_ptr->m_showRenderStats;
+}
+
+Q3DSViewerSettings::ShadeMode Q3DSViewerSettings::shadeMode() const
+{
+ return d_ptr->m_shadeMode;
+}
+
+Q3DSViewerSettings::ScaleMode Q3DSViewerSettings::scaleMode() const
+{
+ return d_ptr->m_scaleMode;
+}
+
+void Q3DSViewerSettings::save(const QString &group, const QString &organization,
+ const QString &application)
+{
+ d_ptr->save(group, organization, application);
+}
+
+void Q3DSViewerSettings::load(const QString &group, const QString &organization,
+ const QString &application)
+{
+ d_ptr->load(group, organization, application);
+}
+
+void Q3DSViewerSettings::setMatteColor(const QColor &color)
+{
+ if (d_ptr->m_matteColor != color) {
+ d_ptr->setMatteColor(color);
+ Q_EMIT matteColorChanged(color);
+ }
+}
+
+void Q3DSViewerSettings::setShowRenderStats(bool show)
+{
+ if (d_ptr->m_showRenderStats != show) {
+ d_ptr->setShowRenderStats(show);
+ Q_EMIT showRenderStatsChanged(show);
+ }
+}
+
+void Q3DSViewerSettings::setShadeMode(Q3DSViewerSettings::ShadeMode mode)
+{
+ if (d_ptr->m_shadeMode != mode) {
+ d_ptr->setShadeMode(mode);
+ Q_EMIT shadeModeChanged(mode);
+ }
+
+}
+
+void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode)
+{
+ if (d_ptr->m_scaleMode != mode) {
+ d_ptr->setScaleMode(mode);
+ Q_EMIT scaleModeChanged(mode);
+ }
+}
+
+Q3DSViewerSettingsPrivate::Q3DSViewerSettingsPrivate(Q3DSViewerSettings *q)
+ : QObject(q)
+ , q_ptr(q)
+ , m_viewerApp(nullptr)
+ , m_commandQueue(nullptr)
+ , m_matteColor(Qt::black)
+ , m_showRenderStats(false)
+ , m_shadeMode(Q3DSViewerSettings::ShadeModeShaded)
+ , m_scaleMode(Q3DSViewerSettings::ScaleModeCenter)
+ , m_savedSettings(nullptr)
+{
+}
+
+Q3DSViewerSettingsPrivate::~Q3DSViewerSettingsPrivate()
+{
+}
+
+void Q3DSViewerSettingsPrivate::setViewerApp(UICViewer::UICViewerApp *app)
+{
+ m_viewerApp = app;
+ if (m_viewerApp) {
+ setMatteColor(m_matteColor);
+ setShowRenderStats(m_showRenderStats);
+ setShadeMode(m_shadeMode);
+ setScaleMode(m_scaleMode);
+ }
+}
+
+void Q3DSViewerSettingsPrivate::setCommandQueue(CommandQueue *queue)
+{
+ m_commandQueue = queue;
+ if (m_commandQueue) {
+ setMatteColor(m_matteColor);
+ setShowRenderStats(m_showRenderStats);
+ setShadeMode(m_shadeMode);
+ setScaleMode(m_scaleMode);
+ }
+}
+
+void Q3DSViewerSettingsPrivate::save(const QString &group, const QString &organization,
+ const QString &application)
+{
+ initSettingsStore(group, organization, application);
+
+ m_savedSettings->setValue(QStringLiteral("matteColor"), m_matteColor);
+ m_savedSettings->setValue(QStringLiteral("showRenderStats"), m_showRenderStats);
+ m_savedSettings->setValue(QStringLiteral("shadeMode"), m_shadeMode);
+ m_savedSettings->setValue(QStringLiteral("scaleMode"), m_scaleMode);
+}
+
+void Q3DSViewerSettingsPrivate::load(const QString &group, const QString &organization,
+ const QString &application)
+{
+ initSettingsStore(group, organization, application);
+
+ q_ptr->setMatteColor(m_savedSettings->value(QStringLiteral("matteColor")).value<QColor>());
+ q_ptr->setShowRenderStats(m_savedSettings->value(QStringLiteral("showRenderStats")).toBool());
+ q_ptr->setShadeMode(Q3DSViewerSettings::ShadeMode(
+ m_savedSettings->value(QStringLiteral("shadeMode")).toInt()));
+ q_ptr->setScaleMode(Q3DSViewerSettings::ScaleMode(
+ m_savedSettings->value(QStringLiteral("scaleMode")).toInt()));
+}
+
+void Q3DSViewerSettingsPrivate::setMatteColor(const QColor &color)
+{
+ m_matteColor = color;
+ if (m_viewerApp) {
+ m_viewerApp->setMatteColor(color);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_matteColor = color;
+ m_commandQueue->m_matteColorChanged = true;
+ }
+}
+
+void Q3DSViewerSettingsPrivate::setShowRenderStats(bool show)
+{
+ m_showRenderStats = show;
+ if (m_viewerApp) {
+ m_viewerApp->setShowOnScreenStats(show);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_showRenderStats = show;
+ m_commandQueue->m_showRenderStatsChanged = true;
+ }
+}
+
+void Q3DSViewerSettingsPrivate::setShadeMode(Q3DSViewerSettings::ShadeMode mode)
+{
+ m_shadeMode = mode;
+ if (m_viewerApp) {
+ if (mode == Q3DSViewerSettings::ShadeModeShaded)
+ m_viewerApp->SetShadeMode(UICViewer::ViewerShadeModes::Shaded);
+ else
+ m_viewerApp->SetShadeMode(UICViewer::ViewerShadeModes::ShadedWireframe);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_shadeMode = mode;
+ m_commandQueue->m_shadeModeChanged = true;
+ }
+}
+
+void Q3DSViewerSettingsPrivate::setScaleMode(Q3DSViewerSettings::ScaleMode mode)
+{
+ m_scaleMode = mode;
+ if (m_viewerApp) {
+ if (mode == Q3DSViewerSettings::ScaleModeFit)
+ m_viewerApp->SetScaleMode(UICViewer::ViewerScaleModes::ScaleToFit);
+ else if (mode == Q3DSViewerSettings::ScaleModeFill)
+ m_viewerApp->SetScaleMode(UICViewer::ViewerScaleModes::ScaleToFill);
+ else
+ m_viewerApp->SetScaleMode(UICViewer::ViewerScaleModes::ExactSize);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_scaleMode = mode;
+ m_commandQueue->m_scaleModeChanged = true;
+ }
+}
+
+void Q3DSViewerSettingsPrivate::initSettingsStore(const QString &group, const QString &organization,
+ const QString &application)
+{
+ if (!m_savedSettings) {
+ QString org = organization.isEmpty() ? QCoreApplication::instance()->organizationName()
+ : organization;
+ QString app = application.isEmpty() ? QCoreApplication::instance()->applicationName()
+ : application;
+
+ m_savedSettings = new QSettings(org, app, this);
+ m_savedSettings->beginGroup(group);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/q3dsviewersettings.h b/src/Viewer/studio3d/q3dsviewersettings.h
new file mode 100644
index 00000000..312107a3
--- /dev/null
+++ b/src/Viewer/studio3d/q3dsviewersettings.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSVIEWERSETTINGS_H
+#define Q3DSVIEWERSETTINGS_H
+
+#include <QtStudio3D/qstudio3dglobal.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSViewerSettingsPrivate;
+
+class Q_STUDIO3D_EXPORT Q3DSViewerSettings : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3DSViewerSettings)
+ Q_ENUMS(ShadeMode)
+ Q_ENUMS(ScaleMode)
+ Q_PROPERTY(QColor matteColor READ matteColor WRITE setMatteColor NOTIFY matteColorChanged)
+ Q_PROPERTY(bool showRenderStats READ isShowRenderStats WRITE setShowRenderStats NOTIFY showRenderStatsChanged)
+ Q_PROPERTY(ShadeMode shadeMode READ shadeMode WRITE setShadeMode NOTIFY shadeModeChanged)
+ Q_PROPERTY(ScaleMode scaleMode READ scaleMode WRITE setScaleMode NOTIFY scaleModeChanged)
+
+public:
+ enum ShadeMode {
+ ShadeModeShaded,
+ ShadeModeShadedWireframe
+ };
+
+ enum ScaleMode {
+ ScaleModeFit,
+ ScaleModeFill,
+ ScaleModeCenter
+ };
+
+ explicit Q3DSViewerSettings(QObject *parent = nullptr);
+ ~Q3DSViewerSettings();
+
+ QColor matteColor() const;
+ bool isShowRenderStats() const;
+ ShadeMode shadeMode() const;
+ ScaleMode scaleMode() const;
+
+ Q_INVOKABLE void save(const QString &group, const QString &organization = QString(),
+ const QString &application = QString());
+ Q_INVOKABLE void load(const QString &group, const QString &organization = QString(),
+ const QString &application = QString());
+
+public Q_SLOTS:
+ void setMatteColor(const QColor &color);
+ void setShowRenderStats(bool show);
+ void setShadeMode(ShadeMode mode);
+ void setScaleMode(ScaleMode mode);
+
+Q_SIGNALS:
+ void matteColorChanged(const QColor &color);
+ void showRenderStatsChanged(bool show);
+ void shadeModeChanged(ShadeMode mode);
+ void scaleModeChanged(ScaleMode mode);
+
+private:
+ Q_DISABLE_COPY(Q3DSViewerSettings)
+ Q3DSViewerSettingsPrivate *d_ptr;
+
+ friend class Q3DSSurfaceViewerPrivate;
+ friend class Q3DSWidgetPrivate;
+ friend class Q3DSRenderer;
+ friend class Q3DSView;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSVIEWERSETTINGS_H
diff --git a/src/Viewer/studio3d/q3dsviewersettings_p.h b/src/Viewer/studio3d/q3dsviewersettings_p.h
new file mode 100644
index 00000000..6f34d439
--- /dev/null
+++ b/src/Viewer/studio3d/q3dsviewersettings_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSVIEWERSETTINGS_P_H
+#define Q3DSVIEWERSETTINGS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "q3dsviewersettings.h"
+#include "UICViewerApp.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSettings;
+class CommandQueue;
+
+class Q_STUDIO3D_EXPORT Q3DSViewerSettingsPrivate : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PUBLIC(Q3DSViewerSettings)
+public:
+ explicit Q3DSViewerSettingsPrivate(Q3DSViewerSettings *parent);
+ ~Q3DSViewerSettingsPrivate();
+
+ void setViewerApp(UICViewer::UICViewerApp *app);
+ void setCommandQueue(CommandQueue *queue);
+ void save(const QString &group, const QString &organization, const QString &application);
+ void load(const QString &group, const QString &organization, const QString &application);
+
+ void setMatteColor(const QColor &color);
+ void setShowRenderStats(bool show);
+ void setShadeMode(Q3DSViewerSettings::ShadeMode mode);
+ void setScaleMode(Q3DSViewerSettings::ScaleMode mode);
+
+public:
+ Q3DSViewerSettings *q_ptr;
+
+private:
+ void initSettingsStore(const QString &group, const QString &organization,
+ const QString &application);
+
+ UICViewer::UICViewerApp *m_viewerApp; // Not owned
+ CommandQueue *m_commandQueue; // Not owned
+ QColor m_matteColor;
+ bool m_showRenderStats;
+ Q3DSViewerSettings::ShadeMode m_shadeMode;
+ Q3DSViewerSettings::ScaleMode m_scaleMode;
+ QSettings *m_savedSettings;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSVIEWERSETTINGS_P_H
diff --git a/src/Viewer/studio3d/q3dswidget.cpp b/src/Viewer/studio3d/q3dswidget.cpp
new file mode 100644
index 00000000..e079eb8d
--- /dev/null
+++ b/src/Viewer/studio3d/q3dswidget.cpp
@@ -0,0 +1,327 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3dswidget_p.h"
+#include "UICAudioPlayerImpl.h"
+#include "viewerqmlstreamproxy_p.h"
+#include "q3dsviewersettings_p.h"
+#include "q3dspresentation_p.h"
+#include "studioutils_p.h"
+
+#include <QtGui/qevent.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/QWindow>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdebug.h>
+
+using namespace UICViewer;
+
+QT_BEGIN_NAMESPACE
+
+typedef void (QWidget::*QWidgetVoidSlot)();
+
+Q3DSWidget::Q3DSWidget(QWidget *parent)
+ : QOpenGLWidget(parent)
+ , d_ptr(new Q3DSWidgetPrivate(this))
+{
+ // Get keyboard handling
+ setFocusPolicy(Qt::StrongFocus);
+ setMouseTracking(true);
+}
+
+Q3DSWidget::~Q3DSWidget()
+{
+ delete d_ptr;
+}
+
+bool Q3DSWidget::initialize()
+{
+ return d_ptr->initialize();
+}
+
+int Q3DSWidget::updateInterval() const
+{
+ return d_ptr->m_updateInterval;
+}
+
+bool Q3DSWidget::isRunning() const
+{
+ return d_ptr->m_viewerApp != nullptr;
+}
+
+Q3DSViewerSettings *Q3DSWidget::settings() const
+{
+ return d_ptr->settings();
+}
+
+Q3DSPresentation *Q3DSWidget::presentation() const
+{
+ return d_ptr->presentation();
+}
+
+void Q3DSWidget::initializeGL()
+{
+ // Find the native window to determine pixel ratio
+ QWidget *widget = this;
+ QWindow *window = windowHandle();
+ while (widget && window == nullptr) {
+ widget = qobject_cast<QWidget *>(widget->parent());
+ window = widget->windowHandle();
+ }
+ if (window)
+ d_ptr->m_pixelRatio = window->devicePixelRatio();
+}
+
+void Q3DSWidget::resizeGL(int w, int h)
+{
+ if (d_ptr->m_viewerApp)
+ d_ptr->m_viewerApp->Resize(int(w * d_ptr->m_pixelRatio), int(h * d_ptr->m_pixelRatio));
+}
+
+void Q3DSWidget::paintGL()
+{
+ if (d_ptr->m_viewerApp && d_ptr->m_viewerApp->IsInitialised())
+ d_ptr->m_viewerApp->Render();
+}
+
+void Q3DSWidget::setUpdateInterval(int interval)
+{
+ d_ptr->setUpdateInterval(interval);
+}
+
+void Q3DSWidget::shutdown()
+{
+ d_ptr->shutdown();
+}
+
+void Q3DSWidget::reset()
+{
+ d_ptr->reset();
+}
+
+void Q3DSWidget::mousePressEvent(QMouseEvent *event)
+{
+ if (d_ptr->m_pixelRatio != 1.0) {
+ QMouseEvent scaledEvent(event->type(), event->pos() * d_ptr->m_pixelRatio,
+ event->button(), event->buttons(), event->modifiers());
+ d_ptr->m_presentation->mousePressEvent(&scaledEvent);
+ } else {
+ d_ptr->m_presentation->mousePressEvent(event);
+ }
+}
+
+void Q3DSWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (d_ptr->m_pixelRatio != 1.0) {
+ QMouseEvent scaledEvent(event->type(), event->pos() * d_ptr->m_pixelRatio,
+ event->button(), event->buttons(), event->modifiers());
+ d_ptr->m_presentation->mouseReleaseEvent(&scaledEvent);
+ } else {
+ d_ptr->m_presentation->mouseReleaseEvent(event);
+ }
+}
+
+void Q3DSWidget::mouseMoveEvent(QMouseEvent *event)
+{
+ if (d_ptr->m_pixelRatio != 1.0) {
+ QMouseEvent scaledEvent(event->type(), event->pos() * d_ptr->m_pixelRatio,
+ event->button(), event->buttons(), event->modifiers());
+ d_ptr->m_presentation->mouseMoveEvent(&scaledEvent);
+ } else {
+ d_ptr->m_presentation->mouseMoveEvent(event);
+ }
+}
+
+void Q3DSWidget::wheelEvent(QWheelEvent *event)
+{
+ d_ptr->m_presentation->wheelEvent(event);
+}
+
+void Q3DSWidget::keyPressEvent(QKeyEvent *event)
+{
+ d_ptr->m_presentation->keyPressEvent(event);
+}
+
+void Q3DSWidget::keyReleaseEvent(QKeyEvent *event)
+{
+ d_ptr->m_presentation->keyReleaseEvent(event);
+}
+
+Q3DSWidgetPrivate::Q3DSWidgetPrivate(Q3DSWidget *q)
+ : QObject(q)
+ , q_ptr(q)
+ , m_viewerApp(nullptr)
+ , m_timer(nullptr)
+ , m_updateInterval(-1)
+ , m_pixelRatio(1.0)
+ , m_settings(new Q3DSViewerSettings(this))
+ , m_presentation(new Q3DSPresentation(this))
+{
+ connect(m_presentation, &Q3DSPresentation::sourceChanged, this, &Q3DSWidgetPrivate::reset);
+}
+
+Q3DSWidgetPrivate::~Q3DSWidgetPrivate()
+{
+ releaseRuntime();
+
+ delete m_timer;
+}
+
+void Q3DSWidgetPrivate::reset()
+{
+ if (m_viewerApp) {
+ releaseRuntime();
+ initializeRuntime();
+ }
+}
+
+void Q3DSWidgetPrivate::setUpdateInterval(int interval)
+{
+ if (m_updateInterval != interval) {
+ m_updateInterval = interval;
+ resetUpdateTimer();
+ Q_EMIT q_ptr->updateIntervalChanged(m_updateInterval);
+ }
+}
+
+bool Q3DSWidgetPrivate::initialize()
+{
+ Q_ASSERT(q_ptr->context());
+
+ if (m_presentation->source().isEmpty()) {
+ qWarning("Failed to initialize Q3DSWidget,"
+ " presentation source must be set before calling initialize()");
+ return false;
+ }
+
+ QFileInfo info(Q3DSUtils::urlToLocalFileOrQrc(m_presentation->source()));
+ if (!info.exists()) {
+ qWarning() << "Failed to initialize Q3DSWidget, the presentation doesn't exist:"
+ << m_presentation->source().toString();
+ return false;
+ }
+
+ shutdown();
+
+ connect(q_ptr->context(), &QOpenGLContext::aboutToBeDestroyed,
+ this, &Q3DSWidgetPrivate::shutdown);
+
+ bool success = initializeRuntime();
+
+ if (success)
+ Q_EMIT q_ptr->runningChanged(true);
+
+ return success;
+}
+
+Q3DSViewerSettings *Q3DSWidgetPrivate::settings()
+{
+ return m_settings;
+}
+
+Q3DSPresentation *Q3DSWidgetPrivate::presentation()
+{
+ return m_presentation;
+}
+
+void Q3DSWidgetPrivate::shutdown()
+{
+ bool oldInitialized = (m_viewerApp != nullptr);
+
+ if (q_ptr->context()) {
+ disconnect(q_ptr->context(), &QOpenGLContext::aboutToBeDestroyed,
+ this, &Q3DSWidgetPrivate::shutdown);
+ }
+
+ releaseRuntime();
+
+ if (oldInitialized)
+ Q_EMIT q_ptr->runningChanged(false);
+}
+
+bool Q3DSWidgetPrivate::initializeRuntime()
+{
+ Q_ASSERT(!m_viewerApp);
+
+ q_ptr->makeCurrent();
+
+ m_viewerApp = &UICViewerApp::Create(q_ptr->context(), new CUICAudioPlayerImpl());
+
+ Q_ASSERT(m_viewerApp);
+
+ const QString localSource = Q3DSUtils::urlToLocalFileOrQrc(m_presentation->source());
+
+ if (!m_viewerApp->InitializeApp(int(q_ptr->width() * m_pixelRatio),
+ int(q_ptr->height() * m_pixelRatio),
+ q_ptr->context()->format(),
+ q_ptr->defaultFramebufferObject(), localSource,
+ m_presentation->d_ptr->streamProxy())) {
+ releaseRuntime();
+ qWarning("Failed to initialize runtime");
+ return false;
+ }
+
+ m_settings->d_ptr->setViewerApp(m_viewerApp);
+ m_presentation->d_ptr->setViewerApp(m_viewerApp);
+
+ resetUpdateTimer();
+
+ return true;
+}
+
+void Q3DSWidgetPrivate::releaseRuntime()
+{
+ m_settings->d_ptr->setViewerApp(nullptr);
+ m_presentation->d_ptr->setViewerApp(nullptr);
+
+ if (m_viewerApp) {
+ q_ptr->makeCurrent();
+ m_viewerApp->Release();
+ m_viewerApp = nullptr;
+ }
+
+ resetUpdateTimer();
+}
+
+void Q3DSWidgetPrivate::resetUpdateTimer()
+{
+ if (m_viewerApp && m_updateInterval >= 0) {
+ if (!m_timer) {
+ m_timer = new QTimer();
+ connect(m_timer, &QTimer::timeout,
+ q_ptr, static_cast<QWidgetVoidSlot>(&QWidget::update));
+ }
+ m_timer->start(m_updateInterval);
+ } else if (m_timer) {
+ m_timer->stop();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/q3dswidget.h b/src/Viewer/studio3d/q3dswidget.h
new file mode 100644
index 00000000..ad5d823d
--- /dev/null
+++ b/src/Viewer/studio3d/q3dswidget.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3DSWIDGET_H
+#define Q3DSWIDGET_H
+
+#include <QtStudio3D/qstudio3dglobal.h>
+#include <QtWidgets/QOpenGLWidget>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSWidgetPrivate;
+class Q3DSViewerSettings;
+class Q3DSPresentation;
+
+class Q_STUDIO3D_EXPORT Q3DSWidget : public QOpenGLWidget
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(Q3DSWidget)
+ Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval NOTIFY updateIntervalChanged)
+ Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged)
+
+public:
+ explicit Q3DSWidget(QWidget *parent = nullptr);
+ virtual ~Q3DSWidget();
+
+ bool initialize();
+
+ // Property accessors
+ int updateInterval() const;
+ bool isRunning() const;
+
+ Q3DSViewerSettings *settings() const;
+ Q3DSPresentation *presentation() const;
+
+public Q_SLOTS:
+ void setUpdateInterval(int interval);
+ void shutdown();
+ void reset();
+
+Q_SIGNALS:
+ void updateIntervalChanged(bool autoUpdate);
+ void runningChanged(bool initialized);
+
+protected:
+ // Qt event handling
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void wheelEvent(QWheelEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *e) override;
+
+ // Qt overrides
+ void initializeGL() override;
+ void resizeGL(int w, int h) override;
+ void paintGL() override;
+
+private:
+ Q_DISABLE_COPY(Q3DSWidget)
+ Q3DSWidgetPrivate *d_ptr;
+};
+QT_END_NAMESPACE
+#endif // Q3DSWIDGET_H
diff --git a/src/Viewer/studio3d/q3dswidget_p.h b/src/Viewer/studio3d/q3dswidget_p.h
new file mode 100644
index 00000000..5a919081
--- /dev/null
+++ b/src/Viewer/studio3d/q3dswidget_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 - 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Q3DSWIDGET_P_H
+#define Q3DSWIDGET_P_H
+
+#include "q3dswidget.h"
+#include "UICViewerApp.h"
+
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSViewerSettings;
+class Q3DSPresentation;
+
+class Q_STUDIO3D_EXPORT Q3DSWidgetPrivate : public QObject
+{
+public:
+ Q_OBJECT
+ Q_DECLARE_PUBLIC(Q3DSWidget)
+
+public:
+ explicit Q3DSWidgetPrivate(Q3DSWidget *q);
+ virtual ~Q3DSWidgetPrivate();
+
+ void reset();
+ void setUpdateInterval(int interval);
+ bool initialize();
+
+ Q3DSViewerSettings *settings();
+ Q3DSPresentation *presentation();
+
+private Q_SLOTS:
+ void shutdown();
+
+private:
+ bool initializeRuntime();
+ void releaseRuntime();
+ void resetUpdateTimer();
+
+ Q3DSWidget *q_ptr;
+
+ UICViewer::UICViewerApp *m_viewerApp;
+ QTimer *m_timer;
+ int m_updateInterval;
+ qreal m_pixelRatio;
+
+ Q3DSViewerSettings *m_settings;
+ Q3DSPresentation *m_presentation;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSWIDGET_P_H
diff --git a/src/Viewer/studio3d/qstudio3dglobal.h b/src/Viewer/studio3d/qstudio3dglobal.h
new file mode 100644
index 00000000..d1960634
--- /dev/null
+++ b/src/Viewer/studio3d/qstudio3dglobal.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTUDIO3D_GLOBAL_H
+#define QSTUDIO3D_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_STATIC
+# if defined(QT_BUILD_STUDIO3D_LIB)
+# define Q_STUDIO3D_EXPORT Q_DECL_EXPORT
+# else
+# define Q_STUDIO3D_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define Q_STUDIO3D_EXPORT
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QSTUDIO3D_GLOBAL_H
diff --git a/src/Viewer/studio3d/studio3d.pri b/src/Viewer/studio3d/studio3d.pri
new file mode 100644
index 00000000..a4a10d83
--- /dev/null
+++ b/src/Viewer/studio3d/studio3d.pri
@@ -0,0 +1,35 @@
+HEADERS += \
+ q3dswidget.h \
+ q3dswidget_p.h \
+ q3dssurfaceviewer.h \
+ q3dssurfaceviewer_p.h \
+ qstudio3dglobal.h \
+ viewerqmlstreamproxy_p.h \
+ q3dsviewersettings.h \
+ q3dsviewersettings_p.h \
+ q3dspresentation.h \
+ q3dspresentation_p.h \
+ q3dssceneelement.h \
+ q3dssceneelement_p.h \
+ q3dselement.h \
+ q3dselement_p.h \
+ studioutils_p.h \
+ q3dscommandqueue_p.h
+
+SOURCES += q3dswidget.cpp \
+ q3dssurfaceviewer.cpp \
+ viewerqmlstreamproxy.cpp \
+ q3dsviewersettings.cpp \
+ q3dspresentation.cpp \
+ q3dssceneelement.cpp \
+ q3dselement.cpp \
+ studioutils.cpp \
+ q3dscommandqueue.cpp
+
+macos {
+INCLUDEPATH += $$PWD/../../Runtime/SDKsAndTools/nvap_sdk/libs/inc
+}
+
+android {
+SOURCES += $$PWD/../../Runtime/Source/PlatformSpecific/Android/jni/Qt3DSLibs/nv_thread/nv_thread.c
+}
diff --git a/src/Viewer/studio3d/studio3d.pro b/src/Viewer/studio3d/studio3d.pro
new file mode 100644
index 00000000..403ee3ac
--- /dev/null
+++ b/src/Viewer/studio3d/studio3d.pro
@@ -0,0 +1,21 @@
+TARGET = QtStudio3D
+
+include($$PWD/../../Runtime/commoninclude.pri)
+QT += opengl widgets qml
+
+qtHaveModule(multimedia) {
+DEFINES += PLATFORM_HAS_QT_MULTIMEDIA_LIB
+QT += multimedia
+}
+CONFIG += console
+DEFINES += QTSTUDIO3D_EXPORTS
+
+LIBS += \
+ -lqt3dsruntime$$qtPlatformTargetSuffix() \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+include(studio3d.pri)
+
+load(qt_module)
+
+OTHER_FILES += $$PWD/../../../doc/src/12-cpp-reference/*
diff --git a/src/Viewer/studio3d/studioutils.cpp b/src/Viewer/studio3d/studioutils.cpp
new file mode 100644
index 00000000..9156be7f
--- /dev/null
+++ b/src/Viewer/studio3d/studioutils.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "studioutils_p.h"
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+QString Q3DSUtils::urlToLocalFileOrQrc(const QUrl &url)
+{
+ const QString scheme(url.scheme().toLower());
+ if (scheme == QLatin1String("qrc")) {
+ if (url.authority().isEmpty())
+ return QLatin1Char(':') + url.path();
+ return QString();
+ }
+
+#if defined(Q_OS_ANDROID)
+ if (scheme == QLatin1String("assets")) {
+ if (url.authority().isEmpty())
+ return url.toString();
+ return QString();
+ }
+#endif
+
+ return url.toLocalFile();
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/studioutils_p.h b/src/Viewer/studio3d/studioutils_p.h
new file mode 100644
index 00000000..afec688c
--- /dev/null
+++ b/src/Viewer/studio3d/studioutils_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#include "qstudio3dglobal.h"
+
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class Q_STUDIO3D_EXPORT Q3DSUtils
+{
+public:
+ static QString urlToLocalFileOrQrc(const QUrl &url);
+};
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/viewerqmlstreamproxy.cpp b/src/Viewer/studio3d/viewerqmlstreamproxy.cpp
new file mode 100644
index 00000000..520dc8c6
--- /dev/null
+++ b/src/Viewer/studio3d/viewerqmlstreamproxy.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "viewerqmlstreamproxy_p.h"
+
+QT_BEGIN_NAMESPACE
+
+ViewerQmlStreamProxy::ViewerQmlStreamProxy(QObject *parent)
+ : Q3DSQmlStreamProxy(parent)
+{
+}
+
+ViewerQmlStreamProxy::~ViewerQmlStreamProxy()
+{
+}
+
+void ViewerQmlStreamProxy::visit(const char *path)
+{
+ setPath(QLatin1String(path));
+}
+
+void ViewerQmlStreamProxy::visit(const char *type, const char *id, const char *src,
+ const char *args)
+{
+ Q_UNUSED(src);
+ QString assetType = QLatin1String(type);
+ QString presentationId = QLatin1String(id);
+ QString presentationArgs = QLatin1String(args);
+ if (assetType == QLatin1String("presentation-qml"))
+ registerPresentation(presentationId, presentationArgs);
+}
+
+QT_END_NAMESPACE
diff --git a/src/Viewer/studio3d/viewerqmlstreamproxy_p.h b/src/Viewer/studio3d/viewerqmlstreamproxy_p.h
new file mode 100644
index 00000000..c0e52d7a
--- /dev/null
+++ b/src/Viewer/studio3d/viewerqmlstreamproxy_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtStudio3D API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#include "qstudio3dglobal.h"
+#include "q3dsqmlstreamproxy.h"
+#include "UICViewerApp.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_STUDIO3D_EXPORT ViewerQmlStreamProxy : public Q3DSQmlStreamProxy,
+ public uic::UICAssetVisitor
+{
+public:
+ ViewerQmlStreamProxy(QObject *parent = nullptr);
+ ~ViewerQmlStreamProxy();
+
+ void visit(const char *path) override;
+ void visit(const char *type, const char *id, const char *src, const char *args) override;
+};
+
+QT_END_NAMESPACE
diff --git a/src/commonplatform.pri b/src/commonplatform.pri
new file mode 100644
index 00000000..740ac080
--- /dev/null
+++ b/src/commonplatform.pri
@@ -0,0 +1,194 @@
+load(qt_build_config)
+load(qt_build_paths)
+
+# Common defines across platforms that should be checked if/where they are used
+# as we remove dependencies to see where we can reduce
+DEFINES += \
+ BOOST_SIGNALS_NO_DEPRECATION_WARNING \
+ QT3DS_FOUNDATION_NO_EXPORTS \
+ _CRT_SECURE_NO_DEPRECATE \
+ _CRT_NONSTDC_NO_DEPRECATE \
+ UIC_FPMODEL_HARDFP \
+ UIC_GRAPHICS_API_GL \
+ UIC_NO_SEARCH_PATH \
+ UIC_RENDER_ENABLE_LOAD_UIP \
+ FONT_NO_RES_DIR \
+ _TEGRA_NO_LOG_FILE \
+ EA_COMPILER_HAS_INTTYPES \
+ EASTL_ALLOCATOR_COPY_ENABLED \
+ OPENKODE \
+ KD \
+ UNICODE \
+ _UNICODE
+
+win32: PlatformSpecificDir = Windows
+macos: PlatformSpecificDir = Macos
+linux|integrity: PlatformSpecificDir = Linux
+android: PlatformSpecificDir = Android/jni
+
+integrity: {
+ DEFINES += _LINUX
+ DEFINES += _INTEGRITYPLATFORM
+}
+
+INCLUDEPATH += $$PWD/Runtime/Source/PlatformSpecific/$$PlatformSpecificDir
+
+THIRDPARTY_DIR = $$(QT3DSTUDIO_3RDPARTY_DIR)
+isEmpty(THIRDPARTY_DIR) {
+ THIRDPARTY_DIR = $$PWD/3rdparty
+}
+
+contains(QT_ARCH, x86_64) {
+ DEFINES += UIC_PROCESSOR_X64
+}
+
+CONFIG(debug, debug|release) {
+ DEFINES += _DEBUG
+} else {
+ DEFINES += NDEBUG
+}
+
+linux {
+ CONFIG += egl
+ DEFINES+=_LINUX UIC_OS_LINUX _LINUXPLATFORM QT3DS_NO_X11 \
+ UICVIEWER_EXPORTS WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+
+ contains(QT_ARCH, x86_64) {
+ BINDIR = $$PWD/../Bin/Linux64
+ } else {
+ BINDIR = $$PWD/../Bin/Linux32
+ }
+ QMAKE_CXXFLAGS_WARN_ON = -Wall -Wno-unused-local-typedefs
+}
+
+integrity {
+ exists($$THIRDPARTY_DIR/boost/1.65.0) {
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.65.0
+ } else {
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.55.0
+ }
+}
+
+macos {
+ DEFINES += _MACOSX _LINUXPLATFORM WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
+
+ BOOSTDIR = /usr/local/lib
+ BOOSTSIGNALLIB = boost_signals-mt
+ BOOSTSYSTEMLIB = boost_system-mt
+ BOOSTFILESYSTEMLIB = boost_filesystem-mt
+
+ contains(QT_ARCH, x86_64) {
+ BINDIR = $$PWD/../Bin/Macosx64
+ } else {
+ BINDIR = $$PWD/../Bin/Macosx32
+ }
+
+ INCLUDEPATH += /usr/local/include
+ # macOS uses GLog from Homebrew, the thirdparty one doesn't work
+ # which also means we use Boost from Homebrew
+
+ QMAKE_CXXFLAGS += -Wno-unused-local-typedef
+ QMAKE_CFLAGS += -Wno-unused-local-typedef
+}
+
+linux:!android {
+ BOOSTDIR = /usr/lib/x86_64-linux-gnu/
+ BOOSTSIGNALLIB = boost_signals
+ BOOSTSYSTEMLIB = boost_system
+ BOOSTFILESYSTEMLIB = boost_filesystem
+ exists($$THIRDPARTY_DIR/boost/1.65.0) {
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.65.0
+ } else {
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.55.0
+ }
+}
+
+android {
+ QMAKE_CXXFLAGS -= -fstack-protector-strong
+ QMAKE_CFLAGS -= -fstack-protector-strong
+ exists($$THIRDPARTY_DIR/boost/1.65.0) {
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.65.0
+ } else {
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.55.0
+ }
+ # TODO: Should be done using this instead of copying the GLES headers, but including this
+ # causes lots of conflicting definitions in signal.h for some reason. Feel free to fix it if
+ # you know how. After this works, GLES3 and GLES2 folders can be deleted from
+ # 3rdparty/RuntimePlatformSpecific/Android/jni
+# INCLUDEPATH += $$(ANDROID_NDK_ROOT)/sysroot/usr/include
+# DEFINES += __BITS_PER_LONG=32
+}
+
+win32 {
+ DEFINES += UIC_OS_WINDOWS _WIN32 _PCPLATFORM \
+ WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T LUA_BUILD_AS_DLL KDWIN NOMINMAX
+
+ win32-msvc {
+ QMAKE_CXXFLAGS += /MP /d2Zi+
+ QMAKE_CFLAGS += /MP /d2Zi+
+ }
+
+ CONFIG(debug, debug|release) {
+ win32-msvc {
+ QMAKE_CXXFLAGS += /Od
+ QMAKE_CFLAGS += /Od
+ }
+ } else {
+ win32-msvc {
+ QMAKE_CXXFLAGS += /Ox
+ QMAKE_CFLAGS += /Ox
+ }
+ }
+
+ contains(QT_ARCH, x86_64) {
+ DEFINES += _WIN64
+ }
+
+ exists($$THIRDPARTY_DIR/boost/1.65.0) {
+ contains(QT_ARCH, x86_64) {
+ BOOSTDIR = $$THIRDPARTY_DIR/boost/1.65.0/msvc14/lib64
+ } else {
+ BOOSTDIR = $$THIRDPARTY_DIR/boost/1.65.0/msvc14/lib
+ }
+
+ CONFIG(debug, debug|release) {
+ BOOSTSIGNALLIB = libboost_signals-vc140-mt-gd-1_65
+ BOOSTSYSTEMLIB = libboost_system-vc140-mt-gd-1_65
+ BOOSTFILESYSTEMLIB = libboost_filesystem-vc140-mt-gd-1_65
+ } else {
+ BOOSTSIGNALLIB = libboost_signals-vc140-mt-1_65
+ BOOSTSYSTEMLIB = libboost_system-vc140-mt-1_65
+ BOOSTFILESYSTEMLIB = libboost_filesystem-vc140-mt-1_65
+ }
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.65.0
+ } else {
+ contains(QT_ARCH, x86_64) {
+ BOOSTDIR = $$THIRDPARTY_DIR/boost/1.55.0/msvc14/lib64
+ } else {
+ BOOSTDIR = $$THIRDPARTY_DIR/boost/1.55.0/msvc14/lib
+ }
+
+ CONFIG(debug, debug|release) {
+ BOOSTSIGNALLIB = libboost_signals-vc120-mt-gd-1_55
+ BOOSTSYSTEMLIB = libboost_system-vc120-mt-gd-1_55
+ BOOSTFILESYSTEMLIB = libboost_filesystem-vc120-mt-gd-1_55
+ } else {
+ BOOSTSIGNALLIB = libboost_signals-vc120-mt-1_55
+ BOOSTSYSTEMLIB = libboost_system-vc120-mt-1_55
+ BOOSTFILESYSTEMLIB = libboost_filesystem-vc120-mt-1_55
+ }
+ INCLUDEPATH += $$THIRDPARTY_DIR/boost/1.55.0
+ }
+}
+
+BINDIR = $$MODULE_BASE_OUTDIR/bin
+LIBDIR = $$MODULE_BASE_OUTDIR/lib
+LIBS += -L"$$LIBDIR"
+!testcase {
+ contains(TEMPLATE, app) {
+ DESTDIR = $$BINDIR
+ } else {
+ DESTDIR = $$LIBDIR
+ win32: DLLDESTDIR = $$BINDIR
+ }
+}
diff --git a/src/src.pro b/src/src.pro
new file mode 100644
index 00000000..a7162708
--- /dev/null
+++ b/src/src.pro
@@ -0,0 +1,11 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS += \
+ 3rdparty \
+ QtExtras \
+ Runtime \
+ Viewer
+
+!boot2qt:!android:!integrity {
+ SUBDIRS += Authoring
+}
diff --git a/src/utils.pri b/src/utils.pri
new file mode 100644
index 00000000..8d56baa4
--- /dev/null
+++ b/src/utils.pri
@@ -0,0 +1,8 @@
+# Add our static libs to target dependencies so we detect changes to them
+defineReplace(fixLibPredeps) {
+ # TODO Needs something more clever once debug libs are correctly suffixed
+ for(lib, $${2}) {
+ PREDEPS *= $${1}/$${QMAKE_PREFIX_STATICLIB}$${lib}$$qtPlatformTargetSuffix().$${QMAKE_EXTENSION_STATICLIB}
+ }
+ return($$PREDEPS)
+}
diff --git a/sync.profile b/sync.profile
new file mode 100644
index 00000000..aa354125
--- /dev/null
+++ b/sync.profile
@@ -0,0 +1,10 @@
+%modules = ( # path to module name map
+ "QtStudio3D" => "$basedir/src/Viewer/studio3d",
+);
+%moduleheaders = ( # restrict the module headers to those found in relative path
+);
+%dependencies = (
+ "qtbase" => "",
+ "qtdeclarative" => "",
+ "qtmultimedia" => "",
+);
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
new file mode 100644
index 00000000..5967855d
--- /dev/null
+++ b/tests/auto/auto.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += \
+ runtime \
+ viewer \
+ qtextras \
+ studio3d
diff --git a/tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro b/tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro
new file mode 100644
index 00000000..6e180f80
--- /dev/null
+++ b/tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+CONFIG += testcase
+include($$PWD/../../../../src/commonplatform.pri)
+
+TARGET = tst_qt3dsqmlstream
+
+QT += testlib quick
+
+SOURCES += tst_qt3dsqmlstream.cpp
+
+INCLUDEPATH += \
+ $$PWD/../../../../src/QtExtras/qmlstreamer
+
+LIBS += \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+ANDROID_EXTRA_LIBS = \
+ libqt3dsqmlstreamer.so
diff --git a/tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp b/tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp
new file mode 100644
index 00000000..71de525f
--- /dev/null
+++ b/tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QSignalSpy>
+#include <q3dsqmlstream.h>
+#include <QQuickItem>
+
+class tst_Qt3DSQmlStream : public QObject
+{
+ Q_OBJECT
+public:
+ tst_Qt3DSQmlStream()
+ {
+ qRegisterMetaType<QQuickItem*>();
+ }
+ ~tst_Qt3DSQmlStream() {}
+private slots:
+
+ void checkInitialState()
+ {
+ // GIVEN
+ Q3DSQmlStream qmlstream;
+
+ // THEN
+ QVERIFY(qmlstream.presentationId().isNull());
+ QVERIFY(qmlstream.item() == nullptr);
+ }
+
+ void testSetPresentationId()
+ {
+ // GIVEN
+ Q3DSQmlStream qmlstream;
+ QString pid = "presentation0";
+ QSignalSpy spy(&qmlstream, SIGNAL(presentationIdChanged(const QString&)));
+
+ // WHEN
+ qmlstream.setPresentationId(pid);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(qmlstream.presentationId(), pid);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ qmlstream.setPresentationId(pid);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+ }
+
+ void testSetItem()
+ {
+ // GIVEN
+ Q3DSQmlStream qmlstream;
+ QScopedPointer<QQuickItem> item(new QQuickItem());
+ QSignalSpy spy(&qmlstream, SIGNAL(itemChanged(QQuickItem *)));
+
+ // WHEN
+ qmlstream.setItem(item.data());
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(qmlstream.item(), item.data());
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ qmlstream.setItem(item.data());
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+ }
+};
+
+QTEST_APPLESS_MAIN(tst_Qt3DSQmlStream)
+
+#include "tst_qt3dsqmlstream.moc"
diff --git a/tests/auto/qtextras/qtextras.pro b/tests/auto/qtextras/qtextras.pro
new file mode 100644
index 00000000..16a1ed80
--- /dev/null
+++ b/tests/auto/qtextras/qtextras.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ qt3dsqmlstream
diff --git a/tests/auto/runtime/Qt3DSRenderTestBase.cpp b/tests/auto/runtime/Qt3DSRenderTestBase.cpp
new file mode 100644
index 00000000..24712ec8
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestBase.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestBase.h"
+
+using namespace uic::render;
+
+namespace qt3ds {
+namespace render {
+
+NVRenderTestBase::~NVRenderTestBase()
+{
+ delete m_renderImpl;
+}
+
+bool NVRenderTestBase::initializeUICRenderer(QSurfaceFormat format)
+{
+ m_coreFactory = uic::render::IUICRenderFactoryCore::CreateRenderFactoryCore("", m_windowSystem,
+ m_timeProvider);
+ m_factory = m_coreFactory->CreateRenderFactory(format);
+ m_rc = m_factory->GetUICRenderContext();
+ m_renderImpl = new uic::render::CUICRendererImpl(*m_rc);
+
+ return true;
+}
+
+CUICRendererImpl *NVRenderTestBase::uicRenderer()
+{
+ return m_renderImpl;
+}
+
+Q3DStudio::IRuntimeMetaData *NVRenderTestBase::metadata()
+{
+ if (m_metaData.mPtr == NULL)
+ m_metaData = &Q3DStudio::IRuntimeMetaData::Create(m_coreFactory->GetInputStreamFactory());
+ return m_metaData.mPtr;
+}
+
+}
+}
diff --git a/tests/auto/runtime/Qt3DSRenderTestBase.h b/tests/auto/runtime/Qt3DSRenderTestBase.h
new file mode 100644
index 00000000..40ac36fb
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestBase.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_BASE_H
+#define QT3DS_RENDER_TEST_BASE_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICWindowSystem.h"
+#include "UICTypes.h"
+#include "UICTimer.h"
+#include "UICRenderRuntimeBinding.h"
+#include "UICRenderRuntimeBindingImpl.h"
+#include "UICRenderContext.h"
+#include "UICRendererImpl.h"
+#include "UICMetadata.h"
+
+namespace uic {
+namespace render {
+class IUICRenderer;
+class CUICRendererImpl;
+class IUICRenderFactoryCore;
+class IUICRenderFactory;
+}
+}
+
+namespace qt3ds {
+namespace render {
+
+ class IUICRenderFactoryCore;
+ class IUICRenderFactory;
+ class UICRenderer;
+
+ typedef struct SUSER_CONTEXT_DATA
+ {
+ unsigned int winWidth;
+ unsigned int winHeight;
+ } userContextData;
+
+ struct SNullTimeProvider : public Q3DStudio::ITimeProvider
+ {
+ virtual Q3DStudio::INT64 GetCurrentTimeMicroSeconds() { return 0; }
+ };
+
+ struct SNullWindowSystem : public Q3DStudio::IWindowSystem
+ {
+ virtual Q3DStudio::SSize GetWindowDimensions() { return Q3DStudio::SSize(); }
+
+ virtual void SetWindowDimensions(const Q3DStudio::SSize &) {}
+ // For platforms that support it, we get the egl info for render plugins
+ // Feel free to return NULL.
+ virtual Q3DStudio::SEGLInfo *GetEGLInfo() { return NULL; }
+
+ // on some systems we allow our default render target to be a offscreen buffer
+ // otherwise return 0;
+ virtual int GetDefaultRenderTargetID() { return 0; }
+ // returns the depth buffer bit count for the render window
+ // does not really matter here
+ virtual int GetDepthBitCount() { return 16; }
+ };
+
+ /// this is the base class for all tests
+ class NVRenderTestBase
+ {
+ public:
+ /// constructor
+ NVRenderTestBase(){}
+ /// destructor
+ virtual ~NVRenderTestBase();
+
+ /// Checks if this test is supported
+ ///
+ /// @return true if supported
+ virtual bool isSupported(NVRenderContext *context) = 0;
+
+ /// This runs the test
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ /// @param pUserData (in) Pointer to pUserData
+ ///
+ /// @return false if failed
+ virtual bool run(NVRenderContext *context, userContextData *pUserData) = 0;
+
+ /// This cleans up state after the test if needed
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ /// @param pUserData (in) Pointer to pUserData
+ ///
+ /// @return false if failed
+ virtual void cleanup(NVRenderContext *context, userContextData *pUserData) = 0;
+
+ /// This runs the performance test
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ /// @param pUserData (in) Pointer to pUserData
+ ///
+ /// @return false if failed
+ virtual bool runPerformance(NVRenderContext *context, userContextData *pContextData) = 0;
+
+ /// This is a query to determine if we run on a ES context
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ ///
+ /// @return false if failed
+ virtual const bool isGLESContext(NVRenderContext *context)
+ {
+ NVRenderContextType ctxType = context->GetRenderContextType();
+
+ // Need minimum of GL3 or GLES3
+ if (ctxType == NVRenderContextValues::GLES2 || ctxType == NVRenderContextValues::GLES3
+ || ctxType == NVRenderContextValues::GLES3PLUS) {
+ return true;
+ }
+
+ return false;
+ }
+
+ bool initializeUICRenderer(QSurfaceFormat format);
+ uic::render::CUICRendererImpl *uicRenderer();
+ Q3DStudio::IRuntimeMetaData *NVRenderTestBase::metadata();
+
+ private:
+
+ NVScopedRefCounted<uic::render::IUICRenderFactoryCore> m_coreFactory;
+ NVScopedRefCounted<uic::render::IUICRenderFactory> m_factory;
+ NVScopedRefCounted<uic::render::IUICRenderContext> m_rc;
+ qt3ds::foundation::NVScopedReleasable<Q3DStudio::IRuntimeMetaData> m_metaData;
+ uic::render::CUICRendererImpl *m_renderImpl;
+
+ SNullTimeProvider m_timeProvider;
+ SNullWindowSystem m_windowSystem;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_BASE_H
diff --git a/tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp b/tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp
new file mode 100644
index 00000000..f216faa2
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestMathUtil.h"
+#include <math.h>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+#define QT3DS_RENDER_TEST_PI 3.14159265358979323846f
+
+inline float degreeToRad(float degree)
+{
+ return (degree * QT3DS_RENDER_TEST_PI) / 180.0f;
+}
+
+void qt3ds::render::NvRenderTestMatrixFrustum(QT3DSMat44 *m, float l, float r, float b, float t, float n,
+ float f)
+{
+ float rightMinusLeftInv, topMinusBottomInv, farMinusNearInv, twoNear;
+
+ rightMinusLeftInv = 1.0f / (r - l);
+ topMinusBottomInv = 1.0f / (t - b);
+ farMinusNearInv = 1.0f / (f - n);
+ twoNear = 2.0f * n;
+
+ m->column0 = QT3DSVec4(twoNear * rightMinusLeftInv, 0, 0, 0);
+ m->column1 = QT3DSVec4(0, twoNear * topMinusBottomInv, 0, 0);
+ m->column2 = QT3DSVec4((r + l) * rightMinusLeftInv, (t + b) * topMinusBottomInv,
+ -(f + n) * farMinusNearInv, -1.0f);
+ m->column3 = QT3DSVec4(0, 0, -(twoNear * f) * farMinusNearInv, 0.0f);
+}
+
+void qt3ds::render::NvGl2DemoMatrixOrtho(QT3DSMat44 *m, float l, float r, float b, float t, float n,
+ float f)
+{
+ float rightMinusLeftInv, topMinusBottomInv, farMinusNearInv;
+
+ rightMinusLeftInv = 1.0f / (r - l);
+ topMinusBottomInv = 1.0f / (t - b);
+ farMinusNearInv = 1.0f / (f - n);
+
+ m->column0 = QT3DSVec4(2.0f * rightMinusLeftInv, 0, 0, 0);
+ m->column1 = QT3DSVec4(0, 2.0f * topMinusBottomInv, 0, 0);
+ m->column2 = QT3DSVec4(0, 0, -2.0f * farMinusNearInv, 0);
+ m->column3 = QT3DSVec4(-(r + l) * rightMinusLeftInv, -(t + b) * topMinusBottomInv,
+ -(f + n) * farMinusNearInv, 1.0f);
+}
+
+void qt3ds::render::NvRenderTestMatrixRotX(QT3DSMat44 *m, float angle)
+{
+ float rad = degreeToRad(angle);
+ float cosPhi = cos(rad);
+ float sinPhi = sin(rad);
+
+ m->column0 = QT3DSVec4(1.0, 0.0, 0.0, 0.0);
+ m->column1 = QT3DSVec4(0.0, cosPhi, -sinPhi, 0.0);
+ m->column2 = QT3DSVec4(0.0, sinPhi, cosPhi, 0.0);
+ m->column3 = QT3DSVec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void qt3ds::render::NvRenderTestMatrixRotY(QT3DSMat44 *m, float angle)
+{
+ float rad = degreeToRad(angle);
+ float cosPhi = cos(rad);
+ float sinPhi = sin(rad);
+
+ m->column0 = QT3DSVec4(cosPhi, 0.0, sinPhi, 0.0);
+ m->column1 = QT3DSVec4(0.0, 1.0, 0.0, 0.0);
+ m->column2 = QT3DSVec4(-sinPhi, 0.0, cosPhi, 0.0);
+ m->column3 = QT3DSVec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void qt3ds::render::NvRenderTestMatrixRotZ(QT3DSMat44 *m, float angle)
+{
+ float rad = degreeToRad(angle);
+ float cosPhi = cos(rad);
+ float sinPhi = sin(rad);
+
+ m->column0 = QT3DSVec4(cosPhi, -sinPhi, 0.0, 0.0);
+ m->column1 = QT3DSVec4(sinPhi, cosPhi, 0.0, 0.0);
+ m->column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ m->column3 = QT3DSVec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void qt3ds::render::NvRenderTestMatrixTranslation(QT3DSMat44 *m, float x, float y, float z)
+{
+ m->column0 = QT3DSVec4(1.0, 0.0, 0.0, 0.0);
+ m->column1 = QT3DSVec4(0.0, 1.0, 0.0, 0.0);
+ m->column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ m->column3 = QT3DSVec4(x, y, z, 1.0);
+}
diff --git a/tests/auto/runtime/Qt3DSRenderTestMathUtil.h b/tests/auto/runtime/Qt3DSRenderTestMathUtil.h
new file mode 100644
index 00000000..739209e8
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestMathUtil.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_MATH_UTIL_H
+#define QT3DS_RENDER_TEST_MATH_UTIL_H
+
+#include "foundation/Qt3DSMat44.h"
+
+namespace qt3ds {
+namespace render {
+
+ void NvRenderTestMatrixFrustum(QT3DSMat44 *m, float l, float r, float b, float t, float n,
+ float f);
+
+ void NvGl2DemoMatrixOrtho(QT3DSMat44 *m, float l, float r, float b, float t, float n, float f);
+
+ void NvRenderTestMatrixRotX(QT3DSMat44 *m, float angle);
+ void NvRenderTestMatrixRotY(QT3DSMat44 *m, float angle);
+ void NvRenderTestMatrixRotZ(QT3DSMat44 *m, float angle);
+
+ void NvRenderTestMatrixTranslation(QT3DSMat44 *m, float x, float y, float z);
+}
+}
+
+#endif
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp
new file mode 100644
index 00000000..ee108230
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestAtomicCounterBuffer.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderAtomicCounterBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "layout(binding = 2, offset = 0) uniform atomic_uint ac_raster;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " uint counter = atomicCounterIncrement(ac_raster);\n"
+ " float g = (float(counter)/255.0) / 255.0;\n"
+ " fragColor = vec4(0.0, g, 0.0, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestAtomicCounterBuffer::NVRenderTestAtomicCounterBuffer()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestAtomicCounterBuffer::~NVRenderTestAtomicCounterBuffer()
+{
+}
+
+bool NVRenderTestAtomicCounterBuffer::isSupported(NVRenderContext *context)
+{
+ // This is currently only supported on GL 4 and GLES 3.1
+ if (!context->IsAtomicCounterBufferSupported())
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestAtomicCounterBuffer::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= rasterizerTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestAtomicCounterBuffer::rasterizerTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderAtomicCounterBuffer> mAtomicCounterBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create atomic counter buffer
+ QT3DSU32 acCounter = 0;
+ NVDataRef<QT3DSU8> acData((QT3DSU8 *)&acCounter, sizeof(QT3DSU32));
+ mAtomicCounterBuffer = context->CreateAtomicCounterBuffer(
+ "ac_buffer", NVRenderBufferUsageType::Static, sizeof(QT3DSU32), acData);
+ if (!mAtomicCounterBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create atomic counter buffer";
+ return false;
+ }
+ // add a parameter
+ CRegisteredString theACName(context->GetStringTable().RegisterStr("ac_raster"));
+ mAtomicCounterBuffer->AddParam(theACName, 0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestAtomicCounterBuffer shader",
+ toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderAtomicCounterBuffer *> atomicBuffer(
+ "ac_buffer", *compResult.mShader);
+ atomicBuffer.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestAtomicCounterBuffer::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestAtomicCounterBuffer::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h
new file mode 100644
index 00000000..87b0910a
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
+#define QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestAtomicCounterBuffer : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestAtomicCounterBuffer();
+ ~NVRenderTestAtomicCounterBuffer();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool rasterizerTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp
new file mode 100644
index 00000000..f8f97533
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestAttribBuffers.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_col; // Vertex col\n"
+ "out vec3 color; // output color\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ " color = attr_col;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "in vec3 color; // input color\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4( color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestAttribBuffers::NVRenderTestAttribBuffers()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestAttribBuffers::~NVRenderTestAttribBuffers()
+{
+}
+
+bool NVRenderTestAttribBuffers::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestAttribBuffers::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= multiAttribBufferTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestAttribBuffers::multiAttribBufferTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ static const Vertex vertexColors[] = { { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 0.6, 0.0) },
+ { QT3DSVec3(0.0, 0.2, 0.0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderVertexBuffer> mColorBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVRenderVertexBuffer *attribBuffers[2];
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestAttribBuffers shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0, 0),
+ NVRenderVertexBufferEntry("attr_col", NVRenderComponentTypes::QT3DSF32, 3, 0, 1),
+ };
+
+ // position buffer
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create vertex buffer";
+ return false;
+ }
+ // color buffer
+ NVDataRef<QT3DSU8> colorData((QT3DSU8 *)vertexColors, bufSize);
+ mColorBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), colorData);
+ if (!mColorBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create color buffer";
+ return false;
+ }
+
+ attribBuffers[0] = mVertexBuffer;
+ attribBuffers[1] = mColorBuffer;
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides[2];
+ QT3DSU32 offsets[2];
+ strides[0] = mVertexBuffer->GetStride();
+ offsets[0] = 0;
+ strides[1] = mColorBuffer->GetStride();
+ offsets[1] = 0;
+
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, NVConstDataRef<NVRenderVertexBuffer *>(attribBuffers, 2), NULL,
+ toConstDataRef(strides, 2), toConstDataRef(offsets, 2), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestAttribBuffers::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestAttribBuffers::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h
new file mode 100644
index 00000000..47e898f2
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_ATTRIB_BUFFERS_H
+#define QT3DS_RENDER_TEST_ATTRIB_BUFFERS_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestAttribBuffers : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestAttribBuffers();
+ ~NVRenderTestAttribBuffers();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool multiAttribBufferTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_ATTRIB_BUFFERS_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp
new file mode 100644
index 00000000..1ec8830a
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestBackendQuery.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *PassthroughVertShader()
+{
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+}
+
+static const char *SimpleFragShader()
+{
+ return "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform vec3 color;\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor = vec4( color, 1);\n"
+ "}\n";
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+NVRenderTestBackendQuery::NVRenderTestBackendQuery()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestBackendQuery::~NVRenderTestBackendQuery()
+{
+}
+
+bool NVRenderTestBackendQuery::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestBackendQuery::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= depthBitsTest(context, pUserData);
+ _curTest++;
+ success &= depthBitsFBOTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestBackendQuery::renderQuad(NVRenderContext *context, userContextData *pUserData,
+ QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestBackendQuery shader", toRef(PassthroughVertShader()),
+ toRef(SimpleFragShader()));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestBackendQuery::depthBitsTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestBackendQuery::depthBitsTest: Failed to create input assembler";
+ return false;
+ }
+
+ // check if default buffer bit size is in an acceptable size range
+ // we accept a range from 16 to 32
+ const QT3DSU32 bits = context->GetDepthBits();
+ bool passed = (bits >= 16 && bits <= 32);
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return passed;
+}
+
+bool NVRenderTestBackendQuery::depthBitsTest(NVRenderContext *context, userContextData *pUserData)
+{
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ // check if default buffer bit size is in an acceptable size range
+ // we accept a range from 16 to 32
+ const QT3DSU32 bits = context->GetDepthBits();
+ bool passed = (bits >= 16 && bits <= 32);
+ if (passed)
+ color.y = 1.0;
+ else
+ color.x = 1.0;
+
+ passed &= renderQuad(context, pUserData, color);
+
+ return passed;
+}
+
+bool NVRenderTestBackendQuery::depthBitsFBOTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ // depneding on the context we get different values
+ NVRenderContextType theContextFlags(NVRenderContextValues::GLES2 | NVRenderContextValues::GL2);
+ NVRenderContextType type = context->GetRenderContextType();
+ bool depth16_Only = (type & theContextFlags);
+ // create a FBO
+ NVScopedRefCounted<NVRenderFrameBuffer> m_FBO;
+ NVScopedRefCounted<NVRenderTexture2D> m_ColorTexture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth16Texture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth24Texture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth32Texture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth24Stencil8Texture;
+
+ m_ColorTexture = context->CreateTexture2D();
+ m_ColorTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256, NVRenderTextureFormats::RGBA8);
+ m_Depth16Texture = context->CreateTexture2D();
+ m_Depth16Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth16);
+
+ m_FBO = context->CreateFrameBuffer();
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*m_ColorTexture));
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_Depth16Texture));
+
+ if (!m_FBO->IsComplete()) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+
+ context->SetRenderTarget(m_FBO);
+
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ // check depth bit count
+ QT3DSU32 bits = context->GetDepthBits();
+ QT3DSU32 bitsExpected = 16;
+ bool passed = (bits == bitsExpected);
+
+ // detach depth
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+
+ m_Depth24Texture = context->CreateTexture2D();
+ m_Depth24Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth24);
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_Depth24Texture));
+ if (!m_FBO->IsComplete()) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+ // check depth bit count
+ bits = context->GetDepthBits();
+ bitsExpected = (depth16_Only) ? 16 : 24;
+ passed &= (bits == bitsExpected);
+
+ // detach depth
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+
+ m_Depth32Texture = context->CreateTexture2D();
+ m_Depth32Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth32);
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_Depth32Texture));
+ if (!m_FBO->IsComplete()) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+ // check depth bit count
+ bits = context->GetDepthBits();
+ bitsExpected = (depth16_Only) ? 16 : 32;
+ passed &= (bits == bitsExpected);
+
+ // detach depth
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+
+ // only test depth stencil if supported
+ if (context->IsDepthStencilSupported()) {
+ m_Depth24Stencil8Texture = context->CreateTexture2D();
+ m_Depth24Stencil8Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth24Stencil8);
+ m_FBO->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ NVRenderTextureOrRenderBuffer(*m_Depth24Stencil8Texture));
+ if (!m_FBO->IsComplete()) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+ // check depth bit count
+ bits = context->GetDepthBits();
+ bitsExpected = (depth16_Only) ? 16 : 24;
+ passed &= (bits == bitsExpected);
+ }
+
+ context->SetRenderTarget(NULL);
+
+ if (passed)
+ color.y = 1.0;
+ else
+ color.x = 1.0;
+
+ passed &= renderQuad(context, pUserData, color);
+
+ return passed;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestBackendQuery::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestBackendQuery::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h
new file mode 100644
index 00000000..e5fde648
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_BACKEND_QUERY_H
+#define QT3DS_RENDER_TEST_BACKEND_QUERY_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestBackendQuery : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestBackendQuery();
+ ~NVRenderTestBackendQuery();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool depthBitsTest(NVRenderContext *context, userContextData *pUserData);
+ bool depthBitsFBOTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderQuad(NVRenderContext *context, userContextData *pUserData, QT3DSVec3 color);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestClear.cpp b/tests/auto/runtime/base/Qt3DSRenderTestClear.cpp
new file mode 100644
index 00000000..8accb864
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestClear.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestClear.h"
+#include "foundation/Qt3DSVec4.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+NVRenderTestClear::NVRenderTestClear()
+{
+}
+
+NVRenderTestClear::~NVRenderTestClear()
+{
+}
+
+bool NVRenderTestClear::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+static bool checkColor(int width, int height, unsigned char *pixels, const QT3DSVec3 &color)
+{
+ unsigned char *pSrc = pixels;
+
+ for (int h = 0; h < height; h++) {
+ for (int w = 0; w < width; w++) {
+ if (pSrc[0] != (unsigned char)color.x || pSrc[1] != (unsigned char)color.y
+ || pSrc[2] != (unsigned char)color.z) {
+ return false;
+ }
+
+ pSrc += 3;
+ }
+ }
+
+ return true;
+}
+
+bool NVRenderTestClear::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ success &= testColorClear(context, pUserData);
+
+ // if successfull draw green otherwise a red
+ if (success) {
+ // set clear color to green
+ context->SetClearColor(QT3DSVec4(0.0f, 1.0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+ } else {
+ // set clear color to green
+ context->SetClearColor(QT3DSVec4(1.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+ }
+
+ return success;
+}
+
+bool NVRenderTestClear::testColorClear(NVRenderContext *context, userContextData *pUserData)
+{
+ // allocate buffer for readback
+ NVAllocatorCallback &alloc(context->GetFoundation().getAllocator());
+ QT3DSU32 size = pUserData->winHeight * pUserData->winHeight * 3 * sizeof(QT3DSU8);
+ QT3DSU8 *pixels = (QT3DSU8 *)alloc.allocate(size, "testColorClear color clear", __FILE__, __LINE__);
+
+ if (!pixels)
+ return false;
+
+ // set clear color to yellow
+ context->SetClearColor(QT3DSVec4(1.0f, 1.0f, .0f, 0.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+
+ // read back pixels
+ context->ReadPixels(NVRenderRect(0, 0, pUserData->winHeight, pUserData->winHeight),
+ NVRenderReadPixelFormats::RGB8, NVDataRef<QT3DSU8>(pixels, size));
+ // check color
+ bool passed =
+ checkColor(pUserData->winHeight, pUserData->winHeight, pixels, QT3DSVec3(255.0f, 255.0f, .0f));
+
+ alloc.deallocate(pixels);
+
+ return passed;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestClear::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestClear::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestClear.h b/tests/auto/runtime/base/Qt3DSRenderTestClear.h
new file mode 100644
index 00000000..6113b7bd
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestClear.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_CLEAR_H
+#define QT3DS_RENDER_TEST_CLEAR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the render target clearing
+ class NVRenderTestClear : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestClear();
+ ~NVRenderTestClear();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextDat);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ /// subtests
+ bool testColorClear(NVRenderContext *context, userContextData *pUserData);
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_CLEAR_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp
new file mode 100644
index 00000000..93836205
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp
@@ -0,0 +1,847 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestConstantBuffer.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *scalarVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "float red;\n"
+ "float green;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *scalarFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "float red;\n"
+ "float green;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(red, green, blue, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vectorVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "vec2 ba;\n };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vectorFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "vec2 ba;\n };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(rg[0], rg[1], ba[0], ba[1]);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *structVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "struct sampleStruct {\n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n"
+ "float alpha; };\n"
+ "layout (std140) uniform cbBuffer { \n"
+ "sampleStruct s[2]; };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = s[0].mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *structFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "struct sampleStruct {\n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n"
+ "float alpha; };\n"
+ "layout (std140) uniform cbBuffer { \n"
+ "sampleStruct s[2]; };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(s[0].rg[0], s[0].rg[1], s[0].blue, s[0].alpha);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *multiCBVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBufferTrans { \n"
+ "mat4 mat_mvp;\n };\n"
+ "layout (std140) uniform cbBufferCol { \n"
+ "float red;\n"
+ "float green;\n"
+ "float blue;\n };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *multiCBFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBufferTrans { \n"
+ "mat4 mat_mvp;\n };\n"
+ "layout (std140) uniform cbBufferCol { \n"
+ "float red;\n"
+ "float green;\n"
+ "float blue;\n };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(red, green, blue, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestConstantBuffer::NVRenderTestConstantBuffer()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestConstantBuffer::~NVRenderTestConstantBuffer()
+{
+}
+
+bool NVRenderTestConstantBuffer::isSupported(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+ NVRenderContextType nonSupportedFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+
+ // This is currently only supported on GL(Es) >= 3
+ if ((ctxType & nonSupportedFlags))
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestConstantBuffer::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= scalarTest(context, pUserData);
+ _curTest++;
+ success &= vectorTest(context, pUserData);
+ _curTest++;
+ success &= structTest(context, pUserData);
+ _curTest++;
+ success &= rawTest(context, pUserData);
+ _curTest++;
+ success &= multiCBTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestConstantBuffer::scalarTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static, 0,
+ NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theRedName(context->GetStringTable().RegisterStr("red"));
+ mConstantBuffer->AddParam(theRedName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theGreenName(context->GetStringTable().RegisterStr("green"));
+ mConstantBuffer->AddParam(theGreenName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("mat_mvp"));
+ mConstantBuffer->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+ CRegisteredString theBlueName(context->GetStringTable().RegisterStr("blue"));
+ mConstantBuffer->AddParam(theBlueName, NVRenderShaderDataTypes::QT3DSF32, 1);
+
+ // set values
+ QT3DSF32 red = 0.0;
+ mConstantBuffer->UpdateParam("red", NVDataRef<QT3DSU8>((QT3DSU8 *)&red, 1));
+ QT3DSF32 green = 1.0;
+ mConstantBuffer->UpdateParam("green", NVDataRef<QT3DSU8>((QT3DSU8 *)&green, 1));
+ QT3DSF32 blue = 0.0;
+ mConstantBuffer->UpdateParam("blue", NVDataRef<QT3DSU8>((QT3DSU8 *)&blue, 1));
+ mConstantBuffer->UpdateParam("mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::scalarTest",
+ toRef(scalarVertShader(isGLESContext(context), vtxProg)),
+ toRef(scalarFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::scalarTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::scalarTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ mConstantBuffer->Update();
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestConstantBuffer::vectorTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static, 0,
+ NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theRGName(context->GetStringTable().RegisterStr("rg"));
+ mConstantBuffer->AddParam(theRGName, NVRenderShaderDataTypes::QT3DSVec2, 1);
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("mat_mvp"));
+ mConstantBuffer->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+ CRegisteredString theBAName(context->GetStringTable().RegisterStr("ba"));
+ mConstantBuffer->AddParam(theBAName, NVRenderShaderDataTypes::QT3DSVec2, 1);
+
+ // set values
+ QT3DSVec2 rg;
+ rg[0] = 0.0;
+ rg[1] = 1.0;
+ mConstantBuffer->UpdateParam("rg", NVDataRef<QT3DSU8>((QT3DSU8 *)&rg, 1));
+ QT3DSVec2 ba;
+ ba[0] = 0.0;
+ ba[1] = 1.0;
+ mConstantBuffer->UpdateParam("ba", NVDataRef<QT3DSU8>((QT3DSU8 *)&ba, 1));
+ mConstantBuffer->UpdateParam("mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::vectorTest",
+ toRef(vectorVertShader(isGLESContext(context), vtxProg)),
+ toRef(vectorFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::vectorTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::vectorTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestConstantBuffer::structTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static, 0,
+ NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theRGName(context->GetStringTable().RegisterStr("s[0].rg"));
+ mConstantBuffer->AddParam(theRGName, NVRenderShaderDataTypes::QT3DSVec2, 1);
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("s[0].mat_mvp"));
+ mConstantBuffer->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+ CRegisteredString theBlueName(context->GetStringTable().RegisterStr("s[0].blue"));
+ mConstantBuffer->AddParam(theBlueName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theAlphaName(context->GetStringTable().RegisterStr("s[0].alpha"));
+ mConstantBuffer->AddParam(theAlphaName, NVRenderShaderDataTypes::QT3DSF32, 1);
+
+ // set values
+ QT3DSVec2 rg;
+ rg[0] = 0.0;
+ rg[1] = 1.0;
+ mConstantBuffer->UpdateParam("s[0].rg", NVDataRef<QT3DSU8>((QT3DSU8 *)&rg, 1));
+ QT3DSF32 blue, alpha;
+ blue = 0.0;
+ alpha = 1.0;
+ mConstantBuffer->UpdateParam("s[0].blue", NVDataRef<QT3DSU8>((QT3DSU8 *)&blue, 1));
+ mConstantBuffer->UpdateParam("s[0].alpha", NVDataRef<QT3DSU8>((QT3DSU8 *)&alpha, 1));
+ mConstantBuffer->UpdateParam("s[0].mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::structTest",
+ toRef(structVertShader(isGLESContext(context), vtxProg)),
+ toRef(structFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::structTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::structTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestConstantBuffer::rawTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ struct sampleStruct
+ {
+ float rg[2];
+ float padding[2];
+ QT3DSMat44 mat_mvp; // matrices start on 16 byte boundaries
+ float blue;
+ float alpha;
+ } s;
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ NVDataRef<QT3DSU8> cBuffer((QT3DSU8 *)&s, sizeof(sampleStruct));
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static,
+ sizeof(sampleStruct), cBuffer);
+ // set values
+ s.rg[0] = 0.0;
+ s.rg[1] = 1.0;
+ s.mat_mvp = mvp;
+ s.blue = 0.0;
+ s.alpha = 0.0;
+ mConstantBuffer->UpdateRaw(0, cBuffer);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::rawTest",
+ toRef(structVertShader(isGLESContext(context), vtxProg)),
+ toRef(structFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::rawTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::rawTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+///< test of multiple constant buffers
+bool NVRenderTestConstantBuffer::multiCBTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBufferTrans;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBufferCol;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBufferTrans = context->CreateConstantBuffer(
+ "cbBufferTrans", NVRenderBufferUsageType::Static, 0, NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("mat_mvp"));
+ mConstantBufferTrans->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+
+ // create constant buffer referred in the program
+ mConstantBufferCol = context->CreateConstantBuffer(
+ "cbBufferCol", NVRenderBufferUsageType::Static, 0, NVDataRef<QT3DSU8>());
+ CRegisteredString theRedName(context->GetStringTable().RegisterStr("red"));
+ mConstantBufferCol->AddParam(theRedName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theGreenName(context->GetStringTable().RegisterStr("green"));
+ mConstantBufferCol->AddParam(theGreenName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theBlueName(context->GetStringTable().RegisterStr("blue"));
+ mConstantBufferCol->AddParam(theBlueName, NVRenderShaderDataTypes::QT3DSF32, 1);
+
+ // set values
+ mConstantBufferTrans->UpdateParam("mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ QT3DSF32 red = 0.0;
+ mConstantBufferCol->UpdateParam("red", NVDataRef<QT3DSU8>((QT3DSU8 *)&red, 1));
+ QT3DSF32 green = 1.0;
+ mConstantBufferCol->UpdateParam("green", NVDataRef<QT3DSU8>((QT3DSU8 *)&green, 1));
+ QT3DSF32 blue = 0.0;
+ mConstantBufferCol->UpdateParam("blue", NVDataRef<QT3DSU8>((QT3DSU8 *)&blue, 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::multiCBTest",
+ toRef(multiCBVertShader(isGLESContext(context), vtxProg)),
+ toRef(multiCBFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::scalarTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestConstantBuffer::scalarTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cbTrans(
+ "cbBufferTrans", *compResult.mShader);
+ mConstantBufferTrans->Update();
+ cbTrans.Set();
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cbCol(
+ "cbBufferCol", *compResult.mShader);
+ mConstantBufferCol->Update();
+ cbCol.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestConstantBuffer::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestConstantBuffer::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h
new file mode 100644
index 00000000..417e4bb3
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
+#define QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestConstantBuffer : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestConstantBuffer();
+ ~NVRenderTestConstantBuffer();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool scalarTest(NVRenderContext *context, userContextData *pUserData);
+ bool vectorTest(NVRenderContext *context, userContextData *pUserData);
+ bool structTest(NVRenderContext *context, userContextData *pUserData);
+ bool rawTest(NVRenderContext *context, userContextData *pUserData);
+ bool multiCBTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp
new file mode 100644
index 00000000..b12976c6
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestDrawIndirectBuffer.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderDrawIndirectBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestDrawIndirectBuffer::NVRenderTestDrawIndirectBuffer()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestDrawIndirectBuffer::~NVRenderTestDrawIndirectBuffer()
+{
+}
+
+bool NVRenderTestDrawIndirectBuffer::isSupported(NVRenderContext *context)
+{
+ // This is currently only supported on GL 4 and GLES 3.1
+ // we have no direct check for this but this is the same version
+ if (!context->IsAtomicCounterBufferSupported())
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestDrawIndirectBuffer::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= drawArrayIndirect(context, pUserData);
+ _curTest++;
+ success &= drawElementsIndirect(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestDrawIndirectBuffer::drawArrayIndirect(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderDrawIndirectBuffer> mDrawIndirectBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestDrawIndirectBuffer shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL, toConstDataRef(&strides, 1),
+ toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create input assembler";
+ return false;
+ }
+
+ // create draw indirect buffer
+ DrawArraysIndirectCommand command;
+ command.baseInstance = 0;
+ command.count = 6;
+ command.first = 0;
+ command.primCount = 1;
+ QT3DSU32 commandBufSize = sizeof(DrawArraysIndirectCommand);
+ NVDataRef<QT3DSU8> commandData((QT3DSU8 *)&command, commandBufSize);
+ mDrawIndirectBuffer = context->CreateDrawIndirectBuffer(NVRenderBufferUsageType::Dynamic,
+ commandBufSize, commandData);
+
+ if (!mDrawIndirectBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ mDrawIndirectBuffer->Bind();
+ context->DrawIndirect(mInputAssembler->GetPrimitiveType(), 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestDrawIndirectBuffer::drawElementsIndirect(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3, 4, 5 };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderDrawIndirectBuffer> mDrawIndirectBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestDrawIndirectBuffer shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // index buffer
+ bufSize = 6 * sizeof(unsigned short);
+ NVDataRef<QT3DSU8> idxData((QT3DSU8 *)indices, bufSize);
+ mIndexBuffer = context->CreateIndexBuffer(
+ NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU16, bufSize,
+ NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(indices), bufSize));
+ if (!mIndexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestPrimitives::Triangles: Failed to create index buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create input assembler";
+ return false;
+ }
+
+ // create draw indirect buffer
+ DrawElementsIndirectCommand command;
+ command.baseInstance = 0;
+ command.count = 6;
+ command.firstIndex = 0;
+ command.baseVertex = 0;
+ command.primCount = 1;
+ QT3DSU32 commandBufSize = sizeof(DrawElementsIndirectCommand);
+ NVDataRef<QT3DSU8> commandData((QT3DSU8 *)&command, commandBufSize);
+ mDrawIndirectBuffer = context->CreateDrawIndirectBuffer(NVRenderBufferUsageType::Dynamic,
+ commandBufSize, commandData);
+
+ if (!mDrawIndirectBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ mDrawIndirectBuffer->Bind();
+ context->DrawIndirect(mInputAssembler->GetPrimitiveType(), 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestDrawIndirectBuffer::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestDrawIndirectBuffer::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h
new file mode 100644
index 00000000..ee37a133
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_DRAW_INDIRECT_BUFFER_H
+#define QT3DS_RENDER_TEST_DRAW_INDIRECT_BUFFER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestDrawIndirectBuffer : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestDrawIndirectBuffer();
+ ~NVRenderTestDrawIndirectBuffer();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool drawArrayIndirect(NVRenderContext *context, userContextData *pUserData);
+ bool drawElementsIndirect(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp
new file mode 100644
index 00000000..c0cdc9e3
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestPrimitives.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *PassthroughVertShader()
+{
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+}
+
+static const char *SimpleFragShader()
+{
+ return "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor = vec4(0, 1, 0, 1);\n"
+ "}\n";
+}
+
+NVRenderTestPrimitives::NVRenderTestPrimitives()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestPrimitives::~NVRenderTestPrimitives()
+{
+}
+
+bool NVRenderTestPrimitives::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestPrimitives::renderPrimitive(NVRenderContext *context,
+ userContextData *pContextData,
+ const Vertex *pVertexData, unsigned int vertexCount,
+ const unsigned short *pIndexData,
+ unsigned int indexCount,
+ NVRenderDrawMode::Enum primType)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestPrimitives shader", toRef(PassthroughVertShader()), toRef(SimpleFragShader()));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = vertexCount * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)pVertexData, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestPrimitives::Triangles: Failed to create vertex buffer";
+ return false;
+ }
+
+ // index buffer
+ if (pIndexData && indexCount) {
+ bufSize = indexCount * sizeof(unsigned short);
+ NVDataRef<QT3DSU8> idxData((QT3DSU8 *)pIndexData, bufSize);
+ mIndexBuffer = context->CreateIndexBuffer(
+ NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU16, bufSize,
+ NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(pIndexData), bufSize));
+ if (!mIndexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestPrimitives::Triangles: Failed to create index buffer";
+ return false;
+ }
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestPrimitives::Triangles: Failed to create inout assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ QT3DSU32 count = (mIndexBuffer.mPtr) ? indexCount : vertexCount;
+ context->Draw(primType, count, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestPrimitives::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= triangles(context, pUserData);
+ _curTest++;
+ success &= triangleStrip(context, pUserData);
+ _curTest++;
+ success &= lines(context, pUserData);
+ _curTest++;
+ success &= lineStrip(context, pUserData);
+ _curTest++;
+ success &= trianglesIndexed(context, pUserData);
+ _curTest++;
+ success &= triangleStripIndexed(context, pUserData);
+ _curTest++;
+ success &= linesIndexed(context, pUserData);
+ _curTest++;
+ success &= lineStripIndexed(context, pUserData);
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestPrimitives::triangles(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.85, -0.9, 0) }, { QT3DSVec3(-0.85, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 6, NULL, 0,
+ NVRenderDrawMode::Triangles);
+}
+
+bool NVRenderTestPrimitives::triangleStrip(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0.0) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) } };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 4, NULL, 0,
+ NVRenderDrawMode::TriangleStrip);
+}
+
+bool NVRenderTestPrimitives::lines(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = {
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) }, { QT3DSVec3(0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) }, { QT3DSVec3(-0.85f, -0.9f, 0.0f) },
+ { QT3DSVec3(-0.85f, -0.9f, 0.0f) }, { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) }, { QT3DSVec3(0.85f, 0.9f, 0.0f) },
+ { QT3DSVec3(0.85f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(-0.9f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, -0.9f, 0.0f) }
+ };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 12, NULL, 0,
+ NVRenderDrawMode::Lines);
+}
+
+bool NVRenderTestPrimitives::lineStrip(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = {
+ { QT3DSVec3(-0.9f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) }, { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(-0.9f, 0.9f, 0.0f) },
+ };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 5, NULL, 0,
+ NVRenderDrawMode::LineStrip);
+}
+
+bool NVRenderTestPrimitives::trianglesIndexed(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.85, -0.9, 0) }, { QT3DSVec3(-0.85, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3, 4, 5 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 6, indices, 6,
+ NVRenderDrawMode::Triangles);
+}
+
+bool NVRenderTestPrimitives::triangleStripIndexed(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0.0) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 4, indices, 4,
+ NVRenderDrawMode::TriangleStrip);
+}
+
+bool NVRenderTestPrimitives::linesIndexed(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = {
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) }, { QT3DSVec3(0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(-0.85f, -0.9f, 0.0f) }, { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.85f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, 0.9f, 0.0f) },
+ };
+
+ const unsigned short indices[] = { 0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 5, 3 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 6, indices, 12,
+ NVRenderDrawMode::Lines);
+}
+
+bool NVRenderTestPrimitives::lineStripIndexed(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0.0) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3, 0 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 4, indices, 5,
+ NVRenderDrawMode::LineStrip);
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestPrimitives::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestPrimitives::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h
new file mode 100644
index 00000000..4b6128e2
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_PRIMITIVES_H
+#define QT3DS_RENDER_TEST_PRIMITIVES_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ struct Vertex
+ {
+ QT3DSVec3 positions;
+ };
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestPrimitives : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestPrimitives();
+ ~NVRenderTestPrimitives();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool triangles(NVRenderContext *context, userContextData *pUserData);
+ bool triangleStrip(NVRenderContext *context, userContextData *pUserData);
+ bool lines(NVRenderContext *context, userContextData *pUserData);
+ bool lineStrip(NVRenderContext *context, userContextData *pContextData);
+
+ bool trianglesIndexed(NVRenderContext *context, userContextData *pUserData);
+ bool triangleStripIndexed(NVRenderContext *context, userContextData *pUserData);
+ bool linesIndexed(NVRenderContext *context, userContextData *pUserData);
+ bool lineStripIndexed(NVRenderContext *context, userContextData *pContextData);
+
+ bool renderPrimitive(NVRenderContext *context, userContextData *pContextData,
+ const Vertex *pVertexData, unsigned int vertexCount,
+ const unsigned short *pIndexData, unsigned int indexCount,
+ NVRenderDrawMode::Enum primType);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_PRIMITIVES_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp
new file mode 100644
index 00000000..b08dec27
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestProgramPipeline.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderProgramPipeline.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+
+ prog += "out gl_PerVertex\n"
+ "{\n"
+ "\tvec4 gl_Position;\n"
+ "\tfloat gl_PointSize;\n"
+ "\tfloat gl_ClipDistance[];\n"
+ "};\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_col; // Vertex col\n"
+ "out vec3 color; // output color\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ " color = attr_col;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "in vec3 color; // input color\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4( color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestProgramPipeline::NVRenderTestProgramPipeline()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestProgramPipeline::~NVRenderTestProgramPipeline()
+{
+}
+
+bool NVRenderTestProgramPipeline::isSupported(NVRenderContext *context)
+{
+ return context->IsProgramPipelineSupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestProgramPipeline::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= vertFragSeparateTest(context, pUserData);
+ _curTest++;
+ success &= vertFragCombinedTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestProgramPipeline::vertFragSeparateTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ static const Vertex vertexColors[] = { { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderVertexBuffer> mColorBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderProgramPipeline> mProgramPipeline;
+ NVRenderVertexBuffer *attribBuffers[2];
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult vtxResult = context->CompileSource(
+ "NVRenderTestProgramPipeline vertex shader",
+ toRef(vertShader(vtxProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), true);
+ if (!vtxResult.mShader) {
+ return false;
+ }
+
+ NVRenderVertFragCompilationResult fragResult = context->CompileSource(
+ "NVRenderTestProgramPipeline fragment shader", NVConstDataRef<QT3DSI8>(),
+ toRef(fragShader(frgProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), true);
+
+ if (!fragResult.mShader) {
+ return false;
+ }
+
+ // setup program pipeline
+ mProgramPipeline = context->CreateProgramPipeline();
+ if (!mProgramPipeline) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestProgramPipeline: Failed to create program pipeline";
+ return false;
+ }
+
+ mProgramPipeline->SetProgramStages(vtxResult.mShader,
+ NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Vertex));
+ mProgramPipeline->SetProgramStages(fragResult.mShader,
+ NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Fragment));
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0, 0),
+ NVRenderVertexBufferEntry("attr_col", NVRenderComponentTypes::QT3DSF32, 3, 0, 1),
+ };
+
+ // position buffer
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create vertex buffer";
+ return false;
+ }
+ // color buffer
+ NVDataRef<QT3DSU8> colorData((QT3DSU8 *)vertexColors, bufSize);
+ mColorBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), colorData);
+ if (!mColorBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create color buffer";
+ return false;
+ }
+
+ attribBuffers[0] = mVertexBuffer;
+ attribBuffers[1] = mColorBuffer;
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides[2];
+ QT3DSU32 offsets[2];
+ strides[0] = mVertexBuffer->GetStride();
+ offsets[0] = 0;
+ strides[1] = mColorBuffer->GetStride();
+ offsets[1] = 0;
+
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, NVConstDataRef<NVRenderVertexBuffer *>(attribBuffers, 2), NULL,
+ toConstDataRef(strides, 2), toConstDataRef(offsets, 2), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveProgramPipeline(mProgramPipeline);
+ vtxResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ vtxResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveProgramPipeline(0);
+ return true;
+}
+
+bool NVRenderTestProgramPipeline::vertFragCombinedTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ static const Vertex vertexColors[] = { { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderVertexBuffer> mColorBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderProgramPipeline> mProgramPipeline;
+ NVRenderVertexBuffer *attribBuffers[2];
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestProgramPipeline vertex shader",
+ toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), true);
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ // setup program pipeline
+ mProgramPipeline = context->CreateProgramPipeline();
+ if (!mProgramPipeline) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestProgramPipeline: Failed to create program pipeline";
+ return false;
+ }
+
+ mProgramPipeline->SetProgramStages(
+ compResult.mShader, NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Vertex
+ | NVRenderShaderTypeValue::Fragment));
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0, 0),
+ NVRenderVertexBufferEntry("attr_col", NVRenderComponentTypes::QT3DSF32, 3, 0, 1),
+ };
+
+ // position buffer
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create vertex buffer";
+ return false;
+ }
+ // color buffer
+ NVDataRef<QT3DSU8> colorData((QT3DSU8 *)vertexColors, bufSize);
+ mColorBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), colorData);
+ if (!mColorBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create color buffer";
+ return false;
+ }
+
+ attribBuffers[0] = mVertexBuffer;
+ attribBuffers[1] = mColorBuffer;
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides[2];
+ QT3DSU32 offsets[2];
+ strides[0] = mVertexBuffer->GetStride();
+ offsets[0] = 0;
+ strides[1] = mColorBuffer->GetStride();
+ offsets[1] = 0;
+
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, NVConstDataRef<NVRenderVertexBuffer *>(attribBuffers, 2), NULL,
+ toConstDataRef(strides, 2), toConstDataRef(offsets, 2), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestAttribBuffers: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveProgramPipeline(mProgramPipeline);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveProgramPipeline(0);
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestProgramPipeline::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestProgramPipeline::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h
new file mode 100644
index 00000000..eeec086d
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_PROGRAM_PIPELINE_H
+#define QT3DS_RENDER_TEST_PROGRAM_PIPELINE_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestProgramPipeline : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestProgramPipeline();
+ ~NVRenderTestProgramPipeline();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool vertFragSeparateTest(NVRenderContext *context, userContextData *pUserData);
+ bool vertFragCombinedTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_PROGRAM_PIPELINE_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp
new file mode 100644
index 00000000..525f1f4e
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestTexture2D.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderTexture2DArray.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_uv; // texture coord\n"
+ "out vec3 varTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ " varTexCoord = attr_uv;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform sampler2DArray inTex;\n"
+ "in vec3 varTexCoord;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = texture(inTex, varTexCoord);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec3 texCoord;
+};
+
+static const Vertex vertexPositionsL0[] = {
+ { QT3DSVec3(-0.9, 0.0, 0), QT3DSVec3(0, 0, 0) }, { QT3DSVec3(0.0, 0.9, 0), QT3DSVec3(1, 1, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0), QT3DSVec3(0, 1, 0) }, { QT3DSVec3(-0.9, 0.0, 0), QT3DSVec3(0, 0, 0) },
+ { QT3DSVec3(0.0, 0.0, 0), QT3DSVec3(1, 0, 0) }, { QT3DSVec3(0.0, 0.9, 0), QT3DSVec3(1, 1, 0) }
+};
+
+static const Vertex vertexPositionsL1[] = {
+ { QT3DSVec3(0.0, -0.9, 0), QT3DSVec3(0, 0, 1) }, { QT3DSVec3(0.9, 0.0, 0), QT3DSVec3(1, 1, 1) },
+ { QT3DSVec3(0.0, 0.0, 0), QT3DSVec3(0, 1, 1) }, { QT3DSVec3(0.0, -0.9, 0), QT3DSVec3(0, 0, 1) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec3(1, 0, 1) }, { QT3DSVec3(0.9, 0.0, 0), QT3DSVec3(1, 1, 1) }
+};
+
+#define TEXTURE_LAYER_SIZE 2
+#define TEXTURE_SIZE 64
+#define PATTERN_SIZE 0x8
+
+NVRenderTestTexture2D::NVRenderTestTexture2D()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+ _pTextureData = NULL;
+}
+
+NVRenderTestTexture2D::~NVRenderTestTexture2D()
+{
+}
+
+bool NVRenderTestTexture2D::isSupported(NVRenderContext *context)
+{
+ return context->IsTextureArraySupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestTexture2D::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ // alloc data
+ _pTextureData = new unsigned char[TEXTURE_SIZE * TEXTURE_SIZE * 4 * TEXTURE_LAYER_SIZE];
+ CreateTexData(_pTextureData);
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= texArray2DTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ if (_pTextureData)
+ delete _pTextureData;
+
+ return success;
+}
+
+void NVRenderTestTexture2D::CreateTexData(unsigned char *_pOutData)
+{
+ if (!_pOutData)
+ return;
+
+ unsigned char *_pData = _pOutData;
+
+ // Create a checkerboard pattern
+ for (int i = 0; i < TEXTURE_LAYER_SIZE; i++) {
+ for (int j = 0; j < TEXTURE_SIZE; j++) {
+ for (int k = 0; k < TEXTURE_SIZE; k++) {
+ unsigned char c = (((j & PATTERN_SIZE) == 0) ^ ((k & PATTERN_SIZE) == 0)) * 255;
+ *_pData++ = 0x0;
+ *_pData++ = c >> i;
+ *_pData++ = 0x0;
+ *_pData++ = 0xFF;
+ }
+ }
+ }
+}
+
+bool NVRenderTestTexture2D::renderTexArrayQuad(NVRenderContext *context, userContextData *pUserData,
+ NVRenderTexture2DArray *pTex, QT3DSU8 *vertexPositions)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTexture2D shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_uv", NVRenderComponentTypes::QT3DSF32, 3, 12),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData(vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 6 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTexture2D: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTexture2D: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ NVRenderCachedShaderProperty<NVRenderTexture2DArray *> mArrayTexture("inTex",
+ *compResult.mShader);
+ mArrayTexture.Set(pTex);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestTexture2D::texArray2DTest(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // create texture
+ NVScopedRefCounted<NVRenderTexture2DArray> mArrayTexture;
+ mArrayTexture = context->CreateTexture2DArray();
+ mArrayTexture->SetTextureData(
+ NVDataRef<QT3DSU8>(_pTextureData, TEXTURE_SIZE * TEXTURE_SIZE * 4 * TEXTURE_LAYER_SIZE), 0,
+ TEXTURE_SIZE, TEXTURE_SIZE, TEXTURE_LAYER_SIZE, NVRenderTextureFormats::RGBA8);
+
+ success &= renderTexArrayQuad(context, pUserData, mArrayTexture, (QT3DSU8 *)vertexPositionsL0);
+ success &= renderTexArrayQuad(context, pUserData, mArrayTexture, (QT3DSU8 *)vertexPositionsL1);
+
+ return success;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestTexture2D::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestTexture2D::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h
new file mode 100644
index 00000000..5c5de114
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_TEXTURE_2D_H
+#define QT3DS_RENDER_TEST_TEXTURE_2D_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderTexture2D;
+ class NVRenderTexture2DArray;
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestTexture2D : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestTexture2D();
+ ~NVRenderTestTexture2D();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool texArray2DTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderTexArrayQuad(NVRenderContext *context, userContextData *pUserData,
+ NVRenderTexture2DArray *pTex, QT3DSU8 *vertexPositions);
+ void CreateTexData(unsigned char *_pOutData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ unsigned char *_pTextureData;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_TEXTURE_2D_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp
new file mode 100644
index 00000000..bd595983
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestTimerQuery.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderTimerQuery.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+NVRenderTestTimerQuery::NVRenderTestTimerQuery()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestTimerQuery::~NVRenderTestTimerQuery()
+{
+}
+
+bool NVRenderTestTimerQuery::isSupported(NVRenderContext *context)
+{
+ return context->IsTimerQuerySupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestTimerQuery::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= timerTest(context, pUserData);
+ _curTest++;
+ success &= absoluteTimerTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestTimerQuery::renderQuad(NVRenderContext *context, userContextData *pUserData,
+ QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTimerQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTimerQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTimerQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestTimerQuery::timerTest(NVRenderContext *context, userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ QT3DSMat44 proj = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&proj, -1, 1, -1, 1, -10, 10);
+ QT3DSVec3 color(1.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTimerQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTimerQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTimerQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+
+ // setup translation
+ QT3DSMat44 transZ;
+ NvRenderTestMatrixTranslation(&transZ, 0.0, 0.0, 0.2);
+ mvp = transZ * proj;
+
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ NVScopedRefCounted<NVRenderTimerQuery> pQuery = context->CreateTimerQuery();
+
+ // render 1000 quads this should take at least some amount of time
+ pQuery->Begin();
+ for (QT3DSI32 i = 0; i < 1000; i++) {
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+ }
+ pQuery->End();
+
+ // get elapsed time in nano seconds
+ QT3DSU64 result = 0;
+ pQuery->GetResult(&result);
+ // convert to milli second
+ QT3DSF64 elapsed = double(result) / 1e06;
+
+ /// it should take at least a fraction of a milli second
+ if (elapsed > 0.0)
+ color.x = 0.0; // right
+ else
+ color.y = 0.0; // wrong
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ renderQuad(context, pUserData, color);
+
+ return (elapsed > 0.0);
+}
+
+bool NVRenderTestTimerQuery::absoluteTimerTest(NVRenderContext *context, userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ QT3DSMat44 proj = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&proj, -1, 1, -1, 1, -10, 10);
+ QT3DSVec3 color(1.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTimerQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTimerQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestTimerQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+
+ // setup translation
+ QT3DSMat44 transZ;
+ NvRenderTestMatrixTranslation(&transZ, 0.0, 0.0, 0.2);
+ mvp = transZ * proj;
+
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ NVScopedRefCounted<NVRenderTimerQuery> pQueryStart = context->CreateTimerQuery();
+ NVScopedRefCounted<NVRenderTimerQuery> pQueryEnd = context->CreateTimerQuery();
+
+ // render 1000 quads this should take at least some amount of time
+ pQueryStart->SetTimerQuery();
+ for (QT3DSI32 i = 0; i < 1000; i++) {
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+ }
+ pQueryEnd->SetTimerQuery();
+
+ // get absolute time in nano seconds
+ QT3DSU64 start = 0;
+ pQueryStart->GetResult(&start);
+ QT3DSU64 end = 0;
+ pQueryEnd->GetResult(&end);
+
+ // convert to milli second
+ QT3DSF64 elapsed = double(end - start) / 1e06;
+
+ // it should take at least a fraction of a milli second
+ if (elapsed > 0.0)
+ color.x = 0.0; // right
+ else
+ color.y = 0.0; // wrong
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ renderQuad(context, pUserData, color);
+
+ return (elapsed > 0.0);
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestTimerQuery::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestTimerQuery::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h
new file mode 100644
index 00000000..127c25fc
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_TIMER_QUERY_H
+#define QT3DS_RENDER_TEST_TIMER_QUERY_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderTimerQuery;
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestTimerQuery : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestTimerQuery();
+ ~NVRenderTestTimerQuery();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool timerTest(NVRenderContext *context, userContextData *pUserData);
+ bool absoluteTimerTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderQuad(NVRenderContext *context, userContextData *pUserData, QT3DSVec3 color);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_TIMER_QUERY_H
diff --git a/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp
new file mode 100644
index 00000000..f00d648f
--- /dev/null
+++ b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp
@@ -0,0 +1,636 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestComputeShader.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderImageTexture.h"
+#include "render/Qt3DSRenderStorageBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vertTexShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec2 attr_uv; // texture coord\n"
+ "out vec2 varTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ " varTexCoord = attr_uv;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragTexShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform sampler2D inTex;\n"
+ "in vec2 varTexCoord;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = texture(inTex, varTexCoord);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *computeShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x =16, local_size_y = 16) in;\n\n"
+ "void main()\n"
+ "{\n"
+ " // do nothing\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *computeWorkShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "precision mediump image2D;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 32, local_size_y = 32) in;\n\n"
+ "layout (rgba8, binding = 2) uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), vec4( "
+ "vec2(gl_LocalInvocationID.xy) / vec2(gl_WorkGroupSize.xy), 0.0, 1.0 ) );\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *computeStorageShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "#extension GL_ARB_shader_storage_buffer_object : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "#extension GL_ARB_shader_storage_buffer_object : enable\n";
+ }
+
+ prog += "layout( std140, binding=4 ) buffer Pos\n"
+ "{\n"
+ " vec4 Positions[ ]; // array of positions\n"
+ "};\n"
+ "// Set workgroup layout;\n"
+ "layout (local_size_x = 32, local_size_y = 1) in;\n\n"
+ "void main()\n"
+ "{\n"
+ " uint gid = gl_GlobalInvocationID.x;\n"
+ " if ( gid < uint(1000) ) {\n"
+ " Positions[gid].x = float(gl_GlobalInvocationID.x);\n"
+ " }\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec2 texCoord;
+};
+
+NVRenderTestComputeShader::NVRenderTestComputeShader()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestComputeShader::~NVRenderTestComputeShader()
+{
+}
+
+bool NVRenderTestComputeShader::isSupported(NVRenderContext *context)
+{
+ return context->IsComputeSupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestComputeShader::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ context->SetRenderTarget(NULL);
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= computeCompile(context, pUserData);
+ _curTest++;
+ success &= computeWorkgroup(context, pUserData);
+ _curTest++;
+ success &= computeStorage(context, pUserData);
+ _curTest++;
+
+ return success;
+}
+
+bool NVRenderTestComputeShader::computeCompile(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestComputeShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a compute shader which does nothing just as a compile check
+ std::string computeProg;
+ NVRenderVertFragCompilationResult computeResult = context->CompileComputeSource(
+ "Compute nothing shader", toRef(computeShader(computeProg, isGLESContext(context))));
+
+ if (!computeResult.mShader) {
+ color.x = 1.0;
+ color.y = 0.0;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+ if (computeResult.mShader)
+ computeResult.mShader->release();
+
+ return true;
+}
+
+#define WORKGROUP_SIZE 32
+
+bool NVRenderTestComputeShader::computeWorkgroup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = {
+ { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) }, { QT3DSVec3(0.9, 0.9, 0), QT3DSVec2(1, 1) },
+ { QT3DSVec3(-0.9, 0.9, 0), QT3DSVec2(0, 1) }, { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(1, 0) }, { QT3DSVec3(0.9, 0.9, 0), QT3DSVec2(1, 1) }
+ };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create texture
+ NVScopedRefCounted<NVRenderTexture2D> mColorTexture;
+ mColorTexture = context->CreateTexture2D();
+ mColorTexture->SetTextureStorage(1, pUserData->winWidth, pUserData->winHeight,
+ NVRenderTextureFormats::RGBA8);
+ // create a image buffer wrapper
+ NVScopedRefCounted<NVRenderImage2D> mColorImage;
+ mColorImage = context->CreateImage2D(mColorTexture, NVRenderImageAccessType::Write);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestComputeShader shader", toRef(vertTexShader(vtxProg, isGLESContext(context))),
+ toRef(fragTexShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_uv", NVRenderComponentTypes::QT3DSF32, 2, 12),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a compute shader which outputs the workgroups as color codes
+ std::string computeProg;
+ NVRenderVertFragCompilationResult computeResult = context->CompileComputeSource(
+ "Compute workgroup shader", toRef(computeWorkShader(computeProg, isGLESContext(context))));
+
+ if (!computeResult.mShader) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create compute shader";
+ return false;
+ }
+
+ // set program
+ context->SetActiveShader(computeResult.mShader);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> mOutputImage("outputImage",
+ *computeResult.mShader);
+ mOutputImage.Set(mColorImage);
+ // run compute shader
+ context->DispatchCompute(computeResult.mShader, pUserData->winWidth / WORKGROUP_SIZE,
+ pUserData->winHeight / WORKGROUP_SIZE, 1);
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderImageAccess);
+ // sync
+ context->SetMemoryBarrier(flags);
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+ // set texture
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> mInputImage("inTex", *compResult.mShader);
+ mInputImage.Set(mColorTexture);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 6, 0);
+
+ context->SetActiveShader(0);
+
+ compResult.mShader->release();
+ if (computeResult.mShader)
+ computeResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestComputeShader::computeStorage(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create vertex buffer for compute shader usage
+ NVScopedRefCounted<NVRenderVertexBuffer> mComputeVertexBuffer;
+ QT3DSF32 *storageData = new QT3DSF32[1000 * 4]; // vec 4 in shader program
+ NVDataRef<QT3DSU8> storData((QT3DSU8 *)storageData, 1000 * sizeof(QT3DSF32) * 4);
+ mComputeVertexBuffer = context->CreateVertexBuffer(
+ NVRenderBufferUsageType::Static, 1000 * sizeof(QT3DSF32) * 4, sizeof(QT3DSF32), storData);
+ if (!mComputeVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create compute vertex buffer";
+ return false;
+ }
+ // create storage wrapper for vertex buffer
+ NVScopedRefCounted<NVRenderStorageBuffer> mComputeStorageBuffer;
+ mComputeStorageBuffer =
+ context->CreateStorageBuffer("Pos", NVRenderBufferUsageType::Static,
+ 1000 * sizeof(QT3DSF32) * 4, storData, mComputeVertexBuffer.mPtr);
+ if (!mComputeStorageBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create compute storage buffer";
+ return false;
+ }
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestComputeShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a compute shader which places id's into the buffer
+ std::string computeProg;
+ NVRenderVertFragCompilationResult computeResult = context->CompileComputeSource(
+ "Compute storage shader", toRef(computeStorageShader(computeProg, isGLESContext(context))));
+
+ if (!computeResult.mShader) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestComputeShader: Failed to create compute shader";
+ return false;
+ }
+
+ // set and run compute program
+ context->SetActiveShader(computeResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderStorageBuffer *> storageBuffer(
+ "Pos", *computeResult.mShader);
+ storageBuffer.Set();
+ // run compute shader
+ context->DispatchCompute(computeResult.mShader, 1024 / WORKGROUP_SIZE, 1, 1);
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderStorage
+ | NVRenderBufferBarrierValues::VertexAttribArray);
+ // sync
+ context->SetMemoryBarrier(flags);
+
+ // check content
+ bool contentOK = true;
+ mComputeVertexBuffer->Bind();
+ NVDataRef<QT3DSU8> pData = mComputeVertexBuffer->MapBuffer();
+ QT3DSF32 *fData = (QT3DSF32 *)pData.begin();
+ QT3DSU32 size = pData.size() / 4;
+ for (QT3DSU32 i = 0, k = 0; i < size; i += 4, k++) {
+ if (fData[i] != (float)k)
+ contentOK = false;
+ }
+
+ mComputeVertexBuffer->UnmapBuffer();
+
+ if (!contentOK) {
+ color.x = 1.0;
+ color.y = 0.0;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+ if (computeResult.mShader)
+ computeResult.mShader->release();
+
+ delete storageData;
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestComputeShader::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestComputeShader::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h
new file mode 100644
index 00000000..826fb9c7
--- /dev/null
+++ b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_COMPUTE_SHADER_H
+#define QT3DS_RENDER_TEST_COMPUTE_SHADER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestComputeShader : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestComputeShader();
+ ~NVRenderTestComputeShader();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool computeCompile(NVRenderContext *context, userContextData *pUserData);
+ bool computeWorkgroup(NVRenderContext *context, userContextData *pUserData);
+ bool computeStorage(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif
diff --git a/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp
new file mode 100644
index 00000000..32c5e122
--- /dev/null
+++ b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestFboMsaa.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *PassthroughVertShader()
+{
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+}
+
+static const char *SimpleFragShader()
+{
+ return "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform vec3 color;\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor = vec4( color, 1.0);\n"
+ "}\n";
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+NVRenderTestFboMsaa::NVRenderTestFboMsaa()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestFboMsaa::~NVRenderTestFboMsaa()
+{
+}
+
+bool NVRenderTestFboMsaa::isSupported(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+ NVRenderContextType nonSupportedFlags(NVRenderContextValues::GL2 | NVRenderContextValues::GLES2
+ | NVRenderContextValues::GLES3);
+
+ // This is currently only supported on >= GL3 && >= GLES 3.1
+ if ((ctxType & nonSupportedFlags))
+ return false;
+
+ return true;
+}
+
+bool NVRenderTestFboMsaa::run(NVRenderContext *context, userContextData *pUserData)
+{
+ if (!setupResolveFbo(context, pUserData))
+ return false;
+
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetRenderTarget(NULL);
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= simpleMsaaTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestFboMsaa::renderTriangle(NVRenderContext *context, QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestBackendQuery shader", toRef(PassthroughVertShader()),
+ toRef(SimpleFragShader()));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestFboMsaa: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestFboMsaa: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestFboMsaa::setupResolveFbo(NVRenderContext *context, userContextData *pUserData)
+{
+ // color texture
+ m_ResolveColorTexture = context->CreateTexture2D();
+ m_ResolveColorTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, pUserData->winWidth,
+ pUserData->winHeight, NVRenderTextureFormats::RGBA8);
+ // depth texture
+ m_ResolveDepthTexture = context->CreateTexture2D();
+ m_ResolveDepthTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, pUserData->winWidth,
+ pUserData->winHeight, NVRenderTextureFormats::Depth24);
+ // create resolve FBO
+ m_ResolveFbo = context->CreateFrameBuffer();
+ m_ResolveFbo->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*m_ResolveColorTexture));
+ m_ResolveFbo->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_ResolveDepthTexture));
+
+ return m_ResolveFbo->IsComplete();
+}
+
+bool NVRenderTestFboMsaa::simpleMsaaTest(NVRenderContext *context, userContextData *pUserData)
+{
+ // create a multisampled FBO
+ NVScopedRefCounted<NVRenderFrameBuffer> msFBO;
+ NVScopedRefCounted<NVRenderTexture2D> msColorTexture;
+ NVScopedRefCounted<NVRenderTexture2D> msDepth24Texture;
+
+ msColorTexture = context->CreateTexture2D();
+ msColorTexture->SetTextureDataMultisample(4, pUserData->winWidth, pUserData->winHeight,
+ NVRenderTextureFormats::RGBA8);
+ msDepth24Texture = context->CreateTexture2D();
+ msDepth24Texture->SetTextureDataMultisample(4, pUserData->winWidth, pUserData->winHeight,
+ NVRenderTextureFormats::Depth24);
+
+ msFBO = context->CreateFrameBuffer();
+ msFBO->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*msColorTexture),
+ NVRenderTextureTargetType::Texture2D_MS);
+ msFBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*msDepth24Texture),
+ NVRenderTextureTargetType::Texture2D_MS);
+
+ if (!msFBO->IsComplete())
+ return false;
+
+ // clear and draw to multisampled buffer
+ context->SetRenderTarget(msFBO);
+ context->SetMultisampleEnabled(true);
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+ renderTriangle(context, qt3ds::QT3DSVec3(0.0, 1.0, 0.0));
+ context->SetMultisampleEnabled(false);
+
+ // do resolve blit
+ // first we must setup the render target
+ context->SetRenderTarget(m_ResolveFbo);
+ // second setup read target
+ context->SetReadTarget(msFBO);
+ context->SetReadBuffer(NVReadFaces::Color0);
+
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ context->BlitFramebuffer(0, 0, pUserData->winWidth, pUserData->winHeight, 0, 0,
+ pUserData->winWidth, pUserData->winHeight, NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+
+ // copy to default buffer
+ // first we must setup the render target
+ context->SetRenderTarget(NULL);
+ // second setup read target
+ context->SetReadTarget(m_ResolveFbo);
+ context->SetReadBuffer(NVReadFaces::Color0);
+
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ context->BlitFramebuffer(0, 0, pUserData->winWidth, pUserData->winHeight, 0, 0,
+ pUserData->winWidth, pUserData->winHeight, NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+
+ context->SetReadTarget(NULL);
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestFboMsaa::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestFboMsaa::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ m_ResolveColorTexture->release();
+ m_ResolveDepthTexture->release();
+ m_ResolveFbo->release();
+
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ context->SetRenderTarget(NULL);
+}
diff --git a/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h
new file mode 100644
index 00000000..bf9ed842
--- /dev/null
+++ b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_FBO_MSAA_H
+#define QT3DS_RENDER_TEST_FBO_MSAA_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestFboMsaa : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestFboMsaa();
+ ~NVRenderTestFboMsaa();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool setupResolveFbo(NVRenderContext *context, userContextData *pUserData);
+ bool renderTriangle(NVRenderContext *context, QT3DSVec3 color);
+
+ // tests
+ bool simpleMsaaTest(NVRenderContext *context, userContextData *pUserData);
+
+ NVScopedRefCounted<NVRenderFrameBuffer> m_ResolveFbo;
+ NVScopedRefCounted<NVRenderTexture2D> m_ResolveColorTexture;
+ NVScopedRefCounted<NVRenderTexture2D> m_ResolveDepthTexture;
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_FBO_MSAA_H
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp
new file mode 100644
index 00000000..ef266ad8
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestGeometryShader.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderImageTexture.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *geometryShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_geometry_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ // pass through shader
+ prog += "layout (triangles) in;\n"
+ "layout (triangle_strip, max_vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ " int i;\n"
+ " for(i=0; i<gl_in.length(); i++)\n"
+ " {\n"
+ " gl_Position = gl_in[i].gl_Position;\n"
+ " EmitVertex();\n"
+ " }\n"
+ " EndPrimitive();\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *wireframeShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_geometry_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ // convert to wireframe
+ prog += "layout (triangles) in;\n"
+ "layout (line_strip, max_vertices = 4) out;\n"
+ "void main()\n"
+ "{\n"
+ " int i;\n"
+ " for(i=0; i<gl_in.length(); i++)\n"
+ " {\n"
+ " gl_Position = gl_in[i].gl_Position;\n"
+ " EmitVertex();\n"
+ " }\n"
+ " gl_Position = gl_in[0].gl_Position;\n"
+ " EmitVertex();\n"
+ " EndPrimitive();\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec2 texCoord;
+};
+
+NVRenderTestGeometryShader::NVRenderTestGeometryShader()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestGeometryShader::~NVRenderTestGeometryShader()
+{
+}
+
+bool NVRenderTestGeometryShader::isSupported(NVRenderContext *context)
+{
+ return context->IsGeometryStageSupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestGeometryShader::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ context->SetRenderTarget(NULL);
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= geometryCompile(context, pUserData);
+ _curTest++;
+ success &= wireframe(context, pUserData);
+ _curTest++;
+
+ return success;
+}
+
+bool NVRenderTestGeometryShader::geometryCompile(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestGeometryShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestGeometryShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestGeometryShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a geometry shader which does nothing just as a compile check
+ std::string geomProg;
+ std::string vtxProgDummy;
+ std::string frgProgDummy;
+ NVRenderVertFragCompilationResult geomResult = context->CompileSource(
+ "NVRenderTestGeometryShader shader",
+ toRef(vertShader(vtxProgDummy, isGLESContext(context))),
+ toRef(fragShader(frgProgDummy, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), toRef(geometryShader(geomProg, isGLESContext(context))));
+
+ if (!geomResult.mShader) {
+ color.x = 1.0;
+ color.y = 0.0;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+ if (geomResult.mShader)
+ geomResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestGeometryShader::wireframe(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ // geometry shader converts primitives from triangles to lines
+ std::string vtxProg;
+ std::string frgProg;
+ std::string geomProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestGeometryShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), toRef(wireframeShader(geomProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestGeometryShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestGeometryShader: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestGeometryShader::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestGeometryShader::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h
new file mode 100644
index 00000000..139a7e26
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_GEOMETRY_SHADER_H
+#define QT3DS_RENDER_TEST_GEOMETRY_SHADER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestGeometryShader : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestGeometryShader();
+ ~NVRenderTestGeometryShader();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool geometryCompile(NVRenderContext *context, userContextData *pUserData);
+ bool wireframe(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp
new file mode 100644
index 00000000..34cfe860
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestOcclusionQuery.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderOcclusionQuery.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+static const Vertex largeQuadPositions[] = { { QT3DSVec3(-0.7, 0.7, 0) }, { QT3DSVec3(-0.7, -0.7, 0) },
+ { QT3DSVec3(0.7, -0.7, 0) }, { QT3DSVec3(-0.7, 0.7, 0) },
+ { QT3DSVec3(0.7, -0.7, 0) }, { QT3DSVec3(0.7, 0.7, 0) } };
+
+static const Vertex smallQuadPositions[] = { { QT3DSVec3(-0.5, 0.5, 0) }, { QT3DSVec3(-0.5, -0.5, 0) },
+ { QT3DSVec3(0.5, -0.5, 0) }, { QT3DSVec3(-0.5, 0.5, 0) },
+ { QT3DSVec3(0.5, -0.5, 0) }, { QT3DSVec3(0.5, 0.5, 0) } };
+
+NVRenderTestOcclusionQuery::NVRenderTestOcclusionQuery()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestOcclusionQuery::~NVRenderTestOcclusionQuery()
+{
+}
+
+bool NVRenderTestOcclusionQuery::isSupported(NVRenderContext *context)
+{
+ return context->IsSampleQuerySupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestOcclusionQuery::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= occlusionPassTest(context, pUserData);
+ _curTest++;
+ success &= occlusionFailTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestOcclusionQuery::renderQuad(NVRenderContext *context, userContextData *pUserData,
+ QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestOcclusionQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestOcclusionQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestOcclusionQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+void NVRenderTestOcclusionQuery::renderPrim(NVRenderContext *context, userContextData *pUserData,
+ void *pData, float zOffset, QT3DSVec3 color,
+ NVRenderOcclusionQuery *pQuery)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVB;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mIA;
+ Vertex *pVtxData = (Vertex *)pData;
+ QT3DSMat44 proj = QT3DSMat44::createIdentity();
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&proj, -1, 1, -1, 1, -10, 10);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestOcclusionQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertDataSmall((QT3DSU8 *)pVtxData, bufSize);
+ mVB = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize, 3 * sizeof(QT3DSF32),
+ vertDataSmall);
+ if (!mVB)
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestOcclusionQuery: Failed to create vertex buffer";
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVB->GetStride();
+ QT3DSU32 offsets = 0;
+ mIA = context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVB.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mVB) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestOcclusionQuery: Failed to create input assembler";
+ return;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mIA);
+ // setup translation
+ QT3DSMat44 transZ;
+ NvRenderTestMatrixTranslation(&transZ, 0.0, 0.0, zOffset);
+ mvp = transZ * proj;
+
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ // start query
+ if (pQuery)
+ pQuery->Begin();
+
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ // end query
+ if (pQuery)
+ pQuery->End();
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+}
+
+bool NVRenderTestOcclusionQuery::occlusionPassTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderOcclusionQuery> pQuery = context->CreateOcclusionQuery();
+
+ renderPrim(context, pUserData, (void *)largeQuadPositions, 0.1, QT3DSVec3(0.0, 0.0, 1.0), NULL);
+ // this quad should be covered by the previous one
+ renderPrim(context, pUserData, (void *)smallQuadPositions, 0.2, QT3DSVec3(1.0, 1.0, 0.0), pQuery);
+ // check visibility
+ QT3DSU32 result = 0;
+ pQuery->GetResult(&result);
+
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ if (result)
+ color.x = 1.0; // wrong
+ else
+ color.y = 1.0; // right
+
+ renderQuad(context, pUserData, color);
+
+ return (result == 0);
+}
+
+bool NVRenderTestOcclusionQuery::occlusionFailTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderOcclusionQuery> pQuery = context->CreateOcclusionQuery();
+
+ renderPrim(context, pUserData, (void *)largeQuadPositions, 0.2, QT3DSVec3(0.0, 0.0, 1.0), NULL);
+ // this quad should be visible by the previous one
+ renderPrim(context, pUserData, (void *)smallQuadPositions, 0.1, QT3DSVec3(1.0, 1.0, 0.0), pQuery);
+ // check visibility
+ QT3DSU32 result = 0;
+ pQuery->GetResult(&result);
+
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ if (result == 0)
+ color.x = 1.0; // wrong
+ else
+ color.y = 1.0; // right
+
+ renderQuad(context, pUserData, color);
+
+ return (result == 1);
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestOcclusionQuery::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestOcclusionQuery::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h
new file mode 100644
index 00000000..d540dadf
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_OCCLUSION_QUERY_H
+#define QT3DS_RENDER_TEST_OCCLUSION_QUERY_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderOcclusionQuery;
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestOcclusionQuery : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestOcclusionQuery();
+ ~NVRenderTestOcclusionQuery();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool occlusionPassTest(NVRenderContext *context, userContextData *pUserData);
+ bool occlusionFailTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderQuad(NVRenderContext *context, userContextData *pUserData, QT3DSVec3 color);
+ void renderPrim(NVRenderContext *context, userContextData *pUserData, void *pData, float z,
+ QT3DSVec3 color, NVRenderOcclusionQuery *pQuery);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_OCCLUSION_QUERY_H
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp
new file mode 100644
index 00000000..655dc9f5
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp
@@ -0,0 +1,560 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestTessellation.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/backends/gl/Qt3DSOpenGLUtil.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vertPhongShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_norm; // normal pos\n"
+ "out vec3 ctNorm; // output normal control patch\n"
+ "void main()\n"
+ "{\n"
+ " ctNorm = attr_norm;\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragPhongShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "in vec3 normWorld;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessControlShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "// number of CPs in patch\n"
+ "layout (vertices = 3) out;\n"
+ "uniform float tessLevelInner; // controlled by keyboard buttons\n"
+ "uniform float tessLevelOuter; // controlled by keyboard buttons\n"
+ "void main () {\n"
+ "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "// Calculate the tessellation levels\n"
+ "gl_TessLevelInner[0] = tessLevelInner; // number of nested primitives to generate\n"
+ "gl_TessLevelOuter[0] = tessLevelOuter; // times to subdivide first side\n"
+ "gl_TessLevelOuter[1] = tessLevelOuter; // times to subdivide second side\n"
+ "gl_TessLevelOuter[2] = tessLevelOuter; // times to subdivide third side\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessPhongControlShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog +=
+ "// number of CPs in patch\n"
+ "layout (vertices = 3) out;\n"
+ "// phong tessellation per patch data\n"
+ "struct PhongTessPatch {\n"
+ " float projIJ;\n"
+ " float projJK;\n"
+ " float projIK;\n"
+ "};\n"
+ "in vec3 ctNorm[]; // control point normal\n"
+ "out vec3 normObj[]; // output normal pos\n"
+ "uniform float tessLevels;\n"
+ "uniform float tessBlend;\n"
+ "out PhongTessPatch tcTessPatch[3];\n"
+ "float PIi(int i, vec3 q)\n"
+ "{\n"
+ " vec3 q_minus_p = q - gl_in[i].gl_Position.xyz;\n"
+ " return q[gl_InvocationID] - dot(q_minus_p, ctNorm[i]) * ctNorm[i][gl_InvocationID];\n"
+ "}\n"
+ "void main () {\n"
+ " // path through data\n"
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ " normObj[gl_InvocationID] = ctNorm[gl_InvocationID];\n"
+ " // compute projections separate for each xyz component\n"
+ " tcTessPatch[gl_InvocationID].projIJ = PIi(0, gl_in[1].gl_Position.xyz) + PIi(1, "
+ "gl_in[0].gl_Position.xyz);\n"
+ " tcTessPatch[gl_InvocationID].projJK = PIi(1, gl_in[2].gl_Position.xyz) + PIi(2, "
+ "gl_in[1].gl_Position.xyz);\n"
+ " tcTessPatch[gl_InvocationID].projIK = PIi(2, gl_in[0].gl_Position.xyz) + PIi(0, "
+ "gl_in[2].gl_Position.xyz);\n"
+ " // set the tessellation levels\n"
+ " gl_TessLevelInner[0] = tessLevels; // number of nested primitives to generate\n"
+ " gl_TessLevelOuter[gl_InvocationID] = tessLevels; // times to subdivide first side\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessEvaluationShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "// triangles, quads, or isolines\n"
+ "layout (triangles, equal_spacing, ccw) in;\n"
+ "uniform mat4 mat_mvp;\n"
+ "// gl_TessCoord is location within the patch\n"
+ "// (barycentric for triangles, UV for quads)\n"
+ "void main () {\n"
+ "vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position; // x is one corner\n"
+ "vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position; // y is the 2nd corner\n"
+ "vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position; // z is the 3rd corner (ignore when "
+ "using quads)\n"
+ "vec4 pos = p0 + p1 + p2;\n"
+ "gl_Position = mat_mvp * pos;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessPhongEvaluationShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "// triangles, quads, or isolines\n"
+ "layout (triangles, fractional_odd_spacing, ccw) in;\n"
+ "struct PhongTessPatch {\n"
+ " float projIJ;\n"
+ " float projJK;\n"
+ " float projIK;\n"
+ "};\n"
+ "in vec3 normObj[]; // control point normal\n"
+ "out vec3 normWorld; // output normal pos\n"
+ "in PhongTessPatch tcTessPatch[];\n"
+ "uniform mat4 mat_mvp;\n"
+ "uniform float tessBlend;\n"
+ "// gl_TessCoord is location within the patch\n"
+ "// (barycentric for triangles, UV for quads)\n"
+ "void main () {\n"
+ " // output normal\n"
+ " // pre compute square tesselation coord\n"
+ " vec3 tessSquared = gl_TessCoord * gl_TessCoord;\n"
+ " vec3 norm = gl_TessCoord.x * normObj[0]\n"
+ " + gl_TessCoord.y * normObj[1]\n"
+ " + gl_TessCoord.z * normObj[2]; // z is the 3rd corner (ignore when "
+ "using quads)\n"
+ " // barycentric linear position\n"
+ " vec3 linearPos = gl_TessCoord.x * gl_in[0].gl_Position.xyz\n"
+ " + gl_TessCoord.y * gl_in[1].gl_Position.xyz\n"
+ " + gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
+ " // projective terms\n"
+ " vec3 projJI = vec3(tcTessPatch[0].projIJ, tcTessPatch[1].projIJ, "
+ "tcTessPatch[2].projIJ);\n"
+ " vec3 projKJ = vec3(tcTessPatch[0].projJK, tcTessPatch[1].projJK, "
+ "tcTessPatch[2].projJK);\n"
+ " vec3 projIK = vec3(tcTessPatch[0].projIK, tcTessPatch[1].projIK, "
+ "tcTessPatch[2].projIK);\n"
+ " // phong interpolated position\n"
+ " vec3 phongPos = tessSquared.x * gl_in[0].gl_Position.xyz\n"
+ " + tessSquared.y * gl_in[1].gl_Position.xyz\n"
+ " + tessSquared.z * gl_in[2].gl_Position.xyz\n"
+ " + gl_TessCoord.x * gl_TessCoord.y * projJI\n"
+ " + gl_TessCoord.y * gl_TessCoord.z * projKJ\n"
+ " + gl_TessCoord.z * gl_TessCoord.x * projIK;\n"
+ " // final position\n"
+ " vec3 finalPos = (1.0-tessBlend)*linearPos + tessBlend*phongPos;\n"
+ " gl_Position = mat_mvp * vec4(finalPos, 1.0);\n"
+ " normWorld = norm;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec3 normals;
+};
+
+NVRenderTestTessellation::NVRenderTestTessellation()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestTessellation::~NVRenderTestTessellation()
+{
+}
+
+bool NVRenderTestTessellation::isSupported(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+ NVRenderContextType nonSupportedFlags(
+ NVRenderContextValues::GL2 | NVRenderContextValues::GLES2 | NVRenderContextValues::GL3
+ | NVRenderContextValues::GLES3 | NVRenderContextValues::GLES3PLUS);
+
+ // This is currently only supported on >= GL4 && >= GLES 3.1
+ if ((ctxType & nonSupportedFlags))
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestTessellation::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ context->SetRenderTarget(NULL);
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= trianglePatches(context, pUserData);
+ _curTest++;
+ success &= phongPatches(context, pUserData);
+ _curTest++;
+
+ return success;
+}
+
+bool NVRenderTestTessellation::trianglePatches(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ std::string tcProg;
+ std::string teProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTessellation shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))),
+ toRef(tessControlShader(tcProg, isGLESContext(context))),
+ toRef(tessEvaluationShader(teProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 6 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestFboMsaa: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Patches, 3);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestFboMsaa: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+ // set tessellation values
+ float tessLevelInner = 4.0;
+ compResult.mShader->SetPropertyValue("tessLevelInner", tessLevelInner);
+ float tessLevelOuter = 4.0;
+ compResult.mShader->SetPropertyValue("tessLevelOuter", tessLevelOuter);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestTessellation::phongPatches(NVRenderContext *context, userContextData *pUserData)
+{
+ QT3DSVec3 n1(-1.0, 0.5, 1.0);
+ n1.normalize();
+ QT3DSVec3 n2(1.0, 0.5, 1.0);
+ n2.normalize();
+ QT3DSVec3 n3(0.0, 1.0, 1.0);
+ n3.normalize();
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0.0), n1 },
+ { QT3DSVec3(0.9, -0.9, 0.0), n2 },
+ { QT3DSVec3(0.0, 0.9, -0.0), n3 } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 p = QT3DSMat44::createIdentity();
+ QT3DSMat44 rotX = QT3DSMat44::createIdentity();
+ QT3DSMat44 rotY = QT3DSMat44::createIdentity();
+ QT3DSMat44 mv = QT3DSMat44::createIdentity();
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&p, -1, 1, -1, 1, -10, 10);
+ // NvRenderTestMatrixRotY( &rotY, 45.0 );
+ // NvRenderTestMatrixRotX( &rotX, 90.0 );
+ mv = rotY * rotX;
+ mvp = mv * p;
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ std::string tcProg;
+ std::string teProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTessellation shader", toRef(vertPhongShader(vtxProg, isGLESContext(context))),
+ toRef(fragPhongShader(frgProg, isGLESContext(context))),
+ toRef(tessPhongControlShader(tcProg, isGLESContext(context))),
+ toRef(tessPhongEvaluationShader(teProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_norm", NVRenderComponentTypes::QT3DSF32, 3, 12),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 6 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestFboMsaa: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Patches, 3);
+ if (!mInputAssembler) {
+ qCInfo(qt3ds::TRACE_INFO) << "NVRenderTestFboMsaa: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+ // set tessellation values
+ float tessLevels = 8.0;
+ compResult.mShader->SetPropertyValue("tessLevels", tessLevels);
+ float tessBlend = 1.0;
+ compResult.mShader->SetPropertyValue("tessBlend", tessBlend);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestTessellation::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestTessellation::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h
new file mode 100644
index 00000000..74036969
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_TESSELLATION_H
+#define QT3DS_RENDER_TEST_TESSELLATION_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestTessellation : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestTessellation();
+ ~NVRenderTestTessellation();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool trianglePatches(NVRenderContext *context, userContextData *pUserData);
+ bool phongPatches(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_TESSELLATION_H
diff --git a/tests/auto/runtime/images/NVRenderTestAttribBuffers.png b/tests/auto/runtime/images/NVRenderTestAttribBuffers.png
new file mode 100644
index 00000000..e0fe9463
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestAttribBuffers.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestBackendQuery.png b/tests/auto/runtime/images/NVRenderTestBackendQuery.png
new file mode 100644
index 00000000..76592360
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestBackendQuery.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestClear.png b/tests/auto/runtime/images/NVRenderTestClear.png
new file mode 100644
index 00000000..6e4c3191
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestClear.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestComputeShader.png b/tests/auto/runtime/images/NVRenderTestComputeShader.png
new file mode 100644
index 00000000..6f08814a
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestComputeShader.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.png b/tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.png
new file mode 100644
index 00000000..76592360
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestFboMsaa.png b/tests/auto/runtime/images/NVRenderTestFboMsaa.png
new file mode 100644
index 00000000..8eab95ce
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestFboMsaa.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestGeometryShader.png b/tests/auto/runtime/images/NVRenderTestGeometryShader.png
new file mode 100644
index 00000000..820534e0
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestGeometryShader.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestOcclusionQuery.png b/tests/auto/runtime/images/NVRenderTestOcclusionQuery.png
new file mode 100644
index 00000000..76592360
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestOcclusionQuery.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestProgramPipeline.png b/tests/auto/runtime/images/NVRenderTestProgramPipeline.png
new file mode 100644
index 00000000..f868b2d7
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestProgramPipeline.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestTexture2D.png b/tests/auto/runtime/images/NVRenderTestTexture2D.png
new file mode 100644
index 00000000..afde59f3
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestTexture2D.png
Binary files differ
diff --git a/tests/auto/runtime/runtime.pro b/tests/auto/runtime/runtime.pro
new file mode 100644
index 00000000..e604339c
--- /dev/null
+++ b/tests/auto/runtime/runtime.pro
@@ -0,0 +1,92 @@
+TEMPLATE = app
+CONFIG += testcase
+include($$PWD/../../../src/Runtime/commoninclude.pri)
+
+TARGET = tst_qt3dsruntime
+QT += testlib gui
+RESOURCES += \
+ runtime.qrc \
+ $$PWD/../../../src/Runtime/res.qrc \
+ $$PWD/../../../src/Runtime/testres.qrc \
+ $$PWD/../../../src/Runtime/platformres.qrc
+
+INCLUDEPATH += \
+ $$PWD/../../../src/Runtime/Source/UICRender/RendererImpl
+
+HEADERS += \
+ base/Qt3DSRenderTestAtomicCounterBuffer.h \
+ base/Qt3DSRenderTestAttribBuffers.h \
+ base/Qt3DSRenderTestBackendQuery.h \
+ base/Qt3DSRenderTestClear.h \
+ base/Qt3DSRenderTestConstantBuffer.h \
+ base/Qt3DSRenderTestDrawIndirectBuffer.h \
+ base/Qt3DSRenderTestPrimitives.h \
+ base/Qt3DSRenderTestProgramPipeline.h \
+ base/Qt3DSRenderTestTexture2D.h \
+ base/Qt3DSRenderTestTimerQuery.h \
+ compute/Qt3DSRenderTestComputeShader.h \
+ fbo/Qt3DSRenderTestFboMsaa.h \
+ geometry/Qt3DSRenderTestGeometryShader.h \
+ geometry/Qt3DSRenderTestOcclusionQuery.h \
+ geometry/Qt3DSRenderTestTessellation.h \
+ Qt3DSRenderTestBase.h \
+ Qt3DSRenderTestMathUtil.h \
+ tst_qt3dsruntime.h \
+ shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h \
+ shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h \
+ shadergenerator/Qt3DSRenderTestEffectGenerator.h
+
+SOURCES += \
+ base/Qt3DSRenderTestAtomicCounterBuffer.cpp \
+ base/Qt3DSRenderTestAttribBuffers.cpp \
+ base/Qt3DSRenderTestBackendQuery.cpp \
+ base/Qt3DSRenderTestClear.cpp \
+ base/Qt3DSRenderTestConstantBuffer.cpp \
+ base/Qt3DSRenderTestDrawIndirectBuffer.cpp \
+ base/Qt3DSRenderTestPrimitives.cpp \
+ base/Qt3DSRenderTestProgramPipeline.cpp \
+ base/Qt3DSRenderTestTexture2D.cpp \
+ base/Qt3DSRenderTestTimerQuery.cpp \
+ compute/Qt3DSRenderTestComputeShader.cpp \
+ fbo/Qt3DSRenderTestFboMsaa.cpp \
+ geometry/Qt3DSRenderTestGeometryShader.cpp \
+ geometry/Qt3DSRenderTestOcclusionQuery.cpp \
+ geometry/Qt3DSRenderTestTessellation.cpp \
+ Qt3DSRenderTestMathUtil.cpp \
+ tst_qt3dsruntime.cpp \
+ Qt3DSRenderTestBase.cpp \
+ shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp \
+ shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp \
+ shadergenerator/Qt3DSRenderTestEffectGenerator.cpp
+
+linux {
+ BEGIN_ARCHIVE = -Wl,--whole-archive
+ END_ARCHIVE = -Wl,--no-whole-archive
+}
+
+LIBS += \
+ $$BEGIN_ARCHIVE \
+ -lEASTL$$qtPlatformTargetSuffix() \
+ -lLua$$qtPlatformTargetSuffix() \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix() \
+ $$END_ARCHIVE \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+ANDROID_EXTRA_LIBS = \
+ libqt3dsqmlstreamer.so
+
+win32 {
+ LIBS += \
+ -lws2_32
+}
+
+linux {
+ LIBS += \
+ -ldl \
+ -lEGL
+}
+
+PREDEPS_LIBS = qt3dsruntimestatic
+
+include($$PWD/../../../src/utils.pri)
+PRE_TARGETDEPS += $$fixLibPredeps($$LIBDIR, PREDEPS_LIBS)
diff --git a/tests/auto/runtime/runtime.qrc b/tests/auto/runtime/runtime.qrc
new file mode 100644
index 00000000..f4318f5a
--- /dev/null
+++ b/tests/auto/runtime/runtime.qrc
@@ -0,0 +1,14 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/NVRenderTestTexture2D.png</file>
+ <file>images/NVRenderTestProgramPipeline.png</file>
+ <file>images/NVRenderTestAttribBuffers.png</file>
+ <file>images/NVRenderTestBackendQuery.png</file>
+ <file>images/NVRenderTestClear.png</file>
+ <file>images/NVRenderTestComputeShader.png</file>
+ <file>images/NVRenderTestDrawIndirectBuffer.png</file>
+ <file>images/NVRenderTestFboMsaa.png</file>
+ <file>images/NVRenderTestGeometryShader.png</file>
+ <file>images/NVRenderTestOcclusionQuery.png</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp
new file mode 100644
index 00000000..a76a2de8
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp
@@ -0,0 +1,468 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "Qt3DSRenderTestCustomMaterialGenerator.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderCustomMaterialRenderContext.h"
+#include "UICRenderCustomMaterialShaderGenerator.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "UICRenderContext.h"
+#include "UICTypes.h"
+#include "UICRenderRuntimeBinding.h"
+#include "UICApplication.h"
+#include "UICInputEngine.h"
+#include "foundation/FileTools.h"
+#include "UICWindowSystem.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCache.h"
+#include "UICRendererImpl.h"
+#include "UICRenderLight.h"
+#include "UICRenderUIPLoader.h"
+#include "UICDMMetaDataTypes.h"
+
+#include <QTime>
+#include <QString>
+#include <QTextStream>
+
+using namespace uic::render;
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+
+
+namespace qt3ds {
+namespace render {
+
+Qt3DSRenderTestCustomMaterialGenerator::Qt3DSRenderTestCustomMaterialGenerator()
+{
+
+}
+
+Qt3DSRenderTestCustomMaterialGenerator::~Qt3DSRenderTestCustomMaterialGenerator()
+{
+
+}
+
+
+bool Qt3DSRenderTestCustomMaterialGenerator::isSupported(NVRenderContext *context)
+{
+ Q_UNUSED(context);
+ return true;
+}
+
+bool Qt3DSRenderTestCustomMaterialGenerator::runPerformance(NVRenderContext *context,
+ userContextData *pContextData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pContextData);
+ return false;
+}
+
+void Qt3DSRenderTestCustomMaterialGenerator::cleanup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pUserData);
+}
+
+struct CustomTestParams
+{
+ SRenderableObjectFlags flags;
+ dynamic::SDynamicShaderProgramFlags dynamicFlags;
+ QT3DSF32 opacity;
+ SLayer layer;
+ SLayerRenderData layerData;
+ SRenderableImage *images;
+ SLight light[UIC_MAX_NUM_LIGHTS];
+ SModel model;
+ SRenderSubset subset;
+ SShaderDefaultMaterialKey shaderkey;
+ SCustomMaterial *material;
+ eastl::vector<SShaderPreprocessorFeature> features;
+ Option<UICDM::SMetaDataCustomMaterial> metaMaterial;
+ SImage dummyImages[SShaderDefaultMaterialKeyProperties::ImageMapCount];
+ eastl::vector<SRenderableImage*> renderableImages;
+ uic::render::CUICRendererImpl *render;
+ SImage iblLightProbe;
+ NVRenderTexture2D *texture;
+
+ CustomTestParams(CUICRendererImpl &impl)
+ : layerData(layer, impl)
+ , images(NULL)
+ , subset(impl.GetContext().GetAllocator())
+ , material(NULL)
+ , render(&impl)
+ , texture(NULL)
+ {
+ }
+ ~CustomTestParams()
+ {
+ if (texture)
+ texture->release();
+ }
+
+ void addRenderableImage(ImageMapTypes::Enum type,
+ SShaderDefaultMaterialKeyProperties::ImageMapNames name)
+ {
+ renderableImages.push_back(new SRenderableImage(type, dummyImages[name]));
+ render->DefaultMaterialShaderKeyProperties().m_ImageMaps[name].SetEnabled(shaderkey, true);
+ }
+ void prepare()
+ {
+ for (unsigned int i = 0; i < renderableImages.size(); i++) {
+ if (i == 0)
+ images = renderableImages[0];
+ else
+ renderableImages[i-1]->m_NextImage = renderableImages[i];
+ }
+ }
+};
+
+struct CustomTestKey
+{
+ unsigned int tessellation : 2;
+ unsigned int wireframe : 1;
+ unsigned int lighting: 1;
+ unsigned int indirectLightmap: 1;
+ unsigned int radiosityLightmap: 1;
+ unsigned int shadowLightmap: 1;
+ unsigned int transparency : 1;
+ unsigned int refraction : 1;
+ unsigned int iblprobe : 1;
+ unsigned int emissiveMap : 1;
+ unsigned int displacementMap : 1;
+ unsigned int diffuse = 1;
+ unsigned int specular = 1;
+ unsigned int glossy = 1;
+ unsigned int cutout = 1;
+ unsigned int transmissive : 1;
+ unsigned int ssao : 1;
+ unsigned int ssdo : 1;
+ unsigned int ssm : 1;
+
+ CustomTestKey(TessModeValues::Enum tess = TessModeValues::NoTess, bool wire = false,
+ bool lights = false, bool indirect = false, bool radiosity = false,
+ bool shadow = false, bool trans = false, bool refract = false, bool ibl = false,
+ bool emissive = false, bool disp = false, bool diff = false,
+ bool spec = false, bool glo = false, bool cut = false, bool transm = false,
+ bool ao = false, bool direct = false, bool shadowssm = false)
+ : tessellation(tess), wireframe(wire), lighting(lights), indirectLightmap(indirect)
+ , radiosityLightmap(radiosity), shadowLightmap(shadow), transparency(trans)
+ , refraction(refract), iblprobe(ibl), emissiveMap(emissive), displacementMap(disp)
+ , diffuse(diff), specular(spec), glossy(glo), cutout(cut), transmissive(transm)
+ , ssao(ao), ssdo(direct), ssm(shadowssm)
+ {
+
+ }
+
+ bool operator == (const CustomTestKey &other) const
+ {
+ uint64_t a = *(uint64_t *)this;
+ uint64_t b = *(uint64_t *)&other;
+ return a == b;
+ }
+
+ QString toString()
+ {
+ QString str;
+ QTextStream stream(&str);
+ stream << "Custom Key tessellation: " << int(tessellation);
+ stream << " wireframe: " << (wireframe ? "true" : "false");
+ stream << " lighting: " << (lighting ? "true" : "false");
+ stream << " indirectLightmap: " << (indirectLightmap ? "true" : "false");
+ stream << " radiosityLightmap: " << (radiosityLightmap ? "true" : "false");
+ stream << " shadowLightmap: " << (shadowLightmap ? "true" : "false");
+ stream << " transparency: " << (transparency ? "true" : "false");
+ stream << " refraction: " << (refraction ? "true" : "false");
+ stream << " iblprobe: " << (iblprobe ? "true" : "false");
+ stream << " emissiveMap: " << (emissiveMap ? "true" : "false");
+ stream << " displacementMap: " << (displacementMap ? "true" : "false");
+ stream << " diffuse: " << (diffuse ? "true" : "false");
+ stream << " specular: " << (specular ? "true" : "false");
+ stream << " glossy: " << (glossy ? "true" : "false");
+ stream << " cutout: " << (cutout ? "true" : "false");
+ stream << " transmissive: " << (transmissive ? "true" : "false");
+ stream << " ssao: " << (ssao ? "true" : "false");
+ stream << " ssdo: " << (ssdo ? "true" : "false");
+ stream << " ssm: " << (ssm ? "true" : "false");
+ return str;
+ }
+};
+
+#define MAX_TEST_KEY ((1llu<<20)-1)
+
+CustomTestKey randomizeTestKey()
+{
+ uint64_t v = (uint64_t(qrand()))%MAX_TEST_KEY;
+ return *reinterpret_cast<CustomTestKey*>(&v);
+}
+
+CustomTestParams *generateTest(uic::render::CUICRendererImpl *renderImpl,
+ NVRenderContext *context, CustomTestKey key, SCustomMaterial *material)
+{
+ CustomTestParams *params = new CustomTestParams(*renderImpl);
+ params->material = material;
+ params->material->m_ShaderKeyValues = (SCustomMaterialShaderKeyFlags)0;
+ params->material->m_Lightmaps = SLightmaps();
+ params->material->m_DisplacementMap = NULL;
+ params->material->m_EmissiveMap2 = NULL;
+ params->material->m_hasTransparency = false;
+ params->material->m_IblProbe = NULL;
+ params->material->m_hasRefraction = false;
+ switch (key.tessellation) {
+ case 1:
+ params->model.m_TessellationMode = TessModeValues::TessLinear;
+ break;
+ case 2:
+ params->model.m_TessellationMode = TessModeValues::TessPhong;
+ break;
+ case 3:
+ params->model.m_TessellationMode = TessModeValues::TessNPatch;
+ break;
+ default:
+ params->model.m_TessellationMode = TessModeValues::NoTess;
+ break;
+ }
+
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_TessellationMode.SetValue(params->shaderkey, params->model.m_TessellationMode);
+
+ if (key.wireframe && key.tessellation > 0) {
+ params->subset.m_WireframeMode = true;
+ renderImpl->DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
+ params->shaderkey, true);
+ }
+
+ CRegisteredString lighting =
+ renderImpl->GetContext().GetStringTable().RegisterStr("UIC_ENABLE_CG_LIGHTING");
+ params->features.push_back(SShaderPreprocessorFeature(lighting, key.lighting));
+
+ if (key.indirectLightmap) {
+ params->material->m_Lightmaps.m_LightmapIndirect
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapIndirect];
+ params->addRenderableImage(ImageMapTypes::LightmapIndirect,
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ }
+ if (key.radiosityLightmap) {
+ params->material->m_Lightmaps.m_LightmapRadiosity
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapRadiosity];
+ params->addRenderableImage(ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ }
+ if (key.shadowLightmap) {
+ params->material->m_Lightmaps.m_LightmapShadow
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapShadow];
+ params->addRenderableImage(ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapShadow);
+ }
+
+ if (key.diffuse)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::diffuse;
+
+ // TODO: emissive mask doesn't work
+// if (key.emissiveMap >= 1) {
+// params->material->m_EmissiveMap2
+// = &params->dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap];
+// params->addRenderableImage(ImageMapTypes::Emissive,
+// SShaderDefaultMaterialKeyProperties::EmissiveMap);
+// }
+
+ if (key.specular)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::specular;
+
+ if (key.displacementMap) {
+ params->material->m_DisplacementMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::DisplacementMap];
+ params->material->m_DisplacementMap->m_ImageShaderName
+ = renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("DisplacementMap");
+ params->material->m_DisplaceAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::Displacement,
+ SShaderDefaultMaterialKeyProperties::DisplacementMap);
+
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::displace;
+ }
+
+ if (key.iblprobe) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_HasIbl.SetValue(
+ params->shaderkey, true);
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_LIGHT_PROBE"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+
+ params->material->m_IblProbe = &params->iblLightProbe;
+ params->texture = context->CreateTexture2D();
+ NVRenderTextureFormats::Enum format = NVRenderTextureFormats::RGBA8;
+ unsigned int data = 0;
+ NVDataRef<QT3DSU8> buffer = toU8DataRef<unsigned int>(data);
+ params->texture->SetTextureData(buffer, 0, 1, 1, format);
+ params->iblLightProbe.m_TextureData.m_Texture = params->texture;
+ }
+
+ // these requires calculateGlass function in material
+// if (key.transparency) {
+// params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::transparent;
+// params->material->m_hasTransparency = true;
+// }
+// if (key.refraction) {
+// params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::refraction;
+// params->material->m_hasRefraction = true;
+// }
+ if (key.glossy)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::glossy;
+
+ if (key.cutout)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::cutout;
+
+ if (key.transmissive)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::transmissive;
+
+ if (key.ssm) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_SSM"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssao) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_SSAO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssdo) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_SSDO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+
+ params->prepare();
+ return params;
+}
+
+bool GenShader(IUICRenderContext &UICContext, CustomTestParams &params)
+{
+ bool success = true;
+ ICustomMaterialShaderGenerator &theMaterialGenerator(UICContext.GetCustomMaterialShaderGenerator());
+
+ SCustomMaterialVertexPipeline thePipeline(&UICContext,
+ params.model.m_TessellationMode);
+
+ for (int i = 0; i < params.metaMaterial->m_CustomMaterialCommands.size(); i++) {
+ dynamic::SCommand &command = *params.metaMaterial->m_CustomMaterialCommands[i];
+ if (command.m_Type == dynamic::CommandTypes::Enum::BindShader) {
+ dynamic::SBindShader *bindShader = static_cast<dynamic::SBindShader *>(&command);
+ NVRenderShaderProgram *theProgram = theMaterialGenerator.GenerateShader(
+ *params.material, params.shaderkey, thePipeline,
+ toConstDataRef(params.features.data(), (QT3DSU32)params.features.size()),
+ params.layerData.m_Lights, params.images,
+ (params.material->m_hasTransparency || params.material->m_hasRefraction),
+ "custom material pipeline-- ", bindShader->m_ShaderPath);
+ if (!theProgram) {
+ success = false;
+ break;
+ }
+ }
+ }
+
+ return success;
+}
+
+bool Qt3DSRenderTestCustomMaterialGenerator::run(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(pUserData);
+ bool success = true;
+
+ QVector<CustomTestKey> testKeys;
+ testKeys.push_back(CustomTestKey());
+ testKeys.push_back(CustomTestKey(TessModeValues::TessLinear));
+ testKeys.push_back(CustomTestKey(TessModeValues::TessNPatch));
+ testKeys.push_back(CustomTestKey(TessModeValues::TessPhong));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+
+ while (testKeys.size() < 100) {
+ CustomTestKey key = randomizeTestKey();
+ if (!testKeys.contains(key))
+ testKeys.push_back(key);
+ }
+
+ if (success) {
+ CRegisteredString name = context->GetStringTable().RegisterStr("qrc:/copper.material");
+
+ metadata()->LoadMaterialXMLFile("CustomMaterial", "", "copper", "qrc:/copper.material");
+ Option<UICDM::SMetaDataCustomMaterial> metaMaterial =
+ metadata()->GetMaterialMetaDataBySourcePath("qrc:/copper.material");
+
+ if (metaMaterial.hasValue()) {
+ uic::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ name, context->GetFoundation(),
+ uicRenderer()->GetUICContext().GetCustomMaterialSystem(), *metaMaterial,
+ context->GetStringTable());
+ SCustomMaterial *material = uicRenderer()->GetUICContext().GetCustomMaterialSystem()
+ .CreateCustomMaterial(name, uicRenderer()->GetContext().GetAllocator());
+
+ for (CustomTestKey key : testKeys) {
+ CustomTestParams *params = generateTest(uicRenderer(), context, key, material);
+ params->metaMaterial = metaMaterial;
+ success &= GenShader(uicRenderer()->GetUICContext(), *params);
+ if (!success)
+ qDebug () << "failing key: " << key.toString();
+ delete params;
+ }
+ delete material;
+ }
+ }
+
+ return success;
+}
+
+} // render
+} // qt3ds
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h
new file mode 100644
index 00000000..621d20f6
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_RENDER_TEST_CUSTOM_MATERIAL_GENERATOR_H
+#define QT3DS_RENDER_TEST_CUSTOM_MATERIAL_GENERATOR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+class Qt3DSRenderTestCustomMaterialGenerator : public NVRenderTestBase
+{
+public:
+ Qt3DSRenderTestCustomMaterialGenerator();
+ ~Qt3DSRenderTestCustomMaterialGenerator();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+private:
+
+};
+
+} // render
+} // qt3ds
+
+#endif
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp
new file mode 100644
index 00000000..6e9be253
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp
@@ -0,0 +1,576 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "Qt3DSRenderTestDefaultMaterialGenerator.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICTypes.h"
+#include "UICRenderRuntimeBinding.h"
+#include "UICApplication.h"
+#include "UICInputEngine.h"
+#include "foundation/FileTools.h"
+#include "UICWindowSystem.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCache.h"
+#include "UICRendererImpl.h"
+#include "UICRenderLight.h"
+
+#include <QTime>
+
+using namespace uic::render;
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+
+
+namespace qt3ds {
+namespace render {
+
+Qt3DSRenderTestDefaultMaterialGenerator::Qt3DSRenderTestDefaultMaterialGenerator()
+{
+
+}
+
+Qt3DSRenderTestDefaultMaterialGenerator::~Qt3DSRenderTestDefaultMaterialGenerator()
+{
+
+}
+
+
+bool Qt3DSRenderTestDefaultMaterialGenerator::isSupported(NVRenderContext *context)
+{
+ Q_UNUSED(context);
+ return true;
+}
+
+bool Qt3DSRenderTestDefaultMaterialGenerator::runPerformance(NVRenderContext *context,
+ userContextData *pContextData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pContextData);
+ return false;
+}
+
+void Qt3DSRenderTestDefaultMaterialGenerator::cleanup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pUserData);
+}
+
+
+#define MAX_TEST_KEY ((1llu<<32)-1)
+
+struct TestKey
+{
+ unsigned int tessellation: 2;
+ unsigned int wireframe: 1;
+ unsigned int lighting: 2;
+ unsigned int lights: 4;
+ unsigned int indirectLightmap: 1;
+ unsigned int radiosityLightmap: 1;
+ unsigned int lightProbe: 2;
+ unsigned int iblLightProbe: 1;
+ unsigned int iblfow: 1;
+ unsigned int diffuseMap: 2;
+ unsigned int emissiveMap: 2;
+ unsigned int specularModel: 2;
+ unsigned int specularMap: 1;
+ unsigned int specularReflection: 1;
+ unsigned int fresnel: 1;
+ unsigned int bumpmapping: 2;
+ unsigned int displacementMap: 1;
+ unsigned int opacityMap: 1;
+ unsigned int translucencyMap: 1;
+ unsigned int ssm: 1;
+ unsigned int ssdo: 1;
+ unsigned int ssao: 1;
+
+ TestKey(TessModeValues::Enum tess = TessModeValues::NoTess, bool wire = false,
+ DefaultMaterialLighting::Enum lmode = DefaultMaterialLighting::NoLighting,
+ int lightCount = 0, bool indirect = false, bool radio = false, int lprobe = 0,
+ bool iblProbe = false, bool iblf = false, int diffuse = 0, int emissive = 0,
+ DefaultMaterialSpecularModel::Enum sModel = DefaultMaterialSpecularModel::Default,
+ bool sMap = false, bool sRef = false, bool fre = false, int bump = 0,
+ bool disp = false, bool opac = false, bool trans = false, bool shadow = false,
+ bool ao = false, bool directOcc = false)
+ : tessellation(tess), wireframe(wire), lighting(lmode), lights(lightCount)
+ , indirectLightmap(indirect), radiosityLightmap(radio), lightProbe(lprobe)
+ , iblLightProbe(iblProbe), iblfow(iblf), diffuseMap(diffuse), emissiveMap(emissive)
+ , specularModel(sModel), specularMap(sMap), specularReflection(sRef)
+ , fresnel(fre), bumpmapping(bump), displacementMap(disp), opacityMap(opac)
+ , translucencyMap(trans), ssm(shadow), ssao(ao), ssdo(directOcc)
+ {
+
+ }
+
+ bool operator == (const TestKey &other) const
+ {
+ return toInt() == other.toInt();
+ }
+
+ QString toString()
+ {
+ QString str;
+ QTextStream stream(&str);
+
+ stream << " tessellation: " << tessellation;
+ stream << " wireframe: " << (wireframe ? "true" : "false");
+ stream << " lighting: " << lighting;
+ stream << " lights: " << lights;
+ stream << " indirectLightmap: " << (indirectLightmap ? "true" : "false");
+ stream << " radiosityLightmap: " << (radiosityLightmap ? "true" : "false");
+ stream << " lightProbe: " << lightProbe;
+ stream << " iblLightProbe: " << (iblLightProbe ? "true" : "false");
+ stream << " iblfow: " << (iblfow ? "true" : "false");
+ stream << " diffuseMap: " << diffuseMap;
+ stream << " emissiveMap: " << emissiveMap;
+ stream << " specularModel: " << specularModel;
+ stream << " specularMap: " << (specularMap ? "true" : "false");
+ stream << " specularReflection: " << (specularReflection ? "true" : "false");
+ stream << " fresnel: " << (fresnel ? "true" : "false");
+ stream << " bumpmapping: " << bumpmapping;
+ stream << " displacementMap: " << (displacementMap ? "true" : "false");
+ stream << " opacityMap: " << (opacityMap ? "true" : "false");
+ stream << " translucencyMap: " << (translucencyMap ? "true" : "false");
+ stream << " ssm: " << (ssm ? "true" : "false");
+ stream << " ssdo: " << (ssdo ? "true" : "false");
+ stream << " ssao: " << (ssao ? "true" : "false");
+
+ return str;
+ }
+
+ void clampValues()
+ {
+ lighting = qMin(lighting, 2u);
+ if (lighting == 1)
+ lighting = 2;
+ emissiveMap = qMin(emissiveMap, 2u);
+ specularModel = qMin(specularModel, 2u);
+ bumpmapping = qMin(bumpmapping, 2u);
+ lightProbe = 0;
+ if (!iblLightProbe)
+ iblfow = 0;
+ if (!tessellation)
+ wireframe = 0;
+ }
+
+ uint64_t toInt() const
+ {
+ return (*(uint64_t *)this)&MAX_TEST_KEY;
+ }
+};
+
+struct TestParams
+{
+ SRenderableObjectFlags flags;
+ NVConstDataRef<QT3DSMat44> boneGlobals;
+ SRenderSubset subset;
+ SDefaultMaterial material;
+ SModel model;
+ QT3DSMat44 viewProjection;
+ SModelContext modelContext;
+ SRenderableImage *images;
+ SShaderDefaultMaterialKey shaderkey;
+ SSubsetRenderable renderable;
+ eastl::vector<SShaderPreprocessorFeature> features;
+ SLight light[UIC_MAX_NUM_LIGHTS];
+ SLayer layer;
+ SLayerRenderData layerData;
+ SImage dummyImages[SShaderDefaultMaterialKeyProperties::ImageMapCount];
+ NVRenderTexture2D *textures[4];
+ eastl::vector<SRenderableImage*> renderableImages;
+ uic::render::CUICRendererImpl *render;
+
+ TestParams(NVRenderContext *context, uic::render::CUICRendererImpl *renderImpl)
+ : subset(context->GetAllocator())
+ , modelContext(model, viewProjection)
+ , images(NULL)
+ , renderable(flags, QT3DSVec3(), *renderImpl, subset, material, modelContext, 1.0f, images,
+ shaderkey, boneGlobals)
+ , layerData(layer, *renderImpl)
+ , render(renderImpl)
+ {
+ for (int i = 0; i < 4; ++i) {
+ textures[i] = context->CreateTexture2D();
+ NVRenderTextureFormats::Enum format = NVRenderTextureFormats::RGBA8;
+ unsigned int data = 0;
+ NVDataRef<QT3DSU8> buffer = toU8DataRef<unsigned int>(data);
+ textures[i]->SetTextureData(buffer, 0, 1, 1, format);
+ }
+ for (int i = 0; i < SShaderDefaultMaterialKeyProperties::ImageMapCount; ++i)
+ dummyImages[i].m_TextureData.m_Texture = textures[i%4];
+ dummyImages[SShaderDefaultMaterialKeyProperties::DiffuseMap1].m_TextureData.
+ m_TextureFlags.SetPreMultiplied(true);
+ dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap2].m_TextureData.
+ m_TextureFlags.SetInvertUVCoords(true);
+ }
+ ~TestParams()
+ {
+ for (NVRenderTexture2D *tex : textures)
+ tex->release();
+ for (SRenderableImage *img : renderableImages)
+ delete img;
+ }
+ void addRenderableImage(ImageMapTypes::Enum type,
+ SShaderDefaultMaterialKeyProperties::ImageMapNames name)
+ {
+ renderableImages.push_back(new SRenderableImage(type, dummyImages[name]));
+ render->DefaultMaterialShaderKeyProperties().m_ImageMaps[name].SetEnabled(shaderkey, true);
+ }
+ void prepare()
+ {
+ for (unsigned int i = 0; i < renderableImages.size(); i++) {
+ if (i == 0)
+ images = renderableImages[0];
+ else {
+ renderableImages[i-1]->m_NextImage = renderableImages[i];
+ }
+
+ }
+ renderable.m_ShaderDescription = shaderkey;
+ renderable.m_FirstImage = images;
+ }
+};
+
+TestKey randomizeTestKey()
+{
+ uint64_t v = (uint64_t(qrand()) << 32 | uint64_t(qrand()))&MAX_TEST_KEY;
+ TestKey key = *reinterpret_cast<TestKey*>(&v);
+ key.clampValues();
+ return key;
+}
+
+
+TestParams *generateTest(uic::render::CUICRendererImpl *renderImpl,
+ NVRenderContext *context, TestKey key)
+{
+ // TODO: light probes
+ TestParams *params = new TestParams(context, renderImpl);
+
+ switch (key.tessellation) {
+ case 1:
+ params->model.m_TessellationMode = TessModeValues::TessLinear;
+ break;
+ case 2:
+ params->model.m_TessellationMode = TessModeValues::TessPhong;
+ break;
+ case 3:
+ params->model.m_TessellationMode = TessModeValues::TessNPatch;
+ break;
+ default:
+ params->model.m_TessellationMode = TessModeValues::NoTess;
+ break;
+ }
+
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_TessellationMode.SetValue(params->shaderkey, params->model.m_TessellationMode);
+
+ switch (key.lighting) {
+ case 1:
+ params->material.m_Lighting = DefaultMaterialLighting::VertexLighting;
+ break;
+ case 2:
+ params->material.m_Lighting = DefaultMaterialLighting::FragmentLighting;
+ break;
+ default:
+ params->material.m_Lighting = DefaultMaterialLighting::NoLighting;
+ break;
+ }
+ if (key.lighting != 0) {
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_HasLighting.SetValue(params->shaderkey, true);
+ }
+
+ if (key.wireframe && key.tessellation > 0) {
+ params->subset.m_WireframeMode = true;
+ renderImpl->DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
+ params->shaderkey, true);
+ }
+ bool castShadow = false;
+ key.lights = qMin(int(key.lights), int(UIC_MAX_NUM_LIGHTS));
+ for (unsigned int i = 0; i < key.lights; ++i) {
+ params->light[i].m_LightType = static_cast<RenderLightTypes::Enum>((i%3)+1);
+ if (params->light[i].m_LightType != RenderLightTypes::Directional) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_LightFlags[i].SetValue(
+ params->shaderkey, true);
+ }
+ if (params->light[i].m_LightType == RenderLightTypes::Area) {
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_LightAreaFlags[i]
+ .SetValue(params->shaderkey, true);
+ }
+ if (params->light[i].m_LightType != RenderLightTypes::Point) {
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_LightShadowFlags[i]
+ .SetValue(params->shaderkey, castShadow);
+ castShadow = !castShadow;
+ }
+ params->layerData.m_Lights.push_back(&params->light[i]);
+ }
+
+ renderImpl->DefaultMaterialShaderKeyProperties().m_LightCount.SetValue(params->shaderkey,
+ key.lights);
+
+ // shadow lightmap is not used
+ if (key.indirectLightmap) {
+ params->material.m_Lightmaps.m_LightmapIndirect
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapIndirect];
+ params->addRenderableImage(ImageMapTypes::LightmapIndirect,
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ }
+ if (key.radiosityLightmap) {
+ params->material.m_Lightmaps.m_LightmapRadiosity
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapRadiosity];
+ params->addRenderableImage(ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ }
+
+ for (unsigned int i = 0; i < key.diffuseMap; ++i) {
+ params->material.m_DiffuseMaps[i]
+ = &params->dummyImages[static_cast<SShaderDefaultMaterialKeyProperties::ImageMapNames>
+ (SShaderDefaultMaterialKeyProperties::DiffuseMap0 + i)];
+ params->addRenderableImage(ImageMapTypes::Diffuse,
+ static_cast<SShaderDefaultMaterialKeyProperties::ImageMapNames>
+ (SShaderDefaultMaterialKeyProperties::DiffuseMap0 + i));
+ }
+
+ if (key.emissiveMap >= 1) {
+ params->material.m_EmissiveMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap];
+ params->addRenderableImage(ImageMapTypes::Emissive,
+ SShaderDefaultMaterialKeyProperties::EmissiveMap);
+ }
+ if (key.emissiveMap == 2) {
+ params->material.m_EmissiveMap2
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap2];
+ params->addRenderableImage(ImageMapTypes::Emissive,
+ SShaderDefaultMaterialKeyProperties::EmissiveMap2);
+ }
+
+ switch (key.specularModel) {
+ case 1:
+ params->material.m_SpecularModel = DefaultMaterialSpecularModel::KGGX;
+ break;
+ case 2:
+ params->material.m_SpecularModel = DefaultMaterialSpecularModel::KWard;
+ break;
+ default:
+ params->material.m_SpecularModel = DefaultMaterialSpecularModel::Default;
+ break;
+ }
+
+ if (key.specularMap) {
+ params->material.m_SpecularMap =
+ &params->dummyImages[SShaderDefaultMaterialKeyProperties::SpecularAmountMap];
+ params->material.m_SpecularAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::SpecularAmountMap,
+ SShaderDefaultMaterialKeyProperties::SpecularAmountMap);
+ }
+ if (key.specularReflection) {
+ params->dummyImages[SShaderDefaultMaterialKeyProperties::SpecularMap].m_MappingMode
+ = ImageMappingModes::Environment;
+ params->material.m_SpecularAmount = 1.0f;
+ params->material.m_SpecularReflection
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::SpecularMap];
+ params->addRenderableImage(ImageMapTypes::Specular,
+ SShaderDefaultMaterialKeyProperties::SpecularMap);
+ }
+ if (key.fresnel)
+ params->material.m_FresnelPower = 1.0f;
+
+ if (key.bumpmapping == 1) {
+ params->material.m_BumpMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::BumpMap];
+ params->material.m_BumpAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::Bump, SShaderDefaultMaterialKeyProperties::BumpMap);
+ }
+ if (key.bumpmapping == 2) {
+ params->material.m_NormalMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::NormalMap];
+ params->addRenderableImage(ImageMapTypes::Normal, SShaderDefaultMaterialKeyProperties::NormalMap);
+ }
+
+ if (key.displacementMap) {
+ params->material.m_DisplacementMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::DisplacementMap];
+ params->material.m_DisplaceAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::Displacement,
+ SShaderDefaultMaterialKeyProperties::DisplacementMap);
+ }
+
+ if (key.opacityMap) {
+ params->material.m_OpacityMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::OpacityMap];
+ params->material.m_Opacity = 0.5f;
+ params->addRenderableImage(ImageMapTypes::Opacity,
+ SShaderDefaultMaterialKeyProperties::OpacityMap);
+ }
+
+ if (key.translucencyMap) {
+ params->material.m_TranslucencyMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::TranslucencyMap];
+ params->material.m_TranslucentFalloff = 0.1f;
+ params->addRenderableImage(ImageMapTypes::Translucency,
+ SShaderDefaultMaterialKeyProperties::TranslucencyMap);
+ }
+
+ if (key.ssm) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_SSM"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssao) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_SSAO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssdo) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_SSDO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+
+ if (key.iblLightProbe) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_HasIbl.SetValue(
+ params->shaderkey, true);
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_LIGHT_PROBE"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ if (key.iblfow) {
+ CRegisteredString str(renderImpl->GetUICContext().GetStringTable()
+ .RegisterStr("UIC_ENABLE_IBL_FOV"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ }
+
+ if (params->material.IsSpecularEnabled()) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_SpecularEnabled.SetValue(
+ params->shaderkey, true);
+ renderImpl->DefaultMaterialShaderKeyProperties().m_SpecularModel.SetSpecularModel(
+ params->shaderkey, params->material.m_SpecularModel);
+ }
+ if (params->material.IsFresnelEnabled()) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_FresnelEnabled.SetValue(
+ params->shaderkey, true);
+ }
+
+ params->prepare();
+ return params;
+}
+
+
+
+bool Qt3DSRenderTestDefaultMaterialGenerator::run(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(pUserData);
+ bool success = true;
+
+ qsrand(QTime::currentTime().msec());
+
+ QVector<TestKey> testKeys;
+
+ testKeys.push_back(TestKey());
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessLinear, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessNPatch, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessPhong, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessLinear, true, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 6));
+ // vertex lighting is not supported?
+ //testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::VertexLighting, 6));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 1, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 1, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 2));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 3, true, true, 0, false, false, 3));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 3, true, true, 0, false, false, 1, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 4, true, true, 0, false, false, 1, 2));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 4, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::KGGX, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 5, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::KWard, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 5, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 6, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 6, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 2));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true, false, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true, true, false, true));
+
+ while (testKeys.size() < 100) {
+ TestKey key = randomizeTestKey();
+ if (!testKeys.contains(key))
+ testKeys.push_back(key);
+ }
+ // generated programs must be unique
+ QVector<NVRenderShaderProgram *> programs;
+ success = initializeUICRenderer(context->format());
+ if (success) {
+ for (TestKey key : testKeys) {
+ qDebug () << "testing key: " << key.toInt();
+ TestParams *params = generateTest(uicRenderer(), context, key);
+
+ uicRenderer()->BeginLayerRender(params->layerData);
+ NVRenderShaderProgram *program
+ = uicRenderer()->GenerateShader(params->renderable,
+ toConstDataRef(params->features.data(),
+ (QT3DSU32)params->features.size()));
+ if (!program) {
+ success = false;
+ } else {
+ if (programs.contains(program)) {
+ qDebug () << "Generated program is not unique vs " << testKeys[programs.indexOf(program)].toString();
+ success = false;
+ }
+ else {
+ programs.push_back(program);
+ }
+ }
+
+ if (!success)
+ qDebug () << "failing test key: " << key.toString();
+
+ uicRenderer()->EndLayerRender();
+ delete params;
+ }
+ }
+
+ return success;
+}
+
+} // render
+} // qt3ds
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h
new file mode 100644
index 00000000..c1464a30
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_RENDER_TEST_DEFAULT_MATERIAL_GENERATOR_H
+#define QT3DS_RENDER_TEST_DEFAULT_MATERIAL_GENERATOR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+
+namespace qt3ds {
+namespace render {
+
+class Qt3DSRenderTestDefaultMaterialGenerator : public NVRenderTestBase
+{
+public:
+ Qt3DSRenderTestDefaultMaterialGenerator();
+ ~Qt3DSRenderTestDefaultMaterialGenerator();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+private:
+
+};
+
+} // render
+} // qt3ds
+
+#endif
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp
new file mode 100644
index 00000000..f779845c
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "Qt3DSRenderTestEffectGenerator.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "UICRenderCustomMaterialSystem.h"
+#include "UICRenderCustomMaterialRenderContext.h"
+#include "UICRenderCustomMaterialShaderGenerator.h"
+#include "UICRenderDynamicObjectSystem.h"
+#include "UICRenderDynamicObjectSystemCommands.h"
+#include "UICRenderContext.h"
+#include "UICTypes.h"
+#include "UICRenderRuntimeBinding.h"
+#include "UICApplication.h"
+#include "UICInputEngine.h"
+#include "foundation/FileTools.h"
+#include "UICWindowSystem.h"
+#include "UICRenderContext.h"
+#include "UICRenderShaderCache.h"
+#include "UICRendererImpl.h"
+#include "UICRenderLight.h"
+#include "UICRenderUIPLoader.h"
+#include "UICDMMetaDataTypes.h"
+
+#include <QTime>
+#include <QString>
+#include <QStringList>
+
+#include <string>
+
+using namespace uic::render;
+
+namespace qt3ds {
+namespace render {
+
+Qt3DSRenderTestEffectGenerator::Qt3DSRenderTestEffectGenerator()
+{
+
+}
+
+Qt3DSRenderTestEffectGenerator::~Qt3DSRenderTestEffectGenerator()
+{
+
+}
+
+bool Qt3DSRenderTestEffectGenerator::isSupported(NVRenderContext *context)
+{
+ Q_UNUSED(context);
+ return true;
+}
+
+bool Qt3DSRenderTestEffectGenerator::runPerformance(NVRenderContext *context,
+ userContextData *pContextData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pContextData);
+ return false;
+}
+
+void Qt3DSRenderTestEffectGenerator::cleanup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pUserData);
+}
+
+bool GenShader(IUICRenderContext &UICContext, SEffect &effect, UICDM::SMetaDataEffect *metaEffect)
+{
+ bool success = true;
+ for (int i = 0; i < metaEffect->m_EffectCommands.size(); i++) {
+ dynamic::SCommand &command = *metaEffect->m_EffectCommands[i];
+ if (command.m_Type == dynamic::CommandTypes::Enum::BindShader) {
+ dynamic::SBindShader *bindShader = static_cast<dynamic::SBindShader *>(&command);
+ NVRenderShaderProgram *theProgram =
+ UICContext.GetDynamicObjectSystem()
+ .GetShaderProgram(bindShader->m_ShaderPath, bindShader->m_ShaderDefine,
+ TShaderFeatureSet(), dynamic::SDynamicShaderProgramFlags())
+ .first;
+ if (!theProgram)
+ success = false;
+ }
+ }
+ return success;
+}
+
+bool Qt3DSRenderTestEffectGenerator::run(NVRenderContext *context, userContextData *pUserData)
+{
+ Q_UNUSED(pUserData);
+ bool success = true;
+
+ QStringList effectFiles;
+ effectFiles.append("Desaturate.effect");
+ effectFiles.append("Gaussian Blur.effect");
+ effectFiles.append("Sepia.effect");
+ effectFiles.append("Bloom.effect");
+
+ for (QString effectName : effectFiles) {
+ QString qfile = "qrc:/";
+ qfile.append(effectName);
+ QByteArray data = qfile.toLatin1();
+ const char *cname = data.data();
+ CRegisteredString name = context->GetStringTable().RegisterStr(cname);
+
+ metadata()->LoadEffectXMLFile("Effect", "", effectName.toLatin1().data(), cname);
+ Option<UICDM::SMetaDataEffect> metaEffect =
+ metadata()->GetEffectMetaDataBySourcePath(cname);
+
+ if (metaEffect.hasValue()) {
+ uic::render::IUIPLoader::CreateEffectClassFromMetaEffect(
+ name, context->GetFoundation(),
+ uicRenderer()->GetUICContext().GetEffectSystem(), *metaEffect,
+ context->GetStringTable());
+
+ SEffect *effect = uicRenderer()->GetUICContext().GetEffectSystem()
+ .CreateEffectInstance(name, uicRenderer()->GetContext().GetAllocator());
+
+ success &= GenShader(uicRenderer()->GetUICContext(), *effect, &metaEffect.getValue());
+ if (!success)
+ qDebug () << "failed effect: " << effectName;
+ delete effect;
+ }
+ }
+
+ return success;
+}
+
+} // render
+} // qt3ds
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h
new file mode 100644
index 00000000..4e26cf3c
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_RENDER_TEST_EFFECT_GENERATOR_H
+#define QT3DS_RENDER_TEST_EFFECT_GENERATOR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+class Qt3DSRenderTestEffectGenerator : public NVRenderTestBase
+{
+public:
+ Qt3DSRenderTestEffectGenerator();
+ ~Qt3DSRenderTestEffectGenerator();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+private:
+
+};
+
+} // render
+} // qt3ds
+
+#endif
diff --git a/tests/auto/runtime/tst_qt3dsruntime.cpp b/tests/auto/runtime/tst_qt3dsruntime.cpp
new file mode 100644
index 00000000..f272d7ea
--- /dev/null
+++ b/tests/auto/runtime/tst_qt3dsruntime.cpp
@@ -0,0 +1,685 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "tst_qt3dsruntime.h"
+
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSMat44.h"
+
+#include "base/Qt3DSRenderTestClear.h"
+#include "base/Qt3DSRenderTestPrimitives.h"
+#include "base/Qt3DSRenderTestConstantBuffer.h"
+#include "base/Qt3DSRenderTestBackendQuery.h"
+#include "base/Qt3DSRenderTestTimerQuery.h"
+#include "base/Qt3DSRenderTestTexture2D.h"
+#include "base/Qt3DSRenderTestAtomicCounterBuffer.h"
+#include "base/Qt3DSRenderTestDrawIndirectBuffer.h"
+#include "base/Qt3DSRenderTestAttribBuffers.h"
+#include "base/Qt3DSRenderTestProgramPipeline.h"
+#include "fbo/Qt3DSRenderTestFboMsaa.h"
+#include "geometry/Qt3DSRenderTestTessellation.h"
+#include "geometry/Qt3DSRenderTestGeometryShader.h"
+#include "geometry/Qt3DSRenderTestOcclusionQuery.h"
+#include "compute/Qt3DSRenderTestComputeShader.h"
+#include "shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h"
+#include "shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h"
+#include "shadergenerator/Qt3DSRenderTestEffectGenerator.h"
+
+#include <QImage>
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLFramebufferObjectFormat>
+
+using namespace std;
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+
+extern "C" {
+bool InitializeGL();
+}
+
+// Enable this to dump the test output into a log.txt file
+//#define DUMP_LOGFILE
+
+#ifndef EA_PLATFORM_WINDOWS
+
+#ifndef EASTL_DEBUG_BREAK
+void EASTL_DEBUG_BREAK()
+{
+ return;
+}
+#endif
+
+// Boost insists this be defined
+namespace boost {
+void throw_exception(std::exception const & e) {}
+}
+
+namespace qt3ds {
+void NVAssert(const char *exp, const char *file, int line, bool *ignore)
+{
+ *ignore = true;
+ QString message = QString("failed: %1, file %2, line %3\n")
+ .arg(exp).arg(file).arg(line);
+ QFAIL(message.toLatin1().constData());
+}
+}
+#endif
+
+void messageOutput(QtMsgType type, const QMessageLogContext &context,
+ const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg: {
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+ QTextStream stream(&file);
+ stream << msg;
+ }
+ file.close();
+#endif
+ } break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_qt3dsruntime::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
+ QTextStream stream(&file);
+ stream << "Log file: " << QTime::currentTime().toString() << "\n";
+ }
+ file.close();
+#endif
+}
+
+QSurfaceFormat makeFormat(int major, int minor, bool gles = false, bool coreProfile = true)
+{
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(major, minor);
+ if (coreProfile)
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ else
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ if (gles)
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ return format;
+}
+
+bool tst_qt3dsruntime::init(QSurfaceFormat format)
+{
+ m_glContext = new QT_PREPEND_NAMESPACE(QOpenGLContext)(this);
+ m_glContext->setFormat(format);
+ bool success = m_glContext->create();
+ if (!success)
+ return false;
+
+ m_glSurface = new QOffscreenSurface;
+ m_glSurface->setFormat(format);
+ m_glSurface->create();
+ m_glContext->makeCurrent(m_glSurface);
+
+ m_allocator = new CAllocator;
+ m_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *m_allocator);
+ m_stringTable = &IStringTable::CreateStringTable(*m_allocator);
+ m_renderContext = &NVRenderContext::CreateGL(*m_foundation, *m_stringTable, format);
+ return true;
+}
+
+bool tst_qt3dsruntime::init()
+{
+#if defined(Q_OS_ANDROID)
+ return init(makeFormat(3, 2, true, false));
+#else
+ return init(makeFormat(4, 3));
+#endif
+}
+
+bool tst_qt3dsruntime::executeTest(NVRenderTestBase *curTest,
+ const QString &testName,
+ bool performPixelTest)
+{
+ bool success = true;
+ int width = 640;
+ int height = 480;
+ userContextData userData = { (unsigned int)width, (unsigned int)height };
+
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(QSize(width, height), fboFormat);
+
+ m_renderContext->SetDefaultRenderTarget(fbo->handle());
+ m_renderContext->SetDefaultDepthBufferBitCount(m_glContext->format().depthBufferSize());
+ m_renderContext->SetViewport(NVRenderRect(0, 0, userData.winWidth, userData.winHeight));
+
+ success = curTest->run(m_renderContext, &userData);
+
+ if (performPixelTest) {
+ QImage image = fbo->toImage();
+ QImage refImage(QString(":/images/%1.png").arg(testName));
+ refImage = refImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ if (!refImage.isNull()) {
+ bool pixelTest = image == refImage;
+ success &= pixelTest;
+ if (!pixelTest)
+ image.save(QString("%1_failed.png").arg(testName));
+ }
+ }
+
+ curTest->cleanup(m_renderContext, &userData);
+
+ return success;
+}
+
+void tst_qt3dsruntime::testNVRenderTestClear()
+{
+ init();
+ NVRenderTestClear *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestClear);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestClear");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestPrimitives()
+{
+ init();
+ NVRenderTestPrimitives *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestPrimitives);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestPrimitives");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestConstantBuffer()
+{
+ init();
+ NVRenderTestConstantBuffer *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestConstantBuffer);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestConstantBuffer");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestBackendQuery()
+{
+ init();
+ NVRenderTestBackendQuery *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestBackendQuery);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestBackendQuery", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestTimerQuery()
+{
+ init();
+ NVRenderTestTimerQuery *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestTimerQuery);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestTimerQuery");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestFboMsaa()
+{
+ init();
+ NVRenderTestFboMsaa *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestFboMsaa);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestFboMsaa", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestTessellation()
+{
+ init();
+ NVRenderTestTessellation *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestTessellation);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestTessellation");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestGeometryShader()
+{
+ init();
+ NVRenderTestGeometryShader *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestGeometryShader);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestGeometryShader");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestComputeShader()
+{
+ init();
+ NVRenderTestComputeShader *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestComputeShader);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestComputeShader", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestOcclusionQuery()
+{
+ init();
+ NVRenderTestOcclusionQuery *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestOcclusionQuery);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestOcclusionQuery", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestTexture2D()
+{
+ init();
+ NVRenderTestTexture2D *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestTexture2D);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestTexture2D", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestAtomicCounterBuffer()
+{
+ init();
+ NVRenderTestAtomicCounterBuffer *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestAtomicCounterBuffer);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestAtomicCounterBuffer");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestDrawIndirectBuffer()
+{
+ init();
+ NVRenderTestDrawIndirectBuffer *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestDrawIndirectBuffer);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestDrawIndirectBuffer", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestAttribBuffers()
+{
+ init();
+ NVRenderTestAttribBuffers *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestAttribBuffers);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestAttribBuffers", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestProgramPipeline()
+{
+ init();
+ NVRenderTestProgramPipeline *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestProgramPipeline);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestProgramPipeline", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+#if !defined(Q_OS_ANDROID)
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_300()
+{
+ QSKIP("OpenGL 3.0 is not supported");
+ if (init(makeFormat(3, 0))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_310()
+{
+ if (init(makeFormat(3, 1))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_320()
+{
+ if (init(makeFormat(3, 2))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_330()
+{
+ if (init(makeFormat(3, 3))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_400()
+{
+ if (init(makeFormat(4, 0))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_410()
+{
+ if (init(makeFormat(4, 1))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_420()
+{
+ if (init(makeFormat(4, 2))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_430()
+{
+ if (init(makeFormat(4, 3))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_300()
+{
+ QSKIP("OpenGL 3.0 is not supported");
+ runCustomShaderGeneratorTest(makeFormat(3, 0));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_310()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 1));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_320()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 2));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_330()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 3));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_400()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 0));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_410()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 1));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_420()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 2));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_430()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 3));
+}
+
+#else
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_320es()
+{
+ if (init(makeFormat(3, 2, true, false))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_320es()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 2, true, false));
+}
+
+#endif
+
+void tst_qt3dsruntime::runDefaultShaderGeneratorTest()
+{
+ Qt3DSRenderTestDefaultMaterialGenerator *test =
+ QT3DS_NEW(m_foundation->getAllocator(), Qt3DSRenderTestDefaultMaterialGenerator);
+ if (!test->isSupported(m_renderContext))
+ QSKIP("not supported");
+ bool success = executeTest(test, "Qt3DSRenderTestDefaultMaterialGenerator");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+}
+
+void tst_qt3dsruntime::runCustomShaderGeneratorTest(QSurfaceFormat format)
+{
+ m_glContext = new QT_PREPEND_NAMESPACE(QOpenGLContext)(this);
+ m_glContext->setFormat(format);
+ bool success = m_glContext->create();
+ if (!success)
+ return;
+
+ m_glSurface = new QOffscreenSurface;
+ m_glSurface->setFormat(format);
+ m_glSurface->create();
+ m_glContext->makeCurrent(m_glSurface);
+
+ m_allocator = new CAllocator;
+ m_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *m_allocator);
+
+ Qt3DSRenderTestCustomMaterialGenerator *test =
+ QT3DS_NEW(m_foundation->getAllocator(), Qt3DSRenderTestCustomMaterialGenerator);
+
+ test->initializeUICRenderer(format);
+ m_renderContext = &NVRenderContext::CreateGL(*m_foundation, test->uicRenderer()->GetContext()
+ .GetStringTable(), format);
+
+ if (!test->isSupported(m_renderContext))
+ QSKIP("not supported");
+ success = executeTest(test, "Qt3DSRenderTestCusromMaterialGenerator");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testRenderEffectGenerator()
+{
+ QSurfaceFormat format = makeFormat(4, 3);
+ m_glContext = new QT_PREPEND_NAMESPACE(QOpenGLContext)(this);
+ m_glContext->setFormat(format);
+ bool success = m_glContext->create();
+ if (!success)
+ return;
+
+ m_glSurface = new QOffscreenSurface;
+ m_glSurface->setFormat(format);
+ m_glSurface->create();
+ m_glContext->makeCurrent(m_glSurface);
+
+ m_allocator = new CAllocator;
+ m_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *m_allocator);
+
+ Qt3DSRenderTestEffectGenerator *test =
+ QT3DS_NEW(m_foundation->getAllocator(), Qt3DSRenderTestEffectGenerator);
+
+ test->initializeUICRenderer(format);
+ m_renderContext = &NVRenderContext::CreateGL(*m_foundation, test->uicRenderer()->GetContext()
+ .GetStringTable(), format);
+
+ if (!test->isSupported(m_renderContext))
+ QSKIP("not supported");
+ success = executeTest(test, "Qt3DSRenderTestEffectGenerator");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::cleanup()
+{
+ if (m_renderContext)
+ m_renderContext->release();
+ if (m_foundation)
+ m_foundation->release();
+
+ m_renderContext = 0;
+ m_stringTable = 0;
+ m_foundation = 0;
+
+ delete m_allocator;
+ m_allocator = 0;
+
+ m_glSurface->destroy();
+ delete m_glSurface;
+ m_glSurface = 0;
+
+ delete m_glContext;
+ m_glContext = 0;
+}
+
+QTEST_MAIN(tst_qt3dsruntime)
diff --git a/tests/auto/runtime/tst_qt3dsruntime.h b/tests/auto/runtime/tst_qt3dsruntime.h
new file mode 100644
index 00000000..a6370d75
--- /dev/null
+++ b/tests/auto/runtime/tst_qt3dsruntime.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QT3DSRUNTIME
+#define TST_QT3DSRUNTIME
+
+#include <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+
+namespace qt3ds {
+class NVFoundation;
+namespace foundation {
+class CAllocator;
+class IStringTable;
+}
+namespace render {
+class NVRenderContext;
+class NVRenderTestBase;
+}
+}
+
+QT_BEGIN_NAMESPACE
+class QOpenGLContext;
+class QOffscreenSurface;
+QT_END_NAMESPACE
+
+class tst_qt3dsruntime : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qt3dsruntime()
+ : m_allocator(0)
+ , m_foundation(0)
+ , m_stringTable(0)
+ , m_renderContext(0)
+ , m_glContext(0)
+ , m_glSurface(0)
+ {
+ }
+
+private Q_SLOTS:
+ void initTestCase();
+
+ void testNVRenderTestClear();
+ void testNVRenderTestPrimitives();
+ void testNVRenderTestConstantBuffer();
+ void testNVRenderTestBackendQuery();
+ void testNVRenderTestTimerQuery();
+ void testNVRenderTestFboMsaa();
+ void testNVRenderTestTessellation();
+ void testNVRenderTestGeometryShader();
+ void testNVRenderTestComputeShader();
+ void testNVRenderTestOcclusionQuery();
+ void testNVRenderTestTexture2D();
+ void testNVRenderTestAtomicCounterBuffer();
+ void testNVRenderTestDrawIndirectBuffer();
+ void testNVRenderTestAttribBuffers();
+ void testNVRenderTestProgramPipeline();
+
+ void testRenderEffectGenerator();
+
+#if !defined(Q_OS_ANDROID)
+ void testRenderDefaultShaderGenerator_300();
+ void testRenderDefaultShaderGenerator_310();
+ void testRenderDefaultShaderGenerator_320();
+ void testRenderDefaultShaderGenerator_330();
+ void testRenderDefaultShaderGenerator_400();
+ void testRenderDefaultShaderGenerator_410();
+ void testRenderDefaultShaderGenerator_420();
+ void testRenderDefaultShaderGenerator_430();
+
+ void testRenderCustomShaderGenerator_300();
+ void testRenderCustomShaderGenerator_310();
+ void testRenderCustomShaderGenerator_320();
+ void testRenderCustomShaderGenerator_330();
+ void testRenderCustomShaderGenerator_400();
+ void testRenderCustomShaderGenerator_410();
+ void testRenderCustomShaderGenerator_420();
+ void testRenderCustomShaderGenerator_430();
+#else
+ void testRenderDefaultShaderGenerator_320es();
+ void testRenderCustomShaderGenerator_320es();
+#endif
+
+
+
+private:
+ bool executeTest(qt3ds::render::NVRenderTestBase *curTest,
+ const QString &testName, bool peformPixelTest = true);
+ bool init(QSurfaceFormat format);
+ bool init();
+ void runDefaultShaderGeneratorTest();
+ void runCustomShaderGeneratorTest(QSurfaceFormat format);
+ void cleanup();
+
+ qt3ds::foundation::CAllocator *m_allocator;
+ qt3ds::NVFoundation *m_foundation;
+ qt3ds::foundation::IStringTable *m_stringTable;
+ qt3ds::render::NVRenderContext *m_renderContext;
+ QOpenGLContext *m_glContext;
+ QOffscreenSurface *m_glSurface;
+};
+
+#endif // TST_QT3DSRUNTIME
diff --git a/tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro b/tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro
new file mode 100644
index 00000000..7da6bf77
--- /dev/null
+++ b/tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+CONFIG += testcase
+
+TARGET = tst_q3dssurfaceviewer
+
+QT += testlib studio3d
+
+SOURCES += tst_q3dssurfaceviewer.cpp
+
+RESOURCES += ../shared/shared_presentations.qrc
diff --git a/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp b/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
new file mode 100644
index 00000000..ef3cb942
--- /dev/null
+++ b/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
@@ -0,0 +1,1478 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtStudio3D/q3dssurfaceviewer.h>
+#include <QtStudio3D/q3dsviewersettings.h>
+#include <QtStudio3D/q3dspresentation.h>
+#include <QtStudio3D/q3dssceneelement.h>
+#include <QtStudio3D/q3dselement.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qoffscreensurface.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qopenglframebufferobject.h>
+#include <QtGui/qevent.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qfile.h>
+#include "../shared/shared_presentations.h"
+
+class tst_Q3DSSurfaceViewer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_Q3DSSurfaceViewer();
+ ~tst_Q3DSSurfaceViewer() {}
+
+private slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+
+ void testBasics_data();
+ void testBasics();
+ void testSourceChange_data();
+ void testSourceChange();
+ void testSizeChange_data();
+ void testSizeChange();
+ void testUpdateInterval_data();
+ void testUpdateInterval();
+ void testMultiple_data();
+ void testMultiple();
+ void testGrab_data();
+ void testGrab();
+ void testReset_data();
+ void testReset();
+ void testSettings_data();
+ void testSettings();
+ void testPresentation_data();
+ void testPresentation();
+ void testPresentationActivation_data();
+ void testPresentationActivation();
+ void testSceneElement_data();
+ void testSceneElement();
+ void testElement_data();
+ void testElement();
+ void testMouseInput_data();
+ void testMouseInput();
+
+private:
+ QWindow *createWindow(const QSize &size);
+ QOffscreenSurface *createOffscreen();
+ QOpenGLFramebufferObject *createFbo(const QSize &size);
+
+ // Created viewers are returned via *&viewer parameter rather than return value, so that we can
+ // use QCOMPARE and QVERIFY inside these functions (they require void return value).
+ void createViewer(Q3DSSurfaceViewer *&viewer, QSurface *surface, const QUrl &url,
+ bool autoSize, const QSize &size, int updateInterval, int fboId);
+ void createWindowAndViewer(Q3DSSurfaceViewer *&viewer, const QUrl &url = RED,
+ bool autoSize = true, const QSize &size = QSize(),
+ int updateInterval = 0);
+ void createOffscreenAndViewer(Q3DSSurfaceViewer *&viewer, const QUrl &url = RED,
+ const QSize &size = QSize(), int updateInterval = 0);
+ void checkPixel(Q3DSSurfaceViewer *viewer, const QColor &color,
+ const QPoint &pixel = QPoint(50, 50));
+
+ QWindow *m_window;
+ QOffscreenSurface *m_surface;
+ Q3DSSurfaceViewer *m_viewer;
+ QSurfaceFormat m_format;
+ QOpenGLContext *m_context;
+ QOpenGLFramebufferObject *m_fbo;
+};
+
+tst_Q3DSSurfaceViewer::tst_Q3DSSurfaceViewer()
+ : m_window(nullptr)
+ , m_surface(nullptr)
+ , m_viewer(nullptr)
+ , m_context(nullptr)
+ , m_fbo(nullptr)
+{
+}
+
+//#define DUMP_LOGFILE // Uncomment log Qt 3D Studio internal messages to log.txt file
+void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ // case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg: {
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+ QTextStream stream(&file);
+ stream << msg << "\n";
+ }
+ file.close();
+#endif
+ } break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_Q3DSSurfaceViewer::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
+ QTextStream stream(&file);
+ stream << "Log file: " << QTime::currentTime().toString() << "\n";
+ }
+ file.close();
+#endif
+
+ QWindow *dummy = createWindow(QSize(100, 100));
+ m_format = dummy->format();
+ qDebug() << m_format;
+ delete dummy;
+}
+
+void tst_Q3DSSurfaceViewer::init()
+{
+ m_context = new QOpenGLContext();
+ m_context->setFormat(m_format);
+ m_context->create();
+}
+
+void tst_Q3DSSurfaceViewer::cleanup()
+{
+ if (m_window)
+ m_window->close();
+
+ delete m_viewer;
+ m_viewer = nullptr;
+
+ delete m_window;
+ m_window = nullptr;
+
+ delete m_surface;
+ m_surface = nullptr;
+
+ delete m_fbo;
+ m_fbo = nullptr;
+
+ delete m_context;
+ m_context = nullptr;
+}
+
+QWindow *tst_Q3DSSurfaceViewer::createWindow(const QSize &size)
+{
+ QWindow *window = new QWindow();
+
+ window->resize(size);
+ window->setSurfaceType(QSurface::OpenGLSurface);
+ window->setFormat(m_format);
+ window->setTitle(QStringLiteral("Q3DSSurfaceViewer test window"));
+ window->create();
+
+ return window;
+}
+
+QOffscreenSurface *tst_Q3DSSurfaceViewer::createOffscreen()
+{
+ QOffscreenSurface *surface = new QOffscreenSurface();
+ surface->setFormat(m_format);
+ surface->create();
+
+ return surface;
+}
+
+QOpenGLFramebufferObject *tst_Q3DSSurfaceViewer::createFbo(const QSize &size)
+{
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ return new QOpenGLFramebufferObject(size, fboFormat);
+}
+
+void tst_Q3DSSurfaceViewer::createViewer(Q3DSSurfaceViewer *&viewer, QSurface *surface,
+ const QUrl &url, bool autoSize, const QSize &size,
+ int updateInterval, int fboId)
+{
+ viewer = new Q3DSSurfaceViewer();
+ QSignalSpy spy(viewer, &Q3DSSurfaceViewer::runningChanged);
+
+ viewer->presentation()->setSource(url);
+ QCOMPARE(viewer->presentation()->source(), url);
+
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+
+ viewer->setAutoSize(autoSize);
+ if (!autoSize)
+ viewer->setSize(size);
+ viewer->setUpdateInterval(updateInterval);
+
+ QVERIFY(viewer->initialize(surface, m_context, fboId));
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(viewer->isRunning());
+
+ QVERIFY(viewer->fboId() == fboId);
+ QVERIFY(viewer->surface() == surface);
+ QVERIFY(viewer->context() == m_context);
+}
+
+void tst_Q3DSSurfaceViewer::createWindowAndViewer(Q3DSSurfaceViewer *&viewer,
+ const QUrl &url, bool autoSize,
+ const QSize &size, int updateInterval)
+{
+ QSize actualSize = size;
+ if (actualSize.isEmpty())
+ actualSize = QSize(300, 200);
+
+ m_window = createWindow(actualSize);
+
+ createViewer(viewer, m_window, url, autoSize, actualSize, updateInterval, 0);
+
+ m_window->show();
+ QGuiApplication::processEvents();
+}
+
+void tst_Q3DSSurfaceViewer::createOffscreenAndViewer(Q3DSSurfaceViewer *&viewer,
+ const QUrl &url, const QSize &size,
+ int updateInterval)
+{
+ QSize actualSize = size;
+ if (actualSize.isEmpty())
+ actualSize = QSize(300, 200);
+
+ m_surface = createOffscreen();
+ m_context->makeCurrent(m_surface);
+ m_fbo = createFbo(actualSize);
+
+ createViewer(viewer, m_surface, url, false, actualSize, updateInterval, m_fbo->handle());
+}
+
+void tst_Q3DSSurfaceViewer::checkPixel(Q3DSSurfaceViewer *viewer, const QColor &color,
+ const QPoint &pixel)
+{
+ // Grab operation is potentially costly, so retry only every second instead of using
+ // QTRY_COMPARE which would try it every 50ms. We also want to wait first as it takes some time
+ // for the presentation to be displayed.
+ QColor grabColor;
+ for (int i = 0; i < 20; i++) {
+ // Note: If checkpixel is ever changed to not have this wait, some
+ // QGuiApplication::processEvents() calls may be necessary in various test cases to
+ // ensure expected signaling order.
+ QTest::qWait(1000);
+ QImage image = viewer->grab(QRect(pixel, QSize(1, 1)));
+ grabColor = QColor(image.pixel(0, 0));
+ if (grabColor == color)
+ break;
+ }
+ QCOMPARE(grabColor, color);
+}
+
+void tst_Q3DSSurfaceViewer::testBasics_data()
+{
+ QTest::addColumn<bool>("isWindow");
+ QTest::newRow("window") << true;
+ QTest::newRow("offscreen") << false;
+}
+
+void tst_Q3DSSurfaceViewer::testBasics()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, RED);
+ else
+ createOffscreenAndViewer(m_viewer, RED);
+
+ QSignalSpy spy(m_viewer, &Q3DSSurfaceViewer::runningChanged);
+ QVERIFY(spy.isValid());
+
+ checkPixel(m_viewer, Qt::red);
+
+ m_viewer->shutdown();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!m_viewer->isRunning());
+}
+
+void tst_Q3DSSurfaceViewer::testSourceChange_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSourceChange()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, RED);
+ else
+ createOffscreenAndViewer(m_viewer, RED);
+
+ QSignalSpy spy(m_viewer->presentation(), &Q3DSPresentation::sourceChanged);
+ QVERIFY(spy.isValid());
+ QVERIFY(m_viewer->presentation()->source() == RED);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // Different source
+ m_viewer->presentation()->setSource(BLUE);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_viewer->presentation()->source() == BLUE);
+
+ checkPixel(m_viewer, Qt::blue);
+
+ // Reset same source
+ m_viewer->presentation()->setSource(BLUE);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_viewer->presentation()->source() == BLUE);
+
+ checkPixel(m_viewer, Qt::blue);
+
+ // Different source again
+ m_viewer->presentation()->setSource(RED);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(m_viewer->presentation()->source() == RED);
+
+ checkPixel(m_viewer, Qt::red);
+}
+
+void tst_Q3DSSurfaceViewer::testSizeChange_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSizeChange()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow) {
+ createWindowAndViewer(m_viewer, MIXED, true, QSize(600, 600));
+ } else {
+ // Changing size for offscreen surface means recreating the fbo. There's no guarantee
+ // we can get the same fbo id if we do that, so we would have to reinitialize anyway
+ QSKIP("Skipping size change testing for offscreen surfaces");
+ }
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spy1(m_viewer, &Q3DSSurfaceViewer::sizeChanged);
+ QVERIFY(spy1.isValid());
+ QSignalSpy spy2(m_viewer, &Q3DSSurfaceViewer::autoSizeChanged);
+ QVERIFY(spy2.isValid());
+
+ QPoint leftPoint(m_viewer->size().width() * 11 / 24, m_viewer->size().height() / 2);
+ QPoint rightPoint(m_viewer->size().width() * 13 / 24, m_viewer->size().height() / 2);
+
+ // MIXED presentation has left side blue, right side red
+ checkPixel(m_viewer, Qt::blue, leftPoint);
+ checkPixel(m_viewer, Qt::red, rightPoint);
+
+ m_window->resize(QSize(800, 800));
+ QGuiApplication::processEvents();
+ QCOMPARE(spy1.count(), 1);
+
+ checkPixel(m_viewer, Qt::blue, leftPoint);
+ checkPixel(m_viewer, Qt::blue, rightPoint);
+
+ m_window->resize(QSize(400, 400));
+ QGuiApplication::processEvents();
+ QCOMPARE(spy1.count(), 2);
+
+ checkPixel(m_viewer, Qt::red, leftPoint);
+ checkPixel(m_viewer, Qt::red, rightPoint);
+
+ m_viewer->setAutoSize(false);
+ QCOMPARE(spy2.count(), 1);
+
+ // Size should not change since autosize is no longer on
+ m_window->resize(QSize(600, 600));
+ QGuiApplication::processEvents();
+ QCOMPARE(spy1.count(), 2);
+
+ checkPixel(m_viewer, Qt::red, leftPoint);
+ checkPixel(m_viewer, Qt::red, rightPoint);
+
+ m_viewer->setSize(QSize(700, 700));
+ QCOMPARE(spy1.count(), 3);
+
+ checkPixel(m_viewer, Qt::blue, leftPoint);
+ checkPixel(m_viewer, Qt::blue, rightPoint);
+}
+
+void tst_Q3DSSurfaceViewer::testUpdateInterval_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testUpdateInterval()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, ANIMATION);
+ else
+ createOffscreenAndViewer(m_viewer, ANIMATION);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spy(m_viewer, &Q3DSSurfaceViewer::updateIntervalChanged);
+ QVERIFY(spy.isValid());
+ QVERIFY(m_viewer->updateInterval() == 0);
+
+ checkPixel(m_viewer, Qt::black);
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+
+ }
+ {
+ m_viewer->setUpdateInterval(100000);
+ QVERIFY(m_viewer->updateInterval() == 100000);
+ QCOMPARE(spy.count(), 1);
+ // Can't test if animation actually stopped, as grabbing the viewer forces update on it
+ }
+ {
+ m_viewer->setUpdateInterval(20);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(m_viewer->updateInterval() == 20);
+
+ // Non-zero interval short enough to see animation
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ }
+ {
+ m_viewer->setUpdateInterval(-1);
+ QCOMPARE(spy.count(), 3);
+ QVERIFY(m_viewer->updateInterval() == -1);
+ // Can't test if animation actually stopped, as grabbing the viewer forces update on it
+ }
+}
+
+void tst_Q3DSSurfaceViewer::testMultiple_data()
+{
+ QTest::addColumn<int>("windowCount");
+ QTest::addColumn<int>("offscreenCount");
+ QTest::newRow("windows") << 2 << 0;
+ QTest::newRow("offscreens") << 0 << 2;
+ QTest::newRow("mixed") << 1 << 1;
+}
+
+void tst_Q3DSSurfaceViewer::testMultiple()
+{
+ QFETCH(int, windowCount);
+ QFETCH(int, offscreenCount);
+
+ QVector<QWindow *> windows;
+ QVector<QOffscreenSurface *> surfaces;
+ QVector<Q3DSSurfaceViewer *> viewers;
+ QVector<QOpenGLFramebufferObject *> fbos;
+
+ int viewerCount = windowCount + offscreenCount;
+ windows.resize(windowCount);
+ surfaces.resize(offscreenCount);
+ fbos.resize(offscreenCount);
+ viewers.resize(viewerCount);
+
+ QSize size(200, 150);
+ QUrl url;
+ for (int i = 0; i < windowCount; i++) {
+ windows[i] = createWindow(size);
+ if (i % 2)
+ url = RED;
+ else
+ url = BLUE;
+ createViewer(viewers[i], windows[i], url, true, size, 0, 0);
+ windows[i]->setPosition(10 + i * 50, 10 + i * 50);
+ windows[i]->show();
+ QGuiApplication::processEvents();
+ }
+ for (int i = 0; i < offscreenCount; i++) {
+ surfaces[i] = createOffscreen();
+ m_context->makeCurrent(surfaces[i]);
+ fbos[i] = createFbo(size);
+ if ((i + windowCount) % 2)
+ url = RED;
+ else
+ url = BLUE;
+ createViewer(viewers[i + windowCount], surfaces[i], url, false, size, 0,
+ fbos[i]->handle());
+ }
+
+ for (int i = 0; i < viewerCount; i++) {
+ if (i % 2)
+ checkPixel(viewers[i], Qt::red);
+ else
+ checkPixel(viewers[i], Qt::blue);
+ }
+
+ for (QWindow *w : windows) {
+ w->close();
+ delete w;
+ }
+ windows.clear();
+
+ for (QOffscreenSurface *s : surfaces)
+ delete s;
+ surfaces.clear();
+
+ for (Q3DSSurfaceViewer *v : viewers)
+ delete v;
+ viewers.clear();
+
+ for (QOpenGLFramebufferObject *f : fbos)
+ delete f;
+ fbos.clear();
+}
+
+void tst_Q3DSSurfaceViewer::testGrab_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testGrab()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MIXED_VERTICAL);
+ else
+ createOffscreenAndViewer(m_viewer, MIXED_VERTICAL);
+
+ // Single pixels
+ int w = m_viewer->size().width();
+ int h = m_viewer->size().height();
+
+ checkPixel(m_viewer, Qt::blue, QPoint(w / 2, h / 4));
+ checkPixel(m_viewer, Qt::red, QPoint(w / 2, 3 * h / 4));
+
+ checkPixel(m_viewer, Qt::blue, QPoint(0, 0));
+ checkPixel(m_viewer, Qt::blue, QPoint(w - 1, 0));
+ checkPixel(m_viewer, Qt::red, QPoint(0, h - 1));
+ checkPixel(m_viewer, Qt::red, QPoint(w - 1, h - 1));
+
+ // Full buffer
+ QImage img = m_viewer->grab();
+ QColor grabColor1 = img.pixel(w / 2, h / 4);
+ QColor grabColor2 = img.pixel(w / 2, 3 * h / 4);
+ QCOMPARE(grabColor1, QColor(Qt::blue));
+ QCOMPARE(grabColor2, QColor(Qt::red));
+
+ // Partial buffer
+ img = m_viewer->grab(QRect(w / 3, h / 3, w / 2, h / 2));
+ grabColor1 = img.pixel(0, 0);
+ grabColor2 = img.pixel(w / 2 - 1, h / 2 - 1);
+ QCOMPARE(grabColor1, QColor(Qt::blue));
+ QCOMPARE(grabColor2, QColor(Qt::red));
+}
+
+void tst_Q3DSSurfaceViewer::testReset_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testReset()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, RED);
+ else
+ createOffscreenAndViewer(m_viewer, RED);
+
+ checkPixel(m_viewer, Qt::red);
+
+ m_viewer->presentation()->setAttribute(QStringLiteral("Scene.Layer.Rectangle.Material"),
+ QStringLiteral("diffuse.r"), QVariant(0.0));
+ m_viewer->presentation()->setAttribute(QStringLiteral("Scene.Layer.Rectangle.Material"),
+ QStringLiteral("diffuse.b"), QVariant(1.0));
+ checkPixel(m_viewer, Qt::blue);
+
+ m_viewer->reset();
+
+ checkPixel(m_viewer, Qt::red);
+}
+
+void tst_Q3DSSurfaceViewer::testSettings_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSettings()
+{
+ QFETCH(bool, isWindow);
+
+ int width = 500;
+ int height = 500;
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, SETTINGS, false, QSize(width, height));
+ else
+ createOffscreenAndViewer(m_viewer, SETTINGS, QSize(width, height));
+
+ Q3DSViewerSettings *s = m_viewer->settings();
+
+ QSignalSpy spy1(s, &Q3DSViewerSettings::matteColorChanged);
+ QSignalSpy spy2(s, &Q3DSViewerSettings::showRenderStatsChanged);
+ QSignalSpy spy3(s, &Q3DSViewerSettings::shadeModeChanged);
+ QSignalSpy spy4(s, &Q3DSViewerSettings::scaleModeChanged);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+ QVERIFY(spy3.isValid());
+ QVERIFY(spy4.isValid());
+
+ // Check defaults
+ QCOMPARE(s->matteColor(), QColor(Qt::black));
+ QCOMPARE(s->isShowRenderStats(), false);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShaded);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeCenter);
+
+ // Matte
+ checkPixel(m_viewer, Qt::black);
+
+ s->setMatteColor(Qt::cyan);
+ QCOMPARE(s->matteColor(), QColor(Qt::cyan));
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 0);
+ QCOMPARE(spy3.count(), 0);
+ QCOMPARE(spy4.count(), 0);
+
+ checkPixel(m_viewer, Qt::cyan);
+
+ // Render stats
+ QImage image1 = m_viewer->grab();
+
+ s->setShowRenderStats(true);
+ QCOMPARE(s->isShowRenderStats(), true);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 0);
+ QCOMPARE(spy4.count(), 0);
+
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+
+ // ShadeMode
+ image1 = m_viewer->grab();
+
+ s->setShadeMode(Q3DSViewerSettings::ShadeModeShadedWireframe);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShadedWireframe);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 0);
+
+ image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+
+ // Restore shade mode so following tests are not affected by wireframes
+ s->setShadeMode(Q3DSViewerSettings::ShadeModeShaded);
+
+ // ScaleMode
+ checkPixel(m_viewer, Qt::cyan);
+ checkPixel(m_viewer, Qt::cyan, QPoint(50, height / 2));
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 1);
+
+ checkPixel(m_viewer, Qt::cyan);
+ checkPixel(m_viewer, Qt::red, QPoint(50, height / 2));
+
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFill);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+
+ checkPixel(m_viewer, Qt::blue);
+ checkPixel(m_viewer, Qt::red, QPoint(50, height / 2));
+
+ // Saving & loading settings
+ s->save(QStringLiteral("testViewer"), QStringLiteral("The Qt Company"),
+ QStringLiteral("tst_q3dsurfaceviewer"));
+
+ image1 = m_viewer->grab();
+
+ s->setMatteColor(Qt::yellow);
+ s->setShowRenderStats(false);
+ s->setShadeMode(Q3DSViewerSettings::ShadeModeShadedWireframe);
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(s->matteColor(), QColor(Qt::yellow));
+ QCOMPARE(s->isShowRenderStats(), false);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShadedWireframe);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 3);
+ QCOMPARE(spy4.count(), 3);
+
+ image2 = m_viewer->grab();
+
+ s->load(QStringLiteral("testViewer"), QStringLiteral("The Qt Company"),
+ QStringLiteral("tst_q3dsurfaceviewer"));
+
+ QCOMPARE(s->matteColor(), QColor(Qt::cyan));
+ QCOMPARE(s->isShowRenderStats(), true);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShaded);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFill);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 3);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+
+ QImage image3 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ QVERIFY(image3 != image2);
+ QVERIFY(image1 == image3);
+
+ // Clean up the settings so they don't pollute the system (and we have clean slate next time)
+ QSettings(QStringLiteral("The Qt Company"), QStringLiteral("tst_q3dsurfaceviewer")).clear();
+}
+
+void tst_Q3DSSurfaceViewer::testPresentation_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testPresentation()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+ else
+ createOffscreenAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QList<QVariant> args;
+ Q3DSPresentation *p = m_viewer->presentation();
+ QSignalSpy spy1(p, &Q3DSPresentation::slideEntered);
+ QSignalSpy spy2(p, &Q3DSPresentation::slideExited);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+
+ // There are three different "scenes":
+ // The main Scene, three slides: S1, S2, S3
+ // Two components on Scene.Layer:
+ // Scene.Layer.Component1, two slides: C1S1, C1S2
+ // Scene.Layer.Component2, two slides: C2S1, C2S2
+ // The component slides also get enter when parent slide is entered, but they do not get
+ // the corresponding exit if parent slide is exited.
+ QString path = QStringLiteral("Scene");
+ QString pathC1 = QStringLiteral("Scene.Layer.Component1");
+ QString pathC2 = QStringLiteral("Scene.Layer.Component2");
+ QPoint mainPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 2);
+ QPoint bgPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 32);
+ QPoint c1Point(m_viewer->size().width() * 5 / 8, m_viewer->size().height() / 2);
+ QPoint c2Point(m_viewer->size().width() * 7 / 8, m_viewer->size().height() / 2);
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 0);
+
+ // String Attribute
+ QImage image1 = m_viewer->grab();
+ p->setAttribute(QStringLiteral("Scene.Layer.Text"),
+ QStringLiteral("textstring"), QStringLiteral("Test!"));
+ QImage image2 = m_viewer->grab();
+ QTRY_VERIFY(image1 != image2);
+
+ // Float Attribute
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.r"), 0.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.g"), 1.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.b"), 1.0);
+
+ checkPixel(m_viewer, Qt::cyan, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.r"), 1.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.g"), 0.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.b"), 0.0);
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ // Bool Attribute
+ checkPixel(m_viewer, Qt::yellow, bgPoint);
+ p->setAttribute(QStringLiteral("Scene"), QStringLiteral("bgcolorenable"), false);
+ checkPixel(m_viewer, Qt::black, bgPoint);
+
+ // Slide changes
+ p->goToSlide(path, 2);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::blue, c1Point);
+ checkPixel(m_viewer, Qt::blue, c2Point);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S2"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S1"));
+
+ // Time change
+ p->goToTime(path, 7.0f);
+ checkPixel(m_viewer, Qt::black, mainPoint);
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+
+ // More complex slide changes
+ // Changing slide that is not visible should not trigger enter signals
+ // The slides should still change, though, and become visible later when we switch back to S1
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ p->goToSlide(pathC2, QStringLiteral("C2S2"));
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::cyan, c1Point);
+ checkPixel(m_viewer, Qt::magenta, c2Point);
+ QCOMPARE(spy1.count(), 7);
+ QCOMPARE(spy2.count(), 2);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::magenta, c2Point);
+ QCOMPARE(spy1.count(), 8);
+ QCOMPARE(spy2.count(), 3);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), pathC1);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C1S1"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), pathC1);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C1S2"));
+
+ p->goToSlide(pathC2, QStringLiteral("C2S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 4);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), pathC2);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C2S1"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), pathC2);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C2S2"));
+
+ p->goToSlide(path, true, true);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::blue, c1Point);
+ checkPixel(m_viewer, Qt::blue, c2Point);
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 5);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S2"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S1"));
+
+ p->goToSlide(path, false, true);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 6);
+
+ // No wrap, should not change
+ p->goToSlide(path, false, false);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 6);
+
+ // Should wrap
+ p->goToSlide(path, false, true);
+ checkPixel(m_viewer, Qt::green, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::green, c2Point);
+ QCOMPARE(spy1.count(), 14);
+ QCOMPARE(spy2.count(), 7);
+
+ // No wrap, should not change
+ p->goToSlide(path, true, false);
+ checkPixel(m_viewer, Qt::green, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::green, c2Point);
+ QCOMPARE(spy1.count(), 14);
+ QCOMPARE(spy2.count(), 7);
+
+ // Should wrap
+ p->goToSlide(path, true, true);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 17);
+ QCOMPARE(spy2.count(), 8);
+}
+
+void tst_Q3DSSurfaceViewer::testPresentationActivation_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testPresentationActivation()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, ANIMATION);
+ else
+ createOffscreenAndViewer(m_viewer, ANIMATION);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ }
+
+ m_viewer->presentation()->setPresentationActive(QStringLiteral("animation"), false);
+
+ {
+ // Grab two images two seconds apart to verify animation has stopped
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 == image2);
+ }
+
+ m_viewer->presentation()->setPresentationActive(QStringLiteral("animation"), true);
+
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ }
+}
+
+void tst_Q3DSSurfaceViewer::testSceneElement_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSceneElement()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+ else
+ createOffscreenAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QString path = QStringLiteral("Scene");
+ QString pathC1 = QStringLiteral("Scene.Layer.Component1");
+ QString pathC2 = QStringLiteral("Scene.Layer.Component2");
+
+ Q3DSPresentation *p = m_viewer->presentation();
+ Q3DSSceneElement *scene = new Q3DSSceneElement(path);
+ Q3DSSceneElement *sceneC1 = new Q3DSSceneElement(pathC1);
+ Q3DSSceneElement *sceneC2 = new Q3DSSceneElement(pathC2);
+ QSignalSpy spy1(scene, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy2(scene, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy3(scene, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy4(scene, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy5(scene, &Q3DSSceneElement::elementPathChanged);
+ QSignalSpy spy6(sceneC1, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy7(sceneC1, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy8(sceneC1, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy9(sceneC1, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy10(sceneC1, &Q3DSSceneElement::elementPathChanged);
+ QSignalSpy spy11(sceneC2, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy12(sceneC2, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy13(sceneC2, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy14(sceneC2, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy15(sceneC2, &Q3DSSceneElement::elementPathChanged);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+ QVERIFY(spy3.isValid());
+ QVERIFY(spy4.isValid());
+ QVERIFY(spy5.isValid());
+ QVERIFY(spy6.isValid());
+ QVERIFY(spy7.isValid());
+ QVERIFY(spy8.isValid());
+ QVERIFY(spy9.isValid());
+ QVERIFY(spy10.isValid());
+ QVERIFY(spy11.isValid());
+ QVERIFY(spy12.isValid());
+ QVERIFY(spy13.isValid());
+ QVERIFY(spy14.isValid());
+ QVERIFY(spy15.isValid());
+
+ // Defaults
+ QCOMPARE(scene->currentSlideIndex(), 0);
+ QCOMPARE(scene->previousSlideIndex(), 0);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->elementPath(), path);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // Ensure we have no pending events to confuse spy counts
+ QGuiApplication::processEvents();
+
+ p->registerElement(scene);
+ p->registerElement(sceneC1);
+ p->registerElement(sceneC2);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 0);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->elementPath(), path);
+
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 1);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 0);
+ QCOMPARE(spy7.count(), 0);
+ QCOMPARE(spy8.count(), 0);
+ QCOMPARE(spy9.count(), 0);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 0);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 0);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 0);
+ // Getting previous slide change without getting current slide change seems illogical here,
+ // but that's how the internal viewer logic for previous slide works. It makes sense when
+ // you consider the fact that we always get enter events for child slides when parent slide
+ // is entered.
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 0);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(pathC2, QStringLiteral("C2S2"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 1);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 1);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ // Subscenes revert to original slides when parent is re-entered
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 3);
+ QCOMPARE(spy3.count(), 3);
+ QCOMPARE(spy4.count(), 3);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 1);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 1);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 2);
+ QCOMPARE(spy7.count(), 2);
+ QCOMPARE(spy8.count(), 2);
+ QCOMPARE(spy9.count(), 2);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 2);
+ QCOMPARE(spy12.count(), 2);
+ QCOMPARE(spy13.count(), 2);
+ QCOMPARE(spy14.count(), 2);
+ QCOMPARE(spy15.count(), 0);
+
+ p->unregisterElement(scene);
+ p->unregisterElement(sceneC1);
+ p->unregisterElement(sceneC2);
+
+ // No more signals after unregistering
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 2);
+ QCOMPARE(spy7.count(), 2);
+ QCOMPARE(spy8.count(), 2);
+ QCOMPARE(spy9.count(), 2);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 2);
+ QCOMPARE(spy12.count(), 2);
+ QCOMPARE(spy13.count(), 2);
+ QCOMPARE(spy14.count(), 2);
+ QCOMPARE(spy15.count(), 0);
+
+ // Reregister
+ p->registerElement(scene);
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 5);
+ QCOMPARE(spy2.count(), 5);
+ QCOMPARE(spy3.count(), 5);
+ QCOMPARE(spy4.count(), 5);
+ QCOMPARE(spy5.count(), 0);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 2);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral("S2"));
+ QCOMPARE(scene->elementPath(), path);
+
+ scene->setCurrentSlideName(QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 6);
+ QCOMPARE(spy2.count(), 6);
+
+ scene->setCurrentSlideIndex(1);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 7);
+ QCOMPARE(spy2.count(), 7);
+
+ // Go to next slide, wrap parameter doesn't matter
+ scene->goToSlide(true, true);
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 8);
+ QCOMPARE(spy2.count(), 8);
+
+ // Go to next slide, wrap parameter doesn't matter
+ scene->goToSlide(true, false);
+ checkPixel(m_viewer, Qt::green);
+
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 9);
+
+ // No wrap, should not change
+ scene->goToSlide(true, false);
+ checkPixel(m_viewer, Qt::green);
+
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 9);
+
+ // Should wrap
+ scene->goToSlide(true, true);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 10);
+
+ // No wrap, should not change
+ scene->goToSlide(false, false);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 10);
+
+ // Should wrap
+ scene->goToSlide(false, true);
+ checkPixel(m_viewer, Qt::green);
+
+ QCOMPARE(spy1.count(), 11);
+ QCOMPARE(spy2.count(), 11);
+
+ // Time change
+ scene->goToTime(7.0f);
+ checkPixel(m_viewer, Qt::yellow);
+
+ QCOMPARE(spy1.count(), 11);
+ QCOMPARE(spy2.count(), 11);
+
+ // Back to slide 1 for further tests
+ scene->setCurrentSlideIndex(1);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 12);
+ QCOMPARE(spy2.count(), 12);
+
+ // Change element path
+ scene->setElementPath(pathC1);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 12);
+ QCOMPARE(spy2.count(), 12);
+ QCOMPARE(spy3.count(), 12);
+ QCOMPARE(spy4.count(), 12);
+ QCOMPARE(spy5.count(), 1);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 1);
+ // Having current and previous slides the same seems weird, but that's how the slide
+ // logic works internally.
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("C1S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral("C1S1"));
+ QCOMPARE(scene->elementPath(), pathC1);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 12);
+ QCOMPARE(spy3.count(), 13);
+ QCOMPARE(spy4.count(), 12);
+ QCOMPARE(spy5.count(), 1);
+}
+
+void tst_Q3DSSurfaceViewer::testElement_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testElement()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+ else
+ createOffscreenAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QString path1 = QStringLiteral("Scene.Layer.Rect.Material"); // Red
+ QString path2 = QStringLiteral("Scene.Layer.Component1.Rectangle4.Material"); // Green
+ QString path3 = QStringLiteral("Scene.Layer.Component2.Rectangle6.Material"); // Yellow
+
+ QPoint mainPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 2);
+ QPoint c1Point(m_viewer->size().width() * 5 / 8, m_viewer->size().height() / 2);
+ QPoint c2Point(m_viewer->size().width() * 7 / 8, m_viewer->size().height() / 2);
+
+ Q3DSPresentation *p = m_viewer->presentation();
+ Q3DSElement *element1 = new Q3DSElement(p, path1);
+ Q3DSElement *element2 = new Q3DSElement(p, path2);
+ QSignalSpy spy2(element2, &Q3DSSceneElement::elementPathChanged);
+ QVERIFY(spy2.isValid());
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ element1->setAttribute(QStringLiteral("diffuse.r"), 0.0);
+ element1->setAttribute(QStringLiteral("diffuse.g"), 0.0);
+ element1->setAttribute(QStringLiteral("diffuse.b"), 1.0);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ element2->setAttribute(QStringLiteral("diffuse.r"), 1.0);
+ element2->setAttribute(QStringLiteral("diffuse.g"), 0.0);
+ element2->setAttribute(QStringLiteral("diffuse.b"), 1.0);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::magenta, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ // Change elementpath, nothing changes visually
+ element2->setElementPath(path3);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::magenta, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy2.count(), 1);
+
+ element2->setAttribute(QStringLiteral("diffuse.r"), 0.0);
+ element2->setAttribute(QStringLiteral("diffuse.g"), 1.0);
+ element2->setAttribute(QStringLiteral("diffuse.b"), 1.0);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::magenta, c1Point);
+ checkPixel(m_viewer, Qt::cyan, c2Point);
+}
+
+void tst_Q3DSSurfaceViewer::testMouseInput_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testMouseInput()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MOUSE);
+ else
+ createOffscreenAndViewer(m_viewer, MOUSE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QPoint point1(m_viewer->size().width() * 1 / 4, m_viewer->size().height() / 2);
+ QPoint point2(m_viewer->size().width() * 3 / 4, m_viewer->size().height() / 2);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e1(QEvent::MouseButtonPress, point1, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mousePressEvent(&e1);
+
+ checkPixel(m_viewer, Qt::green, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e2(QEvent::MouseButtonRelease, point1, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mouseReleaseEvent(&e2);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e3(QEvent::MouseButtonPress, point2, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mousePressEvent(&e3);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::blue, point2);
+
+ QMouseEvent e4(QEvent::MouseButtonRelease, point2, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mouseReleaseEvent(&e4);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ // Note: No way yet to hook mouse move into anything in the presentation
+}
+
+
+QTEST_MAIN(tst_Q3DSSurfaceViewer)
+
+#include "tst_q3dssurfaceviewer.moc"
diff --git a/tests/auto/studio3d/q3dswidget/q3dswidget.pro b/tests/auto/studio3d/q3dswidget/q3dswidget.pro
new file mode 100644
index 00000000..82339b2b
--- /dev/null
+++ b/tests/auto/studio3d/q3dswidget/q3dswidget.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+CONFIG += testcase
+
+TARGET = tst_q3dswidget
+
+QT += testlib studio3d
+
+SOURCES += tst_q3dswidget.cpp
+
+RESOURCES += ../shared/shared_presentations.qrc
diff --git a/tests/auto/studio3d/q3dswidget/tst_q3dswidget.cpp b/tests/auto/studio3d/q3dswidget/tst_q3dswidget.cpp
new file mode 100644
index 00000000..c92a9159
--- /dev/null
+++ b/tests/auto/studio3d/q3dswidget/tst_q3dswidget.cpp
@@ -0,0 +1,1040 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtStudio3D/q3dswidget.h>
+#include <QtStudio3D/q3dsviewersettings.h>
+#include <QtStudio3D/q3dspresentation.h>
+#include <QtStudio3D/q3dssceneelement.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qopenglframebufferobject.h>
+#include <QtGui/qevent.h>
+#include <QtWidgets/qmainwindow.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qfile.h>
+#include "../shared/shared_presentations.h"
+
+class tst_Q3DSWidget : public QObject
+{
+ Q_OBJECT
+public:
+ tst_Q3DSWidget();
+ ~tst_Q3DSWidget() {}
+
+private slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+
+ void testBasics();
+ void testSourceChange();
+ void testUpdateInterval();
+ void testMultiple();
+ void testReset();
+ void testSettings();
+ void testPresentation();
+ void testPresentationActivation();
+ void testScene();
+ void testMouseInput();
+
+private:
+ QMainWindow *createWindow(const QSize &size);
+
+ // Created viewers are returned via *&viewer parameter rather than return value, so that we can
+ // use QCOMPARE and QVERIFY inside these functions (they require void return value).
+ void createViewer(Q3DSWidget *&viewer, QMainWindow *window, const QUrl &url,
+ int updateInterval);
+ void createWindowAndViewer(Q3DSWidget *&viewer, const QUrl &url,
+ const QSize &size = QSize(), int updateInterval = 0);
+ void checkPixel(Q3DSWidget *viewer, const QColor &color,
+ const QPoint &pixel = QPoint(50, 50));
+
+ QMainWindow *m_window;
+ Q3DSWidget *m_viewer;
+};
+
+tst_Q3DSWidget::tst_Q3DSWidget()
+ : m_window(nullptr)
+ , m_viewer(nullptr)
+{
+}
+
+//#define DUMP_LOGFILE // Uncomment log Qt 3D Studio internal messages to log.txt file
+void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ // case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg: {
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+ QTextStream stream(&file);
+ stream << msg << "\n";
+ }
+ file.close();
+#endif
+ } break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_Q3DSWidget::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
+ QTextStream stream(&file);
+ stream << "Log file: " << QTime::currentTime().toString() << "\n";
+ }
+ file.close();
+#endif
+}
+
+void tst_Q3DSWidget::init()
+{
+}
+
+void tst_Q3DSWidget::cleanup()
+{
+ if (m_window)
+ m_window->close();
+
+ delete m_viewer;
+ m_viewer = nullptr;
+
+ delete m_window;
+ m_window = nullptr;
+}
+
+QMainWindow *tst_Q3DSWidget::createWindow(const QSize &size)
+{
+ QMainWindow *window = new QMainWindow();
+
+ window->resize(size);
+
+ return window;
+}
+
+void tst_Q3DSWidget::createViewer(Q3DSWidget *&viewer, QMainWindow *window, const QUrl &url,
+ int updateInterval)
+{
+ viewer = new Q3DSWidget();
+ QSignalSpy spy(viewer, &Q3DSWidget::runningChanged);
+
+ window->setCentralWidget(viewer);
+
+ viewer->presentation()->setSource(url);
+ QCOMPARE(viewer->presentation()->source(), url);
+
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+
+ viewer->setUpdateInterval(updateInterval);
+
+ QVERIFY(viewer->initialize());
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(viewer->isRunning());
+}
+
+void tst_Q3DSWidget::createWindowAndViewer(Q3DSWidget *&viewer, const QUrl &url,
+ const QSize &size, int updateInterval)
+{
+ QSize actualSize = size;
+ if (actualSize.isEmpty())
+ actualSize = QSize(300, 200);
+
+ m_window = createWindow(actualSize);
+ m_window->show();
+
+ createViewer(viewer, m_window, url, updateInterval);
+
+ QGuiApplication::processEvents();
+}
+
+void tst_Q3DSWidget::checkPixel(Q3DSWidget *viewer, const QColor &color,
+ const QPoint &pixel)
+{
+ // Grab operation is potentially costly, so retry only every second instead of using
+ // QTRY_COMPARE which would try it every 50ms. We also want to wait first as it takes some time
+ // for the presentation to be displayed.
+ QColor grabColor;
+ for (int i = 0; i < 20; i++) {
+ QTest::qWait(1000);
+ QImage image = viewer->grabFramebuffer();
+ grabColor = QColor(image.pixel(pixel));
+ if (grabColor == color)
+ break;
+ }
+ QCOMPARE(grabColor, color);
+}
+
+void tst_Q3DSWidget::testBasics()
+{
+ createWindowAndViewer(m_viewer, RED);
+
+ QSignalSpy spy(m_viewer, &Q3DSWidget::runningChanged);
+ QVERIFY(spy.isValid());
+
+ checkPixel(m_viewer, Qt::red);
+
+ m_viewer->shutdown();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!m_viewer->isRunning());
+}
+
+void tst_Q3DSWidget::testSourceChange()
+{
+ createWindowAndViewer(m_viewer, RED);
+
+ QSignalSpy spy(m_viewer->presentation(), &Q3DSPresentation::sourceChanged);
+ QVERIFY(spy.isValid());
+ QVERIFY(m_viewer->presentation()->source() == RED);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // Different source
+ m_viewer->presentation()->setSource(BLUE);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_viewer->presentation()->source() == BLUE);
+
+ checkPixel(m_viewer, Qt::blue);
+
+ // Reset same source
+ m_viewer->presentation()->setSource(BLUE);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_viewer->presentation()->source() == BLUE);
+
+ checkPixel(m_viewer, Qt::blue);
+
+ // Different source again
+ m_viewer->presentation()->setSource(RED);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(m_viewer->presentation()->source() == RED);
+
+ checkPixel(m_viewer, Qt::red);
+}
+
+void tst_Q3DSWidget::testUpdateInterval()
+{
+ createWindowAndViewer(m_viewer, ANIMATION);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spy(m_viewer, &Q3DSWidget::updateIntervalChanged);
+ QVERIFY(spy.isValid());
+ QVERIFY(m_viewer->updateInterval() == 0);
+
+ checkPixel(m_viewer, Qt::black);
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grabFramebuffer();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+
+ }
+ {
+ m_viewer->setUpdateInterval(100000);
+ QVERIFY(m_viewer->updateInterval() == 100000);
+ QCOMPARE(spy.count(), 1);
+ // Can't test if animation actually stopped, as grabbing the viewer forces update on it
+ }
+ {
+ m_viewer->setUpdateInterval(20);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(m_viewer->updateInterval() == 20);
+
+ // Non-zero interval short enough to see animation
+ QImage image1 = m_viewer->grabFramebuffer();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+ }
+ {
+ m_viewer->setUpdateInterval(-1);
+ QCOMPARE(spy.count(), 3);
+ QVERIFY(m_viewer->updateInterval() == -1);
+ // Can't test if animation actually stopped, as grabbing the viewer forces update on it
+ }
+}
+
+void tst_Q3DSWidget::testMultiple()
+{
+ int viewerCount = 3;
+
+ QVector<QMainWindow *> windows;
+ QVector<Q3DSWidget *> viewers;
+
+ windows.resize(viewerCount);
+ viewers.resize(viewerCount);
+
+ QSize size(200, 150);
+ QUrl url;
+ for (int i = 0; i < viewerCount; i++) {
+ windows[i] = createWindow(size);
+ if (i % 2)
+ url = RED;
+ else
+ url = BLUE;
+ windows[i]->move(10 + i * 50, 10 + i * 50);
+ windows[i]->show();
+ createViewer(viewers[i], windows[i], url, 0);
+ QGuiApplication::processEvents();
+ }
+
+ for (int i = 0; i < viewerCount; i++) {
+ if (i % 2)
+ checkPixel(viewers[i], Qt::red);
+ else
+ checkPixel(viewers[i], Qt::blue);
+ }
+
+ for (QMainWindow *w : windows) {
+ w->close();
+ delete w;
+ }
+ windows.clear();
+}
+
+void tst_Q3DSWidget::testReset()
+{
+ createWindowAndViewer(m_viewer, RED);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // TODO: change color of the cube to blue (not currently possible, API missing)
+ // checkPixel(m_viewer, Qt::blue);
+
+ m_viewer->reset();
+
+ checkPixel(m_viewer, Qt::red);
+}
+
+void tst_Q3DSWidget::testSettings()
+{
+ int width = 500;
+ int height = 500;
+
+ createWindowAndViewer(m_viewer, SETTINGS, QSize(width, height));
+
+ Q3DSViewerSettings *s = m_viewer->settings();
+
+ QSignalSpy spy1(s, &Q3DSViewerSettings::matteColorChanged);
+ QSignalSpy spy2(s, &Q3DSViewerSettings::showRenderStatsChanged);
+ QSignalSpy spy3(s, &Q3DSViewerSettings::shadeModeChanged);
+ QSignalSpy spy4(s, &Q3DSViewerSettings::scaleModeChanged);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+ QVERIFY(spy3.isValid());
+ QVERIFY(spy4.isValid());
+
+ // Check defaults
+ QCOMPARE(s->matteColor(), QColor(Qt::black));
+ QCOMPARE(s->isShowRenderStats(), false);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShaded);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeCenter);
+
+ // Matte
+ checkPixel(m_viewer, Qt::black);
+
+ s->setMatteColor(Qt::cyan);
+ QCOMPARE(s->matteColor(), QColor(Qt::cyan));
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 0);
+ QCOMPARE(spy3.count(), 0);
+ QCOMPARE(spy4.count(), 0);
+
+ checkPixel(m_viewer, Qt::cyan);
+
+ // Render stats
+ QImage image1 = m_viewer->grabFramebuffer();
+
+ s->setShowRenderStats(true);
+ QCOMPARE(s->isShowRenderStats(), true);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 0);
+ QCOMPARE(spy4.count(), 0);
+
+ QImage image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+
+ // ShadeMode
+ image1 = m_viewer->grabFramebuffer();
+
+ s->setShadeMode(Q3DSViewerSettings::ShadeModeShadedWireframe);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShadedWireframe);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 0);
+
+ image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+
+ // Restore shade mode so following tests are not affected by wireframes
+ s->setShadeMode(Q3DSViewerSettings::ShadeModeShaded);
+
+ // ScaleMode
+ checkPixel(m_viewer, Qt::cyan);
+ checkPixel(m_viewer, Qt::cyan, QPoint(50, height / 2));
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 1);
+
+ checkPixel(m_viewer, Qt::cyan);
+ checkPixel(m_viewer, Qt::red, QPoint(50, height / 2));
+
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFill);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+
+ checkPixel(m_viewer, Qt::blue);
+ checkPixel(m_viewer, Qt::red, QPoint(50, height / 2));
+
+ // Saving & loading settings
+ s->save(QStringLiteral("testViewer"), QStringLiteral("The Qt Company"),
+ QStringLiteral("tst_q3dsurfaceviewer"));
+
+ image1 = m_viewer->grabFramebuffer();
+
+ s->setMatteColor(Qt::yellow);
+ s->setShowRenderStats(false);
+ s->setShadeMode(Q3DSViewerSettings::ShadeModeShadedWireframe);
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(s->matteColor(), QColor(Qt::yellow));
+ QCOMPARE(s->isShowRenderStats(), false);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShadedWireframe);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 3);
+ QCOMPARE(spy4.count(), 3);
+
+ image2 = m_viewer->grabFramebuffer();
+
+ s->load(QStringLiteral("testViewer"), QStringLiteral("The Qt Company"),
+ QStringLiteral("tst_q3dsurfaceviewer"));
+
+ QCOMPARE(s->matteColor(), QColor(Qt::cyan));
+ QCOMPARE(s->isShowRenderStats(), true);
+ QCOMPARE(s->shadeMode(), Q3DSViewerSettings::ShadeModeShaded);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFill);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 3);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+
+ QImage image3 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+ QVERIFY(image3 != image2);
+ QVERIFY(image1 == image3);
+
+ // Clean up the settings so they don't pollute the system (and we have clean slate next time)
+ QSettings(QStringLiteral("The Qt Company"), QStringLiteral("tst_q3dwidget")).clear();
+}
+
+void tst_Q3DSWidget::testPresentation()
+{
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->setUpdateBehavior(QOpenGLWidget::PartialUpdate);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QList<QVariant> args;
+ Q3DSPresentation *p = m_viewer->presentation();
+ QSignalSpy spy1(p, &Q3DSPresentation::slideEntered);
+ QSignalSpy spy2(p, &Q3DSPresentation::slideExited);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+
+ // There are three different "scenes":
+ // The main Scene, three slides: S1, S2, S3
+ // Two components on Scene.Layer:
+ // Scene.Layer.Component1, two slides: C1S1, C1S2
+ // Scene.Layer.Component2, two slides: C2S1, C2S2
+ // The component slides also get enter when parent slide is entered, but they do not get
+ // the corresponding exit if parent slide is exited.
+ QString path = QStringLiteral("Scene");
+ QString pathC1 = QStringLiteral("Scene.Layer.Component1");
+ QString pathC2 = QStringLiteral("Scene.Layer.Component2");
+ QPoint mainPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 2);
+ QPoint bgPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 32);
+ QPoint c1Point(m_viewer->size().width() * 5 / 8, m_viewer->size().height() / 2);
+ QPoint c2Point(m_viewer->size().width() * 7 / 8, m_viewer->size().height() / 2);
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 0);
+
+ // String Attribute
+ QImage image1 = m_viewer->grabFramebuffer();
+ p->setAttribute(QStringLiteral("Scene.Layer.Text"),
+ QStringLiteral("textstring"), QStringLiteral("Test!"));
+ QImage image2 = m_viewer->grabFramebuffer();
+ QTRY_VERIFY(image1 != image2);
+
+ // Float Attribute
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.r"), 0.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.g"), 1.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.b"), 1.0);
+
+ checkPixel(m_viewer, Qt::cyan, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.r"), 1.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.g"), 0.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.b"), 0.0);
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ // Bool Attribute
+ checkPixel(m_viewer, Qt::yellow, bgPoint);
+ p->setAttribute(QStringLiteral("Scene"), QStringLiteral("bgcolorenable"), false);
+ checkPixel(m_viewer, Qt::black, bgPoint);
+
+ // Slide changes
+ p->goToSlide(path, 2);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::blue, c1Point);
+ checkPixel(m_viewer, Qt::blue, c2Point);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S2"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S1"));
+
+ // Time change
+ p->goToTime(path, 7);
+ checkPixel(m_viewer, Qt::black, mainPoint);
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+
+ // More complex slide changes
+ // Changing slide that is not visible should not trigger enter signals
+ // The slides should still change, though, and become visible later when we switch back to S1
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ p->goToSlide(pathC2, QStringLiteral("C2S2"));
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::cyan, c1Point);
+ checkPixel(m_viewer, Qt::magenta, c2Point);
+ QCOMPARE(spy1.count(), 7);
+ QCOMPARE(spy2.count(), 2);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::magenta, c2Point);
+ QCOMPARE(spy1.count(), 8);
+ QCOMPARE(spy2.count(), 3);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), pathC1);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C1S1"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), pathC1);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C1S2"));
+
+ p->goToSlide(pathC2, QStringLiteral("C2S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 4);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), pathC2);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C2S1"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), pathC2);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C2S2"));
+
+ p->goToSlide(path, true, true);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::blue, c1Point);
+ checkPixel(m_viewer, Qt::blue, c2Point);
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 5);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S2"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S1"));
+
+ p->goToSlide(path, false, true);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 6);
+
+ // No wrap, should not change
+ p->goToSlide(path, false, false);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 6);
+
+ // Should wrap
+ p->goToSlide(path, false, true);
+ checkPixel(m_viewer, Qt::green, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::green, c2Point);
+ QCOMPARE(spy1.count(), 14);
+ QCOMPARE(spy2.count(), 7);
+
+ // No wrap, should not change
+ p->goToSlide(path, true, false);
+ checkPixel(m_viewer, Qt::green, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::green, c2Point);
+ QCOMPARE(spy1.count(), 14);
+ QCOMPARE(spy2.count(), 7);
+
+ // Should wrap
+ p->goToSlide(path, true, true);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 17);
+ QCOMPARE(spy2.count(), 8);
+}
+
+void tst_Q3DSWidget::testPresentationActivation()
+{
+ createWindowAndViewer(m_viewer, ANIMATION);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grabFramebuffer();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+ }
+
+ m_viewer->presentation()->setPresentationActive(QStringLiteral("animation"), false);
+
+ {
+ // Grab two images two seconds apart to verify animation has stopped
+ QImage image1 = m_viewer->grabFramebuffer();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 == image2);
+ }
+
+ m_viewer->presentation()->setPresentationActive(QStringLiteral("animation"), true);
+
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grabFramebuffer();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grabFramebuffer();
+ QVERIFY(image1 != image2);
+ }
+}
+
+void tst_Q3DSWidget::testScene()
+{
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QString path = QStringLiteral("Scene");
+ QString pathC1 = QStringLiteral("Scene.Layer.Component1");
+ QString pathC2 = QStringLiteral("Scene.Layer.Component2");
+
+ Q3DSPresentation *p = m_viewer->presentation();
+ Q3DSSceneElement *scene = new Q3DSSceneElement(path);
+ Q3DSSceneElement *sceneC1 = new Q3DSSceneElement(pathC1);
+ Q3DSSceneElement *sceneC2 = new Q3DSSceneElement(pathC2);
+ QSignalSpy spy1(scene, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy2(scene, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy3(scene, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy4(scene, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy5(scene, &Q3DSSceneElement::elementPathChanged);
+ QSignalSpy spy6(sceneC1, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy7(sceneC1, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy8(sceneC1, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy9(sceneC1, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy10(sceneC1, &Q3DSSceneElement::elementPathChanged);
+ QSignalSpy spy11(sceneC2, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy12(sceneC2, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy13(sceneC2, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy14(sceneC2, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy15(sceneC2, &Q3DSSceneElement::elementPathChanged);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+ QVERIFY(spy3.isValid());
+ QVERIFY(spy4.isValid());
+ QVERIFY(spy5.isValid());
+ QVERIFY(spy6.isValid());
+ QVERIFY(spy7.isValid());
+ QVERIFY(spy8.isValid());
+ QVERIFY(spy9.isValid());
+ QVERIFY(spy10.isValid());
+ QVERIFY(spy11.isValid());
+ QVERIFY(spy12.isValid());
+ QVERIFY(spy13.isValid());
+ QVERIFY(spy14.isValid());
+ QVERIFY(spy15.isValid());
+
+ // Defaults
+ QCOMPARE(scene->currentSlideIndex(), 0);
+ QCOMPARE(scene->previousSlideIndex(), 0);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->elementPath(), path);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // Ensure the first slide enter events come before we register so they don't muddle the waters
+ QGuiApplication::processEvents();
+
+ p->registerElement(scene);
+ p->registerElement(sceneC1);
+ p->registerElement(sceneC2);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 0);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->elementPath(), path);
+
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 1);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 0);
+ QCOMPARE(spy7.count(), 0);
+ QCOMPARE(spy8.count(), 0);
+ QCOMPARE(spy9.count(), 0);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 0);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 0);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 0);
+ // Getting previous slide change without getting current slide change seems illogical here,
+ // but that's how the internal viewer logic for previous slide works. It makes sense when
+ // you consider the fact that we always get enter events for child slides when parent slide
+ // is entered.
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 0);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(pathC2, QStringLiteral("C2S2"));
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 1);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 1);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ // Subscenes revert to original slides when parent is re-entered
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 3);
+ QCOMPARE(spy3.count(), 3);
+ QCOMPARE(spy4.count(), 3);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 1);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 1);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 2);
+ QCOMPARE(spy7.count(), 2);
+ QCOMPARE(spy8.count(), 2);
+ QCOMPARE(spy9.count(), 2);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 2);
+ QCOMPARE(spy12.count(), 2);
+ QCOMPARE(spy13.count(), 2);
+ QCOMPARE(spy14.count(), 2);
+ QCOMPARE(spy15.count(), 0);
+
+ p->unregisterElement(scene);
+ p->unregisterElement(sceneC1);
+ p->unregisterElement(sceneC2);
+
+ // No more signals after unregistering
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 2);
+ QCOMPARE(spy7.count(), 2);
+ QCOMPARE(spy8.count(), 2);
+ QCOMPARE(spy9.count(), 2);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 2);
+ QCOMPARE(spy12.count(), 2);
+ QCOMPARE(spy13.count(), 2);
+ QCOMPARE(spy14.count(), 2);
+ QCOMPARE(spy15.count(), 0);
+
+ // Reregister
+ p->registerElement(scene);
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 5);
+ QCOMPARE(spy2.count(), 5);
+ QCOMPARE(spy3.count(), 5);
+ QCOMPARE(spy4.count(), 5);
+ QCOMPARE(spy5.count(), 0);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 2);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral("S2"));
+ QCOMPARE(scene->elementPath(), path);
+
+ // Change elementpath
+ scene->setElementPath(pathC1);
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 5);
+ QCOMPARE(spy2.count(), 5);
+ QCOMPARE(spy3.count(), 5);
+ QCOMPARE(spy4.count(), 5);
+ QCOMPARE(spy5.count(), 1);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 1);
+ // Having current and previous slides the same seems weird, but that's how the slide
+ // logic works internally.
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("C1S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral("C1S1"));
+ QCOMPARE(scene->elementPath(), pathC1);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ checkPixel(m_viewer, Qt::red);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 6);
+ QCOMPARE(spy2.count(), 5);
+ QCOMPARE(spy3.count(), 6);
+ QCOMPARE(spy4.count(), 5);
+ QCOMPARE(spy5.count(), 1);
+
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(spy1.count(), 6);
+ QCOMPARE(spy2.count(), 5);
+ QCOMPARE(spy3.count(), 6);
+ QCOMPARE(spy4.count(), 5);
+ QCOMPARE(spy5.count(), 1);
+}
+
+void tst_Q3DSWidget::testMouseInput()
+{
+ createWindowAndViewer(m_viewer, MOUSE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QPoint point1(m_viewer->size().width() * 1 / 4, m_viewer->size().height() / 2);
+ QPoint point2(m_viewer->size().width() * 3 / 4, m_viewer->size().height() / 2);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e1(QEvent::MouseButtonPress, point1, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mousePressEvent(&e1);
+
+ checkPixel(m_viewer, Qt::green, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e2(QEvent::MouseButtonRelease, point1, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mouseReleaseEvent(&e2);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e3(QEvent::MouseButtonPress, point2, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mousePressEvent(&e3);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::blue, point2);
+
+ QMouseEvent e4(QEvent::MouseButtonRelease, point2, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mouseReleaseEvent(&e4);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ // Note: No way yet to hook mouse move into anything in the presentation
+}
+
+QTEST_MAIN(tst_Q3DSWidget)
+
+#include "tst_q3dswidget.moc"
diff --git a/tests/auto/studio3d/shared/presentation/animation.uip b/tests/auto/studio3d/shared/presentation/animation.uip
new file mode 100644
index 00000000..bd78b515
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/animation.uip
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Cube" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="29690" />
+ <Set ref="#Camera" endtime="29690" />
+ <Set ref="#Light" endtime="29690" />
+ <Add ref="#Cube" name="Cube" endtime="29690" position="5.7735 -14.4338 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -457.55 100 100 4.832 -8.66028 100 100 11.174 440.23 100 100 20.037 -64.9519 100 100 29.69 -401.258 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 -1.52588e-05 100 100 4.832 -220.837 100 100 11.174 -18.7639 100 100 20.037 225.167 100 100 29.69 -14.4337 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 4.832 0 100 100 11.174 0 100 100 20.037 0 100 100 29.69 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/blue.uip b/tests/auto/studio3d/shared/presentation/blue.uip
new file mode 100644
index 00000000..a6eefa7e
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/blue.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttf b/tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttf
new file mode 100644
index 00000000..6da82193
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttf
Binary files differ
diff --git a/tests/auto/studio3d/shared/presentation/mixed.uip b/tests/auto/studio3d/shared/presentation/mixed.uip
new file mode 100644
index 00000000..16fea006
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/mixed.uip
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="401.651 25 0" scale="8 16 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="8000" position="-378.164 25 0" scale="8 16 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_001" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/mixed_vertical.uip b/tests/auto/studio3d/shared/presentation/mixed_vertical.uip
new file mode 100644
index 00000000..7914b119
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/mixed_vertical.uip
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="0 -400 0" scale="16 8 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="8000" position="0 400 0" scale="16 8 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_001" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/mouse.uip b/tests/auto/studio3d/shared/presentation/mouse.uip
new file mode 100644
index 00000000..edd9f95f
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/mouse.uip
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="668.283 7.21691 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" >
+ <Action id="Rectangle-Action" eyeball="True" triggerObject="#Rectangle" event="onPressureDown" targetObject="#Material" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 0 1" />
+ </Action>
+ <Action id="Rectangle-Action_001" eyeball="True" triggerObject="#Rectangle" event="onPressureUp" targetObject="#Material" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="1 0 0" />
+ </Action>
+ </Add>
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="8000" position="-528.276 -19.6247 0" scale="10.6053 8.67004 1" sourcepath="#Rectangle" >
+ <Action id="Rectangle2-Action" eyeball="True" triggerObject="#Rectangle2" event="onPressureDown" targetObject="#Material_001" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 1 0" />
+ </Action>
+ <Action id="Rectangle2-Action_001" eyeball="True" triggerObject="#Rectangle2" event="onPressureUp" targetObject="#Material_001" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 0 1" />
+ </Action>
+ </Add>
+ <Add ref="#Material_001" diffuse="0 0 1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/multislide.uip b/tests/auto/studio3d/shared/presentation/multislide.uip
new file mode 100644
index 00000000..e17db1db
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/multislide.uip
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" backgroundcolor="1 1 0" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle1" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ <Model id="Rectangle2_003" >
+ <Material id="Material_006" />
+ </Model>
+ <Component id="Component" >
+ <Model id="Rectangle" >
+ <Material id="Material_002" />
+ </Model>
+ <Model id="Rectangle2_001" >
+ <Material id="Material_003" />
+ </Model>
+ </Component>
+ <Component id="Component2" >
+ <Model id="Rectangle_001" >
+ <Material id="Material_004" />
+ </Model>
+ <Model id="Rectangle2_002" >
+ <Material id="Material_005" />
+ </Model>
+ </Component>
+ <Text id="Text" />
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-S1" name="S1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle1" name="Rect" position="0 0 0" scale="13.3333 5 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" opacity="100" />
+ <Add ref="#Component" name="Component1" endtime="8000" position="400 0 -1" scale="4 3 1" />
+ <Add ref="#Component2" name="Component2" endtime="8000" position="461.548 -5.72538 -5" />
+ <Add ref="#Text" name="Text" endtime="8000" font="TitilliumWeb-Regular" position="-304.552 -193.631 0" size="36" />
+ </State>
+ <State id="Scene-S2" name="S2" initialplaystate="Pause" playmode="Looping" playthroughto="Previous" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle2" name="Rectangle2" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" >
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 11.6 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 9.5252 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 8 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_001" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ <State id="Scene-S3" name="S3" initialplaystate="Pause" playmode="Looping" playthroughto="Previous" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle2_003" name="Rectangle3" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" >
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 11.6 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 9.5252 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 8 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_006" diffuse="0 1 0" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ <State name="Master Slide" component="#Component" >
+ <State id="Component1-C1S1" name="C1S1" >
+ <Add ref="#Rectangle" name="Rectangle4" position="0 0 -1" scale="2 3 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_002" diffuse="0 1 0" />
+ </State>
+ <State id="Component1-C1S2" name="C1S2" playthroughto="Previous" >
+ <Add ref="#Rectangle2_001" name="Rectangle5" position="0 0 -1" scale="2 3 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_003" diffuse="0 1 1" />
+ </State>
+ </State>
+ <State name="Master Slide" component="#Component2" >
+ <State id="Component2-C2S1" name="C2S1" >
+ <Add ref="#Rectangle_001" name="Rectangle6" scale="3.5 7 3.03591" sourcepath="#Rectangle" />
+ <Add ref="#Material_004" diffuse="1 1 0" />
+ </State>
+ <State id="Component2-C2S2" name="C2S2" playthroughto="Previous" >
+ <Add ref="#Rectangle2_002" name="Rectangle7" scale="3.5 7 3.03591" sourcepath="#Rectangle" />
+ <Add ref="#Material_005" diffuse="1 0 1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/red.uip b/tests/auto/studio3d/shared/presentation/red.uip
new file mode 100644
index 00000000..a04d2f8a
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/red.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/settings.uip b/tests/auto/studio3d/shared/presentation/settings.uip
new file mode 100644
index 00000000..acd580ab
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/settings.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="300" presentationHeight="200" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" backgroundcolor="0 0 1" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" edgetess="1" endtime="8000" innertess="1" position="0 -15.8771 0" scale="11 2.375 1" sourcepath="#Rectangle" tessellation="Linear" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/shared_presentations.h b/tests/auto/studio3d/shared/shared_presentations.h
new file mode 100644
index 00000000..c778b453
--- /dev/null
+++ b/tests/auto/studio3d/shared/shared_presentations.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qurl.h>
+
+const QUrl RED = QUrl(QStringLiteral("qrc:/red.uip"));
+const QUrl BLUE = QUrl(QStringLiteral("qrc:/blue.uip"));
+const QUrl MIXED = QUrl(QStringLiteral("qrc:/mixed.uip"));
+const QUrl MIXED_VERTICAL = QUrl(QStringLiteral("qrc:/mixed_vertical.uip"));
+const QUrl ANIMATION = QUrl(QStringLiteral("qrc:/animation.uip"));
+const QUrl SETTINGS = QUrl(QStringLiteral("qrc:/settings.uip"));
+const QUrl MULTISLIDE = QUrl(QStringLiteral("qrc:/multislide.uip"));
+const QUrl MOUSE = QUrl(QStringLiteral("qrc:/mouse.uip"));
diff --git a/tests/auto/studio3d/shared/shared_presentations.qrc b/tests/auto/studio3d/shared/shared_presentations.qrc
new file mode 100644
index 00000000..a68dae72
--- /dev/null
+++ b/tests/auto/studio3d/shared/shared_presentations.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="blue.uip">presentation/blue.uip</file>
+ <file alias="red.uip">presentation/red.uip</file>
+ <file alias="mixed.uip">presentation/mixed.uip</file>
+ <file alias="animation.uip">presentation/animation.uip</file>
+ <file alias="mixed_vertical.uip">presentation/mixed_vertical.uip</file>
+ <file alias="settings.uip">presentation/settings.uip</file>
+ <file alias="multislide.uip">presentation/multislide.uip</file>
+ <file alias="mouse.uip">presentation/mouse.uip</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/studio3d/studio3d.pro b/tests/auto/studio3d/studio3d.pro
new file mode 100644
index 00000000..bc866821
--- /dev/null
+++ b/tests/auto/studio3d/studio3d.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ q3dssurfaceviewer \
+ q3dswidget
diff --git a/tests/auto/viewer/simple_cube_animation/simple_cube_animation.uia b/tests/auto/viewer/simple_cube_animation/simple_cube_animation.uia
new file mode 100644
index 00000000..b3dffbd2
--- /dev/null
+++ b/tests/auto/viewer/simple_cube_animation/simple_cube_animation.uia
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application xmlns="http://qt.io/qt3dstudio/uia">
+ <assets initial="simple_cube_animation">
+ <presentation id="simple_cube_animation" src="simple_cube_animation.uip"/>
+ </assets>
+</application>
diff --git a/tests/auto/viewer/simple_cube_animation/simple_cube_animation.uip b/tests/auto/viewer/simple_cube_animation/simple_cube_animation.uip
new file mode 100644
index 00000000..22584127
--- /dev/null
+++ b/tests/auto/viewer/simple_cube_animation/simple_cube_animation.uip
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="640" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Cube" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Cube_001" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" />
+ <AnimationTrack property="rotation.y" type="EaseInOut" />
+ <AnimationTrack property="rotation.z" type="EaseInOut" />
+ </Add>
+ <Add ref="#Light" lightdiffuse="0 1 0" lightspecular="1 1 1" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" />
+ <AnimationTrack property="rotation.y" type="EaseInOut" />
+ <AnimationTrack property="rotation.z" type="EaseInOut" />
+ </Add>
+ <State id="Scene-Slide1" name="Slide1" playmode="Play Through To..." playthroughto="#Scene-Slide2" >
+ <Add ref="#Cube" name="Cube" scale="1 1 1" sourcepath="#Cube" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 0.963 45 100 100 1.926 45 100 100 2.944 45 100 100 6.942 0 100 100 8.022 0 100 100 8.98 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 0.963 0 100 100 1.926 45 100 100 2.944 45 100 100 6.942 45 100 100 8.022 0 100 100 8.98 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 0.963 0 100 100 1.926 0 100 100 2.944 45 100 100 6.942 45 100 100 8.022 45 100 100 8.98 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" dynamic="True" >0 1 100 100 3.958 2 100 100 4.902 2 100 100 5.981 2 100 100 10 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" dynamic="True" >0 1 100 100 3.958 1 100 100 4.902 2 100 100 5.981 2 100 100 10 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" dynamic="True" >0 1 100 100 3.958 1 100 100 4.902 1 100 100 5.981 2 100 100 10 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material" />
+ </State>
+ <State id="Scene-Slide2" name="Slide2" initialplaystate="Play" playmode="Stop at end" playthroughto="Previous" >
+ <Add ref="#Cube_001" name="Cube" scale="100 100 2" sourcepath="#Cube" />
+ <Add ref="#Material_001" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/viewer/tst_qt3dsviewer.cpp b/tests/auto/viewer/tst_qt3dsviewer.cpp
new file mode 100644
index 00000000..f1d09407
--- /dev/null
+++ b/tests/auto/viewer/tst_qt3dsviewer.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "tst_qt3dsviewer.h"
+
+#include <QtQuick/QQuickView>
+#include <QtQuick/QQuickItem>
+#include <QtGui/QSurfaceFormat>
+
+void messageOutput(QtMsgType type, const QMessageLogContext &context,
+ const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg:
+ break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_qt3dsviewer::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+}
+
+void tst_qt3dsviewer::init()
+{
+#if defined(Q_OS_ANDROID)
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(3, 2);
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+#else
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(4, 3);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ QSurfaceFormat::setDefaultFormat(format);
+#endif
+}
+
+void tst_qt3dsviewer::testQml()
+{
+ QQuickView viewer;
+ viewer.setSource(QUrl("qrc:/tst_qt3dsviewer.qml"));
+ viewer.setTitle(QStringLiteral("tst_qt3dsviewer"));
+ viewer.show();
+
+ QObject *item = viewer.rootObject();
+ QObject *presentation = viewer.rootObject()->children().at(0);
+ QSignalSpy spyFrames(item, SIGNAL(frameUpdate()));
+ QSignalSpy spyEntered(presentation,
+ SIGNAL(slideEntered(const QString &, unsigned int, const QString &)));
+ QSignalSpy spyExited(presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+ QVERIFY(spyExited.wait(11000));
+ QVERIFY(spyFrames.count() > 590); // Should be 60 with fudge for startup
+ QCOMPARE(spyEntered.count(), 2);
+ QCOMPARE(spyExited.count(), 1);
+}
+
+QTEST_MAIN(tst_qt3dsviewer)
diff --git a/tests/auto/viewer/tst_qt3dsviewer.h b/tests/auto/viewer/tst_qt3dsviewer.h
new file mode 100644
index 00000000..d1b4b863
--- /dev/null
+++ b/tests/auto/viewer/tst_qt3dsviewer.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QT3DSVIEWER
+#define TST_QT3DSVIEWER
+
+#include <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+
+class tst_qt3dsviewer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qt3dsviewer()
+ {
+ }
+
+private Q_SLOTS:
+ void initTestCase();
+ void init();
+
+ void testQml();
+};
+
+#endif // TST_QT3DSVIEWER
diff --git a/tests/auto/viewer/tst_qt3dsviewer.qml b/tests/auto/viewer/tst_qt3dsviewer.qml
new file mode 100644
index 00000000..804cc370
--- /dev/null
+++ b/tests/auto/viewer/tst_qt3dsviewer.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtStudio3D 1.0
+
+Studio3D {
+ id: studio3D
+ width: 640
+ height: 480
+ Presentation {
+ source: "qrc:/simple_cube_animation/simple_cube_animation.uia"
+ }
+}
diff --git a/tests/auto/viewer/viewer.pro b/tests/auto/viewer/viewer.pro
new file mode 100644
index 00000000..d6d69b4e
--- /dev/null
+++ b/tests/auto/viewer/viewer.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+CONFIG += testcase
+include($$PWD/../../../src/Runtime/commoninclude.pri)
+
+TARGET = tst_qt3dsviewer
+QT += testlib gui quick
+RESOURCES += viewer.qrc
+
+HEADERS += \
+ tst_qt3dsviewer.h
+
+SOURCES += \
+ tst_qt3dsviewer.cpp
+
+LIBS += \
+ -lqt3dsruntime$$qtPlatformTargetSuffix() \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+ANDROID_EXTRA_LIBS = \
+ libqt3dsruntime.so \
+ libqt3dsqmlstreamer.so
diff --git a/tests/auto/viewer/viewer.qrc b/tests/auto/viewer/viewer.qrc
new file mode 100644
index 00000000..2f38ba14
--- /dev/null
+++ b/tests/auto/viewer/viewer.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>simple_cube_animation/simple_cube_animation.uia</file>
+ <file>simple_cube_animation/simple_cube_animation.uip</file>
+ <file>tst_qt3dsviewer.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/tests.pro b/tests/tests.pro
new file mode 100644
index 00000000..c458bbbe
--- /dev/null
+++ b/tests/tests.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+!package: SUBDIRS += \
+ auto